[kernel] r11188 - in dists/trunk/linux-2.6/debian/patches: bugfix/all series
Maximilian Attems
maks at alioth.debian.org
Sat Apr 26 21:59:25 UTC 2008
Author: maks
Date: Sat Apr 26 21:59:14 2008
New Revision: 11188
Log:
update to patch-2.6.25-git9
push it out
* debian integration of experimental kernel
* allow early beta testing
* 2.6.26 is Lenny goal
Added:
dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-git9
Modified:
dists/trunk/linux-2.6/debian/patches/series/1~experimental.1
Added: dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-git9
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-git9 Sat Apr 26 21:59:14 2008
@@ -0,0 +1,952011 @@
+diff --git a/.gitignore b/.gitignore
+index fdcce40..3016ed3 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -27,6 +27,7 @@ TAGS
+ vmlinux*
+ !vmlinux.lds.S
+ System.map
++Module.markers
+ Module.symvers
+ !.gitignore
+
+diff --git a/CREDITS b/CREDITS
+index da0a56e..8fec7b3 100644
+--- a/CREDITS
++++ b/CREDITS
+@@ -403,6 +403,8 @@ D: Linux CD and Support Giveaway List
+ N: Erik Inge Bolsø
+ E: knan at mo.himolde.no
+ D: Misc kernel hacks
++D: Updated PC speaker driver for 2.3
++S: Norway
+
+ N: Andreas E. Bombe
+ E: andreas.bombe at munich.netsurf.de
+@@ -3116,6 +3118,12 @@ S: Post Office Box 64132
+ S: Sunnyvale, California 94088-4132
+ S: USA
+
++N: Stas Sergeev
++E: stsp at users.sourceforge.net
++D: PCM PC-Speaker driver
++D: misc fixes
++S: Russia
++
+ N: Simon Shapiro
+ E: shimon at i-Connect.Net
+ W: http://www.-i-Connect.Net/~shimon
+diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
+index e8fb246..1977fab 100644
+--- a/Documentation/00-INDEX
++++ b/Documentation/00-INDEX
+@@ -25,8 +25,6 @@ DMA-API.txt
+ - DMA API, pci_ API & extensions for non-consistent memory machines.
+ DMA-ISA-LPC.txt
+ - How to do DMA with ISA (and LPC) devices.
+-DMA-mapping.txt
+- - info for PCI drivers using DMA portably across all platforms.
+ DocBook/
+ - directory with DocBook templates etc. for kernel documentation.
+ HOWTO
+@@ -43,8 +41,6 @@ ManagementStyle
+ - how to (attempt to) manage kernel hackers.
+ MSI-HOWTO.txt
+ - the Message Signaled Interrupts (MSI) Driver Guide HOWTO and FAQ.
+-PCIEBUS-HOWTO.txt
+- - a guide describing the PCI Express Port Bus driver.
+ RCU/
+ - directory with info on RCU (read-copy update).
+ README.DAC960
+@@ -167,10 +163,8 @@ highuid.txt
+ - notes on the change from 16 bit to 32 bit user/group IDs.
+ hpet.txt
+ - High Precision Event Timer Driver for Linux.
+-hrtimer/
+- - info on the timer_stats debugging facility for timer (ab)use.
+-hrtimers/
+- - info on the hrtimers subsystem for high-resolution kernel timers.
++timers/
++ - info on the timer related topics
+ hw_random.txt
+ - info on Linux support for random number generator in i8xx chipsets.
+ hwmon/
+@@ -287,12 +281,6 @@ parport.txt
+ - how to use the parallel-port driver.
+ parport-lowlevel.txt
+ - description and usage of the low level parallel port functions.
+-pci-error-recovery.txt
+- - info on PCI error recovery.
+-pci.txt
+- - info on the PCI subsystem for device driver authors.
+-pcieaer-howto.txt
+- - the PCI Express Advanced Error Reporting Driver Guide HOWTO.
+ pcmcia/
+ - info on the Linux PCMCIA driver.
+ pi-futex.txt
+@@ -341,8 +329,6 @@ sgi-visws.txt
+ - short blurb on the SGI Visual Workstations.
+ sh/
+ - directory with info on porting Linux to a new architecture.
+-smart-config.txt
+- - description of the Smart Config makefile feature.
+ sound/
+ - directory with info on sound card support.
+ sparc/
+diff --git a/Documentation/ABI/obsolete/o2cb b/Documentation/ABI/obsolete/o2cb
+new file mode 100644
+index 0000000..9c49d8e
+--- /dev/null
++++ b/Documentation/ABI/obsolete/o2cb
+@@ -0,0 +1,11 @@
++What: /sys/o2cb symlink
++Date: Dec 2005
++KernelVersion: 2.6.16
++Contact: ocfs2-devel at oss.oracle.com
++Description: This is a symlink: /sys/o2cb to /sys/fs/o2cb. The symlink will
++ be removed when new versions of ocfs2-tools which know to look
++ in /sys/fs/o2cb are sufficiently prevalent. Don't code new
++ software to look here, it should try /sys/fs/o2cb instead.
++ See Documentation/ABI/stable/o2cb for more information on usage.
++Users: ocfs2-tools. It's sufficient to mail proposed changes to
++ ocfs2-devel at oss.oracle.com.
+diff --git a/Documentation/ABI/stable/o2cb b/Documentation/ABI/stable/o2cb
+new file mode 100644
+index 0000000..5eb1545
+--- /dev/null
++++ b/Documentation/ABI/stable/o2cb
+@@ -0,0 +1,10 @@
++What: /sys/fs/o2cb/ (was /sys/o2cb)
++Date: Dec 2005
++KernelVersion: 2.6.16
++Contact: ocfs2-devel at oss.oracle.com
++Description: Ocfs2-tools looks at 'interface-revision' for versioning
++ information. Each logmask/ file controls a set of debug prints
++ and can be written into with the strings "allow", "deny", or
++ "off". Reading the file returns the current state.
++Users: ocfs2-tools. It's sufficient to mail proposed changes to
++ ocfs2-devel at oss.oracle.com.
+diff --git a/Documentation/ABI/stable/sysfs-class-ubi b/Documentation/ABI/stable/sysfs-class-ubi
+new file mode 100644
+index 0000000..18d471d
+--- /dev/null
++++ b/Documentation/ABI/stable/sysfs-class-ubi
+@@ -0,0 +1,212 @@
++What: /sys/class/ubi/
++Date: July 2006
++KernelVersion: 2.6.22
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ The ubi/ class sub-directory belongs to the UBI subsystem and
++ provides general UBI information, per-UBI device information
++ and per-UBI volume information.
++
++What: /sys/class/ubi/version
++Date: July 2006
++KernelVersion: 2.6.22
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ This file contains version of the latest supported UBI on-media
++ format. Currently it is 1, and there is no plan to change this.
++ However, if in the future UBI needs on-flash format changes
++ which cannot be done in a compatible manner, a new format
++ version will be added. So this is a mechanism for possible
++ future backward-compatible (but forward-incompatible)
++ improvements.
++
++What: /sys/class/ubiX/
++Date: July 2006
++KernelVersion: 2.6.22
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ The /sys/class/ubi0, /sys/class/ubi1, etc directories describe
++ UBI devices (UBI device 0, 1, etc). They contain general UBI
++ device information and per UBI volume information (each UBI
++ device may have many UBI volumes)
++
++What: /sys/class/ubi/ubiX/avail_eraseblocks
++Date: July 2006
++KernelVersion: 2.6.22
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ Amount of available logical eraseblock. For example, one may
++ create a new UBI volume which has this amount of logical
++ eraseblocks.
++
++What: /sys/class/ubi/ubiX/bad_peb_count
++Date: July 2006
++KernelVersion: 2.6.22
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ Count of bad physical eraseblocks on the underlying MTD device.
++
++What: /sys/class/ubi/ubiX/bgt_enabled
++Date: July 2006
++KernelVersion: 2.6.22
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ Contains ASCII "0\n" if the UBI background thread is disabled,
++ and ASCII "1\n" if it is enabled.
++
++What: /sys/class/ubi/ubiX/dev
++Date: July 2006
++KernelVersion: 2.6.22
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ Major and minor numbers of the character device corresponding
++ to this UBI device (in <major>:<minor> format).
++
++What: /sys/class/ubi/ubiX/eraseblock_size
++Date: July 2006
++KernelVersion: 2.6.22
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ Maximum logical eraseblock size this UBI device may provide. UBI
++ volumes may have smaller logical eraseblock size because of their
++ alignment.
++
++What: /sys/class/ubi/ubiX/max_ec
++Date: July 2006
++KernelVersion: 2.6.22
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ Maximum physical eraseblock erase counter value.
++
++What: /sys/class/ubi/ubiX/max_vol_count
++Date: July 2006
++KernelVersion: 2.6.22
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ Maximum number of volumes which this UBI device may have.
++
++What: /sys/class/ubi/ubiX/min_io_size
++Date: July 2006
++KernelVersion: 2.6.22
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ Minimum input/output unit size. All the I/O may only be done
++ in fractions of the contained number.
++
++What: /sys/class/ubi/ubiX/mtd_num
++Date: January 2008
++KernelVersion: 2.6.25
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ Number of the underlying MTD device.
++
++What: /sys/class/ubi/ubiX/reserved_for_bad
++Date: July 2006
++KernelVersion: 2.6.22
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ Number of physical eraseblocks reserved for bad block handling.
++
++What: /sys/class/ubi/ubiX/total_eraseblocks
++Date: July 2006
++KernelVersion: 2.6.22
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ Total number of good (not marked as bad) physical eraseblocks on
++ the underlying MTD device.
++
++What: /sys/class/ubi/ubiX/volumes_count
++Date: July 2006
++KernelVersion: 2.6.22
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ Count of volumes on this UBI device.
++
++What: /sys/class/ubi/ubiX/ubiX_Y/
++Date: July 2006
++KernelVersion: 2.6.22
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ The /sys/class/ubi/ubiX/ubiX_0/, /sys/class/ubi/ubiX/ubiX_1/,
++ etc directories describe UBI volumes on UBI device X (volumes
++ 0, 1, etc).
++
++What: /sys/class/ubi/ubiX/ubiX_Y/alignment
++Date: July 2006
++KernelVersion: 2.6.22
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ Volume alignment - the value the logical eraseblock size of
++ this volume has to be aligned on. For example, 2048 means that
++ logical eraseblock size is multiple of 2048. In other words,
++ volume logical eraseblock size is UBI device logical eraseblock
++ size aligned to the alignment value.
++
++What: /sys/class/ubi/ubiX/ubiX_Y/corrupted
++Date: July 2006
++KernelVersion: 2.6.22
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ Contains ASCII "0\n" if the UBI volume is OK, and ASCII "1\n"
++ if it is corrupted (e.g., due to an interrupted volume update).
++
++What: /sys/class/ubi/ubiX/ubiX_Y/data_bytes
++Date: July 2006
++KernelVersion: 2.6.22
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ The amount of data this volume contains. This value makes sense
++ only for static volumes, and for dynamic volume it equivalent
++ to the total volume size in bytes.
++
++What: /sys/class/ubi/ubiX/ubiX_Y/dev
++Date: July 2006
++KernelVersion: 2.6.22
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ Major and minor numbers of the character device corresponding
++ to this UBI volume (in <major>:<minor> format).
++
++What: /sys/class/ubi/ubiX/ubiX_Y/name
++Date: July 2006
++KernelVersion: 2.6.22
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ Volume name.
++
++What: /sys/class/ubi/ubiX/ubiX_Y/reserved_ebs
++Date: July 2006
++KernelVersion: 2.6.22
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ Count of physical eraseblock reserved for this volume.
++ Equivalent to the volume size in logical eraseblocks.
++
++What: /sys/class/ubi/ubiX/ubiX_Y/type
++Date: July 2006
++KernelVersion: 2.6.22
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ Volume type. Contains ASCII "dynamic\n" for dynamic volumes and
++ "static\n" for static volumes.
++
++What: /sys/class/ubi/ubiX/ubiX_Y/upd_marker
++Date: July 2006
++KernelVersion: 2.6.22
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ Contains ASCII "0\n" if the update marker is not set for this
++ volume, and "1\n" if it is set. The update marker is set when
++ volume update starts, and cleaned when it ends. So the presence
++ of the update marker indicates that the volume is being updated
++ at the moment of the update was interrupted. The later may be
++ checked using the "corrupted" sysfs file.
++
++What: /sys/class/ubi/ubiX/ubiX_Y/usable_eb_size
++Date: July 2006
++KernelVersion: 2.6.22
++Contact: Artem Bityutskiy <dedekind at infradead.org>
++Description:
++ Logical eraseblock size of this volume. Equivalent to logical
++ eraseblock size of the device aligned on the volume alignment
++ value.
+diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci
+new file mode 100644
+index 0000000..ceddcff
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-bus-pci
+@@ -0,0 +1,11 @@
++What: /sys/bus/pci/devices/.../vpd
++Date: February 2008
++Contact: Ben Hutchings <bhutchings at solarflare.com>
++Description:
++ A file named vpd in a device directory will be a
++ binary file containing the Vital Product Data for the
++ device. It should follow the VPD format defined in
++ PCI Specification 2.1 or 2.2, but users should consider
++ that some devices may have malformatted data. If the
++ underlying VPD has a writable section then the
++ corresponding section of this file will be writable.
+diff --git a/Documentation/ABI/testing/sysfs-ibft b/Documentation/ABI/testing/sysfs-ibft
+new file mode 100644
+index 0000000..c2b7d11
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-ibft
+@@ -0,0 +1,23 @@
++What: /sys/firmware/ibft/initiator
++Date: November 2007
++Contact: Konrad Rzeszutek <ketuzsezr at darnok.org>
++Description: The /sys/firmware/ibft/initiator directory will contain
++ files that expose the iSCSI Boot Firmware Table initiator data.
++ Usually this contains the Initiator name.
++
++What: /sys/firmware/ibft/targetX
++Date: November 2007
++Contact: Konrad Rzeszutek <ketuzsezr at darnok.org>
++Description: The /sys/firmware/ibft/targetX directory will contain
++ files that expose the iSCSI Boot Firmware Table target data.
++ Usually this contains the target's IP address, boot LUN,
++ target name, and what NIC it is associated with. It can also
++ contain the CHAP name (and password), the reverse CHAP
++ name (and password)
++
++What: /sys/firmware/ibft/ethernetX
++Date: November 2007
++Contact: Konrad Rzeszutek <ketuzsezr at darnok.org>
++Description: The /sys/firmware/ibft/ethernetX directory will contain
++ files that expose the iSCSI Boot Firmware Table NIC data.
++ This can this can the IP address, MAC, and gateway of the NIC.
+diff --git a/Documentation/ABI/testing/sysfs-ocfs2 b/Documentation/ABI/testing/sysfs-ocfs2
+new file mode 100644
+index 0000000..b7cc516
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-ocfs2
+@@ -0,0 +1,89 @@
++What: /sys/fs/ocfs2/
++Date: April 2008
++Contact: ocfs2-devel at oss.oracle.com
++Description:
++ The /sys/fs/ocfs2 directory contains knobs used by the
++ ocfs2-tools to interact with the filesystem.
++
++What: /sys/fs/ocfs2/max_locking_protocol
++Date: April 2008
++Contact: ocfs2-devel at oss.oracle.com
++Description:
++ The /sys/fs/ocfs2/max_locking_protocol file displays version
++ of ocfs2 locking supported by the filesystem. This version
++ covers how ocfs2 uses distributed locking between cluster
++ nodes.
++
++ The protocol version has a major and minor number. Two
++ cluster nodes can interoperate if they have an identical
++ major number and an overlapping minor number - thus,
++ a node with version 1.10 can interoperate with a node
++ sporting version 1.8, as long as both use the 1.8 protocol.
++
++ Reading from this file returns a single line, the major
++ number and minor number joined by a period, eg "1.10".
++
++ This file is read-only. The value is compiled into the
++ driver.
++
++What: /sys/fs/ocfs2/loaded_cluster_plugins
++Date: April 2008
++Contact: ocfs2-devel at oss.oracle.com
++Description:
++ The /sys/fs/ocfs2/loaded_cluster_plugins file describes
++ the available plugins to support ocfs2 cluster operation.
++ A cluster plugin is required to use ocfs2 in a cluster.
++ There are currently two available plugins:
++
++ * 'o2cb' - The classic o2cb cluster stack that ocfs2 has
++ used since its inception.
++ * 'user' - A plugin supporting userspace cluster software
++ in conjunction with fs/dlm.
++
++ Reading from this file returns the names of all loaded
++ plugins, one per line.
++
++ This file is read-only. Its contents may change as
++ plugins are loaded or removed.
++
++What: /sys/fs/ocfs2/active_cluster_plugin
++Date: April 2008
++Contact: ocfs2-devel at oss.oracle.com
++Description:
++ The /sys/fs/ocfs2/active_cluster_plugin displays which
++ cluster plugin is currently in use by the filesystem.
++ The active plugin will appear in the loaded_cluster_plugins
++ file as well. Only one plugin can be used at a time.
++
++ Reading from this file returns the name of the active plugin
++ on a single line.
++
++ This file is read-only. Which plugin is active depends on
++ the cluster stack in use. The contents may change
++ when all filesystems are unmounted and the cluster stack
++ is changed.
++
++What: /sys/fs/ocfs2/cluster_stack
++Date: April 2008
++Contact: ocfs2-devel at oss.oracle.com
++Description:
++ The /sys/fs/ocfs2/cluster_stack file contains the name
++ of current ocfs2 cluster stack. This value is set by
++ userspace tools when bringing the cluster stack online.
++
++ Cluster stack names are 4 characters in length.
++
++ When the 'o2cb' cluster stack is used, the 'o2cb' cluster
++ plugin is active. All other cluster stacks use the 'user'
++ cluster plugin.
++
++ Reading from this file returns the name of the current
++ cluster stack on a single line.
++
++ Writing a new stack name to this file changes the current
++ cluster stack unless there are mounted ocfs2 filesystems.
++ If there are mounted filesystems, attempts to change the
++ stack return an error.
++
++Users:
++ ocfs2-tools <ocfs2-tools-devel at oss.oracle.com>
+diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
+index 300e170..83966e9 100644
+--- a/Documentation/DocBook/Makefile
++++ b/Documentation/DocBook/Makefile
+@@ -9,9 +9,10 @@
+ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
+ kernel-hacking.xml kernel-locking.xml deviceiobook.xml \
+ procfs-guide.xml writing_usb_driver.xml networking.xml \
+- kernel-api.xml filesystems.xml lsm.xml usb.xml \
++ kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \
+ gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
+- genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml
++ genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
++ mac80211.xml
+
+ ###
+ # The build process is as follows (targets):
+@@ -186,8 +187,11 @@ quiet_cmd_fig2png = FIG2PNG $@
+
+ ###
+ # Rule to convert a .c file to inline XML documentation
++ gen_xml = :
++ quiet_gen_xml = echo ' GEN $@'
++silent_gen_xml = :
+ %.xml: %.c
+- @echo ' GEN $@'
++ @$($(quiet)gen_xml)
+ @( \
+ echo "<programlisting>"; \
+ expand --tabs=8 < $< | \
+diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
+index dc0f30c..488dd4a 100644
+--- a/Documentation/DocBook/kernel-api.tmpl
++++ b/Documentation/DocBook/kernel-api.tmpl
+@@ -297,11 +297,6 @@ X!Earch/x86/kernel/mca_32.c
+ !Ikernel/acct.c
+ </chapter>
+
+- <chapter id="pmfuncs">
+- <title>Power Management</title>
+-!Ekernel/power/pm.c
+- </chapter>
+-
+ <chapter id="devdrivers">
+ <title>Device drivers infrastructure</title>
+ <sect1><title>Device Drivers Base</title>
+diff --git a/Documentation/DocBook/kernel-locking.tmpl b/Documentation/DocBook/kernel-locking.tmpl
+index 2e9d6b4..77c42f4 100644
+--- a/Documentation/DocBook/kernel-locking.tmpl
++++ b/Documentation/DocBook/kernel-locking.tmpl
+@@ -241,7 +241,7 @@
+ </para>
+ <para>
+ The third type is a semaphore
+- (<filename class="headerfile">include/asm/semaphore.h</filename>): it
++ (<filename class="headerfile">include/linux/semaphore.h</filename>): it
+ can have more than one holder at any time (the number decided at
+ initialization time), although it is most commonly used as a
+ single-holder lock (a mutex). If you can't get a semaphore, your
+@@ -290,7 +290,7 @@
+ <para>
+ If you have a data structure which is only ever accessed from
+ user context, then you can use a simple semaphore
+- (<filename>linux/asm/semaphore.h</filename>) to protect it. This
++ (<filename>linux/linux/semaphore.h</filename>) to protect it. This
+ is the most trivial case: you initialize the semaphore to the number
+ of resources available (usually 1), and call
+ <function>down_interruptible()</function> to grab the semaphore, and
+@@ -854,7 +854,7 @@ The change is shown below, in standard patch format: the
+ };
+
+ -static DEFINE_MUTEX(cache_lock);
+-+static spinlock_t cache_lock = SPIN_LOCK_UNLOCKED;
+++static DEFINE_SPINLOCK(cache_lock);
+ static LIST_HEAD(cache);
+ static unsigned int cache_num = 0;
+ #define MAX_CACHE_SIZE 10
+@@ -1238,7 +1238,7 @@ Here is the "lock-per-object" implementation:
+ - int popularity;
+ };
+
+- static spinlock_t cache_lock = SPIN_LOCK_UNLOCKED;
++ static DEFINE_SPINLOCK(cache_lock);
+ @@ -77,6 +84,7 @@
+ obj->id = id;
+ obj->popularity = 0;
+@@ -1656,7 +1656,7 @@ the amount of locking which needs to be done.
+ #include <linux/slab.h>
+ #include <linux/string.h>
+ +#include <linux/rcupdate.h>
+- #include <asm/semaphore.h>
++ #include <linux/semaphore.h>
+ #include <asm/errno.h>
+
+ struct object
+diff --git a/Documentation/DocBook/kgdb.tmpl b/Documentation/DocBook/kgdb.tmpl
+new file mode 100644
+index 0000000..97618be
+--- /dev/null
++++ b/Documentation/DocBook/kgdb.tmpl
+@@ -0,0 +1,447 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
++ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
++
++<book id="kgdbOnLinux">
++ <bookinfo>
++ <title>Using kgdb and the kgdb Internals</title>
++
++ <authorgroup>
++ <author>
++ <firstname>Jason</firstname>
++ <surname>Wessel</surname>
++ <affiliation>
++ <address>
++ <email>jason.wessel at windriver.com</email>
++ </address>
++ </affiliation>
++ </author>
++ </authorgroup>
++
++ <authorgroup>
++ <author>
++ <firstname>Tom</firstname>
++ <surname>Rini</surname>
++ <affiliation>
++ <address>
++ <email>trini at kernel.crashing.org</email>
++ </address>
++ </affiliation>
++ </author>
++ </authorgroup>
++
++ <authorgroup>
++ <author>
++ <firstname>Amit S.</firstname>
++ <surname>Kale</surname>
++ <affiliation>
++ <address>
++ <email>amitkale at linsyssoft.com</email>
++ </address>
++ </affiliation>
++ </author>
++ </authorgroup>
++
++ <copyright>
++ <year>2008</year>
++ <holder>Wind River Systems, Inc.</holder>
++ </copyright>
++ <copyright>
++ <year>2004-2005</year>
++ <holder>MontaVista Software, Inc.</holder>
++ </copyright>
++ <copyright>
++ <year>2004</year>
++ <holder>Amit S. Kale</holder>
++ </copyright>
++
++ <legalnotice>
++ <para>
++ This file is licensed under the terms of the GNU General Public License
++ version 2. This program is licensed "as is" without any warranty of any
++ kind, whether express or implied.
++ </para>
++
++ </legalnotice>
++ </bookinfo>
++
++<toc></toc>
++ <chapter id="Introduction">
++ <title>Introduction</title>
++ <para>
++ kgdb is a source level debugger for linux kernel. It is used along
++ with gdb to debug a linux kernel. The expectation is that gdb can
++ be used to "break in" to the kernel to inspect memory, variables
++ and look through a cal stack information similar to what an
++ application developer would use gdb for. It is possible to place
++ breakpoints in kernel code and perform some limited execution
++ stepping.
++ </para>
++ <para>
++ Two machines are required for using kgdb. One of these machines is a
++ development machine and the other is a test machine. The kernel
++ to be debugged runs on the test machine. The development machine
++ runs an instance of gdb against the vmlinux file which contains
++ the symbols (not boot image such as bzImage, zImage, uImage...).
++ In gdb the developer specifies the connection parameters and
++ connects to kgdb. Depending on which kgdb I/O modules exist in
++ the kernel for a given architecture, it may be possible to debug
++ the test machine's kernel with the development machine using a
++ rs232 or ethernet connection.
++ </para>
++ </chapter>
++ <chapter id="CompilingAKernel">
++ <title>Compiling a kernel</title>
++ <para>
++ To enable <symbol>CONFIG_KGDB</symbol>, look under the "Kernel debugging"
++ and then select "KGDB: kernel debugging with remote gdb".
++ </para>
++ <para>
++ Next you should choose one of more I/O drivers to interconnect debugging
++ host and debugged target. Early boot debugging requires a KGDB
++ I/O driver that supports early debugging and the driver must be
++ built into the kernel directly. Kgdb I/O driver configuration
++ takes place via kernel or module parameters, see following
++ chapter.
++ </para>
++ <para>
++ The kgdb test compile options are described in the kgdb test suite chapter.
++ </para>
++
++ </chapter>
++ <chapter id="EnableKGDB">
++ <title>Enable kgdb for debugging</title>
++ <para>
++ In order to use kgdb you must activate it by passing configuration
++ information to one of the kgdb I/O drivers. If you do not pass any
++ configuration information kgdb will not do anything at all. Kgdb
++ will only actively hook up to the kernel trap hooks if a kgdb I/O
++ driver is loaded and configured. If you unconfigure a kgdb I/O
++ driver, kgdb will unregister all the kernel hook points.
++ </para>
++ <para>
++ All drivers can be reconfigured at run time, if
++ <symbol>CONFIG_SYSFS</symbol> and <symbol>CONFIG_MODULES</symbol>
++ are enabled, by echo'ing a new config string to
++ <constant>/sys/module/<driver>/parameter/<option></constant>.
++ The driver can be unconfigured by passing an empty string. You cannot
++ change the configuration while the debugger is attached. Make sure
++ to detach the debugger with the <constant>detach</constant> command
++ prior to trying unconfigure a kgdb I/O driver.
++ </para>
++ <sect1 id="kgdbwait">
++ <title>Kernel parameter: kgdbwait</title>
++ <para>
++ The Kernel command line option <constant>kgdbwait</constant> makes
++ kgdb wait for a debugger connection during booting of a kernel. You
++ can only use this option you compiled a kgdb I/O driver into the
++ kernel and you specified the I/O driver configuration as a kernel
++ command line option. The kgdbwait parameter should always follow the
++ configuration parameter for the kgdb I/O driver in the kernel
++ command line else the I/O driver will not be configured prior to
++ asking the kernel to use it to wait.
++ </para>
++ <para>
++ The kernel will stop and wait as early as the I/O driver and
++ architecture will allow when you use this option. If you build the
++ kgdb I/O driver as a kernel module kgdbwait will not do anything.
++ </para>
++ </sect1>
++ <sect1 id="kgdboc">
++ <title>Kernel parameter: kgdboc</title>
++ <para>
++ The kgdboc driver was originally an abbreviation meant to stand for
++ "kgdb over console". Kgdboc is designed to work with a single
++ serial port. It was meant to cover the circumstance
++ where you wanted to use a serial console as your primary console as
++ well as using it to perform kernel debugging. Of course you can
++ also use kgdboc without assigning a console to the same port.
++ </para>
++ <sect2 id="UsingKgdboc">
++ <title>Using kgdboc</title>
++ <para>
++ You can configure kgdboc via sysfs or a module or kernel boot line
++ parameter depending on if you build with CONFIG_KGDBOC as a module
++ or built-in.
++ <orderedlist>
++ <listitem><para>From the module load or build-in</para>
++ <para><constant>kgdboc=<tty-device>,[baud]</constant></para>
++ <para>
++ The example here would be if your console port was typically ttyS0, you would use something like <constant>kgdboc=ttyS0,115200</constant> or on the ARM Versatile AB you would likely use <constant>kgdboc=ttyAMA0,115200</constant>
++ </para>
++ </listitem>
++ <listitem><para>From sysfs</para>
++ <para><constant>echo ttyS0 > /sys/module/kgdboc/parameters/kgdboc</constant></para>
++ </listitem>
++ </orderedlist>
++ </para>
++ <para>
++ NOTE: Kgdboc does not support interrupting the target via the
++ gdb remote protocol. You must manually send a sysrq-g unless you
++ have a proxy that splits console output to a terminal problem and
++ has a separate port for the debugger to connect to that sends the
++ sysrq-g for you.
++ </para>
++ <para>When using kgdboc with no debugger proxy, you can end up
++ connecting the debugger for one of two entry points. If an
++ exception occurs after you have loaded kgdboc a message should print
++ on the console stating it is waiting for the debugger. In case you
++ disconnect your terminal program and then connect the debugger in
++ its place. If you want to interrupt the target system and forcibly
++ enter a debug session you have to issue a Sysrq sequence and then
++ type the letter <constant>g</constant>. Then you disconnect the
++ terminal session and connect gdb. Your options if you don't like
++ this are to hack gdb to send the sysrq-g for you as well as on the
++ initial connect, or to use a debugger proxy that allows an
++ unmodified gdb to do the debugging.
++ </para>
++ </sect2>
++ </sect1>
++ <sect1 id="kgdbcon">
++ <title>Kernel parameter: kgdbcon</title>
++ <para>
++ Kgdb supports using the gdb serial protocol to send console messages
++ to the debugger when the debugger is connected and running. There
++ are two ways to activate this feature.
++ <orderedlist>
++ <listitem><para>Activate with the kernel command line option:</para>
++ <para><constant>kgdbcon</constant></para>
++ </listitem>
++ <listitem><para>Use sysfs before configuring an io driver</para>
++ <para>
++ <constant>echo 1 > /sys/module/kgdb/parameters/kgdb_use_con</constant>
++ </para>
++ <para>
++ NOTE: If you do this after you configure the kgdb I/O driver, the
++ setting will not take effect until the next point the I/O is
++ reconfigured.
++ </para>
++ </listitem>
++ </orderedlist>
++ </para>
++ <para>
++ IMPORTANT NOTE: Using this option with kgdb over the console
++ (kgdboc) or kgdb over ethernet (kgdboe) is not supported.
++ </para>
++ </sect1>
++ </chapter>
++ <chapter id="ConnectingGDB">
++ <title>Connecting gdb</title>
++ <para>
++ If you are using kgdboc, you need to have used kgdbwait as a boot
++ argument, issued a sysrq-g, or the system you are going to debug
++ has already taken an exception and is waiting for the debugger to
++ attach before you can connect gdb.
++ </para>
++ <para>
++ If you are not using different kgdb I/O driver other than kgdboc,
++ you should be able to connect and the target will automatically
++ respond.
++ </para>
++ <para>
++ Example (using a serial port):
++ </para>
++ <programlisting>
++ % gdb ./vmlinux
++ (gdb) set remotebaud 115200
++ (gdb) target remote /dev/ttyS0
++ </programlisting>
++ <para>
++ Example (kgdb to a terminal server):
++ </para>
++ <programlisting>
++ % gdb ./vmlinux
++ (gdb) target remote udp:192.168.2.2:6443
++ </programlisting>
++ <para>
++ Example (kgdb over ethernet):
++ </para>
++ <programlisting>
++ % gdb ./vmlinux
++ (gdb) target remote udp:192.168.2.2:6443
++ </programlisting>
++ <para>
++ Once connected, you can debug a kernel the way you would debug an
++ application program.
++ </para>
++ <para>
++ If you are having problems connecting or something is going
++ seriously wrong while debugging, it will most often be the case
++ that you want to enable gdb to be verbose about its target
++ communications. You do this prior to issuing the <constant>target
++ remote</constant> command by typing in: <constant>set remote debug 1</constant>
++ </para>
++ </chapter>
++ <chapter id="KGDBTestSuite">
++ <title>kgdb Test Suite</title>
++ <para>
++ When kgdb is enabled in the kernel config you can also elect to
++ enable the config parameter KGDB_TESTS. Turning this on will
++ enable a special kgdb I/O module which is designed to test the
++ kgdb internal functions.
++ </para>
++ <para>
++ The kgdb tests are mainly intended for developers to test the kgdb
++ internals as well as a tool for developing a new kgdb architecture
++ specific implementation. These tests are not really for end users
++ of the Linux kernel. The primary source of documentation would be
++ to look in the drivers/misc/kgdbts.c file.
++ </para>
++ <para>
++ The kgdb test suite can also be configured at compile time to run
++ the core set of tests by setting the kernel config parameter
++ KGDB_TESTS_ON_BOOT. This particular option is aimed at automated
++ regression testing and does not require modifying the kernel boot
++ config arguments. If this is turned on, the kgdb test suite can
++ be disabled by specifying "kgdbts=" as a kernel boot argument.
++ </para>
++ </chapter>
++ <chapter id="CommonBackEndReq">
++ <title>KGDB Internals</title>
++ <sect1 id="kgdbArchitecture">
++ <title>Architecture Specifics</title>
++ <para>
++ Kgdb is organized into three basic components:
++ <orderedlist>
++ <listitem><para>kgdb core</para>
++ <para>
++ The kgdb core is found in kernel/kgdb.c. It contains:
++ <itemizedlist>
++ <listitem><para>All the logic to implement the gdb serial protocol</para></listitem>
++ <listitem><para>A generic OS exception handler which includes sync'ing the processors into a stopped state on an multi cpu system.</para></listitem>
++ <listitem><para>The API to talk to the kgdb I/O drivers</para></listitem>
++ <listitem><para>The API to make calls to the arch specific kgdb implementation</para></listitem>
++ <listitem><para>The logic to perform safe memory reads and writes to memory while using the debugger</para></listitem>
++ <listitem><para>A full implementation for software breakpoints unless overridden by the arch</para></listitem>
++ </itemizedlist>
++ </para>
++ </listitem>
++ <listitem><para>kgdb arch specific implementation</para>
++ <para>
++ This implementation is generally found in arch/*/kernel/kgdb.c.
++ As an example, arch/x86/kernel/kgdb.c contains the specifics to
++ implement HW breakpoint as well as the initialization to
++ dynamically register and unregister for the trap handlers on
++ this architecture. The arch specific portion implements:
++ <itemizedlist>
++ <listitem><para>contains an arch specific trap catcher which
++ invokes kgdb_handle_exception() to start kgdb about doing its
++ work</para></listitem>
++ <listitem><para>translation to and from gdb specific packet format to pt_regs</para></listitem>
++ <listitem><para>Registration and unregistration of architecture specific trap hooks</para></listitem>
++ <listitem><para>Any special exception handling and cleanup</para></listitem>
++ <listitem><para>NMI exception handling and cleanup</para></listitem>
++ <listitem><para>(optional)HW breakpoints</para></listitem>
++ </itemizedlist>
++ </para>
++ </listitem>
++ <listitem><para>kgdb I/O driver</para>
++ <para>
++ Each kgdb I/O driver has to provide an implemenation for the following:
++ <itemizedlist>
++ <listitem><para>configuration via builtin or module</para></listitem>
++ <listitem><para>dynamic configuration and kgdb hook registration calls</para></listitem>
++ <listitem><para>read and write character interface</para></listitem>
++ <listitem><para>A cleanup handler for unconfiguring from the kgdb core</para></listitem>
++ <listitem><para>(optional) Early debug methodology</para></listitem>
++ </itemizedlist>
++ Any given kgdb I/O driver has to operate very closely with the
++ hardware and must do it in such a way that does not enable
++ interrupts or change other parts of the system context without
++ completely restoring them. The kgdb core will repeatedly "poll"
++ a kgdb I/O driver for characters when it needs input. The I/O
++ driver is expected to return immediately if there is no data
++ available. Doing so allows for the future possibility to touch
++ watch dog hardware in such a way as to have a target system not
++ reset when these are enabled.
++ </para>
++ </listitem>
++ </orderedlist>
++ </para>
++ <para>
++ If you are intent on adding kgdb architecture specific support
++ for a new architecture, the architecture should define
++ <constant>HAVE_ARCH_KGDB</constant> in the architecture specific
++ Kconfig file. This will enable kgdb for the architecture, and
++ at that point you must create an architecture specific kgdb
++ implementation.
++ </para>
++ <para>
++ There are a few flags which must be set on every architecture in
++ their <asm/kgdb.h> file. These are:
++ <itemizedlist>
++ <listitem>
++ <para>
++ NUMREGBYTES: The size in bytes of all of the registers, so
++ that we can ensure they will all fit into a packet.
++ </para>
++ <para>
++ BUFMAX: The size in bytes of the buffer GDB will read into.
++ This must be larger than NUMREGBYTES.
++ </para>
++ <para>
++ CACHE_FLUSH_IS_SAFE: Set to 1 if it is always safe to call
++ flush_cache_range or flush_icache_range. On some architectures,
++ these functions may not be safe to call on SMP since we keep other
++ CPUs in a holding pattern.
++ </para>
++ </listitem>
++ </itemizedlist>
++ </para>
++ <para>
++ There are also the following functions for the common backend,
++ found in kernel/kgdb.c, that must be supplied by the
++ architecture-specific backend unless marked as (optional), in
++ which case a default function maybe used if the architecture
++ does not need to provide a specific implementation.
++ </para>
++!Iinclude/linux/kgdb.h
++ </sect1>
++ <sect1 id="kgdbocDesign">
++ <title>kgdboc internals</title>
++ <para>
++ The kgdboc driver is actually a very thin driver that relies on the
++ underlying low level to the hardware driver having "polling hooks"
++ which the to which the tty driver is attached. In the initial
++ implementation of kgdboc it the serial_core was changed to expose a
++ low level uart hook for doing polled mode reading and writing of a
++ single character while in an atomic context. When kgdb makes an I/O
++ request to the debugger, kgdboc invokes a call back in the serial
++ core which in turn uses the call back in the uart driver. It is
++ certainly possible to extend kgdboc to work with non-uart based
++ consoles in the future.
++ </para>
++ <para>
++ When using kgdboc with a uart, the uart driver must implement two callbacks in the <constant>struct uart_ops</constant>. Example from drivers/8250.c:<programlisting>
++#ifdef CONFIG_CONSOLE_POLL
++ .poll_get_char = serial8250_get_poll_char,
++ .poll_put_char = serial8250_put_poll_char,
++#endif
++ </programlisting>
++ Any implementation specifics around creating a polling driver use the
++ <constant>#ifdef CONFIG_CONSOLE_POLL</constant>, as shown above.
++ Keep in mind that polling hooks have to be implemented in such a way
++ that they can be called from an atomic context and have to restore
++ the state of the uart chip on return such that the system can return
++ to normal when the debugger detaches. You need to be very careful
++ with any kind of lock you consider, because failing here is most
++ going to mean pressing the reset button.
++ </para>
++ </sect1>
++ </chapter>
++ <chapter id="credits">
++ <title>Credits</title>
++ <para>
++ The following people have contributed to this document:
++ <orderedlist>
++ <listitem><para>Amit Kale<email>amitkale at linsyssoft.com</email></para></listitem>
++ <listitem><para>Tom Rini<email>trini at kernel.crashing.org</email></para></listitem>
++ </orderedlist>
++ In March 2008 this document was completely rewritten by:
++ <itemizedlist>
++ <listitem><para>Jason Wessel<email>jason.wessel at windriver.com</email></para></listitem>
++ </itemizedlist>
++ </para>
++ </chapter>
++</book>
++
+diff --git a/Documentation/DocBook/mac80211.tmpl b/Documentation/DocBook/mac80211.tmpl
+new file mode 100644
+index 0000000..b651e0a
+--- /dev/null
++++ b/Documentation/DocBook/mac80211.tmpl
+@@ -0,0 +1,335 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
++ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
++
++<book id="mac80211-developers-guide">
++ <bookinfo>
++ <title>The mac80211 subsystem for kernel developers</title>
++
++ <authorgroup>
++ <author>
++ <firstname>Johannes</firstname>
++ <surname>Berg</surname>
++ <affiliation>
++ <address><email>johannes at sipsolutions.net</email></address>
++ </affiliation>
++ </author>
++ </authorgroup>
++
++ <copyright>
++ <year>2007</year>
++ <year>2008</year>
++ <holder>Johannes Berg</holder>
++ </copyright>
++
++ <legalnotice>
++ <para>
++ This documentation is free software; you can redistribute
++ it and/or modify it under the terms of the GNU General Public
++ License version 2 as published by the Free Software Foundation.
++ </para>
++
++ <para>
++ This documentation 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.
++ </para>
++
++ <para>
++ You should have received a copy of the GNU General Public
++ License along with this documentation; if not, write to the Free
++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ MA 02111-1307 USA
++ </para>
++
++ <para>
++ For more details see the file COPYING in the source
++ distribution of Linux.
++ </para>
++ </legalnotice>
++
++ <abstract>
++!Pinclude/net/mac80211.h Introduction
++!Pinclude/net/mac80211.h Warning
++ </abstract>
++ </bookinfo>
++
++ <toc></toc>
++
++<!--
++Generally, this document shall be ordered by increasing complexity.
++It is important to note that readers should be able to read only
++the first few sections to get a working driver and only advanced
++usage should require reading the full document.
++-->
++
++ <part>
++ <title>The basic mac80211 driver interface</title>
++ <partintro>
++ <para>
++ You should read and understand the information contained
++ within this part of the book while implementing a driver.
++ In some chapters, advanced usage is noted, that may be
++ skipped at first.
++ </para>
++ <para>
++ This part of the book only covers station and monitor mode
++ functionality, additional information required to implement
++ the other modes is covered in the second part of the book.
++ </para>
++ </partintro>
++
++ <chapter id="basics">
++ <title>Basic hardware handling</title>
++ <para>TBD</para>
++ <para>
++ This chapter shall contain information on getting a hw
++ struct allocated and registered with mac80211.
++ </para>
++ <para>
++ Since it is required to allocate rates/modes before registering
++ a hw struct, this chapter shall also contain information on setting
++ up the rate/mode structs.
++ </para>
++ <para>
++ Additionally, some discussion about the callbacks and
++ the general programming model should be in here, including
++ the definition of ieee80211_ops which will be referred to
++ a lot.
++ </para>
++ <para>
++ Finally, a discussion of hardware capabilities should be done
++ with references to other parts of the book.
++ </para>
++<!-- intentionally multiple !F lines to get proper order -->
++!Finclude/net/mac80211.h ieee80211_hw
++!Finclude/net/mac80211.h ieee80211_hw_flags
++!Finclude/net/mac80211.h SET_IEEE80211_DEV
++!Finclude/net/mac80211.h SET_IEEE80211_PERM_ADDR
++!Finclude/net/mac80211.h ieee80211_ops
++!Finclude/net/mac80211.h ieee80211_alloc_hw
++!Finclude/net/mac80211.h ieee80211_register_hw
++!Finclude/net/mac80211.h ieee80211_get_tx_led_name
++!Finclude/net/mac80211.h ieee80211_get_rx_led_name
++!Finclude/net/mac80211.h ieee80211_get_assoc_led_name
++!Finclude/net/mac80211.h ieee80211_get_radio_led_name
++!Finclude/net/mac80211.h ieee80211_unregister_hw
++!Finclude/net/mac80211.h ieee80211_free_hw
++ </chapter>
++
++ <chapter id="phy-handling">
++ <title>PHY configuration</title>
++ <para>TBD</para>
++ <para>
++ This chapter should describe PHY handling including
++ start/stop callbacks and the various structures used.
++ </para>
++!Finclude/net/mac80211.h ieee80211_conf
++!Finclude/net/mac80211.h ieee80211_conf_flags
++ </chapter>
++
++ <chapter id="iface-handling">
++ <title>Virtual interfaces</title>
++ <para>TBD</para>
++ <para>
++ This chapter should describe virtual interface basics
++ that are relevant to the driver (VLANs, MGMT etc are not.)
++ It should explain the use of the add_iface/remove_iface
++ callbacks as well as the interface configuration callbacks.
++ </para>
++ <para>Things related to AP mode should be discussed there.</para>
++ <para>
++ Things related to supporting multiple interfaces should be
++ in the appropriate chapter, a BIG FAT note should be here about
++ this though and the recommendation to allow only a single
++ interface in STA mode at first!
++ </para>
++!Finclude/net/mac80211.h ieee80211_if_types
++!Finclude/net/mac80211.h ieee80211_if_init_conf
++!Finclude/net/mac80211.h ieee80211_if_conf
++ </chapter>
++
++ <chapter id="rx-tx">
++ <title>Receive and transmit processing</title>
++ <sect1>
++ <title>what should be here</title>
++ <para>TBD</para>
++ <para>
++ This should describe the receive and transmit
++ paths in mac80211/the drivers as well as
++ transmit status handling.
++ </para>
++ </sect1>
++ <sect1>
++ <title>Frame format</title>
++!Pinclude/net/mac80211.h Frame format
++ </sect1>
++ <sect1>
++ <title>Alignment issues</title>
++ <para>TBD</para>
++ </sect1>
++ <sect1>
++ <title>Calling into mac80211 from interrupts</title>
++!Pinclude/net/mac80211.h Calling mac80211 from interrupts
++ </sect1>
++ <sect1>
++ <title>functions/definitions</title>
++!Finclude/net/mac80211.h ieee80211_rx_status
++!Finclude/net/mac80211.h mac80211_rx_flags
++!Finclude/net/mac80211.h ieee80211_tx_control
++!Finclude/net/mac80211.h ieee80211_tx_status_flags
++!Finclude/net/mac80211.h ieee80211_rx
++!Finclude/net/mac80211.h ieee80211_rx_irqsafe
++!Finclude/net/mac80211.h ieee80211_tx_status
++!Finclude/net/mac80211.h ieee80211_tx_status_irqsafe
++!Finclude/net/mac80211.h ieee80211_rts_get
++!Finclude/net/mac80211.h ieee80211_rts_duration
++!Finclude/net/mac80211.h ieee80211_ctstoself_get
++!Finclude/net/mac80211.h ieee80211_ctstoself_duration
++!Finclude/net/mac80211.h ieee80211_generic_frame_duration
++!Finclude/net/mac80211.h ieee80211_get_hdrlen_from_skb
++!Finclude/net/mac80211.h ieee80211_get_hdrlen
++!Finclude/net/mac80211.h ieee80211_wake_queue
++!Finclude/net/mac80211.h ieee80211_stop_queue
++!Finclude/net/mac80211.h ieee80211_start_queues
++!Finclude/net/mac80211.h ieee80211_stop_queues
++!Finclude/net/mac80211.h ieee80211_wake_queues
++ </sect1>
++ </chapter>
++
++ <chapter id="filters">
++ <title>Frame filtering</title>
++!Pinclude/net/mac80211.h Frame filtering
++!Finclude/net/mac80211.h ieee80211_filter_flags
++ </chapter>
++ </part>
++
++ <part id="advanced">
++ <title>Advanced driver interface</title>
++ <partintro>
++ <para>
++ Information contained within this part of the book is
++ of interest only for advanced interaction of mac80211
++ with drivers to exploit more hardware capabilities and
++ improve performance.
++ </para>
++ </partintro>
++
++ <chapter id="hardware-crypto-offload">
++ <title>Hardware crypto acceleration</title>
++!Pinclude/net/mac80211.h Hardware crypto acceleration
++<!-- intentionally multiple !F lines to get proper order -->
++!Finclude/net/mac80211.h set_key_cmd
++!Finclude/net/mac80211.h ieee80211_key_conf
++!Finclude/net/mac80211.h ieee80211_key_alg
++!Finclude/net/mac80211.h ieee80211_key_flags
++ </chapter>
++
++ <chapter id="qos">
++ <title>Multiple queues and QoS support</title>
++ <para>TBD</para>
++!Finclude/net/mac80211.h ieee80211_tx_queue_params
++!Finclude/net/mac80211.h ieee80211_tx_queue_stats_data
++!Finclude/net/mac80211.h ieee80211_tx_queue
++ </chapter>
++
++ <chapter id="AP">
++ <title>Access point mode support</title>
++ <para>TBD</para>
++ <para>Some parts of the if_conf should be discussed here instead</para>
++ <para>
++ Insert notes about VLAN interfaces with hw crypto here or
++ in the hw crypto chapter.
++ </para>
++!Finclude/net/mac80211.h ieee80211_get_buffered_bc
++!Finclude/net/mac80211.h ieee80211_beacon_get
++ </chapter>
++
++ <chapter id="multi-iface">
++ <title>Supporting multiple virtual interfaces</title>
++ <para>TBD</para>
++ <para>
++ Note: WDS with identical MAC address should almost always be OK
++ </para>
++ <para>
++ Insert notes about having multiple virtual interfaces with
++ different MAC addresses here, note which configurations are
++ supported by mac80211, add notes about supporting hw crypto
++ with it.
++ </para>
++ </chapter>
++
++ <chapter id="hardware-scan-offload">
++ <title>Hardware scan offload</title>
++ <para>TBD</para>
++!Finclude/net/mac80211.h ieee80211_scan_completed
++ </chapter>
++ </part>
++
++ <part id="rate-control">
++ <title>Rate control interface</title>
++ <partintro>
++ <para>TBD</para>
++ <para>
++ This part of the book describes the rate control algorithm
++ interface and how it relates to mac80211 and drivers.
++ </para>
++ </partintro>
++ <chapter id="dummy">
++ <title>dummy chapter</title>
++ <para>TBD</para>
++ </chapter>
++ </part>
++
++ <part id="internal">
++ <title>Internals</title>
++ <partintro>
++ <para>TBD</para>
++ <para>
++ This part of the book describes mac80211 internals.
++ </para>
++ </partintro>
++
++ <chapter id="key-handling">
++ <title>Key handling</title>
++ <sect1>
++ <title>Key handling basics</title>
++!Pnet/mac80211/key.c Key handling basics
++ </sect1>
++ <sect1>
++ <title>MORE TBD</title>
++ <para>TBD</para>
++ </sect1>
++ </chapter>
++
++ <chapter id="rx-processing">
++ <title>Receive processing</title>
++ <para>TBD</para>
++ </chapter>
++
++ <chapter id="tx-processing">
++ <title>Transmit processing</title>
++ <para>TBD</para>
++ </chapter>
++
++ <chapter id="sta-info">
++ <title>Station info handling</title>
++ <sect1>
++ <title>Programming information</title>
++!Fnet/mac80211/sta_info.h sta_info
++!Fnet/mac80211/sta_info.h ieee80211_sta_info_flags
++ </sect1>
++ <sect1>
++ <title>STA information lifetime rules</title>
++!Pnet/mac80211/sta_info.c STA information lifetime rules
++ </sect1>
++ </chapter>
++
++ <chapter id="synchronisation">
++ <title>Synchronisation</title>
++ <para>TBD</para>
++ <para>Locking, lots of RCU</para>
++ </chapter>
++ </part>
++</book>
+diff --git a/Documentation/DocBook/writing_usb_driver.tmpl b/Documentation/DocBook/writing_usb_driver.tmpl
+index d4188d4..eeff19c 100644
+--- a/Documentation/DocBook/writing_usb_driver.tmpl
++++ b/Documentation/DocBook/writing_usb_driver.tmpl
+@@ -100,8 +100,8 @@
+ useful documents, at the USB home page (see Resources). An excellent
+ introduction to the Linux USB subsystem can be found at the USB Working
+ Devices List (see Resources). It explains how the Linux USB subsystem is
+- structured and introduces the reader to the concept of USB urbs, which
+- are essential to USB drivers.
++ structured and introduces the reader to the concept of USB urbs
++ (USB Request Blocks), which are essential to USB drivers.
+ </para>
+ <para>
+ The first thing a Linux USB driver needs to do is register itself with
+@@ -162,8 +162,8 @@ static int __init usb_skel_init(void)
+ module_init(usb_skel_init);
+ </programlisting>
+ <para>
+- When the driver is unloaded from the system, it needs to unregister
+- itself with the USB subsystem. This is done with the usb_unregister
++ When the driver is unloaded from the system, it needs to deregister
++ itself with the USB subsystem. This is done with the usb_deregister
+ function:
+ </para>
+ <programlisting>
+@@ -232,7 +232,7 @@ static int skel_probe(struct usb_interface *interface,
+ were passed to the USB subsystem will be called from a user program trying
+ to talk to the device. The first function called will be open, as the
+ program tries to open the device for I/O. We increment our private usage
+- count and save off a pointer to our internal structure in the file
++ count and save a pointer to our internal structure in the file
+ structure. This is done so that future calls to file operations will
+ enable the driver to determine which device the user is addressing. All
+ of this is done with the following code:
+@@ -252,8 +252,8 @@ file->private_data = dev;
+ send to the device based on the size of the write urb it has created (this
+ size depends on the size of the bulk out end point that the device has).
+ Then it copies the data from user space to kernel space, points the urb to
+- the data and submits the urb to the USB subsystem. This can be shown in
+- he following code:
++ the data and submits the urb to the USB subsystem. This can be seen in
++ the following code:
+ </para>
+ <programlisting>
+ /* we can only write as much as 1 urb will hold */
+diff --git a/Documentation/HOWTO b/Documentation/HOWTO
+index 5483561..0291ade 100644
+--- a/Documentation/HOWTO
++++ b/Documentation/HOWTO
+@@ -249,9 +249,11 @@ process is as follows:
+ release a new -rc kernel every week.
+ - Process continues until the kernel is considered "ready", the
+ process should last around 6 weeks.
+- - A list of known regressions present in each -rc release is
+- tracked at the following URI:
+- http://kernelnewbies.org/known_regressions
++ - Known regressions in each release are periodically posted to the
++ linux-kernel mailing list. The goal is to reduce the length of
++ that list to zero before declaring the kernel to be "ready," but, in
++ the real world, a small number of regressions often remain at
++ release time.
+
+ It is worth mentioning what Andrew Morton wrote on the linux-kernel
+ mailing list about kernel releases:
+@@ -261,7 +263,7 @@ mailing list about kernel releases:
+
+ 2.6.x.y -stable kernel tree
+ ---------------------------
+-Kernels with 4 digit versions are -stable kernels. They contain
++Kernels with 4-part versions are -stable kernels. They contain
+ relatively small and critical fixes for security problems or significant
+ regressions discovered in a given 2.6.x kernel.
+
+@@ -273,7 +275,10 @@ If no 2.6.x.y kernel is available, then the highest numbered 2.6.x
+ kernel is the current stable kernel.
+
+ 2.6.x.y are maintained by the "stable" team <stable at kernel.org>, and are
+-released almost every other week.
++released as needs dictate. The normal release period is approximately
++two weeks, but it can be longer if there are no pressing problems. A
++security-related problem, instead, can cause a release to happen almost
++instantly.
+
+ The file Documentation/stable_kernel_rules.txt in the kernel tree
+ documents what kinds of changes are acceptable for the -stable tree, and
+@@ -298,7 +303,9 @@ a while Andrew or the subsystem maintainer pushes it on to Linus for
+ inclusion in mainline.
+
+ It is heavily encouraged that all new patches get tested in the -mm tree
+-before they are sent to Linus for inclusion in the main kernel tree.
++before they are sent to Linus for inclusion in the main kernel tree. Code
++which does not make an appearance in -mm before the opening of the merge
++window will prove hard to merge into the mainline.
+
+ These kernels are not appropriate for use on systems that are supposed
+ to be stable and they are more risky to run than any of the other
+@@ -354,11 +361,12 @@ Here is a list of some of the different kernel trees available:
+ - SCSI, James Bottomley <James.Bottomley at SteelEye.com>
+ git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
+
++ - x86, Ingo Molnar <mingo at elte.hu>
++ git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git
++
+ quilt trees:
+- - USB, PCI, Driver Core, and I2C, Greg Kroah-Hartman <gregkh at suse.de>
++ - USB, Driver Core, and I2C, Greg Kroah-Hartman <gregkh at suse.de>
+ kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
+- - x86-64, partly i386, Andi Kleen <ak at suse.de>
+- ftp.firstfloor.org:/pub/ak/x86_64/quilt/
+
+ Other kernel trees can be found listed at http://git.kernel.org/ and in
+ the MAINTAINERS file.
+@@ -392,8 +400,8 @@ If you want to be advised of the future bug reports, you can subscribe to the
+ bugme-new mailing list (only new bug reports are mailed here) or to the
+ bugme-janitor mailing list (every change in the bugzilla is mailed here)
+
+- http://lists.osdl.org/mailman/listinfo/bugme-new
+- http://lists.osdl.org/mailman/listinfo/bugme-janitors
++ http://lists.linux-foundation.org/mailman/listinfo/bugme-new
++ http://lists.linux-foundation.org/mailman/listinfo/bugme-janitors
+
+
+
+diff --git a/Documentation/PCI/00-INDEX b/Documentation/PCI/00-INDEX
+new file mode 100644
+index 0000000..49f4394
+--- /dev/null
++++ b/Documentation/PCI/00-INDEX
+@@ -0,0 +1,12 @@
++00-INDEX
++ - this file
++PCI-DMA-mapping.txt
++ - info for PCI drivers using DMA portably across all platforms
++PCIEBUS-HOWTO.txt
++ - a guide describing the PCI Express Port Bus driver
++pci-error-recovery.txt
++ - info on PCI error recovery
++pci.txt
++ - info on the PCI subsystem for device driver authors
++pcieaer-howto.txt
++ - the PCI Express Advanced Error Reporting Driver Guide HOWTO
+diff --git a/Documentation/PCI/PCIEBUS-HOWTO.txt b/Documentation/PCI/PCIEBUS-HOWTO.txt
+new file mode 100644
+index 0000000..9a07e38
+--- /dev/null
++++ b/Documentation/PCI/PCIEBUS-HOWTO.txt
+@@ -0,0 +1,217 @@
++ The PCI Express Port Bus Driver Guide HOWTO
++ Tom L Nguyen tom.l.nguyen at intel.com
++ 11/03/2004
++
++1. About this guide
++
++This guide describes the basics of the PCI Express Port Bus driver
++and provides information on how to enable the service drivers to
++register/unregister with the PCI Express Port Bus Driver.
++
++2. Copyright 2004 Intel Corporation
++
++3. What is the PCI Express Port Bus Driver
++
++A PCI Express Port is a logical PCI-PCI Bridge structure. There
++are two types of PCI Express Port: the Root Port and the Switch
++Port. The Root Port originates a PCI Express link from a PCI Express
++Root Complex and the Switch Port connects PCI Express links to
++internal logical PCI buses. The Switch Port, which has its secondary
++bus representing the switch's internal routing logic, is called the
++switch's Upstream Port. The switch's Downstream Port is bridging from
++switch's internal routing bus to a bus representing the downstream
++PCI Express link from the PCI Express Switch.
++
++A PCI Express Port can provide up to four distinct functions,
++referred to in this document as services, depending on its port type.
++PCI Express Port's services include native hotplug support (HP),
++power management event support (PME), advanced error reporting
++support (AER), and virtual channel support (VC). These services may
++be handled by a single complex driver or be individually distributed
++and handled by corresponding service drivers.
++
++4. Why use the PCI Express Port Bus Driver?
++
++In existing Linux kernels, the Linux Device Driver Model allows a
++physical device to be handled by only a single driver. The PCI
++Express Port is a PCI-PCI Bridge device with multiple distinct
++services. To maintain a clean and simple solution each service
++may have its own software service driver. In this case several
++service drivers will compete for a single PCI-PCI Bridge device.
++For example, if the PCI Express Root Port native hotplug service
++driver is loaded first, it claims a PCI-PCI Bridge Root Port. The
++kernel therefore does not load other service drivers for that Root
++Port. In other words, it is impossible to have multiple service
++drivers load and run on a PCI-PCI Bridge device simultaneously
++using the current driver model.
++
++To enable multiple service drivers running simultaneously requires
++having a PCI Express Port Bus driver, which manages all populated
++PCI Express Ports and distributes all provided service requests
++to the corresponding service drivers as required. Some key
++advantages of using the PCI Express Port Bus driver are listed below:
++
++ - Allow multiple service drivers to run simultaneously on
++ a PCI-PCI Bridge Port device.
++
++ - Allow service drivers implemented in an independent
++ staged approach.
++
++ - Allow one service driver to run on multiple PCI-PCI Bridge
++ Port devices.
++
++ - Manage and distribute resources of a PCI-PCI Bridge Port
++ device to requested service drivers.
++
++5. Configuring the PCI Express Port Bus Driver vs. Service Drivers
++
++5.1 Including the PCI Express Port Bus Driver Support into the Kernel
++
++Including the PCI Express Port Bus driver depends on whether the PCI
++Express support is included in the kernel config. The kernel will
++automatically include the PCI Express Port Bus driver as a kernel
++driver when the PCI Express support is enabled in the kernel.
++
++5.2 Enabling Service Driver Support
++
++PCI device drivers are implemented based on Linux Device Driver Model.
++All service drivers are PCI device drivers. As discussed above, it is
++impossible to load any service driver once the kernel has loaded the
++PCI Express Port Bus Driver. To meet the PCI Express Port Bus Driver
++Model requires some minimal changes on existing service drivers that
++imposes no impact on the functionality of existing service drivers.
++
++A service driver is required to use the two APIs shown below to
++register its service with the PCI Express Port Bus driver (see
++section 5.2.1 & 5.2.2). It is important that a service driver
++initializes the pcie_port_service_driver data structure, included in
++header file /include/linux/pcieport_if.h, before calling these APIs.
++Failure to do so will result an identity mismatch, which prevents
++the PCI Express Port Bus driver from loading a service driver.
++
++5.2.1 pcie_port_service_register
++
++int pcie_port_service_register(struct pcie_port_service_driver *new)
++
++This API replaces the Linux Driver Model's pci_module_init API. A
++service driver should always calls pcie_port_service_register at
++module init. Note that after service driver being loaded, calls
++such as pci_enable_device(dev) and pci_set_master(dev) are no longer
++necessary since these calls are executed by the PCI Port Bus driver.
++
++5.2.2 pcie_port_service_unregister
++
++void pcie_port_service_unregister(struct pcie_port_service_driver *new)
++
++pcie_port_service_unregister replaces the Linux Driver Model's
++pci_unregister_driver. It's always called by service driver when a
++module exits.
++
++5.2.3 Sample Code
++
++Below is sample service driver code to initialize the port service
++driver data structure.
++
++static struct pcie_port_service_id service_id[] = { {
++ .vendor = PCI_ANY_ID,
++ .device = PCI_ANY_ID,
++ .port_type = PCIE_RC_PORT,
++ .service_type = PCIE_PORT_SERVICE_AER,
++ }, { /* end: all zeroes */ }
++};
++
++static struct pcie_port_service_driver root_aerdrv = {
++ .name = (char *)device_name,
++ .id_table = &service_id[0],
++
++ .probe = aerdrv_load,
++ .remove = aerdrv_unload,
++
++ .suspend = aerdrv_suspend,
++ .resume = aerdrv_resume,
++};
++
++Below is a sample code for registering/unregistering a service
++driver.
++
++static int __init aerdrv_service_init(void)
++{
++ int retval = 0;
++
++ retval = pcie_port_service_register(&root_aerdrv);
++ if (!retval) {
++ /*
++ * FIX ME
++ */
++ }
++ return retval;
++}
++
++static void __exit aerdrv_service_exit(void)
++{
++ pcie_port_service_unregister(&root_aerdrv);
++}
++
++module_init(aerdrv_service_init);
++module_exit(aerdrv_service_exit);
++
++6. Possible Resource Conflicts
++
++Since all service drivers of a PCI-PCI Bridge Port device are
++allowed to run simultaneously, below lists a few of possible resource
++conflicts with proposed solutions.
++
++6.1 MSI Vector Resource
++
++The MSI capability structure enables a device software driver to call
++pci_enable_msi to request MSI based interrupts. Once MSI interrupts
++are enabled on a device, it stays in this mode until a device driver
++calls pci_disable_msi to disable MSI interrupts and revert back to
++INTx emulation mode. Since service drivers of the same PCI-PCI Bridge
++port share the same physical device, if an individual service driver
++calls pci_enable_msi/pci_disable_msi it may result unpredictable
++behavior. For example, two service drivers run simultaneously on the
++same physical Root Port. Both service drivers call pci_enable_msi to
++request MSI based interrupts. A service driver may not know whether
++any other service drivers have run on this Root Port. If either one
++of them calls pci_disable_msi, it puts the other service driver
++in a wrong interrupt mode.
++
++To avoid this situation all service drivers are not permitted to
++switch interrupt mode on its device. The PCI Express Port Bus driver
++is responsible for determining the interrupt mode and this should be
++transparent to service drivers. Service drivers need to know only
++the vector IRQ assigned to the field irq of struct pcie_device, which
++is passed in when the PCI Express Port Bus driver probes each service
++driver. Service drivers should use (struct pcie_device*)dev->irq to
++call request_irq/free_irq. In addition, the interrupt mode is stored
++in the field interrupt_mode of struct pcie_device.
++
++6.2 MSI-X Vector Resources
++
++Similar to the MSI a device driver for an MSI-X capable device can
++call pci_enable_msix to request MSI-X interrupts. All service drivers
++are not permitted to switch interrupt mode on its device. The PCI
++Express Port Bus driver is responsible for determining the interrupt
++mode and this should be transparent to service drivers. Any attempt
++by service driver to call pci_enable_msix/pci_disable_msix may
++result unpredictable behavior. Service drivers should use
++(struct pcie_device*)dev->irq and call request_irq/free_irq.
++
++6.3 PCI Memory/IO Mapped Regions
++
++Service drivers for PCI Express Power Management (PME), Advanced
++Error Reporting (AER), Hot-Plug (HP) and Virtual Channel (VC) access
++PCI configuration space on the PCI Express port. In all cases the
++registers accessed are independent of each other. This patch assumes
++that all service drivers will be well behaved and not overwrite
++other service driver's configuration settings.
++
++6.4 PCI Config Registers
++
++Each service driver runs its PCI config operations on its own
++capability structure except the PCI Express capability structure, in
++which Root Control register and Device Control register are shared
++between PME and AER. This patch assumes that all service drivers
++will be well behaved and not overwrite other service driver's
++configuration settings.
+diff --git a/Documentation/PCI/pci-error-recovery.txt b/Documentation/PCI/pci-error-recovery.txt
+new file mode 100644
+index 0000000..6650af4
+--- /dev/null
++++ b/Documentation/PCI/pci-error-recovery.txt
+@@ -0,0 +1,396 @@
++
++ PCI Error Recovery
++ ------------------
++ February 2, 2006
++
++ Current document maintainer:
++ Linas Vepstas <linas at austin.ibm.com>
++
++
++Many PCI bus controllers are able to detect a variety of hardware
++PCI errors on the bus, such as parity errors on the data and address
++busses, as well as SERR and PERR errors. Some of the more advanced
++chipsets are able to deal with these errors; these include PCI-E chipsets,
++and the PCI-host bridges found on IBM Power4 and Power5-based pSeries
++boxes. A typical action taken is to disconnect the affected device,
++halting all I/O to it. The goal of a disconnection is to avoid system
++corruption; for example, to halt system memory corruption due to DMA's
++to "wild" addresses. Typically, a reconnection mechanism is also
++offered, so that the affected PCI device(s) are reset and put back
++into working condition. The reset phase requires coordination
++between the affected device drivers and the PCI controller chip.
++This document describes a generic API for notifying device drivers
++of a bus disconnection, and then performing error recovery.
++This API is currently implemented in the 2.6.16 and later kernels.
++
++Reporting and recovery is performed in several steps. First, when
++a PCI hardware error has resulted in a bus disconnect, that event
++is reported as soon as possible to all affected device drivers,
++including multiple instances of a device driver on multi-function
++cards. This allows device drivers to avoid deadlocking in spinloops,
++waiting for some i/o-space register to change, when it never will.
++It also gives the drivers a chance to defer incoming I/O as
++needed.
++
++Next, recovery is performed in several stages. Most of the complexity
++is forced by the need to handle multi-function devices, that is,
++devices that have multiple device drivers associated with them.
++In the first stage, each driver is allowed to indicate what type
++of reset it desires, the choices being a simple re-enabling of I/O
++or requesting a hard reset (a full electrical #RST of the PCI card).
++If any driver requests a full reset, that is what will be done.
++
++After a full reset and/or a re-enabling of I/O, all drivers are
++again notified, so that they may then perform any device setup/config
++that may be required. After these have all completed, a final
++"resume normal operations" event is sent out.
++
++The biggest reason for choosing a kernel-based implementation rather
++than a user-space implementation was the need to deal with bus
++disconnects of PCI devices attached to storage media, and, in particular,
++disconnects from devices holding the root file system. If the root
++file system is disconnected, a user-space mechanism would have to go
++through a large number of contortions to complete recovery. Almost all
++of the current Linux file systems are not tolerant of disconnection
++from/reconnection to their underlying block device. By contrast,
++bus errors are easy to manage in the device driver. Indeed, most
++device drivers already handle very similar recovery procedures;
++for example, the SCSI-generic layer already provides significant
++mechanisms for dealing with SCSI bus errors and SCSI bus resets.
++
++
++Detailed Design
++---------------
++Design and implementation details below, based on a chain of
++public email discussions with Ben Herrenschmidt, circa 5 April 2005.
++
++The error recovery API support is exposed to the driver in the form of
++a structure of function pointers pointed to by a new field in struct
++pci_driver. A driver that fails to provide the structure is "non-aware",
++and the actual recovery steps taken are platform dependent. The
++arch/powerpc implementation will simulate a PCI hotplug remove/add.
++
++This structure has the form:
++struct pci_error_handlers
++{
++ int (*error_detected)(struct pci_dev *dev, enum pci_channel_state);
++ int (*mmio_enabled)(struct pci_dev *dev);
++ int (*link_reset)(struct pci_dev *dev);
++ int (*slot_reset)(struct pci_dev *dev);
++ void (*resume)(struct pci_dev *dev);
++};
++
++The possible channel states are:
++enum pci_channel_state {
++ pci_channel_io_normal, /* I/O channel is in normal state */
++ pci_channel_io_frozen, /* I/O to channel is blocked */
++ pci_channel_io_perm_failure, /* PCI card is dead */
++};
++
++Possible return values are:
++enum pci_ers_result {
++ PCI_ERS_RESULT_NONE, /* no result/none/not supported in device driver */
++ PCI_ERS_RESULT_CAN_RECOVER, /* Device driver can recover without slot reset */
++ PCI_ERS_RESULT_NEED_RESET, /* Device driver wants slot to be reset. */
++ PCI_ERS_RESULT_DISCONNECT, /* Device has completely failed, is unrecoverable */
++ PCI_ERS_RESULT_RECOVERED, /* Device driver is fully recovered and operational */
++};
++
++A driver does not have to implement all of these callbacks; however,
++if it implements any, it must implement error_detected(). If a callback
++is not implemented, the corresponding feature is considered unsupported.
++For example, if mmio_enabled() and resume() aren't there, then it
++is assumed that the driver is not doing any direct recovery and requires
++a reset. If link_reset() is not implemented, the card is assumed as
++not care about link resets. Typically a driver will want to know about
++a slot_reset().
++
++The actual steps taken by a platform to recover from a PCI error
++event will be platform-dependent, but will follow the general
++sequence described below.
++
++STEP 0: Error Event
++-------------------
++PCI bus error is detect by the PCI hardware. On powerpc, the slot
++is isolated, in that all I/O is blocked: all reads return 0xffffffff,
++all writes are ignored.
++
++
++STEP 1: Notification
++--------------------
++Platform calls the error_detected() callback on every instance of
++every driver affected by the error.
++
++At this point, the device might not be accessible anymore, depending on
++the platform (the slot will be isolated on powerpc). The driver may
++already have "noticed" the error because of a failing I/O, but this
++is the proper "synchronization point", that is, it gives the driver
++a chance to cleanup, waiting for pending stuff (timers, whatever, etc...)
++to complete; it can take semaphores, schedule, etc... everything but
++touch the device. Within this function and after it returns, the driver
++shouldn't do any new IOs. Called in task context. This is sort of a
++"quiesce" point. See note about interrupts at the end of this doc.
++
++All drivers participating in this system must implement this call.
++The driver must return one of the following result codes:
++ - PCI_ERS_RESULT_CAN_RECOVER:
++ Driver returns this if it thinks it might be able to recover
++ the HW by just banging IOs or if it wants to be given
++ a chance to extract some diagnostic information (see
++ mmio_enable, below).
++ - PCI_ERS_RESULT_NEED_RESET:
++ Driver returns this if it can't recover without a hard
++ slot reset.
++ - PCI_ERS_RESULT_DISCONNECT:
++ Driver returns this if it doesn't want to recover at all.
++
++The next step taken will depend on the result codes returned by the
++drivers.
++
++If all drivers on the segment/slot return PCI_ERS_RESULT_CAN_RECOVER,
++then the platform should re-enable IOs on the slot (or do nothing in
++particular, if the platform doesn't isolate slots), and recovery
++proceeds to STEP 2 (MMIO Enable).
++
++If any driver requested a slot reset (by returning PCI_ERS_RESULT_NEED_RESET),
++then recovery proceeds to STEP 4 (Slot Reset).
++
++If the platform is unable to recover the slot, the next step
++is STEP 6 (Permanent Failure).
++
++>>> The current powerpc implementation assumes that a device driver will
++>>> *not* schedule or semaphore in this routine; the current powerpc
++>>> implementation uses one kernel thread to notify all devices;
++>>> thus, if one device sleeps/schedules, all devices are affected.
++>>> Doing better requires complex multi-threaded logic in the error
++>>> recovery implementation (e.g. waiting for all notification threads
++>>> to "join" before proceeding with recovery.) This seems excessively
++>>> complex and not worth implementing.
++
++>>> The current powerpc implementation doesn't much care if the device
++>>> attempts I/O at this point, or not. I/O's will fail, returning
++>>> a value of 0xff on read, and writes will be dropped. If the device
++>>> driver attempts more than 10K I/O's to a frozen adapter, it will
++>>> assume that the device driver has gone into an infinite loop, and
++>>> it will panic the kernel. There doesn't seem to be any other
++>>> way of stopping a device driver that insists on spinning on I/O.
++
++STEP 2: MMIO Enabled
++-------------------
++The platform re-enables MMIO to the device (but typically not the
++DMA), and then calls the mmio_enabled() callback on all affected
++device drivers.
++
++This is the "early recovery" call. IOs are allowed again, but DMA is
++not (hrm... to be discussed, I prefer not), with some restrictions. This
++is NOT a callback for the driver to start operations again, only to
++peek/poke at the device, extract diagnostic information, if any, and
++eventually do things like trigger a device local reset or some such,
++but not restart operations. This is callback is made if all drivers on
++a segment agree that they can try to recover and if no automatic link reset
++was performed by the HW. If the platform can't just re-enable IOs without
++a slot reset or a link reset, it wont call this callback, and instead
++will have gone directly to STEP 3 (Link Reset) or STEP 4 (Slot Reset)
++
++>>> The following is proposed; no platform implements this yet:
++>>> Proposal: All I/O's should be done _synchronously_ from within
++>>> this callback, errors triggered by them will be returned via
++>>> the normal pci_check_whatever() API, no new error_detected()
++>>> callback will be issued due to an error happening here. However,
++>>> such an error might cause IOs to be re-blocked for the whole
++>>> segment, and thus invalidate the recovery that other devices
++>>> on the same segment might have done, forcing the whole segment
++>>> into one of the next states, that is, link reset or slot reset.
++
++The driver should return one of the following result codes:
++ - PCI_ERS_RESULT_RECOVERED
++ Driver returns this if it thinks the device is fully
++ functional and thinks it is ready to start
++ normal driver operations again. There is no
++ guarantee that the driver will actually be
++ allowed to proceed, as another driver on the
++ same segment might have failed and thus triggered a
++ slot reset on platforms that support it.
++
++ - PCI_ERS_RESULT_NEED_RESET
++ Driver returns this if it thinks the device is not
++ recoverable in it's current state and it needs a slot
++ reset to proceed.
++
++ - PCI_ERS_RESULT_DISCONNECT
++ Same as above. Total failure, no recovery even after
++ reset driver dead. (To be defined more precisely)
++
++The next step taken depends on the results returned by the drivers.
++If all drivers returned PCI_ERS_RESULT_RECOVERED, then the platform
++proceeds to either STEP3 (Link Reset) or to STEP 5 (Resume Operations).
++
++If any driver returned PCI_ERS_RESULT_NEED_RESET, then the platform
++proceeds to STEP 4 (Slot Reset)
++
++>>> The current powerpc implementation does not implement this callback.
++
++
++STEP 3: Link Reset
++------------------
++The platform resets the link, and then calls the link_reset() callback
++on all affected device drivers. This is a PCI-Express specific state
++and is done whenever a non-fatal error has been detected that can be
++"solved" by resetting the link. This call informs the driver of the
++reset and the driver should check to see if the device appears to be
++in working condition.
++
++The driver is not supposed to restart normal driver I/O operations
++at this point. It should limit itself to "probing" the device to
++check it's recoverability status. If all is right, then the platform
++will call resume() once all drivers have ack'd link_reset().
++
++ Result codes:
++ (identical to STEP 3 (MMIO Enabled)
++
++The platform then proceeds to either STEP 4 (Slot Reset) or STEP 5
++(Resume Operations).
++
++>>> The current powerpc implementation does not implement this callback.
++
++
++STEP 4: Slot Reset
++------------------
++The platform performs a soft or hard reset of the device, and then
++calls the slot_reset() callback.
++
++A soft reset consists of asserting the adapter #RST line and then
++restoring the PCI BAR's and PCI configuration header to a state
++that is equivalent to what it would be after a fresh system
++power-on followed by power-on BIOS/system firmware initialization.
++If the platform supports PCI hotplug, then the reset might be
++performed by toggling the slot electrical power off/on.
++
++It is important for the platform to restore the PCI config space
++to the "fresh poweron" state, rather than the "last state". After
++a slot reset, the device driver will almost always use its standard
++device initialization routines, and an unusual config space setup
++may result in hung devices, kernel panics, or silent data corruption.
++
++This call gives drivers the chance to re-initialize the hardware
++(re-download firmware, etc.). At this point, the driver may assume
++that he card is in a fresh state and is fully functional. In
++particular, interrupt generation should work normally.
++
++Drivers should not yet restart normal I/O processing operations
++at this point. If all device drivers report success on this
++callback, the platform will call resume() to complete the sequence,
++and let the driver restart normal I/O processing.
++
++A driver can still return a critical failure for this function if
++it can't get the device operational after reset. If the platform
++previously tried a soft reset, it might now try a hard reset (power
++cycle) and then call slot_reset() again. It the device still can't
++be recovered, there is nothing more that can be done; the platform
++will typically report a "permanent failure" in such a case. The
++device will be considered "dead" in this case.
++
++Drivers for multi-function cards will need to coordinate among
++themselves as to which driver instance will perform any "one-shot"
++or global device initialization. For example, the Symbios sym53cxx2
++driver performs device init only from PCI function 0:
++
+++ if (PCI_FUNC(pdev->devfn) == 0)
+++ sym_reset_scsi_bus(np, 0);
++
++ Result codes:
++ - PCI_ERS_RESULT_DISCONNECT
++ Same as above.
++
++Platform proceeds either to STEP 5 (Resume Operations) or STEP 6 (Permanent
++Failure).
++
++>>> The current powerpc implementation does not currently try a
++>>> power-cycle reset if the driver returned PCI_ERS_RESULT_DISCONNECT.
++>>> However, it probably should.
++
++
++STEP 5: Resume Operations
++-------------------------
++The platform will call the resume() callback on all affected device
++drivers if all drivers on the segment have returned
++PCI_ERS_RESULT_RECOVERED from one of the 3 previous callbacks.
++The goal of this callback is to tell the driver to restart activity,
++that everything is back and running. This callback does not return
++a result code.
++
++At this point, if a new error happens, the platform will restart
++a new error recovery sequence.
++
++STEP 6: Permanent Failure
++-------------------------
++A "permanent failure" has occurred, and the platform cannot recover
++the device. The platform will call error_detected() with a
++pci_channel_state value of pci_channel_io_perm_failure.
++
++The device driver should, at this point, assume the worst. It should
++cancel all pending I/O, refuse all new I/O, returning -EIO to
++higher layers. The device driver should then clean up all of its
++memory and remove itself from kernel operations, much as it would
++during system shutdown.
++
++The platform will typically notify the system operator of the
++permanent failure in some way. If the device is hotplug-capable,
++the operator will probably want to remove and replace the device.
++Note, however, not all failures are truly "permanent". Some are
++caused by over-heating, some by a poorly seated card. Many
++PCI error events are caused by software bugs, e.g. DMA's to
++wild addresses or bogus split transactions due to programming
++errors. See the discussion in powerpc/eeh-pci-error-recovery.txt
++for additional detail on real-life experience of the causes of
++software errors.
++
++
++Conclusion; General Remarks
++---------------------------
++The way those callbacks are called is platform policy. A platform with
++no slot reset capability may want to just "ignore" drivers that can't
++recover (disconnect them) and try to let other cards on the same segment
++recover. Keep in mind that in most real life cases, though, there will
++be only one driver per segment.
++
++Now, a note about interrupts. If you get an interrupt and your
++device is dead or has been isolated, there is a problem :)
++The current policy is to turn this into a platform policy.
++That is, the recovery API only requires that:
++
++ - There is no guarantee that interrupt delivery can proceed from any
++device on the segment starting from the error detection and until the
++resume callback is sent, at which point interrupts are expected to be
++fully operational.
++
++ - There is no guarantee that interrupt delivery is stopped, that is,
++a driver that gets an interrupt after detecting an error, or that detects
++an error within the interrupt handler such that it prevents proper
++ack'ing of the interrupt (and thus removal of the source) should just
++return IRQ_NOTHANDLED. It's up to the platform to deal with that
++condition, typically by masking the IRQ source during the duration of
++the error handling. It is expected that the platform "knows" which
++interrupts are routed to error-management capable slots and can deal
++with temporarily disabling that IRQ number during error processing (this
++isn't terribly complex). That means some IRQ latency for other devices
++sharing the interrupt, but there is simply no other way. High end
++platforms aren't supposed to share interrupts between many devices
++anyway :)
++
++>>> Implementation details for the powerpc platform are discussed in
++>>> the file Documentation/powerpc/eeh-pci-error-recovery.txt
++
++>>> As of this writing, there are six device drivers with patches
++>>> implementing error recovery. Not all of these patches are in
++>>> mainline yet. These may be used as "examples":
++>>>
++>>> drivers/scsi/ipr.c
++>>> drivers/scsi/sym53cxx_2
++>>> drivers/next/e100.c
++>>> drivers/net/e1000
++>>> drivers/net/ixgb
++>>> drivers/net/s2io.c
++
++The End
++-------
+diff --git a/Documentation/PCI/pci.txt b/Documentation/PCI/pci.txt
+new file mode 100644
+index 0000000..8d4dc62
+--- /dev/null
++++ b/Documentation/PCI/pci.txt
+@@ -0,0 +1,646 @@
++
++ How To Write Linux PCI Drivers
++
++ by Martin Mares <mj at ucw.cz> on 07-Feb-2000
++ updated by Grant Grundler <grundler at parisc-linux.org> on 23-Dec-2006
++
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++The world of PCI is vast and full of (mostly unpleasant) surprises.
++Since each CPU architecture implements different chip-sets and PCI devices
++have different requirements (erm, "features"), the result is the PCI support
++in the Linux kernel is not as trivial as one would wish. This short paper
++tries to introduce all potential driver authors to Linux APIs for
++PCI device drivers.
++
++A more complete resource is the third edition of "Linux Device Drivers"
++by Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman.
++LDD3 is available for free (under Creative Commons License) from:
++
++ http://lwn.net/Kernel/LDD3/
++
++However, keep in mind that all documents are subject to "bit rot".
++Refer to the source code if things are not working as described here.
++
++Please send questions/comments/patches about Linux PCI API to the
++"Linux PCI" <linux-pci at atrey.karlin.mff.cuni.cz> mailing list.
++
++
++
++0. Structure of PCI drivers
++~~~~~~~~~~~~~~~~~~~~~~~~~~~
++PCI drivers "discover" PCI devices in a system via pci_register_driver().
++Actually, it's the other way around. When the PCI generic code discovers
++a new device, the driver with a matching "description" will be notified.
++Details on this below.
++
++pci_register_driver() leaves most of the probing for devices to
++the PCI layer and supports online insertion/removal of devices [thus
++supporting hot-pluggable PCI, CardBus, and Express-Card in a single driver].
++pci_register_driver() call requires passing in a table of function
++pointers and thus dictates the high level structure of a driver.
++
++Once the driver knows about a PCI device and takes ownership, the
++driver generally needs to perform the following initialization:
++
++ Enable the device
++ Request MMIO/IOP resources
++ Set the DMA mask size (for both coherent and streaming DMA)
++ Allocate and initialize shared control data (pci_allocate_coherent())
++ Access device configuration space (if needed)
++ Register IRQ handler (request_irq())
++ Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip)
++ Enable DMA/processing engines
++
++When done using the device, and perhaps the module needs to be unloaded,
++the driver needs to take the follow steps:
++ Disable the device from generating IRQs
++ Release the IRQ (free_irq())
++ Stop all DMA activity
++ Release DMA buffers (both streaming and coherent)
++ Unregister from other subsystems (e.g. scsi or netdev)
++ Release MMIO/IOP resources
++ Disable the device
++
++Most of these topics are covered in the following sections.
++For the rest look at LDD3 or <linux/pci.h> .
++
++If the PCI subsystem is not configured (CONFIG_PCI is not set), most of
++the PCI functions described below are defined as inline functions either
++completely empty or just returning an appropriate error codes to avoid
++lots of ifdefs in the drivers.
++
++
++
++1. pci_register_driver() call
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++PCI device drivers call pci_register_driver() during their
++initialization with a pointer to a structure describing the driver
++(struct pci_driver):
++
++ field name Description
++ ---------- ------------------------------------------------------
++ id_table Pointer to table of device ID's the driver is
++ interested in. Most drivers should export this
++ table using MODULE_DEVICE_TABLE(pci,...).
++
++ probe This probing function gets called (during execution
++ of pci_register_driver() for already existing
++ devices or later if a new device gets inserted) for
++ all PCI devices which match the ID table and are not
++ "owned" by the other drivers yet. This function gets
++ passed a "struct pci_dev *" for each device whose
++ entry in the ID table matches the device. The probe
++ function returns zero when the driver chooses to
++ take "ownership" of the device or an error code
++ (negative number) otherwise.
++ The probe function always gets called from process
++ context, so it can sleep.
++
++ remove The remove() function gets called whenever a device
++ being handled by this driver is removed (either during
++ deregistration of the driver or when it's manually
++ pulled out of a hot-pluggable slot).
++ The remove function always gets called from process
++ context, so it can sleep.
++
++ suspend Put device into low power state.
++ suspend_late Put device into low power state.
++
++ resume_early Wake device from low power state.
++ resume Wake device from low power state.
++
++ (Please see Documentation/power/pci.txt for descriptions
++ of PCI Power Management and the related functions.)
++
++ shutdown Hook into reboot_notifier_list (kernel/sys.c).
++ Intended to stop any idling DMA operations.
++ Useful for enabling wake-on-lan (NIC) or changing
++ the power state of a device before reboot.
++ e.g. drivers/net/e100.c.
++
++ err_handler See Documentation/PCI/pci-error-recovery.txt
++
++
++The ID table is an array of struct pci_device_id entries ending with an
++all-zero entry; use of the macro DEFINE_PCI_DEVICE_TABLE is the preferred
++method of declaring the table. Each entry consists of:
++
++ vendor,device Vendor and device ID to match (or PCI_ANY_ID)
++
++ subvendor, Subsystem vendor and device ID to match (or PCI_ANY_ID)
++ subdevice,
++
++ class Device class, subclass, and "interface" to match.
++ See Appendix D of the PCI Local Bus Spec or
++ include/linux/pci_ids.h for a full list of classes.
++ Most drivers do not need to specify class/class_mask
++ as vendor/device is normally sufficient.
++
++ class_mask limit which sub-fields of the class field are compared.
++ See drivers/scsi/sym53c8xx_2/ for example of usage.
++
++ driver_data Data private to the driver.
++ Most drivers don't need to use driver_data field.
++ Best practice is to use driver_data as an index
++ into a static list of equivalent device types,
++ instead of using it as a pointer.
++
++
++Most drivers only need PCI_DEVICE() or PCI_DEVICE_CLASS() to set up
++a pci_device_id table.
++
++New PCI IDs may be added to a device driver pci_ids table at runtime
++as shown below:
++
++echo "vendor device subvendor subdevice class class_mask driver_data" > \
++/sys/bus/pci/drivers/{driver}/new_id
++
++All fields are passed in as hexadecimal values (no leading 0x).
++The vendor and device fields are mandatory, the others are optional. Users
++need pass only as many optional fields as necessary:
++ o subvendor and subdevice fields default to PCI_ANY_ID (FFFFFFFF)
++ o class and classmask fields default to 0
++ o driver_data defaults to 0UL.
++
++Once added, the driver probe routine will be invoked for any unclaimed
++PCI devices listed in its (newly updated) pci_ids list.
++
++When the driver exits, it just calls pci_unregister_driver() and the PCI layer
++automatically calls the remove hook for all devices handled by the driver.
++
++
++1.1 "Attributes" for driver functions/data
++
++Please mark the initialization and cleanup functions where appropriate
++(the corresponding macros are defined in <linux/init.h>):
++
++ __init Initialization code. Thrown away after the driver
++ initializes.
++ __exit Exit code. Ignored for non-modular drivers.
++
++
++ __devinit Device initialization code.
++ Identical to __init if the kernel is not compiled
++ with CONFIG_HOTPLUG, normal function otherwise.
++ __devexit The same for __exit.
++
++Tips on when/where to use the above attributes:
++ o The module_init()/module_exit() functions (and all
++ initialization functions called _only_ from these)
++ should be marked __init/__exit.
++
++ o Do not mark the struct pci_driver.
++
++ o The ID table array should be marked __devinitconst; this is done
++ automatically if the table is declared with DEFINE_PCI_DEVICE_TABLE().
++
++ o The probe() and remove() functions should be marked __devinit
++ and __devexit respectively. All initialization functions
++ exclusively called by the probe() routine, can be marked __devinit.
++ Ditto for remove() and __devexit.
++
++ o If mydriver_remove() is marked with __devexit(), then all address
++ references to mydriver_remove must use __devexit_p(mydriver_remove)
++ (in the struct pci_driver declaration for example).
++ __devexit_p() will generate the function name _or_ NULL if the
++ function will be discarded. For an example, see drivers/net/tg3.c.
++
++ o Do NOT mark a function if you are not sure which mark to use.
++ Better to not mark the function than mark the function wrong.
++
++
++
++2. How to find PCI devices manually
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++PCI drivers should have a really good reason for not using the
++pci_register_driver() interface to search for PCI devices.
++The main reason PCI devices are controlled by multiple drivers
++is because one PCI device implements several different HW services.
++E.g. combined serial/parallel port/floppy controller.
++
++A manual search may be performed using the following constructs:
++
++Searching by vendor and device ID:
++
++ struct pci_dev *dev = NULL;
++ while (dev = pci_get_device(VENDOR_ID, DEVICE_ID, dev))
++ configure_device(dev);
++
++Searching by class ID (iterate in a similar way):
++
++ pci_get_class(CLASS_ID, dev)
++
++Searching by both vendor/device and subsystem vendor/device ID:
++
++ pci_get_subsys(VENDOR_ID,DEVICE_ID, SUBSYS_VENDOR_ID, SUBSYS_DEVICE_ID, dev).
++
++You can use the constant PCI_ANY_ID as a wildcard replacement for
++VENDOR_ID or DEVICE_ID. This allows searching for any device from a
++specific vendor, for example.
++
++These functions are hotplug-safe. They increment the reference count on
++the pci_dev that they return. You must eventually (possibly at module unload)
++decrement the reference count on these devices by calling pci_dev_put().
++
++
++
++3. Device Initialization Steps
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++As noted in the introduction, most PCI drivers need the following steps
++for device initialization:
++
++ Enable the device
++ Request MMIO/IOP resources
++ Set the DMA mask size (for both coherent and streaming DMA)
++ Allocate and initialize shared control data (pci_allocate_coherent())
++ Access device configuration space (if needed)
++ Register IRQ handler (request_irq())
++ Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip)
++ Enable DMA/processing engines.
++
++The driver can access PCI config space registers at any time.
++(Well, almost. When running BIST, config space can go away...but
++that will just result in a PCI Bus Master Abort and config reads
++will return garbage).
++
++
++3.1 Enable the PCI device
++~~~~~~~~~~~~~~~~~~~~~~~~~
++Before touching any device registers, the driver needs to enable
++the PCI device by calling pci_enable_device(). This will:
++ o wake up the device if it was in suspended state,
++ o allocate I/O and memory regions of the device (if BIOS did not),
++ o allocate an IRQ (if BIOS did not).
++
++NOTE: pci_enable_device() can fail! Check the return value.
++
++[ OS BUG: we don't check resource allocations before enabling those
++ resources. The sequence would make more sense if we called
++ pci_request_resources() before calling pci_enable_device().
++ Currently, the device drivers can't detect the bug when when two
++ devices have been allocated the same range. This is not a common
++ problem and unlikely to get fixed soon.
++
++ This has been discussed before but not changed as of 2.6.19:
++ http://lkml.org/lkml/2006/3/2/194
++]
++
++pci_set_master() will enable DMA by setting the bus master bit
++in the PCI_COMMAND register. It also fixes the latency timer value if
++it's set to something bogus by the BIOS.
++
++If the PCI device can use the PCI Memory-Write-Invalidate transaction,
++call pci_set_mwi(). This enables the PCI_COMMAND bit for Mem-Wr-Inval
++and also ensures that the cache line size register is set correctly.
++Check the return value of pci_set_mwi() as not all architectures
++or chip-sets may support Memory-Write-Invalidate. Alternatively,
++if Mem-Wr-Inval would be nice to have but is not required, call
++pci_try_set_mwi() to have the system do its best effort at enabling
++Mem-Wr-Inval.
++
++
++3.2 Request MMIO/IOP resources
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++Memory (MMIO), and I/O port addresses should NOT be read directly
++from the PCI device config space. Use the values in the pci_dev structure
++as the PCI "bus address" might have been remapped to a "host physical"
++address by the arch/chip-set specific kernel support.
++
++See Documentation/IO-mapping.txt for how to access device registers
++or device memory.
++
++The device driver needs to call pci_request_region() to verify
++no other device is already using the same address resource.
++Conversely, drivers should call pci_release_region() AFTER
++calling pci_disable_device().
++The idea is to prevent two devices colliding on the same address range.
++
++[ See OS BUG comment above. Currently (2.6.19), The driver can only
++ determine MMIO and IO Port resource availability _after_ calling
++ pci_enable_device(). ]
++
++Generic flavors of pci_request_region() are request_mem_region()
++(for MMIO ranges) and request_region() (for IO Port ranges).
++Use these for address resources that are not described by "normal" PCI
++BARs.
++
++Also see pci_request_selected_regions() below.
++
++
++3.3 Set the DMA mask size
++~~~~~~~~~~~~~~~~~~~~~~~~~
++[ If anything below doesn't make sense, please refer to
++ Documentation/DMA-API.txt. This section is just a reminder that
++ drivers need to indicate DMA capabilities of the device and is not
++ an authoritative source for DMA interfaces. ]
++
++While all drivers should explicitly indicate the DMA capability
++(e.g. 32 or 64 bit) of the PCI bus master, devices with more than
++32-bit bus master capability for streaming data need the driver
++to "register" this capability by calling pci_set_dma_mask() with
++appropriate parameters. In general this allows more efficient DMA
++on systems where System RAM exists above 4G _physical_ address.
++
++Drivers for all PCI-X and PCIe compliant devices must call
++pci_set_dma_mask() as they are 64-bit DMA devices.
++
++Similarly, drivers must also "register" this capability if the device
++can directly address "consistent memory" in System RAM above 4G physical
++address by calling pci_set_consistent_dma_mask().
++Again, this includes drivers for all PCI-X and PCIe compliant devices.
++Many 64-bit "PCI" devices (before PCI-X) and some PCI-X devices are
++64-bit DMA capable for payload ("streaming") data but not control
++("consistent") data.
++
++
++3.4 Setup shared control data
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++Once the DMA masks are set, the driver can allocate "consistent" (a.k.a. shared)
++memory. See Documentation/DMA-API.txt for a full description of
++the DMA APIs. This section is just a reminder that it needs to be done
++before enabling DMA on the device.
++
++
++3.5 Initialize device registers
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++Some drivers will need specific "capability" fields programmed
++or other "vendor specific" register initialized or reset.
++E.g. clearing pending interrupts.
++
++
++3.6 Register IRQ handler
++~~~~~~~~~~~~~~~~~~~~~~~~
++While calling request_irq() is the last step described here,
++this is often just another intermediate step to initialize a device.
++This step can often be deferred until the device is opened for use.
++
++All interrupt handlers for IRQ lines should be registered with IRQF_SHARED
++and use the devid to map IRQs to devices (remember that all PCI IRQ lines
++can be shared).
++
++request_irq() will associate an interrupt handler and device handle
++with an interrupt number. Historically interrupt numbers represent
++IRQ lines which run from the PCI device to the Interrupt controller.
++With MSI and MSI-X (more below) the interrupt number is a CPU "vector".
++
++request_irq() also enables the interrupt. Make sure the device is
++quiesced and does not have any interrupts pending before registering
++the interrupt handler.
++
++MSI and MSI-X are PCI capabilities. Both are "Message Signaled Interrupts"
++which deliver interrupts to the CPU via a DMA write to a Local APIC.
++The fundamental difference between MSI and MSI-X is how multiple
++"vectors" get allocated. MSI requires contiguous blocks of vectors
++while MSI-X can allocate several individual ones.
++
++MSI capability can be enabled by calling pci_enable_msi() or
++pci_enable_msix() before calling request_irq(). This causes
++the PCI support to program CPU vector data into the PCI device
++capability registers.
++
++If your PCI device supports both, try to enable MSI-X first.
++Only one can be enabled at a time. Many architectures, chip-sets,
++or BIOSes do NOT support MSI or MSI-X and the call to pci_enable_msi/msix
++will fail. This is important to note since many drivers have
++two (or more) interrupt handlers: one for MSI/MSI-X and another for IRQs.
++They choose which handler to register with request_irq() based on the
++return value from pci_enable_msi/msix().
++
++There are (at least) two really good reasons for using MSI:
++1) MSI is an exclusive interrupt vector by definition.
++ This means the interrupt handler doesn't have to verify
++ its device caused the interrupt.
++
++2) MSI avoids DMA/IRQ race conditions. DMA to host memory is guaranteed
++ to be visible to the host CPU(s) when the MSI is delivered. This
++ is important for both data coherency and avoiding stale control data.
++ This guarantee allows the driver to omit MMIO reads to flush
++ the DMA stream.
++
++See drivers/infiniband/hw/mthca/ or drivers/net/tg3.c for examples
++of MSI/MSI-X usage.
++
++
++
++4. PCI device shutdown
++~~~~~~~~~~~~~~~~~~~~~~~
++
++When a PCI device driver is being unloaded, most of the following
++steps need to be performed:
++
++ Disable the device from generating IRQs
++ Release the IRQ (free_irq())
++ Stop all DMA activity
++ Release DMA buffers (both streaming and consistent)
++ Unregister from other subsystems (e.g. scsi or netdev)
++ Disable device from responding to MMIO/IO Port addresses
++ Release MMIO/IO Port resource(s)
++
++
++4.1 Stop IRQs on the device
++~~~~~~~~~~~~~~~~~~~~~~~~~~~
++How to do this is chip/device specific. If it's not done, it opens
++the possibility of a "screaming interrupt" if (and only if)
++the IRQ is shared with another device.
++
++When the shared IRQ handler is "unhooked", the remaining devices
++using the same IRQ line will still need the IRQ enabled. Thus if the
++"unhooked" device asserts IRQ line, the system will respond assuming
++it was one of the remaining devices asserted the IRQ line. Since none
++of the other devices will handle the IRQ, the system will "hang" until
++it decides the IRQ isn't going to get handled and masks the IRQ (100,000
++iterations later). Once the shared IRQ is masked, the remaining devices
++will stop functioning properly. Not a nice situation.
++
++This is another reason to use MSI or MSI-X if it's available.
++MSI and MSI-X are defined to be exclusive interrupts and thus
++are not susceptible to the "screaming interrupt" problem.
++
++
++4.2 Release the IRQ
++~~~~~~~~~~~~~~~~~~~
++Once the device is quiesced (no more IRQs), one can call free_irq().
++This function will return control once any pending IRQs are handled,
++"unhook" the drivers IRQ handler from that IRQ, and finally release
++the IRQ if no one else is using it.
++
++
++4.3 Stop all DMA activity
++~~~~~~~~~~~~~~~~~~~~~~~~~
++It's extremely important to stop all DMA operations BEFORE attempting
++to deallocate DMA control data. Failure to do so can result in memory
++corruption, hangs, and on some chip-sets a hard crash.
++
++Stopping DMA after stopping the IRQs can avoid races where the
++IRQ handler might restart DMA engines.
++
++While this step sounds obvious and trivial, several "mature" drivers
++didn't get this step right in the past.
++
++
++4.4 Release DMA buffers
++~~~~~~~~~~~~~~~~~~~~~~~
++Once DMA is stopped, clean up streaming DMA first.
++I.e. unmap data buffers and return buffers to "upstream"
++owners if there is one.
++
++Then clean up "consistent" buffers which contain the control data.
++
++See Documentation/DMA-API.txt for details on unmapping interfaces.
++
++
++4.5 Unregister from other subsystems
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++Most low level PCI device drivers support some other subsystem
++like USB, ALSA, SCSI, NetDev, Infiniband, etc. Make sure your
++driver isn't losing resources from that other subsystem.
++If this happens, typically the symptom is an Oops (panic) when
++the subsystem attempts to call into a driver that has been unloaded.
++
++
++4.6 Disable Device from responding to MMIO/IO Port addresses
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++io_unmap() MMIO or IO Port resources and then call pci_disable_device().
++This is the symmetric opposite of pci_enable_device().
++Do not access device registers after calling pci_disable_device().
++
++
++4.7 Release MMIO/IO Port Resource(s)
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++Call pci_release_region() to mark the MMIO or IO Port range as available.
++Failure to do so usually results in the inability to reload the driver.
++
++
++
++5. How to access PCI config space
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++You can use pci_(read|write)_config_(byte|word|dword) to access the config
++space of a device represented by struct pci_dev *. All these functions return 0
++when successful or an error code (PCIBIOS_...) which can be translated to a text
++string by pcibios_strerror. Most drivers expect that accesses to valid PCI
++devices don't fail.
++
++If you don't have a struct pci_dev available, you can call
++pci_bus_(read|write)_config_(byte|word|dword) to access a given device
++and function on that bus.
++
++If you access fields in the standard portion of the config header, please
++use symbolic names of locations and bits declared in <linux/pci.h>.
++
++If you need to access Extended PCI Capability registers, just call
++pci_find_capability() for the particular capability and it will find the
++corresponding register block for you.
++
++
++
++6. Other interesting functions
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++pci_find_slot() Find pci_dev corresponding to given bus and
++ slot numbers.
++pci_set_power_state() Set PCI Power Management state (0=D0 ... 3=D3)
++pci_find_capability() Find specified capability in device's capability
++ list.
++pci_resource_start() Returns bus start address for a given PCI region
++pci_resource_end() Returns bus end address for a given PCI region
++pci_resource_len() Returns the byte length of a PCI region
++pci_set_drvdata() Set private driver data pointer for a pci_dev
++pci_get_drvdata() Return private driver data pointer for a pci_dev
++pci_set_mwi() Enable Memory-Write-Invalidate transactions.
++pci_clear_mwi() Disable Memory-Write-Invalidate transactions.
++
++
++
++7. Miscellaneous hints
++~~~~~~~~~~~~~~~~~~~~~~
++
++When displaying PCI device names to the user (for example when a driver wants
++to tell the user what card has it found), please use pci_name(pci_dev).
++
++Always refer to the PCI devices by a pointer to the pci_dev structure.
++All PCI layer functions use this identification and it's the only
++reasonable one. Don't use bus/slot/function numbers except for very
++special purposes -- on systems with multiple primary buses their semantics
++can be pretty complex.
++
++Don't try to turn on Fast Back to Back writes in your driver. All devices
++on the bus need to be capable of doing it, so this is something which needs
++to be handled by platform and generic code, not individual drivers.
++
++
++
++8. Vendor and device identifications
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++One is not not required to add new device ids to include/linux/pci_ids.h.
++Please add PCI_VENDOR_ID_xxx for vendors and a hex constant for device ids.
++
++PCI_VENDOR_ID_xxx constants are re-used. The device ids are arbitrary
++hex numbers (vendor controlled) and normally used only in a single
++location, the pci_device_id table.
++
++Please DO submit new vendor/device ids to pciids.sourceforge.net project.
++
++
++
++9. Obsolete functions
++~~~~~~~~~~~~~~~~~~~~~
++
++There are several functions which you might come across when trying to
++port an old driver to the new PCI interface. They are no longer present
++in the kernel as they aren't compatible with hotplug or PCI domains or
++having sane locking.
++
++pci_find_device() Superseded by pci_get_device()
++pci_find_subsys() Superseded by pci_get_subsys()
++pci_find_slot() Superseded by pci_get_slot()
++
++
++The alternative is the traditional PCI device driver that walks PCI
++device lists. This is still possible but discouraged.
++
++
++
++10. MMIO Space and "Write Posting"
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++Converting a driver from using I/O Port space to using MMIO space
++often requires some additional changes. Specifically, "write posting"
++needs to be handled. Many drivers (e.g. tg3, acenic, sym53c8xx_2)
++already do this. I/O Port space guarantees write transactions reach the PCI
++device before the CPU can continue. Writes to MMIO space allow the CPU
++to continue before the transaction reaches the PCI device. HW weenies
++call this "Write Posting" because the write completion is "posted" to
++the CPU before the transaction has reached its destination.
++
++Thus, timing sensitive code should add readl() where the CPU is
++expected to wait before doing other work. The classic "bit banging"
++sequence works fine for I/O Port space:
++
++ for (i = 8; --i; val >>= 1) {
++ outb(val & 1, ioport_reg); /* write bit */
++ udelay(10);
++ }
++
++The same sequence for MMIO space should be:
++
++ for (i = 8; --i; val >>= 1) {
++ writeb(val & 1, mmio_reg); /* write bit */
++ readb(safe_mmio_reg); /* flush posted write */
++ udelay(10);
++ }
++
++It is important that "safe_mmio_reg" not have any side effects that
++interferes with the correct operation of the device.
++
++Another case to watch out for is when resetting a PCI device. Use PCI
++Configuration space reads to flush the writel(). This will gracefully
++handle the PCI master abort on all platforms if the PCI device is
++expected to not respond to a readl(). Most x86 platforms will allow
++MMIO reads to master abort (a.k.a. "Soft Fail") and return garbage
++(e.g. ~0). But many RISC platforms will crash (a.k.a."Hard Fail").
++
+diff --git a/Documentation/PCI/pcieaer-howto.txt b/Documentation/PCI/pcieaer-howto.txt
+new file mode 100644
+index 0000000..16c2512
+--- /dev/null
++++ b/Documentation/PCI/pcieaer-howto.txt
+@@ -0,0 +1,253 @@
++ The PCI Express Advanced Error Reporting Driver Guide HOWTO
++ T. Long Nguyen <tom.l.nguyen at intel.com>
++ Yanmin Zhang <yanmin.zhang at intel.com>
++ 07/29/2006
++
++
++1. Overview
++
++1.1 About this guide
++
++This guide describes the basics of the PCI Express Advanced Error
++Reporting (AER) driver and provides information on how to use it, as
++well as how to enable the drivers of endpoint devices to conform with
++PCI Express AER driver.
++
++1.2 Copyright © Intel Corporation 2006.
++
++1.3 What is the PCI Express AER Driver?
++
++PCI Express error signaling can occur on the PCI Express link itself
++or on behalf of transactions initiated on the link. PCI Express
++defines two error reporting paradigms: the baseline capability and
++the Advanced Error Reporting capability. The baseline capability is
++required of all PCI Express components providing a minimum defined
++set of error reporting requirements. Advanced Error Reporting
++capability is implemented with a PCI Express advanced error reporting
++extended capability structure providing more robust error reporting.
++
++The PCI Express AER driver provides the infrastructure to support PCI
++Express Advanced Error Reporting capability. The PCI Express AER
++driver provides three basic functions:
++
++- Gathers the comprehensive error information if errors occurred.
++- Reports error to the users.
++- Performs error recovery actions.
++
++AER driver only attaches root ports which support PCI-Express AER
++capability.
++
++
++2. User Guide
++
++2.1 Include the PCI Express AER Root Driver into the Linux Kernel
++
++The PCI Express AER Root driver is a Root Port service driver attached
++to the PCI Express Port Bus driver. If a user wants to use it, the driver
++has to be compiled. Option CONFIG_PCIEAER supports this capability. It
++depends on CONFIG_PCIEPORTBUS, so pls. set CONFIG_PCIEPORTBUS=y and
++CONFIG_PCIEAER = y.
++
++2.2 Load PCI Express AER Root Driver
++There is a case where a system has AER support in BIOS. Enabling the AER
++Root driver and having AER support in BIOS may result unpredictable
++behavior. To avoid this conflict, a successful load of the AER Root driver
++requires ACPI _OSC support in the BIOS to allow the AER Root driver to
++request for native control of AER. See the PCI FW 3.0 Specification for
++details regarding OSC usage. Currently, lots of firmwares don't provide
++_OSC support while they use PCI Express. To support such firmwares,
++forceload, a parameter of type bool, could enable AER to continue to
++be initiated although firmwares have no _OSC support. To enable the
++walkaround, pls. add aerdriver.forceload=y to kernel boot parameter line
++when booting kernel. Note that forceload=n by default.
++
++2.3 AER error output
++When a PCI-E AER error is captured, an error message will be outputed to
++console. If it's a correctable error, it is outputed as a warning.
++Otherwise, it is printed as an error. So users could choose different
++log level to filter out correctable error messages.
++
++Below shows an example.
+++------ PCI-Express Device Error -----+
++Error Severity : Uncorrected (Fatal)
++PCIE Bus Error type : Transaction Layer
++Unsupported Request : First
++Requester ID : 0500
++VendorID=8086h, DeviceID=0329h, Bus=05h, Device=00h, Function=00h
++TLB Header:
++04000001 00200a03 05010000 00050100
++
++In the example, 'Requester ID' means the ID of the device who sends
++the error message to root port. Pls. refer to pci express specs for
++other fields.
++
++
++3. Developer Guide
++
++To enable AER aware support requires a software driver to configure
++the AER capability structure within its device and to provide callbacks.
++
++To support AER better, developers need understand how AER does work
++firstly.
++
++PCI Express errors are classified into two types: correctable errors
++and uncorrectable errors. This classification is based on the impacts
++of those errors, which may result in degraded performance or function
++failure.
++
++Correctable errors pose no impacts on the functionality of the
++interface. The PCI Express protocol can recover without any software
++intervention or any loss of data. These errors are detected and
++corrected by hardware. Unlike correctable errors, uncorrectable
++errors impact functionality of the interface. Uncorrectable errors
++can cause a particular transaction or a particular PCI Express link
++to be unreliable. Depending on those error conditions, uncorrectable
++errors are further classified into non-fatal errors and fatal errors.
++Non-fatal errors cause the particular transaction to be unreliable,
++but the PCI Express link itself is fully functional. Fatal errors, on
++the other hand, cause the link to be unreliable.
++
++When AER is enabled, a PCI Express device will automatically send an
++error message to the PCIE root port above it when the device captures
++an error. The Root Port, upon receiving an error reporting message,
++internally processes and logs the error message in its PCI Express
++capability structure. Error information being logged includes storing
++the error reporting agent's requestor ID into the Error Source
++Identification Registers and setting the error bits of the Root Error
++Status Register accordingly. If AER error reporting is enabled in Root
++Error Command Register, the Root Port generates an interrupt if an
++error is detected.
++
++Note that the errors as described above are related to the PCI Express
++hierarchy and links. These errors do not include any device specific
++errors because device specific errors will still get sent directly to
++the device driver.
++
++3.1 Configure the AER capability structure
++
++AER aware drivers of PCI Express component need change the device
++control registers to enable AER. They also could change AER registers,
++including mask and severity registers. Helper function
++pci_enable_pcie_error_reporting could be used to enable AER. See
++section 3.3.
++
++3.2. Provide callbacks
++
++3.2.1 callback reset_link to reset pci express link
++
++This callback is used to reset the pci express physical link when a
++fatal error happens. The root port aer service driver provides a
++default reset_link function, but different upstream ports might
++have different specifications to reset pci express link, so all
++upstream ports should provide their own reset_link functions.
++
++In struct pcie_port_service_driver, a new pointer, reset_link, is
++added.
++
++pci_ers_result_t (*reset_link) (struct pci_dev *dev);
++
++Section 3.2.2.2 provides more detailed info on when to call
++reset_link.
++
++3.2.2 PCI error-recovery callbacks
++
++The PCI Express AER Root driver uses error callbacks to coordinate
++with downstream device drivers associated with a hierarchy in question
++when performing error recovery actions.
++
++Data struct pci_driver has a pointer, err_handler, to point to
++pci_error_handlers who consists of a couple of callback function
++pointers. AER driver follows the rules defined in
++pci-error-recovery.txt except pci express specific parts (e.g.
++reset_link). Pls. refer to pci-error-recovery.txt for detailed
++definitions of the callbacks.
++
++Below sections specify when to call the error callback functions.
++
++3.2.2.1 Correctable errors
++
++Correctable errors pose no impacts on the functionality of
++the interface. The PCI Express protocol can recover without any
++software intervention or any loss of data. These errors do not
++require any recovery actions. The AER driver clears the device's
++correctable error status register accordingly and logs these errors.
++
++3.2.2.2 Non-correctable (non-fatal and fatal) errors
++
++If an error message indicates a non-fatal error, performing link reset
++at upstream is not required. The AER driver calls error_detected(dev,
++pci_channel_io_normal) to all drivers associated within a hierarchy in
++question. for example,
++EndPoint<==>DownstreamPort B<==>UpstreamPort A<==>RootPort.
++If Upstream port A captures an AER error, the hierarchy consists of
++Downstream port B and EndPoint.
++
++A driver may return PCI_ERS_RESULT_CAN_RECOVER,
++PCI_ERS_RESULT_DISCONNECT, or PCI_ERS_RESULT_NEED_RESET, depending on
++whether it can recover or the AER driver calls mmio_enabled as next.
++
++If an error message indicates a fatal error, kernel will broadcast
++error_detected(dev, pci_channel_io_frozen) to all drivers within
++a hierarchy in question. Then, performing link reset at upstream is
++necessary. As different kinds of devices might use different approaches
++to reset link, AER port service driver is required to provide the
++function to reset link. Firstly, kernel looks for if the upstream
++component has an aer driver. If it has, kernel uses the reset_link
++callback of the aer driver. If the upstream component has no aer driver
++and the port is downstream port, we will use the aer driver of the
++root port who reports the AER error. As for upstream ports,
++they should provide their own aer service drivers with reset_link
++function. If error_detected returns PCI_ERS_RESULT_CAN_RECOVER and
++reset_link returns PCI_ERS_RESULT_RECOVERED, the error handling goes
++to mmio_enabled.
++
++3.3 helper functions
++
++3.3.1 int pci_find_aer_capability(struct pci_dev *dev);
++pci_find_aer_capability locates the PCI Express AER capability
++in the device configuration space. If the device doesn't support
++PCI-Express AER, the function returns 0.
++
++3.3.2 int pci_enable_pcie_error_reporting(struct pci_dev *dev);
++pci_enable_pcie_error_reporting enables the device to send error
++messages to root port when an error is detected. Note that devices
++don't enable the error reporting by default, so device drivers need
++call this function to enable it.
++
++3.3.3 int pci_disable_pcie_error_reporting(struct pci_dev *dev);
++pci_disable_pcie_error_reporting disables the device to send error
++messages to root port when an error is detected.
++
++3.3.4 int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev);
++pci_cleanup_aer_uncorrect_error_status cleanups the uncorrectable
++error status register.
++
++3.4 Frequent Asked Questions
++
++Q: What happens if a PCI Express device driver does not provide an
++error recovery handler (pci_driver->err_handler is equal to NULL)?
++
++A: The devices attached with the driver won't be recovered. If the
++error is fatal, kernel will print out warning messages. Please refer
++to section 3 for more information.
++
++Q: What happens if an upstream port service driver does not provide
++callback reset_link?
++
++A: Fatal error recovery will fail if the errors are reported by the
++upstream ports who are attached by the service driver.
++
++Q: How does this infrastructure deal with driver that is not PCI
++Express aware?
++
++A: This infrastructure calls the error callback functions of the
++driver when an error happens. But if the driver is not aware of
++PCI Express, the device might not report its own errors to root
++port.
++
++Q: What modifications will that driver need to make it compatible
++with the PCI Express AER Root driver?
++
++A: It could call the helper functions to enable AER in devices and
++cleanup uncorrectable status register. Pls. refer to section 3.3.
++
+diff --git a/Documentation/PCIEBUS-HOWTO.txt b/Documentation/PCIEBUS-HOWTO.txt
+deleted file mode 100644
+index c93f42a..0000000
+--- a/Documentation/PCIEBUS-HOWTO.txt
++++ /dev/null
+@@ -1,217 +0,0 @@
+- The PCI Express Port Bus Driver Guide HOWTO
+- Tom L Nguyen tom.l.nguyen at intel.com
+- 11/03/2004
+-
+-1. About this guide
+-
+-This guide describes the basics of the PCI Express Port Bus driver
+-and provides information on how to enable the service drivers to
+-register/unregister with the PCI Express Port Bus Driver.
+-
+-2. Copyright 2004 Intel Corporation
+-
+-3. What is the PCI Express Port Bus Driver
+-
+-A PCI Express Port is a logical PCI-PCI Bridge structure. There
+-are two types of PCI Express Port: the Root Port and the Switch
+-Port. The Root Port originates a PCI Express link from a PCI Express
+-Root Complex and the Switch Port connects PCI Express links to
+-internal logical PCI buses. The Switch Port, which has its secondary
+-bus representing the switch's internal routing logic, is called the
+-switch's Upstream Port. The switch's Downstream Port is bridging from
+-switch's internal routing bus to a bus representing the downstream
+-PCI Express link from the PCI Express Switch.
+-
+-A PCI Express Port can provide up to four distinct functions,
+-referred to in this document as services, depending on its port type.
+-PCI Express Port's services include native hotplug support (HP),
+-power management event support (PME), advanced error reporting
+-support (AER), and virtual channel support (VC). These services may
+-be handled by a single complex driver or be individually distributed
+-and handled by corresponding service drivers.
+-
+-4. Why use the PCI Express Port Bus Driver?
+-
+-In existing Linux kernels, the Linux Device Driver Model allows a
+-physical device to be handled by only a single driver. The PCI
+-Express Port is a PCI-PCI Bridge device with multiple distinct
+-services. To maintain a clean and simple solution each service
+-may have its own software service driver. In this case several
+-service drivers will compete for a single PCI-PCI Bridge device.
+-For example, if the PCI Express Root Port native hotplug service
+-driver is loaded first, it claims a PCI-PCI Bridge Root Port. The
+-kernel therefore does not load other service drivers for that Root
+-Port. In other words, it is impossible to have multiple service
+-drivers load and run on a PCI-PCI Bridge device simultaneously
+-using the current driver model.
+-
+-To enable multiple service drivers running simultaneously requires
+-having a PCI Express Port Bus driver, which manages all populated
+-PCI Express Ports and distributes all provided service requests
+-to the corresponding service drivers as required. Some key
+-advantages of using the PCI Express Port Bus driver are listed below:
+-
+- - Allow multiple service drivers to run simultaneously on
+- a PCI-PCI Bridge Port device.
+-
+- - Allow service drivers implemented in an independent
+- staged approach.
+-
+- - Allow one service driver to run on multiple PCI-PCI Bridge
+- Port devices.
+-
+- - Manage and distribute resources of a PCI-PCI Bridge Port
+- device to requested service drivers.
+-
+-5. Configuring the PCI Express Port Bus Driver vs. Service Drivers
+-
+-5.1 Including the PCI Express Port Bus Driver Support into the Kernel
+-
+-Including the PCI Express Port Bus driver depends on whether the PCI
+-Express support is included in the kernel config. The kernel will
+-automatically include the PCI Express Port Bus driver as a kernel
+-driver when the PCI Express support is enabled in the kernel.
+-
+-5.2 Enabling Service Driver Support
+-
+-PCI device drivers are implemented based on Linux Device Driver Model.
+-All service drivers are PCI device drivers. As discussed above, it is
+-impossible to load any service driver once the kernel has loaded the
+-PCI Express Port Bus Driver. To meet the PCI Express Port Bus Driver
+-Model requires some minimal changes on existing service drivers that
+-imposes no impact on the functionality of existing service drivers.
+-
+-A service driver is required to use the two APIs shown below to
+-register its service with the PCI Express Port Bus driver (see
+-section 5.2.1 & 5.2.2). It is important that a service driver
+-initializes the pcie_port_service_driver data structure, included in
+-header file /include/linux/pcieport_if.h, before calling these APIs.
+-Failure to do so will result an identity mismatch, which prevents
+-the PCI Express Port Bus driver from loading a service driver.
+-
+-5.2.1 pcie_port_service_register
+-
+-int pcie_port_service_register(struct pcie_port_service_driver *new)
+-
+-This API replaces the Linux Driver Model's pci_module_init API. A
+-service driver should always calls pcie_port_service_register at
+-module init. Note that after service driver being loaded, calls
+-such as pci_enable_device(dev) and pci_set_master(dev) are no longer
+-necessary since these calls are executed by the PCI Port Bus driver.
+-
+-5.2.2 pcie_port_service_unregister
+-
+-void pcie_port_service_unregister(struct pcie_port_service_driver *new)
+-
+-pcie_port_service_unregister replaces the Linux Driver Model's
+-pci_unregister_driver. It's always called by service driver when a
+-module exits.
+-
+-5.2.3 Sample Code
+-
+-Below is sample service driver code to initialize the port service
+-driver data structure.
+-
+-static struct pcie_port_service_id service_id[] = { {
+- .vendor = PCI_ANY_ID,
+- .device = PCI_ANY_ID,
+- .port_type = PCIE_RC_PORT,
+- .service_type = PCIE_PORT_SERVICE_AER,
+- }, { /* end: all zeroes */ }
+-};
+-
+-static struct pcie_port_service_driver root_aerdrv = {
+- .name = (char *)device_name,
+- .id_table = &service_id[0],
+-
+- .probe = aerdrv_load,
+- .remove = aerdrv_unload,
+-
+- .suspend = aerdrv_suspend,
+- .resume = aerdrv_resume,
+-};
+-
+-Below is a sample code for registering/unregistering a service
+-driver.
+-
+-static int __init aerdrv_service_init(void)
+-{
+- int retval = 0;
+-
+- retval = pcie_port_service_register(&root_aerdrv);
+- if (!retval) {
+- /*
+- * FIX ME
+- */
+- }
+- return retval;
+-}
+-
+-static void __exit aerdrv_service_exit(void)
+-{
+- pcie_port_service_unregister(&root_aerdrv);
+-}
+-
+-module_init(aerdrv_service_init);
+-module_exit(aerdrv_service_exit);
+-
+-6. Possible Resource Conflicts
+-
+-Since all service drivers of a PCI-PCI Bridge Port device are
+-allowed to run simultaneously, below lists a few of possible resource
+-conflicts with proposed solutions.
+-
+-6.1 MSI Vector Resource
+-
+-The MSI capability structure enables a device software driver to call
+-pci_enable_msi to request MSI based interrupts. Once MSI interrupts
+-are enabled on a device, it stays in this mode until a device driver
+-calls pci_disable_msi to disable MSI interrupts and revert back to
+-INTx emulation mode. Since service drivers of the same PCI-PCI Bridge
+-port share the same physical device, if an individual service driver
+-calls pci_enable_msi/pci_disable_msi it may result unpredictable
+-behavior. For example, two service drivers run simultaneously on the
+-same physical Root Port. Both service drivers call pci_enable_msi to
+-request MSI based interrupts. A service driver may not know whether
+-any other service drivers have run on this Root Port. If either one
+-of them calls pci_disable_msi, it puts the other service driver
+-in a wrong interrupt mode.
+-
+-To avoid this situation all service drivers are not permitted to
+-switch interrupt mode on its device. The PCI Express Port Bus driver
+-is responsible for determining the interrupt mode and this should be
+-transparent to service drivers. Service drivers need to know only
+-the vector IRQ assigned to the field irq of struct pcie_device, which
+-is passed in when the PCI Express Port Bus driver probes each service
+-driver. Service drivers should use (struct pcie_device*)dev->irq to
+-call request_irq/free_irq. In addition, the interrupt mode is stored
+-in the field interrupt_mode of struct pcie_device.
+-
+-6.2 MSI-X Vector Resources
+-
+-Similar to the MSI a device driver for an MSI-X capable device can
+-call pci_enable_msix to request MSI-X interrupts. All service drivers
+-are not permitted to switch interrupt mode on its device. The PCI
+-Express Port Bus driver is responsible for determining the interrupt
+-mode and this should be transparent to service drivers. Any attempt
+-by service driver to call pci_enable_msix/pci_disable_msix may
+-result unpredictable behavior. Service drivers should use
+-(struct pcie_device*)dev->irq and call request_irq/free_irq.
+-
+-6.3 PCI Memory/IO Mapped Regions
+-
+-Service drivers for PCI Express Power Management (PME), Advanced
+-Error Reporting (AER), Hot-Plug (HP) and Virtual Channel (VC) access
+-PCI configuration space on the PCI Express port. In all cases the
+-registers accessed are independent of each other. This patch assumes
+-that all service drivers will be well behaved and not overwrite
+-other service driver's configuration settings.
+-
+-6.4 PCI Config Registers
+-
+-Each service driver runs its PCI config operations on its own
+-capability structure except the PCI Express capability structure, in
+-which Root Control register and Device Control register are shared
+-between PME and AER. This patch assumes that all service drivers
+-will be well behaved and not overwrite other service driver's
+-configuration settings.
+diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
+index 1fc4e71..9c93a03 100644
+--- a/Documentation/SubmittingPatches
++++ b/Documentation/SubmittingPatches
+@@ -183,7 +183,7 @@ Even if the maintainer did not respond in step #4, make sure to ALWAYS
+ copy the maintainer when you change their code.
+
+ For small patches you may want to CC the Trivial Patch Monkey
+-trivial at kernel.org managed by Adrian Bunk; which collects "trivial"
++trivial at kernel.org managed by Jesper Juhl; which collects "trivial"
+ patches. Trivial patches must qualify for one of the following rules:
+ Spelling fixes in documentation
+ Spelling fixes which could break grep(1)
+@@ -196,7 +196,7 @@ patches. Trivial patches must qualify for one of the following rules:
+ since people copy, as long as it's trivial)
+ Any fix by the author/maintainer of the file (ie. patch monkey
+ in re-transmission mode)
+-URL: <http://www.kernel.org/pub/linux/kernel/people/bunk/trivial/>
++URL: <http://www.kernel.org/pub/linux/kernel/people/juhl/trivial/>
+
+
+
+diff --git a/Documentation/arm/Samsung-S3C24XX/NAND.txt b/Documentation/arm/Samsung-S3C24XX/NAND.txt
+new file mode 100644
+index 0000000..bc478a3
+--- /dev/null
++++ b/Documentation/arm/Samsung-S3C24XX/NAND.txt
+@@ -0,0 +1,30 @@
++ S3C24XX NAND Support
++ ====================
++
++Introduction
++------------
++
++Small Page NAND
++---------------
++
++The driver uses a 512 byte (1 page) ECC code for this setup. The
++ECC code is not directly compatible with the default kernel ECC
++code, so the driver enforces its own OOB layout and ECC parameters
++
++Large Page NAND
++---------------
++
++The driver is capable of handling NAND flash with a 2KiB page
++size, with support for hardware ECC generation and correction.
++
++Unlike the 512byte page mode, the driver generates ECC data for
++each 256 byte block in an 2KiB page. This means that more than
++one error in a page can be rectified. It also means that the
++OOB layout remains the default kernel layout for these flashes.
++
++
++Document Author
++---------------
++
++Ben Dooks, Copyright 2007 Simtec Electronics
++
+diff --git a/Documentation/arm/Samsung-S3C24XX/Overview.txt b/Documentation/arm/Samsung-S3C24XX/Overview.txt
+index c31b76f..d04e1e3 100644
+--- a/Documentation/arm/Samsung-S3C24XX/Overview.txt
++++ b/Documentation/arm/Samsung-S3C24XX/Overview.txt
+@@ -156,6 +156,8 @@ NAND
+ controller. If there are any problems the latest linux-mtd
+ code can be found from http://www.linux-mtd.infradead.org/
+
++ For more information see Documentation/arm/Samsung-S3C24XX/NAND.txt
++
+
+ Serial
+ ------
+diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt
+index 93f223b..4dbb8be 100644
+--- a/Documentation/block/biodoc.txt
++++ b/Documentation/block/biodoc.txt
+@@ -1097,7 +1097,7 @@ lock themselves, if required. Drivers that explicitly used the
+ io_request_lock for serialization need to be modified accordingly.
+ Usually it's as easy as adding a global lock:
+
+- static spinlock_t my_driver_lock = SPIN_LOCK_UNLOCKED;
++ static DEFINE_SPINLOCK(my_driver_lock);
+
+ and passing the address to that lock to blk_init_queue().
+
+diff --git a/Documentation/cdrom/cdrom-standard.tex b/Documentation/cdrom/cdrom-standard.tex
+index c713aeb..c06233f 100644
+--- a/Documentation/cdrom/cdrom-standard.tex
++++ b/Documentation/cdrom/cdrom-standard.tex
+@@ -777,7 +777,7 @@ Note that a driver must have one static structure, $<device>_dops$, while
+ it may have as many structures $<device>_info$ as there are minor devices
+ active. $Register_cdrom()$ builds a linked list from these.
+
+-\subsection{$Int\ unregister_cdrom(struct\ cdrom_device_info * cdi)$}
++\subsection{$Void\ unregister_cdrom(struct\ cdrom_device_info * cdi)$}
+
+ Unregistering device $cdi$ with minor number $MINOR(cdi\to dev)$ removes
+ the minor device from the list. If it was the last registered minor for
+diff --git a/Documentation/cli-sti-removal.txt b/Documentation/cli-sti-removal.txt
+index 0223c9d..60932b0 100644
+--- a/Documentation/cli-sti-removal.txt
++++ b/Documentation/cli-sti-removal.txt
+@@ -43,7 +43,7 @@ would execute while the cli()-ed section is executing.
+
+ but from now on a more direct method of locking has to be used:
+
+- spinlock_t driver_lock = SPIN_LOCK_UNLOCKED;
++ DEFINE_SPINLOCK(driver_lock);
+ struct driver_data;
+
+ irq_handler (...)
+diff --git a/Documentation/cpusets.txt b/Documentation/cpusets.txt
+index ad2bb3b..aa854b9 100644
+--- a/Documentation/cpusets.txt
++++ b/Documentation/cpusets.txt
+@@ -8,6 +8,7 @@ Portions Copyright (c) 2004-2006 Silicon Graphics, Inc.
+ Modified by Paul Jackson <pj at sgi.com>
+ Modified by Christoph Lameter <clameter at sgi.com>
+ Modified by Paul Menage <menage at google.com>
++Modified by Hidetoshi Seto <seto.hidetoshi at jp.fujitsu.com>
+
+ CONTENTS:
+ =========
+@@ -20,7 +21,8 @@ CONTENTS:
+ 1.5 What is memory_pressure ?
+ 1.6 What is memory spread ?
+ 1.7 What is sched_load_balance ?
+- 1.8 How do I use cpusets ?
++ 1.8 What is sched_relax_domain_level ?
++ 1.9 How do I use cpusets ?
+ 2. Usage Examples and Syntax
+ 2.1 Basic Usage
+ 2.2 Adding/removing cpus
+@@ -497,7 +499,73 @@ the cpuset code to update these sched domains, it compares the new
+ partition requested with the current, and updates its sched domains,
+ removing the old and adding the new, for each change.
+
+-1.8 How do I use cpusets ?
++
++1.8 What is sched_relax_domain_level ?
++--------------------------------------
++
++In sched domain, the scheduler migrates tasks in 2 ways; periodic load
++balance on tick, and at time of some schedule events.
++
++When a task is woken up, scheduler try to move the task on idle CPU.
++For example, if a task A running on CPU X activates another task B
++on the same CPU X, and if CPU Y is X's sibling and performing idle,
++then scheduler migrate task B to CPU Y so that task B can start on
++CPU Y without waiting task A on CPU X.
++
++And if a CPU run out of tasks in its runqueue, the CPU try to pull
++extra tasks from other busy CPUs to help them before it is going to
++be idle.
++
++Of course it takes some searching cost to find movable tasks and/or
++idle CPUs, the scheduler might not search all CPUs in the domain
++everytime. In fact, in some architectures, the searching ranges on
++events are limited in the same socket or node where the CPU locates,
++while the load balance on tick searchs all.
++
++For example, assume CPU Z is relatively far from CPU X. Even if CPU Z
++is idle while CPU X and the siblings are busy, scheduler can't migrate
++woken task B from X to Z since it is out of its searching range.
++As the result, task B on CPU X need to wait task A or wait load balance
++on the next tick. For some applications in special situation, waiting
++1 tick may be too long.
++
++The 'sched_relax_domain_level' file allows you to request changing
++this searching range as you like. This file takes int value which
++indicates size of searching range in levels ideally as follows,
++otherwise initial value -1 that indicates the cpuset has no request.
++
++ -1 : no request. use system default or follow request of others.
++ 0 : no search.
++ 1 : search siblings (hyperthreads in a core).
++ 2 : search cores in a package.
++ 3 : search cpus in a node [= system wide on non-NUMA system]
++ ( 4 : search nodes in a chunk of node [on NUMA system] )
++ ( 5~ : search system wide [on NUMA system])
++
++This file is per-cpuset and affect the sched domain where the cpuset
++belongs to. Therefore if the flag 'sched_load_balance' of a cpuset
++is disabled, then 'sched_relax_domain_level' have no effect since
++there is no sched domain belonging the cpuset.
++
++If multiple cpusets are overlapping and hence they form a single sched
++domain, the largest value among those is used. Be careful, if one
++requests 0 and others are -1 then 0 is used.
++
++Note that modifying this file will have both good and bad effects,
++and whether it is acceptable or not will be depend on your situation.
++Don't modify this file if you are not sure.
++
++If your situation is:
++ - The migration costs between each cpu can be assumed considerably
++ small(for you) due to your special application's behavior or
++ special hardware support for CPU cache etc.
++ - The searching cost doesn't have impact(for you) or you can make
++ the searching cost enough small by managing cpuset to compact etc.
++ - The latency is required even it sacrifices cache hit rate etc.
++then increasing 'sched_relax_domain_level' would benefit you.
++
++
++1.9 How do I use cpusets ?
+ --------------------------
+
+ In order to minimize the impact of cpusets on critical kernel
+diff --git a/Documentation/debugging-via-ohci1394.txt b/Documentation/debugging-via-ohci1394.txt
+index c360d4e..59a91e5 100644
+--- a/Documentation/debugging-via-ohci1394.txt
++++ b/Documentation/debugging-via-ohci1394.txt
+@@ -41,15 +41,19 @@ to a working state and enables physical DMA by default for all remote nodes.
+ This can be turned off by ohci1394's module parameter phys_dma=0.
+
+ The alternative firewire-ohci driver in drivers/firewire uses filtered physical
+-DMA, hence is not yet suitable for remote debugging.
++DMA by default, which is more secure but not suitable for remote debugging.
++Compile the driver with CONFIG_FIREWIRE_OHCI_REMOTE_DMA (Kernel hacking menu:
++Remote debugging over FireWire with firewire-ohci) to get unfiltered physical
++DMA.
+
+-Because ohci1394 depends on the PCI enumeration to be completed, an
+-initialization routine which runs pretty early (long before console_init()
+-which makes the printk buffer appear on the console can be called) was written.
++Because ohci1394 and firewire-ohci depend on the PCI enumeration to be
++completed, an initialization routine which runs pretty early has been
++implemented for x86. This routine runs long before console_init() can be
++called, i.e. before the printk buffer appears on the console.
+
+ To activate it, enable CONFIG_PROVIDE_OHCI1394_DMA_INIT (Kernel hacking menu:
+-Provide code for enabling DMA over FireWire early on boot) and pass the
+-parameter "ohci1394_dma=early" to the recompiled kernel on boot.
++Remote debugging over FireWire early on boot) and pass the parameter
++"ohci1394_dma=early" to the recompiled kernel on boot.
+
+ Tools
+ -----
+diff --git a/Documentation/device-mapper/dm-crypt.txt b/Documentation/device-mapper/dm-crypt.txt
+new file mode 100644
+index 0000000..6680cab
+--- /dev/null
++++ b/Documentation/device-mapper/dm-crypt.txt
+@@ -0,0 +1,52 @@
++dm-crypt
++=========
++
++Device-Mapper's "crypt" target provides transparent encryption of block devices
++using the kernel crypto API.
++
++Parameters: <cipher> <key> <iv_offset> <device path> <offset>
++
++<cipher>
++ Encryption cipher and an optional IV generation mode.
++ (In format cipher-chainmode-ivopts:ivmode).
++ Examples:
++ des
++ aes-cbc-essiv:sha256
++ twofish-ecb
++
++ /proc/crypto contains supported crypto modes
++
++<key>
++ Key used for encryption. It is encoded as a hexadecimal number.
++ You can only use key sizes that are valid for the selected cipher.
++
++<iv_offset>
++ The IV offset is a sector count that is added to the sector number
++ before creating the IV.
++
++<device path>
++ This is the device that is going to be used as backend and contains the
++ encrypted data. You can specify it as a path like /dev/xxx or a device
++ number <major>:<minor>.
++
++<offset>
++ Starting sector within the device where the encrypted data begins.
++
++Example scripts
++===============
++LUKS (Linux Unified Key Setup) is now the preferred way to set up disk
++encryption with dm-crypt using the 'cryptsetup' utility, see
++http://luks.endorphin.org/
++
++[[
++#!/bin/sh
++# Create a crypt device using dmsetup
++dmsetup create crypt1 --table "0 `blockdev --getsize $1` crypt aes-cbc-essiv:sha256 babebabebabebabebabebabebabebabe 0 $1 0"
++]]
++
++[[
++#!/bin/sh
++# Create a crypt device using cryptsetup and LUKS header with default cipher
++cryptsetup luksFormat $1
++cryptsetup luksOpen $1 crypt1
++]]
+diff --git a/Documentation/dontdiff b/Documentation/dontdiff
+index c09a96b..354aec0 100644
+--- a/Documentation/dontdiff
++++ b/Documentation/dontdiff
+@@ -47,7 +47,6 @@
+ .mm
+ 53c700_d.h
+ 53c8xx_d.h*
+-BitKeeper
+ COPYING
+ CREDITS
+ CVS
+diff --git a/Documentation/early-userspace/README b/Documentation/early-userspace/README
+index 766d320..e35d830 100644
+--- a/Documentation/early-userspace/README
++++ b/Documentation/early-userspace/README
+@@ -89,8 +89,8 @@ the 2.7 era (it missed the boat for 2.5).
+ You can obtain somewhat infrequent snapshots of klibc from
+ ftp://ftp.kernel.org/pub/linux/libs/klibc/
+
+-For active users, you are better off using the klibc BitKeeper
+-repositories, at http://klibc.bkbits.net/
++For active users, you are better off using the klibc git
++repository, at http://git.kernel.org/?p=libs/klibc/klibc.git
+
+ The standalone klibc distribution currently provides three components,
+ in addition to the klibc library:
+diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
+index bf0e3df..448729f 100644
+--- a/Documentation/feature-removal-schedule.txt
++++ b/Documentation/feature-removal-schedule.txt
+@@ -203,16 +203,8 @@ Who: linuxppc-dev at ozlabs.org
+
+ ---------------------------
+
+-What: sk98lin network driver
+-When: Feburary 2008
+-Why: In kernel tree version of driver is unmaintained. Sk98lin driver
+- replaced by the skge driver.
+-Who: Stephen Hemminger <shemminger at linux-foundation.org>
+-
+----------------------------
+-
+ What: i386/x86_64 bzImage symlinks
+-When: April 2008
++When: April 2010
+
+ Why: The i386/x86_64 merge provides a symlink to the old bzImage
+ location so not yet updated user space tools, e.g. package
+@@ -221,8 +213,6 @@ Who: Thomas Gleixner <tglx at linutronix.de>
+
+ ---------------------------
+
+----------------------------
+-
+ What: i2c-i810, i2c-prosavage and i2c-savage4
+ When: May 2008
+ Why: These drivers are superseded by i810fb, intelfb and savagefb.
+@@ -230,33 +220,6 @@ Who: Jean Delvare <khali at linux-fr.org>
+
+ ---------------------------
+
+-What: bcm43xx wireless network driver
+-When: 2.6.26
+-Files: drivers/net/wireless/bcm43xx
+-Why: This driver's functionality has been replaced by the
+- mac80211-based b43 and b43legacy drivers.
+-Who: John W. Linville <linville at tuxdriver.com>
+-
+----------------------------
+-
+-What: ieee80211 softmac wireless networking component
+-When: 2.6.26 (or after removal of bcm43xx and port of zd1211rw to mac80211)
+-Files: net/ieee80211/softmac
+-Why: No in-kernel drivers will depend on it any longer.
+-Who: John W. Linville <linville at tuxdriver.com>
+-
+----------------------------
+-
+-What: rc80211-simple rate control algorithm for mac80211
+-When: 2.6.26
+-Files: net/mac80211/rc80211-simple.c
+-Why: This algorithm was provided for reference but always exhibited bad
+- responsiveness and performance and has some serious flaws. It has been
+- replaced by rc80211-pid.
+-Who: Stefano Brivio <stefano.brivio at polimi.it>
+-
+----------------------------
+-
+ What (Why):
+ - include/linux/netfilter_ipv4/ipt_TOS.h ipt_tos.h header files
+ (superseded by xt_TOS/xt_tos target & match)
+@@ -298,17 +261,6 @@ Who: Michael Buesch <mb at bu3sch.de>
+
+ ---------------------------
+
+-What: Solaris/SunOS syscall and binary support on Sparc
+-When: 2.6.26
+-Why: Largely unmaintained and almost entirely unused. File system
+- layering used to divert library and dynamic linker searches to
+- /usr/gnemul is extremely buggy and unfixable. Making it work
+- is largely pointless as without a lot of work only the most
+- trivial of Solaris binaries can work with the emulation code.
+-Who: David S. Miller <davem at davemloft.net>
+-
+----------------------------
+-
+ What: init_mm export
+ When: 2.6.26
+ Why: Not used in-tree. The current out-of-tree users used it to
+@@ -318,3 +270,28 @@ Why: Not used in-tree. The current out-of-tree users used it to
+ code / infrastructure should be in the kernel and not in some
+ out-of-tree driver.
+ Who: Thomas Gleixner <tglx at linutronix.de>
++
++----------------------------
++
++What: usedac i386 kernel parameter
++When: 2.6.27
++Why: replaced by allowdac and no dac combination
++Who: Glauber Costa <gcosta at redhat.com>
++
++---------------------------
++
++What: /sys/o2cb symlink
++When: January 2010
++Why: /sys/fs/o2cb is the proper location for this information - /sys/o2cb
++ exists as a symlink for backwards compatibility for old versions of
++ ocfs2-tools. 2 years should be sufficient time to phase in new versions
++ which know to look in /sys/fs/o2cb.
++Who: ocfs2-devel at oss.oracle.com
++
++---------------------------
++
++What: asm/semaphore.h
++When: 2.6.26
++Why: Implementation became generic; users should now include
++ linux/semaphore.h instead.
++Who: Matthew Wilcox <willy at linux.intel.com>
+diff --git a/Documentation/filesystems/nfs-rdma.txt b/Documentation/filesystems/nfs-rdma.txt
+new file mode 100644
+index 0000000..d0ec45a
+--- /dev/null
++++ b/Documentation/filesystems/nfs-rdma.txt
+@@ -0,0 +1,256 @@
++################################################################################
++# #
++# NFS/RDMA README #
++# #
++################################################################################
++
++ Author: NetApp and Open Grid Computing
++ Date: April 15, 2008
++
++Table of Contents
++~~~~~~~~~~~~~~~~~
++ - Overview
++ - Getting Help
++ - Installation
++ - Check RDMA and NFS Setup
++ - NFS/RDMA Setup
++
++Overview
++~~~~~~~~
++
++ This document describes how to install and setup the Linux NFS/RDMA client
++ and server software.
++
++ The NFS/RDMA client was first included in Linux 2.6.24. The NFS/RDMA server
++ was first included in the following release, Linux 2.6.25.
++
++ In our testing, we have obtained excellent performance results (full 10Gbit
++ wire bandwidth at minimal client CPU) under many workloads. The code passes
++ the full Connectathon test suite and operates over both Infiniband and iWARP
++ RDMA adapters.
++
++Getting Help
++~~~~~~~~~~~~
++
++ If you get stuck, you can ask questions on the
++
++ nfs-rdma-devel at lists.sourceforge.net
++
++ mailing list.
++
++Installation
++~~~~~~~~~~~~
++
++ These instructions are a step by step guide to building a machine for
++ use with NFS/RDMA.
++
++ - Install an RDMA device
++
++ Any device supported by the drivers in drivers/infiniband/hw is acceptable.
++
++ Testing has been performed using several Mellanox-based IB cards, the
++ Ammasso AMS1100 iWARP adapter, and the Chelsio cxgb3 iWARP adapter.
++
++ - Install a Linux distribution and tools
++
++ The first kernel release to contain both the NFS/RDMA client and server was
++ Linux 2.6.25 Therefore, a distribution compatible with this and subsequent
++ Linux kernel release should be installed.
++
++ The procedures described in this document have been tested with
++ distributions from Red Hat's Fedora Project (http://fedora.redhat.com/).
++
++ - Install nfs-utils-1.1.1 or greater on the client
++
++ An NFS/RDMA mount point can only be obtained by using the mount.nfs
++ command in nfs-utils-1.1.1 or greater. To see which version of mount.nfs
++ you are using, type:
++
++ > /sbin/mount.nfs -V
++
++ If the version is less than 1.1.1 or the command does not exist,
++ then you will need to install the latest version of nfs-utils.
++
++ Download the latest package from:
++
++ http://www.kernel.org/pub/linux/utils/nfs
++
++ Uncompress the package and follow the installation instructions.
++
++ If you will not be using GSS and NFSv4, the installation process
++ can be simplified by disabling these features when running configure:
++
++ > ./configure --disable-gss --disable-nfsv4
++
++ For more information on this see the package's README and INSTALL files.
++
++ After building the nfs-utils package, there will be a mount.nfs binary in
++ the utils/mount directory. This binary can be used to initiate NFS v2, v3,
++ or v4 mounts. To initiate a v4 mount, the binary must be called mount.nfs4.
++ The standard technique is to create a symlink called mount.nfs4 to mount.nfs.
++
++ NOTE: mount.nfs and therefore nfs-utils-1.1.1 or greater is only needed
++ on the NFS client machine. You do not need this specific version of
++ nfs-utils on the server. Furthermore, only the mount.nfs command from
++ nfs-utils-1.1.1 is needed on the client.
++
++ - Install a Linux kernel with NFS/RDMA
++
++ The NFS/RDMA client and server are both included in the mainline Linux
++ kernel version 2.6.25 and later. This and other versions of the 2.6 Linux
++ kernel can be found at:
++
++ ftp://ftp.kernel.org/pub/linux/kernel/v2.6/
++
++ Download the sources and place them in an appropriate location.
++
++ - Configure the RDMA stack
++
++ Make sure your kernel configuration has RDMA support enabled. Under
++ Device Drivers -> InfiniBand support, update the kernel configuration
++ to enable InfiniBand support [NOTE: the option name is misleading. Enabling
++ InfiniBand support is required for all RDMA devices (IB, iWARP, etc.)].
++
++ Enable the appropriate IB HCA support (mlx4, mthca, ehca, ipath, etc.) or
++ iWARP adapter support (amso, cxgb3, etc.).
++
++ If you are using InfiniBand, be sure to enable IP-over-InfiniBand support.
++
++ - Configure the NFS client and server
++
++ Your kernel configuration must also have NFS file system support and/or
++ NFS server support enabled. These and other NFS related configuration
++ options can be found under File Systems -> Network File Systems.
++
++ - Build, install, reboot
++
++ The NFS/RDMA code will be enabled automatically if NFS and RDMA
++ are turned on. The NFS/RDMA client and server are configured via the hidden
++ SUNRPC_XPRT_RDMA config option that depends on SUNRPC and INFINIBAND. The
++ value of SUNRPC_XPRT_RDMA will be:
++
++ - N if either SUNRPC or INFINIBAND are N, in this case the NFS/RDMA client
++ and server will not be built
++ - M if both SUNRPC and INFINIBAND are on (M or Y) and at least one is M,
++ in this case the NFS/RDMA client and server will be built as modules
++ - Y if both SUNRPC and INFINIBAND are Y, in this case the NFS/RDMA client
++ and server will be built into the kernel
++
++ Therefore, if you have followed the steps above and turned no NFS and RDMA,
++ the NFS/RDMA client and server will be built.
++
++ Build a new kernel, install it, boot it.
++
++Check RDMA and NFS Setup
++~~~~~~~~~~~~~~~~~~~~~~~~
++
++ Before configuring the NFS/RDMA software, it is a good idea to test
++ your new kernel to ensure that the kernel is working correctly.
++ In particular, it is a good idea to verify that the RDMA stack
++ is functioning as expected and standard NFS over TCP/IP and/or UDP/IP
++ is working properly.
++
++ - Check RDMA Setup
++
++ If you built the RDMA components as modules, load them at
++ this time. For example, if you are using a Mellanox Tavor/Sinai/Arbel
++ card:
++
++ > modprobe ib_mthca
++ > modprobe ib_ipoib
++
++ If you are using InfiniBand, make sure there is a Subnet Manager (SM)
++ running on the network. If your IB switch has an embedded SM, you can
++ use it. Otherwise, you will need to run an SM, such as OpenSM, on one
++ of your end nodes.
++
++ If an SM is running on your network, you should see the following:
++
++ > cat /sys/class/infiniband/driverX/ports/1/state
++ 4: ACTIVE
++
++ where driverX is mthca0, ipath5, ehca3, etc.
++
++ To further test the InfiniBand software stack, use IPoIB (this
++ assumes you have two IB hosts named host1 and host2):
++
++ host1> ifconfig ib0 a.b.c.x
++ host2> ifconfig ib0 a.b.c.y
++ host1> ping a.b.c.y
++ host2> ping a.b.c.x
++
++ For other device types, follow the appropriate procedures.
++
++ - Check NFS Setup
++
++ For the NFS components enabled above (client and/or server),
++ test their functionality over standard Ethernet using TCP/IP or UDP/IP.
++
++NFS/RDMA Setup
++~~~~~~~~~~~~~~
++
++ We recommend that you use two machines, one to act as the client and
++ one to act as the server.
++
++ One time configuration:
++
++ - On the server system, configure the /etc/exports file and
++ start the NFS/RDMA server.
++
++ Exports entries with the following formats have been tested:
++
++ /vol0 192.168.0.47(fsid=0,rw,async,insecure,no_root_squash)
++ /vol0 192.168.0.0/255.255.255.0(fsid=0,rw,async,insecure,no_root_squash)
++
++ The IP address(es) is(are) the client's IPoIB address for an InfiniBand HCA or the
++ cleint's iWARP address(es) for an RNIC.
++
++ NOTE: The "insecure" option must be used because the NFS/RDMA client does not
++ use a reserved port.
++
++ Each time a machine boots:
++
++ - Load and configure the RDMA drivers
++
++ For InfiniBand using a Mellanox adapter:
++
++ > modprobe ib_mthca
++ > modprobe ib_ipoib
++ > ifconfig ib0 a.b.c.d
++
++ NOTE: use unique addresses for the client and server
++
++ - Start the NFS server
++
++ If the NFS/RDMA server was built as a module (CONFIG_SUNRPC_XPRT_RDMA=m in kernel config),
++ load the RDMA transport module:
++
++ > modprobe svcrdma
++
++ Regardless of how the server was built (module or built-in), start the server:
++
++ > /etc/init.d/nfs start
++
++ or
++
++ > service nfs start
++
++ Instruct the server to listen on the RDMA transport:
++
++ > echo rdma 2050 > /proc/fs/nfsd/portlist
++
++ - On the client system
++
++ If the NFS/RDMA client was built as a module (CONFIG_SUNRPC_XPRT_RDMA=m in kernel config),
++ load the RDMA client module:
++
++ > modprobe xprtrdma.ko
++
++ Regardless of how the client was built (module or built-in), issue the mount.nfs command:
++
++ > /path/to/your/mount.nfs <IPoIB-server-name-or-address>:/<export> /mnt -i -o rdma,port=2050
++
++ To verify that the mount is using RDMA, run "cat /proc/mounts" and check the
++ "proto" field for the given mount.
++
++ Congratulations! You're using NFS/RDMA!
+diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
+index 518ebe6..2a99116 100644
+--- a/Documentation/filesystems/proc.txt
++++ b/Documentation/filesystems/proc.txt
+@@ -43,6 +43,7 @@ Table of Contents
+ 2.13 /proc/<pid>/oom_score - Display current oom-killer score
+ 2.14 /proc/<pid>/io - Display the IO accounting fields
+ 2.15 /proc/<pid>/coredump_filter - Core dump filtering settings
++ 2.16 /proc/<pid>/mountinfo - Information about mounts
+
+ ------------------------------------------------------------------------------
+ Preface
+@@ -2348,4 +2349,41 @@ For example:
+ $ echo 0x7 > /proc/self/coredump_filter
+ $ ./some_program
+
++2.16 /proc/<pid>/mountinfo - Information about mounts
++--------------------------------------------------------
++
++This file contains lines of the form:
++
++36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue
++(1)(2)(3) (4) (5) (6) (7) (8) (9) (10) (11)
++
++(1) mount ID: unique identifier of the mount (may be reused after umount)
++(2) parent ID: ID of parent (or of self for the top of the mount tree)
++(3) major:minor: value of st_dev for files on filesystem
++(4) root: root of the mount within the filesystem
++(5) mount point: mount point relative to the process's root
++(6) mount options: per mount options
++(7) optional fields: zero or more fields of the form "tag[:value]"
++(8) separator: marks the end of the optional fields
++(9) filesystem type: name of filesystem of the form "type[.subtype]"
++(10) mount source: filesystem specific information or "none"
++(11) super options: per super block options
++
++Parsers should ignore all unrecognised optional fields. Currently the
++possible optional fields are:
++
++shared:X mount is shared in peer group X
++master:X mount is slave to peer group X
++propagate_from:X mount is slave and receives propagation from peer group X (*)
++unbindable mount is unbindable
++
++(*) X is the closest dominant peer group under the process's root. If
++X is the immediate master of the mount, or if there's no dominant peer
++group under the same root, then only the "master:X" field is present
++and not the "propagate_from:X" field.
++
++For more information on mount propagation see:
++
++ Documentation/filesystems/sharedsubtree.txt
++
+ ------------------------------------------------------------------------------
+diff --git a/Documentation/filesystems/seq_file.txt b/Documentation/filesystems/seq_file.txt
+index 7fb8e6d..b843743 100644
+--- a/Documentation/filesystems/seq_file.txt
++++ b/Documentation/filesystems/seq_file.txt
+@@ -122,8 +122,7 @@ stop() is the place to free it.
+ }
+
+ Finally, the show() function should format the object currently pointed to
+-by the iterator for output. It should return zero, or an error code if
+-something goes wrong. The example module's show() function is:
++by the iterator for output. The example module's show() function is:
+
+ static int ct_seq_show(struct seq_file *s, void *v)
+ {
+@@ -132,6 +131,12 @@ something goes wrong. The example module's show() function is:
+ return 0;
+ }
+
++If all is well, the show() function should return zero. A negative error
++code in the usual manner indicates that something went wrong; it will be
++passed back to user space. This function can also return SEQ_SKIP, which
++causes the current item to be skipped; if the show() function has already
++generated output before returning SEQ_SKIP, that output will be dropped.
++
+ We will look at seq_printf() in a moment. But first, the definition of the
+ seq_file iterator is finished by creating a seq_operations structure with
+ the four functions we have just defined:
+@@ -182,12 +187,18 @@ The first two output a single character and a string, just like one would
+ expect. seq_escape() is like seq_puts(), except that any character in s
+ which is in the string esc will be represented in octal form in the output.
+
+-There is also a function for printing filenames:
++There is also a pair of functions for printing filenames:
+
+ int seq_path(struct seq_file *m, struct path *path, char *esc);
++ int seq_path_root(struct seq_file *m, struct path *path,
++ struct path *root, char *esc)
+
+ Here, path indicates the file of interest, and esc is a set of characters
+-which should be escaped in the output.
++which should be escaped in the output. A call to seq_path() will output
++the path relative to the current process's filesystem root. If a different
++root is desired, it can be used with seq_path_root(). Note that, if it
++turns out that path cannot be reached from root, the value of root will be
++changed in seq_file_root() to a root which *does* work.
+
+
+ Making it all work
+diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt
+index 4598ef7..7f27b8f 100644
+--- a/Documentation/filesystems/sysfs.txt
++++ b/Documentation/filesystems/sysfs.txt
+@@ -176,8 +176,10 @@ implementations:
+ Recall that an attribute should only be exporting one value, or an
+ array of similar values, so this shouldn't be that expensive.
+
+- This allows userspace to do partial reads and seeks arbitrarily over
+- the entire file at will.
++ This allows userspace to do partial reads and forward seeks
++ arbitrarily over the entire file at will. If userspace seeks back to
++ zero or does a pread(2) with an offset of '0' the show() method will
++ be called again, rearmed, to fill the buffer.
+
+ - On write(2), sysfs expects the entire buffer to be passed during the
+ first write. Sysfs then passes the entire buffer to the store()
+@@ -192,6 +194,9 @@ implementations:
+
+ Other notes:
+
++- Writing causes the show() method to be rearmed regardless of current
++ file position.
++
+ - The buffer will always be PAGE_SIZE bytes in length. On i386, this
+ is 4096.
+
+diff --git a/Documentation/filesystems/xfs.txt b/Documentation/filesystems/xfs.txt
+index 74aeb14..0a1668b 100644
+--- a/Documentation/filesystems/xfs.txt
++++ b/Documentation/filesystems/xfs.txt
+@@ -52,16 +52,15 @@ When mounting an XFS filesystem, the following options are accepted.
+ and also gets the setgid bit set if it is a directory itself.
+
+ ihashsize=value
+- Sets the number of hash buckets available for hashing the
+- in-memory inodes of the specified mount point. If a value
+- of zero is used, the value selected by the default algorithm
+- will be displayed in /proc/mounts.
++ In memory inode hashes have been removed, so this option has
++ no function as of August 2007. Option is deprecated.
+
+ ikeep/noikeep
+- When inode clusters are emptied of inodes, keep them around
+- on the disk (ikeep) - this is the traditional XFS behaviour
+- and is still the default for now. Using the noikeep option,
+- inode clusters are returned to the free space pool.
++ When ikeep is specified, XFS does not delete empty inode clusters
++ and keeps them around on disk. ikeep is the traditional XFS
++ behaviour. When noikeep is specified, empty inode clusters
++ are returned to the free space pool. The default is noikeep for
++ non-DMAPI mounts, while ikeep is the default when DMAPI is in use.
+
+ inode64
+ Indicates that XFS is allowed to create inodes at any location
+diff --git a/Documentation/firmware_class/firmware_sample_driver.c b/Documentation/firmware_class/firmware_sample_driver.c
+deleted file mode 100644
+index 6865cbe..0000000
+--- a/Documentation/firmware_class/firmware_sample_driver.c
++++ /dev/null
+@@ -1,115 +0,0 @@
+-/*
+- * firmware_sample_driver.c -
+- *
+- * Copyright (c) 2003 Manuel Estrada Sainz
+- *
+- * Sample code on how to use request_firmware() from drivers.
+- *
+- */
+-
+-#include <linux/module.h>
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/device.h>
+-#include <linux/string.h>
+-
+-#include "linux/firmware.h"
+-
+-static struct device ghost_device = {
+- .bus_id = "ghost0",
+-};
+-
+-
+-static void sample_firmware_load(char *firmware, int size)
+-{
+- u8 buf[size+1];
+- memcpy(buf, firmware, size);
+- buf[size] = '\0';
+- printk(KERN_INFO "firmware_sample_driver: firmware: %s\n", buf);
+-}
+-
+-static void sample_probe_default(void)
+-{
+- /* uses the default method to get the firmware */
+- const struct firmware *fw_entry;
+- printk(KERN_INFO "firmware_sample_driver: a ghost device got inserted :)\n");
+-
+- if(request_firmware(&fw_entry, "sample_driver_fw", &ghost_device)!=0)
+- {
+- printk(KERN_ERR
+- "firmware_sample_driver: Firmware not available\n");
+- return;
+- }
+-
+- sample_firmware_load(fw_entry->data, fw_entry->size);
+-
+- release_firmware(fw_entry);
+-
+- /* finish setting up the device */
+-}
+-static void sample_probe_specific(void)
+-{
+- /* Uses some specific hotplug support to get the firmware from
+- * userspace directly into the hardware, or via some sysfs file */
+-
+- /* NOTE: This currently doesn't work */
+-
+- printk(KERN_INFO "firmware_sample_driver: a ghost device got inserted :)\n");
+-
+- if(request_firmware(NULL, "sample_driver_fw", &ghost_device)!=0)
+- {
+- printk(KERN_ERR
+- "firmware_sample_driver: Firmware load failed\n");
+- return;
+- }
+-
+- /* request_firmware blocks until userspace finished, so at
+- * this point the firmware should be already in the device */
+-
+- /* finish setting up the device */
+-}
+-static void sample_probe_async_cont(const struct firmware *fw, void *context)
+-{
+- if(!fw){
+- printk(KERN_ERR
+- "firmware_sample_driver: firmware load failed\n");
+- return;
+- }
+-
+- printk(KERN_INFO "firmware_sample_driver: device pointer \"%s\"\n",
+- (char *)context);
+- sample_firmware_load(fw->data, fw->size);
+-}
+-static void sample_probe_async(void)
+-{
+- /* Let's say that I can't sleep */
+- int error;
+- error = request_firmware_nowait (THIS_MODULE, FW_ACTION_NOHOTPLUG,
+- "sample_driver_fw", &ghost_device,
+- "my device pointer",
+- sample_probe_async_cont);
+- if(error){
+- printk(KERN_ERR
+- "firmware_sample_driver:"
+- " request_firmware_nowait failed\n");
+- }
+-}
+-
+-static int sample_init(void)
+-{
+- device_initialize(&ghost_device);
+- /* since there is no real hardware insertion I just call the
+- * sample probe functions here */
+- sample_probe_specific();
+- sample_probe_default();
+- sample_probe_async();
+- return 0;
+-}
+-static void __exit sample_exit(void)
+-{
+-}
+-
+-module_init (sample_init);
+-module_exit (sample_exit);
+-
+-MODULE_LICENSE("GPL");
+diff --git a/Documentation/firmware_class/firmware_sample_firmware_class.c b/Documentation/firmware_class/firmware_sample_firmware_class.c
+deleted file mode 100644
+index 2de6285..0000000
+--- a/Documentation/firmware_class/firmware_sample_firmware_class.c
++++ /dev/null
+@@ -1,207 +0,0 @@
+-/*
+- * firmware_sample_firmware_class.c -
+- *
+- * Copyright (c) 2003 Manuel Estrada Sainz
+- *
+- * NOTE: This is just a probe of concept, if you think that your driver would
+- * be well served by this mechanism please contact me first.
+- *
+- * DON'T USE THIS CODE AS IS
+- *
+- */
+-
+-#include <linux/device.h>
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/timer.h>
+-#include <linux/slab.h>
+-#include <linux/string.h>
+-#include <linux/firmware.h>
+-
+-
+-MODULE_AUTHOR("Manuel Estrada Sainz");
+-MODULE_DESCRIPTION("Hackish sample for using firmware class directly");
+-MODULE_LICENSE("GPL");
+-
+-static inline struct class_device *to_class_dev(struct kobject *obj)
+-{
+- return container_of(obj,struct class_device,kobj);
+-}
+-static inline
+-struct class_device_attribute *to_class_dev_attr(struct attribute *_attr)
+-{
+- return container_of(_attr,struct class_device_attribute,attr);
+-}
+-
+-int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr);
+-int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr);
+-
+-struct firmware_priv {
+- char fw_id[FIRMWARE_NAME_MAX];
+- s32 loading:2;
+- u32 abort:1;
+-};
+-
+-extern struct class firmware_class;
+-
+-static ssize_t firmware_loading_show(struct class_device *class_dev, char *buf)
+-{
+- struct firmware_priv *fw_priv = class_get_devdata(class_dev);
+- return sprintf(buf, "%d\n", fw_priv->loading);
+-}
+-static ssize_t firmware_loading_store(struct class_device *class_dev,
+- const char *buf, size_t count)
+-{
+- struct firmware_priv *fw_priv = class_get_devdata(class_dev);
+- int prev_loading = fw_priv->loading;
+-
+- fw_priv->loading = simple_strtol(buf, NULL, 10);
+-
+- switch(fw_priv->loading){
+- case -1:
+- /* abort load an panic */
+- break;
+- case 1:
+- /* setup load */
+- break;
+- case 0:
+- if(prev_loading==1){
+- /* finish load and get the device back to working
+- * state */
+- }
+- break;
+- }
+-
+- return count;
+-}
+-static CLASS_DEVICE_ATTR(loading, 0644,
+- firmware_loading_show, firmware_loading_store);
+-
+-static ssize_t firmware_data_read(struct kobject *kobj,
+- struct bin_attribute *bin_attr,
+- char *buffer, loff_t offset, size_t count)
+-{
+- struct class_device *class_dev = to_class_dev(kobj);
+- struct firmware_priv *fw_priv = class_get_devdata(class_dev);
+-
+- /* read from the devices firmware memory */
+-
+- return count;
+-}
+-static ssize_t firmware_data_write(struct kobject *kobj,
+- struct bin_attribute *bin_attr,
+- char *buffer, loff_t offset, size_t count)
+-{
+- struct class_device *class_dev = to_class_dev(kobj);
+- struct firmware_priv *fw_priv = class_get_devdata(class_dev);
+-
+- /* write to the devices firmware memory */
+-
+- return count;
+-}
+-static struct bin_attribute firmware_attr_data = {
+- .attr = {.name = "data", .mode = 0644},
+- .size = 0,
+- .read = firmware_data_read,
+- .write = firmware_data_write,
+-};
+-static int fw_setup_class_device(struct class_device *class_dev,
+- const char *fw_name,
+- struct device *device)
+-{
+- int retval;
+- struct firmware_priv *fw_priv;
+-
+- fw_priv = kzalloc(sizeof(struct firmware_priv), GFP_KERNEL);
+- if (!fw_priv) {
+- retval = -ENOMEM;
+- goto out;
+- }
+-
+- memset(class_dev, 0, sizeof(*class_dev));
+-
+- strncpy(fw_priv->fw_id, fw_name, FIRMWARE_NAME_MAX);
+- fw_priv->fw_id[FIRMWARE_NAME_MAX-1] = '\0';
+-
+- strncpy(class_dev->class_id, device->bus_id, BUS_ID_SIZE);
+- class_dev->class_id[BUS_ID_SIZE-1] = '\0';
+- class_dev->dev = device;
+-
+- class_dev->class = &firmware_class,
+- class_set_devdata(class_dev, fw_priv);
+- retval = class_device_register(class_dev);
+- if (retval){
+- printk(KERN_ERR "%s: class_device_register failed\n",
+- __FUNCTION__);
+- goto error_free_fw_priv;
+- }
+-
+- retval = sysfs_create_bin_file(&class_dev->kobj, &firmware_attr_data);
+- if (retval){
+- printk(KERN_ERR "%s: sysfs_create_bin_file failed\n",
+- __FUNCTION__);
+- goto error_unreg_class_dev;
+- }
+-
+- retval = class_device_create_file(class_dev,
+- &class_device_attr_loading);
+- if (retval){
+- printk(KERN_ERR "%s: class_device_create_file failed\n",
+- __FUNCTION__);
+- goto error_remove_data;
+- }
+-
+- goto out;
+-
+-error_remove_data:
+- sysfs_remove_bin_file(&class_dev->kobj, &firmware_attr_data);
+-error_unreg_class_dev:
+- class_device_unregister(class_dev);
+-error_free_fw_priv:
+- kfree(fw_priv);
+-out:
+- return retval;
+-}
+-static void fw_remove_class_device(struct class_device *class_dev)
+-{
+- struct firmware_priv *fw_priv = class_get_devdata(class_dev);
+-
+- class_device_remove_file(class_dev, &class_device_attr_loading);
+- sysfs_remove_bin_file(&class_dev->kobj, &firmware_attr_data);
+- class_device_unregister(class_dev);
+-}
+-
+-static struct class_device *class_dev;
+-
+-static struct device my_device = {
+- .bus_id = "my_dev0",
+-};
+-
+-static int __init firmware_sample_init(void)
+-{
+- int error;
+-
+- device_initialize(&my_device);
+- class_dev = kmalloc(sizeof(struct class_device), GFP_KERNEL);
+- if(!class_dev)
+- return -ENOMEM;
+-
+- error = fw_setup_class_device(class_dev, "my_firmware_image",
+- &my_device);
+- if(error){
+- kfree(class_dev);
+- return error;
+- }
+- return 0;
+-
+-}
+-static void __exit firmware_sample_exit(void)
+-{
+- struct firmware_priv *fw_priv = class_get_devdata(class_dev);
+- fw_remove_class_device(class_dev);
+- kfree(fw_priv);
+- kfree(class_dev);
+-}
+-module_init(firmware_sample_init);
+-module_exit(firmware_sample_exit);
+-
+diff --git a/Documentation/highuid.txt b/Documentation/highuid.txt
+index 76034d9..6bad6f1 100644
+--- a/Documentation/highuid.txt
++++ b/Documentation/highuid.txt
+@@ -28,8 +28,6 @@ What's left to be done for 32-bit UIDs on all Linux architectures:
+ uses the 32-bit UID system calls properly otherwise.
+
+ This affects at least:
+- SunOS emulation
+- Solaris emulation
+ iBCS on Intel
+
+ sparc32 emulation on sparc64
+diff --git a/Documentation/hrtimer/timer_stats.txt b/Documentation/hrtimer/timer_stats.txt
+deleted file mode 100644
+index 20d368c..0000000
+--- a/Documentation/hrtimer/timer_stats.txt
++++ /dev/null
+@@ -1,73 +0,0 @@
+-timer_stats - timer usage statistics
+-------------------------------------
+-
+-timer_stats is a debugging facility to make the timer (ab)usage in a Linux
+-system visible to kernel and userspace developers. If enabled in the config
+-but not used it has almost zero runtime overhead, and a relatively small
+-data structure overhead. Even if collection is enabled runtime all the
+-locking is per-CPU and lookup is hashed.
+-
+-timer_stats should be used by kernel and userspace developers to verify that
+-their code does not make unduly use of timers. This helps to avoid unnecessary
+-wakeups, which should be avoided to optimize power consumption.
+-
+-It can be enabled by CONFIG_TIMER_STATS in the "Kernel hacking" configuration
+-section.
+-
+-timer_stats collects information about the timer events which are fired in a
+-Linux system over a sample period:
+-
+-- the pid of the task(process) which initialized the timer
+-- the name of the process which initialized the timer
+-- the function where the timer was intialized
+-- the callback function which is associated to the timer
+-- the number of events (callbacks)
+-
+-timer_stats adds an entry to /proc: /proc/timer_stats
+-
+-This entry is used to control the statistics functionality and to read out the
+-sampled information.
+-
+-The timer_stats functionality is inactive on bootup.
+-
+-To activate a sample period issue:
+-# echo 1 >/proc/timer_stats
+-
+-To stop a sample period issue:
+-# echo 0 >/proc/timer_stats
+-
+-The statistics can be retrieved by:
+-# cat /proc/timer_stats
+-
+-The readout of /proc/timer_stats automatically disables sampling. The sampled
+-information is kept until a new sample period is started. This allows multiple
+-readouts.
+-
+-Sample output of /proc/timer_stats:
+-
+-Timerstats sample period: 3.888770 s
+- 12, 0 swapper hrtimer_stop_sched_tick (hrtimer_sched_tick)
+- 15, 1 swapper hcd_submit_urb (rh_timer_func)
+- 4, 959 kedac schedule_timeout (process_timeout)
+- 1, 0 swapper page_writeback_init (wb_timer_fn)
+- 28, 0 swapper hrtimer_stop_sched_tick (hrtimer_sched_tick)
+- 22, 2948 IRQ 4 tty_flip_buffer_push (delayed_work_timer_fn)
+- 3, 3100 bash schedule_timeout (process_timeout)
+- 1, 1 swapper queue_delayed_work_on (delayed_work_timer_fn)
+- 1, 1 swapper queue_delayed_work_on (delayed_work_timer_fn)
+- 1, 1 swapper neigh_table_init_no_netlink (neigh_periodic_timer)
+- 1, 2292 ip __netdev_watchdog_up (dev_watchdog)
+- 1, 23 events/1 do_cache_clean (delayed_work_timer_fn)
+-90 total events, 30.0 events/sec
+-
+-The first column is the number of events, the second column the pid, the third
+-column is the name of the process. The forth column shows the function which
+-initialized the timer and in parantheses the callback function which was
+-executed on expiry.
+-
+- Thomas, Ingo
+-
+-Added flag to indicate 'deferrable timer' in /proc/timer_stats. A deferrable
+-timer will appear as follows
+- 10D, 1 swapper queue_delayed_work_on (delayed_work_timer_fn)
+-
+diff --git a/Documentation/hrtimers/highres.txt b/Documentation/hrtimers/highres.txt
+deleted file mode 100644
+index a73ecf5..0000000
+--- a/Documentation/hrtimers/highres.txt
++++ /dev/null
+@@ -1,249 +0,0 @@
+-High resolution timers and dynamic ticks design notes
+------------------------------------------------------
+-
+-Further information can be found in the paper of the OLS 2006 talk "hrtimers
+-and beyond". The paper is part of the OLS 2006 Proceedings Volume 1, which can
+-be found on the OLS website:
+-http://www.linuxsymposium.org/2006/linuxsymposium_procv1.pdf
+-
+-The slides to this talk are available from:
+-http://tglx.de/projects/hrtimers/ols2006-hrtimers.pdf
+-
+-The slides contain five figures (pages 2, 15, 18, 20, 22), which illustrate the
+-changes in the time(r) related Linux subsystems. Figure #1 (p. 2) shows the
+-design of the Linux time(r) system before hrtimers and other building blocks
+-got merged into mainline.
+-
+-Note: the paper and the slides are talking about "clock event source", while we
+-switched to the name "clock event devices" in meantime.
+-
+-The design contains the following basic building blocks:
+-
+-- hrtimer base infrastructure
+-- timeofday and clock source management
+-- clock event management
+-- high resolution timer functionality
+-- dynamic ticks
+-
+-
+-hrtimer base infrastructure
+----------------------------
+-
+-The hrtimer base infrastructure was merged into the 2.6.16 kernel. Details of
+-the base implementation are covered in Documentation/hrtimers/hrtimer.txt. See
+-also figure #2 (OLS slides p. 15)
+-
+-The main differences to the timer wheel, which holds the armed timer_list type
+-timers are:
+- - time ordered enqueueing into a rb-tree
+- - independent of ticks (the processing is based on nanoseconds)
+-
+-
+-timeofday and clock source management
+--------------------------------------
+-
+-John Stultz's Generic Time Of Day (GTOD) framework moves a large portion of
+-code out of the architecture-specific areas into a generic management
+-framework, as illustrated in figure #3 (OLS slides p. 18). The architecture
+-specific portion is reduced to the low level hardware details of the clock
+-sources, which are registered in the framework and selected on a quality based
+-decision. The low level code provides hardware setup and readout routines and
+-initializes data structures, which are used by the generic time keeping code to
+-convert the clock ticks to nanosecond based time values. All other time keeping
+-related functionality is moved into the generic code. The GTOD base patch got
+-merged into the 2.6.18 kernel.
+-
+-Further information about the Generic Time Of Day framework is available in the
+-OLS 2005 Proceedings Volume 1:
+-http://www.linuxsymposium.org/2005/linuxsymposium_procv1.pdf
+-
+-The paper "We Are Not Getting Any Younger: A New Approach to Time and
+-Timers" was written by J. Stultz, D.V. Hart, & N. Aravamudan.
+-
+-Figure #3 (OLS slides p.18) illustrates the transformation.
+-
+-
+-clock event management
+-----------------------
+-
+-While clock sources provide read access to the monotonically increasing time
+-value, clock event devices are used to schedule the next event
+-interrupt(s). The next event is currently defined to be periodic, with its
+-period defined at compile time. The setup and selection of the event device
+-for various event driven functionalities is hardwired into the architecture
+-dependent code. This results in duplicated code across all architectures and
+-makes it extremely difficult to change the configuration of the system to use
+-event interrupt devices other than those already built into the
+-architecture. Another implication of the current design is that it is necessary
+-to touch all the architecture-specific implementations in order to provide new
+-functionality like high resolution timers or dynamic ticks.
+-
+-The clock events subsystem tries to address this problem by providing a generic
+-solution to manage clock event devices and their usage for the various clock
+-event driven kernel functionalities. The goal of the clock event subsystem is
+-to minimize the clock event related architecture dependent code to the pure
+-hardware related handling and to allow easy addition and utilization of new
+-clock event devices. It also minimizes the duplicated code across the
+-architectures as it provides generic functionality down to the interrupt
+-service handler, which is almost inherently hardware dependent.
+-
+-Clock event devices are registered either by the architecture dependent boot
+-code or at module insertion time. Each clock event device fills a data
+-structure with clock-specific property parameters and callback functions. The
+-clock event management decides, by using the specified property parameters, the
+-set of system functions a clock event device will be used to support. This
+-includes the distinction of per-CPU and per-system global event devices.
+-
+-System-level global event devices are used for the Linux periodic tick. Per-CPU
+-event devices are used to provide local CPU functionality such as process
+-accounting, profiling, and high resolution timers.
+-
+-The management layer assigns one or more of the following functions to a clock
+-event device:
+- - system global periodic tick (jiffies update)
+- - cpu local update_process_times
+- - cpu local profiling
+- - cpu local next event interrupt (non periodic mode)
+-
+-The clock event device delegates the selection of those timer interrupt related
+-functions completely to the management layer. The clock management layer stores
+-a function pointer in the device description structure, which has to be called
+-from the hardware level handler. This removes a lot of duplicated code from the
+-architecture specific timer interrupt handlers and hands the control over the
+-clock event devices and the assignment of timer interrupt related functionality
+-to the core code.
+-
+-The clock event layer API is rather small. Aside from the clock event device
+-registration interface it provides functions to schedule the next event
+-interrupt, clock event device notification service and support for suspend and
+-resume.
+-
+-The framework adds about 700 lines of code which results in a 2KB increase of
+-the kernel binary size. The conversion of i386 removes about 100 lines of
+-code. The binary size decrease is in the range of 400 byte. We believe that the
+-increase of flexibility and the avoidance of duplicated code across
+-architectures justifies the slight increase of the binary size.
+-
+-The conversion of an architecture has no functional impact, but allows to
+-utilize the high resolution and dynamic tick functionalites without any change
+-to the clock event device and timer interrupt code. After the conversion the
+-enabling of high resolution timers and dynamic ticks is simply provided by
+-adding the kernel/time/Kconfig file to the architecture specific Kconfig and
+-adding the dynamic tick specific calls to the idle routine (a total of 3 lines
+-added to the idle function and the Kconfig file)
+-
+-Figure #4 (OLS slides p.20) illustrates the transformation.
+-
+-
+-high resolution timer functionality
+------------------------------------
+-
+-During system boot it is not possible to use the high resolution timer
+-functionality, while making it possible would be difficult and would serve no
+-useful function. The initialization of the clock event device framework, the
+-clock source framework (GTOD) and hrtimers itself has to be done and
+-appropriate clock sources and clock event devices have to be registered before
+-the high resolution functionality can work. Up to the point where hrtimers are
+-initialized, the system works in the usual low resolution periodic mode. The
+-clock source and the clock event device layers provide notification functions
+-which inform hrtimers about availability of new hardware. hrtimers validates
+-the usability of the registered clock sources and clock event devices before
+-switching to high resolution mode. This ensures also that a kernel which is
+-configured for high resolution timers can run on a system which lacks the
+-necessary hardware support.
+-
+-The high resolution timer code does not support SMP machines which have only
+-global clock event devices. The support of such hardware would involve IPI
+-calls when an interrupt happens. The overhead would be much larger than the
+-benefit. This is the reason why we currently disable high resolution and
+-dynamic ticks on i386 SMP systems which stop the local APIC in C3 power
+-state. A workaround is available as an idea, but the problem has not been
+-tackled yet.
+-
+-The time ordered insertion of timers provides all the infrastructure to decide
+-whether the event device has to be reprogrammed when a timer is added. The
+-decision is made per timer base and synchronized across per-cpu timer bases in
+-a support function. The design allows the system to utilize separate per-CPU
+-clock event devices for the per-CPU timer bases, but currently only one
+-reprogrammable clock event device per-CPU is utilized.
+-
+-When the timer interrupt happens, the next event interrupt handler is called
+-from the clock event distribution code and moves expired timers from the
+-red-black tree to a separate double linked list and invokes the softirq
+-handler. An additional mode field in the hrtimer structure allows the system to
+-execute callback functions directly from the next event interrupt handler. This
+-is restricted to code which can safely be executed in the hard interrupt
+-context. This applies, for example, to the common case of a wakeup function as
+-used by nanosleep. The advantage of executing the handler in the interrupt
+-context is the avoidance of up to two context switches - from the interrupted
+-context to the softirq and to the task which is woken up by the expired
+-timer.
+-
+-Once a system has switched to high resolution mode, the periodic tick is
+-switched off. This disables the per system global periodic clock event device -
+-e.g. the PIT on i386 SMP systems.
+-
+-The periodic tick functionality is provided by an per-cpu hrtimer. The callback
+-function is executed in the next event interrupt context and updates jiffies
+-and calls update_process_times and profiling. The implementation of the hrtimer
+-based periodic tick is designed to be extended with dynamic tick functionality.
+-This allows to use a single clock event device to schedule high resolution
+-timer and periodic events (jiffies tick, profiling, process accounting) on UP
+-systems. This has been proved to work with the PIT on i386 and the Incrementer
+-on PPC.
+-
+-The softirq for running the hrtimer queues and executing the callbacks has been
+-separated from the tick bound timer softirq to allow accurate delivery of high
+-resolution timer signals which are used by itimer and POSIX interval
+-timers. The execution of this softirq can still be delayed by other softirqs,
+-but the overall latencies have been significantly improved by this separation.
+-
+-Figure #5 (OLS slides p.22) illustrates the transformation.
+-
+-
+-dynamic ticks
+--------------
+-
+-Dynamic ticks are the logical consequence of the hrtimer based periodic tick
+-replacement (sched_tick). The functionality of the sched_tick hrtimer is
+-extended by three functions:
+-
+-- hrtimer_stop_sched_tick
+-- hrtimer_restart_sched_tick
+-- hrtimer_update_jiffies
+-
+-hrtimer_stop_sched_tick() is called when a CPU goes into idle state. The code
+-evaluates the next scheduled timer event (from both hrtimers and the timer
+-wheel) and in case that the next event is further away than the next tick it
+-reprograms the sched_tick to this future event, to allow longer idle sleeps
+-without worthless interruption by the periodic tick. The function is also
+-called when an interrupt happens during the idle period, which does not cause a
+-reschedule. The call is necessary as the interrupt handler might have armed a
+-new timer whose expiry time is before the time which was identified as the
+-nearest event in the previous call to hrtimer_stop_sched_tick.
+-
+-hrtimer_restart_sched_tick() is called when the CPU leaves the idle state before
+-it calls schedule(). hrtimer_restart_sched_tick() resumes the periodic tick,
+-which is kept active until the next call to hrtimer_stop_sched_tick().
+-
+-hrtimer_update_jiffies() is called from irq_enter() when an interrupt happens
+-in the idle period to make sure that jiffies are up to date and the interrupt
+-handler has not to deal with an eventually stale jiffy value.
+-
+-The dynamic tick feature provides statistical values which are exported to
+-userspace via /proc/stats and can be made available for enhanced power
+-management control.
+-
+-The implementation leaves room for further development like full tickless
+-systems, where the time slice is controlled by the scheduler, variable
+-frequency profiling, and a complete removal of jiffies in the future.
+-
+-
+-Aside the current initial submission of i386 support, the patchset has been
+-extended to x86_64 and ARM already. Initial (work in progress) support is also
+-available for MIPS and PowerPC.
+-
+- Thomas, Ingo
+-
+-
+-
+diff --git a/Documentation/hrtimers/hrtimers.txt b/Documentation/hrtimers/hrtimers.txt
+deleted file mode 100644
+index ce31f65..0000000
+--- a/Documentation/hrtimers/hrtimers.txt
++++ /dev/null
+@@ -1,178 +0,0 @@
+-
+-hrtimers - subsystem for high-resolution kernel timers
+-----------------------------------------------------
+-
+-This patch introduces a new subsystem for high-resolution kernel timers.
+-
+-One might ask the question: we already have a timer subsystem
+-(kernel/timers.c), why do we need two timer subsystems? After a lot of
+-back and forth trying to integrate high-resolution and high-precision
+-features into the existing timer framework, and after testing various
+-such high-resolution timer implementations in practice, we came to the
+-conclusion that the timer wheel code is fundamentally not suitable for
+-such an approach. We initially didn't believe this ('there must be a way
+-to solve this'), and spent a considerable effort trying to integrate
+-things into the timer wheel, but we failed. In hindsight, there are
+-several reasons why such integration is hard/impossible:
+-
+-- the forced handling of low-resolution and high-resolution timers in
+- the same way leads to a lot of compromises, macro magic and #ifdef
+- mess. The timers.c code is very "tightly coded" around jiffies and
+- 32-bitness assumptions, and has been honed and micro-optimized for a
+- relatively narrow use case (jiffies in a relatively narrow HZ range)
+- for many years - and thus even small extensions to it easily break
+- the wheel concept, leading to even worse compromises. The timer wheel
+- code is very good and tight code, there's zero problems with it in its
+- current usage - but it is simply not suitable to be extended for
+- high-res timers.
+-
+-- the unpredictable [O(N)] overhead of cascading leads to delays which
+- necessitate a more complex handling of high resolution timers, which
+- in turn decreases robustness. Such a design still led to rather large
+- timing inaccuracies. Cascading is a fundamental property of the timer
+- wheel concept, it cannot be 'designed out' without unevitably
+- degrading other portions of the timers.c code in an unacceptable way.
+-
+-- the implementation of the current posix-timer subsystem on top of
+- the timer wheel has already introduced a quite complex handling of
+- the required readjusting of absolute CLOCK_REALTIME timers at
+- settimeofday or NTP time - further underlying our experience by
+- example: that the timer wheel data structure is too rigid for high-res
+- timers.
+-
+-- the timer wheel code is most optimal for use cases which can be
+- identified as "timeouts". Such timeouts are usually set up to cover
+- error conditions in various I/O paths, such as networking and block
+- I/O. The vast majority of those timers never expire and are rarely
+- recascaded because the expected correct event arrives in time so they
+- can be removed from the timer wheel before any further processing of
+- them becomes necessary. Thus the users of these timeouts can accept
+- the granularity and precision tradeoffs of the timer wheel, and
+- largely expect the timer subsystem to have near-zero overhead.
+- Accurate timing for them is not a core purpose - in fact most of the
+- timeout values used are ad-hoc. For them it is at most a necessary
+- evil to guarantee the processing of actual timeout completions
+- (because most of the timeouts are deleted before completion), which
+- should thus be as cheap and unintrusive as possible.
+-
+-The primary users of precision timers are user-space applications that
+-utilize nanosleep, posix-timers and itimer interfaces. Also, in-kernel
+-users like drivers and subsystems which require precise timed events
+-(e.g. multimedia) can benefit from the availability of a separate
+-high-resolution timer subsystem as well.
+-
+-While this subsystem does not offer high-resolution clock sources just
+-yet, the hrtimer subsystem can be easily extended with high-resolution
+-clock capabilities, and patches for that exist and are maturing quickly.
+-The increasing demand for realtime and multimedia applications along
+-with other potential users for precise timers gives another reason to
+-separate the "timeout" and "precise timer" subsystems.
+-
+-Another potential benefit is that such a separation allows even more
+-special-purpose optimization of the existing timer wheel for the low
+-resolution and low precision use cases - once the precision-sensitive
+-APIs are separated from the timer wheel and are migrated over to
+-hrtimers. E.g. we could decrease the frequency of the timeout subsystem
+-from 250 Hz to 100 HZ (or even smaller).
+-
+-hrtimer subsystem implementation details
+-----------------------------------------
+-
+-the basic design considerations were:
+-
+-- simplicity
+-
+-- data structure not bound to jiffies or any other granularity. All the
+- kernel logic works at 64-bit nanoseconds resolution - no compromises.
+-
+-- simplification of existing, timing related kernel code
+-
+-another basic requirement was the immediate enqueueing and ordering of
+-timers at activation time. After looking at several possible solutions
+-such as radix trees and hashes, we chose the red black tree as the basic
+-data structure. Rbtrees are available as a library in the kernel and are
+-used in various performance-critical areas of e.g. memory management and
+-file systems. The rbtree is solely used for time sorted ordering, while
+-a separate list is used to give the expiry code fast access to the
+-queued timers, without having to walk the rbtree.
+-
+-(This separate list is also useful for later when we'll introduce
+-high-resolution clocks, where we need separate pending and expired
+-queues while keeping the time-order intact.)
+-
+-Time-ordered enqueueing is not purely for the purposes of
+-high-resolution clocks though, it also simplifies the handling of
+-absolute timers based on a low-resolution CLOCK_REALTIME. The existing
+-implementation needed to keep an extra list of all armed absolute
+-CLOCK_REALTIME timers along with complex locking. In case of
+-settimeofday and NTP, all the timers (!) had to be dequeued, the
+-time-changing code had to fix them up one by one, and all of them had to
+-be enqueued again. The time-ordered enqueueing and the storage of the
+-expiry time in absolute time units removes all this complex and poorly
+-scaling code from the posix-timer implementation - the clock can simply
+-be set without having to touch the rbtree. This also makes the handling
+-of posix-timers simpler in general.
+-
+-The locking and per-CPU behavior of hrtimers was mostly taken from the
+-existing timer wheel code, as it is mature and well suited. Sharing code
+-was not really a win, due to the different data structures. Also, the
+-hrtimer functions now have clearer behavior and clearer names - such as
+-hrtimer_try_to_cancel() and hrtimer_cancel() [which are roughly
+-equivalent to del_timer() and del_timer_sync()] - so there's no direct
+-1:1 mapping between them on the algorithmical level, and thus no real
+-potential for code sharing either.
+-
+-Basic data types: every time value, absolute or relative, is in a
+-special nanosecond-resolution type: ktime_t. The kernel-internal
+-representation of ktime_t values and operations is implemented via
+-macros and inline functions, and can be switched between a "hybrid
+-union" type and a plain "scalar" 64bit nanoseconds representation (at
+-compile time). The hybrid union type optimizes time conversions on 32bit
+-CPUs. This build-time-selectable ktime_t storage format was implemented
+-to avoid the performance impact of 64-bit multiplications and divisions
+-on 32bit CPUs. Such operations are frequently necessary to convert
+-between the storage formats provided by kernel and userspace interfaces
+-and the internal time format. (See include/linux/ktime.h for further
+-details.)
+-
+-hrtimers - rounding of timer values
+------------------------------------
+-
+-the hrtimer code will round timer events to lower-resolution clocks
+-because it has to. Otherwise it will do no artificial rounding at all.
+-
+-one question is, what resolution value should be returned to the user by
+-the clock_getres() interface. This will return whatever real resolution
+-a given clock has - be it low-res, high-res, or artificially-low-res.
+-
+-hrtimers - testing and verification
+-----------------------------------
+-
+-We used the high-resolution clock subsystem ontop of hrtimers to verify
+-the hrtimer implementation details in praxis, and we also ran the posix
+-timer tests in order to ensure specification compliance. We also ran
+-tests on low-resolution clocks.
+-
+-The hrtimer patch converts the following kernel functionality to use
+-hrtimers:
+-
+- - nanosleep
+- - itimers
+- - posix-timers
+-
+-The conversion of nanosleep and posix-timers enabled the unification of
+-nanosleep and clock_nanosleep.
+-
+-The code was successfully compiled for the following platforms:
+-
+- i386, x86_64, ARM, PPC, PPC64, IA64
+-
+-The code was run-tested on the following platforms:
+-
+- i386(UP/SMP), x86_64(UP/SMP), ARM, PPC
+-
+-hrtimers were also integrated into the -rt tree, along with a
+-hrtimers-based high-resolution clock implementation, so the hrtimers
+-code got a healthy amount of testing and use in practice.
+-
+- Thomas Gleixner, Ingo Molnar
+diff --git a/Documentation/i386/boot.txt b/Documentation/i386/boot.txt
+index fc49b79..2eb1610 100644
+--- a/Documentation/i386/boot.txt
++++ b/Documentation/i386/boot.txt
+@@ -170,6 +170,8 @@ Offset Proto Name Meaning
+ 0238/4 2.06+ cmdline_size Maximum size of the kernel command line
+ 023C/4 2.07+ hardware_subarch Hardware subarchitecture
+ 0240/8 2.07+ hardware_subarch_data Subarchitecture-specific data
++0248/4 2.08+ payload_offset Offset of kernel payload
++024C/4 2.08+ payload_length Length of kernel payload
+
+ (1) For backwards compatibility, if the setup_sects field contains 0, the
+ real value is 4.
+@@ -512,6 +514,32 @@ Protocol: 2.07+
+
+ A pointer to data that is specific to hardware subarch
+
++Field name: payload_offset
++Type: read
++Offset/size: 0x248/4
++Protocol: 2.08+
++
++ If non-zero then this field contains the offset from the end of the
++ real-mode code to the payload.
++
++ The payload may be compressed. The format of both the compressed and
++ uncompressed data should be determined using the standard magic
++ numbers. Currently only gzip compressed ELF is used.
++
++Field name: payload_length
++Type: read
++Offset/size: 0x24c/4
++Protocol: 2.08+
++
++ The length of the payload.
++
++**** THE IMAGE CHECKSUM
++
++From boot protocol version 2.08 onwards the CRC-32 is calculated over
++the entire file using the characteristic polynomial 0x04C11DB7 and an
++initial remainder of 0xffffffff. The checksum is appended to the
++file; therefore the CRC of the file up to the limit specified in the
++syssize field of the header is always 0.
+
+ **** THE KERNEL COMMAND LINE
+
+diff --git a/Documentation/ide/ide.txt b/Documentation/ide/ide.txt
+index 818676a..486c699 100644
+--- a/Documentation/ide/ide.txt
++++ b/Documentation/ide/ide.txt
+@@ -71,29 +71,6 @@ This driver automatically probes for most IDE interfaces (including all PCI
+ ones), for the drives/geometries attached to those interfaces, and for the IRQ
+ lines being used by the interfaces (normally 14, 15 for ide0/ide1).
+
+-For special cases, interfaces may be specified using kernel "command line"
+-options. For example,
+-
+- ide3=0x168,0x36e,10 /* ioports 0x168-0x16f,0x36e, irq 10 */
+-
+-Normally the irq number need not be specified, as ide.c will probe for it:
+-
+- ide3=0x168,0x36e /* ioports 0x168-0x16f,0x36e */
+-
+-The standard port, and irq values are these:
+-
+- ide0=0x1f0,0x3f6,14
+- ide1=0x170,0x376,15
+- ide2=0x1e8,0x3ee,11
+- ide3=0x168,0x36e,10
+-
+-Note that the first parameter reserves 8 contiguous ioports, whereas the
+-second value denotes a single ioport. If in doubt, do a 'cat /proc/ioports'.
+-
+-In all probability the device uses these ports and IRQs if it is attached
+-to the appropriate ide channel. Pass the parameter for the correct ide
+-channel to the kernel, as explained above.
+-
+ Any number of interfaces may share a single IRQ if necessary, at a slight
+ performance penalty, whether on separate cards or a single VLB card.
+ The IDE driver automatically detects and handles this. However, this may
+@@ -184,13 +161,6 @@ provided it is mounted with the default block size of 1024 (as above).
+ Please pass on any feedback on any of this stuff to the maintainer,
+ whose address can be found in linux/MAINTAINERS.
+
+-Note that if BOTH hd.c and ide.c are configured into the kernel,
+-hd.c will normally be allowed to control the primary IDE interface.
+-This is useful for older hardware that may be incompatible with ide.c,
+-and still allows newer hardware to run on the 2nd/3rd/4th IDE ports
+-under control of ide.c. To have ide.c also "take over" the primary
+-IDE port in this situation, use the "command line" parameter: ide0=0x1f0
+-
+ The IDE driver is modularized. The high level disk/CD-ROM/tape/floppy
+ drivers can always be compiled as loadable modules, the chipset drivers
+ can only be compiled into the kernel, and the core code (ide.c) can be
+@@ -206,7 +176,7 @@ When ide.c is used as a module, you can pass command line parameters to the
+ driver using the "options=" keyword to insmod, while replacing any ',' with
+ ';'. For example:
+
+- insmod ide.o options="ide0=serialize ide1=serialize ide2=0x1e8;0x3ee;11"
++ insmod ide.o options="hda=nodma hdb=nodma"
+
+
+ ================================================================================
+@@ -247,21 +217,11 @@ Summary of ide driver parameters for kernel command line
+ As for VLB, it is safest to not specify it.
+ Bigger values are safer than smaller ones.
+
+- "idex=base" : probe for an interface at the addr specified,
+- where "base" is usually 0x1f0 or 0x170
+- and "ctl" is assumed to be "base"+0x206
+-
+- "idex=base,ctl" : specify both base and ctl
+-
+- "idex=base,ctl,irq" : specify base, ctl, and irq number
+-
+ "idex=serialize" : do not overlap operations on idex. Please note
+ that you will have to specify this option for
+ both the respective primary and secondary channel
+ to take effect.
+
+- "idex=four" : four drives on idex and ide(x^1) share same ports
+-
+ "idex=reset" : reset interface after probe
+
+ "idex=ata66" : informs the interface that it has an 80c cable
+@@ -269,8 +229,6 @@ Summary of ide driver parameters for kernel command line
+ ability to bit test for detection is currently
+ unknown.
+
+- "ide=reverse" : formerly called to pci sub-system, but now local.
+-
+ "ide=doubler" : probe/support IDE doublers on Amiga
+
+ There may be more options than shown -- use the source, Luke!
+@@ -290,6 +248,9 @@ Also for legacy CMD640 host driver (cmd640) you need to use "probe_vlb"
+ kernel paremeter to enable probing for VLB version of the chipset (PCI ones
+ are detected automatically).
+
++You also need to use "probe" kernel parameter for ide-4drives driver
++(support for IDE generic chipset with four drives on one port).
++
+ ================================================================================
+
+ Some Terminology
+diff --git a/Documentation/ide/warm-plug-howto.txt b/Documentation/ide/warm-plug-howto.txt
+new file mode 100644
+index 0000000..d588546
+--- /dev/null
++++ b/Documentation/ide/warm-plug-howto.txt
+@@ -0,0 +1,13 @@
++
++IDE warm-plug HOWTO
++===================
++
++To warm-plug devices on a port 'idex':
++
++# echo -n "1" > /sys/class/ide_port/idex/delete_devices
++
++unplug old device(s) and plug new device(s)
++
++# echo -n "1" > /sys/class/ide_port/idex/scan
++
++done
+diff --git a/Documentation/kbuild/modules.txt b/Documentation/kbuild/modules.txt
+index 1d247d5..1821c07 100644
+--- a/Documentation/kbuild/modules.txt
++++ b/Documentation/kbuild/modules.txt
+@@ -486,7 +486,7 @@ Module.symvers contains a list of all exported symbols from a kernel build.
+ Sometimes, an external module uses exported symbols from another
+ external module. Kbuild needs to have full knowledge on all symbols
+ to avoid spitting out warnings about undefined symbols.
+- Two solutions exist to let kbuild know all symbols of more than
++ Three solutions exist to let kbuild know all symbols of more than
+ one external module.
+ The method with a top-level kbuild file is recommended but may be
+ impractical in certain situations.
+@@ -523,6 +523,13 @@ Module.symvers contains a list of all exported symbols from a kernel build.
+ containing the sum of all symbols defined and not part of the
+ kernel.
+
++ Use make variable KBUILD_EXTRA_SYMBOLS in the Makefile
++ If it is impractical to copy Module.symvers from another
++ module, you can assign a space separated list of files to
++ KBUILD_EXTRA_SYMBOLS in your Makfile. These files will be
++ loaded by modpost during the initialisation of its symbol
++ tables.
++
+ === 8. Tips & Tricks
+
+ --- 8.1 Testing for CONFIG_FOO_BAR
+diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
+index dafd001..bf6303e 100644
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -366,6 +366,12 @@ and is between 256 and 4096 characters. It is defined in the file
+ possible to determine what the correct size should be.
+ This option provides an override for these situations.
+
++ security= [SECURITY] Choose a security module to enable at boot.
++ If this boot parameter is not specified, only the first
++ security module asking for security registration will be
++ loaded. An invalid security module name will be treated
++ as if no module has been chosen.
++
+ capability.disable=
+ [SECURITY] Disable capabilities. This would normally
+ be used only if an alternative security model is to be
+@@ -763,11 +769,11 @@ and is between 256 and 4096 characters. It is defined in the file
+ Format: <io>[,<membase>[,<icn_id>[,<icn_id2>]]]
+
+ ide= [HW] (E)IDE subsystem
+- Format: ide=nodma or ide=doubler or ide=reverse
++ Format: ide=nodma or ide=doubler
+ See Documentation/ide/ide.txt.
+
+ ide?= [HW] (E)IDE subsystem
+- Format: ide?=noprobe or chipset specific parameters.
++ Format: ide?=ata66 or chipset specific parameters.
+ See Documentation/ide/ide.txt.
+
+ idebus= [HW] (E)IDE subsystem - VLB/PCI bus speed
+@@ -812,6 +818,19 @@ and is between 256 and 4096 characters. It is defined in the file
+
+ inttest= [IA64]
+
++ iommu= [x86]
++ off
++ force
++ noforce
++ biomerge
++ panic
++ nopanic
++ merge
++ nomerge
++ forcesac
++ soft
++
++
+ intel_iommu= [DMAR] Intel IOMMU driver (DMAR) option
+ off
+ Disable intel iommu driver.
+@@ -828,6 +847,10 @@ and is between 256 and 4096 characters. It is defined in the file
+ than 32 bit addressing. The default is to look
+ for translation below 32 bit and if not available
+ then look in the higher range.
++ strict [Default Off]
++ With this option on every unmap_single operation will
++ result in a hardware IOTLB flush operation as opposed
++ to batching them for performance.
+
+ io_delay= [X86-32,X86-64] I/O delay method
+ 0x80
+@@ -928,8 +951,15 @@ and is between 256 and 4096 characters. It is defined in the file
+ kstack=N [X86-32,X86-64] Print N words from the kernel stack
+ in oops dumps.
+
++ kgdboc= [HW] kgdb over consoles.
++ Requires a tty driver that supports console polling.
++ (only serial suported for now)
++ Format: <serial_device>[,baud]
++
+ l2cr= [PPC]
+
++ l3cr= [PPC]
++
+ lapic [X86-32,APIC] Enable the local APIC even if BIOS
+ disabled it.
+
+@@ -1134,6 +1164,11 @@ and is between 256 and 4096 characters. It is defined in the file
+ or
+ memmap=0x10000$0x18690000
+
++ memtest= [KNL,X86_64] Enable memtest
++ Format: <integer>
++ range: 0,4 : pattern number
++ default : 0 <disable>
++
+ meye.*= [HW] Set MotionEye Camera parameters
+ See Documentation/video4linux/meye.txt.
+
+@@ -1251,8 +1286,16 @@ and is between 256 and 4096 characters. It is defined in the file
+ noexec [IA-64]
+
+ noexec [X86-32,X86-64]
++ On X86-32 available only on PAE configured kernels.
+ noexec=on: enable non-executable mappings (default)
+- noexec=off: disable nn-executable mappings
++ noexec=off: disable non-executable mappings
++
++ noexec32 [X86-64]
++ This affects only 32-bit executables.
++ noexec32=on: enable non-executable mappings (default)
++ read doesn't imply executable mappings
++ noexec32=off: disable non-executable mappings
++ read implies executable mappings
+
+ nofxsr [BUGS=X86-32] Disables x86 floating point extended
+ register save and restore. The kernel will only save
+@@ -1339,6 +1382,10 @@ and is between 256 and 4096 characters. It is defined in the file
+
+ nowb [ARM]
+
++ nptcg= [IA64] Override max number of concurrent global TLB
++ purges which is reported from either PAL_VM_SUMMARY or
++ SAL PALO.
++
+ numa_zonelist_order= [KNL, BOOT] Select zonelist order for NUMA.
+ one of ['zone', 'node', 'default'] can be specified
+ This can be set from sysctl after boot.
+@@ -1428,10 +1475,6 @@ and is between 256 and 4096 characters. It is defined in the file
+ nomsi [MSI] If the PCI_MSI kernel config parameter is
+ enabled, this kernel boot option can be used to
+ disable the use of MSI interrupts system-wide.
+- nosort [X86-32] Don't sort PCI devices according to
+- order given by the PCI BIOS. This sorting is
+- done to get a device order compatible with
+- older kernels.
+ biosirq [X86-32] Use PCI BIOS calls to get the interrupt
+ routing table. These calls are known to be buggy
+ on several machines and they hang the machine
+diff --git a/Documentation/laptops/acer-wmi.txt b/Documentation/laptops/acer-wmi.txt
+index 23df051..79b7dbd 100644
+--- a/Documentation/laptops/acer-wmi.txt
++++ b/Documentation/laptops/acer-wmi.txt
+@@ -80,7 +80,7 @@ once you enable the radio, will depend on your hardware and driver combination.
+ e.g. With the BCM4318 on the Acer Aspire 5020 series:
+
+ ndiswrapper: Light blinks on when transmitting
+-bcm43xx/b43: Solid light, blinks off when transmitting
++b43: Solid light, blinks off when transmitting
+
+ Wireless radio control is unconditionally enabled - all Acer laptops that support
+ acer-wmi come with built-in wireless. However, should you feel so inclined to
+diff --git a/Documentation/leds-class.txt b/Documentation/leds-class.txt
+index 56757c7..18860ad 100644
+--- a/Documentation/leds-class.txt
++++ b/Documentation/leds-class.txt
+@@ -19,6 +19,12 @@ optimises away.
+
+ Complex triggers whilst available to all LEDs have LED specific
+ parameters and work on a per LED basis. The timer trigger is an example.
++The timer trigger will periodically change the LED brightness between
++LED_OFF and the current brightness setting. The "on" and "off" time can
++be specified via /sys/class/leds/<device>/delay_{on,off} in milliseconds.
++You can change the brightness value of a LED independently of the timer
++trigger. However, if you set the brightness value to LED_OFF it will
++also disable the timer trigger.
+
+ You can change triggers in a similar manner to the way an IO scheduler
+ is chosen (via /sys/class/leds/<device>/trigger). Trigger specific
+@@ -63,9 +69,9 @@ value if it is called with *delay_on==0 && *delay_off==0 parameters. In
+ this case the driver should give back the chosen value through delay_on
+ and delay_off parameters to the leds subsystem.
+
+-Any call to the brightness_set() callback function should cancel the
+-previously programmed hardware blinking function so setting the brightness
+-to 0 can also cancel the blinking of the LED.
++Setting the brightness to zero with brightness_set() callback function
++should completely turn off the LED and cancel the previously programmed
++hardware blinking function, if any.
+
+
+ Known Issues
+diff --git a/Documentation/magic-number.txt b/Documentation/magic-number.txt
+index bd450e7..9507002 100644
+--- a/Documentation/magic-number.txt
++++ b/Documentation/magic-number.txt
+@@ -95,7 +95,6 @@ RFCOMM_TTY_MAGIC 0x6d02 net/bluetooth/rfcomm/tty.c
+ USB_SERIAL_PORT_MAGIC 0x7301 usb_serial_port drivers/usb/serial/usb-serial.h
+ CG_MAGIC 0x00090255 ufs_cylinder_group include/linux/ufs_fs.h
+ A2232_MAGIC 0x000a2232 gs_port drivers/char/ser_a2232.h
+-SOLARIS_SOCKET_MAGIC 0x000ADDED sol_socket_struct arch/sparc64/solaris/socksys.h
+ RPORT_MAGIC 0x00525001 r_port drivers/char/rocket_int.h
+ LSEMAGIC 0x05091998 lse drivers/fc4/fc.c
+ GDTIOCTL_MAGIC 0x06030f07 gdth_iowr_str drivers/scsi/gdth_ioctl.h
+diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
+index 1f506f7..e5a819a 100644
+--- a/Documentation/memory-barriers.txt
++++ b/Documentation/memory-barriers.txt
+@@ -430,8 +430,8 @@ There are certain things that the Linux kernel memory barriers do not guarantee:
+
+ [*] For information on bus mastering DMA and coherency please read:
+
+- Documentation/pci.txt
+- Documentation/DMA-mapping.txt
++ Documentation/PCI/pci.txt
++ Documentation/PCI/PCI-DMA-mapping.txt
+ Documentation/DMA-API.txt
+
+
+diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX
+index c485ee0..1634c6d 100644
+--- a/Documentation/networking/00-INDEX
++++ b/Documentation/networking/00-INDEX
+@@ -100,8 +100,6 @@ tuntap.txt
+ - TUN/TAP device driver, allowing user space Rx/Tx of packets.
+ vortex.txt
+ - info on using 3Com Vortex (3c590, 3c592, 3c595, 3c597) Ethernet cards.
+-wan-router.txt
+- - WAN router documentation
+ wavelan.txt
+ - AT&T GIS (nee NCR) WaveLAN card: An Ethernet-like radio transceiver
+ x25.txt
+diff --git a/Documentation/networking/bcm43xx.txt b/Documentation/networking/bcm43xx.txt
+deleted file mode 100644
+index d602c8d..0000000
+--- a/Documentation/networking/bcm43xx.txt
++++ /dev/null
+@@ -1,89 +0,0 @@
+-
+- BCM43xx Linux Driver Project
+- ============================
+-
+-Introduction
+-------------
+-
+-Many of the wireless devices found in modern notebook computers are
+-based on the wireless chips produced by Broadcom. These devices have
+-been a problem for Linux users as there is no open-source driver
+-available. In addition, Broadcom has not released specifications
+-for the device, and driver availability has been limited to the
+-binary-only form used in the GPL versions of AP hardware such as the
+-Linksys WRT54G, and the Windows and OS X drivers. Before this project
+-began, the only way to use these devices were to use the Windows or
+-OS X drivers with either the Linuxant or ndiswrapper modules. There
+-is a strong penalty if this method is used as loading the binary-only
+-module "taints" the kernel, and no kernel developer will help diagnose
+-any kernel problems.
+-
+-Development
+------------
+-
+-This driver has been developed using
+-a clean-room technique that is described at
+-http://bcm-specs.sipsolutions.net/ReverseEngineeringProcess. For legal
+-reasons, none of the clean-room crew works on the on the Linux driver,
+-and none of the Linux developers sees anything but the specifications,
+-which are the ultimate product of the reverse-engineering group.
+-
+-Software
+---------
+-
+-Since the release of the 2.6.17 kernel, the bcm43xx driver has been
+-distributed with the kernel source, and is prebuilt in most, if not
+-all, distributions. There is, however, additional software that is
+-required. The firmware used by the chip is the intellectual property
+-of Broadcom and they have not given the bcm43xx team redistribution
+-rights to this firmware. Since we cannot legally redistribute
+-the firmware we cannot include it with the driver. Furthermore, it
+-cannot be placed in the downloadable archives of any distributing
+-organization; therefore, the user is responsible for obtaining the
+-firmware and placing it in the appropriate location so that the driver
+-can find it when initializing.
+-
+-To help with this process, the bcm43xx developers provide a separate
+-program named bcm43xx-fwcutter to "cut" the firmware out of a
+-Windows or OS X driver and write the extracted files to the proper
+-location. This program is usually provided with the distribution;
+-however, it may be downloaded from
+-
+-http://developer.berlios.de/project/showfiles.php?group_id=4547
+-
+-The firmware is available in two versions. V3 firmware is used with
+-the in-kernel bcm43xx driver that uses a software MAC layer called
+-SoftMAC, and will have a microcode revision of 0x127 or smaller. The
+-V4 firmware is used by an out-of-kernel driver employing a variation of
+-the Devicescape MAC layer known as d80211. Once bcm43xx-d80211 reaches
+-a satisfactory level of development, it will replace bcm43xx-softmac
+-in the kernel as it is much more flexible and powerful.
+-
+-A source for the latest V3 firmware is
+-
+-http://downloads.openwrt.org/sources/wl_apsta-3.130.20.0.o
+-
+-Once this file is downloaded, the command
+-'bcm43xx-fwcutter -w <dir> <filename>'
+-will extract the microcode and write it to directory
+-<dir>. The correct directory will depend on your distribution;
+-however, most use '/lib/firmware'. Once this step is completed,
+-the bcm3xx driver should load when the system is booted. To see
+-any messages relating to the driver, issue the command 'dmesg |
+-grep bcm43xx' from a terminal window. If there are any problems,
+-please send that output to Bcm43xx-dev at lists.berlios.de.
+-
+-Although the driver has been in-kernel since 2.6.17, the earliest
+-version is quite limited in its capability. Patches that include
+-all features of later versions are available for the stable kernel
+-versions from 2.6.18. These will be needed if you use a BCM4318,
+-or a PCI Express version (BCM4311 and BCM4312). In addition, if you
+-have an early BCM4306 and more than 1 GB RAM, your kernel will need
+-to be patched. These patches, which are being updated regularly,
+-are available at ftp://lwfinger.dynalias.org/patches. Look for
+-combined_2.6.YY.patch. Of course you will need kernel source downloaded
+-from kernel.org, or the source from your distribution.
+-
+-If you build your own kernel, please enable CONFIG_BCM43XX_DEBUG
+-and CONFIG_IEEE80211_SOFTMAC_DEBUG. The log information provided is
+-essential for solving any problems.
+diff --git a/Documentation/networking/phy.txt b/Documentation/networking/phy.txt
+index 0bc95ea..8df6a7b 100644
+--- a/Documentation/networking/phy.txt
++++ b/Documentation/networking/phy.txt
+@@ -1,7 +1,7 @@
+
+ -------
+ PHY Abstraction Layer
+-(Updated 2006-11-30)
++(Updated 2008-04-08)
+
+ Purpose
+
+@@ -291,3 +291,39 @@ Writing a PHY driver
+ Feel free to look at the Marvell, Cicada, and Davicom drivers in
+ drivers/net/phy/ for examples (the lxt and qsemi drivers have
+ not been tested as of this writing)
++
++Board Fixups
++
++ Sometimes the specific interaction between the platform and the PHY requires
++ special handling. For instance, to change where the PHY's clock input is,
++ or to add a delay to account for latency issues in the data path. In order
++ to support such contingencies, the PHY Layer allows platform code to register
++ fixups to be run when the PHY is brought up (or subsequently reset).
++
++ When the PHY Layer brings up a PHY it checks to see if there are any fixups
++ registered for it, matching based on UID (contained in the PHY device's phy_id
++ field) and the bus identifier (contained in phydev->dev.bus_id). Both must
++ match, however two constants, PHY_ANY_ID and PHY_ANY_UID, are provided as
++ wildcards for the bus ID and UID, respectively.
++
++ When a match is found, the PHY layer will invoke the run function associated
++ with the fixup. This function is passed a pointer to the phy_device of
++ interest. It should therefore only operate on that PHY.
++
++ The platform code can either register the fixup using phy_register_fixup():
++
++ int phy_register_fixup(const char *phy_id,
++ u32 phy_uid, u32 phy_uid_mask,
++ int (*run)(struct phy_device *));
++
++ Or using one of the two stubs, phy_register_fixup_for_uid() and
++ phy_register_fixup_for_id():
++
++ int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask,
++ int (*run)(struct phy_device *));
++ int phy_register_fixup_for_id(const char *phy_id,
++ int (*run)(struct phy_device *));
++
++ The stubs set one of the two matching criteria, and set the other one to
++ match anything.
++
+diff --git a/Documentation/networking/wan-router.txt b/Documentation/networking/wan-router.txt
+deleted file mode 100644
+index bc2ab41..0000000
+--- a/Documentation/networking/wan-router.txt
++++ /dev/null
+@@ -1,621 +0,0 @@
+-------------------------------------------------------------------------------
+-Linux WAN Router Utilities Package
+-------------------------------------------------------------------------------
+-Version 2.2.1
+-Mar 28, 2001
+-Author: Nenad Corbic <ncorbic at sangoma.com>
+-Copyright (c) 1995-2001 Sangoma Technologies Inc.
+-------------------------------------------------------------------------------
+-
+-INTRODUCTION
+-
+-Wide Area Networks (WANs) are used to interconnect Local Area Networks (LANs)
+-and/or stand-alone hosts over vast distances with data transfer rates
+-significantly higher than those achievable with commonly used dial-up
+-connections.
+-
+-Usually an external device called `WAN router' sitting on your local network
+-or connected to your machine's serial port provides physical connection to
+-WAN. Although router's job may be as simple as taking your local network
+-traffic, converting it to WAN format and piping it through the WAN link, these
+-devices are notoriously expensive, with prices as much as 2 - 5 times higher
+-then the price of a typical PC box.
+-
+-Alternatively, considering robustness and multitasking capabilities of Linux,
+-an internal router can be built (most routers use some sort of stripped down
+-Unix-like operating system anyway). With a number of relatively inexpensive WAN
+-interface cards available on the market, a perfectly usable router can be
+-built for less than half a price of an external router. Yet a Linux box
+-acting as a router can still be used for other purposes, such as fire-walling,
+-running FTP, WWW or DNS server, etc.
+-
+-This kernel module introduces the notion of a WAN Link Driver (WLD) to Linux
+-operating system and provides generic hardware-independent services for such
+-drivers. Why can existing Linux network device interface not be used for
+-this purpose? Well, it can. However, there are a few key differences between
+-a typical network interface (e.g. Ethernet) and a WAN link.
+-
+-Many WAN protocols, such as X.25 and frame relay, allow for multiple logical
+-connections (known as `virtual circuits' in X.25 terminology) over a single
+-physical link. Each such virtual circuit may (and almost always does) lead
+-to a different geographical location and, therefore, different network. As a
+-result, it is the virtual circuit, not the physical link, that represents a
+-route and, therefore, a network interface in Linux terms.
+-
+-To further complicate things, virtual circuits are usually volatile in nature
+-(excluding so called `permanent' virtual circuits or PVCs). With almost no
+-time required to set up and tear down a virtual circuit, it is highly desirable
+-to implement on-demand connections in order to minimize network charges. So
+-unlike a typical network driver, the WAN driver must be able to handle multiple
+-network interfaces and cope as multiple virtual circuits come into existence
+-and go away dynamically.
+-
+-Last, but not least, WAN configuration is much more complex than that of say
+-Ethernet and may well amount to several dozens of parameters. Some of them
+-are "link-wide" while others are virtual circuit-specific. The same holds
+-true for WAN statistics which is by far more extensive and extremely useful
+-when troubleshooting WAN connections. Extending the ifconfig utility to suit
+-these needs may be possible, but does not seem quite reasonable. Therefore, a
+-WAN configuration utility and corresponding application programmer's interface
+-is needed for this purpose.
+-
+-Most of these problems are taken care of by this module. Its goal is to
+-provide a user with more-or-less standard look and feel for all WAN devices and
+-assist a WAN device driver writer by providing common services, such as:
+-
+- o User-level interface via /proc file system
+- o Centralized configuration
+- o Device management (setup, shutdown, etc.)
+- o Network interface management (dynamic creation/destruction)
+- o Protocol encapsulation/decapsulation
+-
+-To ba able to use the Linux WAN Router you will also need a WAN Tools package
+-available from
+-
+- ftp.sangoma.com/pub/linux/current_wanpipe/wanpipe-X.Y.Z.tgz
+-
+-where vX.Y.Z represent the wanpipe version number.
+-
+-For technical questions and/or comments please e-mail to ncorbic at sangoma.com.
+-For general inquiries please contact Sangoma Technologies Inc. by
+-
+- Hotline: 1-800-388-2475 (USA and Canada, toll free)
+- Phone: (905) 474-1990 ext: 106
+- Fax: (905) 474-9223
+- E-mail: dm at sangoma.com (David Mandelstam)
+- WWW: http://www.sangoma.com
+-
+-
+-INSTALLATION
+-
+-Please read the WanpipeForLinux.pdf manual on how to
+-install the WANPIPE tools and drivers properly.
+-
+-
+-After installing wanpipe package: /usr/local/wanrouter/doc.
+-On the ftp.sangoma.com : /linux/current_wanpipe/doc
+-
+-
+-COPYRIGHT AND LICENSING INFORMATION
+-
+-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, or (at your option) any later version.
+-
+-This program is distributed in the hope that it will be useful, but WITHOUT
+-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+-
+-You should have received a copy of the GNU General Public License along with
+-this program; if not, write to the Free Software Foundation, Inc., 675 Mass
+-Ave, Cambridge, MA 02139, USA.
+-
+-
+-
+-ACKNOWLEDGEMENTS
+-
+-This product is based on the WANPIPE(tm) Multiprotocol WAN Router developed
+-by Sangoma Technologies Inc. for Linux 2.0.x and 2.2.x. Success of the WANPIPE
+-together with the next major release of Linux kernel in summer 1996 commanded
+-adequate changes to the WANPIPE code to take full advantage of new Linux
+-features.
+-
+-Instead of continuing developing proprietary interface tied to Sangoma WAN
+-cards, we decided to separate all hardware-independent code into a separate
+-module and defined two levels of interfaces - one for user-level applications
+-and another for kernel-level WAN drivers. WANPIPE is now implemented as a
+-WAN driver compliant with the WAN Link Driver interface. Also a general
+-purpose WAN configuration utility and a set of shell scripts was developed to
+-support WAN router at the user level.
+-
+-Many useful ideas concerning hardware-independent interface implementation
+-were given by Mike McLagan <mike.mclagan at linux.org> and his implementation
+-of the Frame Relay router and drivers for Sangoma cards (dlci/sdla).
+-
+-With the new implementation of the APIs being incorporated into the WANPIPE,
+-a special thank goes to Alan Cox in providing insight into BSD sockets.
+-
+-Special thanks to all the WANPIPE users who performed field-testing, reported
+-bugs and made valuable comments and suggestions that help us to improve this
+-product.
+-
+-
+-
+-NEW IN THIS RELEASE
+-
+- o Updated the WANCFG utility
+- Calls the pppconfig to configure the PPPD
+- for async connections.
+-
+- o Added the PPPCONFIG utility
+- Used to configure the PPPD daemon for the
+- WANPIPE Async PPP and standard serial port.
+- The wancfg calls the pppconfig to configure
+- the pppd.
+-
+- o Fixed the PCI autodetect feature.
+- The SLOT 0 was used as an autodetect option
+- however, some high end PC's slot numbers start
+- from 0.
+-
+- o This release has been tested with the new backupd
+- daemon release.
+-
+-
+-PRODUCT COMPONENTS AND RELATED FILES
+-
+-/etc: (or user defined)
+- wanpipe1.conf default router configuration file
+-
+-/lib/modules/X.Y.Z/misc:
+- wanrouter.o router kernel loadable module
+- af_wanpipe.o wanpipe api socket module
+-
+-/lib/modules/X.Y.Z/net:
+- sdladrv.o Sangoma SDLA support module
+- wanpipe.o Sangoma WANPIPE(tm) driver module
+-
+-/proc/net/wanrouter
+- Config reads current router configuration
+- Status reads current router status
+- {name} reads WAN driver statistics
+-
+-/usr/sbin:
+- wanrouter wanrouter start-up script
+- wanconfig wanrouter configuration utility
+- sdladump WANPIPE adapter memory dump utility
+- fpipemon Monitor for Frame Relay
+- cpipemon Monitor for Cisco HDLC
+- ppipemon Monitor for PPP
+- xpipemon Monitor for X25
+- wpkbdmon WANPIPE keyboard led monitor/debugger
+-
+-/usr/local/wanrouter:
+- README this file
+- COPYING GNU General Public License
+- Setup installation script
+- Filelist distribution definition file
+- wanrouter.rc meta-configuration file
+- (used by the Setup and wanrouter script)
+-
+-/usr/local/wanrouter/doc:
+- wanpipeForLinux.pdf WAN Router User's Manual
+-
+-/usr/local/wanrouter/patches:
+- wanrouter-v2213.gz patch for Linux kernels 2.2.11 up to 2.2.13.
+- wanrouter-v2214.gz patch for Linux kernel 2.2.14.
+- wanrouter-v2215.gz patch for Linux kernels 2.2.15 to 2.2.17.
+- wanrouter-v2218.gz patch for Linux kernels 2.2.18 and up.
+- wanrouter-v240.gz patch for Linux kernel 2.4.0.
+- wanrouter-v242.gz patch for Linux kernel 2.4.2 and up.
+- wanrouter-v2034.gz patch for Linux kernel 2.0.34
+- wanrouter-v2036.gz patch for Linux kernel 2.0.36 and up.
+-
+-/usr/local/wanrouter/patches/kdrivers:
+- Sources of the latest WANPIPE device drivers.
+- These are used to UPGRADE the linux kernel to the newest
+- version if the kernel source has already been patched with
+- WANPIPE drivers.
+-
+-/usr/local/wanrouter/samples:
+- interface sample interface configuration file
+- wanpipe1.cpri CHDLC primary port
+- wanpipe2.csec CHDLC secondary port
+- wanpipe1.fr Frame Relay protocol
+- wanpipe1.ppp PPP protocol )
+- wanpipe1.asy CHDLC ASYNC protocol
+- wanpipe1.x25 X25 protocol
+- wanpipe1.stty Sync TTY driver (Used by Kernel PPPD daemon)
+- wanpipe1.atty Async TTY driver (Used by Kernel PPPD daemon)
+- wanrouter.rc sample meta-configuration file
+-
+-/usr/local/wanrouter/util:
+- * wan-tools utilities source code
+-
+-/usr/local/wanrouter/api/x25:
+- * x25 api sample programs.
+-/usr/local/wanrouter/api/chdlc:
+- * chdlc api sample programs.
+-/usr/local/wanrouter/api/fr:
+- * fr api sample programs.
+-/usr/local/wanrouter/config/wancfg:
+- wancfg WANPIPE GUI configuration program.
+- Creates wanpipe#.conf files.
+-/usr/local/wanrouter/config/cfgft1:
+- cfgft1 GUI CSU/DSU configuration program.
+-
+-/usr/include/linux:
+- wanrouter.h router API definitions
+- wanpipe.h WANPIPE API definitions
+- sdladrv.h SDLA support module API definitions
+- sdlasfm.h SDLA firmware module definitions
+- if_wanpipe.h WANPIPE Socket definitions
+- sdlapci.h WANPIPE PCI definitions
+-
+-
+-/usr/src/linux/net/wanrouter:
+- * wanrouter source code
+-
+-/var/log:
+- wanrouter wanrouter start-up log (created by the Setup script)
+-
+-/var/lock: (or /var/lock/subsys for RedHat)
+- wanrouter wanrouter lock file (created by the Setup script)
+-
+-/usr/local/wanrouter/firmware:
+- fr514.sfm Frame relay firmware for Sangoma S508/S514 card
+- cdual514.sfm Dual Port Cisco HDLC firmware for Sangoma S508/S514 card
+- ppp514.sfm PPP Firmware for Sangoma S508 and S514 cards
+- x25_508.sfm X25 Firmware for Sangoma S508 card.
+-
+-
+-REVISION HISTORY
+-
+-1.0.0 December 31, 1996 Initial version
+-
+-1.0.1 January 30, 1997 Status and statistics can be read via /proc
+- filesystem entries.
+-
+-1.0.2 April 30, 1997 Added UDP management via monitors.
+-
+-1.0.3 June 3, 1997 UDP management for multiple boards using Frame
+- Relay and PPP
+- Enabled continuous transmission of Configure
+- Request Packet for PPP (for 508 only)
+- Connection Timeout for PPP changed from 900 to 0
+- Flow Control Problem fixed for Frame Relay
+-
+-1.0.4 July 10, 1997 S508/FT1 monitoring capability in fpipemon and
+- ppipemon utilities.
+- Configurable TTL for UDP packets.
+- Multicast and Broadcast IP source addresses are
+- silently discarded.
+-
+-1.0.5 July 28, 1997 Configurable T391,T392,N391,N392,N393 for Frame
+- Relay in router.conf.
+- Configurable Memory Address through router.conf
+- for Frame Relay, PPP and X.25. (commenting this
+- out enables auto-detection).
+- Fixed freeing up received buffers using kfree()
+- for Frame Relay and X.25.
+- Protect sdla_peek() by calling save_flags(),
+- cli() and restore_flags().
+- Changed number of Trace elements from 32 to 20
+- Added DLCI specific data monitoring in FPIPEMON.
+-2.0.0 Nov 07, 1997 Implemented protection of RACE conditions by
+- critical flags for FRAME RELAY and PPP.
+- DLCI List interrupt mode implemented.
+- IPX support in FRAME RELAY and PPP.
+- IPX Server Support (MARS)
+- More driver specific stats included in FPIPEMON
+- and PIPEMON.
+-
+-2.0.1 Nov 28, 1997 Bug Fixes for version 2.0.0.
+- Protection of "enable_irq()" while
+- "disable_irq()" has been enabled from any other
+- routine (for Frame Relay, PPP and X25).
+- Added additional Stats for Fpipemon and Ppipemon
+- Improved Load Sharing for multiple boards
+-
+-2.0.2 Dec 09, 1997 Support for PAP and CHAP for ppp has been
+- implemented.
+-
+-2.0.3 Aug 15, 1998 New release supporting Cisco HDLC, CIR for Frame
+- relay, Dynamic IP assignment for PPP and Inverse
+- Arp support for Frame-relay. Man Pages are
+- included for better support and a new utility
+- for configuring FT1 cards.
+-
+-2.0.4 Dec 09, 1998 Dual Port support for Cisco HDLC.
+- Support for HDLC (LAPB) API.
+- Supports BiSync Streaming code for S502E
+- and S503 cards.
+- Support for Streaming HDLC API.
+- Provides a BSD socket interface for
+- creating applications using BiSync
+- streaming.
+-
+-2.0.5 Aug 04, 1999 CHDLC initialization bug fix.
+- PPP interrupt driven driver:
+- Fix to the PPP line hangup problem.
+- New PPP firmware
+- Added comments to the startup SYSTEM ERROR messages
+- Xpipemon debugging application for the X25 protocol
+- New USER_MANUAL.txt
+- Fixed the odd boundary 4byte writes to the board.
+- BiSync Streaming code has been taken out.
+- Available as a patch.
+- Streaming HDLC API has been taken out.
+- Available as a patch.
+-
+-2.0.6 Aug 17, 1999 Increased debugging in statup scripts
+- Fixed installation bugs from 2.0.5
+- Kernel patch works for both 2.2.10 and 2.2.11 kernels.
+- There is no functional difference between the two packages
+-
+-2.0.7 Aug 26, 1999 o Merged X25API code into WANPIPE.
+- o Fixed a memory leak for X25API
+- o Updated the X25API code for 2.2.X kernels.
+- o Improved NEM handling.
+-
+-2.1.0 Oct 25, 1999 o New code for S514 PCI Card
+- o New CHDLC and Frame Relay drivers
+- o PPP and X25 are not supported in this release
+-
+-2.1.1 Nov 30, 1999 o PPP support for S514 PCI Cards
+-
+-2.1.3 Apr 06, 2000 o Socket based x25api
+- o Socket based chdlc api
+- o Socket based fr api
+- o Dual Port Receive only CHDLC support.
+- o Asynchronous CHDLC support (Secondary Port)
+- o cfgft1 GUI csu/dsu configurator
+- o wancfg GUI configuration file
+- configurator.
+- o Architectural directory changes.
+-
+-beta-2.1.4 Jul 2000 o Dynamic interface configuration:
+- Network interfaces reflect the state
+- of protocol layer. If the protocol becomes
+- disconnected, driver will bring down
+- the interface. Once the protocol reconnects
+- the interface will be brought up.
+-
+- Note: This option is turned off by default.
+-
+- o Dynamic wanrouter setup using 'wanconfig':
+- wanconfig utility can be used to
+- shutdown,restart,start or reconfigure
+- a virtual circuit dynamically.
+-
+- Frame Relay: Each DLCI can be:
+- created,stopped,restarted and reconfigured
+- dynamically using wanconfig.
+-
+- ex: wanconfig card wanpipe1 dev wp1_fr16 up
+-
+- o Wanrouter startup via command line arguments:
+- wanconfig also supports wanrouter startup via command line
+- arguments. Thus, there is no need to create a wanpipe#.conf
+- configuration file.
+-
+- o Socket based x25api update/bug fixes.
+- Added support for LCN numbers greater than 255.
+- Option to pass up modem messages.
+- Provided a PCI IRQ check, so a single S514
+- card is guaranteed to have a non-sharing interrupt.
+-
+- o Fixes to the wancfg utility.
+- o New FT1 debugging support via *pipemon utilities.
+- o Frame Relay ARP support Enabled.
+-
+-beta3-2.1.4 Jul 2000 o X25 M_BIT Problem fix.
+- o Added the Multi-Port PPP
+- Updated utilities for the Multi-Port PPP.
+-
+-2.1.4 Aut 2000
+- o In X25API:
+- Maximum packet an application can send
+- to the driver has been extended to 4096 bytes.
+-
+- Fixed the x25 startup bug. Enable
+- communications only after all interfaces
+- come up. HIGH SVC/PVC is used to calculate
+- the number of channels.
+- Enable protocol only after all interfaces
+- are enabled.
+-
+- o Added an extra state to the FT1 config, kernel module.
+- o Updated the pipemon debuggers.
+-
+- o Blocked the Multi-Port PPP from running on kernels
+- 2.2.16 or greater, due to syncppp kernel module
+- change.
+-
+-beta1-2.1.5 Nov 15 2000
+- o Fixed the MultiPort PPP Support for kernels 2.2.16 and above.
+- 2.2.X kernels only
+-
+- o Secured the driver UDP debugging calls
+- - All illegal network debugging calls are reported to
+- the log.
+- - Defined a set of allowed commands, all other denied.
+-
+- o Cpipemon
+- - Added set FT1 commands to the cpipemon. Thus CSU/DSU
+- configuration can be performed using cpipemon.
+- All systems that cannot run cfgft1 GUI utility should
+- use cpipemon to configure the on board CSU/DSU.
+-
+-
+- o Keyboard Led Monitor/Debugger
+- - A new utility /usr/sbin/wpkbdmon uses keyboard leds
+- to convey operational statistic information of the
+- Sangoma WANPIPE cards.
+- NUM_LOCK = Line State (On=connected, Off=disconnected)
+- CAPS_LOCK = Tx data (On=transmitting, Off=no tx data)
+- SCROLL_LOCK = Rx data (On=receiving, Off=no rx data
+-
+- o Hardware probe on module load and dynamic device allocation
+- - During WANPIPE module load, all Sangoma cards are probed
+- and found information is printed in the /var/log/messages.
+- - If no cards are found, the module load fails.
+- - Appropriate number of devices are dynamically loaded
+- based on the number of Sangoma cards found.
+-
+- Note: The kernel configuration option
+- CONFIG_WANPIPE_CARDS has been taken out.
+-
+- o Fixed the Frame Relay and Chdlc network interfaces so they are
+- compatible with libpcap libraries. Meaning, tcpdump, snort,
+- ethereal, and all other packet sniffers and debuggers work on
+- all WANPIPE network interfaces.
+- - Set the network interface encoding type to ARPHRD_PPP.
+- This tell the sniffers that data obtained from the
+- network interface is in pure IP format.
+- Fix for 2.2.X kernels only.
+-
+- o True interface encoding option for Frame Relay and CHDLC
+- - The above fix sets the network interface encoding
+- type to ARPHRD_PPP, however some customers use
+- the encoding interface type to determine the
+- protocol running. Therefore, the TURE ENCODING
+- option will set the interface type back to the
+- original value.
+-
+- NOTE: If this option is used with Frame Relay and CHDLC
+- libpcap library support will be broken.
+- i.e. tcpdump will not work.
+- Fix for 2.2.x Kernels only.
+-
+- o Ethernet Bridgind over Frame Relay
+- - The Frame Relay bridging has been developed by
+- Kristian Hoffmann and Mark Wells.
+- - The Linux kernel bridge is used to send ethernet
+- data over the frame relay links.
+- For 2.2.X Kernels only.
+-
+- o Added extensive 2.0.X support. Most new features of
+- 2.1.5 for protocols Frame Relay, PPP and CHDLC are
+- supported under 2.0.X kernels.
+-
+-beta1-2.2.0 Dec 30 2000
+- o Updated drivers for 2.4.X kernels.
+- o Updated drivers for SMP support.
+- o X25API is now able to share PCI interrupts.
+- o Took out a general polling routine that was used
+- only by X25API.
+- o Added appropriate locks to the dynamic reconfiguration
+- code.
+- o Fixed a bug in the keyboard debug monitor.
+-
+-beta2-2.2.0 Jan 8 2001
+- o Patches for 2.4.0 kernel
+- o Patches for 2.2.18 kernel
+- o Minor updates to PPP and CHLDC drivers.
+- Note: No functional difference.
+-
+-beta3-2.2.9 Jan 10 2001
+- o I missed the 2.2.18 kernel patches in beta2-2.2.0
+- release. They are included in this release.
+-
+-Stable Release
+-2.2.0 Feb 01 2001
+- o Bug fix in wancfg GUI configurator.
+- The edit function didn't work properly.
+-
+-
+-bata1-2.2.1 Feb 09 2001
+- o WANPIPE TTY Driver emulation.
+- Two modes of operation Sync and Async.
+- Sync: Using the PPPD daemon, kernel SyncPPP layer
+- and the Wanpipe sync TTY driver: a PPP protocol
+- connection can be established via Sangoma adapter, over
+- a T1 leased line.
+-
+- The 2.4.0 kernel PPP layer supports MULTILINK
+- protocol, that can be used to bundle any number of Sangoma
+- adapters (T1 lines) into one, under a single IP address.
+- Thus, efficiently obtaining multiple T1 throughput.
+-
+- NOTE: The remote side must also implement MULTILINK PPP
+- protocol.
+-
+- Async:Using the PPPD daemon, kernel AsyncPPP layer
+- and the WANPIPE async TTY driver: a PPP protocol
+- connection can be established via Sangoma adapter and
+- a modem, over a telephone line.
+-
+- Thus, the WANPIPE async TTY driver simulates a serial
+- TTY driver that would normally be used to interface the
+- MODEM to the linux kernel.
+-
+- o WANPIPE PPP Backup Utility
+- This utility will monitor the state of the PPP T1 line.
+- In case of failure, a dial up connection will be established
+- via pppd daemon, ether via a serial tty driver (serial port),
+- or a WANPIPE async TTY driver (in case serial port is unavailable).
+-
+- Furthermore, while in dial up mode, the primary PPP T1 link
+- will be monitored for signs of life.
+-
+- If the PPP T1 link comes back to life, the dial up connection
+- will be shutdown and T1 line re-established.
+-
+-
+- o New Setup installation script.
+- Option to UPGRADE device drivers if the kernel source has
+- already been patched with WANPIPE.
+-
+- Option to COMPILE WANPIPE modules against the currently
+- running kernel, thus no need for manual kernel and module
+- re-compilation.
+-
+- o Updates and Bug Fixes to wancfg utility.
+-
+-bata2-2.2.1 Feb 20 2001
+-
+- o Bug fixes to the CHDLC device drivers.
+- The driver had compilation problems under kernels
+- 2.2.14 or lower.
+-
+- o Bug fixes to the Setup installation script.
+- The device drivers compilation options didn't work
+- properly.
+-
+- o Update to the wpbackupd daemon.
+- Optimized the cross-over times, between the primary
+- link and the backup dialup.
+-
+-beta3-2.2.1 Mar 02 2001
+- o Patches for 2.4.2 kernel.
+-
+- o Bug fixes to util/ make files.
+- o Bug fixes to the Setup installation script.
+-
+- o Took out the backupd support and made it into
+- as separate package.
+-
+-beta4-2.2.1 Mar 12 2001
+-
+- o Fix to the Frame Relay Device driver.
+- IPSAC sends a packet of zero length
+- header to the frame relay driver. The
+- driver tries to push its own 2 byte header
+- into the packet, which causes the driver to
+- crash.
+-
+- o Fix the WANPIPE re-configuration code.
+- Bug was found by trying to run the cfgft1 while the
+- interface was already running.
+-
+- o Updates to cfgft1.
+- Writes a wanpipe#.cfgft1 configuration file
+- once the CSU/DSU is configured. This file can
+- holds the current CSU/DSU configuration.
+-
+-
+-
+->>>>>> END OF README <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+-
+-
+diff --git a/Documentation/pci-error-recovery.txt b/Documentation/pci-error-recovery.txt
+deleted file mode 100644
+index 6650af4..0000000
+--- a/Documentation/pci-error-recovery.txt
++++ /dev/null
+@@ -1,396 +0,0 @@
+-
+- PCI Error Recovery
+- ------------------
+- February 2, 2006
+-
+- Current document maintainer:
+- Linas Vepstas <linas at austin.ibm.com>
+-
+-
+-Many PCI bus controllers are able to detect a variety of hardware
+-PCI errors on the bus, such as parity errors on the data and address
+-busses, as well as SERR and PERR errors. Some of the more advanced
+-chipsets are able to deal with these errors; these include PCI-E chipsets,
+-and the PCI-host bridges found on IBM Power4 and Power5-based pSeries
+-boxes. A typical action taken is to disconnect the affected device,
+-halting all I/O to it. The goal of a disconnection is to avoid system
+-corruption; for example, to halt system memory corruption due to DMA's
+-to "wild" addresses. Typically, a reconnection mechanism is also
+-offered, so that the affected PCI device(s) are reset and put back
+-into working condition. The reset phase requires coordination
+-between the affected device drivers and the PCI controller chip.
+-This document describes a generic API for notifying device drivers
+-of a bus disconnection, and then performing error recovery.
+-This API is currently implemented in the 2.6.16 and later kernels.
+-
+-Reporting and recovery is performed in several steps. First, when
+-a PCI hardware error has resulted in a bus disconnect, that event
+-is reported as soon as possible to all affected device drivers,
+-including multiple instances of a device driver on multi-function
+-cards. This allows device drivers to avoid deadlocking in spinloops,
+-waiting for some i/o-space register to change, when it never will.
+-It also gives the drivers a chance to defer incoming I/O as
+-needed.
+-
+-Next, recovery is performed in several stages. Most of the complexity
+-is forced by the need to handle multi-function devices, that is,
+-devices that have multiple device drivers associated with them.
+-In the first stage, each driver is allowed to indicate what type
+-of reset it desires, the choices being a simple re-enabling of I/O
+-or requesting a hard reset (a full electrical #RST of the PCI card).
+-If any driver requests a full reset, that is what will be done.
+-
+-After a full reset and/or a re-enabling of I/O, all drivers are
+-again notified, so that they may then perform any device setup/config
+-that may be required. After these have all completed, a final
+-"resume normal operations" event is sent out.
+-
+-The biggest reason for choosing a kernel-based implementation rather
+-than a user-space implementation was the need to deal with bus
+-disconnects of PCI devices attached to storage media, and, in particular,
+-disconnects from devices holding the root file system. If the root
+-file system is disconnected, a user-space mechanism would have to go
+-through a large number of contortions to complete recovery. Almost all
+-of the current Linux file systems are not tolerant of disconnection
+-from/reconnection to their underlying block device. By contrast,
+-bus errors are easy to manage in the device driver. Indeed, most
+-device drivers already handle very similar recovery procedures;
+-for example, the SCSI-generic layer already provides significant
+-mechanisms for dealing with SCSI bus errors and SCSI bus resets.
+-
+-
+-Detailed Design
+----------------
+-Design and implementation details below, based on a chain of
+-public email discussions with Ben Herrenschmidt, circa 5 April 2005.
+-
+-The error recovery API support is exposed to the driver in the form of
+-a structure of function pointers pointed to by a new field in struct
+-pci_driver. A driver that fails to provide the structure is "non-aware",
+-and the actual recovery steps taken are platform dependent. The
+-arch/powerpc implementation will simulate a PCI hotplug remove/add.
+-
+-This structure has the form:
+-struct pci_error_handlers
+-{
+- int (*error_detected)(struct pci_dev *dev, enum pci_channel_state);
+- int (*mmio_enabled)(struct pci_dev *dev);
+- int (*link_reset)(struct pci_dev *dev);
+- int (*slot_reset)(struct pci_dev *dev);
+- void (*resume)(struct pci_dev *dev);
+-};
+-
+-The possible channel states are:
+-enum pci_channel_state {
+- pci_channel_io_normal, /* I/O channel is in normal state */
+- pci_channel_io_frozen, /* I/O to channel is blocked */
+- pci_channel_io_perm_failure, /* PCI card is dead */
+-};
+-
+-Possible return values are:
+-enum pci_ers_result {
+- PCI_ERS_RESULT_NONE, /* no result/none/not supported in device driver */
+- PCI_ERS_RESULT_CAN_RECOVER, /* Device driver can recover without slot reset */
+- PCI_ERS_RESULT_NEED_RESET, /* Device driver wants slot to be reset. */
+- PCI_ERS_RESULT_DISCONNECT, /* Device has completely failed, is unrecoverable */
+- PCI_ERS_RESULT_RECOVERED, /* Device driver is fully recovered and operational */
+-};
+-
+-A driver does not have to implement all of these callbacks; however,
+-if it implements any, it must implement error_detected(). If a callback
+-is not implemented, the corresponding feature is considered unsupported.
+-For example, if mmio_enabled() and resume() aren't there, then it
+-is assumed that the driver is not doing any direct recovery and requires
+-a reset. If link_reset() is not implemented, the card is assumed as
+-not care about link resets. Typically a driver will want to know about
+-a slot_reset().
+-
+-The actual steps taken by a platform to recover from a PCI error
+-event will be platform-dependent, but will follow the general
+-sequence described below.
+-
+-STEP 0: Error Event
+--------------------
+-PCI bus error is detect by the PCI hardware. On powerpc, the slot
+-is isolated, in that all I/O is blocked: all reads return 0xffffffff,
+-all writes are ignored.
+-
+-
+-STEP 1: Notification
+---------------------
+-Platform calls the error_detected() callback on every instance of
+-every driver affected by the error.
+-
+-At this point, the device might not be accessible anymore, depending on
+-the platform (the slot will be isolated on powerpc). The driver may
+-already have "noticed" the error because of a failing I/O, but this
+-is the proper "synchronization point", that is, it gives the driver
+-a chance to cleanup, waiting for pending stuff (timers, whatever, etc...)
+-to complete; it can take semaphores, schedule, etc... everything but
+-touch the device. Within this function and after it returns, the driver
+-shouldn't do any new IOs. Called in task context. This is sort of a
+-"quiesce" point. See note about interrupts at the end of this doc.
+-
+-All drivers participating in this system must implement this call.
+-The driver must return one of the following result codes:
+- - PCI_ERS_RESULT_CAN_RECOVER:
+- Driver returns this if it thinks it might be able to recover
+- the HW by just banging IOs or if it wants to be given
+- a chance to extract some diagnostic information (see
+- mmio_enable, below).
+- - PCI_ERS_RESULT_NEED_RESET:
+- Driver returns this if it can't recover without a hard
+- slot reset.
+- - PCI_ERS_RESULT_DISCONNECT:
+- Driver returns this if it doesn't want to recover at all.
+-
+-The next step taken will depend on the result codes returned by the
+-drivers.
+-
+-If all drivers on the segment/slot return PCI_ERS_RESULT_CAN_RECOVER,
+-then the platform should re-enable IOs on the slot (or do nothing in
+-particular, if the platform doesn't isolate slots), and recovery
+-proceeds to STEP 2 (MMIO Enable).
+-
+-If any driver requested a slot reset (by returning PCI_ERS_RESULT_NEED_RESET),
+-then recovery proceeds to STEP 4 (Slot Reset).
+-
+-If the platform is unable to recover the slot, the next step
+-is STEP 6 (Permanent Failure).
+-
+->>> The current powerpc implementation assumes that a device driver will
+->>> *not* schedule or semaphore in this routine; the current powerpc
+->>> implementation uses one kernel thread to notify all devices;
+->>> thus, if one device sleeps/schedules, all devices are affected.
+->>> Doing better requires complex multi-threaded logic in the error
+->>> recovery implementation (e.g. waiting for all notification threads
+->>> to "join" before proceeding with recovery.) This seems excessively
+->>> complex and not worth implementing.
+-
+->>> The current powerpc implementation doesn't much care if the device
+->>> attempts I/O at this point, or not. I/O's will fail, returning
+->>> a value of 0xff on read, and writes will be dropped. If the device
+->>> driver attempts more than 10K I/O's to a frozen adapter, it will
+->>> assume that the device driver has gone into an infinite loop, and
+->>> it will panic the kernel. There doesn't seem to be any other
+->>> way of stopping a device driver that insists on spinning on I/O.
+-
+-STEP 2: MMIO Enabled
+--------------------
+-The platform re-enables MMIO to the device (but typically not the
+-DMA), and then calls the mmio_enabled() callback on all affected
+-device drivers.
+-
+-This is the "early recovery" call. IOs are allowed again, but DMA is
+-not (hrm... to be discussed, I prefer not), with some restrictions. This
+-is NOT a callback for the driver to start operations again, only to
+-peek/poke at the device, extract diagnostic information, if any, and
+-eventually do things like trigger a device local reset or some such,
+-but not restart operations. This is callback is made if all drivers on
+-a segment agree that they can try to recover and if no automatic link reset
+-was performed by the HW. If the platform can't just re-enable IOs without
+-a slot reset or a link reset, it wont call this callback, and instead
+-will have gone directly to STEP 3 (Link Reset) or STEP 4 (Slot Reset)
+-
+->>> The following is proposed; no platform implements this yet:
+->>> Proposal: All I/O's should be done _synchronously_ from within
+->>> this callback, errors triggered by them will be returned via
+->>> the normal pci_check_whatever() API, no new error_detected()
+->>> callback will be issued due to an error happening here. However,
+->>> such an error might cause IOs to be re-blocked for the whole
+->>> segment, and thus invalidate the recovery that other devices
+->>> on the same segment might have done, forcing the whole segment
+->>> into one of the next states, that is, link reset or slot reset.
+-
+-The driver should return one of the following result codes:
+- - PCI_ERS_RESULT_RECOVERED
+- Driver returns this if it thinks the device is fully
+- functional and thinks it is ready to start
+- normal driver operations again. There is no
+- guarantee that the driver will actually be
+- allowed to proceed, as another driver on the
+- same segment might have failed and thus triggered a
+- slot reset on platforms that support it.
+-
+- - PCI_ERS_RESULT_NEED_RESET
+- Driver returns this if it thinks the device is not
+- recoverable in it's current state and it needs a slot
+- reset to proceed.
+-
+- - PCI_ERS_RESULT_DISCONNECT
+- Same as above. Total failure, no recovery even after
+- reset driver dead. (To be defined more precisely)
+-
+-The next step taken depends on the results returned by the drivers.
+-If all drivers returned PCI_ERS_RESULT_RECOVERED, then the platform
+-proceeds to either STEP3 (Link Reset) or to STEP 5 (Resume Operations).
+-
+-If any driver returned PCI_ERS_RESULT_NEED_RESET, then the platform
+-proceeds to STEP 4 (Slot Reset)
+-
+->>> The current powerpc implementation does not implement this callback.
+-
+-
+-STEP 3: Link Reset
+-------------------
+-The platform resets the link, and then calls the link_reset() callback
+-on all affected device drivers. This is a PCI-Express specific state
+-and is done whenever a non-fatal error has been detected that can be
+-"solved" by resetting the link. This call informs the driver of the
+-reset and the driver should check to see if the device appears to be
+-in working condition.
+-
+-The driver is not supposed to restart normal driver I/O operations
+-at this point. It should limit itself to "probing" the device to
+-check it's recoverability status. If all is right, then the platform
+-will call resume() once all drivers have ack'd link_reset().
+-
+- Result codes:
+- (identical to STEP 3 (MMIO Enabled)
+-
+-The platform then proceeds to either STEP 4 (Slot Reset) or STEP 5
+-(Resume Operations).
+-
+->>> The current powerpc implementation does not implement this callback.
+-
+-
+-STEP 4: Slot Reset
+-------------------
+-The platform performs a soft or hard reset of the device, and then
+-calls the slot_reset() callback.
+-
+-A soft reset consists of asserting the adapter #RST line and then
+-restoring the PCI BAR's and PCI configuration header to a state
+-that is equivalent to what it would be after a fresh system
+-power-on followed by power-on BIOS/system firmware initialization.
+-If the platform supports PCI hotplug, then the reset might be
+-performed by toggling the slot electrical power off/on.
+-
+-It is important for the platform to restore the PCI config space
+-to the "fresh poweron" state, rather than the "last state". After
+-a slot reset, the device driver will almost always use its standard
+-device initialization routines, and an unusual config space setup
+-may result in hung devices, kernel panics, or silent data corruption.
+-
+-This call gives drivers the chance to re-initialize the hardware
+-(re-download firmware, etc.). At this point, the driver may assume
+-that he card is in a fresh state and is fully functional. In
+-particular, interrupt generation should work normally.
+-
+-Drivers should not yet restart normal I/O processing operations
+-at this point. If all device drivers report success on this
+-callback, the platform will call resume() to complete the sequence,
+-and let the driver restart normal I/O processing.
+-
+-A driver can still return a critical failure for this function if
+-it can't get the device operational after reset. If the platform
+-previously tried a soft reset, it might now try a hard reset (power
+-cycle) and then call slot_reset() again. It the device still can't
+-be recovered, there is nothing more that can be done; the platform
+-will typically report a "permanent failure" in such a case. The
+-device will be considered "dead" in this case.
+-
+-Drivers for multi-function cards will need to coordinate among
+-themselves as to which driver instance will perform any "one-shot"
+-or global device initialization. For example, the Symbios sym53cxx2
+-driver performs device init only from PCI function 0:
+-
+-+ if (PCI_FUNC(pdev->devfn) == 0)
+-+ sym_reset_scsi_bus(np, 0);
+-
+- Result codes:
+- - PCI_ERS_RESULT_DISCONNECT
+- Same as above.
+-
+-Platform proceeds either to STEP 5 (Resume Operations) or STEP 6 (Permanent
+-Failure).
+-
+->>> The current powerpc implementation does not currently try a
+->>> power-cycle reset if the driver returned PCI_ERS_RESULT_DISCONNECT.
+->>> However, it probably should.
+-
+-
+-STEP 5: Resume Operations
+--------------------------
+-The platform will call the resume() callback on all affected device
+-drivers if all drivers on the segment have returned
+-PCI_ERS_RESULT_RECOVERED from one of the 3 previous callbacks.
+-The goal of this callback is to tell the driver to restart activity,
+-that everything is back and running. This callback does not return
+-a result code.
+-
+-At this point, if a new error happens, the platform will restart
+-a new error recovery sequence.
+-
+-STEP 6: Permanent Failure
+--------------------------
+-A "permanent failure" has occurred, and the platform cannot recover
+-the device. The platform will call error_detected() with a
+-pci_channel_state value of pci_channel_io_perm_failure.
+-
+-The device driver should, at this point, assume the worst. It should
+-cancel all pending I/O, refuse all new I/O, returning -EIO to
+-higher layers. The device driver should then clean up all of its
+-memory and remove itself from kernel operations, much as it would
+-during system shutdown.
+-
+-The platform will typically notify the system operator of the
+-permanent failure in some way. If the device is hotplug-capable,
+-the operator will probably want to remove and replace the device.
+-Note, however, not all failures are truly "permanent". Some are
+-caused by over-heating, some by a poorly seated card. Many
+-PCI error events are caused by software bugs, e.g. DMA's to
+-wild addresses or bogus split transactions due to programming
+-errors. See the discussion in powerpc/eeh-pci-error-recovery.txt
+-for additional detail on real-life experience of the causes of
+-software errors.
+-
+-
+-Conclusion; General Remarks
+----------------------------
+-The way those callbacks are called is platform policy. A platform with
+-no slot reset capability may want to just "ignore" drivers that can't
+-recover (disconnect them) and try to let other cards on the same segment
+-recover. Keep in mind that in most real life cases, though, there will
+-be only one driver per segment.
+-
+-Now, a note about interrupts. If you get an interrupt and your
+-device is dead or has been isolated, there is a problem :)
+-The current policy is to turn this into a platform policy.
+-That is, the recovery API only requires that:
+-
+- - There is no guarantee that interrupt delivery can proceed from any
+-device on the segment starting from the error detection and until the
+-resume callback is sent, at which point interrupts are expected to be
+-fully operational.
+-
+- - There is no guarantee that interrupt delivery is stopped, that is,
+-a driver that gets an interrupt after detecting an error, or that detects
+-an error within the interrupt handler such that it prevents proper
+-ack'ing of the interrupt (and thus removal of the source) should just
+-return IRQ_NOTHANDLED. It's up to the platform to deal with that
+-condition, typically by masking the IRQ source during the duration of
+-the error handling. It is expected that the platform "knows" which
+-interrupts are routed to error-management capable slots and can deal
+-with temporarily disabling that IRQ number during error processing (this
+-isn't terribly complex). That means some IRQ latency for other devices
+-sharing the interrupt, but there is simply no other way. High end
+-platforms aren't supposed to share interrupts between many devices
+-anyway :)
+-
+->>> Implementation details for the powerpc platform are discussed in
+->>> the file Documentation/powerpc/eeh-pci-error-recovery.txt
+-
+->>> As of this writing, there are six device drivers with patches
+->>> implementing error recovery. Not all of these patches are in
+->>> mainline yet. These may be used as "examples":
+->>>
+->>> drivers/scsi/ipr.c
+->>> drivers/scsi/sym53cxx_2
+->>> drivers/next/e100.c
+->>> drivers/net/e1000
+->>> drivers/net/ixgb
+->>> drivers/net/s2io.c
+-
+-The End
+--------
+diff --git a/Documentation/pci.txt b/Documentation/pci.txt
+deleted file mode 100644
+index d2c2e6e..0000000
+--- a/Documentation/pci.txt
++++ /dev/null
+@@ -1,646 +0,0 @@
+-
+- How To Write Linux PCI Drivers
+-
+- by Martin Mares <mj at ucw.cz> on 07-Feb-2000
+- updated by Grant Grundler <grundler at parisc-linux.org> on 23-Dec-2006
+-
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-The world of PCI is vast and full of (mostly unpleasant) surprises.
+-Since each CPU architecture implements different chip-sets and PCI devices
+-have different requirements (erm, "features"), the result is the PCI support
+-in the Linux kernel is not as trivial as one would wish. This short paper
+-tries to introduce all potential driver authors to Linux APIs for
+-PCI device drivers.
+-
+-A more complete resource is the third edition of "Linux Device Drivers"
+-by Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman.
+-LDD3 is available for free (under Creative Commons License) from:
+-
+- http://lwn.net/Kernel/LDD3/
+-
+-However, keep in mind that all documents are subject to "bit rot".
+-Refer to the source code if things are not working as described here.
+-
+-Please send questions/comments/patches about Linux PCI API to the
+-"Linux PCI" <linux-pci at atrey.karlin.mff.cuni.cz> mailing list.
+-
+-
+-
+-0. Structure of PCI drivers
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-PCI drivers "discover" PCI devices in a system via pci_register_driver().
+-Actually, it's the other way around. When the PCI generic code discovers
+-a new device, the driver with a matching "description" will be notified.
+-Details on this below.
+-
+-pci_register_driver() leaves most of the probing for devices to
+-the PCI layer and supports online insertion/removal of devices [thus
+-supporting hot-pluggable PCI, CardBus, and Express-Card in a single driver].
+-pci_register_driver() call requires passing in a table of function
+-pointers and thus dictates the high level structure of a driver.
+-
+-Once the driver knows about a PCI device and takes ownership, the
+-driver generally needs to perform the following initialization:
+-
+- Enable the device
+- Request MMIO/IOP resources
+- Set the DMA mask size (for both coherent and streaming DMA)
+- Allocate and initialize shared control data (pci_allocate_coherent())
+- Access device configuration space (if needed)
+- Register IRQ handler (request_irq())
+- Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip)
+- Enable DMA/processing engines
+-
+-When done using the device, and perhaps the module needs to be unloaded,
+-the driver needs to take the follow steps:
+- Disable the device from generating IRQs
+- Release the IRQ (free_irq())
+- Stop all DMA activity
+- Release DMA buffers (both streaming and coherent)
+- Unregister from other subsystems (e.g. scsi or netdev)
+- Release MMIO/IOP resources
+- Disable the device
+-
+-Most of these topics are covered in the following sections.
+-For the rest look at LDD3 or <linux/pci.h> .
+-
+-If the PCI subsystem is not configured (CONFIG_PCI is not set), most of
+-the PCI functions described below are defined as inline functions either
+-completely empty or just returning an appropriate error codes to avoid
+-lots of ifdefs in the drivers.
+-
+-
+-
+-1. pci_register_driver() call
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-PCI device drivers call pci_register_driver() during their
+-initialization with a pointer to a structure describing the driver
+-(struct pci_driver):
+-
+- field name Description
+- ---------- ------------------------------------------------------
+- id_table Pointer to table of device ID's the driver is
+- interested in. Most drivers should export this
+- table using MODULE_DEVICE_TABLE(pci,...).
+-
+- probe This probing function gets called (during execution
+- of pci_register_driver() for already existing
+- devices or later if a new device gets inserted) for
+- all PCI devices which match the ID table and are not
+- "owned" by the other drivers yet. This function gets
+- passed a "struct pci_dev *" for each device whose
+- entry in the ID table matches the device. The probe
+- function returns zero when the driver chooses to
+- take "ownership" of the device or an error code
+- (negative number) otherwise.
+- The probe function always gets called from process
+- context, so it can sleep.
+-
+- remove The remove() function gets called whenever a device
+- being handled by this driver is removed (either during
+- deregistration of the driver or when it's manually
+- pulled out of a hot-pluggable slot).
+- The remove function always gets called from process
+- context, so it can sleep.
+-
+- suspend Put device into low power state.
+- suspend_late Put device into low power state.
+-
+- resume_early Wake device from low power state.
+- resume Wake device from low power state.
+-
+- (Please see Documentation/power/pci.txt for descriptions
+- of PCI Power Management and the related functions.)
+-
+- shutdown Hook into reboot_notifier_list (kernel/sys.c).
+- Intended to stop any idling DMA operations.
+- Useful for enabling wake-on-lan (NIC) or changing
+- the power state of a device before reboot.
+- e.g. drivers/net/e100.c.
+-
+- err_handler See Documentation/pci-error-recovery.txt
+-
+-
+-The ID table is an array of struct pci_device_id entries ending with an
+-all-zero entry; use of the macro DEFINE_PCI_DEVICE_TABLE is the preferred
+-method of declaring the table. Each entry consists of:
+-
+- vendor,device Vendor and device ID to match (or PCI_ANY_ID)
+-
+- subvendor, Subsystem vendor and device ID to match (or PCI_ANY_ID)
+- subdevice,
+-
+- class Device class, subclass, and "interface" to match.
+- See Appendix D of the PCI Local Bus Spec or
+- include/linux/pci_ids.h for a full list of classes.
+- Most drivers do not need to specify class/class_mask
+- as vendor/device is normally sufficient.
+-
+- class_mask limit which sub-fields of the class field are compared.
+- See drivers/scsi/sym53c8xx_2/ for example of usage.
+-
+- driver_data Data private to the driver.
+- Most drivers don't need to use driver_data field.
+- Best practice is to use driver_data as an index
+- into a static list of equivalent device types,
+- instead of using it as a pointer.
+-
+-
+-Most drivers only need PCI_DEVICE() or PCI_DEVICE_CLASS() to set up
+-a pci_device_id table.
+-
+-New PCI IDs may be added to a device driver pci_ids table at runtime
+-as shown below:
+-
+-echo "vendor device subvendor subdevice class class_mask driver_data" > \
+-/sys/bus/pci/drivers/{driver}/new_id
+-
+-All fields are passed in as hexadecimal values (no leading 0x).
+-The vendor and device fields are mandatory, the others are optional. Users
+-need pass only as many optional fields as necessary:
+- o subvendor and subdevice fields default to PCI_ANY_ID (FFFFFFFF)
+- o class and classmask fields default to 0
+- o driver_data defaults to 0UL.
+-
+-Once added, the driver probe routine will be invoked for any unclaimed
+-PCI devices listed in its (newly updated) pci_ids list.
+-
+-When the driver exits, it just calls pci_unregister_driver() and the PCI layer
+-automatically calls the remove hook for all devices handled by the driver.
+-
+-
+-1.1 "Attributes" for driver functions/data
+-
+-Please mark the initialization and cleanup functions where appropriate
+-(the corresponding macros are defined in <linux/init.h>):
+-
+- __init Initialization code. Thrown away after the driver
+- initializes.
+- __exit Exit code. Ignored for non-modular drivers.
+-
+-
+- __devinit Device initialization code.
+- Identical to __init if the kernel is not compiled
+- with CONFIG_HOTPLUG, normal function otherwise.
+- __devexit The same for __exit.
+-
+-Tips on when/where to use the above attributes:
+- o The module_init()/module_exit() functions (and all
+- initialization functions called _only_ from these)
+- should be marked __init/__exit.
+-
+- o Do not mark the struct pci_driver.
+-
+- o The ID table array should be marked __devinitconst; this is done
+- automatically if the table is declared with DEFINE_PCI_DEVICE_TABLE().
+-
+- o The probe() and remove() functions should be marked __devinit
+- and __devexit respectively. All initialization functions
+- exclusively called by the probe() routine, can be marked __devinit.
+- Ditto for remove() and __devexit.
+-
+- o If mydriver_remove() is marked with __devexit(), then all address
+- references to mydriver_remove must use __devexit_p(mydriver_remove)
+- (in the struct pci_driver declaration for example).
+- __devexit_p() will generate the function name _or_ NULL if the
+- function will be discarded. For an example, see drivers/net/tg3.c.
+-
+- o Do NOT mark a function if you are not sure which mark to use.
+- Better to not mark the function than mark the function wrong.
+-
+-
+-
+-2. How to find PCI devices manually
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-PCI drivers should have a really good reason for not using the
+-pci_register_driver() interface to search for PCI devices.
+-The main reason PCI devices are controlled by multiple drivers
+-is because one PCI device implements several different HW services.
+-E.g. combined serial/parallel port/floppy controller.
+-
+-A manual search may be performed using the following constructs:
+-
+-Searching by vendor and device ID:
+-
+- struct pci_dev *dev = NULL;
+- while (dev = pci_get_device(VENDOR_ID, DEVICE_ID, dev))
+- configure_device(dev);
+-
+-Searching by class ID (iterate in a similar way):
+-
+- pci_get_class(CLASS_ID, dev)
+-
+-Searching by both vendor/device and subsystem vendor/device ID:
+-
+- pci_get_subsys(VENDOR_ID,DEVICE_ID, SUBSYS_VENDOR_ID, SUBSYS_DEVICE_ID, dev).
+-
+-You can use the constant PCI_ANY_ID as a wildcard replacement for
+-VENDOR_ID or DEVICE_ID. This allows searching for any device from a
+-specific vendor, for example.
+-
+-These functions are hotplug-safe. They increment the reference count on
+-the pci_dev that they return. You must eventually (possibly at module unload)
+-decrement the reference count on these devices by calling pci_dev_put().
+-
+-
+-
+-3. Device Initialization Steps
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-As noted in the introduction, most PCI drivers need the following steps
+-for device initialization:
+-
+- Enable the device
+- Request MMIO/IOP resources
+- Set the DMA mask size (for both coherent and streaming DMA)
+- Allocate and initialize shared control data (pci_allocate_coherent())
+- Access device configuration space (if needed)
+- Register IRQ handler (request_irq())
+- Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip)
+- Enable DMA/processing engines.
+-
+-The driver can access PCI config space registers at any time.
+-(Well, almost. When running BIST, config space can go away...but
+-that will just result in a PCI Bus Master Abort and config reads
+-will return garbage).
+-
+-
+-3.1 Enable the PCI device
+-~~~~~~~~~~~~~~~~~~~~~~~~~
+-Before touching any device registers, the driver needs to enable
+-the PCI device by calling pci_enable_device(). This will:
+- o wake up the device if it was in suspended state,
+- o allocate I/O and memory regions of the device (if BIOS did not),
+- o allocate an IRQ (if BIOS did not).
+-
+-NOTE: pci_enable_device() can fail! Check the return value.
+-
+-[ OS BUG: we don't check resource allocations before enabling those
+- resources. The sequence would make more sense if we called
+- pci_request_resources() before calling pci_enable_device().
+- Currently, the device drivers can't detect the bug when when two
+- devices have been allocated the same range. This is not a common
+- problem and unlikely to get fixed soon.
+-
+- This has been discussed before but not changed as of 2.6.19:
+- http://lkml.org/lkml/2006/3/2/194
+-]
+-
+-pci_set_master() will enable DMA by setting the bus master bit
+-in the PCI_COMMAND register. It also fixes the latency timer value if
+-it's set to something bogus by the BIOS.
+-
+-If the PCI device can use the PCI Memory-Write-Invalidate transaction,
+-call pci_set_mwi(). This enables the PCI_COMMAND bit for Mem-Wr-Inval
+-and also ensures that the cache line size register is set correctly.
+-Check the return value of pci_set_mwi() as not all architectures
+-or chip-sets may support Memory-Write-Invalidate. Alternatively,
+-if Mem-Wr-Inval would be nice to have but is not required, call
+-pci_try_set_mwi() to have the system do its best effort at enabling
+-Mem-Wr-Inval.
+-
+-
+-3.2 Request MMIO/IOP resources
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-Memory (MMIO), and I/O port addresses should NOT be read directly
+-from the PCI device config space. Use the values in the pci_dev structure
+-as the PCI "bus address" might have been remapped to a "host physical"
+-address by the arch/chip-set specific kernel support.
+-
+-See Documentation/IO-mapping.txt for how to access device registers
+-or device memory.
+-
+-The device driver needs to call pci_request_region() to verify
+-no other device is already using the same address resource.
+-Conversely, drivers should call pci_release_region() AFTER
+-calling pci_disable_device().
+-The idea is to prevent two devices colliding on the same address range.
+-
+-[ See OS BUG comment above. Currently (2.6.19), The driver can only
+- determine MMIO and IO Port resource availability _after_ calling
+- pci_enable_device(). ]
+-
+-Generic flavors of pci_request_region() are request_mem_region()
+-(for MMIO ranges) and request_region() (for IO Port ranges).
+-Use these for address resources that are not described by "normal" PCI
+-BARs.
+-
+-Also see pci_request_selected_regions() below.
+-
+-
+-3.3 Set the DMA mask size
+-~~~~~~~~~~~~~~~~~~~~~~~~~
+-[ If anything below doesn't make sense, please refer to
+- Documentation/DMA-API.txt. This section is just a reminder that
+- drivers need to indicate DMA capabilities of the device and is not
+- an authoritative source for DMA interfaces. ]
+-
+-While all drivers should explicitly indicate the DMA capability
+-(e.g. 32 or 64 bit) of the PCI bus master, devices with more than
+-32-bit bus master capability for streaming data need the driver
+-to "register" this capability by calling pci_set_dma_mask() with
+-appropriate parameters. In general this allows more efficient DMA
+-on systems where System RAM exists above 4G _physical_ address.
+-
+-Drivers for all PCI-X and PCIe compliant devices must call
+-pci_set_dma_mask() as they are 64-bit DMA devices.
+-
+-Similarly, drivers must also "register" this capability if the device
+-can directly address "consistent memory" in System RAM above 4G physical
+-address by calling pci_set_consistent_dma_mask().
+-Again, this includes drivers for all PCI-X and PCIe compliant devices.
+-Many 64-bit "PCI" devices (before PCI-X) and some PCI-X devices are
+-64-bit DMA capable for payload ("streaming") data but not control
+-("consistent") data.
+-
+-
+-3.4 Setup shared control data
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-Once the DMA masks are set, the driver can allocate "consistent" (a.k.a. shared)
+-memory. See Documentation/DMA-API.txt for a full description of
+-the DMA APIs. This section is just a reminder that it needs to be done
+-before enabling DMA on the device.
+-
+-
+-3.5 Initialize device registers
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-Some drivers will need specific "capability" fields programmed
+-or other "vendor specific" register initialized or reset.
+-E.g. clearing pending interrupts.
+-
+-
+-3.6 Register IRQ handler
+-~~~~~~~~~~~~~~~~~~~~~~~~
+-While calling request_irq() is the last step described here,
+-this is often just another intermediate step to initialize a device.
+-This step can often be deferred until the device is opened for use.
+-
+-All interrupt handlers for IRQ lines should be registered with IRQF_SHARED
+-and use the devid to map IRQs to devices (remember that all PCI IRQ lines
+-can be shared).
+-
+-request_irq() will associate an interrupt handler and device handle
+-with an interrupt number. Historically interrupt numbers represent
+-IRQ lines which run from the PCI device to the Interrupt controller.
+-With MSI and MSI-X (more below) the interrupt number is a CPU "vector".
+-
+-request_irq() also enables the interrupt. Make sure the device is
+-quiesced and does not have any interrupts pending before registering
+-the interrupt handler.
+-
+-MSI and MSI-X are PCI capabilities. Both are "Message Signaled Interrupts"
+-which deliver interrupts to the CPU via a DMA write to a Local APIC.
+-The fundamental difference between MSI and MSI-X is how multiple
+-"vectors" get allocated. MSI requires contiguous blocks of vectors
+-while MSI-X can allocate several individual ones.
+-
+-MSI capability can be enabled by calling pci_enable_msi() or
+-pci_enable_msix() before calling request_irq(). This causes
+-the PCI support to program CPU vector data into the PCI device
+-capability registers.
+-
+-If your PCI device supports both, try to enable MSI-X first.
+-Only one can be enabled at a time. Many architectures, chip-sets,
+-or BIOSes do NOT support MSI or MSI-X and the call to pci_enable_msi/msix
+-will fail. This is important to note since many drivers have
+-two (or more) interrupt handlers: one for MSI/MSI-X and another for IRQs.
+-They choose which handler to register with request_irq() based on the
+-return value from pci_enable_msi/msix().
+-
+-There are (at least) two really good reasons for using MSI:
+-1) MSI is an exclusive interrupt vector by definition.
+- This means the interrupt handler doesn't have to verify
+- its device caused the interrupt.
+-
+-2) MSI avoids DMA/IRQ race conditions. DMA to host memory is guaranteed
+- to be visible to the host CPU(s) when the MSI is delivered. This
+- is important for both data coherency and avoiding stale control data.
+- This guarantee allows the driver to omit MMIO reads to flush
+- the DMA stream.
+-
+-See drivers/infiniband/hw/mthca/ or drivers/net/tg3.c for examples
+-of MSI/MSI-X usage.
+-
+-
+-
+-4. PCI device shutdown
+-~~~~~~~~~~~~~~~~~~~~~~~
+-
+-When a PCI device driver is being unloaded, most of the following
+-steps need to be performed:
+-
+- Disable the device from generating IRQs
+- Release the IRQ (free_irq())
+- Stop all DMA activity
+- Release DMA buffers (both streaming and consistent)
+- Unregister from other subsystems (e.g. scsi or netdev)
+- Disable device from responding to MMIO/IO Port addresses
+- Release MMIO/IO Port resource(s)
+-
+-
+-4.1 Stop IRQs on the device
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-How to do this is chip/device specific. If it's not done, it opens
+-the possibility of a "screaming interrupt" if (and only if)
+-the IRQ is shared with another device.
+-
+-When the shared IRQ handler is "unhooked", the remaining devices
+-using the same IRQ line will still need the IRQ enabled. Thus if the
+-"unhooked" device asserts IRQ line, the system will respond assuming
+-it was one of the remaining devices asserted the IRQ line. Since none
+-of the other devices will handle the IRQ, the system will "hang" until
+-it decides the IRQ isn't going to get handled and masks the IRQ (100,000
+-iterations later). Once the shared IRQ is masked, the remaining devices
+-will stop functioning properly. Not a nice situation.
+-
+-This is another reason to use MSI or MSI-X if it's available.
+-MSI and MSI-X are defined to be exclusive interrupts and thus
+-are not susceptible to the "screaming interrupt" problem.
+-
+-
+-4.2 Release the IRQ
+-~~~~~~~~~~~~~~~~~~~
+-Once the device is quiesced (no more IRQs), one can call free_irq().
+-This function will return control once any pending IRQs are handled,
+-"unhook" the drivers IRQ handler from that IRQ, and finally release
+-the IRQ if no one else is using it.
+-
+-
+-4.3 Stop all DMA activity
+-~~~~~~~~~~~~~~~~~~~~~~~~~
+-It's extremely important to stop all DMA operations BEFORE attempting
+-to deallocate DMA control data. Failure to do so can result in memory
+-corruption, hangs, and on some chip-sets a hard crash.
+-
+-Stopping DMA after stopping the IRQs can avoid races where the
+-IRQ handler might restart DMA engines.
+-
+-While this step sounds obvious and trivial, several "mature" drivers
+-didn't get this step right in the past.
+-
+-
+-4.4 Release DMA buffers
+-~~~~~~~~~~~~~~~~~~~~~~~
+-Once DMA is stopped, clean up streaming DMA first.
+-I.e. unmap data buffers and return buffers to "upstream"
+-owners if there is one.
+-
+-Then clean up "consistent" buffers which contain the control data.
+-
+-See Documentation/DMA-API.txt for details on unmapping interfaces.
+-
+-
+-4.5 Unregister from other subsystems
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-Most low level PCI device drivers support some other subsystem
+-like USB, ALSA, SCSI, NetDev, Infiniband, etc. Make sure your
+-driver isn't losing resources from that other subsystem.
+-If this happens, typically the symptom is an Oops (panic) when
+-the subsystem attempts to call into a driver that has been unloaded.
+-
+-
+-4.6 Disable Device from responding to MMIO/IO Port addresses
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-io_unmap() MMIO or IO Port resources and then call pci_disable_device().
+-This is the symmetric opposite of pci_enable_device().
+-Do not access device registers after calling pci_disable_device().
+-
+-
+-4.7 Release MMIO/IO Port Resource(s)
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-Call pci_release_region() to mark the MMIO or IO Port range as available.
+-Failure to do so usually results in the inability to reload the driver.
+-
+-
+-
+-5. How to access PCI config space
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-You can use pci_(read|write)_config_(byte|word|dword) to access the config
+-space of a device represented by struct pci_dev *. All these functions return 0
+-when successful or an error code (PCIBIOS_...) which can be translated to a text
+-string by pcibios_strerror. Most drivers expect that accesses to valid PCI
+-devices don't fail.
+-
+-If you don't have a struct pci_dev available, you can call
+-pci_bus_(read|write)_config_(byte|word|dword) to access a given device
+-and function on that bus.
+-
+-If you access fields in the standard portion of the config header, please
+-use symbolic names of locations and bits declared in <linux/pci.h>.
+-
+-If you need to access Extended PCI Capability registers, just call
+-pci_find_capability() for the particular capability and it will find the
+-corresponding register block for you.
+-
+-
+-
+-6. Other interesting functions
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-pci_find_slot() Find pci_dev corresponding to given bus and
+- slot numbers.
+-pci_set_power_state() Set PCI Power Management state (0=D0 ... 3=D3)
+-pci_find_capability() Find specified capability in device's capability
+- list.
+-pci_resource_start() Returns bus start address for a given PCI region
+-pci_resource_end() Returns bus end address for a given PCI region
+-pci_resource_len() Returns the byte length of a PCI region
+-pci_set_drvdata() Set private driver data pointer for a pci_dev
+-pci_get_drvdata() Return private driver data pointer for a pci_dev
+-pci_set_mwi() Enable Memory-Write-Invalidate transactions.
+-pci_clear_mwi() Disable Memory-Write-Invalidate transactions.
+-
+-
+-
+-7. Miscellaneous hints
+-~~~~~~~~~~~~~~~~~~~~~~
+-
+-When displaying PCI device names to the user (for example when a driver wants
+-to tell the user what card has it found), please use pci_name(pci_dev).
+-
+-Always refer to the PCI devices by a pointer to the pci_dev structure.
+-All PCI layer functions use this identification and it's the only
+-reasonable one. Don't use bus/slot/function numbers except for very
+-special purposes -- on systems with multiple primary buses their semantics
+-can be pretty complex.
+-
+-Don't try to turn on Fast Back to Back writes in your driver. All devices
+-on the bus need to be capable of doing it, so this is something which needs
+-to be handled by platform and generic code, not individual drivers.
+-
+-
+-
+-8. Vendor and device identifications
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-One is not not required to add new device ids to include/linux/pci_ids.h.
+-Please add PCI_VENDOR_ID_xxx for vendors and a hex constant for device ids.
+-
+-PCI_VENDOR_ID_xxx constants are re-used. The device ids are arbitrary
+-hex numbers (vendor controlled) and normally used only in a single
+-location, the pci_device_id table.
+-
+-Please DO submit new vendor/device ids to pciids.sourceforge.net project.
+-
+-
+-
+-9. Obsolete functions
+-~~~~~~~~~~~~~~~~~~~~~
+-
+-There are several functions which you might come across when trying to
+-port an old driver to the new PCI interface. They are no longer present
+-in the kernel as they aren't compatible with hotplug or PCI domains or
+-having sane locking.
+-
+-pci_find_device() Superseded by pci_get_device()
+-pci_find_subsys() Superseded by pci_get_subsys()
+-pci_find_slot() Superseded by pci_get_slot()
+-
+-
+-The alternative is the traditional PCI device driver that walks PCI
+-device lists. This is still possible but discouraged.
+-
+-
+-
+-10. MMIO Space and "Write Posting"
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-
+-Converting a driver from using I/O Port space to using MMIO space
+-often requires some additional changes. Specifically, "write posting"
+-needs to be handled. Many drivers (e.g. tg3, acenic, sym53c8xx_2)
+-already do this. I/O Port space guarantees write transactions reach the PCI
+-device before the CPU can continue. Writes to MMIO space allow the CPU
+-to continue before the transaction reaches the PCI device. HW weenies
+-call this "Write Posting" because the write completion is "posted" to
+-the CPU before the transaction has reached its destination.
+-
+-Thus, timing sensitive code should add readl() where the CPU is
+-expected to wait before doing other work. The classic "bit banging"
+-sequence works fine for I/O Port space:
+-
+- for (i = 8; --i; val >>= 1) {
+- outb(val & 1, ioport_reg); /* write bit */
+- udelay(10);
+- }
+-
+-The same sequence for MMIO space should be:
+-
+- for (i = 8; --i; val >>= 1) {
+- writeb(val & 1, mmio_reg); /* write bit */
+- readb(safe_mmio_reg); /* flush posted write */
+- udelay(10);
+- }
+-
+-It is important that "safe_mmio_reg" not have any side effects that
+-interferes with the correct operation of the device.
+-
+-Another case to watch out for is when resetting a PCI device. Use PCI
+-Configuration space reads to flush the writel(). This will gracefully
+-handle the PCI master abort on all platforms if the PCI device is
+-expected to not respond to a readl(). Most x86 platforms will allow
+-MMIO reads to master abort (a.k.a. "Soft Fail") and return garbage
+-(e.g. ~0). But many RISC platforms will crash (a.k.a."Hard Fail").
+-
+diff --git a/Documentation/pcieaer-howto.txt b/Documentation/pcieaer-howto.txt
+deleted file mode 100644
+index d5da861..0000000
+--- a/Documentation/pcieaer-howto.txt
++++ /dev/null
+@@ -1,253 +0,0 @@
+- The PCI Express Advanced Error Reporting Driver Guide HOWTO
+- T. Long Nguyen <tom.l.nguyen at intel.com>
+- Yanmin Zhang <yanmin.zhang at intel.com>
+- 07/29/2006
+-
+-
+-1. Overview
+-
+-1.1 About this guide
+-
+-This guide describes the basics of the PCI Express Advanced Error
+-Reporting (AER) driver and provides information on how to use it, as
+-well as how to enable the drivers of endpoint devices to conform with
+-PCI Express AER driver.
+-
+-1.2 Copyright © Intel Corporation 2006.
+-
+-1.3 What is the PCI Express AER Driver?
+-
+-PCI Express error signaling can occur on the PCI Express link itself
+-or on behalf of transactions initiated on the link. PCI Express
+-defines two error reporting paradigms: the baseline capability and
+-the Advanced Error Reporting capability. The baseline capability is
+-required of all PCI Express components providing a minimum defined
+-set of error reporting requirements. Advanced Error Reporting
+-capability is implemented with a PCI Express advanced error reporting
+-extended capability structure providing more robust error reporting.
+-
+-The PCI Express AER driver provides the infrastructure to support PCI
+-Express Advanced Error Reporting capability. The PCI Express AER
+-driver provides three basic functions:
+-
+-- Gathers the comprehensive error information if errors occurred.
+-- Reports error to the users.
+-- Performs error recovery actions.
+-
+-AER driver only attaches root ports which support PCI-Express AER
+-capability.
+-
+-
+-2. User Guide
+-
+-2.1 Include the PCI Express AER Root Driver into the Linux Kernel
+-
+-The PCI Express AER Root driver is a Root Port service driver attached
+-to the PCI Express Port Bus driver. If a user wants to use it, the driver
+-has to be compiled. Option CONFIG_PCIEAER supports this capability. It
+-depends on CONFIG_PCIEPORTBUS, so pls. set CONFIG_PCIEPORTBUS=y and
+-CONFIG_PCIEAER = y.
+-
+-2.2 Load PCI Express AER Root Driver
+-There is a case where a system has AER support in BIOS. Enabling the AER
+-Root driver and having AER support in BIOS may result unpredictable
+-behavior. To avoid this conflict, a successful load of the AER Root driver
+-requires ACPI _OSC support in the BIOS to allow the AER Root driver to
+-request for native control of AER. See the PCI FW 3.0 Specification for
+-details regarding OSC usage. Currently, lots of firmwares don't provide
+-_OSC support while they use PCI Express. To support such firmwares,
+-forceload, a parameter of type bool, could enable AER to continue to
+-be initiated although firmwares have no _OSC support. To enable the
+-walkaround, pls. add aerdriver.forceload=y to kernel boot parameter line
+-when booting kernel. Note that forceload=n by default.
+-
+-2.3 AER error output
+-When a PCI-E AER error is captured, an error message will be outputed to
+-console. If it's a correctable error, it is outputed as a warning.
+-Otherwise, it is printed as an error. So users could choose different
+-log level to filter out correctable error messages.
+-
+-Below shows an example.
+-+------ PCI-Express Device Error -----+
+-Error Severity : Uncorrected (Fatal)
+-PCIE Bus Error type : Transaction Layer
+-Unsupported Request : First
+-Requester ID : 0500
+-VendorID=8086h, DeviceID=0329h, Bus=05h, Device=00h, Function=00h
+-TLB Header:
+-04000001 00200a03 05010000 00050100
+-
+-In the example, 'Requester ID' means the ID of the device who sends
+-the error message to root port. Pls. refer to pci express specs for
+-other fields.
+-
+-
+-3. Developer Guide
+-
+-To enable AER aware support requires a software driver to configure
+-the AER capability structure within its device and to provide callbacks.
+-
+-To support AER better, developers need understand how AER does work
+-firstly.
+-
+-PCI Express errors are classified into two types: correctable errors
+-and uncorrectable errors. This classification is based on the impacts
+-of those errors, which may result in degraded performance or function
+-failure.
+-
+-Correctable errors pose no impacts on the functionality of the
+-interface. The PCI Express protocol can recover without any software
+-intervention or any loss of data. These errors are detected and
+-corrected by hardware. Unlike correctable errors, uncorrectable
+-errors impact functionality of the interface. Uncorrectable errors
+-can cause a particular transaction or a particular PCI Express link
+-to be unreliable. Depending on those error conditions, uncorrectable
+-errors are further classified into non-fatal errors and fatal errors.
+-Non-fatal errors cause the particular transaction to be unreliable,
+-but the PCI Express link itself is fully functional. Fatal errors, on
+-the other hand, cause the link to be unreliable.
+-
+-When AER is enabled, a PCI Express device will automatically send an
+-error message to the PCIE root port above it when the device captures
+-an error. The Root Port, upon receiving an error reporting message,
+-internally processes and logs the error message in its PCI Express
+-capability structure. Error information being logged includes storing
+-the error reporting agent's requestor ID into the Error Source
+-Identification Registers and setting the error bits of the Root Error
+-Status Register accordingly. If AER error reporting is enabled in Root
+-Error Command Register, the Root Port generates an interrupt if an
+-error is detected.
+-
+-Note that the errors as described above are related to the PCI Express
+-hierarchy and links. These errors do not include any device specific
+-errors because device specific errors will still get sent directly to
+-the device driver.
+-
+-3.1 Configure the AER capability structure
+-
+-AER aware drivers of PCI Express component need change the device
+-control registers to enable AER. They also could change AER registers,
+-including mask and severity registers. Helper function
+-pci_enable_pcie_error_reporting could be used to enable AER. See
+-section 3.3.
+-
+-3.2. Provide callbacks
+-
+-3.2.1 callback reset_link to reset pci express link
+-
+-This callback is used to reset the pci express physical link when a
+-fatal error happens. The root port aer service driver provides a
+-default reset_link function, but different upstream ports might
+-have different specifications to reset pci express link, so all
+-upstream ports should provide their own reset_link functions.
+-
+-In struct pcie_port_service_driver, a new pointer, reset_link, is
+-added.
+-
+-pci_ers_result_t (*reset_link) (struct pci_dev *dev);
+-
+-Section 3.2.2.2 provides more detailed info on when to call
+-reset_link.
+-
+-3.2.2 PCI error-recovery callbacks
+-
+-The PCI Express AER Root driver uses error callbacks to coordinate
+-with downstream device drivers associated with a hierarchy in question
+-when performing error recovery actions.
+-
+-Data struct pci_driver has a pointer, err_handler, to point to
+-pci_error_handlers who consists of a couple of callback function
+-pointers. AER driver follows the rules defined in
+-pci-error-recovery.txt except pci express specific parts (e.g.
+-reset_link). Pls. refer to pci-error-recovery.txt for detailed
+-definitions of the callbacks.
+-
+-Below sections specify when to call the error callback functions.
+-
+-3.2.2.1 Correctable errors
+-
+-Correctable errors pose no impacts on the functionality of
+-the interface. The PCI Express protocol can recover without any
+-software intervention or any loss of data. These errors do not
+-require any recovery actions. The AER driver clears the device's
+-correctable error status register accordingly and logs these errors.
+-
+-3.2.2.2 Non-correctable (non-fatal and fatal) errors
+-
+-If an error message indicates a non-fatal error, performing link reset
+-at upstream is not required. The AER driver calls error_detected(dev,
+-pci_channel_io_normal) to all drivers associated within a hierarchy in
+-question. for example,
+-EndPoint<==>DownstreamPort B<==>UpstreamPort A<==>RootPort.
+-If Upstream port A captures an AER error, the hierarchy consists of
+-Downstream port B and EndPoint.
+-
+-A driver may return PCI_ERS_RESULT_CAN_RECOVER,
+-PCI_ERS_RESULT_DISCONNECT, or PCI_ERS_RESULT_NEED_RESET, depending on
+-whether it can recover or the AER driver calls mmio_enabled as next.
+-
+-If an error message indicates a fatal error, kernel will broadcast
+-error_detected(dev, pci_channel_io_frozen) to all drivers within
+-a hierarchy in question. Then, performing link reset at upstream is
+-necessary. As different kinds of devices might use different approaches
+-to reset link, AER port service driver is required to provide the
+-function to reset link. Firstly, kernel looks for if the upstream
+-component has an aer driver. If it has, kernel uses the reset_link
+-callback of the aer driver. If the upstream component has no aer driver
+-and the port is downstream port, we will use the aer driver of the
+-root port who reports the AER error. As for upstream ports,
+-they should provide their own aer service drivers with reset_link
+-function. If error_detected returns PCI_ERS_RESULT_CAN_RECOVER and
+-reset_link returns PCI_ERS_RESULT_RECOVERED, the error handling goes
+-to mmio_enabled.
+-
+-3.3 helper functions
+-
+-3.3.1 int pci_find_aer_capability(struct pci_dev *dev);
+-pci_find_aer_capability locates the PCI Express AER capability
+-in the device configuration space. If the device doesn't support
+-PCI-Express AER, the function returns 0.
+-
+-3.3.2 int pci_enable_pcie_error_reporting(struct pci_dev *dev);
+-pci_enable_pcie_error_reporting enables the device to send error
+-messages to root port when an error is detected. Note that devices
+-don't enable the error reporting by default, so device drivers need
+-call this function to enable it.
+-
+-3.3.3 int pci_disable_pcie_error_reporting(struct pci_dev *dev);
+-pci_disable_pcie_error_reporting disables the device to send error
+-messages to root port when an error is detected.
+-
+-3.3.4 int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev);
+-pci_cleanup_aer_uncorrect_error_status cleanups the uncorrectable
+-error status register.
+-
+-3.4 Frequent Asked Questions
+-
+-Q: What happens if a PCI Express device driver does not provide an
+-error recovery handler (pci_driver->err_handler is equal to NULL)?
+-
+-A: The devices attached with the driver won't be recovered. If the
+-error is fatal, kernel will print out warning messages. Please refer
+-to section 3 for more information.
+-
+-Q: What happens if an upstream port service driver does not provide
+-callback reset_link?
+-
+-A: Fatal error recovery will fail if the errors are reported by the
+-upstream ports who are attached by the service driver.
+-
+-Q: How does this infrastructure deal with driver that is not PCI
+-Express aware?
+-
+-A: This infrastructure calls the error callback functions of the
+-driver when an error happens. But if the driver is not aware of
+-PCI Express, the device might not report its own errors to root
+-port.
+-
+-Q: What modifications will that driver need to make it compatible
+-with the PCI Express AER Root driver?
+-
+-A: It could call the helper functions to enable AER in devices and
+-cleanup uncorrectable status register. Pls. refer to section 3.3.
+-
+diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt
+index 461e4f1..421e7d0 100644
+--- a/Documentation/power/devices.txt
++++ b/Documentation/power/devices.txt
+@@ -196,6 +196,11 @@ its parent; and can't be removed or suspended after that parent.
+
+ The policy is that the device tree should match hardware bus topology.
+ (Or at least the control bus, for devices which use multiple busses.)
++In particular, this means that a device registration may fail if the parent of
++the device is suspending (ie. has been chosen by the PM core as the next
++device to suspend) or has already suspended, as well as after all of the other
++devices have been suspended. Device drivers must be prepared to cope with such
++situations.
+
+
+ Suspending Devices
+diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
+index 7b4e8a7..cf89e8c 100644
+--- a/Documentation/powerpc/booting-without-of.txt
++++ b/Documentation/powerpc/booting-without-of.txt
+@@ -59,12 +59,39 @@ Table of Contents
+ p) Freescale Synchronous Serial Interface
+ q) USB EHCI controllers
+
+- VII - Specifying interrupt information for devices
++ VII - Marvell Discovery mv64[345]6x System Controller chips
++ 1) The /system-controller node
++ 2) Child nodes of /system-controller
++ a) Marvell Discovery MDIO bus
++ b) Marvell Discovery ethernet controller
++ c) Marvell Discovery PHY nodes
++ d) Marvell Discovery SDMA nodes
++ e) Marvell Discovery BRG nodes
++ f) Marvell Discovery CUNIT nodes
++ g) Marvell Discovery MPSCROUTING nodes
++ h) Marvell Discovery MPSCINTR nodes
++ i) Marvell Discovery MPSC nodes
++ j) Marvell Discovery Watch Dog Timer nodes
++ k) Marvell Discovery I2C nodes
++ l) Marvell Discovery PIC (Programmable Interrupt Controller) nodes
++ m) Marvell Discovery MPP (Multipurpose Pins) multiplexing nodes
++ n) Marvell Discovery GPP (General Purpose Pins) nodes
++ o) Marvell Discovery PCI host bridge node
++ p) Marvell Discovery CPU Error nodes
++ q) Marvell Discovery SRAM Controller nodes
++ r) Marvell Discovery PCI Error Handler nodes
++ s) Marvell Discovery Memory Controller nodes
++
++ VIII - Specifying interrupt information for devices
+ 1) interrupts property
+ 2) interrupt-parent property
+ 3) OpenPIC Interrupt Controllers
+ 4) ISA Interrupt Controllers
+
++ VIII - Specifying GPIO information for devices
++ 1) gpios property
++ 2) gpio-controller nodes
++
+ Appendix A - Sample SOC node for MPC8540
+
+
+@@ -1269,10 +1296,6 @@ platforms are moved over to use the flattened-device-tree model.
+
+ Recommended properties:
+
+- - linux,network-index : This is the intended "index" of this
+- network device. This is used by the bootwrapper to interpret
+- MAC addresses passed by the firmware when no information other
+- than indices is available to associate an address with a device.
+ - phy-connection-type : a string naming the controller/PHY interface type,
+ i.e., "mii" (default), "rmii", "gmii", "rgmii", "rgmii-id", "sgmii",
+ "tbi", or "rtbi". This property is only really needed if the connection
+@@ -1622,8 +1645,7 @@ platforms are moved over to use the flattened-device-tree model.
+ - device_type : should be "network", "hldc", "uart", "transparent"
+ "bisync", "atm", or "serial".
+ - compatible : could be "ucc_geth" or "fsl_atm" and so on.
+- - model : should be "UCC".
+- - device-id : the ucc number(1-8), corresponding to UCCx in UM.
++ - cell-index : the ucc number(1-8), corresponding to UCCx in UM.
+ - reg : Offset and length of the register set for the device
+ - interrupts : <a b> where a is the interrupt number and b is a
+ field that represents an encoding of the sense and level
+@@ -1667,10 +1689,6 @@ platforms are moved over to use the flattened-device-tree model.
+ - phy-handle : The phandle for the PHY connected to this controller.
+
+ Recommended properties:
+- - linux,network-index : This is the intended "index" of this
+- network device. This is used by the bootwrapper to interpret
+- MAC addresses passed by the firmware when no information other
+- than indices is available to associate an address with a device.
+ - phy-connection-type : a string naming the controller/PHY interface type,
+ i.e., "mii" (default), "rmii", "gmii", "rgmii", "rgmii-id" (Internal
+ Delay), "rgmii-txid" (delay on TX only), "rgmii-rxid" (delay on RX only),
+@@ -1680,8 +1698,7 @@ platforms are moved over to use the flattened-device-tree model.
+ ucc at 2000 {
+ device_type = "network";
+ compatible = "ucc_geth";
+- model = "UCC";
+- device-id = <1>;
++ cell-index = <1>;
+ reg = <2000 200>;
+ interrupts = <a0 0>;
+ interrupt-parent = <700>;
+@@ -1995,7 +2012,6 @@ platforms are moved over to use the flattened-device-tree model.
+ interrupts = <20 8>;
+ interrupt-parent = <&PIC>;
+ phy-handle = <&PHY0>;
+- linux,network-index = <0>;
+ fsl,cpm-command = <12000300>;
+ };
+
+@@ -2217,12 +2233,6 @@ platforms are moved over to use the flattened-device-tree model.
+ EMAC, that is the content of the current (bogus) "phy-port"
+ property.
+
+- Recommended properties:
+- - linux,network-index : This is the intended "index" of this
+- network device. This is used by the bootwrapper to interpret
+- MAC addresses passed by the firmware when no information other
+- than indices is available to associate an address with a device.
+-
+ Optional properties:
+ - phy-address : 1 cell, optional, MDIO address of the PHY. If absent,
+ a search is performed.
+@@ -2246,7 +2256,6 @@ platforms are moved over to use the flattened-device-tree model.
+ Example:
+
+ EMAC0: ethernet at 40000800 {
+- linux,network-index = <0>;
+ device_type = "network";
+ compatible = "ibm,emac-440gp", "ibm,emac";
+ interrupt-parent = <&UIC1>;
+@@ -2592,6 +2601,17 @@ platforms are moved over to use the flattened-device-tree model.
+ differ between different families. May be
+ 'virtex2p', 'virtex4', or 'virtex5'.
+
++ vi) Xilinx Uart 16550
++
++ Xilinx UART 16550 devices are very similar to the NS16550 but with
++ different register spacing and an offset from the base address.
++
++ Requred properties:
++ - clock-frequency : Frequency of the clock input
++ - reg-offset : A value of 3 is required
++ - reg-shift : A value of 2 is required
++
++
+ p) Freescale Synchronous Serial Interface
+
+ The SSI is a serial device that communicates with audio codecs. It can
+@@ -2817,9 +2837,528 @@ platforms are moved over to use the flattened-device-tree model.
+ };
+
+
+- More devices will be defined as this spec matures.
++VII - Marvell Discovery mv64[345]6x System Controller chips
++===========================================================
++
++The Marvell mv64[345]60 series of system controller chips contain
++many of the peripherals needed to implement a complete computer
++system. In this section, we define device tree nodes to describe
++the system controller chip itself and each of the peripherals
++which it contains. Compatible string values for each node are
++prefixed with the string "marvell,", for Marvell Technology Group Ltd.
++
++1) The /system-controller node
++
++ This node is used to represent the system-controller and must be
++ present when the system uses a system contller chip. The top-level
++ system-controller node contains information that is global to all
++ devices within the system controller chip. The node name begins
++ with "system-controller" followed by the unit address, which is
++ the base address of the memory-mapped register set for the system
++ controller chip.
++
++ Required properties:
++
++ - ranges : Describes the translation of system controller addresses
++ for memory mapped registers.
++ - clock-frequency: Contains the main clock frequency for the system
++ controller chip.
++ - reg : This property defines the address and size of the
++ memory-mapped registers contained within the system controller
++ chip. The address specified in the "reg" property should match
++ the unit address of the system-controller node.
++ - #address-cells : Address representation for system controller
++ devices. This field represents the number of cells needed to
++ represent the address of the memory-mapped registers of devices
++ within the system controller chip.
++ - #size-cells : Size representation for for the memory-mapped
++ registers within the system controller chip.
++ - #interrupt-cells : Defines the width of cells used to represent
++ interrupts.
++
++ Optional properties:
++
++ - model : The specific model of the system controller chip. Such
++ as, "mv64360", "mv64460", or "mv64560".
++ - compatible : A string identifying the compatibility identifiers
++ of the system controller chip.
++
++ The system-controller node contains child nodes for each system
++ controller device that the platform uses. Nodes should not be created
++ for devices which exist on the system controller chip but are not used
++
++ Example Marvell Discovery mv64360 system-controller node:
++
++ system-controller at f1000000 { /* Marvell Discovery mv64360 */
++ #address-cells = <1>;
++ #size-cells = <1>;
++ model = "mv64360"; /* Default */
++ compatible = "marvell,mv64360";
++ clock-frequency = <133333333>;
++ reg = <0xf1000000 0x10000>;
++ virtual-reg = <0xf1000000>;
++ ranges = <0x88000000 0x88000000 0x1000000 /* PCI 0 I/O Space */
++ 0x80000000 0x80000000 0x8000000 /* PCI 0 MEM Space */
++ 0xa0000000 0xa0000000 0x4000000 /* User FLASH */
++ 0x00000000 0xf1000000 0x0010000 /* Bridge's regs */
++ 0xf2000000 0xf2000000 0x0040000>;/* Integrated SRAM */
++
++ [ child node definitions... ]
++ }
++
++2) Child nodes of /system-controller
++
++ a) Marvell Discovery MDIO bus
++
++ The MDIO is a bus to which the PHY devices are connected. For each
++ device that exists on this bus, a child node should be created. See
++ the definition of the PHY node below for an example of how to define
++ a PHY.
++
++ Required properties:
++ - #address-cells : Should be <1>
++ - #size-cells : Should be <0>
++ - device_type : Should be "mdio"
++ - compatible : Should be "marvell,mv64360-mdio"
++
++ Example:
++
++ mdio {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ device_type = "mdio";
++ compatible = "marvell,mv64360-mdio";
++
++ ethernet-phy at 0 {
++ ......
++ };
++ };
++
++
++ b) Marvell Discovery ethernet controller
++
++ The Discover ethernet controller is described with two levels
++ of nodes. The first level describes an ethernet silicon block
++ and the second level describes up to 3 ethernet nodes within
++ that block. The reason for the multiple levels is that the
++ registers for the node are interleaved within a single set
++ of registers. The "ethernet-block" level describes the
++ shared register set, and the "ethernet" nodes describe ethernet
++ port-specific properties.
++
++ Ethernet block node
++
++ Required properties:
++ - #address-cells : <1>
++ - #size-cells : <0>
++ - compatible : "marvell,mv64360-eth-block"
++ - reg : Offset and length of the register set for this block
++
++ Example Discovery Ethernet block node:
++ ethernet-block at 2000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "marvell,mv64360-eth-block";
++ reg = <0x2000 0x2000>;
++ ethernet at 0 {
++ .......
++ };
++ };
++
++ Ethernet port node
++
++ Required properties:
++ - device_type : Should be "network".
++ - compatible : Should be "marvell,mv64360-eth".
++ - reg : Should be <0>, <1>, or <2>, according to which registers
++ within the silicon block the device uses.
++ - interrupts : <a> where a is the interrupt number for the port.
++ - interrupt-parent : the phandle for the interrupt controller
++ that services interrupts for this device.
++ - phy : the phandle for the PHY connected to this ethernet
++ controller.
++ - local-mac-address : 6 bytes, MAC address
++
++ Example Discovery Ethernet port node:
++ ethernet at 0 {
++ device_type = "network";
++ compatible = "marvell,mv64360-eth";
++ reg = <0>;
++ interrupts = <32>;
++ interrupt-parent = <&PIC>;
++ phy = <&PHY0>;
++ local-mac-address = [ 00 00 00 00 00 00 ];
++ };
++
++
++
++ c) Marvell Discovery PHY nodes
++
++ Required properties:
++ - device_type : Should be "ethernet-phy"
++ - interrupts : <a> where a is the interrupt number for this phy.
++ - interrupt-parent : the phandle for the interrupt controller that
++ services interrupts for this device.
++ - reg : The ID number for the phy, usually a small integer
++
++ Example Discovery PHY node:
++ ethernet-phy at 1 {
++ device_type = "ethernet-phy";
++ compatible = "broadcom,bcm5421";
++ interrupts = <76>; /* GPP 12 */
++ interrupt-parent = <&PIC>;
++ reg = <1>;
++ };
++
++
++ d) Marvell Discovery SDMA nodes
++
++ Represent DMA hardware associated with the MPSC (multiprotocol
++ serial controllers).
++
++ Required properties:
++ - compatible : "marvell,mv64360-sdma"
++ - reg : Offset and length of the register set for this device
++ - interrupts : <a> where a is the interrupt number for the DMA
++ device.
++ - interrupt-parent : the phandle for the interrupt controller
++ that services interrupts for this device.
++
++ Example Discovery SDMA node:
++ sdma at 4000 {
++ compatible = "marvell,mv64360-sdma";
++ reg = <0x4000 0xc18>;
++ virtual-reg = <0xf1004000>;
++ interrupts = <36>;
++ interrupt-parent = <&PIC>;
++ };
++
++
++ e) Marvell Discovery BRG nodes
++
++ Represent baud rate generator hardware associated with the MPSC
++ (multiprotocol serial controllers).
++
++ Required properties:
++ - compatible : "marvell,mv64360-brg"
++ - reg : Offset and length of the register set for this device
++ - clock-src : A value from 0 to 15 which selects the clock
++ source for the baud rate generator. This value corresponds
++ to the CLKS value in the BRGx configuration register. See
++ the mv64x60 User's Manual.
++ - clock-frequence : The frequency (in Hz) of the baud rate
++ generator's input clock.
++ - current-speed : The current speed setting (presumably by
++ firmware) of the baud rate generator.
++
++ Example Discovery BRG node:
++ brg at b200 {
++ compatible = "marvell,mv64360-brg";
++ reg = <0xb200 0x8>;
++ clock-src = <8>;
++ clock-frequency = <133333333>;
++ current-speed = <9600>;
++ };
++
++
++ f) Marvell Discovery CUNIT nodes
++
++ Represent the Serial Communications Unit device hardware.
++
++ Required properties:
++ - reg : Offset and length of the register set for this device
++
++ Example Discovery CUNIT node:
++ cunit at f200 {
++ reg = <0xf200 0x200>;
++ };
++
++
++ g) Marvell Discovery MPSCROUTING nodes
++
++ Represent the Discovery's MPSC routing hardware
++
++ Required properties:
++ - reg : Offset and length of the register set for this device
++
++ Example Discovery CUNIT node:
++ mpscrouting at b500 {
++ reg = <0xb400 0xc>;
++ };
++
++
++ h) Marvell Discovery MPSCINTR nodes
+
+-VII - Specifying interrupt information for devices
++ Represent the Discovery's MPSC DMA interrupt hardware registers
++ (SDMA cause and mask registers).
++
++ Required properties:
++ - reg : Offset and length of the register set for this device
++
++ Example Discovery MPSCINTR node:
++ mpsintr at b800 {
++ reg = <0xb800 0x100>;
++ };
++
++
++ i) Marvell Discovery MPSC nodes
++
++ Represent the Discovery's MPSC (Multiprotocol Serial Controller)
++ serial port.
++
++ Required properties:
++ - device_type : "serial"
++ - compatible : "marvell,mv64360-mpsc"
++ - reg : Offset and length of the register set for this device
++ - sdma : the phandle for the SDMA node used by this port
++ - brg : the phandle for the BRG node used by this port
++ - cunit : the phandle for the CUNIT node used by this port
++ - mpscrouting : the phandle for the MPSCROUTING node used by this port
++ - mpscintr : the phandle for the MPSCINTR node used by this port
++ - cell-index : the hardware index of this cell in the MPSC core
++ - max_idle : value needed for MPSC CHR3 (Maximum Frame Length)
++ register
++ - interrupts : <a> where a is the interrupt number for the MPSC.
++ - interrupt-parent : the phandle for the interrupt controller
++ that services interrupts for this device.
++
++ Example Discovery MPSCINTR node:
++ mpsc at 8000 {
++ device_type = "serial";
++ compatible = "marvell,mv64360-mpsc";
++ reg = <0x8000 0x38>;
++ virtual-reg = <0xf1008000>;
++ sdma = <&SDMA0>;
++ brg = <&BRG0>;
++ cunit = <&CUNIT>;
++ mpscrouting = <&MPSCROUTING>;
++ mpscintr = <&MPSCINTR>;
++ cell-index = <0>;
++ max_idle = <40>;
++ interrupts = <40>;
++ interrupt-parent = <&PIC>;
++ };
++
++
++ j) Marvell Discovery Watch Dog Timer nodes
++
++ Represent the Discovery's watchdog timer hardware
++
++ Required properties:
++ - compatible : "marvell,mv64360-wdt"
++ - reg : Offset and length of the register set for this device
++
++ Example Discovery Watch Dog Timer node:
++ wdt at b410 {
++ compatible = "marvell,mv64360-wdt";
++ reg = <0xb410 0x8>;
++ };
++
++
++ k) Marvell Discovery I2C nodes
++
++ Represent the Discovery's I2C hardware
++
++ Required properties:
++ - device_type : "i2c"
++ - compatible : "marvell,mv64360-i2c"
++ - reg : Offset and length of the register set for this device
++ - interrupts : <a> where a is the interrupt number for the I2C.
++ - interrupt-parent : the phandle for the interrupt controller
++ that services interrupts for this device.
++
++ Example Discovery I2C node:
++ compatible = "marvell,mv64360-i2c";
++ reg = <0xc000 0x20>;
++ virtual-reg = <0xf100c000>;
++ interrupts = <37>;
++ interrupt-parent = <&PIC>;
++ };
++
++
++ l) Marvell Discovery PIC (Programmable Interrupt Controller) nodes
++
++ Represent the Discovery's PIC hardware
++
++ Required properties:
++ - #interrupt-cells : <1>
++ - #address-cells : <0>
++ - compatible : "marvell,mv64360-pic"
++ - reg : Offset and length of the register set for this device
++ - interrupt-controller
++
++ Example Discovery PIC node:
++ pic {
++ #interrupt-cells = <1>;
++ #address-cells = <0>;
++ compatible = "marvell,mv64360-pic";
++ reg = <0x0 0x88>;
++ interrupt-controller;
++ };
++
++
++ m) Marvell Discovery MPP (Multipurpose Pins) multiplexing nodes
++
++ Represent the Discovery's MPP hardware
++
++ Required properties:
++ - compatible : "marvell,mv64360-mpp"
++ - reg : Offset and length of the register set for this device
++
++ Example Discovery MPP node:
++ mpp at f000 {
++ compatible = "marvell,mv64360-mpp";
++ reg = <0xf000 0x10>;
++ };
++
++
++ n) Marvell Discovery GPP (General Purpose Pins) nodes
++
++ Represent the Discovery's GPP hardware
++
++ Required properties:
++ - compatible : "marvell,mv64360-gpp"
++ - reg : Offset and length of the register set for this device
++
++ Example Discovery GPP node:
++ gpp at f000 {
++ compatible = "marvell,mv64360-gpp";
++ reg = <0xf100 0x20>;
++ };
++
++
++ o) Marvell Discovery PCI host bridge node
++
++ Represents the Discovery's PCI host bridge device. The properties
++ for this node conform to Rev 2.1 of the PCI Bus Binding to IEEE
++ 1275-1994. A typical value for the compatible property is
++ "marvell,mv64360-pci".
++
++ Example Discovery PCI host bridge node
++ pci at 80000000 {
++ #address-cells = <3>;
++ #size-cells = <2>;
++ #interrupt-cells = <1>;
++ device_type = "pci";
++ compatible = "marvell,mv64360-pci";
++ reg = <0xcf8 0x8>;
++ ranges = <0x01000000 0x0 0x0
++ 0x88000000 0x0 0x01000000
++ 0x02000000 0x0 0x80000000
++ 0x80000000 0x0 0x08000000>;
++ bus-range = <0 255>;
++ clock-frequency = <66000000>;
++ interrupt-parent = <&PIC>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
++ interrupt-map = <
++ /* IDSEL 0x0a */
++ 0x5000 0 0 1 &PIC 80
++ 0x5000 0 0 2 &PIC 81
++ 0x5000 0 0 3 &PIC 91
++ 0x5000 0 0 4 &PIC 93
++
++ /* IDSEL 0x0b */
++ 0x5800 0 0 1 &PIC 91
++ 0x5800 0 0 2 &PIC 93
++ 0x5800 0 0 3 &PIC 80
++ 0x5800 0 0 4 &PIC 81
++
++ /* IDSEL 0x0c */
++ 0x6000 0 0 1 &PIC 91
++ 0x6000 0 0 2 &PIC 93
++ 0x6000 0 0 3 &PIC 80
++ 0x6000 0 0 4 &PIC 81
++
++ /* IDSEL 0x0d */
++ 0x6800 0 0 1 &PIC 93
++ 0x6800 0 0 2 &PIC 80
++ 0x6800 0 0 3 &PIC 81
++ 0x6800 0 0 4 &PIC 91
++ >;
++ };
++
++
++ p) Marvell Discovery CPU Error nodes
++
++ Represent the Discovery's CPU error handler device.
++
++ Required properties:
++ - compatible : "marvell,mv64360-cpu-error"
++ - reg : Offset and length of the register set for this device
++ - interrupts : the interrupt number for this device
++ - interrupt-parent : the phandle for the interrupt controller
++ that services interrupts for this device.
++
++ Example Discovery CPU Error node:
++ cpu-error at 0070 {
++ compatible = "marvell,mv64360-cpu-error";
++ reg = <0x70 0x10 0x128 0x28>;
++ interrupts = <3>;
++ interrupt-parent = <&PIC>;
++ };
++
++
++ q) Marvell Discovery SRAM Controller nodes
++
++ Represent the Discovery's SRAM controller device.
++
++ Required properties:
++ - compatible : "marvell,mv64360-sram-ctrl"
++ - reg : Offset and length of the register set for this device
++ - interrupts : the interrupt number for this device
++ - interrupt-parent : the phandle for the interrupt controller
++ that services interrupts for this device.
++
++ Example Discovery SRAM Controller node:
++ sram-ctrl at 0380 {
++ compatible = "marvell,mv64360-sram-ctrl";
++ reg = <0x380 0x80>;
++ interrupts = <13>;
++ interrupt-parent = <&PIC>;
++ };
++
++
++ r) Marvell Discovery PCI Error Handler nodes
++
++ Represent the Discovery's PCI error handler device.
++
++ Required properties:
++ - compatible : "marvell,mv64360-pci-error"
++ - reg : Offset and length of the register set for this device
++ - interrupts : the interrupt number for this device
++ - interrupt-parent : the phandle for the interrupt controller
++ that services interrupts for this device.
++
++ Example Discovery PCI Error Handler node:
++ pci-error at 1d40 {
++ compatible = "marvell,mv64360-pci-error";
++ reg = <0x1d40 0x40 0xc28 0x4>;
++ interrupts = <12>;
++ interrupt-parent = <&PIC>;
++ };
++
++
++ s) Marvell Discovery Memory Controller nodes
++
++ Represent the Discovery's memory controller device.
++
++ Required properties:
++ - compatible : "marvell,mv64360-mem-ctrl"
++ - reg : Offset and length of the register set for this device
++ - interrupts : the interrupt number for this device
++ - interrupt-parent : the phandle for the interrupt controller
++ that services interrupts for this device.
++
++ Example Discovery Memory Controller node:
++ mem-ctrl at 1400 {
++ compatible = "marvell,mv64360-mem-ctrl";
++ reg = <0x1400 0x60>;
++ interrupts = <17>;
++ interrupt-parent = <&PIC>;
++ };
++
++
++VIII - Specifying interrupt information for devices
+ ===================================================
+
+ The device tree represents the busses and devices of a hardware
+@@ -2905,6 +3444,54 @@ encodings listed below:
+ 2 = high to low edge sensitive type enabled
+ 3 = low to high edge sensitive type enabled
+
++VIII - Specifying GPIO information for devices
++==============================================
++
++1) gpios property
++-----------------
++
++Nodes that makes use of GPIOs should define them using `gpios' property,
++format of which is: <&gpio-controller1-phandle gpio1-specifier
++ &gpio-controller2-phandle gpio2-specifier
++ 0 /* holes are permitted, means no GPIO 3 */
++ &gpio-controller4-phandle gpio4-specifier
++ ...>;
++
++Note that gpio-specifier length is controller dependent.
++
++gpio-specifier may encode: bank, pin position inside the bank,
++whether pin is open-drain and whether pin is logically inverted.
++
++Example of the node using GPIOs:
++
++ node {
++ gpios = <&qe_pio_e 18 0>;
++ };
++
++In this example gpio-specifier is "18 0" and encodes GPIO pin number,
++and empty GPIO flags as accepted by the "qe_pio_e" gpio-controller.
++
++2) gpio-controller nodes
++------------------------
++
++Every GPIO controller node must have #gpio-cells property defined,
++this information will be used to translate gpio-specifiers.
++
++Example of two SOC GPIO banks defined as gpio-controller nodes:
++
++ qe_pio_a: gpio-controller at 1400 {
++ #gpio-cells = <2>;
++ compatible = "fsl,qe-pario-bank-a", "fsl,qe-pario-bank";
++ reg = <0x1400 0x18>;
++ gpio-controller;
++ };
++
++ qe_pio_e: gpio-controller at 1460 {
++ #gpio-cells = <2>;
++ compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
++ reg = <0x1460 0x18>;
++ gpio-controller;
++ };
+
+ Appendix A - Sample SOC node for MPC8540
+ ========================================
+diff --git a/Documentation/powerpc/phyp-assisted-dump.txt b/Documentation/powerpc/phyp-assisted-dump.txt
+new file mode 100644
+index 0000000..c4682b9
+--- /dev/null
++++ b/Documentation/powerpc/phyp-assisted-dump.txt
+@@ -0,0 +1,127 @@
++
++ Hypervisor-Assisted Dump
++ ------------------------
++ November 2007
++
++The goal of hypervisor-assisted dump is to enable the dump of
++a crashed system, and to do so from a fully-reset system, and
++to minimize the total elapsed time until the system is back
++in production use.
++
++As compared to kdump or other strategies, hypervisor-assisted
++dump offers several strong, practical advantages:
++
++-- Unlike kdump, the system has been reset, and loaded
++ with a fresh copy of the kernel. In particular,
++ PCI and I/O devices have been reinitialized and are
++ in a clean, consistent state.
++-- As the dump is performed, the dumped memory becomes
++ immediately available to the system for normal use.
++-- After the dump is completed, no further reboots are
++ required; the system will be fully usable, and running
++ in it's normal, production mode on it normal kernel.
++
++The above can only be accomplished by coordination with,
++and assistance from the hypervisor. The procedure is
++as follows:
++
++-- When a system crashes, the hypervisor will save
++ the low 256MB of RAM to a previously registered
++ save region. It will also save system state, system
++ registers, and hardware PTE's.
++
++-- After the low 256MB area has been saved, the
++ hypervisor will reset PCI and other hardware state.
++ It will *not* clear RAM. It will then launch the
++ bootloader, as normal.
++
++-- The freshly booted kernel will notice that there
++ is a new node (ibm,dump-kernel) in the device tree,
++ indicating that there is crash data available from
++ a previous boot. It will boot into only 256MB of RAM,
++ reserving the rest of system memory.
++
++-- Userspace tools will parse /sys/kernel/release_region
++ and read /proc/vmcore to obtain the contents of memory,
++ which holds the previous crashed kernel. The userspace
++ tools may copy this info to disk, or network, nas, san,
++ iscsi, etc. as desired.
++
++ For Example: the values in /sys/kernel/release-region
++ would look something like this (address-range pairs).
++ CPU:0x177fee000-0x10000: HPTE:0x177ffe020-0x1000: /
++ DUMP:0x177fff020-0x10000000, 0x10000000-0x16F1D370A
++
++-- As the userspace tools complete saving a portion of
++ dump, they echo an offset and size to
++ /sys/kernel/release_region to release the reserved
++ memory back to general use.
++
++ An example of this is:
++ "echo 0x40000000 0x10000000 > /sys/kernel/release_region"
++ which will release 256MB at the 1GB boundary.
++
++Please note that the hypervisor-assisted dump feature
++is only available on Power6-based systems with recent
++firmware versions.
++
++Implementation details:
++----------------------
++
++During boot, a check is made to see if firmware supports
++this feature on this particular machine. If it does, then
++we check to see if a active dump is waiting for us. If yes
++then everything but 256 MB of RAM is reserved during early
++boot. This area is released once we collect a dump from user
++land scripts that are run. If there is dump data, then
++the /sys/kernel/release_region file is created, and
++the reserved memory is held.
++
++If there is no waiting dump data, then only the highest
++256MB of the ram is reserved as a scratch area. This area
++is *not* released: this region will be kept permanently
++reserved, so that it can act as a receptacle for a copy
++of the low 256MB in the case a crash does occur. See,
++however, "open issues" below, as to whether
++such a reserved region is really needed.
++
++Currently the dump will be copied from /proc/vmcore to a
++a new file upon user intervention. The starting address
++to be read and the range for each data point in provided
++in /sys/kernel/release_region.
++
++The tools to examine the dump will be same as the ones
++used for kdump.
++
++General notes:
++--------------
++Security: please note that there are potential security issues
++with any sort of dump mechanism. In particular, plaintext
++(unencrypted) data, and possibly passwords, may be present in
++the dump data. Userspace tools must take adequate precautions to
++preserve security.
++
++Open issues/ToDo:
++------------
++ o The various code paths that tell the hypervisor that a crash
++ occurred, vs. it simply being a normal reboot, should be
++ reviewed, and possibly clarified/fixed.
++
++ o Instead of using /sys/kernel, should there be a /sys/dump
++ instead? There is a dump_subsys being created by the s390 code,
++ perhaps the pseries code should use a similar layout as well.
++
++ o Is reserving a 256MB region really required? The goal of
++ reserving a 256MB scratch area is to make sure that no
++ important crash data is clobbered when the hypervisor
++ save low mem to the scratch area. But, if one could assure
++ that nothing important is located in some 256MB area, then
++ it would not need to be reserved. Something that can be
++ improved in subsequent versions.
++
++ o Still working the kdump team to integrate this with kdump,
++ some work remains but this would not affect the current
++ patches.
++
++ o Still need to write a shell script, to copy the dump away.
++ Currently I am parsing it manually.
+diff --git a/Documentation/prctl/disable-tsc-ctxt-sw-stress-test.c b/Documentation/prctl/disable-tsc-ctxt-sw-stress-test.c
+new file mode 100644
+index 0000000..f8e8e95
+--- /dev/null
++++ b/Documentation/prctl/disable-tsc-ctxt-sw-stress-test.c
+@@ -0,0 +1,96 @@
++/*
++ * Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...)
++ *
++ * Tests if the control register is updated correctly
++ * at context switches
++ *
++ * Warning: this test will cause a very high load for a few seconds
++ *
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <signal.h>
++#include <inttypes.h>
++#include <wait.h>
++
++
++#include <sys/prctl.h>
++#include <linux/prctl.h>
++
++/* Get/set the process' ability to use the timestamp counter instruction */
++#ifndef PR_GET_TSC
++#define PR_GET_TSC 25
++#define PR_SET_TSC 26
++# define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */
++# define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */
++#endif
++
++uint64_t rdtsc() {
++uint32_t lo, hi;
++/* We cannot use "=A", since this would use %rax on x86_64 */
++__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
++return (uint64_t)hi << 32 | lo;
++}
++
++void sigsegv_expect(int sig)
++{
++ /* */
++}
++
++void segvtask(void)
++{
++ if (prctl(PR_SET_TSC, PR_TSC_SIGSEGV) < 0)
++ {
++ perror("prctl");
++ exit(0);
++ }
++ signal(SIGSEGV, sigsegv_expect);
++ alarm(10);
++ rdtsc();
++ fprintf(stderr, "FATAL ERROR, rdtsc() succeeded while disabled\n");
++ exit(0);
++}
++
++
++void sigsegv_fail(int sig)
++{
++ fprintf(stderr, "FATAL ERROR, rdtsc() failed while enabled\n");
++ exit(0);
++}
++
++void rdtsctask(void)
++{
++ if (prctl(PR_SET_TSC, PR_TSC_ENABLE) < 0)
++ {
++ perror("prctl");
++ exit(0);
++ }
++ signal(SIGSEGV, sigsegv_fail);
++ alarm(10);
++ for(;;) rdtsc();
++}
++
++
++int main(int argc, char **argv)
++{
++ int n_tasks = 100, i;
++
++ fprintf(stderr, "[No further output means we're allright]\n");
++
++ for (i=0; i<n_tasks; i++)
++ if (fork() == 0)
++ {
++ if (i & 1)
++ segvtask();
++ else
++ rdtsctask();
++ }
++
++ for (i=0; i<n_tasks; i++)
++ wait(NULL);
++
++ exit(0);
++}
++
+diff --git a/Documentation/prctl/disable-tsc-on-off-stress-test.c b/Documentation/prctl/disable-tsc-on-off-stress-test.c
+new file mode 100644
+index 0000000..1fcd914
+--- /dev/null
++++ b/Documentation/prctl/disable-tsc-on-off-stress-test.c
+@@ -0,0 +1,95 @@
++/*
++ * Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...)
++ *
++ * Tests if the control register is updated correctly
++ * when set with prctl()
++ *
++ * Warning: this test will cause a very high load for a few seconds
++ *
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <signal.h>
++#include <inttypes.h>
++#include <wait.h>
++
++
++#include <sys/prctl.h>
++#include <linux/prctl.h>
++
++/* Get/set the process' ability to use the timestamp counter instruction */
++#ifndef PR_GET_TSC
++#define PR_GET_TSC 25
++#define PR_SET_TSC 26
++# define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */
++# define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */
++#endif
++
++/* snippet from wikipedia :-) */
++
++uint64_t rdtsc() {
++uint32_t lo, hi;
++/* We cannot use "=A", since this would use %rax on x86_64 */
++__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
++return (uint64_t)hi << 32 | lo;
++}
++
++int should_segv = 0;
++
++void sigsegv_cb(int sig)
++{
++ if (!should_segv)
++ {
++ fprintf(stderr, "FATAL ERROR, rdtsc() failed while enabled\n");
++ exit(0);
++ }
++ if (prctl(PR_SET_TSC, PR_TSC_ENABLE) < 0)
++ {
++ perror("prctl");
++ exit(0);
++ }
++ should_segv = 0;
++
++ rdtsc();
++}
++
++void task(void)
++{
++ signal(SIGSEGV, sigsegv_cb);
++ alarm(10);
++ for(;;)
++ {
++ rdtsc();
++ if (should_segv)
++ {
++ fprintf(stderr, "FATAL ERROR, rdtsc() succeeded while disabled\n");
++ exit(0);
++ }
++ if (prctl(PR_SET_TSC, PR_TSC_SIGSEGV) < 0)
++ {
++ perror("prctl");
++ exit(0);
++ }
++ should_segv = 1;
++ }
++}
++
++
++int main(int argc, char **argv)
++{
++ int n_tasks = 100, i;
++
++ fprintf(stderr, "[No further output means we're allright]\n");
++
++ for (i=0; i<n_tasks; i++)
++ if (fork() == 0)
++ task();
++
++ for (i=0; i<n_tasks; i++)
++ wait(NULL);
++
++ exit(0);
++}
++
+diff --git a/Documentation/prctl/disable-tsc-test.c b/Documentation/prctl/disable-tsc-test.c
+new file mode 100644
+index 0000000..843c81e
+--- /dev/null
++++ b/Documentation/prctl/disable-tsc-test.c
+@@ -0,0 +1,94 @@
++/*
++ * Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...)
++ *
++ * Basic test to test behaviour of PR_GET_TSC and PR_SET_TSC
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <signal.h>
++#include <inttypes.h>
++
++
++#include <sys/prctl.h>
++#include <linux/prctl.h>
++
++/* Get/set the process' ability to use the timestamp counter instruction */
++#ifndef PR_GET_TSC
++#define PR_GET_TSC 25
++#define PR_SET_TSC 26
++# define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */
++# define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */
++#endif
++
++const char *tsc_names[] =
++{
++ [0] = "[not set]",
++ [PR_TSC_ENABLE] = "PR_TSC_ENABLE",
++ [PR_TSC_SIGSEGV] = "PR_TSC_SIGSEGV",
++};
++
++uint64_t rdtsc() {
++uint32_t lo, hi;
++/* We cannot use "=A", since this would use %rax on x86_64 */
++__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
++return (uint64_t)hi << 32 | lo;
++}
++
++void sigsegv_cb(int sig)
++{
++ int tsc_val = 0;
++
++ printf("[ SIG_SEGV ]\n");
++ printf("prctl(PR_GET_TSC, &tsc_val); ");
++ fflush(stdout);
++
++ if ( prctl(PR_GET_TSC, &tsc_val) == -1)
++ perror("prctl");
++
++ printf("tsc_val == %s\n", tsc_names[tsc_val]);
++ printf("prctl(PR_SET_TSC, PR_TSC_ENABLE)\n");
++ fflush(stdout);
++ if ( prctl(PR_SET_TSC, PR_TSC_ENABLE) == -1)
++ perror("prctl");
++
++ printf("rdtsc() == ");
++}
++
++int main(int argc, char **argv)
++{
++ int tsc_val = 0;
++
++ signal(SIGSEGV, sigsegv_cb);
++
++ printf("rdtsc() == %llu\n", (unsigned long long)rdtsc());
++ printf("prctl(PR_GET_TSC, &tsc_val); ");
++ fflush(stdout);
++
++ if ( prctl(PR_GET_TSC, &tsc_val) == -1)
++ perror("prctl");
++
++ printf("tsc_val == %s\n", tsc_names[tsc_val]);
++ printf("rdtsc() == %llu\n", (unsigned long long)rdtsc());
++ printf("prctl(PR_SET_TSC, PR_TSC_ENABLE)\n");
++ fflush(stdout);
++
++ if ( prctl(PR_SET_TSC, PR_TSC_ENABLE) == -1)
++ perror("prctl");
++
++ printf("rdtsc() == %llu\n", (unsigned long long)rdtsc());
++ printf("prctl(PR_SET_TSC, PR_TSC_SIGSEGV)\n");
++ fflush(stdout);
++
++ if ( prctl(PR_SET_TSC, PR_TSC_SIGSEGV) == -1)
++ perror("prctl");
++
++ printf("rdtsc() == ");
++ fflush(stdout);
++ printf("%llu\n", (unsigned long long)rdtsc());
++ fflush(stdout);
++
++ exit(EXIT_SUCCESS);
++}
++
+diff --git a/Documentation/s390/s390dbf.txt b/Documentation/s390/s390dbf.txt
+index 0eb7c58..e054209 100644
+--- a/Documentation/s390/s390dbf.txt
++++ b/Documentation/s390/s390dbf.txt
+@@ -115,6 +115,27 @@ Return Value: Handle for generated debug area
+ Description: Allocates memory for a debug log
+ Must not be called within an interrupt handler
+
++----------------------------------------------------------------------------
++debug_info_t *debug_register_mode(char *name, int pages, int nr_areas,
++ int buf_size, mode_t mode, uid_t uid,
++ gid_t gid);
++
++Parameter: name: Name of debug log (e.g. used for debugfs entry)
++ pages: Number of pages, which will be allocated per area
++ nr_areas: Number of debug areas
++ buf_size: Size of data area in each debug entry
++ mode: File mode for debugfs files. E.g. S_IRWXUGO
++ uid: User ID for debugfs files. Currently only 0 is
++ supported.
++ gid: Group ID for debugfs files. Currently only 0 is
++ supported.
++
++Return Value: Handle for generated debug area
++ NULL if register failed
++
++Description: Allocates memory for a debug log
++ Must not be called within an interrupt handler
++
+ ---------------------------------------------------------------------------
+ void debug_unregister (debug_info_t * id);
+
+diff --git a/Documentation/scheduler/sched-rt-group.txt b/Documentation/scheduler/sched-rt-group.txt
+index 1c6332f..14f901f 100644
+--- a/Documentation/scheduler/sched-rt-group.txt
++++ b/Documentation/scheduler/sched-rt-group.txt
+@@ -1,59 +1,177 @@
++ Real-Time group scheduling
++ --------------------------
+
++CONTENTS
++========
+
+-Real-Time group scheduling.
++1. Overview
++ 1.1 The problem
++ 1.2 The solution
++2. The interface
++ 2.1 System-wide settings
++ 2.2 Default behaviour
++ 2.3 Basis for grouping tasks
++3. Future plans
+
+-The problem space:
+
+-In order to schedule multiple groups of realtime tasks each group must
+-be assigned a fixed portion of the CPU time available. Without a minimum
+-guarantee a realtime group can obviously fall short. A fuzzy upper limit
+-is of no use since it cannot be relied upon. Which leaves us with just
+-the single fixed portion.
++1. Overview
++===========
+
+-CPU time is divided by means of specifying how much time can be spent
+-running in a given period. Say a frame fixed realtime renderer must
+-deliver 25 frames a second, which yields a period of 0.04s. Now say
+-it will also have to play some music and respond to input, leaving it
+-with around 80% for the graphics. We can then give this group a runtime
+-of 0.8 * 0.04s = 0.032s.
+
+-This way the graphics group will have a 0.04s period with a 0.032s runtime
+-limit.
++1.1 The problem
++---------------
+
+-Now if the audio thread needs to refill the DMA buffer every 0.005s, but
+-needs only about 3% CPU time to do so, it can do with a 0.03 * 0.005s
+-= 0.00015s.
++Realtime scheduling is all about determinism, a group has to be able to rely on
++the amount of bandwidth (eg. CPU time) being constant. In order to schedule
++multiple groups of realtime tasks, each group must be assigned a fixed portion
++of the CPU time available. Without a minimum guarantee a realtime group can
++obviously fall short. A fuzzy upper limit is of no use since it cannot be
++relied upon. Which leaves us with just the single fixed portion.
+
++1.2 The solution
++----------------
+
+-The Interface:
++CPU time is divided by means of specifying how much time can be spent running
++in a given period. We allocate this "run time" for each realtime group which
++the other realtime groups will not be permitted to use.
+
+-system wide:
++Any time not allocated to a realtime group will be used to run normal priority
++tasks (SCHED_OTHER). Any allocated run time not used will also be picked up by
++SCHED_OTHER.
+
+-/proc/sys/kernel/sched_rt_period_ms
+-/proc/sys/kernel/sched_rt_runtime_us
++Let's consider an example: a frame fixed realtime renderer must deliver 25
++frames a second, which yields a period of 0.04s per frame. Now say it will also
++have to play some music and respond to input, leaving it with around 80% CPU
++time dedicated for the graphics. We can then give this group a run time of 0.8
++* 0.04s = 0.032s.
+
+-CONFIG_FAIR_USER_SCHED
++This way the graphics group will have a 0.04s period with a 0.032s run time
++limit. Now if the audio thread needs to refill the DMA buffer every 0.005s, but
++needs only about 3% CPU time to do so, it can do with a 0.03 * 0.005s =
++0.00015s. So this group can be scheduled with a period of 0.005s and a run time
++of 0.00015s.
+
+-/sys/kernel/uids/<uid>/cpu_rt_runtime_us
++The remaining CPU time will be used for user input and other tass. Because
++realtime tasks have explicitly allocated the CPU time they need to perform
++their tasks, buffer underruns in the graphocs or audio can be eliminated.
+
+-or
++NOTE: the above example is not fully implemented as of yet (2.6.25). We still
++lack an EDF scheduler to make non-uniform periods usable.
+
+-CONFIG_FAIR_CGROUP_SCHED
+
+-/cgroup/<cgroup>/cpu.rt_runtime_us
++2. The Interface
++================
+
+-[ time is specified in us because the interface is s32; this gives an
+- operating range of ~35m to 1us ]
+
+-The period takes values in [ 1, INT_MAX ], runtime in [ -1, INT_MAX - 1 ].
++2.1 System wide settings
++------------------------
+
+-A runtime of -1 specifies runtime == period, ie. no limit.
++The system wide settings are configured under the /proc virtual file system:
+
+-New groups get the period from /proc/sys/kernel/sched_rt_period_us and
+-a runtime of 0.
++/proc/sys/kernel/sched_rt_period_us:
++ The scheduling period that is equivalent to 100% CPU bandwidth
+
+-Settings are constrained to:
++/proc/sys/kernel/sched_rt_runtime_us:
++ A global limit on how much time realtime scheduling may use. Even without
++ CONFIG_RT_GROUP_SCHED enabled, this will limit time reserved to realtime
++ processes. With CONFIG_RT_GROUP_SCHED it signifies the total bandwidth
++ available to all realtime groups.
++
++ * Time is specified in us because the interface is s32. This gives an
++ operating range from 1us to about 35 minutes.
++ * sched_rt_period_us takes values from 1 to INT_MAX.
++ * sched_rt_runtime_us takes values from -1 to (INT_MAX - 1).
++ * A run time of -1 specifies runtime == period, ie. no limit.
++
++
++2.2 Default behaviour
++---------------------
++
++The default values for sched_rt_period_us (1000000 or 1s) and
++sched_rt_runtime_us (950000 or 0.95s). This gives 0.05s to be used by
++SCHED_OTHER (non-RT tasks). These defaults were chosen so that a run-away
++realtime tasks will not lock up the machine but leave a little time to recover
++it. By setting runtime to -1 you'd get the old behaviour back.
++
++By default all bandwidth is assigned to the root group and new groups get the
++period from /proc/sys/kernel/sched_rt_period_us and a run time of 0. If you
++want to assign bandwidth to another group, reduce the root group's bandwidth
++and assign some or all of the difference to another group.
++
++Realtime group scheduling means you have to assign a portion of total CPU
++bandwidth to the group before it will accept realtime tasks. Therefore you will
++not be able to run realtime tasks as any user other than root until you have
++done that, even if the user has the rights to run processes with realtime
++priority!
++
++
++2.3 Basis for grouping tasks
++----------------------------
++
++There are two compile-time settings for allocating CPU bandwidth. These are
++configured using the "Basis for grouping tasks" multiple choice menu under
++General setup > Group CPU Scheduler:
++
++a. CONFIG_USER_SCHED (aka "Basis for grouping tasks" = "user id")
++
++This lets you use the virtual files under
++"/sys/kernel/uids/<uid>/cpu_rt_runtime_us" to control he CPU time reserved for
++each user .
++
++The other option is:
++
++.o CONFIG_CGROUP_SCHED (aka "Basis for grouping tasks" = "Control groups")
++
++This uses the /cgroup virtual file system and "/cgroup/<cgroup>/cpu.rt_runtime_us"
++to control the CPU time reserved for each control group instead.
++
++For more information on working with control groups, you should read
++Documentation/cgroups.txt as well.
++
++Group settings are checked against the following limits in order to keep the configuration
++schedulable:
+
+ \Sum_{i} runtime_{i} / global_period <= global_runtime / global_period
+
+-in order to keep the configuration schedulable.
++For now, this can be simplified to just the following (but see Future plans):
++
++ \Sum_{i} runtime_{i} <= global_runtime
++
++
++3. Future plans
++===============
++
++There is work in progress to make the scheduling period for each group
++("/sys/kernel/uids/<uid>/cpu_rt_period_us" or
++"/cgroup/<cgroup>/cpu.rt_period_us" respectively) configurable as well.
++
++The constraint on the period is that a subgroup must have a smaller or
++equal period to its parent. But realistically its not very useful _yet_
++as its prone to starvation without deadline scheduling.
++
++Consider two sibling groups A and B; both have 50% bandwidth, but A's
++period is twice the length of B's.
++
++* group A: period=100000us, runtime=10000us
++ - this runs for 0.01s once every 0.1s
++
++* group B: period= 50000us, runtime=10000us
++ - this runs for 0.01s twice every 0.1s (or once every 0.05 sec).
++
++This means that currently a while (1) loop in A will run for the full period of
++B and can starve B's tasks (assuming they are of lower priority) for a whole
++period.
++
++The next project will be SCHED_EDF (Earliest Deadline First scheduling) to bring
++full deadline scheduling to the linux kernel. Deadline scheduling the above
++groups and treating end of the period as a deadline will ensure that they both
++get their allocated time.
++
++Implementing SCHED_EDF might take a while to complete. Priority Inheritance is
++the biggest challenge as the current linux PI infrastructure is geared towards
++the limited static priority levels 0-139. With deadline scheduling you need to
++do deadline inheritance (since priority is inversely proportional to the
++deadline delta (deadline - now).
++
++This means the whole PI machinery will have to be reworked - and that is one of
++the most complex pieces of code we have.
+diff --git a/Documentation/scsi/st.txt b/Documentation/scsi/st.txt
+index b7be95b..4075260 100644
+--- a/Documentation/scsi/st.txt
++++ b/Documentation/scsi/st.txt
+@@ -2,7 +2,7 @@ This file contains brief information about the SCSI tape driver.
+ The driver is currently maintained by Kai Mäkisara (email
+ Kai.Makisara at kolumbus.fi)
+
+-Last modified: Mon Mar 7 21:14:44 2005 by kai.makisara
++Last modified: Sun Feb 24 21:59:07 2008 by kai.makisara
+
+
+ BASICS
+@@ -133,6 +133,11 @@ the defaults set by the user. The value -1 means the default is not set. The
+ file 'dev' contains the device numbers corresponding to this device. The links
+ 'device' and 'driver' point to the SCSI device and driver entries.
+
++Each directory also contains the entry 'options' which shows the currently
++enabled driver and mode options. The value in the file is a bit mask where the
++bit definitions are the same as those used with MTSETDRVBUFFER in setting the
++options.
++
+ A link named 'tape' is made from the SCSI device directory to the class
+ directory corresponding to the mode 0 auto-rewind device (e.g., st0).
+
+@@ -372,6 +377,11 @@ MTSETDRVBUFFER
+ MT_ST_SYSV sets the SYSV semantics (mode)
+ MT_ST_NOWAIT enables immediate mode (i.e., don't wait for
+ the command to finish) for some commands (e.g., rewind)
++ MT_ST_SILI enables setting the SILI bit in SCSI commands when
++ reading in variable block mode to enhance performance when
++ reading blocks shorter than the byte count; set this only
++ if you are sure that the drive supports SILI and the HBA
++ correctly returns transfer residuals
+ MT_ST_DEBUGGING debugging (global; debugging must be
+ compiled into the driver)
+ MT_ST_SETBOOLEANS
+diff --git a/Documentation/smart-config.txt b/Documentation/smart-config.txt
+deleted file mode 100644
+index 8467447..0000000
+--- a/Documentation/smart-config.txt
++++ /dev/null
+@@ -1,98 +0,0 @@
+-Smart CONFIG_* Dependencies
+-1 August 1999
+-
+-Michael Chastain <mec at shout.net>
+-Werner Almesberger <almesber at lrc.di.epfl.ch>
+-Martin von Loewis <martin at mira.isdn.cs.tu-berlin.de>
+-
+-Here is the problem:
+-
+- Suppose that drivers/net/foo.c has the following lines:
+-
+- #include <linux/config.h>
+-
+- ...
+-
+- #ifdef CONFIG_FOO_AUTOFROB
+- /* Code for auto-frobbing */
+- #else
+- /* Manual frobbing only */
+- #endif
+-
+- ...
+-
+- #ifdef CONFIG_FOO_MODEL_TWO
+- /* Code for model two */
+- #endif
+-
+- Now suppose the user (the person building kernels) reconfigures the
+- kernel to change some unrelated setting. This will regenerate the
+- file include/linux/autoconf.h, which will cause include/linux/config.h
+- to be out of date, which will cause drivers/net/foo.c to be recompiled.
+-
+- Most kernel sources, perhaps 80% of them, have at least one CONFIG_*
+- dependency somewhere. So changing _any_ CONFIG_* setting requires
+- almost _all_ of the kernel to be recompiled.
+-
+-Here is the solution:
+-
+- We've made the dependency generator, mkdep.c, smarter. Instead of
+- generating this dependency:
+-
+- drivers/net/foo.c: include/linux/config.h
+-
+- It now generates these dependencies:
+-
+- drivers/net/foo.c: \
+- include/config/foo/autofrob.h \
+- include/config/foo/model/two.h
+-
+- So drivers/net/foo.c depends only on the CONFIG_* lines that
+- it actually uses.
+-
+- A new program, split-include.c, runs at the beginning of
+- compilation (make bzImage or make zImage). split-include reads
+- include/linux/autoconf.h and updates the include/config/ tree,
+- writing one file per option. It updates only the files for options
+- that have changed.
+-
+-Flag Dependencies
+-
+- Martin Von Loewis contributed another feature to this patch:
+- 'flag dependencies'. The idea is that a .o file depends on
+- the compilation flags used to build it. The file foo.o has
+- its flags stored in .flags.foo.o.
+-
+- Suppose the user changes the foo driver from resident to modular.
+- 'make' will notice that the current foo.o was not compiled with
+- -DMODULE and will recompile foo.c.
+-
+- All .o files made from C source have flag dependencies. So do .o
+- files made with ld, and .a files made with ar. However, .o files
+- made from assembly source do not have flag dependencies (nobody
+- needs this yet, but it would be good to fix).
+-
+-Per-source-file Flags
+-
+- Flag dependencies also work with per-source-file flags.
+- You can specify compilation flags for individual source files
+- like this:
+-
+- CFLAGS_foo.o = -DSPECIAL_FOO_DEFINE
+-
+- This helps clean up drivers/net/Makefile, drivers/scsi/Makefile,
+- and several other Makefiles.
+-
+-Credit
+-
+- Werner Almesberger had the original idea and wrote the first
+- version of this patch.
+-
+- Michael Chastain picked it up and continued development. He is
+- now the principal author and maintainer. Please report any bugs
+- to him.
+-
+- Martin von Loewis wrote flag dependencies, with some modifications
+- by Michael Chastain.
+-
+- Thanks to all of the beta testers.
+diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
+index e985cf5..fd4c32a 100644
+--- a/Documentation/sound/alsa/ALSA-Configuration.txt
++++ b/Documentation/sound/alsa/ALSA-Configuration.txt
+@@ -284,6 +284,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
+ control correctly. If you have problems regarding this, try
+ another ALSA compliant mixer (alsamixer works).
+
++ Module snd-aw2
++ --------------
++
++ Module for Audiowerk2 sound card
++
++ This module supports multiple cards.
++
+ Module snd-azt2320
+ ------------------
+
+@@ -818,19 +825,25 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
+ hippo_1 Hippo (Benq) with jack detection
+ sony-assamd Sony ASSAMD
+ ultra Samsung Q1 Ultra Vista model
++ lenovo-3000 Lenovo 3000 y410
+ basic fixed pin assignment w/o SPDIF
+ auto auto-config reading BIOS (default)
+
+- ALC268
++ ALC267/268
++ quanta-il1 Quanta IL1 mini-notebook
+ 3stack 3-stack model
+ toshiba Toshiba A205
+ acer Acer laptops
+ dell Dell OEM laptops (Vostro 1200)
++ zepto Zepto laptops
+ test for testing/debugging purpose, almost all controls can
+ adjusted. Appearing only when compiled with
+ $CONFIG_SND_DEBUG=y
+ auto auto-config reading BIOS (default)
+
++ ALC269
++ basic Basic preset
++
+ ALC662
+ 3stack-dig 3-stack (2-channel) with SPDIF
+ 3stack-6ch 3-stack (6-channel)
+@@ -871,10 +884,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
+ lenovo-nb0763 Lenovo NB0763
+ lenovo-ms7195-dig Lenovo MS7195
+ haier-w66 Haier W66
+- 6stack-hp HP machines with 6stack (Nettle boards)
+ 3stack-hp HP machines with 3stack (Lucknow, Samba boards)
+ 6stack-dell Dell machines with 6stack (Inspiron 530)
+ mitac Mitac 8252D
++ clevo-m720 Clevo M720 laptop series
++ fujitsu-pi2515 Fujitsu AMILO Pi2515
+ auto auto-config reading BIOS (default)
+
+ ALC861/660
+@@ -911,6 +925,12 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
+ 3stack 3-stack mode (default)
+ 6stack 6-stack mode
+
++ AD1884A / AD1883 / AD1984A / AD1984B
++ desktop 3-stack desktop (default)
++ laptop laptop with HP jack sensing
++ mobile mobile devices with HP jack sensing
++ thinkpad Lenovo Thinkpad X300
++
+ AD1884
+ N/A
+
+@@ -936,7 +956,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
+ laptop-automute 2-channel with EAPD and HP-automute (Lenovo N100)
+ ultra 2-channel with EAPD (Samsung Ultra tablet PC)
+
+- AD1988
++ AD1988/AD1988B/AD1989A/AD1989B
+ 6stack 6-jack
+ 6stack-dig ditto with SPDIF
+ 3stack 3-jack
+@@ -979,6 +999,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
+ dell-m26 Dell Inspiron 1501
+ dell-m27 Dell Inspiron E1705/9400
+ gateway Gateway laptops with EAPD control
++ panasonic Panasonic CF-74
+
+ STAC9205/9254
+ ref Reference board
+@@ -1017,6 +1038,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
+ 3stack D965 3stack
+ 5stack D965 5stack + SPDIF
+ dell-3stack Dell Dimension E520
++ dell-bios Fixes with Dell BIOS setup
++
++ STAC92HD71B*
++ ref Reference board
++ dell-m4-1 Dell desktops
++ dell-m4-2 Dell desktops
++
++ STAC92HD73*
++ ref Reference board
++ dell-m6 Dell desktops
+
+ STAC9872
+ vaio Setup for VAIO FE550G/SZ110
+@@ -1590,6 +1621,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
+
+ Power management is _not_ supported.
+
++ Module snd-pcsp
++ -----------------
++
++ Module for internal PC-Speaker.
++
++ nforce_wa - enable NForce chipset workaround. Expect bad sound.
++
++ This module supports system beeps, some kind of PCM playback and
++ even a few mixer controls.
++
+ Module snd-pcxhr
+ ----------------
+
+diff --git a/Documentation/timers/highres.txt b/Documentation/timers/highres.txt
+new file mode 100644
+index 0000000..a73ecf5
+--- /dev/null
++++ b/Documentation/timers/highres.txt
+@@ -0,0 +1,249 @@
++High resolution timers and dynamic ticks design notes
++-----------------------------------------------------
++
++Further information can be found in the paper of the OLS 2006 talk "hrtimers
++and beyond". The paper is part of the OLS 2006 Proceedings Volume 1, which can
++be found on the OLS website:
++http://www.linuxsymposium.org/2006/linuxsymposium_procv1.pdf
++
++The slides to this talk are available from:
++http://tglx.de/projects/hrtimers/ols2006-hrtimers.pdf
++
++The slides contain five figures (pages 2, 15, 18, 20, 22), which illustrate the
++changes in the time(r) related Linux subsystems. Figure #1 (p. 2) shows the
++design of the Linux time(r) system before hrtimers and other building blocks
++got merged into mainline.
++
++Note: the paper and the slides are talking about "clock event source", while we
++switched to the name "clock event devices" in meantime.
++
++The design contains the following basic building blocks:
++
++- hrtimer base infrastructure
++- timeofday and clock source management
++- clock event management
++- high resolution timer functionality
++- dynamic ticks
++
++
++hrtimer base infrastructure
++---------------------------
++
++The hrtimer base infrastructure was merged into the 2.6.16 kernel. Details of
++the base implementation are covered in Documentation/hrtimers/hrtimer.txt. See
++also figure #2 (OLS slides p. 15)
++
++The main differences to the timer wheel, which holds the armed timer_list type
++timers are:
++ - time ordered enqueueing into a rb-tree
++ - independent of ticks (the processing is based on nanoseconds)
++
++
++timeofday and clock source management
++-------------------------------------
++
++John Stultz's Generic Time Of Day (GTOD) framework moves a large portion of
++code out of the architecture-specific areas into a generic management
++framework, as illustrated in figure #3 (OLS slides p. 18). The architecture
++specific portion is reduced to the low level hardware details of the clock
++sources, which are registered in the framework and selected on a quality based
++decision. The low level code provides hardware setup and readout routines and
++initializes data structures, which are used by the generic time keeping code to
++convert the clock ticks to nanosecond based time values. All other time keeping
++related functionality is moved into the generic code. The GTOD base patch got
++merged into the 2.6.18 kernel.
++
++Further information about the Generic Time Of Day framework is available in the
++OLS 2005 Proceedings Volume 1:
++http://www.linuxsymposium.org/2005/linuxsymposium_procv1.pdf
++
++The paper "We Are Not Getting Any Younger: A New Approach to Time and
++Timers" was written by J. Stultz, D.V. Hart, & N. Aravamudan.
++
++Figure #3 (OLS slides p.18) illustrates the transformation.
++
++
++clock event management
++----------------------
++
++While clock sources provide read access to the monotonically increasing time
++value, clock event devices are used to schedule the next event
++interrupt(s). The next event is currently defined to be periodic, with its
++period defined at compile time. The setup and selection of the event device
++for various event driven functionalities is hardwired into the architecture
++dependent code. This results in duplicated code across all architectures and
++makes it extremely difficult to change the configuration of the system to use
++event interrupt devices other than those already built into the
++architecture. Another implication of the current design is that it is necessary
++to touch all the architecture-specific implementations in order to provide new
++functionality like high resolution timers or dynamic ticks.
++
++The clock events subsystem tries to address this problem by providing a generic
++solution to manage clock event devices and their usage for the various clock
++event driven kernel functionalities. The goal of the clock event subsystem is
++to minimize the clock event related architecture dependent code to the pure
++hardware related handling and to allow easy addition and utilization of new
++clock event devices. It also minimizes the duplicated code across the
++architectures as it provides generic functionality down to the interrupt
++service handler, which is almost inherently hardware dependent.
++
++Clock event devices are registered either by the architecture dependent boot
++code or at module insertion time. Each clock event device fills a data
++structure with clock-specific property parameters and callback functions. The
++clock event management decides, by using the specified property parameters, the
++set of system functions a clock event device will be used to support. This
++includes the distinction of per-CPU and per-system global event devices.
++
++System-level global event devices are used for the Linux periodic tick. Per-CPU
++event devices are used to provide local CPU functionality such as process
++accounting, profiling, and high resolution timers.
++
++The management layer assigns one or more of the following functions to a clock
++event device:
++ - system global periodic tick (jiffies update)
++ - cpu local update_process_times
++ - cpu local profiling
++ - cpu local next event interrupt (non periodic mode)
++
++The clock event device delegates the selection of those timer interrupt related
++functions completely to the management layer. The clock management layer stores
++a function pointer in the device description structure, which has to be called
++from the hardware level handler. This removes a lot of duplicated code from the
++architecture specific timer interrupt handlers and hands the control over the
++clock event devices and the assignment of timer interrupt related functionality
++to the core code.
++
++The clock event layer API is rather small. Aside from the clock event device
++registration interface it provides functions to schedule the next event
++interrupt, clock event device notification service and support for suspend and
++resume.
++
++The framework adds about 700 lines of code which results in a 2KB increase of
++the kernel binary size. The conversion of i386 removes about 100 lines of
++code. The binary size decrease is in the range of 400 byte. We believe that the
++increase of flexibility and the avoidance of duplicated code across
++architectures justifies the slight increase of the binary size.
++
++The conversion of an architecture has no functional impact, but allows to
++utilize the high resolution and dynamic tick functionalites without any change
++to the clock event device and timer interrupt code. After the conversion the
++enabling of high resolution timers and dynamic ticks is simply provided by
++adding the kernel/time/Kconfig file to the architecture specific Kconfig and
++adding the dynamic tick specific calls to the idle routine (a total of 3 lines
++added to the idle function and the Kconfig file)
++
++Figure #4 (OLS slides p.20) illustrates the transformation.
++
++
++high resolution timer functionality
++-----------------------------------
++
++During system boot it is not possible to use the high resolution timer
++functionality, while making it possible would be difficult and would serve no
++useful function. The initialization of the clock event device framework, the
++clock source framework (GTOD) and hrtimers itself has to be done and
++appropriate clock sources and clock event devices have to be registered before
++the high resolution functionality can work. Up to the point where hrtimers are
++initialized, the system works in the usual low resolution periodic mode. The
++clock source and the clock event device layers provide notification functions
++which inform hrtimers about availability of new hardware. hrtimers validates
++the usability of the registered clock sources and clock event devices before
++switching to high resolution mode. This ensures also that a kernel which is
++configured for high resolution timers can run on a system which lacks the
++necessary hardware support.
++
++The high resolution timer code does not support SMP machines which have only
++global clock event devices. The support of such hardware would involve IPI
++calls when an interrupt happens. The overhead would be much larger than the
++benefit. This is the reason why we currently disable high resolution and
++dynamic ticks on i386 SMP systems which stop the local APIC in C3 power
++state. A workaround is available as an idea, but the problem has not been
++tackled yet.
++
++The time ordered insertion of timers provides all the infrastructure to decide
++whether the event device has to be reprogrammed when a timer is added. The
++decision is made per timer base and synchronized across per-cpu timer bases in
++a support function. The design allows the system to utilize separate per-CPU
++clock event devices for the per-CPU timer bases, but currently only one
++reprogrammable clock event device per-CPU is utilized.
++
++When the timer interrupt happens, the next event interrupt handler is called
++from the clock event distribution code and moves expired timers from the
++red-black tree to a separate double linked list and invokes the softirq
++handler. An additional mode field in the hrtimer structure allows the system to
++execute callback functions directly from the next event interrupt handler. This
++is restricted to code which can safely be executed in the hard interrupt
++context. This applies, for example, to the common case of a wakeup function as
++used by nanosleep. The advantage of executing the handler in the interrupt
++context is the avoidance of up to two context switches - from the interrupted
++context to the softirq and to the task which is woken up by the expired
++timer.
++
++Once a system has switched to high resolution mode, the periodic tick is
++switched off. This disables the per system global periodic clock event device -
++e.g. the PIT on i386 SMP systems.
++
++The periodic tick functionality is provided by an per-cpu hrtimer. The callback
++function is executed in the next event interrupt context and updates jiffies
++and calls update_process_times and profiling. The implementation of the hrtimer
++based periodic tick is designed to be extended with dynamic tick functionality.
++This allows to use a single clock event device to schedule high resolution
++timer and periodic events (jiffies tick, profiling, process accounting) on UP
++systems. This has been proved to work with the PIT on i386 and the Incrementer
++on PPC.
++
++The softirq for running the hrtimer queues and executing the callbacks has been
++separated from the tick bound timer softirq to allow accurate delivery of high
++resolution timer signals which are used by itimer and POSIX interval
++timers. The execution of this softirq can still be delayed by other softirqs,
++but the overall latencies have been significantly improved by this separation.
++
++Figure #5 (OLS slides p.22) illustrates the transformation.
++
++
++dynamic ticks
++-------------
++
++Dynamic ticks are the logical consequence of the hrtimer based periodic tick
++replacement (sched_tick). The functionality of the sched_tick hrtimer is
++extended by three functions:
++
++- hrtimer_stop_sched_tick
++- hrtimer_restart_sched_tick
++- hrtimer_update_jiffies
++
++hrtimer_stop_sched_tick() is called when a CPU goes into idle state. The code
++evaluates the next scheduled timer event (from both hrtimers and the timer
++wheel) and in case that the next event is further away than the next tick it
++reprograms the sched_tick to this future event, to allow longer idle sleeps
++without worthless interruption by the periodic tick. The function is also
++called when an interrupt happens during the idle period, which does not cause a
++reschedule. The call is necessary as the interrupt handler might have armed a
++new timer whose expiry time is before the time which was identified as the
++nearest event in the previous call to hrtimer_stop_sched_tick.
++
++hrtimer_restart_sched_tick() is called when the CPU leaves the idle state before
++it calls schedule(). hrtimer_restart_sched_tick() resumes the periodic tick,
++which is kept active until the next call to hrtimer_stop_sched_tick().
++
++hrtimer_update_jiffies() is called from irq_enter() when an interrupt happens
++in the idle period to make sure that jiffies are up to date and the interrupt
++handler has not to deal with an eventually stale jiffy value.
++
++The dynamic tick feature provides statistical values which are exported to
++userspace via /proc/stats and can be made available for enhanced power
++management control.
++
++The implementation leaves room for further development like full tickless
++systems, where the time slice is controlled by the scheduler, variable
++frequency profiling, and a complete removal of jiffies in the future.
++
++
++Aside the current initial submission of i386 support, the patchset has been
++extended to x86_64 and ARM already. Initial (work in progress) support is also
++available for MIPS and PowerPC.
++
++ Thomas, Ingo
++
++
++
+diff --git a/Documentation/timers/hrtimers.txt b/Documentation/timers/hrtimers.txt
+new file mode 100644
+index 0000000..ce31f65
+--- /dev/null
++++ b/Documentation/timers/hrtimers.txt
+@@ -0,0 +1,178 @@
++
++hrtimers - subsystem for high-resolution kernel timers
++----------------------------------------------------
++
++This patch introduces a new subsystem for high-resolution kernel timers.
++
++One might ask the question: we already have a timer subsystem
++(kernel/timers.c), why do we need two timer subsystems? After a lot of
++back and forth trying to integrate high-resolution and high-precision
++features into the existing timer framework, and after testing various
++such high-resolution timer implementations in practice, we came to the
++conclusion that the timer wheel code is fundamentally not suitable for
++such an approach. We initially didn't believe this ('there must be a way
++to solve this'), and spent a considerable effort trying to integrate
++things into the timer wheel, but we failed. In hindsight, there are
++several reasons why such integration is hard/impossible:
++
++- the forced handling of low-resolution and high-resolution timers in
++ the same way leads to a lot of compromises, macro magic and #ifdef
++ mess. The timers.c code is very "tightly coded" around jiffies and
++ 32-bitness assumptions, and has been honed and micro-optimized for a
++ relatively narrow use case (jiffies in a relatively narrow HZ range)
++ for many years - and thus even small extensions to it easily break
++ the wheel concept, leading to even worse compromises. The timer wheel
++ code is very good and tight code, there's zero problems with it in its
++ current usage - but it is simply not suitable to be extended for
++ high-res timers.
++
++- the unpredictable [O(N)] overhead of cascading leads to delays which
++ necessitate a more complex handling of high resolution timers, which
++ in turn decreases robustness. Such a design still led to rather large
++ timing inaccuracies. Cascading is a fundamental property of the timer
++ wheel concept, it cannot be 'designed out' without unevitably
++ degrading other portions of the timers.c code in an unacceptable way.
++
++- the implementation of the current posix-timer subsystem on top of
++ the timer wheel has already introduced a quite complex handling of
++ the required readjusting of absolute CLOCK_REALTIME timers at
++ settimeofday or NTP time - further underlying our experience by
++ example: that the timer wheel data structure is too rigid for high-res
++ timers.
++
++- the timer wheel code is most optimal for use cases which can be
++ identified as "timeouts". Such timeouts are usually set up to cover
++ error conditions in various I/O paths, such as networking and block
++ I/O. The vast majority of those timers never expire and are rarely
++ recascaded because the expected correct event arrives in time so they
++ can be removed from the timer wheel before any further processing of
++ them becomes necessary. Thus the users of these timeouts can accept
++ the granularity and precision tradeoffs of the timer wheel, and
++ largely expect the timer subsystem to have near-zero overhead.
++ Accurate timing for them is not a core purpose - in fact most of the
++ timeout values used are ad-hoc. For them it is at most a necessary
++ evil to guarantee the processing of actual timeout completions
++ (because most of the timeouts are deleted before completion), which
++ should thus be as cheap and unintrusive as possible.
++
++The primary users of precision timers are user-space applications that
++utilize nanosleep, posix-timers and itimer interfaces. Also, in-kernel
++users like drivers and subsystems which require precise timed events
++(e.g. multimedia) can benefit from the availability of a separate
++high-resolution timer subsystem as well.
++
++While this subsystem does not offer high-resolution clock sources just
++yet, the hrtimer subsystem can be easily extended with high-resolution
++clock capabilities, and patches for that exist and are maturing quickly.
++The increasing demand for realtime and multimedia applications along
++with other potential users for precise timers gives another reason to
++separate the "timeout" and "precise timer" subsystems.
++
++Another potential benefit is that such a separation allows even more
++special-purpose optimization of the existing timer wheel for the low
++resolution and low precision use cases - once the precision-sensitive
++APIs are separated from the timer wheel and are migrated over to
++hrtimers. E.g. we could decrease the frequency of the timeout subsystem
++from 250 Hz to 100 HZ (or even smaller).
++
++hrtimer subsystem implementation details
++----------------------------------------
++
++the basic design considerations were:
++
++- simplicity
++
++- data structure not bound to jiffies or any other granularity. All the
++ kernel logic works at 64-bit nanoseconds resolution - no compromises.
++
++- simplification of existing, timing related kernel code
++
++another basic requirement was the immediate enqueueing and ordering of
++timers at activation time. After looking at several possible solutions
++such as radix trees and hashes, we chose the red black tree as the basic
++data structure. Rbtrees are available as a library in the kernel and are
++used in various performance-critical areas of e.g. memory management and
++file systems. The rbtree is solely used for time sorted ordering, while
++a separate list is used to give the expiry code fast access to the
++queued timers, without having to walk the rbtree.
++
++(This separate list is also useful for later when we'll introduce
++high-resolution clocks, where we need separate pending and expired
++queues while keeping the time-order intact.)
++
++Time-ordered enqueueing is not purely for the purposes of
++high-resolution clocks though, it also simplifies the handling of
++absolute timers based on a low-resolution CLOCK_REALTIME. The existing
++implementation needed to keep an extra list of all armed absolute
++CLOCK_REALTIME timers along with complex locking. In case of
++settimeofday and NTP, all the timers (!) had to be dequeued, the
++time-changing code had to fix them up one by one, and all of them had to
++be enqueued again. The time-ordered enqueueing and the storage of the
++expiry time in absolute time units removes all this complex and poorly
++scaling code from the posix-timer implementation - the clock can simply
++be set without having to touch the rbtree. This also makes the handling
++of posix-timers simpler in general.
++
++The locking and per-CPU behavior of hrtimers was mostly taken from the
++existing timer wheel code, as it is mature and well suited. Sharing code
++was not really a win, due to the different data structures. Also, the
++hrtimer functions now have clearer behavior and clearer names - such as
++hrtimer_try_to_cancel() and hrtimer_cancel() [which are roughly
++equivalent to del_timer() and del_timer_sync()] - so there's no direct
++1:1 mapping between them on the algorithmical level, and thus no real
++potential for code sharing either.
++
++Basic data types: every time value, absolute or relative, is in a
++special nanosecond-resolution type: ktime_t. The kernel-internal
++representation of ktime_t values and operations is implemented via
++macros and inline functions, and can be switched between a "hybrid
++union" type and a plain "scalar" 64bit nanoseconds representation (at
++compile time). The hybrid union type optimizes time conversions on 32bit
++CPUs. This build-time-selectable ktime_t storage format was implemented
++to avoid the performance impact of 64-bit multiplications and divisions
++on 32bit CPUs. Such operations are frequently necessary to convert
++between the storage formats provided by kernel and userspace interfaces
++and the internal time format. (See include/linux/ktime.h for further
++details.)
++
++hrtimers - rounding of timer values
++-----------------------------------
++
++the hrtimer code will round timer events to lower-resolution clocks
++because it has to. Otherwise it will do no artificial rounding at all.
++
++one question is, what resolution value should be returned to the user by
++the clock_getres() interface. This will return whatever real resolution
++a given clock has - be it low-res, high-res, or artificially-low-res.
++
++hrtimers - testing and verification
++----------------------------------
++
++We used the high-resolution clock subsystem ontop of hrtimers to verify
++the hrtimer implementation details in praxis, and we also ran the posix
++timer tests in order to ensure specification compliance. We also ran
++tests on low-resolution clocks.
++
++The hrtimer patch converts the following kernel functionality to use
++hrtimers:
++
++ - nanosleep
++ - itimers
++ - posix-timers
++
++The conversion of nanosleep and posix-timers enabled the unification of
++nanosleep and clock_nanosleep.
++
++The code was successfully compiled for the following platforms:
++
++ i386, x86_64, ARM, PPC, PPC64, IA64
++
++The code was run-tested on the following platforms:
++
++ i386(UP/SMP), x86_64(UP/SMP), ARM, PPC
++
++hrtimers were also integrated into the -rt tree, along with a
++hrtimers-based high-resolution clock implementation, so the hrtimers
++code got a healthy amount of testing and use in practice.
++
++ Thomas Gleixner, Ingo Molnar
+diff --git a/Documentation/timers/timer_stats.txt b/Documentation/timers/timer_stats.txt
+new file mode 100644
+index 0000000..20d368c
+--- /dev/null
++++ b/Documentation/timers/timer_stats.txt
+@@ -0,0 +1,73 @@
++timer_stats - timer usage statistics
++------------------------------------
++
++timer_stats is a debugging facility to make the timer (ab)usage in a Linux
++system visible to kernel and userspace developers. If enabled in the config
++but not used it has almost zero runtime overhead, and a relatively small
++data structure overhead. Even if collection is enabled runtime all the
++locking is per-CPU and lookup is hashed.
++
++timer_stats should be used by kernel and userspace developers to verify that
++their code does not make unduly use of timers. This helps to avoid unnecessary
++wakeups, which should be avoided to optimize power consumption.
++
++It can be enabled by CONFIG_TIMER_STATS in the "Kernel hacking" configuration
++section.
++
++timer_stats collects information about the timer events which are fired in a
++Linux system over a sample period:
++
++- the pid of the task(process) which initialized the timer
++- the name of the process which initialized the timer
++- the function where the timer was intialized
++- the callback function which is associated to the timer
++- the number of events (callbacks)
++
++timer_stats adds an entry to /proc: /proc/timer_stats
++
++This entry is used to control the statistics functionality and to read out the
++sampled information.
++
++The timer_stats functionality is inactive on bootup.
++
++To activate a sample period issue:
++# echo 1 >/proc/timer_stats
++
++To stop a sample period issue:
++# echo 0 >/proc/timer_stats
++
++The statistics can be retrieved by:
++# cat /proc/timer_stats
++
++The readout of /proc/timer_stats automatically disables sampling. The sampled
++information is kept until a new sample period is started. This allows multiple
++readouts.
++
++Sample output of /proc/timer_stats:
++
++Timerstats sample period: 3.888770 s
++ 12, 0 swapper hrtimer_stop_sched_tick (hrtimer_sched_tick)
++ 15, 1 swapper hcd_submit_urb (rh_timer_func)
++ 4, 959 kedac schedule_timeout (process_timeout)
++ 1, 0 swapper page_writeback_init (wb_timer_fn)
++ 28, 0 swapper hrtimer_stop_sched_tick (hrtimer_sched_tick)
++ 22, 2948 IRQ 4 tty_flip_buffer_push (delayed_work_timer_fn)
++ 3, 3100 bash schedule_timeout (process_timeout)
++ 1, 1 swapper queue_delayed_work_on (delayed_work_timer_fn)
++ 1, 1 swapper queue_delayed_work_on (delayed_work_timer_fn)
++ 1, 1 swapper neigh_table_init_no_netlink (neigh_periodic_timer)
++ 1, 2292 ip __netdev_watchdog_up (dev_watchdog)
++ 1, 23 events/1 do_cache_clean (delayed_work_timer_fn)
++90 total events, 30.0 events/sec
++
++The first column is the number of events, the second column the pid, the third
++column is the name of the process. The forth column shows the function which
++initialized the timer and in parantheses the callback function which was
++executed on expiry.
++
++ Thomas, Ingo
++
++Added flag to indicate 'deferrable timer' in /proc/timer_stats. A deferrable
++timer will appear as follows
++ 10D, 1 swapper queue_delayed_work_on (delayed_work_timer_fn)
++
+diff --git a/Documentation/usb/anchors.txt b/Documentation/usb/anchors.txt
+new file mode 100644
+index 0000000..7304bcf
+--- /dev/null
++++ b/Documentation/usb/anchors.txt
+@@ -0,0 +1,50 @@
++What is anchor?
++===============
++
++A USB driver needs to support some callbacks requiring
++a driver to cease all IO to an interface. To do so, a
++driver has to keep track of the URBs it has submitted
++to know they've all completed or to call usb_kill_urb
++for them. The anchor is a data structure takes care of
++keeping track of URBs and provides methods to deal with
++multiple URBs.
++
++Allocation and Initialisation
++=============================
++
++There's no API to allocate an anchor. It is simply declared
++as struct usb_anchor. init_usb_anchor() must be called to
++initialise the data structure.
++
++Deallocation
++============
++
++Once it has no more URBs associated with it, the anchor can be
++freed with normal memory management operations.
++
++Association and disassociation of URBs with anchors
++===================================================
++
++An association of URBs to an anchor is made by an explicit
++call to usb_anchor_urb(). The association is maintained until
++an URB is finished by (successfull) completion. Thus disassociation
++is automatic. A function is provided to forcibly finish (kill)
++all URBs associated with an anchor.
++Furthermore, disassociation can be made with usb_unanchor_urb()
++
++Operations on multitudes of URBs
++================================
++
++usb_kill_anchored_urbs()
++------------------------
++
++This function kills all URBs associated with an anchor. The URBs
++are called in the reverse temporal order they were submitted.
++This way no data can be reordered.
++
++usb_wait_anchor_empty_timeout()
++-------------------------------
++
++This function waits for all URBs associated with an anchor to finish
++or a timeout, whichever comes first. Its return value will tell you
++whether the timeout was reached.
+diff --git a/Documentation/usb/callbacks.txt b/Documentation/usb/callbacks.txt
+new file mode 100644
+index 0000000..7c81241
+--- /dev/null
++++ b/Documentation/usb/callbacks.txt
+@@ -0,0 +1,132 @@
++What callbacks will usbcore do?
++===============================
++
++Usbcore will call into a driver through callbacks defined in the driver
++structure and through the completion handler of URBs a driver submits.
++Only the former are in the scope of this document. These two kinds of
++callbacks are completely independent of each other. Information on the
++completion callback can be found in Documentation/usb/URB.txt.
++
++The callbacks defined in the driver structure are:
++
++1. Hotplugging callbacks:
++
++ * @probe: Called to see if the driver is willing to manage a particular
++ * interface on a device.
++ * @disconnect: Called when the interface is no longer accessible, usually
++ * because its device has been (or is being) disconnected or the
++ * driver module is being unloaded.
++
++2. Odd backdoor through usbfs:
++
++ * @ioctl: Used for drivers that want to talk to userspace through
++ * the "usbfs" filesystem. This lets devices provide ways to
++ * expose information to user space regardless of where they
++ * do (or don't) show up otherwise in the filesystem.
++
++3. Power management (PM) callbacks:
++
++ * @suspend: Called when the device is going to be suspended.
++ * @resume: Called when the device is being resumed.
++ * @reset_resume: Called when the suspended device has been reset instead
++ * of being resumed.
++
++4. Device level operations:
++
++ * @pre_reset: Called when the device is about to be reset.
++ * @post_reset: Called after the device has been reset
++
++The ioctl interface (2) should be used only if you have a very good
++reason. Sysfs is preferred these days. The PM callbacks are covered
++separately in Documentation/usb/power-management.txt.
++
++Calling conventions
++===================
++
++All callbacks are mutually exclusive. There's no need for locking
++against other USB callbacks. All callbacks are called from a task
++context. You may sleep. However, it is important that all sleeps have a
++small fixed upper limit in time. In particular you must not call out to
++user space and await results.
++
++Hotplugging callbacks
++=====================
++
++These callbacks are intended to associate and disassociate a driver with
++an interface. A driver's bond to an interface is exclusive.
++
++The probe() callback
++--------------------
++
++int (*probe) (struct usb_interface *intf,
++ const struct usb_device_id *id);
++
++Accept or decline an interface. If you accept the device return 0,
++otherwise -ENODEV or -ENXIO. Other error codes should be used only if a
++genuine error occurred during initialisation which prevented a driver
++from accepting a device that would else have been accepted.
++You are strongly encouraged to use usbcore'sfacility,
++usb_set_intfdata(), to associate a data structure with an interface, so
++that you know which internal state and identity you associate with a
++particular interface. The device will not be suspended and you may do IO
++to the interface you are called for and endpoint 0 of the device. Device
++initialisation that doesn't take too long is a good idea here.
++
++The disconnect() callback
++-------------------------
++
++void (*disconnect) (struct usb_interface *intf);
++
++This callback is a signal to break any connection with an interface.
++You are not allowed any IO to a device after returning from this
++callback. You also may not do any other operation that may interfere
++with another driver bound the interface, eg. a power management
++operation.
++If you are called due to a physical disconnection, all your URBs will be
++killed by usbcore. Note that in this case disconnect will be called some
++time after the physical disconnection. Thus your driver must be prepared
++to deal with failing IO even prior to the callback.
++
++Device level callbacks
++======================
++
++pre_reset
++---------
++
++int (*pre_reset)(struct usb_interface *intf);
++
++Another driver or user space is triggering a reset on the device which
++contains the interface passed as an argument. Cease IO and save any
++device state you need to restore.
++
++If you need to allocate memory here, use GFP_NOIO or GFP_ATOMIC, if you
++are in atomic context.
++
++post_reset
++----------
++
++int (*post_reset)(struct usb_interface *intf);
++
++The reset has completed. Restore any saved device state and begin
++using the device again.
++
++If you need to allocate memory here, use GFP_NOIO or GFP_ATOMIC, if you
++are in atomic context.
++
++Call sequences
++==============
++
++No callbacks other than probe will be invoked for an interface
++that isn't bound to your driver.
++
++Probe will never be called for an interface bound to a driver.
++Hence following a successful probe, disconnect will be called
++before there is another probe for the same interface.
++
++Once your driver is bound to an interface, disconnect can be
++called at any time except in between pre_reset and post_reset.
++pre_reset is always followed by post_reset, even if the reset
++failed or the device has been unplugged.
++
++suspend is always followed by one of: resume, reset_resume, or
++disconnect.
+diff --git a/Documentation/usb/persist.txt b/Documentation/usb/persist.txt
+index df54d64..d56cb1a 100644
+--- a/Documentation/usb/persist.txt
++++ b/Documentation/usb/persist.txt
+@@ -2,7 +2,7 @@
+
+ Alan Stern <stern at rowland.harvard.edu>
+
+- September 2, 2006 (Updated May 29, 2007)
++ September 2, 2006 (Updated February 25, 2008)
+
+
+ What is the problem?
+@@ -65,9 +65,10 @@ much better.)
+
+ What is the solution?
+
+-Setting CONFIG_USB_PERSIST will cause the kernel to work around these
+-issues. It enables a mode in which the core USB device data
+-structures are allowed to persist across a power-session disruption.
++The kernel includes a feature called USB-persist. It tries to work
++around these issues by allowing the core USB device data structures to
++persist across a power-session disruption.
++
+ It works like this. If the kernel sees that a USB host controller is
+ not in the expected state during resume (i.e., if the controller was
+ reset or otherwise had lost power) then it applies a persistence check
+@@ -80,28 +81,30 @@ re-enumeration shows that the device now attached to that port has the
+ same descriptors as before, including the Vendor and Product IDs, then
+ the kernel continues to use the same device structure. In effect, the
+ kernel treats the device as though it had merely been reset instead of
+-unplugged.
++unplugged. The same thing happens if the host controller is in the
++expected state but a USB device was unplugged and then replugged.
+
+ If no device is now attached to the port, or if the descriptors are
+ different from what the kernel remembers, then the treatment is what
+ you would expect. The kernel destroys the old device structure and
+ behaves as though the old device had been unplugged and a new device
+-plugged in, just as it would without the CONFIG_USB_PERSIST option.
++plugged in.
+
+ The end result is that the USB device remains available and usable.
+ Filesystem mounts and memory mappings are unaffected, and the world is
+ now a good and happy place.
+
+-Note that even when CONFIG_USB_PERSIST is set, the "persist" feature
+-will be applied only to those devices for which it is enabled. You
+-can enable the feature by doing (as root):
++Note that the "USB-persist" feature will be applied only to those
++devices for which it is enabled. You can enable the feature by doing
++(as root):
+
+ echo 1 >/sys/bus/usb/devices/.../power/persist
+
+ where the "..." should be filled in the with the device's ID. Disable
+ the feature by writing 0 instead of 1. For hubs the feature is
+-automatically and permanently enabled, so you only have to worry about
+-setting it for devices where it really matters.
++automatically and permanently enabled and the power/persist file
++doesn't even exist, so you only have to worry about setting it for
++devices where it really matters.
+
+
+ Is this the best solution?
+@@ -112,19 +115,19 @@ centralized Logical Volume Manager. Such a solution would allow you
+ to plug in a USB flash device, create a persistent volume associated
+ with it, unplug the flash device, plug it back in later, and still
+ have the same persistent volume associated with the device. As such
+-it would be more far-reaching than CONFIG_USB_PERSIST.
++it would be more far-reaching than USB-persist.
+
+ On the other hand, writing a persistent volume manager would be a big
+ job and using it would require significant input from the user. This
+ solution is much quicker and easier -- and it exists now, a giant
+ point in its favor!
+
+-Furthermore, the USB_PERSIST option applies to _all_ USB devices, not
++Furthermore, the USB-persist feature applies to _all_ USB devices, not
+ just mass-storage devices. It might turn out to be equally useful for
+ other device types, such as network interfaces.
+
+
+- WARNING: Using CONFIG_USB_PERSIST can be dangerous!!
++ WARNING: USB-persist can be dangerous!!
+
+ When recovering an interrupted power session the kernel does its best
+ to make sure the USB device hasn't been changed; that is, the same
+@@ -133,10 +136,10 @@ aren't guaranteed to be 100% accurate.
+
+ If you replace one USB device with another of the same type (same
+ manufacturer, same IDs, and so on) there's an excellent chance the
+-kernel won't detect the change. Serial numbers and other strings are
+-not compared. In many cases it wouldn't help if they were, because
+-manufacturers frequently omit serial numbers entirely in their
+-devices.
++kernel won't detect the change. The serial number string and other
++descriptors are compared with the kernel's stored values, but this
++might not help since manufacturers frequently omit serial numbers
++entirely in their devices.
+
+ Furthermore it's quite possible to leave a USB device exactly the same
+ while changing its media. If you replace the flash memory card in a
+@@ -152,5 +155,5 @@ but yourself.
+ YOU HAVE BEEN WARNED! USE AT YOUR OWN RISK!
+
+ That having been said, most of the time there shouldn't be any trouble
+-at all. The "persist" feature can be extremely useful. Make the most
+-of it.
++at all. The USB-persist feature can be extremely useful. Make the
++most of it.
+diff --git a/Documentation/usb/usb-serial.txt b/Documentation/usb/usb-serial.txt
+index 8b077e4..ff2c1ff 100644
+--- a/Documentation/usb/usb-serial.txt
++++ b/Documentation/usb/usb-serial.txt
+@@ -192,12 +192,9 @@ Keyspan USA-series Serial Adapters
+
+ FTDI Single Port Serial Driver
+
+- This is a single port DB-25 serial adapter. More information about this
+- device and the Linux driver can be found at:
+- http://reality.sgi.com/bryder_wellington/ftdi_sio/
++ This is a single port DB-25 serial adapter.
+
+- For any questions or problems with this driver, please contact Bill Ryder
+- at bryder at sgi.com
++ For any questions or problems with this driver, please contact Bill Ryder.
+
+
+ ZyXEL omni.net lcd plus ISDN TA
+diff --git a/Documentation/video4linux/CARDLIST.au0828 b/Documentation/video4linux/CARDLIST.au0828
+new file mode 100644
+index 0000000..aaae360
+--- /dev/null
++++ b/Documentation/video4linux/CARDLIST.au0828
+@@ -0,0 +1,4 @@
++ 0 -> Unknown board (au0828)
++ 1 -> Hauppauge HVR950Q (au0828) [2040:7200]
++ 2 -> Hauppauge HVR850 (au0828) [2040:7240]
++ 3 -> DViCO FusionHDTV USB (au0828) [0fe9:d620]
+diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv
+index d97cf7c..f32efb6 100644
+--- a/Documentation/video4linux/CARDLIST.bttv
++++ b/Documentation/video4linux/CARDLIST.bttv
+@@ -148,3 +148,5 @@
+ 147 -> VoodooTV 200 (USA) [121a:3000]
+ 148 -> DViCO FusionHDTV 2 [dbc0:d200]
+ 149 -> Typhoon TV-Tuner PCI (50684)
++150 -> Geovision GV-600 [008a:763c]
++151 -> Kozumi KTV-01C
+diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885
+index 0924e6e..929b90c 100644
+--- a/Documentation/video4linux/CARDLIST.cx23885
++++ b/Documentation/video4linux/CARDLIST.cx23885
+@@ -5,3 +5,6 @@
+ 4 -> DViCO FusionHDTV5 Express [18ac:d500]
+ 5 -> Hauppauge WinTV-HVR1500Q [0070:7790,0070:7797]
+ 6 -> Hauppauge WinTV-HVR1500 [0070:7710,0070:7717]
++ 7 -> Hauppauge WinTV-HVR1200 [0070:71d1]
++ 8 -> Hauppauge WinTV-HVR1700 [0070:8101]
++ 9 -> Hauppauge WinTV-HVR1400 [0070:8010]
+diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88
+index bc5593b..5439573 100644
+--- a/Documentation/video4linux/CARDLIST.cx88
++++ b/Documentation/video4linux/CARDLIST.cx88
+@@ -57,3 +57,12 @@
+ 56 -> Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder [0070:9600,0070:9601,0070:9602]
+ 57 -> ADS Tech Instant Video PCI [1421:0390]
+ 58 -> Pinnacle PCTV HD 800i [11bd:0051]
++ 59 -> DViCO FusionHDTV 5 PCI nano [18ac:d530]
++ 60 -> Pinnacle Hybrid PCTV [12ab:1788]
++ 61 -> Winfast TV2000 XP Global [107d:6f18]
++ 62 -> PowerColor Real Angel 330 [14f1:ea3d]
++ 63 -> Geniatech X8000-MT DVBT [14f1:8852]
++ 64 -> DViCO FusionHDTV DVB-T PRO [18ac:db30]
++ 65 -> DViCO FusionHDTV 7 Gold [18ac:d610]
++ 66 -> Prolink Pixelview MPEG 8000GT [1554:4935]
++ 67 -> Kworld PlusTV HD PCI 120 (ATSC 120) [17de:08c1]
+diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134
+index 0424901..44d84dd 100644
+--- a/Documentation/video4linux/CARDLIST.saa7134
++++ b/Documentation/video4linux/CARDLIST.saa7134
+@@ -25,8 +25,8 @@
+ 24 -> KNC One TV-Station DVR [1894:a006]
+ 25 -> ASUS TV-FM 7133 [1043:4843]
+ 26 -> Pinnacle PCTV Stereo (saa7134) [11bd:002b]
+- 27 -> Manli MuchTV M-TV002/Behold TV 403 FM
+- 28 -> Manli MuchTV M-TV001/Behold TV 401
++ 27 -> Manli MuchTV M-TV002
++ 28 -> Manli MuchTV M-TV001
+ 29 -> Nagase Sangyo TransGear 3000TV [1461:050c]
+ 30 -> Elitegroup ECS TVP3XP FM1216 Tuner Card(PAL-BG,FM) [1019:4cb4]
+ 31 -> Elitegroup ECS TVP3XP FM1236 Tuner Card (NTSC,FM) [1019:4cb5]
+@@ -131,3 +131,12 @@
+ 130 -> Beholder BeholdTV M6 / BeholdTV M6 Extra [5ace:6190,5ace:6193]
+ 131 -> Twinhan Hybrid DTV-DVB 3056 PCI [1822:0022]
+ 132 -> Genius TVGO AM11MCE
++133 -> NXP Snake DVB-S reference design
++134 -> Medion/Creatix CTX953 Hybrid [16be:0010]
++135 -> MSI TV at nywhere A/D v1.1 [1462:8625]
++136 -> AVerMedia Cardbus TV/Radio (E506R) [1461:f436]
++137 -> AVerMedia Hybrid TV/Radio (A16D) [1461:f936]
++138 -> Avermedia M115 [1461:a836]
++139 -> Compro VideoMate T750 [185b:c900]
++140 -> Avermedia DVB-S Pro A700 [1461:a7a1]
++141 -> Avermedia DVB-S Hybrid+FM A700 [1461:a7a2]
+diff --git a/Documentation/video4linux/extract_xc3028.pl b/Documentation/video4linux/extract_xc3028.pl
+index cced8ac..2cb8160 100644
+--- a/Documentation/video4linux/extract_xc3028.pl
++++ b/Documentation/video4linux/extract_xc3028.pl
+@@ -686,11 +686,11 @@ sub main_firmware($$$$)
+ write_hunk(812664, 192);
+
+ #
+- # Firmware 58, type: SCODE FW HAS IF (0x60000000), IF = 4.50 MHz id: NTSC/M Jp (0000000000002000), size: 192
++ # Firmware 58, type: SCODE FW MTS LCD NOGD MONO IF HAS IF (0x6002b004), IF = 4.50 MHz id: NTSC PAL/M PAL/N (000000000000b700), size: 192
+ #
+
+- write_le32(0x60000000); # Type
+- write_le64(0x00000000, 0x00002000); # ID
++ write_le32(0x6002b004); # Type
++ write_le64(0x00000000, 0x0000b700); # ID
+ write_le16(4500); # IF
+ write_le32(192); # Size
+ write_hunk(807672, 192);
+@@ -706,10 +706,10 @@ sub main_firmware($$$$)
+ write_hunk(807864, 192);
+
+ #
+- # Firmware 60, type: SCODE FW DTV78 ZARLINK456 HAS IF (0x62000100), IF = 4.76 MHz id: (0000000000000000), size: 192
++ # Firmware 60, type: SCODE FW DTV6 QAM DTV7 DTV78 DTV8 ZARLINK456 HAS IF (0x620003e0), IF = 4.76 MHz id: (0000000000000000), size: 192
+ #
+
+- write_le32(0x62000100); # Type
++ write_le32(0x620003e0); # Type
+ write_le64(0x00000000, 0x00000000); # ID
+ write_le16(4760); # IF
+ write_le32(192); # Size
+@@ -726,30 +726,30 @@ sub main_firmware($$$$)
+ write_hunk(811512, 192);
+
+ #
+- # Firmware 62, type: SCODE FW DTV7 ZARLINK456 HAS IF (0x62000080), IF = 5.26 MHz id: (0000000000000000), size: 192
++ # Firmware 62, type: SCODE FW HAS IF (0x60000000), IF = 5.26 MHz id: (0000000000000000), size: 192
+ #
+
+- write_le32(0x62000080); # Type
++ write_le32(0x60000000); # Type
+ write_le64(0x00000000, 0x00000000); # ID
+ write_le16(5260); # IF
+ write_le32(192); # Size
+ write_hunk(810552, 192);
+
+ #
+- # Firmware 63, type: SCODE FW MONO HAS IF (0x60008000), IF = 5.32 MHz id: PAL/BG NICAM/B (0000000800000007), size: 192
++ # Firmware 63, type: SCODE FW MONO HAS IF (0x60008000), IF = 5.32 MHz id: PAL/BG A2 NICAM (0000000f00000007), size: 192
+ #
+
+ write_le32(0x60008000); # Type
+- write_le64(0x00000008, 0x00000007); # ID
++ write_le64(0x0000000f, 0x00000007); # ID
+ write_le16(5320); # IF
+ write_le32(192); # Size
+ write_hunk(810744, 192);
+
+ #
+- # Firmware 64, type: SCODE FW DTV8 CHINA HAS IF (0x64000200), IF = 5.40 MHz id: (0000000000000000), size: 192
++ # Firmware 64, type: SCODE FW DTV7 DTV78 DTV8 DIBCOM52 CHINA HAS IF (0x65000380), IF = 5.40 MHz id: (0000000000000000), size: 192
+ #
+
+- write_le32(0x64000200); # Type
++ write_le32(0x65000380); # Type
+ write_le64(0x00000000, 0x00000000); # ID
+ write_le16(5400); # IF
+ write_le32(192); # Size
+@@ -766,50 +766,50 @@ sub main_firmware($$$$)
+ write_hunk(809592, 192);
+
+ #
+- # Firmware 66, type: SCODE FW HAS IF (0x60000000), IF = 5.64 MHz id: PAL/BG A2/B (0000000200000007), size: 192
++ # Firmware 66, type: SCODE FW HAS IF (0x60000000), IF = 5.64 MHz id: PAL/BG A2 (0000000300000007), size: 192
+ #
+
+ write_le32(0x60000000); # Type
+- write_le64(0x00000002, 0x00000007); # ID
++ write_le64(0x00000003, 0x00000007); # ID
+ write_le16(5640); # IF
+ write_le32(192); # Size
+ write_hunk(808440, 192);
+
+ #
+- # Firmware 67, type: SCODE FW HAS IF (0x60000000), IF = 5.74 MHz id: PAL/BG NICAM/B (0000000800000007), size: 192
++ # Firmware 67, type: SCODE FW HAS IF (0x60000000), IF = 5.74 MHz id: PAL/BG NICAM (0000000c00000007), size: 192
+ #
+
+ write_le32(0x60000000); # Type
+- write_le64(0x00000008, 0x00000007); # ID
++ write_le64(0x0000000c, 0x00000007); # ID
+ write_le16(5740); # IF
+ write_le32(192); # Size
+ write_hunk(808632, 192);
+
+ #
+- # Firmware 68, type: SCODE FW DTV7 DIBCOM52 HAS IF (0x61000080), IF = 5.90 MHz id: (0000000000000000), size: 192
++ # Firmware 68, type: SCODE FW HAS IF (0x60000000), IF = 5.90 MHz id: (0000000000000000), size: 192
+ #
+
+- write_le32(0x61000080); # Type
++ write_le32(0x60000000); # Type
+ write_le64(0x00000000, 0x00000000); # ID
+ write_le16(5900); # IF
+ write_le32(192); # Size
+ write_hunk(810360, 192);
+
+ #
+- # Firmware 69, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.00 MHz id: PAL/I (0000000000000010), size: 192
++ # Firmware 69, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.00 MHz id: PAL/DK PAL/I SECAM/K3 SECAM/L SECAM/Lc NICAM (0000000c04c000f0), size: 192
+ #
+
+ write_le32(0x60008000); # Type
+- write_le64(0x00000000, 0x00000010); # ID
++ write_le64(0x0000000c, 0x04c000f0); # ID
+ write_le16(6000); # IF
+ write_le32(192); # Size
+ write_hunk(808824, 192);
+
+ #
+- # Firmware 70, type: SCODE FW DTV6 QAM F6MHZ HAS IF (0x68000060), IF = 6.20 MHz id: (0000000000000000), size: 192
++ # Firmware 70, type: SCODE FW DTV6 QAM ATSC LG60 F6MHZ HAS IF (0x68050060), IF = 6.20 MHz id: (0000000000000000), size: 192
+ #
+
+- write_le32(0x68000060); # Type
++ write_le32(0x68050060); # Type
+ write_le64(0x00000000, 0x00000000); # ID
+ write_le16(6200); # IF
+ write_le32(192); # Size
+@@ -846,11 +846,11 @@ sub main_firmware($$$$)
+ write_hunk(809208, 192);
+
+ #
+- # Firmware 74, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.50 MHz id: SECAM/K3 (0000000004000000), size: 192
++ # Firmware 74, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.50 MHz id: PAL/DK SECAM/K3 SECAM/L NICAM (0000000c044000e0), size: 192
+ #
+
+ write_le32(0x60008000); # Type
+- write_le64(0x00000000, 0x04000000); # ID
++ write_le64(0x0000000c, 0x044000e0); # ID
+ write_le16(6500); # IF
+ write_le32(192); # Size
+ write_hunk(811128, 192);
+diff --git a/Documentation/x86/pat.txt b/Documentation/x86/pat.txt
+new file mode 100644
+index 0000000..17965f9
+--- /dev/null
++++ b/Documentation/x86/pat.txt
+@@ -0,0 +1,100 @@
++
++PAT (Page Attribute Table)
++
++x86 Page Attribute Table (PAT) allows for setting the memory attribute at the
++page level granularity. PAT is complementary to the MTRR settings which allows
++for setting of memory types over physical address ranges. However, PAT is
++more flexible than MTRR due to its capability to set attributes at page level
++and also due to the fact that there are no hardware limitations on number of
++such attribute settings allowed. Added flexibility comes with guidelines for
++not having memory type aliasing for the same physical memory with multiple
++virtual addresses.
++
++PAT allows for different types of memory attributes. The most commonly used
++ones that will be supported at this time are Write-back, Uncached,
++Write-combined and Uncached Minus.
++
++There are many different APIs in the kernel that allows setting of memory
++attributes at the page level. In order to avoid aliasing, these interfaces
++should be used thoughtfully. Below is a table of interfaces available,
++their intended usage and their memory attribute relationships. Internally,
++these APIs use a reserve_memtype()/free_memtype() interface on the physical
++address range to avoid any aliasing.
++
++
++-------------------------------------------------------------------
++API | RAM | ACPI,... | Reserved/Holes |
++-----------------------|----------|------------|------------------|
++ | | | |
++ioremap | -- | UC | UC |
++ | | | |
++ioremap_cache | -- | WB | WB |
++ | | | |
++ioremap_nocache | -- | UC | UC |
++ | | | |
++ioremap_wc | -- | -- | WC |
++ | | | |
++set_memory_uc | UC | -- | -- |
++ set_memory_wb | | | |
++ | | | |
++set_memory_wc | WC | -- | -- |
++ set_memory_wb | | | |
++ | | | |
++pci sysfs resource | -- | -- | UC |
++ | | | |
++pci sysfs resource_wc | -- | -- | WC |
++ is IORESOURCE_PREFETCH| | | |
++ | | | |
++pci proc | -- | -- | UC |
++ !PCIIOC_WRITE_COMBINE | | | |
++ | | | |
++pci proc | -- | -- | WC |
++ PCIIOC_WRITE_COMBINE | | | |
++ | | | |
++/dev/mem | -- | UC | UC |
++ read-write | | | |
++ | | | |
++/dev/mem | -- | UC | UC |
++ mmap SYNC flag | | | |
++ | | | |
++/dev/mem | -- | WB/WC/UC | WB/WC/UC |
++ mmap !SYNC flag | |(from exist-| (from exist- |
++ and | | ing alias)| ing alias) |
++ any alias to this area| | | |
++ | | | |
++/dev/mem | -- | WB | WB |
++ mmap !SYNC flag | | | |
++ no alias to this area | | | |
++ and | | | |
++ MTRR says WB | | | |
++ | | | |
++/dev/mem | -- | -- | UC_MINUS |
++ mmap !SYNC flag | | | |
++ no alias to this area | | | |
++ and | | | |
++ MTRR says !WB | | | |
++ | | | |
++-------------------------------------------------------------------
++
++Notes:
++
++-- in the above table mean "Not suggested usage for the API". Some of the --'s
++are strictly enforced by the kernel. Some others are not really enforced
++today, but may be enforced in future.
++
++For ioremap and pci access through /sys or /proc - The actual type returned
++can be more restrictive, in case of any existing aliasing for that address.
++For example: If there is an existing uncached mapping, a new ioremap_wc can
++return uncached mapping in place of write-combine requested.
++
++set_memory_[uc|wc] and set_memory_wb should be used in pairs, where driver will
++first make a region uc or wc and switch it back to wb after use.
++
++Over time writes to /proc/mtrr will be deprecated in favor of using PAT based
++interfaces. Users writing to /proc/mtrr are suggested to use above interfaces.
++
++Drivers should use ioremap_[uc|wc] to access PCI BARs with [uc|wc] access
++types.
++
++Drivers should use set_memory_[uc|wc] to set access type for RAM ranges.
++
+diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt
+index 34abae4..b0c7b6c 100644
+--- a/Documentation/x86_64/boot-options.txt
++++ b/Documentation/x86_64/boot-options.txt
+@@ -307,3 +307,8 @@ Debugging
+ stuck (default)
+
+ Miscellaneous
++
++ nogbpages
++ Do not use GB pages for kernel direct mappings.
++ gbpages
++ Use GB pages for kernel direct mappings.
+diff --git a/MAINTAINERS b/MAINTAINERS
+index e467758..a942f38 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -486,6 +486,12 @@ M: kernel at wantstofly.org
+ L: linux-arm-kernel at lists.arm.linux.org.uk (subscribers-only)
+ S: Maintained
+
++ARM/GUMSTIX MACHINE SUPPORT
++P: Steve Sakoman
++M: sakoman at gmail.com
++L: linux-arm-kernel at lists.arm.linux.org.uk (subscribers-only)
++S: Maintained
++
+ ARM/HP JORNADA 7XX MACHINE SUPPORT
+ P: Kristoffer Ericson
+ M: kristoffer.ericson at gmail.com
+@@ -678,6 +684,11 @@ L: linux-wireless at vger.kernel.org
+ L: ath5k-devel at lists.ath5k.org
+ S: Maintained
+
++ATI_REMOTE2 DRIVER
++P: Ville Syrjala
++M: syrjala at sci.fi
++S: Maintained
++
+ ATL1 ETHERNET DRIVER
+ P: Jay Cliburn
+ M: jcliburn at gmail.com
+@@ -840,15 +851,6 @@ L: linux-wireless at vger.kernel.org
+ W: http://linuxwireless.org/en/users/Drivers/b43
+ S: Maintained
+
+-BCM43XX WIRELESS DRIVER (SOFTMAC BASED VERSION)
+-P: Larry Finger
+-M: Larry.Finger at lwfinger.net
+-P: Stefano Brivio
+-M: stefano.brivio at polimi.it
+-L: linux-wireless at vger.kernel.org
+-W: http://bcm43xx.berlios.de/
+-S: Obsolete
+-
+ BEFS FILE SYSTEM
+ P: Sergey S. Kostyliov
+ M: rathamahata at php4.ru
+@@ -1104,6 +1106,12 @@ M: kernel at wantstofly.org
+ L: linux-usb at vger.kernel.org
+ S: Maintained
+
++CIRRUS LOGIC CS4270 SOUND DRIVER
++P: Timur Tabi
++M: timur at freescale.com
++L: alsa-devel at alsa-project.org
++S: Supported
++
+ CIRRUS LOGIC CS4280/CS461x SOUNDDRIVER
+ P: Cirrus Logic Corporation (kernel 2.2 driver)
+ M: Cirrus Logic Corporation, Thomas Woller <twoller at crystal.cirrus.com>
+@@ -1626,6 +1634,12 @@ L: linuxppc-dev at ozlabs.org
+ L: netdev at vger.kernel.org
+ S: Maintained
+
++FREESCALE QUICC ENGINE LIBRARY
++P: Timur Tabi
++M: timur at freescale.com
++L: linuxppc-dev at ozlabs.org
++S: Supported
++
+ FREESCALE HIGHSPEED USB DEVICE DRIVER
+ P: Li Yang
+ M: leoli at freescale.com
+@@ -1640,6 +1654,19 @@ L: netdev at vger.kernel.org
+ L: linuxppc-dev at ozlabs.org
+ S: Maintained
+
++FREESCALE QUICC ENGINE UCC UART DRIVER
++P: Timur Tabi
++M: timur at freescale.com
++L: linuxppc-dev at ozlabs.org
++S: Supported
++
++FREESCALE SOC SOUND DRIVERS
++P: Timur Tabi
++M: timur at freescale.com
++L: alsa-devel at alsa-project.org
++L: linuxppc-dev at ozlabs.org
++S: Supported
++
+ FILE LOCKING (flock() and fcntl()/lockf())
+ P: Matthew Wilcox
+ M: matthew at wil.cx
+@@ -2319,6 +2346,12 @@ L: linux-kernel at vger.kernel.org
+ L: kexec at lists.infradead.org
+ S: Maintained
+
++KGDB
++P: Jason Wessel
++M: jason.wessel at windriver.com
++L: kgdb-bugreport at lists.sourceforge.net
++S: Maintained
++
+ KPROBES
+ P: Ananth N Mavinakayanahalli
+ M: ananth at in.ibm.com
+@@ -2550,12 +2583,10 @@ W: http://www.tazenda.demon.co.uk/phil/linux-hp
+ S: Maintained
+
+ MAC80211
+-P: Michael Wu
+-M: flamingice at sourmilk.net
+ P: Johannes Berg
+ M: johannes at sipsolutions.net
+-P: Jiri Benc
+-M: jbenc at suse.cz
++P: Michael Wu
++M: flamingice at sourmilk.net
+ L: linux-wireless at vger.kernel.org
+ W: http://linuxwireless.org/
+ T: git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git
+@@ -2944,8 +2975,9 @@ P: Mark Fasheh
+ M: mfasheh at suse.com
+ P: Joel Becker
+ M: joel.becker at oracle.com
+-L: ocfs2-devel at oss.oracle.com
++L: ocfs2-devel at oss.oracle.com (moderated for non-subscribers)
+ W: http://oss.oracle.com/projects/ocfs2/
++T: git git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2.git
+ S: Supported
+
+ OMNIKEY CARDMAN 4000 DRIVER
+@@ -3061,11 +3093,10 @@ L: linux-pci at atrey.karlin.mff.cuni.cz
+ S: Supported
+
+ PCI SUBSYSTEM
+-P: Greg Kroah-Hartman
+-M: gregkh at suse.de
++P: Jesse Barnes
++M: jbarnes at virtuousgeek.org
+ L: linux-kernel at vger.kernel.org
+ L: linux-pci at atrey.karlin.mff.cuni.cz
+-T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
+ S: Supported
+
+ PCI HOTPLUG CORE
+@@ -3472,7 +3503,7 @@ P: Vlad Yasevich
+ M: vladislav.yasevich at hp.com
+ P: Sridhar Samudrala
+ M: sri at us.ibm.com
+-L: lksctp-developers at lists.sourceforge.net
++L: linux-sctp at vger.kernel.org
+ W: http://lksctp.sourceforge.net
+ S: Supported
+
+@@ -3606,11 +3637,10 @@ M: mhoffman at lightlink.com
+ L: lm-sensors at lm-sensors.org
+ S: Maintained
+
+-SOFTMAC LAYER (IEEE 802.11)
+-P: Daniel Drake
+-M: dsd at gentoo.org
+-L: linux-wireless at vger.kernel.org
+-S: Obsolete
++SMX UIO Interface
++P: Ben Nizette
++M: bn at niasdigital.com
++S: Maintained
+
+ SOFTWARE RAID (Multiple Disks) SUPPORT
+ P: Ingo Molnar
+@@ -4351,6 +4381,16 @@ L: linux-wireless at vger.kernel.org
+ W: http://oops.ghostprotocols.net:81/blog
+ S: Maintained
+
++WM97XX TOUCHSCREEN DRIVERS
++P: Mark Brown
++M: broonie at opensource.wolfsonmicro.com
++P: Liam Girdwood
++M: liam.girdwood at wolfsonmicro.com
++L: linux-input at vger.kernel.org
++T: git git://opensource.wolfsonmicro.com/linux-2.6-touch
++W: http://opensource.wolfsonmicro.com/node/7
++S: Supported
++
+ X.25 NETWORK LAYER
+ P: Henner Eisen
+ M: eis at baty.hanse.de
+diff --git a/Makefile b/Makefile
+index 39516bf..cbd79f3 100644
+--- a/Makefile
++++ b/Makefile
+@@ -507,6 +507,10 @@ else
+ KBUILD_CFLAGS += -O2
+ endif
+
++ifneq (CONFIG_FRAME_WARN,0)
++KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN})
++endif
++
+ # Force gcc to behave correct even for buggy distributions
+ # Arch Makefiles may override this setting
+ KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector)
+@@ -1396,7 +1400,7 @@ define xtags
+ $(all-kconfigs) | xargs $1 -a \
+ --langdef=kconfig \
+ --language-force=kconfig \
+- --regex-kconfig='/^[[:blank:]]*config[[:blank:]]+([[:alnum:]_]+)/\1/'; \
++ --regex-kconfig='/^[[:blank:]]*(menu|)config[[:blank:]]+([[:alnum:]_]+)/\2/'; \
+ $(all-defconfigs) | xargs -r $1 -a \
+ --langdef=dotconfig \
+ --language-force=dotconfig \
+@@ -1404,7 +1408,7 @@ define xtags
+ elif $1 --version 2>&1 | grep -iq emacs; then \
+ $(all-sources) | xargs $1 -a; \
+ $(all-kconfigs) | xargs $1 -a \
+- --regex='/^[ \t]*config[ \t]+\([a-zA-Z0-9_]+\)/\1/'; \
++ --regex='/^[ \t]*(menu|)config[ \t]+\([a-zA-Z0-9_]+\)/\2/'; \
+ $(all-defconfigs) | xargs -r $1 -a \
+ --regex='/^#?[ \t]?\(CONFIG_[a-zA-Z0-9_]+\)/\1/'; \
+ else \
+@@ -1538,8 +1542,7 @@ quiet_cmd_rmdirs = $(if $(wildcard $(rm-dirs)),CLEAN $(wildcard $(rm-dirs)))
+ quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN $(wildcard $(rm-files)))
+ cmd_rmfiles = rm -f $(rm-files)
+
+-# Run depmod only is we have System.map and depmod is executable
+-# and we build for the host arch
++# Run depmod only if we have System.map and depmod is executable
+ quiet_cmd_depmod = DEPMOD $(KERNELRELEASE)
+ cmd_depmod = \
+ if [ -r System.map -a -x $(DEPMOD) ]; then \
+diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
+index dccf052..ac706c1 100644
+--- a/arch/alpha/kernel/Makefile
++++ b/arch/alpha/kernel/Makefile
+@@ -7,7 +7,7 @@ EXTRA_AFLAGS := $(KBUILD_CFLAGS)
+ EXTRA_CFLAGS := -Werror -Wno-sign-compare
+
+ obj-y := entry.o traps.o process.o init_task.o osf_sys.o irq.o \
+- irq_alpha.o signal.o setup.o ptrace.o time.o semaphore.o \
++ irq_alpha.o signal.o setup.o ptrace.o time.o \
+ alpha_ksyms.o systbls.o err_common.o io.o
+
+ obj-$(CONFIG_VGA_HOSE) += console.o
+diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
+index e9762a3..d96e742 100644
+--- a/arch/alpha/kernel/alpha_ksyms.c
++++ b/arch/alpha/kernel/alpha_ksyms.c
+@@ -77,15 +77,6 @@ EXPORT_SYMBOL(__do_clear_user);
+ EXPORT_SYMBOL(__strncpy_from_user);
+ EXPORT_SYMBOL(__strnlen_user);
+
+-/* Semaphore helper functions. */
+-EXPORT_SYMBOL(__down_failed);
+-EXPORT_SYMBOL(__down_failed_interruptible);
+-EXPORT_SYMBOL(__up_wakeup);
+-EXPORT_SYMBOL(down);
+-EXPORT_SYMBOL(down_interruptible);
+-EXPORT_SYMBOL(down_trylock);
+-EXPORT_SYMBOL(up);
+-
+ /*
+ * SMP-specific symbols.
+ */
+diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
+index 8c71daf..9fee37e 100644
+--- a/arch/alpha/kernel/osf_sys.c
++++ b/arch/alpha/kernel/osf_sys.c
+@@ -75,6 +75,7 @@ osf_set_program_attributes(unsigned long text_start, unsigned long text_len,
+ lock_kernel();
+ mm = current->mm;
+ mm->end_code = bss_start + bss_len;
++ mm->start_brk = bss_start + bss_len;
+ mm->brk = bss_start + bss_len;
+ #if 0
+ printk("set_program_attributes(%lx %lx %lx %lx)\n",
+diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
+index 9dc1cee..7835779 100644
+--- a/arch/alpha/kernel/pci.c
++++ b/arch/alpha/kernel/pci.c
+@@ -71,25 +71,13 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378, quirk_i
+ static void __init
+ quirk_cypress(struct pci_dev *dev)
+ {
+- /* The Notorious Cy82C693 chip. */
+-
+- /* The Cypress IDE controller doesn't support native mode, but it
+- has programmable addresses of IDE command/control registers.
+- This violates PCI specifications, confuses the IDE subsystem and
+- causes resource conflicts between the primary HD_CMD register and
+- the floppy controller. Ugh. Fix that. */
+- if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE) {
+- dev->resource[0].flags = 0;
+- dev->resource[1].flags = 0;
+- }
+-
+ /* The Cypress bridge responds on the PCI bus in the address range
+ 0xffff0000-0xffffffff (conventional x86 BIOS ROM). There is no
+ way to turn this off. The bridge also supports several extended
+ BIOS ranges (disabled after power-up), and some consoles do turn
+ them on. So if we use a large direct-map window, or a large SG
+ window, we must avoid the entire 0xfff00000-0xffffffff region. */
+- else if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA) {
++ if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA) {
+ if (__direct_map_base + __direct_map_size >= 0xfff00000UL)
+ __direct_map_size = 0xfff00000UL - __direct_map_base;
+ else {
+@@ -372,28 +360,7 @@ EXPORT_SYMBOL(pcibios_bus_to_resource);
+ int
+ pcibios_enable_device(struct pci_dev *dev, int mask)
+ {
+- u16 cmd, oldcmd;
+- int i;
+-
+- pci_read_config_word(dev, PCI_COMMAND, &cmd);
+- oldcmd = cmd;
+-
+- for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+- struct resource *res = &dev->resource[i];
+-
+- if (res->flags & IORESOURCE_IO)
+- cmd |= PCI_COMMAND_IO;
+- else if (res->flags & IORESOURCE_MEM)
+- cmd |= PCI_COMMAND_MEMORY;
+- }
+-
+- if (cmd != oldcmd) {
+- printk(KERN_DEBUG "PCI: Enabling device: (%s), cmd %x\n",
+- pci_name(dev), cmd);
+- /* Enable the appropriate bits in the PCI command register. */
+- pci_write_config_word(dev, PCI_COMMAND, cmd);
+- }
+- return 0;
++ return pci_enable_resources(dev, mask);
+ }
+
+ /*
+@@ -412,7 +379,7 @@ pcibios_set_master(struct pci_dev *dev)
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
+ }
+
+-static void __init
++void __init
+ pcibios_claim_one_bus(struct pci_bus *b)
+ {
+ struct pci_dev *dev;
+@@ -426,7 +393,8 @@ pcibios_claim_one_bus(struct pci_bus *b)
+
+ if (r->parent || !r->start || !r->flags)
+ continue;
+- pci_claim_resource(dev, i);
++ if (pci_probe_only || (r->flags & IORESOURCE_PCI_FIXED))
++ pci_claim_resource(dev, i);
+ }
+ }
+
+@@ -465,8 +433,7 @@ common_init_pci(void)
+ }
+ }
+
+- if (pci_probe_only)
+- pcibios_claim_console_setup();
++ pcibios_claim_console_setup();
+
+ pci_assign_unassigned_resources();
+ pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
+diff --git a/arch/alpha/kernel/semaphore.c b/arch/alpha/kernel/semaphore.c
+deleted file mode 100644
+index 8d2982a..0000000
+--- a/arch/alpha/kernel/semaphore.c
++++ /dev/null
+@@ -1,224 +0,0 @@
+-/*
+- * Alpha semaphore implementation.
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- * (C) Copyright 1999, 2000 Richard Henderson
+- */
+-
+-#include <linux/errno.h>
+-#include <linux/sched.h>
+-#include <linux/init.h>
+-
+-/*
+- * This is basically the PPC semaphore scheme ported to use
+- * the Alpha ll/sc sequences, so see the PPC code for
+- * credits.
+- */
+-
+-/*
+- * Atomically update sem->count.
+- * This does the equivalent of the following:
+- *
+- * old_count = sem->count;
+- * tmp = MAX(old_count, 0) + incr;
+- * sem->count = tmp;
+- * return old_count;
+- */
+-static inline int __sem_update_count(struct semaphore *sem, int incr)
+-{
+- long old_count, tmp = 0;
+-
+- __asm__ __volatile__(
+- "1: ldl_l %0,%2\n"
+- " cmovgt %0,%0,%1\n"
+- " addl %1,%3,%1\n"
+- " stl_c %1,%2\n"
+- " beq %1,2f\n"
+- " mb\n"
+- ".subsection 2\n"
+- "2: br 1b\n"
+- ".previous"
+- : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
+- : "Ir" (incr), "1" (tmp), "m" (sem->count));
+-
+- return old_count;
+-}
+-
+-/*
+- * Perform the "down" function. Return zero for semaphore acquired,
+- * return negative for signalled out of the function.
+- *
+- * If called from down, the return is ignored and the wait loop is
+- * not interruptible. This means that a task waiting on a semaphore
+- * using "down()" cannot be killed until someone does an "up()" on
+- * the semaphore.
+- *
+- * If called from down_interruptible, the return value gets checked
+- * upon return. If the return value is negative then the task continues
+- * with the negative value in the return register (it can be tested by
+- * the caller).
+- *
+- * Either form may be used in conjunction with "up()".
+- */
+-
+-void __sched
+-__down_failed(struct semaphore *sem)
+-{
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+-
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+- printk("%s(%d): down failed(%p)\n",
+- tsk->comm, task_pid_nr(tsk), sem);
+-#endif
+-
+- tsk->state = TASK_UNINTERRUPTIBLE;
+- wmb();
+- add_wait_queue_exclusive(&sem->wait, &wait);
+-
+- /*
+- * Try to get the semaphore. If the count is > 0, then we've
+- * got the semaphore; we decrement count and exit the loop.
+- * If the count is 0 or negative, we set it to -1, indicating
+- * that we are asleep, and then sleep.
+- */
+- while (__sem_update_count(sem, -1) <= 0) {
+- schedule();
+- set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+- }
+- remove_wait_queue(&sem->wait, &wait);
+- tsk->state = TASK_RUNNING;
+-
+- /*
+- * If there are any more sleepers, wake one of them up so
+- * that it can either get the semaphore, or set count to -1
+- * indicating that there are still processes sleeping.
+- */
+- wake_up(&sem->wait);
+-
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+- printk("%s(%d): down acquired(%p)\n",
+- tsk->comm, task_pid_nr(tsk), sem);
+-#endif
+-}
+-
+-int __sched
+-__down_failed_interruptible(struct semaphore *sem)
+-{
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+- long ret = 0;
+-
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+- printk("%s(%d): down failed(%p)\n",
+- tsk->comm, task_pid_nr(tsk), sem);
+-#endif
+-
+- tsk->state = TASK_INTERRUPTIBLE;
+- wmb();
+- add_wait_queue_exclusive(&sem->wait, &wait);
+-
+- while (__sem_update_count(sem, -1) <= 0) {
+- if (signal_pending(current)) {
+- /*
+- * A signal is pending - give up trying.
+- * Set sem->count to 0 if it is negative,
+- * since we are no longer sleeping.
+- */
+- __sem_update_count(sem, 0);
+- ret = -EINTR;
+- break;
+- }
+- schedule();
+- set_task_state(tsk, TASK_INTERRUPTIBLE);
+- }
+-
+- remove_wait_queue(&sem->wait, &wait);
+- tsk->state = TASK_RUNNING;
+- wake_up(&sem->wait);
+-
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+- printk("%s(%d): down %s(%p)\n",
+- current->comm, task_pid_nr(current),
+- (ret < 0 ? "interrupted" : "acquired"), sem);
+-#endif
+- return ret;
+-}
+-
+-void
+-__up_wakeup(struct semaphore *sem)
+-{
+- /*
+- * Note that we incremented count in up() before we came here,
+- * but that was ineffective since the result was <= 0, and
+- * any negative value of count is equivalent to 0.
+- * This ends up setting count to 1, unless count is now > 0
+- * (i.e. because some other cpu has called up() in the meantime),
+- * in which case we just increment count.
+- */
+- __sem_update_count(sem, 1);
+- wake_up(&sem->wait);
+-}
+-
+-void __sched
+-down(struct semaphore *sem)
+-{
+-#ifdef WAITQUEUE_DEBUG
+- CHECK_MAGIC(sem->__magic);
+-#endif
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+- printk("%s(%d): down(%p) <count=%d> from %p\n",
+- current->comm, task_pid_nr(current), sem,
+- atomic_read(&sem->count), __builtin_return_address(0));
+-#endif
+- __down(sem);
+-}
+-
+-int __sched
+-down_interruptible(struct semaphore *sem)
+-{
+-#ifdef WAITQUEUE_DEBUG
+- CHECK_MAGIC(sem->__magic);
+-#endif
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+- printk("%s(%d): down(%p) <count=%d> from %p\n",
+- current->comm, task_pid_nr(current), sem,
+- atomic_read(&sem->count), __builtin_return_address(0));
+-#endif
+- return __down_interruptible(sem);
+-}
+-
+-int
+-down_trylock(struct semaphore *sem)
+-{
+- int ret;
+-
+-#ifdef WAITQUEUE_DEBUG
+- CHECK_MAGIC(sem->__magic);
+-#endif
+-
+- ret = __down_trylock(sem);
+-
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+- printk("%s(%d): down_trylock %s from %p\n",
+- current->comm, task_pid_nr(current),
+- ret ? "failed" : "acquired",
+- __builtin_return_address(0));
+-#endif
+-
+- return ret;
+-}
+-
+-void
+-up(struct semaphore *sem)
+-{
+-#ifdef WAITQUEUE_DEBUG
+- CHECK_MAGIC(sem->__magic);
+-#endif
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+- printk("%s(%d): up(%p) <count=%d> from %p\n",
+- current->comm, task_pid_nr(current), sem,
+- atomic_read(&sem->count), __builtin_return_address(0));
+-#endif
+- __up(sem);
+-}
+diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
+index 920196b..a7f23b5 100644
+--- a/arch/alpha/kernel/sys_nautilus.c
++++ b/arch/alpha/kernel/sys_nautilus.c
+@@ -187,6 +187,7 @@ nautilus_machine_check(unsigned long vector, unsigned long la_ptr)
+ }
+
+ extern void free_reserved_mem(void *, void *);
++extern void pcibios_claim_one_bus(struct pci_bus *);
+
+ static struct resource irongate_mem = {
+ .name = "Irongate PCI MEM",
+@@ -205,6 +206,7 @@ nautilus_init_pci(void)
+ /* Scan our single hose. */
+ bus = pci_scan_bus(0, alpha_mv.pci_ops, hose);
+ hose->bus = bus;
++ pcibios_claim_one_bus(bus);
+
+ irongate = pci_get_bus_and_slot(0, 0);
+ bus->self = irongate;
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index 4039a13..d8d2532 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -255,6 +255,7 @@ config ARCH_EP93XX
+ select ARM_AMBA
+ select ARM_VIC
+ select GENERIC_GPIO
++ select HAVE_GPIO_LIB
+ help
+ This enables support for the Cirrus EP93xx series of CPUs.
+
+@@ -377,15 +378,17 @@ config ARCH_MXC
+ help
+ Support for Freescale MXC/iMX-based family of processors
+
+-config ARCH_ORION
++config ARCH_ORION5X
+ bool "Marvell Orion"
+ depends on MMU
+ select PCI
+ select GENERIC_GPIO
+ select GENERIC_TIME
+ select GENERIC_CLOCKEVENTS
++ select PLAT_ORION
+ help
+- Support for Marvell Orion System on Chip family.
++ Support for the following Marvell Orion 5x series SoCs:
++ Orion-1 (5181), Orion-NAS (5182), Orion-2 (5281.)
+
+ config ARCH_PNX4008
+ bool "Philips Nexperia PNX4008 Mobile"
+@@ -422,10 +425,15 @@ config ARCH_SA1100
+ bool "SA1100-based"
+ select ISA
+ select ARCH_DISCONTIGMEM_ENABLE
++ select ARCH_SPARSEMEM_ENABLE
++ select ARCH_SELECT_MEMORY_MODEL
+ select ARCH_MTD_XIP
+ select GENERIC_GPIO
+ select GENERIC_TIME
++ select GENERIC_CLOCKEVENTS
++ select TICK_ONESHOT
+ select HAVE_IDE
++ select HAVE_GPIO_LIB
+ help
+ Support for StrongARM 11x0 based boards.
+
+@@ -468,6 +476,7 @@ config ARCH_DAVINCI
+ config ARCH_OMAP
+ bool "TI OMAP"
+ select GENERIC_GPIO
++ select HAVE_GPIO_LIB
+ select GENERIC_TIME
+ select GENERIC_CLOCKEVENTS
+ help
+@@ -516,7 +525,7 @@ source "arch/arm/mach-omap1/Kconfig"
+
+ source "arch/arm/mach-omap2/Kconfig"
+
+-source "arch/arm/mach-orion/Kconfig"
++source "arch/arm/mach-orion5x/Kconfig"
+
+ source "arch/arm/plat-s3c24xx/Kconfig"
+ source "arch/arm/plat-s3c/Kconfig"
+@@ -563,6 +572,9 @@ config ARCH_ACORN
+ config PLAT_IOP
+ bool
+
++config PLAT_ORION
++ bool
++
+ source arch/arm/mm/Kconfig
+
+ config IWMMXT
+@@ -650,7 +662,7 @@ source "kernel/time/Kconfig"
+
+ config SMP
+ bool "Symmetric Multi-Processing (EXPERIMENTAL)"
+- depends on EXPERIMENTAL && REALVIEW_EB_ARM11MP
++ depends on EXPERIMENTAL && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP)
+ help
+ This enables support for systems with more than one CPU. If you have
+ a system with only one CPU, like most personal computers, say N. If
+@@ -683,7 +695,7 @@ config HOTPLUG_CPU
+
+ config LOCAL_TIMERS
+ bool "Use local timer interrupts"
+- depends on SMP && REALVIEW_EB_ARM11MP
++ depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP)
+ default y
+ help
+ Enable support for local timers on SMP platforms, rather then the
+@@ -774,6 +786,12 @@ config ARCH_DISCONTIGMEM_ENABLE
+ or have huge holes in the physical address space for other reasons.
+ See <file:Documentation/vm/numa> for more.
+
++config ARCH_SPARSEMEM_ENABLE
++ bool
++
++config ARCH_SELECT_MEMORY_MODEL
++ bool
++
+ config NODES_SHIFT
+ int
+ default "4" if ARCH_LH7A40X
+@@ -1174,6 +1192,8 @@ source "drivers/dma/Kconfig"
+
+ source "drivers/dca/Kconfig"
+
++source "drivers/uio/Kconfig"
++
+ endmenu
+
+ source "fs/Kconfig"
+diff --git a/arch/arm/Makefile b/arch/arm/Makefile
+index 1a46496..e72db27 100644
+--- a/arch/arm/Makefile
++++ b/arch/arm/Makefile
+@@ -134,12 +134,11 @@ endif
+ machine-$(CONFIG_ARCH_PNX4008) := pnx4008
+ machine-$(CONFIG_ARCH_NETX) := netx
+ machine-$(CONFIG_ARCH_NS9XXX) := ns9xxx
+- textofs-$(CONFIG_ARCH_NS9XXX) := 0x00108000
+ machine-$(CONFIG_ARCH_DAVINCI) := davinci
+ machine-$(CONFIG_ARCH_KS8695) := ks8695
+ incdir-$(CONFIG_ARCH_MXC) := mxc
+ machine-$(CONFIG_ARCH_MX3) := mx3
+- machine-$(CONFIG_ARCH_ORION) := orion
++ machine-$(CONFIG_ARCH_ORION5X) := orion5x
+ machine-$(CONFIG_ARCH_MSM7X00A) := msm
+
+ ifeq ($(CONFIG_ARCH_EBSA110),y)
+@@ -185,6 +184,7 @@ core-$(CONFIG_VFP) += arch/arm/vfp/
+
+ # If we have a common platform directory, then include it in the build.
+ core-$(CONFIG_PLAT_IOP) += arch/arm/plat-iop/
++core-$(CONFIG_PLAT_ORION) += arch/arm/plat-orion/
+ core-$(CONFIG_ARCH_OMAP) += arch/arm/plat-omap/
+ core-$(CONFIG_PLAT_S3C24XX) += arch/arm/plat-s3c24xx/
+ core-$(CONFIG_ARCH_MXC) += arch/arm/plat-mxc/
+diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
+index 25f1230..da226ab 100644
+--- a/arch/arm/boot/Makefile
++++ b/arch/arm/boot/Makefile
+@@ -61,9 +61,15 @@ endif
+
+ quiet_cmd_uimage = UIMAGE $@
+ cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \
+- -C none -a $(ZRELADDR) -e $(ZRELADDR) \
++ -C none -a $(LOADADDR) -e $(LOADADDR) \
+ -n 'Linux-$(KERNELRELEASE)' -d $< $@
+
++ifeq ($(CONFIG_ZBOOT_ROM),y)
++$(obj)/uImage: LOADADDR=$(CONFIG_ZBOOT_ROM_TEXT)
++else
++$(obj)/uImage: LOADADDR=$(ZRELADDR)
++endif
++
+ $(obj)/uImage: $(obj)/zImage FORCE
+ $(call if_changed,uimage)
+ @echo ' Image $@ is ready'
+diff --git a/arch/arm/common/rtctime.c b/arch/arm/common/rtctime.c
+index f53bca4..aa8f773 100644
+--- a/arch/arm/common/rtctime.c
++++ b/arch/arm/common/rtctime.c
+@@ -22,7 +22,6 @@
+ #include <linux/mutex.h>
+
+ #include <asm/rtc.h>
+-#include <asm/semaphore.h>
+
+ static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
+ static struct fasync_struct *rtc_async_queue;
+diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
+index 314ebd3..bc299b0 100644
+--- a/arch/arm/common/scoop.c
++++ b/arch/arm/common/scoop.c
+@@ -16,6 +16,7 @@
+ #include <linux/slab.h>
+ #include <linux/platform_device.h>
+ #include <asm/io.h>
++#include <asm/gpio.h>
+ #include <asm/hardware/scoop.h>
+
+ /* PCMCIA to Scoop linkage
+@@ -30,10 +31,9 @@
+ struct scoop_pcmcia_config *platform_scoop_config;
+ EXPORT_SYMBOL(platform_scoop_config);
+
+-#define SCOOP_REG(d,adr) (*(volatile unsigned short*)(d +(adr)))
+-
+ struct scoop_dev {
+- void *base;
++ void __iomem *base;
++ struct gpio_chip gpio;
+ spinlock_t scoop_lock;
+ unsigned short suspend_clr;
+ unsigned short suspend_set;
+@@ -44,13 +44,84 @@ void reset_scoop(struct device *dev)
+ {
+ struct scoop_dev *sdev = dev_get_drvdata(dev);
+
+- SCOOP_REG(sdev->base,SCOOP_MCR) = 0x0100; // 00
+- SCOOP_REG(sdev->base,SCOOP_CDR) = 0x0000; // 04
+- SCOOP_REG(sdev->base,SCOOP_CCR) = 0x0000; // 10
+- SCOOP_REG(sdev->base,SCOOP_IMR) = 0x0000; // 18
+- SCOOP_REG(sdev->base,SCOOP_IRM) = 0x00FF; // 14
+- SCOOP_REG(sdev->base,SCOOP_ISR) = 0x0000; // 1C
+- SCOOP_REG(sdev->base,SCOOP_IRM) = 0x0000;
++ iowrite16(0x0100, sdev->base + SCOOP_MCR); // 00
++ iowrite16(0x0000, sdev->base + SCOOP_CDR); // 04
++ iowrite16(0x0000, sdev->base + SCOOP_CCR); // 10
++ iowrite16(0x0000, sdev->base + SCOOP_IMR); // 18
++ iowrite16(0x00FF, sdev->base + SCOOP_IRM); // 14
++ iowrite16(0x0000, sdev->base + SCOOP_ISR); // 1C
++ iowrite16(0x0000, sdev->base + SCOOP_IRM);
++}
++
++static void __scoop_gpio_set(struct scoop_dev *sdev,
++ unsigned offset, int value)
++{
++ unsigned short gpwr;
++
++ gpwr = ioread16(sdev->base + SCOOP_GPWR);
++ if (value)
++ gpwr |= 1 << (offset + 1);
++ else
++ gpwr &= ~(1 << (offset + 1));
++ iowrite16(gpwr, sdev->base + SCOOP_GPWR);
++}
++
++static void scoop_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
++{
++ struct scoop_dev *sdev = container_of(chip, struct scoop_dev, gpio);
++ unsigned long flags;
++
++ spin_lock_irqsave(&sdev->scoop_lock, flags);
++
++ __scoop_gpio_set(sdev, offset, value);
++
++ spin_unlock_irqrestore(&sdev->scoop_lock, flags);
++}
++
++static int scoop_gpio_get(struct gpio_chip *chip, unsigned offset)
++{
++ struct scoop_dev *sdev = container_of(chip, struct scoop_dev, gpio);
++
++ /* XXX: I'm usure, but it seems so */
++ return ioread16(sdev->base + SCOOP_GPRR) & (1 << (offset + 1));
++}
++
++static int scoop_gpio_direction_input(struct gpio_chip *chip,
++ unsigned offset)
++{
++ struct scoop_dev *sdev = container_of(chip, struct scoop_dev, gpio);
++ unsigned long flags;
++ unsigned short gpcr;
++
++ spin_lock_irqsave(&sdev->scoop_lock, flags);
++
++ gpcr = ioread16(sdev->base + SCOOP_GPCR);
++ gpcr &= ~(1 << (offset + 1));
++ iowrite16(gpcr, sdev->base + SCOOP_GPCR);
++
++ spin_unlock_irqrestore(&sdev->scoop_lock, flags);
++
++ return 0;
++}
++
++static int scoop_gpio_direction_output(struct gpio_chip *chip,
++ unsigned offset, int value)
++{
++ struct scoop_dev *sdev = container_of(chip, struct scoop_dev, gpio);
++ unsigned long flags;
++ unsigned short gpcr;
++
++ spin_lock_irqsave(&sdev->scoop_lock, flags);
++
++ __scoop_gpio_set(sdev, offset, value);
++
++ gpcr = ioread16(sdev->base + SCOOP_GPCR);
++ gpcr |= 1 << (offset + 1);
++ iowrite16(gpcr, sdev->base + SCOOP_GPCR);
++
++ spin_unlock_irqrestore(&sdev->scoop_lock, flags);
++
++ return 0;
+ }
+
+ unsigned short set_scoop_gpio(struct device *dev, unsigned short bit)
+@@ -60,8 +131,8 @@ unsigned short set_scoop_gpio(struct device *dev, unsigned short bit)
+ struct scoop_dev *sdev = dev_get_drvdata(dev);
+
+ spin_lock_irqsave(&sdev->scoop_lock, flag);
+- gpio_bit = SCOOP_REG(sdev->base, SCOOP_GPWR) | bit;
+- SCOOP_REG(sdev->base, SCOOP_GPWR) = gpio_bit;
++ gpio_bit = ioread16(sdev->base + SCOOP_GPWR) | bit;
++ iowrite16(gpio_bit, sdev->base + SCOOP_GPWR);
+ spin_unlock_irqrestore(&sdev->scoop_lock, flag);
+
+ return gpio_bit;
+@@ -74,8 +145,8 @@ unsigned short reset_scoop_gpio(struct device *dev, unsigned short bit)
+ struct scoop_dev *sdev = dev_get_drvdata(dev);
+
+ spin_lock_irqsave(&sdev->scoop_lock, flag);
+- gpio_bit = SCOOP_REG(sdev->base, SCOOP_GPWR) & ~bit;
+- SCOOP_REG(sdev->base,SCOOP_GPWR) = gpio_bit;
++ gpio_bit = ioread16(sdev->base + SCOOP_GPWR) & ~bit;
++ iowrite16(gpio_bit, sdev->base + SCOOP_GPWR);
+ spin_unlock_irqrestore(&sdev->scoop_lock, flag);
+
+ return gpio_bit;
+@@ -87,13 +158,13 @@ EXPORT_SYMBOL(reset_scoop_gpio);
+ unsigned short read_scoop_reg(struct device *dev, unsigned short reg)
+ {
+ struct scoop_dev *sdev = dev_get_drvdata(dev);
+- return SCOOP_REG(sdev->base,reg);
++ return ioread16(sdev->base + reg);
+ }
+
+ void write_scoop_reg(struct device *dev, unsigned short reg, unsigned short data)
+ {
+ struct scoop_dev *sdev = dev_get_drvdata(dev);
+- SCOOP_REG(sdev->base,reg)=data;
++ iowrite16(data, sdev->base + reg);
+ }
+
+ EXPORT_SYMBOL(reset_scoop);
+@@ -104,9 +175,9 @@ static void check_scoop_reg(struct scoop_dev *sdev)
+ {
+ unsigned short mcr;
+
+- mcr = SCOOP_REG(sdev->base, SCOOP_MCR);
++ mcr = ioread16(sdev->base + SCOOP_MCR);
+ if ((mcr & 0x100) == 0)
+- SCOOP_REG(sdev->base, SCOOP_MCR) = 0x0101;
++ iowrite16(0x0101, sdev->base + SCOOP_MCR);
+ }
+
+ #ifdef CONFIG_PM
+@@ -115,8 +186,8 @@ static int scoop_suspend(struct platform_device *dev, pm_message_t state)
+ struct scoop_dev *sdev = platform_get_drvdata(dev);
+
+ check_scoop_reg(sdev);
+- sdev->scoop_gpwr = SCOOP_REG(sdev->base, SCOOP_GPWR);
+- SCOOP_REG(sdev->base, SCOOP_GPWR) = (sdev->scoop_gpwr & ~sdev->suspend_clr) | sdev->suspend_set;
++ sdev->scoop_gpwr = ioread16(sdev->base + SCOOP_GPWR);
++ iowrite16((sdev->scoop_gpwr & ~sdev->suspend_clr) | sdev->suspend_set, sdev->base + SCOOP_GPWR);
+
+ return 0;
+ }
+@@ -126,7 +197,7 @@ static int scoop_resume(struct platform_device *dev)
+ struct scoop_dev *sdev = platform_get_drvdata(dev);
+
+ check_scoop_reg(sdev);
+- SCOOP_REG(sdev->base,SCOOP_GPWR) = sdev->scoop_gpwr;
++ iowrite16(sdev->scoop_gpwr, sdev->base + SCOOP_GPWR);
+
+ return 0;
+ }
+@@ -135,11 +206,13 @@ static int scoop_resume(struct platform_device *dev)
+ #define scoop_resume NULL
+ #endif
+
+-int __init scoop_probe(struct platform_device *pdev)
++static int __devinit scoop_probe(struct platform_device *pdev)
+ {
+ struct scoop_dev *devptr;
+ struct scoop_config *inf;
+ struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ int ret;
++ int temp;
+
+ if (!mem)
+ return -EINVAL;
+@@ -154,40 +227,78 @@ int __init scoop_probe(struct platform_device *pdev)
+ devptr->base = ioremap(mem->start, mem->end - mem->start + 1);
+
+ if (!devptr->base) {
+- kfree(devptr);
+- return -ENOMEM;
++ ret = -ENOMEM;
++ goto err_ioremap;
+ }
+
+ platform_set_drvdata(pdev, devptr);
+
+- printk("Sharp Scoop Device found at 0x%08x -> 0x%08x\n",(unsigned int)mem->start,(unsigned int)devptr->base);
++ printk("Sharp Scoop Device found at 0x%08x -> 0x%8p\n",(unsigned int)mem->start, devptr->base);
+
+- SCOOP_REG(devptr->base, SCOOP_MCR) = 0x0140;
++ iowrite16(0x0140, devptr->base + SCOOP_MCR);
+ reset_scoop(&pdev->dev);
+- SCOOP_REG(devptr->base, SCOOP_CPR) = 0x0000;
+- SCOOP_REG(devptr->base, SCOOP_GPCR) = inf->io_dir & 0xffff;
+- SCOOP_REG(devptr->base, SCOOP_GPWR) = inf->io_out & 0xffff;
++ iowrite16(0x0000, devptr->base + SCOOP_CPR);
++ iowrite16(inf->io_dir & 0xffff, devptr->base + SCOOP_GPCR);
++ iowrite16(inf->io_out & 0xffff, devptr->base + SCOOP_GPWR);
+
+ devptr->suspend_clr = inf->suspend_clr;
+ devptr->suspend_set = inf->suspend_set;
+
++ devptr->gpio.base = -1;
++
++ if (inf->gpio_base != 0) {
++ devptr->gpio.label = pdev->dev.bus_id;
++ devptr->gpio.base = inf->gpio_base;
++ devptr->gpio.ngpio = 12; /* PA11 = 0, PA12 = 1, etc. up to PA22 = 11 */
++ devptr->gpio.set = scoop_gpio_set;
++ devptr->gpio.get = scoop_gpio_get;
++ devptr->gpio.direction_input = scoop_gpio_direction_input;
++ devptr->gpio.direction_output = scoop_gpio_direction_output;
++
++ ret = gpiochip_add(&devptr->gpio);
++ if (ret)
++ goto err_gpio;
++ }
++
+ return 0;
++
++ if (devptr->gpio.base != -1)
++ temp = gpiochip_remove(&devptr->gpio);
++err_gpio:
++ platform_set_drvdata(pdev, NULL);
++err_ioremap:
++ iounmap(devptr->base);
++ kfree(devptr);
++
++ return ret;
+ }
+
+-static int scoop_remove(struct platform_device *pdev)
++static int __devexit scoop_remove(struct platform_device *pdev)
+ {
+ struct scoop_dev *sdev = platform_get_drvdata(pdev);
+- if (sdev) {
+- iounmap(sdev->base);
+- kfree(sdev);
+- platform_set_drvdata(pdev, NULL);
++ int ret;
++
++ if (!sdev)
++ return -EINVAL;
++
++ if (sdev->gpio.base != -1) {
++ ret = gpiochip_remove(&sdev->gpio);
++ if (ret) {
++ dev_err(&pdev->dev, "Can't remove gpio chip: %d\n", ret);
++ return ret;
++ }
+ }
++
++ platform_set_drvdata(pdev, NULL);
++ iounmap(sdev->base);
++ kfree(sdev);
++
+ return 0;
+ }
+
+ static struct platform_driver scoop_driver = {
+ .probe = scoop_probe,
+- .remove = scoop_remove,
++ .remove = __devexit_p(scoop_remove),
+ .suspend = scoop_suspend,
+ .resume = scoop_resume,
+ .driver = {
+@@ -195,7 +306,7 @@ static struct platform_driver scoop_driver = {
+ },
+ };
+
+-int __init scoop_init(void)
++static int __init scoop_init(void)
+ {
+ return platform_driver_register(&scoop_driver);
+ }
+diff --git a/arch/arm/configs/am200epdkit_defconfig b/arch/arm/configs/am200epdkit_defconfig
+new file mode 100644
+index 0000000..dc030cf
+--- /dev/null
++++ b/arch/arm/configs/am200epdkit_defconfig
+@@ -0,0 +1,1149 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc3
++# Sun Mar 9 06:33:33 2008
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ARCH_SUPPORTS_AOUT=y
++CONFIG_ZONE_DMA=y
++CONFIG_ARCH_MTD_XIP=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_LOCK_KERNEL=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION="gum"
++CONFIG_LOCALVERSION_AUTO=y
++# CONFIG_SWAP is not set
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=17
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++# CONFIG_SYSFS_DEPRECATED is not set
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++# CONFIG_BLK_DEV_INITRD is not set
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_UID16=y
++# CONFIG_SYSCTL_SYSCALL is not set
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++# CONFIG_SHMEM is not set
++# CONFIG_VM_EVENT_COUNTERS is not set
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++CONFIG_TINY_SHMEM=y
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++# CONFIG_IOSCHED_DEADLINE is not set
++# CONFIG_IOSCHED_CFQ is not set
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++CONFIG_DEFAULT_NOOP=y
++CONFIG_DEFAULT_IOSCHED="noop"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++
++#
++# System Type
++#
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_ORION is not set
++# CONFIG_ARCH_PNX4008 is not set
++CONFIG_ARCH_PXA=y
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_MSM7X00A is not set
++
++#
++# Intel PXA2xx/PXA3xx Implementations
++#
++CONFIG_ARCH_GUMSTIX=y
++# CONFIG_ARCH_LUBBOCK is not set
++# CONFIG_MACH_LOGICPD_PXA270 is not set
++# CONFIG_MACH_MAINSTONE is not set
++# CONFIG_ARCH_PXA_IDP is not set
++# CONFIG_PXA_SHARPSL is not set
++# CONFIG_ARCH_PXA_ESERIES is not set
++# CONFIG_MACH_TRIZEPS4 is not set
++# CONFIG_MACH_EM_X270 is not set
++# CONFIG_MACH_COLIBRI is not set
++# CONFIG_MACH_ZYLONITE is not set
++# CONFIG_MACH_LITTLETON is not set
++# CONFIG_MACH_ARMCORE is not set
++# CONFIG_MACH_MAGICIAN is not set
++# CONFIG_MACH_PCM027 is not set
++CONFIG_MACH_GUMSTIX_F=y
++CONFIG_PXA25x=y
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_XSCALE=y
++CONFIG_CPU_32v5=y
++CONFIG_CPU_ABRT_EV5T=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_OUTER_CACHE is not set
++# CONFIG_IWMMXT is not set
++CONFIG_XSCALE_PMU=y
++
++#
++# Bus support
++#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++CONFIG_PCCARD=y
++# CONFIG_PCMCIA_DEBUG is not set
++CONFIG_PCMCIA=y
++CONFIG_PCMCIA_LOAD_CIS=y
++# CONFIG_PCMCIA_IOCTL is not set
++
++#
++# PC-card bridges
++#
++CONFIG_PCMCIA_PXA2XX=y
++
++#
++# Kernel Features
++#
++CONFIG_TICK_ONESHOT=y
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++CONFIG_PREEMPT=y
++CONFIG_HZ=100
++CONFIG_AEABI=y
++# CONFIG_OABI_COMPAT is not set
++# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="console=ttyS0,115200n8 root=1f01 rootfstype=jffs2"
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++
++#
++# CPU Frequency scaling
++#
++# CONFIG_CPU_FREQ is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=m
++CONFIG_PACKET_MMAP=y
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++# CONFIG_IP_PNP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++# CONFIG_INET_DIAG is not set
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++CONFIG_BT=m
++CONFIG_BT_L2CAP=m
++CONFIG_BT_SCO=m
++CONFIG_BT_RFCOMM=m
++CONFIG_BT_RFCOMM_TTY=y
++CONFIG_BT_BNEP=m
++# CONFIG_BT_BNEP_MC_FILTER is not set
++# CONFIG_BT_BNEP_PROTO_FILTER is not set
++# CONFIG_BT_HIDP is not set
++
++#
++# Bluetooth device drivers
++#
++# CONFIG_BT_HCIBTSDIO is not set
++CONFIG_BT_HCIUART=m
++CONFIG_BT_HCIUART_H4=y
++# CONFIG_BT_HCIUART_BCSP is not set
++# CONFIG_BT_HCIUART_LL is not set
++# CONFIG_BT_HCIDTL1 is not set
++# CONFIG_BT_HCIBT3C is not set
++# CONFIG_BT_HCIBLUECARD is not set
++# CONFIG_BT_HCIBTUART is not set
++# CONFIG_BT_HCIVHCI is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++CONFIG_WIRELESS_EXT=y
++# CONFIG_MAC80211 is not set
++CONFIG_IEEE80211=m
++# CONFIG_IEEE80211_DEBUG is not set
++CONFIG_IEEE80211_CRYPT_WEP=m
++# CONFIG_IEEE80211_CRYPT_CCMP is not set
++# CONFIG_IEEE80211_CRYPT_TKIP is not set
++# CONFIG_IEEE80211_SOFTMAC is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++CONFIG_MTD_CFI_ADV_OPTIONS=y
++CONFIG_MTD_CFI_NOSWAP=y
++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
++CONFIG_MTD_CFI_GEOMETRY=y
++# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++# CONFIG_MTD_CFI_I2 is not set
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_OTP is not set
++CONFIG_MTD_CFI_INTELEXT=y
++# CONFIG_MTD_CFI_AMDSTD is not set
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++# CONFIG_MTD_XIP is not set
++
++#
++# Mapping drivers for chip access
++#
++CONFIG_MTD_COMPLEX_MAPPINGS=y
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PXA2XX=y
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_SHARP_SL is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=m
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_RAM is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++CONFIG_IDE=m
++CONFIG_IDE_MAX_HWIFS=2
++CONFIG_BLK_DEV_IDE=m
++
++#
++# Please see Documentation/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_IDE_SATA is not set
++CONFIG_BLK_DEV_IDEDISK=m
++# CONFIG_IDEDISK_MULTI_MODE is not set
++CONFIG_BLK_DEV_IDECS=m
++# CONFIG_BLK_DEV_IDECD is not set
++# CONFIG_BLK_DEV_IDETAPE is not set
++# CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_IDE_TASK_IOCTL is not set
++CONFIG_IDE_PROC_FS=y
++
++#
++# IDE chipset support/bugfixes
++#
++CONFIG_IDE_GENERIC=m
++# CONFIG_BLK_DEV_PLATFORM is not set
++# CONFIG_BLK_DEV_IDEDMA is not set
++CONFIG_IDE_ARCH_OBSOLETE_INIT=y
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=m
++# CONFIG_AX88796 is not set
++CONFIG_SMC91X=m
++# CONFIG_DM9000 is not set
++# CONFIG_SMC911X is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_E1000E_ENABLED is not set
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_NET_PCMCIA is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++CONFIG_KEYBOARD_ATKBD=y
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++# CONFIG_KEYBOARD_GPIO is not set
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_PS2_ALPS=y
++CONFIG_MOUSE_PS2_LOGIPS2PP=y
++CONFIG_MOUSE_PS2_SYNAPTICS=y
++CONFIG_MOUSE_PS2_LIFEBOOK=y
++CONFIG_MOUSE_PS2_TRACKPOINT=y
++# CONFIG_MOUSE_PS2_TOUCHKIT is not set
++# CONFIG_MOUSE_SERIAL is not set
++# CONFIG_MOUSE_APPLETOUCH is not set
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_MOUSE_GPIO is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_PXA=y
++CONFIG_SERIAL_PXA_CONSOLE=y
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++# CONFIG_LEGACY_PTYS is not set
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_R3964 is not set
++
++#
++# PCMCIA character devices
++#
++# CONFIG_SYNCLINK_CS is not set
++# CONFIG_CARDMAN_4000 is not set
++# CONFIG_CARDMAN_4040 is not set
++# CONFIG_IPWIRELESS is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++CONFIG_HAVE_GPIO_LIB=y
++
++#
++# GPIO Support
++#
++# CONFIG_DEBUG_GPIO is not set
++
++#
++# I2C GPIO expanders:
++#
++
++#
++# SPI GPIO expanders:
++#
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_SA1100_WATCHDOG=m
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++# CONFIG_MFD_ASIC3 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++CONFIG_FB=y
++# CONFIG_FIRMWARE_EDID is not set
++# CONFIG_FB_DDC is not set
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
++CONFIG_FB_SYS_FILLRECT=m
++CONFIG_FB_SYS_COPYAREA=m
++CONFIG_FB_SYS_IMAGEBLIT=m
++CONFIG_FB_SYS_FOPS=m
++CONFIG_FB_DEFERRED_IO=y
++# CONFIG_FB_SVGALIB is not set
++# CONFIG_FB_MACMODES is not set
++# CONFIG_FB_BACKLIGHT is not set
++CONFIG_FB_MODE_HELPERS=y
++CONFIG_FB_TILEBLITTING=y
++
++#
++# Frame buffer hardware drivers
++#
++# CONFIG_FB_S1D13XXX is not set
++CONFIG_FB_PXA=y
++CONFIG_FB_PXA_PARAMETERS=y
++CONFIG_FB_MBX=m
++CONFIG_FB_VIRTUAL=m
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++# CONFIG_FRAMEBUFFER_CONSOLE is not set
++# CONFIG_LOGO is not set
++
++#
++# Sound
++#
++CONFIG_SOUND=m
++
++#
++# Advanced Linux Sound Architecture
++#
++CONFIG_SND=m
++CONFIG_SND_TIMER=m
++CONFIG_SND_PCM=m
++# CONFIG_SND_SEQUENCER is not set
++CONFIG_SND_OSSEMUL=y
++CONFIG_SND_MIXER_OSS=m
++CONFIG_SND_PCM_OSS=m
++CONFIG_SND_PCM_OSS_PLUGINS=y
++# CONFIG_SND_DYNAMIC_MINORS is not set
++# CONFIG_SND_SUPPORT_OLD_API is not set
++# CONFIG_SND_VERBOSE_PROCFS is not set
++# CONFIG_SND_VERBOSE_PRINTK is not set
++# CONFIG_SND_DEBUG is not set
++
++#
++# Generic devices
++#
++CONFIG_SND_AC97_CODEC=m
++# CONFIG_SND_DUMMY is not set
++# CONFIG_SND_MTPAV is not set
++# CONFIG_SND_SERIAL_U16550 is not set
++# CONFIG_SND_MPU401 is not set
++
++#
++# ALSA ARM devices
++#
++CONFIG_SND_PXA2XX_PCM=m
++CONFIG_SND_PXA2XX_AC97=m
++
++#
++# PCMCIA devices
++#
++# CONFIG_SND_VXPOCKET is not set
++# CONFIG_SND_PDAUDIOCF is not set
++
++#
++# System on Chip audio support
++#
++# CONFIG_SND_SOC is not set
++
++#
++# SoC Audio support for SuperH
++#
++
++#
++# ALSA SoC audio for Freescale SOCs
++#
++
++#
++# Open Sound System
++#
++# CONFIG_SOUND_PRIME is not set
++CONFIG_AC97_BUS=m
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG is not set
++# CONFIG_USB_GADGET_DEBUG_FILES is not set
++CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_ATMEL_USBA is not set
++# CONFIG_USB_GADGET_FSL_USB2 is not set
++# CONFIG_USB_GADGET_NET2280 is not set
++CONFIG_USB_GADGET_PXA2XX=y
++CONFIG_USB_PXA2XX=y
++# CONFIG_USB_PXA2XX_SMALL is not set
++# CONFIG_USB_GADGET_M66592 is not set
++# CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_LH7A40X is not set
++# CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_S3C2410 is not set
++# CONFIG_USB_GADGET_AT91 is not set
++# CONFIG_USB_GADGET_DUMMY_HCD is not set
++# CONFIG_USB_GADGET_DUALSPEED is not set
++# CONFIG_USB_ZERO is not set
++CONFIG_USB_ETH=y
++CONFIG_USB_ETH_RNDIS=y
++# CONFIG_USB_GADGETFS is not set
++# CONFIG_USB_FILE_STORAGE is not set
++# CONFIG_USB_G_SERIAL is not set
++# CONFIG_USB_MIDI_GADGET is not set
++# CONFIG_USB_G_PRINTER is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
++
++#
++# MMC/SD Host Controller Drivers
++#
++CONFIG_MMC_PXA=y
++# CONFIG_NEW_LEDS is not set
++CONFIG_RTC_LIB=y
++# CONFIG_RTC_CLASS is not set
++
++#
++# File systems
++#
++# CONFIG_EXT2_FS is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_DNOTIFY is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++# CONFIG_MSDOS_FS is not set
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++CONFIG_JFFS2_COMPRESSION_OPTIONS=y
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++CONFIG_JFFS2_RUBIN=y
++# CONFIG_JFFS2_CMODE_NONE is not set
++CONFIG_JFFS2_CMODE_PRIORITY=y
++# CONFIG_JFFS2_CMODE_SIZE is not set
++# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++# CONFIG_NFS_FS is not set
++# CONFIG_NFSD is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++# CONFIG_DLM is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++# CONFIG_DETECT_SOFTLOCKUP is not set
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_PREEMPT is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++CONFIG_DEBUG_USER=y
++CONFIG_DEBUG_ERRORS=y
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_LL is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=m
++CONFIG_CRYPTO_BLKCIPHER=m
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=m
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=m
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++CONFIG_CRYPTO_ARC4=m
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/at91rm9200dk_defconfig b/arch/arm/configs/at91rm9200dk_defconfig
+index e10d003..2dbbbc3 100644
+--- a/arch/arm/configs/at91rm9200dk_defconfig
++++ b/arch/arm/configs/at91rm9200dk_defconfig
+@@ -620,14 +620,14 @@ CONFIG_I2C_CHARDEV=y
+ #
+ # I2C Algorithms
+ #
+-# CONFIG_I2C_ALGOBIT is not set
++CONFIG_I2C_ALGOBIT=y
+ # CONFIG_I2C_ALGOPCF is not set
+ # CONFIG_I2C_ALGOPCA is not set
+
+ #
+ # I2C Hardware Bus support
+ #
+-CONFIG_I2C_AT91=y
++CONFIG_I2C_GPIO=y
+ # CONFIG_I2C_PARPORT_LIGHT is not set
+ # CONFIG_I2C_STUB is not set
+ # CONFIG_I2C_PCA_ISA is not set
+diff --git a/arch/arm/configs/at91rm9200ek_defconfig b/arch/arm/configs/at91rm9200ek_defconfig
+index 834dddb..6e994f7 100644
+--- a/arch/arm/configs/at91rm9200ek_defconfig
++++ b/arch/arm/configs/at91rm9200ek_defconfig
+@@ -594,14 +594,14 @@ CONFIG_I2C_CHARDEV=y
+ #
+ # I2C Algorithms
+ #
+-# CONFIG_I2C_ALGOBIT is not set
++CONFIG_I2C_ALGOBIT=y
+ # CONFIG_I2C_ALGOPCF is not set
+ # CONFIG_I2C_ALGOPCA is not set
+
+ #
+ # I2C Hardware Bus support
+ #
+-CONFIG_I2C_AT91=y
++CONFIG_I2C_GPIO=y
+ # CONFIG_I2C_PARPORT_LIGHT is not set
+ # CONFIG_I2C_STUB is not set
+ # CONFIG_I2C_PCA_ISA is not set
+diff --git a/arch/arm/configs/at91sam9260ek_defconfig b/arch/arm/configs/at91sam9260ek_defconfig
+index 46b0c73..f659c93 100644
+--- a/arch/arm/configs/at91sam9260ek_defconfig
++++ b/arch/arm/configs/at91sam9260ek_defconfig
+@@ -1,43 +1,56 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.19-rc6
+-# Fri Nov 17 18:42:21 2006
++# Linux kernel version: 2.6.24-rc7
++# Tue Jan 8 22:20:50 2008
+ #
+ CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
+ # CONFIG_GENERIC_TIME is not set
++# CONFIG_GENERIC_CLOCKEVENTS is not set
+ CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
+ CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
+ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+ CONFIG_HARDIRQS_SW_RESEND=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+ CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ZONE_DMA=y
+ CONFIG_VECTORS_BASE=0xffff0000
+ CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+ #
+-# Code maturity level options
++# General setup
+ #
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_BROKEN_ON_SMP=y
+ CONFIG_INIT_ENV_ARG_LIMIT=32
+-
+-#
+-# General setup
+-#
+ CONFIG_LOCALVERSION=""
+ # CONFIG_LOCALVERSION_AUTO is not set
+ # CONFIG_SWAP is not set
+ CONFIG_SYSVIPC=y
+-# CONFIG_IPC_NS is not set
++CONFIG_SYSVIPC_SYSCTL=y
+ # CONFIG_POSIX_MQUEUE is not set
+ # CONFIG_BSD_PROCESS_ACCT is not set
+ # CONFIG_TASKSTATS is not set
+-# CONFIG_UTS_NS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
+ # CONFIG_AUDIT is not set
+ # CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
+ # CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
+ CONFIG_INITRAMFS_SOURCE=""
+ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+ CONFIG_SYSCTL=y
+@@ -53,30 +66,30 @@ CONFIG_BUG=y
+ CONFIG_ELF_CORE=y
+ CONFIG_BASE_FULL=y
+ CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
+ CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
+ CONFIG_SHMEM=y
+-CONFIG_SLAB=y
+ CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_SLABINFO=y
+ CONFIG_RT_MUTEXES=y
+ # CONFIG_TINY_SHMEM is not set
+ CONFIG_BASE_SMALL=0
+-# CONFIG_SLOB is not set
+-
+-#
+-# Loadable module support
+-#
+ CONFIG_MODULES=y
+ CONFIG_MODULE_UNLOAD=y
+ # CONFIG_MODULE_FORCE_UNLOAD is not set
+ # CONFIG_MODVERSIONS is not set
+ # CONFIG_MODULE_SRCVERSION_ALL is not set
+ CONFIG_KMOD=y
+-
+-#
+-# Block layer
+-#
+ CONFIG_BLOCK=y
++# CONFIG_LBD is not set
+ # CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
+
+ #
+ # IO Schedulers
+@@ -108,12 +121,16 @@ CONFIG_ARCH_AT91=y
+ # CONFIG_ARCH_NETX is not set
+ # CONFIG_ARCH_H720X is not set
+ # CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
+ # CONFIG_ARCH_IOP32X is not set
+ # CONFIG_ARCH_IOP33X is not set
+-# CONFIG_ARCH_IXP4XX is not set
+-# CONFIG_ARCH_IXP2000 is not set
+ # CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
+ # CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
+ # CONFIG_ARCH_PNX4008 is not set
+ # CONFIG_ARCH_PXA is not set
+ # CONFIG_ARCH_RPC is not set
+@@ -121,29 +138,52 @@ CONFIG_ARCH_AT91=y
+ # CONFIG_ARCH_S3C2410 is not set
+ # CONFIG_ARCH_SHARK is not set
+ # CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
+ # CONFIG_ARCH_OMAP is not set
+
+ #
++# Boot options
++#
++
++#
++# Power management
++#
++
++#
+ # Atmel AT91 System-on-Chip
+ #
+ # CONFIG_ARCH_AT91RM9200 is not set
+ CONFIG_ARCH_AT91SAM9260=y
+ # CONFIG_ARCH_AT91SAM9261 is not set
++# CONFIG_ARCH_AT91SAM9263 is not set
++# CONFIG_ARCH_AT91SAM9RL is not set
++# CONFIG_ARCH_AT91X40 is not set
++CONFIG_AT91_PMC_UNIT=y
++
++#
++# AT91SAM9260 Variants
++#
++# CONFIG_ARCH_AT91SAM9260_SAM9XE is not set
+
+ #
+-# AT91SAM9260 Board Type
++# AT91SAM9260 / AT91SAM9XE Board Type
+ #
+ CONFIG_MACH_AT91SAM9260EK=y
++# CONFIG_MACH_CAM60 is not set
++# CONFIG_MACH_SAM9_L9260 is not set
+
+ #
+ # AT91 Board Options
+ #
++# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
+ # CONFIG_MTD_NAND_AT91_BUSWIDTH_16 is not set
+
+ #
+ # AT91 Feature Selections
+ #
+-# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
++CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
++# CONFIG_ATMEL_TCLIB is not set
++CONFIG_AT91_TIMER_HZ=100
+
+ #
+ # Processor Type
+@@ -166,19 +206,19 @@ CONFIG_CPU_CP15_MMU=y
+ # CONFIG_CPU_DCACHE_DISABLE is not set
+ # CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+ # CONFIG_CPU_CACHE_ROUND_ROBIN is not set
++# CONFIG_OUTER_CACHE is not set
+
+ #
+ # Bus support
+ #
+-
+-#
+-# PCCARD (PCMCIA/CardBus) support
+-#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
+ # CONFIG_PCCARD is not set
+
+ #
+ # Kernel Features
+ #
++# CONFIG_TICK_ONESHOT is not set
+ # CONFIG_PREEMPT is not set
+ # CONFIG_NO_IDLE_HZ is not set
+ CONFIG_HZ=100
+@@ -191,8 +231,12 @@ CONFIG_FLATMEM_MANUAL=y
+ CONFIG_FLATMEM=y
+ CONFIG_FLAT_NODE_MEM_MAP=y
+ # CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+ CONFIG_SPLIT_PTLOCK_CPUS=4096
+ # CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
+ # CONFIG_LEDS is not set
+ CONFIG_ALIGNMENT_TRAP=y
+
+@@ -203,6 +247,7 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
+ CONFIG_ZBOOT_ROM_BSS=0x0
+ CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
+ # CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
+
+ #
+ # Floating point emulation
+@@ -228,7 +273,7 @@ CONFIG_BINFMT_ELF=y
+ # Power management options
+ #
+ # CONFIG_PM is not set
+-# CONFIG_APM is not set
++CONFIG_SUSPEND_UP_POSSIBLE=y
+
+ #
+ # Networking
+@@ -238,13 +283,9 @@ CONFIG_NET=y
+ #
+ # Networking options
+ #
+-# CONFIG_NETDEBUG is not set
+ CONFIG_PACKET=y
+ # CONFIG_PACKET_MMAP is not set
+ CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+ # CONFIG_NET_KEY is not set
+ CONFIG_INET=y
+ # CONFIG_IP_MULTICAST is not set
+@@ -263,33 +304,23 @@ CONFIG_IP_PNP_BOOTP=y
+ # CONFIG_INET_IPCOMP is not set
+ # CONFIG_INET_XFRM_TUNNEL is not set
+ # CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
+ CONFIG_INET_DIAG=y
+ CONFIG_INET_TCP_DIAG=y
+ # CONFIG_TCP_CONG_ADVANCED is not set
+ CONFIG_TCP_CONG_CUBIC=y
+ CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
+ # CONFIG_IPV6 is not set
+ # CONFIG_INET6_XFRM_TUNNEL is not set
+ # CONFIG_INET6_TUNNEL is not set
+ # CONFIG_NETWORK_SECMARK is not set
+ # CONFIG_NETFILTER is not set
+-
+-#
+-# DCCP Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_IP_DCCP is not set
+-
+-#
+-# SCTP Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_IP_SCTP is not set
+-
+-#
+-# TIPC Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_TIPC is not set
+ # CONFIG_ATM is not set
+ # CONFIG_BRIDGE is not set
+@@ -302,10 +333,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ # CONFIG_LAPB is not set
+ # CONFIG_ECONET is not set
+ # CONFIG_WAN_ROUTER is not set
+-
+-#
+-# QoS and/or fair queueing
+-#
+ # CONFIG_NET_SCHED is not set
+
+ #
+@@ -315,7 +342,17 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ # CONFIG_HAMRADIO is not set
+ # CONFIG_IRDA is not set
+ # CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
+ # CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
+
+ #
+ # Device Drivers
+@@ -324,34 +361,17 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ #
+ # Generic Driver Options
+ #
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+ CONFIG_STANDALONE=y
+ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ # CONFIG_FW_LOADER is not set
+ # CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
+ # CONFIG_SYS_HYPERVISOR is not set
+-
+-#
+-# Connector - unified userspace <-> kernelspace linker
+-#
+ # CONFIG_CONNECTOR is not set
+-
+-#
+-# Memory Technology Devices (MTD)
+-#
+ # CONFIG_MTD is not set
+-
+-#
+-# Parallel port support
+-#
+ # CONFIG_PARPORT is not set
+-
+-#
+-# Plug and Play support
+-#
+-
+-#
+-# Block devices
+-#
++CONFIG_BLK_DEV=y
+ # CONFIG_BLK_DEV_COW_COMMON is not set
+ # CONFIG_BLK_DEV_LOOP is not set
+ # CONFIG_BLK_DEV_NBD is not set
+@@ -360,15 +380,19 @@ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_COUNT=16
+ CONFIG_BLK_DEV_RAM_SIZE=8192
+ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+-CONFIG_BLK_DEV_INITRD=y
+ # CONFIG_CDROM_PKTCDVD is not set
+ # CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++CONFIG_ATMEL_SSC=y
+
+ #
+ # SCSI device support
+ #
+ # CONFIG_RAID_ATTRS is not set
+ CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
+ # CONFIG_SCSI_NETLINK is not set
+ CONFIG_SCSI_PROC_FS=y
+
+@@ -388,6 +412,8 @@ CONFIG_BLK_DEV_SD=y
+ CONFIG_SCSI_MULTI_LUN=y
+ # CONFIG_SCSI_CONSTANTS is not set
+ # CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
+
+ #
+ # SCSI Transports
+@@ -395,43 +421,72 @@ CONFIG_SCSI_MULTI_LUN=y
+ # CONFIG_SCSI_SPI_ATTRS is not set
+ # CONFIG_SCSI_FC_ATTRS is not set
+ # CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_ATTRS is not set
+ # CONFIG_SCSI_SAS_LIBSAS is not set
+-
+-#
+-# SCSI low-level drivers
+-#
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
+ # CONFIG_ISCSI_TCP is not set
+ # CONFIG_SCSI_DEBUG is not set
+-
+-#
+-# Multi-device support (RAID and LVM)
+-#
++# CONFIG_ATA is not set
+ # CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_MACB=y
++# CONFIG_AX88796 is not set
++# CONFIG_SMC91X is not set
++# CONFIG_DM9000 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
+
+ #
+-# Fusion MPT device support
+-#
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-
+-#
+-# I2O device support
+-#
+-
+-#
+-# Network device support
++# USB Network Adapters
+ #
+-# CONFIG_NETDEVICES is not set
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
+ # CONFIG_NETPOLL is not set
+ # CONFIG_NET_POLL_CONTROLLER is not set
+-
+-#
+-# ISDN subsystem
+-#
+ # CONFIG_ISDN is not set
+
+ #
+@@ -439,6 +494,7 @@ CONFIG_SCSI_MULTI_LUN=y
+ #
+ CONFIG_INPUT=y
+ # CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
+
+ #
+ # Userland interfaces
+@@ -448,7 +504,6 @@ CONFIG_INPUT_MOUSEDEV=y
+ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ # CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_TSDEV is not set
+ # CONFIG_INPUT_EVDEV is not set
+ # CONFIG_INPUT_EVBUG is not set
+
+@@ -458,6 +513,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ # CONFIG_INPUT_KEYBOARD is not set
+ # CONFIG_INPUT_MOUSE is not set
+ # CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
+ # CONFIG_INPUT_TOUCHSCREEN is not set
+ # CONFIG_INPUT_MISC is not set
+
+@@ -492,114 +548,131 @@ CONFIG_SERIAL_CORE_CONSOLE=y
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_LEGACY_PTYS=y
+ CONFIG_LEGACY_PTY_COUNT=256
+-
+-#
+-# IPMI
+-#
+ # CONFIG_IPMI_HANDLER is not set
+-
+-#
+-# Watchdog Cards
+-#
+-CONFIG_WATCHDOG=y
+-CONFIG_WATCHDOG_NOWAYOUT=y
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-
+-#
+-# USB-based Watchdog Cards
+-#
+-# CONFIG_USBPCWATCHDOG is not set
+-CONFIG_HW_RANDOM=y
++# CONFIG_HW_RANDOM is not set
+ # CONFIG_NVRAM is not set
+-# CONFIG_DTLK is not set
+ # CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
+
+ #
+-# Ftape, the floppy tape device driver
++# I2C Algorithms
+ #
+-# CONFIG_RAW_DRIVER is not set
++CONFIG_I2C_ALGOBIT=y
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
+
+ #
+-# TPM devices
++# I2C Hardware Bus support
+ #
+-# CONFIG_TCG_TPM is not set
++CONFIG_I2C_GPIO=y
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_PCA is not set
+
+ #
+-# I2C support
++# Miscellaneous I2C Chip support
+ #
+-# CONFIG_I2C is not set
++# CONFIG_SENSORS_DS1337 is not set
++# CONFIG_SENSORS_DS1374 is not set
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
+
+ #
+ # SPI support
+ #
+ # CONFIG_SPI is not set
+ # CONFIG_SPI_MASTER is not set
+-
+-#
+-# Dallas's 1-wire bus
+-#
+ # CONFIG_W1 is not set
+-
+-#
+-# Hardware Monitoring support
+-#
++# CONFIG_POWER_SUPPLY is not set
+ # CONFIG_HWMON is not set
+-# CONFIG_HWMON_VID is not set
++CONFIG_WATCHDOG=y
++CONFIG_WATCHDOG_NOWAYOUT=y
+
+ #
+-# Misc devices
++# Watchdog Device Drivers
+ #
+-# CONFIG_TIFM_CORE is not set
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_AT91SAM9_WATCHDOG=y
+
+ #
+-# LED devices
++# USB-based Watchdog Cards
+ #
+-# CONFIG_NEW_LEDS is not set
++# CONFIG_USBPCWATCHDOG is not set
+
+ #
+-# LED drivers
++# Sonics Silicon Backplane
+ #
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
+
+ #
+-# LED Triggers
++# Multifunction device drivers
+ #
++# CONFIG_MFD_SM501 is not set
+
+ #
+ # Multimedia devices
+ #
+ # CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
+
+ #
+-# Digital Video Broadcasting Devices
++# Graphics support
+ #
+-# CONFIG_DVB is not set
+-# CONFIG_USB_DABUSB is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+-# Graphics support
++# Display device support
+ #
+-# CONFIG_FIRMWARE_EDID is not set
+-# CONFIG_FB is not set
++# CONFIG_DISPLAY_SUPPORT is not set
+
+ #
+ # Console display driver support
+ #
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+ #
+ # CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
+
+ #
+-# USB support
++# USB Input Devices
+ #
++# CONFIG_USB_HID is not set
++
++#
++# USB HID Boot Protocol drivers
++#
++# CONFIG_USB_KBD is not set
++# CONFIG_USB_MOUSE is not set
++CONFIG_USB_SUPPORT=y
+ CONFIG_USB_ARCH_HAS_HCD=y
+ CONFIG_USB_ARCH_HAS_OHCI=y
+ # CONFIG_USB_ARCH_HAS_EHCI is not set
+@@ -610,7 +683,7 @@ CONFIG_USB=y
+ # Miscellaneous USB options
+ #
+ CONFIG_USB_DEVICEFS=y
+-# CONFIG_USB_BANDWIDTH is not set
++CONFIG_USB_DEVICE_CLASS=y
+ # CONFIG_USB_DYNAMIC_MINORS is not set
+ # CONFIG_USB_OTG is not set
+
+@@ -619,9 +692,11 @@ CONFIG_USB_DEVICEFS=y
+ #
+ # CONFIG_USB_ISP116X_HCD is not set
+ CONFIG_USB_OHCI_HCD=y
+-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+ # CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
+
+ #
+ # USB Device Class drivers
+@@ -640,6 +715,7 @@ CONFIG_USB_STORAGE=y
+ CONFIG_USB_STORAGE_DEBUG=y
+ # CONFIG_USB_STORAGE_DATAFAB is not set
+ # CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
+ # CONFIG_USB_STORAGE_DPCM is not set
+ # CONFIG_USB_STORAGE_USBAT is not set
+ # CONFIG_USB_STORAGE_SDDR09 is not set
+@@ -650,43 +726,10 @@ CONFIG_USB_STORAGE_DEBUG=y
+ # CONFIG_USB_LIBUSUAL is not set
+
+ #
+-# USB Input Devices
+-#
+-# CONFIG_USB_HID is not set
+-
+-#
+-# USB HID Boot Protocol drivers
+-#
+-# CONFIG_USB_KBD is not set
+-# CONFIG_USB_MOUSE is not set
+-# CONFIG_USB_AIPTEK is not set
+-# CONFIG_USB_WACOM is not set
+-# CONFIG_USB_ACECAD is not set
+-# CONFIG_USB_KBTAB is not set
+-# CONFIG_USB_POWERMATE is not set
+-# CONFIG_USB_TOUCHSCREEN is not set
+-# CONFIG_USB_YEALINK is not set
+-# CONFIG_USB_XPAD is not set
+-# CONFIG_USB_ATI_REMOTE is not set
+-# CONFIG_USB_ATI_REMOTE2 is not set
+-# CONFIG_USB_KEYSPAN_REMOTE is not set
+-# CONFIG_USB_APPLETOUCH is not set
+-
+-#
+ # USB Imaging devices
+ #
+ # CONFIG_USB_MDC800 is not set
+ # CONFIG_USB_MICROTEK is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET_MII is not set
+-# CONFIG_USB_USBNET is not set
+ CONFIG_USB_MON=y
+
+ #
+@@ -708,6 +751,7 @@ CONFIG_USB_MON=y
+ # CONFIG_USB_RIO500 is not set
+ # CONFIG_USB_LEGOTOWER is not set
+ # CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
+ # CONFIG_USB_LED is not set
+ # CONFIG_USB_CYPRESS_CY7C63 is not set
+ # CONFIG_USB_CYTHERM is not set
+@@ -717,6 +761,7 @@ CONFIG_USB_MON=y
+ # CONFIG_USB_APPLEDISPLAY is not set
+ # CONFIG_USB_LD is not set
+ # CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
+ # CONFIG_USB_TEST is not set
+
+ #
+@@ -727,13 +772,19 @@ CONFIG_USB_MON=y
+ # USB Gadget Support
+ #
+ CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG is not set
+ # CONFIG_USB_GADGET_DEBUG_FILES is not set
+ CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_ATMEL_USBA is not set
++# CONFIG_USB_GADGET_FSL_USB2 is not set
+ # CONFIG_USB_GADGET_NET2280 is not set
+ # CONFIG_USB_GADGET_PXA2XX is not set
++# CONFIG_USB_GADGET_M66592 is not set
+ # CONFIG_USB_GADGET_GOKU is not set
+ # CONFIG_USB_GADGET_LH7A40X is not set
+ # CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_S3C2410 is not set
+ CONFIG_USB_GADGET_AT91=y
+ CONFIG_USB_AT91=y
+ # CONFIG_USB_GADGET_DUMMY_HCD is not set
+@@ -745,17 +796,56 @@ CONFIG_USB_FILE_STORAGE=m
+ # CONFIG_USB_FILE_STORAGE_TEST is not set
+ CONFIG_USB_G_SERIAL=m
+ # CONFIG_USB_MIDI_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_NEW_LEDS is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
+
+ #
+-# MMC/SD Card support
++# RTC interfaces
+ #
+-# CONFIG_MMC is not set
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
+
+ #
+-# Real Time Clock
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++
++#
++# SPI RTC drivers
+ #
+-CONFIG_RTC_LIB=y
+-# CONFIG_RTC_CLASS is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_AT91SAM9=y
+
+ #
+ # File systems
+@@ -806,7 +896,6 @@ CONFIG_SYSFS=y
+ CONFIG_TMPFS=y
+ # CONFIG_TMPFS_POSIX_ACL is not set
+ # CONFIG_HUGETLB_PAGE is not set
+-CONFIG_RAMFS=y
+ # CONFIG_CONFIGFS_FS is not set
+
+ #
+@@ -825,10 +914,7 @@ CONFIG_CRAMFS=y
+ # CONFIG_QNX4FS_FS is not set
+ # CONFIG_SYSV_FS is not set
+ # CONFIG_UFS_FS is not set
+-
+-#
+-# Network File Systems
+-#
++CONFIG_NETWORK_FILESYSTEMS=y
+ # CONFIG_NFS_FS is not set
+ # CONFIG_NFSD is not set
+ # CONFIG_SMB_FS is not set
+@@ -836,17 +922,12 @@ CONFIG_CRAMFS=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
+-# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+ #
+ # CONFIG_PARTITION_ADVANCED is not set
+ CONFIG_MSDOS_PARTITION=y
+-
+-#
+-# Native Language Support
+-#
+ CONFIG_NLS=y
+ CONFIG_NLS_DEFAULT="iso8859-1"
+ CONFIG_NLS_CODEPAGE_437=y
+@@ -887,41 +968,49 @@ CONFIG_NLS_ISO8859_1=y
+ # CONFIG_NLS_KOI8_R is not set
+ # CONFIG_NLS_KOI8_U is not set
+ # CONFIG_NLS_UTF8 is not set
+-
+-#
+-# Profiling support
+-#
++# CONFIG_DLM is not set
++CONFIG_INSTRUMENTATION=y
+ # CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
+
+ #
+ # Kernel hacking
+ #
+ # CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
+ CONFIG_ENABLE_MUST_CHECK=y
+ # CONFIG_MAGIC_SYSRQ is not set
+ # CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
+ CONFIG_DEBUG_KERNEL=y
+-CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_DEBUG_SHIRQ is not set
+ CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
+ # CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
+ # CONFIG_DEBUG_SLAB is not set
+ # CONFIG_DEBUG_RT_MUTEXES is not set
+ # CONFIG_RT_MUTEX_TESTER is not set
+ # CONFIG_DEBUG_SPINLOCK is not set
+ # CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_RWSEMS is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
+ # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+ # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+ # CONFIG_DEBUG_KOBJECT is not set
+ CONFIG_DEBUG_BUGVERBOSE=y
+ # CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_FS is not set
+ # CONFIG_DEBUG_VM is not set
+ # CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
+ CONFIG_FRAME_POINTER=y
+ CONFIG_FORCED_INLINING=y
+-# CONFIG_HEADERS_CHECK is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
+ # CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
+ CONFIG_DEBUG_USER=y
+ # CONFIG_DEBUG_ERRORS is not set
+ CONFIG_DEBUG_LL=y
+@@ -932,18 +1021,21 @@ CONFIG_DEBUG_LL=y
+ #
+ # CONFIG_KEYS is not set
+ # CONFIG_SECURITY is not set
+-
+-#
+-# Cryptographic options
+-#
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+ # CONFIG_CRYPTO is not set
+
+ #
+ # Library routines
+ #
++CONFIG_BITREVERSE=y
+ # CONFIG_CRC_CCITT is not set
+ # CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
+ CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
+ # CONFIG_LIBCRC32C is not set
+ CONFIG_ZLIB_INFLATE=y
+ CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/at91sam9261ek_defconfig b/arch/arm/configs/at91sam9261ek_defconfig
+index fcd8fa0..3802e85 100644
+--- a/arch/arm/configs/at91sam9261ek_defconfig
++++ b/arch/arm/configs/at91sam9261ek_defconfig
+@@ -1,43 +1,56 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.19-rc6
+-# Fri Nov 17 18:00:38 2006
++# Linux kernel version: 2.6.24-rc7
++# Tue Jan 8 22:21:49 2008
+ #
+ CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
+ # CONFIG_GENERIC_TIME is not set
++# CONFIG_GENERIC_CLOCKEVENTS is not set
+ CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
+ CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
+ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+ CONFIG_HARDIRQS_SW_RESEND=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+ CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ZONE_DMA=y
+ CONFIG_VECTORS_BASE=0xffff0000
+ CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+ #
+-# Code maturity level options
++# General setup
+ #
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_BROKEN_ON_SMP=y
+ CONFIG_INIT_ENV_ARG_LIMIT=32
+-
+-#
+-# General setup
+-#
+ CONFIG_LOCALVERSION=""
+ # CONFIG_LOCALVERSION_AUTO is not set
+ # CONFIG_SWAP is not set
+ CONFIG_SYSVIPC=y
+-# CONFIG_IPC_NS is not set
++CONFIG_SYSVIPC_SYSCTL=y
+ # CONFIG_POSIX_MQUEUE is not set
+ # CONFIG_BSD_PROCESS_ACCT is not set
+ # CONFIG_TASKSTATS is not set
+-# CONFIG_UTS_NS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
+ # CONFIG_AUDIT is not set
+ # CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
+ # CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
+ CONFIG_INITRAMFS_SOURCE=""
+ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+ CONFIG_SYSCTL=y
+@@ -53,30 +66,30 @@ CONFIG_BUG=y
+ CONFIG_ELF_CORE=y
+ CONFIG_BASE_FULL=y
+ CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
+ CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
+ CONFIG_SHMEM=y
+-CONFIG_SLAB=y
+ CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_SLABINFO=y
+ CONFIG_RT_MUTEXES=y
+ # CONFIG_TINY_SHMEM is not set
+ CONFIG_BASE_SMALL=0
+-# CONFIG_SLOB is not set
+-
+-#
+-# Loadable module support
+-#
+ CONFIG_MODULES=y
+ CONFIG_MODULE_UNLOAD=y
+ # CONFIG_MODULE_FORCE_UNLOAD is not set
+ # CONFIG_MODVERSIONS is not set
+ # CONFIG_MODULE_SRCVERSION_ALL is not set
+ CONFIG_KMOD=y
+-
+-#
+-# Block layer
+-#
+ CONFIG_BLOCK=y
++# CONFIG_LBD is not set
+ # CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
+
+ #
+ # IO Schedulers
+@@ -108,12 +121,16 @@ CONFIG_ARCH_AT91=y
+ # CONFIG_ARCH_NETX is not set
+ # CONFIG_ARCH_H720X is not set
+ # CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
+ # CONFIG_ARCH_IOP32X is not set
+ # CONFIG_ARCH_IOP33X is not set
+-# CONFIG_ARCH_IXP4XX is not set
+-# CONFIG_ARCH_IXP2000 is not set
+ # CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
+ # CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
+ # CONFIG_ARCH_PNX4008 is not set
+ # CONFIG_ARCH_PXA is not set
+ # CONFIG_ARCH_RPC is not set
+@@ -121,14 +138,27 @@ CONFIG_ARCH_AT91=y
+ # CONFIG_ARCH_S3C2410 is not set
+ # CONFIG_ARCH_SHARK is not set
+ # CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
+ # CONFIG_ARCH_OMAP is not set
+
+ #
++# Boot options
++#
++
++#
++# Power management
++#
++
++#
+ # Atmel AT91 System-on-Chip
+ #
+ # CONFIG_ARCH_AT91RM9200 is not set
+ # CONFIG_ARCH_AT91SAM9260 is not set
+ CONFIG_ARCH_AT91SAM9261=y
++# CONFIG_ARCH_AT91SAM9263 is not set
++# CONFIG_ARCH_AT91SAM9RL is not set
++# CONFIG_ARCH_AT91X40 is not set
++CONFIG_AT91_PMC_UNIT=y
+
+ #
+ # AT91SAM9261 Board Type
+@@ -138,12 +168,15 @@ CONFIG_MACH_AT91SAM9261EK=y
+ #
+ # AT91 Board Options
+ #
++# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
+ # CONFIG_MTD_NAND_AT91_BUSWIDTH_16 is not set
+
+ #
+ # AT91 Feature Selections
+ #
+-# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
++CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
++# CONFIG_ATMEL_TCLIB is not set
++CONFIG_AT91_TIMER_HZ=100
+
+ #
+ # Processor Type
+@@ -166,19 +199,19 @@ CONFIG_CPU_CP15_MMU=y
+ # CONFIG_CPU_DCACHE_DISABLE is not set
+ # CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+ # CONFIG_CPU_CACHE_ROUND_ROBIN is not set
++# CONFIG_OUTER_CACHE is not set
+
+ #
+ # Bus support
+ #
+-
+-#
+-# PCCARD (PCMCIA/CardBus) support
+-#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
+ # CONFIG_PCCARD is not set
+
+ #
+ # Kernel Features
+ #
++# CONFIG_TICK_ONESHOT is not set
+ # CONFIG_PREEMPT is not set
+ # CONFIG_NO_IDLE_HZ is not set
+ CONFIG_HZ=100
+@@ -191,8 +224,12 @@ CONFIG_FLATMEM_MANUAL=y
+ CONFIG_FLATMEM=y
+ CONFIG_FLAT_NODE_MEM_MAP=y
+ # CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+ CONFIG_SPLIT_PTLOCK_CPUS=4096
+ # CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
+ # CONFIG_LEDS is not set
+ CONFIG_ALIGNMENT_TRAP=y
+
+@@ -203,6 +240,7 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
+ CONFIG_ZBOOT_ROM_BSS=0x0
+ CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
+ # CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
+
+ #
+ # Floating point emulation
+@@ -228,7 +266,7 @@ CONFIG_BINFMT_ELF=y
+ # Power management options
+ #
+ # CONFIG_PM is not set
+-# CONFIG_APM is not set
++CONFIG_SUSPEND_UP_POSSIBLE=y
+
+ #
+ # Networking
+@@ -238,13 +276,13 @@ CONFIG_NET=y
+ #
+ # Networking options
+ #
+-# CONFIG_NETDEBUG is not set
+ CONFIG_PACKET=y
+ # CONFIG_PACKET_MMAP is not set
+ CONFIG_UNIX=y
+ CONFIG_XFRM=y
+ # CONFIG_XFRM_USER is not set
+ # CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
+ # CONFIG_NET_KEY is not set
+ CONFIG_INET=y
+ # CONFIG_IP_MULTICAST is not set
+@@ -266,30 +304,20 @@ CONFIG_IP_PNP_BOOTP=y
+ CONFIG_INET_XFRM_MODE_TRANSPORT=y
+ CONFIG_INET_XFRM_MODE_TUNNEL=y
+ CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
+ CONFIG_INET_DIAG=y
+ CONFIG_INET_TCP_DIAG=y
+ # CONFIG_TCP_CONG_ADVANCED is not set
+ CONFIG_TCP_CONG_CUBIC=y
+ CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
+ # CONFIG_IPV6 is not set
+ # CONFIG_INET6_XFRM_TUNNEL is not set
+ # CONFIG_INET6_TUNNEL is not set
+ # CONFIG_NETWORK_SECMARK is not set
+ # CONFIG_NETFILTER is not set
+-
+-#
+-# DCCP Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_IP_DCCP is not set
+-
+-#
+-# SCTP Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_IP_SCTP is not set
+-
+-#
+-# TIPC Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_TIPC is not set
+ # CONFIG_ATM is not set
+ # CONFIG_BRIDGE is not set
+@@ -302,10 +330,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ # CONFIG_LAPB is not set
+ # CONFIG_ECONET is not set
+ # CONFIG_WAN_ROUTER is not set
+-
+-#
+-# QoS and/or fair queueing
+-#
+ # CONFIG_NET_SCHED is not set
+
+ #
+@@ -315,7 +339,17 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ # CONFIG_HAMRADIO is not set
+ # CONFIG_IRDA is not set
+ # CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
+ # CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
+
+ #
+ # Device Drivers
+@@ -324,20 +358,14 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ #
+ # Generic Driver Options
+ #
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+ CONFIG_STANDALONE=y
+ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ # CONFIG_FW_LOADER is not set
+ # CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
+ # CONFIG_SYS_HYPERVISOR is not set
+-
+-#
+-# Connector - unified userspace <-> kernelspace linker
+-#
+ # CONFIG_CONNECTOR is not set
+-
+-#
+-# Memory Technology Devices (MTD)
+-#
+ CONFIG_MTD=y
+ # CONFIG_MTD_DEBUG is not set
+ # CONFIG_MTD_CONCAT is not set
+@@ -350,12 +378,14 @@ CONFIG_MTD_CMDLINE_PARTS=y
+ # User Modules And Translation Layers
+ #
+ # CONFIG_MTD_CHAR is not set
++CONFIG_MTD_BLKDEVS=y
+ CONFIG_MTD_BLOCK=y
+ # CONFIG_FTL is not set
+ # CONFIG_NFTL is not set
+ # CONFIG_INFTL is not set
+ # CONFIG_RFD_FTL is not set
+ # CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
+
+ #
+ # RAM/ROM/Flash chip drivers
+@@ -375,7 +405,6 @@ CONFIG_MTD_CFI_I2=y
+ # CONFIG_MTD_RAM is not set
+ # CONFIG_MTD_ROM is not set
+ # CONFIG_MTD_ABSENT is not set
+-# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+ #
+ # Mapping drivers for chip access
+@@ -386,6 +415,8 @@ CONFIG_MTD_CFI_I2=y
+ #
+ # Self-contained MTD device drivers
+ #
++# CONFIG_MTD_DATAFLASH is not set
++# CONFIG_MTD_M25P80 is not set
+ # CONFIG_MTD_SLRAM is not set
+ # CONFIG_MTD_PHRAM is not set
+ # CONFIG_MTD_MTDRAM is not set
+@@ -397,35 +428,24 @@ CONFIG_MTD_CFI_I2=y
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOC2001PLUS is not set
+-
+-#
+-# NAND Flash Device Drivers
+-#
+ CONFIG_MTD_NAND=y
+ # CONFIG_MTD_NAND_VERIFY_WRITE is not set
+ # CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+ CONFIG_MTD_NAND_IDS=y
+ # CONFIG_MTD_NAND_DISKONCHIP is not set
+ CONFIG_MTD_NAND_AT91=y
+ # CONFIG_MTD_NAND_NANDSIM is not set
+-
+-#
+-# OneNAND Flash Device Drivers
+-#
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ALAUDA is not set
+ # CONFIG_MTD_ONENAND is not set
+
+ #
+-# Parallel port support
++# UBI - Unsorted block images
+ #
++# CONFIG_MTD_UBI is not set
+ # CONFIG_PARPORT is not set
+-
+-#
+-# Plug and Play support
+-#
+-
+-#
+-# Block devices
+-#
++CONFIG_BLK_DEV=y
+ # CONFIG_BLK_DEV_COW_COMMON is not set
+ # CONFIG_BLK_DEV_LOOP is not set
+ # CONFIG_BLK_DEV_NBD is not set
+@@ -434,15 +454,19 @@ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_COUNT=16
+ CONFIG_BLK_DEV_RAM_SIZE=8192
+ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+-CONFIG_BLK_DEV_INITRD=y
+ # CONFIG_CDROM_PKTCDVD is not set
+ # CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++CONFIG_ATMEL_SSC=y
+
+ #
+ # SCSI device support
+ #
+ # CONFIG_RAID_ATTRS is not set
+ CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
+ # CONFIG_SCSI_NETLINK is not set
+ CONFIG_SCSI_PROC_FS=y
+
+@@ -462,6 +486,8 @@ CONFIG_BLK_DEV_SD=y
+ CONFIG_SCSI_MULTI_LUN=y
+ # CONFIG_SCSI_CONSTANTS is not set
+ # CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
+
+ #
+ # SCSI Transports
+@@ -469,75 +495,49 @@ CONFIG_SCSI_MULTI_LUN=y
+ # CONFIG_SCSI_SPI_ATTRS is not set
+ # CONFIG_SCSI_FC_ATTRS is not set
+ # CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_ATTRS is not set
+ # CONFIG_SCSI_SAS_LIBSAS is not set
+-
+-#
+-# SCSI low-level drivers
+-#
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
+ # CONFIG_ISCSI_TCP is not set
+ # CONFIG_SCSI_DEBUG is not set
+-
+-#
+-# Multi-device support (RAID and LVM)
+-#
++# CONFIG_ATA is not set
+ # CONFIG_MD is not set
+-
+-#
+-# Fusion MPT device support
+-#
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-
+-#
+-# I2O device support
+-#
+-
+-#
+-# Network device support
+-#
+ CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
+ # CONFIG_DUMMY is not set
+ # CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
+ # CONFIG_EQUALIZER is not set
+ # CONFIG_TUN is not set
+-
+-#
+-# PHY device support
+-#
++# CONFIG_VETH is not set
+ # CONFIG_PHYLIB is not set
+-
+-#
+-# Ethernet (10 or 100Mbit)
+-#
+ CONFIG_NET_ETHERNET=y
+ CONFIG_MII=y
++# CONFIG_AX88796 is not set
+ # CONFIG_SMC91X is not set
+ CONFIG_DM9000=y
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
+
+ #
+-# Ethernet (1000 Mbit)
+-#
+-
+-#
+-# Ethernet (10000 Mbit)
+-#
+-
+-#
+-# Token Ring devices
++# Wireless LAN
+ #
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
+
+ #
+-# Wireless LAN (non-hamradio)
+-#
+-# CONFIG_NET_RADIO is not set
+-
+-#
+-# Wan interfaces
++# USB Network Adapters
+ #
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
+ # CONFIG_WAN is not set
+ # CONFIG_PPP is not set
+ # CONFIG_SLIP is not set
+@@ -545,10 +545,6 @@ CONFIG_DM9000=y
+ # CONFIG_NETCONSOLE is not set
+ # CONFIG_NETPOLL is not set
+ # CONFIG_NET_POLL_CONTROLLER is not set
+-
+-#
+-# ISDN subsystem
+-#
+ # CONFIG_ISDN is not set
+
+ #
+@@ -556,6 +552,7 @@ CONFIG_DM9000=y
+ #
+ CONFIG_INPUT=y
+ # CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
+
+ #
+ # Userland interfaces
+@@ -565,23 +562,43 @@ CONFIG_INPUT_MOUSEDEV=y
+ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ # CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_TSDEV is not set
+ # CONFIG_INPUT_EVDEV is not set
+ # CONFIG_INPUT_EVBUG is not set
+
+ #
+ # Input Device Drivers
+ #
+-# CONFIG_INPUT_KEYBOARD is not set
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ATKBD is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++CONFIG_KEYBOARD_GPIO=y
+ # CONFIG_INPUT_MOUSE is not set
+ # CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_TABLET is not set
++CONFIG_INPUT_TOUCHSCREEN=y
++CONFIG_TOUCHSCREEN_ADS7846=y
++# CONFIG_TOUCHSCREEN_FUJITSU is not set
++# CONFIG_TOUCHSCREEN_GUNZE is not set
++# CONFIG_TOUCHSCREEN_ELO is not set
++# CONFIG_TOUCHSCREEN_MTOUCH is not set
++# CONFIG_TOUCHSCREEN_MK712 is not set
++# CONFIG_TOUCHSCREEN_PENMOUNT is not set
++# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
++# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
++# CONFIG_TOUCHSCREEN_UCB1400 is not set
++# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+ # CONFIG_INPUT_MISC is not set
+
+ #
+ # Hardware I/O ports
+ #
+-# CONFIG_SERIO is not set
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_RAW is not set
+ # CONFIG_GAMEPORT is not set
+
+ #
+@@ -609,75 +626,47 @@ CONFIG_SERIAL_CORE_CONSOLE=y
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_LEGACY_PTYS=y
+ CONFIG_LEGACY_PTY_COUNT=256
+-
+-#
+-# IPMI
+-#
+ # CONFIG_IPMI_HANDLER is not set
+-
+-#
+-# Watchdog Cards
+-#
+-CONFIG_WATCHDOG=y
+-CONFIG_WATCHDOG_NOWAYOUT=y
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-
+-#
+-# USB-based Watchdog Cards
+-#
+-# CONFIG_USBPCWATCHDOG is not set
+ CONFIG_HW_RANDOM=y
+ # CONFIG_NVRAM is not set
+-# CONFIG_DTLK is not set
+ # CONFIG_R3964 is not set
+-
+-#
+-# Ftape, the floppy tape device driver
+-#
+ # CONFIG_RAW_DRIVER is not set
+-
+-#
+-# TPM devices
+-#
+ # CONFIG_TCG_TPM is not set
+-
+-#
+-# I2C support
+-#
+ CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
+ CONFIG_I2C_CHARDEV=y
+
+ #
+ # I2C Algorithms
+ #
+-# CONFIG_I2C_ALGOBIT is not set
++CONFIG_I2C_ALGOBIT=y
+ # CONFIG_I2C_ALGOPCF is not set
+ # CONFIG_I2C_ALGOPCA is not set
+
+ #
+ # I2C Hardware Bus support
+ #
+-CONFIG_I2C_AT91=y
++CONFIG_I2C_GPIO=y
+ # CONFIG_I2C_OCORES is not set
+ # CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
+ # CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
+ # CONFIG_I2C_PCA is not set
+-# CONFIG_I2C_PCA_ISA is not set
+
+ #
+ # Miscellaneous I2C Chip support
+ #
+ # CONFIG_SENSORS_DS1337 is not set
+ # CONFIG_SENSORS_DS1374 is not set
++# CONFIG_DS1682 is not set
+ # CONFIG_SENSORS_EEPROM is not set
+ # CONFIG_SENSORS_PCF8574 is not set
+ # CONFIG_SENSORS_PCA9539 is not set
+ # CONFIG_SENSORS_PCF8591 is not set
+ # CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
+ # CONFIG_I2C_DEBUG_CORE is not set
+ # CONFIG_I2C_DEBUG_ALGO is not set
+ # CONFIG_I2C_DEBUG_BUS is not set
+@@ -686,70 +675,125 @@ CONFIG_I2C_AT91=y
+ #
+ # SPI support
+ #
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
++CONFIG_SPI=y
++# CONFIG_SPI_DEBUG is not set
++CONFIG_SPI_MASTER=y
+
+ #
+-# Dallas's 1-wire bus
++# SPI Master Controller Drivers
+ #
+-# CONFIG_W1 is not set
++CONFIG_SPI_ATMEL=y
++# CONFIG_SPI_BITBANG is not set
+
+ #
+-# Hardware Monitoring support
++# SPI Protocol Masters
+ #
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
+ # CONFIG_HWMON is not set
+-# CONFIG_HWMON_VID is not set
++CONFIG_WATCHDOG=y
++CONFIG_WATCHDOG_NOWAYOUT=y
+
+ #
+-# Misc devices
++# Watchdog Device Drivers
+ #
+-# CONFIG_TIFM_CORE is not set
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_AT91SAM9_WATCHDOG=y
+
+ #
+-# LED devices
++# USB-based Watchdog Cards
+ #
+-# CONFIG_NEW_LEDS is not set
++# CONFIG_USBPCWATCHDOG is not set
+
+ #
+-# LED drivers
++# Sonics Silicon Backplane
+ #
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
+
+ #
+-# LED Triggers
++# Multifunction device drivers
+ #
++# CONFIG_MFD_SM501 is not set
+
+ #
+ # Multimedia devices
+ #
+ # CONFIG_VIDEO_DEV is not set
+-
+-#
+-# Digital Video Broadcasting Devices
+-#
+-# CONFIG_DVB is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
+ # CONFIG_USB_DABUSB is not set
+
+ #
+ # Graphics support
+ #
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++CONFIG_FB=y
+ # CONFIG_FIRMWARE_EDID is not set
+-# CONFIG_FB is not set
++# CONFIG_FB_DDC is not set
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
++# CONFIG_FB_SYS_FILLRECT is not set
++# CONFIG_FB_SYS_COPYAREA is not set
++# CONFIG_FB_SYS_IMAGEBLIT is not set
++# CONFIG_FB_SYS_FOPS is not set
++CONFIG_FB_DEFERRED_IO=y
++# CONFIG_FB_SVGALIB is not set
++# CONFIG_FB_MACMODES is not set
++# CONFIG_FB_BACKLIGHT is not set
++# CONFIG_FB_MODE_HELPERS is not set
++# CONFIG_FB_TILEBLITTING is not set
++
++#
++# Frame buffer hardware drivers
++#
++# CONFIG_FB_S1D15605 is not set
++# CONFIG_FB_S1D13XXX is not set
++CONFIG_FB_ATMEL=y
++# CONFIG_FB_INTSRAM is not set
++# CONFIG_FB_ATMEL_STN is not set
++# CONFIG_FB_VIRTUAL is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
+
+ #
+ # Console display driver support
+ #
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++# CONFIG_FRAMEBUFFER_CONSOLE is not set
++# CONFIG_LOGO is not set
+
+ #
+ # Sound
+ #
+ # CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
+
+ #
+-# USB support
++# USB Input Devices
+ #
++# CONFIG_USB_HID is not set
++
++#
++# USB HID Boot Protocol drivers
++#
++# CONFIG_USB_KBD is not set
++# CONFIG_USB_MOUSE is not set
++CONFIG_USB_SUPPORT=y
+ CONFIG_USB_ARCH_HAS_HCD=y
+ CONFIG_USB_ARCH_HAS_OHCI=y
+ # CONFIG_USB_ARCH_HAS_EHCI is not set
+@@ -760,7 +804,7 @@ CONFIG_USB=y
+ # Miscellaneous USB options
+ #
+ CONFIG_USB_DEVICEFS=y
+-# CONFIG_USB_BANDWIDTH is not set
++CONFIG_USB_DEVICE_CLASS=y
+ # CONFIG_USB_DYNAMIC_MINORS is not set
+ # CONFIG_USB_OTG is not set
+
+@@ -769,9 +813,11 @@ CONFIG_USB_DEVICEFS=y
+ #
+ # CONFIG_USB_ISP116X_HCD is not set
+ CONFIG_USB_OHCI_HCD=y
+-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+ # CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
+
+ #
+ # USB Device Class drivers
+@@ -790,6 +836,7 @@ CONFIG_USB_STORAGE=y
+ CONFIG_USB_STORAGE_DEBUG=y
+ # CONFIG_USB_STORAGE_DATAFAB is not set
+ # CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
+ # CONFIG_USB_STORAGE_DPCM is not set
+ # CONFIG_USB_STORAGE_USBAT is not set
+ # CONFIG_USB_STORAGE_SDDR09 is not set
+@@ -800,43 +847,10 @@ CONFIG_USB_STORAGE_DEBUG=y
+ # CONFIG_USB_LIBUSUAL is not set
+
+ #
+-# USB Input Devices
+-#
+-# CONFIG_USB_HID is not set
+-
+-#
+-# USB HID Boot Protocol drivers
+-#
+-# CONFIG_USB_KBD is not set
+-# CONFIG_USB_MOUSE is not set
+-# CONFIG_USB_AIPTEK is not set
+-# CONFIG_USB_WACOM is not set
+-# CONFIG_USB_ACECAD is not set
+-# CONFIG_USB_KBTAB is not set
+-# CONFIG_USB_POWERMATE is not set
+-# CONFIG_USB_TOUCHSCREEN is not set
+-# CONFIG_USB_YEALINK is not set
+-# CONFIG_USB_XPAD is not set
+-# CONFIG_USB_ATI_REMOTE is not set
+-# CONFIG_USB_ATI_REMOTE2 is not set
+-# CONFIG_USB_KEYSPAN_REMOTE is not set
+-# CONFIG_USB_APPLETOUCH is not set
+-
+-#
+ # USB Imaging devices
+ #
+ # CONFIG_USB_MDC800 is not set
+ # CONFIG_USB_MICROTEK is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET_MII is not set
+-# CONFIG_USB_USBNET is not set
+ CONFIG_USB_MON=y
+
+ #
+@@ -858,6 +872,7 @@ CONFIG_USB_MON=y
+ # CONFIG_USB_RIO500 is not set
+ # CONFIG_USB_LEGOTOWER is not set
+ # CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
+ # CONFIG_USB_LED is not set
+ # CONFIG_USB_CYPRESS_CY7C63 is not set
+ # CONFIG_USB_CYTHERM is not set
+@@ -867,6 +882,7 @@ CONFIG_USB_MON=y
+ # CONFIG_USB_APPLEDISPLAY is not set
+ # CONFIG_USB_LD is not set
+ # CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
+ # CONFIG_USB_TEST is not set
+
+ #
+@@ -877,13 +893,19 @@ CONFIG_USB_MON=y
+ # USB Gadget Support
+ #
+ CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG is not set
+ # CONFIG_USB_GADGET_DEBUG_FILES is not set
+ CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_ATMEL_USBA is not set
++# CONFIG_USB_GADGET_FSL_USB2 is not set
+ # CONFIG_USB_GADGET_NET2280 is not set
+ # CONFIG_USB_GADGET_PXA2XX is not set
++# CONFIG_USB_GADGET_M66592 is not set
+ # CONFIG_USB_GADGET_GOKU is not set
+ # CONFIG_USB_GADGET_LH7A40X is not set
+ # CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_S3C2410 is not set
+ CONFIG_USB_GADGET_AT91=y
+ CONFIG_USB_AT91=y
+ # CONFIG_USB_GADGET_DUMMY_HCD is not set
+@@ -895,21 +917,73 @@ CONFIG_USB_FILE_STORAGE=m
+ # CONFIG_USB_FILE_STORAGE_TEST is not set
+ CONFIG_USB_G_SERIAL=m
+ # CONFIG_USB_MIDI_GADGET is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
+
+ #
+-# MMC/SD Card support
++# MMC/SD Card Drivers
+ #
+-CONFIG_MMC=y
+-# CONFIG_MMC_DEBUG is not set
+ CONFIG_MMC_BLOCK=y
+-CONFIG_MMC_AT91=m
+-# CONFIG_MMC_TIFM_SD is not set
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
+
+ #
+-# Real Time Clock
++# MMC/SD Host Controller Drivers
+ #
++CONFIG_MMC_AT91=y
++# CONFIG_MMC_SPI is not set
++# CONFIG_NEW_LEDS is not set
+ CONFIG_RTC_LIB=y
+-# CONFIG_RTC_CLASS is not set
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_AT91SAM9=y
+
+ #
+ # File systems
+@@ -960,7 +1034,6 @@ CONFIG_SYSFS=y
+ CONFIG_TMPFS=y
+ # CONFIG_TMPFS_POSIX_ACL is not set
+ # CONFIG_HUGETLB_PAGE is not set
+-CONFIG_RAMFS=y
+ # CONFIG_CONFIGFS_FS is not set
+
+ #
+@@ -973,7 +1046,6 @@ CONFIG_RAMFS=y
+ # CONFIG_BEFS_FS is not set
+ # CONFIG_BFS_FS is not set
+ # CONFIG_EFS_FS is not set
+-# CONFIG_JFFS_FS is not set
+ # CONFIG_JFFS2_FS is not set
+ CONFIG_CRAMFS=y
+ # CONFIG_VXFS_FS is not set
+@@ -981,10 +1053,7 @@ CONFIG_CRAMFS=y
+ # CONFIG_QNX4FS_FS is not set
+ # CONFIG_SYSV_FS is not set
+ # CONFIG_UFS_FS is not set
+-
+-#
+-# Network File Systems
+-#
++CONFIG_NETWORK_FILESYSTEMS=y
+ # CONFIG_NFS_FS is not set
+ # CONFIG_NFSD is not set
+ # CONFIG_SMB_FS is not set
+@@ -992,17 +1061,12 @@ CONFIG_CRAMFS=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
+-# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+ #
+ # CONFIG_PARTITION_ADVANCED is not set
+ CONFIG_MSDOS_PARTITION=y
+-
+-#
+-# Native Language Support
+-#
+ CONFIG_NLS=y
+ CONFIG_NLS_DEFAULT="iso8859-1"
+ CONFIG_NLS_CODEPAGE_437=y
+@@ -1043,41 +1107,49 @@ CONFIG_NLS_ISO8859_1=y
+ # CONFIG_NLS_KOI8_R is not set
+ # CONFIG_NLS_KOI8_U is not set
+ # CONFIG_NLS_UTF8 is not set
+-
+-#
+-# Profiling support
+-#
++# CONFIG_DLM is not set
++CONFIG_INSTRUMENTATION=y
+ # CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
+
+ #
+ # Kernel hacking
+ #
+ # CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
+ CONFIG_ENABLE_MUST_CHECK=y
+ # CONFIG_MAGIC_SYSRQ is not set
+ # CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
+ CONFIG_DEBUG_KERNEL=y
+-CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_DEBUG_SHIRQ is not set
+ CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
+ # CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
+ # CONFIG_DEBUG_SLAB is not set
+ # CONFIG_DEBUG_RT_MUTEXES is not set
+ # CONFIG_RT_MUTEX_TESTER is not set
+ # CONFIG_DEBUG_SPINLOCK is not set
+ # CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_RWSEMS is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
+ # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+ # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+ # CONFIG_DEBUG_KOBJECT is not set
+ CONFIG_DEBUG_BUGVERBOSE=y
+ # CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_FS is not set
+ # CONFIG_DEBUG_VM is not set
+ # CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
+ CONFIG_FRAME_POINTER=y
+ CONFIG_FORCED_INLINING=y
+-# CONFIG_HEADERS_CHECK is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
+ # CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
+ CONFIG_DEBUG_USER=y
+ # CONFIG_DEBUG_ERRORS is not set
+ CONFIG_DEBUG_LL=y
+@@ -1088,18 +1160,21 @@ CONFIG_DEBUG_LL=y
+ #
+ # CONFIG_KEYS is not set
+ # CONFIG_SECURITY is not set
+-
+-#
+-# Cryptographic options
+-#
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+ # CONFIG_CRYPTO is not set
+
+ #
+ # Library routines
+ #
++CONFIG_BITREVERSE=y
+ # CONFIG_CRC_CCITT is not set
+ # CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
+ CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
+ # CONFIG_LIBCRC32C is not set
+ CONFIG_ZLIB_INFLATE=y
+ CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/at91sam9263ek_defconfig b/arch/arm/configs/at91sam9263ek_defconfig
+index c72ab82..32a0d74 100644
+--- a/arch/arm/configs/at91sam9263ek_defconfig
++++ b/arch/arm/configs/at91sam9263ek_defconfig
+@@ -1,12 +1,18 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.20-rc1
+-# Mon Jan 8 16:06:54 2007
++# Linux kernel version: 2.6.24-rc7
++# Tue Jan 8 22:12:20 2008
+ #
+ CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
+ # CONFIG_GENERIC_TIME is not set
++# CONFIG_GENERIC_CLOCKEVENTS is not set
+ CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
+ CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
+ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+ CONFIG_HARDIRQS_SW_RESEND=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+@@ -15,32 +21,36 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
+ # CONFIG_ARCH_HAS_ILOG2_U64 is not set
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ZONE_DMA=y
+ CONFIG_VECTORS_BASE=0xffff0000
+ CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+ #
+-# Code maturity level options
++# General setup
+ #
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_BROKEN_ON_SMP=y
+ CONFIG_INIT_ENV_ARG_LIMIT=32
+-
+-#
+-# General setup
+-#
+ CONFIG_LOCALVERSION=""
+ # CONFIG_LOCALVERSION_AUTO is not set
+ # CONFIG_SWAP is not set
+ CONFIG_SYSVIPC=y
+-# CONFIG_IPC_NS is not set
++CONFIG_SYSVIPC_SYSCTL=y
+ # CONFIG_POSIX_MQUEUE is not set
+ # CONFIG_BSD_PROCESS_ACCT is not set
+ # CONFIG_TASKSTATS is not set
+-# CONFIG_UTS_NS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
+ # CONFIG_AUDIT is not set
+ # CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
+ CONFIG_SYSFS_DEPRECATED=y
+ # CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
+ CONFIG_INITRAMFS_SOURCE=""
+ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+ CONFIG_SYSCTL=y
+@@ -56,32 +66,30 @@ CONFIG_BUG=y
+ CONFIG_ELF_CORE=y
+ CONFIG_BASE_FULL=y
+ CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
+ CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
+ CONFIG_SHMEM=y
+-CONFIG_SLAB=y
+ CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_SLABINFO=y
+ CONFIG_RT_MUTEXES=y
+ # CONFIG_TINY_SHMEM is not set
+ CONFIG_BASE_SMALL=0
+-# CONFIG_SLOB is not set
+-
+-#
+-# Loadable module support
+-#
+ CONFIG_MODULES=y
+ CONFIG_MODULE_UNLOAD=y
+ # CONFIG_MODULE_FORCE_UNLOAD is not set
+ # CONFIG_MODVERSIONS is not set
+ # CONFIG_MODULE_SRCVERSION_ALL is not set
+ CONFIG_KMOD=y
+-
+-#
+-# Block layer
+-#
+ CONFIG_BLOCK=y
+ # CONFIG_LBD is not set
+ # CONFIG_BLK_DEV_IO_TRACE is not set
+ # CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
+
+ #
+ # IO Schedulers
+@@ -113,13 +121,16 @@ CONFIG_ARCH_AT91=y
+ # CONFIG_ARCH_NETX is not set
+ # CONFIG_ARCH_H720X is not set
+ # CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
+ # CONFIG_ARCH_IOP32X is not set
+ # CONFIG_ARCH_IOP33X is not set
+-# CONFIG_ARCH_IOP13XX is not set
+-# CONFIG_ARCH_IXP4XX is not set
+-# CONFIG_ARCH_IXP2000 is not set
+ # CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
+ # CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
+ # CONFIG_ARCH_PNX4008 is not set
+ # CONFIG_ARCH_PXA is not set
+ # CONFIG_ARCH_RPC is not set
+@@ -127,15 +138,27 @@ CONFIG_ARCH_AT91=y
+ # CONFIG_ARCH_S3C2410 is not set
+ # CONFIG_ARCH_SHARK is not set
+ # CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
+ # CONFIG_ARCH_OMAP is not set
+
+ #
++# Boot options
++#
++
++#
++# Power management
++#
++
++#
+ # Atmel AT91 System-on-Chip
+ #
+ # CONFIG_ARCH_AT91RM9200 is not set
+ # CONFIG_ARCH_AT91SAM9260 is not set
+ # CONFIG_ARCH_AT91SAM9261 is not set
+ CONFIG_ARCH_AT91SAM9263=y
++# CONFIG_ARCH_AT91SAM9RL is not set
++# CONFIG_ARCH_AT91X40 is not set
++CONFIG_AT91_PMC_UNIT=y
+
+ #
+ # AT91SAM9263 Board Type
+@@ -152,6 +175,8 @@ CONFIG_MTD_AT91_DATAFLASH_CARD=y
+ # AT91 Feature Selections
+ #
+ # CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
++# CONFIG_ATMEL_TCLIB is not set
++CONFIG_AT91_TIMER_HZ=100
+
+ #
+ # Processor Type
+@@ -174,19 +199,19 @@ CONFIG_CPU_CP15_MMU=y
+ # CONFIG_CPU_DCACHE_DISABLE is not set
+ # CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+ # CONFIG_CPU_CACHE_ROUND_ROBIN is not set
++# CONFIG_OUTER_CACHE is not set
+
+ #
+ # Bus support
+ #
+-
+-#
+-# PCCARD (PCMCIA/CardBus) support
+-#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
+ # CONFIG_PCCARD is not set
+
+ #
+ # Kernel Features
+ #
++# CONFIG_TICK_ONESHOT is not set
+ # CONFIG_PREEMPT is not set
+ # CONFIG_NO_IDLE_HZ is not set
+ CONFIG_HZ=100
+@@ -199,8 +224,12 @@ CONFIG_FLATMEM_MANUAL=y
+ CONFIG_FLATMEM=y
+ CONFIG_FLAT_NODE_MEM_MAP=y
+ # CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+ CONFIG_SPLIT_PTLOCK_CPUS=4096
+ # CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
+ # CONFIG_LEDS is not set
+ CONFIG_ALIGNMENT_TRAP=y
+
+@@ -211,6 +240,7 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
+ CONFIG_ZBOOT_ROM_BSS=0x0
+ CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
+ # CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
+
+ #
+ # Floating point emulation
+@@ -236,7 +266,7 @@ CONFIG_BINFMT_ELF=y
+ # Power management options
+ #
+ # CONFIG_PM is not set
+-# CONFIG_APM is not set
++CONFIG_SUSPEND_UP_POSSIBLE=y
+
+ #
+ # Networking
+@@ -246,7 +276,6 @@ CONFIG_NET=y
+ #
+ # Networking options
+ #
+-# CONFIG_NETDEBUG is not set
+ CONFIG_PACKET=y
+ # CONFIG_PACKET_MMAP is not set
+ CONFIG_UNIX=y
+@@ -271,6 +300,7 @@ CONFIG_IP_PNP_RARP=y
+ # CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+ # CONFIG_INET_XFRM_MODE_TUNNEL is not set
+ # CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
+ # CONFIG_INET_DIAG is not set
+ # CONFIG_TCP_CONG_ADVANCED is not set
+ CONFIG_TCP_CONG_CUBIC=y
+@@ -281,20 +311,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ # CONFIG_INET6_TUNNEL is not set
+ # CONFIG_NETWORK_SECMARK is not set
+ # CONFIG_NETFILTER is not set
+-
+-#
+-# DCCP Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_IP_DCCP is not set
+-
+-#
+-# SCTP Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_IP_SCTP is not set
+-
+-#
+-# TIPC Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_TIPC is not set
+ # CONFIG_ATM is not set
+ # CONFIG_BRIDGE is not set
+@@ -307,10 +325,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ # CONFIG_LAPB is not set
+ # CONFIG_ECONET is not set
+ # CONFIG_WAN_ROUTER is not set
+-
+-#
+-# QoS and/or fair queueing
+-#
+ # CONFIG_NET_SCHED is not set
+
+ #
+@@ -320,7 +334,17 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ # CONFIG_HAMRADIO is not set
+ # CONFIG_IRDA is not set
+ # CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
+ # CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
+
+ #
+ # Device Drivers
+@@ -329,20 +353,14 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ #
+ # Generic Driver Options
+ #
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+ CONFIG_STANDALONE=y
+ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ # CONFIG_FW_LOADER is not set
+ # CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
+ # CONFIG_SYS_HYPERVISOR is not set
+-
+-#
+-# Connector - unified userspace <-> kernelspace linker
+-#
+ # CONFIG_CONNECTOR is not set
+-
+-#
+-# Memory Technology Devices (MTD)
+-#
+ CONFIG_MTD=y
+ # CONFIG_MTD_DEBUG is not set
+ # CONFIG_MTD_CONCAT is not set
+@@ -362,6 +380,7 @@ CONFIG_MTD_BLOCK=y
+ # CONFIG_INFTL is not set
+ # CONFIG_RFD_FTL is not set
+ # CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
+
+ #
+ # RAM/ROM/Flash chip drivers
+@@ -381,7 +400,6 @@ CONFIG_MTD_CFI_I2=y
+ # CONFIG_MTD_RAM is not set
+ # CONFIG_MTD_ROM is not set
+ # CONFIG_MTD_ABSENT is not set
+-# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+ #
+ # Mapping drivers for chip access
+@@ -405,35 +423,24 @@ CONFIG_MTD_DATAFLASH=y
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOC2001PLUS is not set
+-
+-#
+-# NAND Flash Device Drivers
+-#
+ CONFIG_MTD_NAND=y
+ # CONFIG_MTD_NAND_VERIFY_WRITE is not set
+ # CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+ CONFIG_MTD_NAND_IDS=y
+ # CONFIG_MTD_NAND_DISKONCHIP is not set
+ CONFIG_MTD_NAND_AT91=y
+ # CONFIG_MTD_NAND_NANDSIM is not set
+-
+-#
+-# OneNAND Flash Device Drivers
+-#
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ALAUDA is not set
+ # CONFIG_MTD_ONENAND is not set
+
+ #
+-# Parallel port support
++# UBI - Unsorted block images
+ #
++# CONFIG_MTD_UBI is not set
+ # CONFIG_PARPORT is not set
+-
+-#
+-# Plug and Play support
+-#
+-
+-#
+-# Block devices
+-#
++CONFIG_BLK_DEV=y
+ # CONFIG_BLK_DEV_COW_COMMON is not set
+ CONFIG_BLK_DEV_LOOP=y
+ # CONFIG_BLK_DEV_CRYPTOLOOP is not set
+@@ -443,15 +450,18 @@ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_COUNT=16
+ CONFIG_BLK_DEV_RAM_SIZE=8192
+ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+-CONFIG_BLK_DEV_INITRD=y
+ # CONFIG_CDROM_PKTCDVD is not set
+ # CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++CONFIG_ATMEL_SSC=y
+
+ #
+ # SCSI device support
+ #
+ # CONFIG_RAID_ATTRS is not set
+ CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
+ # CONFIG_SCSI_TGT is not set
+ # CONFIG_SCSI_NETLINK is not set
+ CONFIG_SCSI_PROC_FS=y
+@@ -473,6 +483,7 @@ CONFIG_SCSI_MULTI_LUN=y
+ # CONFIG_SCSI_CONSTANTS is not set
+ # CONFIG_SCSI_LOGGING is not set
+ # CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
+
+ #
+ # SCSI Transports
+@@ -480,80 +491,65 @@ CONFIG_SCSI_MULTI_LUN=y
+ # CONFIG_SCSI_SPI_ATTRS is not set
+ # CONFIG_SCSI_FC_ATTRS is not set
+ # CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_ATTRS is not set
+ # CONFIG_SCSI_SAS_LIBSAS is not set
+-
+-#
+-# SCSI low-level drivers
+-#
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
+ # CONFIG_ISCSI_TCP is not set
+ # CONFIG_SCSI_DEBUG is not set
+-
+-#
+-# Serial ATA (prod) and Parallel ATA (experimental) drivers
+-#
+ # CONFIG_ATA is not set
+-
+-#
+-# Multi-device support (RAID and LVM)
+-#
+ # CONFIG_MD is not set
+-
+-#
+-# Fusion MPT device support
+-#
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-
+-#
+-# I2O device support
+-#
+-
+-#
+-# Network device support
+-#
+ CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
+ # CONFIG_DUMMY is not set
+ # CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
+ # CONFIG_EQUALIZER is not set
+ # CONFIG_TUN is not set
+-
+-#
+-# PHY device support
+-#
+-# CONFIG_PHYLIB is not set
+-
+-#
+-# Ethernet (10 or 100Mbit)
+-#
++# CONFIG_VETH is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
+ CONFIG_NET_ETHERNET=y
+ CONFIG_MII=y
++CONFIG_MACB=y
++# CONFIG_AX88796 is not set
+ # CONFIG_SMC91X is not set
+ # CONFIG_DM9000 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++CONFIG_NETDEV_10000=y
+
+ #
+-# Ethernet (1000 Mbit)
+-#
+-
+-#
+-# Ethernet (10000 Mbit)
+-#
+-
+-#
+-# Token Ring devices
+-#
+-
+-#
+-# Wireless LAN (non-hamradio)
++# Wireless LAN
+ #
+-# CONFIG_NET_RADIO is not set
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
+
+ #
+-# Wan interfaces
++# USB Network Adapters
+ #
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
+ # CONFIG_WAN is not set
+ # CONFIG_PPP is not set
+ # CONFIG_SLIP is not set
+@@ -561,10 +557,6 @@ CONFIG_MII=y
+ # CONFIG_NETCONSOLE is not set
+ # CONFIG_NETPOLL is not set
+ # CONFIG_NET_POLL_CONTROLLER is not set
+-
+-#
+-# ISDN subsystem
+-#
+ # CONFIG_ISDN is not set
+
+ #
+@@ -572,6 +564,7 @@ CONFIG_MII=y
+ #
+ CONFIG_INPUT=y
+ # CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
+
+ #
+ # Userland interfaces
+@@ -581,20 +574,26 @@ CONFIG_INPUT_MOUSEDEV=y
+ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ # CONFIG_INPUT_JOYDEV is not set
+-CONFIG_INPUT_TSDEV=y
+-CONFIG_INPUT_TSDEV_SCREEN_X=240
+-CONFIG_INPUT_TSDEV_SCREEN_Y=320
+ CONFIG_INPUT_EVDEV=y
+ # CONFIG_INPUT_EVBUG is not set
+
+ #
+ # Input Device Drivers
+ #
+-# CONFIG_INPUT_KEYBOARD is not set
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ATKBD is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++CONFIG_KEYBOARD_GPIO=y
+ # CONFIG_INPUT_MOUSE is not set
+ # CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
+ CONFIG_INPUT_TOUCHSCREEN=y
+ CONFIG_TOUCHSCREEN_ADS7846=y
++# CONFIG_TOUCHSCREEN_FUJITSU is not set
+ # CONFIG_TOUCHSCREEN_GUNZE is not set
+ # CONFIG_TOUCHSCREEN_ELO is not set
+ # CONFIG_TOUCHSCREEN_MTOUCH is not set
+@@ -603,6 +602,7 @@ CONFIG_TOUCHSCREEN_ADS7846=y
+ # CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+ # CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+ # CONFIG_TOUCHSCREEN_UCB1400 is not set
++# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+ # CONFIG_INPUT_MISC is not set
+
+ #
+@@ -636,71 +636,47 @@ CONFIG_SERIAL_CORE_CONSOLE=y
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_LEGACY_PTYS=y
+ CONFIG_LEGACY_PTY_COUNT=256
+-
+-#
+-# IPMI
+-#
+ # CONFIG_IPMI_HANDLER is not set
+-
+-#
+-# Watchdog Cards
+-#
+-CONFIG_WATCHDOG=y
+-CONFIG_WATCHDOG_NOWAYOUT=y
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-
+-#
+-# USB-based Watchdog Cards
+-#
+-# CONFIG_USBPCWATCHDOG is not set
+ CONFIG_HW_RANDOM=y
+ # CONFIG_NVRAM is not set
+-# CONFIG_DTLK is not set
+ # CONFIG_R3964 is not set
+ # CONFIG_RAW_DRIVER is not set
+-
+-#
+-# TPM devices
+-#
+ # CONFIG_TCG_TPM is not set
+-
+-#
+-# I2C support
+-#
+ CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
+ CONFIG_I2C_CHARDEV=y
+
+ #
+ # I2C Algorithms
+ #
+-# CONFIG_I2C_ALGOBIT is not set
++CONFIG_I2C_ALGOBIT=y
+ # CONFIG_I2C_ALGOPCF is not set
+ # CONFIG_I2C_ALGOPCA is not set
+
+ #
+ # I2C Hardware Bus support
+ #
+-CONFIG_I2C_AT91=y
++CONFIG_I2C_GPIO=y
+ # CONFIG_I2C_OCORES is not set
+ # CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
+ # CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
+ # CONFIG_I2C_PCA is not set
+-# CONFIG_I2C_PCA_ISA is not set
+
+ #
+ # Miscellaneous I2C Chip support
+ #
+ # CONFIG_SENSORS_DS1337 is not set
+ # CONFIG_SENSORS_DS1374 is not set
++# CONFIG_DS1682 is not set
+ # CONFIG_SENSORS_EEPROM is not set
+ # CONFIG_SENSORS_PCF8574 is not set
+ # CONFIG_SENSORS_PCA9539 is not set
+ # CONFIG_SENSORS_PCF8591 is not set
+ # CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
+ # CONFIG_I2C_DEBUG_CORE is not set
+ # CONFIG_I2C_DEBUG_ALGO is not set
+ # CONFIG_I2C_DEBUG_BUS is not set
+@@ -722,61 +698,80 @@ CONFIG_SPI_ATMEL=y
+ #
+ # SPI Protocol Masters
+ #
+-
+-#
+-# Dallas's 1-wire bus
+-#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
+ # CONFIG_W1 is not set
+-
+-#
+-# Hardware Monitoring support
+-#
++# CONFIG_POWER_SUPPLY is not set
+ # CONFIG_HWMON is not set
+-# CONFIG_HWMON_VID is not set
++CONFIG_WATCHDOG=y
++CONFIG_WATCHDOG_NOWAYOUT=y
+
+ #
+-# Misc devices
++# Watchdog Device Drivers
+ #
+-# CONFIG_TIFM_CORE is not set
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_AT91SAM9_WATCHDOG=y
+
+ #
+-# LED devices
++# USB-based Watchdog Cards
+ #
+-# CONFIG_NEW_LEDS is not set
++# CONFIG_USBPCWATCHDOG is not set
+
+ #
+-# LED drivers
++# Sonics Silicon Backplane
+ #
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
+
+ #
+-# LED Triggers
++# Multifunction device drivers
+ #
++# CONFIG_MFD_SM501 is not set
+
+ #
+ # Multimedia devices
+ #
+ # CONFIG_VIDEO_DEV is not set
+-
+-#
+-# Digital Video Broadcasting Devices
+-#
+-# CONFIG_DVB is not set
+-# CONFIG_USB_DABUSB is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
+
+ #
+ # Graphics support
+ #
+-# CONFIG_FIRMWARE_EDID is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+ CONFIG_FB=y
+-# CONFIG_FB_CFB_FILLRECT is not set
+-# CONFIG_FB_CFB_COPYAREA is not set
+-# CONFIG_FB_CFB_IMAGEBLIT is not set
++# CONFIG_FIRMWARE_EDID is not set
++# CONFIG_FB_DDC is not set
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
++# CONFIG_FB_SYS_FILLRECT is not set
++# CONFIG_FB_SYS_COPYAREA is not set
++# CONFIG_FB_SYS_IMAGEBLIT is not set
++# CONFIG_FB_SYS_FOPS is not set
++CONFIG_FB_DEFERRED_IO=y
++# CONFIG_FB_SVGALIB is not set
+ # CONFIG_FB_MACMODES is not set
+ # CONFIG_FB_BACKLIGHT is not set
+ # CONFIG_FB_MODE_HELPERS is not set
+ # CONFIG_FB_TILEBLITTING is not set
++
++#
++# Frame buffer hardware drivers
++#
++# CONFIG_FB_S1D15605 is not set
+ # CONFIG_FB_S1D13XXX is not set
++CONFIG_FB_ATMEL=y
+ # CONFIG_FB_VIRTUAL is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
+
+ #
+ # Console display driver support
+@@ -784,26 +779,28 @@ CONFIG_FB=y
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+ # CONFIG_FRAMEBUFFER_CONSOLE is not set
+-
+-#
+-# Logo configuration
+-#
+ # CONFIG_LOGO is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Sound
+ #
+ # CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
+
+ #
+-# HID Devices
++# USB Input Devices
+ #
+-CONFIG_HID=y
++# CONFIG_USB_HID is not set
+
+ #
+-# USB support
++# USB HID Boot Protocol drivers
+ #
++# CONFIG_USB_KBD is not set
++# CONFIG_USB_MOUSE is not set
++CONFIG_USB_SUPPORT=y
+ CONFIG_USB_ARCH_HAS_HCD=y
+ CONFIG_USB_ARCH_HAS_OHCI=y
+ # CONFIG_USB_ARCH_HAS_EHCI is not set
+@@ -814,9 +811,8 @@ CONFIG_USB=y
+ # Miscellaneous USB options
+ #
+ CONFIG_USB_DEVICEFS=y
+-# CONFIG_USB_BANDWIDTH is not set
++CONFIG_USB_DEVICE_CLASS=y
+ # CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_MULTITHREAD_PROBE is not set
+ # CONFIG_USB_OTG is not set
+
+ #
+@@ -824,9 +820,11 @@ CONFIG_USB_DEVICEFS=y
+ #
+ # CONFIG_USB_ISP116X_HCD is not set
+ CONFIG_USB_OHCI_HCD=y
+-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+ # CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
+
+ #
+ # USB Device Class drivers
+@@ -845,6 +843,7 @@ CONFIG_USB_STORAGE=y
+ # CONFIG_USB_STORAGE_DEBUG is not set
+ # CONFIG_USB_STORAGE_DATAFAB is not set
+ # CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
+ # CONFIG_USB_STORAGE_DPCM is not set
+ # CONFIG_USB_STORAGE_USBAT is not set
+ # CONFIG_USB_STORAGE_SDDR09 is not set
+@@ -856,43 +855,10 @@ CONFIG_USB_STORAGE=y
+ # CONFIG_USB_LIBUSUAL is not set
+
+ #
+-# USB Input Devices
+-#
+-# CONFIG_USB_HID is not set
+-
+-#
+-# USB HID Boot Protocol drivers
+-#
+-# CONFIG_USB_KBD is not set
+-# CONFIG_USB_MOUSE is not set
+-# CONFIG_USB_AIPTEK is not set
+-# CONFIG_USB_WACOM is not set
+-# CONFIG_USB_ACECAD is not set
+-# CONFIG_USB_KBTAB is not set
+-# CONFIG_USB_POWERMATE is not set
+-# CONFIG_USB_TOUCHSCREEN is not set
+-# CONFIG_USB_YEALINK is not set
+-# CONFIG_USB_XPAD is not set
+-# CONFIG_USB_ATI_REMOTE is not set
+-# CONFIG_USB_ATI_REMOTE2 is not set
+-# CONFIG_USB_KEYSPAN_REMOTE is not set
+-# CONFIG_USB_APPLETOUCH is not set
+-
+-#
+ # USB Imaging devices
+ #
+ # CONFIG_USB_MDC800 is not set
+ # CONFIG_USB_MICROTEK is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET_MII is not set
+-# CONFIG_USB_USBNET is not set
+ CONFIG_USB_MON=y
+
+ #
+@@ -914,6 +880,7 @@ CONFIG_USB_MON=y
+ # CONFIG_USB_RIO500 is not set
+ # CONFIG_USB_LEGOTOWER is not set
+ # CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
+ # CONFIG_USB_LED is not set
+ # CONFIG_USB_CYPRESS_CY7C63 is not set
+ # CONFIG_USB_CYTHERM is not set
+@@ -923,6 +890,7 @@ CONFIG_USB_MON=y
+ # CONFIG_USB_APPLEDISPLAY is not set
+ # CONFIG_USB_LD is not set
+ # CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
+ # CONFIG_USB_TEST is not set
+
+ #
+@@ -933,13 +901,19 @@ CONFIG_USB_MON=y
+ # USB Gadget Support
+ #
+ CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG is not set
+ # CONFIG_USB_GADGET_DEBUG_FILES is not set
+ CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_ATMEL_USBA is not set
++# CONFIG_USB_GADGET_FSL_USB2 is not set
+ # CONFIG_USB_GADGET_NET2280 is not set
+ # CONFIG_USB_GADGET_PXA2XX is not set
++# CONFIG_USB_GADGET_M66592 is not set
+ # CONFIG_USB_GADGET_GOKU is not set
+ # CONFIG_USB_GADGET_LH7A40X is not set
+ # CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_S3C2410 is not set
+ CONFIG_USB_GADGET_AT91=y
+ CONFIG_USB_AT91=y
+ # CONFIG_USB_GADGET_DUMMY_HCD is not set
+@@ -951,21 +925,73 @@ CONFIG_USB_FILE_STORAGE=m
+ # CONFIG_USB_FILE_STORAGE_TEST is not set
+ CONFIG_USB_G_SERIAL=m
+ # CONFIG_USB_MIDI_GADGET is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
+
+ #
+-# MMC/SD Card support
++# MMC/SD Card Drivers
+ #
+-CONFIG_MMC=y
+-# CONFIG_MMC_DEBUG is not set
+ CONFIG_MMC_BLOCK=y
+-CONFIG_MMC_AT91=m
+-# CONFIG_MMC_TIFM_SD is not set
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
+
+ #
+-# Real Time Clock
++# MMC/SD Host Controller Drivers
+ #
++CONFIG_MMC_AT91=m
++# CONFIG_MMC_SPI is not set
++# CONFIG_NEW_LEDS is not set
+ CONFIG_RTC_LIB=y
+-# CONFIG_RTC_CLASS is not set
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_AT91SAM9=y
+
+ #
+ # File systems
+@@ -1016,7 +1042,6 @@ CONFIG_SYSFS=y
+ CONFIG_TMPFS=y
+ # CONFIG_TMPFS_POSIX_ACL is not set
+ # CONFIG_HUGETLB_PAGE is not set
+-CONFIG_RAMFS=y
+ # CONFIG_CONFIGFS_FS is not set
+
+ #
+@@ -1032,10 +1057,12 @@ CONFIG_RAMFS=y
+ CONFIG_JFFS2_FS=y
+ CONFIG_JFFS2_FS_DEBUG=0
+ CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+ # CONFIG_JFFS2_SUMMARY is not set
+ # CONFIG_JFFS2_FS_XATTR is not set
+ # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+ CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
+ CONFIG_JFFS2_RTIME=y
+ # CONFIG_JFFS2_RUBIN is not set
+ CONFIG_CRAMFS=y
+@@ -1044,10 +1071,7 @@ CONFIG_CRAMFS=y
+ # CONFIG_QNX4FS_FS is not set
+ # CONFIG_SYSV_FS is not set
+ # CONFIG_UFS_FS is not set
+-
+-#
+-# Network File Systems
+-#
++CONFIG_NETWORK_FILESYSTEMS=y
+ CONFIG_NFS_FS=y
+ # CONFIG_NFS_V3 is not set
+ # CONFIG_NFS_V4 is not set
+@@ -1057,6 +1081,7 @@ CONFIG_ROOT_NFS=y
+ CONFIG_LOCKD=y
+ CONFIG_NFS_COMMON=y
+ CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
+ # CONFIG_RPCSEC_GSS_KRB5 is not set
+ # CONFIG_RPCSEC_GSS_SPKM3 is not set
+ # CONFIG_SMB_FS is not set
+@@ -1064,17 +1089,12 @@ CONFIG_SUNRPC=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
+-# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+ #
+ # CONFIG_PARTITION_ADVANCED is not set
+ CONFIG_MSDOS_PARTITION=y
+-
+-#
+-# Native Language Support
+-#
+ CONFIG_NLS=y
+ CONFIG_NLS_DEFAULT="iso8859-1"
+ CONFIG_NLS_CODEPAGE_437=y
+@@ -1115,36 +1135,35 @@ CONFIG_NLS_ISO8859_1=y
+ # CONFIG_NLS_KOI8_R is not set
+ # CONFIG_NLS_KOI8_U is not set
+ # CONFIG_NLS_UTF8 is not set
+-
+-#
+-# Distributed Lock Manager
+-#
+ # CONFIG_DLM is not set
+-
+-#
+-# Profiling support
+-#
++CONFIG_INSTRUMENTATION=y
+ # CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
+
+ #
+ # Kernel hacking
+ #
+ # CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
+ CONFIG_ENABLE_MUST_CHECK=y
+ # CONFIG_MAGIC_SYSRQ is not set
+ # CONFIG_UNUSED_SYMBOLS is not set
+ # CONFIG_DEBUG_FS is not set
+ # CONFIG_HEADERS_CHECK is not set
+ CONFIG_DEBUG_KERNEL=y
+-CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_DEBUG_SHIRQ is not set
+ CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
+ # CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
+ # CONFIG_DEBUG_SLAB is not set
+ # CONFIG_DEBUG_RT_MUTEXES is not set
+ # CONFIG_RT_MUTEX_TESTER is not set
+ # CONFIG_DEBUG_SPINLOCK is not set
+ # CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_RWSEMS is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
+ # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+ # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+ # CONFIG_DEBUG_KOBJECT is not set
+@@ -1152,9 +1171,13 @@ CONFIG_DEBUG_BUGVERBOSE=y
+ # CONFIG_DEBUG_INFO is not set
+ # CONFIG_DEBUG_VM is not set
+ # CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
+ CONFIG_FRAME_POINTER=y
+ CONFIG_FORCED_INLINING=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
+ # CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
+ CONFIG_DEBUG_USER=y
+ # CONFIG_DEBUG_ERRORS is not set
+ CONFIG_DEBUG_LL=y
+@@ -1165,10 +1188,7 @@ CONFIG_DEBUG_LL=y
+ #
+ # CONFIG_KEYS is not set
+ # CONFIG_SECURITY is not set
+-
+-#
+-# Cryptographic options
+-#
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+ # CONFIG_CRYPTO is not set
+
+ #
+@@ -1177,8 +1197,13 @@ CONFIG_DEBUG_LL=y
+ CONFIG_BITREVERSE=y
+ # CONFIG_CRC_CCITT is not set
+ # CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
+ CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
+ # CONFIG_LIBCRC32C is not set
+ CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
+ CONFIG_PLIST=y
+-CONFIG_IOMAP_COPY=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/at91sam9rlek_defconfig b/arch/arm/configs/at91sam9rlek_defconfig
+index fbe8b30..98e6746 100644
+--- a/arch/arm/configs/at91sam9rlek_defconfig
++++ b/arch/arm/configs/at91sam9rlek_defconfig
+@@ -1,15 +1,18 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.21
+-# Mon May 7 16:30:40 2007
++# Linux kernel version: 2.6.24-rc7
++# Tue Jan 8 22:24:14 2008
+ #
+ CONFIG_ARM=y
+ CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+ CONFIG_GENERIC_GPIO=y
+ # CONFIG_GENERIC_TIME is not set
++# CONFIG_GENERIC_CLOCKEVENTS is not set
+ CONFIG_MMU=y
+ # CONFIG_NO_IOPORT is not set
+ CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
+ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+ CONFIG_HARDIRQS_SW_RESEND=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+@@ -23,27 +26,28 @@ CONFIG_VECTORS_BASE=0xffff0000
+ CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+ #
+-# Code maturity level options
++# General setup
+ #
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_BROKEN_ON_SMP=y
+ CONFIG_INIT_ENV_ARG_LIMIT=32
+-
+-#
+-# General setup
+-#
+ CONFIG_LOCALVERSION=""
+ # CONFIG_LOCALVERSION_AUTO is not set
+ # CONFIG_SWAP is not set
+ CONFIG_SYSVIPC=y
+-# CONFIG_IPC_NS is not set
+ CONFIG_SYSVIPC_SYSCTL=y
+ # CONFIG_POSIX_MQUEUE is not set
+ # CONFIG_BSD_PROCESS_ACCT is not set
+ # CONFIG_TASKSTATS is not set
+-# CONFIG_UTS_NS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
+ # CONFIG_AUDIT is not set
+ # CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
+ CONFIG_SYSFS_DEPRECATED=y
+ # CONFIG_RELAY is not set
+ CONFIG_BLK_DEV_INITRD=y
+@@ -62,32 +66,30 @@ CONFIG_BUG=y
+ CONFIG_ELF_CORE=y
+ CONFIG_BASE_FULL=y
+ CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
+ CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
+ CONFIG_SHMEM=y
+-CONFIG_SLAB=y
+ CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_SLABINFO=y
+ CONFIG_RT_MUTEXES=y
+ # CONFIG_TINY_SHMEM is not set
+ CONFIG_BASE_SMALL=0
+-# CONFIG_SLOB is not set
+-
+-#
+-# Loadable module support
+-#
+ CONFIG_MODULES=y
+ CONFIG_MODULE_UNLOAD=y
+ # CONFIG_MODULE_FORCE_UNLOAD is not set
+ # CONFIG_MODVERSIONS is not set
+ # CONFIG_MODULE_SRCVERSION_ALL is not set
+ CONFIG_KMOD=y
+-
+-#
+-# Block layer
+-#
+ CONFIG_BLOCK=y
+ # CONFIG_LBD is not set
+ # CONFIG_BLK_DEV_IO_TRACE is not set
+ # CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
+
+ #
+ # IO Schedulers
+@@ -119,14 +121,16 @@ CONFIG_ARCH_AT91=y
+ # CONFIG_ARCH_NETX is not set
+ # CONFIG_ARCH_H720X is not set
+ # CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
+ # CONFIG_ARCH_IOP32X is not set
+ # CONFIG_ARCH_IOP33X is not set
+-# CONFIG_ARCH_IOP13XX is not set
+-# CONFIG_ARCH_IXP4XX is not set
+-# CONFIG_ARCH_IXP2000 is not set
+ # CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
+ # CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
+ # CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
+ # CONFIG_ARCH_PNX4008 is not set
+ # CONFIG_ARCH_PXA is not set
+ # CONFIG_ARCH_RPC is not set
+@@ -134,9 +138,18 @@ CONFIG_ARCH_AT91=y
+ # CONFIG_ARCH_S3C2410 is not set
+ # CONFIG_ARCH_SHARK is not set
+ # CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
+ # CONFIG_ARCH_OMAP is not set
+
+ #
++# Boot options
++#
++
++#
++# Power management
++#
++
++#
+ # Atmel AT91 System-on-Chip
+ #
+ # CONFIG_ARCH_AT91RM9200 is not set
+@@ -144,6 +157,8 @@ CONFIG_ARCH_AT91=y
+ # CONFIG_ARCH_AT91SAM9261 is not set
+ # CONFIG_ARCH_AT91SAM9263 is not set
+ CONFIG_ARCH_AT91SAM9RL=y
++# CONFIG_ARCH_AT91X40 is not set
++CONFIG_AT91_PMC_UNIT=y
+
+ #
+ # AT91SAM9RL Board Type
+@@ -157,7 +172,9 @@ CONFIG_MACH_AT91SAM9RLEK=y
+ #
+ # AT91 Feature Selections
+ #
+-# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
++CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
++# CONFIG_ATMEL_TCLIB is not set
++CONFIG_AT91_TIMER_HZ=100
+
+ #
+ # Processor Type
+@@ -185,15 +202,14 @@ CONFIG_CPU_CP15_MMU=y
+ #
+ # Bus support
+ #
+-
+-#
+-# PCCARD (PCMCIA/CardBus) support
+-#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
+ # CONFIG_PCCARD is not set
+
+ #
+ # Kernel Features
+ #
++# CONFIG_TICK_ONESHOT is not set
+ # CONFIG_PREEMPT is not set
+ # CONFIG_NO_IDLE_HZ is not set
+ CONFIG_HZ=100
+@@ -206,9 +222,12 @@ CONFIG_FLATMEM_MANUAL=y
+ CONFIG_FLATMEM=y
+ CONFIG_FLAT_NODE_MEM_MAP=y
+ # CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+ CONFIG_SPLIT_PTLOCK_CPUS=4096
+ # CONFIG_RESOURCES_64BIT is not set
+ CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
+ # CONFIG_LEDS is not set
+ CONFIG_ALIGNMENT_TRAP=y
+
+@@ -245,6 +264,7 @@ CONFIG_BINFMT_ELF=y
+ # Power management options
+ #
+ # CONFIG_PM is not set
++CONFIG_SUSPEND_UP_POSSIBLE=y
+
+ #
+ # Networking
+@@ -254,7 +274,6 @@ CONFIG_NET=y
+ #
+ # Networking options
+ #
+-# CONFIG_NETDEBUG is not set
+ # CONFIG_PACKET is not set
+ CONFIG_UNIX=y
+ # CONFIG_NET_KEY is not set
+@@ -271,10 +290,6 @@ CONFIG_UNIX=y
+ # CONFIG_X25 is not set
+ # CONFIG_LAPB is not set
+ # CONFIG_WAN_ROUTER is not set
+-
+-#
+-# QoS and/or fair queueing
+-#
+ # CONFIG_NET_SCHED is not set
+
+ #
+@@ -284,7 +299,16 @@ CONFIG_UNIX=y
+ # CONFIG_HAMRADIO is not set
+ # CONFIG_IRDA is not set
+ # CONFIG_BT is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
+ # CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
+
+ #
+ # Device Drivers
+@@ -293,21 +317,14 @@ CONFIG_UNIX=y
+ #
+ # Generic Driver Options
+ #
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+ CONFIG_STANDALONE=y
+ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ # CONFIG_FW_LOADER is not set
+ # CONFIG_DEBUG_DRIVER is not set
+ # CONFIG_DEBUG_DEVRES is not set
+ # CONFIG_SYS_HYPERVISOR is not set
+-
+-#
+-# Connector - unified userspace <-> kernelspace linker
+-#
+ # CONFIG_CONNECTOR is not set
+-
+-#
+-# Memory Technology Devices (MTD)
+-#
+ CONFIG_MTD=y
+ # CONFIG_MTD_DEBUG is not set
+ CONFIG_MTD_CONCAT=y
+@@ -327,6 +344,7 @@ CONFIG_MTD_BLOCK=y
+ # CONFIG_INFTL is not set
+ # CONFIG_RFD_FTL is not set
+ # CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
+
+ #
+ # RAM/ROM/Flash chip drivers
+@@ -346,7 +364,6 @@ CONFIG_MTD_CFI_I2=y
+ # CONFIG_MTD_RAM is not set
+ # CONFIG_MTD_ROM is not set
+ # CONFIG_MTD_ABSENT is not set
+-# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+ #
+ # Mapping drivers for chip access
+@@ -370,36 +387,23 @@ CONFIG_MTD_DATAFLASH=y
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOC2001PLUS is not set
+-
+-#
+-# NAND Flash Device Drivers
+-#
+ CONFIG_MTD_NAND=y
+ # CONFIG_MTD_NAND_VERIFY_WRITE is not set
+ # CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+ CONFIG_MTD_NAND_IDS=y
+ # CONFIG_MTD_NAND_DISKONCHIP is not set
+ CONFIG_MTD_NAND_AT91=y
+ # CONFIG_MTD_NAND_NANDSIM is not set
+-
+-#
+-# OneNAND Flash Device Drivers
+-#
++# CONFIG_MTD_NAND_PLATFORM is not set
+ # CONFIG_MTD_ONENAND is not set
+
+ #
+-# Parallel port support
++# UBI - Unsorted block images
+ #
++# CONFIG_MTD_UBI is not set
+ # CONFIG_PARPORT is not set
+-
+-#
+-# Plug and Play support
+-#
+-# CONFIG_PNPACPI is not set
+-
+-#
+-# Block devices
+-#
++CONFIG_BLK_DEV=y
+ # CONFIG_BLK_DEV_COW_COMMON is not set
+ CONFIG_BLK_DEV_LOOP=y
+ # CONFIG_BLK_DEV_CRYPTOLOOP is not set
+@@ -410,12 +414,16 @@ CONFIG_BLK_DEV_RAM_SIZE=24576
+ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+ # CONFIG_CDROM_PKTCDVD is not set
+ # CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++CONFIG_ATMEL_SSC=y
+
+ #
+ # SCSI device support
+ #
+ # CONFIG_RAID_ATTRS is not set
+ CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
+ # CONFIG_SCSI_TGT is not set
+ # CONFIG_SCSI_NETLINK is not set
+ CONFIG_SCSI_PROC_FS=y
+@@ -437,6 +445,7 @@ CONFIG_SCSI_MULTI_LUN=y
+ # CONFIG_SCSI_CONSTANTS is not set
+ # CONFIG_SCSI_LOGGING is not set
+ # CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
+
+ #
+ # SCSI Transports
+@@ -444,47 +453,13 @@ CONFIG_SCSI_MULTI_LUN=y
+ # CONFIG_SCSI_SPI_ATTRS is not set
+ # CONFIG_SCSI_FC_ATTRS is not set
+ # CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_ATTRS is not set
+ # CONFIG_SCSI_SAS_LIBSAS is not set
+-
+-#
+-# SCSI low-level drivers
+-#
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
+ # CONFIG_SCSI_DEBUG is not set
+-
+-#
+-# Serial ATA (prod) and Parallel ATA (experimental) drivers
+-#
+ # CONFIG_ATA is not set
+-
+-#
+-# Multi-device support (RAID and LVM)
+-#
+ # CONFIG_MD is not set
+-
+-#
+-# Fusion MPT device support
+-#
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-
+-#
+-# I2O device support
+-#
+-
+-#
+-# Network device support
+-#
+ # CONFIG_NETDEVICES is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-
+-#
+-# ISDN subsystem
+-#
+ # CONFIG_ISDN is not set
+
+ #
+@@ -492,6 +467,7 @@ CONFIG_SCSI_MULTI_LUN=y
+ #
+ CONFIG_INPUT=y
+ # CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
+
+ #
+ # Userland interfaces
+@@ -501,7 +477,6 @@ CONFIG_INPUT_MOUSEDEV=y
+ CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
+ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
+ # CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_TSDEV is not set
+ CONFIG_INPUT_EVDEV=y
+ # CONFIG_INPUT_EVBUG is not set
+
+@@ -511,8 +486,10 @@ CONFIG_INPUT_EVDEV=y
+ # CONFIG_INPUT_KEYBOARD is not set
+ # CONFIG_INPUT_MOUSE is not set
+ # CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
+ CONFIG_INPUT_TOUCHSCREEN=y
+ # CONFIG_TOUCHSCREEN_ADS7846 is not set
++# CONFIG_TOUCHSCREEN_FUJITSU is not set
+ # CONFIG_TOUCHSCREEN_GUNZE is not set
+ # CONFIG_TOUCHSCREEN_ELO is not set
+ # CONFIG_TOUCHSCREEN_MTOUCH is not set
+@@ -521,6 +498,7 @@ CONFIG_INPUT_TOUCHSCREEN=y
+ # CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+ # CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+ # CONFIG_TOUCHSCREEN_UCB1400 is not set
++# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+ # CONFIG_INPUT_MISC is not set
+
+ #
+@@ -554,37 +532,50 @@ CONFIG_SERIAL_CORE_CONSOLE=y
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_LEGACY_PTYS=y
+ CONFIG_LEGACY_PTY_COUNT=256
+-
+-#
+-# IPMI
+-#
+ # CONFIG_IPMI_HANDLER is not set
+-
+-#
+-# Watchdog Cards
+-#
+-CONFIG_WATCHDOG=y
+-CONFIG_WATCHDOG_NOWAYOUT=y
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_HW_RANDOM=y
++# CONFIG_HW_RANDOM is not set
+ # CONFIG_NVRAM is not set
+-# CONFIG_DTLK is not set
+ # CONFIG_R3964 is not set
+ # CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
+
+ #
+-# TPM devices
++# I2C Algorithms
+ #
+-# CONFIG_TCG_TPM is not set
++CONFIG_I2C_ALGOBIT=y
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
+
+ #
+-# I2C support
++# I2C Hardware Bus support
+ #
+-# CONFIG_I2C is not set
++CONFIG_I2C_GPIO=y
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_PCA is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_SENSORS_DS1337 is not set
++# CONFIG_SENSORS_DS1374 is not set
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
+
+ #
+ # SPI support
+@@ -603,21 +594,25 @@ CONFIG_SPI_ATMEL=y
+ # SPI Protocol Masters
+ #
+ # CONFIG_SPI_AT25 is not set
+-
+-#
+-# Dallas's 1-wire bus
+-#
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
+ # CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_WATCHDOG=y
++CONFIG_WATCHDOG_NOWAYOUT=y
+
+ #
+-# Hardware Monitoring support
++# Watchdog Device Drivers
+ #
+-# CONFIG_HWMON is not set
+-# CONFIG_HWMON_VID is not set
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_AT91SAM9_WATCHDOG=y
+
+ #
+-# Misc devices
++# Sonics Silicon Backplane
+ #
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
+
+ #
+ # Multifunction device drivers
+@@ -625,37 +620,28 @@ CONFIG_SPI_ATMEL=y
+ # CONFIG_MFD_SM501 is not set
+
+ #
+-# LED devices
+-#
+-# CONFIG_NEW_LEDS is not set
+-
+-#
+-# LED drivers
+-#
+-
+-#
+-# LED Triggers
+-#
+-
+-#
+ # Multimedia devices
+ #
+ # CONFIG_VIDEO_DEV is not set
+-
+-#
+-# Digital Video Broadcasting Devices
+-#
++# CONFIG_DAB is not set
+
+ #
+ # Graphics support
+ #
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+ CONFIG_FB=y
+ # CONFIG_FIRMWARE_EDID is not set
+ # CONFIG_FB_DDC is not set
+ CONFIG_FB_CFB_FILLRECT=y
+ CONFIG_FB_CFB_COPYAREA=y
+ CONFIG_FB_CFB_IMAGEBLIT=y
++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
++# CONFIG_FB_SYS_FILLRECT is not set
++# CONFIG_FB_SYS_COPYAREA is not set
++# CONFIG_FB_SYS_IMAGEBLIT is not set
++# CONFIG_FB_SYS_FOPS is not set
++CONFIG_FB_DEFERRED_IO=y
+ # CONFIG_FB_SVGALIB is not set
+ # CONFIG_FB_MACMODES is not set
+ # CONFIG_FB_BACKLIGHT is not set
+@@ -665,9 +651,16 @@ CONFIG_FB_CFB_IMAGEBLIT=y
+ #
+ # Frame buffer hardware drivers
+ #
++# CONFIG_FB_S1D15605 is not set
+ # CONFIG_FB_S1D13XXX is not set
+ CONFIG_FB_ATMEL=y
+ # CONFIG_FB_VIRTUAL is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
+
+ #
+ # Console display driver support
+@@ -675,97 +668,97 @@ CONFIG_FB_ATMEL=y
+ # CONFIG_VGA_CONSOLE is not set
+ CONFIG_DUMMY_CONSOLE=y
+ # CONFIG_FRAMEBUFFER_CONSOLE is not set
+-
+-#
+-# Logo configuration
+-#
+ # CONFIG_LOGO is not set
+
+ #
+ # Sound
+ #
+-CONFIG_SOUND=y
+-
+-#
+-# Advanced Linux Sound Architecture
+-#
+-CONFIG_SND=y
+-CONFIG_SND_TIMER=y
+-CONFIG_SND_PCM=y
+-CONFIG_SND_SEQUENCER=y
+-CONFIG_SND_SEQ_DUMMY=y
+-CONFIG_SND_OSSEMUL=y
+-CONFIG_SND_MIXER_OSS=y
+-CONFIG_SND_PCM_OSS=y
+-CONFIG_SND_PCM_OSS_PLUGINS=y
+-CONFIG_SND_SEQUENCER_OSS=y
+-# CONFIG_SND_DYNAMIC_MINORS is not set
+-CONFIG_SND_SUPPORT_OLD_API=y
+-CONFIG_SND_VERBOSE_PROCFS=y
+-CONFIG_SND_VERBOSE_PRINTK=y
+-CONFIG_SND_DEBUG=y
+-CONFIG_SND_DEBUG_DETECT=y
+-# CONFIG_SND_PCM_XRUN_DEBUG is not set
+-
+-#
+-# Generic devices
+-#
+-# CONFIG_SND_DUMMY is not set
+-# CONFIG_SND_VIRMIDI is not set
+-# CONFIG_SND_MTPAV is not set
+-# CONFIG_SND_SERIAL_U16550 is not set
+-# CONFIG_SND_MPU401 is not set
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++# CONFIG_USB is not set
+
+ #
+-# ALSA ARM devices
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+ #
+
+ #
+-# SoC audio support
++# USB Gadget Support
+ #
+-# CONFIG_SND_SOC is not set
++# CONFIG_USB_GADGET is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
+
+ #
+-# Open Sound System
++# MMC/SD Card Drivers
+ #
+-# CONFIG_SOUND_PRIME is not set
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
+
+ #
+-# HID Devices
++# MMC/SD Host Controller Drivers
+ #
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
++CONFIG_MMC_AT91=y
++# CONFIG_MMC_SPI is not set
++# CONFIG_NEW_LEDS is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
+
+ #
+-# USB support
++# RTC interfaces
+ #
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-# CONFIG_USB_ARCH_HAS_EHCI is not set
+-# CONFIG_USB is not set
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
+
+ #
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++# I2C RTC drivers
+ #
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
+
+ #
+-# USB Gadget Support
++# SPI RTC drivers
+ #
+-# CONFIG_USB_GADGET is not set
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
+
+ #
+-# MMC/SD Card support
++# Platform RTC drivers
+ #
+-CONFIG_MMC=y
+-# CONFIG_MMC_DEBUG is not set
+-CONFIG_MMC_BLOCK=y
+-CONFIG_MMC_AT91=y
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
+
+ #
+-# Real Time Clock
++# on-CPU RTC drivers
+ #
+-CONFIG_RTC_LIB=y
+-# CONFIG_RTC_CLASS is not set
++CONFIG_RTC_DRV_AT91SAM9=y
+
+ #
+ # File systems
+@@ -816,7 +809,6 @@ CONFIG_SYSFS=y
+ CONFIG_TMPFS=y
+ # CONFIG_TMPFS_POSIX_ACL is not set
+ # CONFIG_HUGETLB_PAGE is not set
+-CONFIG_RAMFS=y
+ # CONFIG_CONFIGFS_FS is not set
+
+ #
+@@ -836,20 +828,13 @@ CONFIG_CRAMFS=y
+ # CONFIG_QNX4FS_FS is not set
+ # CONFIG_SYSV_FS is not set
+ # CONFIG_UFS_FS is not set
+-
+-#
+-# Network File Systems
+-#
++CONFIG_NETWORK_FILESYSTEMS=y
+
+ #
+ # Partition Types
+ #
+ # CONFIG_PARTITION_ADVANCED is not set
+ CONFIG_MSDOS_PARTITION=y
+-
+-#
+-# Native Language Support
+-#
+ CONFIG_NLS=y
+ CONFIG_NLS_DEFAULT="iso8859-1"
+ CONFIG_NLS_CODEPAGE_437=y
+@@ -890,16 +875,15 @@ CONFIG_NLS_ISO8859_15=y
+ # CONFIG_NLS_KOI8_R is not set
+ # CONFIG_NLS_KOI8_U is not set
+ CONFIG_NLS_UTF8=y
+-
+-#
+-# Profiling support
+-#
++CONFIG_INSTRUMENTATION=y
+ # CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
+
+ #
+ # Kernel hacking
+ #
+ # CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
+ CONFIG_ENABLE_MUST_CHECK=y
+ # CONFIG_MAGIC_SYSRQ is not set
+ # CONFIG_UNUSED_SYMBOLS is not set
+@@ -907,8 +891,8 @@ CONFIG_ENABLE_MUST_CHECK=y
+ # CONFIG_HEADERS_CHECK is not set
+ CONFIG_DEBUG_KERNEL=y
+ # CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_LOG_BUF_SHIFT=14
+ CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
+ # CONFIG_SCHEDSTATS is not set
+ # CONFIG_TIMER_STATS is not set
+ # CONFIG_DEBUG_SLAB is not set
+@@ -916,6 +900,9 @@ CONFIG_DETECT_SOFTLOCKUP=y
+ # CONFIG_RT_MUTEX_TESTER is not set
+ # CONFIG_DEBUG_SPINLOCK is not set
+ # CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
+ # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+ # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+ # CONFIG_DEBUG_KOBJECT is not set
+@@ -923,10 +910,13 @@ CONFIG_DEBUG_BUGVERBOSE=y
+ CONFIG_DEBUG_INFO=y
+ # CONFIG_DEBUG_VM is not set
+ # CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
+ CONFIG_FRAME_POINTER=y
+ CONFIG_FORCED_INLINING=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
+ # CONFIG_RCU_TORTURE_TEST is not set
+ # CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
+ CONFIG_DEBUG_USER=y
+ # CONFIG_DEBUG_ERRORS is not set
+ CONFIG_DEBUG_LL=y
+@@ -937,10 +927,7 @@ CONFIG_DEBUG_LL=y
+ #
+ # CONFIG_KEYS is not set
+ # CONFIG_SECURITY is not set
+-
+-#
+-# Cryptographic options
+-#
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+ # CONFIG_CRYPTO is not set
+
+ #
+@@ -949,9 +936,12 @@ CONFIG_DEBUG_LL=y
+ CONFIG_BITREVERSE=y
+ # CONFIG_CRC_CCITT is not set
+ # CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
+ CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
+ # CONFIG_LIBCRC32C is not set
+ CONFIG_ZLIB_INFLATE=y
+ CONFIG_PLIST=y
+ CONFIG_HAS_IOMEM=y
+ CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/ateb9200_defconfig b/arch/arm/configs/ateb9200_defconfig
+index baa9769..d846a49 100644
+--- a/arch/arm/configs/ateb9200_defconfig
++++ b/arch/arm/configs/ateb9200_defconfig
+@@ -714,7 +714,7 @@ CONFIG_I2C_ALGOPCA=m
+ #
+ # I2C Hardware Bus support
+ #
+-CONFIG_I2C_AT91=m
++CONFIG_I2C_GPIO=m
+ # CONFIG_I2C_PARPORT_LIGHT is not set
+ # CONFIG_I2C_STUB is not set
+ # CONFIG_I2C_PCA_ISA is not set
+diff --git a/arch/arm/configs/cam60_defconfig b/arch/arm/configs/cam60_defconfig
+new file mode 100644
+index 0000000..f3cd4a9
+--- /dev/null
++++ b/arch/arm/configs/cam60_defconfig
+@@ -0,0 +1,1228 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.24
++# Thu Mar 6 10:07:26 2008
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ZONE_DMA=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_BSD_PROCESS_ACCT=y
++CONFIG_BSD_PROCESS_ACCT_V3=y
++# CONFIG_TASKSTATS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++CONFIG_AUDIT=y
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_LOG_BUF_SHIFT=17
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_RELAY=y
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++# CONFIG_EMBEDDED is not set
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++CONFIG_MODVERSIONS=y
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++CONFIG_BLK_DEV_IO_TRACE=y
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++
++#
++# System Type
++#
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++CONFIG_ARCH_AT91=y
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
++
++#
++# Atmel AT91 System-on-Chip
++#
++# CONFIG_ARCH_AT91RM9200 is not set
++CONFIG_ARCH_AT91SAM9260=y
++# CONFIG_ARCH_AT91SAM9261 is not set
++# CONFIG_ARCH_AT91SAM9263 is not set
++# CONFIG_ARCH_AT91SAM9RL is not set
++# CONFIG_ARCH_AT91CAP9 is not set
++# CONFIG_ARCH_AT91X40 is not set
++CONFIG_AT91_PMC_UNIT=y
++
++#
++# AT91SAM9260 Variants
++#
++# CONFIG_ARCH_AT91SAM9260_SAM9XE is not set
++
++#
++# AT91SAM9260 / AT91SAM9XE Board Type
++#
++# CONFIG_MACH_AT91SAM9260EK is not set
++CONFIG_MACH_CAM60=y
++# CONFIG_MACH_SAM9_L9260 is not set
++
++#
++# AT91 Board Options
++#
++
++#
++# AT91 Feature Selections
++#
++# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
++CONFIG_AT91_TIMER_HZ=100
++CONFIG_AT91_EARLY_DBGU=y
++# CONFIG_AT91_EARLY_USART0 is not set
++# CONFIG_AT91_EARLY_USART1 is not set
++# CONFIG_AT91_EARLY_USART2 is not set
++# CONFIG_AT91_EARLY_USART3 is not set
++# CONFIG_AT91_EARLY_USART4 is not set
++# CONFIG_AT91_EARLY_USART5 is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM926T=y
++CONFIG_CPU_32v5=y
++CONFIG_CPU_ABRT_EV5TJ=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
++# CONFIG_OUTER_CACHE is not set
++
++#
++# Bus support
++#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_PREEMPT is not set
++CONFIG_HZ=100
++# CONFIG_AEABI is not set
++# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_LEDS is not set
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0
++CONFIG_ZBOOT_ROM_BSS=0x20004000
++# CONFIG_ZBOOT_ROM is not set
++CONFIG_CMDLINE="console=ttyS0,115200 noinitrd root=/dev/mtdblock0 rootfstype=jffs2 mem=64M"
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++# CONFIG_VFP is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_AOUT=y
++CONFIG_BINFMT_MISC=y
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++CONFIG_SUSPEND_UP_POSSIBLE=y
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++# CONFIG_INET_DIAG is not set
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++CONFIG_NETWORK_SECMARK=y
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++CONFIG_NET_SCH_FIFO=y
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++CONFIG_CFG80211=m
++CONFIG_NL80211=y
++CONFIG_WIRELESS_EXT=y
++CONFIG_MAC80211=m
++CONFIG_MAC80211_RCSIMPLE=y
++# CONFIG_MAC80211_DEBUGFS is not set
++# CONFIG_MAC80211_DEBUG is not set
++CONFIG_IEEE80211=m
++# CONFIG_IEEE80211_DEBUG is not set
++CONFIG_IEEE80211_CRYPT_WEP=m
++CONFIG_IEEE80211_CRYPT_CCMP=m
++CONFIG_IEEE80211_CRYPT_TKIP=m
++CONFIG_IEEE80211_SOFTMAC=m
++# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_AFS_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++# CONFIG_MTD_CFI_AMDSTD is not set
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_RAM=m
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++CONFIG_MTD_COMPLEX_MAPPINGS=y
++# CONFIG_MTD_PHYSMAP is not set
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++CONFIG_MTD_PLATRAM=m
++
++#
++# Self-contained MTD device drivers
++#
++CONFIG_MTD_DATAFLASH=y
++# CONFIG_MTD_M25P80 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++CONFIG_MTD_NAND_VERIFY_WRITE=y
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++CONFIG_MTD_NAND_AT91=y
++# CONFIG_MTD_NAND_AT91_ECC_SOFT is not set
++CONFIG_MTD_NAND_AT91_ECC_HW=y
++# CONFIG_MTD_NAND_AT91_ECC_NONE is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ALAUDA is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=4096
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_MISC_DEVICES is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++CONFIG_SCSI_TGT=y
++CONFIG_SCSI_NETLINK=y
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++CONFIG_CHR_DEV_SCH=y
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++CONFIG_SCSI_MULTI_LUN=y
++# CONFIG_SCSI_CONSTANTS is not set
++CONFIG_SCSI_LOGGING=y
++CONFIG_SCSI_SCAN_ASYNC=y
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++CONFIG_SCSI_SPI_ATTRS=m
++CONFIG_SCSI_FC_ATTRS=m
++# CONFIG_SCSI_FC_TGT_ATTRS is not set
++CONFIG_SCSI_ISCSI_ATTRS=m
++CONFIG_SCSI_SAS_ATTRS=m
++CONFIG_SCSI_SAS_LIBSAS=m
++# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++# CONFIG_SCSI_LOWLEVEL is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++CONFIG_MARVELL_PHY=m
++CONFIG_DAVICOM_PHY=m
++CONFIG_QSEMI_PHY=m
++CONFIG_LXT_PHY=m
++CONFIG_CICADA_PHY=m
++CONFIG_VITESSE_PHY=m
++CONFIG_SMSC_PHY=m
++CONFIG_BROADCOM_PHY=m
++# CONFIG_ICPLUS_PHY is not set
++CONFIG_FIXED_PHY=m
++# CONFIG_FIXED_MII_10_FDX is not set
++# CONFIG_FIXED_MII_100_FDX is not set
++# CONFIG_FIXED_MII_1000_FDX is not set
++CONFIG_FIXED_MII_AMNT=1
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_MACB=y
++# CONFIG_AX88796 is not set
++# CONFIG_SMC91X is not set
++# CONFIG_DM9000 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++CONFIG_KEYBOARD_ATKBD=y
++CONFIG_KEYBOARD_SUNKBD=m
++CONFIG_KEYBOARD_LKKBD=m
++CONFIG_KEYBOARD_XTKBD=m
++CONFIG_KEYBOARD_NEWTON=m
++CONFIG_KEYBOARD_STOWAWAY=m
++# CONFIG_KEYBOARD_GPIO is not set
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_PS2_ALPS=y
++CONFIG_MOUSE_PS2_LOGIPS2PP=y
++CONFIG_MOUSE_PS2_SYNAPTICS=y
++CONFIG_MOUSE_PS2_LIFEBOOK=y
++CONFIG_MOUSE_PS2_TRACKPOINT=y
++# CONFIG_MOUSE_PS2_TOUCHKIT is not set
++CONFIG_MOUSE_SERIAL=m
++CONFIG_MOUSE_APPLETOUCH=m
++CONFIG_MOUSE_VSXXXAA=m
++# CONFIG_MOUSE_GPIO is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++# CONFIG_SERIO_SERPORT is not set
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++CONFIG_VT_HW_CONSOLE_BINDING=y
++CONFIG_SERIAL_NONSTANDARD=y
++# CONFIG_MOXA_SMARTIO is not set
++# CONFIG_N_HDLC is not set
++# CONFIG_RISCOM8 is not set
++# CONFIG_SPECIALIX is not set
++# CONFIG_RIO is not set
++# CONFIG_STALDRV is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_ATMEL=y
++CONFIG_SERIAL_ATMEL_CONSOLE=y
++# CONFIG_SERIAL_ATMEL_TTYAT is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++# CONFIG_LEGACY_PTYS is not set
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++CONFIG_I2C_ALGOBIT=y
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_PCA is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_SENSORS_DS1337 is not set
++# CONFIG_SENSORS_DS1374 is not set
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++CONFIG_SPI=y
++# CONFIG_SPI_DEBUG is not set
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_ATMEL=y
++# CONFIG_SPI_BITBANG is not set
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++# CONFIG_HID_SUPPORT is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_ONETOUCH is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++CONFIG_USB_LIBUSUAL=y
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++# CONFIG_USB_MON is not set
++
++#
++# USB port drivers
++#
++
++#
++# USB Serial Converter support
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++
++#
++# USB DSL modem support
++#
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_NEW_LEDS is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++CONFIG_RTC_INTF_DEV_UIE_EMUL=y
++CONFIG_RTC_DRV_TEST=m
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_AT91SAM9=y
++CONFIG_RTC_DRV_AT91SAM9_RTT=0
++CONFIG_RTC_DRV_AT91SAM9_GPBR=0
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++CONFIG_EXT2_FS_POSIX_ACL=y
++# CONFIG_EXT2_FS_SECURITY is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++CONFIG_QUOTA=y
++# CONFIG_QUOTA_NETLINK_INTERFACE is not set
++CONFIG_PRINT_QUOTA_WARNING=y
++# CONFIG_QFMT_V1 is not set
++# CONFIG_QFMT_V2 is not set
++CONFIG_QUOTACTL=y
++CONFIG_DNOTIFY=y
++CONFIG_AUTOFS_FS=y
++CONFIG_AUTOFS4_FS=y
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_CONFIGFS_FS=y
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_YAFFS_FS=y
++CONFIG_YAFFS_YAFFS1=y
++# CONFIG_YAFFS_9BYTE_TAGS is not set
++# CONFIG_YAFFS_DOES_ECC is not set
++CONFIG_YAFFS_YAFFS2=y
++CONFIG_YAFFS_AUTO_YAFFS2=y
++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="cp437"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++CONFIG_NLS_ASCII=y
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++# CONFIG_DLM is not set
++# CONFIG_INSTRUMENTATION is not set
++
++#
++# Kernel hacking
++#
++CONFIG_PRINTK_TIME=y
++CONFIG_ENABLE_WARN_DEPRECATED=y
++# CONFIG_ENABLE_MUST_CHECK is not set
++CONFIG_MAGIC_SYSRQ=y
++CONFIG_UNUSED_SYMBOLS=y
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_FORCED_INLINING is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_USER is not set
++# CONFIG_DEBUG_ERRORS is not set
++CONFIG_DEBUG_LL=y
++# CONFIG_DEBUG_ICEDCC is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_ABLKCIPHER=m
++CONFIG_CRYPTO_BLKCIPHER=m
++CONFIG_CRYPTO_HASH=y
++CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_HMAC=y
++CONFIG_CRYPTO_XCBC=m
++CONFIG_CRYPTO_NULL=m
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++CONFIG_CRYPTO_SHA1=y
++CONFIG_CRYPTO_SHA256=y
++CONFIG_CRYPTO_SHA512=y
++CONFIG_CRYPTO_WP512=m
++CONFIG_CRYPTO_TGR192=m
++CONFIG_CRYPTO_GF128MUL=m
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=m
++CONFIG_CRYPTO_PCBC=m
++CONFIG_CRYPTO_LRW=m
++# CONFIG_CRYPTO_XTS is not set
++CONFIG_CRYPTO_CRYPTD=m
++CONFIG_CRYPTO_DES=y
++CONFIG_CRYPTO_FCRYPT=m
++CONFIG_CRYPTO_BLOWFISH=m
++CONFIG_CRYPTO_TWOFISH=m
++CONFIG_CRYPTO_TWOFISH_COMMON=m
++CONFIG_CRYPTO_SERPENT=m
++CONFIG_CRYPTO_AES=m
++CONFIG_CRYPTO_CAST5=m
++CONFIG_CRYPTO_CAST6=m
++CONFIG_CRYPTO_TEA=m
++CONFIG_CRYPTO_ARC4=m
++CONFIG_CRYPTO_KHAZAD=m
++CONFIG_CRYPTO_ANUBIS=m
++# CONFIG_CRYPTO_SEED is not set
++CONFIG_CRYPTO_DEFLATE=m
++CONFIG_CRYPTO_MICHAEL_MIC=m
++CONFIG_CRYPTO_CRC32C=m
++CONFIG_CRYPTO_CAMELLIA=m
++CONFIG_CRYPTO_TEST=m
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_HW is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=m
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=m
++# CONFIG_CRC7 is not set
++CONFIG_LIBCRC32C=m
++CONFIG_AUDIT_GENERIC=y
++CONFIG_ZLIB_INFLATE=m
++CONFIG_ZLIB_DEFLATE=m
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/csb337_defconfig b/arch/arm/configs/csb337_defconfig
+index 88e5d28..67e65e4 100644
+--- a/arch/arm/configs/csb337_defconfig
++++ b/arch/arm/configs/csb337_defconfig
+@@ -1,69 +1,96 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.15
+-# Mon Jan 9 21:51:31 2006
++# Linux kernel version: 2.6.24-rc7
++# Wed Jan 9 22:19:24 2008
+ #
+ CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
+ CONFIG_MMU=y
+-CONFIG_UID16=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
+ CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ZONE_DMA=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+ #
+-# Code maturity level options
++# General setup
+ #
+ CONFIG_EXPERIMENTAL=y
+-CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
+ CONFIG_INIT_ENV_ARG_LIMIT=32
+-
+-#
+-# General setup
+-#
+ CONFIG_LOCALVERSION=""
+ CONFIG_LOCALVERSION_AUTO=y
+ # CONFIG_SWAP is not set
+ CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
+ # CONFIG_POSIX_MQUEUE is not set
+ # CONFIG_BSD_PROCESS_ACCT is not set
+-CONFIG_SYSCTL=y
++# CONFIG_TASKSTATS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
+ # CONFIG_AUDIT is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_KOBJECT_UEVENT=y
+ # CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
+ CONFIG_INITRAMFS_SOURCE=""
+ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
+ # CONFIG_EMBEDDED is not set
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
+ CONFIG_KALLSYMS=y
+ # CONFIG_KALLSYMS_ALL is not set
+ # CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
+ CONFIG_PRINTK=y
+ CONFIG_BUG=y
++CONFIG_ELF_CORE=y
+ CONFIG_BASE_FULL=y
+ CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
+ CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
+ CONFIG_SHMEM=y
+-CONFIG_CC_ALIGN_FUNCTIONS=0
+-CONFIG_CC_ALIGN_LABELS=0
+-CONFIG_CC_ALIGN_LOOPS=0
+-CONFIG_CC_ALIGN_JUMPS=0
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
+ # CONFIG_TINY_SHMEM is not set
+ CONFIG_BASE_SMALL=0
+-
+-#
+-# Loadable module support
+-#
+ CONFIG_MODULES=y
+ CONFIG_MODULE_UNLOAD=y
+ # CONFIG_MODULE_FORCE_UNLOAD is not set
+-CONFIG_OBSOLETE_MODPARM=y
+ # CONFIG_MODVERSIONS is not set
+ # CONFIG_MODULE_SRCVERSION_ALL is not set
+ CONFIG_KMOD=y
+-
+-#
+-# Block layer
+-#
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
+
+ #
+ # IO Schedulers
+@@ -81,62 +108,101 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
+ #
+ # System Type
+ #
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++CONFIG_ARCH_AT91=y
+ # CONFIG_ARCH_CLPS7500 is not set
+ # CONFIG_ARCH_CLPS711X is not set
+ # CONFIG_ARCH_CO285 is not set
+ # CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
+ # CONFIG_ARCH_FOOTBRIDGE is not set
+-# CONFIG_ARCH_INTEGRATOR is not set
+-# CONFIG_ARCH_IOP3XX is not set
+-# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
+ # CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
+ # CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_PNX4008 is not set
+ # CONFIG_ARCH_PXA is not set
+ # CONFIG_ARCH_RPC is not set
+ # CONFIG_ARCH_SA1100 is not set
+ # CONFIG_ARCH_S3C2410 is not set
+ # CONFIG_ARCH_SHARK is not set
+ # CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
+ # CONFIG_ARCH_OMAP is not set
+-# CONFIG_ARCH_VERSATILE is not set
+-# CONFIG_ARCH_REALVIEW is not set
+-# CONFIG_ARCH_IMX is not set
+-# CONFIG_ARCH_H720X is not set
+-# CONFIG_ARCH_AAEC2000 is not set
+-CONFIG_ARCH_AT91=y
+-CONFIG_ARCH_AT91RM9200=y
+
+ #
+-# AT91RM9200 Implementations
++# Boot options
+ #
+
+ #
++# Power management
++#
++
++#
++# Atmel AT91 System-on-Chip
++#
++CONFIG_ARCH_AT91RM9200=y
++# CONFIG_ARCH_AT91SAM9260 is not set
++# CONFIG_ARCH_AT91SAM9261 is not set
++# CONFIG_ARCH_AT91SAM9263 is not set
++# CONFIG_ARCH_AT91SAM9RL is not set
++# CONFIG_ARCH_AT91X40 is not set
++CONFIG_AT91_PMC_UNIT=y
++
++#
+ # AT91RM9200 Board Type
+ #
++# CONFIG_MACH_ONEARM is not set
+ # CONFIG_ARCH_AT91RM9200DK is not set
+ # CONFIG_MACH_AT91RM9200EK is not set
+ CONFIG_MACH_CSB337=y
+ # CONFIG_MACH_CSB637 is not set
+ # CONFIG_MACH_CARMEVA is not set
+-# CONFIG_MACH_KB9200 is not set
+ # CONFIG_MACH_ATEB9200 is not set
++# CONFIG_MACH_KB9200 is not set
++# CONFIG_MACH_PICOTUX2XX is not set
++# CONFIG_MACH_KAFA is not set
++# CONFIG_MACH_CHUB is not set
++# CONFIG_MACH_HOMEMATIC is not set
++# CONFIG_MACH_ECBAT91 is not set
++# CONFIG_MACH_SWEDATMS is not set
++
++#
++# AT91 Board Options
++#
+
+ #
+-# AT91RM9200 Feature Selections
++# AT91 Feature Selections
+ #
+ CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
++# CONFIG_ATMEL_TCLIB is not set
++CONFIG_AT91_TIMER_HZ=128
+
+ #
+ # Processor Type
+ #
+ CONFIG_CPU_32=y
+ CONFIG_CPU_ARM920T=y
+-CONFIG_CPU_32v4=y
++CONFIG_CPU_32v4T=y
+ CONFIG_CPU_ABRT_EV4T=y
+ CONFIG_CPU_CACHE_V4WT=y
+ CONFIG_CPU_CACHE_VIVT=y
+ CONFIG_CPU_COPY_V4WB=y
+ CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
+
+ #
+ # Processor Features
+@@ -145,15 +211,13 @@ CONFIG_CPU_TLB_V4WBI=y
+ # CONFIG_CPU_ICACHE_DISABLE is not set
+ # CONFIG_CPU_DCACHE_DISABLE is not set
+ # CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_OUTER_CACHE is not set
+
+ #
+ # Bus support
+ #
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# PCCARD (PCMCIA/CardBus) support
+-#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
+ CONFIG_PCCARD=y
+ # CONFIG_PCMCIA_DEBUG is not set
+ CONFIG_PCMCIA=y
+@@ -168,8 +232,13 @@ CONFIG_AT91_CF=y
+ #
+ # Kernel Features
+ #
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+ # CONFIG_PREEMPT is not set
+-# CONFIG_NO_IDLE_HZ is not set
++CONFIG_HZ=128
++# CONFIG_AEABI is not set
+ # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+ CONFIG_SELECT_MEMORY_MODEL=y
+ CONFIG_FLATMEM_MANUAL=y
+@@ -178,9 +247,13 @@ CONFIG_FLATMEM_MANUAL=y
+ CONFIG_FLATMEM=y
+ CONFIG_FLAT_NODE_MEM_MAP=y
+ # CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+ CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
+ CONFIG_LEDS=y
+-CONFIG_LEDS_TIMER=y
+ CONFIG_LEDS_CPU=y
+ CONFIG_ALIGNMENT_TRAP=y
+
+@@ -191,6 +264,7 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
+ CONFIG_ZBOOT_ROM_BSS=0x0
+ CONFIG_CMDLINE="mem=32M console=ttyS0,38400 initrd=0x20410000,3145728 root=/dev/ram0 rw"
+ # CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
+
+ #
+ # Floating point emulation
+@@ -215,6 +289,7 @@ CONFIG_BINFMT_ELF=y
+ # Power management options
+ #
+ # CONFIG_PM is not set
++CONFIG_SUSPEND_UP_POSSIBLE=y
+
+ #
+ # Networking
+@@ -227,6 +302,10 @@ CONFIG_NET=y
+ CONFIG_PACKET=y
+ # CONFIG_PACKET_MMAP is not set
+ CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
+ # CONFIG_NET_KEY is not set
+ CONFIG_INET=y
+ # CONFIG_IP_MULTICAST is not set
+@@ -243,23 +322,26 @@ CONFIG_IP_PNP_BOOTP=y
+ # CONFIG_INET_AH is not set
+ # CONFIG_INET_ESP is not set
+ # CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
+ # CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
+ CONFIG_INET_DIAG=y
+ CONFIG_INET_TCP_DIAG=y
+ # CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_BIC=y
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
+ # CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
+ # CONFIG_NETFILTER is not set
+-
+-#
+-# DCCP Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_IP_DCCP is not set
+-
+-#
+-# SCTP Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
+ # CONFIG_ATM is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_VLAN_8021Q is not set
+@@ -269,13 +351,8 @@ CONFIG_TCP_CONG_BIC=y
+ # CONFIG_ATALK is not set
+ # CONFIG_X25 is not set
+ # CONFIG_LAPB is not set
+-# CONFIG_NET_DIVERT is not set
+ # CONFIG_ECONET is not set
+ # CONFIG_WAN_ROUTER is not set
+-
+-#
+-# QoS and/or fair queueing
+-#
+ # CONFIG_NET_SCHED is not set
+
+ #
+@@ -285,7 +362,17 @@ CONFIG_TCP_CONG_BIC=y
+ # CONFIG_HAMRADIO is not set
+ # CONFIG_IRDA is not set
+ # CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
+ # CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
+
+ #
+ # Device Drivers
+@@ -294,19 +381,14 @@ CONFIG_TCP_CONG_BIC=y
+ #
+ # Generic Driver Options
+ #
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+ CONFIG_STANDALONE=y
+ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ CONFIG_FW_LOADER=y
+ # CONFIG_DEBUG_DRIVER is not set
+-
+-#
+-# Connector - unified userspace <-> kernelspace linker
+-#
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
+ # CONFIG_CONNECTOR is not set
+-
+-#
+-# Memory Technology Devices (MTD)
+-#
+ CONFIG_MTD=y
+ # CONFIG_MTD_DEBUG is not set
+ # CONFIG_MTD_CONCAT is not set
+@@ -319,11 +401,14 @@ CONFIG_MTD_CMDLINE_PARTS=y
+ # User Modules And Translation Layers
+ #
+ CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
+ CONFIG_MTD_BLOCK=y
+ # CONFIG_FTL is not set
+ # CONFIG_NFTL is not set
+ # CONFIG_INFTL is not set
+ # CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
+
+ #
+ # RAM/ROM/Flash chip drivers
+@@ -349,15 +434,14 @@ CONFIG_MTD_CFI_UTIL=y
+ # CONFIG_MTD_RAM is not set
+ # CONFIG_MTD_ROM is not set
+ # CONFIG_MTD_ABSENT is not set
+-# CONFIG_MTD_XIP is not set
+
+ #
+ # Mapping drivers for chip access
+ #
+ # CONFIG_MTD_COMPLEX_MAPPINGS is not set
+ CONFIG_MTD_PHYSMAP=y
+-CONFIG_MTD_PHYSMAP_START=0
+-CONFIG_MTD_PHYSMAP_LEN=0
++CONFIG_MTD_PHYSMAP_START=0x0
++CONFIG_MTD_PHYSMAP_LEN=0x0
+ CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+ # CONFIG_MTD_ARM_INTEGRATOR is not set
+ # CONFIG_MTD_PLATRAM is not set
+@@ -368,7 +452,6 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+ # CONFIG_MTD_SLRAM is not set
+ # CONFIG_MTD_PHRAM is not set
+ # CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLKMTD is not set
+ # CONFIG_MTD_BLOCK2MTD is not set
+
+ #
+@@ -378,29 +461,15 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOC2001PLUS is not set
+ # CONFIG_MTD_AT91_DATAFLASH is not set
+-
+-#
+-# NAND Flash Device Drivers
+-#
+ # CONFIG_MTD_NAND is not set
+-
+-#
+-# OneNAND Flash Device Drivers
+-#
+ # CONFIG_MTD_ONENAND is not set
+
+ #
+-# Parallel port support
++# UBI - Unsorted block images
+ #
++# CONFIG_MTD_UBI is not set
+ # CONFIG_PARPORT is not set
+-
+-#
+-# Plug and Play support
+-#
+-
+-#
+-# Block devices
+-#
++CONFIG_BLK_DEV=y
+ # CONFIG_BLK_DEV_COW_COMMON is not set
+ CONFIG_BLK_DEV_LOOP=y
+ # CONFIG_BLK_DEV_CRYPTOLOOP is not set
+@@ -409,13 +478,12 @@ CONFIG_BLK_DEV_LOOP=y
+ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_COUNT=16
+ CONFIG_BLK_DEV_RAM_SIZE=8192
+-CONFIG_BLK_DEV_INITRD=y
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+ # CONFIG_CDROM_PKTCDVD is not set
+ # CONFIG_ATA_OVER_ETH is not set
+-
+-#
+-# ATA/ATAPI/MFM/RLL support
+-#
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++CONFIG_ATMEL_SSC=y
+ # CONFIG_IDE is not set
+
+ #
+@@ -423,6 +491,9 @@ CONFIG_BLK_DEV_INITRD=y
+ #
+ # CONFIG_RAID_ATTRS is not set
+ CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
+ CONFIG_SCSI_PROC_FS=y
+
+ #
+@@ -441,97 +512,61 @@ CONFIG_SCSI_PROC_FS=y
+ # CONFIG_SCSI_MULTI_LUN is not set
+ # CONFIG_SCSI_CONSTANTS is not set
+ # CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
+
+ #
+-# SCSI Transport Attributes
++# SCSI Transports
+ #
+ # CONFIG_SCSI_SPI_ATTRS is not set
+ # CONFIG_SCSI_FC_ATTRS is not set
+ # CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_ATTRS is not set
+-
+-#
+-# SCSI low-level drivers
+-#
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
+ # CONFIG_ISCSI_TCP is not set
+-# CONFIG_SCSI_SATA is not set
+ # CONFIG_SCSI_DEBUG is not set
+-
+-#
+-# PCMCIA SCSI adapter support
+-#
+-# CONFIG_PCMCIA_AHA152X is not set
+-# CONFIG_PCMCIA_FDOMAIN is not set
+-# CONFIG_PCMCIA_NINJA_SCSI is not set
+-# CONFIG_PCMCIA_QLOGIC is not set
+-# CONFIG_PCMCIA_SYM53C500 is not set
+-
+-#
+-# Multi-device support (RAID and LVM)
+-#
++# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
++# CONFIG_ATA is not set
+ # CONFIG_MD is not set
+-
+-#
+-# Fusion MPT device support
+-#
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-
+-#
+-# I2O device support
+-#
+-
+-#
+-# Network device support
+-#
+ CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
+ # CONFIG_DUMMY is not set
+ # CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
+ # CONFIG_EQUALIZER is not set
+ # CONFIG_TUN is not set
+-
+-#
+-# PHY device support
+-#
++# CONFIG_VETH is not set
+ # CONFIG_PHYLIB is not set
+-
+-#
+-# Ethernet (10 or 100Mbit)
+-#
+ CONFIG_NET_ETHERNET=y
+ CONFIG_MII=y
+ CONFIG_ARM_AT91_ETHER=y
++# CONFIG_AX88796 is not set
+ # CONFIG_SMC91X is not set
+ # CONFIG_DM9000 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++CONFIG_NETDEV_10000=y
+
+ #
+-# Ethernet (1000 Mbit)
+-#
+-
+-#
+-# Ethernet (10000 Mbit)
++# Wireless LAN
+ #
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
+
+ #
+-# Token Ring devices
+-#
+-
+-#
+-# Wireless LAN (non-hamradio)
+-#
+-# CONFIG_NET_RADIO is not set
+-
+-#
+-# PCMCIA network device support
++# USB Network Adapters
+ #
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
+ # CONFIG_NET_PCMCIA is not set
+-
+-#
+-# Wan interfaces
+-#
+ # CONFIG_WAN is not set
+ # CONFIG_PPP is not set
+ # CONFIG_SLIP is not set
+@@ -539,26 +574,23 @@ CONFIG_ARM_AT91_ETHER=y
+ # CONFIG_NETCONSOLE is not set
+ # CONFIG_NETPOLL is not set
+ # CONFIG_NET_POLL_CONTROLLER is not set
+-
+-#
+-# ISDN subsystem
+-#
+ # CONFIG_ISDN is not set
+
+ #
+ # Input device support
+ #
+ CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
+
+ #
+ # Userland interfaces
+ #
+ CONFIG_INPUT_MOUSEDEV=y
+-CONFIG_INPUT_MOUSEDEV_PSAUX=y
++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ # CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_TSDEV is not set
+ # CONFIG_INPUT_EVDEV is not set
+ # CONFIG_INPUT_EVBUG is not set
+
+@@ -568,6 +600,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ # CONFIG_INPUT_KEYBOARD is not set
+ # CONFIG_INPUT_MOUSE is not set
+ # CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
+ # CONFIG_INPUT_TOUCHSCREEN is not set
+ # CONFIG_INPUT_MISC is not set
+
+@@ -583,6 +616,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ CONFIG_VT=y
+ CONFIG_VT_CONSOLE=y
+ CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+
+ #
+@@ -601,152 +635,114 @@ CONFIG_SERIAL_CORE_CONSOLE=y
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_LEGACY_PTYS=y
+ CONFIG_LEGACY_PTY_COUNT=256
+-
+-#
+-# IPMI
+-#
+ # CONFIG_IPMI_HANDLER is not set
+-
+-#
+-# Watchdog Cards
+-#
+-CONFIG_WATCHDOG=y
+-CONFIG_WATCHDOG_NOWAYOUT=y
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_AT91RM9200_WATCHDOG=y
+-
+-#
+-# USB-based Watchdog Cards
+-#
+-# CONFIG_USBPCWATCHDOG is not set
+ # CONFIG_HW_RANDOM is not set
+ # CONFIG_NVRAM is not set
+-# CONFIG_DTLK is not set
+ # CONFIG_R3964 is not set
+
+ #
+-# Ftape, the floppy tape device driver
+-#
+-
+-#
+ # PCMCIA character devices
+ #
+ # CONFIG_SYNCLINK_CS is not set
+ # CONFIG_CARDMAN_4000 is not set
+ # CONFIG_CARDMAN_4040 is not set
+ # CONFIG_RAW_DRIVER is not set
+-
+-#
+-# TPM devices
+-#
+ # CONFIG_TCG_TPM is not set
+-# CONFIG_TELCLOCK is not set
+ CONFIG_AT91_SPI=y
+ CONFIG_AT91_SPIDEV=y
+-
+-#
+-# I2C support
+-#
+ CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
+ CONFIG_I2C_CHARDEV=y
+
+ #
+ # I2C Algorithms
+ #
+-# CONFIG_I2C_ALGOBIT is not set
++CONFIG_I2C_ALGOBIT=y
+ # CONFIG_I2C_ALGOPCF is not set
+ # CONFIG_I2C_ALGOPCA is not set
+
+ #
+ # I2C Hardware Bus support
+ #
+-CONFIG_I2C_AT91=y
++CONFIG_I2C_GPIO=y
++# CONFIG_I2C_OCORES is not set
+ # CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
+ # CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_PCA_ISA is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_PCA is not set
+
+ #
+ # Miscellaneous I2C Chip support
+ #
+ # CONFIG_SENSORS_DS1337 is not set
+ # CONFIG_SENSORS_DS1374 is not set
++# CONFIG_DS1682 is not set
+ # CONFIG_SENSORS_EEPROM is not set
+ # CONFIG_SENSORS_PCF8574 is not set
+ # CONFIG_SENSORS_PCA9539 is not set
+ # CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_SENSORS_RTC8564 is not set
+ # CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_RTC_X1205_I2C is not set
++# CONFIG_SENSORS_TSL2550 is not set
+ # CONFIG_I2C_DEBUG_CORE is not set
+ # CONFIG_I2C_DEBUG_ALGO is not set
+ # CONFIG_I2C_DEBUG_BUS is not set
+ # CONFIG_I2C_DEBUG_CHIP is not set
+
+ #
+-# Hardware Monitoring support
+-#
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ASB100 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_FSCHER is not set
+-# CONFIG_SENSORS_FSCPOS is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-
+-#
+-# Misc devices
+-#
+-
+-#
+-# Multimedia Capabilities Port drivers
++# SPI support
+ #
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_WATCHDOG=y
++CONFIG_WATCHDOG_NOWAYOUT=y
+
+ #
+-# Multimedia devices
++# Watchdog Device Drivers
+ #
+-# CONFIG_VIDEO_DEV is not set
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_AT91RM9200_WATCHDOG=y
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
+
+ #
+-# Digital Video Broadcasting Devices
++# Multifunction device drivers
+ #
+-# CONFIG_DVB is not set
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
+
+ #
+ # Graphics support
+ #
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+ # CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
+
+ #
+ # Console display driver support
+@@ -758,12 +754,25 @@ CONFIG_DUMMY_CONSOLE=y
+ # Sound
+ #
+ # CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++CONFIG_HID_DEBUG=y
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++# CONFIG_USB_HID is not set
+
+ #
+-# USB support
++# USB HID Boot Protocol drivers
+ #
++# CONFIG_USB_KBD is not set
++# CONFIG_USB_MOUSE is not set
++CONFIG_USB_SUPPORT=y
+ CONFIG_USB_ARCH_HAS_HCD=y
+ CONFIG_USB_ARCH_HAS_OHCI=y
++# CONFIG_USB_ARCH_HAS_EHCI is not set
+ CONFIG_USB=y
+ CONFIG_USB_DEBUG=y
+
+@@ -771,7 +780,7 @@ CONFIG_USB_DEBUG=y
+ # Miscellaneous USB options
+ #
+ CONFIG_USB_DEVICEFS=y
+-# CONFIG_USB_BANDWIDTH is not set
++CONFIG_USB_DEVICE_CLASS=y
+ # CONFIG_USB_DYNAMIC_MINORS is not set
+ # CONFIG_USB_OTG is not set
+
+@@ -780,9 +789,11 @@ CONFIG_USB_DEVICEFS=y
+ #
+ # CONFIG_USB_ISP116X_HCD is not set
+ CONFIG_USB_OHCI_HCD=y
+-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+ # CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
+
+ #
+ # USB Device Class drivers
+@@ -801,59 +812,21 @@ CONFIG_USB_STORAGE=y
+ # CONFIG_USB_STORAGE_DEBUG is not set
+ # CONFIG_USB_STORAGE_DATAFAB is not set
+ # CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
+ # CONFIG_USB_STORAGE_DPCM is not set
+ # CONFIG_USB_STORAGE_USBAT is not set
+ # CONFIG_USB_STORAGE_SDDR09 is not set
+ # CONFIG_USB_STORAGE_SDDR55 is not set
+ # CONFIG_USB_STORAGE_JUMPSHOT is not set
+-
+-#
+-# USB Input Devices
+-#
+-# CONFIG_USB_HID is not set
+-
+-#
+-# USB HID Boot Protocol drivers
+-#
+-# CONFIG_USB_KBD is not set
+-# CONFIG_USB_MOUSE is not set
+-# CONFIG_USB_AIPTEK is not set
+-# CONFIG_USB_WACOM is not set
+-# CONFIG_USB_ACECAD is not set
+-# CONFIG_USB_KBTAB is not set
+-# CONFIG_USB_POWERMATE is not set
+-# CONFIG_USB_MTOUCH is not set
+-# CONFIG_USB_ITMTOUCH is not set
+-# CONFIG_USB_EGALAX is not set
+-# CONFIG_USB_YEALINK is not set
+-# CONFIG_USB_XPAD is not set
+-# CONFIG_USB_ATI_REMOTE is not set
+-# CONFIG_USB_KEYSPAN_REMOTE is not set
+-# CONFIG_USB_APPLETOUCH is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
+
+ #
+ # USB Imaging devices
+ #
+ # CONFIG_USB_MDC800 is not set
+ # CONFIG_USB_MICROTEK is not set
+-
+-#
+-# USB Multimedia devices
+-#
+-# CONFIG_USB_DABUSB is not set
+-
+-#
+-# Video4Linux support is needed for USB Multimedia device support
+-#
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
+ CONFIG_USB_MON=y
+
+ #
+@@ -866,15 +839,18 @@ CONFIG_USB_MON=y
+ CONFIG_USB_SERIAL=y
+ CONFIG_USB_SERIAL_CONSOLE=y
+ CONFIG_USB_SERIAL_GENERIC=y
++# CONFIG_USB_SERIAL_AIRCABLE is not set
+ # CONFIG_USB_SERIAL_AIRPRIME is not set
+-# CONFIG_USB_SERIAL_ANYDATA is not set
++# CONFIG_USB_SERIAL_ARK3116 is not set
+ # CONFIG_USB_SERIAL_BELKIN is not set
++# CONFIG_USB_SERIAL_CH341 is not set
+ # CONFIG_USB_SERIAL_WHITEHEAT is not set
+ # CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+ # CONFIG_USB_SERIAL_CP2101 is not set
+ # CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+ # CONFIG_USB_SERIAL_EMPEG is not set
+ CONFIG_USB_SERIAL_FTDI_SIO=y
++# CONFIG_USB_SERIAL_FUNSOFT is not set
+ # CONFIG_USB_SERIAL_VISOR is not set
+ # CONFIG_USB_SERIAL_IPAQ is not set
+ # CONFIG_USB_SERIAL_IR is not set
+@@ -899,14 +875,20 @@ CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+ # CONFIG_USB_SERIAL_KLSI is not set
+ # CONFIG_USB_SERIAL_KOBIL_SCT is not set
+ CONFIG_USB_SERIAL_MCT_U232=y
++# CONFIG_USB_SERIAL_MOS7720 is not set
++# CONFIG_USB_SERIAL_MOS7840 is not set
++# CONFIG_USB_SERIAL_NAVMAN is not set
+ # CONFIG_USB_SERIAL_PL2303 is not set
++# CONFIG_USB_SERIAL_OTI6858 is not set
+ # CONFIG_USB_SERIAL_HP4X is not set
+ # CONFIG_USB_SERIAL_SAFE is not set
++# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+ # CONFIG_USB_SERIAL_TI is not set
+ # CONFIG_USB_SERIAL_CYBERJACK is not set
+ # CONFIG_USB_SERIAL_XIRCOM is not set
+ # CONFIG_USB_SERIAL_OPTION is not set
+ # CONFIG_USB_SERIAL_OMNINET is not set
++# CONFIG_USB_SERIAL_DEBUG is not set
+ CONFIG_USB_EZUSB=y
+
+ #
+@@ -914,16 +896,22 @@ CONFIG_USB_EZUSB=y
+ #
+ # CONFIG_USB_EMI62 is not set
+ # CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
+ # CONFIG_USB_AUERSWALD is not set
+ # CONFIG_USB_RIO500 is not set
+ # CONFIG_USB_LEGOTOWER is not set
+ # CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
+ # CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
+ # CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGETKIT is not set
+-# CONFIG_USB_PHIDGETSERVO is not set
++# CONFIG_USB_PHIDGET is not set
+ # CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
+ # CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
+ # CONFIG_USB_TEST is not set
+
+ #
+@@ -934,13 +922,19 @@ CONFIG_USB_EZUSB=y
+ # USB Gadget Support
+ #
+ CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG is not set
+ # CONFIG_USB_GADGET_DEBUG_FILES is not set
+ CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_ATMEL_USBA is not set
++# CONFIG_USB_GADGET_FSL_USB2 is not set
+ # CONFIG_USB_GADGET_NET2280 is not set
+ # CONFIG_USB_GADGET_PXA2XX is not set
++# CONFIG_USB_GADGET_M66592 is not set
+ # CONFIG_USB_GADGET_GOKU is not set
+ # CONFIG_USB_GADGET_LH7A40X is not set
+ # CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_S3C2410 is not set
+ CONFIG_USB_GADGET_AT91=y
+ CONFIG_USB_AT91=y
+ # CONFIG_USB_GADGET_DUMMY_HCD is not set
+@@ -950,22 +944,28 @@ CONFIG_USB_AT91=y
+ # CONFIG_USB_GADGETFS is not set
+ # CONFIG_USB_FILE_STORAGE is not set
+ # CONFIG_USB_G_SERIAL is not set
++# CONFIG_USB_MIDI_GADGET is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
+
+ #
+-# MMC/SD Card support
++# MMC/SD Card Drivers
+ #
+-CONFIG_MMC=y
+-# CONFIG_MMC_DEBUG is not set
+ CONFIG_MMC_BLOCK=y
+-CONFIG_MMC_AT91RM9200=y
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
+
+ #
+-# Real Time Clock
++# MMC/SD Host Controller Drivers
+ #
++# CONFIG_MMC_AT91 is not set
++# CONFIG_NEW_LEDS is not set
+ CONFIG_RTC_LIB=y
+ CONFIG_RTC_CLASS=y
+ CONFIG_RTC_HCTOSYS=y
+ CONFIG_RTC_HCTOSYS_DEVICE="rtc1"
++# CONFIG_RTC_DEBUG is not set
+
+ #
+ # RTC interfaces
+@@ -974,39 +974,60 @@ CONFIG_RTC_HCTOSYS_DEVICE="rtc1"
+ CONFIG_RTC_INTF_PROC=y
+ CONFIG_RTC_INTF_DEV=y
+ # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
+
+ #
+-# RTC drivers
++# I2C RTC drivers
+ #
+-# CONFIG_RTC_DRV_X1205 is not set
+ CONFIG_RTC_DRV_DS1307=y
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
+ # CONFIG_RTC_DRV_DS1672 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
+ # CONFIG_RTC_DRV_PCF8563 is not set
+ # CONFIG_RTC_DRV_PCF8583 is not set
+-# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
+ # CONFIG_RTC_DRV_M48T86 is not set
+-CONFIG_RTC_DRV_AT91RM9200=y
+-# CONFIG_RTC_DRV_TEST is not set
++# CONFIG_RTC_DRV_M48T59 is not set
+ # CONFIG_RTC_DRV_V3020 is not set
+
+ #
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_AT91RM9200=y
++
++#
+ # File systems
+ #
+ CONFIG_EXT2_FS=y
+ # CONFIG_EXT2_FS_XATTR is not set
+ # CONFIG_EXT2_FS_XIP is not set
+ # CONFIG_EXT3_FS is not set
+-# CONFIG_JBD is not set
++# CONFIG_EXT4DEV_FS is not set
+ # CONFIG_REISERFS_FS is not set
+ # CONFIG_JFS_FS is not set
+ # CONFIG_FS_POSIX_ACL is not set
+ # CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
+ # CONFIG_MINIX_FS is not set
+ # CONFIG_ROMFS_FS is not set
+ CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
+ # CONFIG_QUOTA is not set
+ CONFIG_DNOTIFY=y
+ # CONFIG_AUTOFS_FS is not set
+@@ -1030,11 +1051,12 @@ CONFIG_DNOTIFY=y
+ # Pseudo filesystems
+ #
+ CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
+ CONFIG_SYSFS=y
+ CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
+ # CONFIG_HUGETLB_PAGE is not set
+-CONFIG_RAMFS=y
+-# CONFIG_RELAYFS_FS is not set
++# CONFIG_CONFIGFS_FS is not set
+
+ #
+ # Miscellaneous filesystems
+@@ -1046,7 +1068,6 @@ CONFIG_RAMFS=y
+ # CONFIG_BEFS_FS is not set
+ # CONFIG_BFS_FS is not set
+ # CONFIG_EFS_FS is not set
+-# CONFIG_JFFS_FS is not set
+ # CONFIG_JFFS2_FS is not set
+ CONFIG_CRAMFS=y
+ # CONFIG_VXFS_FS is not set
+@@ -1054,10 +1075,7 @@ CONFIG_CRAMFS=y
+ # CONFIG_QNX4FS_FS is not set
+ # CONFIG_SYSV_FS is not set
+ # CONFIG_UFS_FS is not set
+-
+-#
+-# Network File Systems
+-#
++CONFIG_NETWORK_FILESYSTEMS=y
+ CONFIG_NFS_FS=y
+ CONFIG_NFS_V3=y
+ # CONFIG_NFS_V3_ACL is not set
+@@ -1070,6 +1088,7 @@ CONFIG_LOCKD_V4=y
+ CONFIG_NFS_COMMON=y
+ CONFIG_SUNRPC=y
+ CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
+ CONFIG_RPCSEC_GSS_KRB5=y
+ # CONFIG_RPCSEC_GSS_SPKM3 is not set
+ # CONFIG_SMB_FS is not set
+@@ -1077,43 +1096,56 @@ CONFIG_RPCSEC_GSS_KRB5=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
+-# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+ #
+ # CONFIG_PARTITION_ADVANCED is not set
+ CONFIG_MSDOS_PARTITION=y
+-
+-#
+-# Native Language Support
+-#
+ # CONFIG_NLS is not set
+-
+-#
+-# Profiling support
+-#
++# CONFIG_DLM is not set
++CONFIG_INSTRUMENTATION=y
+ # CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
+
+ #
+ # Kernel hacking
+ #
+ # CONFIG_PRINTK_TIME is not set
+-CONFIG_DEBUG_KERNEL=y
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
+ # CONFIG_MAGIC_SYSRQ is not set
+-CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
+ CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
+ # CONFIG_SCHEDSTATS is not set
+-# CONFIG_DEBUG_SLAB is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
+ # CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
+ # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+ # CONFIG_DEBUG_KOBJECT is not set
+ CONFIG_DEBUG_BUGVERBOSE=y
+ # CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_FS is not set
+ # CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
+ CONFIG_FRAME_POINTER=y
++CONFIG_FORCED_INLINING=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
+ # CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
+ CONFIG_DEBUG_USER=y
+ # CONFIG_DEBUG_ERRORS is not set
+ CONFIG_DEBUG_LL=y
+@@ -1124,12 +1156,13 @@ CONFIG_DEBUG_LL=y
+ #
+ # CONFIG_KEYS is not set
+ # CONFIG_SECURITY is not set
+-
+-#
+-# Cryptographic options
+-#
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+ CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++CONFIG_CRYPTO_MANAGER=y
+ # CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
+ # CONFIG_CRYPTO_NULL is not set
+ # CONFIG_CRYPTO_MD4 is not set
+ CONFIG_CRYPTO_MD5=y
+@@ -1138,7 +1171,15 @@ CONFIG_CRYPTO_MD5=y
+ # CONFIG_CRYPTO_SHA512 is not set
+ # CONFIG_CRYPTO_WP512 is not set
+ # CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++CONFIG_CRYPTO_CBC=y
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CRYPTD is not set
+ CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
+ # CONFIG_CRYPTO_BLOWFISH is not set
+ # CONFIG_CRYPTO_TWOFISH is not set
+ # CONFIG_CRYPTO_SERPENT is not set
+@@ -1149,20 +1190,27 @@ CONFIG_CRYPTO_DES=y
+ # CONFIG_CRYPTO_ARC4 is not set
+ # CONFIG_CRYPTO_KHAZAD is not set
+ # CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
+ # CONFIG_CRYPTO_DEFLATE is not set
+ # CONFIG_CRYPTO_MICHAEL_MIC is not set
+ # CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
+ # CONFIG_CRYPTO_TEST is not set
+-
+-#
+-# Hardware crypto devices
+-#
++# CONFIG_CRYPTO_AUTHENC is not set
++CONFIG_CRYPTO_HW=y
+
+ #
+ # Library routines
+ #
++CONFIG_BITREVERSE=y
+ # CONFIG_CRC_CCITT is not set
+ # CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
+ CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
+ # CONFIG_LIBCRC32C is not set
+ CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/csb637_defconfig b/arch/arm/configs/csb637_defconfig
+index 669f035..9970214 100644
+--- a/arch/arm/configs/csb637_defconfig
++++ b/arch/arm/configs/csb637_defconfig
+@@ -1,69 +1,112 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.15
+-# Mon Jan 9 21:52:00 2006
++# Linux kernel version: 2.6.25-rc8
++# Fri Apr 4 22:06:15 2008
+ #
+ CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
+ CONFIG_MMU=y
+-CONFIG_UID16=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
+ CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ARCH_SUPPORTS_AOUT=y
++CONFIG_ZONE_DMA=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+ #
+-# Code maturity level options
++# General setup
+ #
+ CONFIG_EXPERIMENTAL=y
+-CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
+ CONFIG_INIT_ENV_ARG_LIMIT=32
+-
+-#
+-# General setup
+-#
+ CONFIG_LOCALVERSION=""
+ CONFIG_LOCALVERSION_AUTO=y
+ # CONFIG_SWAP is not set
+ CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
+ # CONFIG_POSIX_MQUEUE is not set
+ # CONFIG_BSD_PROCESS_ACCT is not set
+-CONFIG_SYSCTL=y
++# CONFIG_TASKSTATS is not set
+ # CONFIG_AUDIT is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_KOBJECT_UEVENT=y
+ # CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++CONFIG_NAMESPACES=y
++# CONFIG_UTS_NS is not set
++# CONFIG_IPC_NS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++CONFIG_BLK_DEV_INITRD=y
+ CONFIG_INITRAMFS_SOURCE=""
+ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
+ # CONFIG_EMBEDDED is not set
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
+ CONFIG_KALLSYMS=y
+ # CONFIG_KALLSYMS_ALL is not set
+ # CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
+ CONFIG_PRINTK=y
+ CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
+ CONFIG_BASE_FULL=y
+ CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
+ CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
+ CONFIG_SHMEM=y
+-CONFIG_CC_ALIGN_FUNCTIONS=0
+-CONFIG_CC_ALIGN_LABELS=0
+-CONFIG_CC_ALIGN_LOOPS=0
+-CONFIG_CC_ALIGN_JUMPS=0
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
+ # CONFIG_TINY_SHMEM is not set
+ CONFIG_BASE_SMALL=0
+-
+-#
+-# Loadable module support
+-#
+ CONFIG_MODULES=y
+ CONFIG_MODULE_UNLOAD=y
+ # CONFIG_MODULE_FORCE_UNLOAD is not set
+-CONFIG_OBSOLETE_MODPARM=y
+ # CONFIG_MODVERSIONS is not set
+ # CONFIG_MODULE_SRCVERSION_ALL is not set
+ CONFIG_KMOD=y
+-
+-#
+-# Block layer
+-#
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
+
+ #
+ # IO Schedulers
+@@ -77,66 +120,111 @@ CONFIG_DEFAULT_AS=y
+ # CONFIG_DEFAULT_CFQ is not set
+ # CONFIG_DEFAULT_NOOP is not set
+ CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
+
+ #
+ # System Type
+ #
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++CONFIG_ARCH_AT91=y
+ # CONFIG_ARCH_CLPS7500 is not set
+ # CONFIG_ARCH_CLPS711X is not set
+ # CONFIG_ARCH_CO285 is not set
+ # CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
+ # CONFIG_ARCH_FOOTBRIDGE is not set
+-# CONFIG_ARCH_INTEGRATOR is not set
+-# CONFIG_ARCH_IOP3XX is not set
+-# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
+ # CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
+ # CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_ORION is not set
++# CONFIG_ARCH_PNX4008 is not set
+ # CONFIG_ARCH_PXA is not set
+ # CONFIG_ARCH_RPC is not set
+ # CONFIG_ARCH_SA1100 is not set
+ # CONFIG_ARCH_S3C2410 is not set
+ # CONFIG_ARCH_SHARK is not set
+ # CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
+ # CONFIG_ARCH_OMAP is not set
+-# CONFIG_ARCH_VERSATILE is not set
+-# CONFIG_ARCH_REALVIEW is not set
+-# CONFIG_ARCH_IMX is not set
+-# CONFIG_ARCH_H720X is not set
+-# CONFIG_ARCH_AAEC2000 is not set
+-CONFIG_ARCH_AT91=y
+-CONFIG_ARCH_AT91RM9200=y
++# CONFIG_ARCH_MSM7X00A is not set
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
+
+ #
+-# AT91RM9200 Implementations
++# Atmel AT91 System-on-Chip
+ #
++CONFIG_ARCH_AT91RM9200=y
++# CONFIG_ARCH_AT91SAM9260 is not set
++# CONFIG_ARCH_AT91SAM9261 is not set
++# CONFIG_ARCH_AT91SAM9263 is not set
++# CONFIG_ARCH_AT91SAM9RL is not set
++# CONFIG_ARCH_AT91CAP9 is not set
++# CONFIG_ARCH_AT91X40 is not set
++CONFIG_AT91_PMC_UNIT=y
+
+ #
+ # AT91RM9200 Board Type
+ #
++# CONFIG_MACH_ONEARM is not set
+ # CONFIG_ARCH_AT91RM9200DK is not set
+ # CONFIG_MACH_AT91RM9200EK is not set
+ # CONFIG_MACH_CSB337 is not set
+ CONFIG_MACH_CSB637=y
+ # CONFIG_MACH_CARMEVA is not set
+-# CONFIG_MACH_KB9200 is not set
+ # CONFIG_MACH_ATEB9200 is not set
++# CONFIG_MACH_KB9200 is not set
++# CONFIG_MACH_PICOTUX2XX is not set
++# CONFIG_MACH_KAFA is not set
+
+ #
+-# AT91RM9200 Feature Selections
++# AT91 Board Options
++#
++
++#
++# AT91 Feature Selections
+ #
+ CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
++CONFIG_AT91_TIMER_HZ=128
++CONFIG_AT91_EARLY_DBGU=y
++# CONFIG_AT91_EARLY_USART0 is not set
++# CONFIG_AT91_EARLY_USART1 is not set
++# CONFIG_AT91_EARLY_USART2 is not set
++# CONFIG_AT91_EARLY_USART3 is not set
++# CONFIG_AT91_EARLY_USART4 is not set
++# CONFIG_AT91_EARLY_USART5 is not set
+
+ #
+ # Processor Type
+ #
+ CONFIG_CPU_32=y
+ CONFIG_CPU_ARM920T=y
+-CONFIG_CPU_32v4=y
++CONFIG_CPU_32v4T=y
+ CONFIG_CPU_ABRT_EV4T=y
+ CONFIG_CPU_CACHE_V4WT=y
+ CONFIG_CPU_CACHE_VIVT=y
+ CONFIG_CPU_COPY_V4WB=y
+ CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
+
+ #
+ # Processor Features
+@@ -145,15 +233,13 @@ CONFIG_CPU_TLB_V4WBI=y
+ # CONFIG_CPU_ICACHE_DISABLE is not set
+ # CONFIG_CPU_DCACHE_DISABLE is not set
+ # CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_OUTER_CACHE is not set
+
+ #
+ # Bus support
+ #
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# PCCARD (PCMCIA/CardBus) support
+-#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
+ CONFIG_PCCARD=y
+ # CONFIG_PCMCIA_DEBUG is not set
+ CONFIG_PCMCIA=y
+@@ -168,8 +254,13 @@ CONFIG_AT91_CF=y
+ #
+ # Kernel Features
+ #
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+ # CONFIG_PREEMPT is not set
+-# CONFIG_NO_IDLE_HZ is not set
++CONFIG_HZ=128
++# CONFIG_AEABI is not set
+ # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+ CONFIG_SELECT_MEMORY_MODEL=y
+ CONFIG_FLATMEM_MANUAL=y
+@@ -178,9 +269,13 @@ CONFIG_FLATMEM_MANUAL=y
+ CONFIG_FLATMEM=y
+ CONFIG_FLAT_NODE_MEM_MAP=y
+ # CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+ CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
+ CONFIG_LEDS=y
+-CONFIG_LEDS_TIMER=y
+ CONFIG_LEDS_CPU=y
+ CONFIG_ALIGNMENT_TRAP=y
+
+@@ -191,6 +286,7 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
+ CONFIG_ZBOOT_ROM_BSS=0x0
+ CONFIG_CMDLINE="mem=32M console=ttyS0,38400 initrd=0x20410000,3145728 root=/dev/ram0 rw"
+ # CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
+
+ #
+ # Floating point emulation
+@@ -215,6 +311,7 @@ CONFIG_BINFMT_ELF=y
+ # Power management options
+ #
+ # CONFIG_PM is not set
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
+
+ #
+ # Networking
+@@ -227,6 +324,11 @@ CONFIG_NET=y
+ CONFIG_PACKET=y
+ # CONFIG_PACKET_MMAP is not set
+ CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
+ # CONFIG_NET_KEY is not set
+ CONFIG_INET=y
+ # CONFIG_IP_MULTICAST is not set
+@@ -243,23 +345,26 @@ CONFIG_IP_PNP_BOOTP=y
+ # CONFIG_INET_AH is not set
+ # CONFIG_INET_ESP is not set
+ # CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
+ # CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
+ CONFIG_INET_DIAG=y
+ CONFIG_INET_TCP_DIAG=y
+ # CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_BIC=y
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
+ # CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
+ # CONFIG_NETFILTER is not set
+-
+-#
+-# DCCP Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_IP_DCCP is not set
+-
+-#
+-# SCTP Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
+ # CONFIG_ATM is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_VLAN_8021Q is not set
+@@ -269,13 +374,8 @@ CONFIG_TCP_CONG_BIC=y
+ # CONFIG_ATALK is not set
+ # CONFIG_X25 is not set
+ # CONFIG_LAPB is not set
+-# CONFIG_NET_DIVERT is not set
+ # CONFIG_ECONET is not set
+ # CONFIG_WAN_ROUTER is not set
+-
+-#
+-# QoS and/or fair queueing
+-#
+ # CONFIG_NET_SCHED is not set
+
+ #
+@@ -283,9 +383,20 @@ CONFIG_TCP_CONG_BIC=y
+ #
+ # CONFIG_NET_PKTGEN is not set
+ # CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
+ # CONFIG_IRDA is not set
+ # CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
+ # CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
+
+ #
+ # Device Drivers
+@@ -294,19 +405,14 @@ CONFIG_TCP_CONG_BIC=y
+ #
+ # Generic Driver Options
+ #
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+ CONFIG_STANDALONE=y
+ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ CONFIG_FW_LOADER=y
+ # CONFIG_DEBUG_DRIVER is not set
+-
+-#
+-# Connector - unified userspace <-> kernelspace linker
+-#
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
+ # CONFIG_CONNECTOR is not set
+-
+-#
+-# Memory Technology Devices (MTD)
+-#
+ CONFIG_MTD=y
+ # CONFIG_MTD_DEBUG is not set
+ # CONFIG_MTD_CONCAT is not set
+@@ -319,11 +425,14 @@ CONFIG_MTD_CMDLINE_PARTS=y
+ # User Modules And Translation Layers
+ #
+ CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
+ CONFIG_MTD_BLOCK=y
+ # CONFIG_FTL is not set
+ # CONFIG_NFTL is not set
+ # CONFIG_INFTL is not set
+ # CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
+
+ #
+ # RAM/ROM/Flash chip drivers
+@@ -349,15 +458,14 @@ CONFIG_MTD_CFI_UTIL=y
+ # CONFIG_MTD_RAM is not set
+ # CONFIG_MTD_ROM is not set
+ # CONFIG_MTD_ABSENT is not set
+-# CONFIG_MTD_XIP is not set
+
+ #
+ # Mapping drivers for chip access
+ #
+ # CONFIG_MTD_COMPLEX_MAPPINGS is not set
+ CONFIG_MTD_PHYSMAP=y
+-CONFIG_MTD_PHYSMAP_START=0
+-CONFIG_MTD_PHYSMAP_LEN=0
++CONFIG_MTD_PHYSMAP_START=0x0
++CONFIG_MTD_PHYSMAP_LEN=0x0
+ CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+ # CONFIG_MTD_ARM_INTEGRATOR is not set
+ # CONFIG_MTD_PLATRAM is not set
+@@ -368,7 +476,6 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+ # CONFIG_MTD_SLRAM is not set
+ # CONFIG_MTD_PHRAM is not set
+ # CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLKMTD is not set
+ # CONFIG_MTD_BLOCK2MTD is not set
+
+ #
+@@ -377,30 +484,15 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_AT91_DATAFLASH is not set
+-
+-#
+-# NAND Flash Device Drivers
+-#
+ # CONFIG_MTD_NAND is not set
+-
+-#
+-# OneNAND Flash Device Drivers
+-#
+ # CONFIG_MTD_ONENAND is not set
+
+ #
+-# Parallel port support
++# UBI - Unsorted block images
+ #
++# CONFIG_MTD_UBI is not set
+ # CONFIG_PARPORT is not set
+-
+-#
+-# Plug and Play support
+-#
+-
+-#
+-# Block devices
+-#
++CONFIG_BLK_DEV=y
+ # CONFIG_BLK_DEV_COW_COMMON is not set
+ CONFIG_BLK_DEV_LOOP=y
+ # CONFIG_BLK_DEV_CRYPTOLOOP is not set
+@@ -409,13 +501,15 @@ CONFIG_BLK_DEV_LOOP=y
+ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_COUNT=16
+ CONFIG_BLK_DEV_RAM_SIZE=8192
+-CONFIG_BLK_DEV_INITRD=y
++# CONFIG_BLK_DEV_XIP is not set
+ # CONFIG_CDROM_PKTCDVD is not set
+ # CONFIG_ATA_OVER_ETH is not set
+-
+-#
+-# ATA/ATAPI/MFM/RLL support
+-#
++CONFIG_MISC_DEVICES=y
++# CONFIG_ATMEL_PWM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ATMEL_SSC is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
+ # CONFIG_IDE is not set
+
+ #
+@@ -423,6 +517,9 @@ CONFIG_BLK_DEV_INITRD=y
+ #
+ # CONFIG_RAID_ATTRS is not set
+ CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
+ CONFIG_SCSI_PROC_FS=y
+
+ #
+@@ -441,114 +538,78 @@ CONFIG_SCSI_PROC_FS=y
+ # CONFIG_SCSI_MULTI_LUN is not set
+ # CONFIG_SCSI_CONSTANTS is not set
+ # CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
+
+ #
+-# SCSI Transport Attributes
++# SCSI Transports
+ #
+ # CONFIG_SCSI_SPI_ATTRS is not set
+ # CONFIG_SCSI_FC_ATTRS is not set
+ # CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_ATTRS is not set
+-
+-#
+-# SCSI low-level drivers
+-#
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
+ # CONFIG_ISCSI_TCP is not set
+-# CONFIG_SCSI_SATA is not set
+ # CONFIG_SCSI_DEBUG is not set
+-
+-#
+-# PCMCIA SCSI adapter support
+-#
+-# CONFIG_PCMCIA_AHA152X is not set
+-# CONFIG_PCMCIA_FDOMAIN is not set
+-# CONFIG_PCMCIA_NINJA_SCSI is not set
+-# CONFIG_PCMCIA_QLOGIC is not set
+-# CONFIG_PCMCIA_SYM53C500 is not set
+-
+-#
+-# Multi-device support (RAID and LVM)
+-#
++# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
++# CONFIG_ATA is not set
+ # CONFIG_MD is not set
+-
+-#
+-# Fusion MPT device support
+-#
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-
+-#
+-# I2O device support
+-#
+-
+-#
+-# Network device support
+-#
+ CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
+ # CONFIG_DUMMY is not set
+ # CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
+ # CONFIG_EQUALIZER is not set
+ # CONFIG_TUN is not set
+-
+-#
+-# PHY device support
+-#
++# CONFIG_VETH is not set
+ # CONFIG_PHYLIB is not set
+-
+-#
+-# Ethernet (10 or 100Mbit)
+-#
+ CONFIG_NET_ETHERNET=y
+ CONFIG_MII=y
+ CONFIG_ARM_AT91_ETHER=y
++# CONFIG_AX88796 is not set
+ # CONFIG_SMC91X is not set
++# CONFIG_SMSC911X is not set
+ # CONFIG_DM9000 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++# CONFIG_CS89x0 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_E1000E_ENABLED is not set
++CONFIG_NETDEV_10000=y
+
+ #
+-# Ethernet (1000 Mbit)
++# Wireless LAN
+ #
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
+
+ #
+-# Ethernet (10000 Mbit)
+-#
+-
+-#
+-# Token Ring devices
+-#
+-
+-#
+-# Wireless LAN (non-hamradio)
+-#
+-# CONFIG_NET_RADIO is not set
+-
+-#
+-# PCMCIA network device support
++# USB Network Adapters
+ #
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
+ # CONFIG_NET_PCMCIA is not set
+-
+-#
+-# Wan interfaces
+-#
+ # CONFIG_WAN is not set
+ # CONFIG_PPP is not set
+ # CONFIG_SLIP is not set
+-# CONFIG_SHAPER is not set
+ # CONFIG_NETCONSOLE is not set
+ # CONFIG_NETPOLL is not set
+ # CONFIG_NET_POLL_CONTROLLER is not set
+-
+-#
+-# ISDN subsystem
+-#
+ # CONFIG_ISDN is not set
+
+ #
+ # Input device support
+ #
+ CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
+
+ #
+ # Userland interfaces
+@@ -558,7 +619,6 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y
+ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ # CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_TSDEV is not set
+ # CONFIG_INPUT_EVDEV is not set
+ # CONFIG_INPUT_EVBUG is not set
+
+@@ -568,6 +628,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ # CONFIG_INPUT_KEYBOARD is not set
+ # CONFIG_INPUT_MOUSE is not set
+ # CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
+ # CONFIG_INPUT_TOUCHSCREEN is not set
+ # CONFIG_INPUT_MISC is not set
+
+@@ -583,6 +644,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ CONFIG_VT=y
+ CONFIG_VT_CONSOLE=y
+ CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+
+ #
+@@ -595,64 +657,29 @@ CONFIG_HW_CONSOLE=y
+ #
+ CONFIG_SERIAL_ATMEL=y
+ CONFIG_SERIAL_ATMEL_CONSOLE=y
++CONFIG_SERIAL_ATMEL_PDC=y
+ # CONFIG_SERIAL_ATMEL_TTYAT is not set
+ CONFIG_SERIAL_CORE=y
+ CONFIG_SERIAL_CORE_CONSOLE=y
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_LEGACY_PTYS=y
+ CONFIG_LEGACY_PTY_COUNT=256
+-
+-#
+-# IPMI
+-#
+ # CONFIG_IPMI_HANDLER is not set
+-
+-#
+-# Watchdog Cards
+-#
+-CONFIG_WATCHDOG=y
+-CONFIG_WATCHDOG_NOWAYOUT=y
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_AT91RM9200_WATCHDOG=y
+-
+-#
+-# USB-based Watchdog Cards
+-#
+-# CONFIG_USBPCWATCHDOG is not set
++CONFIG_HW_RANDOM=m
+ # CONFIG_NVRAM is not set
+-CONFIG_RTC=y
+-# CONFIG_AT91RM9200_RTC is not set
+-# CONFIG_DTLK is not set
+ # CONFIG_R3964 is not set
+
+ #
+-# Ftape, the floppy tape device driver
+-#
+-
+-#
+ # PCMCIA character devices
+ #
+ # CONFIG_SYNCLINK_CS is not set
+ # CONFIG_CARDMAN_4000 is not set
+ # CONFIG_CARDMAN_4040 is not set
++# CONFIG_IPWIRELESS is not set
+ # CONFIG_RAW_DRIVER is not set
+-
+-#
+-# TPM devices
+-#
+ # CONFIG_TCG_TPM is not set
+-# CONFIG_TELCLOCK is not set
+-CONFIG_AT91_SPI=y
+-CONFIG_AT91_SPIDEV=y
+-
+-#
+-# I2C support
+-#
+ CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
+ CONFIG_I2C_CHARDEV=y
+
+ #
+@@ -665,43 +692,53 @@ CONFIG_I2C_CHARDEV=y
+ #
+ # I2C Hardware Bus support
+ #
+-CONFIG_I2C_AT91=y
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
+ # CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
+ # CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_PCA_ISA is not set
++# CONFIG_I2C_TINY_USB is not set
+
+ #
+ # Miscellaneous I2C Chip support
+ #
+-# CONFIG_SENSORS_DS1337 is not set
+-# CONFIG_SENSORS_DS1374 is not set
++# CONFIG_DS1682 is not set
+ # CONFIG_SENSORS_EEPROM is not set
+ # CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_PCF8575 is not set
+ # CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_SENSORS_RTC8564 is not set
++# CONFIG_TPS65010 is not set
+ # CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_RTC_X1205_I2C is not set
++# CONFIG_SENSORS_TSL2550 is not set
+ # CONFIG_I2C_DEBUG_CORE is not set
+ # CONFIG_I2C_DEBUG_ALGO is not set
+ # CONFIG_I2C_DEBUG_BUS is not set
+ # CONFIG_I2C_DEBUG_CHIP is not set
+
+ #
+-# Hardware Monitoring support
++# SPI support
+ #
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
+ CONFIG_HWMON=y
+ # CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
+ # CONFIG_SENSORS_ADM1021 is not set
+ # CONFIG_SENSORS_ADM1025 is not set
+ # CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
+ # CONFIG_SENSORS_ADM1031 is not set
+ # CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ASB100 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
+ # CONFIG_SENSORS_ATXP1 is not set
+ # CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_FSCHER is not set
+-# CONFIG_SENSORS_FSCPOS is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
+ # CONFIG_SENSORS_GL518SM is not set
+ # CONFIG_SENSORS_GL520SM is not set
+ # CONFIG_SENSORS_IT87 is not set
+@@ -715,39 +752,72 @@ CONFIG_HWMON=y
+ # CONFIG_SENSORS_LM87 is not set
+ # CONFIG_SENSORS_LM90 is not set
+ # CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
+ # CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
+ # CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_DME1737 is not set
+ # CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
+ # CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VT1211 is not set
+ # CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
+ # CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
+ # CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
+ # CONFIG_SENSORS_W83627HF is not set
+ # CONFIG_SENSORS_W83627EHF is not set
+ # CONFIG_HWMON_DEBUG_CHIP is not set
++CONFIG_WATCHDOG=y
++CONFIG_WATCHDOG_NOWAYOUT=y
+
+ #
+-# Misc devices
++# Watchdog Device Drivers
+ #
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_AT91RM9200_WATCHDOG=y
+
+ #
+-# Multimedia Capabilities Port drivers
++# USB-based Watchdog Cards
+ #
++# CONFIG_USBPCWATCHDOG is not set
+
+ #
+-# Multimedia devices
++# Sonics Silicon Backplane
+ #
+-# CONFIG_VIDEO_DEV is not set
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
+
+ #
+-# Digital Video Broadcasting Devices
++# Multifunction device drivers
+ #
+-# CONFIG_DVB is not set
++# CONFIG_MFD_SM501 is not set
++# CONFIG_MFD_ASIC3 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
+
+ #
+ # Graphics support
+ #
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+ # CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
+
+ #
+ # Console display driver support
+@@ -759,20 +829,34 @@ CONFIG_DUMMY_CONSOLE=y
+ # Sound
+ #
+ # CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++CONFIG_HID_DEBUG=y
++# CONFIG_HIDRAW is not set
+
+ #
+-# USB support
++# USB Input Devices
+ #
++# CONFIG_USB_HID is not set
++
++#
++# USB HID Boot Protocol drivers
++#
++# CONFIG_USB_KBD is not set
++# CONFIG_USB_MOUSE is not set
++CONFIG_USB_SUPPORT=y
+ CONFIG_USB_ARCH_HAS_HCD=y
+ CONFIG_USB_ARCH_HAS_OHCI=y
++# CONFIG_USB_ARCH_HAS_EHCI is not set
+ CONFIG_USB=y
+ CONFIG_USB_DEBUG=y
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+ #
+ # Miscellaneous USB options
+ #
+ CONFIG_USB_DEVICEFS=y
+-# CONFIG_USB_BANDWIDTH is not set
++CONFIG_USB_DEVICE_CLASS=y
+ # CONFIG_USB_DYNAMIC_MINORS is not set
+ # CONFIG_USB_OTG is not set
+
+@@ -781,9 +865,11 @@ CONFIG_USB_DEVICEFS=y
+ #
+ # CONFIG_USB_ISP116X_HCD is not set
+ CONFIG_USB_OHCI_HCD=y
+-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+ # CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
+
+ #
+ # USB Device Class drivers
+@@ -802,80 +888,42 @@ CONFIG_USB_STORAGE=y
+ # CONFIG_USB_STORAGE_DEBUG is not set
+ # CONFIG_USB_STORAGE_DATAFAB is not set
+ # CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
+ # CONFIG_USB_STORAGE_DPCM is not set
+ # CONFIG_USB_STORAGE_USBAT is not set
+ # CONFIG_USB_STORAGE_SDDR09 is not set
+ # CONFIG_USB_STORAGE_SDDR55 is not set
+ # CONFIG_USB_STORAGE_JUMPSHOT is not set
+-
+-#
+-# USB Input Devices
+-#
+-# CONFIG_USB_HID is not set
+-
+-#
+-# USB HID Boot Protocol drivers
+-#
+-# CONFIG_USB_KBD is not set
+-# CONFIG_USB_MOUSE is not set
+-# CONFIG_USB_AIPTEK is not set
+-# CONFIG_USB_WACOM is not set
+-# CONFIG_USB_ACECAD is not set
+-# CONFIG_USB_KBTAB is not set
+-# CONFIG_USB_POWERMATE is not set
+-# CONFIG_USB_MTOUCH is not set
+-# CONFIG_USB_ITMTOUCH is not set
+-# CONFIG_USB_EGALAX is not set
+-# CONFIG_USB_YEALINK is not set
+-# CONFIG_USB_XPAD is not set
+-# CONFIG_USB_ATI_REMOTE is not set
+-# CONFIG_USB_KEYSPAN_REMOTE is not set
+-# CONFIG_USB_APPLETOUCH is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
+
+ #
+ # USB Imaging devices
+ #
+ # CONFIG_USB_MDC800 is not set
+ # CONFIG_USB_MICROTEK is not set
+-
+-#
+-# USB Multimedia devices
+-#
+-# CONFIG_USB_DABUSB is not set
+-
+-#
+-# Video4Linux support is needed for USB Multimedia device support
+-#
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
+ CONFIG_USB_MON=y
+
+ #
+ # USB port drivers
+ #
+-
+-#
+-# USB Serial Converter support
+-#
+ CONFIG_USB_SERIAL=y
+ CONFIG_USB_SERIAL_CONSOLE=y
++CONFIG_USB_EZUSB=y
+ CONFIG_USB_SERIAL_GENERIC=y
++# CONFIG_USB_SERIAL_AIRCABLE is not set
+ # CONFIG_USB_SERIAL_AIRPRIME is not set
+-# CONFIG_USB_SERIAL_ANYDATA is not set
++# CONFIG_USB_SERIAL_ARK3116 is not set
+ # CONFIG_USB_SERIAL_BELKIN is not set
++# CONFIG_USB_SERIAL_CH341 is not set
+ # CONFIG_USB_SERIAL_WHITEHEAT is not set
+ # CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+ # CONFIG_USB_SERIAL_CP2101 is not set
+ # CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+ # CONFIG_USB_SERIAL_EMPEG is not set
+ CONFIG_USB_SERIAL_FTDI_SIO=y
++# CONFIG_USB_SERIAL_FUNSOFT is not set
+ # CONFIG_USB_SERIAL_VISOR is not set
+ # CONFIG_USB_SERIAL_IPAQ is not set
+ # CONFIG_USB_SERIAL_IR is not set
+@@ -883,6 +931,7 @@ CONFIG_USB_SERIAL_FTDI_SIO=y
+ # CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+ # CONFIG_USB_SERIAL_GARMIN is not set
+ # CONFIG_USB_SERIAL_IPW is not set
++# CONFIG_USB_SERIAL_IUU is not set
+ # CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+ CONFIG_USB_SERIAL_KEYSPAN=y
+ CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+@@ -900,46 +949,66 @@ CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+ # CONFIG_USB_SERIAL_KLSI is not set
+ # CONFIG_USB_SERIAL_KOBIL_SCT is not set
+ CONFIG_USB_SERIAL_MCT_U232=y
++# CONFIG_USB_SERIAL_MOS7720 is not set
++# CONFIG_USB_SERIAL_MOS7840 is not set
++# CONFIG_USB_SERIAL_NAVMAN is not set
+ # CONFIG_USB_SERIAL_PL2303 is not set
++# CONFIG_USB_SERIAL_OTI6858 is not set
+ # CONFIG_USB_SERIAL_HP4X is not set
+ # CONFIG_USB_SERIAL_SAFE is not set
++# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+ # CONFIG_USB_SERIAL_TI is not set
+ # CONFIG_USB_SERIAL_CYBERJACK is not set
+ # CONFIG_USB_SERIAL_XIRCOM is not set
+ # CONFIG_USB_SERIAL_OPTION is not set
+ # CONFIG_USB_SERIAL_OMNINET is not set
+-CONFIG_USB_EZUSB=y
++# CONFIG_USB_SERIAL_DEBUG is not set
+
+ #
+ # USB Miscellaneous drivers
+ #
+ # CONFIG_USB_EMI62 is not set
+ # CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
+ # CONFIG_USB_AUERSWALD is not set
+ # CONFIG_USB_RIO500 is not set
+ # CONFIG_USB_LEGOTOWER is not set
+ # CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
+ # CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
+ # CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGETKIT is not set
+-# CONFIG_USB_PHIDGETSERVO is not set
++# CONFIG_USB_PHIDGET is not set
+ # CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
+ # CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
+ # CONFIG_USB_TEST is not set
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=y
+
+ #
+-# USB DSL modem support
++# LED drivers
+ #
++CONFIG_LEDS_GPIO=y
+
+ #
+-# USB Gadget Support
++# LED Triggers
+ #
+-# CONFIG_USB_GADGET is not set
++CONFIG_LEDS_TRIGGERS=y
++# CONFIG_LEDS_TRIGGER_TIMER is not set
++CONFIG_LEDS_TRIGGER_HEARTBEAT=y
++CONFIG_RTC_LIB=y
++# CONFIG_RTC_CLASS is not set
+
+ #
+-# MMC/SD Card support
++# Userspace I/O
+ #
+-# CONFIG_MMC is not set
++# CONFIG_UIO is not set
+
+ #
+ # File systems
+@@ -948,16 +1017,17 @@ CONFIG_EXT2_FS=y
+ # CONFIG_EXT2_FS_XATTR is not set
+ # CONFIG_EXT2_FS_XIP is not set
+ # CONFIG_EXT3_FS is not set
+-# CONFIG_JBD is not set
++# CONFIG_EXT4DEV_FS is not set
+ # CONFIG_REISERFS_FS is not set
+ # CONFIG_JFS_FS is not set
+ # CONFIG_FS_POSIX_ACL is not set
+ # CONFIG_XFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_ROMFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
+ CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
+ # CONFIG_QUOTA is not set
+-CONFIG_DNOTIFY=y
+ # CONFIG_AUTOFS_FS is not set
+ # CONFIG_AUTOFS4_FS is not set
+ # CONFIG_FUSE_FS is not set
+@@ -979,11 +1049,12 @@ CONFIG_DNOTIFY=y
+ # Pseudo filesystems
+ #
+ CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
+ CONFIG_SYSFS=y
+ CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
+ # CONFIG_HUGETLB_PAGE is not set
+-CONFIG_RAMFS=y
+-# CONFIG_RELAYFS_FS is not set
++# CONFIG_CONFIGFS_FS is not set
+
+ #
+ # Miscellaneous filesystems
+@@ -995,18 +1066,16 @@ CONFIG_RAMFS=y
+ # CONFIG_BEFS_FS is not set
+ # CONFIG_BFS_FS is not set
+ # CONFIG_EFS_FS is not set
+-# CONFIG_JFFS_FS is not set
+ # CONFIG_JFFS2_FS is not set
+ CONFIG_CRAMFS=y
+ # CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
+ # CONFIG_HPFS_FS is not set
+ # CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
+ # CONFIG_SYSV_FS is not set
+ # CONFIG_UFS_FS is not set
+-
+-#
+-# Network File Systems
+-#
++CONFIG_NETWORK_FILESYSTEMS=y
+ CONFIG_NFS_FS=y
+ CONFIG_NFS_V3=y
+ # CONFIG_NFS_V3_ACL is not set
+@@ -1019,6 +1088,7 @@ CONFIG_LOCKD_V4=y
+ CONFIG_NFS_COMMON=y
+ CONFIG_SUNRPC=y
+ CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
+ CONFIG_RPCSEC_GSS_KRB5=y
+ # CONFIG_RPCSEC_GSS_SPKM3 is not set
+ # CONFIG_SMB_FS is not set
+@@ -1026,45 +1096,57 @@ CONFIG_RPCSEC_GSS_KRB5=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
+-# CONFIG_9P_FS is not set
+
+ #
+ # Partition Types
+ #
+ # CONFIG_PARTITION_ADVANCED is not set
+ CONFIG_MSDOS_PARTITION=y
+-
+-#
+-# Native Language Support
+-#
+ # CONFIG_NLS is not set
+-
+-#
+-# Profiling support
+-#
+-# CONFIG_PROFILING is not set
++# CONFIG_DLM is not set
+
+ #
+ # Kernel hacking
+ #
+ # CONFIG_PRINTK_TIME is not set
+-CONFIG_DEBUG_KERNEL=y
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
+ # CONFIG_MAGIC_SYSRQ is not set
+-CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
+ CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
+ # CONFIG_SCHEDSTATS is not set
+-# CONFIG_DEBUG_SLAB is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
+ # CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
+ # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+ # CONFIG_DEBUG_KOBJECT is not set
+ CONFIG_DEBUG_BUGVERBOSE=y
+ # CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_FS is not set
+ # CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
+ CONFIG_FRAME_POINTER=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
+ # CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
+ CONFIG_DEBUG_USER=y
+ # CONFIG_DEBUG_ERRORS is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
+ CONFIG_DEBUG_LL=y
+ # CONFIG_DEBUG_ICEDCC is not set
+
+@@ -1073,12 +1155,14 @@ CONFIG_DEBUG_LL=y
+ #
+ # CONFIG_KEYS is not set
+ # CONFIG_SECURITY is not set
+-
+-#
+-# Cryptographic options
+-#
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+ CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
+ # CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
+ # CONFIG_CRYPTO_NULL is not set
+ # CONFIG_CRYPTO_MD4 is not set
+ CONFIG_CRYPTO_MD5=y
+@@ -1087,7 +1171,18 @@ CONFIG_CRYPTO_MD5=y
+ # CONFIG_CRYPTO_SHA512 is not set
+ # CONFIG_CRYPTO_WP512 is not set
+ # CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++CONFIG_CRYPTO_CBC=y
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
+ CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
+ # CONFIG_CRYPTO_BLOWFISH is not set
+ # CONFIG_CRYPTO_TWOFISH is not set
+ # CONFIG_CRYPTO_SERPENT is not set
+@@ -1098,20 +1193,29 @@ CONFIG_CRYPTO_DES=y
+ # CONFIG_CRYPTO_ARC4 is not set
+ # CONFIG_CRYPTO_KHAZAD is not set
+ # CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
+ # CONFIG_CRYPTO_DEFLATE is not set
+ # CONFIG_CRYPTO_MICHAEL_MIC is not set
+ # CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
+ # CONFIG_CRYPTO_TEST is not set
+-
+-#
+-# Hardware crypto devices
+-#
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
+
+ #
+ # Library routines
+ #
++CONFIG_BITREVERSE=y
+ # CONFIG_CRC_CCITT is not set
+ # CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
+ CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
+ # CONFIG_LIBCRC32C is not set
+ CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/ecbat91_defconfig b/arch/arm/configs/ecbat91_defconfig
+new file mode 100644
+index 0000000..90ed214
+--- /dev/null
++++ b/arch/arm/configs/ecbat91_defconfig
+@@ -0,0 +1,1315 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.22-rc4
++# Sat Jun 9 01:30:18 2007
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++# CONFIG_GENERIC_TIME is not set
++# CONFIG_GENERIC_CLOCKEVENTS is not set
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ZONE_DMA=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_LOCK_KERNEL=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++# CONFIG_IPC_NS is not set
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_UTS_NS is not set
++# CONFIG_AUDIT is not set
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_LOG_BUF_SHIFT=14
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_BLK_DEV_INITRD is not set
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++# CONFIG_EMBEDDED is not set
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++
++#
++# Block layer
++#
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++# CONFIG_IOSCHED_DEADLINE is not set
++# CONFIG_IOSCHED_CFQ is not set
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++
++#
++# System Type
++#
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++CONFIG_ARCH_AT91=y
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++
++#
++# Atmel AT91 System-on-Chip
++#
++CONFIG_ARCH_AT91RM9200=y
++# CONFIG_ARCH_AT91SAM9260 is not set
++# CONFIG_ARCH_AT91SAM9261 is not set
++# CONFIG_ARCH_AT91SAM9263 is not set
++# CONFIG_ARCH_AT91SAM9RL is not set
++
++#
++# AT91RM9200 Board Type
++#
++# CONFIG_MACH_ONEARM is not set
++# CONFIG_ARCH_AT91RM9200DK is not set
++# CONFIG_MACH_AT91RM9200EK is not set
++# CONFIG_MACH_CSB337 is not set
++# CONFIG_MACH_CSB637 is not set
++# CONFIG_MACH_CARMEVA is not set
++# CONFIG_MACH_ATEB9200 is not set
++# CONFIG_MACH_KB9200 is not set
++# CONFIG_MACH_PICOTUX2XX is not set
++# CONFIG_MACH_KAFA is not set
++# CONFIG_MACH_CHUB is not set
++CONFIG_MACH_ECBAT91=y
++
++#
++# AT91 Board Options
++#
++# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
++
++#
++# AT91 Feature Selections
++#
++CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
++# CONFIG_ATMEL_TCLIB is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM920T=y
++CONFIG_CPU_32v4T=y
++CONFIG_CPU_ABRT_EV4T=y
++CONFIG_CPU_CACHE_V4WT=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_OUTER_CACHE is not set
++
++#
++# Bus support
++#
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++
++#
++# PCCARD (PCMCIA/CardBus) support
++#
++CONFIG_PCCARD=y
++# CONFIG_PCMCIA_DEBUG is not set
++CONFIG_PCMCIA=y
++CONFIG_PCMCIA_LOAD_CIS=y
++CONFIG_PCMCIA_IOCTL=y
++
++#
++# PC-card bridges
++#
++CONFIG_AT91_CF=y
++
++#
++# Kernel Features
++#
++# CONFIG_TICK_ONESHOT is not set
++CONFIG_PREEMPT=y
++# CONFIG_NO_IDLE_HZ is not set
++CONFIG_HZ=100
++# CONFIG_AEABI is not set
++# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_LEDS=y
++CONFIG_LEDS_TIMER=y
++CONFIG_LEDS_CPU=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="rootfstype=reiserfs root=/dev/mmcblk0p1 console=ttyS0,115200n8 rootdelay=1"
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++CONFIG_NET_SCH_FIFO=y
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++CONFIG_CFG80211=y
++CONFIG_WIRELESS_EXT=y
++CONFIG_MAC80211=y
++# CONFIG_MAC80211_DEBUG is not set
++CONFIG_IEEE80211=y
++# CONFIG_IEEE80211_DEBUG is not set
++CONFIG_IEEE80211_CRYPT_WEP=y
++# CONFIG_IEEE80211_CRYPT_CCMP is not set
++# CONFIG_IEEE80211_CRYPT_TKIP is not set
++CONFIG_IEEE80211_SOFTMAC=y
++CONFIG_IEEE80211_SOFTMAC_DEBUG=y
++# CONFIG_RFKILL is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++# CONFIG_STANDALONE is not set
++# CONFIG_PREVENT_FIRMWARE_BUILD is not set
++CONFIG_FW_LOADER=y
++# CONFIG_SYS_HYPERVISOR is not set
++
++#
++# Connector - unified userspace <-> kernelspace linker
++#
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++CONFIG_MTD_AFS_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++# CONFIG_MTD_CFI is not set
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++CONFIG_MTD_DATAFLASH=y
++# CONFIG_MTD_M25P80 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Plug and Play support
++#
++# CONFIG_PNPACPI is not set
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++# CONFIG_BLK_DEV_RAM is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++
++#
++# SCSI low-level drivers
++#
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_SCSI_DEBUG is not set
++
++#
++# PCMCIA SCSI adapter support
++#
++# CONFIG_PCMCIA_AHA152X is not set
++# CONFIG_PCMCIA_FDOMAIN is not set
++# CONFIG_PCMCIA_NINJA_SCSI is not set
++# CONFIG_PCMCIA_QLOGIC is not set
++# CONFIG_PCMCIA_SYM53C500 is not set
++# CONFIG_ATA is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Network device support
++#
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_PHYLIB is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_ARM_AT91_ETHER=y
++# CONFIG_SMC91X is not set
++# CONFIG_DM9000 is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET_MII is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_NET_PCMCIA is not set
++# CONFIG_WAN is not set
++CONFIG_PPP=y
++CONFIG_PPP_MULTILINK=y
++CONFIG_PPP_FILTER=y
++CONFIG_PPP_ASYNC=y
++# CONFIG_PPP_SYNC_TTY is not set
++# CONFIG_PPP_DEFLATE is not set
++# CONFIG_PPP_BSDCOMP is not set
++# CONFIG_PPP_MPPE is not set
++# CONFIG_PPPOE is not set
++# CONFIG_SLIP is not set
++CONFIG_SLHC=y
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_TSDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_ATMEL=y
++CONFIG_SERIAL_ATMEL_CONSOLE=y
++# CONFIG_SERIAL_ATMEL_TTYAT is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++
++#
++# IPMI
++#
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_WATCHDOG=y
++CONFIG_WATCHDOG_NOWAYOUT=y
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++# CONFIG_AT91RM9200_WATCHDOG is not set
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++# CONFIG_R3964 is not set
++
++#
++# PCMCIA character devices
++#
++# CONFIG_SYNCLINK_CS is not set
++# CONFIG_CARDMAN_4000 is not set
++# CONFIG_CARDMAN_4040 is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# TPM devices
++#
++# CONFIG_TCG_TPM is not set
++# CONFIG_AT91_SPI is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++CONFIG_I2C_ALGOBIT=y
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++CONFIG_I2C_GPIO=y
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_PCA is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_SENSORS_DS1337 is not set
++# CONFIG_SENSORS_DS1374 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++CONFIG_SPI=y
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++# CONFIG_SPI_ATMEL is not set
++CONFIG_SPI_BITBANG=y
++CONFIG_SPI_AT91=y
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++
++#
++# Dallas's 1-wire bus
++#
++# CONFIG_W1 is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_ABITUGURU is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ASB100 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_FSCHER is not set
++# CONFIG_SENSORS_FSCPOS is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM70 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++
++#
++# Misc devices
++#
++# CONFIG_BLINK is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# LED devices
++#
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=y
++
++#
++# LED drivers
++#
++
++#
++# LED Triggers
++#
++# CONFIG_LEDS_TRIGGERS is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
++
++#
++# Graphics support
++#
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_FB is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++
++#
++# HID Devices
++#
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++
++#
++# USB Input Devices
++#
++# CONFIG_USB_HID is not set
++
++#
++# USB HID Boot Protocol drivers
++#
++# CONFIG_USB_KBD is not set
++# CONFIG_USB_MOUSE is not set
++
++#
++# USB support
++#
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++# CONFIG_USB_DEVICE_CLASS is not set
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_SL811_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++CONFIG_USB_PRINTER=y
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++# CONFIG_USB_MON is not set
++
++#
++# USB port drivers
++#
++
++#
++# USB Serial Converter support
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++
++#
++# USB DSL modem support
++#
++
++#
++# USB Gadget Support
++#
++CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG_FILES is not set
++CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_FSL_USB2 is not set
++# CONFIG_USB_GADGET_NET2280 is not set
++# CONFIG_USB_GADGET_PXA2XX is not set
++# CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_LH7A40X is not set
++# CONFIG_USB_GADGET_OMAP is not set
++CONFIG_USB_GADGET_AT91=y
++CONFIG_USB_AT91=y
++# CONFIG_USB_GADGET_DUMMY_HCD is not set
++# CONFIG_USB_GADGET_DUALSPEED is not set
++# CONFIG_USB_ZERO is not set
++# CONFIG_USB_ETH is not set
++# CONFIG_USB_GADGETFS is not set
++# CONFIG_USB_FILE_STORAGE is not set
++# CONFIG_USB_G_SERIAL is not set
++# CONFIG_USB_MIDI_GADGET is not set
++CONFIG_MMC=y
++CONFIG_MMC_DEBUG=y
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++
++#
++# MMC/SD Host Controller Drivers
++#
++CONFIG_MMC_AT91=y
++
++#
++# Real Time Clock
++#
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++# CONFIG_RTC_HCTOSYS is not set
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_AT91RM9200=y
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_FS_MBCACHE=y
++CONFIG_REISERFS_FS=y
++# CONFIG_REISERFS_CHECK is not set
++# CONFIG_REISERFS_PROC_INFO is not set
++# CONFIG_REISERFS_FS_XATTR is not set
++# CONFIG_JFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++CONFIG_CONFIGFS_FS=y
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Network File Systems
++#
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++CONFIG_NFS_V3_ACL=y
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_ACL_SUPPORT=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++
++#
++# Native Language Support
++#
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++# CONFIG_NLS_CODEPAGE_437 is not set
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++# CONFIG_NLS_ISO8859_1 is not set
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++
++#
++# Distributed Lock Manager
++#
++# CONFIG_DLM is not set
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_FRAME_POINTER=y
++CONFIG_DEBUG_USER=y
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++
++#
++# Cryptographic options
++#
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++CONFIG_CRYPTO_SHA1=y
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++CONFIG_CRYPTO_AES=y
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++CONFIG_CRYPTO_ARC4=y
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Hardware crypto devices
++#
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=y
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/kafa_defconfig b/arch/arm/configs/kafa_defconfig
+index a0f48d5..ae51a40 100644
+--- a/arch/arm/configs/kafa_defconfig
++++ b/arch/arm/configs/kafa_defconfig
+@@ -587,14 +587,14 @@ CONFIG_I2C_CHARDEV=y
+ #
+ # I2C Algorithms
+ #
+-# CONFIG_I2C_ALGOBIT is not set
++CONFIG_I2C_ALGOBIT=y
+ # CONFIG_I2C_ALGOPCF is not set
+ # CONFIG_I2C_ALGOPCA is not set
+
+ #
+ # I2C Hardware Bus support
+ #
+-CONFIG_I2C_AT91=y
++CONFIG_I2C_GPIO=y
+ # CONFIG_I2C_PARPORT_LIGHT is not set
+ # CONFIG_I2C_STUB is not set
+ # CONFIG_I2C_PCA_ISA is not set
+diff --git a/arch/arm/configs/magician_defconfig b/arch/arm/configs/magician_defconfig
+new file mode 100644
+index 0000000..4d11678
+--- /dev/null
++++ b/arch/arm/configs/magician_defconfig
+@@ -0,0 +1,1182 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.24-rc6
++# Sun Dec 30 13:02:54 2007
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ZONE_DMA=y
++CONFIG_ARCH_MTD_XIP=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_LOCK_KERNEL=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++# CONFIG_AUDIT is not set
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_LOG_BUF_SHIFT=16
++# CONFIG_CGROUPS is not set
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_SYSFS_DEPRECATED is not set
++# CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++# CONFIG_UID16 is not set
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_FORCE_UNLOAD=y
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++# CONFIG_IOSCHED_DEADLINE is not set
++# CONFIG_IOSCHED_CFQ is not set
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++CONFIG_DEFAULT_NOOP=y
++CONFIG_DEFAULT_IOSCHED="noop"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++
++#
++# System Type
++#
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_PNX4008 is not set
++CONFIG_ARCH_PXA=y
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++
++#
++# Intel PXA2xx/PXA3xx Implementations
++#
++# CONFIG_ARCH_LUBBOCK is not set
++# CONFIG_MACH_LOGICPD_PXA270 is not set
++# CONFIG_MACH_MAINSTONE is not set
++# CONFIG_ARCH_PXA_IDP is not set
++# CONFIG_PXA_SHARPSL is not set
++# CONFIG_MACH_TRIZEPS4 is not set
++# CONFIG_MACH_EM_X270 is not set
++# CONFIG_MACH_ZYLONITE is not set
++# CONFIG_MACH_ARMCORE is not set
++CONFIG_MACH_MAGICIAN=y
++CONFIG_PXA27x=y
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_XSCALE=y
++CONFIG_CPU_32v5=y
++CONFIG_CPU_ABRT_EV5T=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_OUTER_CACHE is not set
++CONFIG_IWMMXT=y
++CONFIG_XSCALE_PMU=y
++
++#
++# Bus support
++#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++CONFIG_PREEMPT=y
++CONFIG_HZ=100
++CONFIG_AEABI=y
++CONFIG_OABI_COMPAT=y
++# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="keepinitrd"
++# CONFIG_XIP_KERNEL is not set
++CONFIG_KEXEC=y
++
++#
++# CPU Frequency scaling
++#
++CONFIG_CPU_FREQ=y
++CONFIG_CPU_FREQ_TABLE=y
++# CONFIG_CPU_FREQ_DEBUG is not set
++CONFIG_CPU_FREQ_STAT=y
++# CONFIG_CPU_FREQ_STAT_DETAILS is not set
++CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
++# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
++CONFIG_CPU_FREQ_GOV_ONDEMAND=y
++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Power management options
++#
++CONFIG_PM=y
++# CONFIG_PM_LEGACY is not set
++# CONFIG_PM_DEBUG is not set
++CONFIG_PM_SLEEP=y
++CONFIG_SUSPEND_UP_POSSIBLE=y
++CONFIG_SUSPEND=y
++CONFIG_APM_EMULATION=y
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++# CONFIG_IP_PNP_DHCP is not set
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++# CONFIG_INET_DIAG is not set
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IP_VS is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++CONFIG_NETFILTER=y
++# CONFIG_NETFILTER_DEBUG is not set
++
++#
++# Core Netfilter Configuration
++#
++# CONFIG_NETFILTER_NETLINK is not set
++# CONFIG_NF_CONNTRACK_ENABLED is not set
++# CONFIG_NF_CONNTRACK is not set
++# CONFIG_NETFILTER_XTABLES is not set
++
++#
++# IP: Netfilter Configuration
++#
++# CONFIG_IP_NF_QUEUE is not set
++# CONFIG_IP_NF_IPTABLES is not set
++# CONFIG_IP_NF_ARPTABLES is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++CONFIG_IRDA=m
++
++#
++# IrDA protocols
++#
++CONFIG_IRLAN=m
++# CONFIG_IRNET is not set
++CONFIG_IRCOMM=m
++CONFIG_IRDA_ULTRA=y
++
++#
++# IrDA options
++#
++CONFIG_IRDA_CACHE_LAST_LSAP=y
++CONFIG_IRDA_FAST_RR=y
++CONFIG_IRDA_DEBUG=y
++
++#
++# Infrared-port device drivers
++#
++
++#
++# SIR device drivers
++#
++CONFIG_IRTTY_SIR=m
++
++#
++# Dongle support
++#
++# CONFIG_DONGLE is not set
++
++#
++# Old SIR device drivers
++#
++# CONFIG_IRPORT_SIR is not set
++
++#
++# Old Serial dongle support
++#
++
++#
++# FIR device drivers
++#
++CONFIG_PXA_FICP=m
++CONFIG_BT=m
++CONFIG_BT_L2CAP=m
++CONFIG_BT_SCO=m
++CONFIG_BT_RFCOMM=m
++CONFIG_BT_RFCOMM_TTY=y
++CONFIG_BT_BNEP=m
++CONFIG_BT_BNEP_MC_FILTER=y
++CONFIG_BT_BNEP_PROTO_FILTER=y
++CONFIG_BT_HIDP=m
++
++#
++# Bluetooth device drivers
++#
++# CONFIG_BT_HCIUART is not set
++# CONFIG_BT_HCIVHCI is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++CONFIG_MTD_DEBUG=y
++CONFIG_MTD_DEBUG_VERBOSE=0
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_AFS_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=m
++CONFIG_MTD_BLKDEVS=m
++CONFIG_MTD_BLOCK=m
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++CONFIG_MTD_CFI_INTELEXT=y
++# CONFIG_MTD_CFI_AMDSTD is not set
++# CONFIG_MTD_CFI_STAA is not set
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++# CONFIG_MTD_XIP is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_START=0x00000000
++CONFIG_MTD_PHYSMAP_LEN=0x04000000
++CONFIG_MTD_PHYSMAP_BANKWIDTH=4
++# CONFIG_MTD_PXA2XX is not set
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_SHARP_SL is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_RAM is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_MISC_DEVICES is not set
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_NET_ETHERNET is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++CONFIG_PPP=m
++# CONFIG_PPP_MULTILINK is not set
++# CONFIG_PPP_FILTER is not set
++CONFIG_PPP_ASYNC=m
++# CONFIG_PPP_SYNC_TTY is not set
++CONFIG_PPP_DEFLATE=m
++CONFIG_PPP_BSDCOMP=m
++CONFIG_PPP_MPPE=m
++# CONFIG_PPPOE is not set
++# CONFIG_PPPOL2TP is not set
++# CONFIG_SLIP is not set
++CONFIG_SLHC=m
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ATKBD is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++# CONFIG_KEYBOARD_PXA27x is not set
++CONFIG_KEYBOARD_GPIO=y
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++CONFIG_INPUT_TOUCHSCREEN=y
++CONFIG_INPUT_MISC=y
++CONFIG_INPUT_UINPUT=m
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_PXA=y
++# CONFIG_SERIAL_PXA_CONSOLE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_UNIX98_PTYS=y
++# CONFIG_LEGACY_PTYS is not set
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=m
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=m
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_GPIO is not set
++CONFIG_I2C_PXA=m
++# CONFIG_I2C_PXA_SLAVE is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_SENSORS_DS1337 is not set
++# CONFIG_SENSORS_DS1374 is not set
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++CONFIG_W1=y
++
++#
++# 1-wire Bus Masters
++#
++# CONFIG_W1_MASTER_DS2482 is not set
++CONFIG_W1_MASTER_DS1WM=y
++
++#
++# 1-wire Slaves
++#
++# CONFIG_W1_SLAVE_THERM is not set
++# CONFIG_W1_SLAVE_SMEM is not set
++# CONFIG_W1_SLAVE_DS2433 is not set
++CONFIG_W1_SLAVE_DS2760=y
++CONFIG_POWER_SUPPLY=y
++# CONFIG_POWER_SUPPLY_DEBUG is not set
++CONFIG_PDA_POWER=y
++# CONFIG_APM_POWER is not set
++CONFIG_BATTERY_DS2760=y
++# CONFIG_HWMON is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++CONFIG_HTC_EGPIO=y
++CONFIG_HTC_PASIC3=y
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++CONFIG_FB=y
++# CONFIG_FIRMWARE_EDID is not set
++# CONFIG_FB_DDC is not set
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
++# CONFIG_FB_SYS_FILLRECT is not set
++# CONFIG_FB_SYS_COPYAREA is not set
++# CONFIG_FB_SYS_IMAGEBLIT is not set
++# CONFIG_FB_SYS_FOPS is not set
++CONFIG_FB_DEFERRED_IO=y
++# CONFIG_FB_SVGALIB is not set
++# CONFIG_FB_MACMODES is not set
++# CONFIG_FB_BACKLIGHT is not set
++# CONFIG_FB_MODE_HELPERS is not set
++# CONFIG_FB_TILEBLITTING is not set
++
++#
++# Frame buffer hardware drivers
++#
++# CONFIG_FB_S1D13XXX is not set
++CONFIG_FB_PXA=y
++# CONFIG_FB_PXA_PARAMETERS is not set
++# CONFIG_FB_MBX is not set
++# CONFIG_FB_VIRTUAL is not set
++CONFIG_BACKLIGHT_LCD_SUPPORT=y
++CONFIG_LCD_CLASS_DEVICE=y
++CONFIG_BACKLIGHT_CLASS_DEVICE=y
++CONFIG_BACKLIGHT_CORGI=y
++
++#
++# Display device support
++#
++CONFIG_DISPLAY_SUPPORT=y
++
++#
++# Display hardware drivers
++#
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE=y
++# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
++CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
++CONFIG_FONTS=y
++# CONFIG_FONT_8x8 is not set
++# CONFIG_FONT_8x16 is not set
++# CONFIG_FONT_6x11 is not set
++# CONFIG_FONT_7x14 is not set
++# CONFIG_FONT_PEARL_8x8 is not set
++# CONFIG_FONT_ACORN_8x8 is not set
++CONFIG_FONT_MINI_4x6=y
++# CONFIG_FONT_SUN8x16 is not set
++# CONFIG_FONT_SUN12x22 is not set
++# CONFIG_FONT_10x18 is not set
++# CONFIG_LOGO is not set
++
++#
++# Sound
++#
++CONFIG_SOUND=y
++
++#
++# Advanced Linux Sound Architecture
++#
++CONFIG_SND=m
++CONFIG_SND_TIMER=m
++CONFIG_SND_PCM=m
++# CONFIG_SND_SEQUENCER is not set
++CONFIG_SND_OSSEMUL=y
++CONFIG_SND_MIXER_OSS=m
++CONFIG_SND_PCM_OSS=m
++CONFIG_SND_PCM_OSS_PLUGINS=y
++# CONFIG_SND_DYNAMIC_MINORS is not set
++CONFIG_SND_SUPPORT_OLD_API=y
++CONFIG_SND_VERBOSE_PROCFS=y
++# CONFIG_SND_VERBOSE_PRINTK is not set
++# CONFIG_SND_DEBUG is not set
++
++#
++# Generic devices
++#
++# CONFIG_SND_DUMMY is not set
++# CONFIG_SND_MTPAV is not set
++# CONFIG_SND_SERIAL_U16550 is not set
++# CONFIG_SND_MPU401 is not set
++
++#
++# ALSA ARM devices
++#
++# CONFIG_SND_PXA2XX_AC97 is not set
++
++#
++# System on Chip audio support
++#
++CONFIG_SND_SOC=m
++CONFIG_SND_PXA2XX_SOC=m
++
++#
++# SoC Audio support for SuperH
++#
++
++#
++# Open Sound System
++#
++# CONFIG_SOUND_PRIME is not set
++# CONFIG_HID_SUPPORT is not set
++CONFIG_HID=m
++# CONFIG_USB_SUPPORT is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_BOUNCE=y
++CONFIG_SDIO_UART=m
++
++#
++# MMC/SD Host Controller Drivers
++#
++CONFIG_MMC_PXA=y
++CONFIG_NEW_LEDS=y
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++CONFIG_RTC_DEBUG=y
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_SA1100=y
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=m
++CONFIG_MSDOS_FS=m
++CONFIG_VFAT_FS=m
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++CONFIG_JFFS2_COMPRESSION_OPTIONS=y
++CONFIG_JFFS2_ZLIB=y
++CONFIG_JFFS2_LZO=y
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_JFFS2_CMODE_NONE is not set
++CONFIG_JFFS2_CMODE_PRIORITY=y
++# CONFIG_JFFS2_CMODE_SIZE is not set
++# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="utf8"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++CONFIG_NLS_CODEPAGE_1251=m
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++# CONFIG_DLM is not set
++
++#
++# Kernel hacking
++#
++CONFIG_PRINTK_TIME=y
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++# CONFIG_SCHED_DEBUG is not set
++# CONFIG_SCHEDSTATS is not set
++CONFIG_TIMER_STATS=y
++# CONFIG_DEBUG_SLAB is not set
++CONFIG_DEBUG_PREEMPT=y
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++CONFIG_DEBUG_MUTEXES=y
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_INFO is not set
++CONFIG_DEBUG_VM=y
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++CONFIG_FRAME_POINTER=y
++CONFIG_FORCED_INLINING=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++CONFIG_DEBUG_USER=y
++CONFIG_DEBUG_ERRORS=y
++CONFIG_DEBUG_LL=y
++# CONFIG_DEBUG_ICEDCC is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=m
++CONFIG_CRYPTO_BLKCIPHER=m
++CONFIG_CRYPTO_MANAGER=m
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++CONFIG_CRYPTO_SHA1=m
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++# CONFIG_CRYPTO_CBC is not set
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++CONFIG_CRYPTO_ARC4=m
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_HW is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=y
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_LZO_COMPRESS=y
++CONFIG_LZO_DECOMPRESS=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/ns9xxx_defconfig b/arch/arm/configs/ns9xxx_defconfig
+index 0e5794c..7dc1580 100644
+--- a/arch/arm/configs/ns9xxx_defconfig
++++ b/arch/arm/configs/ns9xxx_defconfig
+@@ -1,621 +1,79 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.20
+-# Thu Feb 15 20:51:47 2007
+-#
+-CONFIG_ARM=y
+-# CONFIG_GENERIC_TIME is not set
+-CONFIG_MMU=y
+-CONFIG_GENERIC_HARDIRQS=y
+-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+-CONFIG_HARDIRQS_SW_RESEND=y
+-CONFIG_GENERIC_IRQ_PROBE=y
+-CONFIG_RWSEM_GENERIC_SPINLOCK=y
+-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_VECTORS_BASE=0xffff0000
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# Code maturity level options
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-
+-#
+-# General setup
+-#
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-# CONFIG_IPC_NS is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_UTS_NS is not set
+ CONFIG_IKCONFIG=y
+ CONFIG_IKCONFIG_PROC=y
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_UID16=y
+-# CONFIG_SYSCTL_SYSCALL is not set
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_ALL is not set
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_EPOLL=y
+-CONFIG_SHMEM=y
+-CONFIG_SLAB=y
+-# CONFIG_VM_EVENT_COUNTERS is not set
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-# CONFIG_SLOB is not set
+-
+-#
+-# Loadable module support
+-#
++CONFIG_BLK_DEV_INITRD=y
+ CONFIG_MODULES=y
+ CONFIG_MODULE_UNLOAD=y
+-CONFIG_MODULE_FORCE_UNLOAD=y
+-CONFIG_MODVERSIONS=y
+-CONFIG_MODULE_SRCVERSION_ALL=y
+-CONFIG_KMOD=y
+-
+-#
+-# Block layer
+-#
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+ # CONFIG_IOSCHED_AS is not set
+ # CONFIG_IOSCHED_DEADLINE is not set
+ # CONFIG_IOSCHED_CFQ is not set
+-# CONFIG_DEFAULT_AS is not set
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-CONFIG_DEFAULT_NOOP=y
+-CONFIG_DEFAULT_IOSCHED="noop"
+-
+-#
+-# System Type
+-#
+-# CONFIG_ARCH_AAEC2000 is not set
+-# CONFIG_ARCH_INTEGRATOR is not set
+-# CONFIG_ARCH_REALVIEW is not set
+-# CONFIG_ARCH_VERSATILE is not set
+-# CONFIG_ARCH_AT91 is not set
+-# CONFIG_ARCH_CLPS7500 is not set
+-# CONFIG_ARCH_CLPS711X is not set
+-# CONFIG_ARCH_CO285 is not set
+-# CONFIG_ARCH_EBSA110 is not set
+-# CONFIG_ARCH_EP93XX is not set
+-# CONFIG_ARCH_FOOTBRIDGE is not set
+-# CONFIG_ARCH_NETX is not set
+-# CONFIG_ARCH_H720X is not set
+-# CONFIG_ARCH_IMX is not set
+-# CONFIG_ARCH_IOP32X is not set
+-# CONFIG_ARCH_IOP33X is not set
+-# CONFIG_ARCH_IOP13XX is not set
+-# CONFIG_ARCH_IXP4XX is not set
+-# CONFIG_ARCH_IXP2000 is not set
+-# CONFIG_ARCH_IXP23XX is not set
+-# CONFIG_ARCH_L7200 is not set
+ CONFIG_ARCH_NS9XXX=y
+-# CONFIG_ARCH_PNX4008 is not set
+-# CONFIG_ARCH_PXA is not set
+-# CONFIG_ARCH_RPC is not set
+-# CONFIG_ARCH_SA1100 is not set
+-# CONFIG_ARCH_S3C2410 is not set
+-# CONFIG_ARCH_SHARK is not set
+-# CONFIG_ARCH_LH7A40X is not set
+-# CONFIG_ARCH_OMAP is not set
+-
+-#
+-# NS9xxx Implementations
+-#
++CONFIG_MACH_A9M9360=y
++CONFIG_MACH_A9M9750=y
++CONFIG_MACH_CC7UCAMRY=y
++CONFIG_MACH_CC9C=y
++CONFIG_MACH_CC9P9210=y
++CONFIG_MACH_CC9P9210JS=y
++CONFIG_MACH_CC9P9215=y
++CONFIG_MACH_CC9P9215JS=y
+ CONFIG_MACH_CC9P9360DEV=y
+-CONFIG_PROCESSOR_NS9360=y
+-CONFIG_BOARD_A9M9750DEV=y
+-
+-#
+-# Processor Type
+-#
+-CONFIG_CPU_32=y
+-CONFIG_CPU_ARM926T=y
+-CONFIG_CPU_32v5=y
+-CONFIG_CPU_ABRT_EV5TJ=y
+-CONFIG_CPU_CACHE_VIVT=y
+-CONFIG_CPU_COPY_V4WB=y
+-CONFIG_CPU_TLB_V4WBI=y
+-CONFIG_CPU_CP15=y
+-CONFIG_CPU_CP15_MMU=y
+-
+-#
+-# Processor Features
+-#
+-# CONFIG_ARM_THUMB is not set
+-# CONFIG_CPU_ICACHE_DISABLE is not set
+-# CONFIG_CPU_DCACHE_DISABLE is not set
+-# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+-# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+-
+-#
+-# Bus support
+-#
+-
+-#
+-# PCCARD (PCMCIA/CardBus) support
+-#
+-# CONFIG_PCCARD is not set
+-
+-#
+-# Kernel Features
+-#
+-# CONFIG_PREEMPT is not set
+-# CONFIG_NO_IDLE_HZ is not set
+-CONFIG_HZ=100
+-# CONFIG_AEABI is not set
+-# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4096
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ALIGNMENT_TRAP=y
+-
+-#
+-# Boot options
+-#
+-CONFIG_ZBOOT_ROM_TEXT=0x0
+-CONFIG_ZBOOT_ROM_BSS=0x0
+-CONFIG_CMDLINE=""
+-# CONFIG_XIP_KERNEL is not set
+-
+-#
+-# Floating point emulation
+-#
+-
+-#
+-# At least one emulation must be selected
+-#
++CONFIG_MACH_CC9P9360JS=y
++CONFIG_MACH_CC9P9360VAL=y
++CONFIG_MACH_CC9P9750DEV=y
++CONFIG_MACH_CC9P9750VAL=y
++CONFIG_MACH_CCW9C=y
++CONFIG_MACH_INC20OTTER=y
++CONFIG_MACH_OTTER=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
+ CONFIG_FPE_NWFPE=y
+-# CONFIG_FPE_NWFPE_XP is not set
+-# CONFIG_FPE_FASTFPE is not set
+-# CONFIG_VFP is not set
+-
+-#
+-# Userspace binary formats
+-#
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_AOUT is not set
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_ARTHUR is not set
+-
+-#
+-# Power management options
+-#
+-# CONFIG_PM is not set
+-# CONFIG_APM is not set
+-
+-#
+-# Networking
+-#
+-# CONFIG_NET is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-
+-#
+-# Connector - unified userspace <-> kernelspace linker
+-#
+-
+-#
+-# Memory Technology Devices (MTD)
+-#
+-# CONFIG_MTD is not set
+-
+-#
+-# Parallel port support
+-#
+-# CONFIG_PARPORT is not set
+-
+-#
+-# Plug and Play support
+-#
+-
+-#
+-# Block devices
+-#
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=4096
+-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+-CONFIG_BLK_DEV_INITRD=y
+-# CONFIG_CDROM_PKTCDVD is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_NETLINK is not set
+-
+-#
+-# Serial ATA (prod) and Parallel ATA (experimental) drivers
+-#
+-# CONFIG_ATA is not set
+-
+-#
+-# Multi-device support (RAID and LVM)
+-#
+-# CONFIG_MD is not set
+-
+-#
+-# Fusion MPT device support
+-#
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-
+-#
+-# I2O device support
+-#
+-
+-#
+-# ISDN subsystem
+-#
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_TSDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-CONFIG_SERIO=y
++CONFIG_NET=y
++CONFIG_PACKET=m
++CONFIG_INET=y
++CONFIG_IP_PNP=y
++CONFIG_SYN_COOKIES=y
++CONFIG_MTD=m
++CONFIG_MTD_CONCAT=m
++CONFIG_MTD_CHAR=m
++CONFIG_MTD_BLOCK=m
++CONFIG_MTD_CFI=m
++CONFIG_MTD_JEDECPROBE=m
++CONFIG_MTD_CFI_AMDSTD=m
++CONFIG_MTD_PHYSMAP=m
++CONFIG_MTD_PHYSMAP_START=0x0
++CONFIG_BLK_DEV_LOOP=m
++CONFIG_NETDEVICES=y
++CONFIG_NET_ETHERNET=y
++CONFIG_NS9XXX_ETH=y
+ # CONFIG_SERIO_SERPORT is not set
+-CONFIG_SERIO_LIBPS2=y
+-# CONFIG_SERIO_RAW is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-CONFIG_VT=y
+-CONFIG_VT_CONSOLE=y
+-CONFIG_HW_CONSOLE=y
+-# CONFIG_VT_HW_CONSOLE_BINDING is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-
+-#
+-# Serial drivers
+-#
+ CONFIG_SERIAL_8250=y
+ CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-CONFIG_SERIAL_8250_EXTENDED=y
+-# CONFIG_SERIAL_8250_MANY_PORTS is not set
+-# CONFIG_SERIAL_8250_SHARE_IRQ is not set
+-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+-# CONFIG_SERIAL_8250_RSA is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-CONFIG_UNIX98_PTYS=y
++CONFIG_SERIAL_NS921X=y
++CONFIG_SERIAL_NS921X_CONSOLE=y
+ # CONFIG_LEGACY_PTYS is not set
+-
+-#
+-# IPMI
+-#
+-# CONFIG_IPMI_HANDLER is not set
+-
+-#
+-# Watchdog Cards
+-#
+-# CONFIG_WATCHDOG is not set
+ # CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_DTLK is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_RAW_DRIVER is not set
+-
+-#
+-# TPM devices
+-#
+-# CONFIG_TCG_TPM is not set
+-
+-#
+-# I2C support
+-#
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-
+-#
+-# Dallas's 1-wire bus
+-#
+-# CONFIG_W1 is not set
+-
+-#
+-# Hardware Monitoring support
+-#
++CONFIG_ADC_NS9215=m
++CONFIG_I2C=m
++CONFIG_I2C_GPIO=m
+ # CONFIG_HWMON is not set
+-# CONFIG_HWMON_VID is not set
+-
+-#
+-# Misc devices
+-#
+-# CONFIG_TIFM_CORE is not set
+-
+-#
+-# LED devices
+-#
+-# CONFIG_NEW_LEDS is not set
+-
+-#
+-# LED drivers
+-#
+-
+-#
+-# LED Triggers
+-#
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-
+-#
+-# Digital Video Broadcasting Devices
+-#
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_FIRMWARE_EDID is not set
+-# CONFIG_FB is not set
+-
+-#
+-# Console display driver support
+-#
+ # CONFIG_VGA_CONSOLE is not set
+-CONFIG_DUMMY_CONSOLE=y
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-
+-#
+-# HID Devices
+-#
+-CONFIG_HID=y
+-
+-#
+-# USB support
+-#
+-CONFIG_USB_ARCH_HAS_HCD=y
+-# CONFIG_USB_ARCH_HAS_OHCI is not set
+-# CONFIG_USB_ARCH_HAS_EHCI is not set
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# USB Gadget Support
+-#
+-# CONFIG_USB_GADGET is not set
+-
+-#
+-# MMC/SD Card support
+-#
+-# CONFIG_MMC is not set
+-
+-#
+-# Real Time Clock
+-#
+-CONFIG_RTC_LIB=y
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_DNOTIFY is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_USB_SUPPORT is not set
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=m
++CONFIG_LEDS_GPIO=m
++CONFIG_LEDS_TRIGGERS=y
++CONFIG_LEDS_TRIGGER_TIMER=m
++CONFIG_LEDS_TRIGGER_HEARTBEAT=m
++CONFIG_RTC_CLASS=m
++CONFIG_RTC_DRV_NS9215=m
++CONFIG_EXT2_FS=m
+ CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-CONFIG_RAMFS=y
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-
+-#
+-# Native Language Support
+-#
+-# CONFIG_NLS is not set
+-
+-#
+-# Profiling support
+-#
+-# CONFIG_PROFILING is not set
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
++CONFIG_JFFS2_FS=m
++CONFIG_NFS_FS=y
++CONFIG_ROOT_NFS=y
+ # CONFIG_ENABLE_MUST_CHECK is not set
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+ CONFIG_DEBUG_KERNEL=y
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_DETECT_SOFTLOCKUP is not set
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_DEBUG_SLAB is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_RWSEMS is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+ CONFIG_DEBUG_BUGVERBOSE=y
+ CONFIG_DEBUG_INFO=y
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-CONFIG_FRAME_POINTER=y
+-CONFIG_FORCED_INLINING=y
+-# CONFIG_RCU_TORTURE_TEST is not set
+ CONFIG_DEBUG_USER=y
+ CONFIG_DEBUG_ERRORS=y
+-CONFIG_DEBUG_LL=y
+-CONFIG_DEBUG_ICEDCC=y
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-
+-#
+-# Cryptographic options
+-#
+-# CONFIG_CRYPTO is not set
+-
+-#
+-# Library routines
+-#
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC32 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_IOMAP_COPY=y
+diff --git a/arch/arm/configs/orion5x_defconfig b/arch/arm/configs/orion5x_defconfig
+new file mode 100644
+index 0000000..52cd99b
+--- /dev/null
++++ b/arch/arm/configs/orion5x_defconfig
+@@ -0,0 +1,1383 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.24
++# Thu Feb 7 14:10:30 2008
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ZONE_DMA=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_LOCK_KERNEL=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_BLK_DEV_INITRD is not set
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++
++#
++# System Type
++#
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
++CONFIG_ARCH_ORION5X=y
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_MSM7X00A is not set
++
++#
++# Orion Implementations
++#
++CONFIG_MACH_DB88F5281=y
++CONFIG_MACH_RD88F5182=y
++CONFIG_MACH_KUROBOX_PRO=y
++CONFIG_MACH_DNS323=y
++CONFIG_MACH_TS209=y
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_FEROCEON=y
++CONFIG_CPU_FEROCEON_OLD_ID=y
++CONFIG_CPU_32v5=y
++CONFIG_CPU_ABRT_EV5T=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_OUTER_CACHE is not set
++
++#
++# Bus support
++#
++CONFIG_PCI=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++CONFIG_PREEMPT=y
++CONFIG_HZ=100
++CONFIG_AEABI=y
++CONFIG_OABI_COMPAT=y
++# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_LEDS=y
++CONFIG_LEDS_CPU=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE=""
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++# CONFIG_ATAGS_PROC is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++CONFIG_VFP=y
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++CONFIG_NET_PKTGEN=m
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++CONFIG_WIRELESS_EXT=y
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_AFS_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++CONFIG_FTL=y
++CONFIG_NFTL=y
++# CONFIG_NFTL_RW is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++CONFIG_MTD_GEN_PROBE=y
++CONFIG_MTD_CFI_ADV_OPTIONS=y
++CONFIG_MTD_CFI_NOSWAP=y
++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
++CONFIG_MTD_CFI_GEOMETRY=y
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++CONFIG_MTD_CFI_I4=y
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_OTP is not set
++CONFIG_MTD_CFI_INTELEXT=y
++CONFIG_MTD_CFI_AMDSTD=y
++CONFIG_MTD_CFI_STAA=y
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_START=0x0
++CONFIG_MTD_PHYSMAP_LEN=0x0
++CONFIG_MTD_PHYSMAP_BANKWIDTH=0
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_IMPA7 is not set
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++CONFIG_MTD_NAND_VERIFY_WRITE=y
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_CAFE is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ALAUDA is not set
++CONFIG_MTD_NAND_ORION=y
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++# CONFIG_BLK_DEV_UB is not set
++# CONFIG_BLK_DEV_RAM is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_SCSI_PROC_FS is not set
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++CONFIG_BLK_DEV_SR=m
++# CONFIG_BLK_DEV_SR_VENDOR is not set
++CONFIG_CHR_DEV_SG=m
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_IPR is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++CONFIG_ATA=y
++# CONFIG_ATA_NONSTANDARD is not set
++# CONFIG_SATA_AHCI is not set
++# CONFIG_SATA_SVW is not set
++# CONFIG_ATA_PIIX is not set
++CONFIG_SATA_MV=y
++# CONFIG_SATA_NV is not set
++# CONFIG_PDC_ADMA is not set
++# CONFIG_SATA_QSTOR is not set
++# CONFIG_SATA_PROMISE is not set
++# CONFIG_SATA_SX4 is not set
++# CONFIG_SATA_SIL is not set
++# CONFIG_SATA_SIL24 is not set
++# CONFIG_SATA_SIS is not set
++# CONFIG_SATA_ULI is not set
++# CONFIG_SATA_VIA is not set
++# CONFIG_SATA_VITESSE is not set
++# CONFIG_SATA_INIC162X is not set
++# CONFIG_PATA_ALI is not set
++# CONFIG_PATA_AMD is not set
++# CONFIG_PATA_ARTOP is not set
++# CONFIG_PATA_ATIIXP is not set
++# CONFIG_PATA_CMD640_PCI is not set
++# CONFIG_PATA_CMD64X is not set
++# CONFIG_PATA_CS5520 is not set
++# CONFIG_PATA_CS5530 is not set
++# CONFIG_PATA_CYPRESS is not set
++# CONFIG_PATA_EFAR is not set
++# CONFIG_ATA_GENERIC is not set
++# CONFIG_PATA_HPT366 is not set
++# CONFIG_PATA_HPT37X is not set
++# CONFIG_PATA_HPT3X2N is not set
++# CONFIG_PATA_HPT3X3 is not set
++# CONFIG_PATA_IT821X is not set
++# CONFIG_PATA_IT8213 is not set
++# CONFIG_PATA_JMICRON is not set
++# CONFIG_PATA_TRIFLEX is not set
++# CONFIG_PATA_MARVELL is not set
++# CONFIG_PATA_MPIIX is not set
++# CONFIG_PATA_OLDPIIX is not set
++# CONFIG_PATA_NETCELL is not set
++# CONFIG_PATA_NINJA32 is not set
++# CONFIG_PATA_NS87410 is not set
++# CONFIG_PATA_NS87415 is not set
++# CONFIG_PATA_OPTI is not set
++# CONFIG_PATA_OPTIDMA is not set
++# CONFIG_PATA_PDC_OLD is not set
++# CONFIG_PATA_RADISYS is not set
++# CONFIG_PATA_RZ1000 is not set
++# CONFIG_PATA_SC1200 is not set
++# CONFIG_PATA_SERVERWORKS is not set
++# CONFIG_PATA_PDC2027X is not set
++# CONFIG_PATA_SIL680 is not set
++# CONFIG_PATA_SIS is not set
++# CONFIG_PATA_VIA is not set
++# CONFIG_PATA_WINBOND is not set
++# CONFIG_PATA_PLATFORM is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_AX88796 is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_SMC91X is not set
++# CONFIG_DM9000 is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++CONFIG_NET_PCI=y
++# CONFIG_PCNET32 is not set
++# CONFIG_AMD8111_ETH is not set
++# CONFIG_ADAPTEC_STARFIRE is not set
++# CONFIG_B44 is not set
++# CONFIG_FORCEDETH is not set
++# CONFIG_EEPRO100 is not set
++CONFIG_E100=y
++# CONFIG_FEALNX is not set
++# CONFIG_NATSEMI is not set
++# CONFIG_NE2K_PCI is not set
++# CONFIG_8139CP is not set
++# CONFIG_8139TOO is not set
++# CONFIG_R6040 is not set
++# CONFIG_SIS900 is not set
++# CONFIG_EPIC100 is not set
++# CONFIG_SUNDANCE is not set
++# CONFIG_TLAN is not set
++# CONFIG_VIA_RHINE is not set
++# CONFIG_SC92031 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++CONFIG_E1000=y
++CONFIG_E1000_NAPI=y
++# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++CONFIG_SKGE=y
++CONFIG_SKY2=y
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++CONFIG_TIGON3=y
++# CONFIG_BNX2 is not set
++CONFIG_MV643XX_ETH=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=2
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=16
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=m
++# CONFIG_NVRAM is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++CONFIG_I2C_MV64XXX=y
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
++
++#
++# Graphics support
++#
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++# CONFIG_USB_HIDINPUT_POWERBOOK is not set
++# CONFIG_HID_FF is not set
++# CONFIG_USB_HIDDEV is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++CONFIG_USB_EHCI_HCD=y
++CONFIG_USB_EHCI_ROOT_HUB_TT=y
++CONFIG_USB_EHCI_TT_NEWSCHED=y
++# CONFIG_USB_ISP116X_HCD is not set
++# CONFIG_USB_OHCI_HCD is not set
++# CONFIG_USB_UHCI_HCD is not set
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++CONFIG_USB_PRINTER=y
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++CONFIG_USB_STORAGE_DATAFAB=y
++CONFIG_USB_STORAGE_FREECOM=y
++# CONFIG_USB_STORAGE_ISD200 is not set
++CONFIG_USB_STORAGE_DPCM=y
++# CONFIG_USB_STORAGE_USBAT is not set
++CONFIG_USB_STORAGE_SDDR09=y
++CONFIG_USB_STORAGE_SDDR55=y
++CONFIG_USB_STORAGE_JUMPSHOT=y
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++# CONFIG_USB_MON is not set
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=y
++
++#
++# LED drivers
++#
++# CONFIG_LEDS_GPIO is not set
++
++#
++# LED Triggers
++#
++CONFIG_LEDS_TRIGGERS=y
++CONFIG_LEDS_TRIGGER_TIMER=y
++CONFIG_LEDS_TRIGGER_HEARTBEAT=y
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++CONFIG_RTC_DRV_DS1307=y
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++CONFIG_RTC_DRV_RS5C372=y
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++CONFIG_RTC_DRV_M41T80=y
++# CONFIG_RTC_DRV_M41T80_WDT is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++# CONFIG_EXT3_FS_XATTR is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++CONFIG_ISO9660_FS=y
++# CONFIG_JOLIET is not set
++# CONFIG_ZISOFS is not set
++CONFIG_UDF_FS=m
++CONFIG_UDF_NLS=y
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_BSD_DISKLABEL=y
++CONFIG_MINIX_SUBPARTITION=y
++CONFIG_SOLARIS_X86_PARTITION=y
++CONFIG_UNIXWARE_DISKLABEL=y
++CONFIG_LDM_PARTITION=y
++CONFIG_LDM_DEBUG=y
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++CONFIG_SUN_PARTITION=y
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++CONFIG_NLS_CODEPAGE_850=y
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++CONFIG_NLS_ISO8859_2=y
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++# CONFIG_DLM is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_SAMPLES is not set
++CONFIG_DEBUG_USER=y
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=m
++CONFIG_CRYPTO_BLKCIPHER=m
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=m
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=m
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=y
++CONFIG_CRC16=y
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++CONFIG_LIBCRC32C=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/orion_defconfig b/arch/arm/configs/orion_defconfig
+deleted file mode 100644
+index 1e5aaa6..0000000
+--- a/arch/arm/configs/orion_defconfig
++++ /dev/null
+@@ -1,1383 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.24
+-# Thu Feb 7 14:10:30 2008
+-#
+-CONFIG_ARM=y
+-CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+-CONFIG_GENERIC_GPIO=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_MMU=y
+-# CONFIG_NO_IOPORT is not set
+-CONFIG_GENERIC_HARDIRQS=y
+-CONFIG_STACKTRACE_SUPPORT=y
+-CONFIG_LOCKDEP_SUPPORT=y
+-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+-CONFIG_HARDIRQS_SW_RESEND=y
+-CONFIG_GENERIC_IRQ_PROBE=y
+-CONFIG_RWSEM_GENERIC_SPINLOCK=y
+-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_ZONE_DMA=y
+-CONFIG_VECTORS_BASE=0xffff0000
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_LOCK_KERNEL=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_USER_NS is not set
+-# CONFIG_PID_NS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_FAIR_GROUP_SCHED=y
+-CONFIG_FAIR_USER_SCHED=y
+-# CONFIG_FAIR_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-# CONFIG_BLK_DEV_INITRD is not set
+-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_UID16=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLAB=y
+-# CONFIG_SLUB is not set
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-# CONFIG_DEFAULT_AS is not set
+-# CONFIG_DEFAULT_DEADLINE is not set
+-CONFIG_DEFAULT_CFQ=y
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="cfq"
+-CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-
+-#
+-# System Type
+-#
+-# CONFIG_ARCH_AAEC2000 is not set
+-# CONFIG_ARCH_INTEGRATOR is not set
+-# CONFIG_ARCH_REALVIEW is not set
+-# CONFIG_ARCH_VERSATILE is not set
+-# CONFIG_ARCH_AT91 is not set
+-# CONFIG_ARCH_CLPS7500 is not set
+-# CONFIG_ARCH_CLPS711X is not set
+-# CONFIG_ARCH_CO285 is not set
+-# CONFIG_ARCH_EBSA110 is not set
+-# CONFIG_ARCH_EP93XX is not set
+-# CONFIG_ARCH_FOOTBRIDGE is not set
+-# CONFIG_ARCH_NETX is not set
+-# CONFIG_ARCH_H720X is not set
+-# CONFIG_ARCH_IMX is not set
+-# CONFIG_ARCH_IOP13XX is not set
+-# CONFIG_ARCH_IOP32X is not set
+-# CONFIG_ARCH_IOP33X is not set
+-# CONFIG_ARCH_IXP23XX is not set
+-# CONFIG_ARCH_IXP2000 is not set
+-# CONFIG_ARCH_IXP4XX is not set
+-# CONFIG_ARCH_L7200 is not set
+-# CONFIG_ARCH_KS8695 is not set
+-# CONFIG_ARCH_NS9XXX is not set
+-# CONFIG_ARCH_MXC is not set
+-CONFIG_ARCH_ORION=y
+-# CONFIG_ARCH_PNX4008 is not set
+-# CONFIG_ARCH_PXA is not set
+-# CONFIG_ARCH_RPC is not set
+-# CONFIG_ARCH_SA1100 is not set
+-# CONFIG_ARCH_S3C2410 is not set
+-# CONFIG_ARCH_SHARK is not set
+-# CONFIG_ARCH_LH7A40X is not set
+-# CONFIG_ARCH_DAVINCI is not set
+-# CONFIG_ARCH_OMAP is not set
+-# CONFIG_ARCH_MSM7X00A is not set
+-
+-#
+-# Orion Implementations
+-#
+-CONFIG_MACH_DB88F5281=y
+-CONFIG_MACH_RD88F5182=y
+-CONFIG_MACH_KUROBOX_PRO=y
+-CONFIG_MACH_DNS323=y
+-CONFIG_MACH_TS209=y
+-
+-#
+-# Boot options
+-#
+-
+-#
+-# Power management
+-#
+-
+-#
+-# Processor Type
+-#
+-CONFIG_CPU_32=y
+-CONFIG_CPU_FEROCEON=y
+-CONFIG_CPU_FEROCEON_OLD_ID=y
+-CONFIG_CPU_32v5=y
+-CONFIG_CPU_ABRT_EV5T=y
+-CONFIG_CPU_CACHE_VIVT=y
+-CONFIG_CPU_COPY_V4WB=y
+-CONFIG_CPU_TLB_V4WBI=y
+-CONFIG_CPU_CP15=y
+-CONFIG_CPU_CP15_MMU=y
+-
+-#
+-# Processor Features
+-#
+-CONFIG_ARM_THUMB=y
+-# CONFIG_CPU_ICACHE_DISABLE is not set
+-# CONFIG_CPU_DCACHE_DISABLE is not set
+-# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+-# CONFIG_OUTER_CACHE is not set
+-
+-#
+-# Bus support
+-#
+-CONFIG_PCI=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_ARCH_SUPPORTS_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCCARD is not set
+-
+-#
+-# Kernel Features
+-#
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-CONFIG_PREEMPT=y
+-CONFIG_HZ=100
+-CONFIG_AEABI=y
+-CONFIG_OABI_COMPAT=y
+-# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4096
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_LEDS=y
+-CONFIG_LEDS_CPU=y
+-CONFIG_ALIGNMENT_TRAP=y
+-
+-#
+-# Boot options
+-#
+-CONFIG_ZBOOT_ROM_TEXT=0x0
+-CONFIG_ZBOOT_ROM_BSS=0x0
+-CONFIG_CMDLINE=""
+-# CONFIG_XIP_KERNEL is not set
+-# CONFIG_KEXEC is not set
+-# CONFIG_ATAGS_PROC is not set
+-
+-#
+-# Floating point emulation
+-#
+-
+-#
+-# At least one emulation must be selected
+-#
+-CONFIG_FPE_NWFPE=y
+-# CONFIG_FPE_NWFPE_XP is not set
+-# CONFIG_FPE_FASTFPE is not set
+-CONFIG_VFP=y
+-
+-#
+-# Userspace binary formats
+-#
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_AOUT is not set
+-# CONFIG_BINFMT_MISC is not set
+-
+-#
+-# Power management options
+-#
+-# CONFIG_PM is not set
+-CONFIG_ARCH_SUSPEND_POSSIBLE=y
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-CONFIG_PACKET_MMAP=y
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-CONFIG_NET_PKTGEN=m
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-CONFIG_WIRELESS_EXT=y
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-CONFIG_MTD_CMDLINE_PARTS=y
+-# CONFIG_MTD_AFS_PARTS is not set
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=y
+-CONFIG_MTD_BLOCK=y
+-CONFIG_FTL=y
+-CONFIG_NFTL=y
+-# CONFIG_NFTL_RW is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-CONFIG_MTD_JEDECPROBE=y
+-CONFIG_MTD_GEN_PROBE=y
+-CONFIG_MTD_CFI_ADV_OPTIONS=y
+-CONFIG_MTD_CFI_NOSWAP=y
+-# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+-# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+-CONFIG_MTD_CFI_GEOMETRY=y
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-CONFIG_MTD_CFI_I4=y
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_OTP is not set
+-CONFIG_MTD_CFI_INTELEXT=y
+-CONFIG_MTD_CFI_AMDSTD=y
+-CONFIG_MTD_CFI_STAA=y
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-CONFIG_MTD_PHYSMAP=y
+-CONFIG_MTD_PHYSMAP_START=0x0
+-CONFIG_MTD_PHYSMAP_LEN=0x0
+-CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+-# CONFIG_MTD_ARM_INTEGRATOR is not set
+-# CONFIG_MTD_IMPA7 is not set
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-CONFIG_MTD_NAND=y
+-CONFIG_MTD_NAND_VERIFY_WRITE=y
+-# CONFIG_MTD_NAND_ECC_SMC is not set
+-# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+-CONFIG_MTD_NAND_IDS=y
+-# CONFIG_MTD_NAND_DISKONCHIP is not set
+-# CONFIG_MTD_NAND_CAFE is not set
+-# CONFIG_MTD_NAND_NANDSIM is not set
+-# CONFIG_MTD_NAND_PLATFORM is not set
+-# CONFIG_MTD_ALAUDA is not set
+-CONFIG_MTD_NAND_ORION=y
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-# CONFIG_BLK_DEV_UB is not set
+-# CONFIG_BLK_DEV_RAM is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_SCSI_PROC_FS is not set
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-CONFIG_BLK_DEV_SD=y
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-CONFIG_BLK_DEV_SR=m
+-# CONFIG_BLK_DEV_SR_VENDOR is not set
+-CONFIG_CHR_DEV_SG=m
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-# CONFIG_SCSI_SPI_ATTRS is not set
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-# CONFIG_SCSI_AIC7XXX is not set
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-# CONFIG_SCSI_AIC79XX is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_IPR is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-CONFIG_ATA=y
+-# CONFIG_ATA_NONSTANDARD is not set
+-# CONFIG_SATA_AHCI is not set
+-# CONFIG_SATA_SVW is not set
+-# CONFIG_ATA_PIIX is not set
+-CONFIG_SATA_MV=y
+-# CONFIG_SATA_NV is not set
+-# CONFIG_PDC_ADMA is not set
+-# CONFIG_SATA_QSTOR is not set
+-# CONFIG_SATA_PROMISE is not set
+-# CONFIG_SATA_SX4 is not set
+-# CONFIG_SATA_SIL is not set
+-# CONFIG_SATA_SIL24 is not set
+-# CONFIG_SATA_SIS is not set
+-# CONFIG_SATA_ULI is not set
+-# CONFIG_SATA_VIA is not set
+-# CONFIG_SATA_VITESSE is not set
+-# CONFIG_SATA_INIC162X is not set
+-# CONFIG_PATA_ALI is not set
+-# CONFIG_PATA_AMD is not set
+-# CONFIG_PATA_ARTOP is not set
+-# CONFIG_PATA_ATIIXP is not set
+-# CONFIG_PATA_CMD640_PCI is not set
+-# CONFIG_PATA_CMD64X is not set
+-# CONFIG_PATA_CS5520 is not set
+-# CONFIG_PATA_CS5530 is not set
+-# CONFIG_PATA_CYPRESS is not set
+-# CONFIG_PATA_EFAR is not set
+-# CONFIG_ATA_GENERIC is not set
+-# CONFIG_PATA_HPT366 is not set
+-# CONFIG_PATA_HPT37X is not set
+-# CONFIG_PATA_HPT3X2N is not set
+-# CONFIG_PATA_HPT3X3 is not set
+-# CONFIG_PATA_IT821X is not set
+-# CONFIG_PATA_IT8213 is not set
+-# CONFIG_PATA_JMICRON is not set
+-# CONFIG_PATA_TRIFLEX is not set
+-# CONFIG_PATA_MARVELL is not set
+-# CONFIG_PATA_MPIIX is not set
+-# CONFIG_PATA_OLDPIIX is not set
+-# CONFIG_PATA_NETCELL is not set
+-# CONFIG_PATA_NINJA32 is not set
+-# CONFIG_PATA_NS87410 is not set
+-# CONFIG_PATA_NS87415 is not set
+-# CONFIG_PATA_OPTI is not set
+-# CONFIG_PATA_OPTIDMA is not set
+-# CONFIG_PATA_PDC_OLD is not set
+-# CONFIG_PATA_RADISYS is not set
+-# CONFIG_PATA_RZ1000 is not set
+-# CONFIG_PATA_SC1200 is not set
+-# CONFIG_PATA_SERVERWORKS is not set
+-# CONFIG_PATA_PDC2027X is not set
+-# CONFIG_PATA_SIL680 is not set
+-# CONFIG_PATA_SIS is not set
+-# CONFIG_PATA_VIA is not set
+-# CONFIG_PATA_WINBOND is not set
+-# CONFIG_PATA_PLATFORM is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-# CONFIG_PHYLIB is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_AX88796 is not set
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_SMC91X is not set
+-# CONFIG_DM9000 is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-CONFIG_NET_PCI=y
+-# CONFIG_PCNET32 is not set
+-# CONFIG_AMD8111_ETH is not set
+-# CONFIG_ADAPTEC_STARFIRE is not set
+-# CONFIG_B44 is not set
+-# CONFIG_FORCEDETH is not set
+-# CONFIG_EEPRO100 is not set
+-CONFIG_E100=y
+-# CONFIG_FEALNX is not set
+-# CONFIG_NATSEMI is not set
+-# CONFIG_NE2K_PCI is not set
+-# CONFIG_8139CP is not set
+-# CONFIG_8139TOO is not set
+-# CONFIG_R6040 is not set
+-# CONFIG_SIS900 is not set
+-# CONFIG_EPIC100 is not set
+-# CONFIG_SUNDANCE is not set
+-# CONFIG_TLAN is not set
+-# CONFIG_VIA_RHINE is not set
+-# CONFIG_SC92031 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-CONFIG_E1000=y
+-CONFIG_E1000_NAPI=y
+-# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-CONFIG_SKGE=y
+-CONFIG_SKY2=y
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-CONFIG_TIGON3=y
+-# CONFIG_BNX2 is not set
+-CONFIG_MV643XX_ETH=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NET_FC is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-CONFIG_INPUT_MOUSEDEV=y
+-CONFIG_INPUT_MOUSEDEV_PSAUX=y
+-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-CONFIG_VT=y
+-CONFIG_VT_CONSOLE=y
+-CONFIG_HW_CONSOLE=y
+-# CONFIG_VT_HW_CONSOLE_BINDING is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=16
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=m
+-# CONFIG_NVRAM is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_GPIO is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_TINY_USB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-CONFIG_I2C_MV64XXX=y
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-# CONFIG_USB_DABUSB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Console display driver support
+-#
+-# CONFIG_VGA_CONSOLE is not set
+-CONFIG_DUMMY_CONSOLE=y
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-
+-#
+-# USB Input Devices
+-#
+-CONFIG_USB_HID=y
+-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+-# CONFIG_HID_FF is not set
+-# CONFIG_USB_HIDDEV is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-CONFIG_USB=y
+-# CONFIG_USB_DEBUG is not set
+-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+-
+-#
+-# Miscellaneous USB options
+-#
+-CONFIG_USB_DEVICEFS=y
+-CONFIG_USB_DEVICE_CLASS=y
+-# CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_OTG is not set
+-
+-#
+-# USB Host Controller Drivers
+-#
+-CONFIG_USB_EHCI_HCD=y
+-CONFIG_USB_EHCI_ROOT_HUB_TT=y
+-CONFIG_USB_EHCI_TT_NEWSCHED=y
+-# CONFIG_USB_ISP116X_HCD is not set
+-# CONFIG_USB_OHCI_HCD is not set
+-# CONFIG_USB_UHCI_HCD is not set
+-# CONFIG_USB_SL811_HCD is not set
+-# CONFIG_USB_R8A66597_HCD is not set
+-
+-#
+-# USB Device Class drivers
+-#
+-# CONFIG_USB_ACM is not set
+-CONFIG_USB_PRINTER=y
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# may also be needed; see USB_STORAGE Help for more information
+-#
+-CONFIG_USB_STORAGE=y
+-# CONFIG_USB_STORAGE_DEBUG is not set
+-CONFIG_USB_STORAGE_DATAFAB=y
+-CONFIG_USB_STORAGE_FREECOM=y
+-# CONFIG_USB_STORAGE_ISD200 is not set
+-CONFIG_USB_STORAGE_DPCM=y
+-# CONFIG_USB_STORAGE_USBAT is not set
+-CONFIG_USB_STORAGE_SDDR09=y
+-CONFIG_USB_STORAGE_SDDR55=y
+-CONFIG_USB_STORAGE_JUMPSHOT=y
+-# CONFIG_USB_STORAGE_ALAUDA is not set
+-# CONFIG_USB_STORAGE_KARMA is not set
+-# CONFIG_USB_LIBUSUAL is not set
+-
+-#
+-# USB Imaging devices
+-#
+-# CONFIG_USB_MDC800 is not set
+-# CONFIG_USB_MICROTEK is not set
+-# CONFIG_USB_MON is not set
+-
+-#
+-# USB port drivers
+-#
+-# CONFIG_USB_SERIAL is not set
+-
+-#
+-# USB Miscellaneous drivers
+-#
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+-# CONFIG_USB_ADUTUX is not set
+-# CONFIG_USB_AUERSWALD is not set
+-# CONFIG_USB_RIO500 is not set
+-# CONFIG_USB_LEGOTOWER is not set
+-# CONFIG_USB_LCD is not set
+-# CONFIG_USB_BERRY_CHARGE is not set
+-# CONFIG_USB_LED is not set
+-# CONFIG_USB_CYPRESS_CY7C63 is not set
+-# CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGET is not set
+-# CONFIG_USB_IDMOUSE is not set
+-# CONFIG_USB_FTDI_ELAN is not set
+-# CONFIG_USB_APPLEDISPLAY is not set
+-# CONFIG_USB_SISUSBVGA is not set
+-# CONFIG_USB_LD is not set
+-# CONFIG_USB_TRANCEVIBRATOR is not set
+-# CONFIG_USB_IOWARRIOR is not set
+-# CONFIG_USB_TEST is not set
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-CONFIG_NEW_LEDS=y
+-CONFIG_LEDS_CLASS=y
+-
+-#
+-# LED drivers
+-#
+-# CONFIG_LEDS_GPIO is not set
+-
+-#
+-# LED Triggers
+-#
+-CONFIG_LEDS_TRIGGERS=y
+-CONFIG_LEDS_TRIGGER_TIMER=y
+-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+-CONFIG_RTC_LIB=y
+-CONFIG_RTC_CLASS=y
+-CONFIG_RTC_HCTOSYS=y
+-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+-# CONFIG_RTC_DEBUG is not set
+-
+-#
+-# RTC interfaces
+-#
+-CONFIG_RTC_INTF_SYSFS=y
+-CONFIG_RTC_INTF_PROC=y
+-CONFIG_RTC_INTF_DEV=y
+-# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+-# CONFIG_RTC_DRV_TEST is not set
+-
+-#
+-# I2C RTC drivers
+-#
+-CONFIG_RTC_DRV_DS1307=y
+-# CONFIG_RTC_DRV_DS1374 is not set
+-# CONFIG_RTC_DRV_DS1672 is not set
+-# CONFIG_RTC_DRV_MAX6900 is not set
+-CONFIG_RTC_DRV_RS5C372=y
+-# CONFIG_RTC_DRV_ISL1208 is not set
+-# CONFIG_RTC_DRV_X1205 is not set
+-# CONFIG_RTC_DRV_PCF8563 is not set
+-# CONFIG_RTC_DRV_PCF8583 is not set
+-CONFIG_RTC_DRV_M41T80=y
+-# CONFIG_RTC_DRV_M41T80_WDT is not set
+-
+-#
+-# SPI RTC drivers
+-#
+-
+-#
+-# Platform RTC drivers
+-#
+-# CONFIG_RTC_DRV_CMOS is not set
+-# CONFIG_RTC_DRV_DS1511 is not set
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
+-# CONFIG_RTC_DRV_STK17TA8 is not set
+-# CONFIG_RTC_DRV_M48T86 is not set
+-# CONFIG_RTC_DRV_M48T59 is not set
+-# CONFIG_RTC_DRV_V3020 is not set
+-
+-#
+-# on-CPU RTC drivers
+-#
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-# CONFIG_EXT3_FS_XATTR is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-CONFIG_DNOTIFY=y
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-CONFIG_ISO9660_FS=y
+-# CONFIG_JOLIET is not set
+-# CONFIG_ZISOFS is not set
+-CONFIG_UDF_FS=m
+-CONFIG_UDF_NLS=y
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-CONFIG_FAT_FS=y
+-CONFIG_MSDOS_FS=y
+-CONFIG_VFAT_FS=y
+-CONFIG_FAT_DEFAULT_CODEPAGE=437
+-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_JFFS2_FS=y
+-CONFIG_JFFS2_FS_DEBUG=0
+-CONFIG_JFFS2_FS_WRITEBUFFER=y
+-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+-# CONFIG_JFFS2_SUMMARY is not set
+-# CONFIG_JFFS2_FS_XATTR is not set
+-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+-CONFIG_JFFS2_ZLIB=y
+-# CONFIG_JFFS2_LZO is not set
+-CONFIG_JFFS2_RTIME=y
+-# CONFIG_JFFS2_RUBIN is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-CONFIG_MSDOS_PARTITION=y
+-CONFIG_BSD_DISKLABEL=y
+-CONFIG_MINIX_SUBPARTITION=y
+-CONFIG_SOLARIS_X86_PARTITION=y
+-CONFIG_UNIXWARE_DISKLABEL=y
+-CONFIG_LDM_PARTITION=y
+-CONFIG_LDM_DEBUG=y
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-CONFIG_SUN_PARTITION=y
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-CONFIG_NLS=y
+-CONFIG_NLS_DEFAULT="iso8859-1"
+-CONFIG_NLS_CODEPAGE_437=y
+-# CONFIG_NLS_CODEPAGE_737 is not set
+-# CONFIG_NLS_CODEPAGE_775 is not set
+-CONFIG_NLS_CODEPAGE_850=y
+-# CONFIG_NLS_CODEPAGE_852 is not set
+-# CONFIG_NLS_CODEPAGE_855 is not set
+-# CONFIG_NLS_CODEPAGE_857 is not set
+-# CONFIG_NLS_CODEPAGE_860 is not set
+-# CONFIG_NLS_CODEPAGE_861 is not set
+-# CONFIG_NLS_CODEPAGE_862 is not set
+-# CONFIG_NLS_CODEPAGE_863 is not set
+-# CONFIG_NLS_CODEPAGE_864 is not set
+-# CONFIG_NLS_CODEPAGE_865 is not set
+-# CONFIG_NLS_CODEPAGE_866 is not set
+-# CONFIG_NLS_CODEPAGE_869 is not set
+-# CONFIG_NLS_CODEPAGE_936 is not set
+-# CONFIG_NLS_CODEPAGE_950 is not set
+-# CONFIG_NLS_CODEPAGE_932 is not set
+-# CONFIG_NLS_CODEPAGE_949 is not set
+-# CONFIG_NLS_CODEPAGE_874 is not set
+-# CONFIG_NLS_ISO8859_8 is not set
+-# CONFIG_NLS_CODEPAGE_1250 is not set
+-# CONFIG_NLS_CODEPAGE_1251 is not set
+-# CONFIG_NLS_ASCII is not set
+-CONFIG_NLS_ISO8859_1=y
+-CONFIG_NLS_ISO8859_2=y
+-# CONFIG_NLS_ISO8859_3 is not set
+-# CONFIG_NLS_ISO8859_4 is not set
+-# CONFIG_NLS_ISO8859_5 is not set
+-# CONFIG_NLS_ISO8859_6 is not set
+-# CONFIG_NLS_ISO8859_7 is not set
+-# CONFIG_NLS_ISO8859_9 is not set
+-# CONFIG_NLS_ISO8859_13 is not set
+-# CONFIG_NLS_ISO8859_14 is not set
+-# CONFIG_NLS_ISO8859_15 is not set
+-# CONFIG_NLS_KOI8_R is not set
+-# CONFIG_NLS_KOI8_U is not set
+-# CONFIG_NLS_UTF8 is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-CONFIG_FRAME_POINTER=y
+-# CONFIG_SAMPLES is not set
+-CONFIG_DEBUG_USER=y
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=m
+-CONFIG_CRYPTO_BLKCIPHER=m
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=m
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-# CONFIG_CRYPTO_MD5 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=m
+-CONFIG_CRYPTO_CBC=m
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-CONFIG_CRC_CCITT=y
+-CONFIG_CRC16=y
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-CONFIG_LIBCRC32C=y
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_ZLIB_DEFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/picotux200_defconfig b/arch/arm/configs/picotux200_defconfig
+index 3c0c4f1..95a22f5 100644
+--- a/arch/arm/configs/picotux200_defconfig
++++ b/arch/arm/configs/picotux200_defconfig
+@@ -727,14 +727,14 @@ CONFIG_I2C_CHARDEV=m
+ #
+ # I2C Algorithms
+ #
+-# CONFIG_I2C_ALGOBIT is not set
++CONFIG_I2C_ALGOBIT=m
+ # CONFIG_I2C_ALGOPCF is not set
+ # CONFIG_I2C_ALGOPCA is not set
+
+ #
+ # I2C Hardware Bus support
+ #
+-CONFIG_I2C_AT91=m
++CONFIG_I2C_GPIO=m
+ # CONFIG_I2C_OCORES is not set
+ # CONFIG_I2C_PARPORT_LIGHT is not set
+ # CONFIG_I2C_STUB is not set
+diff --git a/arch/arm/configs/sam9_l9260_defconfig b/arch/arm/configs/sam9_l9260_defconfig
+new file mode 100644
+index 0000000..484dc97
+--- /dev/null
++++ b/arch/arm/configs/sam9_l9260_defconfig
+@@ -0,0 +1,1098 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.23
++# Sun Oct 14 02:01:07 2007
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++# CONFIG_GENERIC_TIME is not set
++# CONFIG_GENERIC_CLOCKEVENTS is not set
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ZONE_DMA=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_LOCK_KERNEL=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_BSD_PROCESS_ACCT=y
++CONFIG_BSD_PROCESS_ACCT_V3=y
++# CONFIG_TASKSTATS is not set
++# CONFIG_USER_NS is not set
++CONFIG_AUDIT=y
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=15
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++# CONFIG_EMBEDDED is not set
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++# CONFIG_MODULES is not set
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++CONFIG_LSF=y
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++
++#
++# System Type
++#
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++CONFIG_ARCH_AT91=y
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
++
++#
++# Atmel AT91 System-on-Chip
++#
++# CONFIG_ARCH_AT91RM9200 is not set
++CONFIG_ARCH_AT91SAM9260=y
++# CONFIG_ARCH_AT91SAM9261 is not set
++# CONFIG_ARCH_AT91SAM9263 is not set
++# CONFIG_ARCH_AT91SAM9RL is not set
++
++#
++# AT91SAM9260 Variants
++#
++# CONFIG_ARCH_AT91SAM9260_SAM9XE is not set
++
++#
++# AT91SAM9260 / AT91SAM9XE Board Type
++#
++# CONFIG_MACH_AT91SAM9260EK is not set
++# CONFIG_MACH_CAM60 is not set
++CONFIG_MACH_SAM9_L9260=y
++
++#
++# AT91 Board Options
++#
++CONFIG_MTD_AT91_DATAFLASH_CARD=y
++
++#
++# AT91 Feature Selections
++#
++# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
++# CONFIG_ATMEL_TCLIB is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM926T=y
++CONFIG_CPU_32v5=y
++CONFIG_CPU_ABRT_EV5TJ=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
++# CONFIG_OUTER_CACHE is not set
++
++#
++# Bus support
++#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++
++#
++# PCCARD (PCMCIA/CardBus) support
++#
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++# CONFIG_TICK_ONESHOT is not set
++CONFIG_PREEMPT=y
++# CONFIG_NO_IDLE_HZ is not set
++CONFIG_HZ=100
++# CONFIG_AEABI is not set
++# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_LEDS=y
++CONFIG_LEDS_TIMER=y
++CONFIG_LEDS_CPU=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="console=ttyS0,115200 mem=64M initrd=0x21100000,4194304 root=/dev/ram0 rw"
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++# CONFIG_VFP is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++CONFIG_SUSPEND_UP_POSSIBLE=y
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++CONFIG_XFRM_USER=y
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++CONFIG_NET_KEY=y
++# CONFIG_NET_KEY_MIGRATE is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++# CONFIG_IP_PNP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++# CONFIG_MTD_CFI is not set
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++CONFIG_MTD_BLOCK2MTD=y
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++# CONFIG_MTD_NAND_VERIFY_WRITE is not set
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++CONFIG_MTD_NAND_AT91=y
++# CONFIG_MTD_NAND_NANDSIM is not set
++CONFIG_MTD_NAND_PLATFORM=y
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++CONFIG_MTD_UBI=y
++CONFIG_MTD_UBI_WL_THRESHOLD=4096
++CONFIG_MTD_UBI_BEB_RESERVE=3
++CONFIG_MTD_UBI_GLUEBI=y
++
++#
++# UBI debugging options
++#
++# CONFIG_MTD_UBI_DEBUG is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=8192
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++
++#
++# SCSI device support
++#
++CONFIG_RAID_ATTRS=y
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++CONFIG_SCSI_MULTI_LUN=y
++CONFIG_SCSI_CONSTANTS=y
++CONFIG_SCSI_LOGGING=y
++# CONFIG_SCSI_SCAN_ASYNC is not set
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_LOWLEVEL is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_FIXED_PHY is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_MACB=y
++# CONFIG_AX88796 is not set
++# CONFIG_SMC91X is not set
++# CONFIG_DM9000 is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET_MII is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_TSDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_ATMEL=y
++CONFIG_SERIAL_ATMEL_CONSOLE=y
++# CONFIG_SERIAL_ATMEL_TTYAT is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=16
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_WATCHDOG is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_HWMON is not set
++# CONFIG_MISC_DEVICES is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=y
++
++#
++# LED drivers
++#
++CONFIG_LEDS_GPIO=y
++
++#
++# LED Triggers
++#
++CONFIG_LEDS_TRIGGERS=y
++CONFIG_LEDS_TRIGGER_TIMER=y
++CONFIG_LEDS_TRIGGER_HEARTBEAT=y
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++# CONFIG_HID_SUPPORT is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++CONFIG_USB_LIBUSUAL=y
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++# CONFIG_USB_MON is not set
++
++#
++# USB port drivers
++#
++
++#
++# USB Serial Converter support
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++
++#
++# USB DSL modem support
++#
++
++#
++# USB Gadget Support
++#
++CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG is not set
++# CONFIG_USB_GADGET_DEBUG_FILES is not set
++CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_FSL_USB2 is not set
++# CONFIG_USB_GADGET_NET2280 is not set
++# CONFIG_USB_GADGET_PXA2XX is not set
++# CONFIG_USB_GADGET_M66592 is not set
++# CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_LH7A40X is not set
++# CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_S3C2410 is not set
++CONFIG_USB_GADGET_AT91=y
++CONFIG_USB_AT91=y
++# CONFIG_USB_GADGET_DUMMY_HCD is not set
++# CONFIG_USB_GADGET_DUALSPEED is not set
++# CONFIG_USB_ZERO is not set
++CONFIG_USB_ETH=y
++CONFIG_USB_ETH_RNDIS=y
++# CONFIG_USB_GADGETFS is not set
++# CONFIG_USB_FILE_STORAGE is not set
++# CONFIG_USB_G_SERIAL is not set
++# CONFIG_USB_MIDI_GADGET is not set
++CONFIG_MMC=y
++CONFIG_MMC_DEBUG=y
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_BOUNCE=y
++
++#
++# MMC/SD Host Controller Drivers
++#
++CONFIG_MMC_AT91=y
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++CONFIG_RTC_DRV_DS1553=y
++# CONFIG_RTC_DRV_STK17TA8 is not set
++CONFIG_RTC_DRV_DS1742=y
++CONFIG_RTC_DRV_M48T86=y
++# CONFIG_RTC_DRV_M48T59 is not set
++CONFIG_RTC_DRV_V3020=y
++
++#
++# on-CPU RTC drivers
++#
++
++#
++# DMA Engine support
++#
++# CONFIG_DMA_ENGINE is not set
++
++#
++# DMA Clients
++#
++
++#
++# DMA Devices
++#
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++CONFIG_EXT2_FS_POSIX_ACL=y
++CONFIG_EXT2_FS_SECURITY=y
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++CONFIG_EXT3_FS_POSIX_ACL=y
++CONFIG_EXT3_FS_SECURITY=y
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Network File Systems
++#
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++CONFIG_NFS_DIRECTIO=y
++# CONFIG_NFSD is not set
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++
++#
++# Native Language Support
++#
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++CONFIG_NLS_CODEPAGE_737=y
++CONFIG_NLS_CODEPAGE_775=y
++CONFIG_NLS_CODEPAGE_850=y
++CONFIG_NLS_CODEPAGE_852=y
++CONFIG_NLS_CODEPAGE_855=y
++CONFIG_NLS_CODEPAGE_857=y
++CONFIG_NLS_CODEPAGE_860=y
++CONFIG_NLS_CODEPAGE_861=y
++CONFIG_NLS_CODEPAGE_862=y
++CONFIG_NLS_CODEPAGE_863=y
++CONFIG_NLS_CODEPAGE_864=y
++CONFIG_NLS_CODEPAGE_865=y
++CONFIG_NLS_CODEPAGE_866=y
++CONFIG_NLS_CODEPAGE_869=y
++CONFIG_NLS_CODEPAGE_936=y
++CONFIG_NLS_CODEPAGE_950=y
++CONFIG_NLS_CODEPAGE_932=y
++CONFIG_NLS_CODEPAGE_949=y
++CONFIG_NLS_CODEPAGE_874=y
++CONFIG_NLS_ISO8859_8=y
++CONFIG_NLS_CODEPAGE_1250=y
++CONFIG_NLS_CODEPAGE_1251=y
++CONFIG_NLS_ASCII=y
++CONFIG_NLS_ISO8859_1=y
++CONFIG_NLS_ISO8859_2=y
++CONFIG_NLS_ISO8859_3=y
++CONFIG_NLS_ISO8859_4=y
++CONFIG_NLS_ISO8859_5=y
++CONFIG_NLS_ISO8859_6=y
++CONFIG_NLS_ISO8859_7=y
++CONFIG_NLS_ISO8859_9=y
++CONFIG_NLS_ISO8859_13=y
++CONFIG_NLS_ISO8859_14=y
++CONFIG_NLS_ISO8859_15=y
++CONFIG_NLS_KOI8_R=y
++CONFIG_NLS_KOI8_U=y
++CONFIG_NLS_UTF8=y
++
++#
++# Distributed Lock Manager
++#
++# CONFIG_DLM is not set
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++CONFIG_UNUSED_SYMBOLS=y
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_DEBUG_SLAB is not set
++CONFIG_DEBUG_PREEMPT=y
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++CONFIG_FRAME_POINTER=y
++CONFIG_FORCED_INLINING=y
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_DEBUG_USER is not set
++# CONFIG_DEBUG_ERRORS is not set
++CONFIG_DEBUG_LL=y
++# CONFIG_DEBUG_ICEDCC is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_AUDIT_GENERIC=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/tct_hammer_defconfig b/arch/arm/configs/tct_hammer_defconfig
+new file mode 100644
+index 0000000..576b833
+--- /dev/null
++++ b/arch/arm/configs/tct_hammer_defconfig
+@@ -0,0 +1,886 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc7-hammer
++# Thu Mar 27 16:39:48 2008
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++# CONFIG_GENERIC_TIME is not set
++# CONFIG_GENERIC_CLOCKEVENTS is not set
++CONFIG_MMU=y
++CONFIG_NO_IOPORT=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ARCH_SUPPORTS_AOUT=y
++CONFIG_ZONE_DMA=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++# CONFIG_LOCALVERSION_AUTO is not set
++# CONFIG_SWAP is not set
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++# CONFIG_BUG is not set
++# CONFIG_ELF_CORE is not set
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++# CONFIG_SHMEM is not set
++CONFIG_VM_EVENT_COUNTERS=y
++# CONFIG_SLAB is not set
++# CONFIG_SLUB is not set
++CONFIG_SLOB=y
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_RT_MUTEXES=y
++CONFIG_TINY_SHMEM=y
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# System Type
++#
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_ORION is not set
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++CONFIG_ARCH_S3C2410=y
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_MSM7X00A is not set
++CONFIG_PLAT_S3C24XX=y
++# CONFIG_S3C2410_DMA is not set
++CONFIG_PLAT_S3C=y
++CONFIG_CPU_LLSERIAL_S3C2410_ONLY=y
++CONFIG_CPU_LLSERIAL_S3C2410=y
++
++#
++# Boot options
++#
++# CONFIG_S3C_BOOT_ERROR_RESET is not set
++
++#
++# Power management
++#
++CONFIG_S3C_LOWLEVEL_UART_PORT=0
++
++#
++# S3C2400 Machines
++#
++CONFIG_CPU_S3C2410=y
++CONFIG_S3C2410_GPIO=y
++CONFIG_S3C2410_CLOCK=y
++
++#
++# S3C2410 Machines
++#
++# CONFIG_ARCH_SMDK2410 is not set
++# CONFIG_ARCH_H1940 is not set
++# CONFIG_MACH_N30 is not set
++# CONFIG_ARCH_BAST is not set
++# CONFIG_MACH_OTOM is not set
++# CONFIG_MACH_AML_M5900 is not set
++CONFIG_MACH_TCT_HAMMER=y
++# CONFIG_MACH_VR1000 is not set
++# CONFIG_MACH_QT2410 is not set
++
++#
++# S3C2412 Machines
++#
++# CONFIG_MACH_SMDK2413 is not set
++# CONFIG_MACH_SMDK2412 is not set
++# CONFIG_MACH_VSTMS is not set
++
++#
++# S3C2440 Machines
++#
++# CONFIG_MACH_ANUBIS is not set
++# CONFIG_MACH_OSIRIS is not set
++# CONFIG_MACH_RX3715 is not set
++# CONFIG_ARCH_S3C2440 is not set
++# CONFIG_MACH_NEXCODER_2440 is not set
++
++#
++# S3C2442 Machines
++#
++
++#
++# S3C2443 Machines
++#
++# CONFIG_MACH_SMDK2443 is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM920T=y
++CONFIG_CPU_32v4T=y
++CONFIG_CPU_ABRT_EV4T=y
++CONFIG_CPU_CACHE_V4WT=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_OUTER_CACHE is not set
++
++#
++# Bus support
++#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_PREEMPT is not set
++# CONFIG_NO_IDLE_HZ is not set
++CONFIG_HZ=200
++# CONFIG_AEABI is not set
++# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="mem=64M root=/dev/ram0 init=/linuxrc rw"
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++# CONFIG_INET is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++# CONFIG_PREVENT_FIRMWARE_BUILD is not set
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++CONFIG_MTD_CFI_ADV_OPTIONS=y
++CONFIG_MTD_CFI_NOSWAP=y
++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
++CONFIG_MTD_CFI_GEOMETRY=y
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_OTP is not set
++CONFIG_MTD_CFI_INTELEXT=y
++# CONFIG_MTD_CFI_AMDSTD is not set
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_START=0x00000000
++CONFIG_MTD_PHYSMAP_LEN=0x0
++CONFIG_MTD_PHYSMAP_BANKWIDTH=2
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=10240
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_MISC_DEVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_NETDEVICES is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++# CONFIG_VT_CONSOLE is not set
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_S3C2410=y
++CONFIG_SERIAL_S3C2410_CONSOLE=y
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++# CONFIG_MFD_ASIC3 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++# CONFIG_HID_SUPPORT is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++CONFIG_USB=y
++CONFIG_USB_DEBUG=y
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++# CONFIG_USB_DEVICEFS is not set
++# CONFIG_USB_DEVICE_CLASS is not set
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG is not set
++# CONFIG_USB_GADGET_DEBUG_FILES is not set
++CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_ATMEL_USBA is not set
++# CONFIG_USB_GADGET_FSL_USB2 is not set
++# CONFIG_USB_GADGET_NET2280 is not set
++# CONFIG_USB_GADGET_PXA2XX is not set
++# CONFIG_USB_GADGET_M66592 is not set
++# CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_LH7A40X is not set
++# CONFIG_USB_GADGET_OMAP is not set
++CONFIG_USB_GADGET_S3C2410=y
++CONFIG_USB_S3C2410=y
++# CONFIG_USB_S3C2410_DEBUG is not set
++# CONFIG_USB_GADGET_AT91 is not set
++# CONFIG_USB_GADGET_DUMMY_HCD is not set
++# CONFIG_USB_GADGET_DUALSPEED is not set
++# CONFIG_USB_ZERO is not set
++CONFIG_USB_ETH=y
++CONFIG_USB_ETH_RNDIS=y
++# CONFIG_USB_GADGETFS is not set
++# CONFIG_USB_FILE_STORAGE is not set
++# CONFIG_USB_G_SERIAL is not set
++# CONFIG_USB_MIDI_GADGET is not set
++# CONFIG_USB_G_PRINTER is not set
++# CONFIG_MMC is not set
++# CONFIG_NEW_LEDS is not set
++CONFIG_RTC_LIB=y
++# CONFIG_RTC_CLASS is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_DNOTIFY is not set
++# CONFIG_INOTIFY is not set
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++# CONFIG_PROC_SYSCTL is not set
++CONFIG_SYSFS=y
++# CONFIG_TMPFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++# CONFIG_ENABLE_MUST_CHECK is not set
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++# CONFIG_DETECT_SOFTLOCKUP is not set
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_USER is not set
++CONFIG_DEBUG_ERRORS=y
++# CONFIG_DEBUG_STACK_USAGE is not set
++CONFIG_DEBUG_LL=y
++# CONFIG_DEBUG_ICEDCC is not set
++# CONFIG_DEBUG_S3C_PORT is not set
++CONFIG_DEBUG_S3C_UART=0
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=y
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/yl9200_defconfig b/arch/arm/configs/yl9200_defconfig
+new file mode 100644
+index 0000000..26de37f
+--- /dev/null
++++ b/arch/arm/configs/yl9200_defconfig
+@@ -0,0 +1,1216 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.24-rc6
++# Fri Jan 11 09:53:59 2008
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ZONE_DMA=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++# CONFIG_EXPERIMENTAL is not set
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++# CONFIG_SWAP is not set
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
++# CONFIG_SYSFS_DEPRECATED is not set
++# CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++# CONFIG_EMBEDDED is not set
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++# CONFIG_IOSCHED_DEADLINE is not set
++# CONFIG_IOSCHED_CFQ is not set
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++CONFIG_DEFAULT_NOOP=y
++CONFIG_DEFAULT_IOSCHED="noop"
++
++#
++# System Type
++#
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++CONFIG_ARCH_AT91=y
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
++
++#
++# Atmel AT91 System-on-Chip
++#
++CONFIG_ARCH_AT91RM9200=y
++# CONFIG_ARCH_AT91SAM9260 is not set
++# CONFIG_ARCH_AT91SAM9261 is not set
++# CONFIG_ARCH_AT91SAM9263 is not set
++# CONFIG_ARCH_AT91SAM9RL is not set
++# CONFIG_ARCH_AT91X40 is not set
++CONFIG_AT91_PMC_UNIT=y
++
++#
++# AT91RM9200 Board Type
++#
++# CONFIG_MACH_ONEARM is not set
++CONFIG_ARCH_AT91RM9200DK=y
++# CONFIG_MACH_AT91RM9200EK is not set
++# CONFIG_MACH_CSB337 is not set
++# CONFIG_MACH_CSB637 is not set
++# CONFIG_MACH_CARMEVA is not set
++# CONFIG_MACH_ATEB9200 is not set
++# CONFIG_MACH_KB9200 is not set
++# CONFIG_MACH_PICOTUX2XX is not set
++# CONFIG_MACH_KAFA is not set
++CONFIG_MACH_YL9200=y
++
++#
++# AT91 Board Options
++#
++# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
++
++#
++# AT91 Feature Selections
++#
++# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM920T=y
++CONFIG_CPU_32v4T=y
++CONFIG_CPU_ABRT_EV4T=y
++CONFIG_CPU_CACHE_V4WT=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++# CONFIG_ARM_THUMB is not set
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_OUTER_CACHE is not set
++
++#
++# Bus support
++#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++CONFIG_HZ=100
++# CONFIG_AEABI is not set
++# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_LEDS is not set
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20410000,3145728 root=/dev/ram0 rw"
++# CONFIG_XIP_KERNEL is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++CONFIG_SUSPEND_UP_POSSIBLE=y
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++# CONFIG_INET_DIAG is not set
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_AFS_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++CONFIG_MTD_CFI_INTELEXT=y
++# CONFIG_MTD_CFI_AMDSTD is not set
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++CONFIG_MTD_RAM=y
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++CONFIG_MTD_COMPLEX_MAPPINGS=y
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_START=0x0000000
++CONFIG_MTD_PHYSMAP_LEN=0
++CONFIG_MTD_PHYSMAP_BANKWIDTH=2
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_IMPA7 is not set
++CONFIG_MTD_PLATRAM=y
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++# CONFIG_MTD_NAND_VERIFY_WRITE is not set
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_IDS=y
++CONFIG_MTD_NAND_AT91=y
++# CONFIG_MTD_NAND_NANDSIM is not set
++CONFIG_MTD_NAND_PLATFORM=y
++# CONFIG_MTD_ALAUDA is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=3
++CONFIG_BLK_DEV_RAM_SIZE=8192
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_MISC_DEVICES is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_SCSI_DEBUG is not set
++CONFIG_ATA=y
++# CONFIG_ATA_NONSTANDARD is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++CONFIG_DAVICOM_PHY=y
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_ARM_AT91_ETHER=y
++# CONFIG_AX88796 is not set
++# CONFIG_SMC91X is not set
++# CONFIG_DM9000 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ATKBD is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++CONFIG_KEYBOARD_GPIO=y
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_PS2_ALPS=y
++CONFIG_MOUSE_PS2_LOGIPS2PP=y
++CONFIG_MOUSE_PS2_SYNAPTICS=y
++CONFIG_MOUSE_PS2_LIFEBOOK=y
++CONFIG_MOUSE_PS2_TRACKPOINT=y
++# CONFIG_MOUSE_PS2_TOUCHKIT is not set
++# CONFIG_MOUSE_SERIAL is not set
++# CONFIG_MOUSE_APPLETOUCH is not set
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_MOUSE_GPIO is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++CONFIG_INPUT_TOUCHSCREEN=y
++CONFIG_TOUCHSCREEN_ADS7846=y
++# CONFIG_TOUCHSCREEN_FUJITSU is not set
++# CONFIG_TOUCHSCREEN_GUNZE is not set
++# CONFIG_TOUCHSCREEN_ELO is not set
++# CONFIG_TOUCHSCREEN_MTOUCH is not set
++# CONFIG_TOUCHSCREEN_MK712 is not set
++# CONFIG_TOUCHSCREEN_PENMOUNT is not set
++# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
++# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
++# CONFIG_TOUCHSCREEN_UCB1400 is not set
++# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++# CONFIG_SERIO_SERPORT is not set
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_ATMEL=y
++CONFIG_SERIAL_ATMEL_CONSOLE=y
++# CONFIG_SERIAL_ATMEL_TTYAT is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++# CONFIG_I2C_CHARDEV is not set
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TINY_USB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++CONFIG_SPI=y
++CONFIG_SPI_DEBUG=y
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_ATMEL=y
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_TLE62X0 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++CONFIG_FB=y
++# CONFIG_FIRMWARE_EDID is not set
++# CONFIG_FB_DDC is not set
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
++# CONFIG_FB_SYS_FILLRECT is not set
++# CONFIG_FB_SYS_COPYAREA is not set
++# CONFIG_FB_SYS_IMAGEBLIT is not set
++# CONFIG_FB_SYS_FOPS is not set
++CONFIG_FB_DEFERRED_IO=y
++# CONFIG_FB_SVGALIB is not set
++# CONFIG_FB_MACMODES is not set
++# CONFIG_FB_BACKLIGHT is not set
++# CONFIG_FB_MODE_HELPERS is not set
++# CONFIG_FB_TILEBLITTING is not set
++
++#
++# Frame buffer hardware drivers
++#
++# CONFIG_FB_S1D13XXX is not set
++CONFIG_FB_S1D135XX=y
++# CONFIG_FB_VIRTUAL is not set
++CONFIG_BACKLIGHT_LCD_SUPPORT=y
++CONFIG_LCD_CLASS_DEVICE=y
++# CONFIG_LCD_LTV350QV is not set
++CONFIG_BACKLIGHT_CLASS_DEVICE=y
++# CONFIG_BACKLIGHT_CORGI is not set
++
++#
++# Display device support
++#
++CONFIG_DISPLAY_SUPPORT=y
++
++#
++# Display hardware drivers
++#
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++# CONFIG_FRAMEBUFFER_CONSOLE is not set
++CONFIG_LOGO=y
++# CONFIG_LOGO_LINUX_MONO is not set
++# CONFIG_LOGO_LINUX_VGA16 is not set
++CONFIG_LOGO_LINUX_CLUT224=y
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++CONFIG_HID_DEBUG=y
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++# CONFIG_USB_HIDINPUT_POWERBOOK is not set
++# CONFIG_USB_HIDDEV is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++CONFIG_USB=y
++CONFIG_USB_DEBUG=y
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++# CONFIG_USB_DEVICE_CLASS is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++
++#
++# USB Serial Converter support
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++
++#
++# USB DSL modem support
++#
++
++#
++# USB Gadget Support
++#
++CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG_FILES is not set
++# CONFIG_USB_GADGET_DEBUG_FS is not set
++CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_ATMEL_USBA is not set
++# CONFIG_USB_GADGET_FSL_USB2 is not set
++# CONFIG_USB_GADGET_NET2280 is not set
++# CONFIG_USB_GADGET_PXA2XX is not set
++CONFIG_USB_GADGET_M66592=y
++CONFIG_USB_M66592=y
++# CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_LH7A40X is not set
++# CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_S3C2410 is not set
++# CONFIG_USB_GADGET_AT91 is not set
++# CONFIG_USB_GADGET_DUMMY_HCD is not set
++CONFIG_USB_GADGET_DUALSPEED=y
++# CONFIG_USB_ZERO is not set
++# CONFIG_USB_ETH is not set
++# CONFIG_USB_GADGETFS is not set
++CONFIG_USB_FILE_STORAGE=y
++# CONFIG_USB_FILE_STORAGE_TEST is not set
++# CONFIG_USB_G_SERIAL is not set
++# CONFIG_USB_MIDI_GADGET is not set
++CONFIG_MMC=y
++CONFIG_MMC_DEBUG=y
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++# CONFIG_MMC_BLOCK_BOUNCE is not set
++# CONFIG_SDIO_UART is not set
++
++#
++# MMC/SD Host Controller Drivers
++#
++CONFIG_MMC_AT91=y
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=y
++
++#
++# LED drivers
++#
++CONFIG_LEDS_GPIO=y
++
++#
++# LED Triggers
++#
++CONFIG_LEDS_TRIGGERS=y
++CONFIG_LEDS_TRIGGER_TIMER=y
++CONFIG_LEDS_TRIGGER_HEARTBEAT=y
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_AT91RM9200=y
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++# CONFIG_EXT2_FS_POSIX_ACL is not set
++# CONFIG_EXT2_FS_SECURITY is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_FS_MBCACHE=y
++CONFIG_REISERFS_FS=y
++# CONFIG_REISERFS_CHECK is not set
++# CONFIG_REISERFS_PROC_INFO is not set
++# CONFIG_REISERFS_FS_XATTR is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++CONFIG_ISO9660_FS=y
++CONFIG_JOLIET=y
++CONFIG_ZISOFS=y
++CONFIG_UDF_FS=y
++CONFIG_UDF_NLS=y
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_HFSPLUS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=1
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++CONFIG_JFFS2_COMPRESSION_OPTIONS=y
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++CONFIG_JFFS2_RUBIN=y
++# CONFIG_JFFS2_CMODE_NONE is not set
++CONFIG_JFFS2_CMODE_PRIORITY=y
++# CONFIG_JFFS2_CMODE_SIZE is not set
++# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++# CONFIG_NFS_FS is not set
++# CONFIG_NFSD is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++CONFIG_MAC_PARTITION=y
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++CONFIG_INSTRUMENTATION=y
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++# CONFIG_ENABLE_MUST_CHECK is not set
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++CONFIG_SLUB_DEBUG_ON=y
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++CONFIG_DEBUG_KOBJECT=y
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_DEBUG_INFO=y
++# CONFIG_DEBUG_VM is not set
++CONFIG_DEBUG_LIST=y
++# CONFIG_DEBUG_SG is not set
++CONFIG_FRAME_POINTER=y
++CONFIG_FORCED_INLINING=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++CONFIG_DEBUG_USER=y
++CONFIG_DEBUG_ERRORS=y
++CONFIG_DEBUG_LL=y
++# CONFIG_DEBUG_ICEDCC is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
+index 00d44c6..ad455ff 100644
+--- a/arch/arm/kernel/Makefile
++++ b/arch/arm/kernel/Makefile
+@@ -7,7 +7,7 @@ AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
+ # Object file lists.
+
+ obj-y := compat.o entry-armv.o entry-common.o irq.o \
+- process.o ptrace.o semaphore.o setup.o signal.o \
++ process.o ptrace.o setup.o signal.o \
+ sys_arm.o stacktrace.o time.o traps.o
+
+ obj-$(CONFIG_ISA_DMA_API) += dma.o
+@@ -22,6 +22,7 @@ obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
+ obj-$(CONFIG_KPROBES) += kprobes.o kprobes-decode.o
+ obj-$(CONFIG_ATAGS_PROC) += atags.o
+ obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
++obj-$(CONFIG_ARM_THUMBEE) += thumbee.o
+
+ obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
+ AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312
+diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
+index 3278e71..0a0d247 100644
+--- a/arch/arm/kernel/asm-offsets.c
++++ b/arch/arm/kernel/asm-offsets.c
+@@ -58,6 +58,9 @@ int main(void)
+ DEFINE(TI_TP_VALUE, offsetof(struct thread_info, tp_value));
+ DEFINE(TI_FPSTATE, offsetof(struct thread_info, fpstate));
+ DEFINE(TI_VFPSTATE, offsetof(struct thread_info, vfpstate));
++#ifdef CONFIG_ARM_THUMBEE
++ DEFINE(TI_THUMBEE_STATE, offsetof(struct thread_info, thumbee_state));
++#endif
+ #ifdef CONFIG_IWMMXT
+ DEFINE(TI_IWMMXT_STATE, offsetof(struct thread_info, fpstate.iwmmxt));
+ #endif
+@@ -108,5 +111,12 @@ int main(void)
+ DEFINE(PROCINFO_INITFUNC, offsetof(struct proc_info_list, __cpu_flush));
+ DEFINE(PROCINFO_MM_MMUFLAGS, offsetof(struct proc_info_list, __cpu_mm_mmu_flags));
+ DEFINE(PROCINFO_IO_MMUFLAGS, offsetof(struct proc_info_list, __cpu_io_mmu_flags));
++ BLANK();
++#ifdef MULTI_DABORT
++ DEFINE(PROCESSOR_DABT_FUNC, offsetof(struct processor, _data_abort));
++#endif
++#ifdef MULTI_PABORT
++ DEFINE(PROCESSOR_PABT_FUNC, offsetof(struct processor, _prefetch_abort));
++#endif
+ return 0;
+ }
+diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
+index 7e97b73..30a67a5 100644
+--- a/arch/arm/kernel/calls.S
++++ b/arch/arm/kernel/calls.S
+@@ -359,9 +359,11 @@
+ CALL(sys_kexec_load)
+ CALL(sys_utimensat)
+ CALL(sys_signalfd)
+-/* 350 */ CALL(sys_ni_syscall)
++/* 350 */ CALL(sys_timerfd_create)
+ CALL(sys_eventfd)
+ CALL(sys_fallocate)
++ CALL(sys_timerfd_settime)
++ CALL(sys_timerfd_gettime)
+ #ifndef syscalls_counted
+ .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
+ #define syscalls_counted
+diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
+index a46d5b4..7dca225 100644
+--- a/arch/arm/kernel/entry-armv.S
++++ b/arch/arm/kernel/entry-armv.S
+@@ -166,12 +166,12 @@ __dabt_svc:
+ @ The abort handler must return the aborted address in r0, and
+ @ the fault status register in r1. r9 must be preserved.
+ @
+-#ifdef MULTI_ABORT
++#ifdef MULTI_DABORT
+ ldr r4, .LCprocfns
+ mov lr, pc
+- ldr pc, [r4]
++ ldr pc, [r4, #PROCESSOR_DABT_FUNC]
+ #else
+- bl CPU_ABORT_HANDLER
++ bl CPU_DABORT_HANDLER
+ #endif
+
+ @
+@@ -209,14 +209,12 @@ __irq_svc:
+
+ irq_handler
+ #ifdef CONFIG_PREEMPT
++ str r8, [tsk, #TI_PREEMPT] @ restore preempt count
+ ldr r0, [tsk, #TI_FLAGS] @ get flags
++ teq r8, #0 @ if preempt count != 0
++ movne r0, #0 @ force flags to 0
+ tst r0, #_TIF_NEED_RESCHED
+ blne svc_preempt
+-preempt_return:
+- ldr r0, [tsk, #TI_PREEMPT] @ read preempt value
+- str r8, [tsk, #TI_PREEMPT] @ restore preempt count
+- teq r0, r7
+- strne r0, [r0, -r0] @ bug()
+ #endif
+ ldr r0, [sp, #S_PSR] @ irqs are already disabled
+ msr spsr_cxsf, r0
+@@ -230,19 +228,11 @@ preempt_return:
+
+ #ifdef CONFIG_PREEMPT
+ svc_preempt:
+- teq r8, #0 @ was preempt count = 0
+- ldreq r6, .LCirq_stat
+- movne pc, lr @ no
+- ldr r0, [r6, #4] @ local_irq_count
+- ldr r1, [r6, #8] @ local_bh_count
+- adds r0, r0, r1
+- movne pc, lr
+- mov r7, #0 @ preempt_schedule_irq
+- str r7, [tsk, #TI_PREEMPT] @ expects preempt_count == 0
++ mov r8, lr
+ 1: bl preempt_schedule_irq @ irq en/disable is done inside
+ ldr r0, [tsk, #TI_FLAGS] @ get new tasks TI_FLAGS
+ tst r0, #_TIF_NEED_RESCHED
+- beq preempt_return @ go again
++ moveq pc, r8 @ go again
+ b 1b
+ #endif
+
+@@ -293,7 +283,6 @@ __pabt_svc:
+ mrs r9, cpsr
+ tst r3, #PSR_I_BIT
+ biceq r9, r9, #PSR_I_BIT
+- msr cpsr_c, r9
+
+ @
+ @ set args, then call main handler
+@@ -301,7 +290,15 @@ __pabt_svc:
+ @ r0 - address of faulting instruction
+ @ r1 - pointer to registers on stack
+ @
+- mov r0, r2 @ address (pc)
++#ifdef MULTI_PABORT
++ mov r0, r2 @ pass address of aborted instruction.
++ ldr r4, .LCprocfns
++ mov lr, pc
++ ldr pc, [r4, #PROCESSOR_PABT_FUNC]
++#else
++ CPU_PABORT_HANDLER(r0, r2)
++#endif
++ msr cpsr_c, r9 @ Maybe enable interrupts
+ mov r1, sp @ regs
+ bl do_PrefetchAbort @ call abort handler
+
+@@ -320,16 +317,12 @@ __pabt_svc:
+ .align 5
+ .LCcralign:
+ .word cr_alignment
+-#ifdef MULTI_ABORT
++#ifdef MULTI_DABORT
+ .LCprocfns:
+ .word processor
+ #endif
+ .LCfp:
+ .word fp_enter
+-#ifdef CONFIG_PREEMPT
+-.LCirq_stat:
+- .word irq_stat
+-#endif
+
+ /*
+ * User mode handlers
+@@ -404,12 +397,12 @@ __dabt_usr:
+ @ The abort handler must return the aborted address in r0, and
+ @ the fault status register in r1.
+ @
+-#ifdef MULTI_ABORT
++#ifdef MULTI_DABORT
+ ldr r4, .LCprocfns
+ mov lr, pc
+- ldr pc, [r4]
++ ldr pc, [r4, #PROCESSOR_DABT_FUNC]
+ #else
+- bl CPU_ABORT_HANDLER
++ bl CPU_DABORT_HANDLER
+ #endif
+
+ @
+@@ -455,10 +448,6 @@ __irq_usr:
+ __und_usr:
+ usr_entry
+
+- tst r3, #PSR_T_BIT @ Thumb mode?
+- bne __und_usr_unknown @ ignore FP
+- sub r4, r2, #4
+-
+ @
+ @ fall through to the emulation code, which returns using r9 if
+ @ it has emulated the instruction, or the more conventional lr
+@@ -468,7 +457,24 @@ __und_usr:
+ @
+ adr r9, ret_from_exception
+ adr lr, __und_usr_unknown
+-1: ldrt r0, [r4]
++ tst r3, #PSR_T_BIT @ Thumb mode?
++ subeq r4, r2, #4 @ ARM instr at LR - 4
++ subne r4, r2, #2 @ Thumb instr at LR - 2
++1: ldreqt r0, [r4]
++ beq call_fpe
++ @ Thumb instruction
++#if __LINUX_ARM_ARCH__ >= 7
++2: ldrht r5, [r4], #2
++ and r0, r5, #0xf800 @ mask bits 111x x... .... ....
++ cmp r0, #0xe800 @ 32bit instruction if xx != 0
++ blo __und_usr_unknown
++3: ldrht r0, [r4]
++ add r2, r2, #2 @ r2 is PC + 2, make it PC + 4
++ orr r0, r0, r5, lsl #16
++#else
++ b __und_usr_unknown
++#endif
++
+ @
+ @ fallthrough to call_fpe
+ @
+@@ -477,10 +483,14 @@ __und_usr:
+ * The out of line fixup for the ldrt above.
+ */
+ .section .fixup, "ax"
+-2: mov pc, r9
++4: mov pc, r9
+ .previous
+ .section __ex_table,"a"
+- .long 1b, 2b
++ .long 1b, 4b
++#if __LINUX_ARM_ARCH__ >= 7
++ .long 2b, 4b
++ .long 3b, 4b
++#endif
+ .previous
+
+ /*
+@@ -507,9 +517,16 @@ __und_usr:
+ * r10 = this threads thread_info structure.
+ * lr = unrecognised instruction return address
+ */
++ @
++ @ Fall-through from Thumb-2 __und_usr
++ @
++#ifdef CONFIG_NEON
++ adr r6, .LCneon_thumb_opcodes
++ b 2f
++#endif
+ call_fpe:
+ #ifdef CONFIG_NEON
+- adr r6, .LCneon_opcodes
++ adr r6, .LCneon_arm_opcodes
+ 2:
+ ldr r7, [r6], #4 @ mask value
+ cmp r7, #0 @ end mask?
+@@ -526,6 +543,7 @@ call_fpe:
+ 1:
+ #endif
+ tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC have bit 27
++ tstne r0, #0x04000000 @ bit 26 set on both ARM and Thumb-2
+ #if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
+ and r8, r0, #0x0f000000 @ mask out op-code bits
+ teqne r8, #0x0f000000 @ SWI (ARM6/7 bug)?
+@@ -577,7 +595,7 @@ call_fpe:
+ #ifdef CONFIG_NEON
+ .align 6
+
+-.LCneon_opcodes:
++.LCneon_arm_opcodes:
+ .word 0xfe000000 @ mask
+ .word 0xf2000000 @ opcode
+
+@@ -586,6 +604,16 @@ call_fpe:
+
+ .word 0x00000000 @ mask
+ .word 0x00000000 @ opcode
++
++.LCneon_thumb_opcodes:
++ .word 0xef000000 @ mask
++ .word 0xef000000 @ opcode
++
++ .word 0xff100000 @ mask
++ .word 0xf9000000 @ opcode
++
++ .word 0x00000000 @ mask
++ .word 0x00000000 @ opcode
+ #endif
+
+ do_fpe:
+@@ -619,8 +647,15 @@ __und_usr_unknown:
+ __pabt_usr:
+ usr_entry
+
++#ifdef MULTI_PABORT
++ mov r0, r2 @ pass address of aborted instruction.
++ ldr r4, .LCprocfns
++ mov lr, pc
++ ldr pc, [r4, #PROCESSOR_PABT_FUNC]
++#else
++ CPU_PABORT_HANDLER(r0, r2)
++#endif
+ enable_irq @ Enable interrupts
+- mov r0, r2 @ address (pc)
+ mov r1, sp @ regs
+ bl do_PrefetchAbort @ call abort handler
+ /* fall through */
+diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
+index 6c90c50..597ed00 100644
+--- a/arch/arm/kernel/entry-common.S
++++ b/arch/arm/kernel/entry-common.S
+@@ -352,6 +352,11 @@ sys_mmap2:
+ b do_mmap2
+ #endif
+
++ENTRY(pabort_ifar)
++ mrc p15, 0, r0, cr6, cr0, 2
++ENTRY(pabort_noifar)
++ mov pc, lr
++
+ #ifdef CONFIG_OABI_COMPAT
+
+ /*
+diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
+index 50f667f..7e9c00a 100644
+--- a/arch/arm/kernel/head-common.S
++++ b/arch/arm/kernel/head-common.S
+@@ -75,8 +75,13 @@ __error_p:
+ #ifdef CONFIG_DEBUG_LL
+ adr r0, str_p1
+ bl printascii
++ mov r0, r9
++ bl printhex8
++ adr r0, str_p2
++ bl printascii
+ b __error
+-str_p1: .asciz "\nError: unrecognized/unsupported processor variant.\n"
++str_p1: .asciz "\nError: unrecognized/unsupported processor variant (0x"
++str_p2: .asciz ").\n"
+ .align
+ #endif
+
+diff --git a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c
+deleted file mode 100644
+index 981fe5c..0000000
+--- a/arch/arm/kernel/semaphore.c
++++ /dev/null
+@@ -1,221 +0,0 @@
+-/*
+- * ARM semaphore implementation, taken from
+- *
+- * i386 semaphore implementation.
+- *
+- * (C) Copyright 1999 Linus Torvalds
+- *
+- * Modified for ARM by Russell King
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-#include <linux/module.h>
+-#include <linux/sched.h>
+-#include <linux/errno.h>
+-#include <linux/init.h>
+-
+-#include <asm/semaphore.h>
+-
+-/*
+- * Semaphores are implemented using a two-way counter:
+- * The "count" variable is decremented for each process
+- * that tries to acquire the semaphore, while the "sleeping"
+- * variable is a count of such acquires.
+- *
+- * Notably, the inline "up()" and "down()" functions can
+- * efficiently test if they need to do any extra work (up
+- * needs to do something only if count was negative before
+- * the increment operation.
+- *
+- * "sleeping" and the contention routine ordering is
+- * protected by the semaphore spinlock.
+- *
+- * Note that these functions are only called when there is
+- * contention on the lock, and as such all this is the
+- * "non-critical" part of the whole semaphore business. The
+- * critical part is the inline stuff in <asm/semaphore.h>
+- * where we want to avoid any extra jumps and calls.
+- */
+-
+-/*
+- * Logic:
+- * - only on a boundary condition do we need to care. When we go
+- * from a negative count to a non-negative, we wake people up.
+- * - when we go from a non-negative count to a negative do we
+- * (a) synchronize with the "sleeper" count and (b) make sure
+- * that we're on the wakeup list before we synchronize so that
+- * we cannot lose wakeup events.
+- */
+-
+-void __up(struct semaphore *sem)
+-{
+- wake_up(&sem->wait);
+-}
+-
+-static DEFINE_SPINLOCK(semaphore_lock);
+-
+-void __sched __down(struct semaphore * sem)
+-{
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+- tsk->state = TASK_UNINTERRUPTIBLE;
+- add_wait_queue_exclusive(&sem->wait, &wait);
+-
+- spin_lock_irq(&semaphore_lock);
+- sem->sleepers++;
+- for (;;) {
+- int sleepers = sem->sleepers;
+-
+- /*
+- * Add "everybody else" into it. They aren't
+- * playing, because we own the spinlock.
+- */
+- if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+- sem->sleepers = 0;
+- break;
+- }
+- sem->sleepers = 1; /* us - see -1 above */
+- spin_unlock_irq(&semaphore_lock);
+-
+- schedule();
+- tsk->state = TASK_UNINTERRUPTIBLE;
+- spin_lock_irq(&semaphore_lock);
+- }
+- spin_unlock_irq(&semaphore_lock);
+- remove_wait_queue(&sem->wait, &wait);
+- tsk->state = TASK_RUNNING;
+- wake_up(&sem->wait);
+-}
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+- int retval = 0;
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+- tsk->state = TASK_INTERRUPTIBLE;
+- add_wait_queue_exclusive(&sem->wait, &wait);
+-
+- spin_lock_irq(&semaphore_lock);
+- sem->sleepers ++;
+- for (;;) {
+- int sleepers = sem->sleepers;
+-
+- /*
+- * With signals pending, this turns into
+- * the trylock failure case - we won't be
+- * sleeping, and we* can't get the lock as
+- * it has contention. Just correct the count
+- * and exit.
+- */
+- if (signal_pending(current)) {
+- retval = -EINTR;
+- sem->sleepers = 0;
+- atomic_add(sleepers, &sem->count);
+- break;
+- }
+-
+- /*
+- * Add "everybody else" into it. They aren't
+- * playing, because we own the spinlock. The
+- * "-1" is because we're still hoping to get
+- * the lock.
+- */
+- if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+- sem->sleepers = 0;
+- break;
+- }
+- sem->sleepers = 1; /* us - see -1 above */
+- spin_unlock_irq(&semaphore_lock);
+-
+- schedule();
+- tsk->state = TASK_INTERRUPTIBLE;
+- spin_lock_irq(&semaphore_lock);
+- }
+- spin_unlock_irq(&semaphore_lock);
+- tsk->state = TASK_RUNNING;
+- remove_wait_queue(&sem->wait, &wait);
+- wake_up(&sem->wait);
+- return retval;
+-}
+-
+-/*
+- * Trylock failed - make sure we correct for
+- * having decremented the count.
+- *
+- * We could have done the trylock with a
+- * single "cmpxchg" without failure cases,
+- * but then it wouldn't work on a 386.
+- */
+-int __down_trylock(struct semaphore * sem)
+-{
+- int sleepers;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&semaphore_lock, flags);
+- sleepers = sem->sleepers + 1;
+- sem->sleepers = 0;
+-
+- /*
+- * Add "everybody else" and us into it. They aren't
+- * playing, because we own the spinlock.
+- */
+- if (!atomic_add_negative(sleepers, &sem->count))
+- wake_up(&sem->wait);
+-
+- spin_unlock_irqrestore(&semaphore_lock, flags);
+- return 1;
+-}
+-
+-/*
+- * The semaphore operations have a special calling sequence that
+- * allow us to do a simpler in-line version of them. These routines
+- * need to convert that sequence back into the C sequence when
+- * there is contention on the semaphore.
+- *
+- * ip contains the semaphore pointer on entry. Save the C-clobbered
+- * registers (r0 to r3 and lr), but not ip, as we use it as a return
+- * value in some cases..
+- * To remain AAPCS compliant (64-bit stack align) we save r4 as well.
+- */
+-asm(" .section .sched.text,\"ax\",%progbits \n\
+- .align 5 \n\
+- .globl __down_failed \n\
+-__down_failed: \n\
+- stmfd sp!, {r0 - r4, lr} \n\
+- mov r0, ip \n\
+- bl __down \n\
+- ldmfd sp!, {r0 - r4, pc} \n\
+- \n\
+- .align 5 \n\
+- .globl __down_interruptible_failed \n\
+-__down_interruptible_failed: \n\
+- stmfd sp!, {r0 - r4, lr} \n\
+- mov r0, ip \n\
+- bl __down_interruptible \n\
+- mov ip, r0 \n\
+- ldmfd sp!, {r0 - r4, pc} \n\
+- \n\
+- .align 5 \n\
+- .globl __down_trylock_failed \n\
+-__down_trylock_failed: \n\
+- stmfd sp!, {r0 - r4, lr} \n\
+- mov r0, ip \n\
+- bl __down_trylock \n\
+- mov ip, r0 \n\
+- ldmfd sp!, {r0 - r4, pc} \n\
+- \n\
+- .align 5 \n\
+- .globl __up_wakeup \n\
+-__up_wakeup: \n\
+- stmfd sp!, {r0 - r4, lr} \n\
+- mov r0, ip \n\
+- bl __up \n\
+- ldmfd sp!, {r0 - r4, pc} \n\
+- ");
+-
+-EXPORT_SYMBOL(__down_failed);
+-EXPORT_SYMBOL(__down_interruptible_failed);
+-EXPORT_SYMBOL(__down_trylock_failed);
+-EXPORT_SYMBOL(__up_wakeup);
+diff --git a/arch/arm/kernel/thumbee.c b/arch/arm/kernel/thumbee.c
+new file mode 100644
+index 0000000..df3f6b7
+--- /dev/null
++++ b/arch/arm/kernel/thumbee.c
+@@ -0,0 +1,81 @@
++/*
++ * arch/arm/kernel/thumbee.c
++ *
++ * Copyright (C) 2008 ARM Limited
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++
++#include <asm/thread_notify.h>
++
++/*
++ * Access to the ThumbEE Handler Base register
++ */
++static inline unsigned long teehbr_read()
++{
++ unsigned long v;
++ asm("mrc p14, 6, %0, c1, c0, 0\n" : "=r" (v));
++ return v;
++}
++
++static inline void teehbr_write(unsigned long v)
++{
++ asm("mcr p14, 6, %0, c1, c0, 0\n" : : "r" (v));
++}
++
++static int thumbee_notifier(struct notifier_block *self, unsigned long cmd, void *t)
++{
++ struct thread_info *thread = t;
++
++ switch (cmd) {
++ case THREAD_NOTIFY_FLUSH:
++ thread->thumbee_state = 0;
++ break;
++ case THREAD_NOTIFY_SWITCH:
++ current_thread_info()->thumbee_state = teehbr_read();
++ teehbr_write(thread->thumbee_state);
++ break;
++ }
++
++ return NOTIFY_DONE;
++}
++
++static struct notifier_block thumbee_notifier_block = {
++ .notifier_call = thumbee_notifier,
++};
++
++static int __init thumbee_init(void)
++{
++ unsigned long pfr0;
++ unsigned int cpu_arch = cpu_architecture();
++
++ if (cpu_arch < CPU_ARCH_ARMv7)
++ return 0;
++
++ /* processor feature register 0 */
++ asm("mrc p15, 0, %0, c0, c1, 0\n" : "=r" (pfr0));
++ if ((pfr0 & 0x0000f000) != 0x00001000)
++ return 0;
++
++ printk(KERN_INFO "ThumbEE CPU extension supported.\n");
++ elf_hwcap |= HWCAP_THUMBEE;
++ thread_register_notifier(&thumbee_notifier_block);
++
++ return 0;
++}
++
++late_initcall(thumbee_init);
+diff --git a/arch/arm/mach-aaec2000/clock.c b/arch/arm/mach-aaec2000/clock.c
+index 74aa7a3..e10ee15 100644
+--- a/arch/arm/mach-aaec2000/clock.c
++++ b/arch/arm/mach-aaec2000/clock.c
+@@ -18,8 +18,6 @@
+ #include <linux/clk.h>
+ #include <linux/mutex.h>
+
+-#include <asm/semaphore.h>
+-
+ #include "clock.h"
+
+ static LIST_HEAD(clocks);
+diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
+index 074dcd5..0fc07b6 100644
+--- a/arch/arm/mach-at91/Kconfig
++++ b/arch/arm/mach-at91/Kconfig
+@@ -12,18 +12,28 @@ config ARCH_AT91RM9200
+
+ config ARCH_AT91SAM9260
+ bool "AT91SAM9260 or AT91SAM9XE"
++ select GENERIC_TIME
++ select GENERIC_CLOCKEVENTS
+
+ config ARCH_AT91SAM9261
+ bool "AT91SAM9261"
++ select GENERIC_TIME
++ select GENERIC_CLOCKEVENTS
+
+ config ARCH_AT91SAM9263
+ bool "AT91SAM9263"
++ select GENERIC_TIME
++ select GENERIC_CLOCKEVENTS
+
+ config ARCH_AT91SAM9RL
+ bool "AT91SAM9RL"
++ select GENERIC_TIME
++ select GENERIC_CLOCKEVENTS
+
+ config ARCH_AT91CAP9
+ bool "AT91CAP9"
++ select GENERIC_TIME
++ select GENERIC_CLOCKEVENTS
+
+ config ARCH_AT91X40
+ bool "AT91x40"
+@@ -109,6 +119,13 @@ config MACH_KAFA
+ help
+ Select this if you are using Sperry-Sun's KAFA board.
+
++config MACH_ECBAT91
++ bool "emQbit ECB_AT91 SBC"
++ depends on ARCH_AT91RM9200
++ help
++ Select this if you are using emQbit's ECB_AT91 board.
++ <http://wiki.emqbit.com/free-ecb-at91>
++
+ endif
+
+ # ----------------------------------------------------------
+@@ -133,6 +150,20 @@ config MACH_AT91SAM9260EK
+ Select this if you are using Atmel's AT91SAM9260-EK or AT91SAM9XE Evaluation Kit
+ <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3933>
+
++config MACH_CAM60
++ bool "KwikByte KB9260 (CAM60) board"
++ depends on ARCH_AT91SAM9260
++ help
++ Select this if you are using KwikByte's KB9260 (CAM60) board based on the Atmel AT91SAM9260.
++ <http://www.kwikbyte.com/KB9260.html>
++
++config MACH_SAM9_L9260
++ bool "Olimex SAM9-L9260 board"
++ depends on ARCH_AT91SAM9260
++ help
++ Select this if you are using Olimex's SAM9-L9260 board based on the Atmel AT91SAM9260.
++ <http://www.olimex.com/dev/sam9-L9260.html>
++
+ endif
+
+ # ----------------------------------------------------------
+@@ -216,7 +247,7 @@ comment "AT91 Board Options"
+
+ config MTD_AT91_DATAFLASH_CARD
+ bool "Enable DataFlash Card support"
+- depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9263EK || MACH_AT91CAP9ADK)
++ depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9263EK || MACH_AT91CAP9ADK || MACH_SAM9_L9260 || MACH_ECBAT91)
+ help
+ Enable support for the DataFlash card.
+
+diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
+index bf5f293..8d9bc01 100644
+--- a/arch/arm/mach-at91/Makefile
++++ b/arch/arm/mach-at91/Makefile
+@@ -29,9 +29,12 @@ obj-$(CONFIG_MACH_KB9200) += board-kb9202.o
+ obj-$(CONFIG_MACH_ATEB9200) += board-eb9200.o
+ obj-$(CONFIG_MACH_KAFA) += board-kafa.o
+ obj-$(CONFIG_MACH_PICOTUX2XX) += board-picotux200.o
++obj-$(CONFIG_MACH_ECBAT91) += board-ecbat91.o
+
+ # AT91SAM9260 board-specific support
+ obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o
++obj-$(CONFIG_MACH_CAM60) += board-cam60.o
++obj-$(CONFIG_MACH_SAM9_L9260) += board-sam9-l9260.o
+
+ # AT91SAM9261 board-specific support
+ obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o
+diff --git a/arch/arm/mach-at91/at91cap9.c b/arch/arm/mach-at91/at91cap9.c
+index 48d27d8..933fa8f 100644
+--- a/arch/arm/mach-at91/at91cap9.c
++++ b/arch/arm/mach-at91/at91cap9.c
+@@ -13,12 +13,14 @@
+ */
+
+ #include <linux/module.h>
++#include <linux/pm.h>
+
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+ #include <asm/arch/at91cap9.h>
+ #include <asm/arch/at91_pmc.h>
+ #include <asm/arch/at91_rstc.h>
++#include <asm/arch/at91_shdwc.h>
+
+ #include "generic.h"
+ #include "clock.h"
+@@ -288,6 +290,12 @@ static void at91cap9_reset(void)
+ at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
+ }
+
++static void at91cap9_poweroff(void)
++{
++ at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
++}
++
++
+ /* --------------------------------------------------------------------
+ * AT91CAP9 processor initialization
+ * -------------------------------------------------------------------- */
+@@ -298,6 +306,7 @@ void __init at91cap9_initialize(unsigned long main_clock)
+ iotable_init(at91cap9_io_desc, ARRAY_SIZE(at91cap9_io_desc));
+
+ at91_arch_reset = at91cap9_reset;
++ pm_power_off = at91cap9_poweroff;
+ at91_extern_irq = (1 << AT91CAP9_ID_IRQ0) | (1 << AT91CAP9_ID_IRQ1);
+
+ /* Init clock subsystem */
+diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c
+index c50fad9..f1a80d7 100644
+--- a/arch/arm/mach-at91/at91cap9_devices.c
++++ b/arch/arm/mach-at91/at91cap9_devices.c
+@@ -16,15 +16,15 @@
+
+ #include <linux/dma-mapping.h>
+ #include <linux/platform_device.h>
+-#include <linux/mtd/physmap.h>
++#include <linux/i2c-gpio.h>
+
+ #include <video/atmel_lcdc.h>
+
+ #include <asm/arch/board.h>
+ #include <asm/arch/gpio.h>
+ #include <asm/arch/at91cap9.h>
+-#include <asm/arch/at91sam926x_mc.h>
+ #include <asm/arch/at91cap9_matrix.h>
++#include <asm/arch/at91sam9_smc.h>
+
+ #include "generic.h"
+
+@@ -283,10 +283,15 @@ static struct at91_nand_data nand_data;
+ #define NAND_BASE AT91_CHIPSELECT_3
+
+ static struct resource nand_resources[] = {
+- {
++ [0] = {
+ .start = NAND_BASE,
+ .end = NAND_BASE + SZ_256M - 1,
+ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = AT91_BASE_SYS + AT91_ECC,
++ .end = AT91_BASE_SYS + AT91_ECC + SZ_512 - 1,
++ .flags = IORESOURCE_MEM,
+ }
+ };
+
+@@ -344,6 +349,7 @@ void __init at91_add_device_nand(struct at91_nand_data *data)
+ void __init at91_add_device_nand(struct at91_nand_data *data) {}
+ #endif
+
++
+ /* --------------------------------------------------------------------
+ * TWI (i2c)
+ * -------------------------------------------------------------------- */
+@@ -532,13 +538,59 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
+
+
+ /* --------------------------------------------------------------------
++ * Timer/Counter block
++ * -------------------------------------------------------------------- */
++
++#ifdef CONFIG_ATMEL_TCLIB
++
++static struct resource tcb_resources[] = {
++ [0] = {
++ .start = AT91CAP9_BASE_TCB0,
++ .end = AT91CAP9_BASE_TCB0 + SZ_16K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = AT91CAP9_ID_TCB,
++ .end = AT91CAP9_ID_TCB,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device at91cap9_tcb_device = {
++ .name = "atmel_tcb",
++ .id = 0,
++ .resource = tcb_resources,
++ .num_resources = ARRAY_SIZE(tcb_resources),
++};
++
++static void __init at91_add_device_tc(void)
++{
++ /* this chip has one clock and irq for all three TC channels */
++ at91_clock_associate("tcb_clk", &at91cap9_tcb_device.dev, "t0_clk");
++ platform_device_register(&at91cap9_tcb_device);
++}
++#else
++static void __init at91_add_device_tc(void) { }
++#endif
++
++
++/* --------------------------------------------------------------------
+ * RTT
+ * -------------------------------------------------------------------- */
+
++static struct resource rtt_resources[] = {
++ {
++ .start = AT91_BASE_SYS + AT91_RTT,
++ .end = AT91_BASE_SYS + AT91_RTT + SZ_16 - 1,
++ .flags = IORESOURCE_MEM,
++ }
++};
++
+ static struct platform_device at91cap9_rtt_device = {
+ .name = "at91_rtt",
+- .id = -1,
+- .num_resources = 0,
++ .id = 0,
++ .resource = rtt_resources,
++ .num_resources = ARRAY_SIZE(rtt_resources),
+ };
+
+ static void __init at91_add_device_rtt(void)
+@@ -990,7 +1042,7 @@ static inline void configure_usart2_pins(unsigned pins)
+ at91_set_B_periph(AT91_PIN_PD6, 0); /* CTS2 */
+ }
+
+-static struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */
++static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */
+ struct platform_device *atmel_default_console_device; /* the serial console device */
+
+ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
+@@ -1031,8 +1083,6 @@ void __init at91_set_serial_console(unsigned portnr)
+ {
+ if (portnr < ATMEL_MAX_UART)
+ atmel_default_console_device = at91_uarts[portnr];
+- if (!atmel_default_console_device)
+- printk(KERN_INFO "AT91: No default serial console defined.\n");
+ }
+
+ void __init at91_add_device_serial(void)
+@@ -1043,6 +1093,9 @@ void __init at91_add_device_serial(void)
+ if (at91_uarts[i])
+ platform_device_register(at91_uarts[i]);
+ }
++
++ if (!atmel_default_console_device)
++ printk(KERN_INFO "AT91: No default serial console defined.\n");
+ }
+ #else
+ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
+@@ -1060,6 +1113,7 @@ static int __init at91_add_standard_devices(void)
+ {
+ at91_add_device_rtt();
+ at91_add_device_watchdog();
++ at91_add_device_tc();
+ return 0;
+ }
+
+diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
+index ef6aeb8..de19bee 100644
+--- a/arch/arm/mach-at91/at91rm9200_devices.c
++++ b/arch/arm/mach-at91/at91rm9200_devices.c
+@@ -577,6 +577,90 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
+
+
+ /* --------------------------------------------------------------------
++ * Timer/Counter blocks
++ * -------------------------------------------------------------------- */
++
++#ifdef CONFIG_ATMEL_TCLIB
++
++static struct resource tcb0_resources[] = {
++ [0] = {
++ .start = AT91RM9200_BASE_TCB0,
++ .end = AT91RM9200_BASE_TCB0 + SZ_16K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = AT91RM9200_ID_TC0,
++ .end = AT91RM9200_ID_TC0,
++ .flags = IORESOURCE_IRQ,
++ },
++ [2] = {
++ .start = AT91RM9200_ID_TC1,
++ .end = AT91RM9200_ID_TC1,
++ .flags = IORESOURCE_IRQ,
++ },
++ [3] = {
++ .start = AT91RM9200_ID_TC2,
++ .end = AT91RM9200_ID_TC2,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device at91rm9200_tcb0_device = {
++ .name = "atmel_tcb",
++ .id = 0,
++ .resource = tcb0_resources,
++ .num_resources = ARRAY_SIZE(tcb0_resources),
++};
++
++static struct resource tcb1_resources[] = {
++ [0] = {
++ .start = AT91RM9200_BASE_TCB1,
++ .end = AT91RM9200_BASE_TCB1 + SZ_16K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = AT91RM9200_ID_TC3,
++ .end = AT91RM9200_ID_TC3,
++ .flags = IORESOURCE_IRQ,
++ },
++ [2] = {
++ .start = AT91RM9200_ID_TC4,
++ .end = AT91RM9200_ID_TC4,
++ .flags = IORESOURCE_IRQ,
++ },
++ [3] = {
++ .start = AT91RM9200_ID_TC5,
++ .end = AT91RM9200_ID_TC5,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device at91rm9200_tcb1_device = {
++ .name = "atmel_tcb",
++ .id = 1,
++ .resource = tcb1_resources,
++ .num_resources = ARRAY_SIZE(tcb1_resources),
++};
++
++static void __init at91_add_device_tc(void)
++{
++ /* this chip has a separate clock and irq for each TC channel */
++ at91_clock_associate("tc0_clk", &at91rm9200_tcb0_device.dev, "t0_clk");
++ at91_clock_associate("tc1_clk", &at91rm9200_tcb0_device.dev, "t1_clk");
++ at91_clock_associate("tc2_clk", &at91rm9200_tcb0_device.dev, "t2_clk");
++ platform_device_register(&at91rm9200_tcb0_device);
++
++ at91_clock_associate("tc3_clk", &at91rm9200_tcb1_device.dev, "t0_clk");
++ at91_clock_associate("tc4_clk", &at91rm9200_tcb1_device.dev, "t1_clk");
++ at91_clock_associate("tc5_clk", &at91rm9200_tcb1_device.dev, "t2_clk");
++ platform_device_register(&at91rm9200_tcb1_device);
++}
++#else
++static void __init at91_add_device_tc(void) { }
++#endif
++
++
++/* --------------------------------------------------------------------
+ * RTC
+ * -------------------------------------------------------------------- */
+
+@@ -1019,7 +1103,7 @@ static inline void configure_usart3_pins(unsigned pins)
+ at91_set_B_periph(AT91_PIN_PB0, 0); /* RTS3 */
+ }
+
+-static struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */
++static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */
+ struct platform_device *atmel_default_console_device; /* the serial console device */
+
+ void __init __deprecated at91_init_serial(struct at91_uart_config *config)
+@@ -1110,8 +1194,6 @@ void __init at91_set_serial_console(unsigned portnr)
+ {
+ if (portnr < ATMEL_MAX_UART)
+ atmel_default_console_device = at91_uarts[portnr];
+- if (!atmel_default_console_device)
+- printk(KERN_INFO "AT91: No default serial console defined.\n");
+ }
+
+ void __init at91_add_device_serial(void)
+@@ -1122,6 +1204,9 @@ void __init at91_add_device_serial(void)
+ if (at91_uarts[i])
+ platform_device_register(at91_uarts[i]);
+ }
++
++ if (!atmel_default_console_device)
++ printk(KERN_INFO "AT91: No default serial console defined.\n");
+ }
+ #else
+ void __init __deprecated at91_init_serial(struct at91_uart_config *config) {}
+@@ -1141,6 +1226,7 @@ static int __init at91_add_standard_devices(void)
+ {
+ at91_add_device_rtc();
+ at91_add_device_watchdog();
++ at91_add_device_tc();
+ return 0;
+ }
+
+diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
+index 18d0661..ee26550 100644
+--- a/arch/arm/mach-at91/at91sam9260.c
++++ b/arch/arm/mach-at91/at91sam9260.c
+@@ -11,6 +11,7 @@
+ */
+
+ #include <linux/module.h>
++#include <linux/pm.h>
+
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+@@ -18,6 +19,7 @@
+ #include <asm/arch/at91sam9260.h>
+ #include <asm/arch/at91_pmc.h>
+ #include <asm/arch/at91_rstc.h>
++#include <asm/arch/at91_shdwc.h>
+
+ #include "generic.h"
+ #include "clock.h"
+@@ -267,6 +269,11 @@ static void at91sam9260_reset(void)
+ at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
+ }
+
++static void at91sam9260_poweroff(void)
++{
++ at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
++}
++
+
+ /* --------------------------------------------------------------------
+ * AT91SAM9260 processor initialization
+@@ -304,6 +311,7 @@ void __init at91sam9260_initialize(unsigned long main_clock)
+ iotable_init(at91sam9260_sram_desc, ARRAY_SIZE(at91sam9260_sram_desc));
+
+ at91_arch_reset = at91sam9260_reset;
++ pm_power_off = at91sam9260_poweroff;
+ at91_extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1)
+ | (1 << AT91SAM9260_ID_IRQ2);
+
+diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
+index 105f840..393a32a 100644
+--- a/arch/arm/mach-at91/at91sam9260_devices.c
++++ b/arch/arm/mach-at91/at91sam9260_devices.c
+@@ -19,8 +19,8 @@
+ #include <asm/arch/board.h>
+ #include <asm/arch/gpio.h>
+ #include <asm/arch/at91sam9260.h>
+-#include <asm/arch/at91sam926x_mc.h>
+ #include <asm/arch/at91sam9260_matrix.h>
++#include <asm/arch/at91sam9_smc.h>
+
+ #include "generic.h"
+
+@@ -288,10 +288,15 @@ static struct at91_nand_data nand_data;
+ #define NAND_BASE AT91_CHIPSELECT_3
+
+ static struct resource nand_resources[] = {
+- {
++ [0] = {
+ .start = NAND_BASE,
+ .end = NAND_BASE + SZ_256M - 1,
+ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = AT91_BASE_SYS + AT91_ECC,
++ .end = AT91_BASE_SYS + AT91_ECC + SZ_512 - 1,
++ .flags = IORESOURCE_MEM,
+ }
+ };
+
+@@ -540,6 +545,90 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
+
+
+ /* --------------------------------------------------------------------
++ * Timer/Counter blocks
++ * -------------------------------------------------------------------- */
++
++#ifdef CONFIG_ATMEL_TCLIB
++
++static struct resource tcb0_resources[] = {
++ [0] = {
++ .start = AT91SAM9260_BASE_TCB0,
++ .end = AT91SAM9260_BASE_TCB0 + SZ_16K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = AT91SAM9260_ID_TC0,
++ .end = AT91SAM9260_ID_TC0,
++ .flags = IORESOURCE_IRQ,
++ },
++ [2] = {
++ .start = AT91SAM9260_ID_TC1,
++ .end = AT91SAM9260_ID_TC1,
++ .flags = IORESOURCE_IRQ,
++ },
++ [3] = {
++ .start = AT91SAM9260_ID_TC2,
++ .end = AT91SAM9260_ID_TC2,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device at91sam9260_tcb0_device = {
++ .name = "atmel_tcb",
++ .id = 0,
++ .resource = tcb0_resources,
++ .num_resources = ARRAY_SIZE(tcb0_resources),
++};
++
++static struct resource tcb1_resources[] = {
++ [0] = {
++ .start = AT91SAM9260_BASE_TCB1,
++ .end = AT91SAM9260_BASE_TCB1 + SZ_16K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = AT91SAM9260_ID_TC3,
++ .end = AT91SAM9260_ID_TC3,
++ .flags = IORESOURCE_IRQ,
++ },
++ [2] = {
++ .start = AT91SAM9260_ID_TC4,
++ .end = AT91SAM9260_ID_TC4,
++ .flags = IORESOURCE_IRQ,
++ },
++ [3] = {
++ .start = AT91SAM9260_ID_TC5,
++ .end = AT91SAM9260_ID_TC5,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device at91sam9260_tcb1_device = {
++ .name = "atmel_tcb",
++ .id = 1,
++ .resource = tcb1_resources,
++ .num_resources = ARRAY_SIZE(tcb1_resources),
++};
++
++static void __init at91_add_device_tc(void)
++{
++ /* this chip has a separate clock and irq for each TC channel */
++ at91_clock_associate("tc0_clk", &at91sam9260_tcb0_device.dev, "t0_clk");
++ at91_clock_associate("tc1_clk", &at91sam9260_tcb0_device.dev, "t1_clk");
++ at91_clock_associate("tc2_clk", &at91sam9260_tcb0_device.dev, "t2_clk");
++ platform_device_register(&at91sam9260_tcb0_device);
++
++ at91_clock_associate("tc3_clk", &at91sam9260_tcb1_device.dev, "t0_clk");
++ at91_clock_associate("tc4_clk", &at91sam9260_tcb1_device.dev, "t1_clk");
++ at91_clock_associate("tc5_clk", &at91sam9260_tcb1_device.dev, "t2_clk");
++ platform_device_register(&at91sam9260_tcb1_device);
++}
++#else
++static void __init at91_add_device_tc(void) { }
++#endif
++
++
++/* --------------------------------------------------------------------
+ * RTT
+ * -------------------------------------------------------------------- */
+
+@@ -553,7 +642,7 @@ static struct resource rtt_resources[] = {
+
+ static struct platform_device at91sam9260_rtt_device = {
+ .name = "at91_rtt",
+- .id = -1,
++ .id = 0,
+ .resource = rtt_resources,
+ .num_resources = ARRAY_SIZE(rtt_resources),
+ };
+@@ -962,64 +1051,9 @@ static inline void configure_usart5_pins(void)
+ at91_set_A_periph(AT91_PIN_PB13, 0); /* RXD5 */
+ }
+
+-static struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */
++static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */
+ struct platform_device *atmel_default_console_device; /* the serial console device */
+
+-void __init __deprecated at91_init_serial(struct at91_uart_config *config)
+-{
+- int i;
+-
+- /* Fill in list of supported UARTs */
+- for (i = 0; i < config->nr_tty; i++) {
+- switch (config->tty_map[i]) {
+- case 0:
+- configure_usart0_pins(ATMEL_UART_CTS | ATMEL_UART_RTS | ATMEL_UART_DSR | ATMEL_UART_DTR | ATMEL_UART_DCD | ATMEL_UART_RI);
+- at91_uarts[i] = &at91sam9260_uart0_device;
+- at91_clock_associate("usart0_clk", &at91sam9260_uart0_device.dev, "usart");
+- break;
+- case 1:
+- configure_usart1_pins(ATMEL_UART_CTS | ATMEL_UART_RTS);
+- at91_uarts[i] = &at91sam9260_uart1_device;
+- at91_clock_associate("usart1_clk", &at91sam9260_uart1_device.dev, "usart");
+- break;
+- case 2:
+- configure_usart2_pins(0);
+- at91_uarts[i] = &at91sam9260_uart2_device;
+- at91_clock_associate("usart2_clk", &at91sam9260_uart2_device.dev, "usart");
+- break;
+- case 3:
+- configure_usart3_pins(0);
+- at91_uarts[i] = &at91sam9260_uart3_device;
+- at91_clock_associate("usart3_clk", &at91sam9260_uart3_device.dev, "usart");
+- break;
+- case 4:
+- configure_usart4_pins();
+- at91_uarts[i] = &at91sam9260_uart4_device;
+- at91_clock_associate("usart4_clk", &at91sam9260_uart4_device.dev, "usart");
+- break;
+- case 5:
+- configure_usart5_pins();
+- at91_uarts[i] = &at91sam9260_uart5_device;
+- at91_clock_associate("usart5_clk", &at91sam9260_uart5_device.dev, "usart");
+- break;
+- case 6:
+- configure_dbgu_pins();
+- at91_uarts[i] = &at91sam9260_dbgu_device;
+- at91_clock_associate("mck", &at91sam9260_dbgu_device.dev, "usart");
+- break;
+- default:
+- continue;
+- }
+- at91_uarts[i]->id = i; /* update ID number to mapped ID */
+- }
+-
+- /* Set serial console device */
+- if (config->console_tty < ATMEL_MAX_UART)
+- atmel_default_console_device = at91_uarts[config->console_tty];
+- if (!atmel_default_console_device)
+- printk(KERN_INFO "AT91: No default serial console defined.\n");
+-}
+-
+ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
+ {
+ struct platform_device *pdev;
+@@ -1073,8 +1107,6 @@ void __init at91_set_serial_console(unsigned portnr)
+ {
+ if (portnr < ATMEL_MAX_UART)
+ atmel_default_console_device = at91_uarts[portnr];
+- if (!atmel_default_console_device)
+- printk(KERN_INFO "AT91: No default serial console defined.\n");
+ }
+
+ void __init at91_add_device_serial(void)
+@@ -1085,9 +1117,11 @@ void __init at91_add_device_serial(void)
+ if (at91_uarts[i])
+ platform_device_register(at91_uarts[i]);
+ }
++
++ if (!atmel_default_console_device)
++ printk(KERN_INFO "AT91: No default serial console defined.\n");
+ }
+ #else
+-void __init __deprecated at91_init_serial(struct at91_uart_config *config) {}
+ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
+ void __init at91_set_serial_console(unsigned portnr) {}
+ void __init at91_add_device_serial(void) {}
+@@ -1103,6 +1137,7 @@ static int __init at91_add_standard_devices(void)
+ {
+ at91_add_device_rtt();
+ at91_add_device_watchdog();
++ at91_add_device_tc();
+ return 0;
+ }
+
+diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
+index 90b87e1..35bf6fd 100644
+--- a/arch/arm/mach-at91/at91sam9261.c
++++ b/arch/arm/mach-at91/at91sam9261.c
+@@ -11,12 +11,14 @@
+ */
+
+ #include <linux/module.h>
++#include <linux/pm.h>
+
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+ #include <asm/arch/at91sam9261.h>
+ #include <asm/arch/at91_pmc.h>
+ #include <asm/arch/at91_rstc.h>
++#include <asm/arch/at91_shdwc.h>
+
+ #include "generic.h"
+ #include "clock.h"
+@@ -245,6 +247,11 @@ static void at91sam9261_reset(void)
+ at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
+ }
+
++static void at91sam9261_poweroff(void)
++{
++ at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
++}
++
+
+ /* --------------------------------------------------------------------
+ * AT91SAM9261 processor initialization
+@@ -256,6 +263,7 @@ void __init at91sam9261_initialize(unsigned long main_clock)
+ iotable_init(at91sam9261_io_desc, ARRAY_SIZE(at91sam9261_io_desc));
+
+ at91_arch_reset = at91sam9261_reset;
++ pm_power_off = at91sam9261_poweroff;
+ at91_extern_irq = (1 << AT91SAM9261_ID_IRQ0) | (1 << AT91SAM9261_ID_IRQ1)
+ | (1 << AT91SAM9261_ID_IRQ2);
+
+diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
+index 2456412..37cd547 100644
+--- a/arch/arm/mach-at91/at91sam9261_devices.c
++++ b/arch/arm/mach-at91/at91sam9261_devices.c
+@@ -24,7 +24,7 @@
+ #include <asm/arch/gpio.h>
+ #include <asm/arch/at91sam9261.h>
+ #include <asm/arch/at91sam9261_matrix.h>
+-#include <asm/arch/at91sam926x_mc.h>
++#include <asm/arch/at91sam9_smc.h>
+
+ #include "generic.h"
+
+@@ -548,6 +548,55 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
+
+
+ /* --------------------------------------------------------------------
++ * Timer/Counter block
++ * -------------------------------------------------------------------- */
++
++#ifdef CONFIG_ATMEL_TCLIB
++
++static struct resource tcb_resources[] = {
++ [0] = {
++ .start = AT91SAM9261_BASE_TCB0,
++ .end = AT91SAM9261_BASE_TCB0 + SZ_16K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = AT91SAM9261_ID_TC0,
++ .end = AT91SAM9261_ID_TC0,
++ .flags = IORESOURCE_IRQ,
++ },
++ [2] = {
++ .start = AT91SAM9261_ID_TC1,
++ .end = AT91SAM9261_ID_TC1,
++ .flags = IORESOURCE_IRQ,
++ },
++ [3] = {
++ .start = AT91SAM9261_ID_TC2,
++ .end = AT91SAM9261_ID_TC2,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device at91sam9261_tcb_device = {
++ .name = "atmel_tcb",
++ .id = 0,
++ .resource = tcb_resources,
++ .num_resources = ARRAY_SIZE(tcb_resources),
++};
++
++static void __init at91_add_device_tc(void)
++{
++ /* this chip has a separate clock and irq for each TC channel */
++ at91_clock_associate("tc0_clk", &at91sam9261_tcb_device.dev, "t0_clk");
++ at91_clock_associate("tc1_clk", &at91sam9261_tcb_device.dev, "t1_clk");
++ at91_clock_associate("tc2_clk", &at91sam9261_tcb_device.dev, "t2_clk");
++ platform_device_register(&at91sam9261_tcb_device);
++}
++#else
++static void __init at91_add_device_tc(void) { }
++#endif
++
++
++/* --------------------------------------------------------------------
+ * RTT
+ * -------------------------------------------------------------------- */
+
+@@ -561,7 +610,7 @@ static struct resource rtt_resources[] = {
+
+ static struct platform_device at91sam9261_rtt_device = {
+ .name = "at91_rtt",
+- .id = -1,
++ .id = 0,
+ .resource = rtt_resources,
+ .num_resources = ARRAY_SIZE(rtt_resources),
+ };
+@@ -938,49 +987,9 @@ static inline void configure_usart2_pins(unsigned pins)
+ at91_set_B_periph(AT91_PIN_PA16, 0); /* CTS2 */
+ }
+
+-static struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */
++static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */
+ struct platform_device *atmel_default_console_device; /* the serial console device */
+
+-void __init __deprecated at91_init_serial(struct at91_uart_config *config)
+-{
+- int i;
+-
+- /* Fill in list of supported UARTs */
+- for (i = 0; i < config->nr_tty; i++) {
+- switch (config->tty_map[i]) {
+- case 0:
+- configure_usart0_pins(ATMEL_UART_CTS | ATMEL_UART_RTS);
+- at91_uarts[i] = &at91sam9261_uart0_device;
+- at91_clock_associate("usart0_clk", &at91sam9261_uart0_device.dev, "usart");
+- break;
+- case 1:
+- configure_usart1_pins(0);
+- at91_uarts[i] = &at91sam9261_uart1_device;
+- at91_clock_associate("usart1_clk", &at91sam9261_uart1_device.dev, "usart");
+- break;
+- case 2:
+- configure_usart2_pins(0);
+- at91_uarts[i] = &at91sam9261_uart2_device;
+- at91_clock_associate("usart2_clk", &at91sam9261_uart2_device.dev, "usart");
+- break;
+- case 3:
+- configure_dbgu_pins();
+- at91_uarts[i] = &at91sam9261_dbgu_device;
+- at91_clock_associate("mck", &at91sam9261_dbgu_device.dev, "usart");
+- break;
+- default:
+- continue;
+- }
+- at91_uarts[i]->id = i; /* update ID number to mapped ID */
+- }
+-
+- /* Set serial console device */
+- if (config->console_tty < ATMEL_MAX_UART)
+- atmel_default_console_device = at91_uarts[config->console_tty];
+- if (!atmel_default_console_device)
+- printk(KERN_INFO "AT91: No default serial console defined.\n");
+-}
+-
+ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
+ {
+ struct platform_device *pdev;
+@@ -1019,8 +1028,6 @@ void __init at91_set_serial_console(unsigned portnr)
+ {
+ if (portnr < ATMEL_MAX_UART)
+ atmel_default_console_device = at91_uarts[portnr];
+- if (!atmel_default_console_device)
+- printk(KERN_INFO "AT91: No default serial console defined.\n");
+ }
+
+ void __init at91_add_device_serial(void)
+@@ -1031,9 +1038,11 @@ void __init at91_add_device_serial(void)
+ if (at91_uarts[i])
+ platform_device_register(at91_uarts[i]);
+ }
++
++ if (!atmel_default_console_device)
++ printk(KERN_INFO "AT91: No default serial console defined.\n");
+ }
+ #else
+-void __init __deprecated at91_init_serial(struct at91_uart_config *config) {}
+ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
+ void __init at91_set_serial_console(unsigned portnr) {}
+ void __init at91_add_device_serial(void) {}
+@@ -1050,6 +1059,7 @@ static int __init at91_add_standard_devices(void)
+ {
+ at91_add_device_rtt();
+ at91_add_device_watchdog();
++ at91_add_device_tc();
+ return 0;
+ }
+
+diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
+index a53ba0f..052074a 100644
+--- a/arch/arm/mach-at91/at91sam9263.c
++++ b/arch/arm/mach-at91/at91sam9263.c
+@@ -11,12 +11,14 @@
+ */
+
+ #include <linux/module.h>
++#include <linux/pm.h>
+
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+ #include <asm/arch/at91sam9263.h>
+ #include <asm/arch/at91_pmc.h>
+ #include <asm/arch/at91_rstc.h>
++#include <asm/arch/at91_shdwc.h>
+
+ #include "generic.h"
+ #include "clock.h"
+@@ -271,6 +273,11 @@ static void at91sam9263_reset(void)
+ at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
+ }
+
++static void at91sam9263_poweroff(void)
++{
++ at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
++}
++
+
+ /* --------------------------------------------------------------------
+ * AT91SAM9263 processor initialization
+@@ -282,6 +289,7 @@ void __init at91sam9263_initialize(unsigned long main_clock)
+ iotable_init(at91sam9263_io_desc, ARRAY_SIZE(at91sam9263_io_desc));
+
+ at91_arch_reset = at91sam9263_reset;
++ pm_power_off = at91sam9263_poweroff;
+ at91_extern_irq = (1 << AT91SAM9263_ID_IRQ0) | (1 << AT91SAM9263_ID_IRQ1);
+
+ /* Init clock subsystem */
+diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
+index 0b12e1a..b6454c5 100644
+--- a/arch/arm/mach-at91/at91sam9263_devices.c
++++ b/arch/arm/mach-at91/at91sam9263_devices.c
+@@ -22,8 +22,8 @@
+ #include <asm/arch/board.h>
+ #include <asm/arch/gpio.h>
+ #include <asm/arch/at91sam9263.h>
+-#include <asm/arch/at91sam926x_mc.h>
+ #include <asm/arch/at91sam9263_matrix.h>
++#include <asm/arch/at91sam9_smc.h>
+
+ #include "generic.h"
+
+@@ -358,10 +358,15 @@ static struct at91_nand_data nand_data;
+ #define NAND_BASE AT91_CHIPSELECT_3
+
+ static struct resource nand_resources[] = {
+- {
++ [0] = {
+ .start = NAND_BASE,
+ .end = NAND_BASE + SZ_256M - 1,
+ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = AT91_BASE_SYS + AT91_ECC0,
++ .end = AT91_BASE_SYS + AT91_ECC0 + SZ_512 - 1,
++ .flags = IORESOURCE_MEM,
+ }
+ };
+
+@@ -783,6 +788,43 @@ void __init at91_add_device_isi(void) {}
+
+
+ /* --------------------------------------------------------------------
++ * Timer/Counter block
++ * -------------------------------------------------------------------- */
++
++#ifdef CONFIG_ATMEL_TCLIB
++
++static struct resource tcb_resources[] = {
++ [0] = {
++ .start = AT91SAM9263_BASE_TCB0,
++ .end = AT91SAM9263_BASE_TCB0 + SZ_16K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = AT91SAM9263_ID_TCB,
++ .end = AT91SAM9263_ID_TCB,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device at91sam9263_tcb_device = {
++ .name = "atmel_tcb",
++ .id = 0,
++ .resource = tcb_resources,
++ .num_resources = ARRAY_SIZE(tcb_resources),
++};
++
++static void __init at91_add_device_tc(void)
++{
++ /* this chip has one clock and irq for all three TC channels */
++ at91_clock_associate("tcb_clk", &at91sam9263_tcb_device.dev, "t0_clk");
++ platform_device_register(&at91sam9263_tcb_device);
++}
++#else
++static void __init at91_add_device_tc(void) { }
++#endif
++
++
++/* --------------------------------------------------------------------
+ * RTT
+ * -------------------------------------------------------------------- */
+
+@@ -933,9 +975,6 @@ static inline void configure_ssc1_pins(unsigned pins)
+ }
+
+ /*
+- * Return the device node so that board init code can use it as the
+- * parent for the device node reflecting how it's used on this board.
+- *
+ * SSC controllers are accessed through library code, instead of any
+ * kind of all-singing/all-dancing driver. For example one could be
+ * used by a particular I2S audio codec's driver, while another one
+@@ -1146,49 +1185,9 @@ static inline void configure_usart2_pins(unsigned pins)
+ at91_set_B_periph(AT91_PIN_PD6, 0); /* CTS2 */
+ }
+
+-static struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */
++static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */
+ struct platform_device *atmel_default_console_device; /* the serial console device */
+
+-void __init __deprecated at91_init_serial(struct at91_uart_config *config)
+-{
+- int i;
+-
+- /* Fill in list of supported UARTs */
+- for (i = 0; i < config->nr_tty; i++) {
+- switch (config->tty_map[i]) {
+- case 0:
+- configure_usart0_pins(ATMEL_UART_CTS | ATMEL_UART_RTS);
+- at91_uarts[i] = &at91sam9263_uart0_device;
+- at91_clock_associate("usart0_clk", &at91sam9263_uart0_device.dev, "usart");
+- break;
+- case 1:
+- configure_usart1_pins(ATMEL_UART_CTS | ATMEL_UART_RTS);
+- at91_uarts[i] = &at91sam9263_uart1_device;
+- at91_clock_associate("usart1_clk", &at91sam9263_uart1_device.dev, "usart");
+- break;
+- case 2:
+- configure_usart2_pins(ATMEL_UART_CTS | ATMEL_UART_RTS);
+- at91_uarts[i] = &at91sam9263_uart2_device;
+- at91_clock_associate("usart2_clk", &at91sam9263_uart2_device.dev, "usart");
+- break;
+- case 3:
+- configure_dbgu_pins();
+- at91_uarts[i] = &at91sam9263_dbgu_device;
+- at91_clock_associate("mck", &at91sam9263_dbgu_device.dev, "usart");
+- break;
+- default:
+- continue;
+- }
+- at91_uarts[i]->id = i; /* update ID number to mapped ID */
+- }
+-
+- /* Set serial console device */
+- if (config->console_tty < ATMEL_MAX_UART)
+- atmel_default_console_device = at91_uarts[config->console_tty];
+- if (!atmel_default_console_device)
+- printk(KERN_INFO "AT91: No default serial console defined.\n");
+-}
+-
+ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
+ {
+ struct platform_device *pdev;
+@@ -1227,8 +1226,6 @@ void __init at91_set_serial_console(unsigned portnr)
+ {
+ if (portnr < ATMEL_MAX_UART)
+ atmel_default_console_device = at91_uarts[portnr];
+- if (!atmel_default_console_device)
+- printk(KERN_INFO "AT91: No default serial console defined.\n");
+ }
+
+ void __init at91_add_device_serial(void)
+@@ -1239,9 +1236,11 @@ void __init at91_add_device_serial(void)
+ if (at91_uarts[i])
+ platform_device_register(at91_uarts[i]);
+ }
++
++ if (!atmel_default_console_device)
++ printk(KERN_INFO "AT91: No default serial console defined.\n");
+ }
+ #else
+-void __init at91_init_serial(struct at91_uart_config *config) {}
+ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
+ void __init at91_set_serial_console(unsigned portnr) {}
+ void __init at91_add_device_serial(void) {}
+@@ -1257,6 +1256,7 @@ static int __init at91_add_standard_devices(void)
+ {
+ at91_add_device_rtt();
+ at91_add_device_watchdog();
++ at91_add_device_tc();
+ return 0;
+ }
+
+diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c
+index e38d237..5cecbd7 100644
+--- a/arch/arm/mach-at91/at91sam926x_time.c
++++ b/arch/arm/mach-at91/at91sam926x_time.c
+@@ -1,23 +1,20 @@
+ /*
+- * linux/arch/arm/mach-at91/at91sam926x_time.c
++ * at91sam926x_time.c - Periodic Interval Timer (PIT) for at91sam926x
+ *
+ * Copyright (C) 2005-2006 M. Amine SAYA, ATMEL Rousset, France
+ * Revision 2005 M. Nicolas Diremdjian, ATMEL Rousset, France
++ * Converted to ClockSource/ClockEvents by David Brownell.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+-
+-#include <linux/init.h>
+ #include <linux/interrupt.h>
+ #include <linux/irq.h>
+ #include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/time.h>
++#include <linux/clk.h>
++#include <linux/clockchips.h>
+
+-#include <asm/hardware.h>
+-#include <asm/io.h>
+ #include <asm/mach/time.h>
+
+ #include <asm/arch/at91_pit.h>
+@@ -26,85 +23,167 @@
+ #define PIT_CPIV(x) ((x) & AT91_PIT_CPIV)
+ #define PIT_PICNT(x) (((x) & AT91_PIT_PICNT) >> 20)
+
++static u32 pit_cycle; /* write-once */
++static u32 pit_cnt; /* access only w/system irq blocked */
++
++
+ /*
+- * Returns number of microseconds since last timer interrupt. Note that interrupts
+- * will have been disabled by do_gettimeofday()
+- * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy.
++ * Clocksource: just a monotonic counter of MCK/16 cycles.
++ * We don't care whether or not PIT irqs are enabled.
+ */
+-static unsigned long at91sam926x_gettimeoffset(void)
++static cycle_t read_pit_clk(void)
+ {
+- unsigned long elapsed;
+- unsigned long t = at91_sys_read(AT91_PIT_PIIR);
++ unsigned long flags;
++ u32 elapsed;
++ u32 t;
++
++ raw_local_irq_save(flags);
++ elapsed = pit_cnt;
++ t = at91_sys_read(AT91_PIT_PIIR);
++ raw_local_irq_restore(flags);
++
++ elapsed += PIT_PICNT(t) * pit_cycle;
++ elapsed += PIT_CPIV(t);
++ return elapsed;
++}
++
++static struct clocksource pit_clk = {
++ .name = "pit",
++ .rating = 175,
++ .read = read_pit_clk,
++ .shift = 20,
++ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
++};
+
+- elapsed = (PIT_PICNT(t) * LATCH) + PIT_CPIV(t); /* hardware clock cycles */
+
+- return (unsigned long)(elapsed * jiffies_to_usecs(1)) / LATCH;
++/*
++ * Clockevent device: interrupts every 1/HZ (== pit_cycles * MCK/16)
++ */
++static void
++pit_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
++{
++ unsigned long flags;
++
++ switch (mode) {
++ case CLOCK_EVT_MODE_PERIODIC:
++ /* update clocksource counter, then enable the IRQ */
++ raw_local_irq_save(flags);
++ pit_cnt += pit_cycle * PIT_PICNT(at91_sys_read(AT91_PIT_PIVR));
++ at91_sys_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN
++ | AT91_PIT_PITIEN);
++ raw_local_irq_restore(flags);
++ break;
++ case CLOCK_EVT_MODE_ONESHOT:
++ BUG();
++ /* FALLTHROUGH */
++ case CLOCK_EVT_MODE_SHUTDOWN:
++ case CLOCK_EVT_MODE_UNUSED:
++ /* disable irq, leaving the clocksource active */
++ at91_sys_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN);
++ break;
++ case CLOCK_EVT_MODE_RESUME:
++ break;
++ }
+ }
+
++static struct clock_event_device pit_clkevt = {
++ .name = "pit",
++ .features = CLOCK_EVT_FEAT_PERIODIC,
++ .shift = 32,
++ .rating = 100,
++ .cpumask = CPU_MASK_CPU0,
++ .set_mode = pit_clkevt_mode,
++};
++
++
+ /*
+ * IRQ handler for the timer.
+ */
+-static irqreturn_t at91sam926x_timer_interrupt(int irq, void *dev_id)
++static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id)
+ {
+- volatile long nr_ticks;
+
+- if (at91_sys_read(AT91_PIT_SR) & AT91_PIT_PITS) { /* This is a shared interrupt */
+- /* Get number to ticks performed before interrupt and clear PIT interrupt */
++ /* The PIT interrupt may be disabled, and is shared */
++ if ((pit_clkevt.mode == CLOCK_EVT_MODE_PERIODIC)
++ && (at91_sys_read(AT91_PIT_SR) & AT91_PIT_PITS)) {
++ unsigned nr_ticks;
++
++ /* Get number of ticks performed before irq, and ack it */
+ nr_ticks = PIT_PICNT(at91_sys_read(AT91_PIT_PIVR));
+ do {
+- timer_tick();
++ pit_cnt += pit_cycle;
++ pit_clkevt.event_handler(&pit_clkevt);
+ nr_ticks--;
+ } while (nr_ticks);
+
+ return IRQ_HANDLED;
+- } else
+- return IRQ_NONE; /* not handled */
++ }
++
++ return IRQ_NONE;
+ }
+
+-static struct irqaction at91sam926x_timer_irq = {
++static struct irqaction at91sam926x_pit_irq = {
+ .name = "at91_tick",
+ .flags = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+- .handler = at91sam926x_timer_interrupt
++ .handler = at91sam926x_pit_interrupt
+ };
+
+-void at91sam926x_timer_reset(void)
++static void at91sam926x_pit_reset(void)
+ {
+- /* Disable timer */
++ /* Disable timer and irqs */
+ at91_sys_write(AT91_PIT_MR, 0);
+
+- /* Clear any pending interrupts */
+- (void) at91_sys_read(AT91_PIT_PIVR);
++ /* Clear any pending interrupts, wait for PIT to stop counting */
++ while (PIT_CPIV(at91_sys_read(AT91_PIT_PIVR)) != 0)
++ cpu_relax();
+
+- /* Set Period Interval timer and enable its interrupt */
+- at91_sys_write(AT91_PIT_MR, (LATCH & AT91_PIT_PIV) | AT91_PIT_PITIEN | AT91_PIT_PITEN);
++ /* Start PIT but don't enable IRQ */
++ at91_sys_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN);
+ }
+
+ /*
+- * Set up timer interrupt.
++ * Set up both clocksource and clockevent support.
+ */
+-void __init at91sam926x_timer_init(void)
++static void __init at91sam926x_pit_init(void)
+ {
+- /* Initialize and enable the timer */
+- at91sam926x_timer_reset();
++ unsigned long pit_rate;
++ unsigned bits;
++
++ /*
++ * Use our actual MCK to figure out how many MCK/16 ticks per
++ * 1/HZ period (instead of a compile-time constant LATCH).
++ */
++ pit_rate = clk_get_rate(clk_get(NULL, "mck")) / 16;
++ pit_cycle = (pit_rate + HZ/2) / HZ;
++ WARN_ON(((pit_cycle - 1) & ~AT91_PIT_PIV) != 0);
+
+- /* Make IRQs happen for the system timer. */
+- setup_irq(AT91_ID_SYS, &at91sam926x_timer_irq);
++ /* Initialize and enable the timer */
++ at91sam926x_pit_reset();
++
++ /*
++ * Register clocksource. The high order bits of PIV are unused,
++ * so this isn't a 32-bit counter unless we get clockevent irqs.
++ */
++ pit_clk.mult = clocksource_hz2mult(pit_rate, pit_clk.shift);
++ bits = 12 /* PICNT */ + ilog2(pit_cycle) /* PIV */;
++ pit_clk.mask = CLOCKSOURCE_MASK(bits);
++ clocksource_register(&pit_clk);
++
++ /* Set up irq handler */
++ setup_irq(AT91_ID_SYS, &at91sam926x_pit_irq);
++
++ /* Set up and register clockevents */
++ pit_clkevt.mult = div_sc(pit_rate, NSEC_PER_SEC, pit_clkevt.shift);
++ clockevents_register_device(&pit_clkevt);
+ }
+
+-#ifdef CONFIG_PM
+-static void at91sam926x_timer_suspend(void)
++static void at91sam926x_pit_suspend(void)
+ {
+ /* Disable timer */
+ at91_sys_write(AT91_PIT_MR, 0);
+ }
+-#else
+-#define at91sam926x_timer_suspend NULL
+-#endif
+
+ struct sys_timer at91sam926x_timer = {
+- .init = at91sam926x_timer_init,
+- .offset = at91sam926x_gettimeoffset,
+- .suspend = at91sam926x_timer_suspend,
+- .resume = at91sam926x_timer_reset,
++ .init = at91sam926x_pit_init,
++ .suspend = at91sam926x_pit_suspend,
++ .resume = at91sam926x_pit_reset,
+ };
+-
+diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
+index 4813a35..902c798 100644
+--- a/arch/arm/mach-at91/at91sam9rl.c
++++ b/arch/arm/mach-at91/at91sam9rl.c
+@@ -10,6 +10,7 @@
+ */
+
+ #include <linux/module.h>
++#include <linux/pm.h>
+
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+@@ -17,6 +18,7 @@
+ #include <asm/arch/at91sam9rl.h>
+ #include <asm/arch/at91_pmc.h>
+ #include <asm/arch/at91_rstc.h>
++#include <asm/arch/at91_shdwc.h>
+
+ #include "generic.h"
+ #include "clock.h"
+@@ -244,6 +246,11 @@ static void at91sam9rl_reset(void)
+ at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
+ }
+
++static void at91sam9rl_poweroff(void)
++{
++ at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
++}
++
+
+ /* --------------------------------------------------------------------
+ * AT91SAM9RL processor initialization
+@@ -274,6 +281,7 @@ void __init at91sam9rl_initialize(unsigned long main_clock)
+ iotable_init(at91sam9rl_sram_desc, ARRAY_SIZE(at91sam9rl_sram_desc));
+
+ at91_arch_reset = at91sam9rl_reset;
++ pm_power_off = at91sam9rl_poweroff;
+ at91_extern_irq = (1 << AT91SAM9RL_ID_IRQ0);
+
+ /* Init clock subsystem */
+diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
+index f43b5c3..dbb9a5f 100644
+--- a/arch/arm/mach-at91/at91sam9rl_devices.c
++++ b/arch/arm/mach-at91/at91sam9rl_devices.c
+@@ -20,7 +20,7 @@
+ #include <asm/arch/gpio.h>
+ #include <asm/arch/at91sam9rl.h>
+ #include <asm/arch/at91sam9rl_matrix.h>
+-#include <asm/arch/at91sam926x_mc.h>
++#include <asm/arch/at91sam9_smc.h>
+
+ #include "generic.h"
+
+@@ -105,10 +105,15 @@ static struct at91_nand_data nand_data;
+ #define NAND_BASE AT91_CHIPSELECT_3
+
+ static struct resource nand_resources[] = {
+- {
++ [0] = {
+ .start = NAND_BASE,
+ .end = NAND_BASE + SZ_256M - 1,
+ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = AT91_BASE_SYS + AT91_ECC,
++ .end = AT91_BASE_SYS + AT91_ECC + SZ_512 - 1,
++ .flags = IORESOURCE_MEM,
+ }
+ };
+
+@@ -385,6 +390,55 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
+
+
+ /* --------------------------------------------------------------------
++ * Timer/Counter block
++ * -------------------------------------------------------------------- */
++
++#ifdef CONFIG_ATMEL_TCLIB
++
++static struct resource tcb_resources[] = {
++ [0] = {
++ .start = AT91SAM9RL_BASE_TCB0,
++ .end = AT91SAM9RL_BASE_TCB0 + SZ_16K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = AT91SAM9RL_ID_TC0,
++ .end = AT91SAM9RL_ID_TC0,
++ .flags = IORESOURCE_IRQ,
++ },
++ [2] = {
++ .start = AT91SAM9RL_ID_TC1,
++ .end = AT91SAM9RL_ID_TC1,
++ .flags = IORESOURCE_IRQ,
++ },
++ [3] = {
++ .start = AT91SAM9RL_ID_TC2,
++ .end = AT91SAM9RL_ID_TC2,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device at91sam9rl_tcb_device = {
++ .name = "atmel_tcb",
++ .id = 0,
++ .resource = tcb_resources,
++ .num_resources = ARRAY_SIZE(tcb_resources),
++};
++
++static void __init at91_add_device_tc(void)
++{
++ /* this chip has a separate clock and irq for each TC channel */
++ at91_clock_associate("tc0_clk", &at91sam9rl_tcb_device.dev, "t0_clk");
++ at91_clock_associate("tc1_clk", &at91sam9rl_tcb_device.dev, "t1_clk");
++ at91_clock_associate("tc2_clk", &at91sam9rl_tcb_device.dev, "t2_clk");
++ platform_device_register(&at91sam9rl_tcb_device);
++}
++#else
++static void __init at91_add_device_tc(void) { }
++#endif
++
++
++/* --------------------------------------------------------------------
+ * RTC
+ * -------------------------------------------------------------------- */
+
+@@ -418,7 +472,7 @@ static struct resource rtt_resources[] = {
+
+ static struct platform_device at91sam9rl_rtt_device = {
+ .name = "at91_rtt",
+- .id = -1,
++ .id = 0,
+ .resource = rtt_resources,
+ .num_resources = ARRAY_SIZE(rtt_resources),
+ };
+@@ -539,9 +593,6 @@ static inline void configure_ssc1_pins(unsigned pins)
+ }
+
+ /*
+- * Return the device node so that board init code can use it as the
+- * parent for the device node reflecting how it's used on this board.
+- *
+ * SSC controllers are accessed through library code, instead of any
+ * kind of all-singing/all-dancing driver. For example one could be
+ * used by a particular I2S audio codec's driver, while another one
+@@ -802,54 +853,9 @@ static inline void configure_usart3_pins(unsigned pins)
+ at91_set_B_periph(AT91_PIN_PD3, 0); /* CTS3 */
+ }
+
+-static struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */
++static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */
+ struct platform_device *atmel_default_console_device; /* the serial console device */
+
+-void __init __deprecated at91_init_serial(struct at91_uart_config *config)
+-{
+- int i;
+-
+- /* Fill in list of supported UARTs */
+- for (i = 0; i < config->nr_tty; i++) {
+- switch (config->tty_map[i]) {
+- case 0:
+- configure_usart0_pins(ATMEL_UART_CTS | ATMEL_UART_RTS);
+- at91_uarts[i] = &at91sam9rl_uart0_device;
+- at91_clock_associate("usart0_clk", &at91sam9rl_uart0_device.dev, "usart");
+- break;
+- case 1:
+- configure_usart1_pins(0);
+- at91_uarts[i] = &at91sam9rl_uart1_device;
+- at91_clock_associate("usart1_clk", &at91sam9rl_uart1_device.dev, "usart");
+- break;
+- case 2:
+- configure_usart2_pins(0);
+- at91_uarts[i] = &at91sam9rl_uart2_device;
+- at91_clock_associate("usart2_clk", &at91sam9rl_uart2_device.dev, "usart");
+- break;
+- case 3:
+- configure_usart3_pins(0);
+- at91_uarts[i] = &at91sam9rl_uart3_device;
+- at91_clock_associate("usart3_clk", &at91sam9rl_uart3_device.dev, "usart");
+- break;
+- case 4:
+- configure_dbgu_pins();
+- at91_uarts[i] = &at91sam9rl_dbgu_device;
+- at91_clock_associate("mck", &at91sam9rl_dbgu_device.dev, "usart");
+- break;
+- default:
+- continue;
+- }
+- at91_uarts[i]->id = i; /* update ID number to mapped ID */
+- }
+-
+- /* Set serial console device */
+- if (config->console_tty < ATMEL_MAX_UART)
+- atmel_default_console_device = at91_uarts[config->console_tty];
+- if (!atmel_default_console_device)
+- printk(KERN_INFO "AT91: No default serial console defined.\n");
+-}
+-
+ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
+ {
+ struct platform_device *pdev;
+@@ -893,8 +899,6 @@ void __init at91_set_serial_console(unsigned portnr)
+ {
+ if (portnr < ATMEL_MAX_UART)
+ atmel_default_console_device = at91_uarts[portnr];
+- if (!atmel_default_console_device)
+- printk(KERN_INFO "AT91: No default serial console defined.\n");
+ }
+
+ void __init at91_add_device_serial(void)
+@@ -905,9 +909,11 @@ void __init at91_add_device_serial(void)
+ if (at91_uarts[i])
+ platform_device_register(at91_uarts[i]);
+ }
++
++ if (!atmel_default_console_device)
++ printk(KERN_INFO "AT91: No default serial console defined.\n");
+ }
+ #else
+-void __init __deprecated at91_init_serial(struct at91_uart_config *config) {}
+ void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
+ void __init at91_set_serial_console(unsigned portnr) {}
+ void __init at91_add_device_serial(void) {}
+@@ -925,6 +931,7 @@ static int __init at91_add_standard_devices(void)
+ at91_add_device_rtc();
+ at91_add_device_rtt();
+ at91_add_device_watchdog();
++ at91_add_device_tc();
+ return 0;
+ }
+
+diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c
+new file mode 100644
+index 0000000..b22a1a0
+--- /dev/null
++++ b/arch/arm/mach-at91/board-cam60.c
+@@ -0,0 +1,180 @@
++/*
++ * KwikByte CAM60 (KB9260)
++ *
++ * based on board-sam9260ek.c
++ * Copyright (C) 2005 SAN People
++ * Copyright (C) 2006 Atmel
++ *
++ * 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/types.h>
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/spi/spi.h>
++#include <linux/spi/flash.h>
++
++#include <asm/hardware.h>
++#include <asm/setup.h>
++#include <asm/mach-types.h>
++#include <asm/irq.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <asm/mach/irq.h>
++
++#include <asm/arch/board.h>
++#include <asm/arch/gpio.h>
++
++#include "generic.h"
++
++
++static void __init cam60_map_io(void)
++{
++ /* Initialize processor: 10 MHz crystal */
++ at91sam9260_initialize(10000000);
++
++ /* DGBU on ttyS0. (Rx & Tx only) */
++ at91_register_uart(0, 0, 0);
++
++ /* set serial console to ttyS0 (ie, DBGU) */
++ at91_set_serial_console(0);
++}
++
++static void __init cam60_init_irq(void)
++{
++ at91sam9260_init_interrupts(NULL);
++}
++
++
++/*
++ * USB Host
++ */
++static struct at91_usbh_data __initdata cam60_usbh_data = {
++ .ports = 1,
++};
++
++
++/*
++ * SPI devices.
++ */
++#if defined(CONFIG_MTD_DATAFLASH)
++static struct mtd_partition __initdata cam60_spi_partitions[] = {
++ {
++ .name = "BOOT1",
++ .offset = 0,
++ .size = 4 * 1056,
++ },
++ {
++ .name = "BOOT2",
++ .offset = MTDPART_OFS_NXTBLK,
++ .size = 256 * 1056,
++ },
++ {
++ .name = "kernel",
++ .offset = MTDPART_OFS_NXTBLK,
++ .size = 2222 * 1056,
++ },
++ {
++ .name = "file system",
++ .offset = MTDPART_OFS_NXTBLK,
++ .size = MTDPART_SIZ_FULL,
++ },
++};
++
++static struct flash_platform_data __initdata cam60_spi_flash_platform_data = {
++ .name = "spi_flash",
++ .parts = cam60_spi_partitions,
++ .nr_parts = ARRAY_SIZE(cam60_spi_partitions)
++};
++#endif
++
++static struct spi_board_info cam60_spi_devices[] = {
++#if defined(CONFIG_MTD_DATAFLASH)
++ { /* DataFlash chip */
++ .modalias = "mtd_dataflash",
++ .chip_select = 0,
++ .max_speed_hz = 15 * 1000 * 1000,
++ .bus_num = 0,
++ .platform_data = &cam60_spi_flash_platform_data
++ },
++#endif
++};
++
++
++/*
++ * MACB Ethernet device
++ */
++static struct __initdata at91_eth_data cam60_macb_data = {
++ .phy_irq_pin = AT91_PIN_PB5,
++ .is_rmii = 0,
++};
++
++
++/*
++ * NAND Flash
++ */
++static struct mtd_partition __initdata cam60_nand_partition[] = {
++ {
++ .name = "nand_fs",
++ .offset = 0,
++ .size = MTDPART_SIZ_FULL,
++ },
++};
++
++static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
++{
++ *num_partitions = ARRAY_SIZE(cam60_nand_partition);
++ return cam60_nand_partition;
++}
++
++static struct at91_nand_data __initdata cam60_nand_data = {
++ .ale = 21,
++ .cle = 22,
++ // .det_pin = ... not there
++ .rdy_pin = AT91_PIN_PA9,
++ .enable_pin = AT91_PIN_PA7,
++ .partition_info = nand_partitions,
++};
++
++
++static void __init cam60_board_init(void)
++{
++ /* Serial */
++ at91_add_device_serial();
++ /* SPI */
++ at91_add_device_spi(cam60_spi_devices, ARRAY_SIZE(cam60_spi_devices));
++ /* Ethernet */
++ at91_add_device_eth(&cam60_macb_data);
++ /* USB Host */
++ /* enable USB power supply circuit */
++ at91_set_gpio_output(AT91_PIN_PB18, 1);
++ at91_add_device_usbh(&cam60_usbh_data);
++ /* NAND */
++ at91_add_device_nand(&cam60_nand_data);
++}
++
++MACHINE_START(CAM60, "KwikByte CAM60")
++ /* Maintainer: KwikByte */
++ .phys_io = AT91_BASE_SYS,
++ .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
++ .boot_params = AT91_SDRAM_BASE + 0x100,
++ .timer = &at91sam926x_timer,
++ .map_io = cam60_map_io,
++ .init_irq = cam60_init_irq,
++ .init_machine = cam60_board_init,
++MACHINE_END
+diff --git a/arch/arm/mach-at91/board-cap9adk.c b/arch/arm/mach-at91/board-cap9adk.c
+index 1854371..e5512d1 100644
+--- a/arch/arm/mach-at91/board-cap9adk.c
++++ b/arch/arm/mach-at91/board-cap9adk.c
+@@ -45,7 +45,7 @@
+ #include <asm/arch/board.h>
+ #include <asm/arch/gpio.h>
+ #include <asm/arch/at91cap9_matrix.h>
+-#include <asm/arch/at91sam926x_mc.h>
++#include <asm/arch/at91sam9_smc.h>
+
+ #include "generic.h"
+
+diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
+index 0e2a11f..26fea4d 100644
+--- a/arch/arm/mach-at91/board-csb337.c
++++ b/arch/arm/mach-at91/board-csb337.c
+@@ -43,17 +43,6 @@
+ #include "generic.h"
+
+
+-/*
+- * Serial port configuration.
+- * 0 .. 3 = USART0 .. USART3
+- * 4 = DBGU
+- */
+-static struct at91_uart_config __initdata csb337_uart_config = {
+- .console_tty = 0, /* ttyS0 */
+- .nr_tty = 2,
+- .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */
+-};
+-
+ static void __init csb337_map_io(void)
+ {
+ /* Initialize processor: 3.6864 MHz crystal */
+@@ -62,8 +51,11 @@ static void __init csb337_map_io(void)
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
+
+- /* Setup the serial ports and console */
+- at91_init_serial(&csb337_uart_config);
++ /* DBGU on ttyS0 */
++ at91_register_uart(0, 0, 0);
++
++ /* make console=ttyS0 the default */
++ at91_set_serial_console(0);
+ }
+
+ static void __init csb337_init_irq(void)
+diff --git a/arch/arm/mach-at91/board-csb637.c b/arch/arm/mach-at91/board-csb637.c
+index c5c721d..419fd19 100644
+--- a/arch/arm/mach-at91/board-csb637.c
++++ b/arch/arm/mach-at91/board-csb637.c
+@@ -40,27 +40,16 @@
+ #include "generic.h"
+
+
+-/*
+- * Serial port configuration.
+- * 0 .. 3 = USART0 .. USART3
+- * 4 = DBGU
+- */
+-static struct at91_uart_config __initdata csb637_uart_config = {
+- .console_tty = 0, /* ttyS0 */
+- .nr_tty = 2,
+- .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */
+-};
+-
+ static void __init csb637_map_io(void)
+ {
+ /* Initialize processor: 3.6864 MHz crystal */
+ at91rm9200_initialize(3686400, AT91RM9200_BGA);
+
+- /* Setup the LEDs */
+- at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
++ /* DBGU on ttyS0 */
++ at91_register_uart(0, 0, 0);
+
+- /* Setup the serial ports and console */
+- at91_init_serial(&csb637_uart_config);
++ /* make console=ttyS0 the default */
++ at91_set_serial_console(0);
+ }
+
+ static void __init csb637_init_irq(void)
+@@ -118,8 +107,19 @@ static struct platform_device csb_flash = {
+ .num_resources = ARRAY_SIZE(csb_flash_resources),
+ };
+
++static struct gpio_led csb_leds[] = {
++ { /* "d1", red */
++ .name = "d1",
++ .gpio = AT91_PIN_PB2,
++ .active_low = 1,
++ .default_trigger = "heartbeat",
++ },
++};
++
+ static void __init csb637_board_init(void)
+ {
++ /* LED(s) */
++ at91_gpio_leds(csb_leds, ARRAY_SIZE(csb_leds));
+ /* Serial */
+ at91_add_device_serial();
+ /* Ethernet */
+diff --git a/arch/arm/mach-at91/board-ecbat91.c b/arch/arm/mach-at91/board-ecbat91.c
+new file mode 100644
+index 0000000..e77fad4
+--- /dev/null
++++ b/arch/arm/mach-at91/board-ecbat91.c
+@@ -0,0 +1,178 @@
++/*
++ * linux/arch/arm/mach-at91rm9200/board-ecbat91.c
++ * Copyright (C) 2007 emQbit.com.
++ *
++ * We started from board-dk.c, which is Copyright (C) 2005 SAN People.
++ *
++ * 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/types.h>
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/spi/spi.h>
++#include <linux/spi/flash.h>
++
++#include <asm/hardware.h>
++#include <asm/setup.h>
++#include <asm/mach-types.h>
++#include <asm/irq.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <asm/mach/irq.h>
++
++#include <asm/arch/board.h>
++#include <asm/arch/gpio.h>
++
++#include "generic.h"
++
++
++static void __init ecb_at91map_io(void)
++{
++ /* Initialize processor: 18.432 MHz crystal */
++ at91rm9200_initialize(18432000, AT91RM9200_PQFP);
++
++ /* Setup the LEDs */
++ at91_init_leds(AT91_PIN_PC7, AT91_PIN_PC7);
++
++ /* DBGU on ttyS0. (Rx & Tx only) */
++ at91_register_uart(0, 0, 0);
++
++ /* USART0 on ttyS1. (Rx & Tx only) */
++ at91_register_uart(AT91RM9200_ID_US0, 1, 0);
++
++ /* set serial console to ttyS0 (ie, DBGU) */
++ at91_set_serial_console(0);
++}
++
++static void __init ecb_at91init_irq(void)
++{
++ at91rm9200_init_interrupts(NULL);
++}
++
++static struct at91_eth_data __initdata ecb_at91eth_data = {
++ .phy_irq_pin = AT91_PIN_PC4,
++ .is_rmii = 0,
++};
++
++static struct at91_usbh_data __initdata ecb_at91usbh_data = {
++ .ports = 1,
++};
++
++static struct at91_mmc_data __initdata ecb_at91mmc_data = {
++ .slot_b = 0,
++ .wire4 = 1,
++};
++
++
++#if defined(CONFIG_MTD_DATAFLASH)
++static struct mtd_partition __initdata my_flash0_partitions[] =
++{
++ { /* 0x8400 */
++ .name = "Darrell-loader",
++ .offset = 0,
++ .size = 12* 1056,
++ },
++ {
++ .name = "U-boot",
++ .offset = MTDPART_OFS_NXTBLK,
++ .size = 110 * 1056,
++ },
++ { /* 1336 (167 blocks) pages * 1056 bytes = 0x158700 bytes */
++ .name = "UBoot-env",
++ .offset = MTDPART_OFS_NXTBLK,
++ .size = 8 * 1056,
++ },
++ { /* 1336 (167 blocks) pages * 1056 bytes = 0x158700 bytes */
++ .name = "Kernel",
++ .offset = MTDPART_OFS_NXTBLK,
++ .size = 1534 * 1056,
++ },
++ { /* 190200 - jffs2 root filesystem */
++ .name = "Filesystem",
++ .offset = MTDPART_OFS_NXTBLK,
++ .size = MTDPART_SIZ_FULL, /* 26 sectors */
++ }
++};
++
++static struct flash_platform_data __initdata my_flash0_platform = {
++ .name = "Removable flash card",
++ .parts = my_flash0_partitions,
++ .nr_parts = ARRAY_SIZE(my_flash0_partitions)
++};
++
++#endif
++
++static struct spi_board_info __initdata ecb_at91spi_devices[] = {
++ { /* DataFlash chip */
++ .modalias = "mtd_dataflash",
++ .chip_select = 0,
++ .max_speed_hz = 10 * 1000 * 1000,
++ .bus_num = 0,
++#if defined(CONFIG_MTD_DATAFLASH)
++ .platform_data = &my_flash0_platform,
++#endif
++ },
++ { /* User accessable spi - cs1 (250KHz) */
++ .modalias = "spi-cs1",
++ .chip_select = 1,
++ .max_speed_hz = 250 * 1000,
++ },
++ { /* User accessable spi - cs2 (1MHz) */
++ .modalias = "spi-cs2",
++ .chip_select = 2,
++ .max_speed_hz = 1 * 1000 * 1000,
++ },
++ { /* User accessable spi - cs3 (10MHz) */
++ .modalias = "spi-cs3",
++ .chip_select = 3,
++ .max_speed_hz = 10 * 1000 * 1000,
++ },
++};
++
++static void __init ecb_at91board_init(void)
++{
++ /* Serial */
++ at91_add_device_serial();
++
++ /* Ethernet */
++ at91_add_device_eth(&ecb_at91eth_data);
++
++ /* USB Host */
++ at91_add_device_usbh(&ecb_at91usbh_data);
++
++ /* I2C */
++ at91_add_device_i2c(NULL, 0);
++
++ /* MMC */
++ at91_add_device_mmc(0, &ecb_at91mmc_data);
++
++ /* SPI */
++ at91_add_device_spi(ecb_at91spi_devices, ARRAY_SIZE(ecb_at91spi_devices));
++}
++
++MACHINE_START(ECBAT91, "emQbit's ECB_AT91")
++ /* Maintainer: emQbit.com */
++ .phys_io = AT91_BASE_SYS,
++ .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
++ .boot_params = AT91_SDRAM_BASE + 0x100,
++ .timer = &at91rm9200_timer,
++ .map_io = ecb_at91map_io,
++ .init_irq = ecb_at91init_irq,
++ .init_machine = ecb_at91board_init,
++MACHINE_END
+diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
+new file mode 100644
+index 0000000..8f76af5
+--- /dev/null
++++ b/arch/arm/mach-at91/board-sam9-l9260.c
+@@ -0,0 +1,199 @@
++/*
++ * linux/arch/arm/mach-at91/board-sam9-l9260.c
++ *
++ * Copyright (C) 2005 SAN People
++ * Copyright (C) 2006 Atmel
++ * Copyright (C) 2007 Olimex Ltd
++ *
++ * 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/types.h>
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/spi/spi.h>
++
++#include <asm/hardware.h>
++#include <asm/setup.h>
++#include <asm/mach-types.h>
++#include <asm/irq.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <asm/mach/irq.h>
++
++#include <asm/arch/board.h>
++#include <asm/arch/gpio.h>
++
++#include "generic.h"
++
++
++static void __init ek_map_io(void)
++{
++ /* Initialize processor: 18.432 MHz crystal */
++ at91sam9260_initialize(18432000);
++
++ /* Setup the LEDs */
++ at91_init_leds(AT91_PIN_PA9, AT91_PIN_PA6);
++
++ /* DBGU on ttyS0. (Rx & Tx only) */
++ at91_register_uart(0, 0, 0);
++
++ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
++ at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
++ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
++ | ATMEL_UART_RI);
++
++ /* USART1 on ttyS2. (Rx, Tx, CTS, RTS) */
++ at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
++
++ /* set serial console to ttyS0 (ie, DBGU) */
++ at91_set_serial_console(0);
++}
++
++static void __init ek_init_irq(void)
++{
++ at91sam9260_init_interrupts(NULL);
++}
++
++
++/*
++ * USB Host port
++ */
++static struct at91_usbh_data __initdata ek_usbh_data = {
++ .ports = 2,
++};
++
++/*
++ * USB Device port
++ */
++static struct at91_udc_data __initdata ek_udc_data = {
++ .vbus_pin = AT91_PIN_PC5,
++ .pullup_pin = 0, /* pull-up driven by UDC */
++};
++
++
++/*
++ * SPI devices.
++ */
++static struct spi_board_info ek_spi_devices[] = {
++#if !defined(CONFIG_MMC_AT91)
++ { /* DataFlash chip */
++ .modalias = "mtd_dataflash",
++ .chip_select = 1,
++ .max_speed_hz = 15 * 1000 * 1000,
++ .bus_num = 0,
++ },
++#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
++ { /* DataFlash card */
++ .modalias = "mtd_dataflash",
++ .chip_select = 0,
++ .max_speed_hz = 15 * 1000 * 1000,
++ .bus_num = 0,
++ },
++#endif
++#endif
++};
++
++
++/*
++ * MACB Ethernet device
++ */
++static struct at91_eth_data __initdata ek_macb_data = {
++ .phy_irq_pin = AT91_PIN_PA7,
++ .is_rmii = 0,
++};
++
++
++/*
++ * NAND flash
++ */
++static struct mtd_partition __initdata ek_nand_partition[] = {
++ {
++ .name = "Bootloader Area",
++ .offset = 0,
++ .size = 10 * 1024 * 1024,
++ },
++ {
++ .name = "User Area",
++ .offset = 10 * 1024 * 1024,
++ .size = MTDPART_SIZ_FULL,
++ },
++};
++
++static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
++{
++ *num_partitions = ARRAY_SIZE(ek_nand_partition);
++ return ek_nand_partition;
++}
++
++static struct at91_nand_data __initdata ek_nand_data = {
++ .ale = 21,
++ .cle = 22,
++// .det_pin = ... not connected
++ .rdy_pin = AT91_PIN_PC13,
++ .enable_pin = AT91_PIN_PC14,
++ .partition_info = nand_partitions,
++#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16)
++ .bus_width_16 = 1,
++#else
++ .bus_width_16 = 0,
++#endif
++};
++
++
++/*
++ * MCI (SD/MMC)
++ */
++static struct at91_mmc_data __initdata ek_mmc_data = {
++ .slot_b = 1,
++ .wire4 = 1,
++ .det_pin = AT91_PIN_PC8,
++ .wp_pin = AT91_PIN_PC4,
++// .vcc_pin = ... not connected
++};
++
++static void __init ek_board_init(void)
++{
++ /* Serial */
++ at91_add_device_serial();
++ /* USB Host */
++ at91_add_device_usbh(&ek_usbh_data);
++ /* USB Device */
++ at91_add_device_udc(&ek_udc_data);
++ /* SPI */
++ at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
++ /* NAND */
++ at91_add_device_nand(&ek_nand_data);
++ /* Ethernet */
++ at91_add_device_eth(&ek_macb_data);
++ /* MMC */
++ at91_add_device_mmc(0, &ek_mmc_data);
++ /* I2C */
++ at91_add_device_i2c(NULL, 0);
++}
++
++MACHINE_START(SAM9_L9260, "Olimex SAM9-L9260")
++ /* Maintainer: Olimex */
++ .phys_io = AT91_BASE_SYS,
++ .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
++ .boot_params = AT91_SDRAM_BASE + 0x100,
++ .timer = &at91sam926x_timer,
++ .map_io = ek_map_io,
++ .init_irq = ek_init_irq,
++ .init_machine = ek_board_init,
++MACHINE_END
+diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
+index b343a6c..4d1d9c7 100644
+--- a/arch/arm/mach-at91/board-sam9260ek.c
++++ b/arch/arm/mach-at91/board-sam9260ek.c
+@@ -25,6 +25,8 @@
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+ #include <linux/spi/spi.h>
++#include <linux/spi/at73c213.h>
++#include <linux/clk.h>
+
+ #include <asm/hardware.h>
+ #include <asm/setup.h>
+@@ -37,29 +39,28 @@
+
+ #include <asm/arch/board.h>
+ #include <asm/arch/gpio.h>
+-#include <asm/arch/at91sam926x_mc.h>
+
+ #include "generic.h"
+
+
+-/*
+- * Serial port configuration.
+- * 0 .. 5 = USART0 .. USART5
+- * 6 = DBGU
+- */
+-static struct at91_uart_config __initdata ek_uart_config = {
+- .console_tty = 0, /* ttyS0 */
+- .nr_tty = 3,
+- .tty_map = { 6, 0, 1, -1, -1, -1, -1 } /* ttyS0, ..., ttyS6 */
+-};
+-
+ static void __init ek_map_io(void)
+ {
+ /* Initialize processor: 18.432 MHz crystal */
+ at91sam9260_initialize(18432000);
+
+- /* Setup the serial ports and console */
+- at91_init_serial(&ek_uart_config);
++ /* DGBU on ttyS0. (Rx & Tx only) */
++ at91_register_uart(0, 0, 0);
++
++ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
++ at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
++ | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
++ | ATMEL_UART_RI);
++
++ /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
++ at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
++
++ /* set serial console to ttyS0 (ie, DBGU) */
++ at91_set_serial_console(0);
+ }
+
+ static void __init ek_init_irq(void)
+@@ -85,6 +86,35 @@ static struct at91_udc_data __initdata ek_udc_data = {
+
+
+ /*
++ * Audio
++ */
++static struct at73c213_board_info at73c213_data = {
++ .ssc_id = 0,
++ .shortname = "AT91SAM9260-EK external DAC",
++};
++
++#if defined(CONFIG_SND_AT73C213) || defined(CONFIG_SND_AT73C213_MODULE)
++static void __init at73c213_set_clk(struct at73c213_board_info *info)
++{
++ struct clk *pck0;
++ struct clk *plla;
++
++ pck0 = clk_get(NULL, "pck0");
++ plla = clk_get(NULL, "plla");
++
++ /* AT73C213 MCK Clock */
++ at91_set_B_periph(AT91_PIN_PC1, 0); /* PCK0 */
++
++ clk_set_parent(pck0, plla);
++ clk_put(plla);
++
++ info->dac_clk = pck0;
++}
++#else
++static void __init at73c213_set_clk(struct at73c213_board_info *info) {}
++#endif
++
++/*
+ * SPI devices.
+ */
+ static struct spi_board_info ek_spi_devices[] = {
+@@ -110,6 +140,8 @@ static struct spi_board_info ek_spi_devices[] = {
+ .chip_select = 0,
+ .max_speed_hz = 10 * 1000 * 1000,
+ .bus_num = 1,
++ .mode = SPI_MODE_1,
++ .platform_data = &at73c213_data,
+ },
+ #endif
+ };
+@@ -172,6 +204,24 @@ static struct at91_mmc_data __initdata ek_mmc_data = {
+ // .vcc_pin = ... not connected
+ };
+
++
++/*
++ * LEDs
++ */
++static struct gpio_led ek_leds[] = {
++ { /* "bottom" led, green, userled1 to be defined */
++ .name = "ds5",
++ .gpio = AT91_PIN_PA6,
++ .active_low = 1,
++ .default_trigger = "none",
++ },
++ { /* "power" led, yellow */
++ .name = "ds1",
++ .gpio = AT91_PIN_PA9,
++ .default_trigger = "heartbeat",
++ }
++};
++
+ static void __init ek_board_init(void)
+ {
+ /* Serial */
+@@ -190,6 +240,11 @@ static void __init ek_board_init(void)
+ at91_add_device_mmc(0, &ek_mmc_data);
+ /* I2C */
+ at91_add_device_i2c(NULL, 0);
++ /* SSC (to AT73C213) */
++ at73c213_set_clk(&at73c213_data);
++ at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX);
++ /* LEDs */
++ at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
+ }
+
+ MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
+diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
+index 0ce38df..08382c0 100644
+--- a/arch/arm/mach-at91/board-sam9261ek.c
++++ b/arch/arm/mach-at91/board-sam9261ek.c
+@@ -26,6 +26,8 @@
+ #include <linux/platform_device.h>
+ #include <linux/spi/spi.h>
+ #include <linux/spi/ads7846.h>
++#include <linux/spi/at73c213.h>
++#include <linux/clk.h>
+ #include <linux/dm9000.h>
+ #include <linux/fb.h>
+ #include <linux/gpio_keys.h>
+@@ -44,22 +46,11 @@
+
+ #include <asm/arch/board.h>
+ #include <asm/arch/gpio.h>
+-#include <asm/arch/at91sam926x_mc.h>
++#include <asm/arch/at91sam9_smc.h>
+
+ #include "generic.h"
+
+
+-/*
+- * Serial port configuration.
+- * 0 .. 2 = USART0 .. USART2
+- * 3 = DBGU
+- */
+-static struct at91_uart_config __initdata ek_uart_config = {
+- .console_tty = 0, /* ttyS0 */
+- .nr_tty = 1,
+- .tty_map = { 3, -1, -1, -1 } /* ttyS0, ..., ttyS3 */
+-};
+-
+ static void __init ek_map_io(void)
+ {
+ /* Initialize processor: 18.432 MHz crystal */
+@@ -68,8 +59,11 @@ static void __init ek_map_io(void)
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PA13, AT91_PIN_PA14);
+
+- /* Setup the serial ports and console */
+- at91_init_serial(&ek_uart_config);
++ /* DGBU on ttyS0. (Rx & Tx only) */
++ at91_register_uart(0, 0, 0);
++
++ /* set serial console to ttyS0 (ie, DBGU) */
++ at91_set_serial_console(0);
+ }
+
+ static void __init ek_init_irq(void)
+@@ -239,6 +233,35 @@ static void __init ek_add_device_ts(void) {}
+ #endif
+
+ /*
++ * Audio
++ */
++static struct at73c213_board_info at73c213_data = {
++ .ssc_id = 1,
++ .shortname = "AT91SAM9261-EK external DAC",
++};
++
++#if defined(CONFIG_SND_AT73C213) || defined(CONFIG_SND_AT73C213_MODULE)
++static void __init at73c213_set_clk(struct at73c213_board_info *info)
++{
++ struct clk *pck2;
++ struct clk *plla;
++
++ pck2 = clk_get(NULL, "pck2");
++ plla = clk_get(NULL, "plla");
++
++ /* AT73C213 MCK Clock */
++ at91_set_B_periph(AT91_PIN_PB31, 0); /* PCK2 */
++
++ clk_set_parent(pck2, plla);
++ clk_put(plla);
++
++ info->dac_clk = pck2;
++}
++#else
++static void __init at73c213_set_clk(struct at73c213_board_info *info) {}
++#endif
++
++/*
+ * SPI devices
+ */
+ static struct spi_board_info ek_spi_devices[] = {
+@@ -256,6 +279,7 @@ static struct spi_board_info ek_spi_devices[] = {
+ .bus_num = 0,
+ .platform_data = &ads_info,
+ .irq = AT91SAM9261_ID_IRQ0,
++ .controller_data = (void *) AT91_PIN_PA28, /* CS pin */
+ },
+ #endif
+ #if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
+@@ -271,6 +295,9 @@ static struct spi_board_info ek_spi_devices[] = {
+ .chip_select = 3,
+ .max_speed_hz = 10 * 1000 * 1000,
+ .bus_num = 0,
++ .mode = SPI_MODE_1,
++ .platform_data = &at73c213_data,
++ .controller_data = (void*) AT91_PIN_PA29, /* default for CS3 is PA6, but it must be PA29 */
+ },
+ #endif
+ };
+@@ -460,6 +487,29 @@ static void __init ek_add_device_buttons(void)
+ static void __init ek_add_device_buttons(void) {}
+ #endif
+
++/*
++ * LEDs
++ */
++static struct gpio_led ek_leds[] = {
++ { /* "bottom" led, green, userled1 to be defined */
++ .name = "ds7",
++ .gpio = AT91_PIN_PA14,
++ .active_low = 1,
++ .default_trigger = "none",
++ },
++ { /* "top" led, green, userled2 to be defined */
++ .name = "ds8",
++ .gpio = AT91_PIN_PA13,
++ .active_low = 1,
++ .default_trigger = "none",
++ },
++ { /* "power" led, yellow */
++ .name = "ds1",
++ .gpio = AT91_PIN_PA23,
++ .default_trigger = "heartbeat",
++ }
++};
++
+ static void __init ek_board_init(void)
+ {
+ /* Serial */
+@@ -481,6 +531,9 @@ static void __init ek_board_init(void)
+ at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
+ /* Touchscreen */
+ ek_add_device_ts();
++ /* SSC (to AT73C213) */
++ at73c213_set_clk(&at73c213_data);
++ at91_add_device_ssc(AT91SAM9261_ID_SSC1, ATMEL_SSC_TX);
+ #else
+ /* MMC */
+ at91_add_device_mmc(0, &ek_mmc_data);
+@@ -489,6 +542,8 @@ static void __init ek_board_init(void)
+ at91_add_device_lcdc(&ek_lcdc_data);
+ /* Push Buttons */
+ ek_add_device_buttons();
++ /* LEDs */
++ at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
+ }
+
+ MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK")
+diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
+index bf103b2..b4cd5d0 100644
+--- a/arch/arm/mach-at91/board-sam9263ek.c
++++ b/arch/arm/mach-at91/board-sam9263ek.c
+@@ -43,29 +43,24 @@
+
+ #include <asm/arch/board.h>
+ #include <asm/arch/gpio.h>
+-#include <asm/arch/at91sam926x_mc.h>
++#include <asm/arch/at91sam9_smc.h>
+
+ #include "generic.h"
+
+
+-/*
+- * Serial port configuration.
+- * 0 .. 2 = USART0 .. USART2
+- * 3 = DBGU
+- */
+-static struct at91_uart_config __initdata ek_uart_config = {
+- .console_tty = 0, /* ttyS0 */
+- .nr_tty = 2,
+- .tty_map = { 3, 0, -1, -1, } /* ttyS0, ..., ttyS3 */
+-};
+-
+ static void __init ek_map_io(void)
+ {
+ /* Initialize processor: 16.367 MHz crystal */
+ at91sam9263_initialize(16367660);
+
+- /* Setup the serial ports and console */
+- at91_init_serial(&ek_uart_config);
++ /* DGBU on ttyS0. (Rx & Tx only) */
++ at91_register_uart(0, 0, 0);
++
++ /* USART0 on ttyS1. (Rx, Tx, RTS, CTS) */
++ at91_register_uart(AT91SAM9263_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
++
++ /* set serial console to ttyS0 (ie, DBGU) */
++ at91_set_serial_console(0);
+ }
+
+ static void __init ek_init_irq(void)
+@@ -341,7 +336,7 @@ static struct gpio_led ek_leds[] = {
+ .name = "ds3",
+ .gpio = AT91_PIN_PB7,
+ .default_trigger = "heartbeat",
+- },
++ }
+ };
+
+
+diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
+index bc0546d..ffc0597 100644
+--- a/arch/arm/mach-at91/board-sam9rlek.c
++++ b/arch/arm/mach-at91/board-sam9rlek.c
+@@ -29,29 +29,24 @@
+
+ #include <asm/arch/board.h>
+ #include <asm/arch/gpio.h>
+-#include <asm/arch/at91sam926x_mc.h>
++#include <asm/arch/at91sam9_smc.h>
+
+ #include "generic.h"
+
+
+-/*
+- * Serial port configuration.
+- * 0 .. 3 = USART0 .. USART3
+- * 4 = DBGU
+- */
+-static struct at91_uart_config __initdata ek_uart_config = {
+- .console_tty = 0, /* ttyS0 */
+- .nr_tty = 2,
+- .tty_map = { 4, 0, -1, -1, -1 } /* ttyS0, ..., ttyS4 */
+-};
+-
+ static void __init ek_map_io(void)
+ {
+ /* Initialize processor: 12.000 MHz crystal */
+ at91sam9rl_initialize(12000000);
+
+- /* Setup the serial ports and console */
+- at91_init_serial(&ek_uart_config);
++ /* DGBU on ttyS0. (Rx & Tx only) */
++ at91_register_uart(0, 0, 0);
++
++ /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) */
++ at91_register_uart(AT91SAM9RL_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
++
++ /* set serial console to ttyS0 (ie, DBGU) */
++ at91_set_serial_console(0);
+ }
+
+ static void __init ek_init_irq(void)
+diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c
+new file mode 100755
+index 0000000..b571710
+--- /dev/null
++++ b/arch/arm/mach-at91/board-yl-9200.c
+@@ -0,0 +1,683 @@
++/*
++ * linux/arch/arm/mach-at91/board-yl-9200.c
++ *
++ * Adapted from:
++ *various board files in
++ * /arch/arm/mach-at91
++ * modifications to convert to YL-9200 platform
++ * Copyright (C) 2007 S.Birtles
++ *
++ * 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/types.h>
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/spi/spi.h>
++/*#include <linux/can_bus/candata.h>*/
++#include <linux/spi/ads7846.h>
++#include <linux/mtd/physmap.h>
++
++/*#include <sound/gpio_sounder.h>*/
++#include <asm/hardware.h>
++#include <asm/setup.h>
++#include <asm/mach-types.h>
++#include <asm/irq.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <asm/mach/irq.h>
++
++#include <asm/arch/board.h>
++#include <asm/arch/gpio.h>
++#include <asm/arch/at91rm9200_mc.h>
++#include <linux/gpio_keys.h>
++#include <linux/input.h>
++
++#include "generic.h"
++#include <asm/arch/at91_pio.h>
++
++#define YL_9200_FLASH_BASE AT91_CHIPSELECT_0
++#define YL_9200_FLASH_SIZE 0x800000
++
++/*
++ * Serial port configuration.
++ * 0 .. 3 = USART0 .. USART3
++ * 4 = DBGU
++ *atmel_usart.0: ttyS0 at MMIO 0xfefff200 (irq = 1) is a ATMEL_SERIAL
++ *atmel_usart.1: ttyS1 at MMIO 0xfffc0000 (irq = 6) is a ATMEL_SERIAL
++ *atmel_usart.2: ttyS2 at MMIO 0xfffc4000 (irq = 7) is a ATMEL_SERIAL
++ *atmel_usart.3: ttyS3 at MMIO 0xfffc8000 (irq = 8) is a ATMEL_SERIAL
++ *atmel_usart.4: ttyS4 at MMIO 0xfffcc000 (irq = 9) is a ATMEL_SERIAL
++ * on the YL-9200 we are sitting at the following
++ *ttyS0 at MMIO 0xfefff200 (irq = 1) is a AT91_SERIAL
++ *ttyS1 at MMIO 0xfefc4000 (irq = 7) is a AT91_SERIAL
++ */
++
++/* extern void __init yl_9200_add_device_sounder(struct gpio_sounder *sounders, int nr);*/
++
++static struct at91_uart_config __initdata yl_9200_uart_config = {
++ .console_tty = 0, /* ttyS0 */
++ .nr_tty = 3,
++ .tty_map = { 4, 1, 0, -1, -1 } /* ttyS0, ..., ttyS4 */
++};
++
++static void __init yl_9200_map_io(void)
++{
++ /* Initialize processor: 18.432 MHz crystal */
++ /*Also initialises register clocks & gpio*/
++ at91rm9200_initialize(18432000, AT91RM9200_PQFP); /*we have a 3 bank system*/
++
++ /* Setup the serial ports and console */
++ at91_init_serial(&yl_9200_uart_config);
++
++ /* Setup the LEDs D2=PB17,D3=PB16 */
++ at91_init_leds(AT91_PIN_PB16,AT91_PIN_PB17); /*cpu-led,timer-led*/
++}
++
++static void __init yl_9200_init_irq(void)
++{
++ at91rm9200_init_interrupts(NULL);
++}
++
++static struct at91_eth_data __initdata yl_9200_eth_data = {
++ .phy_irq_pin = AT91_PIN_PB28,
++ .is_rmii = 1,
++};
++
++static struct at91_usbh_data __initdata yl_9200_usbh_data = {
++ .ports = 1, /* this should be 1 not 2 for the Yl9200*/
++};
++
++static struct at91_udc_data __initdata yl_9200_udc_data = {
++/*on sheet 7 Schemitic rev 1.0*/
++ .pullup_pin = AT91_PIN_PC4,
++ .vbus_pin= AT91_PIN_PC5,
++ .pullup_active_low = 1, /*ACTIVE LOW!! due to PNP transistor on page 7*/
++
++};
++/*
++static struct at91_cf_data __initdata yl_9200_cf_data = {
++TODO S.BIRTLES
++ .det_pin = AT91_PIN_xxx,
++ .rst_pin = AT91_PIN_xxx,
++ .irq_pin = ... not connected
++ .vcc_pin = ... always powered
++
++};
++*/
++static struct at91_mmc_data __initdata yl_9200_mmc_data = {
++ .det_pin = AT91_PIN_PB9, /*THIS LOOKS CORRECT SHEET7*/
++/* .wp_pin = ... not connected SHEET7*/
++ .slot_b = 0,
++ .wire4 = 1,
++
++};
++
++/* --------------------------------------------------------------------
++ * Touch screen
++ * -------------------------------------------------------------------- */
++#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
++static int ads7843_pendown_state(void)
++{
++ return !at91_get_gpio_value(AT91_PIN_PB11); /* Touchscreen PENIRQ */
++}
++
++static void __init at91_init_device_ts(void)
++{
++/*IMPORTANT NOTE THE SPI INTERFACE IS ALREADY CONFIGURED BY XXX_DEVICES.C
++THAT IS TO SAY THAT MISO,MOSI,SPCK AND CS are already configured
++we only need to enable the other datapins which are:
++PB10/RK1 BUSY
++*/
++/* Touchscreen BUSY signal , pin,use pullup ( TODO not currently used in the ADS7843/6.c driver)*/
++at91_set_gpio_input(AT91_PIN_PB10, 1);
++}
++
++#else
++static void __init at91_init_device_ts(void) {}
++#endif
++
++static struct ads7846_platform_data ads_info = {
++ .model = 7843,
++ .x_min = 150,
++ .x_max = 3830,
++ .y_min = 190,
++ .y_max = 3830,
++ .vref_delay_usecs = 100,
++/* for a 8" touch screen*/
++ //.x_plate_ohms = 603, //= 450, S.Birtles TODO
++ //.y_plate_ohms = 332, //= 250, S.Birtles TODO
++/*for a 10.4" touch screen*/
++ //.x_plate_ohms =611,
++ //.y_plate_ohms =325,
++
++ .x_plate_ohms = 576,
++ .y_plate_ohms = 366,
++ //
++ .pressure_max = 15000, /*generally nonsense on the 7843*/
++ /*number of times to send query to chip in a given run 0 equals one time (do not set to 0!! ,there is a bug in ADS 7846 code)*/
++ .debounce_max = 1,
++ .debounce_rep = 0,
++ .debounce_tol = (~0),
++ .get_pendown_state = ads7843_pendown_state,
++};
++
++/*static struct canbus_platform_data can_info = {
++ .model = 2510,
++};
++*/
++
++static struct spi_board_info yl_9200_spi_devices[] = {
++/*this sticks it at:
++ /sys/devices/platform/atmel_spi.0/spi0.0
++ /sys/bus/platform/devices/
++Documentation/spi IIRC*/
++
++#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
++ /*(this IS correct 04-NOV-2007)*/
++ {
++ .modalias = "ads7846", /* because the driver is called ads7846*/
++ .chip_select = 0, /*THIS MUST BE AN INDEX INTO AN ARRAY OF pins */
++/*this is ONLY TO BE USED if chipselect above is not used, it passes a pin directly for the chip select*/
++ /*.controller_data =AT91_PIN_PA3 ,*/
++ .max_speed_hz = 5000*26, /*(4700 * 26)-125000 * 26, (max sample rate @ 3V) * (cmd + data + overhead) */
++ .bus_num = 0,
++ .platform_data = &ads_info,
++ .irq = AT91_PIN_PB11,
++ },
++#endif
++/*we need to put our CAN driver data here!!*/
++/*THIS IS ALL DUMMY DATA*/
++/* {
++ .modalias = "mcp2510", //DUMMY for MCP2510 chip
++ .chip_select = 1,*/ /*THIS MUST BE AN INDEX INTO AN ARRAY OF pins */
++ /*this is ONLY TO BE USED if chipselect above is not used, it passes a pin directly for the chip select */
++ /* .controller_data =AT91_PIN_PA4 ,
++ .max_speed_hz = 25000 * 26,
++ .bus_num = 0,
++ .platform_data = &can_info,
++ .irq = AT91_PIN_PC0,
++ },
++ */
++ //max SPI chip needs to go here
++};
++
++static struct mtd_partition __initdata yl_9200_nand_partition[] = {
++ {
++ .name = "AT91 NAND partition 1, boot",
++ .offset = 0,
++ .size = 1 * SZ_256K
++ },
++ {
++ .name = "AT91 NAND partition 2, kernel",
++ .offset = 1 * SZ_256K,
++ .size = 2 * SZ_1M - 1 * SZ_256K
++ },
++ {
++ .name = "AT91 NAND partition 3, filesystem",
++ .offset = 2 * SZ_1M,
++ .size = 14 * SZ_1M
++ },
++ {
++ .name = "AT91 NAND partition 4, storage",
++ .offset = 16 * SZ_1M,
++ .size = 16 * SZ_1M
++ },
++ {
++ .name = "AT91 NAND partition 5, ext-fs",
++ .offset = 32 * SZ_1M,
++ .size = 32 * SZ_1M
++ },
++};
++
++static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
++{
++ *num_partitions = ARRAY_SIZE(yl_9200_nand_partition);
++ return yl_9200_nand_partition;
++}
++
++static struct at91_nand_data __initdata yl_9200_nand_data = {
++ .ale= 6,
++ .cle= 7,
++ /*.det_pin = AT91_PIN_PCxx,*/ /*we don't have a det pin because NandFlash is fixed to board*/
++ .rdy_pin = AT91_PIN_PC14, /*R/!B Sheet10*/
++ .enable_pin = AT91_PIN_PC15, /*!CE Sheet10 */
++ .partition_info = nand_partitions,
++};
++
++
++
++/*
++TODO S.Birtles
++potentially a problem with the size above
++physmap platform flash device: 00800000 at 10000000
++physmap-flash.0: Found 1 x16 devices at 0x0 in 16-bit bank
++NOR chip too large to fit in mapping. Attempting to cope...
++ Intel/Sharp Extended Query Table at 0x0031
++Using buffer write method
++cfi_cmdset_0001: Erase suspend on write enabled
++Reducing visibility of 16384KiB chip to 8192KiB
++*/
++
++static struct mtd_partition yl_9200_flash_partitions[] = {
++ {
++ .name = "Bootloader",
++ .size = 0x00040000,
++ .offset = 0,
++ .mask_flags = MTD_WRITEABLE /* force read-only */
++ },{
++ .name = "Kernel",
++ .size = 0x001C0000,
++ .offset = 0x00040000,
++ },{
++ .name = "Filesystem",
++ .size = MTDPART_SIZ_FULL,
++ .offset = 0x00200000
++ }
++
++};
++
++static struct physmap_flash_data yl_9200_flash_data = {
++ .width = 2,
++ .parts = yl_9200_flash_partitions,
++ .nr_parts = ARRAY_SIZE(yl_9200_flash_partitions),
++};
++
++static struct resource yl_9200_flash_resources[] = {
++{
++ .start = YL_9200_FLASH_BASE,
++ .end = YL_9200_FLASH_BASE + YL_9200_FLASH_SIZE - 1,
++ .flags = IORESOURCE_MEM,
++ }
++};
++
++static struct platform_device yl_9200_flash = {
++ .name = "physmap-flash",
++ .id = 0,
++ .dev = {
++ .platform_data = &yl_9200_flash_data,
++ },
++ .resource = yl_9200_flash_resources,
++ .num_resources = ARRAY_SIZE(yl_9200_flash_resources),
++};
++
++
++static struct gpio_led yl_9200_leds[] = {
++/*D2 &D3 are passed directly in via at91_init_leds*/
++ {
++ .name = "led4", /*D4*/
++ .gpio = AT91_PIN_PB15,
++ .active_low = 1,
++ .default_trigger = "heartbeat",
++ /*.default_trigger = "timer",*/
++ },
++ {
++ .name = "led5", /*D5*/
++ .gpio = AT91_PIN_PB8,
++ .active_low = 1,
++ .default_trigger = "heartbeat",
++ }
++};
++
++//static struct gpio_sounder yl_9200_sounder[] = {*/
++/*This is a simple speaker attached to a gpo line*/
++
++// {
++// .name = "Speaker", /*LS1*/
++// .gpio = AT91_PIN_PA22,
++// .active_low = 0,
++// .default_trigger = "heartbeat",
++ /*.default_trigger = "timer",*/
++// },
++//};
++
++
++
++static struct i2c_board_info __initdata yl_9200_i2c_devices[] = {
++ {
++ /*TODO*/
++ I2C_BOARD_INFO("CS4334", 0x00),
++ }
++};
++
++
++ /*
++ * GPIO Buttons
++ */
++#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
++static struct gpio_keys_button yl_9200_buttons[] = {
++ {
++ .gpio = AT91_PIN_PA24,
++ .code = BTN_2,
++ .desc = "SW2",
++ .active_low = 1,
++ .wakeup = 1,
++ },
++ {
++ .gpio = AT91_PIN_PB1,
++ .code = BTN_3,
++ .desc = "SW3",
++ .active_low = 1,
++ .wakeup = 1,
++ },
++ {
++ .gpio = AT91_PIN_PB2,
++ .code = BTN_4,
++ .desc = "SW4",
++ .active_low = 1,
++ .wakeup = 1,
++ },
++ {
++ .gpio = AT91_PIN_PB6,
++ .code = BTN_5,
++ .desc = "SW5",
++ .active_low = 1,
++ .wakeup = 1,
++ },
++
++};
++
++static struct gpio_keys_platform_data yl_9200_button_data = {
++ .buttons = yl_9200_buttons,
++ .nbuttons = ARRAY_SIZE(yl_9200_buttons),
++};
++
++static struct platform_device yl_9200_button_device = {
++ .name = "gpio-keys",
++ .id = -1,
++ .num_resources = 0,
++ .dev = {
++ .platform_data = &yl_9200_button_data,
++ }
++};
++
++static void __init yl_9200_add_device_buttons(void)
++{
++ //SW2
++ at91_set_gpio_input(AT91_PIN_PA24, 0);
++ at91_set_deglitch(AT91_PIN_PA24, 1);
++
++ //SW3
++ at91_set_gpio_input(AT91_PIN_PB1, 0);
++ at91_set_deglitch(AT91_PIN_PB1, 1);
++ //SW4
++ at91_set_gpio_input(AT91_PIN_PB2, 0);
++ at91_set_deglitch(AT91_PIN_PB2, 1);
++
++ //SW5
++ at91_set_gpio_input(AT91_PIN_PB6, 0);
++ at91_set_deglitch(AT91_PIN_PB6, 1);
++
++
++ at91_set_gpio_output(AT91_PIN_PB7, 1); /* #TURN BUTTONS ON, SHEET 5 of schematics */
++ platform_device_register(&yl_9200_button_device);
++}
++#else
++static void __init yl_9200_add_device_buttons(void) {}
++#endif
++
++#if defined(CONFIG_FB_S1D135XX) || defined(CONFIG_FB_S1D13XXX_MODULE)
++#include <video/s1d13xxxfb.h>
++
++/* EPSON S1D13806 FB (discontinued chip)*/
++/* EPSON S1D13506 FB */
++
++#define AT91_FB_REG_BASE 0x80000000L
++#define AT91_FB_REG_SIZE 0x200
++#define AT91_FB_VMEM_BASE 0x80200000L
++#define AT91_FB_VMEM_SIZE 0x200000L
++
++/*#define S1D_DISPLAY_WIDTH 640*/
++/*#define S1D_DISPLAY_HEIGHT 480*/
++
++
++static void __init yl_9200_init_video(void)
++{
++ at91_sys_write(AT91_PIOC + PIO_ASR,AT91_PIN_PC6);
++ at91_sys_write(AT91_PIOC + PIO_BSR,0);
++ at91_sys_write(AT91_PIOC + PIO_ASR,AT91_PIN_PC6);
++
++ at91_sys_write( AT91_SMC_CSR(2),
++ AT91_SMC_NWS_(0x4) |
++ AT91_SMC_WSEN |
++ AT91_SMC_TDF_(0x100) |
++ AT91_SMC_DBW
++ );
++
++
++
++}
++
++
++static struct s1d13xxxfb_regval yl_9200_s1dfb_initregs[] =
++{
++ {S1DREG_MISC, 0x00}, /* Miscellaneous Register*/
++ {S1DREG_COM_DISP_MODE, 0x01}, /* Display Mode Register, LCD only*/
++ {S1DREG_GPIO_CNF0, 0x00}, /* General IO Pins Configuration Register*/
++ {S1DREG_GPIO_CTL0, 0x00}, /* General IO Pins Control Register*/
++ {S1DREG_CLK_CNF, 0x11}, /* Memory Clock Configuration Register*/
++ {S1DREG_LCD_CLK_CNF, 0x10}, /* LCD Pixel Clock Configuration Register*/
++ {S1DREG_CRT_CLK_CNF, 0x12}, /* CRT/TV Pixel Clock Configuration Register*/
++ {S1DREG_MPLUG_CLK_CNF, 0x01}, /* MediaPlug Clock Configuration Register*/
++ {S1DREG_CPU2MEM_WST_SEL, 0x02}, /* CPU To Memory Wait State Select Register*/
++ {S1DREG_MEM_CNF, 0x00}, /* Memory Configuration Register*/
++ {S1DREG_SDRAM_REF_RATE, 0x04}, /* DRAM Refresh Rate Register, MCLK source*/
++ {S1DREG_SDRAM_TC0, 0x12}, /* DRAM Timings Control Register 0*/
++ {S1DREG_SDRAM_TC1, 0x02}, /* DRAM Timings Control Register 1*/
++ {S1DREG_PANEL_TYPE, 0x25}, /* Panel Type Register*/
++ {S1DREG_MOD_RATE, 0x00}, /* MOD Rate Register*/
++ {S1DREG_LCD_DISP_HWIDTH, 0x4F}, /* LCD Horizontal Display Width Register*/
++ {S1DREG_LCD_NDISP_HPER, 0x13}, /* LCD Horizontal Non-Display Period Register*/
++ {S1DREG_TFT_FPLINE_START, 0x01}, /* TFT FPLINE Start Position Register*/
++ {S1DREG_TFT_FPLINE_PWIDTH, 0x0c}, /* TFT FPLINE Pulse Width Register*/
++ {S1DREG_LCD_DISP_VHEIGHT0, 0xDF}, /* LCD Vertical Display Height Register 0*/
++ {S1DREG_LCD_DISP_VHEIGHT1, 0x01}, /* LCD Vertical Display Height Register 1*/
++ {S1DREG_LCD_NDISP_VPER, 0x2c}, /* LCD Vertical Non-Display Period Register*/
++ {S1DREG_TFT_FPFRAME_START, 0x0a}, /* TFT FPFRAME Start Position Register*/
++ {S1DREG_TFT_FPFRAME_PWIDTH, 0x02}, /* TFT FPFRAME Pulse Width Register*/
++ {S1DREG_LCD_DISP_MODE, 0x05}, /* LCD Display Mode Register*/
++ {S1DREG_LCD_MISC, 0x01}, /* LCD Miscellaneous Register*/
++ {S1DREG_LCD_DISP_START0, 0x00}, /* LCD Display Start Address Register 0*/
++ {S1DREG_LCD_DISP_START1, 0x00}, /* LCD Display Start Address Register 1*/
++ {S1DREG_LCD_DISP_START2, 0x00}, /* LCD Display Start Address Register 2*/
++ {S1DREG_LCD_MEM_OFF0, 0x80}, /* LCD Memory Address Offset Register 0*/
++ {S1DREG_LCD_MEM_OFF1, 0x02}, /* LCD Memory Address Offset Register 1*/
++ {S1DREG_LCD_PIX_PAN, 0x03}, /* LCD Pixel Panning Register*/
++ {S1DREG_LCD_DISP_FIFO_HTC, 0x00}, /* LCD Display FIFO High Threshold Control Register*/
++ {S1DREG_LCD_DISP_FIFO_LTC, 0x00}, /* LCD Display FIFO Low Threshold Control Register*/
++ {S1DREG_CRT_DISP_HWIDTH, 0x4F}, /* CRT/TV Horizontal Display Width Register*/
++ {S1DREG_CRT_NDISP_HPER, 0x13}, /* CRT/TV Horizontal Non-Display Period Register*/
++ {S1DREG_CRT_HRTC_START, 0x01}, /* CRT/TV HRTC Start Position Register*/
++ {S1DREG_CRT_HRTC_PWIDTH, 0x0B}, /* CRT/TV HRTC Pulse Width Register*/
++ {S1DREG_CRT_DISP_VHEIGHT0, 0xDF}, /* CRT/TV Vertical Display Height Register 0*/
++ {S1DREG_CRT_DISP_VHEIGHT1, 0x01}, /* CRT/TV Vertical Display Height Register 1*/
++ {S1DREG_CRT_NDISP_VPER, 0x2B}, /* CRT/TV Vertical Non-Display Period Register*/
++ {S1DREG_CRT_VRTC_START, 0x09}, /* CRT/TV VRTC Start Position Register*/
++ {S1DREG_CRT_VRTC_PWIDTH, 0x01}, /* CRT/TV VRTC Pulse Width Register*/
++ {S1DREG_TV_OUT_CTL, 0x18}, /* TV Output Control Register */
++ {S1DREG_CRT_DISP_MODE, 0x05}, /* CRT/TV Display Mode Register, 16BPP*/
++ {S1DREG_CRT_DISP_START0, 0x00}, /* CRT/TV Display Start Address Register 0*/
++ {S1DREG_CRT_DISP_START1, 0x00}, /* CRT/TV Display Start Address Register 1*/
++ {S1DREG_CRT_DISP_START2, 0x00}, /* CRT/TV Display Start Address Register 2*/
++ {S1DREG_CRT_MEM_OFF0, 0x80}, /* CRT/TV Memory Address Offset Register 0*/
++ {S1DREG_CRT_MEM_OFF1, 0x02}, /* CRT/TV Memory Address Offset Register 1*/
++ {S1DREG_CRT_PIX_PAN, 0x00}, /* CRT/TV Pixel Panning Register*/
++ {S1DREG_CRT_DISP_FIFO_HTC, 0x00}, /* CRT/TV Display FIFO High Threshold Control Register*/
++ {S1DREG_CRT_DISP_FIFO_LTC, 0x00}, /* CRT/TV Display FIFO Low Threshold Control Register*/
++ {S1DREG_LCD_CUR_CTL, 0x00}, /* LCD Ink/Cursor Control Register*/
++ {S1DREG_LCD_CUR_START, 0x01}, /* LCD Ink/Cursor Start Address Register*/
++ {S1DREG_LCD_CUR_XPOS0, 0x00}, /* LCD Cursor X Position Register 0*/
++ {S1DREG_LCD_CUR_XPOS1, 0x00}, /* LCD Cursor X Position Register 1*/
++ {S1DREG_LCD_CUR_YPOS0, 0x00}, /* LCD Cursor Y Position Register 0*/
++ {S1DREG_LCD_CUR_YPOS1, 0x00}, /* LCD Cursor Y Position Register 1*/
++ {S1DREG_LCD_CUR_BCTL0, 0x00}, /* LCD Ink/Cursor Blue Color 0 Register*/
++ {S1DREG_LCD_CUR_GCTL0, 0x00}, /* LCD Ink/Cursor Green Color 0 Register*/
++ {S1DREG_LCD_CUR_RCTL0, 0x00}, /* LCD Ink/Cursor Red Color 0 Register*/
++ {S1DREG_LCD_CUR_BCTL1, 0x1F}, /* LCD Ink/Cursor Blue Color 1 Register*/
++ {S1DREG_LCD_CUR_GCTL1, 0x3F}, /* LCD Ink/Cursor Green Color 1 Register*/
++ {S1DREG_LCD_CUR_RCTL1, 0x1F}, /* LCD Ink/Cursor Red Color 1 Register*/
++ {S1DREG_LCD_CUR_FIFO_HTC, 0x00}, /* LCD Ink/Cursor FIFO Threshold Register*/
++ {S1DREG_CRT_CUR_CTL, 0x00}, /* CRT/TV Ink/Cursor Control Register*/
++ {S1DREG_CRT_CUR_START, 0x01}, /* CRT/TV Ink/Cursor Start Address Register*/
++ {S1DREG_CRT_CUR_XPOS0, 0x00}, /* CRT/TV Cursor X Position Register 0*/
++ {S1DREG_CRT_CUR_XPOS1, 0x00}, /* CRT/TV Cursor X Position Register 1*/
++ {S1DREG_CRT_CUR_YPOS0, 0x00}, /* CRT/TV Cursor Y Position Register 0*/
++ {S1DREG_CRT_CUR_YPOS1, 0x00}, /* CRT/TV Cursor Y Position Register 1*/
++ {S1DREG_CRT_CUR_BCTL0, 0x00}, /* CRT/TV Ink/Cursor Blue Color 0 Register*/
++ {S1DREG_CRT_CUR_GCTL0, 0x00}, /* CRT/TV Ink/Cursor Green Color 0 Register*/
++ {S1DREG_CRT_CUR_RCTL0, 0x00}, /* CRT/TV Ink/Cursor Red Color 0 Register*/
++ {S1DREG_CRT_CUR_BCTL1, 0x1F}, /* CRT/TV Ink/Cursor Blue Color 1 Register*/
++ {S1DREG_CRT_CUR_GCTL1, 0x3F}, /* CRT/TV Ink/Cursor Green Color 1 Register*/
++ {S1DREG_CRT_CUR_RCTL1, 0x1F}, /* CRT/TV Ink/Cursor Red Color 1 Register*/
++ {S1DREG_CRT_CUR_FIFO_HTC, 0x00}, /* CRT/TV Ink/Cursor FIFO Threshold Register*/
++ {S1DREG_BBLT_CTL0, 0x00}, /* BitBlt Control Register 0*/
++ {S1DREG_BBLT_CTL1, 0x01}, /* BitBlt Control Register 1*/
++ {S1DREG_BBLT_CC_EXP, 0x00}, /* BitBlt ROP Code/Color Expansion Register*/
++ {S1DREG_BBLT_OP, 0x00}, /* BitBlt Operation Register*/
++ {S1DREG_BBLT_SRC_START0, 0x00}, /* BitBlt Source Start Address Register 0*/
++ {S1DREG_BBLT_SRC_START1, 0x00}, /* BitBlt Source Start Address Register 1*/
++ {S1DREG_BBLT_SRC_START2, 0x00}, /* BitBlt Source Start Address Register 2*/
++ {S1DREG_BBLT_DST_START0, 0x00}, /* BitBlt Destination Start Address Register 0*/
++ {S1DREG_BBLT_DST_START1, 0x00}, /* BitBlt Destination Start Address Register 1*/
++ {S1DREG_BBLT_DST_START2, 0x00}, /* BitBlt Destination Start Address Register 2*/
++ {S1DREG_BBLT_MEM_OFF0, 0x00}, /* BitBlt Memory Address Offset Register 0*/
++ {S1DREG_BBLT_MEM_OFF1, 0x00}, /* BitBlt Memory Address Offset Register 1*/
++ {S1DREG_BBLT_WIDTH0, 0x00}, /* BitBlt Width Register 0*/
++ {S1DREG_BBLT_WIDTH1, 0x00}, /* BitBlt Width Register 1*/
++ {S1DREG_BBLT_HEIGHT0, 0x00}, /* BitBlt Height Register 0*/
++ {S1DREG_BBLT_HEIGHT1, 0x00}, /* BitBlt Height Register 1*/
++ {S1DREG_BBLT_BGC0, 0x00}, /* BitBlt Background Color Register 0*/
++ {S1DREG_BBLT_BGC1, 0x00}, /* BitBlt Background Color Register 1*/
++ {S1DREG_BBLT_FGC0, 0x00}, /* BitBlt Foreground Color Register 0*/
++ {S1DREG_BBLT_FGC1, 0x00}, /* BitBlt Foreground Color Register 1*/
++ {S1DREG_LKUP_MODE, 0x00}, /* Look-Up Table Mode Register*/
++ {S1DREG_LKUP_ADDR, 0x00}, /* Look-Up Table Address Register*/
++ {S1DREG_PS_CNF, 0x00}, /* Power Save Configuration Register*/
++ {S1DREG_PS_STATUS, 0x00}, /* Power Save Status Register*/
++ {S1DREG_CPU2MEM_WDOGT, 0x00}, /* CPU-to-Memory Access Watchdog Timer Register*/
++ {S1DREG_COM_DISP_MODE, 0x01}, /* Display Mode Register, LCD only*/
++};
++
++static u64 s1dfb_dmamask = 0xffffffffUL;
++
++static struct s1d13xxxfb_pdata yl_9200_s1dfb_pdata = {
++ .initregs = yl_9200_s1dfb_initregs,
++ .initregssize = ARRAY_SIZE(yl_9200_s1dfb_initregs),
++ .platform_init_video = yl_9200_init_video,
++};
++
++static struct resource yl_9200_s1dfb_resource[] = {
++ [0] = { /* video mem */
++ .name = "s1d13xxxfb memory",
++ /* .name = "s1d13806 memory",*/
++ .start = AT91_FB_VMEM_BASE,
++ .end = AT91_FB_VMEM_BASE + AT91_FB_VMEM_SIZE -1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = { /* video registers */
++ .name = "s1d13xxxfb registers",
++ /* .name = "s1d13806 registers",*/
++ .start = AT91_FB_REG_BASE,
++ .end = AT91_FB_REG_BASE + AT91_FB_REG_SIZE -1,
++ .flags = IORESOURCE_MEM,
++ },
++};
++
++static struct platform_device yl_9200_s1dfb_device = {
++ /*TODO S.Birtles , really we need the chip revision in here as well*/
++ .name = "s1d13806fb",
++ /* .name = "s1d13506fb",*/
++ .id = -1,
++ .dev = {
++ /*TODO theres a waring here!!*/
++ /*WARNING: vmlinux.o(.data+0x2dbc): Section mismatch: reference to .init.text: (between 'yl_9200_s1dfb_pdata' and 's1dfb_dmamask')*/
++ .dma_mask = &s1dfb_dmamask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &yl_9200_s1dfb_pdata,
++ },
++ .resource = yl_9200_s1dfb_resource,
++ .num_resources = ARRAY_SIZE(yl_9200_s1dfb_resource),
++};
++
++void __init yl_9200_add_device_video(void)
++{
++ platform_device_register(&yl_9200_s1dfb_device);
++}
++#else
++ void __init yl_9200_add_device_video(void) {}
++#endif
++
++/*this is not called first , yl_9200_map_io is called first*/
++static void __init yl_9200_board_init(void)
++{
++ /* Serial */
++ at91_add_device_serial();
++ /* Ethernet */
++ at91_add_device_eth(&yl_9200_eth_data);
++ /* USB Host */
++ at91_add_device_usbh(&yl_9200_usbh_data);
++ /* USB Device */
++ at91_add_device_udc(&yl_9200_udc_data);
++ /* pullup_pin it is actually active low, but this is not needed, driver sets it up */
++ /*at91_set_multi_drive(yl_9200_udc_data.pullup_pin, 0);*/
++
++ /* Compact Flash */
++ /*at91_add_device_cf(&yl_9200_cf_data);*/
++
++ /* I2C */
++ at91_add_device_i2c(yl_9200_i2c_devices, ARRAY_SIZE(yl_9200_i2c_devices));
++ /* SPI */
++ /*TODO YL9200 we have 2 spi interfaces touch screen & CAN*/
++ /* AT91_PIN_PA5, AT91_PIN_PA6 , are used on the max 485 NOT SPI*/
++
++ /*touch screen and CAN*/
++ at91_add_device_spi(yl_9200_spi_devices, ARRAY_SIZE(yl_9200_spi_devices));
++
++ /*Basically the TS uses PB11 & PB10 , PB11 is configured by the SPI system BP10 IS NOT USED!!*/
++ /* we need this incase the board is running without a touch screen*/
++ #if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
++ at91_init_device_ts(); /*init the touch screen device*/
++ #endif
++ /* DataFlash card */
++ at91_add_device_mmc(0, &yl_9200_mmc_data);
++ /* NAND */
++ at91_add_device_nand(&yl_9200_nand_data);
++ /* NOR Flash */
++ platform_device_register(&yl_9200_flash);
++ /* LEDs. Note!! this does not include the led's we passed for the processor status */
++ at91_gpio_leds(yl_9200_leds, ARRAY_SIZE(yl_9200_leds));
++ /* VGA */
++ /*this is self registered by including the s1d13xxx chip in the kernel build*/
++ yl_9200_add_device_video();
++ /* Push Buttons */
++ yl_9200_add_device_buttons();
++ /*TODO fixup the Sounder */
++// yl_9200_add_device_sounder(yl_9200_sounder,ARRAY_SIZE(yl_9200_sounder));
++
++}
++
++MACHINE_START(YL9200, "uCdragon YL-9200")
++ /* Maintainer: S.Birtles*/
++ .phys_io = AT91_BASE_SYS,
++ .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
++ .boot_params = AT91_SDRAM_BASE + 0x100,
++ .timer = &at91rm9200_timer,
++ .map_io = yl_9200_map_io,
++ .init_irq = yl_9200_init_irq,
++ .init_machine = yl_9200_board_init,
++MACHINE_END
+diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c
+index de6424e..a33dfe4 100644
+--- a/arch/arm/mach-at91/clock.c
++++ b/arch/arm/mach-at91/clock.c
+@@ -23,7 +23,6 @@
+ #include <linux/delay.h>
+ #include <linux/clk.h>
+
+-#include <asm/semaphore.h>
+ #include <asm/io.h>
+ #include <asm/mach-types.h>
+
+diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
+index a67defd..39733b6 100644
+--- a/arch/arm/mach-at91/pm.c
++++ b/arch/arm/mach-at91/pm.c
+@@ -26,12 +26,135 @@
+ #include <asm/mach-types.h>
+
+ #include <asm/arch/at91_pmc.h>
+-#include <asm/arch/at91rm9200_mc.h>
+ #include <asm/arch/gpio.h>
+ #include <asm/arch/cpu.h>
+
+ #include "generic.h"
+
++#ifdef CONFIG_ARCH_AT91RM9200
++#include <asm/arch/at91rm9200_mc.h>
++
++/*
++ * The AT91RM9200 goes into self-refresh mode with this command, and will
++ * terminate self-refresh automatically on the next SDRAM access.
++ */
++#define sdram_selfrefresh_enable() at91_sys_write(AT91_SDRAMC_SRR, 1)
++#define sdram_selfrefresh_disable() do {} while (0)
++
++#elif defined(CONFIG_ARCH_AT91CAP9)
++#include <asm/arch/at91cap9_ddrsdr.h>
++
++static u32 saved_lpr;
++
++static inline void sdram_selfrefresh_enable(void)
++{
++ u32 lpr;
++
++ saved_lpr = at91_sys_read(AT91_DDRSDRC_LPR);
++
++ lpr = saved_lpr & ~AT91_DDRSDRC_LPCB;
++ at91_sys_write(AT91_DDRSDRC_LPR, lpr | AT91_DDRSDRC_LPCB_SELF_REFRESH);
++}
++
++#define sdram_selfrefresh_disable() at91_sys_write(AT91_DDRSDRC_LPR, saved_lpr)
++
++#else
++#include <asm/arch/at91sam9_sdramc.h>
++
++static u32 saved_lpr;
++
++static inline void sdram_selfrefresh_enable(void)
++{
++ u32 lpr;
++
++ saved_lpr = at91_sys_read(AT91_SDRAMC_LPR);
++
++ lpr = saved_lpr & ~AT91_SDRAMC_LPCB;
++ at91_sys_write(AT91_SDRAMC_LPR, lpr | AT91_SDRAMC_LPCB_SELF_REFRESH);
++}
++
++#define sdram_selfrefresh_disable() at91_sys_write(AT91_SDRAMC_LPR, saved_lpr)
++
++/*
++ * FIXME: The AT91SAM9263 has a second EBI controller which may have
++ * additional SDRAM. pm_slowclock.S will require a similar fix.
++ */
++
++#endif
++
++
++/*
++ * Show the reason for the previous system reset.
++ */
++#if defined(AT91_SHDWC)
++
++#include <asm/arch/at91_rstc.h>
++#include <asm/arch/at91_shdwc.h>
++
++static void __init show_reset_status(void)
++{
++ static char reset[] __initdata = "reset";
++
++ static char general[] __initdata = "general";
++ static char wakeup[] __initdata = "wakeup";
++ static char watchdog[] __initdata = "watchdog";
++ static char software[] __initdata = "software";
++ static char user[] __initdata = "user";
++ static char unknown[] __initdata = "unknown";
++
++ static char signal[] __initdata = "signal";
++ static char rtc[] __initdata = "rtc";
++ static char rtt[] __initdata = "rtt";
++ static char restore[] __initdata = "power-restored";
++
++ char *reason, *r2 = reset;
++ u32 reset_type, wake_type;
++
++ reset_type = at91_sys_read(AT91_RSTC_SR) & AT91_RSTC_RSTTYP;
++ wake_type = at91_sys_read(AT91_SHDW_SR);
++
++ switch (reset_type) {
++ case AT91_RSTC_RSTTYP_GENERAL:
++ reason = general;
++ break;
++ case AT91_RSTC_RSTTYP_WAKEUP:
++ /* board-specific code enabled the wakeup sources */
++ reason = wakeup;
++
++ /* "wakeup signal" */
++ if (wake_type & AT91_SHDW_WAKEUP0)
++ r2 = signal;
++ else {
++ r2 = reason;
++ if (wake_type & AT91_SHDW_RTTWK) /* rtt wakeup */
++ reason = rtt;
++ else if (wake_type & AT91_SHDW_RTCWK) /* rtc wakeup */
++ reason = rtc;
++ else if (wake_type == 0) /* power-restored wakeup */
++ reason = restore;
++ else /* unknown wakeup */
++ reason = unknown;
++ }
++ break;
++ case AT91_RSTC_RSTTYP_WATCHDOG:
++ reason = watchdog;
++ break;
++ case AT91_RSTC_RSTTYP_SOFTWARE:
++ reason = software;
++ break;
++ case AT91_RSTC_RSTTYP_USER:
++ reason = user;
++ break;
++ default:
++ reason = unknown;
++ break;
++ }
++ pr_info("AT91: Starting after %s %s\n", reason, r2);
++}
++#else
++static void __init show_reset_status(void) {}
++#endif
++
+
+ static int at91_pm_valid_state(suspend_state_t state)
+ {
+@@ -125,6 +248,11 @@ EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
+
+ static void (*slow_clock)(void);
+
++#ifdef CONFIG_AT91_SLOW_CLOCK
++extern void at91_slow_clock(void);
++extern u32 at91_slow_clock_sz;
++#endif
++
+
+ static int at91_pm_enter(suspend_state_t state)
+ {
+@@ -158,11 +286,14 @@ static int at91_pm_enter(suspend_state_t state)
+ * turning off the main oscillator; reverse on wakeup.
+ */
+ if (slow_clock) {
++#ifdef CONFIG_AT91_SLOW_CLOCK
++ /* copy slow_clock handler to SRAM, and call it */
++ memcpy(slow_clock, at91_slow_clock, at91_slow_clock_sz);
++#endif
+ slow_clock();
+ break;
+ } else {
+- /* DEVELOPMENT ONLY */
+- pr_info("AT91: PM - no slow clock mode yet ...\n");
++ pr_info("AT91: PM - no slow clock mode enabled ...\n");
+ /* FALLTHROUGH leaving master clock alone */
+ }
+
+@@ -175,13 +306,15 @@ static int at91_pm_enter(suspend_state_t state)
+ case PM_SUSPEND_STANDBY:
+ /*
+ * NOTE: the Wait-for-Interrupt instruction needs to be
+- * in icache so the SDRAM stays in self-refresh mode until
+- * the wakeup IRQ occurs.
++ * in icache so no SDRAM accesses are needed until the
++ * wakeup IRQ occurs and self-refresh is terminated.
+ */
+ asm("b 1f; .align 5; 1:");
+ asm("mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */
+- at91_sys_write(AT91_SDRAMC_SRR, 1); /* self-refresh mode */
+- /* fall though to next state */
++ sdram_selfrefresh_enable();
++ asm("mcr p15, 0, r0, c7, c0, 4"); /* wait for interrupt */
++ sdram_selfrefresh_disable();
++ break;
+
+ case PM_SUSPEND_ON:
+ asm("mcr p15, 0, r0, c7, c0, 4"); /* wait for interrupt */
+@@ -196,6 +329,7 @@ static int at91_pm_enter(suspend_state_t state)
+ at91_sys_read(AT91_AIC_IPR) & at91_sys_read(AT91_AIC_IMR));
+
+ error:
++ sdram_selfrefresh_disable();
+ target_state = PM_SUSPEND_ON;
+ at91_irq_resume();
+ at91_gpio_resume();
+@@ -220,21 +354,20 @@ static struct platform_suspend_ops at91_pm_ops ={
+
+ static int __init at91_pm_init(void)
+ {
+- printk("AT91: Power Management\n");
+-
+-#ifdef CONFIG_AT91_PM_SLOW_CLOCK
+- /* REVISIT allocations of SRAM should be dynamically managed.
+- * FIQ handlers and other components will want SRAM/TCM too...
+- */
+- slow_clock = (void *) (AT91_VA_BASE_SRAM + (3 * SZ_4K));
+- memcpy(slow_clock, at91rm9200_slow_clock, at91rm9200_slow_clock_sz);
++#ifdef CONFIG_AT91_SLOW_CLOCK
++ slow_clock = (void *) (AT91_IO_VIRT_BASE - at91_slow_clock_sz);
+ #endif
+
+- /* Disable SDRAM low-power mode. Cannot be used with self-refresh. */
++ pr_info("AT91: Power Management%s\n", (slow_clock ? " (with slow clock mode)" : ""));
++
++#ifdef CONFIG_ARCH_AT91RM9200
++ /* AT91RM9200 SDRAM low-power mode cannot be used with self-refresh. */
+ at91_sys_write(AT91_SDRAMC_LPR, 0);
++#endif
+
+ suspend_set_ops(&at91_pm_ops);
+
++ show_reset_status();
+ return 0;
+ }
+ arch_initcall(at91_pm_init);
+diff --git a/arch/arm/mach-clps711x/Kconfig b/arch/arm/mach-clps711x/Kconfig
+index 0e2b641..dbaae5f 100644
+--- a/arch/arm/mach-clps711x/Kconfig
++++ b/arch/arm/mach-clps711x/Kconfig
+@@ -31,6 +31,8 @@ config ARCH_EDB7211
+ bool "EDB7211"
+ select ISA
+ select ARCH_DISCONTIGMEM_ENABLE
++ select ARCH_SPARSEMEM_ENABLE
++ select ARCH_SELECT_MEMORY_MODEL
+ help
+ Say Y here if you intend to run this kernel on a Cirrus Logic EDB-7211
+ evaluation board.
+diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
+index 0ecf997..c1252ca 100644
+--- a/arch/arm/mach-ep93xx/Makefile
++++ b/arch/arm/mach-ep93xx/Makefile
+@@ -1,7 +1,7 @@
+ #
+ # Makefile for the linux kernel.
+ #
+-obj-y := core.o clock.o
++obj-y := core.o clock.o gpio.o
+ obj-m :=
+ obj-n :=
+ obj- :=
+diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
+index 91f6a07..8bc1872 100644
+--- a/arch/arm/mach-ep93xx/core.c
++++ b/arch/arm/mach-ep93xx/core.c
+@@ -159,7 +159,7 @@ static const u8 int_type2_register_offset[3] = { 0x94, 0xb0, 0x50 };
+ static const u8 eoi_register_offset[3] = { 0x98, 0xb4, 0x54 };
+ static const u8 int_en_register_offset[3] = { 0x9c, 0xb8, 0x5c };
+
+-static void update_gpio_int_params(unsigned port)
++void ep93xx_gpio_update_int_params(unsigned port)
+ {
+ BUG_ON(port > 2);
+
+@@ -175,98 +175,10 @@ static void update_gpio_int_params(unsigned port)
+ EP93XX_GPIO_REG(int_en_register_offset[port]));
+ }
+
+-/* Port ordering is: A B F D E C G H */
+-static const u8 data_register_offset[8] = {
+- 0x00, 0x04, 0x30, 0x0c, 0x20, 0x08, 0x38, 0x40,
+-};
+-
+-static const u8 data_direction_register_offset[8] = {
+- 0x10, 0x14, 0x34, 0x1c, 0x24, 0x18, 0x3c, 0x44,
+-};
+-
+-#define GPIO_IN 0
+-#define GPIO_OUT 1
+-
+-static void ep93xx_gpio_set_direction(unsigned line, int direction)
+-{
+- unsigned int data_direction_register;
+- unsigned long flags;
+- unsigned char v;
+-
+- data_direction_register =
+- EP93XX_GPIO_REG(data_direction_register_offset[line >> 3]);
+-
+- local_irq_save(flags);
+- if (direction == GPIO_OUT) {
+- if (line >= 0 && line <= EP93XX_GPIO_LINE_MAX_IRQ) {
+- /* Port A/B/F */
+- gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
+- update_gpio_int_params(line >> 3);
+- }
+-
+- v = __raw_readb(data_direction_register);
+- v |= 1 << (line & 7);
+- __raw_writeb(v, data_direction_register);
+- } else if (direction == GPIO_IN) {
+- v = __raw_readb(data_direction_register);
+- v &= ~(1 << (line & 7));
+- __raw_writeb(v, data_direction_register);
+- }
+- local_irq_restore(flags);
+-}
+-
+-int gpio_direction_input(unsigned gpio)
+-{
+- if (gpio > EP93XX_GPIO_LINE_MAX)
+- return -EINVAL;
+-
+- ep93xx_gpio_set_direction(gpio, GPIO_IN);
+-
+- return 0;
+-}
+-EXPORT_SYMBOL(gpio_direction_input);
+-
+-int gpio_direction_output(unsigned gpio, int value)
+-{
+- if (gpio > EP93XX_GPIO_LINE_MAX)
+- return -EINVAL;
+-
+- gpio_set_value(gpio, value);
+- ep93xx_gpio_set_direction(gpio, GPIO_OUT);
+-
+- return 0;
+-}
+-EXPORT_SYMBOL(gpio_direction_output);
+-
+-int gpio_get_value(unsigned gpio)
+-{
+- unsigned int data_register;
+-
+- data_register = EP93XX_GPIO_REG(data_register_offset[gpio >> 3]);
+-
+- return !!(__raw_readb(data_register) & (1 << (gpio & 7)));
+-}
+-EXPORT_SYMBOL(gpio_get_value);
+-
+-void gpio_set_value(unsigned gpio, int value)
++void ep93xx_gpio_int_mask(unsigned line)
+ {
+- unsigned int data_register;
+- unsigned long flags;
+- unsigned char v;
+-
+- data_register = EP93XX_GPIO_REG(data_register_offset[gpio >> 3]);
+-
+- local_irq_save(flags);
+- v = __raw_readb(data_register);
+- if (value)
+- v |= 1 << (gpio & 7);
+- else
+- v &= ~(1 << (gpio & 7));
+- __raw_writeb(v, data_register);
+- local_irq_restore(flags);
++ gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
+ }
+-EXPORT_SYMBOL(gpio_set_value);
+-
+
+ /*************************************************************************
+ * EP93xx IRQ handling
+@@ -316,7 +228,7 @@ static void ep93xx_gpio_irq_ack(unsigned int irq)
+
+ if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQT_BOTHEDGE) {
+ gpio_int_type2[port] ^= port_mask; /* switch edge direction */
+- update_gpio_int_params(port);
++ ep93xx_gpio_update_int_params(port);
+ }
+
+ __raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
+@@ -332,7 +244,7 @@ static void ep93xx_gpio_irq_mask_ack(unsigned int irq)
+ gpio_int_type2[port] ^= port_mask; /* switch edge direction */
+
+ gpio_int_unmasked[port] &= ~port_mask;
+- update_gpio_int_params(port);
++ ep93xx_gpio_update_int_params(port);
+
+ __raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
+ }
+@@ -343,7 +255,7 @@ static void ep93xx_gpio_irq_mask(unsigned int irq)
+ int port = line >> 3;
+
+ gpio_int_unmasked[port] &= ~(1 << (line & 7));
+- update_gpio_int_params(port);
++ ep93xx_gpio_update_int_params(port);
+ }
+
+ static void ep93xx_gpio_irq_unmask(unsigned int irq)
+@@ -352,7 +264,7 @@ static void ep93xx_gpio_irq_unmask(unsigned int irq)
+ int port = line >> 3;
+
+ gpio_int_unmasked[port] |= 1 << (line & 7);
+- update_gpio_int_params(port);
++ ep93xx_gpio_update_int_params(port);
+ }
+
+
+@@ -368,7 +280,7 @@ static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
+ const int port = gpio >> 3;
+ const int port_mask = 1 << (gpio & 7);
+
+- ep93xx_gpio_set_direction(gpio, GPIO_IN);
++ gpio_direction_output(gpio, gpio_get_value(gpio));
+
+ switch (type) {
+ case IRQT_RISING:
+@@ -411,7 +323,7 @@ static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
+ desc->status &= ~IRQ_TYPE_SENSE_MASK;
+ desc->status |= type & IRQ_TYPE_SENSE_MASK;
+
+- update_gpio_int_params(port);
++ ep93xx_gpio_update_int_params(port);
+
+ return 0;
+ }
+@@ -549,6 +461,7 @@ static struct platform_device ep93xx_ohci_device = {
+ .resource = ep93xx_ohci_resources,
+ };
+
++extern void ep93xx_gpio_init(void);
+
+ void __init ep93xx_init_devices(void)
+ {
+@@ -562,6 +475,8 @@ void __init ep93xx_init_devices(void)
+ __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK);
+ __raw_writel(v, EP93XX_SYSCON_DEVICE_CONFIG);
+
++ ep93xx_gpio_init();
++
+ amba_device_register(&uart1_device, &iomem_resource);
+ amba_device_register(&uart2_device, &iomem_resource);
+ amba_device_register(&uart3_device, &iomem_resource);
+diff --git a/arch/arm/mach-ep93xx/gpio.c b/arch/arm/mach-ep93xx/gpio.c
+new file mode 100644
+index 0000000..dc2e4c0
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/gpio.c
+@@ -0,0 +1,158 @@
++/*
++ * linux/arch/arm/mach-ep93xx/gpio.c
++ *
++ * Generic EP93xx GPIO handling
++ *
++ * Copyright (c) 2008 Ryan Mallon <ryan at bluewatersys.com>
++ *
++ * Based on code originally from:
++ * linux/arch/arm/mach-ep93xx/core.c
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/seq_file.h>
++
++#include <asm/arch/ep93xx-regs.h>
++#include <asm/io.h>
++#include <asm/gpio.h>
++
++struct ep93xx_gpio_chip {
++ struct gpio_chip chip;
++
++ unsigned int data_reg;
++ unsigned int data_dir_reg;
++};
++
++#define to_ep93xx_gpio_chip(c) container_of(c, struct ep93xx_gpio_chip, chip)
++
++/* From core.c */
++extern void ep93xx_gpio_int_mask(unsigned line);
++extern void ep93xx_gpio_update_int_params(unsigned port);
++
++static int ep93xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
++{
++ struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
++ unsigned long flags;
++ u8 v;
++
++ local_irq_save(flags);
++ v = __raw_readb(ep93xx_chip->data_dir_reg);
++ v &= ~(1 << offset);
++ __raw_writeb(v, ep93xx_chip->data_dir_reg);
++ local_irq_restore(flags);
++
++ return 0;
++}
++
++static int ep93xx_gpio_direction_output(struct gpio_chip *chip,
++ unsigned offset, int val)
++{
++ struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
++ unsigned long flags;
++ int line;
++ u8 v;
++
++ local_irq_save(flags);
++
++ /* Set the value */
++ v = __raw_readb(ep93xx_chip->data_reg);
++ if (val)
++ v |= (1 << offset);
++ else
++ v &= ~(1 << offset);
++ __raw_writeb(v, ep93xx_chip->data_reg);
++
++ /* Drive as an output */
++ line = chip->base + offset;
++ if (line <= EP93XX_GPIO_LINE_MAX_IRQ) {
++ /* Ports A/B/F */
++ ep93xx_gpio_int_mask(line);
++ ep93xx_gpio_update_int_params(line >> 3);
++ }
++
++ v = __raw_readb(ep93xx_chip->data_dir_reg);
++ v |= (1 << offset);
++ __raw_writeb(v, ep93xx_chip->data_dir_reg);
++
++ local_irq_restore(flags);
++
++ return 0;
++}
++
++static int ep93xx_gpio_get(struct gpio_chip *chip, unsigned offset)
++{
++ struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
++
++ return !!(__raw_readb(ep93xx_chip->data_reg) & (1 << offset));
++}
++
++static void ep93xx_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
++{
++ struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
++ unsigned long flags;
++ u8 v;
++
++ local_irq_save(flags);
++ v = __raw_readb(ep93xx_chip->data_reg);
++ if (val)
++ v |= (1 << offset);
++ else
++ v &= ~(1 << offset);
++ __raw_writeb(v, ep93xx_chip->data_reg);
++ local_irq_restore(flags);
++}
++
++static void ep93xx_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
++{
++ struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
++ u8 data_reg, data_dir_reg;
++ int i;
++
++ data_reg = __raw_readb(ep93xx_chip->data_reg);
++ data_dir_reg = __raw_readb(ep93xx_chip->data_dir_reg);
++
++ for (i = 0; i < chip->ngpio; i++)
++ seq_printf(s, "GPIO %s%d: %s %s\n", chip->label, i,
++ (data_reg & (1 << i)) ? "set" : "clear",
++ (data_dir_reg & (1 << i)) ? "out" : "in");
++}
++
++#define EP93XX_GPIO_BANK(name, dr, ddr, base_gpio) \
++ { \
++ .chip = { \
++ .label = name, \
++ .direction_input = ep93xx_gpio_direction_input, \
++ .direction_output = ep93xx_gpio_direction_output, \
++ .get = ep93xx_gpio_get, \
++ .set = ep93xx_gpio_set, \
++ .dbg_show = ep93xx_gpio_dbg_show, \
++ .base = base_gpio, \
++ .ngpio = 8, \
++ }, \
++ .data_reg = EP93XX_GPIO_REG(dr), \
++ .data_dir_reg = EP93XX_GPIO_REG(ddr), \
++ }
++
++static struct ep93xx_gpio_chip ep93xx_gpio_banks[] = {
++ EP93XX_GPIO_BANK("A", 0x00, 0x10, 0),
++ EP93XX_GPIO_BANK("B", 0x04, 0x14, 8),
++ EP93XX_GPIO_BANK("C", 0x30, 0x34, 40),
++ EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 24),
++ EP93XX_GPIO_BANK("E", 0x20, 0x24, 32),
++ EP93XX_GPIO_BANK("F", 0x08, 0x18, 16),
++ EP93XX_GPIO_BANK("G", 0x38, 0x3c, 48),
++ EP93XX_GPIO_BANK("H", 0x40, 0x44, 56),
++};
++
++void __init ep93xx_gpio_init(void)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++)
++ gpiochip_add(&ep93xx_gpio_banks[i].chip);
++}
+diff --git a/arch/arm/mach-integrator/clock.c b/arch/arm/mach-integrator/clock.c
+index 95a1e26..8d761fd 100644
+--- a/arch/arm/mach-integrator/clock.c
++++ b/arch/arm/mach-integrator/clock.c
+@@ -17,7 +17,6 @@
+ #include <linux/clk.h>
+ #include <linux/mutex.h>
+
+-#include <asm/semaphore.h>
+ #include <asm/hardware/icst525.h>
+
+ #include "clock.h"
+diff --git a/arch/arm/mach-integrator/time.c b/arch/arm/mach-integrator/time.c
+index 5278f58..8508a0d 100644
+--- a/arch/arm/mach-integrator/time.c
++++ b/arch/arm/mach-integrator/time.c
+@@ -124,6 +124,9 @@ static int rtc_probe(struct amba_device *dev, void *id)
+
+ xtime.tv_sec = __raw_readl(rtc_base + RTC_DR);
+
++ /* note that 'dev' is merely used for irq disambiguation;
++ * it is not actually referenced in the irq handler
++ */
+ ret = request_irq(dev->irq[0], arm_rtc_interrupt, IRQF_DISABLED,
+ "rtc-pl030", dev);
+ if (ret)
+diff --git a/arch/arm/mach-iop32x/Kconfig b/arch/arm/mach-iop32x/Kconfig
+index dbe07c9..5e8c6f7 100644
+--- a/arch/arm/mach-iop32x/Kconfig
++++ b/arch/arm/mach-iop32x/Kconfig
+@@ -34,14 +34,6 @@ config MACH_N2100
+ Say Y here if you want to run your kernel on the Thecus n2100
+ NAS appliance.
+
+-config IOP3XX_ATU
+- bool "Enable the PCI Controller"
+- default y
+- help
+- Say Y here if you want the IOP to initialize its PCI Controller.
+- Say N if the IOP is an add in card, the host system owns the PCI
+- bus in this case.
+-
+ config MACH_EM7210
+ bool "Enable support for the Lanner EM7210"
+ help
+diff --git a/arch/arm/mach-iop32x/iq31244.c b/arch/arm/mach-iop32x/iq31244.c
+index 98cfa1c..4a89823 100644
+--- a/arch/arm/mach-iop32x/iq31244.c
++++ b/arch/arm/mach-iop32x/iq31244.c
+@@ -178,10 +178,9 @@ static struct hw_pci iq31244_pci __initdata = {
+
+ static int __init iq31244_pci_init(void)
+ {
+- if (is_ep80219()) {
+- if (iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE)
+- pci_common_init(&ep80219_pci);
+- } else if (machine_is_iq31244()) {
++ if (is_ep80219())
++ pci_common_init(&ep80219_pci);
++ else if (machine_is_iq31244()) {
+ if (is_80219()) {
+ printk("note: iq31244 board type has been selected\n");
+ printk("note: to select ep80219 operation:\n");
+@@ -190,9 +189,7 @@ static int __init iq31244_pci_init(void)
+ printk("\t2/ update boot loader to pass"
+ " the ep80219 id: %d\n", MACH_TYPE_EP80219);
+ }
+-
+- if (iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE)
+- pci_common_init(&iq31244_pci);
++ pci_common_init(&iq31244_pci);
+ }
+
+ return 0;
+diff --git a/arch/arm/mach-iop32x/iq80321.c b/arch/arm/mach-iop32x/iq80321.c
+index 18ad29f..1da3c91 100644
+--- a/arch/arm/mach-iop32x/iq80321.c
++++ b/arch/arm/mach-iop32x/iq80321.c
+@@ -106,7 +106,7 @@ static struct hw_pci iq80321_pci __initdata = {
+ .swizzle = pci_std_swizzle,
+ .nr_controllers = 1,
+ .setup = iop3xx_pci_setup,
+- .preinit = iop3xx_pci_preinit,
++ .preinit = iop3xx_pci_preinit_cond,
+ .scan = iop3xx_pci_scan_bus,
+ .map_irq = iq80321_pci_map_irq,
+ };
+diff --git a/arch/arm/mach-iop33x/Kconfig b/arch/arm/mach-iop33x/Kconfig
+index 45598e0..9aa016b 100644
+--- a/arch/arm/mach-iop33x/Kconfig
++++ b/arch/arm/mach-iop33x/Kconfig
+@@ -16,14 +16,6 @@ config MACH_IQ80332
+ Say Y here if you want to run your kernel on the Intel IQ80332
+ evaluation kit for the IOP332 chipset.
+
+-config IOP3XX_ATU
+- bool "Enable the PCI Controller"
+- default y
+- help
+- Say Y here if you want the IOP to initialize its PCI Controller.
+- Say N if the IOP is an add in card, the host system owns the PCI
+- bus in this case.
+-
+ endmenu
+
+ endif
+diff --git a/arch/arm/mach-iop33x/iq80331.c b/arch/arm/mach-iop33x/iq80331.c
+index 433188e..de39fd7 100644
+--- a/arch/arm/mach-iop33x/iq80331.c
++++ b/arch/arm/mach-iop33x/iq80331.c
+@@ -89,7 +89,7 @@ static struct hw_pci iq80331_pci __initdata = {
+ .swizzle = pci_std_swizzle,
+ .nr_controllers = 1,
+ .setup = iop3xx_pci_setup,
+- .preinit = iop3xx_pci_preinit,
++ .preinit = iop3xx_pci_preinit_cond,
+ .scan = iop3xx_pci_scan_bus,
+ .map_irq = iq80331_pci_map_irq,
+ };
+diff --git a/arch/arm/mach-iop33x/iq80332.c b/arch/arm/mach-iop33x/iq80332.c
+index 416c095..4904fd7 100644
+--- a/arch/arm/mach-iop33x/iq80332.c
++++ b/arch/arm/mach-iop33x/iq80332.c
+@@ -89,7 +89,7 @@ static struct hw_pci iq80332_pci __initdata = {
+ .swizzle = pci_std_swizzle,
+ .nr_controllers = 1,
+ .setup = iop3xx_pci_setup,
+- .preinit = iop3xx_pci_preinit,
++ .preinit = iop3xx_pci_preinit_cond,
+ .scan = iop3xx_pci_scan_bus,
+ .map_irq = iq80332_pci_map_irq,
+ };
+diff --git a/arch/arm/mach-ks8695/Makefile b/arch/arm/mach-ks8695/Makefile
+index 730a3af..ade42b7 100644
+--- a/arch/arm/mach-ks8695/Makefile
++++ b/arch/arm/mach-ks8695/Makefile
+@@ -11,5 +11,8 @@ obj- :=
+ # PCI support is optional
+ obj-$(CONFIG_PCI) += pci.o
+
++# LEDs
++obj-$(CONFIG_LEDS) += leds.o
++
+ # Board-specific support
+ obj-$(CONFIG_MACH_KS8695) += board-micrel.o
+diff --git a/arch/arm/mach-ks8695/devices.c b/arch/arm/mach-ks8695/devices.c
+index 386593f..3db2ec6 100644
+--- a/arch/arm/mach-ks8695/devices.c
++++ b/arch/arm/mach-ks8695/devices.c
+@@ -176,6 +176,27 @@ static void __init ks8695_add_device_watchdog(void) {}
+ #endif
+
+
++/* --------------------------------------------------------------------
++ * LEDs
++ * -------------------------------------------------------------------- */
++
++#if defined(CONFIG_LEDS)
++short ks8695_leds_cpu = -1;
++short ks8695_leds_timer = -1;
++
++void __init ks8695_init_leds(u8 cpu_led, u8 timer_led)
++{
++ /* Enable GPIO to access the LEDs */
++ gpio_direction_output(cpu_led, 1);
++ gpio_direction_output(timer_led, 1);
++
++ ks8695_leds_cpu = cpu_led;
++ ks8695_leds_timer = timer_led;
++}
++#else
++void __init ks8695_init_leds(u8 cpu_led, u8 timer_led) {}
++#endif
++
+ /* -------------------------------------------------------------------- */
+
+ /*
+diff --git a/arch/arm/mach-ks8695/leds.c b/arch/arm/mach-ks8695/leds.c
+new file mode 100644
+index 0000000..d61762a
+--- /dev/null
++++ b/arch/arm/mach-ks8695/leds.c
+@@ -0,0 +1,94 @@
++/*
++ * LED driver for KS8695-based boards.
++ *
++ * Copyright (C) Andrew Victor
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++
++#include <asm/mach-types.h>
++#include <asm/leds.h>
++#include <asm/arch/devices.h>
++#include <asm/arch/gpio.h>
++
++
++static inline void ks8695_led_on(unsigned int led)
++{
++ gpio_set_value(led, 0);
++}
++
++static inline void ks8695_led_off(unsigned int led)
++{
++ gpio_set_value(led, 1);
++}
++
++static inline void ks8695_led_toggle(unsigned int led)
++{
++ unsigned long is_off = gpio_get_value(led);
++ if (is_off)
++ ks8695_led_on(led);
++ else
++ ks8695_led_off(led);
++}
++
++
++/*
++ * Handle LED events.
++ */
++static void ks8695_leds_event(led_event_t evt)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++
++ switch(evt) {
++ case led_start: /* System startup */
++ ks8695_led_on(ks8695_leds_cpu);
++ break;
++
++ case led_stop: /* System stop / suspend */
++ ks8695_led_off(ks8695_leds_cpu);
++ break;
++
++#ifdef CONFIG_LEDS_TIMER
++ case led_timer: /* Every 50 timer ticks */
++ ks8695_led_toggle(ks8695_leds_timer);
++ break;
++#endif
++
++#ifdef CONFIG_LEDS_CPU
++ case led_idle_start: /* Entering idle state */
++ ks8695_led_off(ks8695_leds_cpu);
++ break;
++
++ case led_idle_end: /* Exit idle state */
++ ks8695_led_on(ks8695_leds_cpu);
++ break;
++#endif
++
++ default:
++ break;
++ }
++
++ local_irq_restore(flags);
++}
++
++
++static int __init leds_init(void)
++{
++ if ((ks8695_leds_timer == -1) || (ks8695_leds_cpu == -1))
++ return -ENODEV;
++
++ leds_event = ks8695_leds_event;
++
++ leds_event(led_start);
++ return 0;
++}
++
++__initcall(leds_init);
+diff --git a/arch/arm/mach-lh7a40x/arch-kev7a400.c b/arch/arm/mach-lh7a40x/arch-kev7a400.c
+index 6d26661..2ef7d00 100644
+--- a/arch/arm/mach-lh7a40x/arch-kev7a400.c
++++ b/arch/arm/mach-lh7a40x/arch-kev7a400.c
+@@ -75,10 +75,9 @@ static void kev7a400_cpld_handler (unsigned int irq, struct irq_desc *desc)
+ {
+ u32 mask = CPLD_LATCHED_INTS;
+ irq = IRQ_KEV7A400_CPLD;
+- for (; mask; mask >>= 1, ++irq) {
++ for (; mask; mask >>= 1, ++irq)
+ if (mask & 1)
+- desc[irq].handle (irq, desc);
+- }
++ desc_handle_irq(irq, desc);
+ }
+
+ void __init lh7a40x_init_board_irq (void)
+diff --git a/arch/arm/mach-ns9xxx/Kconfig b/arch/arm/mach-ns9xxx/Kconfig
+index 8584ed1..dd0cd5a 100644
+--- a/arch/arm/mach-ns9xxx/Kconfig
++++ b/arch/arm/mach-ns9xxx/Kconfig
+@@ -2,9 +2,26 @@ if ARCH_NS9XXX
+
+ menu "NS9xxx Implementations"
+
++config NS9XXX_HAVE_SERIAL8250
++ bool
++
++config PROCESSOR_NS9360
++ bool
++
++config MODULE_CC9P9360
++ bool
++ select PROCESSOR_NS9360
++
++config BOARD_A9M9750DEV
++ select NS9XXX_HAVE_SERIAL8250
++ bool
++
++config BOARD_JSCC9P9360
++ bool
++
+ config MACH_CC9P9360DEV
+ bool "ConnectCore 9P 9360 on an A9M9750 Devboard"
+- select PROCESSOR_NS9360
++ select MODULE_CC9P9360
+ select BOARD_A9M9750DEV
+ help
+ Say Y here if you are using the Digi ConnectCore 9P 9360
+@@ -12,21 +29,12 @@ config MACH_CC9P9360DEV
+
+ config MACH_CC9P9360JS
+ bool "ConnectCore 9P 9360 on a JSCC9P9360 Devboard"
+- select PROCESSOR_NS9360
++ select MODULE_CC9P9360
+ select BOARD_JSCC9P9360
+ help
+ Say Y here if you are using the Digi ConnectCore 9P 9360
+ on an JSCC9P9360 Development Board.
+
+-config PROCESSOR_NS9360
+- bool
+-
+-config BOARD_A9M9750DEV
+- bool
+-
+-config BOARD_JSCC9P9360
+- bool
+-
+ endmenu
+
+ endif
+diff --git a/arch/arm/mach-ns9xxx/Makefile b/arch/arm/mach-ns9xxx/Makefile
+index 6fb82b8..41efaf9 100644
+--- a/arch/arm/mach-ns9xxx/Makefile
++++ b/arch/arm/mach-ns9xxx/Makefile
+@@ -1,7 +1,12 @@
+-obj-y := irq.o time.o generic.o gpio.o
++obj-y := clock.o generic.o gpio.o irq.o
+
+ obj-$(CONFIG_MACH_CC9P9360DEV) += mach-cc9p9360dev.o
+ obj-$(CONFIG_MACH_CC9P9360JS) += mach-cc9p9360js.o
+
++obj-$(CONFIG_PROCESSOR_NS9360) += gpio-ns9360.o processor-ns9360.o time-ns9360.o
++
+ obj-$(CONFIG_BOARD_A9M9750DEV) += board-a9m9750dev.o
+ obj-$(CONFIG_BOARD_JSCC9P9360) += board-jscc9p9360.o
++
++# platform devices
++obj-$(CONFIG_NS9XXX_HAVE_SERIAL8250) += plat-serial8250.o
+diff --git a/arch/arm/mach-ns9xxx/Makefile.boot b/arch/arm/mach-ns9xxx/Makefile.boot
+index 75ed64e..5465491 100644
+--- a/arch/arm/mach-ns9xxx/Makefile.boot
++++ b/arch/arm/mach-ns9xxx/Makefile.boot
+@@ -1,2 +1,2 @@
+-zreladdr-y := 0x108000
++zreladdr-y := 0x8000
+ params_phys-y := 0x100
+diff --git a/arch/arm/mach-ns9xxx/board-a9m9750dev.c b/arch/arm/mach-ns9xxx/board-a9m9750dev.c
+index 0f65177..a494b71 100644
+--- a/arch/arm/mach-ns9xxx/board-a9m9750dev.c
++++ b/arch/arm/mach-ns9xxx/board-a9m9750dev.c
+@@ -8,15 +8,14 @@
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+-#include <linux/platform_device.h>
+-#include <linux/serial_8250.h>
+ #include <linux/irq.h>
+
+ #include <asm/mach/map.h>
+ #include <asm/gpio.h>
+
+ #include <asm/arch-ns9xxx/board.h>
+-#include <asm/arch-ns9xxx/regs-sys.h>
++#include <asm/arch-ns9xxx/processor-ns9360.h>
++#include <asm/arch-ns9xxx/regs-sys-ns9360.h>
+ #include <asm/arch-ns9xxx/regs-mem.h>
+ #include <asm/arch-ns9xxx/regs-bbu.h>
+ #include <asm/arch-ns9xxx/regs-board-a9m9750dev.h>
+@@ -105,9 +104,9 @@ void __init board_a9m9750dev_init_irq(void)
+ int i;
+
+ if (gpio_request(11, "board a9m9750dev extirq2") == 0)
+- ns9xxx_gpio_configure(11, 0, 1);
++ ns9360_gpio_configure(11, 0, 1);
+ else
+- printk(KERN_ERR "%s: cannot get gpio 11 for IRQ_EXT2\n",
++ printk(KERN_ERR "%s: cannot get gpio 11 for IRQ_NS9XXX_EXT2\n",
+ __func__);
+
+ for (i = FPGA_IRQ(0); i <= FPGA_IRQ(7); ++i) {
+@@ -116,69 +115,16 @@ void __init board_a9m9750dev_init_irq(void)
+ set_irq_flags(i, IRQF_VALID);
+ }
+
+- /* IRQ_EXT2: level sensitive + active low */
++ /* IRQ_NS9XXX_EXT2: level sensitive + active low */
+ eic = __raw_readl(SYS_EIC(2));
+ REGSET(eic, SYS_EIC, PLTY, AL);
+ REGSET(eic, SYS_EIC, LVEDG, LEVEL);
+ __raw_writel(eic, SYS_EIC(2));
+
+- set_irq_chained_handler(IRQ_EXT2,
++ set_irq_chained_handler(IRQ_NS9XXX_EXT2,
+ a9m9750dev_fpga_demux_handler);
+ }
+
+-static struct plat_serial8250_port board_a9m9750dev_serial8250_port[] = {
+- {
+- .iobase = FPGA_UARTA_BASE,
+- .membase = (unsigned char*)FPGA_UARTA_BASE,
+- .mapbase = FPGA_UARTA_BASE,
+- .irq = IRQ_FPGA_UARTA,
+- .iotype = UPIO_MEM,
+- .uartclk = 18432000,
+- .regshift = 0,
+- .flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
+- }, {
+- .iobase = FPGA_UARTB_BASE,
+- .membase = (unsigned char*)FPGA_UARTB_BASE,
+- .mapbase = FPGA_UARTB_BASE,
+- .irq = IRQ_FPGA_UARTB,
+- .iotype = UPIO_MEM,
+- .uartclk = 18432000,
+- .regshift = 0,
+- .flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
+- }, {
+- .iobase = FPGA_UARTC_BASE,
+- .membase = (unsigned char*)FPGA_UARTC_BASE,
+- .mapbase = FPGA_UARTC_BASE,
+- .irq = IRQ_FPGA_UARTC,
+- .iotype = UPIO_MEM,
+- .uartclk = 18432000,
+- .regshift = 0,
+- .flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
+- }, {
+- .iobase = FPGA_UARTD_BASE,
+- .membase = (unsigned char*)FPGA_UARTD_BASE,
+- .mapbase = FPGA_UARTD_BASE,
+- .irq = IRQ_FPGA_UARTD,
+- .iotype = UPIO_MEM,
+- .uartclk = 18432000,
+- .regshift = 0,
+- .flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
+- }, {
+- /* end marker */
+- },
+-};
+-
+-static struct platform_device board_a9m9750dev_serial_device = {
+- .name = "serial8250",
+- .dev = {
+- .platform_data = board_a9m9750dev_serial8250_port,
+- },
+-};
+-
+-static struct platform_device *board_a9m9750dev_devices[] __initdata = {
+- &board_a9m9750dev_serial_device,
+-};
+-
+ void __init board_a9m9750dev_init_machine(void)
+ {
+ u32 reg;
+@@ -210,7 +156,4 @@ void __init board_a9m9750dev_init_machine(void)
+ __raw_writel(0x2, MEM_SMOED(0));
+ __raw_writel(0x6, MEM_SMRD(0));
+ __raw_writel(0x6, MEM_SMWD(0));
+-
+- platform_add_devices(board_a9m9750dev_devices,
+- ARRAY_SIZE(board_a9m9750dev_devices));
+ }
+diff --git a/arch/arm/mach-ns9xxx/clock.c b/arch/arm/mach-ns9xxx/clock.c
+new file mode 100644
+index 0000000..f863916
+--- /dev/null
++++ b/arch/arm/mach-ns9xxx/clock.c
+@@ -0,0 +1,215 @@
++/*
++ * arch/arm/mach-ns9xxx/clock.c
++ *
++ * Copyright (C) 2007 by Digi International Inc.
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ */
++#include <linux/err.h>
++#include <linux/module.h>
++#include <linux/list.h>
++#include <linux/clk.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++
++#include <asm/semaphore.h>
++#include "clock.h"
++
++static LIST_HEAD(clocks);
++static DEFINE_SPINLOCK(clk_lock);
++
++struct clk *clk_get(struct device *dev, const char *id)
++{
++ struct clk *p, *ret = NULL, *retgen = NULL;
++ unsigned long flags;
++ int idno;
++
++ if (dev == NULL || dev->bus != &platform_bus_type)
++ idno = -1;
++ else
++ idno = to_platform_device(dev)->id;
++
++ spin_lock_irqsave(&clk_lock, flags);
++ list_for_each_entry(p, &clocks, node) {
++ if (strcmp(id, p->name) == 0) {
++ if (p->id == idno) {
++ if (!try_module_get(p->owner))
++ continue;
++ ret = p;
++ break;
++ } else if (p->id == -1)
++ /* remember match with id == -1 in case there is
++ * no clock for idno */
++ retgen = p;
++ }
++ }
++
++ if (!ret && retgen && try_module_get(retgen->owner))
++ ret = retgen;
++
++ if (ret)
++ ++ret->refcount;
++
++ spin_unlock_irqrestore(&clk_lock, flags);
++
++ return ret ? ret : ERR_PTR(-ENOENT);
++}
++EXPORT_SYMBOL(clk_get);
++
++void clk_put(struct clk *clk)
++{
++ module_put(clk->owner);
++ --clk->refcount;
++}
++EXPORT_SYMBOL(clk_put);
++
++static int clk_enable_unlocked(struct clk *clk)
++{
++ int ret = 0;
++ if (clk->parent) {
++ ret = clk_enable_unlocked(clk->parent);
++ if (ret)
++ return ret;
++ }
++
++ if (clk->usage++ == 0 && clk->endisable)
++ ret = clk->endisable(clk, 1);
++
++ return ret;
++}
++
++int clk_enable(struct clk *clk)
++{
++ int ret;
++ unsigned long flags;
++
++ spin_lock_irqsave(&clk_lock, flags);
++
++ ret = clk_enable_unlocked(clk);
++
++ spin_unlock_irqrestore(&clk_lock, flags);
++
++ return ret;
++}
++EXPORT_SYMBOL(clk_enable);
++
++static void clk_disable_unlocked(struct clk *clk)
++{
++ if (--clk->usage == 0 && clk->endisable)
++ clk->endisable(clk, 0);
++
++ if (clk->parent)
++ clk_disable_unlocked(clk->parent);
++}
++
++void clk_disable(struct clk *clk)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&clk_lock, flags);
++
++ clk_disable_unlocked(clk);
++
++ spin_unlock_irqrestore(&clk_lock, flags);
++}
++EXPORT_SYMBOL(clk_disable);
++
++unsigned long clk_get_rate(struct clk *clk)
++{
++ if (clk->get_rate)
++ return clk->get_rate(clk);
++
++ if (clk->rate)
++ return clk->rate;
++
++ if (clk->parent)
++ return clk_get_rate(clk->parent);
++
++ return 0;
++}
++EXPORT_SYMBOL(clk_get_rate);
++
++int clk_register(struct clk *clk)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&clk_lock, flags);
++
++ list_add(&clk->node, &clocks);
++
++ if (clk->parent)
++ ++clk->parent->refcount;
++
++ spin_unlock_irqrestore(&clk_lock, flags);
++
++ return 0;
++}
++
++int clk_unregister(struct clk *clk)
++{
++ int ret = 0;
++ unsigned long flags;
++
++ spin_lock_irqsave(&clk_lock, flags);
++
++ if (clk->usage || clk->refcount)
++ ret = -EBUSY;
++ else
++ list_del(&clk->node);
++
++ if (clk->parent)
++ --clk->parent->refcount;
++
++ spin_unlock_irqrestore(&clk_lock, flags);
++
++ return ret;
++}
++
++#if defined CONFIG_DEBUG_FS
++
++#include <linux/debugfs.h>
++#include <linux/seq_file.h>
++
++static int clk_debugfs_show(struct seq_file *s, void *null)
++{
++ unsigned long flags;
++ struct clk *p;
++
++ spin_lock_irqsave(&clk_lock, flags);
++
++ list_for_each_entry(p, &clocks, node)
++ seq_printf(s, "%s.%d: usage=%lu refcount=%lu rate=%lu\n",
++ p->name, p->id, p->usage, p->refcount,
++ p->usage ? clk_get_rate(p) : 0);
++
++ spin_unlock_irqrestore(&clk_lock, flags);
++
++ return 0;
++}
++
++static int clk_debugfs_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, clk_debugfs_show, NULL);
++}
++
++static struct file_operations clk_debugfs_operations = {
++ .open = clk_debugfs_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static int __init clk_debugfs_init(void)
++{
++ struct dentry *dentry;
++
++ dentry = debugfs_create_file("clk", S_IFREG | S_IRUGO, NULL, NULL,
++ &clk_debugfs_operations);
++ return IS_ERR(dentry) ? PTR_ERR(dentry) : 0;
++}
++subsys_initcall(clk_debugfs_init);
++
++#endif /* if defined CONFIG_DEBUG_FS */
+diff --git a/arch/arm/mach-ns9xxx/clock.h b/arch/arm/mach-ns9xxx/clock.h
+new file mode 100644
+index 0000000..b86c30d
+--- /dev/null
++++ b/arch/arm/mach-ns9xxx/clock.h
+@@ -0,0 +1,35 @@
++/*
++ * arch/arm/mach-ns9xxx/clock.h
++ *
++ * Copyright (C) 2007 by Digi International Inc.
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ */
++#ifndef __NS9XXX_CLOCK_H
++#define __NS9XXX_CLOCK_H
++
++#include <linux/list.h>
++
++struct clk {
++ struct module *owner;
++ const char *name;
++ int id;
++
++ struct clk *parent;
++
++ unsigned long rate;
++ int (*endisable)(struct clk *, int enable);
++ unsigned long (*get_rate)(struct clk *);
++
++ struct list_head node;
++ unsigned long refcount;
++ unsigned long usage;
++};
++
++int clk_register(struct clk *clk);
++int clk_unregister(struct clk *clk);
++
++#endif /* ifndef __NS9XXX_CLOCK_H */
+diff --git a/arch/arm/mach-ns9xxx/generic.c b/arch/arm/mach-ns9xxx/generic.c
+index d742c92..1e0f467 100644
+--- a/arch/arm/mach-ns9xxx/generic.c
++++ b/arch/arm/mach-ns9xxx/generic.c
+@@ -1,7 +1,7 @@
+ /*
+ * arch/arm/mach-ns9xxx/generic.c
+ *
+- * Copyright (C) 2006 by Digi International Inc.
++ * Copyright (C) 2006,2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+@@ -11,34 +11,9 @@
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <asm/memory.h>
+-#include <asm/page.h>
+-#include <asm/mach-types.h>
+-#include <asm/mach/map.h>
+-#include <asm/arch-ns9xxx/regs-sys.h>
+-#include <asm/arch-ns9xxx/regs-mem.h>
+-#include <asm/arch-ns9xxx/board.h>
+
+ #include "generic.h"
+
+-static struct map_desc standard_io_desc[] __initdata = {
+- { /* BBus */
+- .virtual = io_p2v(0x90000000),
+- .pfn = __phys_to_pfn(0x90000000),
+- .length = 0x00700000,
+- .type = MT_DEVICE,
+- }, { /* AHB */
+- .virtual = io_p2v(0xa0100000),
+- .pfn = __phys_to_pfn(0xa0100000),
+- .length = 0x00900000,
+- .type = MT_DEVICE,
+- },
+-};
+-
+-void __init ns9xxx_map_io(void)
+-{
+- iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
+-}
+-
+ void __init ns9xxx_init_machine(void)
+ {
+ }
+diff --git a/arch/arm/mach-ns9xxx/generic.h b/arch/arm/mach-ns9xxx/generic.h
+index 687e291..8249319 100644
+--- a/arch/arm/mach-ns9xxx/generic.h
++++ b/arch/arm/mach-ns9xxx/generic.h
+@@ -1,7 +1,7 @@
+ /*
+ * arch/arm/mach-ns9xxx/generic.h
+ *
+- * Copyright (C) 2006 by Digi International Inc.
++ * Copyright (C) 2006,2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+@@ -13,7 +13,4 @@
+ #include <linux/init.h>
+
+ void __init ns9xxx_init_irq(void);
+-void __init ns9xxx_map_io(void);
+ void __init ns9xxx_init_machine(void);
+-
+-extern struct sys_timer ns9xxx_timer;
+diff --git a/arch/arm/mach-ns9xxx/gpio-ns9360.c b/arch/arm/mach-ns9xxx/gpio-ns9360.c
+new file mode 100644
+index 0000000..cabfb87
+--- /dev/null
++++ b/arch/arm/mach-ns9xxx/gpio-ns9360.c
+@@ -0,0 +1,118 @@
++/*
++ * arch/arm/mach-ns9xxx/gpio-ns9360.c
++ *
++ * Copyright (C) 2006,2007 by Digi International Inc.
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ */
++#include <linux/bug.h>
++#include <linux/errno.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++
++#include <asm/arch-ns9xxx/regs-bbu.h>
++#include <asm/arch-ns9xxx/processor-ns9360.h>
++
++#include "gpio-ns9360.h"
++
++static inline int ns9360_valid_gpio(unsigned gpio)
++{
++ return gpio <= 72;
++}
++
++static inline void __iomem *ns9360_gpio_get_gconfaddr(unsigned gpio)
++{
++ if (gpio < 56)
++ return BBU_GCONFb1(gpio / 8);
++ else
++ /*
++ * this could be optimised away on
++ * ns9750 only builds, but it isn't ...
++ */
++ return BBU_GCONFb2((gpio - 56) / 8);
++}
++
++static inline void __iomem *ns9360_gpio_get_gctrladdr(unsigned gpio)
++{
++ if (gpio < 32)
++ return BBU_GCTRL1;
++ else if (gpio < 64)
++ return BBU_GCTRL2;
++ else
++ /* this could be optimised away on ns9750 only builds */
++ return BBU_GCTRL3;
++}
++
++static inline void __iomem *ns9360_gpio_get_gstataddr(unsigned gpio)
++{
++ if (gpio < 32)
++ return BBU_GSTAT1;
++ else if (gpio < 64)
++ return BBU_GSTAT2;
++ else
++ /* this could be optimised away on ns9750 only builds */
++ return BBU_GSTAT3;
++}
++
++/*
++ * each gpio can serve for 4 different purposes [0..3]. These are called
++ * "functions" and passed in the parameter func. Functions 0-2 are always some
++ * special things, function 3 is GPIO. If func == 3 dir specifies input or
++ * output, and with inv you can enable an inverter (independent of func).
++ */
++int __ns9360_gpio_configure(unsigned gpio, int dir, int inv, int func)
++{
++ void __iomem *conf = ns9360_gpio_get_gconfaddr(gpio);
++ u32 confval;
++
++ confval = __raw_readl(conf);
++ REGSETIM_IDX(confval, BBU_GCONFx, DIR, gpio & 7, dir);
++ REGSETIM_IDX(confval, BBU_GCONFx, INV, gpio & 7, inv);
++ REGSETIM_IDX(confval, BBU_GCONFx, FUNC, gpio & 7, func);
++ __raw_writel(confval, conf);
++
++ return 0;
++}
++
++int ns9360_gpio_configure(unsigned gpio, int inv, int func)
++{
++ if (likely(ns9360_valid_gpio(gpio))) {
++ if (func == 3) {
++ printk(KERN_WARNING "use gpio_direction_input "
++ "or gpio_direction_output\n");
++ return -EINVAL;
++ } else
++ return __ns9360_gpio_configure(gpio, 0, inv, func);
++ } else
++ return -EINVAL;
++}
++EXPORT_SYMBOL(ns9360_gpio_configure);
++
++int ns9360_gpio_get_value(unsigned gpio)
++{
++ void __iomem *stat = ns9360_gpio_get_gstataddr(gpio);
++ int ret;
++
++ ret = 1 & (__raw_readl(stat) >> (gpio & 31));
++
++ return ret;
++}
++
++void ns9360_gpio_set_value(unsigned gpio, int value)
++{
++ void __iomem *ctrl = ns9360_gpio_get_gctrladdr(gpio);
++ u32 ctrlval;
++
++ ctrlval = __raw_readl(ctrl);
++
++ if (value)
++ ctrlval |= 1 << (gpio & 31);
++ else
++ ctrlval &= ~(1 << (gpio & 31));
++
++ __raw_writel(ctrlval, ctrl);
++}
+diff --git a/arch/arm/mach-ns9xxx/gpio-ns9360.h b/arch/arm/mach-ns9xxx/gpio-ns9360.h
+new file mode 100644
+index 0000000..131cd17
+--- /dev/null
++++ b/arch/arm/mach-ns9xxx/gpio-ns9360.h
+@@ -0,0 +1,13 @@
++/*
++ * arch/arm/mach-ns9xxx/gpio-ns9360.h
++ *
++ * Copyright (C) 2006,2007 by Digi International Inc.
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ */
++int __ns9360_gpio_configure(unsigned gpio, int dir, int inv, int func);
++int ns9360_gpio_get_value(unsigned gpio);
++void ns9360_gpio_set_value(unsigned gpio, int value);
+diff --git a/arch/arm/mach-ns9xxx/gpio.c b/arch/arm/mach-ns9xxx/gpio.c
+index 5286e9f..b3c963b 100644
+--- a/arch/arm/mach-ns9xxx/gpio.c
++++ b/arch/arm/mach-ns9xxx/gpio.c
+@@ -1,7 +1,7 @@
+ /*
+ * arch/arm/mach-ns9xxx/gpio.c
+ *
+- * Copyright (C) 2006 by Digi International Inc.
++ * Copyright (C) 2006,2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+@@ -15,12 +15,13 @@
+
+ #include <asm/arch-ns9xxx/gpio.h>
+ #include <asm/arch-ns9xxx/processor.h>
+-#include <asm/arch-ns9xxx/regs-bbu.h>
+-#include <asm/io.h>
++#include <asm/arch-ns9xxx/processor-ns9360.h>
+ #include <asm/bug.h>
+ #include <asm/types.h>
+ #include <asm/bitops.h>
+
++#include "gpio-ns9360.h"
++
+ #if defined(CONFIG_PROCESSOR_NS9360)
+ #define GPIO_MAX 72
+ #elif defined(CONFIG_PROCESSOR_NS9750)
+@@ -45,41 +46,10 @@ static inline int ns9xxx_valid_gpio(unsigned gpio)
+ return gpio <= 49;
+ else
+ #endif
++ {
+ BUG();
+-}
+-
+-static inline void __iomem *ns9xxx_gpio_get_gconfaddr(unsigned gpio)
+-{
+- if (gpio < 56)
+- return BBU_GCONFb1(gpio / 8);
+- else
+- /*
+- * this could be optimised away on
+- * ns9750 only builds, but it isn't ...
+- */
+- return BBU_GCONFb2((gpio - 56) / 8);
+-}
+-
+-static inline void __iomem *ns9xxx_gpio_get_gctrladdr(unsigned gpio)
+-{
+- if (gpio < 32)
+- return BBU_GCTRL1;
+- else if (gpio < 64)
+- return BBU_GCTRL2;
+- else
+- /* this could be optimised away on ns9750 only builds */
+- return BBU_GCTRL3;
+-}
+-
+-static inline void __iomem *ns9xxx_gpio_get_gstataddr(unsigned gpio)
+-{
+- if (gpio < 32)
+- return BBU_GSTAT1;
+- else if (gpio < 64)
+- return BBU_GSTAT2;
+- else
+- /* this could be optimised away on ns9750 only builds */
+- return BBU_GSTAT3;
++ return 0;
++ }
+ }
+
+ int gpio_request(unsigned gpio, const char *label)
+@@ -98,49 +68,24 @@ void gpio_free(unsigned gpio)
+ }
+ EXPORT_SYMBOL(gpio_free);
+
+-/*
+- * each gpio can serve for 4 different purposes [0..3]. These are called
+- * "functions" and passed in the parameter func. Functions 0-2 are always some
+- * special things, function 3 is GPIO. If func == 3 dir specifies input or
+- * output, and with inv you can enable an inverter (independent of func).
+- */
+-static int __ns9xxx_gpio_configure(unsigned gpio, int dir, int inv, int func)
++int gpio_direction_input(unsigned gpio)
+ {
+- void __iomem *conf = ns9xxx_gpio_get_gconfaddr(gpio);
+- u32 confval;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&gpio_lock, flags);
+-
+- confval = __raw_readl(conf);
+- REGSETIM_IDX(confval, BBU_GCONFx, DIR, gpio & 7, dir);
+- REGSETIM_IDX(confval, BBU_GCONFx, INV, gpio & 7, inv);
+- REGSETIM_IDX(confval, BBU_GCONFx, FUNC, gpio & 7, func);
+- __raw_writel(confval, conf);
++ if (likely(ns9xxx_valid_gpio(gpio))) {
++ int ret = -EINVAL;
++ unsigned long flags;
+
+- spin_unlock_irqrestore(&gpio_lock, flags);
++ spin_lock_irqsave(&gpio_lock, flags);
++#if defined(CONFIG_PROCESSOR_NS9360)
++ if (processor_is_ns9360())
++ ret = __ns9360_gpio_configure(gpio, 0, 0, 3);
++ else
++#endif
++ BUG();
+
+- return 0;
+-}
++ spin_unlock_irqrestore(&gpio_lock, flags);
+
+-int ns9xxx_gpio_configure(unsigned gpio, int inv, int func)
+-{
+- if (likely(ns9xxx_valid_gpio(gpio))) {
+- if (func == 3) {
+- printk(KERN_WARNING "use gpio_direction_input "
+- "or gpio_direction_output\n");
+- return -EINVAL;
+- } else
+- return __ns9xxx_gpio_configure(gpio, 0, inv, func);
+- } else
+- return -EINVAL;
+-}
+-EXPORT_SYMBOL(ns9xxx_gpio_configure);
++ return ret;
+
+-int gpio_direction_input(unsigned gpio)
+-{
+- if (likely(ns9xxx_valid_gpio(gpio))) {
+- return __ns9xxx_gpio_configure(gpio, 0, 0, 3);
+ } else
+ return -EINVAL;
+ }
+@@ -149,9 +94,22 @@ EXPORT_SYMBOL(gpio_direction_input);
+ int gpio_direction_output(unsigned gpio, int value)
+ {
+ if (likely(ns9xxx_valid_gpio(gpio))) {
++ int ret = -EINVAL;
++ unsigned long flags;
++
+ gpio_set_value(gpio, value);
+
+- return __ns9xxx_gpio_configure(gpio, 1, 0, 3);
++ spin_lock_irqsave(&gpio_lock, flags);
++#if defined(CONFIG_PROCESSOR_NS9360)
++ if (processor_is_ns9360())
++ ret = __ns9360_gpio_configure(gpio, 1, 0, 3);
++ else
++#endif
++ BUG();
++
++ spin_unlock_irqrestore(&gpio_lock, flags);
++
++ return ret;
+ } else
+ return -EINVAL;
+ }
+@@ -159,31 +117,28 @@ EXPORT_SYMBOL(gpio_direction_output);
+
+ int gpio_get_value(unsigned gpio)
+ {
+- void __iomem *stat = ns9xxx_gpio_get_gstataddr(gpio);
+- int ret;
+-
+- ret = 1 & (__raw_readl(stat) >> (gpio & 31));
+-
+- return ret;
++#if defined(CONFIG_PROCESSOR_NS9360)
++ if (processor_is_ns9360())
++ return ns9360_gpio_get_value(gpio);
++ else
++#endif
++ {
++ BUG();
++ return -EINVAL;
++ }
+ }
+ EXPORT_SYMBOL(gpio_get_value);
+
+ void gpio_set_value(unsigned gpio, int value)
+ {
+- void __iomem *ctrl = ns9xxx_gpio_get_gctrladdr(gpio);
+- u32 ctrlval;
+ unsigned long flags;
+-
+ spin_lock_irqsave(&gpio_lock, flags);
+-
+- ctrlval = __raw_readl(ctrl);
+-
+- if (value)
+- ctrlval |= 1 << (gpio & 31);
++#if defined(CONFIG_PROCESSOR_NS9360)
++ if (processor_is_ns9360())
++ ns9360_gpio_set_value(gpio, value);
+ else
+- ctrlval &= ~(1 << (gpio & 31));
+-
+- __raw_writel(ctrlval, ctrl);
++#endif
++ BUG();
+
+ spin_unlock_irqrestore(&gpio_lock, flags);
+ }
+diff --git a/arch/arm/mach-ns9xxx/irq.c b/arch/arm/mach-ns9xxx/irq.c
+index 00001b8..36e5835 100644
+--- a/arch/arm/mach-ns9xxx/irq.c
++++ b/arch/arm/mach-ns9xxx/irq.c
+@@ -9,21 +9,27 @@
+ * the Free Software Foundation.
+ */
+ #include <linux/interrupt.h>
++#include <linux/kernel_stat.h>
+ #include <asm/io.h>
+ #include <asm/mach/irq.h>
+ #include <asm/mach-types.h>
+-#include <asm/arch-ns9xxx/regs-sys.h>
++#include <asm/arch-ns9xxx/regs-sys-common.h>
+ #include <asm/arch-ns9xxx/irqs.h>
+ #include <asm/arch-ns9xxx/board.h>
+
+ #include "generic.h"
+
++/* simple interrupt prio table: prio(x) < prio(y) <=> x < y */
++#define irq2prio(i) (i)
++#define prio2irq(p) (p)
++
+ static void ns9xxx_mask_irq(unsigned int irq)
+ {
+ /* XXX: better use cpp symbols */
+- u32 ic = __raw_readl(SYS_IC(irq / 4));
+- ic &= ~(1 << (7 + 8 * (3 - (irq & 3))));
+- __raw_writel(ic, SYS_IC(irq / 4));
++ int prio = irq2prio(irq);
++ u32 ic = __raw_readl(SYS_IC(prio / 4));
++ ic &= ~(1 << (7 + 8 * (3 - (prio & 3))));
++ __raw_writel(ic, SYS_IC(prio / 4));
+ }
+
+ static void ns9xxx_ack_irq(unsigned int irq)
+@@ -40,9 +46,10 @@ static void ns9xxx_maskack_irq(unsigned int irq)
+ static void ns9xxx_unmask_irq(unsigned int irq)
+ {
+ /* XXX: better use cpp symbols */
+- u32 ic = __raw_readl(SYS_IC(irq / 4));
+- ic |= 1 << (7 + 8 * (3 - (irq & 3)));
+- __raw_writel(ic, SYS_IC(irq / 4));
++ int prio = irq2prio(irq);
++ u32 ic = __raw_readl(SYS_IC(prio / 4));
++ ic |= 1 << (7 + 8 * (3 - (prio & 3)));
++ __raw_writel(ic, SYS_IC(prio / 4));
+ }
+
+ static struct irq_chip ns9xxx_chip = {
+@@ -52,24 +59,61 @@ static struct irq_chip ns9xxx_chip = {
+ .unmask = ns9xxx_unmask_irq,
+ };
+
++#if 0
++#define handle_irq handle_level_irq
++#else
++void handle_prio_irq(unsigned int irq, struct irq_desc *desc)
++{
++ unsigned int cpu = smp_processor_id();
++ struct irqaction *action;
++ irqreturn_t action_ret;
++
++ spin_lock(&desc->lock);
++
++ if (unlikely(desc->status & IRQ_INPROGRESS))
++ goto out_unlock;
++
++ desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
++ kstat_cpu(cpu).irqs[irq]++;
++
++ action = desc->action;
++ if (unlikely(!action || (desc->status & IRQ_DISABLED)))
++ goto out_unlock;
++
++ desc->status |= IRQ_INPROGRESS;
++ spin_unlock(&desc->lock);
++
++ action_ret = handle_IRQ_event(irq, action);
++
++ spin_lock(&desc->lock);
++ desc->status &= ~IRQ_INPROGRESS;
++ if (!(desc->status & IRQ_DISABLED) && desc->chip->ack)
++ desc->chip->ack(irq);
++
++out_unlock:
++ spin_unlock(&desc->lock);
++}
++#define handle_irq handle_prio_irq
++#endif
++
+ void __init ns9xxx_init_irq(void)
+ {
+ int i;
+
+ /* disable all IRQs */
+ for (i = 0; i < 8; ++i)
+- __raw_writel((4 * i) << 24 | (4 * i + 1) << 16 |
+- (4 * i + 2) << 8 | (4 * i + 3), SYS_IC(i));
++ __raw_writel(prio2irq(4 * i) << 24 |
++ prio2irq(4 * i + 1) << 16 |
++ prio2irq(4 * i + 2) << 8 |
++ prio2irq(4 * i + 3),
++ SYS_IC(i));
+
+- /* simple interrupt prio table:
+- * prio(x) < prio(y) <=> x < y
+- */
+ for (i = 0; i < 32; ++i)
+- __raw_writel(i, SYS_IVA(i));
++ __raw_writel(prio2irq(i), SYS_IVA(i));
+
+- for (i = IRQ_WATCHDOG; i <= IRQ_EXT3; ++i) {
++ for (i = 0; i <= 31; ++i) {
+ set_irq_chip(i, &ns9xxx_chip);
+- set_irq_handler(i, handle_level_irq);
++ set_irq_handler(i, handle_irq);
+ set_irq_flags(i, IRQF_VALID);
+ }
+ }
+diff --git a/arch/arm/mach-ns9xxx/mach-cc9p9360dev.c b/arch/arm/mach-ns9xxx/mach-cc9p9360dev.c
+index 760c9d0..9623fff 100644
+--- a/arch/arm/mach-ns9xxx/mach-cc9p9360dev.c
++++ b/arch/arm/mach-ns9xxx/mach-cc9p9360dev.c
+@@ -1,7 +1,7 @@
+ /*
+ * arch/arm/mach-ns9xxx/mach-cc9p9360dev.c
+ *
+- * Copyright (C) 2006 by Digi International Inc.
++ * Copyright (C) 2006,2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+@@ -11,12 +11,14 @@
+ #include <asm/mach/arch.h>
+ #include <asm/mach-types.h>
+
++#include <asm/arch-ns9xxx/processor-ns9360.h>
++
+ #include "board-a9m9750dev.h"
+ #include "generic.h"
+
+ static void __init mach_cc9p9360dev_map_io(void)
+ {
+- ns9xxx_map_io();
++ ns9360_map_io();
+ board_a9m9750dev_map_io();
+ }
+
+@@ -36,6 +38,6 @@ MACHINE_START(CC9P9360DEV, "Digi ConnectCore 9P 9360 on an A9M9750 Devboard")
+ .map_io = mach_cc9p9360dev_map_io,
+ .init_irq = mach_cc9p9360dev_init_irq,
+ .init_machine = mach_cc9p9360dev_init_machine,
+- .timer = &ns9xxx_timer,
++ .timer = &ns9360_timer,
+ .boot_params = 0x100,
+ MACHINE_END
+diff --git a/arch/arm/mach-ns9xxx/mach-cc9p9360js.c b/arch/arm/mach-ns9xxx/mach-cc9p9360js.c
+index 85c8b41..fcc815b 100644
+--- a/arch/arm/mach-ns9xxx/mach-cc9p9360js.c
++++ b/arch/arm/mach-ns9xxx/mach-cc9p9360js.c
+@@ -1,7 +1,7 @@
+ /*
+ * arch/arm/mach-ns9xxx/mach-cc9p9360js.c
+ *
+- * Copyright (C) 2006 by Digi International Inc.
++ * Copyright (C) 2006,2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+@@ -11,6 +11,8 @@
+ #include <asm/mach/arch.h>
+ #include <asm/mach-types.h>
+
++#include <asm/arch-ns9xxx/processor-ns9360.h>
++
+ #include "board-jscc9p9360.h"
+ #include "generic.h"
+
+@@ -21,9 +23,9 @@ static void __init mach_cc9p9360js_init_machine(void)
+ }
+
+ MACHINE_START(CC9P9360JS, "Digi ConnectCore 9P 9360 on an JSCC9P9360 Devboard")
+- .map_io = ns9xxx_map_io,
++ .map_io = ns9360_map_io,
+ .init_irq = ns9xxx_init_irq,
+ .init_machine = mach_cc9p9360js_init_machine,
+- .timer = &ns9xxx_timer,
++ .timer = &ns9360_timer,
+ .boot_params = 0x100,
+ MACHINE_END
+diff --git a/arch/arm/mach-ns9xxx/plat-serial8250.c b/arch/arm/mach-ns9xxx/plat-serial8250.c
+new file mode 100644
+index 0000000..5aa5d9b
+--- /dev/null
++++ b/arch/arm/mach-ns9xxx/plat-serial8250.c
+@@ -0,0 +1,69 @@
++/*
++ * arch/arm/mach-ns9xxx/plat-serial8250.c
++ *
++ * Copyright (C) 2008 by Digi International Inc.
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ */
++#include <linux/platform_device.h>
++#include <linux/serial_8250.h>
++
++#include <asm/arch-ns9xxx/regs-board-a9m9750dev.h>
++#include <asm/arch-ns9xxx/board.h>
++
++#define DRIVER_NAME "serial8250"
++
++static int __init ns9xxx_plat_serial8250_init(void)
++{
++ struct plat_serial8250_port *pdata;
++ struct platform_device *pdev;
++ int ret = -ENOMEM;
++ int i;
++
++ if (!board_is_a9m9750dev())
++ return -ENODEV;
++
++ pdev = platform_device_alloc(DRIVER_NAME, 0);
++ if (!pdev)
++ goto err;
++
++ pdata = kzalloc(5 * sizeof(*pdata), GFP_KERNEL);
++ if (!pdata)
++ goto err;
++
++ pdev->dev.platform_data = pdata;
++
++ pdata[0].iobase = FPGA_UARTA_BASE;
++ pdata[1].iobase = FPGA_UARTB_BASE;
++ pdata[2].iobase = FPGA_UARTC_BASE;
++ pdata[3].iobase = FPGA_UARTD_BASE;
++
++ for (i = 0; i < 4; ++i) {
++ pdata[i].membase = (void __iomem *)pdata[i].iobase;
++ pdata[i].mapbase = pdata[i].iobase;
++ pdata[i].iotype = UPIO_MEM;
++ pdata[i].uartclk = 18432000;
++ pdata[i].flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
++ }
++
++ pdata[0].irq = IRQ_FPGA_UARTA;
++ pdata[1].irq = IRQ_FPGA_UARTB;
++ pdata[2].irq = IRQ_FPGA_UARTC;
++ pdata[3].irq = IRQ_FPGA_UARTD;
++
++ ret = platform_device_add(pdev);
++ if (ret) {
++err:
++ platform_device_put(pdev);
++
++ printk(KERN_WARNING "Could not add %s (errno=%d)\n",
++ DRIVER_NAME, ret);
++ }
++
++ return 0;
++}
++
++arch_initcall(ns9xxx_plat_serial8250_init);
+diff --git a/arch/arm/mach-ns9xxx/processor-ns9360.c b/arch/arm/mach-ns9xxx/processor-ns9360.c
+new file mode 100644
+index 0000000..2bee0b7
+--- /dev/null
++++ b/arch/arm/mach-ns9xxx/processor-ns9360.c
+@@ -0,0 +1,54 @@
++/*
++ * arch/arm/mach-ns9xxx/processor-ns9360.c
++ *
++ * Copyright (C) 2007 by Digi International Inc.
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ */
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++
++#include <asm/page.h>
++#include <asm/mach/map.h>
++#include <asm/arch-ns9xxx/processor-ns9360.h>
++#include <asm/arch-ns9xxx/regs-sys-ns9360.h>
++
++void ns9360_reset(char mode)
++{
++ u32 reg;
++
++ reg = __raw_readl(SYS_PLL) >> 16;
++ REGSET(reg, SYS_PLL, SWC, YES);
++ __raw_writel(reg, SYS_PLL);
++}
++
++#define CRYSTAL 29491200 /* Hz */
++unsigned long ns9360_systemclock(void)
++{
++ u32 pll = __raw_readl(SYS_PLL);
++ return CRYSTAL * (REGGETIM(pll, SYS_PLL, ND) + 1)
++ >> REGGETIM(pll, SYS_PLL, FS);
++}
++
++static struct map_desc ns9360_io_desc[] __initdata = {
++ { /* BBus */
++ .virtual = io_p2v(0x90000000),
++ .pfn = __phys_to_pfn(0x90000000),
++ .length = 0x00700000,
++ .type = MT_DEVICE,
++ }, { /* AHB */
++ .virtual = io_p2v(0xa0100000),
++ .pfn = __phys_to_pfn(0xa0100000),
++ .length = 0x00900000,
++ .type = MT_DEVICE,
++ },
++};
++
++void __init ns9360_map_io(void)
++{
++ iotable_init(ns9360_io_desc, ARRAY_SIZE(ns9360_io_desc));
++}
+diff --git a/arch/arm/mach-ns9xxx/time-ns9360.c b/arch/arm/mach-ns9xxx/time-ns9360.c
+new file mode 100644
+index 0000000..4d573c9
+--- /dev/null
++++ b/arch/arm/mach-ns9xxx/time-ns9360.c
+@@ -0,0 +1,185 @@
++/*
++ * arch/arm/mach-ns9xxx/time-ns9360.c
++ *
++ * Copyright (C) 2006,2007 by Digi International Inc.
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ */
++#include <linux/jiffies.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <linux/stringify.h>
++#include <linux/clocksource.h>
++#include <linux/clockchips.h>
++
++#include <asm/arch-ns9xxx/processor-ns9360.h>
++#include <asm/arch-ns9xxx/regs-sys-ns9360.h>
++#include <asm/arch-ns9xxx/irqs.h>
++#include <asm/arch/system.h>
++#include "generic.h"
++
++#define TIMER_CLOCKSOURCE 0
++#define TIMER_CLOCKEVENT 1
++static u32 latch;
++
++static cycle_t ns9360_clocksource_read(void)
++{
++ return __raw_readl(SYS_TR(TIMER_CLOCKSOURCE));
++}
++
++static struct clocksource ns9360_clocksource = {
++ .name = "ns9360-timer" __stringify(TIMER_CLOCKSOURCE),
++ .rating = 300,
++ .read = ns9360_clocksource_read,
++ .mask = CLOCKSOURCE_MASK(32),
++ .shift = 20,
++ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
++};
++
++static void ns9360_clockevent_setmode(enum clock_event_mode mode,
++ struct clock_event_device *clk)
++{
++ u32 tc = __raw_readl(SYS_TC(TIMER_CLOCKEVENT));
++
++ switch (mode) {
++ case CLOCK_EVT_MODE_PERIODIC:
++ __raw_writel(latch, SYS_TRC(TIMER_CLOCKEVENT));
++ REGSET(tc, SYS_TCx, REN, EN);
++ REGSET(tc, SYS_TCx, INTS, EN);
++ REGSET(tc, SYS_TCx, TEN, EN);
++ break;
++
++ case CLOCK_EVT_MODE_ONESHOT:
++ REGSET(tc, SYS_TCx, REN, DIS);
++ REGSET(tc, SYS_TCx, INTS, EN);
++
++ /* fall through */
++
++ case CLOCK_EVT_MODE_UNUSED:
++ case CLOCK_EVT_MODE_SHUTDOWN:
++ case CLOCK_EVT_MODE_RESUME:
++ default:
++ REGSET(tc, SYS_TCx, TEN, DIS);
++ break;
++ }
++
++ __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
++}
++
++static int ns9360_clockevent_setnextevent(unsigned long evt,
++ struct clock_event_device *clk)
++{
++ u32 tc = __raw_readl(SYS_TC(TIMER_CLOCKEVENT));
++
++ if (REGGET(tc, SYS_TCx, TEN)) {
++ REGSET(tc, SYS_TCx, TEN, DIS);
++ __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
++ }
++
++ REGSET(tc, SYS_TCx, TEN, EN);
++
++ __raw_writel(evt, SYS_TRC(TIMER_CLOCKEVENT));
++
++ __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
++
++ return 0;
++}
++
++static struct clock_event_device ns9360_clockevent_device = {
++ .name = "ns9360-timer" __stringify(TIMER_CLOCKEVENT),
++ .shift = 20,
++ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
++ .set_mode = ns9360_clockevent_setmode,
++ .set_next_event = ns9360_clockevent_setnextevent,
++};
++
++static irqreturn_t ns9360_clockevent_handler(int irq, void *dev_id)
++{
++ int timerno = irq - IRQ_NS9360_TIMER0;
++ u32 tc;
++
++ struct clock_event_device *evt = &ns9360_clockevent_device;
++
++ /* clear irq */
++ tc = __raw_readl(SYS_TC(timerno));
++ if (REGGET(tc, SYS_TCx, REN) == SYS_TCx_REN_DIS) {
++ REGSET(tc, SYS_TCx, TEN, DIS);
++ __raw_writel(tc, SYS_TC(timerno));
++ }
++ REGSET(tc, SYS_TCx, INTC, SET);
++ __raw_writel(tc, SYS_TC(timerno));
++ REGSET(tc, SYS_TCx, INTC, UNSET);
++ __raw_writel(tc, SYS_TC(timerno));
++
++ evt->event_handler(evt);
++
++ return IRQ_HANDLED;
++}
++
++static struct irqaction ns9360_clockevent_action = {
++ .name = "ns9360-timer" __stringify(TIMER_CLOCKEVENT),
++ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
++ .handler = ns9360_clockevent_handler,
++};
++
++static void __init ns9360_timer_init(void)
++{
++ int tc;
++
++ tc = __raw_readl(SYS_TC(TIMER_CLOCKSOURCE));
++ if (REGGET(tc, SYS_TCx, TEN)) {
++ REGSET(tc, SYS_TCx, TEN, DIS);
++ __raw_writel(tc, SYS_TC(TIMER_CLOCKSOURCE));
++ }
++
++ __raw_writel(0, SYS_TRC(TIMER_CLOCKSOURCE));
++
++ REGSET(tc, SYS_TCx, TEN, EN);
++ REGSET(tc, SYS_TCx, TDBG, STOP);
++ REGSET(tc, SYS_TCx, TLCS, CPU);
++ REGSET(tc, SYS_TCx, TM, IEE);
++ REGSET(tc, SYS_TCx, INTS, DIS);
++ REGSET(tc, SYS_TCx, UDS, UP);
++ REGSET(tc, SYS_TCx, TSZ, 32);
++ REGSET(tc, SYS_TCx, REN, EN);
++
++ __raw_writel(tc, SYS_TC(TIMER_CLOCKSOURCE));
++
++ ns9360_clocksource.mult = clocksource_hz2mult(ns9360_cpuclock(),
++ ns9360_clocksource.shift);
++
++ clocksource_register(&ns9360_clocksource);
++
++ latch = SH_DIV(ns9360_cpuclock(), HZ, 0);
++
++ tc = __raw_readl(SYS_TC(TIMER_CLOCKEVENT));
++ REGSET(tc, SYS_TCx, TEN, DIS);
++ REGSET(tc, SYS_TCx, TDBG, STOP);
++ REGSET(tc, SYS_TCx, TLCS, CPU);
++ REGSET(tc, SYS_TCx, TM, IEE);
++ REGSET(tc, SYS_TCx, INTS, DIS);
++ REGSET(tc, SYS_TCx, UDS, DOWN);
++ REGSET(tc, SYS_TCx, TSZ, 32);
++ REGSET(tc, SYS_TCx, REN, EN);
++ __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
++
++ ns9360_clockevent_device.mult = div_sc(ns9360_cpuclock(),
++ NSEC_PER_SEC, ns9360_clockevent_device.shift);
++ ns9360_clockevent_device.max_delta_ns =
++ clockevent_delta2ns(-1, &ns9360_clockevent_device);
++ ns9360_clockevent_device.min_delta_ns =
++ clockevent_delta2ns(1, &ns9360_clockevent_device);
++
++ ns9360_clockevent_device.cpumask = cpumask_of_cpu(0);
++ clockevents_register_device(&ns9360_clockevent_device);
++
++ setup_irq(IRQ_NS9360_TIMER0 + TIMER_CLOCKEVENT,
++ &ns9360_clockevent_action);
++}
++
++struct sys_timer ns9360_timer = {
++ .init = ns9360_timer_init,
++};
+diff --git a/arch/arm/mach-ns9xxx/time.c b/arch/arm/mach-ns9xxx/time.c
+deleted file mode 100644
+index c3dd1f4..0000000
+--- a/arch/arm/mach-ns9xxx/time.c
++++ /dev/null
+@@ -1,184 +0,0 @@
+-/*
+- * arch/arm/mach-ns9xxx/time.c
+- *
+- * Copyright (C) 2006 by Digi International Inc.
+- * All rights reserved.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License version 2 as published by
+- * the Free Software Foundation.
+- */
+-#include <linux/jiffies.h>
+-#include <linux/interrupt.h>
+-#include <linux/irq.h>
+-#include <linux/stringify.h>
+-#include <linux/clocksource.h>
+-#include <linux/clockchips.h>
+-
+-#include <asm/arch-ns9xxx/regs-sys.h>
+-#include <asm/arch-ns9xxx/clock.h>
+-#include <asm/arch-ns9xxx/irqs.h>
+-#include <asm/arch/system.h>
+-#include "generic.h"
+-
+-#define TIMER_CLOCKSOURCE 0
+-#define TIMER_CLOCKEVENT 1
+-static u32 latch;
+-
+-static cycle_t ns9xxx_clocksource_read(void)
+-{
+- return __raw_readl(SYS_TR(TIMER_CLOCKSOURCE));
+-}
+-
+-static struct clocksource ns9xxx_clocksource = {
+- .name = "ns9xxx-timer" __stringify(TIMER_CLOCKSOURCE),
+- .rating = 300,
+- .read = ns9xxx_clocksource_read,
+- .mask = CLOCKSOURCE_MASK(32),
+- .shift = 20,
+- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+-};
+-
+-static void ns9xxx_clockevent_setmode(enum clock_event_mode mode,
+- struct clock_event_device *clk)
+-{
+- u32 tc = __raw_readl(SYS_TC(TIMER_CLOCKEVENT));
+-
+- switch(mode) {
+- case CLOCK_EVT_MODE_PERIODIC:
+- __raw_writel(latch, SYS_TRC(TIMER_CLOCKEVENT));
+- REGSET(tc, SYS_TCx, REN, EN);
+- REGSET(tc, SYS_TCx, INTS, EN);
+- REGSET(tc, SYS_TCx, TEN, EN);
+- break;
+-
+- case CLOCK_EVT_MODE_ONESHOT:
+- REGSET(tc, SYS_TCx, REN, DIS);
+- REGSET(tc, SYS_TCx, INTS, EN);
+-
+- /* fall through */
+-
+- case CLOCK_EVT_MODE_UNUSED:
+- case CLOCK_EVT_MODE_SHUTDOWN:
+- case CLOCK_EVT_MODE_RESUME:
+- default:
+- REGSET(tc, SYS_TCx, TEN, DIS);
+- break;
+- }
+-
+- __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
+-}
+-
+-static int ns9xxx_clockevent_setnextevent(unsigned long evt,
+- struct clock_event_device *clk)
+-{
+- u32 tc = __raw_readl(SYS_TC(TIMER_CLOCKEVENT));
+-
+- if (REGGET(tc, SYS_TCx, TEN)) {
+- REGSET(tc, SYS_TCx, TEN, DIS);
+- __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
+- }
+-
+- REGSET(tc, SYS_TCx, TEN, EN);
+-
+- __raw_writel(evt, SYS_TRC(TIMER_CLOCKEVENT));
+-
+- __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
+-
+- return 0;
+-}
+-
+-static struct clock_event_device ns9xxx_clockevent_device = {
+- .name = "ns9xxx-timer" __stringify(TIMER_CLOCKEVENT),
+- .shift = 20,
+- .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+- .set_mode = ns9xxx_clockevent_setmode,
+- .set_next_event = ns9xxx_clockevent_setnextevent,
+-};
+-
+-static irqreturn_t ns9xxx_clockevent_handler(int irq, void *dev_id)
+-{
+- int timerno = irq - IRQ_TIMER0;
+- u32 tc;
+-
+- struct clock_event_device *evt = &ns9xxx_clockevent_device;
+-
+- /* clear irq */
+- tc = __raw_readl(SYS_TC(timerno));
+- if (REGGET(tc, SYS_TCx, REN) == SYS_TCx_REN_DIS) {
+- REGSET(tc, SYS_TCx, TEN, DIS);
+- __raw_writel(tc, SYS_TC(timerno));
+- }
+- REGSET(tc, SYS_TCx, INTC, SET);
+- __raw_writel(tc, SYS_TC(timerno));
+- REGSET(tc, SYS_TCx, INTC, UNSET);
+- __raw_writel(tc, SYS_TC(timerno));
+-
+- evt->event_handler(evt);
+-
+- return IRQ_HANDLED;
+-}
+-
+-static struct irqaction ns9xxx_clockevent_action = {
+- .name = "ns9xxx-timer" __stringify(TIMER_CLOCKEVENT),
+- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+- .handler = ns9xxx_clockevent_handler,
+-};
+-
+-static void __init ns9xxx_timer_init(void)
+-{
+- int tc;
+-
+- tc = __raw_readl(SYS_TC(TIMER_CLOCKSOURCE));
+- if (REGGET(tc, SYS_TCx, TEN)) {
+- REGSET(tc, SYS_TCx, TEN, DIS);
+- __raw_writel(tc, SYS_TC(TIMER_CLOCKSOURCE));
+- }
+-
+- __raw_writel(0, SYS_TRC(TIMER_CLOCKSOURCE));
+-
+- REGSET(tc, SYS_TCx, TEN, EN);
+- REGSET(tc, SYS_TCx, TDBG, STOP);
+- REGSET(tc, SYS_TCx, TLCS, CPU);
+- REGSET(tc, SYS_TCx, TM, IEE);
+- REGSET(tc, SYS_TCx, INTS, DIS);
+- REGSET(tc, SYS_TCx, UDS, UP);
+- REGSET(tc, SYS_TCx, TSZ, 32);
+- REGSET(tc, SYS_TCx, REN, EN);
+-
+- __raw_writel(tc, SYS_TC(TIMER_CLOCKSOURCE));
+-
+- ns9xxx_clocksource.mult = clocksource_hz2mult(ns9xxx_cpuclock(),
+- ns9xxx_clocksource.shift);
+-
+- clocksource_register(&ns9xxx_clocksource);
+-
+- latch = SH_DIV(ns9xxx_cpuclock(), HZ, 0);
+-
+- tc = __raw_readl(SYS_TC(TIMER_CLOCKEVENT));
+- REGSET(tc, SYS_TCx, TEN, DIS);
+- REGSET(tc, SYS_TCx, TDBG, STOP);
+- REGSET(tc, SYS_TCx, TLCS, CPU);
+- REGSET(tc, SYS_TCx, TM, IEE);
+- REGSET(tc, SYS_TCx, INTS, DIS);
+- REGSET(tc, SYS_TCx, UDS, DOWN);
+- REGSET(tc, SYS_TCx, TSZ, 32);
+- REGSET(tc, SYS_TCx, REN, EN);
+- __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
+-
+- ns9xxx_clockevent_device.mult = div_sc(ns9xxx_cpuclock(),
+- NSEC_PER_SEC, ns9xxx_clockevent_device.shift);
+- ns9xxx_clockevent_device.max_delta_ns =
+- clockevent_delta2ns(-1, &ns9xxx_clockevent_device);
+- ns9xxx_clockevent_device.min_delta_ns =
+- clockevent_delta2ns(1, &ns9xxx_clockevent_device);
+-
+- ns9xxx_clockevent_device.cpumask = cpumask_of_cpu(0);
+- clockevents_register_device(&ns9xxx_clockevent_device);
+-
+- setup_irq(IRQ_TIMER0 + TIMER_CLOCKEVENT, &ns9xxx_clockevent_action);
+-}
+-
+-struct sys_timer ns9xxx_timer = {
+- .init = ns9xxx_timer_init,
+-};
+diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
+index 015a66b..c06f525 100644
+--- a/arch/arm/mach-omap1/Makefile
++++ b/arch/arm/mach-omap1/Makefile
+@@ -5,7 +5,8 @@
+ # Common support
+ obj-y := io.o id.o clock.o irq.o mux.o serial.o devices.o
+
+-obj-$(CONFIG_OMAP_MPU_TIMER) += time.o
++obj-$(CONFIG_OMAP_MPU_TIMER) += time.o
++obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o
+
+ # Power Management
+ obj-$(CONFIG_PM) += pm.o sleep.o
+diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
+index 5279e35..4f9baba 100644
+--- a/arch/arm/mach-omap1/board-osk.c
++++ b/arch/arm/mach-omap1/board-osk.c
+@@ -32,6 +32,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/irq.h>
+ #include <linux/i2c.h>
++#include <linux/leds.h>
+
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/partitions.h>
+@@ -183,11 +184,80 @@ static struct platform_device *osk5912_devices[] __initdata = {
+ &osk5912_mcbsp1_device,
+ };
+
++static struct gpio_led tps_leds[] = {
++ /* NOTE: D9 and D2 have hardware blink support.
++ * Also, D9 requires non-battery power.
++ */
++ { .gpio = OSK_TPS_GPIO_LED_D9, .name = "d9", },
++ { .gpio = OSK_TPS_GPIO_LED_D2, .name = "d2", },
++ { .gpio = OSK_TPS_GPIO_LED_D3, .name = "d3", .active_low = 1,
++ .default_trigger = "heartbeat", },
++};
++
++static struct gpio_led_platform_data tps_leds_data = {
++ .num_leds = 3,
++ .leds = tps_leds,
++};
++
++static struct platform_device osk5912_tps_leds = {
++ .name = "leds-gpio",
++ .id = 0,
++ .dev.platform_data = &tps_leds_data,
++};
++
++static int osk_tps_setup(struct i2c_client *client, void *context)
++{
++ /* Set GPIO 1 HIGH to disable VBUS power supply;
++ * OHCI driver powers it up/down as needed.
++ */
++ gpio_request(OSK_TPS_GPIO_USB_PWR_EN, "n_vbus_en");
++ gpio_direction_output(OSK_TPS_GPIO_USB_PWR_EN, 1);
++
++ /* Set GPIO 2 high so LED D3 is off by default */
++ tps65010_set_gpio_out_value(GPIO2, HIGH);
++
++ /* Set GPIO 3 low to take ethernet out of reset */
++ gpio_request(OSK_TPS_GPIO_LAN_RESET, "smc_reset");
++ gpio_direction_output(OSK_TPS_GPIO_LAN_RESET, 0);
++
++ /* GPIO4 is VDD_DSP */
++ gpio_request(OSK_TPS_GPIO_DSP_PWR_EN, "dsp_power");
++ gpio_direction_output(OSK_TPS_GPIO_DSP_PWR_EN, 1);
++ /* REVISIT if DSP support isn't configured, power it off ... */
++
++ /* Let LED1 (D9) blink; leds-gpio may override it */
++ tps65010_set_led(LED1, BLINK);
++
++ /* Set LED2 off by default */
++ tps65010_set_led(LED2, OFF);
++
++ /* Enable LOW_PWR handshake */
++ tps65010_set_low_pwr(ON);
++
++ /* Switch VLDO2 to 3.0V for AIC23 */
++ tps65010_config_vregs1(TPS_LDO2_ENABLE | TPS_VLDO2_3_0V
++ | TPS_LDO1_ENABLE);
++
++ /* register these three LEDs */
++ osk5912_tps_leds.dev.parent = &client->dev;
++ platform_device_register(&osk5912_tps_leds);
++
++ return 0;
++}
++
++static struct tps65010_board tps_board = {
++ .base = OSK_TPS_GPIO_BASE,
++ .outmask = 0x0f,
++ .setup = osk_tps_setup,
++};
++
+ static struct i2c_board_info __initdata osk_i2c_board_info[] = {
+ {
+ I2C_BOARD_INFO("tps65010", 0x48),
+ .type = "tps65010",
+ .irq = OMAP_GPIO_IRQ(OMAP_MPUIO(1)),
++ .platform_data = &tps_board,
++
+ },
+ /* TODO when driver support is ready:
+ * - aic23 audio chip at 0x1a
+@@ -198,7 +268,7 @@ static struct i2c_board_info __initdata osk_i2c_board_info[] = {
+
+ static void __init osk_init_smc91x(void)
+ {
+- if ((omap_request_gpio(0)) < 0) {
++ if ((gpio_request(0, "smc_irq")) < 0) {
+ printk("Error requesting gpio 0 for smc91x irq\n");
+ return;
+ }
+@@ -210,7 +280,7 @@ static void __init osk_init_smc91x(void)
+ static void __init osk_init_cf(void)
+ {
+ omap_cfg_reg(M7_1610_GPIO62);
+- if ((omap_request_gpio(62)) < 0) {
++ if ((gpio_request(62, "cf_irq")) < 0) {
+ printk("Error requesting gpio 62 for CF irq\n");
+ return;
+ }
+@@ -334,7 +404,7 @@ static struct platform_device *mistral_devices[] __initdata = {
+
+ static int mistral_get_pendown_state(void)
+ {
+- return !omap_get_gpio_datain(4);
++ return !gpio_get_value(4);
+ }
+
+ static const struct ads7846_platform_data mistral_ts_info = {
+@@ -396,25 +466,31 @@ static void __init osk_mistral_init(void)
+ omap_cfg_reg(W14_1610_CCP_DATAP);
+
+ /* CAM_PWDN */
+- if (omap_request_gpio(11) == 0) {
++ if (gpio_request(11, "cam_pwdn") == 0) {
+ omap_cfg_reg(N20_1610_GPIO11);
+- omap_set_gpio_direction(11, 0 /* out */);
+- omap_set_gpio_dataout(11, 0 /* off */);
++ gpio_direction_output(11, 0);
+ } else
+ pr_debug("OSK+Mistral: CAM_PWDN is awol\n");
+
+
+ /* omap_cfg_reg(P19_1610_GPIO6); */ /* BUSY */
++ gpio_request(6, "ts_busy");
++ gpio_direction_input(6);
++
+ omap_cfg_reg(P20_1610_GPIO4); /* PENIRQ */
++ gpio_request(4, "ts_int");
++ gpio_direction_input(4);
+ set_irq_type(OMAP_GPIO_IRQ(4), IRQT_FALLING);
++
+ spi_register_board_info(mistral_boardinfo,
+ ARRAY_SIZE(mistral_boardinfo));
+
+ /* the sideways button (SW1) is for use as a "wakeup" button */
+ omap_cfg_reg(N15_1610_MPUIO2);
+- if (omap_request_gpio(OMAP_MPUIO(2)) == 0) {
++ if (gpio_request(OMAP_MPUIO(2), "wakeup") == 0) {
+ int ret = 0;
+- omap_set_gpio_direction(OMAP_MPUIO(2), 1);
++
++ gpio_direction_input(OMAP_MPUIO(2));
+ set_irq_type(OMAP_GPIO_IRQ(OMAP_MPUIO(2)), IRQT_RISING);
+ #ifdef CONFIG_PM
+ /* share the IRQ in case someone wants to use the
+@@ -425,7 +501,7 @@ static void __init osk_mistral_init(void)
+ IRQF_SHARED, "mistral_wakeup",
+ &osk_mistral_wake_interrupt);
+ if (ret != 0) {
+- omap_free_gpio(OMAP_MPUIO(2));
++ gpio_free(OMAP_MPUIO(2));
+ printk(KERN_ERR "OSK+Mistral: no wakeup irq, %d?\n",
+ ret);
+ } else
+@@ -438,10 +514,8 @@ static void __init osk_mistral_init(void)
+ * board, like the touchscreen, EEPROM, and wakeup (!) switch.
+ */
+ omap_cfg_reg(PWL);
+- if (omap_request_gpio(2) == 0) {
+- omap_set_gpio_direction(2, 0 /* out */);
+- omap_set_gpio_dataout(2, 1 /* on */);
+- }
++ if (gpio_request(2, "lcd_pwr") == 0)
++ gpio_direction_output(2, 1);
+
+ platform_add_devices(mistral_devices, ARRAY_SIZE(mistral_devices));
+ }
+@@ -484,44 +558,6 @@ static void __init osk_map_io(void)
+ omap1_map_common_io();
+ }
+
+-#ifdef CONFIG_TPS65010
+-static int __init osk_tps_init(void)
+-{
+- if (!machine_is_omap_osk())
+- return 0;
+-
+- /* Let LED1 (D9) blink */
+- tps65010_set_led(LED1, BLINK);
+-
+- /* Disable LED 2 (D2) */
+- tps65010_set_led(LED2, OFF);
+-
+- /* Set GPIO 1 HIGH to disable VBUS power supply;
+- * OHCI driver powers it up/down as needed.
+- */
+- tps65010_set_gpio_out_value(GPIO1, HIGH);
+-
+- /* Set GPIO 2 low to turn on LED D3 */
+- tps65010_set_gpio_out_value(GPIO2, HIGH);
+-
+- /* Set GPIO 3 low to take ethernet out of reset */
+- tps65010_set_gpio_out_value(GPIO3, LOW);
+-
+- /* gpio4 for VDD_DSP */
+- /* FIXME send power to DSP iff it's configured */
+-
+- /* Enable LOW_PWR */
+- tps65010_set_low_pwr(ON);
+-
+- /* Switch VLDO2 to 3.0V for AIC23 */
+- tps65010_config_vregs1(TPS_LDO2_ENABLE | TPS_VLDO2_3_0V
+- | TPS_LDO1_ENABLE);
+-
+- return 0;
+-}
+-fs_initcall(osk_tps_init);
+-#endif
+-
+ MACHINE_START(OMAP_OSK, "TI-OSK")
+ /* Maintainer: Dirk Behme <dirk.behme at de.bosch.com> */
+ .phys_io = 0xfff00000,
+diff --git a/arch/arm/mach-omap1/leds-osk.c b/arch/arm/mach-omap1/leds-osk.c
+index 026685e..754383d 100644
+--- a/arch/arm/mach-omap1/leds-osk.c
++++ b/arch/arm/mach-omap1/leds-osk.c
+@@ -1,11 +1,9 @@
+ /*
+ * linux/arch/arm/mach-omap1/leds-osk.c
+ *
+- * LED driver for OSK, and optionally Mistral QVGA, boards
++ * LED driver for OSK with optional Mistral QVGA board
+ */
+ #include <linux/init.h>
+-#include <linux/workqueue.h>
+-#include <linux/i2c/tps65010.h>
+
+ #include <asm/hardware.h>
+ #include <asm/leds.h>
+@@ -20,49 +18,11 @@
+ #define LED_STATE_CLAIMED (1 << 1)
+ static u8 led_state;
+
+-#define GREEN_LED (1 << 0) /* TPS65010 LED1 */
+-#define AMBER_LED (1 << 1) /* TPS65010 LED2 */
+-#define RED_LED (1 << 2) /* TPS65010 GPIO2 */
+ #define TIMER_LED (1 << 3) /* Mistral board */
+ #define IDLE_LED (1 << 4) /* Mistral board */
+ static u8 hw_led_state;
+
+
+-/* TPS65010 leds are changed using i2c -- from a task context.
+- * Using one of these for the "idle" LED would be impractical...
+- */
+-#define TPS_LEDS (GREEN_LED | RED_LED | AMBER_LED)
+-
+-static u8 tps_leds_change;
+-
+-static void tps_work(struct work_struct *unused)
+-{
+- for (;;) {
+- u8 leds;
+-
+- local_irq_disable();
+- leds = tps_leds_change;
+- tps_leds_change = 0;
+- local_irq_enable();
+-
+- if (!leds)
+- break;
+-
+- /* careful: the set_led() value is on/off/blink */
+- if (leds & GREEN_LED)
+- tps65010_set_led(LED1, !!(hw_led_state & GREEN_LED));
+- if (leds & AMBER_LED)
+- tps65010_set_led(LED2, !!(hw_led_state & AMBER_LED));
+-
+- /* the gpio led doesn't have that issue */
+- if (leds & RED_LED)
+- tps65010_set_gpio_out_value(GPIO2,
+- !(hw_led_state & RED_LED));
+- }
+-}
+-
+-static DECLARE_WORK(work, tps_work);
+-
+ #ifdef CONFIG_OMAP_OSK_MISTRAL
+
+ /* For now, all system indicators require the Mistral board, since that
+@@ -112,7 +72,6 @@ void osk_leds_event(led_event_t evt)
+ case led_stop:
+ led_state &= ~LED_STATE_ENABLED;
+ hw_led_state = 0;
+- /* NOTE: work may still be pending!! */
+ break;
+
+ case led_claim:
+@@ -145,48 +104,11 @@ void osk_leds_event(led_event_t evt)
+
+ #endif /* CONFIG_OMAP_OSK_MISTRAL */
+
+- /* "green" == tps LED1 (leftmost, normally power-good)
+- * works only with DC adapter, not on battery power!
+- */
+- case led_green_on:
+- if (led_state & LED_STATE_CLAIMED)
+- hw_led_state |= GREEN_LED;
+- break;
+- case led_green_off:
+- if (led_state & LED_STATE_CLAIMED)
+- hw_led_state &= ~GREEN_LED;
+- break;
+-
+- /* "amber" == tps LED2 (middle) */
+- case led_amber_on:
+- if (led_state & LED_STATE_CLAIMED)
+- hw_led_state |= AMBER_LED;
+- break;
+- case led_amber_off:
+- if (led_state & LED_STATE_CLAIMED)
+- hw_led_state &= ~AMBER_LED;
+- break;
+-
+- /* "red" == LED on tps gpio3 (rightmost) */
+- case led_red_on:
+- if (led_state & LED_STATE_CLAIMED)
+- hw_led_state |= RED_LED;
+- break;
+- case led_red_off:
+- if (led_state & LED_STATE_CLAIMED)
+- hw_led_state &= ~RED_LED;
+- break;
+-
+ default:
+ break;
+ }
+
+ leds ^= hw_led_state;
+- leds &= TPS_LEDS;
+- if (leds && (led_state & LED_STATE_CLAIMED)) {
+- tps_leds_change |= leds;
+- schedule_work(&work);
+- }
+
+ done:
+ local_irq_restore(flags);
+diff --git a/arch/arm/mach-omap1/mux.c b/arch/arm/mach-omap1/mux.c
+index 52c70e5..e207bf7 100644
+--- a/arch/arm/mach-omap1/mux.c
++++ b/arch/arm/mach-omap1/mux.c
+@@ -3,9 +3,9 @@
+ *
+ * OMAP1 pin multiplexing configurations
+ *
+- * Copyright (C) 2003 - 2005 Nokia Corporation
++ * Copyright (C) 2003 - 2008 Nokia Corporation
+ *
+- * Written by Tony Lindgren <tony.lindgren at nokia.com>
++ * Written by Tony Lindgren
+ *
+ * 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
+@@ -32,8 +32,10 @@
+
+ #ifdef CONFIG_OMAP_MUX
+
++static struct omap_mux_cfg arch_mux_cfg;
++
+ #ifdef CONFIG_ARCH_OMAP730
+-struct pin_config __initdata_or_module omap730_pins[] = {
++static struct pin_config __initdata_or_module omap730_pins[] = {
+ MUX_CFG_730("E2_730_KBR0", 12, 21, 0, 20, 1, 0)
+ MUX_CFG_730("J7_730_KBR1", 12, 25, 0, 24, 1, 0)
+ MUX_CFG_730("E1_730_KBR2", 12, 29, 0, 28, 1, 0)
+@@ -49,10 +51,14 @@ MUX_CFG_730("AA17_730_USB_DM", 2, 21, 0, 20, 0, 0)
+ MUX_CFG_730("W16_730_USB_PU_EN", 2, 25, 0, 24, 0, 0)
+ MUX_CFG_730("W17_730_USB_VBUSI", 2, 29, 0, 28, 0, 0)
+ };
+-#endif
++#define OMAP730_PINS_SZ ARRAY_SIZE(omap730_pins)
++#else
++#define omap730_pins NULL
++#define OMAP730_PINS_SZ 0
++#endif /* CONFIG_ARCH_OMAP730 */
+
+ #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
+-struct pin_config __initdata_or_module omap1xxx_pins[] = {
++static struct pin_config __initdata_or_module omap1xxx_pins[] = {
+ /*
+ * description mux mode mux pull pull pull pu_pd pu dbg
+ * reg offset mode reg bit ena reg
+@@ -306,22 +312,136 @@ MUX_CFG("Y12_1610_CCP_CLKP", 8, 18, 6, 1, 24, 1, 1, 0, 0)
+ MUX_CFG("W13_1610_CCP_CLKM", 9, 0, 6, 1, 28, 1, 1, 0, 0)
+ MUX_CFG("W14_1610_CCP_DATAP", 9, 24, 6, 2, 4, 1, 2, 0, 0)
+ MUX_CFG("Y14_1610_CCP_DATAM", 9, 21, 6, 2, 3, 1, 2, 0, 0)
+-
+ };
++#define OMAP1XXX_PINS_SZ ARRAY_SIZE(omap1xxx_pins)
++#else
++#define omap1xxx_pins NULL
++#define OMAP1XXX_PINS_SZ 0
+ #endif /* CONFIG_ARCH_OMAP15XX || CONFIG_ARCH_OMAP16XX */
+
+-int __init omap1_mux_init(void)
++int __init_or_module omap1_cfg_reg(const struct pin_config *cfg)
+ {
+-
+-#ifdef CONFIG_ARCH_OMAP730
+- omap_mux_register(omap730_pins, ARRAY_SIZE(omap730_pins));
++ static DEFINE_SPINLOCK(mux_spin_lock);
++ unsigned long flags;
++ unsigned int reg_orig = 0, reg = 0, pu_pd_orig = 0, pu_pd = 0,
++ pull_orig = 0, pull = 0;
++ unsigned int mask, warn = 0;
++
++ /* Check the mux register in question */
++ if (cfg->mux_reg) {
++ unsigned tmp1, tmp2;
++
++ spin_lock_irqsave(&mux_spin_lock, flags);
++ reg_orig = omap_readl(cfg->mux_reg);
++
++ /* The mux registers always seem to be 3 bits long */
++ mask = (0x7 << cfg->mask_offset);
++ tmp1 = reg_orig & mask;
++ reg = reg_orig & ~mask;
++
++ tmp2 = (cfg->mask << cfg->mask_offset);
++ reg |= tmp2;
++
++ if (tmp1 != tmp2)
++ warn = 1;
++
++ omap_writel(reg, cfg->mux_reg);
++ spin_unlock_irqrestore(&mux_spin_lock, flags);
++ }
++
++ /* Check for pull up or pull down selection on 1610 */
++ if (!cpu_is_omap15xx()) {
++ if (cfg->pu_pd_reg && cfg->pull_val) {
++ spin_lock_irqsave(&mux_spin_lock, flags);
++ pu_pd_orig = omap_readl(cfg->pu_pd_reg);
++ mask = 1 << cfg->pull_bit;
++
++ if (cfg->pu_pd_val) {
++ if (!(pu_pd_orig & mask))
++ warn = 1;
++ /* Use pull up */
++ pu_pd = pu_pd_orig | mask;
++ } else {
++ if (pu_pd_orig & mask)
++ warn = 1;
++ /* Use pull down */
++ pu_pd = pu_pd_orig & ~mask;
++ }
++ omap_writel(pu_pd, cfg->pu_pd_reg);
++ spin_unlock_irqrestore(&mux_spin_lock, flags);
++ }
++ }
++
++ /* Check for an associated pull down register */
++ if (cfg->pull_reg) {
++ spin_lock_irqsave(&mux_spin_lock, flags);
++ pull_orig = omap_readl(cfg->pull_reg);
++ mask = 1 << cfg->pull_bit;
++
++ if (cfg->pull_val) {
++ if (pull_orig & mask)
++ warn = 1;
++ /* Low bit = pull enabled */
++ pull = pull_orig & ~mask;
++ } else {
++ if (!(pull_orig & mask))
++ warn = 1;
++ /* High bit = pull disabled */
++ pull = pull_orig | mask;
++ }
++
++ omap_writel(pull, cfg->pull_reg);
++ spin_unlock_irqrestore(&mux_spin_lock, flags);
++ }
++
++ if (warn) {
++#ifdef CONFIG_OMAP_MUX_WARNINGS
++ printk(KERN_WARNING "MUX: initialized %s\n", cfg->name);
+ #endif
+-
+-#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
+- omap_mux_register(omap1xxx_pins, ARRAY_SIZE(omap1xxx_pins));
++ }
++
++#ifdef CONFIG_OMAP_MUX_DEBUG
++ if (cfg->debug || warn) {
++ printk("MUX: Setting register %s\n", cfg->name);
++ printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n",
++ cfg->mux_reg_name, cfg->mux_reg, reg_orig, reg);
++
++ if (!cpu_is_omap15xx()) {
++ if (cfg->pu_pd_reg && cfg->pull_val) {
++ printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n",
++ cfg->pu_pd_name, cfg->pu_pd_reg,
++ pu_pd_orig, pu_pd);
++ }
++ }
++
++ if (cfg->pull_reg)
++ printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n",
++ cfg->pull_name, cfg->pull_reg, pull_orig, pull);
++ }
+ #endif
+
++#ifdef CONFIG_OMAP_MUX_ERRORS
++ return warn ? -ETXTBSY : 0;
++#else
+ return 0;
++#endif
++}
++
++int __init omap1_mux_init(void)
++{
++ if (cpu_is_omap730()) {
++ arch_mux_cfg.pins = omap730_pins;
++ arch_mux_cfg.size = OMAP730_PINS_SZ;
++ arch_mux_cfg.cfg_reg = omap1_cfg_reg;
++ }
++
++ if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
++ arch_mux_cfg.pins = omap1xxx_pins;
++ arch_mux_cfg.size = OMAP1XXX_PINS_SZ;
++ arch_mux_cfg.cfg_reg = omap1_cfg_reg;
++ }
++
++ return omap_mux_register(&arch_mux_cfg);
+ }
+
+ #endif
+diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c
+index a4f8b20..5d2b270 100644
+--- a/arch/arm/mach-omap1/time.c
++++ b/arch/arm/mach-omap1/time.c
+@@ -56,37 +56,6 @@
+ #define OMAP_MPU_TIMER_BASE OMAP_MPU_TIMER1_BASE
+ #define OMAP_MPU_TIMER_OFFSET 0x100
+
+-/* cycles to nsec conversions taken from arch/i386/kernel/timers/timer_tsc.c,
+- * converted to use kHz by Kevin Hilman */
+-/* convert from cycles(64bits) => nanoseconds (64bits)
+- * basic equation:
+- * ns = cycles / (freq / ns_per_sec)
+- * ns = cycles * (ns_per_sec / freq)
+- * ns = cycles * (10^9 / (cpu_khz * 10^3))
+- * ns = cycles * (10^6 / cpu_khz)
+- *
+- * Then we use scaling math (suggested by george at mvista.com) to get:
+- * ns = cycles * (10^6 * SC / cpu_khz / SC
+- * ns = cycles * cyc2ns_scale / SC
+- *
+- * And since SC is a constant power of two, we can convert the div
+- * into a shift.
+- * -johnstul at us.ibm.com "math is hard, lets go shopping!"
+- */
+-static unsigned long cyc2ns_scale;
+-#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
+-
+-static inline void set_cyc2ns_scale(unsigned long cpu_khz)
+-{
+- cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz;
+-}
+-
+-static inline unsigned long long cycles_2_ns(unsigned long long cyc)
+-{
+- return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
+-}
+-
+-
+ typedef struct {
+ u32 cntl; /* CNTL_TIMER, R/W */
+ u32 load_tim; /* LOAD_TIM, W */
+@@ -194,8 +163,6 @@ static struct irqaction omap_mpu_timer1_irq = {
+
+ static __init void omap_init_mpu_timer(unsigned long rate)
+ {
+- set_cyc2ns_scale(rate / 1000);
+-
+ setup_irq(INT_TIMER1, &omap_mpu_timer1_irq);
+ omap_mpu_timer_start(0, (rate / HZ) - 1, 1);
+
+@@ -260,22 +227,6 @@ static void __init omap_init_clocksource(unsigned long rate)
+ printk(err, clocksource_mpu.name);
+ }
+
+-
+-/*
+- * Scheduler clock - returns current time in nanosec units.
+- */
+-unsigned long long sched_clock(void)
+-{
+- unsigned long ticks = 0 - omap_mpu_timer_read(1);
+- unsigned long long ticks64;
+-
+- ticks64 = omap_mpu_timer2_overflows;
+- ticks64 <<= 32;
+- ticks64 |= ticks;
+-
+- return cycles_2_ns(ticks64);
+-}
+-
+ /*
+ * ---------------------------------------------------------------------------
+ * Timer initialization
+diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c
+new file mode 100644
+index 0000000..fbbdb80
+--- /dev/null
++++ b/arch/arm/mach-omap1/timer32k.c
+@@ -0,0 +1,209 @@
++/*
++ * linux/arch/arm/mach-omap1/timer32k.c
++ *
++ * OMAP 32K Timer
++ *
++ * Copyright (C) 2004 - 2005 Nokia Corporation
++ * Partial timer rewrite and additional dynamic tick timer support by
++ * Tony Lindgen <tony at atomide.com> and
++ * Tuukka Tikkanen <tuukka.tikkanen at elektrobit.com>
++ * OMAP Dual-mode timer framework support by Timo Teras
++ *
++ * MPU timer code based on the older MPU timer code for OMAP
++ * Copyright (C) 2000 RidgeRun, Inc.
++ * Author: Greg Lonnon <glonnon at ridgerun.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/sched.h>
++#include <linux/spinlock.h>
++#include <linux/err.h>
++#include <linux/clk.h>
++#include <linux/clocksource.h>
++#include <linux/clockchips.h>
++
++#include <asm/system.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/leds.h>
++#include <asm/irq.h>
++#include <asm/mach/irq.h>
++#include <asm/mach/time.h>
++#include <asm/arch/dmtimer.h>
++
++struct sys_timer omap_timer;
++
++/*
++ * ---------------------------------------------------------------------------
++ * 32KHz OS timer
++ *
++ * This currently works only on 16xx, as 1510 does not have the continuous
++ * 32KHz synchronous timer. The 32KHz synchronous timer is used to keep track
++ * of time in addition to the 32KHz OS timer. Using only the 32KHz OS timer
++ * on 1510 would be possible, but the timer would not be as accurate as
++ * with the 32KHz synchronized timer.
++ * ---------------------------------------------------------------------------
++ */
++
++#if defined(CONFIG_ARCH_OMAP16XX)
++#define TIMER_32K_SYNCHRONIZED 0xfffbc410
++#else
++#error OMAP 32KHz timer does not currently work on 15XX!
++#endif
++
++/* 16xx specific defines */
++#define OMAP1_32K_TIMER_BASE 0xfffb9000
++#define OMAP1_32K_TIMER_CR 0x08
++#define OMAP1_32K_TIMER_TVR 0x00
++#define OMAP1_32K_TIMER_TCR 0x04
++
++#define OMAP_32K_TICKS_PER_SEC (32768)
++
++/*
++ * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1
++ * so with HZ = 128, TVR = 255.
++ */
++#define OMAP_32K_TIMER_TICK_PERIOD ((OMAP_32K_TICKS_PER_SEC / HZ) - 1)
++
++#define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate) \
++ (((nr_jiffies) * (clock_rate)) / HZ)
++
++static inline void omap_32k_timer_write(int val, int reg)
++{
++ omap_writew(val, OMAP1_32K_TIMER_BASE + reg);
++}
++
++static inline unsigned long omap_32k_timer_read(int reg)
++{
++ return omap_readl(OMAP1_32K_TIMER_BASE + reg) & 0xffffff;
++}
++
++static inline void omap_32k_timer_start(unsigned long load_val)
++{
++ if (!load_val)
++ load_val = 1;
++ omap_32k_timer_write(load_val, OMAP1_32K_TIMER_TVR);
++ omap_32k_timer_write(0x0f, OMAP1_32K_TIMER_CR);
++}
++
++static inline void omap_32k_timer_stop(void)
++{
++ omap_32k_timer_write(0x0, OMAP1_32K_TIMER_CR);
++}
++
++#define omap_32k_timer_ack_irq()
++
++static int omap_32k_timer_set_next_event(unsigned long delta,
++ struct clock_event_device *dev)
++{
++ omap_32k_timer_start(delta);
++
++ return 0;
++}
++
++static void omap_32k_timer_set_mode(enum clock_event_mode mode,
++ struct clock_event_device *evt)
++{
++ omap_32k_timer_stop();
++
++ switch (mode) {
++ case CLOCK_EVT_MODE_PERIODIC:
++ omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
++ break;
++ case CLOCK_EVT_MODE_ONESHOT:
++ case CLOCK_EVT_MODE_UNUSED:
++ case CLOCK_EVT_MODE_SHUTDOWN:
++ break;
++ case CLOCK_EVT_MODE_RESUME:
++ break;
++ }
++}
++
++static struct clock_event_device clockevent_32k_timer = {
++ .name = "32k-timer",
++ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
++ .shift = 32,
++ .set_next_event = omap_32k_timer_set_next_event,
++ .set_mode = omap_32k_timer_set_mode,
++};
++
++/*
++ * The 32KHz synchronized timer is an additional timer on 16xx.
++ * It is always running.
++ */
++static inline unsigned long omap_32k_sync_timer_read(void)
++{
++ return omap_readl(TIMER_32K_SYNCHRONIZED);
++}
++
++static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id)
++{
++ struct clock_event_device *evt = &clockevent_32k_timer;
++ omap_32k_timer_ack_irq();
++
++ evt->event_handler(evt);
++
++ return IRQ_HANDLED;
++}
++
++static struct irqaction omap_32k_timer_irq = {
++ .name = "32KHz timer",
++ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
++ .handler = omap_32k_timer_interrupt,
++};
++
++static __init void omap_init_32k_timer(void)
++{
++ setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
++
++ clockevent_32k_timer.mult = div_sc(OMAP_32K_TICKS_PER_SEC,
++ NSEC_PER_SEC,
++ clockevent_32k_timer.shift);
++ clockevent_32k_timer.max_delta_ns =
++ clockevent_delta2ns(0xfffffffe, &clockevent_32k_timer);
++ clockevent_32k_timer.min_delta_ns =
++ clockevent_delta2ns(1, &clockevent_32k_timer);
++
++ clockevent_32k_timer.cpumask = cpumask_of_cpu(0);
++ clockevents_register_device(&clockevent_32k_timer);
++}
++
++/*
++ * ---------------------------------------------------------------------------
++ * Timer initialization
++ * ---------------------------------------------------------------------------
++ */
++static void __init omap_timer_init(void)
++{
++#ifdef CONFIG_OMAP_DM_TIMER
++ omap_dm_timer_init();
++#endif
++ omap_init_32k_timer();
++}
++
++struct sys_timer omap_timer = {
++ .init = omap_timer_init,
++};
+diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
+index b05b738..2feb687 100644
+--- a/arch/arm/mach-omap2/Makefile
++++ b/arch/arm/mach-omap2/Makefile
+@@ -3,13 +3,15 @@
+ #
+
+ # Common support
+-obj-y := irq.o id.o io.o sram-fn.o memory.o prcm.o clock.o mux.o devices.o \
+- serial.o gpmc.o
+-
+-obj-$(CONFIG_OMAP_MPU_TIMER) += timer-gp.o
++obj-y := irq.o id.o io.o sram-fn.o memory.o control.o prcm.o clock.o mux.o \
++ devices.o serial.o gpmc.o timer-gp.o
+
+ # Power Management
+-obj-$(CONFIG_PM) += pm.o pm-domain.o sleep.o
++obj-$(CONFIG_PM) += pm.o sleep.o
++
++# Clock framework
++obj-$(CONFIG_ARCH_OMAP2) += clock24xx.o
++obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o
+
+ # Specific board support
+ obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
+diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
+index 64235de..1c12d7c 100644
+--- a/arch/arm/mach-omap2/board-2430sdp.c
++++ b/arch/arm/mach-omap2/board-2430sdp.c
+@@ -33,7 +33,6 @@
+ #include <asm/arch/board.h>
+ #include <asm/arch/common.h>
+ #include <asm/arch/gpmc.h>
+-#include "prcm-regs.h"
+
+ #include <asm/io.h>
+
+@@ -125,15 +124,18 @@ static inline void __init sdp2430_init_smc91x(void)
+ int eth_cs;
+ unsigned long cs_mem_base;
+ unsigned int rate;
+- struct clk *l3ck;
++ struct clk *gpmc_fck;
+
+ eth_cs = SDP2430_SMC91X_CS;
+
+- l3ck = clk_get(NULL, "core_l3_ck");
+- if (IS_ERR(l3ck))
+- rate = 100000000;
+- else
+- rate = clk_get_rate(l3ck);
++ gpmc_fck = clk_get(NULL, "gpmc_fck"); /* Always on ENABLE_ON_INIT */
++ if (IS_ERR(gpmc_fck)) {
++ WARN_ON(1);
++ return;
++ }
++
++ clk_enable(gpmc_fck);
++ rate = clk_get_rate(gpmc_fck);
+
+ /* Make sure CS1 timings are correct, for 2430 always muxed */
+ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1, 0x00011200);
+@@ -160,7 +162,7 @@ static inline void __init sdp2430_init_smc91x(void)
+
+ if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) {
+ printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
+- return;
++ goto out;
+ }
+
+ sdp2430_smc91x_resources[0].start = cs_mem_base + 0x300;
+@@ -171,10 +173,13 @@ static inline void __init sdp2430_init_smc91x(void)
+ printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
+ OMAP24XX_ETHR_GPIO_IRQ);
+ gpmc_cs_free(eth_cs);
+- return;
++ goto out;
+ }
+ omap_set_gpio_direction(OMAP24XX_ETHR_GPIO_IRQ, 1);
+
++out:
++ clk_disable(gpmc_fck);
++ clk_put(gpmc_fck);
+ }
+
+ static void __init omap_2430sdp_init_irq(void)
+diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
+index 7846551..a1e1e67 100644
+--- a/arch/arm/mach-omap2/board-apollon.c
++++ b/arch/arm/mach-omap2/board-apollon.c
+@@ -26,6 +26,8 @@
+ #include <linux/interrupt.h>
+ #include <linux/delay.h>
+ #include <linux/leds.h>
++#include <linux/err.h>
++#include <linux/clk.h>
+
+ #include <asm/hardware.h>
+ #include <asm/mach-types.h>
+@@ -39,7 +41,7 @@
+ #include <asm/arch/board.h>
+ #include <asm/arch/common.h>
+ #include <asm/arch/gpmc.h>
+-#include "prcm-regs.h"
++#include <asm/arch/control.h>
+
+ /* LED & Switch macros */
+ #define LED0_GPIO13 13
+@@ -187,17 +189,47 @@ static inline void __init apollon_init_smc91x(void)
+ {
+ unsigned long base;
+
++ unsigned int rate;
++ struct clk *gpmc_fck;
++ int eth_cs;
++
++ gpmc_fck = clk_get(NULL, "gpmc_fck"); /* Always on ENABLE_ON_INIT */
++ if (IS_ERR(gpmc_fck)) {
++ WARN_ON(1);
++ return;
++ }
++
++ clk_enable(gpmc_fck);
++ rate = clk_get_rate(gpmc_fck);
++
++ eth_cs = APOLLON_ETH_CS;
++
+ /* Make sure CS1 timings are correct */
+- GPMC_CONFIG1_1 = 0x00011203;
+- GPMC_CONFIG2_1 = 0x001f1f01;
+- GPMC_CONFIG3_1 = 0x00080803;
+- GPMC_CONFIG4_1 = 0x1c091c09;
+- GPMC_CONFIG5_1 = 0x041f1f1f;
+- GPMC_CONFIG6_1 = 0x000004c4;
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1, 0x00011200);
++
++ if (rate >= 160000000) {
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f01);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080803);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1c0b1c0a);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
++ } else if (rate >= 130000000) {
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
++ } else {/* rate = 100000000 */
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x031A1F1F);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000003C2);
++ }
+
+ if (gpmc_cs_request(APOLLON_ETH_CS, SZ_16M, &base) < 0) {
+ printk(KERN_ERR "Failed to request GPMC CS for smc91x\n");
+- return;
++ goto out;
+ }
+ apollon_smc91x_resources[0].start = base + 0x300;
+ apollon_smc91x_resources[0].end = base + 0x30f;
+@@ -208,9 +240,13 @@ static inline void __init apollon_init_smc91x(void)
+ printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
+ APOLLON_ETHR_GPIO_IRQ);
+ gpmc_cs_free(APOLLON_ETH_CS);
+- return;
++ goto out;
+ }
+ omap_set_gpio_direction(APOLLON_ETHR_GPIO_IRQ, 1);
++
++out:
++ clk_disable(gpmc_fck);
++ clk_put(gpmc_fck);
+ }
+
+ static void __init omap_apollon_init_irq(void)
+@@ -330,6 +366,8 @@ static void __init apollon_usb_init(void)
+
+ static void __init omap_apollon_init(void)
+ {
++ u32 v;
++
+ apollon_led_init();
+ apollon_sw_init();
+ apollon_flash_init();
+@@ -339,7 +377,9 @@ static void __init omap_apollon_init(void)
+ omap_cfg_reg(W19_24XX_SYS_NIRQ);
+
+ /* Use Interal loop-back in MMC/SDIO Module Input Clock selection */
+- CONTROL_DEVCONF |= (1 << 24);
++ v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
++ v |= (1 << 24);
++ omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
+
+ /*
+ * Make sure the serial ports are muxed on at this point.
+diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
+index f125f43..d1915f9 100644
+--- a/arch/arm/mach-omap2/board-h4.c
++++ b/arch/arm/mach-omap2/board-h4.c
+@@ -19,6 +19,8 @@
+ #include <linux/delay.h>
+ #include <linux/workqueue.h>
+ #include <linux/input.h>
++#include <linux/err.h>
++#include <linux/clk.h>
+
+ #include <asm/hardware.h>
+ #include <asm/mach-types.h>
+@@ -26,6 +28,7 @@
+ #include <asm/mach/map.h>
+ #include <asm/mach/flash.h>
+
++#include <asm/arch/control.h>
+ #include <asm/arch/gpio.h>
+ #include <asm/arch/gpioexpander.h>
+ #include <asm/arch/mux.h>
+@@ -36,10 +39,13 @@
+ #include <asm/arch/keypad.h>
+ #include <asm/arch/menelaus.h>
+ #include <asm/arch/dma.h>
+-#include "prcm-regs.h"
++#include <asm/arch/gpmc.h>
+
+ #include <asm/io.h>
+
++#define H4_FLASH_CS 0
++#define H4_SMC91X_CS 1
++
+ static unsigned int row_gpios[6] = { 88, 89, 124, 11, 6, 96 };
+ static unsigned int col_gpios[7] = { 90, 91, 100, 36, 12, 97, 98 };
+
+@@ -116,8 +122,6 @@ static struct flash_platform_data h4_flash_data = {
+ };
+
+ static struct resource h4_flash_resource = {
+- .start = H4_CS0_BASE,
+- .end = H4_CS0_BASE + SZ_64M - 1,
+ .flags = IORESOURCE_MEM,
+ };
+
+@@ -253,21 +257,107 @@ static struct platform_device *h4_devices[] __initdata = {
+ &h4_lcd_device,
+ };
+
++/* 2420 Sysboot setup (2430 is different) */
++static u32 get_sysboot_value(void)
++{
++ return (omap_ctrl_readl(OMAP24XX_CONTROL_STATUS) &
++ (OMAP2_SYSBOOT_5_MASK | OMAP2_SYSBOOT_4_MASK |
++ OMAP2_SYSBOOT_3_MASK | OMAP2_SYSBOOT_2_MASK |
++ OMAP2_SYSBOOT_1_MASK | OMAP2_SYSBOOT_0_MASK));
++}
++
++/* H4-2420's always used muxed mode, H4-2422's always use non-muxed
++ *
++ * Note: OMAP-GIT doesn't correctly do is_cpu_omap2422 and is_cpu_omap2423
++ * correctly. The macro needs to look at production_id not just hawkeye.
++ */
++static u32 is_gpmc_muxed(void)
++{
++ u32 mux;
++ mux = get_sysboot_value();
++ if ((mux & 0xF) == 0xd)
++ return 1; /* NAND config (could be either) */
++ if (mux & 0x2) /* if mux'ed */
++ return 1;
++ else
++ return 0;
++}
++
+ static inline void __init h4_init_debug(void)
+ {
++ int eth_cs;
++ unsigned long cs_mem_base;
++ unsigned int muxed, rate;
++ struct clk *gpmc_fck;
++
++ eth_cs = H4_SMC91X_CS;
++
++ gpmc_fck = clk_get(NULL, "gpmc_fck"); /* Always on ENABLE_ON_INIT */
++ if (IS_ERR(gpmc_fck)) {
++ WARN_ON(1);
++ return;
++ }
++
++ clk_enable(gpmc_fck);
++ rate = clk_get_rate(gpmc_fck);
++ clk_disable(gpmc_fck);
++ clk_put(gpmc_fck);
++
++ if (is_gpmc_muxed())
++ muxed = 0x200;
++ else
++ muxed = 0;
++
+ /* Make sure CS1 timings are correct */
+- GPMC_CONFIG1_1 = 0x00011200;
+- GPMC_CONFIG2_1 = 0x001f1f01;
+- GPMC_CONFIG3_1 = 0x00080803;
+- GPMC_CONFIG4_1 = 0x1c091c09;
+- GPMC_CONFIG5_1 = 0x041f1f1f;
+- GPMC_CONFIG6_1 = 0x000004c4;
+- GPMC_CONFIG7_1 = 0x00000f40 | (0x08000000 >> 24);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1,
++ 0x00011000 | muxed);
++
++ if (rate >= 160000000) {
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f01);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080803);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1c0b1c0a);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
++ } else if (rate >= 130000000) {
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
++ } else {/* rate = 100000000 */
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x031A1F1F);
++ gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000003C2);
++ }
++
++ if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) {
++ printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
++ goto out;
++ }
++
+ udelay(100);
+
+ omap_cfg_reg(M15_24XX_GPIO92);
+ if (debug_card_init(cs_mem_base, OMAP24XX_ETHR_GPIO_IRQ) < 0)
+ gpmc_cs_free(eth_cs);
++
++out:
++ clk_disable(gpmc_fck);
++ clk_put(gpmc_fck);
++}
++
++static void __init h4_init_flash(void)
++{
++ unsigned long base;
++
++ if (gpmc_cs_request(H4_FLASH_CS, SZ_64M, &base) < 0) {
++ printk("Can't request GPMC CS for flash\n");
++ return;
++ }
++ h4_flash_resource.start = base;
++ h4_flash_resource.end = base + SZ_64M - 1;
+ }
+
+ static void __init omap_h4_init_irq(void)
+@@ -275,6 +365,7 @@ static void __init omap_h4_init_irq(void)
+ omap2_init_common_hw();
+ omap_init_irq();
+ omap_gpio_init();
++ h4_init_flash();
+ }
+
+ static struct omap_uart_config h4_uart_config __initdata = {
+diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
+index e6e85b7..b57ffb5 100644
+--- a/arch/arm/mach-omap2/clock.c
++++ b/arch/arm/mach-omap2/clock.c
+@@ -1,20 +1,19 @@
+ /*
+ * linux/arch/arm/mach-omap2/clock.c
+ *
+- * Copyright (C) 2005 Texas Instruments Inc.
+- * Richard Woodruff <r-woodruff2 at ti.com>
+- * Created for OMAP2.
+- *
+- * Cleaned up and modified to use omap shared clock framework by
+- * Tony Lindgren <tony at atomide.com>
++ * Copyright (C) 2005-2008 Texas Instruments, Inc.
++ * Copyright (C) 2004-2008 Nokia Corporation
+ *
+- * Based on omap1 clock.c, Copyright (C) 2004 - 2005 Nokia corporation
+- * Written by Tuukka Tikkanen <tuukka.tikkanen at elektrobit.com>
++ * Contacts:
++ * Richard Woodruff <r-woodruff2 at ti.com>
++ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
++#undef DEBUG
++
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/device.h>
+@@ -22,176 +21,227 @@
+ #include <linux/errno.h>
+ #include <linux/delay.h>
+ #include <linux/clk.h>
++#include <asm/bitops.h>
+
+ #include <asm/io.h>
+
+ #include <asm/arch/clock.h>
+ #include <asm/arch/sram.h>
++#include <asm/arch/cpu.h>
+ #include <asm/div64.h>
+
+-#include "prcm-regs.h"
+ #include "memory.h"
++#include "sdrc.h"
+ #include "clock.h"
++#include "prm.h"
++#include "prm-regbits-24xx.h"
++#include "cm.h"
++#include "cm-regbits-24xx.h"
++#include "cm-regbits-34xx.h"
+
+-#undef DEBUG
+-
+-//#define DOWN_VARIABLE_DPLL 1 /* Experimental */
++#define MAX_CLOCK_ENABLE_WAIT 100000
+
+-static struct prcm_config *curr_prcm_set;
+-static u32 curr_perf_level = PRCM_FULL_SPEED;
+-static struct clk *vclk;
+-static struct clk *sclk;
++u8 cpu_mask;
+
+ /*-------------------------------------------------------------------------
+ * Omap2 specific clock functions
+ *-------------------------------------------------------------------------*/
+
+-/* Recalculate SYST_CLK */
+-static void omap2_sys_clk_recalc(struct clk * clk)
++/**
++ * omap2_init_clksel_parent - set a clksel clk's parent field from the hardware
++ * @clk: OMAP clock struct ptr to use
++ *
++ * Given a pointer to a source-selectable struct clk, read the hardware
++ * register and determine what its parent is currently set to. Update the
++ * clk->parent field with the appropriate clk ptr.
++ */
++void omap2_init_clksel_parent(struct clk *clk)
+ {
+- u32 div = PRCM_CLKSRC_CTRL;
+- div &= (1 << 7) | (1 << 6); /* Test if ext clk divided by 1 or 2 */
+- div >>= clk->rate_offset;
+- clk->rate = (clk->parent->rate / div);
+- propagate_rate(clk);
++ const struct clksel *clks;
++ const struct clksel_rate *clkr;
++ u32 r, found = 0;
++
++ if (!clk->clksel)
++ return;
++
++ r = __raw_readl(clk->clksel_reg) & clk->clksel_mask;
++ r >>= __ffs(clk->clksel_mask);
++
++ for (clks = clk->clksel; clks->parent && !found; clks++) {
++ for (clkr = clks->rates; clkr->div && !found; clkr++) {
++ if ((clkr->flags & cpu_mask) && (clkr->val == r)) {
++ if (clk->parent != clks->parent) {
++ pr_debug("clock: inited %s parent "
++ "to %s (was %s)\n",
++ clk->name, clks->parent->name,
++ ((clk->parent) ?
++ clk->parent->name : "NULL"));
++ clk->parent = clks->parent;
++ };
++ found = 1;
++ }
++ }
++ }
++
++ if (!found)
++ printk(KERN_ERR "clock: init parent: could not find "
++ "regval %0x for clock %s\n", r, clk->name);
++
++ return;
+ }
+
+-static u32 omap2_get_dpll_rate(struct clk * tclk)
++/* Returns the DPLL rate */
++u32 omap2_get_dpll_rate(struct clk *clk)
+ {
+ long long dpll_clk;
+- int dpll_mult, dpll_div, amult;
++ u32 dpll_mult, dpll_div, dpll;
++ const struct dpll_data *dd;
++
++ dd = clk->dpll_data;
++ /* REVISIT: What do we return on error? */
++ if (!dd)
++ return 0;
++
++ dpll = __raw_readl(dd->mult_div1_reg);
++ dpll_mult = dpll & dd->mult_mask;
++ dpll_mult >>= __ffs(dd->mult_mask);
++ dpll_div = dpll & dd->div1_mask;
++ dpll_div >>= __ffs(dd->div1_mask);
+
+- dpll_mult = (CM_CLKSEL1_PLL >> 12) & 0x03ff; /* 10 bits */
+- dpll_div = (CM_CLKSEL1_PLL >> 8) & 0x0f; /* 4 bits */
+- dpll_clk = (long long)tclk->parent->rate * dpll_mult;
++ dpll_clk = (long long)clk->parent->rate * dpll_mult;
+ do_div(dpll_clk, dpll_div + 1);
+- amult = CM_CLKSEL2_PLL & 0x3;
+- dpll_clk *= amult;
+
+ return dpll_clk;
+ }
+
+-static void omap2_followparent_recalc(struct clk *clk)
+-{
+- followparent_recalc(clk);
+-}
+-
+-static void omap2_propagate_rate(struct clk * clk)
++/*
++ * Used for clocks that have the same value as the parent clock,
++ * divided by some factor
++ */
++void omap2_fixed_divisor_recalc(struct clk *clk)
+ {
+- if (!(clk->flags & RATE_FIXED))
+- clk->rate = clk->parent->rate;
++ WARN_ON(!clk->fixed_div);
+
+- propagate_rate(clk);
+-}
++ clk->rate = clk->parent->rate / clk->fixed_div;
+
+-static void omap2_set_osc_ck(int enable)
+-{
+- if (enable)
+- PRCM_CLKSRC_CTRL &= ~(0x3 << 3);
+- else
+- PRCM_CLKSRC_CTRL |= 0x3 << 3;
++ if (clk->flags & RATE_PROPAGATES)
++ propagate_rate(clk);
+ }
+
+-/* Enable an APLL if off */
+-static void omap2_clk_fixed_enable(struct clk *clk)
++/**
++ * omap2_wait_clock_ready - wait for clock to enable
++ * @reg: physical address of clock IDLEST register
++ * @mask: value to mask against to determine if the clock is active
++ * @name: name of the clock (for printk)
++ *
++ * Returns 1 if the clock enabled in time, or 0 if it failed to enable
++ * in roughly MAX_CLOCK_ENABLE_WAIT microseconds.
++ */
++int omap2_wait_clock_ready(void __iomem *reg, u32 mask, const char *name)
+ {
+- u32 cval, i=0;
++ int i = 0;
++ int ena = 0;
+
+- if (clk->enable_bit == 0xff) /* Parent will do it */
+- return;
++ /*
++ * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
++ * 34xx reverses this, just to keep us on our toes
++ */
++ if (cpu_mask & (RATE_IN_242X | RATE_IN_243X)) {
++ ena = mask;
++ } else if (cpu_mask & RATE_IN_343X) {
++ ena = 0;
++ }
+
+- cval = CM_CLKEN_PLL;
++ /* Wait for lock */
++ while (((__raw_readl(reg) & mask) != ena) &&
++ (i++ < MAX_CLOCK_ENABLE_WAIT)) {
++ udelay(1);
++ }
+
+- if ((cval & (0x3 << clk->enable_bit)) == (0x3 << clk->enable_bit))
+- return;
++ if (i < MAX_CLOCK_ENABLE_WAIT)
++ pr_debug("Clock %s stable after %d loops\n", name, i);
++ else
++ printk(KERN_ERR "Clock %s didn't enable in %d tries\n",
++ name, MAX_CLOCK_ENABLE_WAIT);
+
+- cval &= ~(0x3 << clk->enable_bit);
+- cval |= (0x3 << clk->enable_bit);
+- CM_CLKEN_PLL = cval;
+
+- if (clk == &apll96_ck)
+- cval = (1 << 8);
+- else if (clk == &apll54_ck)
+- cval = (1 << 6);
++ return (i < MAX_CLOCK_ENABLE_WAIT) ? 1 : 0;
++};
+
+- while (!(CM_IDLEST_CKGEN & cval)) { /* Wait for lock */
+- ++i;
+- udelay(1);
+- if (i == 100000) {
+- printk(KERN_ERR "Clock %s didn't lock\n", clk->name);
+- break;
+- }
+- }
+-}
+
++/*
++ * Note: We don't need special code here for INVERT_ENABLE
++ * for the time being since INVERT_ENABLE only applies to clocks enabled by
++ * CM_CLKEN_PLL
++ */
+ static void omap2_clk_wait_ready(struct clk *clk)
+ {
+- unsigned long reg, other_reg, st_reg;
++ void __iomem *reg, *other_reg, *st_reg;
+ u32 bit;
+- int i;
+-
+- reg = (unsigned long) clk->enable_reg;
+- if (reg == (unsigned long) &CM_FCLKEN1_CORE ||
+- reg == (unsigned long) &CM_FCLKEN2_CORE)
+- other_reg = (reg & ~0xf0) | 0x10;
+- else if (reg == (unsigned long) &CM_ICLKEN1_CORE ||
+- reg == (unsigned long) &CM_ICLKEN2_CORE)
+- other_reg = (reg & ~0xf0) | 0x00;
++
++ /*
++ * REVISIT: This code is pretty ugly. It would be nice to generalize
++ * it and pull it into struct clk itself somehow.
++ */
++ reg = clk->enable_reg;
++ if ((((u32)reg & 0xff) >= CM_FCLKEN1) &&
++ (((u32)reg & 0xff) <= OMAP24XX_CM_FCLKEN2))
++ other_reg = (void __iomem *)(((u32)reg & ~0xf0) | 0x10); /* CM_ICLKEN* */
++ else if ((((u32)reg & 0xff) >= CM_ICLKEN1) &&
++ (((u32)reg & 0xff) <= OMAP24XX_CM_ICLKEN4))
++ other_reg = (void __iomem *)(((u32)reg & ~0xf0) | 0x00); /* CM_FCLKEN* */
+ else
+ return;
+
++ /* REVISIT: What are the appropriate exclusions for 34XX? */
+ /* No check for DSS or cam clocks */
+- if ((reg & 0x0f) == 0) {
+- if (clk->enable_bit <= 1 || clk->enable_bit == 31)
++ if (cpu_is_omap24xx() && ((u32)reg & 0x0f) == 0) { /* CM_{F,I}CLKEN1 */
++ if (clk->enable_bit == OMAP24XX_EN_DSS2_SHIFT ||
++ clk->enable_bit == OMAP24XX_EN_DSS1_SHIFT ||
++ clk->enable_bit == OMAP24XX_EN_CAM_SHIFT)
+ return;
+ }
+
++ /* REVISIT: What are the appropriate exclusions for 34XX? */
++ /* OMAP3: ignore DSS-mod clocks */
++ if (cpu_is_omap34xx() &&
++ (((u32)reg & ~0xff) == (u32)OMAP_CM_REGADDR(OMAP3430_DSS_MOD, 0)))
++ return;
++
+ /* Check if both functional and interface clocks
+ * are running. */
+ bit = 1 << clk->enable_bit;
+ if (!(__raw_readl(other_reg) & bit))
+ return;
+- st_reg = (other_reg & ~0xf0) | 0x20;
+- i = 0;
+- while (!(__raw_readl(st_reg) & bit)) {
+- i++;
+- if (i == 100000) {
+- printk(KERN_ERR "Timeout enabling clock %s\n", clk->name);
+- break;
+- }
+- }
+- if (i)
+- pr_debug("Clock %s stable after %d loops\n", clk->name, i);
++ st_reg = (void __iomem *)(((u32)other_reg & ~0xf0) | 0x20); /* CM_IDLEST* */
++
++ omap2_wait_clock_ready(st_reg, bit, clk->name);
+ }
+
+ /* Enables clock without considering parent dependencies or use count
+ * REVISIT: Maybe change this to use clk->enable like on omap1?
+ */
+-static int _omap2_clk_enable(struct clk * clk)
++int _omap2_clk_enable(struct clk *clk)
+ {
+ u32 regval32;
+
+- if (clk->flags & ALWAYS_ENABLED)
++ if (clk->flags & (ALWAYS_ENABLED | PARENT_CONTROLS_CLOCK))
+ return 0;
+
+- if (unlikely(clk == &osc_ck)) {
+- omap2_set_osc_ck(1);
+- return 0;
+- }
++ if (clk->enable)
++ return clk->enable(clk);
+
+ if (unlikely(clk->enable_reg == 0)) {
+ printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
+ clk->name);
+- return 0;
+- }
+-
+- if (clk->enable_reg == (void __iomem *)&CM_CLKEN_PLL) {
+- omap2_clk_fixed_enable(clk);
+- return 0;
++ return 0; /* REVISIT: -EINVAL */
+ }
+
+ regval32 = __raw_readl(clk->enable_reg);
+- regval32 |= (1 << clk->enable_bit);
++ if (clk->flags & INVERT_ENABLE)
++ regval32 &= ~(1 << clk->enable_bit);
++ else
++ regval32 |= (1 << clk->enable_bit);
+ __raw_writel(regval32, clk->enable_reg);
+ wmb();
+
+@@ -200,44 +250,48 @@ static int _omap2_clk_enable(struct clk * clk)
+ return 0;
+ }
+
+-/* Stop APLL */
+-static void omap2_clk_fixed_disable(struct clk *clk)
+-{
+- u32 cval;
+-
+- if(clk->enable_bit == 0xff) /* let parent off do it */
+- return;
+-
+- cval = CM_CLKEN_PLL;
+- cval &= ~(0x3 << clk->enable_bit);
+- CM_CLKEN_PLL = cval;
+-}
+-
+ /* Disables clock without considering parent dependencies or use count */
+-static void _omap2_clk_disable(struct clk *clk)
++void _omap2_clk_disable(struct clk *clk)
+ {
+ u32 regval32;
+
+- if (unlikely(clk == &osc_ck)) {
+- omap2_set_osc_ck(0);
++ if (clk->flags & (ALWAYS_ENABLED | PARENT_CONTROLS_CLOCK))
+ return;
+- }
+
+- if (clk->enable_reg == 0)
++ if (clk->disable) {
++ clk->disable(clk);
+ return;
++ }
+
+- if (clk->enable_reg == (void __iomem *)&CM_CLKEN_PLL) {
+- omap2_clk_fixed_disable(clk);
++ if (clk->enable_reg == 0) {
++ /*
++ * 'Independent' here refers to a clock which is not
++ * controlled by its parent.
++ */
++ printk(KERN_ERR "clock: clk_disable called on independent "
++ "clock %s which has no enable_reg\n", clk->name);
+ return;
+ }
+
+ regval32 = __raw_readl(clk->enable_reg);
+- regval32 &= ~(1 << clk->enable_bit);
++ if (clk->flags & INVERT_ENABLE)
++ regval32 |= (1 << clk->enable_bit);
++ else
++ regval32 &= ~(1 << clk->enable_bit);
+ __raw_writel(regval32, clk->enable_reg);
+ wmb();
+ }
+
+-static int omap2_clk_enable(struct clk *clk)
++void omap2_clk_disable(struct clk *clk)
++{
++ if (clk->usecount > 0 && !(--clk->usecount)) {
++ _omap2_clk_disable(clk);
++ if (likely((u32)clk->parent))
++ omap2_clk_disable(clk->parent);
++ }
++}
++
++int omap2_clk_enable(struct clk *clk)
+ {
+ int ret = 0;
+
+@@ -261,519 +315,314 @@ static int omap2_clk_enable(struct clk *clk)
+ return ret;
+ }
+
+-static void omap2_clk_disable(struct clk *clk)
+-{
+- if (clk->usecount > 0 && !(--clk->usecount)) {
+- _omap2_clk_disable(clk);
+- if (likely((u32)clk->parent))
+- omap2_clk_disable(clk->parent);
+- }
+-}
+-
+-/*
+- * Uses the current prcm set to tell if a rate is valid.
+- * You can go slower, but not faster within a given rate set.
+- */
+-static u32 omap2_dpll_round_rate(unsigned long target_rate)
+-{
+- u32 high, low;
+-
+- if ((CM_CLKSEL2_PLL & 0x3) == 1) { /* DPLL clockout */
+- high = curr_prcm_set->dpll_speed * 2;
+- low = curr_prcm_set->dpll_speed;
+- } else { /* DPLL clockout x 2 */
+- high = curr_prcm_set->dpll_speed;
+- low = curr_prcm_set->dpll_speed / 2;
+- }
+-
+-#ifdef DOWN_VARIABLE_DPLL
+- if (target_rate > high)
+- return high;
+- else
+- return target_rate;
+-#else
+- if (target_rate > low)
+- return high;
+- else
+- return low;
+-#endif
+-
+-}
+-
+ /*
+ * Used for clocks that are part of CLKSEL_xyz governed clocks.
+ * REVISIT: Maybe change to use clk->enable() functions like on omap1?
+ */
+-static void omap2_clksel_recalc(struct clk * clk)
++void omap2_clksel_recalc(struct clk *clk)
+ {
+- u32 fixed = 0, div = 0;
++ u32 div = 0;
+
+- if (clk == &dpll_ck) {
+- clk->rate = omap2_get_dpll_rate(clk);
+- fixed = 1;
+- div = 0;
+- }
++ pr_debug("clock: recalc'ing clksel clk %s\n", clk->name);
+
+- if (clk == &iva1_mpu_int_ifck) {
+- div = 2;
+- fixed = 1;
+- }
+-
+- if ((clk == &dss1_fck) && ((CM_CLKSEL1_CORE & (0x1f << 8)) == 0)) {
+- clk->rate = sys_ck.rate;
++ div = omap2_clksel_get_divisor(clk);
++ if (div == 0)
+ return;
+- }
+
+- if (!fixed) {
+- div = omap2_clksel_get_divisor(clk);
+- if (div == 0)
+- return;
+- }
++ if (unlikely(clk->rate == clk->parent->rate / div))
++ return;
++ clk->rate = clk->parent->rate / div;
+
+- if (div != 0) {
+- if (unlikely(clk->rate == clk->parent->rate / div))
+- return;
+- clk->rate = clk->parent->rate / div;
+- }
++ pr_debug("clock: new clock rate is %ld (div %d)\n", clk->rate, div);
+
+ if (unlikely(clk->flags & RATE_PROPAGATES))
+ propagate_rate(clk);
+ }
+
+-/*
+- * Finds best divider value in an array based on the source and target
+- * rates. The divider array must be sorted with smallest divider first.
++/**
++ * omap2_get_clksel_by_parent - return clksel struct for a given clk & parent
++ * @clk: OMAP struct clk ptr to inspect
++ * @src_clk: OMAP struct clk ptr of the parent clk to search for
++ *
++ * Scan the struct clksel array associated with the clock to find
++ * the element associated with the supplied parent clock address.
++ * Returns a pointer to the struct clksel on success or NULL on error.
+ */
+-static inline u32 omap2_divider_from_table(u32 size, u32 *div_array,
+- u32 src_rate, u32 tgt_rate)
++const struct clksel *omap2_get_clksel_by_parent(struct clk *clk,
++ struct clk *src_clk)
+ {
+- int i, test_rate;
++ const struct clksel *clks;
+
+- if (div_array == NULL)
+- return ~1;
++ if (!clk->clksel)
++ return NULL;
+
+- for (i=0; i < size; i++) {
+- test_rate = src_rate / *div_array;
+- if (test_rate <= tgt_rate)
+- return *div_array;
+- ++div_array;
++ for (clks = clk->clksel; clks->parent; clks++) {
++ if (clks->parent == src_clk)
++ break; /* Found the requested parent */
+ }
+
+- return ~0; /* No acceptable divider */
++ if (!clks->parent) {
++ printk(KERN_ERR "clock: Could not find parent clock %s in "
++ "clksel array of clock %s\n", src_clk->name,
++ clk->name);
++ return NULL;
++ }
++
++ return clks;
+ }
+
+-/*
+- * Find divisor for the given clock and target rate.
++/**
++ * omap2_clksel_round_rate_div - find divisor for the given clock and rate
++ * @clk: OMAP struct clk to use
++ * @target_rate: desired clock rate
++ * @new_div: ptr to where we should store the divisor
+ *
++ * Finds 'best' divider value in an array based on the source and target
++ * rates. The divider array must be sorted with smallest divider first.
+ * Note that this will not work for clocks which are part of CONFIG_PARTICIPANT,
+ * they are only settable as part of virtual_prcm set.
++ *
++ * Returns the rounded clock rate or returns 0xffffffff on error.
+ */
+-static u32 omap2_clksel_round_rate(struct clk *tclk, u32 target_rate,
+- u32 *new_div)
++u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
++ u32 *new_div)
+ {
+- u32 gfx_div[] = {2, 3, 4};
+- u32 sysclkout_div[] = {1, 2, 4, 8, 16};
+- u32 dss1_div[] = {1, 2, 3, 4, 5, 6, 8, 9, 12, 16};
+- u32 vylnq_div[] = {1, 2, 3, 4, 6, 8, 9, 12, 16, 18};
+- u32 best_div = ~0, asize = 0;
+- u32 *div_array = NULL;
+-
+- switch (tclk->flags & SRC_RATE_SEL_MASK) {
+- case CM_GFX_SEL1:
+- asize = 3;
+- div_array = gfx_div;
+- break;
+- case CM_PLL_SEL1:
+- return omap2_dpll_round_rate(target_rate);
+- case CM_SYSCLKOUT_SEL1:
+- asize = 5;
+- div_array = sysclkout_div;
+- break;
+- case CM_CORE_SEL1:
+- if(tclk == &dss1_fck){
+- if(tclk->parent == &core_ck){
+- asize = 10;
+- div_array = dss1_div;
+- } else {
+- *new_div = 0; /* fixed clk */
+- return(tclk->parent->rate);
+- }
+- } else if((tclk == &vlynq_fck) && cpu_is_omap2420()){
+- if(tclk->parent == &core_ck){
+- asize = 10;
+- div_array = vylnq_div;
+- } else {
+- *new_div = 0; /* fixed clk */
+- return(tclk->parent->rate);
+- }
+- }
+- break;
++ unsigned long test_rate;
++ const struct clksel *clks;
++ const struct clksel_rate *clkr;
++ u32 last_div = 0;
++
++ printk(KERN_INFO "clock: clksel_round_rate_div: %s target_rate %ld\n",
++ clk->name, target_rate);
++
++ *new_div = 1;
++
++ clks = omap2_get_clksel_by_parent(clk, clk->parent);
++ if (clks == NULL)
++ return ~0;
++
++ for (clkr = clks->rates; clkr->div; clkr++) {
++ if (!(clkr->flags & cpu_mask))
++ continue;
++
++ /* Sanity check */
++ if (clkr->div <= last_div)
++ printk(KERN_ERR "clock: clksel_rate table not sorted "
++ "for clock %s", clk->name);
++
++ last_div = clkr->div;
++
++ test_rate = clk->parent->rate / clkr->div;
++
++ if (test_rate <= target_rate)
++ break; /* found it */
+ }
+
+- best_div = omap2_divider_from_table(asize, div_array,
+- tclk->parent->rate, target_rate);
+- if (best_div == ~0){
+- *new_div = 1;
+- return best_div; /* signal error */
++ if (!clkr->div) {
++ printk(KERN_ERR "clock: Could not find divisor for target "
++ "rate %ld for clock %s parent %s\n", target_rate,
++ clk->name, clk->parent->name);
++ return ~0;
+ }
+
+- *new_div = best_div;
+- return (tclk->parent->rate / best_div);
++ *new_div = clkr->div;
++
++ printk(KERN_INFO "clock: new_div = %d, new_rate = %ld\n", *new_div,
++ (clk->parent->rate / clkr->div));
++
++ return (clk->parent->rate / clkr->div);
+ }
+
+-/* Given a clock and a rate apply a clock specific rounding function */
+-static long omap2_clk_round_rate(struct clk *clk, unsigned long rate)
++/**
++ * omap2_clksel_round_rate - find rounded rate for the given clock and rate
++ * @clk: OMAP struct clk to use
++ * @target_rate: desired clock rate
++ *
++ * Compatibility wrapper for OMAP clock framework
++ * Finds best target rate based on the source clock and possible dividers.
++ * rates. The divider array must be sorted with smallest divider first.
++ * Note that this will not work for clocks which are part of CONFIG_PARTICIPANT,
++ * they are only settable as part of virtual_prcm set.
++ *
++ * Returns the rounded clock rate or returns 0xffffffff on error.
++ */
++long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate)
+ {
+- u32 new_div = 0;
+- int valid_rate;
++ u32 new_div;
+
+- if (clk->flags & RATE_FIXED)
+- return clk->rate;
++ return omap2_clksel_round_rate_div(clk, target_rate, &new_div);
++}
+
+- if (clk->flags & RATE_CKCTL) {
+- valid_rate = omap2_clksel_round_rate(clk, rate, &new_div);
+- return valid_rate;
+- }
+
++/* Given a clock and a rate apply a clock specific rounding function */
++long omap2_clk_round_rate(struct clk *clk, unsigned long rate)
++{
+ if (clk->round_rate != 0)
+ return clk->round_rate(clk, rate);
+
++ if (clk->flags & RATE_FIXED)
++ printk(KERN_ERR "clock: generic omap2_clk_round_rate called "
++ "on fixed-rate clock %s\n", clk->name);
++
+ return clk->rate;
+ }
+
+-/*
+- * Check the DLL lock state, and return tue if running in unlock mode.
+- * This is needed to compensate for the shifted DLL value in unlock mode.
++/**
++ * omap2_clksel_to_divisor() - turn clksel field value into integer divider
++ * @clk: OMAP struct clk to use
++ * @field_val: register field value to find
++ *
++ * Given a struct clk of a rate-selectable clksel clock, and a register field
++ * value to search for, find the corresponding clock divisor. The register
++ * field value should be pre-masked and shifted down so the LSB is at bit 0
++ * before calling. Returns 0 on error
+ */
+-static u32 omap2_dll_force_needed(void)
++u32 omap2_clksel_to_divisor(struct clk *clk, u32 field_val)
+ {
+- u32 dll_state = SDRC_DLLA_CTRL; /* dlla and dllb are a set */
++ const struct clksel *clks;
++ const struct clksel_rate *clkr;
+
+- if ((dll_state & (1 << 2)) == (1 << 2))
+- return 1;
+- else
++ clks = omap2_get_clksel_by_parent(clk, clk->parent);
++ if (clks == NULL)
+ return 0;
+-}
+
+-static u32 omap2_reprogram_sdrc(u32 level, u32 force)
+-{
+- u32 slow_dll_ctrl, fast_dll_ctrl, m_type;
+- u32 prev = curr_perf_level, flags;
+-
+- if ((curr_perf_level == level) && !force)
+- return prev;
+-
+- m_type = omap2_memory_get_type();
+- slow_dll_ctrl = omap2_memory_get_slow_dll_ctrl();
+- fast_dll_ctrl = omap2_memory_get_fast_dll_ctrl();
+-
+- if (level == PRCM_HALF_SPEED) {
+- local_irq_save(flags);
+- PRCM_VOLTSETUP = 0xffff;
+- omap2_sram_reprogram_sdrc(PRCM_HALF_SPEED,
+- slow_dll_ctrl, m_type);
+- curr_perf_level = PRCM_HALF_SPEED;
+- local_irq_restore(flags);
++ for (clkr = clks->rates; clkr->div; clkr++) {
++ if ((clkr->flags & cpu_mask) && (clkr->val == field_val))
++ break;
+ }
+- if (level == PRCM_FULL_SPEED) {
+- local_irq_save(flags);
+- PRCM_VOLTSETUP = 0xffff;
+- omap2_sram_reprogram_sdrc(PRCM_FULL_SPEED,
+- fast_dll_ctrl, m_type);
+- curr_perf_level = PRCM_FULL_SPEED;
+- local_irq_restore(flags);
++
++ if (!clkr->div) {
++ printk(KERN_ERR "clock: Could not find fieldval %d for "
++ "clock %s parent %s\n", field_val, clk->name,
++ clk->parent->name);
++ return 0;
+ }
+
+- return prev;
++ return clkr->div;
+ }
+
+-static int omap2_reprogram_dpll(struct clk * clk, unsigned long rate)
++/**
++ * omap2_divisor_to_clksel() - turn clksel integer divisor into a field value
++ * @clk: OMAP struct clk to use
++ * @div: integer divisor to search for
++ *
++ * Given a struct clk of a rate-selectable clksel clock, and a clock divisor,
++ * find the corresponding register field value. The return register value is
++ * the value before left-shifting. Returns 0xffffffff on error
++ */
++u32 omap2_divisor_to_clksel(struct clk *clk, u32 div)
+ {
+- u32 flags, cur_rate, low, mult, div, valid_rate, done_rate;
+- u32 bypass = 0;
+- struct prcm_config tmpset;
+- int ret = -EINVAL;
++ const struct clksel *clks;
++ const struct clksel_rate *clkr;
+
+- local_irq_save(flags);
+- cur_rate = omap2_get_dpll_rate(&dpll_ck);
+- mult = CM_CLKSEL2_PLL & 0x3;
+-
+- if ((rate == (cur_rate / 2)) && (mult == 2)) {
+- omap2_reprogram_sdrc(PRCM_HALF_SPEED, 1);
+- } else if ((rate == (cur_rate * 2)) && (mult == 1)) {
+- omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1);
+- } else if (rate != cur_rate) {
+- valid_rate = omap2_dpll_round_rate(rate);
+- if (valid_rate != rate)
+- goto dpll_exit;
+-
+- if ((CM_CLKSEL2_PLL & 0x3) == 1)
+- low = curr_prcm_set->dpll_speed;
+- else
+- low = curr_prcm_set->dpll_speed / 2;
+-
+- tmpset.cm_clksel1_pll = CM_CLKSEL1_PLL;
+- tmpset.cm_clksel1_pll &= ~(0x3FFF << 8);
+- div = ((curr_prcm_set->xtal_speed / 1000000) - 1);
+- tmpset.cm_clksel2_pll = CM_CLKSEL2_PLL;
+- tmpset.cm_clksel2_pll &= ~0x3;
+- if (rate > low) {
+- tmpset.cm_clksel2_pll |= 0x2;
+- mult = ((rate / 2) / 1000000);
+- done_rate = PRCM_FULL_SPEED;
+- } else {
+- tmpset.cm_clksel2_pll |= 0x1;
+- mult = (rate / 1000000);
+- done_rate = PRCM_HALF_SPEED;
+- }
+- tmpset.cm_clksel1_pll |= ((div << 8) | (mult << 12));
+-
+- /* Worst case */
+- tmpset.base_sdrc_rfr = V24XX_SDRC_RFR_CTRL_BYPASS;
+-
+- if (rate == curr_prcm_set->xtal_speed) /* If asking for 1-1 */
+- bypass = 1;
++ /* should never happen */
++ WARN_ON(div == 0);
+
+- omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1); /* For init_mem */
+-
+- /* Force dll lock mode */
+- omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr,
+- bypass);
++ clks = omap2_get_clksel_by_parent(clk, clk->parent);
++ if (clks == NULL)
++ return 0;
+
+- /* Errata: ret dll entry state */
+- omap2_init_memory_params(omap2_dll_force_needed());
+- omap2_reprogram_sdrc(done_rate, 0);
++ for (clkr = clks->rates; clkr->div; clkr++) {
++ if ((clkr->flags & cpu_mask) && (clkr->div == div))
++ break;
+ }
+- omap2_clksel_recalc(&dpll_ck);
+- ret = 0;
+
+-dpll_exit:
+- local_irq_restore(flags);
+- return(ret);
+-}
++ if (!clkr->div) {
++ printk(KERN_ERR "clock: Could not find divisor %d for "
++ "clock %s parent %s\n", div, clk->name,
++ clk->parent->name);
++ return 0;
++ }
+
+-/* Just return the MPU speed */
+-static void omap2_mpu_recalc(struct clk * clk)
+-{
+- clk->rate = curr_prcm_set->mpu_speed;
++ return clkr->val;
+ }
+
+-/*
+- * Look for a rate equal or less than the target rate given a configuration set.
++/**
++ * omap2_get_clksel - find clksel register addr & field mask for a clk
++ * @clk: struct clk to use
++ * @field_mask: ptr to u32 to store the register field mask
+ *
+- * What's not entirely clear is "which" field represents the key field.
+- * Some might argue L3-DDR, others ARM, others IVA. This code is simple and
+- * just uses the ARM rates.
++ * Returns the address of the clksel register upon success or NULL on error.
+ */
+-static long omap2_round_to_table_rate(struct clk * clk, unsigned long rate)
++void __iomem *omap2_get_clksel(struct clk *clk, u32 *field_mask)
+ {
+- struct prcm_config * ptr;
+- long highest_rate;
+-
+- if (clk != &virt_prcm_set)
+- return -EINVAL;
+-
+- highest_rate = -EINVAL;
+-
+- for (ptr = rate_table; ptr->mpu_speed; ptr++) {
+- if (ptr->xtal_speed != sys_ck.rate)
+- continue;
++ if (unlikely((clk->clksel_reg == 0) || (clk->clksel_mask == 0)))
++ return NULL;
+
+- highest_rate = ptr->mpu_speed;
++ *field_mask = clk->clksel_mask;
+
+- /* Can check only after xtal frequency check */
+- if (ptr->mpu_speed <= rate)
+- break;
+- }
+- return highest_rate;
++ return clk->clksel_reg;
+ }
+
+-/*
+- * omap2_convert_field_to_div() - turn field value into integer divider
++/**
++ * omap2_clksel_get_divisor - get current divider applied to parent clock.
++ * @clk: OMAP struct clk to use.
++ *
++ * Returns the integer divisor upon success or 0 on error.
+ */
+-static u32 omap2_clksel_to_divisor(u32 div_sel, u32 field_val)
++u32 omap2_clksel_get_divisor(struct clk *clk)
+ {
+- u32 i;
+- u32 clkout_array[] = {1, 2, 4, 8, 16};
++ u32 field_mask, field_val;
++ void __iomem *div_addr;
+
+- if ((div_sel & SRC_RATE_SEL_MASK) == CM_SYSCLKOUT_SEL1) {
+- for (i = 0; i < 5; i++) {
+- if (field_val == i)
+- return clkout_array[i];
+- }
+- return ~0;
+- } else
+- return field_val;
++ div_addr = omap2_get_clksel(clk, &field_mask);
++ if (div_addr == 0)
++ return 0;
++
++ field_val = __raw_readl(div_addr) & field_mask;
++ field_val >>= __ffs(field_mask);
++
++ return omap2_clksel_to_divisor(clk, field_val);
+ }
+
+-/*
+- * Returns the CLKSEL divider register value
+- * REVISIT: This should be cleaned up to work nicely with void __iomem *
+- */
+-static u32 omap2_get_clksel(u32 *div_sel, u32 *field_mask,
+- struct clk *clk)
++int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
+ {
+- int ret = ~0;
+- u32 reg_val, div_off;
+- u32 div_addr = 0;
+- u32 mask = ~0;
+-
+- div_off = clk->rate_offset;
+-
+- switch ((*div_sel & SRC_RATE_SEL_MASK)) {
+- case CM_MPU_SEL1:
+- div_addr = (u32)&CM_CLKSEL_MPU;
+- mask = 0x1f;
+- break;
+- case CM_DSP_SEL1:
+- div_addr = (u32)&CM_CLKSEL_DSP;
+- if (cpu_is_omap2420()) {
+- if ((div_off == 0) || (div_off == 8))
+- mask = 0x1f;
+- else if (div_off == 5)
+- mask = 0x3;
+- } else if (cpu_is_omap2430()) {
+- if (div_off == 0)
+- mask = 0x1f;
+- else if (div_off == 5)
+- mask = 0x3;
+- }
+- break;
+- case CM_GFX_SEL1:
+- div_addr = (u32)&CM_CLKSEL_GFX;
+- if (div_off == 0)
+- mask = 0x7;
+- break;
+- case CM_MODEM_SEL1:
+- div_addr = (u32)&CM_CLKSEL_MDM;
+- if (div_off == 0)
+- mask = 0xf;
+- break;
+- case CM_SYSCLKOUT_SEL1:
+- div_addr = (u32)&PRCM_CLKOUT_CTRL;
+- if ((div_off == 3) || (div_off == 11))
+- mask= 0x3;
+- break;
+- case CM_CORE_SEL1:
+- div_addr = (u32)&CM_CLKSEL1_CORE;
+- switch (div_off) {
+- case 0: /* l3 */
+- case 8: /* dss1 */
+- case 15: /* vylnc-2420 */
+- case 20: /* ssi */
+- mask = 0x1f; break;
+- case 5: /* l4 */
+- mask = 0x3; break;
+- case 13: /* dss2 */
+- mask = 0x1; break;
+- case 25: /* usb */
+- mask = 0x7; break;
+- }
+- }
++ u32 field_mask, field_val, reg_val, validrate, new_div = 0;
++ void __iomem *div_addr;
+
+- *field_mask = mask;
++ validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
++ if (validrate != rate)
++ return -EINVAL;
+
+- if (unlikely(mask == ~0))
+- div_addr = 0;
++ div_addr = omap2_get_clksel(clk, &field_mask);
++ if (div_addr == 0)
++ return -EINVAL;
+
+- *div_sel = div_addr;
++ field_val = omap2_divisor_to_clksel(clk, new_div);
++ if (field_val == ~0)
++ return -EINVAL;
+
+- if (unlikely(div_addr == 0))
+- return ret;
++ reg_val = __raw_readl(div_addr);
++ reg_val &= ~field_mask;
++ reg_val |= (field_val << __ffs(field_mask));
++ __raw_writel(reg_val, div_addr);
++ wmb();
+
+- /* Isolate field */
+- reg_val = __raw_readl((void __iomem *)div_addr) & (mask << div_off);
++ clk->rate = clk->parent->rate / new_div;
+
+- /* Normalize back to divider value */
+- reg_val >>= div_off;
++ if (clk->flags & DELAYED_APP && cpu_is_omap24xx()) {
++ __raw_writel(OMAP24XX_VALID_CONFIG, OMAP24XX_PRCM_CLKCFG_CTRL);
++ wmb();
++ }
+
+- return reg_val;
++ return 0;
+ }
+
+-/*
+- * Return divider to be applied to parent clock.
+- * Return 0 on error.
+- */
+-static u32 omap2_clksel_get_divisor(struct clk *clk)
+-{
+- int ret = 0;
+- u32 div, div_sel, div_off, field_mask, field_val;
+-
+- /* isolate control register */
+- div_sel = (SRC_RATE_SEL_MASK & clk->flags);
+-
+- div_off = clk->rate_offset;
+- field_val = omap2_get_clksel(&div_sel, &field_mask, clk);
+- if (div_sel == 0)
+- return ret;
+-
+- div_sel = (SRC_RATE_SEL_MASK & clk->flags);
+- div = omap2_clksel_to_divisor(div_sel, field_val);
+-
+- return div;
+-}
+
+ /* Set the clock rate for a clock source */
+-static int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
+-
++int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
+ {
+ int ret = -EINVAL;
+- void __iomem * reg;
+- u32 div_sel, div_off, field_mask, field_val, reg_val, validrate;
+- u32 new_div = 0;
+-
+- if (!(clk->flags & CONFIG_PARTICIPANT) && (clk->flags & RATE_CKCTL)) {
+- if (clk == &dpll_ck)
+- return omap2_reprogram_dpll(clk, rate);
+-
+- /* Isolate control register */
+- div_sel = (SRC_RATE_SEL_MASK & clk->flags);
+- div_off = clk->rate_offset;
+-
+- validrate = omap2_clksel_round_rate(clk, rate, &new_div);
+- if (validrate != rate)
+- return(ret);
+
+- field_val = omap2_get_clksel(&div_sel, &field_mask, clk);
+- if (div_sel == 0)
+- return ret;
+-
+- if (clk->flags & CM_SYSCLKOUT_SEL1) {
+- switch (new_div) {
+- case 16:
+- field_val = 4;
+- break;
+- case 8:
+- field_val = 3;
+- break;
+- case 4:
+- field_val = 2;
+- break;
+- case 2:
+- field_val = 1;
+- break;
+- case 1:
+- field_val = 0;
+- break;
+- }
+- } else
+- field_val = new_div;
++ pr_debug("clock: set_rate for clock %s to rate %ld\n", clk->name, rate);
+
+- reg = (void __iomem *)div_sel;
+-
+- reg_val = __raw_readl(reg);
+- reg_val &= ~(field_mask << div_off);
+- reg_val |= (field_val << div_off);
+- __raw_writel(reg_val, reg);
+- wmb();
+- clk->rate = clk->parent->rate / field_val;
++ /* CONFIG_PARTICIPANT clocks are changed only in sets via the
++ rate table mechanism, driven by mpu_speed */
++ if (clk->flags & CONFIG_PARTICIPANT)
++ return -EINVAL;
+
+- if (clk->flags & DELAYED_APP) {
+- __raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL);
+- wmb();
+- }
+- ret = 0;
+- } else if (clk->set_rate != 0)
++ /* dpll_ck, core_ck, virt_prcm_set; plus all clksel clocks */
++ if (clk->set_rate != 0)
+ ret = clk->set_rate(clk, rate);
+
+ if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES)))
+@@ -782,242 +631,92 @@ static int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
+ return ret;
+ }
+
+-/* Converts encoded control register address into a full address */
+-static u32 omap2_get_src_field(u32 *type_to_addr, u32 reg_offset,
+- struct clk *src_clk, u32 *field_mask)
+-{
+- u32 val = ~0, src_reg_addr = 0, mask = 0;
+-
+- /* Find target control register.*/
+- switch ((*type_to_addr & SRC_RATE_SEL_MASK)) {
+- case CM_CORE_SEL1:
+- src_reg_addr = (u32)&CM_CLKSEL1_CORE;
+- if (reg_offset == 13) { /* DSS2_fclk */
+- mask = 0x1;
+- if (src_clk == &sys_ck)
+- val = 0;
+- if (src_clk == &func_48m_ck)
+- val = 1;
+- } else if (reg_offset == 8) { /* DSS1_fclk */
+- mask = 0x1f;
+- if (src_clk == &sys_ck)
+- val = 0;
+- else if (src_clk == &core_ck) /* divided clock */
+- val = 0x10; /* rate needs fixing */
+- } else if ((reg_offset == 15) && cpu_is_omap2420()){ /*vlnyq*/
+- mask = 0x1F;
+- if(src_clk == &func_96m_ck)
+- val = 0;
+- else if (src_clk == &core_ck)
+- val = 0x10;
+- }
+- break;
+- case CM_CORE_SEL2:
+- src_reg_addr = (u32)&CM_CLKSEL2_CORE;
+- mask = 0x3;
+- if (src_clk == &func_32k_ck)
+- val = 0x0;
+- if (src_clk == &sys_ck)
+- val = 0x1;
+- if (src_clk == &alt_ck)
+- val = 0x2;
+- break;
+- case CM_WKUP_SEL1:
+- src_reg_addr = (u32)&CM_CLKSEL_WKUP;
+- mask = 0x3;
+- if (src_clk == &func_32k_ck)
+- val = 0x0;
+- if (src_clk == &sys_ck)
+- val = 0x1;
+- if (src_clk == &alt_ck)
+- val = 0x2;
+- break;
+- case CM_PLL_SEL1:
+- src_reg_addr = (u32)&CM_CLKSEL1_PLL;
+- mask = 0x1;
+- if (reg_offset == 0x3) {
+- if (src_clk == &apll96_ck)
+- val = 0;
+- if (src_clk == &alt_ck)
+- val = 1;
+- }
+- else if (reg_offset == 0x5) {
+- if (src_clk == &apll54_ck)
+- val = 0;
+- if (src_clk == &alt_ck)
+- val = 1;
+- }
+- break;
+- case CM_PLL_SEL2:
+- src_reg_addr = (u32)&CM_CLKSEL2_PLL;
+- mask = 0x3;
+- if (src_clk == &func_32k_ck)
+- val = 0x0;
+- if (src_clk == &dpll_ck)
+- val = 0x2;
+- break;
+- case CM_SYSCLKOUT_SEL1:
+- src_reg_addr = (u32)&PRCM_CLKOUT_CTRL;
+- mask = 0x3;
+- if (src_clk == &dpll_ck)
+- val = 0;
+- if (src_clk == &sys_ck)
+- val = 1;
+- if (src_clk == &func_96m_ck)
+- val = 2;
+- if (src_clk == &func_54m_ck)
+- val = 3;
+- break;
+- }
+-
+- if (val == ~0) /* Catch errors in offset */
+- *type_to_addr = 0;
+- else
+- *type_to_addr = src_reg_addr;
+- *field_mask = mask;
+-
+- return val;
+-}
+-
+-static int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
++/*
++ * Converts encoded control register address into a full address
++ * On error, *src_addr will be returned as 0.
++ */
++static u32 omap2_clksel_get_src_field(void __iomem **src_addr,
++ struct clk *src_clk, u32 *field_mask,
++ struct clk *clk, u32 *parent_div)
+ {
+- void __iomem * reg;
+- u32 src_sel, src_off, field_val, field_mask, reg_val, rate;
+- int ret = -EINVAL;
+-
+- if (unlikely(clk->flags & CONFIG_PARTICIPANT))
+- return ret;
+-
+- if (clk->flags & SRC_SEL_MASK) { /* On-chip SEL collection */
+- src_sel = (SRC_RATE_SEL_MASK & clk->flags);
+- src_off = clk->src_offset;
+-
+- if (src_sel == 0)
+- goto set_parent_error;
+-
+- field_val = omap2_get_src_field(&src_sel, src_off, new_parent,
+- &field_mask);
+-
+- reg = (void __iomem *)src_sel;
+-
+- if (clk->usecount > 0)
+- _omap2_clk_disable(clk);
+-
+- /* Set new source value (previous dividers if any in effect) */
+- reg_val = __raw_readl(reg) & ~(field_mask << src_off);
+- reg_val |= (field_val << src_off);
+- __raw_writel(reg_val, reg);
+- wmb();
++ const struct clksel *clks;
++ const struct clksel_rate *clkr;
+
+- if (clk->flags & DELAYED_APP) {
+- __raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL);
+- wmb();
+- }
+- if (clk->usecount > 0)
+- _omap2_clk_enable(clk);
+-
+- clk->parent = new_parent;
++ *parent_div = 0;
++ *src_addr = 0;
+
+- /* SRC_RATE_SEL_MASK clocks follow their parents rates.*/
+- if ((new_parent == &core_ck) && (clk == &dss1_fck))
+- clk->rate = new_parent->rate / 0x10;
+- else
+- clk->rate = new_parent->rate;
++ clks = omap2_get_clksel_by_parent(clk, src_clk);
++ if (clks == NULL)
++ return 0;
+
+- if (unlikely(clk->flags & RATE_PROPAGATES))
+- propagate_rate(clk);
++ for (clkr = clks->rates; clkr->div; clkr++) {
++ if (clkr->flags & (cpu_mask | DEFAULT_RATE))
++ break; /* Found the default rate for this platform */
++ }
+
++ if (!clkr->div) {
++ printk(KERN_ERR "clock: Could not find default rate for "
++ "clock %s parent %s\n", clk->name,
++ src_clk->parent->name);
+ return 0;
+- } else {
+- clk->parent = new_parent;
+- rate = new_parent->rate;
+- omap2_clk_set_rate(clk, rate);
+- ret = 0;
+ }
+
+- set_parent_error:
+- return ret;
++ /* Should never happen. Add a clksel mask to the struct clk. */
++ WARN_ON(clk->clksel_mask == 0);
++
++ *field_mask = clk->clksel_mask;
++ *src_addr = clk->clksel_reg;
++ *parent_div = clkr->div;
++
++ return clkr->val;
+ }
+
+-/* Sets basic clocks based on the specified rate */
+-static int omap2_select_table_rate(struct clk * clk, unsigned long rate)
++int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
+ {
+- u32 flags, cur_rate, done_rate, bypass = 0;
+- u8 cpu_mask = 0;
+- struct prcm_config *prcm;
+- unsigned long found_speed = 0;
++ void __iomem *src_addr;
++ u32 field_val, field_mask, reg_val, parent_div;
+
+- if (clk != &virt_prcm_set)
++ if (unlikely(clk->flags & CONFIG_PARTICIPANT))
+ return -EINVAL;
+
+- /* FIXME: Change cpu_is_omap2420() to cpu_is_omap242x() */
+- if (cpu_is_omap2420())
+- cpu_mask = RATE_IN_242X;
+- else if (cpu_is_omap2430())
+- cpu_mask = RATE_IN_243X;
+-
+- for (prcm = rate_table; prcm->mpu_speed; prcm++) {
+- if (!(prcm->flags & cpu_mask))
+- continue;
+-
+- if (prcm->xtal_speed != sys_ck.rate)
+- continue;
+-
+- if (prcm->mpu_speed <= rate) {
+- found_speed = prcm->mpu_speed;
+- break;
+- }
+- }
+-
+- if (!found_speed) {
+- printk(KERN_INFO "Could not set MPU rate to %luMHz\n",
+- rate / 1000000);
++ if (!clk->clksel)
+ return -EINVAL;
+- }
+-
+- curr_prcm_set = prcm;
+- cur_rate = omap2_get_dpll_rate(&dpll_ck);
+-
+- if (prcm->dpll_speed == cur_rate / 2) {
+- omap2_reprogram_sdrc(PRCM_HALF_SPEED, 1);
+- } else if (prcm->dpll_speed == cur_rate * 2) {
+- omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1);
+- } else if (prcm->dpll_speed != cur_rate) {
+- local_irq_save(flags);
+
+- if (prcm->dpll_speed == prcm->xtal_speed)
+- bypass = 1;
++ field_val = omap2_clksel_get_src_field(&src_addr, new_parent,
++ &field_mask, clk, &parent_div);
++ if (src_addr == 0)
++ return -EINVAL;
+
+- if ((prcm->cm_clksel2_pll & 0x3) == 2)
+- done_rate = PRCM_FULL_SPEED;
+- else
+- done_rate = PRCM_HALF_SPEED;
++ if (clk->usecount > 0)
++ _omap2_clk_disable(clk);
+
+- /* MPU divider */
+- CM_CLKSEL_MPU = prcm->cm_clksel_mpu;
++ /* Set new source value (previous dividers if any in effect) */
++ reg_val = __raw_readl(src_addr) & ~field_mask;
++ reg_val |= (field_val << __ffs(field_mask));
++ __raw_writel(reg_val, src_addr);
++ wmb();
+
+- /* dsp + iva1 div(2420), iva2.1(2430) */
+- CM_CLKSEL_DSP = prcm->cm_clksel_dsp;
++ if (clk->flags & DELAYED_APP && cpu_is_omap24xx()) {
++ __raw_writel(OMAP24XX_VALID_CONFIG, OMAP24XX_PRCM_CLKCFG_CTRL);
++ wmb();
++ }
+
+- CM_CLKSEL_GFX = prcm->cm_clksel_gfx;
++ if (clk->usecount > 0)
++ _omap2_clk_enable(clk);
+
+- /* Major subsystem dividers */
+- CM_CLKSEL1_CORE = prcm->cm_clksel1_core;
+- if (cpu_is_omap2430())
+- CM_CLKSEL_MDM = prcm->cm_clksel_mdm;
++ clk->parent = new_parent;
+
+- /* x2 to enter init_mem */
+- omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1);
++ /* CLKSEL clocks follow their parents' rates, divided by a divisor */
++ clk->rate = new_parent->rate;
+
+- omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr,
+- bypass);
++ if (parent_div > 0)
++ clk->rate /= parent_div;
+
+- omap2_init_memory_params(omap2_dll_force_needed());
+- omap2_reprogram_sdrc(done_rate, 0);
++ pr_debug("clock: set parent of %s to %s (new rate %ld)\n",
++ clk->name, clk->parent->name, clk->rate);
+
+- local_irq_restore(flags);
+- }
+- omap2_clksel_recalc(&dpll_ck);
++ if (unlikely(clk->flags & RATE_PROPAGATES))
++ propagate_rate(clk);
+
+ return 0;
+ }
+@@ -1027,150 +726,17 @@ static int omap2_select_table_rate(struct clk * clk, unsigned long rate)
+ *-------------------------------------------------------------------------*/
+
+ #ifdef CONFIG_OMAP_RESET_CLOCKS
+-static void __init omap2_clk_disable_unused(struct clk *clk)
++void omap2_clk_disable_unused(struct clk *clk)
+ {
+- u32 regval32;
++ u32 regval32, v;
++
++ v = (clk->flags & INVERT_ENABLE) ? (1 << clk->enable_bit) : 0;
+
+ regval32 = __raw_readl(clk->enable_reg);
+- if ((regval32 & (1 << clk->enable_bit)) == 0)
++ if ((regval32 & (1 << clk->enable_bit)) == v)
+ return;
+
+ printk(KERN_INFO "Disabling unused clock \"%s\"\n", clk->name);
+ _omap2_clk_disable(clk);
+ }
+-#else
+-#define omap2_clk_disable_unused NULL
+ #endif
+-
+-static struct clk_functions omap2_clk_functions = {
+- .clk_enable = omap2_clk_enable,
+- .clk_disable = omap2_clk_disable,
+- .clk_round_rate = omap2_clk_round_rate,
+- .clk_set_rate = omap2_clk_set_rate,
+- .clk_set_parent = omap2_clk_set_parent,
+- .clk_disable_unused = omap2_clk_disable_unused,
+-};
+-
+-static void __init omap2_get_crystal_rate(struct clk *osc, struct clk *sys)
+-{
+- u32 div, aplls, sclk = 13000000;
+-
+- aplls = CM_CLKSEL1_PLL;
+- aplls &= ((1 << 23) | (1 << 24) | (1 << 25));
+- aplls >>= 23; /* Isolate field, 0,2,3 */
+-
+- if (aplls == 0)
+- sclk = 19200000;
+- else if (aplls == 2)
+- sclk = 13000000;
+- else if (aplls == 3)
+- sclk = 12000000;
+-
+- div = PRCM_CLKSRC_CTRL;
+- div &= ((1 << 7) | (1 << 6));
+- div >>= sys->rate_offset;
+-
+- osc->rate = sclk * div;
+- sys->rate = sclk;
+-}
+-
+-/*
+- * Set clocks for bypass mode for reboot to work.
+- */
+-void omap2_clk_prepare_for_reboot(void)
+-{
+- u32 rate;
+-
+- if (vclk == NULL || sclk == NULL)
+- return;
+-
+- rate = clk_get_rate(sclk);
+- clk_set_rate(vclk, rate);
+-}
+-
+-/*
+- * Switch the MPU rate if specified on cmdline.
+- * We cannot do this early until cmdline is parsed.
+- */
+-static int __init omap2_clk_arch_init(void)
+-{
+- if (!mpurate)
+- return -EINVAL;
+-
+- if (omap2_select_table_rate(&virt_prcm_set, mpurate))
+- printk(KERN_ERR "Could not find matching MPU rate\n");
+-
+- propagate_rate(&osc_ck); /* update main root fast */
+- propagate_rate(&func_32k_ck); /* update main root slow */
+-
+- printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL/MPU): "
+- "%ld.%01ld/%ld/%ld MHz\n",
+- (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
+- (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
+-
+- return 0;
+-}
+-arch_initcall(omap2_clk_arch_init);
+-
+-int __init omap2_clk_init(void)
+-{
+- struct prcm_config *prcm;
+- struct clk ** clkp;
+- u32 clkrate;
+-
+- clk_init(&omap2_clk_functions);
+- omap2_get_crystal_rate(&osc_ck, &sys_ck);
+-
+- for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);
+- clkp++) {
+-
+- if ((*clkp)->flags & CLOCK_IN_OMAP242X && cpu_is_omap2420()) {
+- clk_register(*clkp);
+- continue;
+- }
+-
+- if ((*clkp)->flags & CLOCK_IN_OMAP243X && cpu_is_omap2430()) {
+- clk_register(*clkp);
+- continue;
+- }
+- }
+-
+- /* Check the MPU rate set by bootloader */
+- clkrate = omap2_get_dpll_rate(&dpll_ck);
+- for (prcm = rate_table; prcm->mpu_speed; prcm++) {
+- if (prcm->xtal_speed != sys_ck.rate)
+- continue;
+- if (prcm->dpll_speed <= clkrate)
+- break;
+- }
+- curr_prcm_set = prcm;
+-
+- propagate_rate(&osc_ck); /* update main root fast */
+- propagate_rate(&func_32k_ck); /* update main root slow */
+-
+- printk(KERN_INFO "Clocking rate (Crystal/DPLL/MPU): "
+- "%ld.%01ld/%ld/%ld MHz\n",
+- (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
+- (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
+-
+- /*
+- * Only enable those clocks we will need, let the drivers
+- * enable other clocks as necessary
+- */
+- clk_enable(&sync_32k_ick);
+- clk_enable(&omapctrl_ick);
+-
+- /* Force the APLLs always active. The clocks are idled
+- * automatically by hardware. */
+- clk_enable(&apll96_ck);
+- clk_enable(&apll54_ck);
+-
+- if (cpu_is_omap2430())
+- clk_enable(&sdrc_ick);
+-
+- /* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */
+- vclk = clk_get(NULL, "virt_prcm_set");
+- sclk = clk_get(NULL, "sys_ck");
+-
+- return 0;
+-}
+diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
+index 4f79186..d5980a9 100644
+--- a/arch/arm/mach-omap2/clock.h
++++ b/arch/arm/mach-omap2/clock.h
+@@ -1,13 +1,12 @@
+ /*
+- * linux/arch/arm/mach-omap24xx/clock.h
++ * linux/arch/arm/mach-omap2/clock.h
+ *
+- * Copyright (C) 2005 Texas Instruments Inc.
+- * Richard Woodruff <r-woodruff2 at ti.com>
+- * Created for OMAP2.
++ * Copyright (C) 2005-2008 Texas Instruments, Inc.
++ * Copyright (C) 2004-2008 Nokia Corporation
+ *
+- * Copyright (C) 2004 Nokia corporation
+- * Written by Tuukka Tikkanen <tuukka.tikkanen at elektrobit.com>
+- * Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc
++ * Contacts:
++ * Richard Woodruff <r-woodruff2 at ti.com>
++ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+@@ -17,2095 +16,53 @@
+ #ifndef __ARCH_ARM_MACH_OMAP2_CLOCK_H
+ #define __ARCH_ARM_MACH_OMAP2_CLOCK_H
+
+-static void omap2_sys_clk_recalc(struct clk * clk);
+-static void omap2_clksel_recalc(struct clk * clk);
+-static void omap2_followparent_recalc(struct clk * clk);
+-static void omap2_propagate_rate(struct clk * clk);
+-static void omap2_mpu_recalc(struct clk * clk);
+-static int omap2_select_table_rate(struct clk * clk, unsigned long rate);
+-static long omap2_round_to_table_rate(struct clk * clk, unsigned long rate);
+-static void omap2_clk_disable(struct clk *clk);
+-static void omap2_sys_clk_recalc(struct clk * clk);
+-static u32 omap2_clksel_to_divisor(u32 div_sel, u32 field_val);
+-static u32 omap2_clksel_get_divisor(struct clk *clk);
+-
+-
+-#define RATE_IN_242X (1 << 0)
+-#define RATE_IN_243X (1 << 1)
+-
+-/* Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated.
+- * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,CM_CLKSEL_DSP
+- * CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL CM_CLKSEL2_PLL, CM_CLKSEL_MDM
+- */
+-struct prcm_config {
+- unsigned long xtal_speed; /* crystal rate */
+- unsigned long dpll_speed; /* dpll: out*xtal*M/(N-1)table_recalc */
+- unsigned long mpu_speed; /* speed of MPU */
+- unsigned long cm_clksel_mpu; /* mpu divider */
+- unsigned long cm_clksel_dsp; /* dsp+iva1 div(2420), iva2.1(2430) */
+- unsigned long cm_clksel_gfx; /* gfx dividers */
+- unsigned long cm_clksel1_core; /* major subsystem dividers */
+- unsigned long cm_clksel1_pll; /* m,n */
+- unsigned long cm_clksel2_pll; /* dpllx1 or x2 out */
+- unsigned long cm_clksel_mdm; /* modem dividers 2430 only */
+- unsigned long base_sdrc_rfr; /* base refresh timing for a set */
+- unsigned char flags;
+-};
+-
+-/* Mask for clksel which support parent settign in set_rate */
+-#define SRC_SEL_MASK (CM_CORE_SEL1 | CM_CORE_SEL2 | CM_WKUP_SEL1 | \
+- CM_PLL_SEL1 | CM_PLL_SEL2 | CM_SYSCLKOUT_SEL1)
+-
+-/* Mask for clksel regs which support rate operations */
+-#define SRC_RATE_SEL_MASK (CM_MPU_SEL1 | CM_DSP_SEL1 | CM_GFX_SEL1 | \
+- CM_MODEM_SEL1 | CM_CORE_SEL1 | CM_CORE_SEL2 | \
+- CM_WKUP_SEL1 | CM_PLL_SEL1 | CM_PLL_SEL2 | \
+- CM_SYSCLKOUT_SEL1)
+-
+-/*
+- * The OMAP2 processor can be run at several discrete 'PRCM configurations'.
+- * These configurations are characterized by voltage and speed for clocks.
+- * The device is only validated for certain combinations. One way to express
+- * these combinations is via the 'ratio's' which the clocks operate with
+- * respect to each other. These ratio sets are for a given voltage/DPLL
+- * setting. All configurations can be described by a DPLL setting and a ratio
+- * There are 3 ratio sets for the 2430 and X ratio sets for 2420.
+- *
+- * 2430 differs from 2420 in that there are no more phase synchronizers used.
+- * They both have a slightly different clock domain setup. 2420(iva1,dsp) vs
+- * 2430 (iva2.1, NOdsp, mdm)
+- */
+-
+-/* Core fields for cm_clksel, not ratio governed */
+-#define RX_CLKSEL_DSS1 (0x10 << 8)
+-#define RX_CLKSEL_DSS2 (0x0 << 13)
+-#define RX_CLKSEL_SSI (0x5 << 20)
+-
+-/*-------------------------------------------------------------------------
+- * Voltage/DPLL ratios
+- *-------------------------------------------------------------------------*/
+-
+-/* 2430 Ratio's, 2430-Ratio Config 1 */
+-#define R1_CLKSEL_L3 (4 << 0)
+-#define R1_CLKSEL_L4 (2 << 5)
+-#define R1_CLKSEL_USB (4 << 25)
+-#define R1_CM_CLKSEL1_CORE_VAL R1_CLKSEL_USB | RX_CLKSEL_SSI | \
+- RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
+- R1_CLKSEL_L4 | R1_CLKSEL_L3
+-#define R1_CLKSEL_MPU (2 << 0)
+-#define R1_CM_CLKSEL_MPU_VAL R1_CLKSEL_MPU
+-#define R1_CLKSEL_DSP (2 << 0)
+-#define R1_CLKSEL_DSP_IF (2 << 5)
+-#define R1_CM_CLKSEL_DSP_VAL R1_CLKSEL_DSP | R1_CLKSEL_DSP_IF
+-#define R1_CLKSEL_GFX (2 << 0)
+-#define R1_CM_CLKSEL_GFX_VAL R1_CLKSEL_GFX
+-#define R1_CLKSEL_MDM (4 << 0)
+-#define R1_CM_CLKSEL_MDM_VAL R1_CLKSEL_MDM
+-
+-/* 2430-Ratio Config 2 */
+-#define R2_CLKSEL_L3 (6 << 0)
+-#define R2_CLKSEL_L4 (2 << 5)
+-#define R2_CLKSEL_USB (2 << 25)
+-#define R2_CM_CLKSEL1_CORE_VAL R2_CLKSEL_USB | RX_CLKSEL_SSI | \
+- RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
+- R2_CLKSEL_L4 | R2_CLKSEL_L3
+-#define R2_CLKSEL_MPU (2 << 0)
+-#define R2_CM_CLKSEL_MPU_VAL R2_CLKSEL_MPU
+-#define R2_CLKSEL_DSP (2 << 0)
+-#define R2_CLKSEL_DSP_IF (3 << 5)
+-#define R2_CM_CLKSEL_DSP_VAL R2_CLKSEL_DSP | R2_CLKSEL_DSP_IF
+-#define R2_CLKSEL_GFX (2 << 0)
+-#define R2_CM_CLKSEL_GFX_VAL R2_CLKSEL_GFX
+-#define R2_CLKSEL_MDM (6 << 0)
+-#define R2_CM_CLKSEL_MDM_VAL R2_CLKSEL_MDM
+-
+-/* 2430-Ratio Bootm (BYPASS) */
+-#define RB_CLKSEL_L3 (1 << 0)
+-#define RB_CLKSEL_L4 (1 << 5)
+-#define RB_CLKSEL_USB (1 << 25)
+-#define RB_CM_CLKSEL1_CORE_VAL RB_CLKSEL_USB | RX_CLKSEL_SSI | \
+- RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
+- RB_CLKSEL_L4 | RB_CLKSEL_L3
+-#define RB_CLKSEL_MPU (1 << 0)
+-#define RB_CM_CLKSEL_MPU_VAL RB_CLKSEL_MPU
+-#define RB_CLKSEL_DSP (1 << 0)
+-#define RB_CLKSEL_DSP_IF (1 << 5)
+-#define RB_CM_CLKSEL_DSP_VAL RB_CLKSEL_DSP | RB_CLKSEL_DSP_IF
+-#define RB_CLKSEL_GFX (1 << 0)
+-#define RB_CM_CLKSEL_GFX_VAL RB_CLKSEL_GFX
+-#define RB_CLKSEL_MDM (1 << 0)
+-#define RB_CM_CLKSEL_MDM_VAL RB_CLKSEL_MDM
+-
+-/* 2420 Ratio Equivalents */
+-#define RXX_CLKSEL_VLYNQ (0x12 << 15)
+-#define RXX_CLKSEL_SSI (0x8 << 20)
+-
+-/* 2420-PRCM III 532MHz core */
+-#define RIII_CLKSEL_L3 (4 << 0) /* 133MHz */
+-#define RIII_CLKSEL_L4 (2 << 5) /* 66.5MHz */
+-#define RIII_CLKSEL_USB (4 << 25) /* 33.25MHz */
+-#define RIII_CM_CLKSEL1_CORE_VAL RIII_CLKSEL_USB | RXX_CLKSEL_SSI | \
+- RXX_CLKSEL_VLYNQ | RX_CLKSEL_DSS2 | \
+- RX_CLKSEL_DSS1 | RIII_CLKSEL_L4 | \
+- RIII_CLKSEL_L3
+-#define RIII_CLKSEL_MPU (2 << 0) /* 266MHz */
+-#define RIII_CM_CLKSEL_MPU_VAL RIII_CLKSEL_MPU
+-#define RIII_CLKSEL_DSP (3 << 0) /* c5x - 177.3MHz */
+-#define RIII_CLKSEL_DSP_IF (2 << 5) /* c5x - 88.67MHz */
+-#define RIII_SYNC_DSP (1 << 7) /* Enable sync */
+-#define RIII_CLKSEL_IVA (6 << 8) /* iva1 - 88.67MHz */
+-#define RIII_SYNC_IVA (1 << 13) /* Enable sync */
+-#define RIII_CM_CLKSEL_DSP_VAL RIII_SYNC_IVA | RIII_CLKSEL_IVA | \
+- RIII_SYNC_DSP | RIII_CLKSEL_DSP_IF | \
+- RIII_CLKSEL_DSP
+-#define RIII_CLKSEL_GFX (2 << 0) /* 66.5MHz */
+-#define RIII_CM_CLKSEL_GFX_VAL RIII_CLKSEL_GFX
+-
+-/* 2420-PRCM II 600MHz core */
+-#define RII_CLKSEL_L3 (6 << 0) /* 100MHz */
+-#define RII_CLKSEL_L4 (2 << 5) /* 50MHz */
+-#define RII_CLKSEL_USB (2 << 25) /* 50MHz */
+-#define RII_CM_CLKSEL1_CORE_VAL RII_CLKSEL_USB | \
+- RXX_CLKSEL_SSI | RXX_CLKSEL_VLYNQ | \
+- RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
+- RII_CLKSEL_L4 | RII_CLKSEL_L3
+-#define RII_CLKSEL_MPU (2 << 0) /* 300MHz */
+-#define RII_CM_CLKSEL_MPU_VAL RII_CLKSEL_MPU
+-#define RII_CLKSEL_DSP (3 << 0) /* c5x - 200MHz */
+-#define RII_CLKSEL_DSP_IF (2 << 5) /* c5x - 100MHz */
+-#define RII_SYNC_DSP (0 << 7) /* Bypass sync */
+-#define RII_CLKSEL_IVA (6 << 8) /* iva1 - 200MHz */
+-#define RII_SYNC_IVA (0 << 13) /* Bypass sync */
+-#define RII_CM_CLKSEL_DSP_VAL RII_SYNC_IVA | RII_CLKSEL_IVA | \
+- RII_SYNC_DSP | RII_CLKSEL_DSP_IF | \
+- RII_CLKSEL_DSP
+-#define RII_CLKSEL_GFX (2 << 0) /* 50MHz */
+-#define RII_CM_CLKSEL_GFX_VAL RII_CLKSEL_GFX
+-
+-/* 2420-PRCM VII (boot) */
+-#define RVII_CLKSEL_L3 (1 << 0)
+-#define RVII_CLKSEL_L4 (1 << 5)
+-#define RVII_CLKSEL_DSS1 (1 << 8)
+-#define RVII_CLKSEL_DSS2 (0 << 13)
+-#define RVII_CLKSEL_VLYNQ (1 << 15)
+-#define RVII_CLKSEL_SSI (1 << 20)
+-#define RVII_CLKSEL_USB (1 << 25)
+-
+-#define RVII_CM_CLKSEL1_CORE_VAL RVII_CLKSEL_USB | RVII_CLKSEL_SSI | \
+- RVII_CLKSEL_VLYNQ | RVII_CLKSEL_DSS2 | \
+- RVII_CLKSEL_DSS1 | RVII_CLKSEL_L4 | RVII_CLKSEL_L3
+-
+-#define RVII_CLKSEL_MPU (1 << 0) /* all divide by 1 */
+-#define RVII_CM_CLKSEL_MPU_VAL RVII_CLKSEL_MPU
++#include <asm/arch/clock.h>
+
+-#define RVII_CLKSEL_DSP (1 << 0)
+-#define RVII_CLKSEL_DSP_IF (1 << 5)
+-#define RVII_SYNC_DSP (0 << 7)
+-#define RVII_CLKSEL_IVA (1 << 8)
+-#define RVII_SYNC_IVA (0 << 13)
+-#define RVII_CM_CLKSEL_DSP_VAL RVII_SYNC_IVA | RVII_CLKSEL_IVA | RVII_SYNC_DSP | \
+- RVII_CLKSEL_DSP_IF | RVII_CLKSEL_DSP
+-
+-#define RVII_CLKSEL_GFX (1 << 0)
+-#define RVII_CM_CLKSEL_GFX_VAL RVII_CLKSEL_GFX
+-
+-/*-------------------------------------------------------------------------
+- * 2430 Target modes: Along with each configuration the CPU has several
+- * modes which goes along with them. Modes mainly are the addition of
+- * describe DPLL combinations to go along with a ratio.
+- *-------------------------------------------------------------------------*/
+-
+-/* Hardware governed */
+-#define MX_48M_SRC (0 << 3)
+-#define MX_54M_SRC (0 << 5)
+-#define MX_APLLS_CLIKIN_12 (3 << 23)
+-#define MX_APLLS_CLIKIN_13 (2 << 23)
+-#define MX_APLLS_CLIKIN_19_2 (0 << 23)
+-
+-/*
+- * 2430 - standalone, 2*ref*M/(n+1), M/N is for exactness not relock speed
+- * #2 (ratio1) baseport-target
+- * #5a (ratio1) baseport-target, target DPLL = 266*2 = 532MHz
+- */
+-#define M5A_DPLL_MULT_12 (133 << 12)
+-#define M5A_DPLL_DIV_12 (5 << 8)
+-#define M5A_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \
+- M5A_DPLL_DIV_12 | M5A_DPLL_MULT_12 | \
+- MX_APLLS_CLIKIN_12
+-#define M5A_DPLL_MULT_13 (266 << 12)
+-#define M5A_DPLL_DIV_13 (12 << 8)
+-#define M5A_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | \
+- M5A_DPLL_DIV_13 | M5A_DPLL_MULT_13 | \
+- MX_APLLS_CLIKIN_13
+-#define M5A_DPLL_MULT_19 (180 << 12)
+-#define M5A_DPLL_DIV_19 (12 << 8)
+-#define M5A_CM_CLKSEL1_PLL_19_VAL MX_48M_SRC | MX_54M_SRC | \
+- M5A_DPLL_DIV_19 | M5A_DPLL_MULT_19 | \
+- MX_APLLS_CLIKIN_19_2
+-/* #5b (ratio1) target DPLL = 200*2 = 400MHz */
+-#define M5B_DPLL_MULT_12 (50 << 12)
+-#define M5B_DPLL_DIV_12 (2 << 8)
+-#define M5B_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \
+- M5B_DPLL_DIV_12 | M5B_DPLL_MULT_12 | \
+- MX_APLLS_CLIKIN_12
+-#define M5B_DPLL_MULT_13 (200 << 12)
+-#define M5B_DPLL_DIV_13 (12 << 8)
+-
+-#define M5B_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | \
+- M5B_DPLL_DIV_13 | M5B_DPLL_MULT_13 | \
+- MX_APLLS_CLIKIN_13
+-#define M5B_DPLL_MULT_19 (125 << 12)
+-#define M5B_DPLL_DIV_19 (31 << 8)
+-#define M5B_CM_CLKSEL1_PLL_19_VAL MX_48M_SRC | MX_54M_SRC | \
+- M5B_DPLL_DIV_19 | M5B_DPLL_MULT_19 | \
+- MX_APLLS_CLIKIN_19_2
+-/*
+- * #4 (ratio2)
+- * #3 (ratio2) baseport-target, target DPLL = 330*2 = 660MHz
+- */
+-#define M3_DPLL_MULT_12 (55 << 12)
+-#define M3_DPLL_DIV_12 (1 << 8)
+-#define M3_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \
+- M3_DPLL_DIV_12 | M3_DPLL_MULT_12 | \
+- MX_APLLS_CLIKIN_12
+-#define M3_DPLL_MULT_13 (330 << 12)
+-#define M3_DPLL_DIV_13 (12 << 8)
+-#define M3_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | \
+- M3_DPLL_DIV_13 | M3_DPLL_MULT_13 | \
+- MX_APLLS_CLIKIN_13
+-#define M3_DPLL_MULT_19 (275 << 12)
+-#define M3_DPLL_DIV_19 (15 << 8)
+-#define M3_CM_CLKSEL1_PLL_19_VAL MX_48M_SRC | MX_54M_SRC | \
+- M3_DPLL_DIV_19 | M3_DPLL_MULT_19 | \
+- MX_APLLS_CLIKIN_19_2
+-/* boot (boot) */
+-#define MB_DPLL_MULT (1 << 12)
+-#define MB_DPLL_DIV (0 << 8)
+-#define MB_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | MB_DPLL_DIV |\
+- MB_DPLL_MULT | MX_APLLS_CLIKIN_12
+-
+-#define MB_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | MB_DPLL_DIV |\
+- MB_DPLL_MULT | MX_APLLS_CLIKIN_13
+-
+-#define MB_CM_CLKSEL1_PLL_19_VAL MX_48M_SRC | MX_54M_SRC | MB_DPLL_DIV |\
+- MB_DPLL_MULT | MX_APLLS_CLIKIN_19
+-
+-/*
+- * 2430 - chassis (sedna)
+- * 165 (ratio1) same as above #2
+- * 150 (ratio1)
+- * 133 (ratio2) same as above #4
+- * 110 (ratio2) same as above #3
+- * 104 (ratio2)
+- * boot (boot)
+- */
+-
+-/*
+- * 2420 Equivalent - mode registers
+- * PRCM II , target DPLL = 2*300MHz = 600MHz
+- */
+-#define MII_DPLL_MULT_12 (50 << 12)
+-#define MII_DPLL_DIV_12 (1 << 8)
+-#define MII_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \
+- MII_DPLL_DIV_12 | MII_DPLL_MULT_12 | \
+- MX_APLLS_CLIKIN_12
+-#define MII_DPLL_MULT_13 (300 << 12)
+-#define MII_DPLL_DIV_13 (12 << 8)
+-#define MII_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | \
+- MII_DPLL_DIV_13 | MII_DPLL_MULT_13 | \
+- MX_APLLS_CLIKIN_13
+-
+-/* PRCM III target DPLL = 2*266 = 532MHz*/
+-#define MIII_DPLL_MULT_12 (133 << 12)
+-#define MIII_DPLL_DIV_12 (5 << 8)
+-#define MIII_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \
+- MIII_DPLL_DIV_12 | MIII_DPLL_MULT_12 | \
+- MX_APLLS_CLIKIN_12
+-#define MIII_DPLL_MULT_13 (266 << 12)
+-#define MIII_DPLL_DIV_13 (12 << 8)
+-#define MIII_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | \
+- MIII_DPLL_DIV_13 | MIII_DPLL_MULT_13 | \
+- MX_APLLS_CLIKIN_13
+-
+-/* PRCM VII (boot bypass) */
+-#define MVII_CM_CLKSEL1_PLL_12_VAL MB_CM_CLKSEL1_PLL_12_VAL
+-#define MVII_CM_CLKSEL1_PLL_13_VAL MB_CM_CLKSEL1_PLL_13_VAL
+-
+-/* High and low operation value */
+-#define MX_CLKSEL2_PLL_2x_VAL (2 << 0)
+-#define MX_CLKSEL2_PLL_1x_VAL (1 << 0)
+-
+-/*
+- * These represent optimal values for common parts, it won't work for all.
+- * As long as you scale down, most parameters are still work, they just
+- * become sub-optimal. The RFR value goes in the opposite direction. If you
+- * don't adjust it down as your clock period increases the refresh interval
+- * will not be met. Setting all parameters for complete worst case may work,
+- * but may cut memory performance by 2x. Due to errata the DLLs need to be
+- * unlocked and their value needs run time calibration. A dynamic call is
+- * need for that as no single right value exists acorss production samples.
+- *
+- * Only the FULL speed values are given. Current code is such that rate
+- * changes must be made at DPLLoutx2. The actual value adjustment for low
+- * frequency operation will be handled by omap_set_performance()
+- *
+- * By having the boot loader boot up in the fastest L4 speed available likely
+- * will result in something which you can switch between.
+- */
+-#define V24XX_SDRC_RFR_CTRL_133MHz (0x0003de00 | 1)
+-#define V24XX_SDRC_RFR_CTRL_100MHz (0x0002da01 | 1)
+-#define V24XX_SDRC_RFR_CTRL_110MHz (0x0002da01 | 1) /* Need to calc */
+-#define V24XX_SDRC_RFR_CTRL_BYPASS (0x00005000 | 1) /* Need to calc */
+-
+-/* MPU speed defines */
+-#define S12M 12000000
+-#define S13M 13000000
+-#define S19M 19200000
+-#define S26M 26000000
+-#define S100M 100000000
+-#define S133M 133000000
+-#define S150M 150000000
+-#define S165M 165000000
+-#define S200M 200000000
+-#define S266M 266000000
+-#define S300M 300000000
+-#define S330M 330000000
+-#define S400M 400000000
+-#define S532M 532000000
+-#define S600M 600000000
+-#define S660M 660000000
+-
+-/*-------------------------------------------------------------------------
+- * Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated.
+- * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,
+- * CM_CLKSEL_DSP, CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL,
+- * CM_CLKSEL2_PLL, CM_CLKSEL_MDM
+- *
+- * Filling in table based on H4 boards and 2430-SDPs variants available.
+- * There are quite a few more rates combinations which could be defined.
+- *
+- * When multiple values are defined the start up will try and choose the
+- * fastest one. If a 'fast' value is defined, then automatically, the /2
+- * one should be included as it can be used. Generally having more that
+- * one fast set does not make sense, as static timings need to be changed
+- * to change the set. The exception is the bypass setting which is
+- * availble for low power bypass.
+- *
+- * Note: This table needs to be sorted, fastest to slowest.
+- *-------------------------------------------------------------------------*/
+-static struct prcm_config rate_table[] = {
+- /* PRCM II - FAST */
+- {S12M, S600M, S300M, RII_CM_CLKSEL_MPU_VAL, /* 300MHz ARM */
+- RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL,
+- RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_12_VAL,
+- MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_100MHz,
+- RATE_IN_242X},
+-
+- {S13M, S600M, S300M, RII_CM_CLKSEL_MPU_VAL, /* 300MHz ARM */
+- RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL,
+- RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_13_VAL,
+- MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_100MHz,
+- RATE_IN_242X},
+-
+- /* PRCM III - FAST */
+- {S12M, S532M, S266M, RIII_CM_CLKSEL_MPU_VAL, /* 266MHz ARM */
+- RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL,
+- RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_12_VAL,
+- MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_133MHz,
+- RATE_IN_242X},
+-
+- {S13M, S532M, S266M, RIII_CM_CLKSEL_MPU_VAL, /* 266MHz ARM */
+- RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL,
+- RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_13_VAL,
+- MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_133MHz,
+- RATE_IN_242X},
+-
+- /* PRCM II - SLOW */
+- {S12M, S300M, S150M, RII_CM_CLKSEL_MPU_VAL, /* 150MHz ARM */
+- RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL,
+- RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_12_VAL,
+- MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_100MHz,
+- RATE_IN_242X},
+-
+- {S13M, S300M, S150M, RII_CM_CLKSEL_MPU_VAL, /* 150MHz ARM */
+- RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL,
+- RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_13_VAL,
+- MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_100MHz,
+- RATE_IN_242X},
+-
+- /* PRCM III - SLOW */
+- {S12M, S266M, S133M, RIII_CM_CLKSEL_MPU_VAL, /* 133MHz ARM */
+- RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL,
+- RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_12_VAL,
+- MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_133MHz,
+- RATE_IN_242X},
+-
+- {S13M, S266M, S133M, RIII_CM_CLKSEL_MPU_VAL, /* 133MHz ARM */
+- RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL,
+- RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_13_VAL,
+- MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_133MHz,
+- RATE_IN_242X},
+-
+- /* PRCM-VII (boot-bypass) */
+- {S12M, S12M, S12M, RVII_CM_CLKSEL_MPU_VAL, /* 12MHz ARM*/
+- RVII_CM_CLKSEL_DSP_VAL, RVII_CM_CLKSEL_GFX_VAL,
+- RVII_CM_CLKSEL1_CORE_VAL, MVII_CM_CLKSEL1_PLL_12_VAL,
+- MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_BYPASS,
+- RATE_IN_242X},
+-
+- /* PRCM-VII (boot-bypass) */
+- {S13M, S13M, S13M, RVII_CM_CLKSEL_MPU_VAL, /* 13MHz ARM */
+- RVII_CM_CLKSEL_DSP_VAL, RVII_CM_CLKSEL_GFX_VAL,
+- RVII_CM_CLKSEL1_CORE_VAL, MVII_CM_CLKSEL1_PLL_13_VAL,
+- MX_CLKSEL2_PLL_2x_VAL, 0, V24XX_SDRC_RFR_CTRL_BYPASS,
+- RATE_IN_242X},
+-
+- /* PRCM #3 - ratio2 (ES2) - FAST */
+- {S13M, S660M, S330M, R2_CM_CLKSEL_MPU_VAL, /* 330MHz ARM */
+- R2_CM_CLKSEL_DSP_VAL, R2_CM_CLKSEL_GFX_VAL,
+- R2_CM_CLKSEL1_CORE_VAL, M3_CM_CLKSEL1_PLL_13_VAL,
+- MX_CLKSEL2_PLL_2x_VAL, R2_CM_CLKSEL_MDM_VAL,
+- V24XX_SDRC_RFR_CTRL_110MHz,
+- RATE_IN_243X},
+-
+- /* PRCM #5a - ratio1 - FAST */
+- {S13M, S532M, S266M, R1_CM_CLKSEL_MPU_VAL, /* 266MHz ARM */
+- R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
+- R1_CM_CLKSEL1_CORE_VAL, M5A_CM_CLKSEL1_PLL_13_VAL,
+- MX_CLKSEL2_PLL_2x_VAL, R1_CM_CLKSEL_MDM_VAL,
+- V24XX_SDRC_RFR_CTRL_133MHz,
+- RATE_IN_243X},
+-
+- /* PRCM #5b - ratio1 - FAST */
+- {S13M, S400M, S200M, R1_CM_CLKSEL_MPU_VAL, /* 200MHz ARM */
+- R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
+- R1_CM_CLKSEL1_CORE_VAL, M5B_CM_CLKSEL1_PLL_13_VAL,
+- MX_CLKSEL2_PLL_2x_VAL, R1_CM_CLKSEL_MDM_VAL,
+- V24XX_SDRC_RFR_CTRL_100MHz,
+- RATE_IN_243X},
+-
+- /* PRCM #3 - ratio2 (ES2) - SLOW */
+- {S13M, S330M, S165M, R2_CM_CLKSEL_MPU_VAL, /* 165MHz ARM */
+- R2_CM_CLKSEL_DSP_VAL, R2_CM_CLKSEL_GFX_VAL,
+- R2_CM_CLKSEL1_CORE_VAL, M3_CM_CLKSEL1_PLL_13_VAL,
+- MX_CLKSEL2_PLL_1x_VAL, R2_CM_CLKSEL_MDM_VAL,
+- V24XX_SDRC_RFR_CTRL_110MHz,
+- RATE_IN_243X},
+-
+- /* PRCM #5a - ratio1 - SLOW */
+- {S13M, S266M, S133M, R1_CM_CLKSEL_MPU_VAL, /* 133MHz ARM */
+- R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
+- R1_CM_CLKSEL1_CORE_VAL, M5A_CM_CLKSEL1_PLL_13_VAL,
+- MX_CLKSEL2_PLL_1x_VAL, R1_CM_CLKSEL_MDM_VAL,
+- V24XX_SDRC_RFR_CTRL_133MHz,
+- RATE_IN_243X},
+-
+- /* PRCM #5b - ratio1 - SLOW*/
+- {S13M, S200M, S100M, R1_CM_CLKSEL_MPU_VAL, /* 100MHz ARM */
+- R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
+- R1_CM_CLKSEL1_CORE_VAL, M5B_CM_CLKSEL1_PLL_13_VAL,
+- MX_CLKSEL2_PLL_1x_VAL, R1_CM_CLKSEL_MDM_VAL,
+- V24XX_SDRC_RFR_CTRL_100MHz,
+- RATE_IN_243X},
+-
+- /* PRCM-boot/bypass */
+- {S13M, S13M, S13M, RB_CM_CLKSEL_MPU_VAL, /* 13Mhz */
+- RB_CM_CLKSEL_DSP_VAL, RB_CM_CLKSEL_GFX_VAL,
+- RB_CM_CLKSEL1_CORE_VAL, MB_CM_CLKSEL1_PLL_13_VAL,
+- MX_CLKSEL2_PLL_2x_VAL, RB_CM_CLKSEL_MDM_VAL,
+- V24XX_SDRC_RFR_CTRL_BYPASS,
+- RATE_IN_243X},
+-
+- /* PRCM-boot/bypass */
+- {S12M, S12M, S12M, RB_CM_CLKSEL_MPU_VAL, /* 12Mhz */
+- RB_CM_CLKSEL_DSP_VAL, RB_CM_CLKSEL_GFX_VAL,
+- RB_CM_CLKSEL1_CORE_VAL, MB_CM_CLKSEL1_PLL_12_VAL,
+- MX_CLKSEL2_PLL_2x_VAL, RB_CM_CLKSEL_MDM_VAL,
+- V24XX_SDRC_RFR_CTRL_BYPASS,
+- RATE_IN_243X},
+-
+- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+-};
+-
+-/*-------------------------------------------------------------------------
+- * 24xx clock tree.
+- *
+- * NOTE:In many cases here we are assigning a 'default' parent. In many
+- * cases the parent is selectable. The get/set parent calls will also
+- * switch sources.
+- *
+- * Many some clocks say always_enabled, but they can be auto idled for
+- * power savings. They will always be available upon clock request.
+- *
+- * Several sources are given initial rates which may be wrong, this will
+- * be fixed up in the init func.
+- *
+- * Things are broadly separated below by clock domains. It is
+- * noteworthy that most periferals have dependencies on multiple clock
+- * domains. Many get their interface clocks from the L4 domain, but get
+- * functional clocks from fixed sources or other core domain derived
+- * clocks.
+- *-------------------------------------------------------------------------*/
+-
+-/* Base external input clocks */
+-static struct clk func_32k_ck = {
+- .name = "func_32k_ck",
+- .rate = 32000,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- RATE_FIXED | ALWAYS_ENABLED,
+-};
+-
+-/* Typical 12/13MHz in standalone mode, will be 26Mhz in chassis mode */
+-static struct clk osc_ck = { /* (*12, *13, 19.2, *26, 38.4)MHz */
+- .name = "osc_ck",
+- .rate = 26000000, /* fixed up in clock init */
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- RATE_FIXED | RATE_PROPAGATES,
+-};
+-
+-/* With out modem likely 12MHz, with modem likely 13MHz */
+-static struct clk sys_ck = { /* (*12, *13, 19.2, 26, 38.4)MHz */
+- .name = "sys_ck", /* ~ ref_clk also */
+- .parent = &osc_ck,
+- .rate = 13000000,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+- .rate_offset = 6, /* sysclkdiv 1 or 2, already handled or no boot */
+- .recalc = &omap2_sys_clk_recalc,
+-};
+-
+-static struct clk alt_ck = { /* Typical 54M or 48M, may not exist */
+- .name = "alt_ck",
+- .rate = 54000000,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+- .recalc = &omap2_propagate_rate,
+-};
+-
+-/*
+- * Analog domain root source clocks
+- */
+-
+-/* dpll_ck, is broken out in to special cases through clksel */
+-static struct clk dpll_ck = {
+- .name = "dpll_ck",
+- .parent = &sys_ck, /* Can be func_32k also */
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- RATE_PROPAGATES | RATE_CKCTL | CM_PLL_SEL1,
+- .recalc = &omap2_clksel_recalc,
+-};
+-
+-static struct clk apll96_ck = {
+- .name = "apll96_ck",
+- .parent = &sys_ck,
+- .rate = 96000000,
+- .flags = CLOCK_IN_OMAP242X |CLOCK_IN_OMAP243X |
+- RATE_FIXED | RATE_PROPAGATES,
+- .enable_reg = (void __iomem *)&CM_CLKEN_PLL,
+- .enable_bit = 0x2,
+- .recalc = &omap2_propagate_rate,
+-};
+-
+-static struct clk apll54_ck = {
+- .name = "apll54_ck",
+- .parent = &sys_ck,
+- .rate = 54000000,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- RATE_FIXED | RATE_PROPAGATES,
+- .enable_reg = (void __iomem *)&CM_CLKEN_PLL,
+- .enable_bit = 0x6,
+- .recalc = &omap2_propagate_rate,
+-};
++int omap2_clk_enable(struct clk *clk);
++void omap2_clk_disable(struct clk *clk);
++long omap2_clk_round_rate(struct clk *clk, unsigned long rate);
++int omap2_clk_set_rate(struct clk *clk, unsigned long rate);
++int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent);
+
+-/*
+- * PRCM digital base sources
+- */
+-static struct clk func_54m_ck = {
+- .name = "func_54m_ck",
+- .parent = &apll54_ck, /* can also be alt_clk */
+- .rate = 54000000,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- RATE_FIXED | CM_PLL_SEL1 | RATE_PROPAGATES,
+- .src_offset = 5,
+- .enable_reg = (void __iomem *)&CM_CLKEN_PLL,
+- .enable_bit = 0xff,
+- .recalc = &omap2_propagate_rate,
+-};
+-
+-static struct clk core_ck = {
+- .name = "core_ck",
+- .parent = &dpll_ck, /* can also be 32k */
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- ALWAYS_ENABLED | RATE_PROPAGATES,
+- .recalc = &omap2_propagate_rate,
+-};
+-
+-static struct clk sleep_ck = { /* sys_clk or 32k */
+- .name = "sleep_ck",
+- .parent = &func_32k_ck,
+- .rate = 32000,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .recalc = &omap2_propagate_rate,
+-};
+-
+-static struct clk func_96m_ck = {
+- .name = "func_96m_ck",
+- .parent = &apll96_ck,
+- .rate = 96000000,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- RATE_FIXED | RATE_PROPAGATES,
+- .enable_reg = (void __iomem *)&CM_CLKEN_PLL,
+- .enable_bit = 0xff,
+- .recalc = &omap2_propagate_rate,
+-};
+-
+-static struct clk func_48m_ck = {
+- .name = "func_48m_ck",
+- .parent = &apll96_ck, /* 96M or Alt */
+- .rate = 48000000,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- RATE_FIXED | CM_PLL_SEL1 | RATE_PROPAGATES,
+- .src_offset = 3,
+- .enable_reg = (void __iomem *)&CM_CLKEN_PLL,
+- .enable_bit = 0xff,
+- .recalc = &omap2_propagate_rate,
+-};
+-
+-static struct clk func_12m_ck = {
+- .name = "func_12m_ck",
+- .parent = &func_48m_ck,
+- .rate = 12000000,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- RATE_FIXED | RATE_PROPAGATES,
+- .recalc = &omap2_propagate_rate,
+- .enable_reg = (void __iomem *)&CM_CLKEN_PLL,
+- .enable_bit = 0xff,
+-};
+-
+-/* Secure timer, only available in secure mode */
+-static struct clk wdt1_osc_ck = {
+- .name = "ck_wdt1_osc",
+- .parent = &osc_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk sys_clkout = {
+- .name = "sys_clkout",
+- .parent = &func_54m_ck,
+- .rate = 54000000,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- CM_SYSCLKOUT_SEL1 | RATE_CKCTL,
+- .src_offset = 0,
+- .enable_reg = (void __iomem *)&PRCM_CLKOUT_CTRL,
+- .enable_bit = 7,
+- .rate_offset = 3,
+- .recalc = &omap2_clksel_recalc,
+-};
+-
+-/* In 2430, new in 2420 ES2 */
+-static struct clk sys_clkout2 = {
+- .name = "sys_clkout2",
+- .parent = &func_54m_ck,
+- .rate = 54000000,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- CM_SYSCLKOUT_SEL1 | RATE_CKCTL,
+- .src_offset = 8,
+- .enable_reg = (void __iomem *)&PRCM_CLKOUT_CTRL,
+- .enable_bit = 15,
+- .rate_offset = 11,
+- .recalc = &omap2_clksel_recalc,
+-};
+-
+-static struct clk emul_ck = {
+- .name = "emul_ck",
+- .parent = &func_54m_ck,
+- .flags = CLOCK_IN_OMAP242X,
+- .enable_reg = (void __iomem *)&PRCM_CLKEMUL_CTRL,
+- .enable_bit = 0,
+- .recalc = &omap2_propagate_rate,
+-
+-};
+-
+-/*
+- * MPU clock domain
+- * Clocks:
+- * MPU_FCLK, MPU_ICLK
+- * INT_M_FCLK, INT_M_I_CLK
+- *
+- * - Individual clocks are hardware managed.
+- * - Base divider comes from: CM_CLKSEL_MPU
+- *
+- */
+-static struct clk mpu_ck = { /* Control cpu */
+- .name = "mpu_ck",
+- .parent = &core_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_CKCTL |
+- ALWAYS_ENABLED | CM_MPU_SEL1 | DELAYED_APP |
+- CONFIG_PARTICIPANT | RATE_PROPAGATES,
+- .rate_offset = 0, /* bits 0-4 */
+- .recalc = &omap2_clksel_recalc,
+-};
+-
+-/*
+- * DSP (2430-IVA2.1) (2420-UMA+IVA1) clock domain
+- * Clocks:
+- * 2430: IVA2.1_FCLK, IVA2.1_ICLK
+- * 2420: UMA_FCLK, UMA_ICLK, IVA_MPU, IVA_COP
+- */
+-static struct clk iva2_1_fck = {
+- .name = "iva2_1_fck",
+- .parent = &core_ck,
+- .flags = CLOCK_IN_OMAP243X | RATE_CKCTL | CM_DSP_SEL1 |
+- DELAYED_APP | RATE_PROPAGATES |
+- CONFIG_PARTICIPANT,
+- .rate_offset = 0,
+- .enable_reg = (void __iomem *)&CM_FCLKEN_DSP,
+- .enable_bit = 0,
+- .recalc = &omap2_clksel_recalc,
+-};
+-
+-static struct clk iva2_1_ick = {
+- .name = "iva2_1_ick",
+- .parent = &iva2_1_fck,
+- .flags = CLOCK_IN_OMAP243X | RATE_CKCTL | CM_DSP_SEL1 |
+- DELAYED_APP | CONFIG_PARTICIPANT,
+- .rate_offset = 5,
+- .recalc = &omap2_clksel_recalc,
+-};
+-
+-/*
+- * Won't be too specific here. The core clock comes into this block
+- * it is divided then tee'ed. One branch goes directly to xyz enable
+- * controls. The other branch gets further divided by 2 then possibly
+- * routed into a synchronizer and out of clocks abc.
+- */
+-static struct clk dsp_fck = {
+- .name = "dsp_fck",
+- .parent = &core_ck,
+- .flags = CLOCK_IN_OMAP242X | RATE_CKCTL | CM_DSP_SEL1 |
+- DELAYED_APP | CONFIG_PARTICIPANT | RATE_PROPAGATES,
+- .rate_offset = 0,
+- .enable_reg = (void __iomem *)&CM_FCLKEN_DSP,
+- .enable_bit = 0,
+- .recalc = &omap2_clksel_recalc,
+-};
+-
+-static struct clk dsp_ick = {
+- .name = "dsp_ick", /* apparently ipi and isp */
+- .parent = &dsp_fck,
+- .flags = CLOCK_IN_OMAP242X | RATE_CKCTL | CM_DSP_SEL1 |
+- DELAYED_APP | CONFIG_PARTICIPANT,
+- .rate_offset = 5,
+- .enable_reg = (void __iomem *)&CM_ICLKEN_DSP,
+- .enable_bit = 1, /* for ipi */
+- .recalc = &omap2_clksel_recalc,
+-};
+-
+-static struct clk iva1_ifck = {
+- .name = "iva1_ifck",
+- .parent = &core_ck,
+- .flags = CLOCK_IN_OMAP242X | CM_DSP_SEL1 | RATE_CKCTL |
+- CONFIG_PARTICIPANT | RATE_PROPAGATES | DELAYED_APP,
+- .rate_offset= 8,
+- .enable_reg = (void __iomem *)&CM_FCLKEN_DSP,
+- .enable_bit = 10,
+- .recalc = &omap2_clksel_recalc,
+-};
+-
+-/* IVA1 mpu/int/i/f clocks are /2 of parent */
+-static struct clk iva1_mpu_int_ifck = {
+- .name = "iva1_mpu_int_ifck",
+- .parent = &iva1_ifck,
+- .flags = CLOCK_IN_OMAP242X | RATE_CKCTL | CM_DSP_SEL1,
+- .enable_reg = (void __iomem *)&CM_FCLKEN_DSP,
+- .enable_bit = 8,
+- .recalc = &omap2_clksel_recalc,
+-};
+-
+-/*
+- * L3 clock domain
+- * L3 clocks are used for both interface and functional clocks to
+- * multiple entities. Some of these clocks are completely managed
+- * by hardware, and some others allow software control. Hardware
+- * managed ones general are based on directly CLK_REQ signals and
+- * various auto idle settings. The functional spec sets many of these
+- * as 'tie-high' for their enables.
+- *
+- * I-CLOCKS:
+- * L3-Interconnect, SMS, GPMC, SDRC, OCM_RAM, OCM_ROM, SDMA
+- * CAM, HS-USB.
+- * F-CLOCK
+- * SSI.
+- *
+- * GPMC memories and SDRC have timing and clock sensitive registers which
+- * may very well need notification when the clock changes. Currently for low
+- * operating points, these are taken care of in sleep.S.
+- */
+-static struct clk core_l3_ck = { /* Used for ick and fck, interconnect */
+- .name = "core_l3_ck",
+- .parent = &core_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- RATE_CKCTL | ALWAYS_ENABLED | CM_CORE_SEL1 |
+- DELAYED_APP | CONFIG_PARTICIPANT |
+- RATE_PROPAGATES,
+- .rate_offset = 0,
+- .recalc = &omap2_clksel_recalc,
+-};
+-
+-static struct clk usb_l4_ick = { /* FS-USB interface clock */
+- .name = "usb_l4_ick",
+- .parent = &core_l3_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP |
+- CONFIG_PARTICIPANT,
+- .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE,
+- .enable_bit = 0,
+- .rate_offset = 25,
+- .recalc = &omap2_clksel_recalc,
+-};
+-
+-/*
+- * SSI is in L3 management domain, its direct parent is core not l3,
+- * many core power domain entities are grouped into the L3 clock
+- * domain.
+- * SSI_SSR_FCLK, SSI_SST_FCLK, SSI_L4_CLIK
+- *
+- * ssr = core/1/2/3/4/5, sst = 1/2 ssr.
+- */
+-static struct clk ssi_ssr_sst_fck = {
+- .name = "ssi_fck",
+- .parent = &core_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP,
+- .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE, /* bit 1 */
+- .enable_bit = 1,
+- .rate_offset = 20,
+- .recalc = &omap2_clksel_recalc,
+-};
+-
+-/*
+- * GFX clock domain
+- * Clocks:
+- * GFX_FCLK, GFX_ICLK
+- * GFX_CG1(2d), GFX_CG2(3d)
+- *
+- * GFX_FCLK runs from L3, and is divided by (1,2,3,4)
+- * The 2d and 3d clocks run at a hardware determined
+- * divided value of fclk.
+- *
+- */
+-static struct clk gfx_3d_fck = {
+- .name = "gfx_3d_fck",
+- .parent = &core_l3_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- RATE_CKCTL | CM_GFX_SEL1,
+- .enable_reg = (void __iomem *)&CM_FCLKEN_GFX,
+- .enable_bit = 2,
+- .rate_offset= 0,
+- .recalc = &omap2_clksel_recalc,
+-};
+-
+-static struct clk gfx_2d_fck = {
+- .name = "gfx_2d_fck",
+- .parent = &core_l3_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- RATE_CKCTL | CM_GFX_SEL1,
+- .enable_reg = (void __iomem *)&CM_FCLKEN_GFX,
+- .enable_bit = 1,
+- .rate_offset= 0,
+- .recalc = &omap2_clksel_recalc,
+-};
+-
+-static struct clk gfx_ick = {
+- .name = "gfx_ick", /* From l3 */
+- .parent = &core_l3_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- RATE_CKCTL,
+- .enable_reg = (void __iomem *)&CM_ICLKEN_GFX, /* bit 0 */
+- .enable_bit = 0,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-/*
+- * Modem clock domain (2430)
+- * CLOCKS:
+- * MDM_OSC_CLK
+- * MDM_ICLK
+- */
+-static struct clk mdm_ick = { /* used both as a ick and fck */
+- .name = "mdm_ick",
+- .parent = &core_ck,
+- .flags = CLOCK_IN_OMAP243X | RATE_CKCTL | CM_MODEM_SEL1 |
+- DELAYED_APP | CONFIG_PARTICIPANT,
+- .rate_offset = 0,
+- .enable_reg = (void __iomem *)&CM_ICLKEN_MDM,
+- .enable_bit = 0,
+- .recalc = &omap2_clksel_recalc,
+-};
+-
+-static struct clk mdm_osc_ck = {
+- .name = "mdm_osc_ck",
+- .rate = 26000000,
+- .parent = &osc_ck,
+- .flags = CLOCK_IN_OMAP243X | RATE_FIXED,
+- .enable_reg = (void __iomem *)&CM_FCLKEN_MDM,
+- .enable_bit = 1,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-/*
+- * L4 clock management domain
+- *
+- * This domain contains lots of interface clocks from the L4 interface, some
+- * functional clocks. Fixed APLL functional source clocks are managed in
+- * this domain.
+- */
+-static struct clk l4_ck = { /* used both as an ick and fck */
+- .name = "l4_ck",
+- .parent = &core_l3_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- RATE_CKCTL | ALWAYS_ENABLED | CM_CORE_SEL1 |
+- DELAYED_APP | RATE_PROPAGATES,
+- .rate_offset = 5,
+- .recalc = &omap2_clksel_recalc,
+-};
+-
+-static struct clk ssi_l4_ick = {
+- .name = "ssi_l4_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_CKCTL,
+- .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE, /* bit 1 */
+- .enable_bit = 1,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-/*
+- * DSS clock domain
+- * CLOCKs:
+- * DSS_L4_ICLK, DSS_L3_ICLK,
+- * DSS_CLK1, DSS_CLK2, DSS_54MHz_CLK
+- *
+- * DSS is both initiator and target.
+- */
+-static struct clk dss_ick = { /* Enables both L3,L4 ICLK's */
+- .name = "dss_ick",
+- .parent = &l4_ck, /* really both l3 and l4 */
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_CKCTL,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
+- .enable_bit = 0,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk dss1_fck = {
+- .name = "dss1_fck",
+- .parent = &core_ck, /* Core or sys */
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 0,
+- .rate_offset = 8,
+- .src_offset = 8,
+- .recalc = &omap2_clksel_recalc,
+-};
+-
+-static struct clk dss2_fck = { /* Alt clk used in power management */
+- .name = "dss2_fck",
+- .parent = &sys_ck, /* fixed at sys_ck or 48MHz */
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- RATE_CKCTL | CM_CORE_SEL1 | RATE_FIXED |
+- DELAYED_APP,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 1,
+- .src_offset = 13,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk dss_54m_fck = { /* Alt clk used in power management */
+- .name = "dss_54m_fck", /* 54m tv clk */
+- .parent = &func_54m_ck,
+- .rate = 54000000,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- RATE_FIXED | RATE_PROPAGATES,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 2,
+- .recalc = &omap2_propagate_rate,
+-};
+-
+-/*
+- * CORE power domain ICLK & FCLK defines.
+- * Many of the these can have more than one possible parent. Entries
+- * here will likely have an L4 interface parent, and may have multiple
+- * functional clock parents.
+- */
+-static struct clk gpt1_ick = {
+- .name = "gpt1_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN_WKUP, /* Bit0 */
+- .enable_bit = 0,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt1_fck = {
+- .name = "gpt1_fck",
+- .parent = &func_32k_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- CM_WKUP_SEL1,
+- .enable_reg = (void __iomem *)&CM_FCLKEN_WKUP, /* Bit0 */
+- .enable_bit = 0,
+- .src_offset = 0,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt2_ick = {
+- .name = "gpt2_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* Bit4 */
+- .enable_bit = 4,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt2_fck = {
+- .name = "gpt2_fck",
+- .parent = &func_32k_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- CM_CORE_SEL2,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 4,
+- .src_offset = 2,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt3_ick = {
+- .name = "gpt3_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* Bit5 */
+- .enable_bit = 5,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt3_fck = {
+- .name = "gpt3_fck",
+- .parent = &func_32k_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- CM_CORE_SEL2,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 5,
+- .src_offset = 4,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt4_ick = {
+- .name = "gpt4_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* Bit6 */
+- .enable_bit = 6,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt4_fck = {
+- .name = "gpt4_fck",
+- .parent = &func_32k_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- CM_CORE_SEL2,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 6,
+- .src_offset = 6,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt5_ick = {
+- .name = "gpt5_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* Bit7 */
+- .enable_bit = 7,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt5_fck = {
+- .name = "gpt5_fck",
+- .parent = &func_32k_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- CM_CORE_SEL2,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 7,
+- .src_offset = 8,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt6_ick = {
+- .name = "gpt6_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_bit = 8,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* bit8 */
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt6_fck = {
+- .name = "gpt6_fck",
+- .parent = &func_32k_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- CM_CORE_SEL2,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 8,
+- .src_offset = 10,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt7_ick = {
+- .name = "gpt7_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* bit9 */
+- .enable_bit = 9,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt7_fck = {
+- .name = "gpt7_fck",
+- .parent = &func_32k_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- CM_CORE_SEL2,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 9,
+- .src_offset = 12,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt8_ick = {
+- .name = "gpt8_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* bit10 */
+- .enable_bit = 10,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt8_fck = {
+- .name = "gpt8_fck",
+- .parent = &func_32k_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- CM_CORE_SEL2,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 10,
+- .src_offset = 14,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt9_ick = {
+- .name = "gpt9_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
+- .enable_bit = 11,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt9_fck = {
+- .name = "gpt9_fck",
+- .parent = &func_32k_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- CM_CORE_SEL2,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 11,
+- .src_offset = 16,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt10_ick = {
+- .name = "gpt10_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
+- .enable_bit = 12,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt10_fck = {
+- .name = "gpt10_fck",
+- .parent = &func_32k_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- CM_CORE_SEL2,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 12,
+- .src_offset = 18,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt11_ick = {
+- .name = "gpt11_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
+- .enable_bit = 13,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt11_fck = {
+- .name = "gpt11_fck",
+- .parent = &func_32k_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- CM_CORE_SEL2,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 13,
+- .src_offset = 20,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt12_ick = {
+- .name = "gpt12_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* bit14 */
+- .enable_bit = 14,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpt12_fck = {
+- .name = "gpt12_fck",
+- .parent = &func_32k_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- CM_CORE_SEL2,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 14,
+- .src_offset = 22,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcbsp1_ick = {
+- .name = "mcbsp1_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_bit = 15,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* bit16 */
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcbsp1_fck = {
+- .name = "mcbsp1_fck",
+- .parent = &func_96m_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_bit = 15,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcbsp2_ick = {
+- .name = "mcbsp2_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_bit = 16,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcbsp2_fck = {
+- .name = "mcbsp2_fck",
+- .parent = &func_96m_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_bit = 16,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcbsp3_ick = {
+- .name = "mcbsp3_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE,
+- .enable_bit = 3,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcbsp3_fck = {
+- .name = "mcbsp3_fck",
+- .parent = &func_96m_ck,
+- .flags = CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE,
+- .enable_bit = 3,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcbsp4_ick = {
+- .name = "mcbsp4_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE,
+- .enable_bit = 4,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcbsp4_fck = {
+- .name = "mcbsp4_fck",
+- .parent = &func_96m_ck,
+- .flags = CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE,
+- .enable_bit = 4,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcbsp5_ick = {
+- .name = "mcbsp5_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE,
+- .enable_bit = 5,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcbsp5_fck = {
+- .name = "mcbsp5_fck",
+- .parent = &func_96m_ck,
+- .flags = CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE,
+- .enable_bit = 5,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcspi1_ick = {
+- .name = "mcspi_ick",
+- .id = 1,
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
+- .enable_bit = 17,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcspi1_fck = {
+- .name = "mcspi_fck",
+- .id = 1,
+- .parent = &func_48m_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 17,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcspi2_ick = {
+- .name = "mcspi_ick",
+- .id = 2,
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
+- .enable_bit = 18,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcspi2_fck = {
+- .name = "mcspi_fck",
+- .id = 2,
+- .parent = &func_48m_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 18,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcspi3_ick = {
+- .name = "mcspi_ick",
+- .id = 3,
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE,
+- .enable_bit = 9,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mcspi3_fck = {
+- .name = "mcspi_fck",
+- .id = 3,
+- .parent = &func_48m_ck,
+- .flags = CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE,
+- .enable_bit = 9,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk uart1_ick = {
+- .name = "uart1_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
+- .enable_bit = 21,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk uart1_fck = {
+- .name = "uart1_fck",
+- .parent = &func_48m_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 21,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk uart2_ick = {
+- .name = "uart2_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
+- .enable_bit = 22,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk uart2_fck = {
+- .name = "uart2_fck",
+- .parent = &func_48m_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 22,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk uart3_ick = {
+- .name = "uart3_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE,
+- .enable_bit = 2,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk uart3_fck = {
+- .name = "uart3_fck",
+- .parent = &func_48m_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE,
+- .enable_bit = 2,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpios_ick = {
+- .name = "gpios_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN_WKUP,
+- .enable_bit = 2,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk gpios_fck = {
+- .name = "gpios_fck",
+- .parent = &func_32k_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN_WKUP,
+- .enable_bit = 2,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mpu_wdt_ick = {
+- .name = "mpu_wdt_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN_WKUP,
+- .enable_bit = 3,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mpu_wdt_fck = {
+- .name = "mpu_wdt_fck",
+- .parent = &func_32k_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN_WKUP,
+- .enable_bit = 3,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk sync_32k_ick = {
+- .name = "sync_32k_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN_WKUP,
+- .enable_bit = 1,
+- .recalc = &omap2_followparent_recalc,
+-};
+-static struct clk wdt1_ick = {
+- .name = "wdt1_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN_WKUP,
+- .enable_bit = 4,
+- .recalc = &omap2_followparent_recalc,
+-};
+-static struct clk omapctrl_ick = {
+- .name = "omapctrl_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN_WKUP,
+- .enable_bit = 5,
+- .recalc = &omap2_followparent_recalc,
+-};
+-static struct clk icr_ick = {
+- .name = "icr_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN_WKUP,
+- .enable_bit = 6,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk cam_ick = {
+- .name = "cam_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
+- .enable_bit = 31,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk cam_fck = {
+- .name = "cam_fck",
+- .parent = &func_96m_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 31,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mailboxes_ick = {
+- .name = "mailboxes_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
+- .enable_bit = 30,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk wdt4_ick = {
+- .name = "wdt4_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
+- .enable_bit = 29,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk wdt4_fck = {
+- .name = "wdt4_fck",
+- .parent = &func_32k_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 29,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk wdt3_ick = {
+- .name = "wdt3_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
+- .enable_bit = 28,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk wdt3_fck = {
+- .name = "wdt3_fck",
+- .parent = &func_32k_ck,
+- .flags = CLOCK_IN_OMAP242X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 28,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mspro_ick = {
+- .name = "mspro_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
+- .enable_bit = 27,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mspro_fck = {
+- .name = "mspro_fck",
+- .parent = &func_96m_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 27,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mmc_ick = {
+- .name = "mmc_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
+- .enable_bit = 26,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mmc_fck = {
+- .name = "mmc_fck",
+- .parent = &func_96m_ck,
+- .flags = CLOCK_IN_OMAP242X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 26,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk fac_ick = {
+- .name = "fac_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
+- .enable_bit = 25,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk fac_fck = {
+- .name = "fac_fck",
+- .parent = &func_12m_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 25,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk eac_ick = {
+- .name = "eac_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
+- .enable_bit = 24,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk eac_fck = {
+- .name = "eac_fck",
+- .parent = &func_96m_ck,
+- .flags = CLOCK_IN_OMAP242X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 24,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk hdq_ick = {
+- .name = "hdq_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
+- .enable_bit = 23,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk hdq_fck = {
+- .name = "hdq_fck",
+- .parent = &func_12m_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 23,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk i2c2_ick = {
+- .name = "i2c_ick",
+- .id = 2,
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
+- .enable_bit = 20,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk i2c2_fck = {
+- .name = "i2c_fck",
+- .id = 2,
+- .parent = &func_12m_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 20,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk i2chs2_fck = {
+- .name = "i2chs2_fck",
+- .parent = &func_96m_ck,
+- .flags = CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE,
+- .enable_bit = 20,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk i2c1_ick = {
+- .name = "i2c_ick",
+- .id = 1,
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
+- .enable_bit = 19,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk i2c1_fck = {
+- .name = "i2c_fck",
+- .id = 1,
+- .parent = &func_12m_ck,
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 19,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk i2chs1_fck = {
+- .name = "i2chs1_fck",
+- .parent = &func_96m_ck,
+- .flags = CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE,
+- .enable_bit = 19,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk vlynq_ick = {
+- .name = "vlynq_ick",
+- .parent = &core_l3_ck,
+- .flags = CLOCK_IN_OMAP242X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
+- .enable_bit = 3,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk vlynq_fck = {
+- .name = "vlynq_fck",
+- .parent = &func_96m_ck,
+- .flags = CLOCK_IN_OMAP242X | RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP,
+- .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
+- .enable_bit = 3,
+- .src_offset = 15,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk sdrc_ick = {
+- .name = "sdrc_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN3_CORE,
+- .enable_bit = 2,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk des_ick = {
+- .name = "des_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN4_CORE,
+- .enable_bit = 0,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk sha_ick = {
+- .name = "sha_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN4_CORE,
+- .enable_bit = 1,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk rng_ick = {
+- .name = "rng_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN4_CORE,
+- .enable_bit = 2,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk aes_ick = {
+- .name = "aes_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN4_CORE,
+- .enable_bit = 3,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk pka_ick = {
+- .name = "pka_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN4_CORE,
+- .enable_bit = 4,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk usb_fck = {
+- .name = "usb_fck",
+- .parent = &func_48m_ck,
+- .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE,
+- .enable_bit = 0,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk usbhs_ick = {
+- .name = "usbhs_ick",
+- .parent = &core_l3_ck,
+- .flags = CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE,
+- .enable_bit = 6,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mmchs1_ick = {
+- .name = "mmchs1_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE,
+- .enable_bit = 7,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mmchs1_fck = {
+- .name = "mmchs1_fck",
+- .parent = &func_96m_ck,
+- .flags = CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE,
+- .enable_bit = 7,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mmchs2_ick = {
+- .name = "mmchs2_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE,
+- .enable_bit = 8,
+- .recalc = &omap2_followparent_recalc,
+-};
+-
+-static struct clk mmchs2_fck = {
+- .name = "mmchs2_fck",
+- .parent = &func_96m_ck,
+- .flags = CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE,
+- .enable_bit = 8,
+- .recalc = &omap2_followparent_recalc,
+-};
++#ifdef CONFIG_OMAP_RESET_CLOCKS
++void omap2_clk_disable_unused(struct clk *clk);
++#else
++#define omap2_clk_disable_unused NULL
++#endif
+
+-static struct clk gpio5_ick = {
+- .name = "gpio5_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE,
+- .enable_bit = 10,
+- .recalc = &omap2_followparent_recalc,
+-};
++void omap2_clksel_recalc(struct clk *clk);
++void omap2_init_clksel_parent(struct clk *clk);
++u32 omap2_clksel_get_divisor(struct clk *clk);
++u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
++ u32 *new_div);
++u32 omap2_clksel_to_divisor(struct clk *clk, u32 field_val);
++u32 omap2_divisor_to_clksel(struct clk *clk, u32 div);
++void omap2_fixed_divisor_recalc(struct clk *clk);
++long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate);
++int omap2_clksel_set_rate(struct clk *clk, unsigned long rate);
++u32 omap2_get_dpll_rate(struct clk *clk);
++int omap2_wait_clock_ready(void __iomem *reg, u32 cval, const char *name);
+
+-static struct clk gpio5_fck = {
+- .name = "gpio5_fck",
+- .parent = &func_32k_ck,
+- .flags = CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE,
+- .enable_bit = 10,
+- .recalc = &omap2_followparent_recalc,
+-};
++extern u8 cpu_mask;
+
+-static struct clk mdm_intc_ick = {
+- .name = "mdm_intc_ick",
+- .parent = &l4_ck,
+- .flags = CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE,
+- .enable_bit = 11,
+- .recalc = &omap2_followparent_recalc,
++/* clksel_rate data common to 24xx/343x */
++static const struct clksel_rate gpt_32k_rates[] = {
++ { .div = 1, .val = 0, .flags = RATE_IN_24XX | RATE_IN_343X | DEFAULT_RATE },
++ { .div = 0 }
+ };
+
+-static struct clk mmchsdb1_fck = {
+- .name = "mmchsdb1_fck",
+- .parent = &func_32k_ck,
+- .flags = CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE,
+- .enable_bit = 16,
+- .recalc = &omap2_followparent_recalc,
++static const struct clksel_rate gpt_sys_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_24XX | RATE_IN_343X | DEFAULT_RATE },
++ { .div = 0 }
+ };
+
+-static struct clk mmchsdb2_fck = {
+- .name = "mmchsdb2_fck",
+- .parent = &func_32k_ck,
+- .flags = CLOCK_IN_OMAP243X,
+- .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE,
+- .enable_bit = 17,
+- .recalc = &omap2_followparent_recalc,
++static const struct clksel_rate gfx_l3_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_24XX | RATE_IN_343X },
++ { .div = 2, .val = 2, .flags = RATE_IN_24XX | RATE_IN_343X | DEFAULT_RATE },
++ { .div = 3, .val = 3, .flags = RATE_IN_243X | RATE_IN_343X },
++ { .div = 4, .val = 4, .flags = RATE_IN_243X | RATE_IN_343X },
++ { .div = 0 }
+ };
+
+-/*
+- * This clock is a composite clock which does entire set changes then
+- * forces a rebalance. It keys on the MPU speed, but it really could
+- * be any key speed part of a set in the rate table.
+- *
+- * to really change a set, you need memory table sets which get changed
+- * in sram, pre-notifiers & post notifiers, changing the top set, without
+- * having low level display recalc's won't work... this is why dpm notifiers
+- * work, isr's off, walk a list of clocks already _off_ and not messing with
+- * the bus.
+- *
+- * This clock should have no parent. It embodies the entire upper level
+- * active set. A parent will mess up some of the init also.
+- */
+-static struct clk virt_prcm_set = {
+- .name = "virt_prcm_set",
+- .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+- VIRTUAL_CLOCK | ALWAYS_ENABLED | DELAYED_APP,
+- .parent = &mpu_ck, /* Indexed by mpu speed, no parent */
+- .recalc = &omap2_mpu_recalc, /* sets are keyed on mpu rate */
+- .set_rate = &omap2_select_table_rate,
+- .round_rate = &omap2_round_to_table_rate,
+-};
+-
+-static struct clk *onchip_clks[] = {
+- /* external root sources */
+- &func_32k_ck,
+- &osc_ck,
+- &sys_ck,
+- &alt_ck,
+- /* internal analog sources */
+- &dpll_ck,
+- &apll96_ck,
+- &apll54_ck,
+- /* internal prcm root sources */
+- &func_54m_ck,
+- &core_ck,
+- &sleep_ck,
+- &func_96m_ck,
+- &func_48m_ck,
+- &func_12m_ck,
+- &wdt1_osc_ck,
+- &sys_clkout,
+- &sys_clkout2,
+- &emul_ck,
+- /* mpu domain clocks */
+- &mpu_ck,
+- /* dsp domain clocks */
+- &iva2_1_fck, /* 2430 */
+- &iva2_1_ick,
+- &dsp_ick, /* 2420 */
+- &dsp_fck,
+- &iva1_ifck,
+- &iva1_mpu_int_ifck,
+- /* GFX domain clocks */
+- &gfx_3d_fck,
+- &gfx_2d_fck,
+- &gfx_ick,
+- /* Modem domain clocks */
+- &mdm_ick,
+- &mdm_osc_ck,
+- /* DSS domain clocks */
+- &dss_ick,
+- &dss1_fck,
+- &dss2_fck,
+- &dss_54m_fck,
+- /* L3 domain clocks */
+- &core_l3_ck,
+- &ssi_ssr_sst_fck,
+- &usb_l4_ick,
+- /* L4 domain clocks */
+- &l4_ck, /* used as both core_l4 and wu_l4 */
+- &ssi_l4_ick,
+- /* virtual meta-group clock */
+- &virt_prcm_set,
+- /* general l4 interface ck, multi-parent functional clk */
+- &gpt1_ick,
+- &gpt1_fck,
+- &gpt2_ick,
+- &gpt2_fck,
+- &gpt3_ick,
+- &gpt3_fck,
+- &gpt4_ick,
+- &gpt4_fck,
+- &gpt5_ick,
+- &gpt5_fck,
+- &gpt6_ick,
+- &gpt6_fck,
+- &gpt7_ick,
+- &gpt7_fck,
+- &gpt8_ick,
+- &gpt8_fck,
+- &gpt9_ick,
+- &gpt9_fck,
+- &gpt10_ick,
+- &gpt10_fck,
+- &gpt11_ick,
+- &gpt11_fck,
+- &gpt12_ick,
+- &gpt12_fck,
+- &mcbsp1_ick,
+- &mcbsp1_fck,
+- &mcbsp2_ick,
+- &mcbsp2_fck,
+- &mcbsp3_ick,
+- &mcbsp3_fck,
+- &mcbsp4_ick,
+- &mcbsp4_fck,
+- &mcbsp5_ick,
+- &mcbsp5_fck,
+- &mcspi1_ick,
+- &mcspi1_fck,
+- &mcspi2_ick,
+- &mcspi2_fck,
+- &mcspi3_ick,
+- &mcspi3_fck,
+- &uart1_ick,
+- &uart1_fck,
+- &uart2_ick,
+- &uart2_fck,
+- &uart3_ick,
+- &uart3_fck,
+- &gpios_ick,
+- &gpios_fck,
+- &mpu_wdt_ick,
+- &mpu_wdt_fck,
+- &sync_32k_ick,
+- &wdt1_ick,
+- &omapctrl_ick,
+- &icr_ick,
+- &cam_fck,
+- &cam_ick,
+- &mailboxes_ick,
+- &wdt4_ick,
+- &wdt4_fck,
+- &wdt3_ick,
+- &wdt3_fck,
+- &mspro_ick,
+- &mspro_fck,
+- &mmc_ick,
+- &mmc_fck,
+- &fac_ick,
+- &fac_fck,
+- &eac_ick,
+- &eac_fck,
+- &hdq_ick,
+- &hdq_fck,
+- &i2c1_ick,
+- &i2c1_fck,
+- &i2chs1_fck,
+- &i2c2_ick,
+- &i2c2_fck,
+- &i2chs2_fck,
+- &vlynq_ick,
+- &vlynq_fck,
+- &sdrc_ick,
+- &des_ick,
+- &sha_ick,
+- &rng_ick,
+- &aes_ick,
+- &pka_ick,
+- &usb_fck,
+- &usbhs_ick,
+- &mmchs1_ick,
+- &mmchs1_fck,
+- &mmchs2_ick,
+- &mmchs2_fck,
+- &gpio5_ick,
+- &gpio5_fck,
+- &mdm_intc_ick,
+- &mmchsdb1_fck,
+- &mmchsdb2_fck,
+-};
+
+ #endif
+diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c
+new file mode 100644
+index 0000000..ece32d8
+--- /dev/null
++++ b/arch/arm/mach-omap2/clock24xx.c
+@@ -0,0 +1,539 @@
++/*
++ * linux/arch/arm/mach-omap2/clock.c
++ *
++ * Copyright (C) 2005-2008 Texas Instruments, Inc.
++ * Copyright (C) 2004-2008 Nokia Corporation
++ *
++ * Contacts:
++ * Richard Woodruff <r-woodruff2 at ti.com>
++ * Paul Walmsley
++ *
++ * Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
++ * Gordon McNutt and RidgeRun, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#undef DEBUG
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/device.h>
++#include <linux/list.h>
++#include <linux/errno.h>
++#include <linux/delay.h>
++#include <linux/clk.h>
++
++#include <linux/io.h>
++#include <linux/cpufreq.h>
++
++#include <asm/arch/clock.h>
++#include <asm/arch/sram.h>
++#include <asm/div64.h>
++#include <asm/bitops.h>
++
++#include "memory.h"
++#include "clock.h"
++#include "clock24xx.h"
++#include "prm.h"
++#include "prm-regbits-24xx.h"
++#include "cm.h"
++#include "cm-regbits-24xx.h"
++
++/* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */
++#define EN_APLL_STOPPED 0
++#define EN_APLL_LOCKED 3
++
++/* CM_CLKSEL1_PLL.APLLS_CLKIN options (24XX) */
++#define APLLS_CLKIN_19_2MHZ 0
++#define APLLS_CLKIN_13MHZ 2
++#define APLLS_CLKIN_12MHZ 3
++
++/* #define DOWN_VARIABLE_DPLL 1 */ /* Experimental */
++
++static struct prcm_config *curr_prcm_set;
++static struct clk *vclk;
++static struct clk *sclk;
++
++/*-------------------------------------------------------------------------
++ * Omap24xx specific clock functions
++ *-------------------------------------------------------------------------*/
++
++/* This actually returns the rate of core_ck, not dpll_ck. */
++static u32 omap2_get_dpll_rate_24xx(struct clk *tclk)
++{
++ long long dpll_clk;
++ u8 amult;
++
++ dpll_clk = omap2_get_dpll_rate(tclk);
++
++ amult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
++ amult &= OMAP24XX_CORE_CLK_SRC_MASK;
++ dpll_clk *= amult;
++
++ return dpll_clk;
++}
++
++static int omap2_enable_osc_ck(struct clk *clk)
++{
++ u32 pcc;
++
++ pcc = __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL);
++
++ __raw_writel(pcc & ~OMAP_AUTOEXTCLKMODE_MASK,
++ OMAP24XX_PRCM_CLKSRC_CTRL);
++
++ return 0;
++}
++
++static void omap2_disable_osc_ck(struct clk *clk)
++{
++ u32 pcc;
++
++ pcc = __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL);
++
++ __raw_writel(pcc | OMAP_AUTOEXTCLKMODE_MASK,
++ OMAP24XX_PRCM_CLKSRC_CTRL);
++}
++
++#ifdef OLD_CK
++/* Recalculate SYST_CLK */
++static void omap2_sys_clk_recalc(struct clk * clk)
++{
++ u32 div = PRCM_CLKSRC_CTRL;
++ div &= (1 << 7) | (1 << 6); /* Test if ext clk divided by 1 or 2 */
++ div >>= clk->rate_offset;
++ clk->rate = (clk->parent->rate / div);
++ propagate_rate(clk);
++}
++#endif /* OLD_CK */
++
++/* Enable an APLL if off */
++static int omap2_clk_fixed_enable(struct clk *clk)
++{
++ u32 cval, apll_mask;
++
++ apll_mask = EN_APLL_LOCKED << clk->enable_bit;
++
++ cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN);
++
++ if ((cval & apll_mask) == apll_mask)
++ return 0; /* apll already enabled */
++
++ cval &= ~apll_mask;
++ cval |= apll_mask;
++ cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
++
++ if (clk == &apll96_ck)
++ cval = OMAP24XX_ST_96M_APLL;
++ else if (clk == &apll54_ck)
++ cval = OMAP24XX_ST_54M_APLL;
++
++ omap2_wait_clock_ready(OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), cval,
++ clk->name);
++
++ /*
++ * REVISIT: Should we return an error code if omap2_wait_clock_ready()
++ * fails?
++ */
++ return 0;
++}
++
++/* Stop APLL */
++static void omap2_clk_fixed_disable(struct clk *clk)
++{
++ u32 cval;
++
++ cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN);
++ cval &= ~(EN_APLL_LOCKED << clk->enable_bit);
++ cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
++}
++
++/*
++ * Uses the current prcm set to tell if a rate is valid.
++ * You can go slower, but not faster within a given rate set.
++ */
++static u32 omap2_dpll_round_rate(unsigned long target_rate)
++{
++ u32 high, low, core_clk_src;
++
++ core_clk_src = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
++ core_clk_src &= OMAP24XX_CORE_CLK_SRC_MASK;
++
++ if (core_clk_src == CORE_CLK_SRC_DPLL) { /* DPLL clockout */
++ high = curr_prcm_set->dpll_speed * 2;
++ low = curr_prcm_set->dpll_speed;
++ } else { /* DPLL clockout x 2 */
++ high = curr_prcm_set->dpll_speed;
++ low = curr_prcm_set->dpll_speed / 2;
++ }
++
++#ifdef DOWN_VARIABLE_DPLL
++ if (target_rate > high)
++ return high;
++ else
++ return target_rate;
++#else
++ if (target_rate > low)
++ return high;
++ else
++ return low;
++#endif
++
++}
++
++static void omap2_dpll_recalc(struct clk *clk)
++{
++ clk->rate = omap2_get_dpll_rate_24xx(clk);
++
++ propagate_rate(clk);
++}
++
++static int omap2_reprogram_dpll(struct clk *clk, unsigned long rate)
++{
++ u32 cur_rate, low, mult, div, valid_rate, done_rate;
++ u32 bypass = 0;
++ struct prcm_config tmpset;
++ const struct dpll_data *dd;
++ unsigned long flags;
++ int ret = -EINVAL;
++
++ local_irq_save(flags);
++ cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck);
++ mult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
++ mult &= OMAP24XX_CORE_CLK_SRC_MASK;
++
++ if ((rate == (cur_rate / 2)) && (mult == 2)) {
++ omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1);
++ } else if ((rate == (cur_rate * 2)) && (mult == 1)) {
++ omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
++ } else if (rate != cur_rate) {
++ valid_rate = omap2_dpll_round_rate(rate);
++ if (valid_rate != rate)
++ goto dpll_exit;
++
++ if (mult == 1)
++ low = curr_prcm_set->dpll_speed;
++ else
++ low = curr_prcm_set->dpll_speed / 2;
++
++ dd = clk->dpll_data;
++ if (!dd)
++ goto dpll_exit;
++
++ tmpset.cm_clksel1_pll = __raw_readl(dd->mult_div1_reg);
++ tmpset.cm_clksel1_pll &= ~(dd->mult_mask |
++ dd->div1_mask);
++ div = ((curr_prcm_set->xtal_speed / 1000000) - 1);
++ tmpset.cm_clksel2_pll = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
++ tmpset.cm_clksel2_pll &= ~OMAP24XX_CORE_CLK_SRC_MASK;
++ if (rate > low) {
++ tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL_X2;
++ mult = ((rate / 2) / 1000000);
++ done_rate = CORE_CLK_SRC_DPLL_X2;
++ } else {
++ tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL;
++ mult = (rate / 1000000);
++ done_rate = CORE_CLK_SRC_DPLL;
++ }
++ tmpset.cm_clksel1_pll |= (div << __ffs(dd->mult_mask));
++ tmpset.cm_clksel1_pll |= (mult << __ffs(dd->div1_mask));
++
++ /* Worst case */
++ tmpset.base_sdrc_rfr = SDRC_RFR_CTRL_BYPASS;
++
++ if (rate == curr_prcm_set->xtal_speed) /* If asking for 1-1 */
++ bypass = 1;
++
++ omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1); /* For init_mem */
++
++ /* Force dll lock mode */
++ omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr,
++ bypass);
++
++ /* Errata: ret dll entry state */
++ omap2_init_memory_params(omap2_dll_force_needed());
++ omap2_reprogram_sdrc(done_rate, 0);
++ }
++ omap2_dpll_recalc(&dpll_ck);
++ ret = 0;
++
++dpll_exit:
++ local_irq_restore(flags);
++ return(ret);
++}
++
++/**
++ * omap2_table_mpu_recalc - just return the MPU speed
++ * @clk: virt_prcm_set struct clk
++ *
++ * Set virt_prcm_set's rate to the mpu_speed field of the current PRCM set.
++ */
++static void omap2_table_mpu_recalc(struct clk *clk)
++{
++ clk->rate = curr_prcm_set->mpu_speed;
++}
++
++/*
++ * Look for a rate equal or less than the target rate given a configuration set.
++ *
++ * What's not entirely clear is "which" field represents the key field.
++ * Some might argue L3-DDR, others ARM, others IVA. This code is simple and
++ * just uses the ARM rates.
++ */
++static long omap2_round_to_table_rate(struct clk *clk, unsigned long rate)
++{
++ struct prcm_config *ptr;
++ long highest_rate;
++
++ if (clk != &virt_prcm_set)
++ return -EINVAL;
++
++ highest_rate = -EINVAL;
++
++ for (ptr = rate_table; ptr->mpu_speed; ptr++) {
++ if (!(ptr->flags & cpu_mask))
++ continue;
++ if (ptr->xtal_speed != sys_ck.rate)
++ continue;
++
++ highest_rate = ptr->mpu_speed;
++
++ /* Can check only after xtal frequency check */
++ if (ptr->mpu_speed <= rate)
++ break;
++ }
++ return highest_rate;
++}
++
++/* Sets basic clocks based on the specified rate */
++static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
++{
++ u32 cur_rate, done_rate, bypass = 0, tmp;
++ struct prcm_config *prcm;
++ unsigned long found_speed = 0;
++ unsigned long flags;
++
++ if (clk != &virt_prcm_set)
++ return -EINVAL;
++
++ for (prcm = rate_table; prcm->mpu_speed; prcm++) {
++ if (!(prcm->flags & cpu_mask))
++ continue;
++
++ if (prcm->xtal_speed != sys_ck.rate)
++ continue;
++
++ if (prcm->mpu_speed <= rate) {
++ found_speed = prcm->mpu_speed;
++ break;
++ }
++ }
++
++ if (!found_speed) {
++ printk(KERN_INFO "Could not set MPU rate to %luMHz\n",
++ rate / 1000000);
++ return -EINVAL;
++ }
++
++ curr_prcm_set = prcm;
++ cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck);
++
++ if (prcm->dpll_speed == cur_rate / 2) {
++ omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1);
++ } else if (prcm->dpll_speed == cur_rate * 2) {
++ omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
++ } else if (prcm->dpll_speed != cur_rate) {
++ local_irq_save(flags);
++
++ if (prcm->dpll_speed == prcm->xtal_speed)
++ bypass = 1;
++
++ if ((prcm->cm_clksel2_pll & OMAP24XX_CORE_CLK_SRC_MASK) ==
++ CORE_CLK_SRC_DPLL_X2)
++ done_rate = CORE_CLK_SRC_DPLL_X2;
++ else
++ done_rate = CORE_CLK_SRC_DPLL;
++
++ /* MPU divider */
++ cm_write_mod_reg(prcm->cm_clksel_mpu, MPU_MOD, CM_CLKSEL);
++
++ /* dsp + iva1 div(2420), iva2.1(2430) */
++ cm_write_mod_reg(prcm->cm_clksel_dsp,
++ OMAP24XX_DSP_MOD, CM_CLKSEL);
++
++ cm_write_mod_reg(prcm->cm_clksel_gfx, GFX_MOD, CM_CLKSEL);
++
++ /* Major subsystem dividers */
++ tmp = cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) & OMAP24XX_CLKSEL_DSS2_MASK;
++ cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD, CM_CLKSEL1);
++ if (cpu_is_omap2430())
++ cm_write_mod_reg(prcm->cm_clksel_mdm,
++ OMAP2430_MDM_MOD, CM_CLKSEL);
++
++ /* x2 to enter init_mem */
++ omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
++
++ omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr,
++ bypass);
++
++ omap2_init_memory_params(omap2_dll_force_needed());
++ omap2_reprogram_sdrc(done_rate, 0);
++
++ local_irq_restore(flags);
++ }
++ omap2_dpll_recalc(&dpll_ck);
++
++ return 0;
++}
++
++static struct clk_functions omap2_clk_functions = {
++ .clk_enable = omap2_clk_enable,
++ .clk_disable = omap2_clk_disable,
++ .clk_round_rate = omap2_clk_round_rate,
++ .clk_set_rate = omap2_clk_set_rate,
++ .clk_set_parent = omap2_clk_set_parent,
++ .clk_disable_unused = omap2_clk_disable_unused,
++};
++
++static u32 omap2_get_apll_clkin(void)
++{
++ u32 aplls, sclk = 0;
++
++ aplls = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1);
++ aplls &= OMAP24XX_APLLS_CLKIN_MASK;
++ aplls >>= OMAP24XX_APLLS_CLKIN_SHIFT;
++
++ if (aplls == APLLS_CLKIN_19_2MHZ)
++ sclk = 19200000;
++ else if (aplls == APLLS_CLKIN_13MHZ)
++ sclk = 13000000;
++ else if (aplls == APLLS_CLKIN_12MHZ)
++ sclk = 12000000;
++
++ return sclk;
++}
++
++static u32 omap2_get_sysclkdiv(void)
++{
++ u32 div;
++
++ div = __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL);
++ div &= OMAP_SYSCLKDIV_MASK;
++ div >>= OMAP_SYSCLKDIV_SHIFT;
++
++ return div;
++}
++
++static void omap2_osc_clk_recalc(struct clk *clk)
++{
++ clk->rate = omap2_get_apll_clkin() * omap2_get_sysclkdiv();
++ propagate_rate(clk);
++}
++
++static void omap2_sys_clk_recalc(struct clk *clk)
++{
++ clk->rate = clk->parent->rate / omap2_get_sysclkdiv();
++ propagate_rate(clk);
++}
++
++/*
++ * Set clocks for bypass mode for reboot to work.
++ */
++void omap2_clk_prepare_for_reboot(void)
++{
++ u32 rate;
++
++ if (vclk == NULL || sclk == NULL)
++ return;
++
++ rate = clk_get_rate(sclk);
++ clk_set_rate(vclk, rate);
++}
++
++/*
++ * Switch the MPU rate if specified on cmdline.
++ * We cannot do this early until cmdline is parsed.
++ */
++static int __init omap2_clk_arch_init(void)
++{
++ if (!mpurate)
++ return -EINVAL;
++
++ if (omap2_select_table_rate(&virt_prcm_set, mpurate))
++ printk(KERN_ERR "Could not find matching MPU rate\n");
++
++ recalculate_root_clocks();
++
++ printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL/MPU): "
++ "%ld.%01ld/%ld/%ld MHz\n",
++ (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
++ (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
++
++ return 0;
++}
++arch_initcall(omap2_clk_arch_init);
++
++int __init omap2_clk_init(void)
++{
++ struct prcm_config *prcm;
++ struct clk **clkp;
++ u32 clkrate;
++
++ if (cpu_is_omap242x())
++ cpu_mask = RATE_IN_242X;
++ else if (cpu_is_omap2430())
++ cpu_mask = RATE_IN_243X;
++
++ clk_init(&omap2_clk_functions);
++
++ omap2_osc_clk_recalc(&osc_ck);
++ omap2_sys_clk_recalc(&sys_ck);
++
++ for (clkp = onchip_24xx_clks;
++ clkp < onchip_24xx_clks + ARRAY_SIZE(onchip_24xx_clks);
++ clkp++) {
++
++ if ((*clkp)->flags & CLOCK_IN_OMAP242X && cpu_is_omap2420()) {
++ clk_register(*clkp);
++ continue;
++ }
++
++ if ((*clkp)->flags & CLOCK_IN_OMAP243X && cpu_is_omap2430()) {
++ clk_register(*clkp);
++ continue;
++ }
++ }
++
++ /* Check the MPU rate set by bootloader */
++ clkrate = omap2_get_dpll_rate_24xx(&dpll_ck);
++ for (prcm = rate_table; prcm->mpu_speed; prcm++) {
++ if (!(prcm->flags & cpu_mask))
++ continue;
++ if (prcm->xtal_speed != sys_ck.rate)
++ continue;
++ if (prcm->dpll_speed <= clkrate)
++ break;
++ }
++ curr_prcm_set = prcm;
++
++ recalculate_root_clocks();
++
++ printk(KERN_INFO "Clocking rate (Crystal/DPLL/MPU): "
++ "%ld.%01ld/%ld/%ld MHz\n",
++ (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10,
++ (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ;
++
++ /*
++ * Only enable those clocks we will need, let the drivers
++ * enable other clocks as necessary
++ */
++ clk_enable_init_clocks();
++
++ /* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */
++ vclk = clk_get(NULL, "virt_prcm_set");
++ sclk = clk_get(NULL, "sys_ck");
++
++ return 0;
++}
+diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h
+new file mode 100644
+index 0000000..88081ed
+--- /dev/null
++++ b/arch/arm/mach-omap2/clock24xx.h
+@@ -0,0 +1,2643 @@
++/*
++ * linux/arch/arm/mach-omap2/clock24xx.h
++ *
++ * Copyright (C) 2005-2008 Texas Instruments, Inc.
++ * Copyright (C) 2004-2008 Nokia Corporation
++ *
++ * Contacts:
++ * Richard Woodruff <r-woodruff2 at ti.com>
++ * Paul Walmsley
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK24XX_H
++#define __ARCH_ARM_MACH_OMAP2_CLOCK24XX_H
++
++#include "clock.h"
++
++#include "prm.h"
++#include "cm.h"
++#include "prm-regbits-24xx.h"
++#include "cm-regbits-24xx.h"
++#include "sdrc.h"
++
++static void omap2_table_mpu_recalc(struct clk *clk);
++static int omap2_select_table_rate(struct clk *clk, unsigned long rate);
++static long omap2_round_to_table_rate(struct clk *clk, unsigned long rate);
++static void omap2_sys_clk_recalc(struct clk *clk);
++static void omap2_osc_clk_recalc(struct clk *clk);
++static void omap2_sys_clk_recalc(struct clk *clk);
++static void omap2_dpll_recalc(struct clk *clk);
++static int omap2_clk_fixed_enable(struct clk *clk);
++static void omap2_clk_fixed_disable(struct clk *clk);
++static int omap2_enable_osc_ck(struct clk *clk);
++static void omap2_disable_osc_ck(struct clk *clk);
++static int omap2_reprogram_dpll(struct clk *clk, unsigned long rate);
++
++/* Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated.
++ * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,CM_CLKSEL_DSP
++ * CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL CM_CLKSEL2_PLL, CM_CLKSEL_MDM
++ */
++struct prcm_config {
++ unsigned long xtal_speed; /* crystal rate */
++ unsigned long dpll_speed; /* dpll: out*xtal*M/(N-1)table_recalc */
++ unsigned long mpu_speed; /* speed of MPU */
++ unsigned long cm_clksel_mpu; /* mpu divider */
++ unsigned long cm_clksel_dsp; /* dsp+iva1 div(2420), iva2.1(2430) */
++ unsigned long cm_clksel_gfx; /* gfx dividers */
++ unsigned long cm_clksel1_core; /* major subsystem dividers */
++ unsigned long cm_clksel1_pll; /* m,n */
++ unsigned long cm_clksel2_pll; /* dpllx1 or x2 out */
++ unsigned long cm_clksel_mdm; /* modem dividers 2430 only */
++ unsigned long base_sdrc_rfr; /* base refresh timing for a set */
++ unsigned char flags;
++};
++
++/*
++ * The OMAP2 processor can be run at several discrete 'PRCM configurations'.
++ * These configurations are characterized by voltage and speed for clocks.
++ * The device is only validated for certain combinations. One way to express
++ * these combinations is via the 'ratio's' which the clocks operate with
++ * respect to each other. These ratio sets are for a given voltage/DPLL
++ * setting. All configurations can be described by a DPLL setting and a ratio
++ * There are 3 ratio sets for the 2430 and X ratio sets for 2420.
++ *
++ * 2430 differs from 2420 in that there are no more phase synchronizers used.
++ * They both have a slightly different clock domain setup. 2420(iva1,dsp) vs
++ * 2430 (iva2.1, NOdsp, mdm)
++ */
++
++/* Core fields for cm_clksel, not ratio governed */
++#define RX_CLKSEL_DSS1 (0x10 << 8)
++#define RX_CLKSEL_DSS2 (0x0 << 13)
++#define RX_CLKSEL_SSI (0x5 << 20)
++
++/*-------------------------------------------------------------------------
++ * Voltage/DPLL ratios
++ *-------------------------------------------------------------------------*/
++
++/* 2430 Ratio's, 2430-Ratio Config 1 */
++#define R1_CLKSEL_L3 (4 << 0)
++#define R1_CLKSEL_L4 (2 << 5)
++#define R1_CLKSEL_USB (4 << 25)
++#define R1_CM_CLKSEL1_CORE_VAL R1_CLKSEL_USB | RX_CLKSEL_SSI | \
++ RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
++ R1_CLKSEL_L4 | R1_CLKSEL_L3
++#define R1_CLKSEL_MPU (2 << 0)
++#define R1_CM_CLKSEL_MPU_VAL R1_CLKSEL_MPU
++#define R1_CLKSEL_DSP (2 << 0)
++#define R1_CLKSEL_DSP_IF (2 << 5)
++#define R1_CM_CLKSEL_DSP_VAL R1_CLKSEL_DSP | R1_CLKSEL_DSP_IF
++#define R1_CLKSEL_GFX (2 << 0)
++#define R1_CM_CLKSEL_GFX_VAL R1_CLKSEL_GFX
++#define R1_CLKSEL_MDM (4 << 0)
++#define R1_CM_CLKSEL_MDM_VAL R1_CLKSEL_MDM
++
++/* 2430-Ratio Config 2 */
++#define R2_CLKSEL_L3 (6 << 0)
++#define R2_CLKSEL_L4 (2 << 5)
++#define R2_CLKSEL_USB (2 << 25)
++#define R2_CM_CLKSEL1_CORE_VAL R2_CLKSEL_USB | RX_CLKSEL_SSI | \
++ RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
++ R2_CLKSEL_L4 | R2_CLKSEL_L3
++#define R2_CLKSEL_MPU (2 << 0)
++#define R2_CM_CLKSEL_MPU_VAL R2_CLKSEL_MPU
++#define R2_CLKSEL_DSP (2 << 0)
++#define R2_CLKSEL_DSP_IF (3 << 5)
++#define R2_CM_CLKSEL_DSP_VAL R2_CLKSEL_DSP | R2_CLKSEL_DSP_IF
++#define R2_CLKSEL_GFX (2 << 0)
++#define R2_CM_CLKSEL_GFX_VAL R2_CLKSEL_GFX
++#define R2_CLKSEL_MDM (6 << 0)
++#define R2_CM_CLKSEL_MDM_VAL R2_CLKSEL_MDM
++
++/* 2430-Ratio Bootm (BYPASS) */
++#define RB_CLKSEL_L3 (1 << 0)
++#define RB_CLKSEL_L4 (1 << 5)
++#define RB_CLKSEL_USB (1 << 25)
++#define RB_CM_CLKSEL1_CORE_VAL RB_CLKSEL_USB | RX_CLKSEL_SSI | \
++ RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
++ RB_CLKSEL_L4 | RB_CLKSEL_L3
++#define RB_CLKSEL_MPU (1 << 0)
++#define RB_CM_CLKSEL_MPU_VAL RB_CLKSEL_MPU
++#define RB_CLKSEL_DSP (1 << 0)
++#define RB_CLKSEL_DSP_IF (1 << 5)
++#define RB_CM_CLKSEL_DSP_VAL RB_CLKSEL_DSP | RB_CLKSEL_DSP_IF
++#define RB_CLKSEL_GFX (1 << 0)
++#define RB_CM_CLKSEL_GFX_VAL RB_CLKSEL_GFX
++#define RB_CLKSEL_MDM (1 << 0)
++#define RB_CM_CLKSEL_MDM_VAL RB_CLKSEL_MDM
++
++/* 2420 Ratio Equivalents */
++#define RXX_CLKSEL_VLYNQ (0x12 << 15)
++#define RXX_CLKSEL_SSI (0x8 << 20)
++
++/* 2420-PRCM III 532MHz core */
++#define RIII_CLKSEL_L3 (4 << 0) /* 133MHz */
++#define RIII_CLKSEL_L4 (2 << 5) /* 66.5MHz */
++#define RIII_CLKSEL_USB (4 << 25) /* 33.25MHz */
++#define RIII_CM_CLKSEL1_CORE_VAL RIII_CLKSEL_USB | RXX_CLKSEL_SSI | \
++ RXX_CLKSEL_VLYNQ | RX_CLKSEL_DSS2 | \
++ RX_CLKSEL_DSS1 | RIII_CLKSEL_L4 | \
++ RIII_CLKSEL_L3
++#define RIII_CLKSEL_MPU (2 << 0) /* 266MHz */
++#define RIII_CM_CLKSEL_MPU_VAL RIII_CLKSEL_MPU
++#define RIII_CLKSEL_DSP (3 << 0) /* c5x - 177.3MHz */
++#define RIII_CLKSEL_DSP_IF (2 << 5) /* c5x - 88.67MHz */
++#define RIII_SYNC_DSP (1 << 7) /* Enable sync */
++#define RIII_CLKSEL_IVA (6 << 8) /* iva1 - 88.67MHz */
++#define RIII_SYNC_IVA (1 << 13) /* Enable sync */
++#define RIII_CM_CLKSEL_DSP_VAL RIII_SYNC_IVA | RIII_CLKSEL_IVA | \
++ RIII_SYNC_DSP | RIII_CLKSEL_DSP_IF | \
++ RIII_CLKSEL_DSP
++#define RIII_CLKSEL_GFX (2 << 0) /* 66.5MHz */
++#define RIII_CM_CLKSEL_GFX_VAL RIII_CLKSEL_GFX
++
++/* 2420-PRCM II 600MHz core */
++#define RII_CLKSEL_L3 (6 << 0) /* 100MHz */
++#define RII_CLKSEL_L4 (2 << 5) /* 50MHz */
++#define RII_CLKSEL_USB (2 << 25) /* 50MHz */
++#define RII_CM_CLKSEL1_CORE_VAL RII_CLKSEL_USB | \
++ RXX_CLKSEL_SSI | RXX_CLKSEL_VLYNQ | \
++ RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
++ RII_CLKSEL_L4 | RII_CLKSEL_L3
++#define RII_CLKSEL_MPU (2 << 0) /* 300MHz */
++#define RII_CM_CLKSEL_MPU_VAL RII_CLKSEL_MPU
++#define RII_CLKSEL_DSP (3 << 0) /* c5x - 200MHz */
++#define RII_CLKSEL_DSP_IF (2 << 5) /* c5x - 100MHz */
++#define RII_SYNC_DSP (0 << 7) /* Bypass sync */
++#define RII_CLKSEL_IVA (3 << 8) /* iva1 - 200MHz */
++#define RII_SYNC_IVA (0 << 13) /* Bypass sync */
++#define RII_CM_CLKSEL_DSP_VAL RII_SYNC_IVA | RII_CLKSEL_IVA | \
++ RII_SYNC_DSP | RII_CLKSEL_DSP_IF | \
++ RII_CLKSEL_DSP
++#define RII_CLKSEL_GFX (2 << 0) /* 50MHz */
++#define RII_CM_CLKSEL_GFX_VAL RII_CLKSEL_GFX
++
++/* 2420-PRCM I 660MHz core */
++#define RI_CLKSEL_L3 (4 << 0) /* 165MHz */
++#define RI_CLKSEL_L4 (2 << 5) /* 82.5MHz */
++#define RI_CLKSEL_USB (4 << 25) /* 41.25MHz */
++#define RI_CM_CLKSEL1_CORE_VAL RI_CLKSEL_USB | \
++ RXX_CLKSEL_SSI | RXX_CLKSEL_VLYNQ | \
++ RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
++ RI_CLKSEL_L4 | RI_CLKSEL_L3
++#define RI_CLKSEL_MPU (2 << 0) /* 330MHz */
++#define RI_CM_CLKSEL_MPU_VAL RI_CLKSEL_MPU
++#define RI_CLKSEL_DSP (3 << 0) /* c5x - 220MHz */
++#define RI_CLKSEL_DSP_IF (2 << 5) /* c5x - 110MHz */
++#define RI_SYNC_DSP (1 << 7) /* Activate sync */
++#define RI_CLKSEL_IVA (4 << 8) /* iva1 - 165MHz */
++#define RI_SYNC_IVA (0 << 13) /* Bypass sync */
++#define RI_CM_CLKSEL_DSP_VAL RI_SYNC_IVA | RI_CLKSEL_IVA | \
++ RI_SYNC_DSP | RI_CLKSEL_DSP_IF | \
++ RI_CLKSEL_DSP
++#define RI_CLKSEL_GFX (1 << 0) /* 165MHz */
++#define RI_CM_CLKSEL_GFX_VAL RI_CLKSEL_GFX
++
++/* 2420-PRCM VII (boot) */
++#define RVII_CLKSEL_L3 (1 << 0)
++#define RVII_CLKSEL_L4 (1 << 5)
++#define RVII_CLKSEL_DSS1 (1 << 8)
++#define RVII_CLKSEL_DSS2 (0 << 13)
++#define RVII_CLKSEL_VLYNQ (1 << 15)
++#define RVII_CLKSEL_SSI (1 << 20)
++#define RVII_CLKSEL_USB (1 << 25)
++
++#define RVII_CM_CLKSEL1_CORE_VAL RVII_CLKSEL_USB | RVII_CLKSEL_SSI | \
++ RVII_CLKSEL_VLYNQ | RVII_CLKSEL_DSS2 | \
++ RVII_CLKSEL_DSS1 | RVII_CLKSEL_L4 | RVII_CLKSEL_L3
++
++#define RVII_CLKSEL_MPU (1 << 0) /* all divide by 1 */
++#define RVII_CM_CLKSEL_MPU_VAL RVII_CLKSEL_MPU
++
++#define RVII_CLKSEL_DSP (1 << 0)
++#define RVII_CLKSEL_DSP_IF (1 << 5)
++#define RVII_SYNC_DSP (0 << 7)
++#define RVII_CLKSEL_IVA (1 << 8)
++#define RVII_SYNC_IVA (0 << 13)
++#define RVII_CM_CLKSEL_DSP_VAL RVII_SYNC_IVA | RVII_CLKSEL_IVA | RVII_SYNC_DSP | \
++ RVII_CLKSEL_DSP_IF | RVII_CLKSEL_DSP
++
++#define RVII_CLKSEL_GFX (1 << 0)
++#define RVII_CM_CLKSEL_GFX_VAL RVII_CLKSEL_GFX
++
++/*-------------------------------------------------------------------------
++ * 2430 Target modes: Along with each configuration the CPU has several
++ * modes which goes along with them. Modes mainly are the addition of
++ * describe DPLL combinations to go along with a ratio.
++ *-------------------------------------------------------------------------*/
++
++/* Hardware governed */
++#define MX_48M_SRC (0 << 3)
++#define MX_54M_SRC (0 << 5)
++#define MX_APLLS_CLIKIN_12 (3 << 23)
++#define MX_APLLS_CLIKIN_13 (2 << 23)
++#define MX_APLLS_CLIKIN_19_2 (0 << 23)
++
++/*
++ * 2430 - standalone, 2*ref*M/(n+1), M/N is for exactness not relock speed
++ * #5a (ratio1) baseport-target, target DPLL = 266*2 = 532MHz
++ */
++#define M5A_DPLL_MULT_12 (133 << 12)
++#define M5A_DPLL_DIV_12 (5 << 8)
++#define M5A_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \
++ M5A_DPLL_DIV_12 | M5A_DPLL_MULT_12 | \
++ MX_APLLS_CLIKIN_12
++#define M5A_DPLL_MULT_13 (61 << 12)
++#define M5A_DPLL_DIV_13 (2 << 8)
++#define M5A_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | \
++ M5A_DPLL_DIV_13 | M5A_DPLL_MULT_13 | \
++ MX_APLLS_CLIKIN_13
++#define M5A_DPLL_MULT_19 (55 << 12)
++#define M5A_DPLL_DIV_19 (3 << 8)
++#define M5A_CM_CLKSEL1_PLL_19_VAL MX_48M_SRC | MX_54M_SRC | \
++ M5A_DPLL_DIV_19 | M5A_DPLL_MULT_19 | \
++ MX_APLLS_CLIKIN_19_2
++/* #5b (ratio1) target DPLL = 200*2 = 400MHz */
++#define M5B_DPLL_MULT_12 (50 << 12)
++#define M5B_DPLL_DIV_12 (2 << 8)
++#define M5B_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \
++ M5B_DPLL_DIV_12 | M5B_DPLL_MULT_12 | \
++ MX_APLLS_CLIKIN_12
++#define M5B_DPLL_MULT_13 (200 << 12)
++#define M5B_DPLL_DIV_13 (12 << 8)
++
++#define M5B_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | \
++ M5B_DPLL_DIV_13 | M5B_DPLL_MULT_13 | \
++ MX_APLLS_CLIKIN_13
++#define M5B_DPLL_MULT_19 (125 << 12)
++#define M5B_DPLL_DIV_19 (31 << 8)
++#define M5B_CM_CLKSEL1_PLL_19_VAL MX_48M_SRC | MX_54M_SRC | \
++ M5B_DPLL_DIV_19 | M5B_DPLL_MULT_19 | \
++ MX_APLLS_CLIKIN_19_2
++/*
++ * #4 (ratio2), DPLL = 399*2 = 798MHz, L3=133MHz
++ */
++#define M4_DPLL_MULT_12 (133 << 12)
++#define M4_DPLL_DIV_12 (3 << 8)
++#define M4_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \
++ M4_DPLL_DIV_12 | M4_DPLL_MULT_12 | \
++ MX_APLLS_CLIKIN_12
++
++#define M4_DPLL_MULT_13 (399 << 12)
++#define M4_DPLL_DIV_13 (12 << 8)
++#define M4_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | \
++ M4_DPLL_DIV_13 | M4_DPLL_MULT_13 | \
++ MX_APLLS_CLIKIN_13
++
++#define M4_DPLL_MULT_19 (145 << 12)
++#define M4_DPLL_DIV_19 (6 << 8)
++#define M4_CM_CLKSEL1_PLL_19_VAL MX_48M_SRC | MX_54M_SRC | \
++ M4_DPLL_DIV_19 | M4_DPLL_MULT_19 | \
++ MX_APLLS_CLIKIN_19_2
++
++/*
++ * #3 (ratio2) baseport-target, target DPLL = 330*2 = 660MHz
++ */
++#define M3_DPLL_MULT_12 (55 << 12)
++#define M3_DPLL_DIV_12 (1 << 8)
++#define M3_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \
++ M3_DPLL_DIV_12 | M3_DPLL_MULT_12 | \
++ MX_APLLS_CLIKIN_12
++#define M3_DPLL_MULT_13 (76 << 12)
++#define M3_DPLL_DIV_13 (2 << 8)
++#define M3_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | \
++ M3_DPLL_DIV_13 | M3_DPLL_MULT_13 | \
++ MX_APLLS_CLIKIN_13
++#define M3_DPLL_MULT_19 (17 << 12)
++#define M3_DPLL_DIV_19 (0 << 8)
++#define M3_CM_CLKSEL1_PLL_19_VAL MX_48M_SRC | MX_54M_SRC | \
++ M3_DPLL_DIV_19 | M3_DPLL_MULT_19 | \
++ MX_APLLS_CLIKIN_19_2
++
++/*
++ * #2 (ratio1) DPLL = 330*2 = 660MHz, L3=165MHz
++ */
++#define M2_DPLL_MULT_12 (55 << 12)
++#define M2_DPLL_DIV_12 (1 << 8)
++#define M2_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \
++ M2_DPLL_DIV_12 | M2_DPLL_MULT_12 | \
++ MX_APLLS_CLIKIN_12
++
++/* Speed changes - Used 658.7MHz instead of 660MHz for LP-Refresh M=76 N=2,
++ * relock time issue */
++/* Core frequency changed from 330/165 to 329/164 MHz*/
++#define M2_DPLL_MULT_13 (76 << 12)
++#define M2_DPLL_DIV_13 (2 << 8)
++#define M2_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | \
++ M2_DPLL_DIV_13 | M2_DPLL_MULT_13 | \
++ MX_APLLS_CLIKIN_13
++
++#define M2_DPLL_MULT_19 (17 << 12)
++#define M2_DPLL_DIV_19 (0 << 8)
++#define M2_CM_CLKSEL1_PLL_19_VAL MX_48M_SRC | MX_54M_SRC | \
++ M2_DPLL_DIV_19 | M2_DPLL_MULT_19 | \
++ MX_APLLS_CLIKIN_19_2
++
++/* boot (boot) */
++#define MB_DPLL_MULT (1 << 12)
++#define MB_DPLL_DIV (0 << 8)
++#define MB_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | MB_DPLL_DIV |\
++ MB_DPLL_MULT | MX_APLLS_CLIKIN_12
++
++#define MB_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | MB_DPLL_DIV |\
++ MB_DPLL_MULT | MX_APLLS_CLIKIN_13
++
++#define MB_CM_CLKSEL1_PLL_19_VAL MX_48M_SRC | MX_54M_SRC | MB_DPLL_DIV |\
++ MB_DPLL_MULT | MX_APLLS_CLIKIN_19
++
++/*
++ * 2430 - chassis (sedna)
++ * 165 (ratio1) same as above #2
++ * 150 (ratio1)
++ * 133 (ratio2) same as above #4
++ * 110 (ratio2) same as above #3
++ * 104 (ratio2)
++ * boot (boot)
++ */
++
++/* PRCM I target DPLL = 2*330MHz = 660MHz */
++#define MI_DPLL_MULT_12 (55 << 12)
++#define MI_DPLL_DIV_12 (1 << 8)
++#define MI_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \
++ MI_DPLL_DIV_12 | MI_DPLL_MULT_12 | \
++ MX_APLLS_CLIKIN_12
++
++/*
++ * 2420 Equivalent - mode registers
++ * PRCM II , target DPLL = 2*300MHz = 600MHz
++ */
++#define MII_DPLL_MULT_12 (50 << 12)
++#define MII_DPLL_DIV_12 (1 << 8)
++#define MII_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \
++ MII_DPLL_DIV_12 | MII_DPLL_MULT_12 | \
++ MX_APLLS_CLIKIN_12
++#define MII_DPLL_MULT_13 (300 << 12)
++#define MII_DPLL_DIV_13 (12 << 8)
++#define MII_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | \
++ MII_DPLL_DIV_13 | MII_DPLL_MULT_13 | \
++ MX_APLLS_CLIKIN_13
++
++/* PRCM III target DPLL = 2*266 = 532MHz*/
++#define MIII_DPLL_MULT_12 (133 << 12)
++#define MIII_DPLL_DIV_12 (5 << 8)
++#define MIII_CM_CLKSEL1_PLL_12_VAL MX_48M_SRC | MX_54M_SRC | \
++ MIII_DPLL_DIV_12 | MIII_DPLL_MULT_12 | \
++ MX_APLLS_CLIKIN_12
++#define MIII_DPLL_MULT_13 (266 << 12)
++#define MIII_DPLL_DIV_13 (12 << 8)
++#define MIII_CM_CLKSEL1_PLL_13_VAL MX_48M_SRC | MX_54M_SRC | \
++ MIII_DPLL_DIV_13 | MIII_DPLL_MULT_13 | \
++ MX_APLLS_CLIKIN_13
++
++/* PRCM VII (boot bypass) */
++#define MVII_CM_CLKSEL1_PLL_12_VAL MB_CM_CLKSEL1_PLL_12_VAL
++#define MVII_CM_CLKSEL1_PLL_13_VAL MB_CM_CLKSEL1_PLL_13_VAL
++
++/* High and low operation value */
++#define MX_CLKSEL2_PLL_2x_VAL (2 << 0)
++#define MX_CLKSEL2_PLL_1x_VAL (1 << 0)
++
++/* MPU speed defines */
++#define S12M 12000000
++#define S13M 13000000
++#define S19M 19200000
++#define S26M 26000000
++#define S100M 100000000
++#define S133M 133000000
++#define S150M 150000000
++#define S164M 164000000
++#define S165M 165000000
++#define S199M 199000000
++#define S200M 200000000
++#define S266M 266000000
++#define S300M 300000000
++#define S329M 329000000
++#define S330M 330000000
++#define S399M 399000000
++#define S400M 400000000
++#define S532M 532000000
++#define S600M 600000000
++#define S658M 658000000
++#define S660M 660000000
++#define S798M 798000000
++
++/*-------------------------------------------------------------------------
++ * Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated.
++ * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,
++ * CM_CLKSEL_DSP, CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL,
++ * CM_CLKSEL2_PLL, CM_CLKSEL_MDM
++ *
++ * Filling in table based on H4 boards and 2430-SDPs variants available.
++ * There are quite a few more rates combinations which could be defined.
++ *
++ * When multiple values are defined the start up will try and choose the
++ * fastest one. If a 'fast' value is defined, then automatically, the /2
++ * one should be included as it can be used. Generally having more that
++ * one fast set does not make sense, as static timings need to be changed
++ * to change the set. The exception is the bypass setting which is
++ * availble for low power bypass.
++ *
++ * Note: This table needs to be sorted, fastest to slowest.
++ *-------------------------------------------------------------------------*/
++static struct prcm_config rate_table[] = {
++ /* PRCM I - FAST */
++ {S12M, S660M, S330M, RI_CM_CLKSEL_MPU_VAL, /* 330MHz ARM */
++ RI_CM_CLKSEL_DSP_VAL, RI_CM_CLKSEL_GFX_VAL,
++ RI_CM_CLKSEL1_CORE_VAL, MI_CM_CLKSEL1_PLL_12_VAL,
++ MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_165MHz,
++ RATE_IN_242X},
++
++ /* PRCM II - FAST */
++ {S12M, S600M, S300M, RII_CM_CLKSEL_MPU_VAL, /* 300MHz ARM */
++ RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL,
++ RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_12_VAL,
++ MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_100MHz,
++ RATE_IN_242X},
++
++ {S13M, S600M, S300M, RII_CM_CLKSEL_MPU_VAL, /* 300MHz ARM */
++ RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL,
++ RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_13_VAL,
++ MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_100MHz,
++ RATE_IN_242X},
++
++ /* PRCM III - FAST */
++ {S12M, S532M, S266M, RIII_CM_CLKSEL_MPU_VAL, /* 266MHz ARM */
++ RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL,
++ RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_12_VAL,
++ MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_133MHz,
++ RATE_IN_242X},
++
++ {S13M, S532M, S266M, RIII_CM_CLKSEL_MPU_VAL, /* 266MHz ARM */
++ RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL,
++ RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_13_VAL,
++ MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_133MHz,
++ RATE_IN_242X},
++
++ /* PRCM II - SLOW */
++ {S12M, S300M, S150M, RII_CM_CLKSEL_MPU_VAL, /* 150MHz ARM */
++ RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL,
++ RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_12_VAL,
++ MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_100MHz,
++ RATE_IN_242X},
++
++ {S13M, S300M, S150M, RII_CM_CLKSEL_MPU_VAL, /* 150MHz ARM */
++ RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL,
++ RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_13_VAL,
++ MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_100MHz,
++ RATE_IN_242X},
++
++ /* PRCM III - SLOW */
++ {S12M, S266M, S133M, RIII_CM_CLKSEL_MPU_VAL, /* 133MHz ARM */
++ RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL,
++ RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_12_VAL,
++ MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_133MHz,
++ RATE_IN_242X},
++
++ {S13M, S266M, S133M, RIII_CM_CLKSEL_MPU_VAL, /* 133MHz ARM */
++ RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL,
++ RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_13_VAL,
++ MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_133MHz,
++ RATE_IN_242X},
++
++ /* PRCM-VII (boot-bypass) */
++ {S12M, S12M, S12M, RVII_CM_CLKSEL_MPU_VAL, /* 12MHz ARM*/
++ RVII_CM_CLKSEL_DSP_VAL, RVII_CM_CLKSEL_GFX_VAL,
++ RVII_CM_CLKSEL1_CORE_VAL, MVII_CM_CLKSEL1_PLL_12_VAL,
++ MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_BYPASS,
++ RATE_IN_242X},
++
++ /* PRCM-VII (boot-bypass) */
++ {S13M, S13M, S13M, RVII_CM_CLKSEL_MPU_VAL, /* 13MHz ARM */
++ RVII_CM_CLKSEL_DSP_VAL, RVII_CM_CLKSEL_GFX_VAL,
++ RVII_CM_CLKSEL1_CORE_VAL, MVII_CM_CLKSEL1_PLL_13_VAL,
++ MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_BYPASS,
++ RATE_IN_242X},
++
++ /* PRCM #4 - ratio2 (ES2.1) - FAST */
++ {S13M, S798M, S399M, R2_CM_CLKSEL_MPU_VAL, /* 399MHz ARM */
++ R2_CM_CLKSEL_DSP_VAL, R2_CM_CLKSEL_GFX_VAL,
++ R2_CM_CLKSEL1_CORE_VAL, M4_CM_CLKSEL1_PLL_13_VAL,
++ MX_CLKSEL2_PLL_2x_VAL, R2_CM_CLKSEL_MDM_VAL,
++ SDRC_RFR_CTRL_133MHz,
++ RATE_IN_243X},
++
++ /* PRCM #2 - ratio1 (ES2) - FAST */
++ {S13M, S658M, S329M, R1_CM_CLKSEL_MPU_VAL, /* 330MHz ARM */
++ R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
++ R1_CM_CLKSEL1_CORE_VAL, M2_CM_CLKSEL1_PLL_13_VAL,
++ MX_CLKSEL2_PLL_2x_VAL, R1_CM_CLKSEL_MDM_VAL,
++ SDRC_RFR_CTRL_165MHz,
++ RATE_IN_243X},
++
++ /* PRCM #5a - ratio1 - FAST */
++ {S13M, S532M, S266M, R1_CM_CLKSEL_MPU_VAL, /* 266MHz ARM */
++ R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
++ R1_CM_CLKSEL1_CORE_VAL, M5A_CM_CLKSEL1_PLL_13_VAL,
++ MX_CLKSEL2_PLL_2x_VAL, R1_CM_CLKSEL_MDM_VAL,
++ SDRC_RFR_CTRL_133MHz,
++ RATE_IN_243X},
++
++ /* PRCM #5b - ratio1 - FAST */
++ {S13M, S400M, S200M, R1_CM_CLKSEL_MPU_VAL, /* 200MHz ARM */
++ R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
++ R1_CM_CLKSEL1_CORE_VAL, M5B_CM_CLKSEL1_PLL_13_VAL,
++ MX_CLKSEL2_PLL_2x_VAL, R1_CM_CLKSEL_MDM_VAL,
++ SDRC_RFR_CTRL_100MHz,
++ RATE_IN_243X},
++
++ /* PRCM #4 - ratio1 (ES2.1) - SLOW */
++ {S13M, S399M, S199M, R2_CM_CLKSEL_MPU_VAL, /* 200MHz ARM */
++ R2_CM_CLKSEL_DSP_VAL, R2_CM_CLKSEL_GFX_VAL,
++ R2_CM_CLKSEL1_CORE_VAL, M4_CM_CLKSEL1_PLL_13_VAL,
++ MX_CLKSEL2_PLL_1x_VAL, R2_CM_CLKSEL_MDM_VAL,
++ SDRC_RFR_CTRL_133MHz,
++ RATE_IN_243X},
++
++ /* PRCM #2 - ratio1 (ES2) - SLOW */
++ {S13M, S329M, S164M, R1_CM_CLKSEL_MPU_VAL, /* 165MHz ARM */
++ R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
++ R1_CM_CLKSEL1_CORE_VAL, M2_CM_CLKSEL1_PLL_13_VAL,
++ MX_CLKSEL2_PLL_1x_VAL, R1_CM_CLKSEL_MDM_VAL,
++ SDRC_RFR_CTRL_165MHz,
++ RATE_IN_243X},
++
++ /* PRCM #5a - ratio1 - SLOW */
++ {S13M, S266M, S133M, R1_CM_CLKSEL_MPU_VAL, /* 133MHz ARM */
++ R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
++ R1_CM_CLKSEL1_CORE_VAL, M5A_CM_CLKSEL1_PLL_13_VAL,
++ MX_CLKSEL2_PLL_1x_VAL, R1_CM_CLKSEL_MDM_VAL,
++ SDRC_RFR_CTRL_133MHz,
++ RATE_IN_243X},
++
++ /* PRCM #5b - ratio1 - SLOW*/
++ {S13M, S200M, S100M, R1_CM_CLKSEL_MPU_VAL, /* 100MHz ARM */
++ R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
++ R1_CM_CLKSEL1_CORE_VAL, M5B_CM_CLKSEL1_PLL_13_VAL,
++ MX_CLKSEL2_PLL_1x_VAL, R1_CM_CLKSEL_MDM_VAL,
++ SDRC_RFR_CTRL_100MHz,
++ RATE_IN_243X},
++
++ /* PRCM-boot/bypass */
++ {S13M, S13M, S13M, RB_CM_CLKSEL_MPU_VAL, /* 13Mhz */
++ RB_CM_CLKSEL_DSP_VAL, RB_CM_CLKSEL_GFX_VAL,
++ RB_CM_CLKSEL1_CORE_VAL, MB_CM_CLKSEL1_PLL_13_VAL,
++ MX_CLKSEL2_PLL_2x_VAL, RB_CM_CLKSEL_MDM_VAL,
++ SDRC_RFR_CTRL_BYPASS,
++ RATE_IN_243X},
++
++ /* PRCM-boot/bypass */
++ {S12M, S12M, S12M, RB_CM_CLKSEL_MPU_VAL, /* 12Mhz */
++ RB_CM_CLKSEL_DSP_VAL, RB_CM_CLKSEL_GFX_VAL,
++ RB_CM_CLKSEL1_CORE_VAL, MB_CM_CLKSEL1_PLL_12_VAL,
++ MX_CLKSEL2_PLL_2x_VAL, RB_CM_CLKSEL_MDM_VAL,
++ SDRC_RFR_CTRL_BYPASS,
++ RATE_IN_243X},
++
++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
++};
++
++/*-------------------------------------------------------------------------
++ * 24xx clock tree.
++ *
++ * NOTE:In many cases here we are assigning a 'default' parent. In many
++ * cases the parent is selectable. The get/set parent calls will also
++ * switch sources.
++ *
++ * Many some clocks say always_enabled, but they can be auto idled for
++ * power savings. They will always be available upon clock request.
++ *
++ * Several sources are given initial rates which may be wrong, this will
++ * be fixed up in the init func.
++ *
++ * Things are broadly separated below by clock domains. It is
++ * noteworthy that most periferals have dependencies on multiple clock
++ * domains. Many get their interface clocks from the L4 domain, but get
++ * functional clocks from fixed sources or other core domain derived
++ * clocks.
++ *-------------------------------------------------------------------------*/
++
++/* Base external input clocks */
++static struct clk func_32k_ck = {
++ .name = "func_32k_ck",
++ .rate = 32000,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++ RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
++ .recalc = &propagate_rate,
++};
++
++/* Typical 12/13MHz in standalone mode, will be 26Mhz in chassis mode */
++static struct clk osc_ck = { /* (*12, *13, 19.2, *26, 38.4)MHz */
++ .name = "osc_ck",
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++ RATE_PROPAGATES,
++ .enable = &omap2_enable_osc_ck,
++ .disable = &omap2_disable_osc_ck,
++ .recalc = &omap2_osc_clk_recalc,
++};
++
++/* With out modem likely 12MHz, with modem likely 13MHz */
++static struct clk sys_ck = { /* (*12, *13, 19.2, 26, 38.4)MHz */
++ .name = "sys_ck", /* ~ ref_clk also */
++ .parent = &osc_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++ ALWAYS_ENABLED | RATE_PROPAGATES,
++ .recalc = &omap2_sys_clk_recalc,
++};
++
++static struct clk alt_ck = { /* Typical 54M or 48M, may not exist */
++ .name = "alt_ck",
++ .rate = 54000000,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++ RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
++ .recalc = &propagate_rate,
++};
++
++/*
++ * Analog domain root source clocks
++ */
++
++/* dpll_ck, is broken out in to special cases through clksel */
++/* REVISIT: Rate changes on dpll_ck trigger a full set change. ...
++ * deal with this
++ */
++
++static const struct dpll_data dpll_dd = {
++ .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
++ .mult_mask = OMAP24XX_DPLL_MULT_MASK,
++ .div1_mask = OMAP24XX_DPLL_DIV_MASK,
++};
++
++static struct clk dpll_ck = {
++ .name = "dpll_ck",
++ .parent = &sys_ck, /* Can be func_32k also */
++ .dpll_data = &dpll_dd,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++ RATE_PROPAGATES | ALWAYS_ENABLED,
++ .recalc = &omap2_dpll_recalc,
++ .set_rate = &omap2_reprogram_dpll,
++};
++
++static struct clk apll96_ck = {
++ .name = "apll96_ck",
++ .parent = &sys_ck,
++ .rate = 96000000,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++ RATE_FIXED | RATE_PROPAGATES | ENABLE_ON_INIT,
++ .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
++ .enable_bit = OMAP24XX_EN_96M_PLL_SHIFT,
++ .enable = &omap2_clk_fixed_enable,
++ .disable = &omap2_clk_fixed_disable,
++ .recalc = &propagate_rate,
++};
++
++static struct clk apll54_ck = {
++ .name = "apll54_ck",
++ .parent = &sys_ck,
++ .rate = 54000000,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++ RATE_FIXED | RATE_PROPAGATES | ENABLE_ON_INIT,
++ .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
++ .enable_bit = OMAP24XX_EN_54M_PLL_SHIFT,
++ .enable = &omap2_clk_fixed_enable,
++ .disable = &omap2_clk_fixed_disable,
++ .recalc = &propagate_rate,
++};
++
++/*
++ * PRCM digital base sources
++ */
++
++/* func_54m_ck */
++
++static const struct clksel_rate func_54m_apll54_rates[] = {
++ { .div = 1, .val = 0, .flags = RATE_IN_24XX | DEFAULT_RATE },
++ { .div = 0 },
++};
++
++static const struct clksel_rate func_54m_alt_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
++ { .div = 0 },
++};
++
++static const struct clksel func_54m_clksel[] = {
++ { .parent = &apll54_ck, .rates = func_54m_apll54_rates, },
++ { .parent = &alt_ck, .rates = func_54m_alt_rates, },
++ { .parent = NULL },
++};
++
++static struct clk func_54m_ck = {
++ .name = "func_54m_ck",
++ .parent = &apll54_ck, /* can also be alt_clk */
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++ RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
++ .clksel_mask = OMAP24XX_54M_SOURCE,
++ .clksel = func_54m_clksel,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk core_ck = {
++ .name = "core_ck",
++ .parent = &dpll_ck, /* can also be 32k */
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++ ALWAYS_ENABLED | RATE_PROPAGATES,
++ .recalc = &followparent_recalc,
++};
++
++/* func_96m_ck */
++static const struct clksel_rate func_96m_apll96_rates[] = {
++ { .div = 1, .val = 0, .flags = RATE_IN_24XX | DEFAULT_RATE },
++ { .div = 0 },
++};
++
++static const struct clksel_rate func_96m_alt_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_243X | DEFAULT_RATE },
++ { .div = 0 },
++};
++
++static const struct clksel func_96m_clksel[] = {
++ { .parent = &apll96_ck, .rates = func_96m_apll96_rates },
++ { .parent = &alt_ck, .rates = func_96m_alt_rates },
++ { .parent = NULL }
++};
++
++/* The parent of this clock is not selectable on 2420. */
++static struct clk func_96m_ck = {
++ .name = "func_96m_ck",
++ .parent = &apll96_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++ RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
++ .clksel_mask = OMAP2430_96M_SOURCE,
++ .clksel = func_96m_clksel,
++ .recalc = &omap2_clksel_recalc,
++ .round_rate = &omap2_clksel_round_rate,
++ .set_rate = &omap2_clksel_set_rate
++};
++
++/* func_48m_ck */
++
++static const struct clksel_rate func_48m_apll96_rates[] = {
++ { .div = 2, .val = 0, .flags = RATE_IN_24XX | DEFAULT_RATE },
++ { .div = 0 },
++};
++
++static const struct clksel_rate func_48m_alt_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
++ { .div = 0 },
++};
++
++static const struct clksel func_48m_clksel[] = {
++ { .parent = &apll96_ck, .rates = func_48m_apll96_rates },
++ { .parent = &alt_ck, .rates = func_48m_alt_rates },
++ { .parent = NULL }
++};
++
++static struct clk func_48m_ck = {
++ .name = "func_48m_ck",
++ .parent = &apll96_ck, /* 96M or Alt */
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++ RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
++ .clksel_mask = OMAP24XX_48M_SOURCE,
++ .clksel = func_48m_clksel,
++ .recalc = &omap2_clksel_recalc,
++ .round_rate = &omap2_clksel_round_rate,
++ .set_rate = &omap2_clksel_set_rate
++};
++
++static struct clk func_12m_ck = {
++ .name = "func_12m_ck",
++ .parent = &func_48m_ck,
++ .fixed_div = 4,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++ RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_fixed_divisor_recalc,
++};
++
++/* Secure timer, only available in secure mode */
++static struct clk wdt1_osc_ck = {
++ .name = "ck_wdt1_osc",
++ .parent = &osc_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .recalc = &followparent_recalc,
++};
++
++/*
++ * The common_clkout* clksel_rate structs are common to
++ * sys_clkout, sys_clkout_src, sys_clkout2, and sys_clkout2_src.
++ * sys_clkout2_* are 2420-only, so the
++ * clksel_rate flags fields are inaccurate for those clocks. This is
++ * harmless since access to those clocks are gated by the struct clk
++ * flags fields, which mark them as 2420-only.
++ */
++static const struct clksel_rate common_clkout_src_core_rates[] = {
++ { .div = 1, .val = 0, .flags = RATE_IN_24XX | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel_rate common_clkout_src_sys_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel_rate common_clkout_src_96m_rates[] = {
++ { .div = 1, .val = 2, .flags = RATE_IN_24XX | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel_rate common_clkout_src_54m_rates[] = {
++ { .div = 1, .val = 3, .flags = RATE_IN_24XX | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel common_clkout_src_clksel[] = {
++ { .parent = &core_ck, .rates = common_clkout_src_core_rates },
++ { .parent = &sys_ck, .rates = common_clkout_src_sys_rates },
++ { .parent = &func_96m_ck, .rates = common_clkout_src_96m_rates },
++ { .parent = &func_54m_ck, .rates = common_clkout_src_54m_rates },
++ { .parent = NULL }
++};
++
++static struct clk sys_clkout_src = {
++ .name = "sys_clkout_src",
++ .parent = &func_54m_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++ RATE_PROPAGATES,
++ .enable_reg = OMAP24XX_PRCM_CLKOUT_CTRL,
++ .enable_bit = OMAP24XX_CLKOUT_EN_SHIFT,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP24XX_PRCM_CLKOUT_CTRL,
++ .clksel_mask = OMAP24XX_CLKOUT_SOURCE_MASK,
++ .clksel = common_clkout_src_clksel,
++ .recalc = &omap2_clksel_recalc,
++ .round_rate = &omap2_clksel_round_rate,
++ .set_rate = &omap2_clksel_set_rate
++};
++
++static const struct clksel_rate common_clkout_rates[] = {
++ { .div = 1, .val = 0, .flags = RATE_IN_24XX | DEFAULT_RATE },
++ { .div = 2, .val = 1, .flags = RATE_IN_24XX },
++ { .div = 4, .val = 2, .flags = RATE_IN_24XX },
++ { .div = 8, .val = 3, .flags = RATE_IN_24XX },
++ { .div = 16, .val = 4, .flags = RATE_IN_24XX },
++ { .div = 0 },
++};
++
++static const struct clksel sys_clkout_clksel[] = {
++ { .parent = &sys_clkout_src, .rates = common_clkout_rates },
++ { .parent = NULL }
++};
++
++static struct clk sys_clkout = {
++ .name = "sys_clkout",
++ .parent = &sys_clkout_src,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++ PARENT_CONTROLS_CLOCK,
++ .clksel_reg = OMAP24XX_PRCM_CLKOUT_CTRL,
++ .clksel_mask = OMAP24XX_CLKOUT_DIV_MASK,
++ .clksel = sys_clkout_clksel,
++ .recalc = &omap2_clksel_recalc,
++ .round_rate = &omap2_clksel_round_rate,
++ .set_rate = &omap2_clksel_set_rate
++};
++
++/* In 2430, new in 2420 ES2 */
++static struct clk sys_clkout2_src = {
++ .name = "sys_clkout2_src",
++ .parent = &func_54m_ck,
++ .flags = CLOCK_IN_OMAP242X | RATE_PROPAGATES,
++ .enable_reg = OMAP24XX_PRCM_CLKOUT_CTRL,
++ .enable_bit = OMAP2420_CLKOUT2_EN_SHIFT,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP24XX_PRCM_CLKOUT_CTRL,
++ .clksel_mask = OMAP2420_CLKOUT2_SOURCE_MASK,
++ .clksel = common_clkout_src_clksel,
++ .recalc = &omap2_clksel_recalc,
++ .round_rate = &omap2_clksel_round_rate,
++ .set_rate = &omap2_clksel_set_rate
++};
++
++static const struct clksel sys_clkout2_clksel[] = {
++ { .parent = &sys_clkout2_src, .rates = common_clkout_rates },
++ { .parent = NULL }
++};
++
++/* In 2430, new in 2420 ES2 */
++static struct clk sys_clkout2 = {
++ .name = "sys_clkout2",
++ .parent = &sys_clkout2_src,
++ .flags = CLOCK_IN_OMAP242X | PARENT_CONTROLS_CLOCK,
++ .clksel_reg = OMAP24XX_PRCM_CLKOUT_CTRL,
++ .clksel_mask = OMAP2420_CLKOUT2_DIV_MASK,
++ .clksel = sys_clkout2_clksel,
++ .recalc = &omap2_clksel_recalc,
++ .round_rate = &omap2_clksel_round_rate,
++ .set_rate = &omap2_clksel_set_rate
++};
++
++static struct clk emul_ck = {
++ .name = "emul_ck",
++ .parent = &func_54m_ck,
++ .flags = CLOCK_IN_OMAP242X,
++ .enable_reg = OMAP24XX_PRCM_CLKEMUL_CTRL,
++ .enable_bit = OMAP24XX_EMULATION_EN_SHIFT,
++ .recalc = &followparent_recalc,
++
++};
++
++/*
++ * MPU clock domain
++ * Clocks:
++ * MPU_FCLK, MPU_ICLK
++ * INT_M_FCLK, INT_M_I_CLK
++ *
++ * - Individual clocks are hardware managed.
++ * - Base divider comes from: CM_CLKSEL_MPU
++ *
++ */
++static const struct clksel_rate mpu_core_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
++ { .div = 2, .val = 2, .flags = RATE_IN_24XX },
++ { .div = 4, .val = 4, .flags = RATE_IN_242X },
++ { .div = 6, .val = 6, .flags = RATE_IN_242X },
++ { .div = 8, .val = 8, .flags = RATE_IN_242X },
++ { .div = 0 },
++};
++
++static const struct clksel mpu_clksel[] = {
++ { .parent = &core_ck, .rates = mpu_core_rates },
++ { .parent = NULL }
++};
++
++static struct clk mpu_ck = { /* Control cpu */
++ .name = "mpu_ck",
++ .parent = &core_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++ ALWAYS_ENABLED | DELAYED_APP |
++ CONFIG_PARTICIPANT | RATE_PROPAGATES,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP24XX_CLKSEL_MPU_MASK,
++ .clksel = mpu_clksel,
++ .recalc = &omap2_clksel_recalc,
++ .round_rate = &omap2_clksel_round_rate,
++ .set_rate = &omap2_clksel_set_rate
++};
++
++/*
++ * DSP (2430-IVA2.1) (2420-UMA+IVA1) clock domain
++ * Clocks:
++ * 2430: IVA2.1_FCLK (really just DSP_FCLK), IVA2.1_ICLK
++ * 2420: UMA_FCLK, UMA_ICLK, IVA_MPU, IVA_COP
++ *
++ * Won't be too specific here. The core clock comes into this block
++ * it is divided then tee'ed. One branch goes directly to xyz enable
++ * controls. The other branch gets further divided by 2 then possibly
++ * routed into a synchronizer and out of clocks abc.
++ */
++static const struct clksel_rate dsp_fck_core_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
++ { .div = 2, .val = 2, .flags = RATE_IN_24XX },
++ { .div = 3, .val = 3, .flags = RATE_IN_24XX },
++ { .div = 4, .val = 4, .flags = RATE_IN_24XX },
++ { .div = 6, .val = 6, .flags = RATE_IN_242X },
++ { .div = 8, .val = 8, .flags = RATE_IN_242X },
++ { .div = 12, .val = 12, .flags = RATE_IN_242X },
++ { .div = 0 },
++};
++
++static const struct clksel dsp_fck_clksel[] = {
++ { .parent = &core_ck, .rates = dsp_fck_core_rates },
++ { .parent = NULL }
++};
++
++static struct clk dsp_fck = {
++ .name = "dsp_fck",
++ .parent = &core_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP |
++ CONFIG_PARTICIPANT | RATE_PROPAGATES,
++ .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
++ .enable_bit = OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP24XX_CLKSEL_DSP_MASK,
++ .clksel = dsp_fck_clksel,
++ .recalc = &omap2_clksel_recalc,
++ .round_rate = &omap2_clksel_round_rate,
++ .set_rate = &omap2_clksel_set_rate
++};
++
++/* DSP interface clock */
++static const struct clksel_rate dsp_irate_ick_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
++ { .div = 2, .val = 2, .flags = RATE_IN_24XX },
++ { .div = 3, .val = 3, .flags = RATE_IN_243X },
++ { .div = 0 },
++};
++
++static const struct clksel dsp_irate_ick_clksel[] = {
++ { .parent = &dsp_fck, .rates = dsp_irate_ick_rates },
++ { .parent = NULL }
++};
++
++/*
++ * This clock does not exist as such in the TRM, but is added to
++ * separate source selection from XXX
++ */
++static struct clk dsp_irate_ick = {
++ .name = "dsp_irate_ick",
++ .parent = &dsp_fck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP |
++ CONFIG_PARTICIPANT | PARENT_CONTROLS_CLOCK,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP24XX_CLKSEL_DSP_IF_MASK,
++ .clksel = dsp_irate_ick_clksel,
++ .recalc = &omap2_clksel_recalc,
++ .round_rate = &omap2_clksel_round_rate,
++ .set_rate = &omap2_clksel_set_rate
++};
++
++/* 2420 only */
++static struct clk dsp_ick = {
++ .name = "dsp_ick", /* apparently ipi and isp */
++ .parent = &dsp_irate_ick,
++ .flags = CLOCK_IN_OMAP242X | DELAYED_APP | CONFIG_PARTICIPANT,
++ .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_ICLKEN),
++ .enable_bit = OMAP2420_EN_DSP_IPI_SHIFT, /* for ipi */
++};
++
++/* 2430 only - EN_DSP controls both dsp fclk and iclk on 2430 */
++static struct clk iva2_1_ick = {
++ .name = "iva2_1_ick",
++ .parent = &dsp_irate_ick,
++ .flags = CLOCK_IN_OMAP243X | DELAYED_APP | CONFIG_PARTICIPANT,
++ .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
++ .enable_bit = OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
++};
++
++static struct clk iva1_ifck = {
++ .name = "iva1_ifck",
++ .parent = &core_ck,
++ .flags = CLOCK_IN_OMAP242X | CONFIG_PARTICIPANT |
++ RATE_PROPAGATES | DELAYED_APP,
++ .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
++ .enable_bit = OMAP2420_EN_IVA_COP_SHIFT,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP2420_CLKSEL_IVA_MASK,
++ .clksel = dsp_fck_clksel,
++ .recalc = &omap2_clksel_recalc,
++ .round_rate = &omap2_clksel_round_rate,
++ .set_rate = &omap2_clksel_set_rate
++};
++
++/* IVA1 mpu/int/i/f clocks are /2 of parent */
++static struct clk iva1_mpu_int_ifck = {
++ .name = "iva1_mpu_int_ifck",
++ .parent = &iva1_ifck,
++ .flags = CLOCK_IN_OMAP242X,
++ .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
++ .enable_bit = OMAP2420_EN_IVA_MPU_SHIFT,
++ .fixed_div = 2,
++ .recalc = &omap2_fixed_divisor_recalc,
++};
++
++/*
++ * L3 clock domain
++ * L3 clocks are used for both interface and functional clocks to
++ * multiple entities. Some of these clocks are completely managed
++ * by hardware, and some others allow software control. Hardware
++ * managed ones general are based on directly CLK_REQ signals and
++ * various auto idle settings. The functional spec sets many of these
++ * as 'tie-high' for their enables.
++ *
++ * I-CLOCKS:
++ * L3-Interconnect, SMS, GPMC, SDRC, OCM_RAM, OCM_ROM, SDMA
++ * CAM, HS-USB.
++ * F-CLOCK
++ * SSI.
++ *
++ * GPMC memories and SDRC have timing and clock sensitive registers which
++ * may very well need notification when the clock changes. Currently for low
++ * operating points, these are taken care of in sleep.S.
++ */
++static const struct clksel_rate core_l3_core_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_24XX },
++ { .div = 2, .val = 2, .flags = RATE_IN_242X },
++ { .div = 4, .val = 4, .flags = RATE_IN_24XX | DEFAULT_RATE },
++ { .div = 6, .val = 6, .flags = RATE_IN_24XX },
++ { .div = 8, .val = 8, .flags = RATE_IN_242X },
++ { .div = 12, .val = 12, .flags = RATE_IN_242X },
++ { .div = 16, .val = 16, .flags = RATE_IN_242X },
++ { .div = 0 }
++};
++
++static const struct clksel core_l3_clksel[] = {
++ { .parent = &core_ck, .rates = core_l3_core_rates },
++ { .parent = NULL }
++};
++
++static struct clk core_l3_ck = { /* Used for ick and fck, interconnect */
++ .name = "core_l3_ck",
++ .parent = &core_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++ ALWAYS_ENABLED | DELAYED_APP |
++ CONFIG_PARTICIPANT | RATE_PROPAGATES,
++ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
++ .clksel_mask = OMAP24XX_CLKSEL_L3_MASK,
++ .clksel = core_l3_clksel,
++ .recalc = &omap2_clksel_recalc,
++ .round_rate = &omap2_clksel_round_rate,
++ .set_rate = &omap2_clksel_set_rate
++};
++
++/* usb_l4_ick */
++static const struct clksel_rate usb_l4_ick_core_l3_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_24XX },
++ { .div = 2, .val = 2, .flags = RATE_IN_24XX | DEFAULT_RATE },
++ { .div = 4, .val = 4, .flags = RATE_IN_24XX },
++ { .div = 0 }
++};
++
++static const struct clksel usb_l4_ick_clksel[] = {
++ { .parent = &core_l3_ck, .rates = usb_l4_ick_core_l3_rates },
++ { .parent = NULL },
++};
++
++static struct clk usb_l4_ick = { /* FS-USB interface clock */
++ .name = "usb_l4_ick",
++ .parent = &core_l3_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++ DELAYED_APP | CONFIG_PARTICIPANT,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++ .enable_bit = OMAP24XX_EN_USB_SHIFT,
++ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
++ .clksel_mask = OMAP24XX_CLKSEL_USB_MASK,
++ .clksel = usb_l4_ick_clksel,
++ .recalc = &omap2_clksel_recalc,
++ .round_rate = &omap2_clksel_round_rate,
++ .set_rate = &omap2_clksel_set_rate
++};
++
++/*
++ * SSI is in L3 management domain, its direct parent is core not l3,
++ * many core power domain entities are grouped into the L3 clock
++ * domain.
++ * SSI_SSR_FCLK, SSI_SST_FCLK, SSI_L4_CLIK
++ *
++ * ssr = core/1/2/3/4/5, sst = 1/2 ssr.
++ */
++static const struct clksel_rate ssi_ssr_sst_fck_core_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_24XX },
++ { .div = 2, .val = 2, .flags = RATE_IN_24XX | DEFAULT_RATE },
++ { .div = 3, .val = 3, .flags = RATE_IN_24XX },
++ { .div = 4, .val = 4, .flags = RATE_IN_24XX },
++ { .div = 5, .val = 5, .flags = RATE_IN_243X },
++ { .div = 6, .val = 6, .flags = RATE_IN_242X },
++ { .div = 8, .val = 8, .flags = RATE_IN_242X },
++ { .div = 0 }
++};
++
++static const struct clksel ssi_ssr_sst_fck_clksel[] = {
++ { .parent = &core_ck, .rates = ssi_ssr_sst_fck_core_rates },
++ { .parent = NULL }
++};
++
++static struct clk ssi_ssr_sst_fck = {
++ .name = "ssi_fck",
++ .parent = &core_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++ DELAYED_APP,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++ .enable_bit = OMAP24XX_EN_SSI_SHIFT,
++ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
++ .clksel_mask = OMAP24XX_CLKSEL_SSI_MASK,
++ .clksel = ssi_ssr_sst_fck_clksel,
++ .recalc = &omap2_clksel_recalc,
++ .round_rate = &omap2_clksel_round_rate,
++ .set_rate = &omap2_clksel_set_rate
++};
++
++/*
++ * GFX clock domain
++ * Clocks:
++ * GFX_FCLK, GFX_ICLK
++ * GFX_CG1(2d), GFX_CG2(3d)
++ *
++ * GFX_FCLK runs from L3, and is divided by (1,2,3,4)
++ * The 2d and 3d clocks run at a hardware determined
++ * divided value of fclk.
++ *
++ */
++/* XXX REVISIT: GFX clock is part of CONFIG_PARTICIPANT, no? doublecheck. */
++
++/* This clksel struct is shared between gfx_3d_fck and gfx_2d_fck */
++static const struct clksel gfx_fck_clksel[] = {
++ { .parent = &core_l3_ck, .rates = gfx_l3_rates },
++ { .parent = NULL },
++};
++
++static struct clk gfx_3d_fck = {
++ .name = "gfx_3d_fck",
++ .parent = &core_l3_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
++ .enable_bit = OMAP24XX_EN_3D_SHIFT,
++ .clksel_reg = OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP_CLKSEL_GFX_MASK,
++ .clksel = gfx_fck_clksel,
++ .recalc = &omap2_clksel_recalc,
++ .round_rate = &omap2_clksel_round_rate,
++ .set_rate = &omap2_clksel_set_rate
++};
++
++static struct clk gfx_2d_fck = {
++ .name = "gfx_2d_fck",
++ .parent = &core_l3_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
++ .enable_bit = OMAP24XX_EN_2D_SHIFT,
++ .clksel_reg = OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP_CLKSEL_GFX_MASK,
++ .clksel = gfx_fck_clksel,
++ .recalc = &omap2_clksel_recalc,
++ .round_rate = &omap2_clksel_round_rate,
++ .set_rate = &omap2_clksel_set_rate
++};
++
++static struct clk gfx_ick = {
++ .name = "gfx_ick", /* From l3 */
++ .parent = &core_l3_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
++ .enable_bit = OMAP_EN_GFX_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++/*
++ * Modem clock domain (2430)
++ * CLOCKS:
++ * MDM_OSC_CLK
++ * MDM_ICLK
++ * These clocks are usable in chassis mode only.
++ */
++static const struct clksel_rate mdm_ick_core_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_243X },
++ { .div = 4, .val = 4, .flags = RATE_IN_243X | DEFAULT_RATE },
++ { .div = 6, .val = 6, .flags = RATE_IN_243X },
++ { .div = 9, .val = 9, .flags = RATE_IN_243X },
++ { .div = 0 }
++};
++
++static const struct clksel mdm_ick_clksel[] = {
++ { .parent = &core_ck, .rates = mdm_ick_core_rates },
++ { .parent = NULL }
++};
++
++static struct clk mdm_ick = { /* used both as a ick and fck */
++ .name = "mdm_ick",
++ .parent = &core_ck,
++ .flags = CLOCK_IN_OMAP243X | DELAYED_APP | CONFIG_PARTICIPANT,
++ .enable_reg = OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_ICLKEN),
++ .enable_bit = OMAP2430_CM_ICLKEN_MDM_EN_MDM_SHIFT,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP2430_CLKSEL_MDM_MASK,
++ .clksel = mdm_ick_clksel,
++ .recalc = &omap2_clksel_recalc,
++ .round_rate = &omap2_clksel_round_rate,
++ .set_rate = &omap2_clksel_set_rate
++};
++
++static struct clk mdm_osc_ck = {
++ .name = "mdm_osc_ck",
++ .parent = &osc_ck,
++ .flags = CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_FCLKEN),
++ .enable_bit = OMAP2430_EN_OSC_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++/*
++ * L4 clock management domain
++ *
++ * This domain contains lots of interface clocks from the L4 interface, some
++ * functional clocks. Fixed APLL functional source clocks are managed in
++ * this domain.
++ */
++static const struct clksel_rate l4_core_l3_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
++ { .div = 2, .val = 2, .flags = RATE_IN_24XX },
++ { .div = 0 }
++};
++
++static const struct clksel l4_clksel[] = {
++ { .parent = &core_l3_ck, .rates = l4_core_l3_rates },
++ { .parent = NULL }
++};
++
++static struct clk l4_ck = { /* used both as an ick and fck */
++ .name = "l4_ck",
++ .parent = &core_l3_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++ ALWAYS_ENABLED | DELAYED_APP | RATE_PROPAGATES,
++ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
++ .clksel_mask = OMAP24XX_CLKSEL_L4_MASK,
++ .clksel = l4_clksel,
++ .recalc = &omap2_clksel_recalc,
++ .round_rate = &omap2_clksel_round_rate,
++ .set_rate = &omap2_clksel_set_rate
++};
++
++static struct clk ssi_l4_ick = {
++ .name = "ssi_l4_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++ .enable_bit = OMAP24XX_EN_SSI_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++/*
++ * DSS clock domain
++ * CLOCKs:
++ * DSS_L4_ICLK, DSS_L3_ICLK,
++ * DSS_CLK1, DSS_CLK2, DSS_54MHz_CLK
++ *
++ * DSS is both initiator and target.
++ */
++/* XXX Add RATE_NOT_VALIDATED */
++
++static const struct clksel_rate dss1_fck_sys_rates[] = {
++ { .div = 1, .val = 0, .flags = RATE_IN_24XX | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel_rate dss1_fck_core_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_24XX },
++ { .div = 2, .val = 2, .flags = RATE_IN_24XX },
++ { .div = 3, .val = 3, .flags = RATE_IN_24XX },
++ { .div = 4, .val = 4, .flags = RATE_IN_24XX },
++ { .div = 5, .val = 5, .flags = RATE_IN_24XX },
++ { .div = 6, .val = 6, .flags = RATE_IN_24XX },
++ { .div = 8, .val = 8, .flags = RATE_IN_24XX },
++ { .div = 9, .val = 9, .flags = RATE_IN_24XX },
++ { .div = 12, .val = 12, .flags = RATE_IN_24XX },
++ { .div = 16, .val = 16, .flags = RATE_IN_24XX | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel dss1_fck_clksel[] = {
++ { .parent = &sys_ck, .rates = dss1_fck_sys_rates },
++ { .parent = &core_ck, .rates = dss1_fck_core_rates },
++ { .parent = NULL },
++};
++
++static struct clk dss_ick = { /* Enables both L3,L4 ICLK's */
++ .name = "dss_ick",
++ .parent = &l4_ck, /* really both l3 and l4 */
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP24XX_EN_DSS1_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk dss1_fck = {
++ .name = "dss1_fck",
++ .parent = &core_ck, /* Core or sys */
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++ DELAYED_APP,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_DSS1_SHIFT,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
++ .clksel_mask = OMAP24XX_CLKSEL_DSS1_MASK,
++ .clksel = dss1_fck_clksel,
++ .recalc = &omap2_clksel_recalc,
++ .round_rate = &omap2_clksel_round_rate,
++ .set_rate = &omap2_clksel_set_rate
++};
++
++static const struct clksel_rate dss2_fck_sys_rates[] = {
++ { .div = 1, .val = 0, .flags = RATE_IN_24XX | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel_rate dss2_fck_48m_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel dss2_fck_clksel[] = {
++ { .parent = &sys_ck, .rates = dss2_fck_sys_rates },
++ { .parent = &func_48m_ck, .rates = dss2_fck_48m_rates },
++ { .parent = NULL }
++};
++
++static struct clk dss2_fck = { /* Alt clk used in power management */
++ .name = "dss2_fck",
++ .parent = &sys_ck, /* fixed at sys_ck or 48MHz */
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++ DELAYED_APP,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_DSS2_SHIFT,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
++ .clksel_mask = OMAP24XX_CLKSEL_DSS2_MASK,
++ .clksel = dss2_fck_clksel,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk dss_54m_fck = { /* Alt clk used in power management */
++ .name = "dss_54m_fck", /* 54m tv clk */
++ .parent = &func_54m_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_TV_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++/*
++ * CORE power domain ICLK & FCLK defines.
++ * Many of the these can have more than one possible parent. Entries
++ * here will likely have an L4 interface parent, and may have multiple
++ * functional clock parents.
++ */
++static const struct clksel_rate gpt_alt_rates[] = {
++ { .div = 1, .val = 2, .flags = RATE_IN_24XX | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel omap24xx_gpt_clksel[] = {
++ { .parent = &func_32k_ck, .rates = gpt_32k_rates },
++ { .parent = &sys_ck, .rates = gpt_sys_rates },
++ { .parent = &alt_ck, .rates = gpt_alt_rates },
++ { .parent = NULL },
++};
++
++static struct clk gpt1_ick = {
++ .name = "gpt1_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++ .enable_bit = OMAP24XX_EN_GPT1_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt1_fck = {
++ .name = "gpt1_fck",
++ .parent = &func_32k_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
++ .enable_bit = OMAP24XX_EN_GPT1_SHIFT,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL1),
++ .clksel_mask = OMAP24XX_CLKSEL_GPT1_MASK,
++ .clksel = omap24xx_gpt_clksel,
++ .recalc = &omap2_clksel_recalc,
++ .round_rate = &omap2_clksel_round_rate,
++ .set_rate = &omap2_clksel_set_rate
++};
++
++static struct clk gpt2_ick = {
++ .name = "gpt2_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP24XX_EN_GPT2_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt2_fck = {
++ .name = "gpt2_fck",
++ .parent = &func_32k_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_GPT2_SHIFT,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
++ .clksel_mask = OMAP24XX_CLKSEL_GPT2_MASK,
++ .clksel = omap24xx_gpt_clksel,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk gpt3_ick = {
++ .name = "gpt3_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP24XX_EN_GPT3_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt3_fck = {
++ .name = "gpt3_fck",
++ .parent = &func_32k_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_GPT3_SHIFT,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
++ .clksel_mask = OMAP24XX_CLKSEL_GPT3_MASK,
++ .clksel = omap24xx_gpt_clksel,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk gpt4_ick = {
++ .name = "gpt4_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP24XX_EN_GPT4_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt4_fck = {
++ .name = "gpt4_fck",
++ .parent = &func_32k_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_GPT4_SHIFT,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
++ .clksel_mask = OMAP24XX_CLKSEL_GPT4_MASK,
++ .clksel = omap24xx_gpt_clksel,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk gpt5_ick = {
++ .name = "gpt5_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP24XX_EN_GPT5_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt5_fck = {
++ .name = "gpt5_fck",
++ .parent = &func_32k_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_GPT5_SHIFT,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
++ .clksel_mask = OMAP24XX_CLKSEL_GPT5_MASK,
++ .clksel = omap24xx_gpt_clksel,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk gpt6_ick = {
++ .name = "gpt6_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP24XX_EN_GPT6_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt6_fck = {
++ .name = "gpt6_fck",
++ .parent = &func_32k_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_GPT6_SHIFT,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
++ .clksel_mask = OMAP24XX_CLKSEL_GPT6_MASK,
++ .clksel = omap24xx_gpt_clksel,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk gpt7_ick = {
++ .name = "gpt7_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP24XX_EN_GPT7_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt7_fck = {
++ .name = "gpt7_fck",
++ .parent = &func_32k_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_GPT7_SHIFT,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
++ .clksel_mask = OMAP24XX_CLKSEL_GPT7_MASK,
++ .clksel = omap24xx_gpt_clksel,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk gpt8_ick = {
++ .name = "gpt8_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP24XX_EN_GPT8_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt8_fck = {
++ .name = "gpt8_fck",
++ .parent = &func_32k_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_GPT8_SHIFT,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
++ .clksel_mask = OMAP24XX_CLKSEL_GPT8_MASK,
++ .clksel = omap24xx_gpt_clksel,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk gpt9_ick = {
++ .name = "gpt9_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP24XX_EN_GPT9_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt9_fck = {
++ .name = "gpt9_fck",
++ .parent = &func_32k_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_GPT9_SHIFT,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
++ .clksel_mask = OMAP24XX_CLKSEL_GPT9_MASK,
++ .clksel = omap24xx_gpt_clksel,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk gpt10_ick = {
++ .name = "gpt10_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP24XX_EN_GPT10_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt10_fck = {
++ .name = "gpt10_fck",
++ .parent = &func_32k_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_GPT10_SHIFT,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
++ .clksel_mask = OMAP24XX_CLKSEL_GPT10_MASK,
++ .clksel = omap24xx_gpt_clksel,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk gpt11_ick = {
++ .name = "gpt11_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP24XX_EN_GPT11_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt11_fck = {
++ .name = "gpt11_fck",
++ .parent = &func_32k_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_GPT11_SHIFT,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
++ .clksel_mask = OMAP24XX_CLKSEL_GPT11_MASK,
++ .clksel = omap24xx_gpt_clksel,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk gpt12_ick = {
++ .name = "gpt12_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP24XX_EN_GPT12_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt12_fck = {
++ .name = "gpt12_fck",
++ .parent = &func_32k_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_GPT12_SHIFT,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
++ .clksel_mask = OMAP24XX_CLKSEL_GPT12_MASK,
++ .clksel = omap24xx_gpt_clksel,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk mcbsp1_ick = {
++ .name = "mcbsp1_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP24XX_EN_MCBSP1_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcbsp1_fck = {
++ .name = "mcbsp1_fck",
++ .parent = &func_96m_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_MCBSP1_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcbsp2_ick = {
++ .name = "mcbsp2_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP24XX_EN_MCBSP2_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcbsp2_fck = {
++ .name = "mcbsp2_fck",
++ .parent = &func_96m_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_MCBSP2_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcbsp3_ick = {
++ .name = "mcbsp3_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++ .enable_bit = OMAP2430_EN_MCBSP3_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcbsp3_fck = {
++ .name = "mcbsp3_fck",
++ .parent = &func_96m_ck,
++ .flags = CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++ .enable_bit = OMAP2430_EN_MCBSP3_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcbsp4_ick = {
++ .name = "mcbsp4_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++ .enable_bit = OMAP2430_EN_MCBSP4_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcbsp4_fck = {
++ .name = "mcbsp4_fck",
++ .parent = &func_96m_ck,
++ .flags = CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++ .enable_bit = OMAP2430_EN_MCBSP4_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcbsp5_ick = {
++ .name = "mcbsp5_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++ .enable_bit = OMAP2430_EN_MCBSP5_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcbsp5_fck = {
++ .name = "mcbsp5_fck",
++ .parent = &func_96m_ck,
++ .flags = CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++ .enable_bit = OMAP2430_EN_MCBSP5_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcspi1_ick = {
++ .name = "mcspi_ick",
++ .id = 1,
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP24XX_EN_MCSPI1_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcspi1_fck = {
++ .name = "mcspi_fck",
++ .id = 1,
++ .parent = &func_48m_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_MCSPI1_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcspi2_ick = {
++ .name = "mcspi_ick",
++ .id = 2,
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP24XX_EN_MCSPI2_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcspi2_fck = {
++ .name = "mcspi_fck",
++ .id = 2,
++ .parent = &func_48m_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_MCSPI2_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcspi3_ick = {
++ .name = "mcspi_ick",
++ .id = 3,
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++ .enable_bit = OMAP2430_EN_MCSPI3_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcspi3_fck = {
++ .name = "mcspi_fck",
++ .id = 3,
++ .parent = &func_48m_ck,
++ .flags = CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++ .enable_bit = OMAP2430_EN_MCSPI3_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk uart1_ick = {
++ .name = "uart1_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP24XX_EN_UART1_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk uart1_fck = {
++ .name = "uart1_fck",
++ .parent = &func_48m_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_UART1_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk uart2_ick = {
++ .name = "uart2_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP24XX_EN_UART2_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk uart2_fck = {
++ .name = "uart2_fck",
++ .parent = &func_48m_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_UART2_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk uart3_ick = {
++ .name = "uart3_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++ .enable_bit = OMAP24XX_EN_UART3_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk uart3_fck = {
++ .name = "uart3_fck",
++ .parent = &func_48m_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++ .enable_bit = OMAP24XX_EN_UART3_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpios_ick = {
++ .name = "gpios_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++ .enable_bit = OMAP24XX_EN_GPIOS_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpios_fck = {
++ .name = "gpios_fck",
++ .parent = &func_32k_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
++ .enable_bit = OMAP24XX_EN_GPIOS_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mpu_wdt_ick = {
++ .name = "mpu_wdt_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++ .enable_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mpu_wdt_fck = {
++ .name = "mpu_wdt_fck",
++ .parent = &func_32k_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
++ .enable_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk sync_32k_ick = {
++ .name = "sync_32k_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ENABLE_ON_INIT,
++ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++ .enable_bit = OMAP24XX_EN_32KSYNC_SHIFT,
++ .recalc = &followparent_recalc,
++};
++static struct clk wdt1_ick = {
++ .name = "wdt1_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++ .enable_bit = OMAP24XX_EN_WDT1_SHIFT,
++ .recalc = &followparent_recalc,
++};
++static struct clk omapctrl_ick = {
++ .name = "omapctrl_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ENABLE_ON_INIT,
++ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++ .enable_bit = OMAP24XX_EN_OMAPCTRL_SHIFT,
++ .recalc = &followparent_recalc,
++};
++static struct clk icr_ick = {
++ .name = "icr_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++ .enable_bit = OMAP2430_EN_ICR_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk cam_ick = {
++ .name = "cam_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP24XX_EN_CAM_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk cam_fck = {
++ .name = "cam_fck",
++ .parent = &func_96m_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_CAM_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mailboxes_ick = {
++ .name = "mailboxes_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP24XX_EN_MAILBOXES_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk wdt4_ick = {
++ .name = "wdt4_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP24XX_EN_WDT4_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk wdt4_fck = {
++ .name = "wdt4_fck",
++ .parent = &func_32k_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_WDT4_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk wdt3_ick = {
++ .name = "wdt3_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP2420_EN_WDT3_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk wdt3_fck = {
++ .name = "wdt3_fck",
++ .parent = &func_32k_ck,
++ .flags = CLOCK_IN_OMAP242X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP2420_EN_WDT3_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mspro_ick = {
++ .name = "mspro_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP24XX_EN_MSPRO_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mspro_fck = {
++ .name = "mspro_fck",
++ .parent = &func_96m_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_MSPRO_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mmc_ick = {
++ .name = "mmc_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP2420_EN_MMC_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mmc_fck = {
++ .name = "mmc_fck",
++ .parent = &func_96m_ck,
++ .flags = CLOCK_IN_OMAP242X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP2420_EN_MMC_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk fac_ick = {
++ .name = "fac_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP24XX_EN_FAC_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk fac_fck = {
++ .name = "fac_fck",
++ .parent = &func_12m_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_FAC_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk eac_ick = {
++ .name = "eac_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP2420_EN_EAC_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk eac_fck = {
++ .name = "eac_fck",
++ .parent = &func_96m_ck,
++ .flags = CLOCK_IN_OMAP242X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP2420_EN_EAC_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk hdq_ick = {
++ .name = "hdq_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP24XX_EN_HDQ_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk hdq_fck = {
++ .name = "hdq_fck",
++ .parent = &func_12m_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP24XX_EN_HDQ_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk i2c2_ick = {
++ .name = "i2c_ick",
++ .id = 2,
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP2420_EN_I2C2_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk i2c2_fck = {
++ .name = "i2c_fck",
++ .id = 2,
++ .parent = &func_12m_ck,
++ .flags = CLOCK_IN_OMAP242X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP2420_EN_I2C2_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk i2chs2_fck = {
++ .name = "i2chs_fck",
++ .id = 2,
++ .parent = &func_96m_ck,
++ .flags = CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++ .enable_bit = OMAP2430_EN_I2CHS2_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk i2c1_ick = {
++ .name = "i2c_ick",
++ .id = 1,
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP2420_EN_I2C1_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk i2c1_fck = {
++ .name = "i2c_fck",
++ .id = 1,
++ .parent = &func_12m_ck,
++ .flags = CLOCK_IN_OMAP242X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP2420_EN_I2C1_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk i2chs1_fck = {
++ .name = "i2chs_fck",
++ .id = 1,
++ .parent = &func_96m_ck,
++ .flags = CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++ .enable_bit = OMAP2430_EN_I2CHS1_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpmc_fck = {
++ .name = "gpmc_fck",
++ .parent = &core_l3_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ENABLE_ON_INIT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk sdma_fck = {
++ .name = "sdma_fck",
++ .parent = &core_l3_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk sdma_ick = {
++ .name = "sdma_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk vlynq_ick = {
++ .name = "vlynq_ick",
++ .parent = &core_l3_ck,
++ .flags = CLOCK_IN_OMAP242X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP2420_EN_VLYNQ_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static const struct clksel_rate vlynq_fck_96m_rates[] = {
++ { .div = 1, .val = 0, .flags = RATE_IN_242X | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel_rate vlynq_fck_core_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_242X },
++ { .div = 2, .val = 2, .flags = RATE_IN_242X },
++ { .div = 3, .val = 3, .flags = RATE_IN_242X },
++ { .div = 4, .val = 4, .flags = RATE_IN_242X },
++ { .div = 6, .val = 6, .flags = RATE_IN_242X },
++ { .div = 8, .val = 8, .flags = RATE_IN_242X },
++ { .div = 9, .val = 9, .flags = RATE_IN_242X },
++ { .div = 12, .val = 12, .flags = RATE_IN_242X },
++ { .div = 16, .val = 16, .flags = RATE_IN_242X | DEFAULT_RATE },
++ { .div = 18, .val = 18, .flags = RATE_IN_242X },
++ { .div = 0 }
++};
++
++static const struct clksel vlynq_fck_clksel[] = {
++ { .parent = &func_96m_ck, .rates = vlynq_fck_96m_rates },
++ { .parent = &core_ck, .rates = vlynq_fck_core_rates },
++ { .parent = NULL }
++};
++
++static struct clk vlynq_fck = {
++ .name = "vlynq_fck",
++ .parent = &func_96m_ck,
++ .flags = CLOCK_IN_OMAP242X | DELAYED_APP,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP2420_EN_VLYNQ_SHIFT,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
++ .clksel_mask = OMAP2420_CLKSEL_VLYNQ_MASK,
++ .clksel = vlynq_fck_clksel,
++ .recalc = &omap2_clksel_recalc,
++ .round_rate = &omap2_clksel_round_rate,
++ .set_rate = &omap2_clksel_set_rate
++};
++
++static struct clk sdrc_ick = {
++ .name = "sdrc_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP243X | ENABLE_ON_INIT,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
++ .enable_bit = OMAP2430_EN_SDRC_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk des_ick = {
++ .name = "des_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
++ .enable_bit = OMAP24XX_EN_DES_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk sha_ick = {
++ .name = "sha_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
++ .enable_bit = OMAP24XX_EN_SHA_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk rng_ick = {
++ .name = "rng_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
++ .enable_bit = OMAP24XX_EN_RNG_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk aes_ick = {
++ .name = "aes_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
++ .enable_bit = OMAP24XX_EN_AES_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk pka_ick = {
++ .name = "pka_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
++ .enable_bit = OMAP24XX_EN_PKA_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk usb_fck = {
++ .name = "usb_fck",
++ .parent = &func_48m_ck,
++ .flags = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++ .enable_bit = OMAP24XX_EN_USB_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk usbhs_ick = {
++ .name = "usbhs_ick",
++ .parent = &core_l3_ck,
++ .flags = CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++ .enable_bit = OMAP2430_EN_USBHS_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mmchs1_ick = {
++ .name = "mmchs_ick",
++ .id = 1,
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++ .enable_bit = OMAP2430_EN_MMCHS1_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mmchs1_fck = {
++ .name = "mmchs_fck",
++ .id = 1,
++ .parent = &func_96m_ck,
++ .flags = CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++ .enable_bit = OMAP2430_EN_MMCHS1_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mmchs2_ick = {
++ .name = "mmchs_ick",
++ .id = 2,
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++ .enable_bit = OMAP2430_EN_MMCHS2_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mmchs2_fck = {
++ .name = "mmchs_fck",
++ .id = 2,
++ .parent = &func_96m_ck,
++ .flags = CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++ .enable_bit = OMAP2430_EN_MMCHS2_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpio5_ick = {
++ .name = "gpio5_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++ .enable_bit = OMAP2430_EN_GPIO5_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpio5_fck = {
++ .name = "gpio5_fck",
++ .parent = &func_32k_ck,
++ .flags = CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++ .enable_bit = OMAP2430_EN_GPIO5_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mdm_intc_ick = {
++ .name = "mdm_intc_ick",
++ .parent = &l4_ck,
++ .flags = CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++ .enable_bit = OMAP2430_EN_MDM_INTC_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mmchsdb1_fck = {
++ .name = "mmchsdb_fck",
++ .id = 1,
++ .parent = &func_32k_ck,
++ .flags = CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++ .enable_bit = OMAP2430_EN_MMCHSDB1_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mmchsdb2_fck = {
++ .name = "mmchsdb_fck",
++ .id = 2,
++ .parent = &func_32k_ck,
++ .flags = CLOCK_IN_OMAP243X,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
++ .enable_bit = OMAP2430_EN_MMCHSDB2_SHIFT,
++ .recalc = &followparent_recalc,
++};
++
++/*
++ * This clock is a composite clock which does entire set changes then
++ * forces a rebalance. It keys on the MPU speed, but it really could
++ * be any key speed part of a set in the rate table.
++ *
++ * to really change a set, you need memory table sets which get changed
++ * in sram, pre-notifiers & post notifiers, changing the top set, without
++ * having low level display recalc's won't work... this is why dpm notifiers
++ * work, isr's off, walk a list of clocks already _off_ and not messing with
++ * the bus.
++ *
++ * This clock should have no parent. It embodies the entire upper level
++ * active set. A parent will mess up some of the init also.
++ */
++static struct clk virt_prcm_set = {
++ .name = "virt_prcm_set",
++ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
++ VIRTUAL_CLOCK | ALWAYS_ENABLED | DELAYED_APP,
++ .parent = &mpu_ck, /* Indexed by mpu speed, no parent */
++ .recalc = &omap2_table_mpu_recalc, /* sets are keyed on mpu rate */
++ .set_rate = &omap2_select_table_rate,
++ .round_rate = &omap2_round_to_table_rate,
++};
++
++static struct clk *onchip_24xx_clks[] __initdata = {
++ /* external root sources */
++ &func_32k_ck,
++ &osc_ck,
++ &sys_ck,
++ &alt_ck,
++ /* internal analog sources */
++ &dpll_ck,
++ &apll96_ck,
++ &apll54_ck,
++ /* internal prcm root sources */
++ &func_54m_ck,
++ &core_ck,
++ &func_96m_ck,
++ &func_48m_ck,
++ &func_12m_ck,
++ &wdt1_osc_ck,
++ &sys_clkout_src,
++ &sys_clkout,
++ &sys_clkout2_src,
++ &sys_clkout2,
++ &emul_ck,
++ /* mpu domain clocks */
++ &mpu_ck,
++ /* dsp domain clocks */
++ &dsp_fck,
++ &dsp_irate_ick,
++ &dsp_ick, /* 242x */
++ &iva2_1_ick, /* 243x */
++ &iva1_ifck, /* 242x */
++ &iva1_mpu_int_ifck, /* 242x */
++ /* GFX domain clocks */
++ &gfx_3d_fck,
++ &gfx_2d_fck,
++ &gfx_ick,
++ /* Modem domain clocks */
++ &mdm_ick,
++ &mdm_osc_ck,
++ /* DSS domain clocks */
++ &dss_ick,
++ &dss1_fck,
++ &dss2_fck,
++ &dss_54m_fck,
++ /* L3 domain clocks */
++ &core_l3_ck,
++ &ssi_ssr_sst_fck,
++ &usb_l4_ick,
++ /* L4 domain clocks */
++ &l4_ck, /* used as both core_l4 and wu_l4 */
++ &ssi_l4_ick,
++ /* virtual meta-group clock */
++ &virt_prcm_set,
++ /* general l4 interface ck, multi-parent functional clk */
++ &gpt1_ick,
++ &gpt1_fck,
++ &gpt2_ick,
++ &gpt2_fck,
++ &gpt3_ick,
++ &gpt3_fck,
++ &gpt4_ick,
++ &gpt4_fck,
++ &gpt5_ick,
++ &gpt5_fck,
++ &gpt6_ick,
++ &gpt6_fck,
++ &gpt7_ick,
++ &gpt7_fck,
++ &gpt8_ick,
++ &gpt8_fck,
++ &gpt9_ick,
++ &gpt9_fck,
++ &gpt10_ick,
++ &gpt10_fck,
++ &gpt11_ick,
++ &gpt11_fck,
++ &gpt12_ick,
++ &gpt12_fck,
++ &mcbsp1_ick,
++ &mcbsp1_fck,
++ &mcbsp2_ick,
++ &mcbsp2_fck,
++ &mcbsp3_ick,
++ &mcbsp3_fck,
++ &mcbsp4_ick,
++ &mcbsp4_fck,
++ &mcbsp5_ick,
++ &mcbsp5_fck,
++ &mcspi1_ick,
++ &mcspi1_fck,
++ &mcspi2_ick,
++ &mcspi2_fck,
++ &mcspi3_ick,
++ &mcspi3_fck,
++ &uart1_ick,
++ &uart1_fck,
++ &uart2_ick,
++ &uart2_fck,
++ &uart3_ick,
++ &uart3_fck,
++ &gpios_ick,
++ &gpios_fck,
++ &mpu_wdt_ick,
++ &mpu_wdt_fck,
++ &sync_32k_ick,
++ &wdt1_ick,
++ &omapctrl_ick,
++ &icr_ick,
++ &cam_fck,
++ &cam_ick,
++ &mailboxes_ick,
++ &wdt4_ick,
++ &wdt4_fck,
++ &wdt3_ick,
++ &wdt3_fck,
++ &mspro_ick,
++ &mspro_fck,
++ &mmc_ick,
++ &mmc_fck,
++ &fac_ick,
++ &fac_fck,
++ &eac_ick,
++ &eac_fck,
++ &hdq_ick,
++ &hdq_fck,
++ &i2c1_ick,
++ &i2c1_fck,
++ &i2chs1_fck,
++ &i2c2_ick,
++ &i2c2_fck,
++ &i2chs2_fck,
++ &gpmc_fck,
++ &sdma_fck,
++ &sdma_ick,
++ &vlynq_ick,
++ &vlynq_fck,
++ &sdrc_ick,
++ &des_ick,
++ &sha_ick,
++ &rng_ick,
++ &aes_ick,
++ &pka_ick,
++ &usb_fck,
++ &usbhs_ick,
++ &mmchs1_ick,
++ &mmchs1_fck,
++ &mmchs2_ick,
++ &mmchs2_fck,
++ &gpio5_ick,
++ &gpio5_fck,
++ &mdm_intc_ick,
++ &mmchsdb1_fck,
++ &mmchsdb2_fck,
++};
++
++#endif
++
+diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
+new file mode 100644
+index 0000000..b42bdd6
+--- /dev/null
++++ b/arch/arm/mach-omap2/clock34xx.c
+@@ -0,0 +1,235 @@
++/*
++ * OMAP3-specific clock framework functions
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ * Copyright (C) 2007 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ *
++ * Parts of this code are based on code written by
++ * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#undef DEBUG
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/device.h>
++#include <linux/list.h>
++#include <linux/errno.h>
++#include <linux/delay.h>
++#include <linux/clk.h>
++#include <linux/io.h>
++
++#include <asm/arch/clock.h>
++#include <asm/arch/sram.h>
++#include <asm/div64.h>
++#include <asm/bitops.h>
++
++#include "memory.h"
++#include "clock.h"
++#include "clock34xx.h"
++#include "prm.h"
++#include "prm-regbits-34xx.h"
++#include "cm.h"
++#include "cm-regbits-34xx.h"
++
++/* CM_CLKEN_PLL*.EN* bit values */
++#define DPLL_LOCKED 0x7
++
++/**
++ * omap3_dpll_recalc - recalculate DPLL rate
++ * @clk: DPLL struct clk
++ *
++ * Recalculate and propagate the DPLL rate.
++ */
++static void omap3_dpll_recalc(struct clk *clk)
++{
++ clk->rate = omap2_get_dpll_rate(clk);
++
++ propagate_rate(clk);
++}
++
++/**
++ * omap3_clkoutx2_recalc - recalculate DPLL X2 output virtual clock rate
++ * @clk: DPLL output struct clk
++ *
++ * Using parent clock DPLL data, look up DPLL state. If locked, set our
++ * rate to the dpll_clk * 2; otherwise, just use dpll_clk.
++ */
++static void omap3_clkoutx2_recalc(struct clk *clk)
++{
++ const struct dpll_data *dd;
++ u32 v;
++ struct clk *pclk;
++
++ /* Walk up the parents of clk, looking for a DPLL */
++ pclk = clk->parent;
++ while (pclk && !pclk->dpll_data)
++ pclk = pclk->parent;
++
++ /* clk does not have a DPLL as a parent? */
++ WARN_ON(!pclk);
++
++ dd = pclk->dpll_data;
++
++ WARN_ON(!dd->control_reg || !dd->enable_mask);
++
++ v = __raw_readl(dd->control_reg) & dd->enable_mask;
++ v >>= __ffs(dd->enable_mask);
++ if (v != DPLL_LOCKED)
++ clk->rate = clk->parent->rate;
++ else
++ clk->rate = clk->parent->rate * 2;
++
++ if (clk->flags & RATE_PROPAGATES)
++ propagate_rate(clk);
++}
++
++/*
++ * As it is structured now, this will prevent an OMAP2/3 multiboot
++ * kernel from compiling. This will need further attention.
++ */
++#if defined(CONFIG_ARCH_OMAP3)
++
++static struct clk_functions omap2_clk_functions = {
++ .clk_enable = omap2_clk_enable,
++ .clk_disable = omap2_clk_disable,
++ .clk_round_rate = omap2_clk_round_rate,
++ .clk_set_rate = omap2_clk_set_rate,
++ .clk_set_parent = omap2_clk_set_parent,
++ .clk_disable_unused = omap2_clk_disable_unused,
++};
++
++/*
++ * Set clocks for bypass mode for reboot to work.
++ */
++void omap2_clk_prepare_for_reboot(void)
++{
++ /* REVISIT: Not ready for 343x */
++#if 0
++ u32 rate;
++
++ if (vclk == NULL || sclk == NULL)
++ return;
++
++ rate = clk_get_rate(sclk);
++ clk_set_rate(vclk, rate);
++#endif
++}
++
++/* REVISIT: Move this init stuff out into clock.c */
++
++/*
++ * Switch the MPU rate if specified on cmdline.
++ * We cannot do this early until cmdline is parsed.
++ */
++static int __init omap2_clk_arch_init(void)
++{
++ if (!mpurate)
++ return -EINVAL;
++
++ /* REVISIT: not yet ready for 343x */
++#if 0
++ if (omap2_select_table_rate(&virt_prcm_set, mpurate))
++ printk(KERN_ERR "Could not find matching MPU rate\n");
++#endif
++
++ recalculate_root_clocks();
++
++ printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL3/MPU): "
++ "%ld.%01ld/%ld/%ld MHz\n",
++ (osc_sys_ck.rate / 1000000), (osc_sys_ck.rate / 100000) % 10,
++ (core_ck.rate / 1000000), (dpll1_fck.rate / 1000000)) ;
++
++ return 0;
++}
++arch_initcall(omap2_clk_arch_init);
++
++int __init omap2_clk_init(void)
++{
++ /* struct prcm_config *prcm; */
++ struct clk **clkp;
++ /* u32 clkrate; */
++ u32 cpu_clkflg;
++
++ /* REVISIT: Ultimately this will be used for multiboot */
++#if 0
++ if (cpu_is_omap242x()) {
++ cpu_mask = RATE_IN_242X;
++ cpu_clkflg = CLOCK_IN_OMAP242X;
++ clkp = onchip_24xx_clks;
++ } else if (cpu_is_omap2430()) {
++ cpu_mask = RATE_IN_243X;
++ cpu_clkflg = CLOCK_IN_OMAP243X;
++ clkp = onchip_24xx_clks;
++ }
++#endif
++ if (cpu_is_omap34xx()) {
++ cpu_mask = RATE_IN_343X;
++ cpu_clkflg = CLOCK_IN_OMAP343X;
++ clkp = onchip_34xx_clks;
++
++ /*
++ * Update this if there are further clock changes between ES2
++ * and production parts
++ */
++ if (is_sil_rev_equal_to(OMAP3430_REV_ES1_0)) {
++ /* No 3430ES1-only rates exist, so no RATE_IN_3430ES1 */
++ cpu_clkflg |= CLOCK_IN_OMAP3430ES1;
++ } else {
++ cpu_mask |= RATE_IN_3430ES2;
++ cpu_clkflg |= CLOCK_IN_OMAP3430ES2;
++ }
++ }
++
++ clk_init(&omap2_clk_functions);
++
++ for (clkp = onchip_34xx_clks;
++ clkp < onchip_34xx_clks + ARRAY_SIZE(onchip_34xx_clks);
++ clkp++) {
++ if ((*clkp)->flags & cpu_clkflg)
++ clk_register(*clkp);
++ }
++
++ /* REVISIT: Not yet ready for OMAP3 */
++#if 0
++ /* Check the MPU rate set by bootloader */
++ clkrate = omap2_get_dpll_rate_24xx(&dpll_ck);
++ for (prcm = rate_table; prcm->mpu_speed; prcm++) {
++ if (!(prcm->flags & cpu_mask))
++ continue;
++ if (prcm->xtal_speed != sys_ck.rate)
++ continue;
++ if (prcm->dpll_speed <= clkrate)
++ break;
++ }
++ curr_prcm_set = prcm;
++#endif
++
++ recalculate_root_clocks();
++
++ printk(KERN_INFO "Clocking rate (Crystal/DPLL/ARM core): "
++ "%ld.%01ld/%ld/%ld MHz\n",
++ (osc_sys_ck.rate / 1000000), (osc_sys_ck.rate / 100000) % 10,
++ (core_ck.rate / 1000000), (arm_fck.rate / 1000000));
++
++ /*
++ * Only enable those clocks we will need, let the drivers
++ * enable other clocks as necessary
++ */
++ clk_enable_init_clocks();
++
++ /* Avoid sleeping during omap2_clk_prepare_for_reboot() */
++ /* REVISIT: not yet ready for 343x */
++#if 0
++ vclk = clk_get(NULL, "virt_prcm_set");
++ sclk = clk_get(NULL, "sys_ck");
++#endif
++ return 0;
++}
++
++#endif
+diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
+new file mode 100644
+index 0000000..cf4644a
+--- /dev/null
++++ b/arch/arm/mach-omap2/clock34xx.h
+@@ -0,0 +1,3009 @@
++/*
++ * OMAP3 clock framework
++ *
++ * Virtual clocks are introduced as a convenient tools.
++ * They are sources for other clocks and not supposed
++ * to be requested from drivers directly.
++ *
++ * Copyright (C) 2007-2008 Texas Instruments, Inc.
++ * Copyright (C) 2007-2008 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ */
++
++#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H
++#define __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H
++
++#include <asm/arch/control.h>
++
++#include "clock.h"
++#include "cm.h"
++#include "cm-regbits-34xx.h"
++#include "prm.h"
++#include "prm-regbits-34xx.h"
++
++static void omap3_dpll_recalc(struct clk *clk);
++static void omap3_clkoutx2_recalc(struct clk *clk);
++
++/*
++ * DPLL1 supplies clock to the MPU.
++ * DPLL2 supplies clock to the IVA2.
++ * DPLL3 supplies CORE domain clocks.
++ * DPLL4 supplies peripheral clocks.
++ * DPLL5 supplies other peripheral clocks (USBHOST, USIM).
++ */
++
++/* PRM CLOCKS */
++
++/* According to timer32k.c, this is a 32768Hz clock, not a 32000Hz clock. */
++static struct clk omap_32k_fck = {
++ .name = "omap_32k_fck",
++ .rate = 32768,
++ .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
++ ALWAYS_ENABLED,
++ .recalc = &propagate_rate,
++};
++
++static struct clk secure_32k_fck = {
++ .name = "secure_32k_fck",
++ .rate = 32768,
++ .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
++ ALWAYS_ENABLED,
++ .recalc = &propagate_rate,
++};
++
++/* Virtual source clocks for osc_sys_ck */
++static struct clk virt_12m_ck = {
++ .name = "virt_12m_ck",
++ .rate = 12000000,
++ .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
++ ALWAYS_ENABLED,
++ .recalc = &propagate_rate,
++};
++
++static struct clk virt_13m_ck = {
++ .name = "virt_13m_ck",
++ .rate = 13000000,
++ .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
++ ALWAYS_ENABLED,
++ .recalc = &propagate_rate,
++};
++
++static struct clk virt_16_8m_ck = {
++ .name = "virt_16_8m_ck",
++ .rate = 16800000,
++ .flags = CLOCK_IN_OMAP3430ES2 | RATE_FIXED | RATE_PROPAGATES |
++ ALWAYS_ENABLED,
++ .recalc = &propagate_rate,
++};
++
++static struct clk virt_19_2m_ck = {
++ .name = "virt_19_2m_ck",
++ .rate = 19200000,
++ .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
++ ALWAYS_ENABLED,
++ .recalc = &propagate_rate,
++};
++
++static struct clk virt_26m_ck = {
++ .name = "virt_26m_ck",
++ .rate = 26000000,
++ .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
++ ALWAYS_ENABLED,
++ .recalc = &propagate_rate,
++};
++
++static struct clk virt_38_4m_ck = {
++ .name = "virt_38_4m_ck",
++ .rate = 38400000,
++ .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
++ ALWAYS_ENABLED,
++ .recalc = &propagate_rate,
++};
++
++static const struct clksel_rate osc_sys_12m_rates[] = {
++ { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel_rate osc_sys_13m_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel_rate osc_sys_16_8m_rates[] = {
++ { .div = 1, .val = 5, .flags = RATE_IN_3430ES2 | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel_rate osc_sys_19_2m_rates[] = {
++ { .div = 1, .val = 2, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel_rate osc_sys_26m_rates[] = {
++ { .div = 1, .val = 3, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel_rate osc_sys_38_4m_rates[] = {
++ { .div = 1, .val = 4, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel osc_sys_clksel[] = {
++ { .parent = &virt_12m_ck, .rates = osc_sys_12m_rates },
++ { .parent = &virt_13m_ck, .rates = osc_sys_13m_rates },
++ { .parent = &virt_16_8m_ck, .rates = osc_sys_16_8m_rates },
++ { .parent = &virt_19_2m_ck, .rates = osc_sys_19_2m_rates },
++ { .parent = &virt_26m_ck, .rates = osc_sys_26m_rates },
++ { .parent = &virt_38_4m_ck, .rates = osc_sys_38_4m_rates },
++ { .parent = NULL },
++};
++
++/* Oscillator clock */
++/* 12, 13, 16.8, 19.2, 26, or 38.4 MHz */
++static struct clk osc_sys_ck = {
++ .name = "osc_sys_ck",
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP3430_PRM_CLKSEL,
++ .clksel_mask = OMAP3430_SYS_CLKIN_SEL_MASK,
++ .clksel = osc_sys_clksel,
++ /* REVISIT: deal with autoextclkmode? */
++ .flags = CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
++ ALWAYS_ENABLED,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static const struct clksel_rate div2_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 2, .val = 2, .flags = RATE_IN_343X },
++ { .div = 0 }
++};
++
++static const struct clksel sys_clksel[] = {
++ { .parent = &osc_sys_ck, .rates = div2_rates },
++ { .parent = NULL }
++};
++
++/* Latency: this clock is only enabled after PRM_CLKSETUP.SETUP_TIME */
++/* Feeds DPLLs - divided first by PRM_CLKSRC_CTRL.SYSCLKDIV? */
++static struct clk sys_ck = {
++ .name = "sys_ck",
++ .parent = &osc_sys_ck,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP3430_PRM_CLKSRC_CTRL,
++ .clksel_mask = OMAP_SYSCLKDIV_MASK,
++ .clksel = sys_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk sys_altclk = {
++ .name = "sys_altclk",
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++ .recalc = &propagate_rate,
++};
++
++/* Optional external clock input for some McBSPs */
++static struct clk mcbsp_clks = {
++ .name = "mcbsp_clks",
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++ .recalc = &propagate_rate,
++};
++
++/* PRM EXTERNAL CLOCK OUTPUT */
++
++static struct clk sys_clkout1 = {
++ .name = "sys_clkout1",
++ .parent = &osc_sys_ck,
++ .enable_reg = OMAP3430_PRM_CLKOUT_CTRL,
++ .enable_bit = OMAP3430_CLKOUT_EN_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++/* DPLLS */
++
++/* CM CLOCKS */
++
++static const struct clksel_rate dpll_bypass_rates[] = {
++ { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel_rate dpll_locked_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel_rate div16_dpll_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 2, .val = 2, .flags = RATE_IN_343X },
++ { .div = 3, .val = 3, .flags = RATE_IN_343X },
++ { .div = 4, .val = 4, .flags = RATE_IN_343X },
++ { .div = 5, .val = 5, .flags = RATE_IN_343X },
++ { .div = 6, .val = 6, .flags = RATE_IN_343X },
++ { .div = 7, .val = 7, .flags = RATE_IN_343X },
++ { .div = 8, .val = 8, .flags = RATE_IN_343X },
++ { .div = 9, .val = 9, .flags = RATE_IN_343X },
++ { .div = 10, .val = 10, .flags = RATE_IN_343X },
++ { .div = 11, .val = 11, .flags = RATE_IN_343X },
++ { .div = 12, .val = 12, .flags = RATE_IN_343X },
++ { .div = 13, .val = 13, .flags = RATE_IN_343X },
++ { .div = 14, .val = 14, .flags = RATE_IN_343X },
++ { .div = 15, .val = 15, .flags = RATE_IN_343X },
++ { .div = 16, .val = 16, .flags = RATE_IN_343X },
++ { .div = 0 }
++};
++
++/* DPLL1 */
++/* MPU clock source */
++/* Type: DPLL */
++static const struct dpll_data dpll1_dd = {
++ .mult_div1_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL),
++ .mult_mask = OMAP3430_MPU_DPLL_MULT_MASK,
++ .div1_mask = OMAP3430_MPU_DPLL_DIV_MASK,
++ .control_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKEN_PLL),
++ .enable_mask = OMAP3430_EN_MPU_DPLL_MASK,
++ .auto_recal_bit = OMAP3430_EN_MPU_DPLL_DRIFTGUARD_SHIFT,
++ .recal_en_bit = OMAP3430_MPU_DPLL_RECAL_EN_SHIFT,
++ .recal_st_bit = OMAP3430_MPU_DPLL_ST_SHIFT,
++};
++
++static struct clk dpll1_ck = {
++ .name = "dpll1_ck",
++ .parent = &sys_ck,
++ .dpll_data = &dpll1_dd,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++ .recalc = &omap3_dpll_recalc,
++};
++
++/*
++ * This virtual clock provides the CLKOUTX2 output from the DPLL if the
++ * DPLL isn't bypassed.
++ */
++static struct clk dpll1_x2_ck = {
++ .name = "dpll1_x2_ck",
++ .parent = &dpll1_ck,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap3_clkoutx2_recalc,
++};
++
++/* On DPLL1, unlike other DPLLs, the divider is downstream from CLKOUTX2 */
++static const struct clksel div16_dpll1_x2m2_clksel[] = {
++ { .parent = &dpll1_x2_ck, .rates = div16_dpll_rates },
++ { .parent = NULL }
++};
++
++/*
++ * Does not exist in the TRM - needed to separate the M2 divider from
++ * bypass selection in mpu_ck
++ */
++static struct clk dpll1_x2m2_ck = {
++ .name = "dpll1_x2m2_ck",
++ .parent = &dpll1_x2_ck,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL),
++ .clksel_mask = OMAP3430_MPU_DPLL_CLKOUT_DIV_MASK,
++ .clksel = div16_dpll1_x2m2_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++/* DPLL2 */
++/* IVA2 clock source */
++/* Type: DPLL */
++
++static const struct dpll_data dpll2_dd = {
++ .mult_div1_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL),
++ .mult_mask = OMAP3430_IVA2_DPLL_MULT_MASK,
++ .div1_mask = OMAP3430_IVA2_DPLL_DIV_MASK,
++ .control_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL),
++ .enable_mask = OMAP3430_EN_IVA2_DPLL_MASK,
++ .auto_recal_bit = OMAP3430_EN_IVA2_DPLL_DRIFTGUARD_SHIFT,
++ .recal_en_bit = OMAP3430_PRM_IRQENABLE_MPU_IVA2_DPLL_RECAL_EN_SHIFT,
++ .recal_st_bit = OMAP3430_PRM_IRQSTATUS_MPU_IVA2_DPLL_ST_SHIFT,
++};
++
++static struct clk dpll2_ck = {
++ .name = "dpll2_ck",
++ .parent = &sys_ck,
++ .dpll_data = &dpll2_dd,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++ .recalc = &omap3_dpll_recalc,
++};
++
++static const struct clksel div16_dpll2_m2x2_clksel[] = {
++ { .parent = &dpll2_ck, .rates = div16_dpll_rates },
++ { .parent = NULL }
++};
++
++/*
++ * The TRM is conflicted on whether IVA2 clock comes from DPLL2 CLKOUT
++ * or CLKOUTX2. CLKOUT seems most plausible.
++ */
++static struct clk dpll2_m2_ck = {
++ .name = "dpll2_m2_ck",
++ .parent = &dpll2_ck,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD,
++ OMAP3430_CM_CLKSEL2_PLL),
++ .clksel_mask = OMAP3430_IVA2_DPLL_CLKOUT_DIV_MASK,
++ .clksel = div16_dpll2_m2x2_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++/* DPLL3 */
++/* Source clock for all interfaces and for some device fclks */
++/* Type: DPLL */
++static const struct dpll_data dpll3_dd = {
++ .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
++ .mult_mask = OMAP3430_CORE_DPLL_MULT_MASK,
++ .div1_mask = OMAP3430_CORE_DPLL_DIV_MASK,
++ .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
++ .enable_mask = OMAP3430_EN_CORE_DPLL_MASK,
++ .auto_recal_bit = OMAP3430_EN_CORE_DPLL_DRIFTGUARD_SHIFT,
++ .recal_en_bit = OMAP3430_CORE_DPLL_RECAL_EN_SHIFT,
++ .recal_st_bit = OMAP3430_CORE_DPLL_ST_SHIFT,
++};
++
++static struct clk dpll3_ck = {
++ .name = "dpll3_ck",
++ .parent = &sys_ck,
++ .dpll_data = &dpll3_dd,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++ .recalc = &omap3_dpll_recalc,
++};
++
++/*
++ * This virtual clock provides the CLKOUTX2 output from the DPLL if the
++ * DPLL isn't bypassed
++ */
++static struct clk dpll3_x2_ck = {
++ .name = "dpll3_x2_ck",
++ .parent = &dpll3_ck,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap3_clkoutx2_recalc,
++};
++
++static const struct clksel_rate div31_dpll3_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 2, .val = 2, .flags = RATE_IN_343X },
++ { .div = 3, .val = 3, .flags = RATE_IN_3430ES2 },
++ { .div = 4, .val = 4, .flags = RATE_IN_3430ES2 },
++ { .div = 5, .val = 5, .flags = RATE_IN_3430ES2 },
++ { .div = 6, .val = 6, .flags = RATE_IN_3430ES2 },
++ { .div = 7, .val = 7, .flags = RATE_IN_3430ES2 },
++ { .div = 8, .val = 8, .flags = RATE_IN_3430ES2 },
++ { .div = 9, .val = 9, .flags = RATE_IN_3430ES2 },
++ { .div = 10, .val = 10, .flags = RATE_IN_3430ES2 },
++ { .div = 11, .val = 11, .flags = RATE_IN_3430ES2 },
++ { .div = 12, .val = 12, .flags = RATE_IN_3430ES2 },
++ { .div = 13, .val = 13, .flags = RATE_IN_3430ES2 },
++ { .div = 14, .val = 14, .flags = RATE_IN_3430ES2 },
++ { .div = 15, .val = 15, .flags = RATE_IN_3430ES2 },
++ { .div = 16, .val = 16, .flags = RATE_IN_3430ES2 },
++ { .div = 17, .val = 17, .flags = RATE_IN_3430ES2 },
++ { .div = 18, .val = 18, .flags = RATE_IN_3430ES2 },
++ { .div = 19, .val = 19, .flags = RATE_IN_3430ES2 },
++ { .div = 20, .val = 20, .flags = RATE_IN_3430ES2 },
++ { .div = 21, .val = 21, .flags = RATE_IN_3430ES2 },
++ { .div = 22, .val = 22, .flags = RATE_IN_3430ES2 },
++ { .div = 23, .val = 23, .flags = RATE_IN_3430ES2 },
++ { .div = 24, .val = 24, .flags = RATE_IN_3430ES2 },
++ { .div = 25, .val = 25, .flags = RATE_IN_3430ES2 },
++ { .div = 26, .val = 26, .flags = RATE_IN_3430ES2 },
++ { .div = 27, .val = 27, .flags = RATE_IN_3430ES2 },
++ { .div = 28, .val = 28, .flags = RATE_IN_3430ES2 },
++ { .div = 29, .val = 29, .flags = RATE_IN_3430ES2 },
++ { .div = 30, .val = 30, .flags = RATE_IN_3430ES2 },
++ { .div = 31, .val = 31, .flags = RATE_IN_3430ES2 },
++ { .div = 0 },
++};
++
++static const struct clksel div31_dpll3m2_clksel[] = {
++ { .parent = &dpll3_ck, .rates = div31_dpll3_rates },
++ { .parent = NULL }
++};
++
++/*
++ * DPLL3 output M2
++ * REVISIT: This DPLL output divider must be changed in SRAM, so until
++ * that code is ready, this should remain a 'read-only' clksel clock.
++ */
++static struct clk dpll3_m2_ck = {
++ .name = "dpll3_m2_ck",
++ .parent = &dpll3_ck,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
++ .clksel_mask = OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK,
++ .clksel = div31_dpll3m2_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static const struct clksel core_ck_clksel[] = {
++ { .parent = &sys_ck, .rates = dpll_bypass_rates },
++ { .parent = &dpll3_m2_ck, .rates = dpll_locked_rates },
++ { .parent = NULL }
++};
++
++static struct clk core_ck = {
++ .name = "core_ck",
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
++ .clksel_mask = OMAP3430_ST_CORE_CLK,
++ .clksel = core_ck_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static const struct clksel dpll3_m2x2_ck_clksel[] = {
++ { .parent = &sys_ck, .rates = dpll_bypass_rates },
++ { .parent = &dpll3_x2_ck, .rates = dpll_locked_rates },
++ { .parent = NULL }
++};
++
++static struct clk dpll3_m2x2_ck = {
++ .name = "dpll3_m2x2_ck",
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
++ .clksel_mask = OMAP3430_ST_CORE_CLK,
++ .clksel = dpll3_m2x2_ck_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++/* The PWRDN bit is apparently only available on 3430ES2 and above */
++static const struct clksel div16_dpll3_clksel[] = {
++ { .parent = &dpll3_ck, .rates = div16_dpll_rates },
++ { .parent = NULL }
++};
++
++/* This virtual clock is the source for dpll3_m3x2_ck */
++static struct clk dpll3_m3_ck = {
++ .name = "dpll3_m3_ck",
++ .parent = &dpll3_ck,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
++ .clksel_mask = OMAP3430_DIV_DPLL3_MASK,
++ .clksel = div16_dpll3_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++/* The PWRDN bit is apparently only available on 3430ES2 and above */
++static struct clk dpll3_m3x2_ck = {
++ .name = "dpll3_m3x2_ck",
++ .parent = &dpll3_m3_ck,
++ .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
++ .enable_bit = OMAP3430_PWRDN_EMU_CORE_SHIFT,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
++ .recalc = &omap3_clkoutx2_recalc,
++};
++
++static const struct clksel emu_core_alwon_ck_clksel[] = {
++ { .parent = &sys_ck, .rates = dpll_bypass_rates },
++ { .parent = &dpll3_m3x2_ck, .rates = dpll_locked_rates },
++ { .parent = NULL }
++};
++
++static struct clk emu_core_alwon_ck = {
++ .name = "emu_core_alwon_ck",
++ .parent = &dpll3_m3x2_ck,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
++ .clksel_mask = OMAP3430_ST_CORE_CLK,
++ .clksel = emu_core_alwon_ck_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++/* DPLL4 */
++/* Supplies 96MHz, 54Mhz TV DAC, DSS fclk, CAM sensor clock, emul trace clk */
++/* Type: DPLL */
++static const struct dpll_data dpll4_dd = {
++ .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2),
++ .mult_mask = OMAP3430_PERIPH_DPLL_MULT_MASK,
++ .div1_mask = OMAP3430_PERIPH_DPLL_DIV_MASK,
++ .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
++ .enable_mask = OMAP3430_EN_PERIPH_DPLL_MASK,
++ .auto_recal_bit = OMAP3430_EN_PERIPH_DPLL_DRIFTGUARD_SHIFT,
++ .recal_en_bit = OMAP3430_PERIPH_DPLL_RECAL_EN_SHIFT,
++ .recal_st_bit = OMAP3430_PERIPH_DPLL_ST_SHIFT,
++};
++
++static struct clk dpll4_ck = {
++ .name = "dpll4_ck",
++ .parent = &sys_ck,
++ .dpll_data = &dpll4_dd,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++ .recalc = &omap3_dpll_recalc,
++};
++
++/*
++ * This virtual clock provides the CLKOUTX2 output from the DPLL if the
++ * DPLL isn't bypassed --
++ * XXX does this serve any downstream clocks?
++ */
++static struct clk dpll4_x2_ck = {
++ .name = "dpll4_x2_ck",
++ .parent = &dpll4_ck,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap3_clkoutx2_recalc,
++};
++
++static const struct clksel div16_dpll4_clksel[] = {
++ { .parent = &dpll4_ck, .rates = div16_dpll_rates },
++ { .parent = NULL }
++};
++
++/* This virtual clock is the source for dpll4_m2x2_ck */
++static struct clk dpll4_m2_ck = {
++ .name = "dpll4_m2_ck",
++ .parent = &dpll4_ck,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430_CM_CLKSEL3),
++ .clksel_mask = OMAP3430_DIV_96M_MASK,
++ .clksel = div16_dpll4_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++/* The PWRDN bit is apparently only available on 3430ES2 and above */
++static struct clk dpll4_m2x2_ck = {
++ .name = "dpll4_m2x2_ck",
++ .parent = &dpll4_m2_ck,
++ .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
++ .enable_bit = OMAP3430_PWRDN_96M_SHIFT,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
++ .recalc = &omap3_clkoutx2_recalc,
++};
++
++static const struct clksel omap_96m_alwon_fck_clksel[] = {
++ { .parent = &sys_ck, .rates = dpll_bypass_rates },
++ { .parent = &dpll4_m2x2_ck, .rates = dpll_locked_rates },
++ { .parent = NULL }
++};
++
++static struct clk omap_96m_alwon_fck = {
++ .name = "omap_96m_alwon_fck",
++ .parent = &dpll4_m2x2_ck,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
++ .clksel_mask = OMAP3430_ST_PERIPH_CLK,
++ .clksel = omap_96m_alwon_fck_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk omap_96m_fck = {
++ .name = "omap_96m_fck",
++ .parent = &omap_96m_alwon_fck,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &followparent_recalc,
++};
++
++static const struct clksel cm_96m_fck_clksel[] = {
++ { .parent = &sys_ck, .rates = dpll_bypass_rates },
++ { .parent = &dpll4_m2x2_ck, .rates = dpll_locked_rates },
++ { .parent = NULL }
++};
++
++static struct clk cm_96m_fck = {
++ .name = "cm_96m_fck",
++ .parent = &dpll4_m2x2_ck,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
++ .clksel_mask = OMAP3430_ST_PERIPH_CLK,
++ .clksel = cm_96m_fck_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++/* This virtual clock is the source for dpll4_m3x2_ck */
++static struct clk dpll4_m3_ck = {
++ .name = "dpll4_m3_ck",
++ .parent = &dpll4_ck,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP3430_CLKSEL_TV_MASK,
++ .clksel = div16_dpll4_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++/* The PWRDN bit is apparently only available on 3430ES2 and above */
++static struct clk dpll4_m3x2_ck = {
++ .name = "dpll4_m3x2_ck",
++ .parent = &dpll4_m3_ck,
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
++ .enable_bit = OMAP3430_PWRDN_TV_SHIFT,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
++ .recalc = &omap3_clkoutx2_recalc,
++};
++
++static const struct clksel virt_omap_54m_fck_clksel[] = {
++ { .parent = &sys_ck, .rates = dpll_bypass_rates },
++ { .parent = &dpll4_m3x2_ck, .rates = dpll_locked_rates },
++ { .parent = NULL }
++};
++
++static struct clk virt_omap_54m_fck = {
++ .name = "virt_omap_54m_fck",
++ .parent = &dpll4_m3x2_ck,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
++ .clksel_mask = OMAP3430_ST_PERIPH_CLK,
++ .clksel = virt_omap_54m_fck_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static const struct clksel_rate omap_54m_d4m3x2_rates[] = {
++ { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel_rate omap_54m_alt_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel omap_54m_clksel[] = {
++ { .parent = &virt_omap_54m_fck, .rates = omap_54m_d4m3x2_rates },
++ { .parent = &sys_altclk, .rates = omap_54m_alt_rates },
++ { .parent = NULL }
++};
++
++static struct clk omap_54m_fck = {
++ .name = "omap_54m_fck",
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
++ .clksel_mask = OMAP3430_SOURCE_54M,
++ .clksel = omap_54m_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static const struct clksel_rate omap_48m_96md2_rates[] = {
++ { .div = 2, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel_rate omap_48m_alt_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel omap_48m_clksel[] = {
++ { .parent = &cm_96m_fck, .rates = omap_48m_96md2_rates },
++ { .parent = &sys_altclk, .rates = omap_48m_alt_rates },
++ { .parent = NULL }
++};
++
++static struct clk omap_48m_fck = {
++ .name = "omap_48m_fck",
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
++ .clksel_mask = OMAP3430_SOURCE_48M,
++ .clksel = omap_48m_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk omap_12m_fck = {
++ .name = "omap_12m_fck",
++ .parent = &omap_48m_fck,
++ .fixed_div = 4,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_fixed_divisor_recalc,
++};
++
++/* This virstual clock is the source for dpll4_m4x2_ck */
++static struct clk dpll4_m4_ck = {
++ .name = "dpll4_m4_ck",
++ .parent = &dpll4_ck,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP3430_CLKSEL_DSS1_MASK,
++ .clksel = div16_dpll4_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++/* The PWRDN bit is apparently only available on 3430ES2 and above */
++static struct clk dpll4_m4x2_ck = {
++ .name = "dpll4_m4x2_ck",
++ .parent = &dpll4_m4_ck,
++ .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
++ .enable_bit = OMAP3430_PWRDN_CAM_SHIFT,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
++ .recalc = &omap3_clkoutx2_recalc,
++};
++
++/* This virtual clock is the source for dpll4_m5x2_ck */
++static struct clk dpll4_m5_ck = {
++ .name = "dpll4_m5_ck",
++ .parent = &dpll4_ck,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP3430_CLKSEL_CAM_MASK,
++ .clksel = div16_dpll4_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++/* The PWRDN bit is apparently only available on 3430ES2 and above */
++static struct clk dpll4_m5x2_ck = {
++ .name = "dpll4_m5x2_ck",
++ .parent = &dpll4_m5_ck,
++ .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
++ .enable_bit = OMAP3430_PWRDN_CAM_SHIFT,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
++ .recalc = &omap3_clkoutx2_recalc,
++};
++
++/* This virtual clock is the source for dpll4_m6x2_ck */
++static struct clk dpll4_m6_ck = {
++ .name = "dpll4_m6_ck",
++ .parent = &dpll4_ck,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
++ .clksel_mask = OMAP3430_DIV_DPLL4_MASK,
++ .clksel = div16_dpll4_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++/* The PWRDN bit is apparently only available on 3430ES2 and above */
++static struct clk dpll4_m6x2_ck = {
++ .name = "dpll4_m6x2_ck",
++ .parent = &dpll4_m6_ck,
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
++ .enable_bit = OMAP3430_PWRDN_EMU_PERIPH_SHIFT,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
++ .recalc = &omap3_clkoutx2_recalc,
++};
++
++static struct clk emu_per_alwon_ck = {
++ .name = "emu_per_alwon_ck",
++ .parent = &dpll4_m6x2_ck,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &followparent_recalc,
++};
++
++/* DPLL5 */
++/* Supplies 120MHz clock, USIM source clock */
++/* Type: DPLL */
++/* 3430ES2 only */
++static const struct dpll_data dpll5_dd = {
++ .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL4),
++ .mult_mask = OMAP3430ES2_PERIPH2_DPLL_MULT_MASK,
++ .div1_mask = OMAP3430ES2_PERIPH2_DPLL_DIV_MASK,
++ .control_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKEN2),
++ .enable_mask = OMAP3430ES2_EN_PERIPH2_DPLL_MASK,
++ .auto_recal_bit = OMAP3430ES2_EN_PERIPH2_DPLL_DRIFTGUARD_SHIFT,
++ .recal_en_bit = OMAP3430ES2_SND_PERIPH_DPLL_RECAL_EN_SHIFT,
++ .recal_st_bit = OMAP3430ES2_SND_PERIPH_DPLL_ST_SHIFT,
++};
++
++static struct clk dpll5_ck = {
++ .name = "dpll5_ck",
++ .parent = &sys_ck,
++ .dpll_data = &dpll5_dd,
++ .flags = CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES |
++ ALWAYS_ENABLED,
++ .recalc = &omap3_dpll_recalc,
++};
++
++static const struct clksel div16_dpll5_clksel[] = {
++ { .parent = &dpll5_ck, .rates = div16_dpll_rates },
++ { .parent = NULL }
++};
++
++static struct clk dpll5_m2_ck = {
++ .name = "dpll5_m2_ck",
++ .parent = &dpll5_ck,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL5),
++ .clksel_mask = OMAP3430ES2_DIV_120M_MASK,
++ .clksel = div16_dpll5_clksel,
++ .flags = CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static const struct clksel omap_120m_fck_clksel[] = {
++ { .parent = &sys_ck, .rates = dpll_bypass_rates },
++ { .parent = &dpll5_m2_ck, .rates = dpll_locked_rates },
++ { .parent = NULL }
++};
++
++static struct clk omap_120m_fck = {
++ .name = "omap_120m_fck",
++ .parent = &dpll5_m2_ck,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2),
++ .clksel_mask = OMAP3430ES2_ST_PERIPH2_CLK_MASK,
++ .clksel = omap_120m_fck_clksel,
++ .flags = CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++/* CM EXTERNAL CLOCK OUTPUTS */
++
++static const struct clksel_rate clkout2_src_core_rates[] = {
++ { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel_rate clkout2_src_sys_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel_rate clkout2_src_96m_rates[] = {
++ { .div = 1, .val = 2, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel_rate clkout2_src_54m_rates[] = {
++ { .div = 1, .val = 3, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel clkout2_src_clksel[] = {
++ { .parent = &core_ck, .rates = clkout2_src_core_rates },
++ { .parent = &sys_ck, .rates = clkout2_src_sys_rates },
++ { .parent = &omap_96m_alwon_fck, .rates = clkout2_src_96m_rates },
++ { .parent = &omap_54m_fck, .rates = clkout2_src_54m_rates },
++ { .parent = NULL }
++};
++
++static struct clk clkout2_src_ck = {
++ .name = "clkout2_src_ck",
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP3430_CM_CLKOUT_CTRL,
++ .enable_bit = OMAP3430_CLKOUT2_EN_SHIFT,
++ .clksel_reg = OMAP3430_CM_CLKOUT_CTRL,
++ .clksel_mask = OMAP3430_CLKOUT2SOURCE_MASK,
++ .clksel = clkout2_src_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static const struct clksel_rate sys_clkout2_rates[] = {
++ { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 2, .val = 1, .flags = RATE_IN_343X },
++ { .div = 4, .val = 2, .flags = RATE_IN_343X },
++ { .div = 8, .val = 3, .flags = RATE_IN_343X },
++ { .div = 16, .val = 4, .flags = RATE_IN_343X },
++ { .div = 0 },
++};
++
++static const struct clksel sys_clkout2_clksel[] = {
++ { .parent = &clkout2_src_ck, .rates = sys_clkout2_rates },
++ { .parent = NULL },
++};
++
++static struct clk sys_clkout2 = {
++ .name = "sys_clkout2",
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP3430_CM_CLKOUT_CTRL,
++ .clksel_mask = OMAP3430_CLKOUT2_DIV_MASK,
++ .clksel = sys_clkout2_clksel,
++ .flags = CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++/* CM OUTPUT CLOCKS */
++
++static struct clk corex2_fck = {
++ .name = "corex2_fck",
++ .parent = &dpll3_m2x2_ck,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &followparent_recalc,
++};
++
++/* DPLL power domain clock controls */
++
++static const struct clksel div2_core_clksel[] = {
++ { .parent = &core_ck, .rates = div2_rates },
++ { .parent = NULL }
++};
++
++/*
++ * REVISIT: Are these in DPLL power domain or CM power domain? docs
++ * may be inconsistent here?
++ */
++static struct clk dpll1_fck = {
++ .name = "dpll1_fck",
++ .parent = &core_ck,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL),
++ .clksel_mask = OMAP3430_MPU_CLK_SRC_MASK,
++ .clksel = div2_core_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++/*
++ * MPU clksel:
++ * If DPLL1 is locked, mpu_ck derives from DPLL1; otherwise, mpu_ck
++ * derives from the high-frequency bypass clock originating from DPLL3,
++ * called 'dpll1_fck'
++ */
++static const struct clksel mpu_clksel[] = {
++ { .parent = &dpll1_fck, .rates = dpll_bypass_rates },
++ { .parent = &dpll1_x2m2_ck, .rates = dpll_locked_rates },
++ { .parent = NULL }
++};
++
++static struct clk mpu_ck = {
++ .name = "mpu_ck",
++ .parent = &dpll1_x2m2_ck,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL),
++ .clksel_mask = OMAP3430_ST_MPU_CLK_MASK,
++ .clksel = mpu_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++/* arm_fck is divided by two when DPLL1 locked; otherwise, passthrough mpu_ck */
++static const struct clksel_rate arm_fck_rates[] = {
++ { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 2, .val = 1, .flags = RATE_IN_343X },
++ { .div = 0 },
++};
++
++static const struct clksel arm_fck_clksel[] = {
++ { .parent = &mpu_ck, .rates = arm_fck_rates },
++ { .parent = NULL }
++};
++
++static struct clk arm_fck = {
++ .name = "arm_fck",
++ .parent = &mpu_ck,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL),
++ .clksel_mask = OMAP3430_ST_MPU_CLK_MASK,
++ .clksel = arm_fck_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++/*
++ * REVISIT: This clock is never specifically defined in the 3430 TRM,
++ * although it is referenced - so this is a guess
++ */
++static struct clk emu_mpu_alwon_ck = {
++ .name = "emu_mpu_alwon_ck",
++ .parent = &mpu_ck,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk dpll2_fck = {
++ .name = "dpll2_fck",
++ .parent = &core_ck,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL),
++ .clksel_mask = OMAP3430_IVA2_CLK_SRC_MASK,
++ .clksel = div2_core_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++/*
++ * IVA2 clksel:
++ * If DPLL2 is locked, iva2_ck derives from DPLL2; otherwise, iva2_ck
++ * derives from the high-frequency bypass clock originating from DPLL3,
++ * called 'dpll2_fck'
++ */
++
++static const struct clksel iva2_clksel[] = {
++ { .parent = &dpll2_fck, .rates = dpll_bypass_rates },
++ { .parent = &dpll2_m2_ck, .rates = dpll_locked_rates },
++ { .parent = NULL }
++};
++
++static struct clk iva2_ck = {
++ .name = "iva2_ck",
++ .parent = &dpll2_m2_ck,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD,
++ OMAP3430_CM_IDLEST_PLL),
++ .clksel_mask = OMAP3430_ST_IVA2_CLK_MASK,
++ .clksel = iva2_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++/* Common interface clocks */
++
++static struct clk l3_ick = {
++ .name = "l3_ick",
++ .parent = &core_ck,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP3430_CLKSEL_L3_MASK,
++ .clksel = div2_core_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static const struct clksel div2_l3_clksel[] = {
++ { .parent = &l3_ick, .rates = div2_rates },
++ { .parent = NULL }
++};
++
++static struct clk l4_ick = {
++ .name = "l4_ick",
++ .parent = &l3_ick,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP3430_CLKSEL_L4_MASK,
++ .clksel = div2_l3_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++
++};
++
++static const struct clksel div2_l4_clksel[] = {
++ { .parent = &l4_ick, .rates = div2_rates },
++ { .parent = NULL }
++};
++
++static struct clk rm_ick = {
++ .name = "rm_ick",
++ .parent = &l4_ick,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP3430_CLKSEL_RM_MASK,
++ .clksel = div2_l4_clksel,
++ .flags = CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_clksel_recalc,
++};
++
++/* GFX power domain */
++
++/* GFX clocks are in 3430ES1 only. 3430ES2 and later uses the SGX instead */
++
++static const struct clksel gfx_l3_clksel[] = {
++ { .parent = &l3_ick, .rates = gfx_l3_rates },
++ { .parent = NULL }
++};
++
++static struct clk gfx_l3_fck = {
++ .name = "gfx_l3_fck",
++ .parent = &l3_ick,
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
++ .enable_bit = OMAP_EN_GFX_SHIFT,
++ .clksel_reg = OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP_CLKSEL_GFX_MASK,
++ .clksel = gfx_l3_clksel,
++ .flags = CLOCK_IN_OMAP3430ES1 | RATE_PROPAGATES,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk gfx_l3_ick = {
++ .name = "gfx_l3_ick",
++ .parent = &l3_ick,
++ .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
++ .enable_bit = OMAP_EN_GFX_SHIFT,
++ .flags = CLOCK_IN_OMAP3430ES1,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gfx_cg1_ck = {
++ .name = "gfx_cg1_ck",
++ .parent = &gfx_l3_fck, /* REVISIT: correct? */
++ .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430ES1_EN_2D_SHIFT,
++ .flags = CLOCK_IN_OMAP3430ES1,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gfx_cg2_ck = {
++ .name = "gfx_cg2_ck",
++ .parent = &gfx_l3_fck, /* REVISIT: correct? */
++ .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430ES1_EN_3D_SHIFT,
++ .flags = CLOCK_IN_OMAP3430ES1,
++ .recalc = &followparent_recalc,
++};
++
++/* SGX power domain - 3430ES2 only */
++
++static const struct clksel_rate sgx_core_rates[] = {
++ { .div = 3, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 4, .val = 1, .flags = RATE_IN_343X },
++ { .div = 6, .val = 2, .flags = RATE_IN_343X },
++ { .div = 0 },
++};
++
++static const struct clksel_rate sgx_96m_rates[] = {
++ { .div = 1, .val = 3, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 0 },
++};
++
++static const struct clksel sgx_clksel[] = {
++ { .parent = &core_ck, .rates = sgx_core_rates },
++ { .parent = &cm_96m_fck, .rates = sgx_96m_rates },
++ { .parent = NULL },
++};
++
++static struct clk sgx_fck = {
++ .name = "sgx_fck",
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430ES2_EN_SGX_SHIFT,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP3430ES2_CLKSEL_SGX_MASK,
++ .clksel = sgx_clksel,
++ .flags = CLOCK_IN_OMAP3430ES2,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk sgx_ick = {
++ .name = "sgx_ick",
++ .parent = &l3_ick,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430ES2_EN_SGX_SHIFT,
++ .flags = CLOCK_IN_OMAP3430ES2,
++ .recalc = &followparent_recalc,
++};
++
++/* CORE power domain */
++
++static struct clk d2d_26m_fck = {
++ .name = "d2d_26m_fck",
++ .parent = &sys_ck,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP3430ES1_EN_D2D_SHIFT,
++ .flags = CLOCK_IN_OMAP3430ES1,
++ .recalc = &followparent_recalc,
++};
++
++static const struct clksel omap343x_gpt_clksel[] = {
++ { .parent = &omap_32k_fck, .rates = gpt_32k_rates },
++ { .parent = &sys_ck, .rates = gpt_sys_rates },
++ { .parent = NULL}
++};
++
++static struct clk gpt10_fck = {
++ .name = "gpt10_fck",
++ .parent = &sys_ck,
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP3430_EN_GPT10_SHIFT,
++ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP3430_CLKSEL_GPT10_MASK,
++ .clksel = omap343x_gpt_clksel,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk gpt11_fck = {
++ .name = "gpt11_fck",
++ .parent = &sys_ck,
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP3430_EN_GPT11_SHIFT,
++ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP3430_CLKSEL_GPT11_MASK,
++ .clksel = omap343x_gpt_clksel,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk cpefuse_fck = {
++ .name = "cpefuse_fck",
++ .parent = &sys_ck,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
++ .enable_bit = OMAP3430ES2_EN_CPEFUSE_SHIFT,
++ .flags = CLOCK_IN_OMAP3430ES2,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk ts_fck = {
++ .name = "ts_fck",
++ .parent = &omap_32k_fck,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
++ .enable_bit = OMAP3430ES2_EN_TS_SHIFT,
++ .flags = CLOCK_IN_OMAP3430ES2,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk usbtll_fck = {
++ .name = "usbtll_fck",
++ .parent = &omap_120m_fck,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
++ .enable_bit = OMAP3430ES2_EN_USBTLL_SHIFT,
++ .flags = CLOCK_IN_OMAP3430ES2,
++ .recalc = &followparent_recalc,
++};
++
++/* CORE 96M FCLK-derived clocks */
++
++static struct clk core_96m_fck = {
++ .name = "core_96m_fck",
++ .parent = &omap_96m_fck,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mmchs3_fck = {
++ .name = "mmchs_fck",
++ .id = 3,
++ .parent = &core_96m_fck,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP3430ES2_EN_MMC3_SHIFT,
++ .flags = CLOCK_IN_OMAP3430ES2,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mmchs2_fck = {
++ .name = "mmchs_fck",
++ .id = 2,
++ .parent = &core_96m_fck,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP3430_EN_MMC2_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mspro_fck = {
++ .name = "mspro_fck",
++ .parent = &core_96m_fck,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP3430_EN_MSPRO_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mmchs1_fck = {
++ .name = "mmchs_fck",
++ .id = 1,
++ .parent = &core_96m_fck,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP3430_EN_MMC1_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk i2c3_fck = {
++ .name = "i2c_fck",
++ .id = 3,
++ .parent = &core_96m_fck,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP3430_EN_I2C3_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk i2c2_fck = {
++ .name = "i2c_fck",
++ .id = 2,
++ .parent = &core_96m_fck,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP3430_EN_I2C2_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk i2c1_fck = {
++ .name = "i2c_fck",
++ .id = 1,
++ .parent = &core_96m_fck,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP3430_EN_I2C1_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++/*
++ * MCBSP 1 & 5 get their 96MHz clock from core_96m_fck;
++ * MCBSP 2, 3, 4 get their 96MHz clock from per_96m_fck.
++ */
++static const struct clksel_rate common_mcbsp_96m_rates[] = {
++ { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 0 }
++};
++
++static const struct clksel mcbsp_15_clksel[] = {
++ { .parent = &core_96m_fck, .rates = common_mcbsp_96m_rates },
++ { .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates },
++ { .parent = NULL }
++};
++
++static struct clk mcbsp5_fck = {
++ .name = "mcbsp5_fck",
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP3430_EN_MCBSP5_SHIFT,
++ .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1),
++ .clksel_mask = OMAP2_MCBSP5_CLKS_MASK,
++ .clksel = mcbsp_15_clksel,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk mcbsp1_fck = {
++ .name = "mcbsp1_fck",
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP3430_EN_MCBSP1_SHIFT,
++ .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
++ .clksel_mask = OMAP2_MCBSP1_CLKS_MASK,
++ .clksel = mcbsp_15_clksel,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &omap2_clksel_recalc,
++};
++
++/* CORE_48M_FCK-derived clocks */
++
++static struct clk core_48m_fck = {
++ .name = "core_48m_fck",
++ .parent = &omap_48m_fck,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcspi4_fck = {
++ .name = "mcspi_fck",
++ .id = 4,
++ .parent = &core_48m_fck,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP3430_EN_MCSPI4_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcspi3_fck = {
++ .name = "mcspi_fck",
++ .id = 3,
++ .parent = &core_48m_fck,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP3430_EN_MCSPI3_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcspi2_fck = {
++ .name = "mcspi_fck",
++ .id = 2,
++ .parent = &core_48m_fck,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP3430_EN_MCSPI2_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcspi1_fck = {
++ .name = "mcspi_fck",
++ .id = 1,
++ .parent = &core_48m_fck,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP3430_EN_MCSPI1_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk uart2_fck = {
++ .name = "uart2_fck",
++ .parent = &core_48m_fck,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP3430_EN_UART2_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk uart1_fck = {
++ .name = "uart1_fck",
++ .parent = &core_48m_fck,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP3430_EN_UART1_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk fshostusb_fck = {
++ .name = "fshostusb_fck",
++ .parent = &core_48m_fck,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP3430ES1_EN_FSHOSTUSB_SHIFT,
++ .flags = CLOCK_IN_OMAP3430ES1,
++ .recalc = &followparent_recalc,
++};
++
++/* CORE_12M_FCK based clocks */
++
++static struct clk core_12m_fck = {
++ .name = "core_12m_fck",
++ .parent = &omap_12m_fck,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk hdq_fck = {
++ .name = "hdq_fck",
++ .parent = &core_12m_fck,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP3430_EN_HDQ_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++/* DPLL3-derived clock */
++
++static const struct clksel_rate ssi_ssr_corex2_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 2, .val = 2, .flags = RATE_IN_343X },
++ { .div = 3, .val = 3, .flags = RATE_IN_343X },
++ { .div = 4, .val = 4, .flags = RATE_IN_343X },
++ { .div = 6, .val = 6, .flags = RATE_IN_343X },
++ { .div = 8, .val = 8, .flags = RATE_IN_343X },
++ { .div = 0 }
++};
++
++static const struct clksel ssi_ssr_clksel[] = {
++ { .parent = &corex2_fck, .rates = ssi_ssr_corex2_rates },
++ { .parent = NULL }
++};
++
++static struct clk ssi_ssr_fck = {
++ .name = "ssi_ssr_fck",
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
++ .enable_bit = OMAP3430_EN_SSI_SHIFT,
++ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP3430_CLKSEL_SSI_MASK,
++ .clksel = ssi_ssr_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk ssi_sst_fck = {
++ .name = "ssi_sst_fck",
++ .parent = &ssi_ssr_fck,
++ .fixed_div = 2,
++ .flags = CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
++ .recalc = &omap2_fixed_divisor_recalc,
++};
++
++
++
++/* CORE_L3_ICK based clocks */
++
++static struct clk core_l3_ick = {
++ .name = "core_l3_ick",
++ .parent = &l3_ick,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk hsotgusb_ick = {
++ .name = "hsotgusb_ick",
++ .parent = &core_l3_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_HSOTGUSB_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk sdrc_ick = {
++ .name = "sdrc_ick",
++ .parent = &core_l3_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_SDRC_SHIFT,
++ .flags = CLOCK_IN_OMAP343X | ENABLE_ON_INIT,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpmc_fck = {
++ .name = "gpmc_fck",
++ .parent = &core_l3_ick,
++ .flags = CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK |
++ ENABLE_ON_INIT,
++ .recalc = &followparent_recalc,
++};
++
++/* SECURITY_L3_ICK based clocks */
++
++static struct clk security_l3_ick = {
++ .name = "security_l3_ick",
++ .parent = &l3_ick,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk pka_ick = {
++ .name = "pka_ick",
++ .parent = &security_l3_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++ .enable_bit = OMAP3430_EN_PKA_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++/* CORE_L4_ICK based clocks */
++
++static struct clk core_l4_ick = {
++ .name = "core_l4_ick",
++ .parent = &l4_ick,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk usbtll_ick = {
++ .name = "usbtll_ick",
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
++ .enable_bit = OMAP3430ES2_EN_USBTLL_SHIFT,
++ .flags = CLOCK_IN_OMAP3430ES2,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mmchs3_ick = {
++ .name = "mmchs_ick",
++ .id = 3,
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430ES2_EN_MMC3_SHIFT,
++ .flags = CLOCK_IN_OMAP3430ES2,
++ .recalc = &followparent_recalc,
++};
++
++/* Intersystem Communication Registers - chassis mode only */
++static struct clk icr_ick = {
++ .name = "icr_ick",
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_ICR_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk aes2_ick = {
++ .name = "aes2_ick",
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_AES2_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk sha12_ick = {
++ .name = "sha12_ick",
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_SHA12_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk des2_ick = {
++ .name = "des2_ick",
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_DES2_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mmchs2_ick = {
++ .name = "mmchs_ick",
++ .id = 2,
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_MMC2_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mmchs1_ick = {
++ .name = "mmchs_ick",
++ .id = 1,
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_MMC1_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mspro_ick = {
++ .name = "mspro_ick",
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_MSPRO_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk hdq_ick = {
++ .name = "hdq_ick",
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_HDQ_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcspi4_ick = {
++ .name = "mcspi_ick",
++ .id = 4,
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_MCSPI4_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcspi3_ick = {
++ .name = "mcspi_ick",
++ .id = 3,
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_MCSPI3_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcspi2_ick = {
++ .name = "mcspi_ick",
++ .id = 2,
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_MCSPI2_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcspi1_ick = {
++ .name = "mcspi_ick",
++ .id = 1,
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_MCSPI1_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk i2c3_ick = {
++ .name = "i2c_ick",
++ .id = 3,
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_I2C3_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk i2c2_ick = {
++ .name = "i2c_ick",
++ .id = 2,
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_I2C2_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk i2c1_ick = {
++ .name = "i2c_ick",
++ .id = 1,
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_I2C1_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk uart2_ick = {
++ .name = "uart2_ick",
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_UART2_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk uart1_ick = {
++ .name = "uart1_ick",
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_UART1_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt11_ick = {
++ .name = "gpt11_ick",
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_GPT11_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt10_ick = {
++ .name = "gpt10_ick",
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_GPT10_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcbsp5_ick = {
++ .name = "mcbsp5_ick",
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_MCBSP5_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcbsp1_ick = {
++ .name = "mcbsp1_ick",
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_MCBSP1_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk fac_ick = {
++ .name = "fac_ick",
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430ES1_EN_FAC_SHIFT,
++ .flags = CLOCK_IN_OMAP3430ES1,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mailboxes_ick = {
++ .name = "mailboxes_ick",
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_MAILBOXES_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk omapctrl_ick = {
++ .name = "omapctrl_ick",
++ .parent = &core_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_OMAPCTRL_SHIFT,
++ .flags = CLOCK_IN_OMAP343X | ENABLE_ON_INIT,
++ .recalc = &followparent_recalc,
++};
++
++/* SSI_L4_ICK based clocks */
++
++static struct clk ssi_l4_ick = {
++ .name = "ssi_l4_ick",
++ .parent = &l4_ick,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk ssi_ick = {
++ .name = "ssi_ick",
++ .parent = &ssi_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430_EN_SSI_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++/* REVISIT: Technically the TRM claims that this is CORE_CLK based,
++ * but l4_ick makes more sense to me */
++
++static const struct clksel usb_l4_clksel[] = {
++ { .parent = &l4_ick, .rates = div2_rates },
++ { .parent = NULL },
++};
++
++static struct clk usb_l4_ick = {
++ .name = "usb_l4_ick",
++ .parent = &l4_ick,
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
++ .enable_bit = OMAP3430ES1_EN_FSHOSTUSB_SHIFT,
++ .clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP3430ES1_CLKSEL_FSHOSTUSB_MASK,
++ .clksel = usb_l4_clksel,
++ .flags = CLOCK_IN_OMAP3430ES1,
++ .recalc = &omap2_clksel_recalc,
++};
++
++/* XXX MDM_INTC_ICK, SAD2D_ICK ?? */
++
++/* SECURITY_L4_ICK2 based clocks */
++
++static struct clk security_l4_ick2 = {
++ .name = "security_l4_ick2",
++ .parent = &l4_ick,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk aes1_ick = {
++ .name = "aes1_ick",
++ .parent = &security_l4_ick2,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++ .enable_bit = OMAP3430_EN_AES1_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk rng_ick = {
++ .name = "rng_ick",
++ .parent = &security_l4_ick2,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++ .enable_bit = OMAP3430_EN_RNG_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk sha11_ick = {
++ .name = "sha11_ick",
++ .parent = &security_l4_ick2,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++ .enable_bit = OMAP3430_EN_SHA11_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk des1_ick = {
++ .name = "des1_ick",
++ .parent = &security_l4_ick2,
++ .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
++ .enable_bit = OMAP3430_EN_DES1_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++/* DSS */
++static const struct clksel dss1_alwon_fck_clksel[] = {
++ { .parent = &sys_ck, .rates = dpll_bypass_rates },
++ { .parent = &dpll4_m4x2_ck, .rates = dpll_locked_rates },
++ { .parent = NULL }
++};
++
++static struct clk dss1_alwon_fck = {
++ .name = "dss1_alwon_fck",
++ .parent = &dpll4_m4x2_ck,
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_DSS1_SHIFT,
++ .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
++ .clksel_mask = OMAP3430_ST_PERIPH_CLK,
++ .clksel = dss1_alwon_fck_clksel,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk dss_tv_fck = {
++ .name = "dss_tv_fck",
++ .parent = &omap_54m_fck,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_TV_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk dss_96m_fck = {
++ .name = "dss_96m_fck",
++ .parent = &omap_96m_fck,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_TV_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk dss2_alwon_fck = {
++ .name = "dss2_alwon_fck",
++ .parent = &sys_ck,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_DSS2_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk dss_ick = {
++ /* Handles both L3 and L4 clocks */
++ .name = "dss_ick",
++ .parent = &l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++/* CAM */
++
++static const struct clksel cam_mclk_clksel[] = {
++ { .parent = &sys_ck, .rates = dpll_bypass_rates },
++ { .parent = &dpll4_m5x2_ck, .rates = dpll_locked_rates },
++ { .parent = NULL }
++};
++
++static struct clk cam_mclk = {
++ .name = "cam_mclk",
++ .parent = &dpll4_m5x2_ck,
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
++ .clksel_mask = OMAP3430_ST_PERIPH_CLK,
++ .clksel = cam_mclk_clksel,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_CAM_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk cam_l3_ick = {
++ .name = "cam_l3_ick",
++ .parent = &l3_ick,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_CAM_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk cam_l4_ick = {
++ .name = "cam_l4_ick",
++ .parent = &l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_CAM_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++/* USBHOST - 3430ES2 only */
++
++static struct clk usbhost_120m_fck = {
++ .name = "usbhost_120m_fck",
++ .parent = &omap_120m_fck,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430ES2_EN_USBHOST2_SHIFT,
++ .flags = CLOCK_IN_OMAP3430ES2,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk usbhost_48m_fck = {
++ .name = "usbhost_48m_fck",
++ .parent = &omap_48m_fck,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430ES2_EN_USBHOST1_SHIFT,
++ .flags = CLOCK_IN_OMAP3430ES2,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk usbhost_l3_ick = {
++ .name = "usbhost_l3_ick",
++ .parent = &l3_ick,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430ES2_EN_USBHOST_SHIFT,
++ .flags = CLOCK_IN_OMAP3430ES2,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk usbhost_l4_ick = {
++ .name = "usbhost_l4_ick",
++ .parent = &l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430ES2_EN_USBHOST_SHIFT,
++ .flags = CLOCK_IN_OMAP3430ES2,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk usbhost_sar_fck = {
++ .name = "usbhost_sar_fck",
++ .parent = &osc_sys_ck,
++ .enable_reg = OMAP_PRM_REGADDR(OMAP3430ES2_USBHOST_MOD, PM_PWSTCTRL),
++ .enable_bit = OMAP3430ES2_SAVEANDRESTORE_SHIFT,
++ .flags = CLOCK_IN_OMAP3430ES2,
++ .recalc = &followparent_recalc,
++};
++
++/* WKUP */
++
++static const struct clksel_rate usim_96m_rates[] = {
++ { .div = 2, .val = 3, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 4, .val = 4, .flags = RATE_IN_343X },
++ { .div = 8, .val = 5, .flags = RATE_IN_343X },
++ { .div = 10, .val = 6, .flags = RATE_IN_343X },
++ { .div = 0 },
++};
++
++static const struct clksel_rate usim_120m_rates[] = {
++ { .div = 4, .val = 7, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 8, .val = 8, .flags = RATE_IN_343X },
++ { .div = 16, .val = 9, .flags = RATE_IN_343X },
++ { .div = 20, .val = 10, .flags = RATE_IN_343X },
++ { .div = 0 },
++};
++
++static const struct clksel usim_clksel[] = {
++ { .parent = &omap_96m_fck, .rates = usim_96m_rates },
++ { .parent = &omap_120m_fck, .rates = usim_120m_rates },
++ { .parent = &sys_ck, .rates = div2_rates },
++ { .parent = NULL },
++};
++
++/* 3430ES2 only */
++static struct clk usim_fck = {
++ .name = "usim_fck",
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430ES2_EN_USIMOCP_SHIFT,
++ .clksel_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP3430ES2_CLKSEL_USIMOCP_MASK,
++ .clksel = usim_clksel,
++ .flags = CLOCK_IN_OMAP3430ES2,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk gpt1_fck = {
++ .name = "gpt1_fck",
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_GPT1_SHIFT,
++ .clksel_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP3430_CLKSEL_GPT1_MASK,
++ .clksel = omap343x_gpt_clksel,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk wkup_32k_fck = {
++ .name = "wkup_32k_fck",
++ .parent = &omap_32k_fck,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpio1_fck = {
++ .name = "gpio1_fck",
++ .parent = &wkup_32k_fck,
++ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_GPIO1_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk wdt2_fck = {
++ .name = "wdt2_fck",
++ .parent = &wkup_32k_fck,
++ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_WDT2_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk wkup_l4_ick = {
++ .name = "wkup_l4_ick",
++ .parent = &sys_ck,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++ .recalc = &followparent_recalc,
++};
++
++/* 3430ES2 only */
++/* Never specifically named in the TRM, so we have to infer a likely name */
++static struct clk usim_ick = {
++ .name = "usim_ick",
++ .parent = &wkup_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430ES2_EN_USIMOCP_SHIFT,
++ .flags = CLOCK_IN_OMAP3430ES2,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk wdt2_ick = {
++ .name = "wdt2_ick",
++ .parent = &wkup_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_WDT2_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk wdt1_ick = {
++ .name = "wdt1_ick",
++ .parent = &wkup_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_WDT1_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpio1_ick = {
++ .name = "gpio1_ick",
++ .parent = &wkup_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_GPIO1_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk omap_32ksync_ick = {
++ .name = "omap_32ksync_ick",
++ .parent = &wkup_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_32KSYNC_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt12_ick = {
++ .name = "gpt12_ick",
++ .parent = &wkup_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_GPT12_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt1_ick = {
++ .name = "gpt1_ick",
++ .parent = &wkup_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_GPT1_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++
++
++/* PER clock domain */
++
++static struct clk per_96m_fck = {
++ .name = "per_96m_fck",
++ .parent = &omap_96m_alwon_fck,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk per_48m_fck = {
++ .name = "per_48m_fck",
++ .parent = &omap_48m_fck,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk uart3_fck = {
++ .name = "uart3_fck",
++ .parent = &per_48m_fck,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_UART3_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt2_fck = {
++ .name = "gpt2_fck",
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_GPT2_SHIFT,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP3430_CLKSEL_GPT2_MASK,
++ .clksel = omap343x_gpt_clksel,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk gpt3_fck = {
++ .name = "gpt3_fck",
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_GPT3_SHIFT,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP3430_CLKSEL_GPT3_MASK,
++ .clksel = omap343x_gpt_clksel,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk gpt4_fck = {
++ .name = "gpt4_fck",
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_GPT4_SHIFT,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP3430_CLKSEL_GPT4_MASK,
++ .clksel = omap343x_gpt_clksel,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk gpt5_fck = {
++ .name = "gpt5_fck",
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_GPT5_SHIFT,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP3430_CLKSEL_GPT5_MASK,
++ .clksel = omap343x_gpt_clksel,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk gpt6_fck = {
++ .name = "gpt6_fck",
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_GPT6_SHIFT,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP3430_CLKSEL_GPT6_MASK,
++ .clksel = omap343x_gpt_clksel,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk gpt7_fck = {
++ .name = "gpt7_fck",
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_GPT7_SHIFT,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP3430_CLKSEL_GPT7_MASK,
++ .clksel = omap343x_gpt_clksel,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk gpt8_fck = {
++ .name = "gpt8_fck",
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_GPT8_SHIFT,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP3430_CLKSEL_GPT8_MASK,
++ .clksel = omap343x_gpt_clksel,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk gpt9_fck = {
++ .name = "gpt9_fck",
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_GPT9_SHIFT,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
++ .clksel_mask = OMAP3430_CLKSEL_GPT9_MASK,
++ .clksel = omap343x_gpt_clksel,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk per_32k_alwon_fck = {
++ .name = "per_32k_alwon_fck",
++ .parent = &omap_32k_fck,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpio6_fck = {
++ .name = "gpio6_fck",
++ .parent = &per_32k_alwon_fck,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_GPT6_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpio5_fck = {
++ .name = "gpio5_fck",
++ .parent = &per_32k_alwon_fck,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_GPT5_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpio4_fck = {
++ .name = "gpio4_fck",
++ .parent = &per_32k_alwon_fck,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_GPT4_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpio3_fck = {
++ .name = "gpio3_fck",
++ .parent = &per_32k_alwon_fck,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_GPT3_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpio2_fck = {
++ .name = "gpio2_fck",
++ .parent = &per_32k_alwon_fck,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_GPT2_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk wdt3_fck = {
++ .name = "wdt3_fck",
++ .parent = &per_32k_alwon_fck,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_WDT3_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk per_l4_ick = {
++ .name = "per_l4_ick",
++ .parent = &l4_ick,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
++ PARENT_CONTROLS_CLOCK,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpio6_ick = {
++ .name = "gpio6_ick",
++ .parent = &per_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_GPIO6_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpio5_ick = {
++ .name = "gpio5_ick",
++ .parent = &per_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_GPIO5_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpio4_ick = {
++ .name = "gpio4_ick",
++ .parent = &per_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_GPIO4_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpio3_ick = {
++ .name = "gpio3_ick",
++ .parent = &per_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_GPIO3_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpio2_ick = {
++ .name = "gpio2_ick",
++ .parent = &per_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_GPIO2_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk wdt3_ick = {
++ .name = "wdt3_ick",
++ .parent = &per_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_WDT3_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk uart3_ick = {
++ .name = "uart3_ick",
++ .parent = &per_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_UART3_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt9_ick = {
++ .name = "gpt9_ick",
++ .parent = &per_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_GPT9_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt8_ick = {
++ .name = "gpt8_ick",
++ .parent = &per_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_GPT8_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt7_ick = {
++ .name = "gpt7_ick",
++ .parent = &per_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_GPT7_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt6_ick = {
++ .name = "gpt6_ick",
++ .parent = &per_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_GPT6_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt5_ick = {
++ .name = "gpt5_ick",
++ .parent = &per_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_GPT5_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt4_ick = {
++ .name = "gpt4_ick",
++ .parent = &per_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_GPT4_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt3_ick = {
++ .name = "gpt3_ick",
++ .parent = &per_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_GPT3_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk gpt2_ick = {
++ .name = "gpt2_ick",
++ .parent = &per_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_GPT2_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcbsp2_ick = {
++ .name = "mcbsp2_ick",
++ .parent = &per_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_MCBSP2_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcbsp3_ick = {
++ .name = "mcbsp3_ick",
++ .parent = &per_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_MCBSP3_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk mcbsp4_ick = {
++ .name = "mcbsp4_ick",
++ .parent = &per_l4_ick,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
++ .enable_bit = OMAP3430_EN_MCBSP4_SHIFT,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++static const struct clksel mcbsp_234_clksel[] = {
++ { .parent = &per_96m_fck, .rates = common_mcbsp_96m_rates },
++ { .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates },
++ { .parent = NULL }
++};
++
++static struct clk mcbsp2_fck = {
++ .name = "mcbsp2_fck",
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_MCBSP2_SHIFT,
++ .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
++ .clksel_mask = OMAP2_MCBSP2_CLKS_MASK,
++ .clksel = mcbsp_234_clksel,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk mcbsp3_fck = {
++ .name = "mcbsp3_fck",
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_MCBSP3_SHIFT,
++ .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1),
++ .clksel_mask = OMAP2_MCBSP3_CLKS_MASK,
++ .clksel = mcbsp_234_clksel,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk mcbsp4_fck = {
++ .name = "mcbsp4_fck",
++ .init = &omap2_init_clksel_parent,
++ .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_MCBSP4_SHIFT,
++ .clksel_reg = OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1),
++ .clksel_mask = OMAP2_MCBSP4_CLKS_MASK,
++ .clksel = mcbsp_234_clksel,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &omap2_clksel_recalc,
++};
++
++/* EMU clocks */
++
++/* More information: ARM Cortex-A8 Technical Reference Manual, sect 10.1 */
++
++static const struct clksel_rate emu_src_sys_rates[] = {
++ { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 0 },
++};
++
++static const struct clksel_rate emu_src_core_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 0 },
++};
++
++static const struct clksel_rate emu_src_per_rates[] = {
++ { .div = 1, .val = 2, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 0 },
++};
++
++static const struct clksel_rate emu_src_mpu_rates[] = {
++ { .div = 1, .val = 3, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 0 },
++};
++
++static const struct clksel emu_src_clksel[] = {
++ { .parent = &sys_ck, .rates = emu_src_sys_rates },
++ { .parent = &emu_core_alwon_ck, .rates = emu_src_core_rates },
++ { .parent = &emu_per_alwon_ck, .rates = emu_src_per_rates },
++ { .parent = &emu_mpu_alwon_ck, .rates = emu_src_mpu_rates },
++ { .parent = NULL },
++};
++
++/*
++ * Like the clkout_src clocks, emu_src_clk is a virtual clock, existing only
++ * to switch the source of some of the EMU clocks.
++ * XXX Are there CLKEN bits for these EMU clks?
++ */
++static struct clk emu_src_ck = {
++ .name = "emu_src_ck",
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
++ .clksel_mask = OMAP3430_MUX_CTRL_MASK,
++ .clksel = emu_src_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static const struct clksel_rate pclk_emu_rates[] = {
++ { .div = 2, .val = 2, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 3, .val = 3, .flags = RATE_IN_343X },
++ { .div = 4, .val = 4, .flags = RATE_IN_343X },
++ { .div = 6, .val = 6, .flags = RATE_IN_343X },
++ { .div = 0 },
++};
++
++static const struct clksel pclk_emu_clksel[] = {
++ { .parent = &emu_src_ck, .rates = pclk_emu_rates },
++ { .parent = NULL },
++};
++
++static struct clk pclk_fck = {
++ .name = "pclk_fck",
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
++ .clksel_mask = OMAP3430_CLKSEL_PCLK_MASK,
++ .clksel = pclk_emu_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static const struct clksel_rate pclkx2_emu_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 2, .val = 2, .flags = RATE_IN_343X },
++ { .div = 3, .val = 3, .flags = RATE_IN_343X },
++ { .div = 0 },
++};
++
++static const struct clksel pclkx2_emu_clksel[] = {
++ { .parent = &emu_src_ck, .rates = pclkx2_emu_rates },
++ { .parent = NULL },
++};
++
++static struct clk pclkx2_fck = {
++ .name = "pclkx2_fck",
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
++ .clksel_mask = OMAP3430_CLKSEL_PCLKX2_MASK,
++ .clksel = pclkx2_emu_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static const struct clksel atclk_emu_clksel[] = {
++ { .parent = &emu_src_ck, .rates = div2_rates },
++ { .parent = NULL },
++};
++
++static struct clk atclk_fck = {
++ .name = "atclk_fck",
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
++ .clksel_mask = OMAP3430_CLKSEL_ATCLK_MASK,
++ .clksel = atclk_emu_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static struct clk traceclk_src_fck = {
++ .name = "traceclk_src_fck",
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
++ .clksel_mask = OMAP3430_TRACE_MUX_CTRL_MASK,
++ .clksel = emu_src_clksel,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
++ .recalc = &omap2_clksel_recalc,
++};
++
++static const struct clksel_rate traceclk_rates[] = {
++ { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
++ { .div = 2, .val = 2, .flags = RATE_IN_343X },
++ { .div = 4, .val = 4, .flags = RATE_IN_343X },
++ { .div = 0 },
++};
++
++static const struct clksel traceclk_clksel[] = {
++ { .parent = &traceclk_src_fck, .rates = traceclk_rates },
++ { .parent = NULL },
++};
++
++static struct clk traceclk_fck = {
++ .name = "traceclk_fck",
++ .init = &omap2_init_clksel_parent,
++ .clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
++ .clksel_mask = OMAP3430_CLKSEL_TRACECLK_MASK,
++ .clksel = traceclk_clksel,
++ .flags = CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
++ .recalc = &omap2_clksel_recalc,
++};
++
++/* SR clocks */
++
++/* SmartReflex fclk (VDD1) */
++static struct clk sr1_fck = {
++ .name = "sr1_fck",
++ .parent = &sys_ck,
++ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_SR1_SHIFT,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES,
++ .recalc = &followparent_recalc,
++};
++
++/* SmartReflex fclk (VDD2) */
++static struct clk sr2_fck = {
++ .name = "sr2_fck",
++ .parent = &sys_ck,
++ .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
++ .enable_bit = OMAP3430_EN_SR2_SHIFT,
++ .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk sr_l4_ick = {
++ .name = "sr_l4_ick",
++ .parent = &l4_ick,
++ .flags = CLOCK_IN_OMAP343X,
++ .recalc = &followparent_recalc,
++};
++
++/* SECURE_32K_FCK clocks */
++
++static struct clk gpt12_fck = {
++ .name = "gpt12_fck",
++ .parent = &secure_32k_fck,
++ .flags = CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk wdt1_fck = {
++ .name = "wdt1_fck",
++ .parent = &secure_32k_fck,
++ .flags = CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
++ .recalc = &followparent_recalc,
++};
++
++static struct clk *onchip_34xx_clks[] __initdata = {
++ &omap_32k_fck,
++ &virt_12m_ck,
++ &virt_13m_ck,
++ &virt_16_8m_ck,
++ &virt_19_2m_ck,
++ &virt_26m_ck,
++ &virt_38_4m_ck,
++ &osc_sys_ck,
++ &sys_ck,
++ &sys_altclk,
++ &mcbsp_clks,
++ &sys_clkout1,
++ &dpll1_ck,
++ &dpll1_x2_ck,
++ &dpll1_x2m2_ck,
++ &dpll2_ck,
++ &dpll2_m2_ck,
++ &dpll3_ck,
++ &core_ck,
++ &dpll3_x2_ck,
++ &dpll3_m2_ck,
++ &dpll3_m2x2_ck,
++ &dpll3_m3_ck,
++ &dpll3_m3x2_ck,
++ &emu_core_alwon_ck,
++ &dpll4_ck,
++ &dpll4_x2_ck,
++ &omap_96m_alwon_fck,
++ &omap_96m_fck,
++ &cm_96m_fck,
++ &virt_omap_54m_fck,
++ &omap_54m_fck,
++ &omap_48m_fck,
++ &omap_12m_fck,
++ &dpll4_m2_ck,
++ &dpll4_m2x2_ck,
++ &dpll4_m3_ck,
++ &dpll4_m3x2_ck,
++ &dpll4_m4_ck,
++ &dpll4_m4x2_ck,
++ &dpll4_m5_ck,
++ &dpll4_m5x2_ck,
++ &dpll4_m6_ck,
++ &dpll4_m6x2_ck,
++ &emu_per_alwon_ck,
++ &dpll5_ck,
++ &dpll5_m2_ck,
++ &omap_120m_fck,
++ &clkout2_src_ck,
++ &sys_clkout2,
++ &corex2_fck,
++ &dpll1_fck,
++ &mpu_ck,
++ &arm_fck,
++ &emu_mpu_alwon_ck,
++ &dpll2_fck,
++ &iva2_ck,
++ &l3_ick,
++ &l4_ick,
++ &rm_ick,
++ &gfx_l3_fck,
++ &gfx_l3_ick,
++ &gfx_cg1_ck,
++ &gfx_cg2_ck,
++ &sgx_fck,
++ &sgx_ick,
++ &d2d_26m_fck,
++ &gpt10_fck,
++ &gpt11_fck,
++ &cpefuse_fck,
++ &ts_fck,
++ &usbtll_fck,
++ &core_96m_fck,
++ &mmchs3_fck,
++ &mmchs2_fck,
++ &mspro_fck,
++ &mmchs1_fck,
++ &i2c3_fck,
++ &i2c2_fck,
++ &i2c1_fck,
++ &mcbsp5_fck,
++ &mcbsp1_fck,
++ &core_48m_fck,
++ &mcspi4_fck,
++ &mcspi3_fck,
++ &mcspi2_fck,
++ &mcspi1_fck,
++ &uart2_fck,
++ &uart1_fck,
++ &fshostusb_fck,
++ &core_12m_fck,
++ &hdq_fck,
++ &ssi_ssr_fck,
++ &ssi_sst_fck,
++ &core_l3_ick,
++ &hsotgusb_ick,
++ &sdrc_ick,
++ &gpmc_fck,
++ &security_l3_ick,
++ &pka_ick,
++ &core_l4_ick,
++ &usbtll_ick,
++ &mmchs3_ick,
++ &icr_ick,
++ &aes2_ick,
++ &sha12_ick,
++ &des2_ick,
++ &mmchs2_ick,
++ &mmchs1_ick,
++ &mspro_ick,
++ &hdq_ick,
++ &mcspi4_ick,
++ &mcspi3_ick,
++ &mcspi2_ick,
++ &mcspi1_ick,
++ &i2c3_ick,
++ &i2c2_ick,
++ &i2c1_ick,
++ &uart2_ick,
++ &uart1_ick,
++ &gpt11_ick,
++ &gpt10_ick,
++ &mcbsp5_ick,
++ &mcbsp1_ick,
++ &fac_ick,
++ &mailboxes_ick,
++ &omapctrl_ick,
++ &ssi_l4_ick,
++ &ssi_ick,
++ &usb_l4_ick,
++ &security_l4_ick2,
++ &aes1_ick,
++ &rng_ick,
++ &sha11_ick,
++ &des1_ick,
++ &dss1_alwon_fck,
++ &dss_tv_fck,
++ &dss_96m_fck,
++ &dss2_alwon_fck,
++ &dss_ick,
++ &cam_mclk,
++ &cam_l3_ick,
++ &cam_l4_ick,
++ &usbhost_120m_fck,
++ &usbhost_48m_fck,
++ &usbhost_l3_ick,
++ &usbhost_l4_ick,
++ &usbhost_sar_fck,
++ &usim_fck,
++ &gpt1_fck,
++ &wkup_32k_fck,
++ &gpio1_fck,
++ &wdt2_fck,
++ &wkup_l4_ick,
++ &usim_ick,
++ &wdt2_ick,
++ &wdt1_ick,
++ &gpio1_ick,
++ &omap_32ksync_ick,
++ &gpt12_ick,
++ &gpt1_ick,
++ &per_96m_fck,
++ &per_48m_fck,
++ &uart3_fck,
++ &gpt2_fck,
++ &gpt3_fck,
++ &gpt4_fck,
++ &gpt5_fck,
++ &gpt6_fck,
++ &gpt7_fck,
++ &gpt8_fck,
++ &gpt9_fck,
++ &per_32k_alwon_fck,
++ &gpio6_fck,
++ &gpio5_fck,
++ &gpio4_fck,
++ &gpio3_fck,
++ &gpio2_fck,
++ &wdt3_fck,
++ &per_l4_ick,
++ &gpio6_ick,
++ &gpio5_ick,
++ &gpio4_ick,
++ &gpio3_ick,
++ &gpio2_ick,
++ &wdt3_ick,
++ &uart3_ick,
++ &gpt9_ick,
++ &gpt8_ick,
++ &gpt7_ick,
++ &gpt6_ick,
++ &gpt5_ick,
++ &gpt4_ick,
++ &gpt3_ick,
++ &gpt2_ick,
++ &mcbsp2_ick,
++ &mcbsp3_ick,
++ &mcbsp4_ick,
++ &mcbsp2_fck,
++ &mcbsp3_fck,
++ &mcbsp4_fck,
++ &emu_src_ck,
++ &pclk_fck,
++ &pclkx2_fck,
++ &atclk_fck,
++ &traceclk_src_fck,
++ &traceclk_fck,
++ &sr1_fck,
++ &sr2_fck,
++ &sr_l4_ick,
++ &secure_32k_fck,
++ &gpt12_fck,
++ &wdt1_fck,
++};
++
++#endif
+diff --git a/arch/arm/mach-omap2/cm-regbits-24xx.h b/arch/arm/mach-omap2/cm-regbits-24xx.h
+new file mode 100644
+index 0000000..20ac381
+--- /dev/null
++++ b/arch/arm/mach-omap2/cm-regbits-24xx.h
+@@ -0,0 +1,401 @@
++#ifndef __ARCH_ARM_MACH_OMAP2_CM_REGBITS_24XX_H
++#define __ARCH_ARM_MACH_OMAP2_CM_REGBITS_24XX_H
++
++/*
++ * OMAP24XX Clock Management register bits
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ * Copyright (C) 2007 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "cm.h"
++
++/* Bits shared between registers */
++
++/* CM_FCLKEN1_CORE and CM_ICLKEN1_CORE shared bits */
++#define OMAP24XX_EN_CAM_SHIFT 31
++#define OMAP24XX_EN_CAM (1 << 31)
++#define OMAP24XX_EN_WDT4_SHIFT 29
++#define OMAP24XX_EN_WDT4 (1 << 29)
++#define OMAP2420_EN_WDT3_SHIFT 28
++#define OMAP2420_EN_WDT3 (1 << 28)
++#define OMAP24XX_EN_MSPRO_SHIFT 27
++#define OMAP24XX_EN_MSPRO (1 << 27)
++#define OMAP24XX_EN_FAC_SHIFT 25
++#define OMAP24XX_EN_FAC (1 << 25)
++#define OMAP2420_EN_EAC_SHIFT 24
++#define OMAP2420_EN_EAC (1 << 24)
++#define OMAP24XX_EN_HDQ_SHIFT 23
++#define OMAP24XX_EN_HDQ (1 << 23)
++#define OMAP2420_EN_I2C2_SHIFT 20
++#define OMAP2420_EN_I2C2 (1 << 20)
++#define OMAP2420_EN_I2C1_SHIFT 19
++#define OMAP2420_EN_I2C1 (1 << 19)
++
++/* CM_FCLKEN2_CORE and CM_ICLKEN2_CORE shared bits */
++#define OMAP2430_EN_MCBSP5_SHIFT 5
++#define OMAP2430_EN_MCBSP5 (1 << 5)
++#define OMAP2430_EN_MCBSP4_SHIFT 4
++#define OMAP2430_EN_MCBSP4 (1 << 4)
++#define OMAP2430_EN_MCBSP3_SHIFT 3
++#define OMAP2430_EN_MCBSP3 (1 << 3)
++#define OMAP24XX_EN_SSI_SHIFT 1
++#define OMAP24XX_EN_SSI (1 << 1)
++
++/* CM_FCLKEN_WKUP and CM_ICLKEN_WKUP shared bits */
++#define OMAP24XX_EN_MPU_WDT_SHIFT 3
++#define OMAP24XX_EN_MPU_WDT (1 << 3)
++
++/* Bits specific to each register */
++
++/* CM_IDLEST_MPU */
++/* 2430 only */
++#define OMAP2430_ST_MPU (1 << 0)
++
++/* CM_CLKSEL_MPU */
++#define OMAP24XX_CLKSEL_MPU_SHIFT 0
++#define OMAP24XX_CLKSEL_MPU_MASK (0x1f << 0)
++
++/* CM_CLKSTCTRL_MPU */
++#define OMAP24XX_AUTOSTATE_MPU (1 << 0)
++
++/* CM_FCLKEN1_CORE specific bits*/
++#define OMAP24XX_EN_TV_SHIFT 2
++#define OMAP24XX_EN_TV (1 << 2)
++#define OMAP24XX_EN_DSS2_SHIFT 1
++#define OMAP24XX_EN_DSS2 (1 << 1)
++#define OMAP24XX_EN_DSS1_SHIFT 0
++#define OMAP24XX_EN_DSS1 (1 << 0)
++
++/* CM_FCLKEN2_CORE specific bits */
++#define OMAP2430_EN_I2CHS2_SHIFT 20
++#define OMAP2430_EN_I2CHS2 (1 << 20)
++#define OMAP2430_EN_I2CHS1_SHIFT 19
++#define OMAP2430_EN_I2CHS1 (1 << 19)
++#define OMAP2430_EN_MMCHSDB2_SHIFT 17
++#define OMAP2430_EN_MMCHSDB2 (1 << 17)
++#define OMAP2430_EN_MMCHSDB1_SHIFT 16
++#define OMAP2430_EN_MMCHSDB1 (1 << 16)
++
++/* CM_ICLKEN1_CORE specific bits */
++#define OMAP24XX_EN_MAILBOXES_SHIFT 30
++#define OMAP24XX_EN_MAILBOXES (1 << 30)
++#define OMAP24XX_EN_DSS_SHIFT 0
++#define OMAP24XX_EN_DSS (1 << 0)
++
++/* CM_ICLKEN2_CORE specific bits */
++
++/* CM_ICLKEN3_CORE */
++/* 2430 only */
++#define OMAP2430_EN_SDRC_SHIFT 2
++#define OMAP2430_EN_SDRC (1 << 2)
++
++/* CM_ICLKEN4_CORE */
++#define OMAP24XX_EN_PKA_SHIFT 4
++#define OMAP24XX_EN_PKA (1 << 4)
++#define OMAP24XX_EN_AES_SHIFT 3
++#define OMAP24XX_EN_AES (1 << 3)
++#define OMAP24XX_EN_RNG_SHIFT 2
++#define OMAP24XX_EN_RNG (1 << 2)
++#define OMAP24XX_EN_SHA_SHIFT 1
++#define OMAP24XX_EN_SHA (1 << 1)
++#define OMAP24XX_EN_DES_SHIFT 0
++#define OMAP24XX_EN_DES (1 << 0)
++
++/* CM_IDLEST1_CORE specific bits */
++#define OMAP24XX_ST_MAILBOXES (1 << 30)
++#define OMAP24XX_ST_WDT4 (1 << 29)
++#define OMAP2420_ST_WDT3 (1 << 28)
++#define OMAP24XX_ST_MSPRO (1 << 27)
++#define OMAP24XX_ST_FAC (1 << 25)
++#define OMAP2420_ST_EAC (1 << 24)
++#define OMAP24XX_ST_HDQ (1 << 23)
++#define OMAP24XX_ST_I2C2 (1 << 20)
++#define OMAP24XX_ST_I2C1 (1 << 19)
++#define OMAP24XX_ST_MCBSP2 (1 << 16)
++#define OMAP24XX_ST_MCBSP1 (1 << 15)
++#define OMAP24XX_ST_DSS (1 << 0)
++
++/* CM_IDLEST2_CORE */
++#define OMAP2430_ST_MCBSP5 (1 << 5)
++#define OMAP2430_ST_MCBSP4 (1 << 4)
++#define OMAP2430_ST_MCBSP3 (1 << 3)
++#define OMAP24XX_ST_SSI (1 << 1)
++
++/* CM_IDLEST3_CORE */
++/* 2430 only */
++#define OMAP2430_ST_SDRC (1 << 2)
++
++/* CM_IDLEST4_CORE */
++#define OMAP24XX_ST_PKA (1 << 4)
++#define OMAP24XX_ST_AES (1 << 3)
++#define OMAP24XX_ST_RNG (1 << 2)
++#define OMAP24XX_ST_SHA (1 << 1)
++#define OMAP24XX_ST_DES (1 << 0)
++
++/* CM_AUTOIDLE1_CORE */
++#define OMAP24XX_AUTO_CAM (1 << 31)
++#define OMAP24XX_AUTO_MAILBOXES (1 << 30)
++#define OMAP24XX_AUTO_WDT4 (1 << 29)
++#define OMAP2420_AUTO_WDT3 (1 << 28)
++#define OMAP24XX_AUTO_MSPRO (1 << 27)
++#define OMAP2420_AUTO_MMC (1 << 26)
++#define OMAP24XX_AUTO_FAC (1 << 25)
++#define OMAP2420_AUTO_EAC (1 << 24)
++#define OMAP24XX_AUTO_HDQ (1 << 23)
++#define OMAP24XX_AUTO_UART2 (1 << 22)
++#define OMAP24XX_AUTO_UART1 (1 << 21)
++#define OMAP24XX_AUTO_I2C2 (1 << 20)
++#define OMAP24XX_AUTO_I2C1 (1 << 19)
++#define OMAP24XX_AUTO_MCSPI2 (1 << 18)
++#define OMAP24XX_AUTO_MCSPI1 (1 << 17)
++#define OMAP24XX_AUTO_MCBSP2 (1 << 16)
++#define OMAP24XX_AUTO_MCBSP1 (1 << 15)
++#define OMAP24XX_AUTO_GPT12 (1 << 14)
++#define OMAP24XX_AUTO_GPT11 (1 << 13)
++#define OMAP24XX_AUTO_GPT10 (1 << 12)
++#define OMAP24XX_AUTO_GPT9 (1 << 11)
++#define OMAP24XX_AUTO_GPT8 (1 << 10)
++#define OMAP24XX_AUTO_GPT7 (1 << 9)
++#define OMAP24XX_AUTO_GPT6 (1 << 8)
++#define OMAP24XX_AUTO_GPT5 (1 << 7)
++#define OMAP24XX_AUTO_GPT4 (1 << 6)
++#define OMAP24XX_AUTO_GPT3 (1 << 5)
++#define OMAP24XX_AUTO_GPT2 (1 << 4)
++#define OMAP2420_AUTO_VLYNQ (1 << 3)
++#define OMAP24XX_AUTO_DSS (1 << 0)
++
++/* CM_AUTOIDLE2_CORE */
++#define OMAP2430_AUTO_MDM_INTC (1 << 11)
++#define OMAP2430_AUTO_GPIO5 (1 << 10)
++#define OMAP2430_AUTO_MCSPI3 (1 << 9)
++#define OMAP2430_AUTO_MMCHS2 (1 << 8)
++#define OMAP2430_AUTO_MMCHS1 (1 << 7)
++#define OMAP2430_AUTO_USBHS (1 << 6)
++#define OMAP2430_AUTO_MCBSP5 (1 << 5)
++#define OMAP2430_AUTO_MCBSP4 (1 << 4)
++#define OMAP2430_AUTO_MCBSP3 (1 << 3)
++#define OMAP24XX_AUTO_UART3 (1 << 2)
++#define OMAP24XX_AUTO_SSI (1 << 1)
++#define OMAP24XX_AUTO_USB (1 << 0)
++
++/* CM_AUTOIDLE3_CORE */
++#define OMAP24XX_AUTO_SDRC (1 << 2)
++#define OMAP24XX_AUTO_GPMC (1 << 1)
++#define OMAP24XX_AUTO_SDMA (1 << 0)
++
++/* CM_AUTOIDLE4_CORE */
++#define OMAP24XX_AUTO_PKA (1 << 4)
++#define OMAP24XX_AUTO_AES (1 << 3)
++#define OMAP24XX_AUTO_RNG (1 << 2)
++#define OMAP24XX_AUTO_SHA (1 << 1)
++#define OMAP24XX_AUTO_DES (1 << 0)
++
++/* CM_CLKSEL1_CORE */
++#define OMAP24XX_CLKSEL_USB_SHIFT 25
++#define OMAP24XX_CLKSEL_USB_MASK (0x7 << 25)
++#define OMAP24XX_CLKSEL_SSI_SHIFT 20
++#define OMAP24XX_CLKSEL_SSI_MASK (0x1f << 20)
++#define OMAP2420_CLKSEL_VLYNQ_SHIFT 15
++#define OMAP2420_CLKSEL_VLYNQ_MASK (0x1f << 15)
++#define OMAP24XX_CLKSEL_DSS2_SHIFT 13
++#define OMAP24XX_CLKSEL_DSS2_MASK (0x1 << 13)
++#define OMAP24XX_CLKSEL_DSS1_SHIFT 8
++#define OMAP24XX_CLKSEL_DSS1_MASK (0x1f << 8)
++#define OMAP24XX_CLKSEL_L4_SHIFT 5
++#define OMAP24XX_CLKSEL_L4_MASK (0x3 << 5)
++#define OMAP24XX_CLKSEL_L3_SHIFT 0
++#define OMAP24XX_CLKSEL_L3_MASK (0x1f << 0)
++
++/* CM_CLKSEL2_CORE */
++#define OMAP24XX_CLKSEL_GPT12_SHIFT 22
++#define OMAP24XX_CLKSEL_GPT12_MASK (0x3 << 22)
++#define OMAP24XX_CLKSEL_GPT11_SHIFT 20
++#define OMAP24XX_CLKSEL_GPT11_MASK (0x3 << 20)
++#define OMAP24XX_CLKSEL_GPT10_SHIFT 18
++#define OMAP24XX_CLKSEL_GPT10_MASK (0x3 << 18)
++#define OMAP24XX_CLKSEL_GPT9_SHIFT 16
++#define OMAP24XX_CLKSEL_GPT9_MASK (0x3 << 16)
++#define OMAP24XX_CLKSEL_GPT8_SHIFT 14
++#define OMAP24XX_CLKSEL_GPT8_MASK (0x3 << 14)
++#define OMAP24XX_CLKSEL_GPT7_SHIFT 12
++#define OMAP24XX_CLKSEL_GPT7_MASK (0x3 << 12)
++#define OMAP24XX_CLKSEL_GPT6_SHIFT 10
++#define OMAP24XX_CLKSEL_GPT6_MASK (0x3 << 10)
++#define OMAP24XX_CLKSEL_GPT5_SHIFT 8
++#define OMAP24XX_CLKSEL_GPT5_MASK (0x3 << 8)
++#define OMAP24XX_CLKSEL_GPT4_SHIFT 6
++#define OMAP24XX_CLKSEL_GPT4_MASK (0x3 << 6)
++#define OMAP24XX_CLKSEL_GPT3_SHIFT 4
++#define OMAP24XX_CLKSEL_GPT3_MASK (0x3 << 4)
++#define OMAP24XX_CLKSEL_GPT2_SHIFT 2
++#define OMAP24XX_CLKSEL_GPT2_MASK (0x3 << 2)
++
++/* CM_CLKSTCTRL_CORE */
++#define OMAP24XX_AUTOSTATE_DSS (1 << 2)
++#define OMAP24XX_AUTOSTATE_L4 (1 << 1)
++#define OMAP24XX_AUTOSTATE_L3 (1 << 0)
++
++/* CM_FCLKEN_GFX */
++#define OMAP24XX_EN_3D_SHIFT 2
++#define OMAP24XX_EN_3D (1 << 2)
++#define OMAP24XX_EN_2D_SHIFT 1
++#define OMAP24XX_EN_2D (1 << 1)
++
++/* CM_ICLKEN_GFX specific bits */
++
++/* CM_IDLEST_GFX specific bits */
++
++/* CM_CLKSEL_GFX specific bits */
++
++/* CM_CLKSTCTRL_GFX */
++#define OMAP24XX_AUTOSTATE_GFX (1 << 0)
++
++/* CM_FCLKEN_WKUP specific bits */
++
++/* CM_ICLKEN_WKUP specific bits */
++#define OMAP2430_EN_ICR_SHIFT 6
++#define OMAP2430_EN_ICR (1 << 6)
++#define OMAP24XX_EN_OMAPCTRL_SHIFT 5
++#define OMAP24XX_EN_OMAPCTRL (1 << 5)
++#define OMAP24XX_EN_WDT1_SHIFT 4
++#define OMAP24XX_EN_WDT1 (1 << 4)
++#define OMAP24XX_EN_32KSYNC_SHIFT 1
++#define OMAP24XX_EN_32KSYNC (1 << 1)
++
++/* CM_IDLEST_WKUP specific bits */
++#define OMAP2430_ST_ICR (1 << 6)
++#define OMAP24XX_ST_OMAPCTRL (1 << 5)
++#define OMAP24XX_ST_WDT1 (1 << 4)
++#define OMAP24XX_ST_MPU_WDT (1 << 3)
++#define OMAP24XX_ST_32KSYNC (1 << 1)
++
++/* CM_AUTOIDLE_WKUP */
++#define OMAP24XX_AUTO_OMAPCTRL (1 << 5)
++#define OMAP24XX_AUTO_WDT1 (1 << 4)
++#define OMAP24XX_AUTO_MPU_WDT (1 << 3)
++#define OMAP24XX_AUTO_GPIOS (1 << 2)
++#define OMAP24XX_AUTO_32KSYNC (1 << 1)
++#define OMAP24XX_AUTO_GPT1 (1 << 0)
++
++/* CM_CLKSEL_WKUP */
++#define OMAP24XX_CLKSEL_GPT1_SHIFT 0
++#define OMAP24XX_CLKSEL_GPT1_MASK (0x3 << 0)
++
++/* CM_CLKEN_PLL */
++#define OMAP24XX_EN_54M_PLL_SHIFT 6
++#define OMAP24XX_EN_54M_PLL_MASK (0x3 << 6)
++#define OMAP24XX_EN_96M_PLL_SHIFT 2
++#define OMAP24XX_EN_96M_PLL_MASK (0x3 << 2)
++#define OMAP24XX_EN_DPLL_SHIFT 0
++#define OMAP24XX_EN_DPLL_MASK (0x3 << 0)
++
++/* CM_IDLEST_CKGEN */
++#define OMAP24XX_ST_54M_APLL (1 << 9)
++#define OMAP24XX_ST_96M_APLL (1 << 8)
++#define OMAP24XX_ST_54M_CLK (1 << 6)
++#define OMAP24XX_ST_12M_CLK (1 << 5)
++#define OMAP24XX_ST_48M_CLK (1 << 4)
++#define OMAP24XX_ST_96M_CLK (1 << 2)
++#define OMAP24XX_ST_CORE_CLK_SHIFT 0
++#define OMAP24XX_ST_CORE_CLK_MASK (0x3 << 0)
++
++/* CM_AUTOIDLE_PLL */
++#define OMAP24XX_AUTO_54M_SHIFT 6
++#define OMAP24XX_AUTO_54M_MASK (0x3 << 6)
++#define OMAP24XX_AUTO_96M_SHIFT 2
++#define OMAP24XX_AUTO_96M_MASK (0x3 << 2)
++#define OMAP24XX_AUTO_DPLL_SHIFT 0
++#define OMAP24XX_AUTO_DPLL_MASK (0x3 << 0)
++
++/* CM_CLKSEL1_PLL */
++#define OMAP2430_MAXDPLLFASTLOCK_SHIFT 28
++#define OMAP2430_MAXDPLLFASTLOCK_MASK (0x7 << 28)
++#define OMAP24XX_APLLS_CLKIN_SHIFT 23
++#define OMAP24XX_APLLS_CLKIN_MASK (0x7 << 23)
++#define OMAP24XX_DPLL_MULT_SHIFT 12
++#define OMAP24XX_DPLL_MULT_MASK (0x3ff << 12)
++#define OMAP24XX_DPLL_DIV_SHIFT 8
++#define OMAP24XX_DPLL_DIV_MASK (0xf << 8)
++#define OMAP24XX_54M_SOURCE_SHIFT 5
++#define OMAP24XX_54M_SOURCE (1 << 5)
++#define OMAP2430_96M_SOURCE_SHIFT 4
++#define OMAP2430_96M_SOURCE (1 << 4)
++#define OMAP24XX_48M_SOURCE_SHIFT 3
++#define OMAP24XX_48M_SOURCE (1 << 3)
++#define OMAP2430_ALTCLK_SOURCE_SHIFT 0
++#define OMAP2430_ALTCLK_SOURCE_MASK (0x7 << 0)
++
++/* CM_CLKSEL2_PLL */
++#define OMAP24XX_CORE_CLK_SRC_SHIFT 0
++#define OMAP24XX_CORE_CLK_SRC_MASK (0x3 << 0)
++
++/* CM_FCLKEN_DSP */
++#define OMAP2420_EN_IVA_COP_SHIFT 10
++#define OMAP2420_EN_IVA_COP (1 << 10)
++#define OMAP2420_EN_IVA_MPU_SHIFT 8
++#define OMAP2420_EN_IVA_MPU (1 << 8)
++#define OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT 0
++#define OMAP24XX_CM_FCLKEN_DSP_EN_DSP (1 << 0)
++
++/* CM_ICLKEN_DSP */
++#define OMAP2420_EN_DSP_IPI_SHIFT 1
++#define OMAP2420_EN_DSP_IPI (1 << 1)
++
++/* CM_IDLEST_DSP */
++#define OMAP2420_ST_IVA (1 << 8)
++#define OMAP2420_ST_IPI (1 << 1)
++#define OMAP24XX_ST_DSP (1 << 0)
++
++/* CM_AUTOIDLE_DSP */
++#define OMAP2420_AUTO_DSP_IPI (1 << 1)
++
++/* CM_CLKSEL_DSP */
++#define OMAP2420_SYNC_IVA (1 << 13)
++#define OMAP2420_CLKSEL_IVA_SHIFT 8
++#define OMAP2420_CLKSEL_IVA_MASK (0x1f << 8)
++#define OMAP24XX_SYNC_DSP (1 << 7)
++#define OMAP24XX_CLKSEL_DSP_IF_SHIFT 5
++#define OMAP24XX_CLKSEL_DSP_IF_MASK (0x3 << 5)
++#define OMAP24XX_CLKSEL_DSP_SHIFT 0
++#define OMAP24XX_CLKSEL_DSP_MASK (0x1f << 0)
++
++/* CM_CLKSTCTRL_DSP */
++#define OMAP2420_AUTOSTATE_IVA (1 << 8)
++#define OMAP24XX_AUTOSTATE_DSP (1 << 0)
++
++/* CM_FCLKEN_MDM */
++/* 2430 only */
++#define OMAP2430_EN_OSC_SHIFT 1
++#define OMAP2430_EN_OSC (1 << 1)
++
++/* CM_ICLKEN_MDM */
++/* 2430 only */
++#define OMAP2430_CM_ICLKEN_MDM_EN_MDM_SHIFT 0
++#define OMAP2430_CM_ICLKEN_MDM_EN_MDM (1 << 0)
++
++/* CM_IDLEST_MDM specific bits */
++/* 2430 only */
++
++/* CM_AUTOIDLE_MDM */
++/* 2430 only */
++#define OMAP2430_AUTO_OSC (1 << 1)
++#define OMAP2430_AUTO_MDM (1 << 0)
++
++/* CM_CLKSEL_MDM */
++/* 2430 only */
++#define OMAP2430_SYNC_MDM (1 << 4)
++#define OMAP2430_CLKSEL_MDM_SHIFT 0
++#define OMAP2430_CLKSEL_MDM_MASK (0xf << 0)
++
++/* CM_CLKSTCTRL_MDM */
++/* 2430 only */
++#define OMAP2430_AUTOSTATE_MDM (1 << 0)
++
++#endif
+diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h b/arch/arm/mach-omap2/cm-regbits-34xx.h
+new file mode 100644
+index 0000000..9249129
+--- /dev/null
++++ b/arch/arm/mach-omap2/cm-regbits-34xx.h
+@@ -0,0 +1,673 @@
++#ifndef __ARCH_ARM_MACH_OMAP2_CM_REGBITS_34XX_H
++#define __ARCH_ARM_MACH_OMAP2_CM_REGBITS_34XX_H
++
++/*
++ * OMAP3430 Clock Management register bits
++ *
++ * Copyright (C) 2007-2008 Texas Instruments, Inc.
++ * Copyright (C) 2007-2008 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "cm.h"
++
++/* Bits shared between registers */
++
++/* CM_FCLKEN1_CORE and CM_ICLKEN1_CORE shared bits */
++#define OMAP3430ES2_EN_MMC3_MASK (1 << 30)
++#define OMAP3430ES2_EN_MMC3_SHIFT 30
++#define OMAP3430_EN_MSPRO (1 << 23)
++#define OMAP3430_EN_MSPRO_SHIFT 23
++#define OMAP3430_EN_HDQ (1 << 22)
++#define OMAP3430_EN_HDQ_SHIFT 22
++#define OMAP3430ES1_EN_FSHOSTUSB (1 << 5)
++#define OMAP3430ES1_EN_FSHOSTUSB_SHIFT 5
++#define OMAP3430ES1_EN_D2D (1 << 3)
++#define OMAP3430ES1_EN_D2D_SHIFT 3
++#define OMAP3430_EN_SSI (1 << 0)
++#define OMAP3430_EN_SSI_SHIFT 0
++
++/* CM_FCLKEN3_CORE and CM_ICLKEN3_CORE shared bits */
++#define OMAP3430ES2_EN_USBTLL_SHIFT 2
++#define OMAP3430ES2_EN_USBTLL_MASK (1 << 2)
++
++/* CM_FCLKEN_WKUP and CM_ICLKEN_WKUP shared bits */
++#define OMAP3430_EN_WDT2 (1 << 5)
++#define OMAP3430_EN_WDT2_SHIFT 5
++
++/* CM_ICLKEN_CAM, CM_FCLKEN_CAM shared bits */
++#define OMAP3430_EN_CAM (1 << 0)
++#define OMAP3430_EN_CAM_SHIFT 0
++
++/* CM_FCLKEN_PER, CM_ICLKEN_PER shared bits */
++#define OMAP3430_EN_WDT3 (1 << 12)
++#define OMAP3430_EN_WDT3_SHIFT 12
++
++/* CM_CLKSEL2_EMU, CM_CLKSEL3_EMU shared bits */
++#define OMAP3430_OVERRIDE_ENABLE (1 << 19)
++
++
++/* Bits specific to each register */
++
++/* CM_FCLKEN_IVA2 */
++#define OMAP3430_CM_FCLKEN_IVA2_EN_IVA2 (1 << 0)
++
++/* CM_CLKEN_PLL_IVA2 */
++#define OMAP3430_IVA2_DPLL_RAMPTIME_SHIFT 8
++#define OMAP3430_IVA2_DPLL_RAMPTIME_MASK (0x3 << 8)
++#define OMAP3430_IVA2_DPLL_FREQSEL_SHIFT 4
++#define OMAP3430_IVA2_DPLL_FREQSEL_MASK (0xf << 4)
++#define OMAP3430_EN_IVA2_DPLL_DRIFTGUARD_SHIFT 3
++#define OMAP3430_EN_IVA2_DPLL_DRIFTGUARD_MASK (1 << 3)
++#define OMAP3430_EN_IVA2_DPLL_SHIFT 0
++#define OMAP3430_EN_IVA2_DPLL_MASK (0x7 << 0)
++
++/* CM_IDLEST_IVA2 */
++#define OMAP3430_ST_IVA2 (1 << 0)
++
++/* CM_IDLEST_PLL_IVA2 */
++#define OMAP3430_ST_IVA2_CLK (1 << 0)
++
++/* CM_AUTOIDLE_PLL_IVA2 */
++#define OMAP3430_AUTO_IVA2_DPLL_SHIFT 0
++#define OMAP3430_AUTO_IVA2_DPLL_MASK (0x7 << 0)
++
++/* CM_CLKSEL1_PLL_IVA2 */
++#define OMAP3430_IVA2_CLK_SRC_SHIFT 19
++#define OMAP3430_IVA2_CLK_SRC_MASK (0x3 << 19)
++#define OMAP3430_IVA2_DPLL_MULT_SHIFT 8
++#define OMAP3430_IVA2_DPLL_MULT_MASK (0x7ff << 8)
++#define OMAP3430_IVA2_DPLL_DIV_SHIFT 0
++#define OMAP3430_IVA2_DPLL_DIV_MASK (0x7f << 0)
++
++/* CM_CLKSEL2_PLL_IVA2 */
++#define OMAP3430_IVA2_DPLL_CLKOUT_DIV_SHIFT 0
++#define OMAP3430_IVA2_DPLL_CLKOUT_DIV_MASK (0x1f << 0)
++
++/* CM_CLKSTCTRL_IVA2 */
++#define OMAP3430_CLKTRCTRL_IVA2_SHIFT 0
++#define OMAP3430_CLKTRCTRL_IVA2_MASK (0x3 << 0)
++
++/* CM_CLKSTST_IVA2 */
++#define OMAP3430_CLKACTIVITY_IVA2 (1 << 0)
++
++/* CM_REVISION specific bits */
++
++/* CM_SYSCONFIG specific bits */
++
++/* CM_CLKEN_PLL_MPU */
++#define OMAP3430_MPU_DPLL_RAMPTIME_SHIFT 8
++#define OMAP3430_MPU_DPLL_RAMPTIME_MASK (0x3 << 8)
++#define OMAP3430_MPU_DPLL_FREQSEL_SHIFT 4
++#define OMAP3430_MPU_DPLL_FREQSEL_MASK (0xf << 4)
++#define OMAP3430_EN_MPU_DPLL_DRIFTGUARD_SHIFT 3
++#define OMAP3430_EN_MPU_DPLL_DRIFTGUARD_MASK (1 << 3)
++#define OMAP3430_EN_MPU_DPLL_SHIFT 0
++#define OMAP3430_EN_MPU_DPLL_MASK (0x7 << 0)
++
++/* CM_IDLEST_MPU */
++#define OMAP3430_ST_MPU (1 << 0)
++
++/* CM_IDLEST_PLL_MPU */
++#define OMAP3430_ST_MPU_CLK (1 << 0)
++#define OMAP3430_ST_IVA2_CLK_MASK (1 << 0)
++
++/* CM_IDLEST_PLL_MPU */
++#define OMAP3430_ST_MPU_CLK_MASK (1 << 0)
++
++/* CM_AUTOIDLE_PLL_MPU */
++#define OMAP3430_AUTO_MPU_DPLL_SHIFT 0
++#define OMAP3430_AUTO_MPU_DPLL_MASK (0x7 << 0)
++
++/* CM_CLKSEL1_PLL_MPU */
++#define OMAP3430_MPU_CLK_SRC_SHIFT 19
++#define OMAP3430_MPU_CLK_SRC_MASK (0x3 << 19)
++#define OMAP3430_MPU_DPLL_MULT_SHIFT 8
++#define OMAP3430_MPU_DPLL_MULT_MASK (0x7ff << 8)
++#define OMAP3430_MPU_DPLL_DIV_SHIFT 0
++#define OMAP3430_MPU_DPLL_DIV_MASK (0x7f << 0)
++
++/* CM_CLKSEL2_PLL_MPU */
++#define OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT 0
++#define OMAP3430_MPU_DPLL_CLKOUT_DIV_MASK (0x1f << 0)
++
++/* CM_CLKSTCTRL_MPU */
++#define OMAP3430_CLKTRCTRL_MPU_SHIFT 0
++#define OMAP3430_CLKTRCTRL_MPU_MASK (0x3 << 0)
++
++/* CM_CLKSTST_MPU */
++#define OMAP3430_CLKACTIVITY_MPU (1 << 0)
++
++/* CM_FCLKEN1_CORE specific bits */
++
++/* CM_ICLKEN1_CORE specific bits */
++#define OMAP3430_EN_ICR (1 << 29)
++#define OMAP3430_EN_ICR_SHIFT 29
++#define OMAP3430_EN_AES2 (1 << 28)
++#define OMAP3430_EN_AES2_SHIFT 28
++#define OMAP3430_EN_SHA12 (1 << 27)
++#define OMAP3430_EN_SHA12_SHIFT 27
++#define OMAP3430_EN_DES2 (1 << 26)
++#define OMAP3430_EN_DES2_SHIFT 26
++#define OMAP3430ES1_EN_FAC (1 << 8)
++#define OMAP3430ES1_EN_FAC_SHIFT 8
++#define OMAP3430_EN_MAILBOXES (1 << 7)
++#define OMAP3430_EN_MAILBOXES_SHIFT 7
++#define OMAP3430_EN_OMAPCTRL (1 << 6)
++#define OMAP3430_EN_OMAPCTRL_SHIFT 6
++#define OMAP3430_EN_SDRC (1 << 1)
++#define OMAP3430_EN_SDRC_SHIFT 1
++
++/* CM_ICLKEN2_CORE */
++#define OMAP3430_EN_PKA (1 << 4)
++#define OMAP3430_EN_PKA_SHIFT 4
++#define OMAP3430_EN_AES1 (1 << 3)
++#define OMAP3430_EN_AES1_SHIFT 3
++#define OMAP3430_EN_RNG (1 << 2)
++#define OMAP3430_EN_RNG_SHIFT 2
++#define OMAP3430_EN_SHA11 (1 << 1)
++#define OMAP3430_EN_SHA11_SHIFT 1
++#define OMAP3430_EN_DES1 (1 << 0)
++#define OMAP3430_EN_DES1_SHIFT 0
++
++/* CM_FCLKEN3_CORE specific bits */
++#define OMAP3430ES2_EN_TS_SHIFT 1
++#define OMAP3430ES2_EN_TS_MASK (1 << 1)
++#define OMAP3430ES2_EN_CPEFUSE_SHIFT 0
++#define OMAP3430ES2_EN_CPEFUSE_MASK (1 << 0)
++
++/* CM_IDLEST1_CORE specific bits */
++#define OMAP3430_ST_ICR (1 << 29)
++#define OMAP3430_ST_AES2 (1 << 28)
++#define OMAP3430_ST_SHA12 (1 << 27)
++#define OMAP3430_ST_DES2 (1 << 26)
++#define OMAP3430_ST_MSPRO (1 << 23)
++#define OMAP3430_ST_HDQ (1 << 22)
++#define OMAP3430ES1_ST_FAC (1 << 8)
++#define OMAP3430ES1_ST_MAILBOXES (1 << 7)
++#define OMAP3430_ST_OMAPCTRL (1 << 6)
++#define OMAP3430_ST_SDMA (1 << 2)
++#define OMAP3430_ST_SDRC (1 << 1)
++#define OMAP3430_ST_SSI (1 << 0)
++
++/* CM_IDLEST2_CORE */
++#define OMAP3430_ST_PKA (1 << 4)
++#define OMAP3430_ST_AES1 (1 << 3)
++#define OMAP3430_ST_RNG (1 << 2)
++#define OMAP3430_ST_SHA11 (1 << 1)
++#define OMAP3430_ST_DES1 (1 << 0)
++
++/* CM_IDLEST3_CORE */
++#define OMAP3430ES2_ST_USBTLL_SHIFT 2
++#define OMAP3430ES2_ST_USBTLL_MASK (1 << 2)
++
++/* CM_AUTOIDLE1_CORE */
++#define OMAP3430_AUTO_AES2 (1 << 28)
++#define OMAP3430_AUTO_AES2_SHIFT 28
++#define OMAP3430_AUTO_SHA12 (1 << 27)
++#define OMAP3430_AUTO_SHA12_SHIFT 27
++#define OMAP3430_AUTO_DES2 (1 << 26)
++#define OMAP3430_AUTO_DES2_SHIFT 26
++#define OMAP3430_AUTO_MMC2 (1 << 25)
++#define OMAP3430_AUTO_MMC2_SHIFT 25
++#define OMAP3430_AUTO_MMC1 (1 << 24)
++#define OMAP3430_AUTO_MMC1_SHIFT 24
++#define OMAP3430_AUTO_MSPRO (1 << 23)
++#define OMAP3430_AUTO_MSPRO_SHIFT 23
++#define OMAP3430_AUTO_HDQ (1 << 22)
++#define OMAP3430_AUTO_HDQ_SHIFT 22
++#define OMAP3430_AUTO_MCSPI4 (1 << 21)
++#define OMAP3430_AUTO_MCSPI4_SHIFT 21
++#define OMAP3430_AUTO_MCSPI3 (1 << 20)
++#define OMAP3430_AUTO_MCSPI3_SHIFT 20
++#define OMAP3430_AUTO_MCSPI2 (1 << 19)
++#define OMAP3430_AUTO_MCSPI2_SHIFT 19
++#define OMAP3430_AUTO_MCSPI1 (1 << 18)
++#define OMAP3430_AUTO_MCSPI1_SHIFT 18
++#define OMAP3430_AUTO_I2C3 (1 << 17)
++#define OMAP3430_AUTO_I2C3_SHIFT 17
++#define OMAP3430_AUTO_I2C2 (1 << 16)
++#define OMAP3430_AUTO_I2C2_SHIFT 16
++#define OMAP3430_AUTO_I2C1 (1 << 15)
++#define OMAP3430_AUTO_I2C1_SHIFT 15
++#define OMAP3430_AUTO_UART2 (1 << 14)
++#define OMAP3430_AUTO_UART2_SHIFT 14
++#define OMAP3430_AUTO_UART1 (1 << 13)
++#define OMAP3430_AUTO_UART1_SHIFT 13
++#define OMAP3430_AUTO_GPT11 (1 << 12)
++#define OMAP3430_AUTO_GPT11_SHIFT 12
++#define OMAP3430_AUTO_GPT10 (1 << 11)
++#define OMAP3430_AUTO_GPT10_SHIFT 11
++#define OMAP3430_AUTO_MCBSP5 (1 << 10)
++#define OMAP3430_AUTO_MCBSP5_SHIFT 10
++#define OMAP3430_AUTO_MCBSP1 (1 << 9)
++#define OMAP3430_AUTO_MCBSP1_SHIFT 9
++#define OMAP3430ES1_AUTO_FAC (1 << 8)
++#define OMAP3430ES1_AUTO_FAC_SHIFT 8
++#define OMAP3430_AUTO_MAILBOXES (1 << 7)
++#define OMAP3430_AUTO_MAILBOXES_SHIFT 7
++#define OMAP3430_AUTO_OMAPCTRL (1 << 6)
++#define OMAP3430_AUTO_OMAPCTRL_SHIFT 6
++#define OMAP3430ES1_AUTO_FSHOSTUSB (1 << 5)
++#define OMAP3430ES1_AUTO_FSHOSTUSB_SHIFT 5
++#define OMAP3430_AUTO_HSOTGUSB (1 << 4)
++#define OMAP3430_AUTO_HSOTGUSB_SHIFT 4
++#define OMAP3430ES1_AUTO_D2D (1 << 3)
++#define OMAP3430ES1_AUTO_D2D_SHIFT 3
++#define OMAP3430_AUTO_SSI (1 << 0)
++#define OMAP3430_AUTO_SSI_SHIFT 0
++
++/* CM_AUTOIDLE2_CORE */
++#define OMAP3430_AUTO_PKA (1 << 4)
++#define OMAP3430_AUTO_PKA_SHIFT 4
++#define OMAP3430_AUTO_AES1 (1 << 3)
++#define OMAP3430_AUTO_AES1_SHIFT 3
++#define OMAP3430_AUTO_RNG (1 << 2)
++#define OMAP3430_AUTO_RNG_SHIFT 2
++#define OMAP3430_AUTO_SHA11 (1 << 1)
++#define OMAP3430_AUTO_SHA11_SHIFT 1
++#define OMAP3430_AUTO_DES1 (1 << 0)
++#define OMAP3430_AUTO_DES1_SHIFT 0
++
++/* CM_AUTOIDLE3_CORE */
++#define OMAP3430ES2_AUTO_USBTLL_SHIFT 2
++#define OMAP3430ES2_AUTO_USBTLL_MASK (1 << 2)
++
++/* CM_CLKSEL_CORE */
++#define OMAP3430_CLKSEL_SSI_SHIFT 8
++#define OMAP3430_CLKSEL_SSI_MASK (0xf << 8)
++#define OMAP3430_CLKSEL_GPT11_MASK (1 << 7)
++#define OMAP3430_CLKSEL_GPT11_SHIFT 7
++#define OMAP3430_CLKSEL_GPT10_MASK (1 << 6)
++#define OMAP3430_CLKSEL_GPT10_SHIFT 6
++#define OMAP3430ES1_CLKSEL_FSHOSTUSB_SHIFT 4
++#define OMAP3430ES1_CLKSEL_FSHOSTUSB_MASK (0x3 << 4)
++#define OMAP3430_CLKSEL_L4_SHIFT 2
++#define OMAP3430_CLKSEL_L4_MASK (0x3 << 2)
++#define OMAP3430_CLKSEL_L3_SHIFT 0
++#define OMAP3430_CLKSEL_L3_MASK (0x3 << 0)
++
++/* CM_CLKSTCTRL_CORE */
++#define OMAP3430ES1_CLKTRCTRL_D2D_SHIFT 4
++#define OMAP3430ES1_CLKTRCTRL_D2D_MASK (0x3 << 4)
++#define OMAP3430_CLKTRCTRL_L4_SHIFT 2
++#define OMAP3430_CLKTRCTRL_L4_MASK (0x3 << 2)
++#define OMAP3430_CLKTRCTRL_L3_SHIFT 0
++#define OMAP3430_CLKTRCTRL_L3_MASK (0x3 << 0)
++
++/* CM_CLKSTST_CORE */
++#define OMAP3430ES1_CLKACTIVITY_D2D (1 << 2)
++#define OMAP3430_CLKACTIVITY_L4 (1 << 1)
++#define OMAP3430_CLKACTIVITY_L3 (1 << 0)
++
++/* CM_FCLKEN_GFX */
++#define OMAP3430ES1_EN_3D (1 << 2)
++#define OMAP3430ES1_EN_3D_SHIFT 2
++#define OMAP3430ES1_EN_2D (1 << 1)
++#define OMAP3430ES1_EN_2D_SHIFT 1
++
++/* CM_ICLKEN_GFX specific bits */
++
++/* CM_IDLEST_GFX specific bits */
++
++/* CM_CLKSEL_GFX specific bits */
++
++/* CM_SLEEPDEP_GFX specific bits */
++
++/* CM_CLKSTCTRL_GFX */
++#define OMAP3430ES1_CLKTRCTRL_GFX_SHIFT 0
++#define OMAP3430ES1_CLKTRCTRL_GFX_MASK (0x3 << 0)
++
++/* CM_CLKSTST_GFX */
++#define OMAP3430ES1_CLKACTIVITY_GFX (1 << 0)
++
++/* CM_FCLKEN_SGX */
++#define OMAP3430ES2_EN_SGX_SHIFT 1
++#define OMAP3430ES2_EN_SGX_MASK (1 << 1)
++
++/* CM_CLKSEL_SGX */
++#define OMAP3430ES2_CLKSEL_SGX_SHIFT 0
++#define OMAP3430ES2_CLKSEL_SGX_MASK (0x7 << 0)
++
++/* CM_FCLKEN_WKUP specific bits */
++#define OMAP3430ES2_EN_USIMOCP_SHIFT 9
++
++/* CM_ICLKEN_WKUP specific bits */
++#define OMAP3430_EN_WDT1 (1 << 4)
++#define OMAP3430_EN_WDT1_SHIFT 4
++#define OMAP3430_EN_32KSYNC (1 << 2)
++#define OMAP3430_EN_32KSYNC_SHIFT 2
++
++/* CM_IDLEST_WKUP specific bits */
++#define OMAP3430_ST_WDT2 (1 << 5)
++#define OMAP3430_ST_WDT1 (1 << 4)
++#define OMAP3430_ST_32KSYNC (1 << 2)
++
++/* CM_AUTOIDLE_WKUP */
++#define OMAP3430_AUTO_WDT2 (1 << 5)
++#define OMAP3430_AUTO_WDT2_SHIFT 5
++#define OMAP3430_AUTO_WDT1 (1 << 4)
++#define OMAP3430_AUTO_WDT1_SHIFT 4
++#define OMAP3430_AUTO_GPIO1 (1 << 3)
++#define OMAP3430_AUTO_GPIO1_SHIFT 3
++#define OMAP3430_AUTO_32KSYNC (1 << 2)
++#define OMAP3430_AUTO_32KSYNC_SHIFT 2
++#define OMAP3430_AUTO_GPT12 (1 << 1)
++#define OMAP3430_AUTO_GPT12_SHIFT 1
++#define OMAP3430_AUTO_GPT1 (1 << 0)
++#define OMAP3430_AUTO_GPT1_SHIFT 0
++
++/* CM_CLKSEL_WKUP */
++#define OMAP3430ES2_CLKSEL_USIMOCP_MASK (0xf << 3)
++#define OMAP3430_CLKSEL_RM_SHIFT 1
++#define OMAP3430_CLKSEL_RM_MASK (0x3 << 1)
++#define OMAP3430_CLKSEL_GPT1_SHIFT 0
++#define OMAP3430_CLKSEL_GPT1_MASK (1 << 0)
++
++/* CM_CLKEN_PLL */
++#define OMAP3430_PWRDN_EMU_PERIPH_SHIFT 31
++#define OMAP3430_PWRDN_CAM_SHIFT 30
++#define OMAP3430_PWRDN_DSS1_SHIFT 29
++#define OMAP3430_PWRDN_TV_SHIFT 28
++#define OMAP3430_PWRDN_96M_SHIFT 27
++#define OMAP3430_PERIPH_DPLL_RAMPTIME_SHIFT 24
++#define OMAP3430_PERIPH_DPLL_RAMPTIME_MASK (0x3 << 24)
++#define OMAP3430_PERIPH_DPLL_FREQSEL_SHIFT 20
++#define OMAP3430_PERIPH_DPLL_FREQSEL_MASK (0xf << 20)
++#define OMAP3430_EN_PERIPH_DPLL_DRIFTGUARD_SHIFT 19
++#define OMAP3430_EN_PERIPH_DPLL_DRIFTGUARD_MASK (1 << 19)
++#define OMAP3430_EN_PERIPH_DPLL_SHIFT 16
++#define OMAP3430_EN_PERIPH_DPLL_MASK (0x7 << 16)
++#define OMAP3430_PWRDN_EMU_CORE_SHIFT 12
++#define OMAP3430_CORE_DPLL_RAMPTIME_SHIFT 8
++#define OMAP3430_CORE_DPLL_RAMPTIME_MASK (0x3 << 8)
++#define OMAP3430_CORE_DPLL_FREQSEL_SHIFT 4
++#define OMAP3430_CORE_DPLL_FREQSEL_MASK (0xf << 4)
++#define OMAP3430_EN_CORE_DPLL_DRIFTGUARD_SHIFT 3
++#define OMAP3430_EN_CORE_DPLL_DRIFTGUARD_MASK (1 << 3)
++#define OMAP3430_EN_CORE_DPLL_SHIFT 0
++#define OMAP3430_EN_CORE_DPLL_MASK (0x7 << 0)
++
++/* CM_CLKEN2_PLL */
++#define OMAP3430ES2_EN_PERIPH2_DPLL_LPMODE_SHIFT 10
++#define OMAP3430ES2_PERIPH2_DPLL_RAMPTIME_MASK (0x3 << 8)
++#define OMAP3430ES2_PERIPH2_DPLL_FREQSEL_SHIFT 4
++#define OMAP3430ES2_PERIPH2_DPLL_FREQSEL_MASK (0xf << 4)
++#define OMAP3430ES2_EN_PERIPH2_DPLL_DRIFTGUARD_SHIFT 3
++#define OMAP3430ES2_EN_PERIPH2_DPLL_SHIFT 0
++#define OMAP3430ES2_EN_PERIPH2_DPLL_MASK (0x7 << 0)
++
++/* CM_IDLEST_CKGEN */
++#define OMAP3430_ST_54M_CLK (1 << 5)
++#define OMAP3430_ST_12M_CLK (1 << 4)
++#define OMAP3430_ST_48M_CLK (1 << 3)
++#define OMAP3430_ST_96M_CLK (1 << 2)
++#define OMAP3430_ST_PERIPH_CLK (1 << 1)
++#define OMAP3430_ST_CORE_CLK (1 << 0)
++
++/* CM_IDLEST2_CKGEN */
++#define OMAP3430ES2_ST_120M_CLK_SHIFT 1
++#define OMAP3430ES2_ST_120M_CLK_MASK (1 << 1)
++#define OMAP3430ES2_ST_PERIPH2_CLK_SHIFT 0
++#define OMAP3430ES2_ST_PERIPH2_CLK_MASK (1 << 0)
++
++/* CM_AUTOIDLE_PLL */
++#define OMAP3430_AUTO_PERIPH_DPLL_SHIFT 3
++#define OMAP3430_AUTO_PERIPH_DPLL_MASK (0x7 << 3)
++#define OMAP3430_AUTO_CORE_DPLL_SHIFT 0
++#define OMAP3430_AUTO_CORE_DPLL_MASK (0x7 << 0)
++
++/* CM_CLKSEL1_PLL */
++/* Note that OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK was (0x3 << 27) on 3430ES1 */
++#define OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT 27
++#define OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK (0x1f << 27)
++#define OMAP3430_CORE_DPLL_MULT_SHIFT 16
++#define OMAP3430_CORE_DPLL_MULT_MASK (0x7ff << 16)
++#define OMAP3430_CORE_DPLL_DIV_SHIFT 8
++#define OMAP3430_CORE_DPLL_DIV_MASK (0x7f << 8)
++#define OMAP3430_SOURCE_54M (1 << 5)
++#define OMAP3430_SOURCE_48M (1 << 3)
++
++/* CM_CLKSEL2_PLL */
++#define OMAP3430_PERIPH_DPLL_MULT_SHIFT 8
++#define OMAP3430_PERIPH_DPLL_MULT_MASK (0x7ff << 8)
++#define OMAP3430_PERIPH_DPLL_DIV_SHIFT 0
++#define OMAP3430_PERIPH_DPLL_DIV_MASK (0x7f << 0)
++
++/* CM_CLKSEL3_PLL */
++#define OMAP3430_DIV_96M_SHIFT 0
++#define OMAP3430_DIV_96M_MASK (0x1f << 0)
++
++/* CM_CLKSEL4_PLL */
++#define OMAP3430ES2_PERIPH2_DPLL_MULT_SHIFT 8
++#define OMAP3430ES2_PERIPH2_DPLL_MULT_MASK (0x7ff << 8)
++#define OMAP3430ES2_PERIPH2_DPLL_DIV_SHIFT 0
++#define OMAP3430ES2_PERIPH2_DPLL_DIV_MASK (0x7f << 0)
++
++/* CM_CLKSEL5_PLL */
++#define OMAP3430ES2_DIV_120M_SHIFT 0
++#define OMAP3430ES2_DIV_120M_MASK (0x1f << 0)
++
++/* CM_CLKOUT_CTRL */
++#define OMAP3430_CLKOUT2_EN_SHIFT 7
++#define OMAP3430_CLKOUT2_EN (1 << 7)
++#define OMAP3430_CLKOUT2_DIV_SHIFT 3
++#define OMAP3430_CLKOUT2_DIV_MASK (0x7 << 3)
++#define OMAP3430_CLKOUT2SOURCE_SHIFT 0
++#define OMAP3430_CLKOUT2SOURCE_MASK (0x3 << 0)
++
++/* CM_FCLKEN_DSS */
++#define OMAP3430_EN_TV (1 << 2)
++#define OMAP3430_EN_TV_SHIFT 2
++#define OMAP3430_EN_DSS2 (1 << 1)
++#define OMAP3430_EN_DSS2_SHIFT 1
++#define OMAP3430_EN_DSS1 (1 << 0)
++#define OMAP3430_EN_DSS1_SHIFT 0
++
++/* CM_ICLKEN_DSS */
++#define OMAP3430_CM_ICLKEN_DSS_EN_DSS (1 << 0)
++#define OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT 0
++
++/* CM_IDLEST_DSS */
++#define OMAP3430_ST_DSS (1 << 0)
++
++/* CM_AUTOIDLE_DSS */
++#define OMAP3430_AUTO_DSS (1 << 0)
++#define OMAP3430_AUTO_DSS_SHIFT 0
++
++/* CM_CLKSEL_DSS */
++#define OMAP3430_CLKSEL_TV_SHIFT 8
++#define OMAP3430_CLKSEL_TV_MASK (0x1f << 8)
++#define OMAP3430_CLKSEL_DSS1_SHIFT 0
++#define OMAP3430_CLKSEL_DSS1_MASK (0x1f << 0)
++
++/* CM_SLEEPDEP_DSS specific bits */
++
++/* CM_CLKSTCTRL_DSS */
++#define OMAP3430_CLKTRCTRL_DSS_SHIFT 0
++#define OMAP3430_CLKTRCTRL_DSS_MASK (0x3 << 0)
++
++/* CM_CLKSTST_DSS */
++#define OMAP3430_CLKACTIVITY_DSS (1 << 0)
++
++/* CM_FCLKEN_CAM specific bits */
++
++/* CM_ICLKEN_CAM specific bits */
++
++/* CM_IDLEST_CAM */
++#define OMAP3430_ST_CAM (1 << 0)
++
++/* CM_AUTOIDLE_CAM */
++#define OMAP3430_AUTO_CAM (1 << 0)
++#define OMAP3430_AUTO_CAM_SHIFT 0
++
++/* CM_CLKSEL_CAM */
++#define OMAP3430_CLKSEL_CAM_SHIFT 0
++#define OMAP3430_CLKSEL_CAM_MASK (0x1f << 0)
++
++/* CM_SLEEPDEP_CAM specific bits */
++
++/* CM_CLKSTCTRL_CAM */
++#define OMAP3430_CLKTRCTRL_CAM_SHIFT 0
++#define OMAP3430_CLKTRCTRL_CAM_MASK (0x3 << 0)
++
++/* CM_CLKSTST_CAM */
++#define OMAP3430_CLKACTIVITY_CAM (1 << 0)
++
++/* CM_FCLKEN_PER specific bits */
++
++/* CM_ICLKEN_PER specific bits */
++
++/* CM_IDLEST_PER */
++#define OMAP3430_ST_WDT3 (1 << 12)
++#define OMAP3430_ST_MCBSP4 (1 << 2)
++#define OMAP3430_ST_MCBSP3 (1 << 1)
++#define OMAP3430_ST_MCBSP2 (1 << 0)
++
++/* CM_AUTOIDLE_PER */
++#define OMAP3430_AUTO_GPIO6 (1 << 17)
++#define OMAP3430_AUTO_GPIO6_SHIFT 17
++#define OMAP3430_AUTO_GPIO5 (1 << 16)
++#define OMAP3430_AUTO_GPIO5_SHIFT 16
++#define OMAP3430_AUTO_GPIO4 (1 << 15)
++#define OMAP3430_AUTO_GPIO4_SHIFT 15
++#define OMAP3430_AUTO_GPIO3 (1 << 14)
++#define OMAP3430_AUTO_GPIO3_SHIFT 14
++#define OMAP3430_AUTO_GPIO2 (1 << 13)
++#define OMAP3430_AUTO_GPIO2_SHIFT 13
++#define OMAP3430_AUTO_WDT3 (1 << 12)
++#define OMAP3430_AUTO_WDT3_SHIFT 12
++#define OMAP3430_AUTO_UART3 (1 << 11)
++#define OMAP3430_AUTO_UART3_SHIFT 11
++#define OMAP3430_AUTO_GPT9 (1 << 10)
++#define OMAP3430_AUTO_GPT9_SHIFT 10
++#define OMAP3430_AUTO_GPT8 (1 << 9)
++#define OMAP3430_AUTO_GPT8_SHIFT 9
++#define OMAP3430_AUTO_GPT7 (1 << 8)
++#define OMAP3430_AUTO_GPT7_SHIFT 8
++#define OMAP3430_AUTO_GPT6 (1 << 7)
++#define OMAP3430_AUTO_GPT6_SHIFT 7
++#define OMAP3430_AUTO_GPT5 (1 << 6)
++#define OMAP3430_AUTO_GPT5_SHIFT 6
++#define OMAP3430_AUTO_GPT4 (1 << 5)
++#define OMAP3430_AUTO_GPT4_SHIFT 5
++#define OMAP3430_AUTO_GPT3 (1 << 4)
++#define OMAP3430_AUTO_GPT3_SHIFT 4
++#define OMAP3430_AUTO_GPT2 (1 << 3)
++#define OMAP3430_AUTO_GPT2_SHIFT 3
++#define OMAP3430_AUTO_MCBSP4 (1 << 2)
++#define OMAP3430_AUTO_MCBSP4_SHIFT 2
++#define OMAP3430_AUTO_MCBSP3 (1 << 1)
++#define OMAP3430_AUTO_MCBSP3_SHIFT 1
++#define OMAP3430_AUTO_MCBSP2 (1 << 0)
++#define OMAP3430_AUTO_MCBSP2_SHIFT 0
++
++/* CM_CLKSEL_PER */
++#define OMAP3430_CLKSEL_GPT9_MASK (1 << 7)
++#define OMAP3430_CLKSEL_GPT9_SHIFT 7
++#define OMAP3430_CLKSEL_GPT8_MASK (1 << 6)
++#define OMAP3430_CLKSEL_GPT8_SHIFT 6
++#define OMAP3430_CLKSEL_GPT7_MASK (1 << 5)
++#define OMAP3430_CLKSEL_GPT7_SHIFT 5
++#define OMAP3430_CLKSEL_GPT6_MASK (1 << 4)
++#define OMAP3430_CLKSEL_GPT6_SHIFT 4
++#define OMAP3430_CLKSEL_GPT5_MASK (1 << 3)
++#define OMAP3430_CLKSEL_GPT5_SHIFT 3
++#define OMAP3430_CLKSEL_GPT4_MASK (1 << 2)
++#define OMAP3430_CLKSEL_GPT4_SHIFT 2
++#define OMAP3430_CLKSEL_GPT3_MASK (1 << 1)
++#define OMAP3430_CLKSEL_GPT3_SHIFT 1
++#define OMAP3430_CLKSEL_GPT2_MASK (1 << 0)
++#define OMAP3430_CLKSEL_GPT2_SHIFT 0
++
++/* CM_SLEEPDEP_PER specific bits */
++#define OMAP3430_CM_SLEEPDEP_PER_EN_IVA2 (1 << 2)
++
++/* CM_CLKSTCTRL_PER */
++#define OMAP3430_CLKTRCTRL_PER_SHIFT 0
++#define OMAP3430_CLKTRCTRL_PER_MASK (0x3 << 0)
++
++/* CM_CLKSTST_PER */
++#define OMAP3430_CLKACTIVITY_PER (1 << 0)
++
++/* CM_CLKSEL1_EMU */
++#define OMAP3430_DIV_DPLL4_SHIFT 24
++#define OMAP3430_DIV_DPLL4_MASK (0x1f << 24)
++#define OMAP3430_DIV_DPLL3_SHIFT 16
++#define OMAP3430_DIV_DPLL3_MASK (0x1f << 16)
++#define OMAP3430_CLKSEL_TRACECLK_SHIFT 11
++#define OMAP3430_CLKSEL_TRACECLK_MASK (0x7 << 11)
++#define OMAP3430_CLKSEL_PCLK_SHIFT 8
++#define OMAP3430_CLKSEL_PCLK_MASK (0x7 << 8)
++#define OMAP3430_CLKSEL_PCLKX2_SHIFT 6
++#define OMAP3430_CLKSEL_PCLKX2_MASK (0x3 << 6)
++#define OMAP3430_CLKSEL_ATCLK_SHIFT 4
++#define OMAP3430_CLKSEL_ATCLK_MASK (0x3 << 4)
++#define OMAP3430_TRACE_MUX_CTRL_SHIFT 2
++#define OMAP3430_TRACE_MUX_CTRL_MASK (0x3 << 2)
++#define OMAP3430_MUX_CTRL_SHIFT 0
++#define OMAP3430_MUX_CTRL_MASK (0x3 << 0)
++
++/* CM_CLKSTCTRL_EMU */
++#define OMAP3430_CLKTRCTRL_EMU_SHIFT 0
++#define OMAP3430_CLKTRCTRL_EMU_MASK (0x3 << 0)
++
++/* CM_CLKSTST_EMU */
++#define OMAP3430_CLKACTIVITY_EMU (1 << 0)
++
++/* CM_CLKSEL2_EMU specific bits */
++#define OMAP3430_CORE_DPLL_EMU_MULT_SHIFT 8
++#define OMAP3430_CORE_DPLL_EMU_MULT_MASK (0x7ff << 8)
++#define OMAP3430_CORE_DPLL_EMU_DIV_SHIFT 0
++#define OMAP3430_CORE_DPLL_EMU_DIV_MASK (0x7f << 0)
++
++/* CM_CLKSEL3_EMU specific bits */
++#define OMAP3430_PERIPH_DPLL_EMU_MULT_SHIFT 8
++#define OMAP3430_PERIPH_DPLL_EMU_MULT_MASK (0x7ff << 8)
++#define OMAP3430_PERIPH_DPLL_EMU_DIV_SHIFT 0
++#define OMAP3430_PERIPH_DPLL_EMU_DIV_MASK (0x7f << 0)
++
++/* CM_POLCTRL */
++#define OMAP3430_CLKOUT2_POL (1 << 0)
++
++/* CM_IDLEST_NEON */
++#define OMAP3430_ST_NEON (1 << 0)
++
++/* CM_CLKSTCTRL_NEON */
++#define OMAP3430_CLKTRCTRL_NEON_SHIFT 0
++#define OMAP3430_CLKTRCTRL_NEON_MASK (0x3 << 0)
++
++/* CM_FCLKEN_USBHOST */
++#define OMAP3430ES2_EN_USBHOST2_SHIFT 1
++#define OMAP3430ES2_EN_USBHOST2_MASK (1 << 1)
++#define OMAP3430ES2_EN_USBHOST1_SHIFT 0
++#define OMAP3430ES2_EN_USBHOST1_MASK (1 << 0)
++
++/* CM_ICLKEN_USBHOST */
++#define OMAP3430ES2_EN_USBHOST_SHIFT 0
++#define OMAP3430ES2_EN_USBHOST_MASK (1 << 0)
++
++/* CM_IDLEST_USBHOST */
++
++/* CM_AUTOIDLE_USBHOST */
++#define OMAP3430ES2_AUTO_USBHOST_SHIFT 0
++#define OMAP3430ES2_AUTO_USBHOST_MASK (1 << 0)
++
++/* CM_SLEEPDEP_USBHOST */
++#define OMAP3430ES2_EN_MPU_SHIFT 1
++#define OMAP3430ES2_EN_MPU_MASK (1 << 1)
++#define OMAP3430ES2_EN_IVA2_SHIFT 2
++#define OMAP3430ES2_EN_IVA2_MASK (1 << 2)
++
++/* CM_CLKSTCTRL_USBHOST */
++#define OMAP3430ES2_CLKTRCTRL_USBHOST_SHIFT 0
++#define OMAP3430ES2_CLKTRCTRL_USBHOST_MASK (3 << 0)
++
++
++
++#endif
+diff --git a/arch/arm/mach-omap2/cm.h b/arch/arm/mach-omap2/cm.h
+new file mode 100644
+index 0000000..8489f30
+--- /dev/null
++++ b/arch/arm/mach-omap2/cm.h
+@@ -0,0 +1,124 @@
++#ifndef __ARCH_ASM_MACH_OMAP2_CM_H
++#define __ARCH_ASM_MACH_OMAP2_CM_H
++
++/*
++ * OMAP2/3 Clock Management (CM) register definitions
++ *
++ * Copyright (C) 2007-2008 Texas Instruments, Inc.
++ * Copyright (C) 2007-2008 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "prcm-common.h"
++
++#ifndef __ASSEMBLER__
++#define OMAP_CM_REGADDR(module, reg) \
++ (void __iomem *)IO_ADDRESS(OMAP2_CM_BASE + (module) + (reg))
++#else
++#define OMAP2420_CM_REGADDR(module, reg) \
++ IO_ADDRESS(OMAP2420_CM_BASE + (module) + (reg))
++#define OMAP2430_CM_REGADDR(module, reg) \
++ IO_ADDRESS(OMAP2430_CM_BASE + (module) + (reg))
++#define OMAP34XX_CM_REGADDR(module, reg) \
++ IO_ADDRESS(OMAP3430_CM_BASE + (module) + (reg))
++#endif
++
++/*
++ * Architecture-specific global CM registers
++ * Use cm_{read,write}_reg() with these registers.
++ * These registers appear once per CM module.
++ */
++
++#define OMAP3430_CM_REVISION OMAP_CM_REGADDR(OCP_MOD, 0x0000)
++#define OMAP3430_CM_SYSCONFIG OMAP_CM_REGADDR(OCP_MOD, 0x0010)
++#define OMAP3430_CM_POLCTRL OMAP_CM_REGADDR(OCP_MOD, 0x009c)
++
++#define OMAP3430_CM_CLKOUT_CTRL OMAP_CM_REGADDR(OMAP3430_CCR_MOD, 0x0070)
++
++/*
++ * Module specific CM registers from CM_BASE + domain offset
++ * Use cm_{read,write}_mod_reg() with these registers.
++ * These register offsets generally appear in more than one PRCM submodule.
++ */
++
++/* Common between 24xx and 34xx */
++
++#define CM_FCLKEN 0x0000
++#define CM_FCLKEN1 CM_FCLKEN
++#define CM_CLKEN CM_FCLKEN
++#define CM_ICLKEN 0x0010
++#define CM_ICLKEN1 CM_ICLKEN
++#define CM_ICLKEN2 0x0014
++#define CM_ICLKEN3 0x0018
++#define CM_IDLEST 0x0020
++#define CM_IDLEST1 CM_IDLEST
++#define CM_IDLEST2 0x0024
++#define CM_AUTOIDLE 0x0030
++#define CM_AUTOIDLE1 CM_AUTOIDLE
++#define CM_AUTOIDLE2 0x0034
++#define CM_AUTOIDLE3 0x0038
++#define CM_CLKSEL 0x0040
++#define CM_CLKSEL1 CM_CLKSEL
++#define CM_CLKSEL2 0x0044
++#define CM_CLKSTCTRL 0x0048
++
++
++/* Architecture-specific registers */
++
++#define OMAP24XX_CM_FCLKEN2 0x0004
++#define OMAP24XX_CM_ICLKEN4 0x001c
++#define OMAP24XX_CM_AUTOIDLE4 0x003c
++
++#define OMAP2430_CM_IDLEST3 0x0028
++
++#define OMAP3430_CM_CLKEN_PLL 0x0004
++#define OMAP3430ES2_CM_CLKEN2 0x0004
++#define OMAP3430ES2_CM_FCLKEN3 0x0008
++#define OMAP3430_CM_IDLEST_PLL CM_IDLEST2
++#define OMAP3430_CM_AUTOIDLE_PLL CM_AUTOIDLE2
++#define OMAP3430_CM_CLKSEL1 CM_CLKSEL
++#define OMAP3430_CM_CLKSEL1_PLL CM_CLKSEL
++#define OMAP3430_CM_CLKSEL2_PLL CM_CLKSEL2
++#define OMAP3430_CM_SLEEPDEP CM_CLKSEL2
++#define OMAP3430_CM_CLKSEL3 CM_CLKSTCTRL
++#define OMAP3430_CM_CLKSTST 0x004c
++#define OMAP3430ES2_CM_CLKSEL4 0x004c
++#define OMAP3430ES2_CM_CLKSEL5 0x0050
++#define OMAP3430_CM_CLKSEL2_EMU 0x0050
++#define OMAP3430_CM_CLKSEL3_EMU 0x0054
++
++
++/* Clock management domain register get/set */
++
++#ifndef __ASSEMBLER__
++static inline void cm_write_mod_reg(u32 val, s16 module, s16 idx)
++{
++ __raw_writel(val, OMAP_CM_REGADDR(module, idx));
++}
++
++static inline u32 cm_read_mod_reg(s16 module, s16 idx)
++{
++ return __raw_readl(OMAP_CM_REGADDR(module, idx));
++}
++#endif
++
++/* CM register bits shared between 24XX and 3430 */
++
++/* CM_CLKSEL_GFX */
++#define OMAP_CLKSEL_GFX_SHIFT 0
++#define OMAP_CLKSEL_GFX_MASK (0x7 << 0)
++
++/* CM_ICLKEN_GFX */
++#define OMAP_EN_GFX_SHIFT 0
++#define OMAP_EN_GFX (1 << 0)
++
++/* CM_IDLEST_GFX */
++#define OMAP_ST_GFX (1 << 0)
++
++
++#endif
+diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
+new file mode 100644
+index 0000000..a5d86a4
+--- /dev/null
++++ b/arch/arm/mach-omap2/control.c
+@@ -0,0 +1,74 @@
++/*
++ * OMAP2/3 System Control Module register access
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ * Copyright (C) 2007 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#undef DEBUG
++
++#include <linux/kernel.h>
++
++#include <asm/io.h>
++
++#include <asm/arch/control.h>
++
++static u32 omap2_ctrl_base;
++
++#define OMAP_CTRL_REGADDR(reg) (void __iomem *)IO_ADDRESS(omap2_ctrl_base \
++ + (reg))
++
++void omap_ctrl_base_set(u32 base)
++{
++ omap2_ctrl_base = base;
++}
++
++u32 omap_ctrl_base_get(void)
++{
++ return omap2_ctrl_base;
++}
++
++u8 omap_ctrl_readb(u16 offset)
++{
++ return __raw_readb(OMAP_CTRL_REGADDR(offset));
++}
++
++u16 omap_ctrl_readw(u16 offset)
++{
++ return __raw_readw(OMAP_CTRL_REGADDR(offset));
++}
++
++u32 omap_ctrl_readl(u16 offset)
++{
++ return __raw_readl(OMAP_CTRL_REGADDR(offset));
++}
++
++void omap_ctrl_writeb(u8 val, u16 offset)
++{
++ pr_debug("omap_ctrl_writeb: writing 0x%0x to 0x%0x\n", val,
++ (u32)OMAP_CTRL_REGADDR(offset));
++
++ __raw_writeb(val, OMAP_CTRL_REGADDR(offset));
++}
++
++void omap_ctrl_writew(u16 val, u16 offset)
++{
++ pr_debug("omap_ctrl_writew: writing 0x%0x to 0x%0x\n", val,
++ (u32)OMAP_CTRL_REGADDR(offset));
++
++ __raw_writew(val, OMAP_CTRL_REGADDR(offset));
++}
++
++void omap_ctrl_writel(u32 val, u16 offset)
++{
++ pr_debug("omap_ctrl_writel: writing 0x%0x to 0x%0x\n", val,
++ (u32)OMAP_CTRL_REGADDR(offset));
++
++ __raw_writel(val, OMAP_CTRL_REGADDR(offset));
++}
++
+diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
+index 5a4cc20..02cede2 100644
+--- a/arch/arm/mach-omap2/gpmc.c
++++ b/arch/arm/mach-omap2/gpmc.c
+@@ -69,7 +69,7 @@ static void __iomem *gpmc_base =
+ static void __iomem *gpmc_cs_base =
+ (void __iomem *) IO_ADDRESS(GPMC_BASE) + GPMC_CS0;
+
+-static struct clk *gpmc_l3_clk;
++static struct clk *gpmc_fck;
+
+ static void gpmc_write_reg(int idx, u32 val)
+ {
+@@ -94,11 +94,10 @@ u32 gpmc_cs_read_reg(int cs, int idx)
+ return __raw_readl(gpmc_cs_base + (cs * GPMC_CS_SIZE) + idx);
+ }
+
+-/* TODO: Add support for gpmc_fck to clock framework and use it */
+ unsigned long gpmc_get_fclk_period(void)
+ {
+ /* In picoseconds */
+- return 1000000000 / ((clk_get_rate(gpmc_l3_clk)) / 1000);
++ return 1000000000 / ((clk_get_rate(gpmc_fck)) / 1000);
+ }
+
+ unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
+@@ -398,8 +397,11 @@ void __init gpmc_init(void)
+ {
+ u32 l;
+
+- gpmc_l3_clk = clk_get(NULL, "core_l3_ck");
+- BUG_ON(IS_ERR(gpmc_l3_clk));
++ gpmc_fck = clk_get(NULL, "gpmc_fck"); /* Always on ENABLE_ON_INIT */
++ if (IS_ERR(gpmc_fck))
++ WARN_ON(1);
++ else
++ clk_enable(gpmc_fck);
+
+ l = gpmc_read_reg(GPMC_REVISION);
+ printk(KERN_INFO "GPMC revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
+diff --git a/arch/arm/mach-omap2/memory.c b/arch/arm/mach-omap2/memory.c
+index 3e5d8cd..1247908 100644
+--- a/arch/arm/mach-omap2/memory.c
++++ b/arch/arm/mach-omap2/memory.c
+@@ -27,11 +27,16 @@
+ #include <asm/arch/clock.h>
+ #include <asm/arch/sram.h>
+
+-#include "prcm-regs.h"
++#include "prm.h"
++
+ #include "memory.h"
++#include "sdrc.h"
+
++unsigned long omap2_sdrc_base;
++unsigned long omap2_sms_base;
+
+ static struct memory_timings mem_timings;
++static u32 curr_perf_level = CORE_CLK_SRC_DPLL_X2;
+
+ u32 omap2_memory_get_slow_dll_ctrl(void)
+ {
+@@ -48,12 +53,60 @@ u32 omap2_memory_get_type(void)
+ return mem_timings.m_type;
+ }
+
++/*
++ * Check the DLL lock state, and return tue if running in unlock mode.
++ * This is needed to compensate for the shifted DLL value in unlock mode.
++ */
++u32 omap2_dll_force_needed(void)
++{
++ /* dlla and dllb are a set */
++ u32 dll_state = sdrc_read_reg(SDRC_DLLA_CTRL);
++
++ if ((dll_state & (1 << 2)) == (1 << 2))
++ return 1;
++ else
++ return 0;
++}
++
++/*
++ * 'level' is the value to store to CM_CLKSEL2_PLL.CORE_CLK_SRC.
++ * Practical values are CORE_CLK_SRC_DPLL (for CORE_CLK = DPLL_CLK) or
++ * CORE_CLK_SRC_DPLL_X2 (for CORE_CLK = * DPLL_CLK * 2)
++ */
++u32 omap2_reprogram_sdrc(u32 level, u32 force)
++{
++ u32 dll_ctrl, m_type;
++ u32 prev = curr_perf_level;
++ unsigned long flags;
++
++ if ((curr_perf_level == level) && !force)
++ return prev;
++
++ if (level == CORE_CLK_SRC_DPLL) {
++ dll_ctrl = omap2_memory_get_slow_dll_ctrl();
++ } else if (level == CORE_CLK_SRC_DPLL_X2) {
++ dll_ctrl = omap2_memory_get_fast_dll_ctrl();
++ } else {
++ return prev;
++ }
++
++ m_type = omap2_memory_get_type();
++
++ local_irq_save(flags);
++ __raw_writel(0xffff, OMAP24XX_PRCM_VOLTSETUP);
++ omap2_sram_reprogram_sdrc(level, dll_ctrl, m_type);
++ curr_perf_level = level;
++ local_irq_restore(flags);
++
++ return prev;
++}
++
+ void omap2_init_memory_params(u32 force_lock_to_unlock_mode)
+ {
+ unsigned long dll_cnt;
+ u32 fast_dll = 0;
+
+- mem_timings.m_type = !((SDRC_MR_0 & 0x3) == 0x1); /* DDR = 1, SDR = 0 */
++ mem_timings.m_type = !((sdrc_read_reg(SDRC_MR_0) & 0x3) == 0x1); /* DDR = 1, SDR = 0 */
+
+ /* 2422 es2.05 and beyond has a single SIP DDR instead of 2 like others.
+ * In the case of 2422, its ok to use CS1 instead of CS0.
+@@ -73,11 +126,11 @@ void omap2_init_memory_params(u32 force_lock_to_unlock_mode)
+ mem_timings.dll_mode = M_LOCK;
+
+ if (mem_timings.base_cs == 0) {
+- fast_dll = SDRC_DLLA_CTRL;
+- dll_cnt = SDRC_DLLA_STATUS & 0xff00;
++ fast_dll = sdrc_read_reg(SDRC_DLLA_CTRL);
++ dll_cnt = sdrc_read_reg(SDRC_DLLA_STATUS) & 0xff00;
+ } else {
+- fast_dll = SDRC_DLLB_CTRL;
+- dll_cnt = SDRC_DLLB_STATUS & 0xff00;
++ fast_dll = sdrc_read_reg(SDRC_DLLB_CTRL);
++ dll_cnt = sdrc_read_reg(SDRC_DLLB_STATUS) & 0xff00;
+ }
+ if (force_lock_to_unlock_mode) {
+ fast_dll &= ~0xff00;
+@@ -106,14 +159,13 @@ void __init omap2_init_memory(void)
+ {
+ u32 l;
+
+- l = SMS_SYSCONFIG;
++ l = sms_read_reg(SMS_SYSCONFIG);
+ l &= ~(0x3 << 3);
+ l |= (0x2 << 3);
+- SMS_SYSCONFIG = l;
++ sms_write_reg(l, SMS_SYSCONFIG);
+
+- l = SDRC_SYSCONFIG;
++ l = sdrc_read_reg(SDRC_SYSCONFIG);
+ l &= ~(0x3 << 3);
+ l |= (0x2 << 3);
+- SDRC_SYSCONFIG = l;
+-
++ sdrc_write_reg(l, SDRC_SYSCONFIG);
+ }
+diff --git a/arch/arm/mach-omap2/memory.h b/arch/arm/mach-omap2/memory.h
+index d212eea..9a280b5 100644
+--- a/arch/arm/mach-omap2/memory.h
++++ b/arch/arm/mach-omap2/memory.h
+@@ -32,3 +32,5 @@ extern void omap2_init_memory_params(u32 force_lock_to_unlock_mode);
+ extern u32 omap2_memory_get_slow_dll_ctrl(void);
+ extern u32 omap2_memory_get_fast_dll_ctrl(void);
+ extern u32 omap2_memory_get_type(void);
++u32 omap2_dll_force_needed(void);
++u32 omap2_reprogram_sdrc(u32 level, u32 force);
+diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
+index 0575097..9307700 100644
+--- a/arch/arm/mach-omap2/mux.c
++++ b/arch/arm/mach-omap2/mux.c
+@@ -1,11 +1,12 @@
+ /*
+ * linux/arch/arm/mach-omap2/mux.c
+ *
+- * OMAP1 pin multiplexing configurations
++ * OMAP2 pin multiplexing configurations
+ *
+- * Copyright (C) 2003 - 2005 Nokia Corporation
++ * Copyright (C) 2004 - 2008 Texas Instruments Inc.
++ * Copyright (C) 2003 - 2008 Nokia Corporation
+ *
+- * Written by Tony Lindgren <tony.lindgren at nokia.com>
++ * Written by Tony Lindgren
+ *
+ * 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
+@@ -28,13 +29,17 @@
+ #include <asm/io.h>
+ #include <linux/spinlock.h>
+
++#include <asm/arch/control.h>
+ #include <asm/arch/mux.h>
+
+ #ifdef CONFIG_OMAP_MUX
+
++static struct omap_mux_cfg arch_mux_cfg;
++
+ /* NOTE: See mux.h for the enumeration */
+
+-struct pin_config __initdata_or_module omap24xx_pins[] = {
++#ifdef CONFIG_ARCH_OMAP24XX
++static struct pin_config __initdata_or_module omap24xx_pins[] = {
+ /*
+ * description mux mux pull pull debug
+ * offset mode ena type
+@@ -77,7 +82,12 @@ MUX_CFG_24XX("AA12_242X_GPIO17", 0x0e9, 3, 0, 0, 1)
+ MUX_CFG_24XX("AA8_242X_GPIO58", 0x0ea, 3, 0, 0, 1)
+ MUX_CFG_24XX("Y20_24XX_GPIO60", 0x12c, 3, 0, 0, 1)
+ MUX_CFG_24XX("W4__24XX_GPIO74", 0x0f2, 3, 0, 0, 1)
++MUX_CFG_24XX("N15_24XX_GPIO85", 0x103, 3, 0, 0, 1)
+ MUX_CFG_24XX("M15_24XX_GPIO92", 0x10a, 3, 0, 0, 1)
++MUX_CFG_24XX("P20_24XX_GPIO93", 0x10b, 3, 0, 0, 1)
++MUX_CFG_24XX("P18_24XX_GPIO95", 0x10d, 3, 0, 0, 1)
++MUX_CFG_24XX("M18_24XX_GPIO96", 0x10e, 3, 0, 0, 1)
++MUX_CFG_24XX("L14_24XX_GPIO97", 0x10f, 3, 0, 0, 1)
+ MUX_CFG_24XX("J15_24XX_GPIO99", 0x113, 3, 1, 1, 1)
+ MUX_CFG_24XX("V14_24XX_GPIO117", 0x128, 3, 1, 0, 1)
+ MUX_CFG_24XX("P14_24XX_GPIO125", 0x140, 3, 1, 1, 1)
+@@ -102,9 +112,6 @@ MUX_CFG_24XX("G4_242X_DMAREQ3", 0x073, 2, 0, 0, 1)
+ MUX_CFG_24XX("D3_242X_DMAREQ4", 0x072, 2, 0, 0, 1)
+ MUX_CFG_24XX("E3_242X_DMAREQ5", 0x071, 2, 0, 0, 1)
+
+-/* TSC IRQ */
+-MUX_CFG_24XX("P20_24XX_TSC_IRQ", 0x108, 0, 0, 0, 1)
+-
+ /* UART3 */
+ MUX_CFG_24XX("K15_24XX_UART3_TX", 0x118, 0, 0, 0, 1)
+ MUX_CFG_24XX("K14_24XX_UART3_RX", 0x119, 0, 0, 0, 1)
+@@ -167,12 +174,108 @@ MUX_CFG_24XX("B3__24XX_KBR5", 0x30, 3, 1, 1, 1)
+ MUX_CFG_24XX("AA4_24XX_KBC2", 0xe7, 3, 0, 0, 1)
+ MUX_CFG_24XX("B13_24XX_KBC6", 0x110, 3, 0, 0, 1)
+
++/* 2430 USB */
++MUX_CFG_24XX("AD9_2430_USB0_PUEN", 0x133, 4, 0, 0, 1)
++MUX_CFG_24XX("Y11_2430_USB0_VP", 0x134, 4, 0, 0, 1)
++MUX_CFG_24XX("AD7_2430_USB0_VM", 0x135, 4, 0, 0, 1)
++MUX_CFG_24XX("AE7_2430_USB0_RCV", 0x136, 4, 0, 0, 1)
++MUX_CFG_24XX("AD4_2430_USB0_TXEN", 0x137, 4, 0, 0, 1)
++MUX_CFG_24XX("AF9_2430_USB0_SE0", 0x138, 4, 0, 0, 1)
++MUX_CFG_24XX("AE6_2430_USB0_DAT", 0x139, 4, 0, 0, 1)
++MUX_CFG_24XX("AD24_2430_USB1_SE0", 0x107, 2, 0, 0, 1)
++MUX_CFG_24XX("AB24_2430_USB1_RCV", 0x108, 2, 0, 0, 1)
++MUX_CFG_24XX("Y25_2430_USB1_TXEN", 0x109, 2, 0, 0, 1)
++MUX_CFG_24XX("AA26_2430_USB1_DAT", 0x10A, 2, 0, 0, 1)
++
++/* 2430 HS-USB */
++MUX_CFG_24XX("AD9_2430_USB0HS_DATA3", 0x133, 0, 0, 0, 1)
++MUX_CFG_24XX("Y11_2430_USB0HS_DATA4", 0x134, 0, 0, 0, 1)
++MUX_CFG_24XX("AD7_2430_USB0HS_DATA5", 0x135, 0, 0, 0, 1)
++MUX_CFG_24XX("AE7_2430_USB0HS_DATA6", 0x136, 0, 0, 0, 1)
++MUX_CFG_24XX("AD4_2430_USB0HS_DATA2", 0x137, 0, 0, 0, 1)
++MUX_CFG_24XX("AF9_2430_USB0HS_DATA0", 0x138, 0, 0, 0, 1)
++MUX_CFG_24XX("AE6_2430_USB0HS_DATA1", 0x139, 0, 0, 0, 1)
++MUX_CFG_24XX("AE8_2430_USB0HS_CLK", 0x13A, 0, 0, 0, 1)
++MUX_CFG_24XX("AD8_2430_USB0HS_DIR", 0x13B, 0, 0, 0, 1)
++MUX_CFG_24XX("AE5_2430_USB0HS_STP", 0x13c, 0, 1, 1, 1)
++MUX_CFG_24XX("AE9_2430_USB0HS_NXT", 0x13D, 0, 0, 0, 1)
++MUX_CFG_24XX("AC7_2430_USB0HS_DATA7", 0x13E, 0, 0, 0, 1)
++
++/* 2430 McBSP */
++MUX_CFG_24XX("AC10_2430_MCBSP2_FSX", 0x012E, 1, 0, 0, 1)
++MUX_CFG_24XX("AD16_2430_MCBSP2_CLX", 0x012F, 1, 0, 0, 1)
++MUX_CFG_24XX("AE13_2430_MCBSP2_DX", 0x0130, 1, 0, 0, 1)
++MUX_CFG_24XX("AD13_2430_MCBSP2_DR", 0x0131, 1, 0, 0, 1)
++MUX_CFG_24XX("AC10_2430_MCBSP2_FSX_OFF",0x012E, 0, 0, 0, 1)
++MUX_CFG_24XX("AD16_2430_MCBSP2_CLX_OFF",0x012F, 0, 0, 0, 1)
++MUX_CFG_24XX("AE13_2430_MCBSP2_DX_OFF", 0x0130, 0, 0, 0, 1)
++MUX_CFG_24XX("AD13_2430_MCBSP2_DR_OFF", 0x0131, 0, 0, 0, 1)
+ };
+
+-int __init omap2_mux_init(void)
++#define OMAP24XX_PINS_SZ ARRAY_SIZE(omap24xx_pins)
++
++#else
++#define omap24xx_pins NULL
++#define OMAP24XX_PINS_SZ 0
++#endif /* CONFIG_ARCH_OMAP24XX */
++
++#define OMAP24XX_PULL_ENA (1 << 3)
++#define OMAP24XX_PULL_UP (1 << 4)
++
++#if defined(CONFIG_OMAP_MUX_DEBUG) || defined(CONFIG_OMAP_MUX_WARNINGS)
++void __init_or_module omap2_cfg_debug(const struct pin_config *cfg, u8 reg)
+ {
+- omap_mux_register(omap24xx_pins, ARRAY_SIZE(omap24xx_pins));
++ u16 orig;
++ u8 warn = 0, debug = 0;
++
++ orig = omap_ctrl_readb(cfg->mux_reg);
++
++#ifdef CONFIG_OMAP_MUX_DEBUG
++ debug = cfg->debug;
++#endif
++ warn = (orig != reg);
++ if (debug || warn)
++ printk(KERN_WARNING
++ "MUX: setup %s (0x%08x): 0x%02x -> 0x%02x\n",
++ cfg->name, omap_ctrl_base_get() + cfg->mux_reg,
++ orig, reg);
++}
++#else
++#define omap2_cfg_debug(x, y) do {} while (0)
++#endif
++
++#ifdef CONFIG_ARCH_OMAP24XX
++int __init_or_module omap24xx_cfg_reg(const struct pin_config *cfg)
++{
++ static DEFINE_SPINLOCK(mux_spin_lock);
++ unsigned long flags;
++ u8 reg = 0;
++
++ spin_lock_irqsave(&mux_spin_lock, flags);
++ reg |= cfg->mask & 0x7;
++ if (cfg->pull_val)
++ reg |= OMAP24XX_PULL_ENA;
++ if (cfg->pu_pd_val)
++ reg |= OMAP24XX_PULL_UP;
++ omap2_cfg_debug(cfg, reg);
++ omap_ctrl_writeb(reg, cfg->mux_reg);
++ spin_unlock_irqrestore(&mux_spin_lock, flags);
++
+ return 0;
+ }
++#else
++#define omap24xx_cfg_reg 0
++#endif
++
++int __init omap2_mux_init(void)
++{
++ if (cpu_is_omap24xx()) {
++ arch_mux_cfg.pins = omap24xx_pins;
++ arch_mux_cfg.size = OMAP24XX_PINS_SZ;
++ arch_mux_cfg.cfg_reg = omap24xx_cfg_reg;
++ }
++
++ return omap_mux_register(&arch_mux_cfg);
++}
+
+ #endif
+diff --git a/arch/arm/mach-omap2/pm-domain.c b/arch/arm/mach-omap2/pm-domain.c
+deleted file mode 100644
+index 2494091..0000000
+--- a/arch/arm/mach-omap2/pm-domain.c
++++ /dev/null
+@@ -1,299 +0,0 @@
+-/*
+- * linux/arch/arm/mach-omap2/pm-domain.c
+- *
+- * Power domain functions for OMAP2
+- *
+- * Copyright (C) 2006 Nokia Corporation
+- * Tony Lindgren <tony at atomide.com>
+- *
+- * Some code based on earlier OMAP2 sample PM code
+- * Copyright (C) 2005 Texas Instruments, Inc.
+- * Richard Woodruff <r-woodruff2 at ti.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/clk.h>
+-
+-#include <asm/io.h>
+-
+-#include "prcm-regs.h"
+-
+-/* Power domain offsets */
+-#define PM_MPU_OFFSET 0x100
+-#define PM_CORE_OFFSET 0x200
+-#define PM_GFX_OFFSET 0x300
+-#define PM_WKUP_OFFSET 0x400 /* Autoidle only */
+-#define PM_PLL_OFFSET 0x500 /* Autoidle only */
+-#define PM_DSP_OFFSET 0x800
+-#define PM_MDM_OFFSET 0xc00
+-
+-/* Power domain wake-up dependency control register */
+-#define PM_WKDEP_OFFSET 0xc8
+-#define EN_MDM (1 << 5)
+-#define EN_WKUP (1 << 4)
+-#define EN_GFX (1 << 3)
+-#define EN_DSP (1 << 2)
+-#define EN_MPU (1 << 1)
+-#define EN_CORE (1 << 0)
+-
+-/* Core power domain state transition control register */
+-#define PM_PWSTCTRL_OFFSET 0xe0
+-#define FORCESTATE (1 << 18) /* Only for DSP & GFX */
+-#define MEM4RETSTATE (1 << 6)
+-#define MEM3RETSTATE (1 << 5)
+-#define MEM2RETSTATE (1 << 4)
+-#define MEM1RETSTATE (1 << 3)
+-#define LOGICRETSTATE (1 << 2) /* Logic is retained */
+-#define POWERSTATE_OFF 0x3
+-#define POWERSTATE_RETENTION 0x1
+-#define POWERSTATE_ON 0x0
+-
+-/* Power domain state register */
+-#define PM_PWSTST_OFFSET 0xe4
+-
+-/* Hardware supervised state transition control register */
+-#define CM_CLKSTCTRL_OFFSET 0x48
+-#define AUTOSTAT_MPU (1 << 0) /* MPU */
+-#define AUTOSTAT_DSS (1 << 2) /* Core */
+-#define AUTOSTAT_L4 (1 << 1) /* Core */
+-#define AUTOSTAT_L3 (1 << 0) /* Core */
+-#define AUTOSTAT_GFX (1 << 0) /* GFX */
+-#define AUTOSTAT_IVA (1 << 8) /* 2420 IVA in DSP domain */
+-#define AUTOSTAT_DSP (1 << 0) /* DSP */
+-#define AUTOSTAT_MDM (1 << 0) /* MDM */
+-
+-/* Automatic control of interface clock idling */
+-#define CM_AUTOIDLE1_OFFSET 0x30
+-#define CM_AUTOIDLE2_OFFSET 0x34 /* Core only */
+-#define CM_AUTOIDLE3_OFFSET 0x38 /* Core only */
+-#define CM_AUTOIDLE4_OFFSET 0x3c /* Core only */
+-#define AUTO_54M(x) (((x) & 0x3) << 6)
+-#define AUTO_96M(x) (((x) & 0x3) << 2)
+-#define AUTO_DPLL(x) (((x) & 0x3) << 0)
+-#define AUTO_STOPPED 0x3
+-#define AUTO_BYPASS_FAST 0x2 /* DPLL only */
+-#define AUTO_BYPASS_LOW_POWER 0x1 /* DPLL only */
+-#define AUTO_DISABLED 0x0
+-
+-/* Voltage control PRCM_VOLTCTRL bits */
+-#define AUTO_EXTVOLT (1 << 15)
+-#define FORCE_EXTVOLT (1 << 14)
+-#define SETOFF_LEVEL(x) (((x) & 0x3) << 12)
+-#define MEMRETCTRL (1 << 8)
+-#define SETRET_LEVEL(x) (((x) & 0x3) << 6)
+-#define VOLT_LEVEL(x) (((x) & 0x3) << 0)
+-
+-#define OMAP24XX_PRCM_VBASE IO_ADDRESS(OMAP24XX_PRCM_BASE)
+-#define prcm_readl(r) __raw_readl(OMAP24XX_PRCM_VBASE + (r))
+-#define prcm_writel(v, r) __raw_writel((v), OMAP24XX_PRCM_VBASE + (r))
+-
+-static u32 pmdomain_get_wakeup_dependencies(int domain_offset)
+-{
+- return prcm_readl(domain_offset + PM_WKDEP_OFFSET);
+-}
+-
+-static void pmdomain_set_wakeup_dependencies(u32 state, int domain_offset)
+-{
+- prcm_writel(state, domain_offset + PM_WKDEP_OFFSET);
+-}
+-
+-static u32 pmdomain_get_powerstate(int domain_offset)
+-{
+- return prcm_readl(domain_offset + PM_PWSTCTRL_OFFSET);
+-}
+-
+-static void pmdomain_set_powerstate(u32 state, int domain_offset)
+-{
+- prcm_writel(state, domain_offset + PM_PWSTCTRL_OFFSET);
+-}
+-
+-static u32 pmdomain_get_clock_autocontrol(int domain_offset)
+-{
+- return prcm_readl(domain_offset + CM_CLKSTCTRL_OFFSET);
+-}
+-
+-static void pmdomain_set_clock_autocontrol(u32 state, int domain_offset)
+-{
+- prcm_writel(state, domain_offset + CM_CLKSTCTRL_OFFSET);
+-}
+-
+-static u32 pmdomain_get_clock_autoidle1(int domain_offset)
+-{
+- return prcm_readl(domain_offset + CM_AUTOIDLE1_OFFSET);
+-}
+-
+-/* Core domain only */
+-static u32 pmdomain_get_clock_autoidle2(int domain_offset)
+-{
+- return prcm_readl(domain_offset + CM_AUTOIDLE2_OFFSET);
+-}
+-
+-/* Core domain only */
+-static u32 pmdomain_get_clock_autoidle3(int domain_offset)
+-{
+- return prcm_readl(domain_offset + CM_AUTOIDLE3_OFFSET);
+-}
+-
+-/* Core domain only */
+-static u32 pmdomain_get_clock_autoidle4(int domain_offset)
+-{
+- return prcm_readl(domain_offset + CM_AUTOIDLE4_OFFSET);
+-}
+-
+-static void pmdomain_set_clock_autoidle1(u32 state, int domain_offset)
+-{
+- prcm_writel(state, CM_AUTOIDLE1_OFFSET + domain_offset);
+-}
+-
+-/* Core domain only */
+-static void pmdomain_set_clock_autoidle2(u32 state, int domain_offset)
+-{
+- prcm_writel(state, CM_AUTOIDLE2_OFFSET + domain_offset);
+-}
+-
+-/* Core domain only */
+-static void pmdomain_set_clock_autoidle3(u32 state, int domain_offset)
+-{
+- prcm_writel(state, CM_AUTOIDLE3_OFFSET + domain_offset);
+-}
+-
+-/* Core domain only */
+-static void pmdomain_set_clock_autoidle4(u32 state, int domain_offset)
+-{
+- prcm_writel(state, CM_AUTOIDLE4_OFFSET + domain_offset);
+-}
+-
+-/*
+- * Configures power management domains to idle clocks automatically.
+- */
+-void pmdomain_set_autoidle(void)
+-{
+- u32 val;
+-
+- /* Set PLL auto stop for 54M, 96M & DPLL */
+- pmdomain_set_clock_autoidle1(AUTO_54M(AUTO_STOPPED) |
+- AUTO_96M(AUTO_STOPPED) |
+- AUTO_DPLL(AUTO_STOPPED), PM_PLL_OFFSET);
+-
+- /* External clock input control
+- * REVISIT: Should this be in clock framework?
+- */
+- PRCM_CLKSRC_CTRL |= (0x3 << 3);
+-
+- /* Configure number of 32KHz clock cycles for sys_clk */
+- PRCM_CLKSSETUP = 0x00ff;
+-
+- /* Configure automatic voltage transition */
+- PRCM_VOLTSETUP = 0;
+- val = PRCM_VOLTCTRL;
+- val &= ~(SETOFF_LEVEL(0x3) | VOLT_LEVEL(0x3));
+- val |= SETOFF_LEVEL(1) | VOLT_LEVEL(1) | AUTO_EXTVOLT;
+- PRCM_VOLTCTRL = val;
+-
+- /* Disable emulation tools functional clock */
+- PRCM_CLKEMUL_CTRL = 0x0;
+-
+- /* Set core memory retention state */
+- val = pmdomain_get_powerstate(PM_CORE_OFFSET);
+- if (cpu_is_omap2420()) {
+- val &= ~(0x7 << 3);
+- val |= (MEM3RETSTATE | MEM2RETSTATE | MEM1RETSTATE);
+- } else {
+- val &= ~(0xf << 3);
+- val |= (MEM4RETSTATE | MEM3RETSTATE | MEM2RETSTATE |
+- MEM1RETSTATE);
+- }
+- pmdomain_set_powerstate(val, PM_CORE_OFFSET);
+-
+- /* OCP interface smart idle. REVISIT: Enable autoidle bit0 ? */
+- val = SMS_SYSCONFIG;
+- val &= ~(0x3 << 3);
+- val |= (0x2 << 3) | (1 << 0);
+- SMS_SYSCONFIG |= val;
+-
+- val = SDRC_SYSCONFIG;
+- val &= ~(0x3 << 3);
+- val |= (0x2 << 3);
+- SDRC_SYSCONFIG = val;
+-
+- /* Configure L3 interface for smart idle.
+- * REVISIT: Enable autoidle bit0 ?
+- */
+- val = GPMC_SYSCONFIG;
+- val &= ~(0x3 << 3);
+- val |= (0x2 << 3) | (1 << 0);
+- GPMC_SYSCONFIG = val;
+-
+- pmdomain_set_powerstate(LOGICRETSTATE | POWERSTATE_RETENTION,
+- PM_MPU_OFFSET);
+- pmdomain_set_powerstate(POWERSTATE_RETENTION, PM_CORE_OFFSET);
+- if (!cpu_is_omap2420())
+- pmdomain_set_powerstate(POWERSTATE_RETENTION, PM_MDM_OFFSET);
+-
+- /* Assume suspend function has saved the state for DSP and GFX */
+- pmdomain_set_powerstate(FORCESTATE | POWERSTATE_OFF, PM_DSP_OFFSET);
+- pmdomain_set_powerstate(FORCESTATE | POWERSTATE_OFF, PM_GFX_OFFSET);
+-
+-#if 0
+- /* REVISIT: Internal USB needs special handling */
+- force_standby_usb();
+- if (cpu_is_omap2430())
+- force_hsmmc();
+- sdram_self_refresh_on_idle_req(1);
+-#endif
+-
+- /* Enable clock auto control for all domains.
+- * Note that CORE domain includes also DSS, L4 & L3.
+- */
+- pmdomain_set_clock_autocontrol(AUTOSTAT_MPU, PM_MPU_OFFSET);
+- pmdomain_set_clock_autocontrol(AUTOSTAT_GFX, PM_GFX_OFFSET);
+- pmdomain_set_clock_autocontrol(AUTOSTAT_DSS | AUTOSTAT_L4 | AUTOSTAT_L3,
+- PM_CORE_OFFSET);
+- if (cpu_is_omap2420())
+- pmdomain_set_clock_autocontrol(AUTOSTAT_IVA | AUTOSTAT_DSP,
+- PM_DSP_OFFSET);
+- else {
+- pmdomain_set_clock_autocontrol(AUTOSTAT_DSP, PM_DSP_OFFSET);
+- pmdomain_set_clock_autocontrol(AUTOSTAT_MDM, PM_MDM_OFFSET);
+- }
+-
+- /* Enable clock autoidle for all domains */
+- pmdomain_set_clock_autoidle1(0x2, PM_DSP_OFFSET);
+- if (cpu_is_omap2420()) {
+- pmdomain_set_clock_autoidle1(0xfffffff9, PM_CORE_OFFSET);
+- pmdomain_set_clock_autoidle2(0x7, PM_CORE_OFFSET);
+- pmdomain_set_clock_autoidle1(0x3f, PM_WKUP_OFFSET);
+- } else {
+- pmdomain_set_clock_autoidle1(0xeafffff1, PM_CORE_OFFSET);
+- pmdomain_set_clock_autoidle2(0xfff, PM_CORE_OFFSET);
+- pmdomain_set_clock_autoidle1(0x7f, PM_WKUP_OFFSET);
+- pmdomain_set_clock_autoidle1(0x3, PM_MDM_OFFSET);
+- }
+- pmdomain_set_clock_autoidle3(0x7, PM_CORE_OFFSET);
+- pmdomain_set_clock_autoidle4(0x1f, PM_CORE_OFFSET);
+-}
+-
+-/*
+- * Initializes power domains by removing wake-up dependencies and powering
+- * down DSP and GFX. Gets called from PM init. Note that DSP and IVA code
+- * must re-enable DSP and GFX when used.
+- */
+-void __init pmdomain_init(void)
+-{
+- /* Remove all domain wakeup dependencies */
+- pmdomain_set_wakeup_dependencies(EN_WKUP | EN_CORE, PM_MPU_OFFSET);
+- pmdomain_set_wakeup_dependencies(0, PM_DSP_OFFSET);
+- pmdomain_set_wakeup_dependencies(0, PM_GFX_OFFSET);
+- pmdomain_set_wakeup_dependencies(EN_WKUP | EN_MPU, PM_CORE_OFFSET);
+- if (cpu_is_omap2430())
+- pmdomain_set_wakeup_dependencies(0, PM_MDM_OFFSET);
+-
+- /* Power down DSP and GFX */
+- pmdomain_set_powerstate(POWERSTATE_OFF | FORCESTATE, PM_DSP_OFFSET);
+- pmdomain_set_powerstate(POWERSTATE_OFF | FORCESTATE, PM_GFX_OFFSET);
+-}
+diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
+index baf7d82..aad781d 100644
+--- a/arch/arm/mach-omap2/pm.c
++++ b/arch/arm/mach-omap2/pm.c
+@@ -23,6 +23,7 @@
+ #include <linux/sysfs.h>
+ #include <linux/module.h>
+ #include <linux/delay.h>
++#include <linux/clk.h>
+
+ #include <asm/io.h>
+ #include <asm/irq.h>
+@@ -36,8 +37,6 @@
+ #include <asm/arch/sram.h>
+ #include <asm/arch/pm.h>
+
+-#include "prcm-regs.h"
+-
+ static struct clk *vclk;
+ static void (*omap2_sram_idle)(void);
+ static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev);
+@@ -78,251 +77,8 @@ static int omap2_pm_prepare(void)
+ return 0;
+ }
+
+-#define INT0_WAKE_MASK (OMAP_IRQ_BIT(INT_24XX_GPIO_BANK1) | \
+- OMAP_IRQ_BIT(INT_24XX_GPIO_BANK2) | \
+- OMAP_IRQ_BIT(INT_24XX_GPIO_BANK3))
+-
+-#define INT1_WAKE_MASK (OMAP_IRQ_BIT(INT_24XX_GPIO_BANK4))
+-
+-#define INT2_WAKE_MASK (OMAP_IRQ_BIT(INT_24XX_UART1_IRQ) | \
+- OMAP_IRQ_BIT(INT_24XX_UART2_IRQ) | \
+- OMAP_IRQ_BIT(INT_24XX_UART3_IRQ))
+-
+-#define preg(reg) printk("%s\t(0x%p):\t0x%08x\n", #reg, ®, reg);
+-
+-static void omap2_pm_debug(char * desc)
+-{
+- printk("%s:\n", desc);
+-
+- preg(CM_CLKSTCTRL_MPU);
+- preg(CM_CLKSTCTRL_CORE);
+- preg(CM_CLKSTCTRL_GFX);
+- preg(CM_CLKSTCTRL_DSP);
+- preg(CM_CLKSTCTRL_MDM);
+-
+- preg(PM_PWSTCTRL_MPU);
+- preg(PM_PWSTCTRL_CORE);
+- preg(PM_PWSTCTRL_GFX);
+- preg(PM_PWSTCTRL_DSP);
+- preg(PM_PWSTCTRL_MDM);
+-
+- preg(PM_PWSTST_MPU);
+- preg(PM_PWSTST_CORE);
+- preg(PM_PWSTST_GFX);
+- preg(PM_PWSTST_DSP);
+- preg(PM_PWSTST_MDM);
+-
+- preg(CM_AUTOIDLE1_CORE);
+- preg(CM_AUTOIDLE2_CORE);
+- preg(CM_AUTOIDLE3_CORE);
+- preg(CM_AUTOIDLE4_CORE);
+- preg(CM_AUTOIDLE_WKUP);
+- preg(CM_AUTOIDLE_PLL);
+- preg(CM_AUTOIDLE_DSP);
+- preg(CM_AUTOIDLE_MDM);
+-
+- preg(CM_ICLKEN1_CORE);
+- preg(CM_ICLKEN2_CORE);
+- preg(CM_ICLKEN3_CORE);
+- preg(CM_ICLKEN4_CORE);
+- preg(CM_ICLKEN_GFX);
+- preg(CM_ICLKEN_WKUP);
+- preg(CM_ICLKEN_DSP);
+- preg(CM_ICLKEN_MDM);
+-
+- preg(CM_IDLEST1_CORE);
+- preg(CM_IDLEST2_CORE);
+- preg(CM_IDLEST3_CORE);
+- preg(CM_IDLEST4_CORE);
+- preg(CM_IDLEST_GFX);
+- preg(CM_IDLEST_WKUP);
+- preg(CM_IDLEST_CKGEN);
+- preg(CM_IDLEST_DSP);
+- preg(CM_IDLEST_MDM);
+-
+- preg(RM_RSTST_MPU);
+- preg(RM_RSTST_GFX);
+- preg(RM_RSTST_WKUP);
+- preg(RM_RSTST_DSP);
+- preg(RM_RSTST_MDM);
+-
+- preg(PM_WKDEP_MPU);
+- preg(PM_WKDEP_CORE);
+- preg(PM_WKDEP_GFX);
+- preg(PM_WKDEP_DSP);
+- preg(PM_WKDEP_MDM);
+-
+- preg(CM_FCLKEN_WKUP);
+- preg(CM_ICLKEN_WKUP);
+- preg(CM_IDLEST_WKUP);
+- preg(CM_AUTOIDLE_WKUP);
+- preg(CM_CLKSEL_WKUP);
+-
+- preg(PM_WKEN_WKUP);
+- preg(PM_WKST_WKUP);
+-}
+-
+-static inline void omap2_pm_save_registers(void)
+-{
+- /* Save interrupt registers */
+- OMAP24XX_SAVE(INTC_MIR0);
+- OMAP24XX_SAVE(INTC_MIR1);
+- OMAP24XX_SAVE(INTC_MIR2);
+-
+- /* Save power control registers */
+- OMAP24XX_SAVE(CM_CLKSTCTRL_MPU);
+- OMAP24XX_SAVE(CM_CLKSTCTRL_CORE);
+- OMAP24XX_SAVE(CM_CLKSTCTRL_GFX);
+- OMAP24XX_SAVE(CM_CLKSTCTRL_DSP);
+- OMAP24XX_SAVE(CM_CLKSTCTRL_MDM);
+-
+- /* Save power state registers */
+- OMAP24XX_SAVE(PM_PWSTCTRL_MPU);
+- OMAP24XX_SAVE(PM_PWSTCTRL_CORE);
+- OMAP24XX_SAVE(PM_PWSTCTRL_GFX);
+- OMAP24XX_SAVE(PM_PWSTCTRL_DSP);
+- OMAP24XX_SAVE(PM_PWSTCTRL_MDM);
+-
+- /* Save autoidle registers */
+- OMAP24XX_SAVE(CM_AUTOIDLE1_CORE);
+- OMAP24XX_SAVE(CM_AUTOIDLE2_CORE);
+- OMAP24XX_SAVE(CM_AUTOIDLE3_CORE);
+- OMAP24XX_SAVE(CM_AUTOIDLE4_CORE);
+- OMAP24XX_SAVE(CM_AUTOIDLE_WKUP);
+- OMAP24XX_SAVE(CM_AUTOIDLE_PLL);
+- OMAP24XX_SAVE(CM_AUTOIDLE_DSP);
+- OMAP24XX_SAVE(CM_AUTOIDLE_MDM);
+-
+- /* Save idle state registers */
+- OMAP24XX_SAVE(CM_IDLEST1_CORE);
+- OMAP24XX_SAVE(CM_IDLEST2_CORE);
+- OMAP24XX_SAVE(CM_IDLEST3_CORE);
+- OMAP24XX_SAVE(CM_IDLEST4_CORE);
+- OMAP24XX_SAVE(CM_IDLEST_GFX);
+- OMAP24XX_SAVE(CM_IDLEST_WKUP);
+- OMAP24XX_SAVE(CM_IDLEST_CKGEN);
+- OMAP24XX_SAVE(CM_IDLEST_DSP);
+- OMAP24XX_SAVE(CM_IDLEST_MDM);
+-
+- /* Save clock registers */
+- OMAP24XX_SAVE(CM_FCLKEN1_CORE);
+- OMAP24XX_SAVE(CM_FCLKEN2_CORE);
+- OMAP24XX_SAVE(CM_ICLKEN1_CORE);
+- OMAP24XX_SAVE(CM_ICLKEN2_CORE);
+- OMAP24XX_SAVE(CM_ICLKEN3_CORE);
+- OMAP24XX_SAVE(CM_ICLKEN4_CORE);
+-}
+-
+-static inline void omap2_pm_restore_registers(void)
+-{
+- /* Restore clock state registers */
+- OMAP24XX_RESTORE(CM_CLKSTCTRL_MPU);
+- OMAP24XX_RESTORE(CM_CLKSTCTRL_CORE);
+- OMAP24XX_RESTORE(CM_CLKSTCTRL_GFX);
+- OMAP24XX_RESTORE(CM_CLKSTCTRL_DSP);
+- OMAP24XX_RESTORE(CM_CLKSTCTRL_MDM);
+-
+- /* Restore power state registers */
+- OMAP24XX_RESTORE(PM_PWSTCTRL_MPU);
+- OMAP24XX_RESTORE(PM_PWSTCTRL_CORE);
+- OMAP24XX_RESTORE(PM_PWSTCTRL_GFX);
+- OMAP24XX_RESTORE(PM_PWSTCTRL_DSP);
+- OMAP24XX_RESTORE(PM_PWSTCTRL_MDM);
+-
+- /* Restore idle state registers */
+- OMAP24XX_RESTORE(CM_IDLEST1_CORE);
+- OMAP24XX_RESTORE(CM_IDLEST2_CORE);
+- OMAP24XX_RESTORE(CM_IDLEST3_CORE);
+- OMAP24XX_RESTORE(CM_IDLEST4_CORE);
+- OMAP24XX_RESTORE(CM_IDLEST_GFX);
+- OMAP24XX_RESTORE(CM_IDLEST_WKUP);
+- OMAP24XX_RESTORE(CM_IDLEST_CKGEN);
+- OMAP24XX_RESTORE(CM_IDLEST_DSP);
+- OMAP24XX_RESTORE(CM_IDLEST_MDM);
+-
+- /* Restore autoidle registers */
+- OMAP24XX_RESTORE(CM_AUTOIDLE1_CORE);
+- OMAP24XX_RESTORE(CM_AUTOIDLE2_CORE);
+- OMAP24XX_RESTORE(CM_AUTOIDLE3_CORE);
+- OMAP24XX_RESTORE(CM_AUTOIDLE4_CORE);
+- OMAP24XX_RESTORE(CM_AUTOIDLE_WKUP);
+- OMAP24XX_RESTORE(CM_AUTOIDLE_PLL);
+- OMAP24XX_RESTORE(CM_AUTOIDLE_DSP);
+- OMAP24XX_RESTORE(CM_AUTOIDLE_MDM);
+-
+- /* Restore clock registers */
+- OMAP24XX_RESTORE(CM_FCLKEN1_CORE);
+- OMAP24XX_RESTORE(CM_FCLKEN2_CORE);
+- OMAP24XX_RESTORE(CM_ICLKEN1_CORE);
+- OMAP24XX_RESTORE(CM_ICLKEN2_CORE);
+- OMAP24XX_RESTORE(CM_ICLKEN3_CORE);
+- OMAP24XX_RESTORE(CM_ICLKEN4_CORE);
+-
+- /* REVISIT: Clear interrupts here */
+-
+- /* Restore interrupt registers */
+- OMAP24XX_RESTORE(INTC_MIR0);
+- OMAP24XX_RESTORE(INTC_MIR1);
+- OMAP24XX_RESTORE(INTC_MIR2);
+-}
+-
+ static int omap2_pm_suspend(void)
+ {
+- int processor_type = 0;
+-
+- /* REVISIT: 0x21 or 0x26? */
+- if (cpu_is_omap2420())
+- processor_type = 0x21;
+-
+- if (!processor_type)
+- return -ENOTSUPP;
+-
+- local_irq_disable();
+- local_fiq_disable();
+-
+- omap2_pm_save_registers();
+-
+- /* Disable interrupts except for the wake events */
+- INTC_MIR_SET0 = 0xffffffff & ~INT0_WAKE_MASK;
+- INTC_MIR_SET1 = 0xffffffff & ~INT1_WAKE_MASK;
+- INTC_MIR_SET2 = 0xffffffff & ~INT2_WAKE_MASK;
+-
+- pmdomain_set_autoidle();
+-
+- /* Clear old wake-up events */
+- PM_WKST1_CORE = 0;
+- PM_WKST2_CORE = 0;
+- PM_WKST_WKUP = 0;
+-
+- /* Enable wake-up events */
+- PM_WKEN1_CORE = (1 << 22) | (1 << 21); /* UART1 & 2 */
+- PM_WKEN2_CORE = (1 << 2); /* UART3 */
+- PM_WKEN_WKUP = (1 << 2) | (1 << 0); /* GPIO & GPT1 */
+-
+- /* Disable clocks except for CM_ICLKEN2_CORE. It gets disabled
+- * in the SRAM suspend code */
+- CM_FCLKEN1_CORE = 0;
+- CM_FCLKEN2_CORE = 0;
+- CM_ICLKEN1_CORE = 0;
+- CM_ICLKEN3_CORE = 0;
+- CM_ICLKEN4_CORE = 0;
+-
+- omap2_pm_debug("Status before suspend");
+-
+- /* Must wait for serial buffers to clear */
+- mdelay(200);
+-
+- /* Jump to SRAM suspend code
+- * REVISIT: When is this SDRC_DLLB_CTRL?
+- */
+- omap2_sram_suspend(SDRC_DLLA_CTRL, processor_type);
+-
+- /* Back from sleep */
+- omap2_pm_restore_registers();
+-
+- local_fiq_enable();
+- local_irq_enable();
+-
+ return 0;
+ }
+
+@@ -357,30 +113,6 @@ static struct platform_suspend_ops omap_pm_ops = {
+
+ int __init omap2_pm_init(void)
+ {
+- printk("Power Management for TI OMAP.\n");
+-
+- vclk = clk_get(NULL, "virt_prcm_set");
+- if (IS_ERR(vclk)) {
+- printk(KERN_ERR "Could not get PM vclk\n");
+- return -ENODEV;
+- }
+-
+- /*
+- * We copy the assembler sleep/wakeup routines to SRAM.
+- * These routines need to be in SRAM as that's the only
+- * memory the MPU can see when it wakes up.
+- */
+- omap2_sram_idle = omap_sram_push(omap24xx_idle_loop_suspend,
+- omap24xx_idle_loop_suspend_sz);
+-
+- omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend,
+- omap24xx_cpu_suspend_sz);
+-
+- suspend_set_ops(&omap_pm_ops);
+- pm_idle = omap2_pm_idle;
+-
+- pmdomain_init();
+-
+ return 0;
+ }
+
+diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h
+new file mode 100644
+index 0000000..cacb340
+--- /dev/null
++++ b/arch/arm/mach-omap2/prcm-common.h
+@@ -0,0 +1,317 @@
++#ifndef __ARCH_ASM_MACH_OMAP2_PRCM_COMMON_H
++#define __ARCH_ASM_MACH_OMAP2_PRCM_COMMON_H
++
++/*
++ * OMAP2/3 PRCM base and module definitions
++ *
++ * Copyright (C) 2007-2008 Texas Instruments, Inc.
++ * Copyright (C) 2007-2008 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++
++/* Module offsets from both CM_BASE & PRM_BASE */
++
++/*
++ * Offsets that are the same on 24xx and 34xx
++ *
++ * Technically, in terms of the TRM, OCP_MOD is 34xx only; PLL_MOD is
++ * CCR_MOD on 3430; and GFX_MOD only exists < 3430ES2.
++ */
++#define OCP_MOD 0x000
++#define MPU_MOD 0x100
++#define CORE_MOD 0x200
++#define GFX_MOD 0x300
++#define WKUP_MOD 0x400
++#define PLL_MOD 0x500
++
++
++/* Chip-specific module offsets */
++#define OMAP24XX_DSP_MOD 0x800
++
++#define OMAP2430_MDM_MOD 0xc00
++
++/* IVA2 module is < base on 3430 */
++#define OMAP3430_IVA2_MOD -0x800
++#define OMAP3430ES2_SGX_MOD GFX_MOD
++#define OMAP3430_CCR_MOD PLL_MOD
++#define OMAP3430_DSS_MOD 0x600
++#define OMAP3430_CAM_MOD 0x700
++#define OMAP3430_PER_MOD 0x800
++#define OMAP3430_EMU_MOD 0x900
++#define OMAP3430_GR_MOD 0xa00
++#define OMAP3430_NEON_MOD 0xb00
++#define OMAP3430ES2_USBHOST_MOD 0xc00
++
++
++/* 24XX register bits shared between CM & PRM registers */
++
++/* CM_FCLKEN1_CORE, CM_ICLKEN1_CORE, PM_WKEN1_CORE shared bits */
++#define OMAP2420_EN_MMC_SHIFT 26
++#define OMAP2420_EN_MMC (1 << 26)
++#define OMAP24XX_EN_UART2_SHIFT 22
++#define OMAP24XX_EN_UART2 (1 << 22)
++#define OMAP24XX_EN_UART1_SHIFT 21
++#define OMAP24XX_EN_UART1 (1 << 21)
++#define OMAP24XX_EN_MCSPI2_SHIFT 18
++#define OMAP24XX_EN_MCSPI2 (1 << 18)
++#define OMAP24XX_EN_MCSPI1_SHIFT 17
++#define OMAP24XX_EN_MCSPI1 (1 << 17)
++#define OMAP24XX_EN_MCBSP2_SHIFT 16
++#define OMAP24XX_EN_MCBSP2 (1 << 16)
++#define OMAP24XX_EN_MCBSP1_SHIFT 15
++#define OMAP24XX_EN_MCBSP1 (1 << 15)
++#define OMAP24XX_EN_GPT12_SHIFT 14
++#define OMAP24XX_EN_GPT12 (1 << 14)
++#define OMAP24XX_EN_GPT11_SHIFT 13
++#define OMAP24XX_EN_GPT11 (1 << 13)
++#define OMAP24XX_EN_GPT10_SHIFT 12
++#define OMAP24XX_EN_GPT10 (1 << 12)
++#define OMAP24XX_EN_GPT9_SHIFT 11
++#define OMAP24XX_EN_GPT9 (1 << 11)
++#define OMAP24XX_EN_GPT8_SHIFT 10
++#define OMAP24XX_EN_GPT8 (1 << 10)
++#define OMAP24XX_EN_GPT7_SHIFT 9
++#define OMAP24XX_EN_GPT7 (1 << 9)
++#define OMAP24XX_EN_GPT6_SHIFT 8
++#define OMAP24XX_EN_GPT6 (1 << 8)
++#define OMAP24XX_EN_GPT5_SHIFT 7
++#define OMAP24XX_EN_GPT5 (1 << 7)
++#define OMAP24XX_EN_GPT4_SHIFT 6
++#define OMAP24XX_EN_GPT4 (1 << 6)
++#define OMAP24XX_EN_GPT3_SHIFT 5
++#define OMAP24XX_EN_GPT3 (1 << 5)
++#define OMAP24XX_EN_GPT2_SHIFT 4
++#define OMAP24XX_EN_GPT2 (1 << 4)
++#define OMAP2420_EN_VLYNQ_SHIFT 3
++#define OMAP2420_EN_VLYNQ (1 << 3)
++
++/* CM_FCLKEN2_CORE, CM_ICLKEN2_CORE, PM_WKEN2_CORE shared bits */
++#define OMAP2430_EN_GPIO5_SHIFT 10
++#define OMAP2430_EN_GPIO5 (1 << 10)
++#define OMAP2430_EN_MCSPI3_SHIFT 9
++#define OMAP2430_EN_MCSPI3 (1 << 9)
++#define OMAP2430_EN_MMCHS2_SHIFT 8
++#define OMAP2430_EN_MMCHS2 (1 << 8)
++#define OMAP2430_EN_MMCHS1_SHIFT 7
++#define OMAP2430_EN_MMCHS1 (1 << 7)
++#define OMAP24XX_EN_UART3_SHIFT 2
++#define OMAP24XX_EN_UART3 (1 << 2)
++#define OMAP24XX_EN_USB_SHIFT 0
++#define OMAP24XX_EN_USB (1 << 0)
++
++/* CM_ICLKEN2_CORE, PM_WKEN2_CORE shared bits */
++#define OMAP2430_EN_MDM_INTC_SHIFT 11
++#define OMAP2430_EN_MDM_INTC (1 << 11)
++#define OMAP2430_EN_USBHS_SHIFT 6
++#define OMAP2430_EN_USBHS (1 << 6)
++
++/* CM_IDLEST1_CORE, PM_WKST1_CORE shared bits */
++#define OMAP2420_ST_MMC (1 << 26)
++#define OMAP24XX_ST_UART2 (1 << 22)
++#define OMAP24XX_ST_UART1 (1 << 21)
++#define OMAP24XX_ST_MCSPI2 (1 << 18)
++#define OMAP24XX_ST_MCSPI1 (1 << 17)
++#define OMAP24XX_ST_GPT12 (1 << 14)
++#define OMAP24XX_ST_GPT11 (1 << 13)
++#define OMAP24XX_ST_GPT10 (1 << 12)
++#define OMAP24XX_ST_GPT9 (1 << 11)
++#define OMAP24XX_ST_GPT8 (1 << 10)
++#define OMAP24XX_ST_GPT7 (1 << 9)
++#define OMAP24XX_ST_GPT6 (1 << 8)
++#define OMAP24XX_ST_GPT5 (1 << 7)
++#define OMAP24XX_ST_GPT4 (1 << 6)
++#define OMAP24XX_ST_GPT3 (1 << 5)
++#define OMAP24XX_ST_GPT2 (1 << 4)
++#define OMAP2420_ST_VLYNQ (1 << 3)
++
++/* CM_IDLEST2_CORE, PM_WKST2_CORE shared bits */
++#define OMAP2430_ST_MDM_INTC (1 << 11)
++#define OMAP2430_ST_GPIO5 (1 << 10)
++#define OMAP2430_ST_MCSPI3 (1 << 9)
++#define OMAP2430_ST_MMCHS2 (1 << 8)
++#define OMAP2430_ST_MMCHS1 (1 << 7)
++#define OMAP2430_ST_USBHS (1 << 6)
++#define OMAP24XX_ST_UART3 (1 << 2)
++#define OMAP24XX_ST_USB (1 << 0)
++
++/* CM_FCLKEN_WKUP, CM_ICLKEN_WKUP, PM_WKEN_WKUP shared bits */
++#define OMAP24XX_EN_GPIOS_SHIFT 2
++#define OMAP24XX_EN_GPIOS (1 << 2)
++#define OMAP24XX_EN_GPT1_SHIFT 0
++#define OMAP24XX_EN_GPT1 (1 << 0)
++
++/* PM_WKST_WKUP, CM_IDLEST_WKUP shared bits */
++#define OMAP24XX_ST_GPIOS (1 << 2)
++#define OMAP24XX_ST_GPT1 (1 << 0)
++
++/* CM_IDLEST_MDM and PM_WKST_MDM shared bits */
++#define OMAP2430_ST_MDM (1 << 0)
++
++
++/* 3430 register bits shared between CM & PRM registers */
++
++/* CM_REVISION, PRM_REVISION shared bits */
++#define OMAP3430_REV_SHIFT 0
++#define OMAP3430_REV_MASK (0xff << 0)
++
++/* CM_SYSCONFIG, PRM_SYSCONFIG shared bits */
++#define OMAP3430_AUTOIDLE (1 << 0)
++
++/* CM_FCLKEN1_CORE, CM_ICLKEN1_CORE, PM_WKEN1_CORE shared bits */
++#define OMAP3430_EN_MMC2 (1 << 25)
++#define OMAP3430_EN_MMC2_SHIFT 25
++#define OMAP3430_EN_MMC1 (1 << 24)
++#define OMAP3430_EN_MMC1_SHIFT 24
++#define OMAP3430_EN_MCSPI4 (1 << 21)
++#define OMAP3430_EN_MCSPI4_SHIFT 21
++#define OMAP3430_EN_MCSPI3 (1 << 20)
++#define OMAP3430_EN_MCSPI3_SHIFT 20
++#define OMAP3430_EN_MCSPI2 (1 << 19)
++#define OMAP3430_EN_MCSPI2_SHIFT 19
++#define OMAP3430_EN_MCSPI1 (1 << 18)
++#define OMAP3430_EN_MCSPI1_SHIFT 18
++#define OMAP3430_EN_I2C3 (1 << 17)
++#define OMAP3430_EN_I2C3_SHIFT 17
++#define OMAP3430_EN_I2C2 (1 << 16)
++#define OMAP3430_EN_I2C2_SHIFT 16
++#define OMAP3430_EN_I2C1 (1 << 15)
++#define OMAP3430_EN_I2C1_SHIFT 15
++#define OMAP3430_EN_UART2 (1 << 14)
++#define OMAP3430_EN_UART2_SHIFT 14
++#define OMAP3430_EN_UART1 (1 << 13)
++#define OMAP3430_EN_UART1_SHIFT 13
++#define OMAP3430_EN_GPT11 (1 << 12)
++#define OMAP3430_EN_GPT11_SHIFT 12
++#define OMAP3430_EN_GPT10 (1 << 11)
++#define OMAP3430_EN_GPT10_SHIFT 11
++#define OMAP3430_EN_MCBSP5 (1 << 10)
++#define OMAP3430_EN_MCBSP5_SHIFT 10
++#define OMAP3430_EN_MCBSP1 (1 << 9)
++#define OMAP3430_EN_MCBSP1_SHIFT 9
++#define OMAP3430_EN_FSHOSTUSB (1 << 5)
++#define OMAP3430_EN_FSHOSTUSB_SHIFT 5
++#define OMAP3430_EN_D2D (1 << 3)
++#define OMAP3430_EN_D2D_SHIFT 3
++
++/* CM_ICLKEN1_CORE, PM_WKEN1_CORE shared bits */
++#define OMAP3430_EN_HSOTGUSB (1 << 4)
++#define OMAP3430_EN_HSOTGUSB_SHIFT 4
++
++/* PM_WKST1_CORE, CM_IDLEST1_CORE shared bits */
++#define OMAP3430_ST_MMC2 (1 << 25)
++#define OMAP3430_ST_MMC1 (1 << 24)
++#define OMAP3430_ST_MCSPI4 (1 << 21)
++#define OMAP3430_ST_MCSPI3 (1 << 20)
++#define OMAP3430_ST_MCSPI2 (1 << 19)
++#define OMAP3430_ST_MCSPI1 (1 << 18)
++#define OMAP3430_ST_I2C3 (1 << 17)
++#define OMAP3430_ST_I2C2 (1 << 16)
++#define OMAP3430_ST_I2C1 (1 << 15)
++#define OMAP3430_ST_UART2 (1 << 14)
++#define OMAP3430_ST_UART1 (1 << 13)
++#define OMAP3430_ST_GPT11 (1 << 12)
++#define OMAP3430_ST_GPT10 (1 << 11)
++#define OMAP3430_ST_MCBSP5 (1 << 10)
++#define OMAP3430_ST_MCBSP1 (1 << 9)
++#define OMAP3430_ST_FSHOSTUSB (1 << 5)
++#define OMAP3430_ST_HSOTGUSB (1 << 4)
++#define OMAP3430_ST_D2D (1 << 3)
++
++/* CM_FCLKEN_WKUP, CM_ICLKEN_WKUP, PM_WKEN_WKUP shared bits */
++#define OMAP3430_EN_GPIO1 (1 << 3)
++#define OMAP3430_EN_GPIO1_SHIFT 3
++#define OMAP3430_EN_GPT1 (1 << 0)
++#define OMAP3430_EN_GPT1_SHIFT 0
++
++/* CM_FCLKEN_WKUP, PM_WKEN_WKUP shared bits */
++#define OMAP3430_EN_SR2 (1 << 7)
++#define OMAP3430_EN_SR2_SHIFT 7
++#define OMAP3430_EN_SR1 (1 << 6)
++#define OMAP3430_EN_SR1_SHIFT 6
++
++/* CM_ICLKEN_WKUP, PM_WKEN_WKUP shared bits */
++#define OMAP3430_EN_GPT12 (1 << 1)
++#define OMAP3430_EN_GPT12_SHIFT 1
++
++/* CM_IDLEST_WKUP, PM_WKST_WKUP shared bits */
++#define OMAP3430_ST_SR2 (1 << 7)
++#define OMAP3430_ST_SR1 (1 << 6)
++#define OMAP3430_ST_GPIO1 (1 << 3)
++#define OMAP3430_ST_GPT12 (1 << 1)
++#define OMAP3430_ST_GPT1 (1 << 0)
++
++/*
++ * CM_SLEEPDEP_GFX, CM_SLEEPDEP_DSS, CM_SLEEPDEP_CAM,
++ * CM_SLEEPDEP_PER, PM_WKDEP_IVA2, PM_WKDEP_GFX,
++ * PM_WKDEP_DSS, PM_WKDEP_CAM, PM_WKDEP_PER, PM_WKDEP_NEON shared bits
++ */
++#define OMAP3430_EN_MPU (1 << 1)
++#define OMAP3430_EN_MPU_SHIFT 1
++
++/* CM_FCLKEN_PER, CM_ICLKEN_PER, PM_WKEN_PER shared bits */
++#define OMAP3430_EN_GPIO6 (1 << 17)
++#define OMAP3430_EN_GPIO6_SHIFT 17
++#define OMAP3430_EN_GPIO5 (1 << 16)
++#define OMAP3430_EN_GPIO5_SHIFT 16
++#define OMAP3430_EN_GPIO4 (1 << 15)
++#define OMAP3430_EN_GPIO4_SHIFT 15
++#define OMAP3430_EN_GPIO3 (1 << 14)
++#define OMAP3430_EN_GPIO3_SHIFT 14
++#define OMAP3430_EN_GPIO2 (1 << 13)
++#define OMAP3430_EN_GPIO2_SHIFT 13
++#define OMAP3430_EN_UART3 (1 << 11)
++#define OMAP3430_EN_UART3_SHIFT 11
++#define OMAP3430_EN_GPT9 (1 << 10)
++#define OMAP3430_EN_GPT9_SHIFT 10
++#define OMAP3430_EN_GPT8 (1 << 9)
++#define OMAP3430_EN_GPT8_SHIFT 9
++#define OMAP3430_EN_GPT7 (1 << 8)
++#define OMAP3430_EN_GPT7_SHIFT 8
++#define OMAP3430_EN_GPT6 (1 << 7)
++#define OMAP3430_EN_GPT6_SHIFT 7
++#define OMAP3430_EN_GPT5 (1 << 6)
++#define OMAP3430_EN_GPT5_SHIFT 6
++#define OMAP3430_EN_GPT4 (1 << 5)
++#define OMAP3430_EN_GPT4_SHIFT 5
++#define OMAP3430_EN_GPT3 (1 << 4)
++#define OMAP3430_EN_GPT3_SHIFT 4
++#define OMAP3430_EN_GPT2 (1 << 3)
++#define OMAP3430_EN_GPT2_SHIFT 3
++
++/* CM_FCLKEN_PER, CM_ICLKEN_PER, PM_WKEN_PER, PM_WKST_PER shared bits */
++/* XXX Possible TI documentation bug: should the PM_WKST_PER EN_* bits
++ * be ST_* bits instead? */
++#define OMAP3430_EN_MCBSP4 (1 << 2)
++#define OMAP3430_EN_MCBSP4_SHIFT 2
++#define OMAP3430_EN_MCBSP3 (1 << 1)
++#define OMAP3430_EN_MCBSP3_SHIFT 1
++#define OMAP3430_EN_MCBSP2 (1 << 0)
++#define OMAP3430_EN_MCBSP2_SHIFT 0
++
++/* CM_IDLEST_PER, PM_WKST_PER shared bits */
++#define OMAP3430_ST_GPIO6 (1 << 17)
++#define OMAP3430_ST_GPIO5 (1 << 16)
++#define OMAP3430_ST_GPIO4 (1 << 15)
++#define OMAP3430_ST_GPIO3 (1 << 14)
++#define OMAP3430_ST_GPIO2 (1 << 13)
++#define OMAP3430_ST_UART3 (1 << 11)
++#define OMAP3430_ST_GPT9 (1 << 10)
++#define OMAP3430_ST_GPT8 (1 << 9)
++#define OMAP3430_ST_GPT7 (1 << 8)
++#define OMAP3430_ST_GPT6 (1 << 7)
++#define OMAP3430_ST_GPT5 (1 << 6)
++#define OMAP3430_ST_GPT4 (1 << 5)
++#define OMAP3430_ST_GPT3 (1 << 4)
++#define OMAP3430_ST_GPT2 (1 << 3)
++
++/* CM_SLEEPDEP_PER, PM_WKDEP_IVA2, PM_WKDEP_MPU, PM_WKDEP_PER shared bits */
++#define OMAP3430_EN_CORE (1 << 0)
++
++#endif
++
+diff --git a/arch/arm/mach-omap2/prcm-regs.h b/arch/arm/mach-omap2/prcm-regs.h
+deleted file mode 100644
+index 5e1c4b5..0000000
+--- a/arch/arm/mach-omap2/prcm-regs.h
++++ /dev/null
+@@ -1,483 +0,0 @@
+-/*
+- * linux/arch/arm/mach-omap2/prcm-regs.h
+- *
+- * OMAP24XX Power Reset and Clock Management (PRCM) registers
+- *
+- * Copyright (C) 2005 Texas Instruments, Inc.
+- *
+- * 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 __ARCH_ARM_MACH_OMAP2_PRCM_H
+-#define __ARCH_ARM_MACH_OMAP2_PRCM_H
+-
+-/* SET_PERFORMANCE_LEVEL PARAMETERS */
+-#define PRCM_HALF_SPEED 1
+-#define PRCM_FULL_SPEED 2
+-
+-#ifndef __ASSEMBLER__
+-
+-#define PRCM_REG32(offset) __REG32(OMAP24XX_PRCM_BASE + (offset))
+-
+-#define PRCM_REVISION PRCM_REG32(0x000)
+-#define PRCM_SYSCONFIG PRCM_REG32(0x010)
+-#define PRCM_IRQSTATUS_MPU PRCM_REG32(0x018)
+-#define PRCM_IRQENABLE_MPU PRCM_REG32(0x01C)
+-#define PRCM_VOLTCTRL PRCM_REG32(0x050)
+-#define PRCM_VOLTST PRCM_REG32(0x054)
+-#define PRCM_CLKSRC_CTRL PRCM_REG32(0x060)
+-#define PRCM_CLKOUT_CTRL PRCM_REG32(0x070)
+-#define PRCM_CLKEMUL_CTRL PRCM_REG32(0x078)
+-#define PRCM_CLKCFG_CTRL PRCM_REG32(0x080)
+-#define PRCM_CLKCFG_STATUS PRCM_REG32(0x084)
+-#define PRCM_VOLTSETUP PRCM_REG32(0x090)
+-#define PRCM_CLKSSETUP PRCM_REG32(0x094)
+-#define PRCM_POLCTRL PRCM_REG32(0x098)
+-
+-/* GENERAL PURPOSE */
+-#define GENERAL_PURPOSE1 PRCM_REG32(0x0B0)
+-#define GENERAL_PURPOSE2 PRCM_REG32(0x0B4)
+-#define GENERAL_PURPOSE3 PRCM_REG32(0x0B8)
+-#define GENERAL_PURPOSE4 PRCM_REG32(0x0BC)
+-#define GENERAL_PURPOSE5 PRCM_REG32(0x0C0)
+-#define GENERAL_PURPOSE6 PRCM_REG32(0x0C4)
+-#define GENERAL_PURPOSE7 PRCM_REG32(0x0C8)
+-#define GENERAL_PURPOSE8 PRCM_REG32(0x0CC)
+-#define GENERAL_PURPOSE9 PRCM_REG32(0x0D0)
+-#define GENERAL_PURPOSE10 PRCM_REG32(0x0D4)
+-#define GENERAL_PURPOSE11 PRCM_REG32(0x0D8)
+-#define GENERAL_PURPOSE12 PRCM_REG32(0x0DC)
+-#define GENERAL_PURPOSE13 PRCM_REG32(0x0E0)
+-#define GENERAL_PURPOSE14 PRCM_REG32(0x0E4)
+-#define GENERAL_PURPOSE15 PRCM_REG32(0x0E8)
+-#define GENERAL_PURPOSE16 PRCM_REG32(0x0EC)
+-#define GENERAL_PURPOSE17 PRCM_REG32(0x0F0)
+-#define GENERAL_PURPOSE18 PRCM_REG32(0x0F4)
+-#define GENERAL_PURPOSE19 PRCM_REG32(0x0F8)
+-#define GENERAL_PURPOSE20 PRCM_REG32(0x0FC)
+-
+-/* MPU */
+-#define CM_CLKSEL_MPU PRCM_REG32(0x140)
+-#define CM_CLKSTCTRL_MPU PRCM_REG32(0x148)
+-#define RM_RSTST_MPU PRCM_REG32(0x158)
+-#define PM_WKDEP_MPU PRCM_REG32(0x1C8)
+-#define PM_EVGENCTRL_MPU PRCM_REG32(0x1D4)
+-#define PM_EVEGENONTIM_MPU PRCM_REG32(0x1D8)
+-#define PM_EVEGENOFFTIM_MPU PRCM_REG32(0x1DC)
+-#define PM_PWSTCTRL_MPU PRCM_REG32(0x1E0)
+-#define PM_PWSTST_MPU PRCM_REG32(0x1E4)
+-
+-/* CORE */
+-#define CM_FCLKEN1_CORE PRCM_REG32(0x200)
+-#define CM_FCLKEN2_CORE PRCM_REG32(0x204)
+-#define CM_FCLKEN3_CORE PRCM_REG32(0x208)
+-#define CM_ICLKEN1_CORE PRCM_REG32(0x210)
+-#define CM_ICLKEN2_CORE PRCM_REG32(0x214)
+-#define CM_ICLKEN3_CORE PRCM_REG32(0x218)
+-#define CM_ICLKEN4_CORE PRCM_REG32(0x21C)
+-#define CM_IDLEST1_CORE PRCM_REG32(0x220)
+-#define CM_IDLEST2_CORE PRCM_REG32(0x224)
+-#define CM_IDLEST3_CORE PRCM_REG32(0x228)
+-#define CM_IDLEST4_CORE PRCM_REG32(0x22C)
+-#define CM_AUTOIDLE1_CORE PRCM_REG32(0x230)
+-#define CM_AUTOIDLE2_CORE PRCM_REG32(0x234)
+-#define CM_AUTOIDLE3_CORE PRCM_REG32(0x238)
+-#define CM_AUTOIDLE4_CORE PRCM_REG32(0x23C)
+-#define CM_CLKSEL1_CORE PRCM_REG32(0x240)
+-#define CM_CLKSEL2_CORE PRCM_REG32(0x244)
+-#define CM_CLKSTCTRL_CORE PRCM_REG32(0x248)
+-#define PM_WKEN1_CORE PRCM_REG32(0x2A0)
+-#define PM_WKEN2_CORE PRCM_REG32(0x2A4)
+-#define PM_WKST1_CORE PRCM_REG32(0x2B0)
+-#define PM_WKST2_CORE PRCM_REG32(0x2B4)
+-#define PM_WKDEP_CORE PRCM_REG32(0x2C8)
+-#define PM_PWSTCTRL_CORE PRCM_REG32(0x2E0)
+-#define PM_PWSTST_CORE PRCM_REG32(0x2E4)
+-
+-/* GFX */
+-#define CM_FCLKEN_GFX PRCM_REG32(0x300)
+-#define CM_ICLKEN_GFX PRCM_REG32(0x310)
+-#define CM_IDLEST_GFX PRCM_REG32(0x320)
+-#define CM_CLKSEL_GFX PRCM_REG32(0x340)
+-#define CM_CLKSTCTRL_GFX PRCM_REG32(0x348)
+-#define RM_RSTCTRL_GFX PRCM_REG32(0x350)
+-#define RM_RSTST_GFX PRCM_REG32(0x358)
+-#define PM_WKDEP_GFX PRCM_REG32(0x3C8)
+-#define PM_PWSTCTRL_GFX PRCM_REG32(0x3E0)
+-#define PM_PWSTST_GFX PRCM_REG32(0x3E4)
+-
+-/* WAKE-UP */
+-#define CM_FCLKEN_WKUP PRCM_REG32(0x400)
+-#define CM_ICLKEN_WKUP PRCM_REG32(0x410)
+-#define CM_IDLEST_WKUP PRCM_REG32(0x420)
+-#define CM_AUTOIDLE_WKUP PRCM_REG32(0x430)
+-#define CM_CLKSEL_WKUP PRCM_REG32(0x440)
+-#define RM_RSTCTRL_WKUP PRCM_REG32(0x450)
+-#define RM_RSTTIME_WKUP PRCM_REG32(0x454)
+-#define RM_RSTST_WKUP PRCM_REG32(0x458)
+-#define PM_WKEN_WKUP PRCM_REG32(0x4A0)
+-#define PM_WKST_WKUP PRCM_REG32(0x4B0)
+-
+-/* CLOCKS */
+-#define CM_CLKEN_PLL PRCM_REG32(0x500)
+-#define CM_IDLEST_CKGEN PRCM_REG32(0x520)
+-#define CM_AUTOIDLE_PLL PRCM_REG32(0x530)
+-#define CM_CLKSEL1_PLL PRCM_REG32(0x540)
+-#define CM_CLKSEL2_PLL PRCM_REG32(0x544)
+-
+-/* DSP */
+-#define CM_FCLKEN_DSP PRCM_REG32(0x800)
+-#define CM_ICLKEN_DSP PRCM_REG32(0x810)
+-#define CM_IDLEST_DSP PRCM_REG32(0x820)
+-#define CM_AUTOIDLE_DSP PRCM_REG32(0x830)
+-#define CM_CLKSEL_DSP PRCM_REG32(0x840)
+-#define CM_CLKSTCTRL_DSP PRCM_REG32(0x848)
+-#define RM_RSTCTRL_DSP PRCM_REG32(0x850)
+-#define RM_RSTST_DSP PRCM_REG32(0x858)
+-#define PM_WKEN_DSP PRCM_REG32(0x8A0)
+-#define PM_WKDEP_DSP PRCM_REG32(0x8C8)
+-#define PM_PWSTCTRL_DSP PRCM_REG32(0x8E0)
+-#define PM_PWSTST_DSP PRCM_REG32(0x8E4)
+-#define PRCM_IRQSTATUS_DSP PRCM_REG32(0x8F0)
+-#define PRCM_IRQENABLE_DSP PRCM_REG32(0x8F4)
+-
+-/* IVA */
+-#define PRCM_IRQSTATUS_IVA PRCM_REG32(0x8F8)
+-#define PRCM_IRQENABLE_IVA PRCM_REG32(0x8FC)
+-
+-/* Modem on 2430 */
+-#define CM_FCLKEN_MDM PRCM_REG32(0xC00)
+-#define CM_ICLKEN_MDM PRCM_REG32(0xC10)
+-#define CM_IDLEST_MDM PRCM_REG32(0xC20)
+-#define CM_AUTOIDLE_MDM PRCM_REG32(0xC30)
+-#define CM_CLKSEL_MDM PRCM_REG32(0xC40)
+-#define CM_CLKSTCTRL_MDM PRCM_REG32(0xC48)
+-#define RM_RSTCTRL_MDM PRCM_REG32(0xC50)
+-#define RM_RSTST_MDM PRCM_REG32(0xC58)
+-#define PM_WKEN_MDM PRCM_REG32(0xCA0)
+-#define PM_WKST_MDM PRCM_REG32(0xCB0)
+-#define PM_WKDEP_MDM PRCM_REG32(0xCC8)
+-#define PM_PWSTCTRL_MDM PRCM_REG32(0xCE0)
+-#define PM_PWSTST_MDM PRCM_REG32(0xCE4)
+-
+-#define OMAP24XX_L4_IO_BASE 0x48000000
+-
+-#define DISP_BASE (OMAP24XX_L4_IO_BASE + 0x50000)
+-#define DISP_REG32(offset) __REG32(DISP_BASE + (offset))
+-
+-#define OMAP24XX_GPMC_BASE (L3_24XX_BASE + 0xa000)
+-#define GPMC_REG32(offset) __REG32(OMAP24XX_GPMC_BASE + (offset))
+-
+-/* FIXME: Move these to timer code */
+-#define GPT1_BASE (0x48028000)
+-#define GPT1_REG32(offset) __REG32(GPT1_BASE + (offset))
+-
+-/* Misc sysconfig */
+-#define DISPC_SYSCONFIG DISP_REG32(0x410)
+-#define SPI_BASE (OMAP24XX_L4_IO_BASE + 0x98000)
+-#define MCSPI1_SYSCONFIG __REG32(SPI_BASE + 0x10)
+-#define MCSPI2_SYSCONFIG __REG32(SPI_BASE + 0x2000 + 0x10)
+-#define MCSPI3_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0xb8010)
+-
+-#define CAMERA_MMU_SYSCONFIG __REG32(DISP_BASE + 0x2C10)
+-#define CAMERA_DMA_SYSCONFIG __REG32(DISP_BASE + 0x282C)
+-#define SYSTEM_DMA_SYSCONFIG __REG32(DISP_BASE + 0x602C)
+-#define GPMC_SYSCONFIG GPMC_REG32(0x010)
+-#define MAILBOXES_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0x94010)
+-#define UART1_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0x6A054)
+-#define UART2_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0x6C054)
+-#define UART3_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0x6E054)
+-#define SDRC_SYSCONFIG __REG32(OMAP24XX_SDRC_BASE + 0x10)
+-#define OMAP24XX_SMS_BASE (L3_24XX_BASE + 0x8000)
+-#define SMS_SYSCONFIG __REG32(OMAP24XX_SMS_BASE + 0x10)
+-#define SSI_SYSCONFIG __REG32(DISP_BASE + 0x8010)
+-
+-/* rkw - good cannidates for PM_ to start what nm was trying */
+-#define OMAP24XX_GPT2 (OMAP24XX_L4_IO_BASE + 0x2A000)
+-#define OMAP24XX_GPT3 (OMAP24XX_L4_IO_BASE + 0x78000)
+-#define OMAP24XX_GPT4 (OMAP24XX_L4_IO_BASE + 0x7A000)
+-#define OMAP24XX_GPT5 (OMAP24XX_L4_IO_BASE + 0x7C000)
+-#define OMAP24XX_GPT6 (OMAP24XX_L4_IO_BASE + 0x7E000)
+-#define OMAP24XX_GPT7 (OMAP24XX_L4_IO_BASE + 0x80000)
+-#define OMAP24XX_GPT8 (OMAP24XX_L4_IO_BASE + 0x82000)
+-#define OMAP24XX_GPT9 (OMAP24XX_L4_IO_BASE + 0x84000)
+-#define OMAP24XX_GPT10 (OMAP24XX_L4_IO_BASE + 0x86000)
+-#define OMAP24XX_GPT11 (OMAP24XX_L4_IO_BASE + 0x88000)
+-#define OMAP24XX_GPT12 (OMAP24XX_L4_IO_BASE + 0x8A000)
+-
+-/* FIXME: Move these to timer code */
+-#define GPTIMER1_SYSCONFIG GPT1_REG32(0x010)
+-#define GPTIMER2_SYSCONFIG __REG32(OMAP24XX_GPT2 + 0x10)
+-#define GPTIMER3_SYSCONFIG __REG32(OMAP24XX_GPT3 + 0x10)
+-#define GPTIMER4_SYSCONFIG __REG32(OMAP24XX_GPT4 + 0x10)
+-#define GPTIMER5_SYSCONFIG __REG32(OMAP24XX_GPT5 + 0x10)
+-#define GPTIMER6_SYSCONFIG __REG32(OMAP24XX_GPT6 + 0x10)
+-#define GPTIMER7_SYSCONFIG __REG32(OMAP24XX_GPT7 + 0x10)
+-#define GPTIMER8_SYSCONFIG __REG32(OMAP24XX_GPT8 + 0x10)
+-#define GPTIMER9_SYSCONFIG __REG32(OMAP24XX_GPT9 + 0x10)
+-#define GPTIMER10_SYSCONFIG __REG32(OMAP24XX_GPT10 + 0x10)
+-#define GPTIMER11_SYSCONFIG __REG32(OMAP24XX_GPT11 + 0x10)
+-#define GPTIMER12_SYSCONFIG __REG32(OMAP24XX_GPT12 + 0x10)
+-
+-/* FIXME: Move these to gpio code */
+-#define OMAP24XX_GPIO_BASE 0x48018000
+-#define GPIOX_BASE(X) (OMAP24XX_GPIO_BASE + (0x2000 * ((X) - 1)))
+-
+-#define GPIO1_SYSCONFIG __REG32((GPIOX_BASE(1) + 0x10))
+-#define GPIO2_SYSCONFIG __REG32((GPIOX_BASE(2) + 0x10))
+-#define GPIO3_SYSCONFIG __REG32((GPIOX_BASE(3) + 0x10))
+-#define GPIO4_SYSCONFIG __REG32((GPIOX_BASE(4) + 0x10))
+-
+-#if defined(CONFIG_ARCH_OMAP243X)
+-#define GPIO5_SYSCONFIG __REG32((OMAP24XX_GPIO5_BASE + 0x10))
+-#endif
+-
+-/* GP TIMER 1 */
+-#define GPTIMER1_TISTAT GPT1_REG32(0x014)
+-#define GPTIMER1_TISR GPT1_REG32(0x018)
+-#define GPTIMER1_TIER GPT1_REG32(0x01C)
+-#define GPTIMER1_TWER GPT1_REG32(0x020)
+-#define GPTIMER1_TCLR GPT1_REG32(0x024)
+-#define GPTIMER1_TCRR GPT1_REG32(0x028)
+-#define GPTIMER1_TLDR GPT1_REG32(0x02C)
+-#define GPTIMER1_TTGR GPT1_REG32(0x030)
+-#define GPTIMER1_TWPS GPT1_REG32(0x034)
+-#define GPTIMER1_TMAR GPT1_REG32(0x038)
+-#define GPTIMER1_TCAR1 GPT1_REG32(0x03C)
+-#define GPTIMER1_TSICR GPT1_REG32(0x040)
+-#define GPTIMER1_TCAR2 GPT1_REG32(0x044)
+-
+-/* rkw -- base fix up please... */
+-#define GPTIMER3_TISR __REG32(OMAP24XX_L4_IO_BASE + 0x78018)
+-
+-/* SDRC */
+-#define SDRC_DLLA_CTRL __REG32(OMAP24XX_SDRC_BASE + 0x060)
+-#define SDRC_DLLA_STATUS __REG32(OMAP24XX_SDRC_BASE + 0x064)
+-#define SDRC_DLLB_CTRL __REG32(OMAP24XX_SDRC_BASE + 0x068)
+-#define SDRC_DLLB_STATUS __REG32(OMAP24XX_SDRC_BASE + 0x06C)
+-#define SDRC_POWER __REG32(OMAP24XX_SDRC_BASE + 0x070)
+-#define SDRC_MR_0 __REG32(OMAP24XX_SDRC_BASE + 0x084)
+-
+-/* GPIO 1 */
+-#define GPIO1_BASE GPIOX_BASE(1)
+-#define GPIO1_REG32(offset) __REG32(GPIO1_BASE + (offset))
+-#define GPIO1_IRQENABLE1 GPIO1_REG32(0x01C)
+-#define GPIO1_IRQSTATUS1 GPIO1_REG32(0x018)
+-#define GPIO1_IRQENABLE2 GPIO1_REG32(0x02C)
+-#define GPIO1_IRQSTATUS2 GPIO1_REG32(0x028)
+-#define GPIO1_WAKEUPENABLE GPIO1_REG32(0x020)
+-#define GPIO1_RISINGDETECT GPIO1_REG32(0x048)
+-#define GPIO1_DATAIN GPIO1_REG32(0x038)
+-#define GPIO1_OE GPIO1_REG32(0x034)
+-#define GPIO1_DATAOUT GPIO1_REG32(0x03C)
+-
+-/* GPIO2 */
+-#define GPIO2_BASE GPIOX_BASE(2)
+-#define GPIO2_REG32(offset) __REG32(GPIO2_BASE + (offset))
+-#define GPIO2_IRQENABLE1 GPIO2_REG32(0x01C)
+-#define GPIO2_IRQSTATUS1 GPIO2_REG32(0x018)
+-#define GPIO2_IRQENABLE2 GPIO2_REG32(0x02C)
+-#define GPIO2_IRQSTATUS2 GPIO2_REG32(0x028)
+-#define GPIO2_WAKEUPENABLE GPIO2_REG32(0x020)
+-#define GPIO2_RISINGDETECT GPIO2_REG32(0x048)
+-#define GPIO2_DATAIN GPIO2_REG32(0x038)
+-#define GPIO2_OE GPIO2_REG32(0x034)
+-#define GPIO2_DATAOUT GPIO2_REG32(0x03C)
+-#define GPIO2_DEBOUNCENABLE GPIO2_REG32(0x050)
+-#define GPIO2_DEBOUNCINGTIME GPIO2_REG32(0x054)
+-
+-/* GPIO 3 */
+-#define GPIO3_BASE GPIOX_BASE(3)
+-#define GPIO3_REG32(offset) __REG32(GPIO3_BASE + (offset))
+-#define GPIO3_IRQENABLE1 GPIO3_REG32(0x01C)
+-#define GPIO3_IRQSTATUS1 GPIO3_REG32(0x018)
+-#define GPIO3_IRQENABLE2 GPIO3_REG32(0x02C)
+-#define GPIO3_IRQSTATUS2 GPIO3_REG32(0x028)
+-#define GPIO3_WAKEUPENABLE GPIO3_REG32(0x020)
+-#define GPIO3_RISINGDETECT GPIO3_REG32(0x048)
+-#define GPIO3_FALLINGDETECT GPIO3_REG32(0x04C)
+-#define GPIO3_DATAIN GPIO3_REG32(0x038)
+-#define GPIO3_OE GPIO3_REG32(0x034)
+-#define GPIO3_DATAOUT GPIO3_REG32(0x03C)
+-#define GPIO3_DEBOUNCENABLE GPIO3_REG32(0x050)
+-#define GPIO3_DEBOUNCINGTIME GPIO3_REG32(0x054)
+-#define GPIO3_DEBOUNCENABLE GPIO3_REG32(0x050)
+-#define GPIO3_DEBOUNCINGTIME GPIO3_REG32(0x054)
+-
+-/* GPIO 4 */
+-#define GPIO4_BASE GPIOX_BASE(4)
+-#define GPIO4_REG32(offset) __REG32(GPIO4_BASE + (offset))
+-#define GPIO4_IRQENABLE1 GPIO4_REG32(0x01C)
+-#define GPIO4_IRQSTATUS1 GPIO4_REG32(0x018)
+-#define GPIO4_IRQENABLE2 GPIO4_REG32(0x02C)
+-#define GPIO4_IRQSTATUS2 GPIO4_REG32(0x028)
+-#define GPIO4_WAKEUPENABLE GPIO4_REG32(0x020)
+-#define GPIO4_RISINGDETECT GPIO4_REG32(0x048)
+-#define GPIO4_FALLINGDETECT GPIO4_REG32(0x04C)
+-#define GPIO4_DATAIN GPIO4_REG32(0x038)
+-#define GPIO4_OE GPIO4_REG32(0x034)
+-#define GPIO4_DATAOUT GPIO4_REG32(0x03C)
+-#define GPIO4_DEBOUNCENABLE GPIO4_REG32(0x050)
+-#define GPIO4_DEBOUNCINGTIME GPIO4_REG32(0x054)
+-
+-#if defined(CONFIG_ARCH_OMAP243X)
+-/* GPIO 5 */
+-#define GPIO5_REG32(offset) __REG32((OMAP24XX_GPIO5_BASE + (offset)))
+-#define GPIO5_IRQENABLE1 GPIO5_REG32(0x01C)
+-#define GPIO5_IRQSTATUS1 GPIO5_REG32(0x018)
+-#define GPIO5_IRQENABLE2 GPIO5_REG32(0x02C)
+-#define GPIO5_IRQSTATUS2 GPIO5_REG32(0x028)
+-#define GPIO5_WAKEUPENABLE GPIO5_REG32(0x020)
+-#define GPIO5_RISINGDETECT GPIO5_REG32(0x048)
+-#define GPIO5_FALLINGDETECT GPIO5_REG32(0x04C)
+-#define GPIO5_DATAIN GPIO5_REG32(0x038)
+-#define GPIO5_OE GPIO5_REG32(0x034)
+-#define GPIO5_DATAOUT GPIO5_REG32(0x03C)
+-#define GPIO5_DEBOUNCENABLE GPIO5_REG32(0x050)
+-#define GPIO5_DEBOUNCINGTIME GPIO5_REG32(0x054)
+-#endif
+-
+-/* IO CONFIG */
+-#define OMAP24XX_CTRL_BASE (L4_24XX_BASE)
+-#define CONTROL_REG32(offset) __REG32(OMAP24XX_CTRL_BASE + (offset))
+-
+-#define CONTROL_PADCONF_SPI1_NCS2 CONTROL_REG32(0x104)
+-#define CONTROL_PADCONF_SYS_XTALOUT CONTROL_REG32(0x134)
+-#define CONTROL_PADCONF_UART1_RX CONTROL_REG32(0x0C8)
+-#define CONTROL_PADCONF_MCBSP1_DX CONTROL_REG32(0x10C)
+-#define CONTROL_PADCONF_GPMC_NCS4 CONTROL_REG32(0x090)
+-#define CONTROL_PADCONF_DSS_D5 CONTROL_REG32(0x0B8)
+-#define CONTROL_PADCONF_DSS_D9 CONTROL_REG32(0x0BC) /* 2420 */
+-#define CONTROL_PADCONF_DSS_D13 CONTROL_REG32(0x0C0)
+-#define CONTROL_PADCONF_DSS_VSYNC CONTROL_REG32(0x0CC)
+-#define CONTROL_PADCONF_SYS_NIRQW0 CONTROL_REG32(0x0BC) /* 2430 */
+-#define CONTROL_PADCONF_SSI1_FLAG_TX CONTROL_REG32(0x108) /* 2430 */
+-
+-/* CONTROL */
+-#define CONTROL_DEVCONF CONTROL_REG32(0x274)
+-#define CONTROL_DEVCONF1 CONTROL_REG32(0x2E8)
+-
+-/* INTERRUPT CONTROLLER */
+-#define INTC_BASE ((L4_24XX_BASE) + 0xfe000)
+-#define INTC_REG32(offset) __REG32(INTC_BASE + (offset))
+-
+-#define INTC1_U_BASE INTC_REG32(0x000)
+-#define INTC_MIR0 INTC_REG32(0x084)
+-#define INTC_MIR_SET0 INTC_REG32(0x08C)
+-#define INTC_MIR_CLEAR0 INTC_REG32(0x088)
+-#define INTC_ISR_CLEAR0 INTC_REG32(0x094)
+-#define INTC_MIR1 INTC_REG32(0x0A4)
+-#define INTC_MIR_SET1 INTC_REG32(0x0AC)
+-#define INTC_MIR_CLEAR1 INTC_REG32(0x0A8)
+-#define INTC_ISR_CLEAR1 INTC_REG32(0x0B4)
+-#define INTC_MIR2 INTC_REG32(0x0C4)
+-#define INTC_MIR_SET2 INTC_REG32(0x0CC)
+-#define INTC_MIR_CLEAR2 INTC_REG32(0x0C8)
+-#define INTC_ISR_CLEAR2 INTC_REG32(0x0D4)
+-#define INTC_SIR_IRQ INTC_REG32(0x040)
+-#define INTC_CONTROL INTC_REG32(0x048)
+-#define INTC_ILR11 INTC_REG32(0x12C) /* PRCM on MPU PIC */
+-#define INTC_ILR30 INTC_REG32(0x178)
+-#define INTC_ILR31 INTC_REG32(0x17C)
+-#define INTC_ILR32 INTC_REG32(0x180)
+-#define INTC_ILR37 INTC_REG32(0x194) /* GPIO4 on MPU PIC */
+-#define INTC_SYSCONFIG INTC_REG32(0x010) /* GPT1 on MPU PIC */
+-
+-/* RAM FIREWALL */
+-#define RAMFW_BASE (0x68005000)
+-#define RAMFW_REG32(offset) __REG32(RAMFW_BASE + (offset))
+-
+-#define RAMFW_REQINFOPERM0 RAMFW_REG32(0x048)
+-#define RAMFW_READPERM0 RAMFW_REG32(0x050)
+-#define RAMFW_WRITEPERM0 RAMFW_REG32(0x058)
+-
+-/* GPMC CS1 FPGA ON USER INTERFACE MODULE */
+-//#define DEBUG_BOARD_LED_REGISTER 0x04000014
+-
+-/* GPMC CS0 */
+-#define GPMC_CONFIG1_0 GPMC_REG32(0x060)
+-#define GPMC_CONFIG2_0 GPMC_REG32(0x064)
+-#define GPMC_CONFIG3_0 GPMC_REG32(0x068)
+-#define GPMC_CONFIG4_0 GPMC_REG32(0x06C)
+-#define GPMC_CONFIG5_0 GPMC_REG32(0x070)
+-#define GPMC_CONFIG6_0 GPMC_REG32(0x074)
+-#define GPMC_CONFIG7_0 GPMC_REG32(0x078)
+-
+-/* GPMC CS1 */
+-#define GPMC_CONFIG1_1 GPMC_REG32(0x090)
+-#define GPMC_CONFIG2_1 GPMC_REG32(0x094)
+-#define GPMC_CONFIG3_1 GPMC_REG32(0x098)
+-#define GPMC_CONFIG4_1 GPMC_REG32(0x09C)
+-#define GPMC_CONFIG5_1 GPMC_REG32(0x0a0)
+-#define GPMC_CONFIG6_1 GPMC_REG32(0x0a4)
+-#define GPMC_CONFIG7_1 GPMC_REG32(0x0a8)
+-
+-/* GPMC CS3 */
+-#define GPMC_CONFIG1_3 GPMC_REG32(0x0F0)
+-#define GPMC_CONFIG2_3 GPMC_REG32(0x0F4)
+-#define GPMC_CONFIG3_3 GPMC_REG32(0x0F8)
+-#define GPMC_CONFIG4_3 GPMC_REG32(0x0FC)
+-#define GPMC_CONFIG5_3 GPMC_REG32(0x100)
+-#define GPMC_CONFIG6_3 GPMC_REG32(0x104)
+-#define GPMC_CONFIG7_3 GPMC_REG32(0x108)
+-
+-/* DSS */
+-#define DSS_CONTROL DISP_REG32(0x040)
+-#define DISPC_CONTROL DISP_REG32(0x440)
+-#define DISPC_SYSSTATUS DISP_REG32(0x414)
+-#define DISPC_IRQSTATUS DISP_REG32(0x418)
+-#define DISPC_IRQENABLE DISP_REG32(0x41C)
+-#define DISPC_CONFIG DISP_REG32(0x444)
+-#define DISPC_DEFAULT_COLOR0 DISP_REG32(0x44C)
+-#define DISPC_DEFAULT_COLOR1 DISP_REG32(0x450)
+-#define DISPC_TRANS_COLOR0 DISP_REG32(0x454)
+-#define DISPC_TRANS_COLOR1 DISP_REG32(0x458)
+-#define DISPC_LINE_NUMBER DISP_REG32(0x460)
+-#define DISPC_TIMING_H DISP_REG32(0x464)
+-#define DISPC_TIMING_V DISP_REG32(0x468)
+-#define DISPC_POL_FREQ DISP_REG32(0x46C)
+-#define DISPC_DIVISOR DISP_REG32(0x470)
+-#define DISPC_SIZE_DIG DISP_REG32(0x478)
+-#define DISPC_SIZE_LCD DISP_REG32(0x47C)
+-#define DISPC_GFX_BA0 DISP_REG32(0x480)
+-#define DISPC_GFX_BA1 DISP_REG32(0x484)
+-#define DISPC_GFX_POSITION DISP_REG32(0x488)
+-#define DISPC_GFX_SIZE DISP_REG32(0x48C)
+-#define DISPC_GFX_ATTRIBUTES DISP_REG32(0x4A0)
+-#define DISPC_GFX_FIFO_THRESHOLD DISP_REG32(0x4A4)
+-#define DISPC_GFX_ROW_INC DISP_REG32(0x4AC)
+-#define DISPC_GFX_PIXEL_INC DISP_REG32(0x4B0)
+-#define DISPC_GFX_WINDOW_SKIP DISP_REG32(0x4B4)
+-#define DISPC_GFX_TABLE_BA DISP_REG32(0x4B8)
+-#define DISPC_DATA_CYCLE1 DISP_REG32(0x5D4)
+-#define DISPC_DATA_CYCLE2 DISP_REG32(0x5D8)
+-#define DISPC_DATA_CYCLE3 DISP_REG32(0x5DC)
+-
+-/* HSUSB Suspend */
+-#define HSUSB_CTRL __REG8(0x480AC001)
+-#define USBOTG_POWER __REG32(0x480AC000)
+-
+-/* HS MMC */
+-#define MMCHS1_SYSCONFIG __REG32(0x4809C010)
+-#define MMCHS2_SYSCONFIG __REG32(0x480b4010)
+-
+-#endif /* __ASSEMBLER__ */
+-
+-#endif
+-
+-
+-
+-
+-
+diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
+index 90f5305..b12f423 100644
+--- a/arch/arm/mach-omap2/prcm.c
++++ b/arch/arm/mach-omap2/prcm.c
+@@ -17,19 +17,27 @@
+ #include <linux/init.h>
+ #include <linux/clk.h>
+
+-#include "prcm-regs.h"
++#include <asm/io.h>
++
++#include "prm.h"
++#include "prm-regbits-24xx.h"
+
+ extern void omap2_clk_prepare_for_reboot(void);
+
+ u32 omap_prcm_get_reset_sources(void)
+ {
+- return RM_RSTST_WKUP & 0x7f;
++ return prm_read_mod_reg(WKUP_MOD, RM_RSTST) & 0x7f;
+ }
+ EXPORT_SYMBOL(omap_prcm_get_reset_sources);
+
+ /* Resets clock rates and reboots the system. Only called from system.h */
+ void omap_prcm_arch_reset(char mode)
+ {
++ u32 wkup;
+ omap2_clk_prepare_for_reboot();
+- RM_RSTCTRL_WKUP |= 2;
++
++ if (cpu_is_omap24xx()) {
++ wkup = prm_read_mod_reg(WKUP_MOD, RM_RSTCTRL) | OMAP_RST_DPLL3;
++ prm_write_mod_reg(wkup, WKUP_MOD, RM_RSTCTRL);
++ }
+ }
+diff --git a/arch/arm/mach-omap2/prm-regbits-24xx.h b/arch/arm/mach-omap2/prm-regbits-24xx.h
+new file mode 100644
+index 0000000..c6d17a3
+--- /dev/null
++++ b/arch/arm/mach-omap2/prm-regbits-24xx.h
+@@ -0,0 +1,279 @@
++#ifndef __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_24XX_H
++#define __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_24XX_H
++
++/*
++ * OMAP24XX Power/Reset Management register bits
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ * Copyright (C) 2007 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "prm.h"
++
++/* Bits shared between registers */
++
++/* PRCM_IRQSTATUS_MPU, PM_IRQSTATUS_DSP, PRCM_IRQSTATUS_IVA shared bits */
++#define OMAP24XX_VOLTTRANS_ST (1 << 2)
++#define OMAP24XX_WKUP2_ST (1 << 1)
++#define OMAP24XX_WKUP1_ST (1 << 0)
++
++/* PRCM_IRQENABLE_MPU, PM_IRQENABLE_DSP, PRCM_IRQENABLE_IVA shared bits */
++#define OMAP24XX_VOLTTRANS_EN (1 << 2)
++#define OMAP24XX_WKUP2_EN (1 << 1)
++#define OMAP24XX_WKUP1_EN (1 << 0)
++
++/* PM_WKDEP_GFX, PM_WKDEP_MPU, PM_WKDEP_DSP, PM_WKDEP_MDM shared bits */
++#define OMAP24XX_EN_MPU (1 << 1)
++#define OMAP24XX_EN_CORE (1 << 0)
++
++/*
++ * PM_PWSTCTRL_MPU, PM_PWSTCTRL_GFX, PM_PWSTCTRL_DSP, PM_PWSTCTRL_MDM
++ * shared bits
++ */
++#define OMAP24XX_MEMONSTATE_SHIFT 10
++#define OMAP24XX_MEMONSTATE_MASK (0x3 << 10)
++#define OMAP24XX_MEMRETSTATE (1 << 3)
++
++/* PM_PWSTCTRL_GFX, PM_PWSTCTRL_DSP, PM_PWSTCTRL_MDM shared bits */
++#define OMAP24XX_FORCESTATE (1 << 18)
++
++/*
++ * PM_PWSTST_CORE, PM_PWSTST_GFX, PM_PWSTST_MPU, PM_PWSTST_DSP,
++ * PM_PWSTST_MDM shared bits
++ */
++#define OMAP24XX_CLKACTIVITY (1 << 19)
++
++/* PM_PWSTST_MPU, PM_PWSTST_CORE, PM_PWSTST_DSP shared bits */
++#define OMAP24XX_LASTSTATEENTERED_SHIFT 4
++#define OMAP24XX_LASTSTATEENTERED_MASK (0x3 << 4)
++
++/* PM_PWSTST_MPU and PM_PWSTST_DSP shared bits */
++#define OMAP2430_MEMSTATEST_SHIFT 10
++#define OMAP2430_MEMSTATEST_MASK (0x3 << 10)
++
++/* PM_PWSTST_GFX, PM_PWSTST_DSP, PM_PWSTST_MDM shared bits */
++#define OMAP24XX_POWERSTATEST_SHIFT 0
++#define OMAP24XX_POWERSTATEST_MASK (0x3 << 0)
++
++
++/* Bits specific to each register */
++
++/* PRCM_REVISION */
++#define OMAP24XX_REV_SHIFT 0
++#define OMAP24XX_REV_MASK (0xff << 0)
++
++/* PRCM_SYSCONFIG */
++#define OMAP24XX_AUTOIDLE (1 << 0)
++
++/* PRCM_IRQSTATUS_MPU specific bits */
++#define OMAP2430_DPLL_RECAL_ST (1 << 6)
++#define OMAP24XX_TRANSITION_ST (1 << 5)
++#define OMAP24XX_EVGENOFF_ST (1 << 4)
++#define OMAP24XX_EVGENON_ST (1 << 3)
++
++/* PRCM_IRQENABLE_MPU specific bits */
++#define OMAP2430_DPLL_RECAL_EN (1 << 6)
++#define OMAP24XX_TRANSITION_EN (1 << 5)
++#define OMAP24XX_EVGENOFF_EN (1 << 4)
++#define OMAP24XX_EVGENON_EN (1 << 3)
++
++/* PRCM_VOLTCTRL */
++#define OMAP24XX_AUTO_EXTVOLT (1 << 15)
++#define OMAP24XX_FORCE_EXTVOLT (1 << 14)
++#define OMAP24XX_SETOFF_LEVEL_SHIFT 12
++#define OMAP24XX_SETOFF_LEVEL_MASK (0x3 << 12)
++#define OMAP24XX_MEMRETCTRL (1 << 8)
++#define OMAP24XX_SETRET_LEVEL_SHIFT 6
++#define OMAP24XX_SETRET_LEVEL_MASK (0x3 << 6)
++#define OMAP24XX_VOLT_LEVEL_SHIFT 0
++#define OMAP24XX_VOLT_LEVEL_MASK (0x3 << 0)
++
++/* PRCM_VOLTST */
++#define OMAP24XX_ST_VOLTLEVEL_SHIFT 0
++#define OMAP24XX_ST_VOLTLEVEL_MASK (0x3 << 0)
++
++/* PRCM_CLKSRC_CTRL specific bits */
++
++/* PRCM_CLKOUT_CTRL */
++#define OMAP2420_CLKOUT2_EN_SHIFT 15
++#define OMAP2420_CLKOUT2_EN (1 << 15)
++#define OMAP2420_CLKOUT2_DIV_SHIFT 11
++#define OMAP2420_CLKOUT2_DIV_MASK (0x7 << 11)
++#define OMAP2420_CLKOUT2_SOURCE_SHIFT 8
++#define OMAP2420_CLKOUT2_SOURCE_MASK (0x3 << 8)
++#define OMAP24XX_CLKOUT_EN_SHIFT 7
++#define OMAP24XX_CLKOUT_EN (1 << 7)
++#define OMAP24XX_CLKOUT_DIV_SHIFT 3
++#define OMAP24XX_CLKOUT_DIV_MASK (0x7 << 3)
++#define OMAP24XX_CLKOUT_SOURCE_SHIFT 0
++#define OMAP24XX_CLKOUT_SOURCE_MASK (0x3 << 0)
++
++/* PRCM_CLKEMUL_CTRL */
++#define OMAP24XX_EMULATION_EN_SHIFT 0
++#define OMAP24XX_EMULATION_EN (1 << 0)
++
++/* PRCM_CLKCFG_CTRL */
++#define OMAP24XX_VALID_CONFIG (1 << 0)
++
++/* PRCM_CLKCFG_STATUS */
++#define OMAP24XX_CONFIG_STATUS (1 << 0)
++
++/* PRCM_VOLTSETUP specific bits */
++
++/* PRCM_CLKSSETUP specific bits */
++
++/* PRCM_POLCTRL */
++#define OMAP2420_CLKOUT2_POL (1 << 10)
++#define OMAP24XX_CLKOUT_POL (1 << 9)
++#define OMAP24XX_CLKREQ_POL (1 << 8)
++#define OMAP2430_USE_POWEROK (1 << 2)
++#define OMAP2430_POWEROK_POL (1 << 1)
++#define OMAP24XX_EXTVOL_POL (1 << 0)
++
++/* RM_RSTST_MPU specific bits */
++/* 2430 calls GLOBALWMPU_RST "GLOBALWARM_RST" instead */
++
++/* PM_WKDEP_MPU specific bits */
++#define OMAP2430_PM_WKDEP_MPU_EN_MDM (1 << 5)
++#define OMAP24XX_PM_WKDEP_MPU_EN_DSP (1 << 2)
++
++/* PM_EVGENCTRL_MPU specific bits */
++
++/* PM_EVEGENONTIM_MPU specific bits */
++
++/* PM_EVEGENOFFTIM_MPU specific bits */
++
++/* PM_PWSTCTRL_MPU specific bits */
++#define OMAP2430_FORCESTATE (1 << 18)
++
++/* PM_PWSTST_MPU specific bits */
++/* INTRANSITION, CLKACTIVITY, POWERSTATE, MEMSTATEST are 2430 only */
++
++/* PM_WKEN1_CORE specific bits */
++
++/* PM_WKEN2_CORE specific bits */
++
++/* PM_WKST1_CORE specific bits*/
++
++/* PM_WKST2_CORE specific bits */
++
++/* PM_WKDEP_CORE specific bits*/
++#define OMAP2430_PM_WKDEP_CORE_EN_MDM (1 << 5)
++#define OMAP24XX_PM_WKDEP_CORE_EN_GFX (1 << 3)
++#define OMAP24XX_PM_WKDEP_CORE_EN_DSP (1 << 2)
++
++/* PM_PWSTCTRL_CORE specific bits */
++#define OMAP24XX_MEMORYCHANGE (1 << 20)
++#define OMAP24XX_MEM3ONSTATE_SHIFT 14
++#define OMAP24XX_MEM3ONSTATE_MASK (0x3 << 14)
++#define OMAP24XX_MEM2ONSTATE_SHIFT 12
++#define OMAP24XX_MEM2ONSTATE_MASK (0x3 << 12)
++#define OMAP24XX_MEM1ONSTATE_SHIFT 10
++#define OMAP24XX_MEM1ONSTATE_MASK (0x3 << 10)
++#define OMAP24XX_MEM3RETSTATE (1 << 5)
++#define OMAP24XX_MEM2RETSTATE (1 << 4)
++#define OMAP24XX_MEM1RETSTATE (1 << 3)
++
++/* PM_PWSTST_CORE specific bits */
++#define OMAP24XX_MEM3STATEST_SHIFT 14
++#define OMAP24XX_MEM3STATEST_MASK (0x3 << 14)
++#define OMAP24XX_MEM2STATEST_SHIFT 12
++#define OMAP24XX_MEM2STATEST_MASK (0x3 << 12)
++#define OMAP24XX_MEM1STATEST_SHIFT 10
++#define OMAP24XX_MEM1STATEST_MASK (0x3 << 10)
++
++/* RM_RSTCTRL_GFX */
++#define OMAP24XX_GFX_RST (1 << 0)
++
++/* RM_RSTST_GFX specific bits */
++#define OMAP24XX_GFX_SW_RST (1 << 4)
++
++/* PM_PWSTCTRL_GFX specific bits */
++
++/* PM_WKDEP_GFX specific bits */
++/* 2430 often calls EN_WAKEUP "EN_WKUP" */
++
++/* RM_RSTCTRL_WKUP specific bits */
++
++/* RM_RSTTIME_WKUP specific bits */
++
++/* RM_RSTST_WKUP specific bits */
++/* 2430 calls EXTWMPU_RST "EXTWARM_RST" and GLOBALWMPU_RST "GLOBALWARM_RST" */
++#define OMAP24XX_EXTWMPU_RST (1 << 6)
++#define OMAP24XX_SECU_WD_RST (1 << 5)
++#define OMAP24XX_MPU_WD_RST (1 << 4)
++#define OMAP24XX_SECU_VIOL_RST (1 << 3)
++
++/* PM_WKEN_WKUP specific bits */
++
++/* PM_WKST_WKUP specific bits */
++
++/* RM_RSTCTRL_DSP */
++#define OMAP2420_RST_IVA (1 << 8)
++#define OMAP24XX_RST2_DSP (1 << 1)
++#define OMAP24XX_RST1_DSP (1 << 0)
++
++/* RM_RSTST_DSP specific bits */
++/* 2430 calls GLOBALWMPU_RST "GLOBALWARM_RST" */
++#define OMAP2420_IVA_SW_RST (1 << 8)
++#define OMAP24XX_DSP_SW_RST2 (1 << 5)
++#define OMAP24XX_DSP_SW_RST1 (1 << 4)
++
++/* PM_WKDEP_DSP specific bits */
++
++/* PM_PWSTCTRL_DSP specific bits */
++/* 2430 only: MEMONSTATE, MEMRETSTATE */
++#define OMAP2420_MEMIONSTATE_SHIFT 12
++#define OMAP2420_MEMIONSTATE_MASK (0x3 << 12)
++#define OMAP2420_MEMIRETSTATE (1 << 4)
++
++/* PM_PWSTST_DSP specific bits */
++/* MEMSTATEST is 2430 only */
++#define OMAP2420_MEMISTATEST_SHIFT 12
++#define OMAP2420_MEMISTATEST_MASK (0x3 << 12)
++
++/* PRCM_IRQSTATUS_DSP specific bits */
++
++/* PRCM_IRQENABLE_DSP specific bits */
++
++/* RM_RSTCTRL_MDM */
++/* 2430 only */
++#define OMAP2430_PWRON1_MDM (1 << 1)
++#define OMAP2430_RST1_MDM (1 << 0)
++
++/* RM_RSTST_MDM specific bits */
++/* 2430 only */
++#define OMAP2430_MDM_SECU_VIOL (1 << 6)
++#define OMAP2430_MDM_SW_PWRON1 (1 << 5)
++#define OMAP2430_MDM_SW_RST1 (1 << 4)
++
++/* PM_WKEN_MDM */
++/* 2430 only */
++#define OMAP2430_PM_WKEN_MDM_EN_MDM (1 << 0)
++
++/* PM_WKST_MDM specific bits */
++/* 2430 only */
++
++/* PM_WKDEP_MDM specific bits */
++/* 2430 only */
++
++/* PM_PWSTCTRL_MDM specific bits */
++/* 2430 only */
++#define OMAP2430_KILLDOMAINWKUP (1 << 19)
++
++/* PM_PWSTST_MDM specific bits */
++/* 2430 only */
++
++/* PRCM_IRQSTATUS_IVA */
++/* 2420 only */
++
++/* PRCM_IRQENABLE_IVA */
++/* 2420 only */
++
++#endif
+diff --git a/arch/arm/mach-omap2/prm-regbits-34xx.h b/arch/arm/mach-omap2/prm-regbits-34xx.h
+new file mode 100644
+index 0000000..b4686bc
+--- /dev/null
++++ b/arch/arm/mach-omap2/prm-regbits-34xx.h
+@@ -0,0 +1,582 @@
++#ifndef __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_34XX_H
++#define __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_34XX_H
++
++/*
++ * OMAP3430 Power/Reset Management register bits
++ *
++ * Copyright (C) 2007-2008 Texas Instruments, Inc.
++ * Copyright (C) 2007-2008 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "prm.h"
++
++/* Shared register bits */
++
++/* PRM_VC_CMD_VAL_0, PRM_VC_CMD_VAL_1 shared bits */
++#define OMAP3430_ON_SHIFT 24
++#define OMAP3430_ON_MASK (0xff << 24)
++#define OMAP3430_ONLP_SHIFT 16
++#define OMAP3430_ONLP_MASK (0xff << 16)
++#define OMAP3430_RET_SHIFT 8
++#define OMAP3430_RET_MASK (0xff << 8)
++#define OMAP3430_OFF_SHIFT 0
++#define OMAP3430_OFF_MASK (0xff << 0)
++
++/* PRM_VP1_CONFIG, PRM_VP2_CONFIG shared bits */
++#define OMAP3430_ERROROFFSET_SHIFT 24
++#define OMAP3430_ERROROFFSET_MASK (0xff << 24)
++#define OMAP3430_ERRORGAIN_SHIFT 16
++#define OMAP3430_ERRORGAIN_MASK (0xff << 16)
++#define OMAP3430_INITVOLTAGE_SHIFT 8
++#define OMAP3430_INITVOLTAGE_MASK (0xff << 8)
++#define OMAP3430_TIMEOUTEN (1 << 3)
++#define OMAP3430_INITVDD (1 << 2)
++#define OMAP3430_FORCEUPDATE (1 << 1)
++#define OMAP3430_VPENABLE (1 << 0)
++
++/* PRM_VP1_VSTEPMIN, PRM_VP2_VSTEPMIN shared bits */
++#define OMAP3430_SMPSWAITTIMEMIN_SHIFT 8
++#define OMAP3430_SMPSWAITTIMEMIN_MASK (0xffff << 8)
++#define OMAP3430_VSTEPMIN_SHIFT 0
++#define OMAP3430_VSTEPMIN_MASK (0xff << 0)
++
++/* PRM_VP1_VSTEPMAX, PRM_VP2_VSTEPMAX shared bits */
++#define OMAP3430_SMPSWAITTIMEMAX_SHIFT 8
++#define OMAP3430_SMPSWAITTIMEMAX_MASK (0xffff << 8)
++#define OMAP3430_VSTEPMAX_SHIFT 0
++#define OMAP3430_VSTEPMAX_MASK (0xff << 0)
++
++/* PRM_VP1_VLIMITTO, PRM_VP2_VLIMITTO shared bits */
++#define OMAP3430_VDDMAX_SHIFT 24
++#define OMAP3430_VDDMAX_MASK (0xff << 24)
++#define OMAP3430_VDDMIN_SHIFT 16
++#define OMAP3430_VDDMIN_MASK (0xff << 16)
++#define OMAP3430_TIMEOUT_SHIFT 0
++#define OMAP3430_TIMEOUT_MASK (0xffff << 0)
++
++/* PRM_VP1_VOLTAGE, PRM_VP2_VOLTAGE shared bits */
++#define OMAP3430_VPVOLTAGE_SHIFT 0
++#define OMAP3430_VPVOLTAGE_MASK (0xff << 0)
++
++/* PRM_VP1_STATUS, PRM_VP2_STATUS shared bits */
++#define OMAP3430_VPINIDLE (1 << 0)
++
++/* PM_WKDEP_IVA2, PM_WKDEP_MPU shared bits */
++#define OMAP3430_EN_PER (1 << 7)
++
++/* PM_PWSTCTRL_IVA2, PM_PWSTCTRL_MPU, PM_PWSTCTRL_CORE shared bits */
++#define OMAP3430_MEMORYCHANGE (1 << 3)
++
++/* PM_PWSTST_IVA2, PM_PWSTST_CORE shared bits */
++#define OMAP3430_LOGICSTATEST (1 << 2)
++
++/* PM_PREPWSTST_IVA2, PM_PREPWSTST_CORE shared bits */
++#define OMAP3430_LASTLOGICSTATEENTERED (1 << 2)
++
++/*
++ * PM_PREPWSTST_IVA2, PM_PREPWSTST_MPU, PM_PREPWSTST_CORE,
++ * PM_PREPWSTST_GFX, PM_PREPWSTST_DSS, PM_PREPWSTST_CAM,
++ * PM_PREPWSTST_PER, PM_PREPWSTST_NEON shared bits
++ */
++#define OMAP3430_LASTPOWERSTATEENTERED_SHIFT 0
++#define OMAP3430_LASTPOWERSTATEENTERED_MASK (0x3 << 0)
++
++/* PRM_IRQSTATUS_IVA2, PRM_IRQSTATUS_MPU shared bits */
++#define OMAP3430_WKUP_ST (1 << 0)
++
++/* PRM_IRQENABLE_IVA2, PRM_IRQENABLE_MPU shared bits */
++#define OMAP3430_WKUP_EN (1 << 0)
++
++/* PM_MPUGRPSEL1_CORE, PM_IVA2GRPSEL1_CORE shared bits */
++#define OMAP3430_GRPSEL_MMC2 (1 << 25)
++#define OMAP3430_GRPSEL_MMC1 (1 << 24)
++#define OMAP3430_GRPSEL_MCSPI4 (1 << 21)
++#define OMAP3430_GRPSEL_MCSPI3 (1 << 20)
++#define OMAP3430_GRPSEL_MCSPI2 (1 << 19)
++#define OMAP3430_GRPSEL_MCSPI1 (1 << 18)
++#define OMAP3430_GRPSEL_I2C3 (1 << 17)
++#define OMAP3430_GRPSEL_I2C2 (1 << 16)
++#define OMAP3430_GRPSEL_I2C1 (1 << 15)
++#define OMAP3430_GRPSEL_UART2 (1 << 14)
++#define OMAP3430_GRPSEL_UART1 (1 << 13)
++#define OMAP3430_GRPSEL_GPT11 (1 << 12)
++#define OMAP3430_GRPSEL_GPT10 (1 << 11)
++#define OMAP3430_GRPSEL_MCBSP5 (1 << 10)
++#define OMAP3430_GRPSEL_MCBSP1 (1 << 9)
++#define OMAP3430_GRPSEL_HSOTGUSB (1 << 4)
++#define OMAP3430_GRPSEL_D2D (1 << 3)
++
++/*
++ * PM_PWSTCTRL_GFX, PM_PWSTCTRL_DSS, PM_PWSTCTRL_CAM,
++ * PM_PWSTCTRL_PER shared bits
++ */
++#define OMAP3430_MEMONSTATE_SHIFT 16
++#define OMAP3430_MEMONSTATE_MASK (0x3 << 16)
++#define OMAP3430_MEMRETSTATE (1 << 8)
++
++/* PM_MPUGRPSEL_PER, PM_IVA2GRPSEL_PER shared bits */
++#define OMAP3430_GRPSEL_GPIO6 (1 << 17)
++#define OMAP3430_GRPSEL_GPIO5 (1 << 16)
++#define OMAP3430_GRPSEL_GPIO4 (1 << 15)
++#define OMAP3430_GRPSEL_GPIO3 (1 << 14)
++#define OMAP3430_GRPSEL_GPIO2 (1 << 13)
++#define OMAP3430_GRPSEL_UART3 (1 << 11)
++#define OMAP3430_GRPSEL_GPT9 (1 << 10)
++#define OMAP3430_GRPSEL_GPT8 (1 << 9)
++#define OMAP3430_GRPSEL_GPT7 (1 << 8)
++#define OMAP3430_GRPSEL_GPT6 (1 << 7)
++#define OMAP3430_GRPSEL_GPT5 (1 << 6)
++#define OMAP3430_GRPSEL_GPT4 (1 << 5)
++#define OMAP3430_GRPSEL_GPT3 (1 << 4)
++#define OMAP3430_GRPSEL_GPT2 (1 << 3)
++#define OMAP3430_GRPSEL_MCBSP4 (1 << 2)
++#define OMAP3430_GRPSEL_MCBSP3 (1 << 1)
++#define OMAP3430_GRPSEL_MCBSP2 (1 << 0)
++
++/* PM_MPUGRPSEL_WKUP, PM_IVA2GRPSEL_WKUP shared bits */
++#define OMAP3430_GRPSEL_IO (1 << 8)
++#define OMAP3430_GRPSEL_SR2 (1 << 7)
++#define OMAP3430_GRPSEL_SR1 (1 << 6)
++#define OMAP3430_GRPSEL_GPIO1 (1 << 3)
++#define OMAP3430_GRPSEL_GPT12 (1 << 1)
++#define OMAP3430_GRPSEL_GPT1 (1 << 0)
++
++/* Bits specific to each register */
++
++/* RM_RSTCTRL_IVA2 */
++#define OMAP3430_RST3_IVA2 (1 << 2)
++#define OMAP3430_RST2_IVA2 (1 << 1)
++#define OMAP3430_RST1_IVA2 (1 << 0)
++
++/* RM_RSTST_IVA2 specific bits */
++#define OMAP3430_EMULATION_VSEQ_RST (1 << 13)
++#define OMAP3430_EMULATION_VHWA_RST (1 << 12)
++#define OMAP3430_EMULATION_IVA2_RST (1 << 11)
++#define OMAP3430_IVA2_SW_RST3 (1 << 10)
++#define OMAP3430_IVA2_SW_RST2 (1 << 9)
++#define OMAP3430_IVA2_SW_RST1 (1 << 8)
++
++/* PM_WKDEP_IVA2 specific bits */
++
++/* PM_PWSTCTRL_IVA2 specific bits */
++#define OMAP3430_L2FLATMEMONSTATE_SHIFT 22
++#define OMAP3430_L2FLATMEMONSTATE_MASK (0x3 << 22)
++#define OMAP3430_SHAREDL2CACHEFLATONSTATE_SHIFT 20
++#define OMAP3430_SHAREDL2CACHEFLATONSTATE_MASK (0x3 << 20)
++#define OMAP3430_L1FLATMEMONSTATE_SHIFT 18
++#define OMAP3430_L1FLATMEMONSTATE_MASK (0x3 << 18)
++#define OMAP3430_SHAREDL1CACHEFLATONSTATE_SHIFT 16
++#define OMAP3430_SHAREDL1CACHEFLATONSTATE_MASK (0x3 << 16)
++#define OMAP3430_L2FLATMEMRETSTATE (1 << 11)
++#define OMAP3430_SHAREDL2CACHEFLATRETSTATE (1 << 10)
++#define OMAP3430_L1FLATMEMRETSTATE (1 << 9)
++#define OMAP3430_SHAREDL1CACHEFLATRETSTATE (1 << 8)
++
++/* PM_PWSTST_IVA2 specific bits */
++#define OMAP3430_L2FLATMEMSTATEST_SHIFT 10
++#define OMAP3430_L2FLATMEMSTATEST_MASK (0x3 << 10)
++#define OMAP3430_SHAREDL2CACHEFLATSTATEST_SHIFT 8
++#define OMAP3430_SHAREDL2CACHEFLATSTATEST_MASK (0x3 << 8)
++#define OMAP3430_L1FLATMEMSTATEST_SHIFT 6
++#define OMAP3430_L1FLATMEMSTATEST_MASK (0x3 << 6)
++#define OMAP3430_SHAREDL1CACHEFLATSTATEST_SHIFT 4
++#define OMAP3430_SHAREDL1CACHEFLATSTATEST_MASK (0x3 << 4)
++
++/* PM_PREPWSTST_IVA2 specific bits */
++#define OMAP3430_LASTL2FLATMEMSTATEENTERED_SHIFT 10
++#define OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK (0x3 << 10)
++#define OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_SHIFT 8
++#define OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK (0x3 << 8)
++#define OMAP3430_LASTL1FLATMEMSTATEENTERED_SHIFT 6
++#define OMAP3430_LASTL1FLATMEMSTATEENTERED_MASK (0x3 << 6)
++#define OMAP3430_LASTSHAREDL1CACHEFLATSTATEENTERED_SHIFT 4
++#define OMAP3430_LASTSHAREDL1CACHEFLATSTATEENTERED_MASK (0x3 << 4)
++
++/* PRM_IRQSTATUS_IVA2 specific bits */
++#define OMAP3430_PRM_IRQSTATUS_IVA2_IVA2_DPLL_ST (1 << 2)
++#define OMAP3430_FORCEWKUP_ST (1 << 1)
++
++/* PRM_IRQENABLE_IVA2 specific bits */
++#define OMAP3430_PRM_IRQENABLE_IVA2_IVA2_DPLL_RECAL_EN (1 << 2)
++#define OMAP3430_FORCEWKUP_EN (1 << 1)
++
++/* PRM_REVISION specific bits */
++
++/* PRM_SYSCONFIG specific bits */
++
++/* PRM_IRQSTATUS_MPU specific bits */
++#define OMAP3430ES2_SND_PERIPH_DPLL_ST_SHIFT 25
++#define OMAP3430ES2_SND_PERIPH_DPLL_ST (1 << 25)
++#define OMAP3430_VC_TIMEOUTERR_ST (1 << 24)
++#define OMAP3430_VC_RAERR_ST (1 << 23)
++#define OMAP3430_VC_SAERR_ST (1 << 22)
++#define OMAP3430_VP2_TRANXDONE_ST (1 << 21)
++#define OMAP3430_VP2_EQVALUE_ST (1 << 20)
++#define OMAP3430_VP2_NOSMPSACK_ST (1 << 19)
++#define OMAP3430_VP2_MAXVDD_ST (1 << 18)
++#define OMAP3430_VP2_MINVDD_ST (1 << 17)
++#define OMAP3430_VP2_OPPCHANGEDONE_ST (1 << 16)
++#define OMAP3430_VP1_TRANXDONE_ST (1 << 15)
++#define OMAP3430_VP1_EQVALUE_ST (1 << 14)
++#define OMAP3430_VP1_NOSMPSACK_ST (1 << 13)
++#define OMAP3430_VP1_MAXVDD_ST (1 << 12)
++#define OMAP3430_VP1_MINVDD_ST (1 << 11)
++#define OMAP3430_VP1_OPPCHANGEDONE_ST (1 << 10)
++#define OMAP3430_IO_ST (1 << 9)
++#define OMAP3430_PRM_IRQSTATUS_MPU_IVA2_DPLL_ST (1 << 8)
++#define OMAP3430_PRM_IRQSTATUS_MPU_IVA2_DPLL_ST_SHIFT 8
++#define OMAP3430_MPU_DPLL_ST (1 << 7)
++#define OMAP3430_MPU_DPLL_ST_SHIFT 7
++#define OMAP3430_PERIPH_DPLL_ST (1 << 6)
++#define OMAP3430_PERIPH_DPLL_ST_SHIFT 6
++#define OMAP3430_CORE_DPLL_ST (1 << 5)
++#define OMAP3430_CORE_DPLL_ST_SHIFT 5
++#define OMAP3430_TRANSITION_ST (1 << 4)
++#define OMAP3430_EVGENOFF_ST (1 << 3)
++#define OMAP3430_EVGENON_ST (1 << 2)
++#define OMAP3430_FS_USB_WKUP_ST (1 << 1)
++
++/* PRM_IRQENABLE_MPU specific bits */
++#define OMAP3430ES2_SND_PERIPH_DPLL_RECAL_EN_SHIFT 25
++#define OMAP3430ES2_SND_PERIPH_DPLL_RECAL_EN (1 << 25)
++#define OMAP3430_VC_TIMEOUTERR_EN (1 << 24)
++#define OMAP3430_VC_RAERR_EN (1 << 23)
++#define OMAP3430_VC_SAERR_EN (1 << 22)
++#define OMAP3430_VP2_TRANXDONE_EN (1 << 21)
++#define OMAP3430_VP2_EQVALUE_EN (1 << 20)
++#define OMAP3430_VP2_NOSMPSACK_EN (1 << 19)
++#define OMAP3430_VP2_MAXVDD_EN (1 << 18)
++#define OMAP3430_VP2_MINVDD_EN (1 << 17)
++#define OMAP3430_VP2_OPPCHANGEDONE_EN (1 << 16)
++#define OMAP3430_VP1_TRANXDONE_EN (1 << 15)
++#define OMAP3430_VP1_EQVALUE_EN (1 << 14)
++#define OMAP3430_VP1_NOSMPSACK_EN (1 << 13)
++#define OMAP3430_VP1_MAXVDD_EN (1 << 12)
++#define OMAP3430_VP1_MINVDD_EN (1 << 11)
++#define OMAP3430_VP1_OPPCHANGEDONE_EN (1 << 10)
++#define OMAP3430_IO_EN (1 << 9)
++#define OMAP3430_PRM_IRQENABLE_MPU_IVA2_DPLL_RECAL_EN (1 << 8)
++#define OMAP3430_PRM_IRQENABLE_MPU_IVA2_DPLL_RECAL_EN_SHIFT 8
++#define OMAP3430_MPU_DPLL_RECAL_EN (1 << 7)
++#define OMAP3430_MPU_DPLL_RECAL_EN_SHIFT 7
++#define OMAP3430_PERIPH_DPLL_RECAL_EN (1 << 6)
++#define OMAP3430_PERIPH_DPLL_RECAL_EN_SHIFT 6
++#define OMAP3430_CORE_DPLL_RECAL_EN (1 << 5)
++#define OMAP3430_CORE_DPLL_RECAL_EN_SHIFT 5
++#define OMAP3430_TRANSITION_EN (1 << 4)
++#define OMAP3430_EVGENOFF_EN (1 << 3)
++#define OMAP3430_EVGENON_EN (1 << 2)
++#define OMAP3430_FS_USB_WKUP_EN (1 << 1)
++
++/* RM_RSTST_MPU specific bits */
++#define OMAP3430_EMULATION_MPU_RST (1 << 11)
++
++/* PM_WKDEP_MPU specific bits */
++#define OMAP3430_PM_WKDEP_MPU_EN_DSS (1 << 5)
++#define OMAP3430_PM_WKDEP_MPU_EN_IVA2 (1 << 2)
++
++/* PM_EVGENCTRL_MPU */
++#define OMAP3430_OFFLOADMODE_SHIFT 3
++#define OMAP3430_OFFLOADMODE_MASK (0x3 << 3)
++#define OMAP3430_ONLOADMODE_SHIFT 1
++#define OMAP3430_ONLOADMODE_MASK (0x3 << 1)
++#define OMAP3430_ENABLE (1 << 0)
++
++/* PM_EVGENONTIM_MPU */
++#define OMAP3430_ONTIMEVAL_SHIFT 0
++#define OMAP3430_ONTIMEVAL_MASK (0xffffffff << 0)
++
++/* PM_EVGENOFFTIM_MPU */
++#define OMAP3430_OFFTIMEVAL_SHIFT 0
++#define OMAP3430_OFFTIMEVAL_MASK (0xffffffff << 0)
++
++/* PM_PWSTCTRL_MPU specific bits */
++#define OMAP3430_L2CACHEONSTATE_SHIFT 16
++#define OMAP3430_L2CACHEONSTATE_MASK (0x3 << 16)
++#define OMAP3430_L2CACHERETSTATE (1 << 8)
++#define OMAP3430_LOGICL1CACHERETSTATE (1 << 2)
++
++/* PM_PWSTST_MPU specific bits */
++#define OMAP3430_L2CACHESTATEST_SHIFT 6
++#define OMAP3430_L2CACHESTATEST_MASK (0x3 << 6)
++#define OMAP3430_LOGICL1CACHESTATEST (1 << 2)
++
++/* PM_PREPWSTST_MPU specific bits */
++#define OMAP3430_LASTL2CACHESTATEENTERED_SHIFT 6
++#define OMAP3430_LASTL2CACHESTATEENTERED_MASK (0x3 << 6)
++#define OMAP3430_LASTLOGICL1CACHESTATEENTERED (1 << 2)
++
++/* RM_RSTCTRL_CORE */
++#define OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RSTPWRON (1 << 1)
++#define OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RST (1 << 0)
++
++/* RM_RSTST_CORE specific bits */
++#define OMAP3430_MODEM_SECURITY_VIOL_RST (1 << 10)
++#define OMAP3430_RM_RSTST_CORE_MODEM_SW_RSTPWRON (1 << 9)
++#define OMAP3430_RM_RSTST_CORE_MODEM_SW_RST (1 << 8)
++
++/* PM_WKEN1_CORE specific bits */
++
++/* PM_MPUGRPSEL1_CORE specific bits */
++#define OMAP3430_GRPSEL_FSHOSTUSB (1 << 5)
++
++/* PM_IVA2GRPSEL1_CORE specific bits */
++
++/* PM_WKST1_CORE specific bits */
++
++/* PM_PWSTCTRL_CORE specific bits */
++#define OMAP3430_MEM2ONSTATE_SHIFT 18
++#define OMAP3430_MEM2ONSTATE_MASK (0x3 << 18)
++#define OMAP3430_MEM1ONSTATE_SHIFT 16
++#define OMAP3430_MEM1ONSTATE_MASK (0x3 << 16)
++#define OMAP3430_MEM2RETSTATE (1 << 9)
++#define OMAP3430_MEM1RETSTATE (1 << 8)
++
++/* PM_PWSTST_CORE specific bits */
++#define OMAP3430_MEM2STATEST_SHIFT 6
++#define OMAP3430_MEM2STATEST_MASK (0x3 << 6)
++#define OMAP3430_MEM1STATEST_SHIFT 4
++#define OMAP3430_MEM1STATEST_MASK (0x3 << 4)
++
++/* PM_PREPWSTST_CORE specific bits */
++#define OMAP3430_LASTMEM2STATEENTERED_SHIFT 6
++#define OMAP3430_LASTMEM2STATEENTERED_MASK (0x3 << 6)
++#define OMAP3430_LASTMEM1STATEENTERED_SHIFT 4
++#define OMAP3430_LASTMEM1STATEENTERED_MASK (0x3 << 4)
++
++/* RM_RSTST_GFX specific bits */
++
++/* PM_WKDEP_GFX specific bits */
++#define OMAP3430_PM_WKDEP_GFX_EN_IVA2 (1 << 2)
++
++/* PM_PWSTCTRL_GFX specific bits */
++
++/* PM_PWSTST_GFX specific bits */
++
++/* PM_PREPWSTST_GFX specific bits */
++
++/* PM_WKEN_WKUP specific bits */
++#define OMAP3430_EN_IO (1 << 8)
++
++/* PM_MPUGRPSEL_WKUP specific bits */
++
++/* PM_IVA2GRPSEL_WKUP specific bits */
++
++/* PM_WKST_WKUP specific bits */
++#define OMAP3430_ST_IO (1 << 8)
++
++/* PRM_CLKSEL */
++#define OMAP3430_SYS_CLKIN_SEL_SHIFT 0
++#define OMAP3430_SYS_CLKIN_SEL_MASK (0x7 << 0)
++
++/* PRM_CLKOUT_CTRL */
++#define OMAP3430_CLKOUT_EN (1 << 7)
++#define OMAP3430_CLKOUT_EN_SHIFT 7
++
++/* RM_RSTST_DSS specific bits */
++
++/* PM_WKEN_DSS */
++#define OMAP3430_PM_WKEN_DSS_EN_DSS (1 << 0)
++
++/* PM_WKDEP_DSS specific bits */
++#define OMAP3430_PM_WKDEP_DSS_EN_IVA2 (1 << 2)
++
++/* PM_PWSTCTRL_DSS specific bits */
++
++/* PM_PWSTST_DSS specific bits */
++
++/* PM_PREPWSTST_DSS specific bits */
++
++/* RM_RSTST_CAM specific bits */
++
++/* PM_WKDEP_CAM specific bits */
++#define OMAP3430_PM_WKDEP_CAM_EN_IVA2 (1 << 2)
++
++/* PM_PWSTCTRL_CAM specific bits */
++
++/* PM_PWSTST_CAM specific bits */
++
++/* PM_PREPWSTST_CAM specific bits */
++
++/* PM_PWSTCTRL_USBHOST specific bits */
++#define OMAP3430ES2_SAVEANDRESTORE_SHIFT (1 << 4)
++
++/* RM_RSTST_PER specific bits */
++
++/* PM_WKEN_PER specific bits */
++
++/* PM_MPUGRPSEL_PER specific bits */
++
++/* PM_IVA2GRPSEL_PER specific bits */
++
++/* PM_WKST_PER specific bits */
++
++/* PM_WKDEP_PER specific bits */
++#define OMAP3430_PM_WKDEP_PER_EN_IVA2 (1 << 2)
++
++/* PM_PWSTCTRL_PER specific bits */
++
++/* PM_PWSTST_PER specific bits */
++
++/* PM_PREPWSTST_PER specific bits */
++
++/* RM_RSTST_EMU specific bits */
++
++/* PM_PWSTST_EMU specific bits */
++
++/* PRM_VC_SMPS_SA */
++#define OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT 16
++#define OMAP3430_PRM_VC_SMPS_SA_SA1_MASK (0x7f << 16)
++#define OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT 0
++#define OMAP3430_PRM_VC_SMPS_SA_SA0_MASK (0x7f << 0)
++
++/* PRM_VC_SMPS_VOL_RA */
++#define OMAP3430_VOLRA1_SHIFT 16
++#define OMAP3430_VOLRA1_MASK (0xff << 16)
++#define OMAP3430_VOLRA0_SHIFT 0
++#define OMAP3430_VOLRA0_MASK (0xff << 0)
++
++/* PRM_VC_SMPS_CMD_RA */
++#define OMAP3430_CMDRA1_SHIFT 16
++#define OMAP3430_CMDRA1_MASK (0xff << 16)
++#define OMAP3430_CMDRA0_SHIFT 0
++#define OMAP3430_CMDRA0_MASK (0xff << 0)
++
++/* PRM_VC_CMD_VAL_0 specific bits */
++
++/* PRM_VC_CMD_VAL_1 specific bits */
++
++/* PRM_VC_CH_CONF */
++#define OMAP3430_CMD1 (1 << 20)
++#define OMAP3430_RACEN1 (1 << 19)
++#define OMAP3430_RAC1 (1 << 18)
++#define OMAP3430_RAV1 (1 << 17)
++#define OMAP3430_PRM_VC_CH_CONF_SA1 (1 << 16)
++#define OMAP3430_CMD0 (1 << 4)
++#define OMAP3430_RACEN0 (1 << 3)
++#define OMAP3430_RAC0 (1 << 2)
++#define OMAP3430_RAV0 (1 << 1)
++#define OMAP3430_PRM_VC_CH_CONF_SA0 (1 << 0)
++
++/* PRM_VC_I2C_CFG */
++#define OMAP3430_HSMASTER (1 << 5)
++#define OMAP3430_SREN (1 << 4)
++#define OMAP3430_HSEN (1 << 3)
++#define OMAP3430_MCODE_SHIFT 0
++#define OMAP3430_MCODE_MASK (0x7 << 0)
++
++/* PRM_VC_BYPASS_VAL */
++#define OMAP3430_VALID (1 << 24)
++#define OMAP3430_DATA_SHIFT 16
++#define OMAP3430_DATA_MASK (0xff << 16)
++#define OMAP3430_REGADDR_SHIFT 8
++#define OMAP3430_REGADDR_MASK (0xff << 8)
++#define OMAP3430_SLAVEADDR_SHIFT 0
++#define OMAP3430_SLAVEADDR_MASK (0x7f << 0)
++
++/* PRM_RSTCTRL */
++#define OMAP3430_RST_DPLL3 (1 << 2)
++#define OMAP3430_RST_GS (1 << 1)
++
++/* PRM_RSTTIME */
++#define OMAP3430_RSTTIME2_SHIFT 8
++#define OMAP3430_RSTTIME2_MASK (0x1f << 8)
++#define OMAP3430_RSTTIME1_SHIFT 0
++#define OMAP3430_RSTTIME1_MASK (0xff << 0)
++
++/* PRM_RSTST */
++#define OMAP3430_ICECRUSHER_RST (1 << 10)
++#define OMAP3430_ICEPICK_RST (1 << 9)
++#define OMAP3430_VDD2_VOLTAGE_MANAGER_RST (1 << 8)
++#define OMAP3430_VDD1_VOLTAGE_MANAGER_RST (1 << 7)
++#define OMAP3430_EXTERNAL_WARM_RST (1 << 6)
++#define OMAP3430_SECURE_WD_RST (1 << 5)
++#define OMAP3430_MPU_WD_RST (1 << 4)
++#define OMAP3430_SECURITY_VIOL_RST (1 << 3)
++#define OMAP3430_GLOBAL_SW_RST (1 << 1)
++#define OMAP3430_GLOBAL_COLD_RST (1 << 0)
++
++/* PRM_VOLTCTRL */
++#define OMAP3430_SEL_VMODE (1 << 4)
++#define OMAP3430_SEL_OFF (1 << 3)
++#define OMAP3430_AUTO_OFF (1 << 2)
++#define OMAP3430_AUTO_RET (1 << 1)
++#define OMAP3430_AUTO_SLEEP (1 << 0)
++
++/* PRM_SRAM_PCHARGE */
++#define OMAP3430_PCHARGE_TIME_SHIFT 0
++#define OMAP3430_PCHARGE_TIME_MASK (0xff << 0)
++
++/* PRM_CLKSRC_CTRL */
++#define OMAP3430_SYSCLKDIV_SHIFT 6
++#define OMAP3430_SYSCLKDIV_MASK (0x3 << 6)
++#define OMAP3430_AUTOEXTCLKMODE_SHIFT 3
++#define OMAP3430_AUTOEXTCLKMODE_MASK (0x3 << 3)
++#define OMAP3430_SYSCLKSEL_SHIFT 0
++#define OMAP3430_SYSCLKSEL_MASK (0x3 << 0)
++
++/* PRM_VOLTSETUP1 */
++#define OMAP3430_SETUP_TIME2_SHIFT 16
++#define OMAP3430_SETUP_TIME2_MASK (0xffff << 16)
++#define OMAP3430_SETUP_TIME1_SHIFT 0
++#define OMAP3430_SETUP_TIME1_MASK (0xffff << 0)
++
++/* PRM_VOLTOFFSET */
++#define OMAP3430_OFFSET_TIME_SHIFT 0
++#define OMAP3430_OFFSET_TIME_MASK (0xffff << 0)
++
++/* PRM_CLKSETUP */
++#define OMAP3430_SETUP_TIME_SHIFT 0
++#define OMAP3430_SETUP_TIME_MASK (0xffff << 0)
++
++/* PRM_POLCTRL */
++#define OMAP3430_OFFMODE_POL (1 << 3)
++#define OMAP3430_CLKOUT_POL (1 << 2)
++#define OMAP3430_CLKREQ_POL (1 << 1)
++#define OMAP3430_EXTVOL_POL (1 << 0)
++
++/* PRM_VOLTSETUP2 */
++#define OMAP3430_OFFMODESETUPTIME_SHIFT 0
++#define OMAP3430_OFFMODESETUPTIME_MASK (0xffff << 0)
++
++/* PRM_VP1_CONFIG specific bits */
++
++/* PRM_VP1_VSTEPMIN specific bits */
++
++/* PRM_VP1_VSTEPMAX specific bits */
++
++/* PRM_VP1_VLIMITTO specific bits */
++
++/* PRM_VP1_VOLTAGE specific bits */
++
++/* PRM_VP1_STATUS specific bits */
++
++/* PRM_VP2_CONFIG specific bits */
++
++/* PRM_VP2_VSTEPMIN specific bits */
++
++/* PRM_VP2_VSTEPMAX specific bits */
++
++/* PRM_VP2_VLIMITTO specific bits */
++
++/* PRM_VP2_VOLTAGE specific bits */
++
++/* PRM_VP2_STATUS specific bits */
++
++/* RM_RSTST_NEON specific bits */
++
++/* PM_WKDEP_NEON specific bits */
++
++/* PM_PWSTCTRL_NEON specific bits */
++
++/* PM_PWSTST_NEON specific bits */
++
++/* PM_PREPWSTST_NEON specific bits */
++
++#endif
+diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h
+new file mode 100644
+index 0000000..ab7649a
+--- /dev/null
++++ b/arch/arm/mach-omap2/prm.h
+@@ -0,0 +1,316 @@
++#ifndef __ARCH_ARM_MACH_OMAP2_PRM_H
++#define __ARCH_ARM_MACH_OMAP2_PRM_H
++
++/*
++ * OMAP2/3 Power/Reset Management (PRM) register definitions
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ * Copyright (C) 2007 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "prcm-common.h"
++
++#ifndef __ASSEMBLER__
++#define OMAP_PRM_REGADDR(module, reg) \
++ (void __iomem *)IO_ADDRESS(OMAP2_PRM_BASE + (module) + (reg))
++#else
++#define OMAP2420_PRM_REGADDR(module, reg) \
++ IO_ADDRESS(OMAP2420_PRM_BASE + (module) + (reg))
++#define OMAP2430_PRM_REGADDR(module, reg) \
++ IO_ADDRESS(OMAP2430_PRM_BASE + (module) + (reg))
++#define OMAP34XX_PRM_REGADDR(module, reg) \
++ IO_ADDRESS(OMAP3430_PRM_BASE + (module) + (reg))
++#endif
++
++/*
++ * Architecture-specific global PRM registers
++ * Use prm_{read,write}_reg() with these registers.
++ *
++ * With a few exceptions, these are the register names beginning with
++ * PRCM_* on 24xx, and PRM_* on 34xx. (The exceptions are the
++ * IRQSTATUS and IRQENABLE bits.)
++ *
++ */
++
++#define OMAP24XX_PRCM_REVISION OMAP_PRM_REGADDR(OCP_MOD, 0x0000)
++#define OMAP24XX_PRCM_SYSCONFIG OMAP_PRM_REGADDR(OCP_MOD, 0x0010)
++
++#define OMAP24XX_PRCM_IRQSTATUS_MPU OMAP_PRM_REGADDR(OCP_MOD, 0x0018)
++#define OMAP24XX_PRCM_IRQENABLE_MPU OMAP_PRM_REGADDR(OCP_MOD, 0x001c)
++
++#define OMAP24XX_PRCM_VOLTCTRL OMAP_PRM_REGADDR(OCP_MOD, 0x0050)
++#define OMAP24XX_PRCM_VOLTST OMAP_PRM_REGADDR(OCP_MOD, 0x0054)
++#define OMAP24XX_PRCM_CLKSRC_CTRL OMAP_PRM_REGADDR(OCP_MOD, 0x0060)
++#define OMAP24XX_PRCM_CLKOUT_CTRL OMAP_PRM_REGADDR(OCP_MOD, 0x0070)
++#define OMAP24XX_PRCM_CLKEMUL_CTRL OMAP_PRM_REGADDR(OCP_MOD, 0x0078)
++#define OMAP24XX_PRCM_CLKCFG_CTRL OMAP_PRM_REGADDR(OCP_MOD, 0x0080)
++#define OMAP24XX_PRCM_CLKCFG_STATUS OMAP_PRM_REGADDR(OCP_MOD, 0x0084)
++#define OMAP24XX_PRCM_VOLTSETUP OMAP_PRM_REGADDR(OCP_MOD, 0x0090)
++#define OMAP24XX_PRCM_CLKSSETUP OMAP_PRM_REGADDR(OCP_MOD, 0x0094)
++#define OMAP24XX_PRCM_POLCTRL OMAP_PRM_REGADDR(OCP_MOD, 0x0098)
++
++#define OMAP3430_PRM_REVISION OMAP_PRM_REGADDR(OCP_MOD, 0x0004)
++#define OMAP3430_PRM_SYSCONFIG OMAP_PRM_REGADDR(OCP_MOD, 0x0014)
++
++#define OMAP3430_PRM_IRQSTATUS_MPU OMAP_PRM_REGADDR(OCP_MOD, 0x0018)
++#define OMAP3430_PRM_IRQENABLE_MPU OMAP_PRM_REGADDR(OCP_MOD, 0x001c)
++
++
++#define OMAP3430_PRM_VC_SMPS_SA OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0020)
++#define OMAP3430_PRM_VC_SMPS_VOL_RA OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0024)
++#define OMAP3430_PRM_VC_SMPS_CMD_RA OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0028)
++#define OMAP3430_PRM_VC_CMD_VAL_0 OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x002c)
++#define OMAP3430_PRM_VC_CMD_VAL_1 OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0030)
++#define OMAP3430_PRM_VC_CH_CONF OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0034)
++#define OMAP3430_PRM_VC_I2C_CFG OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0038)
++#define OMAP3430_PRM_VC_BYPASS_VAL OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x003c)
++#define OMAP3430_PRM_RSTCTRL OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0050)
++#define OMAP3430_PRM_RSTTIME OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0054)
++#define OMAP3430_PRM_RSTST OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0058)
++#define OMAP3430_PRM_VOLTCTRL OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0060)
++#define OMAP3430_PRM_SRAM_PCHARGE OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0064)
++#define OMAP3430_PRM_CLKSRC_CTRL OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0070)
++#define OMAP3430_PRM_VOLTSETUP1 OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0090)
++#define OMAP3430_PRM_VOLTOFFSET OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0094)
++#define OMAP3430_PRM_CLKSETUP OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0098)
++#define OMAP3430_PRM_POLCTRL OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x009c)
++#define OMAP3430_PRM_VOLTSETUP2 OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00a0)
++#define OMAP3430_PRM_VP1_CONFIG OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b0)
++#define OMAP3430_PRM_VP1_VSTEPMIN OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b4)
++#define OMAP3430_PRM_VP1_VSTEPMAX OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b8)
++#define OMAP3430_PRM_VP1_VLIMITTO OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00bc)
++#define OMAP3430_PRM_VP1_VOLTAGE OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c0)
++#define OMAP3430_PRM_VP1_STATUS OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c4)
++#define OMAP3430_PRM_VP2_CONFIG OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d0)
++#define OMAP3430_PRM_VP2_VSTEPMIN OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d4)
++#define OMAP3430_PRM_VP2_VSTEPMAX OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d8)
++#define OMAP3430_PRM_VP2_VLIMITTO OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00dc)
++#define OMAP3430_PRM_VP2_VOLTAGE OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e0)
++#define OMAP3430_PRM_VP2_STATUS OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e4)
++
++#define OMAP3430_PRM_CLKSEL OMAP_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0040)
++#define OMAP3430_PRM_CLKOUT_CTRL OMAP_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0070)
++
++/*
++ * Module specific PRM registers from PRM_BASE + domain offset
++ *
++ * Use prm_{read,write}_mod_reg() with these registers.
++ *
++ * With a few exceptions, these are the register names beginning with
++ * {PM,RM}_* on both architectures. (The exceptions are the IRQSTATUS
++ * and IRQENABLE bits.)
++ *
++ */
++
++/* Registers appearing on both 24xx and 34xx */
++
++#define RM_RSTCTRL 0x0050
++#define RM_RSTTIME 0x0054
++#define RM_RSTST 0x0058
++
++#define PM_WKEN 0x00a0
++#define PM_WKEN1 PM_WKEN
++#define PM_WKST 0x00b0
++#define PM_WKST1 PM_WKST
++#define PM_WKDEP 0x00c8
++#define PM_EVGENCTRL 0x00d4
++#define PM_EVGENONTIM 0x00d8
++#define PM_EVGENOFFTIM 0x00dc
++#define PM_PWSTCTRL 0x00e0
++#define PM_PWSTST 0x00e4
++
++#define OMAP3430_PM_MPUGRPSEL 0x00a4
++#define OMAP3430_PM_MPUGRPSEL1 OMAP3430_PM_MPUGRPSEL
++
++#define OMAP3430_PM_IVAGRPSEL 0x00a8
++#define OMAP3430_PM_IVAGRPSEL1 OMAP3430_PM_IVAGRPSEL
++
++#define OMAP3430_PM_PREPWSTST 0x00e8
++
++#define OMAP3430_PRM_IRQSTATUS_IVA2 0x00f8
++#define OMAP3430_PRM_IRQENABLE_IVA2 0x00fc
++
++
++/* Architecture-specific registers */
++
++#define OMAP24XX_PM_WKEN2 0x00a4
++#define OMAP24XX_PM_WKST2 0x00b4
++
++#define OMAP24XX_PRCM_IRQSTATUS_DSP 0x00f0 /* IVA mod */
++#define OMAP24XX_PRCM_IRQENABLE_DSP 0x00f4 /* IVA mod */
++#define OMAP24XX_PRCM_IRQSTATUS_IVA 0x00f8
++#define OMAP24XX_PRCM_IRQENABLE_IVA 0x00fc
++
++#ifndef __ASSEMBLER__
++
++/* Power/reset management domain register get/set */
++
++static inline void prm_write_mod_reg(u32 val, s16 module, s16 idx)
++{
++ __raw_writel(val, OMAP_PRM_REGADDR(module, idx));
++}
++
++static inline u32 prm_read_mod_reg(s16 module, s16 idx)
++{
++ return __raw_readl(OMAP_PRM_REGADDR(module, idx));
++}
++
++#endif
++
++/*
++ * Bits common to specific registers
++ *
++ * The 3430 register and bit names are generally used,
++ * since they tend to make more sense
++ */
++
++/* PM_EVGENONTIM_MPU */
++/* Named PM_EVEGENONTIM_MPU on the 24XX */
++#define OMAP_ONTIMEVAL_SHIFT 0
++#define OMAP_ONTIMEVAL_MASK (0xffffffff << 0)
++
++/* PM_EVGENOFFTIM_MPU */
++/* Named PM_EVEGENOFFTIM_MPU on the 24XX */
++#define OMAP_OFFTIMEVAL_SHIFT 0
++#define OMAP_OFFTIMEVAL_MASK (0xffffffff << 0)
++
++/* PRM_CLKSETUP and PRCM_VOLTSETUP */
++/* Named PRCM_CLKSSETUP on the 24XX */
++#define OMAP_SETUP_TIME_SHIFT 0
++#define OMAP_SETUP_TIME_MASK (0xffff << 0)
++
++/* PRM_CLKSRC_CTRL */
++/* Named PRCM_CLKSRC_CTRL on the 24XX */
++#define OMAP_SYSCLKDIV_SHIFT 6
++#define OMAP_SYSCLKDIV_MASK (0x3 << 6)
++#define OMAP_AUTOEXTCLKMODE_SHIFT 3
++#define OMAP_AUTOEXTCLKMODE_MASK (0x3 << 3)
++#define OMAP_SYSCLKSEL_SHIFT 0
++#define OMAP_SYSCLKSEL_MASK (0x3 << 0)
++
++/* PM_EVGENCTRL_MPU */
++#define OMAP_OFFLOADMODE_SHIFT 3
++#define OMAP_OFFLOADMODE_MASK (0x3 << 3)
++#define OMAP_ONLOADMODE_SHIFT 1
++#define OMAP_ONLOADMODE_MASK (0x3 << 1)
++#define OMAP_ENABLE (1 << 0)
++
++/* PRM_RSTTIME */
++/* Named RM_RSTTIME_WKUP on the 24xx */
++#define OMAP_RSTTIME2_SHIFT 8
++#define OMAP_RSTTIME2_MASK (0x1f << 8)
++#define OMAP_RSTTIME1_SHIFT 0
++#define OMAP_RSTTIME1_MASK (0xff << 0)
++
++
++/* PRM_RSTCTRL */
++/* Named RM_RSTCTRL_WKUP on the 24xx */
++/* 2420 calls RST_DPLL3 'RST_DPLL' */
++#define OMAP_RST_DPLL3 (1 << 2)
++#define OMAP_RST_GS (1 << 1)
++
++
++/*
++ * Bits common to module-shared registers
++ *
++ * Not all registers of a particular type support all of these bits -
++ * check TRM if you are unsure
++ */
++
++/*
++ * 24XX: PM_PWSTST_CORE, PM_PWSTST_GFX, PM_PWSTST_MPU, PM_PWSTST_DSP
++ *
++ * 2430: PM_PWSTST_MDM
++ *
++ * 3430: PM_PWSTST_IVA2, PM_PWSTST_MPU, PM_PWSTST_CORE, PM_PWSTST_GFX,
++ * PM_PWSTST_DSS, PM_PWSTST_CAM, PM_PWSTST_PER, PM_PWSTST_EMU,
++ * PM_PWSTST_NEON
++ */
++#define OMAP_INTRANSITION (1 << 20)
++
++
++/*
++ * 24XX: PM_PWSTST_GFX, PM_PWSTST_DSP
++ *
++ * 2430: PM_PWSTST_MDM
++ *
++ * 3430: PM_PWSTST_IVA2, PM_PWSTST_MPU, PM_PWSTST_CORE, PM_PWSTST_GFX,
++ * PM_PWSTST_DSS, PM_PWSTST_CAM, PM_PWSTST_PER, PM_PWSTST_EMU,
++ * PM_PWSTST_NEON
++ */
++#define OMAP_POWERSTATEST_SHIFT 0
++#define OMAP_POWERSTATEST_MASK (0x3 << 0)
++
++/*
++ * 24XX: RM_RSTST_MPU and RM_RSTST_DSP - on 24XX, 'COREDOMAINWKUP_RST' is
++ * called 'COREWKUP_RST'
++ *
++ * 3430: RM_RSTST_IVA2, RM_RSTST_MPU, RM_RSTST_GFX, RM_RSTST_DSS,
++ * RM_RSTST_CAM, RM_RSTST_PER, RM_RSTST_NEON
++ */
++#define OMAP_COREDOMAINWKUP_RST (1 << 3)
++
++/*
++ * 24XX: RM_RSTST_MPU, RM_RSTST_GFX, RM_RSTST_DSP
++ *
++ * 2430: RM_RSTST_MDM
++ *
++ * 3430: RM_RSTST_CORE, RM_RSTST_EMU
++ */
++#define OMAP_DOMAINWKUP_RST (1 << 2)
++
++/*
++ * 24XX: RM_RSTST_MPU, RM_RSTST_WKUP, RM_RSTST_DSP
++ * On 24XX, 'GLOBALWARM_RST' is called 'GLOBALWMPU_RST'.
++ *
++ * 2430: RM_RSTST_MDM
++ *
++ * 3430: RM_RSTST_CORE, RM_RSTST_EMU
++ */
++#define OMAP_GLOBALWARM_RST (1 << 1)
++#define OMAP_GLOBALCOLD_RST (1 << 0)
++
++/*
++ * 24XX: PM_WKDEP_GFX, PM_WKDEP_MPU, PM_WKDEP_CORE, PM_WKDEP_DSP
++ * 2420 TRM sometimes uses "EN_WAKEUP" instead of "EN_WKUP"
++ *
++ * 2430: PM_WKDEP_MDM
++ *
++ * 3430: PM_WKDEP_IVA2, PM_WKDEP_GFX, PM_WKDEP_DSS, PM_WKDEP_CAM,
++ * PM_WKDEP_PER
++ */
++#define OMAP_EN_WKUP (1 << 4)
++
++/*
++ * 24XX: PM_PWSTCTRL_MPU, PM_PWSTCTRL_CORE, PM_PWSTCTRL_GFX,
++ * PM_PWSTCTRL_DSP
++ *
++ * 2430: PM_PWSTCTRL_MDM
++ *
++ * 3430: PM_PWSTCTRL_IVA2, PM_PWSTCTRL_CORE, PM_PWSTCTRL_GFX,
++ * PM_PWSTCTRL_DSS, PM_PWSTCTRL_CAM, PM_PWSTCTRL_PER,
++ * PM_PWSTCTRL_NEON
++ */
++#define OMAP_LOGICRETSTATE (1 << 2)
++
++/*
++ * 24XX: PM_PWSTCTRL_MPU, PM_PWSTCTRL_CORE, PM_PWSTCTRL_GFX,
++ * PM_PWSTCTRL_DSP, PM_PWSTST_MPU
++ *
++ * 2430: PM_PWSTCTRL_MDM shared bits
++ *
++ * 3430: PM_PWSTCTRL_IVA2, PM_PWSTCTRL_MPU, PM_PWSTCTRL_CORE,
++ * PM_PWSTCTRL_GFX, PM_PWSTCTRL_DSS, PM_PWSTCTRL_CAM, PM_PWSTCTRL_PER,
++ * PM_PWSTCTRL_NEON shared bits
++ */
++#define OMAP_POWERSTATE_SHIFT 0
++#define OMAP_POWERSTATE_MASK (0x3 << 0)
++
++
++#endif
+diff --git a/arch/arm/mach-omap2/sdrc.h b/arch/arm/mach-omap2/sdrc.h
+new file mode 100644
+index 0000000..d7f23bc
+--- /dev/null
++++ b/arch/arm/mach-omap2/sdrc.h
+@@ -0,0 +1,58 @@
++#ifndef __ARCH_ARM_MACH_OMAP2_SDRC_H
++#define __ARCH_ARM_MACH_OMAP2_SDRC_H
++
++/*
++ * OMAP2 SDRC register definitions
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ * Copyright (C) 2007 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#undef DEBUG
++
++#include <asm/arch/sdrc.h>
++
++#ifndef __ASSEMBLER__
++extern unsigned long omap2_sdrc_base;
++extern unsigned long omap2_sms_base;
++
++#define OMAP_SDRC_REGADDR(reg) \
++ (void __iomem *)IO_ADDRESS(omap2_sdrc_base + (reg))
++#define OMAP_SMS_REGADDR(reg) \
++ (void __iomem *)IO_ADDRESS(omap2_sms_base + (reg))
++
++/* SDRC global register get/set */
++
++static inline void sdrc_write_reg(u32 val, u16 reg)
++{
++ __raw_writel(val, OMAP_SDRC_REGADDR(reg));
++}
++
++static inline u32 sdrc_read_reg(u16 reg)
++{
++ return __raw_readl(OMAP_SDRC_REGADDR(reg));
++}
++
++/* SMS global register get/set */
++
++static inline void sms_write_reg(u32 val, u16 reg)
++{
++ __raw_writel(val, OMAP_SMS_REGADDR(reg));
++}
++
++static inline u32 sms_read_reg(u16 reg)
++{
++ return __raw_readl(OMAP_SMS_REGADDR(reg));
++}
++#else
++#define OMAP242X_SDRC_REGADDR(reg) IO_ADDRESS(OMAP2420_SDRC_BASE + (reg))
++#define OMAP243X_SDRC_REGADDR(reg) IO_ADDRESS(OMAP243X_SDRC_BASE + (reg))
++#define OMAP34XX_SDRC_REGADDR(reg) IO_ADDRESS(OMAP343X_SDRC_BASE + (reg))
++#endif /* __ASSEMBLER__ */
++
++#endif
+diff --git a/arch/arm/mach-omap2/sleep.S b/arch/arm/mach-omap2/sleep.S
+index 16247d5..46ccb9b 100644
+--- a/arch/arm/mach-omap2/sleep.S
++++ b/arch/arm/mach-omap2/sleep.S
+@@ -26,19 +26,10 @@
+ #include <asm/arch/io.h>
+ #include <asm/arch/pm.h>
+
+-#define A_32KSYNC_CR_V IO_ADDRESS(OMAP_TIMER32K_BASE+0x10)
+-#define A_PRCM_VOLTCTRL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x50)
+-#define A_PRCM_CLKCFG_CTRL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x80)
+-#define A_CM_CLKEN_PLL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x500)
+-#define A_CM_IDLEST_CKGEN_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x520)
+-#define A_CM_CLKSEL1_PLL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x540)
+-#define A_CM_CLKSEL2_PLL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x544)
++#include "sdrc.h"
+
+-#define A_SDRC_DLLA_CTRL_V IO_ADDRESS(OMAP24XX_SDRC_BASE+0x60)
+-#define A_SDRC_POWER_V IO_ADDRESS(OMAP24XX_SDRC_BASE+0x70)
+-#define A_SDRC_RFR_CTRL_V IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA4)
++/* First address of reserved address space? apparently valid for OMAP2 & 3 */
+ #define A_SDRC0_V (0xC0000000)
+-#define A_SDRC_MANUAL_V IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA8)
+
+ .text
+
+@@ -126,17 +117,11 @@ loop2:
+ ldmfd sp!, {r0 - r12, pc} @ restore regs and return
+
+ A_SDRC_POWER:
+- .word A_SDRC_POWER_V
++ .word OMAP242X_SDRC_REGADDR(SDRC_POWER)
+ A_SDRC0:
+ .word A_SDRC0_V
+-A_CM_CLKSEL2_PLL_S:
+- .word A_CM_CLKSEL2_PLL_V
+-A_CM_CLKEN_PLL:
+- .word A_CM_CLKEN_PLL_V
+ A_SDRC_DLLA_CTRL_S:
+- .word A_SDRC_DLLA_CTRL_V
+-A_SDRC_MANUAL_S:
+- .word A_SDRC_MANUAL_V
++ .word OMAP242X_SDRC_REGADDR(SDRC_DLLA_CTRL)
+
+ ENTRY(omap24xx_cpu_suspend_sz)
+ .word . - omap24xx_cpu_suspend
+diff --git a/arch/arm/mach-omap2/sram-fn.S b/arch/arm/mach-omap2/sram-fn.S
+index b275766..4a9e491 100644
+--- a/arch/arm/mach-omap2/sram-fn.S
++++ b/arch/arm/mach-omap2/sram-fn.S
+@@ -27,19 +27,11 @@
+ #include <asm/arch/io.h>
+ #include <asm/hardware.h>
+
+-#include "prcm-regs.h"
++#include "sdrc.h"
++#include "prm.h"
++#include "cm.h"
+
+-#define TIMER_32KSYNCT_CR_V IO_ADDRESS(OMAP24XX_32KSYNCT_BASE + 0x010)
+-
+-#define CM_CLKSEL2_PLL_V IO_ADDRESS(OMAP24XX_PRCM_BASE + 0x544)
+-#define PRCM_VOLTCTRL_V IO_ADDRESS(OMAP24XX_PRCM_BASE + 0x050)
+-#define PRCM_CLKCFG_CTRL_V IO_ADDRESS(OMAP24XX_PRCM_BASE + 0x080)
+-#define CM_CLKEN_PLL_V IO_ADDRESS(OMAP24XX_PRCM_BASE + 0x500)
+-#define CM_IDLEST_CKGEN_V IO_ADDRESS(OMAP24XX_PRCM_BASE + 0x520)
+-#define CM_CLKSEL1_PLL_V IO_ADDRESS(OMAP24XX_PRCM_BASE + 0x540)
+-
+-#define SDRC_DLLA_CTRL_V IO_ADDRESS(OMAP24XX_SDRC_BASE + 0x060)
+-#define SDRC_RFR_CTRL_V IO_ADDRESS(OMAP24XX_SDRC_BASE + 0x0a4)
++#define TIMER_32KSYNCT_CR_V IO_ADDRESS(OMAP2420_32KSYNCT_BASE + 0x010)
+
+ .text
+
+@@ -131,11 +123,11 @@ volt_delay:
+
+ /* relative load constants */
+ cm_clksel2_pll:
+- .word CM_CLKSEL2_PLL_V
++ .word OMAP2420_CM_REGADDR(PLL_MOD, CM_CLKSEL2)
+ sdrc_dlla_ctrl:
+- .word SDRC_DLLA_CTRL_V
++ .word OMAP242X_SDRC_REGADDR(SDRC_DLLA_CTRL)
+ prcm_voltctrl:
+- .word PRCM_VOLTCTRL_V
++ .word OMAP2420_PRM_REGADDR(OCP_MOD, 0x50)
+ prcm_mask_val:
+ .word 0xFFFF3FFC
+ timer_32ksynct_cr:
+@@ -225,13 +217,13 @@ volt_delay_c:
+ mov pc, lr @ back to caller
+
+ ddr_cm_clksel2_pll:
+- .word CM_CLKSEL2_PLL_V
++ .word OMAP2420_CM_REGADDR(PLL_MOD, CM_CLKSEL2)
+ ddr_sdrc_dlla_ctrl:
+- .word SDRC_DLLA_CTRL_V
++ .word OMAP242X_SDRC_REGADDR(SDRC_DLLA_CTRL)
+ ddr_sdrc_rfr_ctrl:
+- .word SDRC_RFR_CTRL_V
++ .word OMAP242X_SDRC_REGADDR(SDRC_RFR_CTRL_0)
+ ddr_prcm_voltctrl:
+- .word PRCM_VOLTCTRL_V
++ .word OMAP2420_PRM_REGADDR(OCP_MOD, 0x50)
+ ddr_prcm_mask_val:
+ .word 0xFFFF3FFC
+ ddr_timer_32ksynct:
+@@ -316,17 +308,17 @@ wait_dll_lock:
+ ldmfd sp!, {r0-r12, pc} @ restore regs and return
+
+ set_config:
+- .word PRCM_CLKCFG_CTRL_V
++ .word OMAP2420_PRM_REGADDR(OCP_MOD, 0x80)
+ pll_ctl:
+- .word CM_CLKEN_PLL_V
++ .word OMAP2420_CM_REGADDR(PLL_MOD, CM_FCLKEN1)
+ pll_stat:
+- .word CM_IDLEST_CKGEN_V
++ .word OMAP2420_CM_REGADDR(PLL_MOD, CM_IDLEST1)
+ pll_div:
+- .word CM_CLKSEL1_PLL_V
++ .word OMAP2420_CM_REGADDR(PLL_MOD, CM_CLKSEL)
+ sdrc_rfr:
+- .word SDRC_RFR_CTRL_V
++ .word OMAP242X_SDRC_REGADDR(SDRC_RFR_CTRL_0)
+ dlla_ctrl:
+- .word SDRC_DLLA_CTRL_V
++ .word OMAP242X_SDRC_REGADDR(SDRC_DLLA_CTRL)
+
+ ENTRY(sram_set_prcm_sz)
+ .word . - sram_set_prcm
+diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
+index 3234dee..78d05f2 100644
+--- a/arch/arm/mach-omap2/timer-gp.c
++++ b/arch/arm/mach-omap2/timer-gp.c
+@@ -3,6 +3,11 @@
+ *
+ * OMAP2 GP timer support.
+ *
++ * Update to use new clocksource/clockevent layers
++ * Author: Kevin Hilman, MontaVista Software, Inc. <source at mvista.com>
++ * Copyright (C) 2007 MontaVista Software, Inc.
++ *
++ * Original driver:
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Paul Mundt <paul.mundt at nokia.com>
+ * Juha Yrjölä <juha.yrjola at nokia.com>
+@@ -25,24 +30,23 @@
+ #include <linux/clk.h>
+ #include <linux/delay.h>
+ #include <linux/irq.h>
++#include <linux/clocksource.h>
++#include <linux/clockchips.h>
+
+ #include <asm/mach/time.h>
+ #include <asm/arch/dmtimer.h>
+
+ static struct omap_dm_timer *gptimer;
+-
+-static inline void omap2_gp_timer_start(unsigned long load_val)
+-{
+- omap_dm_timer_set_load(gptimer, 1, 0xffffffff - load_val);
+- omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW);
+- omap_dm_timer_start(gptimer);
+-}
++static struct clock_event_device clockevent_gpt;
+
+ static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
+ {
+- omap_dm_timer_write_status(gptimer, OMAP_TIMER_INT_OVERFLOW);
+- timer_tick();
++ struct omap_dm_timer *gpt = (struct omap_dm_timer *)dev_id;
++ struct clock_event_device *evt = &clockevent_gpt;
++
++ omap_dm_timer_write_status(gpt, OMAP_TIMER_INT_OVERFLOW);
+
++ evt->event_handler(evt);
+ return IRQ_HANDLED;
+ }
+
+@@ -52,20 +56,138 @@ static struct irqaction omap2_gp_timer_irq = {
+ .handler = omap2_gp_timer_interrupt,
+ };
+
+-static void __init omap2_gp_timer_init(void)
++static int omap2_gp_timer_set_next_event(unsigned long cycles,
++ struct clock_event_device *evt)
+ {
+- u32 tick_period;
++ omap_dm_timer_set_load(gptimer, 0, 0xffffffff - cycles);
++ omap_dm_timer_start(gptimer);
++
++ return 0;
++}
++
++static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
++ struct clock_event_device *evt)
++{
++ u32 period;
++
++ omap_dm_timer_stop(gptimer);
++
++ switch (mode) {
++ case CLOCK_EVT_MODE_PERIODIC:
++ period = clk_get_rate(omap_dm_timer_get_fclk(gptimer)) / HZ;
++ period -= 1;
++
++ omap_dm_timer_set_load(gptimer, 1, 0xffffffff - period);
++ omap_dm_timer_start(gptimer);
++ break;
++ case CLOCK_EVT_MODE_ONESHOT:
++ break;
++ case CLOCK_EVT_MODE_UNUSED:
++ case CLOCK_EVT_MODE_SHUTDOWN:
++ case CLOCK_EVT_MODE_RESUME:
++ break;
++ }
++}
++
++static struct clock_event_device clockevent_gpt = {
++ .name = "gp timer",
++ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
++ .shift = 32,
++ .set_next_event = omap2_gp_timer_set_next_event,
++ .set_mode = omap2_gp_timer_set_mode,
++};
++
++static void __init omap2_gp_clockevent_init(void)
++{
++ u32 tick_rate;
+
+- omap_dm_timer_init();
+ gptimer = omap_dm_timer_request_specific(1);
+ BUG_ON(gptimer == NULL);
+
++#if defined(CONFIG_OMAP_32K_TIMER)
++ omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_32_KHZ);
++#else
+ omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_SYS_CLK);
+- tick_period = clk_get_rate(omap_dm_timer_get_fclk(gptimer)) / HZ;
+- tick_period -= 1;
++#endif
++ tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer));
+
++ omap2_gp_timer_irq.dev_id = (void *)gptimer;
+ setup_irq(omap_dm_timer_get_irq(gptimer), &omap2_gp_timer_irq);
+- omap2_gp_timer_start(tick_period);
++ omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW);
++
++ clockevent_gpt.mult = div_sc(tick_rate, NSEC_PER_SEC,
++ clockevent_gpt.shift);
++ clockevent_gpt.max_delta_ns =
++ clockevent_delta2ns(0xffffffff, &clockevent_gpt);
++ clockevent_gpt.min_delta_ns =
++ clockevent_delta2ns(1, &clockevent_gpt);
++
++ clockevent_gpt.cpumask = cpumask_of_cpu(0);
++ clockevents_register_device(&clockevent_gpt);
++}
++
++#ifdef CONFIG_OMAP_32K_TIMER
++/*
++ * When 32k-timer is enabled, don't use GPTimer for clocksource
++ * instead, just leave default clocksource which uses the 32k
++ * sync counter. See clocksource setup in see plat-omap/common.c.
++ */
++
++static inline void __init omap2_gp_clocksource_init(void) {}
++#else
++/*
++ * clocksource
++ */
++static struct omap_dm_timer *gpt_clocksource;
++static cycle_t clocksource_read_cycles(void)
++{
++ return (cycle_t)omap_dm_timer_read_counter(gpt_clocksource);
++}
++
++static struct clocksource clocksource_gpt = {
++ .name = "gp timer",
++ .rating = 300,
++ .read = clocksource_read_cycles,
++ .mask = CLOCKSOURCE_MASK(32),
++ .shift = 24,
++ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
++};
++
++/* Setup free-running counter for clocksource */
++static void __init omap2_gp_clocksource_init(void)
++{
++ static struct omap_dm_timer *gpt;
++ u32 tick_rate, tick_period;
++ static char err1[] __initdata = KERN_ERR
++ "%s: failed to request dm-timer\n";
++ static char err2[] __initdata = KERN_ERR
++ "%s: can't register clocksource!\n";
++
++ gpt = omap_dm_timer_request();
++ if (!gpt)
++ printk(err1, clocksource_gpt.name);
++ gpt_clocksource = gpt;
++
++ omap_dm_timer_set_source(gpt, OMAP_TIMER_SRC_SYS_CLK);
++ tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gpt));
++ tick_period = (tick_rate / HZ) - 1;
++
++ omap_dm_timer_set_load(gpt, 1, 0);
++ omap_dm_timer_start(gpt);
++
++ clocksource_gpt.mult =
++ clocksource_khz2mult(tick_rate/1000, clocksource_gpt.shift);
++ if (clocksource_register(&clocksource_gpt))
++ printk(err2, clocksource_gpt.name);
++}
++#endif
++
++static void __init omap2_gp_timer_init(void)
++{
++ omap_dm_timer_init();
++
++ omap2_gp_clockevent_init();
++ omap2_gp_clocksource_init();
+ }
+
+ struct sys_timer omap_timer = {
+diff --git a/arch/arm/mach-orion/Kconfig b/arch/arm/mach-orion/Kconfig
+deleted file mode 100644
+index 1dcbb6a..0000000
+--- a/arch/arm/mach-orion/Kconfig
++++ /dev/null
+@@ -1,41 +0,0 @@
+-if ARCH_ORION
+-
+-menu "Orion Implementations"
+-
+-config MACH_DB88F5281
+- bool "Marvell Orion-2 Development Board"
+- select I2C_BOARDINFO
+- help
+- Say 'Y' here if you want your kernel to support the
+- Marvell Orion-2 (88F5281) Development Board
+-
+-config MACH_RD88F5182
+- bool "Marvell Orion-NAS Reference Design"
+- select I2C_BOARDINFO
+- help
+- Say 'Y' here if you want your kernel to support the
+- Marvell Orion-NAS (88F5182) RD2
+-
+-config MACH_KUROBOX_PRO
+- bool "KuroBox Pro"
+- select I2C_BOARDINFO
+- help
+- Say 'Y' here if you want your kernel to support the
+- KuroBox Pro platform.
+-
+-config MACH_DNS323
+- bool "D-Link DNS-323"
+- select I2C_BOARDINFO
+- help
+- Say 'Y' here if you want your kernel to support the
+- D-Link DNS-323 platform.
+-
+-config MACH_TS209
+- bool "QNAP TS-109/TS-209"
+- help
+- Say 'Y' here if you want your kernel to support the
+- QNAP TS-109/TS-209 platform.
+-
+-endmenu
+-
+-endif
+diff --git a/arch/arm/mach-orion/Makefile b/arch/arm/mach-orion/Makefile
+deleted file mode 100644
+index f91d937..0000000
+--- a/arch/arm/mach-orion/Makefile
++++ /dev/null
+@@ -1,6 +0,0 @@
+-obj-y += common.o addr-map.o pci.o gpio.o irq.o time.o
+-obj-$(CONFIG_MACH_DB88F5281) += db88f5281-setup.o
+-obj-$(CONFIG_MACH_RD88F5182) += rd88f5182-setup.o
+-obj-$(CONFIG_MACH_KUROBOX_PRO) += kurobox_pro-setup.o
+-obj-$(CONFIG_MACH_DNS323) += dns323-setup.o
+-obj-$(CONFIG_MACH_TS209) += ts209-setup.o
+diff --git a/arch/arm/mach-orion/Makefile.boot b/arch/arm/mach-orion/Makefile.boot
+deleted file mode 100644
+index 67039c3..0000000
+--- a/arch/arm/mach-orion/Makefile.boot
++++ /dev/null
+@@ -1,3 +0,0 @@
+- zreladdr-y := 0x00008000
+-params_phys-y := 0x00000100
+-initrd_phys-y := 0x00800000
+diff --git a/arch/arm/mach-orion/addr-map.c b/arch/arm/mach-orion/addr-map.c
+deleted file mode 100644
+index 58cc3c0..0000000
+--- a/arch/arm/mach-orion/addr-map.c
++++ /dev/null
+@@ -1,490 +0,0 @@
+-/*
+- * arch/arm/mach-orion/addr-map.c
+- *
+- * Address map functions for Marvell Orion System On Chip
+- *
+- * Maintainer: Tzachi Perelstein <tzachi at marvell.com>
+- *
+- * This file is licensed under the terms of the GNU General Public
+- * License version 2. This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <asm/hardware.h>
+-#include "common.h"
+-
+-/*
+- * The Orion has fully programable address map. There's a separate address
+- * map for each of the device _master_ interfaces, e.g. CPU, PCI, PCIE, USB,
+- * Gigabit Ethernet, DMA/XOR engines, etc. Each interface has its own
+- * address decode windows that allow it to access any of the Orion resources.
+- *
+- * CPU address decoding --
+- * Linux assumes that it is the boot loader that already setup the access to
+- * DDR and internal registers.
+- * Setup access to PCI and PCI-E IO/MEM space is issued by core.c.
+- * Setup access to various devices located on the device bus interface (e.g.
+- * flashes, RTC, etc) should be issued by machine-setup.c according to
+- * specific board population (by using orion_setup_cpu_win()).
+- *
+- * Non-CPU Masters address decoding --
+- * Unlike the CPU, we setup the access from Orion's master interfaces to DDR
+- * banks only (the typical use case).
+- * Setup access for each master to DDR is issued by common.c.
+- *
+- * Note: although orion_setbits() and orion_clrbits() are not atomic
+- * no locking is necessary here since code in this file is only called
+- * at boot time when there is no concurrency issues.
+- */
+-
+-/*
+- * Generic Address Decode Windows bit settings
+- */
+-#define TARGET_DDR 0
+-#define TARGET_PCI 3
+-#define TARGET_PCIE 4
+-#define TARGET_DEV_BUS 1
+-#define ATTR_DDR_CS(n) (((n) ==0) ? 0xe : \
+- ((n) == 1) ? 0xd : \
+- ((n) == 2) ? 0xb : \
+- ((n) == 3) ? 0x7 : 0xf)
+-#define ATTR_PCIE_MEM 0x59
+-#define ATTR_PCIE_IO 0x51
+-#define ATTR_PCI_MEM 0x59
+-#define ATTR_PCI_IO 0x51
+-#define ATTR_DEV_CS0 0x1e
+-#define ATTR_DEV_CS1 0x1d
+-#define ATTR_DEV_CS2 0x1b
+-#define ATTR_DEV_BOOT 0xf
+-#define WIN_EN 1
+-
+-/*
+- * Helpers to get DDR banks info
+- */
+-#define DDR_BASE_CS(n) ORION_DDR_REG(0x1500 + ((n) * 8))
+-#define DDR_SIZE_CS(n) ORION_DDR_REG(0x1504 + ((n) * 8))
+-#define DDR_MAX_CS 4
+-#define DDR_REG_TO_SIZE(reg) (((reg) | 0xffffff) + 1)
+-#define DDR_REG_TO_BASE(reg) ((reg) & 0xff000000)
+-#define DDR_BANK_EN 1
+-
+-/*
+- * CPU Address Decode Windows registers
+- */
+-#define CPU_WIN_CTRL(n) ORION_BRIDGE_REG(0x000 | ((n) << 4))
+-#define CPU_WIN_BASE(n) ORION_BRIDGE_REG(0x004 | ((n) << 4))
+-#define CPU_WIN_REMAP_LO(n) ORION_BRIDGE_REG(0x008 | ((n) << 4))
+-#define CPU_WIN_REMAP_HI(n) ORION_BRIDGE_REG(0x00c | ((n) << 4))
+-#define CPU_MAX_WIN 8
+-
+-/*
+- * Use this CPU address decode windows allocation
+- */
+-#define CPU_WIN_PCIE_IO 0
+-#define CPU_WIN_PCI_IO 1
+-#define CPU_WIN_PCIE_MEM 2
+-#define CPU_WIN_PCI_MEM 3
+-#define CPU_WIN_DEV_BOOT 4
+-#define CPU_WIN_DEV_CS0 5
+-#define CPU_WIN_DEV_CS1 6
+-#define CPU_WIN_DEV_CS2 7
+-
+-/*
+- * PCIE Address Decode Windows registers
+- */
+-#define PCIE_BAR_CTRL(n) ORION_PCIE_REG(0x1804 + ((n - 1) * 4))
+-#define PCIE_BAR_LO(n) ORION_PCIE_REG(0x0010 + ((n) * 8))
+-#define PCIE_BAR_HI(n) ORION_PCIE_REG(0x0014 + ((n) * 8))
+-#define PCIE_WIN_CTRL(n) (((n) < 5) ? \
+- ORION_PCIE_REG(0x1820 + ((n) << 4)) : \
+- ORION_PCIE_REG(0x1880))
+-#define PCIE_WIN_BASE(n) (((n) < 5) ? \
+- ORION_PCIE_REG(0x1824 + ((n) << 4)) : \
+- ORION_PCIE_REG(0x1884))
+-#define PCIE_WIN_REMAP(n) (((n) < 5) ? \
+- ORION_PCIE_REG(0x182c + ((n) << 4)) : \
+- ORION_PCIE_REG(0x188c))
+-#define PCIE_DEFWIN_CTRL ORION_PCIE_REG(0x18b0)
+-#define PCIE_EXPROM_WIN_CTRL ORION_PCIE_REG(0x18c0)
+-#define PCIE_EXPROM_WIN_REMP ORION_PCIE_REG(0x18c4)
+-#define PCIE_MAX_BARS 3
+-#define PCIE_MAX_WINS 6
+-
+-/*
+- * Use PCIE BAR '1' for all DDR banks
+- */
+-#define PCIE_DRAM_BAR 1
+-
+-/*
+- * PCI Address Decode Windows registers
+- */
+-#define PCI_BAR_SIZE_DDR_CS(n) (((n) == 0) ? ORION_PCI_REG(0xc08) : \
+- ((n) == 1) ? ORION_PCI_REG(0xd08) : \
+- ((n) == 2) ? ORION_PCI_REG(0xc0c) : \
+- ((n) == 3) ? ORION_PCI_REG(0xd0c) : 0)
+-#define PCI_BAR_REMAP_DDR_CS(n) (((n) ==0) ? ORION_PCI_REG(0xc48) : \
+- ((n) == 1) ? ORION_PCI_REG(0xd48) : \
+- ((n) == 2) ? ORION_PCI_REG(0xc4c) : \
+- ((n) == 3) ? ORION_PCI_REG(0xd4c) : 0)
+-#define PCI_BAR_ENABLE ORION_PCI_REG(0xc3c)
+-#define PCI_CTRL_BASE_LO(n) ORION_PCI_REG(0x1e00 | ((n) << 4))
+-#define PCI_CTRL_BASE_HI(n) ORION_PCI_REG(0x1e04 | ((n) << 4))
+-#define PCI_CTRL_SIZE(n) ORION_PCI_REG(0x1e08 | ((n) << 4))
+-#define PCI_ADDR_DECODE_CTRL ORION_PCI_REG(0xd3c)
+-
+-/*
+- * PCI configuration heleprs for BAR settings
+- */
+-#define PCI_CONF_FUNC_BAR_CS(n) ((n) >> 1)
+-#define PCI_CONF_REG_BAR_LO_CS(n) (((n) & 1) ? 0x18 : 0x10)
+-#define PCI_CONF_REG_BAR_HI_CS(n) (((n) & 1) ? 0x1c : 0x14)
+-
+-/*
+- * Gigabit Ethernet Address Decode Windows registers
+- */
+-#define ETH_WIN_BASE(win) ORION_ETH_REG(0x200 + ((win) * 8))
+-#define ETH_WIN_SIZE(win) ORION_ETH_REG(0x204 + ((win) * 8))
+-#define ETH_WIN_REMAP(win) ORION_ETH_REG(0x280 + ((win) * 4))
+-#define ETH_WIN_EN ORION_ETH_REG(0x290)
+-#define ETH_WIN_PROT ORION_ETH_REG(0x294)
+-#define ETH_MAX_WIN 6
+-#define ETH_MAX_REMAP_WIN 4
+-
+-/*
+- * USB Address Decode Windows registers
+- */
+-#define USB_WIN_CTRL(i, w) ((i == 0) ? ORION_USB0_REG(0x320 + ((w) << 4)) \
+- : ORION_USB1_REG(0x320 + ((w) << 4)))
+-#define USB_WIN_BASE(i, w) ((i == 0) ? ORION_USB0_REG(0x324 + ((w) << 4)) \
+- : ORION_USB1_REG(0x324 + ((w) << 4)))
+-#define USB_MAX_WIN 4
+-
+-/*
+- * SATA Address Decode Windows registers
+- */
+-#define SATA_WIN_CTRL(win) ORION_SATA_REG(0x30 + ((win) * 0x10))
+-#define SATA_WIN_BASE(win) ORION_SATA_REG(0x34 + ((win) * 0x10))
+-#define SATA_MAX_WIN 4
+-
+-static int __init orion_cpu_win_can_remap(u32 win)
+-{
+- u32 dev, rev;
+-
+- orion_pcie_id(&dev, &rev);
+- if ((dev == MV88F5281_DEV_ID && win < 4)
+- || (dev == MV88F5182_DEV_ID && win < 2)
+- || (dev == MV88F5181_DEV_ID && win < 2))
+- return 1;
+-
+- return 0;
+-}
+-
+-void __init orion_setup_cpu_win(enum orion_target target, u32 base, u32 size, int remap)
+-{
+- u32 win, attr, ctrl;
+-
+- switch (target) {
+- case ORION_PCIE_IO:
+- target = TARGET_PCIE;
+- attr = ATTR_PCIE_IO;
+- win = CPU_WIN_PCIE_IO;
+- break;
+- case ORION_PCI_IO:
+- target = TARGET_PCI;
+- attr = ATTR_PCI_IO;
+- win = CPU_WIN_PCI_IO;
+- break;
+- case ORION_PCIE_MEM:
+- target = TARGET_PCIE;
+- attr = ATTR_PCIE_MEM;
+- win = CPU_WIN_PCIE_MEM;
+- break;
+- case ORION_PCI_MEM:
+- target = TARGET_PCI;
+- attr = ATTR_PCI_MEM;
+- win = CPU_WIN_PCI_MEM;
+- break;
+- case ORION_DEV_BOOT:
+- target = TARGET_DEV_BUS;
+- attr = ATTR_DEV_BOOT;
+- win = CPU_WIN_DEV_BOOT;
+- break;
+- case ORION_DEV0:
+- target = TARGET_DEV_BUS;
+- attr = ATTR_DEV_CS0;
+- win = CPU_WIN_DEV_CS0;
+- break;
+- case ORION_DEV1:
+- target = TARGET_DEV_BUS;
+- attr = ATTR_DEV_CS1;
+- win = CPU_WIN_DEV_CS1;
+- break;
+- case ORION_DEV2:
+- target = TARGET_DEV_BUS;
+- attr = ATTR_DEV_CS2;
+- win = CPU_WIN_DEV_CS2;
+- break;
+- case ORION_DDR:
+- case ORION_REGS:
+- /*
+- * Must be mapped by bootloader.
+- */
+- default:
+- target = attr = win = -1;
+- BUG();
+- }
+-
+- base &= 0xffff0000;
+- ctrl = (((size - 1) & 0xffff0000) | (attr << 8) |
+- (target << 4) | WIN_EN);
+-
+- orion_write(CPU_WIN_BASE(win), base);
+- orion_write(CPU_WIN_CTRL(win), ctrl);
+-
+- if (orion_cpu_win_can_remap(win)) {
+- if (remap >= 0) {
+- orion_write(CPU_WIN_REMAP_LO(win), remap & 0xffff0000);
+- orion_write(CPU_WIN_REMAP_HI(win), 0);
+- } else {
+- orion_write(CPU_WIN_REMAP_LO(win), base);
+- orion_write(CPU_WIN_REMAP_HI(win), 0);
+- }
+- }
+-}
+-
+-void __init orion_setup_cpu_wins(void)
+-{
+- int i;
+-
+- /*
+- * First, disable and clear windows
+- */
+- for (i = 0; i < CPU_MAX_WIN; i++) {
+- orion_write(CPU_WIN_BASE(i), 0);
+- orion_write(CPU_WIN_CTRL(i), 0);
+- if (orion_cpu_win_can_remap(i)) {
+- orion_write(CPU_WIN_REMAP_LO(i), 0);
+- orion_write(CPU_WIN_REMAP_HI(i), 0);
+- }
+- }
+-
+- /*
+- * Setup windows for PCI+PCIe IO+MEM space.
+- */
+- orion_setup_cpu_win(ORION_PCIE_IO, ORION_PCIE_IO_PHYS_BASE,
+- ORION_PCIE_IO_SIZE, ORION_PCIE_IO_BUS_BASE);
+- orion_setup_cpu_win(ORION_PCI_IO, ORION_PCI_IO_PHYS_BASE,
+- ORION_PCI_IO_SIZE, ORION_PCI_IO_BUS_BASE);
+- orion_setup_cpu_win(ORION_PCIE_MEM, ORION_PCIE_MEM_PHYS_BASE,
+- ORION_PCIE_MEM_SIZE, -1);
+- orion_setup_cpu_win(ORION_PCI_MEM, ORION_PCI_MEM_PHYS_BASE,
+- ORION_PCI_MEM_SIZE, -1);
+-}
+-
+-/*
+- * Setup PCIE BARs and Address Decode Wins:
+- * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
+- * WIN[0-3] -> DRAM bank[0-3]
+- */
+-void __init orion_setup_pcie_wins(void)
+-{
+- u32 base, size, i;
+-
+- /*
+- * First, disable and clear BARs and windows
+- */
+- for (i = 1; i < PCIE_MAX_BARS; i++) {
+- orion_write(PCIE_BAR_CTRL(i), 0);
+- orion_write(PCIE_BAR_LO(i), 0);
+- orion_write(PCIE_BAR_HI(i), 0);
+- }
+-
+- for (i = 0; i < PCIE_MAX_WINS; i++) {
+- orion_write(PCIE_WIN_CTRL(i), 0);
+- orion_write(PCIE_WIN_BASE(i), 0);
+- orion_write(PCIE_WIN_REMAP(i), 0);
+- }
+-
+- /*
+- * Setup windows for DDR banks. Count total DDR size on the fly.
+- */
+- base = DDR_REG_TO_BASE(orion_read(DDR_BASE_CS(0)));
+- size = 0;
+- for (i = 0; i < DDR_MAX_CS; i++) {
+- u32 bank_base, bank_size;
+- bank_size = orion_read(DDR_SIZE_CS(i));
+- bank_base = orion_read(DDR_BASE_CS(i));
+- if (bank_size & DDR_BANK_EN) {
+- bank_size = DDR_REG_TO_SIZE(bank_size);
+- bank_base = DDR_REG_TO_BASE(bank_base);
+- orion_write(PCIE_WIN_BASE(i), bank_base & 0xffff0000);
+- orion_write(PCIE_WIN_REMAP(i), 0);
+- orion_write(PCIE_WIN_CTRL(i),
+- ((bank_size-1) & 0xffff0000) |
+- (ATTR_DDR_CS(i) << 8) |
+- (TARGET_DDR << 4) |
+- (PCIE_DRAM_BAR << 1) | WIN_EN);
+- size += bank_size;
+- }
+- }
+-
+- /*
+- * Setup BAR[1] to all DRAM banks
+- */
+- orion_write(PCIE_BAR_LO(PCIE_DRAM_BAR), base & 0xffff0000);
+- orion_write(PCIE_BAR_HI(PCIE_DRAM_BAR), 0);
+- orion_write(PCIE_BAR_CTRL(PCIE_DRAM_BAR),
+- ((size - 1) & 0xffff0000) | WIN_EN);
+-}
+-
+-void __init orion_setup_pci_wins(void)
+-{
+- u32 base, size, i;
+-
+- /*
+- * First, disable windows
+- */
+- orion_write(PCI_BAR_ENABLE, 0xffffffff);
+-
+- /*
+- * Setup windows for DDR banks.
+- */
+- for (i = 0; i < DDR_MAX_CS; i++) {
+- base = orion_read(DDR_BASE_CS(i));
+- size = orion_read(DDR_SIZE_CS(i));
+- if (size & DDR_BANK_EN) {
+- u32 bus, dev, func, reg, val;
+- size = DDR_REG_TO_SIZE(size);
+- base = DDR_REG_TO_BASE(base);
+- bus = orion_pci_local_bus_nr();
+- dev = orion_pci_local_dev_nr();
+- func = PCI_CONF_FUNC_BAR_CS(i);
+- reg = PCI_CONF_REG_BAR_LO_CS(i);
+- orion_pci_hw_rd_conf(bus, dev, func, reg, 4, &val);
+- orion_pci_hw_wr_conf(bus, dev, func, reg, 4,
+- (base & 0xfffff000) | (val & 0xfff));
+- reg = PCI_CONF_REG_BAR_HI_CS(i);
+- orion_pci_hw_wr_conf(bus, dev, func, reg, 4, 0);
+- orion_write(PCI_BAR_SIZE_DDR_CS(i),
+- (size - 1) & 0xfffff000);
+- orion_write(PCI_BAR_REMAP_DDR_CS(i),
+- base & 0xfffff000);
+- orion_clrbits(PCI_BAR_ENABLE, (1 << i));
+- }
+- }
+-
+- /*
+- * Disable automatic update of address remaping when writing to BARs
+- */
+- orion_setbits(PCI_ADDR_DECODE_CTRL, 1);
+-}
+-
+-void __init orion_setup_usb_wins(void)
+-{
+- int i;
+- u32 usb_if, dev, rev;
+- u32 max_usb_if = 1;
+-
+- orion_pcie_id(&dev, &rev);
+- if (dev == MV88F5182_DEV_ID)
+- max_usb_if = 2;
+-
+- for (usb_if = 0; usb_if < max_usb_if; usb_if++) {
+- /*
+- * First, disable and clear windows
+- */
+- for (i = 0; i < USB_MAX_WIN; i++) {
+- orion_write(USB_WIN_BASE(usb_if, i), 0);
+- orion_write(USB_WIN_CTRL(usb_if, i), 0);
+- }
+-
+- /*
+- * Setup windows for DDR banks.
+- */
+- for (i = 0; i < DDR_MAX_CS; i++) {
+- u32 base, size;
+- size = orion_read(DDR_SIZE_CS(i));
+- base = orion_read(DDR_BASE_CS(i));
+- if (size & DDR_BANK_EN) {
+- base = DDR_REG_TO_BASE(base);
+- size = DDR_REG_TO_SIZE(size);
+- orion_write(USB_WIN_CTRL(usb_if, i),
+- ((size-1) & 0xffff0000) |
+- (ATTR_DDR_CS(i) << 8) |
+- (TARGET_DDR << 4) | WIN_EN);
+- orion_write(USB_WIN_BASE(usb_if, i),
+- base & 0xffff0000);
+- }
+- }
+- }
+-}
+-
+-void __init orion_setup_eth_wins(void)
+-{
+- int i;
+-
+- /*
+- * First, disable and clear windows
+- */
+- for (i = 0; i < ETH_MAX_WIN; i++) {
+- orion_write(ETH_WIN_BASE(i), 0);
+- orion_write(ETH_WIN_SIZE(i), 0);
+- orion_setbits(ETH_WIN_EN, 1 << i);
+- orion_clrbits(ETH_WIN_PROT, 0x3 << (i * 2));
+- if (i < ETH_MAX_REMAP_WIN)
+- orion_write(ETH_WIN_REMAP(i), 0);
+- }
+-
+- /*
+- * Setup windows for DDR banks.
+- */
+- for (i = 0; i < DDR_MAX_CS; i++) {
+- u32 base, size;
+- size = orion_read(DDR_SIZE_CS(i));
+- base = orion_read(DDR_BASE_CS(i));
+- if (size & DDR_BANK_EN) {
+- base = DDR_REG_TO_BASE(base);
+- size = DDR_REG_TO_SIZE(size);
+- orion_write(ETH_WIN_SIZE(i), (size-1) & 0xffff0000);
+- orion_write(ETH_WIN_BASE(i), (base & 0xffff0000) |
+- (ATTR_DDR_CS(i) << 8) |
+- TARGET_DDR);
+- orion_clrbits(ETH_WIN_EN, 1 << i);
+- orion_setbits(ETH_WIN_PROT, 0x3 << (i * 2));
+- }
+- }
+-}
+-
+-void __init orion_setup_sata_wins(void)
+-{
+- int i;
+-
+- /*
+- * First, disable and clear windows
+- */
+- for (i = 0; i < SATA_MAX_WIN; i++) {
+- orion_write(SATA_WIN_BASE(i), 0);
+- orion_write(SATA_WIN_CTRL(i), 0);
+- }
+-
+- /*
+- * Setup windows for DDR banks.
+- */
+- for (i = 0; i < DDR_MAX_CS; i++) {
+- u32 base, size;
+- size = orion_read(DDR_SIZE_CS(i));
+- base = orion_read(DDR_BASE_CS(i));
+- if (size & DDR_BANK_EN) {
+- base = DDR_REG_TO_BASE(base);
+- size = DDR_REG_TO_SIZE(size);
+- orion_write(SATA_WIN_CTRL(i),
+- ((size-1) & 0xffff0000) |
+- (ATTR_DDR_CS(i) << 8) |
+- (TARGET_DDR << 4) | WIN_EN);
+- orion_write(SATA_WIN_BASE(i),
+- base & 0xffff0000);
+- }
+- }
+-}
+diff --git a/arch/arm/mach-orion/common.c b/arch/arm/mach-orion/common.c
+deleted file mode 100644
+index bbc2b4e..0000000
+--- a/arch/arm/mach-orion/common.c
++++ /dev/null
+@@ -1,369 +0,0 @@
+-/*
+- * arch/arm/mach-orion/common.c
+- *
+- * Core functions for Marvell Orion System On Chip
+- *
+- * Maintainer: Tzachi Perelstein <tzachi at marvell.com>
+- *
+- * This file is licensed under the terms of the GNU General Public
+- * License version 2. This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/platform_device.h>
+-#include <linux/serial_8250.h>
+-#include <linux/mv643xx_eth.h>
+-#include <linux/mv643xx_i2c.h>
+-#include <asm/page.h>
+-#include <asm/setup.h>
+-#include <asm/timex.h>
+-#include <asm/mach/arch.h>
+-#include <asm/mach/map.h>
+-#include <asm/arch/hardware.h>
+-#include "common.h"
+-
+-/*****************************************************************************
+- * I/O Address Mapping
+- ****************************************************************************/
+-static struct map_desc orion_io_desc[] __initdata = {
+- {
+- .virtual = ORION_REGS_VIRT_BASE,
+- .pfn = __phys_to_pfn(ORION_REGS_PHYS_BASE),
+- .length = ORION_REGS_SIZE,
+- .type = MT_DEVICE
+- },
+- {
+- .virtual = ORION_PCIE_IO_VIRT_BASE,
+- .pfn = __phys_to_pfn(ORION_PCIE_IO_PHYS_BASE),
+- .length = ORION_PCIE_IO_SIZE,
+- .type = MT_DEVICE
+- },
+- {
+- .virtual = ORION_PCI_IO_VIRT_BASE,
+- .pfn = __phys_to_pfn(ORION_PCI_IO_PHYS_BASE),
+- .length = ORION_PCI_IO_SIZE,
+- .type = MT_DEVICE
+- },
+- {
+- .virtual = ORION_PCIE_WA_VIRT_BASE,
+- .pfn = __phys_to_pfn(ORION_PCIE_WA_PHYS_BASE),
+- .length = ORION_PCIE_WA_SIZE,
+- .type = MT_DEVICE
+- },
+-};
+-
+-void __init orion_map_io(void)
+-{
+- iotable_init(orion_io_desc, ARRAY_SIZE(orion_io_desc));
+-}
+-
+-/*****************************************************************************
+- * UART
+- ****************************************************************************/
+-
+-static struct resource orion_uart_resources[] = {
+- {
+- .start = UART0_PHYS_BASE,
+- .end = UART0_PHYS_BASE + 0xff,
+- .flags = IORESOURCE_MEM,
+- },
+- {
+- .start = IRQ_ORION_UART0,
+- .end = IRQ_ORION_UART0,
+- .flags = IORESOURCE_IRQ,
+- },
+- {
+- .start = UART1_PHYS_BASE,
+- .end = UART1_PHYS_BASE + 0xff,
+- .flags = IORESOURCE_MEM,
+- },
+- {
+- .start = IRQ_ORION_UART1,
+- .end = IRQ_ORION_UART1,
+- .flags = IORESOURCE_IRQ,
+- },
+-};
+-
+-static struct plat_serial8250_port orion_uart_data[] = {
+- {
+- .mapbase = UART0_PHYS_BASE,
+- .membase = (char *)UART0_VIRT_BASE,
+- .irq = IRQ_ORION_UART0,
+- .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
+- .iotype = UPIO_MEM,
+- .regshift = 2,
+- .uartclk = ORION_TCLK,
+- },
+- {
+- .mapbase = UART1_PHYS_BASE,
+- .membase = (char *)UART1_VIRT_BASE,
+- .irq = IRQ_ORION_UART1,
+- .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
+- .iotype = UPIO_MEM,
+- .regshift = 2,
+- .uartclk = ORION_TCLK,
+- },
+- { },
+-};
+-
+-static struct platform_device orion_uart = {
+- .name = "serial8250",
+- .id = PLAT8250_DEV_PLATFORM,
+- .dev = {
+- .platform_data = orion_uart_data,
+- },
+- .resource = orion_uart_resources,
+- .num_resources = ARRAY_SIZE(orion_uart_resources),
+-};
+-
+-/*******************************************************************************
+- * USB Controller - 2 interfaces
+- ******************************************************************************/
+-
+-static struct resource orion_ehci0_resources[] = {
+- {
+- .start = ORION_USB0_PHYS_BASE,
+- .end = ORION_USB0_PHYS_BASE + SZ_4K,
+- .flags = IORESOURCE_MEM,
+- },
+- {
+- .start = IRQ_ORION_USB0_CTRL,
+- .end = IRQ_ORION_USB0_CTRL,
+- .flags = IORESOURCE_IRQ,
+- },
+-};
+-
+-static struct resource orion_ehci1_resources[] = {
+- {
+- .start = ORION_USB1_PHYS_BASE,
+- .end = ORION_USB1_PHYS_BASE + SZ_4K,
+- .flags = IORESOURCE_MEM,
+- },
+- {
+- .start = IRQ_ORION_USB1_CTRL,
+- .end = IRQ_ORION_USB1_CTRL,
+- .flags = IORESOURCE_IRQ,
+- },
+-};
+-
+-static u64 ehci_dmamask = 0xffffffffUL;
+-
+-static struct platform_device orion_ehci0 = {
+- .name = "orion-ehci",
+- .id = 0,
+- .dev = {
+- .dma_mask = &ehci_dmamask,
+- .coherent_dma_mask = 0xffffffff,
+- },
+- .resource = orion_ehci0_resources,
+- .num_resources = ARRAY_SIZE(orion_ehci0_resources),
+-};
+-
+-static struct platform_device orion_ehci1 = {
+- .name = "orion-ehci",
+- .id = 1,
+- .dev = {
+- .dma_mask = &ehci_dmamask,
+- .coherent_dma_mask = 0xffffffff,
+- },
+- .resource = orion_ehci1_resources,
+- .num_resources = ARRAY_SIZE(orion_ehci1_resources),
+-};
+-
+-/*****************************************************************************
+- * Gigabit Ethernet port
+- * (The Orion and Discovery (MV643xx) families use the same Ethernet driver)
+- ****************************************************************************/
+-
+-static struct resource orion_eth_shared_resources[] = {
+- {
+- .start = ORION_ETH_PHYS_BASE + 0x2000,
+- .end = ORION_ETH_PHYS_BASE + 0x3fff,
+- .flags = IORESOURCE_MEM,
+- },
+-};
+-
+-static struct platform_device orion_eth_shared = {
+- .name = MV643XX_ETH_SHARED_NAME,
+- .id = 0,
+- .num_resources = 1,
+- .resource = orion_eth_shared_resources,
+-};
+-
+-static struct resource orion_eth_resources[] = {
+- {
+- .name = "eth irq",
+- .start = IRQ_ORION_ETH_SUM,
+- .end = IRQ_ORION_ETH_SUM,
+- .flags = IORESOURCE_IRQ,
+- }
+-};
+-
+-static struct platform_device orion_eth = {
+- .name = MV643XX_ETH_NAME,
+- .id = 0,
+- .num_resources = 1,
+- .resource = orion_eth_resources,
+-};
+-
+-void __init orion_eth_init(struct mv643xx_eth_platform_data *eth_data)
+-{
+- orion_eth.dev.platform_data = eth_data;
+- platform_device_register(&orion_eth_shared);
+- platform_device_register(&orion_eth);
+-}
+-
+-/*****************************************************************************
+- * I2C controller
+- * (The Orion and Discovery (MV643xx) families share the same I2C controller)
+- ****************************************************************************/
+-
+-static struct mv64xxx_i2c_pdata orion_i2c_pdata = {
+- .freq_m = 8, /* assumes 166 MHz TCLK */
+- .freq_n = 3,
+- .timeout = 1000, /* Default timeout of 1 second */
+-};
+-
+-static struct resource orion_i2c_resources[] = {
+- {
+- .name = "i2c base",
+- .start = I2C_PHYS_BASE,
+- .end = I2C_PHYS_BASE + 0x20 -1,
+- .flags = IORESOURCE_MEM,
+- },
+- {
+- .name = "i2c irq",
+- .start = IRQ_ORION_I2C,
+- .end = IRQ_ORION_I2C,
+- .flags = IORESOURCE_IRQ,
+- },
+-};
+-
+-static struct platform_device orion_i2c = {
+- .name = MV64XXX_I2C_CTLR_NAME,
+- .id = 0,
+- .num_resources = ARRAY_SIZE(orion_i2c_resources),
+- .resource = orion_i2c_resources,
+- .dev = {
+- .platform_data = &orion_i2c_pdata,
+- },
+-};
+-
+-/*****************************************************************************
+- * Sata port
+- ****************************************************************************/
+-static struct resource orion_sata_resources[] = {
+- {
+- .name = "sata base",
+- .start = ORION_SATA_PHYS_BASE,
+- .end = ORION_SATA_PHYS_BASE + 0x5000 - 1,
+- .flags = IORESOURCE_MEM,
+- },
+- {
+- .name = "sata irq",
+- .start = IRQ_ORION_SATA,
+- .end = IRQ_ORION_SATA,
+- .flags = IORESOURCE_IRQ,
+- },
+-};
+-
+-static struct platform_device orion_sata = {
+- .name = "sata_mv",
+- .id = 0,
+- .dev = {
+- .coherent_dma_mask = 0xffffffff,
+- },
+- .num_resources = ARRAY_SIZE(orion_sata_resources),
+- .resource = orion_sata_resources,
+-};
+-
+-void __init orion_sata_init(struct mv_sata_platform_data *sata_data)
+-{
+- orion_sata.dev.platform_data = sata_data;
+- platform_device_register(&orion_sata);
+-}
+-
+-/*****************************************************************************
+- * General
+- ****************************************************************************/
+-
+-/*
+- * Identify device ID and rev from PCIE configuration header space '0'.
+- */
+-static void orion_id(u32 *dev, u32 *rev, char **dev_name)
+-{
+- orion_pcie_id(dev, rev);
+-
+- if (*dev == MV88F5281_DEV_ID) {
+- if (*rev == MV88F5281_REV_D2) {
+- *dev_name = "MV88F5281-D2";
+- } else if (*rev == MV88F5281_REV_D1) {
+- *dev_name = "MV88F5281-D1";
+- } else {
+- *dev_name = "MV88F5281-Rev-Unsupported";
+- }
+- } else if (*dev == MV88F5182_DEV_ID) {
+- if (*rev == MV88F5182_REV_A2) {
+- *dev_name = "MV88F5182-A2";
+- } else {
+- *dev_name = "MV88F5182-Rev-Unsupported";
+- }
+- } else if (*dev == MV88F5181_DEV_ID) {
+- if (*rev == MV88F5181_REV_B1) {
+- *dev_name = "MV88F5181-Rev-B1";
+- } else {
+- *dev_name = "MV88F5181-Rev-Unsupported";
+- }
+- } else {
+- *dev_name = "Device-Unknown";
+- }
+-}
+-
+-void __init orion_init(void)
+-{
+- char *dev_name;
+- u32 dev, rev;
+-
+- orion_id(&dev, &rev, &dev_name);
+- printk(KERN_INFO "Orion ID: %s. TCLK=%d.\n", dev_name, ORION_TCLK);
+-
+- /*
+- * Setup Orion address map
+- */
+- orion_setup_cpu_wins();
+- orion_setup_usb_wins();
+- orion_setup_eth_wins();
+- orion_setup_pci_wins();
+- orion_setup_pcie_wins();
+- if (dev == MV88F5182_DEV_ID)
+- orion_setup_sata_wins();
+-
+- /*
+- * REgister devices
+- */
+- platform_device_register(&orion_uart);
+- platform_device_register(&orion_ehci0);
+- if (dev == MV88F5182_DEV_ID)
+- platform_device_register(&orion_ehci1);
+- platform_device_register(&orion_i2c);
+-}
+-
+-/*
+- * Many orion-based systems have buggy bootloader implementations.
+- * This is a common fixup for bogus memory tags.
+- */
+-void __init tag_fixup_mem32(struct machine_desc *mdesc, struct tag *t,
+- char **from, struct meminfo *meminfo)
+-{
+- for (; t->hdr.size; t = tag_next(t))
+- if (t->hdr.tag == ATAG_MEM &&
+- (!t->u.mem.size || t->u.mem.size & ~PAGE_MASK ||
+- t->u.mem.start & ~PAGE_MASK)) {
+- printk(KERN_WARNING
+- "Clearing invalid memory bank %dKB at 0x%08x\n",
+- t->u.mem.size / 1024, t->u.mem.start);
+- t->hdr.tag = 0;
+- }
+-}
+diff --git a/arch/arm/mach-orion/common.h b/arch/arm/mach-orion/common.h
+deleted file mode 100644
+index 501497c..0000000
+--- a/arch/arm/mach-orion/common.h
++++ /dev/null
+@@ -1,92 +0,0 @@
+-#ifndef __ARCH_ORION_COMMON_H__
+-#define __ARCH_ORION_COMMON_H__
+-
+-/*
+- * Basic Orion init functions used early by machine-setup.
+- */
+-
+-void __init orion_map_io(void);
+-void __init orion_init_irq(void);
+-void __init orion_init(void);
+-
+-/*
+- * Enumerations and functions for Orion windows mapping. Used by Orion core
+- * functions to map its interfaces and by the machine-setup to map its on-
+- * board devices. Details in /mach-orion/addr-map.c
+- */
+-
+-enum orion_target {
+- ORION_DEV_BOOT = 0,
+- ORION_DEV0,
+- ORION_DEV1,
+- ORION_DEV2,
+- ORION_PCIE_MEM,
+- ORION_PCIE_IO,
+- ORION_PCI_MEM,
+- ORION_PCI_IO,
+- ORION_DDR,
+- ORION_REGS,
+- ORION_MAX_TARGETS
+-};
+-
+-void orion_setup_cpu_win(enum orion_target target, u32 base, u32 size, int remap);
+-void orion_setup_cpu_wins(void);
+-void orion_setup_eth_wins(void);
+-void orion_setup_usb_wins(void);
+-void orion_setup_pci_wins(void);
+-void orion_setup_pcie_wins(void);
+-void orion_setup_sata_wins(void);
+-
+-/*
+- * Shared code used internally by other Orion core functions.
+- * (/mach-orion/pci.c)
+- */
+-
+-struct pci_sys_data;
+-struct pci_bus;
+-
+-void orion_pcie_id(u32 *dev, u32 *rev);
+-u32 orion_pcie_local_bus_nr(void);
+-u32 orion_pci_local_bus_nr(void);
+-u32 orion_pci_local_dev_nr(void);
+-int orion_pci_sys_setup(int nr, struct pci_sys_data *sys);
+-struct pci_bus *orion_pci_sys_scan_bus(int nr, struct pci_sys_data *sys);
+-int orion_pci_hw_rd_conf(u32 bus, u32 dev, u32 func, u32 where, u32 size, u32 *val);
+-int orion_pci_hw_wr_conf(u32 bus, u32 dev, u32 func, u32 where, u32 size, u32 val);
+-
+-/*
+- * Valid GPIO pins according to MPP setup, used by machine-setup.
+- * (/mach-orion/gpio.c).
+- */
+-
+-void __init orion_gpio_set_valid_pins(u32 pins);
+-void gpio_display(void); /* debug */
+-
+-/*
+- * Orion system timer (clocksource + clockevnt, /mach-orion/time.c)
+- */
+-extern struct sys_timer orion_timer;
+-
+-/*
+- * Pull in Orion Ethernet platform_data, used by machine-setup
+- */
+-
+-struct mv643xx_eth_platform_data;
+-
+-void __init orion_eth_init(struct mv643xx_eth_platform_data *eth_data);
+-
+-/*
+- * Orion Sata platform_data, used by machine-setup
+- */
+-
+-struct mv_sata_platform_data;
+-
+-void __init orion_sata_init(struct mv_sata_platform_data *sata_data);
+-
+-struct machine_desc;
+-struct meminfo;
+-struct tag;
+-extern void __init tag_fixup_mem32(struct machine_desc *, struct tag *,
+- char **, struct meminfo *);
+-
+-#endif /* __ARCH_ORION_COMMON_H__ */
+diff --git a/arch/arm/mach-orion/db88f5281-setup.c b/arch/arm/mach-orion/db88f5281-setup.c
+deleted file mode 100644
+index 5ef44e1..0000000
+--- a/arch/arm/mach-orion/db88f5281-setup.c
++++ /dev/null
+@@ -1,364 +0,0 @@
+-/*
+- * arch/arm/mach-orion/db88f5281-setup.c
+- *
+- * Marvell Orion-2 Development Board Setup
+- *
+- * Maintainer: Tzachi Perelstein <tzachi at marvell.com>
+- *
+- * This file is licensed under the terms of the GNU General Public
+- * License version 2. This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/platform_device.h>
+-#include <linux/pci.h>
+-#include <linux/irq.h>
+-#include <linux/mtd/physmap.h>
+-#include <linux/mtd/nand.h>
+-#include <linux/timer.h>
+-#include <linux/mv643xx_eth.h>
+-#include <linux/i2c.h>
+-#include <asm/mach-types.h>
+-#include <asm/gpio.h>
+-#include <asm/mach/arch.h>
+-#include <asm/mach/pci.h>
+-#include <asm/arch/orion.h>
+-#include <asm/arch/platform.h>
+-#include "common.h"
+-
+-/*****************************************************************************
+- * DB-88F5281 on board devices
+- ****************************************************************************/
+-
+-/*
+- * 512K NOR flash Device bus boot chip select
+- */
+-
+-#define DB88F5281_NOR_BOOT_BASE 0xf4000000
+-#define DB88F5281_NOR_BOOT_SIZE SZ_512K
+-
+-/*
+- * 7-Segment on Device bus chip select 0
+- */
+-
+-#define DB88F5281_7SEG_BASE 0xfa000000
+-#define DB88F5281_7SEG_SIZE SZ_1K
+-
+-/*
+- * 32M NOR flash on Device bus chip select 1
+- */
+-
+-#define DB88F5281_NOR_BASE 0xfc000000
+-#define DB88F5281_NOR_SIZE SZ_32M
+-
+-/*
+- * 32M NAND flash on Device bus chip select 2
+- */
+-
+-#define DB88F5281_NAND_BASE 0xfa800000
+-#define DB88F5281_NAND_SIZE SZ_1K
+-
+-/*
+- * PCI
+- */
+-
+-#define DB88F5281_PCI_SLOT0_OFFS 7
+-#define DB88F5281_PCI_SLOT0_IRQ_PIN 12
+-#define DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN 13
+-
+-/*****************************************************************************
+- * 512M NOR Flash on Device bus Boot CS
+- ****************************************************************************/
+-
+-static struct physmap_flash_data db88f5281_boot_flash_data = {
+- .width = 1, /* 8 bit bus width */
+-};
+-
+-static struct resource db88f5281_boot_flash_resource = {
+- .flags = IORESOURCE_MEM,
+- .start = DB88F5281_NOR_BOOT_BASE,
+- .end = DB88F5281_NOR_BOOT_BASE + DB88F5281_NOR_BOOT_SIZE - 1,
+-};
+-
+-static struct platform_device db88f5281_boot_flash = {
+- .name = "physmap-flash",
+- .id = 0,
+- .dev = {
+- .platform_data = &db88f5281_boot_flash_data,
+- },
+- .num_resources = 1,
+- .resource = &db88f5281_boot_flash_resource,
+-};
+-
+-/*****************************************************************************
+- * 32M NOR Flash on Device bus CS1
+- ****************************************************************************/
+-
+-static struct physmap_flash_data db88f5281_nor_flash_data = {
+- .width = 4, /* 32 bit bus width */
+-};
+-
+-static struct resource db88f5281_nor_flash_resource = {
+- .flags = IORESOURCE_MEM,
+- .start = DB88F5281_NOR_BASE,
+- .end = DB88F5281_NOR_BASE + DB88F5281_NOR_SIZE - 1,
+-};
+-
+-static struct platform_device db88f5281_nor_flash = {
+- .name = "physmap-flash",
+- .id = 1,
+- .dev = {
+- .platform_data = &db88f5281_nor_flash_data,
+- },
+- .num_resources = 1,
+- .resource = &db88f5281_nor_flash_resource,
+-};
+-
+-/*****************************************************************************
+- * 32M NAND Flash on Device bus CS2
+- ****************************************************************************/
+-
+-static struct mtd_partition db88f5281_nand_parts[] = {
+- {
+- .name = "kernel",
+- .offset = 0,
+- .size = SZ_2M,
+- },
+- {
+- .name = "root",
+- .offset = SZ_2M,
+- .size = (SZ_16M - SZ_2M),
+- },
+- {
+- .name = "user",
+- .offset = SZ_16M,
+- .size = SZ_8M,
+- },
+- {
+- .name = "recovery",
+- .offset = (SZ_16M + SZ_8M),
+- .size = SZ_8M,
+- },
+-};
+-
+-static struct resource db88f5281_nand_resource = {
+- .flags = IORESOURCE_MEM,
+- .start = DB88F5281_NAND_BASE,
+- .end = DB88F5281_NAND_BASE + DB88F5281_NAND_SIZE - 1,
+-};
+-
+-static struct orion_nand_data db88f5281_nand_data = {
+- .parts = db88f5281_nand_parts,
+- .nr_parts = ARRAY_SIZE(db88f5281_nand_parts),
+- .cle = 0,
+- .ale = 1,
+- .width = 8,
+-};
+-
+-static struct platform_device db88f5281_nand_flash = {
+- .name = "orion_nand",
+- .id = -1,
+- .dev = {
+- .platform_data = &db88f5281_nand_data,
+- },
+- .resource = &db88f5281_nand_resource,
+- .num_resources = 1,
+-};
+-
+-/*****************************************************************************
+- * 7-Segment on Device bus CS0
+- * Dummy counter every 2 sec
+- ****************************************************************************/
+-
+-static void __iomem *db88f5281_7seg;
+-static struct timer_list db88f5281_timer;
+-
+-static void db88f5281_7seg_event(unsigned long data)
+-{
+- static int count = 0;
+- writel(0, db88f5281_7seg + (count << 4));
+- count = (count + 1) & 7;
+- mod_timer(&db88f5281_timer, jiffies + 2 * HZ);
+-}
+-
+-static int __init db88f5281_7seg_init(void)
+-{
+- if (machine_is_db88f5281()) {
+- db88f5281_7seg = ioremap(DB88F5281_7SEG_BASE,
+- DB88F5281_7SEG_SIZE);
+- if (!db88f5281_7seg) {
+- printk(KERN_ERR "Failed to ioremap db88f5281_7seg\n");
+- return -EIO;
+- }
+- setup_timer(&db88f5281_timer, db88f5281_7seg_event, 0);
+- mod_timer(&db88f5281_timer, jiffies + 2 * HZ);
+- }
+-
+- return 0;
+-}
+-
+-__initcall(db88f5281_7seg_init);
+-
+-/*****************************************************************************
+- * PCI
+- ****************************************************************************/
+-
+-void __init db88f5281_pci_preinit(void)
+-{
+- int pin;
+-
+- /*
+- * Configure PCI GPIO IRQ pins
+- */
+- pin = DB88F5281_PCI_SLOT0_IRQ_PIN;
+- if (gpio_request(pin, "PCI Int1") == 0) {
+- if (gpio_direction_input(pin) == 0) {
+- set_irq_type(gpio_to_irq(pin), IRQT_LOW);
+- } else {
+- printk(KERN_ERR "db88f5281_pci_preinit faield to "
+- "set_irq_type pin %d\n", pin);
+- gpio_free(pin);
+- }
+- } else {
+- printk(KERN_ERR "db88f5281_pci_preinit failed to gpio_request %d\n", pin);
+- }
+-
+- pin = DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN;
+- if (gpio_request(pin, "PCI Int2") == 0) {
+- if (gpio_direction_input(pin) == 0) {
+- set_irq_type(gpio_to_irq(pin), IRQT_LOW);
+- } else {
+- printk(KERN_ERR "db88f5281_pci_preinit faield "
+- "to set_irq_type pin %d\n", pin);
+- gpio_free(pin);
+- }
+- } else {
+- printk(KERN_ERR "db88f5281_pci_preinit failed to gpio_request %d\n", pin);
+- }
+-}
+-
+-static int __init db88f5281_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+-{
+- /*
+- * PCIE IRQ is connected internally (not GPIO)
+- */
+- if (dev->bus->number == orion_pcie_local_bus_nr())
+- return IRQ_ORION_PCIE0_INT;
+-
+- /*
+- * PCI IRQs are connected via GPIOs
+- */
+- switch (slot - DB88F5281_PCI_SLOT0_OFFS) {
+- case 0:
+- return gpio_to_irq(DB88F5281_PCI_SLOT0_IRQ_PIN);
+- case 1:
+- case 2:
+- return gpio_to_irq(DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN);
+- default:
+- return -1;
+- }
+-}
+-
+-static struct hw_pci db88f5281_pci __initdata = {
+- .nr_controllers = 2,
+- .preinit = db88f5281_pci_preinit,
+- .swizzle = pci_std_swizzle,
+- .setup = orion_pci_sys_setup,
+- .scan = orion_pci_sys_scan_bus,
+- .map_irq = db88f5281_pci_map_irq,
+-};
+-
+-static int __init db88f5281_pci_init(void)
+-{
+- if (machine_is_db88f5281())
+- pci_common_init(&db88f5281_pci);
+-
+- return 0;
+-}
+-
+-subsys_initcall(db88f5281_pci_init);
+-
+-/*****************************************************************************
+- * Ethernet
+- ****************************************************************************/
+-static struct mv643xx_eth_platform_data db88f5281_eth_data = {
+- .phy_addr = 8,
+- .force_phy_addr = 1,
+-};
+-
+-/*****************************************************************************
+- * RTC DS1339 on I2C bus
+- ****************************************************************************/
+-static struct i2c_board_info __initdata db88f5281_i2c_rtc = {
+- .driver_name = "rtc-ds1307",
+- .type = "ds1339",
+- .addr = 0x68,
+-};
+-
+-/*****************************************************************************
+- * General Setup
+- ****************************************************************************/
+-
+-static struct platform_device *db88f5281_devs[] __initdata = {
+- &db88f5281_boot_flash,
+- &db88f5281_nor_flash,
+- &db88f5281_nand_flash,
+-};
+-
+-static void __init db88f5281_init(void)
+-{
+- /*
+- * Basic Orion setup. Need to be called early.
+- */
+- orion_init();
+-
+- /*
+- * Setup the CPU address decode windows for our on-board devices
+- */
+- orion_setup_cpu_win(ORION_DEV_BOOT, DB88F5281_NOR_BOOT_BASE,
+- DB88F5281_NOR_BOOT_SIZE, -1);
+- orion_setup_cpu_win(ORION_DEV0, DB88F5281_7SEG_BASE,
+- DB88F5281_7SEG_SIZE, -1);
+- orion_setup_cpu_win(ORION_DEV1, DB88F5281_NOR_BASE,
+- DB88F5281_NOR_SIZE, -1);
+- orion_setup_cpu_win(ORION_DEV2, DB88F5281_NAND_BASE,
+- DB88F5281_NAND_SIZE, -1);
+-
+- /*
+- * Setup Multiplexing Pins:
+- * MPP0: GPIO (USB Over Current) MPP1: GPIO (USB Vbat input)
+- * MPP2: PCI_REQn[2] MPP3: PCI_GNTn[2]
+- * MPP4: PCI_REQn[3] MPP5: PCI_GNTn[3]
+- * MPP6: GPIO (JP0, CON17.2) MPP7: GPIO (JP1, CON17.1)
+- * MPP8: GPIO (JP2, CON11.2) MPP9: GPIO (JP3, CON11.3)
+- * MPP10: GPIO (RTC int) MPP11: GPIO (Baud Rate Generator)
+- * MPP12: GPIO (PCI int 1) MPP13: GPIO (PCI int 2)
+- * MPP14: NAND_REn[2] MPP15: NAND_WEn[2]
+- * MPP16: UART1_RX MPP17: UART1_TX
+- * MPP18: UART1_CTS MPP19: UART1_RTS
+- * MPP-DEV: DEV_D[16:31]
+- */
+- orion_write(MPP_0_7_CTRL, 0x00222203);
+- orion_write(MPP_8_15_CTRL, 0x44000000);
+- orion_write(MPP_16_19_CTRL, 0);
+- orion_write(MPP_DEV_CTRL, 0);
+-
+- orion_gpio_set_valid_pins(0x00003fc3);
+-
+- platform_add_devices(db88f5281_devs, ARRAY_SIZE(db88f5281_devs));
+- i2c_register_board_info(0, &db88f5281_i2c_rtc, 1);
+- orion_eth_init(&db88f5281_eth_data);
+-}
+-
+-MACHINE_START(DB88F5281, "Marvell Orion-2 Development Board")
+- /* Maintainer: Tzachi Perelstein <tzachi at marvell.com> */
+- .phys_io = ORION_REGS_PHYS_BASE,
+- .io_pg_offst = ((ORION_REGS_VIRT_BASE) >> 18) & 0xfffc,
+- .boot_params = 0x00000100,
+- .init_machine = db88f5281_init,
+- .map_io = orion_map_io,
+- .init_irq = orion_init_irq,
+- .timer = &orion_timer,
+-MACHINE_END
+diff --git a/arch/arm/mach-orion/dns323-setup.c b/arch/arm/mach-orion/dns323-setup.c
+deleted file mode 100644
+index 076e155..0000000
+--- a/arch/arm/mach-orion/dns323-setup.c
++++ /dev/null
+@@ -1,323 +0,0 @@
+-/*
+- * arch/arm/mach-orion/dns323-setup.c
+- *
+- * Copyright (C) 2007 Herbert Valerio Riedel <hvr at gnu.org>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License as
+- * published by the Free Software Foundation; either version 2 of the
+- * License, or (at your option) any later version.
+- *
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/platform_device.h>
+-#include <linux/pci.h>
+-#include <linux/irq.h>
+-#include <linux/mtd/physmap.h>
+-#include <linux/mv643xx_eth.h>
+-#include <linux/leds.h>
+-#include <linux/gpio_keys.h>
+-#include <linux/input.h>
+-#include <linux/i2c.h>
+-#include <asm/mach-types.h>
+-#include <asm/gpio.h>
+-#include <asm/mach/arch.h>
+-#include <asm/mach/pci.h>
+-#include <asm/arch/orion.h>
+-#include <asm/arch/platform.h>
+-#include "common.h"
+-
+-#define DNS323_GPIO_LED_RIGHT_AMBER 1
+-#define DNS323_GPIO_LED_LEFT_AMBER 2
+-#define DNS323_GPIO_LED_POWER 5
+-#define DNS323_GPIO_OVERTEMP 6
+-#define DNS323_GPIO_RTC 7
+-#define DNS323_GPIO_POWER_OFF 8
+-#define DNS323_GPIO_KEY_POWER 9
+-#define DNS323_GPIO_KEY_RESET 10
+-
+-/****************************************************************************
+- * PCI setup
+- */
+-
+-static int __init dns323_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+-{
+- /* PCI-E */
+- if (dev->bus->number == orion_pcie_local_bus_nr())
+- return IRQ_ORION_PCIE0_INT;
+-
+- pr_err("%s: requested mapping for unknown bus\n", __func__);
+-
+- return -1;
+-}
+-
+-static struct hw_pci dns323_pci __initdata = {
+- .nr_controllers = 1,
+- .swizzle = pci_std_swizzle,
+- .setup = orion_pci_sys_setup,
+- .scan = orion_pci_sys_scan_bus,
+- .map_irq = dns323_pci_map_irq,
+-};
+-
+-static int __init dns323_pci_init(void)
+-{
+- if (machine_is_dns323())
+- pci_common_init(&dns323_pci);
+-
+- return 0;
+-}
+-
+-subsys_initcall(dns323_pci_init);
+-
+-/****************************************************************************
+- * Ethernet
+- */
+-
+-static struct mv643xx_eth_platform_data dns323_eth_data = {
+- .phy_addr = 8,
+- .force_phy_addr = 1,
+-};
+-
+-/****************************************************************************
+- * 8MiB NOR flash (Spansion S29GL064M90TFIR4)
+- *
+- * Layout as used by D-Link:
+- * 0x00000000-0x00010000 : "MTD1"
+- * 0x00010000-0x00020000 : "MTD2"
+- * 0x00020000-0x001a0000 : "Linux Kernel"
+- * 0x001a0000-0x007d0000 : "File System"
+- * 0x007d0000-0x00800000 : "u-boot"
+- */
+-
+-#define DNS323_NOR_BOOT_BASE 0xf4000000
+-#define DNS323_NOR_BOOT_SIZE SZ_8M
+-
+-static struct mtd_partition dns323_partitions[] = {
+- {
+- .name = "MTD1",
+- .size = 0x00010000,
+- .offset = 0,
+- }, {
+- .name = "MTD2",
+- .size = 0x00010000,
+- .offset = 0x00010000,
+- }, {
+- .name = "Linux Kernel",
+- .size = 0x00180000,
+- .offset = 0x00020000,
+- }, {
+- .name = "File System",
+- .size = 0x00630000,
+- .offset = 0x001A0000,
+- }, {
+- .name = "u-boot",
+- .size = 0x00030000,
+- .offset = 0x007d0000,
+- }
+-};
+-
+-static struct physmap_flash_data dns323_nor_flash_data = {
+- .width = 1,
+- .parts = dns323_partitions,
+- .nr_parts = ARRAY_SIZE(dns323_partitions)
+-};
+-
+-static struct resource dns323_nor_flash_resource = {
+- .flags = IORESOURCE_MEM,
+- .start = DNS323_NOR_BOOT_BASE,
+- .end = DNS323_NOR_BOOT_BASE + DNS323_NOR_BOOT_SIZE - 1,
+-};
+-
+-static struct platform_device dns323_nor_flash = {
+- .name = "physmap-flash",
+- .id = 0,
+- .dev = { .platform_data = &dns323_nor_flash_data, },
+- .resource = &dns323_nor_flash_resource,
+- .num_resources = 1,
+-};
+-
+-/****************************************************************************
+- * GPIO LEDs (simple - doesn't use hardware blinking support)
+- */
+-
+-static struct gpio_led dns323_leds[] = {
+- {
+- .name = "power:blue",
+- .gpio = DNS323_GPIO_LED_POWER,
+- .active_low = 1,
+- }, {
+- .name = "right:amber",
+- .gpio = DNS323_GPIO_LED_RIGHT_AMBER,
+- .active_low = 1,
+- }, {
+- .name = "left:amber",
+- .gpio = DNS323_GPIO_LED_LEFT_AMBER,
+- .active_low = 1,
+- },
+-};
+-
+-static struct gpio_led_platform_data dns323_led_data = {
+- .num_leds = ARRAY_SIZE(dns323_leds),
+- .leds = dns323_leds,
+-};
+-
+-static struct platform_device dns323_gpio_leds = {
+- .name = "leds-gpio",
+- .id = -1,
+- .dev = { .platform_data = &dns323_led_data, },
+-};
+-
+-/****************************************************************************
+- * GPIO Attached Keys
+- */
+-
+-static struct gpio_keys_button dns323_buttons[] = {
+- {
+- .code = KEY_RESTART,
+- .gpio = DNS323_GPIO_KEY_RESET,
+- .desc = "Reset Button",
+- .active_low = 1,
+- },
+- {
+- .code = KEY_POWER,
+- .gpio = DNS323_GPIO_KEY_POWER,
+- .desc = "Power Button",
+- .active_low = 1,
+- }
+-};
+-
+-static struct gpio_keys_platform_data dns323_button_data = {
+- .buttons = dns323_buttons,
+- .nbuttons = ARRAY_SIZE(dns323_buttons),
+-};
+-
+-static struct platform_device dns323_button_device = {
+- .name = "gpio-keys",
+- .id = -1,
+- .num_resources = 0,
+- .dev = { .platform_data = &dns323_button_data, },
+-};
+-
+-/****************************************************************************
+- * General Setup
+- */
+-
+-static struct platform_device *dns323_plat_devices[] __initdata = {
+- &dns323_nor_flash,
+- &dns323_gpio_leds,
+- &dns323_button_device,
+-};
+-
+-/*
+- * On the DNS-323 the following devices are attached via I2C:
+- *
+- * i2c addr | chip | description
+- * 0x3e | GMT G760Af | fan speed PWM controller
+- * 0x48 | GMT G751-2f | temp. sensor and therm. watchdog (LM75 compatible)
+- * 0x68 | ST M41T80 | RTC w/ alarm
+- */
+-static struct i2c_board_info __initdata dns323_i2c_devices[] = {
+- {
+- I2C_BOARD_INFO("g760a", 0x3e),
+- .type = "g760a",
+- },
+-#if 0
+- /* this entry requires the new-style driver model lm75 driver,
+- * for the meantime "insmod lm75.ko force_lm75=0,0x48" is needed */
+- {
+- I2C_BOARD_INFO("lm75", 0x48),
+- .type = "g751",
+- },
+-#endif
+- {
+- I2C_BOARD_INFO("rtc-m41t80", 0x68),
+- .type = "m41t80",
+- }
+-};
+-
+-/* DNS-323 specific power off method */
+-static void dns323_power_off(void)
+-{
+- pr_info("%s: triggering power-off...\n", __func__);
+- gpio_set_value(DNS323_GPIO_POWER_OFF, 1);
+-}
+-
+-static void __init dns323_init(void)
+-{
+- /* Setup basic Orion functions. Need to be called early. */
+- orion_init();
+-
+- /* setup flash mapping
+- * CS3 holds a 8 MB Spansion S29GL064M90TFIR4
+- */
+- orion_setup_cpu_win(ORION_DEV_BOOT, DNS323_NOR_BOOT_BASE,
+- DNS323_NOR_BOOT_SIZE, -1);
+-
+- /* DNS-323 has a Marvell 88X7042 SATA controller attached via PCIE
+- *
+- * Open a special address decode windows for the PCIE WA.
+- */
+- orion_write(ORION_REGS_VIRT_BASE | 0x20074, ORION_PCIE_WA_PHYS_BASE);
+- orion_write(ORION_REGS_VIRT_BASE | 0x20070,
+- (0x7941 | (((ORION_PCIE_WA_SIZE >> 16) - 1)) << 16));
+-
+- /* set MPP to 0 as D-Link's 2.6.12.6 kernel did */
+- orion_write(MPP_0_7_CTRL, 0);
+- orion_write(MPP_8_15_CTRL, 0);
+- orion_write(MPP_16_19_CTRL, 0);
+- orion_write(MPP_DEV_CTRL, 0);
+-
+- /* Define used GPIO pins
+-
+- GPIO Map:
+-
+- | 0 | | PEX_RST_OUT (not controlled by GPIO)
+- | 1 | Out | right amber LED (= sata ch0 LED) (low-active)
+- | 2 | Out | left amber LED (= sata ch1 LED) (low-active)
+- | 3 | Out | //unknown//
+- | 4 | Out | power button LED (low-active, together with pin #5)
+- | 5 | Out | power button LED (low-active, together with pin #4)
+- | 6 | In | GMT G751-2f overtemp. shutdown signal (low-active)
+- | 7 | In | M41T80 nIRQ/OUT/SQW signal
+- | 8 | Out | triggers power off (high-active)
+- | 9 | In | power button switch (low-active)
+- | 10 | In | reset button switch (low-active)
+- | 11 | Out | //unknown//
+- | 12 | Out | //unknown//
+- | 13 | Out | //unknown//
+- | 14 | Out | //unknown//
+- | 15 | Out | //unknown//
+- */
+- orion_gpio_set_valid_pins(0x07f6);
+-
+- /* register dns323 specific power-off method */
+- if ((gpio_request(DNS323_GPIO_POWER_OFF, "POWEROFF") != 0)
+- || (gpio_direction_output(DNS323_GPIO_POWER_OFF, 0) != 0))
+- pr_err("DNS323: failed to setup power-off GPIO\n");
+-
+- pm_power_off = dns323_power_off;
+-
+- /* register flash and other platform devices */
+- platform_add_devices(dns323_plat_devices,
+- ARRAY_SIZE(dns323_plat_devices));
+-
+- i2c_register_board_info(0, dns323_i2c_devices,
+- ARRAY_SIZE(dns323_i2c_devices));
+-
+- orion_eth_init(&dns323_eth_data);
+-}
+-
+-/* Warning: D-Link uses a wrong mach-type (=526) in their bootloader */
+-MACHINE_START(DNS323, "D-Link DNS-323")
+- /* Maintainer: Herbert Valerio Riedel <hvr at gnu.org> */
+- .phys_io = ORION_REGS_PHYS_BASE,
+- .io_pg_offst = ((ORION_REGS_VIRT_BASE) >> 18) & 0xFFFC,
+- .boot_params = 0x00000100,
+- .init_machine = dns323_init,
+- .map_io = orion_map_io,
+- .init_irq = orion_init_irq,
+- .timer = &orion_timer,
+- .fixup = tag_fixup_mem32,
+-MACHINE_END
+diff --git a/arch/arm/mach-orion/gpio.c b/arch/arm/mach-orion/gpio.c
+deleted file mode 100644
+index f713818..0000000
+--- a/arch/arm/mach-orion/gpio.c
++++ /dev/null
+@@ -1,225 +0,0 @@
+-/*
+- * arch/arm/mach-orion/gpio.c
+- *
+- * GPIO functions for Marvell Orion System On Chip
+- *
+- * Maintainer: Tzachi Perelstein <tzachi at marvell.com>
+- *
+- * This file is licensed under the terms of the GNU General Public
+- * License version 2. This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/module.h>
+-#include <linux/spinlock.h>
+-#include <linux/bitops.h>
+-#include <asm/gpio.h>
+-#include <asm/arch/orion.h>
+-#include "common.h"
+-
+-static DEFINE_SPINLOCK(gpio_lock);
+-static unsigned long gpio_valid[BITS_TO_LONGS(GPIO_MAX)];
+-static const char *gpio_label[GPIO_MAX]; /* non null for allocated GPIOs */
+-
+-void __init orion_gpio_set_valid_pins(u32 pins)
+-{
+- gpio_valid[0] = pins;
+-}
+-
+-/*
+- * GENERIC_GPIO primitives
+- */
+-int gpio_direction_input(unsigned pin)
+-{
+- unsigned long flags;
+-
+- if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
+- pr_debug("%s: invalid GPIO %d\n", __func__, pin);
+- return -EINVAL;
+- }
+-
+- spin_lock_irqsave(&gpio_lock, flags);
+-
+- /*
+- * Some callers might have not used the gpio_request(),
+- * so flag this pin as requested now.
+- */
+- if (!gpio_label[pin])
+- gpio_label[pin] = "?";
+-
+- orion_setbits(GPIO_IO_CONF, 1 << pin);
+-
+- spin_unlock_irqrestore(&gpio_lock, flags);
+- return 0;
+-}
+-EXPORT_SYMBOL(gpio_direction_input);
+-
+-int gpio_direction_output(unsigned pin, int value)
+-{
+- unsigned long flags;
+- int mask;
+-
+- if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
+- pr_debug("%s: invalid GPIO %d\n", __func__, pin);
+- return -EINVAL;
+- }
+-
+- spin_lock_irqsave(&gpio_lock, flags);
+-
+- /*
+- * Some callers might have not used the gpio_request(),
+- * so flag this pin as requested now.
+- */
+- if (!gpio_label[pin])
+- gpio_label[pin] = "?";
+-
+- mask = 1 << pin;
+- orion_clrbits(GPIO_BLINK_EN, mask);
+- if (value)
+- orion_setbits(GPIO_OUT, mask);
+- else
+- orion_clrbits(GPIO_OUT, mask);
+- orion_clrbits(GPIO_IO_CONF, mask);
+-
+- spin_unlock_irqrestore(&gpio_lock, flags);
+- return 0;
+-}
+-EXPORT_SYMBOL(gpio_direction_output);
+-
+-int gpio_get_value(unsigned pin)
+-{
+- int val, mask = 1 << pin;
+-
+- if (orion_read(GPIO_IO_CONF) & mask)
+- val = orion_read(GPIO_DATA_IN) ^ orion_read(GPIO_IN_POL);
+- else
+- val = orion_read(GPIO_OUT);
+-
+- return val & mask;
+-}
+-EXPORT_SYMBOL(gpio_get_value);
+-
+-void gpio_set_value(unsigned pin, int value)
+-{
+- unsigned long flags;
+- int mask = 1 << pin;
+-
+- spin_lock_irqsave(&gpio_lock, flags);
+-
+- orion_clrbits(GPIO_BLINK_EN, mask);
+- if (value)
+- orion_setbits(GPIO_OUT, mask);
+- else
+- orion_clrbits(GPIO_OUT, mask);
+-
+- spin_unlock_irqrestore(&gpio_lock, flags);
+-}
+-EXPORT_SYMBOL(gpio_set_value);
+-
+-void orion_gpio_set_blink(unsigned pin, int blink)
+-{
+- unsigned long flags;
+- int mask = 1 << pin;
+-
+- spin_lock_irqsave(&gpio_lock, flags);
+-
+- orion_clrbits(GPIO_OUT, mask);
+- if (blink)
+- orion_setbits(GPIO_BLINK_EN, mask);
+- else
+- orion_clrbits(GPIO_BLINK_EN, mask);
+-
+- spin_unlock_irqrestore(&gpio_lock, flags);
+-}
+-EXPORT_SYMBOL(orion_gpio_set_blink);
+-
+-int gpio_request(unsigned pin, const char *label)
+-{
+- int ret = 0;
+- unsigned long flags;
+-
+- if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
+- pr_debug("%s: invalid GPIO %d\n", __func__, pin);
+- return -EINVAL;
+- }
+-
+- spin_lock_irqsave(&gpio_lock, flags);
+-
+- if (gpio_label[pin]) {
+- pr_debug("%s: GPIO %d already used as %s\n",
+- __func__, pin, gpio_label[pin]);
+- ret = -EBUSY;
+- } else
+- gpio_label[pin] = label ? label : "?";
+-
+- spin_unlock_irqrestore(&gpio_lock, flags);
+- return ret;
+-}
+-EXPORT_SYMBOL(gpio_request);
+-
+-void gpio_free(unsigned pin)
+-{
+- if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
+- pr_debug("%s: invalid GPIO %d\n", __func__, pin);
+- return;
+- }
+-
+- if (!gpio_label[pin])
+- pr_warning("%s: GPIO %d already freed\n", __func__, pin);
+- else
+- gpio_label[pin] = NULL;
+-}
+-EXPORT_SYMBOL(gpio_free);
+-
+-/* Debug helper */
+-void gpio_display(void)
+-{
+- int i;
+-
+- for (i = 0; i < GPIO_MAX; i++) {
+- printk(KERN_DEBUG "Pin-%d: ", i);
+-
+- if (!test_bit(i, gpio_valid)) {
+- printk("non-GPIO\n");
+- } else if (!gpio_label[i]) {
+- printk("GPIO, free\n");
+- } else {
+- printk("GPIO, used by %s, ", gpio_label[i]);
+- if (orion_read(GPIO_IO_CONF) & (1 << i)) {
+- printk("input, active %s, level %s, edge %s\n",
+- ((orion_read(GPIO_IN_POL) >> i) & 1) ? "low" : "high",
+- ((orion_read(GPIO_LEVEL_MASK) >> i) & 1) ? "enabled" : "masked",
+- ((orion_read(GPIO_EDGE_MASK) >> i) & 1) ? "enabled" : "masked");
+- } else {
+- printk("output, val=%d\n", (orion_read(GPIO_OUT) >> i) & 1);
+- }
+- }
+- }
+-
+- printk(KERN_DEBUG "MPP_0_7_CTRL (0x%08x) = 0x%08x\n",
+- MPP_0_7_CTRL, orion_read(MPP_0_7_CTRL));
+- printk(KERN_DEBUG "MPP_8_15_CTRL (0x%08x) = 0x%08x\n",
+- MPP_8_15_CTRL, orion_read(MPP_8_15_CTRL));
+- printk(KERN_DEBUG "MPP_16_19_CTRL (0x%08x) = 0x%08x\n",
+- MPP_16_19_CTRL, orion_read(MPP_16_19_CTRL));
+- printk(KERN_DEBUG "MPP_DEV_CTRL (0x%08x) = 0x%08x\n",
+- MPP_DEV_CTRL, orion_read(MPP_DEV_CTRL));
+- printk(KERN_DEBUG "GPIO_OUT (0x%08x) = 0x%08x\n",
+- GPIO_OUT, orion_read(GPIO_OUT));
+- printk(KERN_DEBUG "GPIO_IO_CONF (0x%08x) = 0x%08x\n",
+- GPIO_IO_CONF, orion_read(GPIO_IO_CONF));
+- printk(KERN_DEBUG "GPIO_BLINK_EN (0x%08x) = 0x%08x\n",
+- GPIO_BLINK_EN, orion_read(GPIO_BLINK_EN));
+- printk(KERN_DEBUG "GPIO_IN_POL (0x%08x) = 0x%08x\n",
+- GPIO_IN_POL, orion_read(GPIO_IN_POL));
+- printk(KERN_DEBUG "GPIO_DATA_IN (0x%08x) = 0x%08x\n",
+- GPIO_DATA_IN, orion_read(GPIO_DATA_IN));
+- printk(KERN_DEBUG "GPIO_LEVEL_MASK (0x%08x) = 0x%08x\n",
+- GPIO_LEVEL_MASK, orion_read(GPIO_LEVEL_MASK));
+- printk(KERN_DEBUG "GPIO_EDGE_CAUSE (0x%08x) = 0x%08x\n",
+- GPIO_EDGE_CAUSE, orion_read(GPIO_EDGE_CAUSE));
+- printk(KERN_DEBUG "GPIO_EDGE_MASK (0x%08x) = 0x%08x\n",
+- GPIO_EDGE_MASK, orion_read(GPIO_EDGE_MASK));
+-}
+diff --git a/arch/arm/mach-orion/irq.c b/arch/arm/mach-orion/irq.c
+deleted file mode 100644
+index df7e12a..0000000
+--- a/arch/arm/mach-orion/irq.c
++++ /dev/null
+@@ -1,241 +0,0 @@
+-/*
+- * arch/arm/mach-orion/irq.c
+- *
+- * Core IRQ functions for Marvell Orion System On Chip
+- *
+- * Maintainer: Tzachi Perelstein <tzachi at marvell.com>
+- *
+- * This file is licensed under the terms of the GNU General Public
+- * License version 2. This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/irq.h>
+-#include <asm/gpio.h>
+-#include <asm/arch/orion.h>
+-#include "common.h"
+-
+-/*****************************************************************************
+- * Orion GPIO IRQ
+- *
+- * GPIO_IN_POL register controlls whether GPIO_DATA_IN will hold the same
+- * value of the line or the opposite value.
+- *
+- * Level IRQ handlers: DATA_IN is used directly as cause register.
+- * Interrupt are masked by LEVEL_MASK registers.
+- * Edge IRQ handlers: Change in DATA_IN are latched in EDGE_CAUSE.
+- * Interrupt are masked by EDGE_MASK registers.
+- * Both-edge handlers: Similar to regular Edge handlers, but also swaps
+- * the polarity to catch the next line transaction.
+- * This is a race condition that might not perfectly
+- * work on some use cases.
+- *
+- * Every eight GPIO lines are grouped (OR'ed) before going up to main
+- * cause register.
+- *
+- * EDGE cause mask
+- * data-in /--------| |-----| |----\
+- * -----| |----- ---- to main cause reg
+- * X \----------------| |----/
+- * polarity LEVEL mask
+- *
+- ****************************************************************************/
+-static void orion_gpio_irq_ack(u32 irq)
+-{
+- int pin = irq_to_gpio(irq);
+- if (irq_desc[irq].status & IRQ_LEVEL)
+- /*
+- * Mask bit for level interrupt
+- */
+- orion_clrbits(GPIO_LEVEL_MASK, 1 << pin);
+- else
+- /*
+- * Clear casue bit for egde interrupt
+- */
+- orion_clrbits(GPIO_EDGE_CAUSE, 1 << pin);
+-}
+-
+-static void orion_gpio_irq_mask(u32 irq)
+-{
+- int pin = irq_to_gpio(irq);
+- if (irq_desc[irq].status & IRQ_LEVEL)
+- orion_clrbits(GPIO_LEVEL_MASK, 1 << pin);
+- else
+- orion_clrbits(GPIO_EDGE_MASK, 1 << pin);
+-}
+-
+-static void orion_gpio_irq_unmask(u32 irq)
+-{
+- int pin = irq_to_gpio(irq);
+- if (irq_desc[irq].status & IRQ_LEVEL)
+- orion_setbits(GPIO_LEVEL_MASK, 1 << pin);
+- else
+- orion_setbits(GPIO_EDGE_MASK, 1 << pin);
+-}
+-
+-static int orion_gpio_set_irq_type(u32 irq, u32 type)
+-{
+- int pin = irq_to_gpio(irq);
+- struct irq_desc *desc;
+-
+- if ((orion_read(GPIO_IO_CONF) & (1 << pin)) == 0) {
+- printk(KERN_ERR "orion_gpio_set_irq_type failed "
+- "(irq %d, pin %d).\n", irq, pin);
+- return -EINVAL;
+- }
+-
+- desc = irq_desc + irq;
+-
+- switch (type) {
+- case IRQT_HIGH:
+- desc->handle_irq = handle_level_irq;
+- desc->status |= IRQ_LEVEL;
+- orion_clrbits(GPIO_IN_POL, (1 << pin));
+- break;
+- case IRQT_LOW:
+- desc->handle_irq = handle_level_irq;
+- desc->status |= IRQ_LEVEL;
+- orion_setbits(GPIO_IN_POL, (1 << pin));
+- break;
+- case IRQT_RISING:
+- desc->handle_irq = handle_edge_irq;
+- desc->status &= ~IRQ_LEVEL;
+- orion_clrbits(GPIO_IN_POL, (1 << pin));
+- break;
+- case IRQT_FALLING:
+- desc->handle_irq = handle_edge_irq;
+- desc->status &= ~IRQ_LEVEL;
+- orion_setbits(GPIO_IN_POL, (1 << pin));
+- break;
+- case IRQT_BOTHEDGE:
+- desc->handle_irq = handle_edge_irq;
+- desc->status &= ~IRQ_LEVEL;
+- /*
+- * set initial polarity based on current input level
+- */
+- if ((orion_read(GPIO_IN_POL) ^ orion_read(GPIO_DATA_IN))
+- & (1 << pin))
+- orion_setbits(GPIO_IN_POL, (1 << pin)); /* falling */
+- else
+- orion_clrbits(GPIO_IN_POL, (1 << pin)); /* rising */
+-
+- break;
+- default:
+- printk(KERN_ERR "failed to set irq=%d (type=%d)\n", irq, type);
+- return -EINVAL;
+- }
+-
+- desc->status &= ~IRQ_TYPE_SENSE_MASK;
+- desc->status |= type & IRQ_TYPE_SENSE_MASK;
+-
+- return 0;
+-}
+-
+-static struct irq_chip orion_gpio_irq_chip = {
+- .name = "Orion-IRQ-GPIO",
+- .ack = orion_gpio_irq_ack,
+- .mask = orion_gpio_irq_mask,
+- .unmask = orion_gpio_irq_unmask,
+- .set_type = orion_gpio_set_irq_type,
+-};
+-
+-static void orion_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+-{
+- u32 cause, offs, pin;
+-
+- BUG_ON(irq < IRQ_ORION_GPIO_0_7 || irq > IRQ_ORION_GPIO_24_31);
+- offs = (irq - IRQ_ORION_GPIO_0_7) * 8;
+- cause = (orion_read(GPIO_DATA_IN) & orion_read(GPIO_LEVEL_MASK)) |
+- (orion_read(GPIO_EDGE_CAUSE) & orion_read(GPIO_EDGE_MASK));
+-
+- for (pin = offs; pin < offs + 8; pin++) {
+- if (cause & (1 << pin)) {
+- irq = gpio_to_irq(pin);
+- desc = irq_desc + irq;
+- if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQT_BOTHEDGE) {
+- /* Swap polarity (race with GPIO line) */
+- u32 polarity = orion_read(GPIO_IN_POL);
+- polarity ^= 1 << pin;
+- orion_write(GPIO_IN_POL, polarity);
+- }
+- desc_handle_irq(irq, desc);
+- }
+- }
+-}
+-
+-static void __init orion_init_gpio_irq(void)
+-{
+- int i;
+- struct irq_desc *desc;
+-
+- /*
+- * Mask and clear GPIO IRQ interrupts
+- */
+- orion_write(GPIO_LEVEL_MASK, 0x0);
+- orion_write(GPIO_EDGE_MASK, 0x0);
+- orion_write(GPIO_EDGE_CAUSE, 0x0);
+-
+- /*
+- * Register chained level handlers for GPIO IRQs by default.
+- * User can use set_type() if he wants to use edge types handlers.
+- */
+- for (i = IRQ_ORION_GPIO_START; i < NR_IRQS; i++) {
+- set_irq_chip(i, &orion_gpio_irq_chip);
+- set_irq_handler(i, handle_level_irq);
+- desc = irq_desc + i;
+- desc->status |= IRQ_LEVEL;
+- set_irq_flags(i, IRQF_VALID);
+- }
+- set_irq_chained_handler(IRQ_ORION_GPIO_0_7, orion_gpio_irq_handler);
+- set_irq_chained_handler(IRQ_ORION_GPIO_8_15, orion_gpio_irq_handler);
+- set_irq_chained_handler(IRQ_ORION_GPIO_16_23, orion_gpio_irq_handler);
+- set_irq_chained_handler(IRQ_ORION_GPIO_24_31, orion_gpio_irq_handler);
+-}
+-
+-/*****************************************************************************
+- * Orion Main IRQ
+- ****************************************************************************/
+-static void orion_main_irq_mask(u32 irq)
+-{
+- orion_clrbits(MAIN_IRQ_MASK, 1 << irq);
+-}
+-
+-static void orion_main_irq_unmask(u32 irq)
+-{
+- orion_setbits(MAIN_IRQ_MASK, 1 << irq);
+-}
+-
+-static struct irq_chip orion_main_irq_chip = {
+- .name = "Orion-IRQ-Main",
+- .ack = orion_main_irq_mask,
+- .mask = orion_main_irq_mask,
+- .unmask = orion_main_irq_unmask,
+-};
+-
+-static void __init orion_init_main_irq(void)
+-{
+- int i;
+-
+- /*
+- * Mask and clear Main IRQ interrupts
+- */
+- orion_write(MAIN_IRQ_MASK, 0x0);
+- orion_write(MAIN_IRQ_CAUSE, 0x0);
+-
+- /*
+- * Register level handler for Main IRQs
+- */
+- for (i = 0; i < IRQ_ORION_GPIO_START; i++) {
+- set_irq_chip(i, &orion_main_irq_chip);
+- set_irq_handler(i, handle_level_irq);
+- set_irq_flags(i, IRQF_VALID);
+- }
+-}
+-
+-void __init orion_init_irq(void)
+-{
+- orion_init_main_irq();
+- orion_init_gpio_irq();
+-}
+diff --git a/arch/arm/mach-orion/kurobox_pro-setup.c b/arch/arm/mach-orion/kurobox_pro-setup.c
+deleted file mode 100644
+index 785a07b..0000000
+--- a/arch/arm/mach-orion/kurobox_pro-setup.c
++++ /dev/null
+@@ -1,244 +0,0 @@
+-/*
+- * arch/arm/mach-orion/kurobox_pro-setup.c
+- *
+- * Maintainer: Ronen Shitrit <rshitrit at marvell.com>
+- *
+- * This file is licensed under the terms of the GNU General Public
+- * License version 2. This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/platform_device.h>
+-#include <linux/pci.h>
+-#include <linux/irq.h>
+-#include <linux/mtd/physmap.h>
+-#include <linux/mtd/nand.h>
+-#include <linux/mv643xx_eth.h>
+-#include <linux/i2c.h>
+-#include <linux/ata_platform.h>
+-#include <asm/mach-types.h>
+-#include <asm/gpio.h>
+-#include <asm/mach/arch.h>
+-#include <asm/mach/pci.h>
+-#include <asm/arch/orion.h>
+-#include <asm/arch/platform.h>
+-#include "common.h"
+-
+-/*****************************************************************************
+- * KUROBOX-PRO Info
+- ****************************************************************************/
+-
+-/*
+- * 256K NOR flash Device bus boot chip select
+- */
+-
+-#define KUROBOX_PRO_NOR_BOOT_BASE 0xf4000000
+-#define KUROBOX_PRO_NOR_BOOT_SIZE SZ_256K
+-
+-/*
+- * 256M NAND flash on Device bus chip select 1
+- */
+-
+-#define KUROBOX_PRO_NAND_BASE 0xfc000000
+-#define KUROBOX_PRO_NAND_SIZE SZ_2M
+-
+-/*****************************************************************************
+- * 256MB NAND Flash on Device bus CS0
+- ****************************************************************************/
+-
+-static struct mtd_partition kurobox_pro_nand_parts[] = {
+- {
+- .name = "uImage",
+- .offset = 0,
+- .size = SZ_4M,
+- },
+- {
+- .name = "rootfs",
+- .offset = SZ_4M,
+- .size = SZ_64M,
+- },
+- {
+- .name = "extra",
+- .offset = SZ_4M + SZ_64M,
+- .size = SZ_256M - (SZ_4M + SZ_64M),
+- },
+-};
+-
+-static struct resource kurobox_pro_nand_resource = {
+- .flags = IORESOURCE_MEM,
+- .start = KUROBOX_PRO_NAND_BASE,
+- .end = KUROBOX_PRO_NAND_BASE + KUROBOX_PRO_NAND_SIZE - 1,
+-};
+-
+-static struct orion_nand_data kurobox_pro_nand_data = {
+- .parts = kurobox_pro_nand_parts,
+- .nr_parts = ARRAY_SIZE(kurobox_pro_nand_parts),
+- .cle = 0,
+- .ale = 1,
+- .width = 8,
+-};
+-
+-static struct platform_device kurobox_pro_nand_flash = {
+- .name = "orion_nand",
+- .id = -1,
+- .dev = {
+- .platform_data = &kurobox_pro_nand_data,
+- },
+- .resource = &kurobox_pro_nand_resource,
+- .num_resources = 1,
+-};
+-
+-/*****************************************************************************
+- * 256KB NOR Flash on BOOT Device
+- ****************************************************************************/
+-
+-static struct physmap_flash_data kurobox_pro_nor_flash_data = {
+- .width = 1,
+-};
+-
+-static struct resource kurobox_pro_nor_flash_resource = {
+- .flags = IORESOURCE_MEM,
+- .start = KUROBOX_PRO_NOR_BOOT_BASE,
+- .end = KUROBOX_PRO_NOR_BOOT_BASE + KUROBOX_PRO_NOR_BOOT_SIZE - 1,
+-};
+-
+-static struct platform_device kurobox_pro_nor_flash = {
+- .name = "physmap-flash",
+- .id = 0,
+- .dev = {
+- .platform_data = &kurobox_pro_nor_flash_data,
+- },
+- .num_resources = 1,
+- .resource = &kurobox_pro_nor_flash_resource,
+-};
+-
+-/*****************************************************************************
+- * PCI
+- ****************************************************************************/
+-
+-static int __init kurobox_pro_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+-{
+- /*
+- * PCI isn't used on the Kuro
+- */
+- if (dev->bus->number == orion_pcie_local_bus_nr())
+- return IRQ_ORION_PCIE0_INT;
+- else
+- printk(KERN_ERR "kurobox_pro_pci_map_irq failed, unknown bus\n");
+-
+- return -1;
+-}
+-
+-static struct hw_pci kurobox_pro_pci __initdata = {
+- .nr_controllers = 1,
+- .swizzle = pci_std_swizzle,
+- .setup = orion_pci_sys_setup,
+- .scan = orion_pci_sys_scan_bus,
+- .map_irq = kurobox_pro_pci_map_irq,
+-};
+-
+-static int __init kurobox_pro_pci_init(void)
+-{
+- if (machine_is_kurobox_pro())
+- pci_common_init(&kurobox_pro_pci);
+-
+- return 0;
+-}
+-
+-subsys_initcall(kurobox_pro_pci_init);
+-
+-/*****************************************************************************
+- * Ethernet
+- ****************************************************************************/
+-
+-static struct mv643xx_eth_platform_data kurobox_pro_eth_data = {
+- .phy_addr = 8,
+- .force_phy_addr = 1,
+-};
+-
+-/*****************************************************************************
+- * RTC 5C372a on I2C bus
+- ****************************************************************************/
+-static struct i2c_board_info __initdata kurobox_pro_i2c_rtc = {
+- .driver_name = "rtc-rs5c372",
+- .type = "rs5c372a",
+- .addr = 0x32,
+-};
+-
+-/*****************************************************************************
+- * SATA
+- ****************************************************************************/
+-static struct mv_sata_platform_data kurobox_pro_sata_data = {
+- .n_ports = 2,
+-};
+-
+-/*****************************************************************************
+- * General Setup
+- ****************************************************************************/
+-
+-static struct platform_device *kurobox_pro_devices[] __initdata = {
+- &kurobox_pro_nor_flash,
+- &kurobox_pro_nand_flash,
+-};
+-
+-static void __init kurobox_pro_init(void)
+-{
+- /*
+- * Setup basic Orion functions. Need to be called early.
+- */
+- orion_init();
+-
+- /*
+- * Setup the CPU address decode windows for our devices
+- */
+- orion_setup_cpu_win(ORION_DEV_BOOT, KUROBOX_PRO_NOR_BOOT_BASE,
+- KUROBOX_PRO_NOR_BOOT_SIZE, -1);
+- orion_setup_cpu_win(ORION_DEV0, KUROBOX_PRO_NAND_BASE,
+- KUROBOX_PRO_NAND_SIZE, -1);
+- /*
+- * Open a special address decode windows for the PCIE WA.
+- */
+- orion_write(ORION_REGS_VIRT_BASE | 0x20074, ORION_PCIE_WA_PHYS_BASE);
+- orion_write(ORION_REGS_VIRT_BASE | 0x20070, (0x7941 |
+- (((ORION_PCIE_WA_SIZE >> 16) - 1)) << 16));
+-
+- /*
+- * Setup Multiplexing Pins --
+- * MPP[0-1] Not used
+- * MPP[2] GPIO Micon
+- * MPP[3] GPIO RTC
+- * MPP[4-5] Not used
+- * MPP[6] Nand Flash REn
+- * MPP[7] Nand Flash WEn
+- * MPP[8-11] Not used
+- * MPP[12] SATA 0 presence Indication
+- * MPP[13] SATA 1 presence Indication
+- * MPP[14] SATA 0 active Indication
+- * MPP[15] SATA 1 active indication
+- * MPP[16-19] Not used
+- */
+- orion_write(MPP_0_7_CTRL, 0x44220003);
+- orion_write(MPP_8_15_CTRL, 0x55550000);
+- orion_write(MPP_16_19_CTRL, 0x0);
+-
+- orion_gpio_set_valid_pins(0x0000000c);
+-
+- platform_add_devices(kurobox_pro_devices, ARRAY_SIZE(kurobox_pro_devices));
+- i2c_register_board_info(0, &kurobox_pro_i2c_rtc, 1);
+- orion_eth_init(&kurobox_pro_eth_data);
+- orion_sata_init(&kurobox_pro_sata_data);
+-}
+-
+-MACHINE_START(KUROBOX_PRO, "Buffalo/Revogear Kurobox Pro")
+- /* Maintainer: Ronen Shitrit <rshitrit at marvell.com> */
+- .phys_io = ORION_REGS_PHYS_BASE,
+- .io_pg_offst = ((ORION_REGS_VIRT_BASE) >> 18) & 0xFFFC,
+- .boot_params = 0x00000100,
+- .init_machine = kurobox_pro_init,
+- .map_io = orion_map_io,
+- .init_irq = orion_init_irq,
+- .timer = &orion_timer,
+- .fixup = tag_fixup_mem32,
+-MACHINE_END
+diff --git a/arch/arm/mach-orion/pci.c b/arch/arm/mach-orion/pci.c
+deleted file mode 100644
+index b109bb4..0000000
+--- a/arch/arm/mach-orion/pci.c
++++ /dev/null
+@@ -1,557 +0,0 @@
+-/*
+- * arch/arm/mach-orion/pci.c
+- *
+- * PCI and PCIE functions for Marvell Orion System On Chip
+- *
+- * Maintainer: Tzachi Perelstein <tzachi at marvell.com>
+- *
+- * This file is licensed under the terms of the GNU General Public
+- * License version 2. This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/pci.h>
+-#include <asm/mach/pci.h>
+-#include "common.h"
+-
+-/*****************************************************************************
+- * Orion has one PCIE controller and one PCI controller.
+- *
+- * Note1: The local PCIE bus number is '0'. The local PCI bus number
+- * follows the scanned PCIE bridged busses, if any.
+- *
+- * Note2: It is possible for PCI/PCIE agents to access many subsystem's
+- * space, by configuring BARs and Address Decode Windows, e.g. flashes on
+- * device bus, Orion registers, etc. However this code only enable the
+- * access to DDR banks.
+- ****************************************************************************/
+-
+-
+-/*****************************************************************************
+- * PCIE controller
+- ****************************************************************************/
+-#define PCIE_CTRL ORION_PCIE_REG(0x1a00)
+-#define PCIE_STAT ORION_PCIE_REG(0x1a04)
+-#define PCIE_DEV_ID ORION_PCIE_REG(0x0000)
+-#define PCIE_CMD_STAT ORION_PCIE_REG(0x0004)
+-#define PCIE_DEV_REV ORION_PCIE_REG(0x0008)
+-#define PCIE_MASK ORION_PCIE_REG(0x1910)
+-#define PCIE_CONF_ADDR ORION_PCIE_REG(0x18f8)
+-#define PCIE_CONF_DATA ORION_PCIE_REG(0x18fc)
+-
+-/*
+- * PCIE_STAT bits
+- */
+-#define PCIE_STAT_LINK_DOWN 1
+-#define PCIE_STAT_BUS_OFFS 8
+-#define PCIE_STAT_BUS_MASK (0xff << PCIE_STAT_BUS_OFFS)
+-#define PCIE_STAT_DEV_OFFS 20
+-#define PCIE_STAT_DEV_MASK (0x1f << PCIE_STAT_DEV_OFFS)
+-
+-/*
+- * PCIE_CONF_ADDR bits
+- */
+-#define PCIE_CONF_REG(r) ((((r) & 0xf00) << 24) | ((r) & 0xfc))
+-#define PCIE_CONF_FUNC(f) (((f) & 0x3) << 8)
+-#define PCIE_CONF_DEV(d) (((d) & 0x1f) << 11)
+-#define PCIE_CONF_BUS(b) (((b) & 0xff) << 16)
+-#define PCIE_CONF_ADDR_EN (1 << 31)
+-
+-/*
+- * PCIE config cycles are done by programming the PCIE_CONF_ADDR register
+- * and then reading the PCIE_CONF_DATA register. Need to make sure these
+- * transactions are atomic.
+- */
+-static DEFINE_SPINLOCK(orion_pcie_lock);
+-
+-void orion_pcie_id(u32 *dev, u32 *rev)
+-{
+- *dev = orion_read(PCIE_DEV_ID) >> 16;
+- *rev = orion_read(PCIE_DEV_REV) & 0xff;
+-}
+-
+-u32 orion_pcie_local_bus_nr(void)
+-{
+- u32 stat = orion_read(PCIE_STAT);
+- return((stat & PCIE_STAT_BUS_MASK) >> PCIE_STAT_BUS_OFFS);
+-}
+-
+-static u32 orion_pcie_local_dev_nr(void)
+-{
+- u32 stat = orion_read(PCIE_STAT);
+- return((stat & PCIE_STAT_DEV_MASK) >> PCIE_STAT_DEV_OFFS);
+-}
+-
+-static u32 orion_pcie_no_link(void)
+-{
+- u32 stat = orion_read(PCIE_STAT);
+- return(stat & PCIE_STAT_LINK_DOWN);
+-}
+-
+-static void orion_pcie_set_bus_nr(int nr)
+-{
+- orion_clrbits(PCIE_STAT, PCIE_STAT_BUS_MASK);
+- orion_setbits(PCIE_STAT, nr << PCIE_STAT_BUS_OFFS);
+-}
+-
+-static void orion_pcie_master_slave_enable(void)
+-{
+- orion_setbits(PCIE_CMD_STAT, PCI_COMMAND_MASTER |
+- PCI_COMMAND_IO |
+- PCI_COMMAND_MEMORY);
+-}
+-
+-static void orion_pcie_enable_interrupts(void)
+-{
+- /*
+- * Enable interrupts lines
+- * INTA[24] INTB[25] INTC[26] INTD[27]
+- */
+- orion_setbits(PCIE_MASK, 0xf<<24);
+-}
+-
+-static int orion_pcie_valid_config(u32 bus, u32 dev)
+-{
+- /*
+- * Don't go out when trying to access --
+- * 1. our own device
+- * 2. where there's no device connected (no link)
+- * 3. nonexisting devices on local bus
+- */
+-
+- if ((orion_pcie_local_bus_nr() == bus) &&
+- (orion_pcie_local_dev_nr() == dev))
+- return 0;
+-
+- if (orion_pcie_no_link())
+- return 0;
+-
+- if (bus == orion_pcie_local_bus_nr())
+- if (((orion_pcie_local_dev_nr() == 0) && (dev != 1)) ||
+- ((orion_pcie_local_dev_nr() != 0) && (dev != 0)))
+- return 0;
+-
+- return 1;
+-}
+-
+-static int orion_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
+- int size, u32 *val)
+-{
+- unsigned long flags;
+- unsigned int dev, rev, pcie_addr;
+-
+- if (orion_pcie_valid_config(bus->number, PCI_SLOT(devfn)) == 0) {
+- *val = 0xffffffff;
+- return PCIBIOS_DEVICE_NOT_FOUND;
+- }
+-
+- spin_lock_irqsave(&orion_pcie_lock, flags);
+-
+- orion_write(PCIE_CONF_ADDR, PCIE_CONF_BUS(bus->number) |
+- PCIE_CONF_DEV(PCI_SLOT(devfn)) |
+- PCIE_CONF_FUNC(PCI_FUNC(devfn)) |
+- PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN);
+-
+- orion_pcie_id(&dev, &rev);
+- if (dev == MV88F5181_DEV_ID || dev == MV88F5182_DEV_ID) {
+- /* extended register space */
+- pcie_addr = ORION_PCIE_WA_VIRT_BASE;
+- pcie_addr |= PCIE_CONF_BUS(bus->number) |
+- PCIE_CONF_DEV(PCI_SLOT(devfn)) |
+- PCIE_CONF_FUNC(PCI_FUNC(devfn)) |
+- PCIE_CONF_REG(where);
+- *val = orion_read(pcie_addr);
+- } else
+- *val = orion_read(PCIE_CONF_DATA);
+-
+- if (size == 1)
+- *val = (*val >> (8*(where & 0x3))) & 0xff;
+- else if (size == 2)
+- *val = (*val >> (8*(where & 0x3))) & 0xffff;
+-
+- spin_unlock_irqrestore(&orion_pcie_lock, flags);
+-
+- return PCIBIOS_SUCCESSFUL;
+-}
+-
+-
+-static int orion_pcie_wr_conf(struct pci_bus *bus, u32 devfn, int where,
+- int size, u32 val)
+-{
+- unsigned long flags;
+- int ret;
+-
+- if (orion_pcie_valid_config(bus->number, PCI_SLOT(devfn)) == 0)
+- return PCIBIOS_DEVICE_NOT_FOUND;
+-
+- spin_lock_irqsave(&orion_pcie_lock, flags);
+-
+- ret = PCIBIOS_SUCCESSFUL;
+-
+- orion_write(PCIE_CONF_ADDR, PCIE_CONF_BUS(bus->number) |
+- PCIE_CONF_DEV(PCI_SLOT(devfn)) |
+- PCIE_CONF_FUNC(PCI_FUNC(devfn)) |
+- PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN);
+-
+- if (size == 4) {
+- __raw_writel(val, PCIE_CONF_DATA);
+- } else if (size == 2) {
+- __raw_writew(val, PCIE_CONF_DATA + (where & 0x3));
+- } else if (size == 1) {
+- __raw_writeb(val, PCIE_CONF_DATA + (where & 0x3));
+- } else {
+- ret = PCIBIOS_BAD_REGISTER_NUMBER;
+- }
+-
+- spin_unlock_irqrestore(&orion_pcie_lock, flags);
+-
+- return ret;
+-}
+-
+-struct pci_ops orion_pcie_ops = {
+- .read = orion_pcie_rd_conf,
+- .write = orion_pcie_wr_conf,
+-};
+-
+-
+-static int orion_pcie_setup(struct pci_sys_data *sys)
+-{
+- struct resource *res;
+-
+- /*
+- * Master + Slave enable
+- */
+- orion_pcie_master_slave_enable();
+-
+- /*
+- * Enable interrupts lines A-D
+- */
+- orion_pcie_enable_interrupts();
+-
+- /*
+- * Request resource
+- */
+- res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
+- if (!res)
+- panic("orion_pci_setup unable to alloc resources");
+-
+- /*
+- * IORESOURCE_IO
+- */
+- res[0].name = "PCI-EX I/O Space";
+- res[0].flags = IORESOURCE_IO;
+- res[0].start = ORION_PCIE_IO_BUS_BASE;
+- res[0].end = res[0].start + ORION_PCIE_IO_SIZE - 1;
+- if (request_resource(&ioport_resource, &res[0]))
+- panic("Request PCIE IO resource failed\n");
+- sys->resource[0] = &res[0];
+-
+- /*
+- * IORESOURCE_MEM
+- */
+- res[1].name = "PCI-EX Memory Space";
+- res[1].flags = IORESOURCE_MEM;
+- res[1].start = ORION_PCIE_MEM_PHYS_BASE;
+- res[1].end = res[1].start + ORION_PCIE_MEM_SIZE - 1;
+- if (request_resource(&iomem_resource, &res[1]))
+- panic("Request PCIE Memory resource failed\n");
+- sys->resource[1] = &res[1];
+-
+- sys->resource[2] = NULL;
+- sys->io_offset = 0;
+-
+- return 1;
+-}
+-
+-/*****************************************************************************
+- * PCI controller
+- ****************************************************************************/
+-#define PCI_MODE ORION_PCI_REG(0xd00)
+-#define PCI_CMD ORION_PCI_REG(0xc00)
+-#define PCI_P2P_CONF ORION_PCI_REG(0x1d14)
+-#define PCI_CONF_ADDR ORION_PCI_REG(0xc78)
+-#define PCI_CONF_DATA ORION_PCI_REG(0xc7c)
+-
+-/*
+- * PCI_MODE bits
+- */
+-#define PCI_MODE_64BIT (1 << 2)
+-#define PCI_MODE_PCIX ((1 << 4) | (1 << 5))
+-
+-/*
+- * PCI_CMD bits
+- */
+-#define PCI_CMD_HOST_REORDER (1 << 29)
+-
+-/*
+- * PCI_P2P_CONF bits
+- */
+-#define PCI_P2P_BUS_OFFS 16
+-#define PCI_P2P_BUS_MASK (0xff << PCI_P2P_BUS_OFFS)
+-#define PCI_P2P_DEV_OFFS 24
+-#define PCI_P2P_DEV_MASK (0x1f << PCI_P2P_DEV_OFFS)
+-
+-/*
+- * PCI_CONF_ADDR bits
+- */
+-#define PCI_CONF_REG(reg) ((reg) & 0xfc)
+-#define PCI_CONF_FUNC(func) (((func) & 0x3) << 8)
+-#define PCI_CONF_DEV(dev) (((dev) & 0x1f) << 11)
+-#define PCI_CONF_BUS(bus) (((bus) & 0xff) << 16)
+-#define PCI_CONF_ADDR_EN (1 << 31)
+-
+-/*
+- * Internal configuration space
+- */
+-#define PCI_CONF_FUNC_STAT_CMD 0
+-#define PCI_CONF_REG_STAT_CMD 4
+-#define PCIX_STAT 0x64
+-#define PCIX_STAT_BUS_OFFS 8
+-#define PCIX_STAT_BUS_MASK (0xff << PCIX_STAT_BUS_OFFS)
+-
+-/*
+- * PCI config cycles are done by programming the PCI_CONF_ADDR register
+- * and then reading the PCI_CONF_DATA register. Need to make sure these
+- * transactions are atomic.
+- */
+-static DEFINE_SPINLOCK(orion_pci_lock);
+-
+-u32 orion_pci_local_bus_nr(void)
+-{
+- u32 conf = orion_read(PCI_P2P_CONF);
+- return((conf & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS);
+-}
+-
+-u32 orion_pci_local_dev_nr(void)
+-{
+- u32 conf = orion_read(PCI_P2P_CONF);
+- return((conf & PCI_P2P_DEV_MASK) >> PCI_P2P_DEV_OFFS);
+-}
+-
+-int orion_pci_hw_rd_conf(u32 bus, u32 dev, u32 func,
+- u32 where, u32 size, u32 *val)
+-{
+- unsigned long flags;
+- spin_lock_irqsave(&orion_pci_lock, flags);
+-
+- orion_write(PCI_CONF_ADDR, PCI_CONF_BUS(bus) |
+- PCI_CONF_DEV(dev) | PCI_CONF_REG(where) |
+- PCI_CONF_FUNC(func) | PCI_CONF_ADDR_EN);
+-
+- *val = orion_read(PCI_CONF_DATA);
+-
+- if (size == 1)
+- *val = (*val >> (8*(where & 0x3))) & 0xff;
+- else if (size == 2)
+- *val = (*val >> (8*(where & 0x3))) & 0xffff;
+-
+- spin_unlock_irqrestore(&orion_pci_lock, flags);
+-
+- return PCIBIOS_SUCCESSFUL;
+-}
+-
+-int orion_pci_hw_wr_conf(u32 bus, u32 dev, u32 func,
+- u32 where, u32 size, u32 val)
+-{
+- unsigned long flags;
+- int ret = PCIBIOS_SUCCESSFUL;
+-
+- spin_lock_irqsave(&orion_pci_lock, flags);
+-
+- orion_write(PCI_CONF_ADDR, PCI_CONF_BUS(bus) |
+- PCI_CONF_DEV(dev) | PCI_CONF_REG(where) |
+- PCI_CONF_FUNC(func) | PCI_CONF_ADDR_EN);
+-
+- if (size == 4) {
+- __raw_writel(val, PCI_CONF_DATA);
+- } else if (size == 2) {
+- __raw_writew(val, PCI_CONF_DATA + (where & 0x3));
+- } else if (size == 1) {
+- __raw_writeb(val, PCI_CONF_DATA + (where & 0x3));
+- } else {
+- ret = PCIBIOS_BAD_REGISTER_NUMBER;
+- }
+-
+- spin_unlock_irqrestore(&orion_pci_lock, flags);
+-
+- return ret;
+-}
+-
+-static int orion_pci_rd_conf(struct pci_bus *bus, u32 devfn,
+- int where, int size, u32 *val)
+-{
+- /*
+- * Don't go out for local device
+- */
+- if ((orion_pci_local_bus_nr() == bus->number) &&
+- (orion_pci_local_dev_nr() == PCI_SLOT(devfn))) {
+- *val = 0xffffffff;
+- return PCIBIOS_DEVICE_NOT_FOUND;
+- }
+-
+- return orion_pci_hw_rd_conf(bus->number, PCI_SLOT(devfn),
+- PCI_FUNC(devfn), where, size, val);
+-}
+-
+-static int orion_pci_wr_conf(struct pci_bus *bus, u32 devfn,
+- int where, int size, u32 val)
+-{
+- /*
+- * Don't go out for local device
+- */
+- if ((orion_pci_local_bus_nr() == bus->number) &&
+- (orion_pci_local_dev_nr() == PCI_SLOT(devfn)))
+- return PCIBIOS_DEVICE_NOT_FOUND;
+-
+- return orion_pci_hw_wr_conf(bus->number, PCI_SLOT(devfn),
+- PCI_FUNC(devfn), where, size, val);
+-}
+-
+-struct pci_ops orion_pci_ops = {
+- .read = orion_pci_rd_conf,
+- .write = orion_pci_wr_conf,
+-};
+-
+-static void orion_pci_set_bus_nr(int nr)
+-{
+- u32 p2p = orion_read(PCI_P2P_CONF);
+-
+- if (orion_read(PCI_MODE) & PCI_MODE_PCIX) {
+- /*
+- * PCI-X mode
+- */
+- u32 pcix_status, bus, dev;
+- bus = (p2p & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS;
+- dev = (p2p & PCI_P2P_DEV_MASK) >> PCI_P2P_DEV_OFFS;
+- orion_pci_hw_rd_conf(bus, dev, 0, PCIX_STAT, 4, &pcix_status);
+- pcix_status &= ~PCIX_STAT_BUS_MASK;
+- pcix_status |= (nr << PCIX_STAT_BUS_OFFS);
+- orion_pci_hw_wr_conf(bus, dev, 0, PCIX_STAT, 4, pcix_status);
+- } else {
+- /*
+- * PCI Conventional mode
+- */
+- p2p &= ~PCI_P2P_BUS_MASK;
+- p2p |= (nr << PCI_P2P_BUS_OFFS);
+- orion_write(PCI_P2P_CONF, p2p);
+- }
+-}
+-
+-static void orion_pci_master_slave_enable(void)
+-{
+- u32 bus_nr, dev_nr, func, reg, val;
+-
+- bus_nr = orion_pci_local_bus_nr();
+- dev_nr = orion_pci_local_dev_nr();
+- func = PCI_CONF_FUNC_STAT_CMD;
+- reg = PCI_CONF_REG_STAT_CMD;
+- orion_pci_hw_rd_conf(bus_nr, dev_nr, func, reg, 4, &val);
+- val |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+- orion_pci_hw_wr_conf(bus_nr, dev_nr, func, reg, 4, val | 0x7);
+-}
+-
+-static int orion_pci_setup(struct pci_sys_data *sys)
+-{
+- struct resource *res;
+-
+- /*
+- * Master + Slave enable
+- */
+- orion_pci_master_slave_enable();
+-
+- /*
+- * Force ordering
+- */
+- orion_setbits(PCI_CMD, PCI_CMD_HOST_REORDER);
+-
+- /*
+- * Request resources
+- */
+- res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
+- if (!res)
+- panic("orion_pci_setup unable to alloc resources");
+-
+- /*
+- * IORESOURCE_IO
+- */
+- res[0].name = "PCI I/O Space";
+- res[0].flags = IORESOURCE_IO;
+- res[0].start = ORION_PCI_IO_BUS_BASE;
+- res[0].end = res[0].start + ORION_PCI_IO_SIZE - 1;
+- if (request_resource(&ioport_resource, &res[0]))
+- panic("Request PCI IO resource failed\n");
+- sys->resource[0] = &res[0];
+-
+- /*
+- * IORESOURCE_MEM
+- */
+- res[1].name = "PCI Memory Space";
+- res[1].flags = IORESOURCE_MEM;
+- res[1].start = ORION_PCI_MEM_PHYS_BASE;
+- res[1].end = res[1].start + ORION_PCI_MEM_SIZE - 1;
+- if (request_resource(&iomem_resource, &res[1]))
+- panic("Request PCI Memory resource failed\n");
+- sys->resource[1] = &res[1];
+-
+- sys->resource[2] = NULL;
+- sys->io_offset = 0;
+-
+- return 1;
+-}
+-
+-
+-/*****************************************************************************
+- * General PCIE + PCI
+- ****************************************************************************/
+-int orion_pci_sys_setup(int nr, struct pci_sys_data *sys)
+-{
+- int ret = 0;
+-
+- if (nr == 0) {
+- /*
+- * PCIE setup
+- */
+- orion_pcie_set_bus_nr(0);
+- ret = orion_pcie_setup(sys);
+- } else if (nr == 1) {
+- /*
+- * PCI setup
+- */
+- ret = orion_pci_setup(sys);
+- }
+-
+- return ret;
+-}
+-
+-struct pci_bus *orion_pci_sys_scan_bus(int nr, struct pci_sys_data *sys)
+-{
+- struct pci_ops *ops;
+- struct pci_bus *bus;
+-
+-
+- if (nr == 0) {
+- u32 pci_bus;
+- /*
+- * PCIE scan
+- */
+- ops = &orion_pcie_ops;
+- bus = pci_scan_bus(sys->busnr, ops, sys);
+- /*
+- * Set local PCI bus number to follow PCIE bridges (if any)
+- */
+- pci_bus = bus->number + bus->subordinate - bus->secondary + 1;
+- orion_pci_set_bus_nr(pci_bus);
+- } else if (nr == 1) {
+- /*
+- * PCI scan
+- */
+- ops = &orion_pci_ops;
+- bus = pci_scan_bus(sys->busnr, ops, sys);
+- } else {
+- BUG();
+- bus = NULL;
+- }
+-
+- return bus;
+-}
+diff --git a/arch/arm/mach-orion/rd88f5182-setup.c b/arch/arm/mach-orion/rd88f5182-setup.c
+deleted file mode 100644
+index e851b8c..0000000
+--- a/arch/arm/mach-orion/rd88f5182-setup.c
++++ /dev/null
+@@ -1,315 +0,0 @@
+-/*
+- * arch/arm/mach-orion/rd88f5182-setup.c
+- *
+- * Marvell Orion-NAS Reference Design Setup
+- *
+- * Maintainer: Ronen Shitrit <rshitrit at marvell.com>
+- *
+- * This file is licensed under the terms of the GNU General Public
+- * License version 2. This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/platform_device.h>
+-#include <linux/pci.h>
+-#include <linux/irq.h>
+-#include <linux/mtd/physmap.h>
+-#include <linux/mv643xx_eth.h>
+-#include <linux/ata_platform.h>
+-#include <linux/i2c.h>
+-#include <asm/mach-types.h>
+-#include <asm/gpio.h>
+-#include <asm/leds.h>
+-#include <asm/mach/arch.h>
+-#include <asm/mach/pci.h>
+-#include <asm/arch/orion.h>
+-#include <asm/arch/platform.h>
+-#include "common.h"
+-
+-/*****************************************************************************
+- * RD-88F5182 Info
+- ****************************************************************************/
+-
+-/*
+- * 512K NOR flash Device bus boot chip select
+- */
+-
+-#define RD88F5182_NOR_BOOT_BASE 0xf4000000
+-#define RD88F5182_NOR_BOOT_SIZE SZ_512K
+-
+-/*
+- * 16M NOR flash on Device bus chip select 1
+- */
+-
+-#define RD88F5182_NOR_BASE 0xfc000000
+-#define RD88F5182_NOR_SIZE SZ_16M
+-
+-/*
+- * PCI
+- */
+-
+-#define RD88F5182_PCI_SLOT0_OFFS 7
+-#define RD88F5182_PCI_SLOT0_IRQ_A_PIN 7
+-#define RD88F5182_PCI_SLOT0_IRQ_B_PIN 6
+-
+-/*
+- * GPIO Debug LED
+- */
+-
+-#define RD88F5182_GPIO_DBG_LED 0
+-
+-/*****************************************************************************
+- * 16M NOR Flash on Device bus CS1
+- ****************************************************************************/
+-
+-static struct physmap_flash_data rd88f5182_nor_flash_data = {
+- .width = 1,
+-};
+-
+-static struct resource rd88f5182_nor_flash_resource = {
+- .flags = IORESOURCE_MEM,
+- .start = RD88F5182_NOR_BASE,
+- .end = RD88F5182_NOR_BASE + RD88F5182_NOR_SIZE - 1,
+-};
+-
+-static struct platform_device rd88f5182_nor_flash = {
+- .name = "physmap-flash",
+- .id = 0,
+- .dev = {
+- .platform_data = &rd88f5182_nor_flash_data,
+- },
+- .num_resources = 1,
+- .resource = &rd88f5182_nor_flash_resource,
+-};
+-
+-#ifdef CONFIG_LEDS
+-
+-/*****************************************************************************
+- * Use GPIO debug led as CPU active indication
+- ****************************************************************************/
+-
+-static void rd88f5182_dbgled_event(led_event_t evt)
+-{
+- int val;
+-
+- if (evt == led_idle_end)
+- val = 1;
+- else if (evt == led_idle_start)
+- val = 0;
+- else
+- return;
+-
+- gpio_set_value(RD88F5182_GPIO_DBG_LED, val);
+-}
+-
+-static int __init rd88f5182_dbgled_init(void)
+-{
+- int pin;
+-
+- if (machine_is_rd88f5182()) {
+- pin = RD88F5182_GPIO_DBG_LED;
+-
+- if (gpio_request(pin, "DBGLED") == 0) {
+- if (gpio_direction_output(pin, 0) != 0) {
+- printk(KERN_ERR "rd88f5182_dbgled_init failed "
+- "to set output pin %d\n", pin);
+- gpio_free(pin);
+- return 0;
+- }
+- } else {
+- printk(KERN_ERR "rd88f5182_dbgled_init failed "
+- "to request gpio %d\n", pin);
+- return 0;
+- }
+-
+- leds_event = rd88f5182_dbgled_event;
+- }
+- return 0;
+-}
+-
+-__initcall(rd88f5182_dbgled_init);
+-
+-#endif
+-
+-/*****************************************************************************
+- * PCI
+- ****************************************************************************/
+-
+-void __init rd88f5182_pci_preinit(void)
+-{
+- int pin;
+-
+- /*
+- * Configure PCI GPIO IRQ pins
+- */
+- pin = RD88F5182_PCI_SLOT0_IRQ_A_PIN;
+- if (gpio_request(pin, "PCI IntA") == 0) {
+- if (gpio_direction_input(pin) == 0) {
+- set_irq_type(gpio_to_irq(pin), IRQT_LOW);
+- } else {
+- printk(KERN_ERR "rd88f5182_pci_preinit faield to "
+- "set_irq_type pin %d\n", pin);
+- gpio_free(pin);
+- }
+- } else {
+- printk(KERN_ERR "rd88f5182_pci_preinit failed to request gpio %d\n", pin);
+- }
+-
+- pin = RD88F5182_PCI_SLOT0_IRQ_B_PIN;
+- if (gpio_request(pin, "PCI IntB") == 0) {
+- if (gpio_direction_input(pin) == 0) {
+- set_irq_type(gpio_to_irq(pin), IRQT_LOW);
+- } else {
+- printk(KERN_ERR "rd88f5182_pci_preinit faield to "
+- "set_irq_type pin %d\n", pin);
+- gpio_free(pin);
+- }
+- } else {
+- printk(KERN_ERR "rd88f5182_pci_preinit failed to gpio_request %d\n", pin);
+- }
+-}
+-
+-static int __init rd88f5182_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+-{
+- /*
+- * PCI-E isn't used on the RD2
+- */
+- if (dev->bus->number == orion_pcie_local_bus_nr())
+- return IRQ_ORION_PCIE0_INT;
+-
+- /*
+- * PCI IRQs are connected via GPIOs
+- */
+- switch (slot - RD88F5182_PCI_SLOT0_OFFS) {
+- case 0:
+- if (pin == 1)
+- return gpio_to_irq(RD88F5182_PCI_SLOT0_IRQ_A_PIN);
+- else
+- return gpio_to_irq(RD88F5182_PCI_SLOT0_IRQ_B_PIN);
+- default:
+- return -1;
+- }
+-}
+-
+-static struct hw_pci rd88f5182_pci __initdata = {
+- .nr_controllers = 2,
+- .preinit = rd88f5182_pci_preinit,
+- .swizzle = pci_std_swizzle,
+- .setup = orion_pci_sys_setup,
+- .scan = orion_pci_sys_scan_bus,
+- .map_irq = rd88f5182_pci_map_irq,
+-};
+-
+-static int __init rd88f5182_pci_init(void)
+-{
+- if (machine_is_rd88f5182())
+- pci_common_init(&rd88f5182_pci);
+-
+- return 0;
+-}
+-
+-subsys_initcall(rd88f5182_pci_init);
+-
+-/*****************************************************************************
+- * Ethernet
+- ****************************************************************************/
+-
+-static struct mv643xx_eth_platform_data rd88f5182_eth_data = {
+- .phy_addr = 8,
+- .force_phy_addr = 1,
+-};
+-
+-/*****************************************************************************
+- * RTC DS1338 on I2C bus
+- ****************************************************************************/
+-static struct i2c_board_info __initdata rd88f5182_i2c_rtc = {
+- .driver_name = "rtc-ds1307",
+- .type = "ds1338",
+- .addr = 0x68,
+-};
+-
+-/*****************************************************************************
+- * Sata
+- ****************************************************************************/
+-static struct mv_sata_platform_data rd88f5182_sata_data = {
+- .n_ports = 2,
+-};
+-
+-/*****************************************************************************
+- * General Setup
+- ****************************************************************************/
+-
+-static struct platform_device *rd88f5182_devices[] __initdata = {
+- &rd88f5182_nor_flash,
+-};
+-
+-static void __init rd88f5182_init(void)
+-{
+- /*
+- * Setup basic Orion functions. Need to be called early.
+- */
+- orion_init();
+-
+- /*
+- * Setup the CPU address decode windows for our devices
+- */
+- orion_setup_cpu_win(ORION_DEV_BOOT, RD88F5182_NOR_BOOT_BASE,
+- RD88F5182_NOR_BOOT_SIZE, -1);
+- orion_setup_cpu_win(ORION_DEV1, RD88F5182_NOR_BASE,
+- RD88F5182_NOR_SIZE, -1);
+-
+- /*
+- * Open a special address decode windows for the PCIE WA.
+- */
+- orion_write(ORION_REGS_VIRT_BASE | 0x20074, ORION_PCIE_WA_PHYS_BASE);
+- orion_write(ORION_REGS_VIRT_BASE | 0x20070, (0x7941 |
+- (((ORION_PCIE_WA_SIZE >> 16) - 1)) << 16));
+-
+- /*
+- * Setup Multiplexing Pins --
+- * MPP[0] Debug Led (GPIO - Out)
+- * MPP[1] Debug Led (GPIO - Out)
+- * MPP[2] N/A
+- * MPP[3] RTC_Int (GPIO - In)
+- * MPP[4] GPIO
+- * MPP[5] GPIO
+- * MPP[6] PCI_intA (GPIO - In)
+- * MPP[7] PCI_intB (GPIO - In)
+- * MPP[8-11] N/A
+- * MPP[12] SATA 0 presence Indication
+- * MPP[13] SATA 1 presence Indication
+- * MPP[14] SATA 0 active Indication
+- * MPP[15] SATA 1 active indication
+- * MPP[16-19] Not used
+- * MPP[20] PCI Clock to MV88F5182
+- * MPP[21] PCI Clock to mini PCI CON11
+- * MPP[22] USB 0 over current indication
+- * MPP[23] USB 1 over current indication
+- * MPP[24] USB 1 over current enable
+- * MPP[25] USB 0 over current enable
+- */
+-
+- orion_write(MPP_0_7_CTRL, 0x00000003);
+- orion_write(MPP_8_15_CTRL, 0x55550000);
+- orion_write(MPP_16_19_CTRL, 0x5555);
+-
+- orion_gpio_set_valid_pins(0x000000fb);
+-
+- platform_add_devices(rd88f5182_devices, ARRAY_SIZE(rd88f5182_devices));
+- i2c_register_board_info(0, &rd88f5182_i2c_rtc, 1);
+- orion_eth_init(&rd88f5182_eth_data);
+- orion_sata_init(&rd88f5182_sata_data);
+-}
+-
+-MACHINE_START(RD88F5182, "Marvell Orion-NAS Reference Design")
+- /* Maintainer: Ronen Shitrit <rshitrit at marvell.com> */
+- .phys_io = ORION_REGS_PHYS_BASE,
+- .io_pg_offst = ((ORION_REGS_VIRT_BASE) >> 18) & 0xFFFC,
+- .boot_params = 0x00000100,
+- .init_machine = rd88f5182_init,
+- .map_io = orion_map_io,
+- .init_irq = orion_init_irq,
+- .timer = &orion_timer,
+-MACHINE_END
+diff --git a/arch/arm/mach-orion/time.c b/arch/arm/mach-orion/time.c
+deleted file mode 100644
+index bd4262d..0000000
+--- a/arch/arm/mach-orion/time.c
++++ /dev/null
+@@ -1,181 +0,0 @@
+-/*
+- * arch/arm/mach-orion/time.c
+- *
+- * Core time functions for Marvell Orion System On Chip
+- *
+- * Maintainer: Tzachi Perelstein <tzachi at marvell.com>
+- *
+- * This file is licensed under the terms of the GNU General Public
+- * License version 2. This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/clockchips.h>
+-#include <linux/interrupt.h>
+-#include <linux/irq.h>
+-#include <asm/mach/time.h>
+-#include <asm/arch/orion.h>
+-#include "common.h"
+-
+-/*
+- * Timer0: clock_event_device, Tick.
+- * Timer1: clocksource, Free running.
+- * WatchDog: Not used.
+- *
+- * Timers are counting down.
+- */
+-#define CLOCKEVENT 0
+-#define CLOCKSOURCE 1
+-
+-/*
+- * Timers bits
+- */
+-#define BRIDGE_INT_TIMER(x) (1 << ((x) + 1))
+-#define TIMER_EN(x) (1 << ((x) * 2))
+-#define TIMER_RELOAD_EN(x) (1 << (((x) * 2) + 1))
+-#define BRIDGE_INT_TIMER_WD (1 << 3)
+-#define TIMER_WD_EN (1 << 4)
+-#define TIMER_WD_RELOAD_EN (1 << 5)
+-
+-static cycle_t orion_clksrc_read(void)
+-{
+- return (0xffffffff - orion_read(TIMER_VAL(CLOCKSOURCE)));
+-}
+-
+-static struct clocksource orion_clksrc = {
+- .name = "orion_clocksource",
+- .shift = 20,
+- .rating = 300,
+- .read = orion_clksrc_read,
+- .mask = CLOCKSOURCE_MASK(32),
+- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+-};
+-
+-static int
+-orion_clkevt_next_event(unsigned long delta, struct clock_event_device *dev)
+-{
+- unsigned long flags;
+-
+- if (delta == 0)
+- return -ETIME;
+-
+- local_irq_save(flags);
+-
+- /*
+- * Clear and enable timer interrupt bit
+- */
+- orion_write(BRIDGE_CAUSE, ~BRIDGE_INT_TIMER(CLOCKEVENT));
+- orion_setbits(BRIDGE_MASK, BRIDGE_INT_TIMER(CLOCKEVENT));
+-
+- /*
+- * Setup new timer value
+- */
+- orion_write(TIMER_VAL(CLOCKEVENT), delta);
+-
+- /*
+- * Disable auto reload and kickoff the timer
+- */
+- orion_clrbits(TIMER_CTRL, TIMER_RELOAD_EN(CLOCKEVENT));
+- orion_setbits(TIMER_CTRL, TIMER_EN(CLOCKEVENT));
+-
+- local_irq_restore(flags);
+-
+- return 0;
+-}
+-
+-static void
+-orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
+-{
+- unsigned long flags;
+-
+- local_irq_save(flags);
+-
+- if (mode == CLOCK_EVT_MODE_PERIODIC) {
+- /*
+- * Setup latch cycles in timer and enable reload interrupt.
+- */
+- orion_write(TIMER_VAL_RELOAD(CLOCKEVENT), LATCH);
+- orion_write(TIMER_VAL(CLOCKEVENT), LATCH);
+- orion_setbits(BRIDGE_MASK, BRIDGE_INT_TIMER(CLOCKEVENT));
+- orion_setbits(TIMER_CTRL, TIMER_RELOAD_EN(CLOCKEVENT) |
+- TIMER_EN(CLOCKEVENT));
+- } else {
+- /*
+- * Disable timer and interrupt
+- */
+- orion_clrbits(BRIDGE_MASK, BRIDGE_INT_TIMER(CLOCKEVENT));
+- orion_write(BRIDGE_CAUSE, ~BRIDGE_INT_TIMER(CLOCKEVENT));
+- orion_clrbits(TIMER_CTRL, TIMER_RELOAD_EN(CLOCKEVENT) |
+- TIMER_EN(CLOCKEVENT));
+- }
+-
+- local_irq_restore(flags);
+-}
+-
+-static struct clock_event_device orion_clkevt = {
+- .name = "orion_tick",
+- .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+- .shift = 32,
+- .rating = 300,
+- .cpumask = CPU_MASK_CPU0,
+- .set_next_event = orion_clkevt_next_event,
+- .set_mode = orion_clkevt_mode,
+-};
+-
+-static irqreturn_t orion_timer_interrupt(int irq, void *dev_id)
+-{
+- /*
+- * Clear cause bit and do event
+- */
+- orion_write(BRIDGE_CAUSE, ~BRIDGE_INT_TIMER(CLOCKEVENT));
+- orion_clkevt.event_handler(&orion_clkevt);
+- return IRQ_HANDLED;
+-}
+-
+-static struct irqaction orion_timer_irq = {
+- .name = "orion_tick",
+- .flags = IRQF_DISABLED | IRQF_TIMER,
+- .handler = orion_timer_interrupt
+-};
+-
+-static void orion_timer_init(void)
+-{
+- /*
+- * Setup clocksource free running timer (no interrupt on reload)
+- */
+- orion_write(TIMER_VAL(CLOCKSOURCE), 0xffffffff);
+- orion_write(TIMER_VAL_RELOAD(CLOCKSOURCE), 0xffffffff);
+- orion_clrbits(BRIDGE_MASK, BRIDGE_INT_TIMER(CLOCKSOURCE));
+- orion_setbits(TIMER_CTRL, TIMER_RELOAD_EN(CLOCKSOURCE) |
+- TIMER_EN(CLOCKSOURCE));
+-
+- /*
+- * Register clocksource
+- */
+- orion_clksrc.mult =
+- clocksource_hz2mult(CLOCK_TICK_RATE, orion_clksrc.shift);
+-
+- clocksource_register(&orion_clksrc);
+-
+- /*
+- * Connect and enable tick handler
+- */
+- setup_irq(IRQ_ORION_BRIDGE, &orion_timer_irq);
+-
+- /*
+- * Register clockevent
+- */
+- orion_clkevt.mult =
+- div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, orion_clkevt.shift);
+- orion_clkevt.max_delta_ns =
+- clockevent_delta2ns(0xfffffffe, &orion_clkevt);
+- orion_clkevt.min_delta_ns =
+- clockevent_delta2ns(1, &orion_clkevt);
+-
+- clockevents_register_device(&orion_clkevt);
+-}
+-
+-struct sys_timer orion_timer = {
+- .init = orion_timer_init,
+-};
+diff --git a/arch/arm/mach-orion/ts209-setup.c b/arch/arm/mach-orion/ts209-setup.c
+deleted file mode 100644
+index 45764da..0000000
+--- a/arch/arm/mach-orion/ts209-setup.c
++++ /dev/null
+@@ -1,361 +0,0 @@
+-/*
+- * QNAP TS-109/TS-209 Board Setup
+- *
+- * Maintainer: Byron Bradley <byron.bbradley at gmail.com>
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/platform_device.h>
+-#include <linux/pci.h>
+-#include <linux/irq.h>
+-#include <linux/mtd/physmap.h>
+-#include <linux/mtd/nand.h>
+-#include <linux/mv643xx_eth.h>
+-#include <linux/gpio_keys.h>
+-#include <linux/input.h>
+-#include <linux/i2c.h>
+-#include <linux/serial_reg.h>
+-#include <linux/ata_platform.h>
+-#include <asm/mach-types.h>
+-#include <asm/gpio.h>
+-#include <asm/mach/arch.h>
+-#include <asm/mach/pci.h>
+-#include <asm/arch/orion.h>
+-#include <asm/arch/platform.h>
+-#include "common.h"
+-
+-#define QNAP_TS209_NOR_BOOT_BASE 0xf4000000
+-#define QNAP_TS209_NOR_BOOT_SIZE SZ_8M
+-
+-/****************************************************************************
+- * 8MiB NOR flash. The struct mtd_partition is not in the same order as the
+- * partitions on the device because we want to keep compatability with
+- * existing QNAP firmware.
+- *
+- * Layout as used by QNAP:
+- * [2] 0x00000000-0x00200000 : "Kernel"
+- * [3] 0x00200000-0x00600000 : "RootFS1"
+- * [4] 0x00600000-0x00700000 : "RootFS2"
+- * [6] 0x00700000-0x00760000 : "NAS Config" (read-only)
+- * [5] 0x00760000-0x00780000 : "U-Boot Config"
+- * [1] 0x00780000-0x00800000 : "U-Boot" (read-only)
+- ***************************************************************************/
+-static struct mtd_partition qnap_ts209_partitions[] = {
+- {
+- .name = "U-Boot",
+- .size = 0x00080000,
+- .offset = 0x00780000,
+- .mask_flags = MTD_WRITEABLE,
+- }, {
+- .name = "Kernel",
+- .size = 0x00200000,
+- .offset = 0,
+- }, {
+- .name = "RootFS1",
+- .size = 0x00400000,
+- .offset = 0x00200000,
+- }, {
+- .name = "RootFS2",
+- .size = 0x00100000,
+- .offset = 0x00600000,
+- }, {
+- .name = "U-Boot Config",
+- .size = 0x00020000,
+- .offset = 0x00760000,
+- }, {
+- .name = "NAS Config",
+- .size = 0x00060000,
+- .offset = 0x00700000,
+- .mask_flags = MTD_WRITEABLE,
+- }
+-};
+-
+-static struct physmap_flash_data qnap_ts209_nor_flash_data = {
+- .width = 1,
+- .parts = qnap_ts209_partitions,
+- .nr_parts = ARRAY_SIZE(qnap_ts209_partitions)
+-};
+-
+-static struct resource qnap_ts209_nor_flash_resource = {
+- .flags = IORESOURCE_MEM,
+- .start = QNAP_TS209_NOR_BOOT_BASE,
+- .end = QNAP_TS209_NOR_BOOT_BASE + QNAP_TS209_NOR_BOOT_SIZE - 1,
+-};
+-
+-static struct platform_device qnap_ts209_nor_flash = {
+- .name = "physmap-flash",
+- .id = 0,
+- .dev = { .platform_data = &qnap_ts209_nor_flash_data, },
+- .resource = &qnap_ts209_nor_flash_resource,
+- .num_resources = 1,
+-};
+-
+-/*****************************************************************************
+- * PCI
+- ****************************************************************************/
+-
+-#define QNAP_TS209_PCI_SLOT0_OFFS 7
+-#define QNAP_TS209_PCI_SLOT0_IRQ_PIN 6
+-#define QNAP_TS209_PCI_SLOT1_IRQ_PIN 7
+-
+-void __init qnap_ts209_pci_preinit(void)
+-{
+- int pin;
+-
+- /*
+- * Configure PCI GPIO IRQ pins
+- */
+- pin = QNAP_TS209_PCI_SLOT0_IRQ_PIN;
+- if (gpio_request(pin, "PCI Int1") == 0) {
+- if (gpio_direction_input(pin) == 0) {
+- set_irq_type(gpio_to_irq(pin), IRQT_LOW);
+- } else {
+- printk(KERN_ERR "qnap_ts209_pci_preinit failed to "
+- "set_irq_type pin %d\n", pin);
+- gpio_free(pin);
+- }
+- } else {
+- printk(KERN_ERR "qnap_ts209_pci_preinit failed to gpio_request "
+- "%d\n", pin);
+- }
+-
+- pin = QNAP_TS209_PCI_SLOT1_IRQ_PIN;
+- if (gpio_request(pin, "PCI Int2") == 0) {
+- if (gpio_direction_input(pin) == 0) {
+- set_irq_type(gpio_to_irq(pin), IRQT_LOW);
+- } else {
+- printk(KERN_ERR "qnap_ts209_pci_preinit failed "
+- "to set_irq_type pin %d\n", pin);
+- gpio_free(pin);
+- }
+- } else {
+- printk(KERN_ERR "qnap_ts209_pci_preinit failed to gpio_request "
+- "%d\n", pin);
+- }
+-}
+-
+-static int __init qnap_ts209_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+-{
+- /*
+- * PCIE IRQ is connected internally (not GPIO)
+- */
+- if (dev->bus->number == orion_pcie_local_bus_nr())
+- return IRQ_ORION_PCIE0_INT;
+-
+- /*
+- * PCI IRQs are connected via GPIOs
+- */
+- switch (slot - QNAP_TS209_PCI_SLOT0_OFFS) {
+- case 0:
+- return gpio_to_irq(QNAP_TS209_PCI_SLOT0_IRQ_PIN);
+- case 1:
+- return gpio_to_irq(QNAP_TS209_PCI_SLOT1_IRQ_PIN);
+- default:
+- return -1;
+- }
+-}
+-
+-static struct hw_pci qnap_ts209_pci __initdata = {
+- .nr_controllers = 2,
+- .preinit = qnap_ts209_pci_preinit,
+- .swizzle = pci_std_swizzle,
+- .setup = orion_pci_sys_setup,
+- .scan = orion_pci_sys_scan_bus,
+- .map_irq = qnap_ts209_pci_map_irq,
+-};
+-
+-static int __init qnap_ts209_pci_init(void)
+-{
+- if (machine_is_ts_x09())
+- pci_common_init(&qnap_ts209_pci);
+-
+- return 0;
+-}
+-
+-subsys_initcall(qnap_ts209_pci_init);
+-
+-/*****************************************************************************
+- * Ethernet
+- ****************************************************************************/
+-
+-static struct mv643xx_eth_platform_data qnap_ts209_eth_data = {
+- .phy_addr = 8,
+- .force_phy_addr = 1,
+-};
+-
+-/*****************************************************************************
+- * RTC S35390A on I2C bus
+- ****************************************************************************/
+-
+-#define TS209_RTC_GPIO 3
+-
+-static struct i2c_board_info __initdata qnap_ts209_i2c_rtc = {
+- .driver_name = "rtc-s35390a",
+- .addr = 0x30,
+- .irq = 0,
+-};
+-
+-/****************************************************************************
+- * GPIO Attached Keys
+- * Power button is attached to the PIC microcontroller
+- ****************************************************************************/
+-
+-#define QNAP_TS209_GPIO_KEY_MEDIA 1
+-#define QNAP_TS209_GPIO_KEY_RESET 2
+-
+-static struct gpio_keys_button qnap_ts209_buttons[] = {
+- {
+- .code = KEY_RESTART,
+- .gpio = QNAP_TS209_GPIO_KEY_MEDIA,
+- .desc = "USB Copy Button",
+- .active_low = 1,
+- },
+- {
+- .code = KEY_POWER,
+- .gpio = QNAP_TS209_GPIO_KEY_RESET,
+- .desc = "Reset Button",
+- .active_low = 1,
+- }
+-};
+-
+-static struct gpio_keys_platform_data qnap_ts209_button_data = {
+- .buttons = qnap_ts209_buttons,
+- .nbuttons = ARRAY_SIZE(qnap_ts209_buttons),
+-};
+-
+-static struct platform_device qnap_ts209_button_device = {
+- .name = "gpio-keys",
+- .id = -1,
+- .num_resources = 0,
+- .dev = { .platform_data = &qnap_ts209_button_data, },
+-};
+-
+-/*****************************************************************************
+- * SATA
+- ****************************************************************************/
+-static struct mv_sata_platform_data qnap_ts209_sata_data = {
+- .n_ports = 2,
+-};
+-
+-/*****************************************************************************
+-
+- * General Setup
+- ****************************************************************************/
+-
+-static struct platform_device *qnap_ts209_devices[] __initdata = {
+- &qnap_ts209_nor_flash,
+- &qnap_ts209_button_device,
+-};
+-
+-/*
+- * QNAP TS-[12]09 specific power off method via UART1-attached PIC
+- */
+-
+-#define UART1_REG(x) (UART1_VIRT_BASE + ((UART_##x) << 2))
+-
+-static void qnap_ts209_power_off(void)
+-{
+- /* 19200 baud divisor */
+- const unsigned divisor = ((ORION_TCLK + (8 * 19200)) / (16 * 19200));
+-
+- pr_info("%s: triggering power-off...\n", __func__);
+-
+- /* hijack uart1 and reset into sane state (19200,8n1) */
+- orion_write(UART1_REG(LCR), 0x83);
+- orion_write(UART1_REG(DLL), divisor & 0xff);
+- orion_write(UART1_REG(DLM), (divisor >> 8) & 0xff);
+- orion_write(UART1_REG(LCR), 0x03);
+- orion_write(UART1_REG(IER), 0x00);
+- orion_write(UART1_REG(FCR), 0x00);
+- orion_write(UART1_REG(MCR), 0x00);
+-
+- /* send the power-off command 'A' to PIC */
+- orion_write(UART1_REG(TX), 'A');
+-}
+-
+-static void __init qnap_ts209_init(void)
+-{
+- /*
+- * Setup basic Orion functions. Need to be called early.
+- */
+- orion_init();
+-
+- /*
+- * Setup flash mapping
+- */
+- orion_setup_cpu_win(ORION_DEV_BOOT, QNAP_TS209_NOR_BOOT_BASE,
+- QNAP_TS209_NOR_BOOT_SIZE, -1);
+-
+- /*
+- * Open a special address decode windows for the PCIE WA.
+- */
+- orion_write(ORION_REGS_VIRT_BASE | 0x20074, ORION_PCIE_WA_PHYS_BASE);
+- orion_write(ORION_REGS_VIRT_BASE | 0x20070, (0x7941 |
+- (((ORION_PCIE_WA_SIZE >> 16) - 1)) << 16));
+-
+- /*
+- * Setup Multiplexing Pins --
+- * MPP[0] Reserved
+- * MPP[1] USB copy button (0 active)
+- * MPP[2] Load defaults button (0 active)
+- * MPP[3] GPIO RTC
+- * MPP[4-5] Reserved
+- * MPP[6] PCI Int A
+- * MPP[7] PCI Int B
+- * MPP[8-11] Reserved
+- * MPP[12] SATA 0 presence
+- * MPP[13] SATA 1 presence
+- * MPP[14] SATA 0 active
+- * MPP[15] SATA 1 active
+- * MPP[16] UART1 RXD
+- * MPP[17] UART1 TXD
+- * MPP[18] SW_RST (0 active)
+- * MPP[19] Reserved
+- * MPP[20] PCI clock 0
+- * MPP[21] PCI clock 1
+- * MPP[22] USB 0 over current
+- * MPP[23-25] Reserved
+- */
+- orion_write(MPP_0_7_CTRL, 0x3);
+- orion_write(MPP_8_15_CTRL, 0x55550000);
+- orion_write(MPP_16_19_CTRL, 0x5500);
+- orion_gpio_set_valid_pins(0x3cc0fff);
+-
+- /* register ts209 specific power-off method */
+- pm_power_off = qnap_ts209_power_off;
+-
+- platform_add_devices(qnap_ts209_devices,
+- ARRAY_SIZE(qnap_ts209_devices));
+-
+- /* Get RTC IRQ and register the chip */
+- if (gpio_request(TS209_RTC_GPIO, "rtc") == 0) {
+- if (gpio_direction_input(TS209_RTC_GPIO) == 0)
+- qnap_ts209_i2c_rtc.irq = gpio_to_irq(TS209_RTC_GPIO);
+- else
+- gpio_free(TS209_RTC_GPIO);
+- }
+- if (qnap_ts209_i2c_rtc.irq == 0)
+- pr_warning("qnap_ts209_init: failed to get RTC IRQ\n");
+- i2c_register_board_info(0, &qnap_ts209_i2c_rtc, 1);
+-
+- orion_eth_init(&qnap_ts209_eth_data);
+- orion_sata_init(&qnap_ts209_sata_data);
+-}
+-
+-MACHINE_START(TS209, "QNAP TS-109/TS-209")
+- /* Maintainer: Byron Bradley <byron.bbradley at gmail.com> */
+- .phys_io = ORION_REGS_PHYS_BASE,
+- .io_pg_offst = ((ORION_REGS_VIRT_BASE) >> 18) & 0xFFFC,
+- .boot_params = 0x00000100,
+- .init_machine = qnap_ts209_init,
+- .map_io = orion_map_io,
+- .init_irq = orion_init_irq,
+- .timer = &orion_timer,
+- .fixup = tag_fixup_mem32,
+-MACHINE_END
+diff --git a/arch/arm/mach-orion5x/Kconfig b/arch/arm/mach-orion5x/Kconfig
+new file mode 100644
+index 0000000..93debf3
+--- /dev/null
++++ b/arch/arm/mach-orion5x/Kconfig
+@@ -0,0 +1,49 @@
++if ARCH_ORION5X
++
++menu "Orion Implementations"
++
++config MACH_DB88F5281
++ bool "Marvell Orion-2 Development Board"
++ select I2C_BOARDINFO
++ help
++ Say 'Y' here if you want your kernel to support the
++ Marvell Orion-2 (88F5281) Development Board
++
++config MACH_RD88F5182
++ bool "Marvell Orion-NAS Reference Design"
++ select I2C_BOARDINFO
++ help
++ Say 'Y' here if you want your kernel to support the
++ Marvell Orion-NAS (88F5182) RD2
++
++config MACH_KUROBOX_PRO
++ bool "KuroBox Pro"
++ select I2C_BOARDINFO
++ help
++ Say 'Y' here if you want your kernel to support the
++ KuroBox Pro platform.
++
++config MACH_DNS323
++ bool "D-Link DNS-323"
++ select I2C_BOARDINFO
++ help
++ Say 'Y' here if you want your kernel to support the
++ D-Link DNS-323 platform.
++
++config MACH_TS209
++ bool "QNAP TS-109/TS-209"
++ help
++ Say 'Y' here if you want your kernel to support the
++ QNAP TS-109/TS-209 platform.
++
++config MACH_LINKSTATION_PRO
++ bool "Buffalo Linkstation Pro/Live"
++ select I2C_BOARDINFO
++ help
++ Say 'Y' here if you want your kernel to support the
++ Buffalo Linkstation Pro/Live platform. Both v1 and
++ v2 devices are supported.
++
++endmenu
++
++endif
+diff --git a/arch/arm/mach-orion5x/Makefile b/arch/arm/mach-orion5x/Makefile
+new file mode 100644
+index 0000000..9301bf5
+--- /dev/null
++++ b/arch/arm/mach-orion5x/Makefile
+@@ -0,0 +1,7 @@
++obj-y += common.o addr-map.o pci.o gpio.o irq.o
++obj-$(CONFIG_MACH_DB88F5281) += db88f5281-setup.o
++obj-$(CONFIG_MACH_RD88F5182) += rd88f5182-setup.o
++obj-$(CONFIG_MACH_KUROBOX_PRO) += kurobox_pro-setup.o
++obj-$(CONFIG_MACH_LINKSTATION_PRO) += kurobox_pro-setup.o
++obj-$(CONFIG_MACH_DNS323) += dns323-setup.o
++obj-$(CONFIG_MACH_TS209) += ts209-setup.o
+diff --git a/arch/arm/mach-orion5x/Makefile.boot b/arch/arm/mach-orion5x/Makefile.boot
+new file mode 100644
+index 0000000..67039c3
+--- /dev/null
++++ b/arch/arm/mach-orion5x/Makefile.boot
+@@ -0,0 +1,3 @@
++ zreladdr-y := 0x00008000
++params_phys-y := 0x00000100
++initrd_phys-y := 0x00800000
+diff --git a/arch/arm/mach-orion5x/addr-map.c b/arch/arm/mach-orion5x/addr-map.c
+new file mode 100644
+index 0000000..6b17937
+--- /dev/null
++++ b/arch/arm/mach-orion5x/addr-map.c
+@@ -0,0 +1,240 @@
++/*
++ * arch/arm/mach-orion5x/addr-map.c
++ *
++ * Address map functions for Marvell Orion 5x SoCs
++ *
++ * Maintainer: Tzachi Perelstein <tzachi at marvell.com>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/mbus.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include "common.h"
++
++/*
++ * The Orion has fully programable address map. There's a separate address
++ * map for each of the device _master_ interfaces, e.g. CPU, PCI, PCIE, USB,
++ * Gigabit Ethernet, DMA/XOR engines, etc. Each interface has its own
++ * address decode windows that allow it to access any of the Orion resources.
++ *
++ * CPU address decoding --
++ * Linux assumes that it is the boot loader that already setup the access to
++ * DDR and internal registers.
++ * Setup access to PCI and PCI-E IO/MEM space is issued by this file.
++ * Setup access to various devices located on the device bus interface (e.g.
++ * flashes, RTC, etc) should be issued by machine-setup.c according to
++ * specific board population (by using orion5x_setup_*_win()).
++ *
++ * Non-CPU Masters address decoding --
++ * Unlike the CPU, we setup the access from Orion's master interfaces to DDR
++ * banks only (the typical use case).
++ * Setup access for each master to DDR is issued by common.c.
++ *
++ * Note: although orion_setbits() and orion_clrbits() are not atomic
++ * no locking is necessary here since code in this file is only called
++ * at boot time when there is no concurrency issues.
++ */
++
++/*
++ * Generic Address Decode Windows bit settings
++ */
++#define TARGET_DDR 0
++#define TARGET_DEV_BUS 1
++#define TARGET_PCI 3
++#define TARGET_PCIE 4
++#define ATTR_DDR_CS(n) (((n) ==0) ? 0xe : \
++ ((n) == 1) ? 0xd : \
++ ((n) == 2) ? 0xb : \
++ ((n) == 3) ? 0x7 : 0xf)
++#define ATTR_PCIE_MEM 0x59
++#define ATTR_PCIE_IO 0x51
++#define ATTR_PCIE_WA 0x79
++#define ATTR_PCI_MEM 0x59
++#define ATTR_PCI_IO 0x51
++#define ATTR_DEV_CS0 0x1e
++#define ATTR_DEV_CS1 0x1d
++#define ATTR_DEV_CS2 0x1b
++#define ATTR_DEV_BOOT 0xf
++#define WIN_EN 1
++
++/*
++ * Helpers to get DDR bank info
++ */
++#define DDR_BASE_CS(n) ORION5X_DDR_REG(0x1500 + ((n) * 8))
++#define DDR_SIZE_CS(n) ORION5X_DDR_REG(0x1504 + ((n) * 8))
++#define DDR_MAX_CS 4
++#define DDR_REG_TO_SIZE(reg) (((reg) | 0xffffff) + 1)
++#define DDR_REG_TO_BASE(reg) ((reg) & 0xff000000)
++#define DDR_BANK_EN 1
++
++/*
++ * CPU Address Decode Windows registers
++ */
++#define CPU_WIN_CTRL(n) ORION5X_BRIDGE_REG(0x000 | ((n) << 4))
++#define CPU_WIN_BASE(n) ORION5X_BRIDGE_REG(0x004 | ((n) << 4))
++#define CPU_WIN_REMAP_LO(n) ORION5X_BRIDGE_REG(0x008 | ((n) << 4))
++#define CPU_WIN_REMAP_HI(n) ORION5X_BRIDGE_REG(0x00c | ((n) << 4))
++
++/*
++ * Gigabit Ethernet Address Decode Windows registers
++ */
++#define ETH_WIN_BASE(win) ORION5X_ETH_REG(0x200 + ((win) * 8))
++#define ETH_WIN_SIZE(win) ORION5X_ETH_REG(0x204 + ((win) * 8))
++#define ETH_WIN_REMAP(win) ORION5X_ETH_REG(0x280 + ((win) * 4))
++#define ETH_WIN_EN ORION5X_ETH_REG(0x290)
++#define ETH_WIN_PROT ORION5X_ETH_REG(0x294)
++#define ETH_MAX_WIN 6
++#define ETH_MAX_REMAP_WIN 4
++
++
++struct mbus_dram_target_info orion5x_mbus_dram_info;
++
++static int __init orion5x_cpu_win_can_remap(int win)
++{
++ u32 dev, rev;
++
++ orion5x_pcie_id(&dev, &rev);
++ if ((dev == MV88F5281_DEV_ID && win < 4)
++ || (dev == MV88F5182_DEV_ID && win < 2)
++ || (dev == MV88F5181_DEV_ID && win < 2))
++ return 1;
++
++ return 0;
++}
++
++static void __init setup_cpu_win(int win, u32 base, u32 size,
++ u8 target, u8 attr, int remap)
++{
++ orion5x_write(CPU_WIN_BASE(win), base & 0xffff0000);
++ orion5x_write(CPU_WIN_CTRL(win),
++ ((size - 1) & 0xffff0000) | (attr << 8) | (target << 4) | 1);
++
++ if (orion5x_cpu_win_can_remap(win)) {
++ if (remap < 0)
++ remap = base;
++
++ orion5x_write(CPU_WIN_REMAP_LO(win), remap & 0xffff0000);
++ orion5x_write(CPU_WIN_REMAP_HI(win), 0);
++ }
++}
++
++void __init orion5x_setup_cpu_mbus_bridge(void)
++{
++ int i;
++ int cs;
++
++ /*
++ * First, disable and clear windows.
++ */
++ for (i = 0; i < 8; i++) {
++ orion5x_write(CPU_WIN_BASE(i), 0);
++ orion5x_write(CPU_WIN_CTRL(i), 0);
++ if (orion5x_cpu_win_can_remap(i)) {
++ orion5x_write(CPU_WIN_REMAP_LO(i), 0);
++ orion5x_write(CPU_WIN_REMAP_HI(i), 0);
++ }
++ }
++
++ /*
++ * Setup windows for PCI+PCIe IO+MEM space.
++ */
++ setup_cpu_win(0, ORION5X_PCIE_IO_PHYS_BASE, ORION5X_PCIE_IO_SIZE,
++ TARGET_PCIE, ATTR_PCIE_IO, ORION5X_PCIE_IO_BUS_BASE);
++ setup_cpu_win(1, ORION5X_PCI_IO_PHYS_BASE, ORION5X_PCI_IO_SIZE,
++ TARGET_PCI, ATTR_PCI_IO, ORION5X_PCI_IO_BUS_BASE);
++ setup_cpu_win(2, ORION5X_PCIE_MEM_PHYS_BASE, ORION5X_PCIE_MEM_SIZE,
++ TARGET_PCIE, ATTR_PCIE_MEM, -1);
++ setup_cpu_win(3, ORION5X_PCI_MEM_PHYS_BASE, ORION5X_PCI_MEM_SIZE,
++ TARGET_PCI, ATTR_PCI_MEM, -1);
++
++ /*
++ * Setup MBUS dram target info.
++ */
++ orion5x_mbus_dram_info.mbus_dram_target_id = TARGET_DDR;
++
++ for (i = 0, cs = 0; i < 4; i++) {
++ u32 base = readl(DDR_BASE_CS(i));
++ u32 size = readl(DDR_SIZE_CS(i));
++
++ /*
++ * Chip select enabled?
++ */
++ if (size & 1) {
++ struct mbus_dram_window *w;
++
++ w = &orion5x_mbus_dram_info.cs[cs++];
++ w->cs_index = i;
++ w->mbus_attr = 0xf & ~(1 << i);
++ w->base = base & 0xff000000;
++ w->size = (size | 0x00ffffff) + 1;
++ }
++ }
++ orion5x_mbus_dram_info.num_cs = cs;
++}
++
++void __init orion5x_setup_dev_boot_win(u32 base, u32 size)
++{
++ setup_cpu_win(4, base, size, TARGET_DEV_BUS, ATTR_DEV_BOOT, -1);
++}
++
++void __init orion5x_setup_dev0_win(u32 base, u32 size)
++{
++ setup_cpu_win(5, base, size, TARGET_DEV_BUS, ATTR_DEV_CS0, -1);
++}
++
++void __init orion5x_setup_dev1_win(u32 base, u32 size)
++{
++ setup_cpu_win(6, base, size, TARGET_DEV_BUS, ATTR_DEV_CS1, -1);
++}
++
++void __init orion5x_setup_dev2_win(u32 base, u32 size)
++{
++ setup_cpu_win(7, base, size, TARGET_DEV_BUS, ATTR_DEV_CS2, -1);
++}
++
++void __init orion5x_setup_pcie_wa_win(u32 base, u32 size)
++{
++ setup_cpu_win(7, base, size, TARGET_PCIE, ATTR_PCIE_WA, -1);
++}
++
++void __init orion5x_setup_eth_wins(void)
++{
++ int i;
++
++ /*
++ * First, disable and clear windows
++ */
++ for (i = 0; i < ETH_MAX_WIN; i++) {
++ orion5x_write(ETH_WIN_BASE(i), 0);
++ orion5x_write(ETH_WIN_SIZE(i), 0);
++ orion5x_setbits(ETH_WIN_EN, 1 << i);
++ orion5x_clrbits(ETH_WIN_PROT, 0x3 << (i * 2));
++ if (i < ETH_MAX_REMAP_WIN)
++ orion5x_write(ETH_WIN_REMAP(i), 0);
++ }
++
++ /*
++ * Setup windows for DDR banks.
++ */
++ for (i = 0; i < DDR_MAX_CS; i++) {
++ u32 base, size;
++ size = orion5x_read(DDR_SIZE_CS(i));
++ base = orion5x_read(DDR_BASE_CS(i));
++ if (size & DDR_BANK_EN) {
++ base = DDR_REG_TO_BASE(base);
++ size = DDR_REG_TO_SIZE(size);
++ orion5x_write(ETH_WIN_SIZE(i), (size-1) & 0xffff0000);
++ orion5x_write(ETH_WIN_BASE(i), (base & 0xffff0000) |
++ (ATTR_DDR_CS(i) << 8) |
++ TARGET_DDR);
++ orion5x_clrbits(ETH_WIN_EN, 1 << i);
++ orion5x_setbits(ETH_WIN_PROT, 0x3 << (i * 2));
++ }
++ }
++}
+diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c
+new file mode 100644
+index 0000000..439c778
+--- /dev/null
++++ b/arch/arm/mach-orion5x/common.c
+@@ -0,0 +1,391 @@
++/*
++ * arch/arm/mach-orion5x/common.c
++ *
++ * Core functions for Marvell Orion 5x SoCs
++ *
++ * Maintainer: Tzachi Perelstein <tzachi at marvell.com>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/serial_8250.h>
++#include <linux/mbus.h>
++#include <linux/mv643xx_eth.h>
++#include <linux/mv643xx_i2c.h>
++#include <linux/ata_platform.h>
++#include <asm/page.h>
++#include <asm/setup.h>
++#include <asm/timex.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <asm/mach/time.h>
++#include <asm/arch/hardware.h>
++#include <asm/arch/orion5x.h>
++#include <asm/plat-orion/ehci-orion.h>
++#include <asm/plat-orion/orion_nand.h>
++#include <asm/plat-orion/time.h>
++#include "common.h"
++
++/*****************************************************************************
++ * I/O Address Mapping
++ ****************************************************************************/
++static struct map_desc orion5x_io_desc[] __initdata = {
++ {
++ .virtual = ORION5X_REGS_VIRT_BASE,
++ .pfn = __phys_to_pfn(ORION5X_REGS_PHYS_BASE),
++ .length = ORION5X_REGS_SIZE,
++ .type = MT_DEVICE
++ },
++ {
++ .virtual = ORION5X_PCIE_IO_VIRT_BASE,
++ .pfn = __phys_to_pfn(ORION5X_PCIE_IO_PHYS_BASE),
++ .length = ORION5X_PCIE_IO_SIZE,
++ .type = MT_DEVICE
++ },
++ {
++ .virtual = ORION5X_PCI_IO_VIRT_BASE,
++ .pfn = __phys_to_pfn(ORION5X_PCI_IO_PHYS_BASE),
++ .length = ORION5X_PCI_IO_SIZE,
++ .type = MT_DEVICE
++ },
++ {
++ .virtual = ORION5X_PCIE_WA_VIRT_BASE,
++ .pfn = __phys_to_pfn(ORION5X_PCIE_WA_PHYS_BASE),
++ .length = ORION5X_PCIE_WA_SIZE,
++ .type = MT_DEVICE
++ },
++};
++
++void __init orion5x_map_io(void)
++{
++ iotable_init(orion5x_io_desc, ARRAY_SIZE(orion5x_io_desc));
++}
++
++/*****************************************************************************
++ * UART
++ ****************************************************************************/
++
++static struct resource orion5x_uart_resources[] = {
++ {
++ .start = UART0_PHYS_BASE,
++ .end = UART0_PHYS_BASE + 0xff,
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = IRQ_ORION5X_UART0,
++ .end = IRQ_ORION5X_UART0,
++ .flags = IORESOURCE_IRQ,
++ },
++ {
++ .start = UART1_PHYS_BASE,
++ .end = UART1_PHYS_BASE + 0xff,
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = IRQ_ORION5X_UART1,
++ .end = IRQ_ORION5X_UART1,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct plat_serial8250_port orion5x_uart_data[] = {
++ {
++ .mapbase = UART0_PHYS_BASE,
++ .membase = (char *)UART0_VIRT_BASE,
++ .irq = IRQ_ORION5X_UART0,
++ .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
++ .iotype = UPIO_MEM,
++ .regshift = 2,
++ .uartclk = ORION5X_TCLK,
++ },
++ {
++ .mapbase = UART1_PHYS_BASE,
++ .membase = (char *)UART1_VIRT_BASE,
++ .irq = IRQ_ORION5X_UART1,
++ .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
++ .iotype = UPIO_MEM,
++ .regshift = 2,
++ .uartclk = ORION5X_TCLK,
++ },
++ { },
++};
++
++static struct platform_device orion5x_uart = {
++ .name = "serial8250",
++ .id = PLAT8250_DEV_PLATFORM,
++ .dev = {
++ .platform_data = orion5x_uart_data,
++ },
++ .resource = orion5x_uart_resources,
++ .num_resources = ARRAY_SIZE(orion5x_uart_resources),
++};
++
++/*******************************************************************************
++ * USB Controller - 2 interfaces
++ ******************************************************************************/
++
++static struct resource orion5x_ehci0_resources[] = {
++ {
++ .start = ORION5X_USB0_PHYS_BASE,
++ .end = ORION5X_USB0_PHYS_BASE + SZ_4K,
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = IRQ_ORION5X_USB0_CTRL,
++ .end = IRQ_ORION5X_USB0_CTRL,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct resource orion5x_ehci1_resources[] = {
++ {
++ .start = ORION5X_USB1_PHYS_BASE,
++ .end = ORION5X_USB1_PHYS_BASE + SZ_4K,
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = IRQ_ORION5X_USB1_CTRL,
++ .end = IRQ_ORION5X_USB1_CTRL,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct orion_ehci_data orion5x_ehci_data = {
++ .dram = &orion5x_mbus_dram_info,
++};
++
++static u64 ehci_dmamask = 0xffffffffUL;
++
++static struct platform_device orion5x_ehci0 = {
++ .name = "orion-ehci",
++ .id = 0,
++ .dev = {
++ .dma_mask = &ehci_dmamask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &orion5x_ehci_data,
++ },
++ .resource = orion5x_ehci0_resources,
++ .num_resources = ARRAY_SIZE(orion5x_ehci0_resources),
++};
++
++static struct platform_device orion5x_ehci1 = {
++ .name = "orion-ehci",
++ .id = 1,
++ .dev = {
++ .dma_mask = &ehci_dmamask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &orion5x_ehci_data,
++ },
++ .resource = orion5x_ehci1_resources,
++ .num_resources = ARRAY_SIZE(orion5x_ehci1_resources),
++};
++
++/*****************************************************************************
++ * Gigabit Ethernet port
++ * (The Orion and Discovery (MV643xx) families use the same Ethernet driver)
++ ****************************************************************************/
++
++static struct resource orion5x_eth_shared_resources[] = {
++ {
++ .start = ORION5X_ETH_PHYS_BASE + 0x2000,
++ .end = ORION5X_ETH_PHYS_BASE + 0x3fff,
++ .flags = IORESOURCE_MEM,
++ },
++};
++
++static struct platform_device orion5x_eth_shared = {
++ .name = MV643XX_ETH_SHARED_NAME,
++ .id = 0,
++ .num_resources = 1,
++ .resource = orion5x_eth_shared_resources,
++};
++
++static struct resource orion5x_eth_resources[] = {
++ {
++ .name = "eth irq",
++ .start = IRQ_ORION5X_ETH_SUM,
++ .end = IRQ_ORION5X_ETH_SUM,
++ .flags = IORESOURCE_IRQ,
++ }
++};
++
++static struct platform_device orion5x_eth = {
++ .name = MV643XX_ETH_NAME,
++ .id = 0,
++ .num_resources = 1,
++ .resource = orion5x_eth_resources,
++};
++
++void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data)
++{
++ orion5x_eth.dev.platform_data = eth_data;
++ platform_device_register(&orion5x_eth_shared);
++ platform_device_register(&orion5x_eth);
++}
++
++/*****************************************************************************
++ * I2C controller
++ * (The Orion and Discovery (MV643xx) families share the same I2C controller)
++ ****************************************************************************/
++
++static struct mv64xxx_i2c_pdata orion5x_i2c_pdata = {
++ .freq_m = 8, /* assumes 166 MHz TCLK */
++ .freq_n = 3,
++ .timeout = 1000, /* Default timeout of 1 second */
++};
++
++static struct resource orion5x_i2c_resources[] = {
++ {
++ .name = "i2c base",
++ .start = I2C_PHYS_BASE,
++ .end = I2C_PHYS_BASE + 0x20 -1,
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .name = "i2c irq",
++ .start = IRQ_ORION5X_I2C,
++ .end = IRQ_ORION5X_I2C,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device orion5x_i2c = {
++ .name = MV64XXX_I2C_CTLR_NAME,
++ .id = 0,
++ .num_resources = ARRAY_SIZE(orion5x_i2c_resources),
++ .resource = orion5x_i2c_resources,
++ .dev = {
++ .platform_data = &orion5x_i2c_pdata,
++ },
++};
++
++/*****************************************************************************
++ * Sata port
++ ****************************************************************************/
++static struct resource orion5x_sata_resources[] = {
++ {
++ .name = "sata base",
++ .start = ORION5X_SATA_PHYS_BASE,
++ .end = ORION5X_SATA_PHYS_BASE + 0x5000 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .name = "sata irq",
++ .start = IRQ_ORION5X_SATA,
++ .end = IRQ_ORION5X_SATA,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device orion5x_sata = {
++ .name = "sata_mv",
++ .id = 0,
++ .dev = {
++ .coherent_dma_mask = 0xffffffff,
++ },
++ .num_resources = ARRAY_SIZE(orion5x_sata_resources),
++ .resource = orion5x_sata_resources,
++};
++
++void __init orion5x_sata_init(struct mv_sata_platform_data *sata_data)
++{
++ sata_data->dram = &orion5x_mbus_dram_info;
++ orion5x_sata.dev.platform_data = sata_data;
++ platform_device_register(&orion5x_sata);
++}
++
++/*****************************************************************************
++ * Time handling
++ ****************************************************************************/
++
++static void orion5x_timer_init(void)
++{
++ orion_time_init(IRQ_ORION5X_BRIDGE, ORION5X_TCLK);
++}
++
++struct sys_timer orion5x_timer = {
++ .init = orion5x_timer_init,
++};
++
++/*****************************************************************************
++ * General
++ ****************************************************************************/
++
++/*
++ * Identify device ID and rev from PCIE configuration header space '0'.
++ */
++static void __init orion5x_id(u32 *dev, u32 *rev, char **dev_name)
++{
++ orion5x_pcie_id(dev, rev);
++
++ if (*dev == MV88F5281_DEV_ID) {
++ if (*rev == MV88F5281_REV_D2) {
++ *dev_name = "MV88F5281-D2";
++ } else if (*rev == MV88F5281_REV_D1) {
++ *dev_name = "MV88F5281-D1";
++ } else {
++ *dev_name = "MV88F5281-Rev-Unsupported";
++ }
++ } else if (*dev == MV88F5182_DEV_ID) {
++ if (*rev == MV88F5182_REV_A2) {
++ *dev_name = "MV88F5182-A2";
++ } else {
++ *dev_name = "MV88F5182-Rev-Unsupported";
++ }
++ } else if (*dev == MV88F5181_DEV_ID) {
++ if (*rev == MV88F5181_REV_B1) {
++ *dev_name = "MV88F5181-Rev-B1";
++ } else {
++ *dev_name = "MV88F5181-Rev-Unsupported";
++ }
++ } else {
++ *dev_name = "Device-Unknown";
++ }
++}
++
++void __init orion5x_init(void)
++{
++ char *dev_name;
++ u32 dev, rev;
++
++ orion5x_id(&dev, &rev, &dev_name);
++ printk(KERN_INFO "Orion ID: %s. TCLK=%d.\n", dev_name, ORION5X_TCLK);
++
++ /*
++ * Setup Orion address map
++ */
++ orion5x_setup_cpu_mbus_bridge();
++ orion5x_setup_eth_wins();
++
++ /*
++ * Register devices.
++ */
++ platform_device_register(&orion5x_uart);
++ platform_device_register(&orion5x_ehci0);
++ if (dev == MV88F5182_DEV_ID)
++ platform_device_register(&orion5x_ehci1);
++ platform_device_register(&orion5x_i2c);
++}
++
++/*
++ * Many orion-based systems have buggy bootloader implementations.
++ * This is a common fixup for bogus memory tags.
++ */
++void __init tag_fixup_mem32(struct machine_desc *mdesc, struct tag *t,
++ char **from, struct meminfo *meminfo)
++{
++ for (; t->hdr.size; t = tag_next(t))
++ if (t->hdr.tag == ATAG_MEM &&
++ (!t->u.mem.size || t->u.mem.size & ~PAGE_MASK ||
++ t->u.mem.start & ~PAGE_MASK)) {
++ printk(KERN_WARNING
++ "Clearing invalid memory bank %dKB at 0x%08x\n",
++ t->u.mem.size / 1024, t->u.mem.start);
++ t->hdr.tag = 0;
++ }
++}
+diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h
+new file mode 100644
+index 0000000..f4c4c9a
+--- /dev/null
++++ b/arch/arm/mach-orion5x/common.h
+@@ -0,0 +1,72 @@
++#ifndef __ARCH_ORION5X_COMMON_H
++#define __ARCH_ORION5X_COMMON_H
++
++/*
++ * Basic Orion init functions used early by machine-setup.
++ */
++
++void orion5x_map_io(void);
++void orion5x_init_irq(void);
++void orion5x_init(void);
++extern struct sys_timer orion5x_timer;
++
++/*
++ * Enumerations and functions for Orion windows mapping. Used by Orion core
++ * functions to map its interfaces and by the machine-setup to map its on-
++ * board devices. Details in /mach-orion/addr-map.c
++ */
++extern struct mbus_dram_target_info orion5x_mbus_dram_info;
++void orion5x_setup_cpu_mbus_bridge(void);
++void orion5x_setup_dev_boot_win(u32 base, u32 size);
++void orion5x_setup_dev0_win(u32 base, u32 size);
++void orion5x_setup_dev1_win(u32 base, u32 size);
++void orion5x_setup_dev2_win(u32 base, u32 size);
++void orion5x_setup_pcie_wa_win(u32 base, u32 size);
++void orion5x_setup_eth_wins(void);
++
++/*
++ * Shared code used internally by other Orion core functions.
++ * (/mach-orion/pci.c)
++ */
++
++struct pci_sys_data;
++struct pci_bus;
++
++void orion5x_pcie_id(u32 *dev, u32 *rev);
++int orion5x_pcie_local_bus_nr(void);
++int orion5x_pci_local_bus_nr(void);
++int orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys);
++struct pci_bus *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys);
++
++/*
++ * Valid GPIO pins according to MPP setup, used by machine-setup.
++ * (/mach-orion/gpio.c).
++ */
++
++void orion5x_gpio_set_valid_pins(u32 pins);
++void gpio_display(void); /* debug */
++
++/*
++ * Pull in Orion Ethernet platform_data, used by machine-setup
++ */
++
++struct mv643xx_eth_platform_data;
++
++void orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data);
++
++/*
++ * Orion Sata platform_data, used by machine-setup
++ */
++
++struct mv_sata_platform_data;
++
++void orion5x_sata_init(struct mv_sata_platform_data *sata_data);
++
++struct machine_desc;
++struct meminfo;
++struct tag;
++extern void __init tag_fixup_mem32(struct machine_desc *, struct tag *,
++ char **, struct meminfo *);
++
++
++#endif
+diff --git a/arch/arm/mach-orion5x/db88f5281-setup.c b/arch/arm/mach-orion5x/db88f5281-setup.c
+new file mode 100644
+index 0000000..872aed3
+--- /dev/null
++++ b/arch/arm/mach-orion5x/db88f5281-setup.c
+@@ -0,0 +1,361 @@
++/*
++ * arch/arm/mach-orion5x/db88f5281-setup.c
++ *
++ * Marvell Orion-2 Development Board Setup
++ *
++ * Maintainer: Tzachi Perelstein <tzachi at marvell.com>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/pci.h>
++#include <linux/irq.h>
++#include <linux/mtd/physmap.h>
++#include <linux/mtd/nand.h>
++#include <linux/timer.h>
++#include <linux/mv643xx_eth.h>
++#include <linux/i2c.h>
++#include <asm/mach-types.h>
++#include <asm/gpio.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/pci.h>
++#include <asm/arch/orion5x.h>
++#include <asm/plat-orion/orion_nand.h>
++#include "common.h"
++
++/*****************************************************************************
++ * DB-88F5281 on board devices
++ ****************************************************************************/
++
++/*
++ * 512K NOR flash Device bus boot chip select
++ */
++
++#define DB88F5281_NOR_BOOT_BASE 0xf4000000
++#define DB88F5281_NOR_BOOT_SIZE SZ_512K
++
++/*
++ * 7-Segment on Device bus chip select 0
++ */
++
++#define DB88F5281_7SEG_BASE 0xfa000000
++#define DB88F5281_7SEG_SIZE SZ_1K
++
++/*
++ * 32M NOR flash on Device bus chip select 1
++ */
++
++#define DB88F5281_NOR_BASE 0xfc000000
++#define DB88F5281_NOR_SIZE SZ_32M
++
++/*
++ * 32M NAND flash on Device bus chip select 2
++ */
++
++#define DB88F5281_NAND_BASE 0xfa800000
++#define DB88F5281_NAND_SIZE SZ_1K
++
++/*
++ * PCI
++ */
++
++#define DB88F5281_PCI_SLOT0_OFFS 7
++#define DB88F5281_PCI_SLOT0_IRQ_PIN 12
++#define DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN 13
++
++/*****************************************************************************
++ * 512M NOR Flash on Device bus Boot CS
++ ****************************************************************************/
++
++static struct physmap_flash_data db88f5281_boot_flash_data = {
++ .width = 1, /* 8 bit bus width */
++};
++
++static struct resource db88f5281_boot_flash_resource = {
++ .flags = IORESOURCE_MEM,
++ .start = DB88F5281_NOR_BOOT_BASE,
++ .end = DB88F5281_NOR_BOOT_BASE + DB88F5281_NOR_BOOT_SIZE - 1,
++};
++
++static struct platform_device db88f5281_boot_flash = {
++ .name = "physmap-flash",
++ .id = 0,
++ .dev = {
++ .platform_data = &db88f5281_boot_flash_data,
++ },
++ .num_resources = 1,
++ .resource = &db88f5281_boot_flash_resource,
++};
++
++/*****************************************************************************
++ * 32M NOR Flash on Device bus CS1
++ ****************************************************************************/
++
++static struct physmap_flash_data db88f5281_nor_flash_data = {
++ .width = 4, /* 32 bit bus width */
++};
++
++static struct resource db88f5281_nor_flash_resource = {
++ .flags = IORESOURCE_MEM,
++ .start = DB88F5281_NOR_BASE,
++ .end = DB88F5281_NOR_BASE + DB88F5281_NOR_SIZE - 1,
++};
++
++static struct platform_device db88f5281_nor_flash = {
++ .name = "physmap-flash",
++ .id = 1,
++ .dev = {
++ .platform_data = &db88f5281_nor_flash_data,
++ },
++ .num_resources = 1,
++ .resource = &db88f5281_nor_flash_resource,
++};
++
++/*****************************************************************************
++ * 32M NAND Flash on Device bus CS2
++ ****************************************************************************/
++
++static struct mtd_partition db88f5281_nand_parts[] = {
++ {
++ .name = "kernel",
++ .offset = 0,
++ .size = SZ_2M,
++ },
++ {
++ .name = "root",
++ .offset = SZ_2M,
++ .size = (SZ_16M - SZ_2M),
++ },
++ {
++ .name = "user",
++ .offset = SZ_16M,
++ .size = SZ_8M,
++ },
++ {
++ .name = "recovery",
++ .offset = (SZ_16M + SZ_8M),
++ .size = SZ_8M,
++ },
++};
++
++static struct resource db88f5281_nand_resource = {
++ .flags = IORESOURCE_MEM,
++ .start = DB88F5281_NAND_BASE,
++ .end = DB88F5281_NAND_BASE + DB88F5281_NAND_SIZE - 1,
++};
++
++static struct orion_nand_data db88f5281_nand_data = {
++ .parts = db88f5281_nand_parts,
++ .nr_parts = ARRAY_SIZE(db88f5281_nand_parts),
++ .cle = 0,
++ .ale = 1,
++ .width = 8,
++};
++
++static struct platform_device db88f5281_nand_flash = {
++ .name = "orion_nand",
++ .id = -1,
++ .dev = {
++ .platform_data = &db88f5281_nand_data,
++ },
++ .resource = &db88f5281_nand_resource,
++ .num_resources = 1,
++};
++
++/*****************************************************************************
++ * 7-Segment on Device bus CS0
++ * Dummy counter every 2 sec
++ ****************************************************************************/
++
++static void __iomem *db88f5281_7seg;
++static struct timer_list db88f5281_timer;
++
++static void db88f5281_7seg_event(unsigned long data)
++{
++ static int count = 0;
++ writel(0, db88f5281_7seg + (count << 4));
++ count = (count + 1) & 7;
++ mod_timer(&db88f5281_timer, jiffies + 2 * HZ);
++}
++
++static int __init db88f5281_7seg_init(void)
++{
++ if (machine_is_db88f5281()) {
++ db88f5281_7seg = ioremap(DB88F5281_7SEG_BASE,
++ DB88F5281_7SEG_SIZE);
++ if (!db88f5281_7seg) {
++ printk(KERN_ERR "Failed to ioremap db88f5281_7seg\n");
++ return -EIO;
++ }
++ setup_timer(&db88f5281_timer, db88f5281_7seg_event, 0);
++ mod_timer(&db88f5281_timer, jiffies + 2 * HZ);
++ }
++
++ return 0;
++}
++
++__initcall(db88f5281_7seg_init);
++
++/*****************************************************************************
++ * PCI
++ ****************************************************************************/
++
++void __init db88f5281_pci_preinit(void)
++{
++ int pin;
++
++ /*
++ * Configure PCI GPIO IRQ pins
++ */
++ pin = DB88F5281_PCI_SLOT0_IRQ_PIN;
++ if (gpio_request(pin, "PCI Int1") == 0) {
++ if (gpio_direction_input(pin) == 0) {
++ set_irq_type(gpio_to_irq(pin), IRQT_LOW);
++ } else {
++ printk(KERN_ERR "db88f5281_pci_preinit faield to "
++ "set_irq_type pin %d\n", pin);
++ gpio_free(pin);
++ }
++ } else {
++ printk(KERN_ERR "db88f5281_pci_preinit failed to gpio_request %d\n", pin);
++ }
++
++ pin = DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN;
++ if (gpio_request(pin, "PCI Int2") == 0) {
++ if (gpio_direction_input(pin) == 0) {
++ set_irq_type(gpio_to_irq(pin), IRQT_LOW);
++ } else {
++ printk(KERN_ERR "db88f5281_pci_preinit faield "
++ "to set_irq_type pin %d\n", pin);
++ gpio_free(pin);
++ }
++ } else {
++ printk(KERN_ERR "db88f5281_pci_preinit failed to gpio_request %d\n", pin);
++ }
++}
++
++static int __init db88f5281_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++ /*
++ * PCIE IRQ is connected internally (not GPIO)
++ */
++ if (dev->bus->number == orion5x_pcie_local_bus_nr())
++ return IRQ_ORION5X_PCIE0_INT;
++
++ /*
++ * PCI IRQs are connected via GPIOs
++ */
++ switch (slot - DB88F5281_PCI_SLOT0_OFFS) {
++ case 0:
++ return gpio_to_irq(DB88F5281_PCI_SLOT0_IRQ_PIN);
++ case 1:
++ case 2:
++ return gpio_to_irq(DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN);
++ default:
++ return -1;
++ }
++}
++
++static struct hw_pci db88f5281_pci __initdata = {
++ .nr_controllers = 2,
++ .preinit = db88f5281_pci_preinit,
++ .swizzle = pci_std_swizzle,
++ .setup = orion5x_pci_sys_setup,
++ .scan = orion5x_pci_sys_scan_bus,
++ .map_irq = db88f5281_pci_map_irq,
++};
++
++static int __init db88f5281_pci_init(void)
++{
++ if (machine_is_db88f5281())
++ pci_common_init(&db88f5281_pci);
++
++ return 0;
++}
++
++subsys_initcall(db88f5281_pci_init);
++
++/*****************************************************************************
++ * Ethernet
++ ****************************************************************************/
++static struct mv643xx_eth_platform_data db88f5281_eth_data = {
++ .phy_addr = 8,
++ .force_phy_addr = 1,
++};
++
++/*****************************************************************************
++ * RTC DS1339 on I2C bus
++ ****************************************************************************/
++static struct i2c_board_info __initdata db88f5281_i2c_rtc = {
++ .driver_name = "rtc-ds1307",
++ .type = "ds1339",
++ .addr = 0x68,
++};
++
++/*****************************************************************************
++ * General Setup
++ ****************************************************************************/
++
++static struct platform_device *db88f5281_devs[] __initdata = {
++ &db88f5281_boot_flash,
++ &db88f5281_nor_flash,
++ &db88f5281_nand_flash,
++};
++
++static void __init db88f5281_init(void)
++{
++ /*
++ * Basic Orion setup. Need to be called early.
++ */
++ orion5x_init();
++
++ /*
++ * Setup the CPU address decode windows for our on-board devices
++ */
++ orion5x_setup_dev_boot_win(DB88F5281_NOR_BOOT_BASE,
++ DB88F5281_NOR_BOOT_SIZE);
++ orion5x_setup_dev0_win(DB88F5281_7SEG_BASE, DB88F5281_7SEG_SIZE);
++ orion5x_setup_dev1_win(DB88F5281_NOR_BASE, DB88F5281_NOR_SIZE);
++ orion5x_setup_dev2_win(DB88F5281_NAND_BASE, DB88F5281_NAND_SIZE);
++
++ /*
++ * Setup Multiplexing Pins:
++ * MPP0: GPIO (USB Over Current) MPP1: GPIO (USB Vbat input)
++ * MPP2: PCI_REQn[2] MPP3: PCI_GNTn[2]
++ * MPP4: PCI_REQn[3] MPP5: PCI_GNTn[3]
++ * MPP6: GPIO (JP0, CON17.2) MPP7: GPIO (JP1, CON17.1)
++ * MPP8: GPIO (JP2, CON11.2) MPP9: GPIO (JP3, CON11.3)
++ * MPP10: GPIO (RTC int) MPP11: GPIO (Baud Rate Generator)
++ * MPP12: GPIO (PCI int 1) MPP13: GPIO (PCI int 2)
++ * MPP14: NAND_REn[2] MPP15: NAND_WEn[2]
++ * MPP16: UART1_RX MPP17: UART1_TX
++ * MPP18: UART1_CTS MPP19: UART1_RTS
++ * MPP-DEV: DEV_D[16:31]
++ */
++ orion5x_write(MPP_0_7_CTRL, 0x00222203);
++ orion5x_write(MPP_8_15_CTRL, 0x44000000);
++ orion5x_write(MPP_16_19_CTRL, 0);
++ orion5x_write(MPP_DEV_CTRL, 0);
++
++ orion5x_gpio_set_valid_pins(0x00003fc3);
++
++ platform_add_devices(db88f5281_devs, ARRAY_SIZE(db88f5281_devs));
++ i2c_register_board_info(0, &db88f5281_i2c_rtc, 1);
++ orion5x_eth_init(&db88f5281_eth_data);
++}
++
++MACHINE_START(DB88F5281, "Marvell Orion-2 Development Board")
++ /* Maintainer: Tzachi Perelstein <tzachi at marvell.com> */
++ .phys_io = ORION5X_REGS_PHYS_BASE,
++ .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xfffc,
++ .boot_params = 0x00000100,
++ .init_machine = db88f5281_init,
++ .map_io = orion5x_map_io,
++ .init_irq = orion5x_init_irq,
++ .timer = &orion5x_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c
+new file mode 100644
+index 0000000..d67790e
+--- /dev/null
++++ b/arch/arm/mach-orion5x/dns323-setup.c
+@@ -0,0 +1,320 @@
++/*
++ * arch/arm/mach-orion5x/dns323-setup.c
++ *
++ * Copyright (C) 2007 Herbert Valerio Riedel <hvr at gnu.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/pci.h>
++#include <linux/irq.h>
++#include <linux/mtd/physmap.h>
++#include <linux/mv643xx_eth.h>
++#include <linux/leds.h>
++#include <linux/gpio_keys.h>
++#include <linux/input.h>
++#include <linux/i2c.h>
++#include <asm/mach-types.h>
++#include <asm/gpio.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/pci.h>
++#include <asm/arch/orion5x.h>
++#include "common.h"
++
++#define DNS323_GPIO_LED_RIGHT_AMBER 1
++#define DNS323_GPIO_LED_LEFT_AMBER 2
++#define DNS323_GPIO_LED_POWER 5
++#define DNS323_GPIO_OVERTEMP 6
++#define DNS323_GPIO_RTC 7
++#define DNS323_GPIO_POWER_OFF 8
++#define DNS323_GPIO_KEY_POWER 9
++#define DNS323_GPIO_KEY_RESET 10
++
++/****************************************************************************
++ * PCI setup
++ */
++
++static int __init dns323_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++ /* PCI-E */
++ if (dev->bus->number == orion5x_pcie_local_bus_nr())
++ return IRQ_ORION5X_PCIE0_INT;
++
++ pr_err("%s: requested mapping for unknown bus\n", __func__);
++
++ return -1;
++}
++
++static struct hw_pci dns323_pci __initdata = {
++ .nr_controllers = 1,
++ .swizzle = pci_std_swizzle,
++ .setup = orion5x_pci_sys_setup,
++ .scan = orion5x_pci_sys_scan_bus,
++ .map_irq = dns323_pci_map_irq,
++};
++
++static int __init dns323_pci_init(void)
++{
++ if (machine_is_dns323())
++ pci_common_init(&dns323_pci);
++
++ return 0;
++}
++
++subsys_initcall(dns323_pci_init);
++
++/****************************************************************************
++ * Ethernet
++ */
++
++static struct mv643xx_eth_platform_data dns323_eth_data = {
++ .phy_addr = 8,
++ .force_phy_addr = 1,
++};
++
++/****************************************************************************
++ * 8MiB NOR flash (Spansion S29GL064M90TFIR4)
++ *
++ * Layout as used by D-Link:
++ * 0x00000000-0x00010000 : "MTD1"
++ * 0x00010000-0x00020000 : "MTD2"
++ * 0x00020000-0x001a0000 : "Linux Kernel"
++ * 0x001a0000-0x007d0000 : "File System"
++ * 0x007d0000-0x00800000 : "u-boot"
++ */
++
++#define DNS323_NOR_BOOT_BASE 0xf4000000
++#define DNS323_NOR_BOOT_SIZE SZ_8M
++
++static struct mtd_partition dns323_partitions[] = {
++ {
++ .name = "MTD1",
++ .size = 0x00010000,
++ .offset = 0,
++ }, {
++ .name = "MTD2",
++ .size = 0x00010000,
++ .offset = 0x00010000,
++ }, {
++ .name = "Linux Kernel",
++ .size = 0x00180000,
++ .offset = 0x00020000,
++ }, {
++ .name = "File System",
++ .size = 0x00630000,
++ .offset = 0x001A0000,
++ }, {
++ .name = "u-boot",
++ .size = 0x00030000,
++ .offset = 0x007d0000,
++ }
++};
++
++static struct physmap_flash_data dns323_nor_flash_data = {
++ .width = 1,
++ .parts = dns323_partitions,
++ .nr_parts = ARRAY_SIZE(dns323_partitions)
++};
++
++static struct resource dns323_nor_flash_resource = {
++ .flags = IORESOURCE_MEM,
++ .start = DNS323_NOR_BOOT_BASE,
++ .end = DNS323_NOR_BOOT_BASE + DNS323_NOR_BOOT_SIZE - 1,
++};
++
++static struct platform_device dns323_nor_flash = {
++ .name = "physmap-flash",
++ .id = 0,
++ .dev = { .platform_data = &dns323_nor_flash_data, },
++ .resource = &dns323_nor_flash_resource,
++ .num_resources = 1,
++};
++
++/****************************************************************************
++ * GPIO LEDs (simple - doesn't use hardware blinking support)
++ */
++
++static struct gpio_led dns323_leds[] = {
++ {
++ .name = "power:blue",
++ .gpio = DNS323_GPIO_LED_POWER,
++ .active_low = 1,
++ }, {
++ .name = "right:amber",
++ .gpio = DNS323_GPIO_LED_RIGHT_AMBER,
++ .active_low = 1,
++ }, {
++ .name = "left:amber",
++ .gpio = DNS323_GPIO_LED_LEFT_AMBER,
++ .active_low = 1,
++ },
++};
++
++static struct gpio_led_platform_data dns323_led_data = {
++ .num_leds = ARRAY_SIZE(dns323_leds),
++ .leds = dns323_leds,
++};
++
++static struct platform_device dns323_gpio_leds = {
++ .name = "leds-gpio",
++ .id = -1,
++ .dev = { .platform_data = &dns323_led_data, },
++};
++
++/****************************************************************************
++ * GPIO Attached Keys
++ */
++
++static struct gpio_keys_button dns323_buttons[] = {
++ {
++ .code = KEY_RESTART,
++ .gpio = DNS323_GPIO_KEY_RESET,
++ .desc = "Reset Button",
++ .active_low = 1,
++ },
++ {
++ .code = KEY_POWER,
++ .gpio = DNS323_GPIO_KEY_POWER,
++ .desc = "Power Button",
++ .active_low = 1,
++ }
++};
++
++static struct gpio_keys_platform_data dns323_button_data = {
++ .buttons = dns323_buttons,
++ .nbuttons = ARRAY_SIZE(dns323_buttons),
++};
++
++static struct platform_device dns323_button_device = {
++ .name = "gpio-keys",
++ .id = -1,
++ .num_resources = 0,
++ .dev = { .platform_data = &dns323_button_data, },
++};
++
++/****************************************************************************
++ * General Setup
++ */
++
++static struct platform_device *dns323_plat_devices[] __initdata = {
++ &dns323_nor_flash,
++ &dns323_gpio_leds,
++ &dns323_button_device,
++};
++
++/*
++ * On the DNS-323 the following devices are attached via I2C:
++ *
++ * i2c addr | chip | description
++ * 0x3e | GMT G760Af | fan speed PWM controller
++ * 0x48 | GMT G751-2f | temp. sensor and therm. watchdog (LM75 compatible)
++ * 0x68 | ST M41T80 | RTC w/ alarm
++ */
++static struct i2c_board_info __initdata dns323_i2c_devices[] = {
++ {
++ I2C_BOARD_INFO("g760a", 0x3e),
++ .type = "g760a",
++ },
++#if 0
++ /* this entry requires the new-style driver model lm75 driver,
++ * for the meantime "insmod lm75.ko force_lm75=0,0x48" is needed */
++ {
++ I2C_BOARD_INFO("lm75", 0x48),
++ .type = "g751",
++ },
++#endif
++ {
++ I2C_BOARD_INFO("rtc-m41t80", 0x68),
++ .type = "m41t80",
++ }
++};
++
++/* DNS-323 specific power off method */
++static void dns323_power_off(void)
++{
++ pr_info("%s: triggering power-off...\n", __func__);
++ gpio_set_value(DNS323_GPIO_POWER_OFF, 1);
++}
++
++static void __init dns323_init(void)
++{
++ /* Setup basic Orion functions. Need to be called early. */
++ orion5x_init();
++
++ /* setup flash mapping
++ * CS3 holds a 8 MB Spansion S29GL064M90TFIR4
++ */
++ orion5x_setup_dev_boot_win(DNS323_NOR_BOOT_BASE, DNS323_NOR_BOOT_SIZE);
++
++ /* DNS-323 has a Marvell 88X7042 SATA controller attached via PCIE
++ *
++ * Open a special address decode windows for the PCIE WA.
++ */
++ orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
++ ORION5X_PCIE_WA_SIZE);
++
++ /* set MPP to 0 as D-Link's 2.6.12.6 kernel did */
++ orion5x_write(MPP_0_7_CTRL, 0);
++ orion5x_write(MPP_8_15_CTRL, 0);
++ orion5x_write(MPP_16_19_CTRL, 0);
++ orion5x_write(MPP_DEV_CTRL, 0);
++
++ /* Define used GPIO pins
++
++ GPIO Map:
++
++ | 0 | | PEX_RST_OUT (not controlled by GPIO)
++ | 1 | Out | right amber LED (= sata ch0 LED) (low-active)
++ | 2 | Out | left amber LED (= sata ch1 LED) (low-active)
++ | 3 | Out | //unknown//
++ | 4 | Out | power button LED (low-active, together with pin #5)
++ | 5 | Out | power button LED (low-active, together with pin #4)
++ | 6 | In | GMT G751-2f overtemp. shutdown signal (low-active)
++ | 7 | In | M41T80 nIRQ/OUT/SQW signal
++ | 8 | Out | triggers power off (high-active)
++ | 9 | In | power button switch (low-active)
++ | 10 | In | reset button switch (low-active)
++ | 11 | Out | //unknown//
++ | 12 | Out | //unknown//
++ | 13 | Out | //unknown//
++ | 14 | Out | //unknown//
++ | 15 | Out | //unknown//
++ */
++ orion5x_gpio_set_valid_pins(0x07f6);
++
++ /* register dns323 specific power-off method */
++ if ((gpio_request(DNS323_GPIO_POWER_OFF, "POWEROFF") != 0)
++ || (gpio_direction_output(DNS323_GPIO_POWER_OFF, 0) != 0))
++ pr_err("DNS323: failed to setup power-off GPIO\n");
++
++ pm_power_off = dns323_power_off;
++
++ /* register flash and other platform devices */
++ platform_add_devices(dns323_plat_devices,
++ ARRAY_SIZE(dns323_plat_devices));
++
++ i2c_register_board_info(0, dns323_i2c_devices,
++ ARRAY_SIZE(dns323_i2c_devices));
++
++ orion5x_eth_init(&dns323_eth_data);
++}
++
++/* Warning: D-Link uses a wrong mach-type (=526) in their bootloader */
++MACHINE_START(DNS323, "D-Link DNS-323")
++ /* Maintainer: Herbert Valerio Riedel <hvr at gnu.org> */
++ .phys_io = ORION5X_REGS_PHYS_BASE,
++ .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
++ .boot_params = 0x00000100,
++ .init_machine = dns323_init,
++ .map_io = orion5x_map_io,
++ .init_irq = orion5x_init_irq,
++ .timer = &orion5x_timer,
++ .fixup = tag_fixup_mem32,
++MACHINE_END
+diff --git a/arch/arm/mach-orion5x/gpio.c b/arch/arm/mach-orion5x/gpio.c
+new file mode 100644
+index 0000000..8108c31
+--- /dev/null
++++ b/arch/arm/mach-orion5x/gpio.c
+@@ -0,0 +1,226 @@
++/*
++ * arch/arm/mach-orion5x/gpio.c
++ *
++ * GPIO functions for Marvell Orion System On Chip
++ *
++ * Maintainer: Tzachi Perelstein <tzachi at marvell.com>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/spinlock.h>
++#include <linux/bitops.h>
++#include <asm/gpio.h>
++#include <asm/io.h>
++#include <asm/arch/orion5x.h>
++#include "common.h"
++
++static DEFINE_SPINLOCK(gpio_lock);
++static unsigned long gpio_valid[BITS_TO_LONGS(GPIO_MAX)];
++static const char *gpio_label[GPIO_MAX]; /* non null for allocated GPIOs */
++
++void __init orion5x_gpio_set_valid_pins(u32 pins)
++{
++ gpio_valid[0] = pins;
++}
++
++/*
++ * GENERIC_GPIO primitives
++ */
++int gpio_direction_input(unsigned pin)
++{
++ unsigned long flags;
++
++ if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
++ pr_debug("%s: invalid GPIO %d\n", __func__, pin);
++ return -EINVAL;
++ }
++
++ spin_lock_irqsave(&gpio_lock, flags);
++
++ /*
++ * Some callers might have not used the gpio_request(),
++ * so flag this pin as requested now.
++ */
++ if (!gpio_label[pin])
++ gpio_label[pin] = "?";
++
++ orion5x_setbits(GPIO_IO_CONF, 1 << pin);
++
++ spin_unlock_irqrestore(&gpio_lock, flags);
++ return 0;
++}
++EXPORT_SYMBOL(gpio_direction_input);
++
++int gpio_direction_output(unsigned pin, int value)
++{
++ unsigned long flags;
++ int mask;
++
++ if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
++ pr_debug("%s: invalid GPIO %d\n", __func__, pin);
++ return -EINVAL;
++ }
++
++ spin_lock_irqsave(&gpio_lock, flags);
++
++ /*
++ * Some callers might have not used the gpio_request(),
++ * so flag this pin as requested now.
++ */
++ if (!gpio_label[pin])
++ gpio_label[pin] = "?";
++
++ mask = 1 << pin;
++ orion5x_clrbits(GPIO_BLINK_EN, mask);
++ if (value)
++ orion5x_setbits(GPIO_OUT, mask);
++ else
++ orion5x_clrbits(GPIO_OUT, mask);
++ orion5x_clrbits(GPIO_IO_CONF, mask);
++
++ spin_unlock_irqrestore(&gpio_lock, flags);
++ return 0;
++}
++EXPORT_SYMBOL(gpio_direction_output);
++
++int gpio_get_value(unsigned pin)
++{
++ int val, mask = 1 << pin;
++
++ if (orion5x_read(GPIO_IO_CONF) & mask)
++ val = orion5x_read(GPIO_DATA_IN) ^ orion5x_read(GPIO_IN_POL);
++ else
++ val = orion5x_read(GPIO_OUT);
++
++ return val & mask;
++}
++EXPORT_SYMBOL(gpio_get_value);
++
++void gpio_set_value(unsigned pin, int value)
++{
++ unsigned long flags;
++ int mask = 1 << pin;
++
++ spin_lock_irqsave(&gpio_lock, flags);
++
++ orion5x_clrbits(GPIO_BLINK_EN, mask);
++ if (value)
++ orion5x_setbits(GPIO_OUT, mask);
++ else
++ orion5x_clrbits(GPIO_OUT, mask);
++
++ spin_unlock_irqrestore(&gpio_lock, flags);
++}
++EXPORT_SYMBOL(gpio_set_value);
++
++void orion5x_gpio_set_blink(unsigned pin, int blink)
++{
++ unsigned long flags;
++ int mask = 1 << pin;
++
++ spin_lock_irqsave(&gpio_lock, flags);
++
++ orion5x_clrbits(GPIO_OUT, mask);
++ if (blink)
++ orion5x_setbits(GPIO_BLINK_EN, mask);
++ else
++ orion5x_clrbits(GPIO_BLINK_EN, mask);
++
++ spin_unlock_irqrestore(&gpio_lock, flags);
++}
++EXPORT_SYMBOL(orion5x_gpio_set_blink);
++
++int gpio_request(unsigned pin, const char *label)
++{
++ int ret = 0;
++ unsigned long flags;
++
++ if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
++ pr_debug("%s: invalid GPIO %d\n", __func__, pin);
++ return -EINVAL;
++ }
++
++ spin_lock_irqsave(&gpio_lock, flags);
++
++ if (gpio_label[pin]) {
++ pr_debug("%s: GPIO %d already used as %s\n",
++ __func__, pin, gpio_label[pin]);
++ ret = -EBUSY;
++ } else
++ gpio_label[pin] = label ? label : "?";
++
++ spin_unlock_irqrestore(&gpio_lock, flags);
++ return ret;
++}
++EXPORT_SYMBOL(gpio_request);
++
++void gpio_free(unsigned pin)
++{
++ if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
++ pr_debug("%s: invalid GPIO %d\n", __func__, pin);
++ return;
++ }
++
++ if (!gpio_label[pin])
++ pr_warning("%s: GPIO %d already freed\n", __func__, pin);
++ else
++ gpio_label[pin] = NULL;
++}
++EXPORT_SYMBOL(gpio_free);
++
++/* Debug helper */
++void gpio_display(void)
++{
++ int i;
++
++ for (i = 0; i < GPIO_MAX; i++) {
++ printk(KERN_DEBUG "Pin-%d: ", i);
++
++ if (!test_bit(i, gpio_valid)) {
++ printk("non-GPIO\n");
++ } else if (!gpio_label[i]) {
++ printk("GPIO, free\n");
++ } else {
++ printk("GPIO, used by %s, ", gpio_label[i]);
++ if (orion5x_read(GPIO_IO_CONF) & (1 << i)) {
++ printk("input, active %s, level %s, edge %s\n",
++ ((orion5x_read(GPIO_IN_POL) >> i) & 1) ? "low" : "high",
++ ((orion5x_read(GPIO_LEVEL_MASK) >> i) & 1) ? "enabled" : "masked",
++ ((orion5x_read(GPIO_EDGE_MASK) >> i) & 1) ? "enabled" : "masked");
++ } else {
++ printk("output, val=%d\n", (orion5x_read(GPIO_OUT) >> i) & 1);
++ }
++ }
++ }
++
++ printk(KERN_DEBUG "MPP_0_7_CTRL (0x%08x) = 0x%08x\n",
++ MPP_0_7_CTRL, orion5x_read(MPP_0_7_CTRL));
++ printk(KERN_DEBUG "MPP_8_15_CTRL (0x%08x) = 0x%08x\n",
++ MPP_8_15_CTRL, orion5x_read(MPP_8_15_CTRL));
++ printk(KERN_DEBUG "MPP_16_19_CTRL (0x%08x) = 0x%08x\n",
++ MPP_16_19_CTRL, orion5x_read(MPP_16_19_CTRL));
++ printk(KERN_DEBUG "MPP_DEV_CTRL (0x%08x) = 0x%08x\n",
++ MPP_DEV_CTRL, orion5x_read(MPP_DEV_CTRL));
++ printk(KERN_DEBUG "GPIO_OUT (0x%08x) = 0x%08x\n",
++ GPIO_OUT, orion5x_read(GPIO_OUT));
++ printk(KERN_DEBUG "GPIO_IO_CONF (0x%08x) = 0x%08x\n",
++ GPIO_IO_CONF, orion5x_read(GPIO_IO_CONF));
++ printk(KERN_DEBUG "GPIO_BLINK_EN (0x%08x) = 0x%08x\n",
++ GPIO_BLINK_EN, orion5x_read(GPIO_BLINK_EN));
++ printk(KERN_DEBUG "GPIO_IN_POL (0x%08x) = 0x%08x\n",
++ GPIO_IN_POL, orion5x_read(GPIO_IN_POL));
++ printk(KERN_DEBUG "GPIO_DATA_IN (0x%08x) = 0x%08x\n",
++ GPIO_DATA_IN, orion5x_read(GPIO_DATA_IN));
++ printk(KERN_DEBUG "GPIO_LEVEL_MASK (0x%08x) = 0x%08x\n",
++ GPIO_LEVEL_MASK, orion5x_read(GPIO_LEVEL_MASK));
++ printk(KERN_DEBUG "GPIO_EDGE_CAUSE (0x%08x) = 0x%08x\n",
++ GPIO_EDGE_CAUSE, orion5x_read(GPIO_EDGE_CAUSE));
++ printk(KERN_DEBUG "GPIO_EDGE_MASK (0x%08x) = 0x%08x\n",
++ GPIO_EDGE_MASK, orion5x_read(GPIO_EDGE_MASK));
++}
+diff --git a/arch/arm/mach-orion5x/irq.c b/arch/arm/mach-orion5x/irq.c
+new file mode 100644
+index 0000000..dd21f38
+--- /dev/null
++++ b/arch/arm/mach-orion5x/irq.c
+@@ -0,0 +1,211 @@
++/*
++ * arch/arm/mach-orion5x/irq.c
++ *
++ * Core IRQ functions for Marvell Orion System On Chip
++ *
++ * Maintainer: Tzachi Perelstein <tzachi at marvell.com>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/irq.h>
++#include <asm/gpio.h>
++#include <asm/io.h>
++#include <asm/arch/orion5x.h>
++#include <asm/plat-orion/irq.h>
++#include "common.h"
++
++/*****************************************************************************
++ * Orion GPIO IRQ
++ *
++ * GPIO_IN_POL register controlls whether GPIO_DATA_IN will hold the same
++ * value of the line or the opposite value.
++ *
++ * Level IRQ handlers: DATA_IN is used directly as cause register.
++ * Interrupt are masked by LEVEL_MASK registers.
++ * Edge IRQ handlers: Change in DATA_IN are latched in EDGE_CAUSE.
++ * Interrupt are masked by EDGE_MASK registers.
++ * Both-edge handlers: Similar to regular Edge handlers, but also swaps
++ * the polarity to catch the next line transaction.
++ * This is a race condition that might not perfectly
++ * work on some use cases.
++ *
++ * Every eight GPIO lines are grouped (OR'ed) before going up to main
++ * cause register.
++ *
++ * EDGE cause mask
++ * data-in /--------| |-----| |----\
++ * -----| |----- ---- to main cause reg
++ * X \----------------| |----/
++ * polarity LEVEL mask
++ *
++ ****************************************************************************/
++static void orion5x_gpio_irq_ack(u32 irq)
++{
++ int pin = irq_to_gpio(irq);
++ if (irq_desc[irq].status & IRQ_LEVEL)
++ /*
++ * Mask bit for level interrupt
++ */
++ orion5x_clrbits(GPIO_LEVEL_MASK, 1 << pin);
++ else
++ /*
++ * Clear casue bit for egde interrupt
++ */
++ orion5x_clrbits(GPIO_EDGE_CAUSE, 1 << pin);
++}
++
++static void orion5x_gpio_irq_mask(u32 irq)
++{
++ int pin = irq_to_gpio(irq);
++ if (irq_desc[irq].status & IRQ_LEVEL)
++ orion5x_clrbits(GPIO_LEVEL_MASK, 1 << pin);
++ else
++ orion5x_clrbits(GPIO_EDGE_MASK, 1 << pin);
++}
++
++static void orion5x_gpio_irq_unmask(u32 irq)
++{
++ int pin = irq_to_gpio(irq);
++ if (irq_desc[irq].status & IRQ_LEVEL)
++ orion5x_setbits(GPIO_LEVEL_MASK, 1 << pin);
++ else
++ orion5x_setbits(GPIO_EDGE_MASK, 1 << pin);
++}
++
++static int orion5x_gpio_set_irq_type(u32 irq, u32 type)
++{
++ int pin = irq_to_gpio(irq);
++ struct irq_desc *desc;
++
++ if ((orion5x_read(GPIO_IO_CONF) & (1 << pin)) == 0) {
++ printk(KERN_ERR "orion5x_gpio_set_irq_type failed "
++ "(irq %d, pin %d).\n", irq, pin);
++ return -EINVAL;
++ }
++
++ desc = irq_desc + irq;
++
++ switch (type) {
++ case IRQT_HIGH:
++ desc->handle_irq = handle_level_irq;
++ desc->status |= IRQ_LEVEL;
++ orion5x_clrbits(GPIO_IN_POL, (1 << pin));
++ break;
++ case IRQT_LOW:
++ desc->handle_irq = handle_level_irq;
++ desc->status |= IRQ_LEVEL;
++ orion5x_setbits(GPIO_IN_POL, (1 << pin));
++ break;
++ case IRQT_RISING:
++ desc->handle_irq = handle_edge_irq;
++ desc->status &= ~IRQ_LEVEL;
++ orion5x_clrbits(GPIO_IN_POL, (1 << pin));
++ break;
++ case IRQT_FALLING:
++ desc->handle_irq = handle_edge_irq;
++ desc->status &= ~IRQ_LEVEL;
++ orion5x_setbits(GPIO_IN_POL, (1 << pin));
++ break;
++ case IRQT_BOTHEDGE:
++ desc->handle_irq = handle_edge_irq;
++ desc->status &= ~IRQ_LEVEL;
++ /*
++ * set initial polarity based on current input level
++ */
++ if ((orion5x_read(GPIO_IN_POL) ^ orion5x_read(GPIO_DATA_IN))
++ & (1 << pin))
++ orion5x_setbits(GPIO_IN_POL, (1 << pin)); /* falling */
++ else
++ orion5x_clrbits(GPIO_IN_POL, (1 << pin)); /* rising */
++
++ break;
++ default:
++ printk(KERN_ERR "failed to set irq=%d (type=%d)\n", irq, type);
++ return -EINVAL;
++ }
++
++ desc->status &= ~IRQ_TYPE_SENSE_MASK;
++ desc->status |= type & IRQ_TYPE_SENSE_MASK;
++
++ return 0;
++}
++
++static struct irq_chip orion5x_gpio_irq_chip = {
++ .name = "Orion-IRQ-GPIO",
++ .ack = orion5x_gpio_irq_ack,
++ .mask = orion5x_gpio_irq_mask,
++ .unmask = orion5x_gpio_irq_unmask,
++ .set_type = orion5x_gpio_set_irq_type,
++};
++
++static void orion5x_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
++{
++ u32 cause, offs, pin;
++
++ BUG_ON(irq < IRQ_ORION5X_GPIO_0_7 || irq > IRQ_ORION5X_GPIO_24_31);
++ offs = (irq - IRQ_ORION5X_GPIO_0_7) * 8;
++ cause = (orion5x_read(GPIO_DATA_IN) & orion5x_read(GPIO_LEVEL_MASK)) |
++ (orion5x_read(GPIO_EDGE_CAUSE) & orion5x_read(GPIO_EDGE_MASK));
++
++ for (pin = offs; pin < offs + 8; pin++) {
++ if (cause & (1 << pin)) {
++ irq = gpio_to_irq(pin);
++ desc = irq_desc + irq;
++ if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQT_BOTHEDGE) {
++ /* Swap polarity (race with GPIO line) */
++ u32 polarity = orion5x_read(GPIO_IN_POL);
++ polarity ^= 1 << pin;
++ orion5x_write(GPIO_IN_POL, polarity);
++ }
++ desc_handle_irq(irq, desc);
++ }
++ }
++}
++
++static void __init orion5x_init_gpio_irq(void)
++{
++ int i;
++ struct irq_desc *desc;
++
++ /*
++ * Mask and clear GPIO IRQ interrupts
++ */
++ orion5x_write(GPIO_LEVEL_MASK, 0x0);
++ orion5x_write(GPIO_EDGE_MASK, 0x0);
++ orion5x_write(GPIO_EDGE_CAUSE, 0x0);
++
++ /*
++ * Register chained level handlers for GPIO IRQs by default.
++ * User can use set_type() if he wants to use edge types handlers.
++ */
++ for (i = IRQ_ORION5X_GPIO_START; i < NR_IRQS; i++) {
++ set_irq_chip(i, &orion5x_gpio_irq_chip);
++ set_irq_handler(i, handle_level_irq);
++ desc = irq_desc + i;
++ desc->status |= IRQ_LEVEL;
++ set_irq_flags(i, IRQF_VALID);
++ }
++ set_irq_chained_handler(IRQ_ORION5X_GPIO_0_7, orion5x_gpio_irq_handler);
++ set_irq_chained_handler(IRQ_ORION5X_GPIO_8_15, orion5x_gpio_irq_handler);
++ set_irq_chained_handler(IRQ_ORION5X_GPIO_16_23, orion5x_gpio_irq_handler);
++ set_irq_chained_handler(IRQ_ORION5X_GPIO_24_31, orion5x_gpio_irq_handler);
++}
++
++/*****************************************************************************
++ * Orion Main IRQ
++ ****************************************************************************/
++static void __init orion5x_init_main_irq(void)
++{
++ orion_irq_init(0, (void __iomem *)MAIN_IRQ_MASK);
++}
++
++void __init orion5x_init_irq(void)
++{
++ orion5x_init_main_irq();
++ orion5x_init_gpio_irq();
++}
+diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c
+new file mode 100644
+index 0000000..9141345
+--- /dev/null
++++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c
+@@ -0,0 +1,256 @@
++/*
++ * arch/arm/mach-orion5x/kurobox_pro-setup.c
++ *
++ * Maintainer: Ronen Shitrit <rshitrit at marvell.com>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/pci.h>
++#include <linux/irq.h>
++#include <linux/mtd/physmap.h>
++#include <linux/mtd/nand.h>
++#include <linux/mv643xx_eth.h>
++#include <linux/i2c.h>
++#include <linux/ata_platform.h>
++#include <asm/mach-types.h>
++#include <asm/gpio.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/pci.h>
++#include <asm/arch/orion5x.h>
++#include <asm/plat-orion/orion_nand.h>
++#include "common.h"
++
++/*****************************************************************************
++ * KUROBOX-PRO Info
++ ****************************************************************************/
++
++/*
++ * 256K NOR flash Device bus boot chip select
++ */
++
++#define KUROBOX_PRO_NOR_BOOT_BASE 0xf4000000
++#define KUROBOX_PRO_NOR_BOOT_SIZE SZ_256K
++
++/*
++ * 256M NAND flash on Device bus chip select 1
++ */
++
++#define KUROBOX_PRO_NAND_BASE 0xfc000000
++#define KUROBOX_PRO_NAND_SIZE SZ_2M
++
++/*****************************************************************************
++ * 256MB NAND Flash on Device bus CS0
++ ****************************************************************************/
++
++static struct mtd_partition kurobox_pro_nand_parts[] = {
++ {
++ .name = "uImage",
++ .offset = 0,
++ .size = SZ_4M,
++ },
++ {
++ .name = "rootfs",
++ .offset = SZ_4M,
++ .size = SZ_64M,
++ },
++ {
++ .name = "extra",
++ .offset = SZ_4M + SZ_64M,
++ .size = SZ_256M - (SZ_4M + SZ_64M),
++ },
++};
++
++static struct resource kurobox_pro_nand_resource = {
++ .flags = IORESOURCE_MEM,
++ .start = KUROBOX_PRO_NAND_BASE,
++ .end = KUROBOX_PRO_NAND_BASE + KUROBOX_PRO_NAND_SIZE - 1,
++};
++
++static struct orion_nand_data kurobox_pro_nand_data = {
++ .parts = kurobox_pro_nand_parts,
++ .nr_parts = ARRAY_SIZE(kurobox_pro_nand_parts),
++ .cle = 0,
++ .ale = 1,
++ .width = 8,
++};
++
++static struct platform_device kurobox_pro_nand_flash = {
++ .name = "orion_nand",
++ .id = -1,
++ .dev = {
++ .platform_data = &kurobox_pro_nand_data,
++ },
++ .resource = &kurobox_pro_nand_resource,
++ .num_resources = 1,
++};
++
++/*****************************************************************************
++ * 256KB NOR Flash on BOOT Device
++ ****************************************************************************/
++
++static struct physmap_flash_data kurobox_pro_nor_flash_data = {
++ .width = 1,
++};
++
++static struct resource kurobox_pro_nor_flash_resource = {
++ .flags = IORESOURCE_MEM,
++ .start = KUROBOX_PRO_NOR_BOOT_BASE,
++ .end = KUROBOX_PRO_NOR_BOOT_BASE + KUROBOX_PRO_NOR_BOOT_SIZE - 1,
++};
++
++static struct platform_device kurobox_pro_nor_flash = {
++ .name = "physmap-flash",
++ .id = 0,
++ .dev = {
++ .platform_data = &kurobox_pro_nor_flash_data,
++ },
++ .num_resources = 1,
++ .resource = &kurobox_pro_nor_flash_resource,
++};
++
++/*****************************************************************************
++ * PCI
++ ****************************************************************************/
++
++static int __init kurobox_pro_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++ /*
++ * PCI isn't used on the Kuro
++ */
++ if (dev->bus->number == orion5x_pcie_local_bus_nr())
++ return IRQ_ORION5X_PCIE0_INT;
++ else
++ printk(KERN_ERR "kurobox_pro_pci_map_irq failed, unknown bus\n");
++
++ return -1;
++}
++
++static struct hw_pci kurobox_pro_pci __initdata = {
++ .nr_controllers = 1,
++ .swizzle = pci_std_swizzle,
++ .setup = orion5x_pci_sys_setup,
++ .scan = orion5x_pci_sys_scan_bus,
++ .map_irq = kurobox_pro_pci_map_irq,
++};
++
++static int __init kurobox_pro_pci_init(void)
++{
++ if (machine_is_kurobox_pro())
++ pci_common_init(&kurobox_pro_pci);
++
++ return 0;
++}
++
++subsys_initcall(kurobox_pro_pci_init);
++
++/*****************************************************************************
++ * Ethernet
++ ****************************************************************************/
++
++static struct mv643xx_eth_platform_data kurobox_pro_eth_data = {
++ .phy_addr = 8,
++ .force_phy_addr = 1,
++};
++
++/*****************************************************************************
++ * RTC 5C372a on I2C bus
++ ****************************************************************************/
++static struct i2c_board_info __initdata kurobox_pro_i2c_rtc = {
++ .driver_name = "rtc-rs5c372",
++ .type = "rs5c372a",
++ .addr = 0x32,
++};
++
++/*****************************************************************************
++ * SATA
++ ****************************************************************************/
++static struct mv_sata_platform_data kurobox_pro_sata_data = {
++ .n_ports = 2,
++};
++
++/*****************************************************************************
++ * General Setup
++ ****************************************************************************/
++
++static void __init kurobox_pro_init(void)
++{
++ /*
++ * Setup basic Orion functions. Need to be called early.
++ */
++ orion5x_init();
++
++ /*
++ * Setup the CPU address decode windows for our devices
++ */
++ orion5x_setup_dev_boot_win(KUROBOX_PRO_NOR_BOOT_BASE,
++ KUROBOX_PRO_NOR_BOOT_SIZE);
++ orion5x_setup_dev0_win(KUROBOX_PRO_NAND_BASE, KUROBOX_PRO_NAND_SIZE);
++
++ /*
++ * Open a special address decode windows for the PCIE WA.
++ */
++ orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
++ ORION5X_PCIE_WA_SIZE);
++
++ /*
++ * Setup Multiplexing Pins --
++ * MPP[0-1] Not used
++ * MPP[2] GPIO Micon
++ * MPP[3] GPIO RTC
++ * MPP[4-5] Not used
++ * MPP[6] Nand Flash REn
++ * MPP[7] Nand Flash WEn
++ * MPP[8-11] Not used
++ * MPP[12] SATA 0 presence Indication
++ * MPP[13] SATA 1 presence Indication
++ * MPP[14] SATA 0 active Indication
++ * MPP[15] SATA 1 active indication
++ * MPP[16-19] Not used
++ */
++ orion5x_write(MPP_0_7_CTRL, 0x44220003);
++ orion5x_write(MPP_8_15_CTRL, 0x55550000);
++ orion5x_write(MPP_16_19_CTRL, 0x0);
++
++ orion5x_gpio_set_valid_pins(0x0000000c);
++
++ platform_device_register(&kurobox_pro_nor_flash);
++ if (machine_is_kurobox_pro())
++ platform_device_register(&kurobox_pro_nand_flash);
++ i2c_register_board_info(0, &kurobox_pro_i2c_rtc, 1);
++ orion5x_eth_init(&kurobox_pro_eth_data);
++ orion5x_sata_init(&kurobox_pro_sata_data);
++}
++
++#ifdef CONFIG_MACH_KUROBOX_PRO
++MACHINE_START(KUROBOX_PRO, "Buffalo/Revogear Kurobox Pro")
++ /* Maintainer: Ronen Shitrit <rshitrit at marvell.com> */
++ .phys_io = ORION5X_REGS_PHYS_BASE,
++ .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
++ .boot_params = 0x00000100,
++ .init_machine = kurobox_pro_init,
++ .map_io = orion5x_map_io,
++ .init_irq = orion5x_init_irq,
++ .timer = &orion5x_timer,
++ .fixup = tag_fixup_mem32,
++MACHINE_END
++#endif
++
++#ifdef CONFIG_MACH_LINKSTATION_PRO
++MACHINE_START(LINKSTATION_PRO, "Buffalo Linkstation Pro/Live")
++ /* Maintainer: Byron Bradley <byron.bbradley at gmail.com> */
++ .phys_io = ORION5X_REGS_PHYS_BASE,
++ .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
++ .boot_params = 0x00000100,
++ .init_machine = kurobox_pro_init,
++ .map_io = orion5x_map_io,
++ .init_irq = orion5x_init_irq,
++ .timer = &orion5x_timer,
++ .fixup = tag_fixup_mem32,
++MACHINE_END
++#endif
+diff --git a/arch/arm/mach-orion5x/pci.c b/arch/arm/mach-orion5x/pci.c
+new file mode 100644
+index 0000000..fdf99fc
+--- /dev/null
++++ b/arch/arm/mach-orion5x/pci.c
+@@ -0,0 +1,559 @@
++/*
++ * arch/arm/mach-orion5x/pci.c
++ *
++ * PCI and PCIe functions for Marvell Orion System On Chip
++ *
++ * Maintainer: Tzachi Perelstein <tzachi at marvell.com>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/mbus.h>
++#include <asm/mach/pci.h>
++#include <asm/plat-orion/pcie.h>
++#include "common.h"
++
++/*****************************************************************************
++ * Orion has one PCIe controller and one PCI controller.
++ *
++ * Note1: The local PCIe bus number is '0'. The local PCI bus number
++ * follows the scanned PCIe bridged busses, if any.
++ *
++ * Note2: It is possible for PCI/PCIe agents to access many subsystem's
++ * space, by configuring BARs and Address Decode Windows, e.g. flashes on
++ * device bus, Orion registers, etc. However this code only enable the
++ * access to DDR banks.
++ ****************************************************************************/
++
++
++/*****************************************************************************
++ * PCIe controller
++ ****************************************************************************/
++#define PCIE_BASE ((void __iomem *)ORION5X_PCIE_VIRT_BASE)
++
++void __init orion5x_pcie_id(u32 *dev, u32 *rev)
++{
++ *dev = orion_pcie_dev_id(PCIE_BASE);
++ *rev = orion_pcie_rev(PCIE_BASE);
++}
++
++int __init orion5x_pcie_local_bus_nr(void)
++{
++ return orion_pcie_get_local_bus_nr(PCIE_BASE);
++}
++
++static int pcie_valid_config(int bus, int dev)
++{
++ /*
++ * Don't go out when trying to access --
++ * 1. nonexisting device on local bus
++ * 2. where there's no device connected (no link)
++ */
++ if (bus == 0 && dev == 0)
++ return 1;
++
++ if (!orion_pcie_link_up(PCIE_BASE))
++ return 0;
++
++ if (bus == 0 && dev != 1)
++ return 0;
++
++ return 1;
++}
++
++
++/*
++ * PCIe config cycles are done by programming the PCIE_CONF_ADDR register
++ * and then reading the PCIE_CONF_DATA register. Need to make sure these
++ * transactions are atomic.
++ */
++static DEFINE_SPINLOCK(orion5x_pcie_lock);
++
++static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
++ int size, u32 *val)
++{
++ unsigned long flags;
++ int ret;
++
++ if (pcie_valid_config(bus->number, PCI_SLOT(devfn)) == 0) {
++ *val = 0xffffffff;
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ }
++
++ spin_lock_irqsave(&orion5x_pcie_lock, flags);
++ ret = orion_pcie_rd_conf(PCIE_BASE, bus, devfn, where, size, val);
++ spin_unlock_irqrestore(&orion5x_pcie_lock, flags);
++
++ return ret;
++}
++
++static int pcie_rd_conf_wa(struct pci_bus *bus, u32 devfn,
++ int where, int size, u32 *val)
++{
++ int ret;
++
++ if (pcie_valid_config(bus->number, PCI_SLOT(devfn)) == 0) {
++ *val = 0xffffffff;
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ }
++
++ /*
++ * We only support access to the non-extended configuration
++ * space when using the WA access method (or we would have to
++ * sacrifice 256M of CPU virtual address space.)
++ */
++ if (where >= 0x100) {
++ *val = 0xffffffff;
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ }
++
++ ret = orion_pcie_rd_conf_wa((void __iomem *)ORION5X_PCIE_WA_VIRT_BASE,
++ bus, devfn, where, size, val);
++
++ return ret;
++}
++
++static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
++ int where, int size, u32 val)
++{
++ unsigned long flags;
++ int ret;
++
++ if (pcie_valid_config(bus->number, PCI_SLOT(devfn)) == 0)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ spin_lock_irqsave(&orion5x_pcie_lock, flags);
++ ret = orion_pcie_wr_conf(PCIE_BASE, bus, devfn, where, size, val);
++ spin_unlock_irqrestore(&orion5x_pcie_lock, flags);
++
++ return ret;
++}
++
++static struct pci_ops pcie_ops = {
++ .read = pcie_rd_conf,
++ .write = pcie_wr_conf,
++};
++
++
++static int __init pcie_setup(struct pci_sys_data *sys)
++{
++ struct resource *res;
++ int dev;
++
++ /*
++ * Generic PCIe unit setup.
++ */
++ orion_pcie_setup(PCIE_BASE, &orion5x_mbus_dram_info);
++
++ /*
++ * Check whether to apply Orion-1/Orion-NAS PCIe config
++ * read transaction workaround.
++ */
++ dev = orion_pcie_dev_id(PCIE_BASE);
++ if (dev == MV88F5181_DEV_ID || dev == MV88F5182_DEV_ID) {
++ printk(KERN_NOTICE "Applying Orion-1/Orion-NAS PCIe config "
++ "read transaction workaround\n");
++ pcie_ops.read = pcie_rd_conf_wa;
++ }
++
++ /*
++ * Request resources.
++ */
++ res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
++ if (!res)
++ panic("pcie_setup unable to alloc resources");
++
++ /*
++ * IORESOURCE_IO
++ */
++ res[0].name = "PCIe I/O Space";
++ res[0].flags = IORESOURCE_IO;
++ res[0].start = ORION5X_PCIE_IO_BUS_BASE;
++ res[0].end = res[0].start + ORION5X_PCIE_IO_SIZE - 1;
++ if (request_resource(&ioport_resource, &res[0]))
++ panic("Request PCIe IO resource failed\n");
++ sys->resource[0] = &res[0];
++
++ /*
++ * IORESOURCE_MEM
++ */
++ res[1].name = "PCIe Memory Space";
++ res[1].flags = IORESOURCE_MEM;
++ res[1].start = ORION5X_PCIE_MEM_PHYS_BASE;
++ res[1].end = res[1].start + ORION5X_PCIE_MEM_SIZE - 1;
++ if (request_resource(&iomem_resource, &res[1]))
++ panic("Request PCIe Memory resource failed\n");
++ sys->resource[1] = &res[1];
++
++ sys->resource[2] = NULL;
++ sys->io_offset = 0;
++
++ return 1;
++}
++
++/*****************************************************************************
++ * PCI controller
++ ****************************************************************************/
++#define PCI_MODE ORION5X_PCI_REG(0xd00)
++#define PCI_CMD ORION5X_PCI_REG(0xc00)
++#define PCI_P2P_CONF ORION5X_PCI_REG(0x1d14)
++#define PCI_CONF_ADDR ORION5X_PCI_REG(0xc78)
++#define PCI_CONF_DATA ORION5X_PCI_REG(0xc7c)
++
++/*
++ * PCI_MODE bits
++ */
++#define PCI_MODE_64BIT (1 << 2)
++#define PCI_MODE_PCIX ((1 << 4) | (1 << 5))
++
++/*
++ * PCI_CMD bits
++ */
++#define PCI_CMD_HOST_REORDER (1 << 29)
++
++/*
++ * PCI_P2P_CONF bits
++ */
++#define PCI_P2P_BUS_OFFS 16
++#define PCI_P2P_BUS_MASK (0xff << PCI_P2P_BUS_OFFS)
++#define PCI_P2P_DEV_OFFS 24
++#define PCI_P2P_DEV_MASK (0x1f << PCI_P2P_DEV_OFFS)
++
++/*
++ * PCI_CONF_ADDR bits
++ */
++#define PCI_CONF_REG(reg) ((reg) & 0xfc)
++#define PCI_CONF_FUNC(func) (((func) & 0x3) << 8)
++#define PCI_CONF_DEV(dev) (((dev) & 0x1f) << 11)
++#define PCI_CONF_BUS(bus) (((bus) & 0xff) << 16)
++#define PCI_CONF_ADDR_EN (1 << 31)
++
++/*
++ * Internal configuration space
++ */
++#define PCI_CONF_FUNC_STAT_CMD 0
++#define PCI_CONF_REG_STAT_CMD 4
++#define PCIX_STAT 0x64
++#define PCIX_STAT_BUS_OFFS 8
++#define PCIX_STAT_BUS_MASK (0xff << PCIX_STAT_BUS_OFFS)
++
++/*
++ * PCI Address Decode Windows registers
++ */
++#define PCI_BAR_SIZE_DDR_CS(n) (((n) == 0) ? ORION5X_PCI_REG(0xc08) : \
++ ((n) == 1) ? ORION5X_PCI_REG(0xd08) : \
++ ((n) == 2) ? ORION5X_PCI_REG(0xc0c) : \
++ ((n) == 3) ? ORION5X_PCI_REG(0xd0c) : 0)
++#define PCI_BAR_REMAP_DDR_CS(n) (((n) ==0) ? ORION5X_PCI_REG(0xc48) : \
++ ((n) == 1) ? ORION5X_PCI_REG(0xd48) : \
++ ((n) == 2) ? ORION5X_PCI_REG(0xc4c) : \
++ ((n) == 3) ? ORION5X_PCI_REG(0xd4c) : 0)
++#define PCI_BAR_ENABLE ORION5X_PCI_REG(0xc3c)
++#define PCI_ADDR_DECODE_CTRL ORION5X_PCI_REG(0xd3c)
++
++/*
++ * PCI configuration helpers for BAR settings
++ */
++#define PCI_CONF_FUNC_BAR_CS(n) ((n) >> 1)
++#define PCI_CONF_REG_BAR_LO_CS(n) (((n) & 1) ? 0x18 : 0x10)
++#define PCI_CONF_REG_BAR_HI_CS(n) (((n) & 1) ? 0x1c : 0x14)
++
++/*
++ * PCI config cycles are done by programming the PCI_CONF_ADDR register
++ * and then reading the PCI_CONF_DATA register. Need to make sure these
++ * transactions are atomic.
++ */
++static DEFINE_SPINLOCK(orion5x_pci_lock);
++
++int orion5x_pci_local_bus_nr(void)
++{
++ u32 conf = orion5x_read(PCI_P2P_CONF);
++ return((conf & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS);
++}
++
++static int orion5x_pci_hw_rd_conf(int bus, int dev, u32 func,
++ u32 where, u32 size, u32 *val)
++{
++ unsigned long flags;
++ spin_lock_irqsave(&orion5x_pci_lock, flags);
++
++ orion5x_write(PCI_CONF_ADDR, PCI_CONF_BUS(bus) |
++ PCI_CONF_DEV(dev) | PCI_CONF_REG(where) |
++ PCI_CONF_FUNC(func) | PCI_CONF_ADDR_EN);
++
++ *val = orion5x_read(PCI_CONF_DATA);
++
++ if (size == 1)
++ *val = (*val >> (8*(where & 0x3))) & 0xff;
++ else if (size == 2)
++ *val = (*val >> (8*(where & 0x3))) & 0xffff;
++
++ spin_unlock_irqrestore(&orion5x_pci_lock, flags);
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static int orion5x_pci_hw_wr_conf(int bus, int dev, u32 func,
++ u32 where, u32 size, u32 val)
++{
++ unsigned long flags;
++ int ret = PCIBIOS_SUCCESSFUL;
++
++ spin_lock_irqsave(&orion5x_pci_lock, flags);
++
++ orion5x_write(PCI_CONF_ADDR, PCI_CONF_BUS(bus) |
++ PCI_CONF_DEV(dev) | PCI_CONF_REG(where) |
++ PCI_CONF_FUNC(func) | PCI_CONF_ADDR_EN);
++
++ if (size == 4) {
++ __raw_writel(val, PCI_CONF_DATA);
++ } else if (size == 2) {
++ __raw_writew(val, PCI_CONF_DATA + (where & 0x3));
++ } else if (size == 1) {
++ __raw_writeb(val, PCI_CONF_DATA + (where & 0x3));
++ } else {
++ ret = PCIBIOS_BAD_REGISTER_NUMBER;
++ }
++
++ spin_unlock_irqrestore(&orion5x_pci_lock, flags);
++
++ return ret;
++}
++
++static int orion5x_pci_rd_conf(struct pci_bus *bus, u32 devfn,
++ int where, int size, u32 *val)
++{
++ /*
++ * Don't go out for local device
++ */
++ if (bus->number == orion5x_pci_local_bus_nr() &&
++ PCI_SLOT(devfn) == 0 && PCI_FUNC(devfn) != 0) {
++ *val = 0xffffffff;
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ }
++
++ return orion5x_pci_hw_rd_conf(bus->number, PCI_SLOT(devfn),
++ PCI_FUNC(devfn), where, size, val);
++}
++
++static int orion5x_pci_wr_conf(struct pci_bus *bus, u32 devfn,
++ int where, int size, u32 val)
++{
++ if (bus->number == orion5x_pci_local_bus_nr() &&
++ PCI_SLOT(devfn) == 0 && PCI_FUNC(devfn) != 0)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ return orion5x_pci_hw_wr_conf(bus->number, PCI_SLOT(devfn),
++ PCI_FUNC(devfn), where, size, val);
++}
++
++static struct pci_ops pci_ops = {
++ .read = orion5x_pci_rd_conf,
++ .write = orion5x_pci_wr_conf,
++};
++
++static void __init orion5x_pci_set_bus_nr(int nr)
++{
++ u32 p2p = orion5x_read(PCI_P2P_CONF);
++
++ if (orion5x_read(PCI_MODE) & PCI_MODE_PCIX) {
++ /*
++ * PCI-X mode
++ */
++ u32 pcix_status, bus, dev;
++ bus = (p2p & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS;
++ dev = (p2p & PCI_P2P_DEV_MASK) >> PCI_P2P_DEV_OFFS;
++ orion5x_pci_hw_rd_conf(bus, dev, 0, PCIX_STAT, 4, &pcix_status);
++ pcix_status &= ~PCIX_STAT_BUS_MASK;
++ pcix_status |= (nr << PCIX_STAT_BUS_OFFS);
++ orion5x_pci_hw_wr_conf(bus, dev, 0, PCIX_STAT, 4, pcix_status);
++ } else {
++ /*
++ * PCI Conventional mode
++ */
++ p2p &= ~PCI_P2P_BUS_MASK;
++ p2p |= (nr << PCI_P2P_BUS_OFFS);
++ orion5x_write(PCI_P2P_CONF, p2p);
++ }
++}
++
++static void __init orion5x_pci_master_slave_enable(void)
++{
++ int bus_nr, func, reg;
++ u32 val;
++
++ bus_nr = orion5x_pci_local_bus_nr();
++ func = PCI_CONF_FUNC_STAT_CMD;
++ reg = PCI_CONF_REG_STAT_CMD;
++ orion5x_pci_hw_rd_conf(bus_nr, 0, func, reg, 4, &val);
++ val |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
++ orion5x_pci_hw_wr_conf(bus_nr, 0, func, reg, 4, val | 0x7);
++}
++
++static void __init orion5x_setup_pci_wins(struct mbus_dram_target_info *dram)
++{
++ u32 win_enable;
++ int bus;
++ int i;
++
++ /*
++ * First, disable windows.
++ */
++ win_enable = 0xffffffff;
++ orion5x_write(PCI_BAR_ENABLE, win_enable);
++
++ /*
++ * Setup windows for DDR banks.
++ */
++ bus = orion5x_pci_local_bus_nr();
++
++ for (i = 0; i < dram->num_cs; i++) {
++ struct mbus_dram_window *cs = dram->cs + i;
++ u32 func = PCI_CONF_FUNC_BAR_CS(cs->cs_index);
++ u32 reg;
++ u32 val;
++
++ /*
++ * Write DRAM bank base address register.
++ */
++ reg = PCI_CONF_REG_BAR_LO_CS(cs->cs_index);
++ orion5x_pci_hw_rd_conf(bus, 0, func, reg, 4, &val);
++ val = (cs->base & 0xfffff000) | (val & 0xfff);
++ orion5x_pci_hw_wr_conf(bus, 0, func, reg, 4, val);
++
++ /*
++ * Write DRAM bank size register.
++ */
++ reg = PCI_CONF_REG_BAR_HI_CS(cs->cs_index);
++ orion5x_pci_hw_wr_conf(bus, 0, func, reg, 4, 0);
++ orion5x_write(PCI_BAR_SIZE_DDR_CS(cs->cs_index),
++ (cs->size - 1) & 0xfffff000);
++ orion5x_write(PCI_BAR_REMAP_DDR_CS(cs->cs_index),
++ cs->base & 0xfffff000);
++
++ /*
++ * Enable decode window for this chip select.
++ */
++ win_enable &= ~(1 << cs->cs_index);
++ }
++
++ /*
++ * Re-enable decode windows.
++ */
++ orion5x_write(PCI_BAR_ENABLE, win_enable);
++
++ /*
++ * Disable automatic update of address remaping when writing to BARs.
++ */
++ orion5x_setbits(PCI_ADDR_DECODE_CTRL, 1);
++}
++
++static int __init pci_setup(struct pci_sys_data *sys)
++{
++ struct resource *res;
++
++ /*
++ * Point PCI unit MBUS decode windows to DRAM space.
++ */
++ orion5x_setup_pci_wins(&orion5x_mbus_dram_info);
++
++ /*
++ * Master + Slave enable
++ */
++ orion5x_pci_master_slave_enable();
++
++ /*
++ * Force ordering
++ */
++ orion5x_setbits(PCI_CMD, PCI_CMD_HOST_REORDER);
++
++ /*
++ * Request resources
++ */
++ res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
++ if (!res)
++ panic("pci_setup unable to alloc resources");
++
++ /*
++ * IORESOURCE_IO
++ */
++ res[0].name = "PCI I/O Space";
++ res[0].flags = IORESOURCE_IO;
++ res[0].start = ORION5X_PCI_IO_BUS_BASE;
++ res[0].end = res[0].start + ORION5X_PCI_IO_SIZE - 1;
++ if (request_resource(&ioport_resource, &res[0]))
++ panic("Request PCI IO resource failed\n");
++ sys->resource[0] = &res[0];
++
++ /*
++ * IORESOURCE_MEM
++ */
++ res[1].name = "PCI Memory Space";
++ res[1].flags = IORESOURCE_MEM;
++ res[1].start = ORION5X_PCI_MEM_PHYS_BASE;
++ res[1].end = res[1].start + ORION5X_PCI_MEM_SIZE - 1;
++ if (request_resource(&iomem_resource, &res[1]))
++ panic("Request PCI Memory resource failed\n");
++ sys->resource[1] = &res[1];
++
++ sys->resource[2] = NULL;
++ sys->io_offset = 0;
++
++ return 1;
++}
++
++
++/*****************************************************************************
++ * General PCIe + PCI
++ ****************************************************************************/
++static void __devinit rc_pci_fixup(struct pci_dev *dev)
++{
++ /*
++ * Prevent enumeration of root complex.
++ */
++ if (dev->bus->parent == NULL && dev->devfn == 0) {
++ int i;
++
++ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
++ dev->resource[i].start = 0;
++ dev->resource[i].end = 0;
++ dev->resource[i].flags = 0;
++ }
++ }
++}
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
++
++int __init orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys)
++{
++ int ret = 0;
++
++ if (nr == 0) {
++ orion_pcie_set_local_bus_nr(PCIE_BASE, sys->busnr);
++ ret = pcie_setup(sys);
++ } else if (nr == 1) {
++ orion5x_pci_set_bus_nr(sys->busnr);
++ ret = pci_setup(sys);
++ }
++
++ return ret;
++}
++
++struct pci_bus __init *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys)
++{
++ struct pci_bus *bus;
++
++ if (nr == 0) {
++ bus = pci_scan_bus(sys->busnr, &pcie_ops, sys);
++ } else if (nr == 1) {
++ bus = pci_scan_bus(sys->busnr, &pci_ops, sys);
++ } else {
++ bus = NULL;
++ BUG();
++ }
++
++ return bus;
++}
+diff --git a/arch/arm/mach-orion5x/rd88f5182-setup.c b/arch/arm/mach-orion5x/rd88f5182-setup.c
+new file mode 100644
+index 0000000..37e8b2d
+--- /dev/null
++++ b/arch/arm/mach-orion5x/rd88f5182-setup.c
+@@ -0,0 +1,312 @@
++/*
++ * arch/arm/mach-orion5x/rd88f5182-setup.c
++ *
++ * Marvell Orion-NAS Reference Design Setup
++ *
++ * Maintainer: Ronen Shitrit <rshitrit at marvell.com>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/pci.h>
++#include <linux/irq.h>
++#include <linux/mtd/physmap.h>
++#include <linux/mv643xx_eth.h>
++#include <linux/ata_platform.h>
++#include <linux/i2c.h>
++#include <asm/mach-types.h>
++#include <asm/gpio.h>
++#include <asm/leds.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/pci.h>
++#include <asm/arch/orion5x.h>
++#include "common.h"
++
++/*****************************************************************************
++ * RD-88F5182 Info
++ ****************************************************************************/
++
++/*
++ * 512K NOR flash Device bus boot chip select
++ */
++
++#define RD88F5182_NOR_BOOT_BASE 0xf4000000
++#define RD88F5182_NOR_BOOT_SIZE SZ_512K
++
++/*
++ * 16M NOR flash on Device bus chip select 1
++ */
++
++#define RD88F5182_NOR_BASE 0xfc000000
++#define RD88F5182_NOR_SIZE SZ_16M
++
++/*
++ * PCI
++ */
++
++#define RD88F5182_PCI_SLOT0_OFFS 7
++#define RD88F5182_PCI_SLOT0_IRQ_A_PIN 7
++#define RD88F5182_PCI_SLOT0_IRQ_B_PIN 6
++
++/*
++ * GPIO Debug LED
++ */
++
++#define RD88F5182_GPIO_DBG_LED 0
++
++/*****************************************************************************
++ * 16M NOR Flash on Device bus CS1
++ ****************************************************************************/
++
++static struct physmap_flash_data rd88f5182_nor_flash_data = {
++ .width = 1,
++};
++
++static struct resource rd88f5182_nor_flash_resource = {
++ .flags = IORESOURCE_MEM,
++ .start = RD88F5182_NOR_BASE,
++ .end = RD88F5182_NOR_BASE + RD88F5182_NOR_SIZE - 1,
++};
++
++static struct platform_device rd88f5182_nor_flash = {
++ .name = "physmap-flash",
++ .id = 0,
++ .dev = {
++ .platform_data = &rd88f5182_nor_flash_data,
++ },
++ .num_resources = 1,
++ .resource = &rd88f5182_nor_flash_resource,
++};
++
++#ifdef CONFIG_LEDS
++
++/*****************************************************************************
++ * Use GPIO debug led as CPU active indication
++ ****************************************************************************/
++
++static void rd88f5182_dbgled_event(led_event_t evt)
++{
++ int val;
++
++ if (evt == led_idle_end)
++ val = 1;
++ else if (evt == led_idle_start)
++ val = 0;
++ else
++ return;
++
++ gpio_set_value(RD88F5182_GPIO_DBG_LED, val);
++}
++
++static int __init rd88f5182_dbgled_init(void)
++{
++ int pin;
++
++ if (machine_is_rd88f5182()) {
++ pin = RD88F5182_GPIO_DBG_LED;
++
++ if (gpio_request(pin, "DBGLED") == 0) {
++ if (gpio_direction_output(pin, 0) != 0) {
++ printk(KERN_ERR "rd88f5182_dbgled_init failed "
++ "to set output pin %d\n", pin);
++ gpio_free(pin);
++ return 0;
++ }
++ } else {
++ printk(KERN_ERR "rd88f5182_dbgled_init failed "
++ "to request gpio %d\n", pin);
++ return 0;
++ }
++
++ leds_event = rd88f5182_dbgled_event;
++ }
++ return 0;
++}
++
++__initcall(rd88f5182_dbgled_init);
++
++#endif
++
++/*****************************************************************************
++ * PCI
++ ****************************************************************************/
++
++void __init rd88f5182_pci_preinit(void)
++{
++ int pin;
++
++ /*
++ * Configure PCI GPIO IRQ pins
++ */
++ pin = RD88F5182_PCI_SLOT0_IRQ_A_PIN;
++ if (gpio_request(pin, "PCI IntA") == 0) {
++ if (gpio_direction_input(pin) == 0) {
++ set_irq_type(gpio_to_irq(pin), IRQT_LOW);
++ } else {
++ printk(KERN_ERR "rd88f5182_pci_preinit faield to "
++ "set_irq_type pin %d\n", pin);
++ gpio_free(pin);
++ }
++ } else {
++ printk(KERN_ERR "rd88f5182_pci_preinit failed to request gpio %d\n", pin);
++ }
++
++ pin = RD88F5182_PCI_SLOT0_IRQ_B_PIN;
++ if (gpio_request(pin, "PCI IntB") == 0) {
++ if (gpio_direction_input(pin) == 0) {
++ set_irq_type(gpio_to_irq(pin), IRQT_LOW);
++ } else {
++ printk(KERN_ERR "rd88f5182_pci_preinit faield to "
++ "set_irq_type pin %d\n", pin);
++ gpio_free(pin);
++ }
++ } else {
++ printk(KERN_ERR "rd88f5182_pci_preinit failed to gpio_request %d\n", pin);
++ }
++}
++
++static int __init rd88f5182_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++ /*
++ * PCI-E isn't used on the RD2
++ */
++ if (dev->bus->number == orion5x_pcie_local_bus_nr())
++ return IRQ_ORION5X_PCIE0_INT;
++
++ /*
++ * PCI IRQs are connected via GPIOs
++ */
++ switch (slot - RD88F5182_PCI_SLOT0_OFFS) {
++ case 0:
++ if (pin == 1)
++ return gpio_to_irq(RD88F5182_PCI_SLOT0_IRQ_A_PIN);
++ else
++ return gpio_to_irq(RD88F5182_PCI_SLOT0_IRQ_B_PIN);
++ default:
++ return -1;
++ }
++}
++
++static struct hw_pci rd88f5182_pci __initdata = {
++ .nr_controllers = 2,
++ .preinit = rd88f5182_pci_preinit,
++ .swizzle = pci_std_swizzle,
++ .setup = orion5x_pci_sys_setup,
++ .scan = orion5x_pci_sys_scan_bus,
++ .map_irq = rd88f5182_pci_map_irq,
++};
++
++static int __init rd88f5182_pci_init(void)
++{
++ if (machine_is_rd88f5182())
++ pci_common_init(&rd88f5182_pci);
++
++ return 0;
++}
++
++subsys_initcall(rd88f5182_pci_init);
++
++/*****************************************************************************
++ * Ethernet
++ ****************************************************************************/
++
++static struct mv643xx_eth_platform_data rd88f5182_eth_data = {
++ .phy_addr = 8,
++ .force_phy_addr = 1,
++};
++
++/*****************************************************************************
++ * RTC DS1338 on I2C bus
++ ****************************************************************************/
++static struct i2c_board_info __initdata rd88f5182_i2c_rtc = {
++ .driver_name = "rtc-ds1307",
++ .type = "ds1338",
++ .addr = 0x68,
++};
++
++/*****************************************************************************
++ * Sata
++ ****************************************************************************/
++static struct mv_sata_platform_data rd88f5182_sata_data = {
++ .n_ports = 2,
++};
++
++/*****************************************************************************
++ * General Setup
++ ****************************************************************************/
++
++static struct platform_device *rd88f5182_devices[] __initdata = {
++ &rd88f5182_nor_flash,
++};
++
++static void __init rd88f5182_init(void)
++{
++ /*
++ * Setup basic Orion functions. Need to be called early.
++ */
++ orion5x_init();
++
++ /*
++ * Setup the CPU address decode windows for our devices
++ */
++ orion5x_setup_dev_boot_win(RD88F5182_NOR_BOOT_BASE,
++ RD88F5182_NOR_BOOT_SIZE);
++ orion5x_setup_dev1_win(RD88F5182_NOR_BASE, RD88F5182_NOR_SIZE);
++
++ /*
++ * Open a special address decode windows for the PCIE WA.
++ */
++ orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
++ ORION5X_PCIE_WA_SIZE);
++
++ /*
++ * Setup Multiplexing Pins --
++ * MPP[0] Debug Led (GPIO - Out)
++ * MPP[1] Debug Led (GPIO - Out)
++ * MPP[2] N/A
++ * MPP[3] RTC_Int (GPIO - In)
++ * MPP[4] GPIO
++ * MPP[5] GPIO
++ * MPP[6] PCI_intA (GPIO - In)
++ * MPP[7] PCI_intB (GPIO - In)
++ * MPP[8-11] N/A
++ * MPP[12] SATA 0 presence Indication
++ * MPP[13] SATA 1 presence Indication
++ * MPP[14] SATA 0 active Indication
++ * MPP[15] SATA 1 active indication
++ * MPP[16-19] Not used
++ * MPP[20] PCI Clock to MV88F5182
++ * MPP[21] PCI Clock to mini PCI CON11
++ * MPP[22] USB 0 over current indication
++ * MPP[23] USB 1 over current indication
++ * MPP[24] USB 1 over current enable
++ * MPP[25] USB 0 over current enable
++ */
++
++ orion5x_write(MPP_0_7_CTRL, 0x00000003);
++ orion5x_write(MPP_8_15_CTRL, 0x55550000);
++ orion5x_write(MPP_16_19_CTRL, 0x5555);
++
++ orion5x_gpio_set_valid_pins(0x000000fb);
++
++ platform_add_devices(rd88f5182_devices, ARRAY_SIZE(rd88f5182_devices));
++ i2c_register_board_info(0, &rd88f5182_i2c_rtc, 1);
++ orion5x_eth_init(&rd88f5182_eth_data);
++ orion5x_sata_init(&rd88f5182_sata_data);
++}
++
++MACHINE_START(RD88F5182, "Marvell Orion-NAS Reference Design")
++ /* Maintainer: Ronen Shitrit <rshitrit at marvell.com> */
++ .phys_io = ORION5X_REGS_PHYS_BASE,
++ .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
++ .boot_params = 0x00000100,
++ .init_machine = rd88f5182_init,
++ .map_io = orion5x_map_io,
++ .init_irq = orion5x_init_irq,
++ .timer = &orion5x_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-orion5x/ts209-setup.c b/arch/arm/mach-orion5x/ts209-setup.c
+new file mode 100644
+index 0000000..fd43863
+--- /dev/null
++++ b/arch/arm/mach-orion5x/ts209-setup.c
+@@ -0,0 +1,442 @@
++/*
++ * QNAP TS-109/TS-209 Board Setup
++ *
++ * Maintainer: Byron Bradley <byron.bbradley at gmail.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/pci.h>
++#include <linux/irq.h>
++#include <linux/mtd/physmap.h>
++#include <linux/mtd/nand.h>
++#include <linux/mv643xx_eth.h>
++#include <linux/gpio_keys.h>
++#include <linux/input.h>
++#include <linux/i2c.h>
++#include <linux/serial_reg.h>
++#include <linux/ata_platform.h>
++#include <asm/mach-types.h>
++#include <asm/gpio.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/pci.h>
++#include <asm/arch/orion5x.h>
++#include "common.h"
++
++#define QNAP_TS209_NOR_BOOT_BASE 0xf4000000
++#define QNAP_TS209_NOR_BOOT_SIZE SZ_8M
++
++/****************************************************************************
++ * 8MiB NOR flash. The struct mtd_partition is not in the same order as the
++ * partitions on the device because we want to keep compatability with
++ * existing QNAP firmware.
++ *
++ * Layout as used by QNAP:
++ * [2] 0x00000000-0x00200000 : "Kernel"
++ * [3] 0x00200000-0x00600000 : "RootFS1"
++ * [4] 0x00600000-0x00700000 : "RootFS2"
++ * [6] 0x00700000-0x00760000 : "NAS Config" (read-only)
++ * [5] 0x00760000-0x00780000 : "U-Boot Config"
++ * [1] 0x00780000-0x00800000 : "U-Boot" (read-only)
++ ***************************************************************************/
++static struct mtd_partition qnap_ts209_partitions[] = {
++ {
++ .name = "U-Boot",
++ .size = 0x00080000,
++ .offset = 0x00780000,
++ .mask_flags = MTD_WRITEABLE,
++ }, {
++ .name = "Kernel",
++ .size = 0x00200000,
++ .offset = 0,
++ }, {
++ .name = "RootFS1",
++ .size = 0x00400000,
++ .offset = 0x00200000,
++ }, {
++ .name = "RootFS2",
++ .size = 0x00100000,
++ .offset = 0x00600000,
++ }, {
++ .name = "U-Boot Config",
++ .size = 0x00020000,
++ .offset = 0x00760000,
++ }, {
++ .name = "NAS Config",
++ .size = 0x00060000,
++ .offset = 0x00700000,
++ .mask_flags = MTD_WRITEABLE,
++ }
++};
++
++static struct physmap_flash_data qnap_ts209_nor_flash_data = {
++ .width = 1,
++ .parts = qnap_ts209_partitions,
++ .nr_parts = ARRAY_SIZE(qnap_ts209_partitions)
++};
++
++static struct resource qnap_ts209_nor_flash_resource = {
++ .flags = IORESOURCE_MEM,
++ .start = QNAP_TS209_NOR_BOOT_BASE,
++ .end = QNAP_TS209_NOR_BOOT_BASE + QNAP_TS209_NOR_BOOT_SIZE - 1,
++};
++
++static struct platform_device qnap_ts209_nor_flash = {
++ .name = "physmap-flash",
++ .id = 0,
++ .dev = { .platform_data = &qnap_ts209_nor_flash_data, },
++ .resource = &qnap_ts209_nor_flash_resource,
++ .num_resources = 1,
++};
++
++/*****************************************************************************
++ * PCI
++ ****************************************************************************/
++
++#define QNAP_TS209_PCI_SLOT0_OFFS 7
++#define QNAP_TS209_PCI_SLOT0_IRQ_PIN 6
++#define QNAP_TS209_PCI_SLOT1_IRQ_PIN 7
++
++void __init qnap_ts209_pci_preinit(void)
++{
++ int pin;
++
++ /*
++ * Configure PCI GPIO IRQ pins
++ */
++ pin = QNAP_TS209_PCI_SLOT0_IRQ_PIN;
++ if (gpio_request(pin, "PCI Int1") == 0) {
++ if (gpio_direction_input(pin) == 0) {
++ set_irq_type(gpio_to_irq(pin), IRQT_LOW);
++ } else {
++ printk(KERN_ERR "qnap_ts209_pci_preinit failed to "
++ "set_irq_type pin %d\n", pin);
++ gpio_free(pin);
++ }
++ } else {
++ printk(KERN_ERR "qnap_ts209_pci_preinit failed to gpio_request "
++ "%d\n", pin);
++ }
++
++ pin = QNAP_TS209_PCI_SLOT1_IRQ_PIN;
++ if (gpio_request(pin, "PCI Int2") == 0) {
++ if (gpio_direction_input(pin) == 0) {
++ set_irq_type(gpio_to_irq(pin), IRQT_LOW);
++ } else {
++ printk(KERN_ERR "qnap_ts209_pci_preinit failed "
++ "to set_irq_type pin %d\n", pin);
++ gpio_free(pin);
++ }
++ } else {
++ printk(KERN_ERR "qnap_ts209_pci_preinit failed to gpio_request "
++ "%d\n", pin);
++ }
++}
++
++static int __init qnap_ts209_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++ /*
++ * PCIE IRQ is connected internally (not GPIO)
++ */
++ if (dev->bus->number == orion5x_pcie_local_bus_nr())
++ return IRQ_ORION5X_PCIE0_INT;
++
++ /*
++ * PCI IRQs are connected via GPIOs
++ */
++ switch (slot - QNAP_TS209_PCI_SLOT0_OFFS) {
++ case 0:
++ return gpio_to_irq(QNAP_TS209_PCI_SLOT0_IRQ_PIN);
++ case 1:
++ return gpio_to_irq(QNAP_TS209_PCI_SLOT1_IRQ_PIN);
++ default:
++ return -1;
++ }
++}
++
++static struct hw_pci qnap_ts209_pci __initdata = {
++ .nr_controllers = 2,
++ .preinit = qnap_ts209_pci_preinit,
++ .swizzle = pci_std_swizzle,
++ .setup = orion5x_pci_sys_setup,
++ .scan = orion5x_pci_sys_scan_bus,
++ .map_irq = qnap_ts209_pci_map_irq,
++};
++
++static int __init qnap_ts209_pci_init(void)
++{
++ if (machine_is_ts_x09())
++ pci_common_init(&qnap_ts209_pci);
++
++ return 0;
++}
++
++subsys_initcall(qnap_ts209_pci_init);
++
++/*****************************************************************************
++ * Ethernet
++ ****************************************************************************/
++
++static struct mv643xx_eth_platform_data qnap_ts209_eth_data = {
++ .phy_addr = 8,
++ .force_phy_addr = 1,
++};
++
++static int __init parse_hex_nibble(char n)
++{
++ if (n >= '0' && n <= '9')
++ return n - '0';
++
++ if (n >= 'A' && n <= 'F')
++ return n - 'A' + 10;
++
++ if (n >= 'a' && n <= 'f')
++ return n - 'a' + 10;
++
++ return -1;
++}
++
++static int __init parse_hex_byte(const char *b)
++{
++ int hi;
++ int lo;
++
++ hi = parse_hex_nibble(b[0]);
++ lo = parse_hex_nibble(b[1]);
++
++ if (hi < 0 || lo < 0)
++ return -1;
++
++ return (hi << 4) | lo;
++}
++
++static int __init check_mac_addr(const char *addr_str)
++{
++ u_int8_t addr[6];
++ int i;
++
++ for (i = 0; i < 6; i++) {
++ int byte;
++
++ /*
++ * Enforce "xx:xx:xx:xx:xx:xx\n" format.
++ */
++ if (addr_str[(i * 3) + 2] != ((i < 5) ? ':' : '\n'))
++ return -1;
++
++ byte = parse_hex_byte(addr_str + (i * 3));
++ if (byte < 0)
++ return -1;
++ addr[i] = byte;
++ }
++
++ printk(KERN_INFO "ts209: found ethernet mac address ");
++ for (i = 0; i < 6; i++)
++ printk("%.2x%s", addr[i], (i < 5) ? ":" : ".\n");
++
++ memcpy(qnap_ts209_eth_data.mac_addr, addr, 6);
++
++ return 0;
++}
++
++/*
++ * The 'NAS Config' flash partition has an ext2 filesystem which
++ * contains a file that has the ethernet MAC address in plain text
++ * (format "xx:xx:xx:xx:xx:xx\n".)
++ */
++static void __init ts209_find_mac_addr(void)
++{
++ unsigned long addr;
++
++ for (addr = 0x00700000; addr < 0x00760000; addr += 1024) {
++ char *nor_page;
++ int ret = 0;
++
++ nor_page = ioremap(QNAP_TS209_NOR_BOOT_BASE + addr, 1024);
++ if (nor_page != NULL) {
++ ret = check_mac_addr(nor_page);
++ iounmap(nor_page);
++ }
++
++ if (ret == 0)
++ break;
++ }
++}
++
++/*****************************************************************************
++ * RTC S35390A on I2C bus
++ ****************************************************************************/
++
++#define TS209_RTC_GPIO 3
++
++static struct i2c_board_info __initdata qnap_ts209_i2c_rtc = {
++ .driver_name = "rtc-s35390a",
++ .addr = 0x30,
++ .irq = 0,
++};
++
++/****************************************************************************
++ * GPIO Attached Keys
++ * Power button is attached to the PIC microcontroller
++ ****************************************************************************/
++
++#define QNAP_TS209_GPIO_KEY_MEDIA 1
++#define QNAP_TS209_GPIO_KEY_RESET 2
++
++static struct gpio_keys_button qnap_ts209_buttons[] = {
++ {
++ .code = KEY_RESTART,
++ .gpio = QNAP_TS209_GPIO_KEY_MEDIA,
++ .desc = "USB Copy Button",
++ .active_low = 1,
++ },
++ {
++ .code = KEY_POWER,
++ .gpio = QNAP_TS209_GPIO_KEY_RESET,
++ .desc = "Reset Button",
++ .active_low = 1,
++ }
++};
++
++static struct gpio_keys_platform_data qnap_ts209_button_data = {
++ .buttons = qnap_ts209_buttons,
++ .nbuttons = ARRAY_SIZE(qnap_ts209_buttons),
++};
++
++static struct platform_device qnap_ts209_button_device = {
++ .name = "gpio-keys",
++ .id = -1,
++ .num_resources = 0,
++ .dev = { .platform_data = &qnap_ts209_button_data, },
++};
++
++/*****************************************************************************
++ * SATA
++ ****************************************************************************/
++static struct mv_sata_platform_data qnap_ts209_sata_data = {
++ .n_ports = 2,
++};
++
++/*****************************************************************************
++
++ * General Setup
++ ****************************************************************************/
++
++static struct platform_device *qnap_ts209_devices[] __initdata = {
++ &qnap_ts209_nor_flash,
++ &qnap_ts209_button_device,
++};
++
++/*
++ * QNAP TS-[12]09 specific power off method via UART1-attached PIC
++ */
++
++#define UART1_REG(x) (UART1_VIRT_BASE + ((UART_##x) << 2))
++
++static void qnap_ts209_power_off(void)
++{
++ /* 19200 baud divisor */
++ const unsigned divisor = ((ORION5X_TCLK + (8 * 19200)) / (16 * 19200));
++
++ pr_info("%s: triggering power-off...\n", __func__);
++
++ /* hijack uart1 and reset into sane state (19200,8n1) */
++ orion5x_write(UART1_REG(LCR), 0x83);
++ orion5x_write(UART1_REG(DLL), divisor & 0xff);
++ orion5x_write(UART1_REG(DLM), (divisor >> 8) & 0xff);
++ orion5x_write(UART1_REG(LCR), 0x03);
++ orion5x_write(UART1_REG(IER), 0x00);
++ orion5x_write(UART1_REG(FCR), 0x00);
++ orion5x_write(UART1_REG(MCR), 0x00);
++
++ /* send the power-off command 'A' to PIC */
++ orion5x_write(UART1_REG(TX), 'A');
++}
++
++static void __init qnap_ts209_init(void)
++{
++ /*
++ * Setup basic Orion functions. Need to be called early.
++ */
++ orion5x_init();
++
++ /*
++ * Setup flash mapping
++ */
++ orion5x_setup_dev_boot_win(QNAP_TS209_NOR_BOOT_BASE,
++ QNAP_TS209_NOR_BOOT_SIZE);
++
++ /*
++ * Open a special address decode windows for the PCIE WA.
++ */
++ orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
++ ORION5X_PCIE_WA_SIZE);
++
++ /*
++ * Setup Multiplexing Pins --
++ * MPP[0] Reserved
++ * MPP[1] USB copy button (0 active)
++ * MPP[2] Load defaults button (0 active)
++ * MPP[3] GPIO RTC
++ * MPP[4-5] Reserved
++ * MPP[6] PCI Int A
++ * MPP[7] PCI Int B
++ * MPP[8-11] Reserved
++ * MPP[12] SATA 0 presence
++ * MPP[13] SATA 1 presence
++ * MPP[14] SATA 0 active
++ * MPP[15] SATA 1 active
++ * MPP[16] UART1 RXD
++ * MPP[17] UART1 TXD
++ * MPP[18] SW_RST (0 active)
++ * MPP[19] Reserved
++ * MPP[20] PCI clock 0
++ * MPP[21] PCI clock 1
++ * MPP[22] USB 0 over current
++ * MPP[23-25] Reserved
++ */
++ orion5x_write(MPP_0_7_CTRL, 0x3);
++ orion5x_write(MPP_8_15_CTRL, 0x55550000);
++ orion5x_write(MPP_16_19_CTRL, 0x5500);
++ orion5x_gpio_set_valid_pins(0x3cc0fff);
++
++ /* register ts209 specific power-off method */
++ pm_power_off = qnap_ts209_power_off;
++
++ platform_add_devices(qnap_ts209_devices,
++ ARRAY_SIZE(qnap_ts209_devices));
++
++ /* Get RTC IRQ and register the chip */
++ if (gpio_request(TS209_RTC_GPIO, "rtc") == 0) {
++ if (gpio_direction_input(TS209_RTC_GPIO) == 0)
++ qnap_ts209_i2c_rtc.irq = gpio_to_irq(TS209_RTC_GPIO);
++ else
++ gpio_free(TS209_RTC_GPIO);
++ }
++ if (qnap_ts209_i2c_rtc.irq == 0)
++ pr_warning("qnap_ts209_init: failed to get RTC IRQ\n");
++ i2c_register_board_info(0, &qnap_ts209_i2c_rtc, 1);
++
++ ts209_find_mac_addr();
++ orion5x_eth_init(&qnap_ts209_eth_data);
++
++ orion5x_sata_init(&qnap_ts209_sata_data);
++}
++
++MACHINE_START(TS209, "QNAP TS-109/TS-209")
++ /* Maintainer: Byron Bradley <byron.bbradley at gmail.com> */
++ .phys_io = ORION5X_REGS_PHYS_BASE,
++ .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
++ .boot_params = 0x00000100,
++ .init_machine = qnap_ts209_init,
++ .map_io = orion5x_map_io,
++ .init_irq = orion5x_init_irq,
++ .timer = &orion5x_timer,
++ .fixup = tag_fixup_mem32,
++MACHINE_END
+diff --git a/arch/arm/mach-pnx4008/clock.c b/arch/arm/mach-pnx4008/clock.c
+index 8e00ed4..a5268c3 100644
+--- a/arch/arm/mach-pnx4008/clock.c
++++ b/arch/arm/mach-pnx4008/clock.c
+@@ -21,7 +21,6 @@
+ #include <linux/err.h>
+ #include <linux/delay.h>
+
+-#include <asm/semaphore.h>
+ #include <asm/hardware.h>
+ #include <asm/io.h>
+
+diff --git a/arch/arm/mach-pnx4008/gpio.c b/arch/arm/mach-pnx4008/gpio.c
+index 1ab84ce..ef179ca 100644
+--- a/arch/arm/mach-pnx4008/gpio.c
++++ b/arch/arm/mach-pnx4008/gpio.c
+@@ -17,7 +17,6 @@
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+-#include <asm/semaphore.h>
+ #include <asm/io.h>
+ #include <asm/arch/platform.h>
+ #include <asm/arch/gpio.h>
+diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
+index 0908bea..5da7a68 100644
+--- a/arch/arm/mach-pxa/Kconfig
++++ b/arch/arm/mach-pxa/Kconfig
+@@ -23,6 +23,12 @@ endif
+ choice
+ prompt "Select target board"
+
++config ARCH_GUMSTIX
++ bool "Gumstix XScale boards"
++ help
++ Say Y here if you intend to run this kernel on a
++ Gumstix Full Function Minature Computer.
++
+ config ARCH_LUBBOCK
+ bool "Intel DBPXA250 Development Platform"
+ select PXA25x
+@@ -160,6 +166,20 @@ endchoice
+
+ endif
+
++if ARCH_GUMSTIX
++
++choice
++ prompt "Select target Gumstix board"
++
++config MACH_GUMSTIX_F
++ bool "Basix, Connex, ws-200ax, ws-400ax systems"
++ select PXA25x
++
++endchoice
++
++endif
++
++
+ if MACH_TRIZEPS4
+
+ choice
+diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
+index 6e0c4f5..7cdcb45 100644
+--- a/arch/arm/mach-pxa/Makefile
++++ b/arch/arm/mach-pxa/Makefile
+@@ -5,13 +5,14 @@
+ # Common support (must be linked before board specific support)
+ obj-y += clock.o devices.o generic.o irq.o dma.o \
+ time.o gpio.o
+-obj-$(CONFIG_PXA25x) += pxa25x.o
+-obj-$(CONFIG_PXA27x) += pxa27x.o
+-obj-$(CONFIG_PXA3xx) += pxa3xx.o mfp.o smemc.o
++obj-$(CONFIG_PXA25x) += pxa25x.o mfp-pxa2xx.o
++obj-$(CONFIG_PXA27x) += pxa27x.o mfp-pxa2xx.o
++obj-$(CONFIG_PXA3xx) += pxa3xx.o mfp-pxa3xx.o smemc.o
+ obj-$(CONFIG_CPU_PXA300) += pxa300.o
+ obj-$(CONFIG_CPU_PXA320) += pxa320.o
+
+ # Specific board support
++obj-$(CONFIG_ARCH_GUMSTIX) += gumstix.o
+ obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
+ obj-$(CONFIG_MACH_LOGICPD_PXA270) += lpd270.o
+ obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
+diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c
+index df5ae27..e97dc59 100644
+--- a/arch/arm/mach-pxa/clock.c
++++ b/arch/arm/mach-pxa/clock.c
+@@ -13,6 +13,7 @@
+ #include <linux/delay.h>
+
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/hardware.h>
+
+ #include "devices.h"
+diff --git a/arch/arm/mach-pxa/cm-x270-pci.c b/arch/arm/mach-pxa/cm-x270-pci.c
+index fcda7d5..ac7f05f 100644
+--- a/arch/arm/mach-pxa/cm-x270-pci.c
++++ b/arch/arm/mach-pxa/cm-x270-pci.c
+@@ -23,6 +23,7 @@
+ #include <asm/mach/pci.h>
+ #include <asm/arch/cm-x270.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/mach-types.h>
+
+ #include <asm/hardware/it8152.h>
+diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c
+index ecdbc96..6d4416a 100644
+--- a/arch/arm/mach-pxa/cm-x270.c
++++ b/arch/arm/mach-pxa/cm-x270.c
+@@ -30,6 +30,7 @@
+
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/arch/pxa2xx-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/pxafb.h>
+ #include <asm/arch/ohci.h>
+ #include <asm/arch/mmc.h>
+diff --git a/arch/arm/mach-pxa/colibri.c b/arch/arm/mach-pxa/colibri.c
+index 6db54e3..43bf5a1 100644
+--- a/arch/arm/mach-pxa/colibri.c
++++ b/arch/arm/mach-pxa/colibri.c
+@@ -29,6 +29,7 @@
+ #include <asm/mach/irq.h>
+ #include <asm/mach/flash.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/colibri.h>
+
+ #include "generic.h"
+diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
+index 9292576..259ca82 100644
+--- a/arch/arm/mach-pxa/corgi.c
++++ b/arch/arm/mach-pxa/corgi.c
+@@ -36,6 +36,7 @@
+ #include <asm/mach/irq.h>
+
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/irda.h>
+ #include <asm/arch/mmc.h>
+ #include <asm/arch/udc.h>
+diff --git a/arch/arm/mach-pxa/corgi_pm.c b/arch/arm/mach-pxa/corgi_pm.c
+index 392c387..0a85f70 100644
+--- a/arch/arm/mach-pxa/corgi_pm.c
++++ b/arch/arm/mach-pxa/corgi_pm.c
+@@ -26,6 +26,7 @@
+ #include <asm/arch/sharpsl.h>
+ #include <asm/arch/corgi.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include "sharpsl.h"
+
+ #define SHARPSL_CHARGE_ON_VOLT 0x99 /* 2.9V */
+diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
+index 3170622..eccc45d 100644
+--- a/arch/arm/mach-pxa/corgi_ssp.c
++++ b/arch/arm/mach-pxa/corgi_ssp.c
+@@ -21,6 +21,7 @@
+
+ #include <asm/arch/ssp.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/regs-ssp.h>
+ #include "sharpsl.h"
+
+diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
+index bfccb80..d6c05b6 100644
+--- a/arch/arm/mach-pxa/devices.c
++++ b/arch/arm/mach-pxa/devices.c
+@@ -11,6 +11,8 @@
+ #include <asm/arch/irda.h>
+ #include <asm/arch/i2c.h>
+ #include <asm/arch/ohci.h>
++#include <asm/arch/pxa27x_keypad.h>
++#include <asm/arch/camera.h>
+
+ #include "devices.h"
+
+@@ -396,6 +398,31 @@ struct platform_device pxa25x_device_assp = {
+
+ #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+
++static struct resource pxa27x_resource_keypad[] = {
++ [0] = {
++ .start = 0x41500000,
++ .end = 0x4150004c,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_KEYPAD,
++ .end = IRQ_KEYPAD,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device pxa27x_device_keypad = {
++ .name = "pxa27x-keypad",
++ .id = -1,
++ .resource = pxa27x_resource_keypad,
++ .num_resources = ARRAY_SIZE(pxa27x_resource_keypad),
++};
++
++void __init pxa_set_keypad_info(struct pxa27x_keypad_platform_data *info)
++{
++ pxa_register_device(&pxa27x_device_keypad, info);
++}
++
+ static u64 pxa27x_ohci_dma_mask = DMA_BIT_MASK(32);
+
+ static struct resource pxa27x_resource_ohci[] = {
+@@ -540,6 +567,37 @@ struct platform_device pxa27x_device_ssp3 = {
+ .resource = pxa27x_resource_ssp3,
+ .num_resources = ARRAY_SIZE(pxa27x_resource_ssp3),
+ };
++
++static struct resource pxa27x_resource_camera[] = {
++ [0] = {
++ .start = 0x50000000,
++ .end = 0x50000fff,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_CAMERA,
++ .end = IRQ_CAMERA,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static u64 pxa27x_dma_mask_camera = DMA_BIT_MASK(32);
++
++static struct platform_device pxa27x_device_camera = {
++ .name = "pxa27x-camera",
++ .id = 0, /* This is used to put cameras on this interface */
++ .dev = {
++ .dma_mask = &pxa27x_dma_mask_camera,
++ .coherent_dma_mask = 0xffffffff,
++ },
++ .num_resources = ARRAY_SIZE(pxa27x_resource_camera),
++ .resource = pxa27x_resource_camera,
++};
++
++void __init pxa_set_camera_info(struct pxacamera_platform_data *info)
++{
++ pxa_register_device(&pxa27x_device_camera, info);
++}
+ #endif /* CONFIG_PXA27x || CONFIG_PXA3xx */
+
+ #ifdef CONFIG_PXA3xx
+diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h
+index 96c7c89..fcab017 100644
+--- a/arch/arm/mach-pxa/devices.h
++++ b/arch/arm/mach-pxa/devices.h
+@@ -14,6 +14,7 @@ extern struct platform_device pxa_device_rtc;
+
+ extern struct platform_device pxa27x_device_i2c_power;
+ extern struct platform_device pxa27x_device_ohci;
++extern struct platform_device pxa27x_device_keypad;
+
+ extern struct platform_device pxa25x_device_ssp;
+ extern struct platform_device pxa25x_device_nssp;
+diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
+index 3bb3131..edc4f07 100644
+--- a/arch/arm/mach-pxa/em-x270.c
++++ b/arch/arm/mach-pxa/em-x270.c
+@@ -23,6 +23,7 @@
+ #include <asm/mach/arch.h>
+
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/pxafb.h>
+ #include <asm/arch/ohci.h>
+ #include <asm/arch/mmc.h>
+diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
+index 80721c6..331f29b 100644
+--- a/arch/arm/mach-pxa/generic.c
++++ b/arch/arm/mach-pxa/generic.c
+@@ -19,14 +19,8 @@
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/delay.h>
+-#include <linux/ioport.h>
+-#include <linux/pm.h>
+-#include <linux/string.h>
+-#include <linux/sysdev.h>
+
+ #include <asm/hardware.h>
+-#include <asm/irq.h>
+ #include <asm/system.h>
+ #include <asm/pgtable.h>
+ #include <asm/mach/map.h>
+@@ -134,59 +128,3 @@ void __init pxa_map_io(void)
+ iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
+ get_clk_frequency_khz(1);
+ }
+-
+-#ifdef CONFIG_PM
+-
+-static unsigned long saved_gplr[4];
+-static unsigned long saved_gpdr[4];
+-static unsigned long saved_grer[4];
+-static unsigned long saved_gfer[4];
+-
+-static int pxa_gpio_suspend(struct sys_device *dev, pm_message_t state)
+-{
+- int i, gpio;
+-
+- for (gpio = 0, i = 0; gpio < pxa_last_gpio; gpio += 32, i++) {
+- saved_gplr[i] = GPLR(gpio);
+- saved_gpdr[i] = GPDR(gpio);
+- saved_grer[i] = GRER(gpio);
+- saved_gfer[i] = GFER(gpio);
+-
+- /* Clear GPIO transition detect bits */
+- GEDR(gpio) = GEDR(gpio);
+- }
+- return 0;
+-}
+-
+-static int pxa_gpio_resume(struct sys_device *dev)
+-{
+- int i, gpio;
+-
+- for (gpio = 0, i = 0; gpio < pxa_last_gpio; gpio += 32, i++) {
+- /* restore level with set/clear */
+- GPSR(gpio) = saved_gplr[i];
+- GPCR(gpio) = ~saved_gplr[i];
+-
+- GRER(gpio) = saved_grer[i];
+- GFER(gpio) = saved_gfer[i];
+- GPDR(gpio) = saved_gpdr[i];
+- }
+- return 0;
+-}
+-#else
+-#define pxa_gpio_suspend NULL
+-#define pxa_gpio_resume NULL
+-#endif
+-
+-struct sysdev_class pxa_gpio_sysclass = {
+- .name = "gpio",
+- .suspend = pxa_gpio_suspend,
+- .resume = pxa_gpio_resume,
+-};
+-
+-static int __init pxa_gpio_init(void)
+-{
+- return sysdev_class_register(&pxa_gpio_sysclass);
+-}
+-
+-core_initcall(pxa_gpio_init);
+diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
+index b3d10b0..5bb7ae7 100644
+--- a/arch/arm/mach-pxa/generic.h
++++ b/arch/arm/mach-pxa/generic.h
+@@ -9,14 +9,13 @@
+ * published by the Free Software Foundation.
+ */
+
++typedef int (*set_wake_t)(unsigned int, unsigned int);
++
+ struct sys_timer;
+
+ extern struct sys_timer pxa_timer;
+-extern void __init pxa_init_irq_low(void);
+-extern void __init pxa_init_irq_high(void);
+-extern void __init pxa_init_irq_gpio(int gpio_nr);
+-extern void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int));
+-extern void __init pxa_init_gpio(int gpio_nr);
++extern void __init pxa_init_irq(int irq_nr, set_wake_t fn);
++extern void __init pxa_init_gpio(int gpio_nr, set_wake_t fn);
+ extern void __init pxa25x_init_irq(void);
+ extern void __init pxa27x_init_irq(void);
+ extern void __init pxa3xx_init_irq(void);
+@@ -30,6 +29,8 @@ extern int pxa_last_gpio;
+ mi->bank[__nr].size = (__size), \
+ mi->bank[__nr].node = (((unsigned)(__start) - PHYS_OFFSET) >> 27)
+
++#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x)
++
+ #ifdef CONFIG_PXA25x
+ extern unsigned pxa25x_get_clk_frequency_khz(int);
+ extern unsigned pxa25x_get_memclk_frequency_10khz(void);
+@@ -56,3 +57,4 @@ extern unsigned pxa3xx_get_memclk_frequency_10khz(void);
+
+ extern struct sysdev_class pxa_irq_sysclass;
+ extern struct sysdev_class pxa_gpio_sysclass;
++extern struct sysdev_class pxa3xx_mfp_sysclass;
+diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c
+index 8638dd7..7d3e169 100644
+--- a/arch/arm/mach-pxa/gpio.c
++++ b/arch/arm/mach-pxa/gpio.c
+@@ -14,11 +14,14 @@
+
+ #include <linux/init.h>
+ #include <linux/module.h>
++#include <linux/irq.h>
++#include <linux/sysdev.h>
+
+ #include <asm/gpio.h>
+ #include <asm/hardware.h>
+ #include <asm/io.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+
+ #include "generic.h"
+
+@@ -129,69 +132,283 @@ static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+ __raw_writel(mask, pxa->regbase + GPCR_OFFSET);
+ }
+
++#define GPIO_CHIP(_n) \
++ [_n] = { \
++ .regbase = GPIO##_n##_BASE, \
++ .chip = { \
++ .label = "gpio-" #_n, \
++ .direction_input = pxa_gpio_direction_input, \
++ .direction_output = pxa_gpio_direction_output, \
++ .get = pxa_gpio_get, \
++ .set = pxa_gpio_set, \
++ .base = (_n) * 32, \
++ .ngpio = 32, \
++ }, \
++ }
++
+ static struct pxa_gpio_chip pxa_gpio_chip[] = {
+- [0] = {
+- .regbase = GPIO0_BASE,
+- .chip = {
+- .label = "gpio-0",
+- .direction_input = pxa_gpio_direction_input,
+- .direction_output = pxa_gpio_direction_output,
+- .get = pxa_gpio_get,
+- .set = pxa_gpio_set,
+- .base = 0,
+- .ngpio = 32,
+- },
+- },
+- [1] = {
+- .regbase = GPIO1_BASE,
+- .chip = {
+- .label = "gpio-1",
+- .direction_input = pxa_gpio_direction_input,
+- .direction_output = pxa_gpio_direction_output,
+- .get = pxa_gpio_get,
+- .set = pxa_gpio_set,
+- .base = 32,
+- .ngpio = 32,
+- },
+- },
+- [2] = {
+- .regbase = GPIO2_BASE,
+- .chip = {
+- .label = "gpio-2",
+- .direction_input = pxa_gpio_direction_input,
+- .direction_output = pxa_gpio_direction_output,
+- .get = pxa_gpio_get,
+- .set = pxa_gpio_set,
+- .base = 64,
+- .ngpio = 32, /* 21 for PXA25x */
+- },
+- },
++ GPIO_CHIP(0),
++ GPIO_CHIP(1),
++ GPIO_CHIP(2),
+ #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+- [3] = {
+- .regbase = GPIO3_BASE,
+- .chip = {
+- .label = "gpio-3",
+- .direction_input = pxa_gpio_direction_input,
+- .direction_output = pxa_gpio_direction_output,
+- .get = pxa_gpio_get,
+- .set = pxa_gpio_set,
+- .base = 96,
+- .ngpio = 32,
+- },
+- },
++ GPIO_CHIP(3),
+ #endif
+ };
+
+-void __init pxa_init_gpio(int gpio_nr)
++/*
++ * PXA GPIO edge detection for IRQs:
++ * IRQs are generated on Falling-Edge, Rising-Edge, or both.
++ * Use this instead of directly setting GRER/GFER.
++ */
++
++static unsigned long GPIO_IRQ_rising_edge[4];
++static unsigned long GPIO_IRQ_falling_edge[4];
++static unsigned long GPIO_IRQ_mask[4];
++
++/*
++ * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate
++ * function of a GPIO, and GPDRx cannot be altered once configured. It
++ * is attributed as "occupied" here (I know this terminology isn't
++ * accurate, you are welcome to propose a better one :-)
++ */
++static int __gpio_is_occupied(unsigned gpio)
++{
++ if (cpu_is_pxa25x() || cpu_is_pxa27x())
++ return GAFR(gpio) & (0x3 << (((gpio) & 0xf) * 2));
++ else
++ return 0;
++}
++
++static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
++{
++ int gpio, idx;
++
++ gpio = IRQ_TO_GPIO(irq);
++ idx = gpio >> 5;
++
++ if (type == IRQ_TYPE_PROBE) {
++ /* Don't mess with enabled GPIOs using preconfigured edges or
++ * GPIOs set to alternate function or to output during probe
++ */
++ if ((GPIO_IRQ_rising_edge[idx] |
++ GPIO_IRQ_falling_edge[idx] |
++ GPDR(gpio)) & GPIO_bit(gpio))
++ return 0;
++
++ if (__gpio_is_occupied(gpio))
++ return 0;
++
++ type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
++ }
++
++ GPDR(gpio) &= ~GPIO_bit(gpio);
++
++ if (type & IRQ_TYPE_EDGE_RISING)
++ __set_bit(gpio, GPIO_IRQ_rising_edge);
++ else
++ __clear_bit(gpio, GPIO_IRQ_rising_edge);
++
++ if (type & IRQ_TYPE_EDGE_FALLING)
++ __set_bit(gpio, GPIO_IRQ_falling_edge);
++ else
++ __clear_bit(gpio, GPIO_IRQ_falling_edge);
++
++ GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx];
++ GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
++
++ pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, irq, gpio,
++ ((type & IRQ_TYPE_EDGE_RISING) ? " rising" : ""),
++ ((type & IRQ_TYPE_EDGE_FALLING) ? " falling" : ""));
++ return 0;
++}
++
++/*
++ * GPIO IRQs must be acknowledged. This is for GPIO 0 and 1.
++ */
++
++static void pxa_ack_low_gpio(unsigned int irq)
++{
++ GEDR0 = (1 << (irq - IRQ_GPIO0));
++}
++
++static void pxa_mask_low_gpio(unsigned int irq)
++{
++ ICMR &= ~(1 << (irq - PXA_IRQ(0)));
++}
++
++static void pxa_unmask_low_gpio(unsigned int irq)
++{
++ ICMR |= 1 << (irq - PXA_IRQ(0));
++}
++
++static struct irq_chip pxa_low_gpio_chip = {
++ .name = "GPIO-l",
++ .ack = pxa_ack_low_gpio,
++ .mask = pxa_mask_low_gpio,
++ .unmask = pxa_unmask_low_gpio,
++ .set_type = pxa_gpio_irq_type,
++};
++
++/*
++ * Demux handler for GPIO>=2 edge detect interrupts
++ */
++
++#define GEDR_BITS (sizeof(gedr) * BITS_PER_BYTE)
++
++static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
++{
++ int loop, bit, n;
++ unsigned long gedr[4];
++
++ do {
++ gedr[0] = GEDR0 & GPIO_IRQ_mask[0] & ~3;
++ gedr[1] = GEDR1 & GPIO_IRQ_mask[1];
++ gedr[2] = GEDR2 & GPIO_IRQ_mask[2];
++ gedr[3] = GEDR3 & GPIO_IRQ_mask[3];
++
++ GEDR0 = gedr[0]; GEDR1 = gedr[1];
++ GEDR2 = gedr[2]; GEDR3 = gedr[3];
++
++ loop = 0;
++ bit = find_first_bit(gedr, GEDR_BITS);
++ while (bit < GEDR_BITS) {
++ loop = 1;
++
++ n = PXA_GPIO_IRQ_BASE + bit;
++ desc_handle_irq(n, irq_desc + n);
++
++ bit = find_next_bit(gedr, GEDR_BITS, bit + 1);
++ }
++ } while (loop);
++}
++
++static void pxa_ack_muxed_gpio(unsigned int irq)
++{
++ int gpio = irq - IRQ_GPIO(2) + 2;
++ GEDR(gpio) = GPIO_bit(gpio);
++}
++
++static void pxa_mask_muxed_gpio(unsigned int irq)
++{
++ int gpio = irq - IRQ_GPIO(2) + 2;
++ __clear_bit(gpio, GPIO_IRQ_mask);
++ GRER(gpio) &= ~GPIO_bit(gpio);
++ GFER(gpio) &= ~GPIO_bit(gpio);
++}
++
++static void pxa_unmask_muxed_gpio(unsigned int irq)
++{
++ int gpio = irq - IRQ_GPIO(2) + 2;
++ int idx = gpio >> 5;
++ __set_bit(gpio, GPIO_IRQ_mask);
++ GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx];
++ GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
++}
++
++static struct irq_chip pxa_muxed_gpio_chip = {
++ .name = "GPIO",
++ .ack = pxa_ack_muxed_gpio,
++ .mask = pxa_mask_muxed_gpio,
++ .unmask = pxa_unmask_muxed_gpio,
++ .set_type = pxa_gpio_irq_type,
++};
++
++void __init pxa_init_gpio(int gpio_nr, set_wake_t fn)
+ {
+- int i;
++ int irq, i, gpio;
++
++ pxa_last_gpio = gpio_nr - 1;
++
++ /* clear all GPIO edge detects */
++ for (i = 0; i < gpio_nr; i += 32) {
++ GFER(i) = 0;
++ GRER(i) = 0;
++ GEDR(i) = GEDR(i);
++ }
++
++ /* GPIO 0 and 1 must have their mask bit always set */
++ GPIO_IRQ_mask[0] = 3;
++
++ for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
++ set_irq_chip(irq, &pxa_low_gpio_chip);
++ set_irq_handler(irq, handle_edge_irq);
++ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
++ }
++
++ for (irq = IRQ_GPIO(2); irq < IRQ_GPIO(gpio_nr); irq++) {
++ set_irq_chip(irq, &pxa_muxed_gpio_chip);
++ set_irq_handler(irq, handle_edge_irq);
++ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
++ }
++
++ /* Install handler for GPIO>=2 edge detect interrupts */
++ set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler);
++
++ pxa_low_gpio_chip.set_wake = fn;
++ pxa_muxed_gpio_chip.set_wake = fn;
+
+ /* add a GPIO chip for each register bank.
+ * the last PXA25x register only contains 21 GPIOs
+ */
+- for (i = 0; i < gpio_nr; i += 32) {
+- if (i+32 > gpio_nr)
+- pxa_gpio_chip[i/32].chip.ngpio = gpio_nr - i;
+- gpiochip_add(&pxa_gpio_chip[i/32].chip);
++ for (gpio = 0, i = 0; gpio < gpio_nr; gpio += 32, i++) {
++ if (gpio + 32 > gpio_nr)
++ pxa_gpio_chip[i].chip.ngpio = gpio_nr - gpio;
++ gpiochip_add(&pxa_gpio_chip[i].chip);
+ }
+ }
++
++#ifdef CONFIG_PM
++
++static unsigned long saved_gplr[4];
++static unsigned long saved_gpdr[4];
++static unsigned long saved_grer[4];
++static unsigned long saved_gfer[4];
++
++static int pxa_gpio_suspend(struct sys_device *dev, pm_message_t state)
++{
++ int i, gpio;
++
++ for (gpio = 0, i = 0; gpio < pxa_last_gpio; gpio += 32, i++) {
++ saved_gplr[i] = GPLR(gpio);
++ saved_gpdr[i] = GPDR(gpio);
++ saved_grer[i] = GRER(gpio);
++ saved_gfer[i] = GFER(gpio);
++
++ /* Clear GPIO transition detect bits */
++ GEDR(gpio) = GEDR(gpio);
++ }
++ return 0;
++}
++
++static int pxa_gpio_resume(struct sys_device *dev)
++{
++ int i, gpio;
++
++ for (gpio = 0, i = 0; gpio < pxa_last_gpio; gpio += 32, i++) {
++ /* restore level with set/clear */
++ GPSR(gpio) = saved_gplr[i];
++ GPCR(gpio) = ~saved_gplr[i];
++
++ GRER(gpio) = saved_grer[i];
++ GFER(gpio) = saved_gfer[i];
++ GPDR(gpio) = saved_gpdr[i];
++ }
++ return 0;
++}
++#else
++#define pxa_gpio_suspend NULL
++#define pxa_gpio_resume NULL
++#endif
++
++struct sysdev_class pxa_gpio_sysclass = {
++ .name = "gpio",
++ .suspend = pxa_gpio_suspend,
++ .resume = pxa_gpio_resume,
++};
++
++static int __init pxa_gpio_init(void)
++{
++ return sysdev_class_register(&pxa_gpio_sysclass);
++}
++
++core_initcall(pxa_gpio_init);
+diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c
+new file mode 100644
+index 0000000..f01d185
+--- /dev/null
++++ b/arch/arm/mach-pxa/gumstix.c
+@@ -0,0 +1,147 @@
++/*
++ * linux/arch/arm/mach-pxa/gumstix.c
++ *
++ * Support for the Gumstix motherboards.
++ *
++ * Original Author: Craig Hughes
++ * Created: Feb 14, 2008
++ * Copyright: Craig Hughes
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * Implemented based on lubbock.c by Nicolas Pitre and code from Craig
++ * Hughes
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/interrupt.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++
++#include <asm/setup.h>
++#include <asm/memory.h>
++#include <asm/mach-types.h>
++#include <asm/hardware.h>
++#include <asm/irq.h>
++#include <asm/sizes.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <asm/mach/irq.h>
++#include <asm/mach/flash.h>
++#include <asm/arch/mmc.h>
++#include <asm/arch/udc.h>
++#include <asm/arch/gumstix.h>
++
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-regs.h>
++
++#include "generic.h"
++
++static struct resource flash_resource = {
++ .start = 0x00000000,
++ .end = SZ_64M - 1,
++ .flags = IORESOURCE_MEM,
++};
++
++static struct mtd_partition gumstix_partitions[] = {
++ {
++ .name = "Bootloader",
++ .size = 0x00040000,
++ .offset = 0,
++ .mask_flags = MTD_WRITEABLE /* force read-only */
++ } , {
++ .name = "rootfs",
++ .size = MTDPART_SIZ_FULL,
++ .offset = MTDPART_OFS_APPEND
++ }
++};
++
++static struct flash_platform_data gumstix_flash_data = {
++ .map_name = "cfi_probe",
++ .parts = gumstix_partitions,
++ .nr_parts = ARRAY_SIZE(gumstix_partitions),
++ .width = 2,
++};
++
++static struct platform_device gumstix_flash_device = {
++ .name = "pxa2xx-flash",
++ .id = 0,
++ .dev = {
++ .platform_data = &gumstix_flash_data,
++ },
++ .resource = &flash_resource,
++ .num_resources = 1,
++};
++
++static struct platform_device *devices[] __initdata = {
++ &gumstix_flash_device,
++};
++
++#ifdef CONFIG_MMC_PXA
++static struct pxamci_platform_data gumstix_mci_platform_data;
++
++static int gumstix_mci_init(struct device *dev, irq_handler_t detect_int,
++ void *data)
++{
++ pxa_gpio_mode(GPIO6_MMCCLK_MD);
++ pxa_gpio_mode(GPIO53_MMCCLK_MD);
++ pxa_gpio_mode(GPIO8_MMCCS0_MD);
++
++ return 0;
++}
++
++static struct pxamci_platform_data gumstix_mci_platform_data = {
++ .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
++ .init = gumstix_mci_init,
++};
++
++static void __init gumstix_mmc_init(void)
++{
++ pxa_set_mci_info(&gumstix_mci_platform_data);
++}
++#else
++static void __init gumstix_mmc_init(void)
++{
++ printk(KERN_INFO "Gumstix mmc disabled\n");
++}
++#endif
++
++#ifdef CONFIG_USB_GADGET_PXA2XX
++static struct pxa2xx_udc_mach_info gumstix_udc_info __initdata = {
++ .gpio_vbus = GPIO_GUMSTIX_USB_GPIOn,
++ .gpio_pullup = GPIO_GUMSTIX_USB_GPIOx,
++};
++
++static void __init gumstix_udc_init(void)
++{
++ pxa_set_udc_info(&gumstix_udc_info);
++}
++#else
++static void gumstix_udc_init(void)
++{
++ printk(KERN_INFO "Gumstix udc is disabled\n");
++}
++#endif
++
++static void __init gumstix_init(void)
++{
++ gumstix_udc_init();
++ gumstix_mmc_init();
++ (void) platform_add_devices(devices, ARRAY_SIZE(devices));
++}
++
++MACHINE_START(GUMSTIX, "Gumstix")
++ .phys_io = 0x40000000,
++ .boot_params = 0xa0000100, /* match u-boot bi_boot_params */
++ .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
++ .map_io = pxa_map_io,
++ .init_irq = pxa25x_init_irq,
++ .timer = &pxa_timer,
++ .init_machine = gumstix_init,
++MACHINE_END
+diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
+index 0a94344..2637633 100644
+--- a/arch/arm/mach-pxa/idp.c
++++ b/arch/arm/mach-pxa/idp.c
+@@ -32,6 +32,7 @@
+ #include <asm/mach/map.h>
+
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/idp.h>
+ #include <asm/arch/pxafb.h>
+ #include <asm/arch/bitfield.h>
+diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
+index 36c6a68..a9a0c3f 100644
+--- a/arch/arm/mach-pxa/irq.c
++++ b/arch/arm/mach-pxa/irq.c
+@@ -1,7 +1,7 @@
+ /*
+ * linux/arch/arm/mach-pxa/irq.c
+ *
+- * Generic PXA IRQ handling, GPIO IRQ demultiplexing, etc.
++ * Generic PXA IRQ handling
+ *
+ * Author: Nicolas Pitre
+ * Created: Jun 15, 2001
+@@ -21,308 +21,58 @@
+ #include <asm/irq.h>
+ #include <asm/mach/irq.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+
+ #include "generic.h"
+
++#define IRQ_BIT(n) (((n) - PXA_IRQ(0)) & 0x1f)
++#define _ICMR(n) (*((((n) - PXA_IRQ(0)) & ~0x1f) ? &ICMR2 : &ICMR))
++#define _ICLR(n) (*((((n) - PXA_IRQ(0)) & ~0x1f) ? &ICLR2 : &ICLR))
+
+ /*
+ * This is for peripheral IRQs internal to the PXA chip.
+ */
+
+-static void pxa_mask_low_irq(unsigned int irq)
++static int pxa_internal_irq_nr;
++
++static void pxa_mask_irq(unsigned int irq)
+ {
+- ICMR &= ~(1 << irq);
++ _ICMR(irq) &= ~(1 << IRQ_BIT(irq));
+ }
+
+-static void pxa_unmask_low_irq(unsigned int irq)
++static void pxa_unmask_irq(unsigned int irq)
+ {
+- ICMR |= (1 << irq);
++ _ICMR(irq) |= 1 << IRQ_BIT(irq);
+ }
+
+-static struct irq_chip pxa_internal_chip_low = {
++static struct irq_chip pxa_internal_irq_chip = {
+ .name = "SC",
+- .ack = pxa_mask_low_irq,
+- .mask = pxa_mask_low_irq,
+- .unmask = pxa_unmask_low_irq,
++ .ack = pxa_mask_irq,
++ .mask = pxa_mask_irq,
++ .unmask = pxa_unmask_irq,
+ };
+
+-void __init pxa_init_irq_low(void)
++void __init pxa_init_irq(int irq_nr, set_wake_t fn)
+ {
+ int irq;
+
+- /* disable all IRQs */
+- ICMR = 0;
++ pxa_internal_irq_nr = irq_nr;
+
+- /* all IRQs are IRQ, not FIQ */
+- ICLR = 0;
++ for (irq = 0; irq < irq_nr; irq += 32) {
++ _ICMR(irq) = 0; /* disable all IRQs */
++ _ICLR(irq) = 0; /* all IRQs are IRQ, not FIQ */
++ }
+
+ /* only unmasked interrupts kick us out of idle */
+ ICCR = 1;
+
+- for (irq = PXA_IRQ(0); irq <= PXA_IRQ(31); irq++) {
+- set_irq_chip(irq, &pxa_internal_chip_low);
+- set_irq_handler(irq, handle_level_irq);
+- set_irq_flags(irq, IRQF_VALID);
+- }
+-}
+-
+-#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+-
+-/*
+- * This is for the second set of internal IRQs as found on the PXA27x.
+- */
+-
+-static void pxa_mask_high_irq(unsigned int irq)
+-{
+- ICMR2 &= ~(1 << (irq - 32));
+-}
+-
+-static void pxa_unmask_high_irq(unsigned int irq)
+-{
+- ICMR2 |= (1 << (irq - 32));
+-}
+-
+-static struct irq_chip pxa_internal_chip_high = {
+- .name = "SC-hi",
+- .ack = pxa_mask_high_irq,
+- .mask = pxa_mask_high_irq,
+- .unmask = pxa_unmask_high_irq,
+-};
+-
+-void __init pxa_init_irq_high(void)
+-{
+- int irq;
+-
+- ICMR2 = 0;
+- ICLR2 = 0;
+-
+- for (irq = PXA_IRQ(32); irq < PXA_IRQ(64); irq++) {
+- set_irq_chip(irq, &pxa_internal_chip_high);
++ for (irq = PXA_IRQ(0); irq < PXA_IRQ(irq_nr); irq++) {
++ set_irq_chip(irq, &pxa_internal_irq_chip);
+ set_irq_handler(irq, handle_level_irq);
+ set_irq_flags(irq, IRQF_VALID);
+ }
+-}
+-#endif
+-
+-/*
+- * PXA GPIO edge detection for IRQs:
+- * IRQs are generated on Falling-Edge, Rising-Edge, or both.
+- * Use this instead of directly setting GRER/GFER.
+- */
+-
+-static long GPIO_IRQ_rising_edge[4];
+-static long GPIO_IRQ_falling_edge[4];
+-static long GPIO_IRQ_mask[4];
+-
+-static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
+-{
+- int gpio, idx;
+-
+- gpio = IRQ_TO_GPIO(irq);
+- idx = gpio >> 5;
+-
+- if (type == IRQT_PROBE) {
+- /* Don't mess with enabled GPIOs using preconfigured edges or
+- GPIOs set to alternate function or to output during probe */
+- if ((GPIO_IRQ_rising_edge[idx] | GPIO_IRQ_falling_edge[idx] | GPDR(gpio)) &
+- GPIO_bit(gpio))
+- return 0;
+- if (GAFR(gpio) & (0x3 << (((gpio) & 0xf)*2)))
+- return 0;
+- type = __IRQT_RISEDGE | __IRQT_FALEDGE;
+- }
+-
+- /* printk(KERN_DEBUG "IRQ%d (GPIO%d): ", irq, gpio); */
+-
+- pxa_gpio_mode(gpio | GPIO_IN);
+-
+- if (type & __IRQT_RISEDGE) {
+- /* printk("rising "); */
+- __set_bit (gpio, GPIO_IRQ_rising_edge);
+- } else {
+- __clear_bit (gpio, GPIO_IRQ_rising_edge);
+- }
+-
+- if (type & __IRQT_FALEDGE) {
+- /* printk("falling "); */
+- __set_bit (gpio, GPIO_IRQ_falling_edge);
+- } else {
+- __clear_bit (gpio, GPIO_IRQ_falling_edge);
+- }
+-
+- /* printk("edges\n"); */
+-
+- GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx];
+- GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
+- return 0;
+-}
+-
+-/*
+- * GPIO IRQs must be acknowledged. This is for GPIO 0 and 1.
+- */
+-
+-static void pxa_ack_low_gpio(unsigned int irq)
+-{
+- GEDR0 = (1 << (irq - IRQ_GPIO0));
+-}
+-
+-static struct irq_chip pxa_low_gpio_chip = {
+- .name = "GPIO-l",
+- .ack = pxa_ack_low_gpio,
+- .mask = pxa_mask_low_irq,
+- .unmask = pxa_unmask_low_irq,
+- .set_type = pxa_gpio_irq_type,
+-};
+-
+-/*
+- * Demux handler for GPIO>=2 edge detect interrupts
+- */
+-
+-static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
+-{
+- unsigned int mask;
+- int loop;
+-
+- do {
+- loop = 0;
+-
+- mask = GEDR0 & GPIO_IRQ_mask[0] & ~3;
+- if (mask) {
+- GEDR0 = mask;
+- irq = IRQ_GPIO(2);
+- desc = irq_desc + irq;
+- mask >>= 2;
+- do {
+- if (mask & 1)
+- desc_handle_irq(irq, desc);
+- irq++;
+- desc++;
+- mask >>= 1;
+- } while (mask);
+- loop = 1;
+- }
+-
+- mask = GEDR1 & GPIO_IRQ_mask[1];
+- if (mask) {
+- GEDR1 = mask;
+- irq = IRQ_GPIO(32);
+- desc = irq_desc + irq;
+- do {
+- if (mask & 1)
+- desc_handle_irq(irq, desc);
+- irq++;
+- desc++;
+- mask >>= 1;
+- } while (mask);
+- loop = 1;
+- }
+-
+- mask = GEDR2 & GPIO_IRQ_mask[2];
+- if (mask) {
+- GEDR2 = mask;
+- irq = IRQ_GPIO(64);
+- desc = irq_desc + irq;
+- do {
+- if (mask & 1)
+- desc_handle_irq(irq, desc);
+- irq++;
+- desc++;
+- mask >>= 1;
+- } while (mask);
+- loop = 1;
+- }
+-
+- mask = GEDR3 & GPIO_IRQ_mask[3];
+- if (mask) {
+- GEDR3 = mask;
+- irq = IRQ_GPIO(96);
+- desc = irq_desc + irq;
+- do {
+- if (mask & 1)
+- desc_handle_irq(irq, desc);
+- irq++;
+- desc++;
+- mask >>= 1;
+- } while (mask);
+- loop = 1;
+- }
+- } while (loop);
+-}
+-
+-static void pxa_ack_muxed_gpio(unsigned int irq)
+-{
+- int gpio = irq - IRQ_GPIO(2) + 2;
+- GEDR(gpio) = GPIO_bit(gpio);
+-}
+-
+-static void pxa_mask_muxed_gpio(unsigned int irq)
+-{
+- int gpio = irq - IRQ_GPIO(2) + 2;
+- __clear_bit(gpio, GPIO_IRQ_mask);
+- GRER(gpio) &= ~GPIO_bit(gpio);
+- GFER(gpio) &= ~GPIO_bit(gpio);
+-}
+-
+-static void pxa_unmask_muxed_gpio(unsigned int irq)
+-{
+- int gpio = irq - IRQ_GPIO(2) + 2;
+- int idx = gpio >> 5;
+- __set_bit(gpio, GPIO_IRQ_mask);
+- GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx];
+- GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
+-}
+-
+-static struct irq_chip pxa_muxed_gpio_chip = {
+- .name = "GPIO",
+- .ack = pxa_ack_muxed_gpio,
+- .mask = pxa_mask_muxed_gpio,
+- .unmask = pxa_unmask_muxed_gpio,
+- .set_type = pxa_gpio_irq_type,
+-};
+-
+-void __init pxa_init_irq_gpio(int gpio_nr)
+-{
+- int irq, i;
+-
+- pxa_last_gpio = gpio_nr - 1;
+-
+- /* clear all GPIO edge detects */
+- for (i = 0; i < gpio_nr; i += 32) {
+- GFER(i) = 0;
+- GRER(i) = 0;
+- GEDR(i) = GEDR(i);
+- }
+-
+- /* GPIO 0 and 1 must have their mask bit always set */
+- GPIO_IRQ_mask[0] = 3;
+-
+- for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
+- set_irq_chip(irq, &pxa_low_gpio_chip);
+- set_irq_handler(irq, handle_edge_irq);
+- set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+- }
+
+- for (irq = IRQ_GPIO(2); irq < IRQ_GPIO(gpio_nr); irq++) {
+- set_irq_chip(irq, &pxa_muxed_gpio_chip);
+- set_irq_handler(irq, handle_edge_irq);
+- set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+- }
+-
+- /* Install handler for GPIO>=2 edge detect interrupts */
+- set_irq_chip(IRQ_GPIO_2_x, &pxa_internal_chip_low);
+- set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler);
+-
+- pxa_init_gpio(gpio_nr);
+-}
+-
+-void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int))
+-{
+- pxa_internal_chip_low.set_wake = set_wake;
+-#ifdef CONFIG_PXA27x
+- pxa_internal_chip_high.set_wake = set_wake;
+-#endif
+- pxa_low_gpio_chip.set_wake = set_wake;
+- pxa_muxed_gpio_chip.set_wake = set_wake;
++ pxa_internal_irq_chip.set_wake = fn;
+ }
+
+ #ifdef CONFIG_PM
+@@ -330,19 +80,11 @@ static unsigned long saved_icmr[2];
+
+ static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state)
+ {
+- switch (dev->id) {
+- case 0:
+- saved_icmr[0] = ICMR;
+- ICMR = 0;
+- break;
+-#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+- case 1:
+- saved_icmr[1] = ICMR2;
+- ICMR2 = 0;
+- break;
+-#endif
+- default:
+- return -EINVAL;
++ int i, irq = PXA_IRQ(0);
++
++ for (i = 0; irq < PXA_IRQ(pxa_internal_irq_nr); i++, irq += 32) {
++ saved_icmr[i] = _ICMR(irq);
++ _ICMR(irq) = 0;
+ }
+
+ return 0;
+@@ -350,22 +92,14 @@ static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state)
+
+ static int pxa_irq_resume(struct sys_device *dev)
+ {
+- switch (dev->id) {
+- case 0:
+- ICMR = saved_icmr[0];
+- ICLR = 0;
+- ICCR = 1;
+- break;
+-#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+- case 1:
+- ICMR2 = saved_icmr[1];
+- ICLR2 = 0;
+- break;
+-#endif
+- default:
+- return -EINVAL;
++ int i, irq = PXA_IRQ(0);
++
++ for (i = 0; irq < PXA_IRQ(pxa_internal_irq_nr); i++, irq += 32) {
++ _ICMR(irq) = saved_icmr[i];
++ _ICLR(irq) = 0;
+ }
+
++ ICCR = 1;
+ return 0;
+ }
+ #else
+diff --git a/arch/arm/mach-pxa/leds-trizeps4.c b/arch/arm/mach-pxa/leds-trizeps4.c
+index 2271d20..21880da 100644
+--- a/arch/arm/mach-pxa/leds-trizeps4.c
++++ b/arch/arm/mach-pxa/leds-trizeps4.c
+@@ -18,6 +18,7 @@
+ #include <asm/leds.h>
+
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/trizeps4.h>
+
+ #include "leds.h"
+diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
+index 0a4b54c..0339606 100644
+--- a/arch/arm/mach-pxa/littleton.c
++++ b/arch/arm/mach-pxa/littleton.c
+@@ -37,12 +37,11 @@
+ #include <asm/arch/gpio.h>
+ #include <asm/arch/pxafb.h>
+ #include <asm/arch/ssp.h>
++#include <asm/arch/pxa27x_keypad.h>
+ #include <asm/arch/littleton.h>
+
+ #include "generic.h"
+
+-#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x)
+-
+ /* Littleton MFP configurations */
+ static mfp_cfg_t littleton_mfp_cfg[] __initdata = {
+ /* LCD */
+@@ -76,6 +75,21 @@ static mfp_cfg_t littleton_mfp_cfg[] __initdata = {
+
+ /* Debug Ethernet */
+ GPIO90_GPIO,
++
++ /* Keypad */
++ GPIO107_KP_DKIN_0,
++ GPIO108_KP_DKIN_1,
++ GPIO115_KP_MKIN_0,
++ GPIO116_KP_MKIN_1,
++ GPIO117_KP_MKIN_2,
++ GPIO118_KP_MKIN_3,
++ GPIO119_KP_MKIN_4,
++ GPIO120_KP_MKIN_5,
++ GPIO121_KP_MKOUT_0,
++ GPIO122_KP_MKOUT_1,
++ GPIO123_KP_MKOUT_2,
++ GPIO124_KP_MKOUT_3,
++ GPIO125_KP_MKOUT_4,
+ };
+
+ static struct resource smc91x_resources[] = {
+@@ -300,6 +314,54 @@ static void littleton_init_lcd(void)
+ static inline void littleton_init_lcd(void) {};
+ #endif /* CONFIG_FB_PXA || CONFIG_FB_PXA_MODULES */
+
++#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULES)
++static unsigned int littleton_matrix_key_map[] = {
++ /* KEY(row, col, key_code) */
++ KEY(1, 3, KEY_0), KEY(0, 0, KEY_1), KEY(1, 0, KEY_2), KEY(2, 0, KEY_3),
++ KEY(0, 1, KEY_4), KEY(1, 1, KEY_5), KEY(2, 1, KEY_6), KEY(0, 2, KEY_7),
++ KEY(1, 2, KEY_8), KEY(2, 2, KEY_9),
++
++ KEY(0, 3, KEY_KPASTERISK), /* * */
++ KEY(2, 3, KEY_KPDOT), /* # */
++
++ KEY(5, 4, KEY_ENTER),
++
++ KEY(5, 0, KEY_UP),
++ KEY(5, 1, KEY_DOWN),
++ KEY(5, 2, KEY_LEFT),
++ KEY(5, 3, KEY_RIGHT),
++ KEY(3, 2, KEY_HOME),
++ KEY(4, 1, KEY_END),
++ KEY(3, 3, KEY_BACK),
++
++ KEY(4, 0, KEY_SEND),
++ KEY(4, 2, KEY_VOLUMEUP),
++ KEY(4, 3, KEY_VOLUMEDOWN),
++
++ KEY(3, 0, KEY_F22), /* soft1 */
++ KEY(3, 1, KEY_F23), /* soft2 */
++};
++
++static struct pxa27x_keypad_platform_data littleton_keypad_info = {
++ .matrix_key_rows = 6,
++ .matrix_key_cols = 5,
++ .matrix_key_map = littleton_matrix_key_map,
++ .matrix_key_map_size = ARRAY_SIZE(littleton_matrix_key_map),
++
++ .enable_rotary0 = 1,
++ .rotary0_up_key = KEY_UP,
++ .rotary0_down_key = KEY_DOWN,
++
++ .debounce_interval = 30,
++};
++static void __init littleton_init_keypad(void)
++{
++ pxa_set_keypad_info(&littleton_keypad_info);
++}
++#else
++static inline void littleton_init_keypad(void) {}
++#endif
++
+ static void __init littleton_init(void)
+ {
+ /* initialize MFP configurations */
+@@ -312,6 +374,7 @@ static void __init littleton_init(void)
+ platform_device_register(&smc91x_device);
+
+ littleton_init_lcd();
++ littleton_init_keypad();
+ }
+
+ MACHINE_START(LITTLETON, "Marvell Form Factor Development Platform (aka Littleton)")
+diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
+index afa62ff..a20e4b1 100644
+--- a/arch/arm/mach-pxa/lpd270.c
++++ b/arch/arm/mach-pxa/lpd270.c
+@@ -39,6 +39,7 @@
+
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/arch/pxa2xx-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/lpd270.h>
+ #include <asm/arch/audio.h>
+ #include <asm/arch/pxafb.h>
+diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
+index e7ae4bb..ca209c4 100644
+--- a/arch/arm/mach-pxa/lubbock.c
++++ b/arch/arm/mach-pxa/lubbock.c
+@@ -42,6 +42,7 @@
+
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/arch/pxa2xx-regs.h>
++#include <asm/arch/mfp-pxa25x.h>
+ #include <asm/arch/lubbock.h>
+ #include <asm/arch/udc.h>
+ #include <asm/arch/irda.h>
+@@ -51,6 +52,40 @@
+ #include "generic.h"
+ #include "devices.h"
+
++static unsigned long lubbock_pin_config[] __initdata = {
++ GPIO15_nCS_1, /* CS1 - Flash */
++ GPIO79_nCS_3, /* CS3 - SMC ethernet */
++
++ /* SSP data pins */
++ GPIO23_SSP1_SCLK,
++ GPIO25_SSP1_TXD,
++ GPIO26_SSP1_RXD,
++
++ /* BTUART */
++ GPIO42_BTUART_RXD,
++ GPIO43_BTUART_TXD,
++ GPIO44_BTUART_CTS,
++ GPIO45_BTUART_RTS,
++
++ /* PC Card */
++ GPIO48_nPOE,
++ GPIO49_nPWE,
++ GPIO50_nPIOR,
++ GPIO51_nPIOW,
++ GPIO52_nPCE_1,
++ GPIO53_nPCE_2,
++ GPIO54_nPSKTSEL,
++ GPIO55_nPREG,
++ GPIO56_nPWAIT,
++ GPIO57_nIOIS16,
++
++ /* MMC */
++ GPIO6_MMC_CLK,
++ GPIO8_MMC_CS0,
++
++ /* wakeup */
++ GPIO1_GPIO | WAKEUP_ON_EDGE_RISE,
++};
+
+ #define LUB_MISC_WR __LUB_REG(LUBBOCK_FPGA_PHYS + 0x080)
+
+@@ -186,26 +221,6 @@ static struct platform_device sa1111_device = {
+ .resource = sa1111_resources,
+ };
+
+-static struct resource smc91x_resources[] = {
+- [0] = {
+- .name = "smc91x-regs",
+- .start = 0x0c000c00,
+- .end = 0x0c0fffff,
+- .flags = IORESOURCE_MEM,
+- },
+- [1] = {
+- .start = LUBBOCK_ETH_IRQ,
+- .end = LUBBOCK_ETH_IRQ,
+- .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+- },
+- [2] = {
+- .name = "smc91x-attrib",
+- .start = 0x0e000000,
+- .end = 0x0e0fffff,
+- .flags = IORESOURCE_MEM,
+- },
+-};
+-
+ /* ADS7846 is connected through SSP ... and if your board has J5 populated,
+ * you can select it to replace the ucb1400 by switching the touchscreen cable
+ * (to J5) and poking board registers (as done below). Else it's only useful
+@@ -261,6 +276,26 @@ static struct spi_board_info spi_board_info[] __initdata = { {
+ },
+ };
+
++static struct resource smc91x_resources[] = {
++ [0] = {
++ .name = "smc91x-regs",
++ .start = 0x0c000c00,
++ .end = 0x0c0fffff,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = LUBBOCK_ETH_IRQ,
++ .end = LUBBOCK_ETH_IRQ,
++ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
++ },
++ [2] = {
++ .name = "smc91x-attrib",
++ .start = 0x0e000000,
++ .end = 0x0e0fffff,
++ .flags = IORESOURCE_MEM,
++ },
++};
++
+ static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = -1,
+@@ -404,10 +439,6 @@ static int lubbock_mci_init(struct device *dev,
+ irq_handler_t detect_int,
+ void *data)
+ {
+- /* setup GPIO for PXA25x MMC controller */
+- pxa_gpio_mode(GPIO6_MMCCLK_MD);
+- pxa_gpio_mode(GPIO8_MMCCS0_MD);
+-
+ /* detect card insert/eject */
+ mmc_detect_int = detect_int;
+ init_timer(&mmc_timer);
+@@ -457,6 +488,8 @@ static void __init lubbock_init(void)
+ {
+ int flashboot = (LUB_CONF_SWITCHES & 1);
+
++ pxa2xx_mfp_config(ARRAY_AND_SIZE(lubbock_pin_config));
++
+ pxa_set_udc_info(&udc_info);
+ set_pxa_fb_info(&sharp_lm8v31);
+ pxa_set_mci_info(&lubbock_mci_platform_data);
+@@ -489,46 +522,6 @@ static void __init lubbock_map_io(void)
+ pxa_map_io();
+ iotable_init(lubbock_io_desc, ARRAY_SIZE(lubbock_io_desc));
+
+- /* SSP data pins */
+- pxa_gpio_mode(GPIO23_SCLK_MD);
+- pxa_gpio_mode(GPIO25_STXD_MD);
+- pxa_gpio_mode(GPIO26_SRXD_MD);
+-
+- /* This enables the BTUART */
+- pxa_gpio_mode(GPIO42_BTRXD_MD);
+- pxa_gpio_mode(GPIO43_BTTXD_MD);
+- pxa_gpio_mode(GPIO44_BTCTS_MD);
+- pxa_gpio_mode(GPIO45_BTRTS_MD);
+-
+- GPSR(GPIO48_nPOE) =
+- GPIO_bit(GPIO48_nPOE) |
+- GPIO_bit(GPIO49_nPWE) |
+- GPIO_bit(GPIO50_nPIOR) |
+- GPIO_bit(GPIO51_nPIOW) |
+- GPIO_bit(GPIO52_nPCE_1) |
+- GPIO_bit(GPIO53_nPCE_2);
+-
+- pxa_gpio_mode(GPIO48_nPOE_MD);
+- pxa_gpio_mode(GPIO49_nPWE_MD);
+- pxa_gpio_mode(GPIO50_nPIOR_MD);
+- pxa_gpio_mode(GPIO51_nPIOW_MD);
+- pxa_gpio_mode(GPIO52_nPCE_1_MD);
+- pxa_gpio_mode(GPIO53_nPCE_2_MD);
+- pxa_gpio_mode(GPIO54_pSKTSEL_MD);
+- pxa_gpio_mode(GPIO55_nPREG_MD);
+- pxa_gpio_mode(GPIO56_nPWAIT_MD);
+- pxa_gpio_mode(GPIO57_nIOIS16_MD);
+-
+- /* This is for the SMC chip select */
+- pxa_gpio_mode(GPIO79_nCS_3_MD);
+-
+- /* setup sleep mode values */
+- PWER = 0x00000002;
+- PFER = 0x00000000;
+- PRER = 0x00000002;
+- PGSR0 = 0x00008000;
+- PGSR1 = 0x003F0202;
+- PGSR2 = 0x0001C000;
+ PCFR |= PCFR_OPDE;
+ }
+
+diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
+index d98ef7a..d70be75 100644
+--- a/arch/arm/mach-pxa/magician.c
++++ b/arch/arm/mach-pxa/magician.c
+@@ -16,24 +16,106 @@
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/platform_device.h>
++#include <linux/delay.h>
+ #include <linux/gpio_keys.h>
+ #include <linux/input.h>
++#include <linux/mfd/htc-egpio.h>
++#include <linux/mfd/htc-pasic3.h>
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/map.h>
+ #include <linux/mtd/physmap.h>
++#include <linux/pda_power.h>
+
+ #include <asm/gpio.h>
+ #include <asm/hardware.h>
+ #include <asm/mach-types.h>
+ #include <asm/mach/arch.h>
+ #include <asm/arch/magician.h>
++#include <asm/arch/mfp-pxa27x.h>
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/arch/pxafb.h>
++#include <asm/arch/i2c.h>
++#include <asm/arch/mmc.h>
+ #include <asm/arch/irda.h>
+ #include <asm/arch/ohci.h>
+
+ #include "generic.h"
+
++static unsigned long magician_pin_config[] = {
++
++ /* SDRAM and Static Memory I/O Signals */
++ GPIO20_nSDCS_2,
++ GPIO21_nSDCS_3,
++ GPIO15_nCS_1,
++ GPIO78_nCS_2, /* PASIC3 */
++ GPIO79_nCS_3, /* EGPIO CPLD */
++ GPIO80_nCS_4,
++ GPIO33_nCS_5,
++
++ /* I2C */
++ GPIO117_I2C_SCL,
++ GPIO118_I2C_SDA,
++
++ /* PWM 0 */
++ GPIO16_PWM0_OUT,
++
++ /* I2S */
++ GPIO28_I2S_BITCLK_OUT,
++ GPIO29_I2S_SDATA_IN,
++ GPIO31_I2S_SYNC,
++ GPIO113_I2S_SYSCLK,
++
++ /* SSP 2 */
++ GPIO19_SSP2_SCLK,
++ GPIO14_SSP2_SFRM,
++ GPIO89_SSP2_TXD,
++ GPIO88_SSP2_RXD,
++
++ /* MMC */
++ GPIO32_MMC_CLK,
++ GPIO92_MMC_DAT_0,
++ GPIO109_MMC_DAT_1,
++ GPIO110_MMC_DAT_2,
++ GPIO111_MMC_DAT_3,
++ GPIO112_MMC_CMD,
++
++ /* LCD */
++ GPIO58_LCD_LDD_0,
++ GPIO59_LCD_LDD_1,
++ GPIO60_LCD_LDD_2,
++ GPIO61_LCD_LDD_3,
++ GPIO62_LCD_LDD_4,
++ GPIO63_LCD_LDD_5,
++ GPIO64_LCD_LDD_6,
++ GPIO65_LCD_LDD_7,
++ GPIO66_LCD_LDD_8,
++ GPIO67_LCD_LDD_9,
++ GPIO68_LCD_LDD_10,
++ GPIO69_LCD_LDD_11,
++ GPIO70_LCD_LDD_12,
++ GPIO71_LCD_LDD_13,
++ GPIO72_LCD_LDD_14,
++ GPIO73_LCD_LDD_15,
++ GPIO74_LCD_FCLK,
++ GPIO75_LCD_LCLK,
++ GPIO76_LCD_PCLK,
++ GPIO77_LCD_BIAS,
++
++ /* QCI */
++ GPIO12_CIF_DD_7,
++ GPIO17_CIF_DD_6,
++ GPIO50_CIF_DD_3,
++ GPIO51_CIF_DD_2,
++ GPIO52_CIF_DD_4,
++ GPIO53_CIF_MCLK,
++ GPIO54_CIF_PCLK,
++ GPIO55_CIF_DD_1,
++ GPIO81_CIF_DD_0,
++ GPIO82_CIF_DD_5,
++ GPIO84_CIF_FV,
++ GPIO85_CIF_LV,
++};
++
+ /*
+ * IRDA
+ */
+@@ -83,8 +165,64 @@ static struct platform_device gpio_keys = {
+ .id = -1,
+ };
+
++
++/*
++ * EGPIO (Xilinx CPLD)
++ *
++ * 7 32-bit aligned 8-bit registers: 3x output, 1x irq, 3x input
++ */
++
++static struct resource egpio_resources[] = {
++ [0] = {
++ .start = PXA_CS3_PHYS,
++ .end = PXA_CS3_PHYS + 0x20,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = gpio_to_irq(GPIO13_MAGICIAN_CPLD_IRQ),
++ .end = gpio_to_irq(GPIO13_MAGICIAN_CPLD_IRQ),
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct htc_egpio_chip egpio_chips[] = {
++ [0] = {
++ .reg_start = 0,
++ .gpio_base = MAGICIAN_EGPIO(0, 0),
++ .num_gpios = 24,
++ .direction = HTC_EGPIO_OUTPUT,
++ .initial_values = 0x40, /* EGPIO_MAGICIAN_GSM_RESET */
++ },
++ [1] = {
++ .reg_start = 4,
++ .gpio_base = MAGICIAN_EGPIO(4, 0),
++ .num_gpios = 24,
++ .direction = HTC_EGPIO_INPUT,
++ },
++};
++
++static struct htc_egpio_platform_data egpio_info = {
++ .reg_width = 8,
++ .bus_width = 32,
++ .irq_base = IRQ_BOARD_START,
++ .num_irqs = 4,
++ .ack_register = 3,
++ .chip = egpio_chips,
++ .num_chips = ARRAY_SIZE(egpio_chips),
++};
++
++static struct platform_device egpio = {
++ .name = "htc-egpio",
++ .id = -1,
++ .resource = egpio_resources,
++ .num_resources = ARRAY_SIZE(egpio_resources),
++ .dev = {
++ .platform_data = &egpio_info,
++ },
++};
++
+ /*
+- * LCD - Toppoly TD028STEB1
++ * LCD - Toppoly TD028STEB1 or Samsung LTP280QV
+ */
+
+ static struct pxafb_mode_info toppoly_modes[] = {
+@@ -103,12 +241,99 @@ static struct pxafb_mode_info toppoly_modes[] = {
+ },
+ };
+
++static struct pxafb_mode_info samsung_modes[] = {
++ {
++ .pixclock = 96153,
++ .bpp = 16,
++ .xres = 240,
++ .yres = 320,
++ .hsync_len = 8,
++ .vsync_len = 4,
++ .left_margin = 9,
++ .upper_margin = 4,
++ .right_margin = 9,
++ .lower_margin = 4,
++ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
++ },
++};
++
++static void toppoly_lcd_power(int on, struct fb_var_screeninfo *si)
++{
++ pr_debug("Toppoly LCD power\n");
++
++ if (on) {
++ pr_debug("on\n");
++ gpio_set_value(EGPIO_MAGICIAN_TOPPOLY_POWER, 1);
++ gpio_set_value(GPIO106_MAGICIAN_LCD_POWER_3, 1);
++ udelay(2000);
++ gpio_set_value(EGPIO_MAGICIAN_LCD_POWER, 1);
++ udelay(2000);
++ /* FIXME: enable LCDC here */
++ udelay(2000);
++ gpio_set_value(GPIO104_MAGICIAN_LCD_POWER_1, 1);
++ udelay(2000);
++ gpio_set_value(GPIO105_MAGICIAN_LCD_POWER_2, 1);
++ } else {
++ pr_debug("off\n");
++ msleep(15);
++ gpio_set_value(GPIO105_MAGICIAN_LCD_POWER_2, 0);
++ udelay(500);
++ gpio_set_value(GPIO104_MAGICIAN_LCD_POWER_1, 0);
++ udelay(1000);
++ gpio_set_value(GPIO106_MAGICIAN_LCD_POWER_3, 0);
++ gpio_set_value(EGPIO_MAGICIAN_LCD_POWER, 0);
++ }
++}
++
++static void samsung_lcd_power(int on, struct fb_var_screeninfo *si)
++{
++ pr_debug("Samsung LCD power\n");
++
++ if (on) {
++ pr_debug("on\n");
++ if (system_rev < 3)
++ gpio_set_value(GPIO75_MAGICIAN_SAMSUNG_POWER, 1);
++ else
++ gpio_set_value(EGPIO_MAGICIAN_LCD_POWER, 1);
++ mdelay(10);
++ gpio_set_value(GPIO106_MAGICIAN_LCD_POWER_3, 1);
++ mdelay(10);
++ gpio_set_value(GPIO104_MAGICIAN_LCD_POWER_1, 1);
++ mdelay(30);
++ gpio_set_value(GPIO105_MAGICIAN_LCD_POWER_2, 1);
++ mdelay(10);
++ } else {
++ pr_debug("off\n");
++ mdelay(10);
++ gpio_set_value(GPIO105_MAGICIAN_LCD_POWER_2, 0);
++ mdelay(30);
++ gpio_set_value(GPIO104_MAGICIAN_LCD_POWER_1, 0);
++ mdelay(10);
++ gpio_set_value(GPIO106_MAGICIAN_LCD_POWER_3, 0);
++ mdelay(10);
++ if (system_rev < 3)
++ gpio_set_value(GPIO75_MAGICIAN_SAMSUNG_POWER, 0);
++ else
++ gpio_set_value(EGPIO_MAGICIAN_LCD_POWER, 0);
++ }
++}
++
+ static struct pxafb_mach_info toppoly_info = {
+- .modes = toppoly_modes,
+- .num_modes = 1,
+- .fixed_modes = 1,
+- .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+- .lccr3 = LCCR3_PixRsEdg,
++ .modes = toppoly_modes,
++ .num_modes = 1,
++ .fixed_modes = 1,
++ .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
++ .lccr3 = LCCR3_PixRsEdg,
++ .pxafb_lcd_power = toppoly_lcd_power,
++};
++
++static struct pxafb_mach_info samsung_info = {
++ .modes = samsung_modes,
++ .num_modes = 1,
++ .fixed_modes = 1,
++ .lccr0 = LCCR0_LDDALT | LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
++ .lccr3 = LCCR3_PixFlEdg,
++ .pxafb_lcd_power = samsung_lcd_power,
+ };
+
+ /*
+@@ -120,9 +345,18 @@ static void magician_set_bl_intensity(int intensity)
+ if (intensity) {
+ PWM_CTRL0 = 1;
+ PWM_PERVAL0 = 0xc8;
+- PWM_PWDUTY0 = intensity;
++ if (intensity > 0xc7) {
++ PWM_PWDUTY0 = intensity - 0x48;
++ gpio_set_value(EGPIO_MAGICIAN_BL_POWER2, 1);
++ } else {
++ PWM_PWDUTY0 = intensity;
++ gpio_set_value(EGPIO_MAGICIAN_BL_POWER2, 0);
++ }
++ gpio_set_value(EGPIO_MAGICIAN_BL_POWER, 1);
+ pxa_set_cken(CKEN_PWM0, 1);
+ } else {
++ /* PWM_PWDUTY0 = intensity; */
++ gpio_set_value(EGPIO_MAGICIAN_BL_POWER, 0);
+ pxa_set_cken(CKEN_PWM0, 0);
+ }
+ }
+@@ -130,18 +364,215 @@ static void magician_set_bl_intensity(int intensity)
+ static struct generic_bl_info backlight_info = {
+ .default_intensity = 0x64,
+ .limit_mask = 0x0b,
+- .max_intensity = 0xc7,
++ .max_intensity = 0xc7+0x48,
+ .set_bl_intensity = magician_set_bl_intensity,
+ };
+
+ static struct platform_device backlight = {
+- .name = "corgi-bl",
++ .name = "generic-bl",
+ .dev = {
+ .platform_data = &backlight_info,
+ },
+ .id = -1,
+ };
+
++/*
++ * LEDs
++ */
++
++struct gpio_led gpio_leds[] = {
++ {
++ .name = "magician::vibra",
++ .default_trigger = "none",
++ .gpio = GPIO22_MAGICIAN_VIBRA_EN,
++ },
++ {
++ .name = "magician::phone_bl",
++ .default_trigger = "none",
++ .gpio = GPIO103_MAGICIAN_LED_KP,
++ },
++};
++
++static struct gpio_led_platform_data gpio_led_info = {
++ .leds = gpio_leds,
++ .num_leds = ARRAY_SIZE(gpio_leds),
++};
++
++static struct platform_device leds_gpio = {
++ .name = "leds-gpio",
++ .id = -1,
++ .dev = {
++ .platform_data = &gpio_led_info,
++ },
++};
++
++static struct pasic3_led pasic3_leds[] = {
++ {
++ .led = {
++ .name = "magician:red",
++ .default_trigger = "ds2760-battery.0-charging",
++ },
++ .hw_num = 0,
++ .bit2 = PASIC3_BIT2_LED0,
++ .mask = PASIC3_MASK_LED0,
++ },
++ {
++ .led = {
++ .name = "magician:green",
++ .default_trigger = "ds2760-battery.0-charging-or-full",
++ },
++ .hw_num = 1,
++ .bit2 = PASIC3_BIT2_LED1,
++ .mask = PASIC3_MASK_LED1,
++ },
++ {
++ .led = {
++ .name = "magician:blue",
++ .default_trigger = "bluetooth",
++ },
++ .hw_num = 2,
++ .bit2 = PASIC3_BIT2_LED2,
++ .mask = PASIC3_MASK_LED2,
++ },
++};
++
++static struct platform_device pasic3;
++
++static struct pasic3_leds_machinfo __devinit pasic3_leds_info = {
++ .num_leds = ARRAY_SIZE(pasic3_leds),
++ .power_gpio = EGPIO_MAGICIAN_LED_POWER,
++ .leds = pasic3_leds,
++};
++
++/*
++ * PASIC3 with DS1WM
++ */
++
++static struct resource pasic3_resources[] = {
++ [0] = {
++ .start = PXA_CS2_PHYS,
++ .end = PXA_CS2_PHYS + 0x1b,
++ .flags = IORESOURCE_MEM,
++ },
++ /* No IRQ handler in the PASIC3, DS1WM needs an external IRQ */
++ [1] = {
++ .start = gpio_to_irq(GPIO107_MAGICIAN_DS1WM_IRQ),
++ .end = gpio_to_irq(GPIO107_MAGICIAN_DS1WM_IRQ),
++ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
++ }
++};
++
++static struct pasic3_platform_data pasic3_platform_data = {
++ .bus_shift = 2,
++ .led_pdata = &pasic3_leds_info,
++ .clock_rate = 4000000,
++};
++
++static struct platform_device pasic3 = {
++ .name = "pasic3",
++ .id = -1,
++ .num_resources = ARRAY_SIZE(pasic3_resources),
++ .resource = pasic3_resources,
++ .dev = {
++ .platform_data = &pasic3_platform_data,
++ },
++};
++
++/*
++ * External power
++ */
++
++static int magician_is_ac_online(void)
++{
++ return gpio_get_value(EGPIO_MAGICIAN_CABLE_STATE_AC);
++}
++
++static int magician_is_usb_online(void)
++{
++ return gpio_get_value(EGPIO_MAGICIAN_CABLE_STATE_USB);
++}
++
++static void magician_set_charge(int flags)
++{
++ gpio_set_value(GPIO30_MAGICIAN_nCHARGE_EN, !flags);
++ gpio_set_value(EGPIO_MAGICIAN_CHARGE_EN, flags);
++}
++
++static char *magician_supplicants[] = {
++ "ds2760-battery.0", "backup-battery"
++};
++
++static struct pda_power_pdata power_supply_info = {
++ .is_ac_online = magician_is_ac_online,
++ .is_usb_online = magician_is_usb_online,
++ .set_charge = magician_set_charge,
++ .supplied_to = magician_supplicants,
++ .num_supplicants = ARRAY_SIZE(magician_supplicants),
++};
++
++static struct resource power_supply_resources[] = {
++ [0] = {
++ .name = "ac",
++ .flags = IORESOURCE_IRQ,
++ .start = IRQ_MAGICIAN_AC,
++ .end = IRQ_MAGICIAN_AC,
++ },
++ [1] = {
++ .name = "usb",
++ .flags = IORESOURCE_IRQ,
++ .start = IRQ_MAGICIAN_AC,
++ .end = IRQ_MAGICIAN_AC,
++ },
++};
++
++static struct platform_device power_supply = {
++ .name = "pda-power",
++ .id = -1,
++ .dev = {
++ .platform_data = &power_supply_info,
++ },
++ .resource = power_supply_resources,
++ .num_resources = ARRAY_SIZE(power_supply_resources),
++};
++
++
++/*
++ * MMC/SD
++ */
++
++static int magician_mci_init(struct device *dev,
++ irq_handler_t detect_irq, void *data)
++{
++ return request_irq(IRQ_MAGICIAN_SD, detect_irq,
++ IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
++ "MMC card detect", data);
++}
++
++static void magician_mci_setpower(struct device *dev, unsigned int vdd)
++{
++ struct pxamci_platform_data *pdata = dev->platform_data;
++
++ gpio_set_value(EGPIO_MAGICIAN_SD_POWER, (1 << vdd) & pdata->ocr_mask);
++}
++
++static int magician_mci_get_ro(struct device *dev)
++{
++ return (!gpio_get_value(EGPIO_MAGICIAN_nSD_READONLY));
++}
++
++static void magician_mci_exit(struct device *dev, void *data)
++{
++ free_irq(IRQ_MAGICIAN_SD, data);
++}
++
++static struct pxamci_platform_data magician_mci_info = {
++ .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
++ .init = magician_mci_init,
++ .get_ro = magician_mci_get_ro,
++ .setpower = magician_mci_setpower,
++ .exit = magician_mci_exit,
++};
++
+
+ /*
+ * USB OHCI
+@@ -166,6 +597,11 @@ static struct pxaohci_platform_data magician_ohci_info = {
+ * StrataFlash
+ */
+
++static void magician_set_vpp(struct map_info *map, int vpp)
++{
++ gpio_set_value(EGPIO_MAGICIAN_FLASH_VPP, vpp);
++}
++
+ #define PXA_CS_SIZE 0x04000000
+
+ static struct resource strataflash_resource = {
+@@ -176,13 +612,14 @@ static struct resource strataflash_resource = {
+
+ static struct physmap_flash_data strataflash_data = {
+ .width = 4,
++ .set_vpp = magician_set_vpp,
+ };
+
+ static struct platform_device strataflash = {
+ .name = "physmap-flash",
+ .id = -1,
+- .num_resources = 1,
+ .resource = &strataflash_resource,
++ .num_resources = 1,
+ .dev = {
+ .platform_data = &strataflash_data,
+ },
+@@ -194,16 +631,43 @@ static struct platform_device strataflash = {
+
+ static struct platform_device *devices[] __initdata = {
+ &gpio_keys,
++ &egpio,
+ &backlight,
++ &pasic3,
++ &power_supply,
+ &strataflash,
++ &leds_gpio,
+ };
+
+ static void __init magician_init(void)
+ {
++ void __iomem *cpld;
++ int lcd_select;
++
++ pxa2xx_mfp_config(ARRAY_AND_SIZE(magician_pin_config));
++
+ platform_add_devices(devices, ARRAY_SIZE(devices));
++ pxa_set_i2c_info(NULL);
++ pxa_set_mci_info(&magician_mci_info);
+ pxa_set_ohci_info(&magician_ohci_info);
+ pxa_set_ficp_info(&magician_ficp_info);
+- set_pxa_fb_info(&toppoly_info);
++
++ /* Check LCD type we have */
++ cpld = ioremap_nocache(PXA_CS3_PHYS, 0x1000);
++ if (cpld) {
++ u8 board_id = __raw_readb(cpld+0x14);
++ system_rev = board_id & 0x7;
++ lcd_select = board_id & 0x8;
++ iounmap(cpld);
++ pr_info("LCD type: %s\n", lcd_select ? "Samsung" : "Toppoly");
++ if (lcd_select && (system_rev < 3))
++ pxa_gpio_mode(GPIO75_MAGICIAN_SAMSUNG_POWER_MD);
++ pxa_gpio_mode(GPIO104_MAGICIAN_LCD_POWER_1_MD);
++ pxa_gpio_mode(GPIO105_MAGICIAN_LCD_POWER_2_MD);
++ pxa_gpio_mode(GPIO106_MAGICIAN_LCD_POWER_3_MD);
++ set_pxa_fb_info(lcd_select ? &samsung_info : &toppoly_info);
++ } else
++ pr_err("LCD detection: CPLD mapping failed\n");
+ }
+
+
+diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
+index 72a436f..18d47cf 100644
+--- a/arch/arm/mach-pxa/mainstone.c
++++ b/arch/arm/mach-pxa/mainstone.c
+@@ -24,6 +24,8 @@
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/partitions.h>
+ #include <linux/backlight.h>
++#include <linux/input.h>
++#include <linux/gpio_keys.h>
+
+ #include <asm/types.h>
+ #include <asm/setup.h>
+@@ -40,16 +42,94 @@
+
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/arch/pxa2xx-regs.h>
++#include <asm/arch/mfp-pxa27x.h>
+ #include <asm/arch/mainstone.h>
+ #include <asm/arch/audio.h>
+ #include <asm/arch/pxafb.h>
++#include <asm/arch/i2c.h>
+ #include <asm/arch/mmc.h>
+ #include <asm/arch/irda.h>
+ #include <asm/arch/ohci.h>
++#include <asm/arch/pxa27x_keypad.h>
+
+ #include "generic.h"
+ #include "devices.h"
+
++static unsigned long mainstone_pin_config[] = {
++ /* Chip Select */
++ GPIO15_nCS_1,
++
++ /* LCD - 16bpp Active TFT */
++ GPIO58_LCD_LDD_0,
++ GPIO59_LCD_LDD_1,
++ GPIO60_LCD_LDD_2,
++ GPIO61_LCD_LDD_3,
++ GPIO62_LCD_LDD_4,
++ GPIO63_LCD_LDD_5,
++ GPIO64_LCD_LDD_6,
++ GPIO65_LCD_LDD_7,
++ GPIO66_LCD_LDD_8,
++ GPIO67_LCD_LDD_9,
++ GPIO68_LCD_LDD_10,
++ GPIO69_LCD_LDD_11,
++ GPIO70_LCD_LDD_12,
++ GPIO71_LCD_LDD_13,
++ GPIO72_LCD_LDD_14,
++ GPIO73_LCD_LDD_15,
++ GPIO74_LCD_FCLK,
++ GPIO75_LCD_LCLK,
++ GPIO76_LCD_PCLK,
++ GPIO77_LCD_BIAS,
++ GPIO16_PWM0_OUT, /* Backlight */
++
++ /* MMC */
++ GPIO32_MMC_CLK,
++ GPIO112_MMC_CMD,
++ GPIO92_MMC_DAT_0,
++ GPIO109_MMC_DAT_1,
++ GPIO110_MMC_DAT_2,
++ GPIO111_MMC_DAT_3,
++
++ /* USB Host Port 1 */
++ GPIO88_USBH1_PWR,
++ GPIO89_USBH1_PEN,
++
++ /* PC Card */
++ GPIO48_nPOE,
++ GPIO49_nPWE,
++ GPIO50_nPIOR,
++ GPIO51_nPIOW,
++ GPIO85_nPCE_1,
++ GPIO54_nPCE_2,
++ GPIO79_PSKTSEL,
++ GPIO55_nPREG,
++ GPIO56_nPWAIT,
++ GPIO57_nIOIS16,
++
++ /* AC97 */
++ GPIO45_AC97_SYSCLK,
++
++ /* Keypad */
++ GPIO93_KP_DKIN_0 | WAKEUP_ON_LEVEL_HIGH,
++ GPIO94_KP_DKIN_1 | WAKEUP_ON_LEVEL_HIGH,
++ GPIO95_KP_DKIN_2 | WAKEUP_ON_LEVEL_HIGH,
++ GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH,
++ GPIO101_KP_MKIN_1 | WAKEUP_ON_LEVEL_HIGH,
++ GPIO102_KP_MKIN_2 | WAKEUP_ON_LEVEL_HIGH,
++ GPIO97_KP_MKIN_3 | WAKEUP_ON_LEVEL_HIGH,
++ GPIO98_KP_MKIN_4 | WAKEUP_ON_LEVEL_HIGH,
++ GPIO99_KP_MKIN_5 | WAKEUP_ON_LEVEL_HIGH,
++ GPIO103_KP_MKOUT_0,
++ GPIO104_KP_MKOUT_1,
++ GPIO105_KP_MKOUT_2,
++ GPIO106_KP_MKOUT_3,
++ GPIO107_KP_MKOUT_4,
++ GPIO108_KP_MKOUT_5,
++ GPIO96_KP_MKOUT_6,
++
++ /* GPIO */
++ GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH,
++};
+
+ static unsigned long mainstone_irq_enabled;
+
+@@ -278,13 +358,13 @@ static int mainstone_backlight_update_status(struct backlight_device *bl)
+ bl->props.fb_blank != FB_BLANK_UNBLANK)
+ brightness = 0;
+
+- if (brightness != 0) {
+- pxa_gpio_mode(GPIO16_PWM0_MD);
++ if (brightness != 0)
+ pxa_set_cken(CKEN_PWM0, 1);
+- }
++
+ PWM_CTRL0 = 0;
+ PWM_PWDUTY0 = brightness;
+ PWM_PERVAL0 = bl->props.max_brightness;
++
+ if (brightness == 0)
+ pxa_set_cken(CKEN_PWM0, 0);
+ return 0; /* pointless return value */
+@@ -362,16 +442,6 @@ static int mainstone_mci_init(struct device *dev, irq_handler_t mstone_detect_in
+ {
+ int err;
+
+- /*
+- * setup GPIO for PXA27x MMC controller
+- */
+- pxa_gpio_mode(GPIO32_MMCCLK_MD);
+- pxa_gpio_mode(GPIO112_MMCCMD_MD);
+- pxa_gpio_mode(GPIO92_MMCDAT0_MD);
+- pxa_gpio_mode(GPIO109_MMCDAT1_MD);
+- pxa_gpio_mode(GPIO110_MMCDAT2_MD);
+- pxa_gpio_mode(GPIO111_MMCDAT3_MD);
+-
+ /* make sure SD/Memory Stick multiplexer's signals
+ * are routed to MMC controller
+ */
+@@ -434,19 +504,39 @@ static struct pxaficp_platform_data mainstone_ficp_platform_data = {
+ .transceiver_mode = mainstone_irda_transceiver_mode,
+ };
+
++static struct gpio_keys_button gpio_keys_button[] = {
++ [0] = {
++ .desc = "wakeup",
++ .code = KEY_SUSPEND,
++ .type = EV_KEY,
++ .gpio = 1,
++ .wakeup = 1,
++ },
++};
++
++static struct gpio_keys_platform_data mainstone_gpio_keys = {
++ .buttons = gpio_keys_button,
++ .nbuttons = 1,
++};
++
++static struct platform_device mst_gpio_keys_device = {
++ .name = "gpio-keys",
++ .id = -1,
++ .dev = {
++ .platform_data = &mainstone_gpio_keys,
++ },
++};
++
+ static struct platform_device *platform_devices[] __initdata = {
+ &smc91x_device,
+ &mst_audio_device,
+ &mst_flash_device[0],
+ &mst_flash_device[1],
++ &mst_gpio_keys_device,
+ };
+
+ static int mainstone_ohci_init(struct device *dev)
+ {
+- /* setup Port1 GPIO pin. */
+- pxa_gpio_mode( 88 | GPIO_ALT_FN_1_IN); /* USBHPWR1 */
+- pxa_gpio_mode( 89 | GPIO_ALT_FN_2_OUT); /* USBHPEN1 */
+-
+ /* Set the Power Control Polarity Low and Power Sense
+ Polarity Low to active low. */
+ UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
+@@ -460,10 +550,63 @@ static struct pxaohci_platform_data mainstone_ohci_platform_data = {
+ .init = mainstone_ohci_init,
+ };
+
++#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULES)
++static unsigned int mainstone_matrix_keys[] = {
++ KEY(0, 0, KEY_A), KEY(1, 0, KEY_B), KEY(2, 0, KEY_C),
++ KEY(3, 0, KEY_D), KEY(4, 0, KEY_E), KEY(5, 0, KEY_F),
++ KEY(0, 1, KEY_G), KEY(1, 1, KEY_H), KEY(2, 1, KEY_I),
++ KEY(3, 1, KEY_J), KEY(4, 1, KEY_K), KEY(5, 1, KEY_L),
++ KEY(0, 2, KEY_M), KEY(1, 2, KEY_N), KEY(2, 2, KEY_O),
++ KEY(3, 2, KEY_P), KEY(4, 2, KEY_Q), KEY(5, 2, KEY_R),
++ KEY(0, 3, KEY_S), KEY(1, 3, KEY_T), KEY(2, 3, KEY_U),
++ KEY(3, 3, KEY_V), KEY(4, 3, KEY_W), KEY(5, 3, KEY_X),
++ KEY(2, 4, KEY_Y), KEY(3, 4, KEY_Z),
++
++ KEY(0, 4, KEY_DOT), /* . */
++ KEY(1, 4, KEY_CLOSE), /* @ */
++ KEY(4, 4, KEY_SLASH),
++ KEY(5, 4, KEY_BACKSLASH),
++ KEY(0, 5, KEY_HOME),
++ KEY(1, 5, KEY_LEFTSHIFT),
++ KEY(2, 5, KEY_SPACE),
++ KEY(3, 5, KEY_SPACE),
++ KEY(4, 5, KEY_ENTER),
++ KEY(5, 5, KEY_BACKSPACE),
++
++ KEY(0, 6, KEY_UP),
++ KEY(1, 6, KEY_DOWN),
++ KEY(2, 6, KEY_LEFT),
++ KEY(3, 6, KEY_RIGHT),
++ KEY(4, 6, KEY_SELECT),
++};
++
++struct pxa27x_keypad_platform_data mainstone_keypad_info = {
++ .matrix_key_rows = 6,
++ .matrix_key_cols = 7,
++ .matrix_key_map = mainstone_matrix_keys,
++ .matrix_key_map_size = ARRAY_SIZE(mainstone_matrix_keys),
++
++ .enable_rotary0 = 1,
++ .rotary0_up_key = KEY_UP,
++ .rotary0_down_key = KEY_DOWN,
++
++ .debounce_interval = 30,
++};
++
++static void __init mainstone_init_keypad(void)
++{
++ pxa_set_keypad_info(&mainstone_keypad_info);
++}
++#else
++static inline void mainstone_init_keypad(void) {}
++#endif
++
+ static void __init mainstone_init(void)
+ {
+ int SW7 = 0; /* FIXME: get from SCR (Mst doc section 3.2.1.1) */
+
++ pxa2xx_mfp_config(ARRAY_AND_SIZE(mainstone_pin_config));
++
+ mst_flash_data[0].width = (BOOT_DEF & 1) ? 2 : 4;
+ mst_flash_data[1].width = 4;
+
+@@ -480,31 +623,6 @@ static void __init mainstone_init(void)
+ */
+ ARB_CNTRL = ARB_CORE_PARK | 0x234;
+
+- /*
+- * On Mainstone, we route AC97_SYSCLK via GPIO45 to
+- * the audio daughter card
+- */
+- pxa_gpio_mode(GPIO45_SYSCLK_AC97_MD);
+-
+- GPSR(GPIO48_nPOE) =
+- GPIO_bit(GPIO48_nPOE) |
+- GPIO_bit(GPIO49_nPWE) |
+- GPIO_bit(GPIO50_nPIOR) |
+- GPIO_bit(GPIO51_nPIOW) |
+- GPIO_bit(GPIO85_nPCE_1) |
+- GPIO_bit(GPIO54_nPCE_2);
+-
+- pxa_gpio_mode(GPIO48_nPOE_MD);
+- pxa_gpio_mode(GPIO49_nPWE_MD);
+- pxa_gpio_mode(GPIO50_nPIOR_MD);
+- pxa_gpio_mode(GPIO51_nPIOW_MD);
+- pxa_gpio_mode(GPIO85_nPCE_1_MD);
+- pxa_gpio_mode(GPIO54_nPCE_2_MD);
+- pxa_gpio_mode(GPIO79_pSKTSEL_MD);
+- pxa_gpio_mode(GPIO55_nPREG_MD);
+- pxa_gpio_mode(GPIO56_nPWAIT_MD);
+- pxa_gpio_mode(GPIO57_nIOIS16_MD);
+-
+ platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+
+ /* reading Mainstone's "Virtual Configuration Register"
+@@ -520,6 +638,9 @@ static void __init mainstone_init(void)
+ pxa_set_mci_info(&mainstone_mci_platform_data);
+ pxa_set_ficp_info(&mainstone_ficp_platform_data);
+ pxa_set_ohci_info(&mainstone_ohci_platform_data);
++ pxa_set_i2c_info(NULL);
++
++ mainstone_init_keypad();
+ }
+
+
+@@ -537,23 +658,9 @@ static void __init mainstone_map_io(void)
+ pxa_map_io();
+ iotable_init(mainstone_io_desc, ARRAY_SIZE(mainstone_io_desc));
+
+- /* initialize sleep mode regs (wake-up sources, etc) */
+- PGSR0 = 0x00008800;
+- PGSR1 = 0x00000002;
+- PGSR2 = 0x0001FC00;
+- PGSR3 = 0x00001F81;
+- PWER = 0xC0000002;
+- PRER = 0x00000002;
+- PFER = 0x00000002;
+ /* for use I SRAM as framebuffer. */
+ PSLR |= 0xF04;
+ PCFR = 0x66;
+- /* For Keypad wakeup. */
+- KPC &=~KPC_ASACT;
+- KPC |=KPC_AS;
+- PKWR = 0x000FD000;
+- /* Need read PKWR back after set it. */
+- PKWR;
+ }
+
+ MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
+diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c
+new file mode 100644
+index 0000000..22097a1
+--- /dev/null
++++ b/arch/arm/mach-pxa/mfp-pxa2xx.c
+@@ -0,0 +1,245 @@
++/*
++ * linux/arch/arm/mach-pxa/mfp-pxa2xx.c
++ *
++ * PXA2xx pin mux configuration support
++ *
++ * The GPIOs on PXA2xx can be configured as one of many alternate
++ * functions, this is by concept samilar to the MFP configuration
++ * on PXA3xx, what's more important, the low power pin state and
++ * wakeup detection are also supported by the same framework.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/sysdev.h>
++
++#include <asm/arch/hardware.h>
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/mfp-pxa2xx.h>
++
++#include "generic.h"
++
++#define PGSR(x) __REG2(0x40F00020, ((x) & 0x60) >> 3)
++
++#define PWER_WE35 (1 << 24)
++
++struct gpio_desc {
++ unsigned valid : 1;
++ unsigned can_wakeup : 1;
++ unsigned keypad_gpio : 1;
++ unsigned int mask; /* bit mask in PWER or PKWR */
++ unsigned long config;
++};
++
++static struct gpio_desc gpio_desc[MFP_PIN_GPIO127 + 1];
++
++static int __mfp_config_gpio(unsigned gpio, unsigned long c)
++{
++ unsigned long gafr, mask = GPIO_bit(gpio);
++ int fn;
++
++ fn = MFP_AF(c);
++ if (fn > 3)
++ return -EINVAL;
++
++ /* alternate function and direction */
++ gafr = GAFR(gpio) & ~(0x3 << ((gpio & 0xf) * 2));
++ GAFR(gpio) = gafr | (fn << ((gpio & 0xf) * 2));
++
++ if (c & MFP_DIR_OUT)
++ GPDR(gpio) |= mask;
++ else
++ GPDR(gpio) &= ~mask;
++
++ /* low power state */
++ switch (c & MFP_LPM_STATE_MASK) {
++ case MFP_LPM_DRIVE_HIGH:
++ PGSR(gpio) |= mask;
++ break;
++ case MFP_LPM_DRIVE_LOW:
++ PGSR(gpio) &= ~mask;
++ break;
++ case MFP_LPM_INPUT:
++ break;
++ default:
++ pr_warning("%s: invalid low power state for GPIO%d\n",
++ __func__, gpio);
++ return -EINVAL;
++ }
++
++ /* give early warning if MFP_LPM_CAN_WAKEUP is set on the
++ * configurations of those pins not able to wakeup
++ */
++ if ((c & MFP_LPM_CAN_WAKEUP) && !gpio_desc[gpio].can_wakeup) {
++ pr_warning("%s: GPIO%d unable to wakeup\n",
++ __func__, gpio);
++ return -EINVAL;
++ }
++
++ if ((c & MFP_LPM_CAN_WAKEUP) && (c & MFP_DIR_OUT)) {
++ pr_warning("%s: output GPIO%d unable to wakeup\n",
++ __func__, gpio);
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++void pxa2xx_mfp_config(unsigned long *mfp_cfgs, int num)
++{
++ unsigned long flags;
++ unsigned long *c;
++ int i, gpio;
++
++ for (i = 0, c = mfp_cfgs; i < num; i++, c++) {
++
++ gpio = mfp_to_gpio(MFP_PIN(*c));
++
++ if (!gpio_desc[gpio].valid) {
++ pr_warning("%s: GPIO%d is invalid pin\n",
++ __func__, gpio);
++ continue;
++ }
++
++ local_irq_save(flags);
++
++ gpio_desc[gpio].config = *c;
++ __mfp_config_gpio(gpio, *c);
++
++ local_irq_restore(flags);
++ }
++}
++
++int gpio_set_wake(unsigned int gpio, unsigned int on)
++{
++ struct gpio_desc *d;
++ unsigned long c;
++
++ if (gpio > mfp_to_gpio(MFP_PIN_GPIO127))
++ return -EINVAL;
++
++ d = &gpio_desc[gpio];
++ c = d->config;
++
++ if (!d->valid)
++ return -EINVAL;
++
++ if (d->keypad_gpio)
++ return -EINVAL;
++
++ if (d->can_wakeup && (c & MFP_LPM_CAN_WAKEUP)) {
++ if (on) {
++ PWER |= d->mask;
++
++ if (c & MFP_LPM_EDGE_RISE)
++ PRER |= d->mask;
++ else
++ PRER &= ~d->mask;
++
++ if (c & MFP_LPM_EDGE_FALL)
++ PFER |= d->mask;
++ else
++ PFER &= ~d->mask;
++ } else {
++ PWER &= ~d->mask;
++ PRER &= ~d->mask;
++ PFER &= ~d->mask;
++ }
++ }
++ return 0;
++}
++
++#ifdef CONFIG_PXA25x
++static int __init pxa25x_mfp_init(void)
++{
++ int i;
++
++ if (cpu_is_pxa25x()) {
++ for (i = 0; i <= 84; i++)
++ gpio_desc[i].valid = 1;
++
++ for (i = 0; i <= 15; i++) {
++ gpio_desc[i].can_wakeup = 1;
++ gpio_desc[i].mask = GPIO_bit(i);
++ }
++ }
++
++ return 0;
++}
++postcore_initcall(pxa25x_mfp_init);
++#endif /* CONFIG_PXA25x */
++
++#ifdef CONFIG_PXA27x
++static int pxa27x_pkwr_gpio[] = {
++ 13, 16, 17, 34, 36, 37, 38, 39, 90, 91, 93, 94,
++ 95, 96, 97, 98, 99, 100, 101, 102
++};
++
++int keypad_set_wake(unsigned int on)
++{
++ unsigned int i, gpio, mask = 0;
++
++ if (!on) {
++ PKWR = 0;
++ return 0;
++ }
++
++ for (i = 0; i < ARRAY_SIZE(pxa27x_pkwr_gpio); i++) {
++
++ gpio = pxa27x_pkwr_gpio[i];
++
++ if (gpio_desc[gpio].config & MFP_LPM_CAN_WAKEUP)
++ mask |= gpio_desc[gpio].mask;
++ }
++
++ PKWR = mask;
++ return 0;
++}
++
++static int __init pxa27x_mfp_init(void)
++{
++ int i, gpio;
++
++ if (cpu_is_pxa27x()) {
++ for (i = 0; i <= 120; i++) {
++ /* skip GPIO2, 5, 6, 7, 8, they are not
++ * valid pins allow configuration
++ */
++ if (i == 2 || i == 5 || i == 6 ||
++ i == 7 || i == 8)
++ continue;
++
++ gpio_desc[i].valid = 1;
++ }
++
++ /* Keypad GPIOs */
++ for (i = 0; i < ARRAY_SIZE(pxa27x_pkwr_gpio); i++) {
++ gpio = pxa27x_pkwr_gpio[i];
++ gpio_desc[gpio].can_wakeup = 1;
++ gpio_desc[gpio].keypad_gpio = 1;
++ gpio_desc[gpio].mask = 1 << i;
++ }
++
++ /* Overwrite GPIO13 as a PWER wakeup source */
++ for (i = 0; i <= 15; i++) {
++ /* skip GPIO2, 5, 6, 7, 8 */
++ if (GPIO_bit(i) & 0x1e4)
++ continue;
++
++ gpio_desc[i].can_wakeup = 1;
++ gpio_desc[i].mask = GPIO_bit(i);
++ }
++
++ gpio_desc[35].can_wakeup = 1;
++ gpio_desc[35].mask = PWER_WE35;
++ }
++
++ return 0;
++}
++postcore_initcall(pxa27x_mfp_init);
++#endif /* CONFIG_PXA27x */
+diff --git a/arch/arm/mach-pxa/mfp-pxa3xx.c b/arch/arm/mach-pxa/mfp-pxa3xx.c
+new file mode 100644
+index 0000000..3a5b0fc
+--- /dev/null
++++ b/arch/arm/mach-pxa/mfp-pxa3xx.c
+@@ -0,0 +1,255 @@
++/*
++ * linux/arch/arm/mach-pxa/mfp.c
++ *
++ * PXA3xx Multi-Function Pin Support
++ *
++ * Copyright (C) 2007 Marvell Internation Ltd.
++ *
++ * 2007-08-21: eric miao <eric.miao at marvell.com>
++ * initial version
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/sysdev.h>
++
++#include <asm/hardware.h>
++#include <asm/arch/mfp.h>
++#include <asm/arch/mfp-pxa3xx.h>
++#include <asm/arch/pxa3xx-regs.h>
++
++/* mfp_spin_lock is used to ensure that MFP register configuration
++ * (most likely a read-modify-write operation) is atomic, and that
++ * mfp_table[] is consistent
++ */
++static DEFINE_SPINLOCK(mfp_spin_lock);
++
++static void __iomem *mfpr_mmio_base = (void __iomem *)&__REG(MFPR_BASE);
++
++struct pxa3xx_mfp_pin {
++ unsigned long config; /* -1 for not configured */
++ unsigned long mfpr_off; /* MFPRxx Register offset */
++ unsigned long mfpr_run; /* Run-Mode Register Value */
++ unsigned long mfpr_lpm; /* Low Power Mode Register Value */
++};
++
++static struct pxa3xx_mfp_pin mfp_table[MFP_PIN_MAX];
++
++/* mapping of MFP_LPM_* definitions to MFPR_LPM_* register bits */
++static const unsigned long mfpr_lpm[] = {
++ MFPR_LPM_INPUT,
++ MFPR_LPM_DRIVE_LOW,
++ MFPR_LPM_DRIVE_HIGH,
++ MFPR_LPM_PULL_LOW,
++ MFPR_LPM_PULL_HIGH,
++ MFPR_LPM_FLOAT,
++};
++
++/* mapping of MFP_PULL_* definitions to MFPR_PULL_* register bits */
++static const unsigned long mfpr_pull[] = {
++ MFPR_PULL_NONE,
++ MFPR_PULL_LOW,
++ MFPR_PULL_HIGH,
++ MFPR_PULL_BOTH,
++};
++
++/* mapping of MFP_LPM_EDGE_* definitions to MFPR_EDGE_* register bits */
++static const unsigned long mfpr_edge[] = {
++ MFPR_EDGE_NONE,
++ MFPR_EDGE_RISE,
++ MFPR_EDGE_FALL,
++ MFPR_EDGE_BOTH,
++};
++
++#define mfpr_readl(off) \
++ __raw_readl(mfpr_mmio_base + (off))
++
++#define mfpr_writel(off, val) \
++ __raw_writel(val, mfpr_mmio_base + (off))
++
++#define mfp_configured(p) ((p)->config != -1)
++
++/*
++ * perform a read-back of any MFPR register to make sure the
++ * previous writings are finished
++ */
++#define mfpr_sync() (void)__raw_readl(mfpr_mmio_base + 0)
++
++static inline void __mfp_config_run(struct pxa3xx_mfp_pin *p)
++{
++ if (mfp_configured(p))
++ mfpr_writel(p->mfpr_off, p->mfpr_run);
++}
++
++static inline void __mfp_config_lpm(struct pxa3xx_mfp_pin *p)
++{
++ if (mfp_configured(p)) {
++ unsigned long mfpr_clr = (p->mfpr_run & ~MFPR_EDGE_BOTH) | MFPR_EDGE_CLEAR;
++ if (mfpr_clr != p->mfpr_run)
++ mfpr_writel(p->mfpr_off, mfpr_clr);
++ if (p->mfpr_lpm != mfpr_clr)
++ mfpr_writel(p->mfpr_off, p->mfpr_lpm);
++ }
++}
++
++void pxa3xx_mfp_config(unsigned long *mfp_cfgs, int num)
++{
++ unsigned long flags;
++ int i;
++
++ spin_lock_irqsave(&mfp_spin_lock, flags);
++
++ for (i = 0; i < num; i++, mfp_cfgs++) {
++ unsigned long tmp, c = *mfp_cfgs;
++ struct pxa3xx_mfp_pin *p;
++ int pin, af, drv, lpm, edge, pull;
++
++ pin = MFP_PIN(c);
++ BUG_ON(pin >= MFP_PIN_MAX);
++ p = &mfp_table[pin];
++
++ af = MFP_AF(c);
++ drv = MFP_DS(c);
++ lpm = MFP_LPM_STATE(c);
++ edge = MFP_LPM_EDGE(c);
++ pull = MFP_PULL(c);
++
++ /* run-mode pull settings will conflict with MFPR bits of
++ * low power mode state, calculate mfpr_run and mfpr_lpm
++ * individually if pull != MFP_PULL_NONE
++ */
++ tmp = MFPR_AF_SEL(af) | MFPR_DRIVE(drv);
++
++ if (likely(pull == MFP_PULL_NONE)) {
++ p->mfpr_run = tmp | mfpr_lpm[lpm] | mfpr_edge[edge];
++ p->mfpr_lpm = p->mfpr_run;
++ } else {
++ p->mfpr_lpm = tmp | mfpr_lpm[lpm] | mfpr_edge[edge];
++ p->mfpr_run = tmp | mfpr_pull[pull];
++ }
++
++ p->config = c; __mfp_config_run(p);
++ }
++
++ mfpr_sync();
++ spin_unlock_irqrestore(&mfp_spin_lock, flags);
++}
++
++unsigned long pxa3xx_mfp_read(int mfp)
++{
++ unsigned long val, flags;
++
++ BUG_ON(mfp >= MFP_PIN_MAX);
++
++ spin_lock_irqsave(&mfp_spin_lock, flags);
++ val = mfpr_readl(mfp_table[mfp].mfpr_off);
++ spin_unlock_irqrestore(&mfp_spin_lock, flags);
++
++ return val;
++}
++
++void pxa3xx_mfp_write(int mfp, unsigned long val)
++{
++ unsigned long flags;
++
++ BUG_ON(mfp >= MFP_PIN_MAX);
++
++ spin_lock_irqsave(&mfp_spin_lock, flags);
++ mfpr_writel(mfp_table[mfp].mfpr_off, val);
++ mfpr_sync();
++ spin_unlock_irqrestore(&mfp_spin_lock, flags);
++}
++
++void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *map)
++{
++ struct pxa3xx_mfp_addr_map *p;
++ unsigned long offset, flags;
++ int i;
++
++ spin_lock_irqsave(&mfp_spin_lock, flags);
++
++ for (p = map; p->start != MFP_PIN_INVALID; p++) {
++ offset = p->offset;
++ i = p->start;
++
++ do {
++ mfp_table[i].mfpr_off = offset;
++ mfp_table[i].mfpr_run = 0;
++ mfp_table[i].mfpr_lpm = 0;
++ offset += 4; i++;
++ } while ((i <= p->end) && (p->end != -1));
++ }
++
++ spin_unlock_irqrestore(&mfp_spin_lock, flags);
++}
++
++void __init pxa3xx_init_mfp(void)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(mfp_table); i++)
++ mfp_table[i].config = -1;
++}
++
++#ifdef CONFIG_PM
++/*
++ * Configure the MFPs appropriately for suspend/resume.
++ * FIXME: this should probably depend on which system state we're
++ * entering - for instance, we might not want to place MFP pins in
++ * a pull-down mode if they're an active low chip select, and we're
++ * just entering standby.
++ */
++static int pxa3xx_mfp_suspend(struct sys_device *d, pm_message_t state)
++{
++ int pin;
++
++ for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++) {
++ struct pxa3xx_mfp_pin *p = &mfp_table[pin];
++ __mfp_config_lpm(p);
++ }
++ return 0;
++}
++
++static int pxa3xx_mfp_resume(struct sys_device *d)
++{
++ int pin;
++
++ for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++) {
++ struct pxa3xx_mfp_pin *p = &mfp_table[pin];
++ __mfp_config_run(p);
++ }
++
++ /* clear RDH bit when MFP settings are restored
++ *
++ * NOTE: the last 3 bits DxS are write-1-to-clear so carefully
++ * preserve them here in case they will be referenced later
++ */
++ ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S);
++
++ return 0;
++}
++#else
++#define pxa3xx_mfp_suspend NULL
++#define pxa3xx_mfp_resume NULL
++#endif
++
++struct sysdev_class pxa3xx_mfp_sysclass = {
++ .name = "mfp",
++ .suspend = pxa3xx_mfp_suspend,
++ .resume = pxa3xx_mfp_resume,
++};
++
++static int __init mfp_init_devicefs(void)
++{
++ if (cpu_is_pxa3xx())
++ return sysdev_class_register(&pxa3xx_mfp_sysclass);
++
++ return 0;
++}
++postcore_initcall(mfp_init_devicefs);
+diff --git a/arch/arm/mach-pxa/mfp.c b/arch/arm/mach-pxa/mfp.c
+deleted file mode 100644
+index f5809ad..0000000
+--- a/arch/arm/mach-pxa/mfp.c
++++ /dev/null
+@@ -1,255 +0,0 @@
+-/*
+- * linux/arch/arm/mach-pxa/mfp.c
+- *
+- * PXA3xx Multi-Function Pin Support
+- *
+- * Copyright (C) 2007 Marvell Internation Ltd.
+- *
+- * 2007-08-21: eric miao <eric.miao at marvell.com>
+- * initial version
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#include <linux/module.h>
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/io.h>
+-#include <linux/sysdev.h>
+-
+-#include <asm/hardware.h>
+-#include <asm/arch/mfp.h>
+-#include <asm/arch/mfp-pxa3xx.h>
+-#include <asm/arch/pxa3xx-regs.h>
+-
+-/* mfp_spin_lock is used to ensure that MFP register configuration
+- * (most likely a read-modify-write operation) is atomic, and that
+- * mfp_table[] is consistent
+- */
+-static DEFINE_SPINLOCK(mfp_spin_lock);
+-
+-static void __iomem *mfpr_mmio_base = (void __iomem *)&__REG(MFPR_BASE);
+-
+-struct pxa3xx_mfp_pin {
+- unsigned long config; /* -1 for not configured */
+- unsigned long mfpr_off; /* MFPRxx Register offset */
+- unsigned long mfpr_run; /* Run-Mode Register Value */
+- unsigned long mfpr_lpm; /* Low Power Mode Register Value */
+-};
+-
+-static struct pxa3xx_mfp_pin mfp_table[MFP_PIN_MAX];
+-
+-/* mapping of MFP_LPM_* definitions to MFPR_LPM_* register bits */
+-const static unsigned long mfpr_lpm[] = {
+- MFPR_LPM_INPUT,
+- MFPR_LPM_DRIVE_LOW,
+- MFPR_LPM_DRIVE_HIGH,
+- MFPR_LPM_PULL_LOW,
+- MFPR_LPM_PULL_HIGH,
+- MFPR_LPM_FLOAT,
+-};
+-
+-/* mapping of MFP_PULL_* definitions to MFPR_PULL_* register bits */
+-const static unsigned long mfpr_pull[] = {
+- MFPR_PULL_NONE,
+- MFPR_PULL_LOW,
+- MFPR_PULL_HIGH,
+- MFPR_PULL_BOTH,
+-};
+-
+-/* mapping of MFP_LPM_EDGE_* definitions to MFPR_EDGE_* register bits */
+-const static unsigned long mfpr_edge[] = {
+- MFPR_EDGE_NONE,
+- MFPR_EDGE_RISE,
+- MFPR_EDGE_FALL,
+- MFPR_EDGE_BOTH,
+-};
+-
+-#define mfpr_readl(off) \
+- __raw_readl(mfpr_mmio_base + (off))
+-
+-#define mfpr_writel(off, val) \
+- __raw_writel(val, mfpr_mmio_base + (off))
+-
+-#define mfp_configured(p) ((p)->config != -1)
+-
+-/*
+- * perform a read-back of any MFPR register to make sure the
+- * previous writings are finished
+- */
+-#define mfpr_sync() (void)__raw_readl(mfpr_mmio_base + 0)
+-
+-static inline void __mfp_config_run(struct pxa3xx_mfp_pin *p)
+-{
+- if (mfp_configured(p))
+- mfpr_writel(p->mfpr_off, p->mfpr_run);
+-}
+-
+-static inline void __mfp_config_lpm(struct pxa3xx_mfp_pin *p)
+-{
+- if (mfp_configured(p)) {
+- unsigned long mfpr_clr = (p->mfpr_run & ~MFPR_EDGE_BOTH) | MFPR_EDGE_CLEAR;
+- if (mfpr_clr != p->mfpr_run)
+- mfpr_writel(p->mfpr_off, mfpr_clr);
+- if (p->mfpr_lpm != mfpr_clr)
+- mfpr_writel(p->mfpr_off, p->mfpr_lpm);
+- }
+-}
+-
+-void pxa3xx_mfp_config(unsigned long *mfp_cfgs, int num)
+-{
+- unsigned long flags;
+- int i;
+-
+- spin_lock_irqsave(&mfp_spin_lock, flags);
+-
+- for (i = 0; i < num; i++, mfp_cfgs++) {
+- unsigned long tmp, c = *mfp_cfgs;
+- struct pxa3xx_mfp_pin *p;
+- int pin, af, drv, lpm, edge, pull;
+-
+- pin = MFP_PIN(c);
+- BUG_ON(pin >= MFP_PIN_MAX);
+- p = &mfp_table[pin];
+-
+- af = MFP_AF(c);
+- drv = MFP_DS(c);
+- lpm = MFP_LPM_STATE(c);
+- edge = MFP_LPM_EDGE(c);
+- pull = MFP_PULL(c);
+-
+- /* run-mode pull settings will conflict with MFPR bits of
+- * low power mode state, calculate mfpr_run and mfpr_lpm
+- * individually if pull != MFP_PULL_NONE
+- */
+- tmp = MFPR_AF_SEL(af) | MFPR_DRIVE(drv);
+-
+- if (likely(pull == MFP_PULL_NONE)) {
+- p->mfpr_run = tmp | mfpr_lpm[lpm] | mfpr_edge[edge];
+- p->mfpr_lpm = p->mfpr_run;
+- } else {
+- p->mfpr_lpm = tmp | mfpr_lpm[lpm] | mfpr_edge[edge];
+- p->mfpr_run = tmp | mfpr_pull[pull];
+- }
+-
+- p->config = c; __mfp_config_run(p);
+- }
+-
+- mfpr_sync();
+- spin_unlock_irqrestore(&mfp_spin_lock, flags);
+-}
+-
+-unsigned long pxa3xx_mfp_read(int mfp)
+-{
+- unsigned long val, flags;
+-
+- BUG_ON(mfp >= MFP_PIN_MAX);
+-
+- spin_lock_irqsave(&mfp_spin_lock, flags);
+- val = mfpr_readl(mfp_table[mfp].mfpr_off);
+- spin_unlock_irqrestore(&mfp_spin_lock, flags);
+-
+- return val;
+-}
+-
+-void pxa3xx_mfp_write(int mfp, unsigned long val)
+-{
+- unsigned long flags;
+-
+- BUG_ON(mfp >= MFP_PIN_MAX);
+-
+- spin_lock_irqsave(&mfp_spin_lock, flags);
+- mfpr_writel(mfp_table[mfp].mfpr_off, val);
+- mfpr_sync();
+- spin_unlock_irqrestore(&mfp_spin_lock, flags);
+-}
+-
+-void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *map)
+-{
+- struct pxa3xx_mfp_addr_map *p;
+- unsigned long offset, flags;
+- int i;
+-
+- spin_lock_irqsave(&mfp_spin_lock, flags);
+-
+- for (p = map; p->start != MFP_PIN_INVALID; p++) {
+- offset = p->offset;
+- i = p->start;
+-
+- do {
+- mfp_table[i].mfpr_off = offset;
+- mfp_table[i].mfpr_run = 0;
+- mfp_table[i].mfpr_lpm = 0;
+- offset += 4; i++;
+- } while ((i <= p->end) && (p->end != -1));
+- }
+-
+- spin_unlock_irqrestore(&mfp_spin_lock, flags);
+-}
+-
+-void __init pxa3xx_init_mfp(void)
+-{
+- int i;
+-
+- for (i = 0; i < ARRAY_SIZE(mfp_table); i++)
+- mfp_table[i].config = -1;
+-}
+-
+-#ifdef CONFIG_PM
+-/*
+- * Configure the MFPs appropriately for suspend/resume.
+- * FIXME: this should probably depend on which system state we're
+- * entering - for instance, we might not want to place MFP pins in
+- * a pull-down mode if they're an active low chip select, and we're
+- * just entering standby.
+- */
+-static int pxa3xx_mfp_suspend(struct sys_device *d, pm_message_t state)
+-{
+- int pin;
+-
+- for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++) {
+- struct pxa3xx_mfp_pin *p = &mfp_table[pin];
+- __mfp_config_lpm(p);
+- }
+- return 0;
+-}
+-
+-static int pxa3xx_mfp_resume(struct sys_device *d)
+-{
+- int pin;
+-
+- for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++) {
+- struct pxa3xx_mfp_pin *p = &mfp_table[pin];
+- __mfp_config_run(p);
+- }
+-
+- /* clear RDH bit when MFP settings are restored
+- *
+- * NOTE: the last 3 bits DxS are write-1-to-clear so carefully
+- * preserve them here in case they will be referenced later
+- */
+- ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S);
+-
+- return 0;
+-}
+-
+-static struct sysdev_class mfp_sysclass = {
+- .name = "mfp",
+- .suspend = pxa3xx_mfp_suspend,
+- .resume = pxa3xx_mfp_resume,
+-};
+-
+-static struct sys_device mfp_device = {
+- .id = 0,
+- .cls = &mfp_sysclass,
+-};
+-
+-static int __init mfp_init_devicefs(void)
+-{
+- sysdev_class_register(&mfp_sysclass);
+- return sysdev_register(&mfp_device);
+-}
+-device_initcall(mfp_init_devicefs);
+-#endif
+diff --git a/arch/arm/mach-pxa/pcm027.c b/arch/arm/mach-pxa/pcm027.c
+index c14696b..3b945eb 100644
+--- a/arch/arm/mach-pxa/pcm027.c
++++ b/arch/arm/mach-pxa/pcm027.c
+@@ -29,6 +29,7 @@
+ #include <asm/mach/arch.h>
+ #include <asm/arch/hardware.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/pxa2xx-regs.h>
+ #include <asm/arch/pxa2xx_spi.h>
+ #include <asm/arch/pcm027.h>
+diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
+index 3dda16a..e6be9d0 100644
+--- a/arch/arm/mach-pxa/pcm990-baseboard.c
++++ b/arch/arm/mach-pxa/pcm990-baseboard.c
+@@ -23,8 +23,16 @@
+ #include <linux/irq.h>
+ #include <linux/platform_device.h>
+ #include <linux/ide.h>
++#include <linux/i2c.h>
++
++#include <media/soc_camera.h>
++
++#include <asm/gpio.h>
++#include <asm/arch/i2c.h>
++#include <asm/arch/camera.h>
+ #include <asm/mach/map.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/mmc.h>
+ #include <asm/arch/ohci.h>
+ #include <asm/arch/pcm990_baseboard.h>
+@@ -258,6 +266,76 @@ static struct pxaohci_platform_data pcm990_ohci_platform_data = {
+ };
+
+ /*
++ * PXA27x Camera specific stuff
++ */
++#if defined(CONFIG_VIDEO_PXA27x) || defined(CONFIG_VIDEO_PXA27x_MODULE)
++static int pcm990_pxacamera_init(struct device *dev)
++{
++ pxa_gpio_mode(GPIO98_CIF_DD_0_MD);
++ pxa_gpio_mode(GPIO105_CIF_DD_1_MD);
++ pxa_gpio_mode(GPIO104_CIF_DD_2_MD);
++ pxa_gpio_mode(GPIO103_CIF_DD_3_MD);
++ pxa_gpio_mode(GPIO95_CIF_DD_4_MD);
++ pxa_gpio_mode(GPIO94_CIF_DD_5_MD);
++ pxa_gpio_mode(GPIO93_CIF_DD_6_MD);
++ pxa_gpio_mode(GPIO108_CIF_DD_7_MD);
++ pxa_gpio_mode(GPIO107_CIF_DD_8_MD);
++ pxa_gpio_mode(GPIO106_CIF_DD_9_MD);
++ pxa_gpio_mode(GPIO42_CIF_MCLK_MD);
++ pxa_gpio_mode(GPIO45_CIF_PCLK_MD);
++ pxa_gpio_mode(GPIO43_CIF_FV_MD);
++ pxa_gpio_mode(GPIO44_CIF_LV_MD);
++
++ return 0;
++}
++
++/*
++ * CICR4: PCLK_EN: Pixel clock is supplied by the sensor
++ * MCLK_EN: Master clock is generated by PXA
++ * PCP: Data sampled on the falling edge of pixel clock
++ */
++struct pxacamera_platform_data pcm990_pxacamera_platform_data = {
++ .init = pcm990_pxacamera_init,
++ .flags = PXA_CAMERA_MASTER | PXA_CAMERA_DATAWIDTH_8 | PXA_CAMERA_DATAWIDTH_10 |
++ PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN/* | PXA_CAMERA_PCP*/,
++ .mclk_10khz = 1000,
++};
++
++#include <linux/i2c/pca953x.h>
++
++static struct pca953x_platform_data pca9536_data = {
++ .gpio_base = NR_BUILTIN_GPIO + 1,
++};
++
++static struct soc_camera_link iclink[] = {
++ {
++ .bus_id = 0, /* Must match with the camera ID above */
++ .gpio = NR_BUILTIN_GPIO + 1,
++ }, {
++ .bus_id = 0, /* Must match with the camera ID above */
++ }
++};
++
++/* Board I2C devices. */
++static struct i2c_board_info __initdata pcm990_i2c_devices[] = {
++ {
++ /* Must initialize before the camera(s) */
++ I2C_BOARD_INFO("pca953x", 0x41),
++ .type = "pca9536",
++ .platform_data = &pca9536_data,
++ }, {
++ I2C_BOARD_INFO("mt9v022", 0x48),
++ .type = "mt9v022",
++ .platform_data = &iclink[0], /* With extender */
++ }, {
++ I2C_BOARD_INFO("mt9m001", 0x5d),
++ .type = "mt9m001",
++ .platform_data = &iclink[0], /* With extender */
++ },
++};
++#endif /* CONFIG_VIDEO_PXA27x ||CONFIG_VIDEO_PXA27x_MODULE */
++
++/*
+ * AC97 support
+ * Note: The connected AC97 mixer also reports interrupts at PCM990_AC97_IRQ
+ */
+@@ -326,5 +404,14 @@ void __init pcm990_baseboard_init(void)
+ /* USB host */
+ pxa_set_ohci_info(&pcm990_ohci_platform_data);
+
++ pxa_set_i2c_info(NULL);
++
++#if defined(CONFIG_VIDEO_PXA27x) || defined(CONFIG_VIDEO_PXA27x_MODULE)
++ pxa_set_camera_info(&pcm990_pxacamera_platform_data);
++
++ i2c_register_board_info(0, pcm990_i2c_devices,
++ ARRAY_SIZE(pcm990_i2c_devices));
++#endif
++
+ printk(KERN_INFO"PCM-990 Evaluation baseboard initialized\n");
+ }
+diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
+index 209eabf..ca5ac19 100644
+--- a/arch/arm/mach-pxa/poodle.c
++++ b/arch/arm/mach-pxa/poodle.c
+@@ -32,6 +32,7 @@
+ #include <asm/mach/irq.h>
+
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/mmc.h>
+ #include <asm/arch/udc.h>
+ #include <asm/arch/irda.h>
+diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
+index 599e53f..d9b5450 100644
+--- a/arch/arm/mach-pxa/pxa25x.c
++++ b/arch/arm/mach-pxa/pxa25x.c
+@@ -26,6 +26,7 @@
+ #include <asm/hardware.h>
+ #include <asm/arch/irqs.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/mfp-pxa25x.h>
+ #include <asm/arch/pm.h>
+ #include <asm/arch/dma.h>
+
+@@ -129,6 +130,8 @@ static struct clk pxa25x_clks[] = {
+ INIT_CKEN("SSPCLK", NSSP, 3686400, 0, &pxa25x_device_nssp.dev),
+ INIT_CKEN("SSPCLK", ASSP, 3686400, 0, &pxa25x_device_assp.dev),
+
++ INIT_CKEN("AC97CLK", AC97, 24576000, 0, NULL),
++
+ /*
+ INIT_CKEN("PWMCLK", PWM0, 3686400, 0, NULL),
+ INIT_CKEN("PWMCLK", PWM0, 3686400, 0, NULL),
+@@ -228,24 +231,10 @@ static inline void pxa25x_init_pm(void) {}
+ static int pxa25x_set_wake(unsigned int irq, unsigned int on)
+ {
+ int gpio = IRQ_TO_GPIO(irq);
+- uint32_t gpio_bit, mask = 0;
+-
+- if (gpio >= 0 && gpio <= 15) {
+- gpio_bit = GPIO_bit(gpio);
+- mask = gpio_bit;
+- if (on) {
+- if (GRER(gpio) | gpio_bit)
+- PRER |= gpio_bit;
+- else
+- PRER &= ~gpio_bit;
+-
+- if (GFER(gpio) | gpio_bit)
+- PFER |= gpio_bit;
+- else
+- PFER &= ~gpio_bit;
+- }
+- goto set_pwer;
+- }
++ uint32_t mask = 0;
++
++ if (gpio >= 0 && gpio < 85)
++ return gpio_set_wake(gpio, on);
+
+ if (irq == IRQ_RTCAlrm) {
+ mask = PWER_RTC;
+@@ -265,9 +254,8 @@ set_pwer:
+
+ void __init pxa25x_init_irq(void)
+ {
+- pxa_init_irq_low();
+- pxa_init_irq_gpio(85);
+- pxa_init_irq_set_wake(pxa25x_set_wake);
++ pxa_init_irq(32, pxa25x_set_wake);
++ pxa_init_gpio(85, pxa25x_set_wake);
+ }
+
+ static struct platform_device *pxa25x_devices[] __initdata = {
+@@ -325,4 +313,4 @@ static int __init pxa25x_init(void)
+ return ret;
+ }
+
+-subsys_initcall(pxa25x_init);
++postcore_initcall(pxa25x_init);
+diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
+index 46a951c..7a2449d 100644
+--- a/arch/arm/mach-pxa/pxa27x.c
++++ b/arch/arm/mach-pxa/pxa27x.c
+@@ -23,6 +23,7 @@
+ #include <asm/arch/irqs.h>
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/arch/pxa2xx-regs.h>
++#include <asm/arch/mfp-pxa27x.h>
+ #include <asm/arch/ohci.h>
+ #include <asm/arch/pm.h>
+ #include <asm/arch/dma.h>
+@@ -151,12 +152,15 @@ static struct clk pxa27x_clks[] = {
+
+ INIT_CKEN("USBCLK", USBHOST, 48000000, 0, &pxa27x_device_ohci.dev),
+ INIT_CKEN("I2CCLK", PWRI2C, 13000000, 0, &pxa27x_device_i2c_power.dev),
+- INIT_CKEN("KBDCLK", KEYPAD, 32768, 0, NULL),
++ INIT_CKEN("KBDCLK", KEYPAD, 32768, 0, &pxa27x_device_keypad.dev),
+
+ INIT_CKEN("SSPCLK", SSP1, 13000000, 0, &pxa27x_device_ssp1.dev),
+ INIT_CKEN("SSPCLK", SSP2, 13000000, 0, &pxa27x_device_ssp2.dev),
+ INIT_CKEN("SSPCLK", SSP3, 13000000, 0, &pxa27x_device_ssp3.dev),
+
++ INIT_CKEN("AC97CLK", AC97, 24576000, 0, NULL),
++ INIT_CKEN("AC97CONFCLK", AC97CONF, 24576000, 0, NULL),
++
+ /*
+ INIT_CKEN("PWMCLK", PWM0, 13000000, 0, NULL),
+ INIT_CKEN("MSLCLK", MSL, 48000000, 0, NULL),
+@@ -283,37 +287,16 @@ static inline void pxa27x_init_pm(void) {}
+ /* PXA27x: Various gpios can issue wakeup events. This logic only
+ * handles the simple cases, not the WEMUX2 and WEMUX3 options
+ */
+-#define PXA27x_GPIO_NOWAKE_MASK \
+- ((1 << 8) | (1 << 7) | (1 << 6) | (1 << 5) | (1 << 2))
+-#define WAKEMASK(gpio) \
+- (((gpio) <= 15) \
+- ? ((1 << (gpio)) & ~PXA27x_GPIO_NOWAKE_MASK) \
+- : ((gpio == 35) ? (1 << 24) : 0))
+-
+ static int pxa27x_set_wake(unsigned int irq, unsigned int on)
+ {
+ int gpio = IRQ_TO_GPIO(irq);
+ uint32_t mask;
+
+- if ((gpio >= 0 && gpio <= 15) || (gpio == 35)) {
+- if (WAKEMASK(gpio) == 0)
+- return -EINVAL;
+-
+- mask = WAKEMASK(gpio);
+-
+- if (on) {
+- if (GRER(gpio) | GPIO_bit(gpio))
+- PRER |= mask;
+- else
+- PRER &= ~mask;
++ if (gpio >= 0 && gpio < 128)
++ return gpio_set_wake(gpio, on);
+
+- if (GFER(gpio) | GPIO_bit(gpio))
+- PFER |= mask;
+- else
+- PFER &= ~mask;
+- }
+- goto set_pwer;
+- }
++ if (irq == IRQ_KEYPAD)
++ return keypad_set_wake(on);
+
+ switch (irq) {
+ case IRQ_RTCAlrm:
+@@ -326,7 +309,6 @@ static int pxa27x_set_wake(unsigned int irq, unsigned int on)
+ return -EINVAL;
+ }
+
+-set_pwer:
+ if (on)
+ PWER |= mask;
+ else
+@@ -337,10 +319,8 @@ set_pwer:
+
+ void __init pxa27x_init_irq(void)
+ {
+- pxa_init_irq_low();
+- pxa_init_irq_high();
+- pxa_init_irq_gpio(128);
+- pxa_init_irq_set_wake(pxa27x_set_wake);
++ pxa_init_irq(34, pxa27x_set_wake);
++ pxa_init_gpio(128, pxa27x_set_wake);
+ }
+
+ /*
+@@ -386,10 +366,6 @@ static struct platform_device *devices[] __initdata = {
+
+ static struct sys_device pxa27x_sysdev[] = {
+ {
+- .id = 0,
+- .cls = &pxa_irq_sysclass,
+- }, {
+- .id = 1,
+ .cls = &pxa_irq_sysclass,
+ }, {
+ .cls = &pxa_gpio_sysclass,
+@@ -420,4 +396,4 @@ static int __init pxa27x_init(void)
+ return ret;
+ }
+
+-subsys_initcall(pxa27x_init);
++postcore_initcall(pxa27x_init);
+diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
+index 35f25fd..dde355e 100644
+--- a/arch/arm/mach-pxa/pxa3xx.c
++++ b/arch/arm/mach-pxa/pxa3xx.c
+@@ -110,6 +110,25 @@ unsigned int pxa3xx_get_memclk_frequency_10khz(void)
+ }
+
+ /*
++ * Return the current AC97 clock frequency.
++ */
++static unsigned long clk_pxa3xx_ac97_getrate(struct clk *clk)
++{
++ unsigned long rate = 312000000;
++ unsigned long ac97_div;
++
++ ac97_div = AC97_DIV;
++
++ /* This may loose precision for some rates but won't for the
++ * standard 24.576MHz.
++ */
++ rate /= (ac97_div >> 12) & 0x7fff;
++ rate *= (ac97_div & 0xfff);
++
++ return rate;
++}
++
++/*
+ * Return the current HSIO bus clock frequency
+ */
+ static unsigned long clk_pxa3xx_hsio_getrate(struct clk *clk)
+@@ -156,6 +175,27 @@ static const struct clkops clk_pxa3xx_hsio_ops = {
+ .getrate = clk_pxa3xx_hsio_getrate,
+ };
+
++static const struct clkops clk_pxa3xx_ac97_ops = {
++ .enable = clk_pxa3xx_cken_enable,
++ .disable = clk_pxa3xx_cken_disable,
++ .getrate = clk_pxa3xx_ac97_getrate,
++};
++
++static void clk_pout_enable(struct clk *clk)
++{
++ OSCC |= OSCC_PEN;
++}
++
++static void clk_pout_disable(struct clk *clk)
++{
++ OSCC &= ~OSCC_PEN;
++}
++
++static const struct clkops clk_pout_ops = {
++ .enable = clk_pout_enable,
++ .disable = clk_pout_disable,
++};
++
+ #define PXA3xx_CKEN(_name, _cken, _rate, _delay, _dev) \
+ { \
+ .name = _name, \
+@@ -175,8 +215,16 @@ static const struct clkops clk_pxa3xx_hsio_ops = {
+ }
+
+ static struct clk pxa3xx_clks[] = {
+- PXA3xx_CK("LCDCLK", LCD, &clk_pxa3xx_hsio_ops, &pxa_device_fb.dev),
+- PXA3xx_CK("CAMCLK", CAMERA, &clk_pxa3xx_hsio_ops, NULL),
++ {
++ .name = "CLK_POUT",
++ .ops = &clk_pout_ops,
++ .rate = 13000000,
++ .delay = 70,
++ },
++
++ PXA3xx_CK("LCDCLK", LCD, &clk_pxa3xx_hsio_ops, &pxa_device_fb.dev),
++ PXA3xx_CK("CAMCLK", CAMERA, &clk_pxa3xx_hsio_ops, NULL),
++ PXA3xx_CK("AC97CLK", AC97, &clk_pxa3xx_ac97_ops, NULL),
+
+ PXA3xx_CKEN("UARTCLK", FFUART, 14857000, 1, &pxa_device_ffuart.dev),
+ PXA3xx_CKEN("UARTCLK", BTUART, 14857000, 1, &pxa_device_btuart.dev),
+@@ -185,6 +233,7 @@ static struct clk pxa3xx_clks[] = {
+ PXA3xx_CKEN("I2CCLK", I2C, 32842000, 0, &pxa_device_i2c.dev),
+ PXA3xx_CKEN("UDCCLK", UDC, 48000000, 5, &pxa_device_udc.dev),
+ PXA3xx_CKEN("USBCLK", USBH, 48000000, 0, &pxa27x_device_ohci.dev),
++ PXA3xx_CKEN("KBDCLK", KEYPAD, 32768, 0, &pxa27x_device_keypad.dev),
+
+ PXA3xx_CKEN("SSPCLK", SSP1, 13000000, 0, &pxa27x_device_ssp1.dev),
+ PXA3xx_CKEN("SSPCLK", SSP2, 13000000, 0, &pxa27x_device_ssp2.dev),
+@@ -305,8 +354,10 @@ static void pxa3xx_cpu_pm_enter(suspend_state_t state)
+ /*
+ * Don't sleep if no wakeup sources are defined
+ */
+- if (wakeup_src == 0)
++ if (wakeup_src == 0) {
++ printk(KERN_ERR "Not suspending: no wakeup sources\n");
+ return;
++ }
+
+ switch (state) {
+ case PM_SUSPEND_STANDBY:
+@@ -446,15 +497,9 @@ static int pxa3xx_set_wake(unsigned int irq, unsigned int on)
+
+ return 0;
+ }
+-
+-static void pxa3xx_init_irq_pm(void)
+-{
+- pxa_init_irq_set_wake(pxa3xx_set_wake);
+-}
+-
+ #else
+ static inline void pxa3xx_init_pm(void) {}
+-static inline void pxa3xx_init_irq_pm(void) {}
++#define pxa3xx_set_wake NULL
+ #endif
+
+ void __init pxa3xx_init_irq(void)
+@@ -465,10 +510,8 @@ void __init pxa3xx_init_irq(void)
+ value |= (1 << 6);
+ __asm__ __volatile__("mcr p15, 0, %0, c15, c1, 0\n": :"r"(value));
+
+- pxa_init_irq_low();
+- pxa_init_irq_high();
+- pxa_init_irq_gpio(128);
+- pxa3xx_init_irq_pm();
++ pxa_init_irq(56, pxa3xx_set_wake);
++ pxa_init_gpio(128, NULL);
+ }
+
+ /*
+@@ -490,11 +533,9 @@ static struct platform_device *devices[] __initdata = {
+
+ static struct sys_device pxa3xx_sysdev[] = {
+ {
+- .id = 0,
+ .cls = &pxa_irq_sysclass,
+ }, {
+- .id = 1,
+- .cls = &pxa_irq_sysclass,
++ .cls = &pxa3xx_mfp_sysclass,
+ }, {
+ .cls = &pxa_gpio_sysclass,
+ },
+@@ -532,4 +573,4 @@ static int __init pxa3xx_init(void)
+ return ret;
+ }
+
+-subsys_initcall(pxa3xx_init);
++postcore_initcall(pxa3xx_init);
+diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c
+index f9d1b61..34cd585 100644
+--- a/arch/arm/mach-pxa/sharpsl_pm.c
++++ b/arch/arm/mach-pxa/sharpsl_pm.c
+@@ -26,6 +26,7 @@
+ #include <asm/mach-types.h>
+ #include <asm/arch/pm.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/sharpsl.h>
+ #include "sharpsl.h"
+
+diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
+index 9e7773f..62a02c3 100644
+--- a/arch/arm/mach-pxa/spitz.c
++++ b/arch/arm/mach-pxa/spitz.c
+@@ -37,6 +37,7 @@
+
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/arch/pxa2xx-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/irda.h>
+ #include <asm/arch/mmc.h>
+ #include <asm/arch/ohci.h>
+diff --git a/arch/arm/mach-pxa/spitz_pm.c b/arch/arm/mach-pxa/spitz_pm.c
+index 745a4dc..7a7f5f9 100644
+--- a/arch/arm/mach-pxa/spitz_pm.c
++++ b/arch/arm/mach-pxa/spitz_pm.c
+@@ -26,6 +26,7 @@
+ #include <asm/arch/sharpsl.h>
+ #include <asm/arch/spitz.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include "sharpsl.h"
+
+ #define SHARPSL_CHARGE_ON_VOLT 0x99 /* 2.9V */
+diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
+index f99112d..6458f6d 100644
+--- a/arch/arm/mach-pxa/tosa.c
++++ b/arch/arm/mach-pxa/tosa.c
+@@ -23,6 +23,7 @@
+ #include <linux/delay.h>
+ #include <linux/gpio_keys.h>
+ #include <linux/input.h>
++#include <linux/gpio.h>
+
+ #include <asm/setup.h>
+ #include <asm/memory.h>
+@@ -32,7 +33,9 @@
+ #include <asm/system.h>
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/arch/pxa2xx-regs.h>
++#include <asm/arch/mfp-pxa25x.h>
+ #include <asm/arch/irda.h>
++#include <asm/arch/i2c.h>
+ #include <asm/arch/mmc.h>
+ #include <asm/arch/udc.h>
+
+@@ -47,6 +50,110 @@
+ #include "generic.h"
+ #include "devices.h"
+
++static unsigned long tosa_pin_config[] = {
++ GPIO78_nCS_2, /* Scoop */
++ GPIO80_nCS_4, /* tg6393xb */
++ GPIO33_nCS_5, /* Scoop */
++
++ // GPIO76 CARD_VCC_ON1
++
++ GPIO19_GPIO, /* Reset out */
++ GPIO1_RST | WAKEUP_ON_EDGE_FALL,
++
++ GPIO0_GPIO | WAKEUP_ON_EDGE_FALL, /* WAKE_UP */
++ GPIO2_GPIO | WAKEUP_ON_EDGE_BOTH, /* AC_IN */
++ GPIO3_GPIO | WAKEUP_ON_EDGE_FALL, /* RECORD */
++ GPIO4_GPIO | WAKEUP_ON_EDGE_FALL, /* SYNC */
++ GPIO20_GPIO, /* EAR_IN */
++ GPIO22_GPIO, /* On */
++
++ GPIO5_GPIO, /* USB_IN */
++ GPIO32_GPIO, /* Pen IRQ */
++
++ GPIO7_GPIO, /* Jacket Detect */
++ GPIO14_GPIO, /* BAT0_CRG */
++ GPIO12_GPIO, /* BAT1_CRG */
++ GPIO17_GPIO, /* BAT0_LOW */
++ GPIO84_GPIO, /* BAT1_LOW */
++ GPIO38_GPIO, /* BAT_LOCK */
++
++ GPIO11_3_6MHz,
++ GPIO15_GPIO, /* TC6393XB IRQ */
++ GPIO18_RDY,
++ GPIO27_GPIO, /* LCD Sync */
++
++ /* MMC */
++ GPIO6_MMC_CLK,
++ GPIO8_MMC_CS0,
++ GPIO9_GPIO, /* Detect */
++ // GPIO10 nSD_INT
++
++ /* CF */
++ GPIO13_GPIO, /* CD_IRQ */
++ GPIO21_GPIO, /* Main Slot IRQ */
++ GPIO36_GPIO, /* Jacket Slot IRQ */
++ GPIO48_nPOE,
++ GPIO49_nPWE,
++ GPIO50_nPIOR,
++ GPIO51_nPIOW,
++ GPIO52_nPCE_1,
++ GPIO53_nPCE_2,
++ GPIO54_nPSKTSEL,
++ GPIO55_nPREG,
++ GPIO56_nPWAIT,
++ GPIO57_nIOIS16,
++
++ /* AC97 */
++ GPIO31_AC97_SYNC,
++ GPIO30_AC97_SDATA_OUT,
++ GPIO28_AC97_BITCLK,
++ GPIO29_AC97_SDATA_IN_0,
++ // GPIO79 nAUD_IRQ
++
++ /* FFUART */
++ GPIO34_FFUART_RXD,
++ GPIO35_FFUART_CTS,
++ GPIO37_FFUART_DSR,
++ GPIO39_FFUART_TXD,
++ GPIO40_FFUART_DTR,
++ GPIO41_FFUART_RTS,
++
++ /* BTUART */
++ GPIO42_BTUART_RXD,
++ GPIO43_BTUART_TXD,
++ GPIO44_BTUART_CTS,
++ GPIO45_BTUART_RTS,
++
++ /* IrDA */
++ GPIO46_STUART_RXD,
++ GPIO47_STUART_TXD,
++
++ /* Keybd */
++ GPIO58_GPIO,
++ GPIO59_GPIO,
++ GPIO60_GPIO,
++ GPIO61_GPIO,
++ GPIO62_GPIO,
++ GPIO63_GPIO,
++ GPIO64_GPIO,
++ GPIO65_GPIO,
++ GPIO66_GPIO,
++ GPIO67_GPIO,
++ GPIO68_GPIO,
++ GPIO69_GPIO,
++ GPIO70_GPIO,
++ GPIO71_GPIO,
++ GPIO72_GPIO,
++ GPIO73_GPIO,
++ GPIO74_GPIO,
++ GPIO75_GPIO,
++
++ /* SPI */
++ GPIO81_SSP2_CLK_OUT,
++ GPIO82_SSP2_FRM_OUT,
++ GPIO83_SSP2_TXD,
++};
++
+ /*
+ * SCOOP Device
+ */
+@@ -60,11 +167,10 @@ static struct resource tosa_scoop_resources[] = {
+
+ static struct scoop_config tosa_scoop_setup = {
+ .io_dir = TOSA_SCOOP_IO_DIR,
+- .io_out = TOSA_SCOOP_IO_OUT,
+-
++ .gpio_base = TOSA_SCOOP_GPIO_BASE,
+ };
+
+-struct platform_device tosascoop_device = {
++static struct platform_device tosascoop_device = {
+ .name = "sharp-scoop",
+ .id = 0,
+ .dev = {
+@@ -88,10 +194,10 @@ static struct resource tosa_scoop_jc_resources[] = {
+
+ static struct scoop_config tosa_scoop_jc_setup = {
+ .io_dir = TOSA_SCOOP_JC_IO_DIR,
+- .io_out = TOSA_SCOOP_JC_IO_OUT,
++ .gpio_base = TOSA_SCOOP_JC_GPIO_BASE,
+ };
+
+-struct platform_device tosascoop_jc_device = {
++static struct platform_device tosascoop_jc_device = {
+ .name = "sharp-scoop",
+ .id = 1,
+ .dev = {
+@@ -118,50 +224,16 @@ static struct scoop_pcmcia_dev tosa_pcmcia_scoop[] = {
+ },
+ };
+
+-static void tosa_pcmcia_init(void)
+-{
+- /* Setup default state of GPIO outputs
+- before we enable them as outputs. */
+- GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) |
+- GPIO_bit(GPIO49_nPWE) | GPIO_bit(GPIO50_nPIOR) |
+- GPIO_bit(GPIO51_nPIOW) | GPIO_bit(GPIO52_nPCE_1) |
+- GPIO_bit(GPIO53_nPCE_2);
+-
+- pxa_gpio_mode(GPIO48_nPOE_MD);
+- pxa_gpio_mode(GPIO49_nPWE_MD);
+- pxa_gpio_mode(GPIO50_nPIOR_MD);
+- pxa_gpio_mode(GPIO51_nPIOW_MD);
+- pxa_gpio_mode(GPIO55_nPREG_MD);
+- pxa_gpio_mode(GPIO56_nPWAIT_MD);
+- pxa_gpio_mode(GPIO57_nIOIS16_MD);
+- pxa_gpio_mode(GPIO52_nPCE_1_MD);
+- pxa_gpio_mode(GPIO53_nPCE_2_MD);
+- pxa_gpio_mode(GPIO54_pSKTSEL_MD);
+-}
+-
+ static struct scoop_pcmcia_config tosa_pcmcia_config = {
+ .devs = &tosa_pcmcia_scoop[0],
+ .num_devs = 2,
+- .pcmcia_init = tosa_pcmcia_init,
+ };
+
+ /*
+ * USB Device Controller
+ */
+-static void tosa_udc_command(int cmd)
+-{
+- switch(cmd) {
+- case PXA2XX_UDC_CMD_CONNECT:
+- set_scoop_gpio(&tosascoop_jc_device.dev,TOSA_SCOOP_JC_USB_PULLUP);
+- break;
+- case PXA2XX_UDC_CMD_DISCONNECT:
+- reset_scoop_gpio(&tosascoop_jc_device.dev,TOSA_SCOOP_JC_USB_PULLUP);
+- break;
+- }
+-}
+-
+ static struct pxa2xx_udc_mach_info udc_info __initdata = {
+- .udc_command = tosa_udc_command,
++ .gpio_pullup = TOSA_GPIO_USB_PULLUP,
+ .gpio_vbus = TOSA_GPIO_USB_IN,
+ .gpio_vbus_inverted = 1,
+ };
+@@ -175,19 +247,44 @@ static int tosa_mci_init(struct device *dev, irq_handler_t tosa_detect_int, void
+ {
+ int err;
+
+- /* setup GPIO for PXA25x MMC controller */
+- pxa_gpio_mode(GPIO6_MMCCLK_MD);
+- pxa_gpio_mode(GPIO8_MMCCS0_MD);
+- pxa_gpio_mode(TOSA_GPIO_nSD_DETECT | GPIO_IN);
+-
+ tosa_mci_platform_data.detect_delay = msecs_to_jiffies(250);
+
+ err = request_irq(TOSA_IRQ_GPIO_nSD_DETECT, tosa_detect_int,
+ IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "MMC/SD card detect", data);
+- if (err)
++ if (err) {
+ printk(KERN_ERR "tosa_mci_init: MMC/SD: can't request MMC card detect IRQ\n");
++ goto err_irq;
++ }
+
++ err = gpio_request(TOSA_GPIO_SD_WP, "sd_wp");
++ if (err) {
++ printk(KERN_ERR "tosa_mci_init: can't request SD_WP gpio\n");
++ goto err_gpio_wp;
++ }
++ err = gpio_direction_input(TOSA_GPIO_SD_WP);
++ if (err)
++ goto err_gpio_wp_dir;
++
++ err = gpio_request(TOSA_GPIO_PWR_ON, "sd_pwr");
++ if (err) {
++ printk(KERN_ERR "tosa_mci_init: can't request SD_PWR gpio\n");
++ goto err_gpio_pwr;
++ }
++ err = gpio_direction_output(TOSA_GPIO_PWR_ON, 0);
++ if (err)
++ goto err_gpio_pwr_dir;
++
++ return 0;
++
++err_gpio_pwr_dir:
++ gpio_free(TOSA_GPIO_PWR_ON);
++err_gpio_pwr:
++err_gpio_wp_dir:
++ gpio_free(TOSA_GPIO_SD_WP);
++err_gpio_wp:
++ free_irq(TOSA_IRQ_GPIO_nSD_DETECT, data);
++err_irq:
+ return err;
+ }
+
+@@ -196,19 +293,21 @@ static void tosa_mci_setpower(struct device *dev, unsigned int vdd)
+ struct pxamci_platform_data* p_d = dev->platform_data;
+
+ if (( 1 << vdd) & p_d->ocr_mask) {
+- set_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_PWR_ON);
++ gpio_set_value(TOSA_GPIO_PWR_ON, 1);
+ } else {
+- reset_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_PWR_ON);
++ gpio_set_value(TOSA_GPIO_PWR_ON, 0);
+ }
+ }
+
+ static int tosa_mci_get_ro(struct device *dev)
+ {
+- return (read_scoop_reg(&tosascoop_device.dev, SCOOP_GPWR)&TOSA_SCOOP_SD_WP);
++ return gpio_get_value(TOSA_GPIO_SD_WP);
+ }
+
+ static void tosa_mci_exit(struct device *dev, void *data)
+ {
++ gpio_free(TOSA_GPIO_PWR_ON);
++ gpio_free(TOSA_GPIO_SD_WP);
+ free_irq(TOSA_IRQ_GPIO_nSD_DETECT, data);
+ }
+
+@@ -223,21 +322,36 @@ static struct pxamci_platform_data tosa_mci_platform_data = {
+ /*
+ * Irda
+ */
+-static void tosa_irda_transceiver_mode(struct device *dev, int mode)
++static int tosa_irda_startup(struct device *dev)
+ {
+- if (mode & IR_OFF) {
+- reset_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_IR_POWERDWN);
+- pxa_gpio_mode(GPIO47_STTXD|GPIO_DFLT_LOW);
+- pxa_gpio_mode(GPIO47_STTXD|GPIO_OUT);
+- } else {
+- pxa_gpio_mode(GPIO47_STTXD_MD);
+- set_scoop_gpio(&tosascoop_device.dev,TOSA_SCOOP_IR_POWERDWN);
++ int ret;
++
++ ret = gpio_request(TOSA_GPIO_IR_POWERDWN, "IrDA powerdown");
++ if (ret)
++ return ret;
++
++ ret = gpio_direction_output(TOSA_GPIO_IR_POWERDWN, 0);
++ if (ret)
++ gpio_free(TOSA_GPIO_IR_POWERDWN);
++
++ return ret;
+ }
++
++static void tosa_irda_shutdown(struct device *dev)
++{
++ gpio_free(TOSA_GPIO_IR_POWERDWN);
++}
++
++static void tosa_irda_transceiver_mode(struct device *dev, int mode)
++{
++ gpio_set_value(TOSA_GPIO_IR_POWERDWN, !(mode & IR_OFF));
+ }
+
+ static struct pxaficp_platform_data tosa_ficp_platform_data = {
+ .transceiver_cap = IR_SIRMODE | IR_OFF,
+ .transceiver_mode = tosa_irda_transceiver_mode,
++ .startup = tosa_irda_startup,
++ .shutdown = tosa_irda_shutdown,
+ };
+
+ /*
+@@ -249,12 +363,28 @@ static struct platform_device tosakbd_device = {
+ };
+
+ static struct gpio_keys_button tosa_gpio_keys[] = {
++ /*
++ * Two following keys are directly tied to "ON" button of tosa. Why?
++ * The first one can be used as a wakeup source, the second can't;
++ * also the first one is OR of ac_powered and on_button.
++ */
++ {
++ .type = EV_PWR,
++ .code = KEY_RESERVED,
++ .gpio = TOSA_GPIO_POWERON,
++ .desc = "Poweron",
++ .wakeup = 1,
++ .active_low = 1,
++ },
+ {
+ .type = EV_PWR,
+ .code = KEY_SUSPEND,
+ .gpio = TOSA_GPIO_ON_KEY,
+ .desc = "On key",
+- .wakeup = 1,
++ /*
++ * can't be used as wakeup
++ * .wakeup = 1,
++ */
+ .active_low = 1,
+ },
+ {
+@@ -291,9 +421,40 @@ static struct platform_device tosa_gpio_keys_device = {
+ /*
+ * Tosa LEDs
+ */
++static struct gpio_led tosa_gpio_leds[] = {
++ {
++ .name = "tosa:amber:charge",
++ .default_trigger = "main-battery-charging",
++ .gpio = TOSA_GPIO_CHRG_ERR_LED,
++ },
++ {
++ .name = "tosa:green:mail",
++ .default_trigger = "nand-disk",
++ .gpio = TOSA_GPIO_NOTE_LED,
++ },
++ {
++ .name = "tosa:dual:wlan",
++ .default_trigger = "none",
++ .gpio = TOSA_GPIO_WLAN_LED,
++ },
++ {
++ .name = "tosa:blue:bluetooth",
++ .default_trigger = "none",
++ .gpio = TOSA_GPIO_BT_LED,
++ },
++};
++
++static struct gpio_led_platform_data tosa_gpio_leds_platform_data = {
++ .leds = tosa_gpio_leds,
++ .num_leds = ARRAY_SIZE(tosa_gpio_leds),
++};
++
+ static struct platform_device tosaled_device = {
+- .name = "tosa-led",
+- .id = -1,
++ .name = "leds-gpio",
++ .id = -1,
++ .dev = {
++ .platform_data = &tosa_gpio_leds_platform_data,
++ },
+ };
+
+ static struct platform_device *devices[] __initdata = {
+@@ -326,20 +487,13 @@ static void tosa_restart(char mode)
+
+ static void __init tosa_init(void)
+ {
++ pxa2xx_mfp_config(ARRAY_AND_SIZE(tosa_pin_config));
++ gpio_set_wake(MFP_PIN_GPIO1, 1);
++ /* We can't pass to gpio-keys since it will drop the Reset altfunc */
++
+ pm_power_off = tosa_poweroff;
+ arm_pm_restart = tosa_restart;
+
+- pxa_gpio_mode(TOSA_GPIO_ON_RESET | GPIO_IN);
+- pxa_gpio_mode(TOSA_GPIO_TC6393_INT | GPIO_IN);
+- pxa_gpio_mode(TOSA_GPIO_USB_IN | GPIO_IN);
+-
+- /* setup sleep mode values */
+- PWER = 0x00000002;
+- PFER = 0x00000000;
+- PRER = 0x00000002;
+- PGSR0 = 0x00000000;
+- PGSR1 = 0x00FF0002;
+- PGSR2 = 0x00014000;
+ PCFR |= PCFR_OPDE;
+
+ /* enable batt_fault */
+@@ -348,6 +502,7 @@ static void __init tosa_init(void)
+ pxa_set_mci_info(&tosa_mci_platform_data);
+ pxa_set_udc_info(&udc_info);
+ pxa_set_ficp_info(&tosa_ficp_platform_data);
++ pxa_set_i2c_info(NULL);
+ platform_scoop_config = &tosa_pcmcia_config;
+
+ platform_add_devices(devices, ARRAY_SIZE(devices));
+diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
+index f207fcd..931885d 100644
+--- a/arch/arm/mach-pxa/trizeps4.c
++++ b/arch/arm/mach-pxa/trizeps4.c
+@@ -41,6 +41,7 @@
+ #include <asm/mach/flash.h>
+
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/trizeps4.h>
+ #include <asm/arch/audio.h>
+ #include <asm/arch/pxafb.h>
+diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
+index afd2cbf..dbb5462 100644
+--- a/arch/arm/mach-pxa/zylonite.c
++++ b/arch/arm/mach-pxa/zylonite.c
+@@ -26,6 +26,7 @@
+ #include <asm/arch/pxafb.h>
+ #include <asm/arch/zylonite.h>
+ #include <asm/arch/mmc.h>
++#include <asm/arch/pxa27x_keypad.h>
+
+ #include "generic.h"
+
+@@ -35,6 +36,8 @@ struct platform_mmc_slot zylonite_mmc_slot[MAX_SLOTS];
+ int gpio_backlight;
+ int gpio_eth_irq;
+
++int wm9713_irq;
++
+ int lcd_id;
+ int lcd_orientation;
+
+@@ -249,6 +252,71 @@ static void __init zylonite_init_mmc(void)
+ static inline void zylonite_init_mmc(void) {}
+ #endif
+
++#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULES)
++static unsigned int zylonite_matrix_key_map[] = {
++ /* KEY(row, col, key_code) */
++ KEY(0, 0, KEY_A), KEY(0, 1, KEY_B), KEY(0, 2, KEY_C), KEY(0, 5, KEY_D),
++ KEY(1, 0, KEY_E), KEY(1, 1, KEY_F), KEY(1, 2, KEY_G), KEY(1, 5, KEY_H),
++ KEY(2, 0, KEY_I), KEY(2, 1, KEY_J), KEY(2, 2, KEY_K), KEY(2, 5, KEY_L),
++ KEY(3, 0, KEY_M), KEY(3, 1, KEY_N), KEY(3, 2, KEY_O), KEY(3, 5, KEY_P),
++ KEY(5, 0, KEY_Q), KEY(5, 1, KEY_R), KEY(5, 2, KEY_S), KEY(5, 5, KEY_T),
++ KEY(6, 0, KEY_U), KEY(6, 1, KEY_V), KEY(6, 2, KEY_W), KEY(6, 5, KEY_X),
++ KEY(7, 1, KEY_Y), KEY(7, 2, KEY_Z),
++
++ KEY(4, 4, KEY_0), KEY(1, 3, KEY_1), KEY(4, 1, KEY_2), KEY(1, 4, KEY_3),
++ KEY(2, 3, KEY_4), KEY(4, 2, KEY_5), KEY(2, 4, KEY_6), KEY(3, 3, KEY_7),
++ KEY(4, 3, KEY_8), KEY(3, 4, KEY_9),
++
++ KEY(4, 5, KEY_SPACE),
++ KEY(5, 3, KEY_KPASTERISK), /* * */
++ KEY(5, 4, KEY_KPDOT), /* #" */
++
++ KEY(0, 7, KEY_UP),
++ KEY(1, 7, KEY_DOWN),
++ KEY(2, 7, KEY_LEFT),
++ KEY(3, 7, KEY_RIGHT),
++ KEY(2, 6, KEY_HOME),
++ KEY(3, 6, KEY_END),
++ KEY(6, 4, KEY_DELETE),
++ KEY(6, 6, KEY_BACK),
++ KEY(6, 3, KEY_CAPSLOCK), /* KEY_LEFTSHIFT), */
++
++ KEY(4, 6, KEY_ENTER), /* scroll push */
++ KEY(5, 7, KEY_ENTER), /* keypad action */
++
++ KEY(0, 4, KEY_EMAIL),
++ KEY(5, 6, KEY_SEND),
++ KEY(4, 0, KEY_CALENDAR),
++ KEY(7, 6, KEY_RECORD),
++ KEY(6, 7, KEY_VOLUMEUP),
++ KEY(7, 7, KEY_VOLUMEDOWN),
++
++ KEY(0, 6, KEY_F22), /* soft1 */
++ KEY(1, 6, KEY_F23), /* soft2 */
++ KEY(0, 3, KEY_AUX), /* contact */
++};
++
++static struct pxa27x_keypad_platform_data zylonite_keypad_info = {
++ .matrix_key_rows = 8,
++ .matrix_key_cols = 8,
++ .matrix_key_map = zylonite_matrix_key_map,
++ .matrix_key_map_size = ARRAY_SIZE(zylonite_matrix_key_map),
++
++ .enable_rotary0 = 1,
++ .rotary0_up_key = KEY_UP,
++ .rotary0_down_key = KEY_DOWN,
++
++ .debounce_interval = 30,
++};
++
++static void __init zylonite_init_keypad(void)
++{
++ pxa_set_keypad_info(&zylonite_keypad_info);
++}
++#else
++static inline void zylonite_init_keypad(void) {}
++#endif
++
+ static void __init zylonite_init(void)
+ {
+ /* board-processor specific initialization */
+@@ -265,6 +333,7 @@ static void __init zylonite_init(void)
+
+ zylonite_init_lcd();
+ zylonite_init_mmc();
++ zylonite_init_keypad();
+ }
+
+ MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
+diff --git a/arch/arm/mach-pxa/zylonite_pxa300.c b/arch/arm/mach-pxa/zylonite_pxa300.c
+index 6ac04c0..324fb9d 100644
+--- a/arch/arm/mach-pxa/zylonite_pxa300.c
++++ b/arch/arm/mach-pxa/zylonite_pxa300.c
+@@ -21,7 +21,7 @@
+ #include <asm/arch/mfp-pxa300.h>
+ #include <asm/arch/zylonite.h>
+
+-#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x)
++#include "generic.h"
+
+ /* PXA300/PXA310 common configurations */
+ static mfp_cfg_t common_mfp_cfg[] __initdata = {
+@@ -69,6 +69,9 @@ static mfp_cfg_t common_mfp_cfg[] __initdata = {
+ GPIO27_AC97_SDATA_OUT,
+ GPIO28_AC97_SYNC,
+
++ /* WM9713 IRQ */
++ GPIO26_GPIO,
++
+ /* Keypad */
+ GPIO107_KP_DKIN_0 | MFP_LPM_EDGE_BOTH,
+ GPIO108_KP_DKIN_1 | MFP_LPM_EDGE_BOTH,
+@@ -203,6 +206,9 @@ void __init zylonite_pxa300_init(void)
+ /* MMC card detect & write protect for controller 0 */
+ zylonite_mmc_slot[0].gpio_cd = EXT_GPIO(0);
+ zylonite_mmc_slot[0].gpio_wp = EXT_GPIO(2);
++
++ /* WM9713 IRQ */
++ wm9713_irq = mfp_to_gpio(MFP_PIN_GPIO26);
+ }
+
+ if (cpu_is_pxa300()) {
+diff --git a/arch/arm/mach-pxa/zylonite_pxa320.c b/arch/arm/mach-pxa/zylonite_pxa320.c
+index dfa7999..193d079 100644
+--- a/arch/arm/mach-pxa/zylonite_pxa320.c
++++ b/arch/arm/mach-pxa/zylonite_pxa320.c
+@@ -21,7 +21,7 @@
+ #include <asm/arch/mfp-pxa320.h>
+ #include <asm/arch/zylonite.h>
+
+-#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x)
++#include "generic.h"
+
+ static mfp_cfg_t mfp_cfg[] __initdata = {
+ /* LCD */
+@@ -68,6 +68,9 @@ static mfp_cfg_t mfp_cfg[] __initdata = {
+ GPIO39_AC97_BITCLK,
+ GPIO40_AC97_nACRESET,
+
++ /* WM9713 IRQ */
++ GPIO15_GPIO,
++
+ /* I2C */
+ GPIO32_I2C_SCL,
+ GPIO33_I2C_SDA,
+@@ -190,5 +193,8 @@ void __init zylonite_pxa320_init(void)
+ /* MMC card detect & write protect for controller 0 */
+ zylonite_mmc_slot[0].gpio_cd = mfp_to_gpio(MFP_PIN_GPIO1);
+ zylonite_mmc_slot[0].gpio_wp = mfp_to_gpio(MFP_PIN_GPIO5);
++
++ /* WM9713 IRQ */
++ wm9713_irq = mfp_to_gpio(MFP_PIN_GPIO15);
+ }
+ }
+diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig
+index 39b3bb7..5ccde7c 100644
+--- a/arch/arm/mach-realview/Kconfig
++++ b/arch/arm/mach-realview/Kconfig
+@@ -10,7 +10,6 @@ config MACH_REALVIEW_EB
+ config REALVIEW_EB_ARM11MP
+ bool "Support ARM11MPCore tile"
+ depends on MACH_REALVIEW_EB
+- select CACHE_L2X0
+ help
+ Enable support for the ARM11MPCore tile on the Realview platform.
+
+@@ -24,4 +23,18 @@ config REALVIEW_EB_ARM11MP_REVB
+ kernel built with this option enabled is not compatible with
+ other revisions of the ARM11MPCore tile.
+
++config MACH_REALVIEW_PB11MP
++ bool "Support RealView/PB11MPCore platform"
++ select ARM_GIC
++ help
++ Include support for the ARM(R) RealView MPCore Platform Baseboard.
++ PB11MPCore is a platform with an on-board ARM11MPCore and has
++ support for PCI-E and Compact Flash.
++
++config MACH_REALVIEW_PB1176
++ bool "Support RealView/PB1176 platform"
++ select ARM_GIC
++ help
++ Include support for the ARM(R) RealView ARM1176 Platform Baseboard.
++
+ endmenu
+diff --git a/arch/arm/mach-realview/Makefile b/arch/arm/mach-realview/Makefile
+index ca1e390..d2ae077 100644
+--- a/arch/arm/mach-realview/Makefile
++++ b/arch/arm/mach-realview/Makefile
+@@ -4,5 +4,7 @@
+
+ obj-y := core.o clock.o
+ obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o
++obj-$(CONFIG_MACH_REALVIEW_PB11MP) += realview_pb11mp.o
++obj-$(CONFIG_MACH_REALVIEW_PB1176) += realview_pb1176.o
+ obj-$(CONFIG_SMP) += platsmp.o headsmp.o localtimer.o
+ obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
+diff --git a/arch/arm/mach-realview/clock.c b/arch/arm/mach-realview/clock.c
+index 21325a4..3e706c5 100644
+--- a/arch/arm/mach-realview/clock.c
++++ b/arch/arm/mach-realview/clock.c
+@@ -16,7 +16,6 @@
+ #include <linux/clk.h>
+ #include <linux/mutex.h>
+
+-#include <asm/semaphore.h>
+ #include <asm/hardware/icst307.h>
+
+ #include "clock.h"
+diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
+index 98aefc9..131990d 100644
+--- a/arch/arm/mach-realview/core.c
++++ b/arch/arm/mach-realview/core.c
+@@ -109,22 +109,21 @@ static struct flash_platform_data realview_flash_data = {
+ .set_vpp = realview_flash_set_vpp,
+ };
+
+-static struct resource realview_flash_resource = {
+- .start = REALVIEW_FLASH_BASE,
+- .end = REALVIEW_FLASH_BASE + REALVIEW_FLASH_SIZE,
+- .flags = IORESOURCE_MEM,
+-};
+-
+ struct platform_device realview_flash_device = {
+ .name = "armflash",
+ .id = 0,
+ .dev = {
+ .platform_data = &realview_flash_data,
+ },
+- .num_resources = 1,
+- .resource = &realview_flash_resource,
+ };
+
++int realview_flash_register(struct resource *res, u32 num)
++{
++ realview_flash_device.resource = res;
++ realview_flash_device.num_resources = num;
++ return platform_device_register(&realview_flash_device);
++}
++
+ static struct resource realview_i2c_resource = {
+ .start = REALVIEW_I2C_BASE,
+ .end = REALVIEW_I2C_BASE + SZ_4K - 1,
+@@ -445,10 +444,10 @@ void realview_leds_event(led_event_t ledevt)
+ /*
+ * Where is the timer (VA)?
+ */
+-#define TIMER0_VA_BASE __io_address(REALVIEW_TIMER0_1_BASE)
+-#define TIMER1_VA_BASE (__io_address(REALVIEW_TIMER0_1_BASE) + 0x20)
+-#define TIMER2_VA_BASE __io_address(REALVIEW_TIMER2_3_BASE)
+-#define TIMER3_VA_BASE (__io_address(REALVIEW_TIMER2_3_BASE) + 0x20)
++void __iomem *timer0_va_base;
++void __iomem *timer1_va_base;
++void __iomem *timer2_va_base;
++void __iomem *timer3_va_base;
+
+ /*
+ * How long is the timer interval?
+@@ -475,7 +474,7 @@ static void timer_set_mode(enum clock_event_mode mode,
+
+ switch(mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+- writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
++ writel(TIMER_RELOAD, timer0_va_base + TIMER_LOAD);
+
+ ctrl = TIMER_CTRL_PERIODIC;
+ ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE | TIMER_CTRL_ENABLE;
+@@ -491,16 +490,16 @@ static void timer_set_mode(enum clock_event_mode mode,
+ ctrl = 0;
+ }
+
+- writel(ctrl, TIMER0_VA_BASE + TIMER_CTRL);
++ writel(ctrl, timer0_va_base + TIMER_CTRL);
+ }
+
+ static int timer_set_next_event(unsigned long evt,
+ struct clock_event_device *unused)
+ {
+- unsigned long ctrl = readl(TIMER0_VA_BASE + TIMER_CTRL);
++ unsigned long ctrl = readl(timer0_va_base + TIMER_CTRL);
+
+- writel(evt, TIMER0_VA_BASE + TIMER_LOAD);
+- writel(ctrl | TIMER_CTRL_ENABLE, TIMER0_VA_BASE + TIMER_CTRL);
++ writel(evt, timer0_va_base + TIMER_LOAD);
++ writel(ctrl | TIMER_CTRL_ENABLE, timer0_va_base + TIMER_CTRL);
+
+ return 0;
+ }
+@@ -536,7 +535,7 @@ static irqreturn_t realview_timer_interrupt(int irq, void *dev_id)
+ struct clock_event_device *evt = &timer0_clockevent;
+
+ /* clear the interrupt */
+- writel(1, TIMER0_VA_BASE + TIMER_INTCLR);
++ writel(1, timer0_va_base + TIMER_INTCLR);
+
+ evt->event_handler(evt);
+
+@@ -551,7 +550,7 @@ static struct irqaction realview_timer_irq = {
+
+ static cycle_t realview_get_cycles(void)
+ {
+- return ~readl(TIMER3_VA_BASE + TIMER_VALUE);
++ return ~readl(timer3_va_base + TIMER_VALUE);
+ }
+
+ static struct clocksource clocksource_realview = {
+@@ -566,11 +565,11 @@ static struct clocksource clocksource_realview = {
+ static void __init realview_clocksource_init(void)
+ {
+ /* setup timer 0 as free-running clocksource */
+- writel(0, TIMER3_VA_BASE + TIMER_CTRL);
+- writel(0xffffffff, TIMER3_VA_BASE + TIMER_LOAD);
+- writel(0xffffffff, TIMER3_VA_BASE + TIMER_VALUE);
++ writel(0, timer3_va_base + TIMER_CTRL);
++ writel(0xffffffff, timer3_va_base + TIMER_LOAD);
++ writel(0xffffffff, timer3_va_base + TIMER_VALUE);
+ writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
+- TIMER3_VA_BASE + TIMER_CTRL);
++ timer3_va_base + TIMER_CTRL);
+
+ clocksource_realview.mult =
+ clocksource_khz2mult(1000, clocksource_realview.shift);
+@@ -607,10 +606,10 @@ void __init realview_timer_init(unsigned int timer_irq)
+ /*
+ * Initialise to a known state (all timers off)
+ */
+- writel(0, TIMER0_VA_BASE + TIMER_CTRL);
+- writel(0, TIMER1_VA_BASE + TIMER_CTRL);
+- writel(0, TIMER2_VA_BASE + TIMER_CTRL);
+- writel(0, TIMER3_VA_BASE + TIMER_CTRL);
++ writel(0, timer0_va_base + TIMER_CTRL);
++ writel(0, timer1_va_base + TIMER_CTRL);
++ writel(0, timer2_va_base + TIMER_CTRL);
++ writel(0, timer3_va_base + TIMER_CTRL);
+
+ /*
+ * Make irqs happen for the system timer
+diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h
+index 492a14c..33dbbb4 100644
+--- a/arch/arm/mach-realview/core.h
++++ b/arch/arm/mach-realview/core.h
+@@ -55,8 +55,13 @@ extern void __iomem *gic_cpu_base_addr;
+ extern void __iomem *twd_base_addr;
+ extern unsigned int twd_size;
+ #endif
++extern void __iomem *timer0_va_base;
++extern void __iomem *timer1_va_base;
++extern void __iomem *timer2_va_base;
++extern void __iomem *timer3_va_base;
+
+ extern void realview_leds_event(led_event_t ledevt);
+ extern void realview_timer_init(unsigned int timer_irq);
++extern int realview_flash_register(struct resource *res, u32 num);
+
+ #endif
+diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c
+index de2b715..3e57428 100644
+--- a/arch/arm/mach-realview/platsmp.c
++++ b/arch/arm/mach-realview/platsmp.c
+@@ -15,11 +15,14 @@
+ #include <linux/smp.h>
+
+ #include <asm/cacheflush.h>
+-#include <asm/hardware/arm_scu.h>
+ #include <asm/hardware.h>
+ #include <asm/io.h>
+ #include <asm/mach-types.h>
+
++#include <asm/arch/board-eb.h>
++#include <asm/arch/board-pb11mp.h>
++#include <asm/arch/scu.h>
++
+ extern void realview_secondary_startup(void);
+
+ /*
+@@ -31,9 +34,15 @@ volatile int __cpuinitdata pen_release = -1;
+ static unsigned int __init get_core_count(void)
+ {
+ unsigned int ncores;
++ void __iomem *scu_base = 0;
++
++ if (machine_is_realview_eb() && core_tile_eb11mp())
++ scu_base = __io_address(REALVIEW_EB11MP_SCU_BASE);
++ else if (machine_is_realview_pb11mp())
++ scu_base = __io_address(REALVIEW_TC11MP_SCU_BASE);
+
+- if (machine_is_realview_eb() && core_tile_eb11mp()) {
+- ncores = __raw_readl(__io_address(REALVIEW_EB11MP_SCU_BASE) + SCU_CONFIG);
++ if (scu_base) {
++ ncores = __raw_readl(scu_base + SCU_CONFIG);
+ ncores = (ncores & 0x03) + 1;
+ } else
+ ncores = 1;
+@@ -41,6 +50,26 @@ static unsigned int __init get_core_count(void)
+ return ncores;
+ }
+
++/*
++ * Setup the SCU
++ */
++static void scu_enable(void)
++{
++ u32 scu_ctrl;
++ void __iomem *scu_base;
++
++ if (machine_is_realview_eb() && core_tile_eb11mp())
++ scu_base = __io_address(REALVIEW_EB11MP_SCU_BASE);
++ else if (machine_is_realview_pb11mp())
++ scu_base = __io_address(REALVIEW_TC11MP_SCU_BASE);
++ else
++ BUG();
++
++ scu_ctrl = __raw_readl(scu_base + SCU_CTRL);
++ scu_ctrl |= 1;
++ __raw_writel(scu_ctrl, scu_base + SCU_CTRL);
++}
++
+ static DEFINE_SPINLOCK(boot_lock);
+
+ void __cpuinit platform_secondary_init(unsigned int cpu)
+@@ -57,7 +86,10 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
+ * core (e.g. timer irq), then they will not have been enabled
+ * for us: do so
+ */
+- gic_cpu_init(0, __io_address(REALVIEW_EB11MP_GIC_CPU_BASE));
++ if (machine_is_realview_eb() && core_tile_eb11mp())
++ gic_cpu_init(0, __io_address(REALVIEW_EB11MP_GIC_CPU_BASE));
++ else if (machine_is_realview_pb11mp())
++ gic_cpu_init(0, __io_address(REALVIEW_TC11MP_GIC_CPU_BASE));
+
+ /*
+ * let the primary processor know we're out of the
+@@ -198,7 +230,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
+ * dummy (!CONFIG_LOCAL_TIMERS), it was already registers in
+ * realview_timer_init
+ */
+- if (machine_is_realview_eb() && core_tile_eb11mp())
++ if ((machine_is_realview_eb() && core_tile_eb11mp()) ||
++ machine_is_realview_pb11mp())
+ local_timer_setup(cpu);
+ #endif
+
+@@ -210,11 +243,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
+ cpu_set(i, cpu_present_map);
+
+ /*
+- * Do we need any more CPUs? If so, then let them know where
+- * to start. Note that, on modern versions of MILO, the "poke"
+- * doesn't actually do anything until each individual core is
+- * sent a soft interrupt to get it out of WFI
++ * Initialise the SCU if there are more than one CPU and let
++ * them know where to start. Note that, on modern versions of
++ * MILO, the "poke" doesn't actually do anything until each
++ * individual core is sent a soft interrupt to get it out of
++ * WFI
+ */
+- if (max_cpus > 1)
++ if (max_cpus > 1) {
++ scu_enable();
+ poke_milo();
++ }
+ }
+diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
+index 60d9eb8..5782d83 100644
+--- a/arch/arm/mach-realview/realview_eb.c
++++ b/arch/arm/mach-realview/realview_eb.c
+@@ -51,13 +51,13 @@ static struct map_desc realview_eb_io_desc[] __initdata = {
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+- .virtual = IO_ADDRESS(REALVIEW_GIC_CPU_BASE),
+- .pfn = __phys_to_pfn(REALVIEW_GIC_CPU_BASE),
++ .virtual = IO_ADDRESS(REALVIEW_EB_GIC_CPU_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_EB_GIC_CPU_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+- .virtual = IO_ADDRESS(REALVIEW_GIC_DIST_BASE),
+- .pfn = __phys_to_pfn(REALVIEW_GIC_DIST_BASE),
++ .virtual = IO_ADDRESS(REALVIEW_EB_GIC_DIST_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_EB_GIC_DIST_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+@@ -66,20 +66,20 @@ static struct map_desc realview_eb_io_desc[] __initdata = {
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+- .virtual = IO_ADDRESS(REALVIEW_TIMER0_1_BASE),
+- .pfn = __phys_to_pfn(REALVIEW_TIMER0_1_BASE),
++ .virtual = IO_ADDRESS(REALVIEW_EB_TIMER0_1_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_EB_TIMER0_1_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+- .virtual = IO_ADDRESS(REALVIEW_TIMER2_3_BASE),
+- .pfn = __phys_to_pfn(REALVIEW_TIMER2_3_BASE),
++ .virtual = IO_ADDRESS(REALVIEW_EB_TIMER2_3_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_EB_TIMER2_3_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ },
+ #ifdef CONFIG_DEBUG_LL
+ {
+- .virtual = IO_ADDRESS(REALVIEW_UART0_BASE),
+- .pfn = __phys_to_pfn(REALVIEW_UART0_BASE),
++ .virtual = IO_ADDRESS(REALVIEW_EB_UART0_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_EB_UART0_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }
+@@ -136,12 +136,12 @@ static void __init realview_eb_map_io(void)
+ /*
+ * These devices are connected directly to the multi-layer AHB switch
+ */
+-#define SMC_IRQ { NO_IRQ, NO_IRQ }
+-#define SMC_DMA { 0, 0 }
++#define EB_SMC_IRQ { NO_IRQ, NO_IRQ }
++#define EB_SMC_DMA { 0, 0 }
+ #define MPMC_IRQ { NO_IRQ, NO_IRQ }
+ #define MPMC_DMA { 0, 0 }
+-#define CLCD_IRQ { IRQ_EB_CLCD, NO_IRQ }
+-#define CLCD_DMA { 0, 0 }
++#define EB_CLCD_IRQ { IRQ_EB_CLCD, NO_IRQ }
++#define EB_CLCD_DMA { 0, 0 }
+ #define DMAC_IRQ { IRQ_EB_DMA, NO_IRQ }
+ #define DMAC_DMA { 0, 0 }
+
+@@ -150,53 +150,53 @@ static void __init realview_eb_map_io(void)
+ */
+ #define SCTL_IRQ { NO_IRQ, NO_IRQ }
+ #define SCTL_DMA { 0, 0 }
+-#define WATCHDOG_IRQ { IRQ_EB_WDOG, NO_IRQ }
+-#define WATCHDOG_DMA { 0, 0 }
+-#define GPIO0_IRQ { IRQ_EB_GPIO0, NO_IRQ }
+-#define GPIO0_DMA { 0, 0 }
++#define EB_WATCHDOG_IRQ { IRQ_EB_WDOG, NO_IRQ }
++#define EB_WATCHDOG_DMA { 0, 0 }
++#define EB_GPIO0_IRQ { IRQ_EB_GPIO0, NO_IRQ }
++#define EB_GPIO0_DMA { 0, 0 }
+ #define GPIO1_IRQ { IRQ_EB_GPIO1, NO_IRQ }
+ #define GPIO1_DMA { 0, 0 }
+-#define RTC_IRQ { IRQ_EB_RTC, NO_IRQ }
+-#define RTC_DMA { 0, 0 }
++#define EB_RTC_IRQ { IRQ_EB_RTC, NO_IRQ }
++#define EB_RTC_DMA { 0, 0 }
+
+ /*
+ * These devices are connected via the DMA APB bridge
+ */
+ #define SCI_IRQ { IRQ_EB_SCI, NO_IRQ }
+ #define SCI_DMA { 7, 6 }
+-#define UART0_IRQ { IRQ_EB_UART0, NO_IRQ }
+-#define UART0_DMA { 15, 14 }
+-#define UART1_IRQ { IRQ_EB_UART1, NO_IRQ }
+-#define UART1_DMA { 13, 12 }
+-#define UART2_IRQ { IRQ_EB_UART2, NO_IRQ }
+-#define UART2_DMA { 11, 10 }
+-#define UART3_IRQ { IRQ_EB_UART3, NO_IRQ }
+-#define UART3_DMA { 0x86, 0x87 }
+-#define SSP_IRQ { IRQ_EB_SSP, NO_IRQ }
+-#define SSP_DMA { 9, 8 }
++#define EB_UART0_IRQ { IRQ_EB_UART0, NO_IRQ }
++#define EB_UART0_DMA { 15, 14 }
++#define EB_UART1_IRQ { IRQ_EB_UART1, NO_IRQ }
++#define EB_UART1_DMA { 13, 12 }
++#define EB_UART2_IRQ { IRQ_EB_UART2, NO_IRQ }
++#define EB_UART2_DMA { 11, 10 }
++#define EB_UART3_IRQ { IRQ_EB_UART3, NO_IRQ }
++#define EB_UART3_DMA { 0x86, 0x87 }
++#define EB_SSP_IRQ { IRQ_EB_SSP, NO_IRQ }
++#define EB_SSP_DMA { 9, 8 }
+
+ /* FPGA Primecells */
+ AMBA_DEVICE(aaci, "fpga:04", AACI, NULL);
+ AMBA_DEVICE(mmc0, "fpga:05", MMCI0, &realview_mmc0_plat_data);
+ AMBA_DEVICE(kmi0, "fpga:06", KMI0, NULL);
+ AMBA_DEVICE(kmi1, "fpga:07", KMI1, NULL);
+-AMBA_DEVICE(uart3, "fpga:09", UART3, NULL);
++AMBA_DEVICE(uart3, "fpga:09", EB_UART3, NULL);
+
+ /* DevChip Primecells */
+-AMBA_DEVICE(smc, "dev:00", SMC, NULL);
+-AMBA_DEVICE(clcd, "dev:20", CLCD, &clcd_plat_data);
++AMBA_DEVICE(smc, "dev:00", EB_SMC, NULL);
++AMBA_DEVICE(clcd, "dev:20", EB_CLCD, &clcd_plat_data);
+ AMBA_DEVICE(dmac, "dev:30", DMAC, NULL);
+ AMBA_DEVICE(sctl, "dev:e0", SCTL, NULL);
+-AMBA_DEVICE(wdog, "dev:e1", WATCHDOG, NULL);
+-AMBA_DEVICE(gpio0, "dev:e4", GPIO0, NULL);
++AMBA_DEVICE(wdog, "dev:e1", EB_WATCHDOG, NULL);
++AMBA_DEVICE(gpio0, "dev:e4", EB_GPIO0, NULL);
+ AMBA_DEVICE(gpio1, "dev:e5", GPIO1, NULL);
+ AMBA_DEVICE(gpio2, "dev:e6", GPIO2, NULL);
+-AMBA_DEVICE(rtc, "dev:e8", RTC, NULL);
++AMBA_DEVICE(rtc, "dev:e8", EB_RTC, NULL);
+ AMBA_DEVICE(sci0, "dev:f0", SCI, NULL);
+-AMBA_DEVICE(uart0, "dev:f1", UART0, NULL);
+-AMBA_DEVICE(uart1, "dev:f2", UART1, NULL);
+-AMBA_DEVICE(uart2, "dev:f3", UART2, NULL);
+-AMBA_DEVICE(ssp0, "dev:f4", SSP, NULL);
++AMBA_DEVICE(uart0, "dev:f1", EB_UART0, NULL);
++AMBA_DEVICE(uart1, "dev:f2", EB_UART1, NULL);
++AMBA_DEVICE(uart2, "dev:f3", EB_UART2, NULL);
++AMBA_DEVICE(ssp0, "dev:f4", EB_SSP, NULL);
+
+ static struct amba_device *amba_devs[] __initdata = {
+ &dmac_device,
+@@ -223,11 +223,16 @@ static struct amba_device *amba_devs[] __initdata = {
+ /*
+ * RealView EB platform devices
+ */
++static struct resource realview_eb_flash_resource = {
++ .start = REALVIEW_EB_FLASH_BASE,
++ .end = REALVIEW_EB_FLASH_BASE + REALVIEW_EB_FLASH_SIZE - 1,
++ .flags = IORESOURCE_MEM,
++};
+
+-static struct resource realview_eb_smc91x_resources[] = {
++static struct resource realview_eb_eth_resources[] = {
+ [0] = {
+- .start = REALVIEW_ETH_BASE,
+- .end = REALVIEW_ETH_BASE + SZ_64K - 1,
++ .start = REALVIEW_EB_ETH_BASE,
++ .end = REALVIEW_EB_ETH_BASE + SZ_64K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+@@ -237,13 +242,36 @@ static struct resource realview_eb_smc91x_resources[] = {
+ },
+ };
+
+-static struct platform_device realview_eb_smc91x_device = {
+- .name = "smc91x",
++static struct platform_device realview_eb_eth_device = {
+ .id = 0,
+- .num_resources = ARRAY_SIZE(realview_eb_smc91x_resources),
+- .resource = realview_eb_smc91x_resources,
++ .num_resources = ARRAY_SIZE(realview_eb_eth_resources),
++ .resource = realview_eb_eth_resources,
+ };
+
++/*
++ * Detect and register the correct Ethernet device. RealView/EB rev D
++ * platforms use the newer SMSC LAN9118 Ethernet chip
++ */
++static int eth_device_register(void)
++{
++ void __iomem *eth_addr = ioremap(REALVIEW_EB_ETH_BASE, SZ_4K);
++ u32 idrev;
++
++ if (!eth_addr)
++ return -ENOMEM;
++
++ idrev = readl(eth_addr + 0x50);
++ if ((idrev & 0xFFFF0000) == 0x01180000)
++ /* SMSC LAN9118 chip present */
++ realview_eb_eth_device.name = "smc911x";
++ else
++ /* SMSC 91C111 chip present */
++ realview_eb_eth_device.name = "smc91x";
++
++ iounmap(eth_addr);
++ return platform_device_register(&realview_eb_eth_device);
++}
++
+ static void __init gic_init_irq(void)
+ {
+ if (core_tile_eb11mp()) {
+@@ -263,14 +291,14 @@ static void __init gic_init_irq(void)
+
+ #ifndef CONFIG_REALVIEW_EB_ARM11MP_REVB
+ /* board GIC, secondary */
+- gic_dist_init(1, __io_address(REALVIEW_GIC_DIST_BASE), 64);
+- gic_cpu_init(1, __io_address(REALVIEW_GIC_CPU_BASE));
++ gic_dist_init(1, __io_address(REALVIEW_EB_GIC_DIST_BASE), 64);
++ gic_cpu_init(1, __io_address(REALVIEW_EB_GIC_CPU_BASE));
+ gic_cascade_irq(1, IRQ_EB11MP_EB_IRQ1);
+ #endif
+ } else {
+ /* board GIC, primary */
+- gic_cpu_base_addr = __io_address(REALVIEW_GIC_CPU_BASE);
+- gic_dist_init(0, __io_address(REALVIEW_GIC_DIST_BASE), 29);
++ gic_cpu_base_addr = __io_address(REALVIEW_EB_GIC_CPU_BASE);
++ gic_dist_init(0, __io_address(REALVIEW_EB_GIC_DIST_BASE), 29);
+ gic_cpu_init(0, gic_cpu_base_addr);
+ }
+ }
+@@ -301,14 +329,19 @@ static void realview_eb11mp_fixup(void)
+ kmi1_device.irq[0] = IRQ_EB11MP_KMI1;
+
+ /* platform devices */
+- realview_eb_smc91x_resources[1].start = IRQ_EB11MP_ETH;
+- realview_eb_smc91x_resources[1].end = IRQ_EB11MP_ETH;
++ realview_eb_eth_resources[1].start = IRQ_EB11MP_ETH;
++ realview_eb_eth_resources[1].end = IRQ_EB11MP_ETH;
+ }
+
+ static void __init realview_eb_timer_init(void)
+ {
+ unsigned int timer_irq;
+
++ timer0_va_base = __io_address(REALVIEW_EB_TIMER0_1_BASE);
++ timer1_va_base = __io_address(REALVIEW_EB_TIMER0_1_BASE) + 0x20;
++ timer2_va_base = __io_address(REALVIEW_EB_TIMER2_3_BASE);
++ timer3_va_base = __io_address(REALVIEW_EB_TIMER2_3_BASE) + 0x20;
++
+ if (core_tile_eb11mp()) {
+ #ifdef CONFIG_LOCAL_TIMERS
+ twd_base_addr = __io_address(REALVIEW_EB11MP_TWD_BASE);
+@@ -332,16 +365,18 @@ static void __init realview_eb_init(void)
+ if (core_tile_eb11mp()) {
+ realview_eb11mp_fixup();
+
++#ifdef CONFIG_CACHE_L2X0
+ /* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled
+ * Bits: .... ...0 0111 1001 0000 .... .... .... */
+ l2x0_init(__io_address(REALVIEW_EB11MP_L220_BASE), 0x00790000, 0xfe000fff);
++#endif
+ }
+
+ clk_register(&realview_clcd_clk);
+
+- platform_device_register(&realview_flash_device);
+- platform_device_register(&realview_eb_smc91x_device);
++ realview_flash_register(&realview_eb_flash_resource, 1);
+ platform_device_register(&realview_i2c_device);
++ eth_device_register();
+
+ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+ struct amba_device *d = amba_devs[i];
+@@ -355,8 +390,8 @@ static void __init realview_eb_init(void)
+
+ MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
+ /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
+- .phys_io = REALVIEW_UART0_BASE,
+- .io_pg_offst = (IO_ADDRESS(REALVIEW_UART0_BASE) >> 18) & 0xfffc,
++ .phys_io = REALVIEW_EB_UART0_BASE,
++ .io_pg_offst = (IO_ADDRESS(REALVIEW_EB_UART0_BASE) >> 18) & 0xfffc,
+ .boot_params = 0x00000100,
+ .map_io = realview_eb_map_io,
+ .init_irq = gic_init_irq,
+diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c
+new file mode 100644
+index 0000000..cf7f576
+--- /dev/null
++++ b/arch/arm/mach-realview/realview_pb1176.c
+@@ -0,0 +1,292 @@
++/*
++ * linux/arch/arm/mach-realview/realview_pb1176.c
++ *
++ * Copyright (C) 2008 ARM Limited
++ * Copyright (C) 2000 Deep Blue Solutions Ltd
++ *
++ * 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/init.h>
++#include <linux/platform_device.h>
++#include <linux/sysdev.h>
++#include <linux/amba/bus.h>
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/leds.h>
++#include <asm/mach-types.h>
++#include <asm/hardware/gic.h>
++#include <asm/hardware/icst307.h>
++#include <asm/hardware/cache-l2x0.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/map.h>
++#include <asm/mach/mmc.h>
++#include <asm/mach/time.h>
++
++#include <asm/arch/board-pb1176.h>
++#include <asm/arch/irqs.h>
++
++#include "core.h"
++#include "clock.h"
++
++static struct map_desc realview_pb1176_io_desc[] __initdata = {
++ {
++ .virtual = IO_ADDRESS(REALVIEW_SYS_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_SYS_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(REALVIEW_PB1176_GIC_CPU_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_PB1176_GIC_CPU_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(REALVIEW_PB1176_GIC_DIST_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_PB1176_GIC_DIST_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(REALVIEW_DC1176_GIC_CPU_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_DC1176_GIC_CPU_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(REALVIEW_DC1176_GIC_DIST_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_DC1176_GIC_DIST_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(REALVIEW_SCTL_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_SCTL_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(REALVIEW_PB1176_TIMER0_1_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_PB1176_TIMER0_1_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(REALVIEW_PB1176_TIMER2_3_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_PB1176_TIMER2_3_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(REALVIEW_PB1176_L220_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_PB1176_L220_BASE),
++ .length = SZ_8K,
++ .type = MT_DEVICE,
++ },
++#ifdef CONFIG_DEBUG_LL
++ {
++ .virtual = IO_ADDRESS(REALVIEW_PB1176_UART0_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_PB1176_UART0_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ },
++#endif
++};
++
++static void __init realview_pb1176_map_io(void)
++{
++ iotable_init(realview_pb1176_io_desc, ARRAY_SIZE(realview_pb1176_io_desc));
++}
++
++/*
++ * RealView PB1176 AMBA devices
++ */
++#define GPIO2_IRQ { IRQ_PB1176_GPIO2, NO_IRQ }
++#define GPIO2_DMA { 0, 0 }
++#define GPIO3_IRQ { IRQ_PB1176_GPIO3, NO_IRQ }
++#define GPIO3_DMA { 0, 0 }
++#define AACI_IRQ { IRQ_PB1176_AACI, NO_IRQ }
++#define AACI_DMA { 0x80, 0x81 }
++#define MMCI0_IRQ { IRQ_PB1176_MMCI0A, IRQ_PB1176_MMCI0B }
++#define MMCI0_DMA { 0x84, 0 }
++#define KMI0_IRQ { IRQ_PB1176_KMI0, NO_IRQ }
++#define KMI0_DMA { 0, 0 }
++#define KMI1_IRQ { IRQ_PB1176_KMI1, NO_IRQ }
++#define KMI1_DMA { 0, 0 }
++#define PB1176_SMC_IRQ { NO_IRQ, NO_IRQ }
++#define PB1176_SMC_DMA { 0, 0 }
++#define MPMC_IRQ { NO_IRQ, NO_IRQ }
++#define MPMC_DMA { 0, 0 }
++#define PB1176_CLCD_IRQ { IRQ_DC1176_CLCD, NO_IRQ }
++#define PB1176_CLCD_DMA { 0, 0 }
++#define DMAC_IRQ { IRQ_PB1176_DMAC, NO_IRQ }
++#define DMAC_DMA { 0, 0 }
++#define SCTL_IRQ { NO_IRQ, NO_IRQ }
++#define SCTL_DMA { 0, 0 }
++#define PB1176_WATCHDOG_IRQ { IRQ_DC1176_WATCHDOG, NO_IRQ }
++#define PB1176_WATCHDOG_DMA { 0, 0 }
++#define PB1176_GPIO0_IRQ { IRQ_PB1176_GPIO0, NO_IRQ }
++#define PB1176_GPIO0_DMA { 0, 0 }
++#define GPIO1_IRQ { IRQ_PB1176_GPIO1, NO_IRQ }
++#define GPIO1_DMA { 0, 0 }
++#define PB1176_RTC_IRQ { IRQ_DC1176_RTC, NO_IRQ }
++#define PB1176_RTC_DMA { 0, 0 }
++#define SCI_IRQ { IRQ_PB1176_SCI, NO_IRQ }
++#define SCI_DMA { 7, 6 }
++#define PB1176_UART0_IRQ { IRQ_DC1176_UART0, NO_IRQ }
++#define PB1176_UART0_DMA { 15, 14 }
++#define PB1176_UART1_IRQ { IRQ_DC1176_UART1, NO_IRQ }
++#define PB1176_UART1_DMA { 13, 12 }
++#define PB1176_UART2_IRQ { IRQ_DC1176_UART2, NO_IRQ }
++#define PB1176_UART2_DMA { 11, 10 }
++#define PB1176_UART3_IRQ { IRQ_DC1176_UART3, NO_IRQ }
++#define PB1176_UART3_DMA { 0x86, 0x87 }
++#define PB1176_SSP_IRQ { IRQ_PB1176_SSP, NO_IRQ }
++#define PB1176_SSP_DMA { 9, 8 }
++
++/* FPGA Primecells */
++AMBA_DEVICE(aaci, "fpga:04", AACI, NULL);
++AMBA_DEVICE(mmc0, "fpga:05", MMCI0, &realview_mmc0_plat_data);
++AMBA_DEVICE(kmi0, "fpga:06", KMI0, NULL);
++AMBA_DEVICE(kmi1, "fpga:07", KMI1, NULL);
++AMBA_DEVICE(uart3, "fpga:09", PB1176_UART3, NULL);
++
++/* DevChip Primecells */
++AMBA_DEVICE(smc, "dev:00", PB1176_SMC, NULL);
++AMBA_DEVICE(sctl, "dev:e0", SCTL, NULL);
++AMBA_DEVICE(wdog, "dev:e1", PB1176_WATCHDOG, NULL);
++AMBA_DEVICE(gpio0, "dev:e4", PB1176_GPIO0, NULL);
++AMBA_DEVICE(gpio1, "dev:e5", GPIO1, NULL);
++AMBA_DEVICE(gpio2, "dev:e6", GPIO2, NULL);
++AMBA_DEVICE(rtc, "dev:e8", PB1176_RTC, NULL);
++AMBA_DEVICE(sci0, "dev:f0", SCI, NULL);
++AMBA_DEVICE(uart0, "dev:f1", PB1176_UART0, NULL);
++AMBA_DEVICE(uart1, "dev:f2", PB1176_UART1, NULL);
++AMBA_DEVICE(uart2, "dev:f3", PB1176_UART2, NULL);
++AMBA_DEVICE(ssp0, "dev:f4", PB1176_SSP, NULL);
++
++/* Primecells on the NEC ISSP chip */
++AMBA_DEVICE(clcd, "issp:20", PB1176_CLCD, &clcd_plat_data);
++//AMBA_DEVICE(dmac, "issp:30", PB1176_DMAC, NULL);
++
++static struct amba_device *amba_devs[] __initdata = {
++// &dmac_device,
++ &uart0_device,
++ &uart1_device,
++ &uart2_device,
++ &uart3_device,
++ &smc_device,
++ &clcd_device,
++ &sctl_device,
++ &wdog_device,
++ &gpio0_device,
++ &gpio1_device,
++ &gpio2_device,
++ &rtc_device,
++ &sci0_device,
++ &ssp0_device,
++ &aaci_device,
++ &mmc0_device,
++ &kmi0_device,
++ &kmi1_device,
++};
++
++/*
++ * RealView PB1176 platform devices
++ */
++static struct resource realview_pb1176_flash_resource = {
++ .start = REALVIEW_PB1176_FLASH_BASE,
++ .end = REALVIEW_PB1176_FLASH_BASE + REALVIEW_PB1176_FLASH_SIZE - 1,
++ .flags = IORESOURCE_MEM,
++};
++
++static struct resource realview_pb1176_smsc911x_resources[] = {
++ [0] = {
++ .start = REALVIEW_PB1176_ETH_BASE,
++ .end = REALVIEW_PB1176_ETH_BASE + SZ_64K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_PB1176_ETH,
++ .end = IRQ_PB1176_ETH,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device realview_pb1176_smsc911x_device = {
++ .name = "smc911x",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(realview_pb1176_smsc911x_resources),
++ .resource = realview_pb1176_smsc911x_resources,
++};
++
++static void __init gic_init_irq(void)
++{
++ /* ARM1176 DevChip GIC, primary */
++ gic_cpu_base_addr = __io_address(REALVIEW_DC1176_GIC_CPU_BASE);
++ gic_dist_init(0, __io_address(REALVIEW_DC1176_GIC_DIST_BASE), IRQ_DC1176_GIC_START);
++ gic_cpu_init(0, gic_cpu_base_addr);
++
++ /* board GIC, secondary */
++ gic_dist_init(1, __io_address(REALVIEW_PB1176_GIC_DIST_BASE), IRQ_PB1176_GIC_START);
++ gic_cpu_init(1, __io_address(REALVIEW_PB1176_GIC_CPU_BASE));
++ gic_cascade_irq(1, IRQ_DC1176_PB_IRQ1);
++}
++
++static void __init realview_pb1176_timer_init(void)
++{
++ timer0_va_base = __io_address(REALVIEW_PB1176_TIMER0_1_BASE);
++ timer1_va_base = __io_address(REALVIEW_PB1176_TIMER0_1_BASE) + 0x20;
++ timer2_va_base = __io_address(REALVIEW_PB1176_TIMER2_3_BASE);
++ timer3_va_base = __io_address(REALVIEW_PB1176_TIMER2_3_BASE) + 0x20;
++
++ realview_timer_init(IRQ_DC1176_TIMER0);
++}
++
++static struct sys_timer realview_pb1176_timer = {
++ .init = realview_pb1176_timer_init,
++};
++
++static void __init realview_pb1176_init(void)
++{
++ int i;
++
++#ifdef CONFIG_CACHE_L2X0
++ /* 128Kb (16Kb/way) 8-way associativity. evmon/parity/share enabled. */
++ l2x0_init(__io_address(REALVIEW_PB1176_L220_BASE), 0x00730000, 0xfe000fff);
++#endif
++
++ clk_register(&realview_clcd_clk);
++
++ realview_flash_register(&realview_pb1176_flash_resource, 1);
++ platform_device_register(&realview_pb1176_smsc911x_device);
++
++ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
++ struct amba_device *d = amba_devs[i];
++ amba_device_register(d, &iomem_resource);
++ }
++
++#ifdef CONFIG_LEDS
++ leds_event = realview_leds_event;
++#endif
++}
++
++MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176")
++ /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
++ .phys_io = REALVIEW_PB1176_UART0_BASE,
++ .io_pg_offst = (IO_ADDRESS(REALVIEW_PB1176_UART0_BASE) >> 18) & 0xfffc,
++ .boot_params = 0x00000100,
++ .map_io = realview_pb1176_map_io,
++ .init_irq = gic_init_irq,
++ .timer = &realview_pb1176_timer,
++ .init_machine = realview_pb1176_init,
++MACHINE_END
+diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c
+new file mode 100644
+index 0000000..f7ce1c5
+--- /dev/null
++++ b/arch/arm/mach-realview/realview_pb11mp.c
+@@ -0,0 +1,342 @@
++/*
++ * linux/arch/arm/mach-realview/realview_pb11mp.c
++ *
++ * Copyright (C) 2008 ARM Limited
++ * Copyright (C) 2000 Deep Blue Solutions Ltd
++ *
++ * 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/init.h>
++#include <linux/platform_device.h>
++#include <linux/sysdev.h>
++#include <linux/amba/bus.h>
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/leds.h>
++#include <asm/mach-types.h>
++#include <asm/hardware/gic.h>
++#include <asm/hardware/icst307.h>
++#include <asm/hardware/cache-l2x0.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/map.h>
++#include <asm/mach/mmc.h>
++#include <asm/mach/time.h>
++
++#include <asm/arch/board-pb11mp.h>
++#include <asm/arch/irqs.h>
++
++#include "core.h"
++#include "clock.h"
++
++static struct map_desc realview_pb11mp_io_desc[] __initdata = {
++ {
++ .virtual = IO_ADDRESS(REALVIEW_SYS_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_SYS_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(REALVIEW_PB11MP_GIC_CPU_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_PB11MP_GIC_CPU_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(REALVIEW_PB11MP_GIC_DIST_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_PB11MP_GIC_DIST_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(REALVIEW_TC11MP_GIC_CPU_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_TC11MP_GIC_CPU_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(REALVIEW_TC11MP_GIC_DIST_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_TC11MP_GIC_DIST_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(REALVIEW_SCTL_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_SCTL_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(REALVIEW_PB11MP_TIMER0_1_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_PB11MP_TIMER0_1_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(REALVIEW_PB11MP_TIMER2_3_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_PB11MP_TIMER2_3_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ }, {
++ .virtual = IO_ADDRESS(REALVIEW_TC11MP_L220_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_TC11MP_L220_BASE),
++ .length = SZ_8K,
++ .type = MT_DEVICE,
++ },
++#ifdef CONFIG_DEBUG_LL
++ {
++ .virtual = IO_ADDRESS(REALVIEW_PB11MP_UART0_BASE),
++ .pfn = __phys_to_pfn(REALVIEW_PB11MP_UART0_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE,
++ },
++#endif
++};
++
++static void __init realview_pb11mp_map_io(void)
++{
++ iotable_init(realview_pb11mp_io_desc, ARRAY_SIZE(realview_pb11mp_io_desc));
++}
++
++/*
++ * RealView PB11MPCore AMBA devices
++ */
++
++#define GPIO2_IRQ { IRQ_PB11MP_GPIO2, NO_IRQ }
++#define GPIO2_DMA { 0, 0 }
++#define GPIO3_IRQ { IRQ_PB11MP_GPIO3, NO_IRQ }
++#define GPIO3_DMA { 0, 0 }
++#define AACI_IRQ { IRQ_TC11MP_AACI, NO_IRQ }
++#define AACI_DMA { 0x80, 0x81 }
++#define MMCI0_IRQ { IRQ_TC11MP_MMCI0A, IRQ_TC11MP_MMCI0B }
++#define MMCI0_DMA { 0x84, 0 }
++#define KMI0_IRQ { IRQ_TC11MP_KMI0, NO_IRQ }
++#define KMI0_DMA { 0, 0 }
++#define KMI1_IRQ { IRQ_TC11MP_KMI1, NO_IRQ }
++#define KMI1_DMA { 0, 0 }
++#define PB11MP_SMC_IRQ { NO_IRQ, NO_IRQ }
++#define PB11MP_SMC_DMA { 0, 0 }
++#define MPMC_IRQ { NO_IRQ, NO_IRQ }
++#define MPMC_DMA { 0, 0 }
++#define PB11MP_CLCD_IRQ { IRQ_PB11MP_CLCD, NO_IRQ }
++#define PB11MP_CLCD_DMA { 0, 0 }
++#define DMAC_IRQ { IRQ_PB11MP_DMAC, NO_IRQ }
++#define DMAC_DMA { 0, 0 }
++#define SCTL_IRQ { NO_IRQ, NO_IRQ }
++#define SCTL_DMA { 0, 0 }
++#define PB11MP_WATCHDOG_IRQ { IRQ_PB11MP_WATCHDOG, NO_IRQ }
++#define PB11MP_WATCHDOG_DMA { 0, 0 }
++#define PB11MP_GPIO0_IRQ { IRQ_PB11MP_GPIO0, NO_IRQ }
++#define PB11MP_GPIO0_DMA { 0, 0 }
++#define GPIO1_IRQ { IRQ_PB11MP_GPIO1, NO_IRQ }
++#define GPIO1_DMA { 0, 0 }
++#define PB11MP_RTC_IRQ { IRQ_TC11MP_RTC, NO_IRQ }
++#define PB11MP_RTC_DMA { 0, 0 }
++#define SCI_IRQ { IRQ_PB11MP_SCI, NO_IRQ }
++#define SCI_DMA { 7, 6 }
++#define PB11MP_UART0_IRQ { IRQ_TC11MP_UART0, NO_IRQ }
++#define PB11MP_UART0_DMA { 15, 14 }
++#define PB11MP_UART1_IRQ { IRQ_TC11MP_UART1, NO_IRQ }
++#define PB11MP_UART1_DMA { 13, 12 }
++#define PB11MP_UART2_IRQ { IRQ_PB11MP_UART2, NO_IRQ }
++#define PB11MP_UART2_DMA { 11, 10 }
++#define PB11MP_UART3_IRQ { IRQ_PB11MP_UART3, NO_IRQ }
++#define PB11MP_UART3_DMA { 0x86, 0x87 }
++#define PB11MP_SSP_IRQ { IRQ_PB11MP_SSP, NO_IRQ }
++#define PB11MP_SSP_DMA { 9, 8 }
++
++/* FPGA Primecells */
++AMBA_DEVICE(aaci, "fpga:04", AACI, NULL);
++AMBA_DEVICE(mmc0, "fpga:05", MMCI0, &realview_mmc0_plat_data);
++AMBA_DEVICE(kmi0, "fpga:06", KMI0, NULL);
++AMBA_DEVICE(kmi1, "fpga:07", KMI1, NULL);
++AMBA_DEVICE(uart3, "fpga:09", PB11MP_UART3, NULL);
++
++/* DevChip Primecells */
++AMBA_DEVICE(smc, "dev:00", PB11MP_SMC, NULL);
++AMBA_DEVICE(sctl, "dev:e0", SCTL, NULL);
++AMBA_DEVICE(wdog, "dev:e1", PB11MP_WATCHDOG, NULL);
++AMBA_DEVICE(gpio0, "dev:e4", PB11MP_GPIO0, NULL);
++AMBA_DEVICE(gpio1, "dev:e5", GPIO1, NULL);
++AMBA_DEVICE(gpio2, "dev:e6", GPIO2, NULL);
++AMBA_DEVICE(rtc, "dev:e8", PB11MP_RTC, NULL);
++AMBA_DEVICE(sci0, "dev:f0", SCI, NULL);
++AMBA_DEVICE(uart0, "dev:f1", PB11MP_UART0, NULL);
++AMBA_DEVICE(uart1, "dev:f2", PB11MP_UART1, NULL);
++AMBA_DEVICE(uart2, "dev:f3", PB11MP_UART2, NULL);
++AMBA_DEVICE(ssp0, "dev:f4", PB11MP_SSP, NULL);
++
++/* Primecells on the NEC ISSP chip */
++AMBA_DEVICE(clcd, "issp:20", PB11MP_CLCD, &clcd_plat_data);
++AMBA_DEVICE(dmac, "issp:30", DMAC, NULL);
++
++static struct amba_device *amba_devs[] __initdata = {
++ &dmac_device,
++ &uart0_device,
++ &uart1_device,
++ &uart2_device,
++ &uart3_device,
++ &smc_device,
++ &clcd_device,
++ &sctl_device,
++ &wdog_device,
++ &gpio0_device,
++ &gpio1_device,
++ &gpio2_device,
++ &rtc_device,
++ &sci0_device,
++ &ssp0_device,
++ &aaci_device,
++ &mmc0_device,
++ &kmi0_device,
++ &kmi1_device,
++};
++
++/*
++ * RealView PB11MPCore platform devices
++ */
++static struct resource realview_pb11mp_flash_resource[] = {
++ [0] = {
++ .start = REALVIEW_PB11MP_FLASH0_BASE,
++ .end = REALVIEW_PB11MP_FLASH0_BASE + REALVIEW_PB11MP_FLASH0_SIZE - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = REALVIEW_PB11MP_FLASH1_BASE,
++ .end = REALVIEW_PB11MP_FLASH1_BASE + REALVIEW_PB11MP_FLASH1_SIZE - 1,
++ .flags = IORESOURCE_MEM,
++ },
++};
++
++static struct resource realview_pb11mp_smsc911x_resources[] = {
++ [0] = {
++ .start = REALVIEW_PB11MP_ETH_BASE,
++ .end = REALVIEW_PB11MP_ETH_BASE + SZ_64K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_TC11MP_ETH,
++ .end = IRQ_TC11MP_ETH,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device realview_pb11mp_smsc911x_device = {
++ .name = "smc911x",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(realview_pb11mp_smsc911x_resources),
++ .resource = realview_pb11mp_smsc911x_resources,
++};
++
++struct resource realview_pb11mp_cf_resources[] = {
++ [0] = {
++ .start = REALVIEW_PB11MP_CF_BASE,
++ .end = REALVIEW_PB11MP_CF_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = REALVIEW_PB11MP_CF_MEM_BASE,
++ .end = REALVIEW_PB11MP_CF_MEM_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [2] = {
++ .start = -1, /* FIXME: Find correct irq */
++ .end = -1,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++struct platform_device realview_pb11mp_cf_device = {
++ .name = "compactflash",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(realview_pb11mp_cf_resources),
++ .resource = realview_pb11mp_cf_resources,
++};
++
++static void __init gic_init_irq(void)
++{
++ unsigned int pldctrl;
++
++ /* new irq mode with no DCC */
++ writel(0x0000a05f, __io_address(REALVIEW_SYS_LOCK));
++ pldctrl = readl(__io_address(REALVIEW_SYS_BASE) + REALVIEW_PB11MP_SYS_PLD_CTRL1);
++ pldctrl |= 2 << 22;
++ writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + REALVIEW_PB11MP_SYS_PLD_CTRL1);
++ writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
++
++ /* ARM11MPCore test chip GIC, primary */
++ gic_cpu_base_addr = __io_address(REALVIEW_TC11MP_GIC_CPU_BASE);
++ gic_dist_init(0, __io_address(REALVIEW_TC11MP_GIC_DIST_BASE), 29);
++ gic_cpu_init(0, gic_cpu_base_addr);
++
++ /* board GIC, secondary */
++ gic_dist_init(1, __io_address(REALVIEW_PB11MP_GIC_DIST_BASE), IRQ_PB11MP_GIC_START);
++ gic_cpu_init(1, __io_address(REALVIEW_PB11MP_GIC_CPU_BASE));
++ gic_cascade_irq(1, IRQ_TC11MP_PB_IRQ1);
++}
++
++static void __init realview_pb11mp_timer_init(void)
++{
++ timer0_va_base = __io_address(REALVIEW_PB11MP_TIMER0_1_BASE);
++ timer1_va_base = __io_address(REALVIEW_PB11MP_TIMER0_1_BASE) + 0x20;
++ timer2_va_base = __io_address(REALVIEW_PB11MP_TIMER2_3_BASE);
++ timer3_va_base = __io_address(REALVIEW_PB11MP_TIMER2_3_BASE) + 0x20;
++
++#ifdef CONFIG_LOCAL_TIMERS
++ twd_base_addr = __io_address(REALVIEW_TC11MP_TWD_BASE);
++ twd_size = REALVIEW_TC11MP_TWD_SIZE;
++#endif
++ realview_timer_init(IRQ_TC11MP_TIMER0_1);
++}
++
++static struct sys_timer realview_pb11mp_timer = {
++ .init = realview_pb11mp_timer_init,
++};
++
++static void __init realview_pb11mp_init(void)
++{
++ int i;
++
++#ifdef CONFIG_CACHE_L2X0
++ /* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled
++ * Bits: .... ...0 0111 1001 0000 .... .... .... */
++ l2x0_init(__io_address(REALVIEW_TC11MP_L220_BASE), 0x00790000, 0xfe000fff);
++#endif
++
++ clk_register(&realview_clcd_clk);
++
++ realview_flash_register(realview_pb11mp_flash_resource,
++ ARRAY_SIZE(realview_pb11mp_flash_resource));
++ platform_device_register(&realview_pb11mp_smsc911x_device);
++ platform_device_register(&realview_i2c_device);
++ platform_device_register(&realview_pb11mp_cf_device);
++
++ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
++ struct amba_device *d = amba_devs[i];
++ amba_device_register(d, &iomem_resource);
++ }
++
++#ifdef CONFIG_LEDS
++ leds_event = realview_leds_event;
++#endif
++}
++
++MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore")
++ /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
++ .phys_io = REALVIEW_PB11MP_UART0_BASE,
++ .io_pg_offst = (IO_ADDRESS(REALVIEW_PB11MP_UART0_BASE) >> 18) & 0xfffc,
++ .boot_params = 0x00000100,
++ .map_io = realview_pb11mp_map_io,
++ .init_irq = gic_init_irq,
++ .timer = &realview_pb11mp_timer,
++ .init_machine = realview_pb11mp_init,
++MACHINE_END
+diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
+index e2079cf..cd3dc08 100644
+--- a/arch/arm/mach-s3c2410/Kconfig
++++ b/arch/arm/mach-s3c2410/Kconfig
+@@ -97,6 +97,13 @@ config BAST_PC104_IRQ
+ Say Y here to enable the PC104 IRQ routing on the
+ Simtec BAST (EB2410ITX)
+
++config MACH_TCT_HAMMER
++ bool "TCT Hammer Board"
++ select CPU_S3C2410
++ help
++ Say Y here if you are using the TinCanTools Hammer Board
++ <http://www.tincantools.com>
++
+ config MACH_VR1000
+ bool "Thorcom VR1000"
+ select PM_SIMTEC if PM
+diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
+index 3e7a855..cabc13c 100644
+--- a/arch/arm/mach-s3c2410/Makefile
++++ b/arch/arm/mach-s3c2410/Makefile
+@@ -27,5 +27,6 @@ obj-$(CONFIG_ARCH_BAST) += mach-bast.o usb-simtec.o
+ obj-$(CONFIG_MACH_OTOM) += mach-otom.o
+ obj-$(CONFIG_MACH_AML_M5900) += mach-amlm5900.o
+ obj-$(CONFIG_BAST_PC104_IRQ) += bast-irq.o
++obj-$(CONFIG_MACH_TCT_HAMMER) += mach-tct_hammer.o
+ obj-$(CONFIG_MACH_VR1000) += mach-vr1000.o usb-simtec.o
+ obj-$(CONFIG_MACH_QT2410) += mach-qt2410.o
+diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
+index 6617547..661a235 100644
+--- a/arch/arm/mach-s3c2410/mach-bast.c
++++ b/arch/arm/mach-s3c2410/mach-bast.c
+@@ -16,6 +16,7 @@
+ #include <linux/list.h>
+ #include <linux/timer.h>
+ #include <linux/init.h>
++#include <linux/sysdev.h>
+ #include <linux/serial_core.h>
+ #include <linux/platform_device.h>
+ #include <linux/dm9000.h>
+@@ -236,6 +237,36 @@ static struct platform_device bast_device_nor = {
+
+ /* NAND Flash on BAST board */
+
++#ifdef CONFIG_PM
++static int bast_pm_suspend(struct sys_device *sd, pm_message_t state)
++{
++ /* ensure that an nRESET is not generated on resume. */
++ s3c2410_gpio_setpin(S3C2410_GPA21, 1);
++ s3c2410_gpio_cfgpin(S3C2410_GPA21, S3C2410_GPA21_OUT);
++
++ return 0;
++}
++
++static int bast_pm_resume(struct sys_device *sd)
++{
++ s3c2410_gpio_cfgpin(S3C2410_GPA21, S3C2410_GPA21_nRSTOUT);
++ return 0;
++}
++
++#else
++#define bast_pm_suspend NULL
++#define bast_pm_resume NULL
++#endif
++
++static struct sysdev_class bast_pm_sysclass = {
++ .name = "mach-bast",
++ .suspend = bast_pm_suspend,
++ .resume = bast_pm_resume,
++};
++
++static struct sys_device bast_pm_sysdev = {
++ .cls = &bast_pm_sysclass,
++};
+
+ static int smartmedia_map[] = { 0 };
+ static int chip0_map[] = { 1 };
+@@ -561,10 +592,10 @@ static void __init bast_map_io(void)
+ {
+ /* initialise the clocks */
+
+- s3c24xx_dclk0.parent = NULL;
++ s3c24xx_dclk0.parent = &clk_upll;
+ s3c24xx_dclk0.rate = 12*1000*1000;
+
+- s3c24xx_dclk1.parent = NULL;
++ s3c24xx_dclk1.parent = &clk_upll;
+ s3c24xx_dclk1.rate = 24*1000*1000;
+
+ s3c24xx_clkout0.parent = &s3c24xx_dclk0;
+@@ -586,6 +617,9 @@ static void __init bast_map_io(void)
+
+ static void __init bast_init(void)
+ {
++ sysdev_class_register(&bast_pm_sysclass);
++ sysdev_register(&bast_pm_sysdev);
++
+ s3c24xx_fb_set_platdata(&bast_fb_info);
+ platform_add_devices(bast_devices, ARRAY_SIZE(bast_devices));
+ }
+diff --git a/arch/arm/mach-s3c2410/mach-tct_hammer.c b/arch/arm/mach-s3c2410/mach-tct_hammer.c
+new file mode 100644
+index 0000000..d90d445
+--- /dev/null
++++ b/arch/arm/mach-s3c2410/mach-tct_hammer.c
+@@ -0,0 +1,160 @@
++/* linux/arch/arm/mach-s3c2410/mach-tct_hammer.c
++ *
++ * Copyright (c) 2007 TinCanTools
++ * David Anders <danders at amltd.com>
++
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ *
++ * @History:
++ * derived from linux/arch/arm/mach-s3c2410/mach-bast.c, written by
++ * Ben Dooks <ben at simtec.co.uk>
++ *
++ ***********************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/list.h>
++#include <linux/timer.h>
++#include <linux/init.h>
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/serial_core.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <asm/mach/irq.h>
++#include <asm/mach/flash.h>
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/mach-types.h>
++
++#include <asm/plat-s3c/regs-serial.h>
++#include <asm/plat-s3c24xx/devs.h>
++#include <asm/plat-s3c24xx/cpu.h>
++
++#ifdef CONFIG_MTD_PARTITIONS
++
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/physmap.h>
++
++static struct resource tct_hammer_nor_resource = {
++ .start = 0x00000000,
++ .end = 0x01000000 - 1,
++ .flags = IORESOURCE_MEM,
++};
++
++static struct mtd_partition tct_hammer_mtd_partitions[] = {
++ {
++ .name = "System",
++ .size = 0x240000,
++ .offset = 0,
++ .mask_flags = MTD_WRITEABLE, /* force read-only */
++ }, {
++ .name = "JFFS2",
++ .size = MTDPART_SIZ_FULL,
++ .offset = MTDPART_OFS_APPEND,
++ }
++};
++
++static struct physmap_flash_data tct_hammer_flash_data = {
++ .width = 2,
++ .parts = tct_hammer_mtd_partitions,
++ .nr_parts = ARRAY_SIZE(tct_hammer_mtd_partitions),
++};
++
++static struct platform_device tct_hammer_device_nor = {
++ .name = "physmap-flash",
++ .id = 0,
++ .dev = {
++ .platform_data = &tct_hammer_flash_data,
++ },
++ .num_resources = 1,
++ .resource = &tct_hammer_nor_resource,
++};
++
++#endif
++
++static struct map_desc tct_hammer_iodesc[] __initdata = {
++};
++
++#define UCON S3C2410_UCON_DEFAULT
++#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
++#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
++
++static struct s3c2410_uartcfg tct_hammer_uartcfgs[] = {
++ [0] = {
++ .hwport = 0,
++ .flags = 0,
++ .ucon = UCON,
++ .ulcon = ULCON,
++ .ufcon = UFCON,
++ },
++ [1] = {
++ .hwport = 1,
++ .flags = 0,
++ .ucon = UCON,
++ .ulcon = ULCON,
++ .ufcon = UFCON,
++ },
++ [2] = {
++ .hwport = 2,
++ .flags = 0,
++ .ucon = UCON,
++ .ulcon = ULCON,
++ .ufcon = UFCON,
++ }
++};
++
++
++static struct platform_device *tct_hammer_devices[] __initdata = {
++ &s3c_device_adc,
++ &s3c_device_wdt,
++ &s3c_device_i2c,
++ &s3c_device_usb,
++ &s3c_device_rtc,
++ &s3c_device_usbgadget,
++ &s3c_device_sdi,
++#ifdef CONFIG_MTD_PARTITIONS
++ &tct_hammer_device_nor,
++#endif
++};
++
++static void __init tct_hammer_map_io(void)
++{
++ s3c24xx_init_io(tct_hammer_iodesc, ARRAY_SIZE(tct_hammer_iodesc));
++ s3c24xx_init_clocks(0);
++ s3c24xx_init_uarts(tct_hammer_uartcfgs, ARRAY_SIZE(tct_hammer_uartcfgs));
++}
++
++static void __init tct_hammer_init(void)
++{
++ platform_add_devices(tct_hammer_devices, ARRAY_SIZE(tct_hammer_devices));
++}
++
++MACHINE_START(TCT_HAMMER, "TCT_HAMMER")
++ .phys_io = S3C2410_PA_UART,
++ .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
++ .boot_params = S3C2410_SDRAM_PA + 0x100,
++ .map_io = tct_hammer_map_io,
++ .init_irq = s3c24xx_init_irq,
++ .init_machine = tct_hammer_init,
++ .timer = &s3c24xx_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
+index 3aade7b..c564233 100644
+--- a/arch/arm/mach-s3c2410/mach-vr1000.c
++++ b/arch/arm/mach-s3c2410/mach-vr1000.c
+@@ -393,7 +393,7 @@ static void __init vr1000_map_io(void)
+ {
+ /* initialise clock sources */
+
+- s3c24xx_dclk0.parent = NULL;
++ s3c24xx_dclk0.parent = &clk_upll;
+ s3c24xx_dclk0.rate = 12*1000*1000;
+
+ s3c24xx_dclk1.parent = NULL;
+diff --git a/arch/arm/mach-s3c2412/s3c2412.c b/arch/arm/mach-s3c2412/s3c2412.c
+index abf1599..98a0de9 100644
+--- a/arch/arm/mach-s3c2412/s3c2412.c
++++ b/arch/arm/mach-s3c2412/s3c2412.c
+@@ -175,7 +175,7 @@ void __init s3c2412_init_clocks(int xtal)
+ /* work out clock scalings */
+
+ hclk = fclk / ((tmp & S3C2412_CLKDIVN_HDIVN_MASK) + 1);
+- hclk /= ((tmp & S3C2421_CLKDIVN_ARMDIVN) ? 2 : 1);
++ hclk /= ((tmp & S3C2412_CLKDIVN_ARMDIVN) ? 2 : 1);
+ pclk = hclk / ((tmp & S3C2412_CLKDIVN_PDIVN) ? 2 : 1);
+
+ /* print brieft summary of clocks, etc */
+diff --git a/arch/arm/mach-s3c2440/mach-anubis.c b/arch/arm/mach-s3c2440/mach-anubis.c
+index 3d3dfa9..4725891 100644
+--- a/arch/arm/mach-s3c2440/mach-anubis.c
++++ b/arch/arm/mach-s3c2440/mach-anubis.c
+@@ -413,10 +413,10 @@ static void __init anubis_map_io(void)
+ {
+ /* initialise the clocks */
+
+- s3c24xx_dclk0.parent = NULL;
++ s3c24xx_dclk0.parent = &clk_upll;
+ s3c24xx_dclk0.rate = 12*1000*1000;
+
+- s3c24xx_dclk1.parent = NULL;
++ s3c24xx_dclk1.parent = &clk_upll;
+ s3c24xx_dclk1.rate = 24*1000*1000;
+
+ s3c24xx_clkout0.parent = &s3c24xx_dclk0;
+diff --git a/arch/arm/mach-s3c2440/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c
+index 78af766..8a8acdb 100644
+--- a/arch/arm/mach-s3c2440/mach-osiris.c
++++ b/arch/arm/mach-s3c2440/mach-osiris.c
+@@ -18,6 +18,7 @@
+ #include <linux/device.h>
+ #include <linux/sysdev.h>
+ #include <linux/serial_core.h>
++#include <linux/clk.h>
+
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+@@ -344,10 +345,10 @@ static void __init osiris_map_io(void)
+
+ /* initialise the clocks */
+
+- s3c24xx_dclk0.parent = NULL;
++ s3c24xx_dclk0.parent = &clk_upll;
+ s3c24xx_dclk0.rate = 12*1000*1000;
+
+- s3c24xx_dclk1.parent = NULL;
++ s3c24xx_dclk1.parent = &clk_upll;
+ s3c24xx_dclk1.rate = 24*1000*1000;
+
+ s3c24xx_clkout0.parent = &s3c24xx_dclk0;
+diff --git a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile
+index 7a61e8d..8e02446 100644
+--- a/arch/arm/mach-sa1100/Makefile
++++ b/arch/arm/mach-sa1100/Makefile
+@@ -3,7 +3,7 @@
+ #
+
+ # Common support
+-obj-y := clock.o generic.o irq.o dma.o time.o #nmi-oopser.o
++obj-y := clock.o generic.o gpio.o irq.o dma.o time.o #nmi-oopser.o
+ obj-m :=
+ obj-n :=
+ obj- :=
+diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
+index 5c84c60..0c2fa1c 100644
+--- a/arch/arm/mach-sa1100/generic.c
++++ b/arch/arm/mach-sa1100/generic.c
+@@ -139,37 +139,6 @@ unsigned long long sched_clock(void)
+ return v;
+ }
+
+-int gpio_direction_input(unsigned gpio)
+-{
+- unsigned long flags;
+-
+- if (gpio > GPIO_MAX)
+- return -EINVAL;
+-
+- local_irq_save(flags);
+- GPDR &= ~GPIO_GPIO(gpio);
+- local_irq_restore(flags);
+- return 0;
+-}
+-
+-EXPORT_SYMBOL(gpio_direction_input);
+-
+-int gpio_direction_output(unsigned gpio, int value)
+-{
+- unsigned long flags;
+-
+- if (gpio > GPIO_MAX)
+- return -EINVAL;
+-
+- local_irq_save(flags);
+- gpio_set_value(gpio, value);
+- GPDR |= GPIO_GPIO(gpio);
+- local_irq_restore(flags);
+- return 0;
+-}
+-
+-EXPORT_SYMBOL(gpio_direction_output);
+-
+ /*
+ * Default power-off for SA1100
+ */
+diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h
+index f085d68..793c2e6 100644
+--- a/arch/arm/mach-sa1100/generic.h
++++ b/arch/arm/mach-sa1100/generic.h
+@@ -9,6 +9,7 @@ struct sys_timer;
+ extern struct sys_timer sa1100_timer;
+ extern void __init sa1100_map_io(void);
+ extern void __init sa1100_init_irq(void);
++extern void __init sa1100_init_gpio(void);
+
+ #define SET_BANK(__nr,__start,__size) \
+ mi->bank[__nr].start = (__start), \
+diff --git a/arch/arm/mach-sa1100/gpio.c b/arch/arm/mach-sa1100/gpio.c
+new file mode 100644
+index 0000000..372f1f4
+--- /dev/null
++++ b/arch/arm/mach-sa1100/gpio.c
+@@ -0,0 +1,65 @@
++/*
++ * linux/arch/arm/mach-sa1100/gpio.c
++ *
++ * Generic SA-1100 GPIO handling
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++
++#include <asm/gpio.h>
++#include <asm/hardware.h>
++#include "generic.h"
++
++static int sa1100_gpio_get(struct gpio_chip *chip, unsigned offset)
++{
++ return GPLR & GPIO_GPIO(offset);
++}
++
++static void sa1100_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
++{
++ if (value)
++ GPSR = GPIO_GPIO(offset);
++ else
++ GPCR = GPIO_GPIO(offset);
++}
++
++static int sa1100_direction_input(struct gpio_chip *chip, unsigned offset)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++ GPDR &= ~GPIO_GPIO(offset);
++ local_irq_restore(flags);
++ return 0;
++}
++
++static int sa1100_direction_output(struct gpio_chip *chip, unsigned offset, int value)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++ sa1100_gpio_set(chip, offset, value);
++ GPDR |= GPIO_GPIO(offset);
++ local_irq_restore(flags);
++ return 0;
++}
++
++static struct gpio_chip sa1100_gpio_chip = {
++ .label = "gpio",
++ .direction_input = sa1100_direction_input,
++ .direction_output = sa1100_direction_output,
++ .set = sa1100_gpio_set,
++ .get = sa1100_gpio_get,
++ .base = 0,
++ .ngpio = GPIO_MAX + 1,
++};
++
++void __init sa1100_init_gpio(void)
++{
++ gpiochip_add(&sa1100_gpio_chip);
++}
+diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
+index 3dc17d7..fa0403a 100644
+--- a/arch/arm/mach-sa1100/irq.c
++++ b/arch/arm/mach-sa1100/irq.c
+@@ -347,4 +347,6 @@ void __init sa1100_init_irq(void)
+ */
+ set_irq_chip(IRQ_GPIO11_27, &sa1100_normal_chip);
+ set_irq_chained_handler(IRQ_GPIO11_27, sa1100_high_gpio_handler);
++
++ sa1100_init_gpio();
+ }
+diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c
+index c267736..a9799cb 100644
+--- a/arch/arm/mach-sa1100/time.c
++++ b/arch/arm/mach-sa1100/time.c
+@@ -13,67 +13,69 @@
+ #include <linux/interrupt.h>
+ #include <linux/irq.h>
+ #include <linux/timex.h>
+-#include <linux/signal.h>
+-#include <linux/clocksource.h>
++#include <linux/clockchips.h>
+
+ #include <asm/mach/time.h>
+ #include <asm/hardware.h>
+
+-#define RTC_DEF_DIVIDER (32768 - 1)
+-#define RTC_DEF_TRIM 0
++#define MIN_OSCR_DELTA 2
+
+-static int sa1100_set_rtc(void)
++static irqreturn_t sa1100_ost0_interrupt(int irq, void *dev_id)
+ {
+- unsigned long current_time = xtime.tv_sec;
++ struct clock_event_device *c = dev_id;
+
+- if (RTSR & RTSR_ALE) {
+- /* make sure not to forward the clock over an alarm */
+- unsigned long alarm = RTAR;
+- if (current_time >= alarm && alarm >= RCNR)
+- return -ERESTARTSYS;
+- }
+- RCNR = current_time;
+- return 0;
+-}
++ /* Disarm the compare/match, signal the event. */
++ OIER &= ~OIER_E0;
++ OSSR = OSSR_M0;
++ c->event_handler(c);
+
+-#ifdef CONFIG_NO_IDLE_HZ
+-static unsigned long initial_match;
+-static int match_posponed;
+-#endif
++ return IRQ_HANDLED;
++}
+
+-static irqreturn_t
+-sa1100_timer_interrupt(int irq, void *dev_id)
++static int
++sa1100_osmr0_set_next_event(unsigned long delta, struct clock_event_device *c)
+ {
+- unsigned int next_match;
++ unsigned long flags, next, oscr;
+
+-#ifdef CONFIG_NO_IDLE_HZ
+- if (match_posponed) {
+- match_posponed = 0;
+- OSMR0 = initial_match;
+- }
+-#endif
++ raw_local_irq_save(flags);
++ OIER |= OIER_E0;
++ next = OSCR + delta;
++ OSMR0 = next;
++ oscr = OSCR;
++ raw_local_irq_restore(flags);
+
+- /*
+- * Loop until we get ahead of the free running timer.
+- * This ensures an exact clock tick count and time accuracy.
+- * Since IRQs are disabled at this point, coherence between
+- * lost_ticks(updated in do_timer()) and the match reg value is
+- * ensured, hence we can use do_gettimeofday() from interrupt
+- * handlers.
+- */
+- do {
+- timer_tick();
+- OSSR = OSSR_M0; /* Clear match on timer 0 */
+- next_match = (OSMR0 += LATCH);
+- } while ((signed long)(next_match - OSCR) <= 0);
++ return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0;
++}
+
+- return IRQ_HANDLED;
++static void
++sa1100_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *c)
++{
++ unsigned long flags;
++
++ switch (mode) {
++ case CLOCK_EVT_MODE_ONESHOT:
++ case CLOCK_EVT_MODE_UNUSED:
++ case CLOCK_EVT_MODE_SHUTDOWN:
++ raw_local_irq_save(flags);
++ OIER &= ~OIER_E0;
++ OSSR = OSSR_M0;
++ raw_local_irq_restore(flags);
++ break;
++
++ case CLOCK_EVT_MODE_RESUME:
++ case CLOCK_EVT_MODE_PERIODIC:
++ break;
++ }
+ }
+
+-static struct irqaction sa1100_timer_irq = {
+- .name = "SA11xx Timer Tick",
+- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+- .handler = sa1100_timer_interrupt,
++static struct clock_event_device ckevt_sa1100_osmr0 = {
++ .name = "osmr0",
++ .features = CLOCK_EVT_FEAT_ONESHOT,
++ .shift = 32,
++ .rating = 200,
++ .cpumask = CPU_MASK_CPU0,
++ .set_next_event = sa1100_osmr0_set_next_event,
++ .set_mode = sa1100_osmr0_set_mode,
+ };
+
+ static cycle_t sa1100_read_oscr(void)
+@@ -90,62 +92,34 @@ static struct clocksource cksrc_sa1100_oscr = {
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ };
+
++static struct irqaction sa1100_timer_irq = {
++ .name = "ost0",
++ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
++ .handler = sa1100_ost0_interrupt,
++ .dev_id = &ckevt_sa1100_osmr0,
++};
++
+ static void __init sa1100_timer_init(void)
+ {
+- unsigned long flags;
+-
+- set_rtc = sa1100_set_rtc;
+-
+ OIER = 0; /* disable any timer interrupts */
+ OSSR = 0xf; /* clear status on all timers */
+- setup_irq(IRQ_OST0, &sa1100_timer_irq);
+- local_irq_save(flags);
+- OIER = OIER_E0; /* enable match on timer 0 to cause interrupts */
+- OSMR0 = OSCR + LATCH; /* set initial match */
+- local_irq_restore(flags);
++
++ ckevt_sa1100_osmr0.mult =
++ div_sc(3686400, NSEC_PER_SEC, ckevt_sa1100_osmr0.shift);
++ ckevt_sa1100_osmr0.max_delta_ns =
++ clockevent_delta2ns(0x7fffffff, &ckevt_sa1100_osmr0);
++ ckevt_sa1100_osmr0.min_delta_ns =
++ clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_sa1100_osmr0) + 1;
+
+ cksrc_sa1100_oscr.mult =
+ clocksource_hz2mult(CLOCK_TICK_RATE, cksrc_sa1100_oscr.shift);
+
+- clocksource_register(&cksrc_sa1100_oscr);
+-}
+-
+-#ifdef CONFIG_NO_IDLE_HZ
+-static int sa1100_dyn_tick_enable_disable(void)
+-{
+- /* nothing to do */
+- return 0;
+-}
+-
+-static void sa1100_dyn_tick_reprogram(unsigned long ticks)
+-{
+- if (ticks > 1) {
+- initial_match = OSMR0;
+- OSMR0 = initial_match + ticks * LATCH;
+- match_posponed = 1;
+- }
+-}
++ setup_irq(IRQ_OST0, &sa1100_timer_irq);
+
+-static irqreturn_t
+-sa1100_dyn_tick_handler(int irq, void *dev_id)
+-{
+- if (match_posponed) {
+- match_posponed = 0;
+- OSMR0 = initial_match;
+- if ((signed long)(initial_match - OSCR) <= 0)
+- return sa1100_timer_interrupt(irq, dev_id);
+- }
+- return IRQ_NONE;
++ clocksource_register(&cksrc_sa1100_oscr);
++ clockevents_register_device(&ckevt_sa1100_osmr0);
+ }
+
+-static struct dyn_tick_timer sa1100_dyn_tick = {
+- .enable = sa1100_dyn_tick_enable_disable,
+- .disable = sa1100_dyn_tick_enable_disable,
+- .reprogram = sa1100_dyn_tick_reprogram,
+- .handler = sa1100_dyn_tick_handler,
+-};
+-#endif
+-
+ #ifdef CONFIG_PM
+ unsigned long osmr[4], oier;
+
+@@ -181,7 +155,4 @@ struct sys_timer sa1100_timer = {
+ .init = sa1100_timer_init,
+ .suspend = sa1100_timer_suspend,
+ .resume = sa1100_timer_resume,
+-#ifdef CONFIG_NO_IDLE_HZ
+- .dyn_tick = &sa1100_dyn_tick,
+-#endif
+ };
+diff --git a/arch/arm/mach-versatile/clock.c b/arch/arm/mach-versatile/clock.c
+index 9858c96..9336508 100644
+--- a/arch/arm/mach-versatile/clock.c
++++ b/arch/arm/mach-versatile/clock.c
+@@ -17,7 +17,6 @@
+ #include <linux/clk.h>
+ #include <linux/mutex.h>
+
+-#include <asm/semaphore.h>
+ #include <asm/hardware/icst307.h>
+
+ #include "clock.h"
+diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
+index 76348f0..1b8229d 100644
+--- a/arch/arm/mm/Kconfig
++++ b/arch/arm/mm/Kconfig
+@@ -18,6 +18,7 @@ config CPU_ARM610
+ select CPU_CP15_MMU
+ select CPU_COPY_V3 if MMU
+ select CPU_TLB_V3 if MMU
++ select CPU_PABRT_NOIFAR
+ help
+ The ARM610 is the successor to the ARM3 processor
+ and was produced by VLSI Technology Inc.
+@@ -31,6 +32,7 @@ config CPU_ARM7TDMI
+ depends on !MMU
+ select CPU_32v4T
+ select CPU_ABRT_LV4T
++ select CPU_PABRT_NOIFAR
+ select CPU_CACHE_V4
+ help
+ A 32-bit RISC microprocessor based on the ARM7 processor core
+@@ -49,6 +51,7 @@ config CPU_ARM710
+ select CPU_CP15_MMU
+ select CPU_COPY_V3 if MMU
+ select CPU_TLB_V3 if MMU
++ select CPU_PABRT_NOIFAR
+ help
+ A 32-bit RISC microprocessor based on the ARM7 processor core
+ designed by Advanced RISC Machines Ltd. The ARM710 is the
+@@ -64,6 +67,7 @@ config CPU_ARM720T
+ default y if ARCH_CLPS711X || ARCH_L7200 || ARCH_CDB89712 || ARCH_H720X
+ select CPU_32v4T
+ select CPU_ABRT_LV4T
++ select CPU_PABRT_NOIFAR
+ select CPU_CACHE_V4
+ select CPU_CACHE_VIVT
+ select CPU_CP15_MMU
+@@ -82,6 +86,7 @@ config CPU_ARM740T
+ depends on !MMU
+ select CPU_32v4T
+ select CPU_ABRT_LV4T
++ select CPU_PABRT_NOIFAR
+ select CPU_CACHE_V3 # although the core is v4t
+ select CPU_CP15_MPU
+ help
+@@ -98,6 +103,7 @@ config CPU_ARM9TDMI
+ depends on !MMU
+ select CPU_32v4T
+ select CPU_ABRT_NOMMU
++ select CPU_PABRT_NOIFAR
+ select CPU_CACHE_V4
+ help
+ A 32-bit RISC microprocessor based on the ARM9 processor core
+@@ -113,6 +119,7 @@ config CPU_ARM920T
+ default y if CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_AT91RM9200
+ select CPU_32v4T
+ select CPU_ABRT_EV4T
++ select CPU_PABRT_NOIFAR
+ select CPU_CACHE_V4WT
+ select CPU_CACHE_VIVT
+ select CPU_CP15_MMU
+@@ -135,6 +142,7 @@ config CPU_ARM922T
+ default y if ARCH_LH7A40X || ARCH_KS8695
+ select CPU_32v4T
+ select CPU_ABRT_EV4T
++ select CPU_PABRT_NOIFAR
+ select CPU_CACHE_V4WT
+ select CPU_CACHE_VIVT
+ select CPU_CP15_MMU
+@@ -155,6 +163,7 @@ config CPU_ARM925T
+ default y if ARCH_OMAP15XX
+ select CPU_32v4T
+ select CPU_ABRT_EV4T
++ select CPU_PABRT_NOIFAR
+ select CPU_CACHE_V4WT
+ select CPU_CACHE_VIVT
+ select CPU_CP15_MMU
+@@ -175,6 +184,7 @@ config CPU_ARM926T
+ default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9 || ARCH_NS9XXX || ARCH_DAVINCI
+ select CPU_32v5
+ select CPU_ABRT_EV5TJ
++ select CPU_PABRT_NOIFAR
+ select CPU_CACHE_VIVT
+ select CPU_CP15_MMU
+ select CPU_COPY_V4WB if MMU
+@@ -193,6 +203,7 @@ config CPU_ARM940T
+ depends on !MMU
+ select CPU_32v4T
+ select CPU_ABRT_NOMMU
++ select CPU_PABRT_NOIFAR
+ select CPU_CACHE_VIVT
+ select CPU_CP15_MPU
+ help
+@@ -210,6 +221,7 @@ config CPU_ARM946E
+ depends on !MMU
+ select CPU_32v5
+ select CPU_ABRT_NOMMU
++ select CPU_PABRT_NOIFAR
+ select CPU_CACHE_VIVT
+ select CPU_CP15_MPU
+ help
+@@ -226,6 +238,7 @@ config CPU_ARM1020
+ depends on ARCH_INTEGRATOR
+ select CPU_32v5
+ select CPU_ABRT_EV4T
++ select CPU_PABRT_NOIFAR
+ select CPU_CACHE_V4WT
+ select CPU_CACHE_VIVT
+ select CPU_CP15_MMU
+@@ -244,6 +257,7 @@ config CPU_ARM1020E
+ depends on ARCH_INTEGRATOR
+ select CPU_32v5
+ select CPU_ABRT_EV4T
++ select CPU_PABRT_NOIFAR
+ select CPU_CACHE_V4WT
+ select CPU_CACHE_VIVT
+ select CPU_CP15_MMU
+@@ -257,6 +271,7 @@ config CPU_ARM1022
+ depends on ARCH_INTEGRATOR
+ select CPU_32v5
+ select CPU_ABRT_EV4T
++ select CPU_PABRT_NOIFAR
+ select CPU_CACHE_VIVT
+ select CPU_CP15_MMU
+ select CPU_COPY_V4WB if MMU # can probably do better
+@@ -275,6 +290,7 @@ config CPU_ARM1026
+ depends on ARCH_INTEGRATOR
+ select CPU_32v5
+ select CPU_ABRT_EV5T # But need Jazelle, but EV5TJ ignores bit 10
++ select CPU_PABRT_NOIFAR
+ select CPU_CACHE_VIVT
+ select CPU_CP15_MMU
+ select CPU_COPY_V4WB if MMU # can probably do better
+@@ -293,6 +309,7 @@ config CPU_SA110
+ select CPU_32v3 if ARCH_RPC
+ select CPU_32v4 if !ARCH_RPC
+ select CPU_ABRT_EV4
++ select CPU_PABRT_NOIFAR
+ select CPU_CACHE_V4WB
+ select CPU_CACHE_VIVT
+ select CPU_CP15_MMU
+@@ -314,6 +331,7 @@ config CPU_SA1100
+ default y
+ select CPU_32v4
+ select CPU_ABRT_EV4
++ select CPU_PABRT_NOIFAR
+ select CPU_CACHE_V4WB
+ select CPU_CACHE_VIVT
+ select CPU_CP15_MMU
+@@ -326,6 +344,7 @@ config CPU_XSCALE
+ default y
+ select CPU_32v5
+ select CPU_ABRT_EV5T
++ select CPU_PABRT_NOIFAR
+ select CPU_CACHE_VIVT
+ select CPU_CP15_MMU
+ select CPU_TLB_V4WBI if MMU
+@@ -337,6 +356,7 @@ config CPU_XSC3
+ default y
+ select CPU_32v5
+ select CPU_ABRT_EV5T
++ select CPU_PABRT_NOIFAR
+ select CPU_CACHE_VIVT
+ select CPU_CP15_MMU
+ select CPU_TLB_V4WBI if MMU
+@@ -345,10 +365,11 @@ config CPU_XSC3
+ # Feroceon
+ config CPU_FEROCEON
+ bool
+- depends on ARCH_ORION
++ depends on ARCH_ORION5X
+ default y
+ select CPU_32v5
+ select CPU_ABRT_EV5T
++ select CPU_PABRT_NOIFAR
+ select CPU_CACHE_VIVT
+ select CPU_CP15_MMU
+ select CPU_COPY_V4WB if MMU
+@@ -366,11 +387,12 @@ config CPU_FEROCEON_OLD_ID
+ # ARMv6
+ config CPU_V6
+ bool "Support ARM V6 processor"
+- depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB || ARCH_OMAP2 || ARCH_MX3 || ARCH_MSM7X00A
++ depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB || ARCH_OMAP2 || ARCH_MX3 || ARCH_MSM7X00A || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176
+ default y if ARCH_MX3
+ default y if ARCH_MSM7X00A
+ select CPU_32v6
+ select CPU_ABRT_EV6
++ select CPU_PABRT_NOIFAR
+ select CPU_CACHE_V6
+ select CPU_CACHE_VIPT
+ select CPU_CP15_MMU
+@@ -393,10 +415,11 @@ config CPU_32v6K
+ # ARMv7
+ config CPU_V7
+ bool "Support ARM V7 processor"
+- depends on ARCH_INTEGRATOR
++ depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB
+ select CPU_32v6K
+ select CPU_32v7
+ select CPU_ABRT_EV7
++ select CPU_PABRT_IFAR
+ select CPU_CACHE_V7
+ select CPU_CACHE_VIPT
+ select CPU_CP15_MMU
+@@ -458,6 +481,12 @@ config CPU_ABRT_EV6
+ config CPU_ABRT_EV7
+ bool
+
++config CPU_PABRT_IFAR
++ bool
++
++config CPU_PABRT_NOIFAR
++ bool
++
+ # The cache model
+ config CPU_CACHE_V3
+ bool
+@@ -572,6 +601,13 @@ config ARM_THUMB
+
+ If you don't know what this all is, saying Y is a safe choice.
+
++config ARM_THUMBEE
++ bool "Enable ThumbEE CPU extension"
++ depends on CPU_V7
++ help
++ Say Y here if you have a CPU with the ThumbEE extension and code to
++ make use of it. Say N for code that can run on CPUs without ThumbEE.
++
+ config CPU_BIG_ENDIAN
+ bool "Build big-endian kernel"
+ depends on ARCH_SUPPORTS_BIG_ENDIAN
+@@ -671,5 +707,9 @@ config OUTER_CACHE
+ default n
+
+ config CACHE_L2X0
+- bool
++ bool "Enable the L2x0 outer cache controller"
++ depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176
++ default y
+ select OUTER_CACHE
++ help
++ This option enables the L2x0 PrimeCell.
+diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
+index ec00f26..b657f17 100644
+--- a/arch/arm/mm/init.c
++++ b/arch/arm/mm/init.c
+@@ -48,8 +48,6 @@ void show_mem(void)
+
+ printk("Mem-info:\n");
+ show_free_areas();
+- printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+-
+ for_each_online_node(node) {
+ pg_data_t *n = NODE_DATA(node);
+ struct page *map = n->node_mem_map - n->node_start_pfn;
+diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
+index 700c04d..5673f4d 100644
+--- a/arch/arm/mm/proc-arm1020.S
++++ b/arch/arm/mm/proc-arm1020.S
+@@ -471,6 +471,7 @@ arm1020_crval:
+ .type arm1020_processor_functions, #object
+ arm1020_processor_functions:
+ .word v4t_early_abort
++ .word pabort_noifar
+ .word cpu_arm1020_proc_init
+ .word cpu_arm1020_proc_fin
+ .word cpu_arm1020_reset
+diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S
+index 1cc206a..4343fdb 100644
+--- a/arch/arm/mm/proc-arm1020e.S
++++ b/arch/arm/mm/proc-arm1020e.S
+@@ -452,6 +452,7 @@ arm1020e_crval:
+ .type arm1020e_processor_functions, #object
+ arm1020e_processor_functions:
+ .word v4t_early_abort
++ .word pabort_noifar
+ .word cpu_arm1020e_proc_init
+ .word cpu_arm1020e_proc_fin
+ .word cpu_arm1020e_reset
+diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S
+index aff0ea0..2a4ea16 100644
+--- a/arch/arm/mm/proc-arm1022.S
++++ b/arch/arm/mm/proc-arm1022.S
+@@ -435,6 +435,7 @@ arm1022_crval:
+ .type arm1022_processor_functions, #object
+ arm1022_processor_functions:
+ .word v4t_early_abort
++ .word pabort_noifar
+ .word cpu_arm1022_proc_init
+ .word cpu_arm1022_proc_fin
+ .word cpu_arm1022_reset
+diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S
+index 65e43a1..77a1bab 100644
+--- a/arch/arm/mm/proc-arm1026.S
++++ b/arch/arm/mm/proc-arm1026.S
+@@ -430,6 +430,7 @@ arm1026_crval:
+ .type arm1026_processor_functions, #object
+ arm1026_processor_functions:
+ .word v5t_early_abort
++ .word pabort_noifar
+ .word cpu_arm1026_proc_init
+ .word cpu_arm1026_proc_fin
+ .word cpu_arm1026_reset
+diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S
+index 123a7dc..c371fc8 100644
+--- a/arch/arm/mm/proc-arm6_7.S
++++ b/arch/arm/mm/proc-arm6_7.S
+@@ -293,6 +293,7 @@ __arm7_setup: mov r0, #0
+ .type arm6_processor_functions, #object
+ ENTRY(arm6_processor_functions)
+ .word cpu_arm6_data_abort
++ .word pabort_noifar
+ .word cpu_arm6_proc_init
+ .word cpu_arm6_proc_fin
+ .word cpu_arm6_reset
+@@ -309,6 +310,7 @@ ENTRY(arm6_processor_functions)
+ .type arm7_processor_functions, #object
+ ENTRY(arm7_processor_functions)
+ .word cpu_arm7_data_abort
++ .word pabort_noifar
+ .word cpu_arm7_proc_init
+ .word cpu_arm7_proc_fin
+ .word cpu_arm7_reset
+diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S
+index dc763be..d64f8e6 100644
+--- a/arch/arm/mm/proc-arm720.S
++++ b/arch/arm/mm/proc-arm720.S
+@@ -198,6 +198,7 @@ arm720_crval:
+ .type arm720_processor_functions, #object
+ ENTRY(arm720_processor_functions)
+ .word v4t_late_abort
++ .word pabort_noifar
+ .word cpu_arm720_proc_init
+ .word cpu_arm720_proc_fin
+ .word cpu_arm720_reset
+diff --git a/arch/arm/mm/proc-arm740.S b/arch/arm/mm/proc-arm740.S
+index 7069f49..3a57376 100644
+--- a/arch/arm/mm/proc-arm740.S
++++ b/arch/arm/mm/proc-arm740.S
+@@ -126,6 +126,7 @@ __arm740_setup:
+ .type arm740_processor_functions, #object
+ ENTRY(arm740_processor_functions)
+ .word v4t_late_abort
++ .word pabort_noifar
+ .word cpu_arm740_proc_init
+ .word cpu_arm740_proc_fin
+ .word cpu_arm740_reset
+diff --git a/arch/arm/mm/proc-arm7tdmi.S b/arch/arm/mm/proc-arm7tdmi.S
+index d091c25..7b3ecde 100644
+--- a/arch/arm/mm/proc-arm7tdmi.S
++++ b/arch/arm/mm/proc-arm7tdmi.S
+@@ -64,6 +64,7 @@ __arm7tdmi_setup:
+ .type arm7tdmi_processor_functions, #object
+ ENTRY(arm7tdmi_processor_functions)
+ .word v4t_late_abort
++ .word pabort_noifar
+ .word cpu_arm7tdmi_proc_init
+ .word cpu_arm7tdmi_proc_fin
+ .word cpu_arm7tdmi_reset
+diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
+index 75c945e..28cdb06 100644
+--- a/arch/arm/mm/proc-arm920.S
++++ b/arch/arm/mm/proc-arm920.S
+@@ -417,6 +417,7 @@ arm920_crval:
+ .type arm920_processor_functions, #object
+ arm920_processor_functions:
+ .word v4t_early_abort
++ .word pabort_noifar
+ .word cpu_arm920_proc_init
+ .word cpu_arm920_proc_fin
+ .word cpu_arm920_reset
+diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
+index ffb751b..94ddcb4 100644
+--- a/arch/arm/mm/proc-arm922.S
++++ b/arch/arm/mm/proc-arm922.S
+@@ -421,6 +421,7 @@ arm922_crval:
+ .type arm922_processor_functions, #object
+ arm922_processor_functions:
+ .word v4t_early_abort
++ .word pabort_noifar
+ .word cpu_arm922_proc_init
+ .word cpu_arm922_proc_fin
+ .word cpu_arm922_reset
+diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
+index 44c2c99..065087a 100644
+--- a/arch/arm/mm/proc-arm925.S
++++ b/arch/arm/mm/proc-arm925.S
+@@ -484,6 +484,7 @@ arm925_crval:
+ .type arm925_processor_functions, #object
+ arm925_processor_functions:
+ .word v4t_early_abort
++ .word pabort_noifar
+ .word cpu_arm925_proc_init
+ .word cpu_arm925_proc_fin
+ .word cpu_arm925_reset
+diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
+index 194ef48..997db84 100644
+--- a/arch/arm/mm/proc-arm926.S
++++ b/arch/arm/mm/proc-arm926.S
+@@ -437,6 +437,7 @@ arm926_crval:
+ .type arm926_processor_functions, #object
+ arm926_processor_functions:
+ .word v5tj_early_abort
++ .word pabort_noifar
+ .word cpu_arm926_proc_init
+ .word cpu_arm926_proc_fin
+ .word cpu_arm926_reset
+diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S
+index 786c593..44ead90 100644
+--- a/arch/arm/mm/proc-arm940.S
++++ b/arch/arm/mm/proc-arm940.S
+@@ -321,6 +321,7 @@ __arm940_setup:
+ .type arm940_processor_functions, #object
+ ENTRY(arm940_processor_functions)
+ .word nommu_early_abort
++ .word pabort_noifar
+ .word cpu_arm940_proc_init
+ .word cpu_arm940_proc_fin
+ .word cpu_arm940_reset
+diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S
+index a60c142..2218b0c 100644
+--- a/arch/arm/mm/proc-arm946.S
++++ b/arch/arm/mm/proc-arm946.S
+@@ -376,6 +376,7 @@ __arm946_setup:
+ .type arm946_processor_functions, #object
+ ENTRY(arm946_processor_functions)
+ .word nommu_early_abort
++ .word pabort_noifar
+ .word cpu_arm946_proc_init
+ .word cpu_arm946_proc_fin
+ .word cpu_arm946_reset
+diff --git a/arch/arm/mm/proc-arm9tdmi.S b/arch/arm/mm/proc-arm9tdmi.S
+index 4848eea..c85c1f5 100644
+--- a/arch/arm/mm/proc-arm9tdmi.S
++++ b/arch/arm/mm/proc-arm9tdmi.S
+@@ -64,6 +64,7 @@ __arm9tdmi_setup:
+ .type arm9tdmi_processor_functions, #object
+ ENTRY(arm9tdmi_processor_functions)
+ .word nommu_early_abort
++ .word pabort_noifar
+ .word cpu_arm9tdmi_proc_init
+ .word cpu_arm9tdmi_proc_fin
+ .word cpu_arm9tdmi_reset
+diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S
+index fa0dc7e..90e7594 100644
+--- a/arch/arm/mm/proc-feroceon.S
++++ b/arch/arm/mm/proc-feroceon.S
+@@ -423,6 +423,7 @@ feroceon_crval:
+ .type feroceon_processor_functions, #object
+ feroceon_processor_functions:
+ .word v5t_early_abort
++ .word pabort_noifar
+ .word cpu_feroceon_proc_init
+ .word cpu_feroceon_proc_fin
+ .word cpu_feroceon_reset
+diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
+index 6e226e1..9818195 100644
+--- a/arch/arm/mm/proc-sa110.S
++++ b/arch/arm/mm/proc-sa110.S
+@@ -216,6 +216,7 @@ sa110_crval:
+ .type sa110_processor_functions, #object
+ ENTRY(sa110_processor_functions)
+ .word v4_early_abort
++ .word pabort_noifar
+ .word cpu_sa110_proc_init
+ .word cpu_sa110_proc_fin
+ .word cpu_sa110_reset
+diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S
+index 9afb11d..c5fe27a 100644
+--- a/arch/arm/mm/proc-sa1100.S
++++ b/arch/arm/mm/proc-sa1100.S
+@@ -231,6 +231,7 @@ sa1100_crval:
+ .type sa1100_processor_functions, #object
+ ENTRY(sa1100_processor_functions)
+ .word v4_early_abort
++ .word pabort_noifar
+ .word cpu_sa1100_proc_init
+ .word cpu_sa1100_proc_fin
+ .word cpu_sa1100_reset
+diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
+index eb42e5b..5702ec5 100644
+--- a/arch/arm/mm/proc-v6.S
++++ b/arch/arm/mm/proc-v6.S
+@@ -17,10 +17,6 @@
+ #include <asm/pgtable-hwdef.h>
+ #include <asm/pgtable.h>
+
+-#ifdef CONFIG_SMP
+-#include <asm/hardware/arm_scu.h>
+-#endif
+-
+ #include "proc-macros.S"
+
+ #define D_CACHE_LINE_SIZE 32
+@@ -187,20 +183,10 @@ cpu_v6_name:
+ */
+ __v6_setup:
+ #ifdef CONFIG_SMP
+- /* Set up the SCU on core 0 only */
+- mrc p15, 0, r0, c0, c0, 5 @ CPU core number
+- ands r0, r0, #15
+- ldreq r0, =SCU_BASE
+- ldreq r5, [r0, #SCU_CTRL]
+- orreq r5, r5, #1
+- streq r5, [r0, #SCU_CTRL]
+-
+-#ifndef CONFIG_CPU_DCACHE_DISABLE
+ mrc p15, 0, r0, c1, c0, 1 @ Enable SMP/nAMP mode
+ orr r0, r0, #0x20
+ mcr p15, 0, r0, c1, c0, 1
+ #endif
+-#endif
+
+ mov r0, #0
+ mcr p15, 0, r0, c7, c14, 0 @ clean+invalidate D cache
+@@ -233,6 +219,7 @@ v6_crval:
+ .type v6_processor_functions, #object
+ ENTRY(v6_processor_functions)
+ .word v6_early_abort
++ .word pabort_noifar
+ .word cpu_v6_proc_init
+ .word cpu_v6_proc_fin
+ .word cpu_v6_reset
+diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
+index e0acc5a..b49f9a4 100644
+--- a/arch/arm/mm/proc-v7.S
++++ b/arch/arm/mm/proc-v7.S
+@@ -205,6 +205,7 @@ __v7_setup_stack:
+ .type v7_processor_functions, #object
+ ENTRY(v7_processor_functions)
+ .word v7_early_abort
++ .word pabort_ifar
+ .word cpu_v7_proc_init
+ .word cpu_v7_proc_fin
+ .word cpu_v7_reset
+diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
+index d95921a..3533741 100644
+--- a/arch/arm/mm/proc-xsc3.S
++++ b/arch/arm/mm/proc-xsc3.S
+@@ -450,6 +450,7 @@ xsc3_crval:
+ .type xsc3_processor_functions, #object
+ ENTRY(xsc3_processor_functions)
+ .word v5t_early_abort
++ .word pabort_noifar
+ .word cpu_xsc3_proc_init
+ .word cpu_xsc3_proc_fin
+ .word cpu_xsc3_reset
+diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
+index 016690b..2dd8527 100644
+--- a/arch/arm/mm/proc-xscale.S
++++ b/arch/arm/mm/proc-xscale.S
+@@ -527,6 +527,7 @@ xscale_crval:
+ .type xscale_processor_functions, #object
+ ENTRY(xscale_processor_functions)
+ .word v5t_early_abort
++ .word pabort_noifar
+ .word cpu_xscale_proc_init
+ .word cpu_xscale_proc_fin
+ .word cpu_xscale_reset
+diff --git a/arch/arm/plat-iop/pci.c b/arch/arm/plat-iop/pci.c
+index 98d0151..d9bc15a 100644
+--- a/arch/arm/plat-iop/pci.c
++++ b/arch/arm/plat-iop/pci.c
+@@ -24,6 +24,7 @@
+ #include <asm/hardware.h>
+ #include <asm/mach/pci.h>
+ #include <asm/hardware/iop3xx.h>
++#include <asm/mach-types.h>
+
+ // #define DEBUG
+
+@@ -209,8 +210,11 @@ int iop3xx_pci_setup(int nr, struct pci_sys_data *sys)
+ res[1].flags = IORESOURCE_MEM;
+ request_resource(&iomem_resource, &res[1]);
+
+- sys->mem_offset = IOP3XX_PCI_LOWER_MEM_PA - IOP3XX_PCI_LOWER_MEM_BA;
+- sys->io_offset = IOP3XX_PCI_LOWER_IO_PA - IOP3XX_PCI_LOWER_IO_BA;
++ /*
++ * Use whatever translation is already setup.
++ */
++ sys->mem_offset = IOP3XX_PCI_LOWER_MEM_PA - *IOP3XX_OMWTVR0;
++ sys->io_offset = IOP3XX_PCI_LOWER_IO_PA - *IOP3XX_OIOWTVR;
+
+ sys->resource[0] = &res[0];
+ sys->resource[1] = &res[1];
+@@ -250,11 +254,11 @@ void __init iop3xx_atu_setup(void)
+ *IOP3XX_IATVR2 = PHYS_OFFSET;
+
+ /* Outbound window 0 */
+- *IOP3XX_OMWTVR0 = IOP3XX_PCI_LOWER_MEM_PA;
++ *IOP3XX_OMWTVR0 = IOP3XX_PCI_LOWER_MEM_BA;
+ *IOP3XX_OUMWTVR0 = 0;
+
+ /* Outbound window 1 */
+- *IOP3XX_OMWTVR1 = IOP3XX_PCI_LOWER_MEM_PA + IOP3XX_PCI_MEM_WINDOW_SIZE;
++ *IOP3XX_OMWTVR1 = IOP3XX_PCI_LOWER_MEM_BA + IOP3XX_PCI_MEM_WINDOW_SIZE;
+ *IOP3XX_OUMWTVR1 = 0;
+
+ /* BAR 3 ( Disabled ) */
+@@ -265,7 +269,7 @@ void __init iop3xx_atu_setup(void)
+
+ /* Setup the I/O Bar
+ */
+- *IOP3XX_OIOWTVR = IOP3XX_PCI_LOWER_IO_PA;;
++ *IOP3XX_OIOWTVR = IOP3XX_PCI_LOWER_IO_BA;
+
+ /* Enable inbound and outbound cycles
+ */
+@@ -322,34 +326,59 @@ void __init iop3xx_atu_disable(void)
+ /* Flag to determine whether the ATU is initialized and the PCI bus scanned */
+ int init_atu;
+
+-void __init iop3xx_pci_preinit(void)
++int iop3xx_get_init_atu(void) {
++ /* check if default has been overridden */
++ if (init_atu != IOP3XX_INIT_ATU_DEFAULT)
++ return init_atu;
++ else
++ return IOP3XX_INIT_ATU_DISABLE;
++}
++
++static void __init iop3xx_atu_debug(void)
+ {
+- if (iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE) {
+- iop3xx_atu_disable();
+- iop3xx_atu_setup();
+- }
++ DBG("PCI: Intel IOP3xx PCI init.\n");
++ DBG("PCI: Outbound memory window 0: PCI 0x%08x%08x\n",
++ *IOP3XX_OUMWTVR0, *IOP3XX_OMWTVR0);
++ DBG("PCI: Outbound memory window 1: PCI 0x%08x%08x\n",
++ *IOP3XX_OUMWTVR1, *IOP3XX_OMWTVR1);
++ DBG("PCI: Outbound IO window: PCI 0x%08x\n",
++ *IOP3XX_OIOWTVR);
++
++ DBG("PCI: Inbound memory window 0: PCI 0x%08x%08x 0x%08x -> 0x%08x\n",
++ *IOP3XX_IAUBAR0, *IOP3XX_IABAR0, *IOP3XX_IALR0, *IOP3XX_IATVR0);
++ DBG("PCI: Inbound memory window 1: PCI 0x%08x%08x 0x%08x\n",
++ *IOP3XX_IAUBAR1, *IOP3XX_IABAR1, *IOP3XX_IALR1);
++ DBG("PCI: Inbound memory window 2: PCI 0x%08x%08x 0x%08x -> 0x%08x\n",
++ *IOP3XX_IAUBAR2, *IOP3XX_IABAR2, *IOP3XX_IALR2, *IOP3XX_IATVR2);
++ DBG("PCI: Inbound memory window 3: PCI 0x%08x%08x 0x%08x -> 0x%08x\n",
++ *IOP3XX_IAUBAR3, *IOP3XX_IABAR3, *IOP3XX_IALR3, *IOP3XX_IATVR3);
++
++ DBG("PCI: Expansion ROM window: PCI 0x%08x%08x 0x%08x -> 0x%08x\n",
++ 0, *IOP3XX_ERBAR, *IOP3XX_ERLR, *IOP3XX_ERTVR);
+
+- DBG("PCI: Intel 803xx PCI init code.\n");
+ DBG("ATU: IOP3XX_ATUCMD=0x%04x\n", *IOP3XX_ATUCMD);
+- DBG("ATU: IOP3XX_OMWTVR0=0x%04x, IOP3XX_OIOWTVR=0x%04x\n",
+- *IOP3XX_OMWTVR0,
+- *IOP3XX_OIOWTVR);
+ DBG("ATU: IOP3XX_ATUCR=0x%08x\n", *IOP3XX_ATUCR);
+- DBG("ATU: IOP3XX_IABAR0=0x%08x IOP3XX_IALR0=0x%08x IOP3XX_IATVR0=%08x\n",
+- *IOP3XX_IABAR0, *IOP3XX_IALR0, *IOP3XX_IATVR0);
+- DBG("ATU: IOP3XX_OMWTVR0=0x%08x\n", *IOP3XX_OMWTVR0);
+- DBG("ATU: IOP3XX_IABAR1=0x%08x IOP3XX_IALR1=0x%08x\n",
+- *IOP3XX_IABAR1, *IOP3XX_IALR1);
+- DBG("ATU: IOP3XX_ERBAR=0x%08x IOP3XX_ERLR=0x%08x IOP3XX_ERTVR=%08x\n",
+- *IOP3XX_ERBAR, *IOP3XX_ERLR, *IOP3XX_ERTVR);
+- DBG("ATU: IOP3XX_IABAR2=0x%08x IOP3XX_IALR2=0x%08x IOP3XX_IATVR2=%08x\n",
+- *IOP3XX_IABAR2, *IOP3XX_IALR2, *IOP3XX_IATVR2);
+- DBG("ATU: IOP3XX_IABAR3=0x%08x IOP3XX_IALR3=0x%08x IOP3XX_IATVR3=%08x\n",
+- *IOP3XX_IABAR3, *IOP3XX_IALR3, *IOP3XX_IATVR3);
+
+ hook_fault_code(16+6, iop3xx_pci_abort, SIGBUS, "imprecise external abort");
+ }
+
++/* for platforms that might be host-bus-adapters */
++void __init iop3xx_pci_preinit_cond(void)
++{
++ if (iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE) {
++ iop3xx_atu_disable();
++ iop3xx_atu_setup();
++ iop3xx_atu_debug();
++ }
++}
++
++void __init iop3xx_pci_preinit(void)
++{
++ iop3xx_atu_disable();
++ iop3xx_atu_setup();
++ iop3xx_atu_debug();
++}
++
+ /* allow init_atu to be user overridden */
+ static int __init iop3xx_init_atu_setup(char *str)
+ {
+diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig
+index 03a65c0..bb6e127 100644
+--- a/arch/arm/plat-mxc/Kconfig
++++ b/arch/arm/plat-mxc/Kconfig
+@@ -4,7 +4,7 @@ menu "Freescale MXC Implementations"
+
+ choice
+ prompt "MXC/iMX System Type"
+- default 0
++ default ARCH_MX3
+
+ config ARCH_MX3
+ bool "MX3-based"
+diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
+index 66ad9c2..f96dc03 100644
+--- a/arch/arm/plat-mxc/Makefile
++++ b/arch/arm/plat-mxc/Makefile
+@@ -4,7 +4,3 @@
+
+ # Common support
+ obj-y := irq.o
+-
+-obj-m :=
+-obj-n :=
+-obj- :=
+diff --git a/arch/arm/plat-mxc/irq.c b/arch/arm/plat-mxc/irq.c
+index 87d253b..2ad5a69 100644
+--- a/arch/arm/plat-mxc/irq.c
++++ b/arch/arm/plat-mxc/irq.c
+@@ -19,21 +19,13 @@
+ #include <asm/mach/irq.h>
+ #include <asm/arch/common.h>
+
+-/*!
+- * Disable interrupt number "irq" in the AVIC
+- *
+- * @param irq interrupt source number
+- */
++/* Disable interrupt number "irq" in the AVIC */
+ static void mxc_mask_irq(unsigned int irq)
+ {
+ __raw_writel(irq, AVIC_INTDISNUM);
+ }
+
+-/*!
+- * Enable interrupt number "irq" in the AVIC
+- *
+- * @param irq interrupt source number
+- */
++/* Enable interrupt number "irq" in the AVIC */
+ static void mxc_unmask_irq(unsigned int irq)
+ {
+ __raw_writel(irq, AVIC_INTENNUM);
+@@ -45,7 +37,7 @@ static struct irq_chip mxc_avic_chip = {
+ .unmask = mxc_unmask_irq,
+ };
+
+-/*!
++/*
+ * This function initializes the AVIC hardware and disables all the
+ * interrupts. It registers the interrupt enable and disable functions
+ * to the kernel for each interrupt source.
+diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
+index 8f56c25..bc639a3 100644
+--- a/arch/arm/plat-omap/Makefile
++++ b/arch/arm/plat-omap/Makefile
+@@ -9,8 +9,6 @@ obj-m :=
+ obj-n :=
+ obj- :=
+
+-obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o
+-
+ # OCPI interconnect support for 1710, 1610 and 5912
+ obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
+
+diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
+index 0a60324..72d34a2 100644
+--- a/arch/arm/plat-omap/clock.c
++++ b/arch/arm/plat-omap/clock.c
+@@ -23,7 +23,6 @@
+ #include <linux/platform_device.h>
+
+ #include <asm/io.h>
+-#include <asm/semaphore.h>
+
+ #include <asm/arch/clock.h>
+
+@@ -304,6 +303,23 @@ void propagate_rate(struct clk * tclk)
+ }
+ }
+
++/**
++ * recalculate_root_clocks - recalculate and propagate all root clocks
++ *
++ * Recalculates all root clocks (clocks with no parent), which if the
++ * clock's .recalc is set correctly, should also propagate their rates.
++ * Called at init.
++ */
++void recalculate_root_clocks(void)
++{
++ struct clk *clkp;
++
++ list_for_each_entry(clkp, &clocks, node) {
++ if (unlikely(!clkp->parent) && likely((u32)clkp->recalc))
++ clkp->recalc(clkp);
++ }
++}
++
+ int clk_register(struct clk *clk)
+ {
+ if (clk == NULL || IS_ERR(clk))
+@@ -358,6 +374,30 @@ void clk_allow_idle(struct clk *clk)
+ }
+ EXPORT_SYMBOL(clk_allow_idle);
+
++void clk_enable_init_clocks(void)
++{
++ struct clk *clkp;
++
++ list_for_each_entry(clkp, &clocks, node) {
++ if (clkp->flags & ENABLE_ON_INIT)
++ clk_enable(clkp);
++ }
++}
++EXPORT_SYMBOL(clk_enable_init_clocks);
++
++#ifdef CONFIG_CPU_FREQ
++void clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&clockfw_lock, flags);
++ if (arch_clock->clk_init_cpufreq_table)
++ arch_clock->clk_init_cpufreq_table(table);
++ spin_unlock_irqrestore(&clockfw_lock, flags);
++}
++EXPORT_SYMBOL(clk_init_cpufreq_table);
++#endif
++
+ /*-------------------------------------------------------------------------*/
+
+ #ifdef CONFIG_OMAP_RESET_CLOCKS
+@@ -396,3 +436,4 @@ int __init clk_init(struct clk_functions * custom_clocks)
+
+ return 0;
+ }
++
+diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c
+index 4f0f9c4..bd1cef2 100644
+--- a/arch/arm/plat-omap/common.c
++++ b/arch/arm/plat-omap/common.c
+@@ -27,11 +27,16 @@
+ #include <asm/setup.h>
+
+ #include <asm/arch/board.h>
++#include <asm/arch/control.h>
+ #include <asm/arch/mux.h>
+ #include <asm/arch/fpga.h>
+
+ #include <asm/arch/clock.h>
+
++#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
++# include "../mach-omap2/sdrc.h"
++#endif
++
+ #define NO_LENGTH_CHECK 0xffffffff
+
+ unsigned char omap_bootloader_tag[512];
+@@ -171,8 +176,8 @@ console_initcall(omap_add_serial_console);
+
+ #if defined(CONFIG_ARCH_OMAP16XX)
+ #define TIMER_32K_SYNCHRONIZED 0xfffbc410
+-#elif defined(CONFIG_ARCH_OMAP24XX)
+-#define TIMER_32K_SYNCHRONIZED (OMAP24XX_32KSYNCT_BASE + 0x10)
++#elif defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
++#define TIMER_32K_SYNCHRONIZED (OMAP2_32KSYNCT_BASE + 0x10)
+ #endif
+
+ #ifdef TIMER_32K_SYNCHRONIZED
+@@ -193,12 +198,35 @@ static struct clocksource clocksource_32k = {
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ };
+
++/*
++ * Rounds down to nearest nsec.
++ */
++unsigned long long omap_32k_ticks_to_nsecs(unsigned long ticks_32k)
++{
++ return cyc2ns(&clocksource_32k, ticks_32k);
++}
++
++/*
++ * Returns current time from boot in nsecs. It's OK for this to wrap
++ * around for now, as it's just a relative time stamp.
++ */
++unsigned long long sched_clock(void)
++{
++ return omap_32k_ticks_to_nsecs(omap_32k_read());
++}
++
+ static int __init omap_init_clocksource_32k(void)
+ {
+ static char err[] __initdata = KERN_ERR
+ "%s: can't register clocksource!\n";
+
+- if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
++ if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
++ struct clk *sync_32k_ick;
++
++ sync_32k_ick = clk_get(NULL, "omap_32ksync_ick");
++ if (sync_32k_ick)
++ clk_enable(sync_32k_ick);
++
+ clocksource_32k.mult = clocksource_hz2mult(32768,
+ clocksource_32k.shift);
+
+@@ -210,3 +238,33 @@ static int __init omap_init_clocksource_32k(void)
+ arch_initcall(omap_init_clocksource_32k);
+
+ #endif /* TIMER_32K_SYNCHRONIZED */
++
++/* Global address base setup code */
++
++#if defined(CONFIG_ARCH_OMAP2420)
++void __init omap2_set_globals_242x(void)
++{
++ omap2_sdrc_base = OMAP2420_SDRC_BASE;
++ omap2_sms_base = OMAP2420_SMS_BASE;
++ omap_ctrl_base_set(OMAP2420_CTRL_BASE);
++}
++#endif
++
++#if defined(CONFIG_ARCH_OMAP2430)
++void __init omap2_set_globals_243x(void)
++{
++ omap2_sdrc_base = OMAP243X_SDRC_BASE;
++ omap2_sms_base = OMAP243X_SMS_BASE;
++ omap_ctrl_base_set(OMAP243X_CTRL_BASE);
++}
++#endif
++
++#if defined(CONFIG_ARCH_OMAP3430)
++void __init omap2_set_globals_343x(void)
++{
++ omap2_sdrc_base = OMAP343X_SDRC_BASE;
++ omap2_sms_base = OMAP343X_SMS_BASE;
++ omap_ctrl_base_set(OMAP343X_CTRL_BASE);
++}
++#endif
++
+diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
+index 8c78e4e..1903a34 100644
+--- a/arch/arm/plat-omap/gpio.c
++++ b/arch/arm/plat-omap/gpio.c
+@@ -136,7 +136,6 @@ struct gpio_bank {
+ u16 irq;
+ u16 virtual_irq_start;
+ int method;
+- u32 reserved_map;
+ #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+ u32 suspend_wakeup;
+ u32 saved_wakeup;
+@@ -149,7 +148,9 @@ struct gpio_bank {
+ u32 saved_fallingdetect;
+ u32 saved_risingdetect;
+ #endif
++ u32 level_mask;
+ spinlock_t lock;
++ struct gpio_chip chip;
+ };
+
+ #define METHOD_MPUIO 0
+@@ -538,10 +539,9 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,
+ bank->enabled_non_wakeup_gpios &= ~gpio_bit;
+ }
+
+- /*
+- * FIXME: Possibly do 'set_irq_handler(j, handle_level_irq)' if only
+- * level triggering requested.
+- */
++ bank->level_mask =
++ __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0) |
++ __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1);
+ }
+ #endif
+
+@@ -652,6 +652,12 @@ static int gpio_irq_type(unsigned irq, unsigned type)
+ irq_desc[irq].status |= type;
+ }
+ spin_unlock_irqrestore(&bank->lock, flags);
++
++ if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
++ __set_irq_handler_unlocked(irq, handle_level_irq);
++ else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
++ __set_irq_handler_unlocked(irq, handle_edge_irq);
++
+ return retval;
+ }
+
+@@ -903,19 +909,17 @@ int omap_request_gpio(int gpio)
+ {
+ struct gpio_bank *bank;
+ unsigned long flags;
++ int status;
+
+ if (check_gpio(gpio) < 0)
+ return -EINVAL;
+
++ status = gpio_request(gpio, NULL);
++ if (status < 0)
++ return status;
++
+ bank = get_gpio_bank(gpio);
+ spin_lock_irqsave(&bank->lock, flags);
+- if (unlikely(bank->reserved_map & (1 << get_gpio_index(gpio)))) {
+- printk(KERN_ERR "omap-gpio: GPIO %d is already reserved!\n", gpio);
+- dump_stack();
+- spin_unlock_irqrestore(&bank->lock, flags);
+- return -1;
+- }
+- bank->reserved_map |= (1 << get_gpio_index(gpio));
+
+ /* Set trigger to none. You need to enable the desired trigger with
+ * request_irq() or set_irq_type().
+@@ -945,10 +949,11 @@ void omap_free_gpio(int gpio)
+ return;
+ bank = get_gpio_bank(gpio);
+ spin_lock_irqsave(&bank->lock, flags);
+- if (unlikely(!(bank->reserved_map & (1 << get_gpio_index(gpio))))) {
++ if (unlikely(!gpiochip_is_requested(&bank->chip,
++ get_gpio_index(gpio)))) {
++ spin_unlock_irqrestore(&bank->lock, flags);
+ printk(KERN_ERR "omap-gpio: GPIO %d wasn't reserved!\n", gpio);
+ dump_stack();
+- spin_unlock_irqrestore(&bank->lock, flags);
+ return;
+ }
+ #ifdef CONFIG_ARCH_OMAP16XX
+@@ -965,9 +970,9 @@ void omap_free_gpio(int gpio)
+ __raw_writel(1 << get_gpio_index(gpio), reg);
+ }
+ #endif
+- bank->reserved_map &= ~(1 << get_gpio_index(gpio));
+ _reset_gpio(bank, gpio);
+ spin_unlock_irqrestore(&bank->lock, flags);
++ gpio_free(gpio);
+ }
+
+ /*
+@@ -1022,12 +1027,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+ isr &= 0x0000ffff;
+
+ if (cpu_class_is_omap2()) {
+- level_mask =
+- __raw_readl(bank->base +
+- OMAP24XX_GPIO_LEVELDETECT0) |
+- __raw_readl(bank->base +
+- OMAP24XX_GPIO_LEVELDETECT1);
+- level_mask &= enabled;
++ level_mask = bank->level_mask & enabled;
+ }
+
+ /* clear edge sensitive interrupts before handler(s) are
+@@ -1052,51 +1052,13 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+ gpio_irq = bank->virtual_irq_start;
+ for (; isr != 0; isr >>= 1, gpio_irq++) {
+ struct irq_desc *d;
+- int irq_mask;
++
+ if (!(isr & 1))
+ continue;
+ d = irq_desc + gpio_irq;
+- /* Don't run the handler if it's already running
+- * or was disabled lazely.
+- */
+- if (unlikely((d->depth ||
+- (d->status & IRQ_INPROGRESS)))) {
+- irq_mask = 1 <<
+- (gpio_irq - bank->virtual_irq_start);
+- /* The unmasking will be done by
+- * enable_irq in case it is disabled or
+- * after returning from the handler if
+- * it's already running.
+- */
+- _enable_gpio_irqbank(bank, irq_mask, 0);
+- if (!d->depth) {
+- /* Level triggered interrupts
+- * won't ever be reentered
+- */
+- BUG_ON(level_mask & irq_mask);
+- d->status |= IRQ_PENDING;
+- }
+- continue;
+- }
+
+ desc_handle_irq(gpio_irq, d);
+-
+- if (unlikely((d->status & IRQ_PENDING) && !d->depth)) {
+- irq_mask = 1 <<
+- (gpio_irq - bank->virtual_irq_start);
+- d->status &= ~IRQ_PENDING;
+- _enable_gpio_irqbank(bank, irq_mask, 1);
+- retrigger |= irq_mask;
+- }
+ }
+-
+- if (cpu_class_is_omap2()) {
+- /* clear level sensitive interrupts after handler(s) */
+- _enable_gpio_irqbank(bank, isr_saved & level_mask, 0);
+- _clear_gpio_irqbank(bank, isr_saved & level_mask);
+- _enable_gpio_irqbank(bank, isr_saved & level_mask, 1);
+- }
+-
+ }
+ /* if bank has any level sensitive GPIO pin interrupt
+ configured, we must unmask the bank interrupt only after
+@@ -1135,6 +1097,14 @@ static void gpio_unmask_irq(unsigned int irq)
+ {
+ unsigned int gpio = irq - IH_GPIO_BASE;
+ struct gpio_bank *bank = get_irq_chip_data(irq);
++ unsigned int irq_mask = 1 << get_gpio_index(gpio);
++
++ /* For level-triggered GPIOs, the clearing must be done after
++ * the HW source is cleared, thus after the handler has run */
++ if (bank->level_mask & irq_mask) {
++ _set_gpio_irqenable(bank, gpio, 0);
++ _clear_gpio_irqstatus(bank, gpio);
++ }
+
+ _set_gpio_irqenable(bank, gpio, 1);
+ }
+@@ -1266,6 +1236,53 @@ static inline void mpuio_init(void) {}
+
+ /*---------------------------------------------------------------------*/
+
++/* REVISIT these are stupid implementations! replace by ones that
++ * don't switch on METHOD_* and which mostly avoid spinlocks
++ */
++
++static int gpio_input(struct gpio_chip *chip, unsigned offset)
++{
++ struct gpio_bank *bank;
++ unsigned long flags;
++
++ bank = container_of(chip, struct gpio_bank, chip);
++ spin_lock_irqsave(&bank->lock, flags);
++ _set_gpio_direction(bank, offset, 1);
++ spin_unlock_irqrestore(&bank->lock, flags);
++ return 0;
++}
++
++static int gpio_get(struct gpio_chip *chip, unsigned offset)
++{
++ return omap_get_gpio_datain(chip->base + offset);
++}
++
++static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
++{
++ struct gpio_bank *bank;
++ unsigned long flags;
++
++ bank = container_of(chip, struct gpio_bank, chip);
++ spin_lock_irqsave(&bank->lock, flags);
++ _set_gpio_dataout(bank, offset, value);
++ _set_gpio_direction(bank, offset, 0);
++ spin_unlock_irqrestore(&bank->lock, flags);
++ return 0;
++}
++
++static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
++{
++ struct gpio_bank *bank;
++ unsigned long flags;
++
++ bank = container_of(chip, struct gpio_bank, chip);
++ spin_lock_irqsave(&bank->lock, flags);
++ _set_gpio_dataout(bank, offset, value);
++ spin_unlock_irqrestore(&bank->lock, flags);
++}
++
++/*---------------------------------------------------------------------*/
++
+ static int initialized;
+ #if !defined(CONFIG_ARCH_OMAP3)
+ static struct clk * gpio_ick;
+@@ -1293,6 +1310,7 @@ static struct lock_class_key gpio_lock_class;
+ static int __init _omap_gpio_init(void)
+ {
+ int i;
++ int gpio = 0;
+ struct gpio_bank *bank;
+ #if defined(CONFIG_ARCH_OMAP3)
+ char clk_name[11];
+@@ -1423,7 +1441,6 @@ static int __init _omap_gpio_init(void)
+ int j, gpio_count = 16;
+
+ bank = &gpio_bank[i];
+- bank->reserved_map = 0;
+ bank->base = IO_ADDRESS(bank->base);
+ spin_lock_init(&bank->lock);
+ if (bank_is_mpuio(bank))
+@@ -1461,6 +1478,26 @@ static int __init _omap_gpio_init(void)
+ gpio_count = 32;
+ }
+ #endif
++
++ /* REVISIT eventually switch from OMAP-specific gpio structs
++ * over to the generic ones
++ */
++ bank->chip.direction_input = gpio_input;
++ bank->chip.get = gpio_get;
++ bank->chip.direction_output = gpio_output;
++ bank->chip.set = gpio_set;
++ if (bank_is_mpuio(bank)) {
++ bank->chip.label = "mpuio";
++ bank->chip.base = OMAP_MPUIO(0);
++ } else {
++ bank->chip.label = "gpio";
++ bank->chip.base = gpio;
++ gpio += gpio_count;
++ }
++ bank->chip.ngpio = gpio_count;
++
++ gpiochip_add(&bank->chip);
++
+ for (j = bank->virtual_irq_start;
+ j < bank->virtual_irq_start + gpio_count; j++) {
+ lockdep_set_class(&irq_desc[j].lock, &gpio_lock_class);
+@@ -1757,8 +1794,10 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
+
+ for (j = 0; j < bankwidth; j++, gpio++, mask <<= 1) {
+ unsigned irq, value, is_in, irqstat;
++ const char *label;
+
+- if (!(bank->reserved_map & mask))
++ label = gpiochip_is_requested(&bank->chip, j);
++ if (!label)
+ continue;
+
+ irq = bank->virtual_irq_start + j;
+@@ -1766,13 +1805,16 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
+ is_in = gpio_is_input(bank, mask);
+
+ if (bank_is_mpuio(bank))
+- seq_printf(s, "MPUIO %2d: ", j);
++ seq_printf(s, "MPUIO %2d ", j);
+ else
+- seq_printf(s, "GPIO %3d: ", gpio);
+- seq_printf(s, "%s %s",
++ seq_printf(s, "GPIO %3d ", gpio);
++ seq_printf(s, "(%10s): %s %s",
++ label,
+ is_in ? "in " : "out",
+ value ? "hi" : "lo");
+
++/* FIXME for at least omap2, show pullup/pulldown state */
++
+ irqstat = irq_desc[irq].status;
+ if (is_in && ((bank->suspend_wakeup & mask)
+ || irqstat & IRQ_TYPE_SENSE_MASK)) {
+@@ -1795,10 +1837,10 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
+ trigger = "high";
+ break;
+ case IRQ_TYPE_NONE:
+- trigger = "(unspecified)";
++ trigger = "(?)";
+ break;
+ }
+- seq_printf(s, ", irq-%d %s%s",
++ seq_printf(s, ", irq-%d %-8s%s",
+ irq, trigger,
+ (bank->suspend_wakeup & mask)
+ ? " wakeup" : "");
+diff --git a/arch/arm/plat-omap/mux.c b/arch/arm/plat-omap/mux.c
+index 75211f2..6f3f459 100644
+--- a/arch/arm/plat-omap/mux.c
++++ b/arch/arm/plat-omap/mux.c
+@@ -3,9 +3,9 @@
+ *
+ * Utility to set the Omap MUX and PULL_DWN registers from a table in mux.h
+ *
+- * Copyright (C) 2003 - 2005 Nokia Corporation
++ * Copyright (C) 2003 - 2008 Nokia Corporation
+ *
+- * Written by Tony Lindgren <tony.lindgren at nokia.com>
++ * Written by Tony Lindgren
+ *
+ * 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
+@@ -32,21 +32,17 @@
+
+ #ifdef CONFIG_OMAP_MUX
+
+-#define OMAP24XX_L4_BASE 0x48000000
+-#define OMAP24XX_PULL_ENA (1 << 3)
+-#define OMAP24XX_PULL_UP (1 << 4)
++static struct omap_mux_cfg *mux_cfg;
+
+-static struct pin_config * pin_table;
+-static unsigned long pin_table_sz;
+-
+-extern struct pin_config * omap730_pins;
+-extern struct pin_config * omap1xxx_pins;
+-extern struct pin_config * omap24xx_pins;
+-
+-int __init omap_mux_register(struct pin_config * pins, unsigned long size)
++int __init omap_mux_register(struct omap_mux_cfg *arch_mux_cfg)
+ {
+- pin_table = pins;
+- pin_table_sz = size;
++ if (!arch_mux_cfg || !arch_mux_cfg->pins || arch_mux_cfg->size == 0
++ || !arch_mux_cfg->cfg_reg) {
++ printk(KERN_ERR "Invalid pin table\n");
++ return -EINVAL;
++ }
++
++ mux_cfg = arch_mux_cfg;
+
+ return 0;
+ }
+@@ -56,152 +52,26 @@ int __init omap_mux_register(struct pin_config * pins, unsigned long size)
+ */
+ int __init_or_module omap_cfg_reg(const unsigned long index)
+ {
+- static DEFINE_SPINLOCK(mux_spin_lock);
+-
+- unsigned long flags;
+- struct pin_config *cfg;
+- unsigned int reg_orig = 0, reg = 0, pu_pd_orig = 0, pu_pd = 0,
+- pull_orig = 0, pull = 0;
+- unsigned int mask, warn = 0;
++ struct pin_config *reg;
+
+- if (!pin_table)
+- BUG();
++ if (mux_cfg == NULL) {
++ printk(KERN_ERR "Pin mux table not initialized\n");
++ return -ENODEV;
++ }
+
+- if (index >= pin_table_sz) {
++ if (index >= mux_cfg->size) {
+ printk(KERN_ERR "Invalid pin mux index: %lu (%lu)\n",
+- index, pin_table_sz);
++ index, mux_cfg->size);
+ dump_stack();
+ return -ENODEV;
+ }
+
+- cfg = (struct pin_config *)&pin_table[index];
+- if (cpu_is_omap24xx()) {
+- u8 reg = 0;
+-
+- reg |= cfg->mask & 0x7;
+- if (cfg->pull_val)
+- reg |= OMAP24XX_PULL_ENA;
+- if(cfg->pu_pd_val)
+- reg |= OMAP24XX_PULL_UP;
+-#if defined(CONFIG_OMAP_MUX_DEBUG) || defined(CONFIG_OMAP_MUX_WARNINGS)
+- {
+- u8 orig = omap_readb(OMAP24XX_L4_BASE + cfg->mux_reg);
+- u8 debug = 0;
+-
+-#ifdef CONFIG_OMAP_MUX_DEBUG
+- debug = cfg->debug;
+-#endif
+- warn = (orig != reg);
+- if (debug || warn)
+- printk("MUX: setup %s (0x%08x): 0x%02x -> 0x%02x\n",
+- cfg->name,
+- OMAP24XX_L4_BASE + cfg->mux_reg,
+- orig, reg);
+- }
+-#endif
+- omap_writeb(reg, OMAP24XX_L4_BASE + cfg->mux_reg);
++ reg = (struct pin_config *)&mux_cfg->pins[index];
+
+- return 0;
+- }
+-
+- /* Check the mux register in question */
+- if (cfg->mux_reg) {
+- unsigned tmp1, tmp2;
+-
+- spin_lock_irqsave(&mux_spin_lock, flags);
+- reg_orig = omap_readl(cfg->mux_reg);
+-
+- /* The mux registers always seem to be 3 bits long */
+- mask = (0x7 << cfg->mask_offset);
+- tmp1 = reg_orig & mask;
+- reg = reg_orig & ~mask;
+-
+- tmp2 = (cfg->mask << cfg->mask_offset);
+- reg |= tmp2;
+-
+- if (tmp1 != tmp2)
+- warn = 1;
+-
+- omap_writel(reg, cfg->mux_reg);
+- spin_unlock_irqrestore(&mux_spin_lock, flags);
+- }
+-
+- /* Check for pull up or pull down selection on 1610 */
+- if (!cpu_is_omap15xx()) {
+- if (cfg->pu_pd_reg && cfg->pull_val) {
+- spin_lock_irqsave(&mux_spin_lock, flags);
+- pu_pd_orig = omap_readl(cfg->pu_pd_reg);
+- mask = 1 << cfg->pull_bit;
+-
+- if (cfg->pu_pd_val) {
+- if (!(pu_pd_orig & mask))
+- warn = 1;
+- /* Use pull up */
+- pu_pd = pu_pd_orig | mask;
+- } else {
+- if (pu_pd_orig & mask)
+- warn = 1;
+- /* Use pull down */
+- pu_pd = pu_pd_orig & ~mask;
+- }
+- omap_writel(pu_pd, cfg->pu_pd_reg);
+- spin_unlock_irqrestore(&mux_spin_lock, flags);
+- }
+- }
+-
+- /* Check for an associated pull down register */
+- if (cfg->pull_reg) {
+- spin_lock_irqsave(&mux_spin_lock, flags);
+- pull_orig = omap_readl(cfg->pull_reg);
+- mask = 1 << cfg->pull_bit;
+-
+- if (cfg->pull_val) {
+- if (pull_orig & mask)
+- warn = 1;
+- /* Low bit = pull enabled */
+- pull = pull_orig & ~mask;
+- } else {
+- if (!(pull_orig & mask))
+- warn = 1;
+- /* High bit = pull disabled */
+- pull = pull_orig | mask;
+- }
+-
+- omap_writel(pull, cfg->pull_reg);
+- spin_unlock_irqrestore(&mux_spin_lock, flags);
+- }
+-
+- if (warn) {
+-#ifdef CONFIG_OMAP_MUX_WARNINGS
+- printk(KERN_WARNING "MUX: initialized %s\n", cfg->name);
+-#endif
+- }
+-
+-#ifdef CONFIG_OMAP_MUX_DEBUG
+- if (cfg->debug || warn) {
+- printk("MUX: Setting register %s\n", cfg->name);
+- printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n",
+- cfg->mux_reg_name, cfg->mux_reg, reg_orig, reg);
+-
+- if (!cpu_is_omap15xx()) {
+- if (cfg->pu_pd_reg && cfg->pull_val) {
+- printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n",
+- cfg->pu_pd_name, cfg->pu_pd_reg,
+- pu_pd_orig, pu_pd);
+- }
+- }
+-
+- if (cfg->pull_reg)
+- printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n",
+- cfg->pull_name, cfg->pull_reg, pull_orig, pull);
+- }
+-#endif
++ if (!mux_cfg->cfg_reg)
++ return -ENODEV;
+
+-#ifdef CONFIG_OMAP_MUX_ERRORS
+- return warn ? -ETXTBSY : 0;
+-#else
+- return 0;
+-#endif
++ return mux_cfg->cfg_reg(reg);
+ }
+ EXPORT_SYMBOL(omap_cfg_reg);
+ #else
+diff --git a/arch/arm/plat-omap/timer32k.c b/arch/arm/plat-omap/timer32k.c
+deleted file mode 100644
+index ea76f19..0000000
+--- a/arch/arm/plat-omap/timer32k.c
++++ /dev/null
+@@ -1,269 +0,0 @@
+-/*
+- * linux/arch/arm/plat-omap/timer32k.c
+- *
+- * OMAP 32K Timer
+- *
+- * Copyright (C) 2004 - 2005 Nokia Corporation
+- * Partial timer rewrite and additional dynamic tick timer support by
+- * Tony Lindgen <tony at atomide.com> and
+- * Tuukka Tikkanen <tuukka.tikkanen at elektrobit.com>
+- * OMAP Dual-mode timer framework support by Timo Teras
+- *
+- * MPU timer code based on the older MPU timer code for OMAP
+- * Copyright (C) 2000 RidgeRun, Inc.
+- * Author: Greg Lonnon <glonnon at ridgerun.com>
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the
+- * Free Software Foundation; either version 2 of the License, or (at your
+- * option) any later version.
+- *
+- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/delay.h>
+-#include <linux/interrupt.h>
+-#include <linux/sched.h>
+-#include <linux/spinlock.h>
+-#include <linux/err.h>
+-#include <linux/clk.h>
+-#include <linux/clocksource.h>
+-#include <linux/clockchips.h>
+-
+-#include <asm/system.h>
+-#include <asm/hardware.h>
+-#include <asm/io.h>
+-#include <asm/leds.h>
+-#include <asm/irq.h>
+-#include <asm/mach/irq.h>
+-#include <asm/mach/time.h>
+-#include <asm/arch/dmtimer.h>
+-
+-struct sys_timer omap_timer;
+-
+-/*
+- * ---------------------------------------------------------------------------
+- * 32KHz OS timer
+- *
+- * This currently works only on 16xx, as 1510 does not have the continuous
+- * 32KHz synchronous timer. The 32KHz synchronous timer is used to keep track
+- * of time in addition to the 32KHz OS timer. Using only the 32KHz OS timer
+- * on 1510 would be possible, but the timer would not be as accurate as
+- * with the 32KHz synchronized timer.
+- * ---------------------------------------------------------------------------
+- */
+-
+-#if defined(CONFIG_ARCH_OMAP16XX)
+-#define TIMER_32K_SYNCHRONIZED 0xfffbc410
+-#elif defined(CONFIG_ARCH_OMAP24XX)
+-#define TIMER_32K_SYNCHRONIZED (OMAP24XX_32KSYNCT_BASE + 0x10)
+-#else
+-#error OMAP 32KHz timer does not currently work on 15XX!
+-#endif
+-
+-/* 16xx specific defines */
+-#define OMAP1_32K_TIMER_BASE 0xfffb9000
+-#define OMAP1_32K_TIMER_CR 0x08
+-#define OMAP1_32K_TIMER_TVR 0x00
+-#define OMAP1_32K_TIMER_TCR 0x04
+-
+-#define OMAP_32K_TICKS_PER_SEC (32768)
+-
+-/*
+- * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1
+- * so with HZ = 128, TVR = 255.
+- */
+-#define OMAP_32K_TIMER_TICK_PERIOD ((OMAP_32K_TICKS_PER_SEC / HZ) - 1)
+-
+-#define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate) \
+- (((nr_jiffies) * (clock_rate)) / HZ)
+-
+-#if defined(CONFIG_ARCH_OMAP1)
+-
+-static inline void omap_32k_timer_write(int val, int reg)
+-{
+- omap_writew(val, OMAP1_32K_TIMER_BASE + reg);
+-}
+-
+-static inline unsigned long omap_32k_timer_read(int reg)
+-{
+- return omap_readl(OMAP1_32K_TIMER_BASE + reg) & 0xffffff;
+-}
+-
+-static inline void omap_32k_timer_start(unsigned long load_val)
+-{
+- if (!load_val)
+- load_val = 1;
+- omap_32k_timer_write(load_val, OMAP1_32K_TIMER_TVR);
+- omap_32k_timer_write(0x0f, OMAP1_32K_TIMER_CR);
+-}
+-
+-static inline void omap_32k_timer_stop(void)
+-{
+- omap_32k_timer_write(0x0, OMAP1_32K_TIMER_CR);
+-}
+-
+-#define omap_32k_timer_ack_irq()
+-
+-#elif defined(CONFIG_ARCH_OMAP2)
+-
+-static struct omap_dm_timer *gptimer;
+-
+-static inline void omap_32k_timer_start(unsigned long load_val)
+-{
+- omap_dm_timer_set_load(gptimer, 1, 0xffffffff - load_val);
+- omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW);
+- omap_dm_timer_start(gptimer);
+-}
+-
+-static inline void omap_32k_timer_stop(void)
+-{
+- omap_dm_timer_stop(gptimer);
+-}
+-
+-static inline void omap_32k_timer_ack_irq(void)
+-{
+- u32 status = omap_dm_timer_read_status(gptimer);
+- omap_dm_timer_write_status(gptimer, status);
+-}
+-
+-#endif
+-
+-static void omap_32k_timer_set_mode(enum clock_event_mode mode,
+- struct clock_event_device *evt)
+-{
+- omap_32k_timer_stop();
+-
+- switch (mode) {
+- case CLOCK_EVT_MODE_PERIODIC:
+- omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
+- break;
+- case CLOCK_EVT_MODE_ONESHOT:
+- case CLOCK_EVT_MODE_UNUSED:
+- case CLOCK_EVT_MODE_SHUTDOWN:
+- break;
+- case CLOCK_EVT_MODE_RESUME:
+- break;
+- }
+-}
+-
+-static struct clock_event_device clockevent_32k_timer = {
+- .name = "32k-timer",
+- .features = CLOCK_EVT_FEAT_PERIODIC,
+- .shift = 32,
+- .set_mode = omap_32k_timer_set_mode,
+-};
+-
+-/*
+- * The 32KHz synchronized timer is an additional timer on 16xx.
+- * It is always running.
+- */
+-static inline unsigned long omap_32k_sync_timer_read(void)
+-{
+- return omap_readl(TIMER_32K_SYNCHRONIZED);
+-}
+-
+-/*
+- * Rounds down to nearest usec. Note that this will overflow for larger values.
+- */
+-static inline unsigned long omap_32k_ticks_to_usecs(unsigned long ticks_32k)
+-{
+- return (ticks_32k * 5*5*5*5*5*5) >> 9;
+-}
+-
+-/*
+- * Rounds down to nearest nsec.
+- */
+-static inline unsigned long long
+-omap_32k_ticks_to_nsecs(unsigned long ticks_32k)
+-{
+- return (unsigned long long) ticks_32k * 1000 * 5*5*5*5*5*5 >> 9;
+-}
+-
+-/*
+- * Returns current time from boot in nsecs. It's OK for this to wrap
+- * around for now, as it's just a relative time stamp.
+- */
+-unsigned long long sched_clock(void)
+-{
+- return omap_32k_ticks_to_nsecs(omap_32k_sync_timer_read());
+-}
+-
+-static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id)
+-{
+- struct clock_event_device *evt = &clockevent_32k_timer;
+- omap_32k_timer_ack_irq();
+-
+- evt->event_handler(evt);
+-
+- return IRQ_HANDLED;
+-}
+-
+-static struct irqaction omap_32k_timer_irq = {
+- .name = "32KHz timer",
+- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+- .handler = omap_32k_timer_interrupt,
+-};
+-
+-static __init void omap_init_32k_timer(void)
+-{
+- if (cpu_class_is_omap1())
+- setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
+-
+-#ifdef CONFIG_ARCH_OMAP2
+- /* REVISIT: Check 24xx TIOCP_CFG settings after idle works */
+- if (cpu_is_omap24xx()) {
+- gptimer = omap_dm_timer_request_specific(1);
+- BUG_ON(gptimer == NULL);
+-
+- omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_32_KHZ);
+- setup_irq(omap_dm_timer_get_irq(gptimer), &omap_32k_timer_irq);
+- omap_dm_timer_set_int_enable(gptimer,
+- OMAP_TIMER_INT_CAPTURE | OMAP_TIMER_INT_OVERFLOW |
+- OMAP_TIMER_INT_MATCH);
+- }
+-#endif
+-
+- clockevent_32k_timer.mult = div_sc(OMAP_32K_TICKS_PER_SEC,
+- NSEC_PER_SEC,
+- clockevent_32k_timer.shift);
+- clockevent_32k_timer.max_delta_ns =
+- clockevent_delta2ns(0xfffffffe, &clockevent_32k_timer);
+- clockevent_32k_timer.min_delta_ns =
+- clockevent_delta2ns(1, &clockevent_32k_timer);
+-
+- clockevent_32k_timer.cpumask = cpumask_of_cpu(0);
+- clockevents_register_device(&clockevent_32k_timer);
+-}
+-
+-/*
+- * ---------------------------------------------------------------------------
+- * Timer initialization
+- * ---------------------------------------------------------------------------
+- */
+-static void __init omap_timer_init(void)
+-{
+-#ifdef CONFIG_OMAP_DM_TIMER
+- omap_dm_timer_init();
+-#endif
+- omap_init_32k_timer();
+-}
+-
+-struct sys_timer omap_timer = {
+- .init = omap_timer_init,
+-};
+diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c
+index a5aedf9..a619475 100644
+--- a/arch/arm/plat-omap/usb.c
++++ b/arch/arm/plat-omap/usb.c
+@@ -33,6 +33,7 @@
+ #include <asm/system.h>
+ #include <asm/hardware.h>
+
++#include <asm/arch/control.h>
+ #include <asm/arch/mux.h>
+ #include <asm/arch/usb.h>
+ #include <asm/arch/board.h>
+@@ -76,7 +77,7 @@
+
+ /*-------------------------------------------------------------------------*/
+
+-#ifdef CONFIG_ARCH_OMAP_OTG
++#if defined(CONFIG_ARCH_OMAP_OTG) || defined(CONFIG_USB_MUSB_OTG)
+
+ static struct otg_transceiver *xceiv;
+
+@@ -110,12 +111,48 @@ EXPORT_SYMBOL(otg_set_transceiver);
+
+ #if defined(CONFIG_ARCH_OMAP_OTG) || defined(CONFIG_ARCH_OMAP15XX)
+
++static void omap2_usb_devconf_clear(u8 port, u32 mask)
++{
++ u32 r;
++
++ r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
++ r &= ~USBTXWRMODEI(port, mask);
++ omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0);
++}
++
++static void omap2_usb_devconf_set(u8 port, u32 mask)
++{
++ u32 r;
++
++ r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
++ r |= USBTXWRMODEI(port, mask);
++ omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0);
++}
++
++static void omap2_usb2_disable_5pinbitll(void)
++{
++ u32 r;
++
++ r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
++ r &= ~(USBTXWRMODEI(2, USB_BIDIR_TLL) | USBT2TLL5PI);
++ omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0);
++}
++
++static void omap2_usb2_enable_5pinunitll(void)
++{
++ u32 r;
++
++ r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
++ r |= USBTXWRMODEI(2, USB_UNIDIR_TLL) | USBT2TLL5PI;
++ omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0);
++}
++
+ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device)
+ {
+ u32 syscon1 = 0;
+
+ if (cpu_is_omap24xx())
+- CONTROL_DEVCONF_REG &= ~USBT0WRMODEI(USB_BIDIR_TLL);
++ omap2_usb_devconf_clear(0, USB_BIDIR_TLL);
+
+ if (nwires == 0) {
+ if (cpu_class_is_omap1() && !cpu_is_omap15xx()) {
+@@ -187,19 +224,19 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device)
+ case 3:
+ syscon1 = 2;
+ if (cpu_is_omap24xx())
+- CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_BIDIR);
++ omap2_usb_devconf_set(0, USB_BIDIR);
+ break;
+ case 4:
+ syscon1 = 1;
+ if (cpu_is_omap24xx())
+- CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_BIDIR);
++ omap2_usb_devconf_set(0, USB_BIDIR);
+ break;
+ case 6:
+ syscon1 = 3;
+ if (cpu_is_omap24xx()) {
+ omap_cfg_reg(J19_24XX_USB0_VP);
+ omap_cfg_reg(K20_24XX_USB0_VM);
+- CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_UNIDIR);
++ omap2_usb_devconf_set(0, USB_UNIDIR);
+ } else {
+ omap_cfg_reg(AA9_USB0_VP);
+ omap_cfg_reg(R9_USB0_VM);
+@@ -220,7 +257,7 @@ static u32 __init omap_usb1_init(unsigned nwires)
+ if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6)
+ USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB1_UNI_R;
+ if (cpu_is_omap24xx())
+- CONTROL_DEVCONF_REG &= ~USBT1WRMODEI(USB_BIDIR_TLL);
++ omap2_usb_devconf_clear(1, USB_BIDIR_TLL);
+
+ if (nwires == 0)
+ return 0;
+@@ -261,17 +298,17 @@ static u32 __init omap_usb1_init(unsigned nwires)
+ * this TLL link is not using DP/DM
+ */
+ syscon1 = 1;
+- CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR_TLL);
++ omap2_usb_devconf_set(1, USB_BIDIR_TLL);
+ break;
+ case 3:
+ syscon1 = 2;
+ if (cpu_is_omap24xx())
+- CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR);
++ omap2_usb_devconf_set(1, USB_BIDIR);
+ break;
+ case 4:
+ syscon1 = 1;
+ if (cpu_is_omap24xx())
+- CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR);
++ omap2_usb_devconf_set(1, USB_BIDIR);
+ break;
+ case 6:
+ if (cpu_is_omap24xx())
+@@ -295,8 +332,7 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup)
+ u32 syscon1 = 0;
+
+ if (cpu_is_omap24xx()) {
+- CONTROL_DEVCONF_REG &= ~(USBT2WRMODEI(USB_BIDIR_TLL)
+- | USBT2TLL5PI);
++ omap2_usb2_disable_5pinbitll();
+ alt_pingroup = 0;
+ }
+
+@@ -343,17 +379,17 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup)
+ * this TLL link is not using DP/DM
+ */
+ syscon1 = 1;
+- CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR_TLL);
++ omap2_usb_devconf_set(2, USB_BIDIR_TLL);
+ break;
+ case 3:
+ syscon1 = 2;
+ if (cpu_is_omap24xx())
+- CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR);
++ omap2_usb_devconf_set(2, USB_BIDIR);
+ break;
+ case 4:
+ syscon1 = 1;
+ if (cpu_is_omap24xx())
+- CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR);
++ omap2_usb_devconf_set(2, USB_BIDIR);
+ break;
+ case 5:
+ if (!cpu_is_omap24xx())
+@@ -364,8 +400,7 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup)
+ * set up OTG_SYSCON2.HMC_TLL{ATTACH,SPEED}
+ */
+ syscon1 = 3;
+- CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_UNIDIR_TLL)
+- | USBT2TLL5PI;
++ omap2_usb2_enable_5pinunitll();
+ break;
+ case 6:
+ if (cpu_is_omap24xx())
+diff --git a/arch/arm/plat-orion/Makefile b/arch/arm/plat-orion/Makefile
+new file mode 100644
+index 0000000..198f3dd
+--- /dev/null
++++ b/arch/arm/plat-orion/Makefile
+@@ -0,0 +1,8 @@
++#
++# Makefile for the linux kernel.
++#
++
++obj-y := irq.o pcie.o time.o
++obj-m :=
++obj-n :=
++obj- :=
+diff --git a/arch/arm/plat-orion/irq.c b/arch/arm/plat-orion/irq.c
+new file mode 100644
+index 0000000..c5b669d
+--- /dev/null
++++ b/arch/arm/plat-orion/irq.c
+@@ -0,0 +1,64 @@
++/*
++ * arch/arm/plat-orion/irq.c
++ *
++ * Marvell Orion SoC IRQ handling.
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/irq.h>
++#include <linux/io.h>
++#include <asm/plat-orion/irq.h>
++
++static void orion_irq_mask(u32 irq)
++{
++ void __iomem *maskaddr = get_irq_chip_data(irq);
++ u32 mask;
++
++ mask = readl(maskaddr);
++ mask &= ~(1 << (irq & 31));
++ writel(mask, maskaddr);
++}
++
++static void orion_irq_unmask(u32 irq)
++{
++ void __iomem *maskaddr = get_irq_chip_data(irq);
++ u32 mask;
++
++ mask = readl(maskaddr);
++ mask |= 1 << (irq & 31);
++ writel(mask, maskaddr);
++}
++
++static struct irq_chip orion_irq_chip = {
++ .name = "orion_irq",
++ .ack = orion_irq_mask,
++ .mask = orion_irq_mask,
++ .unmask = orion_irq_unmask,
++};
++
++void __init orion_irq_init(unsigned int irq_start, void __iomem *maskaddr)
++{
++ unsigned int i;
++
++ /*
++ * Mask all interrupts initially.
++ */
++ writel(0, maskaddr);
++
++ /*
++ * Register IRQ sources.
++ */
++ for (i = 0; i < 32; i++) {
++ unsigned int irq = irq_start + i;
++
++ set_irq_chip(irq, &orion_irq_chip);
++ set_irq_chip_data(irq, maskaddr);
++ set_irq_handler(irq, handle_level_irq);
++ set_irq_flags(irq, IRQF_VALID);
++ }
++}
+diff --git a/arch/arm/plat-orion/pcie.c b/arch/arm/plat-orion/pcie.c
+new file mode 100644
+index 0000000..abfda53
+--- /dev/null
++++ b/arch/arm/plat-orion/pcie.c
+@@ -0,0 +1,245 @@
++/*
++ * arch/arm/plat-orion/pcie.c
++ *
++ * Marvell Orion SoC PCIe handling.
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/mbus.h>
++#include <asm/mach/pci.h>
++#include <asm/plat-orion/pcie.h>
++
++/*
++ * PCIe unit register offsets.
++ */
++#define PCIE_DEV_ID_OFF 0x0000
++#define PCIE_CMD_OFF 0x0004
++#define PCIE_DEV_REV_OFF 0x0008
++#define PCIE_BAR_LO_OFF(n) (0x0010 + ((n) << 3))
++#define PCIE_BAR_HI_OFF(n) (0x0014 + ((n) << 3))
++#define PCIE_HEADER_LOG_4_OFF 0x0128
++#define PCIE_BAR_CTRL_OFF(n) (0x1804 + ((n - 1) * 4))
++#define PCIE_WIN04_CTRL_OFF(n) (0x1820 + ((n) << 4))
++#define PCIE_WIN04_BASE_OFF(n) (0x1824 + ((n) << 4))
++#define PCIE_WIN04_REMAP_OFF(n) (0x182c + ((n) << 4))
++#define PCIE_WIN5_CTRL_OFF 0x1880
++#define PCIE_WIN5_BASE_OFF 0x1884
++#define PCIE_WIN5_REMAP_OFF 0x188c
++#define PCIE_CONF_ADDR_OFF 0x18f8
++#define PCIE_CONF_ADDR_EN 0x80000000
++#define PCIE_CONF_REG(r) ((((r) & 0xf00) << 16) | ((r) & 0xfc))
++#define PCIE_CONF_BUS(b) (((b) & 0xff) << 16)
++#define PCIE_CONF_DEV(d) (((d) & 0x1f) << 11)
++#define PCIE_CONF_FUNC(f) (((f) & 0x3) << 8)
++#define PCIE_CONF_DATA_OFF 0x18fc
++#define PCIE_MASK_OFF 0x1910
++#define PCIE_CTRL_OFF 0x1a00
++#define PCIE_STAT_OFF 0x1a04
++#define PCIE_STAT_DEV_OFFS 20
++#define PCIE_STAT_DEV_MASK 0x1f
++#define PCIE_STAT_BUS_OFFS 8
++#define PCIE_STAT_BUS_MASK 0xff
++#define PCIE_STAT_LINK_DOWN 1
++
++
++u32 __init orion_pcie_dev_id(void __iomem *base)
++{
++ return readl(base + PCIE_DEV_ID_OFF) >> 16;
++}
++
++u32 __init orion_pcie_rev(void __iomem *base)
++{
++ return readl(base + PCIE_DEV_REV_OFF) & 0xff;
++}
++
++int orion_pcie_link_up(void __iomem *base)
++{
++ return !(readl(base + PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN);
++}
++
++int orion_pcie_get_local_bus_nr(void __iomem *base)
++{
++ u32 stat = readl(base + PCIE_STAT_OFF);
++
++ return (stat >> PCIE_STAT_BUS_OFFS) & PCIE_STAT_BUS_MASK;
++}
++
++void __init orion_pcie_set_local_bus_nr(void __iomem *base, int nr)
++{
++ u32 stat;
++
++ stat = readl(base + PCIE_STAT_OFF);
++ stat &= ~(PCIE_STAT_BUS_MASK << PCIE_STAT_BUS_OFFS);
++ stat |= nr << PCIE_STAT_BUS_OFFS;
++ writel(stat, base + PCIE_STAT_OFF);
++}
++
++/*
++ * Setup PCIE BARs and Address Decode Wins:
++ * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
++ * WIN[0-3] -> DRAM bank[0-3]
++ */
++static void __init orion_pcie_setup_wins(void __iomem *base,
++ struct mbus_dram_target_info *dram)
++{
++ u32 size;
++ int i;
++
++ /*
++ * First, disable and clear BARs and windows.
++ */
++ for (i = 1; i <= 2; i++) {
++ writel(0, base + PCIE_BAR_CTRL_OFF(i));
++ writel(0, base + PCIE_BAR_LO_OFF(i));
++ writel(0, base + PCIE_BAR_HI_OFF(i));
++ }
++
++ for (i = 0; i < 5; i++) {
++ writel(0, base + PCIE_WIN04_CTRL_OFF(i));
++ writel(0, base + PCIE_WIN04_BASE_OFF(i));
++ writel(0, base + PCIE_WIN04_REMAP_OFF(i));
++ }
++
++ writel(0, base + PCIE_WIN5_CTRL_OFF);
++ writel(0, base + PCIE_WIN5_BASE_OFF);
++ writel(0, base + PCIE_WIN5_REMAP_OFF);
++
++ /*
++ * Setup windows for DDR banks. Count total DDR size on the fly.
++ */
++ size = 0;
++ for (i = 0; i < dram->num_cs; i++) {
++ struct mbus_dram_window *cs = dram->cs + i;
++
++ writel(cs->base & 0xffff0000, base + PCIE_WIN04_BASE_OFF(i));
++ writel(0, base + PCIE_WIN04_REMAP_OFF(i));
++ writel(((cs->size - 1) & 0xffff0000) |
++ (cs->mbus_attr << 8) |
++ (dram->mbus_dram_target_id << 4) | 1,
++ base + PCIE_WIN04_CTRL_OFF(i));
++
++ size += cs->size;
++ }
++
++ /*
++ * Setup BAR[1] to all DRAM banks.
++ */
++ writel(dram->cs[0].base, base + PCIE_BAR_LO_OFF(1));
++ writel(0, base + PCIE_BAR_HI_OFF(1));
++ writel(((size - 1) & 0xffff0000) | 1, base + PCIE_BAR_CTRL_OFF(1));
++}
++
++void __init orion_pcie_setup(void __iomem *base,
++ struct mbus_dram_target_info *dram)
++{
++ u16 cmd;
++ u32 mask;
++
++ /*
++ * Point PCIe unit MBUS decode windows to DRAM space.
++ */
++ orion_pcie_setup_wins(base, dram);
++
++ /*
++ * Master + slave enable.
++ */
++ cmd = readw(base + PCIE_CMD_OFF);
++ cmd |= PCI_COMMAND_IO;
++ cmd |= PCI_COMMAND_MEMORY;
++ cmd |= PCI_COMMAND_MASTER;
++ writew(cmd, base + PCIE_CMD_OFF);
++
++ /*
++ * Enable interrupt lines A-D.
++ */
++ mask = readl(base + PCIE_MASK_OFF);
++ mask |= 0x0f000000;
++ writel(mask, base + PCIE_MASK_OFF);
++}
++
++int orion_pcie_rd_conf(void __iomem *base, struct pci_bus *bus,
++ u32 devfn, int where, int size, u32 *val)
++{
++ writel(PCIE_CONF_BUS(bus->number) |
++ PCIE_CONF_DEV(PCI_SLOT(devfn)) |
++ PCIE_CONF_FUNC(PCI_FUNC(devfn)) |
++ PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN,
++ base + PCIE_CONF_ADDR_OFF);
++
++ *val = readl(base + PCIE_CONF_DATA_OFF);
++
++ if (size == 1)
++ *val = (*val >> (8 * (where & 3))) & 0xff;
++ else if (size == 2)
++ *val = (*val >> (8 * (where & 3))) & 0xffff;
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++int orion_pcie_rd_conf_tlp(void __iomem *base, struct pci_bus *bus,
++ u32 devfn, int where, int size, u32 *val)
++{
++ writel(PCIE_CONF_BUS(bus->number) |
++ PCIE_CONF_DEV(PCI_SLOT(devfn)) |
++ PCIE_CONF_FUNC(PCI_FUNC(devfn)) |
++ PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN,
++ base + PCIE_CONF_ADDR_OFF);
++
++ *val = readl(base + PCIE_CONF_DATA_OFF);
++
++ if (bus->number != orion_pcie_get_local_bus_nr(base) ||
++ PCI_FUNC(devfn) != 0)
++ *val = readl(base + PCIE_HEADER_LOG_4_OFF);
++
++ if (size == 1)
++ *val = (*val >> (8 * (where & 3))) & 0xff;
++ else if (size == 2)
++ *val = (*val >> (8 * (where & 3))) & 0xffff;
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++int orion_pcie_rd_conf_wa(void __iomem *wa_base, struct pci_bus *bus,
++ u32 devfn, int where, int size, u32 *val)
++{
++ *val = readl(wa_base + (PCIE_CONF_BUS(bus->number) |
++ PCIE_CONF_DEV(PCI_SLOT(devfn)) |
++ PCIE_CONF_FUNC(PCI_FUNC(devfn)) |
++ PCIE_CONF_REG(where)));
++
++ if (size == 1)
++ *val = (*val >> (8 * (where & 3))) & 0xff;
++ else if (size == 2)
++ *val = (*val >> (8 * (where & 3))) & 0xffff;
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++int orion_pcie_wr_conf(void __iomem *base, struct pci_bus *bus,
++ u32 devfn, int where, int size, u32 val)
++{
++ int ret = PCIBIOS_SUCCESSFUL;
++
++ writel(PCIE_CONF_BUS(bus->number) |
++ PCIE_CONF_DEV(PCI_SLOT(devfn)) |
++ PCIE_CONF_FUNC(PCI_FUNC(devfn)) |
++ PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN,
++ base + PCIE_CONF_ADDR_OFF);
++
++ if (size == 4) {
++ writel(val, base + PCIE_CONF_DATA_OFF);
++ } else if (size == 2) {
++ writew(val, base + PCIE_CONF_DATA_OFF + (where & 3));
++ } else if (size == 1) {
++ writeb(val, base + PCIE_CONF_DATA_OFF + (where & 3));
++ } else {
++ ret = PCIBIOS_BAD_REGISTER_NUMBER;
++ }
++
++ return ret;
++}
+diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c
+new file mode 100644
+index 0000000..28b5285
+--- /dev/null
++++ b/arch/arm/plat-orion/time.c
+@@ -0,0 +1,203 @@
++/*
++ * arch/arm/plat-orion/time.c
++ *
++ * Marvell Orion SoC timer handling.
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ *
++ * Timer 0 is used as free-running clocksource, while timer 1 is
++ * used as clock_event_device.
++ */
++
++#include <linux/kernel.h>
++#include <linux/clockchips.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <asm/mach/time.h>
++#include <asm/arch/hardware.h>
++
++/*
++ * Number of timer ticks per jiffy.
++ */
++static u32 ticks_per_jiffy;
++
++
++/*
++ * Timer block registers.
++ */
++#define TIMER_CTRL (TIMER_VIRT_BASE + 0x0000)
++#define TIMER0_EN 0x0001
++#define TIMER0_RELOAD_EN 0x0002
++#define TIMER1_EN 0x0004
++#define TIMER1_RELOAD_EN 0x0008
++#define TIMER0_RELOAD (TIMER_VIRT_BASE + 0x0010)
++#define TIMER0_VAL (TIMER_VIRT_BASE + 0x0014)
++#define TIMER1_RELOAD (TIMER_VIRT_BASE + 0x0018)
++#define TIMER1_VAL (TIMER_VIRT_BASE + 0x001c)
++
++
++/*
++ * Clocksource handling.
++ */
++static cycle_t orion_clksrc_read(void)
++{
++ return 0xffffffff - readl(TIMER0_VAL);
++}
++
++static struct clocksource orion_clksrc = {
++ .name = "orion_clocksource",
++ .shift = 20,
++ .rating = 300,
++ .read = orion_clksrc_read,
++ .mask = CLOCKSOURCE_MASK(32),
++ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
++};
++
++
++
++/*
++ * Clockevent handling.
++ */
++static int
++orion_clkevt_next_event(unsigned long delta, struct clock_event_device *dev)
++{
++ unsigned long flags;
++ u32 u;
++
++ if (delta == 0)
++ return -ETIME;
++
++ local_irq_save(flags);
++
++ /*
++ * Clear and enable clockevent timer interrupt.
++ */
++ writel(~BRIDGE_INT_TIMER1, BRIDGE_CAUSE);
++
++ u = readl(BRIDGE_MASK);
++ u |= BRIDGE_INT_TIMER1;
++ writel(u, BRIDGE_MASK);
++
++ /*
++ * Setup new clockevent timer value.
++ */
++ writel(delta, TIMER1_VAL);
++
++ /*
++ * Enable the timer.
++ */
++ u = readl(TIMER_CTRL);
++ u = (u & ~TIMER1_RELOAD_EN) | TIMER1_EN;
++ writel(u, TIMER_CTRL);
++
++ local_irq_restore(flags);
++
++ return 0;
++}
++
++static void
++orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
++{
++ unsigned long flags;
++ u32 u;
++
++ local_irq_save(flags);
++ if (mode == CLOCK_EVT_MODE_PERIODIC) {
++ /*
++ * Setup timer to fire at 1/HZ intervals.
++ */
++ writel(ticks_per_jiffy - 1, TIMER1_RELOAD);
++ writel(ticks_per_jiffy - 1, TIMER1_VAL);
++
++ /*
++ * Enable timer interrupt.
++ */
++ u = readl(BRIDGE_MASK);
++ writel(u | BRIDGE_INT_TIMER1, BRIDGE_MASK);
++
++ /*
++ * Enable timer.
++ */
++ u = readl(TIMER_CTRL);
++ writel(u | TIMER1_EN | TIMER1_RELOAD_EN, TIMER_CTRL);
++ } else {
++ /*
++ * Disable timer.
++ */
++ u = readl(TIMER_CTRL);
++ writel(u & ~TIMER1_EN, TIMER_CTRL);
++
++ /*
++ * Disable timer interrupt.
++ */
++ u = readl(BRIDGE_MASK);
++ writel(u & ~BRIDGE_INT_TIMER1, BRIDGE_MASK);
++
++ /*
++ * ACK pending timer interrupt.
++ */
++ writel(~BRIDGE_INT_TIMER1, BRIDGE_CAUSE);
++
++ }
++ local_irq_restore(flags);
++}
++
++static struct clock_event_device orion_clkevt = {
++ .name = "orion_tick",
++ .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
++ .shift = 32,
++ .rating = 300,
++ .cpumask = CPU_MASK_CPU0,
++ .set_next_event = orion_clkevt_next_event,
++ .set_mode = orion_clkevt_mode,
++};
++
++static irqreturn_t orion_timer_interrupt(int irq, void *dev_id)
++{
++ /*
++ * ACK timer interrupt and call event handler.
++ */
++ writel(~BRIDGE_INT_TIMER1, BRIDGE_CAUSE);
++ orion_clkevt.event_handler(&orion_clkevt);
++
++ return IRQ_HANDLED;
++}
++
++static struct irqaction orion_timer_irq = {
++ .name = "orion_tick",
++ .flags = IRQF_DISABLED | IRQF_TIMER,
++ .handler = orion_timer_interrupt
++};
++
++void __init orion_time_init(unsigned int irq, unsigned int tclk)
++{
++ u32 u;
++
++ ticks_per_jiffy = (tclk + HZ/2) / HZ;
++
++
++ /*
++ * Setup free-running clocksource timer (interrupts
++ * disabled.)
++ */
++ writel(0xffffffff, TIMER0_VAL);
++ writel(0xffffffff, TIMER0_RELOAD);
++ u = readl(BRIDGE_MASK);
++ writel(u & ~BRIDGE_INT_TIMER0, BRIDGE_MASK);
++ u = readl(TIMER_CTRL);
++ writel(u | TIMER0_EN | TIMER0_RELOAD_EN, TIMER_CTRL);
++ orion_clksrc.mult = clocksource_hz2mult(tclk, orion_clksrc.shift);
++ clocksource_register(&orion_clksrc);
++
++
++ /*
++ * Setup clockevent timer (interrupt-driven.)
++ */
++ setup_irq(irq, &orion_timer_irq);
++ orion_clkevt.mult = div_sc(tclk, NSEC_PER_SEC, orion_clkevt.shift);
++ orion_clkevt.max_delta_ns = clockevent_delta2ns(0xfffffffe, &orion_clkevt);
++ orion_clkevt.min_delta_ns = clockevent_delta2ns(1, &orion_clkevt);
++ clockevents_register_device(&orion_clkevt);
++}
+diff --git a/arch/arm/plat-s3c24xx/clock.c b/arch/arm/plat-s3c24xx/clock.c
+index 99a4474..d84167f 100644
+--- a/arch/arm/plat-s3c24xx/clock.c
++++ b/arch/arm/plat-s3c24xx/clock.c
+@@ -332,6 +332,58 @@ static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent)
+ return 0;
+ }
+
++static unsigned long s3c24xx_calc_div(struct clk *clk, unsigned long rate)
++{
++ unsigned long div;
++
++ if ((rate == 0) || !clk->parent)
++ return 0;
++
++ div = clk_get_rate(clk->parent) / rate;
++ if (div < 2)
++ div = 2;
++ else if (div > 16)
++ div = 16;
++
++ return div;
++}
++
++static unsigned long s3c24xx_round_dclk_rate(struct clk *clk,
++ unsigned long rate)
++{
++ unsigned long div = s3c24xx_calc_div(clk, rate);
++
++ if (div == 0)
++ return 0;
++
++ return clk_get_rate(clk->parent) / div;
++}
++
++static int s3c24xx_set_dclk_rate(struct clk *clk, unsigned long rate)
++{
++ unsigned long mask, data, div = s3c24xx_calc_div(clk, rate);
++
++ if (div == 0)
++ return -EINVAL;
++
++ if (clk == &s3c24xx_dclk0) {
++ mask = S3C2410_DCLKCON_DCLK0_DIV_MASK |
++ S3C2410_DCLKCON_DCLK0_CMP_MASK;
++ data = S3C2410_DCLKCON_DCLK0_DIV(div) |
++ S3C2410_DCLKCON_DCLK0_CMP((div + 1) / 2);
++ } else if (clk == &s3c24xx_dclk1) {
++ mask = S3C2410_DCLKCON_DCLK1_DIV_MASK |
++ S3C2410_DCLKCON_DCLK1_CMP_MASK;
++ data = S3C2410_DCLKCON_DCLK1_DIV(div) |
++ S3C2410_DCLKCON_DCLK1_CMP((div + 1) / 2);
++ } else
++ return -EINVAL;
++
++ clk->rate = clk_get_rate(clk->parent) / div;
++ __raw_writel(((__raw_readl(S3C24XX_DCLKCON) & ~mask) | data),
++ S3C24XX_DCLKCON);
++ return clk->rate;
++}
+
+ static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent)
+ {
+@@ -378,6 +430,8 @@ struct clk s3c24xx_dclk0 = {
+ .ctrlbit = S3C2410_DCLKCON_DCLK0EN,
+ .enable = s3c24xx_dclk_enable,
+ .set_parent = s3c24xx_dclk_setparent,
++ .set_rate = s3c24xx_set_dclk_rate,
++ .round_rate = s3c24xx_round_dclk_rate,
+ };
+
+ struct clk s3c24xx_dclk1 = {
+@@ -386,6 +440,8 @@ struct clk s3c24xx_dclk1 = {
+ .ctrlbit = S3C2410_DCLKCON_DCLK0EN,
+ .enable = s3c24xx_dclk_enable,
+ .set_parent = s3c24xx_dclk_setparent,
++ .set_rate = s3c24xx_set_dclk_rate,
++ .round_rate = s3c24xx_round_dclk_rate,
+ };
+
+ struct clk s3c24xx_clkout0 = {
+diff --git a/arch/arm/plat-s3c24xx/cpu.c b/arch/arm/plat-s3c24xx/cpu.c
+index f513ab0..f5699ca 100644
+--- a/arch/arm/plat-s3c24xx/cpu.c
++++ b/arch/arm/plat-s3c24xx/cpu.c
+@@ -28,15 +28,19 @@
+ #include <linux/ioport.h>
+ #include <linux/serial_core.h>
+ #include <linux/platform_device.h>
++#include <linux/delay.h>
+
+ #include <asm/hardware.h>
+ #include <asm/irq.h>
+ #include <asm/io.h>
+ #include <asm/delay.h>
++#include <asm/cacheflush.h>
+
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+
++#include <asm/arch/system-reset.h>
++
+ #include <asm/arch/regs-gpio.h>
+ #include <asm/plat-s3c/regs-serial.h>
+
+@@ -203,6 +207,27 @@ static unsigned long s3c24xx_read_idcode_v4(void)
+ #endif
+ }
+
++/* Hook for arm_pm_restart to ensure we execute the reset code
++ * with the caches enabled. It seems at least the S3C2440 has a problem
++ * resetting if there is bus activity interrupted by the reset.
++ */
++static void s3c24xx_pm_restart(char mode)
++{
++ if (mode != 's') {
++ unsigned long flags;
++
++ local_irq_save(flags);
++ __cpuc_flush_kern_all();
++ __cpuc_flush_user_all();
++
++ arch_reset(mode);
++ local_irq_restore(flags);
++ }
++
++ /* fallback, or unhandled */
++ arm_machine_restart(mode);
++}
++
+ void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
+ {
+ unsigned long idcode = 0x0;
+@@ -230,6 +255,8 @@ void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
+ panic("Unsupported S3C24XX CPU");
+ }
+
++ arm_pm_restart = s3c24xx_pm_restart;
++
+ (cpu->map_io)(mach_desc, size);
+ }
+
+diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
+index 7ed58c0..207a8b5 100644
+--- a/arch/arm/tools/mach-types
++++ b/arch/arm/tools/mach-types
+@@ -12,7 +12,7 @@
+ #
+ # http://www.arm.linux.org.uk/developer/machines/?action=new
+ #
+-# Last update: Sat Jan 26 14:45:34 2008
++# Last update: Sat Apr 19 11:23:38 2008
+ #
+ # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
+ #
+@@ -381,13 +381,13 @@ ks8695p ARCH_KS8695P KS8695P 363
+ se4000 ARCH_SE4000 SE4000 364
+ quadriceps ARCH_QUADRICEPS QUADRICEPS 365
+ bronco ARCH_BRONCO BRONCO 366
+-esl_wireless_tab ARCH_ESL_WIRELESS_TABLETESL_WIRELESS_TABLET 367
++esl_wireless_tab ARCH_ESL_WIRELESS_TAB ESL_WIRELESS_TAB 367
+ esl_sofcomp ARCH_ESL_SOFCOMP ESL_SOFCOMP 368
+ s5c7375 ARCH_S5C7375 S5C7375 369
+ spearhead ARCH_SPEARHEAD SPEARHEAD 370
+ pantera ARCH_PANTERA PANTERA 371
+ prayoglite ARCH_PRAYOGLITE PRAYOGLITE 372
+-gumstix ARCH_GUMSTIK GUMSTIK 373
++gumstix ARCH_GUMSTIX GUMSTIX 373
+ rcube ARCH_RCUBE RCUBE 374
+ rea_olv ARCH_REA_OLV REA_OLV 375
+ pxa_iphone ARCH_PXA_IPHONE PXA_IPHONE 376
+@@ -1463,7 +1463,7 @@ artemis MACH_ARTEMIS ARTEMIS 1462
+ htctitan MACH_HTCTITAN HTCTITAN 1463
+ qranium MACH_QRANIUM QRANIUM 1464
+ adx_wsc2 MACH_ADX_WSC2 ADX_WSC2 1465
+-adx_medinet MACH_ADX_MEDINET ADX_MEDINET 1466
++adx_medcom MACH_ADX_MEDINET ADX_MEDINET 1466
+ bboard MACH_BBOARD BBOARD 1467
+ cambria MACH_CAMBRIA CAMBRIA 1468
+ mt7xxx MACH_MT7XXX MT7XXX 1469
+@@ -1611,3 +1611,112 @@ kb9263 MACH_KB9263 KB9263 1612
+ mt7108 MACH_MT7108 MT7108 1613
+ smtr2440 MACH_SMTR2440 SMTR2440 1614
+ manao MACH_MANAO MANAO 1615
++cm_x300 MACH_CM_X300 CM_X300 1616
++gulfstream_kp MACH_GULFSTREAM_KP GULFSTREAM_KP 1617
++lanreadyfn522 MACH_LANREADYFN522 LANREADYFN522 1618
++arma37 MACH_ARMA37 ARMA37 1619
++mendel MACH_MENDEL MENDEL 1620
++pelco_iliad MACH_PELCO_ILIAD PELCO_ILIAD 1621
++unit2p MACH_UNIT2P UNIT2P 1622
++inc20otter MACH_INC20OTTER INC20OTTER 1623
++at91sam9g20ek MACH_AT91SAM9G20EK AT91SAM9G20EK 1624
++sc_ge2 MACH_STORCENTER STORCENTER 1625
++smdk6410 MACH_SMDK6410 SMDK6410 1626
++u300 MACH_U300 U300 1627
++u500 MACH_U500 U500 1628
++ds9260 MACH_DS9260 DS9260 1629
++riverrock MACH_RIVERROCK RIVERROCK 1630
++scibath MACH_SCIBATH SCIBATH 1631
++at91sam7se MACH_AT91SAM7SE512EK AT91SAM7SE512EK 1632
++wrt350n_v2 MACH_WRT350N_V2 WRT350N_V2 1633
++multimedia MACH_MULTIMEDIA MULTIMEDIA 1634
++marvin MACH_MARVIN MARVIN 1635
++x500 MACH_X500 X500 1636
++awlug4lcu MACH_AWLUG4LCU AWLUG4LCU 1637
++palermoc MACH_PALERMOC PALERMOC 1638
++omap_ldp MACH_OMAP_LDP OMAP_LDP 1639
++ip500 MACH_IP500 IP500 1640
++mx35ads MACH_MACH_MX35ADS MACH_MX35ADS 1641
++ase2 MACH_ASE2 ASE2 1642
++mx35evb MACH_MX35EVB MX35EVB 1643
++aml_m8050 MACH_AML_M8050 AML_M8050 1644
++mx35_3ds MACH_MX35_3DS MX35_3DS 1645
++mars MACH_MARS MARS 1646
++ntosd_644xa MACH_NTOSD_644XA NTOSD_644XA 1647
++badger MACH_BADGER BADGER 1648
++trizeps4wl MACH_TRIZEPS4WL TRIZEPS4WL 1649
++trizeps5 MACH_TRIZEPS5 TRIZEPS5 1650
++marlin MACH_MARLIN MARLIN 1651
++ts7800 MACH_TS7800 TS7800 1652
++hpipaq214 MACH_HPIPAQ214 HPIPAQ214 1653
++at572d940dcm MACH_AT572D940DCM AT572D940DCM 1654
++ne1board MACH_NE1BOARD NE1BOARD 1655
++zante MACH_ZANTE ZANTE 1656
++sffsdr MACH_SFFSDR SFFSDR 1657
++tw2662 MACH_TW2662 TW2662 1658
++vf10xx MACH_VF10XX VF10XX 1659
++zoran43xx MACH_ZORAN43XX ZORAN43XX 1660
++sonix926 MACH_SONIX926 SONIX926 1661
++celestialsemi MACH_CELESTIALSEMI CELESTIALSEMI 1662
++cc9m2443 MACH_CC9M2443 CC9M2443 1663
++tw5334 MACH_TW5334 TW5334 1664
++omap_htcartemis MACH_HTCARTEMIS HTCARTEMIS 1665
++nal_hlite MACH_NAL_HLITE NAL_HLITE 1666
++htcvogue MACH_HTCVOGUE HTCVOGUE 1667
++smartweb MACH_SMARTWEB SMARTWEB 1668
++mv86xx MACH_MV86XX MV86XX 1669
++mv87xx MACH_MV87XX MV87XX 1670
++songyoungho MACH_SONGYOUNGHO SONGYOUNGHO 1671
++younghotema MACH_YOUNGHOTEMA YOUNGHOTEMA 1672
++pcm037 MACH_PCM037 PCM037 1673
++mmvp MACH_MMVP MMVP 1674
++mmap MACH_MMAP MMAP 1675
++ptid2410 MACH_PTID2410 PTID2410 1676
++james_926 MACH_JAMES_926 JAMES_926 1677
++fm6000 MACH_FM6000 FM6000 1678
++db88f6281_bp MACH_DB88F6281_BP DB88F6281_BP 1680
++rd88f6192_nas MACH_RD88F6192_NAS RD88F6192_NAS 1681
++rd88f6281 MACH_RD88F6281 RD88F6281 1682
++db78x00_bp MACH_DB78X00_BP DB78X00_BP 1683
++smdk2416 MACH_SMDK2416 SMDK2416 1685
++oce_spider_si MACH_OCE_SPIDER_SI OCE_SPIDER_SI 1686
++oce_spider_sk MACH_OCE_SPIDER_SK OCE_SPIDER_SK 1687
++rovern6 MACH_ROVERN6 ROVERN6 1688
++pelco_evolution MACH_PELCO_EVOLUTION PELCO_EVOLUTION 1689
++wbd111 MACH_WBD111 WBD111 1690
++elaracpe MACH_ELARACPE ELARACPE 1691
++mabv3 MACH_MABV3 MABV3 1692
++mv2120 MACH_MV2120 MV2120 1693
++csb737 MACH_CSB737 CSB737 1695
++mx51_3ds MACH_MX51_3DS MX51_3DS 1696
++g900 MACH_G900 G900 1697
++apf27 MACH_APF27 APF27 1698
++ggus2000 MACH_GGUS2000 GGUS2000 1699
++omap_2430_mimic MACH_OMAP_2430_MIMIC OMAP_2430_MIMIC 1700
++imx27lite MACH_IMX27LITE IMX27LITE 1701
++almex MACH_ALMEX ALMEX 1702
++control MACH_CONTROL CONTROL 1703
++mba2410 MACH_MBA2410 MBA2410 1704
++volcano MACH_VOLCANO VOLCANO 1705
++zenith MACH_ZENITH ZENITH 1706
++muchip MACH_MUCHIP MUCHIP 1707
++magellan MACH_MAGELLAN MAGELLAN 1708
++usb_a9260 MACH_USB_A9260 USB_A9260 1709
++usb_a9263 MACH_USB_A9263 USB_A9263 1710
++qil_a9260 MACH_QIL_A9260 QIL_A9260 1711
++cme9210 MACH_CME9210 CME9210 1712
++hczh4 MACH_HCZH4 HCZH4 1713
++spearbasic MACH_SPEARBASIC SPEARBASIC 1714
++dep2440 MACH_DEP2440 DEP2440 1715
++hdl_gxr MACH_HDL_GXR HDL_GXR 1716
++hdl_gt MACH_HDL_GT HDL_GT 1717
++hdl_4g MACH_HDL_4G HDL_4G 1718
++s3c6000 MACH_S3C6000 S3C6000 1719
++mmsp2_mdk MACH_MMSP2_MDK MMSP2_MDK 1720
++mpx220 MACH_MPX220 MPX220 1721
++kzm_arm11_01 MACH_KZM_ARM11_01 KZM_ARM11_01 1722
++htc_polaris MACH_HTC_POLARIS HTC_POLARIS 1723
++htc_kaiser MACH_HTC_KAISER HTC_KAISER 1724
++lg_ks20 MACH_LG_KS20 LG_KS20 1725
++hhgps MACH_HHGPS HHGPS 1726
++nokia_n810_wimax MACH_NOKIA_N810_WIMAX NOKIA_N810_WIMAX 1727
+diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
+index 28e0caf..09ad799 100644
+--- a/arch/avr32/Kconfig
++++ b/arch/avr32/Kconfig
+@@ -47,6 +47,9 @@ config RWSEM_GENERIC_SPINLOCK
+ config GENERIC_TIME
+ def_bool y
+
++config GENERIC_CLOCKEVENTS
++ def_bool y
++
+ config RWSEM_XCHGADD_ALGORITHM
+ def_bool n
+
+@@ -70,6 +73,8 @@ source "init/Kconfig"
+
+ menu "System Type and features"
+
++source "kernel/time/Kconfig"
++
+ config SUBARCH_AVR32B
+ bool
+ config MMU
+diff --git a/arch/avr32/kernel/Makefile b/arch/avr32/kernel/Makefile
+index e4b6d12..18229d0 100644
+--- a/arch/avr32/kernel/Makefile
++++ b/arch/avr32/kernel/Makefile
+@@ -6,7 +6,7 @@ extra-y := head.o vmlinux.lds
+
+ obj-$(CONFIG_SUBARCH_AVR32B) += entry-avr32b.o
+ obj-y += syscall_table.o syscall-stubs.o irq.o
+-obj-y += setup.o traps.o semaphore.o ocd.o ptrace.o
++obj-y += setup.o traps.o ocd.o ptrace.o
+ obj-y += signal.o sys_avr32.o process.o time.o
+ obj-y += init_task.o switch_to.o cpu.o
+ obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o
+diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
+index 8cf16d7..5f31702 100644
+--- a/arch/avr32/kernel/entry-avr32b.S
++++ b/arch/avr32/kernel/entry-avr32b.S
+@@ -741,26 +741,6 @@ irq_level\level:
+
+ .section .irq.text,"ax", at progbits
+
+-.global cpu_idle_sleep
+-cpu_idle_sleep:
+- mask_interrupts
+- get_thread_info r8
+- ld.w r9, r8[TI_flags]
+- bld r9, TIF_NEED_RESCHED
+- brcs cpu_idle_enable_int_and_exit
+- sbr r9, TIF_CPU_GOING_TO_SLEEP
+- st.w r8[TI_flags], r9
+- unmask_interrupts
+- sleep 0
+-cpu_idle_skip_sleep:
+- mask_interrupts
+- ld.w r9, r8[TI_flags]
+- cbr r9, TIF_CPU_GOING_TO_SLEEP
+- st.w r8[TI_flags], r9
+-cpu_idle_enable_int_and_exit:
+- unmask_interrupts
+- retal r12
+-
+ .global irq_level0
+ .global irq_level1
+ .global irq_level2
+diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c
+index 7f4af0b..6cf9df1 100644
+--- a/arch/avr32/kernel/process.c
++++ b/arch/avr32/kernel/process.c
+@@ -18,11 +18,11 @@
+ #include <asm/sysreg.h>
+ #include <asm/ocd.h>
+
++#include <asm/arch/pm.h>
++
+ void (*pm_power_off)(void) = NULL;
+ EXPORT_SYMBOL(pm_power_off);
+
+-extern void cpu_idle_sleep(void);
+-
+ /*
+ * This file handles the architecture-dependent parts of process handling..
+ */
+@@ -54,6 +54,8 @@ void machine_halt(void)
+
+ void machine_power_off(void)
+ {
++ if (pm_power_off)
++ pm_power_off();
+ }
+
+ void machine_restart(char *cmd)
+diff --git a/arch/avr32/kernel/semaphore.c b/arch/avr32/kernel/semaphore.c
+deleted file mode 100644
+index 1e2705a..0000000
+--- a/arch/avr32/kernel/semaphore.c
++++ /dev/null
+@@ -1,148 +0,0 @@
+-/*
+- * AVR32 sempahore implementation.
+- *
+- * Copyright (C) 2004-2006 Atmel Corporation
+- *
+- * Based on linux/arch/i386/kernel/semaphore.c
+- * Copyright (C) 1999 Linus Torvalds
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/errno.h>
+-#include <linux/module.h>
+-
+-#include <asm/semaphore.h>
+-#include <asm/atomic.h>
+-
+-/*
+- * Semaphores are implemented using a two-way counter:
+- * The "count" variable is decremented for each process
+- * that tries to acquire the semaphore, while the "sleeping"
+- * variable is a count of such acquires.
+- *
+- * Notably, the inline "up()" and "down()" functions can
+- * efficiently test if they need to do any extra work (up
+- * needs to do something only if count was negative before
+- * the increment operation.
+- *
+- * "sleeping" and the contention routine ordering is protected
+- * by the spinlock in the semaphore's waitqueue head.
+- *
+- * Note that these functions are only called when there is
+- * contention on the lock, and as such all this is the
+- * "non-critical" part of the whole semaphore business. The
+- * critical part is the inline stuff in <asm/semaphore.h>
+- * where we want to avoid any extra jumps and calls.
+- */
+-
+-/*
+- * Logic:
+- * - only on a boundary condition do we need to care. When we go
+- * from a negative count to a non-negative, we wake people up.
+- * - when we go from a non-negative count to a negative do we
+- * (a) synchronize with the "sleeper" count and (b) make sure
+- * that we're on the wakeup list before we synchronize so that
+- * we cannot lose wakeup events.
+- */
+-
+-void __up(struct semaphore *sem)
+-{
+- wake_up(&sem->wait);
+-}
+-EXPORT_SYMBOL(__up);
+-
+-void __sched __down(struct semaphore *sem)
+-{
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+- unsigned long flags;
+-
+- tsk->state = TASK_UNINTERRUPTIBLE;
+- spin_lock_irqsave(&sem->wait.lock, flags);
+- add_wait_queue_exclusive_locked(&sem->wait, &wait);
+-
+- sem->sleepers++;
+- for (;;) {
+- int sleepers = sem->sleepers;
+-
+- /*
+- * Add "everybody else" into it. They aren't
+- * playing, because we own the spinlock in
+- * the wait_queue_head.
+- */
+- if (atomic_add_return(sleepers - 1, &sem->count) >= 0) {
+- sem->sleepers = 0;
+- break;
+- }
+- sem->sleepers = 1; /* us - see -1 above */
+- spin_unlock_irqrestore(&sem->wait.lock, flags);
+-
+- schedule();
+-
+- spin_lock_irqsave(&sem->wait.lock, flags);
+- tsk->state = TASK_UNINTERRUPTIBLE;
+- }
+- remove_wait_queue_locked(&sem->wait, &wait);
+- wake_up_locked(&sem->wait);
+- spin_unlock_irqrestore(&sem->wait.lock, flags);
+- tsk->state = TASK_RUNNING;
+-}
+-EXPORT_SYMBOL(__down);
+-
+-int __sched __down_interruptible(struct semaphore *sem)
+-{
+- int retval = 0;
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+- unsigned long flags;
+-
+- tsk->state = TASK_INTERRUPTIBLE;
+- spin_lock_irqsave(&sem->wait.lock, flags);
+- add_wait_queue_exclusive_locked(&sem->wait, &wait);
+-
+- sem->sleepers++;
+- for (;;) {
+- int sleepers = sem->sleepers;
+-
+- /*
+- * With signals pending, this turns into the trylock
+- * failure case - we won't be sleeping, and we can't
+- * get the lock as it has contention. Just correct the
+- * count and exit.
+- */
+- if (signal_pending(current)) {
+- retval = -EINTR;
+- sem->sleepers = 0;
+- atomic_add(sleepers, &sem->count);
+- break;
+- }
+-
+- /*
+- * Add "everybody else" into it. They aren't
+- * playing, because we own the spinlock in
+- * the wait_queue_head.
+- */
+- if (atomic_add_return(sleepers - 1, &sem->count) >= 0) {
+- sem->sleepers = 0;
+- break;
+- }
+- sem->sleepers = 1; /* us - see -1 above */
+- spin_unlock_irqrestore(&sem->wait.lock, flags);
+-
+- schedule();
+-
+- spin_lock_irqsave(&sem->wait.lock, flags);
+- tsk->state = TASK_INTERRUPTIBLE;
+- }
+- remove_wait_queue_locked(&sem->wait, &wait);
+- wake_up_locked(&sem->wait);
+- spin_unlock_irqrestore(&sem->wait.lock, flags);
+-
+- tsk->state = TASK_RUNNING;
+- return retval;
+-}
+-EXPORT_SYMBOL(__down_interruptible);
+diff --git a/arch/avr32/kernel/time.c b/arch/avr32/kernel/time.c
+index 36a46c3..00a9862 100644
+--- a/arch/avr32/kernel/time.c
++++ b/arch/avr32/kernel/time.c
+@@ -1,16 +1,12 @@
+ /*
+ * Copyright (C) 2004-2007 Atmel Corporation
+ *
+- * Based on MIPS implementation arch/mips/kernel/time.c
+- * Copyright 2001 MontaVista Software Inc.
+- *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+-
+ #include <linux/clk.h>
+-#include <linux/clocksource.h>
++#include <linux/clockchips.h>
+ #include <linux/time.h>
+ #include <linux/module.h>
+ #include <linux/interrupt.h>
+@@ -27,207 +23,133 @@
+ #include <asm/io.h>
+ #include <asm/sections.h>
+
+-/* how many counter cycles in a jiffy? */
+-static u32 cycles_per_jiffy;
++#include <asm/arch/pm.h>
+
+-/* the count value for the next timer interrupt */
+-static u32 expirelo;
+
+-cycle_t __weak read_cycle_count(void)
++static cycle_t read_cycle_count(void)
+ {
+ return (cycle_t)sysreg_read(COUNT);
+ }
+
+-struct clocksource __weak clocksource_avr32 = {
+- .name = "avr32",
+- .rating = 350,
++/*
++ * The architectural cycle count registers are a fine clocksource unless
++ * the system idle loop use sleep states like "idle": the CPU cycles
++ * measured by COUNT (and COMPARE) don't happen during sleep states.
++ * Their duration also changes if cpufreq changes the CPU clock rate.
++ * So we rate the clocksource using COUNT as very low quality.
++ */
++static struct clocksource counter = {
++ .name = "avr32_counter",
++ .rating = 50,
+ .read = read_cycle_count,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 16,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ };
+
+-irqreturn_t __weak timer_interrupt(int irq, void *dev_id);
+-
+-struct irqaction timer_irqaction = {
+- .handler = timer_interrupt,
+- .flags = IRQF_DISABLED,
+- .name = "timer",
+-};
+-
+-/*
+- * By default we provide the null RTC ops
+- */
+-static unsigned long null_rtc_get_time(void)
++static irqreturn_t timer_interrupt(int irq, void *dev_id)
+ {
+- return mktime(2007, 1, 1, 0, 0, 0);
+-}
+-
+-static int null_rtc_set_time(unsigned long sec)
+-{
+- return 0;
+-}
++ struct clock_event_device *evdev = dev_id;
+
+-static unsigned long (*rtc_get_time)(void) = null_rtc_get_time;
+-static int (*rtc_set_time)(unsigned long) = null_rtc_set_time;
+-
+-static void avr32_timer_ack(void)
+-{
+- u32 count;
+-
+- /* Ack this timer interrupt and set the next one */
+- expirelo += cycles_per_jiffy;
+- /* setting COMPARE to 0 stops the COUNT-COMPARE */
+- if (expirelo == 0) {
+- sysreg_write(COMPARE, expirelo + 1);
+- } else {
+- sysreg_write(COMPARE, expirelo);
+- }
++ /*
++ * Disable the interrupt until the clockevent subsystem
++ * reprograms it.
++ */
++ sysreg_write(COMPARE, 0);
+
+- /* Check to see if we have missed any timer interrupts */
+- count = sysreg_read(COUNT);
+- if ((count - expirelo) < 0x7fffffff) {
+- expirelo = count + cycles_per_jiffy;
+- sysreg_write(COMPARE, expirelo);
+- }
++ evdev->event_handler(evdev);
++ return IRQ_HANDLED;
+ }
+
+-int __weak avr32_hpt_init(void)
+-{
+- int ret;
+- unsigned long mult, shift, count_hz;
+-
+- count_hz = clk_get_rate(boot_cpu_data.clk);
+- shift = clocksource_avr32.shift;
+- mult = clocksource_hz2mult(count_hz, shift);
+- clocksource_avr32.mult = mult;
+-
+- {
+- u64 tmp;
+-
+- tmp = TICK_NSEC;
+- tmp <<= shift;
+- tmp += mult / 2;
+- do_div(tmp, mult);
+-
+- cycles_per_jiffy = tmp;
+- }
++static struct irqaction timer_irqaction = {
++ .handler = timer_interrupt,
++ .flags = IRQF_TIMER | IRQF_DISABLED,
++ .name = "avr32_comparator",
++};
+
+- ret = setup_irq(0, &timer_irqaction);
+- if (ret) {
+- pr_debug("timer: could not request IRQ 0: %d\n", ret);
+- return -ENODEV;
+- }
++static int comparator_next_event(unsigned long delta,
++ struct clock_event_device *evdev)
++{
++ unsigned long flags;
+
+- printk(KERN_INFO "timer: AT32AP COUNT-COMPARE at irq 0, "
+- "%lu.%03lu MHz\n",
+- ((count_hz + 500) / 1000) / 1000,
+- ((count_hz + 500) / 1000) % 1000);
++ raw_local_irq_save(flags);
+
+- return 0;
+-}
++ /* The time to read COUNT then update COMPARE must be less
++ * than the min_delta_ns value for this clockevent source.
++ */
++ sysreg_write(COMPARE, (sysreg_read(COUNT) + delta) ? : 1);
+
+-/*
+- * Taken from MIPS c0_hpt_timer_init().
+- *
+- * The reason COUNT is written twice is probably to make sure we don't get any
+- * timer interrupts while we are messing with the counter.
+- */
+-int __weak avr32_hpt_start(void)
+-{
+- u32 count = sysreg_read(COUNT);
+- expirelo = (count / cycles_per_jiffy + 1) * cycles_per_jiffy;
+- sysreg_write(COUNT, expirelo - cycles_per_jiffy);
+- sysreg_write(COMPARE, expirelo);
+- sysreg_write(COUNT, count);
++ raw_local_irq_restore(flags);
+
+ return 0;
+ }
+
+-/*
+- * local_timer_interrupt() does profiling and process accounting on a
+- * per-CPU basis.
+- *
+- * In UP mode, it is invoked from the (global) timer_interrupt.
+- */
+-void local_timer_interrupt(int irq, void *dev_id)
++static void comparator_mode(enum clock_event_mode mode,
++ struct clock_event_device *evdev)
+ {
+- if (current->pid)
+- profile_tick(CPU_PROFILING);
+- update_process_times(user_mode(get_irq_regs()));
++ switch (mode) {
++ case CLOCK_EVT_MODE_ONESHOT:
++ pr_debug("%s: start\n", evdev->name);
++ /* FALLTHROUGH */
++ case CLOCK_EVT_MODE_RESUME:
++ cpu_disable_idle_sleep();
++ break;
++ case CLOCK_EVT_MODE_UNUSED:
++ case CLOCK_EVT_MODE_SHUTDOWN:
++ sysreg_write(COMPARE, 0);
++ pr_debug("%s: stop\n", evdev->name);
++ cpu_enable_idle_sleep();
++ break;
++ default:
++ BUG();
++ }
+ }
+
+-irqreturn_t __weak timer_interrupt(int irq, void *dev_id)
+-{
+- /* ack timer interrupt and try to set next interrupt */
+- avr32_timer_ack();
+-
+- /*
+- * Call the generic timer interrupt handler
+- */
+- write_seqlock(&xtime_lock);
+- do_timer(1);
+- write_sequnlock(&xtime_lock);
+-
+- /*
+- * In UP mode, we call local_timer_interrupt() to do profiling
+- * and process accounting.
+- *
+- * SMP is not supported yet.
+- */
+- local_timer_interrupt(irq, dev_id);
+-
+- return IRQ_HANDLED;
+-}
++static struct clock_event_device comparator = {
++ .name = "avr32_comparator",
++ .features = CLOCK_EVT_FEAT_ONESHOT,
++ .shift = 16,
++ .rating = 50,
++ .cpumask = CPU_MASK_CPU0,
++ .set_next_event = comparator_next_event,
++ .set_mode = comparator_mode,
++};
+
+ void __init time_init(void)
+ {
++ unsigned long counter_hz;
+ int ret;
+
+- /*
+- * Make sure we don't get any COMPARE interrupts before we can
+- * handle them.
+- */
+- sysreg_write(COMPARE, 0);
+-
+- xtime.tv_sec = rtc_get_time();
++ xtime.tv_sec = mktime(2007, 1, 1, 0, 0, 0);
+ xtime.tv_nsec = 0;
+
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
+
+- ret = avr32_hpt_init();
+- if (ret) {
+- pr_debug("timer: failed setup: %d\n", ret);
+- return;
+- }
++ /* figure rate for counter */
++ counter_hz = clk_get_rate(boot_cpu_data.clk);
++ counter.mult = clocksource_hz2mult(counter_hz, counter.shift);
+
+- ret = clocksource_register(&clocksource_avr32);
++ ret = clocksource_register(&counter);
+ if (ret)
+ pr_debug("timer: could not register clocksource: %d\n", ret);
+
+- ret = avr32_hpt_start();
+- if (ret) {
+- pr_debug("timer: failed starting: %d\n", ret);
+- return;
+- }
+-}
++ /* setup COMPARE clockevent */
++ comparator.mult = div_sc(counter_hz, NSEC_PER_SEC, comparator.shift);
++ comparator.max_delta_ns = clockevent_delta2ns((u32)~0, &comparator);
++ comparator.min_delta_ns = clockevent_delta2ns(50, &comparator) + 1;
+
+-static struct sysdev_class timer_class = {
+- .name = "timer",
+-};
++ sysreg_write(COMPARE, 0);
++ timer_irqaction.dev_id = &comparator;
+
+-static struct sys_device timer_device = {
+- .id = 0,
+- .cls = &timer_class,
+-};
++ ret = setup_irq(0, &timer_irqaction);
++ if (ret)
++ pr_debug("timer: could not request IRQ 0: %d\n", ret);
++ else {
++ clockevents_register_device(&comparator);
+
+-static int __init init_timer_sysfs(void)
+-{
+- int err = sysdev_class_register(&timer_class);
+- if (!err)
+- err = sysdev_register(&timer_device);
+- return err;
++ pr_info("%s: irq 0, %lu.%03lu MHz\n", comparator.name,
++ ((counter_hz + 500) / 1000) / 1000,
++ ((counter_hz + 500) / 1000) % 1000);
++ }
+ }
+-
+-device_initcall(init_timer_sysfs);
+diff --git a/arch/avr32/mach-at32ap/Makefile b/arch/avr32/mach-at32ap/Makefile
+index 5e9f821..e890094 100644
+--- a/arch/avr32/mach-at32ap/Makefile
++++ b/arch/avr32/mach-at32ap/Makefile
+@@ -1,4 +1,3 @@
+ obj-y += at32ap.o clock.o intc.o extint.o pio.o hsmc.o
+-obj-$(CONFIG_CPU_AT32AP700X) += at32ap700x.o
+-obj-$(CONFIG_CPU_AT32AP700X) += time-tc.o
++obj-$(CONFIG_CPU_AT32AP700X) += at32ap700x.o pm-at32ap700x.o
+ obj-$(CONFIG_CPU_FREQ_AT32AP) += cpufreq.o
+diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c
+index 7678fee..0f24b4f 100644
+--- a/arch/avr32/mach-at32ap/at32ap700x.c
++++ b/arch/avr32/mach-at32ap/at32ap700x.c
+@@ -6,11 +6,13 @@
+ * published by the Free Software Foundation.
+ */
+ #include <linux/clk.h>
++#include <linux/delay.h>
+ #include <linux/fb.h>
+ #include <linux/init.h>
+ #include <linux/platform_device.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/spi/spi.h>
++#include <linux/usb/atmel_usba_udc.h>
+
+ #include <asm/io.h>
+ #include <asm/irq.h>
+@@ -98,6 +100,9 @@ unsigned long at32ap7000_osc_rates[3] = {
+ [2] = 12000000,
+ };
+
++static struct clk osc0;
++static struct clk osc1;
++
+ static unsigned long osc_get_rate(struct clk *clk)
+ {
+ return at32ap7000_osc_rates[clk->index];
+@@ -107,9 +112,6 @@ static unsigned long pll_get_rate(struct clk *clk, unsigned long control)
+ {
+ unsigned long div, mul, rate;
+
+- if (!(control & PM_BIT(PLLEN)))
+- return 0;
+-
+ div = PM_BFEXT(PLLDIV, control) + 1;
+ mul = PM_BFEXT(PLLMUL, control) + 1;
+
+@@ -120,6 +122,71 @@ static unsigned long pll_get_rate(struct clk *clk, unsigned long control)
+ return rate;
+ }
+
++static long pll_set_rate(struct clk *clk, unsigned long rate,
++ u32 *pll_ctrl)
++{
++ unsigned long mul;
++ unsigned long mul_best_fit = 0;
++ unsigned long div;
++ unsigned long div_min;
++ unsigned long div_max;
++ unsigned long div_best_fit = 0;
++ unsigned long base;
++ unsigned long pll_in;
++ unsigned long actual = 0;
++ unsigned long rate_error;
++ unsigned long rate_error_prev = ~0UL;
++ u32 ctrl;
++
++ /* Rate must be between 80 MHz and 200 Mhz. */
++ if (rate < 80000000UL || rate > 200000000UL)
++ return -EINVAL;
++
++ ctrl = PM_BF(PLLOPT, 4);
++ base = clk->parent->get_rate(clk->parent);
++
++ /* PLL input frequency must be between 6 MHz and 32 MHz. */
++ div_min = DIV_ROUND_UP(base, 32000000UL);
++ div_max = base / 6000000UL;
++
++ if (div_max < div_min)
++ return -EINVAL;
++
++ for (div = div_min; div <= div_max; div++) {
++ pll_in = (base + div / 2) / div;
++ mul = (rate + pll_in / 2) / pll_in;
++
++ if (mul == 0)
++ continue;
++
++ actual = pll_in * mul;
++ rate_error = abs(actual - rate);
++
++ if (rate_error < rate_error_prev) {
++ mul_best_fit = mul;
++ div_best_fit = div;
++ rate_error_prev = rate_error;
++ }
++
++ if (rate_error == 0)
++ break;
++ }
++
++ if (div_best_fit == 0)
++ return -EINVAL;
++
++ ctrl |= PM_BF(PLLMUL, mul_best_fit - 1);
++ ctrl |= PM_BF(PLLDIV, div_best_fit - 1);
++ ctrl |= PM_BF(PLLCOUNT, 16);
++
++ if (clk->parent == &osc1)
++ ctrl |= PM_BIT(PLLOSC);
++
++ *pll_ctrl = ctrl;
++
++ return actual;
++}
++
+ static unsigned long pll0_get_rate(struct clk *clk)
+ {
+ u32 control;
+@@ -129,6 +196,41 @@ static unsigned long pll0_get_rate(struct clk *clk)
+ return pll_get_rate(clk, control);
+ }
+
++static void pll1_mode(struct clk *clk, int enabled)
++{
++ unsigned long timeout;
++ u32 status;
++ u32 ctrl;
++
++ ctrl = pm_readl(PLL1);
++
++ if (enabled) {
++ if (!PM_BFEXT(PLLMUL, ctrl) && !PM_BFEXT(PLLDIV, ctrl)) {
++ pr_debug("clk %s: failed to enable, rate not set\n",
++ clk->name);
++ return;
++ }
++
++ ctrl |= PM_BIT(PLLEN);
++ pm_writel(PLL1, ctrl);
++
++ /* Wait for PLL lock. */
++ for (timeout = 10000; timeout; timeout--) {
++ status = pm_readl(ISR);
++ if (status & PM_BIT(LOCK1))
++ break;
++ udelay(10);
++ }
++
++ if (!(status & PM_BIT(LOCK1)))
++ printk(KERN_ERR "clk %s: timeout waiting for lock\n",
++ clk->name);
++ } else {
++ ctrl &= ~PM_BIT(PLLEN);
++ pm_writel(PLL1, ctrl);
++ }
++}
++
+ static unsigned long pll1_get_rate(struct clk *clk)
+ {
+ u32 control;
+@@ -138,6 +240,49 @@ static unsigned long pll1_get_rate(struct clk *clk)
+ return pll_get_rate(clk, control);
+ }
+
++static long pll1_set_rate(struct clk *clk, unsigned long rate, int apply)
++{
++ u32 ctrl = 0;
++ unsigned long actual_rate;
++
++ actual_rate = pll_set_rate(clk, rate, &ctrl);
++
++ if (apply) {
++ if (actual_rate != rate)
++ return -EINVAL;
++ if (clk->users > 0)
++ return -EBUSY;
++ pr_debug(KERN_INFO "clk %s: new rate %lu (actual rate %lu)\n",
++ clk->name, rate, actual_rate);
++ pm_writel(PLL1, ctrl);
++ }
++
++ return actual_rate;
++}
++
++static int pll1_set_parent(struct clk *clk, struct clk *parent)
++{
++ u32 ctrl;
++
++ if (clk->users > 0)
++ return -EBUSY;
++
++ ctrl = pm_readl(PLL1);
++ WARN_ON(ctrl & PM_BIT(PLLEN));
++
++ if (parent == &osc0)
++ ctrl &= ~PM_BIT(PLLOSC);
++ else if (parent == &osc1)
++ ctrl |= PM_BIT(PLLOSC);
++ else
++ return -EINVAL;
++
++ pm_writel(PLL1, ctrl);
++ clk->parent = parent;
++
++ return 0;
++}
++
+ /*
+ * The AT32AP7000 has five primary clock sources: One 32kHz
+ * oscillator, two crystal oscillators and two PLLs.
+@@ -166,7 +311,10 @@ static struct clk pll0 = {
+ };
+ static struct clk pll1 = {
+ .name = "pll1",
++ .mode = pll1_mode,
+ .get_rate = pll1_get_rate,
++ .set_rate = pll1_set_rate,
++ .set_parent = pll1_set_parent,
+ .parent = &osc0,
+ };
+
+@@ -605,19 +753,32 @@ static inline void set_ebi_sfr_bits(u32 mask)
+ }
+
+ /* --------------------------------------------------------------------
+- * System Timer/Counter (TC)
++ * Timer/Counter (TC)
+ * -------------------------------------------------------------------- */
+-static struct resource at32_systc0_resource[] = {
++
++static struct resource at32_tcb0_resource[] = {
+ PBMEM(0xfff00c00),
+ IRQ(22),
+ };
+-struct platform_device at32_systc0_device = {
+- .name = "systc",
++static struct platform_device at32_tcb0_device = {
++ .name = "atmel_tcb",
+ .id = 0,
+- .resource = at32_systc0_resource,
+- .num_resources = ARRAY_SIZE(at32_systc0_resource),
++ .resource = at32_tcb0_resource,
++ .num_resources = ARRAY_SIZE(at32_tcb0_resource),
+ };
+-DEV_CLK(pclk, at32_systc0, pbb, 3);
++DEV_CLK(t0_clk, at32_tcb0, pbb, 3);
++
++static struct resource at32_tcb1_resource[] = {
++ PBMEM(0xfff01000),
++ IRQ(23),
++};
++static struct platform_device at32_tcb1_device = {
++ .name = "atmel_tcb",
++ .id = 1,
++ .resource = at32_tcb1_resource,
++ .num_resources = ARRAY_SIZE(at32_tcb1_resource),
++};
++DEV_CLK(t0_clk, at32_tcb1, pbb, 4);
+
+ /* --------------------------------------------------------------------
+ * PIO
+@@ -669,7 +830,8 @@ void __init at32_add_system_devices(void)
+ platform_device_register(&pdc_device);
+ platform_device_register(&dmaca0_device);
+
+- platform_device_register(&at32_systc0_device);
++ platform_device_register(&at32_tcb0_device);
++ platform_device_register(&at32_tcb1_device);
+
+ platform_device_register(&pio0_device);
+ platform_device_register(&pio1_device);
+@@ -989,7 +1151,9 @@ static struct clk atmel_twi0_pclk = {
+ .index = 2,
+ };
+
+-struct platform_device *__init at32_add_device_twi(unsigned int id)
++struct platform_device *__init at32_add_device_twi(unsigned int id,
++ struct i2c_board_info *b,
++ unsigned int n)
+ {
+ struct platform_device *pdev;
+
+@@ -1009,6 +1173,9 @@ struct platform_device *__init at32_add_device_twi(unsigned int id)
+
+ atmel_twi0_pclk.dev = &pdev->dev;
+
++ if (b)
++ i2c_register_board_info(id, b, n);
++
+ platform_device_add(pdev);
+ return pdev;
+
+@@ -1351,9 +1518,39 @@ static struct clk usba0_hclk = {
+ .index = 6,
+ };
+
++#define EP(nam, idx, maxpkt, maxbk, dma, isoc) \
++ [idx] = { \
++ .name = nam, \
++ .index = idx, \
++ .fifo_size = maxpkt, \
++ .nr_banks = maxbk, \
++ .can_dma = dma, \
++ .can_isoc = isoc, \
++ }
++
++static struct usba_ep_data at32_usba_ep[] __initdata = {
++ EP("ep0", 0, 64, 1, 0, 0),
++ EP("ep1", 1, 512, 2, 1, 1),
++ EP("ep2", 2, 512, 2, 1, 1),
++ EP("ep3-int", 3, 64, 3, 1, 0),
++ EP("ep4-int", 4, 64, 3, 1, 0),
++ EP("ep5", 5, 1024, 3, 1, 1),
++ EP("ep6", 6, 1024, 3, 1, 1),
++};
++
++#undef EP
++
+ struct platform_device *__init
+ at32_add_device_usba(unsigned int id, struct usba_platform_data *data)
+ {
++ /*
++ * pdata doesn't have room for any endpoints, so we need to
++ * append room for the ones we need right after it.
++ */
++ struct {
++ struct usba_platform_data pdata;
++ struct usba_ep_data ep[7];
++ } usba_data;
+ struct platform_device *pdev;
+
+ if (id != 0)
+@@ -1367,13 +1564,20 @@ at32_add_device_usba(unsigned int id, struct usba_platform_data *data)
+ ARRAY_SIZE(usba0_resource)))
+ goto out_free_pdev;
+
+- if (data) {
+- if (platform_device_add_data(pdev, data, sizeof(*data)))
+- goto out_free_pdev;
++ if (data)
++ usba_data.pdata.vbus_pin = data->vbus_pin;
++ else
++ usba_data.pdata.vbus_pin = -EINVAL;
++
++ data = &usba_data.pdata;
++ data->num_ep = ARRAY_SIZE(at32_usba_ep);
++ memcpy(data->ep, at32_usba_ep, sizeof(at32_usba_ep));
+
+- if (data->vbus_pin != GPIO_PIN_NONE)
+- at32_select_gpio(data->vbus_pin, 0);
+- }
++ if (platform_device_add_data(pdev, data, sizeof(usba_data)))
++ goto out_free_pdev;
++
++ if (data->vbus_pin >= 0)
++ at32_select_gpio(data->vbus_pin, 0);
+
+ usba0_pclk.dev = &pdev->dev;
+ usba0_hclk.dev = &pdev->dev;
+@@ -1694,7 +1898,8 @@ struct clk *at32_clock_list[] = {
+ &pio2_mck,
+ &pio3_mck,
+ &pio4_mck,
+- &at32_systc0_pclk,
++ &at32_tcb0_t0_clk,
++ &at32_tcb1_t0_clk,
+ &atmel_usart0_usart,
+ &atmel_usart1_usart,
+ &atmel_usart2_usart,
+diff --git a/arch/avr32/mach-at32ap/intc.c b/arch/avr32/mach-at32ap/intc.c
+index 0b286cd..097cf4e 100644
+--- a/arch/avr32/mach-at32ap/intc.c
++++ b/arch/avr32/mach-at32ap/intc.c
+@@ -13,7 +13,6 @@
+ #include <linux/irq.h>
+ #include <linux/platform_device.h>
+
+-#include <asm/intc.h>
+ #include <asm/io.h>
+
+ #include "intc.h"
+diff --git a/arch/avr32/mach-at32ap/pm-at32ap700x.S b/arch/avr32/mach-at32ap/pm-at32ap700x.S
+new file mode 100644
+index 0000000..949e248
+--- /dev/null
++++ b/arch/avr32/mach-at32ap/pm-at32ap700x.S
+@@ -0,0 +1,66 @@
++/*
++ * Low-level Power Management code.
++ *
++ * Copyright (C) 2008 Atmel Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <asm/asm.h>
++#include <asm/asm-offsets.h>
++#include <asm/thread_info.h>
++#include <asm/arch/pm.h>
++
++ .section .bss, "wa", @nobits
++ .global disable_idle_sleep
++ .type disable_idle_sleep, @object
++disable_idle_sleep:
++ .int 4
++ .size disable_idle_sleep, . - disable_idle_sleep
++
++ /* Keep this close to the irq handlers */
++ .section .irq.text, "ax", @progbits
++
++ /*
++ * void cpu_enter_idle(void)
++ *
++ * Put the CPU into "idle" mode, in which it will consume
++ * significantly less power.
++ *
++ * If an interrupt comes along in the window between
++ * unmask_interrupts and the sleep instruction below, the
++ * interrupt code will adjust the return address so that we
++ * never execute the sleep instruction. This is required
++ * because the AP7000 doesn't unmask interrupts when entering
++ * sleep modes; later CPUs may not need this workaround.
++ */
++ .global cpu_enter_idle
++ .type cpu_enter_idle, @function
++cpu_enter_idle:
++ mask_interrupts
++ get_thread_info r8
++ ld.w r9, r8[TI_flags]
++ bld r9, TIF_NEED_RESCHED
++ brcs .Lret_from_sleep
++ sbr r9, TIF_CPU_GOING_TO_SLEEP
++ st.w r8[TI_flags], r9
++ unmask_interrupts
++ sleep CPU_SLEEP_IDLE
++ .size cpu_idle_sleep, . - cpu_idle_sleep
++
++ /*
++ * Common return path for PM functions that don't run from
++ * SRAM.
++ */
++ .global cpu_idle_skip_sleep
++ .type cpu_idle_skip_sleep, @function
++cpu_idle_skip_sleep:
++ mask_interrupts
++ ld.w r9, r8[TI_flags]
++ cbr r9, TIF_CPU_GOING_TO_SLEEP
++ st.w r8[TI_flags], r9
++.Lret_from_sleep:
++ unmask_interrupts
++ retal r12
++ .size cpu_idle_skip_sleep, . - cpu_idle_skip_sleep
+diff --git a/arch/avr32/mach-at32ap/time-tc.c b/arch/avr32/mach-at32ap/time-tc.c
+deleted file mode 100644
+index 1026586..0000000
+--- a/arch/avr32/mach-at32ap/time-tc.c
++++ /dev/null
+@@ -1,218 +0,0 @@
+-/*
+- * Copyright (C) 2004-2007 Atmel Corporation
+- *
+- * Based on MIPS implementation arch/mips/kernel/time.c
+- * Copyright 2001 MontaVista Software Inc.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#include <linux/clk.h>
+-#include <linux/clocksource.h>
+-#include <linux/time.h>
+-#include <linux/module.h>
+-#include <linux/interrupt.h>
+-#include <linux/irq.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/errno.h>
+-#include <linux/init.h>
+-#include <linux/profile.h>
+-#include <linux/sysdev.h>
+-#include <linux/err.h>
+-
+-#include <asm/div64.h>
+-#include <asm/sysreg.h>
+-#include <asm/io.h>
+-#include <asm/sections.h>
+-
+-#include <asm/arch/time.h>
+-
+-/* how many counter cycles in a jiffy? */
+-static u32 cycles_per_jiffy;
+-
+-/* the count value for the next timer interrupt */
+-static u32 expirelo;
+-
+-/* the I/O registers of the TC module */
+-static void __iomem *ioregs;
+-
+-cycle_t read_cycle_count(void)
+-{
+- return (cycle_t)timer_read(ioregs, 0, CV);
+-}
+-
+-struct clocksource clocksource_avr32 = {
+- .name = "avr32",
+- .rating = 342,
+- .read = read_cycle_count,
+- .mask = CLOCKSOURCE_MASK(16),
+- .shift = 16,
+- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+-};
+-
+-static void avr32_timer_ack(void)
+-{
+- u16 count = expirelo;
+-
+- /* Ack this timer interrupt and set the next one, use a u16
+- * variable so it will wrap around correctly */
+- count += cycles_per_jiffy;
+- expirelo = count;
+- timer_write(ioregs, 0, RC, expirelo);
+-
+- /* Check to see if we have missed any timer interrupts */
+- count = timer_read(ioregs, 0, CV);
+- if ((count - expirelo) < 0x7fff) {
+- expirelo = count + cycles_per_jiffy;
+- timer_write(ioregs, 0, RC, expirelo);
+- }
+-}
+-
+-u32 avr32_hpt_read(void)
+-{
+- return timer_read(ioregs, 0, CV);
+-}
+-
+-static int avr32_timer_calc_div_and_set_jiffies(struct clk *pclk)
+-{
+- unsigned int cycles_max = (clocksource_avr32.mask + 1) / 2;
+- unsigned int divs[] = { 4, 8, 16, 32 };
+- int divs_size = ARRAY_SIZE(divs);
+- int i = 0;
+- unsigned long count_hz;
+- unsigned long shift;
+- unsigned long mult;
+- int clock_div = -1;
+- u64 tmp;
+-
+- shift = clocksource_avr32.shift;
+-
+- do {
+- count_hz = clk_get_rate(pclk) / divs[i];
+- mult = clocksource_hz2mult(count_hz, shift);
+- clocksource_avr32.mult = mult;
+-
+- tmp = TICK_NSEC;
+- tmp <<= shift;
+- tmp += mult / 2;
+- do_div(tmp, mult);
+-
+- cycles_per_jiffy = tmp;
+- } while (cycles_per_jiffy > cycles_max && ++i < divs_size);
+-
+- clock_div = i + 1;
+-
+- if (clock_div > divs_size) {
+- pr_debug("timer: could not calculate clock divider\n");
+- return -EFAULT;
+- }
+-
+- /* Set the clock divider */
+- timer_write(ioregs, 0, CMR, TIMER_BF(CMR_TCCLKS, clock_div));
+-
+- return 0;
+-}
+-
+-int avr32_hpt_init(unsigned int count)
+-{
+- struct resource *regs;
+- struct clk *pclk;
+- int irq = -1;
+- int ret = 0;
+-
+- ret = -ENXIO;
+-
+- irq = platform_get_irq(&at32_systc0_device, 0);
+- if (irq < 0) {
+- pr_debug("timer: could not get irq\n");
+- goto out_error;
+- }
+-
+- pclk = clk_get(&at32_systc0_device.dev, "pclk");
+- if (IS_ERR(pclk)) {
+- pr_debug("timer: could not get clk: %ld\n", PTR_ERR(pclk));
+- goto out_error;
+- }
+- clk_enable(pclk);
+-
+- regs = platform_get_resource(&at32_systc0_device, IORESOURCE_MEM, 0);
+- if (!regs) {
+- pr_debug("timer: could not get resource\n");
+- goto out_error_clk;
+- }
+-
+- ioregs = ioremap(regs->start, regs->end - regs->start + 1);
+- if (!ioregs) {
+- pr_debug("timer: could not get ioregs\n");
+- goto out_error_clk;
+- }
+-
+- ret = avr32_timer_calc_div_and_set_jiffies(pclk);
+- if (ret)
+- goto out_error_io;
+-
+- ret = setup_irq(irq, &timer_irqaction);
+- if (ret) {
+- pr_debug("timer: could not request irq %d: %d\n",
+- irq, ret);
+- goto out_error_io;
+- }
+-
+- expirelo = (timer_read(ioregs, 0, CV) / cycles_per_jiffy + 1)
+- * cycles_per_jiffy;
+-
+- /* Enable clock and interrupts on RC compare */
+- timer_write(ioregs, 0, CCR, TIMER_BIT(CCR_CLKEN));
+- timer_write(ioregs, 0, IER, TIMER_BIT(IER_CPCS));
+- /* Set cycles to first interrupt */
+- timer_write(ioregs, 0, RC, expirelo);
+-
+- printk(KERN_INFO "timer: AT32AP system timer/counter at 0x%p irq %d\n",
+- ioregs, irq);
+-
+- return 0;
+-
+-out_error_io:
+- iounmap(ioregs);
+-out_error_clk:
+- clk_put(pclk);
+-out_error:
+- return ret;
+-}
+-
+-int avr32_hpt_start(void)
+-{
+- timer_write(ioregs, 0, CCR, TIMER_BIT(CCR_SWTRG));
+- return 0;
+-}
+-
+-irqreturn_t timer_interrupt(int irq, void *dev_id)
+-{
+- unsigned int sr = timer_read(ioregs, 0, SR);
+-
+- if (sr & TIMER_BIT(SR_CPCS)) {
+- /* ack timer interrupt and try to set next interrupt */
+- avr32_timer_ack();
+-
+- /*
+- * Call the generic timer interrupt handler
+- */
+- write_seqlock(&xtime_lock);
+- do_timer(1);
+- write_sequnlock(&xtime_lock);
+-
+- /*
+- * In UP mode, we call local_timer_interrupt() to do profiling
+- * and process accounting.
+- *
+- * SMP is not supported yet.
+- */
+- local_timer_interrupt(irq, dev_id);
+-
+- return IRQ_HANDLED;
+- }
+-
+- return IRQ_NONE;
+-}
+diff --git a/arch/avr32/mm/init.c b/arch/avr32/mm/init.c
+index 480760b..0e64ddc 100644
+--- a/arch/avr32/mm/init.c
++++ b/arch/avr32/mm/init.c
+@@ -34,9 +34,6 @@ struct page *empty_zero_page;
+ */
+ unsigned long mmu_context_cache = NO_CONTEXT;
+
+-#define START_PFN (NODE_DATA(0)->bdata->node_boot_start >> PAGE_SHIFT)
+-#define MAX_LOW_PFN (NODE_DATA(0)->bdata->node_low_pfn)
+-
+ void show_mem(void)
+ {
+ int total = 0, reserved = 0, cached = 0;
+diff --git a/arch/avr32/oprofile/op_model_avr32.c b/arch/avr32/oprofile/op_model_avr32.c
+index e2f876b..df42325 100644
+--- a/arch/avr32/oprofile/op_model_avr32.c
++++ b/arch/avr32/oprofile/op_model_avr32.c
+@@ -16,7 +16,6 @@
+ #include <linux/sched.h>
+ #include <linux/types.h>
+
+-#include <asm/intc.h>
+ #include <asm/sysreg.h>
+ #include <asm/system.h>
+
+diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
+index 589c6ac..795d0ac 100644
+--- a/arch/blackfin/Kconfig
++++ b/arch/blackfin/Kconfig
+@@ -31,10 +31,6 @@ config ZONE_DMA
+ bool
+ default y
+
+-config SEMAPHORE_SLEEPERS
+- bool
+- default y
+-
+ config GENERIC_FIND_NEXT_BIT
+ bool
+ default y
+@@ -51,10 +47,6 @@ config GENERIC_IRQ_PROBE
+ bool
+ default y
+
+-config GENERIC_TIME
+- bool
+- default n
+-
+ config GENERIC_GPIO
+ bool
+ default y
+@@ -228,16 +220,6 @@ config BF54x
+ depends on (BF542 || BF544 || BF547 || BF548 || BF549)
+ default y
+
+-config BFIN_DUAL_CORE
+- bool
+- depends on (BF561)
+- default y
+-
+-config BFIN_SINGLE_CORE
+- bool
+- depends on !BFIN_DUAL_CORE
+- default y
+-
+ config MEM_GENERIC_BOARD
+ bool
+ depends on GENERIC_BOARD
+@@ -267,7 +249,7 @@ config MEM_MT48LC8M32B2B5_7
+
+ config MEM_MT48LC32M16A2TG_75
+ bool
+- depends on (BFIN527_EZKIT)
++ depends on (BFIN527_EZKIT || BFIN532_IP0X)
+ default y
+
+ source "arch/blackfin/mach-bf527/Kconfig"
+@@ -290,17 +272,34 @@ config CMDLINE
+ to the kernel, you may specify one here. As a minimum, you should specify
+ the memory size and the root device (e.g., mem=8M, root=/dev/nfs).
+
++config BOOT_LOAD
++ hex "Kernel load address for booting"
++ default "0x1000"
++ range 0x1000 0x20000000
++ help
++ This option allows you to set the load address of the kernel.
++ This can be useful if you are on a board which has a small amount
++ of memory or you wish to reserve some memory at the beginning of
++ the address space.
++
++ Note that you need to keep this value above 4k (0x1000) as this
++ memory region is used to capture NULL pointer references as well
++ as some core kernel functions.
++
+ comment "Clock/PLL Setup"
+
+ config CLKIN_HZ
+- int "Crystal Frequency in Hz"
++ int "Frequency of the crystal on the board in Hz"
+ default "11059200" if BFIN533_STAMP
+ default "27000000" if BFIN533_EZKIT
+ default "25000000" if (BFIN537_STAMP || BFIN527_EZKIT || H8606_HVSISTEMAS)
+ default "30000000" if BFIN561_EZKIT
+ default "24576000" if PNAV10
++ default "10000000" if BFIN532_IP0X
+ help
+ The frequency of CLKIN crystal oscillator on the board in Hz.
++ Warning: This value should match the crystal on the board. Otherwise,
++ peripherals won't work properly.
+
+ config BFIN_KERNEL_CLOCK
+ bool "Re-program Clocks while Kernel boots?"
+@@ -311,6 +310,25 @@ config BFIN_KERNEL_CLOCK
+ are also not changed, and the Bootloader does 100% of the hardware
+ configuration.
+
++config MEM_SIZE
++ int "SDRAM Memory Size in MBytes"
++ depends on BFIN_KERNEL_CLOCK
++ default 64
++
++config MEM_ADD_WIDTH
++ int "Memory Address Width"
++ depends on BFIN_KERNEL_CLOCK
++ depends on (!BF54x)
++ range 8 11
++ default 9 if BFIN533_EZKIT
++ default 9 if BFIN561_EZKIT
++ default 9 if H8606_HVSISTEMAS
++ default 10 if BFIN527_EZKIT
++ default 10 if BFIN537_STAMP
++ default 11 if BFIN533_STAMP
++ default 10 if PNAV10
++ default 10 if BFIN532_IP0X
++
+ config PLL_BYPASS
+ bool "Bypass PLL"
+ depends on BFIN_KERNEL_CLOCK
+@@ -329,7 +347,7 @@ config VCO_MULT
+ range 1 64
+ default "22" if BFIN533_EZKIT
+ default "45" if BFIN533_STAMP
+- default "20" if (BFIN537_STAMP || BFIN527_EZKIT || BFIN548_EZKIT)
++ default "20" if (BFIN537_STAMP || BFIN527_EZKIT || BFIN548_EZKIT || BFIN548_BLUETECHNIX_CM)
+ default "22" if BFIN533_BLUETECHNIX_CM
+ default "20" if BFIN537_BLUETECHNIX_CM
+ default "20" if BFIN561_BLUETECHNIX_CM
+@@ -364,19 +382,33 @@ config SCLK_DIV
+ int "System Clock Divider"
+ depends on BFIN_KERNEL_CLOCK
+ range 1 15
+- default 5 if BFIN533_EZKIT
+- default 5 if BFIN533_STAMP
+- default 4 if (BFIN537_STAMP || BFIN527_EZKIT || BFIN548_EZKIT)
+- default 5 if BFIN533_BLUETECHNIX_CM
+- default 4 if BFIN537_BLUETECHNIX_CM
+- default 4 if BFIN561_BLUETECHNIX_CM
+- default 5 if BFIN561_EZKIT
+- default 3 if H8606_HVSISTEMAS
++ default 5
+ help
+ This sets the frequency of the system clock (including SDRAM or DDR).
+ This can be between 1 and 15
+ System Clock = (PLL frequency) / (this setting)
+
++config MAX_MEM_SIZE
++ int "Max SDRAM Memory Size in MBytes"
++ depends on !BFIN_KERNEL_CLOCK && !MPU
++ default 512
++ help
++ This is the max memory size that the kernel will create CPLB
++ tables for. Your system will not be able to handle any more.
++
++choice
++ prompt "DDR SDRAM Chip Type"
++ depends on BFIN_KERNEL_CLOCK
++ depends on BF54x
++ default MEM_MT46V32M16_5B
++
++config MEM_MT46V32M16_6T
++ bool "MT46V32M16_6T"
++
++config MEM_MT46V32M16_5B
++ bool "MT46V32M16_5B"
++endchoice
++
+ #
+ # Max & Min Speeds for various Chips
+ #
+@@ -419,42 +451,33 @@ comment "Kernel Timer/Scheduler"
+
+ source kernel/Kconfig.hz
+
+-comment "Memory Setup"
+-
+-config MEM_SIZE
+- int "SDRAM Memory Size in MBytes"
+- default 32 if BFIN533_EZKIT
+- default 64 if BFIN527_EZKIT
+- default 64 if BFIN537_STAMP
+- default 64 if BFIN548_EZKIT
+- default 64 if BFIN561_EZKIT
+- default 128 if BFIN533_STAMP
+- default 64 if PNAV10
+- default 32 if H8606_HVSISTEMAS
++config GENERIC_TIME
++ bool "Generic time"
++ default y
+
+-config MEM_ADD_WIDTH
+- int "SDRAM Memory Address Width"
+- depends on (!BF54x)
+- default 9 if BFIN533_EZKIT
+- default 9 if BFIN561_EZKIT
+- default 9 if H8606_HVSISTEMAS
+- default 10 if BFIN527_EZKIT
+- default 10 if BFIN537_STAMP
+- default 11 if BFIN533_STAMP
+- default 10 if PNAV10
++config GENERIC_CLOCKEVENTS
++ bool "Generic clock events"
++ depends on GENERIC_TIME
++ default y
+
++config CYCLES_CLOCKSOURCE
++ bool "Use 'CYCLES' as a clocksource (EXPERIMENTAL)"
++ depends on EXPERIMENTAL
++ depends on GENERIC_CLOCKEVENTS
++ depends on !BFIN_SCRATCH_REG_CYCLES
++ default n
++ help
++ If you say Y here, you will enable support for using the 'cycles'
++ registers as a clock source. Doing so means you will be unable to
++ safely write to the 'cycles' register during runtime. You will
++ still be able to read it (such as for performance monitoring), but
++ writing the registers will most likely crash the kernel.
+
+-choice
+- prompt "DDR SDRAM Chip Type"
+- depends on BFIN548_EZKIT
+- default MEM_MT46V32M16_5B
++source kernel/time/Kconfig
+
+-config MEM_MT46V32M16_6T
+- bool "MT46V32M16_6T"
++comment "Memory Setup"
+
+-config MEM_MT46V32M16_5B
+- bool "MT46V32M16_5B"
+-endchoice
++comment "Misc"
+
+ config ENET_FLASH_PIN
+ int "PF port/pin used for flash and ethernet sharing"
+@@ -466,20 +489,6 @@ config ENET_FLASH_PIN
+ code.
+ For example: PF0 --> 0,PF1 --> 1,PF2 --> 2, etc.
+
+-config BOOT_LOAD
+- hex "Kernel load address for booting"
+- default "0x1000"
+- range 0x1000 0x20000000
+- help
+- This option allows you to set the load address of the kernel.
+- This can be useful if you are on a board which has a small amount
+- of memory or you wish to reserve some memory at the beginning of
+- the address space.
+-
+- Note that you need to keep this value above 4k (0x1000) as this
+- memory region is used to capture NULL pointer references as well
+- as some core kernel functions.
+-
+ choice
+ prompt "Blackfin Exception Scratch Register"
+ default BFIN_SCRATCH_REG_RETN
+@@ -665,14 +674,6 @@ endchoice
+
+ source "mm/Kconfig"
+
+-config LARGE_ALLOCS
+- bool "Allow allocating large blocks (> 1MB) of memory"
+- help
+- Allow the slab memory allocator to keep chains for very large
+- memory sizes - upto 32MB. You may need this if your system has
+- a lot of RAM, and you need to able to allocate very large
+- contiguous chunks. If unsure, say N.
+-
+ config BFIN_GPTIMERS
+ tristate "Enable Blackfin General Purpose Timers API"
+ default n
+diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile
+index 75eba2c..3cbe16c 100644
+--- a/arch/blackfin/Makefile
++++ b/arch/blackfin/Makefile
+@@ -72,6 +72,11 @@ rev-$(CONFIG_BF_REV_ANY) := any
+ KBUILD_CFLAGS += -mcpu=$(cpu-y)-$(rev-y)
+ KBUILD_AFLAGS += -mcpu=$(cpu-y)-$(rev-y)
+
++# - we utilize the silicon rev from the toolchain, so move it over to the checkflags
++# - the l1_text attribute is Blackfin specific, so fake it out as used to kill warnings
++CHECKFLAGS_SILICON = $(shell echo "" | $(CPP) $(KBUILD_CFLAGS) -dD - 2>/dev/null | awk '$$2 == "__SILICON_REVISION__" { print $$3 }')
++CHECKFLAGS += -D__SILICON_REVISION__=$(CHECKFLAGS_SILICON) -Dl1_text=__used__
++
+ head-y := arch/$(ARCH)/mach-$(MACHINE)/head.o arch/$(ARCH)/kernel/init_task.o
+
+ core-y += arch/$(ARCH)/kernel/ arch/$(ARCH)/mm/ arch/$(ARCH)/mach-common/
+diff --git a/arch/blackfin/boot/.gitignore b/arch/blackfin/boot/.gitignore
+new file mode 100644
+index 0000000..3ae0399
+--- /dev/null
++++ b/arch/blackfin/boot/.gitignore
+@@ -0,0 +1 @@
+++vmImage
+diff --git a/arch/blackfin/configs/BF527-EZKIT_defconfig b/arch/blackfin/configs/BF527-EZKIT_defconfig
+index ae320dc..64876df 100644
+--- a/arch/blackfin/configs/BF527-EZKIT_defconfig
++++ b/arch/blackfin/configs/BF527-EZKIT_defconfig
+@@ -13,7 +13,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_HARDIRQS=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+-# CONFIG_GENERIC_TIME is not set
++CONFIG_GENERIC_TIME=y
+ CONFIG_GENERIC_GPIO=y
+ CONFIG_FORCE_MAX_ZONEORDER=14
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
+@@ -250,7 +250,7 @@ CONFIG_HZ=250
+ #
+ # Memory Setup
+ #
+-CONFIG_MEM_SIZE=64
++CONFIG_MAX_MEM_SIZE=512
+ CONFIG_MEM_ADD_WIDTH=10
+ CONFIG_BOOT_LOAD=0x1000
+ CONFIG_BFIN_SCRATCH_REG_RETN=y
+@@ -720,8 +720,8 @@ CONFIG_BFIN_OTP=y
+ #
+ CONFIG_SERIAL_BFIN=y
+ CONFIG_SERIAL_BFIN_CONSOLE=y
+-# CONFIG_SERIAL_BFIN_DMA is not set
+-CONFIG_SERIAL_BFIN_PIO=y
++CONFIG_SERIAL_BFIN_DMA=y
++# CONFIG_SERIAL_BFIN_PIO is not set
+ # CONFIG_SERIAL_BFIN_UART0 is not set
+ CONFIG_SERIAL_BFIN_UART1=y
+ # CONFIG_BFIN_UART1_CTSRTS is not set
+diff --git a/arch/blackfin/configs/BF533-EZKIT_defconfig b/arch/blackfin/configs/BF533-EZKIT_defconfig
+index 9621caa..8d817ba 100644
+--- a/arch/blackfin/configs/BF533-EZKIT_defconfig
++++ b/arch/blackfin/configs/BF533-EZKIT_defconfig
+@@ -13,7 +13,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_HARDIRQS=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+-# CONFIG_GENERIC_TIME is not set
++CONFIG_GENERIC_TIME=y
+ CONFIG_GENERIC_GPIO=y
+ CONFIG_FORCE_MAX_ZONEORDER=14
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
+@@ -212,7 +212,7 @@ CONFIG_HZ=250
+ #
+ # Memory Setup
+ #
+-CONFIG_MEM_SIZE=32
++CONFIG_MAX_MEM_SIZE=512
+ CONFIG_MEM_ADD_WIDTH=9
+ CONFIG_BOOT_LOAD=0x1000
+ CONFIG_BFIN_SCRATCH_REG_RETN=y
+diff --git a/arch/blackfin/configs/BF533-STAMP_defconfig b/arch/blackfin/configs/BF533-STAMP_defconfig
+index b51e76c..20d598d 100644
+--- a/arch/blackfin/configs/BF533-STAMP_defconfig
++++ b/arch/blackfin/configs/BF533-STAMP_defconfig
+@@ -13,7 +13,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_HARDIRQS=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+-# CONFIG_GENERIC_TIME is not set
++CONFIG_GENERIC_TIME=y
+ CONFIG_GENERIC_GPIO=y
+ CONFIG_FORCE_MAX_ZONEORDER=14
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
+@@ -212,7 +212,7 @@ CONFIG_HZ=250
+ #
+ # Memory Setup
+ #
+-CONFIG_MEM_SIZE=128
++CONFIG_MAX_MEM_SIZE=512
+ CONFIG_MEM_ADD_WIDTH=11
+ CONFIG_ENET_FLASH_PIN=0
+ CONFIG_BOOT_LOAD=0x1000
+diff --git a/arch/blackfin/configs/BF537-STAMP_defconfig b/arch/blackfin/configs/BF537-STAMP_defconfig
+index d45fa53..b5189c8 100644
+--- a/arch/blackfin/configs/BF537-STAMP_defconfig
++++ b/arch/blackfin/configs/BF537-STAMP_defconfig
+@@ -13,7 +13,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_HARDIRQS=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+-# CONFIG_GENERIC_TIME is not set
++CONFIG_GENERIC_TIME=y
+ CONFIG_GENERIC_GPIO=y
+ CONFIG_FORCE_MAX_ZONEORDER=14
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
+@@ -220,7 +220,7 @@ CONFIG_HZ=250
+ #
+ # Memory Setup
+ #
+-CONFIG_MEM_SIZE=64
++CONFIG_MAX_MEM_SIZE=512
+ CONFIG_MEM_ADD_WIDTH=10
+ CONFIG_BOOT_LOAD=0x1000
+ CONFIG_BFIN_SCRATCH_REG_RETN=y
+diff --git a/arch/blackfin/configs/BF548-EZKIT_defconfig b/arch/blackfin/configs/BF548-EZKIT_defconfig
+index c9707f7..5bfdfb2 100644
+--- a/arch/blackfin/configs/BF548-EZKIT_defconfig
++++ b/arch/blackfin/configs/BF548-EZKIT_defconfig
+@@ -13,7 +13,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_HARDIRQS=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+-# CONFIG_GENERIC_TIME is not set
++CONFIG_GENERIC_TIME=y
+ CONFIG_GENERIC_GPIO=y
+ CONFIG_FORCE_MAX_ZONEORDER=14
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
+@@ -285,7 +285,7 @@ CONFIG_HZ=250
+ #
+ # Memory Setup
+ #
+-CONFIG_MEM_SIZE=64
++CONFIG_MAX_MEM_SIZE=512
+ # CONFIG_MEM_MT46V32M16_6T is not set
+ CONFIG_MEM_MT46V32M16_5B=y
+ CONFIG_BOOT_LOAD=0x1000
+@@ -813,8 +813,8 @@ CONFIG_HW_CONSOLE=y
+ #
+ CONFIG_SERIAL_BFIN=y
+ CONFIG_SERIAL_BFIN_CONSOLE=y
+-# CONFIG_SERIAL_BFIN_DMA is not set
+-CONFIG_SERIAL_BFIN_PIO=y
++CONFIG_SERIAL_BFIN_DMA=y
++# CONFIG_SERIAL_BFIN_PIO is not set
+ # CONFIG_SERIAL_BFIN_UART0 is not set
+ CONFIG_SERIAL_BFIN_UART1=y
+ # CONFIG_BFIN_UART1_CTSRTS is not set
+diff --git a/arch/blackfin/configs/BF561-EZKIT_defconfig b/arch/blackfin/configs/BF561-EZKIT_defconfig
+index 4d8a633..b4a20c8 100644
+--- a/arch/blackfin/configs/BF561-EZKIT_defconfig
++++ b/arch/blackfin/configs/BF561-EZKIT_defconfig
+@@ -13,7 +13,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_HARDIRQS=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+-# CONFIG_GENERIC_TIME is not set
++CONFIG_GENERIC_TIME=y
+ CONFIG_GENERIC_GPIO=y
+ CONFIG_FORCE_MAX_ZONEORDER=14
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
+@@ -256,7 +256,7 @@ CONFIG_HZ=250
+ #
+ # Memory Setup
+ #
+-CONFIG_MEM_SIZE=64
++CONFIG_MAX_MEM_SIZE=512
+ CONFIG_MEM_ADD_WIDTH=9
+ CONFIG_BOOT_LOAD=0x1000
+ CONFIG_BFIN_SCRATCH_REG_RETN=y
+diff --git a/arch/blackfin/configs/CM-BF533_defconfig b/arch/blackfin/configs/CM-BF533_defconfig
+new file mode 100644
+index 0000000..560890f
+--- /dev/null
++++ b/arch/blackfin/configs/CM-BF533_defconfig
+@@ -0,0 +1,912 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.22.16
++#
++# CONFIG_MMU is not set
++# CONFIG_FPU is not set
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
++CONFIG_BLACKFIN=y
++CONFIG_ZONE_DMA=y
++CONFIG_SEMAPHORE_SLEEPERS=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_FORCE_MAX_ZONEORDER=14
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SYSVIPC=y
++# CONFIG_IPC_NS is not set
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_UTS_NS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_BLK_DEV_INITRD is not set
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++# CONFIG_UID16 is not set
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++# CONFIG_HOTPLUG is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
++# CONFIG_NP2 is not set
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_RT_MUTEXES=y
++CONFIG_TINY_SHMEM=y
++CONFIG_BASE_SMALL=0
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++
++#
++# Block layer
++#
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++# CONFIG_IOSCHED_DEADLINE is not set
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++CONFIG_DEFAULT_NOOP=y
++CONFIG_DEFAULT_IOSCHED="noop"
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++
++#
++# Blackfin Processor Options
++#
++
++#
++# Processor and Board Settings
++#
++# CONFIG_BF522 is not set
++# CONFIG_BF523 is not set
++# CONFIG_BF524 is not set
++# CONFIG_BF525 is not set
++# CONFIG_BF526 is not set
++# CONFIG_BF527 is not set
++# CONFIG_BF531 is not set
++# CONFIG_BF532 is not set
++CONFIG_BF533=y
++# CONFIG_BF534 is not set
++# CONFIG_BF536 is not set
++# CONFIG_BF537 is not set
++# CONFIG_BF542 is not set
++# CONFIG_BF544 is not set
++# CONFIG_BF547 is not set
++# CONFIG_BF548 is not set
++# CONFIG_BF549 is not set
++# CONFIG_BF561 is not set
++# CONFIG_BF_REV_0_0 is not set
++# CONFIG_BF_REV_0_1 is not set
++# CONFIG_BF_REV_0_2 is not set
++CONFIG_BF_REV_0_3=y
++# CONFIG_BF_REV_0_4 is not set
++# CONFIG_BF_REV_0_5 is not set
++# CONFIG_BF_REV_ANY is not set
++# CONFIG_BF_REV_NONE is not set
++CONFIG_BF53x=y
++CONFIG_BFIN_SINGLE_CORE=y
++CONFIG_MEM_MT48LC16M16A2TG_75=y
++# CONFIG_BFIN533_EZKIT is not set
++# CONFIG_BFIN533_STAMP is not set
++CONFIG_BFIN533_BLUETECHNIX_CM=y
++# CONFIG_H8606_HVSISTEMAS is not set
++# CONFIG_GENERIC_BF533_BOARD is not set
++
++#
++# BF533/2/1 Specific Configuration
++#
++
++#
++# Interrupt Priority Assignment
++#
++
++#
++# Priority
++#
++CONFIG_UART_ERROR=7
++CONFIG_SPORT0_ERROR=7
++CONFIG_SPI_ERROR=7
++CONFIG_SPORT1_ERROR=7
++CONFIG_PPI_ERROR=7
++CONFIG_DMA_ERROR=7
++CONFIG_PLLWAKE_ERROR=7
++CONFIG_RTC_ERROR=8
++CONFIG_DMA0_PPI=8
++CONFIG_DMA1_SPORT0RX=9
++CONFIG_DMA2_SPORT0TX=9
++CONFIG_DMA3_SPORT1RX=9
++CONFIG_DMA4_SPORT1TX=9
++CONFIG_DMA5_SPI=10
++CONFIG_DMA6_UARTRX=10
++CONFIG_DMA7_UARTTX=10
++CONFIG_TIMER0=11
++CONFIG_TIMER1=11
++CONFIG_TIMER2=11
++CONFIG_PFA=12
++CONFIG_PFB=12
++CONFIG_MEMDMA0=13
++CONFIG_MEMDMA1=13
++CONFIG_WDTIMER=13
++
++#
++# Board customizations
++#
++# CONFIG_CMDLINE_BOOL is not set
++
++#
++# Clock/PLL Setup
++#
++CONFIG_CLKIN_HZ=25000000
++# CONFIG_BFIN_KERNEL_CLOCK is not set
++CONFIG_MAX_VCO_HZ=750000000
++CONFIG_MIN_VCO_HZ=50000000
++CONFIG_MAX_SCLK_HZ=133333333
++CONFIG_MIN_SCLK_HZ=27000000
++
++#
++# Kernel Timer/Scheduler
++#
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++
++#
++# Memory Setup
++#
++CONFIG_MAX_MEM_SIZE=32
++CONFIG_MEM_ADD_WIDTH=9
++CONFIG_BOOT_LOAD=0x1000
++CONFIG_BFIN_SCRATCH_REG_RETN=y
++# CONFIG_BFIN_SCRATCH_REG_RETE is not set
++# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
++
++#
++# Blackfin Kernel Optimizations
++#
++
++#
++# Memory Optimizations
++#
++CONFIG_I_ENTRY_L1=y
++CONFIG_EXCPT_IRQ_SYSC_L1=y
++CONFIG_DO_IRQ_L1=y
++CONFIG_CORE_TIMER_IRQ_L1=y
++CONFIG_IDLE_L1=y
++CONFIG_SCHEDULE_L1=y
++CONFIG_ARITHMETIC_OPS_L1=y
++CONFIG_ACCESS_OK_L1=y
++CONFIG_MEMSET_L1=y
++CONFIG_MEMCPY_L1=y
++CONFIG_SYS_BFIN_SPINLOCK_L1=y
++CONFIG_IP_CHECKSUM_L1=y
++CONFIG_CACHELINE_ALIGNED_L1=y
++CONFIG_SYSCALL_TAB_L1=y
++CONFIG_CPLB_SWITCH_TAB_L1=y
++CONFIG_RAMKERNEL=y
++# CONFIG_ROMKERNEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_LARGE_ALLOCS=y
++# CONFIG_BFIN_GPTIMERS is not set
++CONFIG_BFIN_DMA_5XX=y
++# CONFIG_DMA_UNCACHED_2M is not set
++CONFIG_DMA_UNCACHED_1M=y
++# CONFIG_DMA_UNCACHED_NONE is not set
++
++#
++# Cache Support
++#
++CONFIG_BFIN_ICACHE=y
++CONFIG_BFIN_DCACHE=y
++# CONFIG_BFIN_DCACHE_BANKA is not set
++# CONFIG_BFIN_ICACHE_LOCK is not set
++CONFIG_BFIN_WB=y
++# CONFIG_BFIN_WT is not set
++CONFIG_L1_MAX_PIECE=16
++# CONFIG_MPU is not set
++
++#
++# Asynchonous Memory Configuration
++#
++
++#
++# EBIU_AMGCTL Global Control
++#
++CONFIG_C_AMCKEN=y
++CONFIG_C_CDPRIO=y
++# CONFIG_C_AMBEN is not set
++# CONFIG_C_AMBEN_B0 is not set
++# CONFIG_C_AMBEN_B0_B1 is not set
++# CONFIG_C_AMBEN_B0_B1_B2 is not set
++CONFIG_C_AMBEN_ALL=y
++
++#
++# EBIU_AMBCTL Control
++#
++CONFIG_BANK_0=0x7BB0
++CONFIG_BANK_1=0x7BB0
++CONFIG_BANK_2=0x7BB0
++CONFIG_BANK_3=0xFFC3
++
++#
++# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
++#
++# CONFIG_PCI is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++
++#
++# PCCARD (PCMCIA/CardBus) support
++#
++
++#
++# Executable file formats
++#
++CONFIG_BINFMT_ELF_FDPIC=y
++CONFIG_BINFMT_FLAT=y
++CONFIG_BINFMT_ZFLAT=y
++CONFIG_BINFMT_SHARED_FLAT=y
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++# CONFIG_PM_WAKEUP_BY_GPIO is not set
++
++#
++# CPU Frequency scaling
++#
++# CONFIG_CPU_FREQ is not set
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++# CONFIG_IP_PNP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETLABEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_SYS_HYPERVISOR is not set
++
++#
++# Connector - unified userspace <-> kernelspace linker
++#
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++# CONFIG_MTD_CFI is not set
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++CONFIG_MTD_RAM=y
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++CONFIG_MTD_UCLINUX=y
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Plug and Play support
++#
++# CONFIG_PNPACPI is not set
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=4096
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++
++#
++# Misc devices
++#
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Network device support
++#
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_PHYLIB is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_SMC91X=y
++# CONFIG_SMSC911X is not set
++# CONFIG_DM9000 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_AX88180 is not set
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Telephony Support
++#
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_AD9960 is not set
++# CONFIG_SPI_ADC_BF533 is not set
++# CONFIG_BF5xx_PFLAGS is not set
++# CONFIG_BF5xx_PPIFCD is not set
++# CONFIG_BFIN_SIMPLE_TIMER is not set
++# CONFIG_BF5xx_PPI is not set
++CONFIG_BFIN_SPORT=y
++# CONFIG_BFIN_TIMER_LATENCY is not set
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_BFIN=y
++CONFIG_SERIAL_BFIN_CONSOLE=y
++CONFIG_SERIAL_BFIN_DMA=y
++# CONFIG_SERIAL_BFIN_PIO is not set
++CONFIG_SERIAL_BFIN_UART0=y
++# CONFIG_BFIN_UART0_CTSRTS is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_BFIN_SPORT is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++
++#
++# CAN, the car bus and industrial fieldbus
++#
++# CONFIG_CAN4LINUX is not set
++
++#
++# IPMI
++#
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_WATCHDOG is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# TPM devices
++#
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++
++#
++# Dallas's 1-wire bus
++#
++# CONFIG_W1 is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_ABITUGURU is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_FB is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++
++#
++# USB support
++#
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++# CONFIG_USB is not set
++
++#
++# Enable Host or Gadget support to see Inventra options
++#
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++
++#
++# LED devices
++#
++# CONFIG_NEW_LEDS is not set
++
++#
++# LED drivers
++#
++
++#
++# LED Triggers
++#
++
++#
++# InfiniBand support
++#
++
++#
++# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
++#
++
++#
++# Real Time Clock
++#
++# CONFIG_RTC_CLASS is not set
++
++#
++# DMA Engine support
++#
++# CONFIG_DMA_ENGINE is not set
++
++#
++# DMA Clients
++#
++
++#
++# DMA Devices
++#
++
++#
++# PBX support
++#
++# CONFIG_PBX is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++# CONFIG_EXT2_FS_POSIX_ACL is not set
++# CONFIG_EXT2_FS_SECURITY is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++# CONFIG_TMPFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_YAFFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Network File Systems
++#
++# CONFIG_NFS_FS is not set
++# CONFIG_NFSD is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++
++#
++# Native Language Support
++#
++# CONFIG_NLS is not set
++
++#
++# Distributed Lock Manager
++#
++# CONFIG_DLM is not set
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_MMRS is not set
++CONFIG_DEBUG_HUNT_FOR_ZERO=y
++CONFIG_DEBUG_BFIN_HWTRACE_ON=y
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
++# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
++# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
++# CONFIG_EARLY_PRINTK is not set
++CONFIG_CPLB_INFO=y
++CONFIG_ACCESS_CHECK=y
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++CONFIG_SECURITY=y
++# CONFIG_SECURITY_NETWORK is not set
++CONFIG_SECURITY_CAPABILITIES=y
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=m
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/blackfin/configs/CM-BF537E_defconfig b/arch/blackfin/configs/CM-BF537E_defconfig
+new file mode 100644
+index 0000000..9f66d2d
+--- /dev/null
++++ b/arch/blackfin/configs/CM-BF537E_defconfig
+@@ -0,0 +1,940 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.22.16
++#
++# CONFIG_MMU is not set
++# CONFIG_FPU is not set
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
++CONFIG_BLACKFIN=y
++CONFIG_ZONE_DMA=y
++CONFIG_SEMAPHORE_SLEEPERS=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_FORCE_MAX_ZONEORDER=14
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SYSVIPC=y
++# CONFIG_IPC_NS is not set
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_UTS_NS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_BLK_DEV_INITRD is not set
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++# CONFIG_UID16 is not set
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++# CONFIG_HOTPLUG is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
++# CONFIG_NP2 is not set
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_RT_MUTEXES=y
++CONFIG_TINY_SHMEM=y
++CONFIG_BASE_SMALL=0
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++
++#
++# Block layer
++#
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++# CONFIG_IOSCHED_DEADLINE is not set
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++CONFIG_DEFAULT_NOOP=y
++CONFIG_DEFAULT_IOSCHED="noop"
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++
++#
++# Blackfin Processor Options
++#
++
++#
++# Processor and Board Settings
++#
++# CONFIG_BF522 is not set
++# CONFIG_BF523 is not set
++# CONFIG_BF524 is not set
++# CONFIG_BF525 is not set
++# CONFIG_BF526 is not set
++# CONFIG_BF527 is not set
++# CONFIG_BF531 is not set
++# CONFIG_BF532 is not set
++# CONFIG_BF533 is not set
++# CONFIG_BF534 is not set
++# CONFIG_BF536 is not set
++CONFIG_BF537=y
++# CONFIG_BF542 is not set
++# CONFIG_BF544 is not set
++# CONFIG_BF547 is not set
++# CONFIG_BF548 is not set
++# CONFIG_BF549 is not set
++# CONFIG_BF561 is not set
++# CONFIG_BF_REV_0_0 is not set
++# CONFIG_BF_REV_0_1 is not set
++CONFIG_BF_REV_0_2=y
++# CONFIG_BF_REV_0_3 is not set
++# CONFIG_BF_REV_0_4 is not set
++# CONFIG_BF_REV_0_5 is not set
++# CONFIG_BF_REV_ANY is not set
++# CONFIG_BF_REV_NONE is not set
++CONFIG_BF53x=y
++CONFIG_BFIN_SINGLE_CORE=y
++CONFIG_MEM_MT48LC16M16A2TG_75=y
++CONFIG_IRQ_PLL_WAKEUP=7
++CONFIG_IRQ_RTC=8
++CONFIG_IRQ_PPI=8
++CONFIG_IRQ_SPORT0_RX=9
++CONFIG_IRQ_SPORT0_TX=9
++CONFIG_IRQ_SPORT1_RX=9
++CONFIG_IRQ_SPORT1_TX=9
++CONFIG_IRQ_TWI=10
++CONFIG_IRQ_SPI=10
++CONFIG_IRQ_UART0_RX=10
++CONFIG_IRQ_UART0_TX=10
++CONFIG_IRQ_UART1_RX=10
++CONFIG_IRQ_UART1_TX=10
++CONFIG_IRQ_MAC_RX=11
++CONFIG_IRQ_MAC_TX=11
++CONFIG_IRQ_TMR0=12
++CONFIG_IRQ_TMR1=12
++CONFIG_IRQ_TMR2=12
++CONFIG_IRQ_TMR3=12
++CONFIG_IRQ_TMR4=12
++CONFIG_IRQ_TMR5=12
++CONFIG_IRQ_TMR6=12
++CONFIG_IRQ_TMR7=12
++CONFIG_IRQ_PORTG_INTB=12
++CONFIG_IRQ_MEM_DMA0=13
++CONFIG_IRQ_MEM_DMA1=13
++CONFIG_IRQ_WATCH=13
++# CONFIG_BFIN537_STAMP is not set
++CONFIG_BFIN537_BLUETECHNIX_CM=y
++# CONFIG_PNAV10 is not set
++# CONFIG_CAMSIG_MINOTAUR is not set
++# CONFIG_GENERIC_BF537_BOARD is not set
++
++#
++# BF537 Specific Configuration
++#
++
++#
++# Interrupt Priority Assignment
++#
++
++#
++# Priority
++#
++CONFIG_IRQ_DMA_ERROR=7
++CONFIG_IRQ_ERROR=7
++CONFIG_IRQ_CAN_RX=11
++CONFIG_IRQ_CAN_TX=11
++CONFIG_IRQ_PROG_INTA=12
++
++#
++# Board customizations
++#
++# CONFIG_CMDLINE_BOOL is not set
++
++#
++# Clock/PLL Setup
++#
++CONFIG_CLKIN_HZ=25000000
++# CONFIG_BFIN_KERNEL_CLOCK is not set
++CONFIG_MAX_VCO_HZ=600000000
++CONFIG_MIN_VCO_HZ=50000000
++CONFIG_MAX_SCLK_HZ=133333333
++CONFIG_MIN_SCLK_HZ=27000000
++
++#
++# Kernel Timer/Scheduler
++#
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++
++#
++# Memory Setup
++#
++CONFIG_MAX_MEM_SIZE=32
++CONFIG_MEM_ADD_WIDTH=9
++CONFIG_BOOT_LOAD=0x1000
++CONFIG_BFIN_SCRATCH_REG_RETN=y
++# CONFIG_BFIN_SCRATCH_REG_RETE is not set
++# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
++
++#
++# Blackfin Kernel Optimizations
++#
++
++#
++# Memory Optimizations
++#
++CONFIG_I_ENTRY_L1=y
++CONFIG_EXCPT_IRQ_SYSC_L1=y
++CONFIG_DO_IRQ_L1=y
++CONFIG_CORE_TIMER_IRQ_L1=y
++CONFIG_IDLE_L1=y
++CONFIG_SCHEDULE_L1=y
++CONFIG_ARITHMETIC_OPS_L1=y
++CONFIG_ACCESS_OK_L1=y
++CONFIG_MEMSET_L1=y
++CONFIG_MEMCPY_L1=y
++CONFIG_SYS_BFIN_SPINLOCK_L1=y
++CONFIG_IP_CHECKSUM_L1=y
++CONFIG_CACHELINE_ALIGNED_L1=y
++CONFIG_SYSCALL_TAB_L1=y
++CONFIG_CPLB_SWITCH_TAB_L1=y
++CONFIG_RAMKERNEL=y
++# CONFIG_ROMKERNEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_LARGE_ALLOCS=y
++# CONFIG_BFIN_GPTIMERS is not set
++CONFIG_BFIN_DMA_5XX=y
++# CONFIG_DMA_UNCACHED_2M is not set
++CONFIG_DMA_UNCACHED_1M=y
++# CONFIG_DMA_UNCACHED_NONE is not set
++
++#
++# Cache Support
++#
++CONFIG_BFIN_ICACHE=y
++CONFIG_BFIN_DCACHE=y
++# CONFIG_BFIN_DCACHE_BANKA is not set
++# CONFIG_BFIN_ICACHE_LOCK is not set
++CONFIG_BFIN_WB=y
++# CONFIG_BFIN_WT is not set
++CONFIG_L1_MAX_PIECE=16
++# CONFIG_MPU is not set
++
++#
++# Asynchonous Memory Configuration
++#
++
++#
++# EBIU_AMGCTL Global Control
++#
++CONFIG_C_AMCKEN=y
++CONFIG_C_CDPRIO=y
++# CONFIG_C_AMBEN is not set
++# CONFIG_C_AMBEN_B0 is not set
++# CONFIG_C_AMBEN_B0_B1 is not set
++# CONFIG_C_AMBEN_B0_B1_B2 is not set
++CONFIG_C_AMBEN_ALL=y
++
++#
++# EBIU_AMBCTL Control
++#
++CONFIG_BANK_0=0x7BB0
++CONFIG_BANK_1=0x7BB0
++CONFIG_BANK_2=0x7BB0
++CONFIG_BANK_3=0xFFC3
++
++#
++# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
++#
++# CONFIG_PCI is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++
++#
++# PCCARD (PCMCIA/CardBus) support
++#
++
++#
++# Executable file formats
++#
++CONFIG_BINFMT_ELF_FDPIC=y
++CONFIG_BINFMT_FLAT=y
++CONFIG_BINFMT_ZFLAT=y
++CONFIG_BINFMT_SHARED_FLAT=y
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++# CONFIG_PM_WAKEUP_BY_GPIO is not set
++
++#
++# CPU Frequency scaling
++#
++# CONFIG_CPU_FREQ is not set
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++# CONFIG_IP_PNP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETLABEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_SYS_HYPERVISOR is not set
++
++#
++# Connector - unified userspace <-> kernelspace linker
++#
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++# CONFIG_MTD_CFI is not set
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++CONFIG_MTD_RAM=y
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++CONFIG_MTD_UCLINUX=y
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Plug and Play support
++#
++# CONFIG_PNPACPI is not set
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=4096
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++
++#
++# Misc devices
++#
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Network device support
++#
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_FIXED_PHY is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_SMC91X is not set
++CONFIG_BFIN_MAC=y
++CONFIG_BFIN_MAC_USE_L1=y
++CONFIG_BFIN_TX_DESC_NUM=10
++CONFIG_BFIN_RX_DESC_NUM=20
++# CONFIG_BFIN_MAC_RMII is not set
++# CONFIG_SMSC911X is not set
++# CONFIG_DM9000 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_AX88180 is not set
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Telephony Support
++#
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_AD9960 is not set
++# CONFIG_SPI_ADC_BF533 is not set
++# CONFIG_BF5xx_PFLAGS is not set
++# CONFIG_BF5xx_PPIFCD is not set
++# CONFIG_BFIN_SIMPLE_TIMER is not set
++# CONFIG_BF5xx_PPI is not set
++CONFIG_BFIN_SPORT=y
++# CONFIG_BFIN_TIMER_LATENCY is not set
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_BFIN=y
++CONFIG_SERIAL_BFIN_CONSOLE=y
++CONFIG_SERIAL_BFIN_DMA=y
++# CONFIG_SERIAL_BFIN_PIO is not set
++CONFIG_SERIAL_BFIN_UART0=y
++# CONFIG_BFIN_UART0_CTSRTS is not set
++CONFIG_SERIAL_BFIN_UART1=y
++# CONFIG_BFIN_UART1_CTSRTS is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_BFIN_SPORT is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++
++#
++# CAN, the car bus and industrial fieldbus
++#
++# CONFIG_CAN4LINUX is not set
++
++#
++# IPMI
++#
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_WATCHDOG is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# TPM devices
++#
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++
++#
++# Dallas's 1-wire bus
++#
++# CONFIG_W1 is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_ABITUGURU is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_FB is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++
++#
++# USB support
++#
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++# CONFIG_USB is not set
++
++#
++# Enable Host or Gadget support to see Inventra options
++#
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++
++#
++# LED devices
++#
++# CONFIG_NEW_LEDS is not set
++
++#
++# LED drivers
++#
++
++#
++# LED Triggers
++#
++
++#
++# InfiniBand support
++#
++
++#
++# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
++#
++
++#
++# Real Time Clock
++#
++# CONFIG_RTC_CLASS is not set
++
++#
++# DMA Engine support
++#
++# CONFIG_DMA_ENGINE is not set
++
++#
++# DMA Clients
++#
++
++#
++# DMA Devices
++#
++
++#
++# PBX support
++#
++# CONFIG_PBX is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++# CONFIG_EXT2_FS_POSIX_ACL is not set
++# CONFIG_EXT2_FS_SECURITY is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++# CONFIG_TMPFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_YAFFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Network File Systems
++#
++# CONFIG_NFS_FS is not set
++# CONFIG_NFSD is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++
++#
++# Native Language Support
++#
++# CONFIG_NLS is not set
++
++#
++# Distributed Lock Manager
++#
++# CONFIG_DLM is not set
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_MMRS is not set
++# CONFIG_DEBUG_HUNT_FOR_ZERO is not set
++CONFIG_DEBUG_BFIN_HWTRACE_ON=y
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
++# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
++# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
++# CONFIG_EARLY_PRINTK is not set
++CONFIG_CPLB_INFO=y
++CONFIG_ACCESS_CHECK=y
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++CONFIG_SECURITY=y
++# CONFIG_SECURITY_NETWORK is not set
++CONFIG_SECURITY_CAPABILITIES=y
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=m
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/blackfin/configs/CM-BF537U_defconfig b/arch/blackfin/configs/CM-BF537U_defconfig
+new file mode 100644
+index 0000000..2694d06
+--- /dev/null
++++ b/arch/blackfin/configs/CM-BF537U_defconfig
+@@ -0,0 +1,940 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.22.16
++#
++# CONFIG_MMU is not set
++# CONFIG_FPU is not set
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
++CONFIG_BLACKFIN=y
++CONFIG_ZONE_DMA=y
++CONFIG_SEMAPHORE_SLEEPERS=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_FORCE_MAX_ZONEORDER=14
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SYSVIPC=y
++# CONFIG_IPC_NS is not set
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_UTS_NS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_BLK_DEV_INITRD is not set
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++# CONFIG_UID16 is not set
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++# CONFIG_HOTPLUG is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
++# CONFIG_NP2 is not set
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_RT_MUTEXES=y
++CONFIG_TINY_SHMEM=y
++CONFIG_BASE_SMALL=0
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++
++#
++# Block layer
++#
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++# CONFIG_IOSCHED_DEADLINE is not set
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++CONFIG_DEFAULT_NOOP=y
++CONFIG_DEFAULT_IOSCHED="noop"
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++
++#
++# Blackfin Processor Options
++#
++
++#
++# Processor and Board Settings
++#
++# CONFIG_BF522 is not set
++# CONFIG_BF523 is not set
++# CONFIG_BF524 is not set
++# CONFIG_BF525 is not set
++# CONFIG_BF526 is not set
++# CONFIG_BF527 is not set
++# CONFIG_BF531 is not set
++# CONFIG_BF532 is not set
++# CONFIG_BF533 is not set
++# CONFIG_BF534 is not set
++# CONFIG_BF536 is not set
++CONFIG_BF537=y
++# CONFIG_BF542 is not set
++# CONFIG_BF544 is not set
++# CONFIG_BF547 is not set
++# CONFIG_BF548 is not set
++# CONFIG_BF549 is not set
++# CONFIG_BF561 is not set
++# CONFIG_BF_REV_0_0 is not set
++# CONFIG_BF_REV_0_1 is not set
++CONFIG_BF_REV_0_2=y
++# CONFIG_BF_REV_0_3 is not set
++# CONFIG_BF_REV_0_4 is not set
++# CONFIG_BF_REV_0_5 is not set
++# CONFIG_BF_REV_ANY is not set
++# CONFIG_BF_REV_NONE is not set
++CONFIG_BF53x=y
++CONFIG_BFIN_SINGLE_CORE=y
++CONFIG_MEM_MT48LC16M16A2TG_75=y
++CONFIG_IRQ_PLL_WAKEUP=7
++CONFIG_IRQ_RTC=8
++CONFIG_IRQ_PPI=8
++CONFIG_IRQ_SPORT0_RX=9
++CONFIG_IRQ_SPORT0_TX=9
++CONFIG_IRQ_SPORT1_RX=9
++CONFIG_IRQ_SPORT1_TX=9
++CONFIG_IRQ_TWI=10
++CONFIG_IRQ_SPI=10
++CONFIG_IRQ_UART0_RX=10
++CONFIG_IRQ_UART0_TX=10
++CONFIG_IRQ_UART1_RX=10
++CONFIG_IRQ_UART1_TX=10
++CONFIG_IRQ_MAC_RX=11
++CONFIG_IRQ_MAC_TX=11
++CONFIG_IRQ_TMR0=12
++CONFIG_IRQ_TMR1=12
++CONFIG_IRQ_TMR2=12
++CONFIG_IRQ_TMR3=12
++CONFIG_IRQ_TMR4=12
++CONFIG_IRQ_TMR5=12
++CONFIG_IRQ_TMR6=12
++CONFIG_IRQ_TMR7=12
++CONFIG_IRQ_PORTG_INTB=12
++CONFIG_IRQ_MEM_DMA0=13
++CONFIG_IRQ_MEM_DMA1=13
++CONFIG_IRQ_WATCH=13
++# CONFIG_BFIN537_STAMP is not set
++CONFIG_BFIN537_BLUETECHNIX_CM=y
++# CONFIG_PNAV10 is not set
++# CONFIG_CAMSIG_MINOTAUR is not set
++# CONFIG_GENERIC_BF537_BOARD is not set
++
++#
++# BF537 Specific Configuration
++#
++
++#
++# Interrupt Priority Assignment
++#
++
++#
++# Priority
++#
++CONFIG_IRQ_DMA_ERROR=7
++CONFIG_IRQ_ERROR=7
++CONFIG_IRQ_CAN_RX=11
++CONFIG_IRQ_CAN_TX=11
++CONFIG_IRQ_PROG_INTA=12
++
++#
++# Board customizations
++#
++# CONFIG_CMDLINE_BOOL is not set
++
++#
++# Clock/PLL Setup
++#
++CONFIG_CLKIN_HZ=30000000
++# CONFIG_BFIN_KERNEL_CLOCK is not set
++CONFIG_MAX_VCO_HZ=600000000
++CONFIG_MIN_VCO_HZ=50000000
++CONFIG_MAX_SCLK_HZ=133333333
++CONFIG_MIN_SCLK_HZ=27000000
++
++#
++# Kernel Timer/Scheduler
++#
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++
++#
++# Memory Setup
++#
++CONFIG_MAX_MEM_SIZE=32
++CONFIG_MEM_ADD_WIDTH=9
++CONFIG_BOOT_LOAD=0x1000
++CONFIG_BFIN_SCRATCH_REG_RETN=y
++# CONFIG_BFIN_SCRATCH_REG_RETE is not set
++# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
++
++#
++# Blackfin Kernel Optimizations
++#
++
++#
++# Memory Optimizations
++#
++CONFIG_I_ENTRY_L1=y
++CONFIG_EXCPT_IRQ_SYSC_L1=y
++CONFIG_DO_IRQ_L1=y
++CONFIG_CORE_TIMER_IRQ_L1=y
++CONFIG_IDLE_L1=y
++CONFIG_SCHEDULE_L1=y
++CONFIG_ARITHMETIC_OPS_L1=y
++CONFIG_ACCESS_OK_L1=y
++CONFIG_MEMSET_L1=y
++CONFIG_MEMCPY_L1=y
++CONFIG_SYS_BFIN_SPINLOCK_L1=y
++CONFIG_IP_CHECKSUM_L1=y
++CONFIG_CACHELINE_ALIGNED_L1=y
++CONFIG_SYSCALL_TAB_L1=y
++CONFIG_CPLB_SWITCH_TAB_L1=y
++CONFIG_RAMKERNEL=y
++# CONFIG_ROMKERNEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_LARGE_ALLOCS=y
++# CONFIG_BFIN_GPTIMERS is not set
++CONFIG_BFIN_DMA_5XX=y
++# CONFIG_DMA_UNCACHED_2M is not set
++CONFIG_DMA_UNCACHED_1M=y
++# CONFIG_DMA_UNCACHED_NONE is not set
++
++#
++# Cache Support
++#
++CONFIG_BFIN_ICACHE=y
++CONFIG_BFIN_DCACHE=y
++# CONFIG_BFIN_DCACHE_BANKA is not set
++# CONFIG_BFIN_ICACHE_LOCK is not set
++CONFIG_BFIN_WB=y
++# CONFIG_BFIN_WT is not set
++CONFIG_L1_MAX_PIECE=16
++# CONFIG_MPU is not set
++
++#
++# Asynchonous Memory Configuration
++#
++
++#
++# EBIU_AMGCTL Global Control
++#
++CONFIG_C_AMCKEN=y
++CONFIG_C_CDPRIO=y
++# CONFIG_C_AMBEN is not set
++# CONFIG_C_AMBEN_B0 is not set
++# CONFIG_C_AMBEN_B0_B1 is not set
++# CONFIG_C_AMBEN_B0_B1_B2 is not set
++CONFIG_C_AMBEN_ALL=y
++
++#
++# EBIU_AMBCTL Control
++#
++CONFIG_BANK_0=0x7BB0
++CONFIG_BANK_1=0x7BB0
++CONFIG_BANK_2=0xFFC3
++CONFIG_BANK_3=0xFFC3
++
++#
++# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
++#
++# CONFIG_PCI is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++
++#
++# PCCARD (PCMCIA/CardBus) support
++#
++
++#
++# Executable file formats
++#
++CONFIG_BINFMT_ELF_FDPIC=y
++CONFIG_BINFMT_FLAT=y
++CONFIG_BINFMT_ZFLAT=y
++CONFIG_BINFMT_SHARED_FLAT=y
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++# CONFIG_PM_WAKEUP_BY_GPIO is not set
++
++#
++# CPU Frequency scaling
++#
++# CONFIG_CPU_FREQ is not set
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++# CONFIG_IP_PNP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETLABEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_SYS_HYPERVISOR is not set
++
++#
++# Connector - unified userspace <-> kernelspace linker
++#
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++# CONFIG_MTD_CFI is not set
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++CONFIG_MTD_RAM=y
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++CONFIG_MTD_UCLINUX=y
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Plug and Play support
++#
++# CONFIG_PNPACPI is not set
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=4096
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++
++#
++# Misc devices
++#
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Network device support
++#
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_PHYLIB is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_SMC91X=y
++# CONFIG_BFIN_MAC is not set
++# CONFIG_SMSC911X is not set
++# CONFIG_DM9000 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_AX88180 is not set
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Telephony Support
++#
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_AD9960 is not set
++# CONFIG_SPI_ADC_BF533 is not set
++# CONFIG_BF5xx_PFLAGS is not set
++# CONFIG_BF5xx_PPIFCD is not set
++# CONFIG_BFIN_SIMPLE_TIMER is not set
++# CONFIG_BF5xx_PPI is not set
++CONFIG_BFIN_SPORT=y
++# CONFIG_BFIN_TIMER_LATENCY is not set
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_BFIN=y
++CONFIG_SERIAL_BFIN_CONSOLE=y
++CONFIG_SERIAL_BFIN_DMA=y
++# CONFIG_SERIAL_BFIN_PIO is not set
++CONFIG_SERIAL_BFIN_UART0=y
++# CONFIG_BFIN_UART0_CTSRTS is not set
++CONFIG_SERIAL_BFIN_UART1=y
++# CONFIG_BFIN_UART1_CTSRTS is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_BFIN_SPORT is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++
++#
++# CAN, the car bus and industrial fieldbus
++#
++# CONFIG_CAN4LINUX is not set
++
++#
++# IPMI
++#
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_WATCHDOG is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# TPM devices
++#
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++
++#
++# Dallas's 1-wire bus
++#
++# CONFIG_W1 is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_ABITUGURU is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_FB is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++
++#
++# USB support
++#
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++# CONFIG_USB is not set
++# CONFIG_USB_MUSB_HDRC is not set
++# CONFIG_USB_GADGET_MUSB_HDRC is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# USB Gadget Support
++#
++CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG_FILES is not set
++CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_FSL_USB2 is not set
++CONFIG_USB_GADGET_NET2272=y
++CONFIG_USB_NET2272=y
++# CONFIG_USB_GADGET_NET2280 is not set
++# CONFIG_USB_GADGET_PXA2XX is not set
++# CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_LH7A40X is not set
++# CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_AT91 is not set
++# CONFIG_USB_GADGET_DUMMY_HCD is not set
++CONFIG_USB_GADGET_DUALSPEED=y
++# CONFIG_USB_ZERO is not set
++# CONFIG_USB_ETH is not set
++# CONFIG_USB_GADGETFS is not set
++# CONFIG_USB_FILE_STORAGE is not set
++# CONFIG_USB_G_SERIAL is not set
++# CONFIG_USB_MIDI_GADGET is not set
++# CONFIG_MMC is not set
++
++#
++# LED devices
++#
++# CONFIG_NEW_LEDS is not set
++
++#
++# LED drivers
++#
++
++#
++# LED Triggers
++#
++
++#
++# InfiniBand support
++#
++
++#
++# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
++#
++
++#
++# Real Time Clock
++#
++# CONFIG_RTC_CLASS is not set
++
++#
++# DMA Engine support
++#
++# CONFIG_DMA_ENGINE is not set
++
++#
++# DMA Clients
++#
++
++#
++# DMA Devices
++#
++
++#
++# PBX support
++#
++# CONFIG_PBX is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++# CONFIG_EXT2_FS_POSIX_ACL is not set
++# CONFIG_EXT2_FS_SECURITY is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++# CONFIG_TMPFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_YAFFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Network File Systems
++#
++# CONFIG_NFS_FS is not set
++# CONFIG_NFSD is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++
++#
++# Native Language Support
++#
++# CONFIG_NLS is not set
++
++#
++# Distributed Lock Manager
++#
++# CONFIG_DLM is not set
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_MMRS is not set
++# CONFIG_DEBUG_HUNT_FOR_ZERO is not set
++CONFIG_DEBUG_BFIN_HWTRACE_ON=y
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
++# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
++# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
++# CONFIG_EARLY_PRINTK is not set
++CONFIG_CPLB_INFO=y
++CONFIG_ACCESS_CHECK=y
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++CONFIG_SECURITY=y
++# CONFIG_SECURITY_NETWORK is not set
++CONFIG_SECURITY_CAPABILITIES=y
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=m
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/blackfin/configs/CM-BF548_defconfig b/arch/blackfin/configs/CM-BF548_defconfig
+new file mode 100644
+index 0000000..9020725
+--- /dev/null
++++ b/arch/blackfin/configs/CM-BF548_defconfig
+@@ -0,0 +1,1373 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.24.4
++#
++# CONFIG_MMU is not set
++# CONFIG_FPU is not set
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
++CONFIG_BLACKFIN=y
++CONFIG_ZONE_DMA=y
++CONFIG_SEMAPHORE_SLEEPERS=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_FORCE_MAX_ZONEORDER=14
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++# CONFIG_AUDIT is not set
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
++# CONFIG_NP2 is not set
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++CONFIG_TINY_SHMEM=y
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++# CONFIG_IOSCHED_DEADLINE is not set
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++# CONFIG_PREEMPT_NONE is not set
++CONFIG_PREEMPT_VOLUNTARY=y
++# CONFIG_PREEMPT is not set
++
++#
++# Blackfin Processor Options
++#
++
++#
++# Processor and Board Settings
++#
++# CONFIG_BF522 is not set
++# CONFIG_BF523 is not set
++# CONFIG_BF524 is not set
++# CONFIG_BF525 is not set
++# CONFIG_BF526 is not set
++# CONFIG_BF527 is not set
++# CONFIG_BF531 is not set
++# CONFIG_BF532 is not set
++# CONFIG_BF533 is not set
++# CONFIG_BF534 is not set
++# CONFIG_BF536 is not set
++# CONFIG_BF537 is not set
++# CONFIG_BF542 is not set
++# CONFIG_BF544 is not set
++# CONFIG_BF547 is not set
++CONFIG_BF548=y
++# CONFIG_BF549 is not set
++# CONFIG_BF561 is not set
++CONFIG_BF_REV_0_0=y
++# CONFIG_BF_REV_0_1 is not set
++# CONFIG_BF_REV_0_2 is not set
++# CONFIG_BF_REV_0_3 is not set
++# CONFIG_BF_REV_0_4 is not set
++# CONFIG_BF_REV_0_5 is not set
++# CONFIG_BF_REV_ANY is not set
++# CONFIG_BF_REV_NONE is not set
++CONFIG_BF54x=y
++CONFIG_IRQ_PLL_WAKEUP=7
++CONFIG_IRQ_RTC=8
++CONFIG_IRQ_SPORT0_RX=9
++CONFIG_IRQ_SPORT0_TX=9
++CONFIG_IRQ_SPORT1_RX=9
++CONFIG_IRQ_SPORT1_TX=9
++CONFIG_IRQ_UART0_RX=10
++CONFIG_IRQ_UART0_TX=10
++CONFIG_IRQ_UART1_RX=10
++CONFIG_IRQ_UART1_TX=10
++CONFIG_IRQ_CNT=8
++CONFIG_IRQ_USB_INT0=11
++CONFIG_IRQ_USB_INT1=11
++CONFIG_IRQ_USB_INT2=11
++CONFIG_IRQ_USB_DMA=11
++CONFIG_IRQ_TIMER0=11
++CONFIG_IRQ_TIMER1=11
++CONFIG_IRQ_TIMER2=11
++CONFIG_IRQ_TIMER3=11
++CONFIG_IRQ_TIMER4=11
++CONFIG_IRQ_TIMER5=11
++CONFIG_IRQ_TIMER6=11
++CONFIG_IRQ_TIMER7=11
++CONFIG_IRQ_TIMER8=11
++CONFIG_IRQ_TIMER9=11
++CONFIG_IRQ_TIMER10=11
++# CONFIG_BFIN548_EZKIT is not set
++CONFIG_BFIN548_BLUETECHNIX_CM=y
++
++#
++# BF548 Specific Configuration
++#
++# CONFIG_DEB_DMA_URGENT is not set
++
++#
++# Interrupt Priority Assignment
++#
++
++#
++# Priority
++#
++CONFIG_IRQ_DMAC0_ERR=7
++CONFIG_IRQ_EPPI0_ERR=7
++CONFIG_IRQ_SPORT0_ERR=7
++CONFIG_IRQ_SPORT1_ERR=7
++CONFIG_IRQ_SPI0_ERR=7
++CONFIG_IRQ_UART0_ERR=7
++CONFIG_IRQ_EPPI0=8
++CONFIG_IRQ_SPI0=10
++CONFIG_IRQ_PINT0=12
++CONFIG_IRQ_PINT1=12
++CONFIG_IRQ_MDMAS0=13
++CONFIG_IRQ_MDMAS1=13
++CONFIG_IRQ_WATCHDOG=13
++CONFIG_IRQ_DMAC1_ERR=7
++CONFIG_IRQ_SPORT2_ERR=7
++CONFIG_IRQ_SPORT3_ERR=7
++CONFIG_IRQ_MXVR_DATA=7
++CONFIG_IRQ_SPI1_ERR=7
++CONFIG_IRQ_SPI2_ERR=7
++CONFIG_IRQ_UART1_ERR=7
++CONFIG_IRQ_UART2_ERR=7
++CONFIG_IRQ_CAN0_ERR=7
++CONFIG_IRQ_SPORT2_RX=9
++CONFIG_IRQ_SPORT2_TX=9
++CONFIG_IRQ_SPORT3_RX=9
++CONFIG_IRQ_SPORT3_TX=9
++CONFIG_IRQ_EPPI1=9
++CONFIG_IRQ_EPPI2=9
++CONFIG_IRQ_SPI1=10
++CONFIG_IRQ_SPI2=10
++CONFIG_IRQ_ATAPI_RX=10
++CONFIG_IRQ_ATAPI_TX=10
++CONFIG_IRQ_TWI0=11
++CONFIG_IRQ_TWI1=11
++CONFIG_IRQ_CAN0_RX=11
++CONFIG_IRQ_CAN0_TX=11
++CONFIG_IRQ_MDMAS2=13
++CONFIG_IRQ_MDMAS3=13
++CONFIG_IRQ_MXVR_ERR=11
++CONFIG_IRQ_MXVR_MSG=11
++CONFIG_IRQ_MXVR_PKT=11
++CONFIG_IRQ_EPPI1_ERR=7
++CONFIG_IRQ_EPPI2_ERR=7
++CONFIG_IRQ_UART3_ERR=7
++CONFIG_IRQ_HOST_ERR=7
++CONFIG_IRQ_PIXC_ERR=7
++CONFIG_IRQ_NFC_ERR=7
++CONFIG_IRQ_ATAPI_ERR=7
++CONFIG_IRQ_CAN1_ERR=7
++CONFIG_IRQ_HS_DMA_ERR=7
++CONFIG_IRQ_PIXC_IN0=8
++CONFIG_IRQ_PIXC_IN1=8
++CONFIG_IRQ_PIXC_OUT=8
++CONFIG_IRQ_SDH=8
++CONFIG_IRQ_KEY=8
++CONFIG_IRQ_CAN1_RX=11
++CONFIG_IRQ_CAN1_TX=11
++CONFIG_IRQ_SDH_MASK0=11
++CONFIG_IRQ_SDH_MASK1=11
++CONFIG_IRQ_OTPSEC=11
++CONFIG_IRQ_PINT2=11
++CONFIG_IRQ_PINT3=11
++
++#
++# Pin Interrupt to Port Assignment
++#
++
++#
++# Assignment
++#
++CONFIG_PINTx_REASSIGN=y
++CONFIG_PINT0_ASSIGN=0x00000101
++CONFIG_PINT1_ASSIGN=0x01010000
++CONFIG_PINT2_ASSIGN=0x07000101
++CONFIG_PINT3_ASSIGN=0x02020303
++
++#
++# Board customizations
++#
++# CONFIG_CMDLINE_BOOL is not set
++
++#
++# Clock/PLL Setup
++#
++CONFIG_CLKIN_HZ=25000000
++# CONFIG_BFIN_KERNEL_CLOCK is not set
++CONFIG_MAX_VCO_HZ=600000000
++CONFIG_MIN_VCO_HZ=50000000
++CONFIG_MAX_SCLK_HZ=133333333
++CONFIG_MIN_SCLK_HZ=27000000
++
++#
++# Kernel Timer/Scheduler
++#
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_GENERIC_TIME is not set
++# CONFIG_TICK_ONESHOT is not set
++
++#
++# Memory Setup
++#
++CONFIG_MAX_MEM_SIZE=64
++# CONFIG_MEM_MT46V32M16_6T is not set
++CONFIG_MEM_MT46V32M16_5B=y
++CONFIG_BOOT_LOAD=0x1000
++CONFIG_BFIN_SCRATCH_REG_RETN=y
++# CONFIG_BFIN_SCRATCH_REG_RETE is not set
++# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
++
++#
++# Blackfin Kernel Optimizations
++#
++
++#
++# Memory Optimizations
++#
++CONFIG_I_ENTRY_L1=y
++CONFIG_EXCPT_IRQ_SYSC_L1=y
++CONFIG_DO_IRQ_L1=y
++CONFIG_CORE_TIMER_IRQ_L1=y
++CONFIG_IDLE_L1=y
++# CONFIG_SCHEDULE_L1 is not set
++CONFIG_ARITHMETIC_OPS_L1=y
++CONFIG_ACCESS_OK_L1=y
++# CONFIG_MEMSET_L1 is not set
++# CONFIG_MEMCPY_L1 is not set
++# CONFIG_SYS_BFIN_SPINLOCK_L1 is not set
++# CONFIG_IP_CHECKSUM_L1 is not set
++CONFIG_CACHELINE_ALIGNED_L1=y
++# CONFIG_SYSCALL_TAB_L1 is not set
++# CONFIG_CPLB_SWITCH_TAB_L1 is not set
++CONFIG_RAMKERNEL=y
++# CONFIG_ROMKERNEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_BFIN_GPTIMERS is not set
++CONFIG_BFIN_DMA_5XX=y
++# CONFIG_DMA_UNCACHED_2M is not set
++CONFIG_DMA_UNCACHED_1M=y
++# CONFIG_DMA_UNCACHED_NONE is not set
++
++#
++# Cache Support
++#
++CONFIG_BFIN_ICACHE=y
++CONFIG_BFIN_DCACHE=y
++# CONFIG_BFIN_DCACHE_BANKA is not set
++# CONFIG_BFIN_ICACHE_LOCK is not set
++# CONFIG_BFIN_WB is not set
++CONFIG_BFIN_WT=y
++CONFIG_L1_MAX_PIECE=16
++# CONFIG_MPU is not set
++
++#
++# Asynchonous Memory Configuration
++#
++
++#
++# EBIU_AMGCTL Global Control
++#
++CONFIG_C_AMCKEN=y
++# CONFIG_C_CDPRIO is not set
++# CONFIG_C_AMBEN is not set
++# CONFIG_C_AMBEN_B0 is not set
++# CONFIG_C_AMBEN_B0_B1 is not set
++# CONFIG_C_AMBEN_B0_B1_B2 is not set
++CONFIG_C_AMBEN_ALL=y
++
++#
++# EBIU_AMBCTL Control
++#
++CONFIG_BANK_0=0x7BB0
++CONFIG_BANK_1=0x5554
++CONFIG_BANK_2=0x7BB0
++CONFIG_BANK_3=0x99B3
++CONFIG_EBIU_MBSCTLVAL=0x0
++CONFIG_EBIU_MODEVAL=0x1
++CONFIG_EBIU_FCTLVAL=0x6
++
++#
++# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
++#
++# CONFIG_PCI is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Executable file formats
++#
++CONFIG_BINFMT_ELF_FDPIC=y
++CONFIG_BINFMT_FLAT=y
++CONFIG_BINFMT_ZFLAT=y
++# CONFIG_BINFMT_SHARED_FLAT is not set
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++CONFIG_SUSPEND_UP_POSSIBLE=y
++# CONFIG_PM_WAKEUP_BY_GPIO is not set
++
++#
++# CPU Frequency scaling
++#
++# CONFIG_CPU_FREQ is not set
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++# CONFIG_IP_PNP_DHCP is not set
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETLABEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++CONFIG_MTD_CFI_INTELEXT=y
++# CONFIG_MTD_CFI_AMDSTD is not set
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++CONFIG_MTD_RAM=y
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++CONFIG_MTD_COMPLEX_MAPPINGS=y
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_START=0x20000000
++CONFIG_MTD_PHYSMAP_LEN=0x800000
++CONFIG_MTD_PHYSMAP_BANKWIDTH=2
++# CONFIG_MTD_UCLINUX is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_DATAFLASH is not set
++# CONFIG_MTD_M25P80 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=4096
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++CONFIG_BLK_DEV_SR=y
++# CONFIG_BLK_DEV_SR_VENDOR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_SMC91X is not set
++CONFIG_SMSC911X=y
++# CONFIG_DM9000 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=m
++CONFIG_INPUT_EVBUG=m
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ATKBD is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++# CONFIG_KEYBOARD_GPIO is not set
++# CONFIG_KEYBOARD_BFIN is not set
++# CONFIG_KEYBOARD_OPENCORES is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_AD9960 is not set
++# CONFIG_SPI_ADC_BF533 is not set
++# CONFIG_BF5xx_PPIFCD is not set
++# CONFIG_BFIN_SIMPLE_TIMER is not set
++# CONFIG_BF5xx_PPI is not set
++CONFIG_BFIN_OTP=y
++# CONFIG_BFIN_OTP_WRITE_ENABLE is not set
++# CONFIG_BFIN_SPORT is not set
++# CONFIG_BFIN_TIMER_LATENCY is not set
++# CONFIG_TWI_LCD is not set
++# CONFIG_SIMPLE_GPIO is not set
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_BFIN=y
++CONFIG_SERIAL_BFIN_CONSOLE=y
++# CONFIG_SERIAL_BFIN_DMA is not set
++CONFIG_SERIAL_BFIN_PIO=y
++# CONFIG_SERIAL_BFIN_UART0 is not set
++CONFIG_SERIAL_BFIN_UART1=y
++# CONFIG_BFIN_UART1_CTSRTS is not set
++# CONFIG_SERIAL_BFIN_UART2 is not set
++# CONFIG_SERIAL_BFIN_UART3 is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_BFIN_SPORT is not set
++CONFIG_UNIX98_PTYS=y
++# CONFIG_LEGACY_PTYS is not set
++
++#
++# CAN, the car bus and industrial fieldbus
++#
++# CONFIG_CAN4LINUX is not set
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++CONFIG_I2C_BLACKFIN_TWI=y
++CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_SENSORS_DS1337 is not set
++# CONFIG_SENSORS_DS1374 is not set
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_AD5252 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCF8575 is not set
++# CONFIG_SENSORS_PCA9543 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++CONFIG_SPI=y
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_BFIN=y
++# CONFIG_SPI_BITBANG is not set
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM70 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_BFIN_WDT=y
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++# CONFIG_USB_HIDINPUT_POWERBOOK is not set
++# CONFIG_HID_FF is not set
++# CONFIG_USB_HIDDEV is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++
++#
++# Miscellaneous USB options
++#
++# CONFIG_USB_DEVICEFS is not set
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_ISP116X_HCD is not set
++# CONFIG_USB_ISP1362_HCD is not set
++# CONFIG_USB_ISP1760_HCD is not set
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++CONFIG_USB_MUSB_HDRC=y
++CONFIG_USB_MUSB_SOC=y
++
++#
++# Blackfin BF54x, BF525 and BF527 high speed USB support
++#
++CONFIG_USB_MUSB_HOST=y
++# CONFIG_USB_MUSB_PERIPHERAL is not set
++# CONFIG_USB_MUSB_OTG is not set
++CONFIG_USB_MUSB_HDRC_HCD=y
++# CONFIG_MUSB_PIO_ONLY is not set
++# CONFIG_USB_INVENTRA_DMA is not set
++# CONFIG_USB_TI_CPPI_DMA is not set
++CONFIG_USB_MUSB_LOGLEVEL=0
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_ONETOUCH is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++
++#
++# USB Serial Converter support
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++
++#
++# USB DSL modem support
++#
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
++
++#
++# MMC/SD Host Controller Drivers
++#
++CONFIG_SDH_BFIN=y
++# CONFIG_MMC_SPI is not set
++# CONFIG_SPI_MMC is not set
++# CONFIG_NEW_LEDS is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_BFIN=y
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# PBX support
++#
++# CONFIG_PBX is not set
++
++#
++# File systems
++#
++# CONFIG_EXT2_FS is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++CONFIG_ISO9660_FS=m
++CONFIG_JOLIET=y
++CONFIG_ZISOFS=y
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=m
++CONFIG_MSDOS_FS=m
++CONFIG_VFAT_FS=m
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++CONFIG_NTFS_FS=m
++# CONFIG_NTFS_DEBUG is not set
++CONFIG_NTFS_RW=y
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++# CONFIG_TMPFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_YAFFS_FS=m
++CONFIG_YAFFS_YAFFS1=y
++# CONFIG_YAFFS_DOES_ECC is not set
++CONFIG_YAFFS_YAFFS2=y
++CONFIG_YAFFS_AUTO_YAFFS2=y
++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
++CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
++CONFIG_JFFS2_FS=m
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=m
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++CONFIG_NFSD=m
++CONFIG_NFSD_V3=y
++# CONFIG_NFSD_V3_ACL is not set
++# CONFIG_NFSD_V4 is not set
++CONFIG_NFSD_TCP=y
++CONFIG_LOCKD=m
++CONFIG_LOCKD_V4=y
++CONFIG_EXPORTFS=m
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=m
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++CONFIG_SMB_FS=m
++CONFIG_SMB_NLS_DEFAULT=y
++CONFIG_SMB_NLS_REMOTE="cp437"
++CONFIG_CIFS=y
++# CONFIG_CIFS_STATS is not set
++# CONFIG_CIFS_WEAK_PW_HASH is not set
++# CONFIG_CIFS_XATTR is not set
++# CONFIG_CIFS_DEBUG2 is not set
++# CONFIG_CIFS_EXPERIMENTAL is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=m
++CONFIG_NLS_CODEPAGE_737=m
++CONFIG_NLS_CODEPAGE_775=m
++CONFIG_NLS_CODEPAGE_850=m
++CONFIG_NLS_CODEPAGE_852=m
++CONFIG_NLS_CODEPAGE_855=m
++CONFIG_NLS_CODEPAGE_857=m
++CONFIG_NLS_CODEPAGE_860=m
++CONFIG_NLS_CODEPAGE_861=m
++CONFIG_NLS_CODEPAGE_862=m
++CONFIG_NLS_CODEPAGE_863=m
++CONFIG_NLS_CODEPAGE_864=m
++CONFIG_NLS_CODEPAGE_865=m
++CONFIG_NLS_CODEPAGE_866=m
++CONFIG_NLS_CODEPAGE_869=m
++CONFIG_NLS_CODEPAGE_936=m
++CONFIG_NLS_CODEPAGE_950=m
++CONFIG_NLS_CODEPAGE_932=m
++CONFIG_NLS_CODEPAGE_949=m
++CONFIG_NLS_CODEPAGE_874=m
++CONFIG_NLS_ISO8859_8=m
++CONFIG_NLS_CODEPAGE_1250=m
++CONFIG_NLS_CODEPAGE_1251=m
++CONFIG_NLS_ASCII=m
++CONFIG_NLS_ISO8859_1=m
++CONFIG_NLS_ISO8859_2=m
++CONFIG_NLS_ISO8859_3=m
++CONFIG_NLS_ISO8859_4=m
++CONFIG_NLS_ISO8859_5=m
++CONFIG_NLS_ISO8859_6=m
++CONFIG_NLS_ISO8859_7=m
++CONFIG_NLS_ISO8859_9=m
++CONFIG_NLS_ISO8859_13=m
++CONFIG_NLS_ISO8859_14=m
++CONFIG_NLS_ISO8859_15=m
++CONFIG_NLS_KOI8_R=m
++CONFIG_NLS_KOI8_U=m
++CONFIG_NLS_UTF8=m
++# CONFIG_DLM is not set
++CONFIG_INSTRUMENTATION=y
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_MMRS is not set
++CONFIG_DEBUG_HUNT_FOR_ZERO=y
++CONFIG_DEBUG_BFIN_HWTRACE_ON=y
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
++# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
++# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
++# CONFIG_EARLY_PRINTK is not set
++CONFIG_CPLB_INFO=y
++CONFIG_ACCESS_CHECK=y
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++CONFIG_SECURITY=y
++# CONFIG_SECURITY_NETWORK is not set
++# CONFIG_SECURITY_CAPABILITIES is not set
++# CONFIG_SECURITY_ROOTPLUG is not set
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=m
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=m
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/blackfin/configs/CM-BF561_defconfig b/arch/blackfin/configs/CM-BF561_defconfig
+new file mode 100644
+index 0000000..daf0090
+--- /dev/null
++++ b/arch/blackfin/configs/CM-BF561_defconfig
+@@ -0,0 +1,876 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.24.4
++# Tue Apr 1 10:50:11 2008
++#
++# CONFIG_MMU is not set
++# CONFIG_FPU is not set
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
++CONFIG_BLACKFIN=y
++CONFIG_ZONE_DMA=y
++CONFIG_SEMAPHORE_SLEEPERS=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_FORCE_MAX_ZONEORDER=14
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_BLK_DEV_INITRD is not set
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++# CONFIG_UID16 is not set
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++# CONFIG_HOTPLUG is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
++# CONFIG_NP2 is not set
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++CONFIG_TINY_SHMEM=y
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++# CONFIG_IOSCHED_DEADLINE is not set
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++CONFIG_DEFAULT_NOOP=y
++CONFIG_DEFAULT_IOSCHED="noop"
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++
++#
++# Blackfin Processor Options
++#
++
++#
++# Processor and Board Settings
++#
++# CONFIG_BF522 is not set
++# CONFIG_BF523 is not set
++# CONFIG_BF524 is not set
++# CONFIG_BF525 is not set
++# CONFIG_BF526 is not set
++# CONFIG_BF527 is not set
++# CONFIG_BF531 is not set
++# CONFIG_BF532 is not set
++# CONFIG_BF533 is not set
++# CONFIG_BF534 is not set
++# CONFIG_BF536 is not set
++# CONFIG_BF537 is not set
++# CONFIG_BF542 is not set
++# CONFIG_BF544 is not set
++# CONFIG_BF547 is not set
++# CONFIG_BF548 is not set
++# CONFIG_BF549 is not set
++CONFIG_BF561=y
++# CONFIG_BF_REV_0_0 is not set
++# CONFIG_BF_REV_0_1 is not set
++# CONFIG_BF_REV_0_2 is not set
++CONFIG_BF_REV_0_3=y
++# CONFIG_BF_REV_0_4 is not set
++# CONFIG_BF_REV_0_5 is not set
++# CONFIG_BF_REV_ANY is not set
++# CONFIG_BF_REV_NONE is not set
++CONFIG_BFIN_DUAL_CORE=y
++CONFIG_MEM_MT48LC8M32B2B5_7=y
++CONFIG_IRQ_PLL_WAKEUP=7
++CONFIG_IRQ_SPORT0_ERROR=7
++CONFIG_IRQ_SPORT1_ERROR=7
++CONFIG_IRQ_SPI_ERROR=7
++# CONFIG_BFIN561_EZKIT is not set
++# CONFIG_BFIN561_TEPLA is not set
++CONFIG_BFIN561_BLUETECHNIX_CM=y
++# CONFIG_GENERIC_BF561_BOARD is not set
++
++#
++# BF561 Specific Configuration
++#
++
++#
++# Core B Support
++#
++
++#
++# Core B Support
++#
++CONFIG_BF561_COREB=y
++# CONFIG_BF561_COREB_RESET is not set
++
++#
++# Interrupt Priority Assignment
++#
++
++#
++# Priority
++#
++CONFIG_IRQ_DMA1_ERROR=7
++CONFIG_IRQ_DMA2_ERROR=7
++CONFIG_IRQ_IMDMA_ERROR=7
++CONFIG_IRQ_PPI0_ERROR=7
++CONFIG_IRQ_PPI1_ERROR=7
++CONFIG_IRQ_UART_ERROR=7
++CONFIG_IRQ_RESERVED_ERROR=7
++CONFIG_IRQ_DMA1_0=8
++CONFIG_IRQ_DMA1_1=8
++CONFIG_IRQ_DMA1_2=8
++CONFIG_IRQ_DMA1_3=8
++CONFIG_IRQ_DMA1_4=8
++CONFIG_IRQ_DMA1_5=8
++CONFIG_IRQ_DMA1_6=8
++CONFIG_IRQ_DMA1_7=8
++CONFIG_IRQ_DMA1_8=8
++CONFIG_IRQ_DMA1_9=8
++CONFIG_IRQ_DMA1_10=8
++CONFIG_IRQ_DMA1_11=8
++CONFIG_IRQ_DMA2_0=9
++CONFIG_IRQ_DMA2_1=9
++CONFIG_IRQ_DMA2_2=9
++CONFIG_IRQ_DMA2_3=9
++CONFIG_IRQ_DMA2_4=9
++CONFIG_IRQ_DMA2_5=9
++CONFIG_IRQ_DMA2_6=9
++CONFIG_IRQ_DMA2_7=9
++CONFIG_IRQ_DMA2_8=9
++CONFIG_IRQ_DMA2_9=9
++CONFIG_IRQ_DMA2_10=9
++CONFIG_IRQ_DMA2_11=9
++CONFIG_IRQ_TIMER0=10
++CONFIG_IRQ_TIMER1=10
++CONFIG_IRQ_TIMER2=10
++CONFIG_IRQ_TIMER3=10
++CONFIG_IRQ_TIMER4=10
++CONFIG_IRQ_TIMER5=10
++CONFIG_IRQ_TIMER6=10
++CONFIG_IRQ_TIMER7=10
++CONFIG_IRQ_TIMER8=10
++CONFIG_IRQ_TIMER9=10
++CONFIG_IRQ_TIMER10=10
++CONFIG_IRQ_TIMER11=10
++CONFIG_IRQ_PROG0_INTA=11
++CONFIG_IRQ_PROG0_INTB=11
++CONFIG_IRQ_PROG1_INTA=11
++CONFIG_IRQ_PROG1_INTB=11
++CONFIG_IRQ_PROG2_INTA=11
++CONFIG_IRQ_PROG2_INTB=11
++CONFIG_IRQ_DMA1_WRRD0=8
++CONFIG_IRQ_DMA1_WRRD1=8
++CONFIG_IRQ_DMA2_WRRD0=9
++CONFIG_IRQ_DMA2_WRRD1=9
++CONFIG_IRQ_IMDMA_WRRD0=12
++CONFIG_IRQ_IMDMA_WRRD1=12
++CONFIG_IRQ_WDTIMER=13
++
++#
++# Board customizations
++#
++# CONFIG_CMDLINE_BOOL is not set
++
++#
++# Clock/PLL Setup
++#
++CONFIG_CLKIN_HZ=25000000
++# CONFIG_BFIN_KERNEL_CLOCK is not set
++CONFIG_MAX_VCO_HZ=600000000
++CONFIG_MIN_VCO_HZ=50000000
++CONFIG_MAX_SCLK_HZ=133333333
++CONFIG_MIN_SCLK_HZ=27000000
++
++#
++# Kernel Timer/Scheduler
++#
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++# CONFIG_CYCLES_CLOCKSOURCE is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++
++#
++# Memory Setup
++#
++CONFIG_MAX_MEM_SIZE=32
++CONFIG_BOOT_LOAD=0x1000
++CONFIG_BFIN_SCRATCH_REG_RETN=y
++# CONFIG_BFIN_SCRATCH_REG_RETE is not set
++# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
++
++#
++# Blackfin Kernel Optimizations
++#
++
++#
++# Memory Optimizations
++#
++CONFIG_I_ENTRY_L1=y
++CONFIG_EXCPT_IRQ_SYSC_L1=y
++CONFIG_DO_IRQ_L1=y
++CONFIG_CORE_TIMER_IRQ_L1=y
++CONFIG_IDLE_L1=y
++CONFIG_SCHEDULE_L1=y
++CONFIG_ARITHMETIC_OPS_L1=y
++CONFIG_ACCESS_OK_L1=y
++CONFIG_MEMSET_L1=y
++CONFIG_MEMCPY_L1=y
++CONFIG_SYS_BFIN_SPINLOCK_L1=y
++CONFIG_IP_CHECKSUM_L1=y
++CONFIG_CACHELINE_ALIGNED_L1=y
++CONFIG_SYSCALL_TAB_L1=y
++CONFIG_CPLB_SWITCH_TAB_L1=y
++CONFIG_RAMKERNEL=y
++# CONFIG_ROMKERNEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_VIRT_TO_BUS=y
++CONFIG_LARGE_ALLOCS=y
++# CONFIG_BFIN_GPTIMERS is not set
++CONFIG_BFIN_DMA_5XX=y
++# CONFIG_DMA_UNCACHED_2M is not set
++CONFIG_DMA_UNCACHED_1M=y
++# CONFIG_DMA_UNCACHED_NONE is not set
++
++#
++# Cache Support
++#
++CONFIG_BFIN_ICACHE=y
++CONFIG_BFIN_DCACHE=y
++# CONFIG_BFIN_DCACHE_BANKA is not set
++# CONFIG_BFIN_ICACHE_LOCK is not set
++CONFIG_BFIN_WB=y
++# CONFIG_BFIN_WT is not set
++CONFIG_L1_MAX_PIECE=16
++# CONFIG_MPU is not set
++
++#
++# Asynchonous Memory Configuration
++#
++
++#
++# EBIU_AMGCTL Global Control
++#
++CONFIG_C_AMCKEN=y
++CONFIG_C_CDPRIO=y
++CONFIG_C_B0PEN=y
++CONFIG_C_B1PEN=y
++CONFIG_C_B2PEN=y
++# CONFIG_C_B3PEN is not set
++# CONFIG_C_AMBEN is not set
++# CONFIG_C_AMBEN_B0 is not set
++# CONFIG_C_AMBEN_B0_B1 is not set
++# CONFIG_C_AMBEN_B0_B1_B2 is not set
++CONFIG_C_AMBEN_ALL=y
++
++#
++# EBIU_AMBCTL Control
++#
++CONFIG_BANK_0=0x7BB0
++CONFIG_BANK_1=0x7BB0
++CONFIG_BANK_2=0x7BB0
++CONFIG_BANK_3=0xFFC3
++
++#
++# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
++#
++# CONFIG_PCI is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++
++#
++# Executable file formats
++#
++CONFIG_BINFMT_ELF_FDPIC=y
++CONFIG_BINFMT_FLAT=y
++CONFIG_BINFMT_ZFLAT=y
++CONFIG_BINFMT_SHARED_FLAT=y
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++CONFIG_SUSPEND_UP_POSSIBLE=y
++# CONFIG_PM_WAKEUP_BY_GPIO is not set
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++# CONFIG_IP_PNP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETLABEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++# CONFIG_MTD_CFI is not set
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++CONFIG_MTD_RAM=y
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++CONFIG_MTD_UCLINUX=y
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=4096
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_IDE is not set
++# CONFIG_BFIN_IDE_ADDRESS_MAPPING_MODE0 is not set
++# CONFIG_BFIN_IDE_ADDRESS_MAPPING_MODE1 is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_SMC91X=y
++# CONFIG_SMSC911X is not set
++# CONFIG_DM9000 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_AX88180 is not set
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_AD9960 is not set
++# CONFIG_SPI_ADC_BF533 is not set
++# CONFIG_BF5xx_PPIFCD is not set
++# CONFIG_BFIN_SIMPLE_TIMER is not set
++# CONFIG_BF5xx_PPI is not set
++# CONFIG_BFIN_SPORT is not set
++# CONFIG_BFIN_TIMER_LATENCY is not set
++# CONFIG_SIMPLE_GPIO is not set
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_BFIN=y
++CONFIG_SERIAL_BFIN_CONSOLE=y
++CONFIG_SERIAL_BFIN_DMA=y
++# CONFIG_SERIAL_BFIN_PIO is not set
++CONFIG_SERIAL_BFIN_UART0=y
++# CONFIG_BFIN_UART0_CTSRTS is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_BFIN_SPORT is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++
++#
++# CAN, the car bus and industrial fieldbus
++#
++# CONFIG_CAN4LINUX is not set
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++# CONFIG_USB is not set
++
++#
++# Enable Host or Gadget support to see Inventra options
++#
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# PBX support
++#
++# CONFIG_PBX is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++# CONFIG_EXT2_FS_POSIX_ACL is not set
++# CONFIG_EXT2_FS_SECURITY is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++# CONFIG_TMPFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_YAFFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++# CONFIG_NFS_FS is not set
++# CONFIG_NFSD is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++CONFIG_INSTRUMENTATION=y
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_MMRS is not set
++CONFIG_DEBUG_HUNT_FOR_ZERO=y
++CONFIG_DEBUG_BFIN_HWTRACE_ON=y
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
++# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
++# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
++# CONFIG_EARLY_PRINTK is not set
++# CONFIG_DUAL_CORE_TEST_MODULE is not set
++CONFIG_CPLB_INFO=y
++CONFIG_ACCESS_CHECK=y
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++CONFIG_SECURITY=y
++# CONFIG_SECURITY_NETWORK is not set
++CONFIG_SECURITY_CAPABILITIES=y
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=m
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/blackfin/configs/H8606_defconfig b/arch/blackfin/configs/H8606_defconfig
+index 18cbb8c..679c748 100644
+--- a/arch/blackfin/configs/H8606_defconfig
++++ b/arch/blackfin/configs/H8606_defconfig
+@@ -13,7 +13,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_HARDIRQS=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+-# CONFIG_GENERIC_TIME is not set
++CONFIG_GENERIC_TIME=y
+ CONFIG_GENERIC_GPIO=y
+ CONFIG_FORCE_MAX_ZONEORDER=14
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
+@@ -207,7 +207,7 @@ CONFIG_HZ=250
+ #
+ # Memory Setup
+ #
+-CONFIG_MEM_SIZE=32
++CONFIG_MAX_MEM_SIZE=32
+ CONFIG_MEM_ADD_WIDTH=9
+ CONFIG_BOOT_LOAD=0x1000
+ CONFIG_BFIN_SCRATCH_REG_RETN=y
+diff --git a/arch/blackfin/configs/IP0X_defconfig b/arch/blackfin/configs/IP0X_defconfig
+new file mode 100644
+index 0000000..5f6ff04
+--- /dev/null
++++ b/arch/blackfin/configs/IP0X_defconfig
+@@ -0,0 +1,1252 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.22.18
++#
++# CONFIG_MMU is not set
++# CONFIG_FPU is not set
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
++CONFIG_BLACKFIN=y
++CONFIG_ZONE_DMA=y
++CONFIG_SEMAPHORE_SLEEPERS=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_GENERIC_IRQ_PROBE=y
++# CONFIG_GENERIC_TIME is not set
++CONFIG_GENERIC_GPIO=y
++CONFIG_FORCE_MAX_ZONEORDER=14
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SYSVIPC=y
++# CONFIG_IPC_NS is not set
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_UTS_NS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++# CONFIG_HOTPLUG is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
++# CONFIG_NP2 is not set
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_RT_MUTEXES=y
++CONFIG_TINY_SHMEM=y
++CONFIG_BASE_SMALL=0
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++
++#
++# Block layer
++#
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++# CONFIG_IOSCHED_DEADLINE is not set
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++
++#
++# Blackfin Processor Options
++#
++
++#
++# Processor and Board Settings
++#
++# CONFIG_BF522 is not set
++# CONFIG_BF523 is not set
++# CONFIG_BF524 is not set
++# CONFIG_BF525 is not set
++# CONFIG_BF526 is not set
++# CONFIG_BF527 is not set
++# CONFIG_BF531 is not set
++CONFIG_BF532=y
++# CONFIG_BF533 is not set
++# CONFIG_BF534 is not set
++# CONFIG_BF536 is not set
++# CONFIG_BF537 is not set
++# CONFIG_BF542 is not set
++# CONFIG_BF544 is not set
++# CONFIG_BF547 is not set
++# CONFIG_BF548 is not set
++# CONFIG_BF549 is not set
++# CONFIG_BF561 is not set
++# CONFIG_BF_REV_0_0 is not set
++# CONFIG_BF_REV_0_1 is not set
++# CONFIG_BF_REV_0_2 is not set
++# CONFIG_BF_REV_0_3 is not set
++# CONFIG_BF_REV_0_4 is not set
++CONFIG_BF_REV_0_5=y
++# CONFIG_BF_REV_ANY is not set
++# CONFIG_BF_REV_NONE is not set
++CONFIG_BF53x=y
++CONFIG_BFIN_SINGLE_CORE=y
++CONFIG_MEM_MT48LC32M16A2TG_75=y
++# CONFIG_BFIN533_EZKIT is not set
++# CONFIG_BFIN533_STAMP is not set
++# CONFIG_BFIN533_BLUETECHNIX_CM is not set
++# CONFIG_H8606_HVSISTEMAS is not set
++CONFIG_BFIN532_IP0X=y
++# CONFIG_GENERIC_BF533_BOARD is not set
++
++#
++# BF533/2/1 Specific Configuration
++#
++
++#
++# Interrupt Priority Assignment
++#
++
++#
++# Priority
++#
++CONFIG_UART_ERROR=7
++CONFIG_SPORT0_ERROR=7
++CONFIG_SPI_ERROR=7
++CONFIG_SPORT1_ERROR=7
++CONFIG_PPI_ERROR=7
++CONFIG_DMA_ERROR=7
++CONFIG_PLLWAKE_ERROR=7
++CONFIG_RTC_ERROR=8
++CONFIG_DMA0_PPI=8
++CONFIG_DMA1_SPORT0RX=9
++CONFIG_DMA2_SPORT0TX=9
++CONFIG_DMA3_SPORT1RX=9
++CONFIG_DMA4_SPORT1TX=9
++CONFIG_DMA5_SPI=10
++CONFIG_DMA6_UARTRX=10
++CONFIG_DMA7_UARTTX=10
++CONFIG_TIMER0=11
++CONFIG_TIMER1=11
++CONFIG_TIMER2=11
++CONFIG_PFA=12
++CONFIG_PFB=12
++CONFIG_MEMDMA0=13
++CONFIG_MEMDMA1=13
++CONFIG_WDTIMER=13
++
++#
++# Board customizations
++#
++# CONFIG_CMDLINE_BOOL is not set
++
++#
++# Clock/PLL Setup
++#
++CONFIG_CLKIN_HZ=10000000
++# CONFIG_BFIN_KERNEL_CLOCK is not set
++CONFIG_MAX_VCO_HZ=400000000
++CONFIG_MIN_VCO_HZ=50000000
++CONFIG_MAX_SCLK_HZ=133333333
++CONFIG_MIN_SCLK_HZ=27000000
++
++#
++# Kernel Timer/Scheduler
++#
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++
++#
++# Memory Setup
++#
++CONFIG_MEM_SIZE=64
++CONFIG_MEM_ADD_WIDTH=10
++
++#
++# Hardware addresses
++#
++CONFIG_IP0X_NET1=0x20100000
++CONFIG_IP0X_NET2=0x20200000
++CONFIG_IP0X_USB=0x20300000
++CONFIG_BOOT_LOAD=0x1000
++CONFIG_BFIN_SCRATCH_REG_RETN=y
++# CONFIG_BFIN_SCRATCH_REG_RETE is not set
++# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
++
++#
++# Blackfin Kernel Optimizations
++#
++
++#
++# Memory Optimizations
++#
++CONFIG_I_ENTRY_L1=y
++CONFIG_EXCPT_IRQ_SYSC_L1=y
++CONFIG_DO_IRQ_L1=y
++CONFIG_CORE_TIMER_IRQ_L1=y
++CONFIG_IDLE_L1=y
++CONFIG_SCHEDULE_L1=y
++CONFIG_ARITHMETIC_OPS_L1=y
++CONFIG_ACCESS_OK_L1=y
++CONFIG_MEMSET_L1=y
++CONFIG_MEMCPY_L1=y
++CONFIG_SYS_BFIN_SPINLOCK_L1=y
++# CONFIG_IP_CHECKSUM_L1 is not set
++CONFIG_CACHELINE_ALIGNED_L1=y
++# CONFIG_SYSCALL_TAB_L1 is not set
++# CONFIG_CPLB_SWITCH_TAB_L1 is not set
++CONFIG_RAMKERNEL=y
++# CONFIG_ROMKERNEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_LARGE_ALLOCS=y
++# CONFIG_BFIN_GPTIMERS is not set
++CONFIG_BFIN_DMA_5XX=y
++# CONFIG_DMA_UNCACHED_2M is not set
++CONFIG_DMA_UNCACHED_1M=y
++# CONFIG_DMA_UNCACHED_NONE is not set
++
++#
++# Cache Support
++#
++# CONFIG_BFIN_ICACHE is not set
++# CONFIG_BFIN_DCACHE is not set
++# CONFIG_BFIN_ICACHE_LOCK is not set
++CONFIG_L1_MAX_PIECE=16
++# CONFIG_MPU is not set
++
++#
++# Asynchonous Memory Configuration
++#
++
++#
++# EBIU_AMGCTL Global Control
++#
++CONFIG_C_AMCKEN=y
++CONFIG_C_CDPRIO=y
++# CONFIG_C_AMBEN is not set
++# CONFIG_C_AMBEN_B0 is not set
++# CONFIG_C_AMBEN_B0_B1 is not set
++# CONFIG_C_AMBEN_B0_B1_B2 is not set
++CONFIG_C_AMBEN_ALL=y
++
++#
++# EBIU_AMBCTL Control
++#
++CONFIG_BANK_0=0xffc2
++CONFIG_BANK_1=0xffc2
++CONFIG_BANK_2=0xffc2
++CONFIG_BANK_3=0xffc2
++
++#
++# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
++#
++# CONFIG_PCI is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++
++#
++# PCCARD (PCMCIA/CardBus) support
++#
++
++#
++# Executable file formats
++#
++CONFIG_BINFMT_ELF_FDPIC=y
++CONFIG_BINFMT_FLAT=y
++CONFIG_BINFMT_ZFLAT=y
++# CONFIG_BINFMT_SHARED_FLAT is not set
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Power management options
++#
++CONFIG_PM=y
++# CONFIG_PM_LEGACY is not set
++# CONFIG_PM_DEBUG is not set
++# CONFIG_PM_SYSFS_DEPRECATED is not set
++CONFIG_PM_BFIN_SLEEP_DEEPER=y
++# CONFIG_PM_BFIN_SLEEP is not set
++# CONFIG_PM_WAKEUP_BY_GPIO is not set
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++# CONFIG_IP_PNP_DHCP is not set
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IP_VS is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETLABEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++CONFIG_NETFILTER=y
++# CONFIG_NETFILTER_DEBUG is not set
++
++#
++# Core Netfilter Configuration
++#
++# CONFIG_NETFILTER_NETLINK is not set
++# CONFIG_NF_CONNTRACK_ENABLED is not set
++# CONFIG_NF_CONNTRACK is not set
++CONFIG_NETFILTER_XTABLES=y
++# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
++# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
++# CONFIG_NETFILTER_XT_TARGET_MARK is not set
++# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
++# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
++# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
++# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
++# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
++# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
++# CONFIG_NETFILTER_XT_MATCH_ESP is not set
++# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
++# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
++CONFIG_NETFILTER_XT_MATCH_MAC=y
++# CONFIG_NETFILTER_XT_MATCH_MARK is not set
++# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
++CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
++# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
++# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
++# CONFIG_NETFILTER_XT_MATCH_REALM is not set
++# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
++# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
++# CONFIG_NETFILTER_XT_MATCH_STRING is not set
++# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
++# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
++
++#
++# IP: Netfilter Configuration
++#
++# CONFIG_IP_NF_QUEUE is not set
++CONFIG_IP_NF_IPTABLES=y
++CONFIG_IP_NF_MATCH_IPRANGE=y
++CONFIG_IP_NF_MATCH_TOS=y
++# CONFIG_IP_NF_MATCH_RECENT is not set
++# CONFIG_IP_NF_MATCH_ECN is not set
++# CONFIG_IP_NF_MATCH_AH is not set
++# CONFIG_IP_NF_MATCH_TTL is not set
++# CONFIG_IP_NF_MATCH_OWNER is not set
++# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
++CONFIG_IP_NF_FILTER=y
++CONFIG_IP_NF_TARGET_REJECT=y
++# CONFIG_IP_NF_TARGET_LOG is not set
++# CONFIG_IP_NF_TARGET_ULOG is not set
++CONFIG_IP_NF_MANGLE=y
++CONFIG_IP_NF_TARGET_TOS=y
++# CONFIG_IP_NF_TARGET_ECN is not set
++# CONFIG_IP_NF_TARGET_TTL is not set
++# CONFIG_IP_NF_RAW is not set
++# CONFIG_IP_NF_ARPTABLES is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_SYS_HYPERVISOR is not set
++
++#
++# Connector - unified userspace <-> kernelspace linker
++#
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++CONFIG_MTD_RAM=y
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++CONFIG_MTD_COMPLEX_MAPPINGS=y
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_UCLINUX=y
++CONFIG_MTD_PLATRAM=y
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_DATAFLASH is not set
++# CONFIG_MTD_M25P80 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++# CONFIG_MTD_NAND_VERIFY_WRITE is not set
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_BFIN=y
++CONFIG_BFIN_NAND_BASE=0x20000000
++CONFIG_BFIN_NAND_SIZE=0x10000000
++CONFIG_BFIN_NAND_CLE=2
++CONFIG_BFIN_NAND_ALE=1
++CONFIG_BFIN_NAND_READY=10
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Plug and Play support
++#
++# CONFIG_PNPACPI is not set
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=4096
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++
++#
++# Misc devices
++#
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++
++#
++# SCSI low-level drivers
++#
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_ATA is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Network device support
++#
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_PHYLIB is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_SMC91X is not set
++# CONFIG_SMSC911X is not set
++CONFIG_DM9000=y
++CONFIG_NETDEV_1000=y
++# CONFIG_AX88180 is not set
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET_MII is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Telephony Support
++#
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_AD9960 is not set
++# CONFIG_SPI_ADC_BF533 is not set
++# CONFIG_BF5xx_PFLAGS is not set
++# CONFIG_BF5xx_PPIFCD is not set
++# CONFIG_BFIN_SIMPLE_TIMER is not set
++# CONFIG_BF5xx_PPI is not set
++CONFIG_BFIN_SPORT=y
++# CONFIG_BFIN_TIMER_LATENCY is not set
++# CONFIG_AD5304 is not set
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_BFIN=y
++CONFIG_SERIAL_BFIN_CONSOLE=y
++CONFIG_SERIAL_BFIN_DMA=y
++# CONFIG_SERIAL_BFIN_PIO is not set
++CONFIG_SERIAL_BFIN_UART0=y
++# CONFIG_BFIN_UART0_CTSRTS is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_BFIN_SPORT is not set
++CONFIG_UNIX98_PTYS=y
++# CONFIG_LEGACY_PTYS is not set
++
++#
++# CAN, the car bus and industrial fieldbus
++#
++# CONFIG_CAN4LINUX is not set
++
++#
++# IPMI
++#
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++# CONFIG_BFIN_WDT is not set
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# TPM devices
++#
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++CONFIG_SPI=y
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_BFIN=y
++# CONFIG_SPI_BITBANG is not set
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++
++#
++# Dallas's 1-wire bus
++#
++# CONFIG_W1 is not set
++# CONFIG_HWMON is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
++
++#
++# Graphics support
++#
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_FB is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++
++#
++# USB support
++#
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_SUSPEND is not set
++# CONFIG_USB_OTG is not set
++CONFIG_USB_OTG_WHITELIST=y
++# CONFIG_USB_OTG_BLACKLIST_HUB is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_ISP1362_HCD=y
++# CONFIG_USB_ISP1760_HCD is not set
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_MUSB_HDRC is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++
++#
++# USB Serial Converter support
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++
++#
++# USB DSL modem support
++#
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++CONFIG_MMC=m
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD Card Drivers
++#
++CONFIG_MMC_BLOCK=m
++
++#
++# MMC/SD Host Controller Drivers
++#
++CONFIG_SPI_MMC=m
++CONFIG_SPI_MMC_FRAMEWORK_DRIVER=y
++# CONFIG_SPI_MMC_BFIN_PIO_SPI is not set
++CONFIG_SPI_MMC_CS_CHAN=5
++CONFIG_SPI_MMC_MAX_HZ=20000000
++# CONFIG_SPI_MMC_CARD_DETECT is not set
++# CONFIG_SPI_MMC_DEBUG_MODE is not set
++
++#
++# LED devices
++#
++# CONFIG_NEW_LEDS is not set
++
++#
++# LED drivers
++#
++
++#
++# LED Triggers
++#
++
++#
++# InfiniBand support
++#
++
++#
++# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
++#
++
++#
++# Real Time Clock
++#
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_BFIN=y
++
++#
++# DMA Engine support
++#
++# CONFIG_DMA_ENGINE is not set
++
++#
++# DMA Clients
++#
++
++#
++# DMA Devices
++#
++
++#
++# PBX support
++#
++# CONFIG_PBX is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++# CONFIG_EXT2_FS_POSIX_ACL is not set
++# CONFIG_EXT2_FS_SECURITY is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++# CONFIG_TMPFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_YAFFS_FS=y
++CONFIG_YAFFS_YAFFS1=y
++# CONFIG_YAFFS_DOES_ECC is not set
++CONFIG_YAFFS_YAFFS2=y
++CONFIG_YAFFS_AUTO_YAFFS2=y
++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
++CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Network File Systems
++#
++# CONFIG_NFS_FS is not set
++# CONFIG_NFSD is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++
++#
++# Native Language Support
++#
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++
++#
++# Distributed Lock Manager
++#
++# CONFIG_DLM is not set
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_MMRS is not set
++CONFIG_DEBUG_HUNT_FOR_ZERO=y
++CONFIG_DEBUG_BFIN_HWTRACE_ON=y
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
++# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
++# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
++# CONFIG_EARLY_PRINTK is not set
++CONFIG_CPLB_INFO=y
++CONFIG_ACCESS_CHECK=y
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++CONFIG_SECURITY=y
++# CONFIG_SECURITY_NETWORK is not set
++CONFIG_SECURITY_CAPABILITIES=m
++# CONFIG_SECURITY_ROOTPLUG is not set
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=y
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/blackfin/configs/PNAV-10_defconfig b/arch/blackfin/configs/PNAV-10_defconfig
+index 25709f5..87622ad 100644
+--- a/arch/blackfin/configs/PNAV-10_defconfig
++++ b/arch/blackfin/configs/PNAV-10_defconfig
+@@ -13,7 +13,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
+ CONFIG_GENERIC_HWEIGHT=y
+ CONFIG_GENERIC_HARDIRQS=y
+ CONFIG_GENERIC_IRQ_PROBE=y
+-# CONFIG_GENERIC_TIME is not set
++CONFIG_GENERIC_TIME=y
+ CONFIG_GENERIC_GPIO=y
+ CONFIG_FORCE_MAX_ZONEORDER=14
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
+@@ -214,7 +214,7 @@ CONFIG_HZ=250
+ #
+ # Memory Setup
+ #
+-CONFIG_MEM_SIZE=64
++CONFIG_MAX_MEM_SIZE=64
+ CONFIG_MEM_ADD_WIDTH=10
+ CONFIG_BOOT_LOAD=0x1000
+ CONFIG_BFIN_SCRATCH_REG_RETN=y
+diff --git a/arch/blackfin/configs/SRV1_defconfig b/arch/blackfin/configs/SRV1_defconfig
+new file mode 100644
+index 0000000..951ea04
+--- /dev/null
++++ b/arch/blackfin/configs/SRV1_defconfig
+@@ -0,0 +1,1290 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.22.10
++# Fri Nov 2 20:50:23 2007
++#
++# CONFIG_MMU is not set
++# CONFIG_FPU is not set
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
++CONFIG_BLACKFIN=y
++CONFIG_ZONE_DMA=y
++CONFIG_BFIN=y
++CONFIG_SEMAPHORE_SLEEPERS=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_GENERIC_IRQ_PROBE=y
++# CONFIG_GENERIC_TIME is not set
++CONFIG_GENERIC_GPIO=y
++CONFIG_FORCE_MAX_ZONEORDER=14
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_IRQCHIP_DEMUX_GPIO=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SYSVIPC=y
++# CONFIG_IPC_NS is not set
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_UTS_NS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
++# CONFIG_NP2 is not set
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_RT_MUTEXES=y
++CONFIG_TINY_SHMEM=y
++CONFIG_BASE_SMALL=0
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++
++#
++# Block layer
++#
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++# CONFIG_IOSCHED_DEADLINE is not set
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++# CONFIG_PREEMPT_NONE is not set
++CONFIG_PREEMPT_VOLUNTARY=y
++# CONFIG_PREEMPT is not set
++
++#
++# Blackfin Processor Options
++#
++
++#
++# Processor and Board Settings
++#
++# CONFIG_BF522 is not set
++# CONFIG_BF525 is not set
++# CONFIG_BF527 is not set
++# CONFIG_BF531 is not set
++# CONFIG_BF532 is not set
++# CONFIG_BF533 is not set
++# CONFIG_BF534 is not set
++# CONFIG_BF536 is not set
++CONFIG_BF537=y
++# CONFIG_BF542 is not set
++# CONFIG_BF544 is not set
++# CONFIG_BF548 is not set
++# CONFIG_BF549 is not set
++# CONFIG_BF561 is not set
++# CONFIG_BF_REV_0_0 is not set
++# CONFIG_BF_REV_0_1 is not set
++CONFIG_BF_REV_0_2=y
++# CONFIG_BF_REV_0_3 is not set
++# CONFIG_BF_REV_0_4 is not set
++# CONFIG_BF_REV_0_5 is not set
++# CONFIG_BF_REV_ANY is not set
++# CONFIG_BF_REV_NONE is not set
++CONFIG_BF53x=y
++CONFIG_BFIN_SINGLE_CORE=y
++# CONFIG_BFIN527_EZKIT is not set
++# CONFIG_BFIN533_EZKIT is not set
++# CONFIG_BFIN533_STAMP is not set
++# CONFIG_BFIN537_STAMP is not set
++# CONFIG_CAMSIG_MINOTAUR is not set
++# CONFIG_BFIN533_BLUETECHNIX_CM is not set
++# CONFIG_BFIN537_BLUETECHNIX_CM is not set
++# CONFIG_BFIN548_EZKIT is not set
++# CONFIG_BFIN561_BLUETECHNIX_CM is not set
++# CONFIG_BFIN561_EZKIT is not set
++# CONFIG_BFIN561_TEPLA is not set
++# CONFIG_PNAV10 is not set
++# CONFIG_VISTASCAN is not set
++# CONFIG_BFIN533_SR3K is not set
++CONFIG_GENERIC_BOARD=y
++CONFIG_MEM_GENERIC_BOARD=y
++CONFIG_IRQ_PLL_WAKEUP=7
++CONFIG_IRQ_RTC=8
++CONFIG_IRQ_PPI=8
++CONFIG_IRQ_SPORT0_RX=9
++CONFIG_IRQ_SPORT0_TX=9
++CONFIG_IRQ_SPORT1_RX=9
++CONFIG_IRQ_SPORT1_TX=9
++CONFIG_IRQ_TWI=10
++CONFIG_IRQ_SPI=10
++CONFIG_IRQ_UART0_RX=10
++CONFIG_IRQ_UART0_TX=10
++CONFIG_IRQ_UART1_RX=10
++CONFIG_IRQ_UART1_TX=10
++CONFIG_IRQ_MAC_RX=11
++CONFIG_IRQ_MAC_TX=11
++CONFIG_IRQ_TMR0=12
++CONFIG_IRQ_TMR1=12
++CONFIG_IRQ_TMR2=12
++CONFIG_IRQ_TMR3=12
++CONFIG_IRQ_TMR4=12
++CONFIG_IRQ_TMR5=12
++CONFIG_IRQ_TMR6=12
++CONFIG_IRQ_TMR7=12
++CONFIG_IRQ_PORTG_INTB=12
++CONFIG_IRQ_MEM_DMA0=13
++CONFIG_IRQ_MEM_DMA1=13
++CONFIG_IRQ_WATCH=13
++
++#
++# BF537 Specific Configuration
++#
++
++#
++# Interrupt Priority Assignment
++#
++
++#
++# Priority
++#
++CONFIG_IRQ_DMA_ERROR=7
++CONFIG_IRQ_ERROR=7
++CONFIG_IRQ_CAN_RX=11
++CONFIG_IRQ_CAN_TX=11
++CONFIG_IRQ_PROG_INTA=12
++
++#
++# Board customizations
++#
++# CONFIG_CMDLINE_BOOL is not set
++
++#
++# Clock/PLL Setup
++#
++CONFIG_CLKIN_HZ=22118400
++# CONFIG_BFIN_KERNEL_CLOCK is not set
++CONFIG_MAX_VCO_HZ=600000000
++CONFIG_MIN_VCO_HZ=50000000
++CONFIG_MAX_SCLK_HZ=133000000
++CONFIG_MIN_SCLK_HZ=27000000
++
++#
++# Kernel Timer/Scheduler
++#
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++
++#
++# Memory Setup
++#
++CONFIG_MAX_MEM_SIZE=32
++CONFIG_MEM_ADD_WIDTH=9
++CONFIG_BOOT_LOAD=0x400000
++CONFIG_BFIN_SCRATCH_REG_RETN=y
++# CONFIG_BFIN_SCRATCH_REG_RETE is not set
++# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
++
++#
++# Blackfin Kernel Optimizations
++#
++
++#
++# Memory Optimizations
++#
++CONFIG_I_ENTRY_L1=y
++CONFIG_EXCPT_IRQ_SYSC_L1=y
++CONFIG_DO_IRQ_L1=y
++CONFIG_CORE_TIMER_IRQ_L1=y
++CONFIG_IDLE_L1=y
++CONFIG_SCHEDULE_L1=y
++CONFIG_ARITHMETIC_OPS_L1=y
++CONFIG_ACCESS_OK_L1=y
++CONFIG_MEMSET_L1=y
++CONFIG_MEMCPY_L1=y
++CONFIG_SYS_BFIN_SPINLOCK_L1=y
++# CONFIG_IP_CHECKSUM_L1 is not set
++CONFIG_CACHELINE_ALIGNED_L1=y
++# CONFIG_SYSCALL_TAB_L1 is not set
++# CONFIG_CPLB_SWITCH_TAB_L1 is not set
++CONFIG_RAMKERNEL=y
++# CONFIG_ROMKERNEL is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_LARGE_ALLOCS=y
++CONFIG_BFIN_DMA_5XX=y
++CONFIG_DMA_UNCACHED_2M=y
++# CONFIG_DMA_UNCACHED_1M is not set
++# CONFIG_DMA_UNCACHED_NONE is not set
++
++#
++# Cache Support
++#
++CONFIG_BFIN_ICACHE=y
++CONFIG_BFIN_DCACHE=y
++# CONFIG_BFIN_DCACHE_BANKA is not set
++# CONFIG_BFIN_ICACHE_LOCK is not set
++# CONFIG_BFIN_WB is not set
++CONFIG_BFIN_WT=y
++CONFIG_L1_MAX_PIECE=16
++
++#
++# Asynchonous Memory Configuration
++#
++
++#
++# EBIU_AMGCTL Global Control
++#
++CONFIG_C_AMCKEN=y
++CONFIG_C_CDPRIO=y
++# CONFIG_C_AMBEN is not set
++# CONFIG_C_AMBEN_B0 is not set
++# CONFIG_C_AMBEN_B0_B1 is not set
++# CONFIG_C_AMBEN_B0_B1_B2 is not set
++CONFIG_C_AMBEN_ALL=y
++
++#
++# EBIU_AMBCTL Control
++#
++CONFIG_BANK_0=0x7BB0
++CONFIG_BANK_1=0x7BB0
++CONFIG_BANK_2=0x7BB0
++CONFIG_BANK_3=0x99B3
++
++#
++# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
++#
++# CONFIG_PCI is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++
++#
++# PCCARD (PCMCIA/CardBus) support
++#
++# CONFIG_PCCARD is not set
++
++#
++# Executable file formats
++#
++CONFIG_BINFMT_ELF_FDPIC=y
++CONFIG_BINFMT_FLAT=y
++CONFIG_BINFMT_ZFLAT=y
++# CONFIG_BINFMT_SHARED_FLAT is not set
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Power management options
++#
++CONFIG_PM=y
++# CONFIG_PM_LEGACY is not set
++# CONFIG_PM_DEBUG is not set
++# CONFIG_PM_SYSFS_DEPRECATED is not set
++CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR=y
++# CONFIG_PM_WAKEUP_BY_GPIO is not set
++# CONFIG_PM_WAKEUP_GPIO_API is not set
++CONFIG_PM_WAKEUP_SIC_IWR=0x80000000
++
++#
++# CPU Frequency scaling
++#
++# CONFIG_CPU_FREQ is not set
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++# CONFIG_IP_PNP_DHCP is not set
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETLABEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++CONFIG_IRDA=m
++
++#
++# IrDA protocols
++#
++CONFIG_IRLAN=m
++CONFIG_IRCOMM=m
++# CONFIG_IRDA_ULTRA is not set
++
++#
++# IrDA options
++#
++CONFIG_IRDA_CACHE_LAST_LSAP=y
++# CONFIG_IRDA_FAST_RR is not set
++# CONFIG_IRDA_DEBUG is not set
++
++#
++# Infrared-port device drivers
++#
++
++#
++# SIR device drivers
++#
++CONFIG_IRTTY_SIR=m
++
++#
++# Dongle support
++#
++# CONFIG_DONGLE is not set
++
++#
++# Old SIR device drivers
++#
++# CONFIG_IRPORT_SIR is not set
++
++#
++# Old Serial dongle support
++#
++
++#
++# FIR device drivers
++#
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++
++#
++# Connector - unified userspace <-> kernelspace linker
++#
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=m
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++# CONFIG_MTD_CFI is not set
++CONFIG_MTD_JEDECPROBE=m
++CONFIG_MTD_GEN_PROBE=m
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++# CONFIG_MTD_CFI_AMDSTD is not set
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_MW320D=m
++CONFIG_MTD_RAM=y
++CONFIG_MTD_ROM=m
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++CONFIG_MTD_COMPLEX_MAPPINGS=y
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_BF5xx=m
++CONFIG_BFIN_FLASH_SIZE=0x400000
++CONFIG_EBIU_FLASH_BASE=0x20000000
++CONFIG_MTD_UCLINUX=y
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_DATAFLASH is not set
++# CONFIG_MTD_M25P80 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=m
++# CONFIG_MTD_NAND_VERIFY_WRITE is not set
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_BFIN=m
++CONFIG_BFIN_NAND_BASE=0x20212000
++CONFIG_BFIN_NAND_CLE=2
++CONFIG_BFIN_NAND_ALE=1
++CONFIG_BFIN_NAND_READY=3
++CONFIG_MTD_NAND_IDS=m
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Plug and Play support
++#
++# CONFIG_PNPACPI is not set
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=4096
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++
++#
++# Misc devices
++#
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Network device support
++#
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++# CONFIG_NET_ETHERNET is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Telephony Support
++#
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_TSDEV is not set
++CONFIG_INPUT_EVDEV=m
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++CONFIG_INPUT_MISC=y
++# CONFIG_INPUT_ATI_REMOTE is not set
++# CONFIG_INPUT_ATI_REMOTE2 is not set
++# CONFIG_INPUT_KEYSPAN_REMOTE is not set
++# CONFIG_INPUT_POWERMATE is not set
++# CONFIG_INPUT_YEALINK is not set
++CONFIG_INPUT_UINPUT=y
++# CONFIG_BF53X_PFBUTTONS is not set
++# CONFIG_TWI_KEYPAD is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_AD9960 is not set
++# CONFIG_SPI_ADC_BF533 is not set
++CONFIG_BF5xx_PFLAGS=y
++# CONFIG_BF5xx_PFLAGS_PROC is not set
++# CONFIG_BF5xx_PPIFCD is not set
++# CONFIG_BF5xx_TIMERS is not set
++# CONFIG_BF5xx_PPI is not set
++# CONFIG_BFIN_SPORT is not set
++# CONFIG_BFIN_TIMER_LATENCY is not set
++# CONFIG_TWI_LCD is not set
++# CONFIG_AD5304 is not set
++# CONFIG_BF5xx_TEA5764 is not set
++# CONFIG_BF5xx_FBDMA is not set
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_BFIN=y
++CONFIG_SERIAL_BFIN_CONSOLE=y
++CONFIG_SERIAL_BFIN_DMA=y
++# CONFIG_SERIAL_BFIN_PIO is not set
++CONFIG_SERIAL_BFIN_UART0=y
++# CONFIG_BFIN_UART0_CTSRTS is not set
++# CONFIG_SERIAL_BFIN_UART1 is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_BFIN_SPORT is not set
++CONFIG_UNIX98_PTYS=y
++# CONFIG_LEGACY_PTYS is not set
++
++#
++# CAN, the car bus and industrial fieldbus
++#
++# CONFIG_CAN4LINUX is not set
++
++#
++# IPMI
++#
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_BFIN_WDT=y
++CONFIG_HW_RANDOM=m
++# CONFIG_GEN_RTC is not set
++CONFIG_BLACKFIN_DPMC=y
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# TPM devices
++#
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_BLACKFIN_GPIO is not set
++CONFIG_I2C_BLACKFIN_TWI=y
++CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_STUB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_SENSORS_DS1337 is not set
++# CONFIG_SENSORS_DS1374 is not set
++# CONFIG_SENSORS_AD5252 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCF8575 is not set
++# CONFIG_SENSORS_PCA9543 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++CONFIG_SPI=y
++# CONFIG_SPI_DEBUG is not set
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_BFIN=y
++# CONFIG_SPI_BITBANG is not set
++
++#
++# SPI Protocol Masters
++#
++CONFIG_SPI_AT25=m
++# CONFIG_SPI_SPIDEV is not set
++
++#
++# Dallas's 1-wire bus
++#
++# CONFIG_W1 is not set
++CONFIG_HWMON=m
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_ABITUGURU is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ASB100 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_FSCHER is not set
++# CONFIG_SENSORS_FSCPOS is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM70 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++CONFIG_VIDEO_DEV=y
++# CONFIG_VIDEO_V4L1 is not set
++CONFIG_VIDEO_V4L1_COMPAT=y
++CONFIG_VIDEO_V4L2=y
++CONFIG_VIDEO_CAPTURE_DRIVERS=y
++# CONFIG_VIDEO_ADV_DEBUG is not set
++# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
++
++#
++# Encoders/decoders and other helper chips
++#
++
++#
++# Audio decoders
++#
++# CONFIG_VIDEO_TDA9840 is not set
++# CONFIG_VIDEO_TEA6415C is not set
++# CONFIG_VIDEO_TEA6420 is not set
++# CONFIG_VIDEO_MSP3400 is not set
++# CONFIG_VIDEO_CS53L32A is not set
++# CONFIG_VIDEO_TLV320AIC23B is not set
++# CONFIG_VIDEO_WM8775 is not set
++# CONFIG_VIDEO_WM8739 is not set
++
++#
++# Video decoders
++#
++# CONFIG_VIDEO_OV7670 is not set
++# CONFIG_VIDEO_SAA711X is not set
++# CONFIG_VIDEO_TVP5150 is not set
++
++#
++# Video and audio decoders
++#
++# CONFIG_VIDEO_CX25840 is not set
++
++#
++# MPEG video encoders
++#
++# CONFIG_VIDEO_CX2341X is not set
++
++#
++# Video encoders
++#
++# CONFIG_VIDEO_SAA7127 is not set
++
++#
++# Video improvement chips
++#
++# CONFIG_VIDEO_UPD64031A is not set
++# CONFIG_VIDEO_UPD64083 is not set
++# CONFIG_VIDEO_SAA5246A is not set
++# CONFIG_VIDEO_SAA5249 is not set
++# CONFIG_VIDEO_PPI_GENERIC is not set
++CONFIG_VIDEO_BLACKFIN_CAM=m
++# CONFIG_VIDEO_BLACKFIN_MT9M001 is not set
++
++#
++# CMOS Camera Sensor Selection
++#
++# CONFIG_MT9V022 is not set
++# CONFIG_MT9M001 is not set
++# CONFIG_VS6524 is not set
++# CONFIG_VS6624 is not set
++CONFIG_OV9655=y
++# CONFIG_RADIO_ADAPTERS is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_FB is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++
++#
++# HID Devices
++#
++# CONFIG_HID is not set
++
++#
++# USB support
++#
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++# CONFIG_USB is not set
++
++#
++# Enable Host or Gadget support to see Inventra options
++#
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++
++#
++# LED devices
++#
++# CONFIG_NEW_LEDS is not set
++
++#
++# LED drivers
++#
++
++#
++# LED Triggers
++#
++
++#
++# InfiniBand support
++#
++
++#
++# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
++#
++
++#
++# Real Time Clock
++#
++# CONFIG_RTC_CLASS is not set
++
++#
++# DMA Engine support
++#
++# CONFIG_DMA_ENGINE is not set
++
++#
++# DMA Clients
++#
++
++#
++# DMA Devices
++#
++
++#
++# PBX support
++#
++# CONFIG_PBX is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++# CONFIG_EXT2_FS_POSIX_ACL is not set
++# CONFIG_EXT2_FS_SECURITY is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++# CONFIG_TMPFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_YAFFS_FS=m
++CONFIG_YAFFS_YAFFS1=y
++# CONFIG_YAFFS_DOES_ECC is not set
++CONFIG_YAFFS_YAFFS2=y
++CONFIG_YAFFS_AUTO_YAFFS2=y
++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
++CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
++CONFIG_JFFS2_FS=m
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Network File Systems
++#
++CONFIG_NFS_FS=m
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_LOCKD=m
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=m
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++CONFIG_SMB_FS=m
++# CONFIG_SMB_NLS_DEFAULT is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++
++#
++# Native Language Support
++#
++CONFIG_NLS=m
++CONFIG_NLS_DEFAULT="iso8859-1"
++# CONFIG_NLS_CODEPAGE_437 is not set
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++# CONFIG_NLS_ISO8859_1 is not set
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++
++#
++# Distributed Lock Manager
++#
++# CONFIG_DLM is not set
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++CONFIG_DEBUG_INFO=y
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_FRAME_POINTER is not set
++# CONFIG_FORCED_INLINING is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_DEBUG_MMRS is not set
++# CONFIG_DEBUG_HWERR is not set
++CONFIG_DEBUG_HUNT_FOR_ZERO=y
++CONFIG_DEBUG_BFIN_HWTRACE_ON=y
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
++# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
++CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
++# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
++# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
++# CONFIG_EARLY_PRINTK is not set
++CONFIG_CPLB_INFO=y
++CONFIG_ACCESS_CHECK=y
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++CONFIG_SECURITY=y
++# CONFIG_SECURITY_NETWORK is not set
++CONFIG_SECURITY_CAPABILITIES=y
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=m
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=m
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile
+index 318b9b6..6140cd6 100644
+--- a/arch/blackfin/kernel/Makefile
++++ b/arch/blackfin/kernel/Makefile
+@@ -6,9 +6,15 @@ extra-y := init_task.o vmlinux.lds
+
+ obj-y := \
+ entry.o process.o bfin_ksyms.o ptrace.o setup.o signal.o \
+- sys_bfin.o time.o traps.o irqchip.o dma-mapping.o flat.o \
++ sys_bfin.o traps.o irqchip.o dma-mapping.o flat.o \
+ fixed_code.o reboot.o bfin_gpio.o
+
++ifeq ($(CONFIG_GENERIC_CLOCKEVENTS),y)
++ obj-y += time-ts.o
++else
++ obj-y += time.o
++endif
++
+ obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o
+ obj-$(CONFIG_MODULES) += module.o
+ obj-$(CONFIG_BFIN_DMA_5XX) += bfin_dma_5xx.o
+diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c
+index 8fd5d22..fd5448d 100644
+--- a/arch/blackfin/kernel/bfin_dma_5xx.c
++++ b/arch/blackfin/kernel/bfin_dma_5xx.c
+@@ -67,7 +67,7 @@ static int __init blackfin_dma_init(void)
+
+ for (i = 0; i < MAX_BLACKFIN_DMA_CHANNEL; i++) {
+ dma_ch[i].chan_status = DMA_CHANNEL_FREE;
+- dma_ch[i].regs = base_addr[i];
++ dma_ch[i].regs = dma_io_base_addr[i];
+ mutex_init(&(dma_ch[i].dmalock));
+ }
+ /* Mark MEMDMA Channel 0 as requested since we're using it internally */
+@@ -106,12 +106,15 @@ int request_dma(unsigned int channel, char *device_id)
+
+ #ifdef CONFIG_BF54x
+ if (channel >= CH_UART2_RX && channel <= CH_UART3_TX) {
+- if (strncmp(device_id, "BFIN_UART", 9) == 0)
++ if (strncmp(device_id, "BFIN_UART", 9) == 0) {
++ dma_ch[channel].regs->peripheral_map &= 0x0FFF;
+ dma_ch[channel].regs->peripheral_map |=
+- (channel - CH_UART2_RX + 0xC);
+- else
++ ((channel - CH_UART2_RX + 0xC)<<12);
++ } else {
++ dma_ch[channel].regs->peripheral_map &= 0x0FFF;
+ dma_ch[channel].regs->peripheral_map |=
+- (channel - CH_UART2_RX + 0x6);
++ ((channel - CH_UART2_RX + 0x6)<<12);
++ }
+ }
+ #endif
+
+diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c
+index 08788f7..7e8eaf4 100644
+--- a/arch/blackfin/kernel/bfin_gpio.c
++++ b/arch/blackfin/kernel/bfin_gpio.c
+@@ -95,14 +95,14 @@ enum {
+ AWA_data_clear = SYSCR,
+ AWA_data_set = SYSCR,
+ AWA_toggle = SYSCR,
+- AWA_maska = UART_SCR,
+- AWA_maska_clear = UART_SCR,
+- AWA_maska_set = UART_SCR,
+- AWA_maska_toggle = UART_SCR,
+- AWA_maskb = UART_GCTL,
+- AWA_maskb_clear = UART_GCTL,
+- AWA_maskb_set = UART_GCTL,
+- AWA_maskb_toggle = UART_GCTL,
++ AWA_maska = BFIN_UART_SCR,
++ AWA_maska_clear = BFIN_UART_SCR,
++ AWA_maska_set = BFIN_UART_SCR,
++ AWA_maska_toggle = BFIN_UART_SCR,
++ AWA_maskb = BFIN_UART_GCTL,
++ AWA_maskb_clear = BFIN_UART_GCTL,
++ AWA_maskb_set = BFIN_UART_GCTL,
++ AWA_maskb_toggle = BFIN_UART_GCTL,
+ AWA_dir = SPORT1_STAT,
+ AWA_polar = SPORT1_STAT,
+ AWA_edge = SPORT1_STAT,
+@@ -348,11 +348,10 @@ static void portmux_setup(unsigned short per, unsigned short function)
+ offset = port_mux_lut[y].offset;
+ muxreg = bfin_read_PORT_MUX();
+
+- if (offset != 1) {
++ if (offset != 1)
+ muxreg &= ~(1 << offset);
+- } else {
++ else
+ muxreg &= ~(3 << 1);
+- }
+
+ muxreg |= (function << offset);
+ bfin_write_PORT_MUX(muxreg);
+@@ -396,39 +395,11 @@ inline void portmux_setup(unsigned short portno, unsigned short function)
+ # define portmux_setup(...) do { } while (0)
+ #endif
+
+-#ifndef BF548_FAMILY
+-static void default_gpio(unsigned gpio)
+-{
+- unsigned short bank, bitmask;
+- unsigned long flags;
+-
+- bank = gpio_bank(gpio);
+- bitmask = gpio_bit(gpio);
+-
+- local_irq_save(flags);
+-
+- gpio_bankb[bank]->maska_clear = bitmask;
+- gpio_bankb[bank]->maskb_clear = bitmask;
+- SSYNC();
+- gpio_bankb[bank]->inen &= ~bitmask;
+- gpio_bankb[bank]->dir &= ~bitmask;
+- gpio_bankb[bank]->polar &= ~bitmask;
+- gpio_bankb[bank]->both &= ~bitmask;
+- gpio_bankb[bank]->edge &= ~bitmask;
+- AWA_DUMMY_READ(edge);
+- local_irq_restore(flags);
+-}
+-#else
+-# define default_gpio(...) do { } while (0)
+-#endif
+-
+ static int __init bfin_gpio_init(void)
+ {
+-
+ printk(KERN_INFO "Blackfin GPIO Controller\n");
+
+ return 0;
+-
+ }
+ arch_initcall(bfin_gpio_init);
+
+@@ -821,10 +792,10 @@ int peripheral_request(unsigned short per, const char *label)
+ local_irq_save(flags);
+
+ if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {
++ dump_stack();
+ printk(KERN_ERR
+ "%s: Peripheral %d is already reserved as GPIO by %s !\n",
+- __FUNCTION__, ident, get_label(ident));
+- dump_stack();
++ __func__, ident, get_label(ident));
+ local_irq_restore(flags);
+ return -EBUSY;
+ }
+@@ -833,31 +804,31 @@ int peripheral_request(unsigned short per, const char *label)
+
+ u16 funct = get_portmux(ident);
+
+- /*
+- * Pin functions like AMC address strobes my
+- * be requested and used by several drivers
+- */
++ /*
++ * Pin functions like AMC address strobes my
++ * be requested and used by several drivers
++ */
+
+ if (!((per & P_MAYSHARE) && (funct == P_FUNCT2MUX(per)))) {
+
+- /*
+- * Allow that the identical pin function can
+- * be requested from the same driver twice
+- */
++ /*
++ * Allow that the identical pin function can
++ * be requested from the same driver twice
++ */
+
+- if (cmp_label(ident, label) == 0)
+- goto anyway;
++ if (cmp_label(ident, label) == 0)
++ goto anyway;
+
++ dump_stack();
+ printk(KERN_ERR
+ "%s: Peripheral %d function %d is already reserved by %s !\n",
+- __FUNCTION__, ident, P_FUNCT2MUX(per), get_label(ident));
+- dump_stack();
++ __func__, ident, P_FUNCT2MUX(per), get_label(ident));
+ local_irq_restore(flags);
+ return -EBUSY;
+ }
+ }
+
+-anyway:
++ anyway:
+ reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident);
+
+ portmux_setup(ident, P_FUNCT2MUX(per));
+@@ -890,47 +861,47 @@ int peripheral_request(unsigned short per, const char *label)
+
+ if (!check_gpio(ident)) {
+
+- if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {
+- printk(KERN_ERR
+- "%s: Peripheral %d is already reserved as GPIO by %s !\n",
+- __FUNCTION__, ident, get_label(ident));
+- dump_stack();
+- local_irq_restore(flags);
+- return -EBUSY;
+- }
++ if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {
++ dump_stack();
++ printk(KERN_ERR
++ "%s: Peripheral %d is already reserved as GPIO by %s !\n",
++ __func__, ident, get_label(ident));
++ local_irq_restore(flags);
++ return -EBUSY;
++ }
+
+ }
+
+ if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) {
+
+- /*
+- * Pin functions like AMC address strobes my
+- * be requested and used by several drivers
+- */
++ /*
++ * Pin functions like AMC address strobes my
++ * be requested and used by several drivers
++ */
+
+- if (!(per & P_MAYSHARE)) {
++ if (!(per & P_MAYSHARE)) {
+
+- /*
+- * Allow that the identical pin function can
+- * be requested from the same driver twice
+- */
++ /*
++ * Allow that the identical pin function can
++ * be requested from the same driver twice
++ */
+
+- if (cmp_label(ident, label) == 0)
+- goto anyway;
++ if (cmp_label(ident, label) == 0)
++ goto anyway;
+
++ dump_stack();
+ printk(KERN_ERR
+ "%s: Peripheral %d function %d is already"
+ " reserved by %s !\n",
+- __FUNCTION__, ident, P_FUNCT2MUX(per),
++ __func__, ident, P_FUNCT2MUX(per),
+ get_label(ident));
+- dump_stack();
+ local_irq_restore(flags);
+ return -EBUSY;
+ }
+
+ }
+
+-anyway:
++ anyway:
+ portmux_setup(per, P_FUNCT2MUX(per));
+
+ port_setup(ident, PERIPHERAL_USAGE);
+@@ -944,7 +915,7 @@ anyway:
+ EXPORT_SYMBOL(peripheral_request);
+ #endif
+
+-int peripheral_request_list(unsigned short per[], const char *label)
++int peripheral_request_list(const unsigned short per[], const char *label)
+ {
+ u16 cnt;
+ int ret;
+@@ -954,10 +925,10 @@ int peripheral_request_list(unsigned short per[], const char *label)
+ ret = peripheral_request(per[cnt], label);
+
+ if (ret < 0) {
+- for ( ; cnt > 0; cnt--) {
++ for ( ; cnt > 0; cnt--)
+ peripheral_free(per[cnt - 1]);
+- }
+- return ret;
++
++ return ret;
+ }
+ }
+
+@@ -981,15 +952,13 @@ void peripheral_free(unsigned short per)
+
+ local_irq_save(flags);
+
+- if (unlikely(!(reserved_peri_map[gpio_bank(ident)]
+- & gpio_bit(ident)))) {
++ if (unlikely(!(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident)))) {
+ local_irq_restore(flags);
+ return;
+ }
+
+- if (!(per & P_MAYSHARE)) {
++ if (!(per & P_MAYSHARE))
+ port_setup(ident, GPIO_USAGE);
+- }
+
+ reserved_peri_map[gpio_bank(ident)] &= ~gpio_bit(ident);
+
+@@ -999,14 +968,11 @@ void peripheral_free(unsigned short per)
+ }
+ EXPORT_SYMBOL(peripheral_free);
+
+-void peripheral_free_list(unsigned short per[])
++void peripheral_free_list(const unsigned short per[])
+ {
+ u16 cnt;
+-
+- for (cnt = 0; per[cnt] != 0; cnt++) {
++ for (cnt = 0; per[cnt] != 0; cnt++)
+ peripheral_free(per[cnt]);
+- }
+-
+ }
+ EXPORT_SYMBOL(peripheral_free_list);
+
+@@ -1046,17 +1012,17 @@ int gpio_request(unsigned gpio, const char *label)
+ }
+
+ if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
++ dump_stack();
+ printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
+ gpio, get_label(gpio));
+- dump_stack();
+ local_irq_restore(flags);
+ return -EBUSY;
+ }
+ if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
++ dump_stack();
+ printk(KERN_ERR
+ "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
+ gpio, get_label(gpio));
+- dump_stack();
+ local_irq_restore(flags);
+ return -EBUSY;
+ }
+@@ -1082,14 +1048,12 @@ void gpio_free(unsigned gpio)
+ local_irq_save(flags);
+
+ if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
+- gpio_error(gpio);
+ dump_stack();
++ gpio_error(gpio);
+ local_irq_restore(flags);
+ return;
+ }
+
+- default_gpio(gpio);
+-
+ reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
+
+ set_label(gpio, "free");
+@@ -1152,6 +1116,18 @@ int gpio_get_value(unsigned gpio)
+ }
+ EXPORT_SYMBOL(gpio_get_value);
+
++void bfin_gpio_irq_prepare(unsigned gpio)
++{
++ unsigned long flags;
++
++ port_setup(gpio, GPIO_USAGE);
++
++ local_irq_save(flags);
++ gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio);
++ gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio);
++ local_irq_restore(flags);
++}
++
+ #else
+
+ int gpio_direction_input(unsigned gpio)
+@@ -1218,6 +1194,11 @@ void bfin_gpio_reset_spi0_ssel1(void)
+ udelay(1);
+ }
+
++void bfin_gpio_irq_prepare(unsigned gpio)
++{
++ port_setup(gpio, GPIO_USAGE);
++}
++
+ #endif /*BF548_FAMILY */
+
+ #if defined(CONFIG_PROC_FS)
+diff --git a/arch/blackfin/kernel/bfin_ksyms.c b/arch/blackfin/kernel/bfin_ksyms.c
+index 0bfbb26..053edff 100644
+--- a/arch/blackfin/kernel/bfin_ksyms.c
++++ b/arch/blackfin/kernel/bfin_ksyms.c
+@@ -42,11 +42,6 @@ EXPORT_SYMBOL(ip_fast_csum);
+
+ EXPORT_SYMBOL(kernel_thread);
+
+-EXPORT_SYMBOL(__up);
+-EXPORT_SYMBOL(__down);
+-EXPORT_SYMBOL(__down_trylock);
+-EXPORT_SYMBOL(__down_interruptible);
+-
+ EXPORT_SYMBOL(is_in_rom);
+ EXPORT_SYMBOL(bfin_return_from_exception);
+
+diff --git a/arch/blackfin/kernel/cplb-mpu/cplbinfo.c b/arch/blackfin/kernel/cplb-mpu/cplbinfo.c
+index bd07229..822beef 100644
+--- a/arch/blackfin/kernel/cplb-mpu/cplbinfo.c
++++ b/arch/blackfin/kernel/cplb-mpu/cplbinfo.c
+@@ -39,14 +39,6 @@
+ #include <asm/cplbinit.h>
+ #include <asm/blackfin.h>
+
+-#define CPLB_I 1
+-#define CPLB_D 2
+-
+-#define SYNC_SYS SSYNC()
+-#define SYNC_CORE CSYNC()
+-
+-#define CPLB_BIT_PAGESIZE 0x30000
+-
+ static char page_size_string_table[][4] = { "1K", "4K", "1M", "4M" };
+
+ static char *cplb_print_entry(char *buf, struct cplb_entry *tbl, int switched)
+diff --git a/arch/blackfin/kernel/cplb-mpu/cplbinit.c b/arch/blackfin/kernel/cplb-mpu/cplbinit.c
+index dc6e8a7..4806010 100644
+--- a/arch/blackfin/kernel/cplb-mpu/cplbinit.c
++++ b/arch/blackfin/kernel/cplb-mpu/cplbinit.c
+@@ -43,13 +43,15 @@ void __init generate_cpl_tables(void)
+ unsigned long d_data, i_data;
+ unsigned long d_cache = 0, i_cache = 0;
+
++ printk(KERN_INFO "MPU: setting up cplb tables with memory protection\n");
++
+ #ifdef CONFIG_BFIN_ICACHE
+ i_cache = CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
+ #endif
+
+ #ifdef CONFIG_BFIN_DCACHE
+ d_cache = CPLB_L1_CHBL;
+-#ifdef CONFIG_BLKFIN_WT
++#ifdef CONFIG_BFIN_WT
+ d_cache |= CPLB_L1_AOW | CPLB_WT;
+ #endif
+ #endif
+diff --git a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
+index c426a22..99f2831 100644
+--- a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
++++ b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
+@@ -24,8 +24,6 @@
+ #include <asm/cplbinit.h>
+ #include <asm/mmu_context.h>
+
+-#ifdef CONFIG_BFIN_ICACHE
+-
+ #define FAULT_RW (1 << 16)
+ #define FAULT_USERSUPV (1 << 17)
+
+@@ -143,30 +141,48 @@ static noinline int dcplb_miss(void)
+ unsigned long d_data;
+
+ nr_dcplb_miss++;
+- if (addr >= _ramend)
+- return CPLB_PROT_VIOL;
+
+ d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB;
+ #ifdef CONFIG_BFIN_DCACHE
+- d_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
+-#ifdef CONFIG_BLKFIN_WT
+- d_data |= CPLB_L1_AOW | CPLB_WT;
+-#endif
++ if (addr < _ramend - DMA_UNCACHED_REGION ||
++ (reserved_mem_dcache_on && addr >= _ramend &&
++ addr < physical_mem_end)) {
++ d_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
++#ifdef CONFIG_BFIN_WT
++ d_data |= CPLB_L1_AOW | CPLB_WT;
+ #endif
+- mask = current_rwx_mask;
+- if (mask) {
+- int page = addr >> PAGE_SHIFT;
+- int offs = page >> 5;
+- int bit = 1 << (page & 31);
+-
+- if (mask[offs] & bit)
+- d_data |= CPLB_USER_RD;
+-
+- mask += page_mask_nelts;
+- if (mask[offs] & bit)
+- d_data |= CPLB_USER_WR;
+ }
++#endif
++ if (addr >= physical_mem_end) {
++ if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE
++ && (status & FAULT_USERSUPV)) {
++ addr &= ~0x3fffff;
++ d_data &= ~PAGE_SIZE_4KB;
++ d_data |= PAGE_SIZE_4MB;
++ } else if (addr >= BOOT_ROM_START && addr < BOOT_ROM_START + BOOT_ROM_LENGTH
++ && (status & (FAULT_RW | FAULT_USERSUPV)) == FAULT_USERSUPV) {
++ addr &= ~(1 * 1024 * 1024 - 1);
++ d_data &= ~PAGE_SIZE_4KB;
++ d_data |= PAGE_SIZE_1MB;
++ } else
++ return CPLB_PROT_VIOL;
++ } else if (addr >= _ramend) {
++ d_data |= CPLB_USER_RD | CPLB_USER_WR;
++ } else {
++ mask = current_rwx_mask;
++ if (mask) {
++ int page = addr >> PAGE_SHIFT;
++ int offs = page >> 5;
++ int bit = 1 << (page & 31);
++
++ if (mask[offs] & bit)
++ d_data |= CPLB_USER_RD;
+
++ mask += page_mask_nelts;
++ if (mask[offs] & bit)
++ d_data |= CPLB_USER_WR;
++ }
++ }
+ idx = evict_one_dcplb();
+
+ addr &= PAGE_MASK;
+@@ -189,12 +205,14 @@ static noinline int icplb_miss(void)
+ unsigned long i_data;
+
+ nr_icplb_miss++;
+- if (status & FAULT_USERSUPV)
+- nr_icplb_supv_miss++;
+
+- if (addr >= _ramend)
++ /* If inside the uncached DMA region, fault. */
++ if (addr >= _ramend - DMA_UNCACHED_REGION && addr < _ramend)
+ return CPLB_PROT_VIOL;
+
++ if (status & FAULT_USERSUPV)
++ nr_icplb_supv_miss++;
++
+ /*
+ * First, try to find a CPLB that matches this address. If we
+ * find one, then the fact that we're in the miss handler means
+@@ -211,30 +229,48 @@ static noinline int icplb_miss(void)
+ }
+
+ i_data = CPLB_VALID | CPLB_PORTPRIO | PAGE_SIZE_4KB;
+-#ifdef CONFIG_BFIN_ICACHE
+- i_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
+-#endif
+
++#ifdef CONFIG_BFIN_ICACHE
+ /*
+- * Two cases to distinguish - a supervisor access must necessarily
+- * be for a module page; we grant it unconditionally (could do better
+- * here in the future). Otherwise, check the x bitmap of the current
+- * process.
++ * Normal RAM, and possibly the reserved memory area, are
++ * cacheable.
+ */
+- if (!(status & FAULT_USERSUPV)) {
+- unsigned long *mask = current_rwx_mask;
+-
+- if (mask) {
+- int page = addr >> PAGE_SHIFT;
+- int offs = page >> 5;
+- int bit = 1 << (page & 31);
++ if (addr < _ramend ||
++ (addr < physical_mem_end && reserved_mem_icache_on))
++ i_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
++#endif
+
+- mask += 2 * page_mask_nelts;
+- if (mask[offs] & bit)
+- i_data |= CPLB_USER_RD;
++ if (addr >= physical_mem_end) {
++ if (addr >= BOOT_ROM_START && addr < BOOT_ROM_START + BOOT_ROM_LENGTH
++ && (status & FAULT_USERSUPV)) {
++ addr &= ~(1 * 1024 * 1024 - 1);
++ i_data &= ~PAGE_SIZE_4KB;
++ i_data |= PAGE_SIZE_1MB;
++ } else
++ return CPLB_PROT_VIOL;
++ } else if (addr >= _ramend) {
++ i_data |= CPLB_USER_RD;
++ } else {
++ /*
++ * Two cases to distinguish - a supervisor access must
++ * necessarily be for a module page; we grant it
++ * unconditionally (could do better here in the future).
++ * Otherwise, check the x bitmap of the current process.
++ */
++ if (!(status & FAULT_USERSUPV)) {
++ unsigned long *mask = current_rwx_mask;
++
++ if (mask) {
++ int page = addr >> PAGE_SHIFT;
++ int offs = page >> 5;
++ int bit = 1 << (page & 31);
++
++ mask += 2 * page_mask_nelts;
++ if (mask[offs] & bit)
++ i_data |= CPLB_USER_RD;
++ }
+ }
+ }
+-
+ idx = evict_one_icplb();
+ addr &= PAGE_MASK;
+ icplb_tbl[idx].addr = addr;
+@@ -250,7 +286,6 @@ static noinline int icplb_miss(void)
+
+ static noinline int dcplb_protection_fault(void)
+ {
+- unsigned long addr = bfin_read_DCPLB_FAULT_ADDR();
+ int status = bfin_read_DCPLB_STATUS();
+
+ nr_dcplb_prot++;
+@@ -280,8 +315,7 @@ int cplb_hdr(int seqstat, struct pt_regs *regs)
+ case 0x26:
+ return dcplb_miss();
+ default:
+- return 1;
+- panic_cplb_error(seqstat, regs);
++ return 1;
+ }
+ }
+
+@@ -299,7 +333,7 @@ void flush_switched_cplbs(void)
+ enable_icplb();
+
+ disable_dcplb();
+- for (i = first_mask_dcplb; i < MAX_CPLBS; i++) {
++ for (i = first_switched_dcplb; i < MAX_CPLBS; i++) {
+ dcplb_tbl[i].data = 0;
+ bfin_write32(DCPLB_DATA0 + i * 4, 0);
+ }
+@@ -319,7 +353,7 @@ void set_mask_dcplbs(unsigned long *masks)
+ d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB;
+ #ifdef CONFIG_BFIN_DCACHE
+ d_data |= CPLB_L1_CHBL;
+-#ifdef CONFIG_BLKFIN_WT
++#ifdef CONFIG_BFIN_WT
+ d_data |= CPLB_L1_AOW | CPLB_WT;
+ #endif
+ #endif
+@@ -334,5 +368,3 @@ void set_mask_dcplbs(unsigned long *masks)
+ }
+ enable_dcplb();
+ }
+-
+-#endif
+diff --git a/arch/blackfin/kernel/cplb-nompu/cplbinfo.c b/arch/blackfin/kernel/cplb-nompu/cplbinfo.c
+index a4f0b42..1e74f0b 100644
+--- a/arch/blackfin/kernel/cplb-nompu/cplbinfo.c
++++ b/arch/blackfin/kernel/cplb-nompu/cplbinfo.c
+@@ -33,9 +33,7 @@
+ #include <linux/proc_fs.h>
+ #include <linux/uaccess.h>
+
+-#include <asm/current.h>
+-#include <asm/system.h>
+-#include <asm/cplb.h>
++#include <asm/cplbinit.h>
+ #include <asm/blackfin.h>
+
+ #define CPLB_I 1
+@@ -174,16 +172,6 @@ static int cplbinfo_read_proc(char *page, char **start, off_t off,
+ return len;
+ }
+
+-static int cplbinfo_write_proc(struct file *file, const char __user *buffer,
+- unsigned long count, void *data)
+-{
+- printk(KERN_INFO "Reset the CPLB swap in/out counts.\n");
+- memset(ipdt_swapcount_table, 0, MAX_SWITCH_I_CPLBS * sizeof(unsigned long));
+- memset(dpdt_swapcount_table, 0, MAX_SWITCH_D_CPLBS * sizeof(unsigned long));
+-
+- return count;
+-}
+-
+ static int __init cplbinfo_init(void)
+ {
+ struct proc_dir_entry *entry;
+@@ -193,7 +181,6 @@ static int __init cplbinfo_init(void)
+ return -ENOMEM;
+
+ entry->read_proc = cplbinfo_read_proc;
+- entry->write_proc = cplbinfo_write_proc;
+ entry->data = NULL;
+
+ return 0;
+diff --git a/arch/blackfin/kernel/cplb-nompu/cplbinit.c b/arch/blackfin/kernel/cplb-nompu/cplbinit.c
+index 6320bc4..917325b 100644
+--- a/arch/blackfin/kernel/cplb-nompu/cplbinit.c
++++ b/arch/blackfin/kernel/cplb-nompu/cplbinit.c
+@@ -26,6 +26,35 @@
+ #include <asm/cplb.h>
+ #include <asm/cplbinit.h>
+
++#ifdef CONFIG_MAX_MEM_SIZE
++# define CPLB_MEM CONFIG_MAX_MEM_SIZE
++#else
++# define CPLB_MEM CONFIG_MEM_SIZE
++#endif
++
++/*
++* Number of required data CPLB switchtable entries
++* MEMSIZE / 4 (we mostly install 4M page size CPLBs
++* approx 16 for smaller 1MB page size CPLBs for allignment purposes
++* 1 for L1 Data Memory
++* possibly 1 for L2 Data Memory
++* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
++* 1 for ASYNC Memory
++*/
++#define MAX_SWITCH_D_CPLBS (((CPLB_MEM / 4) + 16 + 1 + 1 + 1 \
++ + ASYNC_MEMORY_CPLB_COVERAGE) * 2)
++
++/*
++* Number of required instruction CPLB switchtable entries
++* MEMSIZE / 4 (we mostly install 4M page size CPLBs
++* approx 12 for smaller 1MB page size CPLBs for allignment purposes
++* 1 for L1 Instruction Memory
++* possibly 1 for L2 Instruction Memory
++* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
++*/
++#define MAX_SWITCH_I_CPLBS (((CPLB_MEM / 4) + 12 + 1 + 1 + 1) * 2)
++
++
+ u_long icplb_table[MAX_CPLBS + 1];
+ u_long dcplb_table[MAX_CPLBS + 1];
+
+@@ -295,6 +324,8 @@ void __init generate_cpl_tables(void)
+ struct cplb_tab *t_d = NULL;
+ struct s_cplb cplb;
+
++ printk(KERN_INFO "NOMPU: setting up cplb tables for global access\n");
++
+ cplb.init_i.size = MAX_CPLBS;
+ cplb.init_d.size = MAX_CPLBS;
+ cplb.switch_i.size = MAX_SWITCH_I_CPLBS;
+diff --git a/arch/blackfin/kernel/dma-mapping.c b/arch/blackfin/kernel/dma-mapping.c
+index d6b61d5..2f62a9f 100644
+--- a/arch/blackfin/kernel/dma-mapping.c
++++ b/arch/blackfin/kernel/dma-mapping.c
+@@ -59,7 +59,7 @@ void dma_alloc_init(unsigned long start, unsigned long end)
+ memset((void *)dma_base, 0, DMA_UNCACHED_REGION);
+ dma_initialized = 1;
+
+- printk(KERN_INFO "%s: dma_page @ 0x%p - %d pages at 0x%08lx\n", __FUNCTION__,
++ printk(KERN_INFO "%s: dma_page @ 0x%p - %d pages at 0x%08lx\n", __func__,
+ dma_page, dma_pages, dma_base);
+ }
+
+@@ -100,7 +100,7 @@ static void __free_dma_pages(unsigned long addr, unsigned int pages)
+ int i;
+
+ if ((page + pages) > dma_pages) {
+- printk(KERN_ERR "%s: freeing outside range.\n", __FUNCTION__);
++ printk(KERN_ERR "%s: freeing outside range.\n", __func__);
+ BUG();
+ }
+
+diff --git a/arch/blackfin/kernel/gptimers.c b/arch/blackfin/kernel/gptimers.c
+index 1904d8b..e698554 100644
+--- a/arch/blackfin/kernel/gptimers.c
++++ b/arch/blackfin/kernel/gptimers.c
+@@ -52,12 +52,14 @@ static volatile GPTIMER_timer_regs *const timer_regs[MAX_BLACKFIN_GPTIMERS] =
+ (GPTIMER_timer_regs *)TIMER5_CONFIG,
+ (GPTIMER_timer_regs *)TIMER6_CONFIG,
+ (GPTIMER_timer_regs *)TIMER7_CONFIG,
+-#endif
+-#if (MAX_BLACKFIN_GPTIMERS > 8)
++# if (MAX_BLACKFIN_GPTIMERS > 8)
+ (GPTIMER_timer_regs *)TIMER8_CONFIG,
+ (GPTIMER_timer_regs *)TIMER9_CONFIG,
+ (GPTIMER_timer_regs *)TIMER10_CONFIG,
++# if (MAX_BLACKFIN_GPTIMERS > 11)
+ (GPTIMER_timer_regs *)TIMER11_CONFIG,
++# endif
++# endif
+ #endif
+ };
+
+@@ -80,12 +82,14 @@ static uint32_t const trun_mask[MAX_BLACKFIN_GPTIMERS] =
+ TIMER_STATUS_TRUN5,
+ TIMER_STATUS_TRUN6,
+ TIMER_STATUS_TRUN7,
+-#endif
+-#if (MAX_BLACKFIN_GPTIMERS > 8)
++# if (MAX_BLACKFIN_GPTIMERS > 8)
+ TIMER_STATUS_TRUN8,
+ TIMER_STATUS_TRUN9,
+ TIMER_STATUS_TRUN10,
++# if (MAX_BLACKFIN_GPTIMERS > 11)
+ TIMER_STATUS_TRUN11,
++# endif
++# endif
+ #endif
+ };
+
+@@ -100,12 +104,14 @@ static uint32_t const tovf_mask[MAX_BLACKFIN_GPTIMERS] =
+ TIMER_STATUS_TOVF5,
+ TIMER_STATUS_TOVF6,
+ TIMER_STATUS_TOVF7,
+-#endif
+-#if (MAX_BLACKFIN_GPTIMERS > 8)
++# if (MAX_BLACKFIN_GPTIMERS > 8)
+ TIMER_STATUS_TOVF8,
+ TIMER_STATUS_TOVF9,
+ TIMER_STATUS_TOVF10,
++# if (MAX_BLACKFIN_GPTIMERS > 11)
+ TIMER_STATUS_TOVF11,
++# endif
++# endif
+ #endif
+ };
+
+@@ -120,12 +126,14 @@ static uint32_t const timil_mask[MAX_BLACKFIN_GPTIMERS] =
+ TIMER_STATUS_TIMIL5,
+ TIMER_STATUS_TIMIL6,
+ TIMER_STATUS_TIMIL7,
+-#endif
+-#if (MAX_BLACKFIN_GPTIMERS > 8)
++# if (MAX_BLACKFIN_GPTIMERS > 8)
+ TIMER_STATUS_TIMIL8,
+ TIMER_STATUS_TIMIL9,
+ TIMER_STATUS_TIMIL10,
++# if (MAX_BLACKFIN_GPTIMERS > 11)
+ TIMER_STATUS_TIMIL11,
++# endif
++# endif
+ #endif
+ };
+
+diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
+index 6b8459c..be9fdd0 100644
+--- a/arch/blackfin/kernel/process.c
++++ b/arch/blackfin/kernel/process.c
+@@ -32,6 +32,8 @@
+ #include <linux/unistd.h>
+ #include <linux/user.h>
+ #include <linux/uaccess.h>
++#include <linux/sched.h>
++#include <linux/tick.h>
+ #include <linux/fs.h>
+ #include <linux/err.h>
+
+@@ -69,33 +71,44 @@ EXPORT_SYMBOL(pm_power_off);
+ * The idle loop on BFIN
+ */
+ #ifdef CONFIG_IDLE_L1
+-void default_idle(void)__attribute__((l1_text));
++static void default_idle(void)__attribute__((l1_text));
+ void cpu_idle(void)__attribute__((l1_text));
+ #endif
+
+-void default_idle(void)
++/*
++ * This is our default idle handler. We need to disable
++ * interrupts here to ensure we don't miss a wakeup call.
++ */
++static void default_idle(void)
+ {
+- while (!need_resched()) {
+- local_irq_disable();
+- if (likely(!need_resched()))
+- idle_with_irq_disabled();
+- local_irq_enable();
+- }
+-}
++ local_irq_disable();
++ if (!need_resched())
++ idle_with_irq_disabled();
+
+-void (*idle)(void) = default_idle;
++ local_irq_enable();
++}
+
+ /*
+- * The idle thread. There's no useful work to be
+- * done, so just try to conserve power and have a
+- * low exit latency (ie sit in a loop waiting for
+- * somebody to say that they'd like to reschedule)
++ * The idle thread. We try to conserve power, while trying to keep
++ * overall latency low. The architecture specific idle is passed
++ * a value to indicate the level of "idleness" of the system.
+ */
+ void cpu_idle(void)
+ {
+ /* endless idle loop with no priority at all */
+ while (1) {
+- idle();
++ void (*idle)(void) = pm_idle;
++
++#ifdef CONFIG_HOTPLUG_CPU
++ if (cpu_is_offline(smp_processor_id()))
++ cpu_die();
++#endif
++ if (!idle)
++ idle = default_idle;
++ tick_nohz_stop_sched_tick();
++ while (!need_resched())
++ idle();
++ tick_nohz_restart_sched_tick();
+ preempt_enable_no_resched();
+ schedule();
+ preempt_disable();
+@@ -189,7 +202,7 @@ copy_thread(int nr, unsigned long clone_flags,
+ * sys_execve() executes a new program.
+ */
+
+-asmlinkage int sys_execve(char *name, char **argv, char **envp)
++asmlinkage int sys_execve(char __user *name, char __user * __user *argv, char __user * __user *envp)
+ {
+ int error;
+ char *filename;
+@@ -232,23 +245,25 @@ unsigned long get_wchan(struct task_struct *p)
+
+ void finish_atomic_sections (struct pt_regs *regs)
+ {
++ int __user *up0 = (int __user *)®s->p0;
++
+ if (regs->pc < ATOMIC_SEQS_START || regs->pc >= ATOMIC_SEQS_END)
+ return;
+
+ switch (regs->pc) {
+ case ATOMIC_XCHG32 + 2:
+- put_user(regs->r1, (int *)regs->p0);
++ put_user(regs->r1, up0);
+ regs->pc += 2;
+ break;
+
+ case ATOMIC_CAS32 + 2:
+ case ATOMIC_CAS32 + 4:
+ if (regs->r0 == regs->r1)
+- put_user(regs->r2, (int *)regs->p0);
++ put_user(regs->r2, up0);
+ regs->pc = ATOMIC_CAS32 + 8;
+ break;
+ case ATOMIC_CAS32 + 6:
+- put_user(regs->r2, (int *)regs->p0);
++ put_user(regs->r2, up0);
+ regs->pc += 2;
+ break;
+
+@@ -256,7 +271,7 @@ void finish_atomic_sections (struct pt_regs *regs)
+ regs->r0 = regs->r1 + regs->r0;
+ /* fall through */
+ case ATOMIC_ADD32 + 4:
+- put_user(regs->r0, (int *)regs->p0);
++ put_user(regs->r0, up0);
+ regs->pc = ATOMIC_ADD32 + 6;
+ break;
+
+@@ -264,7 +279,7 @@ void finish_atomic_sections (struct pt_regs *regs)
+ regs->r0 = regs->r1 - regs->r0;
+ /* fall through */
+ case ATOMIC_SUB32 + 4:
+- put_user(regs->r0, (int *)regs->p0);
++ put_user(regs->r0, up0);
+ regs->pc = ATOMIC_SUB32 + 6;
+ break;
+
+@@ -272,7 +287,7 @@ void finish_atomic_sections (struct pt_regs *regs)
+ regs->r0 = regs->r1 | regs->r0;
+ /* fall through */
+ case ATOMIC_IOR32 + 4:
+- put_user(regs->r0, (int *)regs->p0);
++ put_user(regs->r0, up0);
+ regs->pc = ATOMIC_IOR32 + 6;
+ break;
+
+@@ -280,7 +295,7 @@ void finish_atomic_sections (struct pt_regs *regs)
+ regs->r0 = regs->r1 & regs->r0;
+ /* fall through */
+ case ATOMIC_AND32 + 4:
+- put_user(regs->r0, (int *)regs->p0);
++ put_user(regs->r0, up0);
+ regs->pc = ATOMIC_AND32 + 6;
+ break;
+
+@@ -288,7 +303,7 @@ void finish_atomic_sections (struct pt_regs *regs)
+ regs->r0 = regs->r1 ^ regs->r0;
+ /* fall through */
+ case ATOMIC_XOR32 + 4:
+- put_user(regs->r0, (int *)regs->p0);
++ put_user(regs->r0, up0);
+ regs->pc = ATOMIC_XOR32 + 6;
+ break;
+ }
+@@ -309,6 +324,12 @@ int _access_ok(unsigned long addr, unsigned long size)
+ return 1;
+ if (addr >= memory_mtd_end && (addr + size) <= physical_mem_end)
+ return 1;
++
++#ifdef CONFIG_ROMFS_MTD_FS
++ /* For XIP, allow user space to use pointers within the ROMFS. */
++ if (addr >= memory_mtd_start && (addr + size) <= memory_mtd_end)
++ return 1;
++#endif
+ #else
+ if (addr >= memory_start && (addr + size) <= physical_mem_end)
+ return 1;
+diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c
+index 85caf9b..b4f062c 100644
+--- a/arch/blackfin/kernel/ptrace.c
++++ b/arch/blackfin/kernel/ptrace.c
+@@ -193,6 +193,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+ {
+ int ret;
+ int add = 0;
++ unsigned long __user *datap = (unsigned long __user *)data;
+
+ switch (request) {
+ /* when I and D space are separate, these will need to be fixed. */
+@@ -229,7 +230,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+ pr_debug("ptrace: copied size %d [0x%08lx]\n", copied, tmp);
+ if (copied != sizeof(tmp))
+ break;
+- ret = put_user(tmp, (unsigned long *)data);
++ ret = put_user(tmp, datap);
+ break;
+ }
+
+@@ -263,7 +264,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+ } else {
+ tmp = get_reg(child, addr);
+ }
+- ret = put_user(tmp, (unsigned long *)data);
++ ret = put_user(tmp, datap);
+ break;
+ }
+
+@@ -389,7 +390,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+ {
+
+ /* Get all gp regs from the child. */
+- ret = ptrace_getregs(child, (void __user *)data);
++ ret = ptrace_getregs(child, datap);
+ break;
+ }
+
+diff --git a/arch/blackfin/kernel/reboot.c b/arch/blackfin/kernel/reboot.c
+index 483f93d..367e2dc 100644
+--- a/arch/blackfin/kernel/reboot.c
++++ b/arch/blackfin/kernel/reboot.c
+@@ -11,45 +11,56 @@
+ #include <asm/reboot.h>
+ #include <asm/system.h>
+
+-#if defined(BF537_FAMILY) || defined(BF533_FAMILY) || defined(BF527_FAMILY)
+-#define SYSCR_VAL 0x0
+-#elif defined(BF561_FAMILY)
+-#define SYSCR_VAL 0x20
+-#elif defined(BF548_FAMILY)
+-#define SYSCR_VAL 0x10
+-#endif
+-
+-/*
+- * Delay min 5 SCLK cycles using worst case CCLK/SCLK ratio (15)
+- */
+-#define SWRST_DELAY (5 * 15)
+-
+-/* A system soft reset makes external memory unusable
+- * so force this function into L1.
++/* A system soft reset makes external memory unusable so force
++ * this function into L1. We use the compiler ssync here rather
++ * than SSYNC() because it's safe (no interrupts and such) and
++ * we save some L1. We do not need to force sanity in the SYSCR
++ * register as the BMODE selection bit is cleared by the soft
++ * reset while the Core B bit (on dual core parts) is cleared by
++ * the core reset.
+ */
+ __attribute__((l1_text))
+ void bfin_reset(void)
+ {
+- /* force BMODE and disable Core B (as needed) */
+- bfin_write_SYSCR(SYSCR_VAL);
+-
+- /* we use asm ssync here because it's save and we save some L1 */
+- asm("ssync;");
++ /* Wait for completion of "system" events such as cache line
++ * line fills so that we avoid infinite stalls later on as
++ * much as possible. This code is in L1, so it won't trigger
++ * any such event after this point in time.
++ */
++ __builtin_bfin_ssync();
+
+ while (1) {
+- /* initiate system soft reset with magic 0x7 */
++ /* Initiate System software reset. */
+ bfin_write_SWRST(0x7);
+
+- /* Wait for System reset to actually reset, needs to be 5 SCLKs, */
+- /* Assume CCLK / SCLK ratio is worst case (15), and use 5*15 */
+-
+- asm("LSETUP(.Lfoo,.Lfoo) LC0 = %0\n .Lfoo: NOP;\n"
+- : : "a" (SWRST_DELAY) : "LC0", "LT0", "LB0");
++ /* Due to the way reset is handled in the hardware, we need
++ * to delay for 7 SCLKS. The only reliable way to do this is
++ * to calculate the CCLK/SCLK ratio and multiply 7. For now,
++ * we'll assume worse case which is a 1:15 ratio.
++ */
++ asm(
++ "LSETUP (1f, 1f) LC0 = %0\n"
++ "1: nop;"
++ :
++ : "a" (15 * 7)
++ : "LC0", "LB0", "LT0"
++ );
+
+- /* clear system soft reset */
++ /* Clear System software reset */
+ bfin_write_SWRST(0);
+- asm("ssync;");
+- /* issue core reset */
++
++ /* Wait for the SWRST write to complete. Cannot rely on SSYNC
++ * though as the System state is all reset now.
++ */
++ asm(
++ "LSETUP (1f, 1f) LC1 = %0\n"
++ "1: nop;"
++ :
++ : "a" (15 * 1)
++ : "LC1", "LB1", "LT1"
++ );
++
++ /* Issue core reset */
+ asm("raise 1");
+ }
+ }
+diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c
+index 2255c28..8efea00 100644
+--- a/arch/blackfin/kernel/setup.c
++++ b/arch/blackfin/kernel/setup.c
+@@ -35,6 +35,7 @@ u16 _bfin_swrst;
+ EXPORT_SYMBOL(_bfin_swrst);
+
+ unsigned long memory_start, memory_end, physical_mem_end;
++unsigned long _rambase, _ramstart, _ramend;
+ unsigned long reserved_mem_dcache_on;
+ unsigned long reserved_mem_icache_on;
+ EXPORT_SYMBOL(memory_start);
+@@ -106,7 +107,7 @@ void __init bf53x_relocate_l1_mem(void)
+
+ l1_code_length = _etext_l1 - _stext_l1;
+ if (l1_code_length > L1_CODE_LENGTH)
+- l1_code_length = L1_CODE_LENGTH;
++ panic("L1 Instruction SRAM Overflow\n");
+ /* cannot complain as printk is not available as yet.
+ * But we can continue booting and complain later!
+ */
+@@ -116,19 +117,18 @@ void __init bf53x_relocate_l1_mem(void)
+
+ l1_data_a_length = _ebss_l1 - _sdata_l1;
+ if (l1_data_a_length > L1_DATA_A_LENGTH)
+- l1_data_a_length = L1_DATA_A_LENGTH;
++ panic("L1 Data SRAM Bank A Overflow\n");
+
+ /* Copy _sdata_l1 to _ebss_l1 to L1 data bank A SRAM */
+ dma_memcpy(_sdata_l1, _l1_lma_start + l1_code_length, l1_data_a_length);
+
+ l1_data_b_length = _ebss_b_l1 - _sdata_b_l1;
+ if (l1_data_b_length > L1_DATA_B_LENGTH)
+- l1_data_b_length = L1_DATA_B_LENGTH;
++ panic("L1 Data SRAM Bank B Overflow\n");
+
+ /* Copy _sdata_b_l1 to _ebss_b_l1 to L1 data bank B SRAM */
+ dma_memcpy(_sdata_b_l1, _l1_lma_start + l1_code_length +
+ l1_data_a_length, l1_data_b_length);
+-
+ }
+
+ /* add_memory_region to memmap */
+@@ -547,11 +547,38 @@ static __init void memory_setup(void)
+ );
+ }
+
++/*
++ * Find the lowest, highest page frame number we have available
++ */
++void __init find_min_max_pfn(void)
++{
++ int i;
++
++ max_pfn = 0;
++ min_low_pfn = memory_end;
++
++ for (i = 0; i < bfin_memmap.nr_map; i++) {
++ unsigned long start, end;
++ /* RAM? */
++ if (bfin_memmap.map[i].type != BFIN_MEMMAP_RAM)
++ continue;
++ start = PFN_UP(bfin_memmap.map[i].addr);
++ end = PFN_DOWN(bfin_memmap.map[i].addr +
++ bfin_memmap.map[i].size);
++ if (start >= end)
++ continue;
++ if (end > max_pfn)
++ max_pfn = end;
++ if (start < min_low_pfn)
++ min_low_pfn = start;
++ }
++}
++
+ static __init void setup_bootmem_allocator(void)
+ {
+ int bootmap_size;
+ int i;
+- unsigned long min_pfn, max_pfn;
++ unsigned long start_pfn, end_pfn;
+ unsigned long curr_pfn, last_pfn, size;
+
+ /* mark memory between memory_start and memory_end usable */
+@@ -561,8 +588,19 @@ static __init void setup_bootmem_allocator(void)
+ sanitize_memmap(bfin_memmap.map, &bfin_memmap.nr_map);
+ print_memory_map("boot memmap");
+
+- min_pfn = PAGE_OFFSET >> PAGE_SHIFT;
+- max_pfn = memory_end >> PAGE_SHIFT;
++ /* intialize globals in linux/bootmem.h */
++ find_min_max_pfn();
++ /* pfn of the last usable page frame */
++ if (max_pfn > memory_end >> PAGE_SHIFT)
++ max_pfn = memory_end >> PAGE_SHIFT;
++ /* pfn of last page frame directly mapped by kernel */
++ max_low_pfn = max_pfn;
++ /* pfn of the first usable page frame after kernel image*/
++ if (min_low_pfn < memory_start >> PAGE_SHIFT)
++ min_low_pfn = memory_start >> PAGE_SHIFT;
++
++ start_pfn = PAGE_OFFSET >> PAGE_SHIFT;
++ end_pfn = memory_end >> PAGE_SHIFT;
+
+ /*
+ * give all the memory to the bootmap allocator, tell it to put the
+@@ -570,7 +608,7 @@ static __init void setup_bootmem_allocator(void)
+ */
+ bootmap_size = init_bootmem_node(NODE_DATA(0),
+ memory_start >> PAGE_SHIFT, /* map goes here */
+- min_pfn, max_pfn);
++ start_pfn, end_pfn);
+
+ /* register the memmap regions with the bootmem allocator */
+ for (i = 0; i < bfin_memmap.nr_map; i++) {
+@@ -583,7 +621,7 @@ static __init void setup_bootmem_allocator(void)
+ * We are rounding up the start address of usable memory:
+ */
+ curr_pfn = PFN_UP(bfin_memmap.map[i].addr);
+- if (curr_pfn >= max_pfn)
++ if (curr_pfn >= end_pfn)
+ continue;
+ /*
+ * ... and at the end of the usable range downwards:
+@@ -591,8 +629,8 @@ static __init void setup_bootmem_allocator(void)
+ last_pfn = PFN_DOWN(bfin_memmap.map[i].addr +
+ bfin_memmap.map[i].size);
+
+- if (last_pfn > max_pfn)
+- last_pfn = max_pfn;
++ if (last_pfn > end_pfn)
++ last_pfn = end_pfn;
+
+ /*
+ * .. finally, did all the rounding and playing
+@@ -611,9 +649,59 @@ static __init void setup_bootmem_allocator(void)
+ BOOTMEM_DEFAULT);
+ }
+
++#define EBSZ_TO_MEG(ebsz) \
++({ \
++ int meg = 0; \
++ switch (ebsz & 0xf) { \
++ case 0x1: meg = 16; break; \
++ case 0x3: meg = 32; break; \
++ case 0x5: meg = 64; break; \
++ case 0x7: meg = 128; break; \
++ case 0x9: meg = 256; break; \
++ case 0xb: meg = 512; break; \
++ } \
++ meg; \
++})
++static inline int __init get_mem_size(void)
++{
++#ifdef CONFIG_MEM_SIZE
++ return CONFIG_MEM_SIZE;
++#else
++# if defined(EBIU_SDBCTL)
++# if defined(BF561_FAMILY)
++ int ret = 0;
++ u32 sdbctl = bfin_read_EBIU_SDBCTL();
++ ret += EBSZ_TO_MEG(sdbctl >> 0);
++ ret += EBSZ_TO_MEG(sdbctl >> 8);
++ ret += EBSZ_TO_MEG(sdbctl >> 16);
++ ret += EBSZ_TO_MEG(sdbctl >> 24);
++ return ret;
++# else
++ return EBSZ_TO_MEG(bfin_read_EBIU_SDBCTL());
++# endif
++# elif defined(EBIU_DDRCTL1)
++ u32 ddrctl = bfin_read_EBIU_DDRCTL1();
++ int ret = 0;
++ switch (ddrctl & 0xc0000) {
++ case DEVSZ_64: ret = 64 / 8;
++ case DEVSZ_128: ret = 128 / 8;
++ case DEVSZ_256: ret = 256 / 8;
++ case DEVSZ_512: ret = 512 / 8;
++ }
++ switch (ddrctl & 0x30000) {
++ case DEVWD_4: ret *= 2;
++ case DEVWD_8: ret *= 2;
++ case DEVWD_16: break;
++ }
++ return ret;
++# endif
++#endif
++ BUG();
++}
++
+ void __init setup_arch(char **cmdline_p)
+ {
+- unsigned long l1_length, sclk, cclk;
++ unsigned long sclk, cclk;
+
+ #ifdef CONFIG_DUMMY_CONSOLE
+ conswitchp = &dummy_con;
+@@ -631,7 +719,7 @@ void __init setup_arch(char **cmdline_p)
+
+ /* setup memory defaults from the user config */
+ physical_mem_end = 0;
+- _ramend = CONFIG_MEM_SIZE * 1024 * 1024;
++ _ramend = get_mem_size() * 1024 * 1024;
+
+ memset(&bfin_memmap, 0, sizeof(bfin_memmap));
+
+@@ -712,15 +800,6 @@ void __init setup_arch(char **cmdline_p)
+
+ paging_init();
+
+- /* check the size of the l1 area */
+- l1_length = _etext_l1 - _stext_l1;
+- if (l1_length > L1_CODE_LENGTH)
+- panic("L1 code memory overflow\n");
+-
+- l1_length = _ebss_l1 - _sdata_l1;
+- if (l1_length > L1_DATA_A_LENGTH)
+- panic("L1 data memory overflow\n");
+-
+ /* Copy atomic sequences to their fixed location, and sanity check that
+ these locations are the ones that we advertise to userspace. */
+ memcpy((void *)FIXED_CODE_START, &fixed_code_start,
+@@ -859,12 +938,17 @@ static int show_cpuinfo(struct seq_file *m, void *v)
+ seq_printf(m, "processor\t: %d\n"
+ "vendor_id\t: %s\n"
+ "cpu family\t: 0x%x\n"
+- "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK)\n"
++ "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n"
+ "stepping\t: %d\n",
+ 0,
+ vendor,
+ (bfin_read_CHIPID() & CHIPID_FAMILY),
+ cpu, cclk/1000000, sclk/1000000,
++#ifdef CONFIG_MPU
++ "mpu on",
++#else
++ "mpu off",
++#endif
+ revid);
+
+ seq_printf(m, "cpu MHz\t\t: %lu.%03lu/%lu.%03lu\n",
+@@ -973,7 +1057,6 @@ static int show_cpuinfo(struct seq_file *m, void *v)
+ seq_printf(m, "No Ways are locked\n");
+ }
+ #endif
+-
+ seq_printf(m, "board name\t: %s\n", bfin_board_name);
+ seq_printf(m, "board memory\t: %ld kB (0x%p -> 0x%p)\n",
+ physical_mem_end >> 10, (void *)0, (void *)physical_mem_end);
+diff --git a/arch/blackfin/kernel/signal.c b/arch/blackfin/kernel/signal.c
+index 5564c95..d1fa244 100644
+--- a/arch/blackfin/kernel/signal.c
++++ b/arch/blackfin/kernel/signal.c
+@@ -38,6 +38,7 @@
+
+ #include <asm/cacheflush.h>
+ #include <asm/ucontext.h>
++#include <asm/fixed_code.h>
+
+ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+@@ -50,18 +51,20 @@ struct rt_sigframe {
+ int sig;
+ struct siginfo *pinfo;
+ void *puc;
++ /* This is no longer needed by the kernel, but unfortunately userspace
++ * code expects it to be there. */
+ char retcode[8];
+ struct siginfo info;
+ struct ucontext uc;
+ };
+
+-asmlinkage int sys_sigaltstack(const stack_t * uss, stack_t * uoss)
++asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
+ {
+ return do_sigaltstack(uss, uoss, rdusp());
+ }
+
+ static inline int
+-rt_restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *pr0)
++rt_restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *pr0)
+ {
+ unsigned long usp = 0;
+ int err = 0;
+@@ -159,11 +162,6 @@ static inline int rt_setup_sigcontext(struct sigcontext *sc, struct pt_regs *reg
+ return err;
+ }
+
+-static inline void push_cache(unsigned long vaddr, unsigned int len)
+-{
+- flush_icache_range(vaddr, vaddr + len);
+-}
+-
+ static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+ size_t frame_size)
+ {
+@@ -209,19 +207,9 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
+ err |= rt_setup_sigcontext(&frame->uc.uc_mcontext, regs);
+ err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
+- /* Set up to return from userspace. */
+- err |= __put_user(0x28, &(frame->retcode[0]));
+- err |= __put_user(0xe1, &(frame->retcode[1]));
+- err |= __put_user(0xad, &(frame->retcode[2]));
+- err |= __put_user(0x00, &(frame->retcode[3]));
+- err |= __put_user(0xa0, &(frame->retcode[4]));
+- err |= __put_user(0x00, &(frame->retcode[5]));
+-
+ if (err)
+ goto give_sigsegv;
+
+- push_cache((unsigned long)&frame->retcode, sizeof(frame->retcode));
+-
+ /* Set up registers for signal handler */
+ wrusp((unsigned long)frame);
+ if (get_personality & FDPIC_FUNCPTRS) {
+@@ -231,7 +219,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
+ __get_user(regs->p3, &funcptr->GOT);
+ } else
+ regs->pc = (unsigned long)ka->sa.sa_handler;
+- regs->rets = (unsigned long)(frame->retcode);
++ regs->rets = SIGRETURN_STUB;
+
+ regs->r0 = frame->sig;
+ regs->r1 = (unsigned long)(&frame->info);
+diff --git a/arch/blackfin/kernel/sys_bfin.c b/arch/blackfin/kernel/sys_bfin.c
+index abcd148..efb7b25 100644
+--- a/arch/blackfin/kernel/sys_bfin.c
++++ b/arch/blackfin/kernel/sys_bfin.c
+@@ -49,7 +49,7 @@
+ * sys_pipe() is the normal C calling standard for creating
+ * a pipe. It's not the way unix traditionally does this, though.
+ */
+-asmlinkage int sys_pipe(unsigned long *fildes)
++asmlinkage int sys_pipe(unsigned long __user *fildes)
+ {
+ int fd[2];
+ int error;
+diff --git a/arch/blackfin/kernel/time-ts.c b/arch/blackfin/kernel/time-ts.c
+new file mode 100644
+index 0000000..4482c47
+--- /dev/null
++++ b/arch/blackfin/kernel/time-ts.c
+@@ -0,0 +1,219 @@
++/*
++ * linux/arch/kernel/time-ts.c
++ *
++ * Based on arm clockevents implementation and old bfin time tick.
++ *
++ * Copyright(C) 2008, GeoTechnologies, Vitja Makarov
++ *
++ * This code is licenced under the GPL version 2. For details see
++ * kernel-base/COPYING.
++ */
++#include <linux/module.h>
++#include <linux/profile.h>
++#include <linux/interrupt.h>
++#include <linux/time.h>
++#include <linux/timex.h>
++#include <linux/irq.h>
++#include <linux/clocksource.h>
++#include <linux/clockchips.h>
++#include <linux/cpufreq.h>
++
++#include <asm/blackfin.h>
++#include <asm/time.h>
++
++#ifdef CONFIG_CYCLES_CLOCKSOURCE
++
++/* Accelerators for sched_clock()
++ * convert from cycles(64bits) => nanoseconds (64bits)
++ * basic equation:
++ * ns = cycles / (freq / ns_per_sec)
++ * ns = cycles * (ns_per_sec / freq)
++ * ns = cycles * (10^9 / (cpu_khz * 10^3))
++ * ns = cycles * (10^6 / cpu_khz)
++ *
++ * Then we use scaling math (suggested by george at mvista.com) to get:
++ * ns = cycles * (10^6 * SC / cpu_khz) / SC
++ * ns = cycles * cyc2ns_scale / SC
++ *
++ * And since SC is a constant power of two, we can convert the div
++ * into a shift.
++ *
++ * We can use khz divisor instead of mhz to keep a better precision, since
++ * cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits.
++ * (mathieu.desnoyers at polymtl.ca)
++ *
++ * -johnstul at us.ibm.com "math is hard, lets go shopping!"
++ */
++
++static unsigned long cyc2ns_scale;
++#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
++
++static inline void set_cyc2ns_scale(unsigned long cpu_khz)
++{
++ cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR) / cpu_khz;
++}
++
++static inline unsigned long long cycles_2_ns(cycle_t cyc)
++{
++ return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
++}
++
++static cycle_t read_cycles(void)
++{
++ return get_cycles();
++}
++
++unsigned long long sched_clock(void)
++{
++ return cycles_2_ns(read_cycles());
++}
++
++static struct clocksource clocksource_bfin = {
++ .name = "bfin_cycles",
++ .rating = 350,
++ .read = read_cycles,
++ .mask = CLOCKSOURCE_MASK(64),
++ .shift = 22,
++ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
++};
++
++static int __init bfin_clocksource_init(void)
++{
++ set_cyc2ns_scale(get_cclk() / 1000);
++
++ clocksource_bfin.mult = clocksource_hz2mult(get_cclk(), clocksource_bfin.shift);
++
++ if (clocksource_register(&clocksource_bfin))
++ panic("failed to register clocksource");
++
++ return 0;
++}
++
++#else
++# define bfin_clocksource_init()
++#endif
++
++static int bfin_timer_set_next_event(unsigned long cycles,
++ struct clock_event_device *evt)
++{
++ bfin_write_TCOUNT(cycles);
++ CSYNC();
++ return 0;
++}
++
++static void bfin_timer_set_mode(enum clock_event_mode mode,
++ struct clock_event_device *evt)
++{
++ switch (mode) {
++ case CLOCK_EVT_MODE_PERIODIC: {
++ unsigned long tcount = ((get_cclk() / (HZ * TIME_SCALE)) - 1);
++ bfin_write_TCNTL(TMPWR);
++ bfin_write_TSCALE(TIME_SCALE - 1);
++ CSYNC();
++ bfin_write_TPERIOD(tcount);
++ bfin_write_TCOUNT(tcount);
++ bfin_write_TCNTL(TMPWR | TMREN | TAUTORLD);
++ CSYNC();
++ break;
++ }
++ case CLOCK_EVT_MODE_ONESHOT:
++ bfin_write_TSCALE(0);
++ bfin_write_TCOUNT(0);
++ bfin_write_TCNTL(TMPWR | TMREN);
++ CSYNC();
++ break;
++ case CLOCK_EVT_MODE_UNUSED:
++ case CLOCK_EVT_MODE_SHUTDOWN:
++ bfin_write_TCNTL(0);
++ CSYNC();
++ break;
++ case CLOCK_EVT_MODE_RESUME:
++ break;
++ }
++}
++
++static void __init bfin_timer_init(void)
++{
++ /* power up the timer, but don't enable it just yet */
++ bfin_write_TCNTL(TMPWR);
++ CSYNC();
++
++ /*
++ * the TSCALE prescaler counter.
++ */
++ bfin_write_TSCALE(TIME_SCALE - 1);
++ bfin_write_TPERIOD(0);
++ bfin_write_TCOUNT(0);
++
++ /* now enable the timer */
++ CSYNC();
++}
++
++/*
++ * timer_interrupt() needs to keep up the real-time clock,
++ * as well as call the "do_timer()" routine every clocktick
++ */
++#ifdef CONFIG_CORE_TIMER_IRQ_L1
++__attribute__((l1_text))
++#endif
++irqreturn_t timer_interrupt(int irq, void *dev_id);
++
++static struct clock_event_device clockevent_bfin = {
++ .name = "bfin_core_timer",
++ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
++ .shift = 32,
++ .cpumask = CPU_MASK_CPU0,
++ .set_next_event = bfin_timer_set_next_event,
++ .set_mode = bfin_timer_set_mode,
++};
++
++static struct irqaction bfin_timer_irq = {
++ .name = "Blackfin Core Timer",
++ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
++ .handler = timer_interrupt,
++ .dev_id = &clockevent_bfin,
++};
++
++irqreturn_t timer_interrupt(int irq, void *dev_id)
++{
++ struct clock_event_device *evt = dev_id;
++ evt->event_handler(evt);
++ return IRQ_HANDLED;
++}
++
++static int __init bfin_clockevent_init(void)
++{
++ setup_irq(IRQ_CORETMR, &bfin_timer_irq);
++ bfin_timer_init();
++
++ clockevent_bfin.mult = div_sc(get_cclk(), NSEC_PER_SEC, clockevent_bfin.shift);
++ clockevent_bfin.max_delta_ns = clockevent_delta2ns(-1, &clockevent_bfin);
++ clockevent_bfin.min_delta_ns = clockevent_delta2ns(100, &clockevent_bfin);
++ clockevents_register_device(&clockevent_bfin);
++
++ return 0;
++}
++
++void __init time_init(void)
++{
++ time_t secs_since_1970 = (365 * 37 + 9) * 24 * 60 * 60; /* 1 Jan 2007 */
++
++#ifdef CONFIG_RTC_DRV_BFIN
++ /* [#2663] hack to filter junk RTC values that would cause
++ * userspace to have to deal with time values greater than
++ * 2^31 seconds (which uClibc cannot cope with yet)
++ */
++ if ((bfin_read_RTC_STAT() & 0xC0000000) == 0xC0000000) {
++ printk(KERN_NOTICE "bfin-rtc: invalid date; resetting\n");
++ bfin_write_RTC_STAT(0);
++ }
++#endif
++
++ /* Initialize xtime. From now on, xtime is updated with timer interrupts */
++ xtime.tv_sec = secs_since_1970;
++ xtime.tv_nsec = 0;
++ set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec);
++
++ bfin_clocksource_init();
++ bfin_clockevent_init();
++}
+diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c
+index 9bdc8f9..eb23523 100644
+--- a/arch/blackfin/kernel/time.c
++++ b/arch/blackfin/kernel/time.c
+@@ -6,9 +6,10 @@
+ * Created:
+ * Description: This file contains the bfin-specific time handling details.
+ * Most of the stuff is located in the machine specific files.
++ * FIXME: (This file is subject for removal)
+ *
+ * Modified:
+- * Copyright 2004-2006 Analog Devices Inc.
++ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+@@ -35,12 +36,12 @@
+ #include <linux/irq.h>
+
+ #include <asm/blackfin.h>
++#include <asm/time.h>
+
+ /* This is an NTP setting */
+ #define TICK_SIZE (tick_nsec / 1000)
+
+-static void time_sched_init(irqreturn_t(*timer_routine)
+- (int, void *));
++static void time_sched_init(irq_handler_t timer_routine);
+ static unsigned long gettimeoffset(void);
+
+ static struct irqaction bfin_timer_irq = {
+@@ -48,23 +49,8 @@ static struct irqaction bfin_timer_irq = {
+ .flags = IRQF_DISABLED
+ };
+
+-/*
+- * The way that the Blackfin core timer works is:
+- * - CCLK is divided by a programmable 8-bit pre-scaler (TSCALE)
+- * - Every time TSCALE ticks, a 32bit is counted down (TCOUNT)
+- *
+- * If you take the fastest clock (1ns, or 1GHz to make the math work easier)
+- * 10ms is 10,000,000 clock ticks, which fits easy into a 32-bit counter
+- * (32 bit counter is 4,294,967,296ns or 4.2 seconds) so, we don't need
+- * to use TSCALE, and program it to zero (which is pass CCLK through).
+- * If you feel like using it, try to keep HZ * TIMESCALE to some
+- * value that divides easy (like power of 2).
+- */
+-
+-#define TIME_SCALE 1
+-
+ static void
+-time_sched_init(irqreturn_t(*timer_routine) (int, void *))
++time_sched_init(irq_handler_t timer_routine)
+ {
+ u32 tcount;
+
+diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
+index 56a67ab..5b84707 100644
+--- a/arch/blackfin/kernel/traps.c
++++ b/arch/blackfin/kernel/traps.c
+@@ -67,6 +67,8 @@ void __init trap_init(void)
+ CSYNC();
+ }
+
++void *saved_icplb_fault_addr, *saved_dcplb_fault_addr;
++
+ int kstack_depth_to_print = 48;
+
+ static void decode_address(char *buf, unsigned long address)
+@@ -75,7 +77,7 @@ static void decode_address(char *buf, unsigned long address)
+ struct task_struct *p;
+ struct mm_struct *mm;
+ unsigned long flags, offset;
+- unsigned int in_exception = bfin_read_IPEND() & 0x10;
++ unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic();
+
+ #ifdef CONFIG_KALLSYMS
+ unsigned long symsize;
+@@ -117,7 +119,7 @@ static void decode_address(char *buf, unsigned long address)
+ */
+ write_lock_irqsave(&tasklist_lock, flags);
+ for_each_process(p) {
+- mm = (in_exception ? p->mm : get_task_mm(p));
++ mm = (in_atomic ? p->mm : get_task_mm(p));
+ if (!mm)
+ continue;
+
+@@ -137,23 +139,36 @@ static void decode_address(char *buf, unsigned long address)
+ /* FLAT does not have its text aligned to the start of
+ * the map while FDPIC ELF does ...
+ */
+- if (current->mm &&
+- (address > current->mm->start_code) &&
+- (address < current->mm->end_code))
+- offset = address - current->mm->start_code;
+- else
+- offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);
+-
+- sprintf(buf, "<0x%p> [ %s + 0x%lx ]",
+- (void *)address, name, offset);
+- if (!in_exception)
++
++ /* before we can check flat/fdpic, we need to
++ * make sure current is valid
++ */
++ if ((unsigned long)current >= FIXED_CODE_START &&
++ !((unsigned long)current & 0x3)) {
++ if (current->mm &&
++ (address > current->mm->start_code) &&
++ (address < current->mm->end_code))
++ offset = address - current->mm->start_code;
++ else
++ offset = (address - vma->vm_start) +
++ (vma->vm_pgoff << PAGE_SHIFT);
++
++ sprintf(buf, "<0x%p> [ %s + 0x%lx ]",
++ (void *)address, name, offset);
++ } else
++ sprintf(buf, "<0x%p> [ %s vma:0x%lx-0x%lx]",
++ (void *)address, name,
++ vma->vm_start, vma->vm_end);
++
++ if (!in_atomic)
+ mmput(mm);
++
+ goto done;
+ }
+
+ vml = vml->next;
+ }
+- if (!in_exception)
++ if (!in_atomic)
+ mmput(mm);
+ }
+
+@@ -506,7 +521,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
+
+ info.si_signo = sig;
+ info.si_errno = 0;
+- info.si_addr = (void *)fp->pc;
++ info.si_addr = (void __user *)fp->pc;
+ force_sig_info(sig, &info, current);
+
+ trace_buffer_restore(j);
+@@ -655,21 +670,31 @@ void dump_bfin_process(struct pt_regs *fp)
+ else if (context & 0x8000)
+ printk(KERN_NOTICE "Kernel process context\n");
+
+- if (current->pid && current->mm) {
++ /* Because we are crashing, and pointers could be bad, we check things
++ * pretty closely before we use them
++ */
++ if ((unsigned long)current >= FIXED_CODE_START &&
++ !((unsigned long)current & 0x3) && current->pid) {
+ printk(KERN_NOTICE "CURRENT PROCESS:\n");
+- printk(KERN_NOTICE "COMM=%s PID=%d\n",
+- current->comm, current->pid);
+-
+- printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n"
+- KERN_NOTICE "BSS = 0x%p-0x%p USER-STACK = 0x%p\n"
+- KERN_NOTICE "\n",
+- (void *)current->mm->start_code,
+- (void *)current->mm->end_code,
+- (void *)current->mm->start_data,
+- (void *)current->mm->end_data,
+- (void *)current->mm->end_data,
+- (void *)current->mm->brk,
+- (void *)current->mm->start_stack);
++ if (current->comm >= (char *)FIXED_CODE_START)
++ printk(KERN_NOTICE "COMM=%s PID=%d\n",
++ current->comm, current->pid);
++ else
++ printk(KERN_NOTICE "COMM= invalid\n");
++
++ if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START)
++ printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n"
++ KERN_NOTICE " BSS = 0x%p-0x%p USER-STACK = 0x%p\n"
++ KERN_NOTICE "\n",
++ (void *)current->mm->start_code,
++ (void *)current->mm->end_code,
++ (void *)current->mm->start_data,
++ (void *)current->mm->end_data,
++ (void *)current->mm->end_data,
++ (void *)current->mm->brk,
++ (void *)current->mm->start_stack);
++ else
++ printk(KERN_NOTICE "invalid mm\n");
+ } else
+ printk(KERN_NOTICE "\n" KERN_NOTICE
+ "No Valid process in current context\n");
+@@ -680,10 +705,7 @@ void dump_bfin_mem(struct pt_regs *fp)
+ unsigned short *addr, *erraddr, val = 0, err = 0;
+ char sti = 0, buf[6];
+
+- if (unlikely((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR))
+- erraddr = (void *)fp->pc;
+- else
+- erraddr = (void *)fp->retx;
++ erraddr = (void *)fp->pc;
+
+ printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr);
+
+@@ -807,9 +829,9 @@ unlock:
+
+ if (((long)fp->seqstat & SEQSTAT_EXCAUSE) &&
+ (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) {
+- decode_address(buf, bfin_read_DCPLB_FAULT_ADDR());
++ decode_address(buf, saved_dcplb_fault_addr);
+ printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf);
+- decode_address(buf, bfin_read_ICPLB_FAULT_ADDR());
++ decode_address(buf, saved_icplb_fault_addr);
+ printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf);
+ }
+
+@@ -917,8 +939,8 @@ void panic_cplb_error(int cplb_panic, struct pt_regs *fp)
+
+ oops_in_progress = 1;
+
+- printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void *)bfin_read_DCPLB_FAULT_ADDR());
+- printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void *)bfin_read_ICPLB_FAULT_ADDR());
++ printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", saved_dcplb_fault_addr);
++ printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", saved_icplb_fault_addr);
+ dump_bfin_process(fp);
+ dump_bfin_mem(fp);
+ show_regs(fp);
+diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
+index cb01a9d..3ecc64c 100644
+--- a/arch/blackfin/kernel/vmlinux.lds.S
++++ b/arch/blackfin/kernel/vmlinux.lds.S
+@@ -56,6 +56,10 @@ SECTIONS
+ *(.text.*)
+ *(.fixup)
+
++#if !L1_CODE_LENGTH
++ *(.l1.text)
++#endif
++
+ . = ALIGN(16);
+ ___start___ex_table = .;
+ *(__ex_table)
+@@ -73,6 +77,12 @@ SECTIONS
+ ___bss_start = .;
+ *(.bss .bss.*)
+ *(COMMON)
++#if !L1_DATA_A_LENGTH
++ *(.l1.bss)
++#endif
++#if !L1_DATA_B_LENGTH
++ *(.l1.bss.B)
++#endif
+ ___bss_stop = .;
+ }
+
+@@ -83,6 +93,15 @@ SECTIONS
+ . = ALIGN(32);
+ *(.data.cacheline_aligned)
+
++#if !L1_DATA_A_LENGTH
++ . = ALIGN(32);
++ *(.data_l1.cacheline_aligned)
++ *(.l1.data)
++#endif
++#if !L1_DATA_B_LENGTH
++ *(.l1.data.B)
++#endif
++
+ DATA_DATA
+ *(.data.*)
+ CONSTRUCTORS
+@@ -147,64 +166,43 @@ SECTIONS
+
+ __l1_lma_start = .;
+
+-#if L1_CODE_LENGTH
+-# define LDS_L1_CODE *(.l1.text)
+-#else
+-# define LDS_L1_CODE
+-#endif
+ .text_l1 L1_CODE_START : AT(LOADADDR(.init.ramfs) + SIZEOF(.init.ramfs))
+ {
+ . = ALIGN(4);
+ __stext_l1 = .;
+- LDS_L1_CODE
++ *(.l1.text)
+ . = ALIGN(4);
+ __etext_l1 = .;
+ }
+
+-#if L1_DATA_A_LENGTH
+-# define LDS_L1_A_DATA *(.l1.data)
+-# define LDS_L1_A_BSS *(.l1.bss)
+-# define LDS_L1_A_CACHE *(.data_l1.cacheline_aligned)
+-#else
+-# define LDS_L1_A_DATA
+-# define LDS_L1_A_BSS
+-# define LDS_L1_A_CACHE
+-#endif
+ .data_l1 L1_DATA_A_START : AT(LOADADDR(.text_l1) + SIZEOF(.text_l1))
+ {
+ . = ALIGN(4);
+ __sdata_l1 = .;
+- LDS_L1_A_DATA
++ *(.l1.data)
+ __edata_l1 = .;
+
+ . = ALIGN(4);
+ __sbss_l1 = .;
+- LDS_L1_A_BSS
++ *(.l1.bss)
+
+ . = ALIGN(32);
+- LDS_L1_A_CACHE
++ *(.data_l1.cacheline_aligned)
+
+ . = ALIGN(4);
+ __ebss_l1 = .;
+ }
+
+-#if L1_DATA_B_LENGTH
+-# define LDS_L1_B_DATA *(.l1.data.B)
+-# define LDS_L1_B_BSS *(.l1.bss.B)
+-#else
+-# define LDS_L1_B_DATA
+-# define LDS_L1_B_BSS
+-#endif
+ .data_b_l1 L1_DATA_B_START : AT(LOADADDR(.data_l1) + SIZEOF(.data_l1))
+ {
+ . = ALIGN(4);
+ __sdata_b_l1 = .;
+- LDS_L1_B_DATA
++ *(.l1.data.B)
+ __edata_b_l1 = .;
+
+ . = ALIGN(4);
+ __sbss_b_l1 = .;
+- LDS_L1_B_BSS
++ *(.l1.bss.B)
+
+ . = ALIGN(4);
+ __ebss_b_l1 = .;
+@@ -223,8 +221,6 @@ SECTIONS
+
+ DWARF_DEBUG
+
+- NOTES
+-
+ /DISCARD/ :
+ {
+ EXIT_TEXT
+diff --git a/arch/blackfin/mach-bf527/Makefile b/arch/blackfin/mach-bf527/Makefile
+index 9f99f5d..4eddb58 100644
+--- a/arch/blackfin/mach-bf527/Makefile
++++ b/arch/blackfin/mach-bf527/Makefile
+@@ -5,5 +5,3 @@
+ extra-y := head.o
+
+ obj-y := ints-priority.o dma.o
+-
+-obj-$(CONFIG_CPU_FREQ) += cpu.o
+diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c
+index cf4bc0d..583d538 100644
+--- a/arch/blackfin/mach-bf527/boards/ezkit.c
++++ b/arch/blackfin/mach-bf527/boards/ezkit.c
+@@ -94,7 +94,7 @@ int __init bfin_isp1761_init(void)
+ {
+ unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
+
+- printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++ printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
+
+ return platform_add_devices(bfin_isp1761_devices, num_devices);
+@@ -416,7 +416,7 @@ static struct platform_device net2272_bfin_device = {
+ static struct mtd_partition bfin_spi_flash_partitions[] = {
+ {
+ .name = "bootloader",
+- .size = 0x00020000,
++ .size = 0x00040000,
+ .offset = 0,
+ .mask_flags = MTD_CAP_ROM
+ }, {
+@@ -707,6 +707,32 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++ {
++ .start = 0xFFC00400,
++ .end = 0xFFC004FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++#ifdef CONFIG_BFIN_SIR1
++ {
++ .start = 0xFFC02000,
++ .end = 0xFFC020FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++ .name = "bfin_sir",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(bfin_sir_resources),
++ .resource = bfin_sir_resources,
++};
++#endif
++
+ #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+ static struct resource bfin_twi0_resource[] = {
+ [0] = {
+@@ -874,6 +900,10 @@ static struct platform_device *stamp_devices[] __initdata = {
+ &bfin_uart_device,
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++ &bfin_sir_device,
++#endif
++
+ #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+ &i2c_bfin_twi_device,
+ #endif
+@@ -896,7 +926,7 @@ static struct platform_device *stamp_devices[] __initdata = {
+
+ static int __init stamp_init(void)
+ {
+- printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++ printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ spi_register_board_info(bfin_spi_board_info,
+diff --git a/arch/blackfin/mach-bf527/cpu.c b/arch/blackfin/mach-bf527/cpu.c
+deleted file mode 100644
+index 1975402..0000000
+--- a/arch/blackfin/mach-bf527/cpu.c
++++ /dev/null
+@@ -1,161 +0,0 @@
+-/*
+- * File: arch/blackfin/mach-bf527/cpu.c
+- * Based on: arch/blackfin/mach-bf537/cpu.c
+- * Author: michael.kang at analog.com
+- *
+- * Created:
+- * Description: clock scaling for the bf527
+- *
+- * Modified:
+- * Copyright 2004-2007 Analog Devices Inc.
+- *
+- * Bugs: Enter bugs at http://blackfin.uclinux.org/
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (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, see the file COPYING, or write
+- * to the Free Software Foundation, Inc.,
+- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/types.h>
+-#include <linux/init.h>
+-#include <linux/cpufreq.h>
+-#include <asm/dpmc.h>
+-#include <linux/fs.h>
+-#include <asm/bfin-global.h>
+-
+-/* CONFIG_CLKIN_HZ=11059200 */
+-#define VCO5 (CONFIG_CLKIN_HZ*45) /*497664000 */
+-#define VCO4 (CONFIG_CLKIN_HZ*36) /*398131200 */
+-#define VCO3 (CONFIG_CLKIN_HZ*27) /*298598400 */
+-#define VCO2 (CONFIG_CLKIN_HZ*18) /*199065600 */
+-#define VCO1 (CONFIG_CLKIN_HZ*9) /*99532800 */
+-#define VCO(x) VCO##x
+-
+-#define MFREQ(x) {VCO(x), VCO(x)/4}, {VCO(x), VCO(x)/2}, {VCO(x), VCO(x)}
+-/* frequency */
+-static struct cpufreq_frequency_table bf527_freq_table[] = {
+- MFREQ(1),
+- MFREQ(3),
+- {VCO4, VCO4 / 2}, {VCO4, VCO4},
+- MFREQ(5),
+- {0, CPUFREQ_TABLE_END},
+-};
+-
+-/*
+- * dpmc_fops->ioctl()
+- * static int dpmc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+- */
+-static int bf527_getfreq(unsigned int cpu)
+-{
+- unsigned long cclk_mhz;
+-
+- /* The driver only support single cpu */
+- if (cpu == 0)
+- dpmc_fops.ioctl(NULL, NULL, IOCTL_GET_CORECLOCK, &cclk_mhz);
+- else
+- cclk_mhz = -1;
+-
+- return cclk_mhz;
+-}
+-
+-static int bf527_target(struct cpufreq_policy *policy,
+- unsigned int target_freq, unsigned int relation)
+-{
+- unsigned long cclk_mhz;
+- unsigned long vco_mhz;
+- unsigned long flags;
+- unsigned int index;
+- struct cpufreq_freqs freqs;
+-
+- if (cpufreq_frequency_table_target
+- (policy, bf527_freq_table, target_freq, relation, &index))
+- return -EINVAL;
+-
+- cclk_mhz = bf527_freq_table[index].frequency;
+- vco_mhz = bf527_freq_table[index].index;
+-
+- dpmc_fops.ioctl(NULL, NULL, IOCTL_CHANGE_FREQUENCY, &vco_mhz);
+- freqs.old = bf527_getfreq(0);
+- freqs.new = cclk_mhz;
+- freqs.cpu = 0;
+-
+- pr_debug
+- ("cclk begin change to cclk %d,vco=%d,index=%d,target=%d,oldfreq=%d\n",
+- cclk_mhz, vco_mhz, index, target_freq, freqs.old);
+-
+- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+- local_irq_save(flags);
+- dpmc_fops.ioctl(NULL, NULL, IOCTL_SET_CCLK, &cclk_mhz);
+- local_irq_restore(flags);
+- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+-
+- vco_mhz = get_vco();
+- cclk_mhz = get_cclk();
+- return 0;
+-}
+-
+-/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
+- * this platform, anyway.
+- */
+-static int bf527_verify_speed(struct cpufreq_policy *policy)
+-{
+- return cpufreq_frequency_table_verify(policy, &bf527_freq_table);
+-}
+-
+-static int __init __bf527_cpu_init(struct cpufreq_policy *policy)
+-{
+- if (policy->cpu != 0)
+- return -EINVAL;
+-
+- policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+-
+- policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+- /*Now ,only support one cpu */
+- policy->cur = bf527_getfreq(0);
+- cpufreq_frequency_table_get_attr(bf527_freq_table, policy->cpu);
+- return cpufreq_frequency_table_cpuinfo(policy, bf527_freq_table);
+-}
+-
+-static struct freq_attr *bf527_freq_attr[] = {
+- &cpufreq_freq_attr_scaling_available_freqs,
+- NULL,
+-};
+-
+-static struct cpufreq_driver bf527_driver = {
+- .verify = bf527_verify_speed,
+- .target = bf527_target,
+- .get = bf527_getfreq,
+- .init = __bf527_cpu_init,
+- .name = "bf527",
+- .owner = THIS_MODULE,
+- .attr = bf527_freq_attr,
+-};
+-
+-static int __init bf527_cpu_init(void)
+-{
+- return cpufreq_register_driver(&bf527_driver);
+-}
+-
+-static void __exit bf527_cpu_exit(void)
+-{
+- cpufreq_unregister_driver(&bf527_driver);
+-}
+-
+-MODULE_AUTHOR("Mickael Kang");
+-MODULE_DESCRIPTION("cpufreq driver for bf527 CPU");
+-MODULE_LICENSE("GPL");
+-
+-module_init(bf527_cpu_init);
+-module_exit(bf527_cpu_exit);
+diff --git a/arch/blackfin/mach-bf527/dma.c b/arch/blackfin/mach-bf527/dma.c
+index 522de24..dfd080c 100644
+--- a/arch/blackfin/mach-bf527/dma.c
++++ b/arch/blackfin/mach-bf527/dma.c
+@@ -26,10 +26,12 @@
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
++#include <linux/module.h>
++
+ #include <asm/blackfin.h>
+ #include <asm/dma.h>
+
+-struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
++struct dma_register *dma_io_base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ (struct dma_register *) DMA0_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_NEXT_DESC_PTR,
+@@ -47,6 +49,7 @@ struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ (struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
+ };
++EXPORT_SYMBOL(dma_io_base_addr);
+
+ int channel2irq(unsigned int channel)
+ {
+diff --git a/arch/blackfin/mach-bf527/head.S b/arch/blackfin/mach-bf527/head.S
+index cdb00a0..57bdb3b 100644
+--- a/arch/blackfin/mach-bf527/head.S
++++ b/arch/blackfin/mach-bf527/head.S
+@@ -37,9 +37,6 @@
+ #include <asm/mach/mem_init.h>
+ #endif
+
+-.global __rambase
+-.global __ramstart
+-.global __ramend
+ .extern ___bss_stop
+ .extern ___bss_start
+ .extern _bf53x_relocate_l1_mem
+@@ -439,18 +436,3 @@ ENTRY(_start_dma_code)
+ RTS;
+ ENDPROC(_start_dma_code)
+ #endif /* CONFIG_BFIN_KERNEL_CLOCK */
+-
+-.data
+-
+-/*
+- * Set up the usable of RAM stuff. Size of RAM is determined then
+- * an initial stack set up at the end.
+- */
+-
+-.align 4
+-__rambase:
+-.long 0
+-__ramstart:
+-.long 0
+-__ramend:
+-.long 0
+diff --git a/arch/blackfin/mach-bf533/Makefile b/arch/blackfin/mach-bf533/Makefile
+index 8cce173..aa9f264 100644
+--- a/arch/blackfin/mach-bf533/Makefile
++++ b/arch/blackfin/mach-bf533/Makefile
+@@ -5,5 +5,3 @@
+ extra-y := head.o
+
+ obj-y := ints-priority.o dma.o
+-
+-obj-$(CONFIG_CPU_FREQ) += cpu.o
+diff --git a/arch/blackfin/mach-bf533/boards/H8606.c b/arch/blackfin/mach-bf533/boards/H8606.c
+index 97378b0..7cc4864 100644
+--- a/arch/blackfin/mach-bf533/boards/H8606.c
++++ b/arch/blackfin/mach-bf533/boards/H8606.c
+@@ -304,6 +304,25 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++ {
++ .start = 0xFFC00400,
++ .end = 0xFFC004FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++ .name = "bfin_sir",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(bfin_sir_resources),
++ .resource = bfin_sir_resources,
++};
++#endif
++
+ #if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
+
+ #include <linux/serial_8250.h>
+@@ -403,6 +422,10 @@ static struct platform_device *h8606_devices[] __initdata = {
+ &serial8250_device,
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++ &bfin_sir_device,
++#endif
++
+ #if defined(CONFIG_KEYBOARD_OPENCORES) || defined(CONFIG_KEYBOARD_OPENCORES_MODULE)
+ &opencores_kbd_device,
+ #endif
+@@ -411,7 +434,7 @@ static struct platform_device *h8606_devices[] __initdata = {
+ static int __init H8606_init(void)
+ {
+ printk(KERN_INFO "HV Sistemas H8606 board support by http://www.hvsistemas.com\n");
+- printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++ printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ platform_add_devices(h8606_devices, ARRAY_SIZE(h8606_devices));
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+diff --git a/arch/blackfin/mach-bf533/boards/Kconfig b/arch/blackfin/mach-bf533/boards/Kconfig
+index 751de51..8400592 100644
+--- a/arch/blackfin/mach-bf533/boards/Kconfig
++++ b/arch/blackfin/mach-bf533/boards/Kconfig
+@@ -26,6 +26,12 @@ config H8606_HVSISTEMAS
+ help
+ HV Sistemas H8606 board support.
+
++config BFIN532_IP0X
++ bool "IP04/IP08 IP-PBX"
++ depends on (BF532)
++ help
++ Core support for IP04/IP04 open hardware IP-PBX.
++
+ config GENERIC_BF533_BOARD
+ bool "Generic"
+ help
+diff --git a/arch/blackfin/mach-bf533/boards/Makefile b/arch/blackfin/mach-bf533/boards/Makefile
+index 54f57fb..b7a1a1d 100644
+--- a/arch/blackfin/mach-bf533/boards/Makefile
++++ b/arch/blackfin/mach-bf533/boards/Makefile
+@@ -4,6 +4,7 @@
+
+ obj-$(CONFIG_GENERIC_BF533_BOARD) += generic_board.o
+ obj-$(CONFIG_BFIN533_STAMP) += stamp.o
++obj-$(CONFIG_BFIN532_IP0X) += ip0x.o
+ obj-$(CONFIG_BFIN533_EZKIT) += ezkit.o
+ obj-$(CONFIG_BFIN533_BLUETECHNIX_CM) += cm_bf533.o
+ obj-$(CONFIG_H8606_HVSISTEMAS) += H8606.o
+diff --git a/arch/blackfin/mach-bf533/boards/cm_bf533.c b/arch/blackfin/mach-bf533/boards/cm_bf533.c
+index 886f260..a03149c 100644
+--- a/arch/blackfin/mach-bf533/boards/cm_bf533.c
++++ b/arch/blackfin/mach-bf533/boards/cm_bf533.c
+@@ -234,6 +234,25 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++ {
++ .start = 0xFFC00400,
++ .end = 0xFFC004FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++ .name = "bfin_sir",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(bfin_sir_resources),
++ .resource = bfin_sir_resources,
++};
++#endif
++
+ #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+ static struct platform_device bfin_sport0_uart_device = {
+ .name = "bfin-sport-uart",
+@@ -327,6 +346,10 @@ static struct platform_device *cm_bf533_devices[] __initdata = {
+ &bfin_uart_device,
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++ &bfin_sir_device,
++#endif
++
+ #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+ &bfin_sport0_uart_device,
+ &bfin_sport1_uart_device,
+@@ -355,7 +378,7 @@ static struct platform_device *cm_bf533_devices[] __initdata = {
+
+ static int __init cm_bf533_init(void)
+ {
+- printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++ printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ platform_add_devices(cm_bf533_devices, ARRAY_SIZE(cm_bf533_devices));
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+diff --git a/arch/blackfin/mach-bf533/boards/ezkit.c b/arch/blackfin/mach-bf533/boards/ezkit.c
+index 241b5a2..08a7943 100644
+--- a/arch/blackfin/mach-bf533/boards/ezkit.c
++++ b/arch/blackfin/mach-bf533/boards/ezkit.c
+@@ -237,6 +237,25 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++ {
++ .start = 0xFFC00400,
++ .end = 0xFFC004FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++ .name = "bfin_sir",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(bfin_sir_resources),
++ .resource = bfin_sir_resources,
++};
++#endif
++
+ #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
+ #define PATA_INT 55
+
+@@ -352,6 +371,10 @@ static struct platform_device *ezkit_devices[] __initdata = {
+ &bfin_uart_device,
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++ &bfin_sir_device,
++#endif
++
+ #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
+ &bfin_pata_device,
+ #endif
+@@ -369,7 +392,7 @@ static struct platform_device *ezkit_devices[] __initdata = {
+
+ static int __init ezkit_init(void)
+ {
+- printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++ printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ platform_add_devices(ezkit_devices, ARRAY_SIZE(ezkit_devices));
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+diff --git a/arch/blackfin/mach-bf533/boards/generic_board.c b/arch/blackfin/mach-bf533/boards/generic_board.c
+index e359a0d..82b1f6a 100644
+--- a/arch/blackfin/mach-bf533/boards/generic_board.c
++++ b/arch/blackfin/mach-bf533/boards/generic_board.c
+@@ -84,7 +84,7 @@ static struct platform_device *generic_board_devices[] __initdata = {
+
+ static int __init generic_board_init(void)
+ {
+- printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++ printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ return platform_add_devices(generic_board_devices, ARRAY_SIZE(generic_board_devices));
+ }
+
+diff --git a/arch/blackfin/mach-bf533/boards/ip0x.c b/arch/blackfin/mach-bf533/boards/ip0x.c
+new file mode 100644
+index 0000000..5864892
+--- /dev/null
++++ b/arch/blackfin/mach-bf533/boards/ip0x.c
+@@ -0,0 +1,303 @@
++/*
++ * File: arch/blackfin/mach-bf533/ip0x.c
++ * Based on: arch/blackfin/mach-bf533/bf1.c
++ * Based on: arch/blackfin/mach-bf533/stamp.c
++ * Author: Ivan Danov <idanov at gmail.com>
++ * Modified for IP0X David Rowe
++ *
++ * Created: 2007
++ * Description: Board info file for the IP04/IP08 boards, which
++ * are derived from the BlackfinOne V2.0 boards.
++ *
++ * Modified:
++ * COpyright 2007 David Rowe
++ * Copyright 2006 Intratrade Ltd.
++ * Copyright 2005 National ICT Australia (NICTA)
++ * Copyright 2004-2006 Analog Devices Inc.
++ *
++ * 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, see the file COPYING, or write
++ * to the Free Software Foundation, Inc.,
++ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#include <linux/spi/spi.h>
++#include <linux/spi/flash.h>
++#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
++#include <linux/usb/isp1362.h>
++#endif
++#include <asm/irq.h>
++#include <asm/bfin5xx_spi.h>
++
++/*
++ * Name the Board for the /proc/cpuinfo
++ */
++const char bfin_board_name[] = "IP04/IP08";
++
++/*
++ * Driver needs to know address, irq and flag pin.
++ */
++#if defined(CONFIG_BFIN532_IP0X)
++#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
++
++#include <linux/dm9000.h>
++
++static struct resource dm9000_resource1[] = {
++ {
++ .start = 0x20100000,
++ .end = 0x20100000 + 1,
++ .flags = IORESOURCE_MEM
++ },{
++ .start = 0x20100000 + 2,
++ .end = 0x20100000 + 3,
++ .flags = IORESOURCE_MEM
++ },{
++ .start = IRQ_PF15,
++ .end = IRQ_PF15,
++ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE
++ }
++};
++
++static struct resource dm9000_resource2[] = {
++ {
++ .start = 0x20200000,
++ .end = 0x20200000 + 1,
++ .flags = IORESOURCE_MEM
++ },{
++ .start = 0x20200000 + 2,
++ .end = 0x20200000 + 3,
++ .flags = IORESOURCE_MEM
++ },{
++ .start = IRQ_PF14,
++ .end = IRQ_PF14,
++ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE
++ }
++};
++
++/*
++* for the moment we limit ourselves to 16bit IO until some
++* better IO routines can be written and tested
++*/
++static struct dm9000_plat_data dm9000_platdata1 = {
++ .flags = DM9000_PLATF_16BITONLY,
++};
++
++static struct platform_device dm9000_device1 = {
++ .name = "dm9000",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(dm9000_resource1),
++ .resource = dm9000_resource1,
++ .dev = {
++ .platform_data = &dm9000_platdata1,
++ }
++};
++
++static struct dm9000_plat_data dm9000_platdata2 = {
++ .flags = DM9000_PLATF_16BITONLY,
++};
++
++static struct platform_device dm9000_device2 = {
++ .name = "dm9000",
++ .id = 1,
++ .num_resources = ARRAY_SIZE(dm9000_resource2),
++ .resource = dm9000_resource2,
++ .dev = {
++ .platform_data = &dm9000_platdata2,
++ }
++};
++
++#endif
++#endif
++
++
++#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
++/* all SPI peripherals info goes here */
++
++#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
++static struct bfin5xx_spi_chip spi_mmc_chip_info = {
++/*
++ * CPOL (Clock Polarity)
++ * 0 - Active high SCK
++ * 1 - Active low SCK
++ * CPHA (Clock Phase) Selects transfer format and operation mode
++ * 0 - SCLK toggles from middle of the first data bit, slave select
++ * pins controlled by hardware.
++ * 1 - SCLK toggles from beginning of first data bit, slave select
++ * pins controller by user software.
++ * .ctl_reg = 0x1c00, * CPOL=1,CPHA=1,Sandisk 1G work
++ * NO NO .ctl_reg = 0x1800, * CPOL=1,CPHA=0
++ * NO NO .ctl_reg = 0x1400, * CPOL=0,CPHA=1
++ */
++ .ctl_reg = 0x1000, /* CPOL=0,CPHA=0,Sandisk 1G work */
++ .enable_dma = 0, /* if 1 - block!!! */
++ .bits_per_word = 8,
++ .cs_change_per_word = 0,
++};
++#endif
++
++/* Notice: for blackfin, the speed_hz is the value of register
++ * SPI_BAUD, not the real baudrate */
++static struct spi_board_info bfin_spi_board_info[] __initdata = {
++#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
++ {
++ .modalias = "spi_mmc",
++ .max_speed_hz = 2,
++ .bus_num = 1,
++ .chip_select = CONFIG_SPI_MMC_CS_CHAN,
++ .platform_data = NULL,
++ .controller_data = &spi_mmc_chip_info,
++ },
++#endif
++};
++
++/* SPI controller data */
++static struct bfin5xx_spi_master spi_bfin_master_info = {
++ .num_chipselect = 8,
++ .enable_dma = 1, /* master has the ability to do dma transfer */
++};
++
++static struct platform_device spi_bfin_master_device = {
++ .name = "bfin-spi-master",
++ .id = 1, /* Bus number */
++ .dev = {
++ .platform_data = &spi_bfin_master_info, /* Passed to driver */
++ },
++};
++#endif /* spi master and devices */
++
++#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
++static struct resource bfin_uart_resources[] = {
++ {
++ .start = 0xFFC00400,
++ .end = 0xFFC004FF,
++ .flags = IORESOURCE_MEM,
++ },
++};
++
++static struct platform_device bfin_uart_device = {
++ .name = "bfin-uart",
++ .id = 1,
++ .num_resources = ARRAY_SIZE(bfin_uart_resources),
++ .resource = bfin_uart_resources,
++};
++#endif
++
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++ {
++ .start = 0xFFC00400,
++ .end = 0xFFC004FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++ .name = "bfin_sir",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(bfin_sir_resources),
++ .resource = bfin_sir_resources,
++};
++#endif
++
++#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
++static struct resource isp1362_hcd_resources[] = {
++ {
++ .start = 0x20300000,
++ .end = 0x20300000 + 1,
++ .flags = IORESOURCE_MEM,
++ },{
++ .start = 0x20300000 + 2,
++ .end = 0x20300000 + 3,
++ .flags = IORESOURCE_MEM,
++ },{
++ .start = IRQ_PF11,
++ .end = IRQ_PF11,
++ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
++ },
++};
++
++static struct isp1362_platform_data isp1362_priv = {
++ .sel15Kres = 1,
++ .clknotstop = 0,
++ .oc_enable = 0, /* external OC */
++ .int_act_high = 0,
++ .int_edge_triggered = 0,
++ .remote_wakeup_connected = 0,
++ .no_power_switching = 1,
++ .power_switching_mode = 0,
++};
++
++static struct platform_device isp1362_hcd_device = {
++ .name = "isp1362-hcd",
++ .id = 0,
++ .dev = {
++ .platform_data = &isp1362_priv,
++ },
++ .num_resources = ARRAY_SIZE(isp1362_hcd_resources),
++ .resource = isp1362_hcd_resources,
++};
++#endif
++
++
++static struct platform_device *ip0x_devices[] __initdata = {
++#if defined(CONFIG_BFIN532_IP0X)
++#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
++ &dm9000_device1,
++ &dm9000_device2,
++#endif
++#endif
++
++#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
++ &spi_bfin_master_device,
++#endif
++
++#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
++ &bfin_uart_device,
++#endif
++
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++ &bfin_sir_device,
++#endif
++
++#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
++ &isp1362_hcd_device,
++#endif
++};
++
++static int __init ip0x_init(void)
++{
++ int i;
++
++ printk(KERN_INFO "%s(): registering device resources\n", __func__);
++ platform_add_devices(ip0x_devices, ARRAY_SIZE(ip0x_devices));
++
++#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
++ for (i = 0; i < ARRAY_SIZE(bfin_spi_board_info); ++i) {
++ int j = 1 << bfin_spi_board_info[i].chip_select;
++ /* set spi cs to 1 */
++ bfin_write_FIO_DIR(bfin_read_FIO_DIR() | j);
++ bfin_write_FIO_FLAG_S(j);
++ }
++ spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
++#endif
++
++ return 0;
++}
++
++arch_initcall(ip0x_init);
+diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c
+index b2ac481..fddce32 100644
+--- a/arch/blackfin/mach-bf533/boards/stamp.c
++++ b/arch/blackfin/mach-bf533/boards/stamp.c
+@@ -40,6 +40,7 @@
+ #endif
+ #include <linux/ata_platform.h>
+ #include <linux/irq.h>
++#include <linux/i2c.h>
+ #include <asm/dma.h>
+ #include <asm/bfin5xx_spi.h>
+ #include <asm/reboot.h>
+@@ -109,6 +110,7 @@ static struct platform_device net2272_bfin_device = {
+ };
+ #endif
+
++#if defined(CONFIG_MTD_BF5xx) || defined(CONFIG_MTD_BF5xx_MODULE)
+ static struct mtd_partition stamp_partitions[] = {
+ {
+ .name = "Bootloader",
+@@ -152,6 +154,7 @@ static struct platform_device stamp_flash_device = {
+ .num_resources = ARRAY_SIZE(stamp_flash_resource),
+ .resource = stamp_flash_resource,
+ };
++#endif
+
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ /* all SPI peripherals info goes here */
+@@ -367,6 +370,25 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++ {
++ .start = 0xFFC00400,
++ .end = 0xFFC004FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++ .name = "bfin_sir",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(bfin_sir_resources),
++ .resource = bfin_sir_resources,
++};
++#endif
++
+ #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+ static struct platform_device bfin_sport0_uart_device = {
+ .name = "bfin-sport-uart",
+@@ -472,6 +494,31 @@ static struct platform_device i2c_gpio_device = {
+ };
+ #endif
+
++#ifdef CONFIG_I2C_BOARDINFO
++static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
++#if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE)
++ {
++ I2C_BOARD_INFO("ad7142_joystick", 0x2C),
++ .type = "ad7142_joystick",
++ .irq = 39,
++ },
++#endif
++#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
++ {
++ I2C_BOARD_INFO("pcf8574_lcd", 0x22),
++ .type = "pcf8574_lcd",
++ },
++#endif
++#if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
++ {
++ I2C_BOARD_INFO("pcf8574_keypad", 0x27),
++ .type = "pcf8574_keypad",
++ .irq = 39,
++ },
++#endif
++};
++#endif
++
+ static struct platform_device *stamp_devices[] __initdata = {
+ #if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+ &rtc_device,
+@@ -497,6 +544,10 @@ static struct platform_device *stamp_devices[] __initdata = {
+ &bfin_uart_device,
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++ &bfin_sir_device,
++#endif
++
+ #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+ &bfin_sport0_uart_device,
+ &bfin_sport1_uart_device,
+@@ -515,14 +566,23 @@ static struct platform_device *stamp_devices[] __initdata = {
+ #endif
+
+ &bfin_gpios_device,
++
++#if defined(CONFIG_MTD_BF5xx) || defined(CONFIG_MTD_BF5xx_MODULE)
+ &stamp_flash_device,
++#endif
+ };
+
+ static int __init stamp_init(void)
+ {
+ int ret;
+
+- printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++ printk(KERN_INFO "%s(): registering device resources\n", __func__);
++
++#ifdef CONFIG_I2C_BOARDINFO
++ i2c_register_board_info(0, bfin_i2c_board_info,
++ ARRAY_SIZE(bfin_i2c_board_info));
++#endif
++
+ ret = platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
+ if (ret < 0)
+ return ret;
+diff --git a/arch/blackfin/mach-bf533/cpu.c b/arch/blackfin/mach-bf533/cpu.c
+deleted file mode 100644
+index b7a0e0f..0000000
+--- a/arch/blackfin/mach-bf533/cpu.c
++++ /dev/null
+@@ -1,158 +0,0 @@
+-/*
+- * File: arch/blackfin/mach-bf533/cpu.c
+- * Based on:
+- * Author: michael.kang at analog.com
+- *
+- * Created:
+- * Description: clock scaling for the bf533
+- *
+- * Modified:
+- * Copyright 2004-2006 Analog Devices Inc.
+- *
+- * Bugs: Enter bugs at http://blackfin.uclinux.org/
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (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, see the file COPYING, or write
+- * to the Free Software Foundation, Inc.,
+- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/types.h>
+-#include <linux/init.h>
+-#include <linux/cpufreq.h>
+-#include <asm/dpmc.h>
+-#include <linux/fs.h>
+-#include <asm/bfin-global.h>
+-
+-/* CONFIG_CLKIN_HZ=11059200 */
+-#define VCO5 (CONFIG_CLKIN_HZ*45) /*497664000 */
+-#define VCO4 (CONFIG_CLKIN_HZ*36) /*398131200 */
+-#define VCO3 (CONFIG_CLKIN_HZ*27) /*298598400 */
+-#define VCO2 (CONFIG_CLKIN_HZ*18) /*199065600 */
+-#define VCO1 (CONFIG_CLKIN_HZ*9) /*99532800 */
+-#define VCO(x) VCO##x
+-
+-#define FREQ(x) {VCO(x),VCO(x)/4},{VCO(x),VCO(x)/2},{VCO(x),VCO(x)}
+-/* frequency */
+-static struct cpufreq_frequency_table bf533_freq_table[] = {
+- FREQ(1),
+- FREQ(3),
+- {VCO4, VCO4 / 2}, {VCO4, VCO4},
+- FREQ(5),
+- {0, CPUFREQ_TABLE_END},
+-};
+-
+-/*
+- * dpmc_fops->ioctl()
+- * static int dpmc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+- */
+-static int bf533_getfreq(unsigned int cpu)
+-{
+- unsigned long cclk_mhz, vco_mhz;
+-
+- /* The driver only support single cpu */
+- if (cpu == 0)
+- dpmc_fops.ioctl(NULL, NULL, IOCTL_GET_CORECLOCK, &cclk_mhz);
+- else
+- cclk_mhz = -1;
+- return cclk_mhz;
+-}
+-
+-static int bf533_target(struct cpufreq_policy *policy,
+- unsigned int target_freq, unsigned int relation)
+-{
+- unsigned long cclk_mhz;
+- unsigned long vco_mhz;
+- unsigned long flags;
+- unsigned int index, vco_index;
+- int i;
+-
+- struct cpufreq_freqs freqs;
+- if (cpufreq_frequency_table_target(policy, bf533_freq_table, target_freq, relation, &index))
+- return -EINVAL;
+- cclk_mhz = bf533_freq_table[index].frequency;
+- vco_mhz = bf533_freq_table[index].index;
+-
+- dpmc_fops.ioctl(NULL, NULL, IOCTL_CHANGE_FREQUENCY, &vco_mhz);
+- freqs.old = bf533_getfreq(0);
+- freqs.new = cclk_mhz;
+- freqs.cpu = 0;
+-
+- pr_debug("cclk begin change to cclk %d,vco=%d,index=%d,target=%d,oldfreq=%d\n",
+- cclk_mhz, vco_mhz, index, target_freq, freqs.old);
+-
+- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+- local_irq_save(flags);
+- dpmc_fops.ioctl(NULL, NULL, IOCTL_SET_CCLK, &cclk_mhz);
+- local_irq_restore(flags);
+- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+-
+- vco_mhz = get_vco();
+- cclk_mhz = get_cclk();
+- return 0;
+-}
+-
+-/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
+- * this platform, anyway.
+- */
+-static int bf533_verify_speed(struct cpufreq_policy *policy)
+-{
+- return cpufreq_frequency_table_verify(policy, &bf533_freq_table);
+-}
+-
+-static int __init __bf533_cpu_init(struct cpufreq_policy *policy)
+-{
+- int result;
+-
+- if (policy->cpu != 0)
+- return -EINVAL;
+-
+- policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+- /*Now ,only support one cpu */
+- policy->cur = bf533_getfreq(0);
+- cpufreq_frequency_table_get_attr(bf533_freq_table, policy->cpu);
+- return cpufreq_frequency_table_cpuinfo(policy, bf533_freq_table);
+-}
+-
+-static struct freq_attr *bf533_freq_attr[] = {
+- &cpufreq_freq_attr_scaling_available_freqs,
+- NULL,
+-};
+-
+-static struct cpufreq_driver bf533_driver = {
+- .verify = bf533_verify_speed,
+- .target = bf533_target,
+- .get = bf533_getfreq,
+- .init = __bf533_cpu_init,
+- .name = "bf533",
+- .owner = THIS_MODULE,
+- .attr = bf533_freq_attr,
+-};
+-
+-static int __init bf533_cpu_init(void)
+-{
+- return cpufreq_register_driver(&bf533_driver);
+-}
+-
+-static void __exit bf533_cpu_exit(void)
+-{
+- cpufreq_unregister_driver(&bf533_driver);
+-}
+-
+-MODULE_AUTHOR("Mickael Kang");
+-MODULE_DESCRIPTION("cpufreq driver for BF533 CPU");
+-MODULE_LICENSE("GPL");
+-
+-module_init(bf533_cpu_init);
+-module_exit(bf533_cpu_exit);
+diff --git a/arch/blackfin/mach-bf533/dma.c b/arch/blackfin/mach-bf533/dma.c
+index 6c909cf..28655c1 100644
+--- a/arch/blackfin/mach-bf533/dma.c
++++ b/arch/blackfin/mach-bf533/dma.c
+@@ -26,10 +26,12 @@
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
++#include <linux/module.h>
++
+ #include <asm/blackfin.h>
+ #include <asm/dma.h>
+
+-struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
++struct dma_register *dma_io_base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ (struct dma_register *) DMA0_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_NEXT_DESC_PTR,
+@@ -43,6 +45,7 @@ struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ (struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
+ };
++EXPORT_SYMBOL(dma_io_base_addr);
+
+ int channel2irq(unsigned int channel)
+ {
+diff --git a/arch/blackfin/mach-bf533/head.S b/arch/blackfin/mach-bf533/head.S
+index 1ded945..1295dea 100644
+--- a/arch/blackfin/mach-bf533/head.S
++++ b/arch/blackfin/mach-bf533/head.S
+@@ -36,9 +36,6 @@
+ #include <asm/mach/mem_init.h>
+ #endif
+
+-.global __rambase
+-.global __ramstart
+-.global __ramend
+ .extern ___bss_stop
+ .extern ___bss_start
+ .extern _bf53x_relocate_l1_mem
+@@ -151,26 +148,26 @@ ENTRY(__start)
+
+ /* Initialise UART - when booting from u-boot, the UART is not disabled
+ * so if we dont initalize here, our serial console gets hosed */
+- p0.h = hi(UART_LCR);
+- p0.l = lo(UART_LCR);
++ p0.h = hi(BFIN_UART_LCR);
++ p0.l = lo(BFIN_UART_LCR);
+ r0 = 0x0(Z);
+ w[p0] = r0.L; /* To enable DLL writes */
+ ssync;
+
+- p0.h = hi(UART_DLL);
+- p0.l = lo(UART_DLL);
++ p0.h = hi(BFIN_UART_DLL);
++ p0.l = lo(BFIN_UART_DLL);
+ r0 = 0x0(Z);
+ w[p0] = r0.L;
+ ssync;
+
+- p0.h = hi(UART_DLH);
+- p0.l = lo(UART_DLH);
++ p0.h = hi(BFIN_UART_DLH);
++ p0.l = lo(BFIN_UART_DLH);
+ r0 = 0x00(Z);
+ w[p0] = r0.L;
+ ssync;
+
+- p0.h = hi(UART_GCTL);
+- p0.l = lo(UART_GCTL);
++ p0.h = hi(BFIN_UART_GCTL);
++ p0.l = lo(BFIN_UART_GCTL);
+ r0 = 0x0(Z);
+ w[p0] = r0.L; /* To enable UART clock */
+ ssync;
+@@ -431,18 +428,3 @@ ENTRY(_start_dma_code)
+ RTS;
+ ENDPROC(_start_dma_code)
+ #endif /* CONFIG_BFIN_KERNEL_CLOCK */
+-
+-.data
+-
+-/*
+- * Set up the usable of RAM stuff. Size of RAM is determined then
+- * an initial stack set up at the end.
+- */
+-
+-.align 4
+-__rambase:
+-.long 0
+-__ramstart:
+-.long 0
+-__ramend:
+-.long 0
+diff --git a/arch/blackfin/mach-bf537/Makefile b/arch/blackfin/mach-bf537/Makefile
+index 7e7c9c8..68e5478 100644
+--- a/arch/blackfin/mach-bf537/Makefile
++++ b/arch/blackfin/mach-bf537/Makefile
+@@ -5,5 +5,3 @@
+ extra-y := head.o
+
+ obj-y := ints-priority.o dma.o
+-
+-obj-$(CONFIG_CPU_FREQ) += cpu.o
+diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537.c b/arch/blackfin/mach-bf537/boards/cm_bf537.c
+index f7c1f96..d8a23cd 100644
+--- a/arch/blackfin/mach-bf537/boards/cm_bf537.c
++++ b/arch/blackfin/mach-bf537/boards/cm_bf537.c
+@@ -325,6 +325,54 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++ {
++ .start = 0xFFC00400,
++ .end = 0xFFC004FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++#ifdef CONFIG_BFIN_SIR1
++ {
++ .start = 0xFFC02000,
++ .end = 0xFFC020FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++ .name = "bfin_sir",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(bfin_sir_resources),
++ .resource = bfin_sir_resources,
++};
++#endif
++
++#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
++static struct resource bfin_twi0_resource[] = {
++ [0] = {
++ .start = TWI0_REGBASE,
++ .end = TWI0_REGBASE,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_TWI,
++ .end = IRQ_TWI,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device i2c_bfin_twi_device = {
++ .name = "i2c-bfin-twi",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(bfin_twi0_resource),
++ .resource = bfin_twi0_resource,
++};
++#endif
++
+ #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+ static struct platform_device bfin_sport0_uart_device = {
+ .name = "bfin-sport-uart",
+@@ -393,6 +441,14 @@ static struct platform_device *cm_bf537_devices[] __initdata = {
+ &bfin_uart_device,
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++ &bfin_sir_device,
++#endif
++
++#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
++ &i2c_bfin_twi_device,
++#endif
++
+ #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+ &bfin_sport0_uart_device,
+ &bfin_sport1_uart_device,
+@@ -425,7 +481,7 @@ static struct platform_device *cm_bf537_devices[] __initdata = {
+
+ static int __init cm_bf537_init(void)
+ {
+- printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++ printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ platform_add_devices(cm_bf537_devices, ARRAY_SIZE(cm_bf537_devices));
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+diff --git a/arch/blackfin/mach-bf537/boards/generic_board.c b/arch/blackfin/mach-bf537/boards/generic_board.c
+index c95395b..7d25082 100644
+--- a/arch/blackfin/mach-bf537/boards/generic_board.c
++++ b/arch/blackfin/mach-bf537/boards/generic_board.c
+@@ -90,7 +90,7 @@ int __init bfin_isp1761_init(void)
+ {
+ unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
+
+- printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++ printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
+
+ return platform_add_devices(bfin_isp1761_devices, num_devices);
+@@ -554,6 +554,32 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++ {
++ .start = 0xFFC00400,
++ .end = 0xFFC004FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++#ifdef CONFIG_BFIN_SIR1
++ {
++ .start = 0xFFC02000,
++ .end = 0xFFC020FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++ .name = "bfin_sir",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(bfin_sir_resources),
++ .resource = bfin_sir_resources,
++};
++#endif
++
+ #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+ static struct resource bfin_twi0_resource[] = {
+ [0] = {
+@@ -674,6 +700,10 @@ static struct platform_device *stamp_devices[] __initdata = {
+ &bfin_uart_device,
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++ &bfin_sir_device,
++#endif
++
+ #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+ &i2c_bfin_twi_device,
+ #endif
+@@ -690,7 +720,7 @@ static struct platform_device *stamp_devices[] __initdata = {
+
+ static int __init stamp_init(void)
+ {
+- printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++ printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ spi_register_board_info(bfin_spi_board_info,
+diff --git a/arch/blackfin/mach-bf537/boards/minotaur.c b/arch/blackfin/mach-bf537/boards/minotaur.c
+index d71e0be..18ddf7a 100644
+--- a/arch/blackfin/mach-bf537/boards/minotaur.c
++++ b/arch/blackfin/mach-bf537/boards/minotaur.c
+@@ -8,12 +8,12 @@
+ #include <linux/spi/spi.h>
+ #include <linux/spi/flash.h>
+ #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+-#include <linux/usb_isp1362.h>
++#include <linux/usb/isp1362.h>
+ #endif
+ #include <linux/ata_platform.h>
+ #include <linux/irq.h>
+ #include <linux/interrupt.h>
+-#include <linux/usb_sl811.h>
++#include <linux/usb/sl811.h>
+ #include <asm/dma.h>
+ #include <asm/bfin5xx_spi.h>
+ #include <asm/reboot.h>
+@@ -225,6 +225,32 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++ {
++ .start = 0xFFC00400,
++ .end = 0xFFC004FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++#ifdef CONFIG_BFIN_SIR1
++ {
++ .start = 0xFFC02000,
++ .end = 0xFFC020FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++ .name = "bfin_sir",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(bfin_sir_resources),
++ .resource = bfin_sir_resources,
++};
++#endif
++
+ #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+ static struct resource bfin_twi0_resource[] = {
+ [0] = {
+@@ -284,6 +310,10 @@ static struct platform_device *minotaur_devices[] __initdata = {
+ &bfin_uart_device,
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++ &bfin_sir_device,
++#endif
++
+ #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+ &i2c_bfin_twi_device,
+ #endif
+@@ -297,7 +327,7 @@ static struct platform_device *minotaur_devices[] __initdata = {
+
+ static int __init minotaur_init(void)
+ {
+- printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++ printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ platform_add_devices(minotaur_devices, ARRAY_SIZE(minotaur_devices));
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ spi_register_board_info(bfin_spi_board_info,
+diff --git a/arch/blackfin/mach-bf537/boards/pnav10.c b/arch/blackfin/mach-bf537/boards/pnav10.c
+index 509a8a2..51c3bab 100644
+--- a/arch/blackfin/mach-bf537/boards/pnav10.c
++++ b/arch/blackfin/mach-bf537/boards/pnav10.c
+@@ -452,6 +452,31 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++ {
++ .start = 0xFFC00400,
++ .end = 0xFFC004FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++#ifdef CONFIG_BFIN_SIR1
++ {
++ .start = 0xFFC02000,
++ .end = 0xFFC020FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++ .name = "bfin_sir",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(bfin_sir_resources),
++ .resource = bfin_sir_resources,
++};
++#endif
+
+ static struct platform_device *stamp_devices[] __initdata = {
+ #if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE)
+@@ -493,11 +518,15 @@ static struct platform_device *stamp_devices[] __initdata = {
+ #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+ &bfin_uart_device,
+ #endif
++
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++ &bfin_sir_device,
++#endif
+ };
+
+ static int __init stamp_init(void)
+ {
+- printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++ printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ spi_register_board_info(bfin_spi_board_info,
+diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
+index ea83148..0cec14b 100644
+--- a/arch/blackfin/mach-bf537/boards/stamp.c
++++ b/arch/blackfin/mach-bf537/boards/stamp.c
+@@ -41,6 +41,7 @@
+ #include <linux/ata_platform.h>
+ #include <linux/irq.h>
+ #include <linux/interrupt.h>
++#include <linux/i2c.h>
+ #include <linux/usb/sl811.h>
+ #include <asm/dma.h>
+ #include <asm/bfin5xx_spi.h>
+@@ -90,7 +91,7 @@ int __init bfin_isp1761_init(void)
+ {
+ unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
+
+- printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++ printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
+
+ return platform_add_devices(bfin_isp1761_devices, num_devices);
+@@ -353,6 +354,7 @@ static struct platform_device net2272_bfin_device = {
+ };
+ #endif
+
++#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+ static struct mtd_partition stamp_partitions[] = {
+ {
+ .name = "Bootloader",
+@@ -395,6 +397,7 @@ static struct platform_device stamp_flash_device = {
+ .num_resources = 1,
+ .resource = &stamp_flash_resource,
+ };
++#endif
+
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ /* all SPI peripherals info goes here */
+@@ -500,6 +503,15 @@ static struct bfin5xx_spi_chip spidev_chip_info = {
+ };
+ #endif
+
++#if defined(CONFIG_MTD_DATAFLASH) \
++ || defined(CONFIG_MTD_DATAFLASH_MODULE)
++/* DataFlash chip */
++static struct bfin5xx_spi_chip data_flash_chip_info = {
++ .enable_dma = 0, /* use dma transfer with this chip*/
++ .bits_per_word = 8,
++};
++#endif
++
+ static struct spi_board_info bfin_spi_board_info[] __initdata = {
+ #if defined(CONFIG_MTD_M25P80) \
+ || defined(CONFIG_MTD_M25P80_MODULE)
+@@ -514,7 +526,17 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
+ .mode = SPI_MODE_3,
+ },
+ #endif
+-
++#if defined(CONFIG_MTD_DATAFLASH) \
++ || defined(CONFIG_MTD_DATAFLASH_MODULE)
++ { /* DataFlash chip */
++ .modalias = "mtd_dataflash",
++ .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
++ .bus_num = 0, /* Framework bus number */
++ .chip_select = 1, /* Framework chip select. On STAMP537 it is SPISSEL1*/
++ .controller_data = &data_flash_chip_info,
++ .mode = SPI_MODE_3,
++ },
++#endif
+ #if defined(CONFIG_SPI_ADC_BF533) \
+ || defined(CONFIG_SPI_ADC_BF533_MODULE)
+ {
+@@ -676,6 +698,32 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++ {
++ .start = 0xFFC00400,
++ .end = 0xFFC004FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++#ifdef CONFIG_BFIN_SIR1
++ {
++ .start = 0xFFC02000,
++ .end = 0xFFC020FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++ .name = "bfin_sir",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(bfin_sir_resources),
++ .resource = bfin_sir_resources,
++};
++#endif
++
+ #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+ static struct resource bfin_twi0_resource[] = {
+ [0] = {
+@@ -698,6 +746,31 @@ static struct platform_device i2c_bfin_twi_device = {
+ };
+ #endif
+
++#ifdef CONFIG_I2C_BOARDINFO
++static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
++#if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE)
++ {
++ I2C_BOARD_INFO("ad7142_joystick", 0x2C),
++ .type = "ad7142_joystick",
++ .irq = 55,
++ },
++#endif
++#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
++ {
++ I2C_BOARD_INFO("pcf8574_lcd", 0x22),
++ .type = "pcf8574_lcd",
++ },
++#endif
++#if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
++ {
++ I2C_BOARD_INFO("pcf8574_keypad", 0x27),
++ .type = "pcf8574_keypad",
++ .irq = 72,
++ },
++#endif
++};
++#endif
++
+ #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+ static struct platform_device bfin_sport0_uart_device = {
+ .name = "bfin-sport-uart",
+@@ -800,6 +873,10 @@ static struct platform_device *stamp_devices[] __initdata = {
+ &bfin_uart_device,
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++ &bfin_sir_device,
++#endif
++
+ #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+ &i2c_bfin_twi_device,
+ #endif
+@@ -818,12 +895,21 @@ static struct platform_device *stamp_devices[] __initdata = {
+ #endif
+
+ &bfin_gpios_device,
++
++#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+ &stamp_flash_device,
++#endif
+ };
+
+ static int __init stamp_init(void)
+ {
+- printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++ printk(KERN_INFO "%s(): registering device resources\n", __func__);
++
++#ifdef CONFIG_I2C_BOARDINFO
++ i2c_register_board_info(0, bfin_i2c_board_info,
++ ARRAY_SIZE(bfin_i2c_board_info));
++#endif
++
+ platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ spi_register_board_info(bfin_spi_board_info,
+@@ -833,6 +919,7 @@ static int __init stamp_init(void)
+ #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
+ irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
+ #endif
++
+ return 0;
+ }
+
+diff --git a/arch/blackfin/mach-bf537/cpu.c b/arch/blackfin/mach-bf537/cpu.c
+deleted file mode 100644
+index 0442c4c..0000000
+--- a/arch/blackfin/mach-bf537/cpu.c
++++ /dev/null
+@@ -1,159 +0,0 @@
+-/*
+- * File: arch/blackfin/mach-bf537/cpu.c
+- * Based on:
+- * Author: michael.kang at analog.com
+- *
+- * Created:
+- * Description: clock scaling for the bf537
+- *
+- * Modified:
+- * Copyright 2004-2006 Analog Devices Inc.
+- *
+- * Bugs: Enter bugs at http://blackfin.uclinux.org/
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (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, see the file COPYING, or write
+- * to the Free Software Foundation, Inc.,
+- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/types.h>
+-#include <linux/init.h>
+-#include <linux/cpufreq.h>
+-#include <asm/dpmc.h>
+-#include <linux/fs.h>
+-#include <asm/bfin-global.h>
+-
+-/* CONFIG_CLKIN_HZ=11059200 */
+-#define VCO5 (CONFIG_CLKIN_HZ*45) /*497664000 */
+-#define VCO4 (CONFIG_CLKIN_HZ*36) /*398131200 */
+-#define VCO3 (CONFIG_CLKIN_HZ*27) /*298598400 */
+-#define VCO2 (CONFIG_CLKIN_HZ*18) /*199065600 */
+-#define VCO1 (CONFIG_CLKIN_HZ*9) /*99532800 */
+-#define VCO(x) VCO##x
+-
+-#define MFREQ(x) {VCO(x),VCO(x)/4},{VCO(x),VCO(x)/2},{VCO(x),VCO(x)}
+-/* frequency */
+-static struct cpufreq_frequency_table bf537_freq_table[] = {
+- MFREQ(1),
+- MFREQ(3),
+- {VCO4, VCO4 / 2}, {VCO4, VCO4},
+- MFREQ(5),
+- {0, CPUFREQ_TABLE_END},
+-};
+-
+-/*
+- * dpmc_fops->ioctl()
+- * static int dpmc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+- */
+-static int bf537_getfreq(unsigned int cpu)
+-{
+- unsigned long cclk_mhz;
+-
+- /* The driver only support single cpu */
+- if (cpu == 0)
+- dpmc_fops.ioctl(NULL, NULL, IOCTL_GET_CORECLOCK, &cclk_mhz);
+- else
+- cclk_mhz = -1;
+-
+- return cclk_mhz;
+-}
+-
+-static int bf537_target(struct cpufreq_policy *policy,
+- unsigned int target_freq, unsigned int relation)
+-{
+- unsigned long cclk_mhz;
+- unsigned long vco_mhz;
+- unsigned long flags;
+- unsigned int index;
+- struct cpufreq_freqs freqs;
+-
+- if (cpufreq_frequency_table_target(policy, bf537_freq_table, target_freq, relation, &index))
+- return -EINVAL;
+-
+- cclk_mhz = bf537_freq_table[index].frequency;
+- vco_mhz = bf537_freq_table[index].index;
+-
+- dpmc_fops.ioctl(NULL, NULL, IOCTL_CHANGE_FREQUENCY, &vco_mhz);
+- freqs.old = bf537_getfreq(0);
+- freqs.new = cclk_mhz;
+- freqs.cpu = 0;
+-
+- pr_debug("cclk begin change to cclk %d,vco=%d,index=%d,target=%d,oldfreq=%d\n",
+- cclk_mhz, vco_mhz, index, target_freq, freqs.old);
+-
+- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+- local_irq_save(flags);
+- dpmc_fops.ioctl(NULL, NULL, IOCTL_SET_CCLK, &cclk_mhz);
+- local_irq_restore(flags);
+- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+-
+- vco_mhz = get_vco();
+- cclk_mhz = get_cclk();
+- return 0;
+-}
+-
+-/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
+- * this platform, anyway.
+- */
+-static int bf537_verify_speed(struct cpufreq_policy *policy)
+-{
+- return cpufreq_frequency_table_verify(policy, &bf537_freq_table);
+-}
+-
+-static int __init __bf537_cpu_init(struct cpufreq_policy *policy)
+-{
+- if (policy->cpu != 0)
+- return -EINVAL;
+-
+- policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+-
+- policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+- /*Now ,only support one cpu */
+- policy->cur = bf537_getfreq(0);
+- cpufreq_frequency_table_get_attr(bf537_freq_table, policy->cpu);
+- return cpufreq_frequency_table_cpuinfo(policy, bf537_freq_table);
+-}
+-
+-static struct freq_attr *bf537_freq_attr[] = {
+- &cpufreq_freq_attr_scaling_available_freqs,
+- NULL,
+-};
+-
+-static struct cpufreq_driver bf537_driver = {
+- .verify = bf537_verify_speed,
+- .target = bf537_target,
+- .get = bf537_getfreq,
+- .init = __bf537_cpu_init,
+- .name = "bf537",
+- .owner = THIS_MODULE,
+- .attr = bf537_freq_attr,
+-};
+-
+-static int __init bf537_cpu_init(void)
+-{
+- return cpufreq_register_driver(&bf537_driver);
+-}
+-
+-static void __exit bf537_cpu_exit(void)
+-{
+- cpufreq_unregister_driver(&bf537_driver);
+-}
+-
+-MODULE_AUTHOR("Mickael Kang");
+-MODULE_DESCRIPTION("cpufreq driver for BF537 CPU");
+-MODULE_LICENSE("GPL");
+-
+-module_init(bf537_cpu_init);
+-module_exit(bf537_cpu_exit);
+diff --git a/arch/blackfin/mach-bf537/dma.c b/arch/blackfin/mach-bf537/dma.c
+index 706cb97..4edb363 100644
+--- a/arch/blackfin/mach-bf537/dma.c
++++ b/arch/blackfin/mach-bf537/dma.c
+@@ -26,10 +26,12 @@
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
++#include <linux/module.h>
++
+ #include <asm/blackfin.h>
+ #include <asm/dma.h>
+
+-struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
++struct dma_register *dma_io_base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ (struct dma_register *) DMA0_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_NEXT_DESC_PTR,
+@@ -47,6 +49,7 @@ struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ (struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
+ };
++EXPORT_SYMBOL(dma_io_base_addr);
+
+ int channel2irq(unsigned int channel)
+ {
+diff --git a/arch/blackfin/mach-bf537/head.S b/arch/blackfin/mach-bf537/head.S
+index 3014fe8..48cd58a 100644
+--- a/arch/blackfin/mach-bf537/head.S
++++ b/arch/blackfin/mach-bf537/head.S
+@@ -37,9 +37,6 @@
+ #include <asm/mach/mem_init.h>
+ #endif
+
+-.global __rambase
+-.global __ramstart
+-.global __ramend
+ .extern ___bss_stop
+ .extern ___bss_start
+ .extern _bf53x_relocate_l1_mem
+@@ -180,40 +177,28 @@ ENTRY(__start)
+ SSYNC;
+ #endif
+
+-#ifdef CONFIG_BF537_PORT_H
+- p0.h = hi(PORTH_FER);
+- p0.l = lo(PORTH_FER);
+- R0.L = W[P0]; /* Read */
+- SSYNC;
+- R0 = 0x0000;
+- W[P0] = R0.L; /* Write */
+- SSYNC;
+- W[P0] = R0.L; /* Disable peripheral function of PORTH */
+- SSYNC;
+-#endif
+-
+ /* Initialise UART - when booting from u-boot, the UART is not disabled
+ * so if we dont initalize here, our serial console gets hosed */
+- p0.h = hi(UART_LCR);
+- p0.l = lo(UART_LCR);
++ p0.h = hi(BFIN_UART_LCR);
++ p0.l = lo(BFIN_UART_LCR);
+ r0 = 0x0(Z);
+ w[p0] = r0.L; /* To enable DLL writes */
+ ssync;
+
+- p0.h = hi(UART_DLL);
+- p0.l = lo(UART_DLL);
++ p0.h = hi(BFIN_UART_DLL);
++ p0.l = lo(BFIN_UART_DLL);
+ r0 = 0x0(Z);
+ w[p0] = r0.L;
+ ssync;
+
+- p0.h = hi(UART_DLH);
+- p0.l = lo(UART_DLH);
++ p0.h = hi(BFIN_UART_DLH);
++ p0.l = lo(BFIN_UART_DLH);
+ r0 = 0x00(Z);
+ w[p0] = r0.L;
+ ssync;
+
+- p0.h = hi(UART_GCTL);
+- p0.l = lo(UART_GCTL);
++ p0.h = hi(BFIN_UART_GCTL);
++ p0.l = lo(BFIN_UART_GCTL);
+ r0 = 0x0(Z);
+ w[p0] = r0.L; /* To enable UART clock */
+ ssync;
+@@ -483,18 +468,3 @@ ENTRY(_start_dma_code)
+ RTS;
+ ENDPROC(_start_dma_code)
+ #endif /* CONFIG_BFIN_KERNEL_CLOCK */
+-
+-.data
+-
+-/*
+- * Set up the usable of RAM stuff. Size of RAM is determined then
+- * an initial stack set up at the end.
+- */
+-
+-.align 4
+-__rambase:
+-.long 0
+-__ramstart:
+-.long 0
+-__ramend:
+-.long 0
+diff --git a/arch/blackfin/mach-bf548/Makefile b/arch/blackfin/mach-bf548/Makefile
+index 7e7c9c8..68e5478 100644
+--- a/arch/blackfin/mach-bf548/Makefile
++++ b/arch/blackfin/mach-bf548/Makefile
+@@ -5,5 +5,3 @@
+ extra-y := head.o
+
+ obj-y := ints-priority.o dma.o
+-
+-obj-$(CONFIG_CPU_FREQ) += cpu.o
+diff --git a/arch/blackfin/mach-bf548/boards/Kconfig b/arch/blackfin/mach-bf548/boards/Kconfig
+index 0571290..d38e526 100644
+--- a/arch/blackfin/mach-bf548/boards/Kconfig
++++ b/arch/blackfin/mach-bf548/boards/Kconfig
+@@ -8,5 +8,11 @@ config BFIN548_EZKIT
+ bool "BF548-EZKIT"
+ help
+ BFIN548-EZKIT board support.
++
++config BFIN548_BLUETECHNIX_CM
++ bool "Bluetechnix CM-BF548"
++ depends on (BF548)
++ help
++ CM-BF548 support for DEV-Board.
+
+ endchoice
+diff --git a/arch/blackfin/mach-bf548/boards/Makefile b/arch/blackfin/mach-bf548/boards/Makefile
+index a444cc7..eed161d 100644
+--- a/arch/blackfin/mach-bf548/boards/Makefile
++++ b/arch/blackfin/mach-bf548/boards/Makefile
+@@ -3,3 +3,4 @@
+ #
+
+ obj-$(CONFIG_BFIN548_EZKIT) += ezkit.o led.o
++obj-$(CONFIG_BFIN548_BLUETECHNIX_CM) += cm_bf548.o
+diff --git a/arch/blackfin/mach-bf548/boards/cm_bf548.c b/arch/blackfin/mach-bf548/boards/cm_bf548.c
+new file mode 100644
+index 0000000..e3e8479
+--- /dev/null
++++ b/arch/blackfin/mach-bf548/boards/cm_bf548.c
+@@ -0,0 +1,664 @@
++/*
++ * File: arch/blackfin/mach-bf548/boards/cm_bf548.c
++ * Based on: arch/blackfin/mach-bf537/boards/ezkit.c
++ * Author: Aidan Williams <aidan at nicta.com.au>
++ *
++ * Created:
++ * Description:
++ *
++ * Modified:
++ * Copyright 2005 National ICT Australia (NICTA)
++ * Copyright 2004-2008 Analog Devices Inc.
++ *
++ * Bugs: Enter bugs at http://blackfin.uclinux.org/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (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, see the file COPYING, or write
++ * to the Free Software Foundation, Inc.,
++ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#include <linux/spi/spi.h>
++#include <linux/spi/flash.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/usb/musb.h>
++#include <asm/bfin5xx_spi.h>
++#include <asm/cplb.h>
++#include <asm/dma.h>
++#include <asm/gpio.h>
++#include <asm/nand.h>
++#include <asm/portmux.h>
++#include <asm/mach/bf54x_keys.h>
++#include <linux/input.h>
++#include <linux/spi/ad7877.h>
++
++/*
++ * Name the Board for the /proc/cpuinfo
++ */
++const char bfin_board_name[] = "Bluetechnix CM-BF548";
++
++/*
++ * Driver needs to know address, irq and flag pin.
++ */
++
++#if defined(CONFIG_FB_BF54X_LQ043) || defined(CONFIG_FB_BF54X_LQ043_MODULE)
++
++#include <asm/mach/bf54x-lq043.h>
++
++static struct bfin_bf54xfb_mach_info bf54x_lq043_data = {
++ .width = 480,
++ .height = 272,
++ .xres = {480, 480, 480},
++ .yres = {272, 272, 272},
++ .bpp = {24, 24, 24},
++ .disp = GPIO_PE3,
++};
++
++static struct resource bf54x_lq043_resources[] = {
++ {
++ .start = IRQ_EPPI0_ERR,
++ .end = IRQ_EPPI0_ERR,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device bf54x_lq043_device = {
++ .name = "bf54x-lq043",
++ .id = -1,
++ .num_resources = ARRAY_SIZE(bf54x_lq043_resources),
++ .resource = bf54x_lq043_resources,
++ .dev = {
++ .platform_data = &bf54x_lq043_data,
++ },
++};
++#endif
++
++#if defined(CONFIG_KEYBOARD_BFIN) || defined(CONFIG_KEYBOARD_BFIN_MODULE)
++static unsigned int bf548_keymap[] = {
++ KEYVAL(0, 0, KEY_ENTER),
++ KEYVAL(0, 1, KEY_HELP),
++ KEYVAL(0, 2, KEY_0),
++ KEYVAL(0, 3, KEY_BACKSPACE),
++ KEYVAL(1, 0, KEY_TAB),
++ KEYVAL(1, 1, KEY_9),
++ KEYVAL(1, 2, KEY_8),
++ KEYVAL(1, 3, KEY_7),
++ KEYVAL(2, 0, KEY_DOWN),
++ KEYVAL(2, 1, KEY_6),
++ KEYVAL(2, 2, KEY_5),
++ KEYVAL(2, 3, KEY_4),
++ KEYVAL(3, 0, KEY_UP),
++ KEYVAL(3, 1, KEY_3),
++ KEYVAL(3, 2, KEY_2),
++ KEYVAL(3, 3, KEY_1),
++};
++
++static struct bfin_kpad_platform_data bf54x_kpad_data = {
++ .rows = 4,
++ .cols = 4,
++ .keymap = bf548_keymap,
++ .keymapsize = ARRAY_SIZE(bf548_keymap),
++ .repeat = 0,
++ .debounce_time = 5000, /* ns (5ms) */
++ .coldrive_time = 1000, /* ns (1ms) */
++ .keyup_test_interval = 50, /* ms (50ms) */
++};
++
++static struct resource bf54x_kpad_resources[] = {
++ {
++ .start = IRQ_KEY,
++ .end = IRQ_KEY,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device bf54x_kpad_device = {
++ .name = "bf54x-keys",
++ .id = -1,
++ .num_resources = ARRAY_SIZE(bf54x_kpad_resources),
++ .resource = bf54x_kpad_resources,
++ .dev = {
++ .platform_data = &bf54x_kpad_data,
++ },
++};
++#endif
++
++#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
++static struct platform_device rtc_device = {
++ .name = "rtc-bfin",
++ .id = -1,
++};
++#endif
++
++#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
++static struct resource bfin_uart_resources[] = {
++#ifdef CONFIG_SERIAL_BFIN_UART0
++ {
++ .start = 0xFFC00400,
++ .end = 0xFFC004FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++#ifdef CONFIG_SERIAL_BFIN_UART1
++ {
++ .start = 0xFFC02000,
++ .end = 0xFFC020FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++#ifdef CONFIG_SERIAL_BFIN_UART2
++ {
++ .start = 0xFFC02100,
++ .end = 0xFFC021FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++#ifdef CONFIG_SERIAL_BFIN_UART3
++ {
++ .start = 0xFFC03100,
++ .end = 0xFFC031FF,
++ },
++#endif
++};
++
++static struct platform_device bfin_uart_device = {
++ .name = "bfin-uart",
++ .id = 1,
++ .num_resources = ARRAY_SIZE(bfin_uart_resources),
++ .resource = bfin_uart_resources,
++};
++#endif
++
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++ {
++ .start = 0xFFC00400,
++ .end = 0xFFC004FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++#ifdef CONFIG_BFIN_SIR1
++ {
++ .start = 0xFFC02000,
++ .end = 0xFFC020FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++#ifdef CONFIG_BFIN_SIR2
++ {
++ .start = 0xFFC02100,
++ .end = 0xFFC021FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++#ifdef CONFIG_BFIN_SIR3
++ {
++ .start = 0xFFC03100,
++ .end = 0xFFC031FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++ .name = "bfin_sir",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(bfin_sir_resources),
++ .resource = bfin_sir_resources,
++};
++#endif
++
++#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
++static struct resource smsc911x_resources[] = {
++ {
++ .name = "smsc911x-memory",
++ .start = 0x24000000,
++ .end = 0x24000000 + 0xFF,
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = IRQ_PE6,
++ .end = IRQ_PE6,
++ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
++ },
++};
++static struct platform_device smsc911x_device = {
++ .name = "smsc911x",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(smsc911x_resources),
++ .resource = smsc911x_resources,
++};
++#endif
++
++#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
++static struct resource musb_resources[] = {
++ [0] = {
++ .start = 0xFFC03C00,
++ .end = 0xFFC040FF,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = { /* general IRQ */
++ .start = IRQ_USB_INT0,
++ .end = IRQ_USB_INT0,
++ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
++ },
++ [2] = { /* DMA IRQ */
++ .start = IRQ_USB_DMA,
++ .end = IRQ_USB_DMA,
++ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
++ },
++};
++
++static struct musb_hdrc_platform_data musb_plat = {
++#if defined(CONFIG_USB_MUSB_OTG)
++ .mode = MUSB_OTG,
++#elif defined(CONFIG_USB_MUSB_HDRC_HCD)
++ .mode = MUSB_HOST,
++#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
++ .mode = MUSB_PERIPHERAL,
++#endif
++ .multipoint = 0,
++};
++
++static u64 musb_dmamask = ~(u32)0;
++
++static struct platform_device musb_device = {
++ .name = "musb_hdrc",
++ .id = 0,
++ .dev = {
++ .dma_mask = &musb_dmamask,
++ .coherent_dma_mask = 0xffffffff,
++ .platform_data = &musb_plat,
++ },
++ .num_resources = ARRAY_SIZE(musb_resources),
++ .resource = musb_resources,
++};
++#endif
++
++#if defined(CONFIG_PATA_BF54X) || defined(CONFIG_PATA_BF54X_MODULE)
++static struct resource bfin_atapi_resources[] = {
++ {
++ .start = 0xFFC03800,
++ .end = 0xFFC0386F,
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = IRQ_ATAPI_ERR,
++ .end = IRQ_ATAPI_ERR,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device bfin_atapi_device = {
++ .name = "pata-bf54x",
++ .id = -1,
++ .num_resources = ARRAY_SIZE(bfin_atapi_resources),
++ .resource = bfin_atapi_resources,
++};
++#endif
++
++#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
++static struct mtd_partition partition_info[] = {
++ {
++ .name = "Linux Kernel",
++ .offset = 0,
++ .size = 4 * SIZE_1M,
++ },
++ {
++ .name = "File System",
++ .offset = 4 * SIZE_1M,
++ .size = (256 - 4) * SIZE_1M,
++ },
++};
++
++static struct bf5xx_nand_platform bf5xx_nand_platform = {
++ .page_size = NFC_PG_SIZE_256,
++ .data_width = NFC_NWIDTH_8,
++ .partitions = partition_info,
++ .nr_partitions = ARRAY_SIZE(partition_info),
++ .rd_dly = 3,
++ .wr_dly = 3,
++};
++
++static struct resource bf5xx_nand_resources[] = {
++ {
++ .start = 0xFFC03B00,
++ .end = 0xFFC03B4F,
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = CH_NFC,
++ .end = CH_NFC,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device bf5xx_nand_device = {
++ .name = "bf5xx-nand",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(bf5xx_nand_resources),
++ .resource = bf5xx_nand_resources,
++ .dev = {
++ .platform_data = &bf5xx_nand_platform,
++ },
++};
++#endif
++
++#if defined(CONFIG_SDH_BFIN) || defined(CONFIG_SDH_BFIN_MODULE)
++static struct platform_device bf54x_sdh_device = {
++ .name = "bfin-sdh",
++ .id = 0,
++};
++#endif
++
++#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
++/* all SPI peripherals info goes here */
++#if defined(CONFIG_MTD_M25P80) \
++ || defined(CONFIG_MTD_M25P80_MODULE)
++/* SPI flash chip (m25p16) */
++static struct mtd_partition bfin_spi_flash_partitions[] = {
++ {
++ .name = "bootloader",
++ .size = 0x00040000,
++ .offset = 0,
++ .mask_flags = MTD_CAP_ROM
++ }, {
++ .name = "linux kernel",
++ .size = 0x1c0000,
++ .offset = 0x40000
++ }
++};
++
++static struct flash_platform_data bfin_spi_flash_data = {
++ .name = "m25p80",
++ .parts = bfin_spi_flash_partitions,
++ .nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions),
++ .type = "m25p16",
++};
++
++static struct bfin5xx_spi_chip spi_flash_chip_info = {
++ .enable_dma = 0, /* use dma transfer with this chip*/
++ .bits_per_word = 8,
++ .cs_change_per_word = 0,
++};
++#endif
++
++#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
++static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
++ .cs_change_per_word = 0,
++ .enable_dma = 0,
++ .bits_per_word = 16,
++};
++
++static const struct ad7877_platform_data bfin_ad7877_ts_info = {
++ .model = 7877,
++ .vref_delay_usecs = 50, /* internal, no capacitor */
++ .x_plate_ohms = 419,
++ .y_plate_ohms = 486,
++ .pressure_max = 1000,
++ .pressure_min = 0,
++ .stopacq_polarity = 1,
++ .first_conversion_delay = 3,
++ .acquisition_time = 1,
++ .averaging = 1,
++ .pen_down_acc_interval = 1,
++};
++#endif
++
++#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
++static struct bfin5xx_spi_chip spidev_chip_info = {
++ .enable_dma = 0,
++ .bits_per_word = 8,
++};
++#endif
++
++static struct spi_board_info bf54x_spi_board_info[] __initdata = {
++#if defined(CONFIG_MTD_M25P80) \
++ || defined(CONFIG_MTD_M25P80_MODULE)
++ {
++ /* the modalias must be the same as spi device driver name */
++ .modalias = "m25p80", /* Name of spi_driver for this device */
++ .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
++ .bus_num = 0, /* Framework bus number */
++ .chip_select = 1, /* SPI_SSEL1*/
++ .platform_data = &bfin_spi_flash_data,
++ .controller_data = &spi_flash_chip_info,
++ .mode = SPI_MODE_3,
++ },
++#endif
++#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
++{
++ .modalias = "ad7877",
++ .platform_data = &bfin_ad7877_ts_info,
++ .irq = IRQ_PJ11,
++ .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
++ .bus_num = 0,
++ .chip_select = 2,
++ .controller_data = &spi_ad7877_chip_info,
++},
++#endif
++#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
++ {
++ .modalias = "spidev",
++ .max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
++ .bus_num = 0,
++ .chip_select = 1,
++ .controller_data = &spidev_chip_info,
++ },
++#endif
++};
++
++/* SPI (0) */
++static struct resource bfin_spi0_resource[] = {
++ [0] = {
++ .start = SPI0_REGBASE,
++ .end = SPI0_REGBASE + 0xFF,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = CH_SPI0,
++ .end = CH_SPI0,
++ .flags = IORESOURCE_IRQ,
++ }
++};
++
++/* SPI (1) */
++static struct resource bfin_spi1_resource[] = {
++ [0] = {
++ .start = SPI1_REGBASE,
++ .end = SPI1_REGBASE + 0xFF,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = CH_SPI1,
++ .end = CH_SPI1,
++ .flags = IORESOURCE_IRQ,
++ }
++};
++
++/* SPI controller data */
++static struct bfin5xx_spi_master bf54x_spi_master_info0 = {
++ .num_chipselect = 8,
++ .enable_dma = 1, /* master has the ability to do dma transfer */
++ .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
++};
++
++static struct platform_device bf54x_spi_master0 = {
++ .name = "bfin-spi",
++ .id = 0, /* Bus number */
++ .num_resources = ARRAY_SIZE(bfin_spi0_resource),
++ .resource = bfin_spi0_resource,
++ .dev = {
++ .platform_data = &bf54x_spi_master_info0, /* Passed to driver */
++ },
++};
++
++static struct bfin5xx_spi_master bf54x_spi_master_info1 = {
++ .num_chipselect = 8,
++ .enable_dma = 1, /* master has the ability to do dma transfer */
++ .pin_req = {P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0},
++};
++
++static struct platform_device bf54x_spi_master1 = {
++ .name = "bfin-spi",
++ .id = 1, /* Bus number */
++ .num_resources = ARRAY_SIZE(bfin_spi1_resource),
++ .resource = bfin_spi1_resource,
++ .dev = {
++ .platform_data = &bf54x_spi_master_info1, /* Passed to driver */
++ },
++};
++#endif /* spi master and devices */
++
++#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
++static struct resource bfin_twi0_resource[] = {
++ [0] = {
++ .start = TWI0_REGBASE,
++ .end = TWI0_REGBASE + 0xFF,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_TWI0,
++ .end = IRQ_TWI0,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device i2c_bfin_twi0_device = {
++ .name = "i2c-bfin-twi",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(bfin_twi0_resource),
++ .resource = bfin_twi0_resource,
++};
++
++#if !defined(CONFIG_BF542) /* The BF542 only has 1 TWI */
++static struct resource bfin_twi1_resource[] = {
++ [0] = {
++ .start = TWI1_REGBASE,
++ .end = TWI1_REGBASE + 0xFF,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_TWI1,
++ .end = IRQ_TWI1,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device i2c_bfin_twi1_device = {
++ .name = "i2c-bfin-twi",
++ .id = 1,
++ .num_resources = ARRAY_SIZE(bfin_twi1_resource),
++ .resource = bfin_twi1_resource,
++};
++#endif
++#endif
++
++#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
++#include <linux/gpio_keys.h>
++
++static struct gpio_keys_button bfin_gpio_keys_table[] = {
++ {BTN_0, GPIO_PH7, 1, "gpio-keys: BTN0"},
++};
++
++static struct gpio_keys_platform_data bfin_gpio_keys_data = {
++ .buttons = bfin_gpio_keys_table,
++ .nbuttons = ARRAY_SIZE(bfin_gpio_keys_table),
++};
++
++static struct platform_device bfin_device_gpiokeys = {
++ .name = "gpio-keys",
++ .dev = {
++ .platform_data = &bfin_gpio_keys_data,
++ },
++};
++#endif
++
++static struct platform_device *cm_bf548_devices[] __initdata = {
++#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
++ &rtc_device,
++#endif
++
++#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
++ &bfin_uart_device,
++#endif
++
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++ &bfin_sir_device,
++#endif
++
++#if defined(CONFIG_FB_BF54X_LQ043) || defined(CONFIG_FB_BF54X_LQ043_MODULE)
++ &bf54x_lq043_device,
++#endif
++
++#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
++ &smsc911x_device,
++#endif
++
++#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
++ &musb_device,
++#endif
++
++#if defined(CONFIG_PATA_BF54X) || defined(CONFIG_PATA_BF54X_MODULE)
++ &bfin_atapi_device,
++#endif
++
++#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
++ &bf5xx_nand_device,
++#endif
++
++#if defined(CONFIG_SDH_BFIN) || defined(CONFIG_SDH_BFIN_MODULE)
++ &bf54x_sdh_device,
++#endif
++
++#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
++ &bf54x_spi_master0,
++ &bf54x_spi_master1,
++#endif
++
++#if defined(CONFIG_KEYBOARD_BFIN) || defined(CONFIG_KEYBOARD_BFIN_MODULE)
++ &bf54x_kpad_device,
++#endif
++
++#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
++/* &i2c_bfin_twi0_device, */
++#if !defined(CONFIG_BF542)
++ &i2c_bfin_twi1_device,
++#endif
++#endif
++
++#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
++ &bfin_device_gpiokeys,
++#endif
++};
++
++static int __init cm_bf548_init(void)
++{
++ printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++ platform_add_devices(cm_bf548_devices, ARRAY_SIZE(cm_bf548_devices));
++
++#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
++ spi_register_board_info(bf54x_spi_board_info,
++ ARRAY_SIZE(bf54x_spi_board_info));
++#endif
++
++ return 0;
++}
++
++arch_initcall(cm_bf548_init);
+diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c
+index 40846aa..231dfbd 100644
+--- a/arch/blackfin/mach-bf548/boards/ezkit.c
++++ b/arch/blackfin/mach-bf548/boards/ezkit.c
+@@ -36,6 +36,7 @@
+ #include <linux/spi/spi.h>
+ #include <linux/spi/flash.h>
+ #include <linux/irq.h>
++#include <linux/i2c.h>
+ #include <linux/interrupt.h>
+ #if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
+ #include <linux/usb/musb.h>
+@@ -187,6 +188,46 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++ {
++ .start = 0xFFC00400,
++ .end = 0xFFC004FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++#ifdef CONFIG_BFIN_SIR1
++ {
++ .start = 0xFFC02000,
++ .end = 0xFFC020FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++#ifdef CONFIG_BFIN_SIR2
++ {
++ .start = 0xFFC02100,
++ .end = 0xFFC021FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++#ifdef CONFIG_BFIN_SIR3
++ {
++ .start = 0xFFC03100,
++ .end = 0xFFC031FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++ .name = "bfin_sir",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(bfin_sir_resources),
++ .resource = bfin_sir_resources,
++};
++#endif
++
+ #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
+ static struct resource smsc911x_resources[] = {
+ {
+@@ -330,6 +371,7 @@ static struct platform_device bf54x_sdh_device = {
+ };
+ #endif
+
++#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+ static struct mtd_partition ezkit_partitions[] = {
+ {
+ .name = "Bootloader",
+@@ -337,7 +379,7 @@ static struct mtd_partition ezkit_partitions[] = {
+ .offset = 0,
+ }, {
+ .name = "Kernel",
+- .size = 0xE0000,
++ .size = 0x1C0000,
+ .offset = MTDPART_OFS_APPEND,
+ }, {
+ .name = "RootFS",
+@@ -367,6 +409,7 @@ static struct platform_device ezkit_flash_device = {
+ .num_resources = 1,
+ .resource = &ezkit_flash_resource,
+ };
++#endif
+
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ /* all SPI peripherals info goes here */
+@@ -400,6 +443,14 @@ static struct bfin5xx_spi_chip spi_flash_chip_info = {
+ };
+ #endif
+
++#if defined(CONFIG_SND_BLACKFIN_AD1836) \
++ || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
++static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
++ .enable_dma = 0,
++ .bits_per_word = 16,
++};
++#endif
++
+ #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
+ static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
+ .cs_change_per_word = 0,
+@@ -443,6 +494,16 @@ static struct spi_board_info bf54x_spi_board_info[] __initdata = {
+ .mode = SPI_MODE_3,
+ },
+ #endif
++#if defined(CONFIG_SND_BLACKFIN_AD1836) \
++ || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
++ {
++ .modalias = "ad1836-spi",
++ .max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
++ .bus_num = 1,
++ .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT,
++ .controller_data = &ad1836_spi_chip_info,
++ },
++#endif
+ #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
+ {
+ .modalias = "ad7877",
+@@ -571,6 +632,29 @@ static struct platform_device i2c_bfin_twi1_device = {
+ #endif
+ #endif
+
++#ifdef CONFIG_I2C_BOARDINFO
++static struct i2c_board_info __initdata bfin_i2c_board_info0[] = {
++};
++
++#if !defined(CONFIG_BF542) /* The BF542 only has 1 TWI */
++static struct i2c_board_info __initdata bfin_i2c_board_info1[] = {
++#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
++ {
++ I2C_BOARD_INFO("pcf8574_lcd", 0x22),
++ .type = "pcf8574_lcd",
++ },
++#endif
++#if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
++ {
++ I2C_BOARD_INFO("pcf8574_keypad", 0x27),
++ .type = "pcf8574_keypad",
++ .irq = 212,
++ },
++#endif
++};
++#endif
++#endif
++
+ #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+ #include <linux/gpio_keys.h>
+
+@@ -616,6 +700,10 @@ static struct platform_device *ezkit_devices[] __initdata = {
+ &bfin_uart_device,
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++ &bfin_sir_device,
++#endif
++
+ #if defined(CONFIG_FB_BF54X_LQ043) || defined(CONFIG_FB_BF54X_LQ043_MODULE)
+ &bf54x_lq043_device,
+ #endif
+@@ -661,12 +749,25 @@ static struct platform_device *ezkit_devices[] __initdata = {
+ #endif
+
+ &bfin_gpios_device,
++
++#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+ &ezkit_flash_device,
++#endif
+ };
+
+ static int __init ezkit_init(void)
+ {
+- printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++ printk(KERN_INFO "%s(): registering device resources\n", __func__);
++
++#ifdef CONFIG_I2C_BOARDINFO
++ i2c_register_board_info(0, bfin_i2c_board_info0,
++ ARRAY_SIZE(bfin_i2c_board_info0));
++#if !defined(CONFIG_BF542) /* The BF542 only has 1 TWI */
++ i2c_register_board_info(1, bfin_i2c_board_info1,
++ ARRAY_SIZE(bfin_i2c_board_info1));
++#endif
++#endif
++
+ platform_add_devices(ezkit_devices, ARRAY_SIZE(ezkit_devices));
+
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+diff --git a/arch/blackfin/mach-bf548/cpu.c b/arch/blackfin/mach-bf548/cpu.c
+deleted file mode 100644
+index 4298a3c..0000000
+--- a/arch/blackfin/mach-bf548/cpu.c
++++ /dev/null
+@@ -1,159 +0,0 @@
+-/*
+- * File: arch/blackfin/mach-bf548/cpu.c
+- * Based on:
+- * Author:
+- *
+- * Created:
+- * Description: clock scaling for the bf54x
+- *
+- * Modified:
+- * Copyright 2004-2007 Analog Devices Inc.
+- *
+- * Bugs: Enter bugs at http://blackfin.uclinux.org/
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (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, see the file COPYING, or write
+- * to the Free Software Foundation, Inc.,
+- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/types.h>
+-#include <linux/init.h>
+-#include <linux/cpufreq.h>
+-#include <asm/dpmc.h>
+-#include <linux/fs.h>
+-#include <asm/bfin-global.h>
+-
+-/* CONFIG_CLKIN_HZ=25000000 */
+-#define VCO5 (CONFIG_CLKIN_HZ*45)
+-#define VCO4 (CONFIG_CLKIN_HZ*36)
+-#define VCO3 (CONFIG_CLKIN_HZ*27)
+-#define VCO2 (CONFIG_CLKIN_HZ*18)
+-#define VCO1 (CONFIG_CLKIN_HZ*9)
+-#define VCO(x) VCO##x
+-
+-#define MFREQ(x) {VCO(x),VCO(x)/4},{VCO(x),VCO(x)/2},{VCO(x),VCO(x)}
+-/* frequency */
+-static struct cpufreq_frequency_table bf548_freq_table[] = {
+- MFREQ(1),
+- MFREQ(3),
+- {VCO4, VCO4 / 2}, {VCO4, VCO4},
+- MFREQ(5),
+- {0, CPUFREQ_TABLE_END},
+-};
+-
+-/*
+- * dpmc_fops->ioctl()
+- * static int dpmc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+- */
+-static int bf548_getfreq(unsigned int cpu)
+-{
+- unsigned long cclk_mhz;
+-
+- /* The driver only support single cpu */
+- if (cpu == 0)
+- dpmc_fops.ioctl(NULL, NULL, IOCTL_GET_CORECLOCK, &cclk_mhz);
+- else
+- cclk_mhz = -1;
+-
+- return cclk_mhz;
+-}
+-
+-static int bf548_target(struct cpufreq_policy *policy,
+- unsigned int target_freq, unsigned int relation)
+-{
+- unsigned long cclk_mhz;
+- unsigned long vco_mhz;
+- unsigned long flags;
+- unsigned int index;
+- struct cpufreq_freqs freqs;
+-
+- if (cpufreq_frequency_table_target(policy, bf548_freq_table, target_freq, relation, &index))
+- return -EINVAL;
+-
+- cclk_mhz = bf548_freq_table[index].frequency;
+- vco_mhz = bf548_freq_table[index].index;
+-
+- dpmc_fops.ioctl(NULL, NULL, IOCTL_CHANGE_FREQUENCY, &vco_mhz);
+- freqs.old = bf548_getfreq(0);
+- freqs.new = cclk_mhz;
+- freqs.cpu = 0;
+-
+- pr_debug("cclk begin change to cclk %d,vco=%d,index=%d,target=%d,oldfreq=%d\n",
+- cclk_mhz, vco_mhz, index, target_freq, freqs.old);
+-
+- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+- local_irq_save(flags);
+- dpmc_fops.ioctl(NULL, NULL, IOCTL_SET_CCLK, &cclk_mhz);
+- local_irq_restore(flags);
+- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+-
+- vco_mhz = get_vco();
+- cclk_mhz = get_cclk();
+- return 0;
+-}
+-
+-/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
+- * this platform, anyway.
+- */
+-static int bf548_verify_speed(struct cpufreq_policy *policy)
+-{
+- return cpufreq_frequency_table_verify(policy, &bf548_freq_table);
+-}
+-
+-static int __init __bf548_cpu_init(struct cpufreq_policy *policy)
+-{
+- if (policy->cpu != 0)
+- return -EINVAL;
+-
+- policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+-
+- policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+- /*Now ,only support one cpu */
+- policy->cur = bf548_getfreq(0);
+- cpufreq_frequency_table_get_attr(bf548_freq_table, policy->cpu);
+- return cpufreq_frequency_table_cpuinfo(policy, bf548_freq_table);
+-}
+-
+-static struct freq_attr *bf548_freq_attr[] = {
+- &cpufreq_freq_attr_scaling_available_freqs,
+- NULL,
+-};
+-
+-static struct cpufreq_driver bf548_driver = {
+- .verify = bf548_verify_speed,
+- .target = bf548_target,
+- .get = bf548_getfreq,
+- .init = __bf548_cpu_init,
+- .name = "bf548",
+- .owner = THIS_MODULE,
+- .attr = bf548_freq_attr,
+-};
+-
+-static int __init bf548_cpu_init(void)
+-{
+- return cpufreq_register_driver(&bf548_driver);
+-}
+-
+-static void __exit bf548_cpu_exit(void)
+-{
+- cpufreq_unregister_driver(&bf548_driver);
+-}
+-
+-MODULE_AUTHOR("Mickael Kang");
+-MODULE_DESCRIPTION("cpufreq driver for BF548 CPU");
+-MODULE_LICENSE("GPL");
+-
+-module_init(bf548_cpu_init);
+-module_exit(bf548_cpu_exit);
+diff --git a/arch/blackfin/mach-bf548/dma.c b/arch/blackfin/mach-bf548/dma.c
+index f547929..74730eb 100644
+--- a/arch/blackfin/mach-bf548/dma.c
++++ b/arch/blackfin/mach-bf548/dma.c
+@@ -32,7 +32,7 @@
+ #include <asm/blackfin.h>
+ #include <asm/dma.h>
+
+- struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
++struct dma_register *dma_io_base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ (struct dma_register *) DMA0_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_NEXT_DESC_PTR,
+@@ -66,7 +66,7 @@
+ (struct dma_register *) MDMA_D3_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_S3_NEXT_DESC_PTR,
+ };
+-EXPORT_SYMBOL(base_addr);
++EXPORT_SYMBOL(dma_io_base_addr);
+
+ int channel2irq(unsigned int channel)
+ {
+diff --git a/arch/blackfin/mach-bf548/head.S b/arch/blackfin/mach-bf548/head.S
+index 46222a7..f719114 100644
+--- a/arch/blackfin/mach-bf548/head.S
++++ b/arch/blackfin/mach-bf548/head.S
+@@ -36,9 +36,6 @@
+ #include <asm/mach/mem_init.h>
+ #endif
+
+-.global __rambase
+-.global __ramstart
+-.global __ramend
+ .extern ___bss_stop
+ .extern ___bss_start
+ .extern _bf53x_relocate_l1_mem
+@@ -456,18 +453,3 @@ ENTRY(_start_dma_code)
+ RTS;
+ ENDPROC(_start_dma_code)
+ #endif /* CONFIG_BFIN_KERNEL_CLOCK */
+-
+-.data
+-
+-/*
+- * Set up the usable of RAM stuff. Size of RAM is determined then
+- * an initial stack set up at the end.
+- */
+-
+-.align 4
+-__rambase:
+-.long 0
+-__ramstart:
+-.long 0
+-__ramend:
+-.long 0
+diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c
+index bf9e738..9fd5809 100644
+--- a/arch/blackfin/mach-bf561/boards/cm_bf561.c
++++ b/arch/blackfin/mach-bf561/boards/cm_bf561.c
+@@ -283,6 +283,25 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++ {
++ .start = 0xFFC00400,
++ .end = 0xFFC004FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++ .name = "bfin_sir",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(bfin_sir_resources),
++ .resource = bfin_sir_resources,
++};
++#endif
++
+ #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
+ #define PATA_INT 119
+
+@@ -330,6 +349,10 @@ static struct platform_device *cm_bf561_devices[] __initdata = {
+ &bfin_uart_device,
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++ &bfin_sir_device,
++#endif
++
+ #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+ &isp1362_hcd_device,
+ #endif
+@@ -349,7 +372,7 @@ static struct platform_device *cm_bf561_devices[] __initdata = {
+
+ static int __init cm_bf561_init(void)
+ {
+- printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++ printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ platform_add_devices(cm_bf561_devices, ARRAY_SIZE(cm_bf561_devices));
+ #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c
+index d357f64..0d74b7d 100644
+--- a/arch/blackfin/mach-bf561/boards/ezkit.c
++++ b/arch/blackfin/mach-bf561/boards/ezkit.c
+@@ -78,7 +78,7 @@ int __init bfin_isp1761_init(void)
+ {
+ unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
+
+- printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++ printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
+
+ return platform_add_devices(bfin_isp1761_devices, num_devices);
+@@ -220,6 +220,26 @@ static struct platform_device bfin_uart_device = {
+ };
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++static struct resource bfin_sir_resources[] = {
++#ifdef CONFIG_BFIN_SIR0
++ {
++ .start = 0xFFC00400,
++ .end = 0xFFC004FF,
++ .flags = IORESOURCE_MEM,
++ },
++#endif
++};
++
++static struct platform_device bfin_sir_device = {
++ .name = "bfin_sir",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(bfin_sir_resources),
++ .resource = bfin_sir_resources,
++};
++#endif
++
++#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+ static struct mtd_partition ezkit_partitions[] = {
+ {
+ .name = "Bootloader",
+@@ -227,7 +247,7 @@ static struct mtd_partition ezkit_partitions[] = {
+ .offset = 0,
+ }, {
+ .name = "Kernel",
+- .size = 0xE0000,
++ .size = 0x1C0000,
+ .offset = MTDPART_OFS_APPEND,
+ }, {
+ .name = "RootFS",
+@@ -257,6 +277,7 @@ static struct platform_device ezkit_flash_device = {
+ .num_resources = 1,
+ .resource = &ezkit_flash_resource,
+ };
++#endif
+
+ #ifdef CONFIG_SPI_BFIN
+ #if defined(CONFIG_SND_BLACKFIN_AD1836) \
+@@ -443,6 +464,10 @@ static struct platform_device *ezkit_devices[] __initdata = {
+ &bfin_uart_device,
+ #endif
+
++#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
++ &bfin_sir_device,
++#endif
++
+ #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
+ &bfin_pata_device,
+ #endif
+@@ -460,7 +485,10 @@ static struct platform_device *ezkit_devices[] __initdata = {
+ #endif
+
+ &bfin_gpios_device,
++
++#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+ &ezkit_flash_device,
++#endif
+ };
+
+ static int __init ezkit_init(void)
+diff --git a/arch/blackfin/mach-bf561/boards/generic_board.c b/arch/blackfin/mach-bf561/boards/generic_board.c
+index fc80c5d..2faa007 100644
+--- a/arch/blackfin/mach-bf561/boards/generic_board.c
++++ b/arch/blackfin/mach-bf561/boards/generic_board.c
+@@ -70,7 +70,7 @@ static struct platform_device *generic_board_devices[] __initdata = {
+
+ static int __init generic_board_init(void)
+ {
+- printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++ printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ return platform_add_devices(generic_board_devices,
+ ARRAY_SIZE(generic_board_devices));
+ }
+diff --git a/arch/blackfin/mach-bf561/boards/tepla.c b/arch/blackfin/mach-bf561/boards/tepla.c
+index ec6a220..c9174b3 100644
+--- a/arch/blackfin/mach-bf561/boards/tepla.c
++++ b/arch/blackfin/mach-bf561/boards/tepla.c
+@@ -50,7 +50,7 @@ static struct platform_device *tepla_devices[] __initdata = {
+
+ static int __init tepla_init(void)
+ {
+- printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
++ printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ return platform_add_devices(tepla_devices, ARRAY_SIZE(tepla_devices));
+ }
+
+diff --git a/arch/blackfin/mach-bf561/dma.c b/arch/blackfin/mach-bf561/dma.c
+index 89c65bb..24415eb 100644
+--- a/arch/blackfin/mach-bf561/dma.c
++++ b/arch/blackfin/mach-bf561/dma.c
+@@ -26,10 +26,12 @@
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
++#include <linux/module.h>
++
+ #include <asm/blackfin.h>
+ #include <asm/dma.h>
+
+-struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
++struct dma_register *dma_io_base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ (struct dma_register *) DMA1_0_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_1_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_2_NEXT_DESC_PTR,
+@@ -67,6 +69,7 @@ struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ (struct dma_register *) IMDMA_D1_NEXT_DESC_PTR,
+ (struct dma_register *) IMDMA_S1_NEXT_DESC_PTR,
+ };
++EXPORT_SYMBOL(dma_io_base_addr);
+
+ int channel2irq(unsigned int channel)
+ {
+diff --git a/arch/blackfin/mach-bf561/head.S b/arch/blackfin/mach-bf561/head.S
+index 96a3d45..5b8bd40 100644
+--- a/arch/blackfin/mach-bf561/head.S
++++ b/arch/blackfin/mach-bf561/head.S
+@@ -37,9 +37,6 @@
+ #include <asm/mach/mem_init.h>
+ #endif
+
+-.global __rambase
+-.global __ramstart
+-.global __ramend
+ .extern ___bss_stop
+ .extern ___bss_start
+ .extern _bf53x_relocate_l1_mem
+@@ -139,26 +136,26 @@ ENTRY(__start)
+
+ /* Initialise UART - when booting from u-boot, the UART is not disabled
+ * so if we dont initalize here, our serial console gets hosed */
+- p0.h = hi(UART_LCR);
+- p0.l = lo(UART_LCR);
++ p0.h = hi(BFIN_UART_LCR);
++ p0.l = lo(BFIN_UART_LCR);
+ r0 = 0x0(Z);
+ w[p0] = r0.L; /* To enable DLL writes */
+ ssync;
+
+- p0.h = hi(UART_DLL);
+- p0.l = lo(UART_DLL);
++ p0.h = hi(BFIN_UART_DLL);
++ p0.l = lo(BFIN_UART_DLL);
+ r0 = 0x0(Z);
+ w[p0] = r0.L;
+ ssync;
+
+- p0.h = hi(UART_DLH);
+- p0.l = lo(UART_DLH);
++ p0.h = hi(BFIN_UART_DLH);
++ p0.l = lo(BFIN_UART_DLH);
+ r0 = 0x00(Z);
+ w[p0] = r0.L;
+ ssync;
+
+- p0.h = hi(UART_GCTL);
+- p0.l = lo(UART_GCTL);
++ p0.h = hi(BFIN_UART_GCTL);
++ p0.l = lo(BFIN_UART_GCTL);
+ r0 = 0x0(Z);
+ w[p0] = r0.L; /* To enable UART clock */
+ ssync;
+@@ -411,18 +408,3 @@ ENTRY(_start_dma_code)
+ RTS;
+ ENDPROC(_start_dma_code)
+ #endif /* CONFIG_BFIN_KERNEL_CLOCK */
+-
+-.data
+-
+-/*
+- * Set up the usable of RAM stuff. Size of RAM is determined then
+- * an initial stack set up at the end.
+- */
+-
+-.align 4
+-__rambase:
+-.long 0
+-__ramstart:
+-.long 0
+-__ramend:
+-.long 0
+diff --git a/arch/blackfin/mach-common/Makefile b/arch/blackfin/mach-common/Makefile
+index 15e33ca..393081e 100644
+--- a/arch/blackfin/mach-common/Makefile
++++ b/arch/blackfin/mach-common/Makefile
+@@ -6,4 +6,5 @@ obj-y := \
+ cache.o cacheinit.o entry.o \
+ interrupt.o lock.o irqpanic.o arch_checks.o ints-priority.o
+
+-obj-$(CONFIG_PM) += pm.o dpmc.o
++obj-$(CONFIG_PM) += pm.o dpmc.o
++obj-$(CONFIG_CPU_FREQ) += cpufreq.o
+diff --git a/arch/blackfin/mach-common/arch_checks.c b/arch/blackfin/mach-common/arch_checks.c
+index 2f6ce39..caaab49 100644
+--- a/arch/blackfin/mach-common/arch_checks.c
++++ b/arch/blackfin/mach-common/arch_checks.c
+@@ -54,7 +54,8 @@
+
+ #endif /* CONFIG_BFIN_KERNEL_CLOCK */
+
++#ifdef CONFIG_MEM_SIZE
+ #if (CONFIG_MEM_SIZE % 4)
+ #error "SDRAM mem size must be multible of 4MB"
+ #endif
+-
++#endif
+diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c
+new file mode 100644
+index 0000000..ed81e00
+--- /dev/null
++++ b/arch/blackfin/mach-common/cpufreq.c
+@@ -0,0 +1,194 @@
++/*
++ * File: arch/blackfin/mach-common/cpufreq.c
++ * Based on:
++ * Author:
++ *
++ * Created:
++ * Description: Blackfin core clock scaling
++ *
++ * Modified:
++ * Copyright 2004-2008 Analog Devices Inc.
++ *
++ * Bugs: Enter bugs at http://blackfin.uclinux.org/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (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, see the file COPYING, or write
++ * to the Free Software Foundation, Inc.,
++ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/init.h>
++#include <linux/cpufreq.h>
++#include <linux/fs.h>
++#include <asm/blackfin.h>
++#include <asm/time.h>
++
++
++/* this is the table of CCLK frequencies, in Hz */
++/* .index is the entry in the auxillary dpm_state_table[] */
++static struct cpufreq_frequency_table bfin_freq_table[] = {
++ {
++ .frequency = CPUFREQ_TABLE_END,
++ .index = 0,
++ },
++ {
++ .frequency = CPUFREQ_TABLE_END,
++ .index = 1,
++ },
++ {
++ .frequency = CPUFREQ_TABLE_END,
++ .index = 2,
++ },
++ {
++ .frequency = CPUFREQ_TABLE_END,
++ .index = 0,
++ },
++};
++
++static struct bfin_dpm_state {
++ unsigned int csel; /* system clock divider */
++ unsigned int tscale; /* change the divider on the core timer interrupt */
++} dpm_state_table[3];
++
++/**************************************************************************/
++
++static unsigned int bfin_getfreq(unsigned int cpu)
++{
++ /* The driver only support single cpu */
++ if (cpu != 0)
++ return -1;
++
++ return get_cclk();
++}
++
++
++static int bfin_target(struct cpufreq_policy *policy,
++ unsigned int target_freq, unsigned int relation)
++{
++ unsigned int index, plldiv, tscale;
++ unsigned long flags, cclk_hz;
++ struct cpufreq_freqs freqs;
++
++ if (cpufreq_frequency_table_target(policy, bfin_freq_table,
++ target_freq, relation, &index))
++ return -EINVAL;
++
++ cclk_hz = bfin_freq_table[index].frequency;
++
++ freqs.old = bfin_getfreq(0);
++ freqs.new = cclk_hz;
++ freqs.cpu = 0;
++
++ pr_debug("cpufreq: changing cclk to %lu; target = %u, oldfreq = %u\n",
++ cclk_hz, target_freq, freqs.old);
++
++ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
++ local_irq_save(flags);
++ plldiv = (bfin_read_PLL_DIV() & SSEL) | dpm_state_table[index].csel;
++ tscale = dpm_state_table[index].tscale;
++ bfin_write_PLL_DIV(plldiv);
++ /* we have to adjust the core timer, because it is using cclk */
++ bfin_write_TSCALE(tscale);
++ SSYNC();
++ local_irq_restore(flags);
++ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
++
++ return 0;
++}
++
++static int bfin_verify_speed(struct cpufreq_policy *policy)
++{
++ return cpufreq_frequency_table_verify(policy, bfin_freq_table);
++}
++
++static int __init __bfin_cpu_init(struct cpufreq_policy *policy)
++{
++
++ unsigned long cclk, sclk, csel, min_cclk;
++ int index;
++
++#ifdef CONFIG_CYCLES_CLOCKSOURCE
++/*
++ * Clocksource CYCLES is still CONTINUOUS but not longer MONOTONIC in case we enable
++ * CPU frequency scaling, since CYCLES runs off Core Clock.
++ */
++ printk(KERN_WARNING "CPU frequency scaling not supported: Clocksource not suitable\n"
++ return -ENODEV;
++#endif
++
++ if (policy->cpu != 0)
++ return -EINVAL;
++
++ cclk = get_cclk();
++ sclk = get_sclk();
++
++#if ANOMALY_05000273
++ min_cclk = sclk * 2;
++#else
++ min_cclk = sclk;
++#endif
++ csel = ((bfin_read_PLL_DIV() & CSEL) >> 4);
++
++ for (index = 0; (cclk >> index) >= min_cclk && csel <= 3; index++, csel++) {
++ bfin_freq_table[index].frequency = cclk >> index;
++ dpm_state_table[index].csel = csel << 4; /* Shift now into PLL_DIV bitpos */
++ dpm_state_table[index].tscale = (TIME_SCALE / (1 << csel)) - 1;
++
++ pr_debug("cpufreq: freq:%d csel:%d tscale:%d\n",
++ bfin_freq_table[index].frequency,
++ dpm_state_table[index].csel,
++ dpm_state_table[index].tscale);
++ }
++
++ policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
++
++ policy->cpuinfo.transition_latency = (bfin_read_PLL_LOCKCNT() / (sclk / 1000000)) * 1000;
++ /*Now ,only support one cpu */
++ policy->cur = cclk;
++ cpufreq_frequency_table_get_attr(bfin_freq_table, policy->cpu);
++ return cpufreq_frequency_table_cpuinfo(policy, bfin_freq_table);
++}
++
++static struct freq_attr *bfin_freq_attr[] = {
++ &cpufreq_freq_attr_scaling_available_freqs,
++ NULL,
++};
++
++static struct cpufreq_driver bfin_driver = {
++ .verify = bfin_verify_speed,
++ .target = bfin_target,
++ .get = bfin_getfreq,
++ .init = __bfin_cpu_init,
++ .name = "bfin cpufreq",
++ .owner = THIS_MODULE,
++ .attr = bfin_freq_attr,
++};
++
++static int __init bfin_cpu_init(void)
++{
++ return cpufreq_register_driver(&bfin_driver);
++}
++
++static void __exit bfin_cpu_exit(void)
++{
++ cpufreq_unregister_driver(&bfin_driver);
++}
++
++MODULE_AUTHOR("Michael Hennerich <hennerich at blackfin.uclinux.org>");
++MODULE_DESCRIPTION("cpufreq driver for Blackfin");
++MODULE_LICENSE("GPL");
++
++module_init(bfin_cpu_init);
++module_exit(bfin_cpu_exit);
+diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
+index cee54ce..f2fb87e 100644
+--- a/arch/blackfin/mach-common/entry.S
++++ b/arch/blackfin/mach-common/entry.S
+@@ -38,6 +38,7 @@
+ #include <linux/unistd.h>
+ #include <asm/blackfin.h>
+ #include <asm/errno.h>
++#include <asm/fixed_code.h>
+ #include <asm/thread_info.h> /* TIF_NEED_RESCHED */
+ #include <asm/asm-offsets.h>
+ #include <asm/trace.h>
+@@ -52,15 +53,6 @@
+ # define EX_SCRATCH_REG CYCLES
+ #endif
+
+-#if ANOMALY_05000281
+-ENTRY(_safe_speculative_execution)
+- NOP;
+- NOP;
+- NOP;
+- jump _safe_speculative_execution;
+-ENDPROC(_safe_speculative_execution)
+-#endif
+-
+ #ifdef CONFIG_EXCPT_IRQ_SYSC_L1
+ .section .l1.text
+ #else
+@@ -121,10 +113,14 @@ ENTRY(_ex_icplb_miss)
+ (R7:6,P5:4) = [sp++];
+ ASTAT = [sp++];
+ SAVE_ALL_SYS
+- DEBUG_HWTRACE_SAVE(p5, r7)
+ #ifdef CONFIG_MPU
++ /* We must load R1 here, _before_ DEBUG_HWTRACE_SAVE, since that
++ * will change the stack pointer. */
+ R0 = SEQSTAT;
+ R1 = SP;
++#endif
++ DEBUG_HWTRACE_SAVE(p5, r7)
++#ifdef CONFIG_MPU
+ sp += -12;
+ call _cplb_hdr;
+ sp += 12;
+@@ -191,6 +187,7 @@ ENTRY(_bfin_return_from_exception)
+ ENDPROC(_bfin_return_from_exception)
+
+ ENTRY(_handle_bad_cplb)
++ DEBUG_HWTRACE_RESTORE(p5, r7)
+ /* To get here, we just tried and failed to change a CPLB
+ * so, handle things in trap_c (C code), by lowering to
+ * IRQ5, just like we normally do. Since this is not a
+@@ -225,6 +222,26 @@ ENTRY(_ex_trap_c)
+ [p4] = p5;
+ csync;
+
++ p4.l = lo(DCPLB_FAULT_ADDR);
++ p4.h = hi(DCPLB_FAULT_ADDR);
++ r7 = [p4];
++ p5.h = _saved_dcplb_fault_addr;
++ p5.l = _saved_dcplb_fault_addr;
++ [p5] = r7;
++
++ r7 = [p4 + (ICPLB_FAULT_ADDR - DCPLB_FAULT_ADDR)];
++ p5.h = _saved_icplb_fault_addr;
++ p5.l = _saved_icplb_fault_addr;
++ [p5] = r7;
++
++ p4.l = __retx;
++ p4.h = __retx;
++ r6 = retx;
++ [p4] = r6;
++ p4.l = lo(SAFE_USER_INSTRUCTION);
++ p4.h = hi(SAFE_USER_INSTRUCTION);
++ retx = p4;
++
+ /* Disable all interrupts, but make sure level 5 is enabled so
+ * we can switch to that level. Save the old mask. */
+ cli r6;
+@@ -234,23 +251,6 @@ ENTRY(_ex_trap_c)
+ r6 = 0x3f;
+ sti r6;
+
+- /* Save the excause into a circular buffer, in case the instruction
+- * which caused this excecptions causes others.
+- */
+- P5.l = _in_ptr_excause;
+- P5.h = _in_ptr_excause;
+- R7 = [P5];
+- R7 += 4;
+- R6 = 0xF;
+- R7 = R7 & R6;
+- [P5] = R7;
+- R6.l = _excause_circ_buf;
+- R6.h = _excause_circ_buf;
+- R7 = R7 + R6;
+- p5 = R7;
+- R6 = SEQSTAT;
+- [P5] = R6;
+-
+ (R7:6,P5:4) = [sp++];
+ ASTAT = [sp++];
+ SP = EX_SCRATCH_REG;
+@@ -307,6 +307,11 @@ ENDPROC(_double_fault)
+ ENTRY(_exception_to_level5)
+ SAVE_ALL_SYS
+
++ p4.l = __retx;
++ p4.h = __retx;
++ r6 = [p4];
++ [sp + PT_PC] = r6;
++
+ /* Restore interrupt mask. We haven't pushed RETI, so this
+ * doesn't enable interrupts until we return from this handler. */
+ p4.l = _excpt_saved_imask;
+@@ -328,42 +333,11 @@ ENTRY(_exception_to_level5)
+ r0 = [p2]; /* Read current IPEND */
+ [sp + PT_IPEND] = r0; /* Store IPEND */
+
+- /* Pop the excause from the circular buffer and push it on the stack
+- * (in the right place - if you change the location of SEQSTAT, you
+- * must change this offset.
+- */
+-.L_excep_to_5_again:
+- P5.l = _out_ptr_excause;
+- P5.h = _out_ptr_excause;
+- R7 = [P5];
+- R7 += 4;
+- R6 = 0xF;
+- R7 = R7 & R6;
+- [P5] = R7;
+- R6.l = _excause_circ_buf;
+- R6.h = _excause_circ_buf;
+- R7 = R7 + R6;
+- P5 = R7;
+- R1 = [P5];
+- [SP + PT_SEQSTAT] = r1;
+-
+ r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */
+ SP += -12;
+ call _trap_c;
+ SP += 12;
+
+- /* See if anything else is in the exception buffer
+- * if there is, process it
+- */
+- P5.l = _out_ptr_excause;
+- P5.h = _out_ptr_excause;
+- P4.l = _in_ptr_excause;
+- P4.h = _in_ptr_excause;
+- R6 = [P5];
+- R7 = [P4];
+- CC = R6 == R7;
+- if ! CC JUMP .L_excep_to_5_again
+-
+ call _ret_from_exception;
+ RESTORE_ALL_SYS
+ rti;
+@@ -727,8 +701,8 @@ ENTRY(_return_from_int)
+ [p0] = p1;
+ csync;
+ #if ANOMALY_05000281
+- r0.l = _safe_speculative_execution;
+- r0.h = _safe_speculative_execution;
++ r0.l = lo(SAFE_USER_INSTRUCTION);
++ r0.h = hi(SAFE_USER_INSTRUCTION);
+ reti = r0;
+ #endif
+ r0 = 0x801f (z);
+@@ -741,8 +715,8 @@ ENDPROC(_return_from_int)
+
+ ENTRY(_lower_to_irq14)
+ #if ANOMALY_05000281
+- r0.l = _safe_speculative_execution;
+- r0.h = _safe_speculative_execution;
++ r0.l = lo(SAFE_USER_INSTRUCTION);
++ r0.h = hi(SAFE_USER_INSTRUCTION);
+ reti = r0;
+ #endif
+ r0 = 0x401f;
+@@ -809,20 +783,6 @@ _schedule_and_signal:
+ rti;
+ ENDPROC(_lower_to_irq14)
+
+-/* Make sure when we start, that the circular buffer is initialized properly
+- * R0 and P0 are call clobbered, so we can use them here.
+- */
+-ENTRY(_init_exception_buff)
+- r0 = 0;
+- p0.h = _in_ptr_excause;
+- p0.l = _in_ptr_excause;
+- [p0] = r0;
+- p0.h = _out_ptr_excause;
+- p0.l = _out_ptr_excause;
+- [p0] = r0;
+- rts;
+-ENDPROC(_init_exception_buff)
+-
+ /* We handle this 100% in exception space - to reduce overhead
+ * Only potiential problem is if the software buffer gets swapped out of the
+ * CPLB table - then double fault. - so we don't let this happen in other places
+@@ -1398,17 +1358,7 @@ _exception_stack_top:
+ _last_cplb_fault_retx:
+ .long 0;
+ #endif
+-/*
+- * Single instructions can have multiple faults, which need to be
+- * handled by traps.c, in irq5. We store the exception cause to ensure
+- * we don't miss a double fault condition
+- */
+-ENTRY(_in_ptr_excause)
++ /* Used to save the real RETX when temporarily storing a safe
++ * return address. */
++__retx:
+ .long 0;
+-ENTRY(_out_ptr_excause)
+- .long 0;
+-ALIGN
+-ENTRY(_excause_circ_buf)
+- .rept 4
+- .long 0
+- .endr
+diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c
+index 225ef14..f5fd768 100644
+--- a/arch/blackfin/mach-common/ints-priority.c
++++ b/arch/blackfin/mach-common/ints-priority.c
+@@ -316,7 +316,7 @@ static void bfin_demux_error_irq(unsigned int int_err_irq,
+ printk(KERN_ERR
+ "%s : %s : LINE %d :\nIRQ ?: PERIPHERAL ERROR"
+ " INTERRUPT ASSERTED BUT NO SOURCE FOUND\n",
+- __FUNCTION__, __FILE__, __LINE__);
++ __func__, __FILE__, __LINE__);
+
+ }
+ #endif /* BF537_GENERIC_ERROR_INT_DEMUX */
+@@ -326,6 +326,7 @@ static void bfin_demux_error_irq(unsigned int int_err_irq,
+ static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)];
+ static unsigned short gpio_edge_triggered[gpio_bank(MAX_BLACKFIN_GPIOS)];
+
++extern void bfin_gpio_irq_prepare(unsigned gpio);
+
+ static void bfin_gpio_ack_irq(unsigned int irq)
+ {
+@@ -364,35 +365,25 @@ static void bfin_gpio_unmask_irq(unsigned int irq)
+
+ static unsigned int bfin_gpio_irq_startup(unsigned int irq)
+ {
+- unsigned int ret;
+ u16 gpionr = irq - IRQ_PF0;
+- char buf[8];
+
+- if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
+- snprintf(buf, sizeof buf, "IRQ %d", irq);
+- ret = gpio_request(gpionr, buf);
+- if (ret)
+- return ret;
+- }
++ if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)))
++ bfin_gpio_irq_prepare(gpionr);
+
+ gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
+ bfin_gpio_unmask_irq(irq);
+
+- return ret;
++ return 0;
+ }
+
+ static void bfin_gpio_irq_shutdown(unsigned int irq)
+ {
+ bfin_gpio_mask_irq(irq);
+- gpio_free(irq - IRQ_PF0);
+ gpio_enabled[gpio_bank(irq - IRQ_PF0)] &= ~gpio_bit(irq - IRQ_PF0);
+ }
+
+ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
+ {
+-
+- unsigned int ret;
+- char buf[8];
+ u16 gpionr = irq - IRQ_PF0;
+
+ if (type == IRQ_TYPE_PROBE) {
+@@ -404,12 +395,8 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
+
+ if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
+ IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
+- if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
+- snprintf(buf, sizeof buf, "IRQ %d", irq);
+- ret = gpio_request(gpionr, buf);
+- if (ret)
+- return ret;
+- }
++ if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)))
++ bfin_gpio_irq_prepare(gpionr);
+
+ gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
+ } else {
+@@ -595,6 +582,8 @@ static struct pin_int_t *pint[NR_PINT_SYS_IRQS] = {
+ (struct pin_int_t *)PINT3_MASK_SET,
+ };
+
++extern void bfin_gpio_irq_prepare(unsigned gpio);
++
+ inline unsigned short get_irq_base(u8 bank, u8 bmap)
+ {
+
+@@ -697,8 +686,6 @@ static void bfin_gpio_unmask_irq(unsigned int irq)
+
+ static unsigned int bfin_gpio_irq_startup(unsigned int irq)
+ {
+- unsigned int ret;
+- char buf[8];
+ u16 gpionr = irq_to_gpio(irq);
+ u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+
+@@ -709,17 +696,13 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq)
+ return -ENODEV;
+ }
+
+- if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
+- snprintf(buf, sizeof buf, "IRQ %d", irq);
+- ret = gpio_request(gpionr, buf);
+- if (ret)
+- return ret;
+- }
++ if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)))
++ bfin_gpio_irq_prepare(gpionr);
+
+ gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
+ bfin_gpio_unmask_irq(irq);
+
+- return ret;
++ return 0;
+ }
+
+ static void bfin_gpio_irq_shutdown(unsigned int irq)
+@@ -727,15 +710,12 @@ static void bfin_gpio_irq_shutdown(unsigned int irq)
+ u16 gpionr = irq_to_gpio(irq);
+
+ bfin_gpio_mask_irq(irq);
+- gpio_free(gpionr);
+ gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(gpionr);
+ }
+
+ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
+ {
+
+- unsigned int ret;
+- char buf[8];
+ u16 gpionr = irq_to_gpio(irq);
+ u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+ u32 pintbit = PINT_BIT(pint_val);
+@@ -753,12 +733,8 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
+
+ if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
+ IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
+- if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
+- snprintf(buf, sizeof buf, "IRQ %d", irq);
+- ret = gpio_request(gpionr, buf);
+- if (ret)
+- return ret;
+- }
++ if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)))
++ bfin_gpio_irq_prepare(gpionr);
+
+ gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
+ } else {
+@@ -766,8 +742,6 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
+ return 0;
+ }
+
+- gpio_direction_input(gpionr);
+-
+ if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)))
+ pint[bank]->invert_set = pintbit; /* low or falling edge denoted by one */
+ else
+@@ -965,8 +939,6 @@ int __init init_arch_irq(void)
+
+ local_irq_disable();
+
+- init_exception_buff();
+-
+ #ifdef CONFIG_BF54x
+ # ifdef CONFIG_PINTx_REASSIGN
+ pint[0]->assign = CONFIG_PINT0_ASSIGN;
+diff --git a/arch/blackfin/mach-common/lock.S b/arch/blackfin/mach-common/lock.S
+index 28b87fe..30b887e 100644
+--- a/arch/blackfin/mach-common/lock.S
++++ b/arch/blackfin/mach-common/lock.S
+@@ -174,7 +174,7 @@ ENTRY(_cache_lock)
+ CLI R3;
+
+ R7 = [P1];
+- R2 = 0xFFFFFF87 (X);
++ R2 = ~(0x78) (X); /* mask out ILOC */
+ R7 = R7 & R2;
+ R0 = R0 << 3;
+ R7 = R0 | R7;
+diff --git a/arch/blackfin/mm/blackfin_sram.c b/arch/blackfin/mm/blackfin_sram.c
+index e41f0e8..3246f91 100644
+--- a/arch/blackfin/mm/blackfin_sram.c
++++ b/arch/blackfin/mm/blackfin_sram.c
+@@ -401,7 +401,7 @@ EXPORT_SYMBOL(l1_data_sram_free);
+
+ void *l1_inst_sram_alloc(size_t size)
+ {
+-#if L1_DATA_A_LENGTH != 0
++#if L1_CODE_LENGTH != 0
+ unsigned flags;
+ void *addr;
+
+diff --git a/arch/blackfin/oprofile/common.c b/arch/blackfin/oprofile/common.c
+index cb8b8d5..0f6d303 100644
+--- a/arch/blackfin/oprofile/common.c
++++ b/arch/blackfin/oprofile/common.c
+@@ -75,7 +75,7 @@ static int op_bfin_start(void)
+ {
+ int ret = -EBUSY;
+
+- printk(KERN_INFO "KSDBG:in %s\n", __FUNCTION__);
++ printk(KERN_INFO "KSDBG:in %s\n", __func__);
+ mutex_lock(&pfmon_lock);
+ if (!pfmon_enabled) {
+ ret = model->start(ctr);
+diff --git a/arch/blackfin/oprofile/op_model_bf533.c b/arch/blackfin/oprofile/op_model_bf533.c
+index 872dffe..d1c698b 100644
+--- a/arch/blackfin/oprofile/op_model_bf533.c
++++ b/arch/blackfin/oprofile/op_model_bf533.c
+@@ -125,7 +125,7 @@ int pm_overflow_handler(int irq, struct pt_regs *regs)
+ unsigned int pc, pfctl;
+ unsigned int count[2];
+
+- pr_debug("get interrupt in %s\n", __FUNCTION__);
++ pr_debug("get interrupt in %s\n", __func__);
+ if (oprofile_running == 0) {
+ pr_debug("error: entering interrupt when oprofile is stopped.\n\r");
+ return -1;
+diff --git a/arch/cris/kernel/Makefile b/arch/cris/kernel/Makefile
+index c8e8ea5..ee7bcd4 100644
+--- a/arch/cris/kernel/Makefile
++++ b/arch/cris/kernel/Makefile
+@@ -5,8 +5,7 @@
+
+ extra-y := vmlinux.lds
+
+-obj-y := process.o traps.o irq.o ptrace.o setup.o \
+- time.o sys_cris.o semaphore.o
++obj-y := process.o traps.o irq.o ptrace.o setup.o time.o sys_cris.o
+
+ obj-$(CONFIG_MODULES) += crisksyms.o
+ obj-$(CONFIG_MODULES) += module.o
+diff --git a/arch/cris/kernel/crisksyms.c b/arch/cris/kernel/crisksyms.c
+index 62f0e75..7ac000f 100644
+--- a/arch/cris/kernel/crisksyms.c
++++ b/arch/cris/kernel/crisksyms.c
+@@ -9,7 +9,6 @@
+ #include <linux/string.h>
+ #include <linux/tty.h>
+
+-#include <asm/semaphore.h>
+ #include <asm/processor.h>
+ #include <asm/uaccess.h>
+ #include <asm/checksum.h>
+@@ -49,12 +48,6 @@ EXPORT_SYMBOL(__negdi2);
+ EXPORT_SYMBOL(__ioremap);
+ EXPORT_SYMBOL(iounmap);
+
+-/* Semaphore functions */
+-EXPORT_SYMBOL(__up);
+-EXPORT_SYMBOL(__down);
+-EXPORT_SYMBOL(__down_interruptible);
+-EXPORT_SYMBOL(__down_trylock);
+-
+ /* Userspace access functions */
+ EXPORT_SYMBOL(__copy_user_zeroing);
+ EXPORT_SYMBOL(__copy_user);
+diff --git a/arch/cris/kernel/semaphore.c b/arch/cris/kernel/semaphore.c
+deleted file mode 100644
+index f137a43..0000000
+--- a/arch/cris/kernel/semaphore.c
++++ /dev/null
+@@ -1,129 +0,0 @@
+-/*
+- * Generic semaphore code. Buyer beware. Do your own
+- * specific changes in <asm/semaphore-helper.h>
+- */
+-
+-#include <linux/sched.h>
+-#include <asm/semaphore-helper.h>
+-
+-/*
+- * Semaphores are implemented using a two-way counter:
+- * The "count" variable is decremented for each process
+- * that tries to sleep, while the "waking" variable is
+- * incremented when the "up()" code goes to wake up waiting
+- * processes.
+- *
+- * Notably, the inline "up()" and "down()" functions can
+- * efficiently test if they need to do any extra work (up
+- * needs to do something only if count was negative before
+- * the increment operation.
+- *
+- * waking_non_zero() (from asm/semaphore.h) must execute
+- * atomically.
+- *
+- * When __up() is called, the count was negative before
+- * incrementing it, and we need to wake up somebody.
+- *
+- * This routine adds one to the count of processes that need to
+- * wake up and exit. ALL waiting processes actually wake up but
+- * only the one that gets to the "waking" field first will gate
+- * through and acquire the semaphore. The others will go back
+- * to sleep.
+- *
+- * Note that these functions are only called when there is
+- * contention on the lock, and as such all this is the
+- * "non-critical" part of the whole semaphore business. The
+- * critical part is the inline stuff in <asm/semaphore.h>
+- * where we want to avoid any extra jumps and calls.
+- */
+-void __up(struct semaphore *sem)
+-{
+- wake_one_more(sem);
+- wake_up(&sem->wait);
+-}
+-
+-/*
+- * Perform the "down" function. Return zero for semaphore acquired,
+- * return negative for signalled out of the function.
+- *
+- * If called from __down, the return is ignored and the wait loop is
+- * not interruptible. This means that a task waiting on a semaphore
+- * using "down()" cannot be killed until someone does an "up()" on
+- * the semaphore.
+- *
+- * If called from __down_interruptible, the return value gets checked
+- * upon return. If the return value is negative then the task continues
+- * with the negative value in the return register (it can be tested by
+- * the caller).
+- *
+- * Either form may be used in conjunction with "up()".
+- *
+- */
+-
+-#define DOWN_VAR \
+- struct task_struct *tsk = current; \
+- wait_queue_t wait; \
+- init_waitqueue_entry(&wait, tsk);
+-
+-#define DOWN_HEAD(task_state) \
+- \
+- \
+- tsk->state = (task_state); \
+- add_wait_queue(&sem->wait, &wait); \
+- \
+- /* \
+- * Ok, we're set up. sem->count is known to be less than zero \
+- * so we must wait. \
+- * \
+- * We can let go the lock for purposes of waiting. \
+- * We re-acquire it after awaking so as to protect \
+- * all semaphore operations. \
+- * \
+- * If "up()" is called before we call waking_non_zero() then \
+- * we will catch it right away. If it is called later then \
+- * we will have to go through a wakeup cycle to catch it. \
+- * \
+- * Multiple waiters contend for the semaphore lock to see \
+- * who gets to gate through and who has to wait some more. \
+- */ \
+- for (;;) {
+-
+-#define DOWN_TAIL(task_state) \
+- tsk->state = (task_state); \
+- } \
+- tsk->state = TASK_RUNNING; \
+- remove_wait_queue(&sem->wait, &wait);
+-
+-void __sched __down(struct semaphore * sem)
+-{
+- DOWN_VAR
+- DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+- if (waking_non_zero(sem))
+- break;
+- schedule();
+- DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+-}
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+- int ret = 0;
+- DOWN_VAR
+- DOWN_HEAD(TASK_INTERRUPTIBLE)
+-
+- ret = waking_non_zero_interruptible(sem, tsk);
+- if (ret)
+- {
+- if (ret == 1)
+- /* ret != 0 only if we get interrupted -arca */
+- ret = 0;
+- break;
+- }
+- schedule();
+- DOWN_TAIL(TASK_INTERRUPTIBLE)
+- return ret;
+-}
+-
+-int __down_trylock(struct semaphore * sem)
+-{
+- return waking_non_zero_trylock(sem);
+-}
+diff --git a/arch/frv/kernel/Makefile b/arch/frv/kernel/Makefile
+index e8f73ed..c36f70b 100644
+--- a/arch/frv/kernel/Makefile
++++ b/arch/frv/kernel/Makefile
+@@ -9,7 +9,7 @@ extra-y:= head.o init_task.o vmlinux.lds
+
+ obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o kernel_thread.o \
+ kernel_execve.o process.o traps.o ptrace.o signal.o dma.o \
+- sys_frv.o time.o semaphore.o setup.o frv_ksyms.o \
++ sys_frv.o time.o setup.o frv_ksyms.o \
+ debug-stub.o irq.o sleep.o uaccess.o
+
+ obj-$(CONFIG_GDBSTUB) += gdb-stub.o gdb-io.o
+diff --git a/arch/frv/kernel/frv_ksyms.c b/arch/frv/kernel/frv_ksyms.c
+index f772704..0316b3c 100644
+--- a/arch/frv/kernel/frv_ksyms.c
++++ b/arch/frv/kernel/frv_ksyms.c
+@@ -12,7 +12,6 @@
+ #include <asm/pgalloc.h>
+ #include <asm/irq.h>
+ #include <asm/io.h>
+-#include <asm/semaphore.h>
+ #include <asm/checksum.h>
+ #include <asm/hardirq.h>
+ #include <asm/cacheflush.h>
+diff --git a/arch/frv/kernel/semaphore.c b/arch/frv/kernel/semaphore.c
+deleted file mode 100644
+index 7ee3a14..0000000
+--- a/arch/frv/kernel/semaphore.c
++++ /dev/null
+@@ -1,155 +0,0 @@
+-/* semaphore.c: FR-V semaphores
+- *
+- * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+- * Written by David Howells (dhowells at redhat.com)
+- * - Derived from lib/rwsem-spinlock.c
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/module.h>
+-#include <asm/semaphore.h>
+-
+-struct sem_waiter {
+- struct list_head list;
+- struct task_struct *task;
+-};
+-
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+-void semtrace(struct semaphore *sem, const char *str)
+-{
+- if (sem->debug)
+- printk("[%d] %s({%d,%d})\n",
+- current->pid,
+- str,
+- sem->counter,
+- list_empty(&sem->wait_list) ? 0 : 1);
+-}
+-#else
+-#define semtrace(SEM,STR) do { } while(0)
+-#endif
+-
+-/*
+- * wait for a token to be granted from a semaphore
+- * - entered with lock held and interrupts disabled
+- */
+-void __down(struct semaphore *sem, unsigned long flags)
+-{
+- struct task_struct *tsk = current;
+- struct sem_waiter waiter;
+-
+- semtrace(sem, "Entering __down");
+-
+- /* set up my own style of waitqueue */
+- waiter.task = tsk;
+- get_task_struct(tsk);
+-
+- list_add_tail(&waiter.list, &sem->wait_list);
+-
+- /* we don't need to touch the semaphore struct anymore */
+- spin_unlock_irqrestore(&sem->wait_lock, flags);
+-
+- /* wait to be given the semaphore */
+- set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+-
+- for (;;) {
+- if (list_empty(&waiter.list))
+- break;
+- schedule();
+- set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+- }
+-
+- tsk->state = TASK_RUNNING;
+- semtrace(sem, "Leaving __down");
+-}
+-
+-EXPORT_SYMBOL(__down);
+-
+-/*
+- * interruptibly wait for a token to be granted from a semaphore
+- * - entered with lock held and interrupts disabled
+- */
+-int __down_interruptible(struct semaphore *sem, unsigned long flags)
+-{
+- struct task_struct *tsk = current;
+- struct sem_waiter waiter;
+- int ret;
+-
+- semtrace(sem,"Entering __down_interruptible");
+-
+- /* set up my own style of waitqueue */
+- waiter.task = tsk;
+- get_task_struct(tsk);
+-
+- list_add_tail(&waiter.list, &sem->wait_list);
+-
+- /* we don't need to touch the semaphore struct anymore */
+- set_task_state(tsk, TASK_INTERRUPTIBLE);
+-
+- spin_unlock_irqrestore(&sem->wait_lock, flags);
+-
+- /* wait to be given the semaphore */
+- ret = 0;
+- for (;;) {
+- if (list_empty(&waiter.list))
+- break;
+- if (unlikely(signal_pending(current)))
+- goto interrupted;
+- schedule();
+- set_task_state(tsk, TASK_INTERRUPTIBLE);
+- }
+-
+- out:
+- tsk->state = TASK_RUNNING;
+- semtrace(sem, "Leaving __down_interruptible");
+- return ret;
+-
+- interrupted:
+- spin_lock_irqsave(&sem->wait_lock, flags);
+-
+- if (!list_empty(&waiter.list)) {
+- list_del(&waiter.list);
+- ret = -EINTR;
+- }
+-
+- spin_unlock_irqrestore(&sem->wait_lock, flags);
+- if (ret == -EINTR)
+- put_task_struct(current);
+- goto out;
+-}
+-
+-EXPORT_SYMBOL(__down_interruptible);
+-
+-/*
+- * release a single token back to a semaphore
+- * - entered with lock held and interrupts disabled
+- */
+-void __up(struct semaphore *sem)
+-{
+- struct task_struct *tsk;
+- struct sem_waiter *waiter;
+-
+- semtrace(sem,"Entering __up");
+-
+- /* grant the token to the process at the front of the queue */
+- waiter = list_entry(sem->wait_list.next, struct sem_waiter, list);
+-
+- /* We must be careful not to touch 'waiter' after we set ->task = NULL.
+- * It is allocated on the waiter's stack and may become invalid at
+- * any time after that point (due to a wakeup from another source).
+- */
+- list_del_init(&waiter->list);
+- tsk = waiter->task;
+- mb();
+- waiter->task = NULL;
+- wake_up_process(tsk);
+- put_task_struct(tsk);
+-
+- semtrace(sem,"Leaving __up");
+-}
+-
+-EXPORT_SYMBOL(__up);
+diff --git a/arch/frv/mb93090-mb00/pci-frv.h b/arch/frv/mb93090-mb00/pci-frv.h
+index 7481797..0c7bf39 100644
+--- a/arch/frv/mb93090-mb00/pci-frv.h
++++ b/arch/frv/mb93090-mb00/pci-frv.h
+@@ -17,8 +17,6 @@
+ #define PCI_PROBE_BIOS 0x0001
+ #define PCI_PROBE_CONF1 0x0002
+ #define PCI_PROBE_CONF2 0x0004
+-#define PCI_NO_SORT 0x0100
+-#define PCI_BIOS_SORT 0x0200
+ #define PCI_NO_CHECKS 0x0400
+ #define PCI_ASSIGN_ROMS 0x1000
+ #define PCI_BIOS_IRQ_SCAN 0x2000
+diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c
+index 6d51f13..f003cfa 100644
+--- a/arch/frv/mb93090-mb00/pci-vdk.c
++++ b/arch/frv/mb93090-mb00/pci-vdk.c
+@@ -199,58 +199,6 @@ static struct pci_ops * __init pci_check_direct(void)
+ }
+
+ /*
+- * Several buggy motherboards address only 16 devices and mirror
+- * them to next 16 IDs. We try to detect this `feature' on all
+- * primary buses (those containing host bridges as they are
+- * expected to be unique) and remove the ghost devices.
+- */
+-
+-static void __init pcibios_fixup_ghosts(struct pci_bus *b)
+-{
+- struct list_head *ln, *mn;
+- struct pci_dev *d, *e;
+- int mirror = PCI_DEVFN(16,0);
+- int seen_host_bridge = 0;
+- int i;
+-
+- for (ln=b->devices.next; ln != &b->devices; ln=ln->next) {
+- d = pci_dev_b(ln);
+- if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST)
+- seen_host_bridge++;
+- for (mn=ln->next; mn != &b->devices; mn=mn->next) {
+- e = pci_dev_b(mn);
+- if (e->devfn != d->devfn + mirror ||
+- e->vendor != d->vendor ||
+- e->device != d->device ||
+- e->class != d->class)
+- continue;
+- for(i=0; i<PCI_NUM_RESOURCES; i++)
+- if (e->resource[i].start != d->resource[i].start ||
+- e->resource[i].end != d->resource[i].end ||
+- e->resource[i].flags != d->resource[i].flags)
+- continue;
+- break;
+- }
+- if (mn == &b->devices)
+- return;
+- }
+- if (!seen_host_bridge)
+- return;
+- printk("PCI: Ignoring ghost devices on bus %02x\n", b->number);
+-
+- ln = &b->devices;
+- while (ln->next != &b->devices) {
+- d = pci_dev_b(ln->next);
+- if (d->devfn >= mirror) {
+- list_del(&d->global_list);
+- list_del(&d->bus_list);
+- kfree(d);
+- } else
+- ln = ln->next;
+- }
+-}
+-
+-/*
+ * Discover remaining PCI buses in case there are peer host bridges.
+ * We use the number of last PCI bus provided by the PCI BIOS.
+ */
+@@ -356,7 +304,6 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
+ #if 0
+ printk("### PCIBIOS_FIXUP_BUS(%d)\n",bus->number);
+ #endif
+- pcibios_fixup_ghosts(bus);
+ pci_read_bridge_bases(bus);
+
+ if (bus->number == 0) {
+diff --git a/arch/frv/mm/highmem.c b/arch/frv/mm/highmem.c
+index 7f77db7..eadd076 100644
+--- a/arch/frv/mm/highmem.c
++++ b/arch/frv/mm/highmem.c
+@@ -36,6 +36,3 @@ struct page *kmap_atomic_to_page(void *ptr)
+ {
+ return virt_to_page(ptr);
+ }
+-
+-
+-EXPORT_SYMBOL(kmap_atomic_to_page);
+diff --git a/arch/h8300/kernel/Makefile b/arch/h8300/kernel/Makefile
+index 874f6ae..6c248c3 100644
+--- a/arch/h8300/kernel/Makefile
++++ b/arch/h8300/kernel/Makefile
+@@ -5,7 +5,7 @@
+ extra-y := vmlinux.lds
+
+ obj-y := process.o traps.o ptrace.o irq.o \
+- sys_h8300.o time.o semaphore.o signal.o \
++ sys_h8300.o time.o signal.o \
+ setup.o gpio.o init_task.o syscalls.o \
+ entry.o
+
+diff --git a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c
+index d1b1526..6866bd9 100644
+--- a/arch/h8300/kernel/h8300_ksyms.c
++++ b/arch/h8300/kernel/h8300_ksyms.c
+@@ -12,7 +12,6 @@
+ #include <asm/pgalloc.h>
+ #include <asm/irq.h>
+ #include <asm/io.h>
+-#include <asm/semaphore.h>
+ #include <asm/checksum.h>
+ #include <asm/current.h>
+ #include <asm/gpio.h>
+diff --git a/arch/h8300/kernel/semaphore.c b/arch/h8300/kernel/semaphore.c
+deleted file mode 100644
+index d12cbbf..0000000
+--- a/arch/h8300/kernel/semaphore.c
++++ /dev/null
+@@ -1,132 +0,0 @@
+-/*
+- * Generic semaphore code. Buyer beware. Do your own
+- * specific changes in <asm/semaphore-helper.h>
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/init.h>
+-#include <asm/semaphore-helper.h>
+-
+-#ifndef CONFIG_RMW_INSNS
+-spinlock_t semaphore_wake_lock;
+-#endif
+-
+-/*
+- * Semaphores are implemented using a two-way counter:
+- * The "count" variable is decremented for each process
+- * that tries to sleep, while the "waking" variable is
+- * incremented when the "up()" code goes to wake up waiting
+- * processes.
+- *
+- * Notably, the inline "up()" and "down()" functions can
+- * efficiently test if they need to do any extra work (up
+- * needs to do something only if count was negative before
+- * the increment operation.
+- *
+- * waking_non_zero() (from asm/semaphore.h) must execute
+- * atomically.
+- *
+- * When __up() is called, the count was negative before
+- * incrementing it, and we need to wake up somebody.
+- *
+- * This routine adds one to the count of processes that need to
+- * wake up and exit. ALL waiting processes actually wake up but
+- * only the one that gets to the "waking" field first will gate
+- * through and acquire the semaphore. The others will go back
+- * to sleep.
+- *
+- * Note that these functions are only called when there is
+- * contention on the lock, and as such all this is the
+- * "non-critical" part of the whole semaphore business. The
+- * critical part is the inline stuff in <asm/semaphore.h>
+- * where we want to avoid any extra jumps and calls.
+- */
+-void __up(struct semaphore *sem)
+-{
+- wake_one_more(sem);
+- wake_up(&sem->wait);
+-}
+-
+-/*
+- * Perform the "down" function. Return zero for semaphore acquired,
+- * return negative for signalled out of the function.
+- *
+- * If called from __down, the return is ignored and the wait loop is
+- * not interruptible. This means that a task waiting on a semaphore
+- * using "down()" cannot be killed until someone does an "up()" on
+- * the semaphore.
+- *
+- * If called from __down_interruptible, the return value gets checked
+- * upon return. If the return value is negative then the task continues
+- * with the negative value in the return register (it can be tested by
+- * the caller).
+- *
+- * Either form may be used in conjunction with "up()".
+- *
+- */
+-
+-
+-#define DOWN_HEAD(task_state) \
+- \
+- \
+- current->state = (task_state); \
+- add_wait_queue(&sem->wait, &wait); \
+- \
+- /* \
+- * Ok, we're set up. sem->count is known to be less than zero \
+- * so we must wait. \
+- * \
+- * We can let go the lock for purposes of waiting. \
+- * We re-acquire it after awaking so as to protect \
+- * all semaphore operations. \
+- * \
+- * If "up()" is called before we call waking_non_zero() then \
+- * we will catch it right away. If it is called later then \
+- * we will have to go through a wakeup cycle to catch it. \
+- * \
+- * Multiple waiters contend for the semaphore lock to see \
+- * who gets to gate through and who has to wait some more. \
+- */ \
+- for (;;) {
+-
+-#define DOWN_TAIL(task_state) \
+- current->state = (task_state); \
+- } \
+- current->state = TASK_RUNNING; \
+- remove_wait_queue(&sem->wait, &wait);
+-
+-void __sched __down(struct semaphore * sem)
+-{
+- DECLARE_WAITQUEUE(wait, current);
+-
+- DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+- if (waking_non_zero(sem))
+- break;
+- schedule();
+- DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+-}
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+- DECLARE_WAITQUEUE(wait, current);
+- int ret = 0;
+-
+- DOWN_HEAD(TASK_INTERRUPTIBLE)
+-
+- ret = waking_non_zero_interruptible(sem, current);
+- if (ret)
+- {
+- if (ret == 1)
+- /* ret != 0 only if we get interrupted -arca */
+- ret = 0;
+- break;
+- }
+- schedule();
+- DOWN_TAIL(TASK_INTERRUPTIBLE)
+- return ret;
+-}
+-
+-int __down_trylock(struct semaphore * sem)
+-{
+- return waking_non_zero_trylock(sem);
+-}
+diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
+index 8fa3faf..cd13e13 100644
+--- a/arch/ia64/Kconfig
++++ b/arch/ia64/Kconfig
+@@ -266,23 +266,23 @@ config IOSAPIC
+ depends on !IA64_HP_SIM
+ default y
+
+-config IA64_SGI_SN_XP
+- tristate "Support communication between SGI SSIs"
+- depends on IA64_GENERIC || IA64_SGI_SN2
+- select IA64_UNCACHED_ALLOCATOR
+- help
+- An SGI machine can be divided into multiple Single System
+- Images which act independently of each other and have
+- hardware based memory protection from the others. Enabling
+- this feature will allow for direct communication between SSIs
+- based on a network adapter and DMA messaging.
+-
+ config FORCE_MAX_ZONEORDER
+ int "MAX_ORDER (11 - 17)" if !HUGETLB_PAGE
+ range 11 17 if !HUGETLB_PAGE
+ default "17" if HUGETLB_PAGE
+ default "11"
+
++config VIRT_CPU_ACCOUNTING
++ bool "Deterministic task and CPU time accounting"
++ default n
++ help
++ Select this option to enable more accurate task and CPU time
++ accounting. This is done by reading a CPU counter on each
++ kernel entry and exit and on transitions within the kernel
++ between system, softirq and hardirq state, so there is a
++ small performance impact.
++ If in doubt, say N here.
++
+ config SMP
+ bool "Symmetric multi-processing support"
+ help
+@@ -611,6 +611,9 @@ config IRQ_PER_CPU
+ bool
+ default y
+
++config IOMMU_HELPER
++ def_bool (IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_GENERIC)
++
+ source "arch/ia64/hp/sim/Kconfig"
+
+ source "arch/ia64/Kconfig.debug"
+diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
+index 523eae6..9409de5 100644
+--- a/arch/ia64/hp/common/sba_iommu.c
++++ b/arch/ia64/hp/common/sba_iommu.c
+@@ -35,6 +35,7 @@
+ #include <linux/nodemask.h>
+ #include <linux/bitops.h> /* hweight64() */
+ #include <linux/crash_dump.h>
++#include <linux/iommu-helper.h>
+
+ #include <asm/delay.h> /* ia64_get_itc() */
+ #include <asm/io.h>
+@@ -460,6 +461,13 @@ get_iovp_order (unsigned long size)
+ return order;
+ }
+
++static unsigned long ptr_to_pide(struct ioc *ioc, unsigned long *res_ptr,
++ unsigned int bitshiftcnt)
++{
++ return (((unsigned long)res_ptr - (unsigned long)ioc->res_map) << 3)
++ + bitshiftcnt;
++}
++
+ /**
+ * sba_search_bitmap - find free space in IO PDIR resource bitmap
+ * @ioc: IO MMU structure which owns the pdir we are interested in.
+@@ -471,15 +479,25 @@ get_iovp_order (unsigned long size)
+ * Cool perf optimization: search for log2(size) bits at a time.
+ */
+ static SBA_INLINE unsigned long
+-sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted, int use_hint)
++sba_search_bitmap(struct ioc *ioc, struct device *dev,
++ unsigned long bits_wanted, int use_hint)
+ {
+ unsigned long *res_ptr;
+ unsigned long *res_end = (unsigned long *) &(ioc->res_map[ioc->res_size]);
+- unsigned long flags, pide = ~0UL;
++ unsigned long flags, pide = ~0UL, tpide;
++ unsigned long boundary_size;
++ unsigned long shift;
++ int ret;
+
+ ASSERT(((unsigned long) ioc->res_hint & (sizeof(unsigned long) - 1UL)) == 0);
+ ASSERT(res_ptr < res_end);
+
++ boundary_size = (unsigned long long)dma_get_seg_boundary(dev) + 1;
++ boundary_size = ALIGN(boundary_size, 1ULL << iovp_shift) >> iovp_shift;
++
++ BUG_ON(ioc->ibase & ~iovp_mask);
++ shift = ioc->ibase >> iovp_shift;
++
+ spin_lock_irqsave(&ioc->res_lock, flags);
+
+ /* Allow caller to force a search through the entire resource space */
+@@ -504,9 +522,7 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted, int use_hint)
+ if (likely(*res_ptr != ~0UL)) {
+ bitshiftcnt = ffz(*res_ptr);
+ *res_ptr |= (1UL << bitshiftcnt);
+- pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map);
+- pide <<= 3; /* convert to bit address */
+- pide += bitshiftcnt;
++ pide = ptr_to_pide(ioc, res_ptr, bitshiftcnt);
+ ioc->res_bitshift = bitshiftcnt + bits_wanted;
+ goto found_it;
+ }
+@@ -535,11 +551,13 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted, int use_hint)
+ DBG_RES(" %p %lx %lx\n", res_ptr, mask, *res_ptr);
+ ASSERT(0 != mask);
+ for (; mask ; mask <<= o, bitshiftcnt += o) {
+- if(0 == ((*res_ptr) & mask)) {
++ tpide = ptr_to_pide(ioc, res_ptr, bitshiftcnt);
++ ret = iommu_is_span_boundary(tpide, bits_wanted,
++ shift,
++ boundary_size);
++ if ((0 == ((*res_ptr) & mask)) && !ret) {
+ *res_ptr |= mask; /* mark resources busy! */
+- pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map);
+- pide <<= 3; /* convert to bit address */
+- pide += bitshiftcnt;
++ pide = tpide;
+ ioc->res_bitshift = bitshiftcnt + bits_wanted;
+ goto found_it;
+ }
+@@ -560,6 +578,11 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted, int use_hint)
+ end = res_end - qwords;
+
+ for (; res_ptr < end; res_ptr++) {
++ tpide = ptr_to_pide(ioc, res_ptr, 0);
++ ret = iommu_is_span_boundary(tpide, bits_wanted,
++ shift, boundary_size);
++ if (ret)
++ goto next_ptr;
+ for (i = 0 ; i < qwords ; i++) {
+ if (res_ptr[i] != 0)
+ goto next_ptr;
+@@ -572,8 +595,7 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted, int use_hint)
+ res_ptr[i] = ~0UL;
+ res_ptr[i] |= RESMAP_MASK(bits);
+
+- pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map);
+- pide <<= 3; /* convert to bit address */
++ pide = tpide;
+ res_ptr += qwords;
+ ioc->res_bitshift = bits;
+ goto found_it;
+@@ -605,7 +627,7 @@ found_it:
+ * resource bit map.
+ */
+ static int
+-sba_alloc_range(struct ioc *ioc, size_t size)
++sba_alloc_range(struct ioc *ioc, struct device *dev, size_t size)
+ {
+ unsigned int pages_needed = size >> iovp_shift;
+ #ifdef PDIR_SEARCH_TIMING
+@@ -622,9 +644,9 @@ sba_alloc_range(struct ioc *ioc, size_t size)
+ /*
+ ** "seek and ye shall find"...praying never hurts either...
+ */
+- pide = sba_search_bitmap(ioc, pages_needed, 1);
++ pide = sba_search_bitmap(ioc, dev, pages_needed, 1);
+ if (unlikely(pide >= (ioc->res_size << 3))) {
+- pide = sba_search_bitmap(ioc, pages_needed, 0);
++ pide = sba_search_bitmap(ioc, dev, pages_needed, 0);
+ if (unlikely(pide >= (ioc->res_size << 3))) {
+ #if DELAYED_RESOURCE_CNT > 0
+ unsigned long flags;
+@@ -653,7 +675,7 @@ sba_alloc_range(struct ioc *ioc, size_t size)
+ }
+ spin_unlock_irqrestore(&ioc->saved_lock, flags);
+
+- pide = sba_search_bitmap(ioc, pages_needed, 0);
++ pide = sba_search_bitmap(ioc, dev, pages_needed, 0);
+ if (unlikely(pide >= (ioc->res_size << 3)))
+ panic(__FILE__ ": I/O MMU @ %p is out of mapping resources\n",
+ ioc->ioc_hpa);
+@@ -936,7 +958,7 @@ sba_map_single(struct device *dev, void *addr, size_t size, int dir)
+ spin_unlock_irqrestore(&ioc->res_lock, flags);
+ #endif
+
+- pide = sba_alloc_range(ioc, size);
++ pide = sba_alloc_range(ioc, dev, size);
+
+ iovp = (dma_addr_t) pide << iovp_shift;
+
+@@ -1373,7 +1395,7 @@ sba_coalesce_chunks(struct ioc *ioc, struct device *dev,
+ dma_len = (dma_len + dma_offset + ~iovp_mask) & iovp_mask;
+ ASSERT(dma_len <= DMA_CHUNK_SIZE);
+ dma_sg->dma_address = (dma_addr_t) (PIDE_FLAG
+- | (sba_alloc_range(ioc, dma_len) << iovp_shift)
++ | (sba_alloc_range(ioc, dev, dma_len) << iovp_shift)
+ | dma_offset);
+ n_mappings++;
+ }
+diff --git a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c
+index 969fe9f..3d47839 100644
+--- a/arch/ia64/hp/sim/simeth.c
++++ b/arch/ia64/hp/sim/simeth.c
+@@ -294,7 +294,7 @@ simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr)
+ return NOTIFY_DONE;
+ }
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ if ( event != NETDEV_UP && event != NETDEV_DOWN ) return NOTIFY_DONE;
+diff --git a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c
+index 7661bb0..3a078ad 100644
+--- a/arch/ia64/hp/sim/simscsi.c
++++ b/arch/ia64/hp/sim/simscsi.c
+@@ -201,22 +201,6 @@ simscsi_readwrite10 (struct scsi_cmnd *sc, int mode)
+ simscsi_sg_readwrite(sc, mode, offset);
+ }
+
+-static void simscsi_fillresult(struct scsi_cmnd *sc, char *buf, unsigned len)
+-{
+-
+- int i;
+- unsigned thislen;
+- struct scatterlist *slp;
+-
+- scsi_for_each_sg(sc, slp, scsi_sg_count(sc), i) {
+- if (!len)
+- break;
+- thislen = min(len, slp->length);
+- memcpy(sg_virt(slp), buf, thislen);
+- len -= thislen;
+- }
+-}
+-
+ static int
+ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ {
+@@ -258,7 +242,7 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ buf[6] = 0; /* reserved */
+ buf[7] = 0; /* various flags */
+ memcpy(buf + 8, "HP SIMULATED DISK 0.00", 28);
+- simscsi_fillresult(sc, buf, 36);
++ scsi_sg_copy_from_buffer(sc, buf, 36);
+ sc->result = GOOD;
+ break;
+
+@@ -306,14 +290,15 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+ buf[5] = 0;
+ buf[6] = 2;
+ buf[7] = 0;
+- simscsi_fillresult(sc, buf, 8);
++ scsi_sg_copy_from_buffer(sc, buf, 8);
+ sc->result = GOOD;
+ break;
+
+ case MODE_SENSE:
+ case MODE_SENSE_10:
+ /* sd.c uses this to determine whether disk does write-caching. */
+- simscsi_fillresult(sc, (char *)empty_zero_page, scsi_bufflen(sc));
++ scsi_sg_copy_from_buffer(sc, (char *)empty_zero_page,
++ PAGE_SIZE);
+ sc->result = GOOD;
+ break;
+
+diff --git a/arch/ia64/ia32/elfcore32.h b/arch/ia64/ia32/elfcore32.h
+index 446c9aa..9a3abf5 100644
+--- a/arch/ia64/ia32/elfcore32.h
++++ b/arch/ia64/ia32/elfcore32.h
+@@ -30,7 +30,19 @@ struct elf_siginfo
+ int si_errno; /* errno */
+ };
+
+-#define jiffies_to_timeval(a,b) do { (b)->tv_usec = 0; (b)->tv_sec = (a)/HZ; }while(0)
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++/*
++ * Hacks are here since types between compat_timeval (= pair of s32) and
++ * ia64-native timeval (= pair of s64) are not compatible, at least a file
++ * arch/ia64/ia32/../../../fs/binfmt_elf.c will get warnings from compiler on
++ * use of cputime_to_timeval(), which usually an alias of jiffies_to_timeval().
++ */
++#define cputime_to_timeval(a,b) \
++ do { (b)->tv_usec = 0; (b)->tv_sec = (a)/NSEC_PER_SEC; } while(0)
++#else
++#define jiffies_to_timeval(a,b) \
++ do { (b)->tv_usec = 0; (b)->tv_sec = (a)/HZ; } while(0)
++#endif
+
+ struct elf_prstatus
+ {
+diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
+index b1bf51f..7e028ce 100644
+--- a/arch/ia64/ia32/sys_ia32.c
++++ b/arch/ia64/ia32/sys_ia32.c
+@@ -38,6 +38,7 @@
+ #include <linux/eventpoll.h>
+ #include <linux/personality.h>
+ #include <linux/ptrace.h>
++#include <linux/regset.h>
+ #include <linux/stat.h>
+ #include <linux/ipc.h>
+ #include <linux/capability.h>
+@@ -2387,16 +2388,45 @@ get_free_idx (void)
+ return -ESRCH;
+ }
+
++static void set_tls_desc(struct task_struct *p, int idx,
++ const struct ia32_user_desc *info, int n)
++{
++ struct thread_struct *t = &p->thread;
++ struct desc_struct *desc = &t->tls_array[idx - GDT_ENTRY_TLS_MIN];
++ int cpu;
++
++ /*
++ * We must not get preempted while modifying the TLS.
++ */
++ cpu = get_cpu();
++
++ while (n-- > 0) {
++ if (LDT_empty(info)) {
++ desc->a = 0;
++ desc->b = 0;
++ } else {
++ desc->a = LDT_entry_a(info);
++ desc->b = LDT_entry_b(info);
++ }
++
++ ++info;
++ ++desc;
++ }
++
++ if (t == ¤t->thread)
++ load_TLS(t, cpu);
++
++ put_cpu();
++}
++
+ /*
+ * Set a given TLS descriptor:
+ */
+ asmlinkage int
+ sys32_set_thread_area (struct ia32_user_desc __user *u_info)
+ {
+- struct thread_struct *t = ¤t->thread;
+ struct ia32_user_desc info;
+- struct desc_struct *desc;
+- int cpu, idx;
++ int idx;
+
+ if (copy_from_user(&info, u_info, sizeof(info)))
+ return -EFAULT;
+@@ -2416,18 +2446,7 @@ sys32_set_thread_area (struct ia32_user_desc __user *u_info)
+ if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+ return -EINVAL;
+
+- desc = t->tls_array + idx - GDT_ENTRY_TLS_MIN;
+-
+- cpu = smp_processor_id();
+-
+- if (LDT_empty(&info)) {
+- desc->a = 0;
+- desc->b = 0;
+- } else {
+- desc->a = LDT_entry_a(&info);
+- desc->b = LDT_entry_b(&info);
+- }
+- load_TLS(t, cpu);
++ set_tls_desc(current, idx, &info, 1);
+ return 0;
+ }
+
+@@ -2451,6 +2470,20 @@ sys32_set_thread_area (struct ia32_user_desc __user *u_info)
+ #define GET_PRESENT(desc) (((desc)->b >> 15) & 1)
+ #define GET_USEABLE(desc) (((desc)->b >> 20) & 1)
+
++static void fill_user_desc(struct ia32_user_desc *info, int idx,
++ const struct desc_struct *desc)
++{
++ info->entry_number = idx;
++ info->base_addr = GET_BASE(desc);
++ info->limit = GET_LIMIT(desc);
++ info->seg_32bit = GET_32BIT(desc);
++ info->contents = GET_CONTENTS(desc);
++ info->read_exec_only = !GET_WRITABLE(desc);
++ info->limit_in_pages = GET_LIMIT_PAGES(desc);
++ info->seg_not_present = !GET_PRESENT(desc);
++ info->useable = GET_USEABLE(desc);
++}
++
+ asmlinkage int
+ sys32_get_thread_area (struct ia32_user_desc __user *u_info)
+ {
+@@ -2464,22 +2497,588 @@ sys32_get_thread_area (struct ia32_user_desc __user *u_info)
+ return -EINVAL;
+
+ desc = current->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
+-
+- info.entry_number = idx;
+- info.base_addr = GET_BASE(desc);
+- info.limit = GET_LIMIT(desc);
+- info.seg_32bit = GET_32BIT(desc);
+- info.contents = GET_CONTENTS(desc);
+- info.read_exec_only = !GET_WRITABLE(desc);
+- info.limit_in_pages = GET_LIMIT_PAGES(desc);
+- info.seg_not_present = !GET_PRESENT(desc);
+- info.useable = GET_USEABLE(desc);
++ fill_user_desc(&info, idx, desc);
+
+ if (copy_to_user(u_info, &info, sizeof(info)))
+ return -EFAULT;
+ return 0;
+ }
+
++struct regset_get {
++ void *kbuf;
++ void __user *ubuf;
++};
++
++struct regset_set {
++ const void *kbuf;
++ const void __user *ubuf;
++};
++
++struct regset_getset {
++ struct task_struct *target;
++ const struct user_regset *regset;
++ union {
++ struct regset_get get;
++ struct regset_set set;
++ } u;
++ unsigned int pos;
++ unsigned int count;
++ int ret;
++};
++
++static void getfpreg(struct task_struct *task, int regno, int *val)
++{
++ switch (regno / sizeof(int)) {
++ case 0:
++ *val = task->thread.fcr & 0xffff;
++ break;
++ case 1:
++ *val = task->thread.fsr & 0xffff;
++ break;
++ case 2:
++ *val = (task->thread.fsr>>16) & 0xffff;
++ break;
++ case 3:
++ *val = task->thread.fir;
++ break;
++ case 4:
++ *val = (task->thread.fir>>32) & 0xffff;
++ break;
++ case 5:
++ *val = task->thread.fdr;
++ break;
++ case 6:
++ *val = (task->thread.fdr >> 32) & 0xffff;
++ break;
++ }
++}
++
++static void setfpreg(struct task_struct *task, int regno, int val)
++{
++ switch (regno / sizeof(int)) {
++ case 0:
++ task->thread.fcr = (task->thread.fcr & (~0x1f3f))
++ | (val & 0x1f3f);
++ break;
++ case 1:
++ task->thread.fsr = (task->thread.fsr & (~0xffff)) | val;
++ break;
++ case 2:
++ task->thread.fsr = (task->thread.fsr & (~0xffff0000))
++ | (val << 16);
++ break;
++ case 3:
++ task->thread.fir = (task->thread.fir & (~0xffffffff)) | val;
++ break;
++ case 5:
++ task->thread.fdr = (task->thread.fdr & (~0xffffffff)) | val;
++ break;
++ }
++}
++
++static void access_fpreg_ia32(int regno, void *reg,
++ struct pt_regs *pt, struct switch_stack *sw,
++ int tos, int write)
++{
++ void *f;
++
++ if ((regno += tos) >= 8)
++ regno -= 8;
++ if (regno < 4)
++ f = &pt->f8 + regno;
++ else if (regno <= 7)
++ f = &sw->f12 + (regno - 4);
++ else {
++ printk(KERN_ERR "regno must be less than 7 \n");
++ return;
++ }
++
++ if (write)
++ memcpy(f, reg, sizeof(struct _fpreg_ia32));
++ else
++ memcpy(reg, f, sizeof(struct _fpreg_ia32));
++}
++
++static void do_fpregs_get(struct unw_frame_info *info, void *arg)
++{
++ struct regset_getset *dst = arg;
++ struct task_struct *task = dst->target;
++ struct pt_regs *pt;
++ int start, end, tos;
++ char buf[80];
++
++ if (dst->count == 0 || unw_unwind_to_user(info) < 0)
++ return;
++ if (dst->pos < 7 * sizeof(int)) {
++ end = min((dst->pos + dst->count),
++ (unsigned int)(7 * sizeof(int)));
++ for (start = dst->pos; start < end; start += sizeof(int))
++ getfpreg(task, start, (int *)(buf + start));
++ dst->ret = user_regset_copyout(&dst->pos, &dst->count,
++ &dst->u.get.kbuf, &dst->u.get.ubuf, buf,
++ 0, 7 * sizeof(int));
++ if (dst->ret || dst->count == 0)
++ return;
++ }
++ if (dst->pos < sizeof(struct ia32_user_i387_struct)) {
++ pt = task_pt_regs(task);
++ tos = (task->thread.fsr >> 11) & 7;
++ end = min(dst->pos + dst->count,
++ (unsigned int)(sizeof(struct ia32_user_i387_struct)));
++ start = (dst->pos - 7 * sizeof(int)) /
++ sizeof(struct _fpreg_ia32);
++ end = (end - 7 * sizeof(int)) / sizeof(struct _fpreg_ia32);
++ for (; start < end; start++)
++ access_fpreg_ia32(start,
++ (struct _fpreg_ia32 *)buf + start,
++ pt, info->sw, tos, 0);
++ dst->ret = user_regset_copyout(&dst->pos, &dst->count,
++ &dst->u.get.kbuf, &dst->u.get.ubuf,
++ buf, 7 * sizeof(int),
++ sizeof(struct ia32_user_i387_struct));
++ if (dst->ret || dst->count == 0)
++ return;
++ }
++}
++
++static void do_fpregs_set(struct unw_frame_info *info, void *arg)
++{
++ struct regset_getset *dst = arg;
++ struct task_struct *task = dst->target;
++ struct pt_regs *pt;
++ char buf[80];
++ int end, start, tos;
++
++ if (dst->count == 0 || unw_unwind_to_user(info) < 0)
++ return;
++
++ if (dst->pos < 7 * sizeof(int)) {
++ start = dst->pos;
++ dst->ret = user_regset_copyin(&dst->pos, &dst->count,
++ &dst->u.set.kbuf, &dst->u.set.ubuf, buf,
++ 0, 7 * sizeof(int));
++ if (dst->ret)
++ return;
++ for (; start < dst->pos; start += sizeof(int))
++ setfpreg(task, start, *((int *)(buf + start)));
++ if (dst->count == 0)
++ return;
++ }
++ if (dst->pos < sizeof(struct ia32_user_i387_struct)) {
++ start = (dst->pos - 7 * sizeof(int)) /
++ sizeof(struct _fpreg_ia32);
++ dst->ret = user_regset_copyin(&dst->pos, &dst->count,
++ &dst->u.set.kbuf, &dst->u.set.ubuf,
++ buf, 7 * sizeof(int),
++ sizeof(struct ia32_user_i387_struct));
++ if (dst->ret)
++ return;
++ pt = task_pt_regs(task);
++ tos = (task->thread.fsr >> 11) & 7;
++ end = (dst->pos - 7 * sizeof(int)) / sizeof(struct _fpreg_ia32);
++ for (; start < end; start++)
++ access_fpreg_ia32(start,
++ (struct _fpreg_ia32 *)buf + start,
++ pt, info->sw, tos, 1);
++ if (dst->count == 0)
++ return;
++ }
++}
++
++#define OFFSET(member) ((int)(offsetof(struct ia32_user_fxsr_struct, member)))
++static void getfpxreg(struct task_struct *task, int start, int end, char *buf)
++{
++ int min_val;
++
++ min_val = min(end, OFFSET(fop));
++ while (start < min_val) {
++ if (start == OFFSET(cwd))
++ *((short *)buf) = task->thread.fcr & 0xffff;
++ else if (start == OFFSET(swd))
++ *((short *)buf) = task->thread.fsr & 0xffff;
++ else if (start == OFFSET(twd))
++ *((short *)buf) = (task->thread.fsr>>16) & 0xffff;
++ buf += 2;
++ start += 2;
++ }
++ /* skip fop element */
++ if (start == OFFSET(fop)) {
++ start += 2;
++ buf += 2;
++ }
++ while (start < end) {
++ if (start == OFFSET(fip))
++ *((int *)buf) = task->thread.fir;
++ else if (start == OFFSET(fcs))
++ *((int *)buf) = (task->thread.fir>>32) & 0xffff;
++ else if (start == OFFSET(foo))
++ *((int *)buf) = task->thread.fdr;
++ else if (start == OFFSET(fos))
++ *((int *)buf) = (task->thread.fdr>>32) & 0xffff;
++ else if (start == OFFSET(mxcsr))
++ *((int *)buf) = ((task->thread.fcr>>32) & 0xff80)
++ | ((task->thread.fsr>>32) & 0x3f);
++ buf += 4;
++ start += 4;
++ }
++}
++
++static void setfpxreg(struct task_struct *task, int start, int end, char *buf)
++{
++ int min_val, num32;
++ short num;
++ unsigned long num64;
++
++ min_val = min(end, OFFSET(fop));
++ while (start < min_val) {
++ num = *((short *)buf);
++ if (start == OFFSET(cwd)) {
++ task->thread.fcr = (task->thread.fcr & (~0x1f3f))
++ | (num & 0x1f3f);
++ } else if (start == OFFSET(swd)) {
++ task->thread.fsr = (task->thread.fsr & (~0xffff)) | num;
++ } else if (start == OFFSET(twd)) {
++ task->thread.fsr = (task->thread.fsr & (~0xffff0000))
++ | (((int)num) << 16);
++ }
++ buf += 2;
++ start += 2;
++ }
++ /* skip fop element */
++ if (start == OFFSET(fop)) {
++ start += 2;
++ buf += 2;
++ }
++ while (start < end) {
++ num32 = *((int *)buf);
++ if (start == OFFSET(fip))
++ task->thread.fir = (task->thread.fir & (~0xffffffff))
++ | num32;
++ else if (start == OFFSET(foo))
++ task->thread.fdr = (task->thread.fdr & (~0xffffffff))
++ | num32;
++ else if (start == OFFSET(mxcsr)) {
++ num64 = num32 & 0xff10;
++ task->thread.fcr = (task->thread.fcr &
++ (~0xff1000000000UL)) | (num64<<32);
++ num64 = num32 & 0x3f;
++ task->thread.fsr = (task->thread.fsr &
++ (~0x3f00000000UL)) | (num64<<32);
++ }
++ buf += 4;
++ start += 4;
++ }
++}
++
++static void do_fpxregs_get(struct unw_frame_info *info, void *arg)
++{
++ struct regset_getset *dst = arg;
++ struct task_struct *task = dst->target;
++ struct pt_regs *pt;
++ char buf[128];
++ int start, end, tos;
++
++ if (dst->count == 0 || unw_unwind_to_user(info) < 0)
++ return;
++ if (dst->pos < OFFSET(st_space[0])) {
++ end = min(dst->pos + dst->count, (unsigned int)32);
++ getfpxreg(task, dst->pos, end, buf);
++ dst->ret = user_regset_copyout(&dst->pos, &dst->count,
++ &dst->u.get.kbuf, &dst->u.get.ubuf, buf,
++ 0, OFFSET(st_space[0]));
++ if (dst->ret || dst->count == 0)
++ return;
++ }
++ if (dst->pos < OFFSET(xmm_space[0])) {
++ pt = task_pt_regs(task);
++ tos = (task->thread.fsr >> 11) & 7;
++ end = min(dst->pos + dst->count,
++ (unsigned int)OFFSET(xmm_space[0]));
++ start = (dst->pos - OFFSET(st_space[0])) / 16;
++ end = (end - OFFSET(st_space[0])) / 16;
++ for (; start < end; start++)
++ access_fpreg_ia32(start, buf + 16 * start, pt,
++ info->sw, tos, 0);
++ dst->ret = user_regset_copyout(&dst->pos, &dst->count,
++ &dst->u.get.kbuf, &dst->u.get.ubuf,
++ buf, OFFSET(st_space[0]), OFFSET(xmm_space[0]));
++ if (dst->ret || dst->count == 0)
++ return;
++ }
++ if (dst->pos < OFFSET(padding[0]))
++ dst->ret = user_regset_copyout(&dst->pos, &dst->count,
++ &dst->u.get.kbuf, &dst->u.get.ubuf,
++ &info->sw->f16, OFFSET(xmm_space[0]),
++ OFFSET(padding[0]));
++}
++
++static void do_fpxregs_set(struct unw_frame_info *info, void *arg)
++{
++ struct regset_getset *dst = arg;
++ struct task_struct *task = dst->target;
++ char buf[128];
++ int start, end;
++
++ if (dst->count == 0 || unw_unwind_to_user(info) < 0)
++ return;
++
++ if (dst->pos < OFFSET(st_space[0])) {
++ start = dst->pos;
++ dst->ret = user_regset_copyin(&dst->pos, &dst->count,
++ &dst->u.set.kbuf, &dst->u.set.ubuf,
++ buf, 0, OFFSET(st_space[0]));
++ if (dst->ret)
++ return;
++ setfpxreg(task, start, dst->pos, buf);
++ if (dst->count == 0)
++ return;
++ }
++ if (dst->pos < OFFSET(xmm_space[0])) {
++ struct pt_regs *pt;
++ int tos;
++ pt = task_pt_regs(task);
++ tos = (task->thread.fsr >> 11) & 7;
++ start = (dst->pos - OFFSET(st_space[0])) / 16;
++ dst->ret = user_regset_copyin(&dst->pos, &dst->count,
++ &dst->u.set.kbuf, &dst->u.set.ubuf,
++ buf, OFFSET(st_space[0]), OFFSET(xmm_space[0]));
++ if (dst->ret)
++ return;
++ end = (dst->pos - OFFSET(st_space[0])) / 16;
++ for (; start < end; start++)
++ access_fpreg_ia32(start, buf + 16 * start, pt, info->sw,
++ tos, 1);
++ if (dst->count == 0)
++ return;
++ }
++ if (dst->pos < OFFSET(padding[0]))
++ dst->ret = user_regset_copyin(&dst->pos, &dst->count,
++ &dst->u.set.kbuf, &dst->u.set.ubuf,
++ &info->sw->f16, OFFSET(xmm_space[0]),
++ OFFSET(padding[0]));
++}
++#undef OFFSET
++
++static int do_regset_call(void (*call)(struct unw_frame_info *, void *),
++ struct task_struct *target,
++ const struct user_regset *regset,
++ unsigned int pos, unsigned int count,
++ const void *kbuf, const void __user *ubuf)
++{
++ struct regset_getset info = { .target = target, .regset = regset,
++ .pos = pos, .count = count,
++ .u.set = { .kbuf = kbuf, .ubuf = ubuf },
++ .ret = 0 };
++
++ if (target == current)
++ unw_init_running(call, &info);
++ else {
++ struct unw_frame_info ufi;
++ memset(&ufi, 0, sizeof(ufi));
++ unw_init_from_blocked_task(&ufi, target);
++ (*call)(&ufi, &info);
++ }
++
++ return info.ret;
++}
++
++static int ia32_fpregs_get(struct task_struct *target,
++ const struct user_regset *regset,
++ unsigned int pos, unsigned int count,
++ void *kbuf, void __user *ubuf)
++{
++ return do_regset_call(do_fpregs_get, target, regset, pos, count,
++ kbuf, ubuf);
++}
++
++static int ia32_fpregs_set(struct task_struct *target,
++ const struct user_regset *regset,
++ unsigned int pos, unsigned int count,
++ const void *kbuf, const void __user *ubuf)
++{
++ return do_regset_call(do_fpregs_set, target, regset, pos, count,
++ kbuf, ubuf);
++}
++
++static int ia32_fpxregs_get(struct task_struct *target,
++ const struct user_regset *regset,
++ unsigned int pos, unsigned int count,
++ void *kbuf, void __user *ubuf)
++{
++ return do_regset_call(do_fpxregs_get, target, regset, pos, count,
++ kbuf, ubuf);
++}
++
++static int ia32_fpxregs_set(struct task_struct *target,
++ const struct user_regset *regset,
++ unsigned int pos, unsigned int count,
++ const void *kbuf, const void __user *ubuf)
++{
++ return do_regset_call(do_fpxregs_set, target, regset, pos, count,
++ kbuf, ubuf);
++}
++
++static int ia32_genregs_get(struct task_struct *target,
++ const struct user_regset *regset,
++ unsigned int pos, unsigned int count,
++ void *kbuf, void __user *ubuf)
++{
++ if (kbuf) {
++ u32 *kp = kbuf;
++ while (count > 0) {
++ *kp++ = getreg(target, pos);
++ pos += 4;
++ count -= 4;
++ }
++ } else {
++ u32 __user *up = ubuf;
++ while (count > 0) {
++ if (__put_user(getreg(target, pos), up++))
++ return -EFAULT;
++ pos += 4;
++ count -= 4;
++ }
++ }
++ return 0;
++}
++
++static int ia32_genregs_set(struct task_struct *target,
++ const struct user_regset *regset,
++ unsigned int pos, unsigned int count,
++ const void *kbuf, const void __user *ubuf)
++{
++ int ret = 0;
++
++ if (kbuf) {
++ const u32 *kp = kbuf;
++ while (!ret && count > 0) {
++ putreg(target, pos, *kp++);
++ pos += 4;
++ count -= 4;
++ }
++ } else {
++ const u32 __user *up = ubuf;
++ u32 val;
++ while (!ret && count > 0) {
++ ret = __get_user(val, up++);
++ if (!ret)
++ putreg(target, pos, val);
++ pos += 4;
++ count -= 4;
++ }
++ }
++ return ret;
++}
++
++static int ia32_tls_active(struct task_struct *target,
++ const struct user_regset *regset)
++{
++ struct thread_struct *t = &target->thread;
++ int n = GDT_ENTRY_TLS_ENTRIES;
++ while (n > 0 && desc_empty(&t->tls_array[n -1]))
++ --n;
++ return n;
++}
++
++static int ia32_tls_get(struct task_struct *target,
++ const struct user_regset *regset, unsigned int pos,
++ unsigned int count, void *kbuf, void __user *ubuf)
++{
++ const struct desc_struct *tls;
++
++ if (pos > GDT_ENTRY_TLS_ENTRIES * sizeof(struct ia32_user_desc) ||
++ (pos % sizeof(struct ia32_user_desc)) != 0 ||
++ (count % sizeof(struct ia32_user_desc)) != 0)
++ return -EINVAL;
++
++ pos /= sizeof(struct ia32_user_desc);
++ count /= sizeof(struct ia32_user_desc);
++
++ tls = &target->thread.tls_array[pos];
++
++ if (kbuf) {
++ struct ia32_user_desc *info = kbuf;
++ while (count-- > 0)
++ fill_user_desc(info++, GDT_ENTRY_TLS_MIN + pos++,
++ tls++);
++ } else {
++ struct ia32_user_desc __user *u_info = ubuf;
++ while (count-- > 0) {
++ struct ia32_user_desc info;
++ fill_user_desc(&info, GDT_ENTRY_TLS_MIN + pos++, tls++);
++ if (__copy_to_user(u_info++, &info, sizeof(info)))
++ return -EFAULT;
++ }
++ }
++
++ return 0;
++}
++
++static int ia32_tls_set(struct task_struct *target,
++ const struct user_regset *regset, unsigned int pos,
++ unsigned int count, const void *kbuf, const void __user *ubuf)
++{
++ struct ia32_user_desc infobuf[GDT_ENTRY_TLS_ENTRIES];
++ const struct ia32_user_desc *info;
++
++ if (pos > GDT_ENTRY_TLS_ENTRIES * sizeof(struct ia32_user_desc) ||
++ (pos % sizeof(struct ia32_user_desc)) != 0 ||
++ (count % sizeof(struct ia32_user_desc)) != 0)
++ return -EINVAL;
++
++ if (kbuf)
++ info = kbuf;
++ else if (__copy_from_user(infobuf, ubuf, count))
++ return -EFAULT;
++ else
++ info = infobuf;
++
++ set_tls_desc(target,
++ GDT_ENTRY_TLS_MIN + (pos / sizeof(struct ia32_user_desc)),
++ info, count / sizeof(struct ia32_user_desc));
++
++ return 0;
++}
++
++/*
++ * This should match arch/i386/kernel/ptrace.c:native_regsets.
++ * XXX ioperm? vm86?
++ */
++static const struct user_regset ia32_regsets[] = {
++ {
++ .core_note_type = NT_PRSTATUS,
++ .n = sizeof(struct user_regs_struct32)/4,
++ .size = 4, .align = 4,
++ .get = ia32_genregs_get, .set = ia32_genregs_set
++ },
++ {
++ .core_note_type = NT_PRFPREG,
++ .n = sizeof(struct ia32_user_i387_struct) / 4,
++ .size = 4, .align = 4,
++ .get = ia32_fpregs_get, .set = ia32_fpregs_set
++ },
++ {
++ .core_note_type = NT_PRXFPREG,
++ .n = sizeof(struct ia32_user_fxsr_struct) / 4,
++ .size = 4, .align = 4,
++ .get = ia32_fpxregs_get, .set = ia32_fpxregs_set
++ },
++ {
++ .core_note_type = NT_386_TLS,
++ .n = GDT_ENTRY_TLS_ENTRIES,
++ .bias = GDT_ENTRY_TLS_MIN,
++ .size = sizeof(struct ia32_user_desc),
++ .align = sizeof(struct ia32_user_desc),
++ .active = ia32_tls_active,
++ .get = ia32_tls_get, .set = ia32_tls_set,
++ },
++};
++
++const struct user_regset_view user_ia32_view = {
++ .name = "i386", .e_machine = EM_386,
++ .regsets = ia32_regsets, .n = ARRAY_SIZE(ia32_regsets)
++};
++
+ long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high,
+ __u32 len_low, __u32 len_high, int advice)
+ {
+diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
+index 33e5a59..13fd10e 100644
+--- a/arch/ia64/kernel/Makefile
++++ b/arch/ia64/kernel/Makefile
+@@ -6,7 +6,7 @@ extra-y := head.o init_task.o vmlinux.lds
+
+ obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o \
+ irq_lsapic.o ivt.o machvec.o pal.o patch.o process.o perfmon.o ptrace.o sal.o \
+- salinfo.o semaphore.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o \
++ salinfo.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o \
+ unwind.o mca.o mca_asm.o topology.o
+
+ obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o
+diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
+index 78f28d8..c7467f8 100644
+--- a/arch/ia64/kernel/acpi.c
++++ b/arch/ia64/kernel/acpi.c
+@@ -423,6 +423,7 @@ static u32 __devinitdata pxm_flag[PXM_FLAG_LEN];
+ #define pxm_bit_set(bit) (set_bit(bit,(void *)pxm_flag))
+ #define pxm_bit_test(bit) (test_bit(bit,(void *)pxm_flag))
+ static struct acpi_table_slit __initdata *slit_table;
++cpumask_t early_cpu_possible_map = CPU_MASK_NONE;
+
+ static int get_processor_proximity_domain(struct acpi_srat_cpu_affinity *pa)
+ {
+@@ -482,6 +483,7 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
+ (pa->apic_id << 8) | (pa->local_sapic_eid);
+ /* nid should be overridden as logical node id later */
+ node_cpuid[srat_num_cpus].nid = pxm;
++ cpu_set(srat_num_cpus, early_cpu_possible_map);
+ srat_num_cpus++;
+ }
+
+@@ -559,7 +561,7 @@ void __init acpi_numa_arch_fixup(void)
+ }
+
+ /* set logical node id in cpu structure */
+- for (i = 0; i < srat_num_cpus; i++)
++ for_each_possible_early_cpu(i)
+ node_cpuid[i].nid = pxm_to_node(node_cpuid[i].nid);
+
+ printk(KERN_INFO "Number of logical nodes in system = %d\n",
+diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c
+index 0aebc6f..230a6f9 100644
+--- a/arch/ia64/kernel/asm-offsets.c
++++ b/arch/ia64/kernel/asm-offsets.c
+@@ -7,6 +7,7 @@
+ #define ASM_OFFSETS_C 1
+
+ #include <linux/sched.h>
++#include <linux/pid.h>
+ #include <linux/clocksource.h>
+
+ #include <asm-ia64/processor.h>
+@@ -34,17 +35,29 @@ void foo(void)
+ DEFINE(SIGFRAME_SIZE, sizeof (struct sigframe));
+ DEFINE(UNW_FRAME_INFO_SIZE, sizeof (struct unw_frame_info));
+
++ BUILD_BUG_ON(sizeof(struct upid) != 32);
++ DEFINE(IA64_UPID_SHIFT, 5);
++
+ BLANK();
+
+ DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+ DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
+ DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count));
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++ DEFINE(TI_AC_STAMP, offsetof(struct thread_info, ac_stamp));
++ DEFINE(TI_AC_LEAVE, offsetof(struct thread_info, ac_leave));
++ DEFINE(TI_AC_STIME, offsetof(struct thread_info, ac_stime));
++ DEFINE(TI_AC_UTIME, offsetof(struct thread_info, ac_utime));
++#endif
+
+ BLANK();
+
+ DEFINE(IA64_TASK_BLOCKED_OFFSET,offsetof (struct task_struct, blocked));
+ DEFINE(IA64_TASK_CLEAR_CHILD_TID_OFFSET,offsetof (struct task_struct, clear_child_tid));
+ DEFINE(IA64_TASK_GROUP_LEADER_OFFSET, offsetof (struct task_struct, group_leader));
++ DEFINE(IA64_TASK_TGIDLINK_OFFSET, offsetof (struct task_struct, pids[PIDTYPE_PID].pid));
++ DEFINE(IA64_PID_LEVEL_OFFSET, offsetof (struct pid, level));
++ DEFINE(IA64_PID_UPID_OFFSET, offsetof (struct pid, numbers[0]));
+ DEFINE(IA64_TASK_PENDING_OFFSET,offsetof (struct task_struct, pending));
+ DEFINE(IA64_TASK_PID_OFFSET, offsetof (struct task_struct, pid));
+ DEFINE(IA64_TASK_REAL_PARENT_OFFSET, offsetof (struct task_struct, real_parent));
+diff --git a/arch/ia64/kernel/crash.c b/arch/ia64/kernel/crash.c
+index fbe742a..f065093 100644
+--- a/arch/ia64/kernel/crash.c
++++ b/arch/ia64/kernel/crash.c
+@@ -24,6 +24,7 @@ int kdump_status[NR_CPUS];
+ static atomic_t kdump_cpu_frozen;
+ atomic_t kdump_in_progress;
+ static int kdump_on_init = 1;
++static int kdump_on_fatal_mca = 1;
+
+ static inline Elf64_Word
+ *append_elf_note(Elf64_Word *buf, char *name, unsigned type, void *data,
+@@ -118,6 +119,7 @@ machine_crash_shutdown(struct pt_regs *pt)
+ static void
+ machine_kdump_on_init(void)
+ {
++ crash_save_vmcoreinfo();
+ local_irq_disable();
+ kexec_disable_iosapic();
+ machine_kexec(ia64_kimage);
+@@ -148,7 +150,7 @@ kdump_init_notifier(struct notifier_block *self, unsigned long val, void *data)
+ struct ia64_mca_notify_die *nd;
+ struct die_args *args = data;
+
+- if (!kdump_on_init)
++ if (!kdump_on_init && !kdump_on_fatal_mca)
+ return NOTIFY_DONE;
+
+ if (!ia64_kimage) {
+@@ -173,32 +175,38 @@ kdump_init_notifier(struct notifier_block *self, unsigned long val, void *data)
+ return NOTIFY_DONE;
+
+ switch (val) {
+- case DIE_INIT_MONARCH_PROCESS:
++ case DIE_INIT_MONARCH_PROCESS:
++ if (kdump_on_init) {
+ atomic_set(&kdump_in_progress, 1);
+ *(nd->monarch_cpu) = -1;
+- break;
+- case DIE_INIT_MONARCH_LEAVE:
++ }
++ break;
++ case DIE_INIT_MONARCH_LEAVE:
++ if (kdump_on_init)
+ machine_kdump_on_init();
+- break;
+- case DIE_INIT_SLAVE_LEAVE:
+- if (atomic_read(&kdump_in_progress))
+- unw_init_running(kdump_cpu_freeze, NULL);
+- break;
+- case DIE_MCA_RENDZVOUS_LEAVE:
+- if (atomic_read(&kdump_in_progress))
+- unw_init_running(kdump_cpu_freeze, NULL);
+- break;
+- case DIE_MCA_MONARCH_LEAVE:
+- /* die_register->signr indicate if MCA is recoverable */
+- if (!args->signr)
+- machine_kdump_on_init();
+- break;
++ break;
++ case DIE_INIT_SLAVE_LEAVE:
++ if (atomic_read(&kdump_in_progress))
++ unw_init_running(kdump_cpu_freeze, NULL);
++ break;
++ case DIE_MCA_RENDZVOUS_LEAVE:
++ if (atomic_read(&kdump_in_progress))
++ unw_init_running(kdump_cpu_freeze, NULL);
++ break;
++ case DIE_MCA_MONARCH_LEAVE:
++ /* *(nd->data) indicate if MCA is recoverable */
++ if (kdump_on_fatal_mca && !(*(nd->data))) {
++ atomic_set(&kdump_in_progress, 1);
++ *(nd->monarch_cpu) = -1;
++ machine_kdump_on_init();
++ }
++ break;
+ }
+ return NOTIFY_DONE;
+ }
+
+ #ifdef CONFIG_SYSCTL
+-static ctl_table kdump_on_init_table[] = {
++static ctl_table kdump_ctl_table[] = {
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "kdump_on_init",
+@@ -207,6 +215,14 @@ static ctl_table kdump_on_init_table[] = {
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
++ {
++ .ctl_name = CTL_UNNUMBERED,
++ .procname = "kdump_on_fatal_mca",
++ .data = &kdump_on_fatal_mca,
++ .maxlen = sizeof(int),
++ .mode = 0644,
++ .proc_handler = &proc_dointvec,
++ },
+ { .ctl_name = 0 }
+ };
+
+@@ -215,7 +231,7 @@ static ctl_table sys_table[] = {
+ .ctl_name = CTL_KERN,
+ .procname = "kernel",
+ .mode = 0555,
+- .child = kdump_on_init_table,
++ .child = kdump_ctl_table,
+ },
+ { .ctl_name = 0 }
+ };
+diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
+index 728d724..d45f215 100644
+--- a/arch/ia64/kernel/efi.c
++++ b/arch/ia64/kernel/efi.c
+@@ -37,6 +37,7 @@
+ #include <asm/pgtable.h>
+ #include <asm/processor.h>
+ #include <asm/mca.h>
++#include <asm/tlbflush.h>
+
+ #define EFI_DEBUG 0
+
+@@ -403,6 +404,41 @@ efi_get_pal_addr (void)
+ return NULL;
+ }
+
++
++static u8 __init palo_checksum(u8 *buffer, u32 length)
++{
++ u8 sum = 0;
++ u8 *end = buffer + length;
++
++ while (buffer < end)
++ sum = (u8) (sum + *(buffer++));
++
++ return sum;
++}
++
++/*
++ * Parse and handle PALO table which is published at:
++ * http://www.dig64.org/home/DIG64_PALO_R1_0.pdf
++ */
++static void __init handle_palo(unsigned long palo_phys)
++{
++ struct palo_table *palo = __va(palo_phys);
++ u8 checksum;
++
++ if (strncmp(palo->signature, PALO_SIG, sizeof(PALO_SIG) - 1)) {
++ printk(KERN_INFO "PALO signature incorrect.\n");
++ return;
++ }
++
++ checksum = palo_checksum((u8 *)palo, palo->length);
++ if (checksum) {
++ printk(KERN_INFO "PALO checksum incorrect.\n");
++ return;
++ }
++
++ setup_ptcg_sem(palo->max_tlb_purges, NPTCG_FROM_PALO);
++}
++
+ void
+ efi_map_pal_code (void)
+ {
+@@ -432,6 +468,7 @@ efi_init (void)
+ u64 efi_desc_size;
+ char *cp, vendor[100] = "unknown";
+ int i;
++ unsigned long palo_phys;
+
+ /*
+ * It's too early to be able to use the standard kernel command line
+@@ -496,6 +533,8 @@ efi_init (void)
+ efi.hcdp = EFI_INVALID_TABLE_ADDR;
+ efi.uga = EFI_INVALID_TABLE_ADDR;
+
++ palo_phys = EFI_INVALID_TABLE_ADDR;
++
+ for (i = 0; i < (int) efi.systab->nr_tables; i++) {
+ if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) {
+ efi.mps = config_tables[i].table;
+@@ -515,10 +554,17 @@ efi_init (void)
+ } else if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) {
+ efi.hcdp = config_tables[i].table;
+ printk(" HCDP=0x%lx", config_tables[i].table);
++ } else if (efi_guidcmp(config_tables[i].guid,
++ PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID) == 0) {
++ palo_phys = config_tables[i].table;
++ printk(" PALO=0x%lx", config_tables[i].table);
+ }
+ }
+ printk("\n");
+
++ if (palo_phys != EFI_INVALID_TABLE_ADDR)
++ handle_palo(palo_phys);
++
+ runtime = __va(efi.systab->runtime);
+ efi.get_time = phys_get_time;
+ efi.set_time = phys_set_time;
+diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
+index 3c331c4..e49ad8c 100644
+--- a/arch/ia64/kernel/entry.S
++++ b/arch/ia64/kernel/entry.S
+@@ -570,6 +570,7 @@ GLOBAL_ENTRY(ia64_trace_syscall)
+ br.call.sptk.many rp=syscall_trace_leave // give parent a chance to catch return value
+ .ret3:
+ (pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk
++(pUStk) rsm psr.i // disable interrupts
+ br.cond.sptk .work_pending_syscall_end
+
+ strace_error:
+@@ -710,6 +711,16 @@ ENTRY(ia64_leave_syscall)
+ (pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk
+ #endif
+ .work_processed_syscall:
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++ adds r2=PT(LOADRS)+16,r12
++(pUStk) mov.m r22=ar.itc // fetch time at leave
++ adds r18=TI_FLAGS+IA64_TASK_SIZE,r13
++ ;;
++(p6) ld4 r31=[r18] // load current_thread_info()->flags
++ ld8 r19=[r2],PT(B6)-PT(LOADRS) // load ar.rsc value for "loadrs"
++ adds r3=PT(AR_BSPSTORE)+16,r12 // deferred
++ ;;
++#else
+ adds r2=PT(LOADRS)+16,r12
+ adds r3=PT(AR_BSPSTORE)+16,r12
+ adds r18=TI_FLAGS+IA64_TASK_SIZE,r13
+@@ -718,6 +729,7 @@ ENTRY(ia64_leave_syscall)
+ ld8 r19=[r2],PT(B6)-PT(LOADRS) // load ar.rsc value for "loadrs"
+ nop.i 0
+ ;;
++#endif
+ mov r16=ar.bsp // M2 get existing backing store pointer
+ ld8 r18=[r2],PT(R9)-PT(B6) // load b6
+ (p6) and r15=TIF_WORK_MASK,r31 // any work other than TIF_SYSCALL_TRACE?
+@@ -737,12 +749,21 @@ ENTRY(ia64_leave_syscall)
+
+ ld8 r29=[r2],16 // M0|1 load cr.ipsr
+ ld8 r28=[r3],16 // M0|1 load cr.iip
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++(pUStk) add r14=TI_AC_LEAVE+IA64_TASK_SIZE,r13
++ ;;
++ ld8 r30=[r2],16 // M0|1 load cr.ifs
++ ld8 r25=[r3],16 // M0|1 load ar.unat
++(pUStk) add r15=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
++ ;;
++#else
+ mov r22=r0 // A clear r22
+ ;;
+ ld8 r30=[r2],16 // M0|1 load cr.ifs
+ ld8 r25=[r3],16 // M0|1 load ar.unat
+ (pUStk) add r14=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
+ ;;
++#endif
+ ld8 r26=[r2],PT(B0)-PT(AR_PFS) // M0|1 load ar.pfs
+ (pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled
+ nop 0
+@@ -759,7 +780,11 @@ ENTRY(ia64_leave_syscall)
+ ld8.fill r1=[r3],16 // M0|1 load r1
+ (pUStk) mov r17=1 // A
+ ;;
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++(pUStk) st1 [r15]=r17 // M2|3
++#else
+ (pUStk) st1 [r14]=r17 // M2|3
++#endif
+ ld8.fill r13=[r3],16 // M0|1
+ mov f8=f0 // F clear f8
+ ;;
+@@ -775,12 +800,22 @@ ENTRY(ia64_leave_syscall)
+ shr.u r18=r19,16 // I0|1 get byte size of existing "dirty" partition
+ cover // B add current frame into dirty partition & set cr.ifs
+ ;;
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++ mov r19=ar.bsp // M2 get new backing store pointer
++ st8 [r14]=r22 // M save time at leave
++ mov f10=f0 // F clear f10
++
++ mov r22=r0 // A clear r22
++ movl r14=__kernel_syscall_via_epc // X
++ ;;
++#else
+ mov r19=ar.bsp // M2 get new backing store pointer
+ mov f10=f0 // F clear f10
+
+ nop.m 0
+ movl r14=__kernel_syscall_via_epc // X
+ ;;
++#endif
+ mov.m ar.csd=r0 // M2 clear ar.csd
+ mov.m ar.ccv=r0 // M2 clear ar.ccv
+ mov b7=r14 // I0 clear b7 (hint with __kernel_syscall_via_epc)
+@@ -913,10 +948,18 @@ GLOBAL_ENTRY(ia64_leave_kernel)
+ adds r16=PT(CR_IPSR)+16,r12
+ adds r17=PT(CR_IIP)+16,r12
+
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++ .pred.rel.mutex pUStk,pKStk
++(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled
++(pUStk) mov.m r22=ar.itc // M fetch time at leave
++ nop.i 0
++ ;;
++#else
+ (pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled
+ nop.i 0
+ nop.i 0
+ ;;
++#endif
+ ld8 r29=[r16],16 // load cr.ipsr
+ ld8 r28=[r17],16 // load cr.iip
+ ;;
+@@ -938,15 +981,37 @@ GLOBAL_ENTRY(ia64_leave_kernel)
+ ;;
+ ld8.fill r12=[r16],16
+ ld8.fill r13=[r17],16
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++(pUStk) adds r3=TI_AC_LEAVE+IA64_TASK_SIZE,r18
++#else
+ (pUStk) adds r18=IA64_TASK_THREAD_ON_USTACK_OFFSET,r18
++#endif
+ ;;
+ ld8 r20=[r16],16 // ar.fpsr
+ ld8.fill r15=[r17],16
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++(pUStk) adds r18=IA64_TASK_THREAD_ON_USTACK_OFFSET,r18 // deferred
++#endif
+ ;;
+ ld8.fill r14=[r16],16
+ ld8.fill r2=[r17]
+ (pUStk) mov r17=1
+ ;;
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++ // mmi_ : ld8 st1 shr;; mmi_ : st8 st1 shr;;
++ // mib : mov add br -> mib : ld8 add br
++ // bbb_ : br nop cover;; mbb_ : mov br cover;;
++ //
++ // no one require bsp in r16 if (pKStk) branch is selected.
++(pUStk) st8 [r3]=r22 // save time at leave
++(pUStk) st1 [r18]=r17 // restore current->thread.on_ustack
++ shr.u r18=r19,16 // get byte size of existing "dirty" partition
++ ;;
++ ld8.fill r3=[r16] // deferred
++ LOAD_PHYS_STACK_REG_SIZE(r17)
++(pKStk) br.cond.dpnt skip_rbs_switch
++ mov r16=ar.bsp // get existing backing store pointer
++#else
+ ld8.fill r3=[r16]
+ (pUStk) st1 [r18]=r17 // restore current->thread.on_ustack
+ shr.u r18=r19,16 // get byte size of existing "dirty" partition
+@@ -954,6 +1019,7 @@ GLOBAL_ENTRY(ia64_leave_kernel)
+ mov r16=ar.bsp // get existing backing store pointer
+ LOAD_PHYS_STACK_REG_SIZE(r17)
+ (pKStk) br.cond.dpnt skip_rbs_switch
++#endif
+
+ /*
+ * Restore user backing store.
+diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
+index 4484197..c1625c7 100644
+--- a/arch/ia64/kernel/fsys.S
++++ b/arch/ia64/kernel/fsys.S
+@@ -61,13 +61,29 @@ ENTRY(fsys_getpid)
+ .prologue
+ .altrp b6
+ .body
++ add r17=IA64_TASK_GROUP_LEADER_OFFSET,r16
++ ;;
++ ld8 r17=[r17] // r17 = current->group_leader
+ add r9=TI_FLAGS+IA64_TASK_SIZE,r16
+ ;;
+ ld4 r9=[r9]
+- add r8=IA64_TASK_TGID_OFFSET,r16
++ add r17=IA64_TASK_TGIDLINK_OFFSET,r17
+ ;;
+ and r9=TIF_ALLWORK_MASK,r9
+- ld4 r8=[r8] // r8 = current->tgid
++ ld8 r17=[r17] // r17 = current->group_leader->pids[PIDTYPE_PID].pid
++ ;;
++ add r8=IA64_PID_LEVEL_OFFSET,r17
++ ;;
++ ld4 r8=[r8] // r8 = pid->level
++ add r17=IA64_PID_UPID_OFFSET,r17 // r17 = &pid->numbers[0]
++ ;;
++ shl r8=r8,IA64_UPID_SHIFT
++ ;;
++ add r17=r17,r8 // r17 = &pid->numbers[pid->level]
++ ;;
++ ld4 r8=[r17] // r8 = pid->numbers[pid->level].nr
++ ;;
++ mov r17=0
+ ;;
+ cmp.ne p8,p0=0,r9
+ (p8) br.spnt.many fsys_fallback_syscall
+@@ -126,15 +142,25 @@ ENTRY(fsys_set_tid_address)
+ .altrp b6
+ .body
+ add r9=TI_FLAGS+IA64_TASK_SIZE,r16
++ add r17=IA64_TASK_TGIDLINK_OFFSET,r16
+ ;;
+ ld4 r9=[r9]
+ tnat.z p6,p7=r32 // check argument register for being NaT
++ ld8 r17=[r17] // r17 = current->pids[PIDTYPE_PID].pid
+ ;;
+ and r9=TIF_ALLWORK_MASK,r9
+- add r8=IA64_TASK_PID_OFFSET,r16
++ add r8=IA64_PID_LEVEL_OFFSET,r17
+ add r18=IA64_TASK_CLEAR_CHILD_TID_OFFSET,r16
+ ;;
+- ld4 r8=[r8]
++ ld4 r8=[r8] // r8 = pid->level
++ add r17=IA64_PID_UPID_OFFSET,r17 // r17 = &pid->numbers[0]
++ ;;
++ shl r8=r8,IA64_UPID_SHIFT
++ ;;
++ add r17=r17,r8 // r17 = &pid->numbers[pid->level]
++ ;;
++ ld4 r8=[r17] // r8 = pid->numbers[pid->level].nr
++ ;;
+ cmp.ne p8,p0=0,r9
+ mov r17=-1
+ ;;
+@@ -210,27 +236,25 @@ ENTRY(fsys_gettimeofday)
+ // Note that instructions are optimized for McKinley. McKinley can
+ // process two bundles simultaneously and therefore we continuously
+ // try to feed the CPU two bundles and then a stop.
+- //
+- // Additional note that code has changed a lot. Optimization is TBD.
+- // Comments begin with "?" are maybe outdated.
+- tnat.nz p6,p0 = r31 // ? branch deferred to fit later bundle
+- mov pr = r30,0xc000 // Set predicates according to function
++
+ add r2 = TI_FLAGS+IA64_TASK_SIZE,r16
++ tnat.nz p6,p0 = r31 // guard against Nat argument
++(p6) br.cond.spnt.few .fail_einval
+ movl r20 = fsyscall_gtod_data // load fsyscall gettimeofday data address
+ ;;
++ ld4 r2 = [r2] // process work pending flags
+ movl r29 = itc_jitter_data // itc_jitter
+ add r22 = IA64_GTOD_WALL_TIME_OFFSET,r20 // wall_time
+- ld4 r2 = [r2] // process work pending flags
+- ;;
+-(p15) add r22 = IA64_GTOD_MONO_TIME_OFFSET,r20 // monotonic_time
+ add r21 = IA64_CLKSRC_MMIO_OFFSET,r20
+- add r19 = IA64_ITC_LASTCYCLE_OFFSET,r29
++ mov pr = r30,0xc000 // Set predicates according to function
++ ;;
+ and r2 = TIF_ALLWORK_MASK,r2
+-(p6) br.cond.spnt.few .fail_einval // ? deferred branch
++ add r19 = IA64_ITC_LASTCYCLE_OFFSET,r29
++(p15) add r22 = IA64_GTOD_MONO_TIME_OFFSET,r20 // monotonic_time
+ ;;
+- add r26 = IA64_CLKSRC_CYCLE_LAST_OFFSET,r20 // clksrc_cycle_last
++ add r26 = IA64_CLKSRC_CYCLE_LAST_OFFSET,r20 // clksrc_cycle_last
+ cmp.ne p6, p0 = 0, r2 // Fallback if work is scheduled
+-(p6) br.cond.spnt.many fsys_fallback_syscall
++(p6) br.cond.spnt.many fsys_fallback_syscall
+ ;;
+ // Begin critical section
+ .time_redo:
+@@ -258,7 +282,6 @@ ENTRY(fsys_gettimeofday)
+ (p8) mov r2 = ar.itc // CPU_TIMER. 36 clocks latency!!!
+ (p9) ld8 r2 = [r30] // MMIO_TIMER. Could also have latency issues..
+ (p13) ld8 r25 = [r19] // get itc_lastcycle value
+- ;; // ? could be removed by moving the last add upward
+ ld8 r9 = [r22],IA64_TIMESPEC_TV_NSEC_OFFSET // tv_sec
+ ;;
+ ld8 r8 = [r22],-IA64_TIMESPEC_TV_NSEC_OFFSET // tv_nsec
+@@ -285,13 +308,12 @@ ENTRY(fsys_gettimeofday)
+ EX(.fail_efault, probe.w.fault r31, 3)
+ xmpy.l f8 = f8,f7 // nsec_per_cyc*(counter-last_counter)
+ ;;
+- // ? simulate tbit.nz.or p7,p0 = r28,0
+ getf.sig r2 = f8
+ mf
+ ;;
+ ld4 r10 = [r20] // gtod_lock.sequence
+ shr.u r2 = r2,r23 // shift by factor
+- ;; // ? overloaded 3 bundles!
++ ;;
+ add r8 = r8,r2 // Add xtime.nsecs
+ cmp4.ne p7,p0 = r28,r10
+ (p7) br.cond.dpnt.few .time_redo // sequence number changed, redo
+@@ -319,9 +341,9 @@ EX(.fail_efault, probe.w.fault r31, 3)
+ EX(.fail_efault, probe.w.fault r23, 3) // This also costs 5 cycles
+ (p14) xmpy.hu f8 = f8, f7 // xmpy has 5 cycles latency so use it
+ ;;
+- mov r8 = r0
+ (p14) getf.sig r2 = f8
+ ;;
++ mov r8 = r0
+ (p14) shr.u r21 = r2, 4
+ ;;
+ EX(.fail_efault, st8 [r31] = r9)
+@@ -660,7 +682,11 @@ GLOBAL_ENTRY(fsys_bubble_down)
+ nop.i 0
+ ;;
+ mov ar.rsc=0 // M2 set enforced lazy mode, pl 0, LE, loadrs=0
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++ mov.m r30=ar.itc // M get cycle for accounting
++#else
+ nop.m 0
++#endif
+ nop.i 0
+ ;;
+ mov r23=ar.bspstore // M2 (12 cyc) save ar.bspstore
+@@ -682,6 +708,28 @@ GLOBAL_ENTRY(fsys_bubble_down)
+ cmp.ne pKStk,pUStk=r0,r0 // A set pKStk <- 0, pUStk <- 1
+ br.call.sptk.many b7=ia64_syscall_setup // B
+ ;;
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++ // mov.m r30=ar.itc is called in advance
++ add r16=TI_AC_STAMP+IA64_TASK_SIZE,r2
++ add r17=TI_AC_LEAVE+IA64_TASK_SIZE,r2
++ ;;
++ ld8 r18=[r16],TI_AC_STIME-TI_AC_STAMP // time at last check in kernel
++ ld8 r19=[r17],TI_AC_UTIME-TI_AC_LEAVE // time at leave kernel
++ ;;
++ ld8 r20=[r16],TI_AC_STAMP-TI_AC_STIME // cumulated stime
++ ld8 r21=[r17] // cumulated utime
++ sub r22=r19,r18 // stime before leave kernel
++ ;;
++ st8 [r16]=r30,TI_AC_STIME-TI_AC_STAMP // update stamp
++ sub r18=r30,r19 // elapsed time in user mode
++ ;;
++ add r20=r20,r22 // sum stime
++ add r21=r21,r18 // sum utime
++ ;;
++ st8 [r16]=r20 // update stime
++ st8 [r17]=r21 // update utime
++ ;;
++#endif
+ mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0
+ mov rp=r14 // I0 set the real return addr
+ and r3=_TIF_SYSCALL_TRACEAUDIT,r3 // A
+diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
+index d3a41d5..ddeab4e 100644
+--- a/arch/ia64/kernel/head.S
++++ b/arch/ia64/kernel/head.S
+@@ -1002,6 +1002,26 @@ GLOBAL_ENTRY(sched_clock)
+ br.ret.sptk.many rp
+ END(sched_clock)
+
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++GLOBAL_ENTRY(cycle_to_cputime)
++ alloc r16=ar.pfs,1,0,0,0
++ addl r8=THIS_CPU(cpu_info) + IA64_CPUINFO_NSEC_PER_CYC_OFFSET,r0
++ ;;
++ ldf8 f8=[r8]
++ ;;
++ setf.sig f9=r32
++ ;;
++ xmpy.lu f10=f9,f8 // calculate low 64 bits of 128-bit product (4 cyc)
++ xmpy.hu f11=f9,f8 // calculate high 64 bits of 128-bit product
++ ;;
++ getf.sig r8=f10 // (5 cyc)
++ getf.sig r9=f11
++ ;;
++ shrp r8=r9,r8,IA64_NSEC_PER_CYC_SHIFT
++ br.ret.sptk.many rp
++END(cycle_to_cputime)
++#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
++
+ GLOBAL_ENTRY(start_kernel_thread)
+ .prologue
+ .save rp, r0 // this is the end of the call-chain
+diff --git a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c
+index 8e7193d..6da1f20 100644
+--- a/arch/ia64/kernel/ia64_ksyms.c
++++ b/arch/ia64/kernel/ia64_ksyms.c
+@@ -19,12 +19,6 @@ EXPORT_SYMBOL_GPL(empty_zero_page);
+ EXPORT_SYMBOL(ip_fast_csum); /* hand-coded assembly */
+ EXPORT_SYMBOL(csum_ipv6_magic);
+
+-#include <asm/semaphore.h>
+-EXPORT_SYMBOL(__down);
+-EXPORT_SYMBOL(__down_interruptible);
+-EXPORT_SYMBOL(__down_trylock);
+-EXPORT_SYMBOL(__up);
+-
+ #include <asm/page.h>
+ EXPORT_SYMBOL(clear_page);
+
+diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
+index d8be23f..5538471 100644
+--- a/arch/ia64/kernel/irq_ia64.c
++++ b/arch/ia64/kernel/irq_ia64.c
+@@ -472,7 +472,7 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)
+ static unsigned char count;
+ static long last_time;
+
+- if (jiffies - last_time > 5*HZ)
++ if (time_after(jiffies, last_time + 5 * HZ))
+ count = 0;
+ if (++count < 5) {
+ last_time = jiffies;
+diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S
+index 34f44d8..6678c49 100644
+--- a/arch/ia64/kernel/ivt.S
++++ b/arch/ia64/kernel/ivt.S
+@@ -805,8 +805,13 @@ ENTRY(break_fault)
+
+ (p8) adds r28=16,r28 // A switch cr.iip to next bundle
+ (p9) adds r8=1,r8 // A increment ei to next slot
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++ ;;
++ mov b6=r30 // I0 setup syscall handler branch reg early
++#else
+ nop.i 0
+ ;;
++#endif
+
+ mov.m r25=ar.unat // M2 (5 cyc)
+ dep r29=r8,r29,41,2 // I0 insert new ei into cr.ipsr
+@@ -817,7 +822,11 @@ ENTRY(break_fault)
+ //
+ ///////////////////////////////////////////////////////////////////////
+ st1 [r16]=r0 // M2|3 clear current->thread.on_ustack flag
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++ mov.m r30=ar.itc // M get cycle for accounting
++#else
+ mov b6=r30 // I0 setup syscall handler branch reg early
++#endif
+ cmp.eq pKStk,pUStk=r0,r17 // A were we on kernel stacks already?
+
+ and r9=_TIF_SYSCALL_TRACEAUDIT,r9 // A mask trace or audit
+@@ -829,6 +838,30 @@ ENTRY(break_fault)
+ cmp.eq p14,p0=r9,r0 // A are syscalls being traced/audited?
+ br.call.sptk.many b7=ia64_syscall_setup // B
+ 1:
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++ // mov.m r30=ar.itc is called in advance, and r13 is current
++ add r16=TI_AC_STAMP+IA64_TASK_SIZE,r13 // A
++ add r17=TI_AC_LEAVE+IA64_TASK_SIZE,r13 // A
++(pKStk) br.cond.spnt .skip_accounting // B unlikely skip
++ ;;
++ ld8 r18=[r16],TI_AC_STIME-TI_AC_STAMP // M get last stamp
++ ld8 r19=[r17],TI_AC_UTIME-TI_AC_LEAVE // M time at leave
++ ;;
++ ld8 r20=[r16],TI_AC_STAMP-TI_AC_STIME // M cumulated stime
++ ld8 r21=[r17] // M cumulated utime
++ sub r22=r19,r18 // A stime before leave
++ ;;
++ st8 [r16]=r30,TI_AC_STIME-TI_AC_STAMP // M update stamp
++ sub r18=r30,r19 // A elapsed time in user
++ ;;
++ add r20=r20,r22 // A sum stime
++ add r21=r21,r18 // A sum utime
++ ;;
++ st8 [r16]=r20 // M update stime
++ st8 [r17]=r21 // M update utime
++ ;;
++.skip_accounting:
++#endif
+ mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0
+ nop 0
+ bsw.1 // B (6 cyc) regs are saved, switch to bank 1
+@@ -928,6 +961,7 @@ END(interrupt)
+ * - r27: saved ar.rsc
+ * - r28: saved cr.iip
+ * - r29: saved cr.ipsr
++ * - r30: ar.itc for accounting (don't touch)
+ * - r31: saved pr
+ * - b0: original contents (to be saved)
+ * On exit:
+@@ -1090,6 +1124,41 @@ END(dispatch_illegal_op_fault)
+ DBG_FAULT(16)
+ FAULT(16)
+
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++ /*
++ * There is no particular reason for this code to be here, other than
++ * that there happens to be space here that would go unused otherwise.
++ * If this fault ever gets "unreserved", simply moved the following
++ * code to a more suitable spot...
++ *
++ * account_sys_enter is called from SAVE_MIN* macros if accounting is
++ * enabled and if the macro is entered from user mode.
++ */
++ENTRY(account_sys_enter)
++ // mov.m r20=ar.itc is called in advance, and r13 is current
++ add r16=TI_AC_STAMP+IA64_TASK_SIZE,r13
++ add r17=TI_AC_LEAVE+IA64_TASK_SIZE,r13
++ ;;
++ ld8 r18=[r16],TI_AC_STIME-TI_AC_STAMP // time at last check in kernel
++ ld8 r19=[r17],TI_AC_UTIME-TI_AC_LEAVE // time at left from kernel
++ ;;
++ ld8 r23=[r16],TI_AC_STAMP-TI_AC_STIME // cumulated stime
++ ld8 r21=[r17] // cumulated utime
++ sub r22=r19,r18 // stime before leave kernel
++ ;;
++ st8 [r16]=r20,TI_AC_STIME-TI_AC_STAMP // update stamp
++ sub r18=r20,r19 // elapsed time in user mode
++ ;;
++ add r23=r23,r22 // sum stime
++ add r21=r21,r18 // sum utime
++ ;;
++ st8 [r16]=r23 // update stime
++ st8 [r17]=r21 // update utime
++ ;;
++ br.ret.sptk.many rp
++END(account_sys_enter)
++#endif
++
+ .org ia64_ivt+0x4400
+ /////////////////////////////////////////////////////////////////////////////////////////
+ // 0x4400 Entry 17 (size 64 bundles) Reserved
+diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
+index 8d9a446..233434f 100644
+--- a/arch/ia64/kernel/kprobes.c
++++ b/arch/ia64/kernel/kprobes.c
+@@ -78,6 +78,20 @@ static enum instruction_type bundle_encoding[32][3] = {
+ { u, u, u }, /* 1F */
+ };
+
++/* Insert a long branch code */
++static void __kprobes set_brl_inst(void *from, void *to)
++{
++ s64 rel = ((s64) to - (s64) from) >> 4;
++ bundle_t *brl;
++ brl = (bundle_t *) ((u64) from & ~0xf);
++ brl->quad0.template = 0x05; /* [MLX](stop) */
++ brl->quad0.slot0 = NOP_M_INST; /* nop.m 0x0 */
++ brl->quad0.slot1_p0 = ((rel >> 20) & 0x7fffffffff) << 2;
++ brl->quad1.slot1_p1 = (((rel >> 20) & 0x7fffffffff) << 2) >> (64 - 46);
++ /* brl.cond.sptk.many.clr rel<<4 (qp=0) */
++ brl->quad1.slot2 = BRL_INST(rel >> 59, rel & 0xfffff);
++}
++
+ /*
+ * In this function we check to see if the instruction
+ * is IP relative instruction and update the kprobe
+@@ -496,6 +510,77 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
+ regs->b0 = ((struct fnptr *)kretprobe_trampoline)->ip;
+ }
+
++/* Check the instruction in the slot is break */
++static int __kprobes __is_ia64_break_inst(bundle_t *bundle, uint slot)
++{
++ unsigned int major_opcode;
++ unsigned int template = bundle->quad0.template;
++ unsigned long kprobe_inst;
++
++ /* Move to slot 2, if bundle is MLX type and kprobe slot is 1 */
++ if (slot == 1 && bundle_encoding[template][1] == L)
++ slot++;
++
++ /* Get Kprobe probe instruction at given slot*/
++ get_kprobe_inst(bundle, slot, &kprobe_inst, &major_opcode);
++
++ /* For break instruction,
++ * Bits 37:40 Major opcode to be zero
++ * Bits 27:32 X6 to be zero
++ * Bits 32:35 X3 to be zero
++ */
++ if (major_opcode || ((kprobe_inst >> 27) & 0x1FF)) {
++ /* Not a break instruction */
++ return 0;
++ }
++
++ /* Is a break instruction */
++ return 1;
++}
++
++/*
++ * In this function, we check whether the target bundle modifies IP or
++ * it triggers an exception. If so, it cannot be boostable.
++ */
++static int __kprobes can_boost(bundle_t *bundle, uint slot,
++ unsigned long bundle_addr)
++{
++ unsigned int template = bundle->quad0.template;
++
++ do {
++ if (search_exception_tables(bundle_addr + slot) ||
++ __is_ia64_break_inst(bundle, slot))
++ return 0; /* exception may occur in this bundle*/
++ } while ((++slot) < 3);
++ template &= 0x1e;
++ if (template >= 0x10 /* including B unit */ ||
++ template == 0x04 /* including X unit */ ||
++ template == 0x06) /* undefined */
++ return 0;
++
++ return 1;
++}
++
++/* Prepare long jump bundle and disables other boosters if need */
++static void __kprobes prepare_booster(struct kprobe *p)
++{
++ unsigned long addr = (unsigned long)p->addr & ~0xFULL;
++ unsigned int slot = (unsigned long)p->addr & 0xf;
++ struct kprobe *other_kp;
++
++ if (can_boost(&p->ainsn.insn[0].bundle, slot, addr)) {
++ set_brl_inst(&p->ainsn.insn[1].bundle, (bundle_t *)addr + 1);
++ p->ainsn.inst_flag |= INST_FLAG_BOOSTABLE;
++ }
++
++ /* disables boosters in previous slots */
++ for (; addr < (unsigned long)p->addr; addr++) {
++ other_kp = get_kprobe((void *)addr);
++ if (other_kp)
++ other_kp->ainsn.inst_flag &= ~INST_FLAG_BOOSTABLE;
++ }
++}
++
+ int __kprobes arch_prepare_kprobe(struct kprobe *p)
+ {
+ unsigned long addr = (unsigned long) p->addr;
+@@ -530,6 +615,8 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
+
+ prepare_break_inst(template, slot, major_opcode, kprobe_inst, p, qp);
+
++ prepare_booster(p);
++
+ return 0;
+ }
+
+@@ -543,7 +630,9 @@ void __kprobes arch_arm_kprobe(struct kprobe *p)
+ src = &p->opcode.bundle;
+
+ flush_icache_range((unsigned long)p->ainsn.insn,
+- (unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t));
++ (unsigned long)p->ainsn.insn +
++ sizeof(kprobe_opcode_t) * MAX_INSN_SIZE);
++
+ switch (p->ainsn.slot) {
+ case 0:
+ dest->quad0.slot0 = src->quad0.slot0;
+@@ -584,13 +673,13 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
+ void __kprobes arch_remove_kprobe(struct kprobe *p)
+ {
+ mutex_lock(&kprobe_mutex);
+- free_insn_slot(p->ainsn.insn, 0);
++ free_insn_slot(p->ainsn.insn, p->ainsn.inst_flag & INST_FLAG_BOOSTABLE);
+ mutex_unlock(&kprobe_mutex);
+ }
+ /*
+ * We are resuming execution after a single step fault, so the pt_regs
+ * structure reflects the register state after we executed the instruction
+- * located in the kprobe (p->ainsn.insn.bundle). We still need to adjust
++ * located in the kprobe (p->ainsn.insn->bundle). We still need to adjust
+ * the ip to point back to the original stack address. To set the IP address
+ * to original stack address, handle the case where we need to fixup the
+ * relative IP address and/or fixup branch register.
+@@ -607,7 +696,7 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
+ if (slot == 1 && bundle_encoding[template][1] == L)
+ slot = 2;
+
+- if (p->ainsn.inst_flag) {
++ if (p->ainsn.inst_flag & ~INST_FLAG_BOOSTABLE) {
+
+ if (p->ainsn.inst_flag & INST_FLAG_FIX_RELATIVE_IP_ADDR) {
+ /* Fix relative IP address */
+@@ -686,33 +775,12 @@ static void __kprobes prepare_ss(struct kprobe *p, struct pt_regs *regs)
+ static int __kprobes is_ia64_break_inst(struct pt_regs *regs)
+ {
+ unsigned int slot = ia64_psr(regs)->ri;
+- unsigned int template, major_opcode;
+- unsigned long kprobe_inst;
+ unsigned long *kprobe_addr = (unsigned long *)regs->cr_iip;
+ bundle_t bundle;
+
+ memcpy(&bundle, kprobe_addr, sizeof(bundle_t));
+- template = bundle.quad0.template;
+-
+- /* Move to slot 2, if bundle is MLX type and kprobe slot is 1 */
+- if (slot == 1 && bundle_encoding[template][1] == L)
+- slot++;
+
+- /* Get Kprobe probe instruction at given slot*/
+- get_kprobe_inst(&bundle, slot, &kprobe_inst, &major_opcode);
+-
+- /* For break instruction,
+- * Bits 37:40 Major opcode to be zero
+- * Bits 27:32 X6 to be zero
+- * Bits 32:35 X3 to be zero
+- */
+- if (major_opcode || ((kprobe_inst >> 27) & 0x1FF) ) {
+- /* Not a break instruction */
+- return 0;
+- }
+-
+- /* Is a break instruction */
+- return 1;
++ return __is_ia64_break_inst(&bundle, slot);
+ }
+
+ static int __kprobes pre_kprobes_handler(struct die_args *args)
+@@ -802,6 +870,19 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
+ return 1;
+
+ ss_probe:
++#if !defined(CONFIG_PREEMPT) || defined(CONFIG_PM)
++ if (p->ainsn.inst_flag == INST_FLAG_BOOSTABLE && !p->post_handler) {
++ /* Boost up -- we can execute copied instructions directly */
++ ia64_psr(regs)->ri = p->ainsn.slot;
++ regs->cr_iip = (unsigned long)&p->ainsn.insn->bundle & ~0xFULL;
++ /* turn single stepping off */
++ ia64_psr(regs)->ss = 0;
++
++ reset_current_kprobe();
++ preempt_enable_no_resched();
++ return 1;
++ }
++#endif
+ prepare_ss(p, regs);
+ kcb->kprobe_status = KPROBE_HIT_SS;
+ return 1;
+diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
+index 6c18221..705176b 100644
+--- a/arch/ia64/kernel/mca.c
++++ b/arch/ia64/kernel/mca.c
+@@ -69,6 +69,7 @@
+ * 2007-04-27 Russ Anderson <rja at sgi.com>
+ * Support multiple cpus going through OS_MCA in the same event.
+ */
++#include <linux/jiffies.h>
+ #include <linux/types.h>
+ #include <linux/init.h>
+ #include <linux/sched.h>
+@@ -97,6 +98,7 @@
+
+ #include <asm/irq.h>
+ #include <asm/hw_irq.h>
++#include <asm/tlb.h>
+
+ #include "mca_drv.h"
+ #include "entry.h"
+@@ -107,11 +109,26 @@
+ # define IA64_MCA_DEBUG(fmt...)
+ #endif
+
++#define NOTIFY_INIT(event, regs, arg, spin) \
++do { \
++ if ((notify_die((event), "INIT", (regs), (arg), 0, 0) \
++ == NOTIFY_STOP) && ((spin) == 1)) \
++ ia64_mca_spin(__func__); \
++} while (0)
++
++#define NOTIFY_MCA(event, regs, arg, spin) \
++do { \
++ if ((notify_die((event), "MCA", (regs), (arg), 0, 0) \
++ == NOTIFY_STOP) && ((spin) == 1)) \
++ ia64_mca_spin(__func__); \
++} while (0)
++
+ /* Used by mca_asm.S */
+ DEFINE_PER_CPU(u64, ia64_mca_data); /* == __per_cpu_mca[smp_processor_id()] */
+ DEFINE_PER_CPU(u64, ia64_mca_per_cpu_pte); /* PTE to map per-CPU area */
+ DEFINE_PER_CPU(u64, ia64_mca_pal_pte); /* PTE to map PAL code */
+ DEFINE_PER_CPU(u64, ia64_mca_pal_base); /* vaddr PAL code granule */
++DEFINE_PER_CPU(u64, ia64_mca_tr_reload); /* Flag for TR reload */
+
+ unsigned long __per_cpu_mca[NR_CPUS];
+
+@@ -293,7 +310,8 @@ static void ia64_mlogbuf_dump_from_init(void)
+ if (mlogbuf_finished)
+ return;
+
+- if (mlogbuf_timestamp && (mlogbuf_timestamp + 30*HZ > jiffies)) {
++ if (mlogbuf_timestamp &&
++ time_before(jiffies, mlogbuf_timestamp + 30 * HZ)) {
+ printk(KERN_ERR "INIT: mlogbuf_dump is interrupted by INIT "
+ " and the system seems to be messed up.\n");
+ ia64_mlogbuf_finish(0);
+@@ -762,9 +780,8 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg)
+
+ /* Mask all interrupts */
+ local_irq_save(flags);
+- if (notify_die(DIE_MCA_RENDZVOUS_ENTER, "MCA", get_irq_regs(),
+- (long)&nd, 0, 0) == NOTIFY_STOP)
+- ia64_mca_spin(__func__);
++
++ NOTIFY_MCA(DIE_MCA_RENDZVOUS_ENTER, get_irq_regs(), (long)&nd, 1);
+
+ ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_DONE;
+ /* Register with the SAL monarch that the slave has
+@@ -772,17 +789,13 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg)
+ */
+ ia64_sal_mc_rendez();
+
+- if (notify_die(DIE_MCA_RENDZVOUS_PROCESS, "MCA", get_irq_regs(),
+- (long)&nd, 0, 0) == NOTIFY_STOP)
+- ia64_mca_spin(__func__);
++ NOTIFY_MCA(DIE_MCA_RENDZVOUS_PROCESS, get_irq_regs(), (long)&nd, 1);
+
+ /* Wait for the monarch cpu to exit. */
+ while (monarch_cpu != -1)
+ cpu_relax(); /* spin until monarch leaves */
+
+- if (notify_die(DIE_MCA_RENDZVOUS_LEAVE, "MCA", get_irq_regs(),
+- (long)&nd, 0, 0) == NOTIFY_STOP)
+- ia64_mca_spin(__func__);
++ NOTIFY_MCA(DIE_MCA_RENDZVOUS_LEAVE, get_irq_regs(), (long)&nd, 1);
+
+ ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
+ /* Enable all interrupts */
+@@ -1182,6 +1195,49 @@ all_in:
+ return;
+ }
+
++/* mca_insert_tr
++ *
++ * Switch rid when TR reload and needed!
++ * iord: 1: itr, 2: itr;
++ *
++*/
++static void mca_insert_tr(u64 iord)
++{
++
++ int i;
++ u64 old_rr;
++ struct ia64_tr_entry *p;
++ unsigned long psr;
++ int cpu = smp_processor_id();
++
++ psr = ia64_clear_ic();
++ for (i = IA64_TR_ALLOC_BASE; i < IA64_TR_ALLOC_MAX; i++) {
++ p = &__per_cpu_idtrs[cpu][iord-1][i];
++ if (p->pte & 0x1) {
++ old_rr = ia64_get_rr(p->ifa);
++ if (old_rr != p->rr) {
++ ia64_set_rr(p->ifa, p->rr);
++ ia64_srlz_d();
++ }
++ ia64_ptr(iord, p->ifa, p->itir >> 2);
++ ia64_srlz_i();
++ if (iord & 0x1) {
++ ia64_itr(0x1, i, p->ifa, p->pte, p->itir >> 2);
++ ia64_srlz_i();
++ }
++ if (iord & 0x2) {
++ ia64_itr(0x2, i, p->ifa, p->pte, p->itir >> 2);
++ ia64_srlz_i();
++ }
++ if (old_rr != p->rr) {
++ ia64_set_rr(p->ifa, old_rr);
++ ia64_srlz_d();
++ }
++ }
++ }
++ ia64_set_psr(psr);
++}
++
+ /*
+ * ia64_mca_handler
+ *
+@@ -1209,7 +1265,7 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
+ int recover, cpu = smp_processor_id();
+ struct task_struct *previous_current;
+ struct ia64_mca_notify_die nd =
+- { .sos = sos, .monarch_cpu = &monarch_cpu };
++ { .sos = sos, .monarch_cpu = &monarch_cpu, .data = &recover };
+ static atomic_t mca_count;
+ static cpumask_t mca_cpu;
+
+@@ -1225,9 +1281,7 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
+
+ previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA");
+
+- if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, (long)&nd, 0, 0)
+- == NOTIFY_STOP)
+- ia64_mca_spin(__func__);
++ NOTIFY_MCA(DIE_MCA_MONARCH_ENTER, regs, (long)&nd, 1);
+
+ ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA;
+ if (sos->monarch) {
+@@ -1241,13 +1295,12 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
+ * does not work.
+ */
+ ia64_mca_wakeup_all();
+- if (notify_die(DIE_MCA_MONARCH_PROCESS, "MCA", regs, (long)&nd, 0, 0)
+- == NOTIFY_STOP)
+- ia64_mca_spin(__func__);
+ } else {
+ while (cpu_isset(cpu, mca_cpu))
+ cpu_relax(); /* spin until monarch wakes us */
+- }
++ }
++
++ NOTIFY_MCA(DIE_MCA_MONARCH_PROCESS, regs, (long)&nd, 1);
+
+ /* Get the MCA error record and log it */
+ ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA);
+@@ -1266,15 +1319,14 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
+ } else {
+ /* Dump buffered message to console */
+ ia64_mlogbuf_finish(1);
+-#ifdef CONFIG_KEXEC
+- atomic_set(&kdump_in_progress, 1);
+- monarch_cpu = -1;
+-#endif
+ }
+- if (notify_die(DIE_MCA_MONARCH_LEAVE, "MCA", regs, (long)&nd, 0, recover)
+- == NOTIFY_STOP)
+- ia64_mca_spin(__func__);
+
++ if (__get_cpu_var(ia64_mca_tr_reload)) {
++ mca_insert_tr(0x1); /*Reload dynamic itrs*/
++ mca_insert_tr(0x2); /*Reload dynamic itrs*/
++ }
++
++ NOTIFY_MCA(DIE_MCA_MONARCH_LEAVE, regs, (long)&nd, 1);
+
+ if (atomic_dec_return(&mca_count) > 0) {
+ int i;
+@@ -1595,7 +1647,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
+ struct ia64_mca_notify_die nd =
+ { .sos = sos, .monarch_cpu = &monarch_cpu };
+
+- (void) notify_die(DIE_INIT_ENTER, "INIT", regs, (long)&nd, 0, 0);
++ NOTIFY_INIT(DIE_INIT_ENTER, regs, (long)&nd, 0);
+
+ mprintk(KERN_INFO "Entered OS INIT handler. PSP=%lx cpu=%d monarch=%ld\n",
+ sos->proc_state_param, cpu, sos->monarch);
+@@ -1632,17 +1684,15 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
+ ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_INIT;
+ while (monarch_cpu == -1)
+ cpu_relax(); /* spin until monarch enters */
+- if (notify_die(DIE_INIT_SLAVE_ENTER, "INIT", regs, (long)&nd, 0, 0)
+- == NOTIFY_STOP)
+- ia64_mca_spin(__func__);
+- if (notify_die(DIE_INIT_SLAVE_PROCESS, "INIT", regs, (long)&nd, 0, 0)
+- == NOTIFY_STOP)
+- ia64_mca_spin(__func__);
++
++ NOTIFY_INIT(DIE_INIT_SLAVE_ENTER, regs, (long)&nd, 1);
++ NOTIFY_INIT(DIE_INIT_SLAVE_PROCESS, regs, (long)&nd, 1);
++
+ while (monarch_cpu != -1)
+ cpu_relax(); /* spin until monarch leaves */
+- if (notify_die(DIE_INIT_SLAVE_LEAVE, "INIT", regs, (long)&nd, 0, 0)
+- == NOTIFY_STOP)
+- ia64_mca_spin(__func__);
++
++ NOTIFY_INIT(DIE_INIT_SLAVE_LEAVE, regs, (long)&nd, 1);
++
+ mprintk("Slave on cpu %d returning to normal service.\n", cpu);
+ set_curr_task(cpu, previous_current);
+ ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
+@@ -1651,9 +1701,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
+ }
+
+ monarch_cpu = cpu;
+- if (notify_die(DIE_INIT_MONARCH_ENTER, "INIT", regs, (long)&nd, 0, 0)
+- == NOTIFY_STOP)
+- ia64_mca_spin(__func__);
++ NOTIFY_INIT(DIE_INIT_MONARCH_ENTER, regs, (long)&nd, 1);
+
+ /*
+ * Wait for a bit. On some machines (e.g., HP's zx2000 and zx6000, INIT can be
+@@ -1668,12 +1716,9 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
+ * to default_monarch_init_process() above and just print all the
+ * tasks.
+ */
+- if (notify_die(DIE_INIT_MONARCH_PROCESS, "INIT", regs, (long)&nd, 0, 0)
+- == NOTIFY_STOP)
+- ia64_mca_spin(__func__);
+- if (notify_die(DIE_INIT_MONARCH_LEAVE, "INIT", regs, (long)&nd, 0, 0)
+- == NOTIFY_STOP)
+- ia64_mca_spin(__func__);
++ NOTIFY_INIT(DIE_INIT_MONARCH_PROCESS, regs, (long)&nd, 1);
++ NOTIFY_INIT(DIE_INIT_MONARCH_LEAVE, regs, (long)&nd, 1);
++
+ mprintk("\nINIT dump complete. Monarch on cpu %d returning to normal service.\n", cpu);
+ atomic_dec(&monarchs);
+ set_curr_task(cpu, previous_current);
+@@ -1905,7 +1950,7 @@ ia64_mca_init(void)
+ printk(KERN_INFO "Increasing MCA rendezvous timeout from "
+ "%ld to %ld milliseconds\n", timeout, isrv.v0);
+ timeout = isrv.v0;
+- (void) notify_die(DIE_MCA_NEW_TIMEOUT, "MCA", NULL, timeout, 0, 0);
++ NOTIFY_MCA(DIE_MCA_NEW_TIMEOUT, NULL, timeout, 0);
+ continue;
+ }
+ printk(KERN_ERR "Failed to register rendezvous interrupt "
+diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
+index 8bc7d25..a06d465 100644
+--- a/arch/ia64/kernel/mca_asm.S
++++ b/arch/ia64/kernel/mca_asm.S
+@@ -219,8 +219,13 @@ ia64_reload_tr:
+ mov r20=IA64_TR_CURRENT_STACK
+ ;;
+ itr.d dtr[r20]=r16
++ GET_THIS_PADDR(r2, ia64_mca_tr_reload)
++ mov r18 = 1
+ ;;
+ srlz.d
++ ;;
++ st8 [r2] =r18
++ ;;
+
+ done_tlb_purge_and_reload:
+
+diff --git a/arch/ia64/kernel/minstate.h b/arch/ia64/kernel/minstate.h
+index c9ac8ba..7c548ac 100644
+--- a/arch/ia64/kernel/minstate.h
++++ b/arch/ia64/kernel/minstate.h
+@@ -3,6 +3,18 @@
+
+ #include "entry.h"
+
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++/* read ar.itc in advance, and use it before leaving bank 0 */
++#define ACCOUNT_GET_STAMP \
++(pUStk) mov.m r20=ar.itc;
++#define ACCOUNT_SYS_ENTER \
++(pUStk) br.call.spnt rp=account_sys_enter \
++ ;;
++#else
++#define ACCOUNT_GET_STAMP
++#define ACCOUNT_SYS_ENTER
++#endif
++
+ /*
+ * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves
+ * the minimum state necessary that allows us to turn psr.ic back
+@@ -122,11 +134,13 @@
+ ;; \
+ .mem.offset 0,0; st8.spill [r16]=r2,16; \
+ .mem.offset 8,0; st8.spill [r17]=r3,16; \
++ ACCOUNT_GET_STAMP \
+ adds r2=IA64_PT_REGS_R16_OFFSET,r1; \
+ ;; \
+ EXTRA; \
+ movl r1=__gp; /* establish kernel global pointer */ \
+ ;; \
++ ACCOUNT_SYS_ENTER \
+ bsw.1; /* switch back to bank 1 (must be last in insn group) */ \
+ ;;
+
+diff --git a/arch/ia64/kernel/numa.c b/arch/ia64/kernel/numa.c
+index a78b45f..c93420c 100644
+--- a/arch/ia64/kernel/numa.c
++++ b/arch/ia64/kernel/numa.c
+@@ -73,7 +73,7 @@ void __init build_cpu_to_node_map(void)
+ for(node=0; node < MAX_NUMNODES; node++)
+ cpus_clear(node_to_cpu_mask[node]);
+
+- for(cpu = 0; cpu < NR_CPUS; ++cpu) {
++ for_each_possible_early_cpu(cpu) {
+ node = -1;
+ for (i = 0; i < NR_CPUS; ++i)
+ if (cpu_physical_id(cpu) == node_cpuid[i].phys_id) {
+diff --git a/arch/ia64/kernel/patch.c b/arch/ia64/kernel/patch.c
+index 2cb9425..e0dca87 100644
+--- a/arch/ia64/kernel/patch.c
++++ b/arch/ia64/kernel/patch.c
+@@ -135,10 +135,10 @@ ia64_patch_mckinley_e9 (unsigned long start, unsigned long end)
+
+ while (offp < (s32 *) end) {
+ wp = (u64 *) ia64_imva((char *) offp + *offp);
+- wp[0] = 0x0000000100000000UL; /* nop.m 0; nop.i 0; nop.i 0 */
+- wp[1] = 0x0004000000000200UL;
+- wp[2] = 0x0000000100000011UL; /* nop.m 0; nop.i 0; br.ret.sptk.many b6 */
+- wp[3] = 0x0084006880000200UL;
++ wp[0] = 0x0000000100000011UL; /* nop.m 0; nop.i 0; br.ret.sptk.many b6 */
++ wp[1] = 0x0084006880000200UL;
++ wp[2] = 0x0000000100000000UL; /* nop.m 0; nop.i 0; nop.i 0 */
++ wp[3] = 0x0004000000000200UL;
+ ia64_fc(wp); ia64_fc(wp + 2);
+ ++offp;
+ }
+diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
+index a2aabfd..c8e4037 100644
+--- a/arch/ia64/kernel/perfmon.c
++++ b/arch/ia64/kernel/perfmon.c
+@@ -4204,10 +4204,10 @@ pfm_check_task_exist(pfm_context_t *ctx)
+ do_each_thread (g, t) {
+ if (t->thread.pfm_context == ctx) {
+ ret = 0;
+- break;
++ goto out;
+ }
+ } while_each_thread (g, t);
+-
++out:
+ read_unlock(&tasklist_lock);
+
+ DPRINT(("pfm_check_task_exist: ret=%d ctx=%p\n", ret, ctx));
+@@ -5511,7 +5511,7 @@ stop_monitoring:
+ }
+
+ static int
+-pfm_do_interrupt_handler(int irq, void *arg, struct pt_regs *regs)
++pfm_do_interrupt_handler(void *arg, struct pt_regs *regs)
+ {
+ struct task_struct *task;
+ pfm_context_t *ctx;
+@@ -5591,7 +5591,7 @@ pfm_interrupt_handler(int irq, void *arg)
+
+ start_cycles = ia64_get_itc();
+
+- ret = pfm_do_interrupt_handler(irq, arg, regs);
++ ret = pfm_do_interrupt_handler(arg, regs);
+
+ total_cycles = ia64_get_itc();
+
+diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
+index 49937a3..a5ea817 100644
+--- a/arch/ia64/kernel/process.c
++++ b/arch/ia64/kernel/process.c
+@@ -625,21 +625,6 @@ do_dump_fpu (struct unw_frame_info *info, void *arg)
+ do_dump_task_fpu(current, info, arg);
+ }
+
+-int
+-dump_task_regs(struct task_struct *task, elf_gregset_t *regs)
+-{
+- struct unw_frame_info tcore_info;
+-
+- if (current == task) {
+- unw_init_running(do_copy_regs, regs);
+- } else {
+- memset(&tcore_info, 0, sizeof(tcore_info));
+- unw_init_from_blocked_task(&tcore_info, task);
+- do_copy_task_regs(task, &tcore_info, regs);
+- }
+- return 1;
+-}
+-
+ void
+ ia64_elf_core_copy_regs (struct pt_regs *pt, elf_gregset_t dst)
+ {
+@@ -647,21 +632,6 @@ ia64_elf_core_copy_regs (struct pt_regs *pt, elf_gregset_t dst)
+ }
+
+ int
+-dump_task_fpu (struct task_struct *task, elf_fpregset_t *dst)
+-{
+- struct unw_frame_info tcore_info;
+-
+- if (current == task) {
+- unw_init_running(do_dump_fpu, dst);
+- } else {
+- memset(&tcore_info, 0, sizeof(tcore_info));
+- unw_init_from_blocked_task(&tcore_info, task);
+- do_dump_task_fpu(task, &tcore_info, dst);
+- }
+- return 1;
+-}
+-
+-int
+ dump_fpu (struct pt_regs *pt, elf_fpregset_t dst)
+ {
+ unw_init_running(do_dump_fpu, dst);
+diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
+index ab784ec..2a9943b 100644
+--- a/arch/ia64/kernel/ptrace.c
++++ b/arch/ia64/kernel/ptrace.c
+@@ -3,6 +3,9 @@
+ *
+ * Copyright (C) 1999-2005 Hewlett-Packard Co
+ * David Mosberger-Tang <davidm at hpl.hp.com>
++ * Copyright (C) 2006 Intel Co
++ * 2006-08-12 - IA64 Native Utrace implementation support added by
++ * Anil S Keshavamurthy <anil.s.keshavamurthy at intel.com>
+ *
+ * Derived from the x86 and Alpha versions.
+ */
+@@ -17,6 +20,8 @@
+ #include <linux/security.h>
+ #include <linux/audit.h>
+ #include <linux/signal.h>
++#include <linux/regset.h>
++#include <linux/elf.h>
+
+ #include <asm/pgtable.h>
+ #include <asm/processor.h>
+@@ -740,25 +745,6 @@ ia64_sync_fph (struct task_struct *task)
+ psr->dfh = 1;
+ }
+
+-static int
+-access_fr (struct unw_frame_info *info, int regnum, int hi,
+- unsigned long *data, int write_access)
+-{
+- struct ia64_fpreg fpval;
+- int ret;
+-
+- ret = unw_get_fr(info, regnum, &fpval);
+- if (ret < 0)
+- return ret;
+-
+- if (write_access) {
+- fpval.u.bits[hi] = *data;
+- ret = unw_set_fr(info, regnum, fpval);
+- } else
+- *data = fpval.u.bits[hi];
+- return ret;
+-}
+-
+ /*
+ * Change the machine-state of CHILD such that it will return via the normal
+ * kernel exit-path, rather than the syscall-exit path.
+@@ -860,309 +846,7 @@ access_nat_bits (struct task_struct *child, struct pt_regs *pt,
+
+ static int
+ access_uarea (struct task_struct *child, unsigned long addr,
+- unsigned long *data, int write_access)
+-{
+- unsigned long *ptr, regnum, urbs_end, cfm;
+- struct switch_stack *sw;
+- struct pt_regs *pt;
+-# define pt_reg_addr(pt, reg) ((void *) \
+- ((unsigned long) (pt) \
+- + offsetof(struct pt_regs, reg)))
+-
+-
+- pt = task_pt_regs(child);
+- sw = (struct switch_stack *) (child->thread.ksp + 16);
+-
+- if ((addr & 0x7) != 0) {
+- dprintk("ptrace: unaligned register address 0x%lx\n", addr);
+- return -1;
+- }
+-
+- if (addr < PT_F127 + 16) {
+- /* accessing fph */
+- if (write_access)
+- ia64_sync_fph(child);
+- else
+- ia64_flush_fph(child);
+- ptr = (unsigned long *)
+- ((unsigned long) &child->thread.fph + addr);
+- } else if ((addr >= PT_F10) && (addr < PT_F11 + 16)) {
+- /* scratch registers untouched by kernel (saved in pt_regs) */
+- ptr = pt_reg_addr(pt, f10) + (addr - PT_F10);
+- } else if (addr >= PT_F12 && addr < PT_F15 + 16) {
+- /*
+- * Scratch registers untouched by kernel (saved in
+- * switch_stack).
+- */
+- ptr = (unsigned long *) ((long) sw
+- + (addr - PT_NAT_BITS - 32));
+- } else if (addr < PT_AR_LC + 8) {
+- /* preserved state: */
+- struct unw_frame_info info;
+- char nat = 0;
+- int ret;
+-
+- unw_init_from_blocked_task(&info, child);
+- if (unw_unwind_to_user(&info) < 0)
+- return -1;
+-
+- switch (addr) {
+- case PT_NAT_BITS:
+- return access_nat_bits(child, pt, &info,
+- data, write_access);
+-
+- case PT_R4: case PT_R5: case PT_R6: case PT_R7:
+- if (write_access) {
+- /* read NaT bit first: */
+- unsigned long dummy;
+-
+- ret = unw_get_gr(&info, (addr - PT_R4)/8 + 4,
+- &dummy, &nat);
+- if (ret < 0)
+- return ret;
+- }
+- return unw_access_gr(&info, (addr - PT_R4)/8 + 4, data,
+- &nat, write_access);
+-
+- case PT_B1: case PT_B2: case PT_B3:
+- case PT_B4: case PT_B5:
+- return unw_access_br(&info, (addr - PT_B1)/8 + 1, data,
+- write_access);
+-
+- case PT_AR_EC:
+- return unw_access_ar(&info, UNW_AR_EC, data,
+- write_access);
+-
+- case PT_AR_LC:
+- return unw_access_ar(&info, UNW_AR_LC, data,
+- write_access);
+-
+- default:
+- if (addr >= PT_F2 && addr < PT_F5 + 16)
+- return access_fr(&info, (addr - PT_F2)/16 + 2,
+- (addr & 8) != 0, data,
+- write_access);
+- else if (addr >= PT_F16 && addr < PT_F31 + 16)
+- return access_fr(&info,
+- (addr - PT_F16)/16 + 16,
+- (addr & 8) != 0,
+- data, write_access);
+- else {
+- dprintk("ptrace: rejecting access to register "
+- "address 0x%lx\n", addr);
+- return -1;
+- }
+- }
+- } else if (addr < PT_F9+16) {
+- /* scratch state */
+- switch (addr) {
+- case PT_AR_BSP:
+- /*
+- * By convention, we use PT_AR_BSP to refer to
+- * the end of the user-level backing store.
+- * Use ia64_rse_skip_regs(PT_AR_BSP, -CFM.sof)
+- * to get the real value of ar.bsp at the time
+- * the kernel was entered.
+- *
+- * Furthermore, when changing the contents of
+- * PT_AR_BSP (or PT_CFM) while the task is
+- * blocked in a system call, convert the state
+- * so that the non-system-call exit
+- * path is used. This ensures that the proper
+- * state will be picked up when resuming
+- * execution. However, it *also* means that
+- * once we write PT_AR_BSP/PT_CFM, it won't be
+- * possible to modify the syscall arguments of
+- * the pending system call any longer. This
+- * shouldn't be an issue because modifying
+- * PT_AR_BSP/PT_CFM generally implies that
+- * we're either abandoning the pending system
+- * call or that we defer it's re-execution
+- * (e.g., due to GDB doing an inferior
+- * function call).
+- */
+- urbs_end = ia64_get_user_rbs_end(child, pt, &cfm);
+- if (write_access) {
+- if (*data != urbs_end) {
+- if (in_syscall(pt))
+- convert_to_non_syscall(child,
+- pt,
+- cfm);
+- /*
+- * Simulate user-level write
+- * of ar.bsp:
+- */
+- pt->loadrs = 0;
+- pt->ar_bspstore = *data;
+- }
+- } else
+- *data = urbs_end;
+- return 0;
+-
+- case PT_CFM:
+- urbs_end = ia64_get_user_rbs_end(child, pt, &cfm);
+- if (write_access) {
+- if (((cfm ^ *data) & PFM_MASK) != 0) {
+- if (in_syscall(pt))
+- convert_to_non_syscall(child,
+- pt,
+- cfm);
+- pt->cr_ifs = ((pt->cr_ifs & ~PFM_MASK)
+- | (*data & PFM_MASK));
+- }
+- } else
+- *data = cfm;
+- return 0;
+-
+- case PT_CR_IPSR:
+- if (write_access) {
+- unsigned long tmp = *data;
+- /* psr.ri==3 is a reserved value: SDM 2:25 */
+- if ((tmp & IA64_PSR_RI) == IA64_PSR_RI)
+- tmp &= ~IA64_PSR_RI;
+- pt->cr_ipsr = ((tmp & IPSR_MASK)
+- | (pt->cr_ipsr & ~IPSR_MASK));
+- } else
+- *data = (pt->cr_ipsr & IPSR_MASK);
+- return 0;
+-
+- case PT_AR_RSC:
+- if (write_access)
+- pt->ar_rsc = *data | (3 << 2); /* force PL3 */
+- else
+- *data = pt->ar_rsc;
+- return 0;
+-
+- case PT_AR_RNAT:
+- ptr = pt_reg_addr(pt, ar_rnat);
+- break;
+- case PT_R1:
+- ptr = pt_reg_addr(pt, r1);
+- break;
+- case PT_R2: case PT_R3:
+- ptr = pt_reg_addr(pt, r2) + (addr - PT_R2);
+- break;
+- case PT_R8: case PT_R9: case PT_R10: case PT_R11:
+- ptr = pt_reg_addr(pt, r8) + (addr - PT_R8);
+- break;
+- case PT_R12: case PT_R13:
+- ptr = pt_reg_addr(pt, r12) + (addr - PT_R12);
+- break;
+- case PT_R14:
+- ptr = pt_reg_addr(pt, r14);
+- break;
+- case PT_R15:
+- ptr = pt_reg_addr(pt, r15);
+- break;
+- case PT_R16: case PT_R17: case PT_R18: case PT_R19:
+- case PT_R20: case PT_R21: case PT_R22: case PT_R23:
+- case PT_R24: case PT_R25: case PT_R26: case PT_R27:
+- case PT_R28: case PT_R29: case PT_R30: case PT_R31:
+- ptr = pt_reg_addr(pt, r16) + (addr - PT_R16);
+- break;
+- case PT_B0:
+- ptr = pt_reg_addr(pt, b0);
+- break;
+- case PT_B6:
+- ptr = pt_reg_addr(pt, b6);
+- break;
+- case PT_B7:
+- ptr = pt_reg_addr(pt, b7);
+- break;
+- case PT_F6: case PT_F6+8: case PT_F7: case PT_F7+8:
+- case PT_F8: case PT_F8+8: case PT_F9: case PT_F9+8:
+- ptr = pt_reg_addr(pt, f6) + (addr - PT_F6);
+- break;
+- case PT_AR_BSPSTORE:
+- ptr = pt_reg_addr(pt, ar_bspstore);
+- break;
+- case PT_AR_UNAT:
+- ptr = pt_reg_addr(pt, ar_unat);
+- break;
+- case PT_AR_PFS:
+- ptr = pt_reg_addr(pt, ar_pfs);
+- break;
+- case PT_AR_CCV:
+- ptr = pt_reg_addr(pt, ar_ccv);
+- break;
+- case PT_AR_FPSR:
+- ptr = pt_reg_addr(pt, ar_fpsr);
+- break;
+- case PT_CR_IIP:
+- ptr = pt_reg_addr(pt, cr_iip);
+- break;
+- case PT_PR:
+- ptr = pt_reg_addr(pt, pr);
+- break;
+- /* scratch register */
+-
+- default:
+- /* disallow accessing anything else... */
+- dprintk("ptrace: rejecting access to register "
+- "address 0x%lx\n", addr);
+- return -1;
+- }
+- } else if (addr <= PT_AR_SSD) {
+- ptr = pt_reg_addr(pt, ar_csd) + (addr - PT_AR_CSD);
+- } else {
+- /* access debug registers */
+-
+- if (addr >= PT_IBR) {
+- regnum = (addr - PT_IBR) >> 3;
+- ptr = &child->thread.ibr[0];
+- } else {
+- regnum = (addr - PT_DBR) >> 3;
+- ptr = &child->thread.dbr[0];
+- }
+-
+- if (regnum >= 8) {
+- dprintk("ptrace: rejecting access to register "
+- "address 0x%lx\n", addr);
+- return -1;
+- }
+-#ifdef CONFIG_PERFMON
+- /*
+- * Check if debug registers are used by perfmon. This
+- * test must be done once we know that we can do the
+- * operation, i.e. the arguments are all valid, but
+- * before we start modifying the state.
+- *
+- * Perfmon needs to keep a count of how many processes
+- * are trying to modify the debug registers for system
+- * wide monitoring sessions.
+- *
+- * We also include read access here, because they may
+- * cause the PMU-installed debug register state
+- * (dbr[], ibr[]) to be reset. The two arrays are also
+- * used by perfmon, but we do not use
+- * IA64_THREAD_DBG_VALID. The registers are restored
+- * by the PMU context switch code.
+- */
+- if (pfm_use_debug_registers(child)) return -1;
+-#endif
+-
+- if (!(child->thread.flags & IA64_THREAD_DBG_VALID)) {
+- child->thread.flags |= IA64_THREAD_DBG_VALID;
+- memset(child->thread.dbr, 0,
+- sizeof(child->thread.dbr));
+- memset(child->thread.ibr, 0,
+- sizeof(child->thread.ibr));
+- }
+-
+- ptr += regnum;
+-
+- if ((regnum & 1) && write_access) {
+- /* don't let the user set kernel-level breakpoints: */
+- *ptr = *data & ~(7UL << 56);
+- return 0;
+- }
+- }
+- if (write_access)
+- *ptr = *data;
+- else
+- *data = *ptr;
+- return 0;
+-}
++ unsigned long *data, int write_access);
+
+ static long
+ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
+@@ -1626,3 +1310,892 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3,
+ if (test_thread_flag(TIF_RESTORE_RSE))
+ ia64_sync_krbs();
+ }
++
++/* Utrace implementation starts here */
++struct regset_get {
++ void *kbuf;
++ void __user *ubuf;
++};
++
++struct regset_set {
++ const void *kbuf;
++ const void __user *ubuf;
++};
++
++struct regset_getset {
++ struct task_struct *target;
++ const struct user_regset *regset;
++ union {
++ struct regset_get get;
++ struct regset_set set;
++ } u;
++ unsigned int pos;
++ unsigned int count;
++ int ret;
++};
++
++static int
++access_elf_gpreg(struct task_struct *target, struct unw_frame_info *info,
++ unsigned long addr, unsigned long *data, int write_access)
++{
++ struct pt_regs *pt;
++ unsigned long *ptr = NULL;
++ int ret;
++ char nat = 0;
++
++ pt = task_pt_regs(target);
++ switch (addr) {
++ case ELF_GR_OFFSET(1):
++ ptr = &pt->r1;
++ break;
++ case ELF_GR_OFFSET(2):
++ case ELF_GR_OFFSET(3):
++ ptr = (void *)&pt->r2 + (addr - ELF_GR_OFFSET(2));
++ break;
++ case ELF_GR_OFFSET(4) ... ELF_GR_OFFSET(7):
++ if (write_access) {
++ /* read NaT bit first: */
++ unsigned long dummy;
++
++ ret = unw_get_gr(info, addr/8, &dummy, &nat);
++ if (ret < 0)
++ return ret;
++ }
++ return unw_access_gr(info, addr/8, data, &nat, write_access);
++ case ELF_GR_OFFSET(8) ... ELF_GR_OFFSET(11):
++ ptr = (void *)&pt->r8 + addr - ELF_GR_OFFSET(8);
++ break;
++ case ELF_GR_OFFSET(12):
++ case ELF_GR_OFFSET(13):
++ ptr = (void *)&pt->r12 + addr - ELF_GR_OFFSET(12);
++ break;
++ case ELF_GR_OFFSET(14):
++ ptr = &pt->r14;
++ break;
++ case ELF_GR_OFFSET(15):
++ ptr = &pt->r15;
++ }
++ if (write_access)
++ *ptr = *data;
++ else
++ *data = *ptr;
++ return 0;
++}
++
++static int
++access_elf_breg(struct task_struct *target, struct unw_frame_info *info,
++ unsigned long addr, unsigned long *data, int write_access)
++{
++ struct pt_regs *pt;
++ unsigned long *ptr = NULL;
++
++ pt = task_pt_regs(target);
++ switch (addr) {
++ case ELF_BR_OFFSET(0):
++ ptr = &pt->b0;
++ break;
++ case ELF_BR_OFFSET(1) ... ELF_BR_OFFSET(5):
++ return unw_access_br(info, (addr - ELF_BR_OFFSET(0))/8,
++ data, write_access);
++ case ELF_BR_OFFSET(6):
++ ptr = &pt->b6;
++ break;
++ case ELF_BR_OFFSET(7):
++ ptr = &pt->b7;
++ }
++ if (write_access)
++ *ptr = *data;
++ else
++ *data = *ptr;
++ return 0;
++}
++
++static int
++access_elf_areg(struct task_struct *target, struct unw_frame_info *info,
++ unsigned long addr, unsigned long *data, int write_access)
++{
++ struct pt_regs *pt;
++ unsigned long cfm, urbs_end;
++ unsigned long *ptr = NULL;
++
++ pt = task_pt_regs(target);
++ if (addr >= ELF_AR_RSC_OFFSET && addr <= ELF_AR_SSD_OFFSET) {
++ switch (addr) {
++ case ELF_AR_RSC_OFFSET:
++ /* force PL3 */
++ if (write_access)
++ pt->ar_rsc = *data | (3 << 2);
++ else
++ *data = pt->ar_rsc;
++ return 0;
++ case ELF_AR_BSP_OFFSET:
++ /*
++ * By convention, we use PT_AR_BSP to refer to
++ * the end of the user-level backing store.
++ * Use ia64_rse_skip_regs(PT_AR_BSP, -CFM.sof)
++ * to get the real value of ar.bsp at the time
++ * the kernel was entered.
++ *
++ * Furthermore, when changing the contents of
++ * PT_AR_BSP (or PT_CFM) while the task is
++ * blocked in a system call, convert the state
++ * so that the non-system-call exit
++ * path is used. This ensures that the proper
++ * state will be picked up when resuming
++ * execution. However, it *also* means that
++ * once we write PT_AR_BSP/PT_CFM, it won't be
++ * possible to modify the syscall arguments of
++ * the pending system call any longer. This
++ * shouldn't be an issue because modifying
++ * PT_AR_BSP/PT_CFM generally implies that
++ * we're either abandoning the pending system
++ * call or that we defer it's re-execution
++ * (e.g., due to GDB doing an inferior
++ * function call).
++ */
++ urbs_end = ia64_get_user_rbs_end(target, pt, &cfm);
++ if (write_access) {
++ if (*data != urbs_end) {
++ if (in_syscall(pt))
++ convert_to_non_syscall(target,
++ pt,
++ cfm);
++ /*
++ * Simulate user-level write
++ * of ar.bsp:
++ */
++ pt->loadrs = 0;
++ pt->ar_bspstore = *data;
++ }
++ } else
++ *data = urbs_end;
++ return 0;
++ case ELF_AR_BSPSTORE_OFFSET:
++ ptr = &pt->ar_bspstore;
++ break;
++ case ELF_AR_RNAT_OFFSET:
++ ptr = &pt->ar_rnat;
++ break;
++ case ELF_AR_CCV_OFFSET:
++ ptr = &pt->ar_ccv;
++ break;
++ case ELF_AR_UNAT_OFFSET:
++ ptr = &pt->ar_unat;
++ break;
++ case ELF_AR_FPSR_OFFSET:
++ ptr = &pt->ar_fpsr;
++ break;
++ case ELF_AR_PFS_OFFSET:
++ ptr = &pt->ar_pfs;
++ break;
++ case ELF_AR_LC_OFFSET:
++ return unw_access_ar(info, UNW_AR_LC, data,
++ write_access);
++ case ELF_AR_EC_OFFSET:
++ return unw_access_ar(info, UNW_AR_EC, data,
++ write_access);
++ case ELF_AR_CSD_OFFSET:
++ ptr = &pt->ar_csd;
++ break;
++ case ELF_AR_SSD_OFFSET:
++ ptr = &pt->ar_ssd;
++ }
++ } else if (addr >= ELF_CR_IIP_OFFSET && addr <= ELF_CR_IPSR_OFFSET) {
++ switch (addr) {
++ case ELF_CR_IIP_OFFSET:
++ ptr = &pt->cr_iip;
++ break;
++ case ELF_CFM_OFFSET:
++ urbs_end = ia64_get_user_rbs_end(target, pt, &cfm);
++ if (write_access) {
++ if (((cfm ^ *data) & PFM_MASK) != 0) {
++ if (in_syscall(pt))
++ convert_to_non_syscall(target,
++ pt,
++ cfm);
++ pt->cr_ifs = ((pt->cr_ifs & ~PFM_MASK)
++ | (*data & PFM_MASK));
++ }
++ } else
++ *data = cfm;
++ return 0;
++ case ELF_CR_IPSR_OFFSET:
++ if (write_access) {
++ unsigned long tmp = *data;
++ /* psr.ri==3 is a reserved value: SDM 2:25 */
++ if ((tmp & IA64_PSR_RI) == IA64_PSR_RI)
++ tmp &= ~IA64_PSR_RI;
++ pt->cr_ipsr = ((tmp & IPSR_MASK)
++ | (pt->cr_ipsr & ~IPSR_MASK));
++ } else
++ *data = (pt->cr_ipsr & IPSR_MASK);
++ return 0;
++ }
++ } else if (addr == ELF_NAT_OFFSET)
++ return access_nat_bits(target, pt, info,
++ data, write_access);
++ else if (addr == ELF_PR_OFFSET)
++ ptr = &pt->pr;
++ else
++ return -1;
++
++ if (write_access)
++ *ptr = *data;
++ else
++ *data = *ptr;
++
++ return 0;
++}
++
++static int
++access_elf_reg(struct task_struct *target, struct unw_frame_info *info,
++ unsigned long addr, unsigned long *data, int write_access)
++{
++ if (addr >= ELF_GR_OFFSET(1) && addr <= ELF_GR_OFFSET(15))
++ return access_elf_gpreg(target, info, addr, data, write_access);
++ else if (addr >= ELF_BR_OFFSET(0) && addr <= ELF_BR_OFFSET(7))
++ return access_elf_breg(target, info, addr, data, write_access);
++ else
++ return access_elf_areg(target, info, addr, data, write_access);
++}
++
++void do_gpregs_get(struct unw_frame_info *info, void *arg)
++{
++ struct pt_regs *pt;
++ struct regset_getset *dst = arg;
++ elf_greg_t tmp[16];
++ unsigned int i, index, min_copy;
++
++ if (unw_unwind_to_user(info) < 0)
++ return;
++
++ /*
++ * coredump format:
++ * r0-r31
++ * NaT bits (for r0-r31; bit N == 1 iff rN is a NaT)
++ * predicate registers (p0-p63)
++ * b0-b7
++ * ip cfm user-mask
++ * ar.rsc ar.bsp ar.bspstore ar.rnat
++ * ar.ccv ar.unat ar.fpsr ar.pfs ar.lc ar.ec
++ */
++
++
++ /* Skip r0 */
++ if (dst->count > 0 && dst->pos < ELF_GR_OFFSET(1)) {
++ dst->ret = user_regset_copyout_zero(&dst->pos, &dst->count,
++ &dst->u.get.kbuf,
++ &dst->u.get.ubuf,
++ 0, ELF_GR_OFFSET(1));
++ if (dst->ret || dst->count == 0)
++ return;
++ }
++
++ /* gr1 - gr15 */
++ if (dst->count > 0 && dst->pos < ELF_GR_OFFSET(16)) {
++ index = (dst->pos - ELF_GR_OFFSET(1)) / sizeof(elf_greg_t);
++ min_copy = ELF_GR_OFFSET(16) > (dst->pos + dst->count) ?
++ (dst->pos + dst->count) : ELF_GR_OFFSET(16);
++ for (i = dst->pos; i < min_copy; i += sizeof(elf_greg_t),
++ index++)
++ if (access_elf_reg(dst->target, info, i,
++ &tmp[index], 0) < 0) {
++ dst->ret = -EIO;
++ return;
++ }
++ dst->ret = user_regset_copyout(&dst->pos, &dst->count,
++ &dst->u.get.kbuf, &dst->u.get.ubuf, tmp,
++ ELF_GR_OFFSET(1), ELF_GR_OFFSET(16));
++ if (dst->ret || dst->count == 0)
++ return;
++ }
++
++ /* r16-r31 */
++ if (dst->count > 0 && dst->pos < ELF_NAT_OFFSET) {
++ pt = task_pt_regs(dst->target);
++ dst->ret = user_regset_copyout(&dst->pos, &dst->count,
++ &dst->u.get.kbuf, &dst->u.get.ubuf, &pt->r16,
++ ELF_GR_OFFSET(16), ELF_NAT_OFFSET);
++ if (dst->ret || dst->count == 0)
++ return;
++ }
++
++ /* nat, pr, b0 - b7 */
++ if (dst->count > 0 && dst->pos < ELF_CR_IIP_OFFSET) {
++ index = (dst->pos - ELF_NAT_OFFSET) / sizeof(elf_greg_t);
++ min_copy = ELF_CR_IIP_OFFSET > (dst->pos + dst->count) ?
++ (dst->pos + dst->count) : ELF_CR_IIP_OFFSET;
++ for (i = dst->pos; i < min_copy; i += sizeof(elf_greg_t),
++ index++)
++ if (access_elf_reg(dst->target, info, i,
++ &tmp[index], 0) < 0) {
++ dst->ret = -EIO;
++ return;
++ }
++ dst->ret = user_regset_copyout(&dst->pos, &dst->count,
++ &dst->u.get.kbuf, &dst->u.get.ubuf, tmp,
++ ELF_NAT_OFFSET, ELF_CR_IIP_OFFSET);
++ if (dst->ret || dst->count == 0)
++ return;
++ }
++
++ /* ip cfm psr ar.rsc ar.bsp ar.bspstore ar.rnat
++ * ar.ccv ar.unat ar.fpsr ar.pfs ar.lc ar.ec ar.csd ar.ssd
++ */
++ if (dst->count > 0 && dst->pos < (ELF_AR_END_OFFSET)) {
++ index = (dst->pos - ELF_CR_IIP_OFFSET) / sizeof(elf_greg_t);
++ min_copy = ELF_AR_END_OFFSET > (dst->pos + dst->count) ?
++ (dst->pos + dst->count) : ELF_AR_END_OFFSET;
++ for (i = dst->pos; i < min_copy; i += sizeof(elf_greg_t),
++ index++)
++ if (access_elf_reg(dst->target, info, i,
++ &tmp[index], 0) < 0) {
++ dst->ret = -EIO;
++ return;
++ }
++ dst->ret = user_regset_copyout(&dst->pos, &dst->count,
++ &dst->u.get.kbuf, &dst->u.get.ubuf, tmp,
++ ELF_CR_IIP_OFFSET, ELF_AR_END_OFFSET);
++ }
++}
++
++void do_gpregs_set(struct unw_frame_info *info, void *arg)
++{
++ struct pt_regs *pt;
++ struct regset_getset *dst = arg;
++ elf_greg_t tmp[16];
++ unsigned int i, index;
++
++ if (unw_unwind_to_user(info) < 0)
++ return;
++
++ /* Skip r0 */
++ if (dst->count > 0 && dst->pos < ELF_GR_OFFSET(1)) {
++ dst->ret = user_regset_copyin_ignore(&dst->pos, &dst->count,
++ &dst->u.set.kbuf,
++ &dst->u.set.ubuf,
++ 0, ELF_GR_OFFSET(1));
++ if (dst->ret || dst->count == 0)
++ return;
++ }
++
++ /* gr1-gr15 */
++ if (dst->count > 0 && dst->pos < ELF_GR_OFFSET(16)) {
++ i = dst->pos;
++ index = (dst->pos - ELF_GR_OFFSET(1)) / sizeof(elf_greg_t);
++ dst->ret = user_regset_copyin(&dst->pos, &dst->count,
++ &dst->u.set.kbuf, &dst->u.set.ubuf, tmp,
++ ELF_GR_OFFSET(1), ELF_GR_OFFSET(16));
++ if (dst->ret)
++ return;
++ for ( ; i < dst->pos; i += sizeof(elf_greg_t), index++)
++ if (access_elf_reg(dst->target, info, i,
++ &tmp[index], 1) < 0) {
++ dst->ret = -EIO;
++ return;
++ }
++ if (dst->count == 0)
++ return;
++ }
++
++ /* gr16-gr31 */
++ if (dst->count > 0 && dst->pos < ELF_NAT_OFFSET) {
++ pt = task_pt_regs(dst->target);
++ dst->ret = user_regset_copyin(&dst->pos, &dst->count,
++ &dst->u.set.kbuf, &dst->u.set.ubuf, &pt->r16,
++ ELF_GR_OFFSET(16), ELF_NAT_OFFSET);
++ if (dst->ret || dst->count == 0)
++ return;
++ }
++
++ /* nat, pr, b0 - b7 */
++ if (dst->count > 0 && dst->pos < ELF_CR_IIP_OFFSET) {
++ i = dst->pos;
++ index = (dst->pos - ELF_NAT_OFFSET) / sizeof(elf_greg_t);
++ dst->ret = user_regset_copyin(&dst->pos, &dst->count,
++ &dst->u.set.kbuf, &dst->u.set.ubuf, tmp,
++ ELF_NAT_OFFSET, ELF_CR_IIP_OFFSET);
++ if (dst->ret)
++ return;
++ for (; i < dst->pos; i += sizeof(elf_greg_t), index++)
++ if (access_elf_reg(dst->target, info, i,
++ &tmp[index], 1) < 0) {
++ dst->ret = -EIO;
++ return;
++ }
++ if (dst->count == 0)
++ return;
++ }
++
++ /* ip cfm psr ar.rsc ar.bsp ar.bspstore ar.rnat
++ * ar.ccv ar.unat ar.fpsr ar.pfs ar.lc ar.ec ar.csd ar.ssd
++ */
++ if (dst->count > 0 && dst->pos < (ELF_AR_END_OFFSET)) {
++ i = dst->pos;
++ index = (dst->pos - ELF_CR_IIP_OFFSET) / sizeof(elf_greg_t);
++ dst->ret = user_regset_copyin(&dst->pos, &dst->count,
++ &dst->u.set.kbuf, &dst->u.set.ubuf, tmp,
++ ELF_CR_IIP_OFFSET, ELF_AR_END_OFFSET);
++ if (dst->ret)
++ return;
++ for ( ; i < dst->pos; i += sizeof(elf_greg_t), index++)
++ if (access_elf_reg(dst->target, info, i,
++ &tmp[index], 1) < 0) {
++ dst->ret = -EIO;
++ return;
++ }
++ }
++}
++
++#define ELF_FP_OFFSET(i) (i * sizeof(elf_fpreg_t))
++
++void do_fpregs_get(struct unw_frame_info *info, void *arg)
++{
++ struct regset_getset *dst = arg;
++ struct task_struct *task = dst->target;
++ elf_fpreg_t tmp[30];
++ int index, min_copy, i;
++
++ if (unw_unwind_to_user(info) < 0)
++ return;
++
++ /* Skip pos 0 and 1 */
++ if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(2)) {
++ dst->ret = user_regset_copyout_zero(&dst->pos, &dst->count,
++ &dst->u.get.kbuf,
++ &dst->u.get.ubuf,
++ 0, ELF_FP_OFFSET(2));
++ if (dst->count == 0 || dst->ret)
++ return;
++ }
++
++ /* fr2-fr31 */
++ if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(32)) {
++ index = (dst->pos - ELF_FP_OFFSET(2)) / sizeof(elf_fpreg_t);
++
++ min_copy = min(((unsigned int)ELF_FP_OFFSET(32)),
++ dst->pos + dst->count);
++ for (i = dst->pos; i < min_copy; i += sizeof(elf_fpreg_t),
++ index++)
++ if (unw_get_fr(info, i / sizeof(elf_fpreg_t),
++ &tmp[index])) {
++ dst->ret = -EIO;
++ return;
++ }
++ dst->ret = user_regset_copyout(&dst->pos, &dst->count,
++ &dst->u.get.kbuf, &dst->u.get.ubuf, tmp,
++ ELF_FP_OFFSET(2), ELF_FP_OFFSET(32));
++ if (dst->count == 0 || dst->ret)
++ return;
++ }
++
++ /* fph */
++ if (dst->count > 0) {
++ ia64_flush_fph(dst->target);
++ if (task->thread.flags & IA64_THREAD_FPH_VALID)
++ dst->ret = user_regset_copyout(
++ &dst->pos, &dst->count,
++ &dst->u.get.kbuf, &dst->u.get.ubuf,
++ &dst->target->thread.fph,
++ ELF_FP_OFFSET(32), -1);
++ else
++ /* Zero fill instead. */
++ dst->ret = user_regset_copyout_zero(
++ &dst->pos, &dst->count,
++ &dst->u.get.kbuf, &dst->u.get.ubuf,
++ ELF_FP_OFFSET(32), -1);
++ }
++}
++
++void do_fpregs_set(struct unw_frame_info *info, void *arg)
++{
++ struct regset_getset *dst = arg;
++ elf_fpreg_t fpreg, tmp[30];
++ int index, start, end;
++
++ if (unw_unwind_to_user(info) < 0)
++ return;
++
++ /* Skip pos 0 and 1 */
++ if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(2)) {
++ dst->ret = user_regset_copyin_ignore(&dst->pos, &dst->count,
++ &dst->u.set.kbuf,
++ &dst->u.set.ubuf,
++ 0, ELF_FP_OFFSET(2));
++ if (dst->count == 0 || dst->ret)
++ return;
++ }
++
++ /* fr2-fr31 */
++ if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(32)) {
++ start = dst->pos;
++ end = min(((unsigned int)ELF_FP_OFFSET(32)),
++ dst->pos + dst->count);
++ dst->ret = user_regset_copyin(&dst->pos, &dst->count,
++ &dst->u.set.kbuf, &dst->u.set.ubuf, tmp,
++ ELF_FP_OFFSET(2), ELF_FP_OFFSET(32));
++ if (dst->ret)
++ return;
++
++ if (start & 0xF) { /* only write high part */
++ if (unw_get_fr(info, start / sizeof(elf_fpreg_t),
++ &fpreg)) {
++ dst->ret = -EIO;
++ return;
++ }
++ tmp[start / sizeof(elf_fpreg_t) - 2].u.bits[0]
++ = fpreg.u.bits[0];
++ start &= ~0xFUL;
++ }
++ if (end & 0xF) { /* only write low part */
++ if (unw_get_fr(info, end / sizeof(elf_fpreg_t),
++ &fpreg)) {
++ dst->ret = -EIO;
++ return;
++ }
++ tmp[end / sizeof(elf_fpreg_t) - 2].u.bits[1]
++ = fpreg.u.bits[1];
++ end = (end + 0xF) & ~0xFUL;
++ }
++
++ for ( ; start < end ; start += sizeof(elf_fpreg_t)) {
++ index = start / sizeof(elf_fpreg_t);
++ if (unw_set_fr(info, index, tmp[index - 2])) {
++ dst->ret = -EIO;
++ return;
++ }
++ }
++ if (dst->ret || dst->count == 0)
++ return;
++ }
++
++ /* fph */
++ if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(128)) {
++ ia64_sync_fph(dst->target);
++ dst->ret = user_regset_copyin(&dst->pos, &dst->count,
++ &dst->u.set.kbuf,
++ &dst->u.set.ubuf,
++ &dst->target->thread.fph,
++ ELF_FP_OFFSET(32), -1);
++ }
++}
++
++static int
++do_regset_call(void (*call)(struct unw_frame_info *, void *),
++ struct task_struct *target,
++ const struct user_regset *regset,
++ unsigned int pos, unsigned int count,
++ const void *kbuf, const void __user *ubuf)
++{
++ struct regset_getset info = { .target = target, .regset = regset,
++ .pos = pos, .count = count,
++ .u.set = { .kbuf = kbuf, .ubuf = ubuf },
++ .ret = 0 };
++
++ if (target == current)
++ unw_init_running(call, &info);
++ else {
++ struct unw_frame_info ufi;
++ memset(&ufi, 0, sizeof(ufi));
++ unw_init_from_blocked_task(&ufi, target);
++ (*call)(&ufi, &info);
++ }
++
++ return info.ret;
++}
++
++static int
++gpregs_get(struct task_struct *target,
++ const struct user_regset *regset,
++ unsigned int pos, unsigned int count,
++ void *kbuf, void __user *ubuf)
++{
++ return do_regset_call(do_gpregs_get, target, regset, pos, count,
++ kbuf, ubuf);
++}
++
++static int gpregs_set(struct task_struct *target,
++ const struct user_regset *regset,
++ unsigned int pos, unsigned int count,
++ const void *kbuf, const void __user *ubuf)
++{
++ return do_regset_call(do_gpregs_set, target, regset, pos, count,
++ kbuf, ubuf);
++}
++
++static void do_gpregs_writeback(struct unw_frame_info *info, void *arg)
++{
++ do_sync_rbs(info, ia64_sync_user_rbs);
++}
++
++/*
++ * This is called to write back the register backing store.
++ * ptrace does this before it stops, so that a tracer reading the user
++ * memory after the thread stops will get the current register data.
++ */
++static int
++gpregs_writeback(struct task_struct *target,
++ const struct user_regset *regset,
++ int now)
++{
++ if (test_and_set_tsk_thread_flag(target, TIF_RESTORE_RSE))
++ return 0;
++ tsk_set_notify_resume(target);
++ return do_regset_call(do_gpregs_writeback, target, regset, 0, 0,
++ NULL, NULL);
++}
++
++static int
++fpregs_active(struct task_struct *target, const struct user_regset *regset)
++{
++ return (target->thread.flags & IA64_THREAD_FPH_VALID) ? 128 : 32;
++}
++
++static int fpregs_get(struct task_struct *target,
++ const struct user_regset *regset,
++ unsigned int pos, unsigned int count,
++ void *kbuf, void __user *ubuf)
++{
++ return do_regset_call(do_fpregs_get, target, regset, pos, count,
++ kbuf, ubuf);
++}
++
++static int fpregs_set(struct task_struct *target,
++ const struct user_regset *regset,
++ unsigned int pos, unsigned int count,
++ const void *kbuf, const void __user *ubuf)
++{
++ return do_regset_call(do_fpregs_set, target, regset, pos, count,
++ kbuf, ubuf);
++}
++
++static int
++access_uarea(struct task_struct *child, unsigned long addr,
++ unsigned long *data, int write_access)
++{
++ unsigned int pos = -1; /* an invalid value */
++ int ret;
++ unsigned long *ptr, regnum;
++
++ if ((addr & 0x7) != 0) {
++ dprintk("ptrace: unaligned register address 0x%lx\n", addr);
++ return -1;
++ }
++ if ((addr >= PT_NAT_BITS + 8 && addr < PT_F2) ||
++ (addr >= PT_R7 + 8 && addr < PT_B1) ||
++ (addr >= PT_AR_LC + 8 && addr < PT_CR_IPSR) ||
++ (addr >= PT_AR_SSD + 8 && addr < PT_DBR)) {
++ dprintk("ptrace: rejecting access to register "
++ "address 0x%lx\n", addr);
++ return -1;
++ }
++
++ switch (addr) {
++ case PT_F32 ... (PT_F127 + 15):
++ pos = addr - PT_F32 + ELF_FP_OFFSET(32);
++ break;
++ case PT_F2 ... (PT_F5 + 15):
++ pos = addr - PT_F2 + ELF_FP_OFFSET(2);
++ break;
++ case PT_F10 ... (PT_F31 + 15):
++ pos = addr - PT_F10 + ELF_FP_OFFSET(10);
++ break;
++ case PT_F6 ... (PT_F9 + 15):
++ pos = addr - PT_F6 + ELF_FP_OFFSET(6);
++ break;
++ }
++
++ if (pos != -1) {
++ if (write_access)
++ ret = fpregs_set(child, NULL, pos,
++ sizeof(unsigned long), data, NULL);
++ else
++ ret = fpregs_get(child, NULL, pos,
++ sizeof(unsigned long), data, NULL);
++ if (ret != 0)
++ return -1;
++ return 0;
++ }
++
++ switch (addr) {
++ case PT_NAT_BITS:
++ pos = ELF_NAT_OFFSET;
++ break;
++ case PT_R4 ... PT_R7:
++ pos = addr - PT_R4 + ELF_GR_OFFSET(4);
++ break;
++ case PT_B1 ... PT_B5:
++ pos = addr - PT_B1 + ELF_BR_OFFSET(1);
++ break;
++ case PT_AR_EC:
++ pos = ELF_AR_EC_OFFSET;
++ break;
++ case PT_AR_LC:
++ pos = ELF_AR_LC_OFFSET;
++ break;
++ case PT_CR_IPSR:
++ pos = ELF_CR_IPSR_OFFSET;
++ break;
++ case PT_CR_IIP:
++ pos = ELF_CR_IIP_OFFSET;
++ break;
++ case PT_CFM:
++ pos = ELF_CFM_OFFSET;
++ break;
++ case PT_AR_UNAT:
++ pos = ELF_AR_UNAT_OFFSET;
++ break;
++ case PT_AR_PFS:
++ pos = ELF_AR_PFS_OFFSET;
++ break;
++ case PT_AR_RSC:
++ pos = ELF_AR_RSC_OFFSET;
++ break;
++ case PT_AR_RNAT:
++ pos = ELF_AR_RNAT_OFFSET;
++ break;
++ case PT_AR_BSPSTORE:
++ pos = ELF_AR_BSPSTORE_OFFSET;
++ break;
++ case PT_PR:
++ pos = ELF_PR_OFFSET;
++ break;
++ case PT_B6:
++ pos = ELF_BR_OFFSET(6);
++ break;
++ case PT_AR_BSP:
++ pos = ELF_AR_BSP_OFFSET;
++ break;
++ case PT_R1 ... PT_R3:
++ pos = addr - PT_R1 + ELF_GR_OFFSET(1);
++ break;
++ case PT_R12 ... PT_R15:
++ pos = addr - PT_R12 + ELF_GR_OFFSET(12);
++ break;
++ case PT_R8 ... PT_R11:
++ pos = addr - PT_R8 + ELF_GR_OFFSET(8);
++ break;
++ case PT_R16 ... PT_R31:
++ pos = addr - PT_R16 + ELF_GR_OFFSET(16);
++ break;
++ case PT_AR_CCV:
++ pos = ELF_AR_CCV_OFFSET;
++ break;
++ case PT_AR_FPSR:
++ pos = ELF_AR_FPSR_OFFSET;
++ break;
++ case PT_B0:
++ pos = ELF_BR_OFFSET(0);
++ break;
++ case PT_B7:
++ pos = ELF_BR_OFFSET(7);
++ break;
++ case PT_AR_CSD:
++ pos = ELF_AR_CSD_OFFSET;
++ break;
++ case PT_AR_SSD:
++ pos = ELF_AR_SSD_OFFSET;
++ break;
++ }
++
++ if (pos != -1) {
++ if (write_access)
++ ret = gpregs_set(child, NULL, pos,
++ sizeof(unsigned long), data, NULL);
++ else
++ ret = gpregs_get(child, NULL, pos,
++ sizeof(unsigned long), data, NULL);
++ if (ret != 0)
++ return -1;
++ return 0;
++ }
++
++ /* access debug registers */
++ if (addr >= PT_IBR) {
++ regnum = (addr - PT_IBR) >> 3;
++ ptr = &child->thread.ibr[0];
++ } else {
++ regnum = (addr - PT_DBR) >> 3;
++ ptr = &child->thread.dbr[0];
++ }
++
++ if (regnum >= 8) {
++ dprintk("ptrace: rejecting access to register "
++ "address 0x%lx\n", addr);
++ return -1;
++ }
++#ifdef CONFIG_PERFMON
++ /*
++ * Check if debug registers are used by perfmon. This
++ * test must be done once we know that we can do the
++ * operation, i.e. the arguments are all valid, but
++ * before we start modifying the state.
++ *
++ * Perfmon needs to keep a count of how many processes
++ * are trying to modify the debug registers for system
++ * wide monitoring sessions.
++ *
++ * We also include read access here, because they may
++ * cause the PMU-installed debug register state
++ * (dbr[], ibr[]) to be reset. The two arrays are also
++ * used by perfmon, but we do not use
++ * IA64_THREAD_DBG_VALID. The registers are restored
++ * by the PMU context switch code.
++ */
++ if (pfm_use_debug_registers(child))
++ return -1;
++#endif
++
++ if (!(child->thread.flags & IA64_THREAD_DBG_VALID)) {
++ child->thread.flags |= IA64_THREAD_DBG_VALID;
++ memset(child->thread.dbr, 0,
++ sizeof(child->thread.dbr));
++ memset(child->thread.ibr, 0,
++ sizeof(child->thread.ibr));
++ }
++
++ ptr += regnum;
++
++ if ((regnum & 1) && write_access) {
++ /* don't let the user set kernel-level breakpoints: */
++ *ptr = *data & ~(7UL << 56);
++ return 0;
++ }
++ if (write_access)
++ *ptr = *data;
++ else
++ *data = *ptr;
++ return 0;
++}
++
++static const struct user_regset native_regsets[] = {
++ {
++ .core_note_type = NT_PRSTATUS,
++ .n = ELF_NGREG,
++ .size = sizeof(elf_greg_t), .align = sizeof(elf_greg_t),
++ .get = gpregs_get, .set = gpregs_set,
++ .writeback = gpregs_writeback
++ },
++ {
++ .core_note_type = NT_PRFPREG,
++ .n = ELF_NFPREG,
++ .size = sizeof(elf_fpreg_t), .align = sizeof(elf_fpreg_t),
++ .get = fpregs_get, .set = fpregs_set, .active = fpregs_active
++ },
++};
++
++static const struct user_regset_view user_ia64_view = {
++ .name = "ia64",
++ .e_machine = EM_IA_64,
++ .regsets = native_regsets, .n = ARRAY_SIZE(native_regsets)
++};
++
++const struct user_regset_view *task_user_regset_view(struct task_struct *tsk)
++{
++#ifdef CONFIG_IA32_SUPPORT
++ extern const struct user_regset_view user_ia32_view;
++ if (IS_IA32_PROCESS(task_pt_regs(tsk)))
++ return &user_ia32_view;
++#endif
++ return &user_ia64_view;
++}
+diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
+index 779c3cc..b11bb50 100644
+--- a/arch/ia64/kernel/salinfo.c
++++ b/arch/ia64/kernel/salinfo.c
+@@ -44,8 +44,8 @@
+ #include <linux/smp.h>
+ #include <linux/timer.h>
+ #include <linux/vmalloc.h>
++#include <linux/semaphore.h>
+
+-#include <asm/semaphore.h>
+ #include <asm/sal.h>
+ #include <asm/uaccess.h>
+
+diff --git a/arch/ia64/kernel/semaphore.c b/arch/ia64/kernel/semaphore.c
+deleted file mode 100644
+index 2724ef3..0000000
+--- a/arch/ia64/kernel/semaphore.c
++++ /dev/null
+@@ -1,165 +0,0 @@
+-/*
+- * IA-64 semaphore implementation (derived from x86 version).
+- *
+- * Copyright (C) 1999-2000, 2002 Hewlett-Packard Co
+- * David Mosberger-Tang <davidm at hpl.hp.com>
+- */
+-
+-/*
+- * Semaphores are implemented using a two-way counter: The "count"
+- * variable is decremented for each process that tries to acquire the
+- * semaphore, while the "sleepers" variable is a count of such
+- * acquires.
+- *
+- * Notably, the inline "up()" and "down()" functions can efficiently
+- * test if they need to do any extra work (up needs to do something
+- * only if count was negative before the increment operation.
+- *
+- * "sleeping" and the contention routine ordering is protected
+- * by the spinlock in the semaphore's waitqueue head.
+- *
+- * Note that these functions are only called when there is contention
+- * on the lock, and as such all this is the "non-critical" part of the
+- * whole semaphore business. The critical part is the inline stuff in
+- * <asm/semaphore.h> where we want to avoid any extra jumps and calls.
+- */
+-#include <linux/sched.h>
+-#include <linux/init.h>
+-
+-#include <asm/errno.h>
+-#include <asm/semaphore.h>
+-
+-/*
+- * Logic:
+- * - Only on a boundary condition do we need to care. When we go
+- * from a negative count to a non-negative, we wake people up.
+- * - When we go from a non-negative count to a negative do we
+- * (a) synchronize with the "sleepers" count and (b) make sure
+- * that we're on the wakeup list before we synchronize so that
+- * we cannot lose wakeup events.
+- */
+-
+-void
+-__up (struct semaphore *sem)
+-{
+- wake_up(&sem->wait);
+-}
+-
+-void __sched __down (struct semaphore *sem)
+-{
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+- unsigned long flags;
+-
+- tsk->state = TASK_UNINTERRUPTIBLE;
+- spin_lock_irqsave(&sem->wait.lock, flags);
+- add_wait_queue_exclusive_locked(&sem->wait, &wait);
+-
+- sem->sleepers++;
+- for (;;) {
+- int sleepers = sem->sleepers;
+-
+- /*
+- * Add "everybody else" into it. They aren't
+- * playing, because we own the spinlock in
+- * the wait_queue_head.
+- */
+- if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+- sem->sleepers = 0;
+- break;
+- }
+- sem->sleepers = 1; /* us - see -1 above */
+- spin_unlock_irqrestore(&sem->wait.lock, flags);
+-
+- schedule();
+-
+- spin_lock_irqsave(&sem->wait.lock, flags);
+- tsk->state = TASK_UNINTERRUPTIBLE;
+- }
+- remove_wait_queue_locked(&sem->wait, &wait);
+- wake_up_locked(&sem->wait);
+- spin_unlock_irqrestore(&sem->wait.lock, flags);
+- tsk->state = TASK_RUNNING;
+-}
+-
+-int __sched __down_interruptible (struct semaphore * sem)
+-{
+- int retval = 0;
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+- unsigned long flags;
+-
+- tsk->state = TASK_INTERRUPTIBLE;
+- spin_lock_irqsave(&sem->wait.lock, flags);
+- add_wait_queue_exclusive_locked(&sem->wait, &wait);
+-
+- sem->sleepers ++;
+- for (;;) {
+- int sleepers = sem->sleepers;
+-
+- /*
+- * With signals pending, this turns into
+- * the trylock failure case - we won't be
+- * sleeping, and we* can't get the lock as
+- * it has contention. Just correct the count
+- * and exit.
+- */
+- if (signal_pending(current)) {
+- retval = -EINTR;
+- sem->sleepers = 0;
+- atomic_add(sleepers, &sem->count);
+- break;
+- }
+-
+- /*
+- * Add "everybody else" into it. They aren't
+- * playing, because we own the spinlock in
+- * wait_queue_head. The "-1" is because we're
+- * still hoping to get the semaphore.
+- */
+- if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+- sem->sleepers = 0;
+- break;
+- }
+- sem->sleepers = 1; /* us - see -1 above */
+- spin_unlock_irqrestore(&sem->wait.lock, flags);
+-
+- schedule();
+-
+- spin_lock_irqsave(&sem->wait.lock, flags);
+- tsk->state = TASK_INTERRUPTIBLE;
+- }
+- remove_wait_queue_locked(&sem->wait, &wait);
+- wake_up_locked(&sem->wait);
+- spin_unlock_irqrestore(&sem->wait.lock, flags);
+-
+- tsk->state = TASK_RUNNING;
+- return retval;
+-}
+-
+-/*
+- * Trylock failed - make sure we correct for having decremented the
+- * count.
+- */
+-int
+-__down_trylock (struct semaphore *sem)
+-{
+- unsigned long flags;
+- int sleepers;
+-
+- spin_lock_irqsave(&sem->wait.lock, flags);
+- sleepers = sem->sleepers + 1;
+- sem->sleepers = 0;
+-
+- /*
+- * Add "everybody else" and us into it. They aren't
+- * playing, because we own the spinlock in the
+- * wait_queue_head.
+- */
+- if (!atomic_add_negative(sleepers, &sem->count)) {
+- wake_up_locked(&sem->wait);
+- }
+-
+- spin_unlock_irqrestore(&sem->wait.lock, flags);
+- return 1;
+-}
+diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
+index 4aa9eae..5015ca1 100644
+--- a/arch/ia64/kernel/setup.c
++++ b/arch/ia64/kernel/setup.c
+@@ -59,6 +59,7 @@
+ #include <asm/setup.h>
+ #include <asm/smp.h>
+ #include <asm/system.h>
++#include <asm/tlbflush.h>
+ #include <asm/unistd.h>
+ #include <asm/hpsim.h>
+
+@@ -176,6 +177,29 @@ filter_rsvd_memory (unsigned long start, unsigned long end, void *arg)
+ return 0;
+ }
+
++/*
++ * Similar to "filter_rsvd_memory()", but the reserved memory ranges
++ * are not filtered out.
++ */
++int __init
++filter_memory(unsigned long start, unsigned long end, void *arg)
++{
++ void (*func)(unsigned long, unsigned long, int);
++
++#if IGNORE_PFN0
++ if (start == PAGE_OFFSET) {
++ printk(KERN_WARNING "warning: skipping physical page 0\n");
++ start += PAGE_SIZE;
++ if (start >= end)
++ return 0;
++ }
++#endif
++ func = arg;
++ if (start < end)
++ call_pernode_memory(__pa(start), end - start, func);
++ return 0;
++}
++
+ static void __init
+ sort_regions (struct rsvd_region *rsvd_region, int max)
+ {
+@@ -493,6 +517,8 @@ setup_arch (char **cmdline_p)
+ acpi_table_init();
+ # ifdef CONFIG_ACPI_NUMA
+ acpi_numa_init();
++ per_cpu_scan_finalize((cpus_weight(early_cpu_possible_map) == 0 ?
++ 32 : cpus_weight(early_cpu_possible_map)), additional_cpus);
+ # endif
+ #else
+ # ifdef CONFIG_SMP
+@@ -946,9 +972,10 @@ cpu_init (void)
+ #endif
+
+ /* set ia64_ctx.max_rid to the maximum RID that is supported by all CPUs: */
+- if (ia64_pal_vm_summary(NULL, &vmi) == 0)
++ if (ia64_pal_vm_summary(NULL, &vmi) == 0) {
+ max_ctx = (1U << (vmi.pal_vm_info_2_s.rid_size - 3)) - 1;
+- else {
++ setup_ptcg_sem(vmi.pal_vm_info_2_s.max_purges, NPTCG_FROM_PAL);
++ } else {
+ printk(KERN_WARNING "cpu_init: PAL VM summary failed, assuming 18 RID bits\n");
+ max_ctx = (1U << 15) - 1; /* use architected minimum */
+ }
+diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
+index 4e446aa..9a9d4c4 100644
+--- a/arch/ia64/kernel/smp.c
++++ b/arch/ia64/kernel/smp.c
+@@ -213,6 +213,19 @@ send_IPI_allbutself (int op)
+ * Called with preemption disabled.
+ */
+ static inline void
++send_IPI_mask(cpumask_t mask, int op)
++{
++ unsigned int cpu;
++
++ for_each_cpu_mask(cpu, mask) {
++ send_IPI_single(cpu, op);
++ }
++}
++
++/*
++ * Called with preemption disabled.
++ */
++static inline void
+ send_IPI_all (int op)
+ {
+ int i;
+@@ -401,6 +414,75 @@ smp_call_function_single (int cpuid, void (*func) (void *info), void *info, int
+ }
+ EXPORT_SYMBOL(smp_call_function_single);
+
++/**
++ * smp_call_function_mask(): Run a function on a set of other CPUs.
++ * <mask> The set of cpus to run on. Must not include the current cpu.
++ * <func> The function to run. This must be fast and non-blocking.
++ * <info> An arbitrary pointer to pass to the function.
++ * <wait> If true, wait (atomically) until function
++ * has completed on other CPUs.
++ *
++ * Returns 0 on success, else a negative status code.
++ *
++ * If @wait is true, then returns once @func has returned; otherwise
++ * it returns just before the target cpu calls @func.
++ *
++ * You must not call this function with disabled interrupts or from a
++ * hardware interrupt handler or from a bottom half handler.
++ */
++int smp_call_function_mask(cpumask_t mask,
++ void (*func)(void *), void *info,
++ int wait)
++{
++ struct call_data_struct data;
++ cpumask_t allbutself;
++ int cpus;
++
++ spin_lock(&call_lock);
++ allbutself = cpu_online_map;
++ cpu_clear(smp_processor_id(), allbutself);
++
++ cpus_and(mask, mask, allbutself);
++ cpus = cpus_weight(mask);
++ if (!cpus) {
++ spin_unlock(&call_lock);
++ return 0;
++ }
++
++ /* Can deadlock when called with interrupts disabled */
++ WARN_ON(irqs_disabled());
++
++ data.func = func;
++ data.info = info;
++ atomic_set(&data.started, 0);
++ data.wait = wait;
++ if (wait)
++ atomic_set(&data.finished, 0);
++
++ call_data = &data;
++ mb(); /* ensure store to call_data precedes setting of IPI_CALL_FUNC*/
++
++ /* Send a message to other CPUs */
++ if (cpus_equal(mask, allbutself))
++ send_IPI_allbutself(IPI_CALL_FUNC);
++ else
++ send_IPI_mask(mask, IPI_CALL_FUNC);
++
++ /* Wait for response */
++ while (atomic_read(&data.started) != cpus)
++ cpu_relax();
++
++ if (wait)
++ while (atomic_read(&data.finished) != cpus)
++ cpu_relax();
++ call_data = NULL;
++
++ spin_unlock(&call_lock);
++ return 0;
++
++}
++EXPORT_SYMBOL(smp_call_function_mask);
++
+ /*
+ * this function sends a 'generic call function' IPI to all other CPUs
+ * in the system.
+diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
+index 32ee597..16483be 100644
+--- a/arch/ia64/kernel/smpboot.c
++++ b/arch/ia64/kernel/smpboot.c
+@@ -400,9 +400,9 @@ smp_callin (void)
+ /* Setup the per cpu irq handling data structures */
+ __setup_vector_irq(cpuid);
+ cpu_set(cpuid, cpu_online_map);
+- unlock_ipi_calllock();
+ per_cpu(cpu_state, cpuid) = CPU_ONLINE;
+ spin_unlock(&vector_lock);
++ unlock_ipi_calllock();
+
+ smp_setup_percpu_timer();
+
+diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
+index 17fda52..48e15a5 100644
+--- a/arch/ia64/kernel/time.c
++++ b/arch/ia64/kernel/time.c
+@@ -59,6 +59,84 @@ static struct clocksource clocksource_itc = {
+ };
+ static struct clocksource *itc_clocksource;
+
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++
++#include <linux/kernel_stat.h>
++
++extern cputime_t cycle_to_cputime(u64 cyc);
++
++/*
++ * Called from the context switch with interrupts disabled, to charge all
++ * accumulated times to the current process, and to prepare accounting on
++ * the next process.
++ */
++void ia64_account_on_switch(struct task_struct *prev, struct task_struct *next)
++{
++ struct thread_info *pi = task_thread_info(prev);
++ struct thread_info *ni = task_thread_info(next);
++ cputime_t delta_stime, delta_utime;
++ __u64 now;
++
++ now = ia64_get_itc();
++
++ delta_stime = cycle_to_cputime(pi->ac_stime + (now - pi->ac_stamp));
++ account_system_time(prev, 0, delta_stime);
++ account_system_time_scaled(prev, delta_stime);
++
++ if (pi->ac_utime) {
++ delta_utime = cycle_to_cputime(pi->ac_utime);
++ account_user_time(prev, delta_utime);
++ account_user_time_scaled(prev, delta_utime);
++ }
++
++ pi->ac_stamp = ni->ac_stamp = now;
++ ni->ac_stime = ni->ac_utime = 0;
++}
++
++/*
++ * Account time for a transition between system, hard irq or soft irq state.
++ * Note that this function is called with interrupts enabled.
++ */
++void account_system_vtime(struct task_struct *tsk)
++{
++ struct thread_info *ti = task_thread_info(tsk);
++ unsigned long flags;
++ cputime_t delta_stime;
++ __u64 now;
++
++ local_irq_save(flags);
++
++ now = ia64_get_itc();
++
++ delta_stime = cycle_to_cputime(ti->ac_stime + (now - ti->ac_stamp));
++ account_system_time(tsk, 0, delta_stime);
++ account_system_time_scaled(tsk, delta_stime);
++ ti->ac_stime = 0;
++
++ ti->ac_stamp = now;
++
++ local_irq_restore(flags);
++}
++
++/*
++ * Called from the timer interrupt handler to charge accumulated user time
++ * to the current process. Must be called with interrupts disabled.
++ */
++void account_process_tick(struct task_struct *p, int user_tick)
++{
++ struct thread_info *ti = task_thread_info(p);
++ cputime_t delta_utime;
++
++ if (ti->ac_utime) {
++ delta_utime = cycle_to_cputime(ti->ac_utime);
++ account_user_time(p, delta_utime);
++ account_user_time_scaled(p, delta_utime);
++ ti->ac_utime = 0;
++ }
++}
++
++#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
++
+ static irqreturn_t
+ timer_interrupt (int irq, void *dev_id)
+ {
+diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c
+index 6903361..ff0e7c1 100644
+--- a/arch/ia64/kernel/unaligned.c
++++ b/arch/ia64/kernel/unaligned.c
+@@ -13,6 +13,7 @@
+ * 2001/08/13 Correct size of extended floats (float_fsz) from 16 to 10 bytes.
+ * 2001/01/17 Add support emulation of unaligned kernel accesses.
+ */
++#include <linux/jiffies.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+ #include <linux/tty.h>
+@@ -1290,7 +1291,7 @@ within_logging_rate_limit (void)
+ {
+ static unsigned long count, last_time;
+
+- if (jiffies - last_time > 5*HZ)
++ if (time_after(jiffies, last_time + 5 * HZ))
+ count = 0;
+ if (count < 5) {
+ last_time = jiffies;
+diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
+index 344f64e..798bf98 100644
+--- a/arch/ia64/mm/contig.c
++++ b/arch/ia64/mm/contig.c
+@@ -45,8 +45,6 @@ void show_mem(void)
+
+ printk(KERN_INFO "Mem-info:\n");
+ show_free_areas();
+- printk(KERN_INFO "Free swap: %6ldkB\n",
+- nr_swap_pages<<(PAGE_SHIFT-10));
+ printk(KERN_INFO "Node memory in pages:\n");
+ for_each_online_pgdat(pgdat) {
+ unsigned long present;
+@@ -255,7 +253,7 @@ paging_init (void)
+ max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
+
+ #ifdef CONFIG_VIRTUAL_MEM_MAP
+- efi_memmap_walk(register_active_ranges, NULL);
++ efi_memmap_walk(filter_memory, register_active_ranges);
+ efi_memmap_walk(find_largest_hole, (u64 *)&max_gap);
+ if (max_gap < LARGE_GAP) {
+ vmem_map = (struct page *) 0;
+diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
+index ee5e68b..544dc42 100644
+--- a/arch/ia64/mm/discontig.c
++++ b/arch/ia64/mm/discontig.c
+@@ -104,7 +104,7 @@ static int __meminit early_nr_cpus_node(int node)
+ {
+ int cpu, n = 0;
+
+- for (cpu = 0; cpu < NR_CPUS; cpu++)
++ for_each_possible_early_cpu(cpu)
+ if (node == node_cpuid[cpu].nid)
+ n++;
+
+@@ -124,6 +124,7 @@ static unsigned long __meminit compute_pernodesize(int node)
+ pernodesize += node * L1_CACHE_BYTES;
+ pernodesize += L1_CACHE_ALIGN(sizeof(pg_data_t));
+ pernodesize += L1_CACHE_ALIGN(sizeof(struct ia64_node_data));
++ pernodesize += L1_CACHE_ALIGN(sizeof(pg_data_t));
+ pernodesize = PAGE_ALIGN(pernodesize);
+ return pernodesize;
+ }
+@@ -142,7 +143,7 @@ static void *per_cpu_node_setup(void *cpu_data, int node)
+ #ifdef CONFIG_SMP
+ int cpu;
+
+- for (cpu = 0; cpu < NR_CPUS; cpu++) {
++ for_each_possible_early_cpu(cpu) {
+ if (node == node_cpuid[cpu].nid) {
+ memcpy(__va(cpu_data), __phys_per_cpu_start,
+ __per_cpu_end - __per_cpu_start);
+@@ -345,7 +346,7 @@ static void __init initialize_pernode_data(void)
+
+ #ifdef CONFIG_SMP
+ /* Set the node_data pointer for each per-cpu struct */
+- for (cpu = 0; cpu < NR_CPUS; cpu++) {
++ for_each_possible_early_cpu(cpu) {
+ node = node_cpuid[cpu].nid;
+ per_cpu(cpu_info, cpu).node_data = mem_data[node].node_data;
+ }
+@@ -444,7 +445,7 @@ void __init find_memory(void)
+ mem_data[node].min_pfn = ~0UL;
+ }
+
+- efi_memmap_walk(register_active_ranges, NULL);
++ efi_memmap_walk(filter_memory, register_active_ranges);
+
+ /*
+ * Initialize the boot memory maps in reverse order since that's
+@@ -493,13 +494,9 @@ void __cpuinit *per_cpu_init(void)
+ int cpu;
+ static int first_time = 1;
+
+-
+- if (smp_processor_id() != 0)
+- return __per_cpu_start + __per_cpu_offset[smp_processor_id()];
+-
+ if (first_time) {
+ first_time = 0;
+- for (cpu = 0; cpu < NR_CPUS; cpu++)
++ for_each_possible_early_cpu(cpu)
+ per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
+ }
+
+@@ -522,8 +519,6 @@ void show_mem(void)
+
+ printk(KERN_INFO "Mem-info:\n");
+ show_free_areas();
+- printk(KERN_INFO "Free swap: %6ldkB\n",
+- nr_swap_pages<<(PAGE_SHIFT-10));
+ printk(KERN_INFO "Node memory in pages:\n");
+ for_each_online_pgdat(pgdat) {
+ unsigned long present;
+diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
+index a4ca657..5c1de53 100644
+--- a/arch/ia64/mm/init.c
++++ b/arch/ia64/mm/init.c
+@@ -58,7 +58,6 @@ __ia64_sync_icache_dcache (pte_t pte)
+ {
+ unsigned long addr;
+ struct page *page;
+- unsigned long order;
+
+ page = pte_page(pte);
+ addr = (unsigned long) page_address(page);
+@@ -66,12 +65,7 @@ __ia64_sync_icache_dcache (pte_t pte)
+ if (test_bit(PG_arch_1, &page->flags))
+ return; /* i-cache is already coherent with d-cache */
+
+- if (PageCompound(page)) {
+- order = compound_order(page);
+- flush_icache_range(addr, addr + (1UL << order << PAGE_SHIFT));
+- }
+- else
+- flush_icache_range(addr, addr + PAGE_SIZE);
++ flush_icache_range(addr, addr + (PAGE_SIZE << compound_order(page)));
+ set_bit(PG_arch_1, &page->flags); /* mark page as clean */
+ }
+
+@@ -553,12 +547,10 @@ find_largest_hole (u64 start, u64 end, void *arg)
+ #endif /* CONFIG_VIRTUAL_MEM_MAP */
+
+ int __init
+-register_active_ranges(u64 start, u64 end, void *arg)
++register_active_ranges(u64 start, u64 len, int nid)
+ {
+- int nid = paddr_to_nid(__pa(start));
++ u64 end = start + len;
+
+- if (nid < 0)
+- nid = 0;
+ #ifdef CONFIG_KEXEC
+ if (start > crashk_res.start && start < crashk_res.end)
+ start = crashk_res.end;
+diff --git a/arch/ia64/mm/numa.c b/arch/ia64/mm/numa.c
+index 7807fc5..b73bf18 100644
+--- a/arch/ia64/mm/numa.c
++++ b/arch/ia64/mm/numa.c
+@@ -27,7 +27,9 @@
+ */
+ int num_node_memblks;
+ struct node_memblk_s node_memblk[NR_NODE_MEMBLKS];
+-struct node_cpuid_s node_cpuid[NR_CPUS];
++struct node_cpuid_s node_cpuid[NR_CPUS] =
++ { [0 ... NR_CPUS-1] = { .phys_id = 0, .nid = NUMA_NO_NODE } };
++
+ /*
+ * This is a matrix with "distances" between nodes, they should be
+ * proportional to the memory access latency ratios.
+diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
+index 655da24..d52ec4e 100644
+--- a/arch/ia64/mm/tlb.c
++++ b/arch/ia64/mm/tlb.c
+@@ -11,6 +11,9 @@
+ * Rohit Seth <rohit.seth at intel.com>
+ * Ken Chen <kenneth.w.chen at intel.com>
+ * Christophe de Dinechin <ddd at hp.com>: Avoid ptc.e on memory allocation
++ * Copyright (C) 2007 Intel Corp
++ * Fenghua Yu <fenghua.yu at intel.com>
++ * Add multiple ptc.g/ptc.ga instruction support in global tlb purge.
+ */
+ #include <linux/module.h>
+ #include <linux/init.h>
+@@ -26,6 +29,9 @@
+ #include <asm/pal.h>
+ #include <asm/tlbflush.h>
+ #include <asm/dma.h>
++#include <asm/processor.h>
++#include <asm/sal.h>
++#include <asm/tlb.h>
+
+ static struct {
+ unsigned long mask; /* mask of supported purge page-sizes */
+@@ -39,6 +45,10 @@ struct ia64_ctx ia64_ctx = {
+ };
+
+ DEFINE_PER_CPU(u8, ia64_need_tlb_flush);
++DEFINE_PER_CPU(u8, ia64_tr_num); /*Number of TR slots in current processor*/
++DEFINE_PER_CPU(u8, ia64_tr_used); /*Max Slot number used by kernel*/
++
++struct ia64_tr_entry __per_cpu_idtrs[NR_CPUS][2][IA64_TR_ALLOC_MAX];
+
+ /*
+ * Initializes the ia64_ctx.bitmap array based on max_ctx+1.
+@@ -84,14 +94,140 @@ wrap_mmu_context (struct mm_struct *mm)
+ local_flush_tlb_all();
+ }
+
++/*
++ * Implement "spinaphores" ... like counting semaphores, but they
++ * spin instead of sleeping. If there are ever any other users for
++ * this primitive it can be moved up to a spinaphore.h header.
++ */
++struct spinaphore {
++ atomic_t cur;
++};
++
++static inline void spinaphore_init(struct spinaphore *ss, int val)
++{
++ atomic_set(&ss->cur, val);
++}
++
++static inline void down_spin(struct spinaphore *ss)
++{
++ while (unlikely(!atomic_add_unless(&ss->cur, -1, 0)))
++ while (atomic_read(&ss->cur) == 0)
++ cpu_relax();
++}
++
++static inline void up_spin(struct spinaphore *ss)
++{
++ atomic_add(1, &ss->cur);
++}
++
++static struct spinaphore ptcg_sem;
++static u16 nptcg = 1;
++static int need_ptcg_sem = 1;
++static int toolatetochangeptcgsem = 0;
++
++/*
++ * Kernel parameter "nptcg=" overrides max number of concurrent global TLB
++ * purges which is reported from either PAL or SAL PALO.
++ *
++ * We don't have sanity checking for nptcg value. It's the user's responsibility
++ * for valid nptcg value on the platform. Otherwise, kernel may hang in some
++ * cases.
++ */
++static int __init
++set_nptcg(char *str)
++{
++ int value = 0;
++
++ get_option(&str, &value);
++ setup_ptcg_sem(value, NPTCG_FROM_KERNEL_PARAMETER);
++
++ return 1;
++}
++
++__setup("nptcg=", set_nptcg);
++
++/*
++ * Maximum number of simultaneous ptc.g purges in the system can
++ * be defined by PAL_VM_SUMMARY (in which case we should take
++ * the smallest value for any cpu in the system) or by the PAL
++ * override table (in which case we should ignore the value from
++ * PAL_VM_SUMMARY).
++ *
++ * Kernel parameter "nptcg=" overrides maximum number of simultanesous ptc.g
++ * purges defined in either PAL_VM_SUMMARY or PAL override table. In this case,
++ * we should ignore the value from either PAL_VM_SUMMARY or PAL override table.
++ *
++ * Complicating the logic here is the fact that num_possible_cpus()
++ * isn't fully setup until we start bringing cpus online.
++ */
++void
++setup_ptcg_sem(int max_purges, int nptcg_from)
++{
++ static int kp_override;
++ static int palo_override;
++ static int firstcpu = 1;
++
++ if (toolatetochangeptcgsem) {
++ BUG_ON(max_purges < nptcg);
++ return;
++ }
++
++ if (nptcg_from == NPTCG_FROM_KERNEL_PARAMETER) {
++ kp_override = 1;
++ nptcg = max_purges;
++ goto resetsema;
++ }
++ if (kp_override) {
++ need_ptcg_sem = num_possible_cpus() > nptcg;
++ return;
++ }
++
++ if (nptcg_from == NPTCG_FROM_PALO) {
++ palo_override = 1;
++
++ /* In PALO max_purges == 0 really means it! */
++ if (max_purges == 0)
++ panic("Whoa! Platform does not support global TLB purges.\n");
++ nptcg = max_purges;
++ if (nptcg == PALO_MAX_TLB_PURGES) {
++ need_ptcg_sem = 0;
++ return;
++ }
++ goto resetsema;
++ }
++ if (palo_override) {
++ if (nptcg != PALO_MAX_TLB_PURGES)
++ need_ptcg_sem = (num_possible_cpus() > nptcg);
++ return;
++ }
++
++ /* In PAL_VM_SUMMARY max_purges == 0 actually means 1 */
++ if (max_purges == 0) max_purges = 1;
++
++ if (firstcpu) {
++ nptcg = max_purges;
++ firstcpu = 0;
++ }
++ if (max_purges < nptcg)
++ nptcg = max_purges;
++ if (nptcg == PAL_MAX_PURGES) {
++ need_ptcg_sem = 0;
++ return;
++ } else
++ need_ptcg_sem = (num_possible_cpus() > nptcg);
++
++resetsema:
++ spinaphore_init(&ptcg_sem, max_purges);
++}
++
+ void
+ ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start,
+ unsigned long end, unsigned long nbits)
+ {
+- static DEFINE_SPINLOCK(ptcg_lock);
+-
+ struct mm_struct *active_mm = current->active_mm;
+
++ toolatetochangeptcgsem = 1;
++
+ if (mm != active_mm) {
+ /* Restore region IDs for mm */
+ if (mm && active_mm) {
+@@ -102,19 +238,20 @@ ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start,
+ }
+ }
+
+- /* HW requires global serialization of ptc.ga. */
+- spin_lock(&ptcg_lock);
+- {
+- do {
+- /*
+- * Flush ALAT entries also.
+- */
+- ia64_ptcga(start, (nbits<<2));
+- ia64_srlz_i();
+- start += (1UL << nbits);
+- } while (start < end);
+- }
+- spin_unlock(&ptcg_lock);
++ if (need_ptcg_sem)
++ down_spin(&ptcg_sem);
++
++ do {
++ /*
++ * Flush ALAT entries also.
++ */
++ ia64_ptcga(start, (nbits << 2));
++ ia64_srlz_i();
++ start += (1UL << nbits);
++ } while (start < end);
++
++ if (need_ptcg_sem)
++ up_spin(&ptcg_sem);
+
+ if (mm != active_mm) {
+ activate_context(active_mm);
+@@ -190,6 +327,9 @@ ia64_tlb_init (void)
+ ia64_ptce_info_t uninitialized_var(ptce_info); /* GCC be quiet */
+ unsigned long tr_pgbits;
+ long status;
++ pal_vm_info_1_u_t vm_info_1;
++ pal_vm_info_2_u_t vm_info_2;
++ int cpu = smp_processor_id();
+
+ if ((status = ia64_pal_vm_page_size(&tr_pgbits, &purge.mask)) != 0) {
+ printk(KERN_ERR "PAL_VM_PAGE_SIZE failed with status=%ld; "
+@@ -206,4 +346,191 @@ ia64_tlb_init (void)
+ local_cpu_data->ptce_stride[1] = ptce_info.stride[1];
+
+ local_flush_tlb_all(); /* nuke left overs from bootstrapping... */
++ status = ia64_pal_vm_summary(&vm_info_1, &vm_info_2);
++
++ if (status) {
++ printk(KERN_ERR "ia64_pal_vm_summary=%ld\n", status);
++ per_cpu(ia64_tr_num, cpu) = 8;
++ return;
++ }
++ per_cpu(ia64_tr_num, cpu) = vm_info_1.pal_vm_info_1_s.max_itr_entry+1;
++ if (per_cpu(ia64_tr_num, cpu) >
++ (vm_info_1.pal_vm_info_1_s.max_dtr_entry+1))
++ per_cpu(ia64_tr_num, cpu) =
++ vm_info_1.pal_vm_info_1_s.max_dtr_entry+1;
++ if (per_cpu(ia64_tr_num, cpu) > IA64_TR_ALLOC_MAX) {
++ per_cpu(ia64_tr_num, cpu) = IA64_TR_ALLOC_MAX;
++ printk(KERN_DEBUG "TR register number exceeds IA64_TR_ALLOC_MAX!"
++ "IA64_TR_ALLOC_MAX should be extended\n");
++ }
++}
++
++/*
++ * is_tr_overlap
++ *
++ * Check overlap with inserted TRs.
++ */
++static int is_tr_overlap(struct ia64_tr_entry *p, u64 va, u64 log_size)
++{
++ u64 tr_log_size;
++ u64 tr_end;
++ u64 va_rr = ia64_get_rr(va);
++ u64 va_rid = RR_TO_RID(va_rr);
++ u64 va_end = va + (1<<log_size) - 1;
++
++ if (va_rid != RR_TO_RID(p->rr))
++ return 0;
++ tr_log_size = (p->itir & 0xff) >> 2;
++ tr_end = p->ifa + (1<<tr_log_size) - 1;
++
++ if (va > tr_end || p->ifa > va_end)
++ return 0;
++ return 1;
++
++}
++
++/*
++ * ia64_insert_tr in virtual mode. Allocate a TR slot
++ *
++ * target_mask : 0x1 : itr, 0x2 : dtr, 0x3 : idtr
++ *
++ * va : virtual address.
++ * pte : pte entries inserted.
++ * log_size: range to be covered.
++ *
++ * Return value: <0 : error No.
++ *
++ * >=0 : slot number allocated for TR.
++ * Must be called with preemption disabled.
++ */
++int ia64_itr_entry(u64 target_mask, u64 va, u64 pte, u64 log_size)
++{
++ int i, r;
++ unsigned long psr;
++ struct ia64_tr_entry *p;
++ int cpu = smp_processor_id();
++
++ r = -EINVAL;
++ /*Check overlap with existing TR entries*/
++ if (target_mask & 0x1) {
++ p = &__per_cpu_idtrs[cpu][0][0];
++ for (i = IA64_TR_ALLOC_BASE; i <= per_cpu(ia64_tr_used, cpu);
++ i++, p++) {
++ if (p->pte & 0x1)
++ if (is_tr_overlap(p, va, log_size)) {
++ printk(KERN_DEBUG "Overlapped Entry"
++ "Inserted for TR Reigster!!\n");
++ goto out;
++ }
++ }
++ }
++ if (target_mask & 0x2) {
++ p = &__per_cpu_idtrs[cpu][1][0];
++ for (i = IA64_TR_ALLOC_BASE; i <= per_cpu(ia64_tr_used, cpu);
++ i++, p++) {
++ if (p->pte & 0x1)
++ if (is_tr_overlap(p, va, log_size)) {
++ printk(KERN_DEBUG "Overlapped Entry"
++ "Inserted for TR Reigster!!\n");
++ goto out;
++ }
++ }
++ }
++
++ for (i = IA64_TR_ALLOC_BASE; i < per_cpu(ia64_tr_num, cpu); i++) {
++ switch (target_mask & 0x3) {
++ case 1:
++ if (!(__per_cpu_idtrs[cpu][0][i].pte & 0x1))
++ goto found;
++ continue;
++ case 2:
++ if (!(__per_cpu_idtrs[cpu][1][i].pte & 0x1))
++ goto found;
++ continue;
++ case 3:
++ if (!(__per_cpu_idtrs[cpu][0][i].pte & 0x1) &&
++ !(__per_cpu_idtrs[cpu][1][i].pte & 0x1))
++ goto found;
++ continue;
++ default:
++ r = -EINVAL;
++ goto out;
++ }
++ }
++found:
++ if (i >= per_cpu(ia64_tr_num, cpu))
++ return -EBUSY;
++
++ /*Record tr info for mca hander use!*/
++ if (i > per_cpu(ia64_tr_used, cpu))
++ per_cpu(ia64_tr_used, cpu) = i;
++
++ psr = ia64_clear_ic();
++ if (target_mask & 0x1) {
++ ia64_itr(0x1, i, va, pte, log_size);
++ ia64_srlz_i();
++ p = &__per_cpu_idtrs[cpu][0][i];
++ p->ifa = va;
++ p->pte = pte;
++ p->itir = log_size << 2;
++ p->rr = ia64_get_rr(va);
++ }
++ if (target_mask & 0x2) {
++ ia64_itr(0x2, i, va, pte, log_size);
++ ia64_srlz_i();
++ p = &__per_cpu_idtrs[cpu][1][i];
++ p->ifa = va;
++ p->pte = pte;
++ p->itir = log_size << 2;
++ p->rr = ia64_get_rr(va);
++ }
++ ia64_set_psr(psr);
++ r = i;
++out:
++ return r;
++}
++EXPORT_SYMBOL_GPL(ia64_itr_entry);
++
++/*
++ * ia64_purge_tr
++ *
++ * target_mask: 0x1: purge itr, 0x2 : purge dtr, 0x3 purge idtr.
++ * slot: slot number to be freed.
++ *
++ * Must be called with preemption disabled.
++ */
++void ia64_ptr_entry(u64 target_mask, int slot)
++{
++ int cpu = smp_processor_id();
++ int i;
++ struct ia64_tr_entry *p;
++
++ if (slot < IA64_TR_ALLOC_BASE || slot >= per_cpu(ia64_tr_num, cpu))
++ return;
++
++ if (target_mask & 0x1) {
++ p = &__per_cpu_idtrs[cpu][0][slot];
++ if ((p->pte&0x1) && is_tr_overlap(p, p->ifa, p->itir>>2)) {
++ p->pte = 0;
++ ia64_ptr(0x1, p->ifa, p->itir>>2);
++ ia64_srlz_i();
++ }
++ }
++
++ if (target_mask & 0x2) {
++ p = &__per_cpu_idtrs[cpu][1][slot];
++ if ((p->pte & 0x1) && is_tr_overlap(p, p->ifa, p->itir>>2)) {
++ p->pte = 0;
++ ia64_ptr(0x2, p->ifa, p->itir>>2);
++ ia64_srlz_i();
++ }
++ }
++
++ for (i = per_cpu(ia64_tr_used, cpu); i >= IA64_TR_ALLOC_BASE; i--) {
++ if ((__per_cpu_idtrs[cpu][0][i].pte & 0x1) ||
++ (__per_cpu_idtrs[cpu][1][i].pte & 0x1))
++ break;
++ }
++ per_cpu(ia64_tr_used, cpu) = i;
+ }
++EXPORT_SYMBOL_GPL(ia64_ptr_entry);
+diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
+index 53d0a8e..77b15f8 100644
+--- a/arch/ia64/pci/pci.c
++++ b/arch/ia64/pci/pci.c
+@@ -504,54 +504,12 @@ pcibios_update_irq (struct pci_dev *dev, int irq)
+ /* ??? FIXME -- record old value for shutdown. */
+ }
+
+-static inline int
+-pcibios_enable_resources (struct pci_dev *dev, int mask)
+-{
+- u16 cmd, old_cmd;
+- int idx;
+- struct resource *r;
+- unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM;
+-
+- if (!dev)
+- return -EINVAL;
+-
+- pci_read_config_word(dev, PCI_COMMAND, &cmd);
+- old_cmd = cmd;
+- for (idx=0; idx<PCI_NUM_RESOURCES; idx++) {
+- /* Only set up the desired resources. */
+- if (!(mask & (1 << idx)))
+- continue;
+-
+- r = &dev->resource[idx];
+- if (!(r->flags & type_mask))
+- continue;
+- if ((idx == PCI_ROM_RESOURCE) &&
+- (!(r->flags & IORESOURCE_ROM_ENABLE)))
+- continue;
+- if (!r->start && r->end) {
+- printk(KERN_ERR
+- "PCI: Device %s not available because of resource collisions\n",
+- pci_name(dev));
+- return -EINVAL;
+- }
+- if (r->flags & IORESOURCE_IO)
+- cmd |= PCI_COMMAND_IO;
+- if (r->flags & IORESOURCE_MEM)
+- cmd |= PCI_COMMAND_MEMORY;
+- }
+- if (cmd != old_cmd) {
+- printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);
+- pci_write_config_word(dev, PCI_COMMAND, cmd);
+- }
+- return 0;
+-}
+-
+ int
+ pcibios_enable_device (struct pci_dev *dev, int mask)
+ {
+ int ret;
+
+- ret = pcibios_enable_resources(dev, mask);
++ ret = pci_enable_resources(dev, mask);
+ if (ret < 0)
+ return ret;
+
+diff --git a/arch/ia64/sn/kernel/Makefile b/arch/ia64/sn/kernel/Makefile
+index 688a3c2..0591038 100644
+--- a/arch/ia64/sn/kernel/Makefile
++++ b/arch/ia64/sn/kernel/Makefile
+@@ -4,7 +4,7 @@
+ # License. See the file "COPYING" in the main directory of this archive
+ # for more details.
+ #
+-# Copyright (C) 1999,2001-2006 Silicon Graphics, Inc. All Rights Reserved.
++# Copyright (C) 1999,2001-2006,2008 Silicon Graphics, Inc. All Rights Reserved.
+ #
+
+ EXTRA_CFLAGS += -Iarch/ia64/sn/include
+@@ -15,9 +15,4 @@ obj-y += setup.o bte.o bte_error.o irq.o mca.o idle.o \
+ sn2/
+ obj-$(CONFIG_IA64_GENERIC) += machvec.o
+ obj-$(CONFIG_SGI_TIOCX) += tiocx.o
+-obj-$(CONFIG_IA64_SGI_SN_XP) += xp.o
+-xp-y := xp_main.o xp_nofault.o
+-obj-$(CONFIG_IA64_SGI_SN_XP) += xpc.o
+-xpc-y := xpc_main.o xpc_channel.o xpc_partition.o
+-obj-$(CONFIG_IA64_SGI_SN_XP) += xpnet.o
+ obj-$(CONFIG_PCI_MSI) += msi_sn.o
+diff --git a/arch/ia64/sn/kernel/huberror.c b/arch/ia64/sn/kernel/huberror.c
+index 0101c79..08b0d9b 100644
+--- a/arch/ia64/sn/kernel/huberror.c
++++ b/arch/ia64/sn/kernel/huberror.c
+@@ -187,8 +187,8 @@ void hub_error_init(struct hubdev_info *hubdev_info)
+ {
+
+ if (request_irq(SGI_II_ERROR, hub_eint_handler, IRQF_SHARED,
+- "SN_hub_error", (void *)hubdev_info)) {
+- printk("hub_error_init: Failed to request_irq for 0x%p\n",
++ "SN_hub_error", hubdev_info)) {
++ printk(KERN_ERR "hub_error_init: Failed to request_irq for 0x%p\n",
+ hubdev_info);
+ return;
+ }
+diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+index 4b0d153..8cc0c47 100644
+--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
++++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+@@ -37,7 +37,6 @@
+
+ #include <asm/processor.h>
+ #include <asm/topology.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ #include <asm/sal.h>
+ #include <asm/sn/io.h>
+diff --git a/arch/ia64/sn/kernel/xp_main.c b/arch/ia64/sn/kernel/xp_main.c
+deleted file mode 100644
+index b7ea466..0000000
+--- a/arch/ia64/sn/kernel/xp_main.c
++++ /dev/null
+@@ -1,290 +0,0 @@
+-/*
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License. See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.
+- */
+-
+-
+-/*
+- * Cross Partition (XP) base.
+- *
+- * XP provides a base from which its users can interact
+- * with XPC, yet not be dependent on XPC.
+- *
+- */
+-
+-
+-#include <linux/kernel.h>
+-#include <linux/interrupt.h>
+-#include <linux/module.h>
+-#include <linux/mutex.h>
+-#include <asm/sn/intr.h>
+-#include <asm/sn/sn_sal.h>
+-#include <asm/sn/xp.h>
+-
+-
+-/*
+- * Target of nofault PIO read.
+- */
+-u64 xp_nofault_PIOR_target;
+-
+-
+-/*
+- * xpc_registrations[] keeps track of xpc_connect()'s done by the kernel-level
+- * users of XPC.
+- */
+-struct xpc_registration xpc_registrations[XPC_NCHANNELS];
+-
+-
+-/*
+- * Initialize the XPC interface to indicate that XPC isn't loaded.
+- */
+-static enum xpc_retval xpc_notloaded(void) { return xpcNotLoaded; }
+-
+-struct xpc_interface xpc_interface = {
+- (void (*)(int)) xpc_notloaded,
+- (void (*)(int)) xpc_notloaded,
+- (enum xpc_retval (*)(partid_t, int, u32, void **)) xpc_notloaded,
+- (enum xpc_retval (*)(partid_t, int, void *)) xpc_notloaded,
+- (enum xpc_retval (*)(partid_t, int, void *, xpc_notify_func, void *))
+- xpc_notloaded,
+- (void (*)(partid_t, int, void *)) xpc_notloaded,
+- (enum xpc_retval (*)(partid_t, void *)) xpc_notloaded
+-};
+-
+-
+-/*
+- * XPC calls this when it (the XPC module) has been loaded.
+- */
+-void
+-xpc_set_interface(void (*connect)(int),
+- void (*disconnect)(int),
+- enum xpc_retval (*allocate)(partid_t, int, u32, void **),
+- enum xpc_retval (*send)(partid_t, int, void *),
+- enum xpc_retval (*send_notify)(partid_t, int, void *,
+- xpc_notify_func, void *),
+- void (*received)(partid_t, int, void *),
+- enum xpc_retval (*partid_to_nasids)(partid_t, void *))
+-{
+- xpc_interface.connect = connect;
+- xpc_interface.disconnect = disconnect;
+- xpc_interface.allocate = allocate;
+- xpc_interface.send = send;
+- xpc_interface.send_notify = send_notify;
+- xpc_interface.received = received;
+- xpc_interface.partid_to_nasids = partid_to_nasids;
+-}
+-
+-
+-/*
+- * XPC calls this when it (the XPC module) is being unloaded.
+- */
+-void
+-xpc_clear_interface(void)
+-{
+- xpc_interface.connect = (void (*)(int)) xpc_notloaded;
+- xpc_interface.disconnect = (void (*)(int)) xpc_notloaded;
+- xpc_interface.allocate = (enum xpc_retval (*)(partid_t, int, u32,
+- void **)) xpc_notloaded;
+- xpc_interface.send = (enum xpc_retval (*)(partid_t, int, void *))
+- xpc_notloaded;
+- xpc_interface.send_notify = (enum xpc_retval (*)(partid_t, int, void *,
+- xpc_notify_func, void *)) xpc_notloaded;
+- xpc_interface.received = (void (*)(partid_t, int, void *))
+- xpc_notloaded;
+- xpc_interface.partid_to_nasids = (enum xpc_retval (*)(partid_t, void *))
+- xpc_notloaded;
+-}
+-
+-
+-/*
+- * Register for automatic establishment of a channel connection whenever
+- * a partition comes up.
+- *
+- * Arguments:
+- *
+- * ch_number - channel # to register for connection.
+- * func - function to call for asynchronous notification of channel
+- * state changes (i.e., connection, disconnection, error) and
+- * the arrival of incoming messages.
+- * key - pointer to optional user-defined value that gets passed back
+- * to the user on any callouts made to func.
+- * payload_size - size in bytes of the XPC message's payload area which
+- * contains a user-defined message. The user should make
+- * this large enough to hold their largest message.
+- * nentries - max #of XPC message entries a message queue can contain.
+- * The actual number, which is determined when a connection
+- * is established and may be less then requested, will be
+- * passed to the user via the xpcConnected callout.
+- * assigned_limit - max number of kthreads allowed to be processing
+- * messages (per connection) at any given instant.
+- * idle_limit - max number of kthreads allowed to be idle at any given
+- * instant.
+- */
+-enum xpc_retval
+-xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
+- u16 nentries, u32 assigned_limit, u32 idle_limit)
+-{
+- struct xpc_registration *registration;
+-
+-
+- DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
+- DBUG_ON(payload_size == 0 || nentries == 0);
+- DBUG_ON(func == NULL);
+- DBUG_ON(assigned_limit == 0 || idle_limit > assigned_limit);
+-
+- registration = &xpc_registrations[ch_number];
+-
+- if (mutex_lock_interruptible(®istration->mutex) != 0) {
+- return xpcInterrupted;
+- }
+-
+- /* if XPC_CHANNEL_REGISTERED(ch_number) */
+- if (registration->func != NULL) {
+- mutex_unlock(®istration->mutex);
+- return xpcAlreadyRegistered;
+- }
+-
+- /* register the channel for connection */
+- registration->msg_size = XPC_MSG_SIZE(payload_size);
+- registration->nentries = nentries;
+- registration->assigned_limit = assigned_limit;
+- registration->idle_limit = idle_limit;
+- registration->key = key;
+- registration->func = func;
+-
+- mutex_unlock(®istration->mutex);
+-
+- xpc_interface.connect(ch_number);
+-
+- return xpcSuccess;
+-}
+-
+-
+-/*
+- * Remove the registration for automatic connection of the specified channel
+- * when a partition comes up.
+- *
+- * Before returning this xpc_disconnect() will wait for all connections on the
+- * specified channel have been closed/torndown. So the caller can be assured
+- * that they will not be receiving any more callouts from XPC to their
+- * function registered via xpc_connect().
+- *
+- * Arguments:
+- *
+- * ch_number - channel # to unregister.
+- */
+-void
+-xpc_disconnect(int ch_number)
+-{
+- struct xpc_registration *registration;
+-
+-
+- DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
+-
+- registration = &xpc_registrations[ch_number];
+-
+- /*
+- * We've decided not to make this a down_interruptible(), since we
+- * figured XPC's users will just turn around and call xpc_disconnect()
+- * again anyways, so we might as well wait, if need be.
+- */
+- mutex_lock(®istration->mutex);
+-
+- /* if !XPC_CHANNEL_REGISTERED(ch_number) */
+- if (registration->func == NULL) {
+- mutex_unlock(®istration->mutex);
+- return;
+- }
+-
+- /* remove the connection registration for the specified channel */
+- registration->func = NULL;
+- registration->key = NULL;
+- registration->nentries = 0;
+- registration->msg_size = 0;
+- registration->assigned_limit = 0;
+- registration->idle_limit = 0;
+-
+- xpc_interface.disconnect(ch_number);
+-
+- mutex_unlock(®istration->mutex);
+-
+- return;
+-}
+-
+-
+-int __init
+-xp_init(void)
+-{
+- int ret, ch_number;
+- u64 func_addr = *(u64 *) xp_nofault_PIOR;
+- u64 err_func_addr = *(u64 *) xp_error_PIOR;
+-
+-
+- if (!ia64_platform_is("sn2")) {
+- return -ENODEV;
+- }
+-
+- /*
+- * Register a nofault code region which performs a cross-partition
+- * PIO read. If the PIO read times out, the MCA handler will consume
+- * the error and return to a kernel-provided instruction to indicate
+- * an error. This PIO read exists because it is guaranteed to timeout
+- * if the destination is down (AMO operations do not timeout on at
+- * least some CPUs on Shubs <= v1.2, which unfortunately we have to
+- * work around).
+- */
+- if ((ret = sn_register_nofault_code(func_addr, err_func_addr,
+- err_func_addr, 1, 1)) != 0) {
+- printk(KERN_ERR "XP: can't register nofault code, error=%d\n",
+- ret);
+- }
+- /*
+- * Setup the nofault PIO read target. (There is no special reason why
+- * SH_IPI_ACCESS was selected.)
+- */
+- if (is_shub2()) {
+- xp_nofault_PIOR_target = SH2_IPI_ACCESS0;
+- } else {
+- xp_nofault_PIOR_target = SH1_IPI_ACCESS;
+- }
+-
+- /* initialize the connection registration mutex */
+- for (ch_number = 0; ch_number < XPC_NCHANNELS; ch_number++) {
+- mutex_init(&xpc_registrations[ch_number].mutex);
+- }
+-
+- return 0;
+-}
+-module_init(xp_init);
+-
+-
+-void __exit
+-xp_exit(void)
+-{
+- u64 func_addr = *(u64 *) xp_nofault_PIOR;
+- u64 err_func_addr = *(u64 *) xp_error_PIOR;
+-
+-
+- /* unregister the PIO read nofault code region */
+- (void) sn_register_nofault_code(func_addr, err_func_addr,
+- err_func_addr, 1, 0);
+-}
+-module_exit(xp_exit);
+-
+-
+-MODULE_AUTHOR("Silicon Graphics, Inc.");
+-MODULE_DESCRIPTION("Cross Partition (XP) base");
+-MODULE_LICENSE("GPL");
+-
+-EXPORT_SYMBOL(xp_nofault_PIOR);
+-EXPORT_SYMBOL(xp_nofault_PIOR_target);
+-EXPORT_SYMBOL(xpc_registrations);
+-EXPORT_SYMBOL(xpc_interface);
+-EXPORT_SYMBOL(xpc_clear_interface);
+-EXPORT_SYMBOL(xpc_set_interface);
+-EXPORT_SYMBOL(xpc_connect);
+-EXPORT_SYMBOL(xpc_disconnect);
+-
+diff --git a/arch/ia64/sn/kernel/xp_nofault.S b/arch/ia64/sn/kernel/xp_nofault.S
+deleted file mode 100644
+index 98e7c7d..0000000
+--- a/arch/ia64/sn/kernel/xp_nofault.S
++++ /dev/null
+@@ -1,36 +0,0 @@
+-/*
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License. See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (c) 2004-2007 Silicon Graphics, Inc. All Rights Reserved.
+- */
+-
+-
+-/*
+- * The xp_nofault_PIOR function takes a pointer to a remote PIO register
+- * and attempts to load and consume a value from it. This function
+- * will be registered as a nofault code block. In the event that the
+- * PIO read fails, the MCA handler will force the error to look
+- * corrected and vector to the xp_error_PIOR which will return an error.
+- *
+- * The definition of "consumption" and the time it takes for an MCA
+- * to surface is processor implementation specific. This code
+- * is sufficient on Itanium through the Montvale processor family.
+- * It may need to be adjusted for future processor implementations.
+- *
+- * extern int xp_nofault_PIOR(void *remote_register);
+- */
+-
+- .global xp_nofault_PIOR
+-xp_nofault_PIOR:
+- mov r8=r0 // Stage a success return value
+- ld8.acq r9=[r32];; // PIO Read the specified register
+- adds r9=1,r9;; // Add to force consumption
+- srlz.i;; // Allow time for MCA to surface
+- br.ret.sptk.many b0;; // Return success
+-
+- .global xp_error_PIOR
+-xp_error_PIOR:
+- mov r8=1 // Return value of 1
+- br.ret.sptk.many b0;; // Return failure
+diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c
+deleted file mode 100644
+index 44ccc0d..0000000
+--- a/arch/ia64/sn/kernel/xpc_channel.c
++++ /dev/null
+@@ -1,2379 +0,0 @@
+-/*
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License. See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved.
+- */
+-
+-
+-/*
+- * Cross Partition Communication (XPC) channel support.
+- *
+- * This is the part of XPC that manages the channels and
+- * sends/receives messages across them to/from other partitions.
+- *
+- */
+-
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/cache.h>
+-#include <linux/interrupt.h>
+-#include <linux/mutex.h>
+-#include <linux/completion.h>
+-#include <asm/sn/bte.h>
+-#include <asm/sn/sn_sal.h>
+-#include <asm/sn/xpc.h>
+-
+-
+-/*
+- * Guarantee that the kzalloc'd memory is cacheline aligned.
+- */
+-static void *
+-xpc_kzalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
+-{
+- /* see if kzalloc will give us cachline aligned memory by default */
+- *base = kzalloc(size, flags);
+- if (*base == NULL) {
+- return NULL;
+- }
+- if ((u64) *base == L1_CACHE_ALIGN((u64) *base)) {
+- return *base;
+- }
+- kfree(*base);
+-
+- /* nope, we'll have to do it ourselves */
+- *base = kzalloc(size + L1_CACHE_BYTES, flags);
+- if (*base == NULL) {
+- return NULL;
+- }
+- return (void *) L1_CACHE_ALIGN((u64) *base);
+-}
+-
+-
+-/*
+- * Set up the initial values for the XPartition Communication channels.
+- */
+-static void
+-xpc_initialize_channels(struct xpc_partition *part, partid_t partid)
+-{
+- int ch_number;
+- struct xpc_channel *ch;
+-
+-
+- for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
+- ch = &part->channels[ch_number];
+-
+- ch->partid = partid;
+- ch->number = ch_number;
+- ch->flags = XPC_C_DISCONNECTED;
+-
+- ch->local_GP = &part->local_GPs[ch_number];
+- ch->local_openclose_args =
+- &part->local_openclose_args[ch_number];
+-
+- atomic_set(&ch->kthreads_assigned, 0);
+- atomic_set(&ch->kthreads_idle, 0);
+- atomic_set(&ch->kthreads_active, 0);
+-
+- atomic_set(&ch->references, 0);
+- atomic_set(&ch->n_to_notify, 0);
+-
+- spin_lock_init(&ch->lock);
+- mutex_init(&ch->msg_to_pull_mutex);
+- init_completion(&ch->wdisconnect_wait);
+-
+- atomic_set(&ch->n_on_msg_allocate_wq, 0);
+- init_waitqueue_head(&ch->msg_allocate_wq);
+- init_waitqueue_head(&ch->idle_wq);
+- }
+-}
+-
+-
+-/*
+- * Setup the infrastructure necessary to support XPartition Communication
+- * between the specified remote partition and the local one.
+- */
+-enum xpc_retval
+-xpc_setup_infrastructure(struct xpc_partition *part)
+-{
+- int ret, cpuid;
+- struct timer_list *timer;
+- partid_t partid = XPC_PARTID(part);
+-
+-
+- /*
+- * Zero out MOST of the entry for this partition. Only the fields
+- * starting with `nchannels' will be zeroed. The preceding fields must
+- * remain `viable' across partition ups and downs, since they may be
+- * referenced during this memset() operation.
+- */
+- memset(&part->nchannels, 0, sizeof(struct xpc_partition) -
+- offsetof(struct xpc_partition, nchannels));
+-
+- /*
+- * Allocate all of the channel structures as a contiguous chunk of
+- * memory.
+- */
+- part->channels = kzalloc(sizeof(struct xpc_channel) * XPC_NCHANNELS,
+- GFP_KERNEL);
+- if (part->channels == NULL) {
+- dev_err(xpc_chan, "can't get memory for channels\n");
+- return xpcNoMemory;
+- }
+-
+- part->nchannels = XPC_NCHANNELS;
+-
+-
+- /* allocate all the required GET/PUT values */
+-
+- part->local_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE,
+- GFP_KERNEL, &part->local_GPs_base);
+- if (part->local_GPs == NULL) {
+- kfree(part->channels);
+- part->channels = NULL;
+- dev_err(xpc_chan, "can't get memory for local get/put "
+- "values\n");
+- return xpcNoMemory;
+- }
+-
+- part->remote_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE,
+- GFP_KERNEL, &part->remote_GPs_base);
+- if (part->remote_GPs == NULL) {
+- dev_err(xpc_chan, "can't get memory for remote get/put "
+- "values\n");
+- kfree(part->local_GPs_base);
+- part->local_GPs = NULL;
+- kfree(part->channels);
+- part->channels = NULL;
+- return xpcNoMemory;
+- }
+-
+-
+- /* allocate all the required open and close args */
+-
+- part->local_openclose_args = xpc_kzalloc_cacheline_aligned(
+- XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL,
+- &part->local_openclose_args_base);
+- if (part->local_openclose_args == NULL) {
+- dev_err(xpc_chan, "can't get memory for local connect args\n");
+- kfree(part->remote_GPs_base);
+- part->remote_GPs = NULL;
+- kfree(part->local_GPs_base);
+- part->local_GPs = NULL;
+- kfree(part->channels);
+- part->channels = NULL;
+- return xpcNoMemory;
+- }
+-
+- part->remote_openclose_args = xpc_kzalloc_cacheline_aligned(
+- XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL,
+- &part->remote_openclose_args_base);
+- if (part->remote_openclose_args == NULL) {
+- dev_err(xpc_chan, "can't get memory for remote connect args\n");
+- kfree(part->local_openclose_args_base);
+- part->local_openclose_args = NULL;
+- kfree(part->remote_GPs_base);
+- part->remote_GPs = NULL;
+- kfree(part->local_GPs_base);
+- part->local_GPs = NULL;
+- kfree(part->channels);
+- part->channels = NULL;
+- return xpcNoMemory;
+- }
+-
+-
+- xpc_initialize_channels(part, partid);
+-
+- atomic_set(&part->nchannels_active, 0);
+- atomic_set(&part->nchannels_engaged, 0);
+-
+-
+- /* local_IPI_amo were set to 0 by an earlier memset() */
+-
+- /* Initialize this partitions AMO_t structure */
+- part->local_IPI_amo_va = xpc_IPI_init(partid);
+-
+- spin_lock_init(&part->IPI_lock);
+-
+- atomic_set(&part->channel_mgr_requests, 1);
+- init_waitqueue_head(&part->channel_mgr_wq);
+-
+- sprintf(part->IPI_owner, "xpc%02d", partid);
+- ret = request_irq(SGI_XPC_NOTIFY, xpc_notify_IRQ_handler, IRQF_SHARED,
+- part->IPI_owner, (void *) (u64) partid);
+- if (ret != 0) {
+- dev_err(xpc_chan, "can't register NOTIFY IRQ handler, "
+- "errno=%d\n", -ret);
+- kfree(part->remote_openclose_args_base);
+- part->remote_openclose_args = NULL;
+- kfree(part->local_openclose_args_base);
+- part->local_openclose_args = NULL;
+- kfree(part->remote_GPs_base);
+- part->remote_GPs = NULL;
+- kfree(part->local_GPs_base);
+- part->local_GPs = NULL;
+- kfree(part->channels);
+- part->channels = NULL;
+- return xpcLackOfResources;
+- }
+-
+- /* Setup a timer to check for dropped IPIs */
+- timer = &part->dropped_IPI_timer;
+- init_timer(timer);
+- timer->function = (void (*)(unsigned long)) xpc_dropped_IPI_check;
+- timer->data = (unsigned long) part;
+- timer->expires = jiffies + XPC_P_DROPPED_IPI_WAIT;
+- add_timer(timer);
+-
+- /*
+- * With the setting of the partition setup_state to XPC_P_SETUP, we're
+- * declaring that this partition is ready to go.
+- */
+- part->setup_state = XPC_P_SETUP;
+-
+-
+- /*
+- * Setup the per partition specific variables required by the
+- * remote partition to establish channel connections with us.
+- *
+- * The setting of the magic # indicates that these per partition
+- * specific variables are ready to be used.
+- */
+- xpc_vars_part[partid].GPs_pa = __pa(part->local_GPs);
+- xpc_vars_part[partid].openclose_args_pa =
+- __pa(part->local_openclose_args);
+- xpc_vars_part[partid].IPI_amo_pa = __pa(part->local_IPI_amo_va);
+- cpuid = raw_smp_processor_id(); /* any CPU in this partition will do */
+- xpc_vars_part[partid].IPI_nasid = cpuid_to_nasid(cpuid);
+- xpc_vars_part[partid].IPI_phys_cpuid = cpu_physical_id(cpuid);
+- xpc_vars_part[partid].nchannels = part->nchannels;
+- xpc_vars_part[partid].magic = XPC_VP_MAGIC1;
+-
+- return xpcSuccess;
+-}
+-
+-
+-/*
+- * Create a wrapper that hides the underlying mechanism for pulling a cacheline
+- * (or multiple cachelines) from a remote partition.
+- *
+- * src must be a cacheline aligned physical address on the remote partition.
+- * dst must be a cacheline aligned virtual address on this partition.
+- * cnt must be an cacheline sized
+- */
+-static enum xpc_retval
+-xpc_pull_remote_cachelines(struct xpc_partition *part, void *dst,
+- const void *src, size_t cnt)
+-{
+- bte_result_t bte_ret;
+-
+-
+- DBUG_ON((u64) src != L1_CACHE_ALIGN((u64) src));
+- DBUG_ON((u64) dst != L1_CACHE_ALIGN((u64) dst));
+- DBUG_ON(cnt != L1_CACHE_ALIGN(cnt));
+-
+- if (part->act_state == XPC_P_DEACTIVATING) {
+- return part->reason;
+- }
+-
+- bte_ret = xp_bte_copy((u64) src, (u64) dst, (u64) cnt,
+- (BTE_NORMAL | BTE_WACQUIRE), NULL);
+- if (bte_ret == BTE_SUCCESS) {
+- return xpcSuccess;
+- }
+-
+- dev_dbg(xpc_chan, "xp_bte_copy() from partition %d failed, ret=%d\n",
+- XPC_PARTID(part), bte_ret);
+-
+- return xpc_map_bte_errors(bte_ret);
+-}
+-
+-
+-/*
+- * Pull the remote per partition specific variables from the specified
+- * partition.
+- */
+-enum xpc_retval
+-xpc_pull_remote_vars_part(struct xpc_partition *part)
+-{
+- u8 buffer[L1_CACHE_BYTES * 2];
+- struct xpc_vars_part *pulled_entry_cacheline =
+- (struct xpc_vars_part *) L1_CACHE_ALIGN((u64) buffer);
+- struct xpc_vars_part *pulled_entry;
+- u64 remote_entry_cacheline_pa, remote_entry_pa;
+- partid_t partid = XPC_PARTID(part);
+- enum xpc_retval ret;
+-
+-
+- /* pull the cacheline that contains the variables we're interested in */
+-
+- DBUG_ON(part->remote_vars_part_pa !=
+- L1_CACHE_ALIGN(part->remote_vars_part_pa));
+- DBUG_ON(sizeof(struct xpc_vars_part) != L1_CACHE_BYTES / 2);
+-
+- remote_entry_pa = part->remote_vars_part_pa +
+- sn_partition_id * sizeof(struct xpc_vars_part);
+-
+- remote_entry_cacheline_pa = (remote_entry_pa & ~(L1_CACHE_BYTES - 1));
+-
+- pulled_entry = (struct xpc_vars_part *) ((u64) pulled_entry_cacheline +
+- (remote_entry_pa & (L1_CACHE_BYTES - 1)));
+-
+- ret = xpc_pull_remote_cachelines(part, pulled_entry_cacheline,
+- (void *) remote_entry_cacheline_pa,
+- L1_CACHE_BYTES);
+- if (ret != xpcSuccess) {
+- dev_dbg(xpc_chan, "failed to pull XPC vars_part from "
+- "partition %d, ret=%d\n", partid, ret);
+- return ret;
+- }
+-
+-
+- /* see if they've been set up yet */
+-
+- if (pulled_entry->magic != XPC_VP_MAGIC1 &&
+- pulled_entry->magic != XPC_VP_MAGIC2) {
+-
+- if (pulled_entry->magic != 0) {
+- dev_dbg(xpc_chan, "partition %d's XPC vars_part for "
+- "partition %d has bad magic value (=0x%lx)\n",
+- partid, sn_partition_id, pulled_entry->magic);
+- return xpcBadMagic;
+- }
+-
+- /* they've not been initialized yet */
+- return xpcRetry;
+- }
+-
+- if (xpc_vars_part[partid].magic == XPC_VP_MAGIC1) {
+-
+- /* validate the variables */
+-
+- if (pulled_entry->GPs_pa == 0 ||
+- pulled_entry->openclose_args_pa == 0 ||
+- pulled_entry->IPI_amo_pa == 0) {
+-
+- dev_err(xpc_chan, "partition %d's XPC vars_part for "
+- "partition %d are not valid\n", partid,
+- sn_partition_id);
+- return xpcInvalidAddress;
+- }
+-
+- /* the variables we imported look to be valid */
+-
+- part->remote_GPs_pa = pulled_entry->GPs_pa;
+- part->remote_openclose_args_pa =
+- pulled_entry->openclose_args_pa;
+- part->remote_IPI_amo_va =
+- (AMO_t *) __va(pulled_entry->IPI_amo_pa);
+- part->remote_IPI_nasid = pulled_entry->IPI_nasid;
+- part->remote_IPI_phys_cpuid = pulled_entry->IPI_phys_cpuid;
+-
+- if (part->nchannels > pulled_entry->nchannels) {
+- part->nchannels = pulled_entry->nchannels;
+- }
+-
+- /* let the other side know that we've pulled their variables */
+-
+- xpc_vars_part[partid].magic = XPC_VP_MAGIC2;
+- }
+-
+- if (pulled_entry->magic == XPC_VP_MAGIC1) {
+- return xpcRetry;
+- }
+-
+- return xpcSuccess;
+-}
+-
+-
+-/*
+- * Get the IPI flags and pull the openclose args and/or remote GPs as needed.
+- */
+-static u64
+-xpc_get_IPI_flags(struct xpc_partition *part)
+-{
+- unsigned long irq_flags;
+- u64 IPI_amo;
+- enum xpc_retval ret;
+-
+-
+- /*
+- * See if there are any IPI flags to be handled.
+- */
+-
+- spin_lock_irqsave(&part->IPI_lock, irq_flags);
+- if ((IPI_amo = part->local_IPI_amo) != 0) {
+- part->local_IPI_amo = 0;
+- }
+- spin_unlock_irqrestore(&part->IPI_lock, irq_flags);
+-
+-
+- if (XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(IPI_amo)) {
+- ret = xpc_pull_remote_cachelines(part,
+- part->remote_openclose_args,
+- (void *) part->remote_openclose_args_pa,
+- XPC_OPENCLOSE_ARGS_SIZE);
+- if (ret != xpcSuccess) {
+- XPC_DEACTIVATE_PARTITION(part, ret);
+-
+- dev_dbg(xpc_chan, "failed to pull openclose args from "
+- "partition %d, ret=%d\n", XPC_PARTID(part),
+- ret);
+-
+- /* don't bother processing IPIs anymore */
+- IPI_amo = 0;
+- }
+- }
+-
+- if (XPC_ANY_MSG_IPI_FLAGS_SET(IPI_amo)) {
+- ret = xpc_pull_remote_cachelines(part, part->remote_GPs,
+- (void *) part->remote_GPs_pa,
+- XPC_GP_SIZE);
+- if (ret != xpcSuccess) {
+- XPC_DEACTIVATE_PARTITION(part, ret);
+-
+- dev_dbg(xpc_chan, "failed to pull GPs from partition "
+- "%d, ret=%d\n", XPC_PARTID(part), ret);
+-
+- /* don't bother processing IPIs anymore */
+- IPI_amo = 0;
+- }
+- }
+-
+- return IPI_amo;
+-}
+-
+-
+-/*
+- * Allocate the local message queue and the notify queue.
+- */
+-static enum xpc_retval
+-xpc_allocate_local_msgqueue(struct xpc_channel *ch)
+-{
+- unsigned long irq_flags;
+- int nentries;
+- size_t nbytes;
+-
+-
+- // >>> may want to check for ch->flags & XPC_C_DISCONNECTING between
+- // >>> iterations of the for-loop, bail if set?
+-
+- // >>> should we impose a minimum #of entries? like 4 or 8?
+- for (nentries = ch->local_nentries; nentries > 0; nentries--) {
+-
+- nbytes = nentries * ch->msg_size;
+- ch->local_msgqueue = xpc_kzalloc_cacheline_aligned(nbytes,
+- GFP_KERNEL,
+- &ch->local_msgqueue_base);
+- if (ch->local_msgqueue == NULL) {
+- continue;
+- }
+-
+- nbytes = nentries * sizeof(struct xpc_notify);
+- ch->notify_queue = kzalloc(nbytes, GFP_KERNEL);
+- if (ch->notify_queue == NULL) {
+- kfree(ch->local_msgqueue_base);
+- ch->local_msgqueue = NULL;
+- continue;
+- }
+-
+- spin_lock_irqsave(&ch->lock, irq_flags);
+- if (nentries < ch->local_nentries) {
+- dev_dbg(xpc_chan, "nentries=%d local_nentries=%d, "
+- "partid=%d, channel=%d\n", nentries,
+- ch->local_nentries, ch->partid, ch->number);
+-
+- ch->local_nentries = nentries;
+- }
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+- return xpcSuccess;
+- }
+-
+- dev_dbg(xpc_chan, "can't get memory for local message queue and notify "
+- "queue, partid=%d, channel=%d\n", ch->partid, ch->number);
+- return xpcNoMemory;
+-}
+-
+-
+-/*
+- * Allocate the cached remote message queue.
+- */
+-static enum xpc_retval
+-xpc_allocate_remote_msgqueue(struct xpc_channel *ch)
+-{
+- unsigned long irq_flags;
+- int nentries;
+- size_t nbytes;
+-
+-
+- DBUG_ON(ch->remote_nentries <= 0);
+-
+- // >>> may want to check for ch->flags & XPC_C_DISCONNECTING between
+- // >>> iterations of the for-loop, bail if set?
+-
+- // >>> should we impose a minimum #of entries? like 4 or 8?
+- for (nentries = ch->remote_nentries; nentries > 0; nentries--) {
+-
+- nbytes = nentries * ch->msg_size;
+- ch->remote_msgqueue = xpc_kzalloc_cacheline_aligned(nbytes,
+- GFP_KERNEL,
+- &ch->remote_msgqueue_base);
+- if (ch->remote_msgqueue == NULL) {
+- continue;
+- }
+-
+- spin_lock_irqsave(&ch->lock, irq_flags);
+- if (nentries < ch->remote_nentries) {
+- dev_dbg(xpc_chan, "nentries=%d remote_nentries=%d, "
+- "partid=%d, channel=%d\n", nentries,
+- ch->remote_nentries, ch->partid, ch->number);
+-
+- ch->remote_nentries = nentries;
+- }
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+- return xpcSuccess;
+- }
+-
+- dev_dbg(xpc_chan, "can't get memory for cached remote message queue, "
+- "partid=%d, channel=%d\n", ch->partid, ch->number);
+- return xpcNoMemory;
+-}
+-
+-
+-/*
+- * Allocate message queues and other stuff associated with a channel.
+- *
+- * Note: Assumes all of the channel sizes are filled in.
+- */
+-static enum xpc_retval
+-xpc_allocate_msgqueues(struct xpc_channel *ch)
+-{
+- unsigned long irq_flags;
+- enum xpc_retval ret;
+-
+-
+- DBUG_ON(ch->flags & XPC_C_SETUP);
+-
+- if ((ret = xpc_allocate_local_msgqueue(ch)) != xpcSuccess) {
+- return ret;
+- }
+-
+- if ((ret = xpc_allocate_remote_msgqueue(ch)) != xpcSuccess) {
+- kfree(ch->local_msgqueue_base);
+- ch->local_msgqueue = NULL;
+- kfree(ch->notify_queue);
+- ch->notify_queue = NULL;
+- return ret;
+- }
+-
+- spin_lock_irqsave(&ch->lock, irq_flags);
+- ch->flags |= XPC_C_SETUP;
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+-
+- return xpcSuccess;
+-}
+-
+-
+-/*
+- * Process a connect message from a remote partition.
+- *
+- * Note: xpc_process_connect() is expecting to be called with the
+- * spin_lock_irqsave held and will leave it locked upon return.
+- */
+-static void
+-xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags)
+-{
+- enum xpc_retval ret;
+-
+-
+- DBUG_ON(!spin_is_locked(&ch->lock));
+-
+- if (!(ch->flags & XPC_C_OPENREQUEST) ||
+- !(ch->flags & XPC_C_ROPENREQUEST)) {
+- /* nothing more to do for now */
+- return;
+- }
+- DBUG_ON(!(ch->flags & XPC_C_CONNECTING));
+-
+- if (!(ch->flags & XPC_C_SETUP)) {
+- spin_unlock_irqrestore(&ch->lock, *irq_flags);
+- ret = xpc_allocate_msgqueues(ch);
+- spin_lock_irqsave(&ch->lock, *irq_flags);
+-
+- if (ret != xpcSuccess) {
+- XPC_DISCONNECT_CHANNEL(ch, ret, irq_flags);
+- }
+- if (ch->flags & (XPC_C_CONNECTED | XPC_C_DISCONNECTING)) {
+- return;
+- }
+-
+- DBUG_ON(!(ch->flags & XPC_C_SETUP));
+- DBUG_ON(ch->local_msgqueue == NULL);
+- DBUG_ON(ch->remote_msgqueue == NULL);
+- }
+-
+- if (!(ch->flags & XPC_C_OPENREPLY)) {
+- ch->flags |= XPC_C_OPENREPLY;
+- xpc_IPI_send_openreply(ch, irq_flags);
+- }
+-
+- if (!(ch->flags & XPC_C_ROPENREPLY)) {
+- return;
+- }
+-
+- DBUG_ON(ch->remote_msgqueue_pa == 0);
+-
+- ch->flags = (XPC_C_CONNECTED | XPC_C_SETUP); /* clear all else */
+-
+- dev_info(xpc_chan, "channel %d to partition %d connected\n",
+- ch->number, ch->partid);
+-
+- spin_unlock_irqrestore(&ch->lock, *irq_flags);
+- xpc_create_kthreads(ch, 1, 0);
+- spin_lock_irqsave(&ch->lock, *irq_flags);
+-}
+-
+-
+-/*
+- * Notify those who wanted to be notified upon delivery of their message.
+- */
+-static void
+-xpc_notify_senders(struct xpc_channel *ch, enum xpc_retval reason, s64 put)
+-{
+- struct xpc_notify *notify;
+- u8 notify_type;
+- s64 get = ch->w_remote_GP.get - 1;
+-
+-
+- while (++get < put && atomic_read(&ch->n_to_notify) > 0) {
+-
+- notify = &ch->notify_queue[get % ch->local_nentries];
+-
+- /*
+- * See if the notify entry indicates it was associated with
+- * a message who's sender wants to be notified. It is possible
+- * that it is, but someone else is doing or has done the
+- * notification.
+- */
+- notify_type = notify->type;
+- if (notify_type == 0 ||
+- cmpxchg(¬ify->type, notify_type, 0) !=
+- notify_type) {
+- continue;
+- }
+-
+- DBUG_ON(notify_type != XPC_N_CALL);
+-
+- atomic_dec(&ch->n_to_notify);
+-
+- if (notify->func != NULL) {
+- dev_dbg(xpc_chan, "notify->func() called, notify=0x%p, "
+- "msg_number=%ld, partid=%d, channel=%d\n",
+- (void *) notify, get, ch->partid, ch->number);
+-
+- notify->func(reason, ch->partid, ch->number,
+- notify->key);
+-
+- dev_dbg(xpc_chan, "notify->func() returned, "
+- "notify=0x%p, msg_number=%ld, partid=%d, "
+- "channel=%d\n", (void *) notify, get,
+- ch->partid, ch->number);
+- }
+- }
+-}
+-
+-
+-/*
+- * Free up message queues and other stuff that were allocated for the specified
+- * channel.
+- *
+- * Note: ch->reason and ch->reason_line are left set for debugging purposes,
+- * they're cleared when XPC_C_DISCONNECTED is cleared.
+- */
+-static void
+-xpc_free_msgqueues(struct xpc_channel *ch)
+-{
+- DBUG_ON(!spin_is_locked(&ch->lock));
+- DBUG_ON(atomic_read(&ch->n_to_notify) != 0);
+-
+- ch->remote_msgqueue_pa = 0;
+- ch->func = NULL;
+- ch->key = NULL;
+- ch->msg_size = 0;
+- ch->local_nentries = 0;
+- ch->remote_nentries = 0;
+- ch->kthreads_assigned_limit = 0;
+- ch->kthreads_idle_limit = 0;
+-
+- ch->local_GP->get = 0;
+- ch->local_GP->put = 0;
+- ch->remote_GP.get = 0;
+- ch->remote_GP.put = 0;
+- ch->w_local_GP.get = 0;
+- ch->w_local_GP.put = 0;
+- ch->w_remote_GP.get = 0;
+- ch->w_remote_GP.put = 0;
+- ch->next_msg_to_pull = 0;
+-
+- if (ch->flags & XPC_C_SETUP) {
+- ch->flags &= ~XPC_C_SETUP;
+-
+- dev_dbg(xpc_chan, "ch->flags=0x%x, partid=%d, channel=%d\n",
+- ch->flags, ch->partid, ch->number);
+-
+- kfree(ch->local_msgqueue_base);
+- ch->local_msgqueue = NULL;
+- kfree(ch->remote_msgqueue_base);
+- ch->remote_msgqueue = NULL;
+- kfree(ch->notify_queue);
+- ch->notify_queue = NULL;
+- }
+-}
+-
+-
+-/*
+- * spin_lock_irqsave() is expected to be held on entry.
+- */
+-static void
+-xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
+-{
+- struct xpc_partition *part = &xpc_partitions[ch->partid];
+- u32 channel_was_connected = (ch->flags & XPC_C_WASCONNECTED);
+-
+-
+- DBUG_ON(!spin_is_locked(&ch->lock));
+-
+- if (!(ch->flags & XPC_C_DISCONNECTING)) {
+- return;
+- }
+-
+- DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
+-
+- /* make sure all activity has settled down first */
+-
+- if (atomic_read(&ch->kthreads_assigned) > 0 ||
+- atomic_read(&ch->references) > 0) {
+- return;
+- }
+- DBUG_ON((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
+- !(ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE));
+-
+- if (part->act_state == XPC_P_DEACTIVATING) {
+- /* can't proceed until the other side disengages from us */
+- if (xpc_partition_engaged(1UL << ch->partid)) {
+- return;
+- }
+-
+- } else {
+-
+- /* as long as the other side is up do the full protocol */
+-
+- if (!(ch->flags & XPC_C_RCLOSEREQUEST)) {
+- return;
+- }
+-
+- if (!(ch->flags & XPC_C_CLOSEREPLY)) {
+- ch->flags |= XPC_C_CLOSEREPLY;
+- xpc_IPI_send_closereply(ch, irq_flags);
+- }
+-
+- if (!(ch->flags & XPC_C_RCLOSEREPLY)) {
+- return;
+- }
+- }
+-
+- /* wake those waiting for notify completion */
+- if (atomic_read(&ch->n_to_notify) > 0) {
+- /* >>> we do callout while holding ch->lock */
+- xpc_notify_senders(ch, ch->reason, ch->w_local_GP.put);
+- }
+-
+- /* both sides are disconnected now */
+-
+- if (ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE) {
+- spin_unlock_irqrestore(&ch->lock, *irq_flags);
+- xpc_disconnect_callout(ch, xpcDisconnected);
+- spin_lock_irqsave(&ch->lock, *irq_flags);
+- }
+-
+- /* it's now safe to free the channel's message queues */
+- xpc_free_msgqueues(ch);
+-
+- /* mark disconnected, clear all other flags except XPC_C_WDISCONNECT */
+- ch->flags = (XPC_C_DISCONNECTED | (ch->flags & XPC_C_WDISCONNECT));
+-
+- atomic_dec(&part->nchannels_active);
+-
+- if (channel_was_connected) {
+- dev_info(xpc_chan, "channel %d to partition %d disconnected, "
+- "reason=%d\n", ch->number, ch->partid, ch->reason);
+- }
+-
+- if (ch->flags & XPC_C_WDISCONNECT) {
+- /* we won't lose the CPU since we're holding ch->lock */
+- complete(&ch->wdisconnect_wait);
+- } else if (ch->delayed_IPI_flags) {
+- if (part->act_state != XPC_P_DEACTIVATING) {
+- /* time to take action on any delayed IPI flags */
+- spin_lock(&part->IPI_lock);
+- XPC_SET_IPI_FLAGS(part->local_IPI_amo, ch->number,
+- ch->delayed_IPI_flags);
+- spin_unlock(&part->IPI_lock);
+- }
+- ch->delayed_IPI_flags = 0;
+- }
+-}
+-
+-
+-/*
+- * Process a change in the channel's remote connection state.
+- */
+-static void
+-xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
+- u8 IPI_flags)
+-{
+- unsigned long irq_flags;
+- struct xpc_openclose_args *args =
+- &part->remote_openclose_args[ch_number];
+- struct xpc_channel *ch = &part->channels[ch_number];
+- enum xpc_retval reason;
+-
+-
+-
+- spin_lock_irqsave(&ch->lock, irq_flags);
+-
+-again:
+-
+- if ((ch->flags & XPC_C_DISCONNECTED) &&
+- (ch->flags & XPC_C_WDISCONNECT)) {
+- /*
+- * Delay processing IPI flags until thread waiting disconnect
+- * has had a chance to see that the channel is disconnected.
+- */
+- ch->delayed_IPI_flags |= IPI_flags;
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+- return;
+- }
+-
+-
+- if (IPI_flags & XPC_IPI_CLOSEREQUEST) {
+-
+- dev_dbg(xpc_chan, "XPC_IPI_CLOSEREQUEST (reason=%d) received "
+- "from partid=%d, channel=%d\n", args->reason,
+- ch->partid, ch->number);
+-
+- /*
+- * If RCLOSEREQUEST is set, we're probably waiting for
+- * RCLOSEREPLY. We should find it and a ROPENREQUEST packed
+- * with this RCLOSEREQUEST in the IPI_flags.
+- */
+-
+- if (ch->flags & XPC_C_RCLOSEREQUEST) {
+- DBUG_ON(!(ch->flags & XPC_C_DISCONNECTING));
+- DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
+- DBUG_ON(!(ch->flags & XPC_C_CLOSEREPLY));
+- DBUG_ON(ch->flags & XPC_C_RCLOSEREPLY);
+-
+- DBUG_ON(!(IPI_flags & XPC_IPI_CLOSEREPLY));
+- IPI_flags &= ~XPC_IPI_CLOSEREPLY;
+- ch->flags |= XPC_C_RCLOSEREPLY;
+-
+- /* both sides have finished disconnecting */
+- xpc_process_disconnect(ch, &irq_flags);
+- DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED));
+- goto again;
+- }
+-
+- if (ch->flags & XPC_C_DISCONNECTED) {
+- if (!(IPI_flags & XPC_IPI_OPENREQUEST)) {
+- if ((XPC_GET_IPI_FLAGS(part->local_IPI_amo,
+- ch_number) & XPC_IPI_OPENREQUEST)) {
+-
+- DBUG_ON(ch->delayed_IPI_flags != 0);
+- spin_lock(&part->IPI_lock);
+- XPC_SET_IPI_FLAGS(part->local_IPI_amo,
+- ch_number,
+- XPC_IPI_CLOSEREQUEST);
+- spin_unlock(&part->IPI_lock);
+- }
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+- return;
+- }
+-
+- XPC_SET_REASON(ch, 0, 0);
+- ch->flags &= ~XPC_C_DISCONNECTED;
+-
+- atomic_inc(&part->nchannels_active);
+- ch->flags |= (XPC_C_CONNECTING | XPC_C_ROPENREQUEST);
+- }
+-
+- IPI_flags &= ~(XPC_IPI_OPENREQUEST | XPC_IPI_OPENREPLY);
+-
+- /*
+- * The meaningful CLOSEREQUEST connection state fields are:
+- * reason = reason connection is to be closed
+- */
+-
+- ch->flags |= XPC_C_RCLOSEREQUEST;
+-
+- if (!(ch->flags & XPC_C_DISCONNECTING)) {
+- reason = args->reason;
+- if (reason <= xpcSuccess || reason > xpcUnknownReason) {
+- reason = xpcUnknownReason;
+- } else if (reason == xpcUnregistering) {
+- reason = xpcOtherUnregistering;
+- }
+-
+- XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags);
+-
+- DBUG_ON(IPI_flags & XPC_IPI_CLOSEREPLY);
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+- return;
+- }
+-
+- xpc_process_disconnect(ch, &irq_flags);
+- }
+-
+-
+- if (IPI_flags & XPC_IPI_CLOSEREPLY) {
+-
+- dev_dbg(xpc_chan, "XPC_IPI_CLOSEREPLY received from partid=%d,"
+- " channel=%d\n", ch->partid, ch->number);
+-
+- if (ch->flags & XPC_C_DISCONNECTED) {
+- DBUG_ON(part->act_state != XPC_P_DEACTIVATING);
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+- return;
+- }
+-
+- DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
+-
+- if (!(ch->flags & XPC_C_RCLOSEREQUEST)) {
+- if ((XPC_GET_IPI_FLAGS(part->local_IPI_amo, ch_number)
+- & XPC_IPI_CLOSEREQUEST)) {
+-
+- DBUG_ON(ch->delayed_IPI_flags != 0);
+- spin_lock(&part->IPI_lock);
+- XPC_SET_IPI_FLAGS(part->local_IPI_amo,
+- ch_number, XPC_IPI_CLOSEREPLY);
+- spin_unlock(&part->IPI_lock);
+- }
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+- return;
+- }
+-
+- ch->flags |= XPC_C_RCLOSEREPLY;
+-
+- if (ch->flags & XPC_C_CLOSEREPLY) {
+- /* both sides have finished disconnecting */
+- xpc_process_disconnect(ch, &irq_flags);
+- }
+- }
+-
+-
+- if (IPI_flags & XPC_IPI_OPENREQUEST) {
+-
+- dev_dbg(xpc_chan, "XPC_IPI_OPENREQUEST (msg_size=%d, "
+- "local_nentries=%d) received from partid=%d, "
+- "channel=%d\n", args->msg_size, args->local_nentries,
+- ch->partid, ch->number);
+-
+- if (part->act_state == XPC_P_DEACTIVATING ||
+- (ch->flags & XPC_C_ROPENREQUEST)) {
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+- return;
+- }
+-
+- if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_WDISCONNECT)) {
+- ch->delayed_IPI_flags |= XPC_IPI_OPENREQUEST;
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+- return;
+- }
+- DBUG_ON(!(ch->flags & (XPC_C_DISCONNECTED |
+- XPC_C_OPENREQUEST)));
+- DBUG_ON(ch->flags & (XPC_C_ROPENREQUEST | XPC_C_ROPENREPLY |
+- XPC_C_OPENREPLY | XPC_C_CONNECTED));
+-
+- /*
+- * The meaningful OPENREQUEST connection state fields are:
+- * msg_size = size of channel's messages in bytes
+- * local_nentries = remote partition's local_nentries
+- */
+- if (args->msg_size == 0 || args->local_nentries == 0) {
+- /* assume OPENREQUEST was delayed by mistake */
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+- return;
+- }
+-
+- ch->flags |= (XPC_C_ROPENREQUEST | XPC_C_CONNECTING);
+- ch->remote_nentries = args->local_nentries;
+-
+-
+- if (ch->flags & XPC_C_OPENREQUEST) {
+- if (args->msg_size != ch->msg_size) {
+- XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes,
+- &irq_flags);
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+- return;
+- }
+- } else {
+- ch->msg_size = args->msg_size;
+-
+- XPC_SET_REASON(ch, 0, 0);
+- ch->flags &= ~XPC_C_DISCONNECTED;
+-
+- atomic_inc(&part->nchannels_active);
+- }
+-
+- xpc_process_connect(ch, &irq_flags);
+- }
+-
+-
+- if (IPI_flags & XPC_IPI_OPENREPLY) {
+-
+- dev_dbg(xpc_chan, "XPC_IPI_OPENREPLY (local_msgqueue_pa=0x%lx, "
+- "local_nentries=%d, remote_nentries=%d) received from "
+- "partid=%d, channel=%d\n", args->local_msgqueue_pa,
+- args->local_nentries, args->remote_nentries,
+- ch->partid, ch->number);
+-
+- if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED)) {
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+- return;
+- }
+- if (!(ch->flags & XPC_C_OPENREQUEST)) {
+- XPC_DISCONNECT_CHANNEL(ch, xpcOpenCloseError,
+- &irq_flags);
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+- return;
+- }
+-
+- DBUG_ON(!(ch->flags & XPC_C_ROPENREQUEST));
+- DBUG_ON(ch->flags & XPC_C_CONNECTED);
+-
+- /*
+- * The meaningful OPENREPLY connection state fields are:
+- * local_msgqueue_pa = physical address of remote
+- * partition's local_msgqueue
+- * local_nentries = remote partition's local_nentries
+- * remote_nentries = remote partition's remote_nentries
+- */
+- DBUG_ON(args->local_msgqueue_pa == 0);
+- DBUG_ON(args->local_nentries == 0);
+- DBUG_ON(args->remote_nentries == 0);
+-
+- ch->flags |= XPC_C_ROPENREPLY;
+- ch->remote_msgqueue_pa = args->local_msgqueue_pa;
+-
+- if (args->local_nentries < ch->remote_nentries) {
+- dev_dbg(xpc_chan, "XPC_IPI_OPENREPLY: new "
+- "remote_nentries=%d, old remote_nentries=%d, "
+- "partid=%d, channel=%d\n",
+- args->local_nentries, ch->remote_nentries,
+- ch->partid, ch->number);
+-
+- ch->remote_nentries = args->local_nentries;
+- }
+- if (args->remote_nentries < ch->local_nentries) {
+- dev_dbg(xpc_chan, "XPC_IPI_OPENREPLY: new "
+- "local_nentries=%d, old local_nentries=%d, "
+- "partid=%d, channel=%d\n",
+- args->remote_nentries, ch->local_nentries,
+- ch->partid, ch->number);
+-
+- ch->local_nentries = args->remote_nentries;
+- }
+-
+- xpc_process_connect(ch, &irq_flags);
+- }
+-
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+-}
+-
+-
+-/*
+- * Attempt to establish a channel connection to a remote partition.
+- */
+-static enum xpc_retval
+-xpc_connect_channel(struct xpc_channel *ch)
+-{
+- unsigned long irq_flags;
+- struct xpc_registration *registration = &xpc_registrations[ch->number];
+-
+-
+- if (mutex_trylock(®istration->mutex) == 0) {
+- return xpcRetry;
+- }
+-
+- if (!XPC_CHANNEL_REGISTERED(ch->number)) {
+- mutex_unlock(®istration->mutex);
+- return xpcUnregistered;
+- }
+-
+- spin_lock_irqsave(&ch->lock, irq_flags);
+-
+- DBUG_ON(ch->flags & XPC_C_CONNECTED);
+- DBUG_ON(ch->flags & XPC_C_OPENREQUEST);
+-
+- if (ch->flags & XPC_C_DISCONNECTING) {
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+- mutex_unlock(®istration->mutex);
+- return ch->reason;
+- }
+-
+-
+- /* add info from the channel connect registration to the channel */
+-
+- ch->kthreads_assigned_limit = registration->assigned_limit;
+- ch->kthreads_idle_limit = registration->idle_limit;
+- DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0);
+- DBUG_ON(atomic_read(&ch->kthreads_idle) != 0);
+- DBUG_ON(atomic_read(&ch->kthreads_active) != 0);
+-
+- ch->func = registration->func;
+- DBUG_ON(registration->func == NULL);
+- ch->key = registration->key;
+-
+- ch->local_nentries = registration->nentries;
+-
+- if (ch->flags & XPC_C_ROPENREQUEST) {
+- if (registration->msg_size != ch->msg_size) {
+- /* the local and remote sides aren't the same */
+-
+- /*
+- * Because XPC_DISCONNECT_CHANNEL() can block we're
+- * forced to up the registration sema before we unlock
+- * the channel lock. But that's okay here because we're
+- * done with the part that required the registration
+- * sema. XPC_DISCONNECT_CHANNEL() requires that the
+- * channel lock be locked and will unlock and relock
+- * the channel lock as needed.
+- */
+- mutex_unlock(®istration->mutex);
+- XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes,
+- &irq_flags);
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+- return xpcUnequalMsgSizes;
+- }
+- } else {
+- ch->msg_size = registration->msg_size;
+-
+- XPC_SET_REASON(ch, 0, 0);
+- ch->flags &= ~XPC_C_DISCONNECTED;
+-
+- atomic_inc(&xpc_partitions[ch->partid].nchannels_active);
+- }
+-
+- mutex_unlock(®istration->mutex);
+-
+-
+- /* initiate the connection */
+-
+- ch->flags |= (XPC_C_OPENREQUEST | XPC_C_CONNECTING);
+- xpc_IPI_send_openrequest(ch, &irq_flags);
+-
+- xpc_process_connect(ch, &irq_flags);
+-
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+-
+- return xpcSuccess;
+-}
+-
+-
+-/*
+- * Clear some of the msg flags in the local message queue.
+- */
+-static inline void
+-xpc_clear_local_msgqueue_flags(struct xpc_channel *ch)
+-{
+- struct xpc_msg *msg;
+- s64 get;
+-
+-
+- get = ch->w_remote_GP.get;
+- do {
+- msg = (struct xpc_msg *) ((u64) ch->local_msgqueue +
+- (get % ch->local_nentries) * ch->msg_size);
+- msg->flags = 0;
+- } while (++get < (volatile s64) ch->remote_GP.get);
+-}
+-
+-
+-/*
+- * Clear some of the msg flags in the remote message queue.
+- */
+-static inline void
+-xpc_clear_remote_msgqueue_flags(struct xpc_channel *ch)
+-{
+- struct xpc_msg *msg;
+- s64 put;
+-
+-
+- put = ch->w_remote_GP.put;
+- do {
+- msg = (struct xpc_msg *) ((u64) ch->remote_msgqueue +
+- (put % ch->remote_nentries) * ch->msg_size);
+- msg->flags = 0;
+- } while (++put < (volatile s64) ch->remote_GP.put);
+-}
+-
+-
+-static void
+-xpc_process_msg_IPI(struct xpc_partition *part, int ch_number)
+-{
+- struct xpc_channel *ch = &part->channels[ch_number];
+- int nmsgs_sent;
+-
+-
+- ch->remote_GP = part->remote_GPs[ch_number];
+-
+-
+- /* See what, if anything, has changed for each connected channel */
+-
+- xpc_msgqueue_ref(ch);
+-
+- if (ch->w_remote_GP.get == ch->remote_GP.get &&
+- ch->w_remote_GP.put == ch->remote_GP.put) {
+- /* nothing changed since GPs were last pulled */
+- xpc_msgqueue_deref(ch);
+- return;
+- }
+-
+- if (!(ch->flags & XPC_C_CONNECTED)){
+- xpc_msgqueue_deref(ch);
+- return;
+- }
+-
+-
+- /*
+- * First check to see if messages recently sent by us have been
+- * received by the other side. (The remote GET value will have
+- * changed since we last looked at it.)
+- */
+-
+- if (ch->w_remote_GP.get != ch->remote_GP.get) {
+-
+- /*
+- * We need to notify any senders that want to be notified
+- * that their sent messages have been received by their
+- * intended recipients. We need to do this before updating
+- * w_remote_GP.get so that we don't allocate the same message
+- * queue entries prematurely (see xpc_allocate_msg()).
+- */
+- if (atomic_read(&ch->n_to_notify) > 0) {
+- /*
+- * Notify senders that messages sent have been
+- * received and delivered by the other side.
+- */
+- xpc_notify_senders(ch, xpcMsgDelivered,
+- ch->remote_GP.get);
+- }
+-
+- /*
+- * Clear msg->flags in previously sent messages, so that
+- * they're ready for xpc_allocate_msg().
+- */
+- xpc_clear_local_msgqueue_flags(ch);
+-
+- ch->w_remote_GP.get = ch->remote_GP.get;
+-
+- dev_dbg(xpc_chan, "w_remote_GP.get changed to %ld, partid=%d, "
+- "channel=%d\n", ch->w_remote_GP.get, ch->partid,
+- ch->number);
+-
+- /*
+- * If anyone was waiting for message queue entries to become
+- * available, wake them up.
+- */
+- if (atomic_read(&ch->n_on_msg_allocate_wq) > 0) {
+- wake_up(&ch->msg_allocate_wq);
+- }
+- }
+-
+-
+- /*
+- * Now check for newly sent messages by the other side. (The remote
+- * PUT value will have changed since we last looked at it.)
+- */
+-
+- if (ch->w_remote_GP.put != ch->remote_GP.put) {
+- /*
+- * Clear msg->flags in previously received messages, so that
+- * they're ready for xpc_get_deliverable_msg().
+- */
+- xpc_clear_remote_msgqueue_flags(ch);
+-
+- ch->w_remote_GP.put = ch->remote_GP.put;
+-
+- dev_dbg(xpc_chan, "w_remote_GP.put changed to %ld, partid=%d, "
+- "channel=%d\n", ch->w_remote_GP.put, ch->partid,
+- ch->number);
+-
+- nmsgs_sent = ch->w_remote_GP.put - ch->w_local_GP.get;
+- if (nmsgs_sent > 0) {
+- dev_dbg(xpc_chan, "msgs waiting to be copied and "
+- "delivered=%d, partid=%d, channel=%d\n",
+- nmsgs_sent, ch->partid, ch->number);
+-
+- if (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) {
+- xpc_activate_kthreads(ch, nmsgs_sent);
+- }
+- }
+- }
+-
+- xpc_msgqueue_deref(ch);
+-}
+-
+-
+-void
+-xpc_process_channel_activity(struct xpc_partition *part)
+-{
+- unsigned long irq_flags;
+- u64 IPI_amo, IPI_flags;
+- struct xpc_channel *ch;
+- int ch_number;
+- u32 ch_flags;
+-
+-
+- IPI_amo = xpc_get_IPI_flags(part);
+-
+- /*
+- * Initiate channel connections for registered channels.
+- *
+- * For each connected channel that has pending messages activate idle
+- * kthreads and/or create new kthreads as needed.
+- */
+-
+- for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
+- ch = &part->channels[ch_number];
+-
+-
+- /*
+- * Process any open or close related IPI flags, and then deal
+- * with connecting or disconnecting the channel as required.
+- */
+-
+- IPI_flags = XPC_GET_IPI_FLAGS(IPI_amo, ch_number);
+-
+- if (XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(IPI_flags)) {
+- xpc_process_openclose_IPI(part, ch_number, IPI_flags);
+- }
+-
+- ch_flags = ch->flags; /* need an atomic snapshot of flags */
+-
+- if (ch_flags & XPC_C_DISCONNECTING) {
+- spin_lock_irqsave(&ch->lock, irq_flags);
+- xpc_process_disconnect(ch, &irq_flags);
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+- continue;
+- }
+-
+- if (part->act_state == XPC_P_DEACTIVATING) {
+- continue;
+- }
+-
+- if (!(ch_flags & XPC_C_CONNECTED)) {
+- if (!(ch_flags & XPC_C_OPENREQUEST)) {
+- DBUG_ON(ch_flags & XPC_C_SETUP);
+- (void) xpc_connect_channel(ch);
+- } else {
+- spin_lock_irqsave(&ch->lock, irq_flags);
+- xpc_process_connect(ch, &irq_flags);
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+- }
+- continue;
+- }
+-
+-
+- /*
+- * Process any message related IPI flags, this may involve the
+- * activation of kthreads to deliver any pending messages sent
+- * from the other partition.
+- */
+-
+- if (XPC_ANY_MSG_IPI_FLAGS_SET(IPI_flags)) {
+- xpc_process_msg_IPI(part, ch_number);
+- }
+- }
+-}
+-
+-
+-/*
+- * XPC's heartbeat code calls this function to inform XPC that a partition is
+- * going down. XPC responds by tearing down the XPartition Communication
+- * infrastructure used for the just downed partition.
+- *
+- * XPC's heartbeat code will never call this function and xpc_partition_up()
+- * at the same time. Nor will it ever make multiple calls to either function
+- * at the same time.
+- */
+-void
+-xpc_partition_going_down(struct xpc_partition *part, enum xpc_retval reason)
+-{
+- unsigned long irq_flags;
+- int ch_number;
+- struct xpc_channel *ch;
+-
+-
+- dev_dbg(xpc_chan, "deactivating partition %d, reason=%d\n",
+- XPC_PARTID(part), reason);
+-
+- if (!xpc_part_ref(part)) {
+- /* infrastructure for this partition isn't currently set up */
+- return;
+- }
+-
+-
+- /* disconnect channels associated with the partition going down */
+-
+- for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
+- ch = &part->channels[ch_number];
+-
+- xpc_msgqueue_ref(ch);
+- spin_lock_irqsave(&ch->lock, irq_flags);
+-
+- XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags);
+-
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+- xpc_msgqueue_deref(ch);
+- }
+-
+- xpc_wakeup_channel_mgr(part);
+-
+- xpc_part_deref(part);
+-}
+-
+-
+-/*
+- * Teardown the infrastructure necessary to support XPartition Communication
+- * between the specified remote partition and the local one.
+- */
+-void
+-xpc_teardown_infrastructure(struct xpc_partition *part)
+-{
+- partid_t partid = XPC_PARTID(part);
+-
+-
+- /*
+- * We start off by making this partition inaccessible to local
+- * processes by marking it as no longer setup. Then we make it
+- * inaccessible to remote processes by clearing the XPC per partition
+- * specific variable's magic # (which indicates that these variables
+- * are no longer valid) and by ignoring all XPC notify IPIs sent to
+- * this partition.
+- */
+-
+- DBUG_ON(atomic_read(&part->nchannels_engaged) != 0);
+- DBUG_ON(atomic_read(&part->nchannels_active) != 0);
+- DBUG_ON(part->setup_state != XPC_P_SETUP);
+- part->setup_state = XPC_P_WTEARDOWN;
+-
+- xpc_vars_part[partid].magic = 0;
+-
+-
+- free_irq(SGI_XPC_NOTIFY, (void *) (u64) partid);
+-
+-
+- /*
+- * Before proceeding with the teardown we have to wait until all
+- * existing references cease.
+- */
+- wait_event(part->teardown_wq, (atomic_read(&part->references) == 0));
+-
+-
+- /* now we can begin tearing down the infrastructure */
+-
+- part->setup_state = XPC_P_TORNDOWN;
+-
+- /* in case we've still got outstanding timers registered... */
+- del_timer_sync(&part->dropped_IPI_timer);
+-
+- kfree(part->remote_openclose_args_base);
+- part->remote_openclose_args = NULL;
+- kfree(part->local_openclose_args_base);
+- part->local_openclose_args = NULL;
+- kfree(part->remote_GPs_base);
+- part->remote_GPs = NULL;
+- kfree(part->local_GPs_base);
+- part->local_GPs = NULL;
+- kfree(part->channels);
+- part->channels = NULL;
+- part->local_IPI_amo_va = NULL;
+-}
+-
+-
+-/*
+- * Called by XP at the time of channel connection registration to cause
+- * XPC to establish connections to all currently active partitions.
+- */
+-void
+-xpc_initiate_connect(int ch_number)
+-{
+- partid_t partid;
+- struct xpc_partition *part;
+- struct xpc_channel *ch;
+-
+-
+- DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
+-
+- for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+- part = &xpc_partitions[partid];
+-
+- if (xpc_part_ref(part)) {
+- ch = &part->channels[ch_number];
+-
+- /*
+- * Initiate the establishment of a connection on the
+- * newly registered channel to the remote partition.
+- */
+- xpc_wakeup_channel_mgr(part);
+- xpc_part_deref(part);
+- }
+- }
+-}
+-
+-
+-void
+-xpc_connected_callout(struct xpc_channel *ch)
+-{
+- /* let the registerer know that a connection has been established */
+-
+- if (ch->func != NULL) {
+- dev_dbg(xpc_chan, "ch->func() called, reason=xpcConnected, "
+- "partid=%d, channel=%d\n", ch->partid, ch->number);
+-
+- ch->func(xpcConnected, ch->partid, ch->number,
+- (void *) (u64) ch->local_nentries, ch->key);
+-
+- dev_dbg(xpc_chan, "ch->func() returned, reason=xpcConnected, "
+- "partid=%d, channel=%d\n", ch->partid, ch->number);
+- }
+-}
+-
+-
+-/*
+- * Called by XP at the time of channel connection unregistration to cause
+- * XPC to teardown all current connections for the specified channel.
+- *
+- * Before returning xpc_initiate_disconnect() will wait until all connections
+- * on the specified channel have been closed/torndown. So the caller can be
+- * assured that they will not be receiving any more callouts from XPC to the
+- * function they registered via xpc_connect().
+- *
+- * Arguments:
+- *
+- * ch_number - channel # to unregister.
+- */
+-void
+-xpc_initiate_disconnect(int ch_number)
+-{
+- unsigned long irq_flags;
+- partid_t partid;
+- struct xpc_partition *part;
+- struct xpc_channel *ch;
+-
+-
+- DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
+-
+- /* initiate the channel disconnect for every active partition */
+- for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+- part = &xpc_partitions[partid];
+-
+- if (xpc_part_ref(part)) {
+- ch = &part->channels[ch_number];
+- xpc_msgqueue_ref(ch);
+-
+- spin_lock_irqsave(&ch->lock, irq_flags);
+-
+- if (!(ch->flags & XPC_C_DISCONNECTED)) {
+- ch->flags |= XPC_C_WDISCONNECT;
+-
+- XPC_DISCONNECT_CHANNEL(ch, xpcUnregistering,
+- &irq_flags);
+- }
+-
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+-
+- xpc_msgqueue_deref(ch);
+- xpc_part_deref(part);
+- }
+- }
+-
+- xpc_disconnect_wait(ch_number);
+-}
+-
+-
+-/*
+- * To disconnect a channel, and reflect it back to all who may be waiting.
+- *
+- * An OPEN is not allowed until XPC_C_DISCONNECTING is cleared by
+- * xpc_process_disconnect(), and if set, XPC_C_WDISCONNECT is cleared by
+- * xpc_disconnect_wait().
+- *
+- * THE CHANNEL IS TO BE LOCKED BY THE CALLER AND WILL REMAIN LOCKED UPON RETURN.
+- */
+-void
+-xpc_disconnect_channel(const int line, struct xpc_channel *ch,
+- enum xpc_retval reason, unsigned long *irq_flags)
+-{
+- u32 channel_was_connected = (ch->flags & XPC_C_CONNECTED);
+-
+-
+- DBUG_ON(!spin_is_locked(&ch->lock));
+-
+- if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED)) {
+- return;
+- }
+- DBUG_ON(!(ch->flags & (XPC_C_CONNECTING | XPC_C_CONNECTED)));
+-
+- dev_dbg(xpc_chan, "reason=%d, line=%d, partid=%d, channel=%d\n",
+- reason, line, ch->partid, ch->number);
+-
+- XPC_SET_REASON(ch, reason, line);
+-
+- ch->flags |= (XPC_C_CLOSEREQUEST | XPC_C_DISCONNECTING);
+- /* some of these may not have been set */
+- ch->flags &= ~(XPC_C_OPENREQUEST | XPC_C_OPENREPLY |
+- XPC_C_ROPENREQUEST | XPC_C_ROPENREPLY |
+- XPC_C_CONNECTING | XPC_C_CONNECTED);
+-
+- xpc_IPI_send_closerequest(ch, irq_flags);
+-
+- if (channel_was_connected) {
+- ch->flags |= XPC_C_WASCONNECTED;
+- }
+-
+- spin_unlock_irqrestore(&ch->lock, *irq_flags);
+-
+- /* wake all idle kthreads so they can exit */
+- if (atomic_read(&ch->kthreads_idle) > 0) {
+- wake_up_all(&ch->idle_wq);
+-
+- } else if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
+- !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) {
+- /* start a kthread that will do the xpcDisconnecting callout */
+- xpc_create_kthreads(ch, 1, 1);
+- }
+-
+- /* wake those waiting to allocate an entry from the local msg queue */
+- if (atomic_read(&ch->n_on_msg_allocate_wq) > 0) {
+- wake_up(&ch->msg_allocate_wq);
+- }
+-
+- spin_lock_irqsave(&ch->lock, *irq_flags);
+-}
+-
+-
+-void
+-xpc_disconnect_callout(struct xpc_channel *ch, enum xpc_retval reason)
+-{
+- /*
+- * Let the channel's registerer know that the channel is being
+- * disconnected. We don't want to do this if the registerer was never
+- * informed of a connection being made.
+- */
+-
+- if (ch->func != NULL) {
+- dev_dbg(xpc_chan, "ch->func() called, reason=%d, partid=%d, "
+- "channel=%d\n", reason, ch->partid, ch->number);
+-
+- ch->func(reason, ch->partid, ch->number, NULL, ch->key);
+-
+- dev_dbg(xpc_chan, "ch->func() returned, reason=%d, partid=%d, "
+- "channel=%d\n", reason, ch->partid, ch->number);
+- }
+-}
+-
+-
+-/*
+- * Wait for a message entry to become available for the specified channel,
+- * but don't wait any longer than 1 jiffy.
+- */
+-static enum xpc_retval
+-xpc_allocate_msg_wait(struct xpc_channel *ch)
+-{
+- enum xpc_retval ret;
+-
+-
+- if (ch->flags & XPC_C_DISCONNECTING) {
+- DBUG_ON(ch->reason == xpcInterrupted); // >>> Is this true?
+- return ch->reason;
+- }
+-
+- atomic_inc(&ch->n_on_msg_allocate_wq);
+- ret = interruptible_sleep_on_timeout(&ch->msg_allocate_wq, 1);
+- atomic_dec(&ch->n_on_msg_allocate_wq);
+-
+- if (ch->flags & XPC_C_DISCONNECTING) {
+- ret = ch->reason;
+- DBUG_ON(ch->reason == xpcInterrupted); // >>> Is this true?
+- } else if (ret == 0) {
+- ret = xpcTimeout;
+- } else {
+- ret = xpcInterrupted;
+- }
+-
+- return ret;
+-}
+-
+-
+-/*
+- * Allocate an entry for a message from the message queue associated with the
+- * specified channel.
+- */
+-static enum xpc_retval
+-xpc_allocate_msg(struct xpc_channel *ch, u32 flags,
+- struct xpc_msg **address_of_msg)
+-{
+- struct xpc_msg *msg;
+- enum xpc_retval ret;
+- s64 put;
+-
+-
+- /* this reference will be dropped in xpc_send_msg() */
+- xpc_msgqueue_ref(ch);
+-
+- if (ch->flags & XPC_C_DISCONNECTING) {
+- xpc_msgqueue_deref(ch);
+- return ch->reason;
+- }
+- if (!(ch->flags & XPC_C_CONNECTED)) {
+- xpc_msgqueue_deref(ch);
+- return xpcNotConnected;
+- }
+-
+-
+- /*
+- * Get the next available message entry from the local message queue.
+- * If none are available, we'll make sure that we grab the latest
+- * GP values.
+- */
+- ret = xpcTimeout;
+-
+- while (1) {
+-
+- put = (volatile s64) ch->w_local_GP.put;
+- if (put - (volatile s64) ch->w_remote_GP.get <
+- ch->local_nentries) {
+-
+- /* There are available message entries. We need to try
+- * to secure one for ourselves. We'll do this by trying
+- * to increment w_local_GP.put as long as someone else
+- * doesn't beat us to it. If they do, we'll have to
+- * try again.
+- */
+- if (cmpxchg(&ch->w_local_GP.put, put, put + 1) ==
+- put) {
+- /* we got the entry referenced by put */
+- break;
+- }
+- continue; /* try again */
+- }
+-
+-
+- /*
+- * There aren't any available msg entries at this time.
+- *
+- * In waiting for a message entry to become available,
+- * we set a timeout in case the other side is not
+- * sending completion IPIs. This lets us fake an IPI
+- * that will cause the IPI handler to fetch the latest
+- * GP values as if an IPI was sent by the other side.
+- */
+- if (ret == xpcTimeout) {
+- xpc_IPI_send_local_msgrequest(ch);
+- }
+-
+- if (flags & XPC_NOWAIT) {
+- xpc_msgqueue_deref(ch);
+- return xpcNoWait;
+- }
+-
+- ret = xpc_allocate_msg_wait(ch);
+- if (ret != xpcInterrupted && ret != xpcTimeout) {
+- xpc_msgqueue_deref(ch);
+- return ret;
+- }
+- }
+-
+-
+- /* get the message's address and initialize it */
+- msg = (struct xpc_msg *) ((u64) ch->local_msgqueue +
+- (put % ch->local_nentries) * ch->msg_size);
+-
+-
+- DBUG_ON(msg->flags != 0);
+- msg->number = put;
+-
+- dev_dbg(xpc_chan, "w_local_GP.put changed to %ld; msg=0x%p, "
+- "msg_number=%ld, partid=%d, channel=%d\n", put + 1,
+- (void *) msg, msg->number, ch->partid, ch->number);
+-
+- *address_of_msg = msg;
+-
+- return xpcSuccess;
+-}
+-
+-
+-/*
+- * Allocate an entry for a message from the message queue associated with the
+- * specified channel. NOTE that this routine can sleep waiting for a message
+- * entry to become available. To not sleep, pass in the XPC_NOWAIT flag.
+- *
+- * Arguments:
+- *
+- * partid - ID of partition to which the channel is connected.
+- * ch_number - channel #.
+- * flags - see xpc.h for valid flags.
+- * payload - address of the allocated payload area pointer (filled in on
+- * return) in which the user-defined message is constructed.
+- */
+-enum xpc_retval
+-xpc_initiate_allocate(partid_t partid, int ch_number, u32 flags, void **payload)
+-{
+- struct xpc_partition *part = &xpc_partitions[partid];
+- enum xpc_retval ret = xpcUnknownReason;
+- struct xpc_msg *msg = NULL;
+-
+-
+- DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+- DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
+-
+- *payload = NULL;
+-
+- if (xpc_part_ref(part)) {
+- ret = xpc_allocate_msg(&part->channels[ch_number], flags, &msg);
+- xpc_part_deref(part);
+-
+- if (msg != NULL) {
+- *payload = &msg->payload;
+- }
+- }
+-
+- return ret;
+-}
+-
+-
+-/*
+- * Now we actually send the messages that are ready to be sent by advancing
+- * the local message queue's Put value and then send an IPI to the recipient
+- * partition.
+- */
+-static void
+-xpc_send_msgs(struct xpc_channel *ch, s64 initial_put)
+-{
+- struct xpc_msg *msg;
+- s64 put = initial_put + 1;
+- int send_IPI = 0;
+-
+-
+- while (1) {
+-
+- while (1) {
+- if (put == (volatile s64) ch->w_local_GP.put) {
+- break;
+- }
+-
+- msg = (struct xpc_msg *) ((u64) ch->local_msgqueue +
+- (put % ch->local_nentries) * ch->msg_size);
+-
+- if (!(msg->flags & XPC_M_READY)) {
+- break;
+- }
+-
+- put++;
+- }
+-
+- if (put == initial_put) {
+- /* nothing's changed */
+- break;
+- }
+-
+- if (cmpxchg_rel(&ch->local_GP->put, initial_put, put) !=
+- initial_put) {
+- /* someone else beat us to it */
+- DBUG_ON((volatile s64) ch->local_GP->put < initial_put);
+- break;
+- }
+-
+- /* we just set the new value of local_GP->put */
+-
+- dev_dbg(xpc_chan, "local_GP->put changed to %ld, partid=%d, "
+- "channel=%d\n", put, ch->partid, ch->number);
+-
+- send_IPI = 1;
+-
+- /*
+- * We need to ensure that the message referenced by
+- * local_GP->put is not XPC_M_READY or that local_GP->put
+- * equals w_local_GP.put, so we'll go have a look.
+- */
+- initial_put = put;
+- }
+-
+- if (send_IPI) {
+- xpc_IPI_send_msgrequest(ch);
+- }
+-}
+-
+-
+-/*
+- * Common code that does the actual sending of the message by advancing the
+- * local message queue's Put value and sends an IPI to the partition the
+- * message is being sent to.
+- */
+-static enum xpc_retval
+-xpc_send_msg(struct xpc_channel *ch, struct xpc_msg *msg, u8 notify_type,
+- xpc_notify_func func, void *key)
+-{
+- enum xpc_retval ret = xpcSuccess;
+- struct xpc_notify *notify = notify;
+- s64 put, msg_number = msg->number;
+-
+-
+- DBUG_ON(notify_type == XPC_N_CALL && func == NULL);
+- DBUG_ON((((u64) msg - (u64) ch->local_msgqueue) / ch->msg_size) !=
+- msg_number % ch->local_nentries);
+- DBUG_ON(msg->flags & XPC_M_READY);
+-
+- if (ch->flags & XPC_C_DISCONNECTING) {
+- /* drop the reference grabbed in xpc_allocate_msg() */
+- xpc_msgqueue_deref(ch);
+- return ch->reason;
+- }
+-
+- if (notify_type != 0) {
+- /*
+- * Tell the remote side to send an ACK interrupt when the
+- * message has been delivered.
+- */
+- msg->flags |= XPC_M_INTERRUPT;
+-
+- atomic_inc(&ch->n_to_notify);
+-
+- notify = &ch->notify_queue[msg_number % ch->local_nentries];
+- notify->func = func;
+- notify->key = key;
+- notify->type = notify_type;
+-
+- // >>> is a mb() needed here?
+-
+- if (ch->flags & XPC_C_DISCONNECTING) {
+- /*
+- * An error occurred between our last error check and
+- * this one. We will try to clear the type field from
+- * the notify entry. If we succeed then
+- * xpc_disconnect_channel() didn't already process
+- * the notify entry.
+- */
+- if (cmpxchg(¬ify->type, notify_type, 0) ==
+- notify_type) {
+- atomic_dec(&ch->n_to_notify);
+- ret = ch->reason;
+- }
+-
+- /* drop the reference grabbed in xpc_allocate_msg() */
+- xpc_msgqueue_deref(ch);
+- return ret;
+- }
+- }
+-
+- msg->flags |= XPC_M_READY;
+-
+- /*
+- * The preceding store of msg->flags must occur before the following
+- * load of ch->local_GP->put.
+- */
+- mb();
+-
+- /* see if the message is next in line to be sent, if so send it */
+-
+- put = ch->local_GP->put;
+- if (put == msg_number) {
+- xpc_send_msgs(ch, put);
+- }
+-
+- /* drop the reference grabbed in xpc_allocate_msg() */
+- xpc_msgqueue_deref(ch);
+- return ret;
+-}
+-
+-
+-/*
+- * Send a message previously allocated using xpc_initiate_allocate() on the
+- * specified channel connected to the specified partition.
+- *
+- * This routine will not wait for the message to be received, nor will
+- * notification be given when it does happen. Once this routine has returned
+- * the message entry allocated via xpc_initiate_allocate() is no longer
+- * accessable to the caller.
+- *
+- * This routine, although called by users, does not call xpc_part_ref() to
+- * ensure that the partition infrastructure is in place. It relies on the
+- * fact that we called xpc_msgqueue_ref() in xpc_allocate_msg().
+- *
+- * Arguments:
+- *
+- * partid - ID of partition to which the channel is connected.
+- * ch_number - channel # to send message on.
+- * payload - pointer to the payload area allocated via
+- * xpc_initiate_allocate().
+- */
+-enum xpc_retval
+-xpc_initiate_send(partid_t partid, int ch_number, void *payload)
+-{
+- struct xpc_partition *part = &xpc_partitions[partid];
+- struct xpc_msg *msg = XPC_MSG_ADDRESS(payload);
+- enum xpc_retval ret;
+-
+-
+- dev_dbg(xpc_chan, "msg=0x%p, partid=%d, channel=%d\n", (void *) msg,
+- partid, ch_number);
+-
+- DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+- DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
+- DBUG_ON(msg == NULL);
+-
+- ret = xpc_send_msg(&part->channels[ch_number], msg, 0, NULL, NULL);
+-
+- return ret;
+-}
+-
+-
+-/*
+- * Send a message previously allocated using xpc_initiate_allocate on the
+- * specified channel connected to the specified partition.
+- *
+- * This routine will not wait for the message to be sent. Once this routine
+- * has returned the message entry allocated via xpc_initiate_allocate() is no
+- * longer accessable to the caller.
+- *
+- * Once the remote end of the channel has received the message, the function
+- * passed as an argument to xpc_initiate_send_notify() will be called. This
+- * allows the sender to free up or re-use any buffers referenced by the
+- * message, but does NOT mean the message has been processed at the remote
+- * end by a receiver.
+- *
+- * If this routine returns an error, the caller's function will NOT be called.
+- *
+- * This routine, although called by users, does not call xpc_part_ref() to
+- * ensure that the partition infrastructure is in place. It relies on the
+- * fact that we called xpc_msgqueue_ref() in xpc_allocate_msg().
+- *
+- * Arguments:
+- *
+- * partid - ID of partition to which the channel is connected.
+- * ch_number - channel # to send message on.
+- * payload - pointer to the payload area allocated via
+- * xpc_initiate_allocate().
+- * func - function to call with asynchronous notification of message
+- * receipt. THIS FUNCTION MUST BE NON-BLOCKING.
+- * key - user-defined key to be passed to the function when it's called.
+- */
+-enum xpc_retval
+-xpc_initiate_send_notify(partid_t partid, int ch_number, void *payload,
+- xpc_notify_func func, void *key)
+-{
+- struct xpc_partition *part = &xpc_partitions[partid];
+- struct xpc_msg *msg = XPC_MSG_ADDRESS(payload);
+- enum xpc_retval ret;
+-
+-
+- dev_dbg(xpc_chan, "msg=0x%p, partid=%d, channel=%d\n", (void *) msg,
+- partid, ch_number);
+-
+- DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+- DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
+- DBUG_ON(msg == NULL);
+- DBUG_ON(func == NULL);
+-
+- ret = xpc_send_msg(&part->channels[ch_number], msg, XPC_N_CALL,
+- func, key);
+- return ret;
+-}
+-
+-
+-static struct xpc_msg *
+-xpc_pull_remote_msg(struct xpc_channel *ch, s64 get)
+-{
+- struct xpc_partition *part = &xpc_partitions[ch->partid];
+- struct xpc_msg *remote_msg, *msg;
+- u32 msg_index, nmsgs;
+- u64 msg_offset;
+- enum xpc_retval ret;
+-
+-
+- if (mutex_lock_interruptible(&ch->msg_to_pull_mutex) != 0) {
+- /* we were interrupted by a signal */
+- return NULL;
+- }
+-
+- while (get >= ch->next_msg_to_pull) {
+-
+- /* pull as many messages as are ready and able to be pulled */
+-
+- msg_index = ch->next_msg_to_pull % ch->remote_nentries;
+-
+- DBUG_ON(ch->next_msg_to_pull >=
+- (volatile s64) ch->w_remote_GP.put);
+- nmsgs = (volatile s64) ch->w_remote_GP.put -
+- ch->next_msg_to_pull;
+- if (msg_index + nmsgs > ch->remote_nentries) {
+- /* ignore the ones that wrap the msg queue for now */
+- nmsgs = ch->remote_nentries - msg_index;
+- }
+-
+- msg_offset = msg_index * ch->msg_size;
+- msg = (struct xpc_msg *) ((u64) ch->remote_msgqueue +
+- msg_offset);
+- remote_msg = (struct xpc_msg *) (ch->remote_msgqueue_pa +
+- msg_offset);
+-
+- if ((ret = xpc_pull_remote_cachelines(part, msg, remote_msg,
+- nmsgs * ch->msg_size)) != xpcSuccess) {
+-
+- dev_dbg(xpc_chan, "failed to pull %d msgs starting with"
+- " msg %ld from partition %d, channel=%d, "
+- "ret=%d\n", nmsgs, ch->next_msg_to_pull,
+- ch->partid, ch->number, ret);
+-
+- XPC_DEACTIVATE_PARTITION(part, ret);
+-
+- mutex_unlock(&ch->msg_to_pull_mutex);
+- return NULL;
+- }
+-
+- mb(); /* >>> this may not be needed, we're not sure */
+-
+- ch->next_msg_to_pull += nmsgs;
+- }
+-
+- mutex_unlock(&ch->msg_to_pull_mutex);
+-
+- /* return the message we were looking for */
+- msg_offset = (get % ch->remote_nentries) * ch->msg_size;
+- msg = (struct xpc_msg *) ((u64) ch->remote_msgqueue + msg_offset);
+-
+- return msg;
+-}
+-
+-
+-/*
+- * Get a message to be delivered.
+- */
+-static struct xpc_msg *
+-xpc_get_deliverable_msg(struct xpc_channel *ch)
+-{
+- struct xpc_msg *msg = NULL;
+- s64 get;
+-
+-
+- do {
+- if ((volatile u32) ch->flags & XPC_C_DISCONNECTING) {
+- break;
+- }
+-
+- get = (volatile s64) ch->w_local_GP.get;
+- if (get == (volatile s64) ch->w_remote_GP.put) {
+- break;
+- }
+-
+- /* There are messages waiting to be pulled and delivered.
+- * We need to try to secure one for ourselves. We'll do this
+- * by trying to increment w_local_GP.get and hope that no one
+- * else beats us to it. If they do, we'll we'll simply have
+- * to try again for the next one.
+- */
+-
+- if (cmpxchg(&ch->w_local_GP.get, get, get + 1) == get) {
+- /* we got the entry referenced by get */
+-
+- dev_dbg(xpc_chan, "w_local_GP.get changed to %ld, "
+- "partid=%d, channel=%d\n", get + 1,
+- ch->partid, ch->number);
+-
+- /* pull the message from the remote partition */
+-
+- msg = xpc_pull_remote_msg(ch, get);
+-
+- DBUG_ON(msg != NULL && msg->number != get);
+- DBUG_ON(msg != NULL && (msg->flags & XPC_M_DONE));
+- DBUG_ON(msg != NULL && !(msg->flags & XPC_M_READY));
+-
+- break;
+- }
+-
+- } while (1);
+-
+- return msg;
+-}
+-
+-
+-/*
+- * Deliver a message to its intended recipient.
+- */
+-void
+-xpc_deliver_msg(struct xpc_channel *ch)
+-{
+- struct xpc_msg *msg;
+-
+-
+- if ((msg = xpc_get_deliverable_msg(ch)) != NULL) {
+-
+- /*
+- * This ref is taken to protect the payload itself from being
+- * freed before the user is finished with it, which the user
+- * indicates by calling xpc_initiate_received().
+- */
+- xpc_msgqueue_ref(ch);
+-
+- atomic_inc(&ch->kthreads_active);
+-
+- if (ch->func != NULL) {
+- dev_dbg(xpc_chan, "ch->func() called, msg=0x%p, "
+- "msg_number=%ld, partid=%d, channel=%d\n",
+- (void *) msg, msg->number, ch->partid,
+- ch->number);
+-
+- /* deliver the message to its intended recipient */
+- ch->func(xpcMsgReceived, ch->partid, ch->number,
+- &msg->payload, ch->key);
+-
+- dev_dbg(xpc_chan, "ch->func() returned, msg=0x%p, "
+- "msg_number=%ld, partid=%d, channel=%d\n",
+- (void *) msg, msg->number, ch->partid,
+- ch->number);
+- }
+-
+- atomic_dec(&ch->kthreads_active);
+- }
+-}
+-
+-
+-/*
+- * Now we actually acknowledge the messages that have been delivered and ack'd
+- * by advancing the cached remote message queue's Get value and if requested
+- * send an IPI to the message sender's partition.
+- */
+-static void
+-xpc_acknowledge_msgs(struct xpc_channel *ch, s64 initial_get, u8 msg_flags)
+-{
+- struct xpc_msg *msg;
+- s64 get = initial_get + 1;
+- int send_IPI = 0;
+-
+-
+- while (1) {
+-
+- while (1) {
+- if (get == (volatile s64) ch->w_local_GP.get) {
+- break;
+- }
+-
+- msg = (struct xpc_msg *) ((u64) ch->remote_msgqueue +
+- (get % ch->remote_nentries) * ch->msg_size);
+-
+- if (!(msg->flags & XPC_M_DONE)) {
+- break;
+- }
+-
+- msg_flags |= msg->flags;
+- get++;
+- }
+-
+- if (get == initial_get) {
+- /* nothing's changed */
+- break;
+- }
+-
+- if (cmpxchg_rel(&ch->local_GP->get, initial_get, get) !=
+- initial_get) {
+- /* someone else beat us to it */
+- DBUG_ON((volatile s64) ch->local_GP->get <=
+- initial_get);
+- break;
+- }
+-
+- /* we just set the new value of local_GP->get */
+-
+- dev_dbg(xpc_chan, "local_GP->get changed to %ld, partid=%d, "
+- "channel=%d\n", get, ch->partid, ch->number);
+-
+- send_IPI = (msg_flags & XPC_M_INTERRUPT);
+-
+- /*
+- * We need to ensure that the message referenced by
+- * local_GP->get is not XPC_M_DONE or that local_GP->get
+- * equals w_local_GP.get, so we'll go have a look.
+- */
+- initial_get = get;
+- }
+-
+- if (send_IPI) {
+- xpc_IPI_send_msgrequest(ch);
+- }
+-}
+-
+-
+-/*
+- * Acknowledge receipt of a delivered message.
+- *
+- * If a message has XPC_M_INTERRUPT set, send an interrupt to the partition
+- * that sent the message.
+- *
+- * This function, although called by users, does not call xpc_part_ref() to
+- * ensure that the partition infrastructure is in place. It relies on the
+- * fact that we called xpc_msgqueue_ref() in xpc_deliver_msg().
+- *
+- * Arguments:
+- *
+- * partid - ID of partition to which the channel is connected.
+- * ch_number - channel # message received on.
+- * payload - pointer to the payload area allocated via
+- * xpc_initiate_allocate().
+- */
+-void
+-xpc_initiate_received(partid_t partid, int ch_number, void *payload)
+-{
+- struct xpc_partition *part = &xpc_partitions[partid];
+- struct xpc_channel *ch;
+- struct xpc_msg *msg = XPC_MSG_ADDRESS(payload);
+- s64 get, msg_number = msg->number;
+-
+-
+- DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+- DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
+-
+- ch = &part->channels[ch_number];
+-
+- dev_dbg(xpc_chan, "msg=0x%p, msg_number=%ld, partid=%d, channel=%d\n",
+- (void *) msg, msg_number, ch->partid, ch->number);
+-
+- DBUG_ON((((u64) msg - (u64) ch->remote_msgqueue) / ch->msg_size) !=
+- msg_number % ch->remote_nentries);
+- DBUG_ON(msg->flags & XPC_M_DONE);
+-
+- msg->flags |= XPC_M_DONE;
+-
+- /*
+- * The preceding store of msg->flags must occur before the following
+- * load of ch->local_GP->get.
+- */
+- mb();
+-
+- /*
+- * See if this message is next in line to be acknowledged as having
+- * been delivered.
+- */
+- get = ch->local_GP->get;
+- if (get == msg_number) {
+- xpc_acknowledge_msgs(ch, get, msg->flags);
+- }
+-
+- /* the call to xpc_msgqueue_ref() was done by xpc_deliver_msg() */
+- xpc_msgqueue_deref(ch);
+-}
+-
+diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c
+deleted file mode 100644
+index 81785b7..0000000
+--- a/arch/ia64/sn/kernel/xpc_main.c
++++ /dev/null
+@@ -1,1431 +0,0 @@
+-/*
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License. See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (c) 2004-2007 Silicon Graphics, Inc. All Rights Reserved.
+- */
+-
+-
+-/*
+- * Cross Partition Communication (XPC) support - standard version.
+- *
+- * XPC provides a message passing capability that crosses partition
+- * boundaries. This module is made up of two parts:
+- *
+- * partition This part detects the presence/absence of other
+- * partitions. It provides a heartbeat and monitors
+- * the heartbeats of other partitions.
+- *
+- * channel This part manages the channels and sends/receives
+- * messages across them to/from other partitions.
+- *
+- * There are a couple of additional functions residing in XP, which
+- * provide an interface to XPC for its users.
+- *
+- *
+- * Caveats:
+- *
+- * . We currently have no way to determine which nasid an IPI came
+- * from. Thus, xpc_IPI_send() does a remote AMO write followed by
+- * an IPI. The AMO indicates where data is to be pulled from, so
+- * after the IPI arrives, the remote partition checks the AMO word.
+- * The IPI can actually arrive before the AMO however, so other code
+- * must periodically check for this case. Also, remote AMO operations
+- * do not reliably time out. Thus we do a remote PIO read solely to
+- * know whether the remote partition is down and whether we should
+- * stop sending IPIs to it. This remote PIO read operation is set up
+- * in a special nofault region so SAL knows to ignore (and cleanup)
+- * any errors due to the remote AMO write, PIO read, and/or PIO
+- * write operations.
+- *
+- * If/when new hardware solves this IPI problem, we should abandon
+- * the current approach.
+- *
+- */
+-
+-
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/syscalls.h>
+-#include <linux/cache.h>
+-#include <linux/interrupt.h>
+-#include <linux/delay.h>
+-#include <linux/reboot.h>
+-#include <linux/completion.h>
+-#include <linux/kdebug.h>
+-#include <asm/sn/intr.h>
+-#include <asm/sn/sn_sal.h>
+-#include <asm/uaccess.h>
+-#include <asm/sn/xpc.h>
+-
+-
+-/* define two XPC debug device structures to be used with dev_dbg() et al */
+-
+-struct device_driver xpc_dbg_name = {
+- .name = "xpc"
+-};
+-
+-struct device xpc_part_dbg_subname = {
+- .bus_id = {0}, /* set to "part" at xpc_init() time */
+- .driver = &xpc_dbg_name
+-};
+-
+-struct device xpc_chan_dbg_subname = {
+- .bus_id = {0}, /* set to "chan" at xpc_init() time */
+- .driver = &xpc_dbg_name
+-};
+-
+-struct device *xpc_part = &xpc_part_dbg_subname;
+-struct device *xpc_chan = &xpc_chan_dbg_subname;
+-
+-
+-static int xpc_kdebug_ignore;
+-
+-
+-/* systune related variables for /proc/sys directories */
+-
+-static int xpc_hb_interval = XPC_HB_DEFAULT_INTERVAL;
+-static int xpc_hb_min_interval = 1;
+-static int xpc_hb_max_interval = 10;
+-
+-static int xpc_hb_check_interval = XPC_HB_CHECK_DEFAULT_INTERVAL;
+-static int xpc_hb_check_min_interval = 10;
+-static int xpc_hb_check_max_interval = 120;
+-
+-int xpc_disengage_request_timelimit = XPC_DISENGAGE_REQUEST_DEFAULT_TIMELIMIT;
+-static int xpc_disengage_request_min_timelimit = 0;
+-static int xpc_disengage_request_max_timelimit = 120;
+-
+-static ctl_table xpc_sys_xpc_hb_dir[] = {
+- {
+- .ctl_name = CTL_UNNUMBERED,
+- .procname = "hb_interval",
+- .data = &xpc_hb_interval,
+- .maxlen = sizeof(int),
+- .mode = 0644,
+- .proc_handler = &proc_dointvec_minmax,
+- .strategy = &sysctl_intvec,
+- .extra1 = &xpc_hb_min_interval,
+- .extra2 = &xpc_hb_max_interval
+- },
+- {
+- .ctl_name = CTL_UNNUMBERED,
+- .procname = "hb_check_interval",
+- .data = &xpc_hb_check_interval,
+- .maxlen = sizeof(int),
+- .mode = 0644,
+- .proc_handler = &proc_dointvec_minmax,
+- .strategy = &sysctl_intvec,
+- .extra1 = &xpc_hb_check_min_interval,
+- .extra2 = &xpc_hb_check_max_interval
+- },
+- {}
+-};
+-static ctl_table xpc_sys_xpc_dir[] = {
+- {
+- .ctl_name = CTL_UNNUMBERED,
+- .procname = "hb",
+- .mode = 0555,
+- .child = xpc_sys_xpc_hb_dir
+- },
+- {
+- .ctl_name = CTL_UNNUMBERED,
+- .procname = "disengage_request_timelimit",
+- .data = &xpc_disengage_request_timelimit,
+- .maxlen = sizeof(int),
+- .mode = 0644,
+- .proc_handler = &proc_dointvec_minmax,
+- .strategy = &sysctl_intvec,
+- .extra1 = &xpc_disengage_request_min_timelimit,
+- .extra2 = &xpc_disengage_request_max_timelimit
+- },
+- {}
+-};
+-static ctl_table xpc_sys_dir[] = {
+- {
+- .ctl_name = CTL_UNNUMBERED,
+- .procname = "xpc",
+- .mode = 0555,
+- .child = xpc_sys_xpc_dir
+- },
+- {}
+-};
+-static struct ctl_table_header *xpc_sysctl;
+-
+-/* non-zero if any remote partition disengage request was timed out */
+-int xpc_disengage_request_timedout;
+-
+-/* #of IRQs received */
+-static atomic_t xpc_act_IRQ_rcvd;
+-
+-/* IRQ handler notifies this wait queue on receipt of an IRQ */
+-static DECLARE_WAIT_QUEUE_HEAD(xpc_act_IRQ_wq);
+-
+-static unsigned long xpc_hb_check_timeout;
+-
+-/* notification that the xpc_hb_checker thread has exited */
+-static DECLARE_COMPLETION(xpc_hb_checker_exited);
+-
+-/* notification that the xpc_discovery thread has exited */
+-static DECLARE_COMPLETION(xpc_discovery_exited);
+-
+-
+-static struct timer_list xpc_hb_timer;
+-
+-
+-static void xpc_kthread_waitmsgs(struct xpc_partition *, struct xpc_channel *);
+-
+-
+-static int xpc_system_reboot(struct notifier_block *, unsigned long, void *);
+-static struct notifier_block xpc_reboot_notifier = {
+- .notifier_call = xpc_system_reboot,
+-};
+-
+-static int xpc_system_die(struct notifier_block *, unsigned long, void *);
+-static struct notifier_block xpc_die_notifier = {
+- .notifier_call = xpc_system_die,
+-};
+-
+-
+-/*
+- * Timer function to enforce the timelimit on the partition disengage request.
+- */
+-static void
+-xpc_timeout_partition_disengage_request(unsigned long data)
+-{
+- struct xpc_partition *part = (struct xpc_partition *) data;
+-
+-
+- DBUG_ON(jiffies < part->disengage_request_timeout);
+-
+- (void) xpc_partition_disengaged(part);
+-
+- DBUG_ON(part->disengage_request_timeout != 0);
+- DBUG_ON(xpc_partition_engaged(1UL << XPC_PARTID(part)) != 0);
+-}
+-
+-
+-/*
+- * Notify the heartbeat check thread that an IRQ has been received.
+- */
+-static irqreturn_t
+-xpc_act_IRQ_handler(int irq, void *dev_id)
+-{
+- atomic_inc(&xpc_act_IRQ_rcvd);
+- wake_up_interruptible(&xpc_act_IRQ_wq);
+- return IRQ_HANDLED;
+-}
+-
+-
+-/*
+- * Timer to produce the heartbeat. The timer structures function is
+- * already set when this is initially called. A tunable is used to
+- * specify when the next timeout should occur.
+- */
+-static void
+-xpc_hb_beater(unsigned long dummy)
+-{
+- xpc_vars->heartbeat++;
+-
+- if (jiffies >= xpc_hb_check_timeout) {
+- wake_up_interruptible(&xpc_act_IRQ_wq);
+- }
+-
+- xpc_hb_timer.expires = jiffies + (xpc_hb_interval * HZ);
+- add_timer(&xpc_hb_timer);
+-}
+-
+-
+-/*
+- * This thread is responsible for nearly all of the partition
+- * activation/deactivation.
+- */
+-static int
+-xpc_hb_checker(void *ignore)
+-{
+- int last_IRQ_count = 0;
+- int new_IRQ_count;
+- int force_IRQ=0;
+-
+-
+- /* this thread was marked active by xpc_hb_init() */
+-
+- daemonize(XPC_HB_CHECK_THREAD_NAME);
+-
+- set_cpus_allowed(current, cpumask_of_cpu(XPC_HB_CHECK_CPU));
+-
+- /* set our heartbeating to other partitions into motion */
+- xpc_hb_check_timeout = jiffies + (xpc_hb_check_interval * HZ);
+- xpc_hb_beater(0);
+-
+- while (!(volatile int) xpc_exiting) {
+-
+- dev_dbg(xpc_part, "woke up with %d ticks rem; %d IRQs have "
+- "been received\n",
+- (int) (xpc_hb_check_timeout - jiffies),
+- atomic_read(&xpc_act_IRQ_rcvd) - last_IRQ_count);
+-
+-
+- /* checking of remote heartbeats is skewed by IRQ handling */
+- if (jiffies >= xpc_hb_check_timeout) {
+- dev_dbg(xpc_part, "checking remote heartbeats\n");
+- xpc_check_remote_hb();
+-
+- /*
+- * We need to periodically recheck to ensure no
+- * IPI/AMO pairs have been missed. That check
+- * must always reset xpc_hb_check_timeout.
+- */
+- force_IRQ = 1;
+- }
+-
+-
+- /* check for outstanding IRQs */
+- new_IRQ_count = atomic_read(&xpc_act_IRQ_rcvd);
+- if (last_IRQ_count < new_IRQ_count || force_IRQ != 0) {
+- force_IRQ = 0;
+-
+- dev_dbg(xpc_part, "found an IRQ to process; will be "
+- "resetting xpc_hb_check_timeout\n");
+-
+- last_IRQ_count += xpc_identify_act_IRQ_sender();
+- if (last_IRQ_count < new_IRQ_count) {
+- /* retry once to help avoid missing AMO */
+- (void) xpc_identify_act_IRQ_sender();
+- }
+- last_IRQ_count = new_IRQ_count;
+-
+- xpc_hb_check_timeout = jiffies +
+- (xpc_hb_check_interval * HZ);
+- }
+-
+- /* wait for IRQ or timeout */
+- (void) wait_event_interruptible(xpc_act_IRQ_wq,
+- (last_IRQ_count < atomic_read(&xpc_act_IRQ_rcvd) ||
+- jiffies >= xpc_hb_check_timeout ||
+- (volatile int) xpc_exiting));
+- }
+-
+- dev_dbg(xpc_part, "heartbeat checker is exiting\n");
+-
+-
+- /* mark this thread as having exited */
+- complete(&xpc_hb_checker_exited);
+- return 0;
+-}
+-
+-
+-/*
+- * This thread will attempt to discover other partitions to activate
+- * based on info provided by SAL. This new thread is short lived and
+- * will exit once discovery is complete.
+- */
+-static int
+-xpc_initiate_discovery(void *ignore)
+-{
+- daemonize(XPC_DISCOVERY_THREAD_NAME);
+-
+- xpc_discovery();
+-
+- dev_dbg(xpc_part, "discovery thread is exiting\n");
+-
+- /* mark this thread as having exited */
+- complete(&xpc_discovery_exited);
+- return 0;
+-}
+-
+-
+-/*
+- * Establish first contact with the remote partititon. This involves pulling
+- * the XPC per partition variables from the remote partition and waiting for
+- * the remote partition to pull ours.
+- */
+-static enum xpc_retval
+-xpc_make_first_contact(struct xpc_partition *part)
+-{
+- enum xpc_retval ret;
+-
+-
+- while ((ret = xpc_pull_remote_vars_part(part)) != xpcSuccess) {
+- if (ret != xpcRetry) {
+- XPC_DEACTIVATE_PARTITION(part, ret);
+- return ret;
+- }
+-
+- dev_dbg(xpc_chan, "waiting to make first contact with "
+- "partition %d\n", XPC_PARTID(part));
+-
+- /* wait a 1/4 of a second or so */
+- (void) msleep_interruptible(250);
+-
+- if (part->act_state == XPC_P_DEACTIVATING) {
+- return part->reason;
+- }
+- }
+-
+- return xpc_mark_partition_active(part);
+-}
+-
+-
+-/*
+- * The first kthread assigned to a newly activated partition is the one
+- * created by XPC HB with which it calls xpc_partition_up(). XPC hangs on to
+- * that kthread until the partition is brought down, at which time that kthread
+- * returns back to XPC HB. (The return of that kthread will signify to XPC HB
+- * that XPC has dismantled all communication infrastructure for the associated
+- * partition.) This kthread becomes the channel manager for that partition.
+- *
+- * Each active partition has a channel manager, who, besides connecting and
+- * disconnecting channels, will ensure that each of the partition's connected
+- * channels has the required number of assigned kthreads to get the work done.
+- */
+-static void
+-xpc_channel_mgr(struct xpc_partition *part)
+-{
+- while (part->act_state != XPC_P_DEACTIVATING ||
+- atomic_read(&part->nchannels_active) > 0 ||
+- !xpc_partition_disengaged(part)) {
+-
+- xpc_process_channel_activity(part);
+-
+-
+- /*
+- * Wait until we've been requested to activate kthreads or
+- * all of the channel's message queues have been torn down or
+- * a signal is pending.
+- *
+- * The channel_mgr_requests is set to 1 after being awakened,
+- * This is done to prevent the channel mgr from making one pass
+- * through the loop for each request, since he will
+- * be servicing all the requests in one pass. The reason it's
+- * set to 1 instead of 0 is so that other kthreads will know
+- * that the channel mgr is running and won't bother trying to
+- * wake him up.
+- */
+- atomic_dec(&part->channel_mgr_requests);
+- (void) wait_event_interruptible(part->channel_mgr_wq,
+- (atomic_read(&part->channel_mgr_requests) > 0 ||
+- (volatile u64) part->local_IPI_amo != 0 ||
+- ((volatile u8) part->act_state ==
+- XPC_P_DEACTIVATING &&
+- atomic_read(&part->nchannels_active) == 0 &&
+- xpc_partition_disengaged(part))));
+- atomic_set(&part->channel_mgr_requests, 1);
+-
+- // >>> Does it need to wakeup periodically as well? In case we
+- // >>> miscalculated the #of kthreads to wakeup or create?
+- }
+-}
+-
+-
+-/*
+- * When XPC HB determines that a partition has come up, it will create a new
+- * kthread and that kthread will call this function to attempt to set up the
+- * basic infrastructure used for Cross Partition Communication with the newly
+- * upped partition.
+- *
+- * The kthread that was created by XPC HB and which setup the XPC
+- * infrastructure will remain assigned to the partition until the partition
+- * goes down. At which time the kthread will teardown the XPC infrastructure
+- * and then exit.
+- *
+- * XPC HB will put the remote partition's XPC per partition specific variables
+- * physical address into xpc_partitions[partid].remote_vars_part_pa prior to
+- * calling xpc_partition_up().
+- */
+-static void
+-xpc_partition_up(struct xpc_partition *part)
+-{
+- DBUG_ON(part->channels != NULL);
+-
+- dev_dbg(xpc_chan, "activating partition %d\n", XPC_PARTID(part));
+-
+- if (xpc_setup_infrastructure(part) != xpcSuccess) {
+- return;
+- }
+-
+- /*
+- * The kthread that XPC HB called us with will become the
+- * channel manager for this partition. It will not return
+- * back to XPC HB until the partition's XPC infrastructure
+- * has been dismantled.
+- */
+-
+- (void) xpc_part_ref(part); /* this will always succeed */
+-
+- if (xpc_make_first_contact(part) == xpcSuccess) {
+- xpc_channel_mgr(part);
+- }
+-
+- xpc_part_deref(part);
+-
+- xpc_teardown_infrastructure(part);
+-}
+-
+-
+-static int
+-xpc_activating(void *__partid)
+-{
+- partid_t partid = (u64) __partid;
+- struct xpc_partition *part = &xpc_partitions[partid];
+- unsigned long irq_flags;
+- struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
+- int ret;
+-
+-
+- DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+-
+- spin_lock_irqsave(&part->act_lock, irq_flags);
+-
+- if (part->act_state == XPC_P_DEACTIVATING) {
+- part->act_state = XPC_P_INACTIVE;
+- spin_unlock_irqrestore(&part->act_lock, irq_flags);
+- part->remote_rp_pa = 0;
+- return 0;
+- }
+-
+- /* indicate the thread is activating */
+- DBUG_ON(part->act_state != XPC_P_ACTIVATION_REQ);
+- part->act_state = XPC_P_ACTIVATING;
+-
+- XPC_SET_REASON(part, 0, 0);
+- spin_unlock_irqrestore(&part->act_lock, irq_flags);
+-
+- dev_dbg(xpc_part, "bringing partition %d up\n", partid);
+-
+- daemonize("xpc%02d", partid);
+-
+- /*
+- * This thread needs to run at a realtime priority to prevent a
+- * significant performance degradation.
+- */
+- ret = sched_setscheduler(current, SCHED_FIFO, ¶m);
+- if (ret != 0) {
+- dev_warn(xpc_part, "unable to set pid %d to a realtime "
+- "priority, ret=%d\n", current->pid, ret);
+- }
+-
+- /* allow this thread and its children to run on any CPU */
+- set_cpus_allowed(current, CPU_MASK_ALL);
+-
+- /*
+- * Register the remote partition's AMOs with SAL so it can handle
+- * and cleanup errors within that address range should the remote
+- * partition go down. We don't unregister this range because it is
+- * difficult to tell when outstanding writes to the remote partition
+- * are finished and thus when it is safe to unregister. This should
+- * not result in wasted space in the SAL xp_addr_region table because
+- * we should get the same page for remote_amos_page_pa after module
+- * reloads and system reboots.
+- */
+- if (sn_register_xp_addr_region(part->remote_amos_page_pa,
+- PAGE_SIZE, 1) < 0) {
+- dev_warn(xpc_part, "xpc_partition_up(%d) failed to register "
+- "xp_addr region\n", partid);
+-
+- spin_lock_irqsave(&part->act_lock, irq_flags);
+- part->act_state = XPC_P_INACTIVE;
+- XPC_SET_REASON(part, xpcPhysAddrRegFailed, __LINE__);
+- spin_unlock_irqrestore(&part->act_lock, irq_flags);
+- part->remote_rp_pa = 0;
+- return 0;
+- }
+-
+- xpc_allow_hb(partid, xpc_vars);
+- xpc_IPI_send_activated(part);
+-
+-
+- /*
+- * xpc_partition_up() holds this thread and marks this partition as
+- * XPC_P_ACTIVE by calling xpc_hb_mark_active().
+- */
+- (void) xpc_partition_up(part);
+-
+- xpc_disallow_hb(partid, xpc_vars);
+- xpc_mark_partition_inactive(part);
+-
+- if (part->reason == xpcReactivating) {
+- /* interrupting ourselves results in activating partition */
+- xpc_IPI_send_reactivate(part);
+- }
+-
+- return 0;
+-}
+-
+-
+-void
+-xpc_activate_partition(struct xpc_partition *part)
+-{
+- partid_t partid = XPC_PARTID(part);
+- unsigned long irq_flags;
+- pid_t pid;
+-
+-
+- spin_lock_irqsave(&part->act_lock, irq_flags);
+-
+- DBUG_ON(part->act_state != XPC_P_INACTIVE);
+-
+- part->act_state = XPC_P_ACTIVATION_REQ;
+- XPC_SET_REASON(part, xpcCloneKThread, __LINE__);
+-
+- spin_unlock_irqrestore(&part->act_lock, irq_flags);
+-
+- pid = kernel_thread(xpc_activating, (void *) ((u64) partid), 0);
+-
+- if (unlikely(pid <= 0)) {
+- spin_lock_irqsave(&part->act_lock, irq_flags);
+- part->act_state = XPC_P_INACTIVE;
+- XPC_SET_REASON(part, xpcCloneKThreadFailed, __LINE__);
+- spin_unlock_irqrestore(&part->act_lock, irq_flags);
+- }
+-}
+-
+-
+-/*
+- * Handle the receipt of a SGI_XPC_NOTIFY IRQ by seeing whether the specified
+- * partition actually sent it. Since SGI_XPC_NOTIFY IRQs may be shared by more
+- * than one partition, we use an AMO_t structure per partition to indicate
+- * whether a partition has sent an IPI or not. >>> If it has, then wake up the
+- * associated kthread to handle it.
+- *
+- * All SGI_XPC_NOTIFY IRQs received by XPC are the result of IPIs sent by XPC
+- * running on other partitions.
+- *
+- * Noteworthy Arguments:
+- *
+- * irq - Interrupt ReQuest number. NOT USED.
+- *
+- * dev_id - partid of IPI's potential sender.
+- */
+-irqreturn_t
+-xpc_notify_IRQ_handler(int irq, void *dev_id)
+-{
+- partid_t partid = (partid_t) (u64) dev_id;
+- struct xpc_partition *part = &xpc_partitions[partid];
+-
+-
+- DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+-
+- if (xpc_part_ref(part)) {
+- xpc_check_for_channel_activity(part);
+-
+- xpc_part_deref(part);
+- }
+- return IRQ_HANDLED;
+-}
+-
+-
+-/*
+- * Check to see if xpc_notify_IRQ_handler() dropped any IPIs on the floor
+- * because the write to their associated IPI amo completed after the IRQ/IPI
+- * was received.
+- */
+-void
+-xpc_dropped_IPI_check(struct xpc_partition *part)
+-{
+- if (xpc_part_ref(part)) {
+- xpc_check_for_channel_activity(part);
+-
+- part->dropped_IPI_timer.expires = jiffies +
+- XPC_P_DROPPED_IPI_WAIT;
+- add_timer(&part->dropped_IPI_timer);
+- xpc_part_deref(part);
+- }
+-}
+-
+-
+-void
+-xpc_activate_kthreads(struct xpc_channel *ch, int needed)
+-{
+- int idle = atomic_read(&ch->kthreads_idle);
+- int assigned = atomic_read(&ch->kthreads_assigned);
+- int wakeup;
+-
+-
+- DBUG_ON(needed <= 0);
+-
+- if (idle > 0) {
+- wakeup = (needed > idle) ? idle : needed;
+- needed -= wakeup;
+-
+- dev_dbg(xpc_chan, "wakeup %d idle kthreads, partid=%d, "
+- "channel=%d\n", wakeup, ch->partid, ch->number);
+-
+- /* only wakeup the requested number of kthreads */
+- wake_up_nr(&ch->idle_wq, wakeup);
+- }
+-
+- if (needed <= 0) {
+- return;
+- }
+-
+- if (needed + assigned > ch->kthreads_assigned_limit) {
+- needed = ch->kthreads_assigned_limit - assigned;
+- // >>>should never be less than 0
+- if (needed <= 0) {
+- return;
+- }
+- }
+-
+- dev_dbg(xpc_chan, "create %d new kthreads, partid=%d, channel=%d\n",
+- needed, ch->partid, ch->number);
+-
+- xpc_create_kthreads(ch, needed, 0);
+-}
+-
+-
+-/*
+- * This function is where XPC's kthreads wait for messages to deliver.
+- */
+-static void
+-xpc_kthread_waitmsgs(struct xpc_partition *part, struct xpc_channel *ch)
+-{
+- do {
+- /* deliver messages to their intended recipients */
+-
+- while ((volatile s64) ch->w_local_GP.get <
+- (volatile s64) ch->w_remote_GP.put &&
+- !((volatile u32) ch->flags &
+- XPC_C_DISCONNECTING)) {
+- xpc_deliver_msg(ch);
+- }
+-
+- if (atomic_inc_return(&ch->kthreads_idle) >
+- ch->kthreads_idle_limit) {
+- /* too many idle kthreads on this channel */
+- atomic_dec(&ch->kthreads_idle);
+- break;
+- }
+-
+- dev_dbg(xpc_chan, "idle kthread calling "
+- "wait_event_interruptible_exclusive()\n");
+-
+- (void) wait_event_interruptible_exclusive(ch->idle_wq,
+- ((volatile s64) ch->w_local_GP.get <
+- (volatile s64) ch->w_remote_GP.put ||
+- ((volatile u32) ch->flags &
+- XPC_C_DISCONNECTING)));
+-
+- atomic_dec(&ch->kthreads_idle);
+-
+- } while (!((volatile u32) ch->flags & XPC_C_DISCONNECTING));
+-}
+-
+-
+-static int
+-xpc_daemonize_kthread(void *args)
+-{
+- partid_t partid = XPC_UNPACK_ARG1(args);
+- u16 ch_number = XPC_UNPACK_ARG2(args);
+- struct xpc_partition *part = &xpc_partitions[partid];
+- struct xpc_channel *ch;
+- int n_needed;
+- unsigned long irq_flags;
+-
+-
+- daemonize("xpc%02dc%d", partid, ch_number);
+-
+- dev_dbg(xpc_chan, "kthread starting, partid=%d, channel=%d\n",
+- partid, ch_number);
+-
+- ch = &part->channels[ch_number];
+-
+- if (!(ch->flags & XPC_C_DISCONNECTING)) {
+-
+- /* let registerer know that connection has been established */
+-
+- spin_lock_irqsave(&ch->lock, irq_flags);
+- if (!(ch->flags & XPC_C_CONNECTEDCALLOUT)) {
+- ch->flags |= XPC_C_CONNECTEDCALLOUT;
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+-
+- xpc_connected_callout(ch);
+-
+- spin_lock_irqsave(&ch->lock, irq_flags);
+- ch->flags |= XPC_C_CONNECTEDCALLOUT_MADE;
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+-
+- /*
+- * It is possible that while the callout was being
+- * made that the remote partition sent some messages.
+- * If that is the case, we may need to activate
+- * additional kthreads to help deliver them. We only
+- * need one less than total #of messages to deliver.
+- */
+- n_needed = ch->w_remote_GP.put - ch->w_local_GP.get - 1;
+- if (n_needed > 0 &&
+- !(ch->flags & XPC_C_DISCONNECTING)) {
+- xpc_activate_kthreads(ch, n_needed);
+- }
+- } else {
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+- }
+-
+- xpc_kthread_waitmsgs(part, ch);
+- }
+-
+- /* let registerer know that connection is disconnecting */
+-
+- spin_lock_irqsave(&ch->lock, irq_flags);
+- if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
+- !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) {
+- ch->flags |= XPC_C_DISCONNECTINGCALLOUT;
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+-
+- xpc_disconnect_callout(ch, xpcDisconnecting);
+-
+- spin_lock_irqsave(&ch->lock, irq_flags);
+- ch->flags |= XPC_C_DISCONNECTINGCALLOUT_MADE;
+- }
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+-
+- if (atomic_dec_return(&ch->kthreads_assigned) == 0) {
+- if (atomic_dec_return(&part->nchannels_engaged) == 0) {
+- xpc_mark_partition_disengaged(part);
+- xpc_IPI_send_disengage(part);
+- }
+- }
+-
+- xpc_msgqueue_deref(ch);
+-
+- dev_dbg(xpc_chan, "kthread exiting, partid=%d, channel=%d\n",
+- partid, ch_number);
+-
+- xpc_part_deref(part);
+- return 0;
+-}
+-
+-
+-/*
+- * For each partition that XPC has established communications with, there is
+- * a minimum of one kernel thread assigned to perform any operation that
+- * may potentially sleep or block (basically the callouts to the asynchronous
+- * functions registered via xpc_connect()).
+- *
+- * Additional kthreads are created and destroyed by XPC as the workload
+- * demands.
+- *
+- * A kthread is assigned to one of the active channels that exists for a given
+- * partition.
+- */
+-void
+-xpc_create_kthreads(struct xpc_channel *ch, int needed,
+- int ignore_disconnecting)
+-{
+- unsigned long irq_flags;
+- pid_t pid;
+- u64 args = XPC_PACK_ARGS(ch->partid, ch->number);
+- struct xpc_partition *part = &xpc_partitions[ch->partid];
+-
+-
+- while (needed-- > 0) {
+-
+- /*
+- * The following is done on behalf of the newly created
+- * kthread. That kthread is responsible for doing the
+- * counterpart to the following before it exits.
+- */
+- if (ignore_disconnecting) {
+- if (!atomic_inc_not_zero(&ch->kthreads_assigned)) {
+- /* kthreads assigned had gone to zero */
+- BUG_ON(!(ch->flags &
+- XPC_C_DISCONNECTINGCALLOUT_MADE));
+- break;
+- }
+-
+- } else if (ch->flags & XPC_C_DISCONNECTING) {
+- break;
+-
+- } else if (atomic_inc_return(&ch->kthreads_assigned) == 1) {
+- if (atomic_inc_return(&part->nchannels_engaged) == 1)
+- xpc_mark_partition_engaged(part);
+- }
+- (void) xpc_part_ref(part);
+- xpc_msgqueue_ref(ch);
+-
+- pid = kernel_thread(xpc_daemonize_kthread, (void *) args, 0);
+- if (pid < 0) {
+- /* the fork failed */
+-
+- /*
+- * NOTE: if (ignore_disconnecting &&
+- * !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) is true,
+- * then we'll deadlock if all other kthreads assigned
+- * to this channel are blocked in the channel's
+- * registerer, because the only thing that will unblock
+- * them is the xpcDisconnecting callout that this
+- * failed kernel_thread would have made.
+- */
+-
+- if (atomic_dec_return(&ch->kthreads_assigned) == 0 &&
+- atomic_dec_return(&part->nchannels_engaged) == 0) {
+- xpc_mark_partition_disengaged(part);
+- xpc_IPI_send_disengage(part);
+- }
+- xpc_msgqueue_deref(ch);
+- xpc_part_deref(part);
+-
+- if (atomic_read(&ch->kthreads_assigned) <
+- ch->kthreads_idle_limit) {
+- /*
+- * Flag this as an error only if we have an
+- * insufficient #of kthreads for the channel
+- * to function.
+- */
+- spin_lock_irqsave(&ch->lock, irq_flags);
+- XPC_DISCONNECT_CHANNEL(ch, xpcLackOfResources,
+- &irq_flags);
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+- }
+- break;
+- }
+-
+- ch->kthreads_created++; // >>> temporary debug only!!!
+- }
+-}
+-
+-
+-void
+-xpc_disconnect_wait(int ch_number)
+-{
+- unsigned long irq_flags;
+- partid_t partid;
+- struct xpc_partition *part;
+- struct xpc_channel *ch;
+- int wakeup_channel_mgr;
+-
+-
+- /* now wait for all callouts to the caller's function to cease */
+- for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+- part = &xpc_partitions[partid];
+-
+- if (!xpc_part_ref(part)) {
+- continue;
+- }
+-
+- ch = &part->channels[ch_number];
+-
+- if (!(ch->flags & XPC_C_WDISCONNECT)) {
+- xpc_part_deref(part);
+- continue;
+- }
+-
+- wait_for_completion(&ch->wdisconnect_wait);
+-
+- spin_lock_irqsave(&ch->lock, irq_flags);
+- DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED));
+- wakeup_channel_mgr = 0;
+-
+- if (ch->delayed_IPI_flags) {
+- if (part->act_state != XPC_P_DEACTIVATING) {
+- spin_lock(&part->IPI_lock);
+- XPC_SET_IPI_FLAGS(part->local_IPI_amo,
+- ch->number, ch->delayed_IPI_flags);
+- spin_unlock(&part->IPI_lock);
+- wakeup_channel_mgr = 1;
+- }
+- ch->delayed_IPI_flags = 0;
+- }
+-
+- ch->flags &= ~XPC_C_WDISCONNECT;
+- spin_unlock_irqrestore(&ch->lock, irq_flags);
+-
+- if (wakeup_channel_mgr) {
+- xpc_wakeup_channel_mgr(part);
+- }
+-
+- xpc_part_deref(part);
+- }
+-}
+-
+-
+-static void
+-xpc_do_exit(enum xpc_retval reason)
+-{
+- partid_t partid;
+- int active_part_count, printed_waiting_msg = 0;
+- struct xpc_partition *part;
+- unsigned long printmsg_time, disengage_request_timeout = 0;
+-
+-
+- /* a 'rmmod XPC' and a 'reboot' cannot both end up here together */
+- DBUG_ON(xpc_exiting == 1);
+-
+- /*
+- * Let the heartbeat checker thread and the discovery thread
+- * (if one is running) know that they should exit. Also wake up
+- * the heartbeat checker thread in case it's sleeping.
+- */
+- xpc_exiting = 1;
+- wake_up_interruptible(&xpc_act_IRQ_wq);
+-
+- /* ignore all incoming interrupts */
+- free_irq(SGI_XPC_ACTIVATE, NULL);
+-
+- /* wait for the discovery thread to exit */
+- wait_for_completion(&xpc_discovery_exited);
+-
+- /* wait for the heartbeat checker thread to exit */
+- wait_for_completion(&xpc_hb_checker_exited);
+-
+-
+- /* sleep for a 1/3 of a second or so */
+- (void) msleep_interruptible(300);
+-
+-
+- /* wait for all partitions to become inactive */
+-
+- printmsg_time = jiffies + (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ);
+- xpc_disengage_request_timedout = 0;
+-
+- do {
+- active_part_count = 0;
+-
+- for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+- part = &xpc_partitions[partid];
+-
+- if (xpc_partition_disengaged(part) &&
+- part->act_state == XPC_P_INACTIVE) {
+- continue;
+- }
+-
+- active_part_count++;
+-
+- XPC_DEACTIVATE_PARTITION(part, reason);
+-
+- if (part->disengage_request_timeout >
+- disengage_request_timeout) {
+- disengage_request_timeout =
+- part->disengage_request_timeout;
+- }
+- }
+-
+- if (xpc_partition_engaged(-1UL)) {
+- if (time_after(jiffies, printmsg_time)) {
+- dev_info(xpc_part, "waiting for remote "
+- "partitions to disengage, timeout in "
+- "%ld seconds\n",
+- (disengage_request_timeout - jiffies)
+- / HZ);
+- printmsg_time = jiffies +
+- (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ);
+- printed_waiting_msg = 1;
+- }
+-
+- } else if (active_part_count > 0) {
+- if (printed_waiting_msg) {
+- dev_info(xpc_part, "waiting for local partition"
+- " to disengage\n");
+- printed_waiting_msg = 0;
+- }
+-
+- } else {
+- if (!xpc_disengage_request_timedout) {
+- dev_info(xpc_part, "all partitions have "
+- "disengaged\n");
+- }
+- break;
+- }
+-
+- /* sleep for a 1/3 of a second or so */
+- (void) msleep_interruptible(300);
+-
+- } while (1);
+-
+- DBUG_ON(xpc_partition_engaged(-1UL));
+-
+-
+- /* indicate to others that our reserved page is uninitialized */
+- xpc_rsvd_page->vars_pa = 0;
+-
+- /* now it's time to eliminate our heartbeat */
+- del_timer_sync(&xpc_hb_timer);
+- DBUG_ON(xpc_vars->heartbeating_to_mask != 0);
+-
+- if (reason == xpcUnloading) {
+- /* take ourselves off of the reboot_notifier_list */
+- (void) unregister_reboot_notifier(&xpc_reboot_notifier);
+-
+- /* take ourselves off of the die_notifier list */
+- (void) unregister_die_notifier(&xpc_die_notifier);
+- }
+-
+- /* close down protections for IPI operations */
+- xpc_restrict_IPI_ops();
+-
+-
+- /* clear the interface to XPC's functions */
+- xpc_clear_interface();
+-
+- if (xpc_sysctl) {
+- unregister_sysctl_table(xpc_sysctl);
+- }
+-
+- kfree(xpc_remote_copy_buffer_base);
+-}
+-
+-
+-/*
+- * This function is called when the system is being rebooted.
+- */
+-static int
+-xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused)
+-{
+- enum xpc_retval reason;
+-
+-
+- switch (event) {
+- case SYS_RESTART:
+- reason = xpcSystemReboot;
+- break;
+- case SYS_HALT:
+- reason = xpcSystemHalt;
+- break;
+- case SYS_POWER_OFF:
+- reason = xpcSystemPoweroff;
+- break;
+- default:
+- reason = xpcSystemGoingDown;
+- }
+-
+- xpc_do_exit(reason);
+- return NOTIFY_DONE;
+-}
+-
+-
+-/*
+- * Notify other partitions to disengage from all references to our memory.
+- */
+-static void
+-xpc_die_disengage(void)
+-{
+- struct xpc_partition *part;
+- partid_t partid;
+- unsigned long engaged;
+- long time, printmsg_time, disengage_request_timeout;
+-
+-
+- /* keep xpc_hb_checker thread from doing anything (just in case) */
+- xpc_exiting = 1;
+-
+- xpc_vars->heartbeating_to_mask = 0; /* indicate we're deactivated */
+-
+- for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+- part = &xpc_partitions[partid];
+-
+- if (!XPC_SUPPORTS_DISENGAGE_REQUEST(part->
+- remote_vars_version)) {
+-
+- /* just in case it was left set by an earlier XPC */
+- xpc_clear_partition_engaged(1UL << partid);
+- continue;
+- }
+-
+- if (xpc_partition_engaged(1UL << partid) ||
+- part->act_state != XPC_P_INACTIVE) {
+- xpc_request_partition_disengage(part);
+- xpc_mark_partition_disengaged(part);
+- xpc_IPI_send_disengage(part);
+- }
+- }
+-
+- time = rtc_time();
+- printmsg_time = time +
+- (XPC_DISENGAGE_PRINTMSG_INTERVAL * sn_rtc_cycles_per_second);
+- disengage_request_timeout = time +
+- (xpc_disengage_request_timelimit * sn_rtc_cycles_per_second);
+-
+- /* wait for all other partitions to disengage from us */
+-
+- while (1) {
+- engaged = xpc_partition_engaged(-1UL);
+- if (!engaged) {
+- dev_info(xpc_part, "all partitions have disengaged\n");
+- break;
+- }
+-
+- time = rtc_time();
+- if (time >= disengage_request_timeout) {
+- for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+- if (engaged & (1UL << partid)) {
+- dev_info(xpc_part, "disengage from "
+- "remote partition %d timed "
+- "out\n", partid);
+- }
+- }
+- break;
+- }
+-
+- if (time >= printmsg_time) {
+- dev_info(xpc_part, "waiting for remote partitions to "
+- "disengage, timeout in %ld seconds\n",
+- (disengage_request_timeout - time) /
+- sn_rtc_cycles_per_second);
+- printmsg_time = time +
+- (XPC_DISENGAGE_PRINTMSG_INTERVAL *
+- sn_rtc_cycles_per_second);
+- }
+- }
+-}
+-
+-
+-/*
+- * This function is called when the system is being restarted or halted due
+- * to some sort of system failure. If this is the case we need to notify the
+- * other partitions to disengage from all references to our memory.
+- * This function can also be called when our heartbeater could be offlined
+- * for a time. In this case we need to notify other partitions to not worry
+- * about the lack of a heartbeat.
+- */
+-static int
+-xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused)
+-{
+- switch (event) {
+- case DIE_MACHINE_RESTART:
+- case DIE_MACHINE_HALT:
+- xpc_die_disengage();
+- break;
+-
+- case DIE_KDEBUG_ENTER:
+- /* Should lack of heartbeat be ignored by other partitions? */
+- if (!xpc_kdebug_ignore) {
+- break;
+- }
+- /* fall through */
+- case DIE_MCA_MONARCH_ENTER:
+- case DIE_INIT_MONARCH_ENTER:
+- xpc_vars->heartbeat++;
+- xpc_vars->heartbeat_offline = 1;
+- break;
+-
+- case DIE_KDEBUG_LEAVE:
+- /* Is lack of heartbeat being ignored by other partitions? */
+- if (!xpc_kdebug_ignore) {
+- break;
+- }
+- /* fall through */
+- case DIE_MCA_MONARCH_LEAVE:
+- case DIE_INIT_MONARCH_LEAVE:
+- xpc_vars->heartbeat++;
+- xpc_vars->heartbeat_offline = 0;
+- break;
+- }
+-
+- return NOTIFY_DONE;
+-}
+-
+-
+-int __init
+-xpc_init(void)
+-{
+- int ret;
+- partid_t partid;
+- struct xpc_partition *part;
+- pid_t pid;
+- size_t buf_size;
+-
+-
+- if (!ia64_platform_is("sn2")) {
+- return -ENODEV;
+- }
+-
+-
+- buf_size = max(XPC_RP_VARS_SIZE,
+- XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES);
+- xpc_remote_copy_buffer = xpc_kmalloc_cacheline_aligned(buf_size,
+- GFP_KERNEL, &xpc_remote_copy_buffer_base);
+- if (xpc_remote_copy_buffer == NULL)
+- return -ENOMEM;
+-
+- snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part");
+- snprintf(xpc_chan->bus_id, BUS_ID_SIZE, "chan");
+-
+- xpc_sysctl = register_sysctl_table(xpc_sys_dir);
+-
+- /*
+- * The first few fields of each entry of xpc_partitions[] need to
+- * be initialized now so that calls to xpc_connect() and
+- * xpc_disconnect() can be made prior to the activation of any remote
+- * partition. NOTE THAT NONE OF THE OTHER FIELDS BELONGING TO THESE
+- * ENTRIES ARE MEANINGFUL UNTIL AFTER AN ENTRY'S CORRESPONDING
+- * PARTITION HAS BEEN ACTIVATED.
+- */
+- for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+- part = &xpc_partitions[partid];
+-
+- DBUG_ON((u64) part != L1_CACHE_ALIGN((u64) part));
+-
+- part->act_IRQ_rcvd = 0;
+- spin_lock_init(&part->act_lock);
+- part->act_state = XPC_P_INACTIVE;
+- XPC_SET_REASON(part, 0, 0);
+-
+- init_timer(&part->disengage_request_timer);
+- part->disengage_request_timer.function =
+- xpc_timeout_partition_disengage_request;
+- part->disengage_request_timer.data = (unsigned long) part;
+-
+- part->setup_state = XPC_P_UNSET;
+- init_waitqueue_head(&part->teardown_wq);
+- atomic_set(&part->references, 0);
+- }
+-
+- /*
+- * Open up protections for IPI operations (and AMO operations on
+- * Shub 1.1 systems).
+- */
+- xpc_allow_IPI_ops();
+-
+- /*
+- * Interrupts being processed will increment this atomic variable and
+- * awaken the heartbeat thread which will process the interrupts.
+- */
+- atomic_set(&xpc_act_IRQ_rcvd, 0);
+-
+- /*
+- * This is safe to do before the xpc_hb_checker thread has started
+- * because the handler releases a wait queue. If an interrupt is
+- * received before the thread is waiting, it will not go to sleep,
+- * but rather immediately process the interrupt.
+- */
+- ret = request_irq(SGI_XPC_ACTIVATE, xpc_act_IRQ_handler, 0,
+- "xpc hb", NULL);
+- if (ret != 0) {
+- dev_err(xpc_part, "can't register ACTIVATE IRQ handler, "
+- "errno=%d\n", -ret);
+-
+- xpc_restrict_IPI_ops();
+-
+- if (xpc_sysctl) {
+- unregister_sysctl_table(xpc_sysctl);
+- }
+-
+- kfree(xpc_remote_copy_buffer_base);
+- return -EBUSY;
+- }
+-
+- /*
+- * Fill the partition reserved page with the information needed by
+- * other partitions to discover we are alive and establish initial
+- * communications.
+- */
+- xpc_rsvd_page = xpc_rsvd_page_init();
+- if (xpc_rsvd_page == NULL) {
+- dev_err(xpc_part, "could not setup our reserved page\n");
+-
+- free_irq(SGI_XPC_ACTIVATE, NULL);
+- xpc_restrict_IPI_ops();
+-
+- if (xpc_sysctl) {
+- unregister_sysctl_table(xpc_sysctl);
+- }
+-
+- kfree(xpc_remote_copy_buffer_base);
+- return -EBUSY;
+- }
+-
+-
+- /* add ourselves to the reboot_notifier_list */
+- ret = register_reboot_notifier(&xpc_reboot_notifier);
+- if (ret != 0) {
+- dev_warn(xpc_part, "can't register reboot notifier\n");
+- }
+-
+- /* add ourselves to the die_notifier list */
+- ret = register_die_notifier(&xpc_die_notifier);
+- if (ret != 0) {
+- dev_warn(xpc_part, "can't register die notifier\n");
+- }
+-
+- init_timer(&xpc_hb_timer);
+- xpc_hb_timer.function = xpc_hb_beater;
+-
+- /*
+- * The real work-horse behind xpc. This processes incoming
+- * interrupts and monitors remote heartbeats.
+- */
+- pid = kernel_thread(xpc_hb_checker, NULL, 0);
+- if (pid < 0) {
+- dev_err(xpc_part, "failed while forking hb check thread\n");
+-
+- /* indicate to others that our reserved page is uninitialized */
+- xpc_rsvd_page->vars_pa = 0;
+-
+- /* take ourselves off of the reboot_notifier_list */
+- (void) unregister_reboot_notifier(&xpc_reboot_notifier);
+-
+- /* take ourselves off of the die_notifier list */
+- (void) unregister_die_notifier(&xpc_die_notifier);
+-
+- del_timer_sync(&xpc_hb_timer);
+- free_irq(SGI_XPC_ACTIVATE, NULL);
+- xpc_restrict_IPI_ops();
+-
+- if (xpc_sysctl) {
+- unregister_sysctl_table(xpc_sysctl);
+- }
+-
+- kfree(xpc_remote_copy_buffer_base);
+- return -EBUSY;
+- }
+-
+-
+- /*
+- * Startup a thread that will attempt to discover other partitions to
+- * activate based on info provided by SAL. This new thread is short
+- * lived and will exit once discovery is complete.
+- */
+- pid = kernel_thread(xpc_initiate_discovery, NULL, 0);
+- if (pid < 0) {
+- dev_err(xpc_part, "failed while forking discovery thread\n");
+-
+- /* mark this new thread as a non-starter */
+- complete(&xpc_discovery_exited);
+-
+- xpc_do_exit(xpcUnloading);
+- return -EBUSY;
+- }
+-
+-
+- /* set the interface to point at XPC's functions */
+- xpc_set_interface(xpc_initiate_connect, xpc_initiate_disconnect,
+- xpc_initiate_allocate, xpc_initiate_send,
+- xpc_initiate_send_notify, xpc_initiate_received,
+- xpc_initiate_partid_to_nasids);
+-
+- return 0;
+-}
+-module_init(xpc_init);
+-
+-
+-void __exit
+-xpc_exit(void)
+-{
+- xpc_do_exit(xpcUnloading);
+-}
+-module_exit(xpc_exit);
+-
+-
+-MODULE_AUTHOR("Silicon Graphics, Inc.");
+-MODULE_DESCRIPTION("Cross Partition Communication (XPC) support");
+-MODULE_LICENSE("GPL");
+-
+-module_param(xpc_hb_interval, int, 0);
+-MODULE_PARM_DESC(xpc_hb_interval, "Number of seconds between "
+- "heartbeat increments.");
+-
+-module_param(xpc_hb_check_interval, int, 0);
+-MODULE_PARM_DESC(xpc_hb_check_interval, "Number of seconds between "
+- "heartbeat checks.");
+-
+-module_param(xpc_disengage_request_timelimit, int, 0);
+-MODULE_PARM_DESC(xpc_disengage_request_timelimit, "Number of seconds to wait "
+- "for disengage request to complete.");
+-
+-module_param(xpc_kdebug_ignore, int, 0);
+-MODULE_PARM_DESC(xpc_kdebug_ignore, "Should lack of heartbeat be ignored by "
+- "other partitions when dropping into kdebug.");
+-
+diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c
+deleted file mode 100644
+index 7ba4032..0000000
+--- a/arch/ia64/sn/kernel/xpc_partition.c
++++ /dev/null
+@@ -1,1239 +0,0 @@
+-/*
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License. See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved.
+- */
+-
+-
+-/*
+- * Cross Partition Communication (XPC) partition support.
+- *
+- * This is the part of XPC that detects the presence/absence of
+- * other partitions. It provides a heartbeat and monitors the
+- * heartbeats of other partitions.
+- *
+- */
+-
+-
+-#include <linux/kernel.h>
+-#include <linux/sysctl.h>
+-#include <linux/cache.h>
+-#include <linux/mmzone.h>
+-#include <linux/nodemask.h>
+-#include <asm/uncached.h>
+-#include <asm/sn/bte.h>
+-#include <asm/sn/intr.h>
+-#include <asm/sn/sn_sal.h>
+-#include <asm/sn/nodepda.h>
+-#include <asm/sn/addrs.h>
+-#include <asm/sn/xpc.h>
+-
+-
+-/* XPC is exiting flag */
+-int xpc_exiting;
+-
+-
+-/* SH_IPI_ACCESS shub register value on startup */
+-static u64 xpc_sh1_IPI_access;
+-static u64 xpc_sh2_IPI_access0;
+-static u64 xpc_sh2_IPI_access1;
+-static u64 xpc_sh2_IPI_access2;
+-static u64 xpc_sh2_IPI_access3;
+-
+-
+-/* original protection values for each node */
+-u64 xpc_prot_vec[MAX_NUMNODES];
+-
+-
+-/* this partition's reserved page pointers */
+-struct xpc_rsvd_page *xpc_rsvd_page;
+-static u64 *xpc_part_nasids;
+-static u64 *xpc_mach_nasids;
+-struct xpc_vars *xpc_vars;
+-struct xpc_vars_part *xpc_vars_part;
+-
+-static int xp_nasid_mask_bytes; /* actual size in bytes of nasid mask */
+-static int xp_nasid_mask_words; /* actual size in words of nasid mask */
+-
+-
+-/*
+- * For performance reasons, each entry of xpc_partitions[] is cacheline
+- * aligned. And xpc_partitions[] is padded with an additional entry at the
+- * end so that the last legitimate entry doesn't share its cacheline with
+- * another variable.
+- */
+-struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1];
+-
+-
+-/*
+- * Generic buffer used to store a local copy of portions of a remote
+- * partition's reserved page (either its header and part_nasids mask,
+- * or its vars).
+- */
+-char *xpc_remote_copy_buffer;
+-void *xpc_remote_copy_buffer_base;
+-
+-
+-/*
+- * Guarantee that the kmalloc'd memory is cacheline aligned.
+- */
+-void *
+-xpc_kmalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
+-{
+- /* see if kmalloc will give us cachline aligned memory by default */
+- *base = kmalloc(size, flags);
+- if (*base == NULL) {
+- return NULL;
+- }
+- if ((u64) *base == L1_CACHE_ALIGN((u64) *base)) {
+- return *base;
+- }
+- kfree(*base);
+-
+- /* nope, we'll have to do it ourselves */
+- *base = kmalloc(size + L1_CACHE_BYTES, flags);
+- if (*base == NULL) {
+- return NULL;
+- }
+- return (void *) L1_CACHE_ALIGN((u64) *base);
+-}
+-
+-
+-/*
+- * Given a nasid, get the physical address of the partition's reserved page
+- * for that nasid. This function returns 0 on any error.
+- */
+-static u64
+-xpc_get_rsvd_page_pa(int nasid)
+-{
+- bte_result_t bte_res;
+- s64 status;
+- u64 cookie = 0;
+- u64 rp_pa = nasid; /* seed with nasid */
+- u64 len = 0;
+- u64 buf = buf;
+- u64 buf_len = 0;
+- void *buf_base = NULL;
+-
+-
+- while (1) {
+-
+- status = sn_partition_reserved_page_pa(buf, &cookie, &rp_pa,
+- &len);
+-
+- dev_dbg(xpc_part, "SAL returned with status=%li, cookie="
+- "0x%016lx, address=0x%016lx, len=0x%016lx\n",
+- status, cookie, rp_pa, len);
+-
+- if (status != SALRET_MORE_PASSES) {
+- break;
+- }
+-
+- if (L1_CACHE_ALIGN(len) > buf_len) {
+- kfree(buf_base);
+- buf_len = L1_CACHE_ALIGN(len);
+- buf = (u64) xpc_kmalloc_cacheline_aligned(buf_len,
+- GFP_KERNEL, &buf_base);
+- if (buf_base == NULL) {
+- dev_err(xpc_part, "unable to kmalloc "
+- "len=0x%016lx\n", buf_len);
+- status = SALRET_ERROR;
+- break;
+- }
+- }
+-
+- bte_res = xp_bte_copy(rp_pa, buf, buf_len,
+- (BTE_NOTIFY | BTE_WACQUIRE), NULL);
+- if (bte_res != BTE_SUCCESS) {
+- dev_dbg(xpc_part, "xp_bte_copy failed %i\n", bte_res);
+- status = SALRET_ERROR;
+- break;
+- }
+- }
+-
+- kfree(buf_base);
+-
+- if (status != SALRET_OK) {
+- rp_pa = 0;
+- }
+- dev_dbg(xpc_part, "reserved page at phys address 0x%016lx\n", rp_pa);
+- return rp_pa;
+-}
+-
+-
+-/*
+- * Fill the partition reserved page with the information needed by
+- * other partitions to discover we are alive and establish initial
+- * communications.
+- */
+-struct xpc_rsvd_page *
+-xpc_rsvd_page_init(void)
+-{
+- struct xpc_rsvd_page *rp;
+- AMO_t *amos_page;
+- u64 rp_pa, nasid_array = 0;
+- int i, ret;
+-
+-
+- /* get the local reserved page's address */
+-
+- preempt_disable();
+- rp_pa = xpc_get_rsvd_page_pa(cpuid_to_nasid(smp_processor_id()));
+- preempt_enable();
+- if (rp_pa == 0) {
+- dev_err(xpc_part, "SAL failed to locate the reserved page\n");
+- return NULL;
+- }
+- rp = (struct xpc_rsvd_page *) __va(rp_pa);
+-
+- if (rp->partid != sn_partition_id) {
+- dev_err(xpc_part, "the reserved page's partid of %d should be "
+- "%d\n", rp->partid, sn_partition_id);
+- return NULL;
+- }
+-
+- rp->version = XPC_RP_VERSION;
+-
+- /* establish the actual sizes of the nasid masks */
+- if (rp->SAL_version == 1) {
+- /* SAL_version 1 didn't set the nasids_size field */
+- rp->nasids_size = 128;
+- }
+- xp_nasid_mask_bytes = rp->nasids_size;
+- xp_nasid_mask_words = xp_nasid_mask_bytes / 8;
+-
+- /* setup the pointers to the various items in the reserved page */
+- xpc_part_nasids = XPC_RP_PART_NASIDS(rp);
+- xpc_mach_nasids = XPC_RP_MACH_NASIDS(rp);
+- xpc_vars = XPC_RP_VARS(rp);
+- xpc_vars_part = XPC_RP_VARS_PART(rp);
+-
+- /*
+- * Before clearing xpc_vars, see if a page of AMOs had been previously
+- * allocated. If not we'll need to allocate one and set permissions
+- * so that cross-partition AMOs are allowed.
+- *
+- * The allocated AMO page needs MCA reporting to remain disabled after
+- * XPC has unloaded. To make this work, we keep a copy of the pointer
+- * to this page (i.e., amos_page) in the struct xpc_vars structure,
+- * which is pointed to by the reserved page, and re-use that saved copy
+- * on subsequent loads of XPC. This AMO page is never freed, and its
+- * memory protections are never restricted.
+- */
+- if ((amos_page = xpc_vars->amos_page) == NULL) {
+- amos_page = (AMO_t *) TO_AMO(uncached_alloc_page(0));
+- if (amos_page == NULL) {
+- dev_err(xpc_part, "can't allocate page of AMOs\n");
+- return NULL;
+- }
+-
+- /*
+- * Open up AMO-R/W to cpu. This is done for Shub 1.1 systems
+- * when xpc_allow_IPI_ops() is called via xpc_hb_init().
+- */
+- if (!enable_shub_wars_1_1()) {
+- ret = sn_change_memprotect(ia64_tpa((u64) amos_page),
+- PAGE_SIZE, SN_MEMPROT_ACCESS_CLASS_1,
+- &nasid_array);
+- if (ret != 0) {
+- dev_err(xpc_part, "can't change memory "
+- "protections\n");
+- uncached_free_page(__IA64_UNCACHED_OFFSET |
+- TO_PHYS((u64) amos_page));
+- return NULL;
+- }
+- }
+- } else if (!IS_AMO_ADDRESS((u64) amos_page)) {
+- /*
+- * EFI's XPBOOT can also set amos_page in the reserved page,
+- * but it happens to leave it as an uncached physical address
+- * and we need it to be an uncached virtual, so we'll have to
+- * convert it.
+- */
+- if (!IS_AMO_PHYS_ADDRESS((u64) amos_page)) {
+- dev_err(xpc_part, "previously used amos_page address "
+- "is bad = 0x%p\n", (void *) amos_page);
+- return NULL;
+- }
+- amos_page = (AMO_t *) TO_AMO((u64) amos_page);
+- }
+-
+- /* clear xpc_vars */
+- memset(xpc_vars, 0, sizeof(struct xpc_vars));
+-
+- xpc_vars->version = XPC_V_VERSION;
+- xpc_vars->act_nasid = cpuid_to_nasid(0);
+- xpc_vars->act_phys_cpuid = cpu_physical_id(0);
+- xpc_vars->vars_part_pa = __pa(xpc_vars_part);
+- xpc_vars->amos_page_pa = ia64_tpa((u64) amos_page);
+- xpc_vars->amos_page = amos_page; /* save for next load of XPC */
+-
+-
+- /* clear xpc_vars_part */
+- memset((u64 *) xpc_vars_part, 0, sizeof(struct xpc_vars_part) *
+- XP_MAX_PARTITIONS);
+-
+- /* initialize the activate IRQ related AMO variables */
+- for (i = 0; i < xp_nasid_mask_words; i++) {
+- (void) xpc_IPI_init(XPC_ACTIVATE_IRQ_AMOS + i);
+- }
+-
+- /* initialize the engaged remote partitions related AMO variables */
+- (void) xpc_IPI_init(XPC_ENGAGED_PARTITIONS_AMO);
+- (void) xpc_IPI_init(XPC_DISENGAGE_REQUEST_AMO);
+-
+- /* timestamp of when reserved page was setup by XPC */
+- rp->stamp = CURRENT_TIME;
+-
+- /*
+- * This signifies to the remote partition that our reserved
+- * page is initialized.
+- */
+- rp->vars_pa = __pa(xpc_vars);
+-
+- return rp;
+-}
+-
+-
+-/*
+- * Change protections to allow IPI operations (and AMO operations on
+- * Shub 1.1 systems).
+- */
+-void
+-xpc_allow_IPI_ops(void)
+-{
+- int node;
+- int nasid;
+-
+-
+- // >>> Change SH_IPI_ACCESS code to use SAL call once it is available.
+-
+- if (is_shub2()) {
+- xpc_sh2_IPI_access0 =
+- (u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH2_IPI_ACCESS0));
+- xpc_sh2_IPI_access1 =
+- (u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH2_IPI_ACCESS1));
+- xpc_sh2_IPI_access2 =
+- (u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH2_IPI_ACCESS2));
+- xpc_sh2_IPI_access3 =
+- (u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH2_IPI_ACCESS3));
+-
+- for_each_online_node(node) {
+- nasid = cnodeid_to_nasid(node);
+- HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS0),
+- -1UL);
+- HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS1),
+- -1UL);
+- HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS2),
+- -1UL);
+- HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS3),
+- -1UL);
+- }
+-
+- } else {
+- xpc_sh1_IPI_access =
+- (u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH1_IPI_ACCESS));
+-
+- for_each_online_node(node) {
+- nasid = cnodeid_to_nasid(node);
+- HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH1_IPI_ACCESS),
+- -1UL);
+-
+- /*
+- * Since the BIST collides with memory operations on
+- * SHUB 1.1 sn_change_memprotect() cannot be used.
+- */
+- if (enable_shub_wars_1_1()) {
+- /* open up everything */
+- xpc_prot_vec[node] = (u64) HUB_L((u64 *)
+- GLOBAL_MMR_ADDR(nasid,
+- SH1_MD_DQLP_MMR_DIR_PRIVEC0));
+- HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid,
+- SH1_MD_DQLP_MMR_DIR_PRIVEC0),
+- -1UL);
+- HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid,
+- SH1_MD_DQRP_MMR_DIR_PRIVEC0),
+- -1UL);
+- }
+- }
+- }
+-}
+-
+-
+-/*
+- * Restrict protections to disallow IPI operations (and AMO operations on
+- * Shub 1.1 systems).
+- */
+-void
+-xpc_restrict_IPI_ops(void)
+-{
+- int node;
+- int nasid;
+-
+-
+- // >>> Change SH_IPI_ACCESS code to use SAL call once it is available.
+-
+- if (is_shub2()) {
+-
+- for_each_online_node(node) {
+- nasid = cnodeid_to_nasid(node);
+- HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS0),
+- xpc_sh2_IPI_access0);
+- HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS1),
+- xpc_sh2_IPI_access1);
+- HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS2),
+- xpc_sh2_IPI_access2);
+- HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS3),
+- xpc_sh2_IPI_access3);
+- }
+-
+- } else {
+-
+- for_each_online_node(node) {
+- nasid = cnodeid_to_nasid(node);
+- HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH1_IPI_ACCESS),
+- xpc_sh1_IPI_access);
+-
+- if (enable_shub_wars_1_1()) {
+- HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid,
+- SH1_MD_DQLP_MMR_DIR_PRIVEC0),
+- xpc_prot_vec[node]);
+- HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid,
+- SH1_MD_DQRP_MMR_DIR_PRIVEC0),
+- xpc_prot_vec[node]);
+- }
+- }
+- }
+-}
+-
+-
+-/*
+- * At periodic intervals, scan through all active partitions and ensure
+- * their heartbeat is still active. If not, the partition is deactivated.
+- */
+-void
+-xpc_check_remote_hb(void)
+-{
+- struct xpc_vars *remote_vars;
+- struct xpc_partition *part;
+- partid_t partid;
+- bte_result_t bres;
+-
+-
+- remote_vars = (struct xpc_vars *) xpc_remote_copy_buffer;
+-
+- for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+-
+- if (xpc_exiting) {
+- break;
+- }
+-
+- if (partid == sn_partition_id) {
+- continue;
+- }
+-
+- part = &xpc_partitions[partid];
+-
+- if (part->act_state == XPC_P_INACTIVE ||
+- part->act_state == XPC_P_DEACTIVATING) {
+- continue;
+- }
+-
+- /* pull the remote_hb cache line */
+- bres = xp_bte_copy(part->remote_vars_pa,
+- (u64) remote_vars,
+- XPC_RP_VARS_SIZE,
+- (BTE_NOTIFY | BTE_WACQUIRE), NULL);
+- if (bres != BTE_SUCCESS) {
+- XPC_DEACTIVATE_PARTITION(part,
+- xpc_map_bte_errors(bres));
+- continue;
+- }
+-
+- dev_dbg(xpc_part, "partid = %d, heartbeat = %ld, last_heartbeat"
+- " = %ld, heartbeat_offline = %ld, HB_mask = 0x%lx\n",
+- partid, remote_vars->heartbeat, part->last_heartbeat,
+- remote_vars->heartbeat_offline,
+- remote_vars->heartbeating_to_mask);
+-
+- if (((remote_vars->heartbeat == part->last_heartbeat) &&
+- (remote_vars->heartbeat_offline == 0)) ||
+- !xpc_hb_allowed(sn_partition_id, remote_vars)) {
+-
+- XPC_DEACTIVATE_PARTITION(part, xpcNoHeartbeat);
+- continue;
+- }
+-
+- part->last_heartbeat = remote_vars->heartbeat;
+- }
+-}
+-
+-
+-/*
+- * Get a copy of a portion of the remote partition's rsvd page.
+- *
+- * remote_rp points to a buffer that is cacheline aligned for BTE copies and
+- * is large enough to contain a copy of their reserved page header and
+- * part_nasids mask.
+- */
+-static enum xpc_retval
+-xpc_get_remote_rp(int nasid, u64 *discovered_nasids,
+- struct xpc_rsvd_page *remote_rp, u64 *remote_rp_pa)
+-{
+- int bres, i;
+-
+-
+- /* get the reserved page's physical address */
+-
+- *remote_rp_pa = xpc_get_rsvd_page_pa(nasid);
+- if (*remote_rp_pa == 0) {
+- return xpcNoRsvdPageAddr;
+- }
+-
+-
+- /* pull over the reserved page header and part_nasids mask */
+- bres = xp_bte_copy(*remote_rp_pa, (u64) remote_rp,
+- XPC_RP_HEADER_SIZE + xp_nasid_mask_bytes,
+- (BTE_NOTIFY | BTE_WACQUIRE), NULL);
+- if (bres != BTE_SUCCESS) {
+- return xpc_map_bte_errors(bres);
+- }
+-
+-
+- if (discovered_nasids != NULL) {
+- u64 *remote_part_nasids = XPC_RP_PART_NASIDS(remote_rp);
+-
+-
+- for (i = 0; i < xp_nasid_mask_words; i++) {
+- discovered_nasids[i] |= remote_part_nasids[i];
+- }
+- }
+-
+-
+- /* check that the partid is for another partition */
+-
+- if (remote_rp->partid < 1 ||
+- remote_rp->partid > (XP_MAX_PARTITIONS - 1)) {
+- return xpcInvalidPartid;
+- }
+-
+- if (remote_rp->partid == sn_partition_id) {
+- return xpcLocalPartid;
+- }
+-
+-
+- if (XPC_VERSION_MAJOR(remote_rp->version) !=
+- XPC_VERSION_MAJOR(XPC_RP_VERSION)) {
+- return xpcBadVersion;
+- }
+-
+- return xpcSuccess;
+-}
+-
+-
+-/*
+- * Get a copy of the remote partition's XPC variables from the reserved page.
+- *
+- * remote_vars points to a buffer that is cacheline aligned for BTE copies and
+- * assumed to be of size XPC_RP_VARS_SIZE.
+- */
+-static enum xpc_retval
+-xpc_get_remote_vars(u64 remote_vars_pa, struct xpc_vars *remote_vars)
+-{
+- int bres;
+-
+-
+- if (remote_vars_pa == 0) {
+- return xpcVarsNotSet;
+- }
+-
+- /* pull over the cross partition variables */
+- bres = xp_bte_copy(remote_vars_pa, (u64) remote_vars, XPC_RP_VARS_SIZE,
+- (BTE_NOTIFY | BTE_WACQUIRE), NULL);
+- if (bres != BTE_SUCCESS) {
+- return xpc_map_bte_errors(bres);
+- }
+-
+- if (XPC_VERSION_MAJOR(remote_vars->version) !=
+- XPC_VERSION_MAJOR(XPC_V_VERSION)) {
+- return xpcBadVersion;
+- }
+-
+- return xpcSuccess;
+-}
+-
+-
+-/*
+- * Update the remote partition's info.
+- */
+-static void
+-xpc_update_partition_info(struct xpc_partition *part, u8 remote_rp_version,
+- struct timespec *remote_rp_stamp, u64 remote_rp_pa,
+- u64 remote_vars_pa, struct xpc_vars *remote_vars)
+-{
+- part->remote_rp_version = remote_rp_version;
+- dev_dbg(xpc_part, " remote_rp_version = 0x%016x\n",
+- part->remote_rp_version);
+-
+- part->remote_rp_stamp = *remote_rp_stamp;
+- dev_dbg(xpc_part, " remote_rp_stamp (tv_sec = 0x%lx tv_nsec = 0x%lx\n",
+- part->remote_rp_stamp.tv_sec, part->remote_rp_stamp.tv_nsec);
+-
+- part->remote_rp_pa = remote_rp_pa;
+- dev_dbg(xpc_part, " remote_rp_pa = 0x%016lx\n", part->remote_rp_pa);
+-
+- part->remote_vars_pa = remote_vars_pa;
+- dev_dbg(xpc_part, " remote_vars_pa = 0x%016lx\n",
+- part->remote_vars_pa);
+-
+- part->last_heartbeat = remote_vars->heartbeat;
+- dev_dbg(xpc_part, " last_heartbeat = 0x%016lx\n",
+- part->last_heartbeat);
+-
+- part->remote_vars_part_pa = remote_vars->vars_part_pa;
+- dev_dbg(xpc_part, " remote_vars_part_pa = 0x%016lx\n",
+- part->remote_vars_part_pa);
+-
+- part->remote_act_nasid = remote_vars->act_nasid;
+- dev_dbg(xpc_part, " remote_act_nasid = 0x%x\n",
+- part->remote_act_nasid);
+-
+- part->remote_act_phys_cpuid = remote_vars->act_phys_cpuid;
+- dev_dbg(xpc_part, " remote_act_phys_cpuid = 0x%x\n",
+- part->remote_act_phys_cpuid);
+-
+- part->remote_amos_page_pa = remote_vars->amos_page_pa;
+- dev_dbg(xpc_part, " remote_amos_page_pa = 0x%lx\n",
+- part->remote_amos_page_pa);
+-
+- part->remote_vars_version = remote_vars->version;
+- dev_dbg(xpc_part, " remote_vars_version = 0x%x\n",
+- part->remote_vars_version);
+-}
+-
+-
+-/*
+- * Prior code has determined the nasid which generated an IPI. Inspect
+- * that nasid to determine if its partition needs to be activated or
+- * deactivated.
+- *
+- * A partition is consider "awaiting activation" if our partition
+- * flags indicate it is not active and it has a heartbeat. A
+- * partition is considered "awaiting deactivation" if our partition
+- * flags indicate it is active but it has no heartbeat or it is not
+- * sending its heartbeat to us.
+- *
+- * To determine the heartbeat, the remote nasid must have a properly
+- * initialized reserved page.
+- */
+-static void
+-xpc_identify_act_IRQ_req(int nasid)
+-{
+- struct xpc_rsvd_page *remote_rp;
+- struct xpc_vars *remote_vars;
+- u64 remote_rp_pa;
+- u64 remote_vars_pa;
+- int remote_rp_version;
+- int reactivate = 0;
+- int stamp_diff;
+- struct timespec remote_rp_stamp = { 0, 0 };
+- partid_t partid;
+- struct xpc_partition *part;
+- enum xpc_retval ret;
+-
+-
+- /* pull over the reserved page structure */
+-
+- remote_rp = (struct xpc_rsvd_page *) xpc_remote_copy_buffer;
+-
+- ret = xpc_get_remote_rp(nasid, NULL, remote_rp, &remote_rp_pa);
+- if (ret != xpcSuccess) {
+- dev_warn(xpc_part, "unable to get reserved page from nasid %d, "
+- "which sent interrupt, reason=%d\n", nasid, ret);
+- return;
+- }
+-
+- remote_vars_pa = remote_rp->vars_pa;
+- remote_rp_version = remote_rp->version;
+- if (XPC_SUPPORTS_RP_STAMP(remote_rp_version)) {
+- remote_rp_stamp = remote_rp->stamp;
+- }
+- partid = remote_rp->partid;
+- part = &xpc_partitions[partid];
+-
+-
+- /* pull over the cross partition variables */
+-
+- remote_vars = (struct xpc_vars *) xpc_remote_copy_buffer;
+-
+- ret = xpc_get_remote_vars(remote_vars_pa, remote_vars);
+- if (ret != xpcSuccess) {
+-
+- dev_warn(xpc_part, "unable to get XPC variables from nasid %d, "
+- "which sent interrupt, reason=%d\n", nasid, ret);
+-
+- XPC_DEACTIVATE_PARTITION(part, ret);
+- return;
+- }
+-
+-
+- part->act_IRQ_rcvd++;
+-
+- dev_dbg(xpc_part, "partid for nasid %d is %d; IRQs = %d; HB = "
+- "%ld:0x%lx\n", (int) nasid, (int) partid, part->act_IRQ_rcvd,
+- remote_vars->heartbeat, remote_vars->heartbeating_to_mask);
+-
+- if (xpc_partition_disengaged(part) &&
+- part->act_state == XPC_P_INACTIVE) {
+-
+- xpc_update_partition_info(part, remote_rp_version,
+- &remote_rp_stamp, remote_rp_pa,
+- remote_vars_pa, remote_vars);
+-
+- if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version)) {
+- if (xpc_partition_disengage_requested(1UL << partid)) {
+- /*
+- * Other side is waiting on us to disengage,
+- * even though we already have.
+- */
+- return;
+- }
+- } else {
+- /* other side doesn't support disengage requests */
+- xpc_clear_partition_disengage_request(1UL << partid);
+- }
+-
+- xpc_activate_partition(part);
+- return;
+- }
+-
+- DBUG_ON(part->remote_rp_version == 0);
+- DBUG_ON(part->remote_vars_version == 0);
+-
+- if (!XPC_SUPPORTS_RP_STAMP(part->remote_rp_version)) {
+- DBUG_ON(XPC_SUPPORTS_DISENGAGE_REQUEST(part->
+- remote_vars_version));
+-
+- if (!XPC_SUPPORTS_RP_STAMP(remote_rp_version)) {
+- DBUG_ON(XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->
+- version));
+- /* see if the other side rebooted */
+- if (part->remote_amos_page_pa ==
+- remote_vars->amos_page_pa &&
+- xpc_hb_allowed(sn_partition_id,
+- remote_vars)) {
+- /* doesn't look that way, so ignore the IPI */
+- return;
+- }
+- }
+-
+- /*
+- * Other side rebooted and previous XPC didn't support the
+- * disengage request, so we don't need to do anything special.
+- */
+-
+- xpc_update_partition_info(part, remote_rp_version,
+- &remote_rp_stamp, remote_rp_pa,
+- remote_vars_pa, remote_vars);
+- part->reactivate_nasid = nasid;
+- XPC_DEACTIVATE_PARTITION(part, xpcReactivating);
+- return;
+- }
+-
+- DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version));
+-
+- if (!XPC_SUPPORTS_RP_STAMP(remote_rp_version)) {
+- DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->version));
+-
+- /*
+- * Other side rebooted and previous XPC did support the
+- * disengage request, but the new one doesn't.
+- */
+-
+- xpc_clear_partition_engaged(1UL << partid);
+- xpc_clear_partition_disengage_request(1UL << partid);
+-
+- xpc_update_partition_info(part, remote_rp_version,
+- &remote_rp_stamp, remote_rp_pa,
+- remote_vars_pa, remote_vars);
+- reactivate = 1;
+-
+- } else {
+- DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->version));
+-
+- stamp_diff = xpc_compare_stamps(&part->remote_rp_stamp,
+- &remote_rp_stamp);
+- if (stamp_diff != 0) {
+- DBUG_ON(stamp_diff >= 0);
+-
+- /*
+- * Other side rebooted and the previous XPC did support
+- * the disengage request, as does the new one.
+- */
+-
+- DBUG_ON(xpc_partition_engaged(1UL << partid));
+- DBUG_ON(xpc_partition_disengage_requested(1UL <<
+- partid));
+-
+- xpc_update_partition_info(part, remote_rp_version,
+- &remote_rp_stamp, remote_rp_pa,
+- remote_vars_pa, remote_vars);
+- reactivate = 1;
+- }
+- }
+-
+- if (part->disengage_request_timeout > 0 &&
+- !xpc_partition_disengaged(part)) {
+- /* still waiting on other side to disengage from us */
+- return;
+- }
+-
+- if (reactivate) {
+- part->reactivate_nasid = nasid;
+- XPC_DEACTIVATE_PARTITION(part, xpcReactivating);
+-
+- } else if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version) &&
+- xpc_partition_disengage_requested(1UL << partid)) {
+- XPC_DEACTIVATE_PARTITION(part, xpcOtherGoingDown);
+- }
+-}
+-
+-
+-/*
+- * Loop through the activation AMO variables and process any bits
+- * which are set. Each bit indicates a nasid sending a partition
+- * activation or deactivation request.
+- *
+- * Return #of IRQs detected.
+- */
+-int
+-xpc_identify_act_IRQ_sender(void)
+-{
+- int word, bit;
+- u64 nasid_mask;
+- u64 nasid; /* remote nasid */
+- int n_IRQs_detected = 0;
+- AMO_t *act_amos;
+-
+-
+- act_amos = xpc_vars->amos_page + XPC_ACTIVATE_IRQ_AMOS;
+-
+-
+- /* scan through act AMO variable looking for non-zero entries */
+- for (word = 0; word < xp_nasid_mask_words; word++) {
+-
+- if (xpc_exiting) {
+- break;
+- }
+-
+- nasid_mask = xpc_IPI_receive(&act_amos[word]);
+- if (nasid_mask == 0) {
+- /* no IRQs from nasids in this variable */
+- continue;
+- }
+-
+- dev_dbg(xpc_part, "AMO[%d] gave back 0x%lx\n", word,
+- nasid_mask);
+-
+-
+- /*
+- * If this nasid has been added to the machine since
+- * our partition was reset, this will retain the
+- * remote nasid in our reserved pages machine mask.
+- * This is used in the event of module reload.
+- */
+- xpc_mach_nasids[word] |= nasid_mask;
+-
+-
+- /* locate the nasid(s) which sent interrupts */
+-
+- for (bit = 0; bit < (8 * sizeof(u64)); bit++) {
+- if (nasid_mask & (1UL << bit)) {
+- n_IRQs_detected++;
+- nasid = XPC_NASID_FROM_W_B(word, bit);
+- dev_dbg(xpc_part, "interrupt from nasid %ld\n",
+- nasid);
+- xpc_identify_act_IRQ_req(nasid);
+- }
+- }
+- }
+- return n_IRQs_detected;
+-}
+-
+-
+-/*
+- * See if the other side has responded to a partition disengage request
+- * from us.
+- */
+-int
+-xpc_partition_disengaged(struct xpc_partition *part)
+-{
+- partid_t partid = XPC_PARTID(part);
+- int disengaged;
+-
+-
+- disengaged = (xpc_partition_engaged(1UL << partid) == 0);
+- if (part->disengage_request_timeout) {
+- if (!disengaged) {
+- if (jiffies < part->disengage_request_timeout) {
+- /* timelimit hasn't been reached yet */
+- return 0;
+- }
+-
+- /*
+- * Other side hasn't responded to our disengage
+- * request in a timely fashion, so assume it's dead.
+- */
+-
+- dev_info(xpc_part, "disengage from remote partition %d "
+- "timed out\n", partid);
+- xpc_disengage_request_timedout = 1;
+- xpc_clear_partition_engaged(1UL << partid);
+- disengaged = 1;
+- }
+- part->disengage_request_timeout = 0;
+-
+- /* cancel the timer function, provided it's not us */
+- if (!in_interrupt()) {
+- del_singleshot_timer_sync(&part->
+- disengage_request_timer);
+- }
+-
+- DBUG_ON(part->act_state != XPC_P_DEACTIVATING &&
+- part->act_state != XPC_P_INACTIVE);
+- if (part->act_state != XPC_P_INACTIVE) {
+- xpc_wakeup_channel_mgr(part);
+- }
+-
+- if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version)) {
+- xpc_cancel_partition_disengage_request(part);
+- }
+- }
+- return disengaged;
+-}
+-
+-
+-/*
+- * Mark specified partition as active.
+- */
+-enum xpc_retval
+-xpc_mark_partition_active(struct xpc_partition *part)
+-{
+- unsigned long irq_flags;
+- enum xpc_retval ret;
+-
+-
+- dev_dbg(xpc_part, "setting partition %d to ACTIVE\n", XPC_PARTID(part));
+-
+- spin_lock_irqsave(&part->act_lock, irq_flags);
+- if (part->act_state == XPC_P_ACTIVATING) {
+- part->act_state = XPC_P_ACTIVE;
+- ret = xpcSuccess;
+- } else {
+- DBUG_ON(part->reason == xpcSuccess);
+- ret = part->reason;
+- }
+- spin_unlock_irqrestore(&part->act_lock, irq_flags);
+-
+- return ret;
+-}
+-
+-
+-/*
+- * Notify XPC that the partition is down.
+- */
+-void
+-xpc_deactivate_partition(const int line, struct xpc_partition *part,
+- enum xpc_retval reason)
+-{
+- unsigned long irq_flags;
+-
+-
+- spin_lock_irqsave(&part->act_lock, irq_flags);
+-
+- if (part->act_state == XPC_P_INACTIVE) {
+- XPC_SET_REASON(part, reason, line);
+- spin_unlock_irqrestore(&part->act_lock, irq_flags);
+- if (reason == xpcReactivating) {
+- /* we interrupt ourselves to reactivate partition */
+- xpc_IPI_send_reactivate(part);
+- }
+- return;
+- }
+- if (part->act_state == XPC_P_DEACTIVATING) {
+- if ((part->reason == xpcUnloading && reason != xpcUnloading) ||
+- reason == xpcReactivating) {
+- XPC_SET_REASON(part, reason, line);
+- }
+- spin_unlock_irqrestore(&part->act_lock, irq_flags);
+- return;
+- }
+-
+- part->act_state = XPC_P_DEACTIVATING;
+- XPC_SET_REASON(part, reason, line);
+-
+- spin_unlock_irqrestore(&part->act_lock, irq_flags);
+-
+- if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version)) {
+- xpc_request_partition_disengage(part);
+- xpc_IPI_send_disengage(part);
+-
+- /* set a timelimit on the disengage request */
+- part->disengage_request_timeout = jiffies +
+- (xpc_disengage_request_timelimit * HZ);
+- part->disengage_request_timer.expires =
+- part->disengage_request_timeout;
+- add_timer(&part->disengage_request_timer);
+- }
+-
+- dev_dbg(xpc_part, "bringing partition %d down, reason = %d\n",
+- XPC_PARTID(part), reason);
+-
+- xpc_partition_going_down(part, reason);
+-}
+-
+-
+-/*
+- * Mark specified partition as inactive.
+- */
+-void
+-xpc_mark_partition_inactive(struct xpc_partition *part)
+-{
+- unsigned long irq_flags;
+-
+-
+- dev_dbg(xpc_part, "setting partition %d to INACTIVE\n",
+- XPC_PARTID(part));
+-
+- spin_lock_irqsave(&part->act_lock, irq_flags);
+- part->act_state = XPC_P_INACTIVE;
+- spin_unlock_irqrestore(&part->act_lock, irq_flags);
+- part->remote_rp_pa = 0;
+-}
+-
+-
+-/*
+- * SAL has provided a partition and machine mask. The partition mask
+- * contains a bit for each even nasid in our partition. The machine
+- * mask contains a bit for each even nasid in the entire machine.
+- *
+- * Using those two bit arrays, we can determine which nasids are
+- * known in the machine. Each should also have a reserved page
+- * initialized if they are available for partitioning.
+- */
+-void
+-xpc_discovery(void)
+-{
+- void *remote_rp_base;
+- struct xpc_rsvd_page *remote_rp;
+- struct xpc_vars *remote_vars;
+- u64 remote_rp_pa;
+- u64 remote_vars_pa;
+- int region;
+- int region_size;
+- int max_regions;
+- int nasid;
+- struct xpc_rsvd_page *rp;
+- partid_t partid;
+- struct xpc_partition *part;
+- u64 *discovered_nasids;
+- enum xpc_retval ret;
+-
+-
+- remote_rp = xpc_kmalloc_cacheline_aligned(XPC_RP_HEADER_SIZE +
+- xp_nasid_mask_bytes,
+- GFP_KERNEL, &remote_rp_base);
+- if (remote_rp == NULL) {
+- return;
+- }
+- remote_vars = (struct xpc_vars *) remote_rp;
+-
+-
+- discovered_nasids = kzalloc(sizeof(u64) * xp_nasid_mask_words,
+- GFP_KERNEL);
+- if (discovered_nasids == NULL) {
+- kfree(remote_rp_base);
+- return;
+- }
+-
+- rp = (struct xpc_rsvd_page *) xpc_rsvd_page;
+-
+- /*
+- * The term 'region' in this context refers to the minimum number of
+- * nodes that can comprise an access protection grouping. The access
+- * protection is in regards to memory, IOI and IPI.
+- */
+- max_regions = 64;
+- region_size = sn_region_size;
+-
+- switch (region_size) {
+- case 128:
+- max_regions *= 2;
+- case 64:
+- max_regions *= 2;
+- case 32:
+- max_regions *= 2;
+- region_size = 16;
+- DBUG_ON(!is_shub2());
+- }
+-
+- for (region = 0; region < max_regions; region++) {
+-
+- if ((volatile int) xpc_exiting) {
+- break;
+- }
+-
+- dev_dbg(xpc_part, "searching region %d\n", region);
+-
+- for (nasid = (region * region_size * 2);
+- nasid < ((region + 1) * region_size * 2);
+- nasid += 2) {
+-
+- if ((volatile int) xpc_exiting) {
+- break;
+- }
+-
+- dev_dbg(xpc_part, "checking nasid %d\n", nasid);
+-
+-
+- if (XPC_NASID_IN_ARRAY(nasid, xpc_part_nasids)) {
+- dev_dbg(xpc_part, "PROM indicates Nasid %d is "
+- "part of the local partition; skipping "
+- "region\n", nasid);
+- break;
+- }
+-
+- if (!(XPC_NASID_IN_ARRAY(nasid, xpc_mach_nasids))) {
+- dev_dbg(xpc_part, "PROM indicates Nasid %d was "
+- "not on Numa-Link network at reset\n",
+- nasid);
+- continue;
+- }
+-
+- if (XPC_NASID_IN_ARRAY(nasid, discovered_nasids)) {
+- dev_dbg(xpc_part, "Nasid %d is part of a "
+- "partition which was previously "
+- "discovered\n", nasid);
+- continue;
+- }
+-
+-
+- /* pull over the reserved page structure */
+-
+- ret = xpc_get_remote_rp(nasid, discovered_nasids,
+- remote_rp, &remote_rp_pa);
+- if (ret != xpcSuccess) {
+- dev_dbg(xpc_part, "unable to get reserved page "
+- "from nasid %d, reason=%d\n", nasid,
+- ret);
+-
+- if (ret == xpcLocalPartid) {
+- break;
+- }
+- continue;
+- }
+-
+- remote_vars_pa = remote_rp->vars_pa;
+-
+- partid = remote_rp->partid;
+- part = &xpc_partitions[partid];
+-
+-
+- /* pull over the cross partition variables */
+-
+- ret = xpc_get_remote_vars(remote_vars_pa, remote_vars);
+- if (ret != xpcSuccess) {
+- dev_dbg(xpc_part, "unable to get XPC variables "
+- "from nasid %d, reason=%d\n", nasid,
+- ret);
+-
+- XPC_DEACTIVATE_PARTITION(part, ret);
+- continue;
+- }
+-
+- if (part->act_state != XPC_P_INACTIVE) {
+- dev_dbg(xpc_part, "partition %d on nasid %d is "
+- "already activating\n", partid, nasid);
+- break;
+- }
+-
+- /*
+- * Register the remote partition's AMOs with SAL so it
+- * can handle and cleanup errors within that address
+- * range should the remote partition go down. We don't
+- * unregister this range because it is difficult to
+- * tell when outstanding writes to the remote partition
+- * are finished and thus when it is thus safe to
+- * unregister. This should not result in wasted space
+- * in the SAL xp_addr_region table because we should
+- * get the same page for remote_act_amos_pa after
+- * module reloads and system reboots.
+- */
+- if (sn_register_xp_addr_region(
+- remote_vars->amos_page_pa,
+- PAGE_SIZE, 1) < 0) {
+- dev_dbg(xpc_part, "partition %d failed to "
+- "register xp_addr region 0x%016lx\n",
+- partid, remote_vars->amos_page_pa);
+-
+- XPC_SET_REASON(part, xpcPhysAddrRegFailed,
+- __LINE__);
+- break;
+- }
+-
+- /*
+- * The remote nasid is valid and available.
+- * Send an interrupt to that nasid to notify
+- * it that we are ready to begin activation.
+- */
+- dev_dbg(xpc_part, "sending an interrupt to AMO 0x%lx, "
+- "nasid %d, phys_cpuid 0x%x\n",
+- remote_vars->amos_page_pa,
+- remote_vars->act_nasid,
+- remote_vars->act_phys_cpuid);
+-
+- if (XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->
+- version)) {
+- part->remote_amos_page_pa =
+- remote_vars->amos_page_pa;
+- xpc_mark_partition_disengaged(part);
+- xpc_cancel_partition_disengage_request(part);
+- }
+- xpc_IPI_send_activate(remote_vars);
+- }
+- }
+-
+- kfree(discovered_nasids);
+- kfree(remote_rp_base);
+-}
+-
+-
+-/*
+- * Given a partid, get the nasids owned by that partition from the
+- * remote partition's reserved page.
+- */
+-enum xpc_retval
+-xpc_initiate_partid_to_nasids(partid_t partid, void *nasid_mask)
+-{
+- struct xpc_partition *part;
+- u64 part_nasid_pa;
+- int bte_res;
+-
+-
+- part = &xpc_partitions[partid];
+- if (part->remote_rp_pa == 0) {
+- return xpcPartitionDown;
+- }
+-
+- memset(nasid_mask, 0, XP_NASID_MASK_BYTES);
+-
+- part_nasid_pa = (u64) XPC_RP_PART_NASIDS(part->remote_rp_pa);
+-
+- bte_res = xp_bte_copy(part_nasid_pa, (u64) nasid_mask,
+- xp_nasid_mask_bytes, (BTE_NOTIFY | BTE_WACQUIRE), NULL);
+-
+- return xpc_map_bte_errors(bte_res);
+-}
+-
+diff --git a/arch/ia64/sn/kernel/xpnet.c b/arch/ia64/sn/kernel/xpnet.c
+deleted file mode 100644
+index a5df672..0000000
+--- a/arch/ia64/sn/kernel/xpnet.c
++++ /dev/null
+@@ -1,718 +0,0 @@
+-/*
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License. See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (C) 1999,2001-2005 Silicon Graphics, Inc. All rights reserved.
+- */
+-
+-
+-/*
+- * Cross Partition Network Interface (XPNET) support
+- *
+- * XPNET provides a virtual network layered on top of the Cross
+- * Partition communication layer.
+- *
+- * XPNET provides direct point-to-point and broadcast-like support
+- * for an ethernet-like device. The ethernet broadcast medium is
+- * replaced with a point-to-point message structure which passes
+- * pointers to a DMA-capable block that a remote partition should
+- * retrieve and pass to the upper level networking layer.
+- *
+- */
+-
+-
+-#include <linux/module.h>
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/ioport.h>
+-#include <linux/netdevice.h>
+-#include <linux/etherdevice.h>
+-#include <linux/delay.h>
+-#include <linux/ethtool.h>
+-#include <linux/mii.h>
+-#include <linux/smp.h>
+-#include <linux/string.h>
+-#include <asm/sn/bte.h>
+-#include <asm/sn/io.h>
+-#include <asm/sn/sn_sal.h>
+-#include <asm/types.h>
+-#include <asm/atomic.h>
+-#include <asm/sn/xp.h>
+-
+-
+-/*
+- * The message payload transferred by XPC.
+- *
+- * buf_pa is the physical address where the DMA should pull from.
+- *
+- * NOTE: for performance reasons, buf_pa should _ALWAYS_ begin on a
+- * cacheline boundary. To accomplish this, we record the number of
+- * bytes from the beginning of the first cacheline to the first useful
+- * byte of the skb (leadin_ignore) and the number of bytes from the
+- * last useful byte of the skb to the end of the last cacheline
+- * (tailout_ignore).
+- *
+- * size is the number of bytes to transfer which includes the skb->len
+- * (useful bytes of the senders skb) plus the leadin and tailout
+- */
+-struct xpnet_message {
+- u16 version; /* Version for this message */
+- u16 embedded_bytes; /* #of bytes embedded in XPC message */
+- u32 magic; /* Special number indicating this is xpnet */
+- u64 buf_pa; /* phys address of buffer to retrieve */
+- u32 size; /* #of bytes in buffer */
+- u8 leadin_ignore; /* #of bytes to ignore at the beginning */
+- u8 tailout_ignore; /* #of bytes to ignore at the end */
+- unsigned char data; /* body of small packets */
+-};
+-
+-/*
+- * Determine the size of our message, the cacheline aligned size,
+- * and then the number of message will request from XPC.
+- *
+- * XPC expects each message to exist in an individual cacheline.
+- */
+-#define XPNET_MSG_SIZE (L1_CACHE_BYTES - XPC_MSG_PAYLOAD_OFFSET)
+-#define XPNET_MSG_DATA_MAX \
+- (XPNET_MSG_SIZE - (u64)(&((struct xpnet_message *)0)->data))
+-#define XPNET_MSG_ALIGNED_SIZE (L1_CACHE_ALIGN(XPNET_MSG_SIZE))
+-#define XPNET_MSG_NENTRIES (PAGE_SIZE / XPNET_MSG_ALIGNED_SIZE)
+-
+-
+-#define XPNET_MAX_KTHREADS (XPNET_MSG_NENTRIES + 1)
+-#define XPNET_MAX_IDLE_KTHREADS (XPNET_MSG_NENTRIES + 1)
+-
+-/*
+- * Version number of XPNET implementation. XPNET can always talk to versions
+- * with same major #, and never talk to versions with a different version.
+- */
+-#define _XPNET_VERSION(_major, _minor) (((_major) << 4) | (_minor))
+-#define XPNET_VERSION_MAJOR(_v) ((_v) >> 4)
+-#define XPNET_VERSION_MINOR(_v) ((_v) & 0xf)
+-
+-#define XPNET_VERSION _XPNET_VERSION(1,0) /* version 1.0 */
+-#define XPNET_VERSION_EMBED _XPNET_VERSION(1,1) /* version 1.1 */
+-#define XPNET_MAGIC 0x88786984 /* "XNET" */
+-
+-#define XPNET_VALID_MSG(_m) \
+- ((XPNET_VERSION_MAJOR(_m->version) == XPNET_VERSION_MAJOR(XPNET_VERSION)) \
+- && (msg->magic == XPNET_MAGIC))
+-
+-#define XPNET_DEVICE_NAME "xp0"
+-
+-
+-/*
+- * When messages are queued with xpc_send_notify, a kmalloc'd buffer
+- * of the following type is passed as a notification cookie. When the
+- * notification function is called, we use the cookie to decide
+- * whether all outstanding message sends have completed. The skb can
+- * then be released.
+- */
+-struct xpnet_pending_msg {
+- struct list_head free_list;
+- struct sk_buff *skb;
+- atomic_t use_count;
+-};
+-
+-/* driver specific structure pointed to by the device structure */
+-struct xpnet_dev_private {
+- struct net_device_stats stats;
+-};
+-
+-struct net_device *xpnet_device;
+-
+-/*
+- * When we are notified of other partitions activating, we add them to
+- * our bitmask of partitions to which we broadcast.
+- */
+-static u64 xpnet_broadcast_partitions;
+-/* protect above */
+-static DEFINE_SPINLOCK(xpnet_broadcast_lock);
+-
+-/*
+- * Since the Block Transfer Engine (BTE) is being used for the transfer
+- * and it relies upon cache-line size transfers, we need to reserve at
+- * least one cache-line for head and tail alignment. The BTE is
+- * limited to 8MB transfers.
+- *
+- * Testing has shown that changing MTU to greater than 64KB has no effect
+- * on TCP as the two sides negotiate a Max Segment Size that is limited
+- * to 64K. Other protocols May use packets greater than this, but for
+- * now, the default is 64KB.
+- */
+-#define XPNET_MAX_MTU (0x800000UL - L1_CACHE_BYTES)
+-/* 32KB has been determined to be the ideal */
+-#define XPNET_DEF_MTU (0x8000UL)
+-
+-
+-/*
+- * The partition id is encapsulated in the MAC address. The following
+- * define locates the octet the partid is in.
+- */
+-#define XPNET_PARTID_OCTET 1
+-#define XPNET_LICENSE_OCTET 2
+-
+-
+-/*
+- * Define the XPNET debug device structure that is to be used with dev_dbg(),
+- * dev_err(), dev_warn(), and dev_info().
+- */
+-struct device_driver xpnet_dbg_name = {
+- .name = "xpnet"
+-};
+-
+-struct device xpnet_dbg_subname = {
+- .bus_id = {0}, /* set to "" */
+- .driver = &xpnet_dbg_name
+-};
+-
+-struct device *xpnet = &xpnet_dbg_subname;
+-
+-/*
+- * Packet was recevied by XPC and forwarded to us.
+- */
+-static void
+-xpnet_receive(partid_t partid, int channel, struct xpnet_message *msg)
+-{
+- struct sk_buff *skb;
+- bte_result_t bret;
+- struct xpnet_dev_private *priv =
+- (struct xpnet_dev_private *) xpnet_device->priv;
+-
+-
+- if (!XPNET_VALID_MSG(msg)) {
+- /*
+- * Packet with a different XPC version. Ignore.
+- */
+- xpc_received(partid, channel, (void *) msg);
+-
+- priv->stats.rx_errors++;
+-
+- return;
+- }
+- dev_dbg(xpnet, "received 0x%lx, %d, %d, %d\n", msg->buf_pa, msg->size,
+- msg->leadin_ignore, msg->tailout_ignore);
+-
+-
+- /* reserve an extra cache line */
+- skb = dev_alloc_skb(msg->size + L1_CACHE_BYTES);
+- if (!skb) {
+- dev_err(xpnet, "failed on dev_alloc_skb(%d)\n",
+- msg->size + L1_CACHE_BYTES);
+-
+- xpc_received(partid, channel, (void *) msg);
+-
+- priv->stats.rx_errors++;
+-
+- return;
+- }
+-
+- /*
+- * The allocated skb has some reserved space.
+- * In order to use bte_copy, we need to get the
+- * skb->data pointer moved forward.
+- */
+- skb_reserve(skb, (L1_CACHE_BYTES - ((u64)skb->data &
+- (L1_CACHE_BYTES - 1)) +
+- msg->leadin_ignore));
+-
+- /*
+- * Update the tail pointer to indicate data actually
+- * transferred.
+- */
+- skb_put(skb, (msg->size - msg->leadin_ignore - msg->tailout_ignore));
+-
+- /*
+- * Move the data over from the other side.
+- */
+- if ((XPNET_VERSION_MINOR(msg->version) == 1) &&
+- (msg->embedded_bytes != 0)) {
+- dev_dbg(xpnet, "copying embedded message. memcpy(0x%p, 0x%p, "
+- "%lu)\n", skb->data, &msg->data,
+- (size_t) msg->embedded_bytes);
+-
+- skb_copy_to_linear_data(skb, &msg->data, (size_t)msg->embedded_bytes);
+- } else {
+- dev_dbg(xpnet, "transferring buffer to the skb->data area;\n\t"
+- "bte_copy(0x%p, 0x%p, %hu)\n", (void *)msg->buf_pa,
+- (void *)__pa((u64)skb->data & ~(L1_CACHE_BYTES - 1)),
+- msg->size);
+-
+- bret = bte_copy(msg->buf_pa,
+- __pa((u64)skb->data & ~(L1_CACHE_BYTES - 1)),
+- msg->size, (BTE_NOTIFY | BTE_WACQUIRE), NULL);
+-
+- if (bret != BTE_SUCCESS) {
+- // >>> Need better way of cleaning skb. Currently skb
+- // >>> appears in_use and we can't just call
+- // >>> dev_kfree_skb.
+- dev_err(xpnet, "bte_copy(0x%p, 0x%p, 0x%hx) returned "
+- "error=0x%x\n", (void *)msg->buf_pa,
+- (void *)__pa((u64)skb->data &
+- ~(L1_CACHE_BYTES - 1)),
+- msg->size, bret);
+-
+- xpc_received(partid, channel, (void *) msg);
+-
+- priv->stats.rx_errors++;
+-
+- return;
+- }
+- }
+-
+- dev_dbg(xpnet, "<skb->head=0x%p skb->data=0x%p skb->tail=0x%p "
+- "skb->end=0x%p skb->len=%d\n", (void *) skb->head,
+- (void *)skb->data, skb_tail_pointer(skb), skb_end_pointer(skb),
+- skb->len);
+-
+- skb->protocol = eth_type_trans(skb, xpnet_device);
+- skb->ip_summed = CHECKSUM_UNNECESSARY;
+-
+- dev_dbg(xpnet, "passing skb to network layer\n"
+- KERN_DEBUG "\tskb->head=0x%p skb->data=0x%p skb->tail=0x%p "
+- "skb->end=0x%p skb->len=%d\n",
+- (void *)skb->head, (void *)skb->data, skb_tail_pointer(skb),
+- skb_end_pointer(skb), skb->len);
+-
+-
+- xpnet_device->last_rx = jiffies;
+- priv->stats.rx_packets++;
+- priv->stats.rx_bytes += skb->len + ETH_HLEN;
+-
+- netif_rx_ni(skb);
+- xpc_received(partid, channel, (void *) msg);
+-}
+-
+-
+-/*
+- * This is the handler which XPC calls during any sort of change in
+- * state or message reception on a connection.
+- */
+-static void
+-xpnet_connection_activity(enum xpc_retval reason, partid_t partid, int channel,
+- void *data, void *key)
+-{
+- long bp;
+-
+-
+- DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+- DBUG_ON(channel != XPC_NET_CHANNEL);
+-
+- switch(reason) {
+- case xpcMsgReceived: /* message received */
+- DBUG_ON(data == NULL);
+-
+- xpnet_receive(partid, channel, (struct xpnet_message *) data);
+- break;
+-
+- case xpcConnected: /* connection completed to a partition */
+- spin_lock_bh(&xpnet_broadcast_lock);
+- xpnet_broadcast_partitions |= 1UL << (partid -1 );
+- bp = xpnet_broadcast_partitions;
+- spin_unlock_bh(&xpnet_broadcast_lock);
+-
+- netif_carrier_on(xpnet_device);
+-
+- dev_dbg(xpnet, "%s connection created to partition %d; "
+- "xpnet_broadcast_partitions=0x%lx\n",
+- xpnet_device->name, partid, bp);
+- break;
+-
+- default:
+- spin_lock_bh(&xpnet_broadcast_lock);
+- xpnet_broadcast_partitions &= ~(1UL << (partid -1 ));
+- bp = xpnet_broadcast_partitions;
+- spin_unlock_bh(&xpnet_broadcast_lock);
+-
+- if (bp == 0) {
+- netif_carrier_off(xpnet_device);
+- }
+-
+- dev_dbg(xpnet, "%s disconnected from partition %d; "
+- "xpnet_broadcast_partitions=0x%lx\n",
+- xpnet_device->name, partid, bp);
+- break;
+-
+- }
+-}
+-
+-
+-static int
+-xpnet_dev_open(struct net_device *dev)
+-{
+- enum xpc_retval ret;
+-
+-
+- dev_dbg(xpnet, "calling xpc_connect(%d, 0x%p, NULL, %ld, %ld, %ld, "
+- "%ld)\n", XPC_NET_CHANNEL, xpnet_connection_activity,
+- XPNET_MSG_SIZE, XPNET_MSG_NENTRIES, XPNET_MAX_KTHREADS,
+- XPNET_MAX_IDLE_KTHREADS);
+-
+- ret = xpc_connect(XPC_NET_CHANNEL, xpnet_connection_activity, NULL,
+- XPNET_MSG_SIZE, XPNET_MSG_NENTRIES,
+- XPNET_MAX_KTHREADS, XPNET_MAX_IDLE_KTHREADS);
+- if (ret != xpcSuccess) {
+- dev_err(xpnet, "ifconfig up of %s failed on XPC connect, "
+- "ret=%d\n", dev->name, ret);
+-
+- return -ENOMEM;
+- }
+-
+- dev_dbg(xpnet, "ifconfig up of %s; XPC connected\n", dev->name);
+-
+- return 0;
+-}
+-
+-
+-static int
+-xpnet_dev_stop(struct net_device *dev)
+-{
+- xpc_disconnect(XPC_NET_CHANNEL);
+-
+- dev_dbg(xpnet, "ifconfig down of %s; XPC disconnected\n", dev->name);
+-
+- return 0;
+-}
+-
+-
+-static int
+-xpnet_dev_change_mtu(struct net_device *dev, int new_mtu)
+-{
+- /* 68 comes from min TCP+IP+MAC header */
+- if ((new_mtu < 68) || (new_mtu > XPNET_MAX_MTU)) {
+- dev_err(xpnet, "ifconfig %s mtu %d failed; value must be "
+- "between 68 and %ld\n", dev->name, new_mtu,
+- XPNET_MAX_MTU);
+- return -EINVAL;
+- }
+-
+- dev->mtu = new_mtu;
+- dev_dbg(xpnet, "ifconfig %s mtu set to %d\n", dev->name, new_mtu);
+- return 0;
+-}
+-
+-
+-/*
+- * Required for the net_device structure.
+- */
+-static int
+-xpnet_dev_set_config(struct net_device *dev, struct ifmap *new_map)
+-{
+- return 0;
+-}
+-
+-
+-/*
+- * Return statistics to the caller.
+- */
+-static struct net_device_stats *
+-xpnet_dev_get_stats(struct net_device *dev)
+-{
+- struct xpnet_dev_private *priv;
+-
+-
+- priv = (struct xpnet_dev_private *) dev->priv;
+-
+- return &priv->stats;
+-}
+-
+-
+-/*
+- * Notification that the other end has received the message and
+- * DMA'd the skb information. At this point, they are done with
+- * our side. When all recipients are done processing, we
+- * release the skb and then release our pending message structure.
+- */
+-static void
+-xpnet_send_completed(enum xpc_retval reason, partid_t partid, int channel,
+- void *__qm)
+-{
+- struct xpnet_pending_msg *queued_msg =
+- (struct xpnet_pending_msg *) __qm;
+-
+-
+- DBUG_ON(queued_msg == NULL);
+-
+- dev_dbg(xpnet, "message to %d notified with reason %d\n",
+- partid, reason);
+-
+- if (atomic_dec_return(&queued_msg->use_count) == 0) {
+- dev_dbg(xpnet, "all acks for skb->head=-x%p\n",
+- (void *) queued_msg->skb->head);
+-
+- dev_kfree_skb_any(queued_msg->skb);
+- kfree(queued_msg);
+- }
+-}
+-
+-
+-/*
+- * Network layer has formatted a packet (skb) and is ready to place it
+- * "on the wire". Prepare and send an xpnet_message to all partitions
+- * which have connected with us and are targets of this packet.
+- *
+- * MAC-NOTE: For the XPNET driver, the MAC address contains the
+- * destination partition_id. If the destination partition id word
+- * is 0xff, this packet is to broadcast to all partitions.
+- */
+-static int
+-xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+-{
+- struct xpnet_pending_msg *queued_msg;
+- enum xpc_retval ret;
+- struct xpnet_message *msg;
+- u64 start_addr, end_addr;
+- long dp;
+- u8 second_mac_octet;
+- partid_t dest_partid;
+- struct xpnet_dev_private *priv;
+- u16 embedded_bytes;
+-
+-
+- priv = (struct xpnet_dev_private *) dev->priv;
+-
+-
+- dev_dbg(xpnet, ">skb->head=0x%p skb->data=0x%p skb->tail=0x%p "
+- "skb->end=0x%p skb->len=%d\n", (void *) skb->head,
+- (void *)skb->data, skb_tail_pointer(skb), skb_end_pointer(skb),
+- skb->len);
+-
+-
+- /*
+- * The xpnet_pending_msg tracks how many outstanding
+- * xpc_send_notifies are relying on this skb. When none
+- * remain, release the skb.
+- */
+- queued_msg = kmalloc(sizeof(struct xpnet_pending_msg), GFP_ATOMIC);
+- if (queued_msg == NULL) {
+- dev_warn(xpnet, "failed to kmalloc %ld bytes; dropping "
+- "packet\n", sizeof(struct xpnet_pending_msg));
+-
+- priv->stats.tx_errors++;
+-
+- return -ENOMEM;
+- }
+-
+-
+- /* get the beginning of the first cacheline and end of last */
+- start_addr = ((u64) skb->data & ~(L1_CACHE_BYTES - 1));
+- end_addr = L1_CACHE_ALIGN((u64)skb_tail_pointer(skb));
+-
+- /* calculate how many bytes to embed in the XPC message */
+- embedded_bytes = 0;
+- if (unlikely(skb->len <= XPNET_MSG_DATA_MAX)) {
+- /* skb->data does fit so embed */
+- embedded_bytes = skb->len;
+- }
+-
+-
+- /*
+- * Since the send occurs asynchronously, we set the count to one
+- * and begin sending. Any sends that happen to complete before
+- * we are done sending will not free the skb. We will be left
+- * with that task during exit. This also handles the case of
+- * a packet destined for a partition which is no longer up.
+- */
+- atomic_set(&queued_msg->use_count, 1);
+- queued_msg->skb = skb;
+-
+-
+- second_mac_octet = skb->data[XPNET_PARTID_OCTET];
+- if (second_mac_octet == 0xff) {
+- /* we are being asked to broadcast to all partitions */
+- dp = xpnet_broadcast_partitions;
+- } else if (second_mac_octet != 0) {
+- dp = xpnet_broadcast_partitions &
+- (1UL << (second_mac_octet - 1));
+- } else {
+- /* 0 is an invalid partid. Ignore */
+- dp = 0;
+- }
+- dev_dbg(xpnet, "destination Partitions mask (dp) = 0x%lx\n", dp);
+-
+- /*
+- * If we wanted to allow promiscuous mode to work like an
+- * unswitched network, this would be a good point to OR in a
+- * mask of partitions which should be receiving all packets.
+- */
+-
+- /*
+- * Main send loop.
+- */
+- for (dest_partid = 1; dp && dest_partid < XP_MAX_PARTITIONS;
+- dest_partid++) {
+-
+-
+- if (!(dp & (1UL << (dest_partid - 1)))) {
+- /* not destined for this partition */
+- continue;
+- }
+-
+- /* remove this partition from the destinations mask */
+- dp &= ~(1UL << (dest_partid - 1));
+-
+-
+- /* found a partition to send to */
+-
+- ret = xpc_allocate(dest_partid, XPC_NET_CHANNEL,
+- XPC_NOWAIT, (void **)&msg);
+- if (unlikely(ret != xpcSuccess)) {
+- continue;
+- }
+-
+- msg->embedded_bytes = embedded_bytes;
+- if (unlikely(embedded_bytes != 0)) {
+- msg->version = XPNET_VERSION_EMBED;
+- dev_dbg(xpnet, "calling memcpy(0x%p, 0x%p, 0x%lx)\n",
+- &msg->data, skb->data, (size_t) embedded_bytes);
+- skb_copy_from_linear_data(skb, &msg->data,
+- (size_t)embedded_bytes);
+- } else {
+- msg->version = XPNET_VERSION;
+- }
+- msg->magic = XPNET_MAGIC;
+- msg->size = end_addr - start_addr;
+- msg->leadin_ignore = (u64) skb->data - start_addr;
+- msg->tailout_ignore = end_addr - (u64)skb_tail_pointer(skb);
+- msg->buf_pa = __pa(start_addr);
+-
+- dev_dbg(xpnet, "sending XPC message to %d:%d\n"
+- KERN_DEBUG "msg->buf_pa=0x%lx, msg->size=%u, "
+- "msg->leadin_ignore=%u, msg->tailout_ignore=%u\n",
+- dest_partid, XPC_NET_CHANNEL, msg->buf_pa, msg->size,
+- msg->leadin_ignore, msg->tailout_ignore);
+-
+-
+- atomic_inc(&queued_msg->use_count);
+-
+- ret = xpc_send_notify(dest_partid, XPC_NET_CHANNEL, msg,
+- xpnet_send_completed, queued_msg);
+- if (unlikely(ret != xpcSuccess)) {
+- atomic_dec(&queued_msg->use_count);
+- continue;
+- }
+-
+- }
+-
+- if (atomic_dec_return(&queued_msg->use_count) == 0) {
+- dev_dbg(xpnet, "no partitions to receive packet destined for "
+- "%d\n", dest_partid);
+-
+-
+- dev_kfree_skb(skb);
+- kfree(queued_msg);
+- }
+-
+- priv->stats.tx_packets++;
+- priv->stats.tx_bytes += skb->len;
+-
+- return 0;
+-}
+-
+-
+-/*
+- * Deal with transmit timeouts coming from the network layer.
+- */
+-static void
+-xpnet_dev_tx_timeout (struct net_device *dev)
+-{
+- struct xpnet_dev_private *priv;
+-
+-
+- priv = (struct xpnet_dev_private *) dev->priv;
+-
+- priv->stats.tx_errors++;
+- return;
+-}
+-
+-
+-static int __init
+-xpnet_init(void)
+-{
+- int i;
+- u32 license_num;
+- int result = -ENOMEM;
+-
+-
+- if (!ia64_platform_is("sn2")) {
+- return -ENODEV;
+- }
+-
+- dev_info(xpnet, "registering network device %s\n", XPNET_DEVICE_NAME);
+-
+- /*
+- * use ether_setup() to init the majority of our device
+- * structure and then override the necessary pieces.
+- */
+- xpnet_device = alloc_netdev(sizeof(struct xpnet_dev_private),
+- XPNET_DEVICE_NAME, ether_setup);
+- if (xpnet_device == NULL) {
+- return -ENOMEM;
+- }
+-
+- netif_carrier_off(xpnet_device);
+-
+- xpnet_device->mtu = XPNET_DEF_MTU;
+- xpnet_device->change_mtu = xpnet_dev_change_mtu;
+- xpnet_device->open = xpnet_dev_open;
+- xpnet_device->get_stats = xpnet_dev_get_stats;
+- xpnet_device->stop = xpnet_dev_stop;
+- xpnet_device->hard_start_xmit = xpnet_dev_hard_start_xmit;
+- xpnet_device->tx_timeout = xpnet_dev_tx_timeout;
+- xpnet_device->set_config = xpnet_dev_set_config;
+-
+- /*
+- * Multicast assumes the LSB of the first octet is set for multicast
+- * MAC addresses. We chose the first octet of the MAC to be unlikely
+- * to collide with any vendor's officially issued MAC.
+- */
+- xpnet_device->dev_addr[0] = 0xfe;
+- xpnet_device->dev_addr[XPNET_PARTID_OCTET] = sn_partition_id;
+- license_num = sn_partition_serial_number_val();
+- for (i = 3; i >= 0; i--) {
+- xpnet_device->dev_addr[XPNET_LICENSE_OCTET + i] =
+- license_num & 0xff;
+- license_num = license_num >> 8;
+- }
+-
+- /*
+- * ether_setup() sets this to a multicast device. We are
+- * really not supporting multicast at this time.
+- */
+- xpnet_device->flags &= ~IFF_MULTICAST;
+-
+- /*
+- * No need to checksum as it is a DMA transfer. The BTE will
+- * report an error if the data is not retrievable and the
+- * packet will be dropped.
+- */
+- xpnet_device->features = NETIF_F_NO_CSUM;
+-
+- result = register_netdev(xpnet_device);
+- if (result != 0) {
+- free_netdev(xpnet_device);
+- }
+-
+- return result;
+-}
+-module_init(xpnet_init);
+-
+-
+-static void __exit
+-xpnet_exit(void)
+-{
+- dev_info(xpnet, "unregistering network device %s\n",
+- xpnet_device[0].name);
+-
+- unregister_netdev(xpnet_device);
+-
+- free_netdev(xpnet_device);
+-}
+-module_exit(xpnet_exit);
+-
+-
+-MODULE_AUTHOR("Silicon Graphics, Inc.");
+-MODULE_DESCRIPTION("Cross Partition Network adapter (XPNET)");
+-MODULE_LICENSE("GPL");
+-
+diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c
+index 9b3c113..94e5845 100644
+--- a/arch/ia64/sn/pci/tioce_provider.c
++++ b/arch/ia64/sn/pci/tioce_provider.c
+@@ -655,7 +655,8 @@ tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags)
+ *
+ * Simply call tioce_do_dma_map() to create a map with the barrier bit set
+ * in the address.
+- */ static u64
++ */
++static u64
+ tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags)
+ {
+ return tioce_do_dma_map(pdev, paddr, byte_count, 1, dma_flags);
+@@ -668,7 +669,8 @@ tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma
+ *
+ * Handle a CE error interrupt. Simply a wrapper around a SAL call which
+ * defers processing to the SGI prom.
+- */ static irqreturn_t
++ */
++static irqreturn_t
+ tioce_error_intr_handler(int irq, void *arg)
+ {
+ struct tioce_common *soft = arg;
+diff --git a/arch/m32r/kernel/Makefile b/arch/m32r/kernel/Makefile
+index e97e26e..09200d4 100644
+--- a/arch/m32r/kernel/Makefile
++++ b/arch/m32r/kernel/Makefile
+@@ -5,7 +5,7 @@
+ extra-y := head.o init_task.o vmlinux.lds
+
+ obj-y := process.o entry.o traps.o align.o irq.o setup.o time.o \
+- m32r_ksyms.o sys_m32r.o semaphore.o signal.o ptrace.o
++ m32r_ksyms.o sys_m32r.o signal.o ptrace.o
+
+ obj-$(CONFIG_SMP) += smp.o smpboot.o
+ obj-$(CONFIG_MODULES) += module.o
+diff --git a/arch/m32r/kernel/m32r_ksyms.c b/arch/m32r/kernel/m32r_ksyms.c
+index 41a4c95..e6709fe 100644
+--- a/arch/m32r/kernel/m32r_ksyms.c
++++ b/arch/m32r/kernel/m32r_ksyms.c
+@@ -7,7 +7,6 @@
+ #include <linux/interrupt.h>
+ #include <linux/string.h>
+
+-#include <asm/semaphore.h>
+ #include <asm/processor.h>
+ #include <asm/uaccess.h>
+ #include <asm/checksum.h>
+@@ -22,10 +21,6 @@ EXPORT_SYMBOL(dump_fpu);
+ EXPORT_SYMBOL(__ioremap);
+ EXPORT_SYMBOL(iounmap);
+ EXPORT_SYMBOL(kernel_thread);
+-EXPORT_SYMBOL(__down);
+-EXPORT_SYMBOL(__down_interruptible);
+-EXPORT_SYMBOL(__up);
+-EXPORT_SYMBOL(__down_trylock);
+
+ /* Networking helper routines. */
+ /* Delay loops */
+diff --git a/arch/m32r/kernel/semaphore.c b/arch/m32r/kernel/semaphore.c
+deleted file mode 100644
+index 940c2d3..0000000
+--- a/arch/m32r/kernel/semaphore.c
++++ /dev/null
+@@ -1,185 +0,0 @@
+-/*
+- * linux/arch/m32r/semaphore.c
+- * orig : i386 2.6.4
+- *
+- * M32R semaphore implementation.
+- *
+- * Copyright (c) 2002 - 2004 Hitoshi Yamamoto
+- */
+-
+-/*
+- * i386 semaphore implementation.
+- *
+- * (C) Copyright 1999 Linus Torvalds
+- *
+- * Portions Copyright 1999 Red Hat, Inc.
+- *
+- * 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.
+- *
+- * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl at kvack.org>
+- */
+-#include <linux/sched.h>
+-#include <linux/err.h>
+-#include <linux/init.h>
+-#include <asm/semaphore.h>
+-
+-/*
+- * Semaphores are implemented using a two-way counter:
+- * The "count" variable is decremented for each process
+- * that tries to acquire the semaphore, while the "sleeping"
+- * variable is a count of such acquires.
+- *
+- * Notably, the inline "up()" and "down()" functions can
+- * efficiently test if they need to do any extra work (up
+- * needs to do something only if count was negative before
+- * the increment operation.
+- *
+- * "sleeping" and the contention routine ordering is protected
+- * by the spinlock in the semaphore's waitqueue head.
+- *
+- * Note that these functions are only called when there is
+- * contention on the lock, and as such all this is the
+- * "non-critical" part of the whole semaphore business. The
+- * critical part is the inline stuff in <asm/semaphore.h>
+- * where we want to avoid any extra jumps and calls.
+- */
+-
+-/*
+- * Logic:
+- * - only on a boundary condition do we need to care. When we go
+- * from a negative count to a non-negative, we wake people up.
+- * - when we go from a non-negative count to a negative do we
+- * (a) synchronize with the "sleeper" count and (b) make sure
+- * that we're on the wakeup list before we synchronize so that
+- * we cannot lose wakeup events.
+- */
+-
+-asmlinkage void __up(struct semaphore *sem)
+-{
+- wake_up(&sem->wait);
+-}
+-
+-asmlinkage void __sched __down(struct semaphore * sem)
+-{
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+- unsigned long flags;
+-
+- tsk->state = TASK_UNINTERRUPTIBLE;
+- spin_lock_irqsave(&sem->wait.lock, flags);
+- add_wait_queue_exclusive_locked(&sem->wait, &wait);
+-
+- sem->sleepers++;
+- for (;;) {
+- int sleepers = sem->sleepers;
+-
+- /*
+- * Add "everybody else" into it. They aren't
+- * playing, because we own the spinlock in
+- * the wait_queue_head.
+- */
+- if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+- sem->sleepers = 0;
+- break;
+- }
+- sem->sleepers = 1; /* us - see -1 above */
+- spin_unlock_irqrestore(&sem->wait.lock, flags);
+-
+- schedule();
+-
+- spin_lock_irqsave(&sem->wait.lock, flags);
+- tsk->state = TASK_UNINTERRUPTIBLE;
+- }
+- remove_wait_queue_locked(&sem->wait, &wait);
+- wake_up_locked(&sem->wait);
+- spin_unlock_irqrestore(&sem->wait.lock, flags);
+- tsk->state = TASK_RUNNING;
+-}
+-
+-asmlinkage int __sched __down_interruptible(struct semaphore * sem)
+-{
+- int retval = 0;
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+- unsigned long flags;
+-
+- tsk->state = TASK_INTERRUPTIBLE;
+- spin_lock_irqsave(&sem->wait.lock, flags);
+- add_wait_queue_exclusive_locked(&sem->wait, &wait);
+-
+- sem->sleepers++;
+- for (;;) {
+- int sleepers = sem->sleepers;
+-
+- /*
+- * With signals pending, this turns into
+- * the trylock failure case - we won't be
+- * sleeping, and we* can't get the lock as
+- * it has contention. Just correct the count
+- * and exit.
+- */
+- if (signal_pending(current)) {
+- retval = -EINTR;
+- sem->sleepers = 0;
+- atomic_add(sleepers, &sem->count);
+- break;
+- }
+-
+- /*
+- * Add "everybody else" into it. They aren't
+- * playing, because we own the spinlock in
+- * wait_queue_head. The "-1" is because we're
+- * still hoping to get the semaphore.
+- */
+- if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+- sem->sleepers = 0;
+- break;
+- }
+- sem->sleepers = 1; /* us - see -1 above */
+- spin_unlock_irqrestore(&sem->wait.lock, flags);
+-
+- schedule();
+-
+- spin_lock_irqsave(&sem->wait.lock, flags);
+- tsk->state = TASK_INTERRUPTIBLE;
+- }
+- remove_wait_queue_locked(&sem->wait, &wait);
+- wake_up_locked(&sem->wait);
+- spin_unlock_irqrestore(&sem->wait.lock, flags);
+-
+- tsk->state = TASK_RUNNING;
+- return retval;
+-}
+-
+-/*
+- * Trylock failed - make sure we correct for
+- * having decremented the count.
+- *
+- * We could have done the trylock with a
+- * single "cmpxchg" without failure cases,
+- * but then it wouldn't work on a 386.
+- */
+-asmlinkage int __down_trylock(struct semaphore * sem)
+-{
+- int sleepers;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&sem->wait.lock, flags);
+- sleepers = sem->sleepers + 1;
+- sem->sleepers = 0;
+-
+- /*
+- * Add "everybody else" and us into it. They aren't
+- * playing, because we own the spinlock in the
+- * wait_queue_head.
+- */
+- if (!atomic_add_negative(sleepers, &sem->count)) {
+- wake_up_locked(&sem->wait);
+- }
+-
+- spin_unlock_irqrestore(&sem->wait.lock, flags);
+- return 1;
+-}
+diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
+index 0055a6c..04c69ff 100644
+--- a/arch/m68k/atari/stram.c
++++ b/arch/m68k/atari/stram.c
+@@ -29,7 +29,6 @@
+ #include <asm/atarihw.h>
+ #include <asm/atari_stram.h>
+ #include <asm/io.h>
+-#include <asm/semaphore.h>
+
+ #undef DEBUG
+
+diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
+index a806208..7a62a71 100644
+--- a/arch/m68k/kernel/Makefile
++++ b/arch/m68k/kernel/Makefile
+@@ -10,7 +10,7 @@ endif
+ extra-y += vmlinux.lds
+
+ obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o module.o \
+- sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o devres.o
++ sys_m68k.o time.o setup.o m68k_ksyms.o devres.o
+
+ devres-y = ../../../kernel/irq/devres.o
+
+diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
+index 6fc69c7..d900e77 100644
+--- a/arch/m68k/kernel/m68k_ksyms.c
++++ b/arch/m68k/kernel/m68k_ksyms.c
+@@ -1,5 +1,4 @@
+ #include <linux/module.h>
+-#include <asm/semaphore.h>
+
+ asmlinkage long long __ashldi3 (long long, int);
+ asmlinkage long long __ashrdi3 (long long, int);
+@@ -15,8 +14,3 @@ EXPORT_SYMBOL(__ashrdi3);
+ EXPORT_SYMBOL(__lshrdi3);
+ EXPORT_SYMBOL(__muldi3);
+
+-EXPORT_SYMBOL(__down_failed);
+-EXPORT_SYMBOL(__down_failed_interruptible);
+-EXPORT_SYMBOL(__down_failed_trylock);
+-EXPORT_SYMBOL(__up_wakeup);
+-
+diff --git a/arch/m68k/kernel/semaphore.c b/arch/m68k/kernel/semaphore.c
+deleted file mode 100644
+index d12cbbf..0000000
+--- a/arch/m68k/kernel/semaphore.c
++++ /dev/null
+@@ -1,132 +0,0 @@
+-/*
+- * Generic semaphore code. Buyer beware. Do your own
+- * specific changes in <asm/semaphore-helper.h>
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/init.h>
+-#include <asm/semaphore-helper.h>
+-
+-#ifndef CONFIG_RMW_INSNS
+-spinlock_t semaphore_wake_lock;
+-#endif
+-
+-/*
+- * Semaphores are implemented using a two-way counter:
+- * The "count" variable is decremented for each process
+- * that tries to sleep, while the "waking" variable is
+- * incremented when the "up()" code goes to wake up waiting
+- * processes.
+- *
+- * Notably, the inline "up()" and "down()" functions can
+- * efficiently test if they need to do any extra work (up
+- * needs to do something only if count was negative before
+- * the increment operation.
+- *
+- * waking_non_zero() (from asm/semaphore.h) must execute
+- * atomically.
+- *
+- * When __up() is called, the count was negative before
+- * incrementing it, and we need to wake up somebody.
+- *
+- * This routine adds one to the count of processes that need to
+- * wake up and exit. ALL waiting processes actually wake up but
+- * only the one that gets to the "waking" field first will gate
+- * through and acquire the semaphore. The others will go back
+- * to sleep.
+- *
+- * Note that these functions are only called when there is
+- * contention on the lock, and as such all this is the
+- * "non-critical" part of the whole semaphore business. The
+- * critical part is the inline stuff in <asm/semaphore.h>
+- * where we want to avoid any extra jumps and calls.
+- */
+-void __up(struct semaphore *sem)
+-{
+- wake_one_more(sem);
+- wake_up(&sem->wait);
+-}
+-
+-/*
+- * Perform the "down" function. Return zero for semaphore acquired,
+- * return negative for signalled out of the function.
+- *
+- * If called from __down, the return is ignored and the wait loop is
+- * not interruptible. This means that a task waiting on a semaphore
+- * using "down()" cannot be killed until someone does an "up()" on
+- * the semaphore.
+- *
+- * If called from __down_interruptible, the return value gets checked
+- * upon return. If the return value is negative then the task continues
+- * with the negative value in the return register (it can be tested by
+- * the caller).
+- *
+- * Either form may be used in conjunction with "up()".
+- *
+- */
+-
+-
+-#define DOWN_HEAD(task_state) \
+- \
+- \
+- current->state = (task_state); \
+- add_wait_queue(&sem->wait, &wait); \
+- \
+- /* \
+- * Ok, we're set up. sem->count is known to be less than zero \
+- * so we must wait. \
+- * \
+- * We can let go the lock for purposes of waiting. \
+- * We re-acquire it after awaking so as to protect \
+- * all semaphore operations. \
+- * \
+- * If "up()" is called before we call waking_non_zero() then \
+- * we will catch it right away. If it is called later then \
+- * we will have to go through a wakeup cycle to catch it. \
+- * \
+- * Multiple waiters contend for the semaphore lock to see \
+- * who gets to gate through and who has to wait some more. \
+- */ \
+- for (;;) {
+-
+-#define DOWN_TAIL(task_state) \
+- current->state = (task_state); \
+- } \
+- current->state = TASK_RUNNING; \
+- remove_wait_queue(&sem->wait, &wait);
+-
+-void __sched __down(struct semaphore * sem)
+-{
+- DECLARE_WAITQUEUE(wait, current);
+-
+- DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+- if (waking_non_zero(sem))
+- break;
+- schedule();
+- DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+-}
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+- DECLARE_WAITQUEUE(wait, current);
+- int ret = 0;
+-
+- DOWN_HEAD(TASK_INTERRUPTIBLE)
+-
+- ret = waking_non_zero_interruptible(sem, current);
+- if (ret)
+- {
+- if (ret == 1)
+- /* ret != 0 only if we get interrupted -arca */
+- ret = 0;
+- break;
+- }
+- schedule();
+- DOWN_TAIL(TASK_INTERRUPTIBLE)
+- return ret;
+-}
+-
+-int __down_trylock(struct semaphore * sem)
+-{
+- return waking_non_zero_trylock(sem);
+-}
+diff --git a/arch/m68k/lib/Makefile b/arch/m68k/lib/Makefile
+index 6bbf19f..a18af09 100644
+--- a/arch/m68k/lib/Makefile
++++ b/arch/m68k/lib/Makefile
+@@ -5,4 +5,4 @@
+ EXTRA_AFLAGS := -traditional
+
+ lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
+- checksum.o string.o semaphore.o uaccess.o
++ checksum.o string.o uaccess.o
+diff --git a/arch/m68k/lib/semaphore.S b/arch/m68k/lib/semaphore.S
+deleted file mode 100644
+index 0215624..0000000
+--- a/arch/m68k/lib/semaphore.S
++++ /dev/null
+@@ -1,53 +0,0 @@
+-/*
+- * linux/arch/m68k/lib/semaphore.S
+- *
+- * Copyright (C) 1996 Linus Torvalds
+- *
+- * m68k version by Andreas Schwab
+- */
+-
+-#include <linux/linkage.h>
+-#include <asm/semaphore.h>
+-
+-/*
+- * The semaphore operations have a special calling sequence that
+- * allow us to do a simpler in-line version of them. These routines
+- * need to convert that sequence back into the C sequence when
+- * there is contention on the semaphore.
+- */
+-ENTRY(__down_failed)
+- moveml %a0/%d0/%d1,-(%sp)
+- movel %a1,-(%sp)
+- jbsr __down
+- movel (%sp)+,%a1
+- moveml (%sp)+,%a0/%d0/%d1
+- rts
+-
+-ENTRY(__down_failed_interruptible)
+- movel %a0,-(%sp)
+- movel %d1,-(%sp)
+- movel %a1,-(%sp)
+- jbsr __down_interruptible
+- movel (%sp)+,%a1
+- movel (%sp)+,%d1
+- movel (%sp)+,%a0
+- rts
+-
+-ENTRY(__down_failed_trylock)
+- movel %a0,-(%sp)
+- movel %d1,-(%sp)
+- movel %a1,-(%sp)
+- jbsr __down_trylock
+- movel (%sp)+,%a1
+- movel (%sp)+,%d1
+- movel (%sp)+,%a0
+- rts
+-
+-ENTRY(__up_wakeup)
+- moveml %a0/%d0/%d1,-(%sp)
+- movel %a1,-(%sp)
+- jbsr __up
+- movel (%sp)+,%a1
+- moveml (%sp)+,%a0/%d0/%d1
+- rts
+-
+diff --git a/arch/m68k/sun3/intersil.c b/arch/m68k/sun3/intersil.c
+index db359d7..0116d20 100644
+--- a/arch/m68k/sun3/intersil.c
++++ b/arch/m68k/sun3/intersil.c
+@@ -15,7 +15,6 @@
+
+ #include <asm/errno.h>
+ #include <asm/system.h>
+-#include <asm/semaphore.h>
+ #include <asm/rtc.h>
+ #include <asm/intersil.h>
+
+diff --git a/arch/m68knommu/kernel/Makefile b/arch/m68knommu/kernel/Makefile
+index 1524b39..f0eab3d 100644
+--- a/arch/m68knommu/kernel/Makefile
++++ b/arch/m68knommu/kernel/Makefile
+@@ -5,7 +5,7 @@
+ extra-y := vmlinux.lds
+
+ obj-y += dma.o entry.o init_task.o irq.o m68k_ksyms.o process.o ptrace.o \
+- semaphore.o setup.o signal.o syscalltable.o sys_m68k.o time.o traps.o
++ setup.o signal.o syscalltable.o sys_m68k.o time.o traps.o
+
+ obj-$(CONFIG_MODULES) += module.o
+ obj-$(CONFIG_COMEMPCI) += comempci.o
+diff --git a/arch/m68knommu/kernel/m68k_ksyms.c b/arch/m68knommu/kernel/m68k_ksyms.c
+index 53fad14..39fe0a7 100644
+--- a/arch/m68knommu/kernel/m68k_ksyms.c
++++ b/arch/m68knommu/kernel/m68k_ksyms.c
+@@ -13,7 +13,6 @@
+ #include <asm/pgalloc.h>
+ #include <asm/irq.h>
+ #include <asm/io.h>
+-#include <asm/semaphore.h>
+ #include <asm/checksum.h>
+ #include <asm/current.h>
+
+@@ -39,11 +38,6 @@ EXPORT_SYMBOL(csum_partial_copy_nocheck);
+ EXPORT_SYMBOL(memcpy);
+ EXPORT_SYMBOL(memset);
+
+-EXPORT_SYMBOL(__down_failed);
+-EXPORT_SYMBOL(__down_failed_interruptible);
+-EXPORT_SYMBOL(__down_failed_trylock);
+-EXPORT_SYMBOL(__up_wakeup);
+-
+ /*
+ * libgcc functions - functions that are used internally by the
+ * compiler... (prototypes are not correct though, but that
+diff --git a/arch/m68knommu/kernel/semaphore.c b/arch/m68knommu/kernel/semaphore.c
+deleted file mode 100644
+index bce2bc7..0000000
+--- a/arch/m68knommu/kernel/semaphore.c
++++ /dev/null
+@@ -1,133 +0,0 @@
+-/*
+- * Generic semaphore code. Buyer beware. Do your own
+- * specific changes in <asm/semaphore-helper.h>
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/err.h>
+-#include <linux/init.h>
+-#include <asm/semaphore-helper.h>
+-
+-#ifndef CONFIG_RMW_INSNS
+-spinlock_t semaphore_wake_lock;
+-#endif
+-
+-/*
+- * Semaphores are implemented using a two-way counter:
+- * The "count" variable is decremented for each process
+- * that tries to sleep, while the "waking" variable is
+- * incremented when the "up()" code goes to wake up waiting
+- * processes.
+- *
+- * Notably, the inline "up()" and "down()" functions can
+- * efficiently test if they need to do any extra work (up
+- * needs to do something only if count was negative before
+- * the increment operation.
+- *
+- * waking_non_zero() (from asm/semaphore.h) must execute
+- * atomically.
+- *
+- * When __up() is called, the count was negative before
+- * incrementing it, and we need to wake up somebody.
+- *
+- * This routine adds one to the count of processes that need to
+- * wake up and exit. ALL waiting processes actually wake up but
+- * only the one that gets to the "waking" field first will gate
+- * through and acquire the semaphore. The others will go back
+- * to sleep.
+- *
+- * Note that these functions are only called when there is
+- * contention on the lock, and as such all this is the
+- * "non-critical" part of the whole semaphore business. The
+- * critical part is the inline stuff in <asm/semaphore.h>
+- * where we want to avoid any extra jumps and calls.
+- */
+-void __up(struct semaphore *sem)
+-{
+- wake_one_more(sem);
+- wake_up(&sem->wait);
+-}
+-
+-/*
+- * Perform the "down" function. Return zero for semaphore acquired,
+- * return negative for signalled out of the function.
+- *
+- * If called from __down, the return is ignored and the wait loop is
+- * not interruptible. This means that a task waiting on a semaphore
+- * using "down()" cannot be killed until someone does an "up()" on
+- * the semaphore.
+- *
+- * If called from __down_interruptible, the return value gets checked
+- * upon return. If the return value is negative then the task continues
+- * with the negative value in the return register (it can be tested by
+- * the caller).
+- *
+- * Either form may be used in conjunction with "up()".
+- *
+- */
+-
+-
+-#define DOWN_HEAD(task_state) \
+- \
+- \
+- current->state = (task_state); \
+- add_wait_queue(&sem->wait, &wait); \
+- \
+- /* \
+- * Ok, we're set up. sem->count is known to be less than zero \
+- * so we must wait. \
+- * \
+- * We can let go the lock for purposes of waiting. \
+- * We re-acquire it after awaking so as to protect \
+- * all semaphore operations. \
+- * \
+- * If "up()" is called before we call waking_non_zero() then \
+- * we will catch it right away. If it is called later then \
+- * we will have to go through a wakeup cycle to catch it. \
+- * \
+- * Multiple waiters contend for the semaphore lock to see \
+- * who gets to gate through and who has to wait some more. \
+- */ \
+- for (;;) {
+-
+-#define DOWN_TAIL(task_state) \
+- current->state = (task_state); \
+- } \
+- current->state = TASK_RUNNING; \
+- remove_wait_queue(&sem->wait, &wait);
+-
+-void __sched __down(struct semaphore * sem)
+-{
+- DECLARE_WAITQUEUE(wait, current);
+-
+- DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+- if (waking_non_zero(sem))
+- break;
+- schedule();
+- DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+-}
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+- DECLARE_WAITQUEUE(wait, current);
+- int ret = 0;
+-
+- DOWN_HEAD(TASK_INTERRUPTIBLE)
+-
+- ret = waking_non_zero_interruptible(sem, current);
+- if (ret)
+- {
+- if (ret == 1)
+- /* ret != 0 only if we get interrupted -arca */
+- ret = 0;
+- break;
+- }
+- schedule();
+- DOWN_TAIL(TASK_INTERRUPTIBLE)
+- return ret;
+-}
+-
+-int __down_trylock(struct semaphore * sem)
+-{
+- return waking_non_zero_trylock(sem);
+-}
+diff --git a/arch/m68knommu/lib/Makefile b/arch/m68knommu/lib/Makefile
+index e051a79..d94d709 100644
+--- a/arch/m68knommu/lib/Makefile
++++ b/arch/m68knommu/lib/Makefile
+@@ -4,4 +4,4 @@
+
+ lib-y := ashldi3.o ashrdi3.o lshrdi3.o \
+ muldi3.o mulsi3.o divsi3.o udivsi3.o modsi3.o umodsi3.o \
+- checksum.o semaphore.o memcpy.o memset.o delay.o
++ checksum.o memcpy.o memset.o delay.o
+diff --git a/arch/m68knommu/lib/semaphore.S b/arch/m68knommu/lib/semaphore.S
+deleted file mode 100644
+index 87c7460..0000000
+--- a/arch/m68knommu/lib/semaphore.S
++++ /dev/null
+@@ -1,66 +0,0 @@
+-/*
+- * linux/arch/m68k/lib/semaphore.S
+- *
+- * Copyright (C) 1996 Linus Torvalds
+- *
+- * m68k version by Andreas Schwab
+- *
+- * MAR/1999 -- modified to support ColdFire (gerg at snapgear.com)
+- */
+-
+-#include <linux/linkage.h>
+-#include <asm/semaphore.h>
+-
+-/*
+- * "down_failed" is called with the eventual return address
+- * in %a0, and the address of the semaphore in %a1. We need
+- * to increment the number of waiters on the semaphore,
+- * call "__down()", and then eventually return to try again.
+- */
+-ENTRY(__down_failed)
+-#ifdef CONFIG_COLDFIRE
+- subl #12,%sp
+- moveml %a0/%d0/%d1,(%sp)
+-#else
+- moveml %a0/%d0/%d1,-(%sp)
+-#endif
+- movel %a1,-(%sp)
+- jbsr __down
+- movel (%sp)+,%a1
+- movel (%sp)+,%d0
+- movel (%sp)+,%d1
+- rts
+-
+-ENTRY(__down_failed_interruptible)
+- movel %a0,-(%sp)
+- movel %d1,-(%sp)
+- movel %a1,-(%sp)
+- jbsr __down_interruptible
+- movel (%sp)+,%a1
+- movel (%sp)+,%d1
+- rts
+-
+-ENTRY(__up_wakeup)
+-#ifdef CONFIG_COLDFIRE
+- subl #12,%sp
+- moveml %a0/%d0/%d1,(%sp)
+-#else
+- moveml %a0/%d0/%d1,-(%sp)
+-#endif
+- movel %a1,-(%sp)
+- jbsr __up
+- movel (%sp)+,%a1
+- movel (%sp)+,%d0
+- movel (%sp)+,%d1
+- rts
+-
+-ENTRY(__down_failed_trylock)
+- movel %a0,-(%sp)
+- movel %d1,-(%sp)
+- movel %a1,-(%sp)
+- jbsr __down_trylock
+- movel (%sp)+,%a1
+- movel (%sp)+,%d1
+- movel (%sp)+,%a0
+- rts
+-
+diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
+index 9e78e1a..6fcdb6f 100644
+--- a/arch/mips/kernel/Makefile
++++ b/arch/mips/kernel/Makefile
+@@ -5,7 +5,7 @@
+ extra-y := head.o init_task.o vmlinux.lds
+
+ obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \
+- ptrace.o reset.o semaphore.o setup.o signal.o syscall.o \
++ ptrace.o reset.o setup.o signal.o syscall.o \
+ time.o topology.o traps.o unaligned.o
+
+ obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o
+diff --git a/arch/mips/kernel/semaphore.c b/arch/mips/kernel/semaphore.c
+deleted file mode 100644
+index 1265358..0000000
+--- a/arch/mips/kernel/semaphore.c
++++ /dev/null
+@@ -1,168 +0,0 @@
+-/*
+- * MIPS-specific semaphore code.
+- *
+- * Copyright (C) 1999 Cort Dougan <cort at cs.nmt.edu>
+- * Copyright (C) 2004 Ralf Baechle <ralf at linux-mips.org>
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- *
+- * April 2001 - Reworked by Paul Mackerras <paulus at samba.org>
+- * to eliminate the SMP races in the old version between the updates
+- * of `count' and `waking'. Now we use negative `count' values to
+- * indicate that some process(es) are waiting for the semaphore.
+- */
+-
+-#include <linux/module.h>
+-#include <linux/sched.h>
+-#include <linux/init.h>
+-#include <asm/atomic.h>
+-#include <asm/cpu-features.h>
+-#include <asm/errno.h>
+-#include <asm/semaphore.h>
+-#include <asm/war.h>
+-/*
+- * Atomically update sem->count.
+- * This does the equivalent of the following:
+- *
+- * old_count = sem->count;
+- * tmp = MAX(old_count, 0) + incr;
+- * sem->count = tmp;
+- * return old_count;
+- *
+- * On machines without lld/scd we need a spinlock to make the manipulation of
+- * sem->count and sem->waking atomic. Scalability isn't an issue because
+- * this lock is used on UP only so it's just an empty variable.
+- */
+-static inline int __sem_update_count(struct semaphore *sem, int incr)
+-{
+- int old_count, tmp;
+-
+- if (cpu_has_llsc && R10000_LLSC_WAR) {
+- __asm__ __volatile__(
+- " .set mips3 \n"
+- "1: ll %0, %2 # __sem_update_count \n"
+- " sra %1, %0, 31 \n"
+- " not %1 \n"
+- " and %1, %0, %1 \n"
+- " addu %1, %1, %3 \n"
+- " sc %1, %2 \n"
+- " beqzl %1, 1b \n"
+- " .set mips0 \n"
+- : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
+- : "r" (incr), "m" (sem->count));
+- } else if (cpu_has_llsc) {
+- __asm__ __volatile__(
+- " .set mips3 \n"
+- "1: ll %0, %2 # __sem_update_count \n"
+- " sra %1, %0, 31 \n"
+- " not %1 \n"
+- " and %1, %0, %1 \n"
+- " addu %1, %1, %3 \n"
+- " sc %1, %2 \n"
+- " beqz %1, 1b \n"
+- " .set mips0 \n"
+- : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
+- : "r" (incr), "m" (sem->count));
+- } else {
+- static DEFINE_SPINLOCK(semaphore_lock);
+- unsigned long flags;
+-
+- spin_lock_irqsave(&semaphore_lock, flags);
+- old_count = atomic_read(&sem->count);
+- tmp = max_t(int, old_count, 0) + incr;
+- atomic_set(&sem->count, tmp);
+- spin_unlock_irqrestore(&semaphore_lock, flags);
+- }
+-
+- return old_count;
+-}
+-
+-void __up(struct semaphore *sem)
+-{
+- /*
+- * Note that we incremented count in up() before we came here,
+- * but that was ineffective since the result was <= 0, and
+- * any negative value of count is equivalent to 0.
+- * This ends up setting count to 1, unless count is now > 0
+- * (i.e. because some other cpu has called up() in the meantime),
+- * in which case we just increment count.
+- */
+- __sem_update_count(sem, 1);
+- wake_up(&sem->wait);
+-}
+-
+-EXPORT_SYMBOL(__up);
+-
+-/*
+- * Note that when we come in to __down or __down_interruptible,
+- * we have already decremented count, but that decrement was
+- * ineffective since the result was < 0, and any negative value
+- * of count is equivalent to 0.
+- * Thus it is only when we decrement count from some value > 0
+- * that we have actually got the semaphore.
+- */
+-void __sched __down(struct semaphore *sem)
+-{
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+-
+- __set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+- add_wait_queue_exclusive(&sem->wait, &wait);
+-
+- /*
+- * Try to get the semaphore. If the count is > 0, then we've
+- * got the semaphore; we decrement count and exit the loop.
+- * If the count is 0 or negative, we set it to -1, indicating
+- * that we are asleep, and then sleep.
+- */
+- while (__sem_update_count(sem, -1) <= 0) {
+- schedule();
+- set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+- }
+- remove_wait_queue(&sem->wait, &wait);
+- __set_task_state(tsk, TASK_RUNNING);
+-
+- /*
+- * If there are any more sleepers, wake one of them up so
+- * that it can either get the semaphore, or set count to -1
+- * indicating that there are still processes sleeping.
+- */
+- wake_up(&sem->wait);
+-}
+-
+-EXPORT_SYMBOL(__down);
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+- int retval = 0;
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+-
+- __set_task_state(tsk, TASK_INTERRUPTIBLE);
+- add_wait_queue_exclusive(&sem->wait, &wait);
+-
+- while (__sem_update_count(sem, -1) <= 0) {
+- if (signal_pending(current)) {
+- /*
+- * A signal is pending - give up trying.
+- * Set sem->count to 0 if it is negative,
+- * since we are no longer sleeping.
+- */
+- __sem_update_count(sem, 0);
+- retval = -EINTR;
+- break;
+- }
+- schedule();
+- set_task_state(tsk, TASK_INTERRUPTIBLE);
+- }
+- remove_wait_queue(&sem->wait, &wait);
+- __set_task_state(tsk, TASK_RUNNING);
+-
+- wake_up(&sem->wait);
+- return retval;
+-}
+-
+-EXPORT_SYMBOL(__down_interruptible);
+diff --git a/arch/mips/sgi-ip27/ip27-console.c b/arch/mips/sgi-ip27/ip27-console.c
+index 3ba8306..984e561 100644
+--- a/arch/mips/sgi-ip27/ip27-console.c
++++ b/arch/mips/sgi-ip27/ip27-console.c
+@@ -8,7 +8,6 @@
+ #include <linux/init.h>
+
+ #include <asm/page.h>
+-#include <asm/semaphore.h>
+ #include <asm/sn/addrs.h>
+ #include <asm/sn/sn0/hub.h>
+ #include <asm/sn/klconfig.h>
+diff --git a/arch/mn10300/kernel/Makefile b/arch/mn10300/kernel/Makefile
+index ef07c95..23f2ab6 100644
+--- a/arch/mn10300/kernel/Makefile
++++ b/arch/mn10300/kernel/Makefile
+@@ -3,7 +3,7 @@
+ #
+ extra-y := head.o init_task.o vmlinux.lds
+
+-obj-y := process.o semaphore.o signal.o entry.o fpu.o traps.o irq.o \
++obj-y := process.o signal.o entry.o fpu.o traps.o irq.o \
+ ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \
+ switch_to.o mn10300_ksyms.o kernel_execve.o
+
+diff --git a/arch/mn10300/kernel/semaphore.c b/arch/mn10300/kernel/semaphore.c
+deleted file mode 100644
+index 9153c40..0000000
+--- a/arch/mn10300/kernel/semaphore.c
++++ /dev/null
+@@ -1,149 +0,0 @@
+-/* MN10300 Semaphore implementation
+- *
+- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+- * Written by David Howells (dhowells at redhat.com)
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public Licence
+- * as published by the Free Software Foundation; either version
+- * 2 of the Licence, or (at your option) any later version.
+- */
+-#include <linux/sched.h>
+-#include <linux/module.h>
+-#include <asm/semaphore.h>
+-
+-struct sem_waiter {
+- struct list_head list;
+- struct task_struct *task;
+-};
+-
+-#if SEMAPHORE_DEBUG
+-void semtrace(struct semaphore *sem, const char *str)
+-{
+- if (sem->debug)
+- printk(KERN_DEBUG "[%d] %s({%d,%d})\n",
+- current->pid,
+- str,
+- atomic_read(&sem->count),
+- list_empty(&sem->wait_list) ? 0 : 1);
+-}
+-#else
+-#define semtrace(SEM, STR) do { } while (0)
+-#endif
+-
+-/*
+- * wait for a token to be granted from a semaphore
+- * - entered with lock held and interrupts disabled
+- */
+-void __down(struct semaphore *sem, unsigned long flags)
+-{
+- struct task_struct *tsk = current;
+- struct sem_waiter waiter;
+-
+- semtrace(sem, "Entering __down");
+-
+- /* set up my own style of waitqueue */
+- waiter.task = tsk;
+- get_task_struct(tsk);
+-
+- list_add_tail(&waiter.list, &sem->wait_list);
+-
+- /* we don't need to touch the semaphore struct anymore */
+- spin_unlock_irqrestore(&sem->wait_lock, flags);
+-
+- /* wait to be given the semaphore */
+- set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+-
+- for (;;) {
+- if (!waiter.task)
+- break;
+- schedule();
+- set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+- }
+-
+- tsk->state = TASK_RUNNING;
+- semtrace(sem, "Leaving __down");
+-}
+-EXPORT_SYMBOL(__down);
+-
+-/*
+- * interruptibly wait for a token to be granted from a semaphore
+- * - entered with lock held and interrupts disabled
+- */
+-int __down_interruptible(struct semaphore *sem, unsigned long flags)
+-{
+- struct task_struct *tsk = current;
+- struct sem_waiter waiter;
+- int ret;
+-
+- semtrace(sem, "Entering __down_interruptible");
+-
+- /* set up my own style of waitqueue */
+- waiter.task = tsk;
+- get_task_struct(tsk);
+-
+- list_add_tail(&waiter.list, &sem->wait_list);
+-
+- /* we don't need to touch the semaphore struct anymore */
+- set_task_state(tsk, TASK_INTERRUPTIBLE);
+-
+- spin_unlock_irqrestore(&sem->wait_lock, flags);
+-
+- /* wait to be given the semaphore */
+- ret = 0;
+- for (;;) {
+- if (!waiter.task)
+- break;
+- if (unlikely(signal_pending(current)))
+- goto interrupted;
+- schedule();
+- set_task_state(tsk, TASK_INTERRUPTIBLE);
+- }
+-
+- out:
+- tsk->state = TASK_RUNNING;
+- semtrace(sem, "Leaving __down_interruptible");
+- return ret;
+-
+- interrupted:
+- spin_lock_irqsave(&sem->wait_lock, flags);
+- list_del(&waiter.list);
+- spin_unlock_irqrestore(&sem->wait_lock, flags);
+-
+- ret = 0;
+- if (!waiter.task) {
+- put_task_struct(current);
+- ret = -EINTR;
+- }
+- goto out;
+-}
+-EXPORT_SYMBOL(__down_interruptible);
+-
+-/*
+- * release a single token back to a semaphore
+- * - entered with lock held and interrupts disabled
+- */
+-void __up(struct semaphore *sem)
+-{
+- struct task_struct *tsk;
+- struct sem_waiter *waiter;
+-
+- semtrace(sem, "Entering __up");
+-
+- /* grant the token to the process at the front of the queue */
+- waiter = list_entry(sem->wait_list.next, struct sem_waiter, list);
+-
+- /* We must be careful not to touch 'waiter' after we set ->task = NULL.
+- * It is an allocated on the waiter's stack and may become invalid at
+- * any time after that point (due to a wakeup from another source).
+- */
+- list_del_init(&waiter->list);
+- tsk = waiter->task;
+- smp_mb();
+- waiter->task = NULL;
+- wake_up_process(tsk);
+- put_task_struct(tsk);
+-
+- semtrace(sem, "Leaving __up");
+-}
+-EXPORT_SYMBOL(__up);
+diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.h b/arch/mn10300/unit-asb2305/pci-asb2305.h
+index 84634fa..9763d1c 100644
+--- a/arch/mn10300/unit-asb2305/pci-asb2305.h
++++ b/arch/mn10300/unit-asb2305/pci-asb2305.h
+@@ -23,8 +23,6 @@
+ #define PCI_PROBE_BIOS 1
+ #define PCI_PROBE_CONF1 2
+ #define PCI_PROBE_CONF2 4
+-#define PCI_NO_SORT 0x100
+-#define PCI_BIOS_SORT 0x200
+ #define PCI_NO_CHECKS 0x400
+ #define PCI_ASSIGN_ROMS 0x1000
+ #define PCI_BIOS_IRQ_SCAN 0x2000
+diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile
+index 27827bc..1f6585a 100644
+--- a/arch/parisc/kernel/Makefile
++++ b/arch/parisc/kernel/Makefile
+@@ -9,7 +9,7 @@ AFLAGS_pacache.o := -traditional
+
+ obj-y := cache.o pacache.o setup.o traps.o time.o irq.o \
+ pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \
+- ptrace.o hardware.o inventory.o drivers.o semaphore.o \
++ ptrace.o hardware.o inventory.o drivers.o \
+ signal.o hpmc.o real2.o parisc_ksyms.o unaligned.o \
+ process.o processor.o pdc_cons.o pdc_chassis.o unwind.o \
+ topology.o
+diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c
+index 7aca704..5b7fc4a 100644
+--- a/arch/parisc/kernel/parisc_ksyms.c
++++ b/arch/parisc/kernel/parisc_ksyms.c
+@@ -69,11 +69,6 @@ EXPORT_SYMBOL(memcpy_toio);
+ EXPORT_SYMBOL(memcpy_fromio);
+ EXPORT_SYMBOL(memset_io);
+
+-#include <asm/semaphore.h>
+-EXPORT_SYMBOL(__up);
+-EXPORT_SYMBOL(__down_interruptible);
+-EXPORT_SYMBOL(__down);
+-
+ extern void $$divI(void);
+ extern void $$divU(void);
+ extern void $$remI(void);
+diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c
+index 507d0ac..6936386 100644
+--- a/arch/parisc/kernel/pci.c
++++ b/arch/parisc/kernel/pci.c
+@@ -287,23 +287,15 @@ void pcibios_align_resource(void *data, struct resource *res,
+ */
+ int pcibios_enable_device(struct pci_dev *dev, int mask)
+ {
+- u16 cmd;
+- int idx;
++ int err;
++ u16 cmd, old_cmd;
+
+- pci_read_config_word(dev, PCI_COMMAND, &cmd);
+-
+- for (idx = 0; idx < DEVICE_COUNT_RESOURCE; idx++) {
+- struct resource *r = &dev->resource[idx];
++ err = pci_enable_resources(dev, mask);
++ if (err < 0)
++ return err;
+
+- /* only setup requested resources */
+- if (!(mask & (1<<idx)))
+- continue;
+-
+- if (r->flags & IORESOURCE_IO)
+- cmd |= PCI_COMMAND_IO;
+- if (r->flags & IORESOURCE_MEM)
+- cmd |= PCI_COMMAND_MEMORY;
+- }
++ pci_read_config_word(dev, PCI_COMMAND, &cmd);
++ old_cmd = cmd;
+
+ cmd |= (PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
+
+@@ -312,8 +304,12 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
+ if (dev->bus->bridge_ctl & PCI_BRIDGE_CTL_FAST_BACK)
+ cmd |= PCI_COMMAND_FAST_BACK;
+ #endif
+- DBGC("PCIBIOS: Enabling device %s cmd 0x%04x\n", pci_name(dev), cmd);
+- pci_write_config_word(dev, PCI_COMMAND, cmd);
++
++ if (cmd != old_cmd) {
++ dev_info(&dev->dev, "enabling SERR and PARITY (%04x -> %04x)\n",
++ old_cmd, cmd);
++ pci_write_config_word(dev, PCI_COMMAND, cmd);
++ }
+ return 0;
+ }
+
+diff --git a/arch/parisc/kernel/semaphore.c b/arch/parisc/kernel/semaphore.c
+deleted file mode 100644
+index ee806bc..0000000
+--- a/arch/parisc/kernel/semaphore.c
++++ /dev/null
+@@ -1,102 +0,0 @@
+-/*
+- * Semaphore implementation Copyright (c) 2001 Matthew Wilcox, Hewlett-Packard
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/spinlock.h>
+-#include <linux/errno.h>
+-#include <linux/init.h>
+-
+-/*
+- * Semaphores are complex as we wish to avoid using two variables.
+- * `count' has multiple roles, depending on its value. If it is positive
+- * or zero, there are no waiters. The functions here will never be
+- * called; see <asm/semaphore.h>
+- *
+- * When count is -1 it indicates there is at least one task waiting
+- * for the semaphore.
+- *
+- * When count is less than that, there are '- count - 1' wakeups
+- * pending. ie if it has value -3, there are 2 wakeups pending.
+- *
+- * Note that these functions are only called when there is contention
+- * on the lock, and as such all this is the "non-critical" part of the
+- * whole semaphore business. The critical part is the inline stuff in
+- * <asm/semaphore.h> where we want to avoid any extra jumps and calls.
+- */
+-void __up(struct semaphore *sem)
+-{
+- sem->count--;
+- wake_up(&sem->wait);
+-}
+-
+-#define wakers(count) (-1 - count)
+-
+-#define DOWN_HEAD \
+- int ret = 0; \
+- DECLARE_WAITQUEUE(wait, current); \
+- \
+- /* Note that someone is waiting */ \
+- if (sem->count == 0) \
+- sem->count = -1; \
+- \
+- /* protected by the sentry still -- use unlocked version */ \
+- wait.flags = WQ_FLAG_EXCLUSIVE; \
+- __add_wait_queue_tail(&sem->wait, &wait); \
+- lost_race: \
+- spin_unlock_irq(&sem->sentry); \
+-
+-#define DOWN_TAIL \
+- spin_lock_irq(&sem->sentry); \
+- if (wakers(sem->count) == 0 && ret == 0) \
+- goto lost_race; /* Someone stole our wakeup */ \
+- __remove_wait_queue(&sem->wait, &wait); \
+- current->state = TASK_RUNNING; \
+- if (!waitqueue_active(&sem->wait) && (sem->count < 0)) \
+- sem->count = wakers(sem->count);
+-
+-#define UPDATE_COUNT \
+- sem->count += (sem->count < 0) ? 1 : - 1;
+-
+-
+-void __sched __down(struct semaphore * sem)
+-{
+- DOWN_HEAD
+-
+- for(;;) {
+- set_task_state(current, TASK_UNINTERRUPTIBLE);
+- /* we can _read_ this without the sentry */
+- if (sem->count != -1)
+- break;
+- schedule();
+- }
+-
+- DOWN_TAIL
+- UPDATE_COUNT
+-}
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+- DOWN_HEAD
+-
+- for(;;) {
+- set_task_state(current, TASK_INTERRUPTIBLE);
+- /* we can _read_ this without the sentry */
+- if (sem->count != -1)
+- break;
+-
+- if (signal_pending(current)) {
+- ret = -EINTR;
+- break;
+- }
+- schedule();
+- }
+-
+- DOWN_TAIL
+-
+- if (!ret) {
+- UPDATE_COUNT
+- }
+-
+- return ret;
+-}
+diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
+index 50bbf33..71efd6a 100644
+--- a/arch/parisc/kernel/sys_parisc32.c
++++ b/arch/parisc/kernel/sys_parisc32.c
+@@ -49,7 +49,6 @@
+
+ #include <asm/types.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #include <asm/mmu_context.h>
+
+ #include "sys32.h"
+diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
+index 1189d8d..20f45a8 100644
+--- a/arch/powerpc/Kconfig
++++ b/arch/powerpc/Kconfig
+@@ -49,6 +49,19 @@ config IRQ_PER_CPU
+ bool
+ default y
+
++config STACKTRACE_SUPPORT
++ bool
++ default y
++
++config TRACE_IRQFLAGS_SUPPORT
++ bool
++ depends on PPC64
++ default y
++
++config LOCKDEP_SUPPORT
++ bool
++ default y
++
+ config RWSEM_GENERIC_SPINLOCK
+ bool
+
+@@ -81,6 +94,11 @@ config GENERIC_FIND_NEXT_BIT
+ bool
+ default y
+
++config GENERIC_GPIO
++ bool
++ help
++ Generic GPIO API support
++
+ config ARCH_NO_VIRT_TO_BUS
+ def_bool PPC64
+
+@@ -91,6 +109,7 @@ config PPC
+ select HAVE_OPROFILE
+ select HAVE_KPROBES
+ select HAVE_KRETPROBES
++ select HAVE_LMB
+
+ config EARLY_PRINTK
+ bool
+@@ -210,15 +229,6 @@ source kernel/Kconfig.hz
+ source kernel/Kconfig.preempt
+ source "fs/Kconfig.binfmt"
+
+-# We optimistically allocate largepages from the VM, so make the limit
+-# large enough (16MB). This badly named config option is actually
+-# max order + 1
+-config FORCE_MAX_ZONEORDER
+- int
+- depends on PPC64
+- default "9" if PPC_64K_PAGES
+- default "13"
+-
+ config HUGETLB_PAGE_SIZE_VARIABLE
+ bool
+ depends on HUGETLB_PAGE
+@@ -307,6 +317,16 @@ config CRASH_DUMP
+
+ Don't change this unless you know what you are doing.
+
++config PHYP_DUMP
++ bool "Hypervisor-assisted dump (EXPERIMENTAL)"
++ depends on PPC_PSERIES && EXPERIMENTAL
++ help
++ Hypervisor-assisted dump is meant to be a kdump replacement
++ offering robustness and speed not possible without system
++ hypervisor assistence.
++
++ If unsure, say "N"
++
+ config PPCBUG_NVRAM
+ bool "Enable reading PPCBUG NVRAM during boot" if PPLUS || LOPEC
+ default y if PPC_PREP
+@@ -381,6 +401,26 @@ config PPC_64K_PAGES
+ while on hardware with such support, it will be used to map
+ normal application pages.
+
++config FORCE_MAX_ZONEORDER
++ int "Maximum zone order"
++ default "9" if PPC_64K_PAGES
++ default "13" if PPC64 && !PPC_64K_PAGES
++ default "11"
++ help
++ The kernel memory allocator divides physically contiguous memory
++ blocks into "zones", where each zone is a power of two number of
++ pages. This option selects the largest power of two that the kernel
++ keeps in the memory allocator. If you need to allocate very large
++ blocks of physically contiguous memory, then you may need to
++ increase this value.
++
++ This config option is actually maximum order plus one. For example,
++ a value of 11 means that the largest free memory block is 2^10 pages.
++
++ The page size is not necessarily 4KB. For example, on 64-bit
++ systems, 64KB pages can be enabled via CONFIG_PPC_64K_PAGES. Keep
++ this in mind when choosing a value for this option.
++
+ config PPC_SUBPAGE_PROT
+ bool "Support setting protections for 4k subpages"
+ depends on PPC_64K_PAGES
+@@ -490,6 +530,14 @@ config FSL_PCI
+ bool
+ select PPC_INDIRECT_PCI
+
++config 4xx_SOC
++ bool
++
++config FSL_LBC
++ bool
++ help
++ Freescale Localbus support
++
+ # Yes MCA RS/6000s exist but Linux-PPC does not currently support any
+ config MCA
+ bool
+@@ -578,20 +626,6 @@ config ADVANCED_OPTIONS
+ comment "Default settings for advanced configuration options are used"
+ depends on !ADVANCED_OPTIONS
+
+-config HIGHMEM_START_BOOL
+- bool "Set high memory pool address"
+- depends on ADVANCED_OPTIONS && HIGHMEM
+- help
+- This option allows you to set the base address of the kernel virtual
+- area used to map high memory pages. This can be useful in
+- optimizing the layout of kernel virtual memory.
+-
+- Say N here unless you know what you are doing.
+-
+-config HIGHMEM_START
+- hex "Virtual start address of high memory pool" if HIGHMEM_START_BOOL
+- default "0xfe000000"
+-
+ config LOWMEM_SIZE_BOOL
+ bool "Set maximum low memory"
+ depends on ADVANCED_OPTIONS
+@@ -608,21 +642,76 @@ config LOWMEM_SIZE
+ hex "Maximum low memory size (in bytes)" if LOWMEM_SIZE_BOOL
+ default "0x30000000"
+
++config RELOCATABLE
++ bool "Build a relocatable kernel (EXPERIMENTAL)"
++ depends on EXPERIMENTAL && ADVANCED_OPTIONS && FLATMEM && FSL_BOOKE
++ help
++ This builds a kernel image that is capable of running at the
++ location the kernel is loaded at (some alignment restrictions may
++ exist).
++
++ One use is for the kexec on panic case where the recovery kernel
++ must live at a different physical address than the primary
++ kernel.
++
++ Note: If CONFIG_RELOCATABLE=y, then the kernel runs from the address
++ it has been loaded at and the compile time physical addresses
++ CONFIG_PHYSICAL_START is ignored. However CONFIG_PHYSICAL_START
++ setting can still be useful to bootwrappers that need to know the
++ load location of the kernel (eg. u-boot/mkimage).
++
++config PAGE_OFFSET_BOOL
++ bool "Set custom page offset address"
++ depends on ADVANCED_OPTIONS
++ help
++ This option allows you to set the kernel virtual address at which
++ the kernel will map low memory. This can be useful in optimizing
++ the virtual memory layout of the system.
++
++ Say N here unless you know what you are doing.
++
++config PAGE_OFFSET
++ hex "Virtual address of memory base" if PAGE_OFFSET_BOOL
++ default "0xc0000000"
++
+ config KERNEL_START_BOOL
+ bool "Set custom kernel base address"
+ depends on ADVANCED_OPTIONS
+ help
+ This option allows you to set the kernel virtual address at which
+- the kernel will map low memory (the kernel image will be linked at
+- this address). This can be useful in optimizing the virtual memory
+- layout of the system.
++ the kernel will be loaded. Normally this should match PAGE_OFFSET
++ however there are times (like kdump) that one might not want them
++ to be the same.
+
+ Say N here unless you know what you are doing.
+
+ config KERNEL_START
+ hex "Virtual address of kernel base" if KERNEL_START_BOOL
++ default PAGE_OFFSET if PAGE_OFFSET_BOOL
++ default "0xc2000000" if CRASH_DUMP
+ default "0xc0000000"
+
++config PHYSICAL_START_BOOL
++ bool "Set physical address where the kernel is loaded"
++ depends on ADVANCED_OPTIONS && FLATMEM && FSL_BOOKE
++ help
++ This gives the physical address where the kernel is loaded.
++
++ Say N here unless you know what you are doing.
++
++config PHYSICAL_START
++ hex "Physical address where the kernel is loaded" if PHYSICAL_START_BOOL
++ default "0x02000000" if PPC_STD_MMU && CRASH_DUMP
++ default "0x00000000"
++
++config PHYSICAL_ALIGN
++ hex
++ default "0x10000000" if FSL_BOOKE
++ help
++ This value puts the alignment restrictions on physical address
++ where kernel is loaded and run from. Kernel is compiled for an
++ address which meets above alignment restriction.
++
+ config TASK_SIZE_BOOL
+ bool "Set custom user task size"
+ depends on ADVANCED_OPTIONS
+@@ -663,31 +752,23 @@ config CONSISTENT_SIZE
+ hex "Size of consistent memory pool" if CONSISTENT_SIZE_BOOL
+ default "0x00200000" if NOT_COHERENT_CACHE
+
+-config BOOT_LOAD_BOOL
+- bool "Set the boot link/load address"
+- depends on ADVANCED_OPTIONS && !PPC_MULTIPLATFORM
+- help
+- This option allows you to set the initial load address of the zImage
+- or zImage.initrd file. This can be useful if you are on a board
+- which has a small amount of memory.
+-
+- Say N here unless you know what you are doing.
+-
+-config BOOT_LOAD
+- hex "Link/load address for booting" if BOOT_LOAD_BOOL
+- default "0x00400000" if 40x || 8xx || 8260
+- default "0x01000000" if 44x
+- default "0x00800000"
+-
+ config PIN_TLB
+ bool "Pinned Kernel TLBs (860 ONLY)"
+ depends on ADVANCED_OPTIONS && 8xx
+ endmenu
+
+ if PPC64
++config PAGE_OFFSET
++ hex
++ default "0xc000000000000000"
+ config KERNEL_START
+ hex
++ default "0xc000000002000000" if CRASH_DUMP
+ default "0xc000000000000000"
++config PHYSICAL_START
++ hex
++ default "0x02000000" if CRASH_DUMP
++ default "0x00000000"
+ endif
+
+ source "net/Kconfig"
+diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
+index db7cc34..a86d8d8 100644
+--- a/arch/powerpc/Kconfig.debug
++++ b/arch/powerpc/Kconfig.debug
+@@ -269,7 +269,7 @@ config PPC_EARLY_DEBUG_CPM_ADDR
+ hex "CPM UART early debug transmit descriptor address"
+ depends on PPC_EARLY_DEBUG_CPM
+ default "0xfa202008" if PPC_EP88XC
+- default "0xf0000008" if CPM2
++ default "0xf0001ff8" if CPM2
+ default "0xff002008" if CPM1
+ help
+ This specifies the address of the transmit descriptor
+diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
+index ab5cfe8..e2ec4a9 100644
+--- a/arch/powerpc/Makefile
++++ b/arch/powerpc/Makefile
+@@ -71,13 +71,11 @@ endif
+
+ LDFLAGS_vmlinux := -Bstatic
+
+-CPPFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH)
+-AFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH)
+ CFLAGS-$(CONFIG_PPC64) := -mminimal-toc -mtraceback=none -mcall-aixdesc
+-CFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH) -ffixed-r2 -mmultiple
+-KBUILD_CPPFLAGS += $(CPPFLAGS-y)
+-KBUILD_AFLAGS += $(AFLAGS-y)
+-KBUILD_CFLAGS += -msoft-float -pipe $(CFLAGS-y)
++CFLAGS-$(CONFIG_PPC32) := -ffixed-r2 -mmultiple
++KBUILD_CPPFLAGS += -Iarch/$(ARCH)
++KBUILD_AFLAGS += -Iarch/$(ARCH)
++KBUILD_CFLAGS += -msoft-float -pipe -Iarch/$(ARCH) $(CFLAGS-y)
+ CPP = $(CC) -E $(KBUILD_CFLAGS)
+
+ CHECKFLAGS += -m$(CONFIG_WORD_SIZE) -D__powerpc__ -D__powerpc$(CONFIG_WORD_SIZE)__
+@@ -164,7 +162,7 @@ boot := arch/$(ARCH)/boot
+ $(BOOT_TARGETS): vmlinux
+ $(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
+
+-bootwrapper_install:
++bootwrapper_install %.dtb:
+ $(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
+
+ define archhelp
+diff --git a/arch/powerpc/boot/.gitignore b/arch/powerpc/boot/.gitignore
+index 5ef2bdf..2347294 100644
+--- a/arch/powerpc/boot/.gitignore
++++ b/arch/powerpc/boot/.gitignore
+@@ -27,6 +27,7 @@ zImage.chrp
+ zImage.coff
+ zImage.coff.lds
+ zImage.ep*
++zImage.iseries
+ zImage.*lds
+ zImage.miboot
+ zImage.pmac
+diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
+index 1aded8f..7822d25 100644
+--- a/arch/powerpc/boot/Makefile
++++ b/arch/powerpc/boot/Makefile
+@@ -40,6 +40,7 @@ $(obj)/ebony.o: BOOTCFLAGS += -mcpu=405
+ $(obj)/cuboot-taishan.o: BOOTCFLAGS += -mcpu=405
+ $(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=405
+ $(obj)/treeboot-walnut.o: BOOTCFLAGS += -mcpu=405
++$(obj)/virtex405-head.o: BOOTAFLAGS += -mcpu=405
+
+
+ zlib := inffast.c inflate.c inftrees.c
+@@ -64,7 +65,8 @@ src-plat := of.c cuboot-52xx.c cuboot-824x.c cuboot-83xx.c cuboot-85xx.c holly.c
+ cuboot-bamboo.c cuboot-mpc7448hpc2.c cuboot-taishan.c \
+ fixed-head.S ep88xc.c ep405.c \
+ cuboot-katmai.c cuboot-rainier.c redboot-8xx.c ep8248e.c \
+- cuboot-warp.c cuboot-85xx-cpm2.c
++ cuboot-warp.c cuboot-85xx-cpm2.c cuboot-yosemite.c simpleboot.c \
++ virtex405-head.S
+ src-boot := $(src-wlib) $(src-plat) empty.c
+
+ src-boot := $(addprefix $(obj)/, $(src-boot))
+@@ -192,7 +194,7 @@ image-$(CONFIG_PPC_CHRP) += zImage.chrp
+ image-$(CONFIG_PPC_EFIKA) += zImage.chrp
+ image-$(CONFIG_PPC_PMAC) += zImage.pmac
+ image-$(CONFIG_PPC_HOLLY) += zImage.holly
+-image-$(CONFIG_PPC_PRPMC2800) += zImage.prpmc2800
++image-$(CONFIG_PPC_PRPMC2800) += dtbImage.prpmc2800
+ image-$(CONFIG_PPC_ISERIES) += zImage.iseries
+ image-$(CONFIG_DEFAULT_UIMAGE) += uImage
+
+@@ -216,6 +218,7 @@ image-$(CONFIG_RAINIER) += cuImage.rainier
+ image-$(CONFIG_TAISHAN) += cuImage.taishan
+ image-$(CONFIG_KATMAI) += cuImage.katmai
+ image-$(CONFIG_WARP) += cuImage.warp
++image-$(CONFIG_YOSEMITE) += cuImage.yosemite
+
+ # Board ports in arch/powerpc/platform/8xx/Kconfig
+ image-$(CONFIG_PPC_MPC86XADS) += cuImage.mpc866ads
+@@ -255,6 +258,7 @@ image-$(CONFIG_TQM8555) += cuImage.tqm8555
+ image-$(CONFIG_TQM8560) += cuImage.tqm8560
+ image-$(CONFIG_SBC8548) += cuImage.sbc8548
+ image-$(CONFIG_SBC8560) += cuImage.sbc8560
++image-$(CONFIG_KSI8560) += cuImage.ksi8560
+
+ # Board ports in arch/powerpc/platform/embedded6xx/Kconfig
+ image-$(CONFIG_STORCENTER) += cuImage.storcenter
+@@ -285,11 +289,11 @@ $(obj)/zImage.%: vmlinux $(wrapperbits)
+ $(call if_changed,wrap,$*)
+
+ # dtbImage% - a dtbImage is a zImage with an embedded device tree blob
+-$(obj)/dtbImage.initrd.%: vmlinux $(wrapperbits) $(dtstree)/%.dts
+- $(call if_changed,wrap,$*,$(dtstree)/$*.dts,,$(obj)/ramdisk.image.gz)
++$(obj)/dtbImage.initrd.%: vmlinux $(wrapperbits) $(obj)/%.dtb
++ $(call if_changed,wrap,$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz)
+
+-$(obj)/dtbImage.%: vmlinux $(wrapperbits) $(dtstree)/%.dts
+- $(call if_changed,wrap,$*,$(dtstree)/$*.dts)
++$(obj)/dtbImage.%: vmlinux $(wrapperbits) $(obj)/%.dtb
++ $(call if_changed,wrap,$*,,$(obj)/$*.dtb)
+
+ # This cannot be in the root of $(src) as the zImage rule always adds a $(obj)
+ # prefix
+@@ -302,14 +306,24 @@ $(obj)/zImage.iseries: vmlinux
+ $(obj)/uImage: vmlinux $(wrapperbits)
+ $(call if_changed,wrap,uboot)
+
+-$(obj)/cuImage.%: vmlinux $(dtstree)/%.dts $(wrapperbits)
+- $(call if_changed,wrap,cuboot-$*,$(dtstree)/$*.dts)
++$(obj)/cuImage.%: vmlinux $(obj)/%.dtb $(wrapperbits)
++ $(call if_changed,wrap,cuboot-$*,,$(obj)/$*.dtb)
+
+-$(obj)/treeImage.initrd.%: vmlinux $(dtstree)/%.dts $(wrapperbits)
+- $(call if_changed,wrap,treeboot-$*,$(dtstree)/$*.dts,,$(obj)/ramdisk.image.gz)
++$(obj)/simpleImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits)
++ $(call if_changed,wrap,simpleboot-$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz)
+
+-$(obj)/treeImage.%: vmlinux $(dtstree)/%.dts $(wrapperbits)
+- $(call if_changed,wrap,treeboot-$*,$(dtstree)/$*.dts)
++$(obj)/simpleImage.%: vmlinux $(obj)/%.dtb $(wrapperbits)
++ $(call if_changed,wrap,simpleboot-$*,,$(obj)/$*.dtb)
++
++$(obj)/treeImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits)
++ $(call if_changed,wrap,treeboot-$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz)
++
++$(obj)/treeImage.%: vmlinux $(obj)/%.dtb $(wrapperbits)
++ $(call if_changed,wrap,treeboot-$*,,$(obj)/$*.dtb)
++
++# Rule to build device tree blobs
++$(obj)/%.dtb: $(dtstree)/%.dts $(obj)/dtc
++ $(obj)/dtc -O dtb -o $(obj)/$*.dtb -b 0 $(DTS_FLAGS) $(dtstree)/$*.dts
+
+ # If there isn't a platform selected then just strip the vmlinux.
+ ifeq (,$(image-y))
+@@ -326,7 +340,7 @@ install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y))
+
+ # anything not in $(targets)
+ clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* treeImage.* \
+- otheros.bld
++ otheros.bld *.dtb
+
+ # clean up files cached by wrapper
+ clean-kernel := vmlinux.strip vmlinux.bin
+diff --git a/arch/powerpc/boot/bamboo.c b/arch/powerpc/boot/bamboo.c
+index 54b33f1..b82cacb 100644
+--- a/arch/powerpc/boot/bamboo.c
++++ b/arch/powerpc/boot/bamboo.c
+@@ -33,7 +33,8 @@ static void bamboo_fixups(void)
+ ibm440ep_fixup_clocks(sysclk, 11059200, 25000000);
+ ibm4xx_sdram_fixup_memsize();
+ ibm4xx_quiesce_eth((u32 *)0xef600e00, (u32 *)0xef600f00);
+- dt_fixup_mac_addresses(bamboo_mac0, bamboo_mac1);
++ dt_fixup_mac_address_by_alias("ethernet0", bamboo_mac0);
++ dt_fixup_mac_address_by_alias("ethernet1", bamboo_mac1);
+ }
+
+ void bamboo_init(void *mac0, void *mac1)
+diff --git a/arch/powerpc/boot/cpm-serial.c b/arch/powerpc/boot/cpm-serial.c
+index 28296fa..19dc15a 100644
+--- a/arch/powerpc/boot/cpm-serial.c
++++ b/arch/powerpc/boot/cpm-serial.c
+@@ -11,6 +11,7 @@
+ #include "types.h"
+ #include "io.h"
+ #include "ops.h"
++#include "page.h"
+
+ struct cpm_scc {
+ u32 gsmrl;
+@@ -42,6 +43,22 @@ struct cpm_param {
+ u16 tbase;
+ u8 rfcr;
+ u8 tfcr;
++ u16 mrblr;
++ u32 rstate;
++ u8 res1[4];
++ u16 rbptr;
++ u8 res2[6];
++ u32 tstate;
++ u8 res3[4];
++ u16 tbptr;
++ u8 res4[6];
++ u16 maxidl;
++ u16 idlc;
++ u16 brkln;
++ u16 brkec;
++ u16 brkcr;
++ u16 rmask;
++ u8 res5[4];
+ };
+
+ struct cpm_bd {
+@@ -54,10 +71,10 @@ static void *cpcr;
+ static struct cpm_param *param;
+ static struct cpm_smc *smc;
+ static struct cpm_scc *scc;
+-struct cpm_bd *tbdf, *rbdf;
++static struct cpm_bd *tbdf, *rbdf;
+ static u32 cpm_cmd;
+-static u8 *muram_start;
+-static u32 muram_offset;
++static void *cbd_addr;
++static u32 cbd_offset;
+
+ static void (*do_cmd)(int op);
+ static void (*enable_port)(void);
+@@ -119,20 +136,25 @@ static int cpm_serial_open(void)
+
+ out_8(¶m->rfcr, 0x10);
+ out_8(¶m->tfcr, 0x10);
+-
+- rbdf = (struct cpm_bd *)muram_start;
+- rbdf->addr = (u8 *)(rbdf + 2);
++ out_be16(¶m->mrblr, 1);
++ out_be16(¶m->maxidl, 0);
++ out_be16(¶m->brkec, 0);
++ out_be16(¶m->brkln, 0);
++ out_be16(¶m->brkcr, 0);
++
++ rbdf = cbd_addr;
++ rbdf->addr = (u8 *)rbdf - 1;
+ rbdf->sc = 0xa000;
+ rbdf->len = 1;
+
+ tbdf = rbdf + 1;
+- tbdf->addr = (u8 *)(rbdf + 2) + 1;
++ tbdf->addr = (u8 *)rbdf - 2;
+ tbdf->sc = 0x2000;
+ tbdf->len = 1;
+
+ sync();
+- out_be16(¶m->rbase, muram_offset);
+- out_be16(¶m->tbase, muram_offset + sizeof(struct cpm_bd));
++ out_be16(¶m->rbase, cbd_offset);
++ out_be16(¶m->tbase, cbd_offset + sizeof(struct cpm_bd));
+
+ do_cmd(CPM_CMD_INIT_RX_TX);
+
+@@ -175,10 +197,12 @@ static unsigned char cpm_serial_getc(void)
+
+ int cpm_console_init(void *devp, struct serial_console_data *scdp)
+ {
+- void *reg_virt[2];
+- int is_smc = 0, is_cpm2 = 0, n;
+- unsigned long reg_phys;
++ void *vreg[2];
++ u32 reg[2];
++ int is_smc = 0, is_cpm2 = 0;
+ void *parent, *muram;
++ void *muram_addr;
++ unsigned long muram_offset, muram_size;
+
+ if (dt_is_compatible(devp, "fsl,cpm1-smc-uart")) {
+ is_smc = 1;
+@@ -202,63 +226,64 @@ int cpm_console_init(void *devp, struct serial_console_data *scdp)
+ else
+ do_cmd = cpm1_cmd;
+
+- n = getprop(devp, "fsl,cpm-command", &cpm_cmd, 4);
+- if (n < 4)
++ if (getprop(devp, "fsl,cpm-command", &cpm_cmd, 4) < 4)
+ return -1;
+
+- n = getprop(devp, "virtual-reg", reg_virt, sizeof(reg_virt));
+- if (n < (int)sizeof(reg_virt)) {
+- for (n = 0; n < 2; n++) {
+- if (!dt_xlate_reg(devp, n, ®_phys, NULL))
+- return -1;
+-
+- reg_virt[n] = (void *)reg_phys;
+- }
+- }
++ if (dt_get_virtual_reg(devp, vreg, 2) < 2)
++ return -1;
+
+ if (is_smc)
+- smc = reg_virt[0];
++ smc = vreg[0];
+ else
+- scc = reg_virt[0];
++ scc = vreg[0];
+
+- param = reg_virt[1];
++ param = vreg[1];
+
+ parent = get_parent(devp);
+ if (!parent)
+ return -1;
+
+- n = getprop(parent, "virtual-reg", reg_virt, sizeof(reg_virt));
+- if (n < (int)sizeof(reg_virt)) {
+- if (!dt_xlate_reg(parent, 0, ®_phys, NULL))
+- return -1;
+-
+- reg_virt[0] = (void *)reg_phys;
+- }
+-
+- cpcr = reg_virt[0];
++ if (dt_get_virtual_reg(parent, &cpcr, 1) < 1)
++ return -1;
+
+ muram = finddevice("/soc/cpm/muram/data");
+ if (!muram)
+ return -1;
+
+ /* For bootwrapper-compatible device trees, we assume that the first
+- * entry has at least 18 bytes, and that #address-cells/#data-cells
++ * entry has at least 128 bytes, and that #address-cells/#data-cells
+ * is one for both parent and child.
+ */
+
+- n = getprop(muram, "virtual-reg", reg_virt, sizeof(reg_virt));
+- if (n < (int)sizeof(reg_virt)) {
+- if (!dt_xlate_reg(muram, 0, ®_phys, NULL))
+- return -1;
++ if (dt_get_virtual_reg(muram, &muram_addr, 1) < 1)
++ return -1;
+
+- reg_virt[0] = (void *)reg_phys;
+- }
++ if (getprop(muram, "reg", reg, 8) < 8)
++ return -1;
+
+- muram_start = reg_virt[0];
++ muram_offset = reg[0];
++ muram_size = reg[1];
+
+- n = getprop(muram, "reg", &muram_offset, 4);
+- if (n < 4)
+- return -1;
++ /* Store the buffer descriptors at the end of the first muram chunk.
++ * For SMC ports on CPM2-based platforms, relocate the parameter RAM
++ * just before the buffer descriptors.
++ */
++
++ cbd_offset = muram_offset + muram_size - 2 * sizeof(struct cpm_bd);
++
++ if (is_cpm2 && is_smc) {
++ u16 *smc_base = (u16 *)param;
++ u16 pram_offset;
++
++ pram_offset = cbd_offset - 64;
++ pram_offset = _ALIGN_DOWN(pram_offset, 64);
++
++ disable_port();
++ out_be16(smc_base, pram_offset);
++ param = muram_addr - muram_offset + pram_offset;
++ }
++
++ cbd_addr = muram_addr - muram_offset + cbd_offset;
+
+ scdp->open = cpm_serial_open;
+ scdp->putc = cpm_serial_putc;
+diff --git a/arch/powerpc/boot/cuboot-pq2.c b/arch/powerpc/boot/cuboot-pq2.c
+index f56ac6c..9c7d134 100644
+--- a/arch/powerpc/boot/cuboot-pq2.c
++++ b/arch/powerpc/boot/cuboot-pq2.c
+@@ -128,7 +128,7 @@ static void fixup_pci(void)
+ u8 *soc_regs;
+ int i, len;
+ void *node, *parent_node;
+- u32 naddr, nsize, mem_log2;
++ u32 naddr, nsize, mem_pow2, mem_mask;
+
+ node = finddevice("/pci");
+ if (!node || !dt_is_compatible(node, "fsl,pq2-pci"))
+@@ -141,7 +141,7 @@ static void fixup_pci(void)
+
+ soc_regs = (u8 *)fsl_get_immr();
+ if (!soc_regs)
+- goto err;
++ goto unhandled;
+
+ dt_get_reg_format(node, &naddr, &nsize);
+ if (naddr != 3 || nsize != 2)
+@@ -153,7 +153,7 @@ static void fixup_pci(void)
+
+ dt_get_reg_format(parent_node, &naddr, &nsize);
+ if (naddr != 1 || nsize != 1)
+- goto err;
++ goto unhandled;
+
+ len = getprop(node, "ranges", pci_ranges_buf,
+ sizeof(pci_ranges_buf));
+@@ -170,14 +170,20 @@ static void fixup_pci(void)
+ }
+
+ if (!mem || !mmio || !io)
+- goto err;
++ goto unhandled;
++ if (mem->size[1] != mmio->size[1])
++ goto unhandled;
++ if (mem->size[1] & (mem->size[1] - 1))
++ goto unhandled;
++ if (io->size[1] & (io->size[1] - 1))
++ goto unhandled;
+
+ if (mem->phys_addr + mem->size[1] == mmio->phys_addr)
+ mem_base = mem;
+ else if (mmio->phys_addr + mmio->size[1] == mem->phys_addr)
+ mem_base = mmio;
+ else
+- goto err;
++ goto unhandled;
+
+ out_be32(&pci_regs[1][0], mem_base->phys_addr | 1);
+ out_be32(&pci_regs[2][0], ~(mem->size[1] + mmio->size[1] - 1));
+@@ -201,8 +207,9 @@ static void fixup_pci(void)
+ out_le32(&pci_regs[0][58], 0);
+ out_le32(&pci_regs[0][60], 0);
+
+- mem_log2 = 1 << (__ilog2_u32(bd.bi_memsize - 1) + 1);
+- out_le32(&pci_regs[0][62], 0xa0000000 | ~((1 << (mem_log2 - 12)) - 1));
++ mem_pow2 = 1 << (__ilog2_u32(bd.bi_memsize - 1) + 1);
++ mem_mask = ~(mem_pow2 - 1) >> 12;
++ out_le32(&pci_regs[0][62], 0xa0000000 | mem_mask);
+
+ /* If PCI is disabled, drive RST high to enable. */
+ if (!(in_le32(&pci_regs[0][32]) & 1)) {
+@@ -228,7 +235,11 @@ static void fixup_pci(void)
+ return;
+
+ err:
+- printf("Bad PCI node\r\n");
++ printf("Bad PCI node -- using existing firmware setup.\r\n");
++ return;
++
++unhandled:
++ printf("Unsupported PCI node -- using existing firmware setup.\r\n");
+ }
+
+ static void pq2_platform_fixups(void)
+diff --git a/arch/powerpc/boot/cuboot-rainier.c b/arch/powerpc/boot/cuboot-rainier.c
+index cf452b6..0a3fdde 100644
+--- a/arch/powerpc/boot/cuboot-rainier.c
++++ b/arch/powerpc/boot/cuboot-rainier.c
+@@ -42,7 +42,8 @@ static void rainier_fixups(void)
+ ibm440ep_fixup_clocks(sysclk, 11059200, 50000000);
+ ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
+ ibm4xx_denali_fixup_memsize();
+- dt_fixup_mac_addresses(&bd.bi_enetaddr, &bd.bi_enet1addr);
++ dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
++ dt_fixup_mac_address_by_alias("ethernet1", bd.bi_enet1addr);
+ }
+
+ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+diff --git a/arch/powerpc/boot/cuboot-sequoia.c b/arch/powerpc/boot/cuboot-sequoia.c
+index f555575..caf8f2e 100644
+--- a/arch/powerpc/boot/cuboot-sequoia.c
++++ b/arch/powerpc/boot/cuboot-sequoia.c
+@@ -42,7 +42,8 @@ static void sequoia_fixups(void)
+ ibm440ep_fixup_clocks(sysclk, 11059200, 50000000);
+ ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
+ ibm4xx_denali_fixup_memsize();
+- dt_fixup_mac_addresses(&bd.bi_enetaddr, &bd.bi_enet1addr);
++ dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
++ dt_fixup_mac_address_by_alias("ethernet1", bd.bi_enet1addr);
+ }
+
+ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+diff --git a/arch/powerpc/boot/cuboot-taishan.c b/arch/powerpc/boot/cuboot-taishan.c
+index b55b804..9bc906a 100644
+--- a/arch/powerpc/boot/cuboot-taishan.c
++++ b/arch/powerpc/boot/cuboot-taishan.c
+@@ -40,7 +40,8 @@ static void taishan_fixups(void)
+
+ ibm4xx_sdram_fixup_memsize();
+
+- dt_fixup_mac_addresses(bd.bi_enetaddr, bd.bi_enet1addr);
++ dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
++ dt_fixup_mac_address_by_alias("ethernet1", bd.bi_enet1addr);
+
+ ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
+ }
+diff --git a/arch/powerpc/boot/cuboot-warp.c b/arch/powerpc/boot/cuboot-warp.c
+index 3db93e8..eb108a8 100644
+--- a/arch/powerpc/boot/cuboot-warp.c
++++ b/arch/powerpc/boot/cuboot-warp.c
+@@ -24,7 +24,7 @@ static void warp_fixups(void)
+ ibm440ep_fixup_clocks(sysclk, 11059200, 50000000);
+ ibm4xx_sdram_fixup_memsize();
+ ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
+- dt_fixup_mac_addresses(&bd.bi_enetaddr);
++ dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
+ }
+
+
+diff --git a/arch/powerpc/boot/cuboot-yosemite.c b/arch/powerpc/boot/cuboot-yosemite.c
+new file mode 100644
+index 0000000..cc6e338
+--- /dev/null
++++ b/arch/powerpc/boot/cuboot-yosemite.c
+@@ -0,0 +1,44 @@
++/*
++ * Old U-boot compatibility for Yosemite
++ *
++ * Author: Josh Boyer <jwboyer at linux.vnet.ibm.com>
++ *
++ * Copyright 2008 IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ */
++
++#include "ops.h"
++#include "stdio.h"
++#include "4xx.h"
++#include "44x.h"
++#include "cuboot.h"
++
++#define TARGET_4xx
++#define TARGET_44x
++#include "ppcboot.h"
++
++static bd_t bd;
++
++static void yosemite_fixups(void)
++{
++ unsigned long sysclk = 66666666;
++
++ ibm440ep_fixup_clocks(sysclk, 11059200, 50000000);
++ ibm4xx_sdram_fixup_memsize();
++ ibm4xx_quiesce_eth((u32 *)0xef600e00, (u32 *)0xef600f00);
++ dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
++ dt_fixup_mac_address_by_alias("ethernet1", bd.bi_enet1addr);
++}
++
++void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
++ unsigned long r6, unsigned long r7)
++{
++ CUBOOT_INIT();
++ platform_ops.fixups = yosemite_fixups;
++ platform_ops.exit = ibm44x_dbcr_reset;
++ fdt_init(_dtb_start);
++ serial_console_init();
++}
+diff --git a/arch/powerpc/boot/devtree.c b/arch/powerpc/boot/devtree.c
+index 60f561e..5d12336 100644
+--- a/arch/powerpc/boot/devtree.c
++++ b/arch/powerpc/boot/devtree.c
+@@ -350,3 +350,23 @@ int dt_is_compatible(void *node, const char *compat)
+
+ return 0;
+ }
++
++int dt_get_virtual_reg(void *node, void **addr, int nres)
++{
++ unsigned long xaddr;
++ int n;
++
++ n = getprop(node, "virtual-reg", addr, nres * 4);
++ if (n > 0)
++ return n / 4;
++
++ for (n = 0; n < nres; n++) {
++ if (!dt_xlate_reg(node, n, &xaddr, NULL))
++ break;
++
++ addr[n] = (void *)xaddr;
++ }
++
++ return n;
++}
++
+diff --git a/arch/powerpc/boot/dts/bamboo.dts b/arch/powerpc/boot/dts/bamboo.dts
+index 7dc37c9..ba2521b 100644
+--- a/arch/powerpc/boot/dts/bamboo.dts
++++ b/arch/powerpc/boot/dts/bamboo.dts
+@@ -204,7 +204,6 @@
+ };
+
+ EMAC0: ethernet at ef600e00 {
+- linux,network-index = <0>;
+ device_type = "network";
+ compatible = "ibm,emac-440ep", "ibm,emac-440gp", "ibm,emac";
+ interrupt-parent = <&UIC1>;
+@@ -225,7 +224,6 @@
+ };
+
+ EMAC1: ethernet at ef600f00 {
+- linux,network-index = <1>;
+ device_type = "network";
+ compatible = "ibm,emac-440ep", "ibm,emac-440gp", "ibm,emac";
+ interrupt-parent = <&UIC1>;
+diff --git a/arch/powerpc/boot/dts/canyonlands.dts b/arch/powerpc/boot/dts/canyonlands.dts
+new file mode 100644
+index 0000000..3963412
+--- /dev/null
++++ b/arch/powerpc/boot/dts/canyonlands.dts
+@@ -0,0 +1,439 @@
++/*
++ * Device Tree Source for AMCC Canyonlands (460EX)
++ *
++ * Copyright 2008 DENX Software Engineering, Stefan Roese <sr at denx.de>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without
++ * any warranty of any kind, whether express or implied.
++ */
++
++/ {
++ #address-cells = <2>;
++ #size-cells = <1>;
++ model = "amcc,canyonlands";
++ compatible = "amcc,canyonlands";
++ dcr-parent = <&/cpus/cpu at 0>;
++
++ aliases {
++ ethernet0 = &EMAC0;
++ ethernet1 = &EMAC1;
++ serial0 = &UART0;
++ serial1 = &UART1;
++ };
++
++ cpus {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ cpu at 0 {
++ device_type = "cpu";
++ model = "PowerPC,460EX";
++ reg = <0>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++ timebase-frequency = <0>; /* Filled in by U-Boot */
++ i-cache-line-size = <20>;
++ d-cache-line-size = <20>;
++ i-cache-size = <8000>;
++ d-cache-size = <8000>;
++ dcr-controller;
++ dcr-access-method = "native";
++ };
++ };
++
++ memory {
++ device_type = "memory";
++ reg = <0 0 0>; /* Filled in by U-Boot */
++ };
++
++ UIC0: interrupt-controller0 {
++ compatible = "ibm,uic-460ex","ibm,uic";
++ interrupt-controller;
++ cell-index = <0>;
++ dcr-reg = <0c0 009>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ #interrupt-cells = <2>;
++ };
++
++ UIC1: interrupt-controller1 {
++ compatible = "ibm,uic-460ex","ibm,uic";
++ interrupt-controller;
++ cell-index = <1>;
++ dcr-reg = <0d0 009>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ #interrupt-cells = <2>;
++ interrupts = <1e 4 1f 4>; /* cascade */
++ interrupt-parent = <&UIC0>;
++ };
++
++ UIC2: interrupt-controller2 {
++ compatible = "ibm,uic-460ex","ibm,uic";
++ interrupt-controller;
++ cell-index = <2>;
++ dcr-reg = <0e0 009>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ #interrupt-cells = <2>;
++ interrupts = <a 4 b 4>; /* cascade */
++ interrupt-parent = <&UIC0>;
++ };
++
++ UIC3: interrupt-controller3 {
++ compatible = "ibm,uic-460ex","ibm,uic";
++ interrupt-controller;
++ cell-index = <3>;
++ dcr-reg = <0f0 009>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ #interrupt-cells = <2>;
++ interrupts = <10 4 11 4>; /* cascade */
++ interrupt-parent = <&UIC0>;
++ };
++
++ SDR0: sdr {
++ compatible = "ibm,sdr-460ex";
++ dcr-reg = <00e 002>;
++ };
++
++ CPR0: cpr {
++ compatible = "ibm,cpr-460ex";
++ dcr-reg = <00c 002>;
++ };
++
++ plb {
++ compatible = "ibm,plb-460ex", "ibm,plb4";
++ #address-cells = <2>;
++ #size-cells = <1>;
++ ranges;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++
++ SDRAM0: sdram {
++ compatible = "ibm,sdram-460ex", "ibm,sdram-405gp";
++ dcr-reg = <010 2>;
++ };
++
++ MAL0: mcmal {
++ compatible = "ibm,mcmal-460ex", "ibm,mcmal2";
++ dcr-reg = <180 62>;
++ num-tx-chans = <2>;
++ num-rx-chans = <10>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ interrupt-parent = <&UIC2>;
++ interrupts = < /*TXEOB*/ 6 4
++ /*RXEOB*/ 7 4
++ /*SERR*/ 3 4
++ /*TXDE*/ 4 4
++ /*RXDE*/ 5 4>;
++ };
++
++ POB0: opb {
++ compatible = "ibm,opb-460ex", "ibm,opb";
++ #address-cells = <1>;
++ #size-cells = <1>;
++ ranges = <b0000000 4 b0000000 50000000>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++
++ EBC0: ebc {
++ compatible = "ibm,ebc-460ex", "ibm,ebc";
++ dcr-reg = <012 2>;
++ #address-cells = <2>;
++ #size-cells = <1>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++ /* ranges property is supplied by U-Boot */
++ interrupts = <6 4>;
++ interrupt-parent = <&UIC1>;
++
++ nor_flash at 0,0 {
++ compatible = "amd,s29gl512n", "cfi-flash";
++ bank-width = <2>;
++ reg = <0 000000 4000000>;
++ #address-cells = <1>;
++ #size-cells = <1>;
++ partition at 0 {
++ label = "kernel";
++ reg = <0 1e0000>;
++ };
++ partition at 1e0000 {
++ label = "dtb";
++ reg = <1e0000 20000>;
++ };
++ partition at 200000 {
++ label = "ramdisk";
++ reg = <200000 1400000>;
++ };
++ partition at 1600000 {
++ label = "jffs2";
++ reg = <1600000 400000>;
++ };
++ partition at 1a00000 {
++ label = "user";
++ reg = <1a00000 2560000>;
++ };
++ partition at 3f60000 {
++ label = "env";
++ reg = <3f60000 40000>;
++ };
++ partition at 3fa0000 {
++ label = "u-boot";
++ reg = <3fa0000 60000>;
++ };
++ };
++ };
++
++ UART0: serial at ef600300 {
++ device_type = "serial";
++ compatible = "ns16550";
++ reg = <ef600300 8>;
++ virtual-reg = <ef600300>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++ current-speed = <0>; /* Filled in by U-Boot */
++ interrupt-parent = <&UIC1>;
++ interrupts = <1 4>;
++ };
++
++ UART1: serial at ef600400 {
++ device_type = "serial";
++ compatible = "ns16550";
++ reg = <ef600400 8>;
++ virtual-reg = <ef600400>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++ current-speed = <0>; /* Filled in by U-Boot */
++ interrupt-parent = <&UIC0>;
++ interrupts = <1 4>;
++ };
++
++ UART2: serial at ef600500 {
++ device_type = "serial";
++ compatible = "ns16550";
++ reg = <ef600500 8>;
++ virtual-reg = <ef600500>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++ current-speed = <0>; /* Filled in by U-Boot */
++ interrupt-parent = <&UIC1>;
++ interrupts = <1d 4>;
++ };
++
++ UART3: serial at ef600600 {
++ device_type = "serial";
++ compatible = "ns16550";
++ reg = <ef600600 8>;
++ virtual-reg = <ef600600>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++ current-speed = <0>; /* Filled in by U-Boot */
++ interrupt-parent = <&UIC1>;
++ interrupts = <1e 4>;
++ };
++
++ IIC0: i2c at ef600700 {
++ compatible = "ibm,iic-460ex", "ibm,iic";
++ reg = <ef600700 14>;
++ interrupt-parent = <&UIC0>;
++ interrupts = <2 4>;
++ };
++
++ IIC1: i2c at ef600800 {
++ compatible = "ibm,iic-460ex", "ibm,iic";
++ reg = <ef600800 14>;
++ interrupt-parent = <&UIC0>;
++ interrupts = <3 4>;
++ };
++
++ ZMII0: emac-zmii at ef600d00 {
++ compatible = "ibm,zmii-460ex", "ibm,zmii";
++ reg = <ef600d00 c>;
++ };
++
++ RGMII0: emac-rgmii at ef601500 {
++ compatible = "ibm,rgmii-460ex", "ibm,rgmii";
++ reg = <ef601500 8>;
++ has-mdio;
++ };
++
++ TAH0: emac-tah at ef601350 {
++ compatible = "ibm,tah-460ex", "ibm,tah";
++ reg = <ef601350 30>;
++ };
++
++ TAH1: emac-tah at ef601450 {
++ compatible = "ibm,tah-460ex", "ibm,tah";
++ reg = <ef601450 30>;
++ };
++
++ EMAC0: ethernet at ef600e00 {
++ device_type = "network";
++ compatible = "ibm,emac-460ex", "ibm,emac4";
++ interrupt-parent = <&EMAC0>;
++ interrupts = <0 1>;
++ #interrupt-cells = <1>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ interrupt-map = </*Status*/ 0 &UIC2 10 4
++ /*Wake*/ 1 &UIC2 14 4>;
++ reg = <ef600e00 70>;
++ local-mac-address = [000000000000]; /* Filled in by U-Boot */
++ mal-device = <&MAL0>;
++ mal-tx-channel = <0>;
++ mal-rx-channel = <0>;
++ cell-index = <0>;
++ max-frame-size = <2328>;
++ rx-fifo-size = <1000>;
++ tx-fifo-size = <800>;
++ phy-mode = "rgmii";
++ phy-map = <00000000>;
++ rgmii-device = <&RGMII0>;
++ rgmii-channel = <0>;
++ tah-device = <&TAH0>;
++ tah-channel = <0>;
++ has-inverted-stacr-oc;
++ has-new-stacr-staopc;
++ };
++
++ EMAC1: ethernet at ef600f00 {
++ device_type = "network";
++ compatible = "ibm,emac-460ex", "ibm,emac4";
++ interrupt-parent = <&EMAC1>;
++ interrupts = <0 1>;
++ #interrupt-cells = <1>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ interrupt-map = </*Status*/ 0 &UIC2 11 4
++ /*Wake*/ 1 &UIC2 15 4>;
++ reg = <ef600f00 70>;
++ local-mac-address = [000000000000]; /* Filled in by U-Boot */
++ mal-device = <&MAL0>;
++ mal-tx-channel = <1>;
++ mal-rx-channel = <8>;
++ cell-index = <1>;
++ max-frame-size = <2328>;
++ rx-fifo-size = <1000>;
++ tx-fifo-size = <800>;
++ phy-mode = "rgmii";
++ phy-map = <00000000>;
++ rgmii-device = <&RGMII0>;
++ rgmii-channel = <1>;
++ tah-device = <&TAH1>;
++ tah-channel = <1>;
++ has-inverted-stacr-oc;
++ has-new-stacr-staopc;
++ mdio-device = <&EMAC0>;
++ };
++ };
++
++ PCIX0: pci at c0ec00000 {
++ device_type = "pci";
++ #interrupt-cells = <1>;
++ #size-cells = <2>;
++ #address-cells = <3>;
++ compatible = "ibm,plb-pcix-460ex", "ibm,plb-pcix";
++ primary;
++ large-inbound-windows;
++ enable-msi-hole;
++ reg = <c 0ec00000 8 /* Config space access */
++ 0 0 0 /* no IACK cycles */
++ c 0ed00000 4 /* Special cycles */
++ c 0ec80000 100 /* Internal registers */
++ c 0ec80100 fc>; /* Internal messaging registers */
++
++ /* Outbound ranges, one memory and one IO,
++ * later cannot be changed
++ */
++ ranges = <02000000 0 80000000 0000000d 80000000 0 80000000
++ 01000000 0 00000000 0000000c 08000000 0 00010000>;
++
++ /* Inbound 2GB range starting at 0 */
++ dma-ranges = <42000000 0 0 0 0 0 80000000>;
++
++ /* This drives busses 0 to 0x3f */
++ bus-range = <0 3f>;
++
++ /* All PCI interrupts are routed to ext IRQ 2 -> UIC1-0 */
++ interrupt-map-mask = <0000 0 0 0>;
++ interrupt-map = < 0000 0 0 0 &UIC1 0 8 >;
++ };
++
++ PCIE0: pciex at d00000000 {
++ device_type = "pci";
++ #interrupt-cells = <1>;
++ #size-cells = <2>;
++ #address-cells = <3>;
++ compatible = "ibm,plb-pciex-460ex", "ibm,plb-pciex";
++ primary;
++ port = <0>; /* port number */
++ reg = <d 00000000 20000000 /* Config space access */
++ c 08010000 00001000>; /* Registers */
++ dcr-reg = <100 020>;
++ sdr-base = <300>;
++
++ /* Outbound ranges, one memory and one IO,
++ * later cannot be changed
++ */
++ ranges = <02000000 0 80000000 0000000e 00000000 0 80000000
++ 01000000 0 00000000 0000000f 80000000 0 00010000>;
++
++ /* Inbound 2GB range starting at 0 */
++ dma-ranges = <42000000 0 0 0 0 0 80000000>;
++
++ /* This drives busses 40 to 0x7f */
++ bus-range = <40 7f>;
++
++ /* Legacy interrupts (note the weird polarity, the bridge seems
++ * to invert PCIe legacy interrupts).
++ * We are de-swizzling here because the numbers are actually for
++ * port of the root complex virtual P2P bridge. But I want
++ * to avoid putting a node for it in the tree, so the numbers
++ * below are basically de-swizzled numbers.
++ * The real slot is on idsel 0, so the swizzling is 1:1
++ */
++ interrupt-map-mask = <0000 0 0 7>;
++ interrupt-map = <
++ 0000 0 0 1 &UIC3 c 4 /* swizzled int A */
++ 0000 0 0 2 &UIC3 d 4 /* swizzled int B */
++ 0000 0 0 3 &UIC3 e 4 /* swizzled int C */
++ 0000 0 0 4 &UIC3 f 4 /* swizzled int D */>;
++ };
++
++ PCIE1: pciex at d20000000 {
++ device_type = "pci";
++ #interrupt-cells = <1>;
++ #size-cells = <2>;
++ #address-cells = <3>;
++ compatible = "ibm,plb-pciex-460ex", "ibm,plb-pciex";
++ primary;
++ port = <1>; /* port number */
++ reg = <d 20000000 20000000 /* Config space access */
++ c 08011000 00001000>; /* Registers */
++ dcr-reg = <120 020>;
++ sdr-base = <340>;
++
++ /* Outbound ranges, one memory and one IO,
++ * later cannot be changed
++ */
++ ranges = <02000000 0 80000000 0000000e 80000000 0 80000000
++ 01000000 0 00000000 0000000f 80010000 0 00010000>;
++
++ /* Inbound 2GB range starting at 0 */
++ dma-ranges = <42000000 0 0 0 0 0 80000000>;
++
++ /* This drives busses 80 to 0xbf */
++ bus-range = <80 bf>;
++
++ /* Legacy interrupts (note the weird polarity, the bridge seems
++ * to invert PCIe legacy interrupts).
++ * We are de-swizzling here because the numbers are actually for
++ * port of the root complex virtual P2P bridge. But I want
++ * to avoid putting a node for it in the tree, so the numbers
++ * below are basically de-swizzled numbers.
++ * The real slot is on idsel 0, so the swizzling is 1:1
++ */
++ interrupt-map-mask = <0000 0 0 7>;
++ interrupt-map = <
++ 0000 0 0 1 &UIC3 10 4 /* swizzled int A */
++ 0000 0 0 2 &UIC3 11 4 /* swizzled int B */
++ 0000 0 0 3 &UIC3 12 4 /* swizzled int C */
++ 0000 0 0 4 &UIC3 13 4 /* swizzled int D */>;
++ };
++ };
++};
+diff --git a/arch/powerpc/boot/dts/ebony.dts b/arch/powerpc/boot/dts/ebony.dts
+index 0b000cb..5079dc8 100644
+--- a/arch/powerpc/boot/dts/ebony.dts
++++ b/arch/powerpc/boot/dts/ebony.dts
+@@ -241,7 +241,6 @@
+ };
+
+ EMAC0: ethernet at 40000800 {
+- linux,network-index = <0>;
+ device_type = "network";
+ compatible = "ibm,emac-440gp", "ibm,emac";
+ interrupt-parent = <&UIC1>;
+@@ -261,7 +260,6 @@
+ zmii-channel = <0>;
+ };
+ EMAC1: ethernet at 40000900 {
+- linux,network-index = <1>;
+ device_type = "network";
+ compatible = "ibm,emac-440gp", "ibm,emac";
+ interrupt-parent = <&UIC1>;
+diff --git a/arch/powerpc/boot/dts/ep8248e.dts b/arch/powerpc/boot/dts/ep8248e.dts
+index 5d2fb76..756758f 100644
+--- a/arch/powerpc/boot/dts/ep8248e.dts
++++ b/arch/powerpc/boot/dts/ep8248e.dts
+@@ -121,8 +121,7 @@
+
+ data at 0 {
+ compatible = "fsl,cpm-muram-data";
+- reg = <0 0x1100 0x1140
+- 0xec0 0x9800 0x800>;
++ reg = <0 0x2000 0x9800 0x800>;
+ };
+ };
+
+@@ -138,7 +137,7 @@
+ device_type = "serial";
+ compatible = "fsl,mpc8248-smc-uart",
+ "fsl,cpm2-smc-uart";
+- reg = <0x11a80 0x20 0x1100 0x40>;
++ reg = <0x11a80 0x20 0x87fc 2>;
+ interrupts = <4 8>;
+ interrupt-parent = <&PIC>;
+ fsl,cpm-brg = <7>;
+diff --git a/arch/powerpc/boot/dts/ep88xc.dts b/arch/powerpc/boot/dts/ep88xc.dts
+index 02705f2..ae57d62 100644
+--- a/arch/powerpc/boot/dts/ep88xc.dts
++++ b/arch/powerpc/boot/dts/ep88xc.dts
+@@ -2,7 +2,7 @@
+ * EP88xC Device Tree Source
+ *
+ * Copyright 2006 MontaVista Software, Inc.
+- * Copyright 2007 Freescale Semiconductor, Inc.
++ * Copyright 2007,2008 Freescale Semiconductor, Inc.
+ *
+ * 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
+@@ -10,6 +10,7 @@
+ * option) any later version.
+ */
+
++/dts-v1/;
+
+ / {
+ model = "EP88xC";
+@@ -23,44 +24,44 @@
+
+ PowerPC,885 at 0 {
+ device_type = "cpu";
+- reg = <0>;
+- d-cache-line-size = <d#16>;
+- i-cache-line-size = <d#16>;
+- d-cache-size = <d#8192>;
+- i-cache-size = <d#8192>;
++ reg = <0x0>;
++ d-cache-line-size = <16>;
++ i-cache-line-size = <16>;
++ d-cache-size = <8192>;
++ i-cache-size = <8192>;
+ timebase-frequency = <0>;
+ bus-frequency = <0>;
+ clock-frequency = <0>;
+- interrupts = <f 2>; // decrementer interrupt
++ interrupts = <15 2>; // decrementer interrupt
+ interrupt-parent = <&PIC>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+- reg = <0 0>;
++ reg = <0x0 0x0>;
+ };
+
+ localbus at fa200100 {
+ compatible = "fsl,mpc885-localbus", "fsl,pq1-localbus";
+ #address-cells = <2>;
+ #size-cells = <1>;
+- reg = <fa200100 40>;
++ reg = <0xfa200100 0x40>;
+
+ ranges = <
+- 0 0 fc000000 04000000
+- 3 0 fa000000 01000000
++ 0x0 0x0 0xfc000000 0x4000000
++ 0x3 0x0 0xfa000000 0x1000000
+ >;
+
+ flash at 0,2000000 {
+ compatible = "cfi-flash";
+- reg = <0 2000000 2000000>;
++ reg = <0x0 0x2000000 0x2000000>;
+ bank-width = <4>;
+ device-width = <2>;
+ };
+
+ board-control at 3,400000 {
+- reg = <3 400000 10>;
++ reg = <0x3 0x400000 0x10>;
+ compatible = "fsl,ep88xc-bcsr";
+ };
+ };
+@@ -70,25 +71,25 @@
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+- ranges = <0 fa200000 00004000>;
++ ranges = <0x0 0xfa200000 0x4000>;
+ bus-frequency = <0>;
+
+ // Temporary -- will go away once kernel uses ranges for get_immrbase().
+- reg = <fa200000 4000>;
++ reg = <0xfa200000 0x4000>;
+
+ mdio at e00 {
+ compatible = "fsl,mpc885-fec-mdio", "fsl,pq1-fec-mdio";
+- reg = <e00 188>;
++ reg = <0xe00 0x188>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ PHY0: ethernet-phy at 0 {
+- reg = <0>;
++ reg = <0x0>;
+ device_type = "ethernet-phy";
+ };
+
+ PHY1: ethernet-phy at 1 {
+- reg = <1>;
++ reg = <0x1>;
+ device_type = "ethernet-phy";
+ };
+ };
+@@ -97,7 +98,7 @@
+ device_type = "network";
+ compatible = "fsl,mpc885-fec-enet",
+ "fsl,pq1-fec-enet";
+- reg = <e00 188>;
++ reg = <0xe00 0x188>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <3 1>;
+ interrupt-parent = <&PIC>;
+@@ -109,7 +110,7 @@
+ device_type = "network";
+ compatible = "fsl,mpc885-fec-enet",
+ "fsl,pq1-fec-enet";
+- reg = <1e00 188>;
++ reg = <0x1e00 0x188>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <7 1>;
+ interrupt-parent = <&PIC>;
+@@ -120,7 +121,7 @@
+ PIC: interrupt-controller at 0 {
+ interrupt-controller;
+ #interrupt-cells = <2>;
+- reg = <0 24>;
++ reg = <0x0 0x24>;
+ compatible = "fsl,mpc885-pic", "fsl,pq1-pic";
+ };
+
+@@ -130,29 +131,29 @@
+ #size-cells = <2>;
+ compatible = "fsl,pq-pcmcia";
+ device_type = "pcmcia";
+- reg = <80 80>;
++ reg = <0x80 0x80>;
+ interrupt-parent = <&PIC>;
+- interrupts = <d 1>;
++ interrupts = <13 1>;
+ };
+
+ cpm at 9c0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc885-cpm", "fsl,cpm1";
+- command-proc = <9c0>;
++ command-proc = <0x9c0>;
+ interrupts = <0>; // cpm error interrupt
+ interrupt-parent = <&CPM_PIC>;
+- reg = <9c0 40>;
++ reg = <0x9c0 0x40>;
+ ranges;
+
+ muram at 2000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+- ranges = <0 2000 2000>;
++ ranges = <0x0 0x2000 0x2000>;
+
+ data at 0 {
+ compatible = "fsl,cpm-muram-data";
+- reg = <0 1c00>;
++ reg = <0x0 0x1c00>;
+ };
+ };
+
+@@ -160,7 +161,7 @@
+ compatible = "fsl,mpc885-brg",
+ "fsl,cpm1-brg",
+ "fsl,cpm-brg";
+- reg = <9f0 10>;
++ reg = <0x9f0 0x10>;
+ };
+
+ CPM_PIC: interrupt-controller at 930 {
+@@ -168,7 +169,7 @@
+ #interrupt-cells = <1>;
+ interrupts = <5 2 0 2>;
+ interrupt-parent = <&PIC>;
+- reg = <930 20>;
++ reg = <0x930 0x20>;
+ compatible = "fsl,mpc885-cpm-pic",
+ "fsl,cpm1-pic";
+ };
+@@ -178,11 +179,11 @@
+ device_type = "serial";
+ compatible = "fsl,mpc885-smc-uart",
+ "fsl,cpm1-smc-uart";
+- reg = <a80 10 3e80 40>;
++ reg = <0xa80 0x10 0x3e80 0x40>;
+ interrupts = <4>;
+ interrupt-parent = <&CPM_PIC>;
+ fsl,cpm-brg = <1>;
+- fsl,cpm-command = <0090>;
++ fsl,cpm-command = <0x90>;
+ linux,planetcore-label = "SMC1";
+ };
+
+@@ -191,11 +192,11 @@
+ device_type = "serial";
+ compatible = "fsl,mpc885-scc-uart",
+ "fsl,cpm1-scc-uart";
+- reg = <a20 20 3d00 80>;
+- interrupts = <1d>;
++ reg = <0xa20 0x20 0x3d00 0x80>;
++ interrupts = <29>;
+ interrupt-parent = <&CPM_PIC>;
+ fsl,cpm-brg = <2>;
+- fsl,cpm-command = <0040>;
++ fsl,cpm-command = <0x40>;
+ linux,planetcore-label = "SCC2";
+ };
+
+@@ -204,9 +205,9 @@
+ #size-cells = <0>;
+ compatible = "fsl,mpc885-usb",
+ "fsl,cpm1-usb";
+- reg = <a00 18 1c00 80>;
++ reg = <0xa00 0x18 0x1c00 0x80>;
+ interrupt-parent = <&CPM_PIC>;
+- interrupts = <1e>;
++ interrupts = <30>;
+ fsl,cpm-command = <0000>;
+ };
+ };
+diff --git a/arch/powerpc/boot/dts/glacier.dts b/arch/powerpc/boot/dts/glacier.dts
+new file mode 100644
+index 0000000..0f2fc07
+--- /dev/null
++++ b/arch/powerpc/boot/dts/glacier.dts
+@@ -0,0 +1,504 @@
++/*
++ * Device Tree Source for AMCC Glacier (460GT)
++ *
++ * Copyright 2008 DENX Software Engineering, Stefan Roese <sr at denx.de>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without
++ * any warranty of any kind, whether express or implied.
++ */
++
++/ {
++ #address-cells = <2>;
++ #size-cells = <1>;
++ model = "amcc,glacier";
++ compatible = "amcc,glacier", "amcc,canyonlands";
++ dcr-parent = <&/cpus/cpu at 0>;
++
++ aliases {
++ ethernet0 = &EMAC0;
++ ethernet1 = &EMAC1;
++ ethernet2 = &EMAC2;
++ ethernet3 = &EMAC3;
++ serial0 = &UART0;
++ serial1 = &UART1;
++ };
++
++ cpus {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ cpu at 0 {
++ device_type = "cpu";
++ model = "PowerPC,460GT";
++ reg = <0>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++ timebase-frequency = <0>; /* Filled in by U-Boot */
++ i-cache-line-size = <20>;
++ d-cache-line-size = <20>;
++ i-cache-size = <8000>;
++ d-cache-size = <8000>;
++ dcr-controller;
++ dcr-access-method = "native";
++ };
++ };
++
++ memory {
++ device_type = "memory";
++ reg = <0 0 0>; /* Filled in by U-Boot */
++ };
++
++ UIC0: interrupt-controller0 {
++ compatible = "ibm,uic-460gt","ibm,uic";
++ interrupt-controller;
++ cell-index = <0>;
++ dcr-reg = <0c0 009>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ #interrupt-cells = <2>;
++ };
++
++ UIC1: interrupt-controller1 {
++ compatible = "ibm,uic-460gt","ibm,uic";
++ interrupt-controller;
++ cell-index = <1>;
++ dcr-reg = <0d0 009>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ #interrupt-cells = <2>;
++ interrupts = <1e 4 1f 4>; /* cascade */
++ interrupt-parent = <&UIC0>;
++ };
++
++ UIC2: interrupt-controller2 {
++ compatible = "ibm,uic-460gt","ibm,uic";
++ interrupt-controller;
++ cell-index = <2>;
++ dcr-reg = <0e0 009>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ #interrupt-cells = <2>;
++ interrupts = <a 4 b 4>; /* cascade */
++ interrupt-parent = <&UIC0>;
++ };
++
++ UIC3: interrupt-controller3 {
++ compatible = "ibm,uic-460gt","ibm,uic";
++ interrupt-controller;
++ cell-index = <3>;
++ dcr-reg = <0f0 009>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ #interrupt-cells = <2>;
++ interrupts = <10 4 11 4>; /* cascade */
++ interrupt-parent = <&UIC0>;
++ };
++
++ SDR0: sdr {
++ compatible = "ibm,sdr-460gt";
++ dcr-reg = <00e 002>;
++ };
++
++ CPR0: cpr {
++ compatible = "ibm,cpr-460gt";
++ dcr-reg = <00c 002>;
++ };
++
++ plb {
++ compatible = "ibm,plb-460gt", "ibm,plb4";
++ #address-cells = <2>;
++ #size-cells = <1>;
++ ranges;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++
++ SDRAM0: sdram {
++ compatible = "ibm,sdram-460gt", "ibm,sdram-405gp";
++ dcr-reg = <010 2>;
++ };
++
++ MAL0: mcmal {
++ compatible = "ibm,mcmal-460gt", "ibm,mcmal2";
++ dcr-reg = <180 62>;
++ num-tx-chans = <4>;
++ num-rx-chans = <20>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ interrupt-parent = <&UIC2>;
++ interrupts = < /*TXEOB*/ 6 4
++ /*RXEOB*/ 7 4
++ /*SERR*/ 3 4
++ /*TXDE*/ 4 4
++ /*RXDE*/ 5 4>;
++ desc-base-addr-high = <8>;
++ };
++
++ POB0: opb {
++ compatible = "ibm,opb-460gt", "ibm,opb";
++ #address-cells = <1>;
++ #size-cells = <1>;
++ ranges = <b0000000 4 b0000000 50000000>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++
++ EBC0: ebc {
++ compatible = "ibm,ebc-460gt", "ibm,ebc";
++ dcr-reg = <012 2>;
++ #address-cells = <2>;
++ #size-cells = <1>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++ /* ranges property is supplied by U-Boot */
++ interrupts = <6 4>;
++ interrupt-parent = <&UIC1>;
++
++ nor_flash at 0,0 {
++ compatible = "amd,s29gl512n", "cfi-flash";
++ bank-width = <2>;
++ reg = <0 000000 4000000>;
++ #address-cells = <1>;
++ #size-cells = <1>;
++ partition at 0 {
++ label = "kernel";
++ reg = <0 1e0000>;
++ };
++ partition at 1e0000 {
++ label = "dtb";
++ reg = <1e0000 20000>;
++ };
++ partition at 200000 {
++ label = "ramdisk";
++ reg = <200000 1400000>;
++ };
++ partition at 1600000 {
++ label = "jffs2";
++ reg = <1600000 400000>;
++ };
++ partition at 1a00000 {
++ label = "user";
++ reg = <1a00000 2560000>;
++ };
++ partition at 3f60000 {
++ label = "env";
++ reg = <3f60000 40000>;
++ };
++ partition at 3fa0000 {
++ label = "u-boot";
++ reg = <3fa0000 60000>;
++ };
++ };
++ };
++
++ UART0: serial at ef600300 {
++ device_type = "serial";
++ compatible = "ns16550";
++ reg = <ef600300 8>;
++ virtual-reg = <ef600300>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++ current-speed = <0>; /* Filled in by U-Boot */
++ interrupt-parent = <&UIC1>;
++ interrupts = <1 4>;
++ };
++
++ UART1: serial at ef600400 {
++ device_type = "serial";
++ compatible = "ns16550";
++ reg = <ef600400 8>;
++ virtual-reg = <ef600400>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++ current-speed = <0>; /* Filled in by U-Boot */
++ interrupt-parent = <&UIC0>;
++ interrupts = <1 4>;
++ };
++
++ UART2: serial at ef600500 {
++ device_type = "serial";
++ compatible = "ns16550";
++ reg = <ef600500 8>;
++ virtual-reg = <ef600500>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++ current-speed = <0>; /* Filled in by U-Boot */
++ interrupt-parent = <&UIC1>;
++ interrupts = <1d 4>;
++ };
++
++ UART3: serial at ef600600 {
++ device_type = "serial";
++ compatible = "ns16550";
++ reg = <ef600600 8>;
++ virtual-reg = <ef600600>;
++ clock-frequency = <0>; /* Filled in by U-Boot */
++ current-speed = <0>; /* Filled in by U-Boot */
++ interrupt-parent = <&UIC1>;
++ interrupts = <1e 4>;
++ };
++
++ IIC0: i2c at ef600700 {
++ compatible = "ibm,iic-460gt", "ibm,iic";
++ reg = <ef600700 14>;
++ interrupt-parent = <&UIC0>;
++ interrupts = <2 4>;
++ };
++
++ IIC1: i2c at ef600800 {
++ compatible = "ibm,iic-460gt", "ibm,iic";
++ reg = <ef600800 14>;
++ interrupt-parent = <&UIC0>;
++ interrupts = <3 4>;
++ };
++
++ ZMII0: emac-zmii at ef600d00 {
++ compatible = "ibm,zmii-460gt", "ibm,zmii";
++ reg = <ef600d00 c>;
++ };
++
++ RGMII0: emac-rgmii at ef601500 {
++ compatible = "ibm,rgmii-460gt", "ibm,rgmii";
++ reg = <ef601500 8>;
++ has-mdio;
++ };
++
++ RGMII1: emac-rgmii at ef601600 {
++ compatible = "ibm,rgmii-460gt", "ibm,rgmii";
++ reg = <ef601600 8>;
++ has-mdio;
++ };
++
++ TAH0: emac-tah at ef601350 {
++ compatible = "ibm,tah-460gt", "ibm,tah";
++ reg = <ef601350 30>;
++ };
++
++ TAH1: emac-tah at ef601450 {
++ compatible = "ibm,tah-460gt", "ibm,tah";
++ reg = <ef601450 30>;
++ };
++
++ EMAC0: ethernet at ef600e00 {
++ device_type = "network";
++ compatible = "ibm,emac-460gt", "ibm,emac4";
++ interrupt-parent = <&EMAC0>;
++ interrupts = <0 1>;
++ #interrupt-cells = <1>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ interrupt-map = </*Status*/ 0 &UIC2 10 4
++ /*Wake*/ 1 &UIC2 14 4>;
++ reg = <ef600e00 70>;
++ local-mac-address = [000000000000]; /* Filled in by U-Boot */
++ mal-device = <&MAL0>;
++ mal-tx-channel = <0>;
++ mal-rx-channel = <0>;
++ cell-index = <0>;
++ max-frame-size = <2328>;
++ rx-fifo-size = <1000>;
++ tx-fifo-size = <800>;
++ phy-mode = "rgmii";
++ phy-map = <00000000>;
++ rgmii-device = <&RGMII0>;
++ rgmii-channel = <0>;
++ tah-device = <&TAH0>;
++ tah-channel = <0>;
++ has-inverted-stacr-oc;
++ has-new-stacr-staopc;
++ };
++
++ EMAC1: ethernet at ef600f00 {
++ device_type = "network";
++ compatible = "ibm,emac-460gt", "ibm,emac4";
++ interrupt-parent = <&EMAC1>;
++ interrupts = <0 1>;
++ #interrupt-cells = <1>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ interrupt-map = </*Status*/ 0 &UIC2 11 4
++ /*Wake*/ 1 &UIC2 15 4>;
++ reg = <ef600f00 70>;
++ local-mac-address = [000000000000]; /* Filled in by U-Boot */
++ mal-device = <&MAL0>;
++ mal-tx-channel = <1>;
++ mal-rx-channel = <8>;
++ cell-index = <1>;
++ max-frame-size = <2328>;
++ rx-fifo-size = <1000>;
++ tx-fifo-size = <800>;
++ phy-mode = "rgmii";
++ phy-map = <00000000>;
++ rgmii-device = <&RGMII0>;
++ rgmii-channel = <1>;
++ tah-device = <&TAH1>;
++ tah-channel = <1>;
++ has-inverted-stacr-oc;
++ has-new-stacr-staopc;
++ mdio-device = <&EMAC0>;
++ };
++
++ EMAC2: ethernet at ef601100 {
++ device_type = "network";
++ compatible = "ibm,emac-460gt", "ibm,emac4";
++ interrupt-parent = <&EMAC2>;
++ interrupts = <0 1>;
++ #interrupt-cells = <1>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ interrupt-map = </*Status*/ 0 &UIC2 12 4
++ /*Wake*/ 1 &UIC2 16 4>;
++ reg = <ef601100 70>;
++ local-mac-address = [000000000000]; /* Filled in by U-Boot */
++ mal-device = <&MAL0>;
++ mal-tx-channel = <2>;
++ mal-rx-channel = <10>;
++ cell-index = <2>;
++ max-frame-size = <2328>;
++ rx-fifo-size = <1000>;
++ tx-fifo-size = <800>;
++ phy-mode = "rgmii";
++ phy-map = <00000000>;
++ rgmii-device = <&RGMII1>;
++ rgmii-channel = <0>;
++ has-inverted-stacr-oc;
++ has-new-stacr-staopc;
++ mdio-device = <&EMAC0>;
++ };
++
++ EMAC3: ethernet at ef601200 {
++ device_type = "network";
++ compatible = "ibm,emac-460gt", "ibm,emac4";
++ interrupt-parent = <&EMAC3>;
++ interrupts = <0 1>;
++ #interrupt-cells = <1>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ interrupt-map = </*Status*/ 0 &UIC2 13 4
++ /*Wake*/ 1 &UIC2 17 4>;
++ reg = <ef601200 70>;
++ local-mac-address = [000000000000]; /* Filled in by U-Boot */
++ mal-device = <&MAL0>;
++ mal-tx-channel = <3>;
++ mal-rx-channel = <18>;
++ cell-index = <3>;
++ max-frame-size = <2328>;
++ rx-fifo-size = <1000>;
++ tx-fifo-size = <800>;
++ phy-mode = "rgmii";
++ phy-map = <00000000>;
++ rgmii-device = <&RGMII1>;
++ rgmii-channel = <1>;
++ has-inverted-stacr-oc;
++ has-new-stacr-staopc;
++ mdio-device = <&EMAC0>;
++ };
++ };
++
++ PCIX0: pci at c0ec00000 {
++ device_type = "pci";
++ #interrupt-cells = <1>;
++ #size-cells = <2>;
++ #address-cells = <3>;
++ compatible = "ibm,plb-pcix-460gt", "ibm,plb-pcix";
++ primary;
++ large-inbound-windows;
++ enable-msi-hole;
++ reg = <c 0ec00000 8 /* Config space access */
++ 0 0 0 /* no IACK cycles */
++ c 0ed00000 4 /* Special cycles */
++ c 0ec80000 100 /* Internal registers */
++ c 0ec80100 fc>; /* Internal messaging registers */
++
++ /* Outbound ranges, one memory and one IO,
++ * later cannot be changed
++ */
++ ranges = <02000000 0 80000000 0000000d 80000000 0 80000000
++ 01000000 0 00000000 0000000c 08000000 0 00010000>;
++
++ /* Inbound 2GB range starting at 0 */
++ dma-ranges = <42000000 0 0 0 0 0 80000000>;
++
++ /* This drives busses 0 to 0x3f */
++ bus-range = <0 3f>;
++
++ /* All PCI interrupts are routed to ext IRQ 2 -> UIC1-0 */
++ interrupt-map-mask = <0000 0 0 0>;
++ interrupt-map = < 0000 0 0 0 &UIC1 0 8 >;
++ };
++
++ PCIE0: pciex at d00000000 {
++ device_type = "pci";
++ #interrupt-cells = <1>;
++ #size-cells = <2>;
++ #address-cells = <3>;
++ compatible = "ibm,plb-pciex-460ex", "ibm,plb-pciex";
++ primary;
++ port = <0>; /* port number */
++ reg = <d 00000000 20000000 /* Config space access */
++ c 08010000 00001000>; /* Registers */
++ dcr-reg = <100 020>;
++ sdr-base = <300>;
++
++ /* Outbound ranges, one memory and one IO,
++ * later cannot be changed
++ */
++ ranges = <02000000 0 80000000 0000000e 00000000 0 80000000
++ 01000000 0 00000000 0000000f 80000000 0 00010000>;
++
++ /* Inbound 2GB range starting at 0 */
++ dma-ranges = <42000000 0 0 0 0 0 80000000>;
++
++ /* This drives busses 40 to 0x7f */
++ bus-range = <40 7f>;
++
++ /* Legacy interrupts (note the weird polarity, the bridge seems
++ * to invert PCIe legacy interrupts).
++ * We are de-swizzling here because the numbers are actually for
++ * port of the root complex virtual P2P bridge. But I want
++ * to avoid putting a node for it in the tree, so the numbers
++ * below are basically de-swizzled numbers.
++ * The real slot is on idsel 0, so the swizzling is 1:1
++ */
++ interrupt-map-mask = <0000 0 0 7>;
++ interrupt-map = <
++ 0000 0 0 1 &UIC3 c 4 /* swizzled int A */
++ 0000 0 0 2 &UIC3 d 4 /* swizzled int B */
++ 0000 0 0 3 &UIC3 e 4 /* swizzled int C */
++ 0000 0 0 4 &UIC3 f 4 /* swizzled int D */>;
++ };
++
++ PCIE1: pciex at d20000000 {
++ device_type = "pci";
++ #interrupt-cells = <1>;
++ #size-cells = <2>;
++ #address-cells = <3>;
++ compatible = "ibm,plb-pciex-460ex", "ibm,plb-pciex";
++ primary;
++ port = <1>; /* port number */
++ reg = <d 20000000 20000000 /* Config space access */
++ c 08011000 00001000>; /* Registers */
++ dcr-reg = <120 020>;
++ sdr-base = <340>;
++
++ /* Outbound ranges, one memory and one IO,
++ * later cannot be changed
++ */
++ ranges = <02000000 0 80000000 0000000e 80000000 0 80000000
++ 01000000 0 00000000 0000000f 80010000 0 00010000>;
++
++ /* Inbound 2GB range starting at 0 */
++ dma-ranges = <42000000 0 0 0 0 0 80000000>;
++
++ /* This drives busses 80 to 0xbf */
++ bus-range = <80 bf>;
++
++ /* Legacy interrupts (note the weird polarity, the bridge seems
++ * to invert PCIe legacy interrupts).
++ * We are de-swizzling here because the numbers are actually for
++ * port of the root complex virtual P2P bridge. But I want
++ * to avoid putting a node for it in the tree, so the numbers
++ * below are basically de-swizzled numbers.
++ * The real slot is on idsel 0, so the swizzling is 1:1
++ */
++ interrupt-map-mask = <0000 0 0 7>;
++ interrupt-map = <
++ 0000 0 0 1 &UIC3 10 4 /* swizzled int A */
++ 0000 0 0 2 &UIC3 11 4 /* swizzled int B */
++ 0000 0 0 3 &UIC3 12 4 /* swizzled int C */
++ 0000 0 0 4 &UIC3 13 4 /* swizzled int D */>;
++ };
++ };
++};
+diff --git a/arch/powerpc/boot/dts/haleakala.dts b/arch/powerpc/boot/dts/haleakala.dts
+index ae68fef..b5d95ac 100644
+--- a/arch/powerpc/boot/dts/haleakala.dts
++++ b/arch/powerpc/boot/dts/haleakala.dts
+@@ -12,7 +12,7 @@
+ #address-cells = <1>;
+ #size-cells = <1>;
+ model = "amcc,haleakala";
+- compatible = "amcc,kilauea";
++ compatible = "amcc,haleakala", "amcc,kilauea";
+ dcr-parent = <&/cpus/cpu at 0>;
+
+ aliases {
+@@ -218,7 +218,7 @@
+ mal-tx-channel = <0>;
+ mal-rx-channel = <0>;
+ cell-index = <0>;
+- max-frame-size = <5dc>;
++ max-frame-size = <2328>;
+ rx-fifo-size = <1000>;
+ tx-fifo-size = <800>;
+ phy-mode = "rgmii";
+diff --git a/arch/powerpc/boot/dts/katmai.dts b/arch/powerpc/boot/dts/katmai.dts
+index fc86e5a..cc2873a 100644
+--- a/arch/powerpc/boot/dts/katmai.dts
++++ b/arch/powerpc/boot/dts/katmai.dts
+@@ -212,7 +212,7 @@
+ mal-tx-channel = <0>;
+ mal-rx-channel = <0>;
+ cell-index = <0>;
+- max-frame-size = <5dc>;
++ max-frame-size = <2328>;
+ rx-fifo-size = <1000>;
+ tx-fifo-size = <800>;
+ phy-mode = "gmii";
+diff --git a/arch/powerpc/boot/dts/kilauea.dts b/arch/powerpc/boot/dts/kilauea.dts
+index 8baef61..48c9a6e 100644
+--- a/arch/powerpc/boot/dts/kilauea.dts
++++ b/arch/powerpc/boot/dts/kilauea.dts
+@@ -219,7 +219,7 @@
+ mal-tx-channel = <0>;
+ mal-rx-channel = <0>;
+ cell-index = <0>;
+- max-frame-size = <5dc>;
++ max-frame-size = <2328>;
+ rx-fifo-size = <1000>;
+ tx-fifo-size = <800>;
+ phy-mode = "rgmii";
+@@ -247,7 +247,7 @@
+ mal-tx-channel = <1>;
+ mal-rx-channel = <1>;
+ cell-index = <1>;
+- max-frame-size = <5dc>;
++ max-frame-size = <2328>;
+ rx-fifo-size = <1000>;
+ tx-fifo-size = <800>;
+ phy-mode = "rgmii";
+diff --git a/arch/powerpc/boot/dts/ksi8560.dts b/arch/powerpc/boot/dts/ksi8560.dts
+new file mode 100644
+index 0000000..f869ce3
+--- /dev/null
++++ b/arch/powerpc/boot/dts/ksi8560.dts
+@@ -0,0 +1,267 @@
++/*
++ * Device Tree Source for Emerson KSI8560
++ *
++ * Author: Alexandr Smirnov <asmirnov at ru.mvista.com>
++ *
++ * Based on mpc8560ads.dts
++ *
++ * 2008 (c) MontaVista, Software, Inc. This file is licensed under
++ * the terms of the GNU General Public License version 2. This program
++ * is licensed "as is" without any warranty of any kind, whether express
++ * or implied.
++ *
++ */
++
++/dts-v1/;
++
++/ {
++ model = "KSI8560";
++ compatible = "emerson,KSI8560";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ aliases {
++ ethernet0 = &enet0;
++ ethernet1 = &enet1;
++ ethernet2 = &enet2;
++ };
++
++ cpus {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ PowerPC,8560 at 0 {
++ device_type = "cpu";
++ reg = <0>;
++ d-cache-line-size = <32>;
++ i-cache-line-size = <32>;
++ d-cache-size = <0x8000>; /* L1, 32K */
++ i-cache-size = <0x8000>; /* L1, 32K */
++ timebase-frequency = <0>; /* From U-boot */
++ bus-frequency = <0>; /* From U-boot */
++ clock-frequency = <0>; /* From U-boot */
++ };
++ };
++
++ memory {
++ device_type = "memory";
++ reg = <0x00000000 0x10000000>; /* Fixed by bootwrapper */
++ };
++
++ soc at fdf00000 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ device_type = "soc";
++ ranges = <0x00000000 0xfdf00000 0x00100000>;
++ bus-frequency = <0>; /* Fixed by bootwrapper */
++
++ memory-controller at 2000 {
++ compatible = "fsl,8540-memory-controller";
++ reg = <0x2000 0x1000>;
++ interrupt-parent = <&MPIC>;
++ interrupts = <0x12 0x2>;
++ };
++
++ l2-cache-controller at 20000 {
++ compatible = "fsl,8540-l2-cache-controller";
++ reg = <0x20000 0x1000>;
++ cache-line-size = <0x20>; /* 32 bytes */
++ cache-size = <0x40000>; /* L2, 256K */
++ interrupt-parent = <&MPIC>;
++ interrupts = <0x10 0x2>;
++ };
++
++ i2c at 3000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ cell-index = <0>;
++ compatible = "fsl-i2c";
++ reg = <0x3000 0x100>;
++ interrupts = <0x2b 0x2>;
++ interrupt-parent = <&MPIC>;
++ dfsrr;
++ };
++
++ mdio at 24520 { /* For TSECs */
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "fsl,gianfar-mdio";
++ reg = <0x24520 0x20>;
++
++ PHY1: ethernet-phy at 1 {
++ interrupt-parent = <&MPIC>;
++ reg = <0x1>;
++ device_type = "ethernet-phy";
++ };
++
++ PHY2: ethernet-phy at 2 {
++ interrupt-parent = <&MPIC>;
++ reg = <0x2>;
++ device_type = "ethernet-phy";
++ };
++ };
++
++ enet0: ethernet at 24000 {
++ device_type = "network";
++ model = "TSEC";
++ compatible = "gianfar";
++ reg = <0x24000 0x1000>;
++ /* Mac address filled in by bootwrapper */
++ local-mac-address = [ 00 00 00 00 00 00 ];
++ interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
++ interrupt-parent = <&MPIC>;
++ phy-handle = <&PHY1>;
++ };
++
++ enet1: ethernet at 25000 {
++ device_type = "network";
++ model = "TSEC";
++ compatible = "gianfar";
++ reg = <0x25000 0x1000>;
++ /* Mac address filled in by bootwrapper */
++ local-mac-address = [ 00 00 00 00 00 00 ];
++ interrupts = <0x23 0x2 0x24 0x2 0x28 0x2>;
++ interrupt-parent = <&MPIC>;
++ phy-handle = <&PHY2>;
++ };
++
++ MPIC: pic at 40000 {
++ #address-cells = <0>;
++ #interrupt-cells = <2>;
++ interrupt-controller;
++ reg = <0x40000 0x40000>;
++ device_type = "open-pic";
++ };
++
++ cpm at 919c0 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "fsl,mpc8560-cpm", "fsl,cpm2";
++ reg = <0x919c0 0x30>;
++ ranges;
++
++ muram at 80000 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ ranges = <0x0 0x80000 0x10000>;
++
++ data at 0 {
++ compatible = "fsl,cpm-muram-data";
++ reg = <0x0 0x4000 0x9000 0x2000>;
++ };
++ };
++
++ brg at 919f0 {
++ compatible = "fsl,mpc8560-brg",
++ "fsl,cpm2-brg",
++ "fsl,cpm-brg";
++ reg = <0x919f0 0x10 0x915f0 0x10>;
++ clock-frequency = <165000000>; /* 166MHz */
++ };
++
++ CPMPIC: pic at 90c00 {
++ #address-cells = <0>;
++ #interrupt-cells = <2>;
++ interrupt-controller;
++ interrupts = <0x2e 0x2>;
++ interrupt-parent = <&MPIC>;
++ reg = <0x90c00 0x80>;
++ compatible = "fsl,mpc8560-cpm-pic", "fsl,cpm2-pic";
++ };
++
++ serial at 91a00 {
++ device_type = "serial";
++ compatible = "fsl,mpc8560-scc-uart",
++ "fsl,cpm2-scc-uart";
++ reg = <0x91a00 0x20 0x88000 0x100>;
++ fsl,cpm-brg = <1>;
++ fsl,cpm-command = <0x800000>;
++ current-speed = <0x1c200>;
++ interrupts = <0x28 0x8>;
++ interrupt-parent = <&CPMPIC>;
++ };
++
++ serial at 91a20 {
++ device_type = "serial";
++ compatible = "fsl,mpc8560-scc-uart",
++ "fsl,cpm2-scc-uart";
++ reg = <0x91a20 0x20 0x88100 0x100>;
++ fsl,cpm-brg = <2>;
++ fsl,cpm-command = <0x4a00000>;
++ current-speed = <0x1c200>;
++ interrupts = <0x29 0x8>;
++ interrupt-parent = <&CPMPIC>;
++ };
++
++ mdio at 90d00 { /* For FCCs */
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "fsl,cpm2-mdio-bitbang";
++ reg = <0x90d00 0x14>;
++ fsl,mdio-pin = <24>;
++ fsl,mdc-pin = <25>;
++
++ PHY0: ethernet-phy at 0 {
++ interrupt-parent = <&MPIC>;
++ reg = <0x0>;
++ device_type = "ethernet-phy";
++ };
++ };
++
++ enet2: ethernet at 91300 {
++ device_type = "network";
++ compatible = "fsl,mpc8560-fcc-enet",
++ "fsl,cpm2-fcc-enet";
++ reg = <0x91300 0x20 0x88400 0x100 0x91390 0x1>;
++ /* Mac address filled in by bootwrapper */
++ local-mac-address = [ 00 00 00 00 00 00 ];
++ fsl,cpm-command = <0x12000300>;
++ interrupts = <0x20 0x8>;
++ interrupt-parent = <&CPMPIC>;
++ phy-handle = <&PHY0>;
++ };
++ };
++ };
++
++ localbus at fdf05000 {
++ #address-cells = <2>;
++ #size-cells = <1>;
++ compatible = "fsl,mpc8560-localbus";
++ reg = <0xfdf05000 0x68>;
++
++ ranges = <0x0 0x0 0xe0000000 0x00800000
++ 0x4 0x0 0xe8080000 0x00080000>;
++
++ flash at 0,0 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "jedec-flash";
++ reg = <0x0 0x0 0x800000>;
++ bank-width = <0x2>;
++
++ partition at 0 {
++ label = "Primary Kernel";
++ reg = <0x0 0x180000>;
++ };
++ partition at 180000 {
++ label = "Primary Filesystem";
++ reg = <0x180000 0x580000>;
++ };
++ partition at 700000 {
++ label = "Monitor";
++ reg = <0x300000 0x100000>;
++ read-only;
++ };
++ };
++
++ cpld at 4,0 {
++ compatible = "emerson,KSI8560-cpld";
++ reg = <0x4 0x0 0x80000>;
++ };
++ };
++
++
++ chosen {
++ linux,stdout-path = "/soc/cpm/serial at 91a00";
++ };
++};
+diff --git a/arch/powerpc/boot/dts/kuroboxHD.dts b/arch/powerpc/boot/dts/kuroboxHD.dts
+index 4469588..2e5a1a1 100644
+--- a/arch/powerpc/boot/dts/kuroboxHD.dts
++++ b/arch/powerpc/boot/dts/kuroboxHD.dts
+@@ -7,6 +7,7 @@
+ * Based on sandpoint.dts
+ *
+ * 2006 (c) G. Liakhovetski <g.liakhovetski at gmx.de>
++ * Copyright 2008 Freescale Semiconductor, Inc.
+ *
+ * This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+@@ -17,6 +18,8 @@ XXXX add flash parts, rtc, ??
+
+ */
+
++/dts-v1/;
++
+ / {
+ model = "KuroboxHD";
+ compatible = "linkstation";
+@@ -35,19 +38,19 @@ XXXX add flash parts, rtc, ??
+
+ PowerPC,603e { /* Really 8241 */
+ device_type = "cpu";
+- reg = <0>;
+- clock-frequency = <bebc200>; /* Fixed by bootloader */
+- timebase-frequency = <1743000>; /* Fixed by bootloader */
++ reg = <0x0>;
++ clock-frequency = <200000000>; /* Fixed by bootloader */
++ timebase-frequency = <24391680>; /* Fixed by bootloader */
+ bus-frequency = <0>; /* Fixed by bootloader */
+ /* Following required by dtc but not used */
+- i-cache-size = <4000>;
+- d-cache-size = <4000>;
++ i-cache-size = <0x4000>;
++ d-cache-size = <0x4000>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+- reg = <00000000 04000000>;
++ reg = <0x0 0x4000000>;
+ };
+
+ soc10x { /* AFAICT need to make soc for 8245's uarts to be defined */
+@@ -56,26 +59,26 @@ XXXX add flash parts, rtc, ??
+ device_type = "soc";
+ compatible = "mpc10x";
+ store-gathering = <0>; /* 0 == off, !0 == on */
+- reg = <80000000 00100000>;
+- ranges = <80000000 80000000 70000000 /* pci mem space */
+- fc000000 fc000000 00100000 /* EUMB */
+- fe000000 fe000000 00c00000 /* pci i/o space */
+- fec00000 fec00000 00300000 /* pci cfg regs */
+- fef00000 fef00000 00100000>; /* pci iack */
++ reg = <0x80000000 0x100000>;
++ ranges = <0x80000000 0x80000000 0x70000000 /* pci mem space */
++ 0xfc000000 0xfc000000 0x100000 /* EUMB */
++ 0xfe000000 0xfe000000 0xc00000 /* pci i/o space */
++ 0xfec00000 0xfec00000 0x300000 /* pci cfg regs */
++ 0xfef00000 0xfef00000 0x100000>; /* pci iack */
+
+ i2c at 80003000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+- reg = <80003000 1000>;
++ reg = <0x80003000 0x1000>;
+ interrupts = <5 2>;
+ interrupt-parent = <&mpic>;
+
+ rtc at 32 {
+ device_type = "rtc";
+ compatible = "ricoh,rs5c372a";
+- reg = <32>;
++ reg = <0x32>;
+ };
+ };
+
+@@ -83,9 +86,9 @@ XXXX add flash parts, rtc, ??
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <80004500 8>;
+- clock-frequency = <5d08d88>;
+- current-speed = <2580>;
++ reg = <0x80004500 0x8>;
++ clock-frequency = <97553800>;
++ current-speed = <9600>;
+ interrupts = <9 0>;
+ interrupt-parent = <&mpic>;
+ };
+@@ -94,10 +97,10 @@ XXXX add flash parts, rtc, ??
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <80004600 8>;
+- clock-frequency = <5d08d88>;
+- current-speed = <e100>;
+- interrupts = <a 0>;
++ reg = <0x80004600 0x8>;
++ clock-frequency = <97553800>;
++ current-speed = <57600>;
++ interrupts = <10 0>;
+ interrupt-parent = <&mpic>;
+ };
+
+@@ -107,7 +110,7 @@ XXXX add flash parts, rtc, ??
+ device_type = "open-pic";
+ compatible = "chrp,open-pic";
+ interrupt-controller;
+- reg = <80040000 40000>;
++ reg = <0x80040000 0x40000>;
+ };
+
+ pci0: pci at fec00000 {
+@@ -116,29 +119,29 @@ XXXX add flash parts, rtc, ??
+ #interrupt-cells = <1>;
+ device_type = "pci";
+ compatible = "mpc10x-pci";
+- reg = <fec00000 400000>;
+- ranges = <01000000 0 0 fe000000 0 00c00000
+- 02000000 0 80000000 80000000 0 70000000>;
+- bus-range = <0 ff>;
+- clock-frequency = <7f28155>;
++ reg = <0xfec00000 0x400000>;
++ ranges = <0x1000000 0x0 0x0 0xfe000000 0x0 0xc00000
++ 0x2000000 0x0 0x80000000 0x80000000 0x0 0x70000000>;
++ bus-range = <0 255>;
++ clock-frequency = <133333333>;
+ interrupt-parent = <&mpic>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 11 - IRQ0 ETH */
+- 5800 0 0 1 &mpic 0 1
+- 5800 0 0 2 &mpic 1 1
+- 5800 0 0 3 &mpic 2 1
+- 5800 0 0 4 &mpic 3 1
++ 0x5800 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x5800 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x5800 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x5800 0x0 0x0 0x4 &mpic 0x3 0x1
+ /* IDSEL 12 - IRQ1 IDE0 */
+- 6000 0 0 1 &mpic 1 1
+- 6000 0 0 2 &mpic 2 1
+- 6000 0 0 3 &mpic 3 1
+- 6000 0 0 4 &mpic 0 1
++ 0x6000 0x0 0x0 0x1 &mpic 0x1 0x1
++ 0x6000 0x0 0x0 0x2 &mpic 0x2 0x1
++ 0x6000 0x0 0x0 0x3 &mpic 0x3 0x1
++ 0x6000 0x0 0x0 0x4 &mpic 0x0 0x1
+ /* IDSEL 14 - IRQ3 USB2.0 */
+- 7000 0 0 1 &mpic 3 1
+- 7000 0 0 2 &mpic 3 1
+- 7000 0 0 3 &mpic 3 1
+- 7000 0 0 4 &mpic 3 1
++ 0x7000 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x7000 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x7000 0x0 0x0 0x3 &mpic 0x3 0x1
++ 0x7000 0x0 0x0 0x4 &mpic 0x3 0x1
+ >;
+ };
+ };
+diff --git a/arch/powerpc/boot/dts/kuroboxHG.dts b/arch/powerpc/boot/dts/kuroboxHG.dts
+index 8443c85..e4916e6 100644
+--- a/arch/powerpc/boot/dts/kuroboxHG.dts
++++ b/arch/powerpc/boot/dts/kuroboxHG.dts
+@@ -7,6 +7,7 @@
+ * Based on sandpoint.dts
+ *
+ * 2006 (c) G. Liakhovetski <g.liakhovetski at gmx.de>
++ * Copyright 2008 Freescale Semiconductor, Inc.
+ *
+ * This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+@@ -17,6 +18,8 @@ XXXX add flash parts, rtc, ??
+
+ */
+
++/dts-v1/;
++
+ / {
+ model = "KuroboxHG";
+ compatible = "linkstation";
+@@ -35,19 +38,19 @@ XXXX add flash parts, rtc, ??
+
+ PowerPC,603e { /* Really 8241 */
+ device_type = "cpu";
+- reg = <0>;
+- clock-frequency = <fdad680>; /* Fixed by bootloader */
+- timebase-frequency = <1F04000>; /* Fixed by bootloader */
++ reg = <0x0>;
++ clock-frequency = <266000000>; /* Fixed by bootloader */
++ timebase-frequency = <32522240>; /* Fixed by bootloader */
+ bus-frequency = <0>; /* Fixed by bootloader */
+ /* Following required by dtc but not used */
+- i-cache-size = <4000>;
+- d-cache-size = <4000>;
++ i-cache-size = <0x4000>;
++ d-cache-size = <0x4000>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+- reg = <00000000 08000000>;
++ reg = <0x0 0x8000000>;
+ };
+
+ soc10x { /* AFAICT need to make soc for 8245's uarts to be defined */
+@@ -56,26 +59,26 @@ XXXX add flash parts, rtc, ??
+ device_type = "soc";
+ compatible = "mpc10x";
+ store-gathering = <0>; /* 0 == off, !0 == on */
+- reg = <80000000 00100000>;
+- ranges = <80000000 80000000 70000000 /* pci mem space */
+- fc000000 fc000000 00100000 /* EUMB */
+- fe000000 fe000000 00c00000 /* pci i/o space */
+- fec00000 fec00000 00300000 /* pci cfg regs */
+- fef00000 fef00000 00100000>; /* pci iack */
++ reg = <0x80000000 0x100000>;
++ ranges = <0x80000000 0x80000000 0x70000000 /* pci mem space */
++ 0xfc000000 0xfc000000 0x100000 /* EUMB */
++ 0xfe000000 0xfe000000 0xc00000 /* pci i/o space */
++ 0xfec00000 0xfec00000 0x300000 /* pci cfg regs */
++ 0xfef00000 0xfef00000 0x100000>; /* pci iack */
+
+ i2c at 80003000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+- reg = <80003000 1000>;
++ reg = <0x80003000 0x1000>;
+ interrupts = <5 2>;
+ interrupt-parent = <&mpic>;
+
+ rtc at 32 {
+ device_type = "rtc";
+ compatible = "ricoh,rs5c372a";
+- reg = <32>;
++ reg = <0x32>;
+ };
+ };
+
+@@ -83,9 +86,9 @@ XXXX add flash parts, rtc, ??
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <80004500 8>;
+- clock-frequency = <7c044a8>;
+- current-speed = <2580>;
++ reg = <0x80004500 0x8>;
++ clock-frequency = <130041000>;
++ current-speed = <9600>;
+ interrupts = <9 0>;
+ interrupt-parent = <&mpic>;
+ };
+@@ -94,10 +97,10 @@ XXXX add flash parts, rtc, ??
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <80004600 8>;
+- clock-frequency = <7c044a8>;
+- current-speed = <e100>;
+- interrupts = <a 0>;
++ reg = <0x80004600 0x8>;
++ clock-frequency = <130041000>;
++ current-speed = <57600>;
++ interrupts = <10 0>;
+ interrupt-parent = <&mpic>;
+ };
+
+@@ -107,7 +110,7 @@ XXXX add flash parts, rtc, ??
+ device_type = "open-pic";
+ compatible = "chrp,open-pic";
+ interrupt-controller;
+- reg = <80040000 40000>;
++ reg = <0x80040000 0x40000>;
+ };
+
+ pci0: pci at fec00000 {
+@@ -116,29 +119,29 @@ XXXX add flash parts, rtc, ??
+ #interrupt-cells = <1>;
+ device_type = "pci";
+ compatible = "mpc10x-pci";
+- reg = <fec00000 400000>;
+- ranges = <01000000 0 0 fe000000 0 00c00000
+- 02000000 0 80000000 80000000 0 70000000>;
+- bus-range = <0 ff>;
+- clock-frequency = <7f28155>;
++ reg = <0xfec00000 0x400000>;
++ ranges = <0x1000000 0x0 0x0 0xfe000000 0x0 0xc00000
++ 0x2000000 0x0 0x80000000 0x80000000 0x0 0x70000000>;
++ bus-range = <0 255>;
++ clock-frequency = <133333333>;
+ interrupt-parent = <&mpic>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 11 - IRQ0 ETH */
+- 5800 0 0 1 &mpic 0 1
+- 5800 0 0 2 &mpic 1 1
+- 5800 0 0 3 &mpic 2 1
+- 5800 0 0 4 &mpic 3 1
++ 0x5800 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x5800 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x5800 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x5800 0x0 0x0 0x4 &mpic 0x3 0x1
+ /* IDSEL 12 - IRQ1 IDE0 */
+- 6000 0 0 1 &mpic 1 1
+- 6000 0 0 2 &mpic 2 1
+- 6000 0 0 3 &mpic 3 1
+- 6000 0 0 4 &mpic 0 1
++ 0x6000 0x0 0x0 0x1 &mpic 0x1 0x1
++ 0x6000 0x0 0x0 0x2 &mpic 0x2 0x1
++ 0x6000 0x0 0x0 0x3 &mpic 0x3 0x1
++ 0x6000 0x0 0x0 0x4 &mpic 0x0 0x1
+ /* IDSEL 14 - IRQ3 USB2.0 */
+- 7000 0 0 1 &mpic 3 1
+- 7000 0 0 2 &mpic 3 1
+- 7000 0 0 3 &mpic 3 1
+- 7000 0 0 4 &mpic 3 1
++ 0x7000 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x7000 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x7000 0x0 0x0 0x3 &mpic 0x3 0x1
++ 0x7000 0x0 0x0 0x4 &mpic 0x3 0x1
+ >;
+ };
+ };
+diff --git a/arch/powerpc/boot/dts/makalu.dts b/arch/powerpc/boot/dts/makalu.dts
+index 710c011..84cc5e7 100644
+--- a/arch/powerpc/boot/dts/makalu.dts
++++ b/arch/powerpc/boot/dts/makalu.dts
+@@ -219,7 +219,7 @@
+ mal-tx-channel = <0>;
+ mal-rx-channel = <0>;
+ cell-index = <0>;
+- max-frame-size = <5dc>;
++ max-frame-size = <2328>;
+ rx-fifo-size = <1000>;
+ tx-fifo-size = <800>;
+ phy-mode = "rgmii";
+@@ -247,7 +247,7 @@
+ mal-tx-channel = <1>;
+ mal-rx-channel = <1>;
+ cell-index = <1>;
+- max-frame-size = <5dc>;
++ max-frame-size = <2328>;
+ rx-fifo-size = <1000>;
+ tx-fifo-size = <800>;
+ phy-mode = "rgmii";
+diff --git a/arch/powerpc/boot/dts/mpc7448hpc2.dts b/arch/powerpc/boot/dts/mpc7448hpc2.dts
+index 8fb5423..4936349 100644
+--- a/arch/powerpc/boot/dts/mpc7448hpc2.dts
++++ b/arch/powerpc/boot/dts/mpc7448hpc2.dts
+@@ -1,7 +1,7 @@
+ /*
+ * MPC7448HPC2 (Taiga) board Device Tree Source
+ *
+- * Copyright 2006 Freescale Semiconductor Inc.
++ * Copyright 2006, 2008 Freescale Semiconductor Inc.
+ * 2006 Roy Zang <Roy Zang at freescale.com>.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+@@ -10,6 +10,7 @@
+ * option) any later version.
+ */
+
++/dts-v1/;
+
+ / {
+ model = "mpc7448hpc2";
+@@ -23,11 +24,11 @@
+
+ PowerPC,7448 at 0 {
+ device_type = "cpu";
+- reg = <0>;
+- d-cache-line-size = <20>; // 32 bytes
+- i-cache-line-size = <20>; // 32 bytes
+- d-cache-size = <8000>; // L1, 32K bytes
+- i-cache-size = <8000>; // L1, 32K bytes
++ reg = <0x0>;
++ d-cache-line-size = <32>; // 32 bytes
++ i-cache-line-size = <32>; // 32 bytes
++ d-cache-size = <0x8000>; // L1, 32K bytes
++ i-cache-size = <0x8000>; // L1, 32K bytes
+ timebase-frequency = <0>; // 33 MHz, from uboot
+ clock-frequency = <0>; // From U-Boot
+ bus-frequency = <0>; // From U-Boot
+@@ -36,7 +37,7 @@
+
+ memory {
+ device_type = "memory";
+- reg = <00000000 20000000 // DDR2 512M at 0
++ reg = <0x0 0x20000000 // DDR2 512M at 0
+ >;
+ };
+
+@@ -44,14 +45,14 @@
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "tsi-bridge";
+- ranges = <00000000 c0000000 00010000>;
+- reg = <c0000000 00010000>;
++ ranges = <0x0 0xc0000000 0x10000>;
++ reg = <0xc0000000 0x10000>;
+ bus-frequency = <0>;
+
+ i2c at 7000 {
+ interrupt-parent = <&mpic>;
+- interrupts = <E 0>;
+- reg = <7000 400>;
++ interrupts = <14 0>;
++ reg = <0x7000 0x400>;
+ device_type = "i2c";
+ compatible = "tsi108-i2c";
+ };
+@@ -59,20 +60,20 @@
+ MDIO: mdio at 6000 {
+ device_type = "mdio";
+ compatible = "tsi108-mdio";
+- reg = <6000 50>;
++ reg = <0x6000 0x50>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy8: ethernet-phy at 8 {
+ interrupt-parent = <&mpic>;
+ interrupts = <2 1>;
+- reg = <8>;
++ reg = <0x8>;
+ };
+
+ phy9: ethernet-phy at 9 {
+ interrupt-parent = <&mpic>;
+ interrupts = <2 1>;
+- reg = <9>;
++ reg = <0x9>;
+ };
+
+ };
+@@ -82,9 +83,9 @@
+ #size-cells = <0>;
+ device_type = "network";
+ compatible = "tsi108-ethernet";
+- reg = <6000 200>;
++ reg = <0x6000 0x200>;
+ address = [ 00 06 D2 00 00 01 ];
+- interrupts = <10 2>;
++ interrupts = <16 2>;
+ interrupt-parent = <&mpic>;
+ mdio-handle = <&MDIO>;
+ phy-handle = <&phy8>;
+@@ -96,9 +97,9 @@
+ #size-cells = <0>;
+ device_type = "network";
+ compatible = "tsi108-ethernet";
+- reg = <6400 200>;
++ reg = <0x6400 0x200>;
+ address = [ 00 06 D2 00 00 02 ];
+- interrupts = <11 2>;
++ interrupts = <17 2>;
+ interrupt-parent = <&mpic>;
+ mdio-handle = <&MDIO>;
+ phy-handle = <&phy9>;
+@@ -107,18 +108,18 @@
+ serial at 7808 {
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <7808 200>;
+- clock-frequency = <3f6b5a00>;
+- interrupts = <c 0>;
++ reg = <0x7808 0x200>;
++ clock-frequency = <1064000000>;
++ interrupts = <12 0>;
+ interrupt-parent = <&mpic>;
+ };
+
+ serial at 7c08 {
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <7c08 200>;
+- clock-frequency = <3f6b5a00>;
+- interrupts = <d 0>;
++ reg = <0x7c08 0x200>;
++ clock-frequency = <1064000000>;
++ interrupts = <13 0>;
+ interrupt-parent = <&mpic>;
+ };
+
+@@ -127,7 +128,7 @@
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+- reg = <7400 400>;
++ reg = <0x7400 0x400>;
+ compatible = "chrp,open-pic";
+ device_type = "open-pic";
+ big-endian;
+@@ -138,39 +139,39 @@
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <1000 1000>;
++ reg = <0x1000 0x1000>;
+ bus-range = <0 0>;
+- ranges = <02000000 0 e0000000 e0000000 0 1A000000
+- 01000000 0 00000000 fa000000 0 00010000>;
+- clock-frequency = <7f28154>;
++ ranges = <0x2000000 0x0 0xe0000000 0xe0000000 0x0 0x1a000000
++ 0x1000000 0x0 0x0 0xfa000000 0x0 0x10000>;
++ clock-frequency = <133333332>;
+ interrupt-parent = <&mpic>;
+- interrupts = <17 2>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupts = <23 2>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+
+ /* IDSEL 0x11 */
+- 0800 0 0 1 &RT0 24 0
+- 0800 0 0 2 &RT0 25 0
+- 0800 0 0 3 &RT0 26 0
+- 0800 0 0 4 &RT0 27 0
++ 0x800 0x0 0x0 0x1 &RT0 0x24 0x0
++ 0x800 0x0 0x0 0x2 &RT0 0x25 0x0
++ 0x800 0x0 0x0 0x3 &RT0 0x26 0x0
++ 0x800 0x0 0x0 0x4 &RT0 0x27 0x0
+
+ /* IDSEL 0x12 */
+- 1000 0 0 1 &RT0 25 0
+- 1000 0 0 2 &RT0 26 0
+- 1000 0 0 3 &RT0 27 0
+- 1000 0 0 4 &RT0 24 0
++ 0x1000 0x0 0x0 0x1 &RT0 0x25 0x0
++ 0x1000 0x0 0x0 0x2 &RT0 0x26 0x0
++ 0x1000 0x0 0x0 0x3 &RT0 0x27 0x0
++ 0x1000 0x0 0x0 0x4 &RT0 0x24 0x0
+
+ /* IDSEL 0x13 */
+- 1800 0 0 1 &RT0 26 0
+- 1800 0 0 2 &RT0 27 0
+- 1800 0 0 3 &RT0 24 0
+- 1800 0 0 4 &RT0 25 0
++ 0x1800 0x0 0x0 0x1 &RT0 0x26 0x0
++ 0x1800 0x0 0x0 0x2 &RT0 0x27 0x0
++ 0x1800 0x0 0x0 0x3 &RT0 0x24 0x0
++ 0x1800 0x0 0x0 0x4 &RT0 0x25 0x0
+
+ /* IDSEL 0x14 */
+- 2000 0 0 1 &RT0 27 0
+- 2000 0 0 2 &RT0 24 0
+- 2000 0 0 3 &RT0 25 0
+- 2000 0 0 4 &RT0 26 0
++ 0x2000 0x0 0x0 0x1 &RT0 0x27 0x0
++ 0x2000 0x0 0x0 0x2 &RT0 0x24 0x0
++ 0x2000 0x0 0x0 0x3 &RT0 0x25 0x0
++ 0x2000 0x0 0x0 0x4 &RT0 0x26 0x0
+ >;
+
+ RT0: router at 1180 {
+@@ -180,7 +181,7 @@
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ big-endian;
+- interrupts = <17 2>;
++ interrupts = <23 2>;
+ interrupt-parent = <&mpic>;
+ };
+ };
+diff --git a/arch/powerpc/boot/dts/mpc8272ads.dts b/arch/powerpc/boot/dts/mpc8272ads.dts
+index 7285ca1..46e2da3 100644
+--- a/arch/powerpc/boot/dts/mpc8272ads.dts
++++ b/arch/powerpc/boot/dts/mpc8272ads.dts
+@@ -1,7 +1,7 @@
+ /*
+ * MPC8272 ADS Device Tree Source
+ *
+- * Copyright 2005 Freescale Semiconductor Inc.
++ * Copyright 2005,2008 Freescale Semiconductor Inc.
+ *
+ * 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
+@@ -9,6 +9,8 @@
+ * option) any later version.
+ */
+
++/dts-v1/;
++
+ / {
+ model = "MPC8272ADS";
+ compatible = "fsl,mpc8272ads";
+@@ -21,11 +23,11 @@
+
+ PowerPC,8272 at 0 {
+ device_type = "cpu";
+- reg = <0>;
+- d-cache-line-size = <d#32>;
+- i-cache-line-size = <d#32>;
+- d-cache-size = <d#16384>;
+- i-cache-size = <d#16384>;
++ reg = <0x0>;
++ d-cache-line-size = <32>;
++ i-cache-line-size = <32>;
++ d-cache-size = <16384>;
++ i-cache-size = <16384>;
+ timebase-frequency = <0>;
+ bus-frequency = <0>;
+ clock-frequency = <0>;
+@@ -34,7 +36,7 @@
+
+ memory {
+ device_type = "memory";
+- reg = <0 0>;
++ reg = <0x0 0x0>;
+ };
+
+ localbus at f0010100 {
+@@ -42,21 +44,21 @@
+ "fsl,pq2-localbus";
+ #address-cells = <2>;
+ #size-cells = <1>;
+- reg = <f0010100 40>;
++ reg = <0xf0010100 0x40>;
+
+- ranges = <0 0 fe000000 02000000
+- 1 0 f4500000 00008000
+- 3 0 f8200000 00008000>;
++ ranges = <0x0 0x0 0xfe000000 0x2000000
++ 0x1 0x0 0xf4500000 0x8000
++ 0x3 0x0 0xf8200000 0x8000>;
+
+ flash at 0,0 {
+ compatible = "jedec-flash";
+- reg = <0 0 2000000>;
++ reg = <0x0 0x0 0x2000000>;
+ bank-width = <4>;
+ device-width = <1>;
+ };
+
+ board-control at 1,0 {
+- reg = <1 0 20>;
++ reg = <0x1 0x0 0x20>;
+ compatible = "fsl,mpc8272ads-bcsr";
+ };
+
+@@ -65,46 +67,46 @@
+ "fsl,pq2ads-pci-pic";
+ #interrupt-cells = <1>;
+ interrupt-controller;
+- reg = <3 0 8>;
++ reg = <0x3 0x0 0x8>;
+ interrupt-parent = <&PIC>;
+- interrupts = <14 8>;
++ interrupts = <20 8>;
+ };
+ };
+
+
+ pci at f0010800 {
+ device_type = "pci";
+- reg = <f0010800 10c f00101ac 8 f00101c4 8>;
++ reg = <0xf0010800 0x10c 0xf00101ac 0x8 0xf00101c4 0x8>;
+ compatible = "fsl,mpc8272-pci", "fsl,pq2-pci";
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- clock-frequency = <d#66666666>;
+- interrupt-map-mask = <f800 0 0 7>;
++ clock-frequency = <66666666>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x16 */
+- b000 0 0 1 &PCI_PIC 0
+- b000 0 0 2 &PCI_PIC 1
+- b000 0 0 3 &PCI_PIC 2
+- b000 0 0 4 &PCI_PIC 3
++ 0xb000 0x0 0x0 0x1 &PCI_PIC 0
++ 0xb000 0x0 0x0 0x2 &PCI_PIC 1
++ 0xb000 0x0 0x0 0x3 &PCI_PIC 2
++ 0xb000 0x0 0x0 0x4 &PCI_PIC 3
+
+ /* IDSEL 0x17 */
+- b800 0 0 1 &PCI_PIC 4
+- b800 0 0 2 &PCI_PIC 5
+- b800 0 0 3 &PCI_PIC 6
+- b800 0 0 4 &PCI_PIC 7
++ 0xb800 0x0 0x0 0x1 &PCI_PIC 4
++ 0xb800 0x0 0x0 0x2 &PCI_PIC 5
++ 0xb800 0x0 0x0 0x3 &PCI_PIC 6
++ 0xb800 0x0 0x0 0x4 &PCI_PIC 7
+
+ /* IDSEL 0x18 */
+- c000 0 0 1 &PCI_PIC 8
+- c000 0 0 2 &PCI_PIC 9
+- c000 0 0 3 &PCI_PIC a
+- c000 0 0 4 &PCI_PIC b>;
++ 0xc000 0x0 0x0 0x1 &PCI_PIC 8
++ 0xc000 0x0 0x0 0x2 &PCI_PIC 9
++ 0xc000 0x0 0x0 0x3 &PCI_PIC 10
++ 0xc000 0x0 0x0 0x4 &PCI_PIC 11>;
+
+ interrupt-parent = <&PIC>;
+- interrupts = <12 8>;
+- ranges = <42000000 0 80000000 80000000 0 20000000
+- 02000000 0 a0000000 a0000000 0 20000000
+- 01000000 0 00000000 f6000000 0 02000000>;
++ interrupts = <18 8>;
++ ranges = <0x42000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++ 0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xf6000000 0x0 0x2000000>;
+ };
+
+ soc at f0000000 {
+@@ -112,26 +114,26 @@
+ #size-cells = <1>;
+ device_type = "soc";
+ compatible = "fsl,mpc8272", "fsl,pq2-soc";
+- ranges = <00000000 f0000000 00053000>;
++ ranges = <0x0 0xf0000000 0x53000>;
+
+ // Temporary -- will go away once kernel uses ranges for get_immrbase().
+- reg = <f0000000 00053000>;
++ reg = <0xf0000000 0x53000>;
+
+ cpm at 119c0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8272-cpm", "fsl,cpm2";
+- reg = <119c0 30>;
++ reg = <0x119c0 0x30>;
+ ranges;
+
+ muram at 0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+- ranges = <0 0 10000>;
++ ranges = <0x0 0x0 0x10000>;
+
+ data at 0 {
+ compatible = "fsl,cpm-muram-data";
+- reg = <0 2000 9800 800>;
++ reg = <0x0 0x2000 0x9800 0x800>;
+ };
+ };
+
+@@ -139,29 +141,29 @@
+ compatible = "fsl,mpc8272-brg",
+ "fsl,cpm2-brg",
+ "fsl,cpm-brg";
+- reg = <119f0 10 115f0 10>;
++ reg = <0x119f0 0x10 0x115f0 0x10>;
+ };
+
+ serial at 11a00 {
+ device_type = "serial";
+ compatible = "fsl,mpc8272-scc-uart",
+ "fsl,cpm2-scc-uart";
+- reg = <11a00 20 8000 100>;
+- interrupts = <28 8>;
++ reg = <0x11a00 0x20 0x8000 0x100>;
++ interrupts = <40 8>;
+ interrupt-parent = <&PIC>;
+ fsl,cpm-brg = <1>;
+- fsl,cpm-command = <00800000>;
++ fsl,cpm-command = <0x800000>;
+ };
+
+ serial at 11a60 {
+ device_type = "serial";
+ compatible = "fsl,mpc8272-scc-uart",
+ "fsl,cpm2-scc-uart";
+- reg = <11a60 20 8300 100>;
+- interrupts = <2b 8>;
++ reg = <0x11a60 0x20 0x8300 0x100>;
++ interrupts = <43 8>;
+ interrupt-parent = <&PIC>;
+ fsl,cpm-brg = <4>;
+- fsl,cpm-command = <0ce00000>;
++ fsl,cpm-command = <0xce00000>;
+ };
+
+ mdio at 10d40 {
+@@ -169,23 +171,23 @@
+ compatible = "fsl,mpc8272ads-mdio-bitbang",
+ "fsl,mpc8272-mdio-bitbang",
+ "fsl,cpm2-mdio-bitbang";
+- reg = <10d40 14>;
++ reg = <0x10d40 0x14>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+- fsl,mdio-pin = <12>;
+- fsl,mdc-pin = <13>;
++ fsl,mdio-pin = <18>;
++ fsl,mdc-pin = <19>;
+
+ PHY0: ethernet-phy at 0 {
+ interrupt-parent = <&PIC>;
+- interrupts = <17 8>;
+- reg = <0>;
++ interrupts = <23 8>;
++ reg = <0x0>;
+ device_type = "ethernet-phy";
+ };
+
+ PHY1: ethernet-phy at 1 {
+ interrupt-parent = <&PIC>;
+- interrupts = <17 8>;
+- reg = <3>;
++ interrupts = <23 8>;
++ reg = <0x3>;
+ device_type = "ethernet-phy";
+ };
+ };
+@@ -194,33 +196,33 @@
+ device_type = "network";
+ compatible = "fsl,mpc8272-fcc-enet",
+ "fsl,cpm2-fcc-enet";
+- reg = <11300 20 8400 100 11390 1>;
++ reg = <0x11300 0x20 0x8400 0x100 0x11390 0x1>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <20 8>;
++ interrupts = <32 8>;
+ interrupt-parent = <&PIC>;
+ phy-handle = <&PHY0>;
+ linux,network-index = <0>;
+- fsl,cpm-command = <12000300>;
++ fsl,cpm-command = <0x12000300>;
+ };
+
+ ethernet at 11320 {
+ device_type = "network";
+ compatible = "fsl,mpc8272-fcc-enet",
+ "fsl,cpm2-fcc-enet";
+- reg = <11320 20 8500 100 113b0 1>;
++ reg = <0x11320 0x20 0x8500 0x100 0x113b0 0x1>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <21 8>;
++ interrupts = <33 8>;
+ interrupt-parent = <&PIC>;
+ phy-handle = <&PHY1>;
+ linux,network-index = <1>;
+- fsl,cpm-command = <16200300>;
++ fsl,cpm-command = <0x16200300>;
+ };
+ };
+
+ PIC: interrupt-controller at 10c00 {
+ #interrupt-cells = <2>;
+ interrupt-controller;
+- reg = <10c00 80>;
++ reg = <0x10c00 0x80>;
+ compatible = "fsl,mpc8272-pic", "fsl,cpm2-pic";
+ };
+
+@@ -232,14 +234,14 @@
+ "fsl,talitos-sec2",
+ "fsl,talitos",
+ "talitos";
+- reg = <30000 10000>;
+- interrupts = <b 8>;
++ reg = <0x30000 0x10000>;
++ interrupts = <11 8>;
+ interrupt-parent = <&PIC>;
+ num-channels = <4>;
+- channel-fifo-len = <18>;
+- exec-units-mask = <0000007e>;
++ channel-fifo-len = <24>;
++ exec-units-mask = <0x7e>;
+ /* desc mask is for rev1.x, we need runtime fixup for >=2.x */
+- descriptor-types-mask = <01010ebf>;
++ descriptor-types-mask = <0x1010ebf>;
+ };
+ };
+
+diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts
+index 9bb4083..539e02f 100644
+--- a/arch/powerpc/boot/dts/mpc832x_mds.dts
++++ b/arch/powerpc/boot/dts/mpc832x_mds.dts
+@@ -255,9 +255,7 @@
+ enet0: ucc at 2200 {
+ device_type = "network";
+ compatible = "ucc_geth";
+- model = "UCC";
+ cell-index = <3>;
+- device-id = <3>;
+ reg = <0x2200 0x200>;
+ interrupts = <34>;
+ interrupt-parent = <&qeic>;
+@@ -271,9 +269,7 @@
+ enet1: ucc at 3200 {
+ device_type = "network";
+ compatible = "ucc_geth";
+- model = "UCC";
+ cell-index = <4>;
+- device-id = <4>;
+ reg = <0x3200 0x200>;
+ interrupts = <35>;
+ interrupt-parent = <&qeic>;
+@@ -287,8 +283,7 @@
+ ucc at 2400 {
+ device_type = "serial";
+ compatible = "ucc_uart";
+- model = "UCC";
+- device-id = <5>; /* The UCC number, 1-7*/
++ cell-index = <5>; /* The UCC number, 1-7*/
+ port-number = <0>; /* Which ttyQEx device */
+ soft-uart; /* We need Soft-UART */
+ reg = <0x2400 0x200>;
+diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts
+index 94f93d2..179c81c 100644
+--- a/arch/powerpc/boot/dts/mpc832x_rdb.dts
++++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts
+@@ -208,9 +208,7 @@
+ enet0: ucc at 3000 {
+ device_type = "network";
+ compatible = "ucc_geth";
+- model = "UCC";
+ cell-index = <2>;
+- device-id = <2>;
+ reg = <0x3000 0x200>;
+ interrupts = <33>;
+ interrupt-parent = <&qeic>;
+@@ -224,9 +222,7 @@
+ enet1: ucc at 2200 {
+ device_type = "network";
+ compatible = "ucc_geth";
+- model = "UCC";
+ cell-index = <3>;
+- device-id = <3>;
+ reg = <0x2200 0x200>;
+ interrupts = <34>;
+ interrupt-parent = <&qeic>;
+diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts
+index 55f03e8..8160ff2 100644
+--- a/arch/powerpc/boot/dts/mpc836x_mds.dts
++++ b/arch/powerpc/boot/dts/mpc836x_mds.dts
+@@ -257,9 +257,7 @@
+ enet0: ucc at 2000 {
+ device_type = "network";
+ compatible = "ucc_geth";
+- model = "UCC";
+ cell-index = <1>;
+- device-id = <1>;
+ reg = <0x2000 0x200>;
+ interrupts = <32>;
+ interrupt-parent = <&qeic>;
+@@ -274,9 +272,7 @@
+ enet1: ucc at 3000 {
+ device_type = "network";
+ compatible = "ucc_geth";
+- model = "UCC";
+ cell-index = <2>;
+- device-id = <2>;
+ reg = <0x3000 0x200>;
+ interrupts = <33>;
+ interrupt-parent = <&qeic>;
+diff --git a/arch/powerpc/boot/dts/mpc8540ads.dts b/arch/powerpc/boot/dts/mpc8540ads.dts
+index 9752484..18033ed 100644
+--- a/arch/powerpc/boot/dts/mpc8540ads.dts
++++ b/arch/powerpc/boot/dts/mpc8540ads.dts
+@@ -1,7 +1,7 @@
+ /*
+ * MPC8540 ADS Device Tree Source
+ *
+- * Copyright 2006 Freescale Semiconductor Inc.
++ * Copyright 2006, 2008 Freescale Semiconductor Inc.
+ *
+ * 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
+@@ -9,6 +9,7 @@
+ * option) any later version.
+ */
+
++/dts-v1/;
+
+ / {
+ model = "MPC8540ADS";
+@@ -31,11 +32,11 @@
+
+ PowerPC,8540 at 0 {
+ device_type = "cpu";
+- reg = <0>;
+- d-cache-line-size = <20>; // 32 bytes
+- i-cache-line-size = <20>; // 32 bytes
+- d-cache-size = <8000>; // L1, 32K
+- i-cache-size = <8000>; // L1, 32K
++ reg = <0x0>;
++ d-cache-line-size = <32>; // 32 bytes
++ i-cache-line-size = <32>; // 32 bytes
++ d-cache-size = <0x8000>; // L1, 32K
++ i-cache-size = <0x8000>; // L1, 32K
+ timebase-frequency = <0>; // 33 MHz, from uboot
+ bus-frequency = <0>; // 166 MHz
+ clock-frequency = <0>; // 825 MHz, from uboot
+@@ -44,31 +45,31 @@
+
+ memory {
+ device_type = "memory";
+- reg = <00000000 08000000>; // 128M at 0x0
++ reg = <0x0 0x8000000>; // 128M at 0x0
+ };
+
+ soc8540 at e0000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+- ranges = <0 e0000000 00100000>;
+- reg = <e0000000 00100000>; // CCSRBAR 1M
++ ranges = <0x0 0xe0000000 0x100000>;
++ reg = <0xe0000000 0x100000>; // CCSRBAR 1M
+ bus-frequency = <0>;
+
+ memory-controller at 2000 {
+ compatible = "fsl,8540-memory-controller";
+- reg = <2000 1000>;
++ reg = <0x2000 0x1000>;
+ interrupt-parent = <&mpic>;
+- interrupts = <12 2>;
++ interrupts = <18 2>;
+ };
+
+ l2-cache-controller at 20000 {
+ compatible = "fsl,8540-l2-cache-controller";
+- reg = <20000 1000>;
+- cache-line-size = <20>; // 32 bytes
+- cache-size = <40000>; // L2, 256K
++ reg = <0x20000 0x1000>;
++ cache-line-size = <32>; // 32 bytes
++ cache-size = <0x40000>; // L2, 256K
+ interrupt-parent = <&mpic>;
+- interrupts = <10 2>;
++ interrupts = <16 2>;
+ };
+
+ i2c at 3000 {
+@@ -76,8 +77,8 @@
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+- reg = <3000 100>;
+- interrupts = <2b 2>;
++ reg = <0x3000 0x100>;
++ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+@@ -86,24 +87,24 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,gianfar-mdio";
+- reg = <24520 20>;
++ reg = <0x24520 0x20>;
+
+ phy0: ethernet-phy at 0 {
+ interrupt-parent = <&mpic>;
+ interrupts = <5 1>;
+- reg = <0>;
++ reg = <0x0>;
+ device_type = "ethernet-phy";
+ };
+ phy1: ethernet-phy at 1 {
+ interrupt-parent = <&mpic>;
+ interrupts = <5 1>;
+- reg = <1>;
++ reg = <0x1>;
+ device_type = "ethernet-phy";
+ };
+ phy3: ethernet-phy at 3 {
+ interrupt-parent = <&mpic>;
+ interrupts = <7 1>;
+- reg = <3>;
++ reg = <0x3>;
+ device_type = "ethernet-phy";
+ };
+ };
+@@ -113,9 +114,9 @@
+ device_type = "network";
+ model = "TSEC";
+ compatible = "gianfar";
+- reg = <24000 1000>;
++ reg = <0x24000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <1d 2 1e 2 22 2>;
++ interrupts = <29 2 30 2 34 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy0>;
+ };
+@@ -125,9 +126,9 @@
+ device_type = "network";
+ model = "TSEC";
+ compatible = "gianfar";
+- reg = <25000 1000>;
++ reg = <0x25000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <23 2 24 2 28 2>;
++ interrupts = <35 2 36 2 40 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy1>;
+ };
+@@ -137,9 +138,9 @@
+ device_type = "network";
+ model = "FEC";
+ compatible = "gianfar";
+- reg = <26000 1000>;
++ reg = <0x26000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <29 2>;
++ interrupts = <41 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy3>;
+ };
+@@ -148,9 +149,9 @@
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <4500 100>; // reg base, size
++ reg = <0x4500 0x100>; // reg base, size
+ clock-frequency = <0>; // should we fill in in uboot?
+- interrupts = <2a 2>;
++ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+@@ -158,9 +159,9 @@
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <4600 100>; // reg base, size
++ reg = <0x4600 0x100>; // reg base, size
+ clock-frequency = <0>; // should we fill in in uboot?
+- interrupts = <2a 2>;
++ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+ mpic: pic at 40000 {
+@@ -168,7 +169,7 @@
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+- reg = <40000 40000>;
++ reg = <0x40000 0x40000>;
+ compatible = "chrp,open-pic";
+ device_type = "open-pic";
+ big-endian;
+@@ -177,90 +178,90 @@
+
+ pci0: pci at e0008000 {
+ cell-index = <0>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+
+ /* IDSEL 0x02 */
+- 1000 0 0 1 &mpic 1 1
+- 1000 0 0 2 &mpic 2 1
+- 1000 0 0 3 &mpic 3 1
+- 1000 0 0 4 &mpic 4 1
++ 0x1000 0x0 0x0 0x1 &mpic 0x1 0x1
++ 0x1000 0x0 0x0 0x2 &mpic 0x2 0x1
++ 0x1000 0x0 0x0 0x3 &mpic 0x3 0x1
++ 0x1000 0x0 0x0 0x4 &mpic 0x4 0x1
+
+ /* IDSEL 0x03 */
+- 1800 0 0 1 &mpic 4 1
+- 1800 0 0 2 &mpic 1 1
+- 1800 0 0 3 &mpic 2 1
+- 1800 0 0 4 &mpic 3 1
++ 0x1800 0x0 0x0 0x1 &mpic 0x4 0x1
++ 0x1800 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x1800 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x1800 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x04 */
+- 2000 0 0 1 &mpic 3 1
+- 2000 0 0 2 &mpic 4 1
+- 2000 0 0 3 &mpic 1 1
+- 2000 0 0 4 &mpic 2 1
++ 0x2000 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x2000 0x0 0x0 0x2 &mpic 0x4 0x1
++ 0x2000 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0x2000 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ /* IDSEL 0x05 */
+- 2800 0 0 1 &mpic 2 1
+- 2800 0 0 2 &mpic 3 1
+- 2800 0 0 3 &mpic 4 1
+- 2800 0 0 4 &mpic 1 1
++ 0x2800 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x2800 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x2800 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0x2800 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x0c */
+- 6000 0 0 1 &mpic 1 1
+- 6000 0 0 2 &mpic 2 1
+- 6000 0 0 3 &mpic 3 1
+- 6000 0 0 4 &mpic 4 1
++ 0x6000 0x0 0x0 0x1 &mpic 0x1 0x1
++ 0x6000 0x0 0x0 0x2 &mpic 0x2 0x1
++ 0x6000 0x0 0x0 0x3 &mpic 0x3 0x1
++ 0x6000 0x0 0x0 0x4 &mpic 0x4 0x1
+
+ /* IDSEL 0x0d */
+- 6800 0 0 1 &mpic 4 1
+- 6800 0 0 2 &mpic 1 1
+- 6800 0 0 3 &mpic 2 1
+- 6800 0 0 4 &mpic 3 1
++ 0x6800 0x0 0x0 0x1 &mpic 0x4 0x1
++ 0x6800 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x6800 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x6800 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x0e */
+- 7000 0 0 1 &mpic 3 1
+- 7000 0 0 2 &mpic 4 1
+- 7000 0 0 3 &mpic 1 1
+- 7000 0 0 4 &mpic 2 1
++ 0x7000 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x7000 0x0 0x0 0x2 &mpic 0x4 0x1
++ 0x7000 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0x7000 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ /* IDSEL 0x0f */
+- 7800 0 0 1 &mpic 2 1
+- 7800 0 0 2 &mpic 3 1
+- 7800 0 0 3 &mpic 4 1
+- 7800 0 0 4 &mpic 1 1
++ 0x7800 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x7800 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x7800 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0x7800 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x12 */
+- 9000 0 0 1 &mpic 1 1
+- 9000 0 0 2 &mpic 2 1
+- 9000 0 0 3 &mpic 3 1
+- 9000 0 0 4 &mpic 4 1
++ 0x9000 0x0 0x0 0x1 &mpic 0x1 0x1
++ 0x9000 0x0 0x0 0x2 &mpic 0x2 0x1
++ 0x9000 0x0 0x0 0x3 &mpic 0x3 0x1
++ 0x9000 0x0 0x0 0x4 &mpic 0x4 0x1
+
+ /* IDSEL 0x13 */
+- 9800 0 0 1 &mpic 4 1
+- 9800 0 0 2 &mpic 1 1
+- 9800 0 0 3 &mpic 2 1
+- 9800 0 0 4 &mpic 3 1
++ 0x9800 0x0 0x0 0x1 &mpic 0x4 0x1
++ 0x9800 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x9800 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x9800 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x14 */
+- a000 0 0 1 &mpic 3 1
+- a000 0 0 2 &mpic 4 1
+- a000 0 0 3 &mpic 1 1
+- a000 0 0 4 &mpic 2 1
++ 0xa000 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0xa000 0x0 0x0 0x2 &mpic 0x4 0x1
++ 0xa000 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0xa000 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ /* IDSEL 0x15 */
+- a800 0 0 1 &mpic 2 1
+- a800 0 0 2 &mpic 3 1
+- a800 0 0 3 &mpic 4 1
+- a800 0 0 4 &mpic 1 1>;
++ 0xa800 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0xa800 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0xa800 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0xa800 0x0 0x0 0x4 &mpic 0x1 0x1>;
+ interrupt-parent = <&mpic>;
+- interrupts = <18 2>;
++ interrupts = <24 2>;
+ bus-range = <0 0>;
+- ranges = <02000000 0 80000000 80000000 0 20000000
+- 01000000 0 00000000 e2000000 0 00100000>;
+- clock-frequency = <3f940aa>;
++ ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xe2000000 0x0 0x100000>;
++ clock-frequency = <66666666>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e0008000 1000>;
++ reg = <0xe0008000 0x1000>;
+ compatible = "fsl,mpc8540-pcix", "fsl,mpc8540-pci";
+ device_type = "pci";
+ };
+diff --git a/arch/powerpc/boot/dts/mpc8541cds.dts b/arch/powerpc/boot/dts/mpc8541cds.dts
+index fa8d9aa..663c7c5 100644
+--- a/arch/powerpc/boot/dts/mpc8541cds.dts
++++ b/arch/powerpc/boot/dts/mpc8541cds.dts
+@@ -1,7 +1,7 @@
+ /*
+ * MPC8541 CDS Device Tree Source
+ *
+- * Copyright 2006 Freescale Semiconductor Inc.
++ * Copyright 2006, 2008 Freescale Semiconductor Inc.
+ *
+ * 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
+@@ -9,6 +9,7 @@
+ * option) any later version.
+ */
+
++/dts-v1/;
+
+ / {
+ model = "MPC8541CDS";
+@@ -31,11 +32,11 @@
+
+ PowerPC,8541 at 0 {
+ device_type = "cpu";
+- reg = <0>;
+- d-cache-line-size = <20>; // 32 bytes
+- i-cache-line-size = <20>; // 32 bytes
+- d-cache-size = <8000>; // L1, 32K
+- i-cache-size = <8000>; // L1, 32K
++ reg = <0x0>;
++ d-cache-line-size = <32>; // 32 bytes
++ i-cache-line-size = <32>; // 32 bytes
++ d-cache-size = <0x8000>; // L1, 32K
++ i-cache-size = <0x8000>; // L1, 32K
+ timebase-frequency = <0>; // 33 MHz, from uboot
+ bus-frequency = <0>; // 166 MHz
+ clock-frequency = <0>; // 825 MHz, from uboot
+@@ -44,31 +45,31 @@
+
+ memory {
+ device_type = "memory";
+- reg = <00000000 08000000>; // 128M at 0x0
++ reg = <0x0 0x8000000>; // 128M at 0x0
+ };
+
+ soc8541 at e0000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+- ranges = <0 e0000000 00100000>;
+- reg = <e0000000 00001000>; // CCSRBAR 1M
++ ranges = <0x0 0xe0000000 0x100000>;
++ reg = <0xe0000000 0x1000>; // CCSRBAR 1M
+ bus-frequency = <0>;
+
+ memory-controller at 2000 {
+ compatible = "fsl,8541-memory-controller";
+- reg = <2000 1000>;
++ reg = <0x2000 0x1000>;
+ interrupt-parent = <&mpic>;
+- interrupts = <12 2>;
++ interrupts = <18 2>;
+ };
+
+ l2-cache-controller at 20000 {
+ compatible = "fsl,8541-l2-cache-controller";
+- reg = <20000 1000>;
+- cache-line-size = <20>; // 32 bytes
+- cache-size = <40000>; // L2, 256K
++ reg = <0x20000 0x1000>;
++ cache-line-size = <32>; // 32 bytes
++ cache-size = <0x40000>; // L2, 256K
+ interrupt-parent = <&mpic>;
+- interrupts = <10 2>;
++ interrupts = <16 2>;
+ };
+
+ i2c at 3000 {
+@@ -76,8 +77,8 @@
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+- reg = <3000 100>;
+- interrupts = <2b 2>;
++ reg = <0x3000 0x100>;
++ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+@@ -86,18 +87,18 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,gianfar-mdio";
+- reg = <24520 20>;
++ reg = <0x24520 0x20>;
+
+ phy0: ethernet-phy at 0 {
+ interrupt-parent = <&mpic>;
+ interrupts = <5 1>;
+- reg = <0>;
++ reg = <0x0>;
+ device_type = "ethernet-phy";
+ };
+ phy1: ethernet-phy at 1 {
+ interrupt-parent = <&mpic>;
+ interrupts = <5 1>;
+- reg = <1>;
++ reg = <0x1>;
+ device_type = "ethernet-phy";
+ };
+ };
+@@ -107,9 +108,9 @@
+ device_type = "network";
+ model = "TSEC";
+ compatible = "gianfar";
+- reg = <24000 1000>;
++ reg = <0x24000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <1d 2 1e 2 22 2>;
++ interrupts = <29 2 30 2 34 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy0>;
+ };
+@@ -119,9 +120,9 @@
+ device_type = "network";
+ model = "TSEC";
+ compatible = "gianfar";
+- reg = <25000 1000>;
++ reg = <0x25000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <23 2 24 2 28 2>;
++ interrupts = <35 2 36 2 40 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy1>;
+ };
+@@ -130,9 +131,9 @@
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <4500 100>; // reg base, size
++ reg = <0x4500 0x100>; // reg base, size
+ clock-frequency = <0>; // should we fill in in uboot?
+- interrupts = <2a 2>;
++ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+@@ -140,9 +141,9 @@
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <4600 100>; // reg base, size
++ reg = <0x4600 0x100>; // reg base, size
+ clock-frequency = <0>; // should we fill in in uboot?
+- interrupts = <2a 2>;
++ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+@@ -151,7 +152,7 @@
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+- reg = <40000 40000>;
++ reg = <0x40000 0x40000>;
+ compatible = "chrp,open-pic";
+ device_type = "open-pic";
+ big-endian;
+@@ -161,17 +162,17 @@
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8541-cpm", "fsl,cpm2";
+- reg = <919c0 30>;
++ reg = <0x919c0 0x30>;
+ ranges;
+
+ muram at 80000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+- ranges = <0 80000 10000>;
++ ranges = <0x0 0x80000 0x10000>;
+
+ data at 0 {
+ compatible = "fsl,cpm-muram-data";
+- reg = <0 2000 9000 1000>;
++ reg = <0x0 0x2000 0x9000 0x1000>;
+ };
+ };
+
+@@ -179,16 +180,16 @@
+ compatible = "fsl,mpc8541-brg",
+ "fsl,cpm2-brg",
+ "fsl,cpm-brg";
+- reg = <919f0 10 915f0 10>;
++ reg = <0x919f0 0x10 0x915f0 0x10>;
+ };
+
+ cpmpic: pic at 90c00 {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+- interrupts = <2e 2>;
++ interrupts = <46 2>;
+ interrupt-parent = <&mpic>;
+- reg = <90c00 80>;
++ reg = <0x90c00 0x80>;
+ compatible = "fsl,mpc8541-cpm-pic", "fsl,cpm2-pic";
+ };
+ };
+@@ -196,68 +197,68 @@
+
+ pci0: pci at e0008000 {
+ cell-index = <0>;
+- interrupt-map-mask = <1f800 0 0 7>;
++ interrupt-map-mask = <0x1f800 0x0 0x0 0x7>;
+ interrupt-map = <
+
+ /* IDSEL 0x10 */
+- 08000 0 0 1 &mpic 0 1
+- 08000 0 0 2 &mpic 1 1
+- 08000 0 0 3 &mpic 2 1
+- 08000 0 0 4 &mpic 3 1
++ 0x8000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x8000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x8000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x8000 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x11 */
+- 08800 0 0 1 &mpic 0 1
+- 08800 0 0 2 &mpic 1 1
+- 08800 0 0 3 &mpic 2 1
+- 08800 0 0 4 &mpic 3 1
++ 0x8800 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x8800 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x8800 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x8800 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x12 (Slot 1) */
+- 09000 0 0 1 &mpic 0 1
+- 09000 0 0 2 &mpic 1 1
+- 09000 0 0 3 &mpic 2 1
+- 09000 0 0 4 &mpic 3 1
++ 0x9000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x9000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x9000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x9000 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x13 (Slot 2) */
+- 09800 0 0 1 &mpic 1 1
+- 09800 0 0 2 &mpic 2 1
+- 09800 0 0 3 &mpic 3 1
+- 09800 0 0 4 &mpic 0 1
++ 0x9800 0x0 0x0 0x1 &mpic 0x1 0x1
++ 0x9800 0x0 0x0 0x2 &mpic 0x2 0x1
++ 0x9800 0x0 0x0 0x3 &mpic 0x3 0x1
++ 0x9800 0x0 0x0 0x4 &mpic 0x0 0x1
+
+ /* IDSEL 0x14 (Slot 3) */
+- 0a000 0 0 1 &mpic 2 1
+- 0a000 0 0 2 &mpic 3 1
+- 0a000 0 0 3 &mpic 0 1
+- 0a000 0 0 4 &mpic 1 1
++ 0xa000 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0xa000 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0xa000 0x0 0x0 0x3 &mpic 0x0 0x1
++ 0xa000 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x15 (Slot 4) */
+- 0a800 0 0 1 &mpic 3 1
+- 0a800 0 0 2 &mpic 0 1
+- 0a800 0 0 3 &mpic 1 1
+- 0a800 0 0 4 &mpic 2 1
++ 0xa800 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0xa800 0x0 0x0 0x2 &mpic 0x0 0x1
++ 0xa800 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0xa800 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ /* Bus 1 (Tundra Bridge) */
+ /* IDSEL 0x12 (ISA bridge) */
+- 19000 0 0 1 &mpic 0 1
+- 19000 0 0 2 &mpic 1 1
+- 19000 0 0 3 &mpic 2 1
+- 19000 0 0 4 &mpic 3 1>;
++ 0x19000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x19000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x19000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x19000 0x0 0x0 0x4 &mpic 0x3 0x1>;
+ interrupt-parent = <&mpic>;
+- interrupts = <18 2>;
++ interrupts = <24 2>;
+ bus-range = <0 0>;
+- ranges = <02000000 0 80000000 80000000 0 20000000
+- 01000000 0 00000000 e2000000 0 00100000>;
+- clock-frequency = <3f940aa>;
++ ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xe2000000 0x0 0x100000>;
++ clock-frequency = <66666666>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e0008000 1000>;
++ reg = <0xe0008000 0x1000>;
+ compatible = "fsl,mpc8540-pci";
+ device_type = "pci";
+
+ i8259 at 19000 {
+ interrupt-controller;
+ device_type = "interrupt-controller";
+- reg = <19000 0 0 0 1>;
++ reg = <0x19000 0x0 0x0 0x0 0x1>;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ compatible = "chrp,iic";
+@@ -268,24 +269,24 @@
+
+ pci1: pci at e0009000 {
+ cell-index = <1>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+
+ /* IDSEL 0x15 */
+- a800 0 0 1 &mpic b 1
+- a800 0 0 2 &mpic b 1
+- a800 0 0 3 &mpic b 1
+- a800 0 0 4 &mpic b 1>;
++ 0xa800 0x0 0x0 0x1 &mpic 0xb 0x1
++ 0xa800 0x0 0x0 0x2 &mpic 0xb 0x1
++ 0xa800 0x0 0x0 0x3 &mpic 0xb 0x1
++ 0xa800 0x0 0x0 0x4 &mpic 0xb 0x1>;
+ interrupt-parent = <&mpic>;
+- interrupts = <19 2>;
++ interrupts = <25 2>;
+ bus-range = <0 0>;
+- ranges = <02000000 0 a0000000 a0000000 0 20000000
+- 01000000 0 00000000 e3000000 0 00100000>;
+- clock-frequency = <3f940aa>;
++ ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xe3000000 0x0 0x100000>;
++ clock-frequency = <66666666>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e0009000 1000>;
++ reg = <0xe0009000 0x1000>;
+ compatible = "fsl,mpc8540-pci";
+ device_type = "pci";
+ };
+diff --git a/arch/powerpc/boot/dts/mpc8544ds.dts b/arch/powerpc/boot/dts/mpc8544ds.dts
+index 688af9d..6a0d8db 100644
+--- a/arch/powerpc/boot/dts/mpc8544ds.dts
++++ b/arch/powerpc/boot/dts/mpc8544ds.dts
+@@ -1,7 +1,7 @@
+ /*
+ * MPC8544 DS Device Tree Source
+ *
+- * Copyright 2007 Freescale Semiconductor Inc.
++ * Copyright 2007, 2008 Freescale Semiconductor Inc.
+ *
+ * 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
+@@ -9,6 +9,7 @@
+ * option) any later version.
+ */
+
++/dts-v1/;
+ / {
+ model = "MPC8544DS";
+ compatible = "MPC8544DS", "MPC85xxDS";
+@@ -27,17 +28,16 @@
+ };
+
+ cpus {
+- #cpus = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ PowerPC,8544 at 0 {
+ device_type = "cpu";
+- reg = <0>;
+- d-cache-line-size = <20>; // 32 bytes
+- i-cache-line-size = <20>; // 32 bytes
+- d-cache-size = <8000>; // L1, 32K
+- i-cache-size = <8000>; // L1, 32K
++ reg = <0x0>;
++ d-cache-line-size = <32>; // 32 bytes
++ i-cache-line-size = <32>; // 32 bytes
++ d-cache-size = <0x8000>; // L1, 32K
++ i-cache-size = <0x8000>; // L1, 32K
+ timebase-frequency = <0>;
+ bus-frequency = <0>;
+ clock-frequency = <0>;
+@@ -46,7 +46,7 @@
+
+ memory {
+ device_type = "memory";
+- reg = <00000000 00000000>; // Filled by U-Boot
++ reg = <0x0 0x0>; // Filled by U-Boot
+ };
+
+ soc8544 at e0000000 {
+@@ -54,24 +54,24 @@
+ #size-cells = <1>;
+ device_type = "soc";
+
+- ranges = <00000000 e0000000 00100000>;
+- reg = <e0000000 00001000>; // CCSRBAR 1M
++ ranges = <0x0 0xe0000000 0x100000>;
++ reg = <0xe0000000 0x1000>; // CCSRBAR 1M
+ bus-frequency = <0>; // Filled out by uboot.
+
+ memory-controller at 2000 {
+ compatible = "fsl,8544-memory-controller";
+- reg = <2000 1000>;
++ reg = <0x2000 0x1000>;
+ interrupt-parent = <&mpic>;
+- interrupts = <12 2>;
++ interrupts = <18 2>;
+ };
+
+ l2-cache-controller at 20000 {
+ compatible = "fsl,8544-l2-cache-controller";
+- reg = <20000 1000>;
+- cache-line-size = <20>; // 32 bytes
+- cache-size = <40000>; // L2, 256K
++ reg = <0x20000 0x1000>;
++ cache-line-size = <32>; // 32 bytes
++ cache-size = <0x40000>; // L2, 256K
+ interrupt-parent = <&mpic>;
+- interrupts = <10 2>;
++ interrupts = <16 2>;
+ };
+
+ i2c at 3000 {
+@@ -79,8 +79,8 @@
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+- reg = <3000 100>;
+- interrupts = <2b 2>;
++ reg = <0x3000 0x100>;
++ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+@@ -90,8 +90,8 @@
+ #size-cells = <0>;
+ cell-index = <1>;
+ compatible = "fsl-i2c";
+- reg = <3100 100>;
+- interrupts = <2b 2>;
++ reg = <0x3100 0x100>;
++ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+@@ -100,30 +100,71 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,gianfar-mdio";
+- reg = <24520 20>;
++ reg = <0x24520 0x20>;
+
+ phy0: ethernet-phy at 0 {
+ interrupt-parent = <&mpic>;
+- interrupts = <a 1>;
+- reg = <0>;
++ interrupts = <10 1>;
++ reg = <0x0>;
+ device_type = "ethernet-phy";
+ };
+ phy1: ethernet-phy at 1 {
+ interrupt-parent = <&mpic>;
+- interrupts = <a 1>;
+- reg = <1>;
++ interrupts = <10 1>;
++ reg = <0x1>;
+ device_type = "ethernet-phy";
+ };
+ };
+
++ dma at 21300 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "fsl,mpc8544-dma", "fsl,eloplus-dma";
++ reg = <0x21300 0x4>;
++ ranges = <0x0 0x21100 0x200>;
++ cell-index = <0>;
++ dma-channel at 0 {
++ compatible = "fsl,mpc8544-dma-channel",
++ "fsl,eloplus-dma-channel";
++ reg = <0x0 0x80>;
++ cell-index = <0>;
++ interrupt-parent = <&mpic>;
++ interrupts = <20 2>;
++ };
++ dma-channel at 80 {
++ compatible = "fsl,mpc8544-dma-channel",
++ "fsl,eloplus-dma-channel";
++ reg = <0x80 0x80>;
++ cell-index = <1>;
++ interrupt-parent = <&mpic>;
++ interrupts = <21 2>;
++ };
++ dma-channel at 100 {
++ compatible = "fsl,mpc8544-dma-channel",
++ "fsl,eloplus-dma-channel";
++ reg = <0x100 0x80>;
++ cell-index = <2>;
++ interrupt-parent = <&mpic>;
++ interrupts = <22 2>;
++ };
++ dma-channel at 180 {
++ compatible = "fsl,mpc8544-dma-channel",
++ "fsl,eloplus-dma-channel";
++ reg = <0x180 0x80>;
++ cell-index = <3>;
++ interrupt-parent = <&mpic>;
++ interrupts = <23 2>;
++ };
++ };
++
+ enet0: ethernet at 24000 {
+ cell-index = <0>;
+ device_type = "network";
+ model = "TSEC";
+ compatible = "gianfar";
+- reg = <24000 1000>;
++ reg = <0x24000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <1d 2 1e 2 22 2>;
++ interrupts = <29 2 30 2 34 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy0>;
+ phy-connection-type = "rgmii-id";
+@@ -134,9 +175,9 @@
+ device_type = "network";
+ model = "TSEC";
+ compatible = "gianfar";
+- reg = <26000 1000>;
++ reg = <0x26000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <1f 2 20 2 21 2>;
++ interrupts = <31 2 32 2 33 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy1>;
+ phy-connection-type = "rgmii-id";
+@@ -146,9 +187,9 @@
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <4500 100>;
++ reg = <0x4500 0x100>;
+ clock-frequency = <0>;
+- interrupts = <2a 2>;
++ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+@@ -156,15 +197,15 @@
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <4600 100>;
++ reg = <0x4600 0x100>;
+ clock-frequency = <0>;
+- interrupts = <2a 2>;
++ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ global-utilities at e0000 { //global utilities block
+ compatible = "fsl,mpc8548-guts";
+- reg = <e0000 1000>;
++ reg = <0xe0000 0x1000>;
+ fsl,has-rstcr;
+ };
+
+@@ -173,7 +214,7 @@
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+- reg = <40000 40000>;
++ reg = <0x40000 0x40000>;
+ compatible = "chrp,open-pic";
+ device_type = "open-pic";
+ big-endian;
+@@ -184,32 +225,32 @@
+ cell-index = <0>;
+ compatible = "fsl,mpc8540-pci";
+ device_type = "pci";
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+
+ /* IDSEL 0x11 J17 Slot 1 */
+- 8800 0 0 1 &mpic 2 1
+- 8800 0 0 2 &mpic 3 1
+- 8800 0 0 3 &mpic 4 1
+- 8800 0 0 4 &mpic 1 1
++ 0x8800 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x8800 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x8800 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0x8800 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x12 J16 Slot 2 */
+
+- 9000 0 0 1 &mpic 3 1
+- 9000 0 0 2 &mpic 4 1
+- 9000 0 0 3 &mpic 2 1
+- 9000 0 0 4 &mpic 1 1>;
++ 0x9000 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x9000 0x0 0x0 0x2 &mpic 0x4 0x1
++ 0x9000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x9000 0x0 0x0 0x4 &mpic 0x1 0x1>;
+
+ interrupt-parent = <&mpic>;
+- interrupts = <18 2>;
+- bus-range = <0 ff>;
+- ranges = <02000000 0 c0000000 c0000000 0 20000000
+- 01000000 0 00000000 e1000000 0 00010000>;
+- clock-frequency = <3f940aa>;
++ interrupts = <24 2>;
++ bus-range = <0 255>;
++ ranges = <0x2000000 0x0 0xc0000000 0xc0000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xe1000000 0x0 0x10000>;
++ clock-frequency = <66666666>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e0008000 1000>;
++ reg = <0xe0008000 0x1000>;
+ };
+
+ pci1: pcie at e0009000 {
+@@ -219,33 +260,33 @@
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e0009000 1000>;
+- bus-range = <0 ff>;
+- ranges = <02000000 0 80000000 80000000 0 20000000
+- 01000000 0 00000000 e1010000 0 00010000>;
+- clock-frequency = <1fca055>;
++ reg = <0xe0009000 0x1000>;
++ bus-range = <0 255>;
++ ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xe1010000 0x0 0x10000>;
++ clock-frequency = <33333333>;
+ interrupt-parent = <&mpic>;
+- interrupts = <1a 2>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupts = <26 2>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+- 0000 0 0 1 &mpic 4 1
+- 0000 0 0 2 &mpic 5 1
+- 0000 0 0 3 &mpic 6 1
+- 0000 0 0 4 &mpic 7 1
++ 0000 0x0 0x0 0x1 &mpic 0x4 0x1
++ 0000 0x0 0x0 0x2 &mpic 0x5 0x1
++ 0000 0x0 0x0 0x3 &mpic 0x6 0x1
++ 0000 0x0 0x0 0x4 &mpic 0x7 0x1
+ >;
+ pcie at 0 {
+- reg = <0 0 0 0 0>;
++ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+- ranges = <02000000 0 80000000
+- 02000000 0 80000000
+- 0 20000000
++ ranges = <0x2000000 0x0 0x80000000
++ 0x2000000 0x0 0x80000000
++ 0x0 0x20000000
+
+- 01000000 0 00000000
+- 01000000 0 00000000
+- 0 00010000>;
++ 0x1000000 0x0 0x0
++ 0x1000000 0x0 0x0
++ 0x0 0x10000>;
+ };
+ };
+
+@@ -256,33 +297,33 @@
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e000a000 1000>;
+- bus-range = <0 ff>;
+- ranges = <02000000 0 a0000000 a0000000 0 10000000
+- 01000000 0 00000000 e1020000 0 00010000>;
+- clock-frequency = <1fca055>;
++ reg = <0xe000a000 0x1000>;
++ bus-range = <0 255>;
++ ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000
++ 0x1000000 0x0 0x0 0xe1020000 0x0 0x10000>;
++ clock-frequency = <33333333>;
+ interrupt-parent = <&mpic>;
+- interrupts = <19 2>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupts = <25 2>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+- 0000 0 0 1 &mpic 0 1
+- 0000 0 0 2 &mpic 1 1
+- 0000 0 0 3 &mpic 2 1
+- 0000 0 0 4 &mpic 3 1
++ 0000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0000 0x0 0x0 0x4 &mpic 0x3 0x1
+ >;
+ pcie at 0 {
+- reg = <0 0 0 0 0>;
++ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+- ranges = <02000000 0 a0000000
+- 02000000 0 a0000000
+- 0 10000000
++ ranges = <0x2000000 0x0 0xa0000000
++ 0x2000000 0x0 0xa0000000
++ 0x0 0x10000000
+
+- 01000000 0 00000000
+- 01000000 0 00000000
+- 0 00010000>;
++ 0x1000000 0x0 0x0
++ 0x1000000 0x0 0x0
++ 0x0 0x10000>;
+ };
+ };
+
+@@ -293,72 +334,72 @@
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e000b000 1000>;
+- bus-range = <0 ff>;
+- ranges = <02000000 0 b0000000 b0000000 0 00100000
+- 01000000 0 00000000 b0100000 0 00100000>;
+- clock-frequency = <1fca055>;
++ reg = <0xe000b000 0x1000>;
++ bus-range = <0 255>;
++ ranges = <0x2000000 0x0 0xb0000000 0xb0000000 0x0 0x100000
++ 0x1000000 0x0 0x0 0xb0100000 0x0 0x100000>;
++ clock-frequency = <33333333>;
+ interrupt-parent = <&mpic>;
+- interrupts = <1b 2>;
+- interrupt-map-mask = <ff00 0 0 1>;
++ interrupts = <27 2>;
++ interrupt-map-mask = <0xff00 0x0 0x0 0x1>;
+ interrupt-map = <
+ // IDSEL 0x1c USB
+- e000 0 0 1 &i8259 c 2
+- e100 0 0 2 &i8259 9 2
+- e200 0 0 3 &i8259 a 2
+- e300 0 0 4 &i8259 b 2
++ 0xe000 0x0 0x0 0x1 &i8259 0xc 0x2
++ 0xe100 0x0 0x0 0x2 &i8259 0x9 0x2
++ 0xe200 0x0 0x0 0x3 &i8259 0xa 0x2
++ 0xe300 0x0 0x0 0x4 &i8259 0xb 0x2
+
+ // IDSEL 0x1d Audio
+- e800 0 0 1 &i8259 6 2
++ 0xe800 0x0 0x0 0x1 &i8259 0x6 0x2
+
+ // IDSEL 0x1e Legacy
+- f000 0 0 1 &i8259 7 2
+- f100 0 0 1 &i8259 7 2
++ 0xf000 0x0 0x0 0x1 &i8259 0x7 0x2
++ 0xf100 0x0 0x0 0x1 &i8259 0x7 0x2
+
+ // IDSEL 0x1f IDE/SATA
+- f800 0 0 1 &i8259 e 2
+- f900 0 0 1 &i8259 5 2
++ 0xf800 0x0 0x0 0x1 &i8259 0xe 0x2
++ 0xf900 0x0 0x0 0x1 &i8259 0x5 0x2
+ >;
+
+ pcie at 0 {
+- reg = <0 0 0 0 0>;
++ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+- ranges = <02000000 0 b0000000
+- 02000000 0 b0000000
+- 0 00100000
++ ranges = <0x2000000 0x0 0xb0000000
++ 0x2000000 0x0 0xb0000000
++ 0x0 0x100000
+
+- 01000000 0 00000000
+- 01000000 0 00000000
+- 0 00100000>;
++ 0x1000000 0x0 0x0
++ 0x1000000 0x0 0x0
++ 0x0 0x100000>;
+
+ uli1575 at 0 {
+- reg = <0 0 0 0 0>;
++ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- ranges = <02000000 0 b0000000
+- 02000000 0 b0000000
+- 0 00100000
++ ranges = <0x2000000 0x0 0xb0000000
++ 0x2000000 0x0 0xb0000000
++ 0x0 0x100000
+
+- 01000000 0 00000000
+- 01000000 0 00000000
+- 0 00100000>;
++ 0x1000000 0x0 0x0
++ 0x1000000 0x0 0x0
++ 0x0 0x100000>;
+ isa at 1e {
+ device_type = "isa";
+ #interrupt-cells = <2>;
+ #size-cells = <1>;
+ #address-cells = <2>;
+- reg = <f000 0 0 0 0>;
+- ranges = <1 0
+- 01000000 0 0
+- 00001000>;
++ reg = <0xf000 0x0 0x0 0x0 0x0>;
++ ranges = <0x1 0x0
++ 0x1000000 0x0 0x0
++ 0x1000>;
+ interrupt-parent = <&i8259>;
+
+ i8259: interrupt-controller at 20 {
+- reg = <1 20 2
+- 1 a0 2
+- 1 4d0 2>;
++ reg = <0x1 0x20 0x2
++ 0x1 0xa0 0x2
++ 0x1 0x4d0 0x2>;
+ interrupt-controller;
+ device_type = "interrupt-controller";
+ #address-cells = <0>;
+@@ -371,28 +412,28 @@
+ i8042 at 60 {
+ #size-cells = <0>;
+ #address-cells = <1>;
+- reg = <1 60 1 1 64 1>;
+- interrupts = <1 3 c 3>;
++ reg = <0x1 0x60 0x1 0x1 0x64 0x1>;
++ interrupts = <1 3 12 3>;
+ interrupt-parent = <&i8259>;
+
+ keyboard at 0 {
+- reg = <0>;
++ reg = <0x0>;
+ compatible = "pnpPNP,303";
+ };
+
+ mouse at 1 {
+- reg = <1>;
++ reg = <0x1>;
+ compatible = "pnpPNP,f03";
+ };
+ };
+
+ rtc at 70 {
+ compatible = "pnpPNP,b00";
+- reg = <1 70 2>;
++ reg = <0x1 0x70 0x2>;
+ };
+
+ gpio at 400 {
+- reg = <1 400 80>;
++ reg = <0x1 0x400 0x80>;
+ };
+ };
+ };
+diff --git a/arch/powerpc/boot/dts/mpc8548cds.dts b/arch/powerpc/boot/dts/mpc8548cds.dts
+index 1f470c6..fa298a8 100644
+--- a/arch/powerpc/boot/dts/mpc8548cds.dts
++++ b/arch/powerpc/boot/dts/mpc8548cds.dts
+@@ -1,7 +1,7 @@
+ /*
+ * MPC8548 CDS Device Tree Source
+ *
+- * Copyright 2006 Freescale Semiconductor Inc.
++ * Copyright 2006, 2008 Freescale Semiconductor Inc.
+ *
+ * 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
+@@ -9,6 +9,7 @@
+ * option) any later version.
+ */
+
++/dts-v1/;
+
+ / {
+ model = "MPC8548CDS";
+@@ -36,11 +37,11 @@
+
+ PowerPC,8548 at 0 {
+ device_type = "cpu";
+- reg = <0>;
+- d-cache-line-size = <20>; // 32 bytes
+- i-cache-line-size = <20>; // 32 bytes
+- d-cache-size = <8000>; // L1, 32K
+- i-cache-size = <8000>; // L1, 32K
++ reg = <0x0>;
++ d-cache-line-size = <32>; // 32 bytes
++ i-cache-line-size = <32>; // 32 bytes
++ d-cache-size = <0x8000>; // L1, 32K
++ i-cache-size = <0x8000>; // L1, 32K
+ timebase-frequency = <0>; // 33 MHz, from uboot
+ bus-frequency = <0>; // 166 MHz
+ clock-frequency = <0>; // 825 MHz, from uboot
+@@ -49,31 +50,31 @@
+
+ memory {
+ device_type = "memory";
+- reg = <00000000 08000000>; // 128M at 0x0
++ reg = <0x0 0x8000000>; // 128M at 0x0
+ };
+
+ soc8548 at e0000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+- ranges = <00000000 e0000000 00100000>;
+- reg = <e0000000 00001000>; // CCSRBAR
++ ranges = <0x0 0xe0000000 0x100000>;
++ reg = <0xe0000000 0x1000>; // CCSRBAR
+ bus-frequency = <0>;
+
+ memory-controller at 2000 {
+ compatible = "fsl,8548-memory-controller";
+- reg = <2000 1000>;
++ reg = <0x2000 0x1000>;
+ interrupt-parent = <&mpic>;
+- interrupts = <12 2>;
++ interrupts = <18 2>;
+ };
+
+ l2-cache-controller at 20000 {
+ compatible = "fsl,8548-l2-cache-controller";
+- reg = <20000 1000>;
+- cache-line-size = <20>; // 32 bytes
+- cache-size = <80000>; // L2, 512K
++ reg = <0x20000 0x1000>;
++ cache-line-size = <32>; // 32 bytes
++ cache-size = <0x80000>; // L2, 512K
+ interrupt-parent = <&mpic>;
+- interrupts = <10 2>;
++ interrupts = <16 2>;
+ };
+
+ i2c at 3000 {
+@@ -81,8 +82,8 @@
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+- reg = <3000 100>;
+- interrupts = <2b 2>;
++ reg = <0x3000 0x100>;
++ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+@@ -92,8 +93,8 @@
+ #size-cells = <0>;
+ cell-index = <1>;
+ compatible = "fsl-i2c";
+- reg = <3100 100>;
+- interrupts = <2b 2>;
++ reg = <0x3100 0x100>;
++ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+@@ -102,30 +103,30 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,gianfar-mdio";
+- reg = <24520 20>;
++ reg = <0x24520 0x20>;
+
+ phy0: ethernet-phy at 0 {
+ interrupt-parent = <&mpic>;
+ interrupts = <5 1>;
+- reg = <0>;
++ reg = <0x0>;
+ device_type = "ethernet-phy";
+ };
+ phy1: ethernet-phy at 1 {
+ interrupt-parent = <&mpic>;
+ interrupts = <5 1>;
+- reg = <1>;
++ reg = <0x1>;
+ device_type = "ethernet-phy";
+ };
+ phy2: ethernet-phy at 2 {
+ interrupt-parent = <&mpic>;
+ interrupts = <5 1>;
+- reg = <2>;
++ reg = <0x2>;
+ device_type = "ethernet-phy";
+ };
+ phy3: ethernet-phy at 3 {
+ interrupt-parent = <&mpic>;
+ interrupts = <5 1>;
+- reg = <3>;
++ reg = <0x3>;
+ device_type = "ethernet-phy";
+ };
+ };
+@@ -135,9 +136,9 @@
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "gianfar";
+- reg = <24000 1000>;
++ reg = <0x24000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <1d 2 1e 2 22 2>;
++ interrupts = <29 2 30 2 34 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy0>;
+ };
+@@ -147,9 +148,9 @@
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "gianfar";
+- reg = <25000 1000>;
++ reg = <0x25000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <23 2 24 2 28 2>;
++ interrupts = <35 2 36 2 40 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy1>;
+ };
+@@ -160,9 +161,9 @@
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "gianfar";
+- reg = <26000 1000>;
++ reg = <0x26000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <1f 2 20 2 21 2>;
++ interrupts = <31 2 32 2 33 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy2>;
+ };
+@@ -172,9 +173,9 @@
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "gianfar";
+- reg = <27000 1000>;
++ reg = <0x27000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <25 2 26 2 27 2>;
++ interrupts = <37 2 38 2 39 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy3>;
+ };
+@@ -184,9 +185,9 @@
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <4500 100>; // reg base, size
++ reg = <0x4500 0x100>; // reg base, size
+ clock-frequency = <0>; // should we fill in in uboot?
+- interrupts = <2a 2>;
++ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+@@ -194,15 +195,15 @@
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <4600 100>; // reg base, size
++ reg = <0x4600 0x100>; // reg base, size
+ clock-frequency = <0>; // should we fill in in uboot?
+- interrupts = <2a 2>;
++ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ global-utilities at e0000 { //global utilities reg
+ compatible = "fsl,mpc8548-guts";
+- reg = <e0000 1000>;
++ reg = <0xe0000 0x1000>;
+ fsl,has-rstcr;
+ };
+
+@@ -211,7 +212,7 @@
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+- reg = <40000 40000>;
++ reg = <0x40000 0x40000>;
+ compatible = "chrp,open-pic";
+ device_type = "open-pic";
+ big-endian;
+@@ -220,139 +221,139 @@
+
+ pci0: pci at e0008000 {
+ cell-index = <0>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x4 (PCIX Slot 2) */
+- 02000 0 0 1 &mpic 0 1
+- 02000 0 0 2 &mpic 1 1
+- 02000 0 0 3 &mpic 2 1
+- 02000 0 0 4 &mpic 3 1
++ 0x2000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x2000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x2000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x2000 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x5 (PCIX Slot 3) */
+- 02800 0 0 1 &mpic 1 1
+- 02800 0 0 2 &mpic 2 1
+- 02800 0 0 3 &mpic 3 1
+- 02800 0 0 4 &mpic 0 1
++ 0x2800 0x0 0x0 0x1 &mpic 0x1 0x1
++ 0x2800 0x0 0x0 0x2 &mpic 0x2 0x1
++ 0x2800 0x0 0x0 0x3 &mpic 0x3 0x1
++ 0x2800 0x0 0x0 0x4 &mpic 0x0 0x1
+
+ /* IDSEL 0x6 (PCIX Slot 4) */
+- 03000 0 0 1 &mpic 2 1
+- 03000 0 0 2 &mpic 3 1
+- 03000 0 0 3 &mpic 0 1
+- 03000 0 0 4 &mpic 1 1
++ 0x3000 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x3000 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x3000 0x0 0x0 0x3 &mpic 0x0 0x1
++ 0x3000 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x8 (PCIX Slot 5) */
+- 04000 0 0 1 &mpic 0 1
+- 04000 0 0 2 &mpic 1 1
+- 04000 0 0 3 &mpic 2 1
+- 04000 0 0 4 &mpic 3 1
++ 0x4000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x4000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x4000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x4000 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0xC (Tsi310 bridge) */
+- 06000 0 0 1 &mpic 0 1
+- 06000 0 0 2 &mpic 1 1
+- 06000 0 0 3 &mpic 2 1
+- 06000 0 0 4 &mpic 3 1
++ 0x6000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x6000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x6000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x6000 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x14 (Slot 2) */
+- 0a000 0 0 1 &mpic 0 1
+- 0a000 0 0 2 &mpic 1 1
+- 0a000 0 0 3 &mpic 2 1
+- 0a000 0 0 4 &mpic 3 1
++ 0xa000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0xa000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0xa000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0xa000 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x15 (Slot 3) */
+- 0a800 0 0 1 &mpic 1 1
+- 0a800 0 0 2 &mpic 2 1
+- 0a800 0 0 3 &mpic 3 1
+- 0a800 0 0 4 &mpic 0 1
++ 0xa800 0x0 0x0 0x1 &mpic 0x1 0x1
++ 0xa800 0x0 0x0 0x2 &mpic 0x2 0x1
++ 0xa800 0x0 0x0 0x3 &mpic 0x3 0x1
++ 0xa800 0x0 0x0 0x4 &mpic 0x0 0x1
+
+ /* IDSEL 0x16 (Slot 4) */
+- 0b000 0 0 1 &mpic 2 1
+- 0b000 0 0 2 &mpic 3 1
+- 0b000 0 0 3 &mpic 0 1
+- 0b000 0 0 4 &mpic 1 1
++ 0xb000 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0xb000 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0xb000 0x0 0x0 0x3 &mpic 0x0 0x1
++ 0xb000 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x18 (Slot 5) */
+- 0c000 0 0 1 &mpic 0 1
+- 0c000 0 0 2 &mpic 1 1
+- 0c000 0 0 3 &mpic 2 1
+- 0c000 0 0 4 &mpic 3 1
++ 0xc000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0xc000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0xc000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0xc000 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x1C (Tsi310 bridge PCI primary) */
+- 0E000 0 0 1 &mpic 0 1
+- 0E000 0 0 2 &mpic 1 1
+- 0E000 0 0 3 &mpic 2 1
+- 0E000 0 0 4 &mpic 3 1>;
++ 0xe000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0xe000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0xe000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0xe000 0x0 0x0 0x4 &mpic 0x3 0x1>;
+
+ interrupt-parent = <&mpic>;
+- interrupts = <18 2>;
++ interrupts = <24 2>;
+ bus-range = <0 0>;
+- ranges = <02000000 0 80000000 80000000 0 10000000
+- 01000000 0 00000000 e2000000 0 00800000>;
+- clock-frequency = <3f940aa>;
++ ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x10000000
++ 0x1000000 0x0 0x0 0xe2000000 0x0 0x800000>;
++ clock-frequency = <66666666>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e0008000 1000>;
++ reg = <0xe0008000 0x1000>;
+ compatible = "fsl,mpc8540-pcix", "fsl,mpc8540-pci";
+ device_type = "pci";
+
+ pci_bridge at 1c {
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+
+ /* IDSEL 0x00 (PrPMC Site) */
+- 0000 0 0 1 &mpic 0 1
+- 0000 0 0 2 &mpic 1 1
+- 0000 0 0 3 &mpic 2 1
+- 0000 0 0 4 &mpic 3 1
++ 0000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0000 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x04 (VIA chip) */
+- 2000 0 0 1 &mpic 0 1
+- 2000 0 0 2 &mpic 1 1
+- 2000 0 0 3 &mpic 2 1
+- 2000 0 0 4 &mpic 3 1
++ 0x2000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x2000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x2000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x2000 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x05 (8139) */
+- 2800 0 0 1 &mpic 1 1
++ 0x2800 0x0 0x0 0x1 &mpic 0x1 0x1
+
+ /* IDSEL 0x06 (Slot 6) */
+- 3000 0 0 1 &mpic 2 1
+- 3000 0 0 2 &mpic 3 1
+- 3000 0 0 3 &mpic 0 1
+- 3000 0 0 4 &mpic 1 1
++ 0x3000 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x3000 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x3000 0x0 0x0 0x3 &mpic 0x0 0x1
++ 0x3000 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDESL 0x07 (Slot 7) */
+- 3800 0 0 1 &mpic 3 1
+- 3800 0 0 2 &mpic 0 1
+- 3800 0 0 3 &mpic 1 1
+- 3800 0 0 4 &mpic 2 1>;
++ 0x3800 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x3800 0x0 0x0 0x2 &mpic 0x0 0x1
++ 0x3800 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0x3800 0x0 0x0 0x4 &mpic 0x2 0x1>;
+
+- reg = <e000 0 0 0 0>;
++ reg = <0xe000 0x0 0x0 0x0 0x0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- ranges = <02000000 0 80000000
+- 02000000 0 80000000
+- 0 20000000
+- 01000000 0 00000000
+- 01000000 0 00000000
+- 0 00080000>;
+- clock-frequency = <1fca055>;
++ ranges = <0x2000000 0x0 0x80000000
++ 0x2000000 0x0 0x80000000
++ 0x0 0x20000000
++ 0x1000000 0x0 0x0
++ 0x1000000 0x0 0x0
++ 0x0 0x80000>;
++ clock-frequency = <33333333>;
+
+ isa at 4 {
+ device_type = "isa";
+ #interrupt-cells = <2>;
+ #size-cells = <1>;
+ #address-cells = <2>;
+- reg = <2000 0 0 0 0>;
+- ranges = <1 0 01000000 0 0 00001000>;
++ reg = <0x2000 0x0 0x0 0x0 0x0>;
++ ranges = <0x1 0x0 0x1000000 0x0 0x0 0x1000>;
+ interrupt-parent = <&i8259>;
+
+ i8259: interrupt-controller at 20 {
+ interrupt-controller;
+ device_type = "interrupt-controller";
+- reg = <1 20 2
+- 1 a0 2
+- 1 4d0 2>;
++ reg = <0x1 0x20 0x2
++ 0x1 0xa0 0x2
++ 0x1 0x4d0 0x2>;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ compatible = "chrp,iic";
+@@ -362,7 +363,7 @@
+
+ rtc at 70 {
+ compatible = "pnpPNP,b00";
+- reg = <1 70 2>;
++ reg = <0x1 0x70 0x2>;
+ };
+ };
+ };
+@@ -370,64 +371,64 @@
+
+ pci1: pci at e0009000 {
+ cell-index = <1>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+
+ /* IDSEL 0x15 */
+- a800 0 0 1 &mpic b 1
+- a800 0 0 2 &mpic 1 1
+- a800 0 0 3 &mpic 2 1
+- a800 0 0 4 &mpic 3 1>;
++ 0xa800 0x0 0x0 0x1 &mpic 0xb 0x1
++ 0xa800 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0xa800 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0xa800 0x0 0x0 0x4 &mpic 0x3 0x1>;
+
+ interrupt-parent = <&mpic>;
+- interrupts = <19 2>;
++ interrupts = <25 2>;
+ bus-range = <0 0>;
+- ranges = <02000000 0 90000000 90000000 0 10000000
+- 01000000 0 00000000 e2800000 0 00800000>;
+- clock-frequency = <3f940aa>;
++ ranges = <0x2000000 0x0 0x90000000 0x90000000 0x0 0x10000000
++ 0x1000000 0x0 0x0 0xe2800000 0x0 0x800000>;
++ clock-frequency = <66666666>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e0009000 1000>;
++ reg = <0xe0009000 0x1000>;
+ compatible = "fsl,mpc8540-pci";
+ device_type = "pci";
+ };
+
+ pci2: pcie at e000a000 {
+ cell-index = <2>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+
+ /* IDSEL 0x0 (PEX) */
+- 00000 0 0 1 &mpic 0 1
+- 00000 0 0 2 &mpic 1 1
+- 00000 0 0 3 &mpic 2 1
+- 00000 0 0 4 &mpic 3 1>;
++ 00000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 00000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 00000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 00000 0x0 0x0 0x4 &mpic 0x3 0x1>;
+
+ interrupt-parent = <&mpic>;
+- interrupts = <1a 2>;
+- bus-range = <0 ff>;
+- ranges = <02000000 0 a0000000 a0000000 0 20000000
+- 01000000 0 00000000 e3000000 0 08000000>;
+- clock-frequency = <1fca055>;
++ interrupts = <26 2>;
++ bus-range = <0 255>;
++ ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xe3000000 0x0 0x8000000>;
++ clock-frequency = <33333333>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e000a000 1000>;
++ reg = <0xe000a000 0x1000>;
+ compatible = "fsl,mpc8548-pcie";
+ device_type = "pci";
+ pcie at 0 {
+- reg = <0 0 0 0 0>;
++ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+- ranges = <02000000 0 a0000000
+- 02000000 0 a0000000
+- 0 20000000
++ ranges = <0x2000000 0x0 0xa0000000
++ 0x2000000 0x0 0xa0000000
++ 0x0 0x20000000
+
+- 01000000 0 00000000
+- 01000000 0 00000000
+- 0 08000000>;
++ 0x1000000 0x0 0x0
++ 0x1000000 0x0 0x0
++ 0x0 0x8000000>;
+ };
+ };
+ };
+diff --git a/arch/powerpc/boot/dts/mpc8555cds.dts b/arch/powerpc/boot/dts/mpc8555cds.dts
+index 4538f3c..b025c56 100644
+--- a/arch/powerpc/boot/dts/mpc8555cds.dts
++++ b/arch/powerpc/boot/dts/mpc8555cds.dts
+@@ -1,7 +1,7 @@
+ /*
+ * MPC8555 CDS Device Tree Source
+ *
+- * Copyright 2006 Freescale Semiconductor Inc.
++ * Copyright 2006, 2008 Freescale Semiconductor Inc.
+ *
+ * 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
+@@ -9,6 +9,7 @@
+ * option) any later version.
+ */
+
++/dts-v1/;
+
+ / {
+ model = "MPC8555CDS";
+@@ -31,11 +32,11 @@
+
+ PowerPC,8555 at 0 {
+ device_type = "cpu";
+- reg = <0>;
+- d-cache-line-size = <20>; // 32 bytes
+- i-cache-line-size = <20>; // 32 bytes
+- d-cache-size = <8000>; // L1, 32K
+- i-cache-size = <8000>; // L1, 32K
++ reg = <0x0>;
++ d-cache-line-size = <32>; // 32 bytes
++ i-cache-line-size = <32>; // 32 bytes
++ d-cache-size = <0x8000>; // L1, 32K
++ i-cache-size = <0x8000>; // L1, 32K
+ timebase-frequency = <0>; // 33 MHz, from uboot
+ bus-frequency = <0>; // 166 MHz
+ clock-frequency = <0>; // 825 MHz, from uboot
+@@ -44,31 +45,31 @@
+
+ memory {
+ device_type = "memory";
+- reg = <00000000 08000000>; // 128M at 0x0
++ reg = <0x0 0x8000000>; // 128M at 0x0
+ };
+
+ soc8555 at e0000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+- ranges = <0 e0000000 00100000>;
+- reg = <e0000000 00001000>; // CCSRBAR 1M
++ ranges = <0x0 0xe0000000 0x100000>;
++ reg = <0xe0000000 0x1000>; // CCSRBAR 1M
+ bus-frequency = <0>;
+
+ memory-controller at 2000 {
+ compatible = "fsl,8555-memory-controller";
+- reg = <2000 1000>;
++ reg = <0x2000 0x1000>;
+ interrupt-parent = <&mpic>;
+- interrupts = <12 2>;
++ interrupts = <18 2>;
+ };
+
+ l2-cache-controller at 20000 {
+ compatible = "fsl,8555-l2-cache-controller";
+- reg = <20000 1000>;
+- cache-line-size = <20>; // 32 bytes
+- cache-size = <40000>; // L2, 256K
++ reg = <0x20000 0x1000>;
++ cache-line-size = <32>; // 32 bytes
++ cache-size = <0x40000>; // L2, 256K
+ interrupt-parent = <&mpic>;
+- interrupts = <10 2>;
++ interrupts = <16 2>;
+ };
+
+ i2c at 3000 {
+@@ -76,8 +77,8 @@
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+- reg = <3000 100>;
+- interrupts = <2b 2>;
++ reg = <0x3000 0x100>;
++ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+@@ -86,18 +87,18 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,gianfar-mdio";
+- reg = <24520 20>;
++ reg = <0x24520 0x20>;
+
+ phy0: ethernet-phy at 0 {
+ interrupt-parent = <&mpic>;
+ interrupts = <5 1>;
+- reg = <0>;
++ reg = <0x0>;
+ device_type = "ethernet-phy";
+ };
+ phy1: ethernet-phy at 1 {
+ interrupt-parent = <&mpic>;
+ interrupts = <5 1>;
+- reg = <1>;
++ reg = <0x1>;
+ device_type = "ethernet-phy";
+ };
+ };
+@@ -107,9 +108,9 @@
+ device_type = "network";
+ model = "TSEC";
+ compatible = "gianfar";
+- reg = <24000 1000>;
++ reg = <0x24000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <1d 2 1e 2 22 2>;
++ interrupts = <29 2 30 2 34 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy0>;
+ };
+@@ -119,9 +120,9 @@
+ device_type = "network";
+ model = "TSEC";
+ compatible = "gianfar";
+- reg = <25000 1000>;
++ reg = <0x25000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <23 2 24 2 28 2>;
++ interrupts = <35 2 36 2 40 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy1>;
+ };
+@@ -130,9 +131,9 @@
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <4500 100>; // reg base, size
++ reg = <0x4500 0x100>; // reg base, size
+ clock-frequency = <0>; // should we fill in in uboot?
+- interrupts = <2a 2>;
++ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+@@ -140,9 +141,9 @@
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <4600 100>; // reg base, size
++ reg = <0x4600 0x100>; // reg base, size
+ clock-frequency = <0>; // should we fill in in uboot?
+- interrupts = <2a 2>;
++ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+@@ -151,7 +152,7 @@
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+- reg = <40000 40000>;
++ reg = <0x40000 0x40000>;
+ compatible = "chrp,open-pic";
+ device_type = "open-pic";
+ big-endian;
+@@ -161,17 +162,17 @@
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8555-cpm", "fsl,cpm2";
+- reg = <919c0 30>;
++ reg = <0x919c0 0x30>;
+ ranges;
+
+ muram at 80000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+- ranges = <0 80000 10000>;
++ ranges = <0x0 0x80000 0x10000>;
+
+ data at 0 {
+ compatible = "fsl,cpm-muram-data";
+- reg = <0 2000 9000 1000>;
++ reg = <0x0 0x2000 0x9000 0x1000>;
+ };
+ };
+
+@@ -179,16 +180,16 @@
+ compatible = "fsl,mpc8555-brg",
+ "fsl,cpm2-brg",
+ "fsl,cpm-brg";
+- reg = <919f0 10 915f0 10>;
++ reg = <0x919f0 0x10 0x915f0 0x10>;
+ };
+
+ cpmpic: pic at 90c00 {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+- interrupts = <2e 2>;
++ interrupts = <46 2>;
+ interrupt-parent = <&mpic>;
+- reg = <90c00 80>;
++ reg = <0x90c00 0x80>;
+ compatible = "fsl,mpc8555-cpm-pic", "fsl,cpm2-pic";
+ };
+ };
+@@ -196,68 +197,68 @@
+
+ pci0: pci at e0008000 {
+ cell-index = <0>;
+- interrupt-map-mask = <1f800 0 0 7>;
++ interrupt-map-mask = <0x1f800 0x0 0x0 0x7>;
+ interrupt-map = <
+
+ /* IDSEL 0x10 */
+- 08000 0 0 1 &mpic 0 1
+- 08000 0 0 2 &mpic 1 1
+- 08000 0 0 3 &mpic 2 1
+- 08000 0 0 4 &mpic 3 1
++ 0x8000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x8000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x8000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x8000 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x11 */
+- 08800 0 0 1 &mpic 0 1
+- 08800 0 0 2 &mpic 1 1
+- 08800 0 0 3 &mpic 2 1
+- 08800 0 0 4 &mpic 3 1
++ 0x8800 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x8800 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x8800 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x8800 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x12 (Slot 1) */
+- 09000 0 0 1 &mpic 0 1
+- 09000 0 0 2 &mpic 1 1
+- 09000 0 0 3 &mpic 2 1
+- 09000 0 0 4 &mpic 3 1
++ 0x9000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x9000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x9000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x9000 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x13 (Slot 2) */
+- 09800 0 0 1 &mpic 1 1
+- 09800 0 0 2 &mpic 2 1
+- 09800 0 0 3 &mpic 3 1
+- 09800 0 0 4 &mpic 0 1
++ 0x9800 0x0 0x0 0x1 &mpic 0x1 0x1
++ 0x9800 0x0 0x0 0x2 &mpic 0x2 0x1
++ 0x9800 0x0 0x0 0x3 &mpic 0x3 0x1
++ 0x9800 0x0 0x0 0x4 &mpic 0x0 0x1
+
+ /* IDSEL 0x14 (Slot 3) */
+- 0a000 0 0 1 &mpic 2 1
+- 0a000 0 0 2 &mpic 3 1
+- 0a000 0 0 3 &mpic 0 1
+- 0a000 0 0 4 &mpic 1 1
++ 0xa000 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0xa000 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0xa000 0x0 0x0 0x3 &mpic 0x0 0x1
++ 0xa000 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x15 (Slot 4) */
+- 0a800 0 0 1 &mpic 3 1
+- 0a800 0 0 2 &mpic 0 1
+- 0a800 0 0 3 &mpic 1 1
+- 0a800 0 0 4 &mpic 2 1
++ 0xa800 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0xa800 0x0 0x0 0x2 &mpic 0x0 0x1
++ 0xa800 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0xa800 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ /* Bus 1 (Tundra Bridge) */
+ /* IDSEL 0x12 (ISA bridge) */
+- 19000 0 0 1 &mpic 0 1
+- 19000 0 0 2 &mpic 1 1
+- 19000 0 0 3 &mpic 2 1
+- 19000 0 0 4 &mpic 3 1>;
++ 0x19000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0x19000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x19000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x19000 0x0 0x0 0x4 &mpic 0x3 0x1>;
+ interrupt-parent = <&mpic>;
+- interrupts = <18 2>;
++ interrupts = <24 2>;
+ bus-range = <0 0>;
+- ranges = <02000000 0 80000000 80000000 0 20000000
+- 01000000 0 00000000 e2000000 0 00100000>;
+- clock-frequency = <3f940aa>;
++ ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xe2000000 0x0 0x100000>;
++ clock-frequency = <66666666>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e0008000 1000>;
++ reg = <0xe0008000 0x1000>;
+ compatible = "fsl,mpc8540-pci";
+ device_type = "pci";
+
+ i8259 at 19000 {
+ interrupt-controller;
+ device_type = "interrupt-controller";
+- reg = <19000 0 0 0 1>;
++ reg = <0x19000 0x0 0x0 0x0 0x1>;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ compatible = "chrp,iic";
+@@ -268,24 +269,24 @@
+
+ pci1: pci at e0009000 {
+ cell-index = <1>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+
+ /* IDSEL 0x15 */
+- a800 0 0 1 &mpic b 1
+- a800 0 0 2 &mpic b 1
+- a800 0 0 3 &mpic b 1
+- a800 0 0 4 &mpic b 1>;
++ 0xa800 0x0 0x0 0x1 &mpic 0xb 0x1
++ 0xa800 0x0 0x0 0x2 &mpic 0xb 0x1
++ 0xa800 0x0 0x0 0x3 &mpic 0xb 0x1
++ 0xa800 0x0 0x0 0x4 &mpic 0xb 0x1>;
+ interrupt-parent = <&mpic>;
+- interrupts = <19 2>;
++ interrupts = <25 2>;
+ bus-range = <0 0>;
+- ranges = <02000000 0 a0000000 a0000000 0 20000000
+- 01000000 0 00000000 e3000000 0 00100000>;
+- clock-frequency = <3f940aa>;
++ ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xe3000000 0x0 0x100000>;
++ clock-frequency = <66666666>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e0009000 1000>;
++ reg = <0xe0009000 0x1000>;
+ compatible = "fsl,mpc8540-pci";
+ device_type = "pci";
+ };
+diff --git a/arch/powerpc/boot/dts/mpc8560ads.dts b/arch/powerpc/boot/dts/mpc8560ads.dts
+index 639ce8a..0cc16ab 100644
+--- a/arch/powerpc/boot/dts/mpc8560ads.dts
++++ b/arch/powerpc/boot/dts/mpc8560ads.dts
+@@ -1,7 +1,7 @@
+ /*
+ * MPC8560 ADS Device Tree Source
+ *
+- * Copyright 2006 Freescale Semiconductor Inc.
++ * Copyright 2006, 2008 Freescale Semiconductor Inc.
+ *
+ * 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
+@@ -9,6 +9,7 @@
+ * option) any later version.
+ */
+
++/dts-v1/;
+
+ / {
+ model = "MPC8560ADS";
+@@ -32,74 +33,74 @@
+
+ PowerPC,8560 at 0 {
+ device_type = "cpu";
+- reg = <0>;
+- d-cache-line-size = <20>; // 32 bytes
+- i-cache-line-size = <20>; // 32 bytes
+- d-cache-size = <8000>; // L1, 32K
+- i-cache-size = <8000>; // L1, 32K
+- timebase-frequency = <04ead9a0>;
+- bus-frequency = <13ab6680>;
+- clock-frequency = <312c8040>;
++ reg = <0x0>;
++ d-cache-line-size = <32>; // 32 bytes
++ i-cache-line-size = <32>; // 32 bytes
++ d-cache-size = <0x8000>; // L1, 32K
++ i-cache-size = <0x8000>; // L1, 32K
++ timebase-frequency = <82500000>;
++ bus-frequency = <330000000>;
++ clock-frequency = <825000000>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+- reg = <00000000 10000000>;
++ reg = <0x0 0x10000000>;
+ };
+
+ soc8560 at e0000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+- ranges = <0 e0000000 00100000>;
+- reg = <e0000000 00000200>;
+- bus-frequency = <13ab6680>;
++ ranges = <0x0 0xe0000000 0x100000>;
++ reg = <0xe0000000 0x200>;
++ bus-frequency = <330000000>;
+
+ memory-controller at 2000 {
+ compatible = "fsl,8540-memory-controller";
+- reg = <2000 1000>;
++ reg = <0x2000 0x1000>;
+ interrupt-parent = <&mpic>;
+- interrupts = <12 2>;
++ interrupts = <18 2>;
+ };
+
+ l2-cache-controller at 20000 {
+ compatible = "fsl,8540-l2-cache-controller";
+- reg = <20000 1000>;
+- cache-line-size = <20>; // 32 bytes
+- cache-size = <40000>; // L2, 256K
++ reg = <0x20000 0x1000>;
++ cache-line-size = <32>; // 32 bytes
++ cache-size = <0x40000>; // L2, 256K
+ interrupt-parent = <&mpic>;
+- interrupts = <10 2>;
++ interrupts = <16 2>;
+ };
+
+ mdio at 24520 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,gianfar-mdio";
+- reg = <24520 20>;
++ reg = <0x24520 0x20>;
+
+ phy0: ethernet-phy at 0 {
+ interrupt-parent = <&mpic>;
+ interrupts = <5 1>;
+- reg = <0>;
++ reg = <0x0>;
+ device_type = "ethernet-phy";
+ };
+ phy1: ethernet-phy at 1 {
+ interrupt-parent = <&mpic>;
+ interrupts = <5 1>;
+- reg = <1>;
++ reg = <0x1>;
+ device_type = "ethernet-phy";
+ };
+ phy2: ethernet-phy at 2 {
+ interrupt-parent = <&mpic>;
+ interrupts = <7 1>;
+- reg = <2>;
++ reg = <0x2>;
+ device_type = "ethernet-phy";
+ };
+ phy3: ethernet-phy at 3 {
+ interrupt-parent = <&mpic>;
+ interrupts = <7 1>;
+- reg = <3>;
++ reg = <0x3>;
+ device_type = "ethernet-phy";
+ };
+ };
+@@ -109,9 +110,9 @@
+ device_type = "network";
+ model = "TSEC";
+ compatible = "gianfar";
+- reg = <24000 1000>;
++ reg = <0x24000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <1d 2 1e 2 22 2>;
++ interrupts = <29 2 30 2 34 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy0>;
+ };
+@@ -121,9 +122,9 @@
+ device_type = "network";
+ model = "TSEC";
+ compatible = "gianfar";
+- reg = <25000 1000>;
++ reg = <0x25000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <23 2 24 2 28 2>;
++ interrupts = <35 2 36 2 40 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy1>;
+ };
+@@ -132,7 +133,7 @@
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+- reg = <40000 40000>;
++ reg = <0x40000 0x40000>;
+ device_type = "open-pic";
+ };
+
+@@ -140,17 +141,17 @@
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8560-cpm", "fsl,cpm2";
+- reg = <919c0 30>;
++ reg = <0x919c0 0x30>;
+ ranges;
+
+ muram at 80000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+- ranges = <0 80000 10000>;
++ ranges = <0x0 0x80000 0x10000>;
+
+ data at 0 {
+ compatible = "fsl,cpm-muram-data";
+- reg = <0 4000 9000 2000>;
++ reg = <0x0 0x4000 0x9000 0x2000>;
+ };
+ };
+
+@@ -158,17 +159,17 @@
+ compatible = "fsl,mpc8560-brg",
+ "fsl,cpm2-brg",
+ "fsl,cpm-brg";
+- reg = <919f0 10 915f0 10>;
+- clock-frequency = <d#165000000>;
++ reg = <0x919f0 0x10 0x915f0 0x10>;
++ clock-frequency = <165000000>;
+ };
+
+ cpmpic: pic at 90c00 {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+- interrupts = <2e 2>;
++ interrupts = <46 2>;
+ interrupt-parent = <&mpic>;
+- reg = <90c00 80>;
++ reg = <0x90c00 0x80>;
+ compatible = "fsl,mpc8560-cpm-pic", "fsl,cpm2-pic";
+ };
+
+@@ -176,11 +177,11 @@
+ device_type = "serial";
+ compatible = "fsl,mpc8560-scc-uart",
+ "fsl,cpm2-scc-uart";
+- reg = <91a00 20 88000 100>;
++ reg = <0x91a00 0x20 0x88000 0x100>;
+ fsl,cpm-brg = <1>;
+- fsl,cpm-command = <00800000>;
+- current-speed = <1c200>;
+- interrupts = <28 8>;
++ fsl,cpm-command = <0x800000>;
++ current-speed = <115200>;
++ interrupts = <40 8>;
+ interrupt-parent = <&cpmpic>;
+ };
+
+@@ -188,11 +189,11 @@
+ device_type = "serial";
+ compatible = "fsl,mpc8560-scc-uart",
+ "fsl,cpm2-scc-uart";
+- reg = <91a20 20 88100 100>;
++ reg = <0x91a20 0x20 0x88100 0x100>;
+ fsl,cpm-brg = <2>;
+- fsl,cpm-command = <04a00000>;
+- current-speed = <1c200>;
+- interrupts = <29 8>;
++ fsl,cpm-command = <0x4a00000>;
++ current-speed = <115200>;
++ interrupts = <41 8>;
+ interrupt-parent = <&cpmpic>;
+ };
+
+@@ -200,10 +201,10 @@
+ device_type = "network";
+ compatible = "fsl,mpc8560-fcc-enet",
+ "fsl,cpm2-fcc-enet";
+- reg = <91320 20 88500 100 913b0 1>;
++ reg = <0x91320 0x20 0x88500 0x100 0x913b0 0x1>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- fsl,cpm-command = <16200300>;
+- interrupts = <21 8>;
++ fsl,cpm-command = <0x16200300>;
++ interrupts = <33 8>;
+ interrupt-parent = <&cpmpic>;
+ phy-handle = <&phy2>;
+ };
+@@ -212,10 +213,10 @@
+ device_type = "network";
+ compatible = "fsl,mpc8560-fcc-enet",
+ "fsl,cpm2-fcc-enet";
+- reg = <91340 20 88600 100 913d0 1>;
++ reg = <0x91340 0x20 0x88600 0x100 0x913d0 0x1>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- fsl,cpm-command = <1a400300>;
+- interrupts = <22 8>;
++ fsl,cpm-command = <0x1a400300>;
++ interrupts = <34 8>;
+ interrupt-parent = <&cpmpic>;
+ phy-handle = <&phy3>;
+ };
+@@ -229,87 +230,87 @@
+ #address-cells = <3>;
+ compatible = "fsl,mpc8540-pcix", "fsl,mpc8540-pci";
+ device_type = "pci";
+- reg = <e0008000 1000>;
+- clock-frequency = <3f940aa>;
+- interrupt-map-mask = <f800 0 0 7>;
++ reg = <0xe0008000 0x1000>;
++ clock-frequency = <66666666>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+
+ /* IDSEL 0x2 */
+- 1000 0 0 1 &mpic 1 1
+- 1000 0 0 2 &mpic 2 1
+- 1000 0 0 3 &mpic 3 1
+- 1000 0 0 4 &mpic 4 1
++ 0x1000 0x0 0x0 0x1 &mpic 0x1 0x1
++ 0x1000 0x0 0x0 0x2 &mpic 0x2 0x1
++ 0x1000 0x0 0x0 0x3 &mpic 0x3 0x1
++ 0x1000 0x0 0x0 0x4 &mpic 0x4 0x1
+
+ /* IDSEL 0x3 */
+- 1800 0 0 1 &mpic 4 1
+- 1800 0 0 2 &mpic 1 1
+- 1800 0 0 3 &mpic 2 1
+- 1800 0 0 4 &mpic 3 1
++ 0x1800 0x0 0x0 0x1 &mpic 0x4 0x1
++ 0x1800 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x1800 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x1800 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 0x4 */
+- 2000 0 0 1 &mpic 3 1
+- 2000 0 0 2 &mpic 4 1
+- 2000 0 0 3 &mpic 1 1
+- 2000 0 0 4 &mpic 2 1
++ 0x2000 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x2000 0x0 0x0 0x2 &mpic 0x4 0x1
++ 0x2000 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0x2000 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ /* IDSEL 0x5 */
+- 2800 0 0 1 &mpic 2 1
+- 2800 0 0 2 &mpic 3 1
+- 2800 0 0 3 &mpic 4 1
+- 2800 0 0 4 &mpic 1 1
++ 0x2800 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x2800 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x2800 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0x2800 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 12 */
+- 6000 0 0 1 &mpic 1 1
+- 6000 0 0 2 &mpic 2 1
+- 6000 0 0 3 &mpic 3 1
+- 6000 0 0 4 &mpic 4 1
++ 0x6000 0x0 0x0 0x1 &mpic 0x1 0x1
++ 0x6000 0x0 0x0 0x2 &mpic 0x2 0x1
++ 0x6000 0x0 0x0 0x3 &mpic 0x3 0x1
++ 0x6000 0x0 0x0 0x4 &mpic 0x4 0x1
+
+ /* IDSEL 13 */
+- 6800 0 0 1 &mpic 4 1
+- 6800 0 0 2 &mpic 1 1
+- 6800 0 0 3 &mpic 2 1
+- 6800 0 0 4 &mpic 3 1
++ 0x6800 0x0 0x0 0x1 &mpic 0x4 0x1
++ 0x6800 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x6800 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x6800 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 14*/
+- 7000 0 0 1 &mpic 3 1
+- 7000 0 0 2 &mpic 4 1
+- 7000 0 0 3 &mpic 1 1
+- 7000 0 0 4 &mpic 2 1
++ 0x7000 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x7000 0x0 0x0 0x2 &mpic 0x4 0x1
++ 0x7000 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0x7000 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ /* IDSEL 15 */
+- 7800 0 0 1 &mpic 2 1
+- 7800 0 0 2 &mpic 3 1
+- 7800 0 0 3 &mpic 4 1
+- 7800 0 0 4 &mpic 1 1
++ 0x7800 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x7800 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x7800 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0x7800 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 18 */
+- 9000 0 0 1 &mpic 1 1
+- 9000 0 0 2 &mpic 2 1
+- 9000 0 0 3 &mpic 3 1
+- 9000 0 0 4 &mpic 4 1
++ 0x9000 0x0 0x0 0x1 &mpic 0x1 0x1
++ 0x9000 0x0 0x0 0x2 &mpic 0x2 0x1
++ 0x9000 0x0 0x0 0x3 &mpic 0x3 0x1
++ 0x9000 0x0 0x0 0x4 &mpic 0x4 0x1
+
+ /* IDSEL 19 */
+- 9800 0 0 1 &mpic 4 1
+- 9800 0 0 2 &mpic 1 1
+- 9800 0 0 3 &mpic 2 1
+- 9800 0 0 4 &mpic 3 1
++ 0x9800 0x0 0x0 0x1 &mpic 0x4 0x1
++ 0x9800 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0x9800 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0x9800 0x0 0x0 0x4 &mpic 0x3 0x1
+
+ /* IDSEL 20 */
+- a000 0 0 1 &mpic 3 1
+- a000 0 0 2 &mpic 4 1
+- a000 0 0 3 &mpic 1 1
+- a000 0 0 4 &mpic 2 1
++ 0xa000 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0xa000 0x0 0x0 0x2 &mpic 0x4 0x1
++ 0xa000 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0xa000 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ /* IDSEL 21 */
+- a800 0 0 1 &mpic 2 1
+- a800 0 0 2 &mpic 3 1
+- a800 0 0 3 &mpic 4 1
+- a800 0 0 4 &mpic 1 1>;
++ 0xa800 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0xa800 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0xa800 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0xa800 0x0 0x0 0x4 &mpic 0x1 0x1>;
+
+ interrupt-parent = <&mpic>;
+- interrupts = <18 2>;
++ interrupts = <24 2>;
+ bus-range = <0 0>;
+- ranges = <02000000 0 80000000 80000000 0 20000000
+- 01000000 0 00000000 e2000000 0 01000000>;
++ ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xe2000000 0x0 0x1000000>;
+ };
+ };
+diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts
+index 97bc048..a025a8e 100644
+--- a/arch/powerpc/boot/dts/mpc8568mds.dts
++++ b/arch/powerpc/boot/dts/mpc8568mds.dts
+@@ -1,7 +1,7 @@
+ /*
+ * MPC8568E MDS Device Tree Source
+ *
+- * Copyright 2007 Freescale Semiconductor Inc.
++ * Copyright 2007, 2008 Freescale Semiconductor Inc.
+ *
+ * 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
+@@ -9,10 +9,7 @@
+ * option) any later version.
+ */
+
+-
+-/*
+-/memreserve/ 00000000 1000000;
+-*/
++/dts-v1/;
+
+ / {
+ model = "MPC8568EMDS";
+@@ -37,11 +34,11 @@
+
+ PowerPC,8568 at 0 {
+ device_type = "cpu";
+- reg = <0>;
+- d-cache-line-size = <20>; // 32 bytes
+- i-cache-line-size = <20>; // 32 bytes
+- d-cache-size = <8000>; // L1, 32K
+- i-cache-size = <8000>; // L1, 32K
++ reg = <0x0>;
++ d-cache-line-size = <32>; // 32 bytes
++ i-cache-line-size = <32>; // 32 bytes
++ d-cache-size = <0x8000>; // L1, 32K
++ i-cache-size = <0x8000>; // L1, 32K
+ timebase-frequency = <0>;
+ bus-frequency = <0>;
+ clock-frequency = <0>;
+@@ -50,36 +47,36 @@
+
+ memory {
+ device_type = "memory";
+- reg = <00000000 10000000>;
++ reg = <0x0 0x10000000>;
+ };
+
+ bcsr at f8000000 {
+ device_type = "board-control";
+- reg = <f8000000 8000>;
++ reg = <0xf8000000 0x8000>;
+ };
+
+ soc8568 at e0000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+- ranges = <0 e0000000 00100000>;
+- reg = <e0000000 00001000>;
++ ranges = <0x0 0xe0000000 0x100000>;
++ reg = <0xe0000000 0x1000>;
+ bus-frequency = <0>;
+
+ memory-controller at 2000 {
+ compatible = "fsl,8568-memory-controller";
+- reg = <2000 1000>;
++ reg = <0x2000 0x1000>;
+ interrupt-parent = <&mpic>;
+- interrupts = <12 2>;
++ interrupts = <18 2>;
+ };
+
+ l2-cache-controller at 20000 {
+ compatible = "fsl,8568-l2-cache-controller";
+- reg = <20000 1000>;
+- cache-line-size = <20>; // 32 bytes
+- cache-size = <80000>; // L2, 512K
++ reg = <0x20000 0x1000>;
++ cache-line-size = <32>; // 32 bytes
++ cache-size = <0x80000>; // L2, 512K
+ interrupt-parent = <&mpic>;
+- interrupts = <10 2>;
++ interrupts = <16 2>;
+ };
+
+ i2c at 3000 {
+@@ -87,14 +84,14 @@
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+- reg = <3000 100>;
+- interrupts = <2b 2>;
++ reg = <0x3000 0x100>;
++ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+
+ rtc at 68 {
+ compatible = "dallas,ds1374";
+- reg = <68>;
++ reg = <0x68>;
+ };
+ };
+
+@@ -103,8 +100,8 @@
+ #size-cells = <0>;
+ cell-index = <1>;
+ compatible = "fsl-i2c";
+- reg = <3100 100>;
+- interrupts = <2b 2>;
++ reg = <0x3100 0x100>;
++ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+@@ -113,30 +110,30 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,gianfar-mdio";
+- reg = <24520 20>;
++ reg = <0x24520 0x20>;
+
+ phy0: ethernet-phy at 7 {
+ interrupt-parent = <&mpic>;
+ interrupts = <1 1>;
+- reg = <7>;
++ reg = <0x7>;
+ device_type = "ethernet-phy";
+ };
+ phy1: ethernet-phy at 1 {
+ interrupt-parent = <&mpic>;
+ interrupts = <2 1>;
+- reg = <1>;
++ reg = <0x1>;
+ device_type = "ethernet-phy";
+ };
+ phy2: ethernet-phy at 2 {
+ interrupt-parent = <&mpic>;
+ interrupts = <1 1>;
+- reg = <2>;
++ reg = <0x2>;
+ device_type = "ethernet-phy";
+ };
+ phy3: ethernet-phy at 3 {
+ interrupt-parent = <&mpic>;
+ interrupts = <2 1>;
+- reg = <3>;
++ reg = <0x3>;
+ device_type = "ethernet-phy";
+ };
+ };
+@@ -146,9 +143,9 @@
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "gianfar";
+- reg = <24000 1000>;
++ reg = <0x24000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <1d 2 1e 2 22 2>;
++ interrupts = <29 2 30 2 34 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy2>;
+ };
+@@ -158,9 +155,9 @@
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "gianfar";
+- reg = <25000 1000>;
++ reg = <0x25000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <23 2 24 2 28 2>;
++ interrupts = <35 2 36 2 40 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy3>;
+ };
+@@ -169,15 +166,15 @@
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <4500 100>;
++ reg = <0x4500 0x100>;
+ clock-frequency = <0>;
+- interrupts = <2a 2>;
++ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ global-utilities at e0000 { //global utilities block
+ compatible = "fsl,mpc8548-guts";
+- reg = <e0000 1000>;
++ reg = <0xe0000 0x1000>;
+ fsl,has-rstcr;
+ };
+
+@@ -185,9 +182,9 @@
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <4600 100>;
++ reg = <0x4600 0x100>;
+ clock-frequency = <0>;
+- interrupts = <2a 2>;
++ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+@@ -195,13 +192,13 @@
+ device_type = "crypto";
+ model = "SEC2";
+ compatible = "talitos";
+- reg = <30000 f000>;
+- interrupts = <2d 2>;
++ reg = <0x30000 0xf000>;
++ interrupts = <45 2>;
+ interrupt-parent = <&mpic>;
+ num-channels = <4>;
+- channel-fifo-len = <18>;
+- exec-units-mask = <000000fe>;
+- descriptor-types-mask = <012b0ebf>;
++ channel-fifo-len = <24>;
++ exec-units-mask = <0xfe>;
++ descriptor-types-mask = <0x12b0ebf>;
+ };
+
+ mpic: pic at 40000 {
+@@ -209,73 +206,73 @@
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+- reg = <40000 40000>;
++ reg = <0x40000 0x40000>;
+ compatible = "chrp,open-pic";
+ device_type = "open-pic";
+ big-endian;
+ };
+
+ par_io at e0100 {
+- reg = <e0100 100>;
++ reg = <0xe0100 0x100>;
+ device_type = "par_io";
+ num-ports = <7>;
+
+ pio1: ucc_pin at 01 {
+ pio-map = <
+ /* port pin dir open_drain assignment has_irq */
+- 4 0a 1 0 2 0 /* TxD0 */
+- 4 09 1 0 2 0 /* TxD1 */
+- 4 08 1 0 2 0 /* TxD2 */
+- 4 07 1 0 2 0 /* TxD3 */
+- 4 17 1 0 2 0 /* TxD4 */
+- 4 16 1 0 2 0 /* TxD5 */
+- 4 15 1 0 2 0 /* TxD6 */
+- 4 14 1 0 2 0 /* TxD7 */
+- 4 0f 2 0 2 0 /* RxD0 */
+- 4 0e 2 0 2 0 /* RxD1 */
+- 4 0d 2 0 2 0 /* RxD2 */
+- 4 0c 2 0 2 0 /* RxD3 */
+- 4 1d 2 0 2 0 /* RxD4 */
+- 4 1c 2 0 2 0 /* RxD5 */
+- 4 1b 2 0 2 0 /* RxD6 */
+- 4 1a 2 0 2 0 /* RxD7 */
+- 4 0b 1 0 2 0 /* TX_EN */
+- 4 18 1 0 2 0 /* TX_ER */
+- 4 10 2 0 2 0 /* RX_DV */
+- 4 1e 2 0 2 0 /* RX_ER */
+- 4 11 2 0 2 0 /* RX_CLK */
+- 4 13 1 0 2 0 /* GTX_CLK */
+- 1 1f 2 0 3 0>; /* GTX125 */
++ 0x4 0xa 0x1 0x0 0x2 0x0 /* TxD0 */
++ 0x4 0x9 0x1 0x0 0x2 0x0 /* TxD1 */
++ 0x4 0x8 0x1 0x0 0x2 0x0 /* TxD2 */
++ 0x4 0x7 0x1 0x0 0x2 0x0 /* TxD3 */
++ 0x4 0x17 0x1 0x0 0x2 0x0 /* TxD4 */
++ 0x4 0x16 0x1 0x0 0x2 0x0 /* TxD5 */
++ 0x4 0x15 0x1 0x0 0x2 0x0 /* TxD6 */
++ 0x4 0x14 0x1 0x0 0x2 0x0 /* TxD7 */
++ 0x4 0xf 0x2 0x0 0x2 0x0 /* RxD0 */
++ 0x4 0xe 0x2 0x0 0x2 0x0 /* RxD1 */
++ 0x4 0xd 0x2 0x0 0x2 0x0 /* RxD2 */
++ 0x4 0xc 0x2 0x0 0x2 0x0 /* RxD3 */
++ 0x4 0x1d 0x2 0x0 0x2 0x0 /* RxD4 */
++ 0x4 0x1c 0x2 0x0 0x2 0x0 /* RxD5 */
++ 0x4 0x1b 0x2 0x0 0x2 0x0 /* RxD6 */
++ 0x4 0x1a 0x2 0x0 0x2 0x0 /* RxD7 */
++ 0x4 0xb 0x1 0x0 0x2 0x0 /* TX_EN */
++ 0x4 0x18 0x1 0x0 0x2 0x0 /* TX_ER */
++ 0x4 0x10 0x2 0x0 0x2 0x0 /* RX_DV */
++ 0x4 0x1e 0x2 0x0 0x2 0x0 /* RX_ER */
++ 0x4 0x11 0x2 0x0 0x2 0x0 /* RX_CLK */
++ 0x4 0x13 0x1 0x0 0x2 0x0 /* GTX_CLK */
++ 0x1 0x1f 0x2 0x0 0x3 0x0>; /* GTX125 */
+ };
+
+ pio2: ucc_pin at 02 {
+ pio-map = <
+ /* port pin dir open_drain assignment has_irq */
+- 5 0a 1 0 2 0 /* TxD0 */
+- 5 09 1 0 2 0 /* TxD1 */
+- 5 08 1 0 2 0 /* TxD2 */
+- 5 07 1 0 2 0 /* TxD3 */
+- 5 17 1 0 2 0 /* TxD4 */
+- 5 16 1 0 2 0 /* TxD5 */
+- 5 15 1 0 2 0 /* TxD6 */
+- 5 14 1 0 2 0 /* TxD7 */
+- 5 0f 2 0 2 0 /* RxD0 */
+- 5 0e 2 0 2 0 /* RxD1 */
+- 5 0d 2 0 2 0 /* RxD2 */
+- 5 0c 2 0 2 0 /* RxD3 */
+- 5 1d 2 0 2 0 /* RxD4 */
+- 5 1c 2 0 2 0 /* RxD5 */
+- 5 1b 2 0 2 0 /* RxD6 */
+- 5 1a 2 0 2 0 /* RxD7 */
+- 5 0b 1 0 2 0 /* TX_EN */
+- 5 18 1 0 2 0 /* TX_ER */
+- 5 10 2 0 2 0 /* RX_DV */
+- 5 1e 2 0 2 0 /* RX_ER */
+- 5 11 2 0 2 0 /* RX_CLK */
+- 5 13 1 0 2 0 /* GTX_CLK */
+- 1 1f 2 0 3 0 /* GTX125 */
+- 4 06 3 0 2 0 /* MDIO */
+- 4 05 1 0 2 0>; /* MDC */
++ 0x5 0xa 0x1 0x0 0x2 0x0 /* TxD0 */
++ 0x5 0x9 0x1 0x0 0x2 0x0 /* TxD1 */
++ 0x5 0x8 0x1 0x0 0x2 0x0 /* TxD2 */
++ 0x5 0x7 0x1 0x0 0x2 0x0 /* TxD3 */
++ 0x5 0x17 0x1 0x0 0x2 0x0 /* TxD4 */
++ 0x5 0x16 0x1 0x0 0x2 0x0 /* TxD5 */
++ 0x5 0x15 0x1 0x0 0x2 0x0 /* TxD6 */
++ 0x5 0x14 0x1 0x0 0x2 0x0 /* TxD7 */
++ 0x5 0xf 0x2 0x0 0x2 0x0 /* RxD0 */
++ 0x5 0xe 0x2 0x0 0x2 0x0 /* RxD1 */
++ 0x5 0xd 0x2 0x0 0x2 0x0 /* RxD2 */
++ 0x5 0xc 0x2 0x0 0x2 0x0 /* RxD3 */
++ 0x5 0x1d 0x2 0x0 0x2 0x0 /* RxD4 */
++ 0x5 0x1c 0x2 0x0 0x2 0x0 /* RxD5 */
++ 0x5 0x1b 0x2 0x0 0x2 0x0 /* RxD6 */
++ 0x5 0x1a 0x2 0x0 0x2 0x0 /* RxD7 */
++ 0x5 0xb 0x1 0x0 0x2 0x0 /* TX_EN */
++ 0x5 0x18 0x1 0x0 0x2 0x0 /* TX_ER */
++ 0x5 0x10 0x2 0x0 0x2 0x0 /* RX_DV */
++ 0x5 0x1e 0x2 0x0 0x2 0x0 /* RX_ER */
++ 0x5 0x11 0x2 0x0 0x2 0x0 /* RX_CLK */
++ 0x5 0x13 0x1 0x0 0x2 0x0 /* GTX_CLK */
++ 0x1 0x1f 0x2 0x0 0x3 0x0 /* GTX125 */
++ 0x4 0x6 0x3 0x0 0x2 0x0 /* MDIO */
++ 0x4 0x5 0x1 0x0 0x2 0x0>; /* MDC */
+ };
+ };
+ };
+@@ -285,28 +282,28 @@
+ #size-cells = <1>;
+ device_type = "qe";
+ compatible = "fsl,qe";
+- ranges = <0 e0080000 00040000>;
+- reg = <e0080000 480>;
++ ranges = <0x0 0xe0080000 0x40000>;
++ reg = <0xe0080000 0x480>;
+ brg-frequency = <0>;
+- bus-frequency = <179A7B00>;
++ bus-frequency = <396000000>;
+
+ muram at 10000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,qe-muram", "fsl,cpm-muram";
+- ranges = <0 00010000 0000c000>;
++ ranges = <0x0 0x10000 0x10000>;
+
+ data-only at 0 {
+ compatible = "fsl,qe-muram-data",
+ "fsl,cpm-muram-data";
+- reg = <0 c000>;
++ reg = <0x0 0x10000>;
+ };
+ };
+
+ spi at 4c0 {
+ cell-index = <0>;
+ compatible = "fsl,spi";
+- reg = <4c0 40>;
++ reg = <0x4c0 0x40>;
+ interrupts = <2>;
+ interrupt-parent = <&qeic>;
+ mode = "cpu";
+@@ -315,7 +312,7 @@
+ spi at 500 {
+ cell-index = <1>;
+ compatible = "fsl,spi";
+- reg = <500 40>;
++ reg = <0x500 0x40>;
+ interrupts = <1>;
+ interrupt-parent = <&qeic>;
+ mode = "cpu";
+@@ -324,11 +321,9 @@
+ enet2: ucc at 2000 {
+ device_type = "network";
+ compatible = "ucc_geth";
+- model = "UCC";
+ cell-index = <1>;
+- device-id = <1>;
+- reg = <2000 200>;
+- interrupts = <20>;
++ reg = <0x2000 0x200>;
++ interrupts = <32>;
+ interrupt-parent = <&qeic>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ rx-clock-name = "none";
+@@ -341,11 +336,9 @@
+ enet3: ucc at 3000 {
+ device_type = "network";
+ compatible = "ucc_geth";
+- model = "UCC";
+ cell-index = <2>;
+- device-id = <2>;
+- reg = <3000 200>;
+- interrupts = <21>;
++ reg = <0x3000 0x200>;
++ interrupts = <33>;
+ interrupt-parent = <&qeic>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ rx-clock-name = "none";
+@@ -358,7 +351,7 @@
+ mdio at 2120 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+- reg = <2120 18>;
++ reg = <0x2120 0x18>;
+ compatible = "fsl,ucc-mdio";
+
+ /* These are the same PHYs as on
+@@ -366,25 +359,25 @@
+ qe_phy0: ethernet-phy at 07 {
+ interrupt-parent = <&mpic>;
+ interrupts = <1 1>;
+- reg = <7>;
++ reg = <0x7>;
+ device_type = "ethernet-phy";
+ };
+ qe_phy1: ethernet-phy at 01 {
+ interrupt-parent = <&mpic>;
+ interrupts = <2 1>;
+- reg = <1>;
++ reg = <0x1>;
+ device_type = "ethernet-phy";
+ };
+ qe_phy2: ethernet-phy at 02 {
+ interrupt-parent = <&mpic>;
+ interrupts = <1 1>;
+- reg = <2>;
++ reg = <0x2>;
+ device_type = "ethernet-phy";
+ };
+ qe_phy3: ethernet-phy at 03 {
+ interrupt-parent = <&mpic>;
+ interrupts = <2 1>;
+- reg = <3>;
++ reg = <0x3>;
+ device_type = "ethernet-phy";
+ };
+ };
+@@ -394,9 +387,9 @@
+ compatible = "fsl,qe-ic";
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+- reg = <80 80>;
++ reg = <0x80 0x80>;
+ big-endian;
+- interrupts = <2e 2 2e 2>; //high:30 low:30
++ interrupts = <46 2 46 2>; //high:30 low:30
+ interrupt-parent = <&mpic>;
+ };
+
+@@ -404,30 +397,30 @@
+
+ pci0: pci at e0008000 {
+ cell-index = <0>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x12 AD18 */
+- 9000 0 0 1 &mpic 5 1
+- 9000 0 0 2 &mpic 6 1
+- 9000 0 0 3 &mpic 7 1
+- 9000 0 0 4 &mpic 4 1
++ 0x9000 0x0 0x0 0x1 &mpic 0x5 0x1
++ 0x9000 0x0 0x0 0x2 &mpic 0x6 0x1
++ 0x9000 0x0 0x0 0x3 &mpic 0x7 0x1
++ 0x9000 0x0 0x0 0x4 &mpic 0x4 0x1
+
+ /* IDSEL 0x13 AD19 */
+- 9800 0 0 1 &mpic 6 1
+- 9800 0 0 2 &mpic 7 1
+- 9800 0 0 3 &mpic 4 1
+- 9800 0 0 4 &mpic 5 1>;
++ 0x9800 0x0 0x0 0x1 &mpic 0x6 0x1
++ 0x9800 0x0 0x0 0x2 &mpic 0x7 0x1
++ 0x9800 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0x9800 0x0 0x0 0x4 &mpic 0x5 0x1>;
+
+ interrupt-parent = <&mpic>;
+- interrupts = <18 2>;
+- bus-range = <0 ff>;
+- ranges = <02000000 0 80000000 80000000 0 20000000
+- 01000000 0 00000000 e2000000 0 00800000>;
+- clock-frequency = <3f940aa>;
++ interrupts = <24 2>;
++ bus-range = <0 255>;
++ ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xe2000000 0x0 0x800000>;
++ clock-frequency = <66666666>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e0008000 1000>;
++ reg = <0xe0008000 0x1000>;
+ compatible = "fsl,mpc8540-pci";
+ device_type = "pci";
+ };
+@@ -435,39 +428,39 @@
+ /* PCI Express */
+ pci1: pcie at e000a000 {
+ cell-index = <2>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+
+ /* IDSEL 0x0 (PEX) */
+- 00000 0 0 1 &mpic 0 1
+- 00000 0 0 2 &mpic 1 1
+- 00000 0 0 3 &mpic 2 1
+- 00000 0 0 4 &mpic 3 1>;
++ 00000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 00000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 00000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 00000 0x0 0x0 0x4 &mpic 0x3 0x1>;
+
+ interrupt-parent = <&mpic>;
+- interrupts = <1a 2>;
+- bus-range = <0 ff>;
+- ranges = <02000000 0 a0000000 a0000000 0 10000000
+- 01000000 0 00000000 e2800000 0 00800000>;
+- clock-frequency = <1fca055>;
++ interrupts = <26 2>;
++ bus-range = <0 255>;
++ ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000
++ 0x1000000 0x0 0x0 0xe2800000 0x0 0x800000>;
++ clock-frequency = <33333333>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <e000a000 1000>;
++ reg = <0xe000a000 0x1000>;
+ compatible = "fsl,mpc8548-pcie";
+ device_type = "pci";
+ pcie at 0 {
+- reg = <0 0 0 0 0>;
++ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+- ranges = <02000000 0 a0000000
+- 02000000 0 a0000000
+- 0 10000000
++ ranges = <0x2000000 0x0 0xa0000000
++ 0x2000000 0x0 0xa0000000
++ 0x0 0x10000000
+
+- 01000000 0 00000000
+- 01000000 0 00000000
+- 0 00800000>;
++ 0x1000000 0x0 0x0
++ 0x1000000 0x0 0x0
++ 0x0 0x800000>;
+ };
+ };
+ };
+diff --git a/arch/powerpc/boot/dts/mpc8572ds.dts b/arch/powerpc/boot/dts/mpc8572ds.dts
+index db37214..66f27ab 100644
+--- a/arch/powerpc/boot/dts/mpc8572ds.dts
++++ b/arch/powerpc/boot/dts/mpc8572ds.dts
+@@ -1,7 +1,7 @@
+ /*
+ * MPC8572 DS Device Tree Source
+ *
+- * Copyright 2007 Freescale Semiconductor Inc.
++ * Copyright 2007, 2008 Freescale Semiconductor Inc.
+ *
+ * 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
+@@ -9,6 +9,7 @@
+ * option) any later version.
+ */
+
++/dts-v1/;
+ / {
+ model = "fsl,MPC8572DS";
+ compatible = "fsl,MPC8572DS";
+@@ -33,11 +34,11 @@
+
+ PowerPC,8572 at 0 {
+ device_type = "cpu";
+- reg = <0>;
+- d-cache-line-size = <20>; // 32 bytes
+- i-cache-line-size = <20>; // 32 bytes
+- d-cache-size = <8000>; // L1, 32K
+- i-cache-size = <8000>; // L1, 32K
++ reg = <0x0>;
++ d-cache-line-size = <32>; // 32 bytes
++ i-cache-line-size = <32>; // 32 bytes
++ d-cache-size = <0x8000>; // L1, 32K
++ i-cache-size = <0x8000>; // L1, 32K
+ timebase-frequency = <0>;
+ bus-frequency = <0>;
+ clock-frequency = <0>;
+@@ -45,11 +46,11 @@
+
+ PowerPC,8572 at 1 {
+ device_type = "cpu";
+- reg = <1>;
+- d-cache-line-size = <20>; // 32 bytes
+- i-cache-line-size = <20>; // 32 bytes
+- d-cache-size = <8000>; // L1, 32K
+- i-cache-size = <8000>; // L1, 32K
++ reg = <0x1>;
++ d-cache-line-size = <32>; // 32 bytes
++ i-cache-line-size = <32>; // 32 bytes
++ d-cache-size = <0x8000>; // L1, 32K
++ i-cache-size = <0x8000>; // L1, 32K
+ timebase-frequency = <0>;
+ bus-frequency = <0>;
+ clock-frequency = <0>;
+@@ -58,38 +59,38 @@
+
+ memory {
+ device_type = "memory";
+- reg = <00000000 00000000>; // Filled by U-Boot
++ reg = <0x0 0x0>; // Filled by U-Boot
+ };
+
+ soc8572 at ffe00000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+- ranges = <00000000 ffe00000 00100000>;
+- reg = <ffe00000 00001000>; // CCSRBAR & soc regs, remove once parse code for immrbase fixed
++ ranges = <0x0 0xffe00000 0x100000>;
++ reg = <0xffe00000 0x1000>; // CCSRBAR & soc regs, remove once parse code for immrbase fixed
+ bus-frequency = <0>; // Filled out by uboot.
+
+ memory-controller at 2000 {
+ compatible = "fsl,mpc8572-memory-controller";
+- reg = <2000 1000>;
++ reg = <0x2000 0x1000>;
+ interrupt-parent = <&mpic>;
+- interrupts = <12 2>;
++ interrupts = <18 2>;
+ };
+
+ memory-controller at 6000 {
+ compatible = "fsl,mpc8572-memory-controller";
+- reg = <6000 1000>;
++ reg = <0x6000 0x1000>;
+ interrupt-parent = <&mpic>;
+- interrupts = <12 2>;
++ interrupts = <18 2>;
+ };
+
+ l2-cache-controller at 20000 {
+ compatible = "fsl,mpc8572-l2-cache-controller";
+- reg = <20000 1000>;
+- cache-line-size = <20>; // 32 bytes
+- cache-size = <80000>; // L2, 512K
++ reg = <0x20000 0x1000>;
++ cache-line-size = <32>; // 32 bytes
++ cache-size = <0x80000>; // L2, 512K
+ interrupt-parent = <&mpic>;
+- interrupts = <10 2>;
++ interrupts = <16 2>;
+ };
+
+ i2c at 3000 {
+@@ -97,8 +98,8 @@
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+- reg = <3000 100>;
+- interrupts = <2b 2>;
++ reg = <0x3000 0x100>;
++ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+@@ -108,8 +109,8 @@
+ #size-cells = <0>;
+ cell-index = <1>;
+ compatible = "fsl-i2c";
+- reg = <3100 100>;
+- interrupts = <2b 2>;
++ reg = <0x3100 0x100>;
++ interrupts = <43 2>;
+ interrupt-parent = <&mpic>;
+ dfsrr;
+ };
+@@ -118,27 +119,27 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,gianfar-mdio";
+- reg = <24520 20>;
++ reg = <0x24520 0x20>;
+
+ phy0: ethernet-phy at 0 {
+ interrupt-parent = <&mpic>;
+- interrupts = <a 1>;
+- reg = <0>;
++ interrupts = <10 1>;
++ reg = <0x0>;
+ };
+ phy1: ethernet-phy at 1 {
+ interrupt-parent = <&mpic>;
+- interrupts = <a 1>;
+- reg = <1>;
++ interrupts = <10 1>;
++ reg = <0x1>;
+ };
+ phy2: ethernet-phy at 2 {
+ interrupt-parent = <&mpic>;
+- interrupts = <a 1>;
+- reg = <2>;
++ interrupts = <10 1>;
++ reg = <0x2>;
+ };
+ phy3: ethernet-phy at 3 {
+ interrupt-parent = <&mpic>;
+- interrupts = <a 1>;
+- reg = <3>;
++ interrupts = <10 1>;
++ reg = <0x3>;
+ };
+ };
+
+@@ -147,9 +148,9 @@
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "gianfar";
+- reg = <24000 1000>;
++ reg = <0x24000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <1d 2 1e 2 22 2>;
++ interrupts = <29 2 30 2 34 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy0>;
+ phy-connection-type = "rgmii-id";
+@@ -160,9 +161,9 @@
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "gianfar";
+- reg = <25000 1000>;
++ reg = <0x25000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <23 2 24 2 28 2>;
++ interrupts = <35 2 36 2 40 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy1>;
+ phy-connection-type = "rgmii-id";
+@@ -173,9 +174,9 @@
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "gianfar";
+- reg = <26000 1000>;
++ reg = <0x26000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <1f 2 20 2 21 2>;
++ interrupts = <31 2 32 2 33 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy2>;
+ phy-connection-type = "rgmii-id";
+@@ -186,9 +187,9 @@
+ device_type = "network";
+ model = "eTSEC";
+ compatible = "gianfar";
+- reg = <27000 1000>;
++ reg = <0x27000 0x1000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <25 2 26 2 27 2>;
++ interrupts = <37 2 38 2 39 2>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy3>;
+ phy-connection-type = "rgmii-id";
+@@ -198,9 +199,9 @@
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <4500 100>;
++ reg = <0x4500 0x100>;
+ clock-frequency = <0>;
+- interrupts = <2a 2>;
++ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+@@ -208,15 +209,15 @@
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+- reg = <4600 100>;
++ reg = <0x4600 0x100>;
+ clock-frequency = <0>;
+- interrupts = <2a 2>;
++ interrupts = <42 2>;
+ interrupt-parent = <&mpic>;
+ };
+
+ global-utilities at e0000 { //global utilities block
+ compatible = "fsl,mpc8572-guts";
+- reg = <e0000 1000>;
++ reg = <0xe0000 0x1000>;
+ fsl,has-rstcr;
+ };
+
+@@ -225,7 +226,7 @@
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+- reg = <40000 40000>;
++ reg = <0x40000 0x40000>;
+ compatible = "chrp,open-pic";
+ device_type = "open-pic";
+ big-endian;
+@@ -239,167 +240,167 @@
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <ffe08000 1000>;
+- bus-range = <0 ff>;
+- ranges = <02000000 0 80000000 80000000 0 20000000
+- 01000000 0 00000000 ffc00000 0 00010000>;
+- clock-frequency = <1fca055>;
++ reg = <0xffe08000 0x1000>;
++ bus-range = <0 255>;
++ ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xffc00000 0x0 0x10000>;
++ clock-frequency = <33333333>;
+ interrupt-parent = <&mpic>;
+- interrupts = <18 2>;
+- interrupt-map-mask = <ff00 0 0 7>;
++ interrupts = <24 2>;
++ interrupt-map-mask = <0xff00 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x11 func 0 - PCI slot 1 */
+- 8800 0 0 1 &mpic 2 1
+- 8800 0 0 2 &mpic 3 1
+- 8800 0 0 3 &mpic 4 1
+- 8800 0 0 4 &mpic 1 1
++ 0x8800 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x8800 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x8800 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0x8800 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x11 func 1 - PCI slot 1 */
+- 8900 0 0 1 &mpic 2 1
+- 8900 0 0 2 &mpic 3 1
+- 8900 0 0 3 &mpic 4 1
+- 8900 0 0 4 &mpic 1 1
++ 0x8900 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x8900 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x8900 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0x8900 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x11 func 2 - PCI slot 1 */
+- 8a00 0 0 1 &mpic 2 1
+- 8a00 0 0 2 &mpic 3 1
+- 8a00 0 0 3 &mpic 4 1
+- 8a00 0 0 4 &mpic 1 1
++ 0x8a00 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x8a00 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x8a00 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0x8a00 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x11 func 3 - PCI slot 1 */
+- 8b00 0 0 1 &mpic 2 1
+- 8b00 0 0 2 &mpic 3 1
+- 8b00 0 0 3 &mpic 4 1
+- 8b00 0 0 4 &mpic 1 1
++ 0x8b00 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x8b00 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x8b00 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0x8b00 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x11 func 4 - PCI slot 1 */
+- 8c00 0 0 1 &mpic 2 1
+- 8c00 0 0 2 &mpic 3 1
+- 8c00 0 0 3 &mpic 4 1
+- 8c00 0 0 4 &mpic 1 1
++ 0x8c00 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x8c00 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x8c00 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0x8c00 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x11 func 5 - PCI slot 1 */
+- 8d00 0 0 1 &mpic 2 1
+- 8d00 0 0 2 &mpic 3 1
+- 8d00 0 0 3 &mpic 4 1
+- 8d00 0 0 4 &mpic 1 1
++ 0x8d00 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x8d00 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x8d00 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0x8d00 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x11 func 6 - PCI slot 1 */
+- 8e00 0 0 1 &mpic 2 1
+- 8e00 0 0 2 &mpic 3 1
+- 8e00 0 0 3 &mpic 4 1
+- 8e00 0 0 4 &mpic 1 1
++ 0x8e00 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x8e00 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x8e00 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0x8e00 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x11 func 7 - PCI slot 1 */
+- 8f00 0 0 1 &mpic 2 1
+- 8f00 0 0 2 &mpic 3 1
+- 8f00 0 0 3 &mpic 4 1
+- 8f00 0 0 4 &mpic 1 1
++ 0x8f00 0x0 0x0 0x1 &mpic 0x2 0x1
++ 0x8f00 0x0 0x0 0x2 &mpic 0x3 0x1
++ 0x8f00 0x0 0x0 0x3 &mpic 0x4 0x1
++ 0x8f00 0x0 0x0 0x4 &mpic 0x1 0x1
+
+ /* IDSEL 0x12 func 0 - PCI slot 2 */
+- 9000 0 0 1 &mpic 3 1
+- 9000 0 0 2 &mpic 4 1
+- 9000 0 0 3 &mpic 1 1
+- 9000 0 0 4 &mpic 2 1
++ 0x9000 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x9000 0x0 0x0 0x2 &mpic 0x4 0x1
++ 0x9000 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0x9000 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ /* IDSEL 0x12 func 1 - PCI slot 2 */
+- 9100 0 0 1 &mpic 3 1
+- 9100 0 0 2 &mpic 4 1
+- 9100 0 0 3 &mpic 1 1
+- 9100 0 0 4 &mpic 2 1
++ 0x9100 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x9100 0x0 0x0 0x2 &mpic 0x4 0x1
++ 0x9100 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0x9100 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ /* IDSEL 0x12 func 2 - PCI slot 2 */
+- 9200 0 0 1 &mpic 3 1
+- 9200 0 0 2 &mpic 4 1
+- 9200 0 0 3 &mpic 1 1
+- 9200 0 0 4 &mpic 2 1
++ 0x9200 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x9200 0x0 0x0 0x2 &mpic 0x4 0x1
++ 0x9200 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0x9200 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ /* IDSEL 0x12 func 3 - PCI slot 2 */
+- 9300 0 0 1 &mpic 3 1
+- 9300 0 0 2 &mpic 4 1
+- 9300 0 0 3 &mpic 1 1
+- 9300 0 0 4 &mpic 2 1
++ 0x9300 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x9300 0x0 0x0 0x2 &mpic 0x4 0x1
++ 0x9300 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0x9300 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ /* IDSEL 0x12 func 4 - PCI slot 2 */
+- 9400 0 0 1 &mpic 3 1
+- 9400 0 0 2 &mpic 4 1
+- 9400 0 0 3 &mpic 1 1
+- 9400 0 0 4 &mpic 2 1
++ 0x9400 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x9400 0x0 0x0 0x2 &mpic 0x4 0x1
++ 0x9400 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0x9400 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ /* IDSEL 0x12 func 5 - PCI slot 2 */
+- 9500 0 0 1 &mpic 3 1
+- 9500 0 0 2 &mpic 4 1
+- 9500 0 0 3 &mpic 1 1
+- 9500 0 0 4 &mpic 2 1
++ 0x9500 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x9500 0x0 0x0 0x2 &mpic 0x4 0x1
++ 0x9500 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0x9500 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ /* IDSEL 0x12 func 6 - PCI slot 2 */
+- 9600 0 0 1 &mpic 3 1
+- 9600 0 0 2 &mpic 4 1
+- 9600 0 0 3 &mpic 1 1
+- 9600 0 0 4 &mpic 2 1
++ 0x9600 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x9600 0x0 0x0 0x2 &mpic 0x4 0x1
++ 0x9600 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0x9600 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ /* IDSEL 0x12 func 7 - PCI slot 2 */
+- 9700 0 0 1 &mpic 3 1
+- 9700 0 0 2 &mpic 4 1
+- 9700 0 0 3 &mpic 1 1
+- 9700 0 0 4 &mpic 2 1
++ 0x9700 0x0 0x0 0x1 &mpic 0x3 0x1
++ 0x9700 0x0 0x0 0x2 &mpic 0x4 0x1
++ 0x9700 0x0 0x0 0x3 &mpic 0x1 0x1
++ 0x9700 0x0 0x0 0x4 &mpic 0x2 0x1
+
+ // IDSEL 0x1c USB
+- e000 0 0 1 &i8259 c 2
+- e100 0 0 2 &i8259 9 2
+- e200 0 0 3 &i8259 a 2
+- e300 0 0 4 &i8259 b 2
++ 0xe000 0x0 0x0 0x1 &i8259 0xc 0x2
++ 0xe100 0x0 0x0 0x2 &i8259 0x9 0x2
++ 0xe200 0x0 0x0 0x3 &i8259 0xa 0x2
++ 0xe300 0x0 0x0 0x4 &i8259 0xb 0x2
+
+ // IDSEL 0x1d Audio
+- e800 0 0 1 &i8259 6 2
++ 0xe800 0x0 0x0 0x1 &i8259 0x6 0x2
+
+ // IDSEL 0x1e Legacy
+- f000 0 0 1 &i8259 7 2
+- f100 0 0 1 &i8259 7 2
++ 0xf000 0x0 0x0 0x1 &i8259 0x7 0x2
++ 0xf100 0x0 0x0 0x1 &i8259 0x7 0x2
+
+ // IDSEL 0x1f IDE/SATA
+- f800 0 0 1 &i8259 e 2
+- f900 0 0 1 &i8259 5 2
++ 0xf800 0x0 0x0 0x1 &i8259 0xe 0x2
++ 0xf900 0x0 0x0 0x1 &i8259 0x5 0x2
+
+ >;
+
+ pcie at 0 {
+- reg = <0 0 0 0 0>;
++ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+- ranges = <02000000 0 80000000
+- 02000000 0 80000000
+- 0 20000000
++ ranges = <0x2000000 0x0 0x80000000
++ 0x2000000 0x0 0x80000000
++ 0x0 0x20000000
+
+- 01000000 0 00000000
+- 01000000 0 00000000
+- 0 00100000>;
++ 0x1000000 0x0 0x0
++ 0x1000000 0x0 0x0
++ 0x0 0x100000>;
+ uli1575 at 0 {
+- reg = <0 0 0 0 0>;
++ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- ranges = <02000000 0 80000000
+- 02000000 0 80000000
+- 0 20000000
++ ranges = <0x2000000 0x0 0x80000000
++ 0x2000000 0x0 0x80000000
++ 0x0 0x20000000
+
+- 01000000 0 00000000
+- 01000000 0 00000000
+- 0 00100000>;
++ 0x1000000 0x0 0x0
++ 0x1000000 0x0 0x0
++ 0x0 0x100000>;
+ isa at 1e {
+ device_type = "isa";
+ #interrupt-cells = <2>;
+ #size-cells = <1>;
+ #address-cells = <2>;
+- reg = <f000 0 0 0 0>;
+- ranges = <1 0 01000000 0 0
+- 00001000>;
++ reg = <0xf000 0x0 0x0 0x0 0x0>;
++ ranges = <0x1 0x0 0x1000000 0x0 0x0
++ 0x1000>;
+ interrupt-parent = <&i8259>;
+
+ i8259: interrupt-controller at 20 {
+- reg = <1 20 2
+- 1 a0 2
+- 1 4d0 2>;
++ reg = <0x1 0x20 0x2
++ 0x1 0xa0 0x2
++ 0x1 0x4d0 0x2>;
+ interrupt-controller;
+ device_type = "interrupt-controller";
+ #address-cells = <0>;
+@@ -412,29 +413,29 @@
+ i8042 at 60 {
+ #size-cells = <0>;
+ #address-cells = <1>;
+- reg = <1 60 1 1 64 1>;
+- interrupts = <1 3 c 3>;
++ reg = <0x1 0x60 0x1 0x1 0x64 0x1>;
++ interrupts = <1 3 12 3>;
+ interrupt-parent =
+ <&i8259>;
+
+ keyboard at 0 {
+- reg = <0>;
++ reg = <0x0>;
+ compatible = "pnpPNP,303";
+ };
+
+ mouse at 1 {
+- reg = <1>;
++ reg = <0x1>;
+ compatible = "pnpPNP,f03";
+ };
+ };
+
+ rtc at 70 {
+ compatible = "pnpPNP,b00";
+- reg = <1 70 2>;
++ reg = <0x1 0x70 0x2>;
+ };
+
+ gpio at 400 {
+- reg = <1 400 80>;
++ reg = <0x1 0x400 0x80>;
+ };
+ };
+ };
+@@ -449,33 +450,33 @@
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <ffe09000 1000>;
+- bus-range = <0 ff>;
+- ranges = <02000000 0 a0000000 a0000000 0 20000000
+- 01000000 0 00000000 ffc10000 0 00010000>;
+- clock-frequency = <1fca055>;
++ reg = <0xffe09000 0x1000>;
++ bus-range = <0 255>;
++ ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xffc10000 0x0 0x10000>;
++ clock-frequency = <33333333>;
+ interrupt-parent = <&mpic>;
+- interrupts = <1a 2>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupts = <26 2>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+- 0000 0 0 1 &mpic 4 1
+- 0000 0 0 2 &mpic 5 1
+- 0000 0 0 3 &mpic 6 1
+- 0000 0 0 4 &mpic 7 1
++ 0000 0x0 0x0 0x1 &mpic 0x4 0x1
++ 0000 0x0 0x0 0x2 &mpic 0x5 0x1
++ 0000 0x0 0x0 0x3 &mpic 0x6 0x1
++ 0000 0x0 0x0 0x4 &mpic 0x7 0x1
+ >;
+ pcie at 0 {
+- reg = <0 0 0 0 0>;
++ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+- ranges = <02000000 0 a0000000
+- 02000000 0 a0000000
+- 0 20000000
++ ranges = <0x2000000 0x0 0xa0000000
++ 0x2000000 0x0 0xa0000000
++ 0x0 0x20000000
+
+- 01000000 0 00000000
+- 01000000 0 00000000
+- 0 00100000>;
++ 0x1000000 0x0 0x0
++ 0x1000000 0x0 0x0
++ 0x0 0x100000>;
+ };
+ };
+
+@@ -486,33 +487,33 @@
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- reg = <ffe0a000 1000>;
+- bus-range = <0 ff>;
+- ranges = <02000000 0 c0000000 c0000000 0 20000000
+- 01000000 0 00000000 ffc20000 0 00010000>;
+- clock-frequency = <1fca055>;
++ reg = <0xffe0a000 0x1000>;
++ bus-range = <0 255>;
++ ranges = <0x2000000 0x0 0xc0000000 0xc0000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xffc20000 0x0 0x10000>;
++ clock-frequency = <33333333>;
+ interrupt-parent = <&mpic>;
+- interrupts = <1b 2>;
+- interrupt-map-mask = <f800 0 0 7>;
++ interrupts = <27 2>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+- 0000 0 0 1 &mpic 0 1
+- 0000 0 0 2 &mpic 1 1
+- 0000 0 0 3 &mpic 2 1
+- 0000 0 0 4 &mpic 3 1
++ 0000 0x0 0x0 0x1 &mpic 0x0 0x1
++ 0000 0x0 0x0 0x2 &mpic 0x1 0x1
++ 0000 0x0 0x0 0x3 &mpic 0x2 0x1
++ 0000 0x0 0x0 0x4 &mpic 0x3 0x1
+ >;
+ pcie at 0 {
+- reg = <0 0 0 0 0>;
++ reg = <0x0 0x0 0x0 0x0 0x0>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+- ranges = <02000000 0 c0000000
+- 02000000 0 c0000000
+- 0 20000000
++ ranges = <0x2000000 0x0 0xc0000000
++ 0x2000000 0x0 0xc0000000
++ 0x0 0x20000000
+
+- 01000000 0 00000000
+- 01000000 0 00000000
+- 0 00100000>;
++ 0x1000000 0x0 0x0
++ 0x1000000 0x0 0x0
++ 0x0 0x100000>;
+ };
+ };
+ };
+diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
+index 79385bc..7f9b999 100644
+--- a/arch/powerpc/boot/dts/mpc8641_hpcn.dts
++++ b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
+@@ -13,7 +13,7 @@
+
+ / {
+ model = "MPC8641HPCN";
+- compatible = "mpc86xx";
++ compatible = "fsl,mpc8641hpcn";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+diff --git a/arch/powerpc/boot/dts/mpc866ads.dts b/arch/powerpc/boot/dts/mpc866ads.dts
+index daf9433..765e43c 100644
+--- a/arch/powerpc/boot/dts/mpc866ads.dts
++++ b/arch/powerpc/boot/dts/mpc866ads.dts
+@@ -2,6 +2,7 @@
+ * MPC866 ADS Device Tree Source
+ *
+ * Copyright 2006 MontaVista Software, Inc.
++ * Copyright 2008 Freescale Semiconductor, Inc.
+ *
+ * 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
+@@ -9,6 +10,7 @@
+ * option) any later version.
+ */
+
++/dts-v1/;
+
+ / {
+ model = "MPC866ADS";
+@@ -22,37 +24,37 @@
+
+ PowerPC,866 at 0 {
+ device_type = "cpu";
+- reg = <0>;
+- d-cache-line-size = <10>; // 16 bytes
+- i-cache-line-size = <10>; // 16 bytes
+- d-cache-size = <2000>; // L1, 8K
+- i-cache-size = <4000>; // L1, 16K
++ reg = <0x0>;
++ d-cache-line-size = <16>; // 16 bytes
++ i-cache-line-size = <16>; // 16 bytes
++ d-cache-size = <0x2000>; // L1, 8K
++ i-cache-size = <0x4000>; // L1, 16K
+ timebase-frequency = <0>;
+ bus-frequency = <0>;
+ clock-frequency = <0>;
+- interrupts = <f 2>; // decrementer interrupt
++ interrupts = <15 2>; // decrementer interrupt
+ interrupt-parent = <&PIC>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+- reg = <00000000 800000>;
++ reg = <0x0 0x800000>;
+ };
+
+ localbus at ff000100 {
+ compatible = "fsl,mpc866-localbus", "fsl,pq1-localbus";
+ #address-cells = <2>;
+ #size-cells = <1>;
+- reg = <ff000100 40>;
++ reg = <0xff000100 0x40>;
+
+ ranges = <
+- 1 0 ff080000 00008000
+- 5 0 ff0a0000 00008000
++ 0x1 0x0 0xff080000 0x8000
++ 0x5 0x0 0xff0a0000 0x8000
+ >;
+
+ board-control at 1,0 {
+- reg = <1 0 20 5 300 4>;
++ reg = <0x1 0x0 0x20 0x5 0x300 0x4>;
+ compatible = "fsl,mpc866ads-bcsr";
+ };
+ };
+@@ -61,17 +63,17 @@
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+- ranges = <0 ff000000 00100000>;
+- reg = <ff000000 00000200>;
++ ranges = <0x0 0xff000000 0x100000>;
++ reg = <0xff000000 0x200>;
+ bus-frequency = <0>;
+
+ mdio at e00 {
+ compatible = "fsl,mpc866-fec-mdio", "fsl,pq1-fec-mdio";
+- reg = <e00 188>;
++ reg = <0xe00 0x188>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ PHY: ethernet-phy at f {
+- reg = <f>;
++ reg = <0xf>;
+ device_type = "ethernet-phy";
+ };
+ };
+@@ -80,7 +82,7 @@
+ device_type = "network";
+ compatible = "fsl,mpc866-fec-enet",
+ "fsl,pq1-fec-enet";
+- reg = <e00 188>;
++ reg = <0xe00 0x188>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <3 1>;
+ interrupt-parent = <&PIC>;
+@@ -91,7 +93,7 @@
+ PIC: pic at 0 {
+ interrupt-controller;
+ #interrupt-cells = <2>;
+- reg = <0 24>;
++ reg = <0x0 0x24>;
+ compatible = "fsl,mpc866-pic", "fsl,pq1-pic";
+ };
+
+@@ -100,7 +102,7 @@
+ #size-cells = <1>;
+ compatible = "fsl,mpc866-cpm", "fsl,cpm1";
+ ranges;
+- reg = <9c0 40>;
++ reg = <0x9c0 0x40>;
+ brg-frequency = <0>;
+ interrupts = <0 2>; // cpm error interrupt
+ interrupt-parent = <&CPM_PIC>;
+@@ -108,11 +110,11 @@
+ muram at 2000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+- ranges = <0 2000 2000>;
++ ranges = <0x0 0x2000 0x2000>;
+
+ data at 0 {
+ compatible = "fsl,cpm-muram-data";
+- reg = <0 1c00>;
++ reg = <0x0 0x1c00>;
+ };
+ };
+
+@@ -120,7 +122,7 @@
+ compatible = "fsl,mpc866-brg",
+ "fsl,cpm1-brg",
+ "fsl,cpm-brg";
+- reg = <9f0 10>;
++ reg = <0x9f0 0x10>;
+ clock-frequency = <0>;
+ };
+
+@@ -130,7 +132,7 @@
+ #interrupt-cells = <1>;
+ interrupts = <5 2 0 2>;
+ interrupt-parent = <&PIC>;
+- reg = <930 20>;
++ reg = <0x930 0x20>;
+ compatible = "fsl,mpc866-cpm-pic",
+ "fsl,cpm1-pic";
+ };
+@@ -140,31 +142,31 @@
+ device_type = "serial";
+ compatible = "fsl,mpc866-smc-uart",
+ "fsl,cpm1-smc-uart";
+- reg = <a80 10 3e80 40>;
++ reg = <0xa80 0x10 0x3e80 0x40>;
+ interrupts = <4>;
+ interrupt-parent = <&CPM_PIC>;
+ fsl,cpm-brg = <1>;
+- fsl,cpm-command = <0090>;
++ fsl,cpm-command = <0x90>;
+ };
+
+ serial at a90 {
+ device_type = "serial";
+ compatible = "fsl,mpc866-smc-uart",
+ "fsl,cpm1-smc-uart";
+- reg = <a90 10 3f80 40>;
++ reg = <0xa90 0x10 0x3f80 0x40>;
+ interrupts = <3>;
+ interrupt-parent = <&CPM_PIC>;
+ fsl,cpm-brg = <2>;
+- fsl,cpm-command = <00d0>;
++ fsl,cpm-command = <0xd0>;
+ };
+
+ ethernet at a00 {
+ device_type = "network";
+ compatible = "fsl,mpc866-scc-enet",
+ "fsl,cpm1-scc-enet";
+- reg = <a00 18 3c00 100>;
++ reg = <0xa00 0x18 0x3c00 0x100>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <1e>;
++ interrupts = <30>;
+ interrupt-parent = <&CPM_PIC>;
+ fsl,cpm-command = <0000>;
+ linux,network-index = <1>;
+diff --git a/arch/powerpc/boot/dts/mpc885ads.dts b/arch/powerpc/boot/dts/mpc885ads.dts
+index d84a012..9895043 100644
+--- a/arch/powerpc/boot/dts/mpc885ads.dts
++++ b/arch/powerpc/boot/dts/mpc885ads.dts
+@@ -2,7 +2,7 @@
+ * MPC885 ADS Device Tree Source
+ *
+ * Copyright 2006 MontaVista Software, Inc.
+- * Copyright 2007 Freescale Semiconductor, Inc.
++ * Copyright 2007,2008 Freescale Semiconductor, Inc.
+ *
+ * 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
+@@ -10,6 +10,7 @@
+ * option) any later version.
+ */
+
++/dts-v1/;
+
+ / {
+ model = "MPC885ADS";
+@@ -23,45 +24,45 @@
+
+ PowerPC,885 at 0 {
+ device_type = "cpu";
+- reg = <0>;
+- d-cache-line-size = <d#16>;
+- i-cache-line-size = <d#16>;
+- d-cache-size = <d#8192>;
+- i-cache-size = <d#8192>;
++ reg = <0x0>;
++ d-cache-line-size = <16>;
++ i-cache-line-size = <16>;
++ d-cache-size = <8192>;
++ i-cache-size = <8192>;
+ timebase-frequency = <0>;
+ bus-frequency = <0>;
+ clock-frequency = <0>;
+- interrupts = <f 2>; // decrementer interrupt
++ interrupts = <15 2>; // decrementer interrupt
+ interrupt-parent = <&PIC>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+- reg = <0 0>;
++ reg = <0x0 0x0>;
+ };
+
+ localbus at ff000100 {
+ compatible = "fsl,mpc885-localbus", "fsl,pq1-localbus";
+ #address-cells = <2>;
+ #size-cells = <1>;
+- reg = <ff000100 40>;
++ reg = <0xff000100 0x40>;
+
+ ranges = <
+- 0 0 fe000000 00800000
+- 1 0 ff080000 00008000
+- 5 0 ff0a0000 00008000
++ 0x0 0x0 0xfe000000 0x800000
++ 0x1 0x0 0xff080000 0x8000
++ 0x5 0x0 0xff0a0000 0x8000
+ >;
+
+ flash at 0,0 {
+ compatible = "jedec-flash";
+- reg = <0 0 800000>;
++ reg = <0x0 0x0 0x800000>;
+ bank-width = <4>;
+ device-width = <1>;
+ };
+
+ board-control at 1,0 {
+- reg = <1 0 20 5 300 4>;
++ reg = <0x1 0x0 0x20 0x5 0x300 0x4>;
+ compatible = "fsl,mpc885ads-bcsr";
+ };
+ };
+@@ -71,30 +72,30 @@
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+- ranges = <0 ff000000 00004000>;
++ ranges = <0x0 0xff000000 0x4000>;
+ bus-frequency = <0>;
+
+ // Temporary -- will go away once kernel uses ranges for get_immrbase().
+- reg = <ff000000 4000>;
++ reg = <0xff000000 0x4000>;
+
+ mdio at e00 {
+ compatible = "fsl,mpc885-fec-mdio", "fsl,pq1-fec-mdio";
+- reg = <e00 188>;
++ reg = <0xe00 0x188>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ PHY0: ethernet-phy at 0 {
+- reg = <0>;
++ reg = <0x0>;
+ device_type = "ethernet-phy";
+ };
+
+ PHY1: ethernet-phy at 1 {
+- reg = <1>;
++ reg = <0x1>;
+ device_type = "ethernet-phy";
+ };
+
+ PHY2: ethernet-phy at 2 {
+- reg = <2>;
++ reg = <0x2>;
+ device_type = "ethernet-phy";
+ };
+ };
+@@ -103,7 +104,7 @@
+ device_type = "network";
+ compatible = "fsl,mpc885-fec-enet",
+ "fsl,pq1-fec-enet";
+- reg = <e00 188>;
++ reg = <0xe00 0x188>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <3 1>;
+ interrupt-parent = <&PIC>;
+@@ -115,7 +116,7 @@
+ device_type = "network";
+ compatible = "fsl,mpc885-fec-enet",
+ "fsl,pq1-fec-enet";
+- reg = <1e00 188>;
++ reg = <0x1e00 0x188>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <7 1>;
+ interrupt-parent = <&PIC>;
+@@ -126,7 +127,7 @@
+ PIC: interrupt-controller at 0 {
+ interrupt-controller;
+ #interrupt-cells = <2>;
+- reg = <0 24>;
++ reg = <0x0 0x24>;
+ compatible = "fsl,mpc885-pic", "fsl,pq1-pic";
+ };
+
+@@ -136,29 +137,29 @@
+ #size-cells = <2>;
+ compatible = "fsl,pq-pcmcia";
+ device_type = "pcmcia";
+- reg = <80 80>;
++ reg = <0x80 0x80>;
+ interrupt-parent = <&PIC>;
+- interrupts = <d 1>;
++ interrupts = <13 1>;
+ };
+
+ cpm at 9c0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc885-cpm", "fsl,cpm1";
+- command-proc = <9c0>;
++ command-proc = <0x9c0>;
+ interrupts = <0>; // cpm error interrupt
+ interrupt-parent = <&CPM_PIC>;
+- reg = <9c0 40>;
++ reg = <0x9c0 0x40>;
+ ranges;
+
+ muram at 2000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+- ranges = <0 2000 2000>;
++ ranges = <0x0 0x2000 0x2000>;
+
+ data at 0 {
+ compatible = "fsl,cpm-muram-data";
+- reg = <0 1c00>;
++ reg = <0x0 0x1c00>;
+ };
+ };
+
+@@ -167,7 +168,7 @@
+ "fsl,cpm1-brg",
+ "fsl,cpm-brg";
+ clock-frequency = <0>;
+- reg = <9f0 10>;
++ reg = <0x9f0 0x10>;
+ };
+
+ CPM_PIC: interrupt-controller at 930 {
+@@ -175,7 +176,7 @@
+ #interrupt-cells = <1>;
+ interrupts = <5 2 0 2>;
+ interrupt-parent = <&PIC>;
+- reg = <930 20>;
++ reg = <0x930 0x20>;
+ compatible = "fsl,mpc885-cpm-pic",
+ "fsl,cpm1-pic";
+ };
+@@ -184,34 +185,34 @@
+ device_type = "serial";
+ compatible = "fsl,mpc885-smc-uart",
+ "fsl,cpm1-smc-uart";
+- reg = <a80 10 3e80 40>;
++ reg = <0xa80 0x10 0x3e80 0x40>;
+ interrupts = <4>;
+ interrupt-parent = <&CPM_PIC>;
+ fsl,cpm-brg = <1>;
+- fsl,cpm-command = <0090>;
++ fsl,cpm-command = <0x90>;
+ };
+
+ serial at a90 {
+ device_type = "serial";
+ compatible = "fsl,mpc885-smc-uart",
+ "fsl,cpm1-smc-uart";
+- reg = <a90 10 3f80 40>;
++ reg = <0xa90 0x10 0x3f80 0x40>;
+ interrupts = <3>;
+ interrupt-parent = <&CPM_PIC>;
+ fsl,cpm-brg = <2>;
+- fsl,cpm-command = <00d0>;
++ fsl,cpm-command = <0xd0>;
+ };
+
+ ethernet at a40 {
+ device_type = "network";
+ compatible = "fsl,mpc885-scc-enet",
+ "fsl,cpm1-scc-enet";
+- reg = <a40 18 3e00 100>;
++ reg = <0xa40 0x18 0x3e00 0x100>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+- interrupts = <1c>;
++ interrupts = <28>;
+ interrupt-parent = <&CPM_PIC>;
+ phy-handle = <&PHY2>;
+- fsl,cpm-command = <0080>;
++ fsl,cpm-command = <0x80>;
+ linux,network-index = <2>;
+ };
+ };
+diff --git a/arch/powerpc/boot/dts/pq2fads.dts b/arch/powerpc/boot/dts/pq2fads.dts
+index 2d56492..b2d6109 100644
+--- a/arch/powerpc/boot/dts/pq2fads.dts
++++ b/arch/powerpc/boot/dts/pq2fads.dts
+@@ -1,7 +1,7 @@
+ /*
+ * Device Tree for the PQ2FADS-ZU board with an MPC8280 chip.
+ *
+- * Copyright 2007 Freescale Semiconductor Inc.
++ * Copyright 2007,2008 Freescale Semiconductor Inc.
+ *
+ * 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
+@@ -9,6 +9,8 @@
+ * option) any later version.
+ */
+
++/dts-v1/;
++
+ / {
+ model = "pq2fads";
+ compatible = "fsl,pq2fads";
+@@ -21,11 +23,11 @@
+
+ cpu at 0 {
+ device_type = "cpu";
+- reg = <0>;
+- d-cache-line-size = <d#32>;
+- i-cache-line-size = <d#32>;
+- d-cache-size = <d#16384>;
+- i-cache-size = <d#16384>;
++ reg = <0x0>;
++ d-cache-line-size = <32>;
++ i-cache-line-size = <32>;
++ d-cache-size = <16384>;
++ i-cache-size = <16384>;
+ timebase-frequency = <0>;
+ clock-frequency = <0>;
+ };
+@@ -33,7 +35,7 @@
+
+ memory {
+ device_type = "memory";
+- reg = <0 0>;
++ reg = <0x0 0x0>;
+ };
+
+ localbus at f0010100 {
+@@ -41,67 +43,67 @@
+ "fsl,pq2-localbus";
+ #address-cells = <2>;
+ #size-cells = <1>;
+- reg = <f0010100 60>;
++ reg = <0xf0010100 0x60>;
+
+- ranges = <0 0 fe000000 00800000
+- 1 0 f4500000 00008000
+- 8 0 f8200000 00008000>;
++ ranges = <0x0 0x0 0xfe000000 0x800000
++ 0x1 0x0 0xf4500000 0x8000
++ 0x8 0x0 0xf8200000 0x8000>;
+
+ flash at 0,0 {
+ compatible = "jedec-flash";
+- reg = <0 0 800000>;
++ reg = <0x0 0x0 0x800000>;
+ bank-width = <4>;
+ device-width = <1>;
+ };
+
+ bcsr at 1,0 {
+- reg = <1 0 20>;
++ reg = <0x1 0x0 0x20>;
+ compatible = "fsl,pq2fads-bcsr";
+ };
+
+ PCI_PIC: pic at 8,0 {
+ #interrupt-cells = <1>;
+ interrupt-controller;
+- reg = <8 0 8>;
++ reg = <0x8 0x0 0x8>;
+ compatible = "fsl,pq2ads-pci-pic";
+ interrupt-parent = <&PIC>;
+- interrupts = <18 8>;
++ interrupts = <24 8>;
+ };
+ };
+
+ pci at f0010800 {
+ device_type = "pci";
+- reg = <f0010800 10c f00101ac 8 f00101c4 8>;
++ reg = <0xf0010800 0x10c 0xf00101ac 0x8 0xf00101c4 0x8>;
+ compatible = "fsl,mpc8280-pci", "fsl,pq2-pci";
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+- clock-frequency = <d#66000000>;
+- interrupt-map-mask = <f800 0 0 7>;
++ clock-frequency = <66000000>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x16 */
+- b000 0 0 1 &PCI_PIC 0
+- b000 0 0 2 &PCI_PIC 1
+- b000 0 0 3 &PCI_PIC 2
+- b000 0 0 4 &PCI_PIC 3
++ 0xb000 0x0 0x0 0x1 &PCI_PIC 0
++ 0xb000 0x0 0x0 0x2 &PCI_PIC 1
++ 0xb000 0x0 0x0 0x3 &PCI_PIC 2
++ 0xb000 0x0 0x0 0x4 &PCI_PIC 3
+
+ /* IDSEL 0x17 */
+- b800 0 0 1 &PCI_PIC 4
+- b800 0 0 2 &PCI_PIC 5
+- b800 0 0 3 &PCI_PIC 6
+- b800 0 0 4 &PCI_PIC 7
++ 0xb800 0x0 0x0 0x1 &PCI_PIC 4
++ 0xb800 0x0 0x0 0x2 &PCI_PIC 5
++ 0xb800 0x0 0x0 0x3 &PCI_PIC 6
++ 0xb800 0x0 0x0 0x4 &PCI_PIC 7
+
+ /* IDSEL 0x18 */
+- c000 0 0 1 &PCI_PIC 8
+- c000 0 0 2 &PCI_PIC 9
+- c000 0 0 3 &PCI_PIC a
+- c000 0 0 4 &PCI_PIC b>;
++ 0xc000 0x0 0x0 0x1 &PCI_PIC 8
++ 0xc000 0x0 0x0 0x2 &PCI_PIC 9
++ 0xc000 0x0 0x0 0x3 &PCI_PIC 10
++ 0xc000 0x0 0x0 0x4 &PCI_PIC 11>;
+
+ interrupt-parent = <&PIC>;
+- interrupts = <12 8>;
+- ranges = <42000000 0 80000000 80000000 0 20000000
+- 02000000 0 a0000000 a0000000 0 20000000
+- 01000000 0 00000000 f6000000 0 02000000>;
++ interrupts = <18 8>;
++ ranges = <0x42000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++ 0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
++ 0x1000000 0x0 0x0 0xf6000000 0x0 0x2000000>;
+ };
+
+ soc at f0000000 {
+@@ -109,27 +111,27 @@
+ #size-cells = <1>;
+ device_type = "soc";
+ compatible = "fsl,mpc8280", "fsl,pq2-soc";
+- ranges = <00000000 f0000000 00053000>;
++ ranges = <0x0 0xf0000000 0x53000>;
+
+ // Temporary -- will go away once kernel uses ranges for get_immrbase().
+- reg = <f0000000 00053000>;
++ reg = <0xf0000000 0x53000>;
+
+ cpm at 119c0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #interrupt-cells = <2>;
+ compatible = "fsl,mpc8280-cpm", "fsl,cpm2";
+- reg = <119c0 30>;
++ reg = <0x119c0 0x30>;
+ ranges;
+
+ muram at 0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+- ranges = <0 0 10000>;
++ ranges = <0x0 0x0 0x10000>;
+
+ data at 0 {
+ compatible = "fsl,cpm-muram-data";
+- reg = <0 2000 9800 800>;
++ reg = <0x0 0x2000 0x9800 0x800>;
+ };
+ };
+
+@@ -137,53 +139,53 @@
+ compatible = "fsl,mpc8280-brg",
+ "fsl,cpm2-brg",
+ "fsl,cpm-brg";
+- reg = <119f0 10 115f0 10>;
++ reg = <0x119f0 0x10 0x115f0 0x10>;
+ };
+
+ serial at 11a00 {
+ device_type = "serial";
+ compatible = "fsl,mpc8280-scc-uart",
+ "fsl,cpm2-scc-uart";
+- reg = <11a00 20 8000 100>;
+- interrupts = <28 8>;
++ reg = <0x11a00 0x20 0x8000 0x100>;
++ interrupts = <40 8>;
+ interrupt-parent = <&PIC>;
+ fsl,cpm-brg = <1>;
+- fsl,cpm-command = <00800000>;
++ fsl,cpm-command = <0x800000>;
+ };
+
+ serial at 11a20 {
+ device_type = "serial";
+ compatible = "fsl,mpc8280-scc-uart",
+ "fsl,cpm2-scc-uart";
+- reg = <11a20 20 8100 100>;
+- interrupts = <29 8>;
++ reg = <0x11a20 0x20 0x8100 0x100>;
++ interrupts = <41 8>;
+ interrupt-parent = <&PIC>;
+ fsl,cpm-brg = <2>;
+- fsl,cpm-command = <04a00000>;
++ fsl,cpm-command = <0x4a00000>;
+ };
+
+ ethernet at 11320 {
+ device_type = "network";
+ compatible = "fsl,mpc8280-fcc-enet",
+ "fsl,cpm2-fcc-enet";
+- reg = <11320 20 8500 100 113b0 1>;
+- interrupts = <21 8>;
++ reg = <0x11320 0x20 0x8500 0x100 0x113b0 0x1>;
++ interrupts = <33 8>;
+ interrupt-parent = <&PIC>;
+ phy-handle = <&PHY0>;
+ linux,network-index = <0>;
+- fsl,cpm-command = <16200300>;
++ fsl,cpm-command = <0x16200300>;
+ };
+
+ ethernet at 11340 {
+ device_type = "network";
+ compatible = "fsl,mpc8280-fcc-enet",
+ "fsl,cpm2-fcc-enet";
+- reg = <11340 20 8600 100 113d0 1>;
+- interrupts = <22 8>;
++ reg = <0x11340 0x20 0x8600 0x100 0x113d0 0x1>;
++ interrupts = <34 8>;
+ interrupt-parent = <&PIC>;
+ phy-handle = <&PHY1>;
+ linux,network-index = <1>;
+- fsl,cpm-command = <1a400300>;
++ fsl,cpm-command = <0x1a400300>;
+ local-mac-address = [00 e0 0c 00 79 01];
+ };
+
+@@ -194,21 +196,21 @@
+ "fsl,cpm2-mdio-bitbang";
+ #address-cells = <1>;
+ #size-cells = <0>;
+- reg = <10d40 14>;
++ reg = <0x10d40 0x14>;
+ fsl,mdio-pin = <9>;
+- fsl,mdc-pin = <a>;
++ fsl,mdc-pin = <10>;
+
+ PHY0: ethernet-phy at 0 {
+ interrupt-parent = <&PIC>;
+- interrupts = <19 2>;
+- reg = <0>;
++ interrupts = <25 2>;
++ reg = <0x0>;
+ device_type = "ethernet-phy";
+ };
+
+ PHY1: ethernet-phy at 1 {
+ interrupt-parent = <&PIC>;
+- interrupts = <19 2>;
+- reg = <3>;
++ interrupts = <25 2>;
++ reg = <0x3>;
+ device_type = "ethernet-phy";
+ };
+ };
+@@ -218,17 +220,17 @@
+ #size-cells = <0>;
+ compatible = "fsl,mpc8280-usb",
+ "fsl,cpm2-usb";
+- reg = <11b60 18 8b00 100>;
++ reg = <0x11b60 0x18 0x8b00 0x100>;
+ interrupt-parent = <&PIC>;
+- interrupts = <b 8>;
+- fsl,cpm-command = <2e600000>;
++ interrupts = <11 8>;
++ fsl,cpm-command = <0x2e600000>;
+ };
+ };
+
+ PIC: interrupt-controller at 10c00 {
+ #interrupt-cells = <2>;
+ interrupt-controller;
+- reg = <10c00 80>;
++ reg = <0x10c00 0x80>;
+ compatible = "fsl,mpc8280-pic", "fsl,cpm2-pic";
+ };
+
+diff --git a/arch/powerpc/boot/dts/prpmc2800.dts b/arch/powerpc/boot/dts/prpmc2800.dts
+index 297dfa5..1ee6ff4 100644
+--- a/arch/powerpc/boot/dts/prpmc2800.dts
++++ b/arch/powerpc/boot/dts/prpmc2800.dts
+@@ -11,6 +11,8 @@
+ * if it can determine the exact PrPMC type.
+ */
+
++/dts-v1/;
++
+ / {
+ #address-cells = <1>;
+ #size-cells = <1>;
+@@ -25,46 +27,46 @@
+ PowerPC,7447 {
+ device_type = "cpu";
+ reg = <0>;
+- clock-frequency = <2bb0b140>; /* Default (733 MHz) */
+- bus-frequency = <7f28155>; /* 133.333333 MHz */
+- timebase-frequency = <1fca055>; /* 33.333333 MHz */
+- i-cache-line-size = <20>;
+- d-cache-line-size = <20>;
+- i-cache-size = <8000>;
+- d-cache-size = <8000>;
++ clock-frequency = <733333333>; /* Default */
++ bus-frequency = <133333333>;
++ timebase-frequency = <33333333>;
++ i-cache-line-size = <32>;
++ d-cache-line-size = <32>;
++ i-cache-size = <32768>;
++ d-cache-size = <32768>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+- reg = <00000000 20000000>; /* Default (512MB) */
++ reg = <0x0 0x20000000>; /* Default (512MB) */
+ };
+
+- mv64x60 at f1000000 { /* Marvell Discovery */
++ system-controller at f1000000 { /* Marvell Discovery mv64360 */
+ #address-cells = <1>;
+ #size-cells = <1>;
+ model = "mv64360"; /* Default */
+- compatible = "marvell,mv64x60";
+- clock-frequency = <7f28155>; /* 133.333333 MHz */
+- reg = <f1000000 00010000>;
+- virtual-reg = <f1000000>;
+- ranges = <88000000 88000000 01000000 /* PCI 0 I/O Space */
+- 80000000 80000000 08000000 /* PCI 0 MEM Space */
+- a0000000 a0000000 04000000 /* User FLASH */
+- 00000000 f1000000 00010000 /* Bridge's regs */
+- f2000000 f2000000 00040000>; /* Integrated SRAM */
++ compatible = "marvell,mv64360";
++ clock-frequency = <133333333>;
++ reg = <0xf1000000 0x10000>;
++ virtual-reg = <0xf1000000>;
++ ranges = <0x88000000 0x88000000 0x1000000 /* PCI 0 I/O Space */
++ 0x80000000 0x80000000 0x8000000 /* PCI 0 MEM Space */
++ 0xa0000000 0xa0000000 0x4000000 /* User FLASH */
++ 0x00000000 0xf1000000 0x0010000 /* Bridge's regs */
++ 0xf2000000 0xf2000000 0x0040000>;/* Integrated SRAM */
+
+ flash at a0000000 {
+ device_type = "rom";
+ compatible = "direct-mapped";
+- reg = <a0000000 4000000>; /* Default (64MB) */
++ reg = <0xa0000000 0x4000000>; /* Default (64MB) */
+ probe-type = "CFI";
+ bank-width = <4>;
+- partitions = <00000000 00100000 /* RO */
+- 00100000 00040001 /* RW */
+- 00140000 00400000 /* RO */
+- 00540000 039c0000 /* RO */
+- 03f00000 00100000>; /* RO */
++ partitions = <0x00000000 0x00100000 /* RO */
++ 0x00100000 0x00040001 /* RW */
++ 0x00140000 0x00400000 /* RO */
++ 0x00540000 0x039c0000 /* RO */
++ 0x03f00000 0x00100000>; /* RO */
+ partition-names = "FW Image A", "FW Config Data", "Kernel Image", "Filesystem", "FW Image B";
+ };
+
+@@ -72,171 +74,153 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ device_type = "mdio";
+- compatible = "marvell,mv64x60-mdio";
+- ethernet-phy at 1 {
++ compatible = "marvell,mv64360-mdio";
++ PHY0: ethernet-phy at 1 {
+ device_type = "ethernet-phy";
+ compatible = "broadcom,bcm5421";
+- interrupts = <4c>; /* GPP 12 */
+- interrupt-parent = <&/mv64x60/pic>;
++ interrupts = <76>; /* GPP 12 */
++ interrupt-parent = <&PIC>;
+ reg = <1>;
+ };
+- ethernet-phy at 3 {
++ PHY1: ethernet-phy at 3 {
+ device_type = "ethernet-phy";
+ compatible = "broadcom,bcm5421";
+- interrupts = <4c>; /* GPP 12 */
+- interrupt-parent = <&/mv64x60/pic>;
++ interrupts = <76>; /* GPP 12 */
++ interrupt-parent = <&PIC>;
+ reg = <3>;
+ };
+ };
+
+- ethernet at 2000 {
+- reg = <2000 2000>;
+- eth0 {
++ ethernet-group at 2000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "marvell,mv64360-eth-group";
++ reg = <0x2000 0x2000>;
++ ethernet at 0 {
+ device_type = "network";
+- compatible = "marvell,mv64x60-eth";
+- block-index = <0>;
+- interrupts = <20>;
+- interrupt-parent = <&/mv64x60/pic>;
+- phy = <&/mv64x60/mdio/ethernet-phy at 1>;
++ compatible = "marvell,mv64360-eth";
++ reg = <0>;
++ interrupts = <32>;
++ interrupt-parent = <&PIC>;
++ phy = <&PHY0>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+- eth1 {
++ ethernet at 1 {
+ device_type = "network";
+- compatible = "marvell,mv64x60-eth";
+- block-index = <1>;
+- interrupts = <21>;
+- interrupt-parent = <&/mv64x60/pic>;
+- phy = <&/mv64x60/mdio/ethernet-phy at 3>;
++ compatible = "marvell,mv64360-eth";
++ reg = <1>;
++ interrupts = <33>;
++ interrupt-parent = <&PIC>;
++ phy = <&PHY1>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ };
+ };
+
+- sdma at 4000 {
+- device_type = "dma";
+- compatible = "marvell,mv64x60-sdma";
+- reg = <4000 c18>;
+- virtual-reg = <f1004000>;
+- interrupt-base = <0>;
+- interrupts = <24>;
+- interrupt-parent = <&/mv64x60/pic>;
++ SDMA0: sdma at 4000 {
++ compatible = "marvell,mv64360-sdma";
++ reg = <0x4000 0xc18>;
++ virtual-reg = <0xf1004000>;
++ interrupts = <36>;
++ interrupt-parent = <&PIC>;
+ };
+
+- sdma at 6000 {
+- device_type = "dma";
+- compatible = "marvell,mv64x60-sdma";
+- reg = <6000 c18>;
+- virtual-reg = <f1006000>;
+- interrupt-base = <0>;
+- interrupts = <26>;
+- interrupt-parent = <&/mv64x60/pic>;
++ SDMA1: sdma at 6000 {
++ compatible = "marvell,mv64360-sdma";
++ reg = <0x6000 0xc18>;
++ virtual-reg = <0xf1006000>;
++ interrupts = <38>;
++ interrupt-parent = <&PIC>;
+ };
+
+- brg at b200 {
+- compatible = "marvell,mv64x60-brg";
+- reg = <b200 8>;
++ BRG0: brg at b200 {
++ compatible = "marvell,mv64360-brg";
++ reg = <0xb200 0x8>;
+ clock-src = <8>;
+- clock-frequency = <7ed6b40>;
+- current-speed = <2580>;
+- bcr = <0>;
++ clock-frequency = <133333333>;
++ current-speed = <9600>;
+ };
+
+- brg at b208 {
+- compatible = "marvell,mv64x60-brg";
+- reg = <b208 8>;
++ BRG1: brg at b208 {
++ compatible = "marvell,mv64360-brg";
++ reg = <0xb208 0x8>;
+ clock-src = <8>;
+- clock-frequency = <7ed6b40>;
+- current-speed = <2580>;
+- bcr = <0>;
++ clock-frequency = <133333333>;
++ current-speed = <9600>;
+ };
+
+- cunit at f200 {
+- reg = <f200 200>;
++ CUNIT: cunit at f200 {
++ reg = <0xf200 0x200>;
+ };
+
+- mpscrouting at b400 {
+- reg = <b400 c>;
++ MPSCROUTING: mpscrouting at b400 {
++ reg = <0xb400 0xc>;
+ };
+
+- mpscintr at b800 {
+- reg = <b800 100>;
+- virtual-reg = <f100b800>;
++ MPSCINTR: mpscintr at b800 {
++ reg = <0xb800 0x100>;
++ virtual-reg = <0xf100b800>;
+ };
+
+- mpsc at 8000 {
++ MPSC0: mpsc at 8000 {
+ device_type = "serial";
+- compatible = "marvell,mpsc";
+- reg = <8000 38>;
+- virtual-reg = <f1008000>;
+- sdma = <&/mv64x60/sdma at 4000>;
+- brg = <&/mv64x60/brg at b200>;
+- cunit = <&/mv64x60/cunit at f200>;
+- mpscrouting = <&/mv64x60/mpscrouting at b400>;
+- mpscintr = <&/mv64x60/mpscintr at b800>;
+- block-index = <0>;
+- max_idle = <28>;
+- chr_1 = <0>;
+- chr_2 = <0>;
+- chr_10 = <3>;
+- mpcr = <0>;
+- interrupts = <28>;
+- interrupt-parent = <&/mv64x60/pic>;
++ compatible = "marvell,mv64360-mpsc";
++ reg = <0x8000 0x38>;
++ virtual-reg = <0xf1008000>;
++ sdma = <&SDMA0>;
++ brg = <&BRG0>;
++ cunit = <&CUNIT>;
++ mpscrouting = <&MPSCROUTING>;
++ mpscintr = <&MPSCINTR>;
++ cell-index = <0>;
++ interrupts = <40>;
++ interrupt-parent = <&PIC>;
+ };
+
+- mpsc at 9000 {
++ MPSC1: mpsc at 9000 {
+ device_type = "serial";
+- compatible = "marvell,mpsc";
+- reg = <9000 38>;
+- virtual-reg = <f1009000>;
+- sdma = <&/mv64x60/sdma at 6000>;
+- brg = <&/mv64x60/brg at b208>;
+- cunit = <&/mv64x60/cunit at f200>;
+- mpscrouting = <&/mv64x60/mpscrouting at b400>;
+- mpscintr = <&/mv64x60/mpscintr at b800>;
+- block-index = <1>;
+- max_idle = <28>;
+- chr_1 = <0>;
+- chr_2 = <0>;
+- chr_10 = <3>;
+- mpcr = <0>;
+- interrupts = <2a>;
+- interrupt-parent = <&/mv64x60/pic>;
++ compatible = "marvell,mv64360-mpsc";
++ reg = <0x9000 0x38>;
++ virtual-reg = <0xf1009000>;
++ sdma = <&SDMA1>;
++ brg = <&BRG1>;
++ cunit = <&CUNIT>;
++ mpscrouting = <&MPSCROUTING>;
++ mpscintr = <&MPSCINTR>;
++ cell-index = <1>;
++ interrupts = <42>;
++ interrupt-parent = <&PIC>;
+ };
+
+ wdt at b410 { /* watchdog timer */
+- compatible = "marvell,mv64x60-wdt";
+- reg = <b410 8>;
+- timeout = <a>; /* wdt timeout in seconds */
++ compatible = "marvell,mv64360-wdt";
++ reg = <0xb410 0x8>;
+ };
+
+ i2c at c000 {
+ device_type = "i2c";
+- compatible = "marvell,mv64x60-i2c";
+- reg = <c000 20>;
+- virtual-reg = <f100c000>;
+- freq_m = <8>;
+- freq_n = <3>;
+- timeout = <3e8>; /* 1000 = 1 second */
+- retries = <1>;
+- interrupts = <25>;
+- interrupt-parent = <&/mv64x60/pic>;
++ compatible = "marvell,mv64360-i2c";
++ reg = <0xc000 0x20>;
++ virtual-reg = <0xf100c000>;
++ interrupts = <37>;
++ interrupt-parent = <&PIC>;
+ };
+
+- pic {
++ PIC: pic {
+ #interrupt-cells = <1>;
+ #address-cells = <0>;
+- compatible = "marvell,mv64x60-pic";
+- reg = <0000 88>;
++ compatible = "marvell,mv64360-pic";
++ reg = <0x0 0x88>;
+ interrupt-controller;
+ };
+
+ mpp at f000 {
+- compatible = "marvell,mv64x60-mpp";
+- reg = <f000 10>;
++ compatible = "marvell,mv64360-mpp";
++ reg = <0xf000 0x10>;
+ };
+
+ gpp at f100 {
+- compatible = "marvell,mv64x60-gpp";
+- reg = <f100 20>;
++ compatible = "marvell,mv64360-gpp";
++ reg = <0xf100 0x20>;
+ };
+
+ pci at 80000000 {
+@@ -244,73 +228,75 @@
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ device_type = "pci";
+- compatible = "marvell,mv64x60-pci";
+- reg = <0cf8 8>;
+- ranges = <01000000 0 0 88000000 0 01000000
+- 02000000 0 80000000 80000000 0 08000000>;
+- bus-range = <0 ff>;
+- clock-frequency = <3EF1480>;
+- interrupt-pci-iack = <0c34>;
+- interrupt-parent = <&/mv64x60/pic>;
+- interrupt-map-mask = <f800 0 0 7>;
++ compatible = "marvell,mv64360-pci";
++ reg = <0xcf8 0x8>;
++ ranges = <0x01000000 0x0 0x0
++ 0x88000000 0x0 0x01000000
++ 0x02000000 0x0 0x80000000
++ 0x80000000 0x0 0x08000000>;
++ bus-range = <0 255>;
++ clock-frequency = <66000000>;
++ interrupt-pci-iack = <0xc34>;
++ interrupt-parent = <&PIC>;
++ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ /* IDSEL 0x0a */
+- 5000 0 0 1 &/mv64x60/pic 50
+- 5000 0 0 2 &/mv64x60/pic 51
+- 5000 0 0 3 &/mv64x60/pic 5b
+- 5000 0 0 4 &/mv64x60/pic 5d
++ 0x5000 0 0 1 &PIC 80
++ 0x5000 0 0 2 &PIC 81
++ 0x5000 0 0 3 &PIC 91
++ 0x5000 0 0 4 &PIC 93
+
+ /* IDSEL 0x0b */
+- 5800 0 0 1 &/mv64x60/pic 5b
+- 5800 0 0 2 &/mv64x60/pic 5d
+- 5800 0 0 3 &/mv64x60/pic 50
+- 5800 0 0 4 &/mv64x60/pic 51
++ 0x5800 0 0 1 &PIC 91
++ 0x5800 0 0 2 &PIC 93
++ 0x5800 0 0 3 &PIC 80
++ 0x5800 0 0 4 &PIC 81
+
+ /* IDSEL 0x0c */
+- 6000 0 0 1 &/mv64x60/pic 5b
+- 6000 0 0 2 &/mv64x60/pic 5d
+- 6000 0 0 3 &/mv64x60/pic 50
+- 6000 0 0 4 &/mv64x60/pic 51
++ 0x6000 0 0 1 &PIC 91
++ 0x6000 0 0 2 &PIC 93
++ 0x6000 0 0 3 &PIC 80
++ 0x6000 0 0 4 &PIC 81
+
+ /* IDSEL 0x0d */
+- 6800 0 0 1 &/mv64x60/pic 5d
+- 6800 0 0 2 &/mv64x60/pic 50
+- 6800 0 0 3 &/mv64x60/pic 51
+- 6800 0 0 4 &/mv64x60/pic 5b
++ 0x6800 0 0 1 &PIC 93
++ 0x6800 0 0 2 &PIC 80
++ 0x6800 0 0 3 &PIC 81
++ 0x6800 0 0 4 &PIC 91
+ >;
+ };
+
+ cpu-error at 0070 {
+- compatible = "marvell,mv64x60-cpu-error";
+- reg = <0070 10 0128 28>;
+- interrupts = <03>;
+- interrupt-parent = <&/mv64x60/pic>;
++ compatible = "marvell,mv64360-cpu-error";
++ reg = <0x70 0x10 0x128 0x28>;
++ interrupts = <3>;
++ interrupt-parent = <&PIC>;
+ };
+
+ sram-ctrl at 0380 {
+- compatible = "marvell,mv64x60-sram-ctrl";
+- reg = <0380 80>;
+- interrupts = <0d>;
+- interrupt-parent = <&/mv64x60/pic>;
++ compatible = "marvell,mv64360-sram-ctrl";
++ reg = <0x380 0x80>;
++ interrupts = <13>;
++ interrupt-parent = <&PIC>;
+ };
+
+ pci-error at 1d40 {
+- compatible = "marvell,mv64x60-pci-error";
+- reg = <1d40 40 0c28 4>;
+- interrupts = <0c>;
+- interrupt-parent = <&/mv64x60/pic>;
++ compatible = "marvell,mv64360-pci-error";
++ reg = <0x1d40 0x40 0xc28 0x4>;
++ interrupts = <12>;
++ interrupt-parent = <&PIC>;
+ };
+
+ mem-ctrl at 1400 {
+- compatible = "marvell,mv64x60-mem-ctrl";
+- reg = <1400 60>;
+- interrupts = <11>;
+- interrupt-parent = <&/mv64x60/pic>;
++ compatible = "marvell,mv64360-mem-ctrl";
++ reg = <0x1400 0x60>;
++ interrupts = <17>;
++ interrupt-parent = <&PIC>;
+ };
+ };
+
+ chosen {
+ bootargs = "ip=on";
+- linux,stdout-path = "/mv64x60 at f1000000/mpsc at 8000";
++ linux,stdout-path = &MPSC0;
+ };
+ };
+diff --git a/arch/powerpc/boot/dts/rainier.dts b/arch/powerpc/boot/dts/rainier.dts
+index f947c75..6a8fa70 100644
+--- a/arch/powerpc/boot/dts/rainier.dts
++++ b/arch/powerpc/boot/dts/rainier.dts
+@@ -254,7 +254,6 @@
+ };
+
+ EMAC0: ethernet at ef600e00 {
+- linux,network-index = <0>;
+ device_type = "network";
+ compatible = "ibm,emac-440grx", "ibm,emac-440epx", "ibm,emac4";
+ interrupt-parent = <&EMAC0>;
+@@ -270,7 +269,7 @@
+ mal-tx-channel = <0>;
+ mal-rx-channel = <0>;
+ cell-index = <0>;
+- max-frame-size = <5dc>;
++ max-frame-size = <2328>;
+ rx-fifo-size = <1000>;
+ tx-fifo-size = <800>;
+ phy-mode = "rgmii";
+@@ -284,7 +283,6 @@
+ };
+
+ EMAC1: ethernet at ef600f00 {
+- linux,network-index = <1>;
+ device_type = "network";
+ compatible = "ibm,emac-440grx", "ibm,emac-440epx", "ibm,emac4";
+ interrupt-parent = <&EMAC1>;
+@@ -300,7 +298,7 @@
+ mal-tx-channel = <1>;
+ mal-rx-channel = <1>;
+ cell-index = <1>;
+- max-frame-size = <5dc>;
++ max-frame-size = <2328>;
+ rx-fifo-size = <1000>;
+ tx-fifo-size = <800>;
+ phy-mode = "rgmii";
+diff --git a/arch/powerpc/boot/dts/sbc8641d.dts b/arch/powerpc/boot/dts/sbc8641d.dts
+new file mode 100644
+index 0000000..3eebeec
+--- /dev/null
++++ b/arch/powerpc/boot/dts/sbc8641d.dts
+@@ -0,0 +1,352 @@
++/*
++ * SBC8641D Device Tree Source
++ *
++ * Copyright 2008 Wind River Systems Inc.
++ *
++ * Paul Gortmaker (see MAINTAINERS for contact information)
++ *
++ * Based largely on the mpc8641_hpcn.dts by Freescale Semiconductor Inc.
++ *
++ * 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.
++ */
++
++/dts-v1/;
++
++/ {
++ model = "SBC8641D";
++ compatible = "wind,sbc8641";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ aliases {
++ ethernet0 = &enet0;
++ ethernet1 = &enet1;
++ ethernet2 = &enet2;
++ ethernet3 = &enet3;
++ serial0 = &serial0;
++ serial1 = &serial1;
++ pci0 = &pci0;
++ pci1 = &pci1;
++ };
++
++ cpus {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ PowerPC,8641 at 0 {
++ device_type = "cpu";
++ reg = <0>;
++ d-cache-line-size = <32>;
++ i-cache-line-size = <32>;
++ d-cache-size = <32768>; // L1
++ i-cache-size = <32768>; // L1
++ timebase-frequency = <0>; // From uboot
++ bus-frequency = <0>; // From uboot
++ clock-frequency = <0>; // From uboot
++ };
++ PowerPC,8641 at 1 {
++ device_type = "cpu";
++ reg = <1>;
++ d-cache-line-size = <32>;
++ i-cache-line-size = <32>;
++ d-cache-size = <32768>;
++ i-cache-size = <32768>;
++ timebase-frequency = <0>; // From uboot
++ bus-frequency = <0>; // From uboot
++ clock-frequency = <0>; // From uboot
++ };
++ };
++
++ memory {
++ device_type = "memory";
++ reg = <0x00000000 0x20000000>; // 512M at 0x0
++ };
++
++ localbus at f8005000 {
++ #address-cells = <2>;
++ #size-cells = <1>;
++ compatible = "fsl,mpc8641-localbus", "simple-bus";
++ reg = <0xf8005000 0x1000>;
++ interrupts = <19 2>;
++ interrupt-parent = <&mpic>;
++
++ ranges = <0 0 0xff000000 0x01000000 // 16MB Boot flash
++ 1 0 0xf0000000 0x00010000 // 64KB EEPROM
++ 2 0 0xf1000000 0x00100000 // EPLD (1MB)
++ 3 0 0xe0000000 0x04000000 // 64MB LB SDRAM (CS3)
++ 4 0 0xe4000000 0x04000000 // 64MB LB SDRAM (CS4)
++ 6 0 0xf4000000 0x00100000 // LCD display (1MB)
++ 7 0 0xe8000000 0x04000000>; // 64MB OneNAND
++
++ flash at 0,0 {
++ compatible = "cfi-flash";
++ reg = <0 0 0x01000000>;
++ bank-width = <2>;
++ device-width = <2>;
++ #address-cells = <1>;
++ #size-cells = <1>;
++ partition at 0 {
++ label = "dtb";
++ reg = <0x00000000 0x00100000>;
++ read-only;
++ };
++ partition at 300000 {
++ label = "kernel";
++ reg = <0x00100000 0x00400000>;
++ read-only;
++ };
++ partition at 400000 {
++ label = "fs";
++ reg = <0x00500000 0x00a00000>;
++ };
++ partition at 700000 {
++ label = "firmware";
++ reg = <0x00f00000 0x00100000>;
++ read-only;
++ };
++ };
++
++ epld at 2,0 {
++ compatible = "wrs,epld-localbus";
++ #address-cells = <2>;
++ #size-cells = <1>;
++ reg = <2 0 0x100000>;
++ ranges = <0 0 5 0 1 // User switches
++ 1 0 5 1 1 // Board ID/Rev
++ 3 0 5 3 1>; // LEDs
++ };
++ };
++
++ soc at f8000000 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ device_type = "soc";
++ compatible = "simple-bus";
++ ranges = <0x00000000 0xf8000000 0x00100000>;
++ reg = <0xf8000000 0x00001000>; // CCSRBAR
++ bus-frequency = <0>;
++
++ i2c at 3000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ cell-index = <0>;
++ compatible = "fsl-i2c";
++ reg = <0x3000 0x100>;
++ interrupts = <43 2>;
++ interrupt-parent = <&mpic>;
++ dfsrr;
++ };
++
++ i2c at 3100 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ cell-index = <1>;
++ compatible = "fsl-i2c";
++ reg = <0x3100 0x100>;
++ interrupts = <43 2>;
++ interrupt-parent = <&mpic>;
++ dfsrr;
++ };
++
++ mdio at 24520 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "fsl,gianfar-mdio";
++ reg = <0x24520 0x20>;
++
++ phy0: ethernet-phy at 1f {
++ interrupt-parent = <&mpic>;
++ interrupts = <10 1>;
++ reg = <0x1f>;
++ device_type = "ethernet-phy";
++ };
++ phy1: ethernet-phy at 0 {
++ interrupt-parent = <&mpic>;
++ interrupts = <10 1>;
++ reg = <0>;
++ device_type = "ethernet-phy";
++ };
++ phy2: ethernet-phy at 1 {
++ interrupt-parent = <&mpic>;
++ interrupts = <10 1>;
++ reg = <1>;
++ device_type = "ethernet-phy";
++ };
++ phy3: ethernet-phy at 2 {
++ interrupt-parent = <&mpic>;
++ interrupts = <10 1>;
++ reg = <2>;
++ device_type = "ethernet-phy";
++ };
++ };
++
++ enet0: ethernet at 24000 {
++ cell-index = <0>;
++ device_type = "network";
++ model = "TSEC";
++ compatible = "gianfar";
++ reg = <0x24000 0x1000>;
++ local-mac-address = [ 00 00 00 00 00 00 ];
++ interrupts = <29 2 30 2 34 2>;
++ interrupt-parent = <&mpic>;
++ phy-handle = <&phy0>;
++ phy-connection-type = "rgmii-id";
++ };
++
++ enet1: ethernet at 25000 {
++ cell-index = <1>;
++ device_type = "network";
++ model = "TSEC";
++ compatible = "gianfar";
++ reg = <0x25000 0x1000>;
++ local-mac-address = [ 00 00 00 00 00 00 ];
++ interrupts = <35 2 36 2 40 2>;
++ interrupt-parent = <&mpic>;
++ phy-handle = <&phy1>;
++ phy-connection-type = "rgmii-id";
++ };
++
++ enet2: ethernet at 26000 {
++ cell-index = <2>;
++ device_type = "network";
++ model = "TSEC";
++ compatible = "gianfar";
++ reg = <0x26000 0x1000>;
++ local-mac-address = [ 00 00 00 00 00 00 ];
++ interrupts = <31 2 32 2 33 2>;
++ interrupt-parent = <&mpic>;
++ phy-handle = <&phy2>;
++ phy-connection-type = "rgmii-id";
++ };
++
++ enet3: ethernet at 27000 {
++ cell-index = <3>;
++ device_type = "network";
++ model = "TSEC";
++ compatible = "gianfar";
++ reg = <0x27000 0x1000>;
++ local-mac-address = [ 00 00 00 00 00 00 ];
++ interrupts = <37 2 38 2 39 2>;
++ interrupt-parent = <&mpic>;
++ phy-handle = <&phy3>;
++ phy-connection-type = "rgmii-id";
++ };
++
++ serial0: serial at 4500 {
++ cell-index = <0>;
++ device_type = "serial";
++ compatible = "ns16550";
++ reg = <0x4500 0x100>;
++ clock-frequency = <0>;
++ interrupts = <42 2>;
++ interrupt-parent = <&mpic>;
++ };
++
++ serial1: serial at 4600 {
++ cell-index = <1>;
++ device_type = "serial";
++ compatible = "ns16550";
++ reg = <0x4600 0x100>;
++ clock-frequency = <0>;
++ interrupts = <28 2>;
++ interrupt-parent = <&mpic>;
++ };
++
++ mpic: pic at 40000 {
++ clock-frequency = <0>;
++ interrupt-controller;
++ #address-cells = <0>;
++ #interrupt-cells = <2>;
++ reg = <0x40000 0x40000>;
++ compatible = "chrp,open-pic";
++ device_type = "open-pic";
++ big-endian;
++ };
++
++ global-utilities at e0000 {
++ compatible = "fsl,mpc8641-guts";
++ reg = <0xe0000 0x1000>;
++ fsl,has-rstcr;
++ };
++ };
++
++ pci0: pcie at f8008000 {
++ cell-index = <0>;
++ compatible = "fsl,mpc8641-pcie";
++ device_type = "pci";
++ #interrupt-cells = <1>;
++ #size-cells = <2>;
++ #address-cells = <3>;
++ reg = <0xf8008000 0x1000>;
++ bus-range = <0x0 0xff>;
++ ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x20000000
++ 0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
++ clock-frequency = <33333333>;
++ interrupt-parent = <&mpic>;
++ interrupts = <24 2>;
++ interrupt-map-mask = <0xff00 0 0 7>;
++ interrupt-map = <
++ /* IDSEL 0x0 */
++ 0x0000 0 0 1 &mpic 0 1
++ 0x0000 0 0 2 &mpic 1 1
++ 0x0000 0 0 3 &mpic 2 1
++ 0x0000 0 0 4 &mpic 3 1
++ >;
++
++ pcie at 0 {
++ reg = <0 0 0 0 0>;
++ #size-cells = <2>;
++ #address-cells = <3>;
++ device_type = "pci";
++ ranges = <0x02000000 0x0 0x80000000
++ 0x02000000 0x0 0x80000000
++ 0x0 0x20000000
++
++ 0x01000000 0x0 0x00000000
++ 0x01000000 0x0 0x00000000
++ 0x0 0x00100000>;
++ };
++
++ };
++
++ pci1: pcie at f8009000 {
++ cell-index = <1>;
++ compatible = "fsl,mpc8641-pcie";
++ device_type = "pci";
++ #interrupt-cells = <1>;
++ #size-cells = <2>;
++ #address-cells = <3>;
++ reg = <0xf8009000 0x1000>;
++ bus-range = <0 0xff>;
++ ranges = <0x02000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
++ 0x01000000 0x0 0x00000000 0xe3000000 0x0 0x00100000>;
++ clock-frequency = <33333333>;
++ interrupt-parent = <&mpic>;
++ interrupts = <25 2>;
++ interrupt-map-mask = <0xf800 0 0 7>;
++ interrupt-map = <
++ /* IDSEL 0x0 */
++ 0x0000 0 0 1 &mpic 4 1
++ 0x0000 0 0 2 &mpic 5 1
++ 0x0000 0 0 3 &mpic 6 1
++ 0x0000 0 0 4 &mpic 7 1
++ >;
++
++ pcie at 0 {
++ reg = <0 0 0 0 0>;
++ #size-cells = <2>;
++ #address-cells = <3>;
++ device_type = "pci";
++ ranges = <0x02000000 0x0 0xa0000000
++ 0x02000000 0x0 0xa0000000
++ 0x0 0x20000000
++
++ 0x01000000 0x0 0x00000000
++ 0x01000000 0x0 0x00000000
++ 0x0 0x00100000>;
++ };
++ };
++};
+diff --git a/arch/powerpc/boot/dts/sequoia.dts b/arch/powerpc/boot/dts/sequoia.dts
+index 8db9515..a1ae4d6 100644
+--- a/arch/powerpc/boot/dts/sequoia.dts
++++ b/arch/powerpc/boot/dts/sequoia.dts
+@@ -269,7 +269,6 @@
+ };
+
+ EMAC0: ethernet at ef600e00 {
+- linux,network-index = <0>;
+ device_type = "network";
+ compatible = "ibm,emac-440epx", "ibm,emac4";
+ interrupt-parent = <&EMAC0>;
+@@ -285,7 +284,7 @@
+ mal-tx-channel = <0>;
+ mal-rx-channel = <0>;
+ cell-index = <0>;
+- max-frame-size = <5dc>;
++ max-frame-size = <2328>;
+ rx-fifo-size = <1000>;
+ tx-fifo-size = <800>;
+ phy-mode = "rgmii";
+@@ -299,7 +298,6 @@
+ };
+
+ EMAC1: ethernet at ef600f00 {
+- linux,network-index = <1>;
+ device_type = "network";
+ compatible = "ibm,emac-440epx", "ibm,emac4";
+ interrupt-parent = <&EMAC1>;
+@@ -315,7 +313,7 @@
+ mal-tx-channel = <1>;
+ mal-rx-channel = <1>;
+ cell-index = <1>;
+- max-frame-size = <5dc>;
++ max-frame-size = <2328>;
+ rx-fifo-size = <1000>;
+ tx-fifo-size = <800>;
+ phy-mode = "rgmii";
+diff --git a/arch/powerpc/boot/dts/taishan.dts b/arch/powerpc/boot/dts/taishan.dts
+index 8278068..e808e1c 100644
+--- a/arch/powerpc/boot/dts/taishan.dts
++++ b/arch/powerpc/boot/dts/taishan.dts
+@@ -104,6 +104,16 @@
+ // FIXME: anything else?
+ };
+
++ L2C0: l2c {
++ compatible = "ibm,l2-cache-440gx", "ibm,l2-cache";
++ dcr-reg = <20 8 /* Internal SRAM DCR's */
++ 30 8>; /* L2 cache DCR's */
++ cache-line-size = <20>; /* 32 bytes */
++ cache-size = <40000>; /* L2, 256K */
++ interrupt-parent = <&UIC2>;
++ interrupts = <17 1>;
++ };
++
+ plb {
+ compatible = "ibm,plb-440gx", "ibm,plb4";
+ #address-cells = <2>;
+@@ -232,10 +242,18 @@
+ reg = <40000790 8>;
+ };
+
++ TAH0: emac-tah at 40000b50 {
++ compatible = "ibm,tah-440gx", "ibm,tah";
++ reg = <40000b50 30>;
++ };
++
++ TAH1: emac-tah at 40000d50 {
++ compatible = "ibm,tah-440gx", "ibm,tah";
++ reg = <40000d50 30>;
++ };
+
+ EMAC0: ethernet at 40000800 {
+ unused = <1>;
+- linux,network-index = <2>;
+ device_type = "network";
+ compatible = "ibm,emac-440gx", "ibm,emac4";
+ interrupt-parent = <&UIC1>;
+@@ -256,7 +274,6 @@
+ };
+ EMAC1: ethernet at 40000900 {
+ unused = <1>;
+- linux,network-index = <3>;
+ device_type = "network";
+ compatible = "ibm,emac-440gx", "ibm,emac4";
+ interrupt-parent = <&UIC1>;
+@@ -277,7 +294,6 @@
+ };
+
+ EMAC2: ethernet at 40000c00 {
+- linux,network-index = <0>;
+ device_type = "network";
+ compatible = "ibm,emac-440gx", "ibm,emac4";
+ interrupt-parent = <&UIC2>;
+@@ -288,7 +304,7 @@
+ mal-tx-channel = <2>;
+ mal-rx-channel = <2>;
+ cell-index = <2>;
+- max-frame-size = <5dc>;
++ max-frame-size = <2328>;
+ rx-fifo-size = <1000>;
+ tx-fifo-size = <800>;
+ phy-mode = "rgmii";
+@@ -297,10 +313,11 @@
+ rgmii-channel = <0>;
+ zmii-device = <&ZMII0>;
+ zmii-channel = <2>;
++ tah-device = <&TAH0>;
++ tah-channel = <0>;
+ };
+
+ EMAC3: ethernet at 40000e00 {
+- linux,network-index = <1>;
+ device_type = "network";
+ compatible = "ibm,emac-440gx", "ibm,emac4";
+ interrupt-parent = <&UIC2>;
+@@ -311,7 +328,7 @@
+ mal-tx-channel = <3>;
+ mal-rx-channel = <3>;
+ cell-index = <3>;
+- max-frame-size = <5dc>;
++ max-frame-size = <2328>;
+ rx-fifo-size = <1000>;
+ tx-fifo-size = <800>;
+ phy-mode = "rgmii";
+@@ -320,6 +337,8 @@
+ rgmii-channel = <1>;
+ zmii-device = <&ZMII0>;
+ zmii-channel = <3>;
++ tah-device = <&TAH1>;
++ tah-channel = <0>;
+ };
+
+
+diff --git a/arch/powerpc/boot/dts/walnut.dts b/arch/powerpc/boot/dts/walnut.dts
+index dcc21b0..a328607 100644
+--- a/arch/powerpc/boot/dts/walnut.dts
++++ b/arch/powerpc/boot/dts/walnut.dts
+@@ -125,7 +125,6 @@
+ };
+
+ EMAC: ethernet at ef600800 {
+- linux,network-index = <0>;
+ device_type = "network";
+ compatible = "ibm,emac-405gp", "ibm,emac";
+ interrupt-parent = <&UIC0>;
+diff --git a/arch/powerpc/boot/dts/warp.dts b/arch/powerpc/boot/dts/warp.dts
+index dc1499d..b04a52e 100644
+--- a/arch/powerpc/boot/dts/warp.dts
++++ b/arch/powerpc/boot/dts/warp.dts
+@@ -204,7 +204,6 @@
+ };
+
+ EMAC0: ethernet at ef600e00 {
+- linux,network-index = <0>;
+ device_type = "network";
+ compatible = "ibm,emac-440ep", "ibm,emac-440gp", "ibm,emac";
+ interrupt-parent = <&UIC1>;
+diff --git a/arch/powerpc/boot/dts/yosemite.dts b/arch/powerpc/boot/dts/yosemite.dts
+new file mode 100644
+index 0000000..0d6d332
+--- /dev/null
++++ b/arch/powerpc/boot/dts/yosemite.dts
+@@ -0,0 +1,304 @@
++/*
++ * Device Tree Source for AMCC Yosemite
++ *
++ * Copyright 2008 IBM Corp.
++ * Josh Boyer <jwboyer at linux.vnet.ibm.com>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without
++ * any warranty of any kind, whether express or implied.
++ */
++
++/ {
++ #address-cells = <2>;
++ #size-cells = <1>;
++ model = "amcc,yosemite";
++ compatible = "amcc,yosemite","amcc,bamboo";
++ dcr-parent = <&/cpus/cpu at 0>;
++
++ aliases {
++ ethernet0 = &EMAC0;
++ ethernet1 = &EMAC1;
++ serial0 = &UART0;
++ serial1 = &UART1;
++ serial2 = &UART2;
++ serial3 = &UART3;
++ };
++
++ cpus {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ cpu at 0 {
++ device_type = "cpu";
++ model = "PowerPC,440EP";
++ reg = <0>;
++ clock-frequency = <0>; /* Filled in by zImage */
++ timebase-frequency = <0>; /* Filled in by zImage */
++ i-cache-line-size = <20>;
++ d-cache-line-size = <20>;
++ i-cache-size = <8000>;
++ d-cache-size = <8000>;
++ dcr-controller;
++ dcr-access-method = "native";
++ };
++ };
++
++ memory {
++ device_type = "memory";
++ reg = <0 0 0>; /* Filled in by zImage */
++ };
++
++ UIC0: interrupt-controller0 {
++ compatible = "ibm,uic-440ep","ibm,uic";
++ interrupt-controller;
++ cell-index = <0>;
++ dcr-reg = <0c0 009>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ #interrupt-cells = <2>;
++ };
++
++ UIC1: interrupt-controller1 {
++ compatible = "ibm,uic-440ep","ibm,uic";
++ interrupt-controller;
++ cell-index = <1>;
++ dcr-reg = <0d0 009>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ #interrupt-cells = <2>;
++ interrupts = <1e 4 1f 4>; /* cascade */
++ interrupt-parent = <&UIC0>;
++ };
++
++ SDR0: sdr {
++ compatible = "ibm,sdr-440ep";
++ dcr-reg = <00e 002>;
++ };
++
++ CPR0: cpr {
++ compatible = "ibm,cpr-440ep";
++ dcr-reg = <00c 002>;
++ };
++
++ plb {
++ compatible = "ibm,plb-440ep", "ibm,plb-440gp", "ibm,plb4";
++ #address-cells = <2>;
++ #size-cells = <1>;
++ ranges;
++ clock-frequency = <0>; /* Filled in by zImage */
++
++ SDRAM0: sdram {
++ compatible = "ibm,sdram-440ep", "ibm,sdram-405gp";
++ dcr-reg = <010 2>;
++ };
++
++ DMA0: dma {
++ compatible = "ibm,dma-440ep", "ibm,dma-440gp";
++ dcr-reg = <100 027>;
++ };
++
++ MAL0: mcmal {
++ compatible = "ibm,mcmal-440ep", "ibm,mcmal-440gp", "ibm,mcmal";
++ dcr-reg = <180 62>;
++ num-tx-chans = <4>;
++ num-rx-chans = <2>;
++ interrupt-parent = <&MAL0>;
++ interrupts = <0 1 2 3 4>;
++ #interrupt-cells = <1>;
++ #address-cells = <0>;
++ #size-cells = <0>;
++ interrupt-map = </*TXEOB*/ 0 &UIC0 a 4
++ /*RXEOB*/ 1 &UIC0 b 4
++ /*SERR*/ 2 &UIC1 0 4
++ /*TXDE*/ 3 &UIC1 1 4
++ /*RXDE*/ 4 &UIC1 2 4>;
++ };
++
++ POB0: opb {
++ compatible = "ibm,opb-440ep", "ibm,opb-440gp", "ibm,opb";
++ #address-cells = <1>;
++ #size-cells = <1>;
++ /* Bamboo is oddball in the 44x world and doesn't use the ERPN
++ * bits.
++ */
++ ranges = <00000000 0 00000000 80000000
++ 80000000 0 80000000 80000000>;
++ interrupt-parent = <&UIC1>;
++ interrupts = <7 4>;
++ clock-frequency = <0>; /* Filled in by zImage */
++
++ EBC0: ebc {
++ compatible = "ibm,ebc-440ep", "ibm,ebc-440gp", "ibm,ebc";
++ dcr-reg = <012 2>;
++ #address-cells = <2>;
++ #size-cells = <1>;
++ clock-frequency = <0>; /* Filled in by zImage */
++ interrupts = <5 1>;
++ interrupt-parent = <&UIC1>;
++ };
++
++ UART0: serial at ef600300 {
++ device_type = "serial";
++ compatible = "ns16550";
++ reg = <ef600300 8>;
++ virtual-reg = <ef600300>;
++ clock-frequency = <0>; /* Filled in by zImage */
++ current-speed = <1c200>;
++ interrupt-parent = <&UIC0>;
++ interrupts = <0 4>;
++ };
++
++ UART1: serial at ef600400 {
++ device_type = "serial";
++ compatible = "ns16550";
++ reg = <ef600400 8>;
++ virtual-reg = <ef600400>;
++ clock-frequency = <0>;
++ current-speed = <0>;
++ interrupt-parent = <&UIC0>;
++ interrupts = <1 4>;
++ };
++
++ UART2: serial at ef600500 {
++ device_type = "serial";
++ compatible = "ns16550";
++ reg = <ef600500 8>;
++ virtual-reg = <ef600500>;
++ clock-frequency = <0>;
++ current-speed = <0>;
++ interrupt-parent = <&UIC0>;
++ interrupts = <3 4>;
++ status = "disabled";
++ };
++
++ UART3: serial at ef600600 {
++ device_type = "serial";
++ compatible = "ns16550";
++ reg = <ef600600 8>;
++ virtual-reg = <ef600600>;
++ clock-frequency = <0>;
++ current-speed = <0>;
++ interrupt-parent = <&UIC0>;
++ interrupts = <4 4>;
++ status = "disabled";
++ };
++
++ IIC0: i2c at ef600700 {
++ compatible = "ibm,iic-440ep", "ibm,iic-440gp", "ibm,iic";
++ reg = <ef600700 14>;
++ interrupt-parent = <&UIC0>;
++ interrupts = <2 4>;
++ };
++
++ IIC1: i2c at ef600800 {
++ compatible = "ibm,iic-440ep", "ibm,iic-440gp", "ibm,iic";
++ reg = <ef600800 14>;
++ interrupt-parent = <&UIC0>;
++ interrupts = <7 4>;
++ };
++
++ spi at ef600900 {
++ compatible = "amcc,spi-440ep";
++ reg = <ef600900 6>;
++ interrupts = <8 4>;
++ interrupt-parent = <&UIC0>;
++ };
++
++ ZMII0: emac-zmii at ef600d00 {
++ compatible = "ibm,zmii-440ep", "ibm,zmii-440gp", "ibm,zmii";
++ reg = <ef600d00 c>;
++ };
++
++ EMAC0: ethernet at ef600e00 {
++ device_type = "network";
++ compatible = "ibm,emac-440ep", "ibm,emac-440gp", "ibm,emac";
++ interrupt-parent = <&UIC1>;
++ interrupts = <1c 4 1d 4>;
++ reg = <ef600e00 70>;
++ local-mac-address = [000000000000];
++ mal-device = <&MAL0>;
++ mal-tx-channel = <0 1>;
++ mal-rx-channel = <0>;
++ cell-index = <0>;
++ max-frame-size = <5dc>;
++ rx-fifo-size = <1000>;
++ tx-fifo-size = <800>;
++ phy-mode = "rmii";
++ phy-map = <00000000>;
++ zmii-device = <&ZMII0>;
++ zmii-channel = <0>;
++ };
++
++ EMAC1: ethernet at ef600f00 {
++ device_type = "network";
++ compatible = "ibm,emac-440ep", "ibm,emac-440gp", "ibm,emac";
++ interrupt-parent = <&UIC1>;
++ interrupts = <1e 4 1f 4>;
++ reg = <ef600f00 70>;
++ local-mac-address = [000000000000];
++ mal-device = <&MAL0>;
++ mal-tx-channel = <2 3>;
++ mal-rx-channel = <1>;
++ cell-index = <1>;
++ max-frame-size = <5dc>;
++ rx-fifo-size = <1000>;
++ tx-fifo-size = <800>;
++ phy-mode = "rmii";
++ phy-map = <00000000>;
++ zmii-device = <&ZMII0>;
++ zmii-channel = <1>;
++ };
++
++ usb at ef601000 {
++ compatible = "ohci-be";
++ reg = <ef601000 80>;
++ interrupts = <8 4 9 4>;
++ interrupt-parent = < &UIC1 >;
++ };
++ };
++
++ PCI0: pci at ec000000 {
++ device_type = "pci";
++ #interrupt-cells = <1>;
++ #size-cells = <2>;
++ #address-cells = <3>;
++ compatible = "ibm,plb440ep-pci", "ibm,plb-pci";
++ primary;
++ reg = <0 eec00000 8 /* Config space access */
++ 0 eed00000 4 /* IACK */
++ 0 eed00000 4 /* Special cycle */
++ 0 ef400000 40>; /* Internal registers */
++
++ /* Outbound ranges, one memory and one IO,
++ * later cannot be changed. Chip supports a second
++ * IO range but we don't use it for now
++ */
++ ranges = <02000000 0 a0000000 0 a0000000 0 20000000
++ 01000000 0 00000000 0 e8000000 0 00010000>;
++
++ /* Inbound 2GB range starting at 0 */
++ dma-ranges = <42000000 0 0 0 0 0 80000000>;
++
++ /* Bamboo has all 4 IRQ pins tied together per slot */
++ interrupt-map-mask = <f800 0 0 0>;
++ interrupt-map = <
++ /* IDSEL 1 */
++ 0800 0 0 0 &UIC0 1c 8
++
++ /* IDSEL 2 */
++ 1000 0 0 0 &UIC0 1b 8
++
++ /* IDSEL 3 */
++ 1800 0 0 0 &UIC0 1a 8
++
++ /* IDSEL 4 */
++ 2000 0 0 0 &UIC0 19 8
++ >;
++ };
++ };
++
++ chosen {
++ linux,stdout-path = "/plb/opb/serial at ef600300";
++ };
++};
+diff --git a/arch/powerpc/boot/ebony.c b/arch/powerpc/boot/ebony.c
+index f61364c..5532ab3 100644
+--- a/arch/powerpc/boot/ebony.c
++++ b/arch/powerpc/boot/ebony.c
+@@ -75,7 +75,8 @@ static void ebony_fixups(void)
+
+ ibm440gp_fixup_clocks(sysclk, 6 * 1843200);
+ ibm4xx_sdram_fixup_memsize();
+- dt_fixup_mac_addresses(ebony_mac0, ebony_mac1);
++ dt_fixup_mac_address_by_alias("ethernet0", ebony_mac0);
++ dt_fixup_mac_address_by_alias("ethernet1", ebony_mac1);
+ ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
+ ebony_flashsel_fixup();
+ }
+diff --git a/arch/powerpc/boot/libfdt-wrapper.c b/arch/powerpc/boot/libfdt-wrapper.c
+index 59016be..c541fd8 100644
+--- a/arch/powerpc/boot/libfdt-wrapper.c
++++ b/arch/powerpc/boot/libfdt-wrapper.c
+@@ -35,7 +35,7 @@
+ #define check_err(err) \
+ ({ \
+ if (BAD_ERROR(err) || ((err < 0) && DEBUG)) \
+- printf("%s():%d %s\n\r", __FUNCTION__, __LINE__, \
++ printf("%s():%d %s\n\r", __func__, __LINE__, \
+ fdt_strerror(err)); \
+ if (BAD_ERROR(err)) \
+ exit(); \
+diff --git a/arch/powerpc/boot/mpc52xx-psc.c b/arch/powerpc/boot/mpc52xx-psc.c
+index 1074626..d4cb4e4 100644
+--- a/arch/powerpc/boot/mpc52xx-psc.c
++++ b/arch/powerpc/boot/mpc52xx-psc.c
+@@ -51,14 +51,9 @@ static unsigned char psc_getc(void)
+
+ int mpc5200_psc_console_init(void *devp, struct serial_console_data *scdp)
+ {
+- int n;
+-
+ /* Get the base address of the psc registers */
+- n = getprop(devp, "virtual-reg", &psc, sizeof(psc));
+- if (n != sizeof(psc)) {
+- if (!dt_xlate_reg(devp, 0, (void *)&psc, NULL))
+- return -1;
+- }
++ if (dt_get_virtual_reg(devp, &psc, 1) < 1)
++ return -1;
+
+ scdp->open = psc_open;
+ scdp->putc = psc_putc;
+diff --git a/arch/powerpc/boot/mpsc.c b/arch/powerpc/boot/mpsc.c
+index 802ea53..425ad88 100644
+--- a/arch/powerpc/boot/mpsc.c
++++ b/arch/powerpc/boot/mpsc.c
+@@ -141,7 +141,7 @@ int mpsc_console_init(void *devp, struct serial_console_data *scdp)
+ if (mpscintr_base == NULL)
+ goto err_out;
+
+- n = getprop(devp, "block-index", &v, sizeof(v));
++ n = getprop(devp, "cell-index", &v, sizeof(v));
+ if (n != sizeof(v))
+ goto err_out;
+ reg_set = (int)v;
+diff --git a/arch/powerpc/boot/mv64x60.c b/arch/powerpc/boot/mv64x60.c
+index b432594..d9bb302 100644
+--- a/arch/powerpc/boot/mv64x60.c
++++ b/arch/powerpc/boot/mv64x60.c
+@@ -535,7 +535,7 @@ u8 *mv64x60_get_bridge_pbase(void)
+ u32 v[2];
+ void *devp;
+
+- devp = finddevice("/mv64x60");
++ devp = find_node_by_compatible(NULL, "marvell,mv64360");
+ if (devp == NULL)
+ goto err_out;
+ if (getprop(devp, "reg", v, sizeof(v)) != sizeof(v))
+@@ -553,7 +553,7 @@ u8 *mv64x60_get_bridge_base(void)
+ u32 v;
+ void *devp;
+
+- devp = finddevice("/mv64x60");
++ devp = find_node_by_compatible(NULL, "marvell,mv64360");
+ if (devp == NULL)
+ goto err_out;
+ if (getprop(devp, "virtual-reg", &v, sizeof(v)) != sizeof(v))
+diff --git a/arch/powerpc/boot/mv64x60_i2c.c b/arch/powerpc/boot/mv64x60_i2c.c
+index d085377..52a3212 100644
+--- a/arch/powerpc/boot/mv64x60_i2c.c
++++ b/arch/powerpc/boot/mv64x60_i2c.c
+@@ -185,7 +185,7 @@ int mv64x60_i2c_open(void)
+ u32 v;
+ void *devp;
+
+- devp = finddevice("/mv64x60/i2c");
++ devp = find_node_by_compatible(NULL, "marvell,mv64360-i2c");
+ if (devp == NULL)
+ goto err_out;
+ if (getprop(devp, "virtual-reg", &v, sizeof(v)) != sizeof(v))
+diff --git a/arch/powerpc/boot/ns16550.c b/arch/powerpc/boot/ns16550.c
+index f8f1b2f..8c9ead9 100644
+--- a/arch/powerpc/boot/ns16550.c
++++ b/arch/powerpc/boot/ns16550.c
+@@ -55,15 +55,14 @@ static u8 ns16550_tstc(void)
+ int ns16550_console_init(void *devp, struct serial_console_data *scdp)
+ {
+ int n;
+- unsigned long reg_phys;
++ u32 reg_offset;
+
+- n = getprop(devp, "virtual-reg", ®_base, sizeof(reg_base));
+- if (n != sizeof(reg_base)) {
+- if (!dt_xlate_reg(devp, 0, ®_phys, NULL))
+- return -1;
++ if (dt_get_virtual_reg(devp, (void **)®_base, 1) < 1)
++ return -1;
+
+- reg_base = (void *)reg_phys;
+- }
++ n = getprop(devp, "reg-offset", ®_offset, sizeof(reg_offset));
++ if (n == sizeof(reg_offset))
++ reg_base += reg_offset;
+
+ n = getprop(devp, "reg-shift", ®_shift, sizeof(reg_shift));
+ if (n != sizeof(reg_shift))
+diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h
+index 4b0544b..321e2f5 100644
+--- a/arch/powerpc/boot/ops.h
++++ b/arch/powerpc/boot/ops.h
+@@ -95,6 +95,7 @@ int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size);
+ int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr);
+ int dt_is_compatible(void *node, const char *compat);
+ void dt_get_reg_format(void *node, u32 *naddr, u32 *nsize);
++int dt_get_virtual_reg(void *node, void **addr, int nres);
+
+ static inline void *finddevice(const char *name)
+ {
+diff --git a/arch/powerpc/boot/prpmc2800.c b/arch/powerpc/boot/prpmc2800.c
+index 05c3245..da31d60 100644
+--- a/arch/powerpc/boot/prpmc2800.c
++++ b/arch/powerpc/boot/prpmc2800.c
+@@ -344,20 +344,20 @@ static void prpmc2800_bridge_setup(u32 mem_size)
+ acc_bits);
+
+ /* Get the cpu -> pci i/o & mem mappings from the device tree */
+- devp = finddevice("/mv64x60/pci at 80000000");
++ devp = find_node_by_compatible(NULL, "marvell,mv64360-pci");
+ if (devp == NULL)
+- fatal("Error: Missing /mv64x60/pci at 80000000"
++ fatal("Error: Missing marvell,mv64360-pci"
+ " device tree node\n\r");
+
+ rc = getprop(devp, "ranges", v, sizeof(v));
+ if (rc != sizeof(v))
+- fatal("Error: Can't find /mv64x60/pci at 80000000/ranges"
++ fatal("Error: Can't find marvell,mv64360-pci ranges"
+ " property\n\r");
+
+ /* Get the cpu -> pci i/o & mem mappings from the device tree */
+- devp = finddevice("/mv64x60");
++ devp = find_node_by_compatible(NULL, "marvell,mv64360");
+ if (devp == NULL)
+- fatal("Error: Missing /mv64x60 device tree node\n\r");
++ fatal("Error: Missing marvell,mv64360 device tree node\n\r");
+
+ enables = in_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE));
+ enables |= 0x0007fe00; /* Disable all cpu->pci windows */
+@@ -429,9 +429,9 @@ static void prpmc2800_fixups(void)
+ setprop(devp, "model", model, l);
+
+ /* Set /cpus/PowerPC,7447/clock-frequency */
+- devp = finddevice("/cpus/PowerPC,7447");
++ devp = find_node_by_prop_value_str(NULL, "device_type", "cpu");
+ if (devp == NULL)
+- fatal("Error: Missing proper /cpus device tree node\n\r");
++ fatal("Error: Missing proper cpu device tree node\n\r");
+ v[0] = bip->core_speed;
+ setprop(devp, "clock-frequency", &v[0], sizeof(v[0]));
+
+@@ -443,16 +443,17 @@ static void prpmc2800_fixups(void)
+ v[1] = bip->mem_size;
+ setprop(devp, "reg", v, sizeof(v));
+
+- /* Update /mv64x60/model, if this is a mv64362 */
++ /* Update model, if this is a mv64362 */
+ if (bip->bridge_type == BRIDGE_TYPE_MV64362) {
+- devp = finddevice("/mv64x60");
++ devp = find_node_by_compatible(NULL, "marvell,mv64360");
+ if (devp == NULL)
+- fatal("Error: Missing /mv64x60 device tree node\n\r");
++ fatal("Error: Missing marvell,mv64360"
++ " device tree node\n\r");
+ setprop(devp, "model", "mv64362", strlen("mv64362") + 1);
+ }
+
+ /* Set User FLASH size */
+- devp = finddevice("/mv64x60/flash at a0000000");
++ devp = find_node_by_compatible(NULL, "direct-mapped");
+ if (devp == NULL)
+ fatal("Error: Missing User FLASH device tree node\n\r");
+ rc = getprop(devp, "reg", v, sizeof(v));
+diff --git a/arch/powerpc/boot/ps3-head.S b/arch/powerpc/boot/ps3-head.S
+index a55c273..b6fcbaf 100644
+--- a/arch/powerpc/boot/ps3-head.S
++++ b/arch/powerpc/boot/ps3-head.S
+@@ -27,8 +27,9 @@
+ /*
+ * __system_reset_overlay - The PS3 first stage entry.
+ *
+- * The bootwraper build script copies the 0x100 bytes at symbol
+- * __system_reset_overlay to offset 0x100 of the rom image.
++ * The bootwraper build script copies the 512 bytes at symbol
++ * __system_reset_overlay to offset 0x100 of the rom image. This symbol
++ * must occupy 512 or less bytes.
+ *
+ * The PS3 has a single processor with two threads.
+ */
+@@ -47,8 +48,6 @@ __system_reset_overlay:
+
+ mfspr r3, 0x88
+ cntlzw. r3, r3
+- li r4, 0
+- li r5, 0
+ beq 1f
+
+ /* Secondary goes to __secondary_hold in kernel. */
+@@ -57,8 +56,14 @@ __system_reset_overlay:
+ mtctr r4
+ bctr
+
+- /* Primary delays then goes to _zimage_start in wrapper. */
+ 1:
++ /* Save the value at addr zero for a null pointer write check later. */
++
++ li r4, 0
++ lwz r3, 0(r4)
++
++ /* Primary delays then goes to _zimage_start in wrapper. */
++
+ or 31, 31, 31 /* db16cyc */
+ or 31, 31, 31 /* db16cyc */
+
+@@ -67,16 +72,18 @@ __system_reset_overlay:
+ mtctr r4
+ bctr
+
++ . = __system_reset_overlay + 512
++
+ /*
+ * __system_reset_kernel - Place holder for the kernel reset vector.
+ *
+- * The bootwrapper build script copies 0x100 bytes from offset 0x100
++ * The bootwrapper build script copies 512 bytes from offset 0x100
+ * of the rom image to the symbol __system_reset_kernel. At runtime
+- * the bootwrapper program copies the 0x100 bytes at __system_reset_kernel
+- * to ram address 0x100. This symbol must occupy 0x100 bytes.
++ * the bootwrapper program copies the 512 bytes at __system_reset_kernel
++ * to ram address 0x100. This symbol must occupy 512 bytes.
+ */
+
+ .globl __system_reset_kernel
+ __system_reset_kernel:
+
+- . = __system_reset_kernel + 0x100
++ . = __system_reset_kernel + 512
+diff --git a/arch/powerpc/boot/ps3.c b/arch/powerpc/boot/ps3.c
+index 3b0ac4d..9954d98 100644
+--- a/arch/powerpc/boot/ps3.c
++++ b/arch/powerpc/boot/ps3.c
+@@ -27,10 +27,10 @@
+ #include "page.h"
+ #include "ops.h"
+
+-extern s64 lv1_panic(u64 in_1);
+-extern s64 lv1_get_logical_partition_id(u64 *out_1);
+-extern s64 lv1_get_logical_ppe_id(u64 *out_1);
+-extern s64 lv1_get_repository_node_value(u64 in_1, u64 in_2, u64 in_3,
++extern int lv1_panic(u64 in_1);
++extern int lv1_get_logical_partition_id(u64 *out_1);
++extern int lv1_get_logical_ppe_id(u64 *out_1);
++extern int lv1_get_repository_node_value(u64 in_1, u64 in_2, u64 in_3,
+ u64 in_4, u64 in_5, u64 *out_1, u64 *out_2);
+
+ #ifdef DEBUG
+@@ -46,6 +46,7 @@ BSS_STACK(4096);
+ * edit the command line passed to vmlinux (by setting /chosen/bootargs).
+ * The buffer is put in it's own section so that tools may locate it easier.
+ */
++
+ static char cmdline[COMMAND_LINE_SIZE]
+ __attribute__((__section__("__builtin_cmdline")));
+
+@@ -75,7 +76,7 @@ static void ps3_exit(void)
+
+ static int ps3_repository_read_rm_size(u64 *rm_size)
+ {
+- s64 result;
++ int result;
+ u64 lpar_id;
+ u64 ppe_id;
+ u64 v2;
+@@ -114,16 +115,17 @@ void ps3_copy_vectors(void)
+ {
+ extern char __system_reset_kernel[];
+
+- memcpy((void *)0x100, __system_reset_kernel, 0x100);
+- flush_cache((void *)0x100, 0x100);
++ memcpy((void *)0x100, __system_reset_kernel, 512);
++ flush_cache((void *)0x100, 512);
+ }
+
+-void platform_init(void)
++void platform_init(unsigned long null_check)
+ {
+ const u32 heapsize = 0x1000000 - (u32)_end; /* 16MiB */
+ void *chosen;
+ unsigned long ft_addr;
+ u64 rm_size;
++ unsigned long val;
+
+ console_ops.write = ps3_console_write;
+ platform_ops.exit = ps3_exit;
+@@ -151,6 +153,11 @@ void platform_init(void)
+
+ printf(" flat tree at 0x%lx\n\r", ft_addr);
+
++ val = *(unsigned long *)0;
++
++ if (val != null_check)
++ printf("null check failed: %lx != %lx\n\r", val, null_check);
++
+ ((kernel_entry_t)0)(ft_addr, 0, NULL);
+
+ ps3_exit();
+diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c
+index 9960421..8b3607c 100644
+--- a/arch/powerpc/boot/serial.c
++++ b/arch/powerpc/boot/serial.c
+@@ -119,7 +119,7 @@ int serial_console_init(void)
+
+ if (dt_is_compatible(devp, "ns16550"))
+ rc = ns16550_console_init(devp, &serial_cd);
+- else if (dt_is_compatible(devp, "marvell,mpsc"))
++ else if (dt_is_compatible(devp, "marvell,mv64360-mpsc"))
+ rc = mpsc_console_init(devp, &serial_cd);
+ else if (dt_is_compatible(devp, "fsl,cpm1-scc-uart") ||
+ dt_is_compatible(devp, "fsl,cpm1-smc-uart") ||
+diff --git a/arch/powerpc/boot/simpleboot.c b/arch/powerpc/boot/simpleboot.c
+new file mode 100644
+index 0000000..86cd285
+--- /dev/null
++++ b/arch/powerpc/boot/simpleboot.c
+@@ -0,0 +1,84 @@
++/*
++ * The simple platform -- for booting when firmware doesn't supply a device
++ * tree or any platform configuration information.
++ * All data is extracted from an embedded device tree
++ * blob.
++ *
++ * Authors: Scott Wood <scottwood at freescale.com>
++ * Grant Likely <grant.likely at secretlab.ca>
++ *
++ * Copyright (c) 2007 Freescale Semiconductor, Inc.
++ * Copyright (c) 2008 Secret Lab Technologies Ltd.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ */
++
++#include "ops.h"
++#include "types.h"
++#include "io.h"
++#include "stdio.h"
++#include "libfdt/libfdt.h"
++
++BSS_STACK(4*1024);
++
++void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
++ unsigned long r6, unsigned long r7)
++{
++ const u32 *na, *ns, *reg, *timebase;
++ u64 memsize64;
++ int node, size, i;
++
++ /* Make sure FDT blob is sane */
++ if (fdt_check_header(_dtb_start) != 0)
++ fatal("Invalid device tree blob\n");
++
++ /* Find the #address-cells and #size-cells properties */
++ node = fdt_path_offset(_dtb_start, "/");
++ if (node < 0)
++ fatal("Cannot find root node\n");
++ na = fdt_getprop(_dtb_start, node, "#address-cells", &size);
++ if (!na || (size != 4))
++ fatal("Cannot find #address-cells property");
++ ns = fdt_getprop(_dtb_start, node, "#size-cells", &size);
++ if (!ns || (size != 4))
++ fatal("Cannot find #size-cells property");
++
++ /* Find the memory range */
++ node = fdt_node_offset_by_prop_value(_dtb_start, -1, "device_type",
++ "memory", sizeof("memory"));
++ if (node < 0)
++ fatal("Cannot find memory node\n");
++ reg = fdt_getprop(_dtb_start, node, "reg", &size);
++ if (size < (*na+*ns) * sizeof(u32))
++ fatal("cannot get memory range\n");
++
++ /* Only interested in memory based at 0 */
++ for (i = 0; i < *na; i++)
++ if (*reg++ != 0)
++ fatal("Memory range is not based at address 0\n");
++
++ /* get the memsize and trucate it to under 4G on 32 bit machines */
++ memsize64 = 0;
++ for (i = 0; i < *ns; i++)
++ memsize64 = (memsize64 << 32) | *reg++;
++ if (sizeof(void *) == 4 && memsize64 >= 0x100000000ULL)
++ memsize64 = 0xffffffff;
++
++ /* finally, setup the timebase */
++ node = fdt_node_offset_by_prop_value(_dtb_start, -1, "device_type",
++ "cpu", sizeof("cpu"));
++ if (!node)
++ fatal("Cannot find cpu node\n");
++ timebase = fdt_getprop(_dtb_start, node, "timebase-frequency", &size);
++ if (timebase && (size == 4))
++ timebase_period_ns = 1000000000 / *timebase;
++
++ /* Now we have the memory size; initialize the heap */
++ simple_alloc_init(_end, memsize64 - (unsigned long)_end, 32, 64);
++
++ /* prepare the device tree and find the console */
++ fdt_init(_dtb_start);
++ serial_console_init();
++}
+diff --git a/arch/powerpc/boot/treeboot-walnut.c b/arch/powerpc/boot/treeboot-walnut.c
+index 472e366..097974e 100644
+--- a/arch/powerpc/boot/treeboot-walnut.c
++++ b/arch/powerpc/boot/treeboot-walnut.c
+@@ -68,7 +68,7 @@ static void walnut_fixups(void)
+ ibm4xx_quiesce_eth((u32 *)0xef600800, NULL);
+ ibm4xx_fixup_ebc_ranges("/plb/ebc");
+ walnut_flashsel_fixup();
+- dt_fixup_mac_addresses((u8 *) WALNUT_OPENBIOS_MAC_OFF);
++ dt_fixup_mac_address_by_alias("ethernet0", (u8 *) WALNUT_OPENBIOS_MAC_OFF);
+ }
+
+ void platform_init(void)
+diff --git a/arch/powerpc/boot/virtex405-head.S b/arch/powerpc/boot/virtex405-head.S
+new file mode 100644
+index 0000000..3edb13f
+--- /dev/null
++++ b/arch/powerpc/boot/virtex405-head.S
+@@ -0,0 +1,30 @@
++#include "ppc_asm.h"
++
++ .text
++ .global _zimage_start
++_zimage_start:
++
++ /* PPC errata 213: needed by Virtex-4 FX */
++ mfccr0 0
++ oris 0,0,0x50000000 at h
++ mtccr0 0
++
++ /*
++ * Invalidate the data cache if the data cache is turned off.
++ * - The 405 core does not invalidate the data cache on power-up
++ * or reset but does turn off the data cache. We cannot assume
++ * that the cache contents are valid.
++ * - If the data cache is turned on this must have been done by
++ * a bootloader and we assume that the cache contents are
++ * valid.
++ */
++ mfdccr r9
++ cmplwi r9,0
++ bne 2f
++ lis r9,0
++ li r8,256
++ mtctr r8
++1: dccci r0,r9
++ addi r9,r9,0x20
++ bdnz 1b
++2: b _zimage_start_lib
+diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
+index 8f8b849..d6c96d9 100755
+--- a/arch/powerpc/boot/wrapper
++++ b/arch/powerpc/boot/wrapper
+@@ -174,7 +174,7 @@ cuboot*)
+ *-mpc83*)
+ platformo=$object/cuboot-83xx.o
+ ;;
+- *-tqm8541|*-mpc8560*|*-tqm8560|*-tqm8555)
++ *-tqm8541|*-mpc8560*|*-tqm8560|*-tqm8555|*-ksi8560*)
+ platformo=$object/cuboot-85xx-cpm2.o
+ ;;
+ *-mpc85*|*-tqm8540|*-sbc85*)
+@@ -199,6 +199,10 @@ adder875-redboot)
+ platformo="$object/fixed-head.o $object/redboot-8xx.o"
+ binary=y
+ ;;
++simpleboot-virtex405-*)
++ platformo="$object/virtex405-head.o $object/simpleboot.o"
++ binary=y
++ ;;
+ esac
+
+ vmz="$tmpdir/`basename \"$kernel\"`.$ext"
+@@ -226,10 +230,13 @@ if [ -n "$version" ]; then
+ uboot_version="-n Linux-$version"
+ fi
+
++# physical offset of kernel image
++membase=`${CROSS}objdump -p "$kernel" | grep -m 1 LOAD | awk '{print $7}'`
++
+ case "$platform" in
+ uboot)
+ rm -f "$ofile"
+- mkimage -A ppc -O linux -T kernel -C gzip -a 00000000 -e 00000000 \
++ mkimage -A ppc -O linux -T kernel -C gzip -a $membase -e $membase \
+ $uboot_version -d "$vmz" "$ofile"
+ if [ -z "$cacheit" ]; then
+ rm -f "$vmz"
+@@ -298,15 +305,16 @@ treeboot*)
+ exit 0
+ ;;
+ ps3)
+- # The ps3's loader supports loading gzipped binary images from flash
+- # rom to addr zero. The loader enters the image at addr 0x100. A
+- # bootwrapper overlay is use to arrange for the kernel to be loaded
+- # to addr zero and to have a suitable bootwrapper entry at 0x100.
+- # To construct the rom image, 0x100 bytes from offset 0x100 in the
+- # kernel is copied to the bootwrapper symbol __system_reset_kernel.
+- # The 0x100 bytes at the bootwrapper symbol __system_reset_overlay is
+- # then copied to offset 0x100. At runtime the bootwrapper program
+- # copies the 0x100 bytes at __system_reset_kernel to addr 0x100.
++ # The ps3's loader supports loading a gzipped binary image from flash
++ # rom to ram addr zero. The loader then enters the system reset
++ # vector at addr 0x100. A bootwrapper overlay is used to arrange for
++ # a binary image of the kernel to be at addr zero, and yet have a
++ # suitable bootwrapper entry at 0x100. To construct the final rom
++ # image 512 bytes from offset 0x100 is copied to the bootwrapper
++ # place holder at symbol __system_reset_kernel. The 512 bytes of the
++ # bootwrapper entry code at symbol __system_reset_overlay is then
++ # copied to offset 0x100. At runtime the bootwrapper program copies
++ # the data at __system_reset_kernel back to addr 0x100.
+
+ system_reset_overlay=0x`${CROSS}nm "$ofile" \
+ | grep ' __system_reset_overlay$' \
+@@ -317,7 +325,7 @@ ps3)
+ | cut -d' ' -f1`
+ system_reset_kernel=`printf "%d" $system_reset_kernel`
+ overlay_dest="256"
+- overlay_size="256"
++ overlay_size="512"
+
+ ${CROSS}objcopy -O binary "$ofile" "$ofile.bin"
+
+diff --git a/arch/powerpc/configs/40x/ep405_defconfig b/arch/powerpc/configs/40x/ep405_defconfig
+new file mode 100644
+index 0000000..e24240a
+--- /dev/null
++++ b/arch/powerpc/configs/40x/ep405_defconfig
+@@ -0,0 +1,968 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc2
++# Fri Feb 15 21:50:09 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++CONFIG_40x=y
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_4xx=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++# CONFIG_PPC4xx_PCI_EXPRESS is not set
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_EP405=y
++# CONFIG_KILAUEA is not set
++# CONFIG_MAKALU is not set
++# CONFIG_WALNUT is not set
++# CONFIG_XILINX_VIRTEX_GENERIC_BOARD is not set
++CONFIG_405GP=y
++CONFIG_IBM405_ERR77=y
++CONFIG_IBM405_ERR51=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_RCU_TRACE=y
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_MATH_EMULATION is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x00400000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++CONFIG_MTD_OF_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=m
++CONFIG_MTD_BLOCK=m
++# CONFIG_MTD_BLOCK_RO is not set
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=35000
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++CONFIG_IBM_NEW_EMAC=y
++CONFIG_IBM_NEW_EMAC_RXB=128
++CONFIG_IBM_NEW_EMAC_TXB=64
++CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
++CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
++CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
++# CONFIG_IBM_NEW_EMAC_DEBUG is not set
++CONFIG_IBM_NEW_EMAC_ZMII=y
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_THERMAL=y
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_EHCI_HCD is not set
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++CONFIG_USB_OHCI_HCD_PPC_OF=y
++CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
++CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
++CONFIG_USB_OHCI_HCD_PCI=y
++CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
++CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_UHCI_HCD is not set
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/40x/kilauea_defconfig b/arch/powerpc/configs/40x/kilauea_defconfig
+new file mode 100644
+index 0000000..2f47539
+--- /dev/null
++++ b/arch/powerpc/configs/40x/kilauea_defconfig
+@@ -0,0 +1,839 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc2
++# Fri Feb 15 21:51:43 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++CONFIG_40x=y
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_4xx=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++CONFIG_PPC4xx_PCI_EXPRESS=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++# CONFIG_EP405 is not set
++CONFIG_KILAUEA=y
++# CONFIG_MAKALU is not set
++# CONFIG_WALNUT is not set
++# CONFIG_XILINX_VIRTEX_GENERIC_BOARD is not set
++CONFIG_405EX=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_RCU_TRACE=y
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_MATH_EMULATION is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x00400000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++CONFIG_MTD_OF_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=m
++CONFIG_MTD_BLOCK=m
++# CONFIG_MTD_BLOCK_RO is not set
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=35000
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++# CONFIG_MISC_DEVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++CONFIG_IBM_NEW_EMAC=y
++CONFIG_IBM_NEW_EMAC_RXB=256
++CONFIG_IBM_NEW_EMAC_TXB=256
++CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
++CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
++CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
++# CONFIG_IBM_NEW_EMAC_DEBUG is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++CONFIG_IBM_NEW_EMAC_RGMII=y
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++CONFIG_IBM_NEW_EMAC_EMAC4=y
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_THERMAL=y
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++# CONFIG_USB_SUPPORT is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/40x/makalu_defconfig b/arch/powerpc/configs/40x/makalu_defconfig
+new file mode 100644
+index 0000000..9ef4d8a
+--- /dev/null
++++ b/arch/powerpc/configs/40x/makalu_defconfig
+@@ -0,0 +1,839 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc2
++# Fri Feb 15 21:52:30 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++CONFIG_40x=y
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_4xx=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++CONFIG_PPC4xx_PCI_EXPRESS=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++# CONFIG_EP405 is not set
++# CONFIG_KILAUEA is not set
++CONFIG_MAKALU=y
++# CONFIG_WALNUT is not set
++# CONFIG_XILINX_VIRTEX_GENERIC_BOARD is not set
++CONFIG_405EX=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_RCU_TRACE=y
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_MATH_EMULATION is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x00400000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++CONFIG_MTD_OF_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=m
++CONFIG_MTD_BLOCK=m
++# CONFIG_MTD_BLOCK_RO is not set
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=35000
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++# CONFIG_MISC_DEVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++CONFIG_IBM_NEW_EMAC=y
++CONFIG_IBM_NEW_EMAC_RXB=256
++CONFIG_IBM_NEW_EMAC_TXB=256
++CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
++CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
++CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
++# CONFIG_IBM_NEW_EMAC_DEBUG is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++CONFIG_IBM_NEW_EMAC_RGMII=y
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++CONFIG_IBM_NEW_EMAC_EMAC4=y
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_THERMAL=y
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++# CONFIG_USB_SUPPORT is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/40x/walnut_defconfig b/arch/powerpc/configs/40x/walnut_defconfig
+new file mode 100644
+index 0000000..3b2689e
+--- /dev/null
++++ b/arch/powerpc/configs/40x/walnut_defconfig
+@@ -0,0 +1,887 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc2
++# Fri Feb 15 21:54:12 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++CONFIG_40x=y
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_4xx=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++# CONFIG_PPC4xx_PCI_EXPRESS is not set
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++# CONFIG_EP405 is not set
++# CONFIG_KILAUEA is not set
++# CONFIG_MAKALU is not set
++CONFIG_WALNUT=y
++# CONFIG_XILINX_VIRTEX_GENERIC_BOARD is not set
++CONFIG_405GP=y
++CONFIG_IBM405_ERR77=y
++CONFIG_IBM405_ERR51=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++CONFIG_OF_RTC=y
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_RCU_TRACE=y
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_MATH_EMULATION is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++CONFIG_RESOURCES_64BIT=y
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++# CONFIG_PCI_LEGACY is not set
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x00400000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++CONFIG_MTD_OF_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=m
++CONFIG_MTD_BLOCK=m
++# CONFIG_MTD_BLOCK_RO is not set
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=35000
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++CONFIG_IBM_NEW_EMAC=y
++CONFIG_IBM_NEW_EMAC_RXB=128
++CONFIG_IBM_NEW_EMAC_TXB=64
++CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
++CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
++CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
++# CONFIG_IBM_NEW_EMAC_DEBUG is not set
++CONFIG_IBM_NEW_EMAC_ZMII=y
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_THERMAL=y
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/44x/bamboo_defconfig b/arch/powerpc/configs/44x/bamboo_defconfig
+new file mode 100644
+index 0000000..c44db55
+--- /dev/null
++++ b/arch/powerpc/configs/44x/bamboo_defconfig
+@@ -0,0 +1,815 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc2
++# Fri Feb 15 21:36:39 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++CONFIG_44x=y
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++CONFIG_4xx=y
++CONFIG_BOOKE=y
++CONFIG_PTE_64BIT=y
++CONFIG_PHYS_64BIT=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++# CONFIG_PPC4xx_PCI_EXPRESS is not set
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_BAMBOO=y
++# CONFIG_EBONY is not set
++# CONFIG_SEQUOIA is not set
++# CONFIG_TAISHAN is not set
++# CONFIG_KATMAI is not set
++# CONFIG_RAINIER is not set
++# CONFIG_WARP is not set
++CONFIG_440EP=y
++CONFIG_IBM440EP_ERR42=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_RCU_TRACE=y
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_MATH_EMULATION is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++CONFIG_RESOURCES_64BIT=y
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++CONFIG_CMDLINE_BOOL=y
++CONFIG_CMDLINE=""
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x01000000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=35000
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++CONFIG_IBM_NEW_EMAC=y
++CONFIG_IBM_NEW_EMAC_RXB=128
++CONFIG_IBM_NEW_EMAC_TXB=64
++CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
++CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
++CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
++# CONFIG_IBM_NEW_EMAC_DEBUG is not set
++CONFIG_IBM_NEW_EMAC_ZMII=y
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++# CONFIG_SERIAL_8250_PCI is not set
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_THERMAL=y
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++CONFIG_DEBUGGER=y
++# CONFIG_KGDB is not set
++# CONFIG_XMON is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/44x/canyonlands_defconfig b/arch/powerpc/configs/44x/canyonlands_defconfig
+new file mode 100644
+index 0000000..a3b763c
+--- /dev/null
++++ b/arch/powerpc/configs/44x/canyonlands_defconfig
+@@ -0,0 +1,721 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc1
++# Thu Feb 21 14:29:28 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++CONFIG_44x=y
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++CONFIG_4xx=y
++CONFIG_BOOKE=y
++CONFIG_PTE_64BIT=y
++CONFIG_PHYS_64BIT=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++# CONFIG_FAIR_GROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++# CONFIG_LOGBUFFER is not set
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++CONFIG_PPC4xx_PCI_EXPRESS=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++# CONFIG_BAMBOO is not set
++# CONFIG_EBONY is not set
++# CONFIG_SEQUOIA is not set
++# CONFIG_TAISHAN is not set
++# CONFIG_KATMAI is not set
++# CONFIG_RAINIER is not set
++# CONFIG_WARP is not set
++CONFIG_CANYONLANDS=y
++CONFIG_460EX=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_RCU_TRACE=y
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_MATH_EMULATION is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++CONFIG_RESOURCES_64BIT=y
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++CONFIG_CMDLINE_BOOL=y
++CONFIG_CMDLINE=""
++CONFIG_SECCOMP=y
++CONFIG_WANT_DEVICE_TREE=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x01000000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=35000
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++# CONFIG_MISC_DEVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++CONFIG_IBM_NEW_EMAC=y
++CONFIG_IBM_NEW_EMAC_RXB=256
++CONFIG_IBM_NEW_EMAC_TXB=256
++CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
++CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
++CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
++# CONFIG_IBM_NEW_EMAC_DEBUG is not set
++CONFIG_IBM_NEW_EMAC_ZMII=y
++CONFIG_IBM_NEW_EMAC_RGMII=y
++CONFIG_IBM_NEW_EMAC_TAH=y
++CONFIG_IBM_NEW_EMAC_EMAC4=y
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++# CONFIG_SERIAL_8250_PCI is not set
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++# CONFIG_USB_SUPPORT is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++CONFIG_DEBUGGER=y
++# CONFIG_KGDB is not set
++# CONFIG_XMON is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++# CONFIG_CRYPTO is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/44x/ebony_defconfig b/arch/powerpc/configs/44x/ebony_defconfig
+new file mode 100644
+index 0000000..07c8d4c
+--- /dev/null
++++ b/arch/powerpc/configs/44x/ebony_defconfig
+@@ -0,0 +1,898 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc2
++# Fri Feb 15 21:50:44 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++CONFIG_44x=y
++# CONFIG_E200 is not set
++CONFIG_4xx=y
++CONFIG_BOOKE=y
++CONFIG_PTE_64BIT=y
++CONFIG_PHYS_64BIT=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++# CONFIG_PPC4xx_PCI_EXPRESS is not set
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++# CONFIG_BAMBOO is not set
++CONFIG_EBONY=y
++# CONFIG_SEQUOIA is not set
++# CONFIG_TAISHAN is not set
++# CONFIG_KATMAI is not set
++# CONFIG_RAINIER is not set
++# CONFIG_WARP is not set
++CONFIG_440GP=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++CONFIG_OF_RTC=y
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_RCU_TRACE=y
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++CONFIG_RESOURCES_64BIT=y
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x01000000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++CONFIG_MTD_OF_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=35000
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++CONFIG_IBM_NEW_EMAC=y
++CONFIG_IBM_NEW_EMAC_RXB=128
++CONFIG_IBM_NEW_EMAC_TXB=64
++CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
++CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
++CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
++# CONFIG_IBM_NEW_EMAC_DEBUG is not set
++CONFIG_IBM_NEW_EMAC_ZMII=y
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++# CONFIG_SERIAL_8250_PCI is not set
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_THERMAL=y
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++# CONFIG_CRYPTO_HW is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/44x/katmai_defconfig b/arch/powerpc/configs/44x/katmai_defconfig
+new file mode 100644
+index 0000000..c8804ec
+--- /dev/null
++++ b/arch/powerpc/configs/44x/katmai_defconfig
+@@ -0,0 +1,790 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.24-rc6
++# Mon Dec 24 11:17:43 2007
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++CONFIG_44x=y
++# CONFIG_E200 is not set
++CONFIG_4xx=y
++CONFIG_BOOKE=y
++CONFIG_PTE_64BIT=y
++CONFIG_PHYS_64BIT=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_PPC4xx_PCI_EXPRESS=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC52xx is not set
++# CONFIG_PPC_MPC5200 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++# CONFIG_BAMBOO is not set
++# CONFIG_EBONY is not set
++# CONFIG_SEQUOIA is not set
++# CONFIG_TAISHAN is not set
++CONFIG_KATMAI=y
++# CONFIG_RAINIER is not set
++CONFIG_440SPe=y
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_CPM2 is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_MATH_EMULATION is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++CONFIG_RESOURCES_64BIT=y
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++CONFIG_CMDLINE_BOOL=y
++CONFIG_CMDLINE=""
++CONFIG_SECCOMP=y
++CONFIG_WANT_DEVICE_TREE=y
++CONFIG_DEVICE_TREE="katmai.dts"
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x01000000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=35000
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++CONFIG_MACINTOSH_DRIVERS=y
++# CONFIG_MAC_EMUMOUSEBTN is not set
++# CONFIG_WINDFARM is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_IP1000 is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++CONFIG_IBM_NEW_EMAC=y
++CONFIG_IBM_NEW_EMAC_RXB=128
++CONFIG_IBM_NEW_EMAC_TXB=64
++CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
++CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
++CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
++# CONFIG_IBM_NEW_EMAC_DEBUG is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++CONFIG_IBM_NEW_EMAC_EMAC4=y
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++# CONFIG_SERIAL_8250_PCI is not set
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++# CONFIG_UCC_SLOW is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++CONFIG_INSTRUMENTATION=y
++# CONFIG_PROFILING is not set
++# CONFIG_KPROBES is not set
++# CONFIG_MARKERS is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++CONFIG_FORCED_INLINING=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++CONFIG_DEBUGGER=y
++# CONFIG_KGDB is not set
++# CONFIG_XMON is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/44x/rainier_defconfig b/arch/powerpc/configs/44x/rainier_defconfig
+new file mode 100644
+index 0000000..dec18ca
+--- /dev/null
++++ b/arch/powerpc/configs/44x/rainier_defconfig
+@@ -0,0 +1,899 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc2
++# Fri Feb 15 21:53:10 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++CONFIG_44x=y
++# CONFIG_E200 is not set
++CONFIG_4xx=y
++CONFIG_BOOKE=y
++CONFIG_PTE_64BIT=y
++CONFIG_PHYS_64BIT=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++# CONFIG_PPC4xx_PCI_EXPRESS is not set
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++# CONFIG_BAMBOO is not set
++# CONFIG_EBONY is not set
++# CONFIG_SEQUOIA is not set
++# CONFIG_TAISHAN is not set
++# CONFIG_KATMAI is not set
++CONFIG_RAINIER=y
++# CONFIG_WARP is not set
++CONFIG_440GRX=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_RCU_TRACE=y
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++CONFIG_RESOURCES_64BIT=y
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++CONFIG_CMDLINE_BOOL=y
++CONFIG_CMDLINE=""
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x01000000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++CONFIG_MTD_OF_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++# CONFIG_MTD_BLKDEVS is not set
++# CONFIG_MTD_BLOCK is not set
++# CONFIG_MTD_BLOCK_RO is not set
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++CONFIG_MTD_CFI_INTELEXT=y
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=35000
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++CONFIG_MACINTOSH_DRIVERS=y
++# CONFIG_MAC_EMUMOUSEBTN is not set
++# CONFIG_WINDFARM is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_NET_ETHERNET is not set
++CONFIG_IBM_NEW_EMAC_ZMII=y
++CONFIG_IBM_NEW_EMAC_RGMII=y
++CONFIG_IBM_NEW_EMAC_EMAC4=y
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++# CONFIG_SERIAL_8250_PCI is not set
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_THERMAL=y
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++CONFIG_DEBUGGER=y
++# CONFIG_KGDB is not set
++# CONFIG_XMON is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++CONFIG_PPC_EARLY_DEBUG=y
++# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
++# CONFIG_PPC_EARLY_DEBUG_G5 is not set
++# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
++# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
++# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
++# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
++# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
++# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
++CONFIG_PPC_EARLY_DEBUG_44x=y
++# CONFIG_PPC_EARLY_DEBUG_40x is not set
++# CONFIG_PPC_EARLY_DEBUG_CPM is not set
++CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW=0xef600300
++CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH=0x1
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/44x/sequoia_defconfig b/arch/powerpc/configs/44x/sequoia_defconfig
+new file mode 100644
+index 0000000..dd5d630
+--- /dev/null
++++ b/arch/powerpc/configs/44x/sequoia_defconfig
+@@ -0,0 +1,916 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc2
++# Fri Feb 15 21:53:46 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++CONFIG_44x=y
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++CONFIG_4xx=y
++CONFIG_BOOKE=y
++CONFIG_PTE_64BIT=y
++CONFIG_PHYS_64BIT=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++# CONFIG_PPC4xx_PCI_EXPRESS is not set
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++# CONFIG_BAMBOO is not set
++# CONFIG_EBONY is not set
++CONFIG_SEQUOIA=y
++# CONFIG_TAISHAN is not set
++# CONFIG_KATMAI is not set
++# CONFIG_RAINIER is not set
++# CONFIG_WARP is not set
++CONFIG_440EPX=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_RCU_TRACE=y
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_MATH_EMULATION is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++CONFIG_RESOURCES_64BIT=y
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++CONFIG_CMDLINE_BOOL=y
++CONFIG_CMDLINE=""
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x01000000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++CONFIG_MTD_OF_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++# CONFIG_MTD_BLKDEVS is not set
++# CONFIG_MTD_BLOCK is not set
++# CONFIG_MTD_BLOCK_RO is not set
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++CONFIG_MTD_CFI_INTELEXT=y
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=35000
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++CONFIG_IBM_NEW_EMAC=y
++CONFIG_IBM_NEW_EMAC_RXB=128
++CONFIG_IBM_NEW_EMAC_TXB=64
++CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
++CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
++CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
++# CONFIG_IBM_NEW_EMAC_DEBUG is not set
++CONFIG_IBM_NEW_EMAC_ZMII=y
++CONFIG_IBM_NEW_EMAC_RGMII=y
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++CONFIG_IBM_NEW_EMAC_EMAC4=y
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++# CONFIG_SERIAL_8250_PCI is not set
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_THERMAL=y
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++CONFIG_DEBUGGER=y
++# CONFIG_KGDB is not set
++# CONFIG_XMON is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++CONFIG_PPC_EARLY_DEBUG=y
++# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
++# CONFIG_PPC_EARLY_DEBUG_G5 is not set
++# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
++# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
++# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
++# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
++# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
++# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
++CONFIG_PPC_EARLY_DEBUG_44x=y
++# CONFIG_PPC_EARLY_DEBUG_40x is not set
++# CONFIG_PPC_EARLY_DEBUG_CPM is not set
++CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW=0xef600300
++CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH=0x1
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/44x/taishan_defconfig b/arch/powerpc/configs/44x/taishan_defconfig
+new file mode 100644
+index 0000000..087aedc
+--- /dev/null
++++ b/arch/powerpc/configs/44x/taishan_defconfig
+@@ -0,0 +1,815 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc2
++# Fri Feb 15 21:40:44 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++CONFIG_44x=y
++# CONFIG_E200 is not set
++CONFIG_4xx=y
++CONFIG_BOOKE=y
++CONFIG_PTE_64BIT=y
++CONFIG_PHYS_64BIT=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++# CONFIG_PPC4xx_PCI_EXPRESS is not set
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++# CONFIG_BAMBOO is not set
++# CONFIG_EBONY is not set
++# CONFIG_SEQUOIA is not set
++CONFIG_TAISHAN=y
++# CONFIG_KATMAI is not set
++# CONFIG_RAINIER is not set
++# CONFIG_WARP is not set
++CONFIG_440GX=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_RCU_TRACE=y
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_MATH_EMULATION is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++CONFIG_RESOURCES_64BIT=y
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++CONFIG_CMDLINE_BOOL=y
++CONFIG_CMDLINE=""
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x01000000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=35000
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++CONFIG_MACINTOSH_DRIVERS=y
++# CONFIG_MAC_EMUMOUSEBTN is not set
++# CONFIG_WINDFARM is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++CONFIG_IBM_NEW_EMAC=y
++CONFIG_IBM_NEW_EMAC_RXB=128
++CONFIG_IBM_NEW_EMAC_TXB=64
++CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
++CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
++CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
++# CONFIG_IBM_NEW_EMAC_DEBUG is not set
++CONFIG_IBM_NEW_EMAC_ZMII=y
++CONFIG_IBM_NEW_EMAC_RGMII=y
++CONFIG_IBM_NEW_EMAC_TAH=y
++CONFIG_IBM_NEW_EMAC_EMAC4=y
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++# CONFIG_SERIAL_8250_PCI is not set
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_THERMAL=y
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++CONFIG_DEBUGGER=y
++# CONFIG_KGDB is not set
++# CONFIG_XMON is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/44x/warp_defconfig b/arch/powerpc/configs/44x/warp_defconfig
+new file mode 100644
+index 0000000..2313c3e
+--- /dev/null
++++ b/arch/powerpc/configs/44x/warp_defconfig
+@@ -0,0 +1,1110 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc2
++# Fri Feb 15 21:54:43 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++CONFIG_44x=y
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++CONFIG_4xx=y
++CONFIG_BOOKE=y
++CONFIG_PTE_64BIT=y
++CONFIG_PHYS_64BIT=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION="-pika"
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++# CONFIG_HOTPLUG is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++# CONFIG_BAMBOO is not set
++# CONFIG_EBONY is not set
++# CONFIG_SEQUOIA is not set
++# CONFIG_TAISHAN is not set
++# CONFIG_KATMAI is not set
++# CONFIG_RAINIER is not set
++CONFIG_WARP=y
++CONFIG_440EP=y
++CONFIG_IBM440EP_ERR42=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++# CONFIG_HZ_250 is not set
++# CONFIG_HZ_300 is not set
++CONFIG_HZ_1000=y
++CONFIG_HZ=1000
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_RCU_TRACE=y
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_MATH_EMULATION is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++CONFIG_RESOURCES_64BIT=y
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++CONFIG_CMDLINE_BOOL=y
++CONFIG_CMDLINE="ip=on"
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++# CONFIG_PCI is not set
++# CONFIG_PCI_DOMAINS is not set
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x01000000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IP_VS is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++CONFIG_NETFILTER=y
++# CONFIG_NETFILTER_DEBUG is not set
++CONFIG_NETFILTER_ADVANCED=y
++
++#
++# Core Netfilter Configuration
++#
++# CONFIG_NETFILTER_NETLINK_QUEUE is not set
++# CONFIG_NETFILTER_NETLINK_LOG is not set
++# CONFIG_NF_CONNTRACK is not set
++# CONFIG_NETFILTER_XTABLES is not set
++
++#
++# IP: Netfilter Configuration
++#
++# CONFIG_IP_NF_QUEUE is not set
++# CONFIG_IP_NF_IPTABLES is not set
++# CONFIG_IP_NF_ARPTABLES is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++CONFIG_VLAN_8021Q=y
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++# CONFIG_STANDALONE is not set
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++CONFIG_MTD_OF_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++CONFIG_MTD_OOPS=m
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++# CONFIG_MTD_NAND_VERIFY_WRITE is not set
++CONFIG_MTD_NAND_ECC_SMC=y
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ALAUDA is not set
++# CONFIG_MTD_NAND_FSL_ELBC is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=4096
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++CONFIG_SCSI_SPI_ATTRS=y
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++# CONFIG_SCSI_LOWLEVEL is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_IBM_NEW_EMAC=y
++CONFIG_IBM_NEW_EMAC_RXB=128
++CONFIG_IBM_NEW_EMAC_TXB=64
++CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
++CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
++CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
++# CONFIG_IBM_NEW_EMAC_DEBUG is not set
++CONFIG_IBM_NEW_EMAC_ZMII=y
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++# CONFIG_I2C_CHARDEV is not set
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_MPC is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++CONFIG_SENSORS_EEPROM=y
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++CONFIG_THERMAL=y
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++# CONFIG_USB_DEVICEFS is not set
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++CONFIG_USB_OHCI_HCD_PPC_OF=y
++CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
++# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
++CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
++CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_GADGET is not set
++CONFIG_MMC=m
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD Card Drivers
++#
++CONFIG_MMC_BLOCK=m
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
++
++#
++# MMC/SD Host Controller Drivers
++#
++# CONFIG_MMC_WBSD is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++# CONFIG_TMPFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++CONFIG_NLS_CODEPAGE_850=y
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++CONFIG_NLS_ASCII=y
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++CONFIG_NLS_ISO8859_15=y
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=y
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++# CONFIG_SCHED_DEBUG is not set
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++CONFIG_DEBUG_INFO=y
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_VIRQ_DEBUG is not set
++CONFIG_BDI_SWITCH=y
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_SEQIV is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig b/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig
+new file mode 100644
+index 0000000..7d18440
+--- /dev/null
++++ b/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig
+@@ -0,0 +1,1395 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Fri Apr 11 11:10:09 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++# CONFIG_FSL_EMB_PERFMON is not set
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++# CONFIG_SMP is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MULTIPLATFORM is not set
++# CONFIG_PPC_82xx is not set
++CONFIG_PPC_83xx=y
++# CONFIG_PPC_86xx is not set
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC83xx=y
++CONFIG_MPC831x_RDB=y
++# CONFIG_MPC832x_MDS is not set
++# CONFIG_MPC832x_RDB is not set
++# CONFIG_MPC834x_MDS is not set
++# CONFIG_MPC834x_ITX is not set
++# CONFIG_MPC836x_MDS is not set
++# CONFIG_MPC837x_MDS is not set
++# CONFIG_MPC837x_RDB is not set
++# CONFIG_SBC834x is not set
++CONFIG_PPC_MPC831x=y
++CONFIG_IPIC=y
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++CONFIG_FORCE_MAX_ZONEORDER=11
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++CONFIG_MTD_OF_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_DATAFLASH is not set
++# CONFIG_MTD_M25P80 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++CONFIG_MTD_NAND_VERIFY_WRITE=y
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_CAFE is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ALAUDA is not set
++CONFIG_MTD_NAND_FSL_ELBC=y
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++# CONFIG_BLK_DEV_SD is not set
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++CONFIG_SCSI_SPI_ATTRS=y
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_MVSAS is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++# CONFIG_ATA is not set
++CONFIG_MD=y
++CONFIG_BLK_DEV_MD=y
++CONFIG_MD_LINEAR=y
++CONFIG_MD_RAID0=y
++CONFIG_MD_RAID1=y
++# CONFIG_MD_RAID10 is not set
++# CONFIG_MD_RAID456 is not set
++# CONFIG_MD_MULTIPATH is not set
++# CONFIG_MD_FAULTY is not set
++# CONFIG_BLK_DEV_DM is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++CONFIG_CICADA_PHY=y
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_ENC28J60 is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++CONFIG_NET_PCI=y
++# CONFIG_PCNET32 is not set
++# CONFIG_AMD8111_ETH is not set
++# CONFIG_ADAPTEC_STARFIRE is not set
++# CONFIG_B44 is not set
++# CONFIG_FORCEDETH is not set
++# CONFIG_EEPRO100 is not set
++CONFIG_E100=y
++# CONFIG_FEALNX is not set
++# CONFIG_NATSEMI is not set
++# CONFIG_NE2K_PCI is not set
++# CONFIG_8139CP is not set
++# CONFIG_8139TOO is not set
++# CONFIG_R6040 is not set
++# CONFIG_SIS900 is not set
++# CONFIG_EPIC100 is not set
++# CONFIG_SUNDANCE is not set
++# CONFIG_TLAN is not set
++# CONFIG_VIA_RHINE is not set
++# CONFIG_SC92031 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++CONFIG_SPI=y
++# CONFIG_SPI_DEBUG is not set
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_BITBANG=y
++CONFIG_SPI_MPC83xx=y
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM70 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_83xx_WDT=y
++
++#
++# PCI-based Watchdog Cards
++#
++# CONFIG_PCIPCWATCHDOG is not set
++# CONFIG_WDTPCI is not set
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++# CONFIG_USB_HID is not set
++
++#
++# USB HID Boot Protocol drivers
++#
++# CONFIG_USB_KBD is not set
++# CONFIG_USB_MOUSE is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++CONFIG_USB_EHCI_HCD=y
++CONFIG_USB_EHCI_ROOT_HUB_TT=y
++# CONFIG_USB_EHCI_TT_NEWSCHED is not set
++CONFIG_USB_EHCI_FSL=y
++CONFIG_USB_EHCI_HCD_PPC_OF=y
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++CONFIG_USB_OHCI_HCD_PPC_OF=y
++CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
++# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
++CONFIG_USB_OHCI_HCD_PCI=y
++CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
++CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++CONFIG_USB_UHCI_HCD=y
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG is not set
++# CONFIG_USB_GADGET_DEBUG_FILES is not set
++CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_ATMEL_USBA is not set
++# CONFIG_USB_GADGET_FSL_USB2 is not set
++CONFIG_USB_GADGET_NET2280=y
++CONFIG_USB_NET2280=y
++# CONFIG_USB_GADGET_PXA2XX is not set
++# CONFIG_USB_GADGET_M66592 is not set
++# CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_LH7A40X is not set
++# CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_S3C2410 is not set
++# CONFIG_USB_GADGET_AT91 is not set
++# CONFIG_USB_GADGET_DUMMY_HCD is not set
++CONFIG_USB_GADGET_DUALSPEED=y
++# CONFIG_USB_ZERO is not set
++CONFIG_USB_ETH=y
++CONFIG_USB_ETH_RNDIS=y
++# CONFIG_USB_GADGETFS is not set
++# CONFIG_USB_FILE_STORAGE is not set
++# CONFIG_USB_G_SERIAL is not set
++# CONFIG_USB_MIDI_GADGET is not set
++# CONFIG_USB_G_PRINTER is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++CONFIG_RTC_INTF_DEV_UIE_EMUL=y
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++CONFIG_RTC_DRV_DS1307=y
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_MAX6902 is not set
++# CONFIG_RTC_DRV_R9701 is not set
++# CONFIG_RTC_DRV_RS5C348 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig b/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig
+new file mode 100644
+index 0000000..1f57456
+--- /dev/null
++++ b/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig
+@@ -0,0 +1,1451 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:15 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++# CONFIG_FSL_EMB_PERFMON is not set
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++# CONFIG_SMP is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MULTIPLATFORM is not set
++# CONFIG_PPC_82xx is not set
++CONFIG_PPC_83xx=y
++# CONFIG_PPC_86xx is not set
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC83xx=y
++CONFIG_MPC831x_RDB=y
++# CONFIG_MPC832x_MDS is not set
++# CONFIG_MPC832x_RDB is not set
++# CONFIG_MPC834x_MDS is not set
++# CONFIG_MPC834x_ITX is not set
++# CONFIG_MPC836x_MDS is not set
++# CONFIG_MPC837x_MDS is not set
++# CONFIG_MPC837x_RDB is not set
++# CONFIG_SBC834x is not set
++CONFIG_PPC_MPC831x=y
++CONFIG_IPIC=y
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_OF_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_DATAFLASH is not set
++# CONFIG_MTD_M25P80 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++CONFIG_MTD_NAND_VERIFY_WRITE=y
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_CAFE is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ALAUDA is not set
++# CONFIG_MTD_NAND_FSL_ELBC is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++# CONFIG_BLK_DEV_SD is not set
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++CONFIG_SCSI_SPI_ATTRS=y
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_MVSAS is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_IPR is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++CONFIG_ATA=y
++# CONFIG_ATA_NONSTANDARD is not set
++# CONFIG_SATA_AHCI is not set
++# CONFIG_SATA_SVW is not set
++# CONFIG_ATA_PIIX is not set
++# CONFIG_SATA_MV is not set
++# CONFIG_SATA_NV is not set
++# CONFIG_PDC_ADMA is not set
++# CONFIG_SATA_QSTOR is not set
++# CONFIG_SATA_PROMISE is not set
++# CONFIG_SATA_SX4 is not set
++# CONFIG_SATA_SIL is not set
++# CONFIG_SATA_SIL24 is not set
++# CONFIG_SATA_SIS is not set
++# CONFIG_SATA_ULI is not set
++# CONFIG_SATA_VIA is not set
++# CONFIG_SATA_VITESSE is not set
++# CONFIG_SATA_INIC162X is not set
++CONFIG_SATA_FSL=y
++# CONFIG_PATA_ALI is not set
++# CONFIG_PATA_AMD is not set
++# CONFIG_PATA_ARTOP is not set
++# CONFIG_PATA_ATIIXP is not set
++# CONFIG_PATA_CMD640_PCI is not set
++# CONFIG_PATA_CMD64X is not set
++# CONFIG_PATA_CS5520 is not set
++# CONFIG_PATA_CS5530 is not set
++# CONFIG_PATA_CYPRESS is not set
++# CONFIG_PATA_EFAR is not set
++# CONFIG_ATA_GENERIC is not set
++# CONFIG_PATA_HPT366 is not set
++# CONFIG_PATA_HPT37X is not set
++# CONFIG_PATA_HPT3X2N is not set
++# CONFIG_PATA_HPT3X3 is not set
++# CONFIG_PATA_IT821X is not set
++# CONFIG_PATA_IT8213 is not set
++# CONFIG_PATA_JMICRON is not set
++# CONFIG_PATA_TRIFLEX is not set
++# CONFIG_PATA_MARVELL is not set
++# CONFIG_PATA_MPIIX is not set
++# CONFIG_PATA_OLDPIIX is not set
++# CONFIG_PATA_NETCELL is not set
++# CONFIG_PATA_NINJA32 is not set
++# CONFIG_PATA_NS87410 is not set
++# CONFIG_PATA_NS87415 is not set
++# CONFIG_PATA_OPTI is not set
++# CONFIG_PATA_OPTIDMA is not set
++# CONFIG_PATA_PDC_OLD is not set
++# CONFIG_PATA_RADISYS is not set
++# CONFIG_PATA_RZ1000 is not set
++# CONFIG_PATA_SC1200 is not set
++# CONFIG_PATA_SERVERWORKS is not set
++# CONFIG_PATA_PDC2027X is not set
++# CONFIG_PATA_SIL680 is not set
++# CONFIG_PATA_SIS is not set
++# CONFIG_PATA_VIA is not set
++# CONFIG_PATA_WINBOND is not set
++# CONFIG_PATA_PLATFORM is not set
++CONFIG_MD=y
++CONFIG_BLK_DEV_MD=y
++CONFIG_MD_LINEAR=y
++CONFIG_MD_RAID0=y
++CONFIG_MD_RAID1=y
++# CONFIG_MD_RAID10 is not set
++# CONFIG_MD_RAID456 is not set
++# CONFIG_MD_MULTIPATH is not set
++# CONFIG_MD_FAULTY is not set
++# CONFIG_BLK_DEV_DM is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_ENC28J60 is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++CONFIG_NET_PCI=y
++# CONFIG_PCNET32 is not set
++# CONFIG_AMD8111_ETH is not set
++# CONFIG_ADAPTEC_STARFIRE is not set
++# CONFIG_B44 is not set
++# CONFIG_FORCEDETH is not set
++# CONFIG_EEPRO100 is not set
++CONFIG_E100=y
++# CONFIG_FEALNX is not set
++# CONFIG_NATSEMI is not set
++# CONFIG_NE2K_PCI is not set
++# CONFIG_8139CP is not set
++# CONFIG_8139TOO is not set
++# CONFIG_R6040 is not set
++# CONFIG_SIS900 is not set
++# CONFIG_EPIC100 is not set
++# CONFIG_SUNDANCE is not set
++# CONFIG_TLAN is not set
++# CONFIG_VIA_RHINE is not set
++# CONFIG_SC92031 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++CONFIG_SPI=y
++# CONFIG_SPI_DEBUG is not set
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_BITBANG=y
++CONFIG_SPI_MPC83xx=y
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM70 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_83xx_WDT=y
++
++#
++# PCI-based Watchdog Cards
++#
++# CONFIG_PCIPCWATCHDOG is not set
++# CONFIG_WDTPCI is not set
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++# CONFIG_USB_HID is not set
++
++#
++# USB HID Boot Protocol drivers
++#
++# CONFIG_USB_KBD is not set
++# CONFIG_USB_MOUSE is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++CONFIG_USB_EHCI_HCD=y
++CONFIG_USB_EHCI_ROOT_HUB_TT=y
++# CONFIG_USB_EHCI_TT_NEWSCHED is not set
++CONFIG_USB_EHCI_FSL=y
++CONFIG_USB_EHCI_HCD_PPC_OF=y
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++CONFIG_USB_OHCI_HCD_PPC_OF=y
++CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
++# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
++CONFIG_USB_OHCI_HCD_PCI=y
++CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
++CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++CONFIG_USB_UHCI_HCD=y
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++CONFIG_USB_GADGET=y
++# CONFIG_USB_GADGET_DEBUG is not set
++# CONFIG_USB_GADGET_DEBUG_FILES is not set
++CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_ATMEL_USBA is not set
++# CONFIG_USB_GADGET_FSL_USB2 is not set
++CONFIG_USB_GADGET_NET2280=y
++CONFIG_USB_NET2280=y
++# CONFIG_USB_GADGET_PXA2XX is not set
++# CONFIG_USB_GADGET_M66592 is not set
++# CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_LH7A40X is not set
++# CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_S3C2410 is not set
++# CONFIG_USB_GADGET_AT91 is not set
++# CONFIG_USB_GADGET_DUMMY_HCD is not set
++CONFIG_USB_GADGET_DUALSPEED=y
++# CONFIG_USB_ZERO is not set
++CONFIG_USB_ETH=y
++CONFIG_USB_ETH_RNDIS=y
++# CONFIG_USB_GADGETFS is not set
++# CONFIG_USB_FILE_STORAGE is not set
++# CONFIG_USB_G_SERIAL is not set
++# CONFIG_USB_MIDI_GADGET is not set
++# CONFIG_USB_G_PRINTER is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++CONFIG_RTC_INTF_DEV_UIE_EMUL=y
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++CONFIG_RTC_DRV_DS1307=y
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_MAX6902 is not set
++# CONFIG_RTC_DRV_R9701 is not set
++# CONFIG_RTC_DRV_RS5C348 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/83xx/mpc832x_mds_defconfig b/arch/powerpc/configs/83xx/mpc832x_mds_defconfig
+new file mode 100644
+index 0000000..50cceda
+--- /dev/null
++++ b/arch/powerpc/configs/83xx/mpc832x_mds_defconfig
+@@ -0,0 +1,1081 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc7
++# Mon Mar 31 11:36:51 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++# CONFIG_FSL_EMB_PERFMON is not set
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++# CONFIG_SMP is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MULTIPLATFORM is not set
++# CONFIG_PPC_82xx is not set
++CONFIG_PPC_83xx=y
++# CONFIG_PPC_86xx is not set
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC83xx=y
++# CONFIG_MPC831x_RDB is not set
++CONFIG_MPC832x_MDS=y
++# CONFIG_MPC832x_RDB is not set
++# CONFIG_MPC834x_MDS is not set
++# CONFIG_MPC834x_ITX is not set
++# CONFIG_MPC836x_MDS is not set
++# CONFIG_MPC837x_MDS is not set
++# CONFIG_MPC837x_RDB is not set
++# CONFIG_SBC834x is not set
++CONFIG_PPC_MPC832x=y
++CONFIG_IPIC=y
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++CONFIG_QUICC_ENGINE=y
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++# CONFIG_BLK_DEV_SD is not set
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_MVSAS is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++CONFIG_DAVICOM_PHY=y
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_GIANFAR is not set
++CONFIG_UCC_GETH=y
++# CONFIG_UGETH_NAPI is not set
++# CONFIG_UGETH_MAGIC_PACKET is not set
++# CONFIG_UGETH_FILTERING is not set
++# CONFIG_UGETH_TX_ON_DEMAND is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++# CONFIG_SERIAL_QE is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_83xx_WDT=y
++
++#
++# PCI-based Watchdog Cards
++#
++# CONFIG_PCIPCWATCHDOG is not set
++# CONFIG_WDTPCI is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++CONFIG_RTC_DRV_DS1374=y
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++CONFIG_UCC_FAST=y
++CONFIG_UCC=y
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
++CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig b/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig
+new file mode 100644
+index 0000000..ac91302
+--- /dev/null
++++ b/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig
+@@ -0,0 +1,1233 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:16 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++# CONFIG_FSL_EMB_PERFMON is not set
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++# CONFIG_SMP is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MULTIPLATFORM is not set
++# CONFIG_PPC_82xx is not set
++CONFIG_PPC_83xx=y
++# CONFIG_PPC_86xx is not set
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC83xx=y
++# CONFIG_MPC831x_RDB is not set
++# CONFIG_MPC832x_MDS is not set
++CONFIG_MPC832x_RDB=y
++# CONFIG_MPC834x_MDS is not set
++# CONFIG_MPC834x_ITX is not set
++# CONFIG_MPC836x_MDS is not set
++# CONFIG_MPC837x_MDS is not set
++# CONFIG_MPC837x_RDB is not set
++# CONFIG_SBC834x is not set
++CONFIG_PPC_MPC832x=y
++CONFIG_IPIC=y
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++CONFIG_QUICC_ENGINE=y
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_MVSAS is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++CONFIG_ICPLUS_PHY=y
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_ENC28J60 is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++CONFIG_E1000=y
++# CONFIG_E1000_NAPI is not set
++# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_GIANFAR is not set
++CONFIG_UCC_GETH=y
++CONFIG_UGETH_NAPI=y
++# CONFIG_UGETH_MAGIC_PACKET is not set
++# CONFIG_UGETH_FILTERING is not set
++# CONFIG_UGETH_TX_ON_DEMAND is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++# CONFIG_SERIAL_QE is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++CONFIG_SPI=y
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_BITBANG=y
++CONFIG_SPI_MPC83xx=y
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM70 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_83xx_WDT=y
++
++#
++# PCI-based Watchdog Cards
++#
++# CONFIG_PCIPCWATCHDOG is not set
++# CONFIG_WDTPCI is not set
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++# CONFIG_USB_HID is not set
++
++#
++# USB HID Boot Protocol drivers
++#
++# CONFIG_USB_KBD is not set
++# CONFIG_USB_MOUSE is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++CONFIG_USB_EHCI_HCD=y
++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
++# CONFIG_USB_EHCI_TT_NEWSCHED is not set
++# CONFIG_USB_EHCI_FSL is not set
++CONFIG_USB_EHCI_HCD_PPC_OF=y
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++CONFIG_USB_OHCI_HCD_PPC_OF=y
++CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
++# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
++CONFIG_USB_OHCI_HCD_PCI=y
++CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
++CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_UHCI_HCD is not set
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++# CONFIG_USB_GADGET is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
++
++#
++# MMC/SD Host Controller Drivers
++#
++# CONFIG_MMC_SDHCI is not set
++# CONFIG_MMC_WBSD is not set
++# CONFIG_MMC_TIFM_SD is not set
++CONFIG_MMC_SPI=y
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++CONFIG_LDM_PARTITION=y
++# CONFIG_LDM_DEBUG is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++CONFIG_NLS_CODEPAGE_932=y
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++CONFIG_NLS_ISO8859_8=y
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++# CONFIG_DLM is not set
++CONFIG_UCC_FAST=y
++CONFIG_UCC=y
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++CONFIG_CRC_ITU_T=y
++CONFIG_CRC32=y
++CONFIG_CRC7=y
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
++CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/83xx/mpc834x_itx_defconfig b/arch/powerpc/configs/83xx/mpc834x_itx_defconfig
+new file mode 100644
+index 0000000..e1de399
+--- /dev/null
++++ b/arch/powerpc/configs/83xx/mpc834x_itx_defconfig
+@@ -0,0 +1,1295 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:17 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++# CONFIG_FSL_EMB_PERFMON is not set
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++# CONFIG_SMP is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MULTIPLATFORM is not set
++# CONFIG_PPC_82xx is not set
++CONFIG_PPC_83xx=y
++# CONFIG_PPC_86xx is not set
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC83xx=y
++# CONFIG_MPC831x_RDB is not set
++# CONFIG_MPC832x_MDS is not set
++# CONFIG_MPC832x_RDB is not set
++# CONFIG_MPC834x_MDS is not set
++CONFIG_MPC834x_ITX=y
++# CONFIG_MPC836x_MDS is not set
++# CONFIG_MPC837x_MDS is not set
++# CONFIG_MPC837x_RDB is not set
++# CONFIG_SBC834x is not set
++CONFIG_PPC_MPC834x=y
++CONFIG_IPIC=y
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++# CONFIG_MTD_PARTITIONS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++# CONFIG_MTD_BLKDEVS is not set
++# CONFIG_MTD_BLOCK is not set
++# CONFIG_MTD_BLOCK_RO is not set
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_START=0xfe000000
++CONFIG_MTD_PHYSMAP_LEN=0x1000000
++CONFIG_MTD_PHYSMAP_BANKWIDTH=2
++# CONFIG_MTD_PHYSMAP_OF is not set
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_DATAFLASH is not set
++# CONFIG_MTD_M25P80 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++CONFIG_IDE=y
++CONFIG_IDE_MAX_HWIFS=4
++# CONFIG_BLK_DEV_IDE is not set
++# CONFIG_BLK_DEV_HD_ONLY is not set
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++CONFIG_SCSI_SPI_ATTRS=y
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_MVSAS is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_IPR is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++CONFIG_ATA=y
++# CONFIG_ATA_NONSTANDARD is not set
++# CONFIG_SATA_AHCI is not set
++# CONFIG_SATA_SVW is not set
++# CONFIG_ATA_PIIX is not set
++# CONFIG_SATA_MV is not set
++# CONFIG_SATA_NV is not set
++# CONFIG_PDC_ADMA is not set
++# CONFIG_SATA_QSTOR is not set
++# CONFIG_SATA_PROMISE is not set
++# CONFIG_SATA_SX4 is not set
++CONFIG_SATA_SIL=y
++# CONFIG_SATA_SIL24 is not set
++# CONFIG_SATA_SIS is not set
++# CONFIG_SATA_ULI is not set
++# CONFIG_SATA_VIA is not set
++# CONFIG_SATA_VITESSE is not set
++# CONFIG_SATA_INIC162X is not set
++# CONFIG_SATA_FSL is not set
++# CONFIG_PATA_ALI is not set
++# CONFIG_PATA_AMD is not set
++# CONFIG_PATA_ARTOP is not set
++# CONFIG_PATA_ATIIXP is not set
++# CONFIG_PATA_CMD640_PCI is not set
++# CONFIG_PATA_CMD64X is not set
++# CONFIG_PATA_CS5520 is not set
++# CONFIG_PATA_CS5530 is not set
++# CONFIG_PATA_CYPRESS is not set
++# CONFIG_PATA_EFAR is not set
++# CONFIG_ATA_GENERIC is not set
++# CONFIG_PATA_HPT366 is not set
++# CONFIG_PATA_HPT37X is not set
++# CONFIG_PATA_HPT3X2N is not set
++# CONFIG_PATA_HPT3X3 is not set
++# CONFIG_PATA_IT821X is not set
++# CONFIG_PATA_IT8213 is not set
++# CONFIG_PATA_JMICRON is not set
++# CONFIG_PATA_TRIFLEX is not set
++# CONFIG_PATA_MARVELL is not set
++# CONFIG_PATA_MPIIX is not set
++# CONFIG_PATA_OLDPIIX is not set
++# CONFIG_PATA_NETCELL is not set
++# CONFIG_PATA_NINJA32 is not set
++# CONFIG_PATA_NS87410 is not set
++# CONFIG_PATA_NS87415 is not set
++# CONFIG_PATA_OPTI is not set
++# CONFIG_PATA_OPTIDMA is not set
++# CONFIG_PATA_PDC_OLD is not set
++# CONFIG_PATA_RADISYS is not set
++# CONFIG_PATA_RZ1000 is not set
++# CONFIG_PATA_SC1200 is not set
++# CONFIG_PATA_SERVERWORKS is not set
++# CONFIG_PATA_PDC2027X is not set
++# CONFIG_PATA_SIL680 is not set
++# CONFIG_PATA_SIS is not set
++# CONFIG_PATA_VIA is not set
++# CONFIG_PATA_WINBOND is not set
++CONFIG_PATA_PLATFORM=y
++CONFIG_PATA_OF_PLATFORM=y
++CONFIG_MD=y
++CONFIG_BLK_DEV_MD=y
++CONFIG_MD_LINEAR=y
++CONFIG_MD_RAID0=y
++CONFIG_MD_RAID1=y
++# CONFIG_MD_RAID10 is not set
++# CONFIG_MD_RAID456 is not set
++# CONFIG_MD_MULTIPATH is not set
++# CONFIG_MD_FAULTY is not set
++# CONFIG_BLK_DEV_DM is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++CONFIG_CICADA_PHY=y
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++# CONFIG_NET_ETHERNET is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++# CONFIG_SERIAL_8250_PCI is not set
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++CONFIG_SENSORS_PCF8574=y
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++CONFIG_SPI=y
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_BITBANG=y
++CONFIG_SPI_MPC83xx=y
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_83xx_WDT=y
++
++#
++# PCI-based Watchdog Cards
++#
++# CONFIG_PCIPCWATCHDOG is not set
++# CONFIG_WDTPCI is not set
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++CONFIG_USB_EHCI_HCD=y
++CONFIG_USB_EHCI_ROOT_HUB_TT=y
++# CONFIG_USB_EHCI_TT_NEWSCHED is not set
++CONFIG_USB_EHCI_FSL=y
++CONFIG_USB_EHCI_HCD_PPC_OF=y
++# CONFIG_USB_ISP116X_HCD is not set
++# CONFIG_USB_OHCI_HCD is not set
++CONFIG_USB_UHCI_HCD=y
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++CONFIG_RTC_INTF_DEV_UIE_EMUL=y
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++CONFIG_RTC_DRV_DS1307=y
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_MAX6902 is not set
++# CONFIG_RTC_DRV_R9701 is not set
++# CONFIG_RTC_DRV_RS5C348 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++CONFIG_MAC_PARTITION=y
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++# CONFIG_NLS_CODEPAGE_437 is not set
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++# CONFIG_NLS_ISO8859_1 is not set
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig b/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig
+new file mode 100644
+index 0000000..b4e39cf
+--- /dev/null
++++ b/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig
+@@ -0,0 +1,1222 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:18 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++# CONFIG_FSL_EMB_PERFMON is not set
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++# CONFIG_SMP is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MULTIPLATFORM is not set
++# CONFIG_PPC_82xx is not set
++CONFIG_PPC_83xx=y
++# CONFIG_PPC_86xx is not set
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC83xx=y
++# CONFIG_MPC831x_RDB is not set
++# CONFIG_MPC832x_MDS is not set
++# CONFIG_MPC832x_RDB is not set
++# CONFIG_MPC834x_MDS is not set
++CONFIG_MPC834x_ITX=y
++# CONFIG_MPC836x_MDS is not set
++# CONFIG_MPC837x_MDS is not set
++# CONFIG_MPC837x_RDB is not set
++# CONFIG_SBC834x is not set
++CONFIG_PPC_MPC834x=y
++CONFIG_IPIC=y
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++# CONFIG_MTD_PARTITIONS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++# CONFIG_MTD_BLKDEVS is not set
++# CONFIG_MTD_BLOCK is not set
++# CONFIG_MTD_BLOCK_RO is not set
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_START=0xfe000000
++CONFIG_MTD_PHYSMAP_LEN=0x800000
++CONFIG_MTD_PHYSMAP_BANKWIDTH=2
++# CONFIG_MTD_PHYSMAP_OF is not set
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_DATAFLASH is not set
++# CONFIG_MTD_M25P80 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++CONFIG_SCSI_SPI_ATTRS=y
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_MVSAS is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++CONFIG_CICADA_PHY=y
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++# CONFIG_NET_ETHERNET is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++# CONFIG_SERIAL_8250_PCI is not set
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++CONFIG_SENSORS_PCF8574=y
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++CONFIG_SPI=y
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_BITBANG=y
++CONFIG_SPI_MPC83xx=y
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_AT25 is not set
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_83xx_WDT=y
++
++#
++# PCI-based Watchdog Cards
++#
++# CONFIG_PCIPCWATCHDOG is not set
++# CONFIG_WDTPCI is not set
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++# CONFIG_USB_DEVICEFS is not set
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++CONFIG_USB_EHCI_HCD=y
++CONFIG_USB_EHCI_ROOT_HUB_TT=y
++# CONFIG_USB_EHCI_TT_NEWSCHED is not set
++CONFIG_USB_EHCI_FSL=y
++CONFIG_USB_EHCI_HCD_PPC_OF=y
++# CONFIG_USB_ISP116X_HCD is not set
++# CONFIG_USB_OHCI_HCD is not set
++CONFIG_USB_UHCI_HCD=y
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++CONFIG_RTC_INTF_DEV_UIE_EMUL=y
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++CONFIG_RTC_DRV_DS1307=y
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_MAX6902 is not set
++# CONFIG_RTC_DRV_R9701 is not set
++# CONFIG_RTC_DRV_RS5C348 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++CONFIG_MAC_PARTITION=y
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++# CONFIG_NLS_CODEPAGE_437 is not set
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++# CONFIG_NLS_ISO8859_1 is not set
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/83xx/mpc834x_mds_defconfig b/arch/powerpc/configs/83xx/mpc834x_mds_defconfig
+new file mode 100644
+index 0000000..b4e82c0
+--- /dev/null
++++ b/arch/powerpc/configs/83xx/mpc834x_mds_defconfig
+@@ -0,0 +1,1021 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc7
++# Mon Mar 31 11:36:56 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++# CONFIG_FSL_EMB_PERFMON is not set
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++# CONFIG_SMP is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MULTIPLATFORM is not set
++# CONFIG_PPC_82xx is not set
++CONFIG_PPC_83xx=y
++# CONFIG_PPC_86xx is not set
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC83xx=y
++# CONFIG_MPC831x_RDB is not set
++# CONFIG_MPC832x_MDS is not set
++# CONFIG_MPC832x_RDB is not set
++CONFIG_MPC834x_MDS=y
++# CONFIG_MPC834x_ITX is not set
++# CONFIG_MPC836x_MDS is not set
++# CONFIG_MPC837x_MDS is not set
++# CONFIG_MPC837x_RDB is not set
++# CONFIG_SBC834x is not set
++CONFIG_PPC_MPC834x=y
++CONFIG_IPIC=y
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++CONFIG_XFRM_USER=m
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++CONFIG_MARVELL_PHY=y
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++CONFIG_NET_PCI=y
++# CONFIG_PCNET32 is not set
++# CONFIG_AMD8111_ETH is not set
++# CONFIG_ADAPTEC_STARFIRE is not set
++# CONFIG_B44 is not set
++# CONFIG_FORCEDETH is not set
++# CONFIG_EEPRO100 is not set
++CONFIG_E100=y
++# CONFIG_FEALNX is not set
++# CONFIG_NATSEMI is not set
++# CONFIG_NE2K_PCI is not set
++# CONFIG_8139CP is not set
++# CONFIG_8139TOO is not set
++# CONFIG_R6040 is not set
++# CONFIG_SIS900 is not set
++# CONFIG_EPIC100 is not set
++# CONFIG_SUNDANCE is not set
++# CONFIG_TLAN is not set
++# CONFIG_VIA_RHINE is not set
++# CONFIG_SC92031 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++# CONFIG_GFAR_NAPI is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_83xx_WDT=y
++
++#
++# PCI-based Watchdog Cards
++#
++# CONFIG_PCIPCWATCHDOG is not set
++# CONFIG_WDTPCI is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++CONFIG_RTC_DRV_DS1374=y
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/83xx/mpc836x_mds_defconfig b/arch/powerpc/configs/83xx/mpc836x_mds_defconfig
+new file mode 100644
+index 0000000..d50a96e
+--- /dev/null
++++ b/arch/powerpc/configs/83xx/mpc836x_mds_defconfig
+@@ -0,0 +1,1079 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc7
++# Mon Mar 31 11:36:57 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++# CONFIG_FSL_EMB_PERFMON is not set
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++# CONFIG_SMP is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MULTIPLATFORM is not set
++# CONFIG_PPC_82xx is not set
++CONFIG_PPC_83xx=y
++# CONFIG_PPC_86xx is not set
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC83xx=y
++# CONFIG_MPC831x_RDB is not set
++# CONFIG_MPC832x_MDS is not set
++# CONFIG_MPC832x_RDB is not set
++# CONFIG_MPC834x_MDS is not set
++# CONFIG_MPC834x_ITX is not set
++CONFIG_MPC836x_MDS=y
++# CONFIG_MPC837x_MDS is not set
++# CONFIG_MPC837x_RDB is not set
++# CONFIG_SBC834x is not set
++CONFIG_IPIC=y
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++CONFIG_QUICC_ENGINE=y
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++# CONFIG_BLK_DEV_SD is not set
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_MVSAS is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++CONFIG_MARVELL_PHY=y
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_GIANFAR is not set
++CONFIG_UCC_GETH=y
++# CONFIG_UGETH_NAPI is not set
++# CONFIG_UGETH_MAGIC_PACKET is not set
++# CONFIG_UGETH_FILTERING is not set
++# CONFIG_UGETH_TX_ON_DEMAND is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++# CONFIG_SERIAL_QE is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_83xx_WDT=y
++
++#
++# PCI-based Watchdog Cards
++#
++# CONFIG_PCIPCWATCHDOG is not set
++# CONFIG_WDTPCI is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++CONFIG_RTC_DRV_DS1374=y
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++CONFIG_UCC_FAST=y
++CONFIG_UCC=y
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
++CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/83xx/mpc837x_mds_defconfig b/arch/powerpc/configs/83xx/mpc837x_mds_defconfig
+new file mode 100644
+index 0000000..f377cde
+--- /dev/null
++++ b/arch/powerpc/configs/83xx/mpc837x_mds_defconfig
+@@ -0,0 +1,899 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:23 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++# CONFIG_FSL_EMB_PERFMON is not set
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++# CONFIG_SMP is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MULTIPLATFORM is not set
++# CONFIG_PPC_82xx is not set
++CONFIG_PPC_83xx=y
++# CONFIG_PPC_86xx is not set
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC83xx=y
++# CONFIG_MPC831x_RDB is not set
++# CONFIG_MPC832x_MDS is not set
++# CONFIG_MPC832x_RDB is not set
++# CONFIG_MPC834x_MDS is not set
++# CONFIG_MPC834x_ITX is not set
++# CONFIG_MPC836x_MDS is not set
++CONFIG_MPC837x_MDS=y
++# CONFIG_MPC837x_RDB is not set
++# CONFIG_SBC834x is not set
++CONFIG_PPC_MPC837x=y
++CONFIG_IPIC=y
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++# CONFIG_PCI is not set
++# CONFIG_PCI_DOMAINS is not set
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++CONFIG_XFRM_USER=m
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_SCSI_DEBUG is not set
++CONFIG_ATA=y
++# CONFIG_ATA_NONSTANDARD is not set
++# CONFIG_SATA_MV is not set
++CONFIG_SATA_FSL=y
++# CONFIG_PATA_PLATFORM is not set
++# CONFIG_MD is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++CONFIG_MARVELL_PHY=y
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_E1000E_ENABLED is not set
++CONFIG_GIANFAR=y
++# CONFIG_GFAR_NAPI is not set
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_83xx_WDT=y
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig b/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig
+new file mode 100644
+index 0000000..a633176
+--- /dev/null
++++ b/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig
+@@ -0,0 +1,930 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:24 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++# CONFIG_FSL_EMB_PERFMON is not set
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++# CONFIG_SMP is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MULTIPLATFORM is not set
++# CONFIG_PPC_82xx is not set
++CONFIG_PPC_83xx=y
++# CONFIG_PPC_86xx is not set
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC83xx=y
++# CONFIG_MPC831x_RDB is not set
++# CONFIG_MPC832x_MDS is not set
++# CONFIG_MPC832x_RDB is not set
++# CONFIG_MPC834x_MDS is not set
++# CONFIG_MPC834x_ITX is not set
++# CONFIG_MPC836x_MDS is not set
++# CONFIG_MPC837x_MDS is not set
++CONFIG_MPC837x_RDB=y
++# CONFIG_SBC834x is not set
++CONFIG_PPC_MPC837x=y
++CONFIG_IPIC=y
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++# CONFIG_PCI is not set
++# CONFIG_PCI_DOMAINS is not set
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_SCSI_DEBUG is not set
++CONFIG_ATA=y
++# CONFIG_ATA_NONSTANDARD is not set
++# CONFIG_SATA_MV is not set
++CONFIG_SATA_FSL=y
++# CONFIG_PATA_PLATFORM is not set
++CONFIG_MD=y
++CONFIG_BLK_DEV_MD=y
++# CONFIG_MD_LINEAR is not set
++# CONFIG_MD_RAID0 is not set
++CONFIG_MD_RAID1=y
++# CONFIG_MD_RAID10 is not set
++CONFIG_MD_RAID456=y
++CONFIG_MD_RAID5_RESHAPE=y
++# CONFIG_MD_MULTIPATH is not set
++# CONFIG_MD_FAULTY is not set
++# CONFIG_BLK_DEV_DM is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++CONFIG_MARVELL_PHY=y
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_E1000E_ENABLED is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_83xx_WDT=y
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++# CONFIG_USB_DEVICEFS is not set
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++CONFIG_USB_EHCI_HCD=y
++CONFIG_USB_EHCI_ROOT_HUB_TT=y
++# CONFIG_USB_EHCI_TT_NEWSCHED is not set
++CONFIG_USB_EHCI_FSL=y
++CONFIG_USB_EHCI_HCD_PPC_OF=y
++# CONFIG_USB_ISP116X_HCD is not set
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++# CONFIG_ENABLE_MUST_CHECK is not set
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_XOR_BLOCKS=y
++CONFIG_ASYNC_CORE=y
++CONFIG_ASYNC_MEMCPY=y
++CONFIG_ASYNC_XOR=y
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/83xx/sbc834x_defconfig b/arch/powerpc/configs/83xx/sbc834x_defconfig
+new file mode 100644
+index 0000000..1f15182
+--- /dev/null
++++ b/arch/powerpc/configs/83xx/sbc834x_defconfig
+@@ -0,0 +1,828 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:38 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++# CONFIG_FSL_EMB_PERFMON is not set
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++# CONFIG_SMP is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MULTIPLATFORM is not set
++# CONFIG_PPC_82xx is not set
++CONFIG_PPC_83xx=y
++# CONFIG_PPC_86xx is not set
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC83xx=y
++# CONFIG_MPC831x_RDB is not set
++# CONFIG_MPC832x_MDS is not set
++# CONFIG_MPC832x_RDB is not set
++# CONFIG_MPC834x_MDS is not set
++# CONFIG_MPC834x_ITX is not set
++# CONFIG_MPC836x_MDS is not set
++# CONFIG_MPC837x_MDS is not set
++# CONFIG_MPC837x_RDB is not set
++CONFIG_SBC834x=y
++CONFIG_PPC_MPC834x=y
++CONFIG_IPIC=y
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++# CONFIG_PCI is not set
++# CONFIG_PCI_DOMAINS is not set
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++CONFIG_XFRM_USER=m
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++CONFIG_BROADCOM_PHY=y
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_E1000E_ENABLED is not set
++CONFIG_GIANFAR=y
++# CONFIG_GFAR_NAPI is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_83xx_WDT=y
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++# CONFIG_USB_SUPPORT is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++# CONFIG_EXT2_FS is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++# CONFIG_CRYPTO_HW is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/85xx/ksi8560_defconfig b/arch/powerpc/configs/85xx/ksi8560_defconfig
+new file mode 100644
+index 0000000..2d0debc
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/ksi8560_defconfig
+@@ -0,0 +1,899 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.24
++# Mon Feb 11 16:25:19 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++# CONFIG_MODULES is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++# CONFIG_MPC8560_ADS is not set
++# CONFIG_MPC85xx_CDS is not set
++# CONFIG_MPC85xx_MDS is not set
++# CONFIG_MPC85xx_DS is not set
++CONFIG_KSI8560=y
++# CONFIG_STX_GP3 is not set
++# CONFIG_TQM8540 is not set
++# CONFIG_TQM8541 is not set
++# CONFIG_TQM8555 is not set
++# CONFIG_TQM8560 is not set
++# CONFIG_SBC8548 is not set
++# CONFIG_SBC8560 is not set
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++CONFIG_CPM2=y
++CONFIG_PPC_CPM_NEW_BINDING=y
++# CONFIG_FSL_ULI1575 is not set
++CONFIG_CPM=y
++
++#
++# Kernel options
++#
++CONFIG_HIGHMEM=y
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_RCU_TRACE=y
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_MISC=y
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_PROC_DEVICETREE is not set
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++# CONFIG_SECCOMP is not set
++CONFIG_WANT_DEVICE_TREE=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_FSL_SOC=y
++# CONFIG_PCI is not set
++# CONFIG_PCI_DOMAINS is not set
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++CONFIG_IDE=y
++CONFIG_IDE_MAX_HWIFS=4
++CONFIG_BLK_DEV_IDE=y
++
++#
++# Please see Documentation/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_IDE_SATA is not set
++# CONFIG_BLK_DEV_IDEDISK is not set
++# CONFIG_IDEDISK_MULTI_MODE is not set
++# CONFIG_BLK_DEV_IDECD is not set
++# CONFIG_BLK_DEV_IDETAPE is not set
++# CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_IDE_TASK_IOCTL is not set
++CONFIG_IDE_PROC_FS=y
++
++#
++# IDE chipset support/bugfixes
++#
++CONFIG_IDE_GENERIC=y
++# CONFIG_BLK_DEV_PLATFORM is not set
++# CONFIG_BLK_DEV_IDEDMA is not set
++CONFIG_IDE_ARCH_OBSOLETE_INIT=y
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++CONFIG_MARVELL_PHY=y
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++CONFIG_MDIO_BITBANG=y
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++CONFIG_FS_ENET=y
++# CONFIG_FS_ENET_HAS_SCC is not set
++CONFIG_FS_ENET_HAS_FCC=y
++CONFIG_FS_ENET_MDIO_FCC=y
++CONFIG_NETDEV_1000=y
++# CONFIG_E1000E_ENABLED is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_SERIAL_CPM=y
++CONFIG_SERIAL_CPM_CONSOLE=y
++CONFIG_SERIAL_CPM_SCC1=y
++# CONFIG_SERIAL_CPM_SCC2 is not set
++# CONFIG_SERIAL_CPM_SCC3 is not set
++# CONFIG_SERIAL_CPM_SCC4 is not set
++# CONFIG_SERIAL_CPM_SMC1 is not set
++# CONFIG_SERIAL_CPM_SMC2 is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=y
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++# CONFIG_USB_ARCH_HAS_HCD is not set
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++CONFIG_DEBUG_MUTEXES=y
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_HIGHMEM is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++CONFIG_FORCED_INLINING=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_KGDB_CONSOLE is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_SEQIV is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_PPC_CLOCK is not set
++CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/85xx/mpc8540_ads_defconfig b/arch/powerpc/configs/85xx/mpc8540_ads_defconfig
+new file mode 100644
+index 0000000..b998539
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/mpc8540_ads_defconfig
+@@ -0,0 +1,796 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:25 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++# CONFIG_MODULES is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++CONFIG_MPC8540_ADS=y
++# CONFIG_MPC8560_ADS is not set
++# CONFIG_MPC85xx_CDS is not set
++# CONFIG_MPC85xx_MDS is not set
++# CONFIG_MPC85xx_DS is not set
++# CONFIG_STX_GP3 is not set
++# CONFIG_TQM8540 is not set
++# CONFIG_TQM8541 is not set
++# CONFIG_TQM8555 is not set
++# CONFIG_TQM8560 is not set
++# CONFIG_SBC8548 is not set
++# CONFIG_SBC8560 is not set
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_CPM2 is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_MISC=y
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++# CONFIG_SECCOMP is not set
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_FSL_SOC=y
++# CONFIG_PCI is not set
++# CONFIG_PCI_DOMAINS is not set
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++CONFIG_XFRM_USER=y
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_E1000E_ENABLED is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=y
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++# CONFIG_USB_ARCH_HAS_HCD is not set
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++CONFIG_DEBUG_MUTEXES=y
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_SEQIV is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/85xx/mpc8544_ds_defconfig b/arch/powerpc/configs/85xx/mpc8544_ds_defconfig
+new file mode 100644
+index 0000000..a9f113b
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/mpc8544_ds_defconfig
+@@ -0,0 +1,1564 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc7
++# Mon Mar 31 11:37:03 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_BSD_PROCESS_ACCT=y
++# CONFIG_BSD_PROCESS_ACCT_V3 is not set
++# CONFIG_TASKSTATS is not set
++CONFIG_AUDIT=y
++# CONFIG_AUDITSYSCALL is not set
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_FORCE_UNLOAD=y
++CONFIG_MODVERSIONS=y
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++# CONFIG_MPC8560_ADS is not set
++# CONFIG_MPC85xx_CDS is not set
++# CONFIG_MPC85xx_MDS is not set
++CONFIG_MPC85xx_DS=y
++# CONFIG_KSI8560 is not set
++# CONFIG_STX_GP3 is not set
++# CONFIG_TQM8540 is not set
++# CONFIG_TQM8541 is not set
++# CONFIG_TQM8555 is not set
++# CONFIG_TQM8560 is not set
++# CONFIG_SBC8548 is not set
++# CONFIG_SBC8560 is not set
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++CONFIG_PPC_I8259=y
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_CPM2 is not set
++CONFIG_FSL_ULI1575=y
++
++#
++# Kernel options
++#
++CONFIG_HIGHMEM=y
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_MISC=m
++CONFIG_FORCE_MAX_ZONEORDER=11
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_FSL_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++CONFIG_XFRM_USER=y
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++CONFIG_NET_KEY=m
++# CONFIG_NET_KEY_MIGRATE is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++CONFIG_IP_ADVANCED_ROUTER=y
++CONFIG_ASK_IP_FIB_HASH=y
++# CONFIG_IP_FIB_TRIE is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_MULTIPLE_TABLES=y
++CONFIG_IP_ROUTE_MULTIPATH=y
++CONFIG_IP_ROUTE_VERBOSE=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++CONFIG_IP_PNP_RARP=y
++CONFIG_NET_IPIP=y
++CONFIG_NET_IPGRE=y
++CONFIG_NET_IPGRE_BROADCAST=y
++CONFIG_IP_MROUTE=y
++CONFIG_IP_PIMSM_V1=y
++CONFIG_IP_PIMSM_V2=y
++CONFIG_ARPD=y
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++CONFIG_INET_TUNNEL=y
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++CONFIG_IPV6=y
++# CONFIG_IPV6_PRIVACY is not set
++# CONFIG_IPV6_ROUTER_PREF is not set
++# CONFIG_IPV6_OPTIMISTIC_DAD is not set
++# CONFIG_INET6_AH is not set
++# CONFIG_INET6_ESP is not set
++# CONFIG_INET6_IPCOMP is not set
++# CONFIG_IPV6_MIP6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++CONFIG_INET6_XFRM_MODE_TRANSPORT=y
++CONFIG_INET6_XFRM_MODE_TUNNEL=y
++CONFIG_INET6_XFRM_MODE_BEET=y
++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
++CONFIG_IPV6_SIT=y
++# CONFIG_IPV6_TUNNEL is not set
++# CONFIG_IPV6_MULTIPLE_TABLES is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++CONFIG_IP_SCTP=m
++# CONFIG_SCTP_DBG_MSG is not set
++# CONFIG_SCTP_DBG_OBJCNT is not set
++# CONFIG_SCTP_HMAC_NONE is not set
++# CONFIG_SCTP_HMAC_SHA1 is not set
++CONFIG_SCTP_HMAC_MD5=y
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++CONFIG_FIB_RULES=y
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++CONFIG_BLK_DEV_NBD=y
++# CONFIG_BLK_DEV_SX8 is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=131072
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++CONFIG_CHR_DEV_ST=y
++# CONFIG_CHR_DEV_OSST is not set
++CONFIG_BLK_DEV_SR=y
++# CONFIG_BLK_DEV_SR_VENDOR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++CONFIG_SCSI_MULTI_LUN=y
++# CONFIG_SCSI_CONSTANTS is not set
++CONFIG_SCSI_LOGGING=y
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_MVSAS is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_IPR is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++CONFIG_ATA=y
++# CONFIG_ATA_NONSTANDARD is not set
++CONFIG_SATA_AHCI=y
++# CONFIG_SATA_SVW is not set
++# CONFIG_ATA_PIIX is not set
++# CONFIG_SATA_MV is not set
++# CONFIG_SATA_NV is not set
++# CONFIG_PDC_ADMA is not set
++# CONFIG_SATA_QSTOR is not set
++# CONFIG_SATA_PROMISE is not set
++# CONFIG_SATA_SX4 is not set
++# CONFIG_SATA_SIL is not set
++# CONFIG_SATA_SIL24 is not set
++# CONFIG_SATA_SIS is not set
++# CONFIG_SATA_ULI is not set
++# CONFIG_SATA_VIA is not set
++# CONFIG_SATA_VITESSE is not set
++# CONFIG_SATA_INIC162X is not set
++# CONFIG_SATA_FSL is not set
++CONFIG_PATA_ALI=y
++# CONFIG_PATA_AMD is not set
++# CONFIG_PATA_ARTOP is not set
++# CONFIG_PATA_ATIIXP is not set
++# CONFIG_PATA_CMD640_PCI is not set
++# CONFIG_PATA_CMD64X is not set
++# CONFIG_PATA_CS5520 is not set
++# CONFIG_PATA_CS5530 is not set
++# CONFIG_PATA_CYPRESS is not set
++# CONFIG_PATA_EFAR is not set
++# CONFIG_ATA_GENERIC is not set
++# CONFIG_PATA_HPT366 is not set
++# CONFIG_PATA_HPT37X is not set
++# CONFIG_PATA_HPT3X2N is not set
++# CONFIG_PATA_HPT3X3 is not set
++# CONFIG_PATA_IT821X is not set
++# CONFIG_PATA_IT8213 is not set
++# CONFIG_PATA_JMICRON is not set
++# CONFIG_PATA_TRIFLEX is not set
++# CONFIG_PATA_MARVELL is not set
++# CONFIG_PATA_MPIIX is not set
++# CONFIG_PATA_OLDPIIX is not set
++# CONFIG_PATA_NETCELL is not set
++# CONFIG_PATA_NINJA32 is not set
++# CONFIG_PATA_NS87410 is not set
++# CONFIG_PATA_NS87415 is not set
++# CONFIG_PATA_OPTI is not set
++# CONFIG_PATA_OPTIDMA is not set
++# CONFIG_PATA_PDC_OLD is not set
++# CONFIG_PATA_RADISYS is not set
++# CONFIG_PATA_RZ1000 is not set
++# CONFIG_PATA_SC1200 is not set
++# CONFIG_PATA_SERVERWORKS is not set
++# CONFIG_PATA_PDC2027X is not set
++# CONFIG_PATA_SIL680 is not set
++# CONFIG_PATA_SIS is not set
++# CONFIG_PATA_VIA is not set
++# CONFIG_PATA_WINBOND is not set
++# CONFIG_PATA_PLATFORM is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++CONFIG_DUMMY=y
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++CONFIG_VITESSE_PHY=y
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++CONFIG_SERIO_I8042=y
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_PCIPS2 is not set
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=2
++CONFIG_SERIAL_8250_RUNTIME_UARTS=2
++CONFIG_SERIAL_8250_EXTENDED=y
++CONFIG_SERIAL_8250_MANY_PORTS=y
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++CONFIG_SERIAL_8250_DETECT_IRQ=y
++CONFIG_SERIAL_8250_RSA=y
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++CONFIG_NVRAM=y
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++# CONFIG_I2C_CHARDEV is not set
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++CONFIG_SENSORS_EEPROM=y
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++CONFIG_DVB_CORE=m
++# CONFIG_DVB_CORE_ATTACH is not set
++CONFIG_DVB_CAPTURE_DRIVERS=y
++
++#
++# Supported SAA7146 based PCI Adapters
++#
++# CONFIG_TTPCI_EEPROM is not set
++# CONFIG_DVB_BUDGET_CORE is not set
++
++#
++# Supported USB Adapters
++#
++# CONFIG_DVB_USB is not set
++# CONFIG_DVB_TTUSB_BUDGET is not set
++# CONFIG_DVB_TTUSB_DEC is not set
++# CONFIG_DVB_CINERGYT2 is not set
++
++#
++# Supported FlexCopII (B2C2) Adapters
++#
++# CONFIG_DVB_B2C2_FLEXCOP is not set
++
++#
++# Supported BT878 Adapters
++#
++
++#
++# Supported Pluto2 Adapters
++#
++# CONFIG_DVB_PLUTO2 is not set
++
++#
++# Supported DVB Frontends
++#
++
++#
++# Customise DVB Frontends
++#
++# CONFIG_DVB_FE_CUSTOMISE is not set
++
++#
++# DVB-S (satellite) frontends
++#
++# CONFIG_DVB_STV0299 is not set
++# CONFIG_DVB_CX24110 is not set
++# CONFIG_DVB_CX24123 is not set
++# CONFIG_DVB_TDA8083 is not set
++# CONFIG_DVB_MT312 is not set
++# CONFIG_DVB_VES1X93 is not set
++# CONFIG_DVB_S5H1420 is not set
++# CONFIG_DVB_TDA10086 is not set
++
++#
++# DVB-T (terrestrial) frontends
++#
++# CONFIG_DVB_SP8870 is not set
++# CONFIG_DVB_SP887X is not set
++# CONFIG_DVB_CX22700 is not set
++# CONFIG_DVB_CX22702 is not set
++# CONFIG_DVB_L64781 is not set
++# CONFIG_DVB_TDA1004X is not set
++# CONFIG_DVB_NXT6000 is not set
++# CONFIG_DVB_MT352 is not set
++# CONFIG_DVB_ZL10353 is not set
++# CONFIG_DVB_DIB3000MB is not set
++# CONFIG_DVB_DIB3000MC is not set
++# CONFIG_DVB_DIB7000M is not set
++# CONFIG_DVB_DIB7000P is not set
++
++#
++# DVB-C (cable) frontends
++#
++# CONFIG_DVB_VES1820 is not set
++# CONFIG_DVB_TDA10021 is not set
++# CONFIG_DVB_TDA10023 is not set
++# CONFIG_DVB_STV0297 is not set
++
++#
++# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
++#
++# CONFIG_DVB_NXT200X is not set
++# CONFIG_DVB_OR51211 is not set
++# CONFIG_DVB_OR51132 is not set
++# CONFIG_DVB_BCM3510 is not set
++# CONFIG_DVB_LGDT330X is not set
++# CONFIG_DVB_S5H1409 is not set
++
++#
++# Tuners/PLL support
++#
++# CONFIG_DVB_PLL is not set
++# CONFIG_DVB_TDA826X is not set
++# CONFIG_DVB_TDA827X is not set
++# CONFIG_DVB_TDA18271 is not set
++# CONFIG_DVB_TUNER_QT1010 is not set
++# CONFIG_DVB_TUNER_MT2060 is not set
++# CONFIG_DVB_TUNER_MT2266 is not set
++# CONFIG_DVB_TUNER_MT2131 is not set
++# CONFIG_DVB_TUNER_DIB0070 is not set
++# CONFIG_DVB_TUNER_XC5000 is not set
++
++#
++# Miscellaneous devices
++#
++# CONFIG_DVB_LNBP21 is not set
++# CONFIG_DVB_ISL6421 is not set
++# CONFIG_DVB_TUA6100 is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=y
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++CONFIG_VGA_CONSOLE=y
++# CONFIG_VGACON_SOFT_SCROLLBACK is not set
++CONFIG_DUMMY_CONSOLE=y
++
++#
++# Sound
++#
++CONFIG_SOUND=y
++
++#
++# Advanced Linux Sound Architecture
++#
++CONFIG_SND=y
++CONFIG_SND_TIMER=y
++CONFIG_SND_PCM=y
++# CONFIG_SND_SEQUENCER is not set
++# CONFIG_SND_MIXER_OSS is not set
++# CONFIG_SND_PCM_OSS is not set
++# CONFIG_SND_DYNAMIC_MINORS is not set
++CONFIG_SND_SUPPORT_OLD_API=y
++CONFIG_SND_VERBOSE_PROCFS=y
++# CONFIG_SND_VERBOSE_PRINTK is not set
++# CONFIG_SND_DEBUG is not set
++
++#
++# Generic devices
++#
++CONFIG_SND_AC97_CODEC=y
++# CONFIG_SND_DUMMY is not set
++# CONFIG_SND_MTPAV is not set
++# CONFIG_SND_SERIAL_U16550 is not set
++# CONFIG_SND_MPU401 is not set
++
++#
++# PCI devices
++#
++# CONFIG_SND_AD1889 is not set
++# CONFIG_SND_ALS300 is not set
++# CONFIG_SND_ALS4000 is not set
++# CONFIG_SND_ALI5451 is not set
++# CONFIG_SND_ATIIXP is not set
++# CONFIG_SND_ATIIXP_MODEM is not set
++# CONFIG_SND_AU8810 is not set
++# CONFIG_SND_AU8820 is not set
++# CONFIG_SND_AU8830 is not set
++# CONFIG_SND_AZT3328 is not set
++# CONFIG_SND_BT87X is not set
++# CONFIG_SND_CA0106 is not set
++# CONFIG_SND_CMIPCI is not set
++# CONFIG_SND_OXYGEN is not set
++# CONFIG_SND_CS4281 is not set
++# CONFIG_SND_CS46XX is not set
++# CONFIG_SND_CS5530 is not set
++# CONFIG_SND_DARLA20 is not set
++# CONFIG_SND_GINA20 is not set
++# CONFIG_SND_LAYLA20 is not set
++# CONFIG_SND_DARLA24 is not set
++# CONFIG_SND_GINA24 is not set
++# CONFIG_SND_LAYLA24 is not set
++# CONFIG_SND_MONA is not set
++# CONFIG_SND_MIA is not set
++# CONFIG_SND_ECHO3G is not set
++# CONFIG_SND_INDIGO is not set
++# CONFIG_SND_INDIGOIO is not set
++# CONFIG_SND_INDIGODJ is not set
++# CONFIG_SND_EMU10K1 is not set
++# CONFIG_SND_EMU10K1X is not set
++# CONFIG_SND_ENS1370 is not set
++# CONFIG_SND_ENS1371 is not set
++# CONFIG_SND_ES1938 is not set
++# CONFIG_SND_ES1968 is not set
++# CONFIG_SND_FM801 is not set
++# CONFIG_SND_HDA_INTEL is not set
++# CONFIG_SND_HDSP is not set
++# CONFIG_SND_HDSPM is not set
++# CONFIG_SND_HIFIER is not set
++# CONFIG_SND_ICE1712 is not set
++# CONFIG_SND_ICE1724 is not set
++CONFIG_SND_INTEL8X0=y
++# CONFIG_SND_INTEL8X0M is not set
++# CONFIG_SND_KORG1212 is not set
++# CONFIG_SND_MAESTRO3 is not set
++# CONFIG_SND_MIXART is not set
++# CONFIG_SND_NM256 is not set
++# CONFIG_SND_PCXHR is not set
++# CONFIG_SND_RIPTIDE is not set
++# CONFIG_SND_RME32 is not set
++# CONFIG_SND_RME96 is not set
++# CONFIG_SND_RME9652 is not set
++# CONFIG_SND_SONICVIBES is not set
++# CONFIG_SND_TRIDENT is not set
++# CONFIG_SND_VIA82XX is not set
++# CONFIG_SND_VIA82XX_MODEM is not set
++# CONFIG_SND_VIRTUOSO is not set
++# CONFIG_SND_VX222 is not set
++# CONFIG_SND_YMFPCI is not set
++# CONFIG_SND_AC97_POWER_SAVE is not set
++
++#
++# ALSA PowerMac devices
++#
++
++#
++# ALSA PowerPC devices
++#
++
++#
++# USB devices
++#
++# CONFIG_SND_USB_AUDIO is not set
++# CONFIG_SND_USB_USX2Y is not set
++# CONFIG_SND_USB_CAIAQ is not set
++
++#
++# System on Chip audio support
++#
++# CONFIG_SND_SOC is not set
++
++#
++# SoC Audio support for SuperH
++#
++
++#
++# ALSA SoC audio for Freescale SOCs
++#
++
++#
++# Open Sound System
++#
++# CONFIG_SOUND_PRIME is not set
++CONFIG_AC97_BUS=y
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++# CONFIG_USB_HIDINPUT_POWERBOOK is not set
++# CONFIG_HID_FF is not set
++# CONFIG_USB_HIDDEV is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++CONFIG_USB_EHCI_HCD=y
++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
++# CONFIG_USB_EHCI_TT_NEWSCHED is not set
++# CONFIG_USB_EHCI_FSL is not set
++CONFIG_USB_EHCI_HCD_PPC_OF=y
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++CONFIG_USB_OHCI_HCD_PPC_OF=y
++CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
++CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
++CONFIG_USB_OHCI_HCD_PCI=y
++CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
++CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_UHCI_HCD is not set
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++CONFIG_RTC_DRV_CMOS=y
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_DMADEVICES=y
++
++#
++# DMA Devices
++#
++CONFIG_FSL_DMA=y
++# CONFIG_FSL_DMA_SELFTEST is not set
++CONFIG_DMA_ENGINE=y
++
++#
++# DMA Clients
++#
++# CONFIG_NET_DMA is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++CONFIG_ISO9660_FS=m
++CONFIG_JOLIET=y
++CONFIG_ZISOFS=y
++CONFIG_UDF_FS=m
++CONFIG_UDF_NLS=y
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=m
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++CONFIG_NTFS_FS=y
++# CONFIG_NTFS_DEBUG is not set
++# CONFIG_NTFS_RW is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++CONFIG_ADFS_FS=m
++# CONFIG_ADFS_FS_RW is not set
++CONFIG_AFFS_FS=m
++CONFIG_HFS_FS=m
++CONFIG_HFSPLUS_FS=m
++CONFIG_BEFS_FS=m
++# CONFIG_BEFS_DEBUG is not set
++CONFIG_BFS_FS=m
++CONFIG_EFS_FS=m
++CONFIG_CRAMFS=y
++CONFIG_VXFS_FS=m
++# CONFIG_MINIX_FS is not set
++CONFIG_HPFS_FS=m
++CONFIG_QNX4FS_FS=m
++# CONFIG_ROMFS_FS is not set
++CONFIG_SYSV_FS=m
++CONFIG_UFS_FS=m
++# CONFIG_UFS_FS_WRITE is not set
++# CONFIG_UFS_DEBUG is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++CONFIG_NFSD=y
++# CONFIG_NFSD_V3 is not set
++CONFIG_NFSD_TCP=y
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_EXPORTFS=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++CONFIG_MAC_PARTITION=y
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++# CONFIG_NLS_CODEPAGE_437 is not set
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++# CONFIG_NLS_ISO8859_1 is not set
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=m
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++CONFIG_LIBCRC32C=m
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_HIGHMEM is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++CONFIG_DEBUG_INFO=y
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_HASH=y
++CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_HMAC=y
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++CONFIG_CRYPTO_SHA1=m
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/85xx/mpc8560_ads_defconfig b/arch/powerpc/configs/85xx/mpc8560_ads_defconfig
+new file mode 100644
+index 0000000..851ac91
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/mpc8560_ads_defconfig
+@@ -0,0 +1,885 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:27 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++# CONFIG_MODULES is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++CONFIG_MPC8560_ADS=y
++# CONFIG_MPC85xx_CDS is not set
++# CONFIG_MPC85xx_MDS is not set
++# CONFIG_MPC85xx_DS is not set
++# CONFIG_STX_GP3 is not set
++# CONFIG_TQM8540 is not set
++# CONFIG_TQM8541 is not set
++# CONFIG_TQM8555 is not set
++# CONFIG_TQM8560 is not set
++# CONFIG_SBC8548 is not set
++# CONFIG_SBC8560 is not set
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++CONFIG_CPM2=y
++CONFIG_PPC_CPM_NEW_BINDING=y
++# CONFIG_FSL_ULI1575 is not set
++CONFIG_CPM=y
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_MISC=y
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_PROC_DEVICETREE is not set
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++# CONFIG_SECCOMP is not set
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_FSL_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++CONFIG_PCI_DEBUG=y
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++CONFIG_MARVELL_PHY=y
++CONFIG_DAVICOM_PHY=y
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_FS_ENET=y
++# CONFIG_FS_ENET_HAS_SCC is not set
++CONFIG_FS_ENET_HAS_FCC=y
++# CONFIG_FS_ENET_MDIO_FCC is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++CONFIG_E1000=y
++CONFIG_E1000_NAPI=y
++# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_SERIAL_CPM=y
++CONFIG_SERIAL_CPM_CONSOLE=y
++CONFIG_SERIAL_CPM_SCC1=y
++CONFIG_SERIAL_CPM_SCC2=y
++# CONFIG_SERIAL_CPM_SCC3 is not set
++# CONFIG_SERIAL_CPM_SCC4 is not set
++# CONFIG_SERIAL_CPM_SMC1 is not set
++# CONFIG_SERIAL_CPM_SMC2 is not set
++# CONFIG_SERIAL_JSM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=y
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++CONFIG_DEBUG_MUTEXES=y
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_KGDB_CONSOLE is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_SEQIV is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
++CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/85xx/mpc8568mds_defconfig b/arch/powerpc/configs/85xx/mpc8568mds_defconfig
+new file mode 100644
+index 0000000..2b866b3
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/mpc8568mds_defconfig
+@@ -0,0 +1,1117 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc7
++# Mon Mar 31 11:37:05 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++# CONFIG_MPC8560_ADS is not set
++# CONFIG_MPC85xx_CDS is not set
++CONFIG_MPC85xx_MDS=y
++# CONFIG_MPC85xx_DS is not set
++# CONFIG_STX_GP3 is not set
++# CONFIG_TQM8540 is not set
++# CONFIG_TQM8541 is not set
++# CONFIG_TQM8555 is not set
++# CONFIG_TQM8560 is not set
++# CONFIG_SBC8548 is not set
++# CONFIG_SBC8560 is not set
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++CONFIG_QUICC_ENGINE=y
++# CONFIG_CPM2 is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_FSL_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++# CONFIG_BLK_DEV_SD is not set
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_MVSAS is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++CONFIG_MARVELL_PHY=y
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_UCC_GETH is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++# CONFIG_SERIAL_QE is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++# CONFIG_BOOKE_WDT is not set
++
++#
++# PCI-based Watchdog Cards
++#
++# CONFIG_PCIPCWATCHDOG is not set
++# CONFIG_WDTPCI is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++CONFIG_RTC_DRV_DS1374=y
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++CONFIG_DEBUGGER=y
++# CONFIG_XMON is not set
++# CONFIG_BDI_SWITCH is not set
++CONFIG_PPC_EARLY_DEBUG=y
++# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
++# CONFIG_PPC_EARLY_DEBUG_G5 is not set
++# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
++# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
++# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
++# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
++# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
++# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
++# CONFIG_PPC_EARLY_DEBUG_44x is not set
++# CONFIG_PPC_EARLY_DEBUG_40x is not set
++# CONFIG_PPC_EARLY_DEBUG_CPM is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
++CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/85xx/mpc8572_ds_defconfig b/arch/powerpc/configs/85xx/mpc8572_ds_defconfig
+new file mode 100644
+index 0000000..53aa6f3
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/mpc8572_ds_defconfig
+@@ -0,0 +1,1549 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc7
++# Mon Mar 31 11:37:06 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_BSD_PROCESS_ACCT=y
++# CONFIG_BSD_PROCESS_ACCT_V3 is not set
++# CONFIG_TASKSTATS is not set
++CONFIG_AUDIT=y
++# CONFIG_AUDITSYSCALL is not set
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_FORCE_UNLOAD=y
++CONFIG_MODVERSIONS=y
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++# CONFIG_MPC8560_ADS is not set
++# CONFIG_MPC85xx_CDS is not set
++# CONFIG_MPC85xx_MDS is not set
++CONFIG_MPC85xx_DS=y
++# CONFIG_STX_GP3 is not set
++# CONFIG_TQM8540 is not set
++# CONFIG_TQM8541 is not set
++# CONFIG_TQM8555 is not set
++# CONFIG_TQM8560 is not set
++# CONFIG_SBC8548 is not set
++# CONFIG_SBC8560 is not set
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++CONFIG_PPC_I8259=y
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_CPM2 is not set
++CONFIG_FSL_ULI1575=y
++
++#
++# Kernel options
++#
++CONFIG_HIGHMEM=y
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_MISC=m
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_FSL_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++CONFIG_XFRM_USER=y
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++CONFIG_NET_KEY=m
++# CONFIG_NET_KEY_MIGRATE is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++CONFIG_IP_ADVANCED_ROUTER=y
++CONFIG_ASK_IP_FIB_HASH=y
++# CONFIG_IP_FIB_TRIE is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_MULTIPLE_TABLES=y
++CONFIG_IP_ROUTE_MULTIPATH=y
++CONFIG_IP_ROUTE_VERBOSE=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++CONFIG_IP_PNP_RARP=y
++CONFIG_NET_IPIP=y
++CONFIG_NET_IPGRE=y
++CONFIG_NET_IPGRE_BROADCAST=y
++CONFIG_IP_MROUTE=y
++CONFIG_IP_PIMSM_V1=y
++CONFIG_IP_PIMSM_V2=y
++CONFIG_ARPD=y
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++CONFIG_INET_TUNNEL=y
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++CONFIG_IPV6=y
++# CONFIG_IPV6_PRIVACY is not set
++# CONFIG_IPV6_ROUTER_PREF is not set
++# CONFIG_IPV6_OPTIMISTIC_DAD is not set
++# CONFIG_INET6_AH is not set
++# CONFIG_INET6_ESP is not set
++# CONFIG_INET6_IPCOMP is not set
++# CONFIG_IPV6_MIP6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++CONFIG_INET6_XFRM_MODE_TRANSPORT=y
++CONFIG_INET6_XFRM_MODE_TUNNEL=y
++CONFIG_INET6_XFRM_MODE_BEET=y
++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
++CONFIG_IPV6_SIT=y
++# CONFIG_IPV6_TUNNEL is not set
++# CONFIG_IPV6_MULTIPLE_TABLES is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++CONFIG_IP_SCTP=m
++# CONFIG_SCTP_DBG_MSG is not set
++# CONFIG_SCTP_DBG_OBJCNT is not set
++# CONFIG_SCTP_HMAC_NONE is not set
++# CONFIG_SCTP_HMAC_SHA1 is not set
++CONFIG_SCTP_HMAC_MD5=y
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++CONFIG_FIB_RULES=y
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++CONFIG_BLK_DEV_NBD=y
++# CONFIG_BLK_DEV_SX8 is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=131072
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++CONFIG_CHR_DEV_ST=y
++# CONFIG_CHR_DEV_OSST is not set
++CONFIG_BLK_DEV_SR=y
++# CONFIG_BLK_DEV_SR_VENDOR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++CONFIG_SCSI_MULTI_LUN=y
++# CONFIG_SCSI_CONSTANTS is not set
++CONFIG_SCSI_LOGGING=y
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_MVSAS is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_IPR is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++CONFIG_ATA=y
++# CONFIG_ATA_NONSTANDARD is not set
++CONFIG_SATA_AHCI=y
++# CONFIG_SATA_SVW is not set
++# CONFIG_ATA_PIIX is not set
++# CONFIG_SATA_MV is not set
++# CONFIG_SATA_NV is not set
++# CONFIG_PDC_ADMA is not set
++# CONFIG_SATA_QSTOR is not set
++# CONFIG_SATA_PROMISE is not set
++# CONFIG_SATA_SX4 is not set
++# CONFIG_SATA_SIL is not set
++# CONFIG_SATA_SIL24 is not set
++# CONFIG_SATA_SIS is not set
++# CONFIG_SATA_ULI is not set
++# CONFIG_SATA_VIA is not set
++# CONFIG_SATA_VITESSE is not set
++# CONFIG_SATA_INIC162X is not set
++# CONFIG_SATA_FSL is not set
++CONFIG_PATA_ALI=y
++# CONFIG_PATA_AMD is not set
++# CONFIG_PATA_ARTOP is not set
++# CONFIG_PATA_ATIIXP is not set
++# CONFIG_PATA_CMD640_PCI is not set
++# CONFIG_PATA_CMD64X is not set
++# CONFIG_PATA_CS5520 is not set
++# CONFIG_PATA_CS5530 is not set
++# CONFIG_PATA_CYPRESS is not set
++# CONFIG_PATA_EFAR is not set
++# CONFIG_ATA_GENERIC is not set
++# CONFIG_PATA_HPT366 is not set
++# CONFIG_PATA_HPT37X is not set
++# CONFIG_PATA_HPT3X2N is not set
++# CONFIG_PATA_HPT3X3 is not set
++# CONFIG_PATA_IT821X is not set
++# CONFIG_PATA_IT8213 is not set
++# CONFIG_PATA_JMICRON is not set
++# CONFIG_PATA_TRIFLEX is not set
++# CONFIG_PATA_MARVELL is not set
++# CONFIG_PATA_MPIIX is not set
++# CONFIG_PATA_OLDPIIX is not set
++# CONFIG_PATA_NETCELL is not set
++# CONFIG_PATA_NINJA32 is not set
++# CONFIG_PATA_NS87410 is not set
++# CONFIG_PATA_NS87415 is not set
++# CONFIG_PATA_OPTI is not set
++# CONFIG_PATA_OPTIDMA is not set
++# CONFIG_PATA_PDC_OLD is not set
++# CONFIG_PATA_RADISYS is not set
++# CONFIG_PATA_RZ1000 is not set
++# CONFIG_PATA_SC1200 is not set
++# CONFIG_PATA_SERVERWORKS is not set
++# CONFIG_PATA_PDC2027X is not set
++# CONFIG_PATA_SIL680 is not set
++# CONFIG_PATA_SIS is not set
++# CONFIG_PATA_VIA is not set
++# CONFIG_PATA_WINBOND is not set
++# CONFIG_PATA_PLATFORM is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++CONFIG_DUMMY=y
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++CONFIG_VITESSE_PHY=y
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++CONFIG_SERIO_I8042=y
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_PCIPS2 is not set
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=2
++CONFIG_SERIAL_8250_RUNTIME_UARTS=2
++CONFIG_SERIAL_8250_EXTENDED=y
++CONFIG_SERIAL_8250_MANY_PORTS=y
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++CONFIG_SERIAL_8250_DETECT_IRQ=y
++CONFIG_SERIAL_8250_RSA=y
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++CONFIG_NVRAM=y
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++# CONFIG_I2C_CHARDEV is not set
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++CONFIG_SENSORS_EEPROM=y
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++CONFIG_DVB_CORE=m
++# CONFIG_DVB_CORE_ATTACH is not set
++CONFIG_DVB_CAPTURE_DRIVERS=y
++
++#
++# Supported SAA7146 based PCI Adapters
++#
++# CONFIG_TTPCI_EEPROM is not set
++# CONFIG_DVB_BUDGET_CORE is not set
++
++#
++# Supported USB Adapters
++#
++# CONFIG_DVB_USB is not set
++# CONFIG_DVB_TTUSB_BUDGET is not set
++# CONFIG_DVB_TTUSB_DEC is not set
++# CONFIG_DVB_CINERGYT2 is not set
++
++#
++# Supported FlexCopII (B2C2) Adapters
++#
++# CONFIG_DVB_B2C2_FLEXCOP is not set
++
++#
++# Supported BT878 Adapters
++#
++
++#
++# Supported Pluto2 Adapters
++#
++# CONFIG_DVB_PLUTO2 is not set
++
++#
++# Supported DVB Frontends
++#
++
++#
++# Customise DVB Frontends
++#
++# CONFIG_DVB_FE_CUSTOMISE is not set
++
++#
++# DVB-S (satellite) frontends
++#
++# CONFIG_DVB_STV0299 is not set
++# CONFIG_DVB_CX24110 is not set
++# CONFIG_DVB_CX24123 is not set
++# CONFIG_DVB_TDA8083 is not set
++# CONFIG_DVB_MT312 is not set
++# CONFIG_DVB_VES1X93 is not set
++# CONFIG_DVB_S5H1420 is not set
++# CONFIG_DVB_TDA10086 is not set
++
++#
++# DVB-T (terrestrial) frontends
++#
++# CONFIG_DVB_SP8870 is not set
++# CONFIG_DVB_SP887X is not set
++# CONFIG_DVB_CX22700 is not set
++# CONFIG_DVB_CX22702 is not set
++# CONFIG_DVB_L64781 is not set
++# CONFIG_DVB_TDA1004X is not set
++# CONFIG_DVB_NXT6000 is not set
++# CONFIG_DVB_MT352 is not set
++# CONFIG_DVB_ZL10353 is not set
++# CONFIG_DVB_DIB3000MB is not set
++# CONFIG_DVB_DIB3000MC is not set
++# CONFIG_DVB_DIB7000M is not set
++# CONFIG_DVB_DIB7000P is not set
++
++#
++# DVB-C (cable) frontends
++#
++# CONFIG_DVB_VES1820 is not set
++# CONFIG_DVB_TDA10021 is not set
++# CONFIG_DVB_TDA10023 is not set
++# CONFIG_DVB_STV0297 is not set
++
++#
++# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
++#
++# CONFIG_DVB_NXT200X is not set
++# CONFIG_DVB_OR51211 is not set
++# CONFIG_DVB_OR51132 is not set
++# CONFIG_DVB_BCM3510 is not set
++# CONFIG_DVB_LGDT330X is not set
++# CONFIG_DVB_S5H1409 is not set
++
++#
++# Tuners/PLL support
++#
++# CONFIG_DVB_PLL is not set
++# CONFIG_DVB_TDA826X is not set
++# CONFIG_DVB_TDA827X is not set
++# CONFIG_DVB_TDA18271 is not set
++# CONFIG_DVB_TUNER_QT1010 is not set
++# CONFIG_DVB_TUNER_MT2060 is not set
++# CONFIG_DVB_TUNER_MT2266 is not set
++# CONFIG_DVB_TUNER_MT2131 is not set
++# CONFIG_DVB_TUNER_DIB0070 is not set
++# CONFIG_DVB_TUNER_XC5000 is not set
++
++#
++# Miscellaneous devices
++#
++# CONFIG_DVB_LNBP21 is not set
++# CONFIG_DVB_ISL6421 is not set
++# CONFIG_DVB_TUA6100 is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=y
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++CONFIG_VGA_CONSOLE=y
++# CONFIG_VGACON_SOFT_SCROLLBACK is not set
++CONFIG_DUMMY_CONSOLE=y
++
++#
++# Sound
++#
++CONFIG_SOUND=y
++
++#
++# Advanced Linux Sound Architecture
++#
++CONFIG_SND=y
++CONFIG_SND_TIMER=y
++CONFIG_SND_PCM=y
++# CONFIG_SND_SEQUENCER is not set
++# CONFIG_SND_MIXER_OSS is not set
++# CONFIG_SND_PCM_OSS is not set
++# CONFIG_SND_DYNAMIC_MINORS is not set
++CONFIG_SND_SUPPORT_OLD_API=y
++CONFIG_SND_VERBOSE_PROCFS=y
++# CONFIG_SND_VERBOSE_PRINTK is not set
++# CONFIG_SND_DEBUG is not set
++
++#
++# Generic devices
++#
++CONFIG_SND_AC97_CODEC=y
++# CONFIG_SND_DUMMY is not set
++# CONFIG_SND_MTPAV is not set
++# CONFIG_SND_SERIAL_U16550 is not set
++# CONFIG_SND_MPU401 is not set
++
++#
++# PCI devices
++#
++# CONFIG_SND_AD1889 is not set
++# CONFIG_SND_ALS300 is not set
++# CONFIG_SND_ALS4000 is not set
++# CONFIG_SND_ALI5451 is not set
++# CONFIG_SND_ATIIXP is not set
++# CONFIG_SND_ATIIXP_MODEM is not set
++# CONFIG_SND_AU8810 is not set
++# CONFIG_SND_AU8820 is not set
++# CONFIG_SND_AU8830 is not set
++# CONFIG_SND_AZT3328 is not set
++# CONFIG_SND_BT87X is not set
++# CONFIG_SND_CA0106 is not set
++# CONFIG_SND_CMIPCI is not set
++# CONFIG_SND_OXYGEN is not set
++# CONFIG_SND_CS4281 is not set
++# CONFIG_SND_CS46XX is not set
++# CONFIG_SND_CS5530 is not set
++# CONFIG_SND_DARLA20 is not set
++# CONFIG_SND_GINA20 is not set
++# CONFIG_SND_LAYLA20 is not set
++# CONFIG_SND_DARLA24 is not set
++# CONFIG_SND_GINA24 is not set
++# CONFIG_SND_LAYLA24 is not set
++# CONFIG_SND_MONA is not set
++# CONFIG_SND_MIA is not set
++# CONFIG_SND_ECHO3G is not set
++# CONFIG_SND_INDIGO is not set
++# CONFIG_SND_INDIGOIO is not set
++# CONFIG_SND_INDIGODJ is not set
++# CONFIG_SND_EMU10K1 is not set
++# CONFIG_SND_EMU10K1X is not set
++# CONFIG_SND_ENS1370 is not set
++# CONFIG_SND_ENS1371 is not set
++# CONFIG_SND_ES1938 is not set
++# CONFIG_SND_ES1968 is not set
++# CONFIG_SND_FM801 is not set
++# CONFIG_SND_HDA_INTEL is not set
++# CONFIG_SND_HDSP is not set
++# CONFIG_SND_HDSPM is not set
++# CONFIG_SND_HIFIER is not set
++# CONFIG_SND_ICE1712 is not set
++# CONFIG_SND_ICE1724 is not set
++CONFIG_SND_INTEL8X0=y
++# CONFIG_SND_INTEL8X0M is not set
++# CONFIG_SND_KORG1212 is not set
++# CONFIG_SND_MAESTRO3 is not set
++# CONFIG_SND_MIXART is not set
++# CONFIG_SND_NM256 is not set
++# CONFIG_SND_PCXHR is not set
++# CONFIG_SND_RIPTIDE is not set
++# CONFIG_SND_RME32 is not set
++# CONFIG_SND_RME96 is not set
++# CONFIG_SND_RME9652 is not set
++# CONFIG_SND_SONICVIBES is not set
++# CONFIG_SND_TRIDENT is not set
++# CONFIG_SND_VIA82XX is not set
++# CONFIG_SND_VIA82XX_MODEM is not set
++# CONFIG_SND_VIRTUOSO is not set
++# CONFIG_SND_VX222 is not set
++# CONFIG_SND_YMFPCI is not set
++# CONFIG_SND_AC97_POWER_SAVE is not set
++
++#
++# ALSA PowerMac devices
++#
++
++#
++# ALSA PowerPC devices
++#
++
++#
++# USB devices
++#
++# CONFIG_SND_USB_AUDIO is not set
++# CONFIG_SND_USB_USX2Y is not set
++# CONFIG_SND_USB_CAIAQ is not set
++
++#
++# System on Chip audio support
++#
++# CONFIG_SND_SOC is not set
++
++#
++# SoC Audio support for SuperH
++#
++
++#
++# ALSA SoC audio for Freescale SOCs
++#
++
++#
++# Open Sound System
++#
++# CONFIG_SOUND_PRIME is not set
++CONFIG_AC97_BUS=y
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++# CONFIG_USB_HIDINPUT_POWERBOOK is not set
++# CONFIG_HID_FF is not set
++# CONFIG_USB_HIDDEV is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++CONFIG_USB_EHCI_HCD=y
++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
++# CONFIG_USB_EHCI_TT_NEWSCHED is not set
++# CONFIG_USB_EHCI_FSL is not set
++CONFIG_USB_EHCI_HCD_PPC_OF=y
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++CONFIG_USB_OHCI_HCD_PPC_OF=y
++CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
++CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
++CONFIG_USB_OHCI_HCD_PCI=y
++CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
++CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_UHCI_HCD is not set
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_S35390A is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++CONFIG_RTC_DRV_CMOS=y
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++CONFIG_ISO9660_FS=m
++CONFIG_JOLIET=y
++CONFIG_ZISOFS=y
++CONFIG_UDF_FS=m
++CONFIG_UDF_NLS=y
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=m
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++CONFIG_NTFS_FS=y
++# CONFIG_NTFS_DEBUG is not set
++# CONFIG_NTFS_RW is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++CONFIG_ADFS_FS=m
++# CONFIG_ADFS_FS_RW is not set
++CONFIG_AFFS_FS=m
++CONFIG_HFS_FS=m
++CONFIG_HFSPLUS_FS=m
++CONFIG_BEFS_FS=m
++# CONFIG_BEFS_DEBUG is not set
++CONFIG_BFS_FS=m
++CONFIG_EFS_FS=m
++CONFIG_CRAMFS=y
++CONFIG_VXFS_FS=m
++# CONFIG_MINIX_FS is not set
++CONFIG_HPFS_FS=m
++CONFIG_QNX4FS_FS=m
++# CONFIG_ROMFS_FS is not set
++CONFIG_SYSV_FS=m
++CONFIG_UFS_FS=m
++# CONFIG_UFS_FS_WRITE is not set
++# CONFIG_UFS_DEBUG is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++CONFIG_NFSD=y
++# CONFIG_NFSD_V3 is not set
++CONFIG_NFSD_TCP=y
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_EXPORTFS=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++CONFIG_MAC_PARTITION=y
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++# CONFIG_NLS_CODEPAGE_437 is not set
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++# CONFIG_NLS_ISO8859_1 is not set
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=m
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++CONFIG_LIBCRC32C=m
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_HIGHMEM is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++CONFIG_DEBUG_INFO=y
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_HASH=y
++CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_HMAC=y
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++CONFIG_CRYPTO_SHA1=m
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/85xx/mpc85xx_cds_defconfig b/arch/powerpc/configs/85xx/mpc85xx_cds_defconfig
+new file mode 100644
+index 0000000..a469fe9
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/mpc85xx_cds_defconfig
+@@ -0,0 +1,935 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:30 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++# CONFIG_FAIR_GROUP_SCHED is not set
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++# CONFIG_MODULES is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++# CONFIG_MPC8560_ADS is not set
++CONFIG_MPC85xx_CDS=y
++# CONFIG_MPC85xx_MDS is not set
++# CONFIG_MPC85xx_DS is not set
++# CONFIG_STX_GP3 is not set
++# CONFIG_TQM8540 is not set
++# CONFIG_TQM8541 is not set
++# CONFIG_TQM8555 is not set
++# CONFIG_TQM8560 is not set
++# CONFIG_SBC8548 is not set
++# CONFIG_SBC8560 is not set
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++CONFIG_PPC_I8259=y
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_CPM2 is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_MISC=y
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++# CONFIG_SECCOMP is not set
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_FSL_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++CONFIG_XFRM_USER=y
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++CONFIG_IDE=y
++CONFIG_IDE_MAX_HWIFS=4
++CONFIG_BLK_DEV_IDE=y
++
++#
++# Please see Documentation/ide/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_IDE_SATA is not set
++# CONFIG_BLK_DEV_IDEDISK is not set
++# CONFIG_IDEDISK_MULTI_MODE is not set
++# CONFIG_BLK_DEV_IDECD is not set
++# CONFIG_BLK_DEV_IDETAPE is not set
++# CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_IDE_TASK_IOCTL is not set
++CONFIG_IDE_PROC_FS=y
++
++#
++# IDE chipset support/bugfixes
++#
++CONFIG_IDE_GENERIC=y
++# CONFIG_BLK_DEV_PLATFORM is not set
++CONFIG_BLK_DEV_IDEDMA_SFF=y
++
++#
++# PCI IDE chipsets support
++#
++CONFIG_BLK_DEV_IDEPCI=y
++CONFIG_IDEPCI_PCIBUS_ORDER=y
++# CONFIG_BLK_DEV_OFFBOARD is not set
++CONFIG_BLK_DEV_GENERIC=y
++# CONFIG_BLK_DEV_OPTI621 is not set
++CONFIG_BLK_DEV_IDEDMA_PCI=y
++# CONFIG_BLK_DEV_AEC62XX is not set
++# CONFIG_BLK_DEV_ALI15X3 is not set
++# CONFIG_BLK_DEV_AMD74XX is not set
++# CONFIG_BLK_DEV_CMD64X is not set
++# CONFIG_BLK_DEV_TRIFLEX is not set
++# CONFIG_BLK_DEV_CY82C693 is not set
++# CONFIG_BLK_DEV_CS5520 is not set
++# CONFIG_BLK_DEV_CS5530 is not set
++# CONFIG_BLK_DEV_HPT34X is not set
++# CONFIG_BLK_DEV_HPT366 is not set
++# CONFIG_BLK_DEV_JMICRON is not set
++# CONFIG_BLK_DEV_SC1200 is not set
++# CONFIG_BLK_DEV_PIIX is not set
++# CONFIG_BLK_DEV_IT8213 is not set
++# CONFIG_BLK_DEV_IT821X is not set
++# CONFIG_BLK_DEV_NS87415 is not set
++# CONFIG_BLK_DEV_PDC202XX_OLD is not set
++# CONFIG_BLK_DEV_PDC202XX_NEW is not set
++# CONFIG_BLK_DEV_SVWKS is not set
++# CONFIG_BLK_DEV_SIIMAGE is not set
++# CONFIG_BLK_DEV_SL82C105 is not set
++# CONFIG_BLK_DEV_SLC90E66 is not set
++# CONFIG_BLK_DEV_TRM290 is not set
++CONFIG_BLK_DEV_VIA82CXXX=y
++# CONFIG_BLK_DEV_TC86C001 is not set
++CONFIG_BLK_DEV_IDEDMA=y
++CONFIG_IDE_ARCH_OBSOLETE_INIT=y
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++CONFIG_E1000=y
++CONFIG_E1000_NAPI=y
++# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=y
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++CONFIG_DEBUG_MUTEXES=y
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_SEQIV is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/85xx/sbc8548_defconfig b/arch/powerpc/configs/85xx/sbc8548_defconfig
+new file mode 100644
+index 0000000..67f6797
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/sbc8548_defconfig
+@@ -0,0 +1,812 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:39 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++# CONFIG_MODULES is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++# CONFIG_MPC8560_ADS is not set
++# CONFIG_MPC85xx_CDS is not set
++# CONFIG_MPC85xx_MDS is not set
++# CONFIG_MPC85xx_DS is not set
++# CONFIG_STX_GP3 is not set
++# CONFIG_TQM8540 is not set
++# CONFIG_TQM8541 is not set
++# CONFIG_TQM8555 is not set
++# CONFIG_TQM8560 is not set
++CONFIG_SBC8548=y
++# CONFIG_SBC8560 is not set
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_CPM2 is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_MISC=y
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++# CONFIG_SECCOMP is not set
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_FSL_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++CONFIG_XFRM_USER=y
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=4096
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++CONFIG_BROADCOM_PHY=y
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=y
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++# CONFIG_HID_SUPPORT is not set
++# CONFIG_USB_SUPPORT is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++# CONFIG_EXT2_FS is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_SEQIV is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/85xx/sbc8560_defconfig b/arch/powerpc/configs/85xx/sbc8560_defconfig
+new file mode 100644
+index 0000000..fef6055
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/sbc8560_defconfig
+@@ -0,0 +1,830 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:39 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++# CONFIG_MODULES is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++# CONFIG_MPC8560_ADS is not set
++# CONFIG_MPC85xx_CDS is not set
++# CONFIG_MPC85xx_MDS is not set
++# CONFIG_MPC85xx_DS is not set
++# CONFIG_STX_GP3 is not set
++# CONFIG_TQM8540 is not set
++# CONFIG_TQM8541 is not set
++# CONFIG_TQM8555 is not set
++# CONFIG_TQM8560 is not set
++# CONFIG_SBC8548 is not set
++CONFIG_SBC8560=y
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_CPM2 is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_MISC=y
++# CONFIG_MATH_EMULATION is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++# CONFIG_SECCOMP is not set
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_FSL_SOC=y
++# CONFIG_PCI is not set
++# CONFIG_PCI_DOMAINS is not set
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++CONFIG_XFRM_USER=y
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++CONFIG_BROADCOM_PHY=y
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_E1000E_ENABLED is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=2
++CONFIG_SERIAL_8250_RUNTIME_UARTS=2
++# CONFIG_SERIAL_8250_EXTENDED is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=y
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++# CONFIG_USB_ARCH_HAS_HCD is not set
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++CONFIG_RTC_DRV_M48T59=y
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++# CONFIG_EXT2_FS is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++CONFIG_DEBUG_MUTEXES=y
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_BDI_SWITCH is not set
++CONFIG_PPC_EARLY_DEBUG=y
++# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
++# CONFIG_PPC_EARLY_DEBUG_G5 is not set
++# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
++# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
++# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
++# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
++# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
++# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
++# CONFIG_PPC_EARLY_DEBUG_44x is not set
++# CONFIG_PPC_EARLY_DEBUG_40x is not set
++# CONFIG_PPC_EARLY_DEBUG_CPM is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_SEQIV is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/85xx/stx_gp3_defconfig b/arch/powerpc/configs/85xx/stx_gp3_defconfig
+new file mode 100644
+index 0000000..1d303c4
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/stx_gp3_defconfig
+@@ -0,0 +1,1253 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:42 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++# CONFIG_MODULE_UNLOAD is not set
++CONFIG_MODVERSIONS=y
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++# CONFIG_MPC8560_ADS is not set
++# CONFIG_MPC85xx_CDS is not set
++# CONFIG_MPC85xx_MDS is not set
++# CONFIG_MPC85xx_DS is not set
++CONFIG_STX_GP3=y
++# CONFIG_TQM8540 is not set
++# CONFIG_TQM8541 is not set
++# CONFIG_TQM8555 is not set
++# CONFIG_TQM8560 is not set
++# CONFIG_SBC8548 is not set
++# CONFIG_SBC8560 is not set
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++CONFIG_CPM2=y
++CONFIG_PPC_CPM_NEW_BINDING=y
++# CONFIG_FSL_ULI1575 is not set
++CONFIG_CPM=y
++
++#
++# Kernel options
++#
++CONFIG_HIGHMEM=y
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_MISC=m
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_FSL_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++# CONFIG_IP_PNP_DHCP is not set
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IP_VS is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++CONFIG_NETFILTER=y
++# CONFIG_NETFILTER_DEBUG is not set
++CONFIG_NETFILTER_ADVANCED=y
++
++#
++# Core Netfilter Configuration
++#
++# CONFIG_NETFILTER_NETLINK_QUEUE is not set
++# CONFIG_NETFILTER_NETLINK_LOG is not set
++# CONFIG_NF_CONNTRACK is not set
++CONFIG_NETFILTER_XTABLES=m
++# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
++# CONFIG_NETFILTER_XT_TARGET_MARK is not set
++# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
++# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
++# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
++# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
++# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
++# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
++# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
++# CONFIG_NETFILTER_XT_MATCH_ESP is not set
++# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
++# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
++# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
++# CONFIG_NETFILTER_XT_MATCH_MAC is not set
++# CONFIG_NETFILTER_XT_MATCH_MARK is not set
++# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
++# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
++# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
++# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
++# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
++# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
++# CONFIG_NETFILTER_XT_MATCH_REALM is not set
++# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
++# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
++# CONFIG_NETFILTER_XT_MATCH_STRING is not set
++# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
++# CONFIG_NETFILTER_XT_MATCH_TIME is not set
++# CONFIG_NETFILTER_XT_MATCH_U32 is not set
++# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
++
++#
++# IP: Netfilter Configuration
++#
++# CONFIG_IP_NF_QUEUE is not set
++CONFIG_IP_NF_IPTABLES=m
++# CONFIG_IP_NF_MATCH_RECENT is not set
++# CONFIG_IP_NF_MATCH_ECN is not set
++# CONFIG_IP_NF_MATCH_AH is not set
++# CONFIG_IP_NF_MATCH_TTL is not set
++# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
++CONFIG_IP_NF_FILTER=m
++# CONFIG_IP_NF_TARGET_REJECT is not set
++# CONFIG_IP_NF_TARGET_LOG is not set
++# CONFIG_IP_NF_TARGET_ULOG is not set
++# CONFIG_IP_NF_MANGLE is not set
++# CONFIG_IP_NF_RAW is not set
++# CONFIG_IP_NF_ARPTABLES is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++CONFIG_NET_PKTGEN=y
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++CONFIG_OF_DEVICE=y
++CONFIG_PARPORT=m
++CONFIG_PARPORT_PC=m
++# CONFIG_PARPORT_PC_FIFO is not set
++# CONFIG_PARPORT_PC_SUPERIO is not set
++# CONFIG_PARPORT_GSC is not set
++# CONFIG_PARPORT_AX88796 is not set
++# CONFIG_PARPORT_1284 is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_PARIDE is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=m
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++CONFIG_BLK_DEV_NBD=m
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++CONFIG_IDE=y
++CONFIG_IDE_MAX_HWIFS=4
++CONFIG_BLK_DEV_IDE=y
++
++#
++# Please see Documentation/ide/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_IDE_SATA is not set
++CONFIG_BLK_DEV_IDEDISK=y
++# CONFIG_IDEDISK_MULTI_MODE is not set
++CONFIG_BLK_DEV_IDECD=m
++CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
++# CONFIG_BLK_DEV_IDETAPE is not set
++# CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_BLK_DEV_IDESCSI is not set
++# CONFIG_IDE_TASK_IOCTL is not set
++CONFIG_IDE_PROC_FS=y
++
++#
++# IDE chipset support/bugfixes
++#
++CONFIG_IDE_GENERIC=y
++# CONFIG_BLK_DEV_PLATFORM is not set
++
++#
++# PCI IDE chipsets support
++#
++# CONFIG_BLK_DEV_GENERIC is not set
++# CONFIG_BLK_DEV_OPTI621 is not set
++# CONFIG_BLK_DEV_AEC62XX is not set
++# CONFIG_BLK_DEV_ALI15X3 is not set
++# CONFIG_BLK_DEV_AMD74XX is not set
++# CONFIG_BLK_DEV_CMD64X is not set
++# CONFIG_BLK_DEV_TRIFLEX is not set
++# CONFIG_BLK_DEV_CY82C693 is not set
++# CONFIG_BLK_DEV_CS5520 is not set
++# CONFIG_BLK_DEV_CS5530 is not set
++# CONFIG_BLK_DEV_HPT34X is not set
++# CONFIG_BLK_DEV_HPT366 is not set
++# CONFIG_BLK_DEV_JMICRON is not set
++# CONFIG_BLK_DEV_SC1200 is not set
++# CONFIG_BLK_DEV_PIIX is not set
++# CONFIG_BLK_DEV_IT8213 is not set
++# CONFIG_BLK_DEV_IT821X is not set
++# CONFIG_BLK_DEV_NS87415 is not set
++# CONFIG_BLK_DEV_PDC202XX_OLD is not set
++# CONFIG_BLK_DEV_PDC202XX_NEW is not set
++# CONFIG_BLK_DEV_SVWKS is not set
++# CONFIG_BLK_DEV_SIIMAGE is not set
++# CONFIG_BLK_DEV_SL82C105 is not set
++# CONFIG_BLK_DEV_SLC90E66 is not set
++# CONFIG_BLK_DEV_TRM290 is not set
++# CONFIG_BLK_DEV_VIA82CXXX is not set
++# CONFIG_BLK_DEV_TC86C001 is not set
++# CONFIG_BLK_DEV_IDEDMA is not set
++CONFIG_IDE_ARCH_OBSOLETE_INIT=y
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=m
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=m
++CONFIG_CHR_DEV_ST=m
++# CONFIG_CHR_DEV_OSST is not set
++CONFIG_BLK_DEV_SR=m
++# CONFIG_BLK_DEV_SR_VENDOR is not set
++CONFIG_CHR_DEV_SG=m
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++CONFIG_SCSI_MULTI_LUN=y
++CONFIG_SCSI_CONSTANTS=y
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_PPA is not set
++# CONFIG_SCSI_IMM is not set
++# CONFIG_SCSI_MVSAS is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++CONFIG_MARVELL_PHY=y
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++# CONFIG_NET_POCKET is not set
++# CONFIG_FS_ENET is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PLIP is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1280
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=1024
++CONFIG_INPUT_JOYDEV=m
++CONFIG_INPUT_EVDEV=m
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++CONFIG_KEYBOARD_ATKBD=y
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_PS2_ALPS=y
++CONFIG_MOUSE_PS2_LOGIPS2PP=y
++CONFIG_MOUSE_PS2_SYNAPTICS=y
++CONFIG_MOUSE_PS2_LIFEBOOK=y
++CONFIG_MOUSE_PS2_TRACKPOINT=y
++# CONFIG_MOUSE_PS2_TOUCHKIT is not set
++# CONFIG_MOUSE_SERIAL is not set
++# CONFIG_MOUSE_APPLETOUCH is not set
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++CONFIG_SERIO_I8042=y
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_PARKBD is not set
++# CONFIG_SERIO_PCIPS2 is not set
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_SERIAL_CPM=y
++CONFIG_SERIAL_CPM_CONSOLE=y
++# CONFIG_SERIAL_CPM_SCC1 is not set
++CONFIG_SERIAL_CPM_SCC2=y
++# CONFIG_SERIAL_CPM_SCC3 is not set
++# CONFIG_SERIAL_CPM_SCC4 is not set
++# CONFIG_SERIAL_CPM_SMC1 is not set
++# CONFIG_SERIAL_CPM_SMC2 is not set
++# CONFIG_SERIAL_JSM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++CONFIG_PRINTER=m
++# CONFIG_LP_CONSOLE is not set
++# CONFIG_PPDEV is not set
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=m
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=m
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=m
++
++#
++# I2C Algorithms
++#
++CONFIG_I2C_ALGOBIT=m
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++# CONFIG_I2C_MPC is not set
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++CONFIG_AGP=m
++CONFIG_DRM=m
++# CONFIG_DRM_TDFX is not set
++# CONFIG_DRM_R128 is not set
++# CONFIG_DRM_RADEON is not set
++# CONFIG_DRM_MGA is not set
++# CONFIG_DRM_SIS is not set
++# CONFIG_DRM_VIA is not set
++# CONFIG_DRM_SAVAGE is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++CONFIG_SOUND=m
++
++#
++# Advanced Linux Sound Architecture
++#
++# CONFIG_SND is not set
++
++#
++# Open Sound System
++#
++# CONFIG_SOUND_PRIME is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++# CONFIG_AUXDISPLAY is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_AUTOFS_FS=m
++CONFIG_AUTOFS4_FS=y
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++CONFIG_ISO9660_FS=m
++# CONFIG_JOLIET is not set
++# CONFIG_ZISOFS is not set
++CONFIG_UDF_FS=m
++CONFIG_UDF_NLS=y
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=m
++CONFIG_MSDOS_FS=m
++CONFIG_VFAT_FS=m
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++# CONFIG_PROC_KCORE is not set
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_CRAMFS=m
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++CONFIG_SMB_FS=m
++# CONFIG_SMB_NLS_DEFAULT is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++# CONFIG_NLS_CODEPAGE_437 is not set
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++# CONFIG_NLS_ISO8859_1 is not set
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=y
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=m
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_HIGHMEM is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_KGDB_CONSOLE is not set
++CONFIG_BDI_SWITCH=y
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_SEQIV is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
++CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/85xx/tqm8540_defconfig b/arch/powerpc/configs/85xx/tqm8540_defconfig
+new file mode 100644
+index 0000000..d39ee3b
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/tqm8540_defconfig
+@@ -0,0 +1,1097 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:43 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++# CONFIG_HOTPLUG is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++# CONFIG_MODULES is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++# CONFIG_MPC8560_ADS is not set
++# CONFIG_MPC85xx_CDS is not set
++# CONFIG_MPC85xx_MDS is not set
++# CONFIG_MPC85xx_DS is not set
++# CONFIG_STX_GP3 is not set
++CONFIG_TQM8540=y
++# CONFIG_TQM8541 is not set
++# CONFIG_TQM8555 is not set
++# CONFIG_TQM8560 is not set
++# CONFIG_SBC8548 is not set
++# CONFIG_SBC8560 is not set
++CONFIG_TQM85xx=y
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_CPM2 is not set
++CONFIG_PPC_CPM_NEW_BINDING=y
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_PROC_DEVICETREE is not set
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_FSL_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_OF_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++# CONFIG_MTD_PHYSMAP_OF is not set
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++CONFIG_IDE=y
++CONFIG_IDE_MAX_HWIFS=4
++CONFIG_BLK_DEV_IDE=y
++
++#
++# Please see Documentation/ide/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_IDE_SATA is not set
++CONFIG_BLK_DEV_IDEDISK=y
++# CONFIG_IDEDISK_MULTI_MODE is not set
++# CONFIG_BLK_DEV_IDECD is not set
++# CONFIG_BLK_DEV_IDETAPE is not set
++# CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_IDE_TASK_IOCTL is not set
++CONFIG_IDE_PROC_FS=y
++
++#
++# IDE chipset support/bugfixes
++#
++CONFIG_IDE_GENERIC=y
++# CONFIG_BLK_DEV_PLATFORM is not set
++CONFIG_BLK_DEV_IDEDMA_SFF=y
++
++#
++# PCI IDE chipsets support
++#
++CONFIG_BLK_DEV_IDEPCI=y
++CONFIG_IDEPCI_PCIBUS_ORDER=y
++# CONFIG_BLK_DEV_OFFBOARD is not set
++CONFIG_BLK_DEV_GENERIC=y
++# CONFIG_BLK_DEV_OPTI621 is not set
++CONFIG_BLK_DEV_IDEDMA_PCI=y
++# CONFIG_BLK_DEV_AEC62XX is not set
++# CONFIG_BLK_DEV_ALI15X3 is not set
++# CONFIG_BLK_DEV_AMD74XX is not set
++# CONFIG_BLK_DEV_CMD64X is not set
++# CONFIG_BLK_DEV_TRIFLEX is not set
++# CONFIG_BLK_DEV_CY82C693 is not set
++# CONFIG_BLK_DEV_CS5520 is not set
++# CONFIG_BLK_DEV_CS5530 is not set
++# CONFIG_BLK_DEV_HPT34X is not set
++# CONFIG_BLK_DEV_HPT366 is not set
++# CONFIG_BLK_DEV_JMICRON is not set
++# CONFIG_BLK_DEV_SC1200 is not set
++# CONFIG_BLK_DEV_PIIX is not set
++# CONFIG_BLK_DEV_IT8213 is not set
++# CONFIG_BLK_DEV_IT821X is not set
++# CONFIG_BLK_DEV_NS87415 is not set
++# CONFIG_BLK_DEV_PDC202XX_OLD is not set
++# CONFIG_BLK_DEV_PDC202XX_NEW is not set
++# CONFIG_BLK_DEV_SVWKS is not set
++# CONFIG_BLK_DEV_SIIMAGE is not set
++# CONFIG_BLK_DEV_SL82C105 is not set
++# CONFIG_BLK_DEV_SLC90E66 is not set
++# CONFIG_BLK_DEV_TRM290 is not set
++CONFIG_BLK_DEV_VIA82CXXX=y
++# CONFIG_BLK_DEV_TC86C001 is not set
++CONFIG_BLK_DEV_IDEDMA=y
++CONFIG_IDE_ARCH_OBSOLETE_INIT=y
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++CONFIG_NET_PCI=y
++# CONFIG_PCNET32 is not set
++# CONFIG_AMD8111_ETH is not set
++# CONFIG_ADAPTEC_STARFIRE is not set
++# CONFIG_B44 is not set
++# CONFIG_FORCEDETH is not set
++# CONFIG_EEPRO100 is not set
++CONFIG_E100=y
++# CONFIG_FEALNX is not set
++# CONFIG_NATSEMI is not set
++# CONFIG_NE2K_PCI is not set
++# CONFIG_8139CP is not set
++# CONFIG_8139TOO is not set
++# CONFIG_R6040 is not set
++# CONFIG_SIS900 is not set
++# CONFIG_EPIC100 is not set
++# CONFIG_SUNDANCE is not set
++# CONFIG_TLAN is not set
++# CONFIG_VIA_RHINE is not set
++# CONFIG_SC92031 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++CONFIG_SENSORS_LM75=y
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++CONFIG_HWMON_DEBUG_CHIP=y
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_SEQIV is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/85xx/tqm8541_defconfig b/arch/powerpc/configs/85xx/tqm8541_defconfig
+new file mode 100644
+index 0000000..cbf6ad2
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/tqm8541_defconfig
+@@ -0,0 +1,1109 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:44 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++# CONFIG_HOTPLUG is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++# CONFIG_MODULES is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++# CONFIG_MPC8560_ADS is not set
++# CONFIG_MPC85xx_CDS is not set
++# CONFIG_MPC85xx_MDS is not set
++# CONFIG_MPC85xx_DS is not set
++# CONFIG_STX_GP3 is not set
++# CONFIG_TQM8540 is not set
++CONFIG_TQM8541=y
++# CONFIG_TQM8555 is not set
++# CONFIG_TQM8560 is not set
++# CONFIG_SBC8548 is not set
++# CONFIG_SBC8560 is not set
++CONFIG_TQM85xx=y
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++CONFIG_CPM2=y
++CONFIG_PPC_CPM_NEW_BINDING=y
++# CONFIG_FSL_ULI1575 is not set
++CONFIG_CPM=y
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_PROC_DEVICETREE is not set
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_FSL_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_OF_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++# CONFIG_MTD_PHYSMAP_OF is not set
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++CONFIG_IDE=y
++CONFIG_IDE_MAX_HWIFS=4
++CONFIG_BLK_DEV_IDE=y
++
++#
++# Please see Documentation/ide/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_IDE_SATA is not set
++CONFIG_BLK_DEV_IDEDISK=y
++# CONFIG_IDEDISK_MULTI_MODE is not set
++# CONFIG_BLK_DEV_IDECD is not set
++# CONFIG_BLK_DEV_IDETAPE is not set
++# CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_IDE_TASK_IOCTL is not set
++CONFIG_IDE_PROC_FS=y
++
++#
++# IDE chipset support/bugfixes
++#
++CONFIG_IDE_GENERIC=y
++# CONFIG_BLK_DEV_PLATFORM is not set
++CONFIG_BLK_DEV_IDEDMA_SFF=y
++
++#
++# PCI IDE chipsets support
++#
++CONFIG_BLK_DEV_IDEPCI=y
++CONFIG_IDEPCI_PCIBUS_ORDER=y
++# CONFIG_BLK_DEV_OFFBOARD is not set
++CONFIG_BLK_DEV_GENERIC=y
++# CONFIG_BLK_DEV_OPTI621 is not set
++CONFIG_BLK_DEV_IDEDMA_PCI=y
++# CONFIG_BLK_DEV_AEC62XX is not set
++# CONFIG_BLK_DEV_ALI15X3 is not set
++# CONFIG_BLK_DEV_AMD74XX is not set
++# CONFIG_BLK_DEV_CMD64X is not set
++# CONFIG_BLK_DEV_TRIFLEX is not set
++# CONFIG_BLK_DEV_CY82C693 is not set
++# CONFIG_BLK_DEV_CS5520 is not set
++# CONFIG_BLK_DEV_CS5530 is not set
++# CONFIG_BLK_DEV_HPT34X is not set
++# CONFIG_BLK_DEV_HPT366 is not set
++# CONFIG_BLK_DEV_JMICRON is not set
++# CONFIG_BLK_DEV_SC1200 is not set
++# CONFIG_BLK_DEV_PIIX is not set
++# CONFIG_BLK_DEV_IT8213 is not set
++# CONFIG_BLK_DEV_IT821X is not set
++# CONFIG_BLK_DEV_NS87415 is not set
++# CONFIG_BLK_DEV_PDC202XX_OLD is not set
++# CONFIG_BLK_DEV_PDC202XX_NEW is not set
++# CONFIG_BLK_DEV_SVWKS is not set
++# CONFIG_BLK_DEV_SIIMAGE is not set
++# CONFIG_BLK_DEV_SL82C105 is not set
++# CONFIG_BLK_DEV_SLC90E66 is not set
++# CONFIG_BLK_DEV_TRM290 is not set
++CONFIG_BLK_DEV_VIA82CXXX=y
++# CONFIG_BLK_DEV_TC86C001 is not set
++CONFIG_BLK_DEV_IDEDMA=y
++CONFIG_IDE_ARCH_OBSOLETE_INIT=y
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++CONFIG_NET_PCI=y
++# CONFIG_PCNET32 is not set
++# CONFIG_AMD8111_ETH is not set
++# CONFIG_ADAPTEC_STARFIRE is not set
++# CONFIG_B44 is not set
++# CONFIG_FORCEDETH is not set
++# CONFIG_EEPRO100 is not set
++CONFIG_E100=y
++# CONFIG_FEALNX is not set
++# CONFIG_NATSEMI is not set
++# CONFIG_NE2K_PCI is not set
++# CONFIG_8139CP is not set
++# CONFIG_8139TOO is not set
++# CONFIG_R6040 is not set
++# CONFIG_SIS900 is not set
++# CONFIG_EPIC100 is not set
++# CONFIG_SUNDANCE is not set
++# CONFIG_TLAN is not set
++# CONFIG_VIA_RHINE is not set
++# CONFIG_SC92031 is not set
++# CONFIG_FS_ENET is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_SERIAL_CPM=y
++CONFIG_SERIAL_CPM_CONSOLE=y
++CONFIG_SERIAL_CPM_SCC1=y
++# CONFIG_SERIAL_CPM_SCC2 is not set
++# CONFIG_SERIAL_CPM_SCC3 is not set
++# CONFIG_SERIAL_CPM_SCC4 is not set
++# CONFIG_SERIAL_CPM_SMC1 is not set
++# CONFIG_SERIAL_CPM_SMC2 is not set
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++CONFIG_SENSORS_LM75=y
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++CONFIG_HWMON_DEBUG_CHIP=y
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_KGDB_CONSOLE is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_SEQIV is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
++CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/85xx/tqm8555_defconfig b/arch/powerpc/configs/85xx/tqm8555_defconfig
+new file mode 100644
+index 0000000..bbff962
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/tqm8555_defconfig
+@@ -0,0 +1,1109 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:44 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++# CONFIG_HOTPLUG is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++# CONFIG_MODULES is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++# CONFIG_MPC8560_ADS is not set
++# CONFIG_MPC85xx_CDS is not set
++# CONFIG_MPC85xx_MDS is not set
++# CONFIG_MPC85xx_DS is not set
++# CONFIG_STX_GP3 is not set
++# CONFIG_TQM8540 is not set
++# CONFIG_TQM8541 is not set
++CONFIG_TQM8555=y
++# CONFIG_TQM8560 is not set
++# CONFIG_SBC8548 is not set
++# CONFIG_SBC8560 is not set
++CONFIG_TQM85xx=y
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++CONFIG_CPM2=y
++CONFIG_PPC_CPM_NEW_BINDING=y
++# CONFIG_FSL_ULI1575 is not set
++CONFIG_CPM=y
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_PROC_DEVICETREE is not set
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_FSL_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_OF_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++# CONFIG_MTD_PHYSMAP_OF is not set
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++CONFIG_IDE=y
++CONFIG_IDE_MAX_HWIFS=4
++CONFIG_BLK_DEV_IDE=y
++
++#
++# Please see Documentation/ide/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_IDE_SATA is not set
++CONFIG_BLK_DEV_IDEDISK=y
++# CONFIG_IDEDISK_MULTI_MODE is not set
++# CONFIG_BLK_DEV_IDECD is not set
++# CONFIG_BLK_DEV_IDETAPE is not set
++# CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_IDE_TASK_IOCTL is not set
++CONFIG_IDE_PROC_FS=y
++
++#
++# IDE chipset support/bugfixes
++#
++CONFIG_IDE_GENERIC=y
++# CONFIG_BLK_DEV_PLATFORM is not set
++CONFIG_BLK_DEV_IDEDMA_SFF=y
++
++#
++# PCI IDE chipsets support
++#
++CONFIG_BLK_DEV_IDEPCI=y
++CONFIG_IDEPCI_PCIBUS_ORDER=y
++# CONFIG_BLK_DEV_OFFBOARD is not set
++CONFIG_BLK_DEV_GENERIC=y
++# CONFIG_BLK_DEV_OPTI621 is not set
++CONFIG_BLK_DEV_IDEDMA_PCI=y
++# CONFIG_BLK_DEV_AEC62XX is not set
++# CONFIG_BLK_DEV_ALI15X3 is not set
++# CONFIG_BLK_DEV_AMD74XX is not set
++# CONFIG_BLK_DEV_CMD64X is not set
++# CONFIG_BLK_DEV_TRIFLEX is not set
++# CONFIG_BLK_DEV_CY82C693 is not set
++# CONFIG_BLK_DEV_CS5520 is not set
++# CONFIG_BLK_DEV_CS5530 is not set
++# CONFIG_BLK_DEV_HPT34X is not set
++# CONFIG_BLK_DEV_HPT366 is not set
++# CONFIG_BLK_DEV_JMICRON is not set
++# CONFIG_BLK_DEV_SC1200 is not set
++# CONFIG_BLK_DEV_PIIX is not set
++# CONFIG_BLK_DEV_IT8213 is not set
++# CONFIG_BLK_DEV_IT821X is not set
++# CONFIG_BLK_DEV_NS87415 is not set
++# CONFIG_BLK_DEV_PDC202XX_OLD is not set
++# CONFIG_BLK_DEV_PDC202XX_NEW is not set
++# CONFIG_BLK_DEV_SVWKS is not set
++# CONFIG_BLK_DEV_SIIMAGE is not set
++# CONFIG_BLK_DEV_SL82C105 is not set
++# CONFIG_BLK_DEV_SLC90E66 is not set
++# CONFIG_BLK_DEV_TRM290 is not set
++CONFIG_BLK_DEV_VIA82CXXX=y
++# CONFIG_BLK_DEV_TC86C001 is not set
++CONFIG_BLK_DEV_IDEDMA=y
++CONFIG_IDE_ARCH_OBSOLETE_INIT=y
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++CONFIG_NET_PCI=y
++# CONFIG_PCNET32 is not set
++# CONFIG_AMD8111_ETH is not set
++# CONFIG_ADAPTEC_STARFIRE is not set
++# CONFIG_B44 is not set
++# CONFIG_FORCEDETH is not set
++# CONFIG_EEPRO100 is not set
++CONFIG_E100=y
++# CONFIG_FEALNX is not set
++# CONFIG_NATSEMI is not set
++# CONFIG_NE2K_PCI is not set
++# CONFIG_8139CP is not set
++# CONFIG_8139TOO is not set
++# CONFIG_R6040 is not set
++# CONFIG_SIS900 is not set
++# CONFIG_EPIC100 is not set
++# CONFIG_SUNDANCE is not set
++# CONFIG_TLAN is not set
++# CONFIG_VIA_RHINE is not set
++# CONFIG_SC92031 is not set
++# CONFIG_FS_ENET is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_SERIAL_CPM=y
++CONFIG_SERIAL_CPM_CONSOLE=y
++CONFIG_SERIAL_CPM_SCC1=y
++# CONFIG_SERIAL_CPM_SCC2 is not set
++# CONFIG_SERIAL_CPM_SCC3 is not set
++# CONFIG_SERIAL_CPM_SCC4 is not set
++# CONFIG_SERIAL_CPM_SMC1 is not set
++# CONFIG_SERIAL_CPM_SMC2 is not set
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++CONFIG_SENSORS_LM75=y
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++CONFIG_HWMON_DEBUG_CHIP=y
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_KGDB_CONSOLE is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_SEQIV is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
++CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/85xx/tqm8560_defconfig b/arch/powerpc/configs/85xx/tqm8560_defconfig
+new file mode 100644
+index 0000000..63c5ec8
+--- /dev/null
++++ b/arch/powerpc/configs/85xx/tqm8560_defconfig
+@@ -0,0 +1,1109 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Mon Mar 24 08:48:45 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++CONFIG_PPC_85xx=y
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_E500=y
++CONFIG_BOOKE=y
++CONFIG_FSL_BOOKE=y
++CONFIG_FSL_EMB_PERFMON=y
++# CONFIG_PHYS_64BIT is not set
++CONFIG_SPE=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++# CONFIG_HOTPLUG is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++# CONFIG_EPOLL is not set
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++# CONFIG_MODULES is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_MPC85xx=y
++# CONFIG_MPC8540_ADS is not set
++# CONFIG_MPC8560_ADS is not set
++# CONFIG_MPC85xx_CDS is not set
++# CONFIG_MPC85xx_MDS is not set
++# CONFIG_MPC85xx_DS is not set
++# CONFIG_STX_GP3 is not set
++# CONFIG_TQM8540 is not set
++# CONFIG_TQM8541 is not set
++# CONFIG_TQM8555 is not set
++CONFIG_TQM8560=y
++# CONFIG_SBC8548 is not set
++# CONFIG_SBC8560 is not set
++CONFIG_TQM85xx=y
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++CONFIG_CPM2=y
++CONFIG_PPC_CPM_NEW_BINDING=y
++# CONFIG_FSL_ULI1575 is not set
++CONFIG_CPM=y
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++CONFIG_MATH_EMULATION=y
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_PROC_DEVICETREE is not set
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_FSL_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_OF_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++# CONFIG_MTD_PHYSMAP_OF is not set
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++CONFIG_IDE=y
++CONFIG_IDE_MAX_HWIFS=4
++CONFIG_BLK_DEV_IDE=y
++
++#
++# Please see Documentation/ide/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_IDE_SATA is not set
++CONFIG_BLK_DEV_IDEDISK=y
++# CONFIG_IDEDISK_MULTI_MODE is not set
++# CONFIG_BLK_DEV_IDECD is not set
++# CONFIG_BLK_DEV_IDETAPE is not set
++# CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_IDE_TASK_IOCTL is not set
++CONFIG_IDE_PROC_FS=y
++
++#
++# IDE chipset support/bugfixes
++#
++CONFIG_IDE_GENERIC=y
++# CONFIG_BLK_DEV_PLATFORM is not set
++CONFIG_BLK_DEV_IDEDMA_SFF=y
++
++#
++# PCI IDE chipsets support
++#
++CONFIG_BLK_DEV_IDEPCI=y
++CONFIG_IDEPCI_PCIBUS_ORDER=y
++# CONFIG_BLK_DEV_OFFBOARD is not set
++CONFIG_BLK_DEV_GENERIC=y
++# CONFIG_BLK_DEV_OPTI621 is not set
++CONFIG_BLK_DEV_IDEDMA_PCI=y
++# CONFIG_BLK_DEV_AEC62XX is not set
++# CONFIG_BLK_DEV_ALI15X3 is not set
++# CONFIG_BLK_DEV_AMD74XX is not set
++# CONFIG_BLK_DEV_CMD64X is not set
++# CONFIG_BLK_DEV_TRIFLEX is not set
++# CONFIG_BLK_DEV_CY82C693 is not set
++# CONFIG_BLK_DEV_CS5520 is not set
++# CONFIG_BLK_DEV_CS5530 is not set
++# CONFIG_BLK_DEV_HPT34X is not set
++# CONFIG_BLK_DEV_HPT366 is not set
++# CONFIG_BLK_DEV_JMICRON is not set
++# CONFIG_BLK_DEV_SC1200 is not set
++# CONFIG_BLK_DEV_PIIX is not set
++# CONFIG_BLK_DEV_IT8213 is not set
++# CONFIG_BLK_DEV_IT821X is not set
++# CONFIG_BLK_DEV_NS87415 is not set
++# CONFIG_BLK_DEV_PDC202XX_OLD is not set
++# CONFIG_BLK_DEV_PDC202XX_NEW is not set
++# CONFIG_BLK_DEV_SVWKS is not set
++# CONFIG_BLK_DEV_SIIMAGE is not set
++# CONFIG_BLK_DEV_SL82C105 is not set
++# CONFIG_BLK_DEV_SLC90E66 is not set
++# CONFIG_BLK_DEV_TRM290 is not set
++CONFIG_BLK_DEV_VIA82CXXX=y
++# CONFIG_BLK_DEV_TC86C001 is not set
++CONFIG_BLK_DEV_IDEDMA=y
++CONFIG_IDE_ARCH_OBSOLETE_INIT=y
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++CONFIG_NET_PCI=y
++# CONFIG_PCNET32 is not set
++# CONFIG_AMD8111_ETH is not set
++# CONFIG_ADAPTEC_STARFIRE is not set
++# CONFIG_B44 is not set
++# CONFIG_FORCEDETH is not set
++# CONFIG_EEPRO100 is not set
++CONFIG_E100=y
++# CONFIG_FEALNX is not set
++# CONFIG_NATSEMI is not set
++# CONFIG_NE2K_PCI is not set
++# CONFIG_8139CP is not set
++# CONFIG_8139TOO is not set
++# CONFIG_R6040 is not set
++# CONFIG_SIS900 is not set
++# CONFIG_EPIC100 is not set
++# CONFIG_SUNDANCE is not set
++# CONFIG_TLAN is not set
++# CONFIG_VIA_RHINE is not set
++# CONFIG_SC92031 is not set
++# CONFIG_FS_ENET is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++CONFIG_GFAR_NAPI=y
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_SERIAL_CPM=y
++CONFIG_SERIAL_CPM_CONSOLE=y
++CONFIG_SERIAL_CPM_SCC1=y
++# CONFIG_SERIAL_CPM_SCC2 is not set
++# CONFIG_SERIAL_CPM_SCC3 is not set
++# CONFIG_SERIAL_CPM_SCC4 is not set
++# CONFIG_SERIAL_CPM_SMC1 is not set
++# CONFIG_SERIAL_CPM_SMC2 is not set
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_NVRAM is not set
++CONFIG_GEN_RTC=y
++# CONFIG_GEN_RTC_X is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++CONFIG_SENSORS_LM75=y
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++CONFIG_HWMON_DEBUG_CHIP=y
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++# CONFIG_MSDOS_PARTITION is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_KGDB_CONSOLE is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_SEQIV is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
++CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/bamboo_defconfig b/arch/powerpc/configs/bamboo_defconfig
+deleted file mode 100644
+index c44db55..0000000
+--- a/arch/powerpc/configs/bamboo_defconfig
++++ /dev/null
+@@ -1,815 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc2
+-# Fri Feb 15 21:36:39 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-CONFIG_44x=y
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-CONFIG_4xx=y
+-CONFIG_BOOKE=y
+-CONFIG_PTE_64BIT=y
+-CONFIG_PHYS_64BIT=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-# CONFIG_DEFAULT_UIMAGE is not set
+-CONFIG_PPC_DCR_NATIVE=y
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_PPC_DCR=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_ALL is not set
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-# CONFIG_PPC4xx_PCI_EXPRESS is not set
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_BAMBOO=y
+-# CONFIG_EBONY is not set
+-# CONFIG_SEQUOIA is not set
+-# CONFIG_TAISHAN is not set
+-# CONFIG_KATMAI is not set
+-# CONFIG_RAINIER is not set
+-# CONFIG_WARP is not set
+-CONFIG_440EP=y
+-CONFIG_IBM440EP_ERR42=y
+-# CONFIG_IPIC is not set
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_RCU_TRACE=y
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_MATH_EMULATION is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-CONFIG_RESOURCES_64BIT=y
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-CONFIG_CMDLINE_BOOL=y
+-CONFIG_CMDLINE=""
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x01000000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+-# CONFIG_INET_XFRM_MODE_BEET is not set
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-CONFIG_CONNECTOR=y
+-CONFIG_PROC_EVENTS=y
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=35000
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-# CONFIG_XILINX_SYSACE is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-# CONFIG_PHYLIB is not set
+-CONFIG_NET_ETHERNET=y
+-# CONFIG_MII is not set
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-CONFIG_IBM_NEW_EMAC=y
+-CONFIG_IBM_NEW_EMAC_RXB=128
+-CONFIG_IBM_NEW_EMAC_TXB=64
+-CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+-CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+-CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+-# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+-CONFIG_IBM_NEW_EMAC_ZMII=y
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-# CONFIG_SERIAL_8250_PCI is not set
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-CONFIG_SERIAL_8250_EXTENDED=y
+-# CONFIG_SERIAL_8250_MANY_PORTS is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+-# CONFIG_SERIAL_8250_RSA is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_SERIAL_OF_PLATFORM=y
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-CONFIG_THERMAL=y
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_MAGIC_SYSRQ=y
+-# CONFIG_UNUSED_SYMBOLS is not set
+-CONFIG_DEBUG_FS=y
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-CONFIG_DEBUGGER=y
+-# CONFIG_KGDB is not set
+-# CONFIG_XMON is not set
+-# CONFIG_VIRQ_DEBUG is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=y
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=y
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/chrp32_defconfig b/arch/powerpc/configs/chrp32_defconfig
+index 38b85b2..d7fd298 100644
+--- a/arch/powerpc/configs/chrp32_defconfig
++++ b/arch/powerpc/configs/chrp32_defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+ # Linux kernel version: 2.6.25-rc6
+-# Thu Mar 20 10:33:36 2008
++# Thu Mar 27 13:55:37 2008
+ #
+ # CONFIG_PPC64 is not set
+
+@@ -74,8 +74,6 @@ CONFIG_IKCONFIG_PROC=y
+ CONFIG_LOG_BUF_SHIFT=15
+ # CONFIG_CGROUPS is not set
+ # CONFIG_GROUP_SCHED is not set
+-# CONFIG_USER_SCHED is not set
+-# CONFIG_CGROUP_SCHED is not set
+ CONFIG_SYSFS_DEPRECATED=y
+ CONFIG_SYSFS_DEPRECATED_V2=y
+ # CONFIG_RELAY is not set
+@@ -243,7 +241,7 @@ CONFIG_PCI_SYSCALL=y
+ # CONFIG_PCIEPORTBUS is not set
+ CONFIG_ARCH_SUPPORTS_MSI=y
+ # CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_LEGACY is not set
+ # CONFIG_PCI_DEBUG is not set
+ # CONFIG_PCCARD is not set
+ # CONFIG_HOTPLUG_PCI is not set
+@@ -1328,6 +1326,7 @@ CONFIG_PLIST=y
+ CONFIG_HAS_IOMEM=y
+ CONFIG_HAS_IOPORT=y
+ CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
+
+ #
+ # Kernel hacking
+diff --git a/arch/powerpc/configs/ebony_defconfig b/arch/powerpc/configs/ebony_defconfig
+deleted file mode 100644
+index 07c8d4c..0000000
+--- a/arch/powerpc/configs/ebony_defconfig
++++ /dev/null
+@@ -1,898 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc2
+-# Fri Feb 15 21:50:44 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-CONFIG_44x=y
+-# CONFIG_E200 is not set
+-CONFIG_4xx=y
+-CONFIG_BOOKE=y
+-CONFIG_PTE_64BIT=y
+-CONFIG_PHYS_64BIT=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-# CONFIG_DEFAULT_UIMAGE is not set
+-CONFIG_PPC_DCR_NATIVE=y
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_PPC_DCR=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-CONFIG_KALLSYMS_ALL=y
+-CONFIG_KALLSYMS_EXTRA_PASS=y
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-# CONFIG_PPC4xx_PCI_EXPRESS is not set
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-# CONFIG_BAMBOO is not set
+-CONFIG_EBONY=y
+-# CONFIG_SEQUOIA is not set
+-# CONFIG_TAISHAN is not set
+-# CONFIG_KATMAI is not set
+-# CONFIG_RAINIER is not set
+-# CONFIG_WARP is not set
+-CONFIG_440GP=y
+-# CONFIG_IPIC is not set
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-CONFIG_OF_RTC=y
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_RCU_TRACE=y
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-CONFIG_RESOURCES_64BIT=y
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x01000000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+-# CONFIG_INET_XFRM_MODE_BEET is not set
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-CONFIG_CONNECTOR=y
+-CONFIG_PROC_EVENTS=y
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-# CONFIG_MTD_CMDLINE_PARTS is not set
+-CONFIG_MTD_OF_PARTS=y
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=y
+-CONFIG_MTD_BLOCK=y
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-CONFIG_MTD_JEDECPROBE=y
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-CONFIG_MTD_PHYSMAP_OF=y
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=35000
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-# CONFIG_XILINX_SYSACE is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-# CONFIG_PHYLIB is not set
+-CONFIG_NET_ETHERNET=y
+-# CONFIG_MII is not set
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-CONFIG_IBM_NEW_EMAC=y
+-CONFIG_IBM_NEW_EMAC_RXB=128
+-CONFIG_IBM_NEW_EMAC_TXB=64
+-CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+-CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+-CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+-# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+-CONFIG_IBM_NEW_EMAC_ZMII=y
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-# CONFIG_SERIAL_8250_PCI is not set
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-CONFIG_SERIAL_8250_EXTENDED=y
+-# CONFIG_SERIAL_8250_MANY_PORTS is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+-# CONFIG_SERIAL_8250_RSA is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_SERIAL_OF_PLATFORM=y
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-CONFIG_THERMAL=y
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-# CONFIG_DAB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_JFFS2_FS=y
+-CONFIG_JFFS2_FS_DEBUG=0
+-CONFIG_JFFS2_FS_WRITEBUFFER=y
+-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+-# CONFIG_JFFS2_SUMMARY is not set
+-# CONFIG_JFFS2_FS_XATTR is not set
+-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+-CONFIG_JFFS2_ZLIB=y
+-# CONFIG_JFFS2_LZO is not set
+-CONFIG_JFFS2_RTIME=y
+-# CONFIG_JFFS2_RUBIN is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_ZLIB_DEFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_MAGIC_SYSRQ=y
+-# CONFIG_UNUSED_SYMBOLS is not set
+-CONFIG_DEBUG_FS=y
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-CONFIG_DEBUG_BUGVERBOSE=y
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_VIRQ_DEBUG is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=y
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=y
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-# CONFIG_CRYPTO_HW is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/ep405_defconfig b/arch/powerpc/configs/ep405_defconfig
+deleted file mode 100644
+index e24240a..0000000
+--- a/arch/powerpc/configs/ep405_defconfig
++++ /dev/null
+@@ -1,968 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc2
+-# Fri Feb 15 21:50:09 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-CONFIG_40x=y
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_4xx=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-# CONFIG_DEFAULT_UIMAGE is not set
+-CONFIG_PPC_DCR_NATIVE=y
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_PPC_DCR=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-CONFIG_KALLSYMS_ALL=y
+-CONFIG_KALLSYMS_EXTRA_PASS=y
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-# CONFIG_PPC4xx_PCI_EXPRESS is not set
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_EP405=y
+-# CONFIG_KILAUEA is not set
+-# CONFIG_MAKALU is not set
+-# CONFIG_WALNUT is not set
+-# CONFIG_XILINX_VIRTEX_GENERIC_BOARD is not set
+-CONFIG_405GP=y
+-CONFIG_IBM405_ERR77=y
+-CONFIG_IBM405_ERR51=y
+-# CONFIG_IPIC is not set
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_RCU_TRACE=y
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_MATH_EMULATION is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x00400000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+-# CONFIG_INET_XFRM_MODE_BEET is not set
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-CONFIG_CONNECTOR=y
+-CONFIG_PROC_EVENTS=y
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-CONFIG_MTD_CMDLINE_PARTS=y
+-CONFIG_MTD_OF_PARTS=y
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=m
+-CONFIG_MTD_BLOCK=m
+-# CONFIG_MTD_BLOCK_RO is not set
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-CONFIG_MTD_JEDECPROBE=y
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-CONFIG_MTD_PHYSMAP_OF=y
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-# CONFIG_BLK_DEV_UB is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=35000
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-# CONFIG_XILINX_SYSACE is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-# CONFIG_PHYLIB is not set
+-CONFIG_NET_ETHERNET=y
+-# CONFIG_MII is not set
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-CONFIG_IBM_NEW_EMAC=y
+-CONFIG_IBM_NEW_EMAC_RXB=128
+-CONFIG_IBM_NEW_EMAC_TXB=64
+-CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+-CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+-CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+-# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+-CONFIG_IBM_NEW_EMAC_ZMII=y
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-CONFIG_SERIAL_8250_EXTENDED=y
+-# CONFIG_SERIAL_8250_MANY_PORTS is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+-# CONFIG_SERIAL_8250_RSA is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_SERIAL_OF_PLATFORM=y
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-CONFIG_THERMAL=y
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-# CONFIG_DAB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-CONFIG_USB=y
+-# CONFIG_USB_DEBUG is not set
+-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+-
+-#
+-# Miscellaneous USB options
+-#
+-CONFIG_USB_DEVICEFS=y
+-CONFIG_USB_DEVICE_CLASS=y
+-# CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_OTG is not set
+-
+-#
+-# USB Host Controller Drivers
+-#
+-# CONFIG_USB_EHCI_HCD is not set
+-# CONFIG_USB_ISP116X_HCD is not set
+-CONFIG_USB_OHCI_HCD=y
+-CONFIG_USB_OHCI_HCD_PPC_OF=y
+-CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+-CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
+-CONFIG_USB_OHCI_HCD_PCI=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
+-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+-# CONFIG_USB_UHCI_HCD is not set
+-# CONFIG_USB_SL811_HCD is not set
+-# CONFIG_USB_R8A66597_HCD is not set
+-
+-#
+-# USB Device Class drivers
+-#
+-# CONFIG_USB_ACM is not set
+-# CONFIG_USB_PRINTER is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# may also be needed; see USB_STORAGE Help for more information
+-#
+-# CONFIG_USB_LIBUSUAL is not set
+-
+-#
+-# USB Imaging devices
+-#
+-# CONFIG_USB_MDC800 is not set
+-CONFIG_USB_MON=y
+-
+-#
+-# USB port drivers
+-#
+-# CONFIG_USB_SERIAL is not set
+-
+-#
+-# USB Miscellaneous drivers
+-#
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+-# CONFIG_USB_ADUTUX is not set
+-# CONFIG_USB_AUERSWALD is not set
+-# CONFIG_USB_RIO500 is not set
+-# CONFIG_USB_LEGOTOWER is not set
+-# CONFIG_USB_LCD is not set
+-# CONFIG_USB_BERRY_CHARGE is not set
+-# CONFIG_USB_LED is not set
+-# CONFIG_USB_CYPRESS_CY7C63 is not set
+-# CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGET is not set
+-# CONFIG_USB_IDMOUSE is not set
+-# CONFIG_USB_FTDI_ELAN is not set
+-# CONFIG_USB_APPLEDISPLAY is not set
+-# CONFIG_USB_LD is not set
+-# CONFIG_USB_TRANCEVIBRATOR is not set
+-# CONFIG_USB_IOWARRIOR is not set
+-# CONFIG_USB_TEST is not set
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_JFFS2_FS is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_MAGIC_SYSRQ=y
+-# CONFIG_UNUSED_SYMBOLS is not set
+-CONFIG_DEBUG_FS=y
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-CONFIG_DEBUG_BUGVERBOSE=y
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_VIRQ_DEBUG is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=y
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=y
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig
+index 0f82f66..a20501f 100644
+--- a/arch/powerpc/configs/g5_defconfig
++++ b/arch/powerpc/configs/g5_defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+ # Linux kernel version: 2.6.25-rc6
+-# Thu Mar 20 10:36:41 2008
++# Thu Mar 27 13:55:43 2008
+ #
+ CONFIG_PPC64=y
+
+@@ -77,8 +77,6 @@ CONFIG_IKCONFIG_PROC=y
+ CONFIG_LOG_BUF_SHIFT=17
+ # CONFIG_CGROUPS is not set
+ # CONFIG_GROUP_SCHED is not set
+-# CONFIG_USER_SCHED is not set
+-# CONFIG_CGROUP_SCHED is not set
+ CONFIG_SYSFS_DEPRECATED=y
+ CONFIG_SYSFS_DEPRECATED_V2=y
+ # CONFIG_RELAY is not set
+@@ -276,7 +274,7 @@ CONFIG_PCI_SYSCALL=y
+ # CONFIG_PCIEPORTBUS is not set
+ CONFIG_ARCH_SUPPORTS_MSI=y
+ CONFIG_PCI_MSI=y
+-CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_LEGACY is not set
+ # CONFIG_PCI_DEBUG is not set
+ # CONFIG_PCCARD is not set
+ # CONFIG_HOTPLUG_PCI is not set
+@@ -1596,6 +1594,7 @@ CONFIG_PLIST=y
+ CONFIG_HAS_IOMEM=y
+ CONFIG_HAS_IOPORT=y
+ CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
+
+ #
+ # Kernel hacking
+diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig
+index 8d9a84f..b3128fb 100644
+--- a/arch/powerpc/configs/iseries_defconfig
++++ b/arch/powerpc/configs/iseries_defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+ # Linux kernel version: 2.6.25-rc6
+-# Thu Mar 20 10:43:46 2008
++# Thu Mar 27 13:55:45 2008
+ #
+ CONFIG_PPC64=y
+
+@@ -77,8 +77,6 @@ CONFIG_IKCONFIG_PROC=y
+ CONFIG_LOG_BUF_SHIFT=17
+ # CONFIG_CGROUPS is not set
+ # CONFIG_GROUP_SCHED is not set
+-# CONFIG_USER_SCHED is not set
+-# CONFIG_CGROUP_SCHED is not set
+ CONFIG_SYSFS_DEPRECATED=y
+ CONFIG_SYSFS_DEPRECATED_V2=y
+ # CONFIG_RELAY is not set
+@@ -261,7 +259,7 @@ CONFIG_PCI_SYSCALL=y
+ # CONFIG_PCIEPORTBUS is not set
+ CONFIG_ARCH_SUPPORTS_MSI=y
+ # CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_LEGACY is not set
+ # CONFIG_PCI_DEBUG is not set
+ # CONFIG_PCCARD is not set
+ # CONFIG_HOTPLUG_PCI is not set
+@@ -1065,6 +1063,7 @@ CONFIG_PLIST=y
+ CONFIG_HAS_IOMEM=y
+ CONFIG_HAS_IOPORT=y
+ CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
+
+ #
+ # Kernel hacking
+diff --git a/arch/powerpc/configs/katmai_defconfig b/arch/powerpc/configs/katmai_defconfig
+deleted file mode 100644
+index c8804ec..0000000
+--- a/arch/powerpc/configs/katmai_defconfig
++++ /dev/null
+@@ -1,790 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.24-rc6
+-# Mon Dec 24 11:17:43 2007
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-CONFIG_44x=y
+-# CONFIG_E200 is not set
+-CONFIG_4xx=y
+-CONFIG_BOOKE=y
+-CONFIG_PTE_64BIT=y
+-CONFIG_PHYS_64BIT=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-# CONFIG_DEFAULT_UIMAGE is not set
+-CONFIG_PPC_DCR_NATIVE=y
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_PPC_DCR=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_USER_NS is not set
+-# CONFIG_PID_NS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_FAIR_GROUP_SCHED=y
+-CONFIG_FAIR_USER_SCHED=y
+-# CONFIG_FAIR_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_ALL is not set
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_PPC4xx_PCI_EXPRESS=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC52xx is not set
+-# CONFIG_PPC_MPC5200 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-# CONFIG_BAMBOO is not set
+-# CONFIG_EBONY is not set
+-# CONFIG_SEQUOIA is not set
+-# CONFIG_TAISHAN is not set
+-CONFIG_KATMAI=y
+-# CONFIG_RAINIER is not set
+-CONFIG_440SPe=y
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_CPM2 is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_MATH_EMULATION is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-CONFIG_RESOURCES_64BIT=y
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-CONFIG_CMDLINE_BOOL=y
+-CONFIG_CMDLINE=""
+-CONFIG_SECCOMP=y
+-CONFIG_WANT_DEVICE_TREE=y
+-CONFIG_DEVICE_TREE="katmai.dts"
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x01000000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+-# CONFIG_INET_XFRM_MODE_BEET is not set
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-CONFIG_CONNECTOR=y
+-CONFIG_PROC_EVENTS=y
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=35000
+-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-# CONFIG_XILINX_SYSACE is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-CONFIG_MACINTOSH_DRIVERS=y
+-# CONFIG_MAC_EMUMOUSEBTN is not set
+-# CONFIG_WINDFARM is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_ARCNET is not set
+-# CONFIG_PHYLIB is not set
+-CONFIG_NET_ETHERNET=y
+-# CONFIG_MII is not set
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-CONFIG_IBM_NEW_EMAC=y
+-CONFIG_IBM_NEW_EMAC_RXB=128
+-CONFIG_IBM_NEW_EMAC_TXB=64
+-CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+-CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+-CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+-# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-CONFIG_IBM_NEW_EMAC_EMAC4=y
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_SHAPER is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-# CONFIG_SERIAL_8250_PCI is not set
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-CONFIG_SERIAL_8250_EXTENDED=y
+-# CONFIG_SERIAL_8250_MANY_PORTS is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+-# CONFIG_SERIAL_8250_RSA is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_SERIAL_OF_PLATFORM=y
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# USB Gadget Support
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-CONFIG_DNOTIFY=y
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-# CONFIG_UCC_SLOW is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-CONFIG_INSTRUMENTATION=y
+-# CONFIG_PROFILING is not set
+-# CONFIG_KPROBES is not set
+-# CONFIG_MARKERS is not set
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_MAGIC_SYSRQ=y
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-CONFIG_FORCED_INLINING=y
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-CONFIG_DEBUGGER=y
+-# CONFIG_KGDB is not set
+-# CONFIG_XMON is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=y
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=y
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/kilauea_defconfig b/arch/powerpc/configs/kilauea_defconfig
+deleted file mode 100644
+index 2f47539..0000000
+--- a/arch/powerpc/configs/kilauea_defconfig
++++ /dev/null
+@@ -1,839 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc2
+-# Fri Feb 15 21:51:43 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-CONFIG_40x=y
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_4xx=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-# CONFIG_DEFAULT_UIMAGE is not set
+-CONFIG_PPC_DCR_NATIVE=y
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_PPC_DCR=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-CONFIG_KALLSYMS_ALL=y
+-CONFIG_KALLSYMS_EXTRA_PASS=y
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-CONFIG_PPC4xx_PCI_EXPRESS=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-# CONFIG_EP405 is not set
+-CONFIG_KILAUEA=y
+-# CONFIG_MAKALU is not set
+-# CONFIG_WALNUT is not set
+-# CONFIG_XILINX_VIRTEX_GENERIC_BOARD is not set
+-CONFIG_405EX=y
+-# CONFIG_IPIC is not set
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_RCU_TRACE=y
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_MATH_EMULATION is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x00400000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+-# CONFIG_INET_XFRM_MODE_BEET is not set
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-CONFIG_CONNECTOR=y
+-CONFIG_PROC_EVENTS=y
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-CONFIG_MTD_CMDLINE_PARTS=y
+-CONFIG_MTD_OF_PARTS=y
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=m
+-CONFIG_MTD_BLOCK=m
+-# CONFIG_MTD_BLOCK_RO is not set
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-CONFIG_MTD_JEDECPROBE=y
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-CONFIG_MTD_PHYSMAP_OF=y
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=35000
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-# CONFIG_XILINX_SYSACE is not set
+-# CONFIG_MISC_DEVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-# CONFIG_PHYLIB is not set
+-CONFIG_NET_ETHERNET=y
+-# CONFIG_MII is not set
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-CONFIG_IBM_NEW_EMAC=y
+-CONFIG_IBM_NEW_EMAC_RXB=256
+-CONFIG_IBM_NEW_EMAC_TXB=256
+-CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+-CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+-CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+-# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-CONFIG_IBM_NEW_EMAC_RGMII=y
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-CONFIG_IBM_NEW_EMAC_EMAC4=y
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-# CONFIG_NETDEV_1000 is not set
+-# CONFIG_NETDEV_10000 is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-CONFIG_SERIAL_8250_EXTENDED=y
+-# CONFIG_SERIAL_8250_MANY_PORTS is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+-# CONFIG_SERIAL_8250_RSA is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_SERIAL_OF_PLATFORM=y
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-CONFIG_THERMAL=y
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-# CONFIG_DAB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-# CONFIG_USB_SUPPORT is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_JFFS2_FS is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_MAGIC_SYSRQ=y
+-# CONFIG_UNUSED_SYMBOLS is not set
+-CONFIG_DEBUG_FS=y
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-CONFIG_DEBUG_BUGVERBOSE=y
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_VIRQ_DEBUG is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=y
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=y
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/makalu_defconfig b/arch/powerpc/configs/makalu_defconfig
+deleted file mode 100644
+index 9ef4d8a..0000000
+--- a/arch/powerpc/configs/makalu_defconfig
++++ /dev/null
+@@ -1,839 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc2
+-# Fri Feb 15 21:52:30 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-CONFIG_40x=y
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_4xx=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-# CONFIG_DEFAULT_UIMAGE is not set
+-CONFIG_PPC_DCR_NATIVE=y
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_PPC_DCR=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-CONFIG_KALLSYMS_ALL=y
+-CONFIG_KALLSYMS_EXTRA_PASS=y
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-CONFIG_PPC4xx_PCI_EXPRESS=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-# CONFIG_EP405 is not set
+-# CONFIG_KILAUEA is not set
+-CONFIG_MAKALU=y
+-# CONFIG_WALNUT is not set
+-# CONFIG_XILINX_VIRTEX_GENERIC_BOARD is not set
+-CONFIG_405EX=y
+-# CONFIG_IPIC is not set
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_RCU_TRACE=y
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_MATH_EMULATION is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x00400000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+-# CONFIG_INET_XFRM_MODE_BEET is not set
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-CONFIG_CONNECTOR=y
+-CONFIG_PROC_EVENTS=y
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-CONFIG_MTD_CMDLINE_PARTS=y
+-CONFIG_MTD_OF_PARTS=y
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=m
+-CONFIG_MTD_BLOCK=m
+-# CONFIG_MTD_BLOCK_RO is not set
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-CONFIG_MTD_JEDECPROBE=y
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-CONFIG_MTD_PHYSMAP_OF=y
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=35000
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-# CONFIG_XILINX_SYSACE is not set
+-# CONFIG_MISC_DEVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-# CONFIG_PHYLIB is not set
+-CONFIG_NET_ETHERNET=y
+-# CONFIG_MII is not set
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-CONFIG_IBM_NEW_EMAC=y
+-CONFIG_IBM_NEW_EMAC_RXB=256
+-CONFIG_IBM_NEW_EMAC_TXB=256
+-CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+-CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+-CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+-# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-CONFIG_IBM_NEW_EMAC_RGMII=y
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-CONFIG_IBM_NEW_EMAC_EMAC4=y
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-# CONFIG_NETDEV_1000 is not set
+-# CONFIG_NETDEV_10000 is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-CONFIG_SERIAL_8250_EXTENDED=y
+-# CONFIG_SERIAL_8250_MANY_PORTS is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+-# CONFIG_SERIAL_8250_RSA is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_SERIAL_OF_PLATFORM=y
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-CONFIG_THERMAL=y
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-# CONFIG_DAB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-# CONFIG_USB_SUPPORT is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_JFFS2_FS is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_MAGIC_SYSRQ=y
+-# CONFIG_UNUSED_SYMBOLS is not set
+-CONFIG_DEBUG_FS=y
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-CONFIG_DEBUG_BUGVERBOSE=y
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_VIRQ_DEBUG is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=y
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=y
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig
+index 8b810d0..7a166a3 100644
+--- a/arch/powerpc/configs/maple_defconfig
++++ b/arch/powerpc/configs/maple_defconfig
+@@ -333,7 +333,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
+ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+ CONFIG_STANDALONE=y
+ CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
++CONFIG_FW_LOADER=y
+ # CONFIG_DEBUG_DRIVER is not set
+ # CONFIG_DEBUG_DEVRES is not set
+ # CONFIG_SYS_HYPERVISOR is not set
+@@ -374,6 +374,7 @@ CONFIG_BLK_DEV_IDEDISK=y
+ CONFIG_BLK_DEV_IDECD=y
+ # CONFIG_BLK_DEV_IDETAPE is not set
+ # CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_BLK_DEV_IDESCSI is not set
+ CONFIG_IDE_TASK_IOCTL=y
+ CONFIG_IDE_PROC_FS=y
+
+@@ -427,10 +428,129 @@ CONFIG_IDE_ARCH_OBSOLETE_INIT=y
+ # SCSI device support
+ #
+ # CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
+ # CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
++# CONFIG_SCSI_PROC_FS is not set
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
++# CONFIG_SCSI_3W_9XXX is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC94XX is not set
++# CONFIG_SCSI_ARCMSR is not set
++# CONFIG_MEGARAID_NEWGEN is not set
++# CONFIG_MEGARAID_LEGACY is not set
++# CONFIG_MEGARAID_SAS is not set
++# CONFIG_SCSI_HPTIOP is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_IPS is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_STEX is not set
++# CONFIG_SCSI_SYM53C8XX_2 is not set
++CONFIG_SCSI_IPR=y
++CONFIG_SCSI_IPR_TRACE=y
++CONFIG_SCSI_IPR_DUMP=y
++# CONFIG_SCSI_QLOGIC_1280 is not set
++# CONFIG_SCSI_QLA_FC is not set
++# CONFIG_SCSI_QLA_ISCSI is not set
++# CONFIG_SCSI_LPFC is not set
++# CONFIG_SCSI_DC395x is not set
++# CONFIG_SCSI_DC390T is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_SRP is not set
++CONFIG_ATA=y
++CONFIG_ATA_NONSTANDARD=y
++# CONFIG_SATA_AHCI is not set
++# CONFIG_SATA_SVW is not set
++# CONFIG_ATA_PIIX is not set
++# CONFIG_SATA_MV is not set
++# CONFIG_SATA_NV is not set
++# CONFIG_PDC_ADMA is not set
++# CONFIG_SATA_QSTOR is not set
++# CONFIG_SATA_PROMISE is not set
++# CONFIG_SATA_SX4 is not set
++# CONFIG_SATA_SIL is not set
++# CONFIG_SATA_SIL24 is not set
++# CONFIG_SATA_SIS is not set
++# CONFIG_SATA_ULI is not set
++# CONFIG_SATA_VIA is not set
++# CONFIG_SATA_VITESSE is not set
++# CONFIG_SATA_INIC162X is not set
++# CONFIG_PATA_ALI is not set
++# CONFIG_PATA_AMD is not set
++# CONFIG_PATA_ARTOP is not set
++# CONFIG_PATA_ATIIXP is not set
++# CONFIG_PATA_CMD640_PCI is not set
++# CONFIG_PATA_CMD64X is not set
++# CONFIG_PATA_CS5520 is not set
++# CONFIG_PATA_CS5530 is not set
++# CONFIG_PATA_CYPRESS is not set
++# CONFIG_PATA_EFAR is not set
++# CONFIG_ATA_GENERIC is not set
++# CONFIG_PATA_HPT366 is not set
++# CONFIG_PATA_HPT37X is not set
++# CONFIG_PATA_HPT3X2N is not set
++# CONFIG_PATA_HPT3X3 is not set
++# CONFIG_PATA_IT821X is not set
++# CONFIG_PATA_IT8213 is not set
++# CONFIG_PATA_JMICRON is not set
++# CONFIG_PATA_TRIFLEX is not set
++# CONFIG_PATA_MARVELL is not set
++# CONFIG_PATA_MPIIX is not set
++# CONFIG_PATA_OLDPIIX is not set
++# CONFIG_PATA_NETCELL is not set
++# CONFIG_PATA_NS87410 is not set
++# CONFIG_PATA_NS87415 is not set
++# CONFIG_PATA_OPTI is not set
++# CONFIG_PATA_OPTIDMA is not set
++# CONFIG_PATA_PDC_OLD is not set
++# CONFIG_PATA_RADISYS is not set
++# CONFIG_PATA_RZ1000 is not set
++# CONFIG_PATA_SC1200 is not set
++# CONFIG_PATA_SERVERWORKS is not set
++# CONFIG_PATA_PDC2027X is not set
++# CONFIG_PATA_SIL680 is not set
++# CONFIG_PATA_SIS is not set
++# CONFIG_PATA_VIA is not set
++# CONFIG_PATA_WINBOND is not set
+ # CONFIG_MD is not set
+ # CONFIG_FUSION is not set
+
+@@ -536,6 +656,7 @@ CONFIG_USB_PEGASUS=y
+ # CONFIG_HIPPI is not set
+ # CONFIG_PPP is not set
+ # CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
+ # CONFIG_SHAPER is not set
+ # CONFIG_NETCONSOLE is not set
+ # CONFIG_NETPOLL is not set
+@@ -783,12 +904,14 @@ CONFIG_USB_UHCI_HCD=y
+ #
+ # may also be needed; see USB_STORAGE Help for more information
+ #
++# CONFIG_USB_STORAGE is not set
+ # CONFIG_USB_LIBUSUAL is not set
+
+ #
+ # USB Imaging devices
+ #
+ # CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
+ CONFIG_USB_MON=y
+
+ #
+diff --git a/arch/powerpc/configs/mpc8313_rdb_defconfig b/arch/powerpc/configs/mpc8313_rdb_defconfig
+deleted file mode 100644
+index 7a862a6..0000000
+--- a/arch/powerpc/configs/mpc8313_rdb_defconfig
++++ /dev/null
+@@ -1,1393 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:14 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-CONFIG_6xx=y
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-# CONFIG_FSL_EMB_PERFMON is not set
+-CONFIG_PPC_STD_MMU=y
+-CONFIG_PPC_STD_MMU_32=y
+-# CONFIG_PPC_MM_SLICES is not set
+-# CONFIG_SMP is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MULTIPLATFORM is not set
+-# CONFIG_PPC_82xx is not set
+-CONFIG_PPC_83xx=y
+-# CONFIG_PPC_86xx is not set
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC83xx=y
+-CONFIG_MPC831x_RDB=y
+-# CONFIG_MPC832x_MDS is not set
+-# CONFIG_MPC832x_RDB is not set
+-# CONFIG_MPC834x_MDS is not set
+-# CONFIG_MPC834x_ITX is not set
+-# CONFIG_MPC836x_MDS is not set
+-# CONFIG_MPC837x_MDS is not set
+-# CONFIG_MPC837x_RDB is not set
+-# CONFIG_SBC834x is not set
+-CONFIG_PPC_MPC831x=y
+-CONFIG_IPIC=y
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-# CONFIG_MTD_CMDLINE_PARTS is not set
+-# CONFIG_MTD_OF_PARTS is not set
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=y
+-CONFIG_MTD_BLOCK=y
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-# CONFIG_MTD_JEDECPROBE is not set
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-CONFIG_MTD_PHYSMAP_OF=y
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_DATAFLASH is not set
+-# CONFIG_MTD_M25P80 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-CONFIG_MTD_NAND=y
+-CONFIG_MTD_NAND_VERIFY_WRITE=y
+-# CONFIG_MTD_NAND_ECC_SMC is not set
+-# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+-CONFIG_MTD_NAND_IDS=y
+-# CONFIG_MTD_NAND_DISKONCHIP is not set
+-# CONFIG_MTD_NAND_CAFE is not set
+-# CONFIG_MTD_NAND_NANDSIM is not set
+-# CONFIG_MTD_NAND_PLATFORM is not set
+-# CONFIG_MTD_ALAUDA is not set
+-# CONFIG_MTD_NAND_FSL_ELBC is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-# CONFIG_BLK_DEV_UB is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-# CONFIG_BLK_DEV_SD is not set
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-# CONFIG_BLK_DEV_SR is not set
+-CONFIG_CHR_DEV_SG=y
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-CONFIG_SCSI_SPI_ATTRS=y
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-# CONFIG_SCSI_AIC7XXX is not set
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-# CONFIG_SCSI_AIC79XX is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_BUSLOGIC is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_EATA is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_GDTH is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_MVSAS is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-# CONFIG_ATA is not set
+-CONFIG_MD=y
+-CONFIG_BLK_DEV_MD=y
+-CONFIG_MD_LINEAR=y
+-CONFIG_MD_RAID0=y
+-CONFIG_MD_RAID1=y
+-# CONFIG_MD_RAID10 is not set
+-# CONFIG_MD_RAID456 is not set
+-# CONFIG_MD_MULTIPATH is not set
+-# CONFIG_MD_FAULTY is not set
+-# CONFIG_BLK_DEV_DM is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-CONFIG_CICADA_PHY=y
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_ENC28J60 is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-CONFIG_NET_PCI=y
+-# CONFIG_PCNET32 is not set
+-# CONFIG_AMD8111_ETH is not set
+-# CONFIG_ADAPTEC_STARFIRE is not set
+-# CONFIG_B44 is not set
+-# CONFIG_FORCEDETH is not set
+-# CONFIG_EEPRO100 is not set
+-CONFIG_E100=y
+-# CONFIG_FEALNX is not set
+-# CONFIG_NATSEMI is not set
+-# CONFIG_NE2K_PCI is not set
+-# CONFIG_8139CP is not set
+-# CONFIG_8139TOO is not set
+-# CONFIG_R6040 is not set
+-# CONFIG_SIS900 is not set
+-# CONFIG_EPIC100 is not set
+-# CONFIG_SUNDANCE is not set
+-# CONFIG_TLAN is not set
+-# CONFIG_VIA_RHINE is not set
+-# CONFIG_SC92031 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NET_FC is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_TINY_USB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-CONFIG_SPI=y
+-# CONFIG_SPI_DEBUG is not set
+-CONFIG_SPI_MASTER=y
+-
+-#
+-# SPI Master Controller Drivers
+-#
+-CONFIG_SPI_BITBANG=y
+-CONFIG_SPI_MPC83xx=y
+-
+-#
+-# SPI Protocol Masters
+-#
+-# CONFIG_SPI_AT25 is not set
+-# CONFIG_SPI_SPIDEV is not set
+-# CONFIG_SPI_TLE62X0 is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM70 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_83xx_WDT=y
+-
+-#
+-# PCI-based Watchdog Cards
+-#
+-# CONFIG_PCIPCWATCHDOG is not set
+-# CONFIG_WDTPCI is not set
+-
+-#
+-# USB-based Watchdog Cards
+-#
+-# CONFIG_USBPCWATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-# CONFIG_USB_DABUSB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-
+-#
+-# USB Input Devices
+-#
+-# CONFIG_USB_HID is not set
+-
+-#
+-# USB HID Boot Protocol drivers
+-#
+-# CONFIG_USB_KBD is not set
+-# CONFIG_USB_MOUSE is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-CONFIG_USB=y
+-# CONFIG_USB_DEBUG is not set
+-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+-
+-#
+-# Miscellaneous USB options
+-#
+-CONFIG_USB_DEVICEFS=y
+-CONFIG_USB_DEVICE_CLASS=y
+-# CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_OTG is not set
+-
+-#
+-# USB Host Controller Drivers
+-#
+-CONFIG_USB_EHCI_HCD=y
+-CONFIG_USB_EHCI_ROOT_HUB_TT=y
+-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+-CONFIG_USB_EHCI_FSL=y
+-CONFIG_USB_EHCI_HCD_PPC_OF=y
+-# CONFIG_USB_ISP116X_HCD is not set
+-CONFIG_USB_OHCI_HCD=y
+-CONFIG_USB_OHCI_HCD_PPC_OF=y
+-CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+-# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+-CONFIG_USB_OHCI_HCD_PCI=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
+-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+-CONFIG_USB_UHCI_HCD=y
+-# CONFIG_USB_SL811_HCD is not set
+-# CONFIG_USB_R8A66597_HCD is not set
+-
+-#
+-# USB Device Class drivers
+-#
+-# CONFIG_USB_ACM is not set
+-# CONFIG_USB_PRINTER is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# may also be needed; see USB_STORAGE Help for more information
+-#
+-CONFIG_USB_STORAGE=y
+-# CONFIG_USB_STORAGE_DEBUG is not set
+-# CONFIG_USB_STORAGE_DATAFAB is not set
+-# CONFIG_USB_STORAGE_FREECOM is not set
+-# CONFIG_USB_STORAGE_ISD200 is not set
+-# CONFIG_USB_STORAGE_DPCM is not set
+-# CONFIG_USB_STORAGE_USBAT is not set
+-# CONFIG_USB_STORAGE_SDDR09 is not set
+-# CONFIG_USB_STORAGE_SDDR55 is not set
+-# CONFIG_USB_STORAGE_JUMPSHOT is not set
+-# CONFIG_USB_STORAGE_ALAUDA is not set
+-# CONFIG_USB_STORAGE_KARMA is not set
+-# CONFIG_USB_LIBUSUAL is not set
+-
+-#
+-# USB Imaging devices
+-#
+-# CONFIG_USB_MDC800 is not set
+-# CONFIG_USB_MICROTEK is not set
+-CONFIG_USB_MON=y
+-
+-#
+-# USB port drivers
+-#
+-# CONFIG_USB_SERIAL is not set
+-
+-#
+-# USB Miscellaneous drivers
+-#
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+-# CONFIG_USB_ADUTUX is not set
+-# CONFIG_USB_AUERSWALD is not set
+-# CONFIG_USB_RIO500 is not set
+-# CONFIG_USB_LEGOTOWER is not set
+-# CONFIG_USB_LCD is not set
+-# CONFIG_USB_BERRY_CHARGE is not set
+-# CONFIG_USB_LED is not set
+-# CONFIG_USB_CYPRESS_CY7C63 is not set
+-# CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGET is not set
+-# CONFIG_USB_IDMOUSE is not set
+-# CONFIG_USB_FTDI_ELAN is not set
+-# CONFIG_USB_APPLEDISPLAY is not set
+-# CONFIG_USB_SISUSBVGA is not set
+-# CONFIG_USB_LD is not set
+-# CONFIG_USB_TRANCEVIBRATOR is not set
+-# CONFIG_USB_IOWARRIOR is not set
+-# CONFIG_USB_TEST is not set
+-CONFIG_USB_GADGET=y
+-# CONFIG_USB_GADGET_DEBUG is not set
+-# CONFIG_USB_GADGET_DEBUG_FILES is not set
+-CONFIG_USB_GADGET_SELECTED=y
+-# CONFIG_USB_GADGET_AMD5536UDC is not set
+-# CONFIG_USB_GADGET_ATMEL_USBA is not set
+-# CONFIG_USB_GADGET_FSL_USB2 is not set
+-CONFIG_USB_GADGET_NET2280=y
+-CONFIG_USB_NET2280=y
+-# CONFIG_USB_GADGET_PXA2XX is not set
+-# CONFIG_USB_GADGET_M66592 is not set
+-# CONFIG_USB_GADGET_GOKU is not set
+-# CONFIG_USB_GADGET_LH7A40X is not set
+-# CONFIG_USB_GADGET_OMAP is not set
+-# CONFIG_USB_GADGET_S3C2410 is not set
+-# CONFIG_USB_GADGET_AT91 is not set
+-# CONFIG_USB_GADGET_DUMMY_HCD is not set
+-CONFIG_USB_GADGET_DUALSPEED=y
+-# CONFIG_USB_ZERO is not set
+-CONFIG_USB_ETH=y
+-CONFIG_USB_ETH_RNDIS=y
+-# CONFIG_USB_GADGETFS is not set
+-# CONFIG_USB_FILE_STORAGE is not set
+-# CONFIG_USB_G_SERIAL is not set
+-# CONFIG_USB_MIDI_GADGET is not set
+-# CONFIG_USB_G_PRINTER is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-CONFIG_RTC_LIB=y
+-CONFIG_RTC_CLASS=y
+-CONFIG_RTC_HCTOSYS=y
+-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+-# CONFIG_RTC_DEBUG is not set
+-
+-#
+-# RTC interfaces
+-#
+-CONFIG_RTC_INTF_SYSFS=y
+-CONFIG_RTC_INTF_PROC=y
+-CONFIG_RTC_INTF_DEV=y
+-CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+-# CONFIG_RTC_DRV_TEST is not set
+-
+-#
+-# I2C RTC drivers
+-#
+-CONFIG_RTC_DRV_DS1307=y
+-# CONFIG_RTC_DRV_DS1374 is not set
+-# CONFIG_RTC_DRV_DS1672 is not set
+-# CONFIG_RTC_DRV_MAX6900 is not set
+-# CONFIG_RTC_DRV_RS5C372 is not set
+-# CONFIG_RTC_DRV_ISL1208 is not set
+-# CONFIG_RTC_DRV_X1205 is not set
+-# CONFIG_RTC_DRV_PCF8563 is not set
+-# CONFIG_RTC_DRV_PCF8583 is not set
+-# CONFIG_RTC_DRV_M41T80 is not set
+-# CONFIG_RTC_DRV_S35390A is not set
+-
+-#
+-# SPI RTC drivers
+-#
+-# CONFIG_RTC_DRV_MAX6902 is not set
+-# CONFIG_RTC_DRV_R9701 is not set
+-# CONFIG_RTC_DRV_RS5C348 is not set
+-
+-#
+-# Platform RTC drivers
+-#
+-# CONFIG_RTC_DRV_CMOS is not set
+-# CONFIG_RTC_DRV_DS1511 is not set
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
+-# CONFIG_RTC_DRV_STK17TA8 is not set
+-# CONFIG_RTC_DRV_M48T86 is not set
+-# CONFIG_RTC_DRV_M48T59 is not set
+-# CONFIG_RTC_DRV_V3020 is not set
+-
+-#
+-# on-CPU RTC drivers
+-#
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_JFFS2_FS=y
+-CONFIG_JFFS2_FS_DEBUG=0
+-CONFIG_JFFS2_FS_WRITEBUFFER=y
+-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+-# CONFIG_JFFS2_SUMMARY is not set
+-# CONFIG_JFFS2_FS_XATTR is not set
+-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+-CONFIG_JFFS2_ZLIB=y
+-# CONFIG_JFFS2_LZO is not set
+-CONFIG_JFFS2_RTIME=y
+-# CONFIG_JFFS2_RUBIN is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_BSD_DISKLABEL is not set
+-# CONFIG_MINIX_SUBPARTITION is not set
+-# CONFIG_SOLARIS_X86_PARTITION is not set
+-# CONFIG_UNIXWARE_DISKLABEL is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_ZLIB_DEFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/mpc8315_rdb_defconfig b/arch/powerpc/configs/mpc8315_rdb_defconfig
+deleted file mode 100644
+index 1f57456..0000000
+--- a/arch/powerpc/configs/mpc8315_rdb_defconfig
++++ /dev/null
+@@ -1,1451 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:15 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-CONFIG_6xx=y
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-# CONFIG_FSL_EMB_PERFMON is not set
+-CONFIG_PPC_STD_MMU=y
+-CONFIG_PPC_STD_MMU_32=y
+-# CONFIG_PPC_MM_SLICES is not set
+-# CONFIG_SMP is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MULTIPLATFORM is not set
+-# CONFIG_PPC_82xx is not set
+-CONFIG_PPC_83xx=y
+-# CONFIG_PPC_86xx is not set
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC83xx=y
+-CONFIG_MPC831x_RDB=y
+-# CONFIG_MPC832x_MDS is not set
+-# CONFIG_MPC832x_RDB is not set
+-# CONFIG_MPC834x_MDS is not set
+-# CONFIG_MPC834x_ITX is not set
+-# CONFIG_MPC836x_MDS is not set
+-# CONFIG_MPC837x_MDS is not set
+-# CONFIG_MPC837x_RDB is not set
+-# CONFIG_SBC834x is not set
+-CONFIG_PPC_MPC831x=y
+-CONFIG_IPIC=y
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-# CONFIG_MTD_CMDLINE_PARTS is not set
+-# CONFIG_MTD_OF_PARTS is not set
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=y
+-CONFIG_MTD_BLOCK=y
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-# CONFIG_MTD_JEDECPROBE is not set
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-CONFIG_MTD_PHYSMAP_OF=y
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_DATAFLASH is not set
+-# CONFIG_MTD_M25P80 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-CONFIG_MTD_NAND=y
+-CONFIG_MTD_NAND_VERIFY_WRITE=y
+-# CONFIG_MTD_NAND_ECC_SMC is not set
+-# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+-CONFIG_MTD_NAND_IDS=y
+-# CONFIG_MTD_NAND_DISKONCHIP is not set
+-# CONFIG_MTD_NAND_CAFE is not set
+-# CONFIG_MTD_NAND_NANDSIM is not set
+-# CONFIG_MTD_NAND_PLATFORM is not set
+-# CONFIG_MTD_ALAUDA is not set
+-# CONFIG_MTD_NAND_FSL_ELBC is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-# CONFIG_BLK_DEV_UB is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-# CONFIG_BLK_DEV_SD is not set
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-# CONFIG_BLK_DEV_SR is not set
+-CONFIG_CHR_DEV_SG=y
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-CONFIG_SCSI_SPI_ATTRS=y
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-# CONFIG_SCSI_AIC7XXX is not set
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-# CONFIG_SCSI_AIC79XX is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_BUSLOGIC is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_EATA is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_GDTH is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_MVSAS is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_IPR is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-CONFIG_ATA=y
+-# CONFIG_ATA_NONSTANDARD is not set
+-# CONFIG_SATA_AHCI is not set
+-# CONFIG_SATA_SVW is not set
+-# CONFIG_ATA_PIIX is not set
+-# CONFIG_SATA_MV is not set
+-# CONFIG_SATA_NV is not set
+-# CONFIG_PDC_ADMA is not set
+-# CONFIG_SATA_QSTOR is not set
+-# CONFIG_SATA_PROMISE is not set
+-# CONFIG_SATA_SX4 is not set
+-# CONFIG_SATA_SIL is not set
+-# CONFIG_SATA_SIL24 is not set
+-# CONFIG_SATA_SIS is not set
+-# CONFIG_SATA_ULI is not set
+-# CONFIG_SATA_VIA is not set
+-# CONFIG_SATA_VITESSE is not set
+-# CONFIG_SATA_INIC162X is not set
+-CONFIG_SATA_FSL=y
+-# CONFIG_PATA_ALI is not set
+-# CONFIG_PATA_AMD is not set
+-# CONFIG_PATA_ARTOP is not set
+-# CONFIG_PATA_ATIIXP is not set
+-# CONFIG_PATA_CMD640_PCI is not set
+-# CONFIG_PATA_CMD64X is not set
+-# CONFIG_PATA_CS5520 is not set
+-# CONFIG_PATA_CS5530 is not set
+-# CONFIG_PATA_CYPRESS is not set
+-# CONFIG_PATA_EFAR is not set
+-# CONFIG_ATA_GENERIC is not set
+-# CONFIG_PATA_HPT366 is not set
+-# CONFIG_PATA_HPT37X is not set
+-# CONFIG_PATA_HPT3X2N is not set
+-# CONFIG_PATA_HPT3X3 is not set
+-# CONFIG_PATA_IT821X is not set
+-# CONFIG_PATA_IT8213 is not set
+-# CONFIG_PATA_JMICRON is not set
+-# CONFIG_PATA_TRIFLEX is not set
+-# CONFIG_PATA_MARVELL is not set
+-# CONFIG_PATA_MPIIX is not set
+-# CONFIG_PATA_OLDPIIX is not set
+-# CONFIG_PATA_NETCELL is not set
+-# CONFIG_PATA_NINJA32 is not set
+-# CONFIG_PATA_NS87410 is not set
+-# CONFIG_PATA_NS87415 is not set
+-# CONFIG_PATA_OPTI is not set
+-# CONFIG_PATA_OPTIDMA is not set
+-# CONFIG_PATA_PDC_OLD is not set
+-# CONFIG_PATA_RADISYS is not set
+-# CONFIG_PATA_RZ1000 is not set
+-# CONFIG_PATA_SC1200 is not set
+-# CONFIG_PATA_SERVERWORKS is not set
+-# CONFIG_PATA_PDC2027X is not set
+-# CONFIG_PATA_SIL680 is not set
+-# CONFIG_PATA_SIS is not set
+-# CONFIG_PATA_VIA is not set
+-# CONFIG_PATA_WINBOND is not set
+-# CONFIG_PATA_PLATFORM is not set
+-CONFIG_MD=y
+-CONFIG_BLK_DEV_MD=y
+-CONFIG_MD_LINEAR=y
+-CONFIG_MD_RAID0=y
+-CONFIG_MD_RAID1=y
+-# CONFIG_MD_RAID10 is not set
+-# CONFIG_MD_RAID456 is not set
+-# CONFIG_MD_MULTIPATH is not set
+-# CONFIG_MD_FAULTY is not set
+-# CONFIG_BLK_DEV_DM is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_ENC28J60 is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-CONFIG_NET_PCI=y
+-# CONFIG_PCNET32 is not set
+-# CONFIG_AMD8111_ETH is not set
+-# CONFIG_ADAPTEC_STARFIRE is not set
+-# CONFIG_B44 is not set
+-# CONFIG_FORCEDETH is not set
+-# CONFIG_EEPRO100 is not set
+-CONFIG_E100=y
+-# CONFIG_FEALNX is not set
+-# CONFIG_NATSEMI is not set
+-# CONFIG_NE2K_PCI is not set
+-# CONFIG_8139CP is not set
+-# CONFIG_8139TOO is not set
+-# CONFIG_R6040 is not set
+-# CONFIG_SIS900 is not set
+-# CONFIG_EPIC100 is not set
+-# CONFIG_SUNDANCE is not set
+-# CONFIG_TLAN is not set
+-# CONFIG_VIA_RHINE is not set
+-# CONFIG_SC92031 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NET_FC is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_TINY_USB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-CONFIG_SPI=y
+-# CONFIG_SPI_DEBUG is not set
+-CONFIG_SPI_MASTER=y
+-
+-#
+-# SPI Master Controller Drivers
+-#
+-CONFIG_SPI_BITBANG=y
+-CONFIG_SPI_MPC83xx=y
+-
+-#
+-# SPI Protocol Masters
+-#
+-# CONFIG_SPI_AT25 is not set
+-# CONFIG_SPI_SPIDEV is not set
+-# CONFIG_SPI_TLE62X0 is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM70 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_83xx_WDT=y
+-
+-#
+-# PCI-based Watchdog Cards
+-#
+-# CONFIG_PCIPCWATCHDOG is not set
+-# CONFIG_WDTPCI is not set
+-
+-#
+-# USB-based Watchdog Cards
+-#
+-# CONFIG_USBPCWATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-# CONFIG_USB_DABUSB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-
+-#
+-# USB Input Devices
+-#
+-# CONFIG_USB_HID is not set
+-
+-#
+-# USB HID Boot Protocol drivers
+-#
+-# CONFIG_USB_KBD is not set
+-# CONFIG_USB_MOUSE is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-CONFIG_USB=y
+-# CONFIG_USB_DEBUG is not set
+-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+-
+-#
+-# Miscellaneous USB options
+-#
+-CONFIG_USB_DEVICEFS=y
+-CONFIG_USB_DEVICE_CLASS=y
+-# CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_OTG is not set
+-
+-#
+-# USB Host Controller Drivers
+-#
+-CONFIG_USB_EHCI_HCD=y
+-CONFIG_USB_EHCI_ROOT_HUB_TT=y
+-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+-CONFIG_USB_EHCI_FSL=y
+-CONFIG_USB_EHCI_HCD_PPC_OF=y
+-# CONFIG_USB_ISP116X_HCD is not set
+-CONFIG_USB_OHCI_HCD=y
+-CONFIG_USB_OHCI_HCD_PPC_OF=y
+-CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+-# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+-CONFIG_USB_OHCI_HCD_PCI=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
+-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+-CONFIG_USB_UHCI_HCD=y
+-# CONFIG_USB_SL811_HCD is not set
+-# CONFIG_USB_R8A66597_HCD is not set
+-
+-#
+-# USB Device Class drivers
+-#
+-# CONFIG_USB_ACM is not set
+-# CONFIG_USB_PRINTER is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# may also be needed; see USB_STORAGE Help for more information
+-#
+-CONFIG_USB_STORAGE=y
+-# CONFIG_USB_STORAGE_DEBUG is not set
+-# CONFIG_USB_STORAGE_DATAFAB is not set
+-# CONFIG_USB_STORAGE_FREECOM is not set
+-# CONFIG_USB_STORAGE_ISD200 is not set
+-# CONFIG_USB_STORAGE_DPCM is not set
+-# CONFIG_USB_STORAGE_USBAT is not set
+-# CONFIG_USB_STORAGE_SDDR09 is not set
+-# CONFIG_USB_STORAGE_SDDR55 is not set
+-# CONFIG_USB_STORAGE_JUMPSHOT is not set
+-# CONFIG_USB_STORAGE_ALAUDA is not set
+-# CONFIG_USB_STORAGE_KARMA is not set
+-# CONFIG_USB_LIBUSUAL is not set
+-
+-#
+-# USB Imaging devices
+-#
+-# CONFIG_USB_MDC800 is not set
+-# CONFIG_USB_MICROTEK is not set
+-CONFIG_USB_MON=y
+-
+-#
+-# USB port drivers
+-#
+-# CONFIG_USB_SERIAL is not set
+-
+-#
+-# USB Miscellaneous drivers
+-#
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+-# CONFIG_USB_ADUTUX is not set
+-# CONFIG_USB_AUERSWALD is not set
+-# CONFIG_USB_RIO500 is not set
+-# CONFIG_USB_LEGOTOWER is not set
+-# CONFIG_USB_LCD is not set
+-# CONFIG_USB_BERRY_CHARGE is not set
+-# CONFIG_USB_LED is not set
+-# CONFIG_USB_CYPRESS_CY7C63 is not set
+-# CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGET is not set
+-# CONFIG_USB_IDMOUSE is not set
+-# CONFIG_USB_FTDI_ELAN is not set
+-# CONFIG_USB_APPLEDISPLAY is not set
+-# CONFIG_USB_SISUSBVGA is not set
+-# CONFIG_USB_LD is not set
+-# CONFIG_USB_TRANCEVIBRATOR is not set
+-# CONFIG_USB_IOWARRIOR is not set
+-# CONFIG_USB_TEST is not set
+-CONFIG_USB_GADGET=y
+-# CONFIG_USB_GADGET_DEBUG is not set
+-# CONFIG_USB_GADGET_DEBUG_FILES is not set
+-CONFIG_USB_GADGET_SELECTED=y
+-# CONFIG_USB_GADGET_AMD5536UDC is not set
+-# CONFIG_USB_GADGET_ATMEL_USBA is not set
+-# CONFIG_USB_GADGET_FSL_USB2 is not set
+-CONFIG_USB_GADGET_NET2280=y
+-CONFIG_USB_NET2280=y
+-# CONFIG_USB_GADGET_PXA2XX is not set
+-# CONFIG_USB_GADGET_M66592 is not set
+-# CONFIG_USB_GADGET_GOKU is not set
+-# CONFIG_USB_GADGET_LH7A40X is not set
+-# CONFIG_USB_GADGET_OMAP is not set
+-# CONFIG_USB_GADGET_S3C2410 is not set
+-# CONFIG_USB_GADGET_AT91 is not set
+-# CONFIG_USB_GADGET_DUMMY_HCD is not set
+-CONFIG_USB_GADGET_DUALSPEED=y
+-# CONFIG_USB_ZERO is not set
+-CONFIG_USB_ETH=y
+-CONFIG_USB_ETH_RNDIS=y
+-# CONFIG_USB_GADGETFS is not set
+-# CONFIG_USB_FILE_STORAGE is not set
+-# CONFIG_USB_G_SERIAL is not set
+-# CONFIG_USB_MIDI_GADGET is not set
+-# CONFIG_USB_G_PRINTER is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-CONFIG_RTC_LIB=y
+-CONFIG_RTC_CLASS=y
+-CONFIG_RTC_HCTOSYS=y
+-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+-# CONFIG_RTC_DEBUG is not set
+-
+-#
+-# RTC interfaces
+-#
+-CONFIG_RTC_INTF_SYSFS=y
+-CONFIG_RTC_INTF_PROC=y
+-CONFIG_RTC_INTF_DEV=y
+-CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+-# CONFIG_RTC_DRV_TEST is not set
+-
+-#
+-# I2C RTC drivers
+-#
+-CONFIG_RTC_DRV_DS1307=y
+-# CONFIG_RTC_DRV_DS1374 is not set
+-# CONFIG_RTC_DRV_DS1672 is not set
+-# CONFIG_RTC_DRV_MAX6900 is not set
+-# CONFIG_RTC_DRV_RS5C372 is not set
+-# CONFIG_RTC_DRV_ISL1208 is not set
+-# CONFIG_RTC_DRV_X1205 is not set
+-# CONFIG_RTC_DRV_PCF8563 is not set
+-# CONFIG_RTC_DRV_PCF8583 is not set
+-# CONFIG_RTC_DRV_M41T80 is not set
+-# CONFIG_RTC_DRV_S35390A is not set
+-
+-#
+-# SPI RTC drivers
+-#
+-# CONFIG_RTC_DRV_MAX6902 is not set
+-# CONFIG_RTC_DRV_R9701 is not set
+-# CONFIG_RTC_DRV_RS5C348 is not set
+-
+-#
+-# Platform RTC drivers
+-#
+-# CONFIG_RTC_DRV_CMOS is not set
+-# CONFIG_RTC_DRV_DS1511 is not set
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
+-# CONFIG_RTC_DRV_STK17TA8 is not set
+-# CONFIG_RTC_DRV_M48T86 is not set
+-# CONFIG_RTC_DRV_M48T59 is not set
+-# CONFIG_RTC_DRV_V3020 is not set
+-
+-#
+-# on-CPU RTC drivers
+-#
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_JFFS2_FS=y
+-CONFIG_JFFS2_FS_DEBUG=0
+-CONFIG_JFFS2_FS_WRITEBUFFER=y
+-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+-# CONFIG_JFFS2_SUMMARY is not set
+-# CONFIG_JFFS2_FS_XATTR is not set
+-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+-CONFIG_JFFS2_ZLIB=y
+-# CONFIG_JFFS2_LZO is not set
+-CONFIG_JFFS2_RTIME=y
+-# CONFIG_JFFS2_RUBIN is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_BSD_DISKLABEL is not set
+-# CONFIG_MINIX_SUBPARTITION is not set
+-# CONFIG_SOLARIS_X86_PARTITION is not set
+-# CONFIG_UNIXWARE_DISKLABEL is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_ZLIB_DEFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/mpc832x_mds_defconfig b/arch/powerpc/configs/mpc832x_mds_defconfig
+deleted file mode 100644
+index 50cceda..0000000
+--- a/arch/powerpc/configs/mpc832x_mds_defconfig
++++ /dev/null
+@@ -1,1081 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc7
+-# Mon Mar 31 11:36:51 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-CONFIG_6xx=y
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-# CONFIG_FSL_EMB_PERFMON is not set
+-CONFIG_PPC_STD_MMU=y
+-CONFIG_PPC_STD_MMU_32=y
+-# CONFIG_PPC_MM_SLICES is not set
+-# CONFIG_SMP is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MULTIPLATFORM is not set
+-# CONFIG_PPC_82xx is not set
+-CONFIG_PPC_83xx=y
+-# CONFIG_PPC_86xx is not set
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC83xx=y
+-# CONFIG_MPC831x_RDB is not set
+-CONFIG_MPC832x_MDS=y
+-# CONFIG_MPC832x_RDB is not set
+-# CONFIG_MPC834x_MDS is not set
+-# CONFIG_MPC834x_ITX is not set
+-# CONFIG_MPC836x_MDS is not set
+-# CONFIG_MPC837x_MDS is not set
+-# CONFIG_MPC837x_RDB is not set
+-# CONFIG_SBC834x is not set
+-CONFIG_PPC_MPC832x=y
+-CONFIG_IPIC=y
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-CONFIG_QUICC_ENGINE=y
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-# CONFIG_BLK_DEV_SD is not set
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-# CONFIG_BLK_DEV_SR is not set
+-# CONFIG_CHR_DEV_SG is not set
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-# CONFIG_SCSI_SPI_ATTRS is not set
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-# CONFIG_SCSI_AIC7XXX is not set
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-# CONFIG_SCSI_AIC79XX is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_BUSLOGIC is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_EATA is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_GDTH is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_MVSAS is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-CONFIG_DAVICOM_PHY=y
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-# CONFIG_GIANFAR is not set
+-CONFIG_UCC_GETH=y
+-# CONFIG_UGETH_NAPI is not set
+-# CONFIG_UGETH_MAGIC_PACKET is not set
+-# CONFIG_UGETH_FILTERING is not set
+-# CONFIG_UGETH_TX_ON_DEMAND is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NET_FC is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-# CONFIG_SERIAL_QE is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_83xx_WDT=y
+-
+-#
+-# PCI-based Watchdog Cards
+-#
+-# CONFIG_PCIPCWATCHDOG is not set
+-# CONFIG_WDTPCI is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-CONFIG_RTC_LIB=y
+-CONFIG_RTC_CLASS=y
+-CONFIG_RTC_HCTOSYS=y
+-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+-# CONFIG_RTC_DEBUG is not set
+-
+-#
+-# RTC interfaces
+-#
+-CONFIG_RTC_INTF_SYSFS=y
+-CONFIG_RTC_INTF_PROC=y
+-CONFIG_RTC_INTF_DEV=y
+-# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+-# CONFIG_RTC_DRV_TEST is not set
+-
+-#
+-# I2C RTC drivers
+-#
+-# CONFIG_RTC_DRV_DS1307 is not set
+-CONFIG_RTC_DRV_DS1374=y
+-# CONFIG_RTC_DRV_DS1672 is not set
+-# CONFIG_RTC_DRV_MAX6900 is not set
+-# CONFIG_RTC_DRV_RS5C372 is not set
+-# CONFIG_RTC_DRV_ISL1208 is not set
+-# CONFIG_RTC_DRV_X1205 is not set
+-# CONFIG_RTC_DRV_PCF8563 is not set
+-# CONFIG_RTC_DRV_PCF8583 is not set
+-# CONFIG_RTC_DRV_M41T80 is not set
+-# CONFIG_RTC_DRV_S35390A is not set
+-
+-#
+-# SPI RTC drivers
+-#
+-
+-#
+-# Platform RTC drivers
+-#
+-# CONFIG_RTC_DRV_CMOS is not set
+-# CONFIG_RTC_DRV_DS1511 is not set
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
+-# CONFIG_RTC_DRV_STK17TA8 is not set
+-# CONFIG_RTC_DRV_M48T86 is not set
+-# CONFIG_RTC_DRV_M48T59 is not set
+-# CONFIG_RTC_DRV_V3020 is not set
+-
+-#
+-# on-CPU RTC drivers
+-#
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-CONFIG_UCC_FAST=y
+-CONFIG_UCC=y
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=m
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+-CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/mpc832x_rdb_defconfig b/arch/powerpc/configs/mpc832x_rdb_defconfig
+deleted file mode 100644
+index ac91302..0000000
+--- a/arch/powerpc/configs/mpc832x_rdb_defconfig
++++ /dev/null
+@@ -1,1233 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:16 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-CONFIG_6xx=y
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-# CONFIG_FSL_EMB_PERFMON is not set
+-CONFIG_PPC_STD_MMU=y
+-CONFIG_PPC_STD_MMU_32=y
+-# CONFIG_PPC_MM_SLICES is not set
+-# CONFIG_SMP is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MULTIPLATFORM is not set
+-# CONFIG_PPC_82xx is not set
+-CONFIG_PPC_83xx=y
+-# CONFIG_PPC_86xx is not set
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC83xx=y
+-# CONFIG_MPC831x_RDB is not set
+-# CONFIG_MPC832x_MDS is not set
+-CONFIG_MPC832x_RDB=y
+-# CONFIG_MPC834x_MDS is not set
+-# CONFIG_MPC834x_ITX is not set
+-# CONFIG_MPC836x_MDS is not set
+-# CONFIG_MPC837x_MDS is not set
+-# CONFIG_MPC837x_RDB is not set
+-# CONFIG_SBC834x is not set
+-CONFIG_PPC_MPC832x=y
+-CONFIG_IPIC=y
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-CONFIG_QUICC_ENGINE=y
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-# CONFIG_BLK_DEV_UB is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-CONFIG_BLK_DEV_SD=y
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-# CONFIG_BLK_DEV_SR is not set
+-# CONFIG_CHR_DEV_SG is not set
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-# CONFIG_SCSI_SPI_ATTRS is not set
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-# CONFIG_SCSI_AIC7XXX is not set
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-# CONFIG_SCSI_AIC79XX is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_BUSLOGIC is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_EATA is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_GDTH is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_MVSAS is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-CONFIG_ICPLUS_PHY=y
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_ENC28J60 is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-CONFIG_E1000=y
+-# CONFIG_E1000_NAPI is not set
+-# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-# CONFIG_GIANFAR is not set
+-CONFIG_UCC_GETH=y
+-CONFIG_UGETH_NAPI=y
+-# CONFIG_UGETH_MAGIC_PACKET is not set
+-# CONFIG_UGETH_FILTERING is not set
+-# CONFIG_UGETH_TX_ON_DEMAND is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NET_FC is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-# CONFIG_SERIAL_QE is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_TINY_USB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-CONFIG_SPI=y
+-CONFIG_SPI_MASTER=y
+-
+-#
+-# SPI Master Controller Drivers
+-#
+-CONFIG_SPI_BITBANG=y
+-CONFIG_SPI_MPC83xx=y
+-
+-#
+-# SPI Protocol Masters
+-#
+-# CONFIG_SPI_AT25 is not set
+-# CONFIG_SPI_SPIDEV is not set
+-# CONFIG_SPI_TLE62X0 is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM70 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_83xx_WDT=y
+-
+-#
+-# PCI-based Watchdog Cards
+-#
+-# CONFIG_PCIPCWATCHDOG is not set
+-# CONFIG_WDTPCI is not set
+-
+-#
+-# USB-based Watchdog Cards
+-#
+-# CONFIG_USBPCWATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-# CONFIG_USB_DABUSB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-
+-#
+-# USB Input Devices
+-#
+-# CONFIG_USB_HID is not set
+-
+-#
+-# USB HID Boot Protocol drivers
+-#
+-# CONFIG_USB_KBD is not set
+-# CONFIG_USB_MOUSE is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-CONFIG_USB=y
+-# CONFIG_USB_DEBUG is not set
+-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+-
+-#
+-# Miscellaneous USB options
+-#
+-CONFIG_USB_DEVICEFS=y
+-CONFIG_USB_DEVICE_CLASS=y
+-# CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_OTG is not set
+-
+-#
+-# USB Host Controller Drivers
+-#
+-CONFIG_USB_EHCI_HCD=y
+-# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+-# CONFIG_USB_EHCI_FSL is not set
+-CONFIG_USB_EHCI_HCD_PPC_OF=y
+-# CONFIG_USB_ISP116X_HCD is not set
+-CONFIG_USB_OHCI_HCD=y
+-CONFIG_USB_OHCI_HCD_PPC_OF=y
+-CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+-# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+-CONFIG_USB_OHCI_HCD_PCI=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
+-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+-# CONFIG_USB_UHCI_HCD is not set
+-# CONFIG_USB_SL811_HCD is not set
+-# CONFIG_USB_R8A66597_HCD is not set
+-
+-#
+-# USB Device Class drivers
+-#
+-# CONFIG_USB_ACM is not set
+-# CONFIG_USB_PRINTER is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# may also be needed; see USB_STORAGE Help for more information
+-#
+-CONFIG_USB_STORAGE=y
+-# CONFIG_USB_STORAGE_DEBUG is not set
+-# CONFIG_USB_STORAGE_DATAFAB is not set
+-# CONFIG_USB_STORAGE_FREECOM is not set
+-# CONFIG_USB_STORAGE_ISD200 is not set
+-# CONFIG_USB_STORAGE_DPCM is not set
+-# CONFIG_USB_STORAGE_USBAT is not set
+-# CONFIG_USB_STORAGE_SDDR09 is not set
+-# CONFIG_USB_STORAGE_SDDR55 is not set
+-# CONFIG_USB_STORAGE_JUMPSHOT is not set
+-# CONFIG_USB_STORAGE_ALAUDA is not set
+-# CONFIG_USB_STORAGE_KARMA is not set
+-# CONFIG_USB_LIBUSUAL is not set
+-
+-#
+-# USB Imaging devices
+-#
+-# CONFIG_USB_MDC800 is not set
+-# CONFIG_USB_MICROTEK is not set
+-CONFIG_USB_MON=y
+-
+-#
+-# USB port drivers
+-#
+-# CONFIG_USB_SERIAL is not set
+-
+-#
+-# USB Miscellaneous drivers
+-#
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+-# CONFIG_USB_ADUTUX is not set
+-# CONFIG_USB_AUERSWALD is not set
+-# CONFIG_USB_RIO500 is not set
+-# CONFIG_USB_LEGOTOWER is not set
+-# CONFIG_USB_LCD is not set
+-# CONFIG_USB_BERRY_CHARGE is not set
+-# CONFIG_USB_LED is not set
+-# CONFIG_USB_CYPRESS_CY7C63 is not set
+-# CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGET is not set
+-# CONFIG_USB_IDMOUSE is not set
+-# CONFIG_USB_FTDI_ELAN is not set
+-# CONFIG_USB_APPLEDISPLAY is not set
+-# CONFIG_USB_SISUSBVGA is not set
+-# CONFIG_USB_LD is not set
+-# CONFIG_USB_TRANCEVIBRATOR is not set
+-# CONFIG_USB_IOWARRIOR is not set
+-# CONFIG_USB_TEST is not set
+-# CONFIG_USB_GADGET is not set
+-CONFIG_MMC=y
+-# CONFIG_MMC_DEBUG is not set
+-# CONFIG_MMC_UNSAFE_RESUME is not set
+-
+-#
+-# MMC/SD Card Drivers
+-#
+-CONFIG_MMC_BLOCK=y
+-CONFIG_MMC_BLOCK_BOUNCE=y
+-# CONFIG_SDIO_UART is not set
+-
+-#
+-# MMC/SD Host Controller Drivers
+-#
+-# CONFIG_MMC_SDHCI is not set
+-# CONFIG_MMC_WBSD is not set
+-# CONFIG_MMC_TIFM_SD is not set
+-CONFIG_MMC_SPI=y
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-CONFIG_FAT_FS=y
+-CONFIG_MSDOS_FS=y
+-CONFIG_VFAT_FS=y
+-CONFIG_FAT_DEFAULT_CODEPAGE=437
+-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_BSD_DISKLABEL is not set
+-# CONFIG_MINIX_SUBPARTITION is not set
+-# CONFIG_SOLARIS_X86_PARTITION is not set
+-# CONFIG_UNIXWARE_DISKLABEL is not set
+-CONFIG_LDM_PARTITION=y
+-# CONFIG_LDM_DEBUG is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-CONFIG_NLS=y
+-CONFIG_NLS_DEFAULT="iso8859-1"
+-CONFIG_NLS_CODEPAGE_437=y
+-# CONFIG_NLS_CODEPAGE_737 is not set
+-# CONFIG_NLS_CODEPAGE_775 is not set
+-# CONFIG_NLS_CODEPAGE_850 is not set
+-# CONFIG_NLS_CODEPAGE_852 is not set
+-# CONFIG_NLS_CODEPAGE_855 is not set
+-# CONFIG_NLS_CODEPAGE_857 is not set
+-# CONFIG_NLS_CODEPAGE_860 is not set
+-# CONFIG_NLS_CODEPAGE_861 is not set
+-# CONFIG_NLS_CODEPAGE_862 is not set
+-# CONFIG_NLS_CODEPAGE_863 is not set
+-# CONFIG_NLS_CODEPAGE_864 is not set
+-# CONFIG_NLS_CODEPAGE_865 is not set
+-# CONFIG_NLS_CODEPAGE_866 is not set
+-# CONFIG_NLS_CODEPAGE_869 is not set
+-# CONFIG_NLS_CODEPAGE_936 is not set
+-# CONFIG_NLS_CODEPAGE_950 is not set
+-CONFIG_NLS_CODEPAGE_932=y
+-# CONFIG_NLS_CODEPAGE_949 is not set
+-# CONFIG_NLS_CODEPAGE_874 is not set
+-CONFIG_NLS_ISO8859_8=y
+-# CONFIG_NLS_CODEPAGE_1250 is not set
+-# CONFIG_NLS_CODEPAGE_1251 is not set
+-# CONFIG_NLS_ASCII is not set
+-CONFIG_NLS_ISO8859_1=y
+-# CONFIG_NLS_ISO8859_2 is not set
+-# CONFIG_NLS_ISO8859_3 is not set
+-# CONFIG_NLS_ISO8859_4 is not set
+-# CONFIG_NLS_ISO8859_5 is not set
+-# CONFIG_NLS_ISO8859_6 is not set
+-# CONFIG_NLS_ISO8859_7 is not set
+-# CONFIG_NLS_ISO8859_9 is not set
+-# CONFIG_NLS_ISO8859_13 is not set
+-# CONFIG_NLS_ISO8859_14 is not set
+-# CONFIG_NLS_ISO8859_15 is not set
+-# CONFIG_NLS_KOI8_R is not set
+-# CONFIG_NLS_KOI8_U is not set
+-# CONFIG_NLS_UTF8 is not set
+-# CONFIG_DLM is not set
+-CONFIG_UCC_FAST=y
+-CONFIG_UCC=y
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-CONFIG_CRC_ITU_T=y
+-CONFIG_CRC32=y
+-CONFIG_CRC7=y
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=m
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+-CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/mpc834x_itx_defconfig b/arch/powerpc/configs/mpc834x_itx_defconfig
+deleted file mode 100644
+index e1de399..0000000
+--- a/arch/powerpc/configs/mpc834x_itx_defconfig
++++ /dev/null
+@@ -1,1295 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:17 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-CONFIG_6xx=y
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-# CONFIG_FSL_EMB_PERFMON is not set
+-CONFIG_PPC_STD_MMU=y
+-CONFIG_PPC_STD_MMU_32=y
+-# CONFIG_PPC_MM_SLICES is not set
+-# CONFIG_SMP is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MULTIPLATFORM is not set
+-# CONFIG_PPC_82xx is not set
+-CONFIG_PPC_83xx=y
+-# CONFIG_PPC_86xx is not set
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC83xx=y
+-# CONFIG_MPC831x_RDB is not set
+-# CONFIG_MPC832x_MDS is not set
+-# CONFIG_MPC832x_RDB is not set
+-# CONFIG_MPC834x_MDS is not set
+-CONFIG_MPC834x_ITX=y
+-# CONFIG_MPC836x_MDS is not set
+-# CONFIG_MPC837x_MDS is not set
+-# CONFIG_MPC837x_RDB is not set
+-# CONFIG_SBC834x is not set
+-CONFIG_PPC_MPC834x=y
+-CONFIG_IPIC=y
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-# CONFIG_MTD_PARTITIONS is not set
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-# CONFIG_MTD_BLKDEVS is not set
+-# CONFIG_MTD_BLOCK is not set
+-# CONFIG_MTD_BLOCK_RO is not set
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-# CONFIG_MTD_JEDECPROBE is not set
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-CONFIG_MTD_PHYSMAP=y
+-CONFIG_MTD_PHYSMAP_START=0xfe000000
+-CONFIG_MTD_PHYSMAP_LEN=0x1000000
+-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+-# CONFIG_MTD_PHYSMAP_OF is not set
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_DATAFLASH is not set
+-# CONFIG_MTD_M25P80 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-# CONFIG_BLK_DEV_UB is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-CONFIG_IDE=y
+-CONFIG_IDE_MAX_HWIFS=4
+-# CONFIG_BLK_DEV_IDE is not set
+-# CONFIG_BLK_DEV_HD_ONLY is not set
+-# CONFIG_BLK_DEV_HD is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-CONFIG_BLK_DEV_SD=y
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-# CONFIG_BLK_DEV_SR is not set
+-CONFIG_CHR_DEV_SG=y
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-CONFIG_SCSI_SPI_ATTRS=y
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-# CONFIG_SCSI_AIC7XXX is not set
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-# CONFIG_SCSI_AIC79XX is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_BUSLOGIC is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_EATA is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_GDTH is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_MVSAS is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_IPR is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-CONFIG_ATA=y
+-# CONFIG_ATA_NONSTANDARD is not set
+-# CONFIG_SATA_AHCI is not set
+-# CONFIG_SATA_SVW is not set
+-# CONFIG_ATA_PIIX is not set
+-# CONFIG_SATA_MV is not set
+-# CONFIG_SATA_NV is not set
+-# CONFIG_PDC_ADMA is not set
+-# CONFIG_SATA_QSTOR is not set
+-# CONFIG_SATA_PROMISE is not set
+-# CONFIG_SATA_SX4 is not set
+-CONFIG_SATA_SIL=y
+-# CONFIG_SATA_SIL24 is not set
+-# CONFIG_SATA_SIS is not set
+-# CONFIG_SATA_ULI is not set
+-# CONFIG_SATA_VIA is not set
+-# CONFIG_SATA_VITESSE is not set
+-# CONFIG_SATA_INIC162X is not set
+-# CONFIG_SATA_FSL is not set
+-# CONFIG_PATA_ALI is not set
+-# CONFIG_PATA_AMD is not set
+-# CONFIG_PATA_ARTOP is not set
+-# CONFIG_PATA_ATIIXP is not set
+-# CONFIG_PATA_CMD640_PCI is not set
+-# CONFIG_PATA_CMD64X is not set
+-# CONFIG_PATA_CS5520 is not set
+-# CONFIG_PATA_CS5530 is not set
+-# CONFIG_PATA_CYPRESS is not set
+-# CONFIG_PATA_EFAR is not set
+-# CONFIG_ATA_GENERIC is not set
+-# CONFIG_PATA_HPT366 is not set
+-# CONFIG_PATA_HPT37X is not set
+-# CONFIG_PATA_HPT3X2N is not set
+-# CONFIG_PATA_HPT3X3 is not set
+-# CONFIG_PATA_IT821X is not set
+-# CONFIG_PATA_IT8213 is not set
+-# CONFIG_PATA_JMICRON is not set
+-# CONFIG_PATA_TRIFLEX is not set
+-# CONFIG_PATA_MARVELL is not set
+-# CONFIG_PATA_MPIIX is not set
+-# CONFIG_PATA_OLDPIIX is not set
+-# CONFIG_PATA_NETCELL is not set
+-# CONFIG_PATA_NINJA32 is not set
+-# CONFIG_PATA_NS87410 is not set
+-# CONFIG_PATA_NS87415 is not set
+-# CONFIG_PATA_OPTI is not set
+-# CONFIG_PATA_OPTIDMA is not set
+-# CONFIG_PATA_PDC_OLD is not set
+-# CONFIG_PATA_RADISYS is not set
+-# CONFIG_PATA_RZ1000 is not set
+-# CONFIG_PATA_SC1200 is not set
+-# CONFIG_PATA_SERVERWORKS is not set
+-# CONFIG_PATA_PDC2027X is not set
+-# CONFIG_PATA_SIL680 is not set
+-# CONFIG_PATA_SIS is not set
+-# CONFIG_PATA_VIA is not set
+-# CONFIG_PATA_WINBOND is not set
+-CONFIG_PATA_PLATFORM=y
+-CONFIG_PATA_OF_PLATFORM=y
+-CONFIG_MD=y
+-CONFIG_BLK_DEV_MD=y
+-CONFIG_MD_LINEAR=y
+-CONFIG_MD_RAID0=y
+-CONFIG_MD_RAID1=y
+-# CONFIG_MD_RAID10 is not set
+-# CONFIG_MD_RAID456 is not set
+-# CONFIG_MD_MULTIPATH is not set
+-# CONFIG_MD_FAULTY is not set
+-# CONFIG_BLK_DEV_DM is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-CONFIG_CICADA_PHY=y
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-# CONFIG_NET_ETHERNET is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NET_FC is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-# CONFIG_SERIAL_8250_PCI is not set
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_TINY_USB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-CONFIG_SENSORS_PCF8574=y
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-CONFIG_SPI=y
+-CONFIG_SPI_MASTER=y
+-
+-#
+-# SPI Master Controller Drivers
+-#
+-CONFIG_SPI_BITBANG=y
+-CONFIG_SPI_MPC83xx=y
+-
+-#
+-# SPI Protocol Masters
+-#
+-# CONFIG_SPI_AT25 is not set
+-# CONFIG_SPI_SPIDEV is not set
+-# CONFIG_SPI_TLE62X0 is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-# CONFIG_THERMAL is not set
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_83xx_WDT=y
+-
+-#
+-# PCI-based Watchdog Cards
+-#
+-# CONFIG_PCIPCWATCHDOG is not set
+-# CONFIG_WDTPCI is not set
+-
+-#
+-# USB-based Watchdog Cards
+-#
+-# CONFIG_USBPCWATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-# CONFIG_USB_DABUSB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-CONFIG_USB=y
+-# CONFIG_USB_DEBUG is not set
+-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+-
+-#
+-# Miscellaneous USB options
+-#
+-CONFIG_USB_DEVICEFS=y
+-CONFIG_USB_DEVICE_CLASS=y
+-# CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_OTG is not set
+-
+-#
+-# USB Host Controller Drivers
+-#
+-CONFIG_USB_EHCI_HCD=y
+-CONFIG_USB_EHCI_ROOT_HUB_TT=y
+-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+-CONFIG_USB_EHCI_FSL=y
+-CONFIG_USB_EHCI_HCD_PPC_OF=y
+-# CONFIG_USB_ISP116X_HCD is not set
+-# CONFIG_USB_OHCI_HCD is not set
+-CONFIG_USB_UHCI_HCD=y
+-# CONFIG_USB_SL811_HCD is not set
+-# CONFIG_USB_R8A66597_HCD is not set
+-
+-#
+-# USB Device Class drivers
+-#
+-# CONFIG_USB_ACM is not set
+-# CONFIG_USB_PRINTER is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# may also be needed; see USB_STORAGE Help for more information
+-#
+-CONFIG_USB_STORAGE=y
+-# CONFIG_USB_STORAGE_DEBUG is not set
+-# CONFIG_USB_STORAGE_DATAFAB is not set
+-# CONFIG_USB_STORAGE_FREECOM is not set
+-# CONFIG_USB_STORAGE_ISD200 is not set
+-# CONFIG_USB_STORAGE_DPCM is not set
+-# CONFIG_USB_STORAGE_USBAT is not set
+-# CONFIG_USB_STORAGE_SDDR09 is not set
+-# CONFIG_USB_STORAGE_SDDR55 is not set
+-# CONFIG_USB_STORAGE_JUMPSHOT is not set
+-# CONFIG_USB_STORAGE_ALAUDA is not set
+-# CONFIG_USB_STORAGE_KARMA is not set
+-# CONFIG_USB_LIBUSUAL is not set
+-
+-#
+-# USB Imaging devices
+-#
+-# CONFIG_USB_MDC800 is not set
+-# CONFIG_USB_MICROTEK is not set
+-CONFIG_USB_MON=y
+-
+-#
+-# USB port drivers
+-#
+-# CONFIG_USB_SERIAL is not set
+-
+-#
+-# USB Miscellaneous drivers
+-#
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+-# CONFIG_USB_ADUTUX is not set
+-# CONFIG_USB_AUERSWALD is not set
+-# CONFIG_USB_RIO500 is not set
+-# CONFIG_USB_LEGOTOWER is not set
+-# CONFIG_USB_LCD is not set
+-# CONFIG_USB_BERRY_CHARGE is not set
+-# CONFIG_USB_LED is not set
+-# CONFIG_USB_CYPRESS_CY7C63 is not set
+-# CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGET is not set
+-# CONFIG_USB_IDMOUSE is not set
+-# CONFIG_USB_FTDI_ELAN is not set
+-# CONFIG_USB_APPLEDISPLAY is not set
+-# CONFIG_USB_SISUSBVGA is not set
+-# CONFIG_USB_LD is not set
+-# CONFIG_USB_TRANCEVIBRATOR is not set
+-# CONFIG_USB_IOWARRIOR is not set
+-# CONFIG_USB_TEST is not set
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-CONFIG_RTC_LIB=y
+-CONFIG_RTC_CLASS=y
+-CONFIG_RTC_HCTOSYS=y
+-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+-# CONFIG_RTC_DEBUG is not set
+-
+-#
+-# RTC interfaces
+-#
+-CONFIG_RTC_INTF_SYSFS=y
+-CONFIG_RTC_INTF_PROC=y
+-CONFIG_RTC_INTF_DEV=y
+-CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+-# CONFIG_RTC_DRV_TEST is not set
+-
+-#
+-# I2C RTC drivers
+-#
+-CONFIG_RTC_DRV_DS1307=y
+-# CONFIG_RTC_DRV_DS1374 is not set
+-# CONFIG_RTC_DRV_DS1672 is not set
+-# CONFIG_RTC_DRV_MAX6900 is not set
+-# CONFIG_RTC_DRV_RS5C372 is not set
+-# CONFIG_RTC_DRV_ISL1208 is not set
+-# CONFIG_RTC_DRV_X1205 is not set
+-# CONFIG_RTC_DRV_PCF8563 is not set
+-# CONFIG_RTC_DRV_PCF8583 is not set
+-# CONFIG_RTC_DRV_M41T80 is not set
+-# CONFIG_RTC_DRV_S35390A is not set
+-
+-#
+-# SPI RTC drivers
+-#
+-# CONFIG_RTC_DRV_MAX6902 is not set
+-# CONFIG_RTC_DRV_R9701 is not set
+-# CONFIG_RTC_DRV_RS5C348 is not set
+-
+-#
+-# Platform RTC drivers
+-#
+-# CONFIG_RTC_DRV_CMOS is not set
+-# CONFIG_RTC_DRV_DS1511 is not set
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
+-# CONFIG_RTC_DRV_STK17TA8 is not set
+-# CONFIG_RTC_DRV_M48T86 is not set
+-# CONFIG_RTC_DRV_M48T59 is not set
+-# CONFIG_RTC_DRV_V3020 is not set
+-
+-#
+-# on-CPU RTC drivers
+-#
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-CONFIG_FAT_FS=y
+-CONFIG_MSDOS_FS=y
+-CONFIG_VFAT_FS=y
+-CONFIG_FAT_DEFAULT_CODEPAGE=437
+-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_JFFS2_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-CONFIG_MAC_PARTITION=y
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_BSD_DISKLABEL is not set
+-# CONFIG_MINIX_SUBPARTITION is not set
+-# CONFIG_SOLARIS_X86_PARTITION is not set
+-# CONFIG_UNIXWARE_DISKLABEL is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-CONFIG_NLS=y
+-CONFIG_NLS_DEFAULT="iso8859-1"
+-# CONFIG_NLS_CODEPAGE_437 is not set
+-# CONFIG_NLS_CODEPAGE_737 is not set
+-# CONFIG_NLS_CODEPAGE_775 is not set
+-# CONFIG_NLS_CODEPAGE_850 is not set
+-# CONFIG_NLS_CODEPAGE_852 is not set
+-# CONFIG_NLS_CODEPAGE_855 is not set
+-# CONFIG_NLS_CODEPAGE_857 is not set
+-# CONFIG_NLS_CODEPAGE_860 is not set
+-# CONFIG_NLS_CODEPAGE_861 is not set
+-# CONFIG_NLS_CODEPAGE_862 is not set
+-# CONFIG_NLS_CODEPAGE_863 is not set
+-# CONFIG_NLS_CODEPAGE_864 is not set
+-# CONFIG_NLS_CODEPAGE_865 is not set
+-# CONFIG_NLS_CODEPAGE_866 is not set
+-# CONFIG_NLS_CODEPAGE_869 is not set
+-# CONFIG_NLS_CODEPAGE_936 is not set
+-# CONFIG_NLS_CODEPAGE_950 is not set
+-# CONFIG_NLS_CODEPAGE_932 is not set
+-# CONFIG_NLS_CODEPAGE_949 is not set
+-# CONFIG_NLS_CODEPAGE_874 is not set
+-# CONFIG_NLS_ISO8859_8 is not set
+-# CONFIG_NLS_CODEPAGE_1250 is not set
+-# CONFIG_NLS_CODEPAGE_1251 is not set
+-# CONFIG_NLS_ASCII is not set
+-# CONFIG_NLS_ISO8859_1 is not set
+-# CONFIG_NLS_ISO8859_2 is not set
+-# CONFIG_NLS_ISO8859_3 is not set
+-# CONFIG_NLS_ISO8859_4 is not set
+-# CONFIG_NLS_ISO8859_5 is not set
+-# CONFIG_NLS_ISO8859_6 is not set
+-# CONFIG_NLS_ISO8859_7 is not set
+-# CONFIG_NLS_ISO8859_9 is not set
+-# CONFIG_NLS_ISO8859_13 is not set
+-# CONFIG_NLS_ISO8859_14 is not set
+-# CONFIG_NLS_ISO8859_15 is not set
+-# CONFIG_NLS_KOI8_R is not set
+-# CONFIG_NLS_KOI8_U is not set
+-# CONFIG_NLS_UTF8 is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/mpc834x_itxgp_defconfig b/arch/powerpc/configs/mpc834x_itxgp_defconfig
+deleted file mode 100644
+index b4e39cf..0000000
+--- a/arch/powerpc/configs/mpc834x_itxgp_defconfig
++++ /dev/null
+@@ -1,1222 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:18 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-CONFIG_6xx=y
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-# CONFIG_FSL_EMB_PERFMON is not set
+-CONFIG_PPC_STD_MMU=y
+-CONFIG_PPC_STD_MMU_32=y
+-# CONFIG_PPC_MM_SLICES is not set
+-# CONFIG_SMP is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MULTIPLATFORM is not set
+-# CONFIG_PPC_82xx is not set
+-CONFIG_PPC_83xx=y
+-# CONFIG_PPC_86xx is not set
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC83xx=y
+-# CONFIG_MPC831x_RDB is not set
+-# CONFIG_MPC832x_MDS is not set
+-# CONFIG_MPC832x_RDB is not set
+-# CONFIG_MPC834x_MDS is not set
+-CONFIG_MPC834x_ITX=y
+-# CONFIG_MPC836x_MDS is not set
+-# CONFIG_MPC837x_MDS is not set
+-# CONFIG_MPC837x_RDB is not set
+-# CONFIG_SBC834x is not set
+-CONFIG_PPC_MPC834x=y
+-CONFIG_IPIC=y
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-# CONFIG_MTD_PARTITIONS is not set
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-# CONFIG_MTD_BLKDEVS is not set
+-# CONFIG_MTD_BLOCK is not set
+-# CONFIG_MTD_BLOCK_RO is not set
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-# CONFIG_MTD_JEDECPROBE is not set
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-CONFIG_MTD_PHYSMAP=y
+-CONFIG_MTD_PHYSMAP_START=0xfe000000
+-CONFIG_MTD_PHYSMAP_LEN=0x800000
+-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+-# CONFIG_MTD_PHYSMAP_OF is not set
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_DATAFLASH is not set
+-# CONFIG_MTD_M25P80 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-# CONFIG_BLK_DEV_UB is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-CONFIG_BLK_DEV_SD=y
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-# CONFIG_BLK_DEV_SR is not set
+-CONFIG_CHR_DEV_SG=y
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-CONFIG_SCSI_SPI_ATTRS=y
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-# CONFIG_SCSI_AIC7XXX is not set
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-# CONFIG_SCSI_AIC79XX is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_BUSLOGIC is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_EATA is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_GDTH is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_MVSAS is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-CONFIG_CICADA_PHY=y
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-# CONFIG_NET_ETHERNET is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NET_FC is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-# CONFIG_SERIAL_8250_PCI is not set
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_TINY_USB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-CONFIG_SENSORS_PCF8574=y
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-CONFIG_SPI=y
+-CONFIG_SPI_MASTER=y
+-
+-#
+-# SPI Master Controller Drivers
+-#
+-CONFIG_SPI_BITBANG=y
+-CONFIG_SPI_MPC83xx=y
+-
+-#
+-# SPI Protocol Masters
+-#
+-# CONFIG_SPI_AT25 is not set
+-# CONFIG_SPI_SPIDEV is not set
+-# CONFIG_SPI_TLE62X0 is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-# CONFIG_THERMAL is not set
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_83xx_WDT=y
+-
+-#
+-# PCI-based Watchdog Cards
+-#
+-# CONFIG_PCIPCWATCHDOG is not set
+-# CONFIG_WDTPCI is not set
+-
+-#
+-# USB-based Watchdog Cards
+-#
+-# CONFIG_USBPCWATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-# CONFIG_USB_DABUSB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-CONFIG_USB=y
+-# CONFIG_USB_DEBUG is not set
+-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+-
+-#
+-# Miscellaneous USB options
+-#
+-# CONFIG_USB_DEVICEFS is not set
+-CONFIG_USB_DEVICE_CLASS=y
+-# CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_OTG is not set
+-
+-#
+-# USB Host Controller Drivers
+-#
+-CONFIG_USB_EHCI_HCD=y
+-CONFIG_USB_EHCI_ROOT_HUB_TT=y
+-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+-CONFIG_USB_EHCI_FSL=y
+-CONFIG_USB_EHCI_HCD_PPC_OF=y
+-# CONFIG_USB_ISP116X_HCD is not set
+-# CONFIG_USB_OHCI_HCD is not set
+-CONFIG_USB_UHCI_HCD=y
+-# CONFIG_USB_SL811_HCD is not set
+-# CONFIG_USB_R8A66597_HCD is not set
+-
+-#
+-# USB Device Class drivers
+-#
+-# CONFIG_USB_ACM is not set
+-# CONFIG_USB_PRINTER is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# may also be needed; see USB_STORAGE Help for more information
+-#
+-CONFIG_USB_STORAGE=y
+-# CONFIG_USB_STORAGE_DEBUG is not set
+-# CONFIG_USB_STORAGE_DATAFAB is not set
+-# CONFIG_USB_STORAGE_FREECOM is not set
+-# CONFIG_USB_STORAGE_ISD200 is not set
+-# CONFIG_USB_STORAGE_DPCM is not set
+-# CONFIG_USB_STORAGE_USBAT is not set
+-# CONFIG_USB_STORAGE_SDDR09 is not set
+-# CONFIG_USB_STORAGE_SDDR55 is not set
+-# CONFIG_USB_STORAGE_JUMPSHOT is not set
+-# CONFIG_USB_STORAGE_ALAUDA is not set
+-# CONFIG_USB_STORAGE_KARMA is not set
+-# CONFIG_USB_LIBUSUAL is not set
+-
+-#
+-# USB Imaging devices
+-#
+-# CONFIG_USB_MDC800 is not set
+-# CONFIG_USB_MICROTEK is not set
+-CONFIG_USB_MON=y
+-
+-#
+-# USB port drivers
+-#
+-# CONFIG_USB_SERIAL is not set
+-
+-#
+-# USB Miscellaneous drivers
+-#
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+-# CONFIG_USB_ADUTUX is not set
+-# CONFIG_USB_AUERSWALD is not set
+-# CONFIG_USB_RIO500 is not set
+-# CONFIG_USB_LEGOTOWER is not set
+-# CONFIG_USB_LCD is not set
+-# CONFIG_USB_BERRY_CHARGE is not set
+-# CONFIG_USB_LED is not set
+-# CONFIG_USB_CYPRESS_CY7C63 is not set
+-# CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGET is not set
+-# CONFIG_USB_IDMOUSE is not set
+-# CONFIG_USB_FTDI_ELAN is not set
+-# CONFIG_USB_APPLEDISPLAY is not set
+-# CONFIG_USB_SISUSBVGA is not set
+-# CONFIG_USB_LD is not set
+-# CONFIG_USB_TRANCEVIBRATOR is not set
+-# CONFIG_USB_IOWARRIOR is not set
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-CONFIG_RTC_LIB=y
+-CONFIG_RTC_CLASS=y
+-CONFIG_RTC_HCTOSYS=y
+-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+-# CONFIG_RTC_DEBUG is not set
+-
+-#
+-# RTC interfaces
+-#
+-CONFIG_RTC_INTF_SYSFS=y
+-CONFIG_RTC_INTF_PROC=y
+-CONFIG_RTC_INTF_DEV=y
+-CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+-# CONFIG_RTC_DRV_TEST is not set
+-
+-#
+-# I2C RTC drivers
+-#
+-CONFIG_RTC_DRV_DS1307=y
+-# CONFIG_RTC_DRV_DS1374 is not set
+-# CONFIG_RTC_DRV_DS1672 is not set
+-# CONFIG_RTC_DRV_MAX6900 is not set
+-# CONFIG_RTC_DRV_RS5C372 is not set
+-# CONFIG_RTC_DRV_ISL1208 is not set
+-# CONFIG_RTC_DRV_X1205 is not set
+-# CONFIG_RTC_DRV_PCF8563 is not set
+-# CONFIG_RTC_DRV_PCF8583 is not set
+-# CONFIG_RTC_DRV_M41T80 is not set
+-# CONFIG_RTC_DRV_S35390A is not set
+-
+-#
+-# SPI RTC drivers
+-#
+-# CONFIG_RTC_DRV_MAX6902 is not set
+-# CONFIG_RTC_DRV_R9701 is not set
+-# CONFIG_RTC_DRV_RS5C348 is not set
+-
+-#
+-# Platform RTC drivers
+-#
+-# CONFIG_RTC_DRV_CMOS is not set
+-# CONFIG_RTC_DRV_DS1511 is not set
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
+-# CONFIG_RTC_DRV_STK17TA8 is not set
+-# CONFIG_RTC_DRV_M48T86 is not set
+-# CONFIG_RTC_DRV_M48T59 is not set
+-# CONFIG_RTC_DRV_V3020 is not set
+-
+-#
+-# on-CPU RTC drivers
+-#
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-CONFIG_FAT_FS=y
+-CONFIG_MSDOS_FS=y
+-CONFIG_VFAT_FS=y
+-CONFIG_FAT_DEFAULT_CODEPAGE=437
+-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_JFFS2_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-CONFIG_MAC_PARTITION=y
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_BSD_DISKLABEL is not set
+-# CONFIG_MINIX_SUBPARTITION is not set
+-# CONFIG_SOLARIS_X86_PARTITION is not set
+-# CONFIG_UNIXWARE_DISKLABEL is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-CONFIG_NLS=y
+-CONFIG_NLS_DEFAULT="iso8859-1"
+-# CONFIG_NLS_CODEPAGE_437 is not set
+-# CONFIG_NLS_CODEPAGE_737 is not set
+-# CONFIG_NLS_CODEPAGE_775 is not set
+-# CONFIG_NLS_CODEPAGE_850 is not set
+-# CONFIG_NLS_CODEPAGE_852 is not set
+-# CONFIG_NLS_CODEPAGE_855 is not set
+-# CONFIG_NLS_CODEPAGE_857 is not set
+-# CONFIG_NLS_CODEPAGE_860 is not set
+-# CONFIG_NLS_CODEPAGE_861 is not set
+-# CONFIG_NLS_CODEPAGE_862 is not set
+-# CONFIG_NLS_CODEPAGE_863 is not set
+-# CONFIG_NLS_CODEPAGE_864 is not set
+-# CONFIG_NLS_CODEPAGE_865 is not set
+-# CONFIG_NLS_CODEPAGE_866 is not set
+-# CONFIG_NLS_CODEPAGE_869 is not set
+-# CONFIG_NLS_CODEPAGE_936 is not set
+-# CONFIG_NLS_CODEPAGE_950 is not set
+-# CONFIG_NLS_CODEPAGE_932 is not set
+-# CONFIG_NLS_CODEPAGE_949 is not set
+-# CONFIG_NLS_CODEPAGE_874 is not set
+-# CONFIG_NLS_ISO8859_8 is not set
+-# CONFIG_NLS_CODEPAGE_1250 is not set
+-# CONFIG_NLS_CODEPAGE_1251 is not set
+-# CONFIG_NLS_ASCII is not set
+-# CONFIG_NLS_ISO8859_1 is not set
+-# CONFIG_NLS_ISO8859_2 is not set
+-# CONFIG_NLS_ISO8859_3 is not set
+-# CONFIG_NLS_ISO8859_4 is not set
+-# CONFIG_NLS_ISO8859_5 is not set
+-# CONFIG_NLS_ISO8859_6 is not set
+-# CONFIG_NLS_ISO8859_7 is not set
+-# CONFIG_NLS_ISO8859_9 is not set
+-# CONFIG_NLS_ISO8859_13 is not set
+-# CONFIG_NLS_ISO8859_14 is not set
+-# CONFIG_NLS_ISO8859_15 is not set
+-# CONFIG_NLS_KOI8_R is not set
+-# CONFIG_NLS_KOI8_U is not set
+-# CONFIG_NLS_UTF8 is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/mpc834x_mds_defconfig b/arch/powerpc/configs/mpc834x_mds_defconfig
+deleted file mode 100644
+index b4e82c0..0000000
+--- a/arch/powerpc/configs/mpc834x_mds_defconfig
++++ /dev/null
+@@ -1,1021 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc7
+-# Mon Mar 31 11:36:56 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-CONFIG_6xx=y
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-# CONFIG_FSL_EMB_PERFMON is not set
+-CONFIG_PPC_STD_MMU=y
+-CONFIG_PPC_STD_MMU_32=y
+-# CONFIG_PPC_MM_SLICES is not set
+-# CONFIG_SMP is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MULTIPLATFORM is not set
+-# CONFIG_PPC_82xx is not set
+-CONFIG_PPC_83xx=y
+-# CONFIG_PPC_86xx is not set
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC83xx=y
+-# CONFIG_MPC831x_RDB is not set
+-# CONFIG_MPC832x_MDS is not set
+-# CONFIG_MPC832x_RDB is not set
+-CONFIG_MPC834x_MDS=y
+-# CONFIG_MPC834x_ITX is not set
+-# CONFIG_MPC836x_MDS is not set
+-# CONFIG_MPC837x_MDS is not set
+-# CONFIG_MPC837x_RDB is not set
+-# CONFIG_SBC834x is not set
+-CONFIG_PPC_MPC834x=y
+-CONFIG_IPIC=y
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-CONFIG_XFRM_USER=m
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-CONFIG_MARVELL_PHY=y
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-CONFIG_NET_PCI=y
+-# CONFIG_PCNET32 is not set
+-# CONFIG_AMD8111_ETH is not set
+-# CONFIG_ADAPTEC_STARFIRE is not set
+-# CONFIG_B44 is not set
+-# CONFIG_FORCEDETH is not set
+-# CONFIG_EEPRO100 is not set
+-CONFIG_E100=y
+-# CONFIG_FEALNX is not set
+-# CONFIG_NATSEMI is not set
+-# CONFIG_NE2K_PCI is not set
+-# CONFIG_8139CP is not set
+-# CONFIG_8139TOO is not set
+-# CONFIG_R6040 is not set
+-# CONFIG_SIS900 is not set
+-# CONFIG_EPIC100 is not set
+-# CONFIG_SUNDANCE is not set
+-# CONFIG_TLAN is not set
+-# CONFIG_VIA_RHINE is not set
+-# CONFIG_SC92031 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-# CONFIG_GFAR_NAPI is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_83xx_WDT=y
+-
+-#
+-# PCI-based Watchdog Cards
+-#
+-# CONFIG_PCIPCWATCHDOG is not set
+-# CONFIG_WDTPCI is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-CONFIG_RTC_LIB=y
+-CONFIG_RTC_CLASS=y
+-CONFIG_RTC_HCTOSYS=y
+-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+-# CONFIG_RTC_DEBUG is not set
+-
+-#
+-# RTC interfaces
+-#
+-CONFIG_RTC_INTF_SYSFS=y
+-CONFIG_RTC_INTF_PROC=y
+-CONFIG_RTC_INTF_DEV=y
+-# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+-# CONFIG_RTC_DRV_TEST is not set
+-
+-#
+-# I2C RTC drivers
+-#
+-# CONFIG_RTC_DRV_DS1307 is not set
+-CONFIG_RTC_DRV_DS1374=y
+-# CONFIG_RTC_DRV_DS1672 is not set
+-# CONFIG_RTC_DRV_MAX6900 is not set
+-# CONFIG_RTC_DRV_RS5C372 is not set
+-# CONFIG_RTC_DRV_ISL1208 is not set
+-# CONFIG_RTC_DRV_X1205 is not set
+-# CONFIG_RTC_DRV_PCF8563 is not set
+-# CONFIG_RTC_DRV_PCF8583 is not set
+-# CONFIG_RTC_DRV_M41T80 is not set
+-# CONFIG_RTC_DRV_S35390A is not set
+-
+-#
+-# SPI RTC drivers
+-#
+-
+-#
+-# Platform RTC drivers
+-#
+-# CONFIG_RTC_DRV_CMOS is not set
+-# CONFIG_RTC_DRV_DS1511 is not set
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
+-# CONFIG_RTC_DRV_STK17TA8 is not set
+-# CONFIG_RTC_DRV_M48T86 is not set
+-# CONFIG_RTC_DRV_M48T59 is not set
+-# CONFIG_RTC_DRV_V3020 is not set
+-
+-#
+-# on-CPU RTC drivers
+-#
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=m
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/mpc836x_mds_defconfig b/arch/powerpc/configs/mpc836x_mds_defconfig
+deleted file mode 100644
+index d50a96e..0000000
+--- a/arch/powerpc/configs/mpc836x_mds_defconfig
++++ /dev/null
+@@ -1,1079 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc7
+-# Mon Mar 31 11:36:57 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-CONFIG_6xx=y
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-# CONFIG_FSL_EMB_PERFMON is not set
+-CONFIG_PPC_STD_MMU=y
+-CONFIG_PPC_STD_MMU_32=y
+-# CONFIG_PPC_MM_SLICES is not set
+-# CONFIG_SMP is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MULTIPLATFORM is not set
+-# CONFIG_PPC_82xx is not set
+-CONFIG_PPC_83xx=y
+-# CONFIG_PPC_86xx is not set
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC83xx=y
+-# CONFIG_MPC831x_RDB is not set
+-# CONFIG_MPC832x_MDS is not set
+-# CONFIG_MPC832x_RDB is not set
+-# CONFIG_MPC834x_MDS is not set
+-# CONFIG_MPC834x_ITX is not set
+-CONFIG_MPC836x_MDS=y
+-# CONFIG_MPC837x_MDS is not set
+-# CONFIG_MPC837x_RDB is not set
+-# CONFIG_SBC834x is not set
+-CONFIG_IPIC=y
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-CONFIG_QUICC_ENGINE=y
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-# CONFIG_BLK_DEV_SD is not set
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-# CONFIG_BLK_DEV_SR is not set
+-# CONFIG_CHR_DEV_SG is not set
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-# CONFIG_SCSI_SPI_ATTRS is not set
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-# CONFIG_SCSI_AIC7XXX is not set
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-# CONFIG_SCSI_AIC79XX is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_BUSLOGIC is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_EATA is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_GDTH is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_MVSAS is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-CONFIG_MARVELL_PHY=y
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-# CONFIG_GIANFAR is not set
+-CONFIG_UCC_GETH=y
+-# CONFIG_UGETH_NAPI is not set
+-# CONFIG_UGETH_MAGIC_PACKET is not set
+-# CONFIG_UGETH_FILTERING is not set
+-# CONFIG_UGETH_TX_ON_DEMAND is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NET_FC is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-# CONFIG_SERIAL_QE is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_83xx_WDT=y
+-
+-#
+-# PCI-based Watchdog Cards
+-#
+-# CONFIG_PCIPCWATCHDOG is not set
+-# CONFIG_WDTPCI is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-CONFIG_RTC_LIB=y
+-CONFIG_RTC_CLASS=y
+-CONFIG_RTC_HCTOSYS=y
+-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+-# CONFIG_RTC_DEBUG is not set
+-
+-#
+-# RTC interfaces
+-#
+-CONFIG_RTC_INTF_SYSFS=y
+-CONFIG_RTC_INTF_PROC=y
+-CONFIG_RTC_INTF_DEV=y
+-# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+-# CONFIG_RTC_DRV_TEST is not set
+-
+-#
+-# I2C RTC drivers
+-#
+-# CONFIG_RTC_DRV_DS1307 is not set
+-CONFIG_RTC_DRV_DS1374=y
+-# CONFIG_RTC_DRV_DS1672 is not set
+-# CONFIG_RTC_DRV_MAX6900 is not set
+-# CONFIG_RTC_DRV_RS5C372 is not set
+-# CONFIG_RTC_DRV_ISL1208 is not set
+-# CONFIG_RTC_DRV_X1205 is not set
+-# CONFIG_RTC_DRV_PCF8563 is not set
+-# CONFIG_RTC_DRV_PCF8583 is not set
+-# CONFIG_RTC_DRV_M41T80 is not set
+-# CONFIG_RTC_DRV_S35390A is not set
+-
+-#
+-# SPI RTC drivers
+-#
+-
+-#
+-# Platform RTC drivers
+-#
+-# CONFIG_RTC_DRV_CMOS is not set
+-# CONFIG_RTC_DRV_DS1511 is not set
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
+-# CONFIG_RTC_DRV_STK17TA8 is not set
+-# CONFIG_RTC_DRV_M48T86 is not set
+-# CONFIG_RTC_DRV_M48T59 is not set
+-# CONFIG_RTC_DRV_V3020 is not set
+-
+-#
+-# on-CPU RTC drivers
+-#
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-CONFIG_UCC_FAST=y
+-CONFIG_UCC=y
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=m
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+-CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/mpc837x_mds_defconfig b/arch/powerpc/configs/mpc837x_mds_defconfig
+deleted file mode 100644
+index f377cde..0000000
+--- a/arch/powerpc/configs/mpc837x_mds_defconfig
++++ /dev/null
+@@ -1,899 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:23 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-CONFIG_6xx=y
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-# CONFIG_FSL_EMB_PERFMON is not set
+-CONFIG_PPC_STD_MMU=y
+-CONFIG_PPC_STD_MMU_32=y
+-# CONFIG_PPC_MM_SLICES is not set
+-# CONFIG_SMP is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLAB=y
+-# CONFIG_SLUB is not set
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MULTIPLATFORM is not set
+-# CONFIG_PPC_82xx is not set
+-CONFIG_PPC_83xx=y
+-# CONFIG_PPC_86xx is not set
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC83xx=y
+-# CONFIG_MPC831x_RDB is not set
+-# CONFIG_MPC832x_MDS is not set
+-# CONFIG_MPC832x_RDB is not set
+-# CONFIG_MPC834x_MDS is not set
+-# CONFIG_MPC834x_ITX is not set
+-# CONFIG_MPC836x_MDS is not set
+-CONFIG_MPC837x_MDS=y
+-# CONFIG_MPC837x_RDB is not set
+-# CONFIG_SBC834x is not set
+-CONFIG_PPC_MPC837x=y
+-CONFIG_IPIC=y
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-# CONFIG_PCI is not set
+-# CONFIG_PCI_DOMAINS is not set
+-# CONFIG_PCI_SYSCALL is not set
+-# CONFIG_ARCH_SUPPORTS_MSI is not set
+-# CONFIG_PCCARD is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-CONFIG_XFRM_USER=m
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-CONFIG_BLK_DEV_SD=y
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-# CONFIG_BLK_DEV_SR is not set
+-CONFIG_CHR_DEV_SG=y
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-# CONFIG_SCSI_SPI_ATTRS is not set
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_SCSI_DEBUG is not set
+-CONFIG_ATA=y
+-# CONFIG_ATA_NONSTANDARD is not set
+-# CONFIG_SATA_MV is not set
+-CONFIG_SATA_FSL=y
+-# CONFIG_PATA_PLATFORM is not set
+-# CONFIG_MD is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-CONFIG_MARVELL_PHY=y
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_E1000E_ENABLED is not set
+-CONFIG_GIANFAR=y
+-# CONFIG_GFAR_NAPI is not set
+-CONFIG_NETDEV_10000=y
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_83xx_WDT=y
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-# CONFIG_USB_ARCH_HAS_OHCI is not set
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_BSD_DISKLABEL is not set
+-# CONFIG_MINIX_SUBPARTITION is not set
+-# CONFIG_SOLARIS_X86_PARTITION is not set
+-# CONFIG_UNIXWARE_DISKLABEL is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=m
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/mpc837x_rdb_defconfig b/arch/powerpc/configs/mpc837x_rdb_defconfig
+deleted file mode 100644
+index a633176..0000000
+--- a/arch/powerpc/configs/mpc837x_rdb_defconfig
++++ /dev/null
+@@ -1,930 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:24 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-CONFIG_6xx=y
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-# CONFIG_FSL_EMB_PERFMON is not set
+-CONFIG_PPC_STD_MMU=y
+-CONFIG_PPC_STD_MMU_32=y
+-# CONFIG_PPC_MM_SLICES is not set
+-# CONFIG_SMP is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLAB=y
+-# CONFIG_SLUB is not set
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MULTIPLATFORM is not set
+-# CONFIG_PPC_82xx is not set
+-CONFIG_PPC_83xx=y
+-# CONFIG_PPC_86xx is not set
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC83xx=y
+-# CONFIG_MPC831x_RDB is not set
+-# CONFIG_MPC832x_MDS is not set
+-# CONFIG_MPC832x_RDB is not set
+-# CONFIG_MPC834x_MDS is not set
+-# CONFIG_MPC834x_ITX is not set
+-# CONFIG_MPC836x_MDS is not set
+-# CONFIG_MPC837x_MDS is not set
+-CONFIG_MPC837x_RDB=y
+-# CONFIG_SBC834x is not set
+-CONFIG_PPC_MPC837x=y
+-CONFIG_IPIC=y
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-# CONFIG_PCI is not set
+-# CONFIG_PCI_DOMAINS is not set
+-# CONFIG_PCI_SYSCALL is not set
+-# CONFIG_ARCH_SUPPORTS_MSI is not set
+-# CONFIG_PCCARD is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+-# CONFIG_INET_XFRM_MODE_BEET is not set
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-CONFIG_BLK_DEV_SD=y
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-# CONFIG_BLK_DEV_SR is not set
+-CONFIG_CHR_DEV_SG=y
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-# CONFIG_SCSI_SPI_ATTRS is not set
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_SCSI_DEBUG is not set
+-CONFIG_ATA=y
+-# CONFIG_ATA_NONSTANDARD is not set
+-# CONFIG_SATA_MV is not set
+-CONFIG_SATA_FSL=y
+-# CONFIG_PATA_PLATFORM is not set
+-CONFIG_MD=y
+-CONFIG_BLK_DEV_MD=y
+-# CONFIG_MD_LINEAR is not set
+-# CONFIG_MD_RAID0 is not set
+-CONFIG_MD_RAID1=y
+-# CONFIG_MD_RAID10 is not set
+-CONFIG_MD_RAID456=y
+-CONFIG_MD_RAID5_RESHAPE=y
+-# CONFIG_MD_MULTIPATH is not set
+-# CONFIG_MD_FAULTY is not set
+-# CONFIG_BLK_DEV_DM is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-CONFIG_MARVELL_PHY=y
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_E1000E_ENABLED is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_NETDEV_10000 is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_83xx_WDT=y
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-# CONFIG_USB_ARCH_HAS_OHCI is not set
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-CONFIG_USB=y
+-# CONFIG_USB_DEBUG is not set
+-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+-
+-#
+-# Miscellaneous USB options
+-#
+-# CONFIG_USB_DEVICEFS is not set
+-CONFIG_USB_DEVICE_CLASS=y
+-# CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_OTG is not set
+-
+-#
+-# USB Host Controller Drivers
+-#
+-CONFIG_USB_EHCI_HCD=y
+-CONFIG_USB_EHCI_ROOT_HUB_TT=y
+-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+-CONFIG_USB_EHCI_FSL=y
+-CONFIG_USB_EHCI_HCD_PPC_OF=y
+-# CONFIG_USB_ISP116X_HCD is not set
+-# CONFIG_USB_SL811_HCD is not set
+-# CONFIG_USB_R8A66597_HCD is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_BSD_DISKLABEL is not set
+-# CONFIG_MINIX_SUBPARTITION is not set
+-# CONFIG_SOLARIS_X86_PARTITION is not set
+-# CONFIG_UNIXWARE_DISKLABEL is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-# CONFIG_ENABLE_MUST_CHECK is not set
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_XOR_BLOCKS=y
+-CONFIG_ASYNC_CORE=y
+-CONFIG_ASYNC_MEMCPY=y
+-CONFIG_ASYNC_XOR=y
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=m
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/mpc83xx_defconfig b/arch/powerpc/configs/mpc83xx_defconfig
+index 029d2da..9e0dd82 100644
+--- a/arch/powerpc/configs/mpc83xx_defconfig
++++ b/arch/powerpc/configs/mpc83xx_defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:25 2008
++# Linux kernel version: 2.6.25-rc9
++# Tue Apr 15 18:07:36 2008
+ #
+ # CONFIG_PPC64 is not set
+
+@@ -201,6 +201,7 @@ CONFIG_PREEMPT_NONE=y
+ # CONFIG_PREEMPT is not set
+ CONFIG_BINFMT_ELF=y
+ # CONFIG_BINFMT_MISC is not set
++CONFIG_FORCE_MAX_ZONEORDER=11
+ CONFIG_MATH_EMULATION=y
+ # CONFIG_IOMMU_HELPER is not set
+ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+@@ -353,7 +354,90 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ # CONFIG_FW_LOADER is not set
+ # CONFIG_SYS_HYPERVISOR is not set
+ # CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++CONFIG_MTD_OF_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++CONFIG_MTD_NAND=y
++CONFIG_MTD_NAND_VERIFY_WRITE=y
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ALAUDA is not set
++CONFIG_MTD_NAND_FSL_ELBC=y
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
+ CONFIG_OF_DEVICE=y
+ # CONFIG_PARPORT is not set
+ CONFIG_BLK_DEV=y
+@@ -362,6 +446,7 @@ CONFIG_BLK_DEV=y
+ CONFIG_BLK_DEV_LOOP=y
+ # CONFIG_BLK_DEV_CRYPTOLOOP is not set
+ # CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
+ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_COUNT=16
+ CONFIG_BLK_DEV_RAM_SIZE=32768
+@@ -469,6 +554,15 @@ CONFIG_NETDEV_10000=y
+ #
+ # CONFIG_WLAN_PRE80211 is not set
+ # CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
+ # CONFIG_WAN is not set
+ # CONFIG_PPP is not set
+ # CONFIG_SLIP is not set
+@@ -563,6 +657,7 @@ CONFIG_I2C_MPC=y
+ # CONFIG_I2C_SIMTEC is not set
+ # CONFIG_I2C_TAOS_EVM is not set
+ # CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
+
+ #
+ # Miscellaneous I2C Chip support
+@@ -648,6 +743,11 @@ CONFIG_WATCHDOG=y
+ CONFIG_83xx_WDT=y
+
+ #
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++
++#
+ # Sonics Silicon Backplane
+ #
+ CONFIG_SSB_POSSIBLE=y
+@@ -664,6 +764,7 @@ CONFIG_SSB_POSSIBLE=y
+ # CONFIG_VIDEO_DEV is not set
+ # CONFIG_DVB_CORE is not set
+ CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
+
+ #
+ # Graphics support
+@@ -686,6 +787,14 @@ CONFIG_HID_SUPPORT=y
+ CONFIG_HID=y
+ # CONFIG_HID_DEBUG is not set
+ # CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++# CONFIG_USB_HIDINPUT_POWERBOOK is not set
++# CONFIG_HID_FF is not set
++# CONFIG_USB_HIDDEV is not set
+ CONFIG_USB_SUPPORT=y
+ CONFIG_USB_ARCH_HAS_HCD=y
+ # CONFIG_USB_ARCH_HAS_OHCI is not set
+@@ -715,8 +824,55 @@ CONFIG_USB_EHCI_HCD_PPC_OF=y
+ # CONFIG_USB_R8A66597_HCD is not set
+
+ #
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
+ # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+ #
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++# CONFIG_USB_STORAGE is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
+ # CONFIG_USB_GADGET is not set
+ # CONFIG_MMC is not set
+ # CONFIG_MEMSTICK is not set
+@@ -792,6 +948,7 @@ CONFIG_TMPFS=y
+ # CONFIG_BEFS_FS is not set
+ # CONFIG_BFS_FS is not set
+ # CONFIG_EFS_FS is not set
++# CONFIG_JFFS2_FS is not set
+ # CONFIG_CRAMFS is not set
+ # CONFIG_VXFS_FS is not set
+ # CONFIG_MINIX_FS is not set
+@@ -862,6 +1019,7 @@ CONFIG_PLIST=y
+ CONFIG_HAS_IOMEM=y
+ CONFIG_HAS_IOPORT=y
+ CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
+
+ #
+ # Kernel hacking
+diff --git a/arch/powerpc/configs/mpc8540_ads_defconfig b/arch/powerpc/configs/mpc8540_ads_defconfig
+deleted file mode 100644
+index b998539..0000000
+--- a/arch/powerpc/configs/mpc8540_ads_defconfig
++++ /dev/null
+@@ -1,796 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:25 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_ALL is not set
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-# CONFIG_MODULES is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-CONFIG_MPC8540_ADS=y
+-# CONFIG_MPC8560_ADS is not set
+-# CONFIG_MPC85xx_CDS is not set
+-# CONFIG_MPC85xx_MDS is not set
+-# CONFIG_MPC85xx_DS is not set
+-# CONFIG_STX_GP3 is not set
+-# CONFIG_TQM8540 is not set
+-# CONFIG_TQM8541 is not set
+-# CONFIG_TQM8555 is not set
+-# CONFIG_TQM8560 is not set
+-# CONFIG_SBC8548 is not set
+-# CONFIG_SBC8560 is not set
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_CPM2 is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-CONFIG_BINFMT_MISC=y
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-# CONFIG_SECCOMP is not set
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_FSL_SOC=y
+-# CONFIG_PCI is not set
+-# CONFIG_PCI_DOMAINS is not set
+-# CONFIG_PCI_SYSCALL is not set
+-# CONFIG_ARCH_SUPPORTS_MSI is not set
+-# CONFIG_PCCARD is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-CONFIG_XFRM_USER=y
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_E1000E_ENABLED is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-CONFIG_NETDEV_10000=y
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=y
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-# CONFIG_USB_ARCH_HAS_HCD is not set
+-# CONFIG_USB_ARCH_HAS_OHCI is not set
+-# CONFIG_USB_ARCH_HAS_EHCI is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-# CONFIG_NFS_V3 is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-CONFIG_DEBUG_MUTEXES=y
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-# CONFIG_CRYPTO_MANAGER is not set
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-# CONFIG_CRYPTO_MD5 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-# CONFIG_CRYPTO_CBC is not set
+-# CONFIG_CRYPTO_PCBC is not set
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/mpc8544_ds_defconfig b/arch/powerpc/configs/mpc8544_ds_defconfig
+deleted file mode 100644
+index 418bcdb..0000000
+--- a/arch/powerpc/configs/mpc8544_ds_defconfig
++++ /dev/null
+@@ -1,1549 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc7
+-# Mon Mar 31 11:37:03 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-CONFIG_BSD_PROCESS_ACCT=y
+-# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+-# CONFIG_TASKSTATS is not set
+-CONFIG_AUDIT=y
+-# CONFIG_AUDITSYSCALL is not set
+-CONFIG_IKCONFIG=y
+-CONFIG_IKCONFIG_PROC=y
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-CONFIG_KALLSYMS_ALL=y
+-CONFIG_KALLSYMS_EXTRA_PASS=y
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-CONFIG_MODULE_FORCE_UNLOAD=y
+-CONFIG_MODVERSIONS=y
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-# CONFIG_DEFAULT_AS is not set
+-# CONFIG_DEFAULT_DEADLINE is not set
+-CONFIG_DEFAULT_CFQ=y
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="cfq"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-# CONFIG_MPC8540_ADS is not set
+-# CONFIG_MPC8560_ADS is not set
+-# CONFIG_MPC85xx_CDS is not set
+-# CONFIG_MPC85xx_MDS is not set
+-CONFIG_MPC85xx_DS=y
+-# CONFIG_STX_GP3 is not set
+-# CONFIG_TQM8540 is not set
+-# CONFIG_TQM8541 is not set
+-# CONFIG_TQM8555 is not set
+-# CONFIG_TQM8560 is not set
+-# CONFIG_SBC8548 is not set
+-# CONFIG_SBC8560 is not set
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-CONFIG_PPC_I8259=y
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_CPM2 is not set
+-CONFIG_FSL_ULI1575=y
+-
+-#
+-# Kernel options
+-#
+-CONFIG_HIGHMEM=y
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-CONFIG_BINFMT_MISC=m
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_FSL_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-CONFIG_XFRM_USER=y
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-CONFIG_NET_KEY=m
+-# CONFIG_NET_KEY_MIGRATE is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-CONFIG_IP_ADVANCED_ROUTER=y
+-CONFIG_ASK_IP_FIB_HASH=y
+-# CONFIG_IP_FIB_TRIE is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_MULTIPLE_TABLES=y
+-CONFIG_IP_ROUTE_MULTIPATH=y
+-CONFIG_IP_ROUTE_VERBOSE=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-CONFIG_IP_PNP_RARP=y
+-CONFIG_NET_IPIP=y
+-CONFIG_NET_IPGRE=y
+-CONFIG_NET_IPGRE_BROADCAST=y
+-CONFIG_IP_MROUTE=y
+-CONFIG_IP_PIMSM_V1=y
+-CONFIG_IP_PIMSM_V2=y
+-CONFIG_ARPD=y
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-CONFIG_INET_TUNNEL=y
+-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+-# CONFIG_INET_XFRM_MODE_BEET is not set
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-CONFIG_IPV6=y
+-# CONFIG_IPV6_PRIVACY is not set
+-# CONFIG_IPV6_ROUTER_PREF is not set
+-# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+-# CONFIG_INET6_AH is not set
+-# CONFIG_INET6_ESP is not set
+-# CONFIG_INET6_IPCOMP is not set
+-# CONFIG_IPV6_MIP6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET6_XFRM_MODE_TUNNEL=y
+-CONFIG_INET6_XFRM_MODE_BEET=y
+-# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+-CONFIG_IPV6_SIT=y
+-# CONFIG_IPV6_TUNNEL is not set
+-# CONFIG_IPV6_MULTIPLE_TABLES is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-CONFIG_IP_SCTP=m
+-# CONFIG_SCTP_DBG_MSG is not set
+-# CONFIG_SCTP_DBG_OBJCNT is not set
+-# CONFIG_SCTP_HMAC_NONE is not set
+-# CONFIG_SCTP_HMAC_SHA1 is not set
+-CONFIG_SCTP_HMAC_MD5=y
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-CONFIG_FIB_RULES=y
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-CONFIG_BLK_DEV_NBD=y
+-# CONFIG_BLK_DEV_SX8 is not set
+-# CONFIG_BLK_DEV_UB is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=131072
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-CONFIG_BLK_DEV_SD=y
+-CONFIG_CHR_DEV_ST=y
+-# CONFIG_CHR_DEV_OSST is not set
+-CONFIG_BLK_DEV_SR=y
+-# CONFIG_BLK_DEV_SR_VENDOR is not set
+-CONFIG_CHR_DEV_SG=y
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-CONFIG_SCSI_MULTI_LUN=y
+-# CONFIG_SCSI_CONSTANTS is not set
+-CONFIG_SCSI_LOGGING=y
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-# CONFIG_SCSI_SPI_ATTRS is not set
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-# CONFIG_SCSI_AIC7XXX is not set
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-# CONFIG_SCSI_AIC79XX is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_BUSLOGIC is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_EATA is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_GDTH is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_MVSAS is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_IPR is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-CONFIG_ATA=y
+-# CONFIG_ATA_NONSTANDARD is not set
+-CONFIG_SATA_AHCI=y
+-# CONFIG_SATA_SVW is not set
+-# CONFIG_ATA_PIIX is not set
+-# CONFIG_SATA_MV is not set
+-# CONFIG_SATA_NV is not set
+-# CONFIG_PDC_ADMA is not set
+-# CONFIG_SATA_QSTOR is not set
+-# CONFIG_SATA_PROMISE is not set
+-# CONFIG_SATA_SX4 is not set
+-# CONFIG_SATA_SIL is not set
+-# CONFIG_SATA_SIL24 is not set
+-# CONFIG_SATA_SIS is not set
+-# CONFIG_SATA_ULI is not set
+-# CONFIG_SATA_VIA is not set
+-# CONFIG_SATA_VITESSE is not set
+-# CONFIG_SATA_INIC162X is not set
+-# CONFIG_SATA_FSL is not set
+-CONFIG_PATA_ALI=y
+-# CONFIG_PATA_AMD is not set
+-# CONFIG_PATA_ARTOP is not set
+-# CONFIG_PATA_ATIIXP is not set
+-# CONFIG_PATA_CMD640_PCI is not set
+-# CONFIG_PATA_CMD64X is not set
+-# CONFIG_PATA_CS5520 is not set
+-# CONFIG_PATA_CS5530 is not set
+-# CONFIG_PATA_CYPRESS is not set
+-# CONFIG_PATA_EFAR is not set
+-# CONFIG_ATA_GENERIC is not set
+-# CONFIG_PATA_HPT366 is not set
+-# CONFIG_PATA_HPT37X is not set
+-# CONFIG_PATA_HPT3X2N is not set
+-# CONFIG_PATA_HPT3X3 is not set
+-# CONFIG_PATA_IT821X is not set
+-# CONFIG_PATA_IT8213 is not set
+-# CONFIG_PATA_JMICRON is not set
+-# CONFIG_PATA_TRIFLEX is not set
+-# CONFIG_PATA_MARVELL is not set
+-# CONFIG_PATA_MPIIX is not set
+-# CONFIG_PATA_OLDPIIX is not set
+-# CONFIG_PATA_NETCELL is not set
+-# CONFIG_PATA_NINJA32 is not set
+-# CONFIG_PATA_NS87410 is not set
+-# CONFIG_PATA_NS87415 is not set
+-# CONFIG_PATA_OPTI is not set
+-# CONFIG_PATA_OPTIDMA is not set
+-# CONFIG_PATA_PDC_OLD is not set
+-# CONFIG_PATA_RADISYS is not set
+-# CONFIG_PATA_RZ1000 is not set
+-# CONFIG_PATA_SC1200 is not set
+-# CONFIG_PATA_SERVERWORKS is not set
+-# CONFIG_PATA_PDC2027X is not set
+-# CONFIG_PATA_SIL680 is not set
+-# CONFIG_PATA_SIS is not set
+-# CONFIG_PATA_VIA is not set
+-# CONFIG_PATA_WINBOND is not set
+-# CONFIG_PATA_PLATFORM is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-CONFIG_DUMMY=y
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-CONFIG_VITESSE_PHY=y
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NET_FC is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-CONFIG_SERIO=y
+-CONFIG_SERIO_I8042=y
+-CONFIG_SERIO_SERPORT=y
+-# CONFIG_SERIO_PCIPS2 is not set
+-CONFIG_SERIO_LIBPS2=y
+-# CONFIG_SERIO_RAW is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-CONFIG_VT=y
+-CONFIG_VT_CONSOLE=y
+-CONFIG_HW_CONSOLE=y
+-# CONFIG_VT_HW_CONSOLE_BINDING is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=2
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+-CONFIG_SERIAL_8250_EXTENDED=y
+-CONFIG_SERIAL_8250_MANY_PORTS=y
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-CONFIG_SERIAL_8250_DETECT_IRQ=y
+-CONFIG_SERIAL_8250_RSA=y
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-CONFIG_NVRAM=y
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-# CONFIG_I2C_CHARDEV is not set
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_TINY_USB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-CONFIG_SENSORS_EEPROM=y
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-CONFIG_DVB_CORE=m
+-# CONFIG_DVB_CORE_ATTACH is not set
+-CONFIG_DVB_CAPTURE_DRIVERS=y
+-
+-#
+-# Supported SAA7146 based PCI Adapters
+-#
+-# CONFIG_TTPCI_EEPROM is not set
+-# CONFIG_DVB_BUDGET_CORE is not set
+-
+-#
+-# Supported USB Adapters
+-#
+-# CONFIG_DVB_USB is not set
+-# CONFIG_DVB_TTUSB_BUDGET is not set
+-# CONFIG_DVB_TTUSB_DEC is not set
+-# CONFIG_DVB_CINERGYT2 is not set
+-
+-#
+-# Supported FlexCopII (B2C2) Adapters
+-#
+-# CONFIG_DVB_B2C2_FLEXCOP is not set
+-
+-#
+-# Supported BT878 Adapters
+-#
+-
+-#
+-# Supported Pluto2 Adapters
+-#
+-# CONFIG_DVB_PLUTO2 is not set
+-
+-#
+-# Supported DVB Frontends
+-#
+-
+-#
+-# Customise DVB Frontends
+-#
+-# CONFIG_DVB_FE_CUSTOMISE is not set
+-
+-#
+-# DVB-S (satellite) frontends
+-#
+-# CONFIG_DVB_STV0299 is not set
+-# CONFIG_DVB_CX24110 is not set
+-# CONFIG_DVB_CX24123 is not set
+-# CONFIG_DVB_TDA8083 is not set
+-# CONFIG_DVB_MT312 is not set
+-# CONFIG_DVB_VES1X93 is not set
+-# CONFIG_DVB_S5H1420 is not set
+-# CONFIG_DVB_TDA10086 is not set
+-
+-#
+-# DVB-T (terrestrial) frontends
+-#
+-# CONFIG_DVB_SP8870 is not set
+-# CONFIG_DVB_SP887X is not set
+-# CONFIG_DVB_CX22700 is not set
+-# CONFIG_DVB_CX22702 is not set
+-# CONFIG_DVB_L64781 is not set
+-# CONFIG_DVB_TDA1004X is not set
+-# CONFIG_DVB_NXT6000 is not set
+-# CONFIG_DVB_MT352 is not set
+-# CONFIG_DVB_ZL10353 is not set
+-# CONFIG_DVB_DIB3000MB is not set
+-# CONFIG_DVB_DIB3000MC is not set
+-# CONFIG_DVB_DIB7000M is not set
+-# CONFIG_DVB_DIB7000P is not set
+-
+-#
+-# DVB-C (cable) frontends
+-#
+-# CONFIG_DVB_VES1820 is not set
+-# CONFIG_DVB_TDA10021 is not set
+-# CONFIG_DVB_TDA10023 is not set
+-# CONFIG_DVB_STV0297 is not set
+-
+-#
+-# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+-#
+-# CONFIG_DVB_NXT200X is not set
+-# CONFIG_DVB_OR51211 is not set
+-# CONFIG_DVB_OR51132 is not set
+-# CONFIG_DVB_BCM3510 is not set
+-# CONFIG_DVB_LGDT330X is not set
+-# CONFIG_DVB_S5H1409 is not set
+-
+-#
+-# Tuners/PLL support
+-#
+-# CONFIG_DVB_PLL is not set
+-# CONFIG_DVB_TDA826X is not set
+-# CONFIG_DVB_TDA827X is not set
+-# CONFIG_DVB_TDA18271 is not set
+-# CONFIG_DVB_TUNER_QT1010 is not set
+-# CONFIG_DVB_TUNER_MT2060 is not set
+-# CONFIG_DVB_TUNER_MT2266 is not set
+-# CONFIG_DVB_TUNER_MT2131 is not set
+-# CONFIG_DVB_TUNER_DIB0070 is not set
+-# CONFIG_DVB_TUNER_XC5000 is not set
+-
+-#
+-# Miscellaneous devices
+-#
+-# CONFIG_DVB_LNBP21 is not set
+-# CONFIG_DVB_ISL6421 is not set
+-# CONFIG_DVB_TUA6100 is not set
+-CONFIG_DAB=y
+-# CONFIG_USB_DABUSB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=y
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Console display driver support
+-#
+-CONFIG_VGA_CONSOLE=y
+-# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+-CONFIG_DUMMY_CONSOLE=y
+-
+-#
+-# Sound
+-#
+-CONFIG_SOUND=y
+-
+-#
+-# Advanced Linux Sound Architecture
+-#
+-CONFIG_SND=y
+-CONFIG_SND_TIMER=y
+-CONFIG_SND_PCM=y
+-# CONFIG_SND_SEQUENCER is not set
+-# CONFIG_SND_MIXER_OSS is not set
+-# CONFIG_SND_PCM_OSS is not set
+-# CONFIG_SND_DYNAMIC_MINORS is not set
+-CONFIG_SND_SUPPORT_OLD_API=y
+-CONFIG_SND_VERBOSE_PROCFS=y
+-# CONFIG_SND_VERBOSE_PRINTK is not set
+-# CONFIG_SND_DEBUG is not set
+-
+-#
+-# Generic devices
+-#
+-CONFIG_SND_AC97_CODEC=y
+-# CONFIG_SND_DUMMY is not set
+-# CONFIG_SND_MTPAV is not set
+-# CONFIG_SND_SERIAL_U16550 is not set
+-# CONFIG_SND_MPU401 is not set
+-
+-#
+-# PCI devices
+-#
+-# CONFIG_SND_AD1889 is not set
+-# CONFIG_SND_ALS300 is not set
+-# CONFIG_SND_ALS4000 is not set
+-# CONFIG_SND_ALI5451 is not set
+-# CONFIG_SND_ATIIXP is not set
+-# CONFIG_SND_ATIIXP_MODEM is not set
+-# CONFIG_SND_AU8810 is not set
+-# CONFIG_SND_AU8820 is not set
+-# CONFIG_SND_AU8830 is not set
+-# CONFIG_SND_AZT3328 is not set
+-# CONFIG_SND_BT87X is not set
+-# CONFIG_SND_CA0106 is not set
+-# CONFIG_SND_CMIPCI is not set
+-# CONFIG_SND_OXYGEN is not set
+-# CONFIG_SND_CS4281 is not set
+-# CONFIG_SND_CS46XX is not set
+-# CONFIG_SND_CS5530 is not set
+-# CONFIG_SND_DARLA20 is not set
+-# CONFIG_SND_GINA20 is not set
+-# CONFIG_SND_LAYLA20 is not set
+-# CONFIG_SND_DARLA24 is not set
+-# CONFIG_SND_GINA24 is not set
+-# CONFIG_SND_LAYLA24 is not set
+-# CONFIG_SND_MONA is not set
+-# CONFIG_SND_MIA is not set
+-# CONFIG_SND_ECHO3G is not set
+-# CONFIG_SND_INDIGO is not set
+-# CONFIG_SND_INDIGOIO is not set
+-# CONFIG_SND_INDIGODJ is not set
+-# CONFIG_SND_EMU10K1 is not set
+-# CONFIG_SND_EMU10K1X is not set
+-# CONFIG_SND_ENS1370 is not set
+-# CONFIG_SND_ENS1371 is not set
+-# CONFIG_SND_ES1938 is not set
+-# CONFIG_SND_ES1968 is not set
+-# CONFIG_SND_FM801 is not set
+-# CONFIG_SND_HDA_INTEL is not set
+-# CONFIG_SND_HDSP is not set
+-# CONFIG_SND_HDSPM is not set
+-# CONFIG_SND_HIFIER is not set
+-# CONFIG_SND_ICE1712 is not set
+-# CONFIG_SND_ICE1724 is not set
+-CONFIG_SND_INTEL8X0=y
+-# CONFIG_SND_INTEL8X0M is not set
+-# CONFIG_SND_KORG1212 is not set
+-# CONFIG_SND_MAESTRO3 is not set
+-# CONFIG_SND_MIXART is not set
+-# CONFIG_SND_NM256 is not set
+-# CONFIG_SND_PCXHR is not set
+-# CONFIG_SND_RIPTIDE is not set
+-# CONFIG_SND_RME32 is not set
+-# CONFIG_SND_RME96 is not set
+-# CONFIG_SND_RME9652 is not set
+-# CONFIG_SND_SONICVIBES is not set
+-# CONFIG_SND_TRIDENT is not set
+-# CONFIG_SND_VIA82XX is not set
+-# CONFIG_SND_VIA82XX_MODEM is not set
+-# CONFIG_SND_VIRTUOSO is not set
+-# CONFIG_SND_VX222 is not set
+-# CONFIG_SND_YMFPCI is not set
+-# CONFIG_SND_AC97_POWER_SAVE is not set
+-
+-#
+-# ALSA PowerMac devices
+-#
+-
+-#
+-# ALSA PowerPC devices
+-#
+-
+-#
+-# USB devices
+-#
+-# CONFIG_SND_USB_AUDIO is not set
+-# CONFIG_SND_USB_USX2Y is not set
+-# CONFIG_SND_USB_CAIAQ is not set
+-
+-#
+-# System on Chip audio support
+-#
+-# CONFIG_SND_SOC is not set
+-
+-#
+-# SoC Audio support for SuperH
+-#
+-
+-#
+-# ALSA SoC audio for Freescale SOCs
+-#
+-
+-#
+-# Open Sound System
+-#
+-# CONFIG_SOUND_PRIME is not set
+-CONFIG_AC97_BUS=y
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-
+-#
+-# USB Input Devices
+-#
+-CONFIG_USB_HID=y
+-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+-# CONFIG_HID_FF is not set
+-# CONFIG_USB_HIDDEV is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-CONFIG_USB=y
+-# CONFIG_USB_DEBUG is not set
+-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+-
+-#
+-# Miscellaneous USB options
+-#
+-CONFIG_USB_DEVICEFS=y
+-CONFIG_USB_DEVICE_CLASS=y
+-# CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_OTG is not set
+-
+-#
+-# USB Host Controller Drivers
+-#
+-CONFIG_USB_EHCI_HCD=y
+-# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+-# CONFIG_USB_EHCI_FSL is not set
+-CONFIG_USB_EHCI_HCD_PPC_OF=y
+-# CONFIG_USB_ISP116X_HCD is not set
+-CONFIG_USB_OHCI_HCD=y
+-CONFIG_USB_OHCI_HCD_PPC_OF=y
+-CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+-CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
+-CONFIG_USB_OHCI_HCD_PCI=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
+-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+-# CONFIG_USB_UHCI_HCD is not set
+-# CONFIG_USB_SL811_HCD is not set
+-# CONFIG_USB_R8A66597_HCD is not set
+-
+-#
+-# USB Device Class drivers
+-#
+-# CONFIG_USB_ACM is not set
+-# CONFIG_USB_PRINTER is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# may also be needed; see USB_STORAGE Help for more information
+-#
+-CONFIG_USB_STORAGE=y
+-# CONFIG_USB_STORAGE_DEBUG is not set
+-# CONFIG_USB_STORAGE_DATAFAB is not set
+-# CONFIG_USB_STORAGE_FREECOM is not set
+-# CONFIG_USB_STORAGE_ISD200 is not set
+-# CONFIG_USB_STORAGE_DPCM is not set
+-# CONFIG_USB_STORAGE_USBAT is not set
+-# CONFIG_USB_STORAGE_SDDR09 is not set
+-# CONFIG_USB_STORAGE_SDDR55 is not set
+-# CONFIG_USB_STORAGE_JUMPSHOT is not set
+-# CONFIG_USB_STORAGE_ALAUDA is not set
+-# CONFIG_USB_STORAGE_KARMA is not set
+-# CONFIG_USB_LIBUSUAL is not set
+-
+-#
+-# USB Imaging devices
+-#
+-# CONFIG_USB_MDC800 is not set
+-# CONFIG_USB_MICROTEK is not set
+-CONFIG_USB_MON=y
+-
+-#
+-# USB port drivers
+-#
+-# CONFIG_USB_SERIAL is not set
+-
+-#
+-# USB Miscellaneous drivers
+-#
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+-# CONFIG_USB_ADUTUX is not set
+-# CONFIG_USB_AUERSWALD is not set
+-# CONFIG_USB_RIO500 is not set
+-# CONFIG_USB_LEGOTOWER is not set
+-# CONFIG_USB_LCD is not set
+-# CONFIG_USB_BERRY_CHARGE is not set
+-# CONFIG_USB_LED is not set
+-# CONFIG_USB_CYPRESS_CY7C63 is not set
+-# CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGET is not set
+-# CONFIG_USB_IDMOUSE is not set
+-# CONFIG_USB_FTDI_ELAN is not set
+-# CONFIG_USB_APPLEDISPLAY is not set
+-# CONFIG_USB_SISUSBVGA is not set
+-# CONFIG_USB_LD is not set
+-# CONFIG_USB_TRANCEVIBRATOR is not set
+-# CONFIG_USB_IOWARRIOR is not set
+-# CONFIG_USB_TEST is not set
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-CONFIG_RTC_LIB=y
+-CONFIG_RTC_CLASS=y
+-CONFIG_RTC_HCTOSYS=y
+-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+-# CONFIG_RTC_DEBUG is not set
+-
+-#
+-# RTC interfaces
+-#
+-CONFIG_RTC_INTF_SYSFS=y
+-CONFIG_RTC_INTF_PROC=y
+-CONFIG_RTC_INTF_DEV=y
+-# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+-# CONFIG_RTC_DRV_TEST is not set
+-
+-#
+-# I2C RTC drivers
+-#
+-# CONFIG_RTC_DRV_DS1307 is not set
+-# CONFIG_RTC_DRV_DS1374 is not set
+-# CONFIG_RTC_DRV_DS1672 is not set
+-# CONFIG_RTC_DRV_MAX6900 is not set
+-# CONFIG_RTC_DRV_RS5C372 is not set
+-# CONFIG_RTC_DRV_ISL1208 is not set
+-# CONFIG_RTC_DRV_X1205 is not set
+-# CONFIG_RTC_DRV_PCF8563 is not set
+-# CONFIG_RTC_DRV_PCF8583 is not set
+-# CONFIG_RTC_DRV_M41T80 is not set
+-# CONFIG_RTC_DRV_S35390A is not set
+-
+-#
+-# SPI RTC drivers
+-#
+-
+-#
+-# Platform RTC drivers
+-#
+-CONFIG_RTC_DRV_CMOS=y
+-# CONFIG_RTC_DRV_DS1511 is not set
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
+-# CONFIG_RTC_DRV_STK17TA8 is not set
+-# CONFIG_RTC_DRV_M48T86 is not set
+-# CONFIG_RTC_DRV_M48T59 is not set
+-# CONFIG_RTC_DRV_V3020 is not set
+-
+-#
+-# on-CPU RTC drivers
+-#
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-CONFIG_ISO9660_FS=m
+-CONFIG_JOLIET=y
+-CONFIG_ZISOFS=y
+-CONFIG_UDF_FS=m
+-CONFIG_UDF_NLS=y
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-CONFIG_FAT_FS=y
+-CONFIG_MSDOS_FS=m
+-CONFIG_VFAT_FS=y
+-CONFIG_FAT_DEFAULT_CODEPAGE=437
+-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+-CONFIG_NTFS_FS=y
+-# CONFIG_NTFS_DEBUG is not set
+-# CONFIG_NTFS_RW is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-CONFIG_ADFS_FS=m
+-# CONFIG_ADFS_FS_RW is not set
+-CONFIG_AFFS_FS=m
+-CONFIG_HFS_FS=m
+-CONFIG_HFSPLUS_FS=m
+-CONFIG_BEFS_FS=m
+-# CONFIG_BEFS_DEBUG is not set
+-CONFIG_BFS_FS=m
+-CONFIG_EFS_FS=m
+-CONFIG_CRAMFS=y
+-CONFIG_VXFS_FS=m
+-# CONFIG_MINIX_FS is not set
+-CONFIG_HPFS_FS=m
+-CONFIG_QNX4FS_FS=m
+-# CONFIG_ROMFS_FS is not set
+-CONFIG_SYSV_FS=m
+-CONFIG_UFS_FS=m
+-# CONFIG_UFS_FS_WRITE is not set
+-# CONFIG_UFS_DEBUG is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-CONFIG_NFSD=y
+-# CONFIG_NFSD_V3 is not set
+-CONFIG_NFSD_TCP=y
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_EXPORTFS=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-CONFIG_MAC_PARTITION=y
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_BSD_DISKLABEL is not set
+-# CONFIG_MINIX_SUBPARTITION is not set
+-# CONFIG_SOLARIS_X86_PARTITION is not set
+-# CONFIG_UNIXWARE_DISKLABEL is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-CONFIG_NLS=y
+-CONFIG_NLS_DEFAULT="iso8859-1"
+-# CONFIG_NLS_CODEPAGE_437 is not set
+-# CONFIG_NLS_CODEPAGE_737 is not set
+-# CONFIG_NLS_CODEPAGE_775 is not set
+-# CONFIG_NLS_CODEPAGE_850 is not set
+-# CONFIG_NLS_CODEPAGE_852 is not set
+-# CONFIG_NLS_CODEPAGE_855 is not set
+-# CONFIG_NLS_CODEPAGE_857 is not set
+-# CONFIG_NLS_CODEPAGE_860 is not set
+-# CONFIG_NLS_CODEPAGE_861 is not set
+-# CONFIG_NLS_CODEPAGE_862 is not set
+-# CONFIG_NLS_CODEPAGE_863 is not set
+-# CONFIG_NLS_CODEPAGE_864 is not set
+-# CONFIG_NLS_CODEPAGE_865 is not set
+-# CONFIG_NLS_CODEPAGE_866 is not set
+-# CONFIG_NLS_CODEPAGE_869 is not set
+-# CONFIG_NLS_CODEPAGE_936 is not set
+-# CONFIG_NLS_CODEPAGE_950 is not set
+-# CONFIG_NLS_CODEPAGE_932 is not set
+-# CONFIG_NLS_CODEPAGE_949 is not set
+-# CONFIG_NLS_CODEPAGE_874 is not set
+-# CONFIG_NLS_ISO8859_8 is not set
+-# CONFIG_NLS_CODEPAGE_1250 is not set
+-# CONFIG_NLS_CODEPAGE_1251 is not set
+-# CONFIG_NLS_ASCII is not set
+-# CONFIG_NLS_ISO8859_1 is not set
+-# CONFIG_NLS_ISO8859_2 is not set
+-# CONFIG_NLS_ISO8859_3 is not set
+-# CONFIG_NLS_ISO8859_4 is not set
+-# CONFIG_NLS_ISO8859_5 is not set
+-# CONFIG_NLS_ISO8859_6 is not set
+-# CONFIG_NLS_ISO8859_7 is not set
+-# CONFIG_NLS_ISO8859_9 is not set
+-# CONFIG_NLS_ISO8859_13 is not set
+-# CONFIG_NLS_ISO8859_14 is not set
+-# CONFIG_NLS_ISO8859_15 is not set
+-# CONFIG_NLS_KOI8_R is not set
+-# CONFIG_NLS_KOI8_U is not set
+-CONFIG_NLS_UTF8=m
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-CONFIG_LIBCRC32C=m
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_HIGHMEM is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-CONFIG_DEBUG_INFO=y
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_HASH=y
+-CONFIG_CRYPTO_MANAGER=y
+-CONFIG_CRYPTO_HMAC=y
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-CONFIG_CRYPTO_SHA1=m
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/mpc8560_ads_defconfig b/arch/powerpc/configs/mpc8560_ads_defconfig
+deleted file mode 100644
+index 851ac91..0000000
+--- a/arch/powerpc/configs/mpc8560_ads_defconfig
++++ /dev/null
+@@ -1,885 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:27 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_ALL is not set
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-# CONFIG_MODULES is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-# CONFIG_MPC8540_ADS is not set
+-CONFIG_MPC8560_ADS=y
+-# CONFIG_MPC85xx_CDS is not set
+-# CONFIG_MPC85xx_MDS is not set
+-# CONFIG_MPC85xx_DS is not set
+-# CONFIG_STX_GP3 is not set
+-# CONFIG_TQM8540 is not set
+-# CONFIG_TQM8541 is not set
+-# CONFIG_TQM8555 is not set
+-# CONFIG_TQM8560 is not set
+-# CONFIG_SBC8548 is not set
+-# CONFIG_SBC8560 is not set
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-CONFIG_CPM2=y
+-CONFIG_PPC_CPM_NEW_BINDING=y
+-# CONFIG_FSL_ULI1575 is not set
+-CONFIG_CPM=y
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-CONFIG_BINFMT_MISC=y
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-# CONFIG_PROC_DEVICETREE is not set
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-# CONFIG_SECCOMP is not set
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_FSL_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-CONFIG_PCI_DEBUG=y
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-CONFIG_MARVELL_PHY=y
+-CONFIG_DAVICOM_PHY=y
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_FS_ENET=y
+-# CONFIG_FS_ENET_HAS_SCC is not set
+-CONFIG_FS_ENET_HAS_FCC=y
+-# CONFIG_FS_ENET_MDIO_FCC is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-CONFIG_E1000=y
+-CONFIG_E1000_NAPI=y
+-# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-# CONFIG_SERIAL_8250 is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-CONFIG_SERIAL_CPM=y
+-CONFIG_SERIAL_CPM_CONSOLE=y
+-CONFIG_SERIAL_CPM_SCC1=y
+-CONFIG_SERIAL_CPM_SCC2=y
+-# CONFIG_SERIAL_CPM_SCC3 is not set
+-# CONFIG_SERIAL_CPM_SCC4 is not set
+-# CONFIG_SERIAL_CPM_SMC1 is not set
+-# CONFIG_SERIAL_CPM_SMC2 is not set
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=y
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-# CONFIG_NFS_V3 is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-CONFIG_DEBUG_MUTEXES=y
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_KGDB_CONSOLE is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-# CONFIG_CRYPTO_MANAGER is not set
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-# CONFIG_CRYPTO_MD5 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-# CONFIG_CRYPTO_CBC is not set
+-# CONFIG_CRYPTO_PCBC is not set
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+-CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/mpc8568mds_defconfig b/arch/powerpc/configs/mpc8568mds_defconfig
+deleted file mode 100644
+index 2b866b3..0000000
+--- a/arch/powerpc/configs/mpc8568mds_defconfig
++++ /dev/null
+@@ -1,1117 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc7
+-# Mon Mar 31 11:37:05 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-# CONFIG_MPC8540_ADS is not set
+-# CONFIG_MPC8560_ADS is not set
+-# CONFIG_MPC85xx_CDS is not set
+-CONFIG_MPC85xx_MDS=y
+-# CONFIG_MPC85xx_DS is not set
+-# CONFIG_STX_GP3 is not set
+-# CONFIG_TQM8540 is not set
+-# CONFIG_TQM8541 is not set
+-# CONFIG_TQM8555 is not set
+-# CONFIG_TQM8560 is not set
+-# CONFIG_SBC8548 is not set
+-# CONFIG_SBC8560 is not set
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-CONFIG_QUICC_ENGINE=y
+-# CONFIG_CPM2 is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_FSL_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-# CONFIG_BLK_DEV_SD is not set
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-# CONFIG_BLK_DEV_SR is not set
+-# CONFIG_CHR_DEV_SG is not set
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-# CONFIG_SCSI_SPI_ATTRS is not set
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-# CONFIG_SCSI_AIC7XXX is not set
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-# CONFIG_SCSI_AIC79XX is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_BUSLOGIC is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_EATA is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_GDTH is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_MVSAS is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-CONFIG_MARVELL_PHY=y
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_UCC_GETH is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NET_FC is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-# CONFIG_SERIAL_QE is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-# CONFIG_BOOKE_WDT is not set
+-
+-#
+-# PCI-based Watchdog Cards
+-#
+-# CONFIG_PCIPCWATCHDOG is not set
+-# CONFIG_WDTPCI is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-CONFIG_RTC_LIB=y
+-CONFIG_RTC_CLASS=y
+-CONFIG_RTC_HCTOSYS=y
+-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+-# CONFIG_RTC_DEBUG is not set
+-
+-#
+-# RTC interfaces
+-#
+-CONFIG_RTC_INTF_SYSFS=y
+-CONFIG_RTC_INTF_PROC=y
+-CONFIG_RTC_INTF_DEV=y
+-# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+-# CONFIG_RTC_DRV_TEST is not set
+-
+-#
+-# I2C RTC drivers
+-#
+-# CONFIG_RTC_DRV_DS1307 is not set
+-CONFIG_RTC_DRV_DS1374=y
+-# CONFIG_RTC_DRV_DS1672 is not set
+-# CONFIG_RTC_DRV_MAX6900 is not set
+-# CONFIG_RTC_DRV_RS5C372 is not set
+-# CONFIG_RTC_DRV_ISL1208 is not set
+-# CONFIG_RTC_DRV_X1205 is not set
+-# CONFIG_RTC_DRV_PCF8563 is not set
+-# CONFIG_RTC_DRV_PCF8583 is not set
+-# CONFIG_RTC_DRV_M41T80 is not set
+-# CONFIG_RTC_DRV_S35390A is not set
+-
+-#
+-# SPI RTC drivers
+-#
+-
+-#
+-# Platform RTC drivers
+-#
+-# CONFIG_RTC_DRV_CMOS is not set
+-# CONFIG_RTC_DRV_DS1511 is not set
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
+-# CONFIG_RTC_DRV_STK17TA8 is not set
+-# CONFIG_RTC_DRV_M48T86 is not set
+-# CONFIG_RTC_DRV_M48T59 is not set
+-# CONFIG_RTC_DRV_V3020 is not set
+-
+-#
+-# on-CPU RTC drivers
+-#
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-CONFIG_DEBUGGER=y
+-# CONFIG_XMON is not set
+-# CONFIG_BDI_SWITCH is not set
+-CONFIG_PPC_EARLY_DEBUG=y
+-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
+-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
+-# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
+-# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
+-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
+-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+-# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
+-# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
+-# CONFIG_PPC_EARLY_DEBUG_44x is not set
+-# CONFIG_PPC_EARLY_DEBUG_40x is not set
+-# CONFIG_PPC_EARLY_DEBUG_CPM is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=m
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+-CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/mpc8572_ds_defconfig b/arch/powerpc/configs/mpc8572_ds_defconfig
+deleted file mode 100644
+index 53aa6f3..0000000
+--- a/arch/powerpc/configs/mpc8572_ds_defconfig
++++ /dev/null
+@@ -1,1549 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc7
+-# Mon Mar 31 11:37:06 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-CONFIG_BSD_PROCESS_ACCT=y
+-# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+-# CONFIG_TASKSTATS is not set
+-CONFIG_AUDIT=y
+-# CONFIG_AUDITSYSCALL is not set
+-CONFIG_IKCONFIG=y
+-CONFIG_IKCONFIG_PROC=y
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-CONFIG_KALLSYMS_ALL=y
+-CONFIG_KALLSYMS_EXTRA_PASS=y
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-CONFIG_MODULE_FORCE_UNLOAD=y
+-CONFIG_MODVERSIONS=y
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-# CONFIG_DEFAULT_AS is not set
+-# CONFIG_DEFAULT_DEADLINE is not set
+-CONFIG_DEFAULT_CFQ=y
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="cfq"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-# CONFIG_MPC8540_ADS is not set
+-# CONFIG_MPC8560_ADS is not set
+-# CONFIG_MPC85xx_CDS is not set
+-# CONFIG_MPC85xx_MDS is not set
+-CONFIG_MPC85xx_DS=y
+-# CONFIG_STX_GP3 is not set
+-# CONFIG_TQM8540 is not set
+-# CONFIG_TQM8541 is not set
+-# CONFIG_TQM8555 is not set
+-# CONFIG_TQM8560 is not set
+-# CONFIG_SBC8548 is not set
+-# CONFIG_SBC8560 is not set
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-CONFIG_PPC_I8259=y
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_CPM2 is not set
+-CONFIG_FSL_ULI1575=y
+-
+-#
+-# Kernel options
+-#
+-CONFIG_HIGHMEM=y
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-CONFIG_BINFMT_MISC=m
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_FSL_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-CONFIG_XFRM_USER=y
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-CONFIG_NET_KEY=m
+-# CONFIG_NET_KEY_MIGRATE is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-CONFIG_IP_ADVANCED_ROUTER=y
+-CONFIG_ASK_IP_FIB_HASH=y
+-# CONFIG_IP_FIB_TRIE is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_MULTIPLE_TABLES=y
+-CONFIG_IP_ROUTE_MULTIPATH=y
+-CONFIG_IP_ROUTE_VERBOSE=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-CONFIG_IP_PNP_RARP=y
+-CONFIG_NET_IPIP=y
+-CONFIG_NET_IPGRE=y
+-CONFIG_NET_IPGRE_BROADCAST=y
+-CONFIG_IP_MROUTE=y
+-CONFIG_IP_PIMSM_V1=y
+-CONFIG_IP_PIMSM_V2=y
+-CONFIG_ARPD=y
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-CONFIG_INET_TUNNEL=y
+-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+-# CONFIG_INET_XFRM_MODE_BEET is not set
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-CONFIG_IPV6=y
+-# CONFIG_IPV6_PRIVACY is not set
+-# CONFIG_IPV6_ROUTER_PREF is not set
+-# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+-# CONFIG_INET6_AH is not set
+-# CONFIG_INET6_ESP is not set
+-# CONFIG_INET6_IPCOMP is not set
+-# CONFIG_IPV6_MIP6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET6_XFRM_MODE_TUNNEL=y
+-CONFIG_INET6_XFRM_MODE_BEET=y
+-# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+-CONFIG_IPV6_SIT=y
+-# CONFIG_IPV6_TUNNEL is not set
+-# CONFIG_IPV6_MULTIPLE_TABLES is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-CONFIG_IP_SCTP=m
+-# CONFIG_SCTP_DBG_MSG is not set
+-# CONFIG_SCTP_DBG_OBJCNT is not set
+-# CONFIG_SCTP_HMAC_NONE is not set
+-# CONFIG_SCTP_HMAC_SHA1 is not set
+-CONFIG_SCTP_HMAC_MD5=y
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-CONFIG_FIB_RULES=y
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-CONFIG_BLK_DEV_NBD=y
+-# CONFIG_BLK_DEV_SX8 is not set
+-# CONFIG_BLK_DEV_UB is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=131072
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-CONFIG_BLK_DEV_SD=y
+-CONFIG_CHR_DEV_ST=y
+-# CONFIG_CHR_DEV_OSST is not set
+-CONFIG_BLK_DEV_SR=y
+-# CONFIG_BLK_DEV_SR_VENDOR is not set
+-CONFIG_CHR_DEV_SG=y
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-CONFIG_SCSI_MULTI_LUN=y
+-# CONFIG_SCSI_CONSTANTS is not set
+-CONFIG_SCSI_LOGGING=y
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-# CONFIG_SCSI_SPI_ATTRS is not set
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-# CONFIG_SCSI_AIC7XXX is not set
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-# CONFIG_SCSI_AIC79XX is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_BUSLOGIC is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_EATA is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_GDTH is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_MVSAS is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_IPR is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-CONFIG_ATA=y
+-# CONFIG_ATA_NONSTANDARD is not set
+-CONFIG_SATA_AHCI=y
+-# CONFIG_SATA_SVW is not set
+-# CONFIG_ATA_PIIX is not set
+-# CONFIG_SATA_MV is not set
+-# CONFIG_SATA_NV is not set
+-# CONFIG_PDC_ADMA is not set
+-# CONFIG_SATA_QSTOR is not set
+-# CONFIG_SATA_PROMISE is not set
+-# CONFIG_SATA_SX4 is not set
+-# CONFIG_SATA_SIL is not set
+-# CONFIG_SATA_SIL24 is not set
+-# CONFIG_SATA_SIS is not set
+-# CONFIG_SATA_ULI is not set
+-# CONFIG_SATA_VIA is not set
+-# CONFIG_SATA_VITESSE is not set
+-# CONFIG_SATA_INIC162X is not set
+-# CONFIG_SATA_FSL is not set
+-CONFIG_PATA_ALI=y
+-# CONFIG_PATA_AMD is not set
+-# CONFIG_PATA_ARTOP is not set
+-# CONFIG_PATA_ATIIXP is not set
+-# CONFIG_PATA_CMD640_PCI is not set
+-# CONFIG_PATA_CMD64X is not set
+-# CONFIG_PATA_CS5520 is not set
+-# CONFIG_PATA_CS5530 is not set
+-# CONFIG_PATA_CYPRESS is not set
+-# CONFIG_PATA_EFAR is not set
+-# CONFIG_ATA_GENERIC is not set
+-# CONFIG_PATA_HPT366 is not set
+-# CONFIG_PATA_HPT37X is not set
+-# CONFIG_PATA_HPT3X2N is not set
+-# CONFIG_PATA_HPT3X3 is not set
+-# CONFIG_PATA_IT821X is not set
+-# CONFIG_PATA_IT8213 is not set
+-# CONFIG_PATA_JMICRON is not set
+-# CONFIG_PATA_TRIFLEX is not set
+-# CONFIG_PATA_MARVELL is not set
+-# CONFIG_PATA_MPIIX is not set
+-# CONFIG_PATA_OLDPIIX is not set
+-# CONFIG_PATA_NETCELL is not set
+-# CONFIG_PATA_NINJA32 is not set
+-# CONFIG_PATA_NS87410 is not set
+-# CONFIG_PATA_NS87415 is not set
+-# CONFIG_PATA_OPTI is not set
+-# CONFIG_PATA_OPTIDMA is not set
+-# CONFIG_PATA_PDC_OLD is not set
+-# CONFIG_PATA_RADISYS is not set
+-# CONFIG_PATA_RZ1000 is not set
+-# CONFIG_PATA_SC1200 is not set
+-# CONFIG_PATA_SERVERWORKS is not set
+-# CONFIG_PATA_PDC2027X is not set
+-# CONFIG_PATA_SIL680 is not set
+-# CONFIG_PATA_SIS is not set
+-# CONFIG_PATA_VIA is not set
+-# CONFIG_PATA_WINBOND is not set
+-# CONFIG_PATA_PLATFORM is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-CONFIG_DUMMY=y
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-CONFIG_VITESSE_PHY=y
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NET_FC is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-CONFIG_SERIO=y
+-CONFIG_SERIO_I8042=y
+-CONFIG_SERIO_SERPORT=y
+-# CONFIG_SERIO_PCIPS2 is not set
+-CONFIG_SERIO_LIBPS2=y
+-# CONFIG_SERIO_RAW is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-CONFIG_VT=y
+-CONFIG_VT_CONSOLE=y
+-CONFIG_HW_CONSOLE=y
+-# CONFIG_VT_HW_CONSOLE_BINDING is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=2
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+-CONFIG_SERIAL_8250_EXTENDED=y
+-CONFIG_SERIAL_8250_MANY_PORTS=y
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-CONFIG_SERIAL_8250_DETECT_IRQ=y
+-CONFIG_SERIAL_8250_RSA=y
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-CONFIG_NVRAM=y
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-# CONFIG_I2C_CHARDEV is not set
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_TINY_USB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-CONFIG_SENSORS_EEPROM=y
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-CONFIG_DVB_CORE=m
+-# CONFIG_DVB_CORE_ATTACH is not set
+-CONFIG_DVB_CAPTURE_DRIVERS=y
+-
+-#
+-# Supported SAA7146 based PCI Adapters
+-#
+-# CONFIG_TTPCI_EEPROM is not set
+-# CONFIG_DVB_BUDGET_CORE is not set
+-
+-#
+-# Supported USB Adapters
+-#
+-# CONFIG_DVB_USB is not set
+-# CONFIG_DVB_TTUSB_BUDGET is not set
+-# CONFIG_DVB_TTUSB_DEC is not set
+-# CONFIG_DVB_CINERGYT2 is not set
+-
+-#
+-# Supported FlexCopII (B2C2) Adapters
+-#
+-# CONFIG_DVB_B2C2_FLEXCOP is not set
+-
+-#
+-# Supported BT878 Adapters
+-#
+-
+-#
+-# Supported Pluto2 Adapters
+-#
+-# CONFIG_DVB_PLUTO2 is not set
+-
+-#
+-# Supported DVB Frontends
+-#
+-
+-#
+-# Customise DVB Frontends
+-#
+-# CONFIG_DVB_FE_CUSTOMISE is not set
+-
+-#
+-# DVB-S (satellite) frontends
+-#
+-# CONFIG_DVB_STV0299 is not set
+-# CONFIG_DVB_CX24110 is not set
+-# CONFIG_DVB_CX24123 is not set
+-# CONFIG_DVB_TDA8083 is not set
+-# CONFIG_DVB_MT312 is not set
+-# CONFIG_DVB_VES1X93 is not set
+-# CONFIG_DVB_S5H1420 is not set
+-# CONFIG_DVB_TDA10086 is not set
+-
+-#
+-# DVB-T (terrestrial) frontends
+-#
+-# CONFIG_DVB_SP8870 is not set
+-# CONFIG_DVB_SP887X is not set
+-# CONFIG_DVB_CX22700 is not set
+-# CONFIG_DVB_CX22702 is not set
+-# CONFIG_DVB_L64781 is not set
+-# CONFIG_DVB_TDA1004X is not set
+-# CONFIG_DVB_NXT6000 is not set
+-# CONFIG_DVB_MT352 is not set
+-# CONFIG_DVB_ZL10353 is not set
+-# CONFIG_DVB_DIB3000MB is not set
+-# CONFIG_DVB_DIB3000MC is not set
+-# CONFIG_DVB_DIB7000M is not set
+-# CONFIG_DVB_DIB7000P is not set
+-
+-#
+-# DVB-C (cable) frontends
+-#
+-# CONFIG_DVB_VES1820 is not set
+-# CONFIG_DVB_TDA10021 is not set
+-# CONFIG_DVB_TDA10023 is not set
+-# CONFIG_DVB_STV0297 is not set
+-
+-#
+-# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+-#
+-# CONFIG_DVB_NXT200X is not set
+-# CONFIG_DVB_OR51211 is not set
+-# CONFIG_DVB_OR51132 is not set
+-# CONFIG_DVB_BCM3510 is not set
+-# CONFIG_DVB_LGDT330X is not set
+-# CONFIG_DVB_S5H1409 is not set
+-
+-#
+-# Tuners/PLL support
+-#
+-# CONFIG_DVB_PLL is not set
+-# CONFIG_DVB_TDA826X is not set
+-# CONFIG_DVB_TDA827X is not set
+-# CONFIG_DVB_TDA18271 is not set
+-# CONFIG_DVB_TUNER_QT1010 is not set
+-# CONFIG_DVB_TUNER_MT2060 is not set
+-# CONFIG_DVB_TUNER_MT2266 is not set
+-# CONFIG_DVB_TUNER_MT2131 is not set
+-# CONFIG_DVB_TUNER_DIB0070 is not set
+-# CONFIG_DVB_TUNER_XC5000 is not set
+-
+-#
+-# Miscellaneous devices
+-#
+-# CONFIG_DVB_LNBP21 is not set
+-# CONFIG_DVB_ISL6421 is not set
+-# CONFIG_DVB_TUA6100 is not set
+-CONFIG_DAB=y
+-# CONFIG_USB_DABUSB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=y
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Console display driver support
+-#
+-CONFIG_VGA_CONSOLE=y
+-# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+-CONFIG_DUMMY_CONSOLE=y
+-
+-#
+-# Sound
+-#
+-CONFIG_SOUND=y
+-
+-#
+-# Advanced Linux Sound Architecture
+-#
+-CONFIG_SND=y
+-CONFIG_SND_TIMER=y
+-CONFIG_SND_PCM=y
+-# CONFIG_SND_SEQUENCER is not set
+-# CONFIG_SND_MIXER_OSS is not set
+-# CONFIG_SND_PCM_OSS is not set
+-# CONFIG_SND_DYNAMIC_MINORS is not set
+-CONFIG_SND_SUPPORT_OLD_API=y
+-CONFIG_SND_VERBOSE_PROCFS=y
+-# CONFIG_SND_VERBOSE_PRINTK is not set
+-# CONFIG_SND_DEBUG is not set
+-
+-#
+-# Generic devices
+-#
+-CONFIG_SND_AC97_CODEC=y
+-# CONFIG_SND_DUMMY is not set
+-# CONFIG_SND_MTPAV is not set
+-# CONFIG_SND_SERIAL_U16550 is not set
+-# CONFIG_SND_MPU401 is not set
+-
+-#
+-# PCI devices
+-#
+-# CONFIG_SND_AD1889 is not set
+-# CONFIG_SND_ALS300 is not set
+-# CONFIG_SND_ALS4000 is not set
+-# CONFIG_SND_ALI5451 is not set
+-# CONFIG_SND_ATIIXP is not set
+-# CONFIG_SND_ATIIXP_MODEM is not set
+-# CONFIG_SND_AU8810 is not set
+-# CONFIG_SND_AU8820 is not set
+-# CONFIG_SND_AU8830 is not set
+-# CONFIG_SND_AZT3328 is not set
+-# CONFIG_SND_BT87X is not set
+-# CONFIG_SND_CA0106 is not set
+-# CONFIG_SND_CMIPCI is not set
+-# CONFIG_SND_OXYGEN is not set
+-# CONFIG_SND_CS4281 is not set
+-# CONFIG_SND_CS46XX is not set
+-# CONFIG_SND_CS5530 is not set
+-# CONFIG_SND_DARLA20 is not set
+-# CONFIG_SND_GINA20 is not set
+-# CONFIG_SND_LAYLA20 is not set
+-# CONFIG_SND_DARLA24 is not set
+-# CONFIG_SND_GINA24 is not set
+-# CONFIG_SND_LAYLA24 is not set
+-# CONFIG_SND_MONA is not set
+-# CONFIG_SND_MIA is not set
+-# CONFIG_SND_ECHO3G is not set
+-# CONFIG_SND_INDIGO is not set
+-# CONFIG_SND_INDIGOIO is not set
+-# CONFIG_SND_INDIGODJ is not set
+-# CONFIG_SND_EMU10K1 is not set
+-# CONFIG_SND_EMU10K1X is not set
+-# CONFIG_SND_ENS1370 is not set
+-# CONFIG_SND_ENS1371 is not set
+-# CONFIG_SND_ES1938 is not set
+-# CONFIG_SND_ES1968 is not set
+-# CONFIG_SND_FM801 is not set
+-# CONFIG_SND_HDA_INTEL is not set
+-# CONFIG_SND_HDSP is not set
+-# CONFIG_SND_HDSPM is not set
+-# CONFIG_SND_HIFIER is not set
+-# CONFIG_SND_ICE1712 is not set
+-# CONFIG_SND_ICE1724 is not set
+-CONFIG_SND_INTEL8X0=y
+-# CONFIG_SND_INTEL8X0M is not set
+-# CONFIG_SND_KORG1212 is not set
+-# CONFIG_SND_MAESTRO3 is not set
+-# CONFIG_SND_MIXART is not set
+-# CONFIG_SND_NM256 is not set
+-# CONFIG_SND_PCXHR is not set
+-# CONFIG_SND_RIPTIDE is not set
+-# CONFIG_SND_RME32 is not set
+-# CONFIG_SND_RME96 is not set
+-# CONFIG_SND_RME9652 is not set
+-# CONFIG_SND_SONICVIBES is not set
+-# CONFIG_SND_TRIDENT is not set
+-# CONFIG_SND_VIA82XX is not set
+-# CONFIG_SND_VIA82XX_MODEM is not set
+-# CONFIG_SND_VIRTUOSO is not set
+-# CONFIG_SND_VX222 is not set
+-# CONFIG_SND_YMFPCI is not set
+-# CONFIG_SND_AC97_POWER_SAVE is not set
+-
+-#
+-# ALSA PowerMac devices
+-#
+-
+-#
+-# ALSA PowerPC devices
+-#
+-
+-#
+-# USB devices
+-#
+-# CONFIG_SND_USB_AUDIO is not set
+-# CONFIG_SND_USB_USX2Y is not set
+-# CONFIG_SND_USB_CAIAQ is not set
+-
+-#
+-# System on Chip audio support
+-#
+-# CONFIG_SND_SOC is not set
+-
+-#
+-# SoC Audio support for SuperH
+-#
+-
+-#
+-# ALSA SoC audio for Freescale SOCs
+-#
+-
+-#
+-# Open Sound System
+-#
+-# CONFIG_SOUND_PRIME is not set
+-CONFIG_AC97_BUS=y
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-
+-#
+-# USB Input Devices
+-#
+-CONFIG_USB_HID=y
+-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+-# CONFIG_HID_FF is not set
+-# CONFIG_USB_HIDDEV is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-CONFIG_USB=y
+-# CONFIG_USB_DEBUG is not set
+-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+-
+-#
+-# Miscellaneous USB options
+-#
+-CONFIG_USB_DEVICEFS=y
+-CONFIG_USB_DEVICE_CLASS=y
+-# CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_OTG is not set
+-
+-#
+-# USB Host Controller Drivers
+-#
+-CONFIG_USB_EHCI_HCD=y
+-# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+-# CONFIG_USB_EHCI_FSL is not set
+-CONFIG_USB_EHCI_HCD_PPC_OF=y
+-# CONFIG_USB_ISP116X_HCD is not set
+-CONFIG_USB_OHCI_HCD=y
+-CONFIG_USB_OHCI_HCD_PPC_OF=y
+-CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+-CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
+-CONFIG_USB_OHCI_HCD_PCI=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
+-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+-# CONFIG_USB_UHCI_HCD is not set
+-# CONFIG_USB_SL811_HCD is not set
+-# CONFIG_USB_R8A66597_HCD is not set
+-
+-#
+-# USB Device Class drivers
+-#
+-# CONFIG_USB_ACM is not set
+-# CONFIG_USB_PRINTER is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# may also be needed; see USB_STORAGE Help for more information
+-#
+-CONFIG_USB_STORAGE=y
+-# CONFIG_USB_STORAGE_DEBUG is not set
+-# CONFIG_USB_STORAGE_DATAFAB is not set
+-# CONFIG_USB_STORAGE_FREECOM is not set
+-# CONFIG_USB_STORAGE_ISD200 is not set
+-# CONFIG_USB_STORAGE_DPCM is not set
+-# CONFIG_USB_STORAGE_USBAT is not set
+-# CONFIG_USB_STORAGE_SDDR09 is not set
+-# CONFIG_USB_STORAGE_SDDR55 is not set
+-# CONFIG_USB_STORAGE_JUMPSHOT is not set
+-# CONFIG_USB_STORAGE_ALAUDA is not set
+-# CONFIG_USB_STORAGE_KARMA is not set
+-# CONFIG_USB_LIBUSUAL is not set
+-
+-#
+-# USB Imaging devices
+-#
+-# CONFIG_USB_MDC800 is not set
+-# CONFIG_USB_MICROTEK is not set
+-CONFIG_USB_MON=y
+-
+-#
+-# USB port drivers
+-#
+-# CONFIG_USB_SERIAL is not set
+-
+-#
+-# USB Miscellaneous drivers
+-#
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+-# CONFIG_USB_ADUTUX is not set
+-# CONFIG_USB_AUERSWALD is not set
+-# CONFIG_USB_RIO500 is not set
+-# CONFIG_USB_LEGOTOWER is not set
+-# CONFIG_USB_LCD is not set
+-# CONFIG_USB_BERRY_CHARGE is not set
+-# CONFIG_USB_LED is not set
+-# CONFIG_USB_CYPRESS_CY7C63 is not set
+-# CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGET is not set
+-# CONFIG_USB_IDMOUSE is not set
+-# CONFIG_USB_FTDI_ELAN is not set
+-# CONFIG_USB_APPLEDISPLAY is not set
+-# CONFIG_USB_SISUSBVGA is not set
+-# CONFIG_USB_LD is not set
+-# CONFIG_USB_TRANCEVIBRATOR is not set
+-# CONFIG_USB_IOWARRIOR is not set
+-# CONFIG_USB_TEST is not set
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-CONFIG_RTC_LIB=y
+-CONFIG_RTC_CLASS=y
+-CONFIG_RTC_HCTOSYS=y
+-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+-# CONFIG_RTC_DEBUG is not set
+-
+-#
+-# RTC interfaces
+-#
+-CONFIG_RTC_INTF_SYSFS=y
+-CONFIG_RTC_INTF_PROC=y
+-CONFIG_RTC_INTF_DEV=y
+-# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+-# CONFIG_RTC_DRV_TEST is not set
+-
+-#
+-# I2C RTC drivers
+-#
+-# CONFIG_RTC_DRV_DS1307 is not set
+-# CONFIG_RTC_DRV_DS1374 is not set
+-# CONFIG_RTC_DRV_DS1672 is not set
+-# CONFIG_RTC_DRV_MAX6900 is not set
+-# CONFIG_RTC_DRV_RS5C372 is not set
+-# CONFIG_RTC_DRV_ISL1208 is not set
+-# CONFIG_RTC_DRV_X1205 is not set
+-# CONFIG_RTC_DRV_PCF8563 is not set
+-# CONFIG_RTC_DRV_PCF8583 is not set
+-# CONFIG_RTC_DRV_M41T80 is not set
+-# CONFIG_RTC_DRV_S35390A is not set
+-
+-#
+-# SPI RTC drivers
+-#
+-
+-#
+-# Platform RTC drivers
+-#
+-CONFIG_RTC_DRV_CMOS=y
+-# CONFIG_RTC_DRV_DS1511 is not set
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
+-# CONFIG_RTC_DRV_STK17TA8 is not set
+-# CONFIG_RTC_DRV_M48T86 is not set
+-# CONFIG_RTC_DRV_M48T59 is not set
+-# CONFIG_RTC_DRV_V3020 is not set
+-
+-#
+-# on-CPU RTC drivers
+-#
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-CONFIG_ISO9660_FS=m
+-CONFIG_JOLIET=y
+-CONFIG_ZISOFS=y
+-CONFIG_UDF_FS=m
+-CONFIG_UDF_NLS=y
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-CONFIG_FAT_FS=y
+-CONFIG_MSDOS_FS=m
+-CONFIG_VFAT_FS=y
+-CONFIG_FAT_DEFAULT_CODEPAGE=437
+-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+-CONFIG_NTFS_FS=y
+-# CONFIG_NTFS_DEBUG is not set
+-# CONFIG_NTFS_RW is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-CONFIG_ADFS_FS=m
+-# CONFIG_ADFS_FS_RW is not set
+-CONFIG_AFFS_FS=m
+-CONFIG_HFS_FS=m
+-CONFIG_HFSPLUS_FS=m
+-CONFIG_BEFS_FS=m
+-# CONFIG_BEFS_DEBUG is not set
+-CONFIG_BFS_FS=m
+-CONFIG_EFS_FS=m
+-CONFIG_CRAMFS=y
+-CONFIG_VXFS_FS=m
+-# CONFIG_MINIX_FS is not set
+-CONFIG_HPFS_FS=m
+-CONFIG_QNX4FS_FS=m
+-# CONFIG_ROMFS_FS is not set
+-CONFIG_SYSV_FS=m
+-CONFIG_UFS_FS=m
+-# CONFIG_UFS_FS_WRITE is not set
+-# CONFIG_UFS_DEBUG is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-CONFIG_NFSD=y
+-# CONFIG_NFSD_V3 is not set
+-CONFIG_NFSD_TCP=y
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_EXPORTFS=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-CONFIG_MAC_PARTITION=y
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_BSD_DISKLABEL is not set
+-# CONFIG_MINIX_SUBPARTITION is not set
+-# CONFIG_SOLARIS_X86_PARTITION is not set
+-# CONFIG_UNIXWARE_DISKLABEL is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-CONFIG_NLS=y
+-CONFIG_NLS_DEFAULT="iso8859-1"
+-# CONFIG_NLS_CODEPAGE_437 is not set
+-# CONFIG_NLS_CODEPAGE_737 is not set
+-# CONFIG_NLS_CODEPAGE_775 is not set
+-# CONFIG_NLS_CODEPAGE_850 is not set
+-# CONFIG_NLS_CODEPAGE_852 is not set
+-# CONFIG_NLS_CODEPAGE_855 is not set
+-# CONFIG_NLS_CODEPAGE_857 is not set
+-# CONFIG_NLS_CODEPAGE_860 is not set
+-# CONFIG_NLS_CODEPAGE_861 is not set
+-# CONFIG_NLS_CODEPAGE_862 is not set
+-# CONFIG_NLS_CODEPAGE_863 is not set
+-# CONFIG_NLS_CODEPAGE_864 is not set
+-# CONFIG_NLS_CODEPAGE_865 is not set
+-# CONFIG_NLS_CODEPAGE_866 is not set
+-# CONFIG_NLS_CODEPAGE_869 is not set
+-# CONFIG_NLS_CODEPAGE_936 is not set
+-# CONFIG_NLS_CODEPAGE_950 is not set
+-# CONFIG_NLS_CODEPAGE_932 is not set
+-# CONFIG_NLS_CODEPAGE_949 is not set
+-# CONFIG_NLS_CODEPAGE_874 is not set
+-# CONFIG_NLS_ISO8859_8 is not set
+-# CONFIG_NLS_CODEPAGE_1250 is not set
+-# CONFIG_NLS_CODEPAGE_1251 is not set
+-# CONFIG_NLS_ASCII is not set
+-# CONFIG_NLS_ISO8859_1 is not set
+-# CONFIG_NLS_ISO8859_2 is not set
+-# CONFIG_NLS_ISO8859_3 is not set
+-# CONFIG_NLS_ISO8859_4 is not set
+-# CONFIG_NLS_ISO8859_5 is not set
+-# CONFIG_NLS_ISO8859_6 is not set
+-# CONFIG_NLS_ISO8859_7 is not set
+-# CONFIG_NLS_ISO8859_9 is not set
+-# CONFIG_NLS_ISO8859_13 is not set
+-# CONFIG_NLS_ISO8859_14 is not set
+-# CONFIG_NLS_ISO8859_15 is not set
+-# CONFIG_NLS_KOI8_R is not set
+-# CONFIG_NLS_KOI8_U is not set
+-CONFIG_NLS_UTF8=m
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-CONFIG_LIBCRC32C=m
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_HIGHMEM is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-CONFIG_DEBUG_INFO=y
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_HASH=y
+-CONFIG_CRYPTO_MANAGER=y
+-CONFIG_CRYPTO_HMAC=y
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-CONFIG_CRYPTO_SHA1=m
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/mpc85xx_cds_defconfig b/arch/powerpc/configs/mpc85xx_cds_defconfig
+deleted file mode 100644
+index a469fe9..0000000
+--- a/arch/powerpc/configs/mpc85xx_cds_defconfig
++++ /dev/null
+@@ -1,935 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:30 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_ALL is not set
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-# CONFIG_MODULES is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-# CONFIG_MPC8540_ADS is not set
+-# CONFIG_MPC8560_ADS is not set
+-CONFIG_MPC85xx_CDS=y
+-# CONFIG_MPC85xx_MDS is not set
+-# CONFIG_MPC85xx_DS is not set
+-# CONFIG_STX_GP3 is not set
+-# CONFIG_TQM8540 is not set
+-# CONFIG_TQM8541 is not set
+-# CONFIG_TQM8555 is not set
+-# CONFIG_TQM8560 is not set
+-# CONFIG_SBC8548 is not set
+-# CONFIG_SBC8560 is not set
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-CONFIG_PPC_I8259=y
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_CPM2 is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-CONFIG_BINFMT_MISC=y
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-# CONFIG_SECCOMP is not set
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_FSL_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-CONFIG_XFRM_USER=y
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-CONFIG_IDE=y
+-CONFIG_IDE_MAX_HWIFS=4
+-CONFIG_BLK_DEV_IDE=y
+-
+-#
+-# Please see Documentation/ide/ide.txt for help/info on IDE drives
+-#
+-# CONFIG_BLK_DEV_IDE_SATA is not set
+-# CONFIG_BLK_DEV_IDEDISK is not set
+-# CONFIG_IDEDISK_MULTI_MODE is not set
+-# CONFIG_BLK_DEV_IDECD is not set
+-# CONFIG_BLK_DEV_IDETAPE is not set
+-# CONFIG_BLK_DEV_IDEFLOPPY is not set
+-# CONFIG_IDE_TASK_IOCTL is not set
+-CONFIG_IDE_PROC_FS=y
+-
+-#
+-# IDE chipset support/bugfixes
+-#
+-CONFIG_IDE_GENERIC=y
+-# CONFIG_BLK_DEV_PLATFORM is not set
+-CONFIG_BLK_DEV_IDEDMA_SFF=y
+-
+-#
+-# PCI IDE chipsets support
+-#
+-CONFIG_BLK_DEV_IDEPCI=y
+-CONFIG_IDEPCI_PCIBUS_ORDER=y
+-# CONFIG_BLK_DEV_OFFBOARD is not set
+-CONFIG_BLK_DEV_GENERIC=y
+-# CONFIG_BLK_DEV_OPTI621 is not set
+-CONFIG_BLK_DEV_IDEDMA_PCI=y
+-# CONFIG_BLK_DEV_AEC62XX is not set
+-# CONFIG_BLK_DEV_ALI15X3 is not set
+-# CONFIG_BLK_DEV_AMD74XX is not set
+-# CONFIG_BLK_DEV_CMD64X is not set
+-# CONFIG_BLK_DEV_TRIFLEX is not set
+-# CONFIG_BLK_DEV_CY82C693 is not set
+-# CONFIG_BLK_DEV_CS5520 is not set
+-# CONFIG_BLK_DEV_CS5530 is not set
+-# CONFIG_BLK_DEV_HPT34X is not set
+-# CONFIG_BLK_DEV_HPT366 is not set
+-# CONFIG_BLK_DEV_JMICRON is not set
+-# CONFIG_BLK_DEV_SC1200 is not set
+-# CONFIG_BLK_DEV_PIIX is not set
+-# CONFIG_BLK_DEV_IT8213 is not set
+-# CONFIG_BLK_DEV_IT821X is not set
+-# CONFIG_BLK_DEV_NS87415 is not set
+-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+-# CONFIG_BLK_DEV_SVWKS is not set
+-# CONFIG_BLK_DEV_SIIMAGE is not set
+-# CONFIG_BLK_DEV_SL82C105 is not set
+-# CONFIG_BLK_DEV_SLC90E66 is not set
+-# CONFIG_BLK_DEV_TRM290 is not set
+-CONFIG_BLK_DEV_VIA82CXXX=y
+-# CONFIG_BLK_DEV_TC86C001 is not set
+-CONFIG_BLK_DEV_IDEDMA=y
+-CONFIG_IDE_ARCH_OBSOLETE_INIT=y
+-# CONFIG_BLK_DEV_HD is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-CONFIG_E1000=y
+-CONFIG_E1000_NAPI=y
+-# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=y
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-# CONFIG_NFS_V3 is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-CONFIG_DEBUG_MUTEXES=y
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-# CONFIG_CRYPTO_MANAGER is not set
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-# CONFIG_CRYPTO_MD5 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-# CONFIG_CRYPTO_CBC is not set
+-# CONFIG_CRYPTO_PCBC is not set
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig
+index 558b0d3..fca1142 100644
+--- a/arch/powerpc/configs/pmac32_defconfig
++++ b/arch/powerpc/configs/pmac32_defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+ # Linux kernel version: 2.6.25-rc6
+-# Thu Mar 20 11:05:14 2008
++# Thu Mar 27 13:56:21 2008
+ #
+ # CONFIG_PPC64 is not set
+
+@@ -77,8 +77,6 @@ CONFIG_IKCONFIG_PROC=y
+ CONFIG_LOG_BUF_SHIFT=14
+ # CONFIG_CGROUPS is not set
+ # CONFIG_GROUP_SCHED is not set
+-# CONFIG_USER_SCHED is not set
+-# CONFIG_CGROUP_SCHED is not set
+ CONFIG_SYSFS_DEPRECATED=y
+ CONFIG_SYSFS_DEPRECATED_V2=y
+ # CONFIG_RELAY is not set
+@@ -272,7 +270,7 @@ CONFIG_PCI_SYSCALL=y
+ # CONFIG_PCIEPORTBUS is not set
+ CONFIG_ARCH_SUPPORTS_MSI=y
+ # CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_LEGACY is not set
+ # CONFIG_PCI_DEBUG is not set
+ CONFIG_PCCARD=m
+ # CONFIG_PCMCIA_DEBUG is not set
+@@ -1895,6 +1893,7 @@ CONFIG_PLIST=y
+ CONFIG_HAS_IOMEM=y
+ CONFIG_HAS_IOPORT=y
+ CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
+
+ #
+ # Kernel hacking
+diff --git a/arch/powerpc/configs/ppc40x_defconfig b/arch/powerpc/configs/ppc40x_defconfig
+new file mode 100644
+index 0000000..9d0140e
+--- /dev/null
++++ b/arch/powerpc/configs/ppc40x_defconfig
+@@ -0,0 +1,896 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc9
++# Tue Apr 15 08:46:44 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++# CONFIG_6xx is not set
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++CONFIG_40x=y
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_4xx=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_NOT_COHERENT_CACHE=y
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++# CONFIG_GENERIC_TBSYNC is not set
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++# CONFIG_DEFAULT_UIMAGE is not set
++CONFIG_PPC_DCR_NATIVE=y
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_PPC_DCR=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++CONFIG_KALLSYMS_EXTRA_PASS=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_BLOCK=y
++CONFIG_LBD=y
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++CONFIG_CLASSIC_RCU=y
++CONFIG_PPC4xx_PCI_EXPRESS=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++CONFIG_EP405=y
++CONFIG_KILAUEA=y
++CONFIG_MAKALU=y
++CONFIG_WALNUT=y
++CONFIG_XILINX_VIRTEX_GENERIC_BOARD=y
++CONFIG_405GP=y
++CONFIG_405EX=y
++CONFIG_XILINX_VIRTEX=y
++CONFIG_XILINX_VIRTEX_II_PRO=y
++CONFIG_XILINX_VIRTEX_4_FX=y
++CONFIG_IBM405_ERR77=y
++CONFIG_IBM405_ERR51=y
++# CONFIG_IPIC is not set
++# CONFIG_MPIC is not set
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++CONFIG_OF_RTC=y
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_MATH_EMULATION is not set
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++CONFIG_RESOURCES_64BIT=y
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_FORCE_MAX_ZONEORDER=11
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_4xx_SOC=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_PCIEPORTBUS is not set
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++# CONFIG_PCI_LEGACY is not set
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_CONSISTENT_START=0xff100000
++CONFIG_CONSISTENT_SIZE=0x00200000
++CONFIG_BOOT_LOAD=0x00400000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++CONFIG_MTD_OF_PARTS=y
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=m
++CONFIG_MTD_BLOCK=m
++# CONFIG_MTD_BLOCK_RO is not set
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=35000
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_XILINX_SYSACE is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++CONFIG_IBM_NEW_EMAC=y
++CONFIG_IBM_NEW_EMAC_RXB=128
++CONFIG_IBM_NEW_EMAC_TXB=64
++CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
++CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
++CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
++# CONFIG_IBM_NEW_EMAC_DEBUG is not set
++CONFIG_IBM_NEW_EMAC_ZMII=y
++CONFIG_IBM_NEW_EMAC_RGMII=y
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++CONFIG_IBM_NEW_EMAC_EMAC4=y
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++# CONFIG_INPUT is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_RSA is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++CONFIG_SERIAL_OF_PLATFORM=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++CONFIG_XILINX_HWICAP=m
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_THERMAL=y
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4DEV_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_NLS is not set
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++# CONFIG_DEBUGGER is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_MANAGER=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/ppc44x_defconfig b/arch/powerpc/configs/ppc44x_defconfig
+index 57bd775..12f9b5a 100644
+--- a/arch/powerpc/configs/ppc44x_defconfig
++++ b/arch/powerpc/configs/ppc44x_defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc2
+-# Fri Feb 15 21:57:35 2008
++# Linux kernel version: 2.6.25-rc6
++# Sat Apr 5 09:35:48 2008
+ #
+ # CONFIG_PPC64 is not set
+
+@@ -79,6 +79,7 @@ CONFIG_FAIR_GROUP_SCHED=y
+ CONFIG_USER_SCHED=y
+ # CONFIG_CGROUP_SCHED is not set
+ CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
+ # CONFIG_RELAY is not set
+ # CONFIG_NAMESPACES is not set
+ CONFIG_BLK_DEV_INITRD=y
+@@ -113,6 +114,7 @@ CONFIG_SLUB=y
+ CONFIG_HAVE_OPROFILE=y
+ # CONFIG_KPROBES is not set
+ CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
+ CONFIG_PROC_PAGE_MONITOR=y
+ CONFIG_SLABINFO=y
+ CONFIG_RT_MUTEXES=y
+@@ -143,7 +145,6 @@ CONFIG_DEFAULT_AS=y
+ # CONFIG_DEFAULT_NOOP is not set
+ CONFIG_DEFAULT_IOSCHED="anticipatory"
+ CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+ CONFIG_PPC4xx_PCI_EXPRESS=y
+
+ #
+@@ -161,12 +162,15 @@ CONFIG_TAISHAN=y
+ CONFIG_KATMAI=y
+ CONFIG_RAINIER=y
+ CONFIG_WARP=y
++CONFIG_CANYONLANDS=y
++CONFIG_YOSEMITE=y
+ CONFIG_440EP=y
+ CONFIG_440EPX=y
+ CONFIG_440GRX=y
+ CONFIG_440GP=y
+ CONFIG_440GX=y
+ CONFIG_440SPe=y
++CONFIG_460EX=y
+ CONFIG_IBM440EP_ERR42=y
+ # CONFIG_IPIC is not set
+ # CONFIG_MPIC is not set
+@@ -199,7 +203,6 @@ CONFIG_HZ=250
+ CONFIG_PREEMPT_NONE=y
+ # CONFIG_PREEMPT_VOLUNTARY is not set
+ # CONFIG_PREEMPT is not set
+-# CONFIG_RCU_TRACE is not set
+ CONFIG_BINFMT_ELF=y
+ # CONFIG_BINFMT_MISC is not set
+ CONFIG_MATH_EMULATION=y
+@@ -232,6 +235,7 @@ CONFIG_ISA_DMA_API=y
+ #
+ CONFIG_ZONE_DMA=y
+ CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_4xx_SOC=y
+ CONFIG_PCI=y
+ CONFIG_PCI_DOMAINS=y
+ CONFIG_PCI_SYSCALL=y
+@@ -678,6 +682,7 @@ CONFIG_USB_ARCH_HAS_EHCI=y
+ # CONFIG_INFINIBAND is not set
+ # CONFIG_EDAC is not set
+ # CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
+
+ #
+ # Userspace I/O
+@@ -805,6 +810,7 @@ CONFIG_PLIST=y
+ CONFIG_HAS_IOMEM=y
+ CONFIG_HAS_IOPORT=y
+ CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
+
+ #
+ # Kernel hacking
+diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
+index 880ab7a..970282b 100644
+--- a/arch/powerpc/configs/ppc64_defconfig
++++ b/arch/powerpc/configs/ppc64_defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+ # Linux kernel version: 2.6.25-rc6
+-# Thu Mar 20 11:06:28 2008
++# Thu Mar 27 13:56:24 2008
+ #
+ CONFIG_PPC64=y
+
+@@ -84,8 +84,6 @@ CONFIG_CGROUPS=y
+ # CONFIG_CGROUP_NS is not set
+ CONFIG_CPUSETS=y
+ # CONFIG_GROUP_SCHED is not set
+-# CONFIG_USER_SCHED is not set
+-# CONFIG_CGROUP_SCHED is not set
+ # CONFIG_CGROUP_CPUACCT is not set
+ # CONFIG_RESOURCE_COUNTERS is not set
+ CONFIG_SYSFS_DEPRECATED=y
+@@ -289,6 +287,7 @@ CONFIG_ARCH_HAS_WALK_MEMORY=y
+ CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+ CONFIG_KEXEC=y
+ # CONFIG_CRASH_DUMP is not set
++# CONFIG_PHYP_DUMP is not set
+ CONFIG_IRQ_ALL_CPUS=y
+ # CONFIG_NUMA is not set
+ CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+@@ -335,7 +334,7 @@ CONFIG_PCI_SYSCALL=y
+ # CONFIG_PCIEPORTBUS is not set
+ CONFIG_ARCH_SUPPORTS_MSI=y
+ CONFIG_PCI_MSI=y
+-CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_LEGACY is not set
+ # CONFIG_PCI_DEBUG is not set
+ CONFIG_PCCARD=y
+ # CONFIG_PCMCIA_DEBUG is not set
+@@ -1881,6 +1880,7 @@ CONFIG_PLIST=y
+ CONFIG_HAS_IOMEM=y
+ CONFIG_HAS_IOPORT=y
+ CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
+
+ #
+ # Kernel hacking
+diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
+index 755aca7..3e2593c 100644
+--- a/arch/powerpc/configs/pseries_defconfig
++++ b/arch/powerpc/configs/pseries_defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+ # Linux kernel version: 2.6.25-rc6
+-# Thu Mar 20 11:08:01 2008
++# Thu Mar 27 13:56:28 2008
+ #
+ CONFIG_PPC64=y
+
+@@ -83,8 +83,6 @@ CONFIG_CGROUPS=y
+ CONFIG_CGROUP_NS=y
+ CONFIG_CPUSETS=y
+ # CONFIG_GROUP_SCHED is not set
+-# CONFIG_USER_SCHED is not set
+-# CONFIG_CGROUP_SCHED is not set
+ CONFIG_CGROUP_CPUACCT=y
+ # CONFIG_RESOURCE_COUNTERS is not set
+ CONFIG_SYSFS_DEPRECATED=y
+@@ -237,6 +235,7 @@ CONFIG_ARCH_HAS_WALK_MEMORY=y
+ CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+ CONFIG_KEXEC=y
+ # CONFIG_CRASH_DUMP is not set
++# CONFIG_PHYP_DUMP is not set
+ CONFIG_IRQ_ALL_CPUS=y
+ CONFIG_NUMA=y
+ CONFIG_NODES_SHIFT=4
+@@ -283,7 +282,7 @@ CONFIG_PCI_SYSCALL=y
+ # CONFIG_PCIEPORTBUS is not set
+ CONFIG_ARCH_SUPPORTS_MSI=y
+ CONFIG_PCI_MSI=y
+-CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_LEGACY is not set
+ # CONFIG_PCI_DEBUG is not set
+ # CONFIG_PCCARD is not set
+ CONFIG_HOTPLUG_PCI=m
+@@ -1519,6 +1518,7 @@ CONFIG_PLIST=y
+ CONFIG_HAS_IOMEM=y
+ CONFIG_HAS_IOPORT=y
+ CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
+
+ #
+ # Kernel hacking
+diff --git a/arch/powerpc/configs/rainier_defconfig b/arch/powerpc/configs/rainier_defconfig
+deleted file mode 100644
+index dec18ca..0000000
+--- a/arch/powerpc/configs/rainier_defconfig
++++ /dev/null
+@@ -1,899 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc2
+-# Fri Feb 15 21:53:10 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-CONFIG_44x=y
+-# CONFIG_E200 is not set
+-CONFIG_4xx=y
+-CONFIG_BOOKE=y
+-CONFIG_PTE_64BIT=y
+-CONFIG_PHYS_64BIT=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-# CONFIG_DEFAULT_UIMAGE is not set
+-CONFIG_PPC_DCR_NATIVE=y
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_PPC_DCR=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_ALL is not set
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-# CONFIG_PPC4xx_PCI_EXPRESS is not set
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-# CONFIG_BAMBOO is not set
+-# CONFIG_EBONY is not set
+-# CONFIG_SEQUOIA is not set
+-# CONFIG_TAISHAN is not set
+-# CONFIG_KATMAI is not set
+-CONFIG_RAINIER=y
+-# CONFIG_WARP is not set
+-CONFIG_440GRX=y
+-# CONFIG_IPIC is not set
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_RCU_TRACE=y
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-CONFIG_RESOURCES_64BIT=y
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-CONFIG_CMDLINE_BOOL=y
+-CONFIG_CMDLINE=""
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x01000000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+-# CONFIG_INET_XFRM_MODE_BEET is not set
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-CONFIG_CONNECTOR=y
+-CONFIG_PROC_EVENTS=y
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-CONFIG_MTD_CMDLINE_PARTS=y
+-CONFIG_MTD_OF_PARTS=y
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-# CONFIG_MTD_BLKDEVS is not set
+-# CONFIG_MTD_BLOCK is not set
+-# CONFIG_MTD_BLOCK_RO is not set
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-CONFIG_MTD_JEDECPROBE=y
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-CONFIG_MTD_CFI_INTELEXT=y
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-CONFIG_MTD_PHYSMAP_OF=y
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=35000
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-# CONFIG_XILINX_SYSACE is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-CONFIG_MACINTOSH_DRIVERS=y
+-# CONFIG_MAC_EMUMOUSEBTN is not set
+-# CONFIG_WINDFARM is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-# CONFIG_NET_ETHERNET is not set
+-CONFIG_IBM_NEW_EMAC_ZMII=y
+-CONFIG_IBM_NEW_EMAC_RGMII=y
+-CONFIG_IBM_NEW_EMAC_EMAC4=y
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-# CONFIG_SERIAL_8250_PCI is not set
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-CONFIG_SERIAL_8250_EXTENDED=y
+-# CONFIG_SERIAL_8250_MANY_PORTS is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+-# CONFIG_SERIAL_8250_RSA is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_SERIAL_OF_PLATFORM=y
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-CONFIG_THERMAL=y
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_JFFS2_FS=y
+-CONFIG_JFFS2_FS_DEBUG=0
+-CONFIG_JFFS2_FS_WRITEBUFFER=y
+-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+-# CONFIG_JFFS2_SUMMARY is not set
+-# CONFIG_JFFS2_FS_XATTR is not set
+-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+-CONFIG_JFFS2_ZLIB=y
+-# CONFIG_JFFS2_LZO is not set
+-CONFIG_JFFS2_RTIME=y
+-# CONFIG_JFFS2_RUBIN is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_ZLIB_DEFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_MAGIC_SYSRQ=y
+-# CONFIG_UNUSED_SYMBOLS is not set
+-CONFIG_DEBUG_FS=y
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-CONFIG_DEBUGGER=y
+-# CONFIG_KGDB is not set
+-# CONFIG_XMON is not set
+-# CONFIG_VIRQ_DEBUG is not set
+-# CONFIG_BDI_SWITCH is not set
+-CONFIG_PPC_EARLY_DEBUG=y
+-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
+-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
+-# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
+-# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
+-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
+-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+-# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
+-# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
+-CONFIG_PPC_EARLY_DEBUG_44x=y
+-# CONFIG_PPC_EARLY_DEBUG_40x is not set
+-# CONFIG_PPC_EARLY_DEBUG_CPM is not set
+-CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW=0xef600300
+-CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH=0x1
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=y
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=y
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/sbc834x_defconfig b/arch/powerpc/configs/sbc834x_defconfig
+deleted file mode 100644
+index 1f15182..0000000
+--- a/arch/powerpc/configs/sbc834x_defconfig
++++ /dev/null
+@@ -1,828 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:38 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-CONFIG_6xx=y
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-# CONFIG_FSL_EMB_PERFMON is not set
+-CONFIG_PPC_STD_MMU=y
+-CONFIG_PPC_STD_MMU_32=y
+-# CONFIG_PPC_MM_SLICES is not set
+-# CONFIG_SMP is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLAB=y
+-# CONFIG_SLUB is not set
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MULTIPLATFORM is not set
+-# CONFIG_PPC_82xx is not set
+-CONFIG_PPC_83xx=y
+-# CONFIG_PPC_86xx is not set
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC83xx=y
+-# CONFIG_MPC831x_RDB is not set
+-# CONFIG_MPC832x_MDS is not set
+-# CONFIG_MPC832x_RDB is not set
+-# CONFIG_MPC834x_MDS is not set
+-# CONFIG_MPC834x_ITX is not set
+-# CONFIG_MPC836x_MDS is not set
+-# CONFIG_MPC837x_MDS is not set
+-# CONFIG_MPC837x_RDB is not set
+-CONFIG_SBC834x=y
+-CONFIG_PPC_MPC834x=y
+-CONFIG_IPIC=y
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_GENERIC_ISA_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-# CONFIG_PCI is not set
+-# CONFIG_PCI_DOMAINS is not set
+-# CONFIG_PCI_SYSCALL is not set
+-# CONFIG_ARCH_SUPPORTS_MSI is not set
+-# CONFIG_PCCARD is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-CONFIG_XFRM_USER=m
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-CONFIG_BROADCOM_PHY=y
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_E1000E_ENABLED is not set
+-CONFIG_GIANFAR=y
+-# CONFIG_GFAR_NAPI is not set
+-# CONFIG_NETDEV_10000 is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_83xx_WDT=y
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-# CONFIG_DAB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-# CONFIG_USB_SUPPORT is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-# CONFIG_EXT2_FS is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=m
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-# CONFIG_CRYPTO_HW is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/sbc8548_defconfig b/arch/powerpc/configs/sbc8548_defconfig
+deleted file mode 100644
+index 67f6797..0000000
+--- a/arch/powerpc/configs/sbc8548_defconfig
++++ /dev/null
+@@ -1,812 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:39 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLAB=y
+-# CONFIG_SLUB is not set
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-# CONFIG_MODULES is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-# CONFIG_MPC8540_ADS is not set
+-# CONFIG_MPC8560_ADS is not set
+-# CONFIG_MPC85xx_CDS is not set
+-# CONFIG_MPC85xx_MDS is not set
+-# CONFIG_MPC85xx_DS is not set
+-# CONFIG_STX_GP3 is not set
+-# CONFIG_TQM8540 is not set
+-# CONFIG_TQM8541 is not set
+-# CONFIG_TQM8555 is not set
+-# CONFIG_TQM8560 is not set
+-CONFIG_SBC8548=y
+-# CONFIG_SBC8560 is not set
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_CPM2 is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-CONFIG_BINFMT_MISC=y
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-# CONFIG_SECCOMP is not set
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_FSL_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-CONFIG_XFRM_USER=y
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=4096
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-CONFIG_BROADCOM_PHY=y
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=y
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-# CONFIG_HID_SUPPORT is not set
+-# CONFIG_USB_SUPPORT is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-# CONFIG_EXT2_FS is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-# CONFIG_NFS_V3 is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-# CONFIG_CRYPTO_MANAGER is not set
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-# CONFIG_CRYPTO_MD5 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-# CONFIG_CRYPTO_CBC is not set
+-# CONFIG_CRYPTO_PCBC is not set
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/sbc8560_defconfig b/arch/powerpc/configs/sbc8560_defconfig
+deleted file mode 100644
+index fef6055..0000000
+--- a/arch/powerpc/configs/sbc8560_defconfig
++++ /dev/null
+@@ -1,830 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:39 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_ALL is not set
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLAB=y
+-# CONFIG_SLUB is not set
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-# CONFIG_MODULES is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-# CONFIG_MPC8540_ADS is not set
+-# CONFIG_MPC8560_ADS is not set
+-# CONFIG_MPC85xx_CDS is not set
+-# CONFIG_MPC85xx_MDS is not set
+-# CONFIG_MPC85xx_DS is not set
+-# CONFIG_STX_GP3 is not set
+-# CONFIG_TQM8540 is not set
+-# CONFIG_TQM8541 is not set
+-# CONFIG_TQM8555 is not set
+-# CONFIG_TQM8560 is not set
+-# CONFIG_SBC8548 is not set
+-CONFIG_SBC8560=y
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_CPM2 is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-CONFIG_BINFMT_MISC=y
+-# CONFIG_MATH_EMULATION is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-# CONFIG_SECCOMP is not set
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_FSL_SOC=y
+-# CONFIG_PCI is not set
+-# CONFIG_PCI_DOMAINS is not set
+-# CONFIG_PCI_SYSCALL is not set
+-# CONFIG_ARCH_SUPPORTS_MSI is not set
+-# CONFIG_PCCARD is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-CONFIG_XFRM_USER=y
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-CONFIG_BROADCOM_PHY=y
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_E1000E_ENABLED is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-CONFIG_NETDEV_10000=y
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_NR_UARTS=2
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=y
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-# CONFIG_USB_ARCH_HAS_HCD is not set
+-# CONFIG_USB_ARCH_HAS_OHCI is not set
+-# CONFIG_USB_ARCH_HAS_EHCI is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_EDAC is not set
+-CONFIG_RTC_LIB=y
+-CONFIG_RTC_CLASS=y
+-CONFIG_RTC_HCTOSYS=y
+-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+-# CONFIG_RTC_DEBUG is not set
+-
+-#
+-# RTC interfaces
+-#
+-CONFIG_RTC_INTF_SYSFS=y
+-CONFIG_RTC_INTF_PROC=y
+-CONFIG_RTC_INTF_DEV=y
+-# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+-# CONFIG_RTC_DRV_TEST is not set
+-
+-#
+-# SPI RTC drivers
+-#
+-
+-#
+-# Platform RTC drivers
+-#
+-# CONFIG_RTC_DRV_CMOS is not set
+-# CONFIG_RTC_DRV_DS1511 is not set
+-# CONFIG_RTC_DRV_DS1553 is not set
+-# CONFIG_RTC_DRV_DS1742 is not set
+-# CONFIG_RTC_DRV_STK17TA8 is not set
+-# CONFIG_RTC_DRV_M48T86 is not set
+-CONFIG_RTC_DRV_M48T59=y
+-# CONFIG_RTC_DRV_V3020 is not set
+-
+-#
+-# on-CPU RTC drivers
+-#
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-# CONFIG_EXT2_FS is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-# CONFIG_NFS_V3 is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_MAGIC_SYSRQ=y
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_DEBUG_SLAB is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-CONFIG_DEBUG_MUTEXES=y
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_BDI_SWITCH is not set
+-CONFIG_PPC_EARLY_DEBUG=y
+-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
+-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
+-# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
+-# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
+-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
+-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+-# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
+-# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
+-# CONFIG_PPC_EARLY_DEBUG_44x is not set
+-# CONFIG_PPC_EARLY_DEBUG_40x is not set
+-# CONFIG_PPC_EARLY_DEBUG_CPM is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-# CONFIG_CRYPTO_MANAGER is not set
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-# CONFIG_CRYPTO_MD5 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-# CONFIG_CRYPTO_CBC is not set
+-# CONFIG_CRYPTO_PCBC is not set
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/sbc8641d_defconfig b/arch/powerpc/configs/sbc8641d_defconfig
+new file mode 100644
+index 0000000..3180125
+--- /dev/null
++++ b/arch/powerpc/configs/sbc8641d_defconfig
+@@ -0,0 +1,1342 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc6
++# Thu Apr 10 18:03:25 2008
++#
++# CONFIG_PPC64 is not set
++
++#
++# Processor support
++#
++CONFIG_6xx=y
++# CONFIG_PPC_85xx is not set
++# CONFIG_PPC_8xx is not set
++# CONFIG_40x is not set
++# CONFIG_44x is not set
++# CONFIG_E200 is not set
++CONFIG_PPC_FPU=y
++CONFIG_ALTIVEC=y
++CONFIG_PPC_STD_MMU=y
++CONFIG_PPC_STD_MMU_32=y
++# CONFIG_PPC_MM_SLICES is not set
++CONFIG_SMP=y
++CONFIG_NR_CPUS=2
++CONFIG_PPC32=y
++CONFIG_WORD_SIZE=32
++CONFIG_PPC_MERGE=y
++CONFIG_MMU=y
++CONFIG_GENERIC_CMOS_UPDATE=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_TIME_VSYSCALL=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_HARDIRQS=y
++# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
++CONFIG_IRQ_PER_CPU=y
++CONFIG_RWSEM_XCHGADD_ALGORITHM=y
++CONFIG_GENERIC_LOCKBREAK=y
++CONFIG_ARCH_HAS_ILOG2_U32=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
++CONFIG_PPC=y
++CONFIG_EARLY_PRINTK=y
++CONFIG_GENERIC_NVRAM=y
++CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
++CONFIG_ARCH_MAY_HAVE_PC_FDC=y
++CONFIG_PPC_OF=y
++CONFIG_OF=y
++CONFIG_PPC_UDBG_16550=y
++CONFIG_GENERIC_TBSYNC=y
++CONFIG_AUDIT_ARCH=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFAULT_UIMAGE=y
++# CONFIG_PPC_DCR_NATIVE is not set
++# CONFIG_PPC_DCR_MMIO is not set
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_LOCK_KERNEL=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_BSD_PROCESS_ACCT=y
++CONFIG_BSD_PROCESS_ACCT_V3=y
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++CONFIG_RELAY=y
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++CONFIG_STOP_MACHINE=y
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_CLASSIC_RCU=y
++
++#
++# Platform support
++#
++# CONFIG_PPC_MULTIPLATFORM is not set
++# CONFIG_PPC_82xx is not set
++# CONFIG_PPC_83xx is not set
++CONFIG_PPC_86xx=y
++# CONFIG_PPC_MPC512x is not set
++# CONFIG_PPC_MPC5121 is not set
++# CONFIG_PPC_CELL is not set
++# CONFIG_PPC_CELL_NATIVE is not set
++# CONFIG_PQ2ADS is not set
++# CONFIG_MPC8641_HPCN is not set
++CONFIG_SBC8641D=y
++# CONFIG_MPC8610_HPCD is not set
++CONFIG_MPC8641=y
++# CONFIG_IPIC is not set
++CONFIG_MPIC=y
++# CONFIG_MPIC_WEIRD is not set
++# CONFIG_PPC_I8259 is not set
++# CONFIG_PPC_RTAS is not set
++# CONFIG_MMIO_NVRAM is not set
++# CONFIG_PPC_MPC106 is not set
++# CONFIG_PPC_970_NAP is not set
++# CONFIG_PPC_INDIRECT_IO is not set
++# CONFIG_GENERIC_IOMAP is not set
++# CONFIG_CPU_FREQ is not set
++# CONFIG_FSL_ULI1575 is not set
++
++#
++# Kernel options
++#
++# CONFIG_HIGHMEM is not set
++CONFIG_TICK_ONESHOT=y
++# CONFIG_NO_HZ is not set
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++# CONFIG_PREEMPT_NONE is not set
++# CONFIG_PREEMPT_VOLUNTARY is not set
++CONFIG_PREEMPT=y
++# CONFIG_PREEMPT_RCU is not set
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_MISC=m
++CONFIG_FORCE_MAX_ZONEORDER=11
++# CONFIG_IOMMU_HELPER is not set
++CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
++CONFIG_ARCH_HAS_WALK_MEMORY=y
++CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
++CONFIG_IRQ_ALL_CPUS=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_PROC_DEVICETREE is not set
++# CONFIG_CMDLINE_BOOL is not set
++# CONFIG_PM is not set
++CONFIG_SECCOMP=y
++CONFIG_ISA_DMA_API=y
++
++#
++# Bus options
++#
++CONFIG_ZONE_DMA=y
++CONFIG_GENERIC_ISA_DMA=y
++CONFIG_PPC_INDIRECT_PCI=y
++CONFIG_FSL_SOC=y
++CONFIG_FSL_PCI=y
++CONFIG_PCI=y
++CONFIG_PCI_DOMAINS=y
++CONFIG_PCI_SYSCALL=y
++CONFIG_PCIEPORTBUS=y
++CONFIG_PCIEAER=y
++CONFIG_ARCH_SUPPORTS_MSI=y
++# CONFIG_PCI_MSI is not set
++CONFIG_PCI_LEGACY=y
++# CONFIG_PCI_DEBUG is not set
++# CONFIG_PCCARD is not set
++# CONFIG_HOTPLUG_PCI is not set
++
++#
++# Advanced setup
++#
++# CONFIG_ADVANCED_OPTIONS is not set
++
++#
++# Default settings for advanced configuration options are used
++#
++CONFIG_HIGHMEM_START=0xfe000000
++CONFIG_LOWMEM_SIZE=0x30000000
++CONFIG_KERNEL_START=0xc0000000
++CONFIG_TASK_SIZE=0xc0000000
++CONFIG_BOOT_LOAD=0x00800000
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++CONFIG_XFRM_USER=m
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++CONFIG_NET_KEY=m
++# CONFIG_NET_KEY_MIGRATE is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++CONFIG_IP_ADVANCED_ROUTER=y
++CONFIG_ASK_IP_FIB_HASH=y
++# CONFIG_IP_FIB_TRIE is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_MULTIPLE_TABLES=y
++CONFIG_IP_ROUTE_MULTIPATH=y
++CONFIG_IP_ROUTE_VERBOSE=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++CONFIG_IP_PNP_RARP=y
++CONFIG_NET_IPIP=m
++CONFIG_NET_IPGRE=m
++CONFIG_NET_IPGRE_BROADCAST=y
++CONFIG_IP_MROUTE=y
++CONFIG_IP_PIMSM_V1=y
++CONFIG_IP_PIMSM_V2=y
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++CONFIG_INET_AH=m
++CONFIG_INET_ESP=m
++CONFIG_INET_IPCOMP=m
++CONFIG_INET_XFRM_TUNNEL=m
++CONFIG_INET_TUNNEL=m
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IP_VS is not set
++CONFIG_IPV6=m
++# CONFIG_IPV6_PRIVACY is not set
++# CONFIG_IPV6_ROUTER_PREF is not set
++# CONFIG_IPV6_OPTIMISTIC_DAD is not set
++CONFIG_INET6_AH=m
++CONFIG_INET6_ESP=m
++CONFIG_INET6_IPCOMP=m
++# CONFIG_IPV6_MIP6 is not set
++CONFIG_INET6_XFRM_TUNNEL=m
++CONFIG_INET6_TUNNEL=m
++CONFIG_INET6_XFRM_MODE_TRANSPORT=m
++CONFIG_INET6_XFRM_MODE_TUNNEL=m
++CONFIG_INET6_XFRM_MODE_BEET=m
++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
++CONFIG_IPV6_SIT=m
++CONFIG_IPV6_TUNNEL=m
++# CONFIG_IPV6_MULTIPLE_TABLES is not set
++# CONFIG_NETLABEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++CONFIG_NETFILTER=y
++# CONFIG_NETFILTER_DEBUG is not set
++CONFIG_NETFILTER_ADVANCED=y
++CONFIG_BRIDGE_NETFILTER=y
++
++#
++# Core Netfilter Configuration
++#
++# CONFIG_NETFILTER_NETLINK_QUEUE is not set
++# CONFIG_NETFILTER_NETLINK_LOG is not set
++# CONFIG_NF_CONNTRACK is not set
++CONFIG_NETFILTER_XTABLES=m
++# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
++# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
++# CONFIG_NETFILTER_XT_TARGET_MARK is not set
++# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
++# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
++# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
++# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
++# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
++# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
++# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
++# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
++# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
++# CONFIG_NETFILTER_XT_MATCH_ESP is not set
++# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
++# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
++# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
++# CONFIG_NETFILTER_XT_MATCH_MAC is not set
++# CONFIG_NETFILTER_XT_MATCH_MARK is not set
++# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
++# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
++# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
++# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
++# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
++# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
++# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
++# CONFIG_NETFILTER_XT_MATCH_REALM is not set
++# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
++# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
++# CONFIG_NETFILTER_XT_MATCH_STRING is not set
++# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
++# CONFIG_NETFILTER_XT_MATCH_TIME is not set
++# CONFIG_NETFILTER_XT_MATCH_U32 is not set
++# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
++
++#
++# IP: Netfilter Configuration
++#
++CONFIG_IP_NF_QUEUE=m
++CONFIG_IP_NF_IPTABLES=m
++CONFIG_IP_NF_MATCH_RECENT=m
++CONFIG_IP_NF_MATCH_ECN=m
++# CONFIG_IP_NF_MATCH_AH is not set
++CONFIG_IP_NF_MATCH_TTL=m
++CONFIG_IP_NF_MATCH_ADDRTYPE=m
++CONFIG_IP_NF_FILTER=m
++CONFIG_IP_NF_TARGET_REJECT=m
++CONFIG_IP_NF_TARGET_LOG=m
++CONFIG_IP_NF_TARGET_ULOG=m
++CONFIG_IP_NF_MANGLE=m
++CONFIG_IP_NF_TARGET_ECN=m
++# CONFIG_IP_NF_TARGET_TTL is not set
++CONFIG_IP_NF_RAW=m
++CONFIG_IP_NF_ARPTABLES=m
++CONFIG_IP_NF_ARPFILTER=m
++CONFIG_IP_NF_ARP_MANGLE=m
++
++#
++# IPv6: Netfilter Configuration
++#
++CONFIG_IP6_NF_QUEUE=m
++CONFIG_IP6_NF_IPTABLES=m
++CONFIG_IP6_NF_MATCH_RT=m
++CONFIG_IP6_NF_MATCH_OPTS=m
++CONFIG_IP6_NF_MATCH_FRAG=m
++CONFIG_IP6_NF_MATCH_HL=m
++CONFIG_IP6_NF_MATCH_IPV6HEADER=m
++# CONFIG_IP6_NF_MATCH_AH is not set
++# CONFIG_IP6_NF_MATCH_MH is not set
++CONFIG_IP6_NF_MATCH_EUI64=m
++CONFIG_IP6_NF_FILTER=m
++CONFIG_IP6_NF_TARGET_LOG=m
++# CONFIG_IP6_NF_TARGET_REJECT is not set
++CONFIG_IP6_NF_MANGLE=m
++# CONFIG_IP6_NF_TARGET_HL is not set
++CONFIG_IP6_NF_RAW=m
++
++#
++# Bridge: Netfilter Configuration
++#
++# CONFIG_BRIDGE_NF_EBTABLES is not set
++# CONFIG_IP_DCCP is not set
++CONFIG_IP_SCTP=m
++# CONFIG_SCTP_DBG_MSG is not set
++# CONFIG_SCTP_DBG_OBJCNT is not set
++# CONFIG_SCTP_HMAC_NONE is not set
++# CONFIG_SCTP_HMAC_SHA1 is not set
++CONFIG_SCTP_HMAC_MD5=y
++CONFIG_TIPC=m
++# CONFIG_TIPC_ADVANCED is not set
++# CONFIG_TIPC_DEBUG is not set
++CONFIG_ATM=m
++CONFIG_ATM_CLIP=m
++# CONFIG_ATM_CLIP_NO_ICMP is not set
++CONFIG_ATM_LANE=m
++CONFIG_ATM_MPOA=m
++CONFIG_ATM_BR2684=m
++# CONFIG_ATM_BR2684_IPFILTER is not set
++CONFIG_BRIDGE=m
++CONFIG_VLAN_8021Q=m
++# CONFIG_DECNET is not set
++CONFIG_LLC=m
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++CONFIG_WAN_ROUTER=m
++CONFIG_NET_SCHED=y
++
++#
++# Queueing/Scheduling
++#
++CONFIG_NET_SCH_CBQ=m
++CONFIG_NET_SCH_HTB=m
++CONFIG_NET_SCH_HFSC=m
++CONFIG_NET_SCH_ATM=m
++CONFIG_NET_SCH_PRIO=m
++# CONFIG_NET_SCH_RR is not set
++CONFIG_NET_SCH_RED=m
++CONFIG_NET_SCH_SFQ=m
++CONFIG_NET_SCH_TEQL=m
++CONFIG_NET_SCH_TBF=m
++CONFIG_NET_SCH_GRED=m
++CONFIG_NET_SCH_DSMARK=m
++CONFIG_NET_SCH_NETEM=m
++
++#
++# Classification
++#
++CONFIG_NET_CLS=y
++# CONFIG_NET_CLS_BASIC is not set
++CONFIG_NET_CLS_TCINDEX=m
++CONFIG_NET_CLS_ROUTE4=m
++CONFIG_NET_CLS_ROUTE=y
++CONFIG_NET_CLS_FW=m
++CONFIG_NET_CLS_U32=m
++# CONFIG_CLS_U32_PERF is not set
++# CONFIG_CLS_U32_MARK is not set
++CONFIG_NET_CLS_RSVP=m
++CONFIG_NET_CLS_RSVP6=m
++# CONFIG_NET_CLS_FLOW is not set
++# CONFIG_NET_EMATCH is not set
++# CONFIG_NET_CLS_ACT is not set
++# CONFIG_NET_CLS_IND is not set
++CONFIG_NET_SCH_FIFO=y
++
++#
++# Network testing
++#
++CONFIG_NET_PKTGEN=m
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++CONFIG_FIB_RULES=y
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_OF_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++CONFIG_MTD_CFI_ADV_OPTIONS=y
++# CONFIG_MTD_CFI_NOSWAP is not set
++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
++CONFIG_MTD_CFI_LE_BYTE_SWAP=y
++# CONFIG_MTD_CFI_GEOMETRY is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_OTP is not set
++CONFIG_MTD_CFI_INTELEXT=y
++# CONFIG_MTD_CFI_AMDSTD is not set
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_PHYSMAP_OF=y
++# CONFIG_MTD_INTEL_VR_NOR is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++CONFIG_OF_DEVICE=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=m
++CONFIG_BLK_DEV_CRYPTOLOOP=m
++CONFIG_BLK_DEV_NBD=m
++# CONFIG_BLK_DEV_SX8 is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=4096
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++CONFIG_MD=y
++CONFIG_BLK_DEV_MD=y
++CONFIG_MD_LINEAR=y
++CONFIG_MD_RAID0=y
++CONFIG_MD_RAID1=y
++CONFIG_MD_RAID10=y
++# CONFIG_MD_RAID456 is not set
++CONFIG_MD_MULTIPATH=y
++CONFIG_MD_FAULTY=y
++CONFIG_BLK_DEV_DM=y
++# CONFIG_DM_DEBUG is not set
++CONFIG_DM_CRYPT=y
++CONFIG_DM_SNAPSHOT=y
++CONFIG_DM_MIRROR=y
++CONFIG_DM_ZERO=y
++# CONFIG_DM_MULTIPATH is not set
++# CONFIG_DM_DELAY is not set
++# CONFIG_DM_UEVENT is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_I2O is not set
++# CONFIG_MACINTOSH_DRIVERS is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++CONFIG_DUMMY=m
++CONFIG_BONDING=m
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++CONFIG_TUN=m
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++CONFIG_BROADCOM_PHY=y
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_HAPPYMEAL is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_CASSINI is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_NET_TULIP is not set
++# CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SIS190 is not set
++# CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++CONFIG_GIANFAR=y
++# CONFIG_GFAR_NAPI is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++# CONFIG_NETDEV_10000 is not set
++# CONFIG_TR is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++CONFIG_ATM_DRIVERS=y
++# CONFIG_ATM_DUMMY is not set
++# CONFIG_ATM_TCP is not set
++# CONFIG_ATM_LANAI is not set
++# CONFIG_ATM_ENI is not set
++# CONFIG_ATM_FIRESTREAM is not set
++# CONFIG_ATM_ZATM is not set
++# CONFIG_ATM_NICSTAR is not set
++# CONFIG_ATM_IDT77252 is not set
++# CONFIG_ATM_AMBASSADOR is not set
++# CONFIG_ATM_HORIZON is not set
++# CONFIG_ATM_IA is not set
++# CONFIG_ATM_FORE200E_MAYBE is not set
++# CONFIG_ATM_HE is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++CONFIG_PPP=m
++CONFIG_PPP_MULTILINK=y
++CONFIG_PPP_FILTER=y
++CONFIG_PPP_ASYNC=m
++CONFIG_PPP_SYNC_TTY=m
++CONFIG_PPP_DEFLATE=m
++CONFIG_PPP_BSDCOMP=m
++# CONFIG_PPP_MPPE is not set
++CONFIG_PPPOE=m
++CONFIG_PPPOATM=m
++# CONFIG_PPPOL2TP is not set
++CONFIG_SLIP=m
++CONFIG_SLIP_COMPRESSED=y
++CONFIG_SLHC=m
++CONFIG_SLIP_SMART=y
++CONFIG_SLIP_MODE_SLIP6=y
++CONFIG_NETCONSOLE=y
++# CONFIG_NETCONSOLE_DYNAMIC is not set
++CONFIG_NETPOLL=y
++CONFIG_NETPOLL_TRAP=y
++CONFIG_NET_POLL_CONTROLLER=y
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++# CONFIG_SERIAL_8250_PCI is not set
++CONFIG_SERIAL_8250_NR_UARTS=2
++CONFIG_SERIAL_8250_RUNTIME_UARTS=2
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_UARTLITE is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=m
++# CONFIG_NVRAM is not set
++# CONFIG_GEN_RTC is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_ALI1535 is not set
++# CONFIG_I2C_ALI1563 is not set
++# CONFIG_I2C_ALI15X3 is not set
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_I801 is not set
++# CONFIG_I2C_I810 is not set
++# CONFIG_I2C_PIIX4 is not set
++CONFIG_I2C_MPC=y
++# CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_PROSAVAGE is not set
++# CONFIG_I2C_SAVAGE4 is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_SIS5595 is not set
++# CONFIG_I2C_SIS630 is not set
++# CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_VIA is not set
++# CONFIG_I2C_VIAPRO is not set
++# CONFIG_I2C_VOODOO3 is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_DS1682 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_PCF8575 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++CONFIG_SOFT_WATCHDOG=m
++
++#
++# PCI-based Watchdog Cards
++#
++# CONFIG_PCIPCWATCHDOG is not set
++# CONFIG_WDTPCI is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++
++#
++# Graphics support
++#
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++CONFIG_VIDEO_OUTPUT_CONTROL=m
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++CONFIG_VGA_CONSOLE=y
++# CONFIG_VGACON_SOFT_SCROLLBACK is not set
++CONFIG_DUMMY_CONSOLE=y
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_INFINIBAND is not set
++# CONFIG_EDAC is not set
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++CONFIG_EXT2_FS_POSIX_ACL=y
++# CONFIG_EXT2_FS_SECURITY is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++CONFIG_EXT3_FS_POSIX_ACL=y
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_FS_MBCACHE=y
++CONFIG_REISERFS_FS=m
++# CONFIG_REISERFS_CHECK is not set
++# CONFIG_REISERFS_PROC_INFO is not set
++CONFIG_REISERFS_FS_XATTR=y
++CONFIG_REISERFS_FS_POSIX_ACL=y
++# CONFIG_REISERFS_FS_SECURITY is not set
++# CONFIG_JFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++CONFIG_OCFS2_FS=m
++CONFIG_OCFS2_DEBUG_MASKLOG=y
++# CONFIG_OCFS2_DEBUG_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++CONFIG_AUTOFS_FS=m
++CONFIG_AUTOFS4_FS=m
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_CONFIGFS_FS=m
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++CONFIG_MINIX_FS=m
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++CONFIG_ROMFS_FS=m
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++CONFIG_NFS_DIRECTIO=y
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++# CONFIG_SUNRPC_BIND34 is not set
++CONFIG_RPCSEC_GSS_KRB5=y
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++CONFIG_SMB_FS=m
++CONFIG_SMB_NLS_DEFAULT=y
++CONFIG_SMB_NLS_REMOTE="cp437"
++CONFIG_CIFS=m
++# CONFIG_CIFS_STATS is not set
++# CONFIG_CIFS_WEAK_PW_HASH is not set
++CONFIG_CIFS_XATTR=y
++CONFIG_CIFS_POSIX=y
++# CONFIG_CIFS_DEBUG2 is not set
++# CONFIG_CIFS_EXPERIMENTAL is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=m
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=m
++CONFIG_NLS_CODEPAGE_737=m
++CONFIG_NLS_CODEPAGE_775=m
++CONFIG_NLS_CODEPAGE_850=m
++CONFIG_NLS_CODEPAGE_852=m
++CONFIG_NLS_CODEPAGE_855=m
++CONFIG_NLS_CODEPAGE_857=m
++CONFIG_NLS_CODEPAGE_860=m
++CONFIG_NLS_CODEPAGE_861=m
++CONFIG_NLS_CODEPAGE_862=m
++CONFIG_NLS_CODEPAGE_863=m
++CONFIG_NLS_CODEPAGE_864=m
++CONFIG_NLS_CODEPAGE_865=m
++CONFIG_NLS_CODEPAGE_866=m
++CONFIG_NLS_CODEPAGE_869=m
++CONFIG_NLS_CODEPAGE_936=m
++CONFIG_NLS_CODEPAGE_950=m
++CONFIG_NLS_CODEPAGE_932=m
++CONFIG_NLS_CODEPAGE_949=m
++CONFIG_NLS_CODEPAGE_874=m
++CONFIG_NLS_ISO8859_8=m
++CONFIG_NLS_CODEPAGE_1250=m
++CONFIG_NLS_CODEPAGE_1251=m
++CONFIG_NLS_ASCII=m
++CONFIG_NLS_ISO8859_1=m
++CONFIG_NLS_ISO8859_2=m
++CONFIG_NLS_ISO8859_3=m
++CONFIG_NLS_ISO8859_4=m
++CONFIG_NLS_ISO8859_5=m
++CONFIG_NLS_ISO8859_6=m
++CONFIG_NLS_ISO8859_7=m
++CONFIG_NLS_ISO8859_9=m
++CONFIG_NLS_ISO8859_13=m
++CONFIG_NLS_ISO8859_14=m
++CONFIG_NLS_ISO8859_15=m
++CONFIG_NLS_KOI8_R=m
++CONFIG_NLS_KOI8_U=m
++CONFIG_NLS_UTF8=m
++# CONFIG_DLM is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=m
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++CONFIG_LIBCRC32C=m
++CONFIG_ZLIB_INFLATE=m
++CONFIG_ZLIB_DEFLATE=m
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++CONFIG_DEBUG_INFO=y
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++CONFIG_DEBUGGER=y
++# CONFIG_XMON is not set
++# CONFIG_VIRQ_DEBUG is not set
++# CONFIG_BDI_SWITCH is not set
++# CONFIG_PPC_EARLY_DEBUG is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++CONFIG_SECURITY=y
++CONFIG_SECURITY_NETWORK=y
++# CONFIG_SECURITY_NETWORK_XFRM is not set
++CONFIG_SECURITY_CAPABILITIES=y
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_AEAD=m
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_HASH=y
++CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_HMAC=y
++# CONFIG_CRYPTO_XCBC is not set
++CONFIG_CRYPTO_NULL=m
++CONFIG_CRYPTO_MD4=m
++CONFIG_CRYPTO_MD5=y
++CONFIG_CRYPTO_SHA1=m
++CONFIG_CRYPTO_SHA256=m
++CONFIG_CRYPTO_SHA512=m
++CONFIG_CRYPTO_WP512=m
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_PCBC=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++CONFIG_CRYPTO_BLOWFISH=m
++CONFIG_CRYPTO_TWOFISH=m
++CONFIG_CRYPTO_TWOFISH_COMMON=m
++CONFIG_CRYPTO_SERPENT=m
++CONFIG_CRYPTO_AES=m
++CONFIG_CRYPTO_CAST5=m
++CONFIG_CRYPTO_CAST6=m
++CONFIG_CRYPTO_TEA=m
++CONFIG_CRYPTO_ARC4=m
++CONFIG_CRYPTO_KHAZAD=m
++CONFIG_CRYPTO_ANUBIS=m
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++CONFIG_CRYPTO_DEFLATE=m
++CONFIG_CRYPTO_MICHAEL_MIC=m
++CONFIG_CRYPTO_CRC32C=m
++# CONFIG_CRYPTO_CAMELLIA is not set
++CONFIG_CRYPTO_TEST=m
++CONFIG_CRYPTO_AUTHENC=m
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_HIFN_795X is not set
++# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/sequoia_defconfig b/arch/powerpc/configs/sequoia_defconfig
+deleted file mode 100644
+index dd5d630..0000000
+--- a/arch/powerpc/configs/sequoia_defconfig
++++ /dev/null
+@@ -1,916 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc2
+-# Fri Feb 15 21:53:46 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-CONFIG_44x=y
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-CONFIG_4xx=y
+-CONFIG_BOOKE=y
+-CONFIG_PTE_64BIT=y
+-CONFIG_PHYS_64BIT=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-# CONFIG_DEFAULT_UIMAGE is not set
+-CONFIG_PPC_DCR_NATIVE=y
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_PPC_DCR=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-# CONFIG_FAIR_GROUP_SCHED is not set
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_ALL is not set
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-# CONFIG_PPC4xx_PCI_EXPRESS is not set
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-# CONFIG_BAMBOO is not set
+-# CONFIG_EBONY is not set
+-CONFIG_SEQUOIA=y
+-# CONFIG_TAISHAN is not set
+-# CONFIG_KATMAI is not set
+-# CONFIG_RAINIER is not set
+-# CONFIG_WARP is not set
+-CONFIG_440EPX=y
+-# CONFIG_IPIC is not set
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-CONFIG_TICK_ONESHOT=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_RCU_TRACE=y
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_MATH_EMULATION is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-CONFIG_RESOURCES_64BIT=y
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-CONFIG_CMDLINE_BOOL=y
+-CONFIG_CMDLINE=""
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x01000000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+-# CONFIG_INET_XFRM_MODE_BEET is not set
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-CONFIG_CONNECTOR=y
+-CONFIG_PROC_EVENTS=y
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-CONFIG_MTD_CMDLINE_PARTS=y
+-CONFIG_MTD_OF_PARTS=y
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-# CONFIG_MTD_BLKDEVS is not set
+-# CONFIG_MTD_BLOCK is not set
+-# CONFIG_MTD_BLOCK_RO is not set
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-CONFIG_MTD_JEDECPROBE=y
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-CONFIG_MTD_CFI_INTELEXT=y
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-CONFIG_MTD_PHYSMAP_OF=y
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=35000
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-# CONFIG_XILINX_SYSACE is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-# CONFIG_PHYLIB is not set
+-CONFIG_NET_ETHERNET=y
+-# CONFIG_MII is not set
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-CONFIG_IBM_NEW_EMAC=y
+-CONFIG_IBM_NEW_EMAC_RXB=128
+-CONFIG_IBM_NEW_EMAC_TXB=64
+-CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+-CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+-CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+-# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+-CONFIG_IBM_NEW_EMAC_ZMII=y
+-CONFIG_IBM_NEW_EMAC_RGMII=y
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-CONFIG_IBM_NEW_EMAC_EMAC4=y
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-# CONFIG_SERIAL_8250_PCI is not set
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-CONFIG_SERIAL_8250_EXTENDED=y
+-# CONFIG_SERIAL_8250_MANY_PORTS is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+-# CONFIG_SERIAL_8250_RSA is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_SERIAL_OF_PLATFORM=y
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-CONFIG_THERMAL=y
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_JFFS2_FS=y
+-CONFIG_JFFS2_FS_DEBUG=0
+-CONFIG_JFFS2_FS_WRITEBUFFER=y
+-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+-# CONFIG_JFFS2_SUMMARY is not set
+-# CONFIG_JFFS2_FS_XATTR is not set
+-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+-CONFIG_JFFS2_ZLIB=y
+-# CONFIG_JFFS2_LZO is not set
+-CONFIG_JFFS2_RTIME=y
+-# CONFIG_JFFS2_RUBIN is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_ZLIB_DEFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_MAGIC_SYSRQ=y
+-# CONFIG_UNUSED_SYMBOLS is not set
+-CONFIG_DEBUG_FS=y
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-CONFIG_DEBUGGER=y
+-# CONFIG_KGDB is not set
+-# CONFIG_XMON is not set
+-# CONFIG_VIRQ_DEBUG is not set
+-# CONFIG_BDI_SWITCH is not set
+-CONFIG_PPC_EARLY_DEBUG=y
+-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
+-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
+-# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
+-# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
+-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
+-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+-# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
+-# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
+-CONFIG_PPC_EARLY_DEBUG_44x=y
+-# CONFIG_PPC_EARLY_DEBUG_40x is not set
+-# CONFIG_PPC_EARLY_DEBUG_CPM is not set
+-CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW=0xef600300
+-CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH=0x1
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=y
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=y
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/stx_gp3_defconfig b/arch/powerpc/configs/stx_gp3_defconfig
+deleted file mode 100644
+index 1d303c4..0000000
+--- a/arch/powerpc/configs/stx_gp3_defconfig
++++ /dev/null
+@@ -1,1253 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:42 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_ALL is not set
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-# CONFIG_MODULE_UNLOAD is not set
+-CONFIG_MODVERSIONS=y
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-# CONFIG_DEFAULT_AS is not set
+-# CONFIG_DEFAULT_DEADLINE is not set
+-CONFIG_DEFAULT_CFQ=y
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="cfq"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-# CONFIG_MPC8540_ADS is not set
+-# CONFIG_MPC8560_ADS is not set
+-# CONFIG_MPC85xx_CDS is not set
+-# CONFIG_MPC85xx_MDS is not set
+-# CONFIG_MPC85xx_DS is not set
+-CONFIG_STX_GP3=y
+-# CONFIG_TQM8540 is not set
+-# CONFIG_TQM8541 is not set
+-# CONFIG_TQM8555 is not set
+-# CONFIG_TQM8560 is not set
+-# CONFIG_SBC8548 is not set
+-# CONFIG_SBC8560 is not set
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-CONFIG_CPM2=y
+-CONFIG_PPC_CPM_NEW_BINDING=y
+-# CONFIG_FSL_ULI1575 is not set
+-CONFIG_CPM=y
+-
+-#
+-# Kernel options
+-#
+-CONFIG_HIGHMEM=y
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-CONFIG_BINFMT_MISC=m
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_FSL_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-# CONFIG_IP_PNP_DHCP is not set
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IP_VS is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-CONFIG_NETFILTER=y
+-# CONFIG_NETFILTER_DEBUG is not set
+-CONFIG_NETFILTER_ADVANCED=y
+-
+-#
+-# Core Netfilter Configuration
+-#
+-# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+-# CONFIG_NETFILTER_NETLINK_LOG is not set
+-# CONFIG_NF_CONNTRACK is not set
+-CONFIG_NETFILTER_XTABLES=m
+-# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+-# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+-# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+-# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+-# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+-# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+-# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+-# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+-# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+-# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+-# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+-# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+-# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+-# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+-# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+-# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+-# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+-# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+-# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+-# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+-# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+-# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+-# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+-# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+-# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+-# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+-# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+-# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+-# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+-
+-#
+-# IP: Netfilter Configuration
+-#
+-# CONFIG_IP_NF_QUEUE is not set
+-CONFIG_IP_NF_IPTABLES=m
+-# CONFIG_IP_NF_MATCH_RECENT is not set
+-# CONFIG_IP_NF_MATCH_ECN is not set
+-# CONFIG_IP_NF_MATCH_AH is not set
+-# CONFIG_IP_NF_MATCH_TTL is not set
+-# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+-CONFIG_IP_NF_FILTER=m
+-# CONFIG_IP_NF_TARGET_REJECT is not set
+-# CONFIG_IP_NF_TARGET_LOG is not set
+-# CONFIG_IP_NF_TARGET_ULOG is not set
+-# CONFIG_IP_NF_MANGLE is not set
+-# CONFIG_IP_NF_RAW is not set
+-# CONFIG_IP_NF_ARPTABLES is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-CONFIG_NET_PKTGEN=y
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-CONFIG_PARPORT=m
+-CONFIG_PARPORT_PC=m
+-# CONFIG_PARPORT_PC_FIFO is not set
+-# CONFIG_PARPORT_PC_SUPERIO is not set
+-# CONFIG_PARPORT_GSC is not set
+-# CONFIG_PARPORT_AX88796 is not set
+-# CONFIG_PARPORT_1284 is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_PARIDE is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=m
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-CONFIG_BLK_DEV_NBD=m
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-CONFIG_IDE=y
+-CONFIG_IDE_MAX_HWIFS=4
+-CONFIG_BLK_DEV_IDE=y
+-
+-#
+-# Please see Documentation/ide/ide.txt for help/info on IDE drives
+-#
+-# CONFIG_BLK_DEV_IDE_SATA is not set
+-CONFIG_BLK_DEV_IDEDISK=y
+-# CONFIG_IDEDISK_MULTI_MODE is not set
+-CONFIG_BLK_DEV_IDECD=m
+-CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
+-# CONFIG_BLK_DEV_IDETAPE is not set
+-# CONFIG_BLK_DEV_IDEFLOPPY is not set
+-# CONFIG_BLK_DEV_IDESCSI is not set
+-# CONFIG_IDE_TASK_IOCTL is not set
+-CONFIG_IDE_PROC_FS=y
+-
+-#
+-# IDE chipset support/bugfixes
+-#
+-CONFIG_IDE_GENERIC=y
+-# CONFIG_BLK_DEV_PLATFORM is not set
+-
+-#
+-# PCI IDE chipsets support
+-#
+-# CONFIG_BLK_DEV_GENERIC is not set
+-# CONFIG_BLK_DEV_OPTI621 is not set
+-# CONFIG_BLK_DEV_AEC62XX is not set
+-# CONFIG_BLK_DEV_ALI15X3 is not set
+-# CONFIG_BLK_DEV_AMD74XX is not set
+-# CONFIG_BLK_DEV_CMD64X is not set
+-# CONFIG_BLK_DEV_TRIFLEX is not set
+-# CONFIG_BLK_DEV_CY82C693 is not set
+-# CONFIG_BLK_DEV_CS5520 is not set
+-# CONFIG_BLK_DEV_CS5530 is not set
+-# CONFIG_BLK_DEV_HPT34X is not set
+-# CONFIG_BLK_DEV_HPT366 is not set
+-# CONFIG_BLK_DEV_JMICRON is not set
+-# CONFIG_BLK_DEV_SC1200 is not set
+-# CONFIG_BLK_DEV_PIIX is not set
+-# CONFIG_BLK_DEV_IT8213 is not set
+-# CONFIG_BLK_DEV_IT821X is not set
+-# CONFIG_BLK_DEV_NS87415 is not set
+-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+-# CONFIG_BLK_DEV_SVWKS is not set
+-# CONFIG_BLK_DEV_SIIMAGE is not set
+-# CONFIG_BLK_DEV_SL82C105 is not set
+-# CONFIG_BLK_DEV_SLC90E66 is not set
+-# CONFIG_BLK_DEV_TRM290 is not set
+-# CONFIG_BLK_DEV_VIA82CXXX is not set
+-# CONFIG_BLK_DEV_TC86C001 is not set
+-# CONFIG_BLK_DEV_IDEDMA is not set
+-CONFIG_IDE_ARCH_OBSOLETE_INIT=y
+-# CONFIG_BLK_DEV_HD is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=m
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-CONFIG_BLK_DEV_SD=m
+-CONFIG_CHR_DEV_ST=m
+-# CONFIG_CHR_DEV_OSST is not set
+-CONFIG_BLK_DEV_SR=m
+-# CONFIG_BLK_DEV_SR_VENDOR is not set
+-CONFIG_CHR_DEV_SG=m
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-CONFIG_SCSI_MULTI_LUN=y
+-CONFIG_SCSI_CONSTANTS=y
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-# CONFIG_SCSI_SPI_ATTRS is not set
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-CONFIG_SCSI_LOWLEVEL=y
+-# CONFIG_ISCSI_TCP is not set
+-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+-# CONFIG_SCSI_3W_9XXX is not set
+-# CONFIG_SCSI_ACARD is not set
+-# CONFIG_SCSI_AACRAID is not set
+-# CONFIG_SCSI_AIC7XXX is not set
+-# CONFIG_SCSI_AIC7XXX_OLD is not set
+-# CONFIG_SCSI_AIC79XX is not set
+-# CONFIG_SCSI_AIC94XX is not set
+-# CONFIG_SCSI_DPT_I2O is not set
+-# CONFIG_SCSI_ADVANSYS is not set
+-# CONFIG_SCSI_ARCMSR is not set
+-# CONFIG_MEGARAID_NEWGEN is not set
+-# CONFIG_MEGARAID_LEGACY is not set
+-# CONFIG_MEGARAID_SAS is not set
+-# CONFIG_SCSI_HPTIOP is not set
+-# CONFIG_SCSI_BUSLOGIC is not set
+-# CONFIG_SCSI_DMX3191D is not set
+-# CONFIG_SCSI_EATA is not set
+-# CONFIG_SCSI_FUTURE_DOMAIN is not set
+-# CONFIG_SCSI_GDTH is not set
+-# CONFIG_SCSI_IPS is not set
+-# CONFIG_SCSI_INITIO is not set
+-# CONFIG_SCSI_INIA100 is not set
+-# CONFIG_SCSI_PPA is not set
+-# CONFIG_SCSI_IMM is not set
+-# CONFIG_SCSI_MVSAS is not set
+-# CONFIG_SCSI_STEX is not set
+-# CONFIG_SCSI_SYM53C8XX_2 is not set
+-# CONFIG_SCSI_QLOGIC_1280 is not set
+-# CONFIG_SCSI_QLA_FC is not set
+-# CONFIG_SCSI_QLA_ISCSI is not set
+-# CONFIG_SCSI_LPFC is not set
+-# CONFIG_SCSI_DC395x is not set
+-# CONFIG_SCSI_DC390T is not set
+-# CONFIG_SCSI_NSP32 is not set
+-# CONFIG_SCSI_DEBUG is not set
+-# CONFIG_SCSI_SRP is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-CONFIG_MARVELL_PHY=y
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-# CONFIG_MII is not set
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-# CONFIG_NET_POCKET is not set
+-# CONFIG_FS_ENET is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PLIP is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NET_FC is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-CONFIG_INPUT_MOUSEDEV=y
+-CONFIG_INPUT_MOUSEDEV_PSAUX=y
+-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1280
+-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=1024
+-CONFIG_INPUT_JOYDEV=m
+-CONFIG_INPUT_EVDEV=m
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-CONFIG_INPUT_KEYBOARD=y
+-CONFIG_KEYBOARD_ATKBD=y
+-# CONFIG_KEYBOARD_SUNKBD is not set
+-# CONFIG_KEYBOARD_LKKBD is not set
+-# CONFIG_KEYBOARD_XTKBD is not set
+-# CONFIG_KEYBOARD_NEWTON is not set
+-# CONFIG_KEYBOARD_STOWAWAY is not set
+-CONFIG_INPUT_MOUSE=y
+-CONFIG_MOUSE_PS2=y
+-CONFIG_MOUSE_PS2_ALPS=y
+-CONFIG_MOUSE_PS2_LOGIPS2PP=y
+-CONFIG_MOUSE_PS2_SYNAPTICS=y
+-CONFIG_MOUSE_PS2_LIFEBOOK=y
+-CONFIG_MOUSE_PS2_TRACKPOINT=y
+-# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+-# CONFIG_MOUSE_SERIAL is not set
+-# CONFIG_MOUSE_APPLETOUCH is not set
+-# CONFIG_MOUSE_VSXXXAA is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-CONFIG_SERIO=y
+-CONFIG_SERIO_I8042=y
+-CONFIG_SERIO_SERPORT=y
+-# CONFIG_SERIO_PARKBD is not set
+-# CONFIG_SERIO_PCIPS2 is not set
+-CONFIG_SERIO_LIBPS2=y
+-# CONFIG_SERIO_RAW is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-# CONFIG_SERIAL_8250 is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-CONFIG_SERIAL_CPM=y
+-CONFIG_SERIAL_CPM_CONSOLE=y
+-# CONFIG_SERIAL_CPM_SCC1 is not set
+-CONFIG_SERIAL_CPM_SCC2=y
+-# CONFIG_SERIAL_CPM_SCC3 is not set
+-# CONFIG_SERIAL_CPM_SCC4 is not set
+-# CONFIG_SERIAL_CPM_SMC1 is not set
+-# CONFIG_SERIAL_CPM_SMC2 is not set
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-CONFIG_PRINTER=m
+-# CONFIG_LP_CONSOLE is not set
+-# CONFIG_PPDEV is not set
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=m
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=m
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=m
+-
+-#
+-# I2C Algorithms
+-#
+-CONFIG_I2C_ALGOBIT=m
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-# CONFIG_I2C_MPC is not set
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-CONFIG_AGP=m
+-CONFIG_DRM=m
+-# CONFIG_DRM_TDFX is not set
+-# CONFIG_DRM_R128 is not set
+-# CONFIG_DRM_RADEON is not set
+-# CONFIG_DRM_MGA is not set
+-# CONFIG_DRM_SIS is not set
+-# CONFIG_DRM_VIA is not set
+-# CONFIG_DRM_SAVAGE is not set
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-CONFIG_SOUND=m
+-
+-#
+-# Advanced Linux Sound Architecture
+-#
+-# CONFIG_SND is not set
+-
+-#
+-# Open Sound System
+-#
+-# CONFIG_SOUND_PRIME is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-# CONFIG_AUXDISPLAY is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-CONFIG_AUTOFS_FS=m
+-CONFIG_AUTOFS4_FS=y
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-CONFIG_ISO9660_FS=m
+-# CONFIG_JOLIET is not set
+-# CONFIG_ZISOFS is not set
+-CONFIG_UDF_FS=m
+-CONFIG_UDF_NLS=y
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-CONFIG_FAT_FS=m
+-CONFIG_MSDOS_FS=m
+-CONFIG_VFAT_FS=m
+-CONFIG_FAT_DEFAULT_CODEPAGE=437
+-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-# CONFIG_PROC_KCORE is not set
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_CRAMFS=m
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-CONFIG_SMB_FS=m
+-# CONFIG_SMB_NLS_DEFAULT is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-CONFIG_NLS=y
+-CONFIG_NLS_DEFAULT="iso8859-1"
+-# CONFIG_NLS_CODEPAGE_437 is not set
+-# CONFIG_NLS_CODEPAGE_737 is not set
+-# CONFIG_NLS_CODEPAGE_775 is not set
+-# CONFIG_NLS_CODEPAGE_850 is not set
+-# CONFIG_NLS_CODEPAGE_852 is not set
+-# CONFIG_NLS_CODEPAGE_855 is not set
+-# CONFIG_NLS_CODEPAGE_857 is not set
+-# CONFIG_NLS_CODEPAGE_860 is not set
+-# CONFIG_NLS_CODEPAGE_861 is not set
+-# CONFIG_NLS_CODEPAGE_862 is not set
+-# CONFIG_NLS_CODEPAGE_863 is not set
+-# CONFIG_NLS_CODEPAGE_864 is not set
+-# CONFIG_NLS_CODEPAGE_865 is not set
+-# CONFIG_NLS_CODEPAGE_866 is not set
+-# CONFIG_NLS_CODEPAGE_869 is not set
+-# CONFIG_NLS_CODEPAGE_936 is not set
+-# CONFIG_NLS_CODEPAGE_950 is not set
+-# CONFIG_NLS_CODEPAGE_932 is not set
+-# CONFIG_NLS_CODEPAGE_949 is not set
+-# CONFIG_NLS_CODEPAGE_874 is not set
+-# CONFIG_NLS_ISO8859_8 is not set
+-# CONFIG_NLS_CODEPAGE_1250 is not set
+-# CONFIG_NLS_CODEPAGE_1251 is not set
+-# CONFIG_NLS_ASCII is not set
+-# CONFIG_NLS_ISO8859_1 is not set
+-# CONFIG_NLS_ISO8859_2 is not set
+-# CONFIG_NLS_ISO8859_3 is not set
+-# CONFIG_NLS_ISO8859_4 is not set
+-# CONFIG_NLS_ISO8859_5 is not set
+-# CONFIG_NLS_ISO8859_6 is not set
+-# CONFIG_NLS_ISO8859_7 is not set
+-# CONFIG_NLS_ISO8859_9 is not set
+-# CONFIG_NLS_ISO8859_13 is not set
+-# CONFIG_NLS_ISO8859_14 is not set
+-# CONFIG_NLS_ISO8859_15 is not set
+-# CONFIG_NLS_KOI8_R is not set
+-# CONFIG_NLS_KOI8_U is not set
+-# CONFIG_NLS_UTF8 is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-CONFIG_CRC_CCITT=y
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=m
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_HIGHMEM is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_KGDB_CONSOLE is not set
+-CONFIG_BDI_SWITCH=y
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-# CONFIG_CRYPTO_MANAGER is not set
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-# CONFIG_CRYPTO_MD5 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-# CONFIG_CRYPTO_CBC is not set
+-# CONFIG_CRYPTO_PCBC is not set
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+-CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/taishan_defconfig b/arch/powerpc/configs/taishan_defconfig
+deleted file mode 100644
+index 087aedc..0000000
+--- a/arch/powerpc/configs/taishan_defconfig
++++ /dev/null
+@@ -1,815 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc2
+-# Fri Feb 15 21:40:44 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-CONFIG_44x=y
+-# CONFIG_E200 is not set
+-CONFIG_4xx=y
+-CONFIG_BOOKE=y
+-CONFIG_PTE_64BIT=y
+-CONFIG_PHYS_64BIT=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-# CONFIG_DEFAULT_UIMAGE is not set
+-CONFIG_PPC_DCR_NATIVE=y
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_PPC_DCR=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_ALL is not set
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-# CONFIG_PPC4xx_PCI_EXPRESS is not set
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-# CONFIG_BAMBOO is not set
+-# CONFIG_EBONY is not set
+-# CONFIG_SEQUOIA is not set
+-CONFIG_TAISHAN=y
+-# CONFIG_KATMAI is not set
+-# CONFIG_RAINIER is not set
+-# CONFIG_WARP is not set
+-CONFIG_440GX=y
+-# CONFIG_IPIC is not set
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_RCU_TRACE=y
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_MATH_EMULATION is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-CONFIG_RESOURCES_64BIT=y
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-CONFIG_CMDLINE_BOOL=y
+-CONFIG_CMDLINE=""
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x01000000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+-# CONFIG_INET_XFRM_MODE_BEET is not set
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-CONFIG_CONNECTOR=y
+-CONFIG_PROC_EVENTS=y
+-# CONFIG_MTD is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=35000
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-# CONFIG_XILINX_SYSACE is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-CONFIG_MACINTOSH_DRIVERS=y
+-# CONFIG_MAC_EMUMOUSEBTN is not set
+-# CONFIG_WINDFARM is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-# CONFIG_PHYLIB is not set
+-CONFIG_NET_ETHERNET=y
+-# CONFIG_MII is not set
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-CONFIG_IBM_NEW_EMAC=y
+-CONFIG_IBM_NEW_EMAC_RXB=128
+-CONFIG_IBM_NEW_EMAC_TXB=64
+-CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+-CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+-CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+-# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+-CONFIG_IBM_NEW_EMAC_ZMII=y
+-CONFIG_IBM_NEW_EMAC_RGMII=y
+-CONFIG_IBM_NEW_EMAC_TAH=y
+-CONFIG_IBM_NEW_EMAC_EMAC4=y
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-# CONFIG_SERIAL_8250_PCI is not set
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-CONFIG_SERIAL_8250_EXTENDED=y
+-# CONFIG_SERIAL_8250_MANY_PORTS is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+-# CONFIG_SERIAL_8250_RSA is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_SERIAL_OF_PLATFORM=y
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-CONFIG_THERMAL=y
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_MAGIC_SYSRQ=y
+-# CONFIG_UNUSED_SYMBOLS is not set
+-CONFIG_DEBUG_FS=y
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-CONFIG_DEBUGGER=y
+-# CONFIG_KGDB is not set
+-# CONFIG_XMON is not set
+-# CONFIG_VIRQ_DEBUG is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=y
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=y
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/tqm8540_defconfig b/arch/powerpc/configs/tqm8540_defconfig
+deleted file mode 100644
+index d39ee3b..0000000
+--- a/arch/powerpc/configs/tqm8540_defconfig
++++ /dev/null
+@@ -1,1097 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:43 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-# CONFIG_HOTPLUG is not set
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-# CONFIG_MODULES is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-# CONFIG_MPC8540_ADS is not set
+-# CONFIG_MPC8560_ADS is not set
+-# CONFIG_MPC85xx_CDS is not set
+-# CONFIG_MPC85xx_MDS is not set
+-# CONFIG_MPC85xx_DS is not set
+-# CONFIG_STX_GP3 is not set
+-CONFIG_TQM8540=y
+-# CONFIG_TQM8541 is not set
+-# CONFIG_TQM8555 is not set
+-# CONFIG_TQM8560 is not set
+-# CONFIG_SBC8548 is not set
+-# CONFIG_SBC8560 is not set
+-CONFIG_TQM85xx=y
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_CPM2 is not set
+-CONFIG_PPC_CPM_NEW_BINDING=y
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-# CONFIG_PROC_DEVICETREE is not set
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_FSL_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-CONFIG_MTD_CONCAT=y
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-CONFIG_MTD_CMDLINE_PARTS=y
+-# CONFIG_MTD_OF_PARTS is not set
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=y
+-CONFIG_MTD_BLOCK=y
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-# CONFIG_MTD_JEDECPROBE is not set
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-# CONFIG_MTD_PHYSMAP_OF is not set
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-CONFIG_IDE=y
+-CONFIG_IDE_MAX_HWIFS=4
+-CONFIG_BLK_DEV_IDE=y
+-
+-#
+-# Please see Documentation/ide/ide.txt for help/info on IDE drives
+-#
+-# CONFIG_BLK_DEV_IDE_SATA is not set
+-CONFIG_BLK_DEV_IDEDISK=y
+-# CONFIG_IDEDISK_MULTI_MODE is not set
+-# CONFIG_BLK_DEV_IDECD is not set
+-# CONFIG_BLK_DEV_IDETAPE is not set
+-# CONFIG_BLK_DEV_IDEFLOPPY is not set
+-# CONFIG_IDE_TASK_IOCTL is not set
+-CONFIG_IDE_PROC_FS=y
+-
+-#
+-# IDE chipset support/bugfixes
+-#
+-CONFIG_IDE_GENERIC=y
+-# CONFIG_BLK_DEV_PLATFORM is not set
+-CONFIG_BLK_DEV_IDEDMA_SFF=y
+-
+-#
+-# PCI IDE chipsets support
+-#
+-CONFIG_BLK_DEV_IDEPCI=y
+-CONFIG_IDEPCI_PCIBUS_ORDER=y
+-# CONFIG_BLK_DEV_OFFBOARD is not set
+-CONFIG_BLK_DEV_GENERIC=y
+-# CONFIG_BLK_DEV_OPTI621 is not set
+-CONFIG_BLK_DEV_IDEDMA_PCI=y
+-# CONFIG_BLK_DEV_AEC62XX is not set
+-# CONFIG_BLK_DEV_ALI15X3 is not set
+-# CONFIG_BLK_DEV_AMD74XX is not set
+-# CONFIG_BLK_DEV_CMD64X is not set
+-# CONFIG_BLK_DEV_TRIFLEX is not set
+-# CONFIG_BLK_DEV_CY82C693 is not set
+-# CONFIG_BLK_DEV_CS5520 is not set
+-# CONFIG_BLK_DEV_CS5530 is not set
+-# CONFIG_BLK_DEV_HPT34X is not set
+-# CONFIG_BLK_DEV_HPT366 is not set
+-# CONFIG_BLK_DEV_JMICRON is not set
+-# CONFIG_BLK_DEV_SC1200 is not set
+-# CONFIG_BLK_DEV_PIIX is not set
+-# CONFIG_BLK_DEV_IT8213 is not set
+-# CONFIG_BLK_DEV_IT821X is not set
+-# CONFIG_BLK_DEV_NS87415 is not set
+-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+-# CONFIG_BLK_DEV_SVWKS is not set
+-# CONFIG_BLK_DEV_SIIMAGE is not set
+-# CONFIG_BLK_DEV_SL82C105 is not set
+-# CONFIG_BLK_DEV_SLC90E66 is not set
+-# CONFIG_BLK_DEV_TRM290 is not set
+-CONFIG_BLK_DEV_VIA82CXXX=y
+-# CONFIG_BLK_DEV_TC86C001 is not set
+-CONFIG_BLK_DEV_IDEDMA=y
+-CONFIG_IDE_ARCH_OBSOLETE_INIT=y
+-# CONFIG_BLK_DEV_HD is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-CONFIG_NET_PCI=y
+-# CONFIG_PCNET32 is not set
+-# CONFIG_AMD8111_ETH is not set
+-# CONFIG_ADAPTEC_STARFIRE is not set
+-# CONFIG_B44 is not set
+-# CONFIG_FORCEDETH is not set
+-# CONFIG_EEPRO100 is not set
+-CONFIG_E100=y
+-# CONFIG_FEALNX is not set
+-# CONFIG_NATSEMI is not set
+-# CONFIG_NE2K_PCI is not set
+-# CONFIG_8139CP is not set
+-# CONFIG_8139TOO is not set
+-# CONFIG_R6040 is not set
+-# CONFIG_SIS900 is not set
+-# CONFIG_EPIC100 is not set
+-# CONFIG_SUNDANCE is not set
+-# CONFIG_TLAN is not set
+-# CONFIG_VIA_RHINE is not set
+-# CONFIG_SC92031 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-CONFIG_SENSORS_LM75=y
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-CONFIG_HWMON_DEBUG_CHIP=y
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_JFFS2_FS=y
+-CONFIG_JFFS2_FS_DEBUG=0
+-CONFIG_JFFS2_FS_WRITEBUFFER=y
+-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+-# CONFIG_JFFS2_SUMMARY is not set
+-# CONFIG_JFFS2_FS_XATTR is not set
+-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+-CONFIG_JFFS2_ZLIB=y
+-# CONFIG_JFFS2_LZO is not set
+-CONFIG_JFFS2_RTIME=y
+-# CONFIG_JFFS2_RUBIN is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-# CONFIG_NFS_V3 is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_ZLIB_DEFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-# CONFIG_CRYPTO_MANAGER is not set
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-# CONFIG_CRYPTO_MD5 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-# CONFIG_CRYPTO_CBC is not set
+-# CONFIG_CRYPTO_PCBC is not set
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/tqm8541_defconfig b/arch/powerpc/configs/tqm8541_defconfig
+deleted file mode 100644
+index cbf6ad2..0000000
+--- a/arch/powerpc/configs/tqm8541_defconfig
++++ /dev/null
+@@ -1,1109 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:44 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-# CONFIG_HOTPLUG is not set
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-# CONFIG_MODULES is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-# CONFIG_MPC8540_ADS is not set
+-# CONFIG_MPC8560_ADS is not set
+-# CONFIG_MPC85xx_CDS is not set
+-# CONFIG_MPC85xx_MDS is not set
+-# CONFIG_MPC85xx_DS is not set
+-# CONFIG_STX_GP3 is not set
+-# CONFIG_TQM8540 is not set
+-CONFIG_TQM8541=y
+-# CONFIG_TQM8555 is not set
+-# CONFIG_TQM8560 is not set
+-# CONFIG_SBC8548 is not set
+-# CONFIG_SBC8560 is not set
+-CONFIG_TQM85xx=y
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-CONFIG_CPM2=y
+-CONFIG_PPC_CPM_NEW_BINDING=y
+-# CONFIG_FSL_ULI1575 is not set
+-CONFIG_CPM=y
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-# CONFIG_PROC_DEVICETREE is not set
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_FSL_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-CONFIG_MTD_CONCAT=y
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-CONFIG_MTD_CMDLINE_PARTS=y
+-# CONFIG_MTD_OF_PARTS is not set
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=y
+-CONFIG_MTD_BLOCK=y
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-# CONFIG_MTD_JEDECPROBE is not set
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-# CONFIG_MTD_PHYSMAP_OF is not set
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-CONFIG_IDE=y
+-CONFIG_IDE_MAX_HWIFS=4
+-CONFIG_BLK_DEV_IDE=y
+-
+-#
+-# Please see Documentation/ide/ide.txt for help/info on IDE drives
+-#
+-# CONFIG_BLK_DEV_IDE_SATA is not set
+-CONFIG_BLK_DEV_IDEDISK=y
+-# CONFIG_IDEDISK_MULTI_MODE is not set
+-# CONFIG_BLK_DEV_IDECD is not set
+-# CONFIG_BLK_DEV_IDETAPE is not set
+-# CONFIG_BLK_DEV_IDEFLOPPY is not set
+-# CONFIG_IDE_TASK_IOCTL is not set
+-CONFIG_IDE_PROC_FS=y
+-
+-#
+-# IDE chipset support/bugfixes
+-#
+-CONFIG_IDE_GENERIC=y
+-# CONFIG_BLK_DEV_PLATFORM is not set
+-CONFIG_BLK_DEV_IDEDMA_SFF=y
+-
+-#
+-# PCI IDE chipsets support
+-#
+-CONFIG_BLK_DEV_IDEPCI=y
+-CONFIG_IDEPCI_PCIBUS_ORDER=y
+-# CONFIG_BLK_DEV_OFFBOARD is not set
+-CONFIG_BLK_DEV_GENERIC=y
+-# CONFIG_BLK_DEV_OPTI621 is not set
+-CONFIG_BLK_DEV_IDEDMA_PCI=y
+-# CONFIG_BLK_DEV_AEC62XX is not set
+-# CONFIG_BLK_DEV_ALI15X3 is not set
+-# CONFIG_BLK_DEV_AMD74XX is not set
+-# CONFIG_BLK_DEV_CMD64X is not set
+-# CONFIG_BLK_DEV_TRIFLEX is not set
+-# CONFIG_BLK_DEV_CY82C693 is not set
+-# CONFIG_BLK_DEV_CS5520 is not set
+-# CONFIG_BLK_DEV_CS5530 is not set
+-# CONFIG_BLK_DEV_HPT34X is not set
+-# CONFIG_BLK_DEV_HPT366 is not set
+-# CONFIG_BLK_DEV_JMICRON is not set
+-# CONFIG_BLK_DEV_SC1200 is not set
+-# CONFIG_BLK_DEV_PIIX is not set
+-# CONFIG_BLK_DEV_IT8213 is not set
+-# CONFIG_BLK_DEV_IT821X is not set
+-# CONFIG_BLK_DEV_NS87415 is not set
+-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+-# CONFIG_BLK_DEV_SVWKS is not set
+-# CONFIG_BLK_DEV_SIIMAGE is not set
+-# CONFIG_BLK_DEV_SL82C105 is not set
+-# CONFIG_BLK_DEV_SLC90E66 is not set
+-# CONFIG_BLK_DEV_TRM290 is not set
+-CONFIG_BLK_DEV_VIA82CXXX=y
+-# CONFIG_BLK_DEV_TC86C001 is not set
+-CONFIG_BLK_DEV_IDEDMA=y
+-CONFIG_IDE_ARCH_OBSOLETE_INIT=y
+-# CONFIG_BLK_DEV_HD is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-CONFIG_NET_PCI=y
+-# CONFIG_PCNET32 is not set
+-# CONFIG_AMD8111_ETH is not set
+-# CONFIG_ADAPTEC_STARFIRE is not set
+-# CONFIG_B44 is not set
+-# CONFIG_FORCEDETH is not set
+-# CONFIG_EEPRO100 is not set
+-CONFIG_E100=y
+-# CONFIG_FEALNX is not set
+-# CONFIG_NATSEMI is not set
+-# CONFIG_NE2K_PCI is not set
+-# CONFIG_8139CP is not set
+-# CONFIG_8139TOO is not set
+-# CONFIG_R6040 is not set
+-# CONFIG_SIS900 is not set
+-# CONFIG_EPIC100 is not set
+-# CONFIG_SUNDANCE is not set
+-# CONFIG_TLAN is not set
+-# CONFIG_VIA_RHINE is not set
+-# CONFIG_SC92031 is not set
+-# CONFIG_FS_ENET is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-CONFIG_SERIAL_CPM=y
+-CONFIG_SERIAL_CPM_CONSOLE=y
+-CONFIG_SERIAL_CPM_SCC1=y
+-# CONFIG_SERIAL_CPM_SCC2 is not set
+-# CONFIG_SERIAL_CPM_SCC3 is not set
+-# CONFIG_SERIAL_CPM_SCC4 is not set
+-# CONFIG_SERIAL_CPM_SMC1 is not set
+-# CONFIG_SERIAL_CPM_SMC2 is not set
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-CONFIG_SENSORS_LM75=y
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-CONFIG_HWMON_DEBUG_CHIP=y
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_JFFS2_FS=y
+-CONFIG_JFFS2_FS_DEBUG=0
+-CONFIG_JFFS2_FS_WRITEBUFFER=y
+-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+-# CONFIG_JFFS2_SUMMARY is not set
+-# CONFIG_JFFS2_FS_XATTR is not set
+-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+-CONFIG_JFFS2_ZLIB=y
+-# CONFIG_JFFS2_LZO is not set
+-CONFIG_JFFS2_RTIME=y
+-# CONFIG_JFFS2_RUBIN is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-# CONFIG_NFS_V3 is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_ZLIB_DEFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_KGDB_CONSOLE is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-# CONFIG_CRYPTO_MANAGER is not set
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-# CONFIG_CRYPTO_MD5 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-# CONFIG_CRYPTO_CBC is not set
+-# CONFIG_CRYPTO_PCBC is not set
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+-CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/tqm8555_defconfig b/arch/powerpc/configs/tqm8555_defconfig
+deleted file mode 100644
+index bbff962..0000000
+--- a/arch/powerpc/configs/tqm8555_defconfig
++++ /dev/null
+@@ -1,1109 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:44 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-# CONFIG_HOTPLUG is not set
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-# CONFIG_MODULES is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-# CONFIG_MPC8540_ADS is not set
+-# CONFIG_MPC8560_ADS is not set
+-# CONFIG_MPC85xx_CDS is not set
+-# CONFIG_MPC85xx_MDS is not set
+-# CONFIG_MPC85xx_DS is not set
+-# CONFIG_STX_GP3 is not set
+-# CONFIG_TQM8540 is not set
+-# CONFIG_TQM8541 is not set
+-CONFIG_TQM8555=y
+-# CONFIG_TQM8560 is not set
+-# CONFIG_SBC8548 is not set
+-# CONFIG_SBC8560 is not set
+-CONFIG_TQM85xx=y
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-CONFIG_CPM2=y
+-CONFIG_PPC_CPM_NEW_BINDING=y
+-# CONFIG_FSL_ULI1575 is not set
+-CONFIG_CPM=y
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-# CONFIG_PROC_DEVICETREE is not set
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_FSL_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-CONFIG_MTD_CONCAT=y
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-CONFIG_MTD_CMDLINE_PARTS=y
+-# CONFIG_MTD_OF_PARTS is not set
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=y
+-CONFIG_MTD_BLOCK=y
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-# CONFIG_MTD_JEDECPROBE is not set
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-# CONFIG_MTD_PHYSMAP_OF is not set
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-CONFIG_IDE=y
+-CONFIG_IDE_MAX_HWIFS=4
+-CONFIG_BLK_DEV_IDE=y
+-
+-#
+-# Please see Documentation/ide/ide.txt for help/info on IDE drives
+-#
+-# CONFIG_BLK_DEV_IDE_SATA is not set
+-CONFIG_BLK_DEV_IDEDISK=y
+-# CONFIG_IDEDISK_MULTI_MODE is not set
+-# CONFIG_BLK_DEV_IDECD is not set
+-# CONFIG_BLK_DEV_IDETAPE is not set
+-# CONFIG_BLK_DEV_IDEFLOPPY is not set
+-# CONFIG_IDE_TASK_IOCTL is not set
+-CONFIG_IDE_PROC_FS=y
+-
+-#
+-# IDE chipset support/bugfixes
+-#
+-CONFIG_IDE_GENERIC=y
+-# CONFIG_BLK_DEV_PLATFORM is not set
+-CONFIG_BLK_DEV_IDEDMA_SFF=y
+-
+-#
+-# PCI IDE chipsets support
+-#
+-CONFIG_BLK_DEV_IDEPCI=y
+-CONFIG_IDEPCI_PCIBUS_ORDER=y
+-# CONFIG_BLK_DEV_OFFBOARD is not set
+-CONFIG_BLK_DEV_GENERIC=y
+-# CONFIG_BLK_DEV_OPTI621 is not set
+-CONFIG_BLK_DEV_IDEDMA_PCI=y
+-# CONFIG_BLK_DEV_AEC62XX is not set
+-# CONFIG_BLK_DEV_ALI15X3 is not set
+-# CONFIG_BLK_DEV_AMD74XX is not set
+-# CONFIG_BLK_DEV_CMD64X is not set
+-# CONFIG_BLK_DEV_TRIFLEX is not set
+-# CONFIG_BLK_DEV_CY82C693 is not set
+-# CONFIG_BLK_DEV_CS5520 is not set
+-# CONFIG_BLK_DEV_CS5530 is not set
+-# CONFIG_BLK_DEV_HPT34X is not set
+-# CONFIG_BLK_DEV_HPT366 is not set
+-# CONFIG_BLK_DEV_JMICRON is not set
+-# CONFIG_BLK_DEV_SC1200 is not set
+-# CONFIG_BLK_DEV_PIIX is not set
+-# CONFIG_BLK_DEV_IT8213 is not set
+-# CONFIG_BLK_DEV_IT821X is not set
+-# CONFIG_BLK_DEV_NS87415 is not set
+-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+-# CONFIG_BLK_DEV_SVWKS is not set
+-# CONFIG_BLK_DEV_SIIMAGE is not set
+-# CONFIG_BLK_DEV_SL82C105 is not set
+-# CONFIG_BLK_DEV_SLC90E66 is not set
+-# CONFIG_BLK_DEV_TRM290 is not set
+-CONFIG_BLK_DEV_VIA82CXXX=y
+-# CONFIG_BLK_DEV_TC86C001 is not set
+-CONFIG_BLK_DEV_IDEDMA=y
+-CONFIG_IDE_ARCH_OBSOLETE_INIT=y
+-# CONFIG_BLK_DEV_HD is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-CONFIG_NET_PCI=y
+-# CONFIG_PCNET32 is not set
+-# CONFIG_AMD8111_ETH is not set
+-# CONFIG_ADAPTEC_STARFIRE is not set
+-# CONFIG_B44 is not set
+-# CONFIG_FORCEDETH is not set
+-# CONFIG_EEPRO100 is not set
+-CONFIG_E100=y
+-# CONFIG_FEALNX is not set
+-# CONFIG_NATSEMI is not set
+-# CONFIG_NE2K_PCI is not set
+-# CONFIG_8139CP is not set
+-# CONFIG_8139TOO is not set
+-# CONFIG_R6040 is not set
+-# CONFIG_SIS900 is not set
+-# CONFIG_EPIC100 is not set
+-# CONFIG_SUNDANCE is not set
+-# CONFIG_TLAN is not set
+-# CONFIG_VIA_RHINE is not set
+-# CONFIG_SC92031 is not set
+-# CONFIG_FS_ENET is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-CONFIG_SERIAL_CPM=y
+-CONFIG_SERIAL_CPM_CONSOLE=y
+-CONFIG_SERIAL_CPM_SCC1=y
+-# CONFIG_SERIAL_CPM_SCC2 is not set
+-# CONFIG_SERIAL_CPM_SCC3 is not set
+-# CONFIG_SERIAL_CPM_SCC4 is not set
+-# CONFIG_SERIAL_CPM_SMC1 is not set
+-# CONFIG_SERIAL_CPM_SMC2 is not set
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-CONFIG_SENSORS_LM75=y
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-CONFIG_HWMON_DEBUG_CHIP=y
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_JFFS2_FS=y
+-CONFIG_JFFS2_FS_DEBUG=0
+-CONFIG_JFFS2_FS_WRITEBUFFER=y
+-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+-# CONFIG_JFFS2_SUMMARY is not set
+-# CONFIG_JFFS2_FS_XATTR is not set
+-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+-CONFIG_JFFS2_ZLIB=y
+-# CONFIG_JFFS2_LZO is not set
+-CONFIG_JFFS2_RTIME=y
+-# CONFIG_JFFS2_RUBIN is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-# CONFIG_NFS_V3 is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_ZLIB_DEFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_KGDB_CONSOLE is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-# CONFIG_CRYPTO_MANAGER is not set
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-# CONFIG_CRYPTO_MD5 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-# CONFIG_CRYPTO_CBC is not set
+-# CONFIG_CRYPTO_PCBC is not set
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+-CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/tqm8560_defconfig b/arch/powerpc/configs/tqm8560_defconfig
+deleted file mode 100644
+index 63c5ec8..0000000
+--- a/arch/powerpc/configs/tqm8560_defconfig
++++ /dev/null
+@@ -1,1109 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc6
+-# Mon Mar 24 08:48:45 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-CONFIG_PPC_85xx=y
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_E500=y
+-CONFIG_BOOKE=y
+-CONFIG_FSL_BOOKE=y
+-CONFIG_FSL_EMB_PERFMON=y
+-# CONFIG_PHYS_64BIT is not set
+-CONFIG_SPE=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFAULT_UIMAGE=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-# CONFIG_HOTPLUG is not set
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-# CONFIG_MODULES is not set
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-CONFIG_MPC85xx=y
+-# CONFIG_MPC8540_ADS is not set
+-# CONFIG_MPC8560_ADS is not set
+-# CONFIG_MPC85xx_CDS is not set
+-# CONFIG_MPC85xx_MDS is not set
+-# CONFIG_MPC85xx_DS is not set
+-# CONFIG_STX_GP3 is not set
+-# CONFIG_TQM8540 is not set
+-# CONFIG_TQM8541 is not set
+-# CONFIG_TQM8555 is not set
+-CONFIG_TQM8560=y
+-# CONFIG_SBC8548 is not set
+-# CONFIG_SBC8560 is not set
+-CONFIG_TQM85xx=y
+-# CONFIG_IPIC is not set
+-CONFIG_MPIC=y
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-CONFIG_CPM2=y
+-CONFIG_PPC_CPM_NEW_BINDING=y
+-# CONFIG_FSL_ULI1575 is not set
+-CONFIG_CPM=y
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-CONFIG_MATH_EMULATION=y
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-# CONFIG_PROC_DEVICETREE is not set
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_FSL_SOC=y
+-CONFIG_FSL_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-CONFIG_PCI_LEGACY=y
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_BOOT_LOAD=0x00800000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-CONFIG_MTD_CONCAT=y
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-CONFIG_MTD_CMDLINE_PARTS=y
+-# CONFIG_MTD_OF_PARTS is not set
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=y
+-CONFIG_MTD_BLOCK=y
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-# CONFIG_MTD_JEDECPROBE is not set
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-# CONFIG_MTD_PHYSMAP_OF is not set
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-CONFIG_IDE=y
+-CONFIG_IDE_MAX_HWIFS=4
+-CONFIG_BLK_DEV_IDE=y
+-
+-#
+-# Please see Documentation/ide/ide.txt for help/info on IDE drives
+-#
+-# CONFIG_BLK_DEV_IDE_SATA is not set
+-CONFIG_BLK_DEV_IDEDISK=y
+-# CONFIG_IDEDISK_MULTI_MODE is not set
+-# CONFIG_BLK_DEV_IDECD is not set
+-# CONFIG_BLK_DEV_IDETAPE is not set
+-# CONFIG_BLK_DEV_IDEFLOPPY is not set
+-# CONFIG_IDE_TASK_IOCTL is not set
+-CONFIG_IDE_PROC_FS=y
+-
+-#
+-# IDE chipset support/bugfixes
+-#
+-CONFIG_IDE_GENERIC=y
+-# CONFIG_BLK_DEV_PLATFORM is not set
+-CONFIG_BLK_DEV_IDEDMA_SFF=y
+-
+-#
+-# PCI IDE chipsets support
+-#
+-CONFIG_BLK_DEV_IDEPCI=y
+-CONFIG_IDEPCI_PCIBUS_ORDER=y
+-# CONFIG_BLK_DEV_OFFBOARD is not set
+-CONFIG_BLK_DEV_GENERIC=y
+-# CONFIG_BLK_DEV_OPTI621 is not set
+-CONFIG_BLK_DEV_IDEDMA_PCI=y
+-# CONFIG_BLK_DEV_AEC62XX is not set
+-# CONFIG_BLK_DEV_ALI15X3 is not set
+-# CONFIG_BLK_DEV_AMD74XX is not set
+-# CONFIG_BLK_DEV_CMD64X is not set
+-# CONFIG_BLK_DEV_TRIFLEX is not set
+-# CONFIG_BLK_DEV_CY82C693 is not set
+-# CONFIG_BLK_DEV_CS5520 is not set
+-# CONFIG_BLK_DEV_CS5530 is not set
+-# CONFIG_BLK_DEV_HPT34X is not set
+-# CONFIG_BLK_DEV_HPT366 is not set
+-# CONFIG_BLK_DEV_JMICRON is not set
+-# CONFIG_BLK_DEV_SC1200 is not set
+-# CONFIG_BLK_DEV_PIIX is not set
+-# CONFIG_BLK_DEV_IT8213 is not set
+-# CONFIG_BLK_DEV_IT821X is not set
+-# CONFIG_BLK_DEV_NS87415 is not set
+-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+-# CONFIG_BLK_DEV_SVWKS is not set
+-# CONFIG_BLK_DEV_SIIMAGE is not set
+-# CONFIG_BLK_DEV_SL82C105 is not set
+-# CONFIG_BLK_DEV_SLC90E66 is not set
+-# CONFIG_BLK_DEV_TRM290 is not set
+-CONFIG_BLK_DEV_VIA82CXXX=y
+-# CONFIG_BLK_DEV_TC86C001 is not set
+-CONFIG_BLK_DEV_IDEDMA=y
+-CONFIG_IDE_ARCH_OBSOLETE_INIT=y
+-# CONFIG_BLK_DEV_HD is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-# CONFIG_MDIO_BITBANG is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_IBM_NEW_EMAC_ZMII is not set
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-CONFIG_NET_PCI=y
+-# CONFIG_PCNET32 is not set
+-# CONFIG_AMD8111_ETH is not set
+-# CONFIG_ADAPTEC_STARFIRE is not set
+-# CONFIG_B44 is not set
+-# CONFIG_FORCEDETH is not set
+-# CONFIG_EEPRO100 is not set
+-CONFIG_E100=y
+-# CONFIG_FEALNX is not set
+-# CONFIG_NATSEMI is not set
+-# CONFIG_NE2K_PCI is not set
+-# CONFIG_8139CP is not set
+-# CONFIG_8139TOO is not set
+-# CONFIG_R6040 is not set
+-# CONFIG_SIS900 is not set
+-# CONFIG_EPIC100 is not set
+-# CONFIG_SUNDANCE is not set
+-# CONFIG_TLAN is not set
+-# CONFIG_VIA_RHINE is not set
+-# CONFIG_SC92031 is not set
+-# CONFIG_FS_ENET is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-CONFIG_GIANFAR=y
+-CONFIG_GFAR_NAPI=y
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-# CONFIG_SERIAL_8250_EXTENDED is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-CONFIG_SERIAL_CPM=y
+-CONFIG_SERIAL_CPM_CONSOLE=y
+-CONFIG_SERIAL_CPM_SCC1=y
+-# CONFIG_SERIAL_CPM_SCC2 is not set
+-# CONFIG_SERIAL_CPM_SCC3 is not set
+-# CONFIG_SERIAL_CPM_SCC4 is not set
+-# CONFIG_SERIAL_CPM_SMC1 is not set
+-# CONFIG_SERIAL_CPM_SMC2 is not set
+-# CONFIG_SERIAL_JSM is not set
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-CONFIG_I2C_CHARDEV=y
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_ALI1535 is not set
+-# CONFIG_I2C_ALI1563 is not set
+-# CONFIG_I2C_ALI15X3 is not set
+-# CONFIG_I2C_AMD756 is not set
+-# CONFIG_I2C_AMD8111 is not set
+-# CONFIG_I2C_I801 is not set
+-# CONFIG_I2C_I810 is not set
+-# CONFIG_I2C_PIIX4 is not set
+-CONFIG_I2C_MPC=y
+-# CONFIG_I2C_NFORCE2 is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_PROSAVAGE is not set
+-# CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_SIS5595 is not set
+-# CONFIG_I2C_SIS630 is not set
+-# CONFIG_I2C_SIS96X is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_VIA is not set
+-# CONFIG_I2C_VIAPRO is not set
+-# CONFIG_I2C_VOODOO3 is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-# CONFIG_SENSORS_EEPROM is not set
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ADT7473 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_I5K_AMB is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-CONFIG_SENSORS_LM75=y
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_SIS5595 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VIA686A is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_VT8231 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-CONFIG_HWMON_DEBUG_CHIP=y
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-CONFIG_DAB=y
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-# CONFIG_HIDRAW is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_JFFS2_FS=y
+-CONFIG_JFFS2_FS_DEBUG=0
+-CONFIG_JFFS2_FS_WRITEBUFFER=y
+-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+-# CONFIG_JFFS2_SUMMARY is not set
+-# CONFIG_JFFS2_FS_XATTR is not set
+-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+-CONFIG_JFFS2_ZLIB=y
+-# CONFIG_JFFS2_LZO is not set
+-CONFIG_JFFS2_RTIME=y
+-# CONFIG_JFFS2_RUBIN is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-# CONFIG_NFS_V3 is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-# CONFIG_SYSV68_PARTITION is not set
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_ZLIB_DEFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_KGDB_CONSOLE is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-# CONFIG_CRYPTO_MANAGER is not set
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-# CONFIG_CRYPTO_MD5 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-# CONFIG_CRYPTO_CBC is not set
+-# CONFIG_CRYPTO_PCBC is not set
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+-CONFIG_PPC_LIB_RHEAP=y
+diff --git a/arch/powerpc/configs/walnut_defconfig b/arch/powerpc/configs/walnut_defconfig
+deleted file mode 100644
+index 3b2689e..0000000
+--- a/arch/powerpc/configs/walnut_defconfig
++++ /dev/null
+@@ -1,887 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc2
+-# Fri Feb 15 21:54:12 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-CONFIG_40x=y
+-# CONFIG_44x is not set
+-# CONFIG_E200 is not set
+-CONFIG_4xx=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-# CONFIG_DEFAULT_UIMAGE is not set
+-CONFIG_PPC_DCR_NATIVE=y
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_PPC_DCR=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-CONFIG_POSIX_MQUEUE=y
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-CONFIG_KALLSYMS_ALL=y
+-CONFIG_KALLSYMS_EXTRA_PASS=y
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLUB_DEBUG=y
+-# CONFIG_SLAB is not set
+-CONFIG_SLUB=y
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-CONFIG_LBD=y
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-# CONFIG_PPC4xx_PCI_EXPRESS is not set
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-# CONFIG_EP405 is not set
+-# CONFIG_KILAUEA is not set
+-# CONFIG_MAKALU is not set
+-CONFIG_WALNUT=y
+-# CONFIG_XILINX_VIRTEX_GENERIC_BOARD is not set
+-CONFIG_405GP=y
+-CONFIG_IBM405_ERR77=y
+-CONFIG_IBM405_ERR51=y
+-# CONFIG_IPIC is not set
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-CONFIG_OF_RTC=y
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_RCU_TRACE=y
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_MATH_EMULATION is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-CONFIG_RESOURCES_64BIT=y
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_SYSCALL=y
+-# CONFIG_PCIEPORTBUS is not set
+-CONFIG_ARCH_SUPPORTS_MSI=y
+-# CONFIG_PCI_MSI is not set
+-# CONFIG_PCI_LEGACY is not set
+-# CONFIG_PCI_DEBUG is not set
+-# CONFIG_PCCARD is not set
+-# CONFIG_HOTPLUG_PCI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x00400000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+-# CONFIG_INET_XFRM_MODE_BEET is not set
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-CONFIG_CONNECTOR=y
+-CONFIG_PROC_EVENTS=y
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-CONFIG_MTD_CMDLINE_PARTS=y
+-CONFIG_MTD_OF_PARTS=y
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=m
+-CONFIG_MTD_BLOCK=m
+-# CONFIG_MTD_BLOCK_RO is not set
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-# CONFIG_MTD_OOPS is not set
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-CONFIG_MTD_JEDECPROBE=y
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-CONFIG_MTD_PHYSMAP_OF=y
+-# CONFIG_MTD_INTEL_VR_NOR is not set
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_PMC551 is not set
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-# CONFIG_MTD_NAND is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=35000
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-# CONFIG_XILINX_SYSACE is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_PHANTOM is not set
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_DMA is not set
+-# CONFIG_SCSI_NETLINK is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_FIREWIRE is not set
+-# CONFIG_IEEE1394 is not set
+-# CONFIG_I2O is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_ARCNET is not set
+-# CONFIG_PHYLIB is not set
+-CONFIG_NET_ETHERNET=y
+-# CONFIG_MII is not set
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-CONFIG_IBM_NEW_EMAC=y
+-CONFIG_IBM_NEW_EMAC_RXB=128
+-CONFIG_IBM_NEW_EMAC_TXB=64
+-CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+-CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+-CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+-# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+-CONFIG_IBM_NEW_EMAC_ZMII=y
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_NET_PCI is not set
+-# CONFIG_B44 is not set
+-CONFIG_NETDEV_1000=y
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_E1000E is not set
+-# CONFIG_E1000E_ENABLED is not set
+-# CONFIG_IP1000 is not set
+-# CONFIG_IGB is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_VIA_VELOCITY is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-CONFIG_NETDEV_10000=y
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGBE is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-# CONFIG_NIU is not set
+-# CONFIG_MLX4_CORE is not set
+-# CONFIG_TEHUTI is not set
+-# CONFIG_BNX2X is not set
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_NOZOMI is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_PCI=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-CONFIG_SERIAL_8250_EXTENDED=y
+-# CONFIG_SERIAL_8250_MANY_PORTS is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+-# CONFIG_SERIAL_8250_RSA is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_SERIAL_OF_PLATFORM=y
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-# CONFIG_HW_RANDOM is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_DEVPORT=y
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-# CONFIG_HWMON is not set
+-CONFIG_THERMAL=y
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-# CONFIG_DAB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-CONFIG_VIDEO_OUTPUT_CONTROL=m
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-# CONFIG_USB_GADGET is not set
+-# CONFIG_MMC is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_INFINIBAND is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_JFFS2_FS is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_NLS is not set
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_MAGIC_SYSRQ=y
+-# CONFIG_UNUSED_SYMBOLS is not set
+-CONFIG_DEBUG_FS=y
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-CONFIG_SCHED_DEBUG=y
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_SLUB_DEBUG_ON is not set
+-# CONFIG_SLUB_STATS is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-CONFIG_DEBUG_BUGVERBOSE=y
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_VIRQ_DEBUG is not set
+-# CONFIG_BDI_SWITCH is not set
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=y
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=y
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/configs/warp_defconfig b/arch/powerpc/configs/warp_defconfig
+deleted file mode 100644
+index 2313c3e..0000000
+--- a/arch/powerpc/configs/warp_defconfig
++++ /dev/null
+@@ -1,1110 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc2
+-# Fri Feb 15 21:54:43 2008
+-#
+-# CONFIG_PPC64 is not set
+-
+-#
+-# Processor support
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_PPC_85xx is not set
+-# CONFIG_PPC_8xx is not set
+-# CONFIG_40x is not set
+-CONFIG_44x=y
+-# CONFIG_E200 is not set
+-CONFIG_PPC_FPU=y
+-CONFIG_4xx=y
+-CONFIG_BOOKE=y
+-CONFIG_PTE_64BIT=y
+-CONFIG_PHYS_64BIT=y
+-# CONFIG_PPC_MM_SLICES is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-CONFIG_PPC32=y
+-CONFIG_WORD_SIZE=32
+-CONFIG_PPC_MERGE=y
+-CONFIG_MMU=y
+-CONFIG_GENERIC_CMOS_UPDATE=y
+-CONFIG_GENERIC_TIME=y
+-CONFIG_GENERIC_TIME_VSYSCALL=y
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_GENERIC_HARDIRQS=y
+-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+-CONFIG_IRQ_PER_CPU=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+-CONFIG_PPC=y
+-CONFIG_EARLY_PRINTK=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_PPC_OF=y
+-CONFIG_OF=y
+-CONFIG_PPC_UDBG_16550=y
+-# CONFIG_GENERIC_TBSYNC is not set
+-CONFIG_AUDIT_ARCH=y
+-CONFIG_GENERIC_BUG=y
+-# CONFIG_DEFAULT_UIMAGE is not set
+-CONFIG_PPC_DCR_NATIVE=y
+-# CONFIG_PPC_DCR_MMIO is not set
+-CONFIG_PPC_DCR=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# General setup
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_LOCALVERSION="-pika"
+-# CONFIG_LOCALVERSION_AUTO is not set
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_CGROUPS is not set
+-CONFIG_GROUP_SCHED=y
+-CONFIG_FAIR_GROUP_SCHED=y
+-# CONFIG_RT_GROUP_SCHED is not set
+-CONFIG_USER_SCHED=y
+-# CONFIG_CGROUP_SCHED is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-# CONFIG_NAMESPACES is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-CONFIG_KALLSYMS=y
+-# CONFIG_KALLSYMS_ALL is not set
+-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+-# CONFIG_HOTPLUG is not set
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_COMPAT_BRK=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_SLAB=y
+-# CONFIG_SLUB is not set
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-# CONFIG_MARKERS is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-CONFIG_MODULES=y
+-CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-CONFIG_KMOD=y
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-# CONFIG_BLK_DEV_BSG is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="anticipatory"
+-CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-
+-#
+-# Platform support
+-#
+-# CONFIG_PPC_MPC512x is not set
+-# CONFIG_PPC_MPC5121 is not set
+-# CONFIG_PPC_CELL is not set
+-# CONFIG_PPC_CELL_NATIVE is not set
+-# CONFIG_PQ2ADS is not set
+-# CONFIG_BAMBOO is not set
+-# CONFIG_EBONY is not set
+-# CONFIG_SEQUOIA is not set
+-# CONFIG_TAISHAN is not set
+-# CONFIG_KATMAI is not set
+-# CONFIG_RAINIER is not set
+-CONFIG_WARP=y
+-CONFIG_440EP=y
+-CONFIG_IBM440EP_ERR42=y
+-# CONFIG_IPIC is not set
+-# CONFIG_MPIC is not set
+-# CONFIG_MPIC_WEIRD is not set
+-# CONFIG_PPC_I8259 is not set
+-# CONFIG_PPC_RTAS is not set
+-# CONFIG_MMIO_NVRAM is not set
+-# CONFIG_PPC_MPC106 is not set
+-# CONFIG_PPC_970_NAP is not set
+-# CONFIG_PPC_INDIRECT_IO is not set
+-# CONFIG_GENERIC_IOMAP is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_FSL_ULI1575 is not set
+-
+-#
+-# Kernel options
+-#
+-# CONFIG_HIGHMEM is not set
+-# CONFIG_TICK_ONESHOT is not set
+-# CONFIG_NO_HZ is not set
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-# CONFIG_HZ_100 is not set
+-# CONFIG_HZ_250 is not set
+-# CONFIG_HZ_300 is not set
+-CONFIG_HZ_1000=y
+-CONFIG_HZ=1000
+-# CONFIG_SCHED_HRTICK is not set
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_RCU_TRACE=y
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_MATH_EMULATION is not set
+-# CONFIG_IOMMU_HELPER is not set
+-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+-CONFIG_ARCH_HAS_WALK_MEMORY=y
+-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+-CONFIG_ARCH_FLATMEM_ENABLE=y
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-CONFIG_RESOURCES_64BIT=y
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BOUNCE=y
+-CONFIG_VIRT_TO_BUS=y
+-CONFIG_PROC_DEVICETREE=y
+-CONFIG_CMDLINE_BOOL=y
+-CONFIG_CMDLINE="ip=on"
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-# CONFIG_PCI is not set
+-# CONFIG_PCI_DOMAINS is not set
+-# CONFIG_PCI_SYSCALL is not set
+-# CONFIG_ARCH_SUPPORTS_MSI is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0xc0000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x01000000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-# CONFIG_IP_PNP_BOOTP is not set
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-# CONFIG_INET_LRO is not set
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IP_VS is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-CONFIG_NETFILTER=y
+-# CONFIG_NETFILTER_DEBUG is not set
+-CONFIG_NETFILTER_ADVANCED=y
+-
+-#
+-# Core Netfilter Configuration
+-#
+-# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+-# CONFIG_NETFILTER_NETLINK_LOG is not set
+-# CONFIG_NF_CONNTRACK is not set
+-# CONFIG_NETFILTER_XTABLES is not set
+-
+-#
+-# IP: Netfilter Configuration
+-#
+-# CONFIG_IP_NF_QUEUE is not set
+-# CONFIG_IP_NF_IPTABLES is not set
+-# CONFIG_IP_NF_ARPTABLES is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-CONFIG_VLAN_8021Q=y
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-
+-#
+-# Wireless
+-#
+-# CONFIG_CFG80211 is not set
+-# CONFIG_WIRELESS_EXT is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_IEEE80211 is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-# CONFIG_STANDALONE is not set
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-CONFIG_MTD=y
+-# CONFIG_MTD_DEBUG is not set
+-# CONFIG_MTD_CONCAT is not set
+-CONFIG_MTD_PARTITIONS=y
+-# CONFIG_MTD_REDBOOT_PARTS is not set
+-# CONFIG_MTD_CMDLINE_PARTS is not set
+-CONFIG_MTD_OF_PARTS=y
+-
+-#
+-# User Modules And Translation Layers
+-#
+-CONFIG_MTD_CHAR=y
+-CONFIG_MTD_BLKDEVS=y
+-CONFIG_MTD_BLOCK=y
+-# CONFIG_FTL is not set
+-# CONFIG_NFTL is not set
+-# CONFIG_INFTL is not set
+-# CONFIG_RFD_FTL is not set
+-# CONFIG_SSFDC is not set
+-CONFIG_MTD_OOPS=m
+-
+-#
+-# RAM/ROM/Flash chip drivers
+-#
+-CONFIG_MTD_CFI=y
+-# CONFIG_MTD_JEDECPROBE is not set
+-CONFIG_MTD_GEN_PROBE=y
+-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+-CONFIG_MTD_MAP_BANK_WIDTH_1=y
+-CONFIG_MTD_MAP_BANK_WIDTH_2=y
+-CONFIG_MTD_MAP_BANK_WIDTH_4=y
+-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+-CONFIG_MTD_CFI_I1=y
+-CONFIG_MTD_CFI_I2=y
+-# CONFIG_MTD_CFI_I4 is not set
+-# CONFIG_MTD_CFI_I8 is not set
+-# CONFIG_MTD_CFI_INTELEXT is not set
+-CONFIG_MTD_CFI_AMDSTD=y
+-# CONFIG_MTD_CFI_STAA is not set
+-CONFIG_MTD_CFI_UTIL=y
+-# CONFIG_MTD_RAM is not set
+-# CONFIG_MTD_ROM is not set
+-# CONFIG_MTD_ABSENT is not set
+-
+-#
+-# Mapping drivers for chip access
+-#
+-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+-# CONFIG_MTD_PHYSMAP is not set
+-CONFIG_MTD_PHYSMAP_OF=y
+-# CONFIG_MTD_PLATRAM is not set
+-
+-#
+-# Self-contained MTD device drivers
+-#
+-# CONFIG_MTD_SLRAM is not set
+-# CONFIG_MTD_PHRAM is not set
+-# CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLOCK2MTD is not set
+-
+-#
+-# Disk-On-Chip Device Drivers
+-#
+-# CONFIG_MTD_DOC2000 is not set
+-# CONFIG_MTD_DOC2001 is not set
+-# CONFIG_MTD_DOC2001PLUS is not set
+-CONFIG_MTD_NAND=y
+-# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+-CONFIG_MTD_NAND_ECC_SMC=y
+-# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+-CONFIG_MTD_NAND_IDS=y
+-# CONFIG_MTD_NAND_DISKONCHIP is not set
+-# CONFIG_MTD_NAND_NANDSIM is not set
+-# CONFIG_MTD_NAND_PLATFORM is not set
+-# CONFIG_MTD_ALAUDA is not set
+-# CONFIG_MTD_NAND_FSL_ELBC is not set
+-# CONFIG_MTD_ONENAND is not set
+-
+-#
+-# UBI - Unsorted block images
+-#
+-# CONFIG_MTD_UBI is not set
+-CONFIG_OF_DEVICE=y
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_UB is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=4096
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-# CONFIG_XILINX_SYSACE is not set
+-CONFIG_MISC_DEVICES=y
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-CONFIG_SCSI=y
+-CONFIG_SCSI_DMA=y
+-# CONFIG_SCSI_TGT is not set
+-# CONFIG_SCSI_NETLINK is not set
+-CONFIG_SCSI_PROC_FS=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-CONFIG_BLK_DEV_SD=y
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
+-# CONFIG_BLK_DEV_SR is not set
+-# CONFIG_CHR_DEV_SG is not set
+-# CONFIG_CHR_DEV_SCH is not set
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-# CONFIG_SCSI_MULTI_LUN is not set
+-# CONFIG_SCSI_CONSTANTS is not set
+-# CONFIG_SCSI_LOGGING is not set
+-# CONFIG_SCSI_SCAN_ASYNC is not set
+-CONFIG_SCSI_WAIT_SCAN=m
+-
+-#
+-# SCSI Transports
+-#
+-CONFIG_SCSI_SPI_ATTRS=y
+-# CONFIG_SCSI_FC_ATTRS is not set
+-# CONFIG_SCSI_ISCSI_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+-# CONFIG_SCSI_LOWLEVEL is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_MACINTOSH_DRIVERS is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-# CONFIG_VETH is not set
+-# CONFIG_PHYLIB is not set
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-CONFIG_IBM_NEW_EMAC=y
+-CONFIG_IBM_NEW_EMAC_RXB=128
+-CONFIG_IBM_NEW_EMAC_TXB=64
+-CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+-CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+-CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+-# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+-CONFIG_IBM_NEW_EMAC_ZMII=y
+-# CONFIG_IBM_NEW_EMAC_RGMII is not set
+-# CONFIG_IBM_NEW_EMAC_TAH is not set
+-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+-# CONFIG_B44 is not set
+-# CONFIG_NETDEV_1000 is not set
+-# CONFIG_NETDEV_10000 is not set
+-
+-#
+-# Wireless LAN
+-#
+-# CONFIG_WLAN_PRE80211 is not set
+-# CONFIG_WLAN_80211 is not set
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
+-# CONFIG_USB_USBNET is not set
+-# CONFIG_WAN is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_ISDN is not set
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-
+-#
+-# Serial drivers
+-#
+-CONFIG_SERIAL_8250=y
+-CONFIG_SERIAL_8250_CONSOLE=y
+-CONFIG_SERIAL_8250_NR_UARTS=4
+-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+-CONFIG_SERIAL_8250_EXTENDED=y
+-# CONFIG_SERIAL_8250_MANY_PORTS is not set
+-CONFIG_SERIAL_8250_SHARE_IRQ=y
+-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+-# CONFIG_SERIAL_8250_RSA is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_OF_PLATFORM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-# CONFIG_IPMI_HANDLER is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_RAW_DRIVER is not set
+-# CONFIG_TCG_TPM is not set
+-CONFIG_I2C=y
+-CONFIG_I2C_BOARDINFO=y
+-# CONFIG_I2C_CHARDEV is not set
+-
+-#
+-# I2C Algorithms
+-#
+-# CONFIG_I2C_ALGOBIT is not set
+-# CONFIG_I2C_ALGOPCF is not set
+-# CONFIG_I2C_ALGOPCA is not set
+-
+-#
+-# I2C Hardware Bus support
+-#
+-# CONFIG_I2C_MPC is not set
+-# CONFIG_I2C_OCORES is not set
+-# CONFIG_I2C_PARPORT_LIGHT is not set
+-# CONFIG_I2C_SIMTEC is not set
+-# CONFIG_I2C_TAOS_EVM is not set
+-# CONFIG_I2C_STUB is not set
+-# CONFIG_I2C_TINY_USB is not set
+-
+-#
+-# Miscellaneous I2C Chip support
+-#
+-# CONFIG_DS1682 is not set
+-CONFIG_SENSORS_EEPROM=y
+-# CONFIG_SENSORS_PCF8574 is not set
+-# CONFIG_PCF8575 is not set
+-# CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+-# CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_SENSORS_TSL2550 is not set
+-# CONFIG_I2C_DEBUG_CORE is not set
+-# CONFIG_I2C_DEBUG_ALGO is not set
+-# CONFIG_I2C_DEBUG_BUS is not set
+-# CONFIG_I2C_DEBUG_CHIP is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_AD7418 is not set
+-# CONFIG_SENSORS_ADM1021 is not set
+-# CONFIG_SENSORS_ADM1025 is not set
+-# CONFIG_SENSORS_ADM1026 is not set
+-# CONFIG_SENSORS_ADM1029 is not set
+-# CONFIG_SENSORS_ADM1031 is not set
+-# CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ADT7470 is not set
+-# CONFIG_SENSORS_ATXP1 is not set
+-# CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_F71882FG is not set
+-# CONFIG_SENSORS_F75375S is not set
+-# CONFIG_SENSORS_GL518SM is not set
+-# CONFIG_SENSORS_GL520SM is not set
+-# CONFIG_SENSORS_IT87 is not set
+-# CONFIG_SENSORS_LM63 is not set
+-# CONFIG_SENSORS_LM75 is not set
+-# CONFIG_SENSORS_LM77 is not set
+-# CONFIG_SENSORS_LM78 is not set
+-# CONFIG_SENSORS_LM80 is not set
+-# CONFIG_SENSORS_LM83 is not set
+-# CONFIG_SENSORS_LM85 is not set
+-# CONFIG_SENSORS_LM87 is not set
+-# CONFIG_SENSORS_LM90 is not set
+-# CONFIG_SENSORS_LM92 is not set
+-# CONFIG_SENSORS_LM93 is not set
+-# CONFIG_SENSORS_MAX1619 is not set
+-# CONFIG_SENSORS_MAX6650 is not set
+-# CONFIG_SENSORS_PC87360 is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_DME1737 is not set
+-# CONFIG_SENSORS_SMSC47M1 is not set
+-# CONFIG_SENSORS_SMSC47M192 is not set
+-# CONFIG_SENSORS_SMSC47B397 is not set
+-# CONFIG_SENSORS_ADS7828 is not set
+-# CONFIG_SENSORS_THMC50 is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_SENSORS_W83781D is not set
+-# CONFIG_SENSORS_W83791D is not set
+-# CONFIG_SENSORS_W83792D is not set
+-# CONFIG_SENSORS_W83793 is not set
+-# CONFIG_SENSORS_W83L785TS is not set
+-# CONFIG_SENSORS_W83L786NG is not set
+-# CONFIG_SENSORS_W83627HF is not set
+-# CONFIG_SENSORS_W83627EHF is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-CONFIG_THERMAL=y
+-# CONFIG_WATCHDOG is not set
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-CONFIG_SSB_POSSIBLE=y
+-# CONFIG_SSB is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-# CONFIG_DVB_CORE is not set
+-# CONFIG_DAB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-# CONFIG_USB_ARCH_HAS_EHCI is not set
+-CONFIG_USB=y
+-# CONFIG_USB_DEBUG is not set
+-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+-
+-#
+-# Miscellaneous USB options
+-#
+-# CONFIG_USB_DEVICEFS is not set
+-CONFIG_USB_DEVICE_CLASS=y
+-# CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_OTG is not set
+-
+-#
+-# USB Host Controller Drivers
+-#
+-# CONFIG_USB_ISP116X_HCD is not set
+-CONFIG_USB_OHCI_HCD=y
+-CONFIG_USB_OHCI_HCD_PPC_OF=y
+-CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+-# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+-CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+-CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
+-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+-# CONFIG_USB_SL811_HCD is not set
+-# CONFIG_USB_R8A66597_HCD is not set
+-
+-#
+-# USB Device Class drivers
+-#
+-# CONFIG_USB_ACM is not set
+-# CONFIG_USB_PRINTER is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# may also be needed; see USB_STORAGE Help for more information
+-#
+-CONFIG_USB_STORAGE=y
+-# CONFIG_USB_STORAGE_DEBUG is not set
+-# CONFIG_USB_STORAGE_DATAFAB is not set
+-# CONFIG_USB_STORAGE_FREECOM is not set
+-# CONFIG_USB_STORAGE_ISD200 is not set
+-# CONFIG_USB_STORAGE_DPCM is not set
+-# CONFIG_USB_STORAGE_USBAT is not set
+-# CONFIG_USB_STORAGE_SDDR09 is not set
+-# CONFIG_USB_STORAGE_SDDR55 is not set
+-# CONFIG_USB_STORAGE_JUMPSHOT is not set
+-# CONFIG_USB_STORAGE_ALAUDA is not set
+-# CONFIG_USB_STORAGE_KARMA is not set
+-# CONFIG_USB_LIBUSUAL is not set
+-
+-#
+-# USB Imaging devices
+-#
+-# CONFIG_USB_MDC800 is not set
+-# CONFIG_USB_MICROTEK is not set
+-CONFIG_USB_MON=y
+-
+-#
+-# USB port drivers
+-#
+-# CONFIG_USB_SERIAL is not set
+-
+-#
+-# USB Miscellaneous drivers
+-#
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+-# CONFIG_USB_ADUTUX is not set
+-# CONFIG_USB_AUERSWALD is not set
+-# CONFIG_USB_RIO500 is not set
+-# CONFIG_USB_LEGOTOWER is not set
+-# CONFIG_USB_LCD is not set
+-# CONFIG_USB_BERRY_CHARGE is not set
+-# CONFIG_USB_LED is not set
+-# CONFIG_USB_CYPRESS_CY7C63 is not set
+-# CONFIG_USB_CYTHERM is not set
+-# CONFIG_USB_PHIDGET is not set
+-# CONFIG_USB_IDMOUSE is not set
+-# CONFIG_USB_FTDI_ELAN is not set
+-# CONFIG_USB_APPLEDISPLAY is not set
+-# CONFIG_USB_LD is not set
+-# CONFIG_USB_TRANCEVIBRATOR is not set
+-# CONFIG_USB_IOWARRIOR is not set
+-# CONFIG_USB_GADGET is not set
+-CONFIG_MMC=m
+-# CONFIG_MMC_DEBUG is not set
+-# CONFIG_MMC_UNSAFE_RESUME is not set
+-
+-#
+-# MMC/SD Card Drivers
+-#
+-CONFIG_MMC_BLOCK=m
+-CONFIG_MMC_BLOCK_BOUNCE=y
+-# CONFIG_SDIO_UART is not set
+-
+-#
+-# MMC/SD Host Controller Drivers
+-#
+-# CONFIG_MMC_WBSD is not set
+-# CONFIG_MEMSTICK is not set
+-# CONFIG_NEW_LEDS is not set
+-# CONFIG_EDAC is not set
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# Userspace I/O
+-#
+-# CONFIG_UIO is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_EXT4DEV_FS is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_FS_POSIX_ACL is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-CONFIG_FAT_FS=y
+-CONFIG_MSDOS_FS=y
+-CONFIG_VFAT_FS=y
+-CONFIG_FAT_DEFAULT_CODEPAGE=437
+-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-# CONFIG_TMPFS is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-CONFIG_JFFS2_FS=y
+-CONFIG_JFFS2_FS_DEBUG=0
+-CONFIG_JFFS2_FS_WRITEBUFFER=y
+-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+-# CONFIG_JFFS2_SUMMARY is not set
+-# CONFIG_JFFS2_FS_XATTR is not set
+-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+-CONFIG_JFFS2_ZLIB=y
+-# CONFIG_JFFS2_LZO is not set
+-CONFIG_JFFS2_RTIME=y
+-# CONFIG_JFFS2_RUBIN is not set
+-CONFIG_CRAMFS=y
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-# CONFIG_NFS_V3_ACL is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-# CONFIG_SUNRPC_BIND34 is not set
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-CONFIG_NLS=y
+-CONFIG_NLS_DEFAULT="iso8859-1"
+-CONFIG_NLS_CODEPAGE_437=y
+-# CONFIG_NLS_CODEPAGE_737 is not set
+-# CONFIG_NLS_CODEPAGE_775 is not set
+-CONFIG_NLS_CODEPAGE_850=y
+-# CONFIG_NLS_CODEPAGE_852 is not set
+-# CONFIG_NLS_CODEPAGE_855 is not set
+-# CONFIG_NLS_CODEPAGE_857 is not set
+-# CONFIG_NLS_CODEPAGE_860 is not set
+-# CONFIG_NLS_CODEPAGE_861 is not set
+-# CONFIG_NLS_CODEPAGE_862 is not set
+-# CONFIG_NLS_CODEPAGE_863 is not set
+-# CONFIG_NLS_CODEPAGE_864 is not set
+-# CONFIG_NLS_CODEPAGE_865 is not set
+-# CONFIG_NLS_CODEPAGE_866 is not set
+-# CONFIG_NLS_CODEPAGE_869 is not set
+-# CONFIG_NLS_CODEPAGE_936 is not set
+-# CONFIG_NLS_CODEPAGE_950 is not set
+-# CONFIG_NLS_CODEPAGE_932 is not set
+-# CONFIG_NLS_CODEPAGE_949 is not set
+-# CONFIG_NLS_CODEPAGE_874 is not set
+-# CONFIG_NLS_ISO8859_8 is not set
+-# CONFIG_NLS_CODEPAGE_1250 is not set
+-# CONFIG_NLS_CODEPAGE_1251 is not set
+-CONFIG_NLS_ASCII=y
+-CONFIG_NLS_ISO8859_1=y
+-# CONFIG_NLS_ISO8859_2 is not set
+-# CONFIG_NLS_ISO8859_3 is not set
+-# CONFIG_NLS_ISO8859_4 is not set
+-# CONFIG_NLS_ISO8859_5 is not set
+-# CONFIG_NLS_ISO8859_6 is not set
+-# CONFIG_NLS_ISO8859_7 is not set
+-# CONFIG_NLS_ISO8859_9 is not set
+-# CONFIG_NLS_ISO8859_13 is not set
+-# CONFIG_NLS_ISO8859_14 is not set
+-CONFIG_NLS_ISO8859_15=y
+-# CONFIG_NLS_KOI8_R is not set
+-# CONFIG_NLS_KOI8_U is not set
+-CONFIG_NLS_UTF8=y
+-# CONFIG_DLM is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-CONFIG_CRC_CCITT=y
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC_ITU_T is not set
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_ZLIB_DEFLATE=y
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_MAGIC_SYSRQ=y
+-# CONFIG_UNUSED_SYMBOLS is not set
+-CONFIG_DEBUG_FS=y
+-# CONFIG_HEADERS_CHECK is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-CONFIG_DETECT_SOFTLOCKUP=y
+-# CONFIG_SCHED_DEBUG is not set
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_DEBUG_SLAB is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-CONFIG_DEBUG_INFO=y
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_SAMPLES is not set
+-# CONFIG_DEBUG_STACKOVERFLOW is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-# CONFIG_DEBUGGER is not set
+-# CONFIG_VIRQ_DEBUG is not set
+-CONFIG_BDI_SWITCH=y
+-# CONFIG_PPC_EARLY_DEBUG is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+-CONFIG_CRYPTO=y
+-# CONFIG_CRYPTO_SEQIV is not set
+-# CONFIG_CRYPTO_MANAGER is not set
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-# CONFIG_CRYPTO_MD5 is not set
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_ECB is not set
+-# CONFIG_CRYPTO_CBC is not set
+-# CONFIG_CRYPTO_PCBC is not set
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_XTS is not set
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-# CONFIG_CRYPTO_DES is not set
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-# CONFIG_CRYPTO_TEST is not set
+-# CONFIG_CRYPTO_AUTHENC is not set
+-# CONFIG_CRYPTO_LZO is not set
+-CONFIG_CRYPTO_HW=y
+-# CONFIG_PPC_CLOCK is not set
+diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
+index c1baf9d..9177b21 100644
+--- a/arch/powerpc/kernel/Makefile
++++ b/arch/powerpc/kernel/Makefile
+@@ -12,7 +12,7 @@ CFLAGS_prom_init.o += -fPIC
+ CFLAGS_btext.o += -fPIC
+ endif
+
+-obj-y := semaphore.o cputable.o ptrace.o syscalls.o \
++obj-y := cputable.o ptrace.o syscalls.o \
+ irq.o align.o signal_32.o pmc.o vdso.o \
+ init_task.o process.o systbl.o idle.o \
+ signal.o
+@@ -67,6 +67,7 @@ obj-$(CONFIG_BOOTX_TEXT) += btext.o
+ obj-$(CONFIG_SMP) += smp.o
+ obj-$(CONFIG_KPROBES) += kprobes.o
+ obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o
++obj-$(CONFIG_STACKTRACE) += stacktrace.o
+
+ pci64-$(CONFIG_PPC64) += pci_dn.o isa-bridge.o
+ obj-$(CONFIG_PCI) += pci_$(CONFIG_WORD_SIZE).o $(pci64-y) \
+@@ -105,4 +106,13 @@ PHONY += systbl_chk
+ systbl_chk: $(src)/systbl_chk.sh $(obj)/systbl_chk.i
+ $(call cmd,systbl_chk)
+
++$(obj)/built-in.o: prom_init_check
++
++quiet_cmd_prom_init_check = CALL $<
++ cmd_prom_init_check = $(CONFIG_SHELL) $< "$(NM)" "$(obj)/prom_init.o"
++
++PHONY += prom_init_check
++prom_init_check: $(src)/prom_init_check.sh $(obj)/prom_init.o
++ $(call cmd,prom_init_check)
++
+ clean-files := vmlinux.lds
+diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
+index 4b749c4..adf1d09 100644
+--- a/arch/powerpc/kernel/asm-offsets.c
++++ b/arch/powerpc/kernel/asm-offsets.c
+@@ -26,8 +26,6 @@
+ #ifdef CONFIG_PPC64
+ #include <linux/time.h>
+ #include <linux/hardirq.h>
+-#else
+-#include <linux/ptrace.h>
+ #endif
+
+ #include <asm/io.h>
+@@ -46,6 +44,9 @@
+ #include <asm/mmu.h>
+ #include <asm/hvcall.h>
+ #endif
++#ifdef CONFIG_PPC_ISERIES
++#include <asm/iseries/alpaca.h>
++#endif
+
+ #define DEFINE(sym, val) \
+ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+@@ -60,7 +61,6 @@ int main(void)
+ DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context));
+ #else
+ DEFINE(THREAD_INFO, offsetof(struct task_struct, stack));
+- DEFINE(PTRACE, offsetof(struct task_struct, ptrace));
+ #endif /* CONFIG_PPC64 */
+
+ DEFINE(KSP, offsetof(struct thread_struct, ksp));
+@@ -80,7 +80,6 @@ int main(void)
+ DEFINE(PGDIR, offsetof(struct thread_struct, pgdir));
+ #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+ DEFINE(THREAD_DBCR0, offsetof(struct thread_struct, dbcr0));
+- DEFINE(PT_PTRACED, PT_PTRACED);
+ #endif
+ #ifdef CONFIG_SPE
+ DEFINE(THREAD_EVR0, offsetof(struct thread_struct, evr[0]));
+@@ -94,10 +93,7 @@ int main(void)
+ DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
+ DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
+ DEFINE(TI_TASK, offsetof(struct thread_info, task));
+-#ifdef CONFIG_PPC32
+- DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
+ DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
+-#endif /* CONFIG_PPC32 */
+
+ #ifdef CONFIG_PPC64
+ DEFINE(DCACHEL1LINESIZE, offsetof(struct ppc64_caches, dline_size));
+@@ -166,13 +162,9 @@ int main(void)
+
+ /* Interrupt register frame */
+ DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD);
+-#ifndef CONFIG_PPC64
+- DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs));
+-#else /* CONFIG_PPC64 */
++ DEFINE(INT_FRAME_SIZE, STACK_INT_FRAME_SIZE);
++#ifdef CONFIG_PPC64
+ DEFINE(SWITCH_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs));
+- /* 288 = # of volatile regs, int & fp, for leaf routines */
+- /* which do not stack a frame. See the PPC64 ABI. */
+- DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 288);
+ /* Create extra stack space for SRR0 and SRR1 when calling prom/rtas. */
+ DEFINE(PROM_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16);
+ DEFINE(RTAS_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16);
+@@ -325,6 +317,9 @@ int main(void)
+ DEFINE(PAGE_OFFSET_VSID, KERNEL_VSID(PAGE_OFFSET));
+ DEFINE(VMALLOC_START_ESID, GET_ESID(VMALLOC_START));
+ DEFINE(VMALLOC_START_VSID, KERNEL_VSID(VMALLOC_START));
++
++ /* alpaca */
++ DEFINE(ALPACA_SIZE, sizeof(struct alpaca));
+ #endif
+
+ DEFINE(PGD_TABLE_SIZE, PGD_TABLE_SIZE);
+diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c
+index 80e2eef..9f93777 100644
+--- a/arch/powerpc/kernel/btext.c
++++ b/arch/powerpc/kernel/btext.c
+@@ -7,6 +7,7 @@
+ #include <linux/string.h>
+ #include <linux/init.h>
+ #include <linux/module.h>
++#include <linux/lmb.h>
+
+ #include <asm/sections.h>
+ #include <asm/prom.h>
+@@ -15,7 +16,7 @@
+ #include <asm/mmu.h>
+ #include <asm/pgtable.h>
+ #include <asm/io.h>
+-#include <asm/lmb.h>
++#include <asm/prom.h>
+ #include <asm/processor.h>
+ #include <asm/udbg.h>
+
+diff --git a/arch/powerpc/kernel/cpu_setup_44x.S b/arch/powerpc/kernel/cpu_setup_44x.S
+index 6250443..e3623e3 100644
+--- a/arch/powerpc/kernel/cpu_setup_44x.S
++++ b/arch/powerpc/kernel/cpu_setup_44x.S
+@@ -3,7 +3,7 @@
+ * Valentine Barshak <vbarshak at ru.mvista.com>
+ * MontaVista Software, Inc (c) 2007
+ *
+- * Based on cpu_setup_6xx code by
++ * Based on cpu_setup_6xx code by
+ * Benjamin Herrenschmidt <benh at kernel.crashing.org>
+ *
+ * This program is free software; you can redistribute it and/or
+@@ -32,6 +32,8 @@ _GLOBAL(__setup_cpu_440grx)
+ bl __fixup_440A_mcheck
+ mtlr r4
+ blr
++_GLOBAL(__setup_cpu_460ex)
++ b __init_fpu_44x
+ _GLOBAL(__setup_cpu_440gx)
+ _GLOBAL(__setup_cpu_440spe)
+ b __fixup_440A_mcheck
+diff --git a/arch/powerpc/kernel/cpu_setup_6xx.S b/arch/powerpc/kernel/cpu_setup_6xx.S
+index f1ee0b3..72d1d73 100644
+--- a/arch/powerpc/kernel/cpu_setup_6xx.S
++++ b/arch/powerpc/kernel/cpu_setup_6xx.S
+@@ -17,7 +17,13 @@
+ #include <asm/cache.h>
+
+ _GLOBAL(__setup_cpu_603)
+- b setup_common_caches
++ mflr r4
++BEGIN_FTR_SECTION
++ bl __init_fpu_registers
++END_FTR_SECTION_IFCLR(CPU_FTR_FPU_UNAVAILABLE)
++ bl setup_common_caches
++ mtlr r4
++ blr
+ _GLOBAL(__setup_cpu_604)
+ mflr r4
+ bl setup_common_caches
+diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
+index 2a8f5cc..36080d4 100644
+--- a/arch/powerpc/kernel/cputable.c
++++ b/arch/powerpc/kernel/cputable.c
+@@ -36,6 +36,7 @@ extern void __setup_cpu_440epx(unsigned long offset, struct cpu_spec* spec);
+ extern void __setup_cpu_440gx(unsigned long offset, struct cpu_spec* spec);
+ extern void __setup_cpu_440grx(unsigned long offset, struct cpu_spec* spec);
+ extern void __setup_cpu_440spe(unsigned long offset, struct cpu_spec* spec);
++extern void __setup_cpu_460ex(unsigned long offset, struct cpu_spec* spec);
+ extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec);
+ extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec);
+ extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec);
+@@ -1397,6 +1398,29 @@ static struct cpu_spec __initdata cpu_specs[] = {
+ .machine_check = machine_check_440A,
+ .platform = "ppc440",
+ },
++ { /* 460EX */
++ .pvr_mask = 0xffff0002,
++ .pvr_value = 0x13020002,
++ .cpu_name = "460EX",
++ .cpu_features = CPU_FTRS_44X,
++ .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .cpu_setup = __setup_cpu_460ex,
++ .machine_check = machine_check_440A,
++ .platform = "ppc440",
++ },
++ { /* 460GT */
++ .pvr_mask = 0xffff0002,
++ .pvr_value = 0x13020000,
++ .cpu_name = "460GT",
++ .cpu_features = CPU_FTRS_44X,
++ .cpu_user_features = COMMON_USER_BOOKE,
++ .icache_bsize = 32,
++ .dcache_bsize = 32,
++ .machine_check = machine_check_440A,
++ .platform = "ppc440",
++ },
+ #endif /* CONFIG_44x */
+ #ifdef CONFIG_FSL_BOOKE
+ #ifdef CONFIG_E200
+@@ -1512,7 +1536,7 @@ struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr)
+ *t = *s;
+ *PTRRELOC(&cur_cpu_spec) = &the_cpu_spec;
+ #if defined(CONFIG_PPC64) || defined(CONFIG_BOOKE)
+- /* ppc64 and booke expect identify_cpu to also call
++ /* ppc64 and booke expect identify_cpu to also call
+ * setup_cpu for that processor. I will consolidate
+ * that at a later time, for now, just use #ifdef.
+ * we also don't need to PTRRELOC the function pointer
+diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
+index 571132e..eae401d 100644
+--- a/arch/powerpc/kernel/crash.c
++++ b/arch/powerpc/kernel/crash.c
+@@ -24,12 +24,13 @@
+ #include <linux/init.h>
+ #include <linux/irq.h>
+ #include <linux/types.h>
++#include <linux/lmb.h>
+
+ #include <asm/processor.h>
+ #include <asm/machdep.h>
+ #include <asm/kexec.h>
+ #include <asm/kdump.h>
+-#include <asm/lmb.h>
++#include <asm/prom.h>
+ #include <asm/firmware.h>
+ #include <asm/smp.h>
+ #include <asm/system.h>
+diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
+index 29ff77c..9ee3c52 100644
+--- a/arch/powerpc/kernel/crash_dump.c
++++ b/arch/powerpc/kernel/crash_dump.c
+@@ -13,8 +13,9 @@
+
+ #include <linux/crash_dump.h>
+ #include <linux/bootmem.h>
++#include <linux/lmb.h>
+ #include <asm/kdump.h>
+-#include <asm/lmb.h>
++#include <asm/prom.h>
+ #include <asm/firmware.h>
+ #include <asm/uaccess.h>
+
+diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
+index 69a91bd..84c8686 100644
+--- a/arch/powerpc/kernel/entry_32.S
++++ b/arch/powerpc/kernel/entry_32.S
+@@ -110,9 +110,9 @@ transfer_to_handler:
+ stw r11,PT_REGS(r12)
+ #if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+ /* Check to see if the dbcr0 register is set up to debug. Use the
+- single-step bit to do this. */
++ internal debug mode bit to do this. */
+ lwz r12,THREAD_DBCR0(r12)
+- andis. r12,r12,DBCR0_IC at h
++ andis. r12,r12,DBCR0_IDM at h
+ beq+ 3f
+ /* From user and task is ptraced - load up global dbcr0 */
+ li r12,-1 /* clear all pending debug events */
+@@ -120,6 +120,12 @@ transfer_to_handler:
+ lis r11,global_dbcr0 at ha
+ tophys(r11,r11)
+ addi r11,r11,global_dbcr0 at l
++#ifdef CONFIG_SMP
++ rlwinm r9,r1,0,0,(31-THREAD_SHIFT)
++ lwz r9,TI_CPU(r9)
++ slwi r9,r9,3
++ add r11,r11,r9
++#endif
+ lwz r12,0(r11)
+ mtspr SPRN_DBCR0,r12
+ lwz r12,4(r11)
+@@ -238,10 +244,10 @@ ret_from_syscall:
+ stw r11,_CCR(r1)
+ syscall_exit_cont:
+ #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+- /* If the process has its own DBCR0 value, load it up. The single
+- step bit tells us that dbcr0 should be loaded. */
++ /* If the process has its own DBCR0 value, load it up. The internal
++ debug mode bit tells us that dbcr0 should be loaded. */
+ lwz r0,THREAD+THREAD_DBCR0(r2)
+- andis. r10,r0,DBCR0_IC at h
++ andis. r10,r0,DBCR0_IDM at h
+ bnel- load_dbcr0
+ #endif
+ #ifdef CONFIG_44x
+@@ -666,10 +672,10 @@ user_exc_return: /* r10 contains MSR_KERNEL here */
+
+ restore_user:
+ #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+- /* Check whether this process has its own DBCR0 value. The single
+- step bit tells us that dbcr0 should be loaded. */
++ /* Check whether this process has its own DBCR0 value. The internal
++ debug mode bit tells us that dbcr0 should be loaded. */
+ lwz r0,THREAD+THREAD_DBCR0(r2)
+- andis. r10,r0,DBCR0_IC at h
++ andis. r10,r0,DBCR0_IDM at h
+ bnel- load_dbcr0
+ #endif
+
+@@ -879,6 +885,12 @@ load_dbcr0:
+ mfspr r10,SPRN_DBCR0
+ lis r11,global_dbcr0 at ha
+ addi r11,r11,global_dbcr0 at l
++#ifdef CONFIG_SMP
++ rlwinm r9,r1,0,0,(31-THREAD_SHIFT)
++ lwz r9,TI_CPU(r9)
++ slwi r9,r9,3
++ add r11,r11,r9
++#endif
+ stw r10,0(r11)
+ mtspr SPRN_DBCR0,r0
+ lwz r10,4(r11)
+@@ -891,7 +903,7 @@ load_dbcr0:
+ .section .bss
+ .align 4
+ global_dbcr0:
+- .space 8
++ .space 8*NR_CPUS
+ .previous
+ #endif /* !(CONFIG_4xx || CONFIG_BOOKE) */
+
+diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
+index 148a354..c0db5b7 100644
+--- a/arch/powerpc/kernel/entry_64.S
++++ b/arch/powerpc/kernel/entry_64.S
+@@ -29,6 +29,8 @@
+ #include <asm/cputable.h>
+ #include <asm/firmware.h>
+ #include <asm/bug.h>
++#include <asm/ptrace.h>
++#include <asm/irqflags.h>
+
+ /*
+ * System calls.
+@@ -39,7 +41,7 @@
+
+ /* This value is used to mark exception frames on the stack. */
+ exception_marker:
+- .tc ID_72656773_68657265[TC],0x7265677368657265
++ .tc ID_EXC_MARKER[TC],STACK_FRAME_REGS_MARKER
+
+ .section ".text"
+ .align 7
+@@ -88,6 +90,14 @@ system_call_common:
+ addi r9,r1,STACK_FRAME_OVERHEAD
+ ld r11,exception_marker at toc(r2)
+ std r11,-16(r9) /* "regshere" marker */
++#ifdef CONFIG_TRACE_IRQFLAGS
++ bl .trace_hardirqs_on
++ REST_GPR(0,r1)
++ REST_4GPRS(3,r1)
++ REST_2GPRS(7,r1)
++ addi r9,r1,STACK_FRAME_OVERHEAD
++ ld r12,_MSR(r1)
++#endif /* CONFIG_TRACE_IRQFLAGS */
+ li r10,1
+ stb r10,PACASOFTIRQEN(r13)
+ stb r10,PACAHARDIRQEN(r13)
+@@ -102,7 +112,7 @@ BEGIN_FW_FTR_SECTION
+ b hardware_interrupt_entry
+ 2:
+ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
+-#endif
++#endif /* CONFIG_PPC_ISERIES */
+ mfmsr r11
+ ori r11,r11,MSR_EE
+ mtmsrd r11,1
+@@ -504,6 +514,10 @@ BEGIN_FW_FTR_SECTION
+
+ li r3,0
+ stb r3,PACASOFTIRQEN(r13) /* ensure we are soft-disabled */
++#ifdef CONFIG_TRACE_IRQFLAGS
++ bl .trace_hardirqs_off
++ mfmsr r10
++#endif
+ ori r10,r10,MSR_EE
+ mtmsrd r10 /* hard-enable again */
+ addi r3,r1,STACK_FRAME_OVERHEAD
+@@ -512,7 +526,7 @@ BEGIN_FW_FTR_SECTION
+ 4:
+ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
+ #endif
+- stb r5,PACASOFTIRQEN(r13)
++ TRACE_AND_RESTORE_IRQ(r5);
+
+ /* extract EE bit and use it to restore paca->hard_enabled */
+ ld r3,_MSR(r1)
+@@ -580,6 +594,16 @@ do_work:
+ bne restore
+ /* here we are preempting the current task */
+ 1:
++#ifdef CONFIG_TRACE_IRQFLAGS
++ bl .trace_hardirqs_on
++ /* Note: we just clobbered r10 which used to contain the previous
++ * MSR before the hard-disabling done by the caller of do_work.
++ * We don't have that value anymore, but it doesn't matter as
++ * we will hard-enable unconditionally, we can just reload the
++ * current MSR into r10
++ */
++ mfmsr r10
++#endif /* CONFIG_TRACE_IRQFLAGS */
+ li r0,1
+ stb r0,PACASOFTIRQEN(r13)
+ stb r0,PACAHARDIRQEN(r13)
+diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
+index 0f4fac5..785af9b 100644
+--- a/arch/powerpc/kernel/head_32.S
++++ b/arch/powerpc/kernel/head_32.S
+@@ -30,6 +30,7 @@
+ #include <asm/thread_info.h>
+ #include <asm/ppc_asm.h>
+ #include <asm/asm-offsets.h>
++#include <asm/ptrace.h>
+
+ /* 601 only have IBAT; cr0.eq is set on 601 when using this macro */
+ #define LOAD_BAT(n, reg, RA, RB) \
+@@ -268,8 +269,8 @@ __secondary_hold_acknowledge:
+ li r10,MSR_KERNEL & ~(MSR_IR|MSR_DR); /* can take exceptions */ \
+ MTMSRD(r10); /* (except for mach check in rtas) */ \
+ stw r0,GPR0(r11); \
+- lis r10,0x7265; /* put exception frame marker */ \
+- addi r10,r10,0x6773; \
++ lis r10,STACK_FRAME_REGS_MARKER at ha; /* exception frame marker */ \
++ addi r10,r10,STACK_FRAME_REGS_MARKER at l; \
+ stw r10,8(r11); \
+ SAVE_4GPRS(3, r11); \
+ SAVE_2GPRS(7, r11)
+@@ -763,23 +764,6 @@ load_up_altivec:
+ b fast_exception_return
+
+ /*
+- * AltiVec unavailable trap from kernel - print a message, but let
+- * the task use AltiVec in the kernel until it returns to user mode.
+- */
+-KernelAltiVec:
+- lwz r3,_MSR(r1)
+- oris r3,r3,MSR_VEC at h
+- stw r3,_MSR(r1) /* enable use of AltiVec after return */
+- lis r3,87f at h
+- ori r3,r3,87f at l
+- mr r4,r2 /* current */
+- lwz r5,_NIP(r1)
+- bl printk
+- b ret_from_except
+-87: .string "AltiVec used in kernel (task=%p, pc=%x) \n"
+- .align 4,0
+-
+-/*
+ * giveup_altivec(tsk)
+ * Disable AltiVec for the task given as the argument,
+ * and save the AltiVec registers in its thread_struct.
+diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
+index ad071a1..b84ec6a 100644
+--- a/arch/powerpc/kernel/head_44x.S
++++ b/arch/powerpc/kernel/head_44x.S
+@@ -211,7 +211,7 @@ skpinv: addi r4,r4,1 /* Increment */
+ SET_IVOR(12, WatchdogTimer);
+ SET_IVOR(13, DataTLBError);
+ SET_IVOR(14, InstructionTLBError);
+- SET_IVOR(15, Debug);
++ SET_IVOR(15, DebugCrit);
+
+ /* Establish the interrupt vector base */
+ lis r4,interrupt_base at h /* IVPR only uses the high 16-bits */
+@@ -578,7 +578,7 @@ interrupt_base:
+ b InstructionStorage
+
+ /* Debug Interrupt */
+- DEBUG_EXCEPTION
++ DEBUG_CRIT_EXCEPTION
+
+ /*
+ * Local functions
+diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
+index d3aee08..215973a 100644
+--- a/arch/powerpc/kernel/head_64.S
++++ b/arch/powerpc/kernel/head_64.S
+@@ -36,8 +36,7 @@
+ #include <asm/firmware.h>
+ #include <asm/page_64.h>
+ #include <asm/exception.h>
+-
+-#define DO_SOFT_DISABLE
++#include <asm/irqflags.h>
+
+ /*
+ * We layout physical memory as follows:
+@@ -450,8 +449,8 @@ bad_stack:
+ */
+ fast_exc_return_irq: /* restores irq state too */
+ ld r3,SOFTE(r1)
++ TRACE_AND_RESTORE_IRQ(r3);
+ ld r12,_MSR(r1)
+- stb r3,PACASOFTIRQEN(r13) /* restore paca->soft_enabled */
+ rldicl r4,r12,49,63 /* get MSR_EE to LSB */
+ stb r4,PACAHARDIRQEN(r13) /* restore paca->hard_enabled */
+ b 1f
+@@ -621,7 +620,7 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
+ mtlr r10
+
+ andi. r10,r12,MSR_RI /* check for unrecoverable exception */
+- beq- unrecov_slb
++ beq- 2f
+
+ .machine push
+ .machine "power4"
+@@ -643,6 +642,22 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
+ rfid
+ b . /* prevent speculative execution */
+
++2:
++#ifdef CONFIG_PPC_ISERIES
++BEGIN_FW_FTR_SECTION
++ b unrecov_slb
++END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
++#endif /* CONFIG_PPC_ISERIES */
++ mfspr r11,SPRN_SRR0
++ clrrdi r10,r13,32
++ LOAD_HANDLER(r10,unrecov_slb)
++ mtspr SPRN_SRR0,r10
++ mfmsr r10
++ ori r10,r10,MSR_IR|MSR_DR|MSR_RI
++ mtspr SPRN_SRR1,r10
++ rfid
++ b .
++
+ unrecov_slb:
+ EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB)
+ DISABLE_INTS
+@@ -808,7 +823,7 @@ _STATIC(load_up_altivec)
+ * Hash table stuff
+ */
+ .align 7
+-_GLOBAL(do_hash_page)
++_STATIC(do_hash_page)
+ std r3,_DAR(r1)
+ std r4,_DSISR(r1)
+
+@@ -820,6 +835,27 @@ BEGIN_FTR_SECTION
+ END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
+
+ /*
++ * On iSeries, we soft-disable interrupts here, then
++ * hard-enable interrupts so that the hash_page code can spin on
++ * the hash_table_lock without problems on a shared processor.
++ */
++ DISABLE_INTS
++
++ /*
++ * Currently, trace_hardirqs_off() will be called by DISABLE_INTS
++ * and will clobber volatile registers when irq tracing is enabled
++ * so we need to reload them. It may be possible to be smarter here
++ * and move the irq tracing elsewhere but let's keep it simple for
++ * now
++ */
++#ifdef CONFIG_TRACE_IRQFLAGS
++ ld r3,_DAR(r1)
++ ld r4,_DSISR(r1)
++ ld r5,_TRAP(r1)
++ ld r12,_MSR(r1)
++ clrrdi r5,r5,4
++#endif /* CONFIG_TRACE_IRQFLAGS */
++ /*
+ * We need to set the _PAGE_USER bit if MSR_PR is set or if we are
+ * accessing a userspace segment (even from the kernel). We assume
+ * kernel addresses always have the high bit set.
+@@ -832,13 +868,6 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
+ rlwimi r4,r5,22+2,31-2,31-2 /* Set _PAGE_EXEC if trap is 0x400 */
+
+ /*
+- * On iSeries, we soft-disable interrupts here, then
+- * hard-enable interrupts so that the hash_page code can spin on
+- * the hash_table_lock without problems on a shared processor.
+- */
+- DISABLE_INTS
+-
+- /*
+ * r3 contains the faulting address
+ * r4 contains the required access permissions
+ * r5 contains the trap number
+@@ -848,7 +877,6 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
+ bl .hash_page /* build HPTE if possible */
+ cmpdi r3,0 /* see if hash_page succeeded */
+
+-#ifdef DO_SOFT_DISABLE
+ BEGIN_FW_FTR_SECTION
+ /*
+ * If we had interrupts soft-enabled at the point where the
+@@ -860,7 +888,7 @@ BEGIN_FW_FTR_SECTION
+ */
+ beq 13f
+ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
+-#endif
++
+ BEGIN_FW_FTR_SECTION
+ /*
+ * Here we have interrupts hard-disabled, so it is sufficient
+@@ -874,11 +902,12 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
+
+ /*
+ * hash_page couldn't handle it, set soft interrupt enable back
+- * to what it was before the trap. Note that .local_irq_restore
++ * to what it was before the trap. Note that .raw_local_irq_restore
+ * handles any interrupts pending at this point.
+ */
+ ld r3,SOFTE(r1)
+- bl .local_irq_restore
++ TRACE_AND_RESTORE_IRQ_PARTIAL(r3, 11f)
++ bl .raw_local_irq_restore
+ b 11f
+
+ /* Here we have a page fault that hash_page can't handle. */
+@@ -1477,6 +1506,10 @@ _INIT_STATIC(start_here_multiplatform)
+ addi r2,r2,0x4000
+ add r2,r2,r26
+
++ /* Set initial ptr to current */
++ LOAD_REG_IMMEDIATE(r4, init_task)
++ std r4,PACACURRENT(r13)
++
+ /* Do very early kernel initializations, including initial hash table,
+ * stab and slb setup before we turn on relocation. */
+
+@@ -1505,10 +1538,6 @@ _INIT_GLOBAL(start_here_common)
+ li r0,0
+ stdu r0,-STACK_FRAME_OVERHEAD(r1)
+
+- /* ptr to current */
+- LOAD_REG_IMMEDIATE(r4, init_task)
+- std r4,PACACURRENT(r13)
+-
+ /* Load the TOC */
+ ld r2,PACATOC(r13)
+ std r1,PACAKSAVE(r13)
+diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h
+index ba9393f..aefafc6 100644
+--- a/arch/powerpc/kernel/head_booke.h
++++ b/arch/powerpc/kernel/head_booke.h
+@@ -56,8 +56,17 @@
+ * is necessary since the MMU is always on, for Book-E parts, and the stacks
+ * are offset from KERNELBASE.
+ *
++ * There is some space optimization to be had here if desired. However
++ * to allow for a common kernel with support for debug exceptions either
++ * going to critical or their own debug level we aren't currently
++ * providing configurations that micro-optimize space usage.
+ */
+-#define BOOKE_EXCEPTION_STACK_SIZE (8192)
++#ifdef CONFIG_44x
++#define NUM_EXCEPTION_LVLS 2
++#else
++#define NUM_EXCEPTION_LVLS 3
++#endif
++#define BOOKE_EXCEPTION_STACK_SIZE (4096 * NUM_EXCEPTION_LVLS)
+
+ /* CRIT_SPRG only used in critical exception handling */
+ #define CRIT_SPRG SPRN_SPRG2
+@@ -68,7 +77,7 @@
+ #define CRIT_STACK_TOP (exception_stack_top)
+
+ /* only on e200 for now */
+-#define DEBUG_STACK_TOP (exception_stack_top - 4096)
++#define DEBUG_STACK_TOP (exception_stack_top - 8192)
+ #define DEBUG_SPRG SPRN_SPRG6W
+
+ #ifdef CONFIG_SMP
+@@ -212,9 +221,8 @@ label:
+ * save (and later restore) the MSR via SPRN_CSRR1, which will still have
+ * the MSR_DE bit set.
+ */
+-#ifdef CONFIG_E200
+-#define DEBUG_EXCEPTION \
+- START_EXCEPTION(Debug); \
++#define DEBUG_DEBUG_EXCEPTION \
++ START_EXCEPTION(DebugDebug); \
+ DEBUG_EXCEPTION_PROLOG; \
+ \
+ /* \
+@@ -234,8 +242,8 @@ label:
+ cmplw r12,r10; \
+ blt+ 2f; /* addr below exception vectors */ \
+ \
+- lis r10,Debug at h; \
+- ori r10,r10,Debug at l; \
++ lis r10,DebugDebug at h; \
++ ori r10,r10,DebugDebug at l; \
+ cmplw r12,r10; \
+ bgt+ 2f; /* addr above exception vectors */ \
+ \
+@@ -265,9 +273,9 @@ label:
+ 2: mfspr r4,SPRN_DBSR; \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, debug_transfer_to_handler, ret_from_debug_exc)
+-#else
+-#define DEBUG_EXCEPTION \
+- START_EXCEPTION(Debug); \
++
++#define DEBUG_CRIT_EXCEPTION \
++ START_EXCEPTION(DebugCrit); \
+ CRITICAL_EXCEPTION_PROLOG; \
+ \
+ /* \
+@@ -287,8 +295,8 @@ label:
+ cmplw r12,r10; \
+ blt+ 2f; /* addr below exception vectors */ \
+ \
+- lis r10,Debug at h; \
+- ori r10,r10,Debug at l; \
++ lis r10,DebugCrit at h; \
++ ori r10,r10,DebugCrit at l; \
+ cmplw r12,r10; \
+ bgt+ 2f; /* addr above exception vectors */ \
+ \
+@@ -318,7 +326,6 @@ label:
+ 2: mfspr r4,SPRN_DBSR; \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)
+-#endif
+
+ #define INSTRUCTION_STORAGE_EXCEPTION \
+ START_EXCEPTION(InstructionStorage) \
+diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
+index d9cc2c2..e581524 100644
+--- a/arch/powerpc/kernel/head_fsl_booke.S
++++ b/arch/powerpc/kernel/head_fsl_booke.S
+@@ -68,7 +68,9 @@ _ENTRY(_start);
+ mr r29,r5
+ mr r28,r6
+ mr r27,r7
++ li r25,0 /* phys kernel start (low) */
+ li r24,0 /* CPU number */
++ li r23,0 /* phys kernel start (high) */
+
+ /* We try to not make any assumptions about how the boot loader
+ * setup or used the TLBs. We invalidate all mappings from the
+@@ -167,7 +169,28 @@ skpinv: addi r6,r6,1 /* Increment */
+ mtspr SPRN_MAS0,r7
+ tlbre
+
+- /* Just modify the entry ID, EPN and RPN for the temp mapping */
++ /* grab and fixup the RPN */
++ mfspr r6,SPRN_MAS1 /* extract MAS1[SIZE] */
++ rlwinm r6,r6,25,27,30
++ li r8,-1
++ addi r6,r6,10
++ slw r6,r8,r6 /* convert to mask */
++
++ bl 1f /* Find our address */
++1: mflr r7
++
++ mfspr r8,SPRN_MAS3
++#ifdef CONFIG_PHYS_64BIT
++ mfspr r23,SPRN_MAS7
++#endif
++ and r8,r6,r8
++ subfic r9,r6,-4096
++ and r9,r9,r7
++
++ or r25,r8,r9
++ ori r8,r25,(MAS3_SX|MAS3_SW|MAS3_SR)
++
++ /* Just modify the entry ID and EPN for the temp mapping */
+ lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
+ rlwimi r7,r5,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r5) */
+ mtspr SPRN_MAS0,r7
+@@ -177,12 +200,10 @@ skpinv: addi r6,r6,1 /* Increment */
+ ori r6,r6,(MAS1_TSIZE(BOOKE_PAGESZ_4K))@l
+ mtspr SPRN_MAS1,r6
+ mfspr r6,SPRN_MAS2
+- lis r7,PHYSICAL_START at h
++ li r7,0 /* temp EPN = 0 */
+ rlwimi r7,r6,0,20,31
+ mtspr SPRN_MAS2,r7
+- mfspr r6,SPRN_MAS3
+- rlwimi r7,r6,0,20,31
+- mtspr SPRN_MAS3,r7
++ mtspr SPRN_MAS3,r8
+ tlbwe
+
+ xori r6,r4,1
+@@ -232,8 +253,7 @@ skpinv: addi r6,r6,1 /* Increment */
+ ori r6,r6,PAGE_OFFSET at l
+ rlwimi r6,r7,0,20,31
+ mtspr SPRN_MAS2,r6
+- li r7,(MAS3_SX|MAS3_SW|MAS3_SR)
+- mtspr SPRN_MAS3,r7
++ mtspr SPRN_MAS3,r8
+ tlbwe
+
+ /* 7. Jump to KERNELBASE mapping */
+@@ -283,7 +303,10 @@ skpinv: addi r6,r6,1 /* Increment */
+ SET_IVOR(12, WatchdogTimer);
+ SET_IVOR(13, DataTLBError);
+ SET_IVOR(14, InstructionTLBError);
+- SET_IVOR(15, Debug);
++ SET_IVOR(15, DebugDebug);
++#if defined(CONFIG_E500)
++ SET_IVOR(15, DebugCrit);
++#endif
+ SET_IVOR(32, SPEUnavailable);
+ SET_IVOR(33, SPEFloatingPointData);
+ SET_IVOR(34, SPEFloatingPointRound);
+@@ -348,6 +371,17 @@ skpinv: addi r6,r6,1 /* Increment */
+
+ bl early_init
+
++#ifdef CONFIG_RELOCATABLE
++ lis r3,kernstart_addr at ha
++ la r3,kernstart_addr at l(r3)
++#ifdef CONFIG_PHYS_64BIT
++ stw r23,0(r3)
++ stw r25,4(r3)
++#else
++ stw r25,0(r3)
++#endif
++#endif
++
+ mfspr r3,SPRN_TLB1CFG
+ andi. r3,r3,0xfff
+ lis r4,num_tlbcam_entries at ha
+@@ -718,7 +752,10 @@ interrupt_base:
+
+
+ /* Debug Interrupt */
+- DEBUG_EXCEPTION
++ DEBUG_DEBUG_EXCEPTION
++#if defined(CONFIG_E500)
++ DEBUG_CRIT_EXCEPTION
++#endif
+
+ /*
+ * Local functions
+diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
+index 2f50bb5..9971159 100644
+--- a/arch/powerpc/kernel/ibmebus.c
++++ b/arch/powerpc/kernel/ibmebus.c
+@@ -183,7 +183,7 @@ static int ibmebus_create_devices(const struct of_device_id *matches)
+ ret = ibmebus_create_device(child);
+ if (ret) {
+ printk(KERN_ERR "%s: failed to create device (%i)",
+- __FUNCTION__, ret);
++ __func__, ret);
+ of_node_put(child);
+ break;
+ }
+@@ -269,7 +269,7 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
+ if (bus_find_device(&ibmebus_bus_type, NULL, path,
+ ibmebus_match_path)) {
+ printk(KERN_WARNING "%s: %s has already been probed\n",
+- __FUNCTION__, path);
++ __func__, path);
+ rc = -EEXIST;
+ goto out;
+ }
+@@ -279,7 +279,7 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
+ of_node_put(dn);
+ } else {
+ printk(KERN_WARNING "%s: no such device node: %s\n",
+- __FUNCTION__, path);
++ __func__, path);
+ rc = -ENODEV;
+ }
+
+@@ -308,7 +308,7 @@ static ssize_t ibmebus_store_remove(struct bus_type *bus,
+ return count;
+ } else {
+ printk(KERN_WARNING "%s: %s not on the bus\n",
+- __FUNCTION__, path);
++ __func__, path);
+
+ kfree(path);
+ return -ENODEV;
+@@ -337,14 +337,14 @@ static int __init ibmebus_bus_init(void)
+ err = of_bus_type_init(&ibmebus_bus_type, "ibmebus");
+ if (err) {
+ printk(KERN_ERR "%s: failed to register IBM eBus.\n",
+- __FUNCTION__);
++ __func__);
+ return err;
+ }
+
+ err = device_register(&ibmebus_bus_device);
+ if (err) {
+ printk(KERN_WARNING "%s: device_register returned %i\n",
+- __FUNCTION__, err);
++ __func__, err);
+ bus_unregister(&ibmebus_bus_type);
+
+ return err;
+diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
+index 8f1f4e5..0c66366 100644
+--- a/arch/powerpc/kernel/iommu.c
++++ b/arch/powerpc/kernel/iommu.c
+@@ -520,7 +520,7 @@ void iommu_free_table(struct iommu_table *tbl, const char *node_name)
+ unsigned int order;
+
+ if (!tbl || !tbl->it_map) {
+- printk(KERN_ERR "%s: expected TCE map for %s\n", __FUNCTION__,
++ printk(KERN_ERR "%s: expected TCE map for %s\n", __func__,
+ node_name);
+ return;
+ }
+@@ -530,7 +530,7 @@ void iommu_free_table(struct iommu_table *tbl, const char *node_name)
+ for (i = 0; i < (tbl->it_size/64); i++) {
+ if (tbl->it_map[i] != 0) {
+ printk(KERN_WARNING "%s: Unexpected TCEs for %s\n",
+- __FUNCTION__, node_name);
++ __func__, node_name);
+ break;
+ }
+ }
+diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
+index 292163f..425616f 100644
+--- a/arch/powerpc/kernel/irq.c
++++ b/arch/powerpc/kernel/irq.c
+@@ -114,7 +114,7 @@ static inline void set_soft_enabled(unsigned long enable)
+ : : "r" (enable), "i" (offsetof(struct paca_struct, soft_enabled)));
+ }
+
+-void local_irq_restore(unsigned long en)
++void raw_local_irq_restore(unsigned long en)
+ {
+ /*
+ * get_paca()->soft_enabled = en;
+@@ -174,6 +174,7 @@ void local_irq_restore(unsigned long en)
+
+ __hard_irq_enable();
+ }
++EXPORT_SYMBOL(raw_local_irq_restore);
+ #endif /* CONFIG_PPC64 */
+
+ int show_interrupts(struct seq_file *p, void *v)
+@@ -310,8 +311,21 @@ void do_IRQ(struct pt_regs *regs)
+ handler = &__do_IRQ;
+ irqtp->task = curtp->task;
+ irqtp->flags = 0;
++
++ /* Copy the softirq bits in preempt_count so that the
++ * softirq checks work in the hardirq context.
++ */
++ irqtp->preempt_count =
++ (irqtp->preempt_count & ~SOFTIRQ_MASK) |
++ (curtp->preempt_count & SOFTIRQ_MASK);
++
+ call_handle_irq(irq, desc, irqtp, handler);
+ irqtp->task = NULL;
++
++
++ /* Set any flag that may have been set on the
++ * alternate stack
++ */
+ if (irqtp->flags)
+ set_bits(irqtp->flags, &curtp->flags);
+ } else
+@@ -357,7 +371,7 @@ void irq_ctx_init(void)
+ memset((void *)softirq_ctx[i], 0, THREAD_SIZE);
+ tp = softirq_ctx[i];
+ tp->cpu = i;
+- tp->preempt_count = SOFTIRQ_OFFSET;
++ tp->preempt_count = 0;
+
+ memset((void *)hardirq_ctx[i], 0, THREAD_SIZE);
+ tp = hardirq_ctx[i];
+diff --git a/arch/powerpc/kernel/isa-bridge.c b/arch/powerpc/kernel/isa-bridge.c
+index ee172aa..289af34 100644
+--- a/arch/powerpc/kernel/isa-bridge.c
++++ b/arch/powerpc/kernel/isa-bridge.c
+@@ -80,13 +80,13 @@ static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
+ * (size depending on dev->n_addr_cells)
+ * cell 5: the size of the range
+ */
+- if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO) {
++ if ((range->isa_addr.a_hi & ISA_SPACE_MASK) != ISA_SPACE_IO) {
+ range++;
+ rlen -= sizeof(struct isa_range);
+ if (rlen < sizeof(struct isa_range))
+ goto inval_range;
+ }
+- if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO)
++ if ((range->isa_addr.a_hi & ISA_SPACE_MASK) != ISA_SPACE_IO)
+ goto inval_range;
+
+ isa_addr = range->isa_addr.a_lo;
+@@ -99,7 +99,7 @@ static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
+ */
+ if ((pci_addr != 0) || (isa_addr != 0)) {
+ printk(KERN_ERR "unexpected isa to pci mapping: %s\n",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+
+diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
+index dcb89a8..1ffacc6 100644
+--- a/arch/powerpc/kernel/lparcfg.c
++++ b/arch/powerpc/kernel/lparcfg.c
+@@ -226,7 +226,7 @@ static void parse_system_parameter_string(struct seq_file *m)
+ unsigned char *local_buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
+ if (!local_buffer) {
+ printk(KERN_ERR "%s %s kmalloc failure at line %d \n",
+- __FILE__, __FUNCTION__, __LINE__);
++ __FILE__, __func__, __LINE__);
+ return;
+ }
+
+@@ -243,14 +243,14 @@ static void parse_system_parameter_string(struct seq_file *m)
+ if (call_status != 0) {
+ printk(KERN_INFO
+ "%s %s Error calling get-system-parameter (0x%x)\n",
+- __FILE__, __FUNCTION__, call_status);
++ __FILE__, __func__, call_status);
+ } else {
+ int splpar_strlen;
+ int idx, w_idx;
+ char *workbuffer = kzalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
+ if (!workbuffer) {
+ printk(KERN_ERR "%s %s kmalloc failure at line %d \n",
+- __FILE__, __FUNCTION__, __LINE__);
++ __FILE__, __func__, __LINE__);
+ kfree(local_buffer);
+ return;
+ }
+@@ -484,10 +484,10 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf,
+ current_weight = (resource >> 5 * 8) & 0xFF;
+
+ pr_debug("%s: current_entitled = %lu, current_weight = %u\n",
+- __FUNCTION__, current_entitled, current_weight);
++ __func__, current_entitled, current_weight);
+
+ pr_debug("%s: new_entitled = %lu, new_weight = %u\n",
+- __FUNCTION__, *new_entitled_ptr, *new_weight_ptr);
++ __func__, *new_entitled_ptr, *new_weight_ptr);
+
+ retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr,
+ *new_weight_ptr);
+@@ -502,7 +502,7 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf,
+ retval = -EINVAL;
+ } else {
+ printk(KERN_WARNING "%s: received unknown hv return code %ld",
+- __FUNCTION__, retval);
++ __func__, retval);
+ retval = -EIO;
+ }
+
+diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c
+index c0c8e8c..2d202f2 100644
+--- a/arch/powerpc/kernel/machine_kexec.c
++++ b/arch/powerpc/kernel/machine_kexec.c
+@@ -12,8 +12,9 @@
+ #include <linux/kexec.h>
+ #include <linux/reboot.h>
+ #include <linux/threads.h>
++#include <linux/lmb.h>
+ #include <asm/machdep.h>
+-#include <asm/lmb.h>
++#include <asm/prom.h>
+
+ void machine_crash_shutdown(struct pt_regs *regs)
+ {
+diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
+index 9d2c566..92ccc6f 100644
+--- a/arch/powerpc/kernel/misc_32.S
++++ b/arch/powerpc/kernel/misc_32.S
+@@ -152,7 +152,7 @@ _GLOBAL(low_choose_750fx_pll)
+ mtspr SPRN_HID1,r4
+
+ /* Store new HID1 image */
+- rlwinm r6,r1,0,0,18
++ rlwinm r6,r1,0,0,(31-THREAD_SHIFT)
+ lwz r6,TI_CPU(r6)
+ slwi r6,r6,2
+ addis r6,r6,nap_save_hid1 at ha
+@@ -281,7 +281,7 @@ _GLOBAL(_tlbia)
+ #endif /* CONFIG_SMP */
+ #else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */
+ #if defined(CONFIG_SMP)
+- rlwinm r8,r1,0,0,18
++ rlwinm r8,r1,0,0,(31-THREAD_SHIFT)
+ lwz r8,TI_CPU(r8)
+ oris r8,r8,10
+ mfmsr r10
+@@ -377,7 +377,7 @@ _GLOBAL(_tlbie)
+ #endif /* CONFIG_SMP */
+ #else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */
+ #if defined(CONFIG_SMP)
+- rlwinm r8,r1,0,0,18
++ rlwinm r8,r1,0,0,(31-THREAD_SHIFT)
+ lwz r8,TI_CPU(r8)
+ oris r8,r8,11
+ mfmsr r10
+diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
+index a3c491e..942951e 100644
+--- a/arch/powerpc/kernel/misc_64.S
++++ b/arch/powerpc/kernel/misc_64.S
+@@ -27,23 +27,11 @@
+
+ .text
+
+-_GLOBAL(get_msr)
+- mfmsr r3
+- blr
+-
+-_GLOBAL(get_srr0)
+- mfsrr0 r3
+- blr
+-
+-_GLOBAL(get_srr1)
+- mfsrr1 r3
+- blr
+-
+ #ifdef CONFIG_IRQSTACKS
+ _GLOBAL(call_do_softirq)
+ mflr r0
+ std r0,16(r1)
+- stdu r1,THREAD_SIZE-112(r3)
++ stdu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
+ mr r1,r3
+ bl .__do_softirq
+ ld r1,0(r1)
+@@ -56,7 +44,7 @@ _GLOBAL(call_handle_irq)
+ mflr r0
+ std r0,16(r1)
+ mtctr r8
+- stdu r1,THREAD_SIZE-112(r5)
++ stdu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r5)
+ mr r1,r5
+ bctrl
+ ld r1,0(r1)
+@@ -599,7 +587,7 @@ _GLOBAL(kexec_sequence)
+ std r0,16(r1)
+
+ /* switch stacks to newstack -- &kexec_stack.stack */
+- stdu r1,THREAD_SIZE-112(r3)
++ stdu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
+ mr r1,r3
+
+ li r0,0
+@@ -616,7 +604,7 @@ _GLOBAL(kexec_sequence)
+ std r26,-48(r1)
+ std r25,-56(r1)
+
+- stdu r1,-112-64(r1)
++ stdu r1,-STACK_FRAME_OVERHEAD-64(r1)
+
+ /* save args into preserved regs */
+ mr r31,r3 /* newstack (both) */
+diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
+index fb698d4..e79ad8a 100644
+--- a/arch/powerpc/kernel/of_platform.c
++++ b/arch/powerpc/kernel/of_platform.c
+@@ -275,6 +275,8 @@ static int __devinit of_pci_phb_probe(struct of_device *dev,
+
+ /* Scan the bus */
+ scan_phb(phb);
++ if (phb->bus == NULL)
++ return -ENXIO;
+
+ /* Claim resources. This might need some rework as well depending
+ * wether we are doing probe-only or not, like assigning unassigned
+diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
+index 55f1a25..c9bf17e 100644
+--- a/arch/powerpc/kernel/paca.c
++++ b/arch/powerpc/kernel/paca.c
+@@ -7,31 +7,24 @@
+ * 2 of the License, or (at your option) any later version.
+ */
+
+-#include <linux/types.h>
+ #include <linux/threads.h>
+ #include <linux/module.h>
+
+-#include <asm/processor.h>
+-#include <asm/ptrace.h>
+-#include <asm/page.h>
+ #include <asm/lppaca.h>
+-#include <asm/iseries/it_lp_reg_save.h>
+ #include <asm/paca.h>
+-#include <asm/mmu.h>
+-
+
+ /* This symbol is provided by the linker - let it fill in the paca
+ * field correctly */
+ extern unsigned long __toc_start;
+
+ /*
+- * iSeries structure which the hypervisor knows about - this structure
++ * The structure which the hypervisor knows about - this structure
+ * should not cross a page boundary. The vpa_init/register_vpa call
+ * is now known to fail if the lppaca structure crosses a page
+- * boundary. The lppaca is also used on POWER5 pSeries boxes. The
+- * lppaca is 640 bytes long, and cannot readily change since the
+- * hypervisor knows its layout, so a 1kB alignment will suffice to
+- * ensure that it doesn't cross a page boundary.
++ * boundary. The lppaca is also used on legacy iSeries and POWER5
++ * pSeries boxes. The lppaca is 640 bytes long, and cannot readily
++ * change since the hypervisor knows its layout, so a 1kB alignment
++ * will suffice to ensure that it doesn't cross a page boundary.
+ */
+ struct lppaca lppaca[] = {
+ [0 ... (NR_CPUS-1)] = {
+@@ -66,75 +59,29 @@ struct slb_shadow slb_shadow[] __cacheline_aligned = {
+ * processors. The processor VPD array needs one entry per physical
+ * processor (not thread).
+ */
+-#define PACA_INIT_COMMON(number) \
+- .lppaca_ptr = &lppaca[number], \
+- .lock_token = 0x8000, \
+- .paca_index = (number), /* Paca Index */ \
+- .kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL, \
+- .hw_cpu_id = 0xffff, \
+- .slb_shadow_ptr = &slb_shadow[number],
++struct paca_struct paca[NR_CPUS];
++EXPORT_SYMBOL(paca);
+
+-#ifdef CONFIG_PPC_ISERIES
+-#define PACA_INIT_ISERIES(number) \
+- .reg_save_ptr = &iseries_reg_save[number],
++void __init initialise_pacas(void)
++{
++ int cpu;
+
+-#define PACA_INIT(number) \
+-{ \
+- PACA_INIT_COMMON(number) \
+- PACA_INIT_ISERIES(number) \
+-}
++ /* The TOC register (GPR2) points 32kB into the TOC, so that 64kB
++ * of the TOC can be addressed using a single machine instruction.
++ */
++ unsigned long kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL;
+
+-#else
+-#define PACA_INIT(number) \
+-{ \
+- PACA_INIT_COMMON(number) \
+-}
++ /* Can't use for_each_*_cpu, as they aren't functional yet */
++ for (cpu = 0; cpu < NR_CPUS; cpu++) {
++ struct paca_struct *new_paca = &paca[cpu];
+
+-#endif
++ new_paca->lppaca_ptr = &lppaca[cpu];
++ new_paca->lock_token = 0x8000;
++ new_paca->paca_index = cpu;
++ new_paca->kernel_toc = kernel_toc;
++ new_paca->hw_cpu_id = 0xffff;
++ new_paca->slb_shadow_ptr = &slb_shadow[cpu];
++ new_paca->__current = &init_task;
+
+-struct paca_struct paca[] = {
+- PACA_INIT(0),
+-#if NR_CPUS > 1
+- PACA_INIT( 1), PACA_INIT( 2), PACA_INIT( 3),
+-#if NR_CPUS > 4
+- PACA_INIT( 4), PACA_INIT( 5), PACA_INIT( 6), PACA_INIT( 7),
+-#if NR_CPUS > 8
+- PACA_INIT( 8), PACA_INIT( 9), PACA_INIT( 10), PACA_INIT( 11),
+- PACA_INIT( 12), PACA_INIT( 13), PACA_INIT( 14), PACA_INIT( 15),
+- PACA_INIT( 16), PACA_INIT( 17), PACA_INIT( 18), PACA_INIT( 19),
+- PACA_INIT( 20), PACA_INIT( 21), PACA_INIT( 22), PACA_INIT( 23),
+- PACA_INIT( 24), PACA_INIT( 25), PACA_INIT( 26), PACA_INIT( 27),
+- PACA_INIT( 28), PACA_INIT( 29), PACA_INIT( 30), PACA_INIT( 31),
+-#if NR_CPUS > 32
+- PACA_INIT( 32), PACA_INIT( 33), PACA_INIT( 34), PACA_INIT( 35),
+- PACA_INIT( 36), PACA_INIT( 37), PACA_INIT( 38), PACA_INIT( 39),
+- PACA_INIT( 40), PACA_INIT( 41), PACA_INIT( 42), PACA_INIT( 43),
+- PACA_INIT( 44), PACA_INIT( 45), PACA_INIT( 46), PACA_INIT( 47),
+- PACA_INIT( 48), PACA_INIT( 49), PACA_INIT( 50), PACA_INIT( 51),
+- PACA_INIT( 52), PACA_INIT( 53), PACA_INIT( 54), PACA_INIT( 55),
+- PACA_INIT( 56), PACA_INIT( 57), PACA_INIT( 58), PACA_INIT( 59),
+- PACA_INIT( 60), PACA_INIT( 61), PACA_INIT( 62), PACA_INIT( 63),
+-#if NR_CPUS > 64
+- PACA_INIT( 64), PACA_INIT( 65), PACA_INIT( 66), PACA_INIT( 67),
+- PACA_INIT( 68), PACA_INIT( 69), PACA_INIT( 70), PACA_INIT( 71),
+- PACA_INIT( 72), PACA_INIT( 73), PACA_INIT( 74), PACA_INIT( 75),
+- PACA_INIT( 76), PACA_INIT( 77), PACA_INIT( 78), PACA_INIT( 79),
+- PACA_INIT( 80), PACA_INIT( 81), PACA_INIT( 82), PACA_INIT( 83),
+- PACA_INIT( 84), PACA_INIT( 85), PACA_INIT( 86), PACA_INIT( 87),
+- PACA_INIT( 88), PACA_INIT( 89), PACA_INIT( 90), PACA_INIT( 91),
+- PACA_INIT( 92), PACA_INIT( 93), PACA_INIT( 94), PACA_INIT( 95),
+- PACA_INIT( 96), PACA_INIT( 97), PACA_INIT( 98), PACA_INIT( 99),
+- PACA_INIT(100), PACA_INIT(101), PACA_INIT(102), PACA_INIT(103),
+- PACA_INIT(104), PACA_INIT(105), PACA_INIT(106), PACA_INIT(107),
+- PACA_INIT(108), PACA_INIT(109), PACA_INIT(110), PACA_INIT(111),
+- PACA_INIT(112), PACA_INIT(113), PACA_INIT(114), PACA_INIT(115),
+- PACA_INIT(116), PACA_INIT(117), PACA_INIT(118), PACA_INIT(119),
+- PACA_INIT(120), PACA_INIT(121), PACA_INIT(122), PACA_INIT(123),
+- PACA_INIT(124), PACA_INIT(125), PACA_INIT(126), PACA_INIT(127),
+-#endif
+-#endif
+-#endif
+-#endif
+-#endif
+-};
+-EXPORT_SYMBOL(paca);
++ }
++}
+diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
+index 89c83cc..063cdd4 100644
+--- a/arch/powerpc/kernel/pci-common.c
++++ b/arch/powerpc/kernel/pci-common.c
+@@ -1161,41 +1161,9 @@ EXPORT_SYMBOL_GPL(pcibios_claim_one_bus);
+
+ int pcibios_enable_device(struct pci_dev *dev, int mask)
+ {
+- u16 cmd, old_cmd;
+- int idx;
+- struct resource *r;
+-
+ if (ppc_md.pcibios_enable_device_hook)
+ if (ppc_md.pcibios_enable_device_hook(dev))
+ return -EINVAL;
+
+- pci_read_config_word(dev, PCI_COMMAND, &cmd);
+- old_cmd = cmd;
+- for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
+- /* Only set up the requested stuff */
+- if (!(mask & (1 << idx)))
+- continue;
+- r = &dev->resource[idx];
+- if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
+- continue;
+- if ((idx == PCI_ROM_RESOURCE) &&
+- (!(r->flags & IORESOURCE_ROM_ENABLE)))
+- continue;
+- if (r->parent == NULL) {
+- printk(KERN_ERR "PCI: Device %s not available because"
+- " of resource collisions\n", pci_name(dev));
+- return -EINVAL;
+- }
+- if (r->flags & IORESOURCE_IO)
+- cmd |= PCI_COMMAND_IO;
+- if (r->flags & IORESOURCE_MEM)
+- cmd |= PCI_COMMAND_MEMORY;
+- }
+- if (cmd != old_cmd) {
+- printk("PCI: Enabling device %s (%04x -> %04x)\n",
+- pci_name(dev), old_cmd, cmd);
+- pci_write_config_word(dev, PCI_COMMAND, cmd);
+- }
+- return 0;
++ return pci_enable_resources(dev, mask);
+ }
+-
+diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
+index 9c98424..09fcb50 100644
+--- a/arch/powerpc/kernel/ppc_ksyms.c
++++ b/arch/powerpc/kernel/ppc_ksyms.c
+@@ -15,7 +15,6 @@
+ #include <linux/bitops.h>
+
+ #include <asm/page.h>
+-#include <asm/semaphore.h>
+ #include <asm/processor.h>
+ #include <asm/cacheflush.h>
+ #include <asm/uaccess.h>
+@@ -45,10 +44,6 @@
+ #include <asm/signal.h>
+ #include <asm/dcr.h>
+
+-#ifdef CONFIG_PPC64
+-EXPORT_SYMBOL(local_irq_restore);
+-#endif
+-
+ #ifdef CONFIG_PPC32
+ extern void transfer_to_handler(void);
+ extern void do_IRQ(struct pt_regs *regs);
+@@ -58,7 +53,6 @@ extern void program_check_exception(struct pt_regs *regs);
+ extern void single_step_exception(struct pt_regs *regs);
+ extern int sys_sigreturn(struct pt_regs *regs);
+
+-EXPORT_SYMBOL(empty_zero_page);
+ EXPORT_SYMBOL(clear_pages);
+ EXPORT_SYMBOL(copy_page);
+ EXPORT_SYMBOL(ISA_DMA_THRESHOLD);
+@@ -79,6 +73,7 @@ EXPORT_SYMBOL(strncpy);
+ EXPORT_SYMBOL(strcat);
+ EXPORT_SYMBOL(strlen);
+ EXPORT_SYMBOL(strcmp);
++EXPORT_SYMBOL(strncmp);
+
+ EXPORT_SYMBOL(csum_partial);
+ EXPORT_SYMBOL(csum_partial_copy_generic);
+@@ -192,3 +187,4 @@ EXPORT_SYMBOL(intercept_table);
+ EXPORT_SYMBOL(__mtdcr);
+ EXPORT_SYMBOL(__mfdcr);
+ #endif
++EXPORT_SYMBOL(empty_zero_page);
+diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
+index 4ec6055..6caad17 100644
+--- a/arch/powerpc/kernel/process.c
++++ b/arch/powerpc/kernel/process.c
+@@ -868,11 +868,6 @@ int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
+ flush_spe_to_thread(current);
+ error = do_execve(filename, (char __user * __user *) a1,
+ (char __user * __user *) a2, regs);
+- if (error == 0) {
+- task_lock(current);
+- current->ptrace &= ~PT_DTRACE;
+- task_unlock(current);
+- }
+ putname(filename);
+ out:
+ return error;
+@@ -919,20 +914,6 @@ int validate_sp(unsigned long sp, struct task_struct *p,
+ return valid_irq_stack(sp, p, nbytes);
+ }
+
+-#ifdef CONFIG_PPC64
+-#define MIN_STACK_FRAME 112 /* same as STACK_FRAME_OVERHEAD, in fact */
+-#define FRAME_LR_SAVE 2
+-#define INT_FRAME_SIZE (sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD + 288)
+-#define REGS_MARKER 0x7265677368657265ul
+-#define FRAME_MARKER 12
+-#else
+-#define MIN_STACK_FRAME 16
+-#define FRAME_LR_SAVE 1
+-#define INT_FRAME_SIZE (sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD)
+-#define REGS_MARKER 0x72656773ul
+-#define FRAME_MARKER 2
+-#endif
+-
+ EXPORT_SYMBOL(validate_sp);
+
+ unsigned long get_wchan(struct task_struct *p)
+@@ -944,15 +925,15 @@ unsigned long get_wchan(struct task_struct *p)
+ return 0;
+
+ sp = p->thread.ksp;
+- if (!validate_sp(sp, p, MIN_STACK_FRAME))
++ if (!validate_sp(sp, p, STACK_FRAME_OVERHEAD))
+ return 0;
+
+ do {
+ sp = *(unsigned long *)sp;
+- if (!validate_sp(sp, p, MIN_STACK_FRAME))
++ if (!validate_sp(sp, p, STACK_FRAME_OVERHEAD))
+ return 0;
+ if (count > 0) {
+- ip = ((unsigned long *)sp)[FRAME_LR_SAVE];
++ ip = ((unsigned long *)sp)[STACK_FRAME_LR_SAVE];
+ if (!in_sched_functions(ip))
+ return ip;
+ }
+@@ -981,12 +962,12 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
+ lr = 0;
+ printk("Call Trace:\n");
+ do {
+- if (!validate_sp(sp, tsk, MIN_STACK_FRAME))
++ if (!validate_sp(sp, tsk, STACK_FRAME_OVERHEAD))
+ return;
+
+ stack = (unsigned long *) sp;
+ newsp = stack[0];
+- ip = stack[FRAME_LR_SAVE];
++ ip = stack[STACK_FRAME_LR_SAVE];
+ if (!firstframe || ip != lr) {
+ printk("["REG"] ["REG"] ", sp, ip);
+ print_symbol("%s", ip);
+@@ -1000,8 +981,8 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
+ * See if this is an exception frame.
+ * We look for the "regshere" marker in the current frame.
+ */
+- if (validate_sp(sp, tsk, INT_FRAME_SIZE)
+- && stack[FRAME_MARKER] == REGS_MARKER) {
++ if (validate_sp(sp, tsk, STACK_INT_FRAME_SIZE)
++ && stack[STACK_FRAME_MARKER] == STACK_FRAME_REGS_MARKER) {
+ struct pt_regs *regs = (struct pt_regs *)
+ (sp + STACK_FRAME_OVERHEAD);
+ printk("--- Exception: %lx", regs->trap);
+@@ -1052,3 +1033,34 @@ void ppc64_runlatch_off(void)
+ }
+ }
+ #endif
++
++#if THREAD_SHIFT < PAGE_SHIFT
++
++static struct kmem_cache *thread_info_cache;
++
++struct thread_info *alloc_thread_info(struct task_struct *tsk)
++{
++ struct thread_info *ti;
++
++ ti = kmem_cache_alloc(thread_info_cache, GFP_KERNEL);
++ if (unlikely(ti == NULL))
++ return NULL;
++#ifdef CONFIG_DEBUG_STACK_USAGE
++ memset(ti, 0, THREAD_SIZE);
++#endif
++ return ti;
++}
++
++void free_thread_info(struct thread_info *ti)
++{
++ kmem_cache_free(thread_info_cache, ti);
++}
++
++void thread_info_cache_init(void)
++{
++ thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE,
++ THREAD_SIZE, 0, NULL);
++ BUG_ON(thread_info_cache == NULL);
++}
++
++#endif /* THREAD_SHIFT < PAGE_SHIFT */
+diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
+index eac97f4..2aefe2a 100644
+--- a/arch/powerpc/kernel/prom.c
++++ b/arch/powerpc/kernel/prom.c
+@@ -31,10 +31,10 @@
+ #include <linux/kexec.h>
+ #include <linux/debugfs.h>
+ #include <linux/irq.h>
++#include <linux/lmb.h>
+
+ #include <asm/prom.h>
+ #include <asm/rtas.h>
+-#include <asm/lmb.h>
+ #include <asm/page.h>
+ #include <asm/processor.h>
+ #include <asm/irq.h>
+@@ -51,7 +51,9 @@
+ #include <asm/machdep.h>
+ #include <asm/pSeries_reconfig.h>
+ #include <asm/pci-bridge.h>
++#include <asm/phyp_dump.h>
+ #include <asm/kexec.h>
++#include <mm/mmu_decl.h>
+
+ #ifdef DEBUG
+ #define DBG(fmt...) printk(KERN_ERR fmt)
+@@ -436,7 +438,7 @@ early_param("mem", early_parse_mem);
+ * The device tree may be allocated beyond our memory limit, or inside the
+ * crash kernel region for kdump. If so, move it out of the way.
+ */
+-static void move_device_tree(void)
++static void __init move_device_tree(void)
+ {
+ unsigned long start, size;
+ void *p;
+@@ -977,7 +979,10 @@ static int __init early_init_dt_scan_memory(unsigned long node,
+ }
+ #endif
+ lmb_add(base, size);
++
++ memstart_addr = min((u64)memstart_addr, base);
+ }
++
+ return 0;
+ }
+
+@@ -1040,6 +1045,87 @@ static void __init early_reserve_mem(void)
+ #endif
+ }
+
++#ifdef CONFIG_PHYP_DUMP
++/**
++ * phyp_dump_calculate_reserve_size() - reserve variable boot area 5% or arg
++ *
++ * Function to find the largest size we need to reserve
++ * during early boot process.
++ *
++ * It either looks for boot param and returns that OR
++ * returns larger of 256 or 5% rounded down to multiples of 256MB.
++ *
++ */
++static inline unsigned long phyp_dump_calculate_reserve_size(void)
++{
++ unsigned long tmp;
++
++ if (phyp_dump_info->reserve_bootvar)
++ return phyp_dump_info->reserve_bootvar;
++
++ /* divide by 20 to get 5% of value */
++ tmp = lmb_end_of_DRAM();
++ do_div(tmp, 20);
++
++ /* round it down in multiples of 256 */
++ tmp = tmp & ~0x0FFFFFFFUL;
++
++ return (tmp > PHYP_DUMP_RMR_END ? tmp : PHYP_DUMP_RMR_END);
++}
++
++/**
++ * phyp_dump_reserve_mem() - reserve all not-yet-dumped mmemory
++ *
++ * This routine may reserve memory regions in the kernel only
++ * if the system is supported and a dump was taken in last
++ * boot instance or if the hardware is supported and the
++ * scratch area needs to be setup. In other instances it returns
++ * without reserving anything. The memory in case of dump being
++ * active is freed when the dump is collected (by userland tools).
++ */
++static void __init phyp_dump_reserve_mem(void)
++{
++ unsigned long base, size;
++ unsigned long variable_reserve_size;
++
++ if (!phyp_dump_info->phyp_dump_configured) {
++ printk(KERN_ERR "Phyp-dump not supported on this hardware\n");
++ return;
++ }
++
++ if (!phyp_dump_info->phyp_dump_at_boot) {
++ printk(KERN_INFO "Phyp-dump disabled at boot time\n");
++ return;
++ }
++
++ variable_reserve_size = phyp_dump_calculate_reserve_size();
++
++ if (phyp_dump_info->phyp_dump_is_active) {
++ /* Reserve *everything* above RMR.Area freed by userland tools*/
++ base = variable_reserve_size;
++ size = lmb_end_of_DRAM() - base;
++
++ /* XXX crashed_ram_end is wrong, since it may be beyond
++ * the memory_limit, it will need to be adjusted. */
++ lmb_reserve(base, size);
++
++ phyp_dump_info->init_reserve_start = base;
++ phyp_dump_info->init_reserve_size = size;
++ } else {
++ size = phyp_dump_info->cpu_state_size +
++ phyp_dump_info->hpte_region_size +
++ variable_reserve_size;
++ base = lmb_end_of_DRAM() - size;
++ lmb_reserve(base, size);
++ phyp_dump_info->init_reserve_start = base;
++ phyp_dump_info->init_reserve_size = size;
++ }
++}
++#else
++static inline void __init phyp_dump_reserve_mem(void) {}
++#endif /* CONFIG_PHYP_DUMP && CONFIG_PPC_RTAS */
++
++
+ void __init early_init_devtree(void *params)
+ {
+ DBG(" -> early_init_devtree(%p)\n", params);
+@@ -1052,6 +1138,11 @@ void __init early_init_devtree(void *params)
+ of_scan_flat_dt(early_init_dt_scan_rtas, NULL);
+ #endif
+
++#ifdef CONFIG_PHYP_DUMP
++ /* scan tree to see if dump occured during last boot */
++ of_scan_flat_dt(early_init_dt_scan_phyp_dump, NULL);
++#endif
++
+ /* Retrieve various informations from the /chosen node of the
+ * device-tree, including the platform type, initrd location and
+ * size, TCE reserve, and more ...
+@@ -1072,6 +1163,7 @@ void __init early_init_devtree(void *params)
+ reserve_kdump_trampoline();
+ reserve_crashkernel();
+ early_reserve_mem();
++ phyp_dump_reserve_mem();
+
+ lmb_enforce_memory_limit(memory_limit);
+ lmb_analyze();
+@@ -1244,12 +1336,14 @@ EXPORT_SYMBOL(of_node_put);
+ */
+ void of_attach_node(struct device_node *np)
+ {
+- write_lock(&devtree_lock);
++ unsigned long flags;
++
++ write_lock_irqsave(&devtree_lock, flags);
+ np->sibling = np->parent->child;
+ np->allnext = allnodes;
+ np->parent->child = np;
+ allnodes = np;
+- write_unlock(&devtree_lock);
++ write_unlock_irqrestore(&devtree_lock, flags);
+ }
+
+ /*
+@@ -1260,8 +1354,9 @@ void of_attach_node(struct device_node *np)
+ void of_detach_node(struct device_node *np)
+ {
+ struct device_node *parent;
++ unsigned long flags;
+
+- write_lock(&devtree_lock);
++ write_lock_irqsave(&devtree_lock, flags);
+
+ parent = np->parent;
+ if (!parent)
+@@ -1292,7 +1387,7 @@ void of_detach_node(struct device_node *np)
+ of_node_set_flag(np, OF_DETACHED);
+
+ out_unlock:
+- write_unlock(&devtree_lock);
++ write_unlock_irqrestore(&devtree_lock, flags);
+ }
+
+ #ifdef CONFIG_PPC_PSERIES
+@@ -1373,20 +1468,21 @@ __initcall(prom_reconfig_setup);
+ int prom_add_property(struct device_node* np, struct property* prop)
+ {
+ struct property **next;
++ unsigned long flags;
+
+ prop->next = NULL;
+- write_lock(&devtree_lock);
++ write_lock_irqsave(&devtree_lock, flags);
+ next = &np->properties;
+ while (*next) {
+ if (strcmp(prop->name, (*next)->name) == 0) {
+ /* duplicate ! don't insert it */
+- write_unlock(&devtree_lock);
++ write_unlock_irqrestore(&devtree_lock, flags);
+ return -1;
+ }
+ next = &(*next)->next;
+ }
+ *next = prop;
+- write_unlock(&devtree_lock);
++ write_unlock_irqrestore(&devtree_lock, flags);
+
+ #ifdef CONFIG_PROC_DEVICETREE
+ /* try to add to proc as well if it was initialized */
+@@ -1406,9 +1502,10 @@ int prom_add_property(struct device_node* np, struct property* prop)
+ int prom_remove_property(struct device_node *np, struct property *prop)
+ {
+ struct property **next;
++ unsigned long flags;
+ int found = 0;
+
+- write_lock(&devtree_lock);
++ write_lock_irqsave(&devtree_lock, flags);
+ next = &np->properties;
+ while (*next) {
+ if (*next == prop) {
+@@ -1421,7 +1518,7 @@ int prom_remove_property(struct device_node *np, struct property *prop)
+ }
+ next = &(*next)->next;
+ }
+- write_unlock(&devtree_lock);
++ write_unlock_irqrestore(&devtree_lock, flags);
+
+ if (!found)
+ return -ENODEV;
+@@ -1447,9 +1544,10 @@ int prom_update_property(struct device_node *np,
+ struct property *oldprop)
+ {
+ struct property **next;
++ unsigned long flags;
+ int found = 0;
+
+- write_lock(&devtree_lock);
++ write_lock_irqsave(&devtree_lock, flags);
+ next = &np->properties;
+ while (*next) {
+ if (*next == oldprop) {
+@@ -1463,7 +1561,7 @@ int prom_update_property(struct device_node *np,
+ }
+ next = &(*next)->next;
+ }
+- write_unlock(&devtree_lock);
++ write_unlock_irqrestore(&devtree_lock, flags);
+
+ if (!found)
+ return -ENODEV;
+diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
+index 5ab4c84..6d6df1e 100644
+--- a/arch/powerpc/kernel/prom_init.c
++++ b/arch/powerpc/kernel/prom_init.c
+@@ -2240,6 +2240,14 @@ static void __init fixup_device_tree_efika(void)
+ if (rv != PROM_ERROR && (strcmp(prop, "chrp") == 0))
+ prom_setprop(node, "/", "device_type", "efika", sizeof("efika"));
+
++ /* CODEGEN,description is exposed in /proc/cpuinfo so
++ fix that too */
++ rv = prom_getprop(node, "CODEGEN,description", prop, sizeof(prop));
++ if (rv != PROM_ERROR && (strstr(prop, "CHRP")))
++ prom_setprop(node, "/", "CODEGEN,description",
++ "Efika 5200B PowerPC System",
++ sizeof("Efika 5200B PowerPC System"));
++
+ /* Fixup bestcomm interrupts property */
+ node = call_prom("finddevice", 1, 1, ADDR("/builtin/bestcomm"));
+ if (PHANDLE_VALID(node)) {
+diff --git a/arch/powerpc/kernel/prom_init_check.sh b/arch/powerpc/kernel/prom_init_check.sh
+new file mode 100644
+index 0000000..8e24fc1
+--- /dev/null
++++ b/arch/powerpc/kernel/prom_init_check.sh
+@@ -0,0 +1,58 @@
++#!/bin/sh
++#
++# Copyright © 2008 IBM Corporation
++#
++# This program is free software; you can redistribute it and/or
++# modify it under the terms of the GNU General Public License
++# as published by the Free Software Foundation; either version
++# 2 of the License, or (at your option) any later version.
++
++# This script checks prom_init.o to see what external symbols it
++# is using, if it finds symbols not in the whitelist it returns
++# an error. The point of this is to discourage people from
++# intentionally or accidentally adding new code to prom_init.c
++# which has side effects on other parts of the kernel.
++
++# If you really need to reference something from prom_init.o add
++# it to the list below:
++
++WHITELIST="add_reloc_offset __bss_start __bss_stop copy_and_flush
++_end enter_prom memcpy memset reloc_offset __secondary_hold
++__secondary_hold_acknowledge __secondary_hold_spinloop __start
++strcmp strcpy strlcpy strlen strncmp strstr logo_linux_clut224
++reloc_got2"
++
++NM="$1"
++OBJ="$2"
++
++ERROR=0
++
++for UNDEF in $($NM -u $OBJ | awk '{print $2}')
++do
++ # On 64-bit nm gives us the function descriptors, which have
++ # a leading . on the name, so strip it off here.
++ UNDEF="${UNDEF#.}"
++
++ if [ $KBUILD_VERBOSE ]; then
++ if [ $KBUILD_VERBOSE -ne 0 ]; then
++ echo "Checking prom_init.o symbol '$UNDEF'"
++ fi
++ fi
++
++ OK=0
++ for WHITE in $WHITELIST
++ do
++ if [ "$UNDEF" = "$WHITE" ]; then
++ OK=1
++ break
++ fi
++ done
++
++ if [ $OK -eq 0 ]; then
++ ERROR=1
++ echo "Error: External symbol '$UNDEF' referenced" \
++ "from prom_init.c" >&2
++ fi
++done
++
++exit $ERROR
+diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
+index 52e95c2..34843c3 100644
+--- a/arch/powerpc/kernel/rtas.c
++++ b/arch/powerpc/kernel/rtas.c
+@@ -22,11 +22,11 @@
+ #include <linux/smp.h>
+ #include <linux/completion.h>
+ #include <linux/cpumask.h>
++#include <linux/lmb.h>
+
+ #include <asm/prom.h>
+ #include <asm/rtas.h>
+ #include <asm/hvcall.h>
+-#include <asm/semaphore.h>
+ #include <asm/machdep.h>
+ #include <asm/firmware.h>
+ #include <asm/page.h>
+@@ -34,7 +34,6 @@
+ #include <asm/system.h>
+ #include <asm/delay.h>
+ #include <asm/uaccess.h>
+-#include <asm/lmb.h>
+ #include <asm/udbg.h>
+ #include <asm/syscalls.h>
+ #include <asm/smp.h>
+@@ -507,7 +506,7 @@ int rtas_error_rc(int rtas_rc)
+ break;
+ default:
+ printk(KERN_ERR "%s: unexpected RTAS error %d\n",
+- __FUNCTION__, rtas_rc);
++ __func__, rtas_rc);
+ rc = -ERANGE;
+ break;
+ }
+diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
+index 538baf4..627f126 100644
+--- a/arch/powerpc/kernel/rtas_flash.c
++++ b/arch/powerpc/kernel/rtas_flash.c
+@@ -807,7 +807,7 @@ int __init rtas_flash_init(void)
+ rtas_block_ctor);
+ if (!flash_block_cache) {
+ printk(KERN_ERR "%s: failed to create block cache\n",
+- __FUNCTION__);
++ __func__);
+ rc = -ENOMEM;
+ goto cleanup;
+ }
+diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
+index 433a0a0..3ab88a9 100644
+--- a/arch/powerpc/kernel/rtas_pci.c
++++ b/arch/powerpc/kernel/rtas_pci.c
+@@ -56,21 +56,6 @@ static inline int config_access_valid(struct pci_dn *dn, int where)
+ return 0;
+ }
+
+-static int of_device_available(struct device_node * dn)
+-{
+- const char *status;
+-
+- status = of_get_property(dn, "status", NULL);
+-
+- if (!status)
+- return 1;
+-
+- if (!strcmp(status, "okay"))
+- return 1;
+-
+- return 0;
+-}
+-
+ int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val)
+ {
+ int returnval = -1;
+@@ -117,7 +102,7 @@ static int rtas_pci_read_config(struct pci_bus *bus,
+ for (dn = busdn->child; dn; dn = dn->sibling) {
+ struct pci_dn *pdn = PCI_DN(dn);
+ if (pdn && pdn->devfn == devfn
+- && of_device_available(dn))
++ && of_device_is_available(dn))
+ return rtas_read_config(pdn, where, size, val);
+ }
+
+@@ -164,7 +149,7 @@ static int rtas_pci_write_config(struct pci_bus *bus,
+ for (dn = busdn->child; dn; dn = dn->sibling) {
+ struct pci_dn *pdn = PCI_DN(dn);
+ if (pdn && pdn->devfn == devfn
+- && of_device_available(dn))
++ && of_device_is_available(dn))
+ return rtas_write_config(pdn, where, size, val);
+ }
+ return PCIBIOS_DEVICE_NOT_FOUND;
+@@ -326,7 +311,7 @@ int pcibios_remove_root_bus(struct pci_controller *phb)
+
+ res = b->resource[0];
+ if (!res->flags) {
+- printk(KERN_ERR "%s: no IO resource for PHB %s\n", __FUNCTION__,
++ printk(KERN_ERR "%s: no IO resource for PHB %s\n", __func__,
+ b->name);
+ return 1;
+ }
+@@ -334,13 +319,13 @@ int pcibios_remove_root_bus(struct pci_controller *phb)
+ rc = pcibios_unmap_io_space(b);
+ if (rc) {
+ printk(KERN_ERR "%s: failed to unmap IO on bus %s\n",
+- __FUNCTION__, b->name);
++ __func__, b->name);
+ return 1;
+ }
+
+ if (release_resource(res)) {
+ printk(KERN_ERR "%s: failed to release IO on bus %s\n",
+- __FUNCTION__, b->name);
++ __func__, b->name);
+ return 1;
+ }
+
+@@ -348,13 +333,13 @@ int pcibios_remove_root_bus(struct pci_controller *phb)
+ res = b->resource[i];
+ if (!res->flags && i == 0) {
+ printk(KERN_ERR "%s: no MEM resource for PHB %s\n",
+- __FUNCTION__, b->name);
++ __func__, b->name);
+ return 1;
+ }
+ if (res->flags && release_resource(res)) {
+ printk(KERN_ERR
+ "%s: failed to release IO %d on bus %s\n",
+- __FUNCTION__, i, b->name);
++ __func__, i, b->name);
+ return 1;
+ }
+ }
+diff --git a/arch/powerpc/kernel/semaphore.c b/arch/powerpc/kernel/semaphore.c
+deleted file mode 100644
+index 2f8c3c9..0000000
+--- a/arch/powerpc/kernel/semaphore.c
++++ /dev/null
+@@ -1,135 +0,0 @@
+-/*
+- * PowerPC-specific semaphore code.
+- *
+- * Copyright (C) 1999 Cort Dougan <cort at cs.nmt.edu>
+- *
+- * 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.
+- *
+- * April 2001 - Reworked by Paul Mackerras <paulus at samba.org>
+- * to eliminate the SMP races in the old version between the updates
+- * of `count' and `waking'. Now we use negative `count' values to
+- * indicate that some process(es) are waiting for the semaphore.
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/init.h>
+-#include <linux/module.h>
+-
+-#include <asm/atomic.h>
+-#include <asm/semaphore.h>
+-#include <asm/errno.h>
+-
+-/*
+- * Atomically update sem->count.
+- * This does the equivalent of the following:
+- *
+- * old_count = sem->count;
+- * tmp = MAX(old_count, 0) + incr;
+- * sem->count = tmp;
+- * return old_count;
+- */
+-static inline int __sem_update_count(struct semaphore *sem, int incr)
+-{
+- int old_count, tmp;
+-
+- __asm__ __volatile__("\n"
+-"1: lwarx %0,0,%3\n"
+-" srawi %1,%0,31\n"
+-" andc %1,%0,%1\n"
+-" add %1,%1,%4\n"
+- PPC405_ERR77(0,%3)
+-" stwcx. %1,0,%3\n"
+-" bne 1b"
+- : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
+- : "r" (&sem->count), "r" (incr), "m" (sem->count)
+- : "cc");
+-
+- return old_count;
+-}
+-
+-void __up(struct semaphore *sem)
+-{
+- /*
+- * Note that we incremented count in up() before we came here,
+- * but that was ineffective since the result was <= 0, and
+- * any negative value of count is equivalent to 0.
+- * This ends up setting count to 1, unless count is now > 0
+- * (i.e. because some other cpu has called up() in the meantime),
+- * in which case we just increment count.
+- */
+- __sem_update_count(sem, 1);
+- wake_up(&sem->wait);
+-}
+-EXPORT_SYMBOL(__up);
+-
+-/*
+- * Note that when we come in to __down or __down_interruptible,
+- * we have already decremented count, but that decrement was
+- * ineffective since the result was < 0, and any negative value
+- * of count is equivalent to 0.
+- * Thus it is only when we decrement count from some value > 0
+- * that we have actually got the semaphore.
+- */
+-void __sched __down(struct semaphore *sem)
+-{
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+-
+- __set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+- add_wait_queue_exclusive(&sem->wait, &wait);
+-
+- /*
+- * Try to get the semaphore. If the count is > 0, then we've
+- * got the semaphore; we decrement count and exit the loop.
+- * If the count is 0 or negative, we set it to -1, indicating
+- * that we are asleep, and then sleep.
+- */
+- while (__sem_update_count(sem, -1) <= 0) {
+- schedule();
+- set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+- }
+- remove_wait_queue(&sem->wait, &wait);
+- __set_task_state(tsk, TASK_RUNNING);
+-
+- /*
+- * If there are any more sleepers, wake one of them up so
+- * that it can either get the semaphore, or set count to -1
+- * indicating that there are still processes sleeping.
+- */
+- wake_up(&sem->wait);
+-}
+-EXPORT_SYMBOL(__down);
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+- int retval = 0;
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+-
+- __set_task_state(tsk, TASK_INTERRUPTIBLE);
+- add_wait_queue_exclusive(&sem->wait, &wait);
+-
+- while (__sem_update_count(sem, -1) <= 0) {
+- if (signal_pending(current)) {
+- /*
+- * A signal is pending - give up trying.
+- * Set sem->count to 0 if it is negative,
+- * since we are no longer sleeping.
+- */
+- __sem_update_count(sem, 0);
+- retval = -EINTR;
+- break;
+- }
+- schedule();
+- set_task_state(tsk, TASK_INTERRUPTIBLE);
+- }
+- remove_wait_queue(&sem->wait, &wait);
+- __set_task_state(tsk, TASK_RUNNING);
+-
+- wake_up(&sem->wait);
+- return retval;
+-}
+-EXPORT_SYMBOL(__down_interruptible);
+diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
+index 6adb5a1..db540ea 100644
+--- a/arch/powerpc/kernel/setup-common.c
++++ b/arch/powerpc/kernel/setup-common.c
+@@ -34,6 +34,7 @@
+ #include <linux/serial_8250.h>
+ #include <linux/debugfs.h>
+ #include <linux/percpu.h>
++#include <linux/lmb.h>
+ #include <asm/io.h>
+ #include <asm/prom.h>
+ #include <asm/processor.h>
+@@ -56,7 +57,6 @@
+ #include <asm/cache.h>
+ #include <asm/page.h>
+ #include <asm/mmu.h>
+-#include <asm/lmb.h>
+ #include <asm/xmon.h>
+ #include <asm/cputhreads.h>
+
+@@ -167,6 +167,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
+ unsigned short min;
+
+ if (cpu_id == NR_CPUS) {
++ struct device_node *root;
++ const char *model = NULL;
+ #if defined(CONFIG_SMP) && defined(CONFIG_PPC32)
+ unsigned long bogosum = 0;
+ int i;
+@@ -178,6 +180,13 @@ static int show_cpuinfo(struct seq_file *m, void *v)
+ seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq);
+ if (ppc_md.name)
+ seq_printf(m, "platform\t: %s\n", ppc_md.name);
++ root = of_find_node_by_path("/");
++ if (root)
++ model = of_get_property(root, "model", NULL);
++ if (model)
++ seq_printf(m, "model\t\t: %s\n", model);
++ of_node_put(root);
++
+ if (ppc_md.show_cpuinfo != NULL)
+ ppc_md.show_cpuinfo(m);
+
+diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
+index cd870a8..36f6779 100644
+--- a/arch/powerpc/kernel/setup_32.c
++++ b/arch/powerpc/kernel/setup_32.c
+@@ -10,9 +10,6 @@
+ #include <linux/reboot.h>
+ #include <linux/delay.h>
+ #include <linux/initrd.h>
+-#if defined(CONFIG_IDE) || defined(CONFIG_IDE_MODULE)
+-#include <linux/ide.h>
+-#endif
+ #include <linux/tty.h>
+ #include <linux/bootmem.h>
+ #include <linux/seq_file.h>
+@@ -51,11 +48,6 @@
+
+ extern void bootx_init(unsigned long r4, unsigned long phys);
+
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+-struct ide_machdep_calls ppc_ide_md;
+-EXPORT_SYMBOL(ppc_ide_md);
+-#endif
+-
+ int boot_cpuid;
+ EXPORT_SYMBOL_GPL(boot_cpuid);
+ int boot_cpuid_phys;
+@@ -172,6 +164,18 @@ int __init ppc_setup_l2cr(char *str)
+ }
+ __setup("l2cr=", ppc_setup_l2cr);
+
++/* Checks "l3cr=xxxx" command-line option */
++int __init ppc_setup_l3cr(char *str)
++{
++ if (cpu_has_feature(CPU_FTR_L3CR)) {
++ unsigned long val = simple_strtoul(str, NULL, 0);
++ printk(KERN_INFO "l3cr set to %lx\n", val);
++ _set_L3CR(val); /* and enable it */
++ }
++ return 1;
++}
++__setup("l3cr=", ppc_setup_l3cr);
++
+ #ifdef CONFIG_GENERIC_NVRAM
+
+ /* Generic nvram hooks used by drivers/char/gen_nvram.c */
+@@ -277,7 +281,7 @@ void __init setup_arch(char **cmdline_p)
+ if (ppc_md.panic)
+ setup_panic();
+
+- init_mm.start_code = PAGE_OFFSET;
++ init_mm.start_code = (unsigned long)_stext;
+ init_mm.end_code = (unsigned long) _etext;
+ init_mm.end_data = (unsigned long) _edata;
+ init_mm.brk = klimit;
+diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
+index 3b1529c..dff6308 100644
+--- a/arch/powerpc/kernel/setup_64.c
++++ b/arch/powerpc/kernel/setup_64.c
+@@ -33,6 +33,8 @@
+ #include <linux/serial_8250.h>
+ #include <linux/bootmem.h>
+ #include <linux/pci.h>
++#include <linux/lockdep.h>
++#include <linux/lmb.h>
+ #include <asm/io.h>
+ #include <asm/kdump.h>
+ #include <asm/prom.h>
+@@ -55,7 +57,6 @@
+ #include <asm/cache.h>
+ #include <asm/page.h>
+ #include <asm/mmu.h>
+-#include <asm/lmb.h>
+ #include <asm/firmware.h>
+ #include <asm/xmon.h>
+ #include <asm/udbg.h>
+@@ -169,6 +170,9 @@ void __init setup_paca(int cpu)
+
+ void __init early_setup(unsigned long dt_ptr)
+ {
++ /* Fill in any unititialised pacas */
++ initialise_pacas();
++
+ /* Identify CPU type */
+ identify_cpu(0, mfspr(SPRN_PVR));
+
+@@ -178,6 +182,9 @@ void __init early_setup(unsigned long dt_ptr)
+ /* Enable early debugging if any specified (see udbg.h) */
+ udbg_early_init();
+
++ /* Initialize lockdep early or else spinlocks will blow */
++ lockdep_init();
++
+ DBG(" -> early_setup(), dt_ptr: 0x%lx\n", dt_ptr);
+
+ /*
+@@ -431,7 +438,7 @@ void __init setup_system(void)
+ printk("htab_address = 0x%p\n", htab_address);
+ printk("htab_hash_mask = 0x%lx\n", htab_hash_mask);
+ #if PHYSICAL_START > 0
+- printk("physical_start = 0x%x\n", PHYSICAL_START);
++ printk("physical_start = 0x%lx\n", PHYSICAL_START);
+ #endif
+ printk("-----------------------------------------------------\n");
+
+@@ -510,7 +517,7 @@ void __init setup_arch(char **cmdline_p)
+ if (ppc_md.panic)
+ setup_panic();
+
+- init_mm.start_code = PAGE_OFFSET;
++ init_mm.start_code = (unsigned long)_stext;
+ init_mm.end_code = (unsigned long) _etext;
+ init_mm.end_data = (unsigned long) _edata;
+ init_mm.brk = klimit;
+diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
+index d840bc7..ad69434 100644
+--- a/arch/powerpc/kernel/signal_32.c
++++ b/arch/powerpc/kernel/signal_32.c
+@@ -621,6 +621,18 @@ int copy_siginfo_to_user32(struct compat_siginfo __user *d, siginfo_t *s)
+
+ #define copy_siginfo_to_user copy_siginfo_to_user32
+
++int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
++{
++ memset(to, 0, sizeof *to);
++
++ if (copy_from_user(to, from, 3*sizeof(int)) ||
++ copy_from_user(to->_sifields._pad,
++ from->_sifields._pad, SI_PAD_SIZE32))
++ return -EFAULT;
++
++ return 0;
++}
++
+ /*
+ * Note: it is necessary to treat pid and sig as unsigned ints, with the
+ * corresponding cast to a signed int to insure that the proper conversion
+@@ -634,9 +646,10 @@ long compat_sys_rt_sigqueueinfo(u32 pid, u32 sig, compat_siginfo_t __user *uinfo
+ int ret;
+ mm_segment_t old_fs = get_fs();
+
+- if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
+- copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE32))
+- return -EFAULT;
++ ret = copy_siginfo_from_user32(&info, uinfo);
++ if (unlikely(ret))
++ return ret;
++
+ set_fs (KERNEL_DS);
+ /* The __user pointer cast is valid becasuse of the set_fs() */
+ ret = sys_rt_sigqueueinfo((int)pid, (int)sig, (siginfo_t __user *) &info);
+diff --git a/arch/powerpc/kernel/stacktrace.c b/arch/powerpc/kernel/stacktrace.c
+new file mode 100644
+index 0000000..9629440
+--- /dev/null
++++ b/arch/powerpc/kernel/stacktrace.c
+@@ -0,0 +1,46 @@
++/*
++ * Stack trace utility
++ *
++ * Copyright 2008 Christoph Hellwig, IBM Corp.
++ *
++ *
++ * 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/sched.h>
++#include <linux/stacktrace.h>
++#include <asm/ptrace.h>
++
++/*
++ * Save stack-backtrace addresses into a stack_trace buffer.
++ */
++void save_stack_trace(struct stack_trace *trace)
++{
++ unsigned long sp;
++
++ asm("mr %0,1" : "=r" (sp));
++
++ for (;;) {
++ unsigned long *stack = (unsigned long *) sp;
++ unsigned long newsp, ip;
++
++ if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD))
++ return;
++
++ newsp = stack[0];
++ ip = stack[STACK_FRAME_LR_SAVE];
++
++ if (!trace->skip)
++ trace->entries[trace->nr_entries++] = ip;
++ else
++ trace->skip--;
++
++ if (trace->nr_entries >= trace->max_entries)
++ return;
++
++ sp = newsp;
++ }
++}
+diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
+index 4a4f5c6..709f8cb 100644
+--- a/arch/powerpc/kernel/sys_ppc32.c
++++ b/arch/powerpc/kernel/sys_ppc32.c
+@@ -47,7 +47,6 @@
+ #include <asm/types.h>
+ #include <asm/uaccess.h>
+ #include <asm/unistd.h>
+-#include <asm/semaphore.h>
+ #include <asm/time.h>
+ #include <asm/mmu_context.h>
+ #include <asm/ppc-pci.h>
+@@ -368,11 +367,6 @@ long compat_sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
+
+ error = compat_do_execve(filename, compat_ptr(a1), compat_ptr(a2), regs);
+
+- if (error == 0) {
+- task_lock(current);
+- current->ptrace &= ~PT_DTRACE;
+- task_unlock(current);
+- }
+ putname(filename);
+
+ out:
+diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c
+index 3b1d5dd..e722a4e 100644
+--- a/arch/powerpc/kernel/syscalls.c
++++ b/arch/powerpc/kernel/syscalls.c
+@@ -38,7 +38,6 @@
+ #include <linux/personality.h>
+
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #include <asm/syscalls.h>
+ #include <asm/time.h>
+ #include <asm/unistd.h>
+diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
+index 7aad620..7d6c9bb 100644
+--- a/arch/powerpc/kernel/udbg.c
++++ b/arch/powerpc/kernel/udbg.c
+@@ -154,8 +154,8 @@ static void udbg_console_write(struct console *con, const char *s,
+ static struct console udbg_console = {
+ .name = "udbg",
+ .write = udbg_console_write,
+- .flags = CON_PRINTBUFFER | CON_ENABLED | CON_BOOT,
+- .index = -1,
++ .flags = CON_PRINTBUFFER | CON_ENABLED | CON_BOOT | CON_ANYTIME,
++ .index = 0,
+ };
+
+ static int early_console_initialized;
+diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
+index d3437c4..c21a626 100644
+--- a/arch/powerpc/kernel/vdso.c
++++ b/arch/powerpc/kernel/vdso.c
+@@ -21,13 +21,14 @@
+ #include <linux/elf.h>
+ #include <linux/security.h>
+ #include <linux/bootmem.h>
++#include <linux/lmb.h>
+
+ #include <asm/pgtable.h>
+ #include <asm/system.h>
+ #include <asm/processor.h>
+ #include <asm/mmu.h>
+ #include <asm/mmu_context.h>
+-#include <asm/lmb.h>
++#include <asm/prom.h>
+ #include <asm/machdep.h>
+ #include <asm/cputable.h>
+ #include <asm/sections.h>
+diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
+index f988672..b77f8af 100644
+--- a/arch/powerpc/kernel/vio.c
++++ b/arch/powerpc/kernel/vio.c
+@@ -139,7 +139,7 @@ static int vio_bus_remove(struct device *dev)
+ */
+ int vio_register_driver(struct vio_driver *viodrv)
+ {
+- printk(KERN_DEBUG "%s: driver %s registering\n", __FUNCTION__,
++ printk(KERN_DEBUG "%s: driver %s registering\n", __func__,
+ viodrv->driver.name);
+
+ /* fill in 'struct driver' fields */
+@@ -184,7 +184,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node)
+ /* we need the 'device_type' property, in order to match with drivers */
+ if (of_node->type == NULL) {
+ printk(KERN_WARNING "%s: node %s missing 'device_type'\n",
+- __FUNCTION__,
++ __func__,
+ of_node->name ? of_node->name : "<unknown>");
+ return NULL;
+ }
+@@ -192,7 +192,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node)
+ unit_address = of_get_property(of_node, "reg", NULL);
+ if (unit_address == NULL) {
+ printk(KERN_WARNING "%s: node %s missing 'reg'\n",
+- __FUNCTION__,
++ __func__,
+ of_node->name ? of_node->name : "<unknown>");
+ return NULL;
+ }
+@@ -227,7 +227,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node)
+ /* register with generic device framework */
+ if (device_register(&viodev->dev)) {
+ printk(KERN_ERR "%s: failed to register device %s\n",
+- __FUNCTION__, viodev->dev.bus_id);
++ __func__, viodev->dev.bus_id);
+ /* XXX free TCE table */
+ kfree(viodev);
+ return NULL;
+@@ -258,7 +258,7 @@ static int __init vio_bus_init(void)
+ err = device_register(&vio_bus_device.dev);
+ if (err) {
+ printk(KERN_WARNING "%s: device_register returned %i\n",
+- __FUNCTION__, err);
++ __func__, err);
+ return err;
+ }
+
+diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
+index 0afb9e3..0c3000b 100644
+--- a/arch/powerpc/kernel/vmlinux.lds.S
++++ b/arch/powerpc/kernel/vmlinux.lds.S
+@@ -1,11 +1,9 @@
+ #ifdef CONFIG_PPC64
+-#include <asm/page.h>
+ #define PROVIDE32(x) PROVIDE(__unused__##x)
+ #else
+-#define PAGE_SIZE 4096
+-#define KERNELBASE CONFIG_KERNEL_START
+ #define PROVIDE32(x) PROVIDE(x)
+ #endif
++#include <asm/page.h>
+ #include <asm-generic/vmlinux.lds.h>
+ #include <asm/cache.h>
+
+@@ -33,7 +31,7 @@ SECTIONS
+ */
+
+ /* Text and gots */
+- .text : {
++ .text : AT(ADDR(.text) - LOAD_OFFSET) {
+ ALIGN_FUNCTION();
+ *(.text.head)
+ _text = .;
+@@ -58,7 +56,7 @@ SECTIONS
+ RODATA
+
+ /* Exception & bug tables */
+- __ex_table : {
++ __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
+ __start___ex_table = .;
+ *(__ex_table)
+ __stop___ex_table = .;
+@@ -74,7 +72,7 @@ SECTIONS
+ . = ALIGN(PAGE_SIZE);
+ __init_begin = .;
+
+- .init.text : {
++ .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
+ _sinittext = .;
+ INIT_TEXT
+ _einittext = .;
+@@ -83,11 +81,11 @@ SECTIONS
+ /* .exit.text is discarded at runtime, not link time,
+ * to deal with references from __bug_table
+ */
+- .exit.text : {
++ .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) {
+ EXIT_TEXT
+ }
+
+- .init.data : {
++ .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
+ INIT_DATA
+ __vtop_table_begin = .;
+ *(.vtop_fixup);
+@@ -103,19 +101,19 @@ SECTIONS
+ }
+
+ . = ALIGN(16);
+- .init.setup : {
++ .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
+ __setup_start = .;
+ *(.init.setup)
+ __setup_end = .;
+ }
+
+- .initcall.init : {
++ .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
+ __initcall_start = .;
+ INITCALLS
+ __initcall_end = .;
+ }
+
+- .con_initcall.init : {
++ .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
+ __con_initcall_start = .;
+ *(.con_initcall.init)
+ __con_initcall_end = .;
+@@ -124,14 +122,14 @@ SECTIONS
+ SECURITY_INIT
+
+ . = ALIGN(8);
+- __ftr_fixup : {
++ __ftr_fixup : AT(ADDR(__ftr_fixup) - LOAD_OFFSET) {
+ __start___ftr_fixup = .;
+ *(__ftr_fixup)
+ __stop___ftr_fixup = .;
+ }
+ #ifdef CONFIG_PPC64
+ . = ALIGN(8);
+- __fw_ftr_fixup : {
++ __fw_ftr_fixup : AT(ADDR(__fw_ftr_fixup) - LOAD_OFFSET) {
+ __start___fw_ftr_fixup = .;
+ *(__fw_ftr_fixup)
+ __stop___fw_ftr_fixup = .;
+@@ -139,14 +137,14 @@ SECTIONS
+ #endif
+ #ifdef CONFIG_BLK_DEV_INITRD
+ . = ALIGN(PAGE_SIZE);
+- .init.ramfs : {
++ .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
+ __initramfs_start = .;
+ *(.init.ramfs)
+ __initramfs_end = .;
+ }
+ #endif
+ . = ALIGN(PAGE_SIZE);
+- .data.percpu : {
++ .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) {
+ __per_cpu_start = .;
+ *(.data.percpu)
+ *(.data.percpu.shared_aligned)
+@@ -154,7 +152,7 @@ SECTIONS
+ }
+
+ . = ALIGN(8);
+- .machine.desc : {
++ .machine.desc : AT(ADDR(.machine.desc) - LOAD_OFFSET) {
+ __machine_desc_start = . ;
+ *(.machine.desc)
+ __machine_desc_end = . ;
+@@ -172,25 +170,24 @@ SECTIONS
+ _sdata = .;
+
+ #ifdef CONFIG_PPC32
+- .data :
+- {
++ .data : AT(ADDR(.data) - LOAD_OFFSET) {
+ DATA_DATA
+ *(.sdata)
+ *(.got.plt) *(.got)
+ }
+ #else
+- .data : {
++ .data : AT(ADDR(.data) - LOAD_OFFSET) {
+ DATA_DATA
+ *(.data.rel*)
+ *(.toc1)
+ *(.branch_lt)
+ }
+
+- .opd : {
++ .opd : AT(ADDR(.opd) - LOAD_OFFSET) {
+ *(.opd)
+ }
+
+- .got : {
++ .got : AT(ADDR(.got) - LOAD_OFFSET) {
+ __toc_start = .;
+ *(.got)
+ *(.toc)
+@@ -207,26 +204,26 @@ SECTIONS
+ #else
+ . = ALIGN(16384);
+ #endif
+- .data.init_task : {
++ .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
+ *(.data.init_task)
+ }
+
+ . = ALIGN(PAGE_SIZE);
+- .data.page_aligned : {
++ .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
+ *(.data.page_aligned)
+ }
+
+- .data.cacheline_aligned : {
++ .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
+ *(.data.cacheline_aligned)
+ }
+
+ . = ALIGN(L1_CACHE_BYTES);
+- .data.read_mostly : {
++ .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) {
+ *(.data.read_mostly)
+ }
+
+ . = ALIGN(PAGE_SIZE);
+- __data_nosave : {
++ .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) {
+ __nosave_begin = .;
+ *(.data.nosave)
+ . = ALIGN(PAGE_SIZE);
+@@ -237,7 +234,7 @@ SECTIONS
+ * And finally the bss
+ */
+
+- .bss : {
++ .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
+ __bss_start = .;
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+diff --git a/arch/powerpc/lib/rheap.c b/arch/powerpc/lib/rheap.c
+index 22c3b4f..29b2941 100644
+--- a/arch/powerpc/lib/rheap.c
++++ b/arch/powerpc/lib/rheap.c
+@@ -54,7 +54,7 @@ static int grow(rh_info_t * info, int max_blocks)
+
+ new_blocks = max_blocks - info->max_blocks;
+
+- block = kmalloc(sizeof(rh_block_t) * max_blocks, GFP_KERNEL);
++ block = kmalloc(sizeof(rh_block_t) * max_blocks, GFP_ATOMIC);
+ if (block == NULL)
+ return -ENOMEM;
+
+@@ -258,7 +258,7 @@ rh_info_t *rh_create(unsigned int alignment)
+ if ((alignment & (alignment - 1)) != 0)
+ return ERR_PTR(-EINVAL);
+
+- info = kmalloc(sizeof(*info), GFP_KERNEL);
++ info = kmalloc(sizeof(*info), GFP_ATOMIC);
+ if (info == NULL)
+ return ERR_PTR(-ENOMEM);
+
+diff --git a/arch/powerpc/lib/string.S b/arch/powerpc/lib/string.S
+index c4c622d..49eb1f1 100644
+--- a/arch/powerpc/lib/string.S
++++ b/arch/powerpc/lib/string.S
+@@ -75,6 +75,20 @@ _GLOBAL(strcmp)
+ beq 1b
+ blr
+
++_GLOBAL(strncmp)
++ PPC_LCMPI r5,0
++ beqlr
++ mtctr r5
++ addi r5,r3,-1
++ addi r4,r4,-1
++1: lbzu r3,1(r5)
++ cmpwi 1,r3,0
++ lbzu r0,1(r4)
++ subf. r3,r0,r3
++ beqlr 1
++ bdnzt eq,1b
++ blr
++
+ _GLOBAL(strlen)
+ addi r4,r3,-1
+ 1: lbzu r0,1(r4)
+diff --git a/arch/powerpc/math-emu/fabs.c b/arch/powerpc/math-emu/fabs.c
+index 41f0617..549baba 100644
+--- a/arch/powerpc/math-emu/fabs.c
++++ b/arch/powerpc/math-emu/fabs.c
+@@ -9,7 +9,7 @@ fabs(u32 *frD, u32 *frB)
+ frD[1] = frB[1];
+
+ #ifdef DEBUG
+- printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB);
++ printk("%s: D %p, B %p: ", __func__, frD, frB);
+ dump_double(frD);
+ printk("\n");
+ #endif
+diff --git a/arch/powerpc/math-emu/fadd.c b/arch/powerpc/math-emu/fadd.c
+index fc88364..7befbbf 100644
+--- a/arch/powerpc/math-emu/fadd.c
++++ b/arch/powerpc/math-emu/fadd.c
+@@ -14,7 +14,7 @@ fadd(void *frD, void *frA, void *frB)
+ int ret = 0;
+
+ #ifdef DEBUG
+- printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
++ printk("%s: %p %p %p\n", __func__, frD, frA, frB);
+ #endif
+
+ __FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fadds.c b/arch/powerpc/math-emu/fadds.c
+index 93025b6..2b346b3 100644
+--- a/arch/powerpc/math-emu/fadds.c
++++ b/arch/powerpc/math-emu/fadds.c
+@@ -15,7 +15,7 @@ fadds(void *frD, void *frA, void *frB)
+ int ret = 0;
+
+ #ifdef DEBUG
+- printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
++ printk("%s: %p %p %p\n", __func__, frD, frA, frB);
+ #endif
+
+ __FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fcmpo.c b/arch/powerpc/math-emu/fcmpo.c
+index 4efac39..36d6890 100644
+--- a/arch/powerpc/math-emu/fcmpo.c
++++ b/arch/powerpc/math-emu/fcmpo.c
+@@ -15,7 +15,7 @@ fcmpo(u32 *ccr, int crfD, void *frA, void *frB)
+ int ret = 0;
+
+ #ifdef DEBUG
+- printk("%s: %p (%08x) %d %p %p\n", __FUNCTION__, ccr, *ccr, crfD, frA, frB);
++ printk("%s: %p (%08x) %d %p %p\n", __func__, ccr, *ccr, crfD, frA, frB);
+ #endif
+
+ __FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fcmpu.c b/arch/powerpc/math-emu/fcmpu.c
+index b7e3317..53d9389 100644
+--- a/arch/powerpc/math-emu/fcmpu.c
++++ b/arch/powerpc/math-emu/fcmpu.c
+@@ -14,7 +14,7 @@ fcmpu(u32 *ccr, int crfD, void *frA, void *frB)
+ long cmp;
+
+ #ifdef DEBUG
+- printk("%s: %p (%08x) %d %p %p\n", __FUNCTION__, ccr, *ccr, crfD, frA, frB);
++ printk("%s: %p (%08x) %d %p %p\n", __func__, ccr, *ccr, crfD, frA, frB);
+ #endif
+
+ __FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fctiw.c b/arch/powerpc/math-emu/fctiw.c
+index 3b3c98b..fcd7a95 100644
+--- a/arch/powerpc/math-emu/fctiw.c
++++ b/arch/powerpc/math-emu/fctiw.c
+@@ -16,7 +16,7 @@ fctiw(u32 *frD, void *frB)
+ frD[1] = r;
+
+ #ifdef DEBUG
+- printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB);
++ printk("%s: D %p, B %p: ", __func__, frD, frB);
+ dump_double(frD);
+ printk("\n");
+ #endif
+diff --git a/arch/powerpc/math-emu/fctiwz.c b/arch/powerpc/math-emu/fctiwz.c
+index 7717eb6..1514d59 100644
+--- a/arch/powerpc/math-emu/fctiwz.c
++++ b/arch/powerpc/math-emu/fctiwz.c
+@@ -23,7 +23,7 @@ fctiwz(u32 *frD, void *frB)
+ __FPU_FPSCR = fpscr;
+
+ #ifdef DEBUG
+- printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB);
++ printk("%s: D %p, B %p: ", __func__, frD, frB);
+ dump_double(frD);
+ printk("\n");
+ #endif
+diff --git a/arch/powerpc/math-emu/fdiv.c b/arch/powerpc/math-emu/fdiv.c
+index f2fba82..18a20fe 100644
+--- a/arch/powerpc/math-emu/fdiv.c
++++ b/arch/powerpc/math-emu/fdiv.c
+@@ -14,7 +14,7 @@ fdiv(void *frD, void *frA, void *frB)
+ int ret = 0;
+
+ #ifdef DEBUG
+- printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
++ printk("%s: %p %p %p\n", __func__, frD, frA, frB);
+ #endif
+
+ __FP_UNPACK_D(A, frA);
+@@ -28,13 +28,13 @@ fdiv(void *frD, void *frA, void *frB)
+ if (A_c == FP_CLS_ZERO && B_c == FP_CLS_ZERO) {
+ ret |= EFLAG_VXZDZ;
+ #ifdef DEBUG
+- printk("%s: FPSCR_VXZDZ raised\n", __FUNCTION__);
++ printk("%s: FPSCR_VXZDZ raised\n", __func__);
+ #endif
+ }
+ if (A_c == FP_CLS_INF && B_c == FP_CLS_INF) {
+ ret |= EFLAG_VXIDI;
+ #ifdef DEBUG
+- printk("%s: FPSCR_VXIDI raised\n", __FUNCTION__);
++ printk("%s: FPSCR_VXIDI raised\n", __func__);
+ #endif
+ }
+
+diff --git a/arch/powerpc/math-emu/fdivs.c b/arch/powerpc/math-emu/fdivs.c
+index b971196..24feed6 100644
+--- a/arch/powerpc/math-emu/fdivs.c
++++ b/arch/powerpc/math-emu/fdivs.c
+@@ -15,7 +15,7 @@ fdivs(void *frD, void *frA, void *frB)
+ int ret = 0;
+
+ #ifdef DEBUG
+- printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
++ printk("%s: %p %p %p\n", __func__, frD, frA, frB);
+ #endif
+
+ __FP_UNPACK_D(A, frA);
+@@ -29,13 +29,13 @@ fdivs(void *frD, void *frA, void *frB)
+ if (A_c == FP_CLS_ZERO && B_c == FP_CLS_ZERO) {
+ ret |= EFLAG_VXZDZ;
+ #ifdef DEBUG
+- printk("%s: FPSCR_VXZDZ raised\n", __FUNCTION__);
++ printk("%s: FPSCR_VXZDZ raised\n", __func__);
+ #endif
+ }
+ if (A_c == FP_CLS_INF && B_c == FP_CLS_INF) {
+ ret |= EFLAG_VXIDI;
+ #ifdef DEBUG
+- printk("%s: FPSCR_VXIDI raised\n", __FUNCTION__);
++ printk("%s: FPSCR_VXIDI raised\n", __func__);
+ #endif
+ }
+
+diff --git a/arch/powerpc/math-emu/fmadd.c b/arch/powerpc/math-emu/fmadd.c
+index 0a1dbce..dedb465 100644
+--- a/arch/powerpc/math-emu/fmadd.c
++++ b/arch/powerpc/math-emu/fmadd.c
+@@ -16,7 +16,7 @@ fmadd(void *frD, void *frA, void *frB, void *frC)
+ int ret = 0;
+
+ #ifdef DEBUG
+- printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
++ printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
+ #endif
+
+ __FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fmadds.c b/arch/powerpc/math-emu/fmadds.c
+index 0f70bba..6bbb56d 100644
+--- a/arch/powerpc/math-emu/fmadds.c
++++ b/arch/powerpc/math-emu/fmadds.c
+@@ -17,7 +17,7 @@ fmadds(void *frD, void *frA, void *frB, void *frC)
+ int ret = 0;
+
+ #ifdef DEBUG
+- printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
++ printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
+ #endif
+
+ __FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fmr.c b/arch/powerpc/math-emu/fmr.c
+index 28df700..bd55384 100644
+--- a/arch/powerpc/math-emu/fmr.c
++++ b/arch/powerpc/math-emu/fmr.c
+@@ -9,7 +9,7 @@ fmr(u32 *frD, u32 *frB)
+ frD[1] = frB[1];
+
+ #ifdef DEBUG
+- printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB);
++ printk("%s: D %p, B %p: ", __func__, frD, frB);
+ dump_double(frD);
+ printk("\n");
+ #endif
+diff --git a/arch/powerpc/math-emu/fmsub.c b/arch/powerpc/math-emu/fmsub.c
+index 203fd48..f311e2c 100644
+--- a/arch/powerpc/math-emu/fmsub.c
++++ b/arch/powerpc/math-emu/fmsub.c
+@@ -16,7 +16,7 @@ fmsub(void *frD, void *frA, void *frB, void *frC)
+ int ret = 0;
+
+ #ifdef DEBUG
+- printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
++ printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
+ #endif
+
+ __FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fmsubs.c b/arch/powerpc/math-emu/fmsubs.c
+index 8ce6862..81a716d 100644
+--- a/arch/powerpc/math-emu/fmsubs.c
++++ b/arch/powerpc/math-emu/fmsubs.c
+@@ -17,7 +17,7 @@ fmsubs(void *frD, void *frA, void *frB, void *frC)
+ int ret = 0;
+
+ #ifdef DEBUG
+- printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
++ printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
+ #endif
+
+ __FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fmul.c b/arch/powerpc/math-emu/fmul.c
+index 66c7e79..2f3d327 100644
+--- a/arch/powerpc/math-emu/fmul.c
++++ b/arch/powerpc/math-emu/fmul.c
+@@ -14,7 +14,7 @@ fmul(void *frD, void *frA, void *frB)
+ int ret = 0;
+
+ #ifdef DEBUG
+- printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
++ printk("%s: %p %p %p\n", __func__, frD, frA, frB);
+ #endif
+
+ __FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fmuls.c b/arch/powerpc/math-emu/fmuls.c
+index 26bc427..962b588 100644
+--- a/arch/powerpc/math-emu/fmuls.c
++++ b/arch/powerpc/math-emu/fmuls.c
+@@ -15,7 +15,7 @@ fmuls(void *frD, void *frA, void *frB)
+ int ret = 0;
+
+ #ifdef DEBUG
+- printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
++ printk("%s: %p %p %p\n", __func__, frD, frA, frB);
+ #endif
+
+ __FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fnabs.c b/arch/powerpc/math-emu/fnabs.c
+index c6b913d..a7d34f3 100644
+--- a/arch/powerpc/math-emu/fnabs.c
++++ b/arch/powerpc/math-emu/fnabs.c
+@@ -9,7 +9,7 @@ fnabs(u32 *frD, u32 *frB)
+ frD[1] = frB[1];
+
+ #ifdef DEBUG
+- printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB);
++ printk("%s: D %p, B %p: ", __func__, frD, frB);
+ dump_double(frD);
+ printk("\n");
+ #endif
+diff --git a/arch/powerpc/math-emu/fneg.c b/arch/powerpc/math-emu/fneg.c
+index fe9a98d..1e988cd 100644
+--- a/arch/powerpc/math-emu/fneg.c
++++ b/arch/powerpc/math-emu/fneg.c
+@@ -9,7 +9,7 @@ fneg(u32 *frD, u32 *frB)
+ frD[1] = frB[1];
+
+ #ifdef DEBUG
+- printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB);
++ printk("%s: D %p, B %p: ", __func__, frD, frB);
+ dump_double(frD);
+ printk("\n");
+ #endif
+diff --git a/arch/powerpc/math-emu/fnmadd.c b/arch/powerpc/math-emu/fnmadd.c
+index 7f31227..8cf7827 100644
+--- a/arch/powerpc/math-emu/fnmadd.c
++++ b/arch/powerpc/math-emu/fnmadd.c
+@@ -16,7 +16,7 @@ fnmadd(void *frD, void *frA, void *frB, void *frC)
+ int ret = 0;
+
+ #ifdef DEBUG
+- printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
++ printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
+ #endif
+
+ __FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fnmadds.c b/arch/powerpc/math-emu/fnmadds.c
+index 65454c9..f1c4f0f 100644
+--- a/arch/powerpc/math-emu/fnmadds.c
++++ b/arch/powerpc/math-emu/fnmadds.c
+@@ -17,7 +17,7 @@ fnmadds(void *frD, void *frA, void *frB, void *frC)
+ int ret = 0;
+
+ #ifdef DEBUG
+- printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
++ printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
+ #endif
+
+ __FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fnmsub.c b/arch/powerpc/math-emu/fnmsub.c
+index f1ca748..98944e6 100644
+--- a/arch/powerpc/math-emu/fnmsub.c
++++ b/arch/powerpc/math-emu/fnmsub.c
+@@ -16,7 +16,7 @@ fnmsub(void *frD, void *frA, void *frB, void *frC)
+ int ret = 0;
+
+ #ifdef DEBUG
+- printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
++ printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
+ #endif
+
+ __FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fnmsubs.c b/arch/powerpc/math-emu/fnmsubs.c
+index 5c9a09a..b20f4eb 100644
+--- a/arch/powerpc/math-emu/fnmsubs.c
++++ b/arch/powerpc/math-emu/fnmsubs.c
+@@ -17,7 +17,7 @@ fnmsubs(void *frD, void *frA, void *frB, void *frC)
+ int ret = 0;
+
+ #ifdef DEBUG
+- printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
++ printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
+ #endif
+
+ __FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fres.c b/arch/powerpc/math-emu/fres.c
+index ec11e46..10ecbd0 100644
+--- a/arch/powerpc/math-emu/fres.c
++++ b/arch/powerpc/math-emu/fres.c
+@@ -6,7 +6,7 @@ int
+ fres(void *frD, void *frB)
+ {
+ #ifdef DEBUG
+- printk("%s: %p %p\n", __FUNCTION__, frD, frB);
++ printk("%s: %p %p\n", __func__, frD, frB);
+ #endif
+ return -ENOSYS;
+ }
+diff --git a/arch/powerpc/math-emu/frsp.c b/arch/powerpc/math-emu/frsp.c
+index d879b2a..724ccbc 100644
+--- a/arch/powerpc/math-emu/frsp.c
++++ b/arch/powerpc/math-emu/frsp.c
+@@ -12,7 +12,7 @@ frsp(void *frD, void *frB)
+ FP_DECL_D(B);
+
+ #ifdef DEBUG
+- printk("%s: D %p, B %p\n", __FUNCTION__, frD, frB);
++ printk("%s: D %p, B %p\n", __func__, frD, frB);
+ #endif
+
+ __FP_UNPACK_D(B, frB);
+diff --git a/arch/powerpc/math-emu/frsqrte.c b/arch/powerpc/math-emu/frsqrte.c
+index a11ae18..1d0a3a0 100644
+--- a/arch/powerpc/math-emu/frsqrte.c
++++ b/arch/powerpc/math-emu/frsqrte.c
+@@ -6,7 +6,7 @@ int
+ frsqrte(void *frD, void *frB)
+ {
+ #ifdef DEBUG
+- printk("%s: %p %p\n", __FUNCTION__, frD, frB);
++ printk("%s: %p %p\n", __func__, frD, frB);
+ #endif
+ return 0;
+ }
+diff --git a/arch/powerpc/math-emu/fsel.c b/arch/powerpc/math-emu/fsel.c
+index e36e6e7..ecb5f28 100644
+--- a/arch/powerpc/math-emu/fsel.c
++++ b/arch/powerpc/math-emu/fsel.c
+@@ -11,7 +11,7 @@ fsel(u32 *frD, void *frA, u32 *frB, u32 *frC)
+ FP_DECL_D(A);
+
+ #ifdef DEBUG
+- printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
++ printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
+ #endif
+
+ __FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fsqrt.c b/arch/powerpc/math-emu/fsqrt.c
+index 6f8319f..38ec2b7 100644
+--- a/arch/powerpc/math-emu/fsqrt.c
++++ b/arch/powerpc/math-emu/fsqrt.c
+@@ -13,7 +13,7 @@ fsqrt(void *frD, void *frB)
+ int ret = 0;
+
+ #ifdef DEBUG
+- printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frB);
++ printk("%s: %p %p %p %p\n", __func__, frD, frB);
+ #endif
+
+ __FP_UNPACK_D(B, frB);
+diff --git a/arch/powerpc/math-emu/fsqrts.c b/arch/powerpc/math-emu/fsqrts.c
+index 3b2b1cf..335263e 100644
+--- a/arch/powerpc/math-emu/fsqrts.c
++++ b/arch/powerpc/math-emu/fsqrts.c
+@@ -14,7 +14,7 @@ fsqrts(void *frD, void *frB)
+ int ret = 0;
+
+ #ifdef DEBUG
+- printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frB);
++ printk("%s: %p %p %p %p\n", __func__, frD, frB);
+ #endif
+
+ __FP_UNPACK_D(B, frB);
+diff --git a/arch/powerpc/math-emu/fsub.c b/arch/powerpc/math-emu/fsub.c
+index 9566790..208d20f 100644
+--- a/arch/powerpc/math-emu/fsub.c
++++ b/arch/powerpc/math-emu/fsub.c
+@@ -14,7 +14,7 @@ fsub(void *frD, void *frA, void *frB)
+ int ret = 0;
+
+ #ifdef DEBUG
+- printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
++ printk("%s: %p %p %p\n", __func__, frD, frA, frB);
+ #endif
+
+ __FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/fsubs.c b/arch/powerpc/math-emu/fsubs.c
+index 3428117..0e61b80 100644
+--- a/arch/powerpc/math-emu/fsubs.c
++++ b/arch/powerpc/math-emu/fsubs.c
+@@ -15,7 +15,7 @@ fsubs(void *frD, void *frA, void *frB)
+ int ret = 0;
+
+ #ifdef DEBUG
+- printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
++ printk("%s: %p %p %p\n", __func__, frD, frA, frB);
+ #endif
+
+ __FP_UNPACK_D(A, frA);
+diff --git a/arch/powerpc/math-emu/lfd.c b/arch/powerpc/math-emu/lfd.c
+index 7d38101..6ec90b5 100644
+--- a/arch/powerpc/math-emu/lfd.c
++++ b/arch/powerpc/math-emu/lfd.c
+@@ -11,7 +11,7 @@ lfd(void *frD, void *ea)
+ if (copy_from_user(frD, ea, sizeof(double)))
+ return -EFAULT;
+ #ifdef DEBUG
+- printk("%s: D %p, ea %p: ", __FUNCTION__, frD, ea);
++ printk("%s: D %p, ea %p: ", __func__, frD, ea);
+ dump_double(frD);
+ printk("\n");
+ #endif
+diff --git a/arch/powerpc/math-emu/lfs.c b/arch/powerpc/math-emu/lfs.c
+index c86dee3..6f18ebe 100644
+--- a/arch/powerpc/math-emu/lfs.c
++++ b/arch/powerpc/math-emu/lfs.c
+@@ -14,7 +14,7 @@ lfs(void *frD, void *ea)
+ float f;
+
+ #ifdef DEBUG
+- printk("%s: D %p, ea %p\n", __FUNCTION__, frD, ea);
++ printk("%s: D %p, ea %p\n", __func__, frD, ea);
+ #endif
+
+ if (copy_from_user(&f, ea, sizeof(float)))
+diff --git a/arch/powerpc/math-emu/mcrfs.c b/arch/powerpc/math-emu/mcrfs.c
+index 106dd91..41ba247 100644
+--- a/arch/powerpc/math-emu/mcrfs.c
++++ b/arch/powerpc/math-emu/mcrfs.c
+@@ -10,7 +10,7 @@ mcrfs(u32 *ccr, u32 crfD, u32 crfS)
+ u32 value, clear;
+
+ #ifdef DEBUG
+- printk("%s: %p (%08x) %d %d\n", __FUNCTION__, ccr, *ccr, crfD, crfS);
++ printk("%s: %p (%08x) %d %d\n", __func__, ccr, *ccr, crfD, crfS);
+ #endif
+
+ clear = 15 << ((7 - crfS) << 2);
+@@ -24,7 +24,7 @@ mcrfs(u32 *ccr, u32 crfD, u32 crfS)
+ *ccr |= (value << ((7 - crfD) << 2));
+
+ #ifdef DEBUG
+- printk("CR: %08x\n", __FUNCTION__, *ccr);
++ printk("CR: %08x\n", __func__, *ccr);
+ #endif
+
+ return 0;
+diff --git a/arch/powerpc/math-emu/mffs.c b/arch/powerpc/math-emu/mffs.c
+index f477c91..b0e2106 100644
+--- a/arch/powerpc/math-emu/mffs.c
++++ b/arch/powerpc/math-emu/mffs.c
+@@ -10,7 +10,7 @@ mffs(u32 *frD)
+ frD[1] = __FPU_FPSCR;
+
+ #ifdef DEBUG
+- printk("%s: frD %p: %08x.%08x\n", __FUNCTION__, frD, frD[0], frD[1]);
++ printk("%s: frD %p: %08x.%08x\n", __func__, frD, frD[0], frD[1]);
+ #endif
+
+ return 0;
+diff --git a/arch/powerpc/math-emu/mtfsb0.c b/arch/powerpc/math-emu/mtfsb0.c
+index 99bfd80..d306235 100644
+--- a/arch/powerpc/math-emu/mtfsb0.c
++++ b/arch/powerpc/math-emu/mtfsb0.c
+@@ -11,7 +11,7 @@ mtfsb0(int crbD)
+ __FPU_FPSCR &= ~(1 << (31 - crbD));
+
+ #ifdef DEBUG
+- printk("%s: %d %08lx\n", __FUNCTION__, crbD, __FPU_FPSCR);
++ printk("%s: %d %08lx\n", __func__, crbD, __FPU_FPSCR);
+ #endif
+
+ return 0;
+diff --git a/arch/powerpc/math-emu/mtfsb1.c b/arch/powerpc/math-emu/mtfsb1.c
+index 3d9e7ed..2e94870 100644
+--- a/arch/powerpc/math-emu/mtfsb1.c
++++ b/arch/powerpc/math-emu/mtfsb1.c
+@@ -11,7 +11,7 @@ mtfsb1(int crbD)
+ __FPU_FPSCR |= (1 << (31 - crbD));
+
+ #ifdef DEBUG
+- printk("%s: %d %08lx\n", __FUNCTION__, crbD, __FPU_FPSCR);
++ printk("%s: %d %08lx\n", __func__, crbD, __FPU_FPSCR);
+ #endif
+
+ return 0;
+diff --git a/arch/powerpc/math-emu/mtfsf.c b/arch/powerpc/math-emu/mtfsf.c
+index d70cf71..48014d8 100644
+--- a/arch/powerpc/math-emu/mtfsf.c
++++ b/arch/powerpc/math-emu/mtfsf.c
+@@ -38,7 +38,7 @@ mtfsf(unsigned int FM, u32 *frB)
+ __FPU_FPSCR |= (frB[1] & mask);
+
+ #ifdef DEBUG
+- printk("%s: %02x %p: %08lx\n", __FUNCTION__, FM, frB, __FPU_FPSCR);
++ printk("%s: %02x %p: %08lx\n", __func__, FM, frB, __FPU_FPSCR);
+ #endif
+
+ return 0;
+diff --git a/arch/powerpc/math-emu/mtfsfi.c b/arch/powerpc/math-emu/mtfsfi.c
+index 71df854..031e200 100644
+--- a/arch/powerpc/math-emu/mtfsfi.c
++++ b/arch/powerpc/math-emu/mtfsfi.c
+@@ -16,7 +16,7 @@ mtfsfi(unsigned int crfD, unsigned int IMM)
+ __FPU_FPSCR |= (IMM & 0xf) << ((7 - crfD) << 2);
+
+ #ifdef DEBUG
+- printk("%s: %d %x: %08lx\n", __FUNCTION__, crfD, IMM, __FPU_FPSCR);
++ printk("%s: %d %x: %08lx\n", __func__, crfD, IMM, __FPU_FPSCR);
+ #endif
+
+ return 0;
+diff --git a/arch/powerpc/math-emu/stfd.c b/arch/powerpc/math-emu/stfd.c
+index 3f8c255..33a165c 100644
+--- a/arch/powerpc/math-emu/stfd.c
++++ b/arch/powerpc/math-emu/stfd.c
+@@ -7,7 +7,7 @@ stfd(void *frS, void *ea)
+ {
+ #if 0
+ #ifdef DEBUG
+- printk("%s: S %p, ea %p: ", __FUNCTION__, frS, ea);
++ printk("%s: S %p, ea %p: ", __func__, frS, ea);
+ dump_double(frS);
+ printk("\n");
+ #endif
+diff --git a/arch/powerpc/math-emu/stfiwx.c b/arch/powerpc/math-emu/stfiwx.c
+index 95caaee..f15a35f 100644
+--- a/arch/powerpc/math-emu/stfiwx.c
++++ b/arch/powerpc/math-emu/stfiwx.c
+@@ -6,7 +6,7 @@ int
+ stfiwx(u32 *frS, void *ea)
+ {
+ #ifdef DEBUG
+- printk("%s: %p %p\n", __FUNCTION__, frS, ea);
++ printk("%s: %p %p\n", __func__, frS, ea);
+ #endif
+
+ if (copy_to_user(ea, &frS[1], sizeof(frS[1])))
+diff --git a/arch/powerpc/math-emu/stfs.c b/arch/powerpc/math-emu/stfs.c
+index e87ca23..8689aa4 100644
+--- a/arch/powerpc/math-emu/stfs.c
++++ b/arch/powerpc/math-emu/stfs.c
+@@ -15,7 +15,7 @@ stfs(void *frS, void *ea)
+ int err;
+
+ #ifdef DEBUG
+- printk("%s: S %p, ea %p\n", __FUNCTION__, frS, ea);
++ printk("%s: S %p, ea %p\n", __func__, frS, ea);
+ #endif
+
+ __FP_UNPACK_D(A, frS);
+diff --git a/arch/powerpc/mm/40x_mmu.c b/arch/powerpc/mm/40x_mmu.c
+index 3899ea9..cecbbc7 100644
+--- a/arch/powerpc/mm/40x_mmu.c
++++ b/arch/powerpc/mm/40x_mmu.c
+@@ -97,7 +97,7 @@ unsigned long __init mmu_mapin_ram(void)
+ phys_addr_t p;
+
+ v = KERNELBASE;
+- p = PPC_MEMSTART;
++ p = 0;
+ s = total_lowmem;
+
+ if (__map_without_ltlbs)
+diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c
+index 04dc087..953fb91 100644
+--- a/arch/powerpc/mm/44x_mmu.c
++++ b/arch/powerpc/mm/44x_mmu.c
+@@ -67,7 +67,7 @@ unsigned long __init mmu_mapin_ram(void)
+
+ /* Pin in enough TLBs to cover any lowmem not covered by the
+ * initial 256M mapping established in head_44x.S */
+- for (addr = PPC_PIN_SIZE; addr < total_lowmem;
++ for (addr = PPC_PIN_SIZE; addr < lowmem_end_addr;
+ addr += PPC_PIN_SIZE)
+ ppc44x_pin_tlb(addr + PAGE_OFFSET, addr);
+
+diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile
+index 41649a5..1c00e01 100644
+--- a/arch/powerpc/mm/Makefile
++++ b/arch/powerpc/mm/Makefile
+@@ -6,7 +6,7 @@ ifeq ($(CONFIG_PPC64),y)
+ EXTRA_CFLAGS += -mno-minimal-toc
+ endif
+
+-obj-y := fault.o mem.o lmb.o \
++obj-y := fault.o mem.o \
+ init_$(CONFIG_WORD_SIZE).o \
+ pgtable_$(CONFIG_WORD_SIZE).o \
+ mmu_context_$(CONFIG_WORD_SIZE).o
+diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c
+index c93a966..ce10e2b 100644
+--- a/arch/powerpc/mm/fsl_booke_mmu.c
++++ b/arch/powerpc/mm/fsl_booke_mmu.c
+@@ -49,18 +49,15 @@
+ #include <asm/mmu.h>
+ #include <asm/uaccess.h>
+ #include <asm/smp.h>
+-#include <asm/bootx.h>
+ #include <asm/machdep.h>
+ #include <asm/setup.h>
+
++#include "mmu_decl.h"
++
+ extern void loadcam_entry(unsigned int index);
+ unsigned int tlbcam_index;
+ unsigned int num_tlbcam_entries;
+ static unsigned long __cam0, __cam1, __cam2;
+-extern unsigned long total_lowmem;
+-extern unsigned long __max_low_memory;
+-extern unsigned long __initial_memory_limit;
+-#define MAX_LOW_MEM CONFIG_LOWMEM_SIZE
+
+ #define NUM_TLBCAMS (16)
+
+@@ -165,15 +162,15 @@ void invalidate_tlbcam_entry(int index)
+ void __init cam_mapin_ram(unsigned long cam0, unsigned long cam1,
+ unsigned long cam2)
+ {
+- settlbcam(0, PAGE_OFFSET, PPC_MEMSTART, cam0, _PAGE_KERNEL, 0);
++ settlbcam(0, PAGE_OFFSET, memstart_addr, cam0, _PAGE_KERNEL, 0);
+ tlbcam_index++;
+ if (cam1) {
+ tlbcam_index++;
+- settlbcam(1, PAGE_OFFSET+cam0, PPC_MEMSTART+cam0, cam1, _PAGE_KERNEL, 0);
++ settlbcam(1, PAGE_OFFSET+cam0, memstart_addr+cam0, cam1, _PAGE_KERNEL, 0);
+ }
+ if (cam2) {
+ tlbcam_index++;
+- settlbcam(2, PAGE_OFFSET+cam0+cam1, PPC_MEMSTART+cam0+cam1, cam2, _PAGE_KERNEL, 0);
++ settlbcam(2, PAGE_OFFSET+cam0+cam1, memstart_addr+cam0+cam1, cam2, _PAGE_KERNEL, 0);
+ }
+ }
+
+@@ -196,35 +193,32 @@ unsigned long __init mmu_mapin_ram(void)
+ void __init
+ adjust_total_lowmem(void)
+ {
+- unsigned long max_low_mem = MAX_LOW_MEM;
+- unsigned long cam_max = 0x10000000;
+- unsigned long ram;
++ phys_addr_t max_lowmem_size = __max_low_memory;
++ phys_addr_t cam_max_size = 0x10000000;
++ phys_addr_t ram;
+
+- /* adjust CAM size to max_low_mem */
+- if (max_low_mem < cam_max)
+- cam_max = max_low_mem;
++ /* adjust CAM size to max_lowmem_size */
++ if (max_lowmem_size < cam_max_size)
++ cam_max_size = max_lowmem_size;
+
+- /* adjust lowmem size to max_low_mem */
+- if (max_low_mem < total_lowmem)
+- ram = max_low_mem;
+- else
+- ram = total_lowmem;
++ /* adjust lowmem size to max_lowmem_size */
++ ram = min(max_lowmem_size, (phys_addr_t)total_lowmem);
+
+ /* Calculate CAM values */
+ __cam0 = 1UL << 2 * (__ilog2(ram) / 2);
+- if (__cam0 > cam_max)
+- __cam0 = cam_max;
++ if (__cam0 > cam_max_size)
++ __cam0 = cam_max_size;
+ ram -= __cam0;
+ if (ram) {
+ __cam1 = 1UL << 2 * (__ilog2(ram) / 2);
+- if (__cam1 > cam_max)
+- __cam1 = cam_max;
++ if (__cam1 > cam_max_size)
++ __cam1 = cam_max_size;
+ ram -= __cam1;
+ }
+ if (ram) {
+ __cam2 = 1UL << 2 * (__ilog2(ram) / 2);
+- if (__cam2 > cam_max)
+- __cam2 = cam_max;
++ if (__cam2 > cam_max_size)
++ __cam2 = cam_max_size;
+ ram -= __cam2;
+ }
+
+@@ -232,6 +226,6 @@ adjust_total_lowmem(void)
+ " CAM2=%ldMb residual: %ldMb\n",
+ __cam0 >> 20, __cam1 >> 20, __cam2 >> 20,
+ (total_lowmem - __cam0 - __cam1 - __cam2) >> 20);
+- __max_low_memory = max_low_mem = __cam0 + __cam1 + __cam2;
+- __initial_memory_limit = __max_low_memory;
++ __max_low_memory = __cam0 + __cam1 + __cam2;
++ __initial_memory_limit_addr = memstart_addr + __max_low_memory;
+ }
+diff --git a/arch/powerpc/mm/hash_low_32.S b/arch/powerpc/mm/hash_low_32.S
+index e10d76a..ddeaf9e 100644
+--- a/arch/powerpc/mm/hash_low_32.S
++++ b/arch/powerpc/mm/hash_low_32.S
+@@ -191,7 +191,7 @@ _GLOBAL(add_hash_page)
+ add r3,r3,r0 /* note create_hpte trims to 24 bits */
+
+ #ifdef CONFIG_SMP
+- rlwinm r8,r1,0,0,18 /* use cpu number to make tag */
++ rlwinm r8,r1,0,0,(31-THREAD_SHIFT) /* use cpu number to make tag */
+ lwz r8,TI_CPU(r8) /* to go in mmu_hash_lock */
+ oris r8,r8,12
+ #endif /* CONFIG_SMP */
+@@ -526,7 +526,7 @@ _GLOBAL(flush_hash_pages)
+ #ifdef CONFIG_SMP
+ addis r9,r7,mmu_hash_lock at ha
+ addi r9,r9,mmu_hash_lock at l
+- rlwinm r8,r1,0,0,18
++ rlwinm r8,r1,0,0,(31-THREAD_SHIFT)
+ add r8,r8,r7
+ lwz r8,TI_CPU(r8)
+ oris r8,r8,9
+diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
+index a83dfa3..2b5a399 100644
+--- a/arch/powerpc/mm/hash_utils_64.c
++++ b/arch/powerpc/mm/hash_utils_64.c
+@@ -31,6 +31,7 @@
+ #include <linux/cache.h>
+ #include <linux/init.h>
+ #include <linux/signal.h>
++#include <linux/lmb.h>
+
+ #include <asm/processor.h>
+ #include <asm/pgtable.h>
+@@ -41,7 +42,7 @@
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+ #include <asm/machdep.h>
+-#include <asm/lmb.h>
++#include <asm/prom.h>
+ #include <asm/abs_addr.h>
+ #include <asm/tlbflush.h>
+ #include <asm/io.h>
+@@ -191,6 +192,29 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
+ return ret < 0 ? ret : 0;
+ }
+
++#ifdef CONFIG_MEMORY_HOTPLUG
++static int htab_remove_mapping(unsigned long vstart, unsigned long vend,
++ int psize, int ssize)
++{
++ unsigned long vaddr;
++ unsigned int step, shift;
++
++ shift = mmu_psize_defs[psize].shift;
++ step = 1 << shift;
++
++ if (!ppc_md.hpte_removebolted) {
++ printk(KERN_WARNING "Platform doesn't implement "
++ "hpte_removebolted\n");
++ return -EINVAL;
++ }
++
++ for (vaddr = vstart; vaddr < vend; vaddr += step)
++ ppc_md.hpte_removebolted(vaddr, psize, ssize);
++
++ return 0;
++}
++#endif /* CONFIG_MEMORY_HOTPLUG */
++
+ static int __init htab_dt_scan_seg_sizes(unsigned long node,
+ const char *uname, int depth,
+ void *data)
+@@ -434,6 +458,12 @@ void create_section_mapping(unsigned long start, unsigned long end)
+ _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX,
+ mmu_linear_psize, mmu_kernel_ssize));
+ }
++
++int remove_section_mapping(unsigned long start, unsigned long end)
++{
++ return htab_remove_mapping(start, end, mmu_linear_psize,
++ mmu_kernel_ssize);
++}
+ #endif /* CONFIG_MEMORY_HOTPLUG */
+
+ static inline void make_bl(unsigned int *insn_addr, void *func)
+diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
+index 977cb1e..1952b4d 100644
+--- a/arch/powerpc/mm/init_32.c
++++ b/arch/powerpc/mm/init_32.c
+@@ -30,6 +30,7 @@
+ #include <linux/highmem.h>
+ #include <linux/initrd.h>
+ #include <linux/pagemap.h>
++#include <linux/lmb.h>
+
+ #include <asm/pgalloc.h>
+ #include <asm/prom.h>
+@@ -41,7 +42,6 @@
+ #include <asm/machdep.h>
+ #include <asm/btext.h>
+ #include <asm/tlb.h>
+-#include <asm/lmb.h>
+ #include <asm/sections.h>
+
+ #include "mmu_decl.h"
+@@ -59,8 +59,11 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+ unsigned long total_memory;
+ unsigned long total_lowmem;
+
+-unsigned long ppc_memstart;
+-unsigned long ppc_memoffset = PAGE_OFFSET;
++phys_addr_t memstart_addr = (phys_addr_t)~0ull;
++EXPORT_SYMBOL(memstart_addr);
++phys_addr_t kernstart_addr;
++EXPORT_SYMBOL(kernstart_addr);
++phys_addr_t lowmem_end_addr;
+
+ int boot_mapsize;
+ #ifdef CONFIG_PPC_PMAC
+@@ -68,14 +71,6 @@ unsigned long agp_special_page;
+ EXPORT_SYMBOL(agp_special_page);
+ #endif
+
+-#ifdef CONFIG_HIGHMEM
+-pte_t *kmap_pte;
+-pgprot_t kmap_prot;
+-
+-EXPORT_SYMBOL(kmap_prot);
+-EXPORT_SYMBOL(kmap_pte);
+-#endif
+-
+ void MMU_init(void);
+
+ /* XXX should be in current.h -- paulus */
+@@ -95,10 +90,10 @@ int __map_without_ltlbs;
+ unsigned long __max_low_memory = MAX_LOW_MEM;
+
+ /*
+- * limit of what is accessible with initial MMU setup -
++ * address of the limit of what is accessible with initial MMU setup -
+ * 256MB usually, but only 16MB on 601.
+ */
+-unsigned long __initial_memory_limit = 0x10000000;
++phys_addr_t __initial_memory_limit_addr = (phys_addr_t)0x10000000;
+
+ /*
+ * Check for command-line options that affect what MMU_init will do.
+@@ -131,10 +126,10 @@ void __init MMU_init(void)
+
+ /* 601 can only access 16MB at the moment */
+ if (PVR_VER(mfspr(SPRN_PVR)) == 1)
+- __initial_memory_limit = 0x01000000;
++ __initial_memory_limit_addr = 0x01000000;
+ /* 8xx can only access 8MB at the moment */
+ if (PVR_VER(mfspr(SPRN_PVR)) == 0x50)
+- __initial_memory_limit = 0x00800000;
++ __initial_memory_limit_addr = 0x00800000;
+
+ /* parse args from command line */
+ MMU_setup();
+@@ -145,8 +140,8 @@ void __init MMU_init(void)
+ printk(KERN_WARNING "Only using first contiguous memory region");
+ }
+
+- total_memory = lmb_end_of_DRAM();
+- total_lowmem = total_memory;
++ total_lowmem = total_memory = lmb_end_of_DRAM() - memstart_addr;
++ lowmem_end_addr = memstart_addr + total_lowmem;
+
+ #ifdef CONFIG_FSL_BOOKE
+ /* Freescale Book-E parts expect lowmem to be mapped by fixed TLB
+@@ -157,9 +152,10 @@ void __init MMU_init(void)
+
+ if (total_lowmem > __max_low_memory) {
+ total_lowmem = __max_low_memory;
++ lowmem_end_addr = memstart_addr + total_lowmem;
+ #ifndef CONFIG_HIGHMEM
+ total_memory = total_lowmem;
+- lmb_enforce_memory_limit(total_lowmem);
++ lmb_enforce_memory_limit(lowmem_end_addr);
+ lmb_analyze();
+ #endif /* CONFIG_HIGHMEM */
+ }
+@@ -184,8 +180,6 @@ void __init MMU_init(void)
+ /* Map in I/O resources */
+ if (ppc_md.progress)
+ ppc_md.progress("MMU:setio", 0x302);
+- if (ppc_md.setup_io_mappings)
+- ppc_md.setup_io_mappings();
+
+ /* Initialize the context management stuff */
+ mmu_context_init();
+@@ -208,7 +202,7 @@ void __init *early_get_page(void)
+ p = alloc_bootmem_pages(PAGE_SIZE);
+ } else {
+ p = __va(lmb_alloc_base(PAGE_SIZE, PAGE_SIZE,
+- __initial_memory_limit));
++ __initial_memory_limit_addr));
+ }
+ return p;
+ }
+@@ -276,7 +270,7 @@ static int __init setup_kcore(void)
+
+ kcore_mem = kmalloc(sizeof(struct kcore_list), GFP_ATOMIC);
+ if (!kcore_mem)
+- panic("%s: kmalloc failed\n", __FUNCTION__);
++ panic("%s: kmalloc failed\n", __func__);
+
+ /* must stay under 32 bits */
+ if ( 0xfffffffful - (unsigned long)__va(base) < size) {
+diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
+index c0f5cff..c5ac532 100644
+--- a/arch/powerpc/mm/init_64.c
++++ b/arch/powerpc/mm/init_64.c
+@@ -38,11 +38,11 @@
+ #include <linux/nodemask.h>
+ #include <linux/module.h>
+ #include <linux/poison.h>
++#include <linux/lmb.h>
+
+ #include <asm/pgalloc.h>
+ #include <asm/page.h>
+ #include <asm/prom.h>
+-#include <asm/lmb.h>
+ #include <asm/rtas.h>
+ #include <asm/io.h>
+ #include <asm/mmu_context.h>
+@@ -72,8 +72,8 @@
+ #warning TASK_SIZE is smaller than it needs to be.
+ #endif
+
+-/* max amount of RAM to use */
+-unsigned long __max_memory;
++phys_addr_t memstart_addr = ~0;
++phys_addr_t kernstart_addr;
+
+ void free_initmem(void)
+ {
+@@ -122,7 +122,7 @@ static int __init setup_kcore(void)
+ /* GFP_ATOMIC to avoid might_sleep warnings during boot */
+ kcore_mem = kmalloc(sizeof(struct kcore_list), GFP_ATOMIC);
+ if (!kcore_mem)
+- panic("%s: kmalloc failed\n", __FUNCTION__);
++ panic("%s: kmalloc failed\n", __func__);
+
+ kclist_add(kcore_mem, __va(base), size);
+ }
+diff --git a/arch/powerpc/mm/lmb.c b/arch/powerpc/mm/lmb.c
+deleted file mode 100644
+index 4ce23bc..0000000
+--- a/arch/powerpc/mm/lmb.c
++++ /dev/null
+@@ -1,357 +0,0 @@
+-/*
+- * Procedures for maintaining information about logical memory blocks.
+- *
+- * Peter Bergner, IBM Corp. June 2001.
+- * Copyright (C) 2001 Peter Bergner.
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/bitops.h>
+-#include <asm/types.h>
+-#include <asm/page.h>
+-#include <asm/prom.h>
+-#include <asm/lmb.h>
+-#ifdef CONFIG_PPC32
+-#include "mmu_decl.h" /* for __max_low_memory */
+-#endif
+-
+-#undef DEBUG
+-
+-#ifdef DEBUG
+-#include <asm/udbg.h>
+-#define DBG(fmt...) udbg_printf(fmt)
+-#else
+-#define DBG(fmt...)
+-#endif
+-
+-#define LMB_ALLOC_ANYWHERE 0
+-
+-struct lmb lmb;
+-
+-void lmb_dump_all(void)
+-{
+-#ifdef DEBUG
+- unsigned long i;
+-
+- DBG("lmb_dump_all:\n");
+- DBG(" memory.cnt = 0x%lx\n", lmb.memory.cnt);
+- DBG(" memory.size = 0x%lx\n", lmb.memory.size);
+- for (i=0; i < lmb.memory.cnt ;i++) {
+- DBG(" memory.region[0x%x].base = 0x%lx\n",
+- i, lmb.memory.region[i].base);
+- DBG(" .size = 0x%lx\n",
+- lmb.memory.region[i].size);
+- }
+-
+- DBG("\n reserved.cnt = 0x%lx\n", lmb.reserved.cnt);
+- DBG(" reserved.size = 0x%lx\n", lmb.reserved.size);
+- for (i=0; i < lmb.reserved.cnt ;i++) {
+- DBG(" reserved.region[0x%x].base = 0x%lx\n",
+- i, lmb.reserved.region[i].base);
+- DBG(" .size = 0x%lx\n",
+- lmb.reserved.region[i].size);
+- }
+-#endif /* DEBUG */
+-}
+-
+-static unsigned long __init lmb_addrs_overlap(unsigned long base1,
+- unsigned long size1, unsigned long base2, unsigned long size2)
+-{
+- return ((base1 < (base2+size2)) && (base2 < (base1+size1)));
+-}
+-
+-static long __init lmb_addrs_adjacent(unsigned long base1, unsigned long size1,
+- unsigned long base2, unsigned long size2)
+-{
+- if (base2 == base1 + size1)
+- return 1;
+- else if (base1 == base2 + size2)
+- return -1;
+-
+- return 0;
+-}
+-
+-static long __init lmb_regions_adjacent(struct lmb_region *rgn,
+- unsigned long r1, unsigned long r2)
+-{
+- unsigned long base1 = rgn->region[r1].base;
+- unsigned long size1 = rgn->region[r1].size;
+- unsigned long base2 = rgn->region[r2].base;
+- unsigned long size2 = rgn->region[r2].size;
+-
+- return lmb_addrs_adjacent(base1, size1, base2, size2);
+-}
+-
+-static void __init lmb_remove_region(struct lmb_region *rgn, unsigned long r)
+-{
+- unsigned long i;
+-
+- for (i = r; i < rgn->cnt - 1; i++) {
+- rgn->region[i].base = rgn->region[i + 1].base;
+- rgn->region[i].size = rgn->region[i + 1].size;
+- }
+- rgn->cnt--;
+-}
+-
+-/* Assumption: base addr of region 1 < base addr of region 2 */
+-static void __init lmb_coalesce_regions(struct lmb_region *rgn,
+- unsigned long r1, unsigned long r2)
+-{
+- rgn->region[r1].size += rgn->region[r2].size;
+- lmb_remove_region(rgn, r2);
+-}
+-
+-/* This routine called with relocation disabled. */
+-void __init lmb_init(void)
+-{
+- /* Create a dummy zero size LMB which will get coalesced away later.
+- * This simplifies the lmb_add() code below...
+- */
+- lmb.memory.region[0].base = 0;
+- lmb.memory.region[0].size = 0;
+- lmb.memory.cnt = 1;
+-
+- /* Ditto. */
+- lmb.reserved.region[0].base = 0;
+- lmb.reserved.region[0].size = 0;
+- lmb.reserved.cnt = 1;
+-}
+-
+-/* This routine may be called with relocation disabled. */
+-void __init lmb_analyze(void)
+-{
+- int i;
+-
+- lmb.memory.size = 0;
+-
+- for (i = 0; i < lmb.memory.cnt; i++)
+- lmb.memory.size += lmb.memory.region[i].size;
+-}
+-
+-/* This routine called with relocation disabled. */
+-static long __init lmb_add_region(struct lmb_region *rgn, unsigned long base,
+- unsigned long size)
+-{
+- unsigned long coalesced = 0;
+- long adjacent, i;
+-
+- /* First try and coalesce this LMB with another. */
+- for (i=0; i < rgn->cnt; i++) {
+- unsigned long rgnbase = rgn->region[i].base;
+- unsigned long rgnsize = rgn->region[i].size;
+-
+- if ((rgnbase == base) && (rgnsize == size))
+- /* Already have this region, so we're done */
+- return 0;
+-
+- adjacent = lmb_addrs_adjacent(base,size,rgnbase,rgnsize);
+- if ( adjacent > 0 ) {
+- rgn->region[i].base -= size;
+- rgn->region[i].size += size;
+- coalesced++;
+- break;
+- }
+- else if ( adjacent < 0 ) {
+- rgn->region[i].size += size;
+- coalesced++;
+- break;
+- }
+- }
+-
+- if ((i < rgn->cnt-1) && lmb_regions_adjacent(rgn, i, i+1) ) {
+- lmb_coalesce_regions(rgn, i, i+1);
+- coalesced++;
+- }
+-
+- if (coalesced)
+- return coalesced;
+- if (rgn->cnt >= MAX_LMB_REGIONS)
+- return -1;
+-
+- /* Couldn't coalesce the LMB, so add it to the sorted table. */
+- for (i = rgn->cnt-1; i >= 0; i--) {
+- if (base < rgn->region[i].base) {
+- rgn->region[i+1].base = rgn->region[i].base;
+- rgn->region[i+1].size = rgn->region[i].size;
+- } else {
+- rgn->region[i+1].base = base;
+- rgn->region[i+1].size = size;
+- break;
+- }
+- }
+- rgn->cnt++;
+-
+- return 0;
+-}
+-
+-/* This routine may be called with relocation disabled. */
+-long __init lmb_add(unsigned long base, unsigned long size)
+-{
+- struct lmb_region *_rgn = &(lmb.memory);
+-
+- /* On pSeries LPAR systems, the first LMB is our RMO region. */
+- if (base == 0)
+- lmb.rmo_size = size;
+-
+- return lmb_add_region(_rgn, base, size);
+-
+-}
+-
+-long __init lmb_reserve(unsigned long base, unsigned long size)
+-{
+- struct lmb_region *_rgn = &(lmb.reserved);
+-
+- BUG_ON(0 == size);
+-
+- return lmb_add_region(_rgn, base, size);
+-}
+-
+-long __init lmb_overlaps_region(struct lmb_region *rgn, unsigned long base,
+- unsigned long size)
+-{
+- unsigned long i;
+-
+- for (i=0; i < rgn->cnt; i++) {
+- unsigned long rgnbase = rgn->region[i].base;
+- unsigned long rgnsize = rgn->region[i].size;
+- if ( lmb_addrs_overlap(base,size,rgnbase,rgnsize) ) {
+- break;
+- }
+- }
+-
+- return (i < rgn->cnt) ? i : -1;
+-}
+-
+-unsigned long __init lmb_alloc(unsigned long size, unsigned long align)
+-{
+- return lmb_alloc_base(size, align, LMB_ALLOC_ANYWHERE);
+-}
+-
+-unsigned long __init lmb_alloc_base(unsigned long size, unsigned long align,
+- unsigned long max_addr)
+-{
+- unsigned long alloc;
+-
+- alloc = __lmb_alloc_base(size, align, max_addr);
+-
+- if (alloc == 0)
+- panic("ERROR: Failed to allocate 0x%lx bytes below 0x%lx.\n",
+- size, max_addr);
+-
+- return alloc;
+-}
+-
+-unsigned long __init __lmb_alloc_base(unsigned long size, unsigned long align,
+- unsigned long max_addr)
+-{
+- long i, j;
+- unsigned long base = 0;
+-
+- BUG_ON(0 == size);
+-
+-#ifdef CONFIG_PPC32
+- /* On 32-bit, make sure we allocate lowmem */
+- if (max_addr == LMB_ALLOC_ANYWHERE)
+- max_addr = __max_low_memory;
+-#endif
+- for (i = lmb.memory.cnt-1; i >= 0; i--) {
+- unsigned long lmbbase = lmb.memory.region[i].base;
+- unsigned long lmbsize = lmb.memory.region[i].size;
+-
+- if (max_addr == LMB_ALLOC_ANYWHERE)
+- base = _ALIGN_DOWN(lmbbase + lmbsize - size, align);
+- else if (lmbbase < max_addr) {
+- base = min(lmbbase + lmbsize, max_addr);
+- base = _ALIGN_DOWN(base - size, align);
+- } else
+- continue;
+-
+- while ((lmbbase <= base) &&
+- ((j = lmb_overlaps_region(&lmb.reserved, base, size)) >= 0) )
+- base = _ALIGN_DOWN(lmb.reserved.region[j].base - size,
+- align);
+-
+- if ((base != 0) && (lmbbase <= base))
+- break;
+- }
+-
+- if (i < 0)
+- return 0;
+-
+- lmb_add_region(&lmb.reserved, base, size);
+-
+- return base;
+-}
+-
+-/* You must call lmb_analyze() before this. */
+-unsigned long __init lmb_phys_mem_size(void)
+-{
+- return lmb.memory.size;
+-}
+-
+-unsigned long __init lmb_end_of_DRAM(void)
+-{
+- int idx = lmb.memory.cnt - 1;
+-
+- return (lmb.memory.region[idx].base + lmb.memory.region[idx].size);
+-}
+-
+-/* You must call lmb_analyze() after this. */
+-void __init lmb_enforce_memory_limit(unsigned long memory_limit)
+-{
+- unsigned long i, limit;
+- struct lmb_property *p;
+-
+- if (! memory_limit)
+- return;
+-
+- /* Truncate the lmb regions to satisfy the memory limit. */
+- limit = memory_limit;
+- for (i = 0; i < lmb.memory.cnt; i++) {
+- if (limit > lmb.memory.region[i].size) {
+- limit -= lmb.memory.region[i].size;
+- continue;
+- }
+-
+- lmb.memory.region[i].size = limit;
+- lmb.memory.cnt = i + 1;
+- break;
+- }
+-
+- if (lmb.memory.region[0].size < lmb.rmo_size)
+- lmb.rmo_size = lmb.memory.region[0].size;
+-
+- /* And truncate any reserves above the limit also. */
+- for (i = 0; i < lmb.reserved.cnt; i++) {
+- p = &lmb.reserved.region[i];
+-
+- if (p->base > memory_limit)
+- p->size = 0;
+- else if ((p->base + p->size) > memory_limit)
+- p->size = memory_limit - p->base;
+-
+- if (p->size == 0) {
+- lmb_remove_region(&lmb.reserved, i);
+- i--;
+- }
+- }
+-}
+-
+-int __init lmb_is_reserved(unsigned long addr)
+-{
+- int i;
+-
+- for (i = 0; i < lmb.reserved.cnt; i++) {
+- unsigned long upper = lmb.reserved.region[i].base +
+- lmb.reserved.region[i].size - 1;
+- if ((addr >= lmb.reserved.region[i].base) && (addr <= upper))
+- return 1;
+- }
+- return 0;
+-}
+diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
+index be5c506..5ccb579 100644
+--- a/arch/powerpc/mm/mem.c
++++ b/arch/powerpc/mm/mem.c
+@@ -31,6 +31,7 @@
+ #include <linux/initrd.h>
+ #include <linux/pagemap.h>
+ #include <linux/suspend.h>
++#include <linux/lmb.h>
+
+ #include <asm/pgalloc.h>
+ #include <asm/prom.h>
+@@ -42,9 +43,9 @@
+ #include <asm/machdep.h>
+ #include <asm/btext.h>
+ #include <asm/tlb.h>
+-#include <asm/lmb.h>
+ #include <asm/sections.h>
+ #include <asm/vdso.h>
++#include <asm/fixmap.h>
+
+ #include "mmu_decl.h"
+
+@@ -57,6 +58,20 @@ int init_bootmem_done;
+ int mem_init_done;
+ unsigned long memory_limit;
+
++#ifdef CONFIG_HIGHMEM
++pte_t *kmap_pte;
++pgprot_t kmap_prot;
++
++EXPORT_SYMBOL(kmap_prot);
++EXPORT_SYMBOL(kmap_pte);
++
++static inline pte_t *virt_to_kpte(unsigned long vaddr)
++{
++ return pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr),
++ vaddr), vaddr), vaddr);
++}
++#endif
++
+ int page_is_ram(unsigned long pfn)
+ {
+ unsigned long paddr = (pfn << PAGE_SHIFT);
+@@ -111,7 +126,7 @@ int memory_add_physaddr_to_nid(u64 start)
+ }
+ #endif
+
+-int __devinit arch_add_memory(int nid, u64 start, u64 size)
++int arch_add_memory(int nid, u64 start, u64 size)
+ {
+ struct pglist_data *pgdata;
+ struct zone *zone;
+@@ -175,7 +190,6 @@ void show_mem(void)
+
+ printk("Mem-info:\n");
+ show_free_areas();
+- printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+ for_each_online_pgdat(pgdat) {
+ unsigned long flags;
+ pgdat_resize_lock(pgdat, &flags);
+@@ -217,9 +231,11 @@ void __init do_init_bootmem(void)
+ unsigned long total_pages;
+ int boot_mapsize;
+
+- max_pfn = total_pages = lmb_end_of_DRAM() >> PAGE_SHIFT;
++ max_low_pfn = max_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT;
++ total_pages = (lmb_end_of_DRAM() - memstart_addr) >> PAGE_SHIFT;
+ #ifdef CONFIG_HIGHMEM
+ total_pages = total_lowmem >> PAGE_SHIFT;
++ max_low_pfn = lowmem_end_addr >> PAGE_SHIFT;
+ #endif
+
+ /*
+@@ -231,7 +247,8 @@ void __init do_init_bootmem(void)
+
+ start = lmb_alloc(bootmap_pages << PAGE_SHIFT, PAGE_SIZE);
+
+- boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages);
++ min_low_pfn = MEMORY_START >> PAGE_SHIFT;
++ boot_mapsize = init_bootmem_node(NODE_DATA(0), start >> PAGE_SHIFT, min_low_pfn, max_low_pfn);
+
+ /* Add active regions with valid PFNs */
+ for (i = 0; i < lmb.memory.cnt; i++) {
+@@ -245,18 +262,18 @@ void __init do_init_bootmem(void)
+ * present.
+ */
+ #ifdef CONFIG_HIGHMEM
+- free_bootmem_with_active_regions(0, total_lowmem >> PAGE_SHIFT);
++ free_bootmem_with_active_regions(0, lowmem_end_addr >> PAGE_SHIFT);
+
+ /* reserve the sections we're already using */
+ for (i = 0; i < lmb.reserved.cnt; i++) {
+ unsigned long addr = lmb.reserved.region[i].base +
+ lmb_size_bytes(&lmb.reserved, i) - 1;
+- if (addr < total_lowmem)
++ if (addr < lowmem_end_addr)
+ reserve_bootmem(lmb.reserved.region[i].base,
+ lmb_size_bytes(&lmb.reserved, i),
+ BOOTMEM_DEFAULT);
+- else if (lmb.reserved.region[i].base < total_lowmem) {
+- unsigned long adjusted_size = total_lowmem -
++ else if (lmb.reserved.region[i].base < lowmem_end_addr) {
++ unsigned long adjusted_size = lowmem_end_addr -
+ lmb.reserved.region[i].base;
+ reserve_bootmem(lmb.reserved.region[i].base,
+ adjusted_size, BOOTMEM_DEFAULT);
+@@ -309,14 +326,19 @@ void __init paging_init(void)
+ unsigned long top_of_ram = lmb_end_of_DRAM();
+ unsigned long max_zone_pfns[MAX_NR_ZONES];
+
++#ifdef CONFIG_PPC32
++ unsigned long v = __fix_to_virt(__end_of_fixed_addresses - 1);
++ unsigned long end = __fix_to_virt(FIX_HOLE);
++
++ for (; v < end; v += PAGE_SIZE)
++ map_page(v, 0, 0); /* XXX gross */
++#endif
++
+ #ifdef CONFIG_HIGHMEM
+ map_page(PKMAP_BASE, 0, 0); /* XXX gross */
+- pkmap_page_table = pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k
+- (PKMAP_BASE), PKMAP_BASE), PKMAP_BASE), PKMAP_BASE);
+- map_page(KMAP_FIX_BEGIN, 0, 0); /* XXX gross */
+- kmap_pte = pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k
+- (KMAP_FIX_BEGIN), KMAP_FIX_BEGIN), KMAP_FIX_BEGIN),
+- KMAP_FIX_BEGIN);
++ pkmap_page_table = virt_to_kpte(PKMAP_BASE);
++
++ kmap_pte = virt_to_kpte(__fix_to_virt(FIX_KMAP_BEGIN));
+ kmap_prot = PAGE_KERNEL;
+ #endif /* CONFIG_HIGHMEM */
+
+@@ -326,7 +348,7 @@ void __init paging_init(void)
+ (top_of_ram - total_ram) >> 20);
+ memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+ #ifdef CONFIG_HIGHMEM
+- max_zone_pfns[ZONE_DMA] = total_lowmem >> PAGE_SHIFT;
++ max_zone_pfns[ZONE_DMA] = lowmem_end_addr >> PAGE_SHIFT;
+ max_zone_pfns[ZONE_HIGHMEM] = top_of_ram >> PAGE_SHIFT;
+ #else
+ max_zone_pfns[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
+@@ -381,7 +403,7 @@ void __init mem_init(void)
+ {
+ unsigned long pfn, highmem_mapnr;
+
+- highmem_mapnr = total_lowmem >> PAGE_SHIFT;
++ highmem_mapnr = lowmem_end_addr >> PAGE_SHIFT;
+ for (pfn = highmem_mapnr; pfn < max_mapnr; ++pfn) {
+ struct page *page = pfn_to_page(pfn);
+ if (lmb_is_reserved(pfn << PAGE_SHIFT))
+diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
+index ebfd13d..0480225 100644
+--- a/arch/powerpc/mm/mmu_decl.h
++++ b/arch/powerpc/mm/mmu_decl.h
+@@ -48,9 +48,11 @@ extern unsigned int num_tlbcam_entries;
+
+ extern unsigned long ioremap_bot;
+ extern unsigned long __max_low_memory;
+-extern unsigned long __initial_memory_limit;
++extern phys_addr_t __initial_memory_limit_addr;
+ extern unsigned long total_memory;
+ extern unsigned long total_lowmem;
++extern phys_addr_t memstart_addr;
++extern phys_addr_t lowmem_end_addr;
+
+ /* ...and now those things that may be slightly different between processor
+ * architectures. -- Dan
+diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
+index a300d25..dc704da 100644
+--- a/arch/powerpc/mm/numa.c
++++ b/arch/powerpc/mm/numa.c
+@@ -17,8 +17,10 @@
+ #include <linux/nodemask.h>
+ #include <linux/cpu.h>
+ #include <linux/notifier.h>
++#include <linux/lmb.h>
++#include <linux/of.h>
+ #include <asm/sparsemem.h>
+-#include <asm/lmb.h>
++#include <asm/prom.h>
+ #include <asm/system.h>
+ #include <asm/smp.h>
+
+diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
+index ac3390f..80d1bab 100644
+--- a/arch/powerpc/mm/pgtable_32.c
++++ b/arch/powerpc/mm/pgtable_32.c
+@@ -29,6 +29,7 @@
+
+ #include <asm/pgtable.h>
+ #include <asm/pgalloc.h>
++#include <asm/fixmap.h>
+ #include <asm/io.h>
+
+ #include "mmu_decl.h"
+@@ -281,12 +282,13 @@ int map_page(unsigned long va, phys_addr_t pa, int flags)
+ */
+ void __init mapin_ram(void)
+ {
+- unsigned long v, p, s, f;
++ unsigned long v, s, f;
++ phys_addr_t p;
+ int ktext;
+
+ s = mmu_mapin_ram();
+ v = KERNELBASE + s;
+- p = PPC_MEMSTART + s;
++ p = memstart_addr + s;
+ for (; s < total_lowmem; s += PAGE_SIZE) {
+ ktext = ((char *) v >= _stext && (char *) v < etext);
+ f = ktext ?_PAGE_RAM_TEXT : _PAGE_RAM;
+@@ -386,3 +388,25 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
+ change_page_attr(page, numpages, enable ? PAGE_KERNEL : __pgprot(0));
+ }
+ #endif /* CONFIG_DEBUG_PAGEALLOC */
++
++static int fixmaps;
++unsigned long FIXADDR_TOP = 0xfffff000;
++EXPORT_SYMBOL(FIXADDR_TOP);
++
++void __set_fixmap (enum fixed_addresses idx, phys_addr_t phys, pgprot_t flags)
++{
++ unsigned long address = __fix_to_virt(idx);
++
++ if (idx >= __end_of_fixed_addresses) {
++ BUG();
++ return;
++ }
++
++ map_page(address, phys, flags);
++ fixmaps++;
++}
++
++void __this_fixmap_does_not_exist(void)
++{
++ WARN_ON(1);
++}
+diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
+index 5c45d47..cef9f15 100644
+--- a/arch/powerpc/mm/ppc_mmu_32.c
++++ b/arch/powerpc/mm/ppc_mmu_32.c
+@@ -26,11 +26,11 @@
+ #include <linux/mm.h>
+ #include <linux/init.h>
+ #include <linux/highmem.h>
++#include <linux/lmb.h>
+
+ #include <asm/prom.h>
+ #include <asm/mmu.h>
+ #include <asm/machdep.h>
+-#include <asm/lmb.h>
+
+ #include "mmu_decl.h"
+
+@@ -82,7 +82,6 @@ unsigned long __init mmu_mapin_ram(void)
+ #else
+ unsigned long tot, bl, done;
+ unsigned long max_size = (256<<20);
+- unsigned long align;
+
+ if (__map_without_bats) {
+ printk(KERN_DEBUG "RAM mapped without BATs\n");
+@@ -93,19 +92,13 @@ unsigned long __init mmu_mapin_ram(void)
+
+ /* Make sure we don't map a block larger than the
+ smallest alignment of the physical address. */
+- /* alignment of PPC_MEMSTART */
+- align = ~(PPC_MEMSTART-1) & PPC_MEMSTART;
+- /* set BAT block size to MIN(max_size, align) */
+- if (align && align < max_size)
+- max_size = align;
+-
+ tot = total_lowmem;
+ for (bl = 128<<10; bl < max_size; bl <<= 1) {
+ if (bl * 2 > tot)
+ break;
+ }
+
+- setbat(2, KERNELBASE, PPC_MEMSTART, bl, _PAGE_RAM);
++ setbat(2, KERNELBASE, 0, bl, _PAGE_RAM);
+ done = (unsigned long)bat_addrs[2].limit - KERNELBASE + 1;
+ if ((done < tot) && !bat_addrs[3].limit) {
+ /* use BAT3 to cover a bit more */
+@@ -113,7 +106,7 @@ unsigned long __init mmu_mapin_ram(void)
+ for (bl = 128<<10; bl < max_size; bl <<= 1)
+ if (bl * 2 > tot)
+ break;
+- setbat(3, KERNELBASE+done, PPC_MEMSTART+done, bl, _PAGE_RAM);
++ setbat(3, KERNELBASE+done, done, bl, _PAGE_RAM);
+ done = (unsigned long)bat_addrs[3].limit - KERNELBASE + 1;
+ }
+
+@@ -240,7 +233,7 @@ void __init MMU_init_hw(void)
+ */
+ if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322);
+ Hash = __va(lmb_alloc_base(Hash_size, Hash_size,
+- __initial_memory_limit));
++ __initial_memory_limit_addr));
+ cacheable_memzero(Hash, Hash_size);
+ _SDR1 = __pa(Hash) | SDR1_LOW_BITS;
+
+diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c
+index 50448d5..efbbd13 100644
+--- a/arch/powerpc/mm/stab.c
++++ b/arch/powerpc/mm/stab.c
+@@ -12,12 +12,14 @@
+ * 2 of the License, or (at your option) any later version.
+ */
+
++#include <linux/lmb.h>
++
+ #include <asm/pgtable.h>
+ #include <asm/mmu.h>
+ #include <asm/mmu_context.h>
+ #include <asm/paca.h>
+ #include <asm/cputable.h>
+-#include <asm/lmb.h>
++#include <asm/prom.h>
+ #include <asm/abs_addr.h>
+ #include <asm/firmware.h>
+ #include <asm/iseries/hv_call.h>
+diff --git a/arch/powerpc/oprofile/cell/spu_task_sync.c b/arch/powerpc/oprofile/cell/spu_task_sync.c
+index 257b13c..2a9b4a0 100644
+--- a/arch/powerpc/oprofile/cell/spu_task_sync.c
++++ b/arch/powerpc/oprofile/cell/spu_task_sync.c
+@@ -68,7 +68,7 @@ static struct cached_info *get_cached_info(struct spu *the_spu, int spu_num)
+ if (spu_num >= num_spu_nodes) {
+ printk(KERN_ERR "SPU_PROF: "
+ "%s, line %d: Invalid index %d into spu info cache\n",
+- __FUNCTION__, __LINE__, spu_num);
++ __func__, __LINE__, spu_num);
+ ret_info = NULL;
+ goto out;
+ }
+@@ -115,7 +115,7 @@ prepare_cached_spu_info(struct spu *spu, unsigned long objectId)
+ if (!info) {
+ printk(KERN_ERR "SPU_PROF: "
+ "%s, line %d: create vma_map failed\n",
+- __FUNCTION__, __LINE__);
++ __func__, __LINE__);
+ retval = -ENOMEM;
+ goto err_alloc;
+ }
+@@ -123,7 +123,7 @@ prepare_cached_spu_info(struct spu *spu, unsigned long objectId)
+ if (!new_map) {
+ printk(KERN_ERR "SPU_PROF: "
+ "%s, line %d: create vma_map failed\n",
+- __FUNCTION__, __LINE__);
++ __func__, __LINE__);
+ retval = -ENOMEM;
+ goto err_alloc;
+ }
+@@ -171,7 +171,7 @@ static int release_cached_info(int spu_index)
+ printk(KERN_ERR "SPU_PROF: "
+ "%s, line %d: "
+ "Invalid index %d into spu info cache\n",
+- __FUNCTION__, __LINE__, spu_index);
++ __func__, __LINE__, spu_index);
+ goto out;
+ }
+ end = spu_index + 1;
+@@ -273,7 +273,7 @@ fail_no_image_cookie:
+
+ printk(KERN_ERR "SPU_PROF: "
+ "%s, line %d: Cannot find dcookie for SPU binary\n",
+- __FUNCTION__, __LINE__);
++ __func__, __LINE__);
+ goto out;
+ }
+
+@@ -467,7 +467,7 @@ int spu_sync_stop(void)
+ if (ret) {
+ printk(KERN_ERR "SPU_PROF: "
+ "%s, line %d: spu_switch_event_unregister returned %d\n",
+- __FUNCTION__, __LINE__, ret);
++ __func__, __LINE__, ret);
+ goto out;
+ }
+
+diff --git a/arch/powerpc/oprofile/cell/vma_map.c b/arch/powerpc/oprofile/cell/vma_map.c
+index 9a93217..fff6666 100644
+--- a/arch/powerpc/oprofile/cell/vma_map.c
++++ b/arch/powerpc/oprofile/cell/vma_map.c
+@@ -72,7 +72,7 @@ vma_map_add(struct vma_to_fileoffset_map *map, unsigned int vma,
+ kzalloc(sizeof(struct vma_to_fileoffset_map), GFP_KERNEL);
+ if (!new) {
+ printk(KERN_ERR "SPU_PROF: %s, line %d: malloc failed\n",
+- __FUNCTION__, __LINE__);
++ __func__, __LINE__);
+ vma_map_free(map);
+ return NULL;
+ }
+@@ -134,19 +134,19 @@ struct vma_to_fileoffset_map *create_vma_map(const struct spu *aSpu,
+ if (memcmp(ehdr.e_ident, expected, EI_PAD) != 0) {
+ printk(KERN_ERR "SPU_PROF: "
+ "%s, line %d: Unexpected e_ident parsing SPU ELF\n",
+- __FUNCTION__, __LINE__);
++ __func__, __LINE__);
+ goto fail;
+ }
+ if (ehdr.e_machine != EM_SPU) {
+ printk(KERN_ERR "SPU_PROF: "
+ "%s, line %d: Unexpected e_machine parsing SPU ELF\n",
+- __FUNCTION__, __LINE__);
++ __func__, __LINE__);
+ goto fail;
+ }
+ if (ehdr.e_type != ET_EXEC) {
+ printk(KERN_ERR "SPU_PROF: "
+ "%s, line %d: Unexpected e_type parsing SPU ELF\n",
+- __FUNCTION__, __LINE__);
++ __func__, __LINE__);
+ goto fail;
+ }
+ phdr_start = spu_elf_start + ehdr.e_phoff;
+@@ -232,7 +232,7 @@ struct vma_to_fileoffset_map *create_vma_map(const struct spu *aSpu,
+ if (overlay_tbl_offset < 0) {
+ printk(KERN_ERR "SPU_PROF: "
+ "%s, line %d: Error finding SPU overlay table\n",
+- __FUNCTION__, __LINE__);
++ __func__, __LINE__);
+ goto fail;
+ }
+ ovly_table = spu_elf_start + overlay_tbl_offset;
+diff --git a/arch/powerpc/oprofile/op_model_cell.c b/arch/powerpc/oprofile/op_model_cell.c
+index 9eed1f6..5ff4de3 100644
+--- a/arch/powerpc/oprofile/op_model_cell.c
++++ b/arch/powerpc/oprofile/op_model_cell.c
+@@ -216,7 +216,7 @@ static void pm_rtas_reset_signals(u32 node)
+ * failure to stop OProfile.
+ */
+ printk(KERN_WARNING "%s: rtas returned: %d\n",
+- __FUNCTION__, ret);
++ __func__, ret);
+ }
+
+ static int pm_rtas_activate_signals(u32 node, u32 count)
+@@ -255,7 +255,7 @@ static int pm_rtas_activate_signals(u32 node, u32 count)
+
+ if (unlikely(ret)) {
+ printk(KERN_WARNING "%s: rtas returned: %d\n",
+- __FUNCTION__, ret);
++ __func__, ret);
+ return -EIO;
+ }
+ }
+@@ -560,7 +560,7 @@ static int cell_reg_setup(struct op_counter_config *ctr,
+ if (unlikely(spu_rtas_token == RTAS_UNKNOWN_SERVICE)) {
+ printk(KERN_ERR
+ "%s: rtas token ibm,cbe-spu-perftools unknown\n",
+- __FUNCTION__);
++ __func__);
+ return -EIO;
+ }
+ }
+@@ -576,7 +576,7 @@ static int cell_reg_setup(struct op_counter_config *ctr,
+ if (unlikely(pm_rtas_token == RTAS_UNKNOWN_SERVICE)) {
+ printk(KERN_ERR
+ "%s: rtas token ibm,cbe-perftools unknown\n",
+- __FUNCTION__);
++ __func__);
+ return -EIO;
+ }
+
+@@ -853,7 +853,7 @@ static int pm_rtas_activate_spu_profiling(u32 node)
+
+ if (unlikely(ret)) {
+ printk(KERN_WARNING "%s: rtas returned: %d\n",
+- __FUNCTION__, ret);
++ __func__, ret);
+ return -EIO;
+ }
+
+@@ -949,7 +949,7 @@ static int cell_global_start_spu(struct op_counter_config *ctr)
+ if (unlikely(ret != 0)) {
+ printk(KERN_ERR
+ "%s: rtas call ibm,cbe-spu-perftools failed, return = %d\n",
+- __FUNCTION__, ret);
++ __func__, ret);
+ rtas_error = -EIO;
+ goto out;
+ }
+@@ -1061,7 +1061,7 @@ static void cell_global_stop_spu(void)
+ if (unlikely(rtn_value != 0)) {
+ printk(KERN_ERR
+ "%s: rtas call ibm,cbe-spu-perftools failed, return = %d\n",
+- __FUNCTION__, rtn_value);
++ __func__, rtn_value);
+ }
+
+ /* Deactivate the signals */
+diff --git a/arch/powerpc/platforms/40x/ep405.c b/arch/powerpc/platforms/40x/ep405.c
+index 13d1345..ae2e7f6 100644
+--- a/arch/powerpc/platforms/40x/ep405.c
++++ b/arch/powerpc/platforms/40x/ep405.c
+@@ -29,6 +29,7 @@
+ #include <asm/time.h>
+ #include <asm/uic.h>
+ #include <asm/pci-bridge.h>
++#include <asm/ppc4xx.h>
+
+ static struct device_node *bcsr_node;
+ static void __iomem *bcsr_regs;
+@@ -119,5 +120,6 @@ define_machine(ep405) {
+ .progress = udbg_progress,
+ .init_IRQ = uic_init_tree,
+ .get_irq = uic_get_irq,
++ .restart = ppc4xx_reset_system,
+ .calibrate_decr = generic_calibrate_decr,
+ };
+diff --git a/arch/powerpc/platforms/40x/kilauea.c b/arch/powerpc/platforms/40x/kilauea.c
+index f9206a7..1dd24ff 100644
+--- a/arch/powerpc/platforms/40x/kilauea.c
++++ b/arch/powerpc/platforms/40x/kilauea.c
+@@ -1,7 +1,7 @@
+ /*
+ * Kilauea board specific routines
+ *
+- * Copyright 2007 DENX Software Engineering, Stefan Roese <sr at denx.de>
++ * Copyright 2007-2008 DENX Software Engineering, Stefan Roese <sr at denx.de>
+ *
+ * Based on the Walnut code by
+ * Josh Boyer <jwboyer at linux.vnet.ibm.com>
+@@ -20,6 +20,7 @@
+ #include <asm/time.h>
+ #include <asm/uic.h>
+ #include <asm/pci-bridge.h>
++#include <asm/ppc4xx.h>
+
+ static __initdata struct of_device_id kilauea_of_bus[] = {
+ { .compatible = "ibm,plb4", },
+@@ -54,5 +55,6 @@ define_machine(kilauea) {
+ .progress = udbg_progress,
+ .init_IRQ = uic_init_tree,
+ .get_irq = uic_get_irq,
++ .restart = ppc4xx_reset_system,
+ .calibrate_decr = generic_calibrate_decr,
+ };
+diff --git a/arch/powerpc/platforms/40x/makalu.c b/arch/powerpc/platforms/40x/makalu.c
+index 4e4df72..a6a1d60 100644
+--- a/arch/powerpc/platforms/40x/makalu.c
++++ b/arch/powerpc/platforms/40x/makalu.c
+@@ -20,6 +20,7 @@
+ #include <asm/time.h>
+ #include <asm/uic.h>
+ #include <asm/pci-bridge.h>
++#include <asm/ppc4xx.h>
+
+ static __initdata struct of_device_id makalu_of_bus[] = {
+ { .compatible = "ibm,plb4", },
+@@ -54,5 +55,6 @@ define_machine(makalu) {
+ .progress = udbg_progress,
+ .init_IRQ = uic_init_tree,
+ .get_irq = uic_get_irq,
++ .restart = ppc4xx_reset_system,
+ .calibrate_decr = generic_calibrate_decr,
+ };
+diff --git a/arch/powerpc/platforms/40x/virtex.c b/arch/powerpc/platforms/40x/virtex.c
+index 0422590..fc7fb00 100644
+--- a/arch/powerpc/platforms/40x/virtex.c
++++ b/arch/powerpc/platforms/40x/virtex.c
+@@ -14,6 +14,7 @@
+ #include <asm/prom.h>
+ #include <asm/time.h>
+ #include <asm/xilinx_intc.h>
++#include <asm/ppc4xx.h>
+
+ static struct of_device_id xilinx_of_bus_ids[] __initdata = {
+ { .compatible = "xlnx,plb-v46-1.00.a", },
+@@ -48,5 +49,6 @@ define_machine(virtex) {
+ .probe = virtex_probe,
+ .init_IRQ = xilinx_intc_init_tree,
+ .get_irq = xilinx_intc_get_irq,
++ .restart = ppc4xx_reset_system,
+ .calibrate_decr = generic_calibrate_decr,
+ };
+diff --git a/arch/powerpc/platforms/40x/walnut.c b/arch/powerpc/platforms/40x/walnut.c
+index b8b257e..335df91 100644
+--- a/arch/powerpc/platforms/40x/walnut.c
++++ b/arch/powerpc/platforms/40x/walnut.c
+@@ -26,6 +26,7 @@
+ #include <asm/time.h>
+ #include <asm/uic.h>
+ #include <asm/pci-bridge.h>
++#include <asm/ppc4xx.h>
+
+ static __initdata struct of_device_id walnut_of_bus[] = {
+ { .compatible = "ibm,plb3", },
+@@ -61,5 +62,6 @@ define_machine(walnut) {
+ .progress = udbg_progress,
+ .init_IRQ = uic_init_tree,
+ .get_irq = uic_get_irq,
+- .calibrate_decr = generic_calibrate_decr,
++ .restart = ppc4xx_reset_system,
++ .calibrate_decr = generic_calibrate_decr,
+ };
+diff --git a/arch/powerpc/platforms/44x/44x.h b/arch/powerpc/platforms/44x/44x.h
+index 42eabf8..dbc4d2b 100644
+--- a/arch/powerpc/platforms/44x/44x.h
++++ b/arch/powerpc/platforms/44x/44x.h
+@@ -3,6 +3,5 @@
+
+ extern u8 as1_readb(volatile u8 __iomem *addr);
+ extern void as1_writeb(u8 data, volatile u8 __iomem *addr);
+-extern void ppc44x_reset_system(char *cmd);
+
+ #endif /* __POWERPC_PLATFORMS_44X_44X_H */
+diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
+index 1bfb219..6abe913 100644
+--- a/arch/powerpc/platforms/44x/Kconfig
++++ b/arch/powerpc/platforms/44x/Kconfig
+@@ -67,6 +67,25 @@ config WARP
+ See http://www.pikatechnologies.com/ and follow the "PIKA for Computer
+ Telephony Developers" link for more information.
+
++config CANYONLANDS
++ bool "Canyonlands"
++ depends on 44x
++ default n
++ select 460EX
++ select PCI
++ select PPC4xx_PCI_EXPRESS
++ help
++ This option enables support for the AMCC PPC460EX evaluation board.
++
++config YOSEMITE
++ bool "Yosemite"
++ depends on 44x
++ default n
++ select 440EP
++ select PCI
++ help
++ This option enables support for the AMCC PPC440EP evaluation board.
++
+ #config LUAN
+ # bool "Luan"
+ # depends on 44x
+@@ -122,6 +141,14 @@ config 440SPe
+ bool
+ select IBM_NEW_EMAC_EMAC4
+
++config 460EX
++ bool
++ select PPC_FPU
++ select IBM_NEW_EMAC_EMAC4
++ select IBM_NEW_EMAC_RGMII
++ select IBM_NEW_EMAC_ZMII
++ select IBM_NEW_EMAC_TAH
++
+ # 44x errata/workaround config symbols, selected by the CPU models above
+ config IBM440EP_ERR42
+ bool
+diff --git a/arch/powerpc/platforms/44x/Makefile b/arch/powerpc/platforms/44x/Makefile
+index 0864d4f..774165f 100644
+--- a/arch/powerpc/platforms/44x/Makefile
++++ b/arch/powerpc/platforms/44x/Makefile
+@@ -1,9 +1,11 @@
+-obj-$(CONFIG_44x) := misc_44x.o
++obj-$(CONFIG_44x) := misc_44x.o idle.o
+ obj-$(CONFIG_EBONY) += ebony.o
+ obj-$(CONFIG_TAISHAN) += taishan.o
+ obj-$(CONFIG_BAMBOO) += bamboo.o
++obj-$(CONFIG_YOSEMITE) += bamboo.o
+ obj-$(CONFIG_SEQUOIA) += sequoia.o
+ obj-$(CONFIG_KATMAI) += katmai.o
+ obj-$(CONFIG_RAINIER) += rainier.o
+ obj-$(CONFIG_WARP) += warp.o
+ obj-$(CONFIG_WARP) += warp-nand.o
++obj-$(CONFIG_CANYONLANDS) += canyonlands.o
+diff --git a/arch/powerpc/platforms/44x/bamboo.c b/arch/powerpc/platforms/44x/bamboo.c
+index fb9a22a..cef169e 100644
+--- a/arch/powerpc/platforms/44x/bamboo.c
++++ b/arch/powerpc/platforms/44x/bamboo.c
+@@ -22,8 +22,7 @@
+ #include <asm/time.h>
+ #include <asm/uic.h>
+ #include <asm/pci-bridge.h>
+-
+-#include "44x.h"
++#include <asm/ppc4xx.h>
+
+ static __initdata struct of_device_id bamboo_of_bus[] = {
+ { .compatible = "ibm,plb4", },
+@@ -53,11 +52,11 @@ static int __init bamboo_probe(void)
+ }
+
+ define_machine(bamboo) {
+- .name = "Bamboo",
+- .probe = bamboo_probe,
+- .progress = udbg_progress,
+- .init_IRQ = uic_init_tree,
+- .get_irq = uic_get_irq,
+- .restart = ppc44x_reset_system,
++ .name = "Bamboo",
++ .probe = bamboo_probe,
++ .progress = udbg_progress,
++ .init_IRQ = uic_init_tree,
++ .get_irq = uic_get_irq,
++ .restart = ppc4xx_reset_system,
+ .calibrate_decr = generic_calibrate_decr,
+ };
+diff --git a/arch/powerpc/platforms/44x/canyonlands.c b/arch/powerpc/platforms/44x/canyonlands.c
+new file mode 100644
+index 0000000..3949289
+--- /dev/null
++++ b/arch/powerpc/platforms/44x/canyonlands.c
+@@ -0,0 +1,63 @@
++/*
++ * Canyonlands board specific routines
++ *
++ * Copyright 2008 DENX Software Engineering, Stefan Roese <sr at denx.de>
++ *
++ * Based on the Katmai code by
++ * Benjamin Herrenschmidt <benh at kernel.crashing.org>
++ * Copyright 2007 IBM Corp.
++ * Josh Boyer <jwboyer at linux.vnet.ibm.com>
++ * Copyright 2007 IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++#include <linux/init.h>
++#include <linux/of_platform.h>
++
++#include <asm/machdep.h>
++#include <asm/prom.h>
++#include <asm/udbg.h>
++#include <asm/time.h>
++#include <asm/uic.h>
++#include <asm/pci-bridge.h>
++#include <asm/ppc4xx.h>
++
++static __initdata struct of_device_id canyonlands_of_bus[] = {
++ { .compatible = "ibm,plb4", },
++ { .compatible = "ibm,opb", },
++ { .compatible = "ibm,ebc", },
++ {},
++};
++
++static int __init canyonlands_device_probe(void)
++{
++ of_platform_bus_probe(NULL, canyonlands_of_bus, NULL);
++
++ return 0;
++}
++machine_device_initcall(canyonlands, canyonlands_device_probe);
++
++static int __init canyonlands_probe(void)
++{
++ unsigned long root = of_get_flat_dt_root();
++
++ if (!of_flat_dt_is_compatible(root, "amcc,canyonlands"))
++ return 0;
++
++ ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
++
++ return 1;
++}
++
++define_machine(canyonlands) {
++ .name = "Canyonlands",
++ .probe = canyonlands_probe,
++ .progress = udbg_progress,
++ .init_IRQ = uic_init_tree,
++ .get_irq = uic_get_irq,
++ .restart = ppc4xx_reset_system,
++ .calibrate_decr = generic_calibrate_decr,
++};
+diff --git a/arch/powerpc/platforms/44x/ebony.c b/arch/powerpc/platforms/44x/ebony.c
+index 1a8d467..a0e8fe4 100644
+--- a/arch/powerpc/platforms/44x/ebony.c
++++ b/arch/powerpc/platforms/44x/ebony.c
+@@ -26,8 +26,7 @@
+ #include <asm/time.h>
+ #include <asm/uic.h>
+ #include <asm/pci-bridge.h>
+-
+-#include "44x.h"
++#include <asm/ppc4xx.h>
+
+ static __initdata struct of_device_id ebony_of_bus[] = {
+ { .compatible = "ibm,plb4", },
+@@ -66,6 +65,6 @@ define_machine(ebony) {
+ .progress = udbg_progress,
+ .init_IRQ = uic_init_tree,
+ .get_irq = uic_get_irq,
+- .restart = ppc44x_reset_system,
++ .restart = ppc4xx_reset_system,
+ .calibrate_decr = generic_calibrate_decr,
+ };
+diff --git a/arch/powerpc/platforms/44x/idle.c b/arch/powerpc/platforms/44x/idle.c
+new file mode 100644
+index 0000000..7a81f92
+--- /dev/null
++++ b/arch/powerpc/platforms/44x/idle.c
+@@ -0,0 +1,67 @@
++/*
++ * Copyright 2008 IBM Corp.
++ *
++ * Based on arch/powerpc/platforms/pasemi/idle.c:
++ * Copyright (C) 2006-2007 PA Semi, Inc
++ *
++ * Added by: Jerone Young <jyoung5 at us.ibm.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ */
++
++#include <linux/of.h>
++#include <linux/kernel.h>
++#include <asm/machdep.h>
++
++static int mode_spin;
++
++static void ppc44x_idle(void)
++{
++ unsigned long msr_save;
++
++ msr_save = mfmsr();
++ /* set wait state MSR */
++ mtmsr(msr_save|MSR_WE|MSR_EE|MSR_CE|MSR_DE);
++ isync();
++ /* return to initial state */
++ mtmsr(msr_save);
++ isync();
++}
++
++int __init ppc44x_idle_init(void)
++{
++ if (!mode_spin) {
++ /* If we are not setting spin mode
++ then we set to wait mode */
++ ppc_md.power_save = &ppc44x_idle;
++ }
++
++ return 0;
++}
++
++arch_initcall(ppc44x_idle_init);
++
++static int __init idle_param(char *p)
++{
++
++ if (!strcmp("spin", p)) {
++ mode_spin = 1;
++ ppc_md.power_save = NULL;
++ }
++
++ return 0;
++}
++
++early_param("idle", idle_param);
+diff --git a/arch/powerpc/platforms/44x/katmai.c b/arch/powerpc/platforms/44x/katmai.c
+index 1113412..44f4b3a 100644
+--- a/arch/powerpc/platforms/44x/katmai.c
++++ b/arch/powerpc/platforms/44x/katmai.c
+@@ -22,8 +22,7 @@
+ #include <asm/time.h>
+ #include <asm/uic.h>
+ #include <asm/pci-bridge.h>
+-
+-#include "44x.h"
++#include <asm/ppc4xx.h>
+
+ static __initdata struct of_device_id katmai_of_bus[] = {
+ { .compatible = "ibm,plb4", },
+@@ -58,6 +57,6 @@ define_machine(katmai) {
+ .progress = udbg_progress,
+ .init_IRQ = uic_init_tree,
+ .get_irq = uic_get_irq,
+- .restart = ppc44x_reset_system,
++ .restart = ppc4xx_reset_system,
+ .calibrate_decr = generic_calibrate_decr,
+ };
+diff --git a/arch/powerpc/platforms/44x/misc_44x.S b/arch/powerpc/platforms/44x/misc_44x.S
+index 3bce71d..dc12b80 100644
+--- a/arch/powerpc/platforms/44x/misc_44x.S
++++ b/arch/powerpc/platforms/44x/misc_44x.S
+@@ -44,14 +44,3 @@ _GLOBAL(as1_writeb)
+ sync
+ isync
+ blr
+-
+-/*
+- * void ppc44x_reset_system(char *cmd)
+- *
+- * At present, this routine just applies a system reset.
+- */
+-_GLOBAL(ppc44x_reset_system)
+- mfspr r13,SPRN_DBCR0
+- oris r13,r13,DBCR0_RST_SYSTEM at h
+- mtspr SPRN_DBCR0,r13
+- b . /* Just in case the reset doesn't work */
+diff --git a/arch/powerpc/platforms/44x/rainier.c b/arch/powerpc/platforms/44x/rainier.c
+index a7fae1c..4f1ff84 100644
+--- a/arch/powerpc/platforms/44x/rainier.c
++++ b/arch/powerpc/platforms/44x/rainier.c
+@@ -22,7 +22,7 @@
+ #include <asm/time.h>
+ #include <asm/uic.h>
+ #include <asm/pci-bridge.h>
+-#include "44x.h"
++#include <asm/ppc4xx.h>
+
+ static __initdata struct of_device_id rainier_of_bus[] = {
+ { .compatible = "ibm,plb4", },
+@@ -57,6 +57,6 @@ define_machine(rainier) {
+ .progress = udbg_progress,
+ .init_IRQ = uic_init_tree,
+ .get_irq = uic_get_irq,
+- .restart = ppc44x_reset_system,
++ .restart = ppc4xx_reset_system,
+ .calibrate_decr = generic_calibrate_decr,
+ };
+diff --git a/arch/powerpc/platforms/44x/sequoia.c b/arch/powerpc/platforms/44x/sequoia.c
+index d279db4..49eb73d 100644
+--- a/arch/powerpc/platforms/44x/sequoia.c
++++ b/arch/powerpc/platforms/44x/sequoia.c
+@@ -23,7 +23,7 @@
+ #include <asm/uic.h>
+ #include <asm/pci-bridge.h>
+
+-#include "44x.h"
++#include <asm/ppc4xx.h>
+
+ static __initdata struct of_device_id sequoia_of_bus[] = {
+ { .compatible = "ibm,plb4", },
+@@ -58,6 +58,6 @@ define_machine(sequoia) {
+ .progress = udbg_progress,
+ .init_IRQ = uic_init_tree,
+ .get_irq = uic_get_irq,
+- .restart = ppc44x_reset_system,
++ .restart = ppc4xx_reset_system,
+ .calibrate_decr = generic_calibrate_decr,
+ };
+diff --git a/arch/powerpc/platforms/44x/taishan.c b/arch/powerpc/platforms/44x/taishan.c
+index 28ab7e2..49c78b2 100644
+--- a/arch/powerpc/platforms/44x/taishan.c
++++ b/arch/powerpc/platforms/44x/taishan.c
+@@ -29,8 +29,7 @@
+ #include <asm/time.h>
+ #include <asm/uic.h>
+ #include <asm/pci-bridge.h>
+-
+-#include "44x.h"
++#include <asm/ppc4xx.h>
+
+ static __initdata struct of_device_id taishan_of_bus[] = {
+ { .compatible = "ibm,plb4", },
+@@ -68,6 +67,6 @@ define_machine(taishan) {
+ .progress = udbg_progress,
+ .init_IRQ = uic_init_tree,
+ .get_irq = uic_get_irq,
+- .restart = ppc44x_reset_system,
++ .restart = ppc4xx_reset_system,
+ .calibrate_decr = generic_calibrate_decr,
+ };
+diff --git a/arch/powerpc/platforms/44x/warp-nand.c b/arch/powerpc/platforms/44x/warp-nand.c
+index 84ab78f..9150318 100644
+--- a/arch/powerpc/platforms/44x/warp-nand.c
++++ b/arch/powerpc/platforms/44x/warp-nand.c
+@@ -11,6 +11,7 @@
+ #include <linux/mtd/partitions.h>
+ #include <linux/mtd/nand.h>
+ #include <linux/mtd/ndfc.h>
++#include <asm/machdep.h>
+
+ #ifdef CONFIG_MTD_NAND_NDFC
+
+@@ -100,6 +101,6 @@ static int warp_setup_nand_flash(void)
+
+ return 0;
+ }
+-device_initcall(warp_setup_nand_flash);
++machine_device_initcall(warp, warp_setup_nand_flash);
+
+ #endif
+diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c
+index da5b7b7..39cf615 100644
+--- a/arch/powerpc/platforms/44x/warp.c
++++ b/arch/powerpc/platforms/44x/warp.c
+@@ -18,9 +18,7 @@
+ #include <asm/udbg.h>
+ #include <asm/time.h>
+ #include <asm/uic.h>
+-
+-#include "44x.h"
+-
++#include <asm/ppc4xx.h>
+
+ static __initdata struct of_device_id warp_of_bus[] = {
+ { .compatible = "ibm,plb4", },
+@@ -49,7 +47,7 @@ define_machine(warp) {
+ .progress = udbg_progress,
+ .init_IRQ = uic_init_tree,
+ .get_irq = uic_get_irq,
+- .restart = ppc44x_reset_system,
++ .restart = ppc4xx_reset_system,
+ .calibrate_decr = generic_calibrate_decr,
+ };
+
+diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
+index 956f459..6d584f4 100644
+--- a/arch/powerpc/platforms/52xx/lite5200.c
++++ b/arch/powerpc/platforms/52xx/lite5200.c
+@@ -63,7 +63,7 @@ lite5200_fix_clock_config(void)
+ of_node_put(np);
+ if (!cdm) {
+ printk(KERN_ERR "%s() failed; expect abnormal behaviour\n",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+
+@@ -98,7 +98,7 @@ lite5200_fix_port_config(void)
+ of_node_put(np);
+ if (!gpio) {
+ printk(KERN_ERR "%s() failed. expect abnormal behavior\n",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+
+diff --git a/arch/powerpc/platforms/82xx/Kconfig b/arch/powerpc/platforms/82xx/Kconfig
+index 4fad6c7..917ac88 100644
+--- a/arch/powerpc/platforms/82xx/Kconfig
++++ b/arch/powerpc/platforms/82xx/Kconfig
+@@ -11,7 +11,6 @@ config MPC8272_ADS
+ select 8260
+ select FSL_SOC
+ select PQ2_ADS_PCI_PIC if PCI
+- select PPC_CPM_NEW_BINDING
+ help
+ This option enables support for the MPC8272 ADS board
+
+@@ -22,7 +21,6 @@ config PQ2FADS
+ select 8260
+ select FSL_SOC
+ select PQ2_ADS_PCI_PIC if PCI
+- select PPC_CPM_NEW_BINDING
+ help
+ This option enables support for the PQ2FADS board
+
+@@ -31,7 +29,6 @@ config EP8248E
+ select 8272
+ select 8260
+ select FSL_SOC
+- select PPC_CPM_NEW_BINDING
+ select MDIO_BITBANG
+ help
+ This enables support for the Embedded Planet EP8248E board.
+diff --git a/arch/powerpc/platforms/82xx/ep8248e.c b/arch/powerpc/platforms/82xx/ep8248e.c
+index ba93d8a..d5770fd 100644
+--- a/arch/powerpc/platforms/82xx/ep8248e.c
++++ b/arch/powerpc/platforms/82xx/ep8248e.c
+@@ -138,7 +138,7 @@ static int __devinit ep8248e_mdio_probe(struct of_device *ofdev,
+
+ bus->name = "ep8248e-mdio-bitbang";
+ bus->dev = &ofdev->dev;
+- bus->id = res.start;
++ snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start);
+
+ return mdiobus_register(bus);
+ }
+diff --git a/arch/powerpc/platforms/83xx/mpc837x_rdb.c b/arch/powerpc/platforms/83xx/mpc837x_rdb.c
+index 2293ae5..c00356b 100644
+--- a/arch/powerpc/platforms/83xx/mpc837x_rdb.c
++++ b/arch/powerpc/platforms/83xx/mpc837x_rdb.c
+@@ -46,6 +46,7 @@ static void __init mpc837x_rdb_setup_arch(void)
+ static struct of_device_id mpc837x_ids[] = {
+ { .type = "soc", },
+ { .compatible = "soc", },
++ { .compatible = "simple-bus", },
+ {},
+ };
+
+diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h
+index 68065e6..88a3b5c 100644
+--- a/arch/powerpc/platforms/83xx/mpc83xx.h
++++ b/arch/powerpc/platforms/83xx/mpc83xx.h
+@@ -16,6 +16,7 @@
+ #define MPC83XX_SCCR_USB_DRCM_10 0x00200000
+ #define MPC8315_SCCR_USB_MASK 0x00c00000
+ #define MPC8315_SCCR_USB_DRCM_11 0x00c00000
++#define MPC8315_SCCR_USB_DRCM_01 0x00400000
+ #define MPC837X_SCCR_USB_DRCM_11 0x00c00000
+
+ /* system i/o configuration register low */
+@@ -37,6 +38,7 @@
+ /* USB Control Register */
+ #define FSL_USB2_CONTROL_OFFS 0x500
+ #define CONTROL_UTMI_PHY_EN 0x00000200
++#define CONTROL_REFSEL_24MHZ 0x00000040
+ #define CONTROL_REFSEL_48MHZ 0x00000080
+ #define CONTROL_PHY_CLK_SEL_ULPI 0x00000400
+ #define CONTROL_OTG_PORT 0x00000020
+diff --git a/arch/powerpc/platforms/83xx/usb.c b/arch/powerpc/platforms/83xx/usb.c
+index 471fdd8..64bcf0a 100644
+--- a/arch/powerpc/platforms/83xx/usb.c
++++ b/arch/powerpc/platforms/83xx/usb.c
+@@ -129,7 +129,7 @@ int mpc831x_usb_cfg(void)
+ if (immr_node && of_device_is_compatible(immr_node, "fsl,mpc8315-immr"))
+ clrsetbits_be32(immap + MPC83XX_SCCR_OFFS,
+ MPC8315_SCCR_USB_MASK,
+- MPC8315_SCCR_USB_DRCM_11);
++ MPC8315_SCCR_USB_DRCM_01);
+ else
+ clrsetbits_be32(immap + MPC83XX_SCCR_OFFS,
+ MPC83XX_SCCR_USB_MASK,
+@@ -164,9 +164,15 @@ int mpc831x_usb_cfg(void)
+ /* Using on-chip PHY */
+ if (prop && (!strcmp(prop, "utmi_wide") ||
+ !strcmp(prop, "utmi"))) {
+- /* Set UTMI_PHY_EN, REFSEL to 48MHZ */
++ u32 refsel;
++
++ if (of_device_is_compatible(immr_node, "fsl,mpc8315-immr"))
++ refsel = CONTROL_REFSEL_24MHZ;
++ else
++ refsel = CONTROL_REFSEL_48MHZ;
++ /* Set UTMI_PHY_EN and REFSEL */
+ out_be32(usb_regs + FSL_USB2_CONTROL_OFFS,
+- CONTROL_UTMI_PHY_EN | CONTROL_REFSEL_48MHZ);
++ CONTROL_UTMI_PHY_EN | refsel);
+ /* Using external UPLI PHY */
+ } else if (prop && !strcmp(prop, "ulpi")) {
+ /* Set PHY_CLK_SEL to ULPI */
+diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
+index 7e76ddb..7ff29d5 100644
+--- a/arch/powerpc/platforms/85xx/Kconfig
++++ b/arch/powerpc/platforms/85xx/Kconfig
+@@ -19,7 +19,6 @@ config MPC8540_ADS
+ config MPC8560_ADS
+ bool "Freescale MPC8560 ADS"
+ select DEFAULT_UIMAGE
+- select PPC_CPM_NEW_BINDING
+ select CPM2
+ help
+ This option enables support for the MPC 8560 ADS board
+@@ -46,6 +45,12 @@ config MPC85xx_DS
+ help
+ This option enables support for the MPC85xx DS (MPC8544 DS) board
+
++config KSI8560
++ bool "Emerson KSI8560"
++ select DEFAULT_UIMAGE
++ help
++ This option enables support for the Emerson KSI8560 board
++
+ config STX_GP3
+ bool "Silicon Turnkey Express GP3"
+ help
+@@ -53,14 +58,12 @@ config STX_GP3
+ board.
+ select CPM2
+ select DEFAULT_UIMAGE
+- select PPC_CPM_NEW_BINDING
+
+ config TQM8540
+ bool "TQ Components TQM8540"
+ help
+ This option enables support for the TQ Components TQM8540 board.
+ select DEFAULT_UIMAGE
+- select PPC_CPM_NEW_BINDING
+ select TQM85xx
+
+ config TQM8541
+@@ -68,7 +71,6 @@ config TQM8541
+ help
+ This option enables support for the TQ Components TQM8541 board.
+ select DEFAULT_UIMAGE
+- select PPC_CPM_NEW_BINDING
+ select TQM85xx
+ select CPM2
+
+@@ -77,7 +79,6 @@ config TQM8555
+ help
+ This option enables support for the TQ Components TQM8555 board.
+ select DEFAULT_UIMAGE
+- select PPC_CPM_NEW_BINDING
+ select TQM85xx
+ select CPM2
+
+@@ -86,7 +87,6 @@ config TQM8560
+ help
+ This option enables support for the TQ Components TQM8560 board.
+ select DEFAULT_UIMAGE
+- select PPC_CPM_NEW_BINDING
+ select TQM85xx
+ select CPM2
+
+@@ -99,7 +99,6 @@ config SBC8548
+ config SBC8560
+ bool "Wind River SBC8560"
+ select DEFAULT_UIMAGE
+- select PPC_CPM_NEW_BINDING if CPM2
+ help
+ This option enables support for the Wind River SBC8560 board
+
+diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
+index cb7af4e..6cea185 100644
+--- a/arch/powerpc/platforms/85xx/Makefile
++++ b/arch/powerpc/platforms/85xx/Makefile
+@@ -10,3 +10,4 @@ obj-$(CONFIG_STX_GP3) += stx_gp3.o
+ obj-$(CONFIG_TQM85xx) += tqm85xx.o
+ obj-$(CONFIG_SBC8560) += sbc8560.o
+ obj-$(CONFIG_SBC8548) += sbc8548.o
++obj-$(CONFIG_KSI8560) += ksi8560.o
+diff --git a/arch/powerpc/platforms/85xx/ksi8560.c b/arch/powerpc/platforms/85xx/ksi8560.c
+new file mode 100644
+index 0000000..2145ade
+--- /dev/null
++++ b/arch/powerpc/platforms/85xx/ksi8560.c
+@@ -0,0 +1,257 @@
++/*
++ * Board setup routines for the Emerson KSI8560
++ *
++ * Author: Alexandr Smirnov <asmirnov at ru.mvista.com>
++ *
++ * Based on mpc85xx_ads.c maintained by Kumar Gala
++ *
++ * 2008 (c) MontaVista, Software, Inc. This file is licensed under
++ * the terms of the GNU General Public License version 2. This program
++ * is licensed "as is" without any warranty of any kind, whether express
++ * or implied.
++ *
++ */
++
++#include <linux/stddef.h>
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/kdev_t.h>
++#include <linux/delay.h>
++#include <linux/seq_file.h>
++#include <linux/of_platform.h>
++
++#include <asm/system.h>
++#include <asm/time.h>
++#include <asm/machdep.h>
++#include <asm/pci-bridge.h>
++#include <asm/mpic.h>
++#include <mm/mmu_decl.h>
++#include <asm/udbg.h>
++#include <asm/prom.h>
++
++#include <sysdev/fsl_soc.h>
++#include <sysdev/fsl_pci.h>
++
++#include <asm/cpm2.h>
++#include <sysdev/cpm2_pic.h>
++
++
++#define KSI8560_CPLD_HVR 0x04 /* Hardware Version Register */
++#define KSI8560_CPLD_PVR 0x08 /* PLD Version Register */
++#define KSI8560_CPLD_RCR1 0x30 /* Reset Command Register 1 */
++
++#define KSI8560_CPLD_RCR1_CPUHR 0x80 /* CPU Hard Reset */
++
++static void __iomem *cpld_base = NULL;
++
++static void machine_restart(char *cmd)
++{
++ if (cpld_base)
++ out_8(cpld_base + KSI8560_CPLD_RCR1, KSI8560_CPLD_RCR1_CPUHR);
++ else
++ printk(KERN_ERR "Can't find CPLD base, hang forever\n");
++
++ for (;;);
++}
++
++static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
++{
++ int cascade_irq;
++
++ while ((cascade_irq = cpm2_get_irq()) >= 0)
++ generic_handle_irq(cascade_irq);
++
++ desc->chip->eoi(irq);
++}
++
++static void __init ksi8560_pic_init(void)
++{
++ struct mpic *mpic;
++ struct resource r;
++ struct device_node *np;
++#ifdef CONFIG_CPM2
++ int irq;
++#endif
++
++ np = of_find_node_by_type(NULL, "open-pic");
++
++ if (np == NULL) {
++ printk(KERN_ERR "Could not find open-pic node\n");
++ return;
++ }
++
++ if (of_address_to_resource(np, 0, &r)) {
++ printk(KERN_ERR "Could not map mpic register space\n");
++ of_node_put(np);
++ return;
++ }
++
++ mpic = mpic_alloc(np, r.start,
++ MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
++ 0, 256, " OpenPIC ");
++ BUG_ON(mpic == NULL);
++ of_node_put(np);
++
++ mpic_init(mpic);
++
++#ifdef CONFIG_CPM2
++ /* Setup CPM2 PIC */
++ np = of_find_compatible_node(NULL, NULL, "fsl,cpm2-pic");
++ if (np == NULL) {
++ printk(KERN_ERR "PIC init: can not find fsl,cpm2-pic node\n");
++ return;
++ }
++ irq = irq_of_parse_and_map(np, 0);
++
++ cpm2_pic_init(np);
++ of_node_put(np);
++ set_irq_chained_handler(irq, cpm2_cascade);
++
++ setup_irq(0, NULL);
++#endif
++}
++
++#ifdef CONFIG_CPM2
++/*
++ * Setup I/O ports
++ */
++struct cpm_pin {
++ int port, pin, flags;
++};
++
++static struct cpm_pin __initdata ksi8560_pins[] = {
++ /* SCC1 */
++ {3, 29, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
++ {3, 30, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
++ {3, 31, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
++
++ /* SCC2 */
++ {3, 26, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
++ {3, 27, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
++ {3, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
++
++ /* FCC1 */
++ {0, 14, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
++ {0, 15, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
++ {0, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
++ {0, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
++ {0, 18, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
++ {0, 19, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
++ {0, 20, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
++ {0, 21, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
++ {0, 26, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
++ {0, 27, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
++ {0, 28, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
++ {0, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
++ {0, 30, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
++ {0, 31, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
++ {2, 23, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* CLK9 */
++ {2, 22, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* CLK10 */
++
++};
++
++static void __init init_ioports(void)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(ksi8560_pins); i++) {
++ struct cpm_pin *pin = &ksi8560_pins[i];
++ cpm2_set_pin(pin->port, pin->pin, pin->flags);
++ }
++
++ cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_RX);
++ cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_TX);
++ cpm2_clk_setup(CPM_CLK_SCC2, CPM_BRG2, CPM_CLK_RX);
++ cpm2_clk_setup(CPM_CLK_SCC2, CPM_BRG2, CPM_CLK_TX);
++ cpm2_clk_setup(CPM_CLK_FCC1, CPM_CLK9, CPM_CLK_RX);
++ cpm2_clk_setup(CPM_CLK_FCC1, CPM_CLK10, CPM_CLK_TX);
++}
++#endif
++
++/*
++ * Setup the architecture
++ */
++static void __init ksi8560_setup_arch(void)
++{
++ struct device_node *cpld;
++
++ cpld = of_find_compatible_node(NULL, NULL, "emerson,KSI8560-cpld");
++ if (cpld)
++ cpld_base = of_iomap(cpld, 0);
++ else
++ printk(KERN_ERR "Can't find CPLD in device tree\n");
++
++ if (ppc_md.progress)
++ ppc_md.progress("ksi8560_setup_arch()", 0);
++
++#ifdef CONFIG_CPM2
++ cpm2_reset();
++ init_ioports();
++#endif
++}
++
++static void ksi8560_show_cpuinfo(struct seq_file *m)
++{
++ uint pvid, svid, phid1;
++ uint memsize = total_memory;
++
++ pvid = mfspr(SPRN_PVR);
++ svid = mfspr(SPRN_SVR);
++
++ seq_printf(m, "Vendor\t\t: Emerson Network Power\n");
++ seq_printf(m, "Board\t\t: KSI8560\n");
++
++ if (cpld_base) {
++ seq_printf(m, "Hardware rev\t: %d\n",
++ in_8(cpld_base + KSI8560_CPLD_HVR));
++ seq_printf(m, "CPLD rev\t: %d\n",
++ in_8(cpld_base + KSI8560_CPLD_PVR));
++ } else
++ seq_printf(m, "Unknown Hardware and CPLD revs\n");
++
++ seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
++ seq_printf(m, "SVR\t\t: 0x%x\n", svid);
++
++ /* Display cpu Pll setting */
++ phid1 = mfspr(SPRN_HID1);
++ seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
++
++ /* Display the amount of memory */
++ seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
++}
++
++static struct of_device_id __initdata of_bus_ids[] = {
++ { .type = "soc", },
++ { .name = "cpm", },
++ { .name = "localbus", },
++ {},
++};
++
++static int __init declare_of_platform_devices(void)
++{
++ of_platform_bus_probe(NULL, of_bus_ids, NULL);
++
++ return 0;
++}
++machine_device_initcall(ksi8560, declare_of_platform_devices);
++
++/*
++ * Called very early, device-tree isn't unflattened
++ */
++static int __init ksi8560_probe(void)
++{
++ unsigned long root = of_get_flat_dt_root();
++
++ return of_flat_dt_is_compatible(root, "emerson,KSI8560");
++}
++
++define_machine(ksi8560) {
++ .name = "KSI8560",
++ .probe = ksi8560_probe,
++ .setup_arch = ksi8560_setup_arch,
++ .init_IRQ = ksi8560_pic_init,
++ .show_cpuinfo = ksi8560_show_cpuinfo,
++ .get_irq = mpic_get_irq,
++ .restart = machine_restart,
++ .calibrate_decr = generic_calibrate_decr,
++};
+diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+index 4e03050..3582c84 100644
+--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
++++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+@@ -165,7 +165,7 @@ static void __init init_ioports(void)
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mpc8560_ads_pins); i++) {
+- struct cpm_pin *pin = &mpc8560_ads_pins[i];
++ const struct cpm_pin *pin = &mpc8560_ads_pins[i];
+ cpm2_set_pin(pin->port, pin->pin, pin->flags);
+ }
+
+diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+index bdb3d0b..dfd8b4a 100644
+--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
++++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+@@ -19,6 +19,7 @@
+ #include <linux/delay.h>
+ #include <linux/seq_file.h>
+ #include <linux/interrupt.h>
++#include <linux/of_platform.h>
+
+ #include <asm/system.h>
+ #include <asm/time.h>
+@@ -36,7 +37,7 @@
+ #undef DEBUG
+
+ #ifdef DEBUG
+-#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
++#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args)
+ #else
+ #define DBG(fmt, args...)
+ #endif
+@@ -183,6 +184,18 @@ static int __init mpc8544_ds_probe(void)
+ }
+ }
+
++static struct of_device_id mpc85xxds_ids[] = {
++ { .type = "soc", },
++ { .compatible = "soc", },
++ {},
++};
++
++static int __init mpc85xxds_publish_devices(void)
++{
++ return of_platform_bus_probe(NULL, mpc85xxds_ids, NULL);
++}
++machine_device_initcall(mpc8544_ds, mpc85xxds_publish_devices);
++
+ /*
+ * Called very early, device-tree isn't unflattened
+ */
+diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig
+index 21d1135..7442c58 100644
+--- a/arch/powerpc/platforms/86xx/Kconfig
++++ b/arch/powerpc/platforms/86xx/Kconfig
+@@ -11,6 +11,12 @@ config MPC8641_HPCN
+ help
+ This option enables support for the MPC8641 HPCN board.
+
++config SBC8641D
++ bool "Wind River SBC8641D"
++ select DEFAULT_UIMAGE
++ help
++ This option enables support for the WRS SBC8641D board.
++
+ config MPC8610_HPCD
+ bool "Freescale MPC8610 HPCD"
+ select DEFAULT_UIMAGE
+@@ -24,7 +30,7 @@ config MPC8641
+ select FSL_PCI if PCI
+ select PPC_UDBG_16550
+ select MPIC
+- default y if MPC8641_HPCN
++ default y if MPC8641_HPCN || SBC8641D
+
+ config MPC8610
+ bool
+diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile
+index c967063..1b9b4a9 100644
+--- a/arch/powerpc/platforms/86xx/Makefile
++++ b/arch/powerpc/platforms/86xx/Makefile
+@@ -4,4 +4,5 @@
+
+ obj-$(CONFIG_SMP) += mpc86xx_smp.o
+ obj-$(CONFIG_MPC8641_HPCN) += mpc86xx_hpcn.o
++obj-$(CONFIG_SBC8641D) += sbc8641d.o
+ obj-$(CONFIG_MPC8610_HPCD) += mpc8610_hpcd.o
+diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+index 0b07485..18b8ebe 100644
+--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
++++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+@@ -52,7 +52,7 @@ static int __init mpc8610_declare_of_platform_devices(void)
+ }
+ machine_device_initcall(mpc86xx_hpcd, mpc8610_declare_of_platform_devices);
+
+-void __init
++static void __init
+ mpc86xx_hpcd_init_irq(void)
+ {
+ struct mpic *mpic1;
+@@ -200,7 +200,7 @@ static int __init mpc86xx_hpcd_probe(void)
+ return 0;
+ }
+
+-long __init
++static long __init
+ mpc86xx_time_init(void)
+ {
+ unsigned int temp;
+diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+index cfbe8c5..f947f55 100644
+--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
++++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+@@ -55,7 +55,7 @@ static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc)
+ }
+ #endif /* CONFIG_PCI */
+
+-void __init
++static void __init
+ mpc86xx_hpcn_init_irq(void)
+ {
+ struct mpic *mpic1;
+@@ -162,7 +162,7 @@ mpc86xx_hpcn_setup_arch(void)
+ }
+
+
+-void
++static void
+ mpc86xx_hpcn_show_cpuinfo(struct seq_file *m)
+ {
+ struct device_node *root;
+@@ -190,13 +190,19 @@ static int __init mpc86xx_hpcn_probe(void)
+ {
+ unsigned long root = of_get_flat_dt_root();
+
+- if (of_flat_dt_is_compatible(root, "mpc86xx"))
++ if (of_flat_dt_is_compatible(root, "fsl,mpc8641hpcn"))
+ return 1; /* Looks good */
+
++ /* Be nice and don't give silent boot death. Delete this in 2.6.27 */
++ if (of_flat_dt_is_compatible(root, "mpc86xx")) {
++ pr_warning("WARNING: your dts/dtb is old. You must update before the next kernel release\n");
++ return 1;
++ }
++
+ return 0;
+ }
+
+-long __init
++static long __init
+ mpc86xx_time_init(void)
+ {
+ unsigned int temp;
+diff --git a/arch/powerpc/platforms/86xx/sbc8641d.c b/arch/powerpc/platforms/86xx/sbc8641d.c
+new file mode 100644
+index 0000000..510a06e
+--- /dev/null
++++ b/arch/powerpc/platforms/86xx/sbc8641d.c
+@@ -0,0 +1,164 @@
++/*
++ * SBC8641D board specific routines
++ *
++ * Copyright 2008 Wind River Systems Inc.
++ *
++ * By Paul Gortmaker (see MAINTAINERS for contact information)
++ *
++ * Based largely on the 8641 HPCN support by Freescale Semiconductor Inc.
++ *
++ * 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/stddef.h>
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/kdev_t.h>
++#include <linux/delay.h>
++#include <linux/seq_file.h>
++#include <linux/of_platform.h>
++
++#include <asm/system.h>
++#include <asm/time.h>
++#include <asm/machdep.h>
++#include <asm/pci-bridge.h>
++#include <asm/mpc86xx.h>
++#include <asm/prom.h>
++#include <mm/mmu_decl.h>
++#include <asm/udbg.h>
++
++#include <asm/mpic.h>
++
++#include <sysdev/fsl_pci.h>
++#include <sysdev/fsl_soc.h>
++
++#include "mpc86xx.h"
++
++static void __init
++sbc8641_init_irq(void)
++{
++ struct mpic *mpic1;
++ struct device_node *np;
++ struct resource res;
++
++ /* Determine PIC address. */
++ np = of_find_node_by_type(NULL, "open-pic");
++ if (np == NULL)
++ return;
++ of_address_to_resource(np, 0, &res);
++
++ /* Alloc mpic structure and per isu has 16 INT entries. */
++ mpic1 = mpic_alloc(np, res.start,
++ MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
++ 0, 256, " MPIC ");
++ of_node_put(np);
++ BUG_ON(mpic1 == NULL);
++
++ mpic_init(mpic1);
++}
++
++static void __init
++sbc8641_setup_arch(void)
++{
++#ifdef CONFIG_PCI
++ struct device_node *np;
++#endif
++
++ if (ppc_md.progress)
++ ppc_md.progress("sbc8641_setup_arch()", 0);
++
++#ifdef CONFIG_PCI
++ for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie")
++ fsl_add_bridge(np, 0);
++#endif
++
++ printk("SBC8641 board from Wind River\n");
++
++#ifdef CONFIG_SMP
++ mpc86xx_smp_init();
++#endif
++}
++
++
++static void
++sbc8641_show_cpuinfo(struct seq_file *m)
++{
++ struct device_node *root;
++ uint memsize = total_memory;
++ const char *model = "";
++ uint svid = mfspr(SPRN_SVR);
++
++ seq_printf(m, "Vendor\t\t: Wind River Systems\n");
++
++ root = of_find_node_by_path("/");
++ if (root)
++ model = of_get_property(root, "model", NULL);
++ seq_printf(m, "Machine\t\t: %s\n", model);
++ of_node_put(root);
++
++ seq_printf(m, "SVR\t\t: 0x%x\n", svid);
++ seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
++}
++
++
++/*
++ * Called very early, device-tree isn't unflattened
++ */
++static int __init sbc8641_probe(void)
++{
++ unsigned long root = of_get_flat_dt_root();
++
++ if (of_flat_dt_is_compatible(root, "wind,sbc8641"))
++ return 1; /* Looks good */
++
++ return 0;
++}
++
++static long __init
++mpc86xx_time_init(void)
++{
++ unsigned int temp;
++
++ /* Set the time base to zero */
++ mtspr(SPRN_TBWL, 0);
++ mtspr(SPRN_TBWU, 0);
++
++ temp = mfspr(SPRN_HID0);
++ temp |= HID0_TBEN;
++ mtspr(SPRN_HID0, temp);
++ asm volatile("isync");
++
++ return 0;
++}
++
++static __initdata struct of_device_id of_bus_ids[] = {
++ { .compatible = "simple-bus", },
++ {},
++};
++
++static int __init declare_of_platform_devices(void)
++{
++ of_platform_bus_probe(NULL, of_bus_ids, NULL);
++
++ return 0;
++}
++machine_device_initcall(sbc8641, declare_of_platform_devices);
++
++define_machine(sbc8641) {
++ .name = "SBC8641D",
++ .probe = sbc8641_probe,
++ .setup_arch = sbc8641_setup_arch,
++ .init_IRQ = sbc8641_init_irq,
++ .show_cpuinfo = sbc8641_show_cpuinfo,
++ .get_irq = mpic_get_irq,
++ .restart = fsl_rstcr_restart,
++ .time_init = mpc86xx_time_init,
++ .calibrate_decr = generic_calibrate_decr,
++ .progress = udbg_progress,
++#ifdef CONFIG_PCI
++ .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
++#endif
++};
+diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig
+index 7fd224c..6fc849e 100644
+--- a/arch/powerpc/platforms/8xx/Kconfig
++++ b/arch/powerpc/platforms/8xx/Kconfig
+@@ -18,7 +18,6 @@ config MPC8XXFADS
+ config MPC86XADS
+ bool "MPC86XADS"
+ select CPM1
+- select PPC_CPM_NEW_BINDING
+ help
+ MPC86x Application Development System by Freescale Semiconductor.
+ The MPC86xADS is meant to serve as a platform for s/w and h/w
+@@ -27,7 +26,6 @@ config MPC86XADS
+ config MPC885ADS
+ bool "MPC885ADS"
+ select CPM1
+- select PPC_CPM_NEW_BINDING
+ help
+ Freescale Semiconductor MPC885 Application Development System (ADS).
+ Also known as DUET.
+@@ -37,7 +35,6 @@ config MPC885ADS
+ config PPC_EP88XC
+ bool "Embedded Planet EP88xC (a.k.a. CWH-PPC-885XN-VE)"
+ select CPM1
+- select PPC_CPM_NEW_BINDING
+ help
+ This enables support for the Embedded Planet EP88xC board.
+
+@@ -47,7 +44,6 @@ config PPC_EP88XC
+ config PPC_ADDER875
+ bool "Analogue & Micro Adder 875"
+ select CPM1
+- select PPC_CPM_NEW_BINDING
+ select REDBOOT
+ help
+ This enables support for the Analogue & Micro Adder 875
+diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c
+index 184f998..0d9f75c 100644
+--- a/arch/powerpc/platforms/8xx/m8xx_setup.c
++++ b/arch/powerpc/platforms/8xx/m8xx_setup.c
+@@ -111,17 +111,12 @@ void __init mpc8xx_calibrate_decr(void)
+
+ /* Processor frequency is MHz.
+ */
+- ppc_tb_freq = 50000000;
+- if (!get_freq("bus-frequency", &ppc_tb_freq)) {
+- printk(KERN_ERR "WARNING: Estimating decrementer frequency "
+- "(not found)\n");
+- }
+- ppc_tb_freq /= 16;
+ ppc_proc_freq = 50000000;
+ if (!get_freq("clock-frequency", &ppc_proc_freq))
+ printk(KERN_ERR "WARNING: Estimating processor frequency "
+ "(not found)\n");
+
++ ppc_tb_freq = ppc_proc_freq / 16;
+ printk("Decrementer Frequency = 0x%lx\n", ppc_tb_freq);
+
+ /* Perform some more timer/timebase initialization. This used
+diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
+index a578b96..87454c5 100644
+--- a/arch/powerpc/platforms/Kconfig
++++ b/arch/powerpc/platforms/Kconfig
+@@ -45,7 +45,6 @@ source "arch/powerpc/platforms/powermac/Kconfig"
+ source "arch/powerpc/platforms/prep/Kconfig"
+ source "arch/powerpc/platforms/maple/Kconfig"
+ source "arch/powerpc/platforms/pasemi/Kconfig"
+-source "arch/powerpc/platforms/celleb/Kconfig"
+ source "arch/powerpc/platforms/ps3/Kconfig"
+ source "arch/powerpc/platforms/cell/Kconfig"
+ source "arch/powerpc/platforms/8xx/Kconfig"
+@@ -290,13 +289,7 @@ config CPM2
+ config PPC_CPM_NEW_BINDING
+ bool
+ depends on CPM1 || CPM2
+- help
+- Select this if your board has been converted to use the new
+- device tree bindings for CPM, and no longer needs the
+- ioport callbacks or the platform device glue code.
+-
+- The fs_enet and cpm_uart drivers will be built as
+- of_platform devices.
++ default y
+
+ config AXON_RAM
+ tristate "Axon DDR2 memory device driver"
+diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
+index 0c3face..f7efaa9 100644
+--- a/arch/powerpc/platforms/Kconfig.cputype
++++ b/arch/powerpc/platforms/Kconfig.cputype
+@@ -41,11 +41,13 @@ config 40x
+ bool "AMCC 40x"
+ select PPC_DCR_NATIVE
+ select PPC_UDBG_16550
++ select 4xx_SOC
+
+ config 44x
+ bool "AMCC 44x"
+ select PPC_DCR_NATIVE
+ select PPC_UDBG_16550
++ select 4xx_SOC
+
+ config E200
+ bool "Freescale e200"
+@@ -218,8 +220,8 @@ config SMP
+ If you don't know what to do here, say N.
+
+ config NR_CPUS
+- int "Maximum number of CPUs (2-128)"
+- range 2 128
++ int "Maximum number of CPUs (2-1024)"
++ range 2 1024
+ depends on SMP
+ default "32" if PPC64
+ default "4"
+diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
+index a984894..423a023 100644
+--- a/arch/powerpc/platforms/Makefile
++++ b/arch/powerpc/platforms/Makefile
+@@ -24,5 +24,4 @@ obj-$(CONFIG_PPC_MAPLE) += maple/
+ obj-$(CONFIG_PPC_PASEMI) += pasemi/
+ obj-$(CONFIG_PPC_CELL) += cell/
+ obj-$(CONFIG_PPC_PS3) += ps3/
+-obj-$(CONFIG_PPC_CELLEB) += celleb/
+ obj-$(CONFIG_EMBEDDED6xx) += embedded6xx/
+diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
+index 2f16999..3959fcf 100644
+--- a/arch/powerpc/platforms/cell/Kconfig
++++ b/arch/powerpc/platforms/cell/Kconfig
+@@ -25,6 +25,19 @@ config PPC_IBM_CELL_BLADE
+ select PPC_UDBG_16550
+ select UDBG_RTAS_CONSOLE
+
++config PPC_CELLEB
++ bool "Toshiba's Cell Reference Set 'Celleb' Architecture"
++ depends on PPC_MULTIPLATFORM && PPC64
++ select PPC_CELL
++ select PPC_CELL_NATIVE
++ select PPC_RTAS
++ select PPC_INDIRECT_IO
++ select PPC_OF_PLATFORM_PCI
++ select HAS_TXX9_SERIAL
++ select PPC_UDBG_BEAT
++ select USB_OHCI_BIG_ENDIAN_MMIO
++ select USB_EHCI_BIG_ENDIAN_MMIO
++
+ menu "Cell Broadband Engine options"
+ depends on PPC_CELL
+
+diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
+index c89964c..c2a7e4e 100644
+--- a/arch/powerpc/platforms/cell/Makefile
++++ b/arch/powerpc/platforms/cell/Makefile
+@@ -1,6 +1,7 @@
+ obj-$(CONFIG_PPC_CELL_NATIVE) += interrupt.o iommu.o setup.o \
+ cbe_regs.o spider-pic.o \
+- pervasive.o pmu.o io-workarounds.o
++ pervasive.o pmu.o io-workarounds.o \
++ spider-pci.o
+ obj-$(CONFIG_CBE_RAS) += ras.o
+
+ obj-$(CONFIG_CBE_THERM) += cbe_thermal.o
+@@ -26,3 +27,20 @@ obj-$(CONFIG_SPU_BASE) += spu_callbacks.o spu_base.o \
+ spufs/
+
+ obj-$(CONFIG_PCI_MSI) += axon_msi.o
++
++
++# celleb stuff
++ifeq ($(CONFIG_PPC_CELLEB),y)
++obj-y += celleb_setup.o \
++ celleb_pci.o celleb_scc_epci.o \
++ celleb_scc_pciex.o \
++ celleb_scc_uhc.o \
++ io-workarounds.o spider-pci.o \
++ beat.o beat_htab.o beat_hvCall.o \
++ beat_interrupt.o beat_iommu.o
++
++obj-$(CONFIG_SMP) += beat_smp.o
++obj-$(CONFIG_PPC_UDBG_BEAT) += beat_udbg.o
++obj-$(CONFIG_SERIAL_TXX9) += celleb_scc_sio.o
++obj-$(CONFIG_SPU_BASE) += beat_spu_priv1.o
++endif
+diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
+index d95e71d..c39f5c2 100644
+--- a/arch/powerpc/platforms/cell/axon_msi.c
++++ b/arch/powerpc/platforms/cell/axon_msi.c
+@@ -123,7 +123,7 @@ static struct axon_msic *find_msi_translator(struct pci_dev *dev)
+ return NULL;
+ }
+
+- for (; dn; tmp = of_get_parent(dn), of_node_put(dn), dn = tmp) {
++ for (; dn; dn = of_get_next_parent(dn)) {
+ ph = of_get_property(dn, "msi-translator", NULL);
+ if (ph)
+ break;
+@@ -169,7 +169,7 @@ static int axon_msi_check_device(struct pci_dev *dev, int nvec, int type)
+
+ static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg)
+ {
+- struct device_node *dn, *tmp;
++ struct device_node *dn;
+ struct msi_desc *entry;
+ int len;
+ const u32 *prop;
+@@ -182,7 +182,7 @@ static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg)
+
+ entry = list_first_entry(&dev->msi_list, struct msi_desc, list);
+
+- for (; dn; tmp = of_get_parent(dn), of_node_put(dn), dn = tmp) {
++ for (; dn; dn = of_get_next_parent(dn)) {
+ if (entry->msi_attrib.is_64) {
+ prop = of_get_property(dn, "msi-address-64", &len);
+ if (prop)
+diff --git a/arch/powerpc/platforms/cell/beat.c b/arch/powerpc/platforms/cell/beat.c
+new file mode 100644
+index 0000000..48c690e
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/beat.c
+@@ -0,0 +1,264 @@
++/*
++ * Simple routines for Celleb/Beat
++ *
++ * (C) Copyright 2006-2007 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; 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.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/err.h>
++#include <linux/rtc.h>
++#include <linux/interrupt.h>
++#include <linux/irqreturn.h>
++#include <linux/reboot.h>
++
++#include <asm/hvconsole.h>
++#include <asm/time.h>
++#include <asm/machdep.h>
++#include <asm/firmware.h>
++
++#include "beat_wrapper.h"
++#include "beat.h"
++#include "beat_interrupt.h"
++
++static int beat_pm_poweroff_flag;
++
++void beat_restart(char *cmd)
++{
++ beat_shutdown_logical_partition(!beat_pm_poweroff_flag);
++}
++
++void beat_power_off(void)
++{
++ beat_shutdown_logical_partition(0);
++}
++
++u64 beat_halt_code = 0x1000000000000000UL;
++EXPORT_SYMBOL(beat_halt_code);
++
++void beat_halt(void)
++{
++ beat_shutdown_logical_partition(beat_halt_code);
++}
++
++int beat_set_rtc_time(struct rtc_time *rtc_time)
++{
++ u64 tim;
++ tim = mktime(rtc_time->tm_year+1900,
++ rtc_time->tm_mon+1, rtc_time->tm_mday,
++ rtc_time->tm_hour, rtc_time->tm_min, rtc_time->tm_sec);
++ if (beat_rtc_write(tim))
++ return -1;
++ return 0;
++}
++
++void beat_get_rtc_time(struct rtc_time *rtc_time)
++{
++ u64 tim;
++
++ if (beat_rtc_read(&tim))
++ tim = 0;
++ to_tm(tim, rtc_time);
++ rtc_time->tm_year -= 1900;
++ rtc_time->tm_mon -= 1;
++}
++
++#define BEAT_NVRAM_SIZE 4096
++
++ssize_t beat_nvram_read(char *buf, size_t count, loff_t *index)
++{
++ unsigned int i;
++ unsigned long len;
++ char *p = buf;
++
++ if (*index >= BEAT_NVRAM_SIZE)
++ return -ENODEV;
++ i = *index;
++ if (i + count > BEAT_NVRAM_SIZE)
++ count = BEAT_NVRAM_SIZE - i;
++
++ for (; count != 0; count -= len) {
++ len = count;
++ if (len > BEAT_NVRW_CNT)
++ len = BEAT_NVRW_CNT;
++ if (beat_eeprom_read(i, len, p))
++ return -EIO;
++
++ p += len;
++ i += len;
++ }
++ *index = i;
++ return p - buf;
++}
++
++ssize_t beat_nvram_write(char *buf, size_t count, loff_t *index)
++{
++ unsigned int i;
++ unsigned long len;
++ char *p = buf;
++
++ if (*index >= BEAT_NVRAM_SIZE)
++ return -ENODEV;
++ i = *index;
++ if (i + count > BEAT_NVRAM_SIZE)
++ count = BEAT_NVRAM_SIZE - i;
++
++ for (; count != 0; count -= len) {
++ len = count;
++ if (len > BEAT_NVRW_CNT)
++ len = BEAT_NVRW_CNT;
++ if (beat_eeprom_write(i, len, p))
++ return -EIO;
++
++ p += len;
++ i += len;
++ }
++ *index = i;
++ return p - buf;
++}
++
++ssize_t beat_nvram_get_size(void)
++{
++ return BEAT_NVRAM_SIZE;
++}
++
++int beat_set_xdabr(unsigned long dabr)
++{
++ if (beat_set_dabr(dabr, DABRX_KERNEL | DABRX_USER))
++ return -1;
++ return 0;
++}
++
++int64_t beat_get_term_char(u64 vterm, u64 *len, u64 *t1, u64 *t2)
++{
++ u64 db[2];
++ s64 ret;
++
++ ret = beat_get_characters_from_console(vterm, len, (u8 *)db);
++ if (ret == 0) {
++ *t1 = db[0];
++ *t2 = db[1];
++ }
++ return ret;
++}
++EXPORT_SYMBOL(beat_get_term_char);
++
++int64_t beat_put_term_char(u64 vterm, u64 len, u64 t1, u64 t2)
++{
++ u64 db[2];
++
++ db[0] = t1;
++ db[1] = t2;
++ return beat_put_characters_to_console(vterm, len, (u8 *)db);
++}
++EXPORT_SYMBOL(beat_put_term_char);
++
++void beat_power_save(void)
++{
++ beat_pause(0);
++}
++
++#ifdef CONFIG_KEXEC
++void beat_kexec_cpu_down(int crash, int secondary)
++{
++ beatic_deinit_IRQ();
++}
++#endif
++
++static irqreturn_t beat_power_event(int virq, void *arg)
++{
++ printk(KERN_DEBUG "Beat: power button pressed\n");
++ beat_pm_poweroff_flag = 1;
++ ctrl_alt_del();
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t beat_reset_event(int virq, void *arg)
++{
++ printk(KERN_DEBUG "Beat: reset button pressed\n");
++ beat_pm_poweroff_flag = 0;
++ ctrl_alt_del();
++ return IRQ_HANDLED;
++}
++
++static struct beat_event_list {
++ const char *typecode;
++ irq_handler_t handler;
++ unsigned int virq;
++} beat_event_list[] = {
++ { "power", beat_power_event, 0 },
++ { "reset", beat_reset_event, 0 },
++};
++
++static int __init beat_register_event(void)
++{
++ u64 path[4], data[2];
++ int rc, i;
++ unsigned int virq;
++
++ for (i = 0; i < ARRAY_SIZE(beat_event_list); i++) {
++ struct beat_event_list *ev = &beat_event_list[i];
++
++ if (beat_construct_event_receive_port(data) != 0) {
++ printk(KERN_ERR "Beat: "
++ "cannot construct event receive port for %s\n",
++ ev->typecode);
++ return -EINVAL;
++ }
++
++ virq = irq_create_mapping(NULL, data[0]);
++ if (virq == NO_IRQ) {
++ printk(KERN_ERR "Beat: failed to get virtual IRQ"
++ " for event receive port for %s\n",
++ ev->typecode);
++ beat_destruct_event_receive_port(data[0]);
++ return -EIO;
++ }
++ ev->virq = virq;
++
++ rc = request_irq(virq, ev->handler, IRQF_DISABLED,
++ ev->typecode, NULL);
++ if (rc != 0) {
++ printk(KERN_ERR "Beat: failed to request virtual IRQ"
++ " for event receive port for %s\n",
++ ev->typecode);
++ beat_destruct_event_receive_port(data[0]);
++ return rc;
++ }
++
++ path[0] = 0x1000000065780000ul; /* 1,ex */
++ path[1] = 0x627574746f6e0000ul; /* button */
++ path[2] = 0;
++ strncpy((char *)&path[2], ev->typecode, 8);
++ path[3] = 0;
++ data[1] = 0;
++
++ beat_create_repository_node(path, data);
++ }
++ return 0;
++}
++
++static int __init beat_event_init(void)
++{
++ if (!firmware_has_feature(FW_FEATURE_BEAT))
++ return -EINVAL;
++
++ beat_pm_poweroff_flag = 0;
++ return beat_register_event();
++}
++
++device_initcall(beat_event_init);
+diff --git a/arch/powerpc/platforms/cell/beat.h b/arch/powerpc/platforms/cell/beat.h
+new file mode 100644
+index 0000000..32c8efc
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/beat.h
+@@ -0,0 +1,39 @@
++/*
++ * Guest OS Interfaces.
++ *
++ * (C) Copyright 2006 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; 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.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#ifndef _CELLEB_BEAT_H
++#define _CELLEB_BEAT_H
++
++int64_t beat_get_term_char(uint64_t, uint64_t *, uint64_t *, uint64_t *);
++int64_t beat_put_term_char(uint64_t, uint64_t, uint64_t, uint64_t);
++int64_t beat_repository_encode(int, const char *, uint64_t[4]);
++void beat_restart(char *);
++void beat_power_off(void);
++void beat_halt(void);
++int beat_set_rtc_time(struct rtc_time *);
++void beat_get_rtc_time(struct rtc_time *);
++ssize_t beat_nvram_get_size(void);
++ssize_t beat_nvram_read(char *, size_t, loff_t *);
++ssize_t beat_nvram_write(char *, size_t, loff_t *);
++int beat_set_xdabr(unsigned long);
++void beat_power_save(void);
++void beat_kexec_cpu_down(int, int);
++
++#endif /* _CELLEB_BEAT_H */
+diff --git a/arch/powerpc/platforms/cell/beat_htab.c b/arch/powerpc/platforms/cell/beat_htab.c
+new file mode 100644
+index 0000000..81467ff
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/beat_htab.c
+@@ -0,0 +1,441 @@
++/*
++ * "Cell Reference Set" HTAB support.
++ *
++ * (C) Copyright 2006-2007 TOSHIBA CORPORATION
++ *
++ * This code is based on arch/powerpc/platforms/pseries/lpar.c:
++ * Copyright (C) 2001 Todd Inglett, IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; 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.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#undef DEBUG_LOW
++
++#include <linux/kernel.h>
++#include <linux/spinlock.h>
++
++#include <asm/mmu.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/machdep.h>
++#include <asm/udbg.h>
++
++#include "beat_wrapper.h"
++
++#ifdef DEBUG_LOW
++#define DBG_LOW(fmt...) do { udbg_printf(fmt); } while (0)
++#else
++#define DBG_LOW(fmt...) do { } while (0)
++#endif
++
++static DEFINE_SPINLOCK(beat_htab_lock);
++
++static inline unsigned int beat_read_mask(unsigned hpte_group)
++{
++ unsigned long hpte_v[5];
++ unsigned long rmask = 0;
++
++ beat_read_htab_entries(0, hpte_group + 0, hpte_v);
++ if (!(hpte_v[0] & HPTE_V_BOLTED))
++ rmask |= 0x8000;
++ if (!(hpte_v[1] & HPTE_V_BOLTED))
++ rmask |= 0x4000;
++ if (!(hpte_v[2] & HPTE_V_BOLTED))
++ rmask |= 0x2000;
++ if (!(hpte_v[3] & HPTE_V_BOLTED))
++ rmask |= 0x1000;
++ beat_read_htab_entries(0, hpte_group + 4, hpte_v);
++ if (!(hpte_v[0] & HPTE_V_BOLTED))
++ rmask |= 0x0800;
++ if (!(hpte_v[1] & HPTE_V_BOLTED))
++ rmask |= 0x0400;
++ if (!(hpte_v[2] & HPTE_V_BOLTED))
++ rmask |= 0x0200;
++ if (!(hpte_v[3] & HPTE_V_BOLTED))
++ rmask |= 0x0100;
++ hpte_group = ~hpte_group & (htab_hash_mask * HPTES_PER_GROUP);
++ beat_read_htab_entries(0, hpte_group + 0, hpte_v);
++ if (!(hpte_v[0] & HPTE_V_BOLTED))
++ rmask |= 0x80;
++ if (!(hpte_v[1] & HPTE_V_BOLTED))
++ rmask |= 0x40;
++ if (!(hpte_v[2] & HPTE_V_BOLTED))
++ rmask |= 0x20;
++ if (!(hpte_v[3] & HPTE_V_BOLTED))
++ rmask |= 0x10;
++ beat_read_htab_entries(0, hpte_group + 4, hpte_v);
++ if (!(hpte_v[0] & HPTE_V_BOLTED))
++ rmask |= 0x08;
++ if (!(hpte_v[1] & HPTE_V_BOLTED))
++ rmask |= 0x04;
++ if (!(hpte_v[2] & HPTE_V_BOLTED))
++ rmask |= 0x02;
++ if (!(hpte_v[3] & HPTE_V_BOLTED))
++ rmask |= 0x01;
++ return rmask;
++}
++
++static long beat_lpar_hpte_insert(unsigned long hpte_group,
++ unsigned long va, unsigned long pa,
++ unsigned long rflags, unsigned long vflags,
++ int psize, int ssize)
++{
++ unsigned long lpar_rc;
++ unsigned long slot;
++ unsigned long hpte_v, hpte_r;
++
++ /* same as iseries */
++ if (vflags & HPTE_V_SECONDARY)
++ return -1;
++
++ if (!(vflags & HPTE_V_BOLTED))
++ DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
++ "rflags=%lx, vflags=%lx, psize=%d)\n",
++ hpte_group, va, pa, rflags, vflags, psize);
++
++ hpte_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M) |
++ vflags | HPTE_V_VALID;
++ hpte_r = hpte_encode_r(pa, psize) | rflags;
++
++ if (!(vflags & HPTE_V_BOLTED))
++ DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
++
++ if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE))
++ hpte_r &= ~_PAGE_COHERENT;
++
++ spin_lock(&beat_htab_lock);
++ lpar_rc = beat_read_mask(hpte_group);
++ if (lpar_rc == 0) {
++ if (!(vflags & HPTE_V_BOLTED))
++ DBG_LOW(" full\n");
++ spin_unlock(&beat_htab_lock);
++ return -1;
++ }
++
++ lpar_rc = beat_insert_htab_entry(0, hpte_group, lpar_rc << 48,
++ hpte_v, hpte_r, &slot);
++ spin_unlock(&beat_htab_lock);
++
++ /*
++ * Since we try and ioremap PHBs we don't own, the pte insert
++ * will fail. However we must catch the failure in hash_page
++ * or we will loop forever, so return -2 in this case.
++ */
++ if (unlikely(lpar_rc != 0)) {
++ if (!(vflags & HPTE_V_BOLTED))
++ DBG_LOW(" lpar err %lx\n", lpar_rc);
++ return -2;
++ }
++ if (!(vflags & HPTE_V_BOLTED))
++ DBG_LOW(" -> slot: %lx\n", slot);
++
++ /* We have to pass down the secondary bucket bit here as well */
++ return (slot ^ hpte_group) & 15;
++}
++
++static long beat_lpar_hpte_remove(unsigned long hpte_group)
++{
++ DBG_LOW("hpte_remove(group=%lx)\n", hpte_group);
++ return -1;
++}
++
++static unsigned long beat_lpar_hpte_getword0(unsigned long slot)
++{
++ unsigned long dword0, dword[5];
++ unsigned long lpar_rc;
++
++ lpar_rc = beat_read_htab_entries(0, slot & ~3UL, dword);
++
++ dword0 = dword[slot&3];
++
++ BUG_ON(lpar_rc != 0);
++
++ return dword0;
++}
++
++static void beat_lpar_hptab_clear(void)
++{
++ unsigned long size_bytes = 1UL << ppc64_pft_size;
++ unsigned long hpte_count = size_bytes >> 4;
++ int i;
++ unsigned long dummy0, dummy1;
++
++ /* TODO: Use bulk call */
++ for (i = 0; i < hpte_count; i++)
++ beat_write_htab_entry(0, i, 0, 0, -1UL, -1UL, &dummy0, &dummy1);
++}
++
++/*
++ * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and
++ * the low 3 bits of flags happen to line up. So no transform is needed.
++ * We can probably optimize here and assume the high bits of newpp are
++ * already zero. For now I am paranoid.
++ */
++static long beat_lpar_hpte_updatepp(unsigned long slot,
++ unsigned long newpp,
++ unsigned long va,
++ int psize, int ssize, int local)
++{
++ unsigned long lpar_rc;
++ unsigned long dummy0, dummy1, want_v;
++
++ want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
++
++ DBG_LOW(" update: "
++ "avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ",
++ want_v & HPTE_V_AVPN, slot, psize, newpp);
++
++ spin_lock(&beat_htab_lock);
++ dummy0 = beat_lpar_hpte_getword0(slot);
++ if ((dummy0 & ~0x7FUL) != (want_v & ~0x7FUL)) {
++ DBG_LOW("not found !\n");
++ spin_unlock(&beat_htab_lock);
++ return -1;
++ }
++
++ lpar_rc = beat_write_htab_entry(0, slot, 0, newpp, 0, 7, &dummy0,
++ &dummy1);
++ spin_unlock(&beat_htab_lock);
++ if (lpar_rc != 0 || dummy0 == 0) {
++ DBG_LOW("not found !\n");
++ return -1;
++ }
++
++ DBG_LOW("ok %lx %lx\n", dummy0, dummy1);
++
++ BUG_ON(lpar_rc != 0);
++
++ return 0;
++}
++
++static long beat_lpar_hpte_find(unsigned long va, int psize)
++{
++ unsigned long hash;
++ unsigned long i, j;
++ long slot;
++ unsigned long want_v, hpte_v;
++
++ hash = hpt_hash(va, mmu_psize_defs[psize].shift, MMU_SEGSIZE_256M);
++ want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
++
++ for (j = 0; j < 2; j++) {
++ slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
++ for (i = 0; i < HPTES_PER_GROUP; i++) {
++ hpte_v = beat_lpar_hpte_getword0(slot);
++
++ if (HPTE_V_COMPARE(hpte_v, want_v)
++ && (hpte_v & HPTE_V_VALID)
++ && (!!(hpte_v & HPTE_V_SECONDARY) == j)) {
++ /* HPTE matches */
++ if (j)
++ slot = -slot;
++ return slot;
++ }
++ ++slot;
++ }
++ hash = ~hash;
++ }
++
++ return -1;
++}
++
++static void beat_lpar_hpte_updateboltedpp(unsigned long newpp,
++ unsigned long ea,
++ int psize, int ssize)
++{
++ unsigned long lpar_rc, slot, vsid, va, dummy0, dummy1;
++
++ vsid = get_kernel_vsid(ea, MMU_SEGSIZE_256M);
++ va = (vsid << 28) | (ea & 0x0fffffff);
++
++ spin_lock(&beat_htab_lock);
++ slot = beat_lpar_hpte_find(va, psize);
++ BUG_ON(slot == -1);
++
++ lpar_rc = beat_write_htab_entry(0, slot, 0, newpp, 0, 7,
++ &dummy0, &dummy1);
++ spin_unlock(&beat_htab_lock);
++
++ BUG_ON(lpar_rc != 0);
++}
++
++static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
++ int psize, int ssize, int local)
++{
++ unsigned long want_v;
++ unsigned long lpar_rc;
++ unsigned long dummy1, dummy2;
++ unsigned long flags;
++
++ DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
++ slot, va, psize, local);
++ want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
++
++ spin_lock_irqsave(&beat_htab_lock, flags);
++ dummy1 = beat_lpar_hpte_getword0(slot);
++
++ if ((dummy1 & ~0x7FUL) != (want_v & ~0x7FUL)) {
++ DBG_LOW("not found !\n");
++ spin_unlock_irqrestore(&beat_htab_lock, flags);
++ return;
++ }
++
++ lpar_rc = beat_write_htab_entry(0, slot, 0, 0, HPTE_V_VALID, 0,
++ &dummy1, &dummy2);
++ spin_unlock_irqrestore(&beat_htab_lock, flags);
++
++ BUG_ON(lpar_rc != 0);
++}
++
++void __init hpte_init_beat(void)
++{
++ ppc_md.hpte_invalidate = beat_lpar_hpte_invalidate;
++ ppc_md.hpte_updatepp = beat_lpar_hpte_updatepp;
++ ppc_md.hpte_updateboltedpp = beat_lpar_hpte_updateboltedpp;
++ ppc_md.hpte_insert = beat_lpar_hpte_insert;
++ ppc_md.hpte_remove = beat_lpar_hpte_remove;
++ ppc_md.hpte_clear_all = beat_lpar_hptab_clear;
++}
++
++static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
++ unsigned long va, unsigned long pa,
++ unsigned long rflags, unsigned long vflags,
++ int psize, int ssize)
++{
++ unsigned long lpar_rc;
++ unsigned long slot;
++ unsigned long hpte_v, hpte_r;
++
++ /* same as iseries */
++ if (vflags & HPTE_V_SECONDARY)
++ return -1;
++
++ if (!(vflags & HPTE_V_BOLTED))
++ DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
++ "rflags=%lx, vflags=%lx, psize=%d)\n",
++ hpte_group, va, pa, rflags, vflags, psize);
++
++ hpte_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M) |
++ vflags | HPTE_V_VALID;
++ hpte_r = hpte_encode_r(pa, psize) | rflags;
++
++ if (!(vflags & HPTE_V_BOLTED))
++ DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
++
++ if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE))
++ hpte_r &= ~_PAGE_COHERENT;
++
++ /* insert into not-volted entry */
++ lpar_rc = beat_insert_htab_entry3(0, hpte_group, hpte_v, hpte_r,
++ HPTE_V_BOLTED, 0, &slot);
++ /*
++ * Since we try and ioremap PHBs we don't own, the pte insert
++ * will fail. However we must catch the failure in hash_page
++ * or we will loop forever, so return -2 in this case.
++ */
++ if (unlikely(lpar_rc != 0)) {
++ if (!(vflags & HPTE_V_BOLTED))
++ DBG_LOW(" lpar err %lx\n", lpar_rc);
++ return -2;
++ }
++ if (!(vflags & HPTE_V_BOLTED))
++ DBG_LOW(" -> slot: %lx\n", slot);
++
++ /* We have to pass down the secondary bucket bit here as well */
++ return (slot ^ hpte_group) & 15;
++}
++
++/*
++ * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and
++ * the low 3 bits of flags happen to line up. So no transform is needed.
++ * We can probably optimize here and assume the high bits of newpp are
++ * already zero. For now I am paranoid.
++ */
++static long beat_lpar_hpte_updatepp_v3(unsigned long slot,
++ unsigned long newpp,
++ unsigned long va,
++ int psize, int ssize, int local)
++{
++ unsigned long lpar_rc;
++ unsigned long want_v;
++ unsigned long pss;
++
++ want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
++ pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc;
++
++ DBG_LOW(" update: "
++ "avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ",
++ want_v & HPTE_V_AVPN, slot, psize, newpp);
++
++ lpar_rc = beat_update_htab_permission3(0, slot, want_v, pss, 7, newpp);
++
++ if (lpar_rc == 0xfffffff7) {
++ DBG_LOW("not found !\n");
++ return -1;
++ }
++
++ DBG_LOW("ok\n");
++
++ BUG_ON(lpar_rc != 0);
++
++ return 0;
++}
++
++static void beat_lpar_hpte_invalidate_v3(unsigned long slot, unsigned long va,
++ int psize, int ssize, int local)
++{
++ unsigned long want_v;
++ unsigned long lpar_rc;
++ unsigned long pss;
++
++ DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
++ slot, va, psize, local);
++ want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
++ pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc;
++
++ lpar_rc = beat_invalidate_htab_entry3(0, slot, want_v, pss);
++
++ /* E_busy can be valid output: page may be already replaced */
++ BUG_ON(lpar_rc != 0 && lpar_rc != 0xfffffff7);
++}
++
++static int64_t _beat_lpar_hptab_clear_v3(void)
++{
++ return beat_clear_htab3(0);
++}
++
++static void beat_lpar_hptab_clear_v3(void)
++{
++ _beat_lpar_hptab_clear_v3();
++}
++
++void __init hpte_init_beat_v3(void)
++{
++ if (_beat_lpar_hptab_clear_v3() == 0) {
++ ppc_md.hpte_invalidate = beat_lpar_hpte_invalidate_v3;
++ ppc_md.hpte_updatepp = beat_lpar_hpte_updatepp_v3;
++ ppc_md.hpte_updateboltedpp = beat_lpar_hpte_updateboltedpp;
++ ppc_md.hpte_insert = beat_lpar_hpte_insert_v3;
++ ppc_md.hpte_remove = beat_lpar_hpte_remove;
++ ppc_md.hpte_clear_all = beat_lpar_hptab_clear_v3;
++ } else {
++ ppc_md.hpte_invalidate = beat_lpar_hpte_invalidate;
++ ppc_md.hpte_updatepp = beat_lpar_hpte_updatepp;
++ ppc_md.hpte_updateboltedpp = beat_lpar_hpte_updateboltedpp;
++ ppc_md.hpte_insert = beat_lpar_hpte_insert;
++ ppc_md.hpte_remove = beat_lpar_hpte_remove;
++ ppc_md.hpte_clear_all = beat_lpar_hptab_clear;
++ }
++}
+diff --git a/arch/powerpc/platforms/cell/beat_hvCall.S b/arch/powerpc/platforms/cell/beat_hvCall.S
+new file mode 100644
+index 0000000..74c8174
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/beat_hvCall.S
+@@ -0,0 +1,287 @@
++/*
++ * Beat hypervisor call I/F
++ *
++ * (C) Copyright 2007 TOSHIBA CORPORATION
++ *
++ * This code is based on arch/powerpc/platforms/pseries/hvCall.S.
++ *
++ * 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.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#include <asm/ppc_asm.h>
++
++#define STK_PARM(i) (48 + ((i)-3)*8)
++
++/* Not implemented on Beat, now */
++#define HCALL_INST_PRECALL
++#define HCALL_INST_POSTCALL
++
++ .text
++
++#define HVSC .long 0x44000022
++
++/* Note: takes only 7 input parameters at maximum */
++_GLOBAL(beat_hcall_norets)
++ HMT_MEDIUM
++
++ mfcr r0
++ stw r0,8(r1)
++
++ HCALL_INST_PRECALL
++
++ mr r11,r3
++ mr r3,r4
++ mr r4,r5
++ mr r5,r6
++ mr r6,r7
++ mr r7,r8
++ mr r8,r9
++
++ HVSC /* invoke the hypervisor */
++
++ HCALL_INST_POSTCALL
++
++ lwz r0,8(r1)
++ mtcrf 0xff,r0
++
++ blr /* return r3 = status */
++
++/* Note: takes 8 input parameters at maximum */
++_GLOBAL(beat_hcall_norets8)
++ HMT_MEDIUM
++
++ mfcr r0
++ stw r0,8(r1)
++
++ HCALL_INST_PRECALL
++
++ mr r11,r3
++ mr r3,r4
++ mr r4,r5
++ mr r5,r6
++ mr r6,r7
++ mr r7,r8
++ mr r8,r9
++ ld r10,STK_PARM(r10)(r1)
++
++ HVSC /* invoke the hypervisor */
++
++ HCALL_INST_POSTCALL
++
++ lwz r0,8(r1)
++ mtcrf 0xff,r0
++
++ blr /* return r3 = status */
++
++/* Note: takes only 6 input parameters, 1 output parameters at maximum */
++_GLOBAL(beat_hcall1)
++ HMT_MEDIUM
++
++ mfcr r0
++ stw r0,8(r1)
++
++ HCALL_INST_PRECALL
++
++ std r4,STK_PARM(r4)(r1) /* save ret buffer */
++
++ mr r11,r3
++ mr r3,r5
++ mr r4,r6
++ mr r5,r7
++ mr r6,r8
++ mr r7,r9
++ mr r8,r10
++
++ HVSC /* invoke the hypervisor */
++
++ HCALL_INST_POSTCALL
++
++ ld r12,STK_PARM(r4)(r1)
++ std r4, 0(r12)
++
++ lwz r0,8(r1)
++ mtcrf 0xff,r0
++
++ blr /* return r3 = status */
++
++/* Note: takes only 6 input parameters, 2 output parameters at maximum */
++_GLOBAL(beat_hcall2)
++ HMT_MEDIUM
++
++ mfcr r0
++ stw r0,8(r1)
++
++ HCALL_INST_PRECALL
++
++ std r4,STK_PARM(r4)(r1) /* save ret buffer */
++
++ mr r11,r3
++ mr r3,r5
++ mr r4,r6
++ mr r5,r7
++ mr r6,r8
++ mr r7,r9
++ mr r8,r10
++
++ HVSC /* invoke the hypervisor */
++
++ HCALL_INST_POSTCALL
++
++ ld r12,STK_PARM(r4)(r1)
++ std r4, 0(r12)
++ std r5, 8(r12)
++
++ lwz r0,8(r1)
++ mtcrf 0xff,r0
++
++ blr /* return r3 = status */
++
++/* Note: takes only 6 input parameters, 3 output parameters at maximum */
++_GLOBAL(beat_hcall3)
++ HMT_MEDIUM
++
++ mfcr r0
++ stw r0,8(r1)
++
++ HCALL_INST_PRECALL
++
++ std r4,STK_PARM(r4)(r1) /* save ret buffer */
++
++ mr r11,r3
++ mr r3,r5
++ mr r4,r6
++ mr r5,r7
++ mr r6,r8
++ mr r7,r9
++ mr r8,r10
++
++ HVSC /* invoke the hypervisor */
++
++ HCALL_INST_POSTCALL
++
++ ld r12,STK_PARM(r4)(r1)
++ std r4, 0(r12)
++ std r5, 8(r12)
++ std r6, 16(r12)
++
++ lwz r0,8(r1)
++ mtcrf 0xff,r0
++
++ blr /* return r3 = status */
++
++/* Note: takes only 6 input parameters, 4 output parameters at maximum */
++_GLOBAL(beat_hcall4)
++ HMT_MEDIUM
++
++ mfcr r0
++ stw r0,8(r1)
++
++ HCALL_INST_PRECALL
++
++ std r4,STK_PARM(r4)(r1) /* save ret buffer */
++
++ mr r11,r3
++ mr r3,r5
++ mr r4,r6
++ mr r5,r7
++ mr r6,r8
++ mr r7,r9
++ mr r8,r10
++
++ HVSC /* invoke the hypervisor */
++
++ HCALL_INST_POSTCALL
++
++ ld r12,STK_PARM(r4)(r1)
++ std r4, 0(r12)
++ std r5, 8(r12)
++ std r6, 16(r12)
++ std r7, 24(r12)
++
++ lwz r0,8(r1)
++ mtcrf 0xff,r0
++
++ blr /* return r3 = status */
++
++/* Note: takes only 6 input parameters, 5 output parameters at maximum */
++_GLOBAL(beat_hcall5)
++ HMT_MEDIUM
++
++ mfcr r0
++ stw r0,8(r1)
++
++ HCALL_INST_PRECALL
++
++ std r4,STK_PARM(r4)(r1) /* save ret buffer */
++
++ mr r11,r3
++ mr r3,r5
++ mr r4,r6
++ mr r5,r7
++ mr r6,r8
++ mr r7,r9
++ mr r8,r10
++
++ HVSC /* invoke the hypervisor */
++
++ HCALL_INST_POSTCALL
++
++ ld r12,STK_PARM(r4)(r1)
++ std r4, 0(r12)
++ std r5, 8(r12)
++ std r6, 16(r12)
++ std r7, 24(r12)
++ std r8, 32(r12)
++
++ lwz r0,8(r1)
++ mtcrf 0xff,r0
++
++ blr /* return r3 = status */
++
++/* Note: takes only 6 input parameters, 6 output parameters at maximum */
++_GLOBAL(beat_hcall6)
++ HMT_MEDIUM
++
++ mfcr r0
++ stw r0,8(r1)
++
++ HCALL_INST_PRECALL
++
++ std r4,STK_PARM(r4)(r1) /* save ret buffer */
++
++ mr r11,r3
++ mr r3,r5
++ mr r4,r6
++ mr r5,r7
++ mr r6,r8
++ mr r7,r9
++ mr r8,r10
++
++ HVSC /* invoke the hypervisor */
++
++ HCALL_INST_POSTCALL
++
++ ld r12,STK_PARM(r4)(r1)
++ std r4, 0(r12)
++ std r5, 8(r12)
++ std r6, 16(r12)
++ std r7, 24(r12)
++ std r8, 32(r12)
++ std r9, 40(r12)
++
++ lwz r0,8(r1)
++ mtcrf 0xff,r0
++
++ blr /* return r3 = status */
+diff --git a/arch/powerpc/platforms/cell/beat_interrupt.c b/arch/powerpc/platforms/cell/beat_interrupt.c
+new file mode 100644
+index 0000000..192a935
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/beat_interrupt.c
+@@ -0,0 +1,283 @@
++/*
++ * Celleb/Beat Interrupt controller
++ *
++ * (C) Copyright 2006-2007 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; 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.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <linux/percpu.h>
++#include <linux/types.h>
++
++#include <asm/machdep.h>
++
++#include "beat_interrupt.h"
++#include "beat_wrapper.h"
++
++#define MAX_IRQS NR_IRQS
++static DEFINE_SPINLOCK(beatic_irq_mask_lock);
++static uint64_t beatic_irq_mask_enable[(MAX_IRQS+255)/64];
++static uint64_t beatic_irq_mask_ack[(MAX_IRQS+255)/64];
++
++static struct irq_host *beatic_host;
++
++/*
++ * In this implementation, "virq" == "IRQ plug number",
++ * "(irq_hw_number_t)hwirq" == "IRQ outlet number".
++ */
++
++/* assumption: locked */
++static inline void beatic_update_irq_mask(unsigned int irq_plug)
++{
++ int off;
++ unsigned long masks[4];
++
++ off = (irq_plug / 256) * 4;
++ masks[0] = beatic_irq_mask_enable[off + 0]
++ & beatic_irq_mask_ack[off + 0];
++ masks[1] = beatic_irq_mask_enable[off + 1]
++ & beatic_irq_mask_ack[off + 1];
++ masks[2] = beatic_irq_mask_enable[off + 2]
++ & beatic_irq_mask_ack[off + 2];
++ masks[3] = beatic_irq_mask_enable[off + 3]
++ & beatic_irq_mask_ack[off + 3];
++ if (beat_set_interrupt_mask(irq_plug&~255UL,
++ masks[0], masks[1], masks[2], masks[3]) != 0)
++ panic("Failed to set mask IRQ!");
++}
++
++static void beatic_mask_irq(unsigned int irq_plug)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&beatic_irq_mask_lock, flags);
++ beatic_irq_mask_enable[irq_plug/64] &= ~(1UL << (63 - (irq_plug%64)));
++ beatic_update_irq_mask(irq_plug);
++ spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
++}
++
++static void beatic_unmask_irq(unsigned int irq_plug)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&beatic_irq_mask_lock, flags);
++ beatic_irq_mask_enable[irq_plug/64] |= 1UL << (63 - (irq_plug%64));
++ beatic_update_irq_mask(irq_plug);
++ spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
++}
++
++static void beatic_ack_irq(unsigned int irq_plug)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&beatic_irq_mask_lock, flags);
++ beatic_irq_mask_ack[irq_plug/64] &= ~(1UL << (63 - (irq_plug%64)));
++ beatic_update_irq_mask(irq_plug);
++ spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
++}
++
++static void beatic_end_irq(unsigned int irq_plug)
++{
++ s64 err;
++ unsigned long flags;
++
++ err = beat_downcount_of_interrupt(irq_plug);
++ if (err != 0) {
++ if ((err & 0xFFFFFFFF) != 0xFFFFFFF5) /* -11: wrong state */
++ panic("Failed to downcount IRQ! Error = %16lx", err);
++
++ printk(KERN_ERR "IRQ over-downcounted, plug %d\n", irq_plug);
++ }
++ spin_lock_irqsave(&beatic_irq_mask_lock, flags);
++ beatic_irq_mask_ack[irq_plug/64] |= 1UL << (63 - (irq_plug%64));
++ beatic_update_irq_mask(irq_plug);
++ spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
++}
++
++static struct irq_chip beatic_pic = {
++ .typename = " CELL-BEAT ",
++ .unmask = beatic_unmask_irq,
++ .mask = beatic_mask_irq,
++ .eoi = beatic_end_irq,
++};
++
++/*
++ * Dispose binding hardware IRQ number (hw) and Virtuql IRQ number (virq),
++ * update flags.
++ *
++ * Note that the number (virq) is already assigned at upper layer.
++ */
++static void beatic_pic_host_unmap(struct irq_host *h, unsigned int virq)
++{
++ beat_destruct_irq_plug(virq);
++}
++
++/*
++ * Create or update binding hardware IRQ number (hw) and Virtuql
++ * IRQ number (virq). This is called only once for a given mapping.
++ *
++ * Note that the number (virq) is already assigned at upper layer.
++ */
++static int beatic_pic_host_map(struct irq_host *h, unsigned int virq,
++ irq_hw_number_t hw)
++{
++ struct irq_desc *desc = get_irq_desc(virq);
++ int64_t err;
++
++ err = beat_construct_and_connect_irq_plug(virq, hw);
++ if (err < 0)
++ return -EIO;
++
++ desc->status |= IRQ_LEVEL;
++ set_irq_chip_and_handler(virq, &beatic_pic, handle_fasteoi_irq);
++ return 0;
++}
++
++/*
++ * Update binding hardware IRQ number (hw) and Virtuql
++ * IRQ number (virq). This is called only once for a given mapping.
++ */
++static void beatic_pic_host_remap(struct irq_host *h, unsigned int virq,
++ irq_hw_number_t hw)
++{
++ beat_construct_and_connect_irq_plug(virq, hw);
++}
++
++/*
++ * Translate device-tree interrupt spec to irq_hw_number_t style (ulong),
++ * to pass away to irq_create_mapping().
++ *
++ * Called from irq_create_of_mapping() only.
++ * Note: We have only 1 entry to translate.
++ */
++static int beatic_pic_host_xlate(struct irq_host *h, struct device_node *ct,
++ u32 *intspec, unsigned int intsize,
++ irq_hw_number_t *out_hwirq,
++ unsigned int *out_flags)
++{
++ u64 *intspec2 = (u64 *)intspec;
++
++ *out_hwirq = *intspec2;
++ *out_flags |= IRQ_TYPE_LEVEL_LOW;
++ return 0;
++}
++
++static int beatic_pic_host_match(struct irq_host *h, struct device_node *np)
++{
++ /* Match all */
++ return 1;
++}
++
++static struct irq_host_ops beatic_pic_host_ops = {
++ .map = beatic_pic_host_map,
++ .remap = beatic_pic_host_remap,
++ .unmap = beatic_pic_host_unmap,
++ .xlate = beatic_pic_host_xlate,
++ .match = beatic_pic_host_match,
++};
++
++/*
++ * Get an IRQ number
++ * Note: returns VIRQ
++ */
++static inline unsigned int beatic_get_irq_plug(void)
++{
++ int i;
++ uint64_t pending[4], ub;
++
++ for (i = 0; i < MAX_IRQS; i += 256) {
++ beat_detect_pending_interrupts(i, pending);
++ __asm__ ("cntlzd %0,%1":"=r"(ub):
++ "r"(pending[0] & beatic_irq_mask_enable[i/64+0]
++ & beatic_irq_mask_ack[i/64+0]));
++ if (ub != 64)
++ return i + ub + 0;
++ __asm__ ("cntlzd %0,%1":"=r"(ub):
++ "r"(pending[1] & beatic_irq_mask_enable[i/64+1]
++ & beatic_irq_mask_ack[i/64+1]));
++ if (ub != 64)
++ return i + ub + 64;
++ __asm__ ("cntlzd %0,%1":"=r"(ub):
++ "r"(pending[2] & beatic_irq_mask_enable[i/64+2]
++ & beatic_irq_mask_ack[i/64+2]));
++ if (ub != 64)
++ return i + ub + 128;
++ __asm__ ("cntlzd %0,%1":"=r"(ub):
++ "r"(pending[3] & beatic_irq_mask_enable[i/64+3]
++ & beatic_irq_mask_ack[i/64+3]));
++ if (ub != 64)
++ return i + ub + 192;
++ }
++
++ return NO_IRQ;
++}
++unsigned int beatic_get_irq(void)
++{
++ unsigned int ret;
++
++ ret = beatic_get_irq_plug();
++ if (ret != NO_IRQ)
++ beatic_ack_irq(ret);
++ return ret;
++}
++
++/*
++ */
++void __init beatic_init_IRQ(void)
++{
++ int i;
++
++ memset(beatic_irq_mask_enable, 0, sizeof(beatic_irq_mask_enable));
++ memset(beatic_irq_mask_ack, 255, sizeof(beatic_irq_mask_ack));
++ for (i = 0; i < MAX_IRQS; i += 256)
++ beat_set_interrupt_mask(i, 0L, 0L, 0L, 0L);
++
++ /* Set out get_irq function */
++ ppc_md.get_irq = beatic_get_irq;
++
++ /* Allocate an irq host */
++ beatic_host = irq_alloc_host(NULL, IRQ_HOST_MAP_NOMAP, 0,
++ &beatic_pic_host_ops,
++ 0);
++ BUG_ON(beatic_host == NULL);
++ irq_set_default_host(beatic_host);
++}
++
++#ifdef CONFIG_SMP
++
++/* Nullified to compile with SMP mode */
++void beatic_setup_cpu(int cpu)
++{
++}
++
++void beatic_cause_IPI(int cpu, int mesg)
++{
++}
++
++void beatic_request_IPIs(void)
++{
++}
++#endif /* CONFIG_SMP */
++
++void beatic_deinit_IRQ(void)
++{
++ int i;
++
++ for (i = 1; i < NR_IRQS; i++)
++ beat_destruct_irq_plug(i);
++}
+diff --git a/arch/powerpc/platforms/cell/beat_interrupt.h b/arch/powerpc/platforms/cell/beat_interrupt.h
+new file mode 100644
+index 0000000..b470fd0
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/beat_interrupt.h
+@@ -0,0 +1,33 @@
++/*
++ * Celleb/Beat Interrupt controller
++ *
++ * (C) Copyright 2006 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; 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.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#ifndef ASM_BEAT_PIC_H
++#define ASM_BEAT_PIC_H
++#ifdef __KERNEL__
++
++extern void beatic_init_IRQ(void);
++extern unsigned int beatic_get_irq(void);
++extern void beatic_cause_IPI(int cpu, int mesg);
++extern void beatic_request_IPIs(void);
++extern void beatic_setup_cpu(int);
++extern void beatic_deinit_IRQ(void);
++
++#endif
++#endif /* ASM_BEAT_PIC_H */
+diff --git a/arch/powerpc/platforms/cell/beat_iommu.c b/arch/powerpc/platforms/cell/beat_iommu.c
+new file mode 100644
+index 0000000..93b0efd
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/beat_iommu.c
+@@ -0,0 +1,116 @@
++/*
++ * Support for IOMMU on Celleb platform.
++ *
++ * (C) Copyright 2006-2007 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; 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.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/dma-mapping.h>
++#include <linux/pci.h>
++#include <linux/of_platform.h>
++
++#include <asm/machdep.h>
++
++#include "beat_wrapper.h"
++
++#define DMA_FLAGS 0xf800000000000000UL /* r/w permitted, coherency required,
++ strongest order */
++
++static int __init find_dma_window(u64 *io_space_id, u64 *ioid,
++ u64 *base, u64 *size, u64 *io_page_size)
++{
++ struct device_node *dn;
++ const unsigned long *dma_window;
++
++ for_each_node_by_type(dn, "ioif") {
++ dma_window = of_get_property(dn, "toshiba,dma-window", NULL);
++ if (dma_window) {
++ *io_space_id = (dma_window[0] >> 32) & 0xffffffffUL;
++ *ioid = dma_window[0] & 0x7ffUL;
++ *base = dma_window[1];
++ *size = dma_window[2];
++ *io_page_size = 1 << dma_window[3];
++ of_node_put(dn);
++ return 1;
++ }
++ }
++ return 0;
++}
++
++static unsigned long celleb_dma_direct_offset;
++
++static void __init celleb_init_direct_mapping(void)
++{
++ u64 lpar_addr, io_addr;
++ u64 io_space_id, ioid, dma_base, dma_size, io_page_size;
++
++ if (!find_dma_window(&io_space_id, &ioid, &dma_base, &dma_size,
++ &io_page_size)) {
++ pr_info("No dma window found !\n");
++ return;
++ }
++
++ for (lpar_addr = 0; lpar_addr < dma_size; lpar_addr += io_page_size) {
++ io_addr = lpar_addr + dma_base;
++ (void)beat_put_iopte(io_space_id, io_addr, lpar_addr,
++ ioid, DMA_FLAGS);
++ }
++
++ celleb_dma_direct_offset = dma_base;
++}
++
++static void celleb_dma_dev_setup(struct device *dev)
++{
++ dev->archdata.dma_ops = get_pci_dma_ops();
++ dev->archdata.dma_data = (void *)celleb_dma_direct_offset;
++}
++
++static void celleb_pci_dma_dev_setup(struct pci_dev *pdev)
++{
++ celleb_dma_dev_setup(&pdev->dev);
++}
++
++static int celleb_of_bus_notify(struct notifier_block *nb,
++ unsigned long action, void *data)
++{
++ struct device *dev = data;
++
++ /* We are only intereted in device addition */
++ if (action != BUS_NOTIFY_ADD_DEVICE)
++ return 0;
++
++ celleb_dma_dev_setup(dev);
++
++ return 0;
++}
++
++static struct notifier_block celleb_of_bus_notifier = {
++ .notifier_call = celleb_of_bus_notify
++};
++
++static int __init celleb_init_iommu(void)
++{
++ celleb_init_direct_mapping();
++ set_pci_dma_ops(&dma_direct_ops);
++ ppc_md.pci_dma_dev_setup = celleb_pci_dma_dev_setup;
++ bus_register_notifier(&of_platform_bus_type, &celleb_of_bus_notifier);
++
++ return 0;
++}
++
++machine_arch_initcall(celleb_beat, celleb_init_iommu);
+diff --git a/arch/powerpc/platforms/cell/beat_smp.c b/arch/powerpc/platforms/cell/beat_smp.c
+new file mode 100644
+index 0000000..26efc20
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/beat_smp.c
+@@ -0,0 +1,124 @@
++/*
++ * SMP support for Celleb platform. (Incomplete)
++ *
++ * (C) Copyright 2006 TOSHIBA CORPORATION
++ *
++ * This code is based on arch/powerpc/platforms/cell/smp.c:
++ * Dave Engebretsen, Peter Bergner, and
++ * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
++ * Plus various changes from other IBM teams...
++ *
++ * 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.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#undef DEBUG
++
++#include <linux/kernel.h>
++#include <linux/smp.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++#include <linux/threads.h>
++#include <linux/cpu.h>
++
++#include <asm/irq.h>
++#include <asm/smp.h>
++#include <asm/machdep.h>
++#include <asm/udbg.h>
++
++#include "beat_interrupt.h"
++
++#ifdef DEBUG
++#define DBG(fmt...) udbg_printf(fmt)
++#else
++#define DBG(fmt...)
++#endif
++
++/*
++ * The primary thread of each non-boot processor is recorded here before
++ * smp init.
++ */
++/* static cpumask_t of_spin_map; */
++
++/**
++ * smp_startup_cpu() - start the given cpu
++ *
++ * At boot time, there is nothing to do for primary threads which were
++ * started from Open Firmware. For anything else, call RTAS with the
++ * appropriate start location.
++ *
++ * Returns:
++ * 0 - failure
++ * 1 - success
++ */
++static inline int __devinit smp_startup_cpu(unsigned int lcpu)
++{
++ return 0;
++}
++
++static void smp_beatic_message_pass(int target, int msg)
++{
++ unsigned int i;
++
++ if (target < NR_CPUS) {
++ beatic_cause_IPI(target, msg);
++ } else {
++ for_each_online_cpu(i) {
++ if (target == MSG_ALL_BUT_SELF
++ && i == smp_processor_id())
++ continue;
++ beatic_cause_IPI(i, msg);
++ }
++ }
++}
++
++static int __init smp_beatic_probe(void)
++{
++ return cpus_weight(cpu_possible_map);
++}
++
++static void __devinit smp_beatic_setup_cpu(int cpu)
++{
++ beatic_setup_cpu(cpu);
++}
++
++static void __devinit smp_celleb_kick_cpu(int nr)
++{
++ BUG_ON(nr < 0 || nr >= NR_CPUS);
++
++ if (!smp_startup_cpu(nr))
++ return;
++}
++
++static int smp_celleb_cpu_bootable(unsigned int nr)
++{
++ return 1;
++}
++static struct smp_ops_t bpa_beatic_smp_ops = {
++ .message_pass = smp_beatic_message_pass,
++ .probe = smp_beatic_probe,
++ .kick_cpu = smp_celleb_kick_cpu,
++ .setup_cpu = smp_beatic_setup_cpu,
++ .cpu_bootable = smp_celleb_cpu_bootable,
++};
++
++/* This is called very early */
++void __init smp_init_celleb(void)
++{
++ DBG(" -> smp_init_celleb()\n");
++
++ smp_ops = &bpa_beatic_smp_ops;
++
++ DBG(" <- smp_init_celleb()\n");
++}
+diff --git a/arch/powerpc/platforms/cell/beat_spu_priv1.c b/arch/powerpc/platforms/cell/beat_spu_priv1.c
+new file mode 100644
+index 0000000..bcc17f7
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/beat_spu_priv1.c
+@@ -0,0 +1,207 @@
++/*
++ * spu hypervisor abstraction for Beat
++ *
++ * (C) Copyright 2006-2007 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; 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.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#include <linux/module.h>
++
++#include <asm/types.h>
++#include <asm/spu.h>
++#include <asm/spu_priv1.h>
++
++#include "beat_wrapper.h"
++
++static inline void _int_mask_set(struct spu *spu, int class, u64 mask)
++{
++ spu->shadow_int_mask_RW[class] = mask;
++ beat_set_irq_mask_for_spe(spu->spe_id, class, mask);
++}
++
++static inline u64 _int_mask_get(struct spu *spu, int class)
++{
++ return spu->shadow_int_mask_RW[class];
++}
++
++static void int_mask_set(struct spu *spu, int class, u64 mask)
++{
++ _int_mask_set(spu, class, mask);
++}
++
++static u64 int_mask_get(struct spu *spu, int class)
++{
++ return _int_mask_get(spu, class);
++}
++
++static void int_mask_and(struct spu *spu, int class, u64 mask)
++{
++ u64 old_mask;
++ old_mask = _int_mask_get(spu, class);
++ _int_mask_set(spu, class, old_mask & mask);
++}
++
++static void int_mask_or(struct spu *spu, int class, u64 mask)
++{
++ u64 old_mask;
++ old_mask = _int_mask_get(spu, class);
++ _int_mask_set(spu, class, old_mask | mask);
++}
++
++static void int_stat_clear(struct spu *spu, int class, u64 stat)
++{
++ beat_clear_interrupt_status_of_spe(spu->spe_id, class, stat);
++}
++
++static u64 int_stat_get(struct spu *spu, int class)
++{
++ u64 int_stat;
++ beat_get_interrupt_status_of_spe(spu->spe_id, class, &int_stat);
++ return int_stat;
++}
++
++static void cpu_affinity_set(struct spu *spu, int cpu)
++{
++ return;
++}
++
++static u64 mfc_dar_get(struct spu *spu)
++{
++ u64 dar;
++ beat_get_spe_privileged_state_1_registers(
++ spu->spe_id,
++ offsetof(struct spu_priv1, mfc_dar_RW), &dar);
++ return dar;
++}
++
++static u64 mfc_dsisr_get(struct spu *spu)
++{
++ u64 dsisr;
++ beat_get_spe_privileged_state_1_registers(
++ spu->spe_id,
++ offsetof(struct spu_priv1, mfc_dsisr_RW), &dsisr);
++ return dsisr;
++}
++
++static void mfc_dsisr_set(struct spu *spu, u64 dsisr)
++{
++ beat_set_spe_privileged_state_1_registers(
++ spu->spe_id,
++ offsetof(struct spu_priv1, mfc_dsisr_RW), dsisr);
++}
++
++static void mfc_sdr_setup(struct spu *spu)
++{
++ return;
++}
++
++static void mfc_sr1_set(struct spu *spu, u64 sr1)
++{
++ beat_set_spe_privileged_state_1_registers(
++ spu->spe_id,
++ offsetof(struct spu_priv1, mfc_sr1_RW), sr1);
++}
++
++static u64 mfc_sr1_get(struct spu *spu)
++{
++ u64 sr1;
++ beat_get_spe_privileged_state_1_registers(
++ spu->spe_id,
++ offsetof(struct spu_priv1, mfc_sr1_RW), &sr1);
++ return sr1;
++}
++
++static void mfc_tclass_id_set(struct spu *spu, u64 tclass_id)
++{
++ beat_set_spe_privileged_state_1_registers(
++ spu->spe_id,
++ offsetof(struct spu_priv1, mfc_tclass_id_RW), tclass_id);
++}
++
++static u64 mfc_tclass_id_get(struct spu *spu)
++{
++ u64 tclass_id;
++ beat_get_spe_privileged_state_1_registers(
++ spu->spe_id,
++ offsetof(struct spu_priv1, mfc_tclass_id_RW), &tclass_id);
++ return tclass_id;
++}
++
++static void tlb_invalidate(struct spu *spu)
++{
++ beat_set_spe_privileged_state_1_registers(
++ spu->spe_id,
++ offsetof(struct spu_priv1, tlb_invalidate_entry_W), 0ul);
++}
++
++static void resource_allocation_groupID_set(struct spu *spu, u64 id)
++{
++ beat_set_spe_privileged_state_1_registers(
++ spu->spe_id,
++ offsetof(struct spu_priv1, resource_allocation_groupID_RW),
++ id);
++}
++
++static u64 resource_allocation_groupID_get(struct spu *spu)
++{
++ u64 id;
++ beat_get_spe_privileged_state_1_registers(
++ spu->spe_id,
++ offsetof(struct spu_priv1, resource_allocation_groupID_RW),
++ &id);
++ return id;
++}
++
++static void resource_allocation_enable_set(struct spu *spu, u64 enable)
++{
++ beat_set_spe_privileged_state_1_registers(
++ spu->spe_id,
++ offsetof(struct spu_priv1, resource_allocation_enable_RW),
++ enable);
++}
++
++static u64 resource_allocation_enable_get(struct spu *spu)
++{
++ u64 enable;
++ beat_get_spe_privileged_state_1_registers(
++ spu->spe_id,
++ offsetof(struct spu_priv1, resource_allocation_enable_RW),
++ &enable);
++ return enable;
++}
++
++const struct spu_priv1_ops spu_priv1_beat_ops = {
++ .int_mask_and = int_mask_and,
++ .int_mask_or = int_mask_or,
++ .int_mask_set = int_mask_set,
++ .int_mask_get = int_mask_get,
++ .int_stat_clear = int_stat_clear,
++ .int_stat_get = int_stat_get,
++ .cpu_affinity_set = cpu_affinity_set,
++ .mfc_dar_get = mfc_dar_get,
++ .mfc_dsisr_get = mfc_dsisr_get,
++ .mfc_dsisr_set = mfc_dsisr_set,
++ .mfc_sdr_setup = mfc_sdr_setup,
++ .mfc_sr1_set = mfc_sr1_set,
++ .mfc_sr1_get = mfc_sr1_get,
++ .mfc_tclass_id_set = mfc_tclass_id_set,
++ .mfc_tclass_id_get = mfc_tclass_id_get,
++ .tlb_invalidate = tlb_invalidate,
++ .resource_allocation_groupID_set = resource_allocation_groupID_set,
++ .resource_allocation_groupID_get = resource_allocation_groupID_get,
++ .resource_allocation_enable_set = resource_allocation_enable_set,
++ .resource_allocation_enable_get = resource_allocation_enable_get,
++};
+diff --git a/arch/powerpc/platforms/cell/beat_syscall.h b/arch/powerpc/platforms/cell/beat_syscall.h
+new file mode 100644
+index 0000000..8580dc7
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/beat_syscall.h
+@@ -0,0 +1,164 @@
++/*
++ * Beat hypervisor call numbers
++ *
++ * (C) Copyright 2004-2007 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; 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.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#ifndef BEAT_BEAT_syscall_H
++#define BEAT_BEAT_syscall_H
++
++#ifdef __ASSEMBLY__
++#define __BEAT_ADD_VENDOR_ID(__x, __v) ((__v)<<60|(__x))
++#else
++#define __BEAT_ADD_VENDOR_ID(__x, __v) ((u64)(__v)<<60|(__x))
++#endif
++#define HV_allocate_memory __BEAT_ADD_VENDOR_ID(0, 0)
++#define HV_construct_virtual_address_space __BEAT_ADD_VENDOR_ID(2, 0)
++#define HV_destruct_virtual_address_space __BEAT_ADD_VENDOR_ID(10, 0)
++#define HV_get_virtual_address_space_id_of_ppe __BEAT_ADD_VENDOR_ID(4, 0)
++#define HV_query_logical_partition_address_region_info \
++ __BEAT_ADD_VENDOR_ID(6, 0)
++#define HV_release_memory __BEAT_ADD_VENDOR_ID(13, 0)
++#define HV_select_virtual_address_space __BEAT_ADD_VENDOR_ID(7, 0)
++#define HV_load_range_registers __BEAT_ADD_VENDOR_ID(68, 0)
++#define HV_set_ppe_l2cache_rmt_entry __BEAT_ADD_VENDOR_ID(70, 0)
++#define HV_set_ppe_tlb_rmt_entry __BEAT_ADD_VENDOR_ID(71, 0)
++#define HV_set_spe_tlb_rmt_entry __BEAT_ADD_VENDOR_ID(72, 0)
++#define HV_get_io_address_translation_fault_info __BEAT_ADD_VENDOR_ID(14, 0)
++#define HV_get_iopte __BEAT_ADD_VENDOR_ID(16, 0)
++#define HV_preload_iopt_cache __BEAT_ADD_VENDOR_ID(17, 0)
++#define HV_put_iopte __BEAT_ADD_VENDOR_ID(15, 0)
++#define HV_connect_event_ports __BEAT_ADD_VENDOR_ID(21, 0)
++#define HV_construct_event_receive_port __BEAT_ADD_VENDOR_ID(18, 0)
++#define HV_destruct_event_receive_port __BEAT_ADD_VENDOR_ID(19, 0)
++#define HV_destruct_event_send_port __BEAT_ADD_VENDOR_ID(22, 0)
++#define HV_get_state_of_event_send_port __BEAT_ADD_VENDOR_ID(25, 0)
++#define HV_request_to_connect_event_ports __BEAT_ADD_VENDOR_ID(20, 0)
++#define HV_send_event_externally __BEAT_ADD_VENDOR_ID(23, 0)
++#define HV_send_event_locally __BEAT_ADD_VENDOR_ID(24, 0)
++#define HV_construct_and_connect_irq_plug __BEAT_ADD_VENDOR_ID(28, 0)
++#define HV_destruct_irq_plug __BEAT_ADD_VENDOR_ID(29, 0)
++#define HV_detect_pending_interrupts __BEAT_ADD_VENDOR_ID(26, 0)
++#define HV_end_of_interrupt __BEAT_ADD_VENDOR_ID(27, 0)
++#define HV_assign_control_signal_notification_port __BEAT_ADD_VENDOR_ID(45, 0)
++#define HV_end_of_control_signal_processing __BEAT_ADD_VENDOR_ID(48, 0)
++#define HV_get_control_signal __BEAT_ADD_VENDOR_ID(46, 0)
++#define HV_set_irq_mask_for_spe __BEAT_ADD_VENDOR_ID(61, 0)
++#define HV_shutdown_logical_partition __BEAT_ADD_VENDOR_ID(44, 0)
++#define HV_connect_message_ports __BEAT_ADD_VENDOR_ID(35, 0)
++#define HV_destruct_message_port __BEAT_ADD_VENDOR_ID(36, 0)
++#define HV_receive_message __BEAT_ADD_VENDOR_ID(37, 0)
++#define HV_get_message_port_info __BEAT_ADD_VENDOR_ID(34, 0)
++#define HV_request_to_connect_message_ports __BEAT_ADD_VENDOR_ID(33, 0)
++#define HV_send_message __BEAT_ADD_VENDOR_ID(32, 0)
++#define HV_get_logical_ppe_id __BEAT_ADD_VENDOR_ID(69, 0)
++#define HV_pause __BEAT_ADD_VENDOR_ID(9, 0)
++#define HV_destruct_shared_memory_handle __BEAT_ADD_VENDOR_ID(51, 0)
++#define HV_get_shared_memory_info __BEAT_ADD_VENDOR_ID(52, 0)
++#define HV_permit_sharing_memory __BEAT_ADD_VENDOR_ID(50, 0)
++#define HV_request_to_attach_shared_memory __BEAT_ADD_VENDOR_ID(49, 0)
++#define HV_enable_logical_spe_execution __BEAT_ADD_VENDOR_ID(55, 0)
++#define HV_construct_logical_spe __BEAT_ADD_VENDOR_ID(53, 0)
++#define HV_disable_logical_spe_execution __BEAT_ADD_VENDOR_ID(56, 0)
++#define HV_destruct_logical_spe __BEAT_ADD_VENDOR_ID(54, 0)
++#define HV_sense_spe_execution_status __BEAT_ADD_VENDOR_ID(58, 0)
++#define HV_insert_htab_entry __BEAT_ADD_VENDOR_ID(101, 0)
++#define HV_read_htab_entries __BEAT_ADD_VENDOR_ID(95, 0)
++#define HV_write_htab_entry __BEAT_ADD_VENDOR_ID(94, 0)
++#define HV_assign_io_address_translation_fault_port \
++ __BEAT_ADD_VENDOR_ID(100, 0)
++#define HV_set_interrupt_mask __BEAT_ADD_VENDOR_ID(73, 0)
++#define HV_get_logical_partition_id __BEAT_ADD_VENDOR_ID(74, 0)
++#define HV_create_repository_node2 __BEAT_ADD_VENDOR_ID(90, 0)
++#define HV_create_repository_node __BEAT_ADD_VENDOR_ID(90, 0) /* alias */
++#define HV_get_repository_node_value2 __BEAT_ADD_VENDOR_ID(91, 0)
++#define HV_get_repository_node_value __BEAT_ADD_VENDOR_ID(91, 0) /* alias */
++#define HV_modify_repository_node_value2 __BEAT_ADD_VENDOR_ID(92, 0)
++#define HV_modify_repository_node_value __BEAT_ADD_VENDOR_ID(92, 0) /* alias */
++#define HV_remove_repository_node2 __BEAT_ADD_VENDOR_ID(93, 0)
++#define HV_remove_repository_node __BEAT_ADD_VENDOR_ID(93, 0) /* alias */
++#define HV_cancel_shared_memory __BEAT_ADD_VENDOR_ID(104, 0)
++#define HV_clear_interrupt_status_of_spe __BEAT_ADD_VENDOR_ID(206, 0)
++#define HV_construct_spe_irq_outlet __BEAT_ADD_VENDOR_ID(80, 0)
++#define HV_destruct_spe_irq_outlet __BEAT_ADD_VENDOR_ID(81, 0)
++#define HV_disconnect_ipspc_service __BEAT_ADD_VENDOR_ID(88, 0)
++#define HV_execute_ipspc_command __BEAT_ADD_VENDOR_ID(86, 0)
++#define HV_get_interrupt_status_of_spe __BEAT_ADD_VENDOR_ID(205, 0)
++#define HV_get_spe_privileged_state_1_registers __BEAT_ADD_VENDOR_ID(208, 0)
++#define HV_permit_use_of_ipspc_service __BEAT_ADD_VENDOR_ID(85, 0)
++#define HV_reinitialize_logical_spe __BEAT_ADD_VENDOR_ID(82, 0)
++#define HV_request_ipspc_service __BEAT_ADD_VENDOR_ID(84, 0)
++#define HV_stop_ipspc_command __BEAT_ADD_VENDOR_ID(87, 0)
++#define HV_set_spe_privileged_state_1_registers __BEAT_ADD_VENDOR_ID(204, 0)
++#define HV_get_status_of_ipspc_service __BEAT_ADD_VENDOR_ID(203, 0)
++#define HV_put_characters_to_console __BEAT_ADD_VENDOR_ID(0x101, 1)
++#define HV_get_characters_from_console __BEAT_ADD_VENDOR_ID(0x102, 1)
++#define HV_get_base_clock __BEAT_ADD_VENDOR_ID(0x111, 1)
++#define HV_set_base_clock __BEAT_ADD_VENDOR_ID(0x112, 1)
++#define HV_get_frame_cycle __BEAT_ADD_VENDOR_ID(0x114, 1)
++#define HV_disable_console __BEAT_ADD_VENDOR_ID(0x115, 1)
++#define HV_disable_all_console __BEAT_ADD_VENDOR_ID(0x116, 1)
++#define HV_oneshot_timer __BEAT_ADD_VENDOR_ID(0x117, 1)
++#define HV_set_dabr __BEAT_ADD_VENDOR_ID(0x118, 1)
++#define HV_get_dabr __BEAT_ADD_VENDOR_ID(0x119, 1)
++#define HV_start_hv_stats __BEAT_ADD_VENDOR_ID(0x21c, 1)
++#define HV_stop_hv_stats __BEAT_ADD_VENDOR_ID(0x21d, 1)
++#define HV_get_hv_stats __BEAT_ADD_VENDOR_ID(0x21e, 1)
++#define HV_get_hv_error_stats __BEAT_ADD_VENDOR_ID(0x221, 1)
++#define HV_get_stats __BEAT_ADD_VENDOR_ID(0x224, 1)
++#define HV_get_heap_stats __BEAT_ADD_VENDOR_ID(0x225, 1)
++#define HV_get_memory_stats __BEAT_ADD_VENDOR_ID(0x227, 1)
++#define HV_get_memory_detail __BEAT_ADD_VENDOR_ID(0x228, 1)
++#define HV_set_priority_of_irq_outlet __BEAT_ADD_VENDOR_ID(0x122, 1)
++#define HV_get_physical_spe_by_reservation_id __BEAT_ADD_VENDOR_ID(0x128, 1)
++#define HV_get_spe_context __BEAT_ADD_VENDOR_ID(0x129, 1)
++#define HV_set_spe_context __BEAT_ADD_VENDOR_ID(0x12a, 1)
++#define HV_downcount_of_interrupt __BEAT_ADD_VENDOR_ID(0x12e, 1)
++#define HV_peek_spe_context __BEAT_ADD_VENDOR_ID(0x12f, 1)
++#define HV_read_bpa_register __BEAT_ADD_VENDOR_ID(0x131, 1)
++#define HV_write_bpa_register __BEAT_ADD_VENDOR_ID(0x132, 1)
++#define HV_map_context_table_of_spe __BEAT_ADD_VENDOR_ID(0x137, 1)
++#define HV_get_slb_for_logical_spe __BEAT_ADD_VENDOR_ID(0x138, 1)
++#define HV_set_slb_for_logical_spe __BEAT_ADD_VENDOR_ID(0x139, 1)
++#define HV_init_pm __BEAT_ADD_VENDOR_ID(0x150, 1)
++#define HV_set_pm_signal __BEAT_ADD_VENDOR_ID(0x151, 1)
++#define HV_get_pm_signal __BEAT_ADD_VENDOR_ID(0x152, 1)
++#define HV_set_pm_config __BEAT_ADD_VENDOR_ID(0x153, 1)
++#define HV_get_pm_config __BEAT_ADD_VENDOR_ID(0x154, 1)
++#define HV_get_inner_trace_data __BEAT_ADD_VENDOR_ID(0x155, 1)
++#define HV_set_ext_trace_buffer __BEAT_ADD_VENDOR_ID(0x156, 1)
++#define HV_get_ext_trace_buffer __BEAT_ADD_VENDOR_ID(0x157, 1)
++#define HV_set_pm_interrupt __BEAT_ADD_VENDOR_ID(0x158, 1)
++#define HV_get_pm_interrupt __BEAT_ADD_VENDOR_ID(0x159, 1)
++#define HV_kick_pm __BEAT_ADD_VENDOR_ID(0x160, 1)
++#define HV_construct_pm_context __BEAT_ADD_VENDOR_ID(0x164, 1)
++#define HV_destruct_pm_context __BEAT_ADD_VENDOR_ID(0x165, 1)
++#define HV_be_slow __BEAT_ADD_VENDOR_ID(0x170, 1)
++#define HV_assign_ipspc_server_connection_status_notification_port \
++ __BEAT_ADD_VENDOR_ID(0x173, 1)
++#define HV_get_raid_of_physical_spe __BEAT_ADD_VENDOR_ID(0x174, 1)
++#define HV_set_physical_spe_to_rag __BEAT_ADD_VENDOR_ID(0x175, 1)
++#define HV_release_physical_spe_from_rag __BEAT_ADD_VENDOR_ID(0x176, 1)
++#define HV_rtc_read __BEAT_ADD_VENDOR_ID(0x190, 1)
++#define HV_rtc_write __BEAT_ADD_VENDOR_ID(0x191, 1)
++#define HV_eeprom_read __BEAT_ADD_VENDOR_ID(0x192, 1)
++#define HV_eeprom_write __BEAT_ADD_VENDOR_ID(0x193, 1)
++#define HV_insert_htab_entry3 __BEAT_ADD_VENDOR_ID(0x104, 1)
++#define HV_invalidate_htab_entry3 __BEAT_ADD_VENDOR_ID(0x105, 1)
++#define HV_update_htab_permission3 __BEAT_ADD_VENDOR_ID(0x106, 1)
++#define HV_clear_htab3 __BEAT_ADD_VENDOR_ID(0x107, 1)
++#endif
+diff --git a/arch/powerpc/platforms/cell/beat_udbg.c b/arch/powerpc/platforms/cell/beat_udbg.c
+new file mode 100644
+index 0000000..6b418f6
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/beat_udbg.c
+@@ -0,0 +1,98 @@
++/*
++ * udbg function for Beat
++ *
++ * (C) Copyright 2006 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; 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.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/console.h>
++
++#include <asm/machdep.h>
++#include <asm/prom.h>
++#include <asm/udbg.h>
++
++#include "beat.h"
++
++#define celleb_vtermno 0
++
++static void udbg_putc_beat(char c)
++{
++ unsigned long rc;
++
++ if (c == '\n')
++ udbg_putc_beat('\r');
++
++ rc = beat_put_term_char(celleb_vtermno, 1, (uint64_t)c << 56, 0);
++}
++
++/* Buffered chars getc */
++static long inbuflen;
++static long inbuf[2]; /* must be 2 longs */
++
++static int udbg_getc_poll_beat(void)
++{
++ /* The interface is tricky because it may return up to 16 chars.
++ * We save them statically for future calls to udbg_getc().
++ */
++ char ch, *buf = (char *)inbuf;
++ int i;
++ long rc;
++ if (inbuflen == 0) {
++ /* get some more chars. */
++ inbuflen = 0;
++ rc = beat_get_term_char(celleb_vtermno, &inbuflen,
++ inbuf+0, inbuf+1);
++ if (rc != 0)
++ inbuflen = 0; /* otherwise inbuflen is garbage */
++ }
++ if (inbuflen <= 0 || inbuflen > 16) {
++ /* Catch error case as well as other oddities (corruption) */
++ inbuflen = 0;
++ return -1;
++ }
++ ch = buf[0];
++ for (i = 1; i < inbuflen; i++) /* shuffle them down. */
++ buf[i-1] = buf[i];
++ inbuflen--;
++ return ch;
++}
++
++static int udbg_getc_beat(void)
++{
++ int ch;
++ for (;;) {
++ ch = udbg_getc_poll_beat();
++ if (ch == -1) {
++ /* This shouldn't be needed...but... */
++ volatile unsigned long delay;
++ for (delay = 0; delay < 2000000; delay++)
++ ;
++ } else {
++ return ch;
++ }
++ }
++}
++
++/* call this from early_init() for a working debug console on
++ * vterm capable LPAR machines
++ */
++void __init udbg_init_debug_beat(void)
++{
++ udbg_putc = udbg_putc_beat;
++ udbg_getc = udbg_getc_beat;
++ udbg_getc_poll = udbg_getc_poll_beat;
++}
+diff --git a/arch/powerpc/platforms/cell/beat_wrapper.h b/arch/powerpc/platforms/cell/beat_wrapper.h
+new file mode 100644
+index 0000000..b47dfda
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/beat_wrapper.h
+@@ -0,0 +1,289 @@
++/*
++ * Beat hypervisor call I/F
++ *
++ * (C) Copyright 2007 TOSHIBA CORPORATION
++ *
++ * This code is based on arch/powerpc/platforms/pseries/plpar_wrapper.h.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++#ifndef BEAT_HCALL
++#include "beat_syscall.h"
++
++/* defined in hvCall.S */
++extern s64 beat_hcall_norets(u64 opcode, ...);
++extern s64 beat_hcall_norets8(u64 opcode, u64 arg1, u64 arg2, u64 arg3,
++ u64 arg4, u64 arg5, u64 arg6, u64 arg7, u64 arg8);
++extern s64 beat_hcall1(u64 opcode, u64 retbuf[1], ...);
++extern s64 beat_hcall2(u64 opcode, u64 retbuf[2], ...);
++extern s64 beat_hcall3(u64 opcode, u64 retbuf[3], ...);
++extern s64 beat_hcall4(u64 opcode, u64 retbuf[4], ...);
++extern s64 beat_hcall5(u64 opcode, u64 retbuf[5], ...);
++extern s64 beat_hcall6(u64 opcode, u64 retbuf[6], ...);
++
++static inline s64 beat_downcount_of_interrupt(u64 plug_id)
++{
++ return beat_hcall_norets(HV_downcount_of_interrupt, plug_id);
++}
++
++static inline s64 beat_set_interrupt_mask(u64 index,
++ u64 val0, u64 val1, u64 val2, u64 val3)
++{
++ return beat_hcall_norets(HV_set_interrupt_mask, index,
++ val0, val1, val2, val3);
++}
++
++static inline s64 beat_destruct_irq_plug(u64 plug_id)
++{
++ return beat_hcall_norets(HV_destruct_irq_plug, plug_id);
++}
++
++static inline s64 beat_construct_and_connect_irq_plug(u64 plug_id,
++ u64 outlet_id)
++{
++ return beat_hcall_norets(HV_construct_and_connect_irq_plug, plug_id,
++ outlet_id);
++}
++
++static inline s64 beat_detect_pending_interrupts(u64 index, u64 *retbuf)
++{
++ return beat_hcall4(HV_detect_pending_interrupts, retbuf, index);
++}
++
++static inline s64 beat_pause(u64 style)
++{
++ return beat_hcall_norets(HV_pause, style);
++}
++
++static inline s64 beat_read_htab_entries(u64 htab_id, u64 index, u64 *retbuf)
++{
++ return beat_hcall5(HV_read_htab_entries, retbuf, htab_id, index);
++}
++
++static inline s64 beat_insert_htab_entry(u64 htab_id, u64 group,
++ u64 bitmask, u64 hpte_v, u64 hpte_r, u64 *slot)
++{
++ u64 dummy[3];
++ s64 ret;
++
++ ret = beat_hcall3(HV_insert_htab_entry, dummy, htab_id, group,
++ bitmask, hpte_v, hpte_r);
++ *slot = dummy[0];
++ return ret;
++}
++
++static inline s64 beat_write_htab_entry(u64 htab_id, u64 slot,
++ u64 hpte_v, u64 hpte_r, u64 mask_v, u64 mask_r,
++ u64 *ret_v, u64 *ret_r)
++{
++ u64 dummy[2];
++ s64 ret;
++
++ ret = beat_hcall2(HV_write_htab_entry, dummy, htab_id, slot,
++ hpte_v, hpte_r, mask_v, mask_r);
++ *ret_v = dummy[0];
++ *ret_r = dummy[1];
++ return ret;
++}
++
++static inline s64 beat_insert_htab_entry3(u64 htab_id, u64 group,
++ u64 hpte_v, u64 hpte_r, u64 mask_v, u64 value_v, u64 *slot)
++{
++ u64 dummy[1];
++ s64 ret;
++
++ ret = beat_hcall1(HV_insert_htab_entry3, dummy, htab_id, group,
++ hpte_v, hpte_r, mask_v, value_v);
++ *slot = dummy[0];
++ return ret;
++}
++
++static inline s64 beat_invalidate_htab_entry3(u64 htab_id, u64 group,
++ u64 va, u64 pss)
++{
++ return beat_hcall_norets(HV_invalidate_htab_entry3,
++ htab_id, group, va, pss);
++}
++
++static inline s64 beat_update_htab_permission3(u64 htab_id, u64 group,
++ u64 va, u64 pss, u64 ptel_mask, u64 ptel_value)
++{
++ return beat_hcall_norets(HV_update_htab_permission3,
++ htab_id, group, va, pss, ptel_mask, ptel_value);
++}
++
++static inline s64 beat_clear_htab3(u64 htab_id)
++{
++ return beat_hcall_norets(HV_clear_htab3, htab_id);
++}
++
++static inline void beat_shutdown_logical_partition(u64 code)
++{
++ (void)beat_hcall_norets(HV_shutdown_logical_partition, code);
++}
++
++static inline s64 beat_rtc_write(u64 time_from_epoch)
++{
++ return beat_hcall_norets(HV_rtc_write, time_from_epoch);
++}
++
++static inline s64 beat_rtc_read(u64 *time_from_epoch)
++{
++ u64 dummy[1];
++ s64 ret;
++
++ ret = beat_hcall1(HV_rtc_read, dummy);
++ *time_from_epoch = dummy[0];
++ return ret;
++}
++
++#define BEAT_NVRW_CNT (sizeof(u64) * 6)
++
++static inline s64 beat_eeprom_write(u64 index, u64 length, u8 *buffer)
++{
++ u64 b[6];
++
++ if (length > BEAT_NVRW_CNT)
++ return -1;
++ memcpy(b, buffer, sizeof(b));
++ return beat_hcall_norets8(HV_eeprom_write, index, length,
++ b[0], b[1], b[2], b[3], b[4], b[5]);
++}
++
++static inline s64 beat_eeprom_read(u64 index, u64 length, u8 *buffer)
++{
++ u64 b[6];
++ s64 ret;
++
++ if (length > BEAT_NVRW_CNT)
++ return -1;
++ ret = beat_hcall6(HV_eeprom_read, b, index, length);
++ memcpy(buffer, b, length);
++ return ret;
++}
++
++static inline s64 beat_set_dabr(u64 value, u64 style)
++{
++ return beat_hcall_norets(HV_set_dabr, value, style);
++}
++
++static inline s64 beat_get_characters_from_console(u64 termno, u64 *len,
++ u8 *buffer)
++{
++ u64 dummy[3];
++ s64 ret;
++
++ ret = beat_hcall3(HV_get_characters_from_console, dummy, termno, len);
++ *len = dummy[0];
++ memcpy(buffer, dummy + 1, *len);
++ return ret;
++}
++
++static inline s64 beat_put_characters_to_console(u64 termno, u64 len,
++ u8 *buffer)
++{
++ u64 b[2];
++
++ memcpy(b, buffer, len);
++ return beat_hcall_norets(HV_put_characters_to_console, termno, len,
++ b[0], b[1]);
++}
++
++static inline s64 beat_get_spe_privileged_state_1_registers(
++ u64 id, u64 offsetof, u64 *value)
++{
++ u64 dummy[1];
++ s64 ret;
++
++ ret = beat_hcall1(HV_get_spe_privileged_state_1_registers, dummy, id,
++ offsetof);
++ *value = dummy[0];
++ return ret;
++}
++
++static inline s64 beat_set_irq_mask_for_spe(u64 id, u64 class, u64 mask)
++{
++ return beat_hcall_norets(HV_set_irq_mask_for_spe, id, class, mask);
++}
++
++static inline s64 beat_clear_interrupt_status_of_spe(u64 id, u64 class,
++ u64 mask)
++{
++ return beat_hcall_norets(HV_clear_interrupt_status_of_spe,
++ id, class, mask);
++}
++
++static inline s64 beat_set_spe_privileged_state_1_registers(
++ u64 id, u64 offsetof, u64 value)
++{
++ return beat_hcall_norets(HV_set_spe_privileged_state_1_registers,
++ id, offsetof, value);
++}
++
++static inline s64 beat_get_interrupt_status_of_spe(u64 id, u64 class, u64 *val)
++{
++ u64 dummy[1];
++ s64 ret;
++
++ ret = beat_hcall1(HV_get_interrupt_status_of_spe, dummy, id, class);
++ *val = dummy[0];
++ return ret;
++}
++
++static inline s64 beat_put_iopte(u64 ioas_id, u64 io_addr, u64 real_addr,
++ u64 ioid, u64 flags)
++{
++ return beat_hcall_norets(HV_put_iopte, ioas_id, io_addr, real_addr,
++ ioid, flags);
++}
++
++static inline s64 beat_construct_event_receive_port(u64 *port)
++{
++ u64 dummy[1];
++ s64 ret;
++
++ ret = beat_hcall1(HV_construct_event_receive_port, dummy);
++ *port = dummy[0];
++ return ret;
++}
++
++static inline s64 beat_destruct_event_receive_port(u64 port)
++{
++ s64 ret;
++
++ ret = beat_hcall_norets(HV_destruct_event_receive_port, port);
++ return ret;
++}
++
++static inline s64 beat_create_repository_node(u64 path[4], u64 data[2])
++{
++ s64 ret;
++
++ ret = beat_hcall_norets(HV_create_repository_node2,
++ path[0], path[1], path[2], path[3], data[0], data[1]);
++ return ret;
++}
++
++static inline s64 beat_get_repository_node_value(u64 lpid, u64 path[4],
++ u64 data[2])
++{
++ s64 ret;
++
++ ret = beat_hcall2(HV_get_repository_node_value2, data,
++ lpid, path[0], path[1], path[2], path[3]);
++ return ret;
++}
++
++#endif
+diff --git a/arch/powerpc/platforms/cell/celleb_pci.c b/arch/powerpc/platforms/cell/celleb_pci.c
+new file mode 100644
+index 0000000..f39a3b2
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/celleb_pci.c
+@@ -0,0 +1,514 @@
++/*
++ * Support for PCI on Celleb platform.
++ *
++ * (C) Copyright 2006-2007 TOSHIBA CORPORATION
++ *
++ * This code is based on arch/powerpc/kernel/rtas_pci.c:
++ * Copyright (C) 2001 Dave Engebretsen, IBM Corporation
++ * Copyright (C) 2003 Anton Blanchard <anton at au.ibm.com>, IBM
++ *
++ * 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.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#undef DEBUG
++
++#include <linux/kernel.h>
++#include <linux/threads.h>
++#include <linux/pci.h>
++#include <linux/string.h>
++#include <linux/init.h>
++#include <linux/bootmem.h>
++#include <linux/pci_regs.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/prom.h>
++#include <asm/pci-bridge.h>
++#include <asm/ppc-pci.h>
++
++#include "io-workarounds.h"
++#include "celleb_pci.h"
++
++#define MAX_PCI_DEVICES 32
++#define MAX_PCI_FUNCTIONS 8
++#define MAX_PCI_BASE_ADDRS 3 /* use 64 bit address */
++
++/* definition for fake pci configuration area for GbE, .... ,and etc. */
++
++struct celleb_pci_resource {
++ struct resource r[MAX_PCI_BASE_ADDRS];
++};
++
++struct celleb_pci_private {
++ unsigned char *fake_config[MAX_PCI_DEVICES][MAX_PCI_FUNCTIONS];
++ struct celleb_pci_resource *res[MAX_PCI_DEVICES][MAX_PCI_FUNCTIONS];
++};
++
++static inline u8 celleb_fake_config_readb(void *addr)
++{
++ u8 *p = addr;
++ return *p;
++}
++
++static inline u16 celleb_fake_config_readw(void *addr)
++{
++ __le16 *p = addr;
++ return le16_to_cpu(*p);
++}
++
++static inline u32 celleb_fake_config_readl(void *addr)
++{
++ __le32 *p = addr;
++ return le32_to_cpu(*p);
++}
++
++static inline void celleb_fake_config_writeb(u32 val, void *addr)
++{
++ u8 *p = addr;
++ *p = val;
++}
++
++static inline void celleb_fake_config_writew(u32 val, void *addr)
++{
++ __le16 val16;
++ __le16 *p = addr;
++ val16 = cpu_to_le16(val);
++ *p = val16;
++}
++
++static inline void celleb_fake_config_writel(u32 val, void *addr)
++{
++ __le32 val32;
++ __le32 *p = addr;
++ val32 = cpu_to_le32(val);
++ *p = val32;
++}
++
++static unsigned char *get_fake_config_start(struct pci_controller *hose,
++ int devno, int fn)
++{
++ struct celleb_pci_private *private = hose->private_data;
++
++ if (private == NULL)
++ return NULL;
++
++ return private->fake_config[devno][fn];
++}
++
++static struct celleb_pci_resource *get_resource_start(
++ struct pci_controller *hose,
++ int devno, int fn)
++{
++ struct celleb_pci_private *private = hose->private_data;
++
++ if (private == NULL)
++ return NULL;
++
++ return private->res[devno][fn];
++}
++
++
++static void celleb_config_read_fake(unsigned char *config, int where,
++ int size, u32 *val)
++{
++ char *p = config + where;
++
++ switch (size) {
++ case 1:
++ *val = celleb_fake_config_readb(p);
++ break;
++ case 2:
++ *val = celleb_fake_config_readw(p);
++ break;
++ case 4:
++ *val = celleb_fake_config_readl(p);
++ break;
++ }
++}
++
++static void celleb_config_write_fake(unsigned char *config, int where,
++ int size, u32 val)
++{
++ char *p = config + where;
++
++ switch (size) {
++ case 1:
++ celleb_fake_config_writeb(val, p);
++ break;
++ case 2:
++ celleb_fake_config_writew(val, p);
++ break;
++ case 4:
++ celleb_fake_config_writel(val, p);
++ break;
++ }
++}
++
++static int celleb_fake_pci_read_config(struct pci_bus *bus,
++ unsigned int devfn, int where, int size, u32 *val)
++{
++ char *config;
++ struct device_node *node;
++ struct pci_controller *hose;
++ unsigned int devno = devfn >> 3;
++ unsigned int fn = devfn & 0x7;
++
++ /* allignment check */
++ BUG_ON(where % size);
++
++ pr_debug(" fake read: bus=0x%x, ", bus->number);
++ node = (struct device_node *)bus->sysdata;
++ hose = pci_find_hose_for_OF_device(node);
++ config = get_fake_config_start(hose, devno, fn);
++
++ pr_debug("devno=0x%x, where=0x%x, size=0x%x, ", devno, where, size);
++ if (!config) {
++ pr_debug("failed\n");
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ }
++
++ celleb_config_read_fake(config, where, size, val);
++ pr_debug("val=0x%x\n", *val);
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++
++static int celleb_fake_pci_write_config(struct pci_bus *bus,
++ unsigned int devfn, int where, int size, u32 val)
++{
++ char *config;
++ struct device_node *node;
++ struct pci_controller *hose;
++ struct celleb_pci_resource *res;
++ unsigned int devno = devfn >> 3;
++ unsigned int fn = devfn & 0x7;
++
++ /* allignment check */
++ BUG_ON(where % size);
++
++ node = (struct device_node *)bus->sysdata;
++ hose = pci_find_hose_for_OF_device(node);
++ config = get_fake_config_start(hose, devno, fn);
++
++ if (!config)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ if (val == ~0) {
++ int i = (where - PCI_BASE_ADDRESS_0) >> 3;
++
++ switch (where) {
++ case PCI_BASE_ADDRESS_0:
++ case PCI_BASE_ADDRESS_2:
++ if (size != 4)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ res = get_resource_start(hose, devno, fn);
++ if (!res)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ celleb_config_write_fake(config, where, size,
++ (res->r[i].end - res->r[i].start));
++ return PCIBIOS_SUCCESSFUL;
++ case PCI_BASE_ADDRESS_1:
++ case PCI_BASE_ADDRESS_3:
++ case PCI_BASE_ADDRESS_4:
++ case PCI_BASE_ADDRESS_5:
++ break;
++ default:
++ break;
++ }
++ }
++
++ celleb_config_write_fake(config, where, size, val);
++ pr_debug(" fake write: where=%x, size=%d, val=%x\n",
++ where, size, val);
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static struct pci_ops celleb_fake_pci_ops = {
++ .read = celleb_fake_pci_read_config,
++ .write = celleb_fake_pci_write_config,
++};
++
++static inline void celleb_setup_pci_base_addrs(struct pci_controller *hose,
++ unsigned int devno, unsigned int fn,
++ unsigned int num_base_addr)
++{
++ u32 val;
++ unsigned char *config;
++ struct celleb_pci_resource *res;
++
++ config = get_fake_config_start(hose, devno, fn);
++ res = get_resource_start(hose, devno, fn);
++
++ if (!config || !res)
++ return;
++
++ switch (num_base_addr) {
++ case 3:
++ val = (res->r[2].start & 0xfffffff0)
++ | PCI_BASE_ADDRESS_MEM_TYPE_64;
++ celleb_config_write_fake(config, PCI_BASE_ADDRESS_4, 4, val);
++ val = res->r[2].start >> 32;
++ celleb_config_write_fake(config, PCI_BASE_ADDRESS_5, 4, val);
++ /* FALLTHROUGH */
++ case 2:
++ val = (res->r[1].start & 0xfffffff0)
++ | PCI_BASE_ADDRESS_MEM_TYPE_64;
++ celleb_config_write_fake(config, PCI_BASE_ADDRESS_2, 4, val);
++ val = res->r[1].start >> 32;
++ celleb_config_write_fake(config, PCI_BASE_ADDRESS_3, 4, val);
++ /* FALLTHROUGH */
++ case 1:
++ val = (res->r[0].start & 0xfffffff0)
++ | PCI_BASE_ADDRESS_MEM_TYPE_64;
++ celleb_config_write_fake(config, PCI_BASE_ADDRESS_0, 4, val);
++ val = res->r[0].start >> 32;
++ celleb_config_write_fake(config, PCI_BASE_ADDRESS_1, 4, val);
++ break;
++ }
++
++ val = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
++ celleb_config_write_fake(config, PCI_COMMAND, 2, val);
++}
++
++static int __init celleb_setup_fake_pci_device(struct device_node *node,
++ struct pci_controller *hose)
++{
++ unsigned int rlen;
++ int num_base_addr = 0;
++ u32 val;
++ const u32 *wi0, *wi1, *wi2, *wi3, *wi4;
++ unsigned int devno, fn;
++ struct celleb_pci_private *private = hose->private_data;
++ unsigned char **config = NULL;
++ struct celleb_pci_resource **res = NULL;
++ const char *name;
++ const unsigned long *li;
++ int size, result;
++
++ if (private == NULL) {
++ printk(KERN_ERR "PCI: "
++ "memory space for pci controller is not assigned\n");
++ goto error;
++ }
++
++ name = of_get_property(node, "model", &rlen);
++ if (!name) {
++ printk(KERN_ERR "PCI: model property not found.\n");
++ goto error;
++ }
++
++ wi4 = of_get_property(node, "reg", &rlen);
++ if (wi4 == NULL)
++ goto error;
++
++ devno = ((wi4[0] >> 8) & 0xff) >> 3;
++ fn = (wi4[0] >> 8) & 0x7;
++
++ pr_debug("PCI: celleb_setup_fake_pci() %s devno=%x fn=%x\n", name,
++ devno, fn);
++
++ size = 256;
++ config = &private->fake_config[devno][fn];
++ *config = alloc_maybe_bootmem(size, GFP_KERNEL);
++ if (*config == NULL) {
++ printk(KERN_ERR "PCI: "
++ "not enough memory for fake configuration space\n");
++ goto error;
++ }
++ pr_debug("PCI: fake config area assigned 0x%016lx\n",
++ (unsigned long)*config);
++
++ size = sizeof(struct celleb_pci_resource);
++ res = &private->res[devno][fn];
++ *res = alloc_maybe_bootmem(size, GFP_KERNEL);
++ if (*res == NULL) {
++ printk(KERN_ERR
++ "PCI: not enough memory for resource data space\n");
++ goto error;
++ }
++ pr_debug("PCI: res assigned 0x%016lx\n", (unsigned long)*res);
++
++ wi0 = of_get_property(node, "device-id", NULL);
++ wi1 = of_get_property(node, "vendor-id", NULL);
++ wi2 = of_get_property(node, "class-code", NULL);
++ wi3 = of_get_property(node, "revision-id", NULL);
++ if (!wi0 || !wi1 || !wi2 || !wi3) {
++ printk(KERN_ERR "PCI: Missing device tree properties.\n");
++ goto error;
++ }
++
++ celleb_config_write_fake(*config, PCI_DEVICE_ID, 2, wi0[0] & 0xffff);
++ celleb_config_write_fake(*config, PCI_VENDOR_ID, 2, wi1[0] & 0xffff);
++ pr_debug("class-code = 0x%08x\n", wi2[0]);
++
++ celleb_config_write_fake(*config, PCI_CLASS_PROG, 1, wi2[0] & 0xff);
++ celleb_config_write_fake(*config, PCI_CLASS_DEVICE, 2,
++ (wi2[0] >> 8) & 0xffff);
++ celleb_config_write_fake(*config, PCI_REVISION_ID, 1, wi3[0]);
++
++ while (num_base_addr < MAX_PCI_BASE_ADDRS) {
++ result = of_address_to_resource(node,
++ num_base_addr, &(*res)->r[num_base_addr]);
++ if (result)
++ break;
++ num_base_addr++;
++ }
++
++ celleb_setup_pci_base_addrs(hose, devno, fn, num_base_addr);
++
++ li = of_get_property(node, "interrupts", &rlen);
++ if (!li) {
++ printk(KERN_ERR "PCI: interrupts not found.\n");
++ goto error;
++ }
++ val = li[0];
++ celleb_config_write_fake(*config, PCI_INTERRUPT_PIN, 1, 1);
++ celleb_config_write_fake(*config, PCI_INTERRUPT_LINE, 1, val);
++
++#ifdef DEBUG
++ pr_debug("PCI: %s irq=%ld\n", name, li[0]);
++ for (i = 0; i < 6; i++) {
++ celleb_config_read_fake(*config,
++ PCI_BASE_ADDRESS_0 + 0x4 * i, 4,
++ &val);
++ pr_debug("PCI: %s fn=%d base_address_%d=0x%x\n",
++ name, fn, i, val);
++ }
++#endif
++
++ celleb_config_write_fake(*config, PCI_HEADER_TYPE, 1,
++ PCI_HEADER_TYPE_NORMAL);
++
++ return 0;
++
++error:
++ if (mem_init_done) {
++ if (config && *config)
++ kfree(*config);
++ if (res && *res)
++ kfree(*res);
++
++ } else {
++ if (config && *config) {
++ size = 256;
++ free_bootmem((unsigned long)(*config), size);
++ }
++ if (res && *res) {
++ size = sizeof(struct celleb_pci_resource);
++ free_bootmem((unsigned long)(*res), size);
++ }
++ }
++
++ return 1;
++}
++
++static int __init phb_set_bus_ranges(struct device_node *dev,
++ struct pci_controller *phb)
++{
++ const int *bus_range;
++ unsigned int len;
++
++ bus_range = of_get_property(dev, "bus-range", &len);
++ if (bus_range == NULL || len < 2 * sizeof(int))
++ return 1;
++
++ phb->first_busno = bus_range[0];
++ phb->last_busno = bus_range[1];
++
++ return 0;
++}
++
++static void __init celleb_alloc_private_mem(struct pci_controller *hose)
++{
++ hose->private_data =
++ alloc_maybe_bootmem(sizeof(struct celleb_pci_private),
++ GFP_KERNEL);
++}
++
++static int __init celleb_setup_fake_pci(struct device_node *dev,
++ struct pci_controller *phb)
++{
++ struct device_node *node;
++
++ phb->ops = &celleb_fake_pci_ops;
++ celleb_alloc_private_mem(phb);
++
++ for (node = of_get_next_child(dev, NULL);
++ node != NULL; node = of_get_next_child(dev, node))
++ celleb_setup_fake_pci_device(node, phb);
++
++ return 0;
++}
++
++static struct celleb_phb_spec celleb_fake_pci_spec __initdata = {
++ .setup = celleb_setup_fake_pci,
++};
++
++static struct of_device_id celleb_phb_match[] __initdata = {
++ {
++ .name = "pci-pseudo",
++ .data = &celleb_fake_pci_spec,
++ }, {
++ .name = "epci",
++ .data = &celleb_epci_spec,
++ }, {
++ .name = "pcie",
++ .data = &celleb_pciex_spec,
++ }, {
++ },
++};
++
++static int __init celleb_io_workaround_init(struct pci_controller *phb,
++ struct celleb_phb_spec *phb_spec)
++{
++ if (phb_spec->ops) {
++ iowa_register_bus(phb, phb_spec->ops, phb_spec->iowa_init,
++ phb_spec->iowa_data);
++ io_workaround_init();
++ }
++
++ return 0;
++}
++
++int __init celleb_setup_phb(struct pci_controller *phb)
++{
++ struct device_node *dev = phb->dn;
++ const struct of_device_id *match;
++ struct celleb_phb_spec *phb_spec;
++ int rc;
++
++ match = of_match_node(celleb_phb_match, dev);
++ if (!match)
++ return 1;
++
++ phb_set_bus_ranges(dev, phb);
++ phb->buid = 1;
++
++ phb_spec = match->data;
++ rc = (*phb_spec->setup)(dev, phb);
++ if (rc)
++ return 1;
++
++ return celleb_io_workaround_init(phb, phb_spec);
++}
++
++int celleb_pci_probe_mode(struct pci_bus *bus)
++{
++ return PCI_PROBE_DEVTREE;
++}
+diff --git a/arch/powerpc/platforms/cell/celleb_pci.h b/arch/powerpc/platforms/cell/celleb_pci.h
+new file mode 100644
+index 0000000..4cba152
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/celleb_pci.h
+@@ -0,0 +1,45 @@
++/*
++ * pci prototypes for Celleb platform
++ *
++ * (C) Copyright 2006-2007 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; 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.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#ifndef _CELLEB_PCI_H
++#define _CELLEB_PCI_H
++
++#include <linux/pci.h>
++
++#include <asm/pci-bridge.h>
++#include <asm/prom.h>
++#include <asm/ppc-pci.h>
++
++#include "io-workarounds.h"
++
++struct celleb_phb_spec {
++ int (*setup)(struct device_node *, struct pci_controller *);
++ struct ppc_pci_io *ops;
++ int (*iowa_init)(struct iowa_bus *, void *);
++ void *iowa_data;
++};
++
++extern int celleb_setup_phb(struct pci_controller *);
++extern int celleb_pci_probe_mode(struct pci_bus *);
++
++extern struct celleb_phb_spec celleb_epci_spec;
++extern struct celleb_phb_spec celleb_pciex_spec;
++
++#endif /* _CELLEB_PCI_H */
+diff --git a/arch/powerpc/platforms/cell/celleb_scc.h b/arch/powerpc/platforms/cell/celleb_scc.h
+new file mode 100644
+index 0000000..b596a71
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/celleb_scc.h
+@@ -0,0 +1,232 @@
++/*
++ * SCC (Super Companion Chip) definitions
++ *
++ * (C) Copyright 2004-2006 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; 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.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#ifndef _CELLEB_SCC_H
++#define _CELLEB_SCC_H
++
++#define PCI_VENDOR_ID_TOSHIBA_2 0x102f
++#define PCI_DEVICE_ID_TOSHIBA_SCC_PCIEXC_BRIDGE 0x01b0
++#define PCI_DEVICE_ID_TOSHIBA_SCC_EPCI_BRIDGE 0x01b1
++#define PCI_DEVICE_ID_TOSHIBA_SCC_BRIDGE 0x01b2
++#define PCI_DEVICE_ID_TOSHIBA_SCC_GBE 0x01b3
++#define PCI_DEVICE_ID_TOSHIBA_SCC_ATA 0x01b4
++#define PCI_DEVICE_ID_TOSHIBA_SCC_USB2 0x01b5
++#define PCI_DEVICE_ID_TOSHIBA_SCC_USB 0x01b6
++#define PCI_DEVICE_ID_TOSHIBA_SCC_ENCDEC 0x01b7
++
++#define SCC_EPCI_REG 0x0000d000
++
++/* EPCI registers */
++#define SCC_EPCI_CNF10_REG 0x010
++#define SCC_EPCI_CNF14_REG 0x014
++#define SCC_EPCI_CNF18_REG 0x018
++#define SCC_EPCI_PVBAT 0x100
++#define SCC_EPCI_VPMBAT 0x104
++#define SCC_EPCI_VPIBAT 0x108
++#define SCC_EPCI_VCSR 0x110
++#define SCC_EPCI_VIENAB 0x114
++#define SCC_EPCI_VISTAT 0x118
++#define SCC_EPCI_VRDCOUNT 0x124
++#define SCC_EPCI_BAM0 0x12c
++#define SCC_EPCI_BAM1 0x134
++#define SCC_EPCI_BAM2 0x13c
++#define SCC_EPCI_IADR 0x164
++#define SCC_EPCI_CLKRST 0x800
++#define SCC_EPCI_INTSET 0x804
++#define SCC_EPCI_STATUS 0x808
++#define SCC_EPCI_ABTSET 0x80c
++#define SCC_EPCI_WATRP 0x810
++#define SCC_EPCI_DUMYRADR 0x814
++#define SCC_EPCI_SWRESP 0x818
++#define SCC_EPCI_CNTOPT 0x81c
++#define SCC_EPCI_ECMODE 0xf00
++#define SCC_EPCI_IOM_AC_NUM 5
++#define SCC_EPCI_IOM_ACTE(n) (0xf10 + (n) * 4)
++#define SCC_EPCI_IOT_AC_NUM 4
++#define SCC_EPCI_IOT_ACTE(n) (0xf30 + (n) * 4)
++#define SCC_EPCI_MAEA 0xf50
++#define SCC_EPCI_MAEC 0xf54
++#define SCC_EPCI_CKCTRL 0xff0
++
++/* bits for SCC_EPCI_VCSR */
++#define SCC_EPCI_VCSR_FRE 0x00020000
++#define SCC_EPCI_VCSR_FWE 0x00010000
++#define SCC_EPCI_VCSR_DR 0x00000400
++#define SCC_EPCI_VCSR_SR 0x00000008
++#define SCC_EPCI_VCSR_AT 0x00000004
++
++/* bits for SCC_EPCI_VIENAB/SCC_EPCI_VISTAT */
++#define SCC_EPCI_VISTAT_PMPE 0x00000008
++#define SCC_EPCI_VISTAT_PMFE 0x00000004
++#define SCC_EPCI_VISTAT_PRA 0x00000002
++#define SCC_EPCI_VISTAT_PRD 0x00000001
++#define SCC_EPCI_VISTAT_ALL 0x0000000f
++
++#define SCC_EPCI_VIENAB_PMPEE 0x00000008
++#define SCC_EPCI_VIENAB_PMFEE 0x00000004
++#define SCC_EPCI_VIENAB_PRA 0x00000002
++#define SCC_EPCI_VIENAB_PRD 0x00000001
++#define SCC_EPCI_VIENAB_ALL 0x0000000f
++
++/* bits for SCC_EPCI_CLKRST */
++#define SCC_EPCI_CLKRST_CKS_MASK 0x00030000
++#define SCC_EPCI_CLKRST_CKS_2 0x00000000
++#define SCC_EPCI_CLKRST_CKS_4 0x00010000
++#define SCC_EPCI_CLKRST_CKS_8 0x00020000
++#define SCC_EPCI_CLKRST_PCICRST 0x00000400
++#define SCC_EPCI_CLKRST_BC 0x00000200
++#define SCC_EPCI_CLKRST_PCIRST 0x00000100
++#define SCC_EPCI_CLKRST_PCKEN 0x00000001
++
++/* bits for SCC_EPCI_INTSET/SCC_EPCI_STATUS */
++#define SCC_EPCI_INT_2M 0x01000000
++#define SCC_EPCI_INT_RERR 0x00200000
++#define SCC_EPCI_INT_SERR 0x00100000
++#define SCC_EPCI_INT_PRTER 0x00080000
++#define SCC_EPCI_INT_SER 0x00040000
++#define SCC_EPCI_INT_PER 0x00020000
++#define SCC_EPCI_INT_PAI 0x00010000
++#define SCC_EPCI_INT_1M 0x00000100
++#define SCC_EPCI_INT_PME 0x00000010
++#define SCC_EPCI_INT_INTD 0x00000008
++#define SCC_EPCI_INT_INTC 0x00000004
++#define SCC_EPCI_INT_INTB 0x00000002
++#define SCC_EPCI_INT_INTA 0x00000001
++#define SCC_EPCI_INT_DEVINT 0x0000000f
++#define SCC_EPCI_INT_ALL 0x003f001f
++#define SCC_EPCI_INT_ALLERR 0x003f0000
++
++/* bits for SCC_EPCI_CKCTRL */
++#define SCC_EPCI_CKCTRL_CRST0 0x00010000
++#define SCC_EPCI_CKCTRL_CRST1 0x00020000
++#define SCC_EPCI_CKCTRL_OCLKEN 0x00000100
++#define SCC_EPCI_CKCTRL_LCLKEN 0x00000001
++
++#define SCC_EPCI_IDSEL_AD_TO_SLOT(ad) ((ad) - 10)
++#define SCC_EPCI_MAX_DEVNU SCC_EPCI_IDSEL_AD_TO_SLOT(32)
++
++/* bits for SCC_EPCI_CNTOPT */
++#define SCC_EPCI_CNTOPT_O2PMB 0x00000002
++
++/* SCC PCIEXC SMMIO registers */
++#define PEXCADRS 0x000
++#define PEXCWDATA 0x004
++#define PEXCRDATA 0x008
++#define PEXDADRS 0x010
++#define PEXDCMND 0x014
++#define PEXDWDATA 0x018
++#define PEXDRDATA 0x01c
++#define PEXREQID 0x020
++#define PEXTIDMAP 0x024
++#define PEXINTMASK 0x028
++#define PEXINTSTS 0x02c
++#define PEXAERRMASK 0x030
++#define PEXAERRSTS 0x034
++#define PEXPRERRMASK 0x040
++#define PEXPRERRSTS 0x044
++#define PEXPRERRID01 0x048
++#define PEXPRERRID23 0x04c
++#define PEXVDMASK 0x050
++#define PEXVDSTS 0x054
++#define PEXRCVCPLIDA 0x060
++#define PEXLENERRIDA 0x068
++#define PEXPHYPLLST 0x070
++#define PEXDMRDEN0 0x100
++#define PEXDMRDADR0 0x104
++#define PEXDMRDENX 0x110
++#define PEXDMRDADRX 0x114
++#define PEXECMODE 0xf00
++#define PEXMAEA(n) (0xf50 + (8 * n))
++#define PEXMAEC(n) (0xf54 + (8 * n))
++#define PEXCCRCTRL 0xff0
++
++/* SCC PCIEXC bits and shifts for PEXCADRS */
++#define PEXCADRS_BYTE_EN_SHIFT 20
++#define PEXCADRS_CMD_SHIFT 16
++#define PEXCADRS_CMD_READ (0xa << PEXCADRS_CMD_SHIFT)
++#define PEXCADRS_CMD_WRITE (0xb << PEXCADRS_CMD_SHIFT)
++
++/* SCC PCIEXC shifts for PEXDADRS */
++#define PEXDADRS_BUSNO_SHIFT 20
++#define PEXDADRS_DEVNO_SHIFT 15
++#define PEXDADRS_FUNCNO_SHIFT 12
++
++/* SCC PCIEXC bits and shifts for PEXDCMND */
++#define PEXDCMND_BYTE_EN_SHIFT 4
++#define PEXDCMND_IO_READ 0x2
++#define PEXDCMND_IO_WRITE 0x3
++#define PEXDCMND_CONFIG_READ 0xa
++#define PEXDCMND_CONFIG_WRITE 0xb
++
++/* SCC PCIEXC bits for PEXPHYPLLST */
++#define PEXPHYPLLST_PEXPHYAPLLST 0x00000001
++
++/* SCC PCIEXC bits for PEXECMODE */
++#define PEXECMODE_ALL_THROUGH 0x00000000
++#define PEXECMODE_ALL_8BIT 0x00550155
++#define PEXECMODE_ALL_16BIT 0x00aa02aa
++
++/* SCC PCIEXC bits for PEXCCRCTRL */
++#define PEXCCRCTRL_PEXIPCOREEN 0x00040000
++#define PEXCCRCTRL_PEXIPCONTEN 0x00020000
++#define PEXCCRCTRL_PEXPHYPLLEN 0x00010000
++#define PEXCCRCTRL_PCIEXCAOCKEN 0x00000100
++
++/* SCC PCIEXC port configuration registers */
++#define PEXTCERRCHK 0x21c
++#define PEXTAMAPB0 0x220
++#define PEXTAMAPL0 0x224
++#define PEXTAMAPB(n) (PEXTAMAPB0 + 8 * (n))
++#define PEXTAMAPL(n) (PEXTAMAPL0 + 8 * (n))
++#define PEXCHVC0P 0x500
++#define PEXCHVC0NP 0x504
++#define PEXCHVC0C 0x508
++#define PEXCDVC0P 0x50c
++#define PEXCDVC0NP 0x510
++#define PEXCDVC0C 0x514
++#define PEXCHVCXP 0x518
++#define PEXCHVCXNP 0x51c
++#define PEXCHVCXC 0x520
++#define PEXCDVCXP 0x524
++#define PEXCDVCXNP 0x528
++#define PEXCDVCXC 0x52c
++#define PEXCTTRG 0x530
++#define PEXTSCTRL 0x700
++#define PEXTSSTS 0x704
++#define PEXSKPCTRL 0x708
++
++/* UHC registers */
++#define SCC_UHC_CKRCTRL 0xff0
++#define SCC_UHC_ECMODE 0xf00
++
++/* bits for SCC_UHC_CKRCTRL */
++#define SCC_UHC_F48MCKLEN 0x00000001
++#define SCC_UHC_P_SUSPEND 0x00000002
++#define SCC_UHC_PHY_SUSPEND_SEL 0x00000004
++#define SCC_UHC_HCLKEN 0x00000100
++#define SCC_UHC_USBEN 0x00010000
++#define SCC_UHC_USBCEN 0x00020000
++#define SCC_UHC_PHYEN 0x00040000
++
++/* bits for SCC_UHC_ECMODE */
++#define SCC_UHC_ECMODE_BY_BYTE 0x00000555
++#define SCC_UHC_ECMODE_BY_WORD 0x00000aaa
++
++#endif /* _CELLEB_SCC_H */
+diff --git a/arch/powerpc/platforms/cell/celleb_scc_epci.c b/arch/powerpc/platforms/cell/celleb_scc_epci.c
+new file mode 100644
+index 0000000..08c285b
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/celleb_scc_epci.c
+@@ -0,0 +1,438 @@
++/*
++ * Support for SCC external PCI
++ *
++ * (C) Copyright 2004-2007 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; 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.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#undef DEBUG
++
++#include <linux/kernel.h>
++#include <linux/threads.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/pci_regs.h>
++#include <linux/bootmem.h>
++
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/prom.h>
++#include <asm/pci-bridge.h>
++#include <asm/ppc-pci.h>
++
++#include "celleb_scc.h"
++#include "celleb_pci.h"
++
++#define MAX_PCI_DEVICES 32
++#define MAX_PCI_FUNCTIONS 8
++
++#define iob() __asm__ __volatile__("eieio; sync":::"memory")
++
++static inline PCI_IO_ADDR celleb_epci_get_epci_base(
++ struct pci_controller *hose)
++{
++ /*
++ * Note:
++ * Celleb epci uses cfg_addr as a base address for
++ * epci control registers.
++ */
++
++ return hose->cfg_addr;
++}
++
++static inline PCI_IO_ADDR celleb_epci_get_epci_cfg(
++ struct pci_controller *hose)
++{
++ /*
++ * Note:
++ * Celleb epci uses cfg_data as a base address for
++ * configuration area for epci devices.
++ */
++
++ return hose->cfg_data;
++}
++
++static inline void clear_and_disable_master_abort_interrupt(
++ struct pci_controller *hose)
++{
++ PCI_IO_ADDR epci_base;
++ PCI_IO_ADDR reg;
++ epci_base = celleb_epci_get_epci_base(hose);
++ reg = epci_base + PCI_COMMAND;
++ out_be32(reg, in_be32(reg) | (PCI_STATUS_REC_MASTER_ABORT << 16));
++}
++
++static int celleb_epci_check_abort(struct pci_controller *hose,
++ PCI_IO_ADDR addr)
++{
++ PCI_IO_ADDR reg;
++ PCI_IO_ADDR epci_base;
++ u32 val;
++
++ iob();
++ epci_base = celleb_epci_get_epci_base(hose);
++
++ reg = epci_base + PCI_COMMAND;
++ val = in_be32(reg);
++
++ if (val & (PCI_STATUS_REC_MASTER_ABORT << 16)) {
++ out_be32(reg,
++ (val & 0xffff) | (PCI_STATUS_REC_MASTER_ABORT << 16));
++
++ /* clear PCI Controller error, FRE, PMFE */
++ reg = epci_base + SCC_EPCI_STATUS;
++ out_be32(reg, SCC_EPCI_INT_PAI);
++
++ reg = epci_base + SCC_EPCI_VCSR;
++ val = in_be32(reg) & 0xffff;
++ val |= SCC_EPCI_VCSR_FRE;
++ out_be32(reg, val);
++
++ reg = epci_base + SCC_EPCI_VISTAT;
++ out_be32(reg, SCC_EPCI_VISTAT_PMFE);
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ }
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static PCI_IO_ADDR celleb_epci_make_config_addr(struct pci_bus *bus,
++ struct pci_controller *hose, unsigned int devfn, int where)
++{
++ PCI_IO_ADDR addr;
++
++ if (bus != hose->bus)
++ addr = celleb_epci_get_epci_cfg(hose) +
++ (((bus->number & 0xff) << 16)
++ | ((devfn & 0xff) << 8)
++ | (where & 0xff)
++ | 0x01000000);
++ else
++ addr = celleb_epci_get_epci_cfg(hose) +
++ (((devfn & 0xff) << 8) | (where & 0xff));
++
++ pr_debug("EPCI: config_addr = 0x%p\n", addr);
++
++ return addr;
++}
++
++static int celleb_epci_read_config(struct pci_bus *bus,
++ unsigned int devfn, int where, int size, u32 *val)
++{
++ PCI_IO_ADDR epci_base;
++ PCI_IO_ADDR addr;
++ struct device_node *node;
++ struct pci_controller *hose;
++
++ /* allignment check */
++ BUG_ON(where % size);
++
++ node = (struct device_node *)bus->sysdata;
++ hose = pci_find_hose_for_OF_device(node);
++
++ if (!celleb_epci_get_epci_cfg(hose))
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ if (bus->number == hose->first_busno && devfn == 0) {
++ /* EPCI controller self */
++
++ epci_base = celleb_epci_get_epci_base(hose);
++ addr = epci_base + where;
++
++ switch (size) {
++ case 1:
++ *val = in_8(addr);
++ break;
++ case 2:
++ *val = in_be16(addr);
++ break;
++ case 4:
++ *val = in_be32(addr);
++ break;
++ default:
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ }
++
++ } else {
++
++ clear_and_disable_master_abort_interrupt(hose);
++ addr = celleb_epci_make_config_addr(bus, hose, devfn, where);
++
++ switch (size) {
++ case 1:
++ *val = in_8(addr);
++ break;
++ case 2:
++ *val = in_le16(addr);
++ break;
++ case 4:
++ *val = in_le32(addr);
++ break;
++ default:
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ }
++ }
++
++ pr_debug("EPCI: "
++ "addr=0x%p, devfn=0x%x, where=0x%x, size=0x%x, val=0x%x\n",
++ addr, devfn, where, size, *val);
++
++ return celleb_epci_check_abort(hose, NULL);
++}
++
++static int celleb_epci_write_config(struct pci_bus *bus,
++ unsigned int devfn, int where, int size, u32 val)
++{
++ PCI_IO_ADDR epci_base;
++ PCI_IO_ADDR addr;
++ struct device_node *node;
++ struct pci_controller *hose;
++
++ /* allignment check */
++ BUG_ON(where % size);
++
++ node = (struct device_node *)bus->sysdata;
++ hose = pci_find_hose_for_OF_device(node);
++
++
++ if (!celleb_epci_get_epci_cfg(hose))
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ if (bus->number == hose->first_busno && devfn == 0) {
++ /* EPCI controller self */
++
++ epci_base = celleb_epci_get_epci_base(hose);
++ addr = epci_base + where;
++
++ switch (size) {
++ case 1:
++ out_8(addr, val);
++ break;
++ case 2:
++ out_be16(addr, val);
++ break;
++ case 4:
++ out_be32(addr, val);
++ break;
++ default:
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ }
++
++ } else {
++
++ clear_and_disable_master_abort_interrupt(hose);
++ addr = celleb_epci_make_config_addr(bus, hose, devfn, where);
++
++ switch (size) {
++ case 1:
++ out_8(addr, val);
++ break;
++ case 2:
++ out_le16(addr, val);
++ break;
++ case 4:
++ out_le32(addr, val);
++ break;
++ default:
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ }
++ }
++
++ return celleb_epci_check_abort(hose, addr);
++}
++
++struct pci_ops celleb_epci_ops = {
++ .read = celleb_epci_read_config,
++ .write = celleb_epci_write_config,
++};
++
++/* to be moved in FW */
++static int __init celleb_epci_init(struct pci_controller *hose)
++{
++ u32 val;
++ PCI_IO_ADDR reg;
++ PCI_IO_ADDR epci_base;
++ int hwres = 0;
++
++ epci_base = celleb_epci_get_epci_base(hose);
++
++ /* PCI core reset(Internal bus and PCI clock) */
++ reg = epci_base + SCC_EPCI_CKCTRL;
++ val = in_be32(reg);
++ if (val == 0x00030101)
++ hwres = 1;
++ else {
++ val &= ~(SCC_EPCI_CKCTRL_CRST0 | SCC_EPCI_CKCTRL_CRST1);
++ out_be32(reg, val);
++
++ /* set PCI core clock */
++ val = in_be32(reg);
++ val |= (SCC_EPCI_CKCTRL_OCLKEN | SCC_EPCI_CKCTRL_LCLKEN);
++ out_be32(reg, val);
++
++ /* release PCI core reset (internal bus) */
++ val = in_be32(reg);
++ val |= SCC_EPCI_CKCTRL_CRST0;
++ out_be32(reg, val);
++
++ /* set PCI clock select */
++ reg = epci_base + SCC_EPCI_CLKRST;
++ val = in_be32(reg);
++ val &= ~SCC_EPCI_CLKRST_CKS_MASK;
++ val |= SCC_EPCI_CLKRST_CKS_2;
++ out_be32(reg, val);
++
++ /* set arbiter */
++ reg = epci_base + SCC_EPCI_ABTSET;
++ out_be32(reg, 0x0f1f001f); /* temporary value */
++
++ /* buffer on */
++ reg = epci_base + SCC_EPCI_CLKRST;
++ val = in_be32(reg);
++ val |= SCC_EPCI_CLKRST_BC;
++ out_be32(reg, val);
++
++ /* PCI clock enable */
++ val = in_be32(reg);
++ val |= SCC_EPCI_CLKRST_PCKEN;
++ out_be32(reg, val);
++
++ /* release PCI core reset (all) */
++ reg = epci_base + SCC_EPCI_CKCTRL;
++ val = in_be32(reg);
++ val |= (SCC_EPCI_CKCTRL_CRST0 | SCC_EPCI_CKCTRL_CRST1);
++ out_be32(reg, val);
++
++ /* set base translation registers. (already set by Beat) */
++
++ /* set base address masks. (already set by Beat) */
++ }
++
++ /* release interrupt masks and clear all interrupts */
++ reg = epci_base + SCC_EPCI_INTSET;
++ out_be32(reg, 0x013f011f); /* all interrupts enable */
++ reg = epci_base + SCC_EPCI_VIENAB;
++ val = SCC_EPCI_VIENAB_PMPEE | SCC_EPCI_VIENAB_PMFEE;
++ out_be32(reg, val);
++ reg = epci_base + SCC_EPCI_STATUS;
++ out_be32(reg, 0xffffffff);
++ reg = epci_base + SCC_EPCI_VISTAT;
++ out_be32(reg, 0xffffffff);
++
++ /* disable PCI->IB address translation */
++ reg = epci_base + SCC_EPCI_VCSR;
++ val = in_be32(reg);
++ val &= ~(SCC_EPCI_VCSR_DR | SCC_EPCI_VCSR_AT);
++ out_be32(reg, val);
++
++ /* set base addresses. (no need to set?) */
++
++ /* memory space, bus master enable */
++ reg = epci_base + PCI_COMMAND;
++ val = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
++ out_be32(reg, val);
++
++ /* endian mode setup */
++ reg = epci_base + SCC_EPCI_ECMODE;
++ val = 0x00550155;
++ out_be32(reg, val);
++
++ /* set control option */
++ reg = epci_base + SCC_EPCI_CNTOPT;
++ val = in_be32(reg);
++ val |= SCC_EPCI_CNTOPT_O2PMB;
++ out_be32(reg, val);
++
++ /* XXX: temporay: set registers for address conversion setup */
++ reg = epci_base + SCC_EPCI_CNF10_REG;
++ out_be32(reg, 0x80000008);
++ reg = epci_base + SCC_EPCI_CNF14_REG;
++ out_be32(reg, 0x40000008);
++
++ reg = epci_base + SCC_EPCI_BAM0;
++ out_be32(reg, 0x80000000);
++ reg = epci_base + SCC_EPCI_BAM1;
++ out_be32(reg, 0xe0000000);
++
++ reg = epci_base + SCC_EPCI_PVBAT;
++ out_be32(reg, 0x80000000);
++
++ if (!hwres) {
++ /* release external PCI reset */
++ reg = epci_base + SCC_EPCI_CLKRST;
++ val = in_be32(reg);
++ val |= SCC_EPCI_CLKRST_PCIRST;
++ out_be32(reg, val);
++ }
++
++ return 0;
++}
++
++static int __init celleb_setup_epci(struct device_node *node,
++ struct pci_controller *hose)
++{
++ struct resource r;
++
++ pr_debug("PCI: celleb_setup_epci()\n");
++
++ /*
++ * Note:
++ * Celleb epci uses cfg_addr and cfg_data member of
++ * pci_controller structure in irregular way.
++ *
++ * cfg_addr is used to map for control registers of
++ * celleb epci.
++ *
++ * cfg_data is used for configuration area of devices
++ * on Celleb epci buses.
++ */
++
++ if (of_address_to_resource(node, 0, &r))
++ goto error;
++ hose->cfg_addr = ioremap(r.start, (r.end - r.start + 1));
++ if (!hose->cfg_addr)
++ goto error;
++ pr_debug("EPCI: cfg_addr map 0x%016lx->0x%016lx + 0x%016lx\n",
++ r.start, (unsigned long)hose->cfg_addr, (r.end - r.start + 1));
++
++ if (of_address_to_resource(node, 2, &r))
++ goto error;
++ hose->cfg_data = ioremap(r.start, (r.end - r.start + 1));
++ if (!hose->cfg_data)
++ goto error;
++ pr_debug("EPCI: cfg_data map 0x%016lx->0x%016lx + 0x%016lx\n",
++ r.start, (unsigned long)hose->cfg_data, (r.end - r.start + 1));
++
++ hose->ops = &celleb_epci_ops;
++ celleb_epci_init(hose);
++
++ return 0;
++
++error:
++ if (hose->cfg_addr)
++ iounmap(hose->cfg_addr);
++
++ if (hose->cfg_data)
++ iounmap(hose->cfg_data);
++ return 1;
++}
++
++struct celleb_phb_spec celleb_epci_spec __initdata = {
++ .setup = celleb_setup_epci,
++ .ops = &spiderpci_ops,
++ .iowa_init = &spiderpci_iowa_init,
++ .iowa_data = (void *)0,
++};
+diff --git a/arch/powerpc/platforms/cell/celleb_scc_pciex.c b/arch/powerpc/platforms/cell/celleb_scc_pciex.c
+new file mode 100644
+index 0000000..ab24d94
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/celleb_scc_pciex.c
+@@ -0,0 +1,547 @@
++/*
++ * Support for Celleb PCI-Express.
++ *
++ * (C) Copyright 2007-2008 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; 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.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#undef DEBUG
++
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/string.h>
++#include <linux/init.h>
++#include <linux/bootmem.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/iommu.h>
++#include <asm/byteorder.h>
++
++#include "celleb_scc.h"
++#include "celleb_pci.h"
++
++#define PEX_IN(base, off) in_be32((void *)(base) + (off))
++#define PEX_OUT(base, off, data) out_be32((void *)(base) + (off), (data))
++
++static void scc_pciex_io_flush(struct iowa_bus *bus)
++{
++ (void)PEX_IN(bus->phb->cfg_addr, PEXDMRDEN0);
++}
++
++/*
++ * Memory space access to device on PCIEX
++ */
++#define PCIEX_MMIO_READ(name, ret) \
++static ret scc_pciex_##name(const PCI_IO_ADDR addr) \
++{ \
++ ret val = __do_##name(addr); \
++ scc_pciex_io_flush(iowa_mem_find_bus(addr)); \
++ return val; \
++}
++
++#define PCIEX_MMIO_READ_STR(name) \
++static void scc_pciex_##name(const PCI_IO_ADDR addr, void *buf, \
++ unsigned long count) \
++{ \
++ __do_##name(addr, buf, count); \
++ scc_pciex_io_flush(iowa_mem_find_bus(addr)); \
++}
++
++PCIEX_MMIO_READ(readb, u8)
++PCIEX_MMIO_READ(readw, u16)
++PCIEX_MMIO_READ(readl, u32)
++PCIEX_MMIO_READ(readq, u64)
++PCIEX_MMIO_READ(readw_be, u16)
++PCIEX_MMIO_READ(readl_be, u32)
++PCIEX_MMIO_READ(readq_be, u64)
++PCIEX_MMIO_READ_STR(readsb)
++PCIEX_MMIO_READ_STR(readsw)
++PCIEX_MMIO_READ_STR(readsl)
++
++static void scc_pciex_memcpy_fromio(void *dest, const PCI_IO_ADDR src,
++ unsigned long n)
++{
++ __do_memcpy_fromio(dest, src, n);
++ scc_pciex_io_flush(iowa_mem_find_bus(src));
++}
++
++/*
++ * I/O port access to devices on PCIEX.
++ */
++
++static inline unsigned long get_bus_address(struct pci_controller *phb,
++ unsigned long port)
++{
++ return port - ((unsigned long)(phb->io_base_virt) - _IO_BASE);
++}
++
++static u32 scc_pciex_read_port(struct pci_controller *phb,
++ unsigned long port, int size)
++{
++ unsigned int byte_enable;
++ unsigned int cmd, shift;
++ unsigned long addr;
++ u32 data, ret;
++
++ BUG_ON(((port & 0x3ul) + size) > 4);
++
++ addr = get_bus_address(phb, port);
++ shift = addr & 0x3ul;
++ byte_enable = ((1 << size) - 1) << shift;
++ cmd = PEXDCMND_IO_READ | (byte_enable << PEXDCMND_BYTE_EN_SHIFT);
++ PEX_OUT(phb->cfg_addr, PEXDADRS, (addr & ~0x3ul));
++ PEX_OUT(phb->cfg_addr, PEXDCMND, cmd);
++ data = PEX_IN(phb->cfg_addr, PEXDRDATA);
++ ret = (data >> (shift * 8)) & (0xFFFFFFFF >> ((4 - size) * 8));
++
++ pr_debug("PCIEX:PIO READ:port=0x%lx, addr=0x%lx, size=%d, be=%x,"
++ " cmd=%x, data=%x, ret=%x\n", port, addr, size, byte_enable,
++ cmd, data, ret);
++
++ return ret;
++}
++
++static void scc_pciex_write_port(struct pci_controller *phb,
++ unsigned long port, int size, u32 val)
++{
++ unsigned int byte_enable;
++ unsigned int cmd, shift;
++ unsigned long addr;
++ u32 data;
++
++ BUG_ON(((port & 0x3ul) + size) > 4);
++
++ addr = get_bus_address(phb, port);
++ shift = addr & 0x3ul;
++ byte_enable = ((1 << size) - 1) << shift;
++ cmd = PEXDCMND_IO_WRITE | (byte_enable << PEXDCMND_BYTE_EN_SHIFT);
++ data = (val & (0xFFFFFFFF >> (4 - size) * 8)) << (shift * 8);
++ PEX_OUT(phb->cfg_addr, PEXDADRS, (addr & ~0x3ul));
++ PEX_OUT(phb->cfg_addr, PEXDCMND, cmd);
++ PEX_OUT(phb->cfg_addr, PEXDWDATA, data);
++
++ pr_debug("PCIEX:PIO WRITE:port=0x%lx, addr=%lx, size=%d, val=%x,"
++ " be=%x, cmd=%x, data=%x\n", port, addr, size, val,
++ byte_enable, cmd, data);
++}
++
++static u8 __scc_pciex_inb(struct pci_controller *phb, unsigned long port)
++{
++ return (u8)scc_pciex_read_port(phb, port, 1);
++}
++
++static u16 __scc_pciex_inw(struct pci_controller *phb, unsigned long port)
++{
++ u32 data;
++ if ((port & 0x3ul) < 3)
++ data = scc_pciex_read_port(phb, port, 2);
++ else {
++ u32 d1 = scc_pciex_read_port(phb, port, 1);
++ u32 d2 = scc_pciex_read_port(phb, port + 1, 1);
++ data = d1 | (d2 << 8);
++ }
++ return (u16)data;
++}
++
++static u32 __scc_pciex_inl(struct pci_controller *phb, unsigned long port)
++{
++ unsigned int mod = port & 0x3ul;
++ u32 data;
++ if (mod == 0)
++ data = scc_pciex_read_port(phb, port, 4);
++ else {
++ u32 d1 = scc_pciex_read_port(phb, port, 4 - mod);
++ u32 d2 = scc_pciex_read_port(phb, port + 1, mod);
++ data = d1 | (d2 << (mod * 8));
++ }
++ return data;
++}
++
++static void __scc_pciex_outb(struct pci_controller *phb,
++ u8 val, unsigned long port)
++{
++ scc_pciex_write_port(phb, port, 1, (u32)val);
++}
++
++static void __scc_pciex_outw(struct pci_controller *phb,
++ u16 val, unsigned long port)
++{
++ if ((port & 0x3ul) < 3)
++ scc_pciex_write_port(phb, port, 2, (u32)val);
++ else {
++ u32 d1 = val & 0x000000FF;
++ u32 d2 = (val & 0x0000FF00) >> 8;
++ scc_pciex_write_port(phb, port, 1, d1);
++ scc_pciex_write_port(phb, port + 1, 1, d2);
++ }
++}
++
++static void __scc_pciex_outl(struct pci_controller *phb,
++ u32 val, unsigned long port)
++{
++ unsigned int mod = port & 0x3ul;
++ if (mod == 0)
++ scc_pciex_write_port(phb, port, 4, val);
++ else {
++ u32 d1 = val & (0xFFFFFFFFul >> (mod * 8));
++ u32 d2 = val >> ((4 - mod) * 8);
++ scc_pciex_write_port(phb, port, 4 - mod, d1);
++ scc_pciex_write_port(phb, port + 1, mod, d2);
++ }
++}
++
++#define PCIEX_PIO_FUNC(size, name) \
++static u##size scc_pciex_in##name(unsigned long port) \
++{ \
++ struct iowa_bus *bus = iowa_pio_find_bus(port); \
++ u##size data = __scc_pciex_in##name(bus->phb, port); \
++ scc_pciex_io_flush(bus); \
++ return data; \
++} \
++static void scc_pciex_ins##name(unsigned long p, void *b, unsigned long c) \
++{ \
++ struct iowa_bus *bus = iowa_pio_find_bus(p); \
++ u##size *dst = b; \
++ for (; c != 0; c--, dst++) \
++ *dst = cpu_to_le##size(__scc_pciex_in##name(bus->phb, p)); \
++ scc_pciex_io_flush(bus); \
++} \
++static void scc_pciex_out##name(u##size val, unsigned long port) \
++{ \
++ struct iowa_bus *bus = iowa_pio_find_bus(port); \
++ __scc_pciex_out##name(bus->phb, val, port); \
++} \
++static void scc_pciex_outs##name(unsigned long p, const void *b, \
++ unsigned long c) \
++{ \
++ struct iowa_bus *bus = iowa_pio_find_bus(p); \
++ const u##size *src = b; \
++ for (; c != 0; c--, src++) \
++ __scc_pciex_out##name(bus->phb, le##size##_to_cpu(*src), p); \
++}
++#define cpu_to_le8(x) (x)
++#define le8_to_cpu(x) (x)
++PCIEX_PIO_FUNC(8, b)
++PCIEX_PIO_FUNC(16, w)
++PCIEX_PIO_FUNC(32, l)
++
++static struct ppc_pci_io scc_pciex_ops = {
++ .readb = scc_pciex_readb,
++ .readw = scc_pciex_readw,
++ .readl = scc_pciex_readl,
++ .readq = scc_pciex_readq,
++ .readw_be = scc_pciex_readw_be,
++ .readl_be = scc_pciex_readl_be,
++ .readq_be = scc_pciex_readq_be,
++ .readsb = scc_pciex_readsb,
++ .readsw = scc_pciex_readsw,
++ .readsl = scc_pciex_readsl,
++ .memcpy_fromio = scc_pciex_memcpy_fromio,
++ .inb = scc_pciex_inb,
++ .inw = scc_pciex_inw,
++ .inl = scc_pciex_inl,
++ .outb = scc_pciex_outb,
++ .outw = scc_pciex_outw,
++ .outl = scc_pciex_outl,
++ .insb = scc_pciex_insb,
++ .insw = scc_pciex_insw,
++ .insl = scc_pciex_insl,
++ .outsb = scc_pciex_outsb,
++ .outsw = scc_pciex_outsw,
++ .outsl = scc_pciex_outsl,
++};
++
++static int __init scc_pciex_iowa_init(struct iowa_bus *bus, void *data)
++{
++ dma_addr_t dummy_page_da;
++ void *dummy_page_va;
++
++ dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL);
++ if (!dummy_page_va) {
++ pr_err("PCIEX:Alloc dummy_page_va failed\n");
++ return -1;
++ }
++
++ dummy_page_da = dma_map_single(bus->phb->parent, dummy_page_va,
++ PAGE_SIZE, DMA_FROM_DEVICE);
++ if (dma_mapping_error(dummy_page_da)) {
++ pr_err("PCIEX:Map dummy page failed.\n");
++ kfree(dummy_page_va);
++ return -1;
++ }
++
++ PEX_OUT(bus->phb->cfg_addr, PEXDMRDADR0, dummy_page_da);
++
++ return 0;
++}
++
++/*
++ * config space access
++ */
++#define MK_PEXDADRS(bus_no, dev_no, func_no, addr) \
++ ((uint32_t)(((addr) & ~0x3UL) | \
++ ((bus_no) << PEXDADRS_BUSNO_SHIFT) | \
++ ((dev_no) << PEXDADRS_DEVNO_SHIFT) | \
++ ((func_no) << PEXDADRS_FUNCNO_SHIFT)))
++
++#define MK_PEXDCMND_BYTE_EN(addr, size) \
++ ((((0x1 << (size))-1) << ((addr) & 0x3)) << PEXDCMND_BYTE_EN_SHIFT)
++#define MK_PEXDCMND(cmd, addr, size) ((cmd) | MK_PEXDCMND_BYTE_EN(addr, size))
++
++static uint32_t config_read_pciex_dev(unsigned int *base,
++ uint64_t bus_no, uint64_t dev_no, uint64_t func_no,
++ uint64_t off, uint64_t size)
++{
++ uint32_t ret;
++ uint32_t addr, cmd;
++
++ addr = MK_PEXDADRS(bus_no, dev_no, func_no, off);
++ cmd = MK_PEXDCMND(PEXDCMND_CONFIG_READ, off, size);
++ PEX_OUT(base, PEXDADRS, addr);
++ PEX_OUT(base, PEXDCMND, cmd);
++ ret = (PEX_IN(base, PEXDRDATA)
++ >> ((off & (4-size)) * 8)) & ((0x1 << (size * 8)) - 1);
++ return ret;
++}
++
++static void config_write_pciex_dev(unsigned int *base, uint64_t bus_no,
++ uint64_t dev_no, uint64_t func_no, uint64_t off, uint64_t size,
++ uint32_t data)
++{
++ uint32_t addr, cmd;
++
++ addr = MK_PEXDADRS(bus_no, dev_no, func_no, off);
++ cmd = MK_PEXDCMND(PEXDCMND_CONFIG_WRITE, off, size);
++ PEX_OUT(base, PEXDADRS, addr);
++ PEX_OUT(base, PEXDCMND, cmd);
++ PEX_OUT(base, PEXDWDATA,
++ (data & ((0x1 << (size * 8)) - 1)) << ((off & (4-size)) * 8));
++}
++
++#define MK_PEXCADRS_BYTE_EN(off, len) \
++ ((((0x1 << (len)) - 1) << ((off) & 0x3)) << PEXCADRS_BYTE_EN_SHIFT)
++#define MK_PEXCADRS(cmd, addr, size) \
++ ((cmd) | MK_PEXCADRS_BYTE_EN(addr, size) | ((addr) & ~0x3))
++static uint32_t config_read_pciex_rc(unsigned int *base,
++ uint32_t where, uint32_t size)
++{
++ PEX_OUT(base, PEXCADRS, MK_PEXCADRS(PEXCADRS_CMD_READ, where, size));
++ return (PEX_IN(base, PEXCRDATA)
++ >> ((where & (4 - size)) * 8)) & ((0x1 << (size * 8)) - 1);
++}
++
++static void config_write_pciex_rc(unsigned int *base, uint32_t where,
++ uint32_t size, uint32_t val)
++{
++ uint32_t data;
++
++ data = (val & ((0x1 << (size * 8)) - 1)) << ((where & (4 - size)) * 8);
++ PEX_OUT(base, PEXCADRS, MK_PEXCADRS(PEXCADRS_CMD_WRITE, where, size));
++ PEX_OUT(base, PEXCWDATA, data);
++}
++
++/* Interfaces */
++/* Note: Work-around
++ * On SCC PCIEXC, one device is seen on all 32 dev_no.
++ * As SCC PCIEXC can have only one device on the bus, we look only one dev_no.
++ * (dev_no = 1)
++ */
++static int scc_pciex_read_config(struct pci_bus *bus, unsigned int devfn,
++ int where, int size, unsigned int *val)
++{
++ struct device_node *dn;
++ struct pci_controller *phb;
++
++ dn = bus->sysdata;
++ phb = pci_find_hose_for_OF_device(dn);
++
++ if (bus->number == phb->first_busno && PCI_SLOT(devfn) != 1) {
++ *val = ~0;
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ }
++
++ if (bus->number == 0 && PCI_SLOT(devfn) == 0)
++ *val = config_read_pciex_rc(phb->cfg_addr, where, size);
++ else
++ *val = config_read_pciex_dev(phb->cfg_addr, bus->number,
++ PCI_SLOT(devfn), PCI_FUNC(devfn), where, size);
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static int scc_pciex_write_config(struct pci_bus *bus, unsigned int devfn,
++ int where, int size, unsigned int val)
++{
++ struct device_node *dn;
++ struct pci_controller *phb;
++
++ dn = bus->sysdata;
++ phb = pci_find_hose_for_OF_device(dn);
++
++ if (bus->number == phb->first_busno && PCI_SLOT(devfn) != 1)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ if (bus->number == 0 && PCI_SLOT(devfn) == 0)
++ config_write_pciex_rc(phb->cfg_addr, where, size, val);
++ else
++ config_write_pciex_dev(phb->cfg_addr, bus->number,
++ PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, val);
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static struct pci_ops scc_pciex_pci_ops = {
++ scc_pciex_read_config,
++ scc_pciex_write_config,
++};
++
++static void pciex_clear_intr_all(unsigned int *base)
++{
++ PEX_OUT(base, PEXAERRSTS, 0xffffffff);
++ PEX_OUT(base, PEXPRERRSTS, 0xffffffff);
++ PEX_OUT(base, PEXINTSTS, 0xffffffff);
++}
++
++#if 0
++static void pciex_disable_intr_all(unsigned int *base)
++{
++ PEX_OUT(base, PEXINTMASK, 0x0);
++ PEX_OUT(base, PEXAERRMASK, 0x0);
++ PEX_OUT(base, PEXPRERRMASK, 0x0);
++ PEX_OUT(base, PEXVDMASK, 0x0);
++}
++#endif
++
++static void pciex_enable_intr_all(unsigned int *base)
++{
++ PEX_OUT(base, PEXINTMASK, 0x0000e7f1);
++ PEX_OUT(base, PEXAERRMASK, 0x03ff01ff);
++ PEX_OUT(base, PEXPRERRMASK, 0x0001010f);
++ PEX_OUT(base, PEXVDMASK, 0x00000001);
++}
++
++static void pciex_check_status(unsigned int *base)
++{
++ uint32_t err = 0;
++ uint32_t intsts, aerr, prerr, rcvcp, lenerr;
++ uint32_t maea, maec;
++
++ intsts = PEX_IN(base, PEXINTSTS);
++ aerr = PEX_IN(base, PEXAERRSTS);
++ prerr = PEX_IN(base, PEXPRERRSTS);
++ rcvcp = PEX_IN(base, PEXRCVCPLIDA);
++ lenerr = PEX_IN(base, PEXLENERRIDA);
++
++ if (intsts || aerr || prerr || rcvcp || lenerr)
++ err = 1;
++
++ pr_info("PCEXC interrupt!!\n");
++ pr_info("PEXINTSTS :0x%08x\n", intsts);
++ pr_info("PEXAERRSTS :0x%08x\n", aerr);
++ pr_info("PEXPRERRSTS :0x%08x\n", prerr);
++ pr_info("PEXRCVCPLIDA :0x%08x\n", rcvcp);
++ pr_info("PEXLENERRIDA :0x%08x\n", lenerr);
++
++ /* print detail of Protection Error */
++ if (intsts & 0x00004000) {
++ uint32_t i, n;
++ for (i = 0; i < 4; i++) {
++ n = 1 << i;
++ if (prerr & n) {
++ maea = PEX_IN(base, PEXMAEA(i));
++ maec = PEX_IN(base, PEXMAEC(i));
++ pr_info("PEXMAEC%d :0x%08x\n", i, maec);
++ pr_info("PEXMAEA%d :0x%08x\n", i, maea);
++ }
++ }
++ }
++
++ if (err)
++ pciex_clear_intr_all(base);
++}
++
++static irqreturn_t pciex_handle_internal_irq(int irq, void *dev_id)
++{
++ struct pci_controller *phb = dev_id;
++
++ pr_debug("PCIEX:pciex_handle_internal_irq(irq=%d)\n", irq);
++
++ BUG_ON(phb->cfg_addr == NULL);
++
++ pciex_check_status(phb->cfg_addr);
++
++ return IRQ_HANDLED;
++}
++
++static __init int celleb_setup_pciex(struct device_node *node,
++ struct pci_controller *phb)
++{
++ struct resource r;
++ struct of_irq oirq;
++ int virq;
++
++ /* SMMIO registers; used inside this file */
++ if (of_address_to_resource(node, 0, &r)) {
++ pr_err("PCIEXC:Failed to get config resource.\n");
++ return 1;
++ }
++ phb->cfg_addr = ioremap(r.start, r.end - r.start + 1);
++ if (!phb->cfg_addr) {
++ pr_err("PCIEXC:Failed to remap SMMIO region.\n");
++ return 1;
++ }
++
++ /* Not use cfg_data, cmd and data regs are near address reg */
++ phb->cfg_data = NULL;
++
++ /* set pci_ops */
++ phb->ops = &scc_pciex_pci_ops;
++
++ /* internal interrupt handler */
++ if (of_irq_map_one(node, 1, &oirq)) {
++ pr_err("PCIEXC:Failed to map irq\n");
++ goto error;
++ }
++ virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
++ oirq.size);
++ if (request_irq(virq, pciex_handle_internal_irq,
++ IRQF_DISABLED, "pciex", (void *)phb)) {
++ pr_err("PCIEXC:Failed to request irq\n");
++ goto error;
++ }
++
++ /* enable all interrupts */
++ pciex_clear_intr_all(phb->cfg_addr);
++ pciex_enable_intr_all(phb->cfg_addr);
++ /* MSI: TBD */
++
++ return 0;
++
++error:
++ phb->cfg_data = NULL;
++ if (phb->cfg_addr)
++ iounmap(phb->cfg_addr);
++ phb->cfg_addr = NULL;
++ return 1;
++}
++
++struct celleb_phb_spec celleb_pciex_spec __initdata = {
++ .setup = celleb_setup_pciex,
++ .ops = &scc_pciex_ops,
++ .iowa_init = &scc_pciex_iowa_init,
++};
+diff --git a/arch/powerpc/platforms/cell/celleb_scc_sio.c b/arch/powerpc/platforms/cell/celleb_scc_sio.c
+new file mode 100644
+index 0000000..3a16c5b
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/celleb_scc_sio.c
+@@ -0,0 +1,101 @@
++/*
++ * setup serial port in SCC
++ *
++ * (C) Copyright 2006-2007 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; 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.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#include <linux/tty.h>
++#include <linux/serial.h>
++#include <linux/serial_core.h>
++#include <linux/console.h>
++
++#include <asm/io.h>
++#include <asm/prom.h>
++
++/* sio irq0=0xb00010022 irq0=0xb00010023 irq2=0xb00010024
++ mmio=0xfff000-0x1000,0xff2000-0x1000 */
++static int txx9_serial_bitmap __initdata;
++
++static struct {
++ uint32_t offset;
++ uint32_t index;
++} txx9_scc_tab[3] __initdata = {
++ { 0x300, 0 }, /* 0xFFF300 */
++ { 0x400, 0 }, /* 0xFFF400 */
++ { 0x800, 1 } /* 0xFF2800 */
++};
++
++static int __init txx9_serial_init(void)
++{
++ extern int early_serial_txx9_setup(struct uart_port *port);
++ struct device_node *node = NULL;
++ int i;
++ struct uart_port req;
++ struct of_irq irq;
++ struct resource res;
++
++ while ((node = of_find_compatible_node(node,
++ "serial", "toshiba,sio-scc")) != NULL) {
++ for (i = 0; i < ARRAY_SIZE(txx9_scc_tab); i++) {
++ if (!(txx9_serial_bitmap & (1<<i)))
++ continue;
++
++ if (of_irq_map_one(node, i, &irq))
++ continue;
++ if (of_address_to_resource(node,
++ txx9_scc_tab[i].index, &res))
++ continue;
++
++ memset(&req, 0, sizeof(req));
++ req.line = i;
++ req.iotype = UPIO_MEM;
++ req.mapbase = res.start + txx9_scc_tab[i].offset;
++#ifdef CONFIG_SERIAL_TXX9_CONSOLE
++ req.membase = ioremap(req.mapbase, 0x24);
++#endif
++ req.irq = irq_create_of_mapping(irq.controller,
++ irq.specifier, irq.size);
++ req.flags |= UPF_IOREMAP | UPF_BUGGY_UART
++ /*HAVE_CTS_LINE*/;
++ req.uartclk = 83300000;
++ early_serial_txx9_setup(&req);
++ }
++ }
++
++ return 0;
++}
++
++static int __init txx9_serial_config(char *ptr)
++{
++ int i;
++
++ for (;;) {
++ switch (get_option(&ptr, &i)) {
++ default:
++ return 0;
++ case 2:
++ txx9_serial_bitmap |= 1 << i;
++ break;
++ case 1:
++ txx9_serial_bitmap |= 1 << i;
++ return 0;
++ }
++ }
++}
++__setup("txx9_serial=", txx9_serial_config);
++
++console_initcall(txx9_serial_init);
+diff --git a/arch/powerpc/platforms/cell/celleb_scc_uhc.c b/arch/powerpc/platforms/cell/celleb_scc_uhc.c
+new file mode 100644
+index 0000000..d63b720
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/celleb_scc_uhc.c
+@@ -0,0 +1,95 @@
++/*
++ * SCC (Super Companion Chip) UHC setup
++ *
++ * (C) Copyright 2006-2007 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; 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.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/pci.h>
++
++#include <asm/delay.h>
++#include <asm/io.h>
++#include <asm/machdep.h>
++
++#include "celleb_scc.h"
++
++#define UHC_RESET_WAIT_MAX 10000
++
++static inline int uhc_clkctrl_ready(u32 val)
++{
++ const u32 mask = SCC_UHC_USBCEN | SCC_UHC_USBCEN;
++ return((val & mask) == mask);
++}
++
++/*
++ * UHC(usb host controller) enable function.
++ * affect to both of OHCI and EHCI core module.
++ */
++static void enable_scc_uhc(struct pci_dev *dev)
++{
++ void __iomem *uhc_base;
++ u32 __iomem *uhc_clkctrl;
++ u32 __iomem *uhc_ecmode;
++ u32 val = 0;
++ int i;
++
++ if (!machine_is(celleb_beat) &&
++ !machine_is(celleb_native))
++ return;
++
++ uhc_base = ioremap(pci_resource_start(dev, 0),
++ pci_resource_len(dev, 0));
++ if (!uhc_base) {
++ printk(KERN_ERR "failed to map UHC register base.\n");
++ return;
++ }
++ uhc_clkctrl = uhc_base + SCC_UHC_CKRCTRL;
++ uhc_ecmode = uhc_base + SCC_UHC_ECMODE;
++
++ /* setup for normal mode */
++ val |= SCC_UHC_F48MCKLEN;
++ out_be32(uhc_clkctrl, val);
++ val |= SCC_UHC_PHY_SUSPEND_SEL;
++ out_be32(uhc_clkctrl, val);
++ udelay(10);
++ val |= SCC_UHC_PHYEN;
++ out_be32(uhc_clkctrl, val);
++ udelay(50);
++
++ /* disable reset */
++ val |= SCC_UHC_HCLKEN;
++ out_be32(uhc_clkctrl, val);
++ val |= (SCC_UHC_USBCEN | SCC_UHC_USBEN);
++ out_be32(uhc_clkctrl, val);
++ i = 0;
++ while (!uhc_clkctrl_ready(in_be32(uhc_clkctrl))) {
++ udelay(10);
++ if (i++ > UHC_RESET_WAIT_MAX) {
++ printk(KERN_ERR "Failed to disable UHC reset %x\n",
++ in_be32(uhc_clkctrl));
++ break;
++ }
++ }
++
++ /* Endian Conversion Mode for Master ALL area */
++ out_be32(uhc_ecmode, SCC_UHC_ECMODE_BY_BYTE);
++
++ iounmap(uhc_base);
++}
++
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA_2,
++ PCI_DEVICE_ID_TOSHIBA_SCC_USB, enable_scc_uhc);
+diff --git a/arch/powerpc/platforms/cell/celleb_setup.c b/arch/powerpc/platforms/cell/celleb_setup.c
+new file mode 100644
+index 0000000..b11cb30
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/celleb_setup.c
+@@ -0,0 +1,256 @@
++/*
++ * Celleb setup code
++ *
++ * (C) Copyright 2006-2007 TOSHIBA CORPORATION
++ *
++ * This code is based on arch/powerpc/platforms/cell/setup.c:
++ * Copyright (C) 1995 Linus Torvalds
++ * Adapted from 'alpha' version by Gary Thomas
++ * Modified by Cort Dougan (cort at cs.nmt.edu)
++ * Modified by PPC64 Team, IBM Corp
++ * Modified by Cell Team, IBM Deutschland Entwicklung GmbH
++ *
++ * 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.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#undef DEBUG
++
++#include <linux/cpu.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/stddef.h>
++#include <linux/unistd.h>
++#include <linux/reboot.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/irq.h>
++#include <linux/seq_file.h>
++#include <linux/root_dev.h>
++#include <linux/console.h>
++#include <linux/of_platform.h>
++
++#include <asm/mmu.h>
++#include <asm/processor.h>
++#include <asm/io.h>
++#include <asm/kexec.h>
++#include <asm/prom.h>
++#include <asm/machdep.h>
++#include <asm/cputable.h>
++#include <asm/irq.h>
++#include <asm/time.h>
++#include <asm/spu_priv1.h>
++#include <asm/firmware.h>
++#include <asm/rtas.h>
++#include <asm/cell-regs.h>
++
++#include "beat_interrupt.h"
++#include "beat_wrapper.h"
++#include "beat.h"
++#include "celleb_pci.h"
++#include "interrupt.h"
++#include "pervasive.h"
++#include "ras.h"
++
++static char celleb_machine_type[128] = "Celleb";
++
++static void celleb_show_cpuinfo(struct seq_file *m)
++{
++ struct device_node *root;
++ const char *model = "";
++
++ root = of_find_node_by_path("/");
++ if (root)
++ model = of_get_property(root, "model", NULL);
++ /* using "CHRP" is to trick anaconda into installing FCx into Celleb */
++ seq_printf(m, "machine\t\t: %s %s\n", celleb_machine_type, model);
++ of_node_put(root);
++}
++
++static int __init celleb_machine_type_hack(char *ptr)
++{
++ strncpy(celleb_machine_type, ptr, sizeof(celleb_machine_type));
++ celleb_machine_type[sizeof(celleb_machine_type)-1] = 0;
++ return 0;
++}
++
++__setup("celleb_machine_type_hack=", celleb_machine_type_hack);
++
++static void celleb_progress(char *s, unsigned short hex)
++{
++ printk("*** %04x : %s\n", hex, s ? s : "");
++}
++
++static void __init celleb_setup_arch_common(void)
++{
++ /* init to some ~sane value until calibrate_delay() runs */
++ loops_per_jiffy = 50000000;
++
++#ifdef CONFIG_DUMMY_CONSOLE
++ conswitchp = &dummy_con;
++#endif
++}
++
++static struct of_device_id celleb_bus_ids[] __initdata = {
++ { .type = "scc", },
++ { .type = "ioif", }, /* old style */
++ {},
++};
++
++static int __init celleb_publish_devices(void)
++{
++ /* Publish OF platform devices for southbridge IOs */
++ of_platform_bus_probe(NULL, celleb_bus_ids, NULL);
++
++ return 0;
++}
++machine_device_initcall(celleb_beat, celleb_publish_devices);
++machine_device_initcall(celleb_native, celleb_publish_devices);
++
++
++/*
++ * functions for Celleb-Beat
++ */
++static void __init celleb_setup_arch_beat(void)
++{
++#ifdef CONFIG_SPU_BASE
++ spu_priv1_ops = &spu_priv1_beat_ops;
++ spu_management_ops = &spu_management_of_ops;
++#endif
++
++#ifdef CONFIG_SMP
++ smp_init_celleb();
++#endif
++
++ celleb_setup_arch_common();
++}
++
++static int __init celleb_probe_beat(void)
++{
++ unsigned long root = of_get_flat_dt_root();
++
++ if (!of_flat_dt_is_compatible(root, "Beat"))
++ return 0;
++
++ powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS
++ | FW_FEATURE_BEAT | FW_FEATURE_LPAR;
++ hpte_init_beat_v3();
++
++ return 1;
++}
++
++
++/*
++ * functions for Celleb-native
++ */
++static void __init celleb_init_IRQ_native(void)
++{
++ iic_init_IRQ();
++ spider_init_IRQ();
++}
++
++static void __init celleb_setup_arch_native(void)
++{
++#ifdef CONFIG_SPU_BASE
++ spu_priv1_ops = &spu_priv1_mmio_ops;
++ spu_management_ops = &spu_management_of_ops;
++#endif
++
++ cbe_regs_init();
++
++#ifdef CONFIG_CBE_RAS
++ cbe_ras_init();
++#endif
++
++#ifdef CONFIG_SMP
++ smp_init_cell();
++#endif
++
++ cbe_pervasive_init();
++
++ /* XXX: nvram initialization should be added */
++
++ celleb_setup_arch_common();
++}
++
++static int __init celleb_probe_native(void)
++{
++ unsigned long root = of_get_flat_dt_root();
++
++ if (of_flat_dt_is_compatible(root, "Beat") ||
++ !of_flat_dt_is_compatible(root, "TOSHIBA,Celleb"))
++ return 0;
++
++ powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS;
++ hpte_init_native();
++
++ return 1;
++}
++
++
++/*
++ * machine definitions
++ */
++define_machine(celleb_beat) {
++ .name = "Cell Reference Set (Beat)",
++ .probe = celleb_probe_beat,
++ .setup_arch = celleb_setup_arch_beat,
++ .show_cpuinfo = celleb_show_cpuinfo,
++ .restart = beat_restart,
++ .power_off = beat_power_off,
++ .halt = beat_halt,
++ .get_rtc_time = beat_get_rtc_time,
++ .set_rtc_time = beat_set_rtc_time,
++ .calibrate_decr = generic_calibrate_decr,
++ .progress = celleb_progress,
++ .power_save = beat_power_save,
++ .nvram_size = beat_nvram_get_size,
++ .nvram_read = beat_nvram_read,
++ .nvram_write = beat_nvram_write,
++ .set_dabr = beat_set_xdabr,
++ .init_IRQ = beatic_init_IRQ,
++ .get_irq = beatic_get_irq,
++ .pci_probe_mode = celleb_pci_probe_mode,
++ .pci_setup_phb = celleb_setup_phb,
++#ifdef CONFIG_KEXEC
++ .kexec_cpu_down = beat_kexec_cpu_down,
++ .machine_kexec = default_machine_kexec,
++ .machine_kexec_prepare = default_machine_kexec_prepare,
++ .machine_crash_shutdown = default_machine_crash_shutdown,
++#endif
++};
++
++define_machine(celleb_native) {
++ .name = "Cell Reference Set (native)",
++ .probe = celleb_probe_native,
++ .setup_arch = celleb_setup_arch_native,
++ .show_cpuinfo = celleb_show_cpuinfo,
++ .restart = rtas_restart,
++ .power_off = rtas_power_off,
++ .halt = rtas_halt,
++ .get_boot_time = rtas_get_boot_time,
++ .get_rtc_time = rtas_get_rtc_time,
++ .set_rtc_time = rtas_set_rtc_time,
++ .calibrate_decr = generic_calibrate_decr,
++ .progress = celleb_progress,
++ .pci_probe_mode = celleb_pci_probe_mode,
++ .pci_setup_phb = celleb_setup_phb,
++ .init_IRQ = celleb_init_IRQ_native,
++#ifdef CONFIG_KEXEC
++ .machine_kexec = default_machine_kexec,
++ .machine_kexec_prepare = default_machine_kexec_prepare,
++ .machine_crash_shutdown = default_machine_crash_shutdown,
++#endif
++};
+diff --git a/arch/powerpc/platforms/cell/io-workarounds.c b/arch/powerpc/platforms/cell/io-workarounds.c
+index 979d4b6..3b84e8b 100644
+--- a/arch/powerpc/platforms/cell/io-workarounds.c
++++ b/arch/powerpc/platforms/cell/io-workarounds.c
+@@ -1,6 +1,9 @@
+ /*
++ * Support PCI IO workaround
++ *
+ * Copyright (C) 2006 Benjamin Herrenschmidt <benh at kernel.crashing.org>
+ * IBM, Corp.
++ * (C) Copyright 2007-2008 TOSHIBA CORPORATION
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+@@ -9,335 +12,174 @@
+ #undef DEBUG
+
+ #include <linux/kernel.h>
+-#include <linux/mm.h>
+-#include <linux/pci.h>
++
+ #include <asm/io.h>
+ #include <asm/machdep.h>
+-#include <asm/pci-bridge.h>
++#include <asm/pgtable.h>
+ #include <asm/ppc-pci.h>
+
++#include "io-workarounds.h"
+
+-#define SPIDER_PCI_REG_BASE 0xd000
+-#define SPIDER_PCI_VCI_CNTL_STAT 0x0110
+-#define SPIDER_PCI_DUMMY_READ 0x0810
+-#define SPIDER_PCI_DUMMY_READ_BASE 0x0814
++#define IOWA_MAX_BUS 8
+
+-/* Undefine that to re-enable bogus prefetch
+- *
+- * Without that workaround, the chip will do bogus prefetch past
+- * page boundary from system memory. This setting will disable that,
+- * though the documentation is unclear as to the consequences of doing
+- * so, either purely performances, or possible misbehaviour... It's not
+- * clear wether the chip can handle unaligned accesses at all without
+- * prefetching enabled.
+- *
+- * For now, things appear to be behaving properly with that prefetching
+- * disabled and IDE, possibly because IDE isn't doing any unaligned
+- * access.
+- */
+-#define SPIDER_DISABLE_PREFETCH
++static struct iowa_bus iowa_busses[IOWA_MAX_BUS];
++static unsigned int iowa_bus_count;
+
+-#define MAX_SPIDERS 3
++static struct iowa_bus *iowa_pci_find(unsigned long vaddr, unsigned long paddr)
++{
++ int i, j;
++ struct resource *res;
++ unsigned long vstart, vend;
+
+-static struct spider_pci_bus {
+- void __iomem *regs;
+- unsigned long mmio_start;
+- unsigned long mmio_end;
+- unsigned long pio_vstart;
+- unsigned long pio_vend;
+-} spider_pci_busses[MAX_SPIDERS];
+-static int spider_pci_count;
++ for (i = 0; i < iowa_bus_count; i++) {
++ struct iowa_bus *bus = &iowa_busses[i];
++ struct pci_controller *phb = bus->phb;
+
+-static struct spider_pci_bus *spider_pci_find(unsigned long vaddr,
+- unsigned long paddr)
+-{
+- int i;
+-
+- for (i = 0; i < spider_pci_count; i++) {
+- struct spider_pci_bus *bus = &spider_pci_busses[i];
+- if (paddr && paddr >= bus->mmio_start && paddr < bus->mmio_end)
+- return bus;
+- if (vaddr && vaddr >= bus->pio_vstart && vaddr < bus->pio_vend)
+- return bus;
++ if (vaddr) {
++ vstart = (unsigned long)phb->io_base_virt;
++ vend = vstart + phb->pci_io_size - 1;
++ if ((vaddr >= vstart) && (vaddr <= vend))
++ return bus;
++ }
++
++ if (paddr)
++ for (j = 0; j < 3; j++) {
++ res = &phb->mem_resources[j];
++ if (paddr >= res->start && paddr <= res->end)
++ return bus;
++ }
+ }
++
+ return NULL;
+ }
+
+-static void spider_io_flush(const volatile void __iomem *addr)
++struct iowa_bus *iowa_mem_find_bus(const PCI_IO_ADDR addr)
+ {
+- struct spider_pci_bus *bus;
++ struct iowa_bus *bus;
+ int token;
+
+- /* Get platform token (set by ioremap) from address */
+ token = PCI_GET_ADDR_TOKEN(addr);
+
+- /* Fast path if we have a non-0 token, it indicates which bus we
+- * are on.
+- *
+- * If the token is 0, that means either that the ioremap was done
+- * before we initialized this layer, or it's a PIO operation. We
+- * fallback to a low path in this case. Hopefully, internal devices
+- * which are ioremap'ed early should use in_XX/out_XX functions
+- * instead of the PCI ones and thus not suffer from the slowdown.
+- *
+- * Also note that currently, the workaround will not work for areas
+- * that are not mapped with PTEs (bolted in the hash table). This
+- * is the case for ioremaps done very early at boot (before
+- * mem_init_done) and includes the mapping of the ISA IO space.
+- *
+- * Fortunately, none of the affected devices is expected to do DMA
+- * and thus there should be no problem in practice.
+- *
+- * In order to improve performances, we only do the PTE search for
+- * addresses falling in the PHB IO space area. That means it will
+- * not work for hotplug'ed PHBs but those don't exist with Spider.
+- */
+- if (token && token <= spider_pci_count)
+- bus = &spider_pci_busses[token - 1];
++ if (token && token <= iowa_bus_count)
++ bus = &iowa_busses[token - 1];
+ else {
+ unsigned long vaddr, paddr;
+ pte_t *ptep;
+
+- /* Fixup physical address */
+ vaddr = (unsigned long)PCI_FIX_ADDR(addr);
++ if (vaddr < PHB_IO_BASE || vaddr >= PHB_IO_END)
++ return NULL;
+
+- /* Check if it's in allowed range for PIO */
+- if (vaddr < PHB_IO_BASE || vaddr > PHB_IO_END)
+- return;
+-
+- /* Try to find a PTE. If not, clear the paddr, we'll do
+- * a vaddr only lookup (PIO only)
+- */
+ ptep = find_linux_pte(init_mm.pgd, vaddr);
+ if (ptep == NULL)
+ paddr = 0;
+ else
+ paddr = pte_pfn(*ptep) << PAGE_SHIFT;
++ bus = iowa_pci_find(vaddr, paddr);
+
+- bus = spider_pci_find(vaddr, paddr);
+ if (bus == NULL)
+- return;
++ return NULL;
+ }
+
+- /* Now do the workaround
+- */
+- (void)in_be32(bus->regs + SPIDER_PCI_DUMMY_READ);
++ return bus;
+ }
+
+-static u8 spider_readb(const volatile void __iomem *addr)
++struct iowa_bus *iowa_pio_find_bus(unsigned long port)
+ {
+- u8 val = __do_readb(addr);
+- spider_io_flush(addr);
+- return val;
++ unsigned long vaddr = (unsigned long)pci_io_base + port;
++ return iowa_pci_find(vaddr, 0);
+ }
+
+-static u16 spider_readw(const volatile void __iomem *addr)
+-{
+- u16 val = __do_readw(addr);
+- spider_io_flush(addr);
+- return val;
+-}
+
+-static u32 spider_readl(const volatile void __iomem *addr)
+-{
+- u32 val = __do_readl(addr);
+- spider_io_flush(addr);
+- return val;
++#define DEF_PCI_AC_RET(name, ret, at, al, space, aa) \
++static ret iowa_##name at \
++{ \
++ struct iowa_bus *bus; \
++ bus = iowa_##space##_find_bus(aa); \
++ if (bus && bus->ops && bus->ops->name) \
++ return bus->ops->name al; \
++ return __do_##name al; \
+ }
+
+-static u64 spider_readq(const volatile void __iomem *addr)
+-{
+- u64 val = __do_readq(addr);
+- spider_io_flush(addr);
+- return val;
++#define DEF_PCI_AC_NORET(name, at, al, space, aa) \
++static void iowa_##name at \
++{ \
++ struct iowa_bus *bus; \
++ bus = iowa_##space##_find_bus(aa); \
++ if (bus && bus->ops && bus->ops->name) { \
++ bus->ops->name al; \
++ return; \
++ } \
++ __do_##name al; \
+ }
+
+-static u16 spider_readw_be(const volatile void __iomem *addr)
+-{
+- u16 val = __do_readw_be(addr);
+- spider_io_flush(addr);
+- return val;
+-}
++#include <asm/io-defs.h>
+
+-static u32 spider_readl_be(const volatile void __iomem *addr)
+-{
+- u32 val = __do_readl_be(addr);
+- spider_io_flush(addr);
+- return val;
+-}
++#undef DEF_PCI_AC_RET
++#undef DEF_PCI_AC_NORET
+
+-static u64 spider_readq_be(const volatile void __iomem *addr)
+-{
+- u64 val = __do_readq_be(addr);
+- spider_io_flush(addr);
+- return val;
+-}
++static struct ppc_pci_io __initdata iowa_pci_io = {
+
+-static void spider_readsb(const volatile void __iomem *addr, void *buf,
+- unsigned long count)
+-{
+- __do_readsb(addr, buf, count);
+- spider_io_flush(addr);
+-}
++#define DEF_PCI_AC_RET(name, ret, at, al, space, aa) .name = iowa_##name,
++#define DEF_PCI_AC_NORET(name, at, al, space, aa) .name = iowa_##name,
+
+-static void spider_readsw(const volatile void __iomem *addr, void *buf,
+- unsigned long count)
+-{
+- __do_readsw(addr, buf, count);
+- spider_io_flush(addr);
+-}
++#include <asm/io-defs.h>
+
+-static void spider_readsl(const volatile void __iomem *addr, void *buf,
+- unsigned long count)
+-{
+- __do_readsl(addr, buf, count);
+- spider_io_flush(addr);
+-}
+-
+-static void spider_memcpy_fromio(void *dest, const volatile void __iomem *src,
+- unsigned long n)
+-{
+- __do_memcpy_fromio(dest, src, n);
+- spider_io_flush(src);
+-}
++#undef DEF_PCI_AC_RET
++#undef DEF_PCI_AC_NORET
+
++};
+
+-static void __iomem * spider_ioremap(unsigned long addr, unsigned long size,
+- unsigned long flags)
++static void __iomem *iowa_ioremap(unsigned long addr, unsigned long size,
++ unsigned long flags)
+ {
+- struct spider_pci_bus *bus;
++ struct iowa_bus *bus;
+ void __iomem *res = __ioremap(addr, size, flags);
+ int busno;
+
+- pr_debug("spider_ioremap(0x%lx, 0x%lx, 0x%lx) -> 0x%p\n",
+- addr, size, flags, res);
+-
+- bus = spider_pci_find(0, addr);
++ bus = iowa_pci_find(0, addr);
+ if (bus != NULL) {
+- busno = bus - spider_pci_busses;
+- pr_debug(" found bus %d, setting token\n", busno);
++ busno = bus - iowa_busses;
+ PCI_SET_ADDR_TOKEN(res, busno + 1);
+ }
+- pr_debug(" result=0x%p\n", res);
+-
+ return res;
+ }
+
+-static void __init spider_pci_setup_chip(struct spider_pci_bus *bus)
+-{
+-#ifdef SPIDER_DISABLE_PREFETCH
+- u32 val = in_be32(bus->regs + SPIDER_PCI_VCI_CNTL_STAT);
+- pr_debug(" PVCI_Control_Status was 0x%08x\n", val);
+- out_be32(bus->regs + SPIDER_PCI_VCI_CNTL_STAT, val | 0x8);
+-#endif
+-
+- /* Configure the dummy address for the workaround */
+- out_be32(bus->regs + SPIDER_PCI_DUMMY_READ_BASE, 0x80000000);
+-}
+-
+-static void __init spider_pci_add_one(struct pci_controller *phb)
++/* Regist new bus to support workaround */
++void __init iowa_register_bus(struct pci_controller *phb,
++ struct ppc_pci_io *ops,
++ int (*initfunc)(struct iowa_bus *, void *), void *data)
+ {
+- struct spider_pci_bus *bus = &spider_pci_busses[spider_pci_count];
++ struct iowa_bus *bus;
+ struct device_node *np = phb->dn;
+- struct resource rsrc;
+- void __iomem *regs;
+
+- if (spider_pci_count >= MAX_SPIDERS) {
+- printk(KERN_ERR "Too many spider bridges, workarounds"
+- " disabled for %s\n", np->full_name);
++ if (iowa_bus_count >= IOWA_MAX_BUS) {
++ pr_err("IOWA:Too many pci bridges, "
++ "workarounds disabled for %s\n", np->full_name);
+ return;
+ }
+
+- /* Get the registers for the beast */
+- if (of_address_to_resource(np, 0, &rsrc)) {
+- printk(KERN_ERR "Failed to get registers for spider %s"
+- " workarounds disabled\n", np->full_name);
+- return;
+- }
++ bus = &iowa_busses[iowa_bus_count];
++ bus->phb = phb;
++ bus->ops = ops;
+
+- /* Mask out some useless bits in there to get to the base of the
+- * spider chip
+- */
+- rsrc.start &= ~0xfffffffful;
+-
+- /* Map them */
+- regs = ioremap(rsrc.start + SPIDER_PCI_REG_BASE, 0x1000);
+- if (regs == NULL) {
+- printk(KERN_ERR "Failed to map registers for spider %s"
+- " workarounds disabled\n", np->full_name);
+- return;
+- }
+-
+- spider_pci_count++;
+-
+- /* We assume spiders only have one MMIO resource */
+- bus->mmio_start = phb->mem_resources[0].start;
+- bus->mmio_end = phb->mem_resources[0].end + 1;
+-
+- bus->pio_vstart = (unsigned long)phb->io_base_virt;
+- bus->pio_vend = bus->pio_vstart + phb->pci_io_size;
+-
+- bus->regs = regs;
+-
+- printk(KERN_INFO "PCI: Spider MMIO workaround for %s\n",np->full_name);
++ if (initfunc)
++ if ((*initfunc)(bus, data))
++ return;
+
+- pr_debug(" mmio (P) = 0x%016lx..0x%016lx\n",
+- bus->mmio_start, bus->mmio_end);
+- pr_debug(" pio (V) = 0x%016lx..0x%016lx\n",
+- bus->pio_vstart, bus->pio_vend);
+- pr_debug(" regs (P) = 0x%016lx (V) = 0x%p\n",
+- rsrc.start + SPIDER_PCI_REG_BASE, bus->regs);
++ iowa_bus_count++;
+
+- spider_pci_setup_chip(bus);
++ pr_debug("IOWA:[%d]Add bus, %s.\n", iowa_bus_count-1, np->full_name);
+ }
+
+-static struct ppc_pci_io __initdata spider_pci_io = {
+- .readb = spider_readb,
+- .readw = spider_readw,
+- .readl = spider_readl,
+- .readq = spider_readq,
+- .readw_be = spider_readw_be,
+- .readl_be = spider_readl_be,
+- .readq_be = spider_readq_be,
+- .readsb = spider_readsb,
+- .readsw = spider_readsw,
+- .readsl = spider_readsl,
+- .memcpy_fromio = spider_memcpy_fromio,
+-};
+-
+-static int __init spider_pci_workaround_init(void)
++/* enable IO workaround */
++void __init io_workaround_init(void)
+ {
+- struct pci_controller *phb;
+-
+- /* Find spider bridges. We assume they have been all probed
+- * in setup_arch(). If that was to change, we would need to
+- * update this code to cope with dynamically added busses
+- */
+- list_for_each_entry(phb, &hose_list, list_node) {
+- struct device_node *np = phb->dn;
+- const char *model = of_get_property(np, "model", NULL);
+-
+- /* If no model property or name isn't exactly "pci", skip */
+- if (model == NULL || strcmp(np->name, "pci"))
+- continue;
+- /* If model is not "Spider", skip */
+- if (strcmp(model, "Spider"))
+- continue;
+- spider_pci_add_one(phb);
+- }
+-
+- /* No Spider PCI found, exit */
+- if (spider_pci_count == 0)
+- return 0;
++ static int io_workaround_inited;
+
+- /* Setup IO callbacks. We only setup MMIO reads. PIO reads will
+- * fallback to MMIO reads (though without a token, thus slower)
+- */
+- ppc_pci_io = spider_pci_io;
+-
+- /* Setup ioremap callback */
+- ppc_md.ioremap = spider_ioremap;
+-
+- return 0;
++ if (io_workaround_inited)
++ return;
++ ppc_pci_io = iowa_pci_io;
++ ppc_md.ioremap = iowa_ioremap;
++ io_workaround_inited = 1;
+ }
+-machine_arch_initcall(cell, spider_pci_workaround_init);
+diff --git a/arch/powerpc/platforms/cell/io-workarounds.h b/arch/powerpc/platforms/cell/io-workarounds.h
+new file mode 100644
+index 0000000..79d8ed3
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/io-workarounds.h
+@@ -0,0 +1,49 @@
++/*
++ * Support PCI IO workaround
++ *
++ * (C) Copyright 2007-2008 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; 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.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#ifndef _IO_WORKAROUNDS_H
++#define _IO_WORKAROUNDS_H
++
++#include <linux/io.h>
++#include <asm/pci-bridge.h>
++
++/* Bus info */
++struct iowa_bus {
++ struct pci_controller *phb;
++ struct ppc_pci_io *ops;
++ void *private;
++};
++
++void __init io_workaround_init(void);
++void __init iowa_register_bus(struct pci_controller *, struct ppc_pci_io *,
++ int (*)(struct iowa_bus *, void *), void *);
++struct iowa_bus *iowa_mem_find_bus(const PCI_IO_ADDR);
++struct iowa_bus *iowa_pio_find_bus(unsigned long);
++
++extern struct ppc_pci_io spiderpci_ops;
++extern int spiderpci_iowa_init(struct iowa_bus *, void *);
++
++#define SPIDER_PCI_REG_BASE 0xd000
++#define SPIDER_PCI_REG_SIZE 0x1000
++#define SPIDER_PCI_VCI_CNTL_STAT 0x0110
++#define SPIDER_PCI_DUMMY_READ 0x0810
++#define SPIDER_PCI_DUMMY_READ_BASE 0x0814
++
++#endif /* _IO_WORKAROUNDS_H */
+diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
+index d75ccde..45646b2 100644
+--- a/arch/powerpc/platforms/cell/iommu.c
++++ b/arch/powerpc/platforms/cell/iommu.c
+@@ -28,13 +28,13 @@
+ #include <linux/notifier.h>
+ #include <linux/of.h>
+ #include <linux/of_platform.h>
++#include <linux/lmb.h>
+
+ #include <asm/prom.h>
+ #include <asm/iommu.h>
+ #include <asm/machdep.h>
+ #include <asm/pci-bridge.h>
+ #include <asm/udbg.h>
+-#include <asm/lmb.h>
+ #include <asm/firmware.h>
+ #include <asm/cell-regs.h>
+
+@@ -316,7 +316,7 @@ static void cell_iommu_setup_stab(struct cbe_iommu *iommu,
+ segments = max(dbase + dsize, fbase + fsize) >> IO_SEGMENT_SHIFT;
+
+ pr_debug("%s: iommu[%d]: segments: %lu\n",
+- __FUNCTION__, iommu->nid, segments);
++ __func__, iommu->nid, segments);
+
+ /* set up the segment table */
+ stab_size = segments * sizeof(unsigned long);
+@@ -343,7 +343,7 @@ static unsigned long *cell_iommu_alloc_ptab(struct cbe_iommu *iommu,
+ (1 << 12) / sizeof(unsigned long));
+
+ ptab_size = segments * pages_per_segment * sizeof(unsigned long);
+- pr_debug("%s: iommu[%d]: ptab_size: %lu, order: %d\n", __FUNCTION__,
++ pr_debug("%s: iommu[%d]: ptab_size: %lu, order: %d\n", __func__,
+ iommu->nid, ptab_size, get_order(ptab_size));
+ page = alloc_pages_node(iommu->nid, GFP_KERNEL, get_order(ptab_size));
+ BUG_ON(!page);
+@@ -355,7 +355,7 @@ static unsigned long *cell_iommu_alloc_ptab(struct cbe_iommu *iommu,
+ n_pte_pages = (pages_per_segment * sizeof(unsigned long)) >> 12;
+
+ pr_debug("%s: iommu[%d]: stab at %p, ptab at %p, n_pte_pages: %lu\n",
+- __FUNCTION__, iommu->nid, iommu->stab, ptab,
++ __func__, iommu->nid, iommu->stab, ptab,
+ n_pte_pages);
+
+ /* initialise the STEs */
+@@ -394,7 +394,7 @@ static void cell_iommu_enable_hardware(struct cbe_iommu *iommu)
+
+ if (cell_iommu_find_ioc(iommu->nid, &xlate_base))
+ panic("%s: missing IOC register mappings for node %d\n",
+- __FUNCTION__, iommu->nid);
++ __func__, iommu->nid);
+
+ iommu->xlate_regs = ioremap(xlate_base, IOC_Reg_Size);
+ iommu->cmd_regs = iommu->xlate_regs + IOC_IOCmd_Offset;
+diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c
+index 0304589..8a3631c 100644
+--- a/arch/powerpc/platforms/cell/pervasive.c
++++ b/arch/powerpc/platforms/cell/pervasive.c
+@@ -65,7 +65,7 @@ static void cbe_power_save(void)
+ break;
+ default:
+ printk(KERN_WARNING "%s: unknown configuration\n",
+- __FUNCTION__);
++ __func__);
+ break;
+ }
+ mtspr(SPRN_TSC_CELL, thread_switch_control);
+diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c
+index e43024c..655704a 100644
+--- a/arch/powerpc/platforms/cell/ras.c
++++ b/arch/powerpc/platforms/cell/ras.c
+@@ -132,7 +132,7 @@ static int __init cbe_ptcal_enable_on_node(int nid, int order)
+ (unsigned int)(addr >> 32),
+ (unsigned int)(addr & 0xffffffff))) {
+ printk(KERN_ERR "%s: error enabling PTCAL on node %d!\n",
+- __FUNCTION__, nid);
++ __func__, nid);
+ goto out_free_pages;
+ }
+
+@@ -162,7 +162,7 @@ static int __init cbe_ptcal_enable(void)
+ if (!size)
+ return -ENODEV;
+
+- pr_debug("%s: enabling PTCAL, size = 0x%x\n", __FUNCTION__, *size);
++ pr_debug("%s: enabling PTCAL, size = 0x%x\n", __func__, *size);
+ order = get_order(*size);
+ of_node_put(np);
+
+@@ -180,7 +180,7 @@ static int __init cbe_ptcal_enable(void)
+ const u32 *nid = of_get_property(np, "node-id", NULL);
+ if (!nid) {
+ printk(KERN_ERR "%s: node %s is missing node-id?\n",
+- __FUNCTION__, np->full_name);
++ __func__, np->full_name);
+ continue;
+ }
+ cbe_ptcal_enable_on_node(*nid, order);
+@@ -195,13 +195,13 @@ static int cbe_ptcal_disable(void)
+ struct ptcal_area *area, *tmp;
+ int ret = 0;
+
+- pr_debug("%s: disabling PTCAL\n", __FUNCTION__);
++ pr_debug("%s: disabling PTCAL\n", __func__);
+
+ list_for_each_entry_safe(area, tmp, &ptcal_list, list) {
+ /* disable ptcal on this node */
+ if (rtas_call(ptcal_stop_tok, 1, 1, NULL, area->nid)) {
+ printk(KERN_ERR "%s: error disabling PTCAL "
+- "on node %d!\n", __FUNCTION__,
++ "on node %d!\n", __func__,
+ area->nid);
+ ret = -EIO;
+ continue;
+diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
+index 5c531e8..ab721b5 100644
+--- a/arch/powerpc/platforms/cell/setup.c
++++ b/arch/powerpc/platforms/cell/setup.c
+@@ -57,6 +57,7 @@
+ #include "interrupt.h"
+ #include "pervasive.h"
+ #include "ras.h"
++#include "io-workarounds.h"
+
+ #ifdef DEBUG
+ #define DBG(fmt...) udbg_printf(fmt)
+@@ -117,13 +118,50 @@ static void cell_fixup_pcie_rootcomplex(struct pci_dev *dev)
+ }
+ DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, cell_fixup_pcie_rootcomplex);
+
++static int __devinit cell_setup_phb(struct pci_controller *phb)
++{
++ const char *model;
++ struct device_node *np;
++
++ int rc = rtas_setup_phb(phb);
++ if (rc)
++ return rc;
++
++ np = phb->dn;
++ model = of_get_property(np, "model", NULL);
++ if (model == NULL || strcmp(np->name, "pci"))
++ return 0;
++
++ /* Setup workarounds for spider */
++ if (strcmp(model, "Spider"))
++ return 0;
++
++ iowa_register_bus(phb, &spiderpci_ops, &spiderpci_iowa_init,
++ (void *)SPIDER_PCI_REG_BASE);
++ io_workaround_init();
++
++ return 0;
++}
++
+ static int __init cell_publish_devices(void)
+ {
++ struct device_node *root = of_find_node_by_path("/");
++ struct device_node *np;
+ int node;
+
+ /* Publish OF platform devices for southbridge IOs */
+ of_platform_bus_probe(NULL, NULL, NULL);
+
++ /* On spider based blades, we need to manually create the OF
++ * platform devices for the PCI host bridges
++ */
++ for_each_child_of_node(root, np) {
++ if (np->type == NULL || (strcmp(np->type, "pci") != 0 &&
++ strcmp(np->type, "pciex") != 0))
++ continue;
++ of_platform_device_create(np, NULL, NULL);
++ }
++
+ /* There is no device for the MIC memory controller, thus we create
+ * a platform device for it to attach the EDAC driver to.
+ */
+@@ -132,6 +170,7 @@ static int __init cell_publish_devices(void)
+ continue;
+ platform_device_register_simple("cbe-mic", node, NULL, 0);
+ }
++
+ return 0;
+ }
+ machine_subsys_initcall(cell, cell_publish_devices);
+@@ -213,7 +252,7 @@ static void __init cell_setup_arch(void)
+
+ /* Find and initialize PCI host bridges */
+ init_pci_config_tokens();
+- find_and_init_phbs();
++
+ cbe_pervasive_init();
+ #ifdef CONFIG_DUMMY_CONSOLE
+ conswitchp = &dummy_con;
+@@ -249,7 +288,7 @@ define_machine(cell) {
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = cell_progress,
+ .init_IRQ = cell_init_irq,
+- .pci_setup_phb = rtas_setup_phb,
++ .pci_setup_phb = cell_setup_phb,
+ #ifdef CONFIG_KEXEC
+ .machine_kexec = default_machine_kexec,
+ .machine_kexec_prepare = default_machine_kexec_prepare,
+diff --git a/arch/powerpc/platforms/cell/spider-pci.c b/arch/powerpc/platforms/cell/spider-pci.c
+new file mode 100644
+index 0000000..418b605
+--- /dev/null
++++ b/arch/powerpc/platforms/cell/spider-pci.c
+@@ -0,0 +1,184 @@
++/*
++ * IO workarounds for PCI on Celleb/Cell platform
++ *
++ * (C) Copyright 2006-2007 TOSHIBA CORPORATION
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; 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.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#undef DEBUG
++
++#include <linux/kernel.h>
++#include <linux/of_platform.h>
++#include <linux/io.h>
++
++#include <asm/ppc-pci.h>
++#include <asm/pci-bridge.h>
++
++#include "io-workarounds.h"
++
++#define SPIDER_PCI_DISABLE_PREFETCH
++
++struct spiderpci_iowa_private {
++ void __iomem *regs;
++};
++
++static void spiderpci_io_flush(struct iowa_bus *bus)
++{
++ struct spiderpci_iowa_private *priv;
++ u32 val;
++
++ priv = bus->private;
++ val = in_be32(priv->regs + SPIDER_PCI_DUMMY_READ);
++ iosync();
++}
++
++#define SPIDER_PCI_MMIO_READ(name, ret) \
++static ret spiderpci_##name(const PCI_IO_ADDR addr) \
++{ \
++ ret val = __do_##name(addr); \
++ spiderpci_io_flush(iowa_mem_find_bus(addr)); \
++ return val; \
++}
++
++#define SPIDER_PCI_MMIO_READ_STR(name) \
++static void spiderpci_##name(const PCI_IO_ADDR addr, void *buf, \
++ unsigned long count) \
++{ \
++ __do_##name(addr, buf, count); \
++ spiderpci_io_flush(iowa_mem_find_bus(addr)); \
++}
++
++SPIDER_PCI_MMIO_READ(readb, u8)
++SPIDER_PCI_MMIO_READ(readw, u16)
++SPIDER_PCI_MMIO_READ(readl, u32)
++SPIDER_PCI_MMIO_READ(readq, u64)
++SPIDER_PCI_MMIO_READ(readw_be, u16)
++SPIDER_PCI_MMIO_READ(readl_be, u32)
++SPIDER_PCI_MMIO_READ(readq_be, u64)
++SPIDER_PCI_MMIO_READ_STR(readsb)
++SPIDER_PCI_MMIO_READ_STR(readsw)
++SPIDER_PCI_MMIO_READ_STR(readsl)
++
++static void spiderpci_memcpy_fromio(void *dest, const PCI_IO_ADDR src,
++ unsigned long n)
++{
++ __do_memcpy_fromio(dest, src, n);
++ spiderpci_io_flush(iowa_mem_find_bus(src));
++}
++
++static int __init spiderpci_pci_setup_chip(struct pci_controller *phb,
++ void __iomem *regs)
++{
++ void *dummy_page_va;
++ dma_addr_t dummy_page_da;
++
++#ifdef SPIDER_PCI_DISABLE_PREFETCH
++ u32 val = in_be32(regs + SPIDER_PCI_VCI_CNTL_STAT);
++ pr_debug("SPIDER_IOWA:PVCI_Control_Status was 0x%08x\n", val);
++ out_be32(regs + SPIDER_PCI_VCI_CNTL_STAT, val | 0x8);
++#endif /* SPIDER_PCI_DISABLE_PREFETCH */
++
++ /* setup dummy read */
++ /*
++ * On CellBlade, we can't know that which XDR memory is used by
++ * kmalloc() to allocate dummy_page_va.
++ * In order to imporve the performance, the XDR which is used to
++ * allocate dummy_page_va is the nearest the spider-pci.
++ * We have to select the CBE which is the nearest the spider-pci
++ * to allocate memory from the best XDR, but I don't know that
++ * how to do.
++ *
++ * Celleb does not have this problem, because it has only one XDR.
++ */
++ dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL);
++ if (!dummy_page_va) {
++ pr_err("SPIDERPCI-IOWA:Alloc dummy_page_va failed.\n");
++ return -1;
++ }
++
++ dummy_page_da = dma_map_single(phb->parent, dummy_page_va,
++ PAGE_SIZE, DMA_FROM_DEVICE);
++ if (dma_mapping_error(dummy_page_da)) {
++ pr_err("SPIDER-IOWA:Map dummy page filed.\n");
++ kfree(dummy_page_va);
++ return -1;
++ }
++
++ out_be32(regs + SPIDER_PCI_DUMMY_READ_BASE, dummy_page_da);
++
++ return 0;
++}
++
++int __init spiderpci_iowa_init(struct iowa_bus *bus, void *data)
++{
++ void __iomem *regs = NULL;
++ struct spiderpci_iowa_private *priv;
++ struct device_node *np = bus->phb->dn;
++ struct resource r;
++ unsigned long offset = (unsigned long)data;
++
++ pr_debug("SPIDERPCI-IOWA:Bus initialize for spider(%s)\n",
++ np->full_name);
++
++ priv = kzalloc(sizeof(struct spiderpci_iowa_private), GFP_KERNEL);
++ if (!priv) {
++ pr_err("SPIDERPCI-IOWA:"
++ "Can't allocate struct spiderpci_iowa_private");
++ return -1;
++ }
++
++ if (of_address_to_resource(np, 0, &r)) {
++ pr_err("SPIDERPCI-IOWA:Can't get resource.\n");
++ goto error;
++ }
++
++ regs = ioremap(r.start + offset, SPIDER_PCI_REG_SIZE);
++ if (!regs) {
++ pr_err("SPIDERPCI-IOWA:ioremap failed.\n");
++ goto error;
++ }
++ priv->regs = regs;
++ bus->private = priv;
++
++ if (spiderpci_pci_setup_chip(bus->phb, regs))
++ goto error;
++
++ return 0;
++
++error:
++ kfree(priv);
++ bus->private = NULL;
++
++ if (regs)
++ iounmap(regs);
++
++ return -1;
++}
++
++struct ppc_pci_io spiderpci_ops = {
++ .readb = spiderpci_readb,
++ .readw = spiderpci_readw,
++ .readl = spiderpci_readl,
++ .readq = spiderpci_readq,
++ .readw_be = spiderpci_readw_be,
++ .readl_be = spiderpci_readl_be,
++ .readq_be = spiderpci_readq_be,
++ .readsb = spiderpci_readsb,
++ .readsw = spiderpci_readsw,
++ .readsl = spiderpci_readsl,
++ .memcpy_fromio = spiderpci_memcpy_fromio,
++};
++
+diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
+index 712001f..6bab44b 100644
+--- a/arch/powerpc/platforms/cell/spu_base.c
++++ b/arch/powerpc/platforms/cell/spu_base.c
+@@ -165,7 +165,7 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
+ struct spu_slb slb;
+ int psize;
+
+- pr_debug("%s\n", __FUNCTION__);
++ pr_debug("%s\n", __func__);
+
+ slb.esid = (ea & ESID_MASK) | SLB_ESID_V;
+
+@@ -215,7 +215,7 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
+ extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); //XXX
+ static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr)
+ {
+- pr_debug("%s, %lx, %lx\n", __FUNCTION__, dsisr, ea);
++ pr_debug("%s, %lx, %lx\n", __func__, dsisr, ea);
+
+ /* Handle kernel space hash faults immediately.
+ User hash faults need to be deferred to process context. */
+@@ -351,7 +351,7 @@ spu_irq_class_1(int irq, void *data)
+ __spu_trap_data_seg(spu, dar);
+
+ spin_unlock(&spu->register_lock);
+- pr_debug("%s: %lx %lx %lx %lx\n", __FUNCTION__, mask, stat,
++ pr_debug("%s: %lx %lx %lx %lx\n", __func__, mask, stat,
+ dar, dsisr);
+
+ if (stat & CLASS1_STORAGE_FAULT_INTR)
+@@ -726,7 +726,7 @@ static int __init init_spu_base(void)
+
+ if (ret < 0) {
+ printk(KERN_WARNING "%s: Error initializing spus\n",
+- __FUNCTION__);
++ __func__);
+ goto out_unregister_sysdev_class;
+ }
+
+diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c
+index dceb8b6..19f6bfd 100644
+--- a/arch/powerpc/platforms/cell/spu_callbacks.c
++++ b/arch/powerpc/platforms/cell/spu_callbacks.c
+@@ -54,7 +54,7 @@ long spu_sys_callback(struct spu_syscall_block *s)
+ long (*syscall)(u64 a1, u64 a2, u64 a3, u64 a4, u64 a5, u64 a6);
+
+ if (s->nr_ret >= ARRAY_SIZE(spu_syscall_table)) {
+- pr_debug("%s: invalid syscall #%ld", __FUNCTION__, s->nr_ret);
++ pr_debug("%s: invalid syscall #%ld", __func__, s->nr_ret);
+ return -ENOSYS;
+ }
+
+diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c
+index d351bde..4c506c1 100644
+--- a/arch/powerpc/platforms/cell/spu_manage.c
++++ b/arch/powerpc/platforms/cell/spu_manage.c
+@@ -92,7 +92,7 @@ static int __init spu_map_interrupts_old(struct spu *spu,
+
+ tmp = of_get_property(np->parent->parent, "node-id", NULL);
+ if (!tmp) {
+- printk(KERN_WARNING "%s: can't find node-id\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: can't find node-id\n", __func__);
+ nid = spu->node;
+ } else
+ nid = tmp[0];
+@@ -296,7 +296,7 @@ static int __init of_enumerate_spus(int (*fn)(void *data))
+ ret = fn(node);
+ if (ret) {
+ printk(KERN_WARNING "%s: Error initializing %s\n",
+- __FUNCTION__, node->name);
++ __func__, node->name);
+ break;
+ }
+ n++;
+@@ -327,7 +327,7 @@ static int __init of_create_spu(struct spu *spu, void *data)
+ if (!legacy_map) {
+ legacy_map = 1;
+ printk(KERN_WARNING "%s: Legacy device tree found, "
+- "trying to map old style\n", __FUNCTION__);
++ "trying to map old style\n", __func__);
+ }
+ ret = spu_map_device_old(spu);
+ if (ret) {
+@@ -342,7 +342,7 @@ static int __init of_create_spu(struct spu *spu, void *data)
+ if (!legacy_irq) {
+ legacy_irq = 1;
+ printk(KERN_WARNING "%s: Legacy device tree found, "
+- "trying old style irq\n", __FUNCTION__);
++ "trying old style irq\n", __func__);
+ }
+ ret = spu_map_interrupts_old(spu, spe);
+ if (ret) {
+diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
+index 0c6a96b..b962c3a 100644
+--- a/arch/powerpc/platforms/cell/spufs/coredump.c
++++ b/arch/powerpc/platforms/cell/spufs/coredump.c
+@@ -133,8 +133,6 @@ static struct spu_context *coredump_next_context(int *fd)
+ if (ctx->flags & SPU_CREATE_NOSCHED)
+ continue;
+
+- /* start searching the next fd next time we're called */
+- (*fd)++;
+ break;
+ }
+
+@@ -157,6 +155,9 @@ int spufs_coredump_extra_notes_size(void)
+ break;
+
+ size += rc;
++
++ /* start searching the next fd next time */
++ fd++;
+ }
+
+ return size;
+@@ -239,6 +240,9 @@ int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset)
+ }
+
+ spu_release_saved(ctx);
++
++ /* start searching the next fd next time */
++ fd++;
+ }
+
+ return 0;
+diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
+index f7a7e86..08f44d1 100644
+--- a/arch/powerpc/platforms/cell/spufs/file.c
++++ b/arch/powerpc/platforms/cell/spufs/file.c
+@@ -32,7 +32,6 @@
+ #include <linux/marker.h>
+
+ #include <asm/io.h>
+-#include <asm/semaphore.h>
+ #include <asm/spu.h>
+ #include <asm/spu_info.h>
+ #include <asm/uaccess.h>
+@@ -1337,7 +1336,7 @@ static u64 spufs_signal1_type_get(struct spu_context *ctx)
+ return ctx->ops->signal1_type_get(ctx);
+ }
+ DEFINE_SPUFS_ATTRIBUTE(spufs_signal1_type, spufs_signal1_type_get,
+- spufs_signal1_type_set, "%llu", SPU_ATTR_ACQUIRE);
++ spufs_signal1_type_set, "%llu\n", SPU_ATTR_ACQUIRE);
+
+
+ static int spufs_signal2_type_set(void *data, u64 val)
+@@ -1359,7 +1358,7 @@ static u64 spufs_signal2_type_get(struct spu_context *ctx)
+ return ctx->ops->signal2_type_get(ctx);
+ }
+ DEFINE_SPUFS_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get,
+- spufs_signal2_type_set, "%llu", SPU_ATTR_ACQUIRE);
++ spufs_signal2_type_set, "%llu\n", SPU_ATTR_ACQUIRE);
+
+ #if SPUFS_MMAP_4K
+ static unsigned long spufs_mss_mmap_nopfn(struct vm_area_struct *vma,
+@@ -1556,7 +1555,7 @@ void spufs_mfc_callback(struct spu *spu)
+
+ wake_up_all(&ctx->mfc_wq);
+
+- pr_debug("%s %s\n", __FUNCTION__, spu->name);
++ pr_debug("%s %s\n", __func__, spu->name);
+ if (ctx->mfc_fasync) {
+ u32 free_elements, tagstatus;
+ unsigned int mask;
+@@ -1790,7 +1789,7 @@ static unsigned int spufs_mfc_poll(struct file *file,poll_table *wait)
+ if (tagstatus & ctx->tagwait)
+ mask |= POLLIN | POLLRDNORM;
+
+- pr_debug("%s: free %d tagstatus %d tagwait %d\n", __FUNCTION__,
++ pr_debug("%s: free %d tagstatus %d tagwait %d\n", __func__,
+ free_elements, tagstatus, ctx->tagwait);
+
+ return mask;
+diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
+index 6d1228c..0c32a05 100644
+--- a/arch/powerpc/platforms/cell/spufs/inode.c
++++ b/arch/powerpc/platforms/cell/spufs/inode.c
+@@ -35,7 +35,6 @@
+ #include <linux/parser.h>
+
+ #include <asm/prom.h>
+-#include <asm/semaphore.h>
+ #include <asm/spu.h>
+ #include <asm/spu_priv1.h>
+ #include <asm/uaccess.h>
+diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
+index cac69e1..96bf7c2 100644
+--- a/arch/powerpc/platforms/cell/spufs/run.c
++++ b/arch/powerpc/platforms/cell/spufs/run.c
+@@ -98,7 +98,7 @@ static int spu_setup_isolated(struct spu_context *ctx)
+ != MFC_CNTL_PURGE_DMA_COMPLETE) {
+ if (time_after(jiffies, timeout)) {
+ printk(KERN_ERR "%s: timeout flushing MFC DMA queue\n",
+- __FUNCTION__);
++ __func__);
+ ret = -EIO;
+ goto out;
+ }
+@@ -124,7 +124,7 @@ static int spu_setup_isolated(struct spu_context *ctx)
+ status_loading) {
+ if (time_after(jiffies, timeout)) {
+ printk(KERN_ERR "%s: timeout waiting for loader\n",
+- __FUNCTION__);
++ __func__);
+ ret = -EIO;
+ goto out_drop_priv;
+ }
+@@ -134,7 +134,7 @@ static int spu_setup_isolated(struct spu_context *ctx)
+ if (!(status & SPU_STATUS_RUNNING)) {
+ /* If isolated LOAD has failed: run SPU, we will get a stop-and
+ * signal later. */
+- pr_debug("%s: isolated LOAD failed\n", __FUNCTION__);
++ pr_debug("%s: isolated LOAD failed\n", __func__);
+ ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
+ ret = -EACCES;
+ goto out_drop_priv;
+@@ -142,7 +142,7 @@ static int spu_setup_isolated(struct spu_context *ctx)
+
+ if (!(status & SPU_STATUS_ISOLATED_STATE)) {
+ /* This isn't allowed by the CBEA, but check anyway */
+- pr_debug("%s: SPU fell out of isolated mode?\n", __FUNCTION__);
++ pr_debug("%s: SPU fell out of isolated mode?\n", __func__);
+ ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_STOP);
+ ret = -EINVAL;
+ goto out_drop_priv;
+@@ -282,7 +282,7 @@ static int spu_handle_restartsys(struct spu_context *ctx, long *spu_ret,
+ break;
+ default:
+ printk(KERN_WARNING "%s: unexpected return code %ld\n",
+- __FUNCTION__, *spu_ret);
++ __func__, *spu_ret);
+ ret = 0;
+ }
+ return ret;
+@@ -323,6 +323,10 @@ static int spu_process_callback(struct spu_context *ctx)
+ return -EINTR;
+ }
+
++ /* need to re-get the ls, as it may have changed when we released the
++ * spu */
++ ls = (void __iomem *)ctx->ops->get_ls(ctx);
++
+ /* write result, jump over indirect pointer */
+ memcpy_toio(ls + ls_pointer, &spu_ret, sizeof(spu_ret));
+ ctx->ops->npc_write(ctx, npc);
+diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
+index e9dc7a5..d2a1249 100644
+--- a/arch/powerpc/platforms/cell/spufs/switch.c
++++ b/arch/powerpc/platforms/cell/spufs/switch.c
+@@ -1815,6 +1815,7 @@ static void save_csa(struct spu_state *prev, struct spu *spu)
+ save_mfc_csr_ato(prev, spu); /* Step 24. */
+ save_mfc_tclass_id(prev, spu); /* Step 25. */
+ set_mfc_tclass_id(prev, spu); /* Step 26. */
++ save_mfc_cmd(prev, spu); /* Step 26a - moved from 44. */
+ purge_mfc_queue(prev, spu); /* Step 27. */
+ wait_purge_complete(prev, spu); /* Step 28. */
+ setup_mfc_sr1(prev, spu); /* Step 30. */
+@@ -1831,7 +1832,6 @@ static void save_csa(struct spu_state *prev, struct spu *spu)
+ save_ppuint_mb(prev, spu); /* Step 41. */
+ save_ch_part1(prev, spu); /* Step 42. */
+ save_spu_mb(prev, spu); /* Step 43. */
+- save_mfc_cmd(prev, spu); /* Step 44. */
+ reset_ch(prev, spu); /* Step 45. */
+ }
+
+diff --git a/arch/powerpc/platforms/celleb/Kconfig b/arch/powerpc/platforms/celleb/Kconfig
+deleted file mode 100644
+index 372891e..0000000
+--- a/arch/powerpc/platforms/celleb/Kconfig
++++ /dev/null
+@@ -1,12 +0,0 @@
+-config PPC_CELLEB
+- bool "Toshiba's Cell Reference Set 'Celleb' Architecture"
+- depends on PPC_MULTIPLATFORM && PPC64
+- select PPC_CELL
+- select PPC_CELL_NATIVE
+- select PPC_RTAS
+- select PPC_INDIRECT_IO
+- select PPC_OF_PLATFORM_PCI
+- select HAS_TXX9_SERIAL
+- select PPC_UDBG_BEAT
+- select USB_OHCI_BIG_ENDIAN_MMIO
+- select USB_EHCI_BIG_ENDIAN_MMIO
+diff --git a/arch/powerpc/platforms/celleb/Makefile b/arch/powerpc/platforms/celleb/Makefile
+deleted file mode 100644
+index 889d43f..0000000
+--- a/arch/powerpc/platforms/celleb/Makefile
++++ /dev/null
+@@ -1,9 +0,0 @@
+-obj-y += interrupt.o iommu.o setup.o \
+- htab.o beat.o hvCall.o pci.o \
+- scc_epci.o scc_uhc.o \
+- io-workarounds.o
+-
+-obj-$(CONFIG_SMP) += smp.o
+-obj-$(CONFIG_PPC_UDBG_BEAT) += udbg_beat.o
+-obj-$(CONFIG_SERIAL_TXX9) += scc_sio.o
+-obj-$(CONFIG_SPU_BASE) += spu_priv1.o
+diff --git a/arch/powerpc/platforms/celleb/beat.c b/arch/powerpc/platforms/celleb/beat.c
+deleted file mode 100644
+index 93ebb7d..0000000
+--- a/arch/powerpc/platforms/celleb/beat.c
++++ /dev/null
+@@ -1,267 +0,0 @@
+-/*
+- * Simple routines for Celleb/Beat
+- *
+- * (C) Copyright 2006-2007 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; 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.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/err.h>
+-#include <linux/rtc.h>
+-#include <linux/interrupt.h>
+-#include <linux/irqreturn.h>
+-#include <linux/reboot.h>
+-
+-#include <asm/hvconsole.h>
+-#include <asm/time.h>
+-#include <asm/machdep.h>
+-#include <asm/firmware.h>
+-
+-#include "beat_wrapper.h"
+-#include "beat.h"
+-#include "interrupt.h"
+-
+-static int beat_pm_poweroff_flag;
+-
+-void beat_restart(char *cmd)
+-{
+- beat_shutdown_logical_partition(!beat_pm_poweroff_flag);
+-}
+-
+-void beat_power_off(void)
+-{
+- beat_shutdown_logical_partition(0);
+-}
+-
+-u64 beat_halt_code = 0x1000000000000000UL;
+-
+-void beat_halt(void)
+-{
+- beat_shutdown_logical_partition(beat_halt_code);
+-}
+-
+-int beat_set_rtc_time(struct rtc_time *rtc_time)
+-{
+- u64 tim;
+- tim = mktime(rtc_time->tm_year+1900,
+- rtc_time->tm_mon+1, rtc_time->tm_mday,
+- rtc_time->tm_hour, rtc_time->tm_min, rtc_time->tm_sec);
+- if (beat_rtc_write(tim))
+- return -1;
+- return 0;
+-}
+-
+-void beat_get_rtc_time(struct rtc_time *rtc_time)
+-{
+- u64 tim;
+-
+- if (beat_rtc_read(&tim))
+- tim = 0;
+- to_tm(tim, rtc_time);
+- rtc_time->tm_year -= 1900;
+- rtc_time->tm_mon -= 1;
+-}
+-
+-#define BEAT_NVRAM_SIZE 4096
+-
+-ssize_t beat_nvram_read(char *buf, size_t count, loff_t *index)
+-{
+- unsigned int i;
+- unsigned long len;
+- char *p = buf;
+-
+- if (*index >= BEAT_NVRAM_SIZE)
+- return -ENODEV;
+- i = *index;
+- if (i + count > BEAT_NVRAM_SIZE)
+- count = BEAT_NVRAM_SIZE - i;
+-
+- for (; count != 0; count -= len) {
+- len = count;
+- if (len > BEAT_NVRW_CNT)
+- len = BEAT_NVRW_CNT;
+- if (beat_eeprom_read(i, len, p)) {
+- return -EIO;
+- }
+-
+- p += len;
+- i += len;
+- }
+- *index = i;
+- return p - buf;
+-}
+-
+-ssize_t beat_nvram_write(char *buf, size_t count, loff_t *index)
+-{
+- unsigned int i;
+- unsigned long len;
+- char *p = buf;
+-
+- if (*index >= BEAT_NVRAM_SIZE)
+- return -ENODEV;
+- i = *index;
+- if (i + count > BEAT_NVRAM_SIZE)
+- count = BEAT_NVRAM_SIZE - i;
+-
+- for (; count != 0; count -= len) {
+- len = count;
+- if (len > BEAT_NVRW_CNT)
+- len = BEAT_NVRW_CNT;
+- if (beat_eeprom_write(i, len, p)) {
+- return -EIO;
+- }
+-
+- p += len;
+- i += len;
+- }
+- *index = i;
+- return p - buf;
+-}
+-
+-ssize_t beat_nvram_get_size(void)
+-{
+- return BEAT_NVRAM_SIZE;
+-}
+-
+-int beat_set_xdabr(unsigned long dabr)
+-{
+- if (beat_set_dabr(dabr, DABRX_KERNEL | DABRX_USER))
+- return -1;
+- return 0;
+-}
+-
+-int64_t beat_get_term_char(u64 vterm, u64 *len, u64 *t1, u64 *t2)
+-{
+- u64 db[2];
+- s64 ret;
+-
+- ret = beat_get_characters_from_console(vterm, len, (u8*)db);
+- if (ret == 0) {
+- *t1 = db[0];
+- *t2 = db[1];
+- }
+- return ret;
+-}
+-
+-int64_t beat_put_term_char(u64 vterm, u64 len, u64 t1, u64 t2)
+-{
+- u64 db[2];
+-
+- db[0] = t1;
+- db[1] = t2;
+- return beat_put_characters_to_console(vterm, len, (u8*)db);
+-}
+-
+-void beat_power_save(void)
+-{
+- beat_pause(0);
+-}
+-
+-#ifdef CONFIG_KEXEC
+-void beat_kexec_cpu_down(int crash, int secondary)
+-{
+- beatic_deinit_IRQ();
+-}
+-#endif
+-
+-static irqreturn_t beat_power_event(int virq, void *arg)
+-{
+- printk(KERN_DEBUG "Beat: power button pressed\n");
+- beat_pm_poweroff_flag = 1;
+- ctrl_alt_del();
+- return IRQ_HANDLED;
+-}
+-
+-static irqreturn_t beat_reset_event(int virq, void *arg)
+-{
+- printk(KERN_DEBUG "Beat: reset button pressed\n");
+- beat_pm_poweroff_flag = 0;
+- ctrl_alt_del();
+- return IRQ_HANDLED;
+-}
+-
+-static struct beat_event_list {
+- const char *typecode;
+- irq_handler_t handler;
+- unsigned int virq;
+-} beat_event_list[] = {
+- { "power", beat_power_event, 0 },
+- { "reset", beat_reset_event, 0 },
+-};
+-
+-static int __init beat_register_event(void)
+-{
+- u64 path[4], data[2];
+- int rc, i;
+- unsigned int virq;
+-
+- for (i = 0; i < ARRAY_SIZE(beat_event_list); i++) {
+- struct beat_event_list *ev = &beat_event_list[i];
+-
+- if (beat_construct_event_receive_port(data) != 0) {
+- printk(KERN_ERR "Beat: "
+- "cannot construct event receive port for %s\n",
+- ev->typecode);
+- return -EINVAL;
+- }
+-
+- virq = irq_create_mapping(NULL, data[0]);
+- if (virq == NO_IRQ) {
+- printk(KERN_ERR "Beat: failed to get virtual IRQ"
+- " for event receive port for %s\n",
+- ev->typecode);
+- beat_destruct_event_receive_port(data[0]);
+- return -EIO;
+- }
+- ev->virq = virq;
+-
+- rc = request_irq(virq, ev->handler, IRQF_DISABLED,
+- ev->typecode, NULL);
+- if (rc != 0) {
+- printk(KERN_ERR "Beat: failed to request virtual IRQ"
+- " for event receive port for %s\n",
+- ev->typecode);
+- beat_destruct_event_receive_port(data[0]);
+- return rc;
+- }
+-
+- path[0] = 0x1000000065780000ul; /* 1,ex */
+- path[1] = 0x627574746f6e0000ul; /* button */
+- path[2] = 0;
+- strncpy((char *)&path[2], ev->typecode, 8);
+- path[3] = 0;
+- data[1] = 0;
+-
+- beat_create_repository_node(path, data);
+- }
+- return 0;
+-}
+-
+-static int __init beat_event_init(void)
+-{
+- if (!firmware_has_feature(FW_FEATURE_BEAT))
+- return -EINVAL;
+-
+- beat_pm_poweroff_flag = 0;
+- return beat_register_event();
+-}
+-
+-device_initcall(beat_event_init);
+-
+-EXPORT_SYMBOL(beat_get_term_char);
+-EXPORT_SYMBOL(beat_put_term_char);
+-EXPORT_SYMBOL(beat_halt_code);
+diff --git a/arch/powerpc/platforms/celleb/beat.h b/arch/powerpc/platforms/celleb/beat.h
+deleted file mode 100644
+index ac82ac3..0000000
+--- a/arch/powerpc/platforms/celleb/beat.h
++++ /dev/null
+@@ -1,39 +0,0 @@
+-/*
+- * Guest OS Interfaces.
+- *
+- * (C) Copyright 2006 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; 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.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#ifndef _CELLEB_BEAT_H
+-#define _CELLEB_BEAT_H
+-
+-int64_t beat_get_term_char(uint64_t,uint64_t*,uint64_t*,uint64_t*);
+-int64_t beat_put_term_char(uint64_t,uint64_t,uint64_t,uint64_t);
+-int64_t beat_repository_encode(int, const char *, uint64_t[4]);
+-void beat_restart(char *);
+-void beat_power_off(void);
+-void beat_halt(void);
+-int beat_set_rtc_time(struct rtc_time *);
+-void beat_get_rtc_time(struct rtc_time *);
+-ssize_t beat_nvram_get_size(void);
+-ssize_t beat_nvram_read(char *, size_t, loff_t *);
+-ssize_t beat_nvram_write(char *, size_t, loff_t *);
+-int beat_set_xdabr(unsigned long);
+-void beat_power_save(void);
+-void beat_kexec_cpu_down(int, int);
+-
+-#endif /* _CELLEB_BEAT_H */
+diff --git a/arch/powerpc/platforms/celleb/beat_syscall.h b/arch/powerpc/platforms/celleb/beat_syscall.h
+deleted file mode 100644
+index 8580dc7..0000000
+--- a/arch/powerpc/platforms/celleb/beat_syscall.h
++++ /dev/null
+@@ -1,164 +0,0 @@
+-/*
+- * Beat hypervisor call numbers
+- *
+- * (C) Copyright 2004-2007 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; 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.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#ifndef BEAT_BEAT_syscall_H
+-#define BEAT_BEAT_syscall_H
+-
+-#ifdef __ASSEMBLY__
+-#define __BEAT_ADD_VENDOR_ID(__x, __v) ((__v)<<60|(__x))
+-#else
+-#define __BEAT_ADD_VENDOR_ID(__x, __v) ((u64)(__v)<<60|(__x))
+-#endif
+-#define HV_allocate_memory __BEAT_ADD_VENDOR_ID(0, 0)
+-#define HV_construct_virtual_address_space __BEAT_ADD_VENDOR_ID(2, 0)
+-#define HV_destruct_virtual_address_space __BEAT_ADD_VENDOR_ID(10, 0)
+-#define HV_get_virtual_address_space_id_of_ppe __BEAT_ADD_VENDOR_ID(4, 0)
+-#define HV_query_logical_partition_address_region_info \
+- __BEAT_ADD_VENDOR_ID(6, 0)
+-#define HV_release_memory __BEAT_ADD_VENDOR_ID(13, 0)
+-#define HV_select_virtual_address_space __BEAT_ADD_VENDOR_ID(7, 0)
+-#define HV_load_range_registers __BEAT_ADD_VENDOR_ID(68, 0)
+-#define HV_set_ppe_l2cache_rmt_entry __BEAT_ADD_VENDOR_ID(70, 0)
+-#define HV_set_ppe_tlb_rmt_entry __BEAT_ADD_VENDOR_ID(71, 0)
+-#define HV_set_spe_tlb_rmt_entry __BEAT_ADD_VENDOR_ID(72, 0)
+-#define HV_get_io_address_translation_fault_info __BEAT_ADD_VENDOR_ID(14, 0)
+-#define HV_get_iopte __BEAT_ADD_VENDOR_ID(16, 0)
+-#define HV_preload_iopt_cache __BEAT_ADD_VENDOR_ID(17, 0)
+-#define HV_put_iopte __BEAT_ADD_VENDOR_ID(15, 0)
+-#define HV_connect_event_ports __BEAT_ADD_VENDOR_ID(21, 0)
+-#define HV_construct_event_receive_port __BEAT_ADD_VENDOR_ID(18, 0)
+-#define HV_destruct_event_receive_port __BEAT_ADD_VENDOR_ID(19, 0)
+-#define HV_destruct_event_send_port __BEAT_ADD_VENDOR_ID(22, 0)
+-#define HV_get_state_of_event_send_port __BEAT_ADD_VENDOR_ID(25, 0)
+-#define HV_request_to_connect_event_ports __BEAT_ADD_VENDOR_ID(20, 0)
+-#define HV_send_event_externally __BEAT_ADD_VENDOR_ID(23, 0)
+-#define HV_send_event_locally __BEAT_ADD_VENDOR_ID(24, 0)
+-#define HV_construct_and_connect_irq_plug __BEAT_ADD_VENDOR_ID(28, 0)
+-#define HV_destruct_irq_plug __BEAT_ADD_VENDOR_ID(29, 0)
+-#define HV_detect_pending_interrupts __BEAT_ADD_VENDOR_ID(26, 0)
+-#define HV_end_of_interrupt __BEAT_ADD_VENDOR_ID(27, 0)
+-#define HV_assign_control_signal_notification_port __BEAT_ADD_VENDOR_ID(45, 0)
+-#define HV_end_of_control_signal_processing __BEAT_ADD_VENDOR_ID(48, 0)
+-#define HV_get_control_signal __BEAT_ADD_VENDOR_ID(46, 0)
+-#define HV_set_irq_mask_for_spe __BEAT_ADD_VENDOR_ID(61, 0)
+-#define HV_shutdown_logical_partition __BEAT_ADD_VENDOR_ID(44, 0)
+-#define HV_connect_message_ports __BEAT_ADD_VENDOR_ID(35, 0)
+-#define HV_destruct_message_port __BEAT_ADD_VENDOR_ID(36, 0)
+-#define HV_receive_message __BEAT_ADD_VENDOR_ID(37, 0)
+-#define HV_get_message_port_info __BEAT_ADD_VENDOR_ID(34, 0)
+-#define HV_request_to_connect_message_ports __BEAT_ADD_VENDOR_ID(33, 0)
+-#define HV_send_message __BEAT_ADD_VENDOR_ID(32, 0)
+-#define HV_get_logical_ppe_id __BEAT_ADD_VENDOR_ID(69, 0)
+-#define HV_pause __BEAT_ADD_VENDOR_ID(9, 0)
+-#define HV_destruct_shared_memory_handle __BEAT_ADD_VENDOR_ID(51, 0)
+-#define HV_get_shared_memory_info __BEAT_ADD_VENDOR_ID(52, 0)
+-#define HV_permit_sharing_memory __BEAT_ADD_VENDOR_ID(50, 0)
+-#define HV_request_to_attach_shared_memory __BEAT_ADD_VENDOR_ID(49, 0)
+-#define HV_enable_logical_spe_execution __BEAT_ADD_VENDOR_ID(55, 0)
+-#define HV_construct_logical_spe __BEAT_ADD_VENDOR_ID(53, 0)
+-#define HV_disable_logical_spe_execution __BEAT_ADD_VENDOR_ID(56, 0)
+-#define HV_destruct_logical_spe __BEAT_ADD_VENDOR_ID(54, 0)
+-#define HV_sense_spe_execution_status __BEAT_ADD_VENDOR_ID(58, 0)
+-#define HV_insert_htab_entry __BEAT_ADD_VENDOR_ID(101, 0)
+-#define HV_read_htab_entries __BEAT_ADD_VENDOR_ID(95, 0)
+-#define HV_write_htab_entry __BEAT_ADD_VENDOR_ID(94, 0)
+-#define HV_assign_io_address_translation_fault_port \
+- __BEAT_ADD_VENDOR_ID(100, 0)
+-#define HV_set_interrupt_mask __BEAT_ADD_VENDOR_ID(73, 0)
+-#define HV_get_logical_partition_id __BEAT_ADD_VENDOR_ID(74, 0)
+-#define HV_create_repository_node2 __BEAT_ADD_VENDOR_ID(90, 0)
+-#define HV_create_repository_node __BEAT_ADD_VENDOR_ID(90, 0) /* alias */
+-#define HV_get_repository_node_value2 __BEAT_ADD_VENDOR_ID(91, 0)
+-#define HV_get_repository_node_value __BEAT_ADD_VENDOR_ID(91, 0) /* alias */
+-#define HV_modify_repository_node_value2 __BEAT_ADD_VENDOR_ID(92, 0)
+-#define HV_modify_repository_node_value __BEAT_ADD_VENDOR_ID(92, 0) /* alias */
+-#define HV_remove_repository_node2 __BEAT_ADD_VENDOR_ID(93, 0)
+-#define HV_remove_repository_node __BEAT_ADD_VENDOR_ID(93, 0) /* alias */
+-#define HV_cancel_shared_memory __BEAT_ADD_VENDOR_ID(104, 0)
+-#define HV_clear_interrupt_status_of_spe __BEAT_ADD_VENDOR_ID(206, 0)
+-#define HV_construct_spe_irq_outlet __BEAT_ADD_VENDOR_ID(80, 0)
+-#define HV_destruct_spe_irq_outlet __BEAT_ADD_VENDOR_ID(81, 0)
+-#define HV_disconnect_ipspc_service __BEAT_ADD_VENDOR_ID(88, 0)
+-#define HV_execute_ipspc_command __BEAT_ADD_VENDOR_ID(86, 0)
+-#define HV_get_interrupt_status_of_spe __BEAT_ADD_VENDOR_ID(205, 0)
+-#define HV_get_spe_privileged_state_1_registers __BEAT_ADD_VENDOR_ID(208, 0)
+-#define HV_permit_use_of_ipspc_service __BEAT_ADD_VENDOR_ID(85, 0)
+-#define HV_reinitialize_logical_spe __BEAT_ADD_VENDOR_ID(82, 0)
+-#define HV_request_ipspc_service __BEAT_ADD_VENDOR_ID(84, 0)
+-#define HV_stop_ipspc_command __BEAT_ADD_VENDOR_ID(87, 0)
+-#define HV_set_spe_privileged_state_1_registers __BEAT_ADD_VENDOR_ID(204, 0)
+-#define HV_get_status_of_ipspc_service __BEAT_ADD_VENDOR_ID(203, 0)
+-#define HV_put_characters_to_console __BEAT_ADD_VENDOR_ID(0x101, 1)
+-#define HV_get_characters_from_console __BEAT_ADD_VENDOR_ID(0x102, 1)
+-#define HV_get_base_clock __BEAT_ADD_VENDOR_ID(0x111, 1)
+-#define HV_set_base_clock __BEAT_ADD_VENDOR_ID(0x112, 1)
+-#define HV_get_frame_cycle __BEAT_ADD_VENDOR_ID(0x114, 1)
+-#define HV_disable_console __BEAT_ADD_VENDOR_ID(0x115, 1)
+-#define HV_disable_all_console __BEAT_ADD_VENDOR_ID(0x116, 1)
+-#define HV_oneshot_timer __BEAT_ADD_VENDOR_ID(0x117, 1)
+-#define HV_set_dabr __BEAT_ADD_VENDOR_ID(0x118, 1)
+-#define HV_get_dabr __BEAT_ADD_VENDOR_ID(0x119, 1)
+-#define HV_start_hv_stats __BEAT_ADD_VENDOR_ID(0x21c, 1)
+-#define HV_stop_hv_stats __BEAT_ADD_VENDOR_ID(0x21d, 1)
+-#define HV_get_hv_stats __BEAT_ADD_VENDOR_ID(0x21e, 1)
+-#define HV_get_hv_error_stats __BEAT_ADD_VENDOR_ID(0x221, 1)
+-#define HV_get_stats __BEAT_ADD_VENDOR_ID(0x224, 1)
+-#define HV_get_heap_stats __BEAT_ADD_VENDOR_ID(0x225, 1)
+-#define HV_get_memory_stats __BEAT_ADD_VENDOR_ID(0x227, 1)
+-#define HV_get_memory_detail __BEAT_ADD_VENDOR_ID(0x228, 1)
+-#define HV_set_priority_of_irq_outlet __BEAT_ADD_VENDOR_ID(0x122, 1)
+-#define HV_get_physical_spe_by_reservation_id __BEAT_ADD_VENDOR_ID(0x128, 1)
+-#define HV_get_spe_context __BEAT_ADD_VENDOR_ID(0x129, 1)
+-#define HV_set_spe_context __BEAT_ADD_VENDOR_ID(0x12a, 1)
+-#define HV_downcount_of_interrupt __BEAT_ADD_VENDOR_ID(0x12e, 1)
+-#define HV_peek_spe_context __BEAT_ADD_VENDOR_ID(0x12f, 1)
+-#define HV_read_bpa_register __BEAT_ADD_VENDOR_ID(0x131, 1)
+-#define HV_write_bpa_register __BEAT_ADD_VENDOR_ID(0x132, 1)
+-#define HV_map_context_table_of_spe __BEAT_ADD_VENDOR_ID(0x137, 1)
+-#define HV_get_slb_for_logical_spe __BEAT_ADD_VENDOR_ID(0x138, 1)
+-#define HV_set_slb_for_logical_spe __BEAT_ADD_VENDOR_ID(0x139, 1)
+-#define HV_init_pm __BEAT_ADD_VENDOR_ID(0x150, 1)
+-#define HV_set_pm_signal __BEAT_ADD_VENDOR_ID(0x151, 1)
+-#define HV_get_pm_signal __BEAT_ADD_VENDOR_ID(0x152, 1)
+-#define HV_set_pm_config __BEAT_ADD_VENDOR_ID(0x153, 1)
+-#define HV_get_pm_config __BEAT_ADD_VENDOR_ID(0x154, 1)
+-#define HV_get_inner_trace_data __BEAT_ADD_VENDOR_ID(0x155, 1)
+-#define HV_set_ext_trace_buffer __BEAT_ADD_VENDOR_ID(0x156, 1)
+-#define HV_get_ext_trace_buffer __BEAT_ADD_VENDOR_ID(0x157, 1)
+-#define HV_set_pm_interrupt __BEAT_ADD_VENDOR_ID(0x158, 1)
+-#define HV_get_pm_interrupt __BEAT_ADD_VENDOR_ID(0x159, 1)
+-#define HV_kick_pm __BEAT_ADD_VENDOR_ID(0x160, 1)
+-#define HV_construct_pm_context __BEAT_ADD_VENDOR_ID(0x164, 1)
+-#define HV_destruct_pm_context __BEAT_ADD_VENDOR_ID(0x165, 1)
+-#define HV_be_slow __BEAT_ADD_VENDOR_ID(0x170, 1)
+-#define HV_assign_ipspc_server_connection_status_notification_port \
+- __BEAT_ADD_VENDOR_ID(0x173, 1)
+-#define HV_get_raid_of_physical_spe __BEAT_ADD_VENDOR_ID(0x174, 1)
+-#define HV_set_physical_spe_to_rag __BEAT_ADD_VENDOR_ID(0x175, 1)
+-#define HV_release_physical_spe_from_rag __BEAT_ADD_VENDOR_ID(0x176, 1)
+-#define HV_rtc_read __BEAT_ADD_VENDOR_ID(0x190, 1)
+-#define HV_rtc_write __BEAT_ADD_VENDOR_ID(0x191, 1)
+-#define HV_eeprom_read __BEAT_ADD_VENDOR_ID(0x192, 1)
+-#define HV_eeprom_write __BEAT_ADD_VENDOR_ID(0x193, 1)
+-#define HV_insert_htab_entry3 __BEAT_ADD_VENDOR_ID(0x104, 1)
+-#define HV_invalidate_htab_entry3 __BEAT_ADD_VENDOR_ID(0x105, 1)
+-#define HV_update_htab_permission3 __BEAT_ADD_VENDOR_ID(0x106, 1)
+-#define HV_clear_htab3 __BEAT_ADD_VENDOR_ID(0x107, 1)
+-#endif
+diff --git a/arch/powerpc/platforms/celleb/beat_wrapper.h b/arch/powerpc/platforms/celleb/beat_wrapper.h
+deleted file mode 100644
+index cbc1487..0000000
+--- a/arch/powerpc/platforms/celleb/beat_wrapper.h
++++ /dev/null
+@@ -1,288 +0,0 @@
+-/*
+- * Beat hypervisor call I/F
+- *
+- * (C) Copyright 2007 TOSHIBA CORPORATION
+- *
+- * This code is based on arch/powerpc/platforms/pseries/plpar_wrapper.h.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-#ifndef BEAT_HCALL
+-#include "beat_syscall.h"
+-
+-/* defined in hvCall.S */
+-extern s64 beat_hcall_norets(u64 opcode, ...);
+-extern s64 beat_hcall_norets8(u64 opcode, u64 arg1, u64 arg2, u64 arg3,
+- u64 arg4, u64 arg5, u64 arg6, u64 arg7, u64 arg8);
+-extern s64 beat_hcall1(u64 opcode, u64 retbuf[1], ...);
+-extern s64 beat_hcall2(u64 opcode, u64 retbuf[2], ...);
+-extern s64 beat_hcall3(u64 opcode, u64 retbuf[3], ...);
+-extern s64 beat_hcall4(u64 opcode, u64 retbuf[4], ...);
+-extern s64 beat_hcall5(u64 opcode, u64 retbuf[5], ...);
+-extern s64 beat_hcall6(u64 opcode, u64 retbuf[6], ...);
+-
+-static inline s64 beat_downcount_of_interrupt(u64 plug_id)
+-{
+- return beat_hcall_norets(HV_downcount_of_interrupt, plug_id);
+-}
+-
+-static inline s64 beat_set_interrupt_mask(u64 index,
+- u64 val0, u64 val1, u64 val2, u64 val3)
+-{
+- return beat_hcall_norets(HV_set_interrupt_mask, index,
+- val0, val1, val2, val3);
+-}
+-
+-static inline s64 beat_destruct_irq_plug(u64 plug_id)
+-{
+- return beat_hcall_norets(HV_destruct_irq_plug, plug_id);
+-}
+-
+-static inline s64 beat_construct_and_connect_irq_plug(u64 plug_id,
+- u64 outlet_id)
+-{
+- return beat_hcall_norets(HV_construct_and_connect_irq_plug, plug_id,
+- outlet_id);
+-}
+-
+-static inline s64 beat_detect_pending_interrupts(u64 index, u64 *retbuf)
+-{
+- return beat_hcall4(HV_detect_pending_interrupts, retbuf, index);
+-}
+-
+-static inline s64 beat_pause(u64 style)
+-{
+- return beat_hcall_norets(HV_pause, style);
+-}
+-
+-static inline s64 beat_read_htab_entries(u64 htab_id, u64 index, u64 *retbuf)
+-{
+- return beat_hcall5(HV_read_htab_entries, retbuf, htab_id, index);
+-}
+-
+-static inline s64 beat_insert_htab_entry(u64 htab_id, u64 group,
+- u64 bitmask, u64 hpte_v, u64 hpte_r, u64 *slot)
+-{
+- u64 dummy[3];
+- s64 ret;
+-
+- ret = beat_hcall3(HV_insert_htab_entry, dummy, htab_id, group,
+- bitmask, hpte_v, hpte_r);
+- *slot = dummy[0];
+- return ret;
+-}
+-
+-static inline s64 beat_write_htab_entry(u64 htab_id, u64 slot,
+- u64 hpte_v, u64 hpte_r, u64 mask_v, u64 mask_r,
+- u64 *ret_v, u64 *ret_r)
+-{
+- u64 dummy[2];
+- s64 ret;
+-
+- ret = beat_hcall2(HV_write_htab_entry, dummy, htab_id, slot,
+- hpte_v, hpte_r, mask_v, mask_r);
+- *ret_v = dummy[0];
+- *ret_r = dummy[1];
+- return ret;
+-}
+-
+-static inline s64 beat_insert_htab_entry3(u64 htab_id, u64 group,
+- u64 hpte_v, u64 hpte_r, u64 mask_v, u64 value_v, u64 *slot)
+-{
+- u64 dummy[1];
+- s64 ret;
+-
+- ret = beat_hcall1(HV_insert_htab_entry3, dummy, htab_id, group,
+- hpte_v, hpte_r, mask_v, value_v);
+- *slot = dummy[0];
+- return ret;
+-}
+-
+-static inline s64 beat_invalidate_htab_entry3(u64 htab_id, u64 group,
+- u64 va, u64 pss)
+-{
+- return beat_hcall_norets(HV_invalidate_htab_entry3,
+- htab_id, group, va, pss);
+-}
+-
+-static inline s64 beat_update_htab_permission3(u64 htab_id, u64 group,
+- u64 va, u64 pss, u64 ptel_mask, u64 ptel_value)
+-{
+- return beat_hcall_norets(HV_update_htab_permission3,
+- htab_id, group, va, pss, ptel_mask, ptel_value);
+-}
+-
+-static inline s64 beat_clear_htab3(u64 htab_id)
+-{
+- return beat_hcall_norets(HV_clear_htab3, htab_id);
+-}
+-
+-static inline void beat_shutdown_logical_partition(u64 code)
+-{
+- (void)beat_hcall_norets(HV_shutdown_logical_partition, code);
+-}
+-
+-static inline s64 beat_rtc_write(u64 time_from_epoch)
+-{
+- return beat_hcall_norets(HV_rtc_write, time_from_epoch);
+-}
+-
+-static inline s64 beat_rtc_read(u64 *time_from_epoch)
+-{
+- u64 dummy[1];
+- s64 ret;
+-
+- ret = beat_hcall1(HV_rtc_read, dummy);
+- *time_from_epoch = dummy[0];
+- return ret;
+-}
+-
+-#define BEAT_NVRW_CNT (sizeof(u64) * 6)
+-
+-static inline s64 beat_eeprom_write(u64 index, u64 length, u8 *buffer)
+-{
+- u64 b[6];
+-
+- if (length > BEAT_NVRW_CNT)
+- return -1;
+- memcpy(b, buffer, sizeof(b));
+- return beat_hcall_norets8(HV_eeprom_write, index, length,
+- b[0], b[1], b[2], b[3], b[4], b[5]);
+-}
+-
+-static inline s64 beat_eeprom_read(u64 index, u64 length, u8 *buffer)
+-{
+- u64 b[6];
+- s64 ret;
+-
+- if (length > BEAT_NVRW_CNT)
+- return -1;
+- ret = beat_hcall6(HV_eeprom_read, b, index, length);
+- memcpy(buffer, b, length);
+- return ret;
+-}
+-
+-static inline s64 beat_set_dabr(u64 value, u64 style)
+-{
+- return beat_hcall_norets(HV_set_dabr, value, style);
+-}
+-
+-static inline s64 beat_get_characters_from_console(u64 termno, u64 *len,
+- u8 *buffer)
+-{
+- u64 dummy[3];
+- s64 ret;
+-
+- ret = beat_hcall3(HV_get_characters_from_console, dummy, termno, len);
+- *len = dummy[0];
+- memcpy(buffer, dummy + 1, *len);
+- return ret;
+-}
+-
+-static inline s64 beat_put_characters_to_console(u64 termno, u64 len,
+- u8 *buffer)
+-{
+- u64 b[2];
+-
+- memcpy(b, buffer, len);
+- return beat_hcall_norets(HV_put_characters_to_console, termno, len, b[0], b[1]);
+-}
+-
+-static inline s64 beat_get_spe_privileged_state_1_registers(
+- u64 id, u64 offsetof, u64 *value)
+-{
+- u64 dummy[1];
+- s64 ret;
+-
+- ret = beat_hcall1(HV_get_spe_privileged_state_1_registers, dummy, id,
+- offsetof);
+- *value = dummy[0];
+- return ret;
+-}
+-
+-static inline s64 beat_set_irq_mask_for_spe(u64 id, u64 class, u64 mask)
+-{
+- return beat_hcall_norets(HV_set_irq_mask_for_spe, id, class, mask);
+-}
+-
+-static inline s64 beat_clear_interrupt_status_of_spe(u64 id, u64 class,
+- u64 mask)
+-{
+- return beat_hcall_norets(HV_clear_interrupt_status_of_spe,
+- id, class, mask);
+-}
+-
+-static inline s64 beat_set_spe_privileged_state_1_registers(
+- u64 id, u64 offsetof, u64 value)
+-{
+- return beat_hcall_norets(HV_set_spe_privileged_state_1_registers,
+- id, offsetof, value);
+-}
+-
+-static inline s64 beat_get_interrupt_status_of_spe(u64 id, u64 class, u64 *val)
+-{
+- u64 dummy[1];
+- s64 ret;
+-
+- ret = beat_hcall1(HV_get_interrupt_status_of_spe, dummy, id, class);
+- *val = dummy[0];
+- return ret;
+-}
+-
+-static inline s64 beat_put_iopte(u64 ioas_id, u64 io_addr, u64 real_addr,
+- u64 ioid, u64 flags)
+-{
+- return beat_hcall_norets(HV_put_iopte, ioas_id, io_addr, real_addr,
+- ioid, flags);
+-}
+-
+-static inline s64 beat_construct_event_receive_port(u64 *port)
+-{
+- u64 dummy[1];
+- s64 ret;
+-
+- ret = beat_hcall1(HV_construct_event_receive_port, dummy);
+- *port = dummy[0];
+- return ret;
+-}
+-
+-static inline s64 beat_destruct_event_receive_port(u64 port)
+-{
+- s64 ret;
+-
+- ret = beat_hcall_norets(HV_destruct_event_receive_port, port);
+- return ret;
+-}
+-
+-static inline s64 beat_create_repository_node(u64 path[4], u64 data[2])
+-{
+- s64 ret;
+-
+- ret = beat_hcall_norets(HV_create_repository_node2,
+- path[0], path[1], path[2], path[3], data[0], data[1]);
+- return ret;
+-}
+-
+-static inline s64 beat_get_repository_node_value(u64 lpid, u64 path[4],
+- u64 data[2])
+-{
+- s64 ret;
+-
+- ret = beat_hcall2(HV_get_repository_node_value2, data,
+- lpid, path[0], path[1], path[2], path[3]);
+- return ret;
+-}
+-
+-#endif
+diff --git a/arch/powerpc/platforms/celleb/htab.c b/arch/powerpc/platforms/celleb/htab.c
+deleted file mode 100644
+index fbf27c7..0000000
+--- a/arch/powerpc/platforms/celleb/htab.c
++++ /dev/null
+@@ -1,440 +0,0 @@
+-/*
+- * "Cell Reference Set" HTAB support.
+- *
+- * (C) Copyright 2006-2007 TOSHIBA CORPORATION
+- *
+- * This code is based on arch/powerpc/platforms/pseries/lpar.c:
+- * Copyright (C) 2001 Todd Inglett, IBM Corporation
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; 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.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#undef DEBUG_LOW
+-
+-#include <linux/kernel.h>
+-#include <linux/spinlock.h>
+-
+-#include <asm/mmu.h>
+-#include <asm/page.h>
+-#include <asm/pgtable.h>
+-#include <asm/machdep.h>
+-#include <asm/udbg.h>
+-
+-#include "beat_wrapper.h"
+-
+-#ifdef DEBUG_LOW
+-#define DBG_LOW(fmt...) do { udbg_printf(fmt); } while(0)
+-#else
+-#define DBG_LOW(fmt...) do { } while(0)
+-#endif
+-
+-static DEFINE_SPINLOCK(beat_htab_lock);
+-
+-static inline unsigned int beat_read_mask(unsigned hpte_group)
+-{
+- unsigned long hpte_v[5];
+- unsigned long rmask = 0;
+-
+- beat_read_htab_entries(0, hpte_group + 0, hpte_v);
+- if (!(hpte_v[0] & HPTE_V_BOLTED))
+- rmask |= 0x8000;
+- if (!(hpte_v[1] & HPTE_V_BOLTED))
+- rmask |= 0x4000;
+- if (!(hpte_v[2] & HPTE_V_BOLTED))
+- rmask |= 0x2000;
+- if (!(hpte_v[3] & HPTE_V_BOLTED))
+- rmask |= 0x1000;
+- beat_read_htab_entries(0, hpte_group + 4, hpte_v);
+- if (!(hpte_v[0] & HPTE_V_BOLTED))
+- rmask |= 0x0800;
+- if (!(hpte_v[1] & HPTE_V_BOLTED))
+- rmask |= 0x0400;
+- if (!(hpte_v[2] & HPTE_V_BOLTED))
+- rmask |= 0x0200;
+- if (!(hpte_v[3] & HPTE_V_BOLTED))
+- rmask |= 0x0100;
+- hpte_group = ~hpte_group & (htab_hash_mask * HPTES_PER_GROUP);
+- beat_read_htab_entries(0, hpte_group + 0, hpte_v);
+- if (!(hpte_v[0] & HPTE_V_BOLTED))
+- rmask |= 0x80;
+- if (!(hpte_v[1] & HPTE_V_BOLTED))
+- rmask |= 0x40;
+- if (!(hpte_v[2] & HPTE_V_BOLTED))
+- rmask |= 0x20;
+- if (!(hpte_v[3] & HPTE_V_BOLTED))
+- rmask |= 0x10;
+- beat_read_htab_entries(0, hpte_group + 4, hpte_v);
+- if (!(hpte_v[0] & HPTE_V_BOLTED))
+- rmask |= 0x08;
+- if (!(hpte_v[1] & HPTE_V_BOLTED))
+- rmask |= 0x04;
+- if (!(hpte_v[2] & HPTE_V_BOLTED))
+- rmask |= 0x02;
+- if (!(hpte_v[3] & HPTE_V_BOLTED))
+- rmask |= 0x01;
+- return rmask;
+-}
+-
+-static long beat_lpar_hpte_insert(unsigned long hpte_group,
+- unsigned long va, unsigned long pa,
+- unsigned long rflags, unsigned long vflags,
+- int psize, int ssize)
+-{
+- unsigned long lpar_rc;
+- unsigned long slot;
+- unsigned long hpte_v, hpte_r;
+-
+- /* same as iseries */
+- if (vflags & HPTE_V_SECONDARY)
+- return -1;
+-
+- if (!(vflags & HPTE_V_BOLTED))
+- DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
+- "rflags=%lx, vflags=%lx, psize=%d)\n",
+- hpte_group, va, pa, rflags, vflags, psize);
+-
+- hpte_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M) |
+- vflags | HPTE_V_VALID;
+- hpte_r = hpte_encode_r(pa, psize) | rflags;
+-
+- if (!(vflags & HPTE_V_BOLTED))
+- DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
+-
+- if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE))
+- hpte_r &= ~_PAGE_COHERENT;
+-
+- spin_lock(&beat_htab_lock);
+- if ((lpar_rc = beat_read_mask(hpte_group)) == 0) {
+- if (!(vflags & HPTE_V_BOLTED))
+- DBG_LOW(" full\n");
+- spin_unlock(&beat_htab_lock);
+- return -1;
+- }
+-
+- lpar_rc = beat_insert_htab_entry(0, hpte_group, lpar_rc << 48,
+- hpte_v, hpte_r, &slot);
+- spin_unlock(&beat_htab_lock);
+-
+- /*
+- * Since we try and ioremap PHBs we don't own, the pte insert
+- * will fail. However we must catch the failure in hash_page
+- * or we will loop forever, so return -2 in this case.
+- */
+- if (unlikely(lpar_rc != 0)) {
+- if (!(vflags & HPTE_V_BOLTED))
+- DBG_LOW(" lpar err %lx\n", lpar_rc);
+- return -2;
+- }
+- if (!(vflags & HPTE_V_BOLTED))
+- DBG_LOW(" -> slot: %lx\n", slot);
+-
+- /* We have to pass down the secondary bucket bit here as well */
+- return (slot ^ hpte_group) & 15;
+-}
+-
+-static long beat_lpar_hpte_remove(unsigned long hpte_group)
+-{
+- DBG_LOW("hpte_remove(group=%lx)\n", hpte_group);
+- return -1;
+-}
+-
+-static unsigned long beat_lpar_hpte_getword0(unsigned long slot)
+-{
+- unsigned long dword0, dword[5];
+- unsigned long lpar_rc;
+-
+- lpar_rc = beat_read_htab_entries(0, slot & ~3UL, dword);
+-
+- dword0 = dword[slot&3];
+-
+- BUG_ON(lpar_rc != 0);
+-
+- return dword0;
+-}
+-
+-static void beat_lpar_hptab_clear(void)
+-{
+- unsigned long size_bytes = 1UL << ppc64_pft_size;
+- unsigned long hpte_count = size_bytes >> 4;
+- int i;
+- unsigned long dummy0, dummy1;
+-
+- /* TODO: Use bulk call */
+- for (i = 0; i < hpte_count; i++)
+- beat_write_htab_entry(0, i, 0, 0, -1UL, -1UL, &dummy0, &dummy1);
+-}
+-
+-/*
+- * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and
+- * the low 3 bits of flags happen to line up. So no transform is needed.
+- * We can probably optimize here and assume the high bits of newpp are
+- * already zero. For now I am paranoid.
+- */
+-static long beat_lpar_hpte_updatepp(unsigned long slot,
+- unsigned long newpp,
+- unsigned long va,
+- int psize, int ssize, int local)
+-{
+- unsigned long lpar_rc;
+- unsigned long dummy0, dummy1, want_v;
+-
+- want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+-
+- DBG_LOW(" update: "
+- "avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ",
+- want_v & HPTE_V_AVPN, slot, psize, newpp);
+-
+- spin_lock(&beat_htab_lock);
+- dummy0 = beat_lpar_hpte_getword0(slot);
+- if ((dummy0 & ~0x7FUL) != (want_v & ~0x7FUL)) {
+- DBG_LOW("not found !\n");
+- spin_unlock(&beat_htab_lock);
+- return -1;
+- }
+-
+- lpar_rc = beat_write_htab_entry(0, slot, 0, newpp, 0, 7, &dummy0,
+- &dummy1);
+- spin_unlock(&beat_htab_lock);
+- if (lpar_rc != 0 || dummy0 == 0) {
+- DBG_LOW("not found !\n");
+- return -1;
+- }
+-
+- DBG_LOW("ok %lx %lx\n", dummy0, dummy1);
+-
+- BUG_ON(lpar_rc != 0);
+-
+- return 0;
+-}
+-
+-static long beat_lpar_hpte_find(unsigned long va, int psize)
+-{
+- unsigned long hash;
+- unsigned long i, j;
+- long slot;
+- unsigned long want_v, hpte_v;
+-
+- hash = hpt_hash(va, mmu_psize_defs[psize].shift, MMU_SEGSIZE_256M);
+- want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+-
+- for (j = 0; j < 2; j++) {
+- slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
+- for (i = 0; i < HPTES_PER_GROUP; i++) {
+- hpte_v = beat_lpar_hpte_getword0(slot);
+-
+- if (HPTE_V_COMPARE(hpte_v, want_v)
+- && (hpte_v & HPTE_V_VALID)
+- && (!!(hpte_v & HPTE_V_SECONDARY) == j)) {
+- /* HPTE matches */
+- if (j)
+- slot = -slot;
+- return slot;
+- }
+- ++slot;
+- }
+- hash = ~hash;
+- }
+-
+- return -1;
+-}
+-
+-static void beat_lpar_hpte_updateboltedpp(unsigned long newpp,
+- unsigned long ea,
+- int psize, int ssize)
+-{
+- unsigned long lpar_rc, slot, vsid, va, dummy0, dummy1;
+-
+- vsid = get_kernel_vsid(ea, MMU_SEGSIZE_256M);
+- va = (vsid << 28) | (ea & 0x0fffffff);
+-
+- spin_lock(&beat_htab_lock);
+- slot = beat_lpar_hpte_find(va, psize);
+- BUG_ON(slot == -1);
+-
+- lpar_rc = beat_write_htab_entry(0, slot, 0, newpp, 0, 7,
+- &dummy0, &dummy1);
+- spin_unlock(&beat_htab_lock);
+-
+- BUG_ON(lpar_rc != 0);
+-}
+-
+-static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
+- int psize, int ssize, int local)
+-{
+- unsigned long want_v;
+- unsigned long lpar_rc;
+- unsigned long dummy1, dummy2;
+- unsigned long flags;
+-
+- DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
+- slot, va, psize, local);
+- want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+-
+- spin_lock_irqsave(&beat_htab_lock, flags);
+- dummy1 = beat_lpar_hpte_getword0(slot);
+-
+- if ((dummy1 & ~0x7FUL) != (want_v & ~0x7FUL)) {
+- DBG_LOW("not found !\n");
+- spin_unlock_irqrestore(&beat_htab_lock, flags);
+- return;
+- }
+-
+- lpar_rc = beat_write_htab_entry(0, slot, 0, 0, HPTE_V_VALID, 0,
+- &dummy1, &dummy2);
+- spin_unlock_irqrestore(&beat_htab_lock, flags);
+-
+- BUG_ON(lpar_rc != 0);
+-}
+-
+-void __init hpte_init_beat(void)
+-{
+- ppc_md.hpte_invalidate = beat_lpar_hpte_invalidate;
+- ppc_md.hpte_updatepp = beat_lpar_hpte_updatepp;
+- ppc_md.hpte_updateboltedpp = beat_lpar_hpte_updateboltedpp;
+- ppc_md.hpte_insert = beat_lpar_hpte_insert;
+- ppc_md.hpte_remove = beat_lpar_hpte_remove;
+- ppc_md.hpte_clear_all = beat_lpar_hptab_clear;
+-}
+-
+-static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
+- unsigned long va, unsigned long pa,
+- unsigned long rflags, unsigned long vflags,
+- int psize, int ssize)
+-{
+- unsigned long lpar_rc;
+- unsigned long slot;
+- unsigned long hpte_v, hpte_r;
+-
+- /* same as iseries */
+- if (vflags & HPTE_V_SECONDARY)
+- return -1;
+-
+- if (!(vflags & HPTE_V_BOLTED))
+- DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
+- "rflags=%lx, vflags=%lx, psize=%d)\n",
+- hpte_group, va, pa, rflags, vflags, psize);
+-
+- hpte_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M) |
+- vflags | HPTE_V_VALID;
+- hpte_r = hpte_encode_r(pa, psize) | rflags;
+-
+- if (!(vflags & HPTE_V_BOLTED))
+- DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
+-
+- if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE))
+- hpte_r &= ~_PAGE_COHERENT;
+-
+- /* insert into not-volted entry */
+- lpar_rc = beat_insert_htab_entry3(0, hpte_group, hpte_v, hpte_r,
+- HPTE_V_BOLTED, 0, &slot);
+- /*
+- * Since we try and ioremap PHBs we don't own, the pte insert
+- * will fail. However we must catch the failure in hash_page
+- * or we will loop forever, so return -2 in this case.
+- */
+- if (unlikely(lpar_rc != 0)) {
+- if (!(vflags & HPTE_V_BOLTED))
+- DBG_LOW(" lpar err %lx\n", lpar_rc);
+- return -2;
+- }
+- if (!(vflags & HPTE_V_BOLTED))
+- DBG_LOW(" -> slot: %lx\n", slot);
+-
+- /* We have to pass down the secondary bucket bit here as well */
+- return (slot ^ hpte_group) & 15;
+-}
+-
+-/*
+- * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and
+- * the low 3 bits of flags happen to line up. So no transform is needed.
+- * We can probably optimize here and assume the high bits of newpp are
+- * already zero. For now I am paranoid.
+- */
+-static long beat_lpar_hpte_updatepp_v3(unsigned long slot,
+- unsigned long newpp,
+- unsigned long va,
+- int psize, int ssize, int local)
+-{
+- unsigned long lpar_rc;
+- unsigned long want_v;
+- unsigned long pss;
+-
+- want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+- pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc;
+-
+- DBG_LOW(" update: "
+- "avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ",
+- want_v & HPTE_V_AVPN, slot, psize, newpp);
+-
+- lpar_rc = beat_update_htab_permission3(0, slot, want_v, pss, 7, newpp);
+-
+- if (lpar_rc == 0xfffffff7) {
+- DBG_LOW("not found !\n");
+- return -1;
+- }
+-
+- DBG_LOW("ok\n");
+-
+- BUG_ON(lpar_rc != 0);
+-
+- return 0;
+-}
+-
+-static void beat_lpar_hpte_invalidate_v3(unsigned long slot, unsigned long va,
+- int psize, int ssize, int local)
+-{
+- unsigned long want_v;
+- unsigned long lpar_rc;
+- unsigned long pss;
+-
+- DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
+- slot, va, psize, local);
+- want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+- pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc;
+-
+- lpar_rc = beat_invalidate_htab_entry3(0, slot, want_v, pss);
+-
+- /* E_busy can be valid output: page may be already replaced */
+- BUG_ON(lpar_rc != 0 && lpar_rc != 0xfffffff7);
+-}
+-
+-static int64_t _beat_lpar_hptab_clear_v3(void)
+-{
+- return beat_clear_htab3(0);
+-}
+-
+-static void beat_lpar_hptab_clear_v3(void)
+-{
+- _beat_lpar_hptab_clear_v3();
+-}
+-
+-void __init hpte_init_beat_v3(void)
+-{
+- if (_beat_lpar_hptab_clear_v3() == 0) {
+- ppc_md.hpte_invalidate = beat_lpar_hpte_invalidate_v3;
+- ppc_md.hpte_updatepp = beat_lpar_hpte_updatepp_v3;
+- ppc_md.hpte_updateboltedpp = beat_lpar_hpte_updateboltedpp;
+- ppc_md.hpte_insert = beat_lpar_hpte_insert_v3;
+- ppc_md.hpte_remove = beat_lpar_hpte_remove;
+- ppc_md.hpte_clear_all = beat_lpar_hptab_clear_v3;
+- } else {
+- ppc_md.hpte_invalidate = beat_lpar_hpte_invalidate;
+- ppc_md.hpte_updatepp = beat_lpar_hpte_updatepp;
+- ppc_md.hpte_updateboltedpp = beat_lpar_hpte_updateboltedpp;
+- ppc_md.hpte_insert = beat_lpar_hpte_insert;
+- ppc_md.hpte_remove = beat_lpar_hpte_remove;
+- ppc_md.hpte_clear_all = beat_lpar_hptab_clear;
+- }
+-}
+diff --git a/arch/powerpc/platforms/celleb/hvCall.S b/arch/powerpc/platforms/celleb/hvCall.S
+deleted file mode 100644
+index 74c8174..0000000
+--- a/arch/powerpc/platforms/celleb/hvCall.S
++++ /dev/null
+@@ -1,287 +0,0 @@
+-/*
+- * Beat hypervisor call I/F
+- *
+- * (C) Copyright 2007 TOSHIBA CORPORATION
+- *
+- * This code is based on arch/powerpc/platforms/pseries/hvCall.S.
+- *
+- * 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.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#include <asm/ppc_asm.h>
+-
+-#define STK_PARM(i) (48 + ((i)-3)*8)
+-
+-/* Not implemented on Beat, now */
+-#define HCALL_INST_PRECALL
+-#define HCALL_INST_POSTCALL
+-
+- .text
+-
+-#define HVSC .long 0x44000022
+-
+-/* Note: takes only 7 input parameters at maximum */
+-_GLOBAL(beat_hcall_norets)
+- HMT_MEDIUM
+-
+- mfcr r0
+- stw r0,8(r1)
+-
+- HCALL_INST_PRECALL
+-
+- mr r11,r3
+- mr r3,r4
+- mr r4,r5
+- mr r5,r6
+- mr r6,r7
+- mr r7,r8
+- mr r8,r9
+-
+- HVSC /* invoke the hypervisor */
+-
+- HCALL_INST_POSTCALL
+-
+- lwz r0,8(r1)
+- mtcrf 0xff,r0
+-
+- blr /* return r3 = status */
+-
+-/* Note: takes 8 input parameters at maximum */
+-_GLOBAL(beat_hcall_norets8)
+- HMT_MEDIUM
+-
+- mfcr r0
+- stw r0,8(r1)
+-
+- HCALL_INST_PRECALL
+-
+- mr r11,r3
+- mr r3,r4
+- mr r4,r5
+- mr r5,r6
+- mr r6,r7
+- mr r7,r8
+- mr r8,r9
+- ld r10,STK_PARM(r10)(r1)
+-
+- HVSC /* invoke the hypervisor */
+-
+- HCALL_INST_POSTCALL
+-
+- lwz r0,8(r1)
+- mtcrf 0xff,r0
+-
+- blr /* return r3 = status */
+-
+-/* Note: takes only 6 input parameters, 1 output parameters at maximum */
+-_GLOBAL(beat_hcall1)
+- HMT_MEDIUM
+-
+- mfcr r0
+- stw r0,8(r1)
+-
+- HCALL_INST_PRECALL
+-
+- std r4,STK_PARM(r4)(r1) /* save ret buffer */
+-
+- mr r11,r3
+- mr r3,r5
+- mr r4,r6
+- mr r5,r7
+- mr r6,r8
+- mr r7,r9
+- mr r8,r10
+-
+- HVSC /* invoke the hypervisor */
+-
+- HCALL_INST_POSTCALL
+-
+- ld r12,STK_PARM(r4)(r1)
+- std r4, 0(r12)
+-
+- lwz r0,8(r1)
+- mtcrf 0xff,r0
+-
+- blr /* return r3 = status */
+-
+-/* Note: takes only 6 input parameters, 2 output parameters at maximum */
+-_GLOBAL(beat_hcall2)
+- HMT_MEDIUM
+-
+- mfcr r0
+- stw r0,8(r1)
+-
+- HCALL_INST_PRECALL
+-
+- std r4,STK_PARM(r4)(r1) /* save ret buffer */
+-
+- mr r11,r3
+- mr r3,r5
+- mr r4,r6
+- mr r5,r7
+- mr r6,r8
+- mr r7,r9
+- mr r8,r10
+-
+- HVSC /* invoke the hypervisor */
+-
+- HCALL_INST_POSTCALL
+-
+- ld r12,STK_PARM(r4)(r1)
+- std r4, 0(r12)
+- std r5, 8(r12)
+-
+- lwz r0,8(r1)
+- mtcrf 0xff,r0
+-
+- blr /* return r3 = status */
+-
+-/* Note: takes only 6 input parameters, 3 output parameters at maximum */
+-_GLOBAL(beat_hcall3)
+- HMT_MEDIUM
+-
+- mfcr r0
+- stw r0,8(r1)
+-
+- HCALL_INST_PRECALL
+-
+- std r4,STK_PARM(r4)(r1) /* save ret buffer */
+-
+- mr r11,r3
+- mr r3,r5
+- mr r4,r6
+- mr r5,r7
+- mr r6,r8
+- mr r7,r9
+- mr r8,r10
+-
+- HVSC /* invoke the hypervisor */
+-
+- HCALL_INST_POSTCALL
+-
+- ld r12,STK_PARM(r4)(r1)
+- std r4, 0(r12)
+- std r5, 8(r12)
+- std r6, 16(r12)
+-
+- lwz r0,8(r1)
+- mtcrf 0xff,r0
+-
+- blr /* return r3 = status */
+-
+-/* Note: takes only 6 input parameters, 4 output parameters at maximum */
+-_GLOBAL(beat_hcall4)
+- HMT_MEDIUM
+-
+- mfcr r0
+- stw r0,8(r1)
+-
+- HCALL_INST_PRECALL
+-
+- std r4,STK_PARM(r4)(r1) /* save ret buffer */
+-
+- mr r11,r3
+- mr r3,r5
+- mr r4,r6
+- mr r5,r7
+- mr r6,r8
+- mr r7,r9
+- mr r8,r10
+-
+- HVSC /* invoke the hypervisor */
+-
+- HCALL_INST_POSTCALL
+-
+- ld r12,STK_PARM(r4)(r1)
+- std r4, 0(r12)
+- std r5, 8(r12)
+- std r6, 16(r12)
+- std r7, 24(r12)
+-
+- lwz r0,8(r1)
+- mtcrf 0xff,r0
+-
+- blr /* return r3 = status */
+-
+-/* Note: takes only 6 input parameters, 5 output parameters at maximum */
+-_GLOBAL(beat_hcall5)
+- HMT_MEDIUM
+-
+- mfcr r0
+- stw r0,8(r1)
+-
+- HCALL_INST_PRECALL
+-
+- std r4,STK_PARM(r4)(r1) /* save ret buffer */
+-
+- mr r11,r3
+- mr r3,r5
+- mr r4,r6
+- mr r5,r7
+- mr r6,r8
+- mr r7,r9
+- mr r8,r10
+-
+- HVSC /* invoke the hypervisor */
+-
+- HCALL_INST_POSTCALL
+-
+- ld r12,STK_PARM(r4)(r1)
+- std r4, 0(r12)
+- std r5, 8(r12)
+- std r6, 16(r12)
+- std r7, 24(r12)
+- std r8, 32(r12)
+-
+- lwz r0,8(r1)
+- mtcrf 0xff,r0
+-
+- blr /* return r3 = status */
+-
+-/* Note: takes only 6 input parameters, 6 output parameters at maximum */
+-_GLOBAL(beat_hcall6)
+- HMT_MEDIUM
+-
+- mfcr r0
+- stw r0,8(r1)
+-
+- HCALL_INST_PRECALL
+-
+- std r4,STK_PARM(r4)(r1) /* save ret buffer */
+-
+- mr r11,r3
+- mr r3,r5
+- mr r4,r6
+- mr r5,r7
+- mr r6,r8
+- mr r7,r9
+- mr r8,r10
+-
+- HVSC /* invoke the hypervisor */
+-
+- HCALL_INST_POSTCALL
+-
+- ld r12,STK_PARM(r4)(r1)
+- std r4, 0(r12)
+- std r5, 8(r12)
+- std r6, 16(r12)
+- std r7, 24(r12)
+- std r8, 32(r12)
+- std r9, 40(r12)
+-
+- lwz r0,8(r1)
+- mtcrf 0xff,r0
+-
+- blr /* return r3 = status */
+diff --git a/arch/powerpc/platforms/celleb/interrupt.c b/arch/powerpc/platforms/celleb/interrupt.c
+deleted file mode 100644
+index c7c68ca..0000000
+--- a/arch/powerpc/platforms/celleb/interrupt.c
++++ /dev/null
+@@ -1,281 +0,0 @@
+-/*
+- * Celleb/Beat Interrupt controller
+- *
+- * (C) Copyright 2006-2007 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; 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.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#include <linux/init.h>
+-#include <linux/interrupt.h>
+-#include <linux/irq.h>
+-#include <linux/percpu.h>
+-#include <linux/types.h>
+-
+-#include <asm/machdep.h>
+-
+-#include "interrupt.h"
+-#include "beat_wrapper.h"
+-
+-#define MAX_IRQS NR_IRQS
+-static DEFINE_SPINLOCK(beatic_irq_mask_lock);
+-static uint64_t beatic_irq_mask_enable[(MAX_IRQS+255)/64];
+-static uint64_t beatic_irq_mask_ack[(MAX_IRQS+255)/64];
+-
+-static struct irq_host *beatic_host = NULL;
+-
+-/*
+- * In this implementation, "virq" == "IRQ plug number",
+- * "(irq_hw_number_t)hwirq" == "IRQ outlet number".
+- */
+-
+-/* assumption: locked */
+-static inline void beatic_update_irq_mask(unsigned int irq_plug)
+-{
+- int off;
+- unsigned long masks[4];
+-
+- off = (irq_plug / 256) * 4;
+- masks[0] = beatic_irq_mask_enable[off + 0]
+- & beatic_irq_mask_ack[off + 0];
+- masks[1] = beatic_irq_mask_enable[off + 1]
+- & beatic_irq_mask_ack[off + 1];
+- masks[2] = beatic_irq_mask_enable[off + 2]
+- & beatic_irq_mask_ack[off + 2];
+- masks[3] = beatic_irq_mask_enable[off + 3]
+- & beatic_irq_mask_ack[off + 3];
+- if (beat_set_interrupt_mask(irq_plug&~255UL,
+- masks[0], masks[1], masks[2], masks[3]) != 0)
+- panic("Failed to set mask IRQ!");
+-}
+-
+-static void beatic_mask_irq(unsigned int irq_plug)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&beatic_irq_mask_lock, flags);
+- beatic_irq_mask_enable[irq_plug/64] &= ~(1UL << (63 - (irq_plug%64)));
+- beatic_update_irq_mask(irq_plug);
+- spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
+-}
+-
+-static void beatic_unmask_irq(unsigned int irq_plug)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&beatic_irq_mask_lock, flags);
+- beatic_irq_mask_enable[irq_plug/64] |= 1UL << (63 - (irq_plug%64));
+- beatic_update_irq_mask(irq_plug);
+- spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
+-}
+-
+-static void beatic_ack_irq(unsigned int irq_plug)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&beatic_irq_mask_lock, flags);
+- beatic_irq_mask_ack[irq_plug/64] &= ~(1UL << (63 - (irq_plug%64)));
+- beatic_update_irq_mask(irq_plug);
+- spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
+-}
+-
+-static void beatic_end_irq(unsigned int irq_plug)
+-{
+- s64 err;
+- unsigned long flags;
+-
+- if ((err = beat_downcount_of_interrupt(irq_plug)) != 0) {
+- if ((err & 0xFFFFFFFF) != 0xFFFFFFF5) /* -11: wrong state */
+- panic("Failed to downcount IRQ! Error = %16lx", err);
+-
+- printk(KERN_ERR "IRQ over-downcounted, plug %d\n", irq_plug);
+- }
+- spin_lock_irqsave(&beatic_irq_mask_lock, flags);
+- beatic_irq_mask_ack[irq_plug/64] |= 1UL << (63 - (irq_plug%64));
+- beatic_update_irq_mask(irq_plug);
+- spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
+-}
+-
+-static struct irq_chip beatic_pic = {
+- .typename = " CELL-BEAT ",
+- .unmask = beatic_unmask_irq,
+- .mask = beatic_mask_irq,
+- .eoi = beatic_end_irq,
+-};
+-
+-/*
+- * Dispose binding hardware IRQ number (hw) and Virtuql IRQ number (virq),
+- * update flags.
+- *
+- * Note that the number (virq) is already assigned at upper layer.
+- */
+-static void beatic_pic_host_unmap(struct irq_host *h, unsigned int virq)
+-{
+- beat_destruct_irq_plug(virq);
+-}
+-
+-/*
+- * Create or update binding hardware IRQ number (hw) and Virtuql
+- * IRQ number (virq). This is called only once for a given mapping.
+- *
+- * Note that the number (virq) is already assigned at upper layer.
+- */
+-static int beatic_pic_host_map(struct irq_host *h, unsigned int virq,
+- irq_hw_number_t hw)
+-{
+- struct irq_desc *desc = get_irq_desc(virq);
+- int64_t err;
+-
+- if ((err = beat_construct_and_connect_irq_plug(virq, hw)) < 0)
+- return -EIO;
+-
+- desc->status |= IRQ_LEVEL;
+- set_irq_chip_and_handler(virq, &beatic_pic, handle_fasteoi_irq);
+- return 0;
+-}
+-
+-/*
+- * Update binding hardware IRQ number (hw) and Virtuql
+- * IRQ number (virq). This is called only once for a given mapping.
+- */
+-static void beatic_pic_host_remap(struct irq_host *h, unsigned int virq,
+- irq_hw_number_t hw)
+-{
+- beat_construct_and_connect_irq_plug(virq, hw);
+-}
+-
+-/*
+- * Translate device-tree interrupt spec to irq_hw_number_t style (ulong),
+- * to pass away to irq_create_mapping().
+- *
+- * Called from irq_create_of_mapping() only.
+- * Note: We have only 1 entry to translate.
+- */
+-static int beatic_pic_host_xlate(struct irq_host *h, struct device_node *ct,
+- u32 *intspec, unsigned int intsize,
+- irq_hw_number_t *out_hwirq,
+- unsigned int *out_flags)
+-{
+- u64 *intspec2 = (u64 *)intspec;
+-
+- *out_hwirq = *intspec2;
+- *out_flags |= IRQ_TYPE_LEVEL_LOW;
+- return 0;
+-}
+-
+-static int beatic_pic_host_match(struct irq_host *h, struct device_node *np)
+-{
+- /* Match all */
+- return 1;
+-}
+-
+-static struct irq_host_ops beatic_pic_host_ops = {
+- .map = beatic_pic_host_map,
+- .remap = beatic_pic_host_remap,
+- .unmap = beatic_pic_host_unmap,
+- .xlate = beatic_pic_host_xlate,
+- .match = beatic_pic_host_match,
+-};
+-
+-/*
+- * Get an IRQ number
+- * Note: returns VIRQ
+- */
+-static inline unsigned int beatic_get_irq_plug(void)
+-{
+- int i;
+- uint64_t pending[4], ub;
+-
+- for (i = 0; i < MAX_IRQS; i += 256) {
+- beat_detect_pending_interrupts(i, pending);
+- __asm__ ("cntlzd %0,%1":"=r"(ub):
+- "r"(pending[0] & beatic_irq_mask_enable[i/64+0]
+- & beatic_irq_mask_ack[i/64+0]));
+- if (ub != 64)
+- return i + ub + 0;
+- __asm__ ("cntlzd %0,%1":"=r"(ub):
+- "r"(pending[1] & beatic_irq_mask_enable[i/64+1]
+- & beatic_irq_mask_ack[i/64+1]));
+- if (ub != 64)
+- return i + ub + 64;
+- __asm__ ("cntlzd %0,%1":"=r"(ub):
+- "r"(pending[2] & beatic_irq_mask_enable[i/64+2]
+- & beatic_irq_mask_ack[i/64+2]));
+- if (ub != 64)
+- return i + ub + 128;
+- __asm__ ("cntlzd %0,%1":"=r"(ub):
+- "r"(pending[3] & beatic_irq_mask_enable[i/64+3]
+- & beatic_irq_mask_ack[i/64+3]));
+- if (ub != 64)
+- return i + ub + 192;
+- }
+-
+- return NO_IRQ;
+-}
+-unsigned int beatic_get_irq(void)
+-{
+- unsigned int ret;
+-
+- ret = beatic_get_irq_plug();
+- if (ret != NO_IRQ)
+- beatic_ack_irq(ret);
+- return ret;
+-}
+-
+-/*
+- */
+-void __init beatic_init_IRQ(void)
+-{
+- int i;
+-
+- memset(beatic_irq_mask_enable, 0, sizeof(beatic_irq_mask_enable));
+- memset(beatic_irq_mask_ack, 255, sizeof(beatic_irq_mask_ack));
+- for (i = 0; i < MAX_IRQS; i += 256)
+- beat_set_interrupt_mask(i, 0L, 0L, 0L, 0L);
+-
+- /* Set out get_irq function */
+- ppc_md.get_irq = beatic_get_irq;
+-
+- /* Allocate an irq host */
+- beatic_host = irq_alloc_host(NULL, IRQ_HOST_MAP_NOMAP, 0,
+- &beatic_pic_host_ops,
+- 0);
+- BUG_ON(beatic_host == NULL);
+- irq_set_default_host(beatic_host);
+-}
+-
+-#ifdef CONFIG_SMP
+-
+-/* Nullified to compile with SMP mode */
+-void beatic_setup_cpu(int cpu)
+-{
+-}
+-
+-void beatic_cause_IPI(int cpu, int mesg)
+-{
+-}
+-
+-void beatic_request_IPIs(void)
+-{
+-}
+-#endif /* CONFIG_SMP */
+-
+-void beatic_deinit_IRQ(void)
+-{
+- int i;
+-
+- for (i = 1; i < NR_IRQS; i++)
+- beat_destruct_irq_plug(i);
+-}
+diff --git a/arch/powerpc/platforms/celleb/interrupt.h b/arch/powerpc/platforms/celleb/interrupt.h
+deleted file mode 100644
+index b470fd0..0000000
+--- a/arch/powerpc/platforms/celleb/interrupt.h
++++ /dev/null
+@@ -1,33 +0,0 @@
+-/*
+- * Celleb/Beat Interrupt controller
+- *
+- * (C) Copyright 2006 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; 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.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#ifndef ASM_BEAT_PIC_H
+-#define ASM_BEAT_PIC_H
+-#ifdef __KERNEL__
+-
+-extern void beatic_init_IRQ(void);
+-extern unsigned int beatic_get_irq(void);
+-extern void beatic_cause_IPI(int cpu, int mesg);
+-extern void beatic_request_IPIs(void);
+-extern void beatic_setup_cpu(int);
+-extern void beatic_deinit_IRQ(void);
+-
+-#endif
+-#endif /* ASM_BEAT_PIC_H */
+diff --git a/arch/powerpc/platforms/celleb/io-workarounds.c b/arch/powerpc/platforms/celleb/io-workarounds.c
+deleted file mode 100644
+index 423339b..0000000
+--- a/arch/powerpc/platforms/celleb/io-workarounds.c
++++ /dev/null
+@@ -1,280 +0,0 @@
+-/*
+- * Support for Celleb io workarounds
+- *
+- * (C) Copyright 2006-2007 TOSHIBA CORPORATION
+- *
+- * This file is based to arch/powerpc/platform/cell/io-workarounds.c
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#undef DEBUG
+-
+-#include <linux/of.h>
+-#include <linux/of_device.h>
+-#include <linux/irq.h>
+-
+-#include <asm/io.h>
+-#include <asm/prom.h>
+-#include <asm/machdep.h>
+-#include <asm/pci-bridge.h>
+-#include <asm/ppc-pci.h>
+-
+-#include "pci.h"
+-
+-#define MAX_CELLEB_PCI_BUS 4
+-
+-void *celleb_dummy_page_va;
+-
+-static struct celleb_pci_bus {
+- struct pci_controller *phb;
+- void (*dummy_read)(struct pci_controller *);
+-} celleb_pci_busses[MAX_CELLEB_PCI_BUS];
+-
+-static int celleb_pci_count = 0;
+-
+-static struct celleb_pci_bus *celleb_pci_find(unsigned long vaddr,
+- unsigned long paddr)
+-{
+- int i, j;
+- struct resource *res;
+-
+- for (i = 0; i < celleb_pci_count; i++) {
+- struct celleb_pci_bus *bus = &celleb_pci_busses[i];
+- struct pci_controller *phb = bus->phb;
+- if (paddr)
+- for (j = 0; j < 3; j++) {
+- res = &phb->mem_resources[j];
+- if (paddr >= res->start && paddr <= res->end)
+- return bus;
+- }
+- res = &phb->io_resource;
+- if (vaddr && vaddr >= res->start && vaddr <= res->end)
+- return bus;
+- }
+- return NULL;
+-}
+-
+-static void celleb_io_flush(const PCI_IO_ADDR addr)
+-{
+- struct celleb_pci_bus *bus;
+- int token;
+-
+- token = PCI_GET_ADDR_TOKEN(addr);
+-
+- if (token && token <= celleb_pci_count)
+- bus = &celleb_pci_busses[token - 1];
+- else {
+- unsigned long vaddr, paddr;
+- pte_t *ptep;
+-
+- vaddr = (unsigned long)PCI_FIX_ADDR(addr);
+- if (vaddr < PHB_IO_BASE || vaddr >= PHB_IO_END)
+- return;
+-
+- ptep = find_linux_pte(init_mm.pgd, vaddr);
+- if (ptep == NULL)
+- paddr = 0;
+- else
+- paddr = pte_pfn(*ptep) << PAGE_SHIFT;
+- bus = celleb_pci_find(vaddr, paddr);
+-
+- if (bus == NULL)
+- return;
+- }
+-
+- if (bus->dummy_read)
+- bus->dummy_read(bus->phb);
+-}
+-
+-static u8 celleb_readb(const PCI_IO_ADDR addr)
+-{
+- u8 val;
+- val = __do_readb(addr);
+- celleb_io_flush(addr);
+- return val;
+-}
+-
+-static u16 celleb_readw(const PCI_IO_ADDR addr)
+-{
+- u16 val;
+- val = __do_readw(addr);
+- celleb_io_flush(addr);
+- return val;
+-}
+-
+-static u32 celleb_readl(const PCI_IO_ADDR addr)
+-{
+- u32 val;
+- val = __do_readl(addr);
+- celleb_io_flush(addr);
+- return val;
+-}
+-
+-static u64 celleb_readq(const PCI_IO_ADDR addr)
+-{
+- u64 val;
+- val = __do_readq(addr);
+- celleb_io_flush(addr);
+- return val;
+-}
+-
+-static u16 celleb_readw_be(const PCI_IO_ADDR addr)
+-{
+- u16 val;
+- val = __do_readw_be(addr);
+- celleb_io_flush(addr);
+- return val;
+-}
+-
+-static u32 celleb_readl_be(const PCI_IO_ADDR addr)
+-{
+- u32 val;
+- val = __do_readl_be(addr);
+- celleb_io_flush(addr);
+- return val;
+-}
+-
+-static u64 celleb_readq_be(const PCI_IO_ADDR addr)
+-{
+- u64 val;
+- val = __do_readq_be(addr);
+- celleb_io_flush(addr);
+- return val;
+-}
+-
+-static void celleb_readsb(const PCI_IO_ADDR addr,
+- void *buf, unsigned long count)
+-{
+- __do_readsb(addr, buf, count);
+- celleb_io_flush(addr);
+-}
+-
+-static void celleb_readsw(const PCI_IO_ADDR addr,
+- void *buf, unsigned long count)
+-{
+- __do_readsw(addr, buf, count);
+- celleb_io_flush(addr);
+-}
+-
+-static void celleb_readsl(const PCI_IO_ADDR addr,
+- void *buf, unsigned long count)
+-{
+- __do_readsl(addr, buf, count);
+- celleb_io_flush(addr);
+-}
+-
+-static void celleb_memcpy_fromio(void *dest,
+- const PCI_IO_ADDR src,
+- unsigned long n)
+-{
+- __do_memcpy_fromio(dest, src, n);
+- celleb_io_flush(src);
+-}
+-
+-static void __iomem *celleb_ioremap(unsigned long addr,
+- unsigned long size,
+- unsigned long flags)
+-{
+- struct celleb_pci_bus *bus;
+- void __iomem *res = __ioremap(addr, size, flags);
+- int busno;
+-
+- bus = celleb_pci_find(0, addr);
+- if (bus != NULL) {
+- busno = bus - celleb_pci_busses;
+- PCI_SET_ADDR_TOKEN(res, busno + 1);
+- }
+- return res;
+-}
+-
+-static void celleb_iounmap(volatile void __iomem *addr)
+-{
+- return __iounmap(PCI_FIX_ADDR(addr));
+-}
+-
+-static struct ppc_pci_io celleb_pci_io __initdata = {
+- .readb = celleb_readb,
+- .readw = celleb_readw,
+- .readl = celleb_readl,
+- .readq = celleb_readq,
+- .readw_be = celleb_readw_be,
+- .readl_be = celleb_readl_be,
+- .readq_be = celleb_readq_be,
+- .readsb = celleb_readsb,
+- .readsw = celleb_readsw,
+- .readsl = celleb_readsl,
+- .memcpy_fromio = celleb_memcpy_fromio,
+-};
+-
+-void __init celleb_pci_add_one(struct pci_controller *phb,
+- void (*dummy_read)(struct pci_controller *))
+-{
+- struct celleb_pci_bus *bus = &celleb_pci_busses[celleb_pci_count];
+- struct device_node *np = phb->dn;
+-
+- if (celleb_pci_count >= MAX_CELLEB_PCI_BUS) {
+- printk(KERN_ERR "Too many pci bridges, workarounds"
+- " disabled for %s\n", np->full_name);
+- return;
+- }
+-
+- celleb_pci_count++;
+-
+- bus->phb = phb;
+- bus->dummy_read = dummy_read;
+-}
+-
+-static struct of_device_id celleb_pci_workaround_match[] __initdata = {
+- {
+- .name = "pci-pseudo",
+- .data = fake_pci_workaround_init,
+- }, {
+- .name = "epci",
+- .data = epci_workaround_init,
+- }, {
+- },
+-};
+-
+-int __init celleb_pci_workaround_init(void)
+-{
+- struct pci_controller *phb;
+- struct device_node *node;
+- const struct of_device_id *match;
+- void (*init_func)(struct pci_controller *);
+-
+- celleb_dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL);
+- if (!celleb_dummy_page_va) {
+- printk(KERN_ERR "Celleb: dummy read disabled. "
+- "Alloc celleb_dummy_page_va failed\n");
+- return 1;
+- }
+-
+- list_for_each_entry(phb, &hose_list, list_node) {
+- node = phb->dn;
+- match = of_match_node(celleb_pci_workaround_match, node);
+-
+- if (match) {
+- init_func = match->data;
+- (*init_func)(phb);
+- }
+- }
+-
+- ppc_pci_io = celleb_pci_io;
+- ppc_md.ioremap = celleb_ioremap;
+- ppc_md.iounmap = celleb_iounmap;
+-
+- return 0;
+-}
+diff --git a/arch/powerpc/platforms/celleb/iommu.c b/arch/powerpc/platforms/celleb/iommu.c
+deleted file mode 100644
+index 93b0efd..0000000
+--- a/arch/powerpc/platforms/celleb/iommu.c
++++ /dev/null
+@@ -1,116 +0,0 @@
+-/*
+- * Support for IOMMU on Celleb platform.
+- *
+- * (C) Copyright 2006-2007 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; 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.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/pci.h>
+-#include <linux/of_platform.h>
+-
+-#include <asm/machdep.h>
+-
+-#include "beat_wrapper.h"
+-
+-#define DMA_FLAGS 0xf800000000000000UL /* r/w permitted, coherency required,
+- strongest order */
+-
+-static int __init find_dma_window(u64 *io_space_id, u64 *ioid,
+- u64 *base, u64 *size, u64 *io_page_size)
+-{
+- struct device_node *dn;
+- const unsigned long *dma_window;
+-
+- for_each_node_by_type(dn, "ioif") {
+- dma_window = of_get_property(dn, "toshiba,dma-window", NULL);
+- if (dma_window) {
+- *io_space_id = (dma_window[0] >> 32) & 0xffffffffUL;
+- *ioid = dma_window[0] & 0x7ffUL;
+- *base = dma_window[1];
+- *size = dma_window[2];
+- *io_page_size = 1 << dma_window[3];
+- of_node_put(dn);
+- return 1;
+- }
+- }
+- return 0;
+-}
+-
+-static unsigned long celleb_dma_direct_offset;
+-
+-static void __init celleb_init_direct_mapping(void)
+-{
+- u64 lpar_addr, io_addr;
+- u64 io_space_id, ioid, dma_base, dma_size, io_page_size;
+-
+- if (!find_dma_window(&io_space_id, &ioid, &dma_base, &dma_size,
+- &io_page_size)) {
+- pr_info("No dma window found !\n");
+- return;
+- }
+-
+- for (lpar_addr = 0; lpar_addr < dma_size; lpar_addr += io_page_size) {
+- io_addr = lpar_addr + dma_base;
+- (void)beat_put_iopte(io_space_id, io_addr, lpar_addr,
+- ioid, DMA_FLAGS);
+- }
+-
+- celleb_dma_direct_offset = dma_base;
+-}
+-
+-static void celleb_dma_dev_setup(struct device *dev)
+-{
+- dev->archdata.dma_ops = get_pci_dma_ops();
+- dev->archdata.dma_data = (void *)celleb_dma_direct_offset;
+-}
+-
+-static void celleb_pci_dma_dev_setup(struct pci_dev *pdev)
+-{
+- celleb_dma_dev_setup(&pdev->dev);
+-}
+-
+-static int celleb_of_bus_notify(struct notifier_block *nb,
+- unsigned long action, void *data)
+-{
+- struct device *dev = data;
+-
+- /* We are only intereted in device addition */
+- if (action != BUS_NOTIFY_ADD_DEVICE)
+- return 0;
+-
+- celleb_dma_dev_setup(dev);
+-
+- return 0;
+-}
+-
+-static struct notifier_block celleb_of_bus_notifier = {
+- .notifier_call = celleb_of_bus_notify
+-};
+-
+-static int __init celleb_init_iommu(void)
+-{
+- celleb_init_direct_mapping();
+- set_pci_dma_ops(&dma_direct_ops);
+- ppc_md.pci_dma_dev_setup = celleb_pci_dma_dev_setup;
+- bus_register_notifier(&of_platform_bus_type, &celleb_of_bus_notifier);
+-
+- return 0;
+-}
+-
+-machine_arch_initcall(celleb_beat, celleb_init_iommu);
+diff --git a/arch/powerpc/platforms/celleb/pci.c b/arch/powerpc/platforms/celleb/pci.c
+deleted file mode 100644
+index 51b390d..0000000
+--- a/arch/powerpc/platforms/celleb/pci.c
++++ /dev/null
+@@ -1,502 +0,0 @@
+-/*
+- * Support for PCI on Celleb platform.
+- *
+- * (C) Copyright 2006-2007 TOSHIBA CORPORATION
+- *
+- * This code is based on arch/powerpc/kernel/rtas_pci.c:
+- * Copyright (C) 2001 Dave Engebretsen, IBM Corporation
+- * Copyright (C) 2003 Anton Blanchard <anton at au.ibm.com>, IBM
+- *
+- * 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.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#undef DEBUG
+-
+-#include <linux/kernel.h>
+-#include <linux/threads.h>
+-#include <linux/pci.h>
+-#include <linux/string.h>
+-#include <linux/init.h>
+-#include <linux/bootmem.h>
+-#include <linux/pci_regs.h>
+-#include <linux/of.h>
+-#include <linux/of_device.h>
+-
+-#include <asm/io.h>
+-#include <asm/irq.h>
+-#include <asm/prom.h>
+-#include <asm/machdep.h>
+-#include <asm/pci-bridge.h>
+-#include <asm/ppc-pci.h>
+-
+-#include "pci.h"
+-#include "interrupt.h"
+-
+-#define MAX_PCI_DEVICES 32
+-#define MAX_PCI_FUNCTIONS 8
+-#define MAX_PCI_BASE_ADDRS 3 /* use 64 bit address */
+-
+-/* definition for fake pci configuration area for GbE, .... ,and etc. */
+-
+-struct celleb_pci_resource {
+- struct resource r[MAX_PCI_BASE_ADDRS];
+-};
+-
+-struct celleb_pci_private {
+- unsigned char *fake_config[MAX_PCI_DEVICES][MAX_PCI_FUNCTIONS];
+- struct celleb_pci_resource *res[MAX_PCI_DEVICES][MAX_PCI_FUNCTIONS];
+-};
+-
+-static inline u8 celleb_fake_config_readb(void *addr)
+-{
+- u8 *p = addr;
+- return *p;
+-}
+-
+-static inline u16 celleb_fake_config_readw(void *addr)
+-{
+- __le16 *p = addr;
+- return le16_to_cpu(*p);
+-}
+-
+-static inline u32 celleb_fake_config_readl(void *addr)
+-{
+- __le32 *p = addr;
+- return le32_to_cpu(*p);
+-}
+-
+-static inline void celleb_fake_config_writeb(u32 val, void *addr)
+-{
+- u8 *p = addr;
+- *p = val;
+-}
+-
+-static inline void celleb_fake_config_writew(u32 val, void *addr)
+-{
+- __le16 val16;
+- __le16 *p = addr;
+- val16 = cpu_to_le16(val);
+- *p = val16;
+-}
+-
+-static inline void celleb_fake_config_writel(u32 val, void *addr)
+-{
+- __le32 val32;
+- __le32 *p = addr;
+- val32 = cpu_to_le32(val);
+- *p = val32;
+-}
+-
+-static unsigned char *get_fake_config_start(struct pci_controller *hose,
+- int devno, int fn)
+-{
+- struct celleb_pci_private *private = hose->private_data;
+-
+- if (private == NULL)
+- return NULL;
+-
+- return private->fake_config[devno][fn];
+-}
+-
+-static struct celleb_pci_resource *get_resource_start(
+- struct pci_controller *hose,
+- int devno, int fn)
+-{
+- struct celleb_pci_private *private = hose->private_data;
+-
+- if (private == NULL)
+- return NULL;
+-
+- return private->res[devno][fn];
+-}
+-
+-
+-static void celleb_config_read_fake(unsigned char *config, int where,
+- int size, u32 *val)
+-{
+- char *p = config + where;
+-
+- switch (size) {
+- case 1:
+- *val = celleb_fake_config_readb(p);
+- break;
+- case 2:
+- *val = celleb_fake_config_readw(p);
+- break;
+- case 4:
+- *val = celleb_fake_config_readl(p);
+- break;
+- }
+-}
+-
+-static void celleb_config_write_fake(unsigned char *config, int where,
+- int size, u32 val)
+-{
+- char *p = config + where;
+-
+- switch (size) {
+- case 1:
+- celleb_fake_config_writeb(val, p);
+- break;
+- case 2:
+- celleb_fake_config_writew(val, p);
+- break;
+- case 4:
+- celleb_fake_config_writel(val, p);
+- break;
+- }
+-}
+-
+-static int celleb_fake_pci_read_config(struct pci_bus *bus,
+- unsigned int devfn, int where, int size, u32 *val)
+-{
+- char *config;
+- struct device_node *node;
+- struct pci_controller *hose;
+- unsigned int devno = devfn >> 3;
+- unsigned int fn = devfn & 0x7;
+-
+- /* allignment check */
+- BUG_ON(where % size);
+-
+- pr_debug(" fake read: bus=0x%x, ", bus->number);
+- node = (struct device_node *)bus->sysdata;
+- hose = pci_find_hose_for_OF_device(node);
+- config = get_fake_config_start(hose, devno, fn);
+-
+- pr_debug("devno=0x%x, where=0x%x, size=0x%x, ", devno, where, size);
+- if (!config) {
+- pr_debug("failed\n");
+- return PCIBIOS_DEVICE_NOT_FOUND;
+- }
+-
+- celleb_config_read_fake(config, where, size, val);
+- pr_debug("val=0x%x\n", *val);
+-
+- return PCIBIOS_SUCCESSFUL;
+-}
+-
+-
+-static int celleb_fake_pci_write_config(struct pci_bus *bus,
+- unsigned int devfn, int where, int size, u32 val)
+-{
+- char *config;
+- struct device_node *node;
+- struct pci_controller *hose;
+- struct celleb_pci_resource *res;
+- unsigned int devno = devfn >> 3;
+- unsigned int fn = devfn & 0x7;
+-
+- /* allignment check */
+- BUG_ON(where % size);
+-
+- node = (struct device_node *)bus->sysdata;
+- hose = pci_find_hose_for_OF_device(node);
+- config = get_fake_config_start(hose, devno, fn);
+-
+- if (!config)
+- return PCIBIOS_DEVICE_NOT_FOUND;
+-
+- if (val == ~0) {
+- int i = (where - PCI_BASE_ADDRESS_0) >> 3;
+-
+- switch (where) {
+- case PCI_BASE_ADDRESS_0:
+- case PCI_BASE_ADDRESS_2:
+- if (size != 4)
+- return PCIBIOS_DEVICE_NOT_FOUND;
+- res = get_resource_start(hose, devno, fn);
+- if (!res)
+- return PCIBIOS_DEVICE_NOT_FOUND;
+- celleb_config_write_fake(config, where, size,
+- (res->r[i].end - res->r[i].start));
+- return PCIBIOS_SUCCESSFUL;
+- case PCI_BASE_ADDRESS_1:
+- case PCI_BASE_ADDRESS_3:
+- case PCI_BASE_ADDRESS_4:
+- case PCI_BASE_ADDRESS_5:
+- break;
+- default:
+- break;
+- }
+- }
+-
+- celleb_config_write_fake(config, where, size, val);
+- pr_debug(" fake write: where=%x, size=%d, val=%x\n",
+- where, size, val);
+-
+- return PCIBIOS_SUCCESSFUL;
+-}
+-
+-static struct pci_ops celleb_fake_pci_ops = {
+- .read = celleb_fake_pci_read_config,
+- .write = celleb_fake_pci_write_config,
+-};
+-
+-static inline void celleb_setup_pci_base_addrs(struct pci_controller *hose,
+- unsigned int devno, unsigned int fn,
+- unsigned int num_base_addr)
+-{
+- u32 val;
+- unsigned char *config;
+- struct celleb_pci_resource *res;
+-
+- config = get_fake_config_start(hose, devno, fn);
+- res = get_resource_start(hose, devno, fn);
+-
+- if (!config || !res)
+- return;
+-
+- switch (num_base_addr) {
+- case 3:
+- val = (res->r[2].start & 0xfffffff0)
+- | PCI_BASE_ADDRESS_MEM_TYPE_64;
+- celleb_config_write_fake(config, PCI_BASE_ADDRESS_4, 4, val);
+- val = res->r[2].start >> 32;
+- celleb_config_write_fake(config, PCI_BASE_ADDRESS_5, 4, val);
+- /* FALLTHROUGH */
+- case 2:
+- val = (res->r[1].start & 0xfffffff0)
+- | PCI_BASE_ADDRESS_MEM_TYPE_64;
+- celleb_config_write_fake(config, PCI_BASE_ADDRESS_2, 4, val);
+- val = res->r[1].start >> 32;
+- celleb_config_write_fake(config, PCI_BASE_ADDRESS_3, 4, val);
+- /* FALLTHROUGH */
+- case 1:
+- val = (res->r[0].start & 0xfffffff0)
+- | PCI_BASE_ADDRESS_MEM_TYPE_64;
+- celleb_config_write_fake(config, PCI_BASE_ADDRESS_0, 4, val);
+- val = res->r[0].start >> 32;
+- celleb_config_write_fake(config, PCI_BASE_ADDRESS_1, 4, val);
+- break;
+- }
+-
+- val = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+- celleb_config_write_fake(config, PCI_COMMAND, 2, val);
+-}
+-
+-static int __init celleb_setup_fake_pci_device(struct device_node *node,
+- struct pci_controller *hose)
+-{
+- unsigned int rlen;
+- int num_base_addr = 0;
+- u32 val;
+- const u32 *wi0, *wi1, *wi2, *wi3, *wi4;
+- unsigned int devno, fn;
+- struct celleb_pci_private *private = hose->private_data;
+- unsigned char **config = NULL;
+- struct celleb_pci_resource **res = NULL;
+- const char *name;
+- const unsigned long *li;
+- int size, result;
+-
+- if (private == NULL) {
+- printk(KERN_ERR "PCI: "
+- "memory space for pci controller is not assigned\n");
+- goto error;
+- }
+-
+- name = of_get_property(node, "model", &rlen);
+- if (!name) {
+- printk(KERN_ERR "PCI: model property not found.\n");
+- goto error;
+- }
+-
+- wi4 = of_get_property(node, "reg", &rlen);
+- if (wi4 == NULL)
+- goto error;
+-
+- devno = ((wi4[0] >> 8) & 0xff) >> 3;
+- fn = (wi4[0] >> 8) & 0x7;
+-
+- pr_debug("PCI: celleb_setup_fake_pci() %s devno=%x fn=%x\n", name,
+- devno, fn);
+-
+- size = 256;
+- config = &private->fake_config[devno][fn];
+- *config = alloc_maybe_bootmem(size, GFP_KERNEL);
+- if (*config == NULL) {
+- printk(KERN_ERR "PCI: "
+- "not enough memory for fake configuration space\n");
+- goto error;
+- }
+- pr_debug("PCI: fake config area assigned 0x%016lx\n",
+- (unsigned long)*config);
+-
+- size = sizeof(struct celleb_pci_resource);
+- res = &private->res[devno][fn];
+- *res = alloc_maybe_bootmem(size, GFP_KERNEL);
+- if (*res == NULL) {
+- printk(KERN_ERR
+- "PCI: not enough memory for resource data space\n");
+- goto error;
+- }
+- pr_debug("PCI: res assigned 0x%016lx\n", (unsigned long)*res);
+-
+- wi0 = of_get_property(node, "device-id", NULL);
+- wi1 = of_get_property(node, "vendor-id", NULL);
+- wi2 = of_get_property(node, "class-code", NULL);
+- wi3 = of_get_property(node, "revision-id", NULL);
+- if (!wi0 || !wi1 || !wi2 || !wi3) {
+- printk(KERN_ERR "PCI: Missing device tree properties.\n");
+- goto error;
+- }
+-
+- celleb_config_write_fake(*config, PCI_DEVICE_ID, 2, wi0[0] & 0xffff);
+- celleb_config_write_fake(*config, PCI_VENDOR_ID, 2, wi1[0] & 0xffff);
+- pr_debug("class-code = 0x%08x\n", wi2[0]);
+-
+- celleb_config_write_fake(*config, PCI_CLASS_PROG, 1, wi2[0] & 0xff);
+- celleb_config_write_fake(*config, PCI_CLASS_DEVICE, 2,
+- (wi2[0] >> 8) & 0xffff);
+- celleb_config_write_fake(*config, PCI_REVISION_ID, 1, wi3[0]);
+-
+- while (num_base_addr < MAX_PCI_BASE_ADDRS) {
+- result = of_address_to_resource(node,
+- num_base_addr, &(*res)->r[num_base_addr]);
+- if (result)
+- break;
+- num_base_addr++;
+- }
+-
+- celleb_setup_pci_base_addrs(hose, devno, fn, num_base_addr);
+-
+- li = of_get_property(node, "interrupts", &rlen);
+- if (!li) {
+- printk(KERN_ERR "PCI: interrupts not found.\n");
+- goto error;
+- }
+- val = li[0];
+- celleb_config_write_fake(*config, PCI_INTERRUPT_PIN, 1, 1);
+- celleb_config_write_fake(*config, PCI_INTERRUPT_LINE, 1, val);
+-
+-#ifdef DEBUG
+- pr_debug("PCI: %s irq=%ld\n", name, li[0]);
+- for (i = 0; i < 6; i++) {
+- celleb_config_read_fake(*config,
+- PCI_BASE_ADDRESS_0 + 0x4 * i, 4,
+- &val);
+- pr_debug("PCI: %s fn=%d base_address_%d=0x%x\n",
+- name, fn, i, val);
+- }
+-#endif
+-
+- celleb_config_write_fake(*config, PCI_HEADER_TYPE, 1,
+- PCI_HEADER_TYPE_NORMAL);
+-
+- return 0;
+-
+-error:
+- if (mem_init_done) {
+- if (config && *config)
+- kfree(*config);
+- if (res && *res)
+- kfree(*res);
+-
+- } else {
+- if (config && *config) {
+- size = 256;
+- free_bootmem((unsigned long)(*config), size);
+- }
+- if (res && *res) {
+- size = sizeof(struct celleb_pci_resource);
+- free_bootmem((unsigned long)(*res), size);
+- }
+- }
+-
+- return 1;
+-}
+-
+-static int __init phb_set_bus_ranges(struct device_node *dev,
+- struct pci_controller *phb)
+-{
+- const int *bus_range;
+- unsigned int len;
+-
+- bus_range = of_get_property(dev, "bus-range", &len);
+- if (bus_range == NULL || len < 2 * sizeof(int))
+- return 1;
+-
+- phb->first_busno = bus_range[0];
+- phb->last_busno = bus_range[1];
+-
+- return 0;
+-}
+-
+-static void __init celleb_alloc_private_mem(struct pci_controller *hose)
+-{
+- hose->private_data =
+- alloc_maybe_bootmem(sizeof(struct celleb_pci_private),
+- GFP_KERNEL);
+-}
+-
+-static int __init celleb_setup_fake_pci(struct device_node *dev,
+- struct pci_controller *phb)
+-{
+- struct device_node *node;
+-
+- phb->ops = &celleb_fake_pci_ops;
+- celleb_alloc_private_mem(phb);
+-
+- for (node = of_get_next_child(dev, NULL);
+- node != NULL; node = of_get_next_child(dev, node))
+- celleb_setup_fake_pci_device(node, phb);
+-
+- return 0;
+-}
+-
+-void __init fake_pci_workaround_init(struct pci_controller *phb)
+-{
+- /**
+- * We will add fake pci bus to scc_pci_bus for the purpose to improve
+- * I/O Macro performance. But device-tree and device drivers
+- * are not ready to use address with a token.
+- */
+-
+- /* celleb_pci_add_one(phb, NULL); */
+-}
+-
+-static struct of_device_id celleb_phb_match[] __initdata = {
+- {
+- .name = "pci-pseudo",
+- .data = celleb_setup_fake_pci,
+- }, {
+- .name = "epci",
+- .data = celleb_setup_epci,
+- }, {
+- },
+-};
+-
+-int __init celleb_setup_phb(struct pci_controller *phb)
+-{
+- struct device_node *dev = phb->dn;
+- const struct of_device_id *match;
+- int (*setup_func)(struct device_node *, struct pci_controller *);
+-
+- match = of_match_node(celleb_phb_match, dev);
+- if (!match)
+- return 1;
+-
+- phb_set_bus_ranges(dev, phb);
+- phb->buid = 1;
+-
+- setup_func = match->data;
+- return (*setup_func)(dev, phb);
+-}
+-
+-int celleb_pci_probe_mode(struct pci_bus *bus)
+-{
+- return PCI_PROBE_DEVTREE;
+-}
+diff --git a/arch/powerpc/platforms/celleb/pci.h b/arch/powerpc/platforms/celleb/pci.h
+deleted file mode 100644
+index 5d5544f..0000000
+--- a/arch/powerpc/platforms/celleb/pci.h
++++ /dev/null
+@@ -1,42 +0,0 @@
+-/*
+- * pci prototypes for Celleb platform
+- *
+- * (C) Copyright 2006-2007 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; 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.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#ifndef _CELLEB_PCI_H
+-#define _CELLEB_PCI_H
+-
+-#include <linux/pci.h>
+-
+-#include <asm/pci-bridge.h>
+-#include <asm/prom.h>
+-#include <asm/ppc-pci.h>
+-
+-extern int celleb_setup_phb(struct pci_controller *);
+-extern int celleb_pci_probe_mode(struct pci_bus *);
+-
+-extern int celleb_setup_epci(struct device_node *, struct pci_controller *);
+-
+-extern void *celleb_dummy_page_va;
+-extern int __init celleb_pci_workaround_init(void);
+-extern void __init celleb_pci_add_one(struct pci_controller *,
+- void (*)(struct pci_controller *));
+-extern void fake_pci_workaround_init(struct pci_controller *);
+-extern void epci_workaround_init(struct pci_controller *);
+-
+-#endif /* _CELLEB_PCI_H */
+diff --git a/arch/powerpc/platforms/celleb/scc.h b/arch/powerpc/platforms/celleb/scc.h
+deleted file mode 100644
+index 6be1542..0000000
+--- a/arch/powerpc/platforms/celleb/scc.h
++++ /dev/null
+@@ -1,145 +0,0 @@
+-/*
+- * SCC (Super Companion Chip) definitions
+- *
+- * (C) Copyright 2004-2006 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; 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.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#ifndef _CELLEB_SCC_H
+-#define _CELLEB_SCC_H
+-
+-#define PCI_VENDOR_ID_TOSHIBA_2 0x102f
+-#define PCI_DEVICE_ID_TOSHIBA_SCC_PCIEXC_BRIDGE 0x01b0
+-#define PCI_DEVICE_ID_TOSHIBA_SCC_EPCI_BRIDGE 0x01b1
+-#define PCI_DEVICE_ID_TOSHIBA_SCC_BRIDGE 0x01b2
+-#define PCI_DEVICE_ID_TOSHIBA_SCC_GBE 0x01b3
+-#define PCI_DEVICE_ID_TOSHIBA_SCC_ATA 0x01b4
+-#define PCI_DEVICE_ID_TOSHIBA_SCC_USB2 0x01b5
+-#define PCI_DEVICE_ID_TOSHIBA_SCC_USB 0x01b6
+-#define PCI_DEVICE_ID_TOSHIBA_SCC_ENCDEC 0x01b7
+-
+-#define SCC_EPCI_REG 0x0000d000
+-
+-/* EPCI registers */
+-#define SCC_EPCI_CNF10_REG 0x010
+-#define SCC_EPCI_CNF14_REG 0x014
+-#define SCC_EPCI_CNF18_REG 0x018
+-#define SCC_EPCI_PVBAT 0x100
+-#define SCC_EPCI_VPMBAT 0x104
+-#define SCC_EPCI_VPIBAT 0x108
+-#define SCC_EPCI_VCSR 0x110
+-#define SCC_EPCI_VIENAB 0x114
+-#define SCC_EPCI_VISTAT 0x118
+-#define SCC_EPCI_VRDCOUNT 0x124
+-#define SCC_EPCI_BAM0 0x12c
+-#define SCC_EPCI_BAM1 0x134
+-#define SCC_EPCI_BAM2 0x13c
+-#define SCC_EPCI_IADR 0x164
+-#define SCC_EPCI_CLKRST 0x800
+-#define SCC_EPCI_INTSET 0x804
+-#define SCC_EPCI_STATUS 0x808
+-#define SCC_EPCI_ABTSET 0x80c
+-#define SCC_EPCI_WATRP 0x810
+-#define SCC_EPCI_DUMYRADR 0x814
+-#define SCC_EPCI_SWRESP 0x818
+-#define SCC_EPCI_CNTOPT 0x81c
+-#define SCC_EPCI_ECMODE 0xf00
+-#define SCC_EPCI_IOM_AC_NUM 5
+-#define SCC_EPCI_IOM_ACTE(n) (0xf10 + (n) * 4)
+-#define SCC_EPCI_IOT_AC_NUM 4
+-#define SCC_EPCI_IOT_ACTE(n) (0xf30 + (n) * 4)
+-#define SCC_EPCI_MAEA 0xf50
+-#define SCC_EPCI_MAEC 0xf54
+-#define SCC_EPCI_CKCTRL 0xff0
+-
+-/* bits for SCC_EPCI_VCSR */
+-#define SCC_EPCI_VCSR_FRE 0x00020000
+-#define SCC_EPCI_VCSR_FWE 0x00010000
+-#define SCC_EPCI_VCSR_DR 0x00000400
+-#define SCC_EPCI_VCSR_SR 0x00000008
+-#define SCC_EPCI_VCSR_AT 0x00000004
+-
+-/* bits for SCC_EPCI_VIENAB/SCC_EPCI_VISTAT */
+-#define SCC_EPCI_VISTAT_PMPE 0x00000008
+-#define SCC_EPCI_VISTAT_PMFE 0x00000004
+-#define SCC_EPCI_VISTAT_PRA 0x00000002
+-#define SCC_EPCI_VISTAT_PRD 0x00000001
+-#define SCC_EPCI_VISTAT_ALL 0x0000000f
+-
+-#define SCC_EPCI_VIENAB_PMPEE 0x00000008
+-#define SCC_EPCI_VIENAB_PMFEE 0x00000004
+-#define SCC_EPCI_VIENAB_PRA 0x00000002
+-#define SCC_EPCI_VIENAB_PRD 0x00000001
+-#define SCC_EPCI_VIENAB_ALL 0x0000000f
+-
+-/* bits for SCC_EPCI_CLKRST */
+-#define SCC_EPCI_CLKRST_CKS_MASK 0x00030000
+-#define SCC_EPCI_CLKRST_CKS_2 0x00000000
+-#define SCC_EPCI_CLKRST_CKS_4 0x00010000
+-#define SCC_EPCI_CLKRST_CKS_8 0x00020000
+-#define SCC_EPCI_CLKRST_PCICRST 0x00000400
+-#define SCC_EPCI_CLKRST_BC 0x00000200
+-#define SCC_EPCI_CLKRST_PCIRST 0x00000100
+-#define SCC_EPCI_CLKRST_PCKEN 0x00000001
+-
+-/* bits for SCC_EPCI_INTSET/SCC_EPCI_STATUS */
+-#define SCC_EPCI_INT_2M 0x01000000
+-#define SCC_EPCI_INT_RERR 0x00200000
+-#define SCC_EPCI_INT_SERR 0x00100000
+-#define SCC_EPCI_INT_PRTER 0x00080000
+-#define SCC_EPCI_INT_SER 0x00040000
+-#define SCC_EPCI_INT_PER 0x00020000
+-#define SCC_EPCI_INT_PAI 0x00010000
+-#define SCC_EPCI_INT_1M 0x00000100
+-#define SCC_EPCI_INT_PME 0x00000010
+-#define SCC_EPCI_INT_INTD 0x00000008
+-#define SCC_EPCI_INT_INTC 0x00000004
+-#define SCC_EPCI_INT_INTB 0x00000002
+-#define SCC_EPCI_INT_INTA 0x00000001
+-#define SCC_EPCI_INT_DEVINT 0x0000000f
+-#define SCC_EPCI_INT_ALL 0x003f001f
+-#define SCC_EPCI_INT_ALLERR 0x003f0000
+-
+-/* bits for SCC_EPCI_CKCTRL */
+-#define SCC_EPCI_CKCTRL_CRST0 0x00010000
+-#define SCC_EPCI_CKCTRL_CRST1 0x00020000
+-#define SCC_EPCI_CKCTRL_OCLKEN 0x00000100
+-#define SCC_EPCI_CKCTRL_LCLKEN 0x00000001
+-
+-#define SCC_EPCI_IDSEL_AD_TO_SLOT(ad) ((ad) - 10)
+-#define SCC_EPCI_MAX_DEVNU SCC_EPCI_IDSEL_AD_TO_SLOT(32)
+-
+-/* bits for SCC_EPCI_CNTOPT */
+-#define SCC_EPCI_CNTOPT_O2PMB 0x00000002
+-
+-/* UHC registers */
+-#define SCC_UHC_CKRCTRL 0xff0
+-#define SCC_UHC_ECMODE 0xf00
+-
+-/* bits for SCC_UHC_CKRCTRL */
+-#define SCC_UHC_F48MCKLEN 0x00000001
+-#define SCC_UHC_P_SUSPEND 0x00000002
+-#define SCC_UHC_PHY_SUSPEND_SEL 0x00000004
+-#define SCC_UHC_HCLKEN 0x00000100
+-#define SCC_UHC_USBEN 0x00010000
+-#define SCC_UHC_USBCEN 0x00020000
+-#define SCC_UHC_PHYEN 0x00040000
+-
+-/* bits for SCC_UHC_ECMODE */
+-#define SCC_UHC_ECMODE_BY_BYTE 0x00000555
+-#define SCC_UHC_ECMODE_BY_WORD 0x00000aaa
+-
+-#endif /* _CELLEB_SCC_H */
+diff --git a/arch/powerpc/platforms/celleb/scc_epci.c b/arch/powerpc/platforms/celleb/scc_epci.c
+deleted file mode 100644
+index a3c7cfb..0000000
+--- a/arch/powerpc/platforms/celleb/scc_epci.c
++++ /dev/null
+@@ -1,485 +0,0 @@
+-/*
+- * Support for SCC external PCI
+- *
+- * (C) Copyright 2004-2007 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; 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.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#undef DEBUG
+-
+-#include <linux/kernel.h>
+-#include <linux/threads.h>
+-#include <linux/pci.h>
+-#include <linux/init.h>
+-#include <linux/pci_regs.h>
+-#include <linux/bootmem.h>
+-
+-#include <asm/io.h>
+-#include <asm/irq.h>
+-#include <asm/prom.h>
+-#include <asm/machdep.h>
+-#include <asm/pci-bridge.h>
+-#include <asm/ppc-pci.h>
+-
+-#include "scc.h"
+-#include "pci.h"
+-#include "interrupt.h"
+-
+-#define MAX_PCI_DEVICES 32
+-#define MAX_PCI_FUNCTIONS 8
+-
+-#define iob() __asm__ __volatile__("eieio; sync":::"memory")
+-
+-struct epci_private {
+- dma_addr_t dummy_page_da;
+-};
+-
+-static inline PCI_IO_ADDR celleb_epci_get_epci_base(
+- struct pci_controller *hose)
+-{
+- /*
+- * Note:
+- * Celleb epci uses cfg_addr as a base address for
+- * epci control registers.
+- */
+-
+- return hose->cfg_addr;
+-}
+-
+-static inline PCI_IO_ADDR celleb_epci_get_epci_cfg(
+- struct pci_controller *hose)
+-{
+- /*
+- * Note:
+- * Celleb epci uses cfg_data as a base address for
+- * configuration area for epci devices.
+- */
+-
+- return hose->cfg_data;
+-}
+-
+-static void scc_epci_dummy_read(struct pci_controller *hose)
+-{
+- PCI_IO_ADDR epci_base;
+- u32 val;
+-
+- epci_base = celleb_epci_get_epci_base(hose);
+-
+- val = in_be32(epci_base + SCC_EPCI_WATRP);
+- iosync();
+-
+- return;
+-}
+-
+-void __init epci_workaround_init(struct pci_controller *hose)
+-{
+- PCI_IO_ADDR epci_base;
+- PCI_IO_ADDR reg;
+- struct epci_private *private = hose->private_data;
+-
+- BUG_ON(!private);
+-
+- private->dummy_page_da = dma_map_single(hose->parent,
+- celleb_dummy_page_va, PAGE_SIZE, DMA_FROM_DEVICE);
+- if (private->dummy_page_da == DMA_ERROR_CODE) {
+- printk(KERN_ERR "EPCI: dummy read disabled. "
+- "Map dummy page failed.\n");
+- return;
+- }
+-
+- celleb_pci_add_one(hose, scc_epci_dummy_read);
+- epci_base = celleb_epci_get_epci_base(hose);
+-
+- reg = epci_base + SCC_EPCI_DUMYRADR;
+- out_be32(reg, private->dummy_page_da);
+-}
+-
+-static inline void clear_and_disable_master_abort_interrupt(
+- struct pci_controller *hose)
+-{
+- PCI_IO_ADDR epci_base;
+- PCI_IO_ADDR reg;
+- epci_base = celleb_epci_get_epci_base(hose);
+- reg = epci_base + PCI_COMMAND;
+- out_be32(reg, in_be32(reg) | (PCI_STATUS_REC_MASTER_ABORT << 16));
+-}
+-
+-static int celleb_epci_check_abort(struct pci_controller *hose,
+- PCI_IO_ADDR addr)
+-{
+- PCI_IO_ADDR reg;
+- PCI_IO_ADDR epci_base;
+- u32 val;
+-
+- iob();
+- epci_base = celleb_epci_get_epci_base(hose);
+-
+- reg = epci_base + PCI_COMMAND;
+- val = in_be32(reg);
+-
+- if (val & (PCI_STATUS_REC_MASTER_ABORT << 16)) {
+- out_be32(reg,
+- (val & 0xffff) | (PCI_STATUS_REC_MASTER_ABORT << 16));
+-
+- /* clear PCI Controller error, FRE, PMFE */
+- reg = epci_base + SCC_EPCI_STATUS;
+- out_be32(reg, SCC_EPCI_INT_PAI);
+-
+- reg = epci_base + SCC_EPCI_VCSR;
+- val = in_be32(reg) & 0xffff;
+- val |= SCC_EPCI_VCSR_FRE;
+- out_be32(reg, val);
+-
+- reg = epci_base + SCC_EPCI_VISTAT;
+- out_be32(reg, SCC_EPCI_VISTAT_PMFE);
+- return PCIBIOS_DEVICE_NOT_FOUND;
+- }
+-
+- return PCIBIOS_SUCCESSFUL;
+-}
+-
+-static PCI_IO_ADDR celleb_epci_make_config_addr(
+- struct pci_bus *bus,
+- struct pci_controller *hose,
+- unsigned int devfn, int where)
+-{
+- PCI_IO_ADDR addr;
+-
+- if (bus != hose->bus)
+- addr = celleb_epci_get_epci_cfg(hose) +
+- (((bus->number & 0xff) << 16)
+- | ((devfn & 0xff) << 8)
+- | (where & 0xff)
+- | 0x01000000);
+- else
+- addr = celleb_epci_get_epci_cfg(hose) +
+- (((devfn & 0xff) << 8) | (where & 0xff));
+-
+- pr_debug("EPCI: config_addr = 0x%p\n", addr);
+-
+- return addr;
+-}
+-
+-static int celleb_epci_read_config(struct pci_bus *bus,
+- unsigned int devfn, int where, int size, u32 * val)
+-{
+- PCI_IO_ADDR epci_base;
+- PCI_IO_ADDR addr;
+- struct device_node *node;
+- struct pci_controller *hose;
+-
+- /* allignment check */
+- BUG_ON(where % size);
+-
+- node = (struct device_node *)bus->sysdata;
+- hose = pci_find_hose_for_OF_device(node);
+-
+- if (!celleb_epci_get_epci_cfg(hose))
+- return PCIBIOS_DEVICE_NOT_FOUND;
+-
+- if (bus->number == hose->first_busno && devfn == 0) {
+- /* EPCI controller self */
+-
+- epci_base = celleb_epci_get_epci_base(hose);
+- addr = epci_base + where;
+-
+- switch (size) {
+- case 1:
+- *val = in_8(addr);
+- break;
+- case 2:
+- *val = in_be16(addr);
+- break;
+- case 4:
+- *val = in_be32(addr);
+- break;
+- default:
+- return PCIBIOS_DEVICE_NOT_FOUND;
+- }
+-
+- } else {
+-
+- clear_and_disable_master_abort_interrupt(hose);
+- addr = celleb_epci_make_config_addr(bus, hose, devfn, where);
+-
+- switch (size) {
+- case 1:
+- *val = in_8(addr);
+- break;
+- case 2:
+- *val = in_le16(addr);
+- break;
+- case 4:
+- *val = in_le32(addr);
+- break;
+- default:
+- return PCIBIOS_DEVICE_NOT_FOUND;
+- }
+- }
+-
+- pr_debug("EPCI: "
+- "addr=0x%p, devfn=0x%x, where=0x%x, size=0x%x, val=0x%x\n",
+- addr, devfn, where, size, *val);
+-
+- return celleb_epci_check_abort(hose, NULL);
+-}
+-
+-static int celleb_epci_write_config(struct pci_bus *bus,
+- unsigned int devfn, int where, int size, u32 val)
+-{
+- PCI_IO_ADDR epci_base;
+- PCI_IO_ADDR addr;
+- struct device_node *node;
+- struct pci_controller *hose;
+-
+- /* allignment check */
+- BUG_ON(where % size);
+-
+- node = (struct device_node *)bus->sysdata;
+- hose = pci_find_hose_for_OF_device(node);
+-
+-
+- if (!celleb_epci_get_epci_cfg(hose))
+- return PCIBIOS_DEVICE_NOT_FOUND;
+-
+- if (bus->number == hose->first_busno && devfn == 0) {
+- /* EPCI controller self */
+-
+- epci_base = celleb_epci_get_epci_base(hose);
+- addr = epci_base + where;
+-
+- switch (size) {
+- case 1:
+- out_8(addr, val);
+- break;
+- case 2:
+- out_be16(addr, val);
+- break;
+- case 4:
+- out_be32(addr, val);
+- break;
+- default:
+- return PCIBIOS_DEVICE_NOT_FOUND;
+- }
+-
+- } else {
+-
+- clear_and_disable_master_abort_interrupt(hose);
+- addr = celleb_epci_make_config_addr(bus, hose, devfn, where);
+-
+- switch (size) {
+- case 1:
+- out_8(addr, val);
+- break;
+- case 2:
+- out_le16(addr, val);
+- break;
+- case 4:
+- out_le32(addr, val);
+- break;
+- default:
+- return PCIBIOS_DEVICE_NOT_FOUND;
+- }
+- }
+-
+- return celleb_epci_check_abort(hose, addr);
+-}
+-
+-struct pci_ops celleb_epci_ops = {
+- .read = celleb_epci_read_config,
+- .write = celleb_epci_write_config,
+-};
+-
+-/* to be moved in FW */
+-static int __init celleb_epci_init(struct pci_controller *hose)
+-{
+- u32 val;
+- PCI_IO_ADDR reg;
+- PCI_IO_ADDR epci_base;
+- int hwres = 0;
+-
+- epci_base = celleb_epci_get_epci_base(hose);
+-
+- /* PCI core reset(Internal bus and PCI clock) */
+- reg = epci_base + SCC_EPCI_CKCTRL;
+- val = in_be32(reg);
+- if (val == 0x00030101)
+- hwres = 1;
+- else {
+- val &= ~(SCC_EPCI_CKCTRL_CRST0 | SCC_EPCI_CKCTRL_CRST1);
+- out_be32(reg, val);
+-
+- /* set PCI core clock */
+- val = in_be32(reg);
+- val |= (SCC_EPCI_CKCTRL_OCLKEN | SCC_EPCI_CKCTRL_LCLKEN);
+- out_be32(reg, val);
+-
+- /* release PCI core reset (internal bus) */
+- val = in_be32(reg);
+- val |= SCC_EPCI_CKCTRL_CRST0;
+- out_be32(reg, val);
+-
+- /* set PCI clock select */
+- reg = epci_base + SCC_EPCI_CLKRST;
+- val = in_be32(reg);
+- val &= ~SCC_EPCI_CLKRST_CKS_MASK;
+- val |= SCC_EPCI_CLKRST_CKS_2;
+- out_be32(reg, val);
+-
+- /* set arbiter */
+- reg = epci_base + SCC_EPCI_ABTSET;
+- out_be32(reg, 0x0f1f001f); /* temporary value */
+-
+- /* buffer on */
+- reg = epci_base + SCC_EPCI_CLKRST;
+- val = in_be32(reg);
+- val |= SCC_EPCI_CLKRST_BC;
+- out_be32(reg, val);
+-
+- /* PCI clock enable */
+- val = in_be32(reg);
+- val |= SCC_EPCI_CLKRST_PCKEN;
+- out_be32(reg, val);
+-
+- /* release PCI core reset (all) */
+- reg = epci_base + SCC_EPCI_CKCTRL;
+- val = in_be32(reg);
+- val |= (SCC_EPCI_CKCTRL_CRST0 | SCC_EPCI_CKCTRL_CRST1);
+- out_be32(reg, val);
+-
+- /* set base translation registers. (already set by Beat) */
+-
+- /* set base address masks. (already set by Beat) */
+- }
+-
+- /* release interrupt masks and clear all interrupts */
+- reg = epci_base + SCC_EPCI_INTSET;
+- out_be32(reg, 0x013f011f); /* all interrupts enable */
+- reg = epci_base + SCC_EPCI_VIENAB;
+- val = SCC_EPCI_VIENAB_PMPEE | SCC_EPCI_VIENAB_PMFEE;
+- out_be32(reg, val);
+- reg = epci_base + SCC_EPCI_STATUS;
+- out_be32(reg, 0xffffffff);
+- reg = epci_base + SCC_EPCI_VISTAT;
+- out_be32(reg, 0xffffffff);
+-
+- /* disable PCI->IB address translation */
+- reg = epci_base + SCC_EPCI_VCSR;
+- val = in_be32(reg);
+- val &= ~(SCC_EPCI_VCSR_DR | SCC_EPCI_VCSR_AT);
+- out_be32(reg, val);
+-
+- /* set base addresses. (no need to set?) */
+-
+- /* memory space, bus master enable */
+- reg = epci_base + PCI_COMMAND;
+- val = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+- out_be32(reg, val);
+-
+- /* endian mode setup */
+- reg = epci_base + SCC_EPCI_ECMODE;
+- val = 0x00550155;
+- out_be32(reg, val);
+-
+- /* set control option */
+- reg = epci_base + SCC_EPCI_CNTOPT;
+- val = in_be32(reg);
+- val |= SCC_EPCI_CNTOPT_O2PMB;
+- out_be32(reg, val);
+-
+- /* XXX: temporay: set registers for address conversion setup */
+- reg = epci_base + SCC_EPCI_CNF10_REG;
+- out_be32(reg, 0x80000008);
+- reg = epci_base + SCC_EPCI_CNF14_REG;
+- out_be32(reg, 0x40000008);
+-
+- reg = epci_base + SCC_EPCI_BAM0;
+- out_be32(reg, 0x80000000);
+- reg = epci_base + SCC_EPCI_BAM1;
+- out_be32(reg, 0xe0000000);
+-
+- reg = epci_base + SCC_EPCI_PVBAT;
+- out_be32(reg, 0x80000000);
+-
+- if (!hwres) {
+- /* release external PCI reset */
+- reg = epci_base + SCC_EPCI_CLKRST;
+- val = in_be32(reg);
+- val |= SCC_EPCI_CLKRST_PCIRST;
+- out_be32(reg, val);
+- }
+-
+- return 0;
+-}
+-
+-int __init celleb_setup_epci(struct device_node *node,
+- struct pci_controller *hose)
+-{
+- struct resource r;
+-
+- pr_debug("PCI: celleb_setup_epci()\n");
+-
+- /*
+- * Note:
+- * Celleb epci uses cfg_addr and cfg_data member of
+- * pci_controller structure in irregular way.
+- *
+- * cfg_addr is used to map for control registers of
+- * celleb epci.
+- *
+- * cfg_data is used for configuration area of devices
+- * on Celleb epci buses.
+- */
+-
+- if (of_address_to_resource(node, 0, &r))
+- goto error;
+- hose->cfg_addr = ioremap(r.start, (r.end - r.start + 1));
+- if (!hose->cfg_addr)
+- goto error;
+- pr_debug("EPCI: cfg_addr map 0x%016lx->0x%016lx + 0x%016lx\n",
+- r.start, (unsigned long)hose->cfg_addr,
+- (r.end - r.start + 1));
+-
+- if (of_address_to_resource(node, 2, &r))
+- goto error;
+- hose->cfg_data = ioremap(r.start, (r.end - r.start + 1));
+- if (!hose->cfg_data)
+- goto error;
+- pr_debug("EPCI: cfg_data map 0x%016lx->0x%016lx + 0x%016lx\n",
+- r.start, (unsigned long)hose->cfg_data,
+- (r.end - r.start + 1));
+-
+- hose->private_data = kzalloc(sizeof(struct epci_private), GFP_KERNEL);
+- if (hose->private_data == NULL) {
+- printk(KERN_ERR "EPCI: no memory for private data.\n");
+- goto error;
+- }
+-
+- hose->ops = &celleb_epci_ops;
+- celleb_epci_init(hose);
+-
+- return 0;
+-
+-error:
+- kfree(hose->private_data);
+-
+- if (hose->cfg_addr)
+- iounmap(hose->cfg_addr);
+-
+- if (hose->cfg_data)
+- iounmap(hose->cfg_data);
+- return 1;
+-}
+diff --git a/arch/powerpc/platforms/celleb/scc_sio.c b/arch/powerpc/platforms/celleb/scc_sio.c
+deleted file mode 100644
+index 6100082..0000000
+--- a/arch/powerpc/platforms/celleb/scc_sio.c
++++ /dev/null
+@@ -1,101 +0,0 @@
+-/*
+- * setup serial port in SCC
+- *
+- * (C) Copyright 2006-2007 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; 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.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#include <linux/tty.h>
+-#include <linux/serial.h>
+-#include <linux/serial_core.h>
+-#include <linux/console.h>
+-
+-#include <asm/io.h>
+-#include <asm/prom.h>
+-
+-/* sio irq0=0xb00010022 irq0=0xb00010023 irq2=0xb00010024
+- mmio=0xfff000-0x1000,0xff2000-0x1000 */
+-static int txx9_serial_bitmap __initdata = 0;
+-
+-static struct {
+- uint32_t offset;
+- uint32_t index;
+-} txx9_scc_tab[3] __initdata = {
+- { 0x300, 0 }, /* 0xFFF300 */
+- { 0x400, 0 }, /* 0xFFF400 */
+- { 0x800, 1 } /* 0xFF2800 */
+-};
+-
+-static int __init txx9_serial_init(void)
+-{
+- extern int early_serial_txx9_setup(struct uart_port *port);
+- struct device_node *node = NULL;
+- int i;
+- struct uart_port req;
+- struct of_irq irq;
+- struct resource res;
+-
+- while ((node = of_find_compatible_node(node,
+- "serial", "toshiba,sio-scc")) != NULL) {
+- for (i = 0; i < ARRAY_SIZE(txx9_scc_tab); i++) {
+- if (!(txx9_serial_bitmap & (1<<i)))
+- continue;
+-
+- if (of_irq_map_one(node, i, &irq))
+- continue;
+- if (of_address_to_resource(node,
+- txx9_scc_tab[i].index, &res))
+- continue;
+-
+- memset(&req, 0, sizeof(req));
+- req.line = i;
+- req.iotype = UPIO_MEM;
+- req.mapbase = res.start + txx9_scc_tab[i].offset;
+-#ifdef CONFIG_SERIAL_TXX9_CONSOLE
+- req.membase = ioremap(req.mapbase, 0x24);
+-#endif
+- req.irq = irq_create_of_mapping(irq.controller,
+- irq.specifier, irq.size);
+- req.flags |= UPF_IOREMAP | UPF_BUGGY_UART
+- /*HAVE_CTS_LINE*/;
+- req.uartclk = 83300000;
+- early_serial_txx9_setup(&req);
+- }
+- }
+-
+- return 0;
+-}
+-
+-static int __init txx9_serial_config(char *ptr)
+-{
+- int i;
+-
+- for (;;) {
+- switch(get_option(&ptr, &i)) {
+- default:
+- return 0;
+- case 2:
+- txx9_serial_bitmap |= 1 << i;
+- break;
+- case 1:
+- txx9_serial_bitmap |= 1 << i;
+- return 0;
+- }
+- }
+-}
+-__setup("txx9_serial=", txx9_serial_config);
+-
+-console_initcall(txx9_serial_init);
+diff --git a/arch/powerpc/platforms/celleb/scc_uhc.c b/arch/powerpc/platforms/celleb/scc_uhc.c
+deleted file mode 100644
+index cb43079..0000000
+--- a/arch/powerpc/platforms/celleb/scc_uhc.c
++++ /dev/null
+@@ -1,95 +0,0 @@
+-/*
+- * SCC (Super Companion Chip) UHC setup
+- *
+- * (C) Copyright 2006-2007 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; 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.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/pci.h>
+-
+-#include <asm/delay.h>
+-#include <asm/io.h>
+-#include <asm/machdep.h>
+-
+-#include "scc.h"
+-
+-#define UHC_RESET_WAIT_MAX 10000
+-
+-static inline int uhc_clkctrl_ready(u32 val)
+-{
+- const u32 mask = SCC_UHC_USBCEN | SCC_UHC_USBCEN;
+- return((val & mask) == mask);
+-}
+-
+-/*
+- * UHC(usb host controller) enable function.
+- * affect to both of OHCI and EHCI core module.
+- */
+-static void enable_scc_uhc(struct pci_dev *dev)
+-{
+- void __iomem *uhc_base;
+- u32 __iomem *uhc_clkctrl;
+- u32 __iomem *uhc_ecmode;
+- u32 val = 0;
+- int i;
+-
+- if (!machine_is(celleb_beat) &&
+- !machine_is(celleb_native))
+- return;
+-
+- uhc_base = ioremap(pci_resource_start(dev, 0),
+- pci_resource_len(dev, 0));
+- if (!uhc_base) {
+- printk(KERN_ERR "failed to map UHC register base.\n");
+- return;
+- }
+- uhc_clkctrl = uhc_base + SCC_UHC_CKRCTRL;
+- uhc_ecmode = uhc_base + SCC_UHC_ECMODE;
+-
+- /* setup for normal mode */
+- val |= SCC_UHC_F48MCKLEN;
+- out_be32(uhc_clkctrl, val);
+- val |= SCC_UHC_PHY_SUSPEND_SEL;
+- out_be32(uhc_clkctrl, val);
+- udelay(10);
+- val |= SCC_UHC_PHYEN;
+- out_be32(uhc_clkctrl, val);
+- udelay(50);
+-
+- /* disable reset */
+- val |= SCC_UHC_HCLKEN;
+- out_be32(uhc_clkctrl, val);
+- val |= (SCC_UHC_USBCEN | SCC_UHC_USBEN);
+- out_be32(uhc_clkctrl, val);
+- i = 0;
+- while (!uhc_clkctrl_ready(in_be32(uhc_clkctrl))) {
+- udelay(10);
+- if (i++ > UHC_RESET_WAIT_MAX) {
+- printk(KERN_ERR "Failed to disable UHC reset %x\n",
+- in_be32(uhc_clkctrl));
+- break;
+- }
+- }
+-
+- /* Endian Conversion Mode for Master ALL area */
+- out_be32(uhc_ecmode, SCC_UHC_ECMODE_BY_BYTE);
+-
+- iounmap(uhc_base);
+-}
+-
+-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA_2,
+- PCI_DEVICE_ID_TOSHIBA_SCC_USB, enable_scc_uhc);
+diff --git a/arch/powerpc/platforms/celleb/setup.c b/arch/powerpc/platforms/celleb/setup.c
+deleted file mode 100644
+index f27ae1e..0000000
+--- a/arch/powerpc/platforms/celleb/setup.c
++++ /dev/null
+@@ -1,258 +0,0 @@
+-/*
+- * Celleb setup code
+- *
+- * (C) Copyright 2006-2007 TOSHIBA CORPORATION
+- *
+- * This code is based on arch/powerpc/platforms/cell/setup.c:
+- * Copyright (C) 1995 Linus Torvalds
+- * Adapted from 'alpha' version by Gary Thomas
+- * Modified by Cort Dougan (cort at cs.nmt.edu)
+- * Modified by PPC64 Team, IBM Corp
+- * Modified by Cell Team, IBM Deutschland Entwicklung GmbH
+- *
+- * 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.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#undef DEBUG
+-
+-#include <linux/cpu.h>
+-#include <linux/sched.h>
+-#include <linux/kernel.h>
+-#include <linux/mm.h>
+-#include <linux/stddef.h>
+-#include <linux/unistd.h>
+-#include <linux/reboot.h>
+-#include <linux/init.h>
+-#include <linux/delay.h>
+-#include <linux/irq.h>
+-#include <linux/seq_file.h>
+-#include <linux/root_dev.h>
+-#include <linux/console.h>
+-#include <linux/of_platform.h>
+-
+-#include <asm/mmu.h>
+-#include <asm/processor.h>
+-#include <asm/io.h>
+-#include <asm/kexec.h>
+-#include <asm/prom.h>
+-#include <asm/machdep.h>
+-#include <asm/cputable.h>
+-#include <asm/irq.h>
+-#include <asm/time.h>
+-#include <asm/spu_priv1.h>
+-#include <asm/firmware.h>
+-#include <asm/rtas.h>
+-#include <asm/cell-regs.h>
+-
+-#include "interrupt.h"
+-#include "beat_wrapper.h"
+-#include "beat.h"
+-#include "pci.h"
+-#include "../cell/interrupt.h"
+-#include "../cell/pervasive.h"
+-#include "../cell/ras.h"
+-
+-static char celleb_machine_type[128] = "Celleb";
+-
+-static void celleb_show_cpuinfo(struct seq_file *m)
+-{
+- struct device_node *root;
+- const char *model = "";
+-
+- root = of_find_node_by_path("/");
+- if (root)
+- model = of_get_property(root, "model", NULL);
+- /* using "CHRP" is to trick anaconda into installing FCx into Celleb */
+- seq_printf(m, "machine\t\t: %s %s\n", celleb_machine_type, model);
+- of_node_put(root);
+-}
+-
+-static int __init celleb_machine_type_hack(char *ptr)
+-{
+- strncpy(celleb_machine_type, ptr, sizeof(celleb_machine_type));
+- celleb_machine_type[sizeof(celleb_machine_type)-1] = 0;
+- return 0;
+-}
+-
+-__setup("celleb_machine_type_hack=", celleb_machine_type_hack);
+-
+-static void celleb_progress(char *s, unsigned short hex)
+-{
+- printk("*** %04x : %s\n", hex, s ? s : "");
+-}
+-
+-static void __init celleb_setup_arch_common(void)
+-{
+- /* init to some ~sane value until calibrate_delay() runs */
+- loops_per_jiffy = 50000000;
+-
+-#ifdef CONFIG_DUMMY_CONSOLE
+- conswitchp = &dummy_con;
+-#endif
+-}
+-
+-static struct of_device_id celleb_bus_ids[] __initdata = {
+- { .type = "scc", },
+- { .type = "ioif", }, /* old style */
+- {},
+-};
+-
+-static int __init celleb_publish_devices(void)
+-{
+- /* Publish OF platform devices for southbridge IOs */
+- of_platform_bus_probe(NULL, celleb_bus_ids, NULL);
+-
+- celleb_pci_workaround_init();
+-
+- return 0;
+-}
+-machine_device_initcall(celleb_beat, celleb_publish_devices);
+-machine_device_initcall(celleb_native, celleb_publish_devices);
+-
+-
+-/*
+- * functions for Celleb-Beat
+- */
+-static void __init celleb_setup_arch_beat(void)
+-{
+-#ifdef CONFIG_SPU_BASE
+- spu_priv1_ops = &spu_priv1_beat_ops;
+- spu_management_ops = &spu_management_of_ops;
+-#endif
+-
+-#ifdef CONFIG_SMP
+- smp_init_celleb();
+-#endif
+-
+- celleb_setup_arch_common();
+-}
+-
+-static int __init celleb_probe_beat(void)
+-{
+- unsigned long root = of_get_flat_dt_root();
+-
+- if (!of_flat_dt_is_compatible(root, "Beat"))
+- return 0;
+-
+- powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS
+- | FW_FEATURE_BEAT | FW_FEATURE_LPAR;
+- hpte_init_beat_v3();
+-
+- return 1;
+-}
+-
+-
+-/*
+- * functions for Celleb-native
+- */
+-static void __init celleb_init_IRQ_native(void)
+-{
+- iic_init_IRQ();
+- spider_init_IRQ();
+-}
+-
+-static void __init celleb_setup_arch_native(void)
+-{
+-#ifdef CONFIG_SPU_BASE
+- spu_priv1_ops = &spu_priv1_mmio_ops;
+- spu_management_ops = &spu_management_of_ops;
+-#endif
+-
+- cbe_regs_init();
+-
+-#ifdef CONFIG_CBE_RAS
+- cbe_ras_init();
+-#endif
+-
+-#ifdef CONFIG_SMP
+- smp_init_cell();
+-#endif
+-
+- cbe_pervasive_init();
+-
+- /* XXX: nvram initialization should be added */
+-
+- celleb_setup_arch_common();
+-}
+-
+-static int __init celleb_probe_native(void)
+-{
+- unsigned long root = of_get_flat_dt_root();
+-
+- if (of_flat_dt_is_compatible(root, "Beat") ||
+- !of_flat_dt_is_compatible(root, "TOSHIBA,Celleb"))
+- return 0;
+-
+- powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS;
+- hpte_init_native();
+-
+- return 1;
+-}
+-
+-
+-/*
+- * machine definitions
+- */
+-define_machine(celleb_beat) {
+- .name = "Cell Reference Set (Beat)",
+- .probe = celleb_probe_beat,
+- .setup_arch = celleb_setup_arch_beat,
+- .show_cpuinfo = celleb_show_cpuinfo,
+- .restart = beat_restart,
+- .power_off = beat_power_off,
+- .halt = beat_halt,
+- .get_rtc_time = beat_get_rtc_time,
+- .set_rtc_time = beat_set_rtc_time,
+- .calibrate_decr = generic_calibrate_decr,
+- .progress = celleb_progress,
+- .power_save = beat_power_save,
+- .nvram_size = beat_nvram_get_size,
+- .nvram_read = beat_nvram_read,
+- .nvram_write = beat_nvram_write,
+- .set_dabr = beat_set_xdabr,
+- .init_IRQ = beatic_init_IRQ,
+- .get_irq = beatic_get_irq,
+- .pci_probe_mode = celleb_pci_probe_mode,
+- .pci_setup_phb = celleb_setup_phb,
+-#ifdef CONFIG_KEXEC
+- .kexec_cpu_down = beat_kexec_cpu_down,
+- .machine_kexec = default_machine_kexec,
+- .machine_kexec_prepare = default_machine_kexec_prepare,
+- .machine_crash_shutdown = default_machine_crash_shutdown,
+-#endif
+-};
+-
+-define_machine(celleb_native) {
+- .name = "Cell Reference Set (native)",
+- .probe = celleb_probe_native,
+- .setup_arch = celleb_setup_arch_native,
+- .show_cpuinfo = celleb_show_cpuinfo,
+- .restart = rtas_restart,
+- .power_off = rtas_power_off,
+- .halt = rtas_halt,
+- .get_boot_time = rtas_get_boot_time,
+- .get_rtc_time = rtas_get_rtc_time,
+- .set_rtc_time = rtas_set_rtc_time,
+- .calibrate_decr = generic_calibrate_decr,
+- .progress = celleb_progress,
+- .pci_probe_mode = celleb_pci_probe_mode,
+- .pci_setup_phb = celleb_setup_phb,
+- .init_IRQ = celleb_init_IRQ_native,
+-#ifdef CONFIG_KEXEC
+- .machine_kexec = default_machine_kexec,
+- .machine_kexec_prepare = default_machine_kexec_prepare,
+- .machine_crash_shutdown = default_machine_crash_shutdown,
+-#endif
+-};
+diff --git a/arch/powerpc/platforms/celleb/smp.c b/arch/powerpc/platforms/celleb/smp.c
+deleted file mode 100644
+index a763125..0000000
+--- a/arch/powerpc/platforms/celleb/smp.c
++++ /dev/null
+@@ -1,124 +0,0 @@
+-/*
+- * SMP support for Celleb platform. (Incomplete)
+- *
+- * (C) Copyright 2006 TOSHIBA CORPORATION
+- *
+- * This code is based on arch/powerpc/platforms/cell/smp.c:
+- * Dave Engebretsen, Peter Bergner, and
+- * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
+- * Plus various changes from other IBM teams...
+- *
+- * 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.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#undef DEBUG
+-
+-#include <linux/kernel.h>
+-#include <linux/smp.h>
+-#include <linux/interrupt.h>
+-#include <linux/init.h>
+-#include <linux/threads.h>
+-#include <linux/cpu.h>
+-
+-#include <asm/irq.h>
+-#include <asm/smp.h>
+-#include <asm/machdep.h>
+-#include <asm/udbg.h>
+-
+-#include "interrupt.h"
+-
+-#ifdef DEBUG
+-#define DBG(fmt...) udbg_printf(fmt)
+-#else
+-#define DBG(fmt...)
+-#endif
+-
+-/*
+- * The primary thread of each non-boot processor is recorded here before
+- * smp init.
+- */
+-/* static cpumask_t of_spin_map; */
+-
+-/**
+- * smp_startup_cpu() - start the given cpu
+- *
+- * At boot time, there is nothing to do for primary threads which were
+- * started from Open Firmware. For anything else, call RTAS with the
+- * appropriate start location.
+- *
+- * Returns:
+- * 0 - failure
+- * 1 - success
+- */
+-static inline int __devinit smp_startup_cpu(unsigned int lcpu)
+-{
+- return 0;
+-}
+-
+-static void smp_beatic_message_pass(int target, int msg)
+-{
+- unsigned int i;
+-
+- if (target < NR_CPUS) {
+- beatic_cause_IPI(target, msg);
+- } else {
+- for_each_online_cpu(i) {
+- if (target == MSG_ALL_BUT_SELF
+- && i == smp_processor_id())
+- continue;
+- beatic_cause_IPI(i, msg);
+- }
+- }
+-}
+-
+-static int __init smp_beatic_probe(void)
+-{
+- return cpus_weight(cpu_possible_map);
+-}
+-
+-static void __devinit smp_beatic_setup_cpu(int cpu)
+-{
+- beatic_setup_cpu(cpu);
+-}
+-
+-static void __devinit smp_celleb_kick_cpu(int nr)
+-{
+- BUG_ON(nr < 0 || nr >= NR_CPUS);
+-
+- if (!smp_startup_cpu(nr))
+- return;
+-}
+-
+-static int smp_celleb_cpu_bootable(unsigned int nr)
+-{
+- return 1;
+-}
+-static struct smp_ops_t bpa_beatic_smp_ops = {
+- .message_pass = smp_beatic_message_pass,
+- .probe = smp_beatic_probe,
+- .kick_cpu = smp_celleb_kick_cpu,
+- .setup_cpu = smp_beatic_setup_cpu,
+- .cpu_bootable = smp_celleb_cpu_bootable,
+-};
+-
+-/* This is called very early */
+-void __init smp_init_celleb(void)
+-{
+- DBG(" -> smp_init_celleb()\n");
+-
+- smp_ops = &bpa_beatic_smp_ops;
+-
+- DBG(" <- smp_init_celleb()\n");
+-}
+diff --git a/arch/powerpc/platforms/celleb/spu_priv1.c b/arch/powerpc/platforms/celleb/spu_priv1.c
+deleted file mode 100644
+index 2bf6700..0000000
+--- a/arch/powerpc/platforms/celleb/spu_priv1.c
++++ /dev/null
+@@ -1,208 +0,0 @@
+-/*
+- * spu hypervisor abstraction for Beat
+- *
+- * (C) Copyright 2006-2007 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; 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.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#include <linux/module.h>
+-
+-#include <asm/types.h>
+-#include <asm/spu.h>
+-#include <asm/spu_priv1.h>
+-
+-#include "beat_wrapper.h"
+-
+-static inline void _int_mask_set(struct spu *spu, int class, u64 mask)
+-{
+- spu->shadow_int_mask_RW[class] = mask;
+- beat_set_irq_mask_for_spe(spu->spe_id, class, mask);
+-}
+-
+-static inline u64 _int_mask_get(struct spu *spu, int class)
+-{
+- return spu->shadow_int_mask_RW[class];
+-}
+-
+-static void int_mask_set(struct spu *spu, int class, u64 mask)
+-{
+- _int_mask_set(spu, class, mask);
+-}
+-
+-static u64 int_mask_get(struct spu *spu, int class)
+-{
+- return _int_mask_get(spu, class);
+-}
+-
+-static void int_mask_and(struct spu *spu, int class, u64 mask)
+-{
+- u64 old_mask;
+- old_mask = _int_mask_get(spu, class);
+- _int_mask_set(spu, class, old_mask & mask);
+-}
+-
+-static void int_mask_or(struct spu *spu, int class, u64 mask)
+-{
+- u64 old_mask;
+- old_mask = _int_mask_get(spu, class);
+- _int_mask_set(spu, class, old_mask | mask);
+-}
+-
+-static void int_stat_clear(struct spu *spu, int class, u64 stat)
+-{
+- beat_clear_interrupt_status_of_spe(spu->spe_id, class, stat);
+-}
+-
+-static u64 int_stat_get(struct spu *spu, int class)
+-{
+- u64 int_stat;
+- beat_get_interrupt_status_of_spe(spu->spe_id, class, &int_stat);
+- return int_stat;
+-}
+-
+-static void cpu_affinity_set(struct spu *spu, int cpu)
+-{
+- return;
+-}
+-
+-static u64 mfc_dar_get(struct spu *spu)
+-{
+- u64 dar;
+- beat_get_spe_privileged_state_1_registers(
+- spu->spe_id,
+- offsetof(struct spu_priv1, mfc_dar_RW), &dar);
+- return dar;
+-}
+-
+-static u64 mfc_dsisr_get(struct spu *spu)
+-{
+- u64 dsisr;
+- beat_get_spe_privileged_state_1_registers(
+- spu->spe_id,
+- offsetof(struct spu_priv1, mfc_dsisr_RW), &dsisr);
+- return dsisr;
+-}
+-
+-static void mfc_dsisr_set(struct spu *spu, u64 dsisr)
+-{
+- beat_set_spe_privileged_state_1_registers(
+- spu->spe_id,
+- offsetof(struct spu_priv1, mfc_dsisr_RW), dsisr);
+-}
+-
+-static void mfc_sdr_setup(struct spu *spu)
+-{
+- return;
+-}
+-
+-static void mfc_sr1_set(struct spu *spu, u64 sr1)
+-{
+- beat_set_spe_privileged_state_1_registers(
+- spu->spe_id,
+- offsetof(struct spu_priv1, mfc_sr1_RW), sr1);
+-}
+-
+-static u64 mfc_sr1_get(struct spu *spu)
+-{
+- u64 sr1;
+- beat_get_spe_privileged_state_1_registers(
+- spu->spe_id,
+- offsetof(struct spu_priv1, mfc_sr1_RW), &sr1);
+- return sr1;
+-}
+-
+-static void mfc_tclass_id_set(struct spu *spu, u64 tclass_id)
+-{
+- beat_set_spe_privileged_state_1_registers(
+- spu->spe_id,
+- offsetof(struct spu_priv1, mfc_tclass_id_RW), tclass_id);
+-}
+-
+-static u64 mfc_tclass_id_get(struct spu *spu)
+-{
+- u64 tclass_id;
+- beat_get_spe_privileged_state_1_registers(
+- spu->spe_id,
+- offsetof(struct spu_priv1, mfc_tclass_id_RW), &tclass_id);
+- return tclass_id;
+-}
+-
+-static void tlb_invalidate(struct spu *spu)
+-{
+- beat_set_spe_privileged_state_1_registers(
+- spu->spe_id,
+- offsetof(struct spu_priv1, tlb_invalidate_entry_W), 0ul);
+-}
+-
+-static void resource_allocation_groupID_set(struct spu *spu, u64 id)
+-{
+- beat_set_spe_privileged_state_1_registers(
+- spu->spe_id,
+- offsetof(struct spu_priv1, resource_allocation_groupID_RW),
+- id);
+-}
+-
+-static u64 resource_allocation_groupID_get(struct spu *spu)
+-{
+- u64 id;
+- beat_get_spe_privileged_state_1_registers(
+- spu->spe_id,
+- offsetof(struct spu_priv1, resource_allocation_groupID_RW),
+- &id);
+- return id;
+-}
+-
+-static void resource_allocation_enable_set(struct spu *spu, u64 enable)
+-{
+- beat_set_spe_privileged_state_1_registers(
+- spu->spe_id,
+- offsetof(struct spu_priv1, resource_allocation_enable_RW),
+- enable);
+-}
+-
+-static u64 resource_allocation_enable_get(struct spu *spu)
+-{
+- u64 enable;
+- beat_get_spe_privileged_state_1_registers(
+- spu->spe_id,
+- offsetof(struct spu_priv1, resource_allocation_enable_RW),
+- &enable);
+- return enable;
+-}
+-
+-const struct spu_priv1_ops spu_priv1_beat_ops =
+-{
+- .int_mask_and = int_mask_and,
+- .int_mask_or = int_mask_or,
+- .int_mask_set = int_mask_set,
+- .int_mask_get = int_mask_get,
+- .int_stat_clear = int_stat_clear,
+- .int_stat_get = int_stat_get,
+- .cpu_affinity_set = cpu_affinity_set,
+- .mfc_dar_get = mfc_dar_get,
+- .mfc_dsisr_get = mfc_dsisr_get,
+- .mfc_dsisr_set = mfc_dsisr_set,
+- .mfc_sdr_setup = mfc_sdr_setup,
+- .mfc_sr1_set = mfc_sr1_set,
+- .mfc_sr1_get = mfc_sr1_get,
+- .mfc_tclass_id_set = mfc_tclass_id_set,
+- .mfc_tclass_id_get = mfc_tclass_id_get,
+- .tlb_invalidate = tlb_invalidate,
+- .resource_allocation_groupID_set = resource_allocation_groupID_set,
+- .resource_allocation_groupID_get = resource_allocation_groupID_get,
+- .resource_allocation_enable_set = resource_allocation_enable_set,
+- .resource_allocation_enable_get = resource_allocation_enable_get,
+-};
+diff --git a/arch/powerpc/platforms/celleb/udbg_beat.c b/arch/powerpc/platforms/celleb/udbg_beat.c
+deleted file mode 100644
+index d888c46..0000000
+--- a/arch/powerpc/platforms/celleb/udbg_beat.c
++++ /dev/null
+@@ -1,97 +0,0 @@
+-/*
+- * udbg function for Beat
+- *
+- * (C) Copyright 2006 TOSHIBA CORPORATION
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; 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.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/console.h>
+-
+-#include <asm/machdep.h>
+-#include <asm/prom.h>
+-#include <asm/udbg.h>
+-
+-#include "beat.h"
+-
+-#define celleb_vtermno 0
+-
+-static void udbg_putc_beat(char c)
+-{
+- unsigned long rc;
+-
+- if (c == '\n')
+- udbg_putc_beat('\r');
+-
+- rc = beat_put_term_char(celleb_vtermno, 1, (uint64_t)c << 56, 0);
+-}
+-
+-/* Buffered chars getc */
+-static long inbuflen;
+-static long inbuf[2]; /* must be 2 longs */
+-
+-static int udbg_getc_poll_beat(void)
+-{
+- /* The interface is tricky because it may return up to 16 chars.
+- * We save them statically for future calls to udbg_getc().
+- */
+- char ch, *buf = (char *)inbuf;
+- int i;
+- long rc;
+- if (inbuflen == 0) {
+- /* get some more chars. */
+- inbuflen = 0;
+- rc = beat_get_term_char(celleb_vtermno, &inbuflen, inbuf+0, inbuf+1);
+- if (rc != 0)
+- inbuflen = 0; /* otherwise inbuflen is garbage */
+- }
+- if (inbuflen <= 0 || inbuflen > 16) {
+- /* Catch error case as well as other oddities (corruption) */
+- inbuflen = 0;
+- return -1;
+- }
+- ch = buf[0];
+- for (i = 1; i < inbuflen; i++) /* shuffle them down. */
+- buf[i-1] = buf[i];
+- inbuflen--;
+- return ch;
+-}
+-
+-static int udbg_getc_beat(void)
+-{
+- int ch;
+- for (;;) {
+- ch = udbg_getc_poll_beat();
+- if (ch == -1) {
+- /* This shouldn't be needed...but... */
+- volatile unsigned long delay;
+- for (delay=0; delay < 2000000; delay++)
+- ;
+- } else {
+- return ch;
+- }
+- }
+-}
+-
+-/* call this from early_init() for a working debug console on
+- * vterm capable LPAR machines
+- */
+-void __init udbg_init_debug_beat(void)
+-{
+- udbg_putc = udbg_putc_beat;
+- udbg_getc = udbg_getc_beat;
+- udbg_getc_poll = udbg_getc_poll_beat;
+-}
+diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
+index d4f8bf5..84e2d78 100644
+--- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
++++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
+@@ -117,11 +117,11 @@ static void __init mpc7448_hpc2_init_IRQ(void)
+ }
+
+ if (mpic_paddr == 0) {
+- printk("%s: No tsi108 PIC found !\n", __FUNCTION__);
++ printk("%s: No tsi108 PIC found !\n", __func__);
+ return;
+ }
+
+- DBG("%s: tsi108 pic phys_addr = 0x%x\n", __FUNCTION__,
++ DBG("%s: tsi108 pic phys_addr = 0x%x\n", __func__,
+ (u32) mpic_paddr);
+
+ mpic = mpic_alloc(tsi_pic, mpic_paddr,
+@@ -140,17 +140,17 @@ static void __init mpc7448_hpc2_init_IRQ(void)
+ #ifdef CONFIG_PCI
+ tsi_pci = of_find_node_by_type(NULL, "pci");
+ if (tsi_pci == NULL) {
+- printk("%s: No tsi108 pci node found !\n", __FUNCTION__);
++ printk("%s: No tsi108 pci node found !\n", __func__);
+ return;
+ }
+ cascade_node = of_find_node_by_type(NULL, "pic-router");
+ if (cascade_node == NULL) {
+- printk("%s: No tsi108 pci cascade node found !\n", __FUNCTION__);
++ printk("%s: No tsi108 pci cascade node found !\n", __func__);
+ return;
+ }
+
+ cascade_pci_irq = irq_of_parse_and_map(tsi_pci, 0);
+- DBG("%s: tsi108 cascade_pci_irq = 0x%x\n", __FUNCTION__,
++ DBG("%s: tsi108 cascade_pci_irq = 0x%x\n", __func__,
+ (u32) cascade_pci_irq);
+ tsi108_pci_int_init(cascade_node);
+ set_irq_data(cascade_pci_irq, mpic);
+diff --git a/arch/powerpc/platforms/embedded6xx/prpmc2800.c b/arch/powerpc/platforms/embedded6xx/prpmc2800.c
+index 653a5eb..5a19b9a 100644
+--- a/arch/powerpc/platforms/embedded6xx/prpmc2800.c
++++ b/arch/powerpc/platforms/embedded6xx/prpmc2800.c
+@@ -49,13 +49,13 @@ static void __init prpmc2800_setup_arch(void)
+ * ioremap mpp and gpp registers in case they are later
+ * needed by prpmc2800_reset_board().
+ */
+- np = of_find_compatible_node(NULL, NULL, "marvell,mv64x60-mpp");
++ np = of_find_compatible_node(NULL, NULL, "marvell,mv64360-mpp");
+ reg = of_get_property(np, "reg", NULL);
+ paddr = of_translate_address(np, reg);
+ of_node_put(np);
+ mv64x60_mpp_reg_base = ioremap(paddr, reg[1]);
+
+- np = of_find_compatible_node(NULL, NULL, "marvell,mv64x60-gpp");
++ np = of_find_compatible_node(NULL, NULL, "marvell,mv64360-gpp");
+ reg = of_get_property(np, "reg", NULL);
+ paddr = of_translate_address(np, reg);
+ of_node_put(np);
+diff --git a/arch/powerpc/platforms/iseries/exception.S b/arch/powerpc/platforms/iseries/exception.S
+index 5381038..8ff330d 100644
+--- a/arch/powerpc/platforms/iseries/exception.S
++++ b/arch/powerpc/platforms/iseries/exception.S
+@@ -38,11 +38,19 @@
+
+ .globl system_reset_iSeries
+ system_reset_iSeries:
+- mfspr r13,SPRN_SPRG3 /* Get paca address */
++ mfspr r13,SPRN_SPRG3 /* Get alpaca address */
++ LOAD_REG_IMMEDIATE(r23, alpaca)
++ li r0,ALPACA_SIZE
++ sub r23,r13,r23
++ divdu r23,r23,r0 /* r23 has cpu number */
++ LOAD_REG_IMMEDIATE(r13, paca)
++ mulli r0,r23,PACA_SIZE
++ add r13,r13,r0
++ mtspr SPRN_SPRG3,r13 /* Save it away for the future */
+ mfmsr r24
+ ori r24,r24,MSR_RI
+ mtmsrd r24 /* RI on */
+- lhz r24,PACAPACAINDEX(r13) /* Get processor # */
++ mr r24,r23
+ cmpwi 0,r24,0 /* Are we processor 0? */
+ bne 1f
+ b .__start_initialization_iSeries /* Start up the first processor */
+@@ -51,8 +59,33 @@ system_reset_iSeries:
+ andc r4,r4,r5
+ mtspr SPRN_CTRLT,r4
+
++/* Spin on __secondary_hold_spinloop until it is updated by the boot cpu. */
++/* In the UP case we'll yeild() later, and we will not access the paca anyway */
++#ifdef CONFIG_SMP
+ 1:
+ HMT_LOW
++ LOAD_REG_IMMEDIATE(r23, __secondary_hold_spinloop)
++ ld r23,0(r23)
++ sync
++ LOAD_REG_IMMEDIATE(r3,current_set)
++ sldi r28,r24,3 /* get current_set[cpu#] */
++ ldx r3,r3,r28
++ addi r1,r3,THREAD_SIZE
++ subi r1,r1,STACK_FRAME_OVERHEAD
++
++ cmpwi 0,r23,0 /* Keep poking the Hypervisor until */
++ bne 2f /* we're released */
++ /* Let the Hypervisor know we are alive */
++ /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */
++ lis r3,0x8002
++ rldicr r3,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */
++ li r0,-1 /* r0=-1 indicates a Hypervisor call */
++ sc /* Invoke the hypervisor via a system call */
++ b 1b
++#endif
++
++2:
++ HMT_LOW
+ #ifdef CONFIG_SMP
+ lbz r23,PACAPROCSTART(r13) /* Test if this processor
+ * should start */
+@@ -83,7 +116,7 @@ iSeries_secondary_smp_loop:
+ li r0,-1 /* r0=-1 indicates a Hypervisor call */
+ sc /* Invoke the hypervisor via a system call */
+ mfspr r13,SPRN_SPRG3 /* Put r13 back ???? */
+- b 1b /* If SMP not configured, secondaries
++ b 2b /* If SMP not configured, secondaries
+ * loop forever */
+
+ /*** ISeries-LPAR interrupt handlers ***/
+diff --git a/arch/powerpc/platforms/iseries/ipl_parms.h b/arch/powerpc/platforms/iseries/ipl_parms.h
+index 77c135d..83e4ca4 100644
+--- a/arch/powerpc/platforms/iseries/ipl_parms.h
++++ b/arch/powerpc/platforms/iseries/ipl_parms.h
+@@ -65,6 +65,4 @@ struct ItIplParmsReal {
+ u64 xRsvd13; // Reserved x38-x3F
+ };
+
+-extern struct ItIplParmsReal xItIplParmsReal;
+-
+ #endif /* _ISERIES_IPL_PARMS_H */
+diff --git a/arch/powerpc/platforms/iseries/lpardata.c b/arch/powerpc/platforms/iseries/lpardata.c
+index 8162049..98bd2d3 100644
+--- a/arch/powerpc/platforms/iseries/lpardata.c
++++ b/arch/powerpc/platforms/iseries/lpardata.c
+@@ -14,10 +14,10 @@
+ #include <asm/ptrace.h>
+ #include <asm/abs_addr.h>
+ #include <asm/lppaca.h>
+-#include <asm/iseries/it_lp_reg_save.h>
+ #include <asm/paca.h>
+ #include <asm/iseries/lpar_map.h>
+ #include <asm/iseries/it_lp_queue.h>
++#include <asm/iseries/alpaca.h>
+
+ #include "naca.h"
+ #include "vpd_areas.h"
+@@ -31,7 +31,7 @@
+ /* The HvReleaseData is the root of the information shared between
+ * the hypervisor and Linux.
+ */
+-struct HvReleaseData hvReleaseData = {
++const struct HvReleaseData hvReleaseData = {
+ .xDesc = 0xc8a5d9c4, /* "HvRD" ebcdic */
+ .xSize = sizeof(struct HvReleaseData),
+ .xVpdAreasPtrOffset = offsetof(struct naca_struct, xItVpdAreas),
+@@ -61,6 +61,63 @@ struct naca_struct naca = {
+ .xRamDiskSize = 0,
+ };
+
++struct ItLpRegSave {
++ u32 xDesc; // Eye catcher "LpRS" ebcdic 000-003
++ u16 xSize; // Size of this class 004-005
++ u8 xInUse; // Area is live 006-007
++ u8 xRsvd1[9]; // Reserved 007-00F
++
++ u8 xFixedRegSave[352]; // Fixed Register Save Area 010-16F
++ u32 xCTRL; // Control Register 170-173
++ u32 xDEC; // Decrementer 174-177
++ u32 xFPSCR; // FP Status and Control Reg 178-17B
++ u32 xPVR; // Processor Version Number 17C-17F
++
++ u64 xMMCR0; // Monitor Mode Control Reg 0 180-187
++ u32 xPMC1; // Perf Monitor Counter 1 188-18B
++ u32 xPMC2; // Perf Monitor Counter 2 18C-18F
++ u32 xPMC3; // Perf Monitor Counter 3 190-193
++ u32 xPMC4; // Perf Monitor Counter 4 194-197
++ u32 xPIR; // Processor ID Reg 198-19B
++
++ u32 xMMCR1; // Monitor Mode Control Reg 1 19C-19F
++ u32 xMMCRA; // Monitor Mode Control Reg A 1A0-1A3
++ u32 xPMC5; // Perf Monitor Counter 5 1A4-1A7
++ u32 xPMC6; // Perf Monitor Counter 6 1A8-1AB
++ u32 xPMC7; // Perf Monitor Counter 7 1AC-1AF
++ u32 xPMC8; // Perf Monitor Counter 8 1B0-1B3
++ u32 xTSC; // Thread Switch Control 1B4-1B7
++ u32 xTST; // Thread Switch Timeout 1B8-1BB
++ u32 xRsvd; // Reserved 1BC-1BF
++
++ u64 xACCR; // Address Compare Control Reg 1C0-1C7
++ u64 xIMR; // Instruction Match Register 1C8-1CF
++ u64 xSDR1; // Storage Description Reg 1 1D0-1D7
++ u64 xSPRG0; // Special Purpose Reg General0 1D8-1DF
++ u64 xSPRG1; // Special Purpose Reg General1 1E0-1E7
++ u64 xSPRG2; // Special Purpose Reg General2 1E8-1EF
++ u64 xSPRG3; // Special Purpose Reg General3 1F0-1F7
++ u64 xTB; // Time Base Register 1F8-1FF
++
++ u64 xFPR[32]; // Floating Point Registers 200-2FF
++
++ u64 xMSR; // Machine State Register 300-307
++ u64 xNIA; // Next Instruction Address 308-30F
++
++ u64 xDABR; // Data Address Breakpoint Reg 310-317
++ u64 xIABR; // Inst Address Breakpoint Reg 318-31F
++
++ u64 xHID0; // HW Implementation Dependent0 320-327
++
++ u64 xHID4; // HW Implementation Dependent4 328-32F
++ u64 xSCOMd; // SCON Data Reg (SPRG4) 330-337
++ u64 xSCOMc; // SCON Command Reg (SPRG5) 338-33F
++ u64 xSDAR; // Sample Data Address Register 340-347
++ u64 xSIAR; // Sample Inst Address Register 348-34F
++
++ u8 xRsvd3[176]; // Reserved 350-3FF
++};
++
+ extern void system_reset_iSeries(void);
+ extern void machine_check_iSeries(void);
+ extern void data_access_iSeries(void);
+@@ -129,7 +186,7 @@ struct ItLpNaca itLpNaca = {
+ };
+
+ /* May be filled in by the hypervisor so cannot end up in the BSS */
+-struct ItIplParmsReal xItIplParmsReal __attribute__((__section__(".data")));
++static struct ItIplParmsReal xItIplParmsReal __attribute__((__section__(".data")));
+
+ /* May be filled in by the hypervisor so cannot end up in the BSS */
+ struct ItExtVpdPanel xItExtVpdPanel __attribute__((__section__(".data")));
+@@ -152,13 +209,54 @@ u64 xMsVpd[3400] __attribute__((__section__(".data")));
+
+ /* Space for Recovery Log Buffer */
+ /* May be filled in by the hypervisor so cannot end up in the BSS */
+-u64 xRecoveryLogBuffer[32] __attribute__((__section__(".data")));
++static u64 xRecoveryLogBuffer[32] __attribute__((__section__(".data")));
+
+-struct SpCommArea xSpCommArea = {
++static const struct SpCommArea xSpCommArea = {
+ .xDesc = 0xE2D7C3C2,
+ .xFormat = 1,
+ };
+
++static const struct ItLpRegSave iseries_reg_save[] = {
++ [0 ... (NR_CPUS-1)] = {
++ .xDesc = 0xd397d9e2, /* "LpRS" */
++ .xSize = sizeof(struct ItLpRegSave),
++ },
++};
++
++#define ALPACA_INIT(number) \
++{ \
++ .lppaca_ptr = &lppaca[number], \
++ .reg_save_ptr = &iseries_reg_save[number], \
++}
++
++const struct alpaca alpaca[] = {
++ ALPACA_INIT( 0),
++#if NR_CPUS > 1
++ ALPACA_INIT( 1), ALPACA_INIT( 2), ALPACA_INIT( 3),
++#if NR_CPUS > 4
++ ALPACA_INIT( 4), ALPACA_INIT( 5), ALPACA_INIT( 6), ALPACA_INIT( 7),
++#if NR_CPUS > 8
++ ALPACA_INIT( 8), ALPACA_INIT( 9), ALPACA_INIT(10), ALPACA_INIT(11),
++ ALPACA_INIT(12), ALPACA_INIT(13), ALPACA_INIT(14), ALPACA_INIT(15),
++ ALPACA_INIT(16), ALPACA_INIT(17), ALPACA_INIT(18), ALPACA_INIT(19),
++ ALPACA_INIT(20), ALPACA_INIT(21), ALPACA_INIT(22), ALPACA_INIT(23),
++ ALPACA_INIT(24), ALPACA_INIT(25), ALPACA_INIT(26), ALPACA_INIT(27),
++ ALPACA_INIT(28), ALPACA_INIT(29), ALPACA_INIT(30), ALPACA_INIT(31),
++#if NR_CPUS > 32
++ ALPACA_INIT(32), ALPACA_INIT(33), ALPACA_INIT(34), ALPACA_INIT(35),
++ ALPACA_INIT(36), ALPACA_INIT(37), ALPACA_INIT(38), ALPACA_INIT(39),
++ ALPACA_INIT(40), ALPACA_INIT(41), ALPACA_INIT(42), ALPACA_INIT(43),
++ ALPACA_INIT(44), ALPACA_INIT(45), ALPACA_INIT(46), ALPACA_INIT(47),
++ ALPACA_INIT(48), ALPACA_INIT(49), ALPACA_INIT(50), ALPACA_INIT(51),
++ ALPACA_INIT(52), ALPACA_INIT(53), ALPACA_INIT(54), ALPACA_INIT(55),
++ ALPACA_INIT(56), ALPACA_INIT(57), ALPACA_INIT(58), ALPACA_INIT(59),
++ ALPACA_INIT(60), ALPACA_INIT(61), ALPACA_INIT(62), ALPACA_INIT(63),
++#endif
++#endif
++#endif
++#endif
++};
++
+ /* The LparMap data is now located at offset 0x6000 in head.S
+ * It was put there so that the HvReleaseData could address it
+ * with a 32-bit offset as required by the iSeries hypervisor
+@@ -167,7 +265,7 @@ struct SpCommArea xSpCommArea = {
+ * the Naca via the HvReleaseData area. The HvReleaseData has the
+ * offset into the Naca of the pointer to the ItVpdAreas.
+ */
+-struct ItVpdAreas itVpdAreas = {
++const struct ItVpdAreas itVpdAreas = {
+ .xSlicDesc = 0xc9a3e5c1, /* "ItVA" */
+ .xSlicSize = sizeof(struct ItVpdAreas),
+ .xSlicVpdEntries = ItVpdMaxEntries, /* # VPD array entries */
+@@ -185,7 +283,7 @@ struct ItVpdAreas itVpdAreas = {
+ .xSlicVpdLens = { /* VPD lengths */
+ 0,0,0, /* 0 - 2 */
+ sizeof(xItExtVpdPanel), /* 3 Extended VPD */
+- sizeof(struct paca_struct), /* 4 length of Paca */
++ sizeof(struct alpaca), /* 4 length of (fake) Paca */
+ 0, /* 5 */
+ sizeof(struct ItIplParmsReal),/* 6 length of IPL parms */
+ 26992, /* 7 length of MS VPD */
+@@ -203,7 +301,7 @@ struct ItVpdAreas itVpdAreas = {
+ .xSlicVpdAdrs = { /* VPD addresses */
+ 0,0,0, /* 0 - 2 */
+ &xItExtVpdPanel, /* 3 Extended VPD */
+- &paca[0], /* 4 first Paca */
++ &alpaca[0], /* 4 first (fake) Paca */
+ 0, /* 5 */
+ &xItIplParmsReal, /* 6 IPL parms */
+ &xMsVpd, /* 7 MS Vpd */
+@@ -219,10 +317,3 @@ struct ItVpdAreas itVpdAreas = {
+ 0,0
+ }
+ };
+-
+-struct ItLpRegSave iseries_reg_save[] = {
+- [0 ... (NR_CPUS-1)] = {
+- .xDesc = 0xd397d9e2, /* "LpRS" */
+- .xSize = sizeof(struct ItLpRegSave),
+- },
+-};
+diff --git a/arch/powerpc/platforms/iseries/naca.h b/arch/powerpc/platforms/iseries/naca.h
+index ab2372e..f01708e 100644
+--- a/arch/powerpc/platforms/iseries/naca.h
++++ b/arch/powerpc/platforms/iseries/naca.h
+@@ -14,7 +14,7 @@
+
+ struct naca_struct {
+ /* Kernel only data - undefined for user space */
+- void *xItVpdAreas; /* VPD Data 0x00 */
++ const void *xItVpdAreas; /* VPD Data 0x00 */
+ void *xRamDisk; /* iSeries ramdisk 0x08 */
+ u64 xRamDiskSize; /* In pages 0x10 */
+ };
+diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
+index cc562e4..02a634f 100644
+--- a/arch/powerpc/platforms/iseries/pci.c
++++ b/arch/powerpc/platforms/iseries/pci.c
+@@ -23,6 +23,7 @@
+
+ #undef DEBUG
+
++#include <linux/jiffies.h>
+ #include <linux/kernel.h>
+ #include <linux/list.h>
+ #include <linux/string.h>
+@@ -586,7 +587,7 @@ static inline struct device_node *xlate_iomm_address(
+ static unsigned long last_jiffies;
+ static int num_printed;
+
+- if ((jiffies - last_jiffies) > 60 * HZ) {
++ if (time_after(jiffies, last_jiffies + 60 * HZ)) {
+ last_jiffies = jiffies;
+ num_printed = 0;
+ }
+diff --git a/arch/powerpc/platforms/iseries/release_data.h b/arch/powerpc/platforms/iseries/release_data.h
+index 66189fd..6ad7d84 100644
+--- a/arch/powerpc/platforms/iseries/release_data.h
++++ b/arch/powerpc/platforms/iseries/release_data.h
+@@ -58,6 +58,6 @@ struct HvReleaseData {
+ char xRsvd3[20]; /* Reserved x2C-x3F */
+ };
+
+-extern struct HvReleaseData hvReleaseData;
++extern const struct HvReleaseData hvReleaseData;
+
+ #endif /* _ISERIES_RELEASE_DATA_H */
+diff --git a/arch/powerpc/platforms/iseries/spcomm_area.h b/arch/powerpc/platforms/iseries/spcomm_area.h
+index 6e3b685..598b7c1 100644
+--- a/arch/powerpc/platforms/iseries/spcomm_area.h
++++ b/arch/powerpc/platforms/iseries/spcomm_area.h
+@@ -31,6 +31,4 @@ struct SpCommArea {
+ u8 xRsvd2[80]; // Reserved 030-07F
+ };
+
+-extern struct SpCommArea xSpCommArea;
+-
+ #endif /* _ISERIES_SPCOMM_AREA_H */
+diff --git a/arch/powerpc/platforms/iseries/vpd_areas.h b/arch/powerpc/platforms/iseries/vpd_areas.h
+index 601e6dd..feb001f 100644
+--- a/arch/powerpc/platforms/iseries/vpd_areas.h
++++ b/arch/powerpc/platforms/iseries/vpd_areas.h
+@@ -80,9 +80,9 @@ struct ItVpdAreas {
+ u32 xPlicDmaLens[ItDmaMaxEntries];// Array of DMA lengths 080-0A7
+ u32 xPlicDmaToks[ItDmaMaxEntries];// Array of DMA tokens 0A8-0CF
+ u32 xSlicVpdLens[ItVpdMaxEntries];// Array of VPD lengths 0D0-12F
+- void *xSlicVpdAdrs[ItVpdMaxEntries];// Array of VPD buffers 130-1EF
++ const void *xSlicVpdAdrs[ItVpdMaxEntries];// Array of VPD buffers 130-1EF
+ };
+
+-extern struct ItVpdAreas itVpdAreas;
++extern const struct ItVpdAreas itVpdAreas;
+
+ #endif /* _ISERIES_VPD_AREAS_H */
+diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
+index 3ffa0ac..3018552 100644
+--- a/arch/powerpc/platforms/maple/pci.c
++++ b/arch/powerpc/platforms/maple/pci.c
+@@ -592,50 +592,3 @@ int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel)
+ }
+ return irq;
+ }
+-
+-/* XXX: To remove once all firmwares are ok */
+-static void fixup_maple_ide(struct pci_dev* dev)
+-{
+- if (!machine_is(maple))
+- return;
+-
+-#if 0 /* Enable this to enable IDE port 0 */
+- {
+- u8 v;
+-
+- pci_read_config_byte(dev, 0x40, &v);
+- v |= 2;
+- pci_write_config_byte(dev, 0x40, v);
+- }
+-#endif
+-#if 0 /* fix bus master base */
+- pci_write_config_dword(dev, 0x20, 0xcc01);
+- printk("old ide resource: %lx -> %lx \n",
+- dev->resource[4].start, dev->resource[4].end);
+- dev->resource[4].start = 0xcc00;
+- dev->resource[4].end = 0xcc10;
+-#endif
+-#if 0 /* Enable this to fixup IDE sense/polarity of irqs in IO-APICs */
+- {
+- struct pci_dev *apicdev;
+- u32 v;
+-
+- apicdev = pci_get_slot (dev->bus, PCI_DEVFN(5,0));
+- if (apicdev == NULL)
+- printk("IDE Fixup IRQ: Can't find IO-APIC !\n");
+- else {
+- pci_write_config_byte(apicdev, 0xf2, 0x10 + 2*14);
+- pci_read_config_dword(apicdev, 0xf4, &v);
+- v &= ~0x00000022;
+- pci_write_config_dword(apicdev, 0xf4, v);
+- pci_write_config_byte(apicdev, 0xf2, 0x10 + 2*15);
+- pci_read_config_dword(apicdev, 0xf4, &v);
+- v &= ~0x00000022;
+- pci_write_config_dword(apicdev, 0xf4, v);
+- pci_dev_put(apicdev);
+- }
+- }
+-#endif
+-}
+-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_IDE,
+- fixup_maple_ide);
+diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
+index 3ce2d73..3647147 100644
+--- a/arch/powerpc/platforms/maple/setup.c
++++ b/arch/powerpc/platforms/maple/setup.c
+@@ -43,6 +43,7 @@
+ #include <linux/smp.h>
+ #include <linux/bitops.h>
+ #include <linux/of_device.h>
++#include <linux/lmb.h>
+
+ #include <asm/processor.h>
+ #include <asm/sections.h>
+@@ -57,7 +58,6 @@
+ #include <asm/dma.h>
+ #include <asm/cputable.h>
+ #include <asm/time.h>
+-#include <asm/lmb.h>
+ #include <asm/mpic.h>
+ #include <asm/rtas.h>
+ #include <asm/udbg.h>
+@@ -319,7 +319,7 @@ static int __init maple_probe(void)
+ return 1;
+ }
+
+-define_machine(maple_md) {
++define_machine(maple) {
+ .name = "Maple",
+ .probe = maple_probe,
+ .setup_arch = maple_setup_arch,
+diff --git a/arch/powerpc/platforms/pasemi/dma_lib.c b/arch/powerpc/platforms/pasemi/dma_lib.c
+index c529d8d..217af32 100644
+--- a/arch/powerpc/platforms/pasemi/dma_lib.c
++++ b/arch/powerpc/platforms/pasemi/dma_lib.c
+@@ -17,6 +17,7 @@
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
++#include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/module.h>
+ #include <linux/pci.h>
+@@ -26,6 +27,8 @@
+
+ #define MAX_TXCH 64
+ #define MAX_RXCH 64
++#define MAX_FLAGS 64
++#define MAX_FUN 8
+
+ static struct pasdma_status *dma_status;
+
+@@ -43,6 +46,8 @@ static struct pci_dev *dma_pdev;
+
+ static DECLARE_BITMAP(txch_free, MAX_TXCH);
+ static DECLARE_BITMAP(rxch_free, MAX_RXCH);
++static DECLARE_BITMAP(flags_free, MAX_FLAGS);
++static DECLARE_BITMAP(fun_free, MAX_FUN);
+
+ /* pasemi_read_iob_reg - read IOB register
+ * @reg: Register to read (offset into PCI CFG space)
+@@ -373,6 +378,106 @@ void pasemi_dma_free_buf(struct pasemi_dmachan *chan, int size,
+ }
+ EXPORT_SYMBOL(pasemi_dma_free_buf);
+
++/* pasemi_dma_alloc_flag - Allocate a flag (event) for channel syncronization
++ *
++ * Allocates a flag for use with channel syncronization (event descriptors).
++ * Returns allocated flag (0-63), < 0 on error.
++ */
++int pasemi_dma_alloc_flag(void)
++{
++ int bit;
++
++retry:
++ bit = find_next_bit(flags_free, MAX_FLAGS, 0);
++ if (bit >= MAX_FLAGS)
++ return -ENOSPC;
++ if (!test_and_clear_bit(bit, flags_free))
++ goto retry;
++
++ return bit;
++}
++EXPORT_SYMBOL(pasemi_dma_alloc_flag);
++
++
++/* pasemi_dma_free_flag - Deallocates a flag (event)
++ * @flag: Flag number to deallocate
++ *
++ * Frees up a flag so it can be reused for other purposes.
++ */
++void pasemi_dma_free_flag(int flag)
++{
++ BUG_ON(test_bit(flag, flags_free));
++ BUG_ON(flag >= MAX_FLAGS);
++ set_bit(flag, flags_free);
++}
++EXPORT_SYMBOL(pasemi_dma_free_flag);
++
++
++/* pasemi_dma_set_flag - Sets a flag (event) to 1
++ * @flag: Flag number to set active
++ *
++ * Sets the flag provided to 1.
++ */
++void pasemi_dma_set_flag(int flag)
++{
++ BUG_ON(flag >= MAX_FLAGS);
++ if (flag < 32)
++ pasemi_write_dma_reg(PAS_DMA_TXF_SFLG0, 1 << flag);
++ else
++ pasemi_write_dma_reg(PAS_DMA_TXF_SFLG1, 1 << flag);
++}
++EXPORT_SYMBOL(pasemi_dma_set_flag);
++
++/* pasemi_dma_clear_flag - Sets a flag (event) to 0
++ * @flag: Flag number to set inactive
++ *
++ * Sets the flag provided to 0.
++ */
++void pasemi_dma_clear_flag(int flag)
++{
++ BUG_ON(flag >= MAX_FLAGS);
++ if (flag < 32)
++ pasemi_write_dma_reg(PAS_DMA_TXF_CFLG0, 1 << flag);
++ else
++ pasemi_write_dma_reg(PAS_DMA_TXF_CFLG1, 1 << flag);
++}
++EXPORT_SYMBOL(pasemi_dma_clear_flag);
++
++/* pasemi_dma_alloc_fun - Allocate a function engine
++ *
++ * Allocates a function engine to use for crypto/checksum offload
++ * Returns allocated engine (0-8), < 0 on error.
++ */
++int pasemi_dma_alloc_fun(void)
++{
++ int bit;
++
++retry:
++ bit = find_next_bit(fun_free, MAX_FLAGS, 0);
++ if (bit >= MAX_FLAGS)
++ return -ENOSPC;
++ if (!test_and_clear_bit(bit, fun_free))
++ goto retry;
++
++ return bit;
++}
++EXPORT_SYMBOL(pasemi_dma_alloc_fun);
++
++
++/* pasemi_dma_free_fun - Deallocates a function engine
++ * @flag: Engine number to deallocate
++ *
++ * Frees up a function engine so it can be used for other purposes.
++ */
++void pasemi_dma_free_fun(int fun)
++{
++ BUG_ON(test_bit(fun, fun_free));
++ BUG_ON(fun >= MAX_FLAGS);
++ set_bit(fun, fun_free);
++}
++EXPORT_SYMBOL(pasemi_dma_free_fun);
++
++
+ static void *map_onedev(struct pci_dev *p, int index)
+ {
+ struct device_node *dn;
+@@ -410,6 +515,7 @@ int pasemi_dma_init(void)
+ struct resource res;
+ struct device_node *dn;
+ int i, intf, err = 0;
++ unsigned long timeout;
+ u32 tmp;
+
+ if (!machine_is(pasemi))
+@@ -478,6 +584,44 @@ int pasemi_dma_init(void)
+ for (i = 0; i < MAX_RXCH; i++)
+ __set_bit(i, rxch_free);
+
++ timeout = jiffies + HZ;
++ pasemi_write_dma_reg(PAS_DMA_COM_RXCMD, 0);
++ while (pasemi_read_dma_reg(PAS_DMA_COM_RXSTA) & 1) {
++ if (time_after(jiffies, timeout)) {
++ pr_warning("Warning: Could not disable RX section\n");
++ break;
++ }
++ }
++
++ timeout = jiffies + HZ;
++ pasemi_write_dma_reg(PAS_DMA_COM_TXCMD, 0);
++ while (pasemi_read_dma_reg(PAS_DMA_COM_TXSTA) & 1) {
++ if (time_after(jiffies, timeout)) {
++ pr_warning("Warning: Could not disable TX section\n");
++ break;
++ }
++ }
++
++ /* setup resource allocations for the different DMA sections */
++ tmp = pasemi_read_dma_reg(PAS_DMA_COM_CFG);
++ pasemi_write_dma_reg(PAS_DMA_COM_CFG, tmp | 0x18000000);
++
++ /* enable tx section */
++ pasemi_write_dma_reg(PAS_DMA_COM_TXCMD, PAS_DMA_COM_TXCMD_EN);
++
++ /* enable rx section */
++ pasemi_write_dma_reg(PAS_DMA_COM_RXCMD, PAS_DMA_COM_RXCMD_EN);
++
++ for (i = 0; i < MAX_FLAGS; i++)
++ __set_bit(i, flags_free);
++
++ for (i = 0; i < MAX_FUN; i++)
++ __set_bit(i, fun_free);
++
++ /* clear all status flags */
++ pasemi_write_dma_reg(PAS_DMA_TXF_CFLG0, 0xffffffff);
++ pasemi_write_dma_reg(PAS_DMA_TXF_CFLG1, 0xffffffff);
++
+ printk(KERN_INFO "PA Semi PWRficient DMA library initialized "
+ "(%d tx, %d rx channels)\n", num_txch, num_rxch);
+
+diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c
+index b465429..ab69554 100644
+--- a/arch/powerpc/platforms/pasemi/gpio_mdio.c
++++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c
+@@ -241,7 +241,7 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev,
+ new_bus->reset = &gpio_mdio_reset;
+
+ prop = of_get_property(np, "reg", NULL);
+- new_bus->id = *prop;
++ snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", *prop);
+ new_bus->priv = priv;
+
+ new_bus->phy_mask = 0;
+diff --git a/arch/powerpc/platforms/pasemi/iommu.c b/arch/powerpc/platforms/pasemi/iommu.c
+index 5803f11..86967bd 100644
+--- a/arch/powerpc/platforms/pasemi/iommu.c
++++ b/arch/powerpc/platforms/pasemi/iommu.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (C) 2005-2007, PA Semi, Inc
++ * Copyright (C) 2005-2008, PA Semi, Inc
+ *
+ * Maintained by: Olof Johansson <olof at lixom.net>
+ *
+@@ -27,7 +27,6 @@
+ #include <asm/abs_addr.h>
+ #include <asm/firmware.h>
+
+-
+ #define IOBMAP_PAGE_SHIFT 12
+ #define IOBMAP_PAGE_SIZE (1 << IOBMAP_PAGE_SHIFT)
+ #define IOBMAP_PAGE_MASK (IOBMAP_PAGE_SIZE - 1)
+@@ -35,13 +34,13 @@
+ #define IOB_BASE 0xe0000000
+ #define IOB_SIZE 0x3000
+ /* Configuration registers */
+-#define IOBCAP_REG 0x10
+-#define IOBCOM_REG 0x40
++#define IOBCAP_REG 0x40
++#define IOBCOM_REG 0x100
+ /* Enable IOB address translation */
+ #define IOBCOM_ATEN 0x00000100
+
+ /* Address decode configuration register */
+-#define IOB_AD_REG 0x53
++#define IOB_AD_REG 0x14c
+ /* IOBCOM_AD_REG fields */
+ #define IOB_AD_VGPRT 0x00000e00
+ #define IOB_AD_VGAEN 0x00000100
+@@ -56,13 +55,13 @@
+ #define IOB_AD_TRNG_2G 0x00000001
+ #define IOB_AD_TRNG_128G 0x00000003
+
+-#define IOB_TABLEBASE_REG 0x55
++#define IOB_TABLEBASE_REG 0x154
+
+ /* Base of the 64 4-byte L1 registers */
+-#define IOB_XLT_L1_REGBASE 0xac0
++#define IOB_XLT_L1_REGBASE 0x2b00
+
+ /* Register to invalidate TLB entries */
+-#define IOB_AT_INVAL_TLB_REG 0xb40
++#define IOB_AT_INVAL_TLB_REG 0x2d00
+
+ /* The top two bits of the level 1 entry contains valid and type flags */
+ #define IOBMAP_L1E_V 0x40000000
+@@ -76,7 +75,7 @@
+ #define IOBMAP_L2E_V 0x80000000
+ #define IOBMAP_L2E_V_CACHED 0xc0000000
+
+-static u32 __iomem *iob;
++static void __iomem *iob;
+ static u32 iob_l1_emptyval;
+ static u32 iob_l2_emptyval;
+ static u32 *iob_l2_base;
+@@ -219,7 +218,7 @@ int __init iob_init(struct device_node *dn)
+ for (i = 0; i < 64; i++) {
+ /* Each L1 covers 32MB, i.e. 8K entries = 32K of ram */
+ regword = IOBMAP_L1E_V | (__pa(iob_l2_base + i*0x2000) >> 12);
+- out_le32(iob+IOB_XLT_L1_REGBASE+i, regword);
++ out_le32(iob+IOB_XLT_L1_REGBASE+i*4, regword);
+ }
+
+ /* set 2GB translation window, based at 0 */
+diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
+index 1c58db9..bcf50d7 100644
+--- a/arch/powerpc/platforms/powermac/pci.c
++++ b/arch/powerpc/platforms/powermac/pci.c
+@@ -1144,28 +1144,6 @@ void __init pmac_pcibios_after_init(void)
+ {
+ struct device_node* nd;
+
+-#ifdef CONFIG_BLK_DEV_IDE
+- struct pci_dev *dev = NULL;
+-
+- /* OF fails to initialize IDE controllers on macs
+- * (and maybe other machines)
+- *
+- * Ideally, this should be moved to the IDE layer, but we need
+- * to check specifically with Andre Hedrick how to do it cleanly
+- * since the common IDE code seem to care about the fact that the
+- * BIOS may have disabled a controller.
+- *
+- * -- BenH
+- */
+- for_each_pci_dev(dev) {
+- if ((dev->class >> 16) != PCI_BASE_CLASS_STORAGE)
+- continue;
+- if (pci_enable_device(dev))
+- printk(KERN_WARNING
+- "pci: Failed to enable %s\n", pci_name(dev));
+- }
+-#endif /* CONFIG_BLK_DEV_IDE */
+-
+ for_each_node_by_name(nd, "firewire") {
+ if (nd->parent && (of_device_is_compatible(nd, "pci106b,18") ||
+ of_device_is_compatible(nd, "pci106b,30") ||
+diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c
+index 8543423..96d5ce5 100644
+--- a/arch/powerpc/platforms/powermac/pfunc_core.c
++++ b/arch/powerpc/platforms/powermac/pfunc_core.c
+@@ -12,7 +12,6 @@
+ #include <linux/module.h>
+ #include <linux/mutex.h>
+
+-#include <asm/semaphore.h>
+ #include <asm/prom.h>
+ #include <asm/pmac_pfunc.h>
+
+diff --git a/arch/powerpc/platforms/powermac/pmac.h b/arch/powerpc/platforms/powermac/pmac.h
+index b3abaaf..3362e78 100644
+--- a/arch/powerpc/platforms/powermac/pmac.h
++++ b/arch/powerpc/platforms/powermac/pmac.h
+@@ -2,7 +2,6 @@
+ #define __PMAC_H__
+
+ #include <linux/pci.h>
+-#include <linux/ide.h>
+ #include <linux/irq.h>
+
+ /*
+@@ -35,10 +34,6 @@ extern void pmac_check_ht_link(void);
+
+ extern void pmac_setup_smp(void);
+
+-extern unsigned long pmac_ide_get_base(int index);
+-extern void pmac_ide_init_hwif_ports(hw_regs_t *hw,
+- unsigned long data_port, unsigned long ctrl_port, int *irq);
+-
+ extern int pmac_nvram_init(void);
+ extern void pmac_pic_init(void);
+
+diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
+index 36ff1b6..bf44c54 100644
+--- a/arch/powerpc/platforms/powermac/setup.c
++++ b/arch/powerpc/platforms/powermac/setup.c
+@@ -53,6 +53,7 @@
+ #include <linux/suspend.h>
+ #include <linux/of_device.h>
+ #include <linux/of_platform.h>
++#include <linux/lmb.h>
+
+ #include <asm/reg.h>
+ #include <asm/sections.h>
+@@ -74,7 +75,6 @@
+ #include <asm/iommu.h>
+ #include <asm/smu.h>
+ #include <asm/pmc.h>
+-#include <asm/lmb.h>
+ #include <asm/udbg.h>
+
+ #include "pmac.h"
+@@ -574,14 +574,6 @@ static int __init pmac_probe(void)
+ ISA_DMA_THRESHOLD = ~0L;
+ DMA_MODE_READ = 1;
+ DMA_MODE_WRITE = 2;
+-
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+-#ifdef CONFIG_BLK_DEV_IDE_PMAC
+- ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports;
+- ppc_ide_md.default_io_base = pmac_ide_get_base;
+-#endif /* CONFIG_BLK_DEV_IDE_PMAC */
+-#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */
+-
+ #endif /* CONFIG_PPC32 */
+
+ #ifdef CONFIG_PMAC_SMU
+diff --git a/arch/powerpc/platforms/ps3/device-init.c b/arch/powerpc/platforms/ps3/device-init.c
+index 9d251d0..3866deb 100644
+--- a/arch/powerpc/platforms/ps3/device-init.c
++++ b/arch/powerpc/platforms/ps3/device-init.c
+@@ -499,41 +499,14 @@ static int __init ps3_register_graphics_devices(void)
+ }
+
+ /**
+- * ps3_register_repository_device - Register a device from the repositiory info.
+- *
++ * ps3_setup_dynamic_device - Setup a dynamic device from the repository
+ */
+
+-static int ps3_register_repository_device(
+- const struct ps3_repository_device *repo)
++static int ps3_setup_dynamic_device(const struct ps3_repository_device *repo)
+ {
+ int result;
+
+ switch (repo->dev_type) {
+- case PS3_DEV_TYPE_SB_GELIC:
+- result = ps3_setup_gelic_device(repo);
+- if (result) {
+- pr_debug("%s:%d ps3_setup_gelic_device failed\n",
+- __func__, __LINE__);
+- }
+- break;
+- case PS3_DEV_TYPE_SB_USB:
+-
+- /* Each USB device has both an EHCI and an OHCI HC */
+-
+- result = ps3_setup_ehci_device(repo);
+-
+- if (result) {
+- pr_debug("%s:%d ps3_setup_ehci_device failed\n",
+- __func__, __LINE__);
+- }
+-
+- result = ps3_setup_ohci_device(repo);
+-
+- if (result) {
+- pr_debug("%s:%d ps3_setup_ohci_device failed\n",
+- __func__, __LINE__);
+- }
+- break;
+ case PS3_DEV_TYPE_STOR_DISK:
+ result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_DISK);
+
+@@ -572,6 +545,48 @@ static int ps3_register_repository_device(
+ return result;
+ }
+
++/**
++ * ps3_setup_static_device - Setup a static device from the repository
++ */
++
++static int __init ps3_setup_static_device(const struct ps3_repository_device *repo)
++{
++ int result;
++
++ switch (repo->dev_type) {
++ case PS3_DEV_TYPE_SB_GELIC:
++ result = ps3_setup_gelic_device(repo);
++ if (result) {
++ pr_debug("%s:%d ps3_setup_gelic_device failed\n",
++ __func__, __LINE__);
++ }
++ break;
++ case PS3_DEV_TYPE_SB_USB:
++
++ /* Each USB device has both an EHCI and an OHCI HC */
++
++ result = ps3_setup_ehci_device(repo);
++
++ if (result) {
++ pr_debug("%s:%d ps3_setup_ehci_device failed\n",
++ __func__, __LINE__);
++ }
++
++ result = ps3_setup_ohci_device(repo);
++
++ if (result) {
++ pr_debug("%s:%d ps3_setup_ohci_device failed\n",
++ __func__, __LINE__);
++ }
++ break;
++
++ default:
++ return ps3_setup_dynamic_device(repo);
++ }
++
++ return result;
++}
++
+ static void ps3_find_and_add_device(u64 bus_id, u64 dev_id)
+ {
+ struct ps3_repository_device repo;
+@@ -601,7 +616,7 @@ found:
+ pr_debug("%s:%u: device %lu:%lu found after %u retries\n",
+ __func__, __LINE__, bus_id, dev_id, retries);
+
+- ps3_register_repository_device(&repo);
++ ps3_setup_dynamic_device(&repo);
+ return;
+ }
+
+@@ -905,8 +920,7 @@ static int __init ps3_register_devices(void)
+
+ ps3_register_graphics_devices();
+
+- ps3_repository_find_devices(PS3_BUS_TYPE_SB,
+- ps3_register_repository_device);
++ ps3_repository_find_devices(PS3_BUS_TYPE_SB, ps3_setup_static_device);
+
+ ps3_register_sound_devices();
+
+diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c
+index 7382f19..1cf901f 100644
+--- a/arch/powerpc/platforms/ps3/htab.c
++++ b/arch/powerpc/platforms/ps3/htab.c
+@@ -19,9 +19,10 @@
+ */
+
+ #include <linux/kernel.h>
++#include <linux/lmb.h>
+
+ #include <asm/machdep.h>
+-#include <asm/lmb.h>
++#include <asm/prom.h>
+ #include <asm/udbg.h>
+ #include <asm/lv1call.h>
+ #include <asm/ps3fb.h>
+diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c
+index 3a6db04..a14e5cd 100644
+--- a/arch/powerpc/platforms/ps3/interrupt.c
++++ b/arch/powerpc/platforms/ps3/interrupt.c
+@@ -709,7 +709,7 @@ static unsigned int ps3_get_irq(void)
+ asm volatile("cntlzd %0,%1" : "=r" (plug) : "r" (x));
+ plug &= 0x3f;
+
+- if (unlikely(plug) == NO_IRQ) {
++ if (unlikely(plug == NO_IRQ)) {
+ pr_debug("%s:%d: no plug found: thread_id %lu\n", __func__,
+ __LINE__, pd->thread_id);
+ dump_bmp(&per_cpu(ps3_private, 0));
+diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c
+index 6890047..5b3fb2b 100644
+--- a/arch/powerpc/platforms/ps3/mm.c
++++ b/arch/powerpc/platforms/ps3/mm.c
+@@ -21,9 +21,10 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/memory_hotplug.h>
++#include <linux/lmb.h>
+
+ #include <asm/firmware.h>
+-#include <asm/lmb.h>
++#include <asm/prom.h>
+ #include <asm/udbg.h>
+ #include <asm/lv1call.h>
+
+diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c
+index b9ea09d..1d20178 100644
+--- a/arch/powerpc/platforms/ps3/os-area.c
++++ b/arch/powerpc/platforms/ps3/os-area.c
+@@ -24,8 +24,10 @@
+ #include <linux/fs.h>
+ #include <linux/syscalls.h>
+ #include <linux/ctype.h>
++#include <linux/lmb.h>
++#include <linux/of.h>
+
+-#include <asm/lmb.h>
++#include <asm/prom.h>
+
+ #include "platform.h"
+
+diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
+index 5c2cbb0..a413abb 100644
+--- a/arch/powerpc/platforms/ps3/setup.c
++++ b/arch/powerpc/platforms/ps3/setup.c
+@@ -95,6 +95,14 @@ static void ps3_power_off(void)
+ ps3_sys_manager_power_off(); /* never returns */
+ }
+
++static void ps3_halt(void)
++{
++ DBG("%s:%d\n", __func__, __LINE__);
++
++ smp_send_stop();
++ ps3_sys_manager_halt(); /* never returns */
++}
++
+ static void ps3_panic(char *str)
+ {
+ DBG("%s:%d %s\n", __func__, __LINE__, str);
+@@ -105,7 +113,8 @@ static void ps3_panic(char *str)
+ printk(" Please press POWER button.\n");
+ printk("\n");
+
+- while(1);
++ while(1)
++ lv1_pause(1);
+ }
+
+ #if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE) || \
+@@ -117,7 +126,7 @@ static void __init prealloc(struct ps3_prealloc *p)
+
+ p->address = __alloc_bootmem(p->size, p->align, __pa(MAX_DMA_ADDRESS));
+ if (!p->address) {
+- printk(KERN_ERR "%s: Cannot allocate %s\n", __FUNCTION__,
++ printk(KERN_ERR "%s: Cannot allocate %s\n", __func__,
+ p->name);
+ return;
+ }
+@@ -266,6 +275,7 @@ define_machine(ps3) {
+ .progress = ps3_progress,
+ .restart = ps3_restart,
+ .power_off = ps3_power_off,
++ .halt = ps3_halt,
+ #if defined(CONFIG_KEXEC)
+ .kexec_cpu_down = ps3_kexec_cpu_down,
+ .machine_kexec = default_machine_kexec,
+diff --git a/arch/powerpc/platforms/ps3/spu.c b/arch/powerpc/platforms/ps3/spu.c
+index 5ad4118..d135cef 100644
+--- a/arch/powerpc/platforms/ps3/spu.c
++++ b/arch/powerpc/platforms/ps3/spu.c
+@@ -27,6 +27,7 @@
+ #include <asm/spu.h>
+ #include <asm/spu_priv1.h>
+ #include <asm/lv1call.h>
++#include <asm/ps3.h>
+
+ #include "../cell/spufs/spufs.h"
+ #include "platform.h"
+@@ -140,6 +141,12 @@ static void _dump_areas(unsigned int spe_id, unsigned long priv2,
+ pr_debug("%s:%d: shadow: %lxh\n", func, line, shadow);
+ }
+
++inline u64 ps3_get_spe_id(void *arg)
++{
++ return spu_pdata(arg)->spe_id;
++}
++EXPORT_SYMBOL_GPL(ps3_get_spe_id);
++
+ static unsigned long get_vas_id(void)
+ {
+ unsigned long id;
+diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
+index 306a9d0..07fe5b6 100644
+--- a/arch/powerpc/platforms/pseries/Kconfig
++++ b/arch/powerpc/platforms/pseries/Kconfig
+@@ -34,3 +34,8 @@ config LPARCFG
+ help
+ Provide system capacity information via human readable
+ <key word>=<value> pairs through a /proc/ppc64/lparcfg interface.
++
++config PPC_PSERIES_DEBUG
++ depends on PPC_PSERIES && PPC_EARLY_DEBUG
++ bool "Enable extra debug logging in platforms/pseries"
++ default y
+diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
+index 992ba67..bd2593e 100644
+--- a/arch/powerpc/platforms/pseries/Makefile
++++ b/arch/powerpc/platforms/pseries/Makefile
+@@ -2,6 +2,10 @@ ifeq ($(CONFIG_PPC64),y)
+ EXTRA_CFLAGS += -mno-minimal-toc
+ endif
+
++ifeq ($(CONFIG_PPC_PSERIES_DEBUG),y)
++EXTRA_CFLAGS += -DDEBUG
++endif
++
+ obj-y := lpar.o hvCall.o nvram.o reconfig.o \
+ setup.o iommu.o ras.o rtasd.o \
+ firmware.o power.o
+@@ -18,3 +22,4 @@ obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o
+ obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
+ obj-$(CONFIG_HVCS) += hvcserver.o
+ obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o
++obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o
+diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
+index 9eb539e..a3fd56b 100644
+--- a/arch/powerpc/platforms/pseries/eeh.c
++++ b/arch/powerpc/platforms/pseries/eeh.c
+@@ -39,7 +39,6 @@
+ #include <asm/ppc-pci.h>
+ #include <asm/rtas.h>
+
+-#undef DEBUG
+
+ /** Overview:
+ * EEH, or "Extended Error Handling" is a PCI bridge technology for
+@@ -945,7 +944,6 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
+ unsigned int rets[3];
+ struct eeh_early_enable_info *info = data;
+ int ret;
+- const char *status = of_get_property(dn, "status", NULL);
+ const u32 *class_code = of_get_property(dn, "class-code", NULL);
+ const u32 *vendor_id = of_get_property(dn, "vendor-id", NULL);
+ const u32 *device_id = of_get_property(dn, "device-id", NULL);
+@@ -959,8 +957,8 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
+ pdn->eeh_freeze_count = 0;
+ pdn->eeh_false_positives = 0;
+
+- if (status && strncmp(status, "ok", 2) != 0)
+- return NULL; /* ignore devices with bad status */
++ if (!of_device_is_available(dn))
++ return NULL;
+
+ /* Ignore bad nodes. */
+ if (!class_code || !vendor_id || !device_id)
+diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c
+index 1e83fcd..ce37040 100644
+--- a/arch/powerpc/platforms/pseries/eeh_cache.c
++++ b/arch/powerpc/platforms/pseries/eeh_cache.c
+@@ -28,7 +28,6 @@
+ #include <asm/pci-bridge.h>
+ #include <asm/ppc-pci.h>
+
+-#undef DEBUG
+
+ /**
+ * The pci address cache subsystem. This subsystem places
+diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c
+index b765b7c..9d3a40f 100644
+--- a/arch/powerpc/platforms/pseries/firmware.c
++++ b/arch/powerpc/platforms/pseries/firmware.c
+@@ -21,17 +21,11 @@
+ * 2 of the License, or (at your option) any later version.
+ */
+
+-#undef DEBUG
+
+ #include <asm/firmware.h>
+ #include <asm/prom.h>
+ #include <asm/udbg.h>
+
+-#ifdef DEBUG
+-#define DBG(fmt...) udbg_printf(fmt)
+-#else
+-#define DBG(fmt...)
+-#endif
+
+ typedef struct {
+ unsigned long val;
+@@ -72,7 +66,7 @@ void __init fw_feature_init(const char *hypertas, unsigned long len)
+ const char *s;
+ int i;
+
+- DBG(" -> fw_feature_init()\n");
++ pr_debug(" -> fw_feature_init()\n");
+
+ for (s = hypertas; s < hypertas + len; s += strlen(s) + 1) {
+ for (i = 0; i < FIRMWARE_MAX_FEATURES; i++) {
+@@ -88,5 +82,5 @@ void __init fw_feature_init(const char *hypertas, unsigned long len)
+ }
+ }
+
+- DBG(" <- fw_feature_init()\n");
++ pr_debug(" <- fw_feature_init()\n");
+ }
+diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
+index a65c763..176f1f3 100644
+--- a/arch/powerpc/platforms/pseries/iommu.c
++++ b/arch/powerpc/platforms/pseries/iommu.c
+@@ -47,7 +47,6 @@
+
+ #include "plpar_wrappers.h"
+
+-#define DBG(fmt...)
+
+ static void tce_build_pSeries(struct iommu_table *tbl, long index,
+ long npages, unsigned long uaddr,
+@@ -322,7 +321,7 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
+
+ dn = pci_bus_to_OF_node(bus);
+
+- DBG("pci_dma_bus_setup_pSeries: setting up bus %s\n", dn->full_name);
++ pr_debug("pci_dma_bus_setup_pSeries: setting up bus %s\n", dn->full_name);
+
+ if (bus->self) {
+ /* This is not a root bus, any setup will be done for the
+@@ -347,7 +346,7 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
+ for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling)
+ children++;
+
+- DBG("Children: %d\n", children);
++ pr_debug("Children: %d\n", children);
+
+ /* Calculate amount of DMA window per slot. Each window must be
+ * a power of two (due to pci_alloc_consistent requirements).
+@@ -361,8 +360,8 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
+
+ while (pci->phb->dma_window_size * children > 0x80000000ul)
+ pci->phb->dma_window_size >>= 1;
+- DBG("No ISA/IDE, window size is 0x%lx\n",
+- pci->phb->dma_window_size);
++ pr_debug("No ISA/IDE, window size is 0x%lx\n",
++ pci->phb->dma_window_size);
+ pci->phb->dma_window_base_cur = 0;
+
+ return;
+@@ -387,8 +386,7 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
+ while (pci->phb->dma_window_size * children > 0x70000000ul)
+ pci->phb->dma_window_size >>= 1;
+
+- DBG("ISA/IDE, window size is 0x%lx\n", pci->phb->dma_window_size);
+-
++ pr_debug("ISA/IDE, window size is 0x%lx\n", pci->phb->dma_window_size);
+ }
+
+
+@@ -401,7 +399,8 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
+
+ dn = pci_bus_to_OF_node(bus);
+
+- DBG("pci_dma_bus_setup_pSeriesLP: setting up bus %s\n", dn->full_name);
++ pr_debug("pci_dma_bus_setup_pSeriesLP: setting up bus %s\n",
++ dn->full_name);
+
+ /* Find nearest ibm,dma-window, walking up the device tree */
+ for (pdn = dn; pdn != NULL; pdn = pdn->parent) {
+@@ -411,14 +410,14 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
+ }
+
+ if (dma_window == NULL) {
+- DBG(" no ibm,dma-window property !\n");
++ pr_debug(" no ibm,dma-window property !\n");
+ return;
+ }
+
+ ppci = PCI_DN(pdn);
+
+- DBG(" parent is %s, iommu_table: 0x%p\n",
+- pdn->full_name, ppci->iommu_table);
++ pr_debug(" parent is %s, iommu_table: 0x%p\n",
++ pdn->full_name, ppci->iommu_table);
+
+ if (!ppci->iommu_table) {
+ tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
+@@ -426,7 +425,7 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
+ iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window,
+ bus->number);
+ ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node);
+- DBG(" created table: %p\n", ppci->iommu_table);
++ pr_debug(" created table: %p\n", ppci->iommu_table);
+ }
+
+ if (pdn != dn)
+@@ -439,7 +438,7 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
+ struct device_node *dn;
+ struct iommu_table *tbl;
+
+- DBG("pci_dma_dev_setup_pSeries: %s\n", pci_name(dev));
++ pr_debug("pci_dma_dev_setup_pSeries: %s\n", pci_name(dev));
+
+ dn = dev->dev.archdata.of_node;
+
+@@ -450,7 +449,7 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
+ if (!dev->bus->self) {
+ struct pci_controller *phb = PCI_DN(dn)->phb;
+
+- DBG(" --> first child, no bridge. Allocating iommu table.\n");
++ pr_debug(" --> first child, no bridge. Allocating iommu table.\n");
+ tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
+ phb->node);
+ iommu_table_setparms(phb, dn, tbl);
+@@ -480,7 +479,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
+ const void *dma_window = NULL;
+ struct pci_dn *pci;
+
+- DBG("pci_dma_dev_setup_pSeriesLP: %s\n", pci_name(dev));
++ pr_debug("pci_dma_dev_setup_pSeriesLP: %s\n", pci_name(dev));
+
+ /* dev setup for LPAR is a little tricky, since the device tree might
+ * contain the dma-window properties per-device and not neccesarily
+@@ -489,7 +488,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
+ * already allocated.
+ */
+ dn = pci_device_to_OF_node(dev);
+- DBG(" node is %s\n", dn->full_name);
++ pr_debug(" node is %s\n", dn->full_name);
+
+ for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table;
+ pdn = pdn->parent) {
+@@ -504,13 +503,13 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
+ pci_name(dev), dn? dn->full_name : "<null>");
+ return;
+ }
+- DBG(" parent is %s\n", pdn->full_name);
++ pr_debug(" parent is %s\n", pdn->full_name);
+
+ /* Check for parent == NULL so we don't try to setup the empty EADS
+ * slots on POWER4 machines.
+ */
+ if (dma_window == NULL || pdn->parent == NULL) {
+- DBG(" no dma window for device, linking to parent\n");
++ pr_debug(" no dma window for device, linking to parent\n");
+ dev->dev.archdata.dma_data = PCI_DN(pdn)->iommu_table;
+ return;
+ }
+@@ -522,9 +521,9 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
+ iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window,
+ pci->phb->bus->number);
+ pci->iommu_table = iommu_init_table(tbl, pci->phb->node);
+- DBG(" created table: %p\n", pci->iommu_table);
++ pr_debug(" created table: %p\n", pci->iommu_table);
+ } else {
+- DBG(" found DMA window, table: %p\n", pci->iommu_table);
++ pr_debug(" found DMA window, table: %p\n", pci->iommu_table);
+ }
+
+ dev->dev.archdata.dma_data = pci->iommu_table;
+diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
+index 9a455d4..2cbaedb 100644
+--- a/arch/powerpc/platforms/pseries/lpar.c
++++ b/arch/powerpc/platforms/pseries/lpar.c
+@@ -19,7 +19,8 @@
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+-#undef DEBUG_LOW
++/* Enables debugging of low-level hash table routines - careful! */
++#undef DEBUG
+
+ #include <linux/kernel.h>
+ #include <linux/dma-mapping.h>
+@@ -40,12 +41,8 @@
+ #include <asm/smp.h>
+
+ #include "plpar_wrappers.h"
++#include "pseries.h"
+
+-#ifdef DEBUG_LOW
+-#define DBG_LOW(fmt...) do { udbg_printf(fmt); } while(0)
+-#else
+-#define DBG_LOW(fmt...) do { } while(0)
+-#endif
+
+ /* in hvCall.S */
+ EXPORT_SYMBOL(plpar_hcall);
+@@ -195,6 +192,8 @@ void __init udbg_init_debug_lpar(void)
+ udbg_putc = udbg_putcLP;
+ udbg_getc = udbg_getcLP;
+ udbg_getc_poll = udbg_getc_pollLP;
++
++ register_early_udbg_console();
+ }
+
+ /* returns 0 if couldn't find or use /chosen/stdout as console */
+@@ -203,7 +202,6 @@ void __init find_udbg_vterm(void)
+ struct device_node *stdout_node;
+ const u32 *termno;
+ const char *name;
+- int add_console;
+
+ /* find the boot console from /chosen/stdout */
+ if (!of_chosen)
+@@ -219,8 +217,6 @@ void __init find_udbg_vterm(void)
+ printk(KERN_WARNING "stdout node missing 'name' property!\n");
+ goto out;
+ }
+- /* The user has requested a console so this is already set up. */
+- add_console = !strstr(cmd_line, "console=");
+
+ /* Check if it's a virtual terminal */
+ if (strncmp(name, "vty", 3) != 0)
+@@ -234,15 +230,13 @@ void __init find_udbg_vterm(void)
+ udbg_putc = udbg_putcLP;
+ udbg_getc = udbg_getcLP;
+ udbg_getc_poll = udbg_getc_pollLP;
+- if (add_console)
+- add_preferred_console("hvc", termno[0] & 0xff, NULL);
++ add_preferred_console("hvc", termno[0] & 0xff, NULL);
+ } else if (of_device_is_compatible(stdout_node, "hvterm-protocol")) {
+ vtermno = termno[0];
+ udbg_putc = udbg_hvsi_putc;
+ udbg_getc = udbg_hvsi_getc;
+ udbg_getc_poll = udbg_hvsi_getc_poll;
+- if (add_console)
+- add_preferred_console("hvsi", termno[0] & 0xff, NULL);
++ add_preferred_console("hvsi", termno[0] & 0xff, NULL);
+ }
+ out:
+ of_node_put(stdout_node);
+@@ -292,15 +286,15 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
+ unsigned long hpte_v, hpte_r;
+
+ if (!(vflags & HPTE_V_BOLTED))
+- DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
+- "rflags=%lx, vflags=%lx, psize=%d)\n",
+- hpte_group, va, pa, rflags, vflags, psize);
++ pr_debug("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
++ "rflags=%lx, vflags=%lx, psize=%d)\n",
++ hpte_group, va, pa, rflags, vflags, psize);
+
+ hpte_v = hpte_encode_v(va, psize, ssize) | vflags | HPTE_V_VALID;
+ hpte_r = hpte_encode_r(pa, psize) | rflags;
+
+ if (!(vflags & HPTE_V_BOLTED))
+- DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
++ pr_debug(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
+
+ /* Now fill in the actual HPTE */
+ /* Set CEC cookie to 0 */
+@@ -317,7 +311,7 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
+ lpar_rc = plpar_pte_enter(flags, hpte_group, hpte_v, hpte_r, &slot);
+ if (unlikely(lpar_rc == H_PTEG_FULL)) {
+ if (!(vflags & HPTE_V_BOLTED))
+- DBG_LOW(" full\n");
++ pr_debug(" full\n");
+ return -1;
+ }
+
+@@ -328,11 +322,11 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
+ */
+ if (unlikely(lpar_rc != H_SUCCESS)) {
+ if (!(vflags & HPTE_V_BOLTED))
+- DBG_LOW(" lpar err %d\n", lpar_rc);
++ pr_debug(" lpar err %lu\n", lpar_rc);
+ return -2;
+ }
+ if (!(vflags & HPTE_V_BOLTED))
+- DBG_LOW(" -> slot: %d\n", slot & 7);
++ pr_debug(" -> slot: %lu\n", slot & 7);
+
+ /* Because of iSeries, we have to pass down the secondary
+ * bucket bit here as well
+@@ -424,17 +418,17 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot,
+
+ want_v = hpte_encode_avpn(va, psize, ssize);
+
+- DBG_LOW(" update: avpnv=%016lx, hash=%016lx, f=%x, psize: %d ... ",
+- want_v, slot, flags, psize);
++ pr_debug(" update: avpnv=%016lx, hash=%016lx, f=%lx, psize: %d ...",
++ want_v, slot, flags, psize);
+
+ lpar_rc = plpar_pte_protect(flags, slot, want_v);
+
+ if (lpar_rc == H_NOT_FOUND) {
+- DBG_LOW("not found !\n");
++ pr_debug("not found !\n");
+ return -1;
+ }
+
+- DBG_LOW("ok\n");
++ pr_debug("ok\n");
+
+ BUG_ON(lpar_rc != H_SUCCESS);
+
+@@ -509,8 +503,8 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
+ unsigned long lpar_rc;
+ unsigned long dummy1, dummy2;
+
+- DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d",
+- slot, va, psize, local);
++ pr_debug(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
++ slot, va, psize, local);
+
+ want_v = hpte_encode_avpn(va, psize, ssize);
+ lpar_rc = plpar_pte_remove(H_AVPN, slot, want_v, &dummy1, &dummy2);
+@@ -520,6 +514,20 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
+ BUG_ON(lpar_rc != H_SUCCESS);
+ }
+
++static void pSeries_lpar_hpte_removebolted(unsigned long ea,
++ int psize, int ssize)
++{
++ unsigned long slot, vsid, va;
++
++ vsid = get_kernel_vsid(ea, ssize);
++ va = hpt_va(ea, vsid, ssize);
++
++ slot = pSeries_lpar_hpte_find(va, psize, ssize);
++ BUG_ON(slot == -1);
++
++ pSeries_lpar_hpte_invalidate(slot, va, psize, ssize, 0);
++}
++
+ /* Flag bits for H_BULK_REMOVE */
+ #define HBR_REQUEST 0x4000000000000000UL
+ #define HBR_RESPONSE 0x8000000000000000UL
+@@ -597,6 +605,7 @@ void __init hpte_init_lpar(void)
+ ppc_md.hpte_updateboltedpp = pSeries_lpar_hpte_updateboltedpp;
+ ppc_md.hpte_insert = pSeries_lpar_hpte_insert;
+ ppc_md.hpte_remove = pSeries_lpar_hpte_remove;
++ ppc_md.hpte_removebolted = pSeries_lpar_hpte_removebolted;
+ ppc_md.flush_hash_range = pSeries_lpar_flush_hash_range;
+ ppc_md.hpte_clear_all = pSeries_lpar_hptab_clear;
+ }
+diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
+index 5a5a19e..21a6d55 100644
+--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
++++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
+@@ -88,11 +88,8 @@ pcibios_fixup_new_pci_devices(struct pci_bus *bus)
+ struct pci_dev *dev;
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+- /*
+- * Skip already-present devices (which are on the
+- * global device list.)
+- */
+- if (list_empty(&dev->global_list)) {
++ /* Skip already-added devices */
++ if (!dev->is_added) {
+ int i;
+
+ /* Fill device archdata and setup iommu table */
+@@ -123,7 +120,7 @@ pcibios_pci_config_bridge(struct pci_dev *dev)
+ /* Add to children of PCI bridge dev->bus */
+ child_bus = pci_add_new_bus(dev->bus, dev, sec_busno);
+ if (!child_bus) {
+- printk (KERN_ERR "%s: could not add second bus\n", __FUNCTION__);
++ printk (KERN_ERR "%s: could not add second bus\n", __func__);
+ return -EIO;
+ }
+ sprintf(child_bus->name, "PCI Bus #%02x", child_bus->number);
+diff --git a/arch/powerpc/platforms/pseries/phyp_dump.c b/arch/powerpc/platforms/pseries/phyp_dump.c
+new file mode 100644
+index 0000000..edbc012
+--- /dev/null
++++ b/arch/powerpc/platforms/pseries/phyp_dump.c
+@@ -0,0 +1,507 @@
++/*
++ * Hypervisor-assisted dump
++ *
++ * Linas Vepstas, Manish Ahuja 2008
++ * Copyright 2008 IBM Corp.
++ *
++ * 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/init.h>
++#include <linux/kobject.h>
++#include <linux/mm.h>
++#include <linux/of.h>
++#include <linux/pfn.h>
++#include <linux/swap.h>
++#include <linux/sysfs.h>
++
++#include <asm/page.h>
++#include <asm/phyp_dump.h>
++#include <asm/machdep.h>
++#include <asm/prom.h>
++#include <asm/rtas.h>
++
++/* Variables, used to communicate data between early boot and late boot */
++static struct phyp_dump phyp_dump_vars;
++struct phyp_dump *phyp_dump_info = &phyp_dump_vars;
++
++static int ibm_configure_kernel_dump;
++/* ------------------------------------------------- */
++/* RTAS interfaces to declare the dump regions */
++
++struct dump_section {
++ u32 dump_flags;
++ u16 source_type;
++ u16 error_flags;
++ u64 source_address;
++ u64 source_length;
++ u64 length_copied;
++ u64 destination_address;
++};
++
++struct phyp_dump_header {
++ u32 version;
++ u16 num_of_sections;
++ u16 status;
++
++ u32 first_offset_section;
++ u32 dump_disk_section;
++ u64 block_num_dd;
++ u64 num_of_blocks_dd;
++ u32 offset_dd;
++ u32 maxtime_to_auto;
++ /* No dump disk path string used */
++
++ struct dump_section cpu_data;
++ struct dump_section hpte_data;
++ struct dump_section kernel_data;
++};
++
++/* The dump header *must be* in low memory, so .bss it */
++static struct phyp_dump_header phdr;
++
++#define NUM_DUMP_SECTIONS 3
++#define DUMP_HEADER_VERSION 0x1
++#define DUMP_REQUEST_FLAG 0x1
++#define DUMP_SOURCE_CPU 0x0001
++#define DUMP_SOURCE_HPTE 0x0002
++#define DUMP_SOURCE_RMO 0x0011
++#define DUMP_ERROR_FLAG 0x2000
++#define DUMP_TRIGGERED 0x4000
++#define DUMP_PERFORMED 0x8000
++
++
++/**
++ * init_dump_header() - initialize the header declaring a dump
++ * Returns: length of dump save area.
++ *
++ * When the hypervisor saves crashed state, it needs to put
++ * it somewhere. The dump header tells the hypervisor where
++ * the data can be saved.
++ */
++static unsigned long init_dump_header(struct phyp_dump_header *ph)
++{
++ unsigned long addr_offset = 0;
++
++ /* Set up the dump header */
++ ph->version = DUMP_HEADER_VERSION;
++ ph->num_of_sections = NUM_DUMP_SECTIONS;
++ ph->status = 0;
++
++ ph->first_offset_section =
++ (u32)offsetof(struct phyp_dump_header, cpu_data);
++ ph->dump_disk_section = 0;
++ ph->block_num_dd = 0;
++ ph->num_of_blocks_dd = 0;
++ ph->offset_dd = 0;
++
++ ph->maxtime_to_auto = 0; /* disabled */
++
++ /* The first two sections are mandatory */
++ ph->cpu_data.dump_flags = DUMP_REQUEST_FLAG;
++ ph->cpu_data.source_type = DUMP_SOURCE_CPU;
++ ph->cpu_data.source_address = 0;
++ ph->cpu_data.source_length = phyp_dump_info->cpu_state_size;
++ ph->cpu_data.destination_address = addr_offset;
++ addr_offset += phyp_dump_info->cpu_state_size;
++
++ ph->hpte_data.dump_flags = DUMP_REQUEST_FLAG;
++ ph->hpte_data.source_type = DUMP_SOURCE_HPTE;
++ ph->hpte_data.source_address = 0;
++ ph->hpte_data.source_length = phyp_dump_info->hpte_region_size;
++ ph->hpte_data.destination_address = addr_offset;
++ addr_offset += phyp_dump_info->hpte_region_size;
++
++ /* This section describes the low kernel region */
++ ph->kernel_data.dump_flags = DUMP_REQUEST_FLAG;
++ ph->kernel_data.source_type = DUMP_SOURCE_RMO;
++ ph->kernel_data.source_address = PHYP_DUMP_RMR_START;
++ ph->kernel_data.source_length = PHYP_DUMP_RMR_END;
++ ph->kernel_data.destination_address = addr_offset;
++ addr_offset += ph->kernel_data.source_length;
++
++ return addr_offset;
++}
++
++static void print_dump_header(const struct phyp_dump_header *ph)
++{
++#ifdef DEBUG
++ printk(KERN_INFO "dump header:\n");
++ /* setup some ph->sections required */
++ printk(KERN_INFO "version = %d\n", ph->version);
++ printk(KERN_INFO "Sections = %d\n", ph->num_of_sections);
++ printk(KERN_INFO "Status = 0x%x\n", ph->status);
++
++ /* No ph->disk, so all should be set to 0 */
++ printk(KERN_INFO "Offset to first section 0x%x\n",
++ ph->first_offset_section);
++ printk(KERN_INFO "dump disk sections should be zero\n");
++ printk(KERN_INFO "dump disk section = %d\n", ph->dump_disk_section);
++ printk(KERN_INFO "block num = %ld\n", ph->block_num_dd);
++ printk(KERN_INFO "number of blocks = %ld\n", ph->num_of_blocks_dd);
++ printk(KERN_INFO "dump disk offset = %d\n", ph->offset_dd);
++ printk(KERN_INFO "Max auto time= %d\n", ph->maxtime_to_auto);
++
++ /*set cpu state and hpte states as well scratch pad area */
++ printk(KERN_INFO " CPU AREA \n");
++ printk(KERN_INFO "cpu dump_flags =%d\n", ph->cpu_data.dump_flags);
++ printk(KERN_INFO "cpu source_type =%d\n", ph->cpu_data.source_type);
++ printk(KERN_INFO "cpu error_flags =%d\n", ph->cpu_data.error_flags);
++ printk(KERN_INFO "cpu source_address =%lx\n",
++ ph->cpu_data.source_address);
++ printk(KERN_INFO "cpu source_length =%lx\n",
++ ph->cpu_data.source_length);
++ printk(KERN_INFO "cpu length_copied =%lx\n",
++ ph->cpu_data.length_copied);
++
++ printk(KERN_INFO " HPTE AREA \n");
++ printk(KERN_INFO "HPTE dump_flags =%d\n", ph->hpte_data.dump_flags);
++ printk(KERN_INFO "HPTE source_type =%d\n", ph->hpte_data.source_type);
++ printk(KERN_INFO "HPTE error_flags =%d\n", ph->hpte_data.error_flags);
++ printk(KERN_INFO "HPTE source_address =%lx\n",
++ ph->hpte_data.source_address);
++ printk(KERN_INFO "HPTE source_length =%lx\n",
++ ph->hpte_data.source_length);
++ printk(KERN_INFO "HPTE length_copied =%lx\n",
++ ph->hpte_data.length_copied);
++
++ printk(KERN_INFO " SRSD AREA \n");
++ printk(KERN_INFO "SRSD dump_flags =%d\n", ph->kernel_data.dump_flags);
++ printk(KERN_INFO "SRSD source_type =%d\n", ph->kernel_data.source_type);
++ printk(KERN_INFO "SRSD error_flags =%d\n", ph->kernel_data.error_flags);
++ printk(KERN_INFO "SRSD source_address =%lx\n",
++ ph->kernel_data.source_address);
++ printk(KERN_INFO "SRSD source_length =%lx\n",
++ ph->kernel_data.source_length);
++ printk(KERN_INFO "SRSD length_copied =%lx\n",
++ ph->kernel_data.length_copied);
++#endif
++}
++
++static ssize_t show_phyp_dump_active(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++
++ /* create filesystem entry so kdump is phyp-dump aware */
++ return sprintf(buf, "%lx\n", phyp_dump_info->phyp_dump_at_boot);
++}
++
++static struct kobj_attribute pdl = __ATTR(phyp_dump_active, 0600,
++ show_phyp_dump_active,
++ NULL);
++
++static void register_dump_area(struct phyp_dump_header *ph, unsigned long addr)
++{
++ int rc;
++
++ /* Add addr value if not initialized before */
++ if (ph->cpu_data.destination_address == 0) {
++ ph->cpu_data.destination_address += addr;
++ ph->hpte_data.destination_address += addr;
++ ph->kernel_data.destination_address += addr;
++ }
++
++ /* ToDo Invalidate kdump and free memory range. */
++
++ do {
++ rc = rtas_call(ibm_configure_kernel_dump, 3, 1, NULL,
++ 1, ph, sizeof(struct phyp_dump_header));
++ } while (rtas_busy_delay(rc));
++
++ if (rc) {
++ printk(KERN_ERR "phyp-dump: unexpected error (%d) on "
++ "register\n", rc);
++ print_dump_header(ph);
++ return;
++ }
++
++ rc = sysfs_create_file(kernel_kobj, &pdl.attr);
++ if (rc)
++ printk(KERN_ERR "phyp-dump: unable to create sysfs"
++ " file (%d)\n", rc);
++}
++
++static
++void invalidate_last_dump(struct phyp_dump_header *ph, unsigned long addr)
++{
++ int rc;
++
++ /* Add addr value if not initialized before */
++ if (ph->cpu_data.destination_address == 0) {
++ ph->cpu_data.destination_address += addr;
++ ph->hpte_data.destination_address += addr;
++ ph->kernel_data.destination_address += addr;
++ }
++
++ do {
++ rc = rtas_call(ibm_configure_kernel_dump, 3, 1, NULL,
++ 2, ph, sizeof(struct phyp_dump_header));
++ } while (rtas_busy_delay(rc));
++
++ if (rc) {
++ printk(KERN_ERR "phyp-dump: unexpected error (%d) "
++ "on invalidate\n", rc);
++ print_dump_header(ph);
++ }
++}
++
++/* ------------------------------------------------- */
++/**
++ * release_memory_range -- release memory previously lmb_reserved
++ * @start_pfn: starting physical frame number
++ * @nr_pages: number of pages to free.
++ *
++ * This routine will release memory that had been previously
++ * lmb_reserved in early boot. The released memory becomes
++ * available for genreal use.
++ */
++static void release_memory_range(unsigned long start_pfn,
++ unsigned long nr_pages)
++{
++ struct page *rpage;
++ unsigned long end_pfn;
++ long i;
++
++ end_pfn = start_pfn + nr_pages;
++
++ for (i = start_pfn; i <= end_pfn; i++) {
++ rpage = pfn_to_page(i);
++ if (PageReserved(rpage)) {
++ ClearPageReserved(rpage);
++ init_page_count(rpage);
++ __free_page(rpage);
++ totalram_pages++;
++ }
++ }
++}
++
++/**
++ * track_freed_range -- Counts the range being freed.
++ * Once the counter goes to zero, it re-registers dump for
++ * future use.
++ */
++static void
++track_freed_range(unsigned long addr, unsigned long length)
++{
++ static unsigned long scratch_area_size, reserved_area_size;
++
++ if (addr < phyp_dump_info->init_reserve_start)
++ return;
++
++ if ((addr >= phyp_dump_info->init_reserve_start) &&
++ (addr <= phyp_dump_info->init_reserve_start +
++ phyp_dump_info->init_reserve_size))
++ reserved_area_size += length;
++
++ if ((addr >= phyp_dump_info->reserved_scratch_addr) &&
++ (addr <= phyp_dump_info->reserved_scratch_addr +
++ phyp_dump_info->reserved_scratch_size))
++ scratch_area_size += length;
++
++ if ((reserved_area_size == phyp_dump_info->init_reserve_size) &&
++ (scratch_area_size == phyp_dump_info->reserved_scratch_size)) {
++
++ invalidate_last_dump(&phdr,
++ phyp_dump_info->reserved_scratch_addr);
++ register_dump_area(&phdr,
++ phyp_dump_info->reserved_scratch_addr);
++ }
++}
++
++/* ------------------------------------------------- */
++/**
++ * sysfs_release_region -- sysfs interface to release memory range.
++ *
++ * Usage:
++ * "echo <start addr> <length> > /sys/kernel/release_region"
++ *
++ * Example:
++ * "echo 0x40000000 0x10000000 > /sys/kernel/release_region"
++ *
++ * will release 256MB starting at 1GB.
++ */
++static ssize_t store_release_region(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ const char *buf, size_t count)
++{
++ unsigned long start_addr, length, end_addr;
++ unsigned long start_pfn, nr_pages;
++ ssize_t ret;
++
++ ret = sscanf(buf, "%lx %lx", &start_addr, &length);
++ if (ret != 2)
++ return -EINVAL;
++
++ track_freed_range(start_addr, length);
++
++ /* Range-check - don't free any reserved memory that
++ * wasn't reserved for phyp-dump */
++ if (start_addr < phyp_dump_info->init_reserve_start)
++ start_addr = phyp_dump_info->init_reserve_start;
++
++ end_addr = phyp_dump_info->init_reserve_start +
++ phyp_dump_info->init_reserve_size;
++ if (start_addr+length > end_addr)
++ length = end_addr - start_addr;
++
++ /* Release the region of memory assed in by user */
++ start_pfn = PFN_DOWN(start_addr);
++ nr_pages = PFN_DOWN(length);
++ release_memory_range(start_pfn, nr_pages);
++
++ return count;
++}
++
++static ssize_t show_release_region(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ u64 second_addr_range;
++
++ /* total reserved size - start of scratch area */
++ second_addr_range = phyp_dump_info->init_reserve_size -
++ phyp_dump_info->reserved_scratch_size;
++ return sprintf(buf, "CPU:0x%lx-0x%lx: HPTE:0x%lx-0x%lx:"
++ " DUMP:0x%lx-0x%lx, 0x%lx-0x%lx:\n",
++ phdr.cpu_data.destination_address,
++ phdr.cpu_data.length_copied,
++ phdr.hpte_data.destination_address,
++ phdr.hpte_data.length_copied,
++ phdr.kernel_data.destination_address,
++ phdr.kernel_data.length_copied,
++ phyp_dump_info->init_reserve_start,
++ second_addr_range);
++}
++
++static struct kobj_attribute rr = __ATTR(release_region, 0600,
++ show_release_region,
++ store_release_region);
++
++static int __init phyp_dump_setup(void)
++{
++ struct device_node *rtas;
++ const struct phyp_dump_header *dump_header = NULL;
++ unsigned long dump_area_start;
++ unsigned long dump_area_length;
++ int header_len = 0;
++ int rc;
++
++ /* If no memory was reserved in early boot, there is nothing to do */
++ if (phyp_dump_info->init_reserve_size == 0)
++ return 0;
++
++ /* Return if phyp dump not supported */
++ if (!phyp_dump_info->phyp_dump_configured)
++ return -ENOSYS;
++
++ /* Is there dump data waiting for us? If there isn't,
++ * then register a new dump area, and release all of
++ * the rest of the reserved ram.
++ *
++ * The /rtas/ibm,kernel-dump rtas node is present only
++ * if there is dump data waiting for us.
++ */
++ rtas = of_find_node_by_path("/rtas");
++ if (rtas) {
++ dump_header = of_get_property(rtas, "ibm,kernel-dump",
++ &header_len);
++ of_node_put(rtas);
++ }
++
++ print_dump_header(dump_header);
++ dump_area_length = init_dump_header(&phdr);
++ /* align down */
++ dump_area_start = phyp_dump_info->init_reserve_start & PAGE_MASK;
++
++ if (dump_header == NULL) {
++ register_dump_area(&phdr, dump_area_start);
++ return 0;
++ }
++
++ /* re-register the dump area, if old dump was invalid */
++ if ((dump_header) && (dump_header->status & DUMP_ERROR_FLAG)) {
++ invalidate_last_dump(&phdr, dump_area_start);
++ register_dump_area(&phdr, dump_area_start);
++ return 0;
++ }
++
++ if (dump_header) {
++ phyp_dump_info->reserved_scratch_addr =
++ dump_header->cpu_data.destination_address;
++ phyp_dump_info->reserved_scratch_size =
++ dump_header->cpu_data.source_length +
++ dump_header->hpte_data.source_length +
++ dump_header->kernel_data.source_length;
++ }
++
++ /* Should we create a dump_subsys, analogous to s390/ipl.c ? */
++ rc = sysfs_create_file(kernel_kobj, &rr.attr);
++ if (rc)
++ printk(KERN_ERR "phyp-dump: unable to create sysfs file (%d)\n",
++ rc);
++
++ /* ToDo: re-register the dump area, for next time. */
++ return 0;
++}
++machine_subsys_initcall(pseries, phyp_dump_setup);
++
++int __init early_init_dt_scan_phyp_dump(unsigned long node,
++ const char *uname, int depth, void *data)
++{
++ const unsigned int *sizes;
++
++ phyp_dump_info->phyp_dump_configured = 0;
++ phyp_dump_info->phyp_dump_is_active = 0;
++
++ if (depth != 1 || strcmp(uname, "rtas") != 0)
++ return 0;
++
++ if (of_get_flat_dt_prop(node, "ibm,configure-kernel-dump", NULL))
++ phyp_dump_info->phyp_dump_configured++;
++
++ if (of_get_flat_dt_prop(node, "ibm,dump-kernel", NULL))
++ phyp_dump_info->phyp_dump_is_active++;
++
++ sizes = of_get_flat_dt_prop(node, "ibm,configure-kernel-dump-sizes",
++ NULL);
++ if (!sizes)
++ return 0;
++
++ if (sizes[0] == 1)
++ phyp_dump_info->cpu_state_size = *((unsigned long *)&sizes[1]);
++
++ if (sizes[3] == 2)
++ phyp_dump_info->hpte_region_size =
++ *((unsigned long *)&sizes[4]);
++ return 1;
++}
++
++/* Look for phyp_dump= cmdline option */
++static int __init early_phyp_dump_enabled(char *p)
++{
++ phyp_dump_info->phyp_dump_at_boot = 1;
++
++ if (!p)
++ return 0;
++
++ if (strncmp(p, "1", 1) == 0)
++ phyp_dump_info->phyp_dump_at_boot = 1;
++ else if (strncmp(p, "0", 1) == 0)
++ phyp_dump_info->phyp_dump_at_boot = 0;
++
++ return 0;
++}
++early_param("phyp_dump", early_phyp_dump_enabled);
++
++/* Look for phyp_dump_reserve_size= cmdline option */
++static int __init early_phyp_dump_reserve_size(char *p)
++{
++ if (p)
++ phyp_dump_info->reserve_bootvar = memparse(p, &p);
++
++ return 0;
++}
++early_param("phyp_dump_reserve_size", early_phyp_dump_reserve_size);
+diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h
+index 61136d0..9e17c0d 100644
+--- a/arch/powerpc/platforms/pseries/pseries.h
++++ b/arch/powerpc/platforms/pseries/pseries.h
+@@ -38,4 +38,6 @@ extern void pSeries_final_fixup(void);
+ /* Poweron flag used for enabling auto ups restart */
+ extern unsigned long rtas_poweron_auto;
+
++extern void find_udbg_vterm(void);
++
+ #endif /* _PSERIES_PSERIES_H */
+diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
+index a1ab25c..2b548af 100644
+--- a/arch/powerpc/platforms/pseries/ras.c
++++ b/arch/powerpc/platforms/pseries/ras.c
+@@ -67,8 +67,6 @@ static int ras_check_exception_token;
+ static irqreturn_t ras_epow_interrupt(int irq, void *dev_id);
+ static irqreturn_t ras_error_interrupt(int irq, void *dev_id);
+
+-/* #define DEBUG */
+-
+
+ static void request_ras_irqs(struct device_node *np,
+ irq_handler_t handler,
+@@ -237,7 +235,7 @@ static irqreturn_t ras_error_interrupt(int irq, void *dev_id)
+ printk(KERN_EMERG "Error: Fatal hardware error <0x%lx 0x%x>\n",
+ *((unsigned long *)&ras_log_buf), status);
+
+-#ifndef DEBUG
++#ifndef DEBUG_RTAS_POWER_OFF
+ /* Don't actually power off when debugging so we can test
+ * without actually failing while injecting errors.
+ * Error data will not be logged to syslog.
+diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
+index 2800fce..ac75c10 100644
+--- a/arch/powerpc/platforms/pseries/reconfig.c
++++ b/arch/powerpc/platforms/pseries/reconfig.c
+@@ -222,14 +222,14 @@ static char * parse_next_property(char *buf, char *end, char **name, int *length
+ tmp = strchr(buf, ' ');
+ if (!tmp) {
+ printk(KERN_ERR "property parse failed in %s at line %d\n",
+- __FUNCTION__, __LINE__);
++ __func__, __LINE__);
+ return NULL;
+ }
+ *tmp = '\0';
+
+ if (++tmp >= end) {
+ printk(KERN_ERR "property parse failed in %s at line %d\n",
+- __FUNCTION__, __LINE__);
++ __func__, __LINE__);
+ return NULL;
+ }
+
+@@ -238,12 +238,12 @@ static char * parse_next_property(char *buf, char *end, char **name, int *length
+ *length = simple_strtoul(tmp, &tmp, 10);
+ if (*length == -1) {
+ printk(KERN_ERR "property parse failed in %s at line %d\n",
+- __FUNCTION__, __LINE__);
++ __func__, __LINE__);
+ return NULL;
+ }
+ if (*tmp != ' ' || ++tmp >= end) {
+ printk(KERN_ERR "property parse failed in %s at line %d\n",
+- __FUNCTION__, __LINE__);
++ __func__, __LINE__);
+ return NULL;
+ }
+
+@@ -252,12 +252,12 @@ static char * parse_next_property(char *buf, char *end, char **name, int *length
+ tmp += *length;
+ if (tmp > end) {
+ printk(KERN_ERR "property parse failed in %s at line %d\n",
+- __FUNCTION__, __LINE__);
++ __func__, __LINE__);
+ return NULL;
+ }
+ else if (tmp < end && *tmp != ' ' && *tmp != '\0') {
+ printk(KERN_ERR "property parse failed in %s at line %d\n",
+- __FUNCTION__, __LINE__);
++ __func__, __LINE__);
+ return NULL;
+ }
+ tmp++;
+diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c
+index e3078ce..befadd4 100644
+--- a/arch/powerpc/platforms/pseries/rtasd.c
++++ b/arch/powerpc/platforms/pseries/rtasd.c
+@@ -29,11 +29,6 @@
+ #include <asm/atomic.h>
+ #include <asm/machdep.h>
+
+-#if 0
+-#define DEBUG(A...) printk(KERN_ERR A)
+-#else
+-#define DEBUG(A...)
+-#endif
+
+ static DEFINE_SPINLOCK(rtasd_log_lock);
+
+@@ -198,7 +193,7 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal)
+ unsigned long s;
+ int len = 0;
+
+- DEBUG("logging event\n");
++ pr_debug("rtasd: logging event\n");
+ if (buf == NULL)
+ return;
+
+@@ -409,7 +404,8 @@ static int rtasd(void *unused)
+ daemonize("rtasd");
+
+ printk(KERN_DEBUG "RTAS daemon started\n");
+- DEBUG("will sleep for %d milliseconds\n", (30000/rtas_event_scan_rate));
++ pr_debug("rtasd: will sleep for %d milliseconds\n",
++ (30000 / rtas_event_scan_rate));
+
+ /* See if we have any error stored in NVRAM */
+ memset(logdata, 0, rtas_error_log_max);
+@@ -428,9 +424,9 @@ static int rtasd(void *unused)
+ do_event_scan_all_cpus(1000);
+
+ if (surveillance_timeout != -1) {
+- DEBUG("enabling surveillance\n");
++ pr_debug("rtasd: enabling surveillance\n");
+ enable_surveillance(surveillance_timeout);
+- DEBUG("surveillance enabled\n");
++ pr_debug("rtasd: surveillance enabled\n");
+ }
+
+ /* Delay should be at least one second since some
+diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c
+index 8e1ef16..bec3803 100644
+--- a/arch/powerpc/platforms/pseries/scanlog.c
++++ b/arch/powerpc/platforms/pseries/scanlog.c
+@@ -38,9 +38,7 @@
+ #define SCANLOG_HWERROR -1
+ #define SCANLOG_CONTINUE 1
+
+-#define DEBUG(A...) do { if (scanlog_debug) printk(KERN_ERR "scanlog: " A); } while (0)
+
+-static int scanlog_debug;
+ static unsigned int ibm_scan_log_dump; /* RTAS token */
+ static struct proc_dir_entry *proc_ppc64_scan_log_dump; /* The proc file */
+
+@@ -86,14 +84,14 @@ static ssize_t scanlog_read(struct file *file, char __user *buf,
+ memcpy(data, rtas_data_buf, RTAS_DATA_BUF_SIZE);
+ spin_unlock(&rtas_data_buf_lock);
+
+- DEBUG("status=%d, data[0]=%x, data[1]=%x, data[2]=%x\n",
+- status, data[0], data[1], data[2]);
++ pr_debug("scanlog: status=%d, data[0]=%x, data[1]=%x, " \
++ "data[2]=%x\n", status, data[0], data[1], data[2]);
+ switch (status) {
+ case SCANLOG_COMPLETE:
+- DEBUG("hit eof\n");
++ pr_debug("scanlog: hit eof\n");
+ return 0;
+ case SCANLOG_HWERROR:
+- DEBUG("hardware error reading scan log data\n");
++ pr_debug("scanlog: hardware error reading data\n");
+ return -EIO;
+ case SCANLOG_CONTINUE:
+ /* We may or may not have data yet */
+@@ -110,7 +108,8 @@ static ssize_t scanlog_read(struct file *file, char __user *buf,
+ /* Assume extended busy */
+ wait_time = rtas_busy_delay_time(status);
+ if (!wait_time) {
+- printk(KERN_ERR "scanlog: unknown error from rtas: %d\n", status);
++ printk(KERN_ERR "scanlog: unknown error " \
++ "from rtas: %d\n", status);
+ return -EIO;
+ }
+ }
+@@ -134,15 +133,9 @@ static ssize_t scanlog_write(struct file * file, const char __user * buf,
+
+ if (buf) {
+ if (strncmp(stkbuf, "reset", 5) == 0) {
+- DEBUG("reset scanlog\n");
++ pr_debug("scanlog: reset scanlog\n");
+ status = rtas_call(ibm_scan_log_dump, 2, 1, NULL, 0, 0);
+- DEBUG("rtas returns %d\n", status);
+- } else if (strncmp(stkbuf, "debugon", 7) == 0) {
+- printk(KERN_ERR "scanlog: debug on\n");
+- scanlog_debug = 1;
+- } else if (strncmp(stkbuf, "debugoff", 8) == 0) {
+- printk(KERN_ERR "scanlog: debug off\n");
+- scanlog_debug = 0;
++ pr_debug("scanlog: rtas returns %d\n", status);
+ }
+ }
+ return count;
+@@ -195,31 +188,30 @@ const struct file_operations scanlog_fops = {
+ static int __init scanlog_init(void)
+ {
+ struct proc_dir_entry *ent;
++ void *data;
++ int err = -ENOMEM;
+
+ ibm_scan_log_dump = rtas_token("ibm,scan-log-dump");
+- if (ibm_scan_log_dump == RTAS_UNKNOWN_SERVICE) {
+- printk(KERN_ERR "scan-log-dump not implemented on this system\n");
+- return -EIO;
+- }
++ if (ibm_scan_log_dump == RTAS_UNKNOWN_SERVICE)
++ return -ENODEV;
+
+- ent = create_proc_entry("ppc64/rtas/scan-log-dump", S_IRUSR, NULL);
+- if (ent) {
+- ent->proc_fops = &scanlog_fops;
+- /* Ideally we could allocate a buffer < 4G */
+- ent->data = kmalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
+- if (!ent->data) {
+- printk(KERN_ERR "Failed to allocate a buffer\n");
+- remove_proc_entry("scan-log-dump", ent->parent);
+- return -ENOMEM;
+- }
+- ((unsigned int *)ent->data)[0] = 0;
+- } else {
+- printk(KERN_ERR "Failed to create ppc64/scan-log-dump proc entry\n");
+- return -EIO;
+- }
++ /* Ideally we could allocate a buffer < 4G */
++ data = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
++ if (!data)
++ goto err;
++
++ ent = proc_create("ppc64/rtas/scan-log-dump", S_IRUSR, NULL,
++ &scanlog_fops);
++ if (!ent)
++ goto err;
++
++ ent->data = data;
+ proc_ppc64_scan_log_dump = ent;
+
+ return 0;
++err:
++ kfree(data);
++ return err;
+ }
+
+ static void __exit scanlog_cleanup(void)
+diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
+index fdb9b1c..f5d29f5 100644
+--- a/arch/powerpc/platforms/pseries/setup.c
++++ b/arch/powerpc/platforms/pseries/setup.c
+@@ -16,8 +16,6 @@
+ * bootup setup stuff..
+ */
+
+-#undef DEBUG
+-
+ #include <linux/cpu.h>
+ #include <linux/errno.h>
+ #include <linux/sched.h>
+@@ -70,14 +68,6 @@
+ #include "plpar_wrappers.h"
+ #include "pseries.h"
+
+-#ifdef DEBUG
+-#define DBG(fmt...) udbg_printf(fmt)
+-#else
+-#define DBG(fmt...)
+-#endif
+-
+-/* move those away to a .h */
+-extern void find_udbg_vterm(void);
+
+ int fwnmi_active; /* TRUE if an FWNMI handler is present */
+
+@@ -127,14 +117,60 @@ void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc)
+ desc->chip->eoi(irq);
+ }
+
+-static void __init pseries_mpic_init_IRQ(void)
++static void __init pseries_setup_i8259_cascade(void)
+ {
+- struct device_node *np, *old, *cascade = NULL;
+- const unsigned int *addrp;
++ struct device_node *np, *old, *found = NULL;
++ unsigned int cascade;
++ const u32 *addrp;
+ unsigned long intack = 0;
++ int naddr;
++
++ for_each_node_by_type(np, "interrupt-controller") {
++ if (of_device_is_compatible(np, "chrp,iic")) {
++ found = np;
++ break;
++ }
++ }
++
++ if (found == NULL) {
++ printk(KERN_DEBUG "pic: no ISA interrupt controller\n");
++ return;
++ }
++
++ cascade = irq_of_parse_and_map(found, 0);
++ if (cascade == NO_IRQ) {
++ printk(KERN_ERR "pic: failed to map cascade interrupt");
++ return;
++ }
++ pr_debug("pic: cascade mapped to irq %d\n", cascade);
++
++ for (old = of_node_get(found); old != NULL ; old = np) {
++ np = of_get_parent(old);
++ of_node_put(old);
++ if (np == NULL)
++ break;
++ if (strcmp(np->name, "pci") != 0)
++ continue;
++ addrp = of_get_property(np, "8259-interrupt-acknowledge", NULL);
++ if (addrp == NULL)
++ continue;
++ naddr = of_n_addr_cells(np);
++ intack = addrp[naddr-1];
++ if (naddr > 1)
++ intack |= ((unsigned long)addrp[naddr-2]) << 32;
++ }
++ if (intack)
++ printk(KERN_DEBUG "pic: PCI 8259 intack at 0x%016lx\n", intack);
++ i8259_init(found, intack);
++ of_node_put(found);
++ set_irq_chained_handler(cascade, pseries_8259_cascade);
++}
++
++static void __init pseries_mpic_init_IRQ(void)
++{
++ struct device_node *np;
+ const unsigned int *opprop;
+ unsigned long openpic_addr = 0;
+- unsigned int cascade_irq;
+ int naddr, n, i, opplen;
+ struct mpic *mpic;
+
+@@ -167,43 +203,13 @@ static void __init pseries_mpic_init_IRQ(void)
+ mpic_init(mpic);
+
+ /* Look for cascade */
+- for_each_node_by_type(np, "interrupt-controller")
+- if (of_device_is_compatible(np, "chrp,iic")) {
+- cascade = np;
+- break;
+- }
+- if (cascade == NULL)
+- return;
+-
+- cascade_irq = irq_of_parse_and_map(cascade, 0);
+- if (cascade_irq == NO_IRQ) {
+- printk(KERN_ERR "mpic: failed to map cascade interrupt");
+- return;
+- }
++ pseries_setup_i8259_cascade();
++}
+
+- /* Check ACK type */
+- for (old = of_node_get(cascade); old != NULL ; old = np) {
+- np = of_get_parent(old);
+- of_node_put(old);
+- if (np == NULL)
+- break;
+- if (strcmp(np->name, "pci") != 0)
+- continue;
+- addrp = of_get_property(np, "8259-interrupt-acknowledge",
+- NULL);
+- if (addrp == NULL)
+- continue;
+- naddr = of_n_addr_cells(np);
+- intack = addrp[naddr-1];
+- if (naddr > 1)
+- intack |= ((unsigned long)addrp[naddr-2]) << 32;
+- }
+- if (intack)
+- printk(KERN_DEBUG "mpic: PCI 8259 intack at 0x%016lx\n",
+- intack);
+- i8259_init(cascade, intack);
+- of_node_put(cascade);
+- set_irq_chained_handler(cascade_irq, pseries_8259_cascade);
++static void __init pseries_xics_init_IRQ(void)
++{
++ xics_init_IRQ();
++ pseries_setup_i8259_cascade();
+ }
+
+ static void pseries_lpar_enable_pmcs(void)
+@@ -235,7 +241,7 @@ static void __init pseries_discover_pic(void)
+ smp_init_pseries_mpic();
+ return;
+ } else if (strstr(typep, "ppc-xicp")) {
+- ppc_md.init_IRQ = xics_init_IRQ;
++ ppc_md.init_IRQ = pseries_xics_init_IRQ;
+ setup_kexec_cpu_down_xics();
+ smp_init_pseries_xics();
+ return;
+@@ -313,7 +319,7 @@ static int pseries_set_xdabr(unsigned long dabr)
+ */
+ static void __init pSeries_init_early(void)
+ {
+- DBG(" -> pSeries_init_early()\n");
++ pr_debug(" -> pSeries_init_early()\n");
+
+ if (firmware_has_feature(FW_FEATURE_LPAR))
+ find_udbg_vterm();
+@@ -325,7 +331,7 @@ static void __init pSeries_init_early(void)
+
+ iommu_init_early_pSeries();
+
+- DBG(" <- pSeries_init_early()\n");
++ pr_debug(" <- pSeries_init_early()\n");
+ }
+
+ /*
+@@ -370,7 +376,7 @@ static int __init pSeries_probe(void)
+ of_flat_dt_is_compatible(root, "IBM,CBEA"))
+ return 0;
+
+- DBG("pSeries detected, looking for LPAR capability...\n");
++ pr_debug("pSeries detected, looking for LPAR capability...\n");
+
+ /* Now try to figure out if we are running on LPAR */
+ of_scan_flat_dt(pSeries_probe_hypertas, NULL);
+@@ -380,8 +386,8 @@ static int __init pSeries_probe(void)
+ else
+ hpte_init_native();
+
+- DBG("Machine is%s LPAR !\n",
+- (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not");
++ pr_debug("Machine is%s LPAR !\n",
++ (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not");
+
+ return 1;
+ }
+@@ -393,6 +399,7 @@ static void pseries_dedicated_idle_sleep(void)
+ {
+ unsigned int cpu = smp_processor_id();
+ unsigned long start_snooze;
++ unsigned long in_purr, out_purr;
+
+ /*
+ * Indicate to the HV that we are idle. Now would be
+@@ -400,6 +407,7 @@ static void pseries_dedicated_idle_sleep(void)
+ */
+ get_lppaca()->idle = 1;
+ get_lppaca()->donate_dedicated_cpu = 1;
++ in_purr = mfspr(SPRN_PURR);
+
+ /*
+ * We come in with interrupts disabled, and need_resched()
+@@ -432,6 +440,8 @@ static void pseries_dedicated_idle_sleep(void)
+
+ out:
+ HMT_medium();
++ out_purr = mfspr(SPRN_PURR);
++ get_lppaca()->wait_state_cycles += out_purr - in_purr;
+ get_lppaca()->donate_dedicated_cpu = 0;
+ get_lppaca()->idle = 0;
+ }
+diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
+index ea4c659..9d8f8c8 100644
+--- a/arch/powerpc/platforms/pseries/smp.c
++++ b/arch/powerpc/platforms/pseries/smp.c
+@@ -12,7 +12,6 @@
+ * 2 of the License, or (at your option) any later version.
+ */
+
+-#undef DEBUG
+
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+@@ -51,12 +50,6 @@
+ #include "plpar_wrappers.h"
+ #include "pseries.h"
+
+-#ifdef DEBUG
+-#include <asm/udbg.h>
+-#define DBG(fmt...) udbg_printf(fmt)
+-#else
+-#define DBG(fmt...)
+-#endif
+
+ /*
+ * The primary thread of each non-boot processor is recorded here before
+@@ -231,7 +224,7 @@ static void __init smp_init_pseries(void)
+ {
+ int i;
+
+- DBG(" -> smp_init_pSeries()\n");
++ pr_debug(" -> smp_init_pSeries()\n");
+
+ /* Mark threads which are still spinning in hold loops. */
+ if (cpu_has_feature(CPU_FTR_SMT)) {
+@@ -255,7 +248,7 @@ static void __init smp_init_pseries(void)
+ smp_ops->take_timebase = pSeries_take_timebase;
+ }
+
+- DBG(" <- smp_init_pSeries()\n");
++ pr_debug(" <- smp_init_pSeries()\n");
+ }
+
+ #ifdef CONFIG_MPIC
+diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
+index a977f20..ebebc28 100644
+--- a/arch/powerpc/platforms/pseries/xics.c
++++ b/arch/powerpc/platforms/pseries/xics.c
+@@ -9,7 +9,6 @@
+ * 2 of the License, or (at your option) any later version.
+ */
+
+-#undef DEBUG
+
+ #include <linux/types.h>
+ #include <linux/threads.h>
+@@ -516,6 +515,8 @@ static struct irq_chip xics_pic_lpar = {
+ .set_affinity = xics_set_affinity
+ };
+
++/* Points to the irq_chip we're actually using */
++static struct irq_chip *xics_irq_chip;
+
+ static int xics_host_match(struct irq_host *h, struct device_node *node)
+ {
+@@ -526,23 +527,13 @@ static int xics_host_match(struct irq_host *h, struct device_node *node)
+ return !of_device_is_compatible(node, "chrp,iic");
+ }
+
+-static int xics_host_map_direct(struct irq_host *h, unsigned int virq,
+- irq_hw_number_t hw)
++static int xics_host_map(struct irq_host *h, unsigned int virq,
++ irq_hw_number_t hw)
+ {
+- pr_debug("xics: map_direct virq %d, hwirq 0x%lx\n", virq, hw);
++ pr_debug("xics: map virq %d, hwirq 0x%lx\n", virq, hw);
+
+ get_irq_desc(virq)->status |= IRQ_LEVEL;
+- set_irq_chip_and_handler(virq, &xics_pic_direct, handle_fasteoi_irq);
+- return 0;
+-}
+-
+-static int xics_host_map_lpar(struct irq_host *h, unsigned int virq,
+- irq_hw_number_t hw)
+-{
+- pr_debug("xics: map_direct virq %d, hwirq 0x%lx\n", virq, hw);
+-
+- get_irq_desc(virq)->status |= IRQ_LEVEL;
+- set_irq_chip_and_handler(virq, &xics_pic_lpar, handle_fasteoi_irq);
++ set_irq_chip_and_handler(virq, xics_irq_chip, handle_fasteoi_irq);
+ return 0;
+ }
+
+@@ -561,27 +552,20 @@ static int xics_host_xlate(struct irq_host *h, struct device_node *ct,
+ return 0;
+ }
+
+-static struct irq_host_ops xics_host_direct_ops = {
++static struct irq_host_ops xics_host_ops = {
+ .match = xics_host_match,
+- .map = xics_host_map_direct,
+- .xlate = xics_host_xlate,
+-};
+-
+-static struct irq_host_ops xics_host_lpar_ops = {
+- .match = xics_host_match,
+- .map = xics_host_map_lpar,
++ .map = xics_host_map,
+ .xlate = xics_host_xlate,
+ };
+
+ static void __init xics_init_host(void)
+ {
+- struct irq_host_ops *ops;
+-
+ if (firmware_has_feature(FW_FEATURE_LPAR))
+- ops = &xics_host_lpar_ops;
++ xics_irq_chip = &xics_pic_lpar;
+ else
+- ops = &xics_host_direct_ops;
+- xics_host = irq_alloc_host(NULL, IRQ_HOST_MAP_TREE, 0, ops,
++ xics_irq_chip = &xics_pic_direct;
++
++ xics_host = irq_alloc_host(NULL, IRQ_HOST_MAP_TREE, 0, &xics_host_ops,
+ XICS_IRQ_SPURIOUS);
+ BUG_ON(xics_host == NULL);
+ irq_set_default_host(xics_host);
+@@ -655,52 +639,6 @@ static void __init xics_init_one_node(struct device_node *np,
+ }
+ }
+
+-
+-static void __init xics_setup_8259_cascade(void)
+-{
+- struct device_node *np, *old, *found = NULL;
+- int cascade, naddr;
+- const u32 *addrp;
+- unsigned long intack = 0;
+-
+- for_each_node_by_type(np, "interrupt-controller")
+- if (of_device_is_compatible(np, "chrp,iic")) {
+- found = np;
+- break;
+- }
+- if (found == NULL) {
+- printk(KERN_DEBUG "xics: no ISA interrupt controller\n");
+- return;
+- }
+- cascade = irq_of_parse_and_map(found, 0);
+- if (cascade == NO_IRQ) {
+- printk(KERN_ERR "xics: failed to map cascade interrupt");
+- return;
+- }
+- pr_debug("xics: cascade mapped to irq %d\n", cascade);
+-
+- for (old = of_node_get(found); old != NULL ; old = np) {
+- np = of_get_parent(old);
+- of_node_put(old);
+- if (np == NULL)
+- break;
+- if (strcmp(np->name, "pci") != 0)
+- continue;
+- addrp = of_get_property(np, "8259-interrupt-acknowledge", NULL);
+- if (addrp == NULL)
+- continue;
+- naddr = of_n_addr_cells(np);
+- intack = addrp[naddr-1];
+- if (naddr > 1)
+- intack |= ((unsigned long)addrp[naddr-2]) << 32;
+- }
+- if (intack)
+- printk(KERN_DEBUG "xics: PCI 8259 intack at 0x%016lx\n", intack);
+- i8259_init(found, intack);
+- of_node_put(found);
+- set_irq_chained_handler(cascade, pseries_8259_cascade);
+-}
+-
+ void __init xics_init_IRQ(void)
+ {
+ struct device_node *np;
+@@ -733,8 +671,6 @@ void __init xics_init_IRQ(void)
+
+ xics_setup_cpu();
+
+- xics_setup_8259_cascade();
+-
+ ppc64_boot_msg(0x21, "XICS Done");
+ }
+
+diff --git a/arch/powerpc/platforms/pseries/xics.h b/arch/powerpc/platforms/pseries/xics.h
+index c26bcff..1c5321a 100644
+--- a/arch/powerpc/platforms/pseries/xics.h
++++ b/arch/powerpc/platforms/pseries/xics.h
+@@ -28,7 +28,4 @@ struct xics_ipi_struct {
+
+ extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
+
+-struct irq_desc;
+-extern void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc);
+-
+ #endif /* _POWERPC_KERNEL_XICS_H */
+diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
+index 15f3e85..6d386d0 100644
+--- a/arch/powerpc/sysdev/Makefile
++++ b/arch/powerpc/sysdev/Makefile
+@@ -12,6 +12,7 @@ obj-$(CONFIG_U3_DART) += dart_iommu.o
+ obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
+ obj-$(CONFIG_FSL_SOC) += fsl_soc.o
+ obj-$(CONFIG_FSL_PCI) += fsl_pci.o
++obj-$(CONFIG_FSL_LBC) += fsl_lbc.o
+ obj-$(CONFIG_RAPIDIO) += fsl_rio.o
+ obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
+ obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
+@@ -27,6 +28,7 @@ obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
+ obj-$(CONFIG_PPC_I8259) += i8259.o
+ obj-$(CONFIG_IPIC) += ipic.o
+ obj-$(CONFIG_4xx) += uic.o
++obj-$(CONFIG_4xx_SOC) += ppc4xx_soc.o
+ obj-$(CONFIG_XILINX_VIRTEX) += xilinx_intc.o
+ obj-$(CONFIG_OF_RTC) += of_rtc.o
+ ifeq ($(CONFIG_PCI),y)
+diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c
+index df8bd2b..58292a0 100644
+--- a/arch/powerpc/sysdev/cpm1.c
++++ b/arch/powerpc/sysdev/cpm1.c
+@@ -44,9 +44,6 @@
+
+ #define CPM_MAP_SIZE (0x4000)
+
+-#ifndef CONFIG_PPC_CPM_NEW_BINDING
+-static void m8xx_cpm_dpinit(void);
+-#endif
+ cpm8xx_t __iomem *cpmp; /* Pointer to comm processor space */
+ immap_t __iomem *mpc8xx_immr;
+ static cpic8xx_t __iomem *cpic_reg;
+@@ -229,12 +226,7 @@ void __init cpm_reset(void)
+ out_be32(&siu_conf->sc_sdcr, 1);
+ immr_unmap(siu_conf);
+
+-#ifdef CONFIG_PPC_CPM_NEW_BINDING
+ cpm_muram_init();
+-#else
+- /* Reclaim the DP memory for our use. */
+- m8xx_cpm_dpinit();
+-#endif
+ }
+
+ static DEFINE_SPINLOCK(cmd_lock);
+@@ -257,7 +249,7 @@ int cpm_command(u32 command, u8 opcode)
+ if ((in_be16(&cpmp->cp_cpcr) & CPM_CR_FLG) == 0)
+ goto out;
+
+- printk(KERN_ERR "%s(): Not able to issue CPM command\n", __FUNCTION__);
++ printk(KERN_ERR "%s(): Not able to issue CPM command\n", __func__);
+ ret = -EIO;
+ out:
+ spin_unlock_irqrestore(&cmd_lock, flags);
+@@ -293,110 +285,6 @@ cpm_setbrg(uint brg, uint rate)
+ CPM_BRG_EN | CPM_BRG_DIV16);
+ }
+
+-#ifndef CONFIG_PPC_CPM_NEW_BINDING
+-/*
+- * dpalloc / dpfree bits.
+- */
+-static spinlock_t cpm_dpmem_lock;
+-/*
+- * 16 blocks should be enough to satisfy all requests
+- * until the memory subsystem goes up...
+- */
+-static rh_block_t cpm_boot_dpmem_rh_block[16];
+-static rh_info_t cpm_dpmem_info;
+-
+-#define CPM_DPMEM_ALIGNMENT 8
+-static u8 __iomem *dpram_vbase;
+-static phys_addr_t dpram_pbase;
+-
+-static void m8xx_cpm_dpinit(void)
+-{
+- spin_lock_init(&cpm_dpmem_lock);
+-
+- dpram_vbase = cpmp->cp_dpmem;
+- dpram_pbase = get_immrbase() + offsetof(immap_t, im_cpm.cp_dpmem);
+-
+- /* Initialize the info header */
+- rh_init(&cpm_dpmem_info, CPM_DPMEM_ALIGNMENT,
+- sizeof(cpm_boot_dpmem_rh_block) /
+- sizeof(cpm_boot_dpmem_rh_block[0]),
+- cpm_boot_dpmem_rh_block);
+-
+- /*
+- * Attach the usable dpmem area.
+- * XXX: This is actually crap. CPM_DATAONLY_BASE and
+- * CPM_DATAONLY_SIZE are a subset of the available dparm. It varies
+- * with the processor and the microcode patches applied / activated.
+- * But the following should be at least safe.
+- */
+- rh_attach_region(&cpm_dpmem_info, CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE);
+-}
+-
+-/*
+- * Allocate the requested size worth of DP memory.
+- * This function returns an offset into the DPRAM area.
+- * Use cpm_dpram_addr() to get the virtual address of the area.
+- */
+-unsigned long cpm_dpalloc(uint size, uint align)
+-{
+- unsigned long start;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&cpm_dpmem_lock, flags);
+- cpm_dpmem_info.alignment = align;
+- start = rh_alloc(&cpm_dpmem_info, size, "commproc");
+- spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+-
+- return (uint)start;
+-}
+-EXPORT_SYMBOL(cpm_dpalloc);
+-
+-int cpm_dpfree(unsigned long offset)
+-{
+- int ret;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&cpm_dpmem_lock, flags);
+- ret = rh_free(&cpm_dpmem_info, offset);
+- spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+-
+- return ret;
+-}
+-EXPORT_SYMBOL(cpm_dpfree);
+-
+-unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align)
+-{
+- unsigned long start;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&cpm_dpmem_lock, flags);
+- cpm_dpmem_info.alignment = align;
+- start = rh_alloc_fixed(&cpm_dpmem_info, offset, size, "commproc");
+- spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+-
+- return start;
+-}
+-EXPORT_SYMBOL(cpm_dpalloc_fixed);
+-
+-void cpm_dpdump(void)
+-{
+- rh_dump(&cpm_dpmem_info);
+-}
+-EXPORT_SYMBOL(cpm_dpdump);
+-
+-void *cpm_dpram_addr(unsigned long offset)
+-{
+- return (void *)(dpram_vbase + offset);
+-}
+-EXPORT_SYMBOL(cpm_dpram_addr);
+-
+-uint cpm_dpram_phys(u8 *addr)
+-{
+- return (dpram_pbase + (uint)(addr - dpram_vbase));
+-}
+-EXPORT_SYMBOL(cpm_dpram_phys);
+-#endif /* !CONFIG_PPC_CPM_NEW_BINDING */
+-
+ struct cpm_ioport16 {
+ __be16 dir, par, odr_sor, dat, intr;
+ __be16 res[3];
+diff --git a/arch/powerpc/sysdev/cpm2.c b/arch/powerpc/sysdev/cpm2.c
+index dd066bb..5a6c5df 100644
+--- a/arch/powerpc/sysdev/cpm2.c
++++ b/arch/powerpc/sysdev/cpm2.c
+@@ -46,10 +46,6 @@
+
+ #include <sysdev/fsl_soc.h>
+
+-#ifndef CONFIG_PPC_CPM_NEW_BINDING
+-static void cpm2_dpinit(void);
+-#endif
+-
+ cpm_cpm2_t __iomem *cpmp; /* Pointer to comm processor space */
+
+ /* We allocate this here because it is used almost exclusively for
+@@ -71,15 +67,17 @@ void __init cpm2_reset(void)
+
+ /* Reclaim the DP memory for our use.
+ */
+-#ifdef CONFIG_PPC_CPM_NEW_BINDING
+ cpm_muram_init();
+-#else
+- cpm2_dpinit();
+-#endif
+
+ /* Tell everyone where the comm processor resides.
+ */
+ cpmp = &cpm2_immr->im_cpm;
++
++#ifndef CONFIG_PPC_EARLY_DEBUG_CPM
++ /* Reset the CPM.
++ */
++ cpm_command(CPM_CR_RST, 0);
++#endif
+ }
+
+ static DEFINE_SPINLOCK(cmd_lock);
+@@ -99,7 +97,7 @@ int cpm_command(u32 command, u8 opcode)
+ if ((in_be32(&cpmp->cp_cpcr) & CPM_CR_FLG) == 0)
+ goto out;
+
+- printk(KERN_ERR "%s(): Not able to issue CPM command\n", __FUNCTION__);
++ printk(KERN_ERR "%s(): Not able to issue CPM command\n", __func__);
+ ret = -EIO;
+ out:
+ spin_unlock_irqrestore(&cmd_lock, flags);
+@@ -347,95 +345,6 @@ int cpm2_smc_clk_setup(enum cpm_clk_target target, int clock)
+ return ret;
+ }
+
+-#ifndef CONFIG_PPC_CPM_NEW_BINDING
+-/*
+- * dpalloc / dpfree bits.
+- */
+-static spinlock_t cpm_dpmem_lock;
+-/* 16 blocks should be enough to satisfy all requests
+- * until the memory subsystem goes up... */
+-static rh_block_t cpm_boot_dpmem_rh_block[16];
+-static rh_info_t cpm_dpmem_info;
+-static u8 __iomem *im_dprambase;
+-
+-static void cpm2_dpinit(void)
+-{
+- spin_lock_init(&cpm_dpmem_lock);
+-
+- /* initialize the info header */
+- rh_init(&cpm_dpmem_info, 1,
+- sizeof(cpm_boot_dpmem_rh_block) /
+- sizeof(cpm_boot_dpmem_rh_block[0]),
+- cpm_boot_dpmem_rh_block);
+-
+- im_dprambase = cpm2_immr;
+-
+- /* Attach the usable dpmem area */
+- /* XXX: This is actually crap. CPM_DATAONLY_BASE and
+- * CPM_DATAONLY_SIZE is only a subset of the available dpram. It
+- * varies with the processor and the microcode patches activated.
+- * But the following should be at least safe.
+- */
+- rh_attach_region(&cpm_dpmem_info, CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE);
+-}
+-
+-/* This function returns an index into the DPRAM area.
+- */
+-unsigned long cpm_dpalloc(uint size, uint align)
+-{
+- unsigned long start;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&cpm_dpmem_lock, flags);
+- cpm_dpmem_info.alignment = align;
+- start = rh_alloc(&cpm_dpmem_info, size, "commproc");
+- spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+-
+- return (uint)start;
+-}
+-EXPORT_SYMBOL(cpm_dpalloc);
+-
+-int cpm_dpfree(unsigned long offset)
+-{
+- int ret;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&cpm_dpmem_lock, flags);
+- ret = rh_free(&cpm_dpmem_info, offset);
+- spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+-
+- return ret;
+-}
+-EXPORT_SYMBOL(cpm_dpfree);
+-
+-/* not sure if this is ever needed */
+-unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align)
+-{
+- unsigned long start;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&cpm_dpmem_lock, flags);
+- cpm_dpmem_info.alignment = align;
+- start = rh_alloc_fixed(&cpm_dpmem_info, offset, size, "commproc");
+- spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+-
+- return start;
+-}
+-EXPORT_SYMBOL(cpm_dpalloc_fixed);
+-
+-void cpm_dpdump(void)
+-{
+- rh_dump(&cpm_dpmem_info);
+-}
+-EXPORT_SYMBOL(cpm_dpdump);
+-
+-void *cpm_dpram_addr(unsigned long offset)
+-{
+- return (void *)(im_dprambase + offset);
+-}
+-EXPORT_SYMBOL(cpm_dpram_addr);
+-#endif /* !CONFIG_PPC_CPM_NEW_BINDING */
+-
+ struct cpm2_ioports {
+ u32 dir, par, sor, odr, dat;
+ u32 res[3];
+diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c
+index 165981c..cb7df2d 100644
+--- a/arch/powerpc/sysdev/cpm_common.c
++++ b/arch/powerpc/sysdev/cpm_common.c
+@@ -58,7 +58,6 @@ void __init udbg_init_cpm(void)
+ }
+ #endif
+
+-#ifdef CONFIG_PPC_CPM_NEW_BINDING
+ static spinlock_t cpm_muram_lock;
+ static rh_block_t cpm_boot_muram_rh_block[16];
+ static rh_info_t cpm_muram_info;
+@@ -199,5 +198,3 @@ dma_addr_t cpm_muram_dma(void __iomem *addr)
+ return muram_pbase + ((u8 __iomem *)addr - muram_vbase);
+ }
+ EXPORT_SYMBOL(cpm_muram_dma);
+-
+-#endif /* CONFIG_PPC_CPM_NEW_BINDING */
+diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
+index e0e24b0..005c2ec 100644
+--- a/arch/powerpc/sysdev/dart_iommu.c
++++ b/arch/powerpc/sysdev/dart_iommu.c
+@@ -37,6 +37,7 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/vmalloc.h>
+ #include <linux/suspend.h>
++#include <linux/lmb.h>
+ #include <asm/io.h>
+ #include <asm/prom.h>
+ #include <asm/iommu.h>
+@@ -44,7 +45,6 @@
+ #include <asm/machdep.h>
+ #include <asm/abs_addr.h>
+ #include <asm/cacheflush.h>
+-#include <asm/lmb.h>
+ #include <asm/ppc-pci.h>
+
+ #include "dart.h"
+diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
+new file mode 100644
+index 0000000..422c8fa
+--- /dev/null
++++ b/arch/powerpc/sysdev/fsl_lbc.c
+@@ -0,0 +1,129 @@
++/*
++ * Freescale LBC and UPM routines.
++ *
++ * Copyright (c) 2007-2008 MontaVista Software, Inc.
++ *
++ * Author: Anton Vorontsov <avorontsov at ru.mvista.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/kernel.h>
++#include <linux/of.h>
++#include <asm/fsl_lbc.h>
++
++spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
++
++struct fsl_lbc_regs __iomem *fsl_lbc_regs;
++EXPORT_SYMBOL(fsl_lbc_regs);
++
++static char __initdata *compat_lbc[] = {
++ "fsl,pq2-localbus",
++ "fsl,pq2pro-localbus",
++ "fsl,pq3-localbus",
++ "fsl,elbc",
++};
++
++static int __init fsl_lbc_init(void)
++{
++ struct device_node *lbus;
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) {
++ lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]);
++ if (lbus)
++ goto found;
++ }
++ return -ENODEV;
++
++found:
++ fsl_lbc_regs = of_iomap(lbus, 0);
++ of_node_put(lbus);
++ if (!fsl_lbc_regs)
++ return -ENOMEM;
++ return 0;
++}
++arch_initcall(fsl_lbc_init);
++
++/**
++ * fsl_lbc_find - find Localbus bank
++ * @addr_base: base address of the memory bank
++ *
++ * This function walks LBC banks comparing "Base address" field of the BR
++ * registers with the supplied addr_base argument. When bases match this
++ * function returns bank number (starting with 0), otherwise it returns
++ * appropriate errno value.
++ */
++int fsl_lbc_find(phys_addr_t addr_base)
++{
++ int i;
++
++ if (!fsl_lbc_regs)
++ return -ENODEV;
++
++ for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) {
++ __be32 br = in_be32(&fsl_lbc_regs->bank[i].br);
++ __be32 or = in_be32(&fsl_lbc_regs->bank[i].or);
++
++ if (br & BR_V && (br & or & BR_BA) == addr_base)
++ return i;
++ }
++
++ return -ENOENT;
++}
++EXPORT_SYMBOL(fsl_lbc_find);
++
++/**
++ * fsl_upm_find - find pre-programmed UPM via base address
++ * @addr_base: base address of the memory bank controlled by the UPM
++ * @upm: pointer to the allocated fsl_upm structure
++ *
++ * This function fills fsl_upm structure so you can use it with the rest of
++ * UPM API. On success this function returns 0, otherwise it returns
++ * appropriate errno value.
++ */
++int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm)
++{
++ int bank;
++ __be32 br;
++
++ bank = fsl_lbc_find(addr_base);
++ if (bank < 0)
++ return bank;
++
++ br = in_be32(&fsl_lbc_regs->bank[bank].br);
++
++ switch (br & BR_MSEL) {
++ case BR_MS_UPMA:
++ upm->mxmr = &fsl_lbc_regs->mamr;
++ break;
++ case BR_MS_UPMB:
++ upm->mxmr = &fsl_lbc_regs->mbmr;
++ break;
++ case BR_MS_UPMC:
++ upm->mxmr = &fsl_lbc_regs->mcmr;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ switch (br & BR_PS) {
++ case BR_PS_8:
++ upm->width = 8;
++ break;
++ case BR_PS_16:
++ upm->width = 16;
++ break;
++ case BR_PS_32:
++ upm->width = 32;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL(fsl_upm_find);
+diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
+index 2c5388c..5c1b246 100644
+--- a/arch/powerpc/sysdev/fsl_soc.c
++++ b/arch/powerpc/sysdev/fsl_soc.c
+@@ -75,6 +75,33 @@ phys_addr_t get_immrbase(void)
+
+ EXPORT_SYMBOL(get_immrbase);
+
++static u32 sysfreq = -1;
++
++u32 fsl_get_sys_freq(void)
++{
++ struct device_node *soc;
++ const u32 *prop;
++ int size;
++
++ if (sysfreq != -1)
++ return sysfreq;
++
++ soc = of_find_node_by_type(NULL, "soc");
++ if (!soc)
++ return -1;
++
++ prop = of_get_property(soc, "clock-frequency", &size);
++ if (!prop || size != sizeof(*prop) || *prop == 0)
++ prop = of_get_property(soc, "bus-frequency", &size);
++
++ if (prop && size == sizeof(*prop))
++ sysfreq = *prop;
++
++ of_node_put(soc);
++ return sysfreq;
++}
++EXPORT_SYMBOL(fsl_get_sys_freq);
++
+ #if defined(CONFIG_CPM2) || defined(CONFIG_QUICC_ENGINE) || defined(CONFIG_8xx)
+
+ static u32 brgfreq = -1;
+@@ -341,7 +368,7 @@ static int __init gfar_of_init(void)
+ goto unreg;
+ }
+
+- gfar_data.bus_id = 0;
++ snprintf(gfar_data.bus_id, MII_BUS_ID_SIZE, "0");
+ gfar_data.phy_id = fixed_link[0];
+ } else {
+ phy = of_find_node_by_phandle(*ph);
+@@ -362,7 +389,8 @@ static int __init gfar_of_init(void)
+ }
+
+ gfar_data.phy_id = *id;
+- gfar_data.bus_id = res.start;
++ snprintf(gfar_data.bus_id, MII_BUS_ID_SIZE, "%x",
++ res.start);
+
+ of_node_put(phy);
+ of_node_put(mdio);
+@@ -516,9 +544,9 @@ arch_initcall(fsl_i2c_of_init);
+ static int __init mpc83xx_wdt_init(void)
+ {
+ struct resource r;
+- struct device_node *soc, *np;
++ struct device_node *np;
+ struct platform_device *dev;
+- const unsigned int *freq;
++ u32 freq = fsl_get_sys_freq();
+ int ret;
+
+ np = of_find_compatible_node(NULL, "watchdog", "mpc83xx_wdt");
+@@ -528,19 +556,6 @@ static int __init mpc83xx_wdt_init(void)
+ goto nodev;
+ }
+
+- soc = of_find_node_by_type(NULL, "soc");
+-
+- if (!soc) {
+- ret = -ENODEV;
+- goto nosoc;
+- }
+-
+- freq = of_get_property(soc, "bus-frequency", NULL);
+- if (!freq) {
+- ret = -ENODEV;
+- goto err;
+- }
+-
+ memset(&r, 0, sizeof(r));
+
+ ret = of_address_to_resource(np, 0, &r);
+@@ -553,20 +568,16 @@ static int __init mpc83xx_wdt_init(void)
+ goto err;
+ }
+
+- ret = platform_device_add_data(dev, freq, sizeof(int));
++ ret = platform_device_add_data(dev, &freq, sizeof(freq));
+ if (ret)
+ goto unreg;
+
+- of_node_put(soc);
+ of_node_put(np);
+-
+ return 0;
+
+ unreg:
+ platform_device_unregister(dev);
+ err:
+- of_node_put(soc);
+-nosoc:
+ of_node_put(np);
+ nodev:
+ return ret;
+@@ -735,547 +746,6 @@ err:
+
+ arch_initcall(fsl_usb_of_init);
+
+-#ifndef CONFIG_PPC_CPM_NEW_BINDING
+-#ifdef CONFIG_CPM2
+-
+-extern void init_scc_ioports(struct fs_uart_platform_info*);
+-
+-static const char fcc_regs[] = "fcc_regs";
+-static const char fcc_regs_c[] = "fcc_regs_c";
+-static const char fcc_pram[] = "fcc_pram";
+-static char bus_id[9][BUS_ID_SIZE];
+-
+-static int __init fs_enet_of_init(void)
+-{
+- struct device_node *np;
+- unsigned int i;
+- struct platform_device *fs_enet_dev;
+- struct resource res;
+- int ret;
+-
+- for (np = NULL, i = 0;
+- (np = of_find_compatible_node(np, "network", "fs_enet")) != NULL;
+- i++) {
+- struct resource r[4];
+- struct device_node *phy, *mdio;
+- struct fs_platform_info fs_enet_data;
+- const unsigned int *id, *phy_addr, *phy_irq;
+- const void *mac_addr;
+- const phandle *ph;
+- const char *model;
+-
+- memset(r, 0, sizeof(r));
+- memset(&fs_enet_data, 0, sizeof(fs_enet_data));
+-
+- ret = of_address_to_resource(np, 0, &r[0]);
+- if (ret)
+- goto err;
+- r[0].name = fcc_regs;
+-
+- ret = of_address_to_resource(np, 1, &r[1]);
+- if (ret)
+- goto err;
+- r[1].name = fcc_pram;
+-
+- ret = of_address_to_resource(np, 2, &r[2]);
+- if (ret)
+- goto err;
+- r[2].name = fcc_regs_c;
+- fs_enet_data.fcc_regs_c = r[2].start;
+-
+- of_irq_to_resource(np, 0, &r[3]);
+-
+- fs_enet_dev =
+- platform_device_register_simple("fsl-cpm-fcc", i, &r[0], 4);
+-
+- if (IS_ERR(fs_enet_dev)) {
+- ret = PTR_ERR(fs_enet_dev);
+- goto err;
+- }
+-
+- model = of_get_property(np, "model", NULL);
+- if (model == NULL) {
+- ret = -ENODEV;
+- goto unreg;
+- }
+-
+- mac_addr = of_get_mac_address(np);
+- if (mac_addr)
+- memcpy(fs_enet_data.macaddr, mac_addr, 6);
+-
+- ph = of_get_property(np, "phy-handle", NULL);
+- phy = of_find_node_by_phandle(*ph);
+-
+- if (phy == NULL) {
+- ret = -ENODEV;
+- goto unreg;
+- }
+-
+- phy_addr = of_get_property(phy, "reg", NULL);
+- fs_enet_data.phy_addr = *phy_addr;
+-
+- phy_irq = of_get_property(phy, "interrupts", NULL);
+-
+- id = of_get_property(np, "device-id", NULL);
+- fs_enet_data.fs_no = *id;
+- strcpy(fs_enet_data.fs_type, model);
+-
+- mdio = of_get_parent(phy);
+- ret = of_address_to_resource(mdio, 0, &res);
+- if (ret) {
+- of_node_put(phy);
+- of_node_put(mdio);
+- goto unreg;
+- }
+-
+- fs_enet_data.clk_rx = *((u32 *)of_get_property(np,
+- "rx-clock", NULL));
+- fs_enet_data.clk_tx = *((u32 *)of_get_property(np,
+- "tx-clock", NULL));
+-
+- if (strstr(model, "FCC")) {
+- int fcc_index = *id - 1;
+- const unsigned char *mdio_bb_prop;
+-
+- fs_enet_data.dpram_offset = (u32)cpm_dpram_addr(0);
+- fs_enet_data.rx_ring = 32;
+- fs_enet_data.tx_ring = 32;
+- fs_enet_data.rx_copybreak = 240;
+- fs_enet_data.use_napi = 0;
+- fs_enet_data.napi_weight = 17;
+- fs_enet_data.mem_offset = FCC_MEM_OFFSET(fcc_index);
+- fs_enet_data.cp_page = CPM_CR_FCC_PAGE(fcc_index);
+- fs_enet_data.cp_block = CPM_CR_FCC_SBLOCK(fcc_index);
+-
+- snprintf((char*)&bus_id[(*id)], BUS_ID_SIZE, "%x:%02x",
+- (u32)res.start, fs_enet_data.phy_addr);
+- fs_enet_data.bus_id = (char*)&bus_id[(*id)];
+- fs_enet_data.init_ioports = init_fcc_ioports;
+-
+- mdio_bb_prop = of_get_property(phy, "bitbang", NULL);
+- if (mdio_bb_prop) {
+- struct platform_device *fs_enet_mdio_bb_dev;
+- struct fs_mii_bb_platform_info fs_enet_mdio_bb_data;
+-
+- fs_enet_mdio_bb_dev =
+- platform_device_register_simple("fsl-bb-mdio",
+- i, NULL, 0);
+- memset(&fs_enet_mdio_bb_data, 0,
+- sizeof(struct fs_mii_bb_platform_info));
+- fs_enet_mdio_bb_data.mdio_dat.bit =
+- mdio_bb_prop[0];
+- fs_enet_mdio_bb_data.mdio_dir.bit =
+- mdio_bb_prop[1];
+- fs_enet_mdio_bb_data.mdc_dat.bit =
+- mdio_bb_prop[2];
+- fs_enet_mdio_bb_data.mdio_port =
+- mdio_bb_prop[3];
+- fs_enet_mdio_bb_data.mdc_port =
+- mdio_bb_prop[4];
+- fs_enet_mdio_bb_data.delay =
+- mdio_bb_prop[5];
+-
+- fs_enet_mdio_bb_data.irq[0] = phy_irq[0];
+- fs_enet_mdio_bb_data.irq[1] = -1;
+- fs_enet_mdio_bb_data.irq[2] = -1;
+- fs_enet_mdio_bb_data.irq[3] = phy_irq[0];
+- fs_enet_mdio_bb_data.irq[31] = -1;
+-
+- fs_enet_mdio_bb_data.mdio_dat.offset =
+- (u32)&cpm2_immr->im_ioport.iop_pdatc;
+- fs_enet_mdio_bb_data.mdio_dir.offset =
+- (u32)&cpm2_immr->im_ioport.iop_pdirc;
+- fs_enet_mdio_bb_data.mdc_dat.offset =
+- (u32)&cpm2_immr->im_ioport.iop_pdatc;
+-
+- ret = platform_device_add_data(
+- fs_enet_mdio_bb_dev,
+- &fs_enet_mdio_bb_data,
+- sizeof(struct fs_mii_bb_platform_info));
+- if (ret)
+- goto unreg;
+- }
+-
+- of_node_put(phy);
+- of_node_put(mdio);
+-
+- ret = platform_device_add_data(fs_enet_dev, &fs_enet_data,
+- sizeof(struct
+- fs_platform_info));
+- if (ret)
+- goto unreg;
+- }
+- }
+- return 0;
+-
+-unreg:
+- platform_device_unregister(fs_enet_dev);
+-err:
+- return ret;
+-}
+-
+-arch_initcall(fs_enet_of_init);
+-
+-static const char scc_regs[] = "regs";
+-static const char scc_pram[] = "pram";
+-
+-static int __init cpm_uart_of_init(void)
+-{
+- struct device_node *np;
+- unsigned int i;
+- struct platform_device *cpm_uart_dev;
+- int ret;
+-
+- for (np = NULL, i = 0;
+- (np = of_find_compatible_node(np, "serial", "cpm_uart")) != NULL;
+- i++) {
+- struct resource r[3];
+- struct fs_uart_platform_info cpm_uart_data;
+- const int *id;
+- const char *model;
+-
+- memset(r, 0, sizeof(r));
+- memset(&cpm_uart_data, 0, sizeof(cpm_uart_data));
+-
+- ret = of_address_to_resource(np, 0, &r[0]);
+- if (ret)
+- goto err;
+-
+- r[0].name = scc_regs;
+-
+- ret = of_address_to_resource(np, 1, &r[1]);
+- if (ret)
+- goto err;
+- r[1].name = scc_pram;
+-
+- of_irq_to_resource(np, 0, &r[2]);
+-
+- cpm_uart_dev =
+- platform_device_register_simple("fsl-cpm-scc:uart", i, &r[0], 3);
+-
+- if (IS_ERR(cpm_uart_dev)) {
+- ret = PTR_ERR(cpm_uart_dev);
+- goto err;
+- }
+-
+- id = of_get_property(np, "device-id", NULL);
+- cpm_uart_data.fs_no = *id;
+-
+- model = of_get_property(np, "model", NULL);
+- strcpy(cpm_uart_data.fs_type, model);
+-
+- cpm_uart_data.uart_clk = ppc_proc_freq;
+-
+- cpm_uart_data.tx_num_fifo = 4;
+- cpm_uart_data.tx_buf_size = 32;
+- cpm_uart_data.rx_num_fifo = 4;
+- cpm_uart_data.rx_buf_size = 32;
+- cpm_uart_data.clk_rx = *((u32 *)of_get_property(np,
+- "rx-clock", NULL));
+- cpm_uart_data.clk_tx = *((u32 *)of_get_property(np,
+- "tx-clock", NULL));
+-
+- ret =
+- platform_device_add_data(cpm_uart_dev, &cpm_uart_data,
+- sizeof(struct
+- fs_uart_platform_info));
+- if (ret)
+- goto unreg;
+- }
+-
+- return 0;
+-
+-unreg:
+- platform_device_unregister(cpm_uart_dev);
+-err:
+- return ret;
+-}
+-
+-arch_initcall(cpm_uart_of_init);
+-#endif /* CONFIG_CPM2 */
+-
+-#ifdef CONFIG_8xx
+-
+-extern void init_scc_ioports(struct fs_platform_info*);
+-extern int platform_device_skip(const char *model, int id);
+-
+-static int __init fs_enet_mdio_of_init(void)
+-{
+- struct device_node *np;
+- unsigned int i;
+- struct platform_device *mdio_dev;
+- struct resource res;
+- int ret;
+-
+- for (np = NULL, i = 0;
+- (np = of_find_compatible_node(np, "mdio", "fs_enet")) != NULL;
+- i++) {
+- struct fs_mii_fec_platform_info mdio_data;
+-
+- memset(&res, 0, sizeof(res));
+- memset(&mdio_data, 0, sizeof(mdio_data));
+-
+- ret = of_address_to_resource(np, 0, &res);
+- if (ret)
+- goto err;
+-
+- mdio_dev =
+- platform_device_register_simple("fsl-cpm-fec-mdio",
+- res.start, &res, 1);
+- if (IS_ERR(mdio_dev)) {
+- ret = PTR_ERR(mdio_dev);
+- goto err;
+- }
+-
+- mdio_data.mii_speed = ((((ppc_proc_freq + 4999999) / 2500000) / 2) & 0x3F) << 1;
+-
+- ret =
+- platform_device_add_data(mdio_dev, &mdio_data,
+- sizeof(struct fs_mii_fec_platform_info));
+- if (ret)
+- goto unreg;
+- }
+- return 0;
+-
+-unreg:
+- platform_device_unregister(mdio_dev);
+-err:
+- return ret;
+-}
+-
+-arch_initcall(fs_enet_mdio_of_init);
+-
+-static const char *enet_regs = "regs";
+-static const char *enet_pram = "pram";
+-static const char *enet_irq = "interrupt";
+-static char bus_id[9][BUS_ID_SIZE];
+-
+-static int __init fs_enet_of_init(void)
+-{
+- struct device_node *np;
+- unsigned int i;
+- struct platform_device *fs_enet_dev = NULL;
+- struct resource res;
+- int ret;
+-
+- for (np = NULL, i = 0;
+- (np = of_find_compatible_node(np, "network", "fs_enet")) != NULL;
+- i++) {
+- struct resource r[4];
+- struct device_node *phy = NULL, *mdio = NULL;
+- struct fs_platform_info fs_enet_data;
+- const unsigned int *id;
+- const unsigned int *phy_addr;
+- const void *mac_addr;
+- const phandle *ph;
+- const char *model;
+-
+- memset(r, 0, sizeof(r));
+- memset(&fs_enet_data, 0, sizeof(fs_enet_data));
+-
+- model = of_get_property(np, "model", NULL);
+- if (model == NULL) {
+- ret = -ENODEV;
+- goto unreg;
+- }
+-
+- id = of_get_property(np, "device-id", NULL);
+- fs_enet_data.fs_no = *id;
+-
+- if (platform_device_skip(model, *id))
+- continue;
+-
+- ret = of_address_to_resource(np, 0, &r[0]);
+- if (ret)
+- goto err;
+- r[0].name = enet_regs;
+-
+- mac_addr = of_get_mac_address(np);
+- if (mac_addr)
+- memcpy(fs_enet_data.macaddr, mac_addr, 6);
+-
+- ph = of_get_property(np, "phy-handle", NULL);
+- if (ph != NULL)
+- phy = of_find_node_by_phandle(*ph);
+-
+- if (phy != NULL) {
+- phy_addr = of_get_property(phy, "reg", NULL);
+- fs_enet_data.phy_addr = *phy_addr;
+- fs_enet_data.has_phy = 1;
+-
+- mdio = of_get_parent(phy);
+- ret = of_address_to_resource(mdio, 0, &res);
+- if (ret) {
+- of_node_put(phy);
+- of_node_put(mdio);
+- goto unreg;
+- }
+- }
+-
+- model = of_get_property(np, "model", NULL);
+- strcpy(fs_enet_data.fs_type, model);
+-
+- if (strstr(model, "FEC")) {
+- r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
+- r[1].flags = IORESOURCE_IRQ;
+- r[1].name = enet_irq;
+-
+- fs_enet_dev =
+- platform_device_register_simple("fsl-cpm-fec", i, &r[0], 2);
+-
+- if (IS_ERR(fs_enet_dev)) {
+- ret = PTR_ERR(fs_enet_dev);
+- goto err;
+- }
+-
+- fs_enet_data.rx_ring = 128;
+- fs_enet_data.tx_ring = 16;
+- fs_enet_data.rx_copybreak = 240;
+- fs_enet_data.use_napi = 1;
+- fs_enet_data.napi_weight = 17;
+-
+- snprintf((char*)&bus_id[i], BUS_ID_SIZE, "%x:%02x",
+- (u32)res.start, fs_enet_data.phy_addr);
+- fs_enet_data.bus_id = (char*)&bus_id[i];
+- fs_enet_data.init_ioports = init_fec_ioports;
+- }
+- if (strstr(model, "SCC")) {
+- ret = of_address_to_resource(np, 1, &r[1]);
+- if (ret)
+- goto err;
+- r[1].name = enet_pram;
+-
+- r[2].start = r[2].end = irq_of_parse_and_map(np, 0);
+- r[2].flags = IORESOURCE_IRQ;
+- r[2].name = enet_irq;
+-
+- fs_enet_dev =
+- platform_device_register_simple("fsl-cpm-scc", i, &r[0], 3);
+-
+- if (IS_ERR(fs_enet_dev)) {
+- ret = PTR_ERR(fs_enet_dev);
+- goto err;
+- }
+-
+- fs_enet_data.rx_ring = 64;
+- fs_enet_data.tx_ring = 8;
+- fs_enet_data.rx_copybreak = 240;
+- fs_enet_data.use_napi = 1;
+- fs_enet_data.napi_weight = 17;
+-
+- snprintf((char*)&bus_id[i], BUS_ID_SIZE, "%s", "fixed at 10:1");
+- fs_enet_data.bus_id = (char*)&bus_id[i];
+- fs_enet_data.init_ioports = init_scc_ioports;
+- }
+-
+- of_node_put(phy);
+- of_node_put(mdio);
+-
+- ret = platform_device_add_data(fs_enet_dev, &fs_enet_data,
+- sizeof(struct
+- fs_platform_info));
+- if (ret)
+- goto unreg;
+- }
+- return 0;
+-
+-unreg:
+- platform_device_unregister(fs_enet_dev);
+-err:
+- return ret;
+-}
+-
+-arch_initcall(fs_enet_of_init);
+-
+-static int __init fsl_pcmcia_of_init(void)
+-{
+- struct device_node *np;
+- /*
+- * Register all the devices which type is "pcmcia"
+- */
+- for_each_compatible_node(np, "pcmcia", "fsl,pq-pcmcia")
+- of_platform_device_create(np, "m8xx-pcmcia", NULL);
+- return 0;
+-}
+-
+-arch_initcall(fsl_pcmcia_of_init);
+-
+-static const char *smc_regs = "regs";
+-static const char *smc_pram = "pram";
+-
+-static int __init cpm_smc_uart_of_init(void)
+-{
+- struct device_node *np;
+- unsigned int i;
+- struct platform_device *cpm_uart_dev;
+- int ret;
+-
+- for (np = NULL, i = 0;
+- (np = of_find_compatible_node(np, "serial", "cpm_uart")) != NULL;
+- i++) {
+- struct resource r[3];
+- struct fs_uart_platform_info cpm_uart_data;
+- const int *id;
+- const char *model;
+-
+- memset(r, 0, sizeof(r));
+- memset(&cpm_uart_data, 0, sizeof(cpm_uart_data));
+-
+- ret = of_address_to_resource(np, 0, &r[0]);
+- if (ret)
+- goto err;
+-
+- r[0].name = smc_regs;
+-
+- ret = of_address_to_resource(np, 1, &r[1]);
+- if (ret)
+- goto err;
+- r[1].name = smc_pram;
+-
+- r[2].start = r[2].end = irq_of_parse_and_map(np, 0);
+- r[2].flags = IORESOURCE_IRQ;
+-
+- cpm_uart_dev =
+- platform_device_register_simple("fsl-cpm-smc:uart", i, &r[0], 3);
+-
+- if (IS_ERR(cpm_uart_dev)) {
+- ret = PTR_ERR(cpm_uart_dev);
+- goto err;
+- }
+-
+- model = of_get_property(np, "model", NULL);
+- strcpy(cpm_uart_data.fs_type, model);
+-
+- id = of_get_property(np, "device-id", NULL);
+- cpm_uart_data.fs_no = *id;
+- cpm_uart_data.uart_clk = ppc_proc_freq;
+-
+- cpm_uart_data.tx_num_fifo = 4;
+- cpm_uart_data.tx_buf_size = 32;
+- cpm_uart_data.rx_num_fifo = 4;
+- cpm_uart_data.rx_buf_size = 32;
+-
+- ret =
+- platform_device_add_data(cpm_uart_dev, &cpm_uart_data,
+- sizeof(struct
+- fs_uart_platform_info));
+- if (ret)
+- goto unreg;
+- }
+-
+- return 0;
+-
+-unreg:
+- platform_device_unregister(cpm_uart_dev);
+-err:
+- return ret;
+-}
+-
+-arch_initcall(cpm_smc_uart_of_init);
+-
+-#endif /* CONFIG_8xx */
+-#endif /* CONFIG_PPC_CPM_NEW_BINDING */
+-
+ static int __init of_fsl_spi_probe(char *type, char *compatible, u32 sysclk,
+ struct spi_board_info *board_infos,
+ unsigned int num_board_infos,
+@@ -1371,25 +841,9 @@ int __init fsl_spi_init(struct spi_board_info *board_infos,
+ sysclk = get_brgfreq();
+ #endif
+ if (sysclk == -1) {
+- struct device_node *np;
+- const u32 *freq;
+- int size;
+-
+- np = of_find_node_by_type(NULL, "soc");
+- if (!np)
++ sysclk = fsl_get_sys_freq();
++ if (sysclk == -1)
+ return -ENODEV;
+-
+- freq = of_get_property(np, "clock-frequency", &size);
+- if (!freq || size != sizeof(*freq) || *freq == 0) {
+- freq = of_get_property(np, "bus-frequency", &size);
+- if (!freq || size != sizeof(*freq) || *freq == 0) {
+- of_node_put(np);
+- return -ENODEV;
+- }
+- }
+-
+- sysclk = *freq;
+- of_node_put(np);
+ }
+
+ ret = of_fsl_spi_probe(NULL, "fsl,spi", sysclk, board_infos,
+diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
+index 63e7db3..74c4a96 100644
+--- a/arch/powerpc/sysdev/fsl_soc.h
++++ b/arch/powerpc/sysdev/fsl_soc.h
+@@ -7,6 +7,7 @@
+ extern phys_addr_t get_immrbase(void);
+ extern u32 get_brgfreq(void);
+ extern u32 get_baudrate(void);
++extern u32 fsl_get_sys_freq(void);
+
+ struct spi_board_info;
+
+diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
+index 6ffdda2..8619f2a 100644
+--- a/arch/powerpc/sysdev/mpic.c
++++ b/arch/powerpc/sysdev/mpic.c
+@@ -175,13 +175,16 @@ static inline void _mpic_write(enum mpic_reg_type type,
+ switch(type) {
+ #ifdef CONFIG_PPC_DCR
+ case mpic_access_dcr:
+- return dcr_write(rb->dhost, reg, value);
++ dcr_write(rb->dhost, reg, value);
++ break;
+ #endif
+ case mpic_access_mmio_be:
+- return out_be32(rb->base + (reg >> 2), value);
++ out_be32(rb->base + (reg >> 2), value);
++ break;
+ case mpic_access_mmio_le:
+ default:
+- return out_le32(rb->base + (reg >> 2), value);
++ out_le32(rb->base + (reg >> 2), value);
++ break;
+ }
+ }
+
+@@ -1000,7 +1003,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
+ const char *name)
+ {
+ struct mpic *mpic;
+- u32 reg;
++ u32 greg_feature;
+ const char *vers;
+ int i;
+ int intvec_top;
+@@ -1064,7 +1067,8 @@ struct mpic * __init mpic_alloc(struct device_node *node,
+
+ /* Look for protected sources */
+ if (node) {
+- unsigned int psize, bits, mapsize;
++ int psize;
++ unsigned int bits, mapsize;
+ const u32 *psrc =
+ of_get_property(node, "protected-sources", &psize);
+ if (psrc) {
+@@ -1107,8 +1111,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
+ * in, try to obtain one
+ */
+ if (paddr == 0 && !(mpic->flags & MPIC_USES_DCR)) {
+- const u32 *reg;
+- reg = of_get_property(node, "reg", NULL);
++ const u32 *reg = of_get_property(node, "reg", NULL);
+ BUG_ON(reg == NULL);
+ paddr = of_translate_address(node, reg);
+ BUG_ON(paddr == OF_BAD_ADDR);
+@@ -1137,12 +1140,13 @@ struct mpic * __init mpic_alloc(struct device_node *node,
+ * MPICs, num sources as well. On ISU MPICs, sources are counted
+ * as ISUs are added
+ */
+- reg = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
+- mpic->num_cpus = ((reg & MPIC_GREG_FEATURE_LAST_CPU_MASK)
++ greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
++ mpic->num_cpus = ((greg_feature & MPIC_GREG_FEATURE_LAST_CPU_MASK)
+ >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
+ if (isu_size == 0)
+- mpic->num_sources = ((reg & MPIC_GREG_FEATURE_LAST_SRC_MASK)
+- >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
++ mpic->num_sources =
++ ((greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK)
++ >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
+
+ /* Map the per-CPU registers */
+ for (i = 0; i < mpic->num_cpus; i++) {
+@@ -1161,7 +1165,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
+ mpic->isu_mask = (1 << mpic->isu_shift) - 1;
+
+ /* Display version */
+- switch (reg & MPIC_GREG_FEATURE_VERSION_MASK) {
++ switch (greg_feature & MPIC_GREG_FEATURE_VERSION_MASK) {
+ case 1:
+ vers = "1.0";
+ break;
+@@ -1321,7 +1325,7 @@ void __init mpic_set_serial_int(struct mpic *mpic, int enable)
+
+ void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
+ {
+- int is_ipi;
++ unsigned int is_ipi;
+ struct mpic *mpic = mpic_find(irq, &is_ipi);
+ unsigned int src = mpic_irq_to_hw(irq);
+ unsigned long flags;
+@@ -1344,7 +1348,7 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
+
+ unsigned int mpic_irq_get_priority(unsigned int irq)
+ {
+- int is_ipi;
++ unsigned int is_ipi;
+ struct mpic *mpic = mpic_find(irq, &is_ipi);
+ unsigned int src = mpic_irq_to_hw(irq);
+ unsigned long flags;
+@@ -1406,11 +1410,6 @@ void mpic_cpu_set_priority(int prio)
+ mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), prio);
+ }
+
+-/*
+- * XXX: someone who knows mpic should check this.
+- * do we need to eoi the ipi including for kexec cpu here (see xics comments)?
+- * or can we reset the mpic in the new kernel?
+- */
+ void mpic_teardown_this_cpu(int secondary)
+ {
+ struct mpic *mpic = mpic_primary;
+@@ -1430,6 +1429,10 @@ void mpic_teardown_this_cpu(int secondary)
+
+ /* Set current processor priority to max */
+ mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf);
++ /* We need to EOI the IPI since not all platforms reset the MPIC
++ * on boot and new interrupts wouldn't get delivered otherwise.
++ */
++ mpic_eoi(mpic);
+
+ spin_unlock_irqrestore(&mpic_lock, flags);
+ }
+diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c
+index efda002..41af122 100644
+--- a/arch/powerpc/sysdev/mv64x60_dev.c
++++ b/arch/powerpc/sysdev/mv64x60_dev.c
+@@ -127,7 +127,7 @@ static int __init mv64x60_mpsc_device_setup(struct device_node *np, int id)
+ if (err)
+ return err;
+
+- prop = of_get_property(np, "block-index", NULL);
++ prop = of_get_property(np, "cell-index", NULL);
+ if (!prop)
+ return -ENODEV;
+ port_number = *(int *)prop;
+@@ -136,6 +136,7 @@ static int __init mv64x60_mpsc_device_setup(struct device_node *np, int id)
+
+ pdata.cache_mgmt = 1; /* All current revs need this set */
+
++ pdata.max_idle = 40; /* default */
+ prop = of_get_property(np, "max_idle", NULL);
+ if (prop)
+ pdata.max_idle = *prop;
+@@ -205,30 +206,24 @@ error:
+ /*
+ * Create mv64x60_eth platform devices
+ */
+-static int __init eth_register_shared_pdev(struct device_node *np)
++static struct platform_device * __init mv64x60_eth_register_shared_pdev(
++ struct device_node *np, int id)
+ {
+ struct platform_device *pdev;
+ struct resource r[1];
+ int err;
+
+- np = of_get_parent(np);
+- if (!np)
+- return -ENODEV;
+-
+ err = of_address_to_resource(np, 0, &r[0]);
+- of_node_put(np);
+ if (err)
+- return err;
++ return ERR_PTR(err);
+
+- pdev = platform_device_register_simple(MV643XX_ETH_SHARED_NAME, 0,
++ pdev = platform_device_register_simple(MV643XX_ETH_SHARED_NAME, id,
+ r, 1);
+- if (IS_ERR(pdev))
+- return PTR_ERR(pdev);
+-
+- return 0;
++ return pdev;
+ }
+
+-static int __init mv64x60_eth_device_setup(struct device_node *np, int id)
++static int __init mv64x60_eth_device_setup(struct device_node *np, int id,
++ struct platform_device *shared_pdev)
+ {
+ struct resource r[1];
+ struct mv643xx_eth_platform_data pdata;
+@@ -239,16 +234,12 @@ static int __init mv64x60_eth_device_setup(struct device_node *np, int id)
+ const phandle *ph;
+ int err;
+
+- /* only register the shared platform device the first time through */
+- if (id == 0 && (err = eth_register_shared_pdev(np)))
+- return err;
+-
+ memset(r, 0, sizeof(r));
+ of_irq_to_resource(np, 0, &r[0]);
+
+ memset(&pdata, 0, sizeof(pdata));
+
+- prop = of_get_property(np, "block-index", NULL);
++ prop = of_get_property(np, "reg", NULL);
+ if (!prop)
+ return -ENODEV;
+ pdata.port_number = *prop;
+@@ -301,7 +292,7 @@ static int __init mv64x60_eth_device_setup(struct device_node *np, int id)
+
+ of_node_put(phy);
+
+- pdev = platform_device_alloc(MV643XX_ETH_NAME, pdata.port_number);
++ pdev = platform_device_alloc(MV643XX_ETH_NAME, id);
+ if (!pdev)
+ return -ENOMEM;
+
+@@ -345,21 +336,17 @@ static int __init mv64x60_i2c_device_setup(struct device_node *np, int id)
+
+ memset(&pdata, 0, sizeof(pdata));
+
++ pdata.freq_m = 8; /* default */
+ prop = of_get_property(np, "freq_m", NULL);
+- if (!prop)
+- return -ENODEV;
+- pdata.freq_m = *prop;
++ if (prop)
++ pdata.freq_m = *prop;
+
++ pdata.freq_m = 3; /* default */
+ prop = of_get_property(np, "freq_n", NULL);
+- if (!prop)
+- return -ENODEV;
+- pdata.freq_n = *prop;
+-
+- prop = of_get_property(np, "timeout", NULL);
+ if (prop)
+- pdata.timeout = *prop;
+- else
+- pdata.timeout = 1000; /* 1 second */
++ pdata.freq_n = *prop;
++
++ pdata.timeout = 1000; /* default: 1 second */
+
+ pdev = platform_device_alloc(MV64XXX_I2C_CTLR_NAME, id);
+ if (!pdev)
+@@ -401,10 +388,7 @@ static int __init mv64x60_wdt_device_setup(struct device_node *np, int id)
+
+ memset(&pdata, 0, sizeof(pdata));
+
+- prop = of_get_property(np, "timeout", NULL);
+- if (!prop)
+- return -ENODEV;
+- pdata.timeout = *prop;
++ pdata.timeout = 10; /* Default: 10 seconds */
+
+ np = of_get_parent(np);
+ if (!np)
+@@ -441,38 +425,64 @@ error:
+
+ static int __init mv64x60_device_setup(void)
+ {
+- struct device_node *np = NULL;
+- int id;
++ struct device_node *np, *np2;
++ struct platform_device *pdev;
++ int id, id2;
+ int err;
+
+ id = 0;
+- for_each_compatible_node(np, "serial", "marvell,mpsc")
+- if ((err = mv64x60_mpsc_device_setup(np, id++)))
+- goto error;
++ for_each_compatible_node(np, "serial", "marvell,mv64360-mpsc") {
++ err = mv64x60_mpsc_device_setup(np, id++);
++ if (err)
++ printk(KERN_ERR "Failed to initialize MV64x60 "
++ "serial device %s: error %d.\n",
++ np->full_name, err);
++ }
+
+ id = 0;
+- for_each_compatible_node(np, "network", "marvell,mv64x60-eth")
+- if ((err = mv64x60_eth_device_setup(np, id++)))
+- goto error;
++ id2 = 0;
++ for_each_compatible_node(np, NULL, "marvell,mv64360-eth-group") {
++ pdev = mv64x60_eth_register_shared_pdev(np, id++);
++ if (IS_ERR(pdev)) {
++ err = PTR_ERR(pdev);
++ printk(KERN_ERR "Failed to initialize MV64x60 "
++ "network block %s: error %d.\n",
++ np->full_name, err);
++ continue;
++ }
++ for_each_child_of_node(np, np2) {
++ if (!of_device_is_compatible(np2,
++ "marvell,mv64360-eth"))
++ continue;
++ err = mv64x60_eth_device_setup(np2, id2++, pdev);
++ if (err)
++ printk(KERN_ERR "Failed to initialize "
++ "MV64x60 network device %s: "
++ "error %d.\n",
++ np2->full_name, err);
++ }
++ }
+
+ id = 0;
+- for_each_compatible_node(np, "i2c", "marvell,mv64x60-i2c")
+- if ((err = mv64x60_i2c_device_setup(np, id++)))
+- goto error;
++ for_each_compatible_node(np, "i2c", "marvell,mv64360-i2c") {
++ err = mv64x60_i2c_device_setup(np, id++);
++ if (err)
++ printk(KERN_ERR "Failed to initialize MV64x60 I2C "
++ "bus %s: error %d.\n",
++ np->full_name, err);
++ }
+
+ /* support up to one watchdog timer */
+- np = of_find_compatible_node(np, NULL, "marvell,mv64x60-wdt");
++ np = of_find_compatible_node(np, NULL, "marvell,mv64360-wdt");
+ if (np) {
+ if ((err = mv64x60_wdt_device_setup(np, id)))
+- goto error;
++ printk(KERN_ERR "Failed to initialize MV64x60 "
++ "Watchdog %s: error %d.\n",
++ np->full_name, err);
+ of_node_put(np);
+ }
+
+ return 0;
+-
+-error:
+- of_node_put(np);
+- return err;
+ }
+ arch_initcall(mv64x60_device_setup);
+
+@@ -489,10 +499,10 @@ static int __init mv64x60_add_mpsc_console(void)
+ if (!np)
+ goto not_mpsc;
+
+- if (!of_device_is_compatible(np, "marvell,mpsc"))
++ if (!of_device_is_compatible(np, "marvell,mv64360-mpsc"))
+ goto not_mpsc;
+
+- prop = of_get_property(np, "block-index", NULL);
++ prop = of_get_property(np, "cell-index", NULL);
+ if (!prop)
+ goto not_mpsc;
+
+diff --git a/arch/powerpc/sysdev/mv64x60_pci.c b/arch/powerpc/sysdev/mv64x60_pci.c
+index d21ab8f..1456015 100644
+--- a/arch/powerpc/sysdev/mv64x60_pci.c
++++ b/arch/powerpc/sysdev/mv64x60_pci.c
+@@ -86,14 +86,14 @@ static int __init mv64x60_sysfs_init(void)
+ struct platform_device *pdev;
+ const unsigned int *prop;
+
+- np = of_find_compatible_node(NULL, NULL, "marvell,mv64x60");
++ np = of_find_compatible_node(NULL, NULL, "marvell,mv64360");
+ if (!np)
+ return 0;
+
+ prop = of_get_property(np, "hs_reg_valid", NULL);
+ of_node_put(np);
+
+- pdev = platform_device_register_simple("marvell,mv64x60", 0, NULL, 0);
++ pdev = platform_device_register_simple("marvell,mv64360", 0, NULL, 0);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+
+@@ -166,6 +166,6 @@ void __init mv64x60_pci_init(void)
+ {
+ struct device_node *np;
+
+- for_each_compatible_node(np, "pci", "marvell,mv64x60-pci")
++ for_each_compatible_node(np, "pci", "marvell,mv64360-pci")
+ mv64x60_add_bridge(np);
+ }
+diff --git a/arch/powerpc/sysdev/mv64x60_pic.c b/arch/powerpc/sysdev/mv64x60_pic.c
+index 19e6ef2..2aa4ed0 100644
+--- a/arch/powerpc/sysdev/mv64x60_pic.c
++++ b/arch/powerpc/sysdev/mv64x60_pic.c
+@@ -238,13 +238,13 @@ void __init mv64x60_init_irq(void)
+ const unsigned int *reg;
+ unsigned long flags;
+
+- np = of_find_compatible_node(NULL, NULL, "marvell,mv64x60-gpp");
++ np = of_find_compatible_node(NULL, NULL, "marvell,mv64360-gpp");
+ reg = of_get_property(np, "reg", &size);
+ paddr = of_translate_address(np, reg);
+ mv64x60_gpp_reg_base = ioremap(paddr, reg[1]);
+ of_node_put(np);
+
+- np = of_find_compatible_node(NULL, NULL, "marvell,mv64x60-pic");
++ np = of_find_compatible_node(NULL, NULL, "marvell,mv64360-pic");
+ reg = of_get_property(np, "reg", &size);
+ paddr = of_translate_address(np, reg);
+ mv64x60_irq_reg_base = ioremap(paddr, reg[1]);
+diff --git a/arch/powerpc/sysdev/mv64x60_udbg.c b/arch/powerpc/sysdev/mv64x60_udbg.c
+index 35c77c7..2792dc8 100644
+--- a/arch/powerpc/sysdev/mv64x60_udbg.c
++++ b/arch/powerpc/sysdev/mv64x60_udbg.c
+@@ -85,7 +85,7 @@ static void mv64x60_udbg_init(void)
+ if (!stdout)
+ return;
+
+- for_each_compatible_node(np, "serial", "marvell,mpsc") {
++ for_each_compatible_node(np, "serial", "marvell,mv64360-mpsc") {
+ if (np == stdout)
+ break;
+ }
+@@ -94,7 +94,7 @@ static void mv64x60_udbg_init(void)
+ if (!np)
+ return;
+
+- block_index = of_get_property(np, "block-index", NULL);
++ block_index = of_get_property(np, "cell-index", NULL);
+ if (!block_index)
+ goto error;
+
+diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
+index 5abfcd1..1814adb 100644
+--- a/arch/powerpc/sysdev/ppc4xx_pci.c
++++ b/arch/powerpc/sysdev/ppc4xx_pci.c
+@@ -527,6 +527,7 @@ static void __init ppc4xx_probe_pcix_bridge(struct device_node *np)
+ *
+ * ibm,plb-pciex-440spe
+ * ibm,plb-pciex-405ex
++ * ibm,plb-pciex-460ex
+ *
+ * Anything else will be rejected for now as they are all subtly
+ * different unfortunately.
+@@ -645,7 +646,7 @@ static int __init ppc440spe_pciex_core_init(struct device_node *np)
+ int time_out = 20;
+
+ /* Set PLL clock receiver to LVPECL */
+- mtdcri(SDR0, PESDR0_PLLLCT1, mfdcri(SDR0, PESDR0_PLLLCT1) | 1 << 28);
++ dcri_clrset(SDR0, PESDR0_PLLLCT1, 0, 1 << 28);
+
+ /* Shouldn't we do all the calibration stuff etc... here ? */
+ if (ppc440spe_pciex_check_reset(np))
+@@ -659,8 +660,7 @@ static int __init ppc440spe_pciex_core_init(struct device_node *np)
+ }
+
+ /* De-assert reset of PCIe PLL, wait for lock */
+- mtdcri(SDR0, PESDR0_PLLLCT1,
+- mfdcri(SDR0, PESDR0_PLLLCT1) & ~(1 << 24));
++ dcri_clrset(SDR0, PESDR0_PLLLCT1, 1 << 24, 0);
+ udelay(3);
+
+ while (time_out) {
+@@ -712,9 +712,8 @@ static int ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+ mtdcri(SDR0, port->sdr_base + PESDRn_440SPE_HSSL7SET1,
+ 0x35000000);
+ }
+- val = mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET);
+- mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET,
+- (val & ~(1 << 24 | 1 << 16)) | 1 << 12);
++ dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET,
++ (1 << 24) | (1 << 16), 1 << 12);
+
+ return 0;
+ }
+@@ -775,6 +774,115 @@ static struct ppc4xx_pciex_hwops ppc440speB_pcie_hwops __initdata =
+ .setup_utl = ppc440speB_pciex_init_utl,
+ };
+
++static int __init ppc460ex_pciex_core_init(struct device_node *np)
++{
++ /* Nothing to do, return 2 ports */
++ return 2;
++}
++
++static int ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
++{
++ u32 val;
++ u32 utlset1;
++
++ if (port->endpoint)
++ val = PTYPE_LEGACY_ENDPOINT << 20;
++ else
++ val = PTYPE_ROOT_PORT << 20;
++
++ if (port->index == 0) {
++ val |= LNKW_X1 << 12;
++ utlset1 = 0x20000000;
++ } else {
++ val |= LNKW_X4 << 12;
++ utlset1 = 0x20101101;
++ }
++
++ mtdcri(SDR0, port->sdr_base + PESDRn_DLPSET, val);
++ mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET1, utlset1);
++ mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET2, 0x01210000);
++
++ switch (port->index) {
++ case 0:
++ mtdcri(SDR0, PESDR0_460EX_L0CDRCTL, 0x00003230);
++ mtdcri(SDR0, PESDR0_460EX_L0DRV, 0x00000136);
++ mtdcri(SDR0, PESDR0_460EX_L0CLK, 0x00000006);
++
++ mtdcri(SDR0, PESDR0_460EX_PHY_CTL_RST,0x10000000);
++ break;
++
++ case 1:
++ mtdcri(SDR0, PESDR1_460EX_L0CDRCTL, 0x00003230);
++ mtdcri(SDR0, PESDR1_460EX_L1CDRCTL, 0x00003230);
++ mtdcri(SDR0, PESDR1_460EX_L2CDRCTL, 0x00003230);
++ mtdcri(SDR0, PESDR1_460EX_L3CDRCTL, 0x00003230);
++ mtdcri(SDR0, PESDR1_460EX_L0DRV, 0x00000136);
++ mtdcri(SDR0, PESDR1_460EX_L1DRV, 0x00000136);
++ mtdcri(SDR0, PESDR1_460EX_L2DRV, 0x00000136);
++ mtdcri(SDR0, PESDR1_460EX_L3DRV, 0x00000136);
++ mtdcri(SDR0, PESDR1_460EX_L0CLK, 0x00000006);
++ mtdcri(SDR0, PESDR1_460EX_L1CLK, 0x00000006);
++ mtdcri(SDR0, PESDR1_460EX_L2CLK, 0x00000006);
++ mtdcri(SDR0, PESDR1_460EX_L3CLK, 0x00000006);
++
++ mtdcri(SDR0, PESDR1_460EX_PHY_CTL_RST,0x10000000);
++ break;
++ }
++
++ mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET,
++ mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET) |
++ (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTPYN));
++
++ /* Poll for PHY reset */
++ /* XXX FIXME add timeout */
++ switch (port->index) {
++ case 0:
++ while (!(mfdcri(SDR0, PESDR0_460EX_RSTSTA) & 0x1))
++ udelay(10);
++ break;
++ case 1:
++ while (!(mfdcri(SDR0, PESDR1_460EX_RSTSTA) & 0x1))
++ udelay(10);
++ break;
++ }
++
++ mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET,
++ (mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET) &
++ ~(PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL)) |
++ PESDRx_RCSSET_RSTPYN);
++
++ port->has_ibpre = 1;
++
++ return 0;
++}
++
++static int ppc460ex_pciex_init_utl(struct ppc4xx_pciex_port *port)
++{
++ dcr_write(port->dcrs, DCRO_PEGPL_SPECIAL, 0x0);
++
++ /*
++ * Set buffer allocations and then assert VRB and TXE.
++ */
++ out_be32(port->utl_base + PEUTL_PBCTL, 0x0800000c);
++ out_be32(port->utl_base + PEUTL_OUTTR, 0x08000000);
++ out_be32(port->utl_base + PEUTL_INTR, 0x02000000);
++ out_be32(port->utl_base + PEUTL_OPDBSZ, 0x04000000);
++ out_be32(port->utl_base + PEUTL_PBBSZ, 0x00000000);
++ out_be32(port->utl_base + PEUTL_IPHBSZ, 0x02000000);
++ out_be32(port->utl_base + PEUTL_IPDBSZ, 0x04000000);
++ out_be32(port->utl_base + PEUTL_RCIRQEN,0x00f00000);
++ out_be32(port->utl_base + PEUTL_PCTL, 0x80800066);
++
++ return 0;
++}
++
++static struct ppc4xx_pciex_hwops ppc460ex_pcie_hwops __initdata =
++{
++ .core_init = ppc460ex_pciex_core_init,
++ .port_init_hw = ppc460ex_pciex_init_port_hw,
++ .setup_utl = ppc460ex_pciex_init_utl,
++};
++
+ #endif /* CONFIG_44x */
+
+ #ifdef CONFIG_40x
+@@ -830,17 +938,9 @@ static int ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+ * PCIe boards don't show this problem.
+ * This has to be re-tested and fixed in a later release!
+ */
+-#if 0 /* XXX FIXME: Not resetting the PHY will leave all resources
+- * configured as done previously by U-Boot. Then Linux will currently
+- * not reassign them. So the PHY reset is now done always. This will
+- * lead to problems with the Atheros PCIe board again.
+- */
+ val = mfdcri(SDR0, port->sdr_base + PESDRn_LOOP);
+ if (!(val & 0x00001000))
+ ppc405ex_pcie_phy_reset(port);
+-#else
+- ppc405ex_pcie_phy_reset(port);
+-#endif
+
+ dcr_write(port->dcrs, DCRO_PEGPL_CFG, 0x10000000); /* guarded on */
+
+@@ -896,6 +996,8 @@ static int __init ppc4xx_pciex_check_core_init(struct device_node *np)
+ else
+ ppc4xx_pciex_hwops = &ppc440speB_pcie_hwops;
+ }
++ if (of_device_is_compatible(np, "ibm,plb-pciex-460ex"))
++ ppc4xx_pciex_hwops = &ppc460ex_pcie_hwops;
+ #endif /* CONFIG_44x */
+ #ifdef CONFIG_40x
+ if (of_device_is_compatible(np, "ibm,plb-pciex-405ex"))
+@@ -1042,8 +1144,7 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port)
+ port->link = 0;
+ }
+
+- mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET,
+- mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET) | 1 << 20);
++ dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET, 0, 1 << 20);
+ msleep(100);
+
+ return 0;
+diff --git a/arch/powerpc/sysdev/ppc4xx_pci.h b/arch/powerpc/sysdev/ppc4xx_pci.h
+index 1c07908..d04e40b 100644
+--- a/arch/powerpc/sysdev/ppc4xx_pci.h
++++ b/arch/powerpc/sysdev/ppc4xx_pci.h
+@@ -271,6 +271,59 @@
+ #define PESDR1_405EX_PHYSTA 0x044C
+
+ /*
++ * 460EX additional DCRs
++ */
++#define PESDR0_460EX_L0BIST 0x0308
++#define PESDR0_460EX_L0BISTSTS 0x0309
++#define PESDR0_460EX_L0CDRCTL 0x030A
++#define PESDR0_460EX_L0DRV 0x030B
++#define PESDR0_460EX_L0REC 0x030C
++#define PESDR0_460EX_L0LPB 0x030D
++#define PESDR0_460EX_L0CLK 0x030E
++#define PESDR0_460EX_PHY_CTL_RST 0x030F
++#define PESDR0_460EX_RSTSTA 0x0310
++#define PESDR0_460EX_OBS 0x0311
++#define PESDR0_460EX_L0ERRC 0x0320
++
++#define PESDR1_460EX_L0BIST 0x0348
++#define PESDR1_460EX_L1BIST 0x0349
++#define PESDR1_460EX_L2BIST 0x034A
++#define PESDR1_460EX_L3BIST 0x034B
++#define PESDR1_460EX_L0BISTSTS 0x034C
++#define PESDR1_460EX_L1BISTSTS 0x034D
++#define PESDR1_460EX_L2BISTSTS 0x034E
++#define PESDR1_460EX_L3BISTSTS 0x034F
++#define PESDR1_460EX_L0CDRCTL 0x0350
++#define PESDR1_460EX_L1CDRCTL 0x0351
++#define PESDR1_460EX_L2CDRCTL 0x0352
++#define PESDR1_460EX_L3CDRCTL 0x0353
++#define PESDR1_460EX_L0DRV 0x0354
++#define PESDR1_460EX_L1DRV 0x0355
++#define PESDR1_460EX_L2DRV 0x0356
++#define PESDR1_460EX_L3DRV 0x0357
++#define PESDR1_460EX_L0REC 0x0358
++#define PESDR1_460EX_L1REC 0x0359
++#define PESDR1_460EX_L2REC 0x035A
++#define PESDR1_460EX_L3REC 0x035B
++#define PESDR1_460EX_L0LPB 0x035C
++#define PESDR1_460EX_L1LPB 0x035D
++#define PESDR1_460EX_L2LPB 0x035E
++#define PESDR1_460EX_L3LPB 0x035F
++#define PESDR1_460EX_L0CLK 0x0360
++#define PESDR1_460EX_L1CLK 0x0361
++#define PESDR1_460EX_L2CLK 0x0362
++#define PESDR1_460EX_L3CLK 0x0363
++#define PESDR1_460EX_PHY_CTL_RST 0x0364
++#define PESDR1_460EX_RSTSTA 0x0365
++#define PESDR1_460EX_OBS 0x0366
++#define PESDR1_460EX_L0ERRC 0x0368
++#define PESDR1_460EX_L1ERRC 0x0369
++#define PESDR1_460EX_L2ERRC 0x036A
++#define PESDR1_460EX_L3ERRC 0x036B
++#define PESDR0_460EX_IHS1 0x036C
++#define PESDR0_460EX_IHS2 0x036D
++
++/*
+ * Of the above, some are common offsets from the base
+ */
+ #define PESDRn_UTLSET1 0x00
+@@ -353,6 +406,12 @@
+ #define PECFG_POM2LAL 0x390
+ #define PECFG_POM2LAH 0x394
+
++/* SDR Bit Mappings */
++#define PESDRx_RCSSET_HLDPLB 0x10000000
++#define PESDRx_RCSSET_RSTGU 0x01000000
++#define PESDRx_RCSSET_RDY 0x00100000
++#define PESDRx_RCSSET_RSTDL 0x00010000
++#define PESDRx_RCSSET_RSTPYN 0x00001000
+
+ enum
+ {
+diff --git a/arch/powerpc/sysdev/ppc4xx_soc.c b/arch/powerpc/sysdev/ppc4xx_soc.c
+new file mode 100644
+index 0000000..5b32adc
+--- /dev/null
++++ b/arch/powerpc/sysdev/ppc4xx_soc.c
+@@ -0,0 +1,200 @@
++/*
++ * IBM/AMCC PPC4xx SoC setup code
++ *
++ * Copyright 2008 DENX Software Engineering, Stefan Roese <sr at denx.de>
++ *
++ * L2 cache routines cloned from arch/ppc/syslib/ibm440gx_common.c which is:
++ * Eugene Surovegin <eugene.surovegin at zultys.com> or <ebs at ebshome.net>
++ * Copyright (c) 2003 - 2006 Zultys Technologies
++ *
++ * 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/stddef.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/errno.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <linux/of_platform.h>
++
++#include <asm/dcr.h>
++#include <asm/dcr-regs.h>
++#include <asm/reg.h>
++
++static u32 dcrbase_l2c;
++
++/*
++ * L2-cache
++ */
++
++/* Issue L2C diagnostic command */
++static inline u32 l2c_diag(u32 addr)
++{
++ mtdcr(dcrbase_l2c + DCRN_L2C0_ADDR, addr);
++ mtdcr(dcrbase_l2c + DCRN_L2C0_CMD, L2C_CMD_DIAG);
++ while (!(mfdcr(dcrbase_l2c + DCRN_L2C0_SR) & L2C_SR_CC))
++ ;
++
++ return mfdcr(dcrbase_l2c + DCRN_L2C0_DATA);
++}
++
++static irqreturn_t l2c_error_handler(int irq, void *dev)
++{
++ u32 sr = mfdcr(dcrbase_l2c + DCRN_L2C0_SR);
++
++ if (sr & L2C_SR_CPE) {
++ /* Read cache trapped address */
++ u32 addr = l2c_diag(0x42000000);
++ printk(KERN_EMERG "L2C: Cache Parity Error, addr[16:26] = 0x%08x\n",
++ addr);
++ }
++ if (sr & L2C_SR_TPE) {
++ /* Read tag trapped address */
++ u32 addr = l2c_diag(0x82000000) >> 16;
++ printk(KERN_EMERG "L2C: Tag Parity Error, addr[16:26] = 0x%08x\n",
++ addr);
++ }
++
++ /* Clear parity errors */
++ if (sr & (L2C_SR_CPE | L2C_SR_TPE)){
++ mtdcr(dcrbase_l2c + DCRN_L2C0_ADDR, 0);
++ mtdcr(dcrbase_l2c + DCRN_L2C0_CMD, L2C_CMD_CCP | L2C_CMD_CTE);
++ } else {
++ printk(KERN_EMERG "L2C: LRU error\n");
++ }
++
++ return IRQ_HANDLED;
++}
++
++static int __init ppc4xx_l2c_probe(void)
++{
++ struct device_node *np;
++ u32 r;
++ unsigned long flags;
++ int irq;
++ const u32 *dcrreg;
++ u32 dcrbase_isram;
++ int len;
++ const u32 *prop;
++ u32 l2_size;
++
++ np = of_find_compatible_node(NULL, NULL, "ibm,l2-cache");
++ if (!np)
++ return 0;
++
++ /* Get l2 cache size */
++ prop = of_get_property(np, "cache-size", NULL);
++ if (prop == NULL) {
++ printk(KERN_ERR "%s: Can't get cache-size!\n", np->full_name);
++ of_node_put(np);
++ return -ENODEV;
++ }
++ l2_size = prop[0];
++
++ /* Map DCRs */
++ dcrreg = of_get_property(np, "dcr-reg", &len);
++ if (!dcrreg || (len != 4 * sizeof(u32))) {
++ printk(KERN_ERR "%s: Can't get DCR register base !",
++ np->full_name);
++ of_node_put(np);
++ return -ENODEV;
++ }
++ dcrbase_isram = dcrreg[0];
++ dcrbase_l2c = dcrreg[2];
++
++ /* Get and map irq number from device tree */
++ irq = irq_of_parse_and_map(np, 0);
++ if (irq == NO_IRQ) {
++ printk(KERN_ERR "irq_of_parse_and_map failed\n");
++ of_node_put(np);
++ return -ENODEV;
++ }
++
++ /* Install error handler */
++ if (request_irq(irq, l2c_error_handler, IRQF_DISABLED, "L2C", 0) < 0) {
++ printk(KERN_ERR "Cannot install L2C error handler"
++ ", cache is not enabled\n");
++ of_node_put(np);
++ return -ENODEV;
++ }
++
++ local_irq_save(flags);
++ asm volatile ("sync" ::: "memory");
++
++ /* Disable SRAM */
++ mtdcr(dcrbase_isram + DCRN_SRAM0_DPC,
++ mfdcr(dcrbase_isram + DCRN_SRAM0_DPC) & ~SRAM_DPC_ENABLE);
++ mtdcr(dcrbase_isram + DCRN_SRAM0_SB0CR,
++ mfdcr(dcrbase_isram + DCRN_SRAM0_SB0CR) & ~SRAM_SBCR_BU_MASK);
++ mtdcr(dcrbase_isram + DCRN_SRAM0_SB1CR,
++ mfdcr(dcrbase_isram + DCRN_SRAM0_SB1CR) & ~SRAM_SBCR_BU_MASK);
++ mtdcr(dcrbase_isram + DCRN_SRAM0_SB2CR,
++ mfdcr(dcrbase_isram + DCRN_SRAM0_SB2CR) & ~SRAM_SBCR_BU_MASK);
++ mtdcr(dcrbase_isram + DCRN_SRAM0_SB3CR,
++ mfdcr(dcrbase_isram + DCRN_SRAM0_SB3CR) & ~SRAM_SBCR_BU_MASK);
++
++ /* Enable L2_MODE without ICU/DCU */
++ r = mfdcr(dcrbase_l2c + DCRN_L2C0_CFG) &
++ ~(L2C_CFG_ICU | L2C_CFG_DCU | L2C_CFG_SS_MASK);
++ r |= L2C_CFG_L2M | L2C_CFG_SS_256;
++ mtdcr(dcrbase_l2c + DCRN_L2C0_CFG, r);
++
++ mtdcr(dcrbase_l2c + DCRN_L2C0_ADDR, 0);
++
++ /* Hardware Clear Command */
++ mtdcr(dcrbase_l2c + DCRN_L2C0_CMD, L2C_CMD_HCC);
++ while (!(mfdcr(dcrbase_l2c + DCRN_L2C0_SR) & L2C_SR_CC))
++ ;
++
++ /* Clear Cache Parity and Tag Errors */
++ mtdcr(dcrbase_l2c + DCRN_L2C0_CMD, L2C_CMD_CCP | L2C_CMD_CTE);
++
++ /* Enable 64G snoop region starting at 0 */
++ r = mfdcr(dcrbase_l2c + DCRN_L2C0_SNP0) &
++ ~(L2C_SNP_BA_MASK | L2C_SNP_SSR_MASK);
++ r |= L2C_SNP_SSR_32G | L2C_SNP_ESR;
++ mtdcr(dcrbase_l2c + DCRN_L2C0_SNP0, r);
++
++ r = mfdcr(dcrbase_l2c + DCRN_L2C0_SNP1) &
++ ~(L2C_SNP_BA_MASK | L2C_SNP_SSR_MASK);
++ r |= 0x80000000 | L2C_SNP_SSR_32G | L2C_SNP_ESR;
++ mtdcr(dcrbase_l2c + DCRN_L2C0_SNP1, r);
++
++ asm volatile ("sync" ::: "memory");
++
++ /* Enable ICU/DCU ports */
++ r = mfdcr(dcrbase_l2c + DCRN_L2C0_CFG);
++ r &= ~(L2C_CFG_DCW_MASK | L2C_CFG_PMUX_MASK | L2C_CFG_PMIM
++ | L2C_CFG_TPEI | L2C_CFG_CPEI | L2C_CFG_NAM | L2C_CFG_NBRM);
++ r |= L2C_CFG_ICU | L2C_CFG_DCU | L2C_CFG_TPC | L2C_CFG_CPC | L2C_CFG_FRAN
++ | L2C_CFG_CPIM | L2C_CFG_TPIM | L2C_CFG_LIM | L2C_CFG_SMCM;
++
++ /* Check for 460EX/GT special handling */
++ if (of_device_is_compatible(np, "ibm,l2-cache-460ex"))
++ r |= L2C_CFG_RDBW;
++
++ mtdcr(dcrbase_l2c + DCRN_L2C0_CFG, r);
++
++ asm volatile ("sync; isync" ::: "memory");
++ local_irq_restore(flags);
++
++ printk(KERN_INFO "%dk L2-cache enabled\n", l2_size >> 10);
++
++ of_node_put(np);
++ return 0;
++}
++arch_initcall(ppc4xx_l2c_probe);
++
++/*
++ * At present, this routine just applies a system reset.
++ */
++void ppc4xx_reset_system(char *cmd)
++{
++ mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_RST_SYSTEM);
++ while (1)
++ ; /* Just in case the reset doesn't work */
++}
+diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
+index cc81fd1..cff550e 100644
+--- a/arch/powerpc/sysdev/qe_lib/qe.c
++++ b/arch/powerpc/sysdev/qe_lib/qe.c
+@@ -55,7 +55,7 @@ struct qe_snum {
+ /* We allocate this here because it is used almost exclusively for
+ * the communication processor devices.
+ */
+-struct qe_immap *qe_immr = NULL;
++struct qe_immap __iomem *qe_immr;
+ EXPORT_SYMBOL(qe_immr);
+
+ static struct qe_snum snums[QE_NUM_OF_SNUM]; /* Dynamically allocated SNUMs */
+@@ -156,7 +156,7 @@ EXPORT_SYMBOL(qe_issue_cmd);
+ */
+ static unsigned int brg_clk = 0;
+
+-unsigned int get_brg_clk(void)
++unsigned int qe_get_brg_clk(void)
+ {
+ struct device_node *qe;
+ unsigned int size;
+@@ -180,6 +180,7 @@ unsigned int get_brg_clk(void)
+
+ return brg_clk;
+ }
++EXPORT_SYMBOL(qe_get_brg_clk);
+
+ /* Program the BRG to the given sampling rate and multiplier
+ *
+@@ -197,7 +198,7 @@ int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier)
+ if ((brg < QE_BRG1) || (brg > QE_BRG16))
+ return -EINVAL;
+
+- divisor = get_brg_clk() / (rate * multiplier);
++ divisor = qe_get_brg_clk() / (rate * multiplier);
+
+ if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
+ div16 = QE_BRGC_DIV16;
+@@ -415,12 +416,6 @@ void qe_muram_dump(void)
+ }
+ EXPORT_SYMBOL(qe_muram_dump);
+
+-void *qe_muram_addr(unsigned long offset)
+-{
+- return (void *)&qe_immr->muram[offset];
+-}
+-EXPORT_SYMBOL(qe_muram_addr);
+-
+ /* The maximum number of RISCs we support */
+ #define MAX_QE_RISC 2
+
+diff --git a/arch/powerpc/sysdev/qe_lib/qe_io.c b/arch/powerpc/sysdev/qe_lib/qe_io.c
+index e53ea4d..93916a4 100644
+--- a/arch/powerpc/sysdev/qe_lib/qe_io.c
++++ b/arch/powerpc/sysdev/qe_lib/qe_io.c
+@@ -22,6 +22,7 @@
+ #include <linux/ioport.h>
+
+ #include <asm/io.h>
++#include <asm/qe.h>
+ #include <asm/prom.h>
+ #include <sysdev/fsl_soc.h>
+
+@@ -41,7 +42,7 @@ struct port_regs {
+ #endif
+ };
+
+-static struct port_regs *par_io = NULL;
++static struct port_regs __iomem *par_io;
+ static int num_par_io_ports = 0;
+
+ int par_io_init(struct device_node *np)
+@@ -165,7 +166,7 @@ int par_io_of_config(struct device_node *np)
+ }
+
+ ph = of_get_property(np, "pio-handle", NULL);
+- if (ph == 0) {
++ if (ph == NULL) {
+ printk(KERN_ERR "pio-handle not available \n");
+ return -1;
+ }
+@@ -200,7 +201,7 @@ static void dump_par_io(void)
+ {
+ unsigned int i;
+
+- printk(KERN_INFO "%s: par_io=%p\n", __FUNCTION__, par_io);
++ printk(KERN_INFO "%s: par_io=%p\n", __func__, par_io);
+ for (i = 0; i < num_par_io_ports; i++) {
+ printk(KERN_INFO " cpodr[%u]=%08x\n", i,
+ in_be32(&par_io[i].cpodr));
+diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
+index 3223acb..bcf88e6 100644
+--- a/arch/powerpc/sysdev/qe_lib/ucc_fast.c
++++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
+@@ -148,57 +148,57 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
+
+ /* check if the UCC port number is in range. */
+ if ((uf_info->ucc_num < 0) || (uf_info->ucc_num > UCC_MAX_NUM - 1)) {
+- printk(KERN_ERR "%s: illegal UCC number\n", __FUNCTION__);
++ printk(KERN_ERR "%s: illegal UCC number\n", __func__);
+ return -EINVAL;
+ }
+
+ /* Check that 'max_rx_buf_length' is properly aligned (4). */
+ if (uf_info->max_rx_buf_length & (UCC_FAST_MRBLR_ALIGNMENT - 1)) {
+ printk(KERN_ERR "%s: max_rx_buf_length not aligned\n",
+- __FUNCTION__);
++ __func__);
+ return -EINVAL;
+ }
+
+ /* Validate Virtual Fifo register values */
+ if (uf_info->urfs < UCC_FAST_URFS_MIN_VAL) {
+- printk(KERN_ERR "%s: urfs is too small\n", __FUNCTION__);
++ printk(KERN_ERR "%s: urfs is too small\n", __func__);
+ return -EINVAL;
+ }
+
+ if (uf_info->urfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
+- printk(KERN_ERR "%s: urfs is not aligned\n", __FUNCTION__);
++ printk(KERN_ERR "%s: urfs is not aligned\n", __func__);
+ return -EINVAL;
+ }
+
+ if (uf_info->urfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
+- printk(KERN_ERR "%s: urfet is not aligned.\n", __FUNCTION__);
++ printk(KERN_ERR "%s: urfet is not aligned.\n", __func__);
+ return -EINVAL;
+ }
+
+ if (uf_info->urfset & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
+- printk(KERN_ERR "%s: urfset is not aligned\n", __FUNCTION__);
++ printk(KERN_ERR "%s: urfset is not aligned\n", __func__);
+ return -EINVAL;
+ }
+
+ if (uf_info->utfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
+- printk(KERN_ERR "%s: utfs is not aligned\n", __FUNCTION__);
++ printk(KERN_ERR "%s: utfs is not aligned\n", __func__);
+ return -EINVAL;
+ }
+
+ if (uf_info->utfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
+- printk(KERN_ERR "%s: utfet is not aligned\n", __FUNCTION__);
++ printk(KERN_ERR "%s: utfet is not aligned\n", __func__);
+ return -EINVAL;
+ }
+
+ if (uf_info->utftt & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
+- printk(KERN_ERR "%s: utftt is not aligned\n", __FUNCTION__);
++ printk(KERN_ERR "%s: utftt is not aligned\n", __func__);
+ return -EINVAL;
+ }
+
+ uccf = kzalloc(sizeof(struct ucc_fast_private), GFP_KERNEL);
+ if (!uccf) {
+ printk(KERN_ERR "%s: Cannot allocate private data\n",
+- __FUNCTION__);
++ __func__);
+ return -ENOMEM;
+ }
+
+@@ -207,7 +207,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
+ /* Set the PHY base address */
+ uccf->uf_regs = ioremap(uf_info->regs, sizeof(struct ucc_fast));
+ if (uccf->uf_regs == NULL) {
+- printk(KERN_ERR "%s: Cannot map UCC registers\n", __FUNCTION__);
++ printk(KERN_ERR "%s: Cannot map UCC registers\n", __func__);
+ return -ENOMEM;
+ }
+
+@@ -230,7 +230,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
+ /* Set UCC to fast type */
+ ret = ucc_set_type(uf_info->ucc_num, UCC_SPEED_TYPE_FAST);
+ if (ret) {
+- printk(KERN_ERR "%s: cannot set UCC type\n", __FUNCTION__);
++ printk(KERN_ERR "%s: cannot set UCC type\n", __func__);
+ ucc_fast_free(uccf);
+ return ret;
+ }
+@@ -270,7 +270,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
+ qe_muram_alloc(uf_info->utfs, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
+ if (IS_ERR_VALUE(uccf->ucc_fast_tx_virtual_fifo_base_offset)) {
+ printk(KERN_ERR "%s: cannot allocate MURAM for TX FIFO\n",
+- __FUNCTION__);
++ __func__);
+ uccf->ucc_fast_tx_virtual_fifo_base_offset = 0;
+ ucc_fast_free(uccf);
+ return -ENOMEM;
+@@ -283,7 +283,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
+ UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
+ if (IS_ERR_VALUE(uccf->ucc_fast_rx_virtual_fifo_base_offset)) {
+ printk(KERN_ERR "%s: cannot allocate MURAM for RX FIFO\n",
+- __FUNCTION__);
++ __func__);
+ uccf->ucc_fast_rx_virtual_fifo_base_offset = 0;
+ ucc_fast_free(uccf);
+ return -ENOMEM;
+@@ -314,7 +314,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
+ ucc_set_qe_mux_rxtx(uf_info->ucc_num, uf_info->rx_clock,
+ COMM_DIR_RX)) {
+ printk(KERN_ERR "%s: illegal value for RX clock\n",
+- __FUNCTION__);
++ __func__);
+ ucc_fast_free(uccf);
+ return -EINVAL;
+ }
+@@ -323,7 +323,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
+ ucc_set_qe_mux_rxtx(uf_info->ucc_num, uf_info->tx_clock,
+ COMM_DIR_TX)) {
+ printk(KERN_ERR "%s: illegal value for TX clock\n",
+- __FUNCTION__);
++ __func__);
+ ucc_fast_free(uccf);
+ return -EINVAL;
+ }
+diff --git a/arch/powerpc/sysdev/qe_lib/ucc_slow.c b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
+index b2870b2..a578bc7 100644
+--- a/arch/powerpc/sysdev/qe_lib/ucc_slow.c
++++ b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
+@@ -142,7 +142,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
+
+ /* check if the UCC port number is in range. */
+ if ((us_info->ucc_num < 0) || (us_info->ucc_num > UCC_MAX_NUM - 1)) {
+- printk(KERN_ERR "%s: illegal UCC number\n", __FUNCTION__);
++ printk(KERN_ERR "%s: illegal UCC number\n", __func__);
+ return -EINVAL;
+ }
+
+@@ -161,7 +161,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
+ uccs = kzalloc(sizeof(struct ucc_slow_private), GFP_KERNEL);
+ if (!uccs) {
+ printk(KERN_ERR "%s: Cannot allocate private data\n",
+- __FUNCTION__);
++ __func__);
+ return -ENOMEM;
+ }
+
+@@ -170,7 +170,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
+ /* Set the PHY base address */
+ uccs->us_regs = ioremap(us_info->regs, sizeof(struct ucc_slow));
+ if (uccs->us_regs == NULL) {
+- printk(KERN_ERR "%s: Cannot map UCC registers\n", __FUNCTION__);
++ printk(KERN_ERR "%s: Cannot map UCC registers\n", __func__);
+ return -ENOMEM;
+ }
+
+@@ -189,7 +189,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
+ uccs->us_pram_offset =
+ qe_muram_alloc(UCC_SLOW_PRAM_SIZE, ALIGNMENT_OF_UCC_SLOW_PRAM);
+ if (IS_ERR_VALUE(uccs->us_pram_offset)) {
+- printk(KERN_ERR "%s: cannot allocate MURAM for PRAM", __FUNCTION__);
++ printk(KERN_ERR "%s: cannot allocate MURAM for PRAM", __func__);
+ ucc_slow_free(uccs);
+ return -ENOMEM;
+ }
+@@ -202,7 +202,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
+ /* Set UCC to slow type */
+ ret = ucc_set_type(us_info->ucc_num, UCC_SPEED_TYPE_SLOW);
+ if (ret) {
+- printk(KERN_ERR "%s: cannot set UCC type", __FUNCTION__);
++ printk(KERN_ERR "%s: cannot set UCC type", __func__);
+ ucc_slow_free(uccs);
+ return ret;
+ }
+@@ -216,7 +216,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
+ qe_muram_alloc(us_info->rx_bd_ring_len * sizeof(struct qe_bd),
+ QE_ALIGNMENT_OF_BD);
+ if (IS_ERR_VALUE(uccs->rx_base_offset)) {
+- printk(KERN_ERR "%s: cannot allocate %u RX BDs\n", __FUNCTION__,
++ printk(KERN_ERR "%s: cannot allocate %u RX BDs\n", __func__,
+ us_info->rx_bd_ring_len);
+ uccs->rx_base_offset = 0;
+ ucc_slow_free(uccs);
+@@ -227,7 +227,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
+ qe_muram_alloc(us_info->tx_bd_ring_len * sizeof(struct qe_bd),
+ QE_ALIGNMENT_OF_BD);
+ if (IS_ERR_VALUE(uccs->tx_base_offset)) {
+- printk(KERN_ERR "%s: cannot allocate TX BDs", __FUNCTION__);
++ printk(KERN_ERR "%s: cannot allocate TX BDs", __func__);
+ uccs->tx_base_offset = 0;
+ ucc_slow_free(uccs);
+ return -ENOMEM;
+@@ -317,7 +317,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
+ if (ucc_set_qe_mux_rxtx(us_info->ucc_num, us_info->rx_clock,
+ COMM_DIR_RX)) {
+ printk(KERN_ERR "%s: illegal value for RX clock\n",
+- __FUNCTION__);
++ __func__);
+ ucc_slow_free(uccs);
+ return -EINVAL;
+ }
+@@ -325,7 +325,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
+ if (ucc_set_qe_mux_rxtx(us_info->ucc_num, us_info->tx_clock,
+ COMM_DIR_TX)) {
+ printk(KERN_ERR "%s: illegal value for TX clock\n",
+- __FUNCTION__);
++ __func__);
+ ucc_slow_free(uccs);
+ return -EINVAL;
+ }
+diff --git a/arch/powerpc/sysdev/rtc_cmos_setup.c b/arch/powerpc/sysdev/rtc_cmos_setup.c
+index 0c9ac7e..c09ddc0 100644
+--- a/arch/powerpc/sysdev/rtc_cmos_setup.c
++++ b/arch/powerpc/sysdev/rtc_cmos_setup.c
+@@ -56,3 +56,5 @@ static int __init add_rtc(void)
+ return 0;
+ }
+ fs_initcall(add_rtc);
++
++MODULE_LICENSE("GPL");
+diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c
+index be2808a..d4d15aa 100644
+--- a/arch/powerpc/sysdev/tsi108_dev.c
++++ b/arch/powerpc/sysdev/tsi108_dev.c
+@@ -84,7 +84,7 @@ static int __init tsi108_eth_of_init(void)
+
+ ret = of_address_to_resource(np, 0, &r[0]);
+ DBG("%s: name:start->end = %s:0x%lx-> 0x%lx\n",
+- __FUNCTION__,r[0].name, r[0].start, r[0].end);
++ __func__,r[0].name, r[0].start, r[0].end);
+ if (ret)
+ goto err;
+
+@@ -93,7 +93,7 @@ static int __init tsi108_eth_of_init(void)
+ r[1].end = irq_of_parse_and_map(np, 0);
+ r[1].flags = IORESOURCE_IRQ;
+ DBG("%s: name:start->end = %s:0x%lx-> 0x%lx\n",
+- __FUNCTION__,r[1].name, r[1].start, r[1].end);
++ __func__,r[1].name, r[1].start, r[1].end);
+
+ tsi_eth_dev =
+ platform_device_register_simple("tsi-ethernet", i++, &r[0],
+diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c
+index 31d3d33..ac1a72d 100644
+--- a/arch/powerpc/sysdev/tsi108_pci.c
++++ b/arch/powerpc/sysdev/tsi108_pci.c
+@@ -207,7 +207,7 @@ int __init tsi108_setup_pci(struct device_node *dev, u32 cfg_phys, int primary)
+ /* PCI Config mapping */
+ tsi108_pci_cfg_base = (u32)ioremap(cfg_phys, TSI108_PCI_CFG_SIZE);
+ tsi108_pci_cfg_phys = cfg_phys;
+- DBG("TSI_PCI: %s tsi108_pci_cfg_base=0x%x\n", __FUNCTION__,
++ DBG("TSI_PCI: %s tsi108_pci_cfg_base=0x%x\n", __func__,
+ tsi108_pci_cfg_base);
+
+ /* Fetch host bridge registers address */
+@@ -395,7 +395,7 @@ static int pci_irq_host_xlate(struct irq_host *h, struct device_node *ct,
+ static int pci_irq_host_map(struct irq_host *h, unsigned int virq,
+ irq_hw_number_t hw)
+ { unsigned int irq;
+- DBG("%s(%d, 0x%lx)\n", __FUNCTION__, virq, hw);
++ DBG("%s(%d, 0x%lx)\n", __func__, virq, hw);
+ if ((virq >= 1) && (virq <= 4)){
+ irq = virq + IRQ_PCI_INTAD_BASE - 1;
+ get_irq_desc(irq)->status |= IRQ_LEVEL;
+diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
+index a34172d..52c7478 100644
+--- a/arch/powerpc/xmon/xmon.c
++++ b/arch/powerpc/xmon/xmon.c
+@@ -45,7 +45,6 @@
+ #ifdef CONFIG_PPC64
+ #include <asm/hvcall.h>
+ #include <asm/paca.h>
+-#include <asm/iseries/it_lp_reg_save.h>
+ #endif
+
+ #include "nonstdio.h"
+@@ -1244,15 +1243,12 @@ static void get_function_bounds(unsigned long pc, unsigned long *startp,
+
+ static int xmon_depth_to_print = 64;
+
+-#ifdef CONFIG_PPC64
+-#define LRSAVE_OFFSET 0x10
+-#define REG_FRAME_MARKER 0x7265677368657265ul /* "regshere" */
+-#define MARKER_OFFSET 0x60
++#define LRSAVE_OFFSET (STACK_FRAME_LR_SAVE * sizeof(unsigned long))
++#define MARKER_OFFSET (STACK_FRAME_MARKER * sizeof(unsigned long))
++
++#ifdef __powerpc64__
+ #define REGS_OFFSET 0x70
+ #else
+-#define LRSAVE_OFFSET 4
+-#define REG_FRAME_MARKER 0x72656773
+-#define MARKER_OFFSET 8
+ #define REGS_OFFSET 16
+ #endif
+
+@@ -1318,7 +1314,7 @@ static void xmon_show_stack(unsigned long sp, unsigned long lr,
+ /* Look for "regshere" marker to see if this is
+ an exception frame. */
+ if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
+- && marker == REG_FRAME_MARKER) {
++ && marker == STACK_FRAME_REGS_MARKER) {
+ if (mread(sp + REGS_OFFSET, ®s, sizeof(regs))
+ != sizeof(regs)) {
+ printf("Couldn't read registers at %lx\n",
+@@ -1598,7 +1594,6 @@ void super_regs(void)
+ if (firmware_has_feature(FW_FEATURE_ISERIES)) {
+ struct paca_struct *ptrPaca;
+ struct lppaca *ptrLpPaca;
+- struct ItLpRegSave *ptrLpRegSave;
+
+ /* Dump out relevant Paca data areas. */
+ printf("Paca: \n");
+@@ -1611,15 +1606,6 @@ void super_regs(void)
+ printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n",
+ ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4);
+ printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5);
+-
+- printf(" Local Processor Register Save Area (LpRegSave): \n");
+- ptrLpRegSave = ptrPaca->reg_save_ptr;
+- printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n",
+- ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0);
+- printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n",
+- ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3);
+- printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n",
+- ptrLpRegSave->xMSR, ptrLpRegSave->xNIA);
+ }
+ #endif
+
+diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c
+index bcc3aa9..d38b57e 100644
+--- a/arch/ppc/8260_io/fcc_enet.c
++++ b/arch/ppc/8260_io/fcc_enet.c
+@@ -165,9 +165,6 @@ static int fcc_enet_set_mac_address(struct net_device *dev, void *addr);
+ #ifdef CONFIG_SBC82xx
+ #define F1_RXCLK 9
+ #define F1_TXCLK 10
+-#elif defined(CONFIG_ADS8272)
+-#define F1_RXCLK 11
+-#define F1_TXCLK 10
+ #else
+ #define F1_RXCLK 12
+ #define F1_TXCLK 11
+@@ -175,13 +172,8 @@ static int fcc_enet_set_mac_address(struct net_device *dev, void *addr);
+
+ /* FCC2 Clock Source Configuration. There are board specific.
+ Can only choose from CLK13-16 */
+-#ifdef CONFIG_ADS8272
+-#define F2_RXCLK 15
+-#define F2_TXCLK 16
+-#else
+ #define F2_RXCLK 13
+ #define F2_TXCLK 14
+-#endif
+
+ /* FCC3 Clock Source Configuration. There are board specific.
+ Can only choose from CLK13-16 */
+@@ -289,10 +281,7 @@ static int fcc_enet_set_mac_address(struct net_device *dev, void *addr);
+ /* TQM8260 has MDIO and MDCK on PC30 and PC31 respectively */
+ #define PC_MDIO ((uint)0x00000002)
+ #define PC_MDCK ((uint)0x00000001)
+-#elif defined(CONFIG_ADS8272)
+-#define PC_MDIO ((uint)0x00002000)
+-#define PC_MDCK ((uint)0x00001000)
+-#elif defined(CONFIG_EST8260) || defined(CONFIG_ADS8260) || defined(CONFIG_PQ2FADS)
++#elif defined(CONFIG_EST8260) || defined(CONFIG_ADS8260)
+ #define PC_MDIO ((uint)0x00400000)
+ #define PC_MDCK ((uint)0x00200000)
+ #else
+@@ -2118,11 +2107,6 @@ init_fcc_startup(fcc_info_t *fip, struct net_device *dev)
+ printk("Can't get FCC IRQ %d\n", fip->fc_interrupt);
+
+ #ifdef PHY_INTERRUPT
+-#ifdef CONFIG_ADS8272
+- if (request_irq(PHY_INTERRUPT, mii_link_interrupt, IRQF_SHARED,
+- "mii", dev) < 0)
+- printk(KERN_CRIT "Can't get MII IRQ %d\n", PHY_INTERRUPT);
+-#else
+ /* Make IRQn edge triggered. This does not work if PHY_INTERRUPT is
+ * on Port C.
+ */
+@@ -2132,7 +2116,6 @@ init_fcc_startup(fcc_info_t *fip, struct net_device *dev)
+ if (request_irq(PHY_INTERRUPT, mii_link_interrupt, 0,
+ "mii", dev) < 0)
+ printk(KERN_CRIT "Can't get MII IRQ %d\n", PHY_INTERRUPT);
+-#endif
+ #endif /* PHY_INTERRUPT */
+
+ /* Set GFMR to enable Ethernet operating mode.
+diff --git a/arch/ppc/8xx_io/commproc.c b/arch/ppc/8xx_io/commproc.c
+index 9d656de..752443d 100644
+--- a/arch/ppc/8xx_io/commproc.c
++++ b/arch/ppc/8xx_io/commproc.c
+@@ -43,7 +43,7 @@
+ ({ \
+ u32 offset = offsetof(immap_t, member); \
+ void *addr = ioremap (IMAP_ADDR + offset, \
+- sizeof( ((immap_t*)0)->member)); \
++ FIELD_SIZEOF(immap_t, member)); \
+ addr; \
+ })
+
+diff --git a/arch/ppc/8xx_io/enet.c b/arch/ppc/8xx_io/enet.c
+index c6d047a..5899aea 100644
+--- a/arch/ppc/8xx_io/enet.c
++++ b/arch/ppc/8xx_io/enet.c
+@@ -946,29 +946,6 @@ static int __init scc_enet_init(void)
+ *((volatile uint *)BCSR1) &= ~BCSR1_ETHEN;
+ #endif
+
+-#ifdef CONFIG_MPC885ADS
+-
+- /* Deassert PHY reset and enable the PHY.
+- */
+- {
+- volatile uint __iomem *bcsr = ioremap(BCSR_ADDR, BCSR_SIZE);
+- uint tmp;
+-
+- tmp = in_be32(bcsr + 1 /* BCSR1 */);
+- tmp |= BCSR1_ETHEN;
+- out_be32(bcsr + 1, tmp);
+- tmp = in_be32(bcsr + 4 /* BCSR4 */);
+- tmp |= BCSR4_ETH10_RST;
+- out_be32(bcsr + 4, tmp);
+- iounmap(bcsr);
+- }
+-
+- /* On MPC885ADS SCC ethernet PHY defaults to the full duplex mode
+- * upon reset. SCC is set to half duplex by default. So this
+- * inconsistency should be better fixed by the software.
+- */
+-#endif
+-
+ dev->base_addr = (unsigned long)ep;
+ #if 0
+ dev->name = "CPM_ENET";
+diff --git a/arch/ppc/8xx_io/fec.c b/arch/ppc/8xx_io/fec.c
+index 11b0aa6..2c604d4 100644
+--- a/arch/ppc/8xx_io/fec.c
++++ b/arch/ppc/8xx_io/fec.c
+@@ -199,7 +199,6 @@ static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
+ #ifdef CONFIG_USE_MDIO
+ static void fec_enet_mii(struct net_device *dev);
+ #endif /* CONFIG_USE_MDIO */
+-static irqreturn_t fec_enet_interrupt(int irq, void * dev_id);
+ #ifdef CONFIG_FEC_PACKETHOOK
+ static void fec_enet_tx(struct net_device *dev, __u32 regval);
+ static void fec_enet_rx(struct net_device *dev, __u32 regval);
+@@ -472,7 +471,7 @@ fec_timeout(struct net_device *dev)
+ * This is called from the MPC core interrupt.
+ */
+ static irqreturn_t
+-fec_enet_interrupt(int irq, void * dev_id)
++fec_enet_interrupt(int irq, void *dev_id)
+ {
+ struct net_device *dev = dev_id;
+ volatile fec_t *fecp;
+@@ -520,7 +519,7 @@ fec_enet_interrupt(int irq, void * dev_id)
+ #ifdef CONFIG_USE_MDIO
+ fec_enet_mii(dev);
+ #else
+-printk("%s[%d] %s: unexpected FEC_ENET_MII event\n", __FILE__,__LINE__,__FUNCTION__);
++printk("%s[%d] %s: unexpected FEC_ENET_MII event\n", __FILE__, __LINE__, __func__);
+ #endif /* CONFIG_USE_MDIO */
+ }
+
+@@ -1441,7 +1440,7 @@ irqreturn_t mii_link_interrupt(int irq, void * dev_id)
+ fecp->fec_ecntrl = ecntrl; /* restore old settings */
+ }
+ #else
+-printk("%s[%d] %s: unexpected Link interrupt\n", __FILE__,__LINE__,__FUNCTION__);
++printk("%s[%d] %s: unexpected Link interrupt\n", __FILE__, __LINE__, __func__);
+ #endif /* CONFIG_USE_MDIO */
+
+ #ifndef CONFIG_RPXCLASSIC
+diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
+index abc877f..0f1863e 100644
+--- a/arch/ppc/Kconfig
++++ b/arch/ppc/Kconfig
+@@ -372,22 +372,6 @@ config MPC8XXFADS
+ bool "FADS"
+ select FADS
+
+-config MPC86XADS
+- bool "MPC86XADS"
+- help
+- MPC86x Application Development System by Freescale Semiconductor.
+- The MPC86xADS is meant to serve as a platform for s/w and h/w
+- development around the MPC86X processor families.
+- select FADS
+-
+-config MPC885ADS
+- bool "MPC885ADS"
+- help
+- Freescale Semiconductor MPC885 Application Development System (ADS).
+- Also known as DUET.
+- The MPC885ADS is meant to serve as a platform for s/w and h/w
+- development around the MPC885 processor family.
+-
+ config TQM823L
+ bool "TQM823L"
+ help
+@@ -479,53 +463,6 @@ config WINCEPT
+
+ endchoice
+
+-menu "Freescale Ethernet driver platform-specific options"
+- depends on FS_ENET
+-
+- config MPC8xx_SECOND_ETH
+- bool "Second Ethernet channel"
+- depends on (MPC885ADS || MPC86XADS)
+- default y
+- help
+- This enables support for second Ethernet on MPC885ADS and MPC86xADS boards.
+- The latter will use SCC1, for 885ADS you can select it below.
+-
+- choice
+- prompt "Second Ethernet channel"
+- depends on MPC8xx_SECOND_ETH
+- default MPC8xx_SECOND_ETH_FEC2
+-
+- config MPC8xx_SECOND_ETH_FEC2
+- bool "FEC2"
+- depends on MPC885ADS
+- help
+- Enable FEC2 to serve as 2-nd Ethernet channel. Note that SMC2
+- (often 2-nd UART) will not work if this is enabled.
+-
+- config MPC8xx_SECOND_ETH_SCC1
+- bool "SCC1"
+- depends on MPC86XADS
+- select MPC8xx_SCC_ENET_FIXED
+- help
+- Enable SCC1 to serve as 2-nd Ethernet channel. Note that SMC1
+- (often 1-nd UART) will not work if this is enabled.
+-
+- config MPC8xx_SECOND_ETH_SCC3
+- bool "SCC3"
+- depends on MPC885ADS
+- help
+- Enable SCC3 to serve as 2-nd Ethernet channel. Note that SMC1
+- (often 1-nd UART) will not work if this is enabled.
+-
+- endchoice
+-
+- config MPC8xx_SCC_ENET_FIXED
+- depends on MPC8xx_SECOND_ETH_SCC
+- default n
+- bool "Use fixed MII-less mode for SCC Ethernet"
+-
+-endmenu
+-
+ choice
+ prompt "Machine Type"
+ depends on 6xx
+@@ -666,9 +603,6 @@ config TQM8260
+ End of Life: not yet :-)
+ URL: <http://www.denx.de/PDF/TQM82xx_SPEC_Rev005.pdf>
+
+-config ADS8272
+- bool "ADS8272"
+-
+ config PQ2FADS
+ bool "Freescale-PQ2FADS"
+ help
+@@ -698,11 +632,6 @@ config EV64360
+ platform.
+ endchoice
+
+-config PQ2ADS
+- bool
+- depends on ADS8272
+- default y
+-
+ config TQM8xxL
+ bool
+ depends on 8xx && (TQM823L || TQM850L || FPS850L || TQM855L || TQM860L)
+@@ -725,15 +654,6 @@ config 8260
+ this option means that you wish to build a kernel for a machine with
+ an 8260 class CPU.
+
+-config 8272
+- bool
+- depends on 6xx
+- default y if ADS8272
+- select 8260
+- help
+- The MPC8272 CPM has a different internal dpram setup than other CPM2
+- devices
+-
+ config CPM1
+ bool
+ depends on 8xx
+@@ -1069,7 +989,7 @@ config PCI_8260
+
+ config 8260_PCI9
+ bool "Enable workaround for MPC826x erratum PCI 9"
+- depends on PCI_8260 && !ADS8272
++ depends on PCI_8260
+ default y
+
+ choice
+diff --git a/arch/ppc/configs/ads8272_defconfig b/arch/ppc/configs/ads8272_defconfig
+deleted file mode 100644
+index 6619f91..0000000
+--- a/arch/ppc/configs/ads8272_defconfig
++++ /dev/null
+@@ -1,930 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.21-rc5
+-# Wed Apr 4 20:55:16 2007
+-#
+-CONFIG_MMU=y
+-CONFIG_GENERIC_HARDIRQS=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_ARCH_HAS_ILOG2_U32=y
+-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_PPC=y
+-CONFIG_PPC32=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_GENERIC_FIND_NEXT_BIT=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+-CONFIG_GENERIC_BUG=y
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-
+-#
+-# Code maturity level options
+-#
+-CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-
+-#
+-# General setup
+-#
+-CONFIG_LOCALVERSION=""
+-CONFIG_LOCALVERSION_AUTO=y
+-CONFIG_SWAP=y
+-CONFIG_SYSVIPC=y
+-# CONFIG_IPC_NS is not set
+-CONFIG_SYSVIPC_SYSCTL=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_UTS_NS is not set
+-# CONFIG_AUDIT is not set
+-# CONFIG_IKCONFIG is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-# CONFIG_RELAY is not set
+-CONFIG_BLK_DEV_INITRD=y
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_EMBEDDED=y
+-CONFIG_SYSCTL_SYSCALL=y
+-# CONFIG_KALLSYMS is not set
+-# CONFIG_HOTPLUG is not set
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_ELF_CORE=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-# CONFIG_EPOLL is not set
+-CONFIG_SHMEM=y
+-CONFIG_SLAB=y
+-CONFIG_VM_EVENT_COUNTERS=y
+-CONFIG_RT_MUTEXES=y
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-# CONFIG_SLOB is not set
+-
+-#
+-# Loadable module support
+-#
+-# CONFIG_MODULES is not set
+-
+-#
+-# Block layer
+-#
+-CONFIG_BLOCK=y
+-# CONFIG_LBD is not set
+-# CONFIG_BLK_DEV_IO_TRACE is not set
+-# CONFIG_LSF is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-# CONFIG_DEFAULT_AS is not set
+-# CONFIG_DEFAULT_DEADLINE is not set
+-CONFIG_DEFAULT_CFQ=y
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="cfq"
+-
+-#
+-# Processor
+-#
+-CONFIG_6xx=y
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_8xx is not set
+-# CONFIG_E200 is not set
+-# CONFIG_E500 is not set
+-CONFIG_PPC_FPU=y
+-# CONFIG_PPC_DCR_NATIVE is not set
+-# CONFIG_KEXEC is not set
+-# CONFIG_CPU_FREQ is not set
+-# CONFIG_WANT_EARLY_SERIAL is not set
+-CONFIG_EMBEDDEDBOOT=y
+-CONFIG_PPC_STD_MMU=y
+-
+-#
+-# Platform options
+-#
+-
+-#
+-# Freescale Ethernet driver platform-specific options
+-#
+-# CONFIG_PPC_PREP is not set
+-# CONFIG_APUS is not set
+-# CONFIG_KATANA is not set
+-# CONFIG_WILLOW is not set
+-# CONFIG_CPCI690 is not set
+-# CONFIG_POWERPMC250 is not set
+-# CONFIG_CHESTNUT is not set
+-# CONFIG_SPRUCE is not set
+-# CONFIG_HDPU is not set
+-# CONFIG_EV64260 is not set
+-# CONFIG_LOPEC is not set
+-# CONFIG_MVME5100 is not set
+-# CONFIG_PPLUS is not set
+-# CONFIG_PRPMC750 is not set
+-# CONFIG_PRPMC800 is not set
+-# CONFIG_SANDPOINT is not set
+-# CONFIG_RADSTONE_PPC7D is not set
+-# CONFIG_PAL4 is not set
+-# CONFIG_EST8260 is not set
+-# CONFIG_SBC82xx is not set
+-# CONFIG_SBS8260 is not set
+-# CONFIG_RPX8260 is not set
+-# CONFIG_TQM8260 is not set
+-CONFIG_ADS8272=y
+-# CONFIG_PQ2FADS is not set
+-# CONFIG_LITE5200 is not set
+-# CONFIG_MPC834x_SYS is not set
+-# CONFIG_EV64360 is not set
+-CONFIG_PQ2ADS=y
+-CONFIG_8260=y
+-CONFIG_8272=y
+-CONFIG_CPM2=y
+-# CONFIG_PC_KEYBOARD is not set
+-# CONFIG_SMP is not set
+-# CONFIG_HIGHMEM is not set
+-CONFIG_ARCH_POPULATES_NODE_MAP=y
+-# CONFIG_HZ_100 is not set
+-CONFIG_HZ_250=y
+-# CONFIG_HZ_300 is not set
+-# CONFIG_HZ_1000 is not set
+-CONFIG_HZ=250
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-# CONFIG_DISCONTIGMEM_MANUAL is not set
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-# CONFIG_SPARSEMEM_STATIC is not set
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_RESOURCES_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=1
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_CMDLINE_BOOL is not set
+-# CONFIG_PM is not set
+-CONFIG_SECCOMP=y
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-CONFIG_ZONE_DMA=y
+-# CONFIG_PPC_I8259 is not set
+-CONFIG_PPC_INDIRECT_PCI=y
+-CONFIG_PCI=y
+-CONFIG_PCI_DOMAINS=y
+-CONFIG_PCI_8260=y
+-
+-#
+-# PCCARD (PCMCIA/CardBus) support
+-#
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0x80000000
+-CONFIG_BOOT_LOAD=0x00400000
+-
+-#
+-# Networking
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-# CONFIG_NETDEBUG is not set
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-CONFIG_XFRM=y
+-# CONFIG_XFRM_USER is not set
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_FIB_HASH=y
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_IP_MROUTE is not set
+-# CONFIG_ARPD is not set
+-CONFIG_SYN_COOKIES=y
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_XFRM_TUNNEL is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_INET_XFRM_MODE_TRANSPORT=y
+-CONFIG_INET_XFRM_MODE_TUNNEL=y
+-CONFIG_INET_XFRM_MODE_BEET=y
+-CONFIG_INET_DIAG=y
+-CONFIG_INET_TCP_DIAG=y
+-# CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_CUBIC=y
+-CONFIG_DEFAULT_TCP_CONG="cubic"
+-# CONFIG_TCP_MD5SIG is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_INET6_XFRM_TUNNEL is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETFILTER is not set
+-
+-#
+-# DCCP Configuration (EXPERIMENTAL)
+-#
+-# CONFIG_IP_DCCP is not set
+-
+-#
+-# SCTP Configuration (EXPERIMENTAL)
+-#
+-# CONFIG_IP_SCTP is not set
+-
+-#
+-# TIPC Configuration (EXPERIMENTAL)
+-#
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-
+-#
+-# QoS and/or fair queueing
+-#
+-# CONFIG_NET_SCHED is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_IEEE80211 is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_SYS_HYPERVISOR is not set
+-
+-#
+-# Connector - unified userspace <-> kernelspace linker
+-#
+-# CONFIG_CONNECTOR is not set
+-
+-#
+-# Memory Technology Devices (MTD)
+-#
+-# CONFIG_MTD is not set
+-
+-#
+-# Parallel port support
+-#
+-# CONFIG_PARPORT is not set
+-
+-#
+-# Plug and Play support
+-#
+-# CONFIG_PNPACPI is not set
+-
+-#
+-# Block devices
+-#
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_CPQ_DA is not set
+-# CONFIG_BLK_CPQ_CISS_DA is not set
+-# CONFIG_BLK_DEV_DAC960 is not set
+-# CONFIG_BLK_DEV_UMEM is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_SX8 is not set
+-CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=32768
+-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-
+-#
+-# Misc devices
+-#
+-# CONFIG_SGI_IOC4 is not set
+-# CONFIG_TIFM_CORE is not set
+-
+-#
+-# ATA/ATAPI/MFM/RLL support
+-#
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-# CONFIG_SCSI_NETLINK is not set
+-
+-#
+-# Serial ATA (prod) and Parallel ATA (experimental) drivers
+-#
+-# CONFIG_ATA is not set
+-
+-#
+-# Multi-device support (RAID and LVM)
+-#
+-# CONFIG_MD is not set
+-
+-#
+-# Fusion MPT device support
+-#
+-# CONFIG_FUSION is not set
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_IEEE1394 is not set
+-
+-#
+-# I2O device support
+-#
+-# CONFIG_I2O is not set
+-
+-#
+-# Macintosh device drivers
+-#
+-# CONFIG_MAC_EMUMOUSEBTN is not set
+-# CONFIG_WINDFARM is not set
+-
+-#
+-# Network device support
+-#
+-CONFIG_NETDEVICES=y
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-
+-#
+-# ARCnet devices
+-#
+-# CONFIG_ARCNET is not set
+-
+-#
+-# PHY device support
+-#
+-CONFIG_PHYLIB=y
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-CONFIG_DAVICOM_PHY=y
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_FIXED_PHY is not set
+-
+-#
+-# Ethernet (10 or 100Mbit)
+-#
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_HAPPYMEAL is not set
+-# CONFIG_SUNGEM is not set
+-# CONFIG_CASSINI is not set
+-# CONFIG_NET_VENDOR_3COM is not set
+-
+-#
+-# Tulip family network device support
+-#
+-# CONFIG_NET_TULIP is not set
+-# CONFIG_HP100 is not set
+-# CONFIG_NET_PCI is not set
+-CONFIG_FS_ENET=y
+-# CONFIG_FS_ENET_HAS_SCC is not set
+-CONFIG_FS_ENET_HAS_FCC=y
+-
+-#
+-# Ethernet (1000 Mbit)
+-#
+-# CONFIG_ACENIC is not set
+-# CONFIG_DL2K is not set
+-# CONFIG_E1000 is not set
+-# CONFIG_NS83820 is not set
+-# CONFIG_HAMACHI is not set
+-# CONFIG_YELLOWFIN is not set
+-# CONFIG_R8169 is not set
+-# CONFIG_SIS190 is not set
+-# CONFIG_SKGE is not set
+-# CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+-# CONFIG_TIGON3 is not set
+-# CONFIG_BNX2 is not set
+-# CONFIG_QLA3XXX is not set
+-# CONFIG_ATL1 is not set
+-
+-#
+-# Ethernet (10000 Mbit)
+-#
+-# CONFIG_CHELSIO_T1 is not set
+-# CONFIG_CHELSIO_T3 is not set
+-# CONFIG_IXGB is not set
+-# CONFIG_S2IO is not set
+-# CONFIG_MYRI10GE is not set
+-# CONFIG_NETXEN_NIC is not set
+-
+-#
+-# Token Ring devices
+-#
+-# CONFIG_TR is not set
+-
+-#
+-# Wireless LAN (non-hamradio)
+-#
+-# CONFIG_NET_RADIO is not set
+-
+-#
+-# Wan interfaces
+-#
+-# CONFIG_WAN is not set
+-# CONFIG_FDDI is not set
+-# CONFIG_HIPPI is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_SHAPER is not set
+-# CONFIG_NETCONSOLE is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-
+-#
+-# ISDN subsystem
+-#
+-# CONFIG_ISDN is not set
+-
+-#
+-# Telephony Support
+-#
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-
+-#
+-# Userland interfaces
+-#
+-# CONFIG_INPUT_MOUSEDEV is not set
+-# CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_TSDEV is not set
+-# CONFIG_INPUT_EVDEV is not set
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+-# CONFIG_INPUT_KEYBOARD is not set
+-# CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-
+-#
+-# Serial drivers
+-#
+-# CONFIG_SERIAL_8250 is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_UARTLITE is not set
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-CONFIG_SERIAL_CPM=y
+-CONFIG_SERIAL_CPM_CONSOLE=y
+-CONFIG_SERIAL_CPM_SCC1=y
+-# CONFIG_SERIAL_CPM_SCC2 is not set
+-# CONFIG_SERIAL_CPM_SCC3 is not set
+-CONFIG_SERIAL_CPM_SCC4=y
+-# CONFIG_SERIAL_CPM_SMC1 is not set
+-# CONFIG_SERIAL_CPM_SMC2 is not set
+-# CONFIG_SERIAL_JSM is not set
+-CONFIG_UNIX98_PTYS=y
+-CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
+-
+-#
+-# IPMI
+-#
+-# CONFIG_IPMI_HANDLER is not set
+-
+-#
+-# Watchdog Cards
+-#
+-# CONFIG_WATCHDOG is not set
+-CONFIG_HW_RANDOM=y
+-# CONFIG_NVRAM is not set
+-CONFIG_GEN_RTC=y
+-# CONFIG_GEN_RTC_X is not set
+-# CONFIG_DTLK is not set
+-# CONFIG_R3964 is not set
+-# CONFIG_APPLICOM is not set
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_RAW_DRIVER is not set
+-
+-#
+-# TPM devices
+-#
+-# CONFIG_TCG_TPM is not set
+-
+-#
+-# I2C support
+-#
+-# CONFIG_I2C is not set
+-
+-#
+-# SPI support
+-#
+-# CONFIG_SPI is not set
+-# CONFIG_SPI_MASTER is not set
+-
+-#
+-# Dallas's 1-wire bus
+-#
+-# CONFIG_W1 is not set
+-
+-#
+-# Hardware Monitoring support
+-#
+-CONFIG_HWMON=y
+-# CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_ABITUGURU is not set
+-# CONFIG_SENSORS_F71805F is not set
+-# CONFIG_SENSORS_PC87427 is not set
+-# CONFIG_SENSORS_VT1211 is not set
+-# CONFIG_HWMON_DEBUG_CHIP is not set
+-
+-#
+-# Multifunction device drivers
+-#
+-# CONFIG_MFD_SM501 is not set
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-
+-#
+-# Digital Video Broadcasting Devices
+-#
+-# CONFIG_DVB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-# CONFIG_FB is not set
+-# CONFIG_FB_IBM_GXT4500 is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-
+-#
+-# HID Devices
+-#
+-CONFIG_HID=y
+-# CONFIG_HID_DEBUG is not set
+-
+-#
+-# USB support
+-#
+-CONFIG_USB_ARCH_HAS_HCD=y
+-CONFIG_USB_ARCH_HAS_OHCI=y
+-CONFIG_USB_ARCH_HAS_EHCI=y
+-# CONFIG_USB is not set
+-
+-#
+-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+-#
+-
+-#
+-# USB Gadget Support
+-#
+-# CONFIG_USB_GADGET is not set
+-
+-#
+-# MMC/SD Card support
+-#
+-# CONFIG_MMC is not set
+-
+-#
+-# LED devices
+-#
+-# CONFIG_NEW_LEDS is not set
+-
+-#
+-# LED drivers
+-#
+-
+-#
+-# LED Triggers
+-#
+-
+-#
+-# InfiniBand support
+-#
+-# CONFIG_INFINIBAND is not set
+-
+-#
+-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+-#
+-
+-#
+-# Real Time Clock
+-#
+-# CONFIG_RTC_CLASS is not set
+-
+-#
+-# DMA Engine support
+-#
+-# CONFIG_DMA_ENGINE is not set
+-
+-#
+-# DMA Clients
+-#
+-
+-#
+-# DMA Devices
+-#
+-
+-#
+-# Auxiliary Display support
+-#
+-
+-#
+-# Virtualization
+-#
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+-# CONFIG_EXT2_FS_XIP is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-# CONFIG_EXT4DEV_FS is not set
+-CONFIG_JBD=y
+-# CONFIG_JBD_DEBUG is not set
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-CONFIG_FS_POSIX_ACL=y
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-CONFIG_INOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_QUOTA is not set
+-CONFIG_DNOTIFY=y
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-# CONFIG_FUSE_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_SYSFS=y
+-CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-CONFIG_RAMFS=y
+-# CONFIG_CONFIGFS_FS is not set
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-
+-#
+-# Network File Systems
+-#
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-CONFIG_NFS_V3_ACL=y
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_ACL_SUPPORT=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-# CONFIG_9P_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-# CONFIG_MSDOS_PARTITION is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_KARMA_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-
+-#
+-# Native Language Support
+-#
+-# CONFIG_NLS is not set
+-
+-#
+-# Distributed Lock Manager
+-#
+-# CONFIG_DLM is not set
+-# CONFIG_SCC_ENET is not set
+-# CONFIG_FEC_ENET is not set
+-
+-#
+-# CPM2 Options
+-#
+-
+-#
+-# Library routines
+-#
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC16 is not set
+-# CONFIG_CRC32 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_PLIST=y
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-# CONFIG_PROFILING is not set
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_ENABLE_MUST_CHECK=y
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-# CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_KGDB_CONSOLE is not set
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-
+-#
+-# Cryptographic options
+-#
+-CONFIG_CRYPTO=y
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-CONFIG_CRYPTO_MANAGER=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_XCBC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-# CONFIG_CRYPTO_GF128MUL is not set
+-CONFIG_CRYPTO_ECB=y
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=y
+-# CONFIG_CRYPTO_LRW is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+-
+-#
+-# Hardware crypto devices
+-#
+diff --git a/arch/ppc/configs/mpc86x_ads_defconfig b/arch/ppc/configs/mpc86x_ads_defconfig
+deleted file mode 100644
+index f63c6f5..0000000
+--- a/arch/ppc/configs/mpc86x_ads_defconfig
++++ /dev/null
+@@ -1,633 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.12-rc4
+-# Tue Jun 14 13:36:35 2005
+-#
+-CONFIG_MMU=y
+-CONFIG_GENERIC_HARDIRQS=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_HAVE_DEC_LOCK=y
+-CONFIG_PPC=y
+-CONFIG_PPC32=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-
+-#
+-# Code maturity level options
+-#
+-CONFIG_EXPERIMENTAL=y
+-# CONFIG_CLEAN_COMPILE is not set
+-CONFIG_BROKEN=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-
+-#
+-# General setup
+-#
+-CONFIG_LOCALVERSION=""
+-# CONFIG_SWAP is not set
+-CONFIG_SYSVIPC=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-CONFIG_SYSCTL=y
+-# CONFIG_AUDIT is not set
+-# CONFIG_HOTPLUG is not set
+-CONFIG_KOBJECT_UEVENT=y
+-# CONFIG_IKCONFIG is not set
+-CONFIG_EMBEDDED=y
+-# CONFIG_KALLSYMS is not set
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-# CONFIG_BASE_FULL is not set
+-CONFIG_FUTEX=y
+-# CONFIG_EPOLL is not set
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-# CONFIG_SHMEM is not set
+-CONFIG_CC_ALIGN_FUNCTIONS=0
+-CONFIG_CC_ALIGN_LABELS=0
+-CONFIG_CC_ALIGN_LOOPS=0
+-CONFIG_CC_ALIGN_JUMPS=0
+-CONFIG_TINY_SHMEM=y
+-CONFIG_BASE_SMALL=1
+-
+-#
+-# Loadable module support
+-#
+-CONFIG_MODULES=y
+-# CONFIG_MODULE_UNLOAD is not set
+-CONFIG_OBSOLETE_MODPARM=y
+-# CONFIG_MODVERSIONS is not set
+-# CONFIG_MODULE_SRCVERSION_ALL is not set
+-# CONFIG_KMOD is not set
+-
+-#
+-# Processor
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_POWER3 is not set
+-# CONFIG_POWER4 is not set
+-CONFIG_8xx=y
+-# CONFIG_E500 is not set
+-# CONFIG_MATH_EMULATION is not set
+-# CONFIG_CPU_FREQ is not set
+-CONFIG_EMBEDDEDBOOT=y
+-# CONFIG_PM is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-
+-#
+-# Platform options
+-#
+-CONFIG_FADS=y
+-# CONFIG_RPXLITE is not set
+-# CONFIG_RPXCLASSIC is not set
+-# CONFIG_BSEIP is not set
+-# CONFIG_MPC8XXFADS is not set
+-CONFIG_MPC86XADS=y
+-# CONFIG_TQM823L is not set
+-# CONFIG_TQM850L is not set
+-# CONFIG_TQM855L is not set
+-# CONFIG_TQM860L is not set
+-# CONFIG_FPS850L is not set
+-# CONFIG_SPD823TS is not set
+-# CONFIG_IVMS8 is not set
+-# CONFIG_IVML24 is not set
+-# CONFIG_SM850 is not set
+-# CONFIG_HERMES_PRO is not set
+-# CONFIG_IP860 is not set
+-# CONFIG_LWMON is not set
+-# CONFIG_PCU_E is not set
+-# CONFIG_CCM is not set
+-# CONFIG_LANTEC is not set
+-# CONFIG_MBX is not set
+-# CONFIG_WINCEPT is not set
+-# CONFIG_SMP is not set
+-# CONFIG_PREEMPT is not set
+-# CONFIG_HIGHMEM is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_CMDLINE_BOOL is not set
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-# CONFIG_PCI is not set
+-# CONFIG_PCI_DOMAINS is not set
+-# CONFIG_PCI_QSPAN is not set
+-
+-#
+-# PCCARD (PCMCIA/CardBus) support
+-#
+-# CONFIG_PCCARD is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0x80000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x00400000
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-# CONFIG_STANDALONE is not set
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-
+-#
+-# Memory Technology Devices (MTD)
+-#
+-# CONFIG_MTD is not set
+-
+-#
+-# Parallel port support
+-#
+-# CONFIG_PARPORT is not set
+-
+-#
+-# Plug and Play support
+-#
+-
+-#
+-# Block devices
+-#
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-CONFIG_BLK_DEV_LOOP=y
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_RAM is not set
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_LBD is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_AS=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-# CONFIG_ATA_OVER_ETH is not set
+-
+-#
+-# ATA/ATAPI/MFM/RLL support
+-#
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_SCSI is not set
+-
+-#
+-# Multi-device support (RAID and LVM)
+-#
+-# CONFIG_MD is not set
+-
+-#
+-# Fusion MPT device support
+-#
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_IEEE1394 is not set
+-
+-#
+-# I2O device support
+-#
+-
+-#
+-# Macintosh device drivers
+-#
+-
+-#
+-# Networking support
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-# CONFIG_IP_PNP_BOOTP is not set
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_IP_TCPDIAG=y
+-# CONFIG_IP_TCPDIAG_IPV6 is not set
+-CONFIG_IPV6=m
+-# CONFIG_IPV6_PRIVACY is not set
+-# CONFIG_INET6_AH is not set
+-# CONFIG_INET6_ESP is not set
+-# CONFIG_INET6_IPCOMP is not set
+-# CONFIG_INET6_TUNNEL is not set
+-# CONFIG_IPV6_TUNNEL is not set
+-# CONFIG_NETFILTER is not set
+-
+-#
+-# SCTP Configuration (EXPERIMENTAL)
+-#
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_NET_DIVERT is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-
+-#
+-# QoS and/or fair queueing
+-#
+-# CONFIG_NET_SCHED is not set
+-# CONFIG_NET_CLS_ROUTE is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-
+-#
+-# Ethernet (10 or 100Mbit)
+-#
+-CONFIG_NET_ETHERNET=y
+-# CONFIG_MII is not set
+-# CONFIG_OAKNET is not set
+-
+-#
+-# Ethernet (1000 Mbit)
+-#
+-
+-#
+-# Ethernet (10000 Mbit)
+-#
+-
+-#
+-# Token Ring devices
+-#
+-
+-#
+-# Wireless LAN (non-hamradio)
+-#
+-# CONFIG_NET_RADIO is not set
+-
+-#
+-# Wan interfaces
+-#
+-# CONFIG_WAN is not set
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_SHAPER is not set
+-# CONFIG_NETCONSOLE is not set
+-
+-#
+-# ISDN subsystem
+-#
+-# CONFIG_ISDN is not set
+-
+-#
+-# Telephony Support
+-#
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-CONFIG_SOUND_GAMEPORT=y
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-
+-#
+-# Serial drivers
+-#
+-# CONFIG_SERIAL_8250 is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-CONFIG_SERIAL_CPM=y
+-CONFIG_SERIAL_CPM_CONSOLE=y
+-# CONFIG_SERIAL_CPM_SCC1 is not set
+-# CONFIG_SERIAL_CPM_SCC2 is not set
+-# CONFIG_SERIAL_CPM_SCC3 is not set
+-# CONFIG_SERIAL_CPM_SCC4 is not set
+-CONFIG_SERIAL_CPM_SMC1=y
+-# CONFIG_SERIAL_CPM_SMC2 is not set
+-CONFIG_UNIX98_PTYS=y
+-# CONFIG_LEGACY_PTYS is not set
+-
+-#
+-# IPMI
+-#
+-# CONFIG_IPMI_HANDLER is not set
+-
+-#
+-# Watchdog Cards
+-#
+-# CONFIG_WATCHDOG is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_DTLK is not set
+-# CONFIG_R3964 is not set
+-
+-#
+-# Ftape, the floppy tape device driver
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_RAW_DRIVER is not set
+-
+-#
+-# TPM devices
+-#
+-
+-#
+-# I2C support
+-#
+-# CONFIG_I2C is not set
+-
+-#
+-# Dallas's 1-wire bus
+-#
+-# CONFIG_W1 is not set
+-
+-#
+-# Misc devices
+-#
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-
+-#
+-# Digital Video Broadcasting Devices
+-#
+-# CONFIG_DVB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_FB is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-
+-#
+-# USB support
+-#
+-# CONFIG_USB_ARCH_HAS_HCD is not set
+-# CONFIG_USB_ARCH_HAS_OHCI is not set
+-
+-#
+-# USB Gadget Support
+-#
+-# CONFIG_USB_GADGET is not set
+-
+-#
+-# MMC/SD Card support
+-#
+-# CONFIG_MMC is not set
+-
+-#
+-# InfiniBand support
+-#
+-# CONFIG_INFINIBAND is not set
+-
+-#
+-# File systems
+-#
+-# CONFIG_EXT2_FS is not set
+-CONFIG_EXT3_FS=y
+-# CONFIG_EXT3_FS_XATTR is not set
+-CONFIG_JBD=y
+-# CONFIG_JBD_DEBUG is not set
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-
+-#
+-# XFS support
+-#
+-# CONFIG_XFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_QUOTA is not set
+-# CONFIG_DNOTIFY is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_KCORE=y
+-CONFIG_SYSFS=y
+-# CONFIG_DEVFS_FS is not set
+-# CONFIG_DEVPTS_FS_XATTR is not set
+-# CONFIG_TMPFS is not set
+-# CONFIG_HUGETLBFS is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-CONFIG_RAMFS=y
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-
+-#
+-# Network File Systems
+-#
+-CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+-CONFIG_NFS_V4=y
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-CONFIG_RPCSEC_GSS_KRB5=y
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-# CONFIG_PARTITION_ADVANCED is not set
+-CONFIG_MSDOS_PARTITION=y
+-
+-#
+-# Native Language Support
+-#
+-# CONFIG_NLS is not set
+-
+-#
+-# MPC8xx CPM Options
+-#
+-CONFIG_SCC_ENET=y
+-CONFIG_SCC1_ENET=y
+-# CONFIG_SCC2_ENET is not set
+-# CONFIG_SCC3_ENET is not set
+-# CONFIG_FEC_ENET is not set
+-# CONFIG_ENET_BIG_BUFFERS is not set
+-
+-#
+-# Generic MPC8xx Options
+-#
+-# CONFIG_8xx_COPYBACK is not set
+-# CONFIG_8xx_CPU6 is not set
+-CONFIG_NO_UCODE_PATCH=y
+-# CONFIG_USB_SOF_UCODE_PATCH is not set
+-# CONFIG_I2C_SPI_UCODE_PATCH is not set
+-# CONFIG_I2C_SPI_SMC1_UCODE_PATCH is not set
+-
+-#
+-# Library routines
+-#
+-# CONFIG_CRC_CCITT is not set
+-# CONFIG_CRC32 is not set
+-# CONFIG_LIBCRC32C is not set
+-
+-#
+-# Profiling support
+-#
+-# CONFIG_PROFILING is not set
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-
+-#
+-# Cryptographic options
+-#
+-CONFIG_CRYPTO=y
+-# CONFIG_CRYPTO_HMAC is not set
+-# CONFIG_CRYPTO_NULL is not set
+-# CONFIG_CRYPTO_MD4 is not set
+-CONFIG_CRYPTO_MD5=y
+-# CONFIG_CRYPTO_SHA1 is not set
+-# CONFIG_CRYPTO_SHA256 is not set
+-# CONFIG_CRYPTO_SHA512 is not set
+-# CONFIG_CRYPTO_WP512 is not set
+-# CONFIG_CRYPTO_TGR192 is not set
+-CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_CAST5 is not set
+-# CONFIG_CRYPTO_CAST6 is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_ARC4 is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-# CONFIG_CRYPTO_DEFLATE is not set
+-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+-# CONFIG_CRYPTO_CRC32C is not set
+-# CONFIG_CRYPTO_TEST is not set
+-
+-#
+-# Hardware crypto devices
+-#
+diff --git a/arch/ppc/configs/mpc885ads_defconfig b/arch/ppc/configs/mpc885ads_defconfig
+deleted file mode 100644
+index 016f94d..0000000
+--- a/arch/ppc/configs/mpc885ads_defconfig
++++ /dev/null
+@@ -1,622 +0,0 @@
+-#
+-# Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.12-rc6
+-# Thu Jun 9 21:17:29 2005
+-#
+-CONFIG_MMU=y
+-CONFIG_GENERIC_HARDIRQS=y
+-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_HAVE_DEC_LOCK=y
+-CONFIG_PPC=y
+-CONFIG_PPC32=y
+-CONFIG_GENERIC_NVRAM=y
+-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+-
+-#
+-# Code maturity level options
+-#
+-CONFIG_EXPERIMENTAL=y
+-# CONFIG_CLEAN_COMPILE is not set
+-CONFIG_BROKEN=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-
+-#
+-# General setup
+-#
+-CONFIG_LOCALVERSION=""
+-# CONFIG_SWAP is not set
+-CONFIG_SYSVIPC=y
+-# CONFIG_POSIX_MQUEUE is not set
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-CONFIG_SYSCTL=y
+-# CONFIG_AUDIT is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_KOBJECT_UEVENT=y
+-# CONFIG_IKCONFIG is not set
+-CONFIG_EMBEDDED=y
+-# CONFIG_KALLSYMS is not set
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-# CONFIG_EPOLL is not set
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SHMEM=y
+-CONFIG_CC_ALIGN_FUNCTIONS=0
+-CONFIG_CC_ALIGN_LABELS=0
+-CONFIG_CC_ALIGN_LOOPS=0
+-CONFIG_CC_ALIGN_JUMPS=0
+-# CONFIG_TINY_SHMEM is not set
+-CONFIG_BASE_SMALL=0
+-
+-#
+-# Loadable module support
+-#
+-# CONFIG_MODULES is not set
+-
+-#
+-# Processor
+-#
+-# CONFIG_6xx is not set
+-# CONFIG_40x is not set
+-# CONFIG_44x is not set
+-# CONFIG_POWER3 is not set
+-# CONFIG_POWER4 is not set
+-CONFIG_8xx=y
+-# CONFIG_E500 is not set
+-# CONFIG_MATH_EMULATION is not set
+-# CONFIG_CPU_FREQ is not set
+-CONFIG_EMBEDDEDBOOT=y
+-# CONFIG_PM is not set
+-CONFIG_NOT_COHERENT_CACHE=y
+-
+-#
+-# Platform options
+-#
+-# CONFIG_RPXLITE is not set
+-# CONFIG_RPXCLASSIC is not set
+-# CONFIG_BSEIP is not set
+-# CONFIG_FADS is not set
+-CONFIG_MPC885ADS=y
+-# CONFIG_TQM823L is not set
+-# CONFIG_TQM850L is not set
+-# CONFIG_TQM855L is not set
+-# CONFIG_TQM860L is not set
+-# CONFIG_FPS850L is not set
+-# CONFIG_SPD823TS is not set
+-# CONFIG_IVMS8 is not set
+-# CONFIG_IVML24 is not set
+-# CONFIG_SM850 is not set
+-# CONFIG_HERMES_PRO is not set
+-# CONFIG_IP860 is not set
+-# CONFIG_LWMON is not set
+-# CONFIG_PCU_E is not set
+-# CONFIG_CCM is not set
+-# CONFIG_LANTEC is not set
+-# CONFIG_MBX is not set
+-# CONFIG_WINCEPT is not set
+-# CONFIG_SMP is not set
+-# CONFIG_PREEMPT is not set
+-# CONFIG_HIGHMEM is not set
+-CONFIG_BINFMT_ELF=y
+-# CONFIG_BINFMT_MISC is not set
+-# CONFIG_CMDLINE_BOOL is not set
+-CONFIG_ISA_DMA_API=y
+-
+-#
+-# Bus options
+-#
+-# CONFIG_PCI is not set
+-# CONFIG_PCI_DOMAINS is not set
+-# CONFIG_PCI_QSPAN is not set
+-
+-#
+-# PCCARD (PCMCIA/CardBus) support
+-#
+-# CONFIG_PCCARD is not set
+-
+-#
+-# Advanced setup
+-#
+-# CONFIG_ADVANCED_OPTIONS is not set
+-
+-#
+-# Default settings for advanced configuration options are used
+-#
+-CONFIG_HIGHMEM_START=0xfe000000
+-CONFIG_LOWMEM_SIZE=0x30000000
+-CONFIG_KERNEL_START=0xc0000000
+-CONFIG_TASK_SIZE=0x80000000
+-CONFIG_CONSISTENT_START=0xff100000
+-CONFIG_CONSISTENT_SIZE=0x00200000
+-CONFIG_BOOT_LOAD=0x00400000
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
+-
+-#
+-# Memory Technology Devices (MTD)
+-#
+-# CONFIG_MTD is not set
+-
+-#
+-# Parallel port support
+-#
+-# CONFIG_PARPORT is not set
+-
+-#
+-# Plug and Play support
+-#
+-
+-#
+-# Block devices
+-#
+-# CONFIG_BLK_DEV_FD is not set
+-# CONFIG_BLK_DEV_COW_COMMON is not set
+-# CONFIG_BLK_DEV_LOOP is not set
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_RAM is not set
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_INITRAMFS_SOURCE=""
+-# CONFIG_LBD is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-# CONFIG_IOSCHED_AS is not set
+-# CONFIG_IOSCHED_DEADLINE is not set
+-# CONFIG_IOSCHED_CFQ is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-
+-#
+-# ATA/ATAPI/MFM/RLL support
+-#
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-# CONFIG_SCSI is not set
+-
+-#
+-# Multi-device support (RAID and LVM)
+-#
+-# CONFIG_MD is not set
+-
+-#
+-# Fusion MPT device support
+-#
+-
+-#
+-# IEEE 1394 (FireWire) support
+-#
+-# CONFIG_IEEE1394 is not set
+-
+-#
+-# I2O device support
+-#
+-
+-#
+-# Macintosh device drivers
+-#
+-
+-#
+-# Networking support
+-#
+-CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+-CONFIG_PACKET=y
+-# CONFIG_PACKET_MMAP is not set
+-CONFIG_UNIX=y
+-# CONFIG_NET_KEY is not set
+-CONFIG_INET=y
+-# CONFIG_IP_MULTICAST is not set
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+-CONFIG_IP_PNP=y
+-CONFIG_IP_PNP_DHCP=y
+-CONFIG_IP_PNP_BOOTP=y
+-# CONFIG_IP_PNP_RARP is not set
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE is not set
+-# CONFIG_ARPD is not set
+-# CONFIG_SYN_COOKIES is not set
+-# CONFIG_INET_AH is not set
+-# CONFIG_INET_ESP is not set
+-# CONFIG_INET_IPCOMP is not set
+-# CONFIG_INET_TUNNEL is not set
+-CONFIG_IP_TCPDIAG=y
+-# CONFIG_IP_TCPDIAG_IPV6 is not set
+-# CONFIG_IPV6 is not set
+-# CONFIG_NETFILTER is not set
+-
+-#
+-# SCTP Configuration (EXPERIMENTAL)
+-#
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_ATM is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_VLAN_8021Q is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_LLC2 is not set
+-# CONFIG_IPX is not set
+-# CONFIG_ATALK is not set
+-# CONFIG_X25 is not set
+-# CONFIG_LAPB is not set
+-# CONFIG_NET_DIVERT is not set
+-# CONFIG_ECONET is not set
+-# CONFIG_WAN_ROUTER is not set
+-
+-#
+-# QoS and/or fair queueing
+-#
+-# CONFIG_NET_SCHED is not set
+-# CONFIG_NET_CLS_ROUTE is not set
+-
+-#
+-# Network testing
+-#
+-# CONFIG_NET_PKTGEN is not set
+-# CONFIG_NETPOLL is not set
+-# CONFIG_NET_POLL_CONTROLLER is not set
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-CONFIG_NETDEVICES=y
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_EQUALIZER is not set
+-# CONFIG_TUN is not set
+-
+-#
+-# Ethernet (10 or 100Mbit)
+-#
+-CONFIG_NET_ETHERNET=y
+-CONFIG_MII=y
+-# CONFIG_OAKNET is not set
+-
+-#
+-# Ethernet (1000 Mbit)
+-#
+-
+-#
+-# Ethernet (10000 Mbit)
+-#
+-
+-#
+-# Token Ring devices
+-#
+-
+-#
+-# Wireless LAN (non-hamradio)
+-#
+-# CONFIG_NET_RADIO is not set
+-
+-#
+-# Wan interfaces
+-#
+-# CONFIG_WAN is not set
+-CONFIG_PPP=y
+-# CONFIG_PPP_MULTILINK is not set
+-# CONFIG_PPP_FILTER is not set
+-CONFIG_PPP_ASYNC=y
+-CONFIG_PPP_SYNC_TTY=y
+-CONFIG_PPP_DEFLATE=y
+-# CONFIG_PPP_BSDCOMP is not set
+-# CONFIG_PPPOE is not set
+-# CONFIG_SLIP is not set
+-# CONFIG_SHAPER is not set
+-# CONFIG_NETCONSOLE is not set
+-
+-#
+-# ISDN subsystem
+-#
+-# CONFIG_ISDN is not set
+-
+-#
+-# Telephony Support
+-#
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-# CONFIG_INPUT is not set
+-
+-#
+-# Hardware I/O ports
+-#
+-# CONFIG_SERIO is not set
+-# CONFIG_GAMEPORT is not set
+-
+-#
+-# Character devices
+-#
+-# CONFIG_VT is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-
+-#
+-# Serial drivers
+-#
+-# CONFIG_SERIAL_8250 is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-CONFIG_SERIAL_CPM=y
+-CONFIG_SERIAL_CPM_CONSOLE=y
+-# CONFIG_SERIAL_CPM_SCC1 is not set
+-# CONFIG_SERIAL_CPM_SCC2 is not set
+-# CONFIG_SERIAL_CPM_SCC3 is not set
+-# CONFIG_SERIAL_CPM_SCC4 is not set
+-CONFIG_SERIAL_CPM_SMC1=y
+-CONFIG_SERIAL_CPM_SMC2=y
+-CONFIG_UNIX98_PTYS=y
+-# CONFIG_LEGACY_PTYS is not set
+-
+-#
+-# IPMI
+-#
+-# CONFIG_IPMI_HANDLER is not set
+-
+-#
+-# Watchdog Cards
+-#
+-# CONFIG_WATCHDOG is not set
+-# CONFIG_NVRAM is not set
+-# CONFIG_GEN_RTC is not set
+-# CONFIG_DTLK is not set
+-# CONFIG_R3964 is not set
+-
+-#
+-# Ftape, the floppy tape device driver
+-#
+-# CONFIG_AGP is not set
+-# CONFIG_DRM is not set
+-# CONFIG_RAW_DRIVER is not set
+-
+-#
+-# TPM devices
+-#
+-
+-#
+-# I2C support
+-#
+-# CONFIG_I2C is not set
+-
+-#
+-# Dallas's 1-wire bus
+-#
+-# CONFIG_W1 is not set
+-
+-#
+-# Misc devices
+-#
+-
+-#
+-# Multimedia devices
+-#
+-# CONFIG_VIDEO_DEV is not set
+-
+-#
+-# Digital Video Broadcasting Devices
+-#
+-# CONFIG_DVB is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_FB is not set
+-
+-#
+-# Sound
+-#
+-# CONFIG_SOUND is not set
+-
+-#
+-# USB support
+-#
+-# CONFIG_USB_ARCH_HAS_HCD is not set
+-# CONFIG_USB_ARCH_HAS_OHCI is not set
+-
+-#
+-# USB Gadget Support
+-#
+-# CONFIG_USB_GADGET is not set
+-
+-#
+-# MMC/SD Card support
+-#
+-# CONFIG_MMC is not set
+-
+-#
+-# InfiniBand support
+-#
+-# CONFIG_INFINIBAND is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=y
+-CONFIG_EXT2_FS_XATTR=y
+-# CONFIG_EXT2_FS_POSIX_ACL is not set
+-# CONFIG_EXT2_FS_SECURITY is not set
+-CONFIG_EXT3_FS=y
+-CONFIG_EXT3_FS_XATTR=y
+-# CONFIG_EXT3_FS_POSIX_ACL is not set
+-# CONFIG_EXT3_FS_SECURITY is not set
+-CONFIG_JBD=y
+-# CONFIG_JBD_DEBUG is not set
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-
+-#
+-# XFS support
+-#
+-# CONFIG_XFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_QUOTA is not set
+-# CONFIG_DNOTIFY is not set
+-# CONFIG_AUTOFS_FS is not set
+-# CONFIG_AUTOFS4_FS is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+-# CONFIG_ISO9660_FS is not set
+-# CONFIG_UDF_FS is not set
+-
+-#
+-# DOS/FAT/NT Filesystems
+-#
+-# CONFIG_MSDOS_FS is not set
+-# CONFIG_VFAT_FS is not set
+-# CONFIG_NTFS_FS is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-# CONFIG_PROC_KCORE is not set
+-CONFIG_SYSFS=y
+-# CONFIG_DEVFS_FS is not set
+-# CONFIG_DEVPTS_FS_XATTR is not set
+-# CONFIG_TMPFS is not set
+-# CONFIG_HUGETLBFS is not set
+-# CONFIG_HUGETLB_PAGE is not set
+-CONFIG_RAMFS=y
+-
+-#
+-# Miscellaneous filesystems
+-#
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_HFS_FS is not set
+-# CONFIG_HFSPLUS_FS is not set
+-# CONFIG_BEFS_FS is not set
+-# CONFIG_BFS_FS is not set
+-# CONFIG_EFS_FS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-
+-#
+-# Network File Systems
+-#
+-CONFIG_NFS_FS=y
+-# CONFIG_NFS_V3 is not set
+-# CONFIG_NFS_V4 is not set
+-# CONFIG_NFS_DIRECTIO is not set
+-# CONFIG_NFSD is not set
+-CONFIG_ROOT_NFS=y
+-CONFIG_LOCKD=y
+-CONFIG_SUNRPC=y
+-# CONFIG_RPCSEC_GSS_KRB5 is not set
+-# CONFIG_RPCSEC_GSS_SPKM3 is not set
+-# CONFIG_SMB_FS is not set
+-# CONFIG_CIFS is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
+-CONFIG_PARTITION_ADVANCED=y
+-# CONFIG_ACORN_PARTITION is not set
+-# CONFIG_OSF_PARTITION is not set
+-# CONFIG_AMIGA_PARTITION is not set
+-# CONFIG_ATARI_PARTITION is not set
+-# CONFIG_MAC_PARTITION is not set
+-CONFIG_MSDOS_PARTITION=y
+-# CONFIG_BSD_DISKLABEL is not set
+-# CONFIG_MINIX_SUBPARTITION is not set
+-# CONFIG_SOLARIS_X86_PARTITION is not set
+-# CONFIG_UNIXWARE_DISKLABEL is not set
+-# CONFIG_LDM_PARTITION is not set
+-# CONFIG_SGI_PARTITION is not set
+-# CONFIG_ULTRIX_PARTITION is not set
+-# CONFIG_SUN_PARTITION is not set
+-# CONFIG_EFI_PARTITION is not set
+-
+-#
+-# Native Language Support
+-#
+-# CONFIG_NLS is not set
+-
+-#
+-# MPC8xx CPM Options
+-#
+-CONFIG_SCC_ENET=y
+-# CONFIG_SCC1_ENET is not set
+-# CONFIG_SCC2_ENET is not set
+-CONFIG_SCC3_ENET=y
+-# CONFIG_FEC_ENET is not set
+-# CONFIG_ENET_BIG_BUFFERS is not set
+-
+-#
+-# Generic MPC8xx Options
+-#
+-CONFIG_8xx_COPYBACK=y
+-CONFIG_8xx_CPU6=y
+-CONFIG_NO_UCODE_PATCH=y
+-# CONFIG_USB_SOF_UCODE_PATCH is not set
+-# CONFIG_I2C_SPI_UCODE_PATCH is not set
+-# CONFIG_I2C_SPI_SMC1_UCODE_PATCH is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_CRC_CCITT=y
+-# CONFIG_CRC32 is not set
+-# CONFIG_LIBCRC32C is not set
+-CONFIG_ZLIB_INFLATE=y
+-CONFIG_ZLIB_DEFLATE=y
+-
+-#
+-# Profiling support
+-#
+-# CONFIG_PROFILING is not set
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-# CONFIG_DEBUG_KERNEL is not set
+-CONFIG_LOG_BUF_SHIFT=14
+-
+-#
+-# Security options
+-#
+-# CONFIG_KEYS is not set
+-# CONFIG_SECURITY is not set
+-
+-#
+-# Cryptographic options
+-#
+-# CONFIG_CRYPTO is not set
+-
+-#
+-# Hardware crypto devices
+-#
+diff --git a/arch/ppc/configs/sandpoint_defconfig b/arch/ppc/configs/sandpoint_defconfig
+index fb493a6..9525e34 100644
+--- a/arch/ppc/configs/sandpoint_defconfig
++++ b/arch/ppc/configs/sandpoint_defconfig
+@@ -189,7 +189,7 @@ CONFIG_IDE_TASKFILE_IO=y
+ #
+ # IDE chipset support/bugfixes
+ #
+-CONFIG_IDE_GENERIC=y
++CONFIG_BLK_DEV_SL82C105=y
+ # CONFIG_BLK_DEV_IDEPCI is not set
+ # CONFIG_BLK_DEV_IDEDMA is not set
+ # CONFIG_IDEDMA_AUTO is not set
+diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
+index 1b0ec72..e7e642b 100644
+--- a/arch/ppc/kernel/head.S
++++ b/arch/ppc/kernel/head.S
+@@ -701,23 +701,6 @@ load_up_altivec:
+ b fast_exception_return
+
+ /*
+- * AltiVec unavailable trap from kernel - print a message, but let
+- * the task use AltiVec in the kernel until it returns to user mode.
+- */
+-KernelAltiVec:
+- lwz r3,_MSR(r1)
+- oris r3,r3,MSR_VEC at h
+- stw r3,_MSR(r1) /* enable use of AltiVec after return */
+- lis r3,87f at h
+- ori r3,r3,87f at l
+- mr r4,r2 /* current */
+- lwz r5,_NIP(r1)
+- bl printk
+- b ret_from_except
+-87: .string "AltiVec used in kernel (task=%p, pc=%x) \n"
+- .align 4,0
+-
+-/*
+ * giveup_altivec(tsk)
+ * Disable AltiVec for the task given as the argument,
+ * and save the AltiVec registers in its thread_struct.
+diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
+index c2ec13b..50ce83f 100644
+--- a/arch/ppc/kernel/pci.c
++++ b/arch/ppc/kernel/pci.c
+@@ -578,39 +578,6 @@ pcibios_assign_resources(void)
+ }
+
+
+-int
+-pcibios_enable_resources(struct pci_dev *dev, int mask)
+-{
+- u16 cmd, old_cmd;
+- int idx;
+- struct resource *r;
+-
+- pci_read_config_word(dev, PCI_COMMAND, &cmd);
+- old_cmd = cmd;
+- for (idx=0; idx<6; idx++) {
+- /* Only set up the requested stuff */
+- if (!(mask & (1<<idx)))
+- continue;
+-
+- r = &dev->resource[idx];
+- if (r->flags & IORESOURCE_UNSET) {
+- printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
+- return -EINVAL;
+- }
+- if (r->flags & IORESOURCE_IO)
+- cmd |= PCI_COMMAND_IO;
+- if (r->flags & IORESOURCE_MEM)
+- cmd |= PCI_COMMAND_MEMORY;
+- }
+- if (dev->resource[PCI_ROM_RESOURCE].start)
+- cmd |= PCI_COMMAND_MEMORY;
+- if (cmd != old_cmd) {
+- printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);
+- pci_write_config_word(dev, PCI_COMMAND, cmd);
+- }
+- return 0;
+-}
+-
+ static int next_controller_index;
+
+ struct pci_controller * __init
+@@ -785,33 +752,11 @@ pcibios_update_irq(struct pci_dev *dev, int irq)
+
+ int pcibios_enable_device(struct pci_dev *dev, int mask)
+ {
+- u16 cmd, old_cmd;
+- int idx;
+- struct resource *r;
+-
+ if (ppc_md.pcibios_enable_device_hook)
+ if (ppc_md.pcibios_enable_device_hook(dev, 0))
+ return -EINVAL;
+-
+- pci_read_config_word(dev, PCI_COMMAND, &cmd);
+- old_cmd = cmd;
+- for (idx=0; idx<6; idx++) {
+- r = &dev->resource[idx];
+- if (r->flags & IORESOURCE_UNSET) {
+- printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
+- return -EINVAL;
+- }
+- if (r->flags & IORESOURCE_IO)
+- cmd |= PCI_COMMAND_IO;
+- if (r->flags & IORESOURCE_MEM)
+- cmd |= PCI_COMMAND_MEMORY;
+- }
+- if (cmd != old_cmd) {
+- printk("PCI: Enabling device %s (%04x -> %04x)\n",
+- pci_name(dev), old_cmd, cmd);
+- pci_write_config_word(dev, PCI_COMMAND, cmd);
+- }
+- return 0;
++
++ return pci_enable_resources(dev, mask);
+ }
+
+ struct pci_controller*
+diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
+index c353502..d9036ef 100644
+--- a/arch/ppc/kernel/ppc_ksyms.c
++++ b/arch/ppc/kernel/ppc_ksyms.c
+@@ -12,7 +12,6 @@
+ #include <linux/irq.h>
+ #include <linux/pci.h>
+ #include <linux/delay.h>
+-#include <linux/ide.h>
+ #include <linux/pm.h>
+ #include <linux/bitops.h>
+
+@@ -89,6 +88,7 @@ EXPORT_SYMBOL(strncpy);
+ EXPORT_SYMBOL(strcat);
+ EXPORT_SYMBOL(strlen);
+ EXPORT_SYMBOL(strcmp);
++EXPORT_SYMBOL(strncmp);
+
+ EXPORT_SYMBOL(csum_partial);
+ EXPORT_SYMBOL(csum_partial_copy_generic);
+@@ -124,10 +124,6 @@ EXPORT_SYMBOL(__ioremap);
+ EXPORT_SYMBOL(iounmap);
+ EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */
+
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+-EXPORT_SYMBOL(ppc_ide_md);
+-#endif
+-
+ #ifdef CONFIG_PCI
+ EXPORT_SYMBOL(isa_io_base);
+ EXPORT_SYMBOL(isa_mem_base);
+diff --git a/arch/ppc/kernel/semaphore.c b/arch/ppc/kernel/semaphore.c
+deleted file mode 100644
+index 2fe429b..0000000
+--- a/arch/ppc/kernel/semaphore.c
++++ /dev/null
+@@ -1,131 +0,0 @@
+-/*
+- * PowerPC-specific semaphore code.
+- *
+- * Copyright (C) 1999 Cort Dougan <cort at cs.nmt.edu>
+- *
+- * 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.
+- *
+- * April 2001 - Reworked by Paul Mackerras <paulus at samba.org>
+- * to eliminate the SMP races in the old version between the updates
+- * of `count' and `waking'. Now we use negative `count' values to
+- * indicate that some process(es) are waiting for the semaphore.
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/init.h>
+-#include <asm/atomic.h>
+-#include <asm/semaphore.h>
+-#include <asm/errno.h>
+-
+-/*
+- * Atomically update sem->count.
+- * This does the equivalent of the following:
+- *
+- * old_count = sem->count;
+- * tmp = MAX(old_count, 0) + incr;
+- * sem->count = tmp;
+- * return old_count;
+- */
+-static inline int __sem_update_count(struct semaphore *sem, int incr)
+-{
+- int old_count, tmp;
+-
+- __asm__ __volatile__("\n"
+-"1: lwarx %0,0,%3\n"
+-" srawi %1,%0,31\n"
+-" andc %1,%0,%1\n"
+-" add %1,%1,%4\n"
+- PPC405_ERR77(0,%3)
+-" stwcx. %1,0,%3\n"
+-" bne 1b"
+- : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
+- : "r" (&sem->count), "r" (incr), "m" (sem->count)
+- : "cc");
+-
+- return old_count;
+-}
+-
+-void __up(struct semaphore *sem)
+-{
+- /*
+- * Note that we incremented count in up() before we came here,
+- * but that was ineffective since the result was <= 0, and
+- * any negative value of count is equivalent to 0.
+- * This ends up setting count to 1, unless count is now > 0
+- * (i.e. because some other cpu has called up() in the meantime),
+- * in which case we just increment count.
+- */
+- __sem_update_count(sem, 1);
+- wake_up(&sem->wait);
+-}
+-
+-/*
+- * Note that when we come in to __down or __down_interruptible,
+- * we have already decremented count, but that decrement was
+- * ineffective since the result was < 0, and any negative value
+- * of count is equivalent to 0.
+- * Thus it is only when we decrement count from some value > 0
+- * that we have actually got the semaphore.
+- */
+-void __sched __down(struct semaphore *sem)
+-{
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+-
+- tsk->state = TASK_UNINTERRUPTIBLE;
+- add_wait_queue_exclusive(&sem->wait, &wait);
+- smp_wmb();
+-
+- /*
+- * Try to get the semaphore. If the count is > 0, then we've
+- * got the semaphore; we decrement count and exit the loop.
+- * If the count is 0 or negative, we set it to -1, indicating
+- * that we are asleep, and then sleep.
+- */
+- while (__sem_update_count(sem, -1) <= 0) {
+- schedule();
+- tsk->state = TASK_UNINTERRUPTIBLE;
+- }
+- remove_wait_queue(&sem->wait, &wait);
+- tsk->state = TASK_RUNNING;
+-
+- /*
+- * If there are any more sleepers, wake one of them up so
+- * that it can either get the semaphore, or set count to -1
+- * indicating that there are still processes sleeping.
+- */
+- wake_up(&sem->wait);
+-}
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+- int retval = 0;
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+-
+- tsk->state = TASK_INTERRUPTIBLE;
+- add_wait_queue_exclusive(&sem->wait, &wait);
+- smp_wmb();
+-
+- while (__sem_update_count(sem, -1) <= 0) {
+- if (signal_pending(current)) {
+- /*
+- * A signal is pending - give up trying.
+- * Set sem->count to 0 if it is negative,
+- * since we are no longer sleeping.
+- */
+- __sem_update_count(sem, 0);
+- retval = -EINTR;
+- break;
+- }
+- schedule();
+- tsk->state = TASK_INTERRUPTIBLE;
+- }
+- tsk->state = TASK_RUNNING;
+- remove_wait_queue(&sem->wait, &wait);
+- wake_up(&sem->wait);
+- return retval;
+-}
+diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
+index 2940559..bfddfde 100644
+--- a/arch/ppc/kernel/setup.c
++++ b/arch/ppc/kernel/setup.c
+@@ -10,7 +10,6 @@
+ #include <linux/reboot.h>
+ #include <linux/delay.h>
+ #include <linux/initrd.h>
+-#include <linux/ide.h>
+ #include <linux/screen_info.h>
+ #include <linux/bootmem.h>
+ #include <linux/seq_file.h>
+@@ -57,7 +56,6 @@ extern void ppc6xx_idle(void);
+ extern void power4_idle(void);
+
+ extern boot_infos_t *boot_infos;
+-struct ide_machdep_calls ppc_ide_md;
+
+ /* Used with the BI_MEMSIZE bootinfo parameter to store the memory
+ size value reported by the boot loader. */
+diff --git a/arch/ppc/lib/string.S b/arch/ppc/lib/string.S
+index 84ed33a..927253b 100644
+--- a/arch/ppc/lib/string.S
++++ b/arch/ppc/lib/string.S
+@@ -121,6 +121,20 @@ _GLOBAL(strcmp)
+ beq 1b
+ blr
+
++_GLOBAL(strncmp)
++ PPC_LCMPI r5,0
++ beqlr
++ mtctr r5
++ addi r5,r3,-1
++ addi r4,r4,-1
++1: lbzu r3,1(r5)
++ cmpwi 1,r3,0
++ lbzu r0,1(r4)
++ subf. r3,r0,r3
++ beqlr 1
++ bdnzt eq,1b
++ blr
++
+ _GLOBAL(strlen)
+ addi r4,r3,-1
+ 1: lbzu r0,1(r4)
+diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
+index 7444df3..1a63711 100644
+--- a/arch/ppc/mm/init.c
++++ b/arch/ppc/mm/init.c
+@@ -109,7 +109,6 @@ void show_mem(void)
+
+ printk("Mem-info:\n");
+ show_free_areas();
+- printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+ i = max_mapnr;
+ while (i-- > 0) {
+ total++;
+diff --git a/arch/ppc/platforms/4xx/bamboo.c b/arch/ppc/platforms/4xx/bamboo.c
+index 017623c..01f20f4 100644
+--- a/arch/ppc/platforms/4xx/bamboo.c
++++ b/arch/ppc/platforms/4xx/bamboo.c
+@@ -22,7 +22,6 @@
+ #include <linux/blkdev.h>
+ #include <linux/console.h>
+ #include <linux/delay.h>
+-#include <linux/ide.h>
+ #include <linux/initrd.h>
+ #include <linux/seq_file.h>
+ #include <linux/root_dev.h>
+diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c
+index 453643a..8027a36 100644
+--- a/arch/ppc/platforms/4xx/ebony.c
++++ b/arch/ppc/platforms/4xx/ebony.c
+@@ -25,7 +25,6 @@
+ #include <linux/blkdev.h>
+ #include <linux/console.h>
+ #include <linux/delay.h>
+-#include <linux/ide.h>
+ #include <linux/initrd.h>
+ #include <linux/seq_file.h>
+ #include <linux/root_dev.h>
+diff --git a/arch/ppc/platforms/4xx/luan.c b/arch/ppc/platforms/4xx/luan.c
+index b79ebb8..f6d8c2e 100644
+--- a/arch/ppc/platforms/4xx/luan.c
++++ b/arch/ppc/platforms/4xx/luan.c
+@@ -23,7 +23,6 @@
+ #include <linux/blkdev.h>
+ #include <linux/console.h>
+ #include <linux/delay.h>
+-#include <linux/ide.h>
+ #include <linux/initrd.h>
+ #include <linux/seq_file.h>
+ #include <linux/root_dev.h>
+diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c
+index 28a712c..308386e 100644
+--- a/arch/ppc/platforms/4xx/ocotea.c
++++ b/arch/ppc/platforms/4xx/ocotea.c
+@@ -23,7 +23,6 @@
+ #include <linux/blkdev.h>
+ #include <linux/console.h>
+ #include <linux/delay.h>
+-#include <linux/ide.h>
+ #include <linux/initrd.h>
+ #include <linux/seq_file.h>
+ #include <linux/root_dev.h>
+diff --git a/arch/ppc/platforms/4xx/taishan.c b/arch/ppc/platforms/4xx/taishan.c
+index f6a0c66..1156942 100644
+--- a/arch/ppc/platforms/4xx/taishan.c
++++ b/arch/ppc/platforms/4xx/taishan.c
+@@ -23,7 +23,6 @@
+ #include <linux/blkdev.h>
+ #include <linux/console.h>
+ #include <linux/delay.h>
+-#include <linux/ide.h>
+ #include <linux/initrd.h>
+ #include <linux/seq_file.h>
+ #include <linux/root_dev.h>
+diff --git a/arch/ppc/platforms/4xx/yucca.c b/arch/ppc/platforms/4xx/yucca.c
+index 66a44ff..f6cfd44 100644
+--- a/arch/ppc/platforms/4xx/yucca.c
++++ b/arch/ppc/platforms/4xx/yucca.c
+@@ -24,7 +24,6 @@
+ #include <linux/blkdev.h>
+ #include <linux/console.h>
+ #include <linux/delay.h>
+-#include <linux/ide.h>
+ #include <linux/initrd.h>
+ #include <linux/seq_file.h>
+ #include <linux/root_dev.h>
+diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
+index 40f53fb..6260231 100644
+--- a/arch/ppc/platforms/Makefile
++++ b/arch/ppc/platforms/Makefile
+@@ -4,7 +4,6 @@
+
+ obj-$(CONFIG_PPC_PREP) += prep_pci.o prep_setup.o
+ obj-$(CONFIG_PREP_RESIDUAL) += residual.o
+-obj-$(CONFIG_PQ2ADS) += pq2ads.o
+ obj-$(CONFIG_TQM8260) += tqm8260_setup.o
+ obj-$(CONFIG_CPCI690) += cpci690.o
+ obj-$(CONFIG_EV64260) += ev64260.o
+@@ -24,6 +23,3 @@ obj-$(CONFIG_SBC82xx) += sbc82xx.o
+ obj-$(CONFIG_SPRUCE) += spruce.o
+ obj-$(CONFIG_LITE5200) += lite5200.o
+ obj-$(CONFIG_EV64360) += ev64360.o
+-obj-$(CONFIG_MPC86XADS) += mpc866ads_setup.o
+-obj-$(CONFIG_MPC885ADS) += mpc885ads_setup.o
+-obj-$(CONFIG_ADS8272) += mpc8272ads_setup.o
+diff --git a/arch/ppc/platforms/chestnut.c b/arch/ppc/platforms/chestnut.c
+index dcd6070..27c140f 100644
+--- a/arch/ppc/platforms/chestnut.c
++++ b/arch/ppc/platforms/chestnut.c
+@@ -22,7 +22,6 @@
+ #include <linux/initrd.h>
+ #include <linux/delay.h>
+ #include <linux/seq_file.h>
+-#include <linux/ide.h>
+ #include <linux/serial.h>
+ #include <linux/serial_core.h>
+ #include <linux/serial_8250.h>
+diff --git a/arch/ppc/platforms/cpci690.c b/arch/ppc/platforms/cpci690.c
+index e78bccf..07f672d 100644
+--- a/arch/ppc/platforms/cpci690.c
++++ b/arch/ppc/platforms/cpci690.c
+@@ -10,7 +10,6 @@
+ */
+ #include <linux/delay.h>
+ #include <linux/pci.h>
+-#include <linux/ide.h>
+ #include <linux/irq.h>
+ #include <linux/fs.h>
+ #include <linux/seq_file.h>
+diff --git a/arch/ppc/platforms/ev64260.c b/arch/ppc/platforms/ev64260.c
+index c1f77e1..f522b31 100644
+--- a/arch/ppc/platforms/ev64260.c
++++ b/arch/ppc/platforms/ev64260.c
+@@ -23,7 +23,6 @@
+
+ #include <linux/delay.h>
+ #include <linux/pci.h>
+-#include <linux/ide.h>
+ #include <linux/irq.h>
+ #include <linux/fs.h>
+ #include <linux/seq_file.h>
+diff --git a/arch/ppc/platforms/fads.h b/arch/ppc/platforms/fads.h
+index 2f9f0f6..5219366 100644
+--- a/arch/ppc/platforms/fads.h
++++ b/arch/ppc/platforms/fads.h
+@@ -22,29 +22,6 @@
+
+ #include <asm/ppcboot.h>
+
+-#if defined(CONFIG_MPC86XADS)
+-
+-#define BOARD_CHIP_NAME "MPC86X"
+-
+-/* U-Boot maps BCSR to 0xff080000 */
+-#define BCSR_ADDR ((uint)0xff080000)
+-
+-/* MPC86XADS has one more CPLD and an additional BCSR.
+- */
+-#define CFG_PHYDEV_ADDR ((uint)0xff0a0000)
+-#define BCSR5 ((uint)(CFG_PHYDEV_ADDR + 0x300))
+-
+-#define BCSR5_T1_RST 0x10
+-#define BCSR5_ATM155_RST 0x08
+-#define BCSR5_ATM25_RST 0x04
+-#define BCSR5_MII1_EN 0x02
+-#define BCSR5_MII1_RST 0x01
+-
+-/* There is no PHY link change interrupt */
+-#define PHY_INTERRUPT (-1)
+-
+-#else /* FADS */
+-
+ /* Memory map is configured by the PROM startup.
+ * I tried to follow the FADS manual, although the startup PROM
+ * dictates this and we simply have to move some of the physical
+@@ -55,8 +32,6 @@
+ /* PHY link change interrupt */
+ #define PHY_INTERRUPT SIU_IRQ2
+
+-#endif /* CONFIG_MPC86XADS */
+-
+ #define BCSR_SIZE ((uint)(64 * 1024))
+ #define BCSR0 ((uint)(BCSR_ADDR + 0x00))
+ #define BCSR1 ((uint)(BCSR_ADDR + 0x04))
+diff --git a/arch/ppc/platforms/hdpu.c b/arch/ppc/platforms/hdpu.c
+index ca5de13..904b518 100644
+--- a/arch/ppc/platforms/hdpu.c
++++ b/arch/ppc/platforms/hdpu.c
+@@ -16,7 +16,6 @@
+ #include <linux/pci.h>
+ #include <linux/delay.h>
+ #include <linux/irq.h>
+-#include <linux/ide.h>
+ #include <linux/seq_file.h>
+ #include <linux/platform_device.h>
+
+@@ -604,41 +603,6 @@ static void parse_bootinfo(unsigned long r3,
+ }
+ }
+
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+-static void
+-hdpu_ide_request_region(ide_ioreg_t from, unsigned int extent, const char *name)
+-{
+- request_region(from, extent, name);
+- return;
+-}
+-
+-static void hdpu_ide_release_region(ide_ioreg_t from, unsigned int extent)
+-{
+- release_region(from, extent);
+- return;
+-}
+-
+-static void __init
+-hdpu_ide_pci_init_hwif_ports(hw_regs_t * hw, ide_ioreg_t data_port,
+- ide_ioreg_t ctrl_port, int *irq)
+-{
+- struct pci_dev *dev;
+-
+- pci_for_each_dev(dev) {
+- if (((dev->class >> 8) == PCI_CLASS_STORAGE_IDE) ||
+- ((dev->class >> 8) == PCI_CLASS_STORAGE_RAID)) {
+- hw->irq = dev->irq;
+-
+- if (irq != NULL) {
+- *irq = dev->irq;
+- }
+- }
+- }
+-
+- return;
+-}
+-#endif
+-
+ void hdpu_heartbeat(void)
+ {
+ if (mv64x60_read(&bh, MV64x60_GPP_VALUE) & (1 << 5))
+diff --git a/arch/ppc/platforms/lopec.c b/arch/ppc/platforms/lopec.c
+index b947c77..1e3aa6e 100644
+--- a/arch/ppc/platforms/lopec.c
++++ b/arch/ppc/platforms/lopec.c
+@@ -15,7 +15,6 @@
+ #include <linux/pci_ids.h>
+ #include <linux/ioport.h>
+ #include <linux/init.h>
+-#include <linux/ide.h>
+ #include <linux/seq_file.h>
+ #include <linux/initrd.h>
+ #include <linux/console.h>
+@@ -168,85 +167,6 @@ lopec_power_off(void)
+ lopec_halt();
+ }
+
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+-int lopec_ide_ports_known = 0;
+-static unsigned long lopec_ide_regbase[MAX_HWIFS];
+-static unsigned long lopec_ide_ctl_regbase[MAX_HWIFS];
+-static unsigned long lopec_idedma_regbase;
+-
+-static void
+-lopec_ide_probe(void)
+-{
+- struct pci_dev *dev = pci_get_device(PCI_VENDOR_ID_WINBOND,
+- PCI_DEVICE_ID_WINBOND_82C105,
+- NULL);
+- lopec_ide_ports_known = 1;
+-
+- if (dev) {
+- lopec_ide_regbase[0] = dev->resource[0].start;
+- lopec_ide_regbase[1] = dev->resource[2].start;
+- lopec_ide_ctl_regbase[0] = dev->resource[1].start;
+- lopec_ide_ctl_regbase[1] = dev->resource[3].start;
+- lopec_idedma_regbase = dev->resource[4].start;
+- pci_dev_put(dev);
+- }
+-}
+-
+-static int
+-lopec_ide_default_irq(unsigned long base)
+-{
+- if (lopec_ide_ports_known == 0)
+- lopec_ide_probe();
+-
+- if (base == lopec_ide_regbase[0])
+- return 14;
+- else if (base == lopec_ide_regbase[1])
+- return 15;
+- else
+- return 0;
+-}
+-
+-static unsigned long
+-lopec_ide_default_io_base(int index)
+-{
+- if (lopec_ide_ports_known == 0)
+- lopec_ide_probe();
+- return lopec_ide_regbase[index];
+-}
+-
+-static void __init
+-lopec_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data,
+- unsigned long ctl, int *irq)
+-{
+- unsigned long reg = data;
+- uint alt_status_base;
+- int i;
+-
+- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
+- hw->io_ports[i] = reg++;
+-
+- if (data == lopec_ide_regbase[0]) {
+- alt_status_base = lopec_ide_ctl_regbase[0] + 2;
+- hw->irq = 14;
+- } else if (data == lopec_ide_regbase[1]) {
+- alt_status_base = lopec_ide_ctl_regbase[1] + 2;
+- hw->irq = 15;
+- } else {
+- alt_status_base = 0;
+- hw->irq = 0;
+- }
+-
+- if (ctl)
+- hw->io_ports[IDE_CONTROL_OFFSET] = ctl;
+- else
+- hw->io_ports[IDE_CONTROL_OFFSET] = alt_status_base;
+-
+- if (irq != NULL)
+- *irq = hw->irq;
+-
+-}
+-#endif /* BLK_DEV_IDE */
+-
+ static void __init
+ lopec_init_IRQ(void)
+ {
+@@ -384,11 +304,6 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ ppc_md.nvram_read_val = todc_direct_read_val;
+ ppc_md.nvram_write_val = todc_direct_write_val;
+
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+- ppc_ide_md.default_irq = lopec_ide_default_irq;
+- ppc_ide_md.default_io_base = lopec_ide_default_io_base;
+- ppc_ide_md.ide_init_hwif = lopec_ide_init_hwif_ports;
+-#endif
+ #ifdef CONFIG_SERIAL_TEXT_DEBUG
+ ppc_md.progress = gen550_progress;
+ #endif
+diff --git a/arch/ppc/platforms/mpc8272ads_setup.c b/arch/ppc/platforms/mpc8272ads_setup.c
+deleted file mode 100644
+index 47f4b38..0000000
+--- a/arch/ppc/platforms/mpc8272ads_setup.c
++++ /dev/null
+@@ -1,367 +0,0 @@
+-/*
+- * arch/ppc/platforms/mpc8272ads_setup.c
+- *
+- * MPC82xx Board-specific PlatformDevice descriptions
+- *
+- * 2005 (c) MontaVista Software, Inc.
+- * Vitaly Bordug <vbordug at ru.mvista.com>
+- *
+- * This file is licensed under the terms of the GNU General Public License
+- * version 2. This program is licensed "as is" without any warranty of any
+- * kind, whether express or implied.
+- */
+-
+-
+-#include <linux/init.h>
+-#include <linux/module.h>
+-#include <linux/device.h>
+-#include <linux/ioport.h>
+-#include <linux/fs_enet_pd.h>
+-#include <linux/platform_device.h>
+-#include <linux/phy.h>
+-
+-#include <asm/io.h>
+-#include <asm/mpc8260.h>
+-#include <asm/cpm2.h>
+-#include <asm/immap_cpm2.h>
+-#include <asm/irq.h>
+-#include <asm/ppc_sys.h>
+-#include <asm/ppcboot.h>
+-#include <linux/fs_uart_pd.h>
+-
+-#include "pq2ads_pd.h"
+-
+-static void init_fcc1_ioports(struct fs_platform_info*);
+-static void init_fcc2_ioports(struct fs_platform_info*);
+-static void init_scc1_uart_ioports(struct fs_uart_platform_info*);
+-static void init_scc4_uart_ioports(struct fs_uart_platform_info*);
+-
+-static struct fs_uart_platform_info mpc8272_uart_pdata[] = {
+- [fsid_scc1_uart] = {
+- .init_ioports = init_scc1_uart_ioports,
+- .fs_no = fsid_scc1_uart,
+- .brg = 1,
+- .tx_num_fifo = 4,
+- .tx_buf_size = 32,
+- .rx_num_fifo = 4,
+- .rx_buf_size = 32,
+- },
+- [fsid_scc4_uart] = {
+- .init_ioports = init_scc4_uart_ioports,
+- .fs_no = fsid_scc4_uart,
+- .brg = 4,
+- .tx_num_fifo = 4,
+- .tx_buf_size = 32,
+- .rx_num_fifo = 4,
+- .rx_buf_size = 32,
+- },
+-};
+-
+-static struct fs_mii_bb_platform_info m82xx_mii_bb_pdata = {
+- .mdio_dat.bit = 18,
+- .mdio_dir.bit = 18,
+- .mdc_dat.bit = 19,
+- .delay = 1,
+-};
+-
+-static struct fs_platform_info mpc82xx_enet_pdata[] = {
+- [fsid_fcc1] = {
+- .fs_no = fsid_fcc1,
+- .cp_page = CPM_CR_FCC1_PAGE,
+- .cp_block = CPM_CR_FCC1_SBLOCK,
+-
+- .clk_trx = (PC_F1RXCLK | PC_F1TXCLK),
+- .clk_route = CMX1_CLK_ROUTE,
+- .clk_mask = CMX1_CLK_MASK,
+- .init_ioports = init_fcc1_ioports,
+-
+- .mem_offset = FCC1_MEM_OFFSET,
+-
+- .rx_ring = 32,
+- .tx_ring = 32,
+- .rx_copybreak = 240,
+- .use_napi = 0,
+- .napi_weight = 17,
+- .bus_id = "0:00",
+- },
+- [fsid_fcc2] = {
+- .fs_no = fsid_fcc2,
+- .cp_page = CPM_CR_FCC2_PAGE,
+- .cp_block = CPM_CR_FCC2_SBLOCK,
+- .clk_trx = (PC_F2RXCLK | PC_F2TXCLK),
+- .clk_route = CMX2_CLK_ROUTE,
+- .clk_mask = CMX2_CLK_MASK,
+- .init_ioports = init_fcc2_ioports,
+-
+- .mem_offset = FCC2_MEM_OFFSET,
+-
+- .rx_ring = 32,
+- .tx_ring = 32,
+- .rx_copybreak = 240,
+- .use_napi = 0,
+- .napi_weight = 17,
+- .bus_id = "0:03",
+- },
+-};
+-
+-static void init_fcc1_ioports(struct fs_platform_info* pdata)
+-{
+- struct io_port *io;
+- u32 tempval;
+- cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
+- u32 *bcsr = ioremap(BCSR_ADDR+4, sizeof(u32));
+-
+- io = &immap->im_ioport;
+-
+- /* Enable the PHY */
+- clrbits32(bcsr, BCSR1_FETHIEN);
+- setbits32(bcsr, BCSR1_FETH_RST);
+-
+- /* FCC1 pins are on port A/C. */
+- /* Configure port A and C pins for FCC1 Ethernet. */
+-
+- tempval = in_be32(&io->iop_pdira);
+- tempval &= ~PA1_DIRA0;
+- tempval |= PA1_DIRA1;
+- out_be32(&io->iop_pdira, tempval);
+-
+- tempval = in_be32(&io->iop_psora);
+- tempval &= ~PA1_PSORA0;
+- tempval |= PA1_PSORA1;
+- out_be32(&io->iop_psora, tempval);
+-
+- setbits32(&io->iop_ppara,PA1_DIRA0 | PA1_DIRA1);
+-
+- /* Alter clocks */
+- tempval = PC_F1TXCLK|PC_F1RXCLK;
+-
+- clrbits32(&io->iop_psorc, tempval);
+- clrbits32(&io->iop_pdirc, tempval);
+- setbits32(&io->iop_pparc, tempval);
+-
+- clrbits32(&immap->im_cpmux.cmx_fcr, CMX1_CLK_MASK);
+- setbits32(&immap->im_cpmux.cmx_fcr, CMX1_CLK_ROUTE);
+- iounmap(bcsr);
+- iounmap(immap);
+-}
+-
+-static void init_fcc2_ioports(struct fs_platform_info* pdata)
+-{
+- cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
+- u32 *bcsr = ioremap(BCSR_ADDR+12, sizeof(u32));
+-
+- struct io_port *io;
+- u32 tempval;
+-
+- immap = cpm2_immr;
+-
+- io = &immap->im_ioport;
+-
+- /* Enable the PHY */
+- clrbits32(bcsr, BCSR3_FETHIEN2);
+- setbits32(bcsr, BCSR3_FETH2_RST);
+-
+- /* FCC2 are port B/C. */
+- /* Configure port A and C pins for FCC2 Ethernet. */
+-
+- tempval = in_be32(&io->iop_pdirb);
+- tempval &= ~PB2_DIRB0;
+- tempval |= PB2_DIRB1;
+- out_be32(&io->iop_pdirb, tempval);
+-
+- tempval = in_be32(&io->iop_psorb);
+- tempval &= ~PB2_PSORB0;
+- tempval |= PB2_PSORB1;
+- out_be32(&io->iop_psorb, tempval);
+-
+- setbits32(&io->iop_pparb,PB2_DIRB0 | PB2_DIRB1);
+-
+- tempval = PC_F2RXCLK|PC_F2TXCLK;
+-
+- /* Alter clocks */
+- clrbits32(&io->iop_psorc,tempval);
+- clrbits32(&io->iop_pdirc,tempval);
+- setbits32(&io->iop_pparc,tempval);
+-
+- clrbits32(&immap->im_cpmux.cmx_fcr, CMX2_CLK_MASK);
+- setbits32(&immap->im_cpmux.cmx_fcr, CMX2_CLK_ROUTE);
+-
+- iounmap(bcsr);
+- iounmap(immap);
+-}
+-
+-
+-static void __init mpc8272ads_fixup_enet_pdata(struct platform_device *pdev,
+- int idx)
+-{
+- bd_t* bi = (void*)__res;
+- int fs_no = fsid_fcc1+pdev->id-1;
+-
+- if(fs_no >= ARRAY_SIZE(mpc82xx_enet_pdata)) {
+- return;
+- }
+-
+- mpc82xx_enet_pdata[fs_no].dpram_offset=
+- (u32)cpm2_immr->im_dprambase;
+- mpc82xx_enet_pdata[fs_no].fcc_regs_c =
+- (u32)cpm2_immr->im_fcc_c;
+- memcpy(&mpc82xx_enet_pdata[fs_no].macaddr,bi->bi_enetaddr,6);
+-
+- /* prevent dup mac */
+- if(fs_no == fsid_fcc2)
+- mpc82xx_enet_pdata[fs_no].macaddr[5] ^= 1;
+-
+- pdev->dev.platform_data = &mpc82xx_enet_pdata[fs_no];
+-}
+-
+-static void mpc8272ads_fixup_uart_pdata(struct platform_device *pdev,
+- int idx)
+-{
+- bd_t *bd = (bd_t *) __res;
+- struct fs_uart_platform_info *pinfo;
+- int num = ARRAY_SIZE(mpc8272_uart_pdata);
+- int id = fs_uart_id_scc2fsid(idx);
+-
+- /* no need to alter anything if console */
+- if ((id < num) && (!pdev->dev.platform_data)) {
+- pinfo = &mpc8272_uart_pdata[id];
+- pinfo->uart_clk = bd->bi_intfreq;
+- pdev->dev.platform_data = pinfo;
+- }
+-}
+-
+-static void init_scc1_uart_ioports(struct fs_uart_platform_info* pdata)
+-{
+- cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
+-
+- /* SCC1 is only on port D */
+- setbits32(&immap->im_ioport.iop_ppard,0x00000003);
+- clrbits32(&immap->im_ioport.iop_psord,0x00000001);
+- setbits32(&immap->im_ioport.iop_psord,0x00000002);
+- clrbits32(&immap->im_ioport.iop_pdird,0x00000001);
+- setbits32(&immap->im_ioport.iop_pdird,0x00000002);
+-
+- /* Wire BRG1 to SCC1 */
+- clrbits32(&immap->im_cpmux.cmx_scr,0x00ffffff);
+-
+- iounmap(immap);
+-}
+-
+-static void init_scc4_uart_ioports(struct fs_uart_platform_info* pdata)
+-{
+- cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
+-
+- setbits32(&immap->im_ioport.iop_ppard,0x00000600);
+- clrbits32(&immap->im_ioport.iop_psord,0x00000600);
+- clrbits32(&immap->im_ioport.iop_pdird,0x00000200);
+- setbits32(&immap->im_ioport.iop_pdird,0x00000400);
+-
+- /* Wire BRG4 to SCC4 */
+- clrbits32(&immap->im_cpmux.cmx_scr,0x000000ff);
+- setbits32(&immap->im_cpmux.cmx_scr,0x0000001b);
+-
+- iounmap(immap);
+-}
+-
+-static void __init mpc8272ads_fixup_mdio_pdata(struct platform_device *pdev,
+- int idx)
+-{
+- m82xx_mii_bb_pdata.irq[0] = PHY_INTERRUPT;
+- m82xx_mii_bb_pdata.irq[1] = PHY_POLL;
+- m82xx_mii_bb_pdata.irq[2] = PHY_POLL;
+- m82xx_mii_bb_pdata.irq[3] = PHY_INTERRUPT;
+- m82xx_mii_bb_pdata.irq[31] = PHY_POLL;
+-
+-
+- m82xx_mii_bb_pdata.mdio_dat.offset =
+- (u32)&cpm2_immr->im_ioport.iop_pdatc;
+-
+- m82xx_mii_bb_pdata.mdio_dir.offset =
+- (u32)&cpm2_immr->im_ioport.iop_pdirc;
+-
+- m82xx_mii_bb_pdata.mdc_dat.offset =
+- (u32)&cpm2_immr->im_ioport.iop_pdatc;
+-
+-
+- pdev->dev.platform_data = &m82xx_mii_bb_pdata;
+-}
+-
+-static int mpc8272ads_platform_notify(struct device *dev)
+-{
+- static const struct platform_notify_dev_map dev_map[] = {
+- {
+- .bus_id = "fsl-cpm-fcc",
+- .rtn = mpc8272ads_fixup_enet_pdata,
+- },
+- {
+- .bus_id = "fsl-cpm-scc:uart",
+- .rtn = mpc8272ads_fixup_uart_pdata,
+- },
+- {
+- .bus_id = "fsl-bb-mdio",
+- .rtn = mpc8272ads_fixup_mdio_pdata,
+- },
+- {
+- .bus_id = NULL
+- }
+- };
+- platform_notify_map(dev_map,dev);
+-
+- return 0;
+-
+-}
+-
+-int __init mpc8272ads_init(void)
+-{
+- printk(KERN_NOTICE "mpc8272ads: Init\n");
+-
+- platform_notify = mpc8272ads_platform_notify;
+-
+- ppc_sys_device_initfunc();
+-
+- ppc_sys_device_disable_all();
+- ppc_sys_device_enable(MPC82xx_CPM_FCC1);
+- ppc_sys_device_enable(MPC82xx_CPM_FCC2);
+-
+- /* to be ready for console, let's attach pdata here */
+-#ifdef CONFIG_SERIAL_CPM_SCC1
+- ppc_sys_device_setfunc(MPC82xx_CPM_SCC1, PPC_SYS_FUNC_UART);
+- ppc_sys_device_enable(MPC82xx_CPM_SCC1);
+-
+-#endif
+-
+-#ifdef CONFIG_SERIAL_CPM_SCC4
+- ppc_sys_device_setfunc(MPC82xx_CPM_SCC4, PPC_SYS_FUNC_UART);
+- ppc_sys_device_enable(MPC82xx_CPM_SCC4);
+-#endif
+-
+- ppc_sys_device_enable(MPC82xx_MDIO_BB);
+-
+- return 0;
+-}
+-
+-/*
+- To prevent confusion, console selection is gross:
+- by 0 assumed SCC1 and by 1 assumed SCC4
+- */
+-struct platform_device* early_uart_get_pdev(int index)
+-{
+- bd_t *bd = (bd_t *) __res;
+- struct fs_uart_platform_info *pinfo;
+-
+- struct platform_device* pdev = NULL;
+- if(index) { /*assume SCC4 here*/
+- pdev = &ppc_sys_platform_devices[MPC82xx_CPM_SCC4];
+- pinfo = &mpc8272_uart_pdata[fsid_scc4_uart];
+- } else { /*over SCC1*/
+- pdev = &ppc_sys_platform_devices[MPC82xx_CPM_SCC1];
+- pinfo = &mpc8272_uart_pdata[fsid_scc1_uart];
+- }
+-
+- pinfo->uart_clk = bd->bi_intfreq;
+- pdev->dev.platform_data = pinfo;
+- ppc_sys_fixup_mem_resource(pdev, CPM_MAP_ADDR);
+- return NULL;
+-}
+-
+-arch_initcall(mpc8272ads_init);
+diff --git a/arch/ppc/platforms/mpc885ads.h b/arch/ppc/platforms/mpc885ads.h
+deleted file mode 100644
+index d3bbbb3..0000000
+--- a/arch/ppc/platforms/mpc885ads.h
++++ /dev/null
+@@ -1,93 +0,0 @@
+-/*
+- * A collection of structures, addresses, and values associated with
+- * the Freescale MPC885ADS board.
+- * Copied from the FADS stuff.
+- *
+- * Author: MontaVista Software, Inc.
+- * source at mvista.com
+- *
+- * 2005 (c) MontaVista Software, Inc. This file is licensed under the
+- * terms of the GNU General Public License version 2. This program is licensed
+- * "as is" without any warranty of any kind, whether express or implied.
+- */
+-
+-#ifdef __KERNEL__
+-#ifndef __ASM_MPC885ADS_H__
+-#define __ASM_MPC885ADS_H__
+-
+-
+-#include <asm/ppcboot.h>
+-
+-/* U-Boot maps BCSR to 0xff080000 */
+-#define BCSR_ADDR ((uint)0xff080000)
+-#define BCSR_SIZE ((uint)32)
+-#define BCSR0 ((uint)(BCSR_ADDR + 0x00))
+-#define BCSR1 ((uint)(BCSR_ADDR + 0x04))
+-#define BCSR2 ((uint)(BCSR_ADDR + 0x08))
+-#define BCSR3 ((uint)(BCSR_ADDR + 0x0c))
+-#define BCSR4 ((uint)(BCSR_ADDR + 0x10))
+-
+-#define CFG_PHYDEV_ADDR ((uint)0xff0a0000)
+-#define BCSR5 ((uint)(CFG_PHYDEV_ADDR + 0x300))
+-
+-#define IMAP_ADDR ((uint)0xff000000)
+-#define IMAP_SIZE ((uint)(64 * 1024))
+-
+-#define PCMCIA_MEM_ADDR ((uint)0xff020000)
+-#define PCMCIA_MEM_SIZE ((uint)(64 * 1024))
+-
+-/* Bits of interest in the BCSRs.
+- */
+-#define BCSR1_ETHEN ((uint)0x20000000)
+-#define BCSR1_IRDAEN ((uint)0x10000000)
+-#define BCSR1_RS232EN_1 ((uint)0x01000000)
+-#define BCSR1_PCCEN ((uint)0x00800000)
+-#define BCSR1_PCCVCC0 ((uint)0x00400000)
+-#define BCSR1_PCCVPP0 ((uint)0x00200000)
+-#define BCSR1_PCCVPP1 ((uint)0x00100000)
+-#define BCSR1_PCCVPP_MASK (BCSR1_PCCVPP0 | BCSR1_PCCVPP1)
+-#define BCSR1_RS232EN_2 ((uint)0x00040000)
+-#define BCSR1_PCCVCC1 ((uint)0x00010000)
+-#define BCSR1_PCCVCC_MASK (BCSR1_PCCVCC0 | BCSR1_PCCVCC1)
+-
+-#define BCSR4_ETH10_RST ((uint)0x80000000) /* 10Base-T PHY reset*/
+-#define BCSR4_USB_LO_SPD ((uint)0x04000000)
+-#define BCSR4_USB_VCC ((uint)0x02000000)
+-#define BCSR4_USB_FULL_SPD ((uint)0x00040000)
+-#define BCSR4_USB_EN ((uint)0x00020000)
+-
+-#define BCSR5_MII2_EN 0x40
+-#define BCSR5_MII2_RST 0x20
+-#define BCSR5_T1_RST 0x10
+-#define BCSR5_ATM155_RST 0x08
+-#define BCSR5_ATM25_RST 0x04
+-#define BCSR5_MII1_EN 0x02
+-#define BCSR5_MII1_RST 0x01
+-
+-/* Interrupt level assignments */
+-#define PHY_INTERRUPT SIU_IRQ7 /* PHY link change interrupt */
+-#define SIU_INT_FEC1 SIU_LEVEL1 /* FEC1 interrupt */
+-#define SIU_INT_FEC2 SIU_LEVEL3 /* FEC2 interrupt */
+-#define FEC_INTERRUPT SIU_INT_FEC1 /* FEC interrupt */
+-
+-/* We don't use the 8259 */
+-#define NR_8259_INTS 0
+-
+-/* CPM Ethernet through SCC3 */
+-#define PA_ENET_RXD ((ushort)0x0040)
+-#define PA_ENET_TXD ((ushort)0x0080)
+-#define PE_ENET_TCLK ((uint)0x00004000)
+-#define PE_ENET_RCLK ((uint)0x00008000)
+-#define PE_ENET_TENA ((uint)0x00000010)
+-#define PC_ENET_CLSN ((ushort)0x0400)
+-#define PC_ENET_RENA ((ushort)0x0800)
+-
+-/* Control bits in the SICR to route TCLK (CLK5) and RCLK (CLK6) to
+- * SCC3. Also, make sure GR3 (bit 8) and SC3 (bit 9) are zero */
+-#define SICR_ENET_MASK ((uint)0x00ff0000)
+-#define SICR_ENET_CLKRT ((uint)0x002c0000)
+-
+-#define BOARD_CHIP_NAME "MPC885"
+-
+-#endif /* __ASM_MPC885ADS_H__ */
+-#endif /* __KERNEL__ */
+diff --git a/arch/ppc/platforms/mpc885ads_setup.c b/arch/ppc/platforms/mpc885ads_setup.c
+deleted file mode 100644
+index ba06cc0..0000000
+--- a/arch/ppc/platforms/mpc885ads_setup.c
++++ /dev/null
+@@ -1,476 +0,0 @@
+-/*arch/ppc/platforms/mpc885ads_setup.c
+- *
+- * Platform setup for the Freescale mpc885ads board
+- *
+- * Vitaly Bordug <vbordug at ru.mvista.com>
+- *
+- * Copyright 2005 MontaVista Software Inc.
+- *
+- * This file is licensed under the terms of the GNU General Public License
+- * version 2. This program is licensed "as is" without any warranty of any
+- * kind, whether express or implied.
+- */
+-
+-#include <linux/init.h>
+-#include <linux/module.h>
+-#include <linux/param.h>
+-#include <linux/string.h>
+-#include <linux/ioport.h>
+-#include <linux/device.h>
+-
+-#include <linux/fs_enet_pd.h>
+-#include <linux/fs_uart_pd.h>
+-#include <linux/mii.h>
+-
+-#include <asm/delay.h>
+-#include <asm/io.h>
+-#include <asm/machdep.h>
+-#include <asm/page.h>
+-#include <asm/processor.h>
+-#include <asm/system.h>
+-#include <asm/time.h>
+-#include <asm/ppcboot.h>
+-#include <asm/8xx_immap.h>
+-#include <asm/cpm1.h>
+-#include <asm/ppc_sys.h>
+-
+-extern unsigned char __res[];
+-static void setup_smc1_ioports(struct fs_uart_platform_info*);
+-static void setup_smc2_ioports(struct fs_uart_platform_info*);
+-
+-static struct fs_mii_fec_platform_info mpc8xx_mdio_fec_pdata;
+-static void setup_fec1_ioports(struct fs_platform_info*);
+-static void setup_fec2_ioports(struct fs_platform_info*);
+-static void setup_scc3_ioports(struct fs_platform_info*);
+-
+-static struct fs_uart_platform_info mpc885_uart_pdata[] = {
+- [fsid_smc1_uart] = {
+- .brg = 1,
+- .fs_no = fsid_smc1_uart,
+- .init_ioports = setup_smc1_ioports,
+- .tx_num_fifo = 4,
+- .tx_buf_size = 32,
+- .rx_num_fifo = 4,
+- .rx_buf_size = 32,
+- },
+- [fsid_smc2_uart] = {
+- .brg = 2,
+- .fs_no = fsid_smc2_uart,
+- .init_ioports = setup_smc2_ioports,
+- .tx_num_fifo = 4,
+- .tx_buf_size = 32,
+- .rx_num_fifo = 4,
+- .rx_buf_size = 32,
+- },
+-};
+-
+-static struct fs_platform_info mpc8xx_enet_pdata[] = {
+- [fsid_fec1] = {
+- .rx_ring = 128,
+- .tx_ring = 16,
+- .rx_copybreak = 240,
+-
+- .use_napi = 1,
+- .napi_weight = 17,
+-
+- .init_ioports = setup_fec1_ioports,
+-
+- .bus_id = "0:00",
+- .has_phy = 1,
+- },
+- [fsid_fec2] = {
+- .rx_ring = 128,
+- .tx_ring = 16,
+- .rx_copybreak = 240,
+-
+- .use_napi = 1,
+- .napi_weight = 17,
+-
+- .init_ioports = setup_fec2_ioports,
+-
+- .bus_id = "0:01",
+- .has_phy = 1,
+- },
+- [fsid_scc3] = {
+- .rx_ring = 64,
+- .tx_ring = 8,
+- .rx_copybreak = 240,
+-
+- .use_napi = 1,
+- .napi_weight = 17,
+-
+- .init_ioports = setup_scc3_ioports,
+-#ifdef CONFIG_FIXED_MII_10_FDX
+- .bus_id = "fixed at 100:1",
+-#else
+- .bus_id = "0:02",
+- #endif
+- },
+-};
+-
+-void __init board_init(void)
+-{
+- cpm8xx_t *cp = cpmp;
+- unsigned int *bcsr_io;
+-
+-#ifdef CONFIG_FS_ENET
+- immap_t *immap = (immap_t *) IMAP_ADDR;
+-#endif
+- bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+-
+- if (bcsr_io == NULL) {
+- printk(KERN_CRIT "Could not remap BCSR\n");
+- return;
+- }
+-#ifdef CONFIG_SERIAL_CPM_SMC1
+- cp->cp_simode &= ~(0xe0000000 >> 17); /* brg1 */
+- clrbits32(bcsr_io, BCSR1_RS232EN_1);
+- cp->cp_smc[0].smc_smcm |= (SMCM_RX | SMCM_TX);
+- cp->cp_smc[0].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+-#else
+- setbits32(bcsr_io,BCSR1_RS232EN_1);
+- cp->cp_smc[0].smc_smcmr = 0;
+- cp->cp_smc[0].smc_smce = 0;
+-#endif
+-
+-#ifdef CONFIG_SERIAL_CPM_SMC2
+- cp->cp_simode &= ~(0xe0000000 >> 1);
+- cp->cp_simode |= (0x20000000 >> 1); /* brg2 */
+- clrbits32(bcsr_io,BCSR1_RS232EN_2);
+- cp->cp_smc[1].smc_smcm |= (SMCM_RX | SMCM_TX);
+- cp->cp_smc[1].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+-#else
+- setbits32(bcsr_io,BCSR1_RS232EN_2);
+- cp->cp_smc[1].smc_smcmr = 0;
+- cp->cp_smc[1].smc_smce = 0;
+-#endif
+- iounmap(bcsr_io);
+-
+-#ifdef CONFIG_FS_ENET
+- /* use MDC for MII (common) */
+- setbits16(&immap->im_ioport.iop_pdpar, 0x0080);
+- clrbits16(&immap->im_ioport.iop_pddir, 0x0080);
+- bcsr_io = ioremap(BCSR5, sizeof(unsigned long));
+- clrbits32(bcsr_io,BCSR5_MII1_EN);
+- clrbits32(bcsr_io,BCSR5_MII1_RST);
+-#ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2
+- clrbits32(bcsr_io,BCSR5_MII2_EN);
+- clrbits32(bcsr_io,BCSR5_MII2_RST);
+-#endif
+- iounmap(bcsr_io);
+-#endif
+-}
+-
+-static void setup_fec1_ioports(struct fs_platform_info* pdata)
+-{
+- immap_t *immap = (immap_t *) IMAP_ADDR;
+-
+- /* configure FEC1 pins */
+- setbits16(&immap->im_ioport.iop_papar, 0xf830);
+- setbits16(&immap->im_ioport.iop_padir, 0x0830);
+- clrbits16(&immap->im_ioport.iop_padir, 0xf000);
+- setbits32(&immap->im_cpm.cp_pbpar, 0x00001001);
+-
+- clrbits32(&immap->im_cpm.cp_pbdir, 0x00001001);
+- setbits16(&immap->im_ioport.iop_pcpar, 0x000c);
+- clrbits16(&immap->im_ioport.iop_pcdir, 0x000c);
+- setbits32(&immap->im_cpm.cp_pepar, 0x00000003);
+-
+- setbits32(&immap->im_cpm.cp_pedir, 0x00000003);
+- clrbits32(&immap->im_cpm.cp_peso, 0x00000003);
+- clrbits32(&immap->im_cpm.cp_cptr, 0x00000100);
+-}
+-
+-static void setup_fec2_ioports(struct fs_platform_info* pdata)
+-{
+- immap_t *immap = (immap_t *) IMAP_ADDR;
+-
+- /* configure FEC2 pins */
+- setbits32(&immap->im_cpm.cp_pepar, 0x0003fffc);
+- setbits32(&immap->im_cpm.cp_pedir, 0x0003fffc);
+- clrbits32(&immap->im_cpm.cp_peso, 0x000087fc);
+- setbits32(&immap->im_cpm.cp_peso, 0x00037800);
+- clrbits32(&immap->im_cpm.cp_cptr, 0x00000080);
+-}
+-
+-static void setup_scc3_ioports(struct fs_platform_info* pdata)
+-{
+- immap_t *immap = (immap_t *) IMAP_ADDR;
+- unsigned *bcsr_io;
+-
+- bcsr_io = ioremap(BCSR_ADDR, BCSR_SIZE);
+-
+- if (bcsr_io == NULL) {
+- printk(KERN_CRIT "Could not remap BCSR\n");
+- return;
+- }
+-
+- /* Enable the PHY.
+- */
+- clrbits32(bcsr_io+4, BCSR4_ETH10_RST);
+- udelay(1000);
+- setbits32(bcsr_io+4, BCSR4_ETH10_RST);
+- /* Configure port A pins for Txd and Rxd.
+- */
+- setbits16(&immap->im_ioport.iop_papar, PA_ENET_RXD | PA_ENET_TXD);
+- clrbits16(&immap->im_ioport.iop_padir, PA_ENET_RXD | PA_ENET_TXD);
+-
+- /* Configure port C pins to enable CLSN and RENA.
+- */
+- clrbits16(&immap->im_ioport.iop_pcpar, PC_ENET_CLSN | PC_ENET_RENA);
+- clrbits16(&immap->im_ioport.iop_pcdir, PC_ENET_CLSN | PC_ENET_RENA);
+- setbits16(&immap->im_ioport.iop_pcso, PC_ENET_CLSN | PC_ENET_RENA);
+-
+- /* Configure port E for TCLK and RCLK.
+- */
+- setbits32(&immap->im_cpm.cp_pepar, PE_ENET_TCLK | PE_ENET_RCLK);
+- clrbits32(&immap->im_cpm.cp_pepar, PE_ENET_TENA);
+- clrbits32(&immap->im_cpm.cp_pedir,
+- PE_ENET_TCLK | PE_ENET_RCLK | PE_ENET_TENA);
+- clrbits32(&immap->im_cpm.cp_peso, PE_ENET_TCLK | PE_ENET_RCLK);
+- setbits32(&immap->im_cpm.cp_peso, PE_ENET_TENA);
+-
+- /* Configure Serial Interface clock routing.
+- * First, clear all SCC bits to zero, then set the ones we want.
+- */
+- clrbits32(&immap->im_cpm.cp_sicr, SICR_ENET_MASK);
+- setbits32(&immap->im_cpm.cp_sicr, SICR_ENET_CLKRT);
+-
+- /* Disable Rx and Tx. SMC1 sshould be stopped if SCC3 eternet are used.
+- */
+- immap->im_cpm.cp_smc[0].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+- /* On the MPC885ADS SCC ethernet PHY is initialized in the full duplex mode
+- * by H/W setting after reset. SCC ethernet controller support only half duplex.
+- * This discrepancy of modes causes a lot of carrier lost errors.
+- */
+-
+- /* In the original SCC enet driver the following code is placed at
+- the end of the initialization */
+- setbits32(&immap->im_cpm.cp_pepar, PE_ENET_TENA);
+- clrbits32(&immap->im_cpm.cp_pedir, PE_ENET_TENA);
+- setbits32(&immap->im_cpm.cp_peso, PE_ENET_TENA);
+-
+- setbits32(bcsr_io+4, BCSR1_ETHEN);
+- iounmap(bcsr_io);
+-}
+-
+-static int mac_count = 0;
+-
+-static void mpc885ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
+-{
+- struct fs_platform_info *fpi;
+- bd_t *bd = (bd_t *) __res;
+- char *e;
+- int i;
+-
+- if(fs_no >= ARRAY_SIZE(mpc8xx_enet_pdata)) {
+- printk(KERN_ERR"No network-suitable #%d device on bus", fs_no);
+- return;
+- }
+-
+- fpi = &mpc8xx_enet_pdata[fs_no];
+-
+- switch (fs_no) {
+- case fsid_fec1:
+- fpi->init_ioports = &setup_fec1_ioports;
+- break;
+- case fsid_fec2:
+- fpi->init_ioports = &setup_fec2_ioports;
+- break;
+- case fsid_scc3:
+- fpi->init_ioports = &setup_scc3_ioports;
+- break;
+- default:
+- printk(KERN_WARNING "Device %s is not supported!\n", pdev->name);
+- return;
+- }
+-
+- pdev->dev.platform_data = fpi;
+- fpi->fs_no = fs_no;
+-
+- e = (unsigned char *)&bd->bi_enetaddr;
+- for (i = 0; i < 6; i++)
+- fpi->macaddr[i] = *e++;
+-
+- fpi->macaddr[5] += mac_count++;
+-
+-}
+-
+-static void mpc885ads_fixup_fec_enet_pdata(struct platform_device *pdev,
+- int idx)
+-{
+- /* This is for FEC devices only */
+- if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-fec")))
+- return;
+- mpc885ads_fixup_enet_pdata(pdev, fsid_fec1 + pdev->id - 1);
+-}
+-
+-static void __init mpc885ads_fixup_scc_enet_pdata(struct platform_device *pdev,
+- int idx)
+-{
+- /* This is for SCC devices only */
+- if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-scc")))
+- return;
+-
+- mpc885ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
+-}
+-
+-static void setup_smc1_ioports(struct fs_uart_platform_info* pdata)
+-{
+- immap_t *immap = (immap_t *) IMAP_ADDR;
+- unsigned *bcsr_io;
+- unsigned int iobits = 0x000000c0;
+-
+- bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+-
+- if (bcsr_io == NULL) {
+- printk(KERN_CRIT "Could not remap BCSR1\n");
+- return;
+- }
+- clrbits32(bcsr_io,BCSR1_RS232EN_1);
+- iounmap(bcsr_io);
+-
+- setbits32(&immap->im_cpm.cp_pbpar, iobits);
+- clrbits32(&immap->im_cpm.cp_pbdir, iobits);
+- clrbits16(&immap->im_cpm.cp_pbodr, iobits);
+-}
+-
+-static void setup_smc2_ioports(struct fs_uart_platform_info* pdata)
+-{
+- immap_t *immap = (immap_t *) IMAP_ADDR;
+- unsigned *bcsr_io;
+- unsigned int iobits = 0x00000c00;
+-
+- bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+-
+- if (bcsr_io == NULL) {
+- printk(KERN_CRIT "Could not remap BCSR1\n");
+- return;
+- }
+- clrbits32(bcsr_io,BCSR1_RS232EN_2);
+- iounmap(bcsr_io);
+-
+-#ifndef CONFIG_SERIAL_CPM_ALT_SMC2
+- setbits32(&immap->im_cpm.cp_pbpar, iobits);
+- clrbits32(&immap->im_cpm.cp_pbdir, iobits);
+- clrbits16(&immap->im_cpm.cp_pbodr, iobits);
+-#else
+- setbits16(&immap->im_ioport.iop_papar, iobits);
+- clrbits16(&immap->im_ioport.iop_padir, iobits);
+- clrbits16(&immap->im_ioport.iop_paodr, iobits);
+-#endif
+-}
+-
+-static void __init mpc885ads_fixup_uart_pdata(struct platform_device *pdev,
+- int idx)
+-{
+- bd_t *bd = (bd_t *) __res;
+- struct fs_uart_platform_info *pinfo;
+- int num = ARRAY_SIZE(mpc885_uart_pdata);
+-
+- int id = fs_uart_id_smc2fsid(idx);
+-
+- /* no need to alter anything if console */
+- if ((id < num) && (!pdev->dev.platform_data)) {
+- pinfo = &mpc885_uart_pdata[id];
+- pinfo->uart_clk = bd->bi_intfreq;
+- pdev->dev.platform_data = pinfo;
+- }
+-}
+-
+-
+-static int mpc885ads_platform_notify(struct device *dev)
+-{
+-
+- static const struct platform_notify_dev_map dev_map[] = {
+- {
+- .bus_id = "fsl-cpm-fec",
+- .rtn = mpc885ads_fixup_fec_enet_pdata,
+- },
+- {
+- .bus_id = "fsl-cpm-scc",
+- .rtn = mpc885ads_fixup_scc_enet_pdata,
+- },
+- {
+- .bus_id = "fsl-cpm-smc:uart",
+- .rtn = mpc885ads_fixup_uart_pdata
+- },
+- {
+- .bus_id = NULL
+- }
+- };
+-
+- platform_notify_map(dev_map,dev);
+-
+- return 0;
+-}
+-
+-int __init mpc885ads_init(void)
+-{
+- struct fs_mii_fec_platform_info* fmpi;
+- bd_t *bd = (bd_t *) __res;
+-
+- printk(KERN_NOTICE "mpc885ads: Init\n");
+-
+- platform_notify = mpc885ads_platform_notify;
+-
+- ppc_sys_device_initfunc();
+- ppc_sys_device_disable_all();
+-
+- ppc_sys_device_enable(MPC8xx_CPM_FEC1);
+-
+- ppc_sys_device_enable(MPC8xx_MDIO_FEC);
+- fmpi = ppc_sys_platform_devices[MPC8xx_MDIO_FEC].dev.platform_data =
+- &mpc8xx_mdio_fec_pdata;
+-
+- fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1;
+-
+- /* No PHY interrupt line here */
+- fmpi->irq[0xf] = SIU_IRQ7;
+-
+-#ifdef CONFIG_MPC8xx_SECOND_ETH_SCC3
+- ppc_sys_device_enable(MPC8xx_CPM_SCC3);
+-
+-#endif
+-#ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2
+- ppc_sys_device_enable(MPC8xx_CPM_FEC2);
+-#endif
+-
+-#ifdef CONFIG_SERIAL_CPM_SMC1
+- ppc_sys_device_enable(MPC8xx_CPM_SMC1);
+- ppc_sys_device_setfunc(MPC8xx_CPM_SMC1, PPC_SYS_FUNC_UART);
+-#endif
+-
+-#ifdef CONFIG_SERIAL_CPM_SMC2
+- ppc_sys_device_enable(MPC8xx_CPM_SMC2);
+- ppc_sys_device_setfunc(MPC8xx_CPM_SMC2, PPC_SYS_FUNC_UART);
+-#endif
+- return 0;
+-}
+-
+-arch_initcall(mpc885ads_init);
+-
+-/*
+- To prevent confusion, console selection is gross:
+- by 0 assumed SMC1 and by 1 assumed SMC2
+- */
+-struct platform_device* early_uart_get_pdev(int index)
+-{
+- bd_t *bd = (bd_t *) __res;
+- struct fs_uart_platform_info *pinfo;
+-
+- struct platform_device* pdev = NULL;
+- if(index) { /*assume SMC2 here*/
+- pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC2];
+- pinfo = &mpc885_uart_pdata[1];
+- } else { /*over SMC1*/
+- pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC1];
+- pinfo = &mpc885_uart_pdata[0];
+- }
+-
+- pinfo->uart_clk = bd->bi_intfreq;
+- pdev->dev.platform_data = pinfo;
+- ppc_sys_fixup_mem_resource(pdev, IMAP_ADDR);
+- return NULL;
+-}
+-
+diff --git a/arch/ppc/platforms/mvme5100.c b/arch/ppc/platforms/mvme5100.c
+index bb8d4a4..053b54a 100644
+--- a/arch/ppc/platforms/mvme5100.c
++++ b/arch/ppc/platforms/mvme5100.c
+@@ -17,7 +17,6 @@
+ #include <linux/initrd.h>
+ #include <linux/console.h>
+ #include <linux/delay.h>
+-#include <linux/ide.h>
+ #include <linux/seq_file.h>
+ #include <linux/kdev_t.h>
+ #include <linux/root_dev.h>
+diff --git a/arch/ppc/platforms/powerpmc250.c b/arch/ppc/platforms/powerpmc250.c
+index 4d46650..162dc85 100644
+--- a/arch/ppc/platforms/powerpmc250.c
++++ b/arch/ppc/platforms/powerpmc250.c
+@@ -25,7 +25,6 @@
+ #include <linux/delay.h>
+ #include <linux/slab.h>
+ #include <linux/seq_file.h>
+-#include <linux/ide.h>
+ #include <linux/root_dev.h>
+
+ #include <asm/byteorder.h>
+diff --git a/arch/ppc/platforms/pplus.c b/arch/ppc/platforms/pplus.c
+index 8a1788c..cbcac85 100644
+--- a/arch/ppc/platforms/pplus.c
++++ b/arch/ppc/platforms/pplus.c
+@@ -19,7 +19,6 @@
+ #include <linux/ioport.h>
+ #include <linux/console.h>
+ #include <linux/pci.h>
+-#include <linux/ide.h>
+ #include <linux/seq_file.h>
+ #include <linux/root_dev.h>
+
+@@ -668,57 +667,6 @@ static void __init pplus_init_IRQ(void)
+ ppc_md.progress("init_irq: exit", 0);
+ }
+
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+-/*
+- * IDE stuff.
+- */
+-static int pplus_ide_default_irq(unsigned long base)
+-{
+- switch (base) {
+- case 0x1f0:
+- return 14;
+- case 0x170:
+- return 15;
+- default:
+- return 0;
+- }
+-}
+-
+-static unsigned long pplus_ide_default_io_base(int index)
+-{
+- switch (index) {
+- case 0:
+- return 0x1f0;
+- case 1:
+- return 0x170;
+- default:
+- return 0;
+- }
+-}
+-
+-static void __init
+-pplus_ide_init_hwif_ports(hw_regs_t * hw, unsigned long data_port,
+- unsigned long ctrl_port, int *irq)
+-{
+- unsigned long reg = data_port;
+- int i;
+-
+- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+- hw->io_ports[i] = reg;
+- reg += 1;
+- }
+-
+- if (ctrl_port)
+- hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+- else
+- hw->io_ports[IDE_CONTROL_OFFSET] =
+- hw->io_ports[IDE_DATA_OFFSET] + 0x206;
+-
+- if (irq != NULL)
+- *irq = pplus_ide_default_irq(data_port);
+-}
+-#endif
+-
+ #ifdef CONFIG_SMP
+ /* PowerPlus (MTX) support */
+ static int __init smp_pplus_probe(void)
+@@ -884,12 +832,6 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ ppc_md.find_end_of_memory = pplus_find_end_of_memory;
+ ppc_md.setup_io_mappings = pplus_map_io;
+
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+- ppc_ide_md.default_irq = pplus_ide_default_irq;
+- ppc_ide_md.default_io_base = pplus_ide_default_io_base;
+- ppc_ide_md.ide_init_hwif = pplus_ide_init_hwif_ports;
+-#endif
+-
+ #ifdef CONFIG_SERIAL_TEXT_DEBUG
+ ppc_md.progress = gen550_progress;
+ #endif /* CONFIG_SERIAL_TEXT_DEBUG */
+diff --git a/arch/ppc/platforms/pq2ads.c b/arch/ppc/platforms/pq2ads.c
+deleted file mode 100644
+index 7fc2e02..0000000
+--- a/arch/ppc/platforms/pq2ads.c
++++ /dev/null
+@@ -1,53 +0,0 @@
+-/*
+- * PQ2ADS platform support
+- *
+- * Author: Kumar Gala <galak at kernel.crashing.org>
+- * Derived from: est8260_setup.c by Allen Curtis
+- *
+- * Copyright 2004 Freescale Semiconductor, Inc.
+- *
+- * 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/init.h>
+-
+-#include <asm/io.h>
+-#include <asm/mpc8260.h>
+-#include <asm/cpm2.h>
+-#include <asm/immap_cpm2.h>
+-
+-void __init
+-m82xx_board_setup(void)
+-{
+- cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
+- u32 *bcsr = ioremap(BCSR_ADDR+4, sizeof(u32));
+-
+- /* Enable the 2nd UART port */
+- clrbits32(bcsr, BCSR1_RS232_EN2);
+-
+-#ifdef CONFIG_SERIAL_CPM_SCC1
+- clrbits32((u32*)&immap->im_scc[0].scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
+- clrbits32((u32*)&immap->im_scc[0].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+-#endif
+-
+-#ifdef CONFIG_SERIAL_CPM_SCC2
+- clrbits32((u32*)&immap->im_scc[1].scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
+- clrbits32((u32*)&immap->im_scc[1].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+-#endif
+-
+-#ifdef CONFIG_SERIAL_CPM_SCC3
+- clrbits32((u32*)&immap->im_scc[2].scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
+- clrbits32((u32*)&immap->im_scc[2].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+-#endif
+-
+-#ifdef CONFIG_SERIAL_CPM_SCC4
+- clrbits32((u32*)&immap->im_scc[3].scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
+- clrbits32((u32*)&immap->im_scc[3].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+-#endif
+-
+- iounmap(bcsr);
+- iounmap(immap);
+-}
+diff --git a/arch/ppc/platforms/pq2ads.h b/arch/ppc/platforms/pq2ads.h
+deleted file mode 100644
+index 2b287f4..0000000
+--- a/arch/ppc/platforms/pq2ads.h
++++ /dev/null
+@@ -1,94 +0,0 @@
+-/*
+- * A collection of structures, addresses, and values associated with
+- * the Motorola MPC8260ADS/MPC8266ADS-PCI boards.
+- * Copied from the RPX-Classic and SBS8260 stuff.
+- *
+- * Copyright (c) 2001 Dan Malek (dan at mvista.com)
+- */
+-#ifdef __KERNEL__
+-#ifndef __MACH_ADS8260_DEFS
+-#define __MACH_ADS8260_DEFS
+-
+-
+-#include <asm/ppcboot.h>
+-
+-#if defined(CONFIG_ADS8272)
+-#define BOARD_CHIP_NAME "8272"
+-#endif
+-
+-/* Memory map is configured by the PROM startup.
+- * We just map a few things we need. The CSR is actually 4 byte-wide
+- * registers that can be accessed as 8-, 16-, or 32-bit values.
+- */
+-#define CPM_MAP_ADDR ((uint)0xf0000000)
+-#define BCSR_ADDR ((uint)0xf4500000)
+-#define BCSR_SIZE ((uint)(32 * 1024))
+-
+-#define BOOTROM_RESTART_ADDR ((uint)0xff000104)
+-
+-/* For our show_cpuinfo hooks. */
+-#define CPUINFO_VENDOR "Motorola"
+-#define CPUINFO_MACHINE "PQ2 ADS PowerPC"
+-
+-/* The ADS8260 has 16, 32-bit wide control/status registers, accessed
+- * only on word boundaries.
+- * Not all are used (yet), or are interesting to us (yet).
+- */
+-
+-/* Things of interest in the CSR.
+-*/
+-#define BCSR0_LED0 ((uint)0x02000000) /* 0 == on */
+-#define BCSR0_LED1 ((uint)0x01000000) /* 0 == on */
+-#define BCSR1_FETHIEN ((uint)0x08000000) /* 0 == enable */
+-#define BCSR1_FETH_RST ((uint)0x04000000) /* 0 == reset */
+-#define BCSR1_RS232_EN1 ((uint)0x02000000) /* 0 == enable */
+-#define BCSR1_RS232_EN2 ((uint)0x01000000) /* 0 == enable */
+-#define BCSR3_FETHIEN2 ((uint)0x10000000) /* 0 == enable */
+-#define BCSR3_FETH2_RST ((uint)0x80000000) /* 0 == reset */
+-
+-#define PHY_INTERRUPT SIU_INT_IRQ7
+-
+-#ifdef CONFIG_PCI
+-/* PCI interrupt controller */
+-#define PCI_INT_STAT_REG 0xF8200000
+-#define PCI_INT_MASK_REG 0xF8200004
+-#define PIRQA (NR_CPM_INTS + 0)
+-#define PIRQB (NR_CPM_INTS + 1)
+-#define PIRQC (NR_CPM_INTS + 2)
+-#define PIRQD (NR_CPM_INTS + 3)
+-
+-/*
+- * PCI memory map definitions for MPC8266ADS-PCI.
+- *
+- * processor view
+- * local address PCI address target
+- * 0x80000000-0x9FFFFFFF 0x80000000-0x9FFFFFFF PCI mem with prefetch
+- * 0xA0000000-0xBFFFFFFF 0xA0000000-0xBFFFFFFF PCI mem w/o prefetch
+- * 0xF4000000-0xF7FFFFFF 0x00000000-0x03FFFFFF PCI IO
+- *
+- * PCI master view
+- * local address PCI address target
+- * 0x00000000-0x1FFFFFFF 0x00000000-0x1FFFFFFF MPC8266 local memory
+- */
+-
+-/* All the other PCI memory map definitions reside at syslib/m82xx_pci.h
+- Here we should redefine what is unique for this board */
+-#define M82xx_PCI_SLAVE_MEM_LOCAL 0x00000000 /* Local base */
+-#define M82xx_PCI_SLAVE_MEM_BUS 0x00000000 /* PCI base */
+-#define M82xx_PCI_SLAVE_MEM_SIZE 0x10000000 /* 256 Mb */
+-
+-#define M82xx_PCI_SLAVE_SEC_WND_SIZE ~(0x40000000 - 1U) /* 2 x 512Mb */
+-#define M82xx_PCI_SLAVE_SEC_WND_BASE 0x80000000 /* PCI Memory base */
+-
+-#if defined(CONFIG_ADS8272)
+-#define PCI_INT_TO_SIU SIU_INT_IRQ2
+-#elif defined(CONFIG_PQ2FADS)
+-#define PCI_INT_TO_SIU SIU_INT_IRQ6
+-#else
+-#warning PCI Bridge will be without interrupts support
+-#endif
+-
+-#endif /* CONFIG_PCI */
+-
+-#endif /* __MACH_ADS8260_DEFS */
+-#endif /* __KERNEL__ */
+diff --git a/arch/ppc/platforms/pq2ads_pd.h b/arch/ppc/platforms/pq2ads_pd.h
+deleted file mode 100644
+index 672483d..0000000
+--- a/arch/ppc/platforms/pq2ads_pd.h
++++ /dev/null
+@@ -1,32 +0,0 @@
+-#ifndef __PQ2ADS_PD_H
+-#define __PQ2ADS_PD_H
+-/*
+- * arch/ppc/platforms/82xx/pq2ads_pd.h
+- *
+- * Some defines for MPC82xx board-specific PlatformDevice descriptions
+- *
+- * 2005 (c) MontaVista Software, Inc.
+- * Vitaly Bordug <vbordug at ru.mvista.com>
+- *
+- * This file is licensed under the terms of the GNU General Public License
+- * version 2. This program is licensed "as is" without any warranty of any
+- * kind, whether express or implied.
+- */
+-
+-/* FCC1 Clock Source Configuration. These can be redefined in the board specific file.
+- Can only choose from CLK9-12 */
+-
+-#define F1_RXCLK 11
+-#define F1_TXCLK 10
+-
+-/* FCC2 Clock Source Configuration. These can be redefined in the board specific file.
+- Can only choose from CLK13-16 */
+-#define F2_RXCLK 15
+-#define F2_TXCLK 16
+-
+-/* FCC3 Clock Source Configuration. These can be redefined in the board specific file.
+- Can only choose from CLK13-16 */
+-#define F3_RXCLK 13
+-#define F3_TXCLK 14
+-
+-#endif
+diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c
+index 3844985..465b658 100644
+--- a/arch/ppc/platforms/prep_setup.c
++++ b/arch/ppc/platforms/prep_setup.c
+@@ -33,7 +33,6 @@
+ #include <linux/console.h>
+ #include <linux/timex.h>
+ #include <linux/pci.h>
+-#include <linux/ide.h>
+ #include <linux/seq_file.h>
+ #include <linux/root_dev.h>
+
+@@ -894,38 +893,6 @@ prep_init_IRQ(void)
+ i8259_init(MPC10X_MAPA_PCI_INTACK_ADDR, 0);
+ }
+
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+-/*
+- * IDE stuff.
+- */
+-static int
+-prep_ide_default_irq(unsigned long base)
+-{
+- switch (base) {
+- case 0x1f0: return 13;
+- case 0x170: return 13;
+- case 0x1e8: return 11;
+- case 0x168: return 10;
+- case 0xfff0: return 14; /* MCP(N)750 ide0 */
+- case 0xffe0: return 15; /* MCP(N)750 ide1 */
+- default: return 0;
+- }
+-}
+-
+-static unsigned long
+-prep_ide_default_io_base(int index)
+-{
+- switch (index) {
+- case 0: return 0x1f0;
+- case 1: return 0x170;
+- case 2: return 0x1e8;
+- case 3: return 0x168;
+- default:
+- return 0;
+- }
+-}
+-#endif
+-
+ #ifdef CONFIG_SMP
+ /* PReP (MTX) support */
+ static int __init
+@@ -1070,11 +1037,6 @@ prep_init(unsigned long r3, unsigned long r4, unsigned long r5,
+
+ ppc_md.setup_io_mappings = prep_map_io;
+
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+- ppc_ide_md.default_irq = prep_ide_default_irq;
+- ppc_ide_md.default_io_base = prep_ide_default_io_base;
+-#endif
+-
+ #ifdef CONFIG_SMP
+ smp_ops = &prep_smp_ops;
+ #endif /* CONFIG_SMP */
+diff --git a/arch/ppc/platforms/prpmc750.c b/arch/ppc/platforms/prpmc750.c
+index fcab513..93bd593 100644
+--- a/arch/ppc/platforms/prpmc750.c
++++ b/arch/ppc/platforms/prpmc750.c
+@@ -22,7 +22,6 @@
+ #include <linux/console.h>
+ #include <linux/delay.h>
+ #include <linux/seq_file.h>
+-#include <linux/ide.h>
+ #include <linux/root_dev.h>
+ #include <linux/slab.h>
+ #include <linux/serial_reg.h>
+diff --git a/arch/ppc/platforms/prpmc800.c b/arch/ppc/platforms/prpmc800.c
+index f4ade5c..5bcda7f 100644
+--- a/arch/ppc/platforms/prpmc800.c
++++ b/arch/ppc/platforms/prpmc800.c
+@@ -20,7 +20,6 @@
+ #include <linux/console.h>
+ #include <linux/delay.h>
+ #include <linux/seq_file.h>
+-#include <linux/ide.h>
+ #include <linux/root_dev.h>
+ #include <linux/harrier_defs.h>
+
+diff --git a/arch/ppc/platforms/radstone_ppc7d.c b/arch/ppc/platforms/radstone_ppc7d.c
+index 44d4398..f1dee1e 100644
+--- a/arch/ppc/platforms/radstone_ppc7d.c
++++ b/arch/ppc/platforms/radstone_ppc7d.c
+@@ -29,7 +29,6 @@
+ #include <linux/initrd.h>
+ #include <linux/console.h>
+ #include <linux/delay.h>
+-#include <linux/ide.h>
+ #include <linux/seq_file.h>
+ #include <linux/root_dev.h>
+ #include <linux/serial.h>
+@@ -512,7 +511,7 @@ static void __init ppc7d_init_irq(void)
+ {
+ int irq;
+
+- pr_debug("%s\n", __FUNCTION__);
++ pr_debug("%s\n", __func__);
+ i8259_init(0, 0);
+ mv64360_init_irq();
+
+@@ -569,7 +568,7 @@ static int __init ppc7d_map_irq(struct pci_dev *dev, unsigned char idsel,
+ };
+ const long min_idsel = 10, max_idsel = 14, irqs_per_slot = 4;
+
+- pr_debug("%s: %04x/%04x/%x: idsel=%hx pin=%hu\n", __FUNCTION__,
++ pr_debug("%s: %04x/%04x/%x: idsel=%hx pin=%hu\n", __func__,
+ dev->vendor, dev->device, PCI_FUNC(dev->devfn), idsel, pin);
+
+ return PCI_IRQ_TABLE_LOOKUP;
+@@ -1300,7 +1299,7 @@ static void ppc7d_init2(void)
+ u32 data;
+ u8 data8;
+
+- pr_debug("%s: enter\n", __FUNCTION__);
++ pr_debug("%s: enter\n", __func__);
+
+ /* Wait for debugger? */
+ if (ppc7d_wait_debugger) {
+@@ -1333,7 +1332,7 @@ static void ppc7d_init2(void)
+ ppc_md.set_rtc_time = ppc7d_set_rtc_time;
+ ppc_md.get_rtc_time = ppc7d_get_rtc_time;
+
+- pr_debug("%s: exit\n", __FUNCTION__);
++ pr_debug("%s: exit\n", __func__);
+ }
+
+ /* Called from machine_init(), early, before any of the __init functions
+diff --git a/arch/ppc/platforms/residual.c b/arch/ppc/platforms/residual.c
+index c991160..18495e7 100644
+--- a/arch/ppc/platforms/residual.c
++++ b/arch/ppc/platforms/residual.c
+@@ -38,7 +38,6 @@
+ #include <linux/init.h>
+ #include <linux/ioport.h>
+ #include <linux/pci.h>
+-#include <linux/ide.h>
+
+ #include <asm/sections.h>
+ #include <asm/mmu.h>
+diff --git a/arch/ppc/platforms/sandpoint.c b/arch/ppc/platforms/sandpoint.c
+index 3352fae..b4897bd 100644
+--- a/arch/ppc/platforms/sandpoint.c
++++ b/arch/ppc/platforms/sandpoint.c
+@@ -71,7 +71,6 @@
+ #include <linux/initrd.h>
+ #include <linux/console.h>
+ #include <linux/delay.h>
+-#include <linux/ide.h>
+ #include <linux/seq_file.h>
+ #include <linux/root_dev.h>
+ #include <linux/serial.h>
+@@ -559,93 +558,6 @@ sandpoint_show_cpuinfo(struct seq_file *m)
+ return 0;
+ }
+
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+-/*
+- * IDE support.
+- */
+-static int sandpoint_ide_ports_known = 0;
+-static unsigned long sandpoint_ide_regbase[MAX_HWIFS];
+-static unsigned long sandpoint_ide_ctl_regbase[MAX_HWIFS];
+-static unsigned long sandpoint_idedma_regbase;
+-
+-static void
+-sandpoint_ide_probe(void)
+-{
+- struct pci_dev *pdev = pci_get_device(PCI_VENDOR_ID_WINBOND,
+- PCI_DEVICE_ID_WINBOND_82C105, NULL);
+-
+- if (pdev) {
+- sandpoint_ide_regbase[0]=pdev->resource[0].start;
+- sandpoint_ide_regbase[1]=pdev->resource[2].start;
+- sandpoint_ide_ctl_regbase[0]=pdev->resource[1].start;
+- sandpoint_ide_ctl_regbase[1]=pdev->resource[3].start;
+- sandpoint_idedma_regbase=pdev->resource[4].start;
+- pci_dev_put(pdev);
+- }
+-
+- sandpoint_ide_ports_known = 1;
+-}
+-
+-static int
+-sandpoint_ide_default_irq(unsigned long base)
+-{
+- if (sandpoint_ide_ports_known == 0)
+- sandpoint_ide_probe();
+-
+- if (base == sandpoint_ide_regbase[0])
+- return SANDPOINT_IDE_INT0;
+- else if (base == sandpoint_ide_regbase[1])
+- return SANDPOINT_IDE_INT1;
+- else
+- return 0;
+-}
+-
+-static unsigned long
+-sandpoint_ide_default_io_base(int index)
+-{
+- if (sandpoint_ide_ports_known == 0)
+- sandpoint_ide_probe();
+-
+- return sandpoint_ide_regbase[index];
+-}
+-
+-static void __init
+-sandpoint_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+- unsigned long ctrl_port, int *irq)
+-{
+- unsigned long reg = data_port;
+- uint alt_status_base;
+- int i;
+-
+- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+- hw->io_ports[i] = reg++;
+- }
+-
+- if (data_port == sandpoint_ide_regbase[0]) {
+- alt_status_base = sandpoint_ide_ctl_regbase[0] + 2;
+- hw->irq = 14;
+- }
+- else if (data_port == sandpoint_ide_regbase[1]) {
+- alt_status_base = sandpoint_ide_ctl_regbase[1] + 2;
+- hw->irq = 15;
+- }
+- else {
+- alt_status_base = 0;
+- hw->irq = 0;
+- }
+-
+- if (ctrl_port) {
+- hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+- } else {
+- hw->io_ports[IDE_CONTROL_OFFSET] = alt_status_base;
+- }
+-
+- if (irq != NULL) {
+- *irq = hw->irq;
+- }
+-}
+-#endif
+-
+ /*
+ * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1.
+ */
+@@ -736,10 +648,4 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ #ifdef CONFIG_SERIAL_TEXT_DEBUG
+ ppc_md.progress = gen550_progress;
+ #endif
+-
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+- ppc_ide_md.default_irq = sandpoint_ide_default_irq;
+- ppc_ide_md.default_io_base = sandpoint_ide_default_io_base;
+- ppc_ide_md.ide_init_hwif = sandpoint_ide_init_hwif_ports;
+-#endif
+ }
+diff --git a/arch/ppc/platforms/sandpoint.h b/arch/ppc/platforms/sandpoint.h
+index 3b64e64..ed83759 100644
+--- a/arch/ppc/platforms/sandpoint.h
++++ b/arch/ppc/platforms/sandpoint.h
+@@ -28,9 +28,6 @@
+ */
+ #define SANDPOINT_IDE_INT0 23 /* EPIC 7 */
+ #define SANDPOINT_IDE_INT1 24 /* EPIC 8 */
+-#else
+-#define SANDPOINT_IDE_INT0 14 /* 8259 Test */
+-#define SANDPOINT_IDE_INT1 15 /* 8259 Test */
+ #endif
+
+ /*
+diff --git a/arch/ppc/platforms/sbc82xx.c b/arch/ppc/platforms/sbc82xx.c
+index cc0935c..0df6aac 100644
+--- a/arch/ppc/platforms/sbc82xx.c
++++ b/arch/ppc/platforms/sbc82xx.c
+@@ -121,8 +121,10 @@ struct hw_interrupt_type sbc82xx_i8259_ic = {
+ .end = sbc82xx_i8259_end_irq,
+ };
+
+-static irqreturn_t sbc82xx_i8259_demux(int irq, void *dev_id)
++static irqreturn_t sbc82xx_i8259_demux(int dummy, void *dev_id)
+ {
++ int irq;
++
+ spin_lock(&sbc82xx_i8259_lock);
+
+ sbc82xx_i8259_map[0] = 0x0c; /* OCW3: Read IR register on RD# pulse */
+diff --git a/arch/ppc/platforms/spruce.c b/arch/ppc/platforms/spruce.c
+index f4de50b..a344134 100644
+--- a/arch/ppc/platforms/spruce.c
++++ b/arch/ppc/platforms/spruce.c
+@@ -22,7 +22,6 @@
+ #include <linux/console.h>
+ #include <linux/delay.h>
+ #include <linux/seq_file.h>
+-#include <linux/ide.h>
+ #include <linux/root_dev.h>
+ #include <linux/serial.h>
+ #include <linux/tty.h>
+diff --git a/arch/ppc/syslib/m8260_setup.c b/arch/ppc/syslib/m8260_setup.c
+index 46588fa..b405837 100644
+--- a/arch/ppc/syslib/m8260_setup.c
++++ b/arch/ppc/syslib/m8260_setup.c
+@@ -175,12 +175,6 @@ m8260_init_IRQ(void)
+ * in case the boot rom changed something on us.
+ */
+ cpm2_immr->im_intctl.ic_siprr = 0x05309770;
+-
+-#if defined(CONFIG_PCI) && (defined(CONFIG_ADS8272) || defined(CONFIG_PQ2FADS))
+- /* Initialize stuff for the 82xx CPLD IC and install demux */
+- pq2pci_init_irq();
+-#endif
+-
+ }
+
+ /*
+diff --git a/arch/ppc/syslib/m82xx_pci.c b/arch/ppc/syslib/m82xx_pci.c
+index fe860d5..657a1c2 100644
+--- a/arch/ppc/syslib/m82xx_pci.c
++++ b/arch/ppc/syslib/m82xx_pci.c
+@@ -150,14 +150,6 @@ pq2pci_init_irq(void)
+ {
+ int irq;
+ volatile cpm2_map_t *immap = cpm2_immr;
+-#if defined CONFIG_ADS8272
+- /* configure chip select for PCI interrupt controller */
+- immap->im_memctl.memc_br3 = PCI_INT_STAT_REG | 0x00001801;
+- immap->im_memctl.memc_or3 = 0xffff8010;
+-#elif defined CONFIG_PQ2FADS
+- immap->im_memctl.memc_br8 = PCI_INT_STAT_REG | 0x00001801;
+- immap->im_memctl.memc_or8 = 0xffff8010;
+-#endif
+ for (irq = NR_CPM_INTS; irq < NR_CPM_INTS + 4; irq++)
+ irq_desc[irq].chip = &pq2pci_ic;
+
+@@ -222,26 +214,6 @@ pq2ads_setup_pci(struct pci_controller *hose)
+ immap->im_memctl.memc_pcibr1 = M82xx_PCI_SEC_WND_BASE | PCIBR_ENABLE;
+ #endif
+
+-#if defined CONFIG_ADS8272
+- immap->im_siu_conf.siu_82xx.sc_siumcr =
+- (immap->im_siu_conf.siu_82xx.sc_siumcr &
+- ~(SIUMCR_BBD | SIUMCR_ESE | SIUMCR_PBSE |
+- SIUMCR_CDIS | SIUMCR_DPPC11 | SIUMCR_L2CPC11 |
+- SIUMCR_LBPC11 | SIUMCR_APPC11 |
+- SIUMCR_CS10PC11 | SIUMCR_BCTLC11 | SIUMCR_MMR11)) |
+- SIUMCR_DPPC11 | SIUMCR_L2CPC01 | SIUMCR_LBPC00 |
+- SIUMCR_APPC10 | SIUMCR_CS10PC00 |
+- SIUMCR_BCTLC00 | SIUMCR_MMR11 ;
+-
+-#elif defined CONFIG_PQ2FADS
+- /*
+- * Setting required to enable IRQ1-IRQ7 (SIUMCR [DPPC]),
+- * and local bus for PCI (SIUMCR [LBPC]).
+- */
+- immap->im_siu_conf.siu_82xx.sc_siumcr = (immap->im_siu_conf.siu_82xx.sc_siumcr &
+- ~(SIUMCR_L2CPC11 | SIUMCR_LBPC11 | SIUMCR_CS10PC11 | SIUMCR_APPC11) |
+- SIUMCR_BBD | SIUMCR_LBPC01 | SIUMCR_DPPC11 | SIUMCR_APPC10);
+-#endif
+ /* Enable PCI */
+ immap->im_pci.pci_gcr = cpu_to_le32(PCIGCR_PCI_BUS_EN);
+
+@@ -284,12 +256,6 @@ pq2ads_setup_pci(struct pci_controller *hose)
+ immap->im_pci.pci_pibar0 = cpu_to_le32(M82xx_PCI_SLAVE_MEM_BUS >> PITA_ADDR_SHIFT);
+ immap->im_pci.pci_pitar0 = cpu_to_le32(M82xx_PCI_SLAVE_MEM_LOCAL>> PITA_ADDR_SHIFT);
+
+-#if defined CONFIG_ADS8272
+- /* PCI int highest prio */
+- immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x01236745;
+-#elif defined CONFIG_PQ2FADS
+- immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x03124567;
+-#endif
+ /* park bus on PCI */
+ immap->im_siu_conf.siu_82xx.sc_ppc_acr = PPC_ACR_BUS_PARK_PCI;
+
+@@ -320,10 +286,6 @@ void __init pq2_find_bridges(void)
+ hose->bus_offset = 0;
+ hose->last_busno = 0xff;
+
+-#ifdef CONFIG_ADS8272
+- hose->set_cfg_type = 1;
+-#endif
+-
+ setup_m8260_indirect_pci(hose,
+ (unsigned long)&cpm2_immr->im_pci.pci_cfg_addr,
+ (unsigned long)&cpm2_immr->im_pci.pci_cfg_data);
+diff --git a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c
+index 9caf850..18da720 100644
+--- a/arch/ppc/syslib/m8xx_setup.c
++++ b/arch/ppc/syslib/m8xx_setup.c
+@@ -87,8 +87,6 @@ void m8xx_calibrate_decr(void);
+
+ unsigned char __res[sizeof(bd_t)];
+
+-extern void m8xx_ide_init(void);
+-
+ extern unsigned long find_available_memory(void);
+ extern void m8xx_cpm_reset(void);
+ extern void m8xx_wdt_handler_install(bd_t *bp);
+@@ -143,16 +141,6 @@ m8xx_setup_arch(void)
+ #endif
+ #endif
+
+-#if defined (CONFIG_MPC86XADS) || defined (CONFIG_MPC885ADS)
+-#if defined(CONFIG_MTD_PHYSMAP)
+- physmap_configure(binfo->bi_flashstart, binfo->bi_flashsize,
+- MPC8xxADS_BANK_WIDTH, NULL);
+-#ifdef CONFIG_MTD_PARTITIONS
+- physmap_set_partitions(mpc8xxads_partitions, mpc8xxads_part_num);
+-#endif /* CONFIG_MTD_PARTITIONS */
+-#endif /* CONFIG_MTD_PHYSMAP */
+-#endif
+-
+ board_init();
+ }
+
+@@ -474,8 +462,4 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+
+ ppc_md.find_end_of_memory = m8xx_find_end_of_memory;
+ ppc_md.setup_io_mappings = m8xx_map_io;
+-
+-#if defined(CONFIG_BLK_DEV_MPC8xx_IDE)
+- m8xx_ide_init();
+-#endif
+ }
+diff --git a/arch/ppc/syslib/mpc52xx_setup.c b/arch/ppc/syslib/mpc52xx_setup.c
+index 9f504fc..ab0cf4c 100644
+--- a/arch/ppc/syslib/mpc52xx_setup.c
++++ b/arch/ppc/syslib/mpc52xx_setup.c
+@@ -279,7 +279,7 @@ int mpc52xx_match_psc_function(int psc_idx, const char *func)
+
+ int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv)
+ {
+- static spinlock_t lock = SPIN_LOCK_UNLOCKED;
++ static DEFINE_SPINLOCK(lock);
+ struct mpc52xx_cdm __iomem *cdm;
+ unsigned long flags;
+ u16 mclken_div;
+diff --git a/arch/ppc/syslib/ocp.c b/arch/ppc/syslib/ocp.c
+index ac80370..a6fb7dc 100644
+--- a/arch/ppc/syslib/ocp.c
++++ b/arch/ppc/syslib/ocp.c
+@@ -49,7 +49,6 @@
+ #include <asm/io.h>
+ #include <asm/ocp.h>
+ #include <asm/errno.h>
+-#include <asm/semaphore.h>
+
+ //#define DBG(x) printk x
+ #define DBG(x)
+diff --git a/arch/ppc/syslib/ppc4xx_setup.c b/arch/ppc/syslib/ppc4xx_setup.c
+index debe14c..353d746 100644
+--- a/arch/ppc/syslib/ppc4xx_setup.c
++++ b/arch/ppc/syslib/ppc4xx_setup.c
+@@ -24,7 +24,6 @@
+ #include <linux/pci.h>
+ #include <linux/rtc.h>
+ #include <linux/console.h>
+-#include <linux/ide.h>
+ #include <linux/serial_reg.h>
+ #include <linux/seq_file.h>
+
+@@ -189,24 +188,6 @@ ppc4xx_calibrate_decr(void)
+ mtspr(SPRN_PIT, tb_ticks_per_jiffy);
+ }
+
+-/*
+- * IDE stuff.
+- * should be generic for every IDE PCI chipset
+- */
+-#if defined(CONFIG_PCI) && defined(CONFIG_IDE)
+-static void
+-ppc4xx_ide_init_hwif_ports(hw_regs_t * hw, unsigned long data_port,
+- unsigned long ctrl_port, int *irq)
+-{
+- int i;
+-
+- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; ++i)
+- hw->io_ports[i] = data_port + i - IDE_DATA_OFFSET;
+-
+- hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+-}
+-#endif /* defined(CONFIG_PCI) && defined(CONFIG_IDE) */
+-
+ TODC_ALLOC();
+
+ /*
+@@ -271,10 +252,6 @@ ppc4xx_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ #ifdef CONFIG_SERIAL_TEXT_DEBUG
+ ppc_md.progress = gen550_progress;
+ #endif
+-
+-#if defined(CONFIG_PCI) && defined(CONFIG_IDE)
+- ppc_ide_md.ide_init_hwif = ppc4xx_ide_init_hwif_ports;
+-#endif /* defined(CONFIG_PCI) && defined(CONFIG_IDE) */
+ }
+
+ /* Called from machine_check_exception */
+diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
+index 1831833..f6a68e1 100644
+--- a/arch/s390/Kconfig
++++ b/arch/s390/Kconfig
+@@ -3,6 +3,10 @@
+ # see Documentation/kbuild/kconfig-language.txt.
+ #
+
++config SCHED_MC
++ def_bool y
++ depends on SMP
++
+ config MMU
+ def_bool y
+
+@@ -39,6 +43,9 @@ config GENERIC_HWEIGHT
+ config GENERIC_TIME
+ def_bool y
+
++config GENERIC_CLOCKEVENTS
++ def_bool y
++
+ config GENERIC_BUG
+ bool
+ depends on BUG
+@@ -69,6 +76,8 @@ menu "Base setup"
+
+ comment "Processor type and features"
+
++source "kernel/time/Kconfig"
++
+ config 64BIT
+ bool "64 bit kernel"
+ help
+@@ -301,10 +310,7 @@ config QDIO
+ tristate "QDIO support"
+ ---help---
+ This driver provides the Queued Direct I/O base support for
+- IBM mainframes.
+-
+- For details please refer to the documentation provided by IBM at
+- <http://www10.software.ibm.com/developerworks/opensource/linux390>
++ IBM System z.
+
+ To compile this driver as a module, choose M here: the
+ module will be called qdio.
+@@ -486,25 +492,6 @@ config APPLDATA_NET_SUM
+
+ source kernel/Kconfig.hz
+
+-config NO_IDLE_HZ
+- bool "No HZ timer ticks in idle"
+- help
+- Switches the regular HZ timer off when the system is going idle.
+- This helps z/VM to detect that the Linux system is idle. VM can
+- then "swap-out" this guest which reduces memory usage. It also
+- reduces the overhead of idle systems.
+-
+- The HZ timer can be switched on/off via /proc/sys/kernel/hz_timer.
+- hz_timer=0 means HZ timer is disabled. hz_timer=1 means HZ
+- timer is active.
+-
+-config NO_IDLE_HZ_INIT
+- bool "HZ timer in idle off by default"
+- depends on NO_IDLE_HZ
+- help
+- The HZ timer is switched off in idle by default. That means the
+- HZ timer is already disabled at boot time.
+-
+ config S390_HYPFS_FS
+ bool "s390 hypervisor file system support"
+ select SYS_HYPERVISOR
+diff --git a/arch/s390/crypto/Makefile b/arch/s390/crypto/Makefile
+index 14e552c..6a1157f 100644
+--- a/arch/s390/crypto/Makefile
++++ b/arch/s390/crypto/Makefile
+@@ -2,8 +2,9 @@
+ # Cryptographic API
+ #
+
+-obj-$(CONFIG_CRYPTO_SHA1_S390) += sha1_s390.o
+-obj-$(CONFIG_CRYPTO_SHA256_S390) += sha256_s390.o
++obj-$(CONFIG_CRYPTO_SHA1_S390) += sha1_s390.o sha_common.o
++obj-$(CONFIG_CRYPTO_SHA256_S390) += sha256_s390.o sha_common.o
++obj-$(CONFIG_CRYPTO_SHA512_S390) += sha512_s390.o sha_common.o
+ obj-$(CONFIG_CRYPTO_DES_S390) += des_s390.o des_check_key.o
+ obj-$(CONFIG_CRYPTO_AES_S390) += aes_s390.o
+ obj-$(CONFIG_S390_PRNG) += prng.o
+diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c
+index a3f67f8..e33f32b 100644
+--- a/arch/s390/crypto/aes_s390.c
++++ b/arch/s390/crypto/aes_s390.c
+@@ -499,7 +499,7 @@ static struct crypto_alg cbc_aes_alg = {
+ }
+ };
+
+-static int __init aes_init(void)
++static int __init aes_s390_init(void)
+ {
+ int ret;
+
+@@ -542,15 +542,15 @@ aes_err:
+ goto out;
+ }
+
+-static void __exit aes_fini(void)
++static void __exit aes_s390_fini(void)
+ {
+ crypto_unregister_alg(&cbc_aes_alg);
+ crypto_unregister_alg(&ecb_aes_alg);
+ crypto_unregister_alg(&aes_alg);
+ }
+
+-module_init(aes_init);
+-module_exit(aes_fini);
++module_init(aes_s390_init);
++module_exit(aes_s390_fini);
+
+ MODULE_ALIAS("aes");
+
+diff --git a/arch/s390/crypto/crypt_s390.h b/arch/s390/crypto/crypt_s390.h
+index 95f5160..9992f95 100644
+--- a/arch/s390/crypto/crypt_s390.h
++++ b/arch/s390/crypto/crypt_s390.h
+@@ -82,6 +82,7 @@ enum crypt_s390_kimd_func {
+ KIMD_QUERY = CRYPT_S390_KIMD | 0,
+ KIMD_SHA_1 = CRYPT_S390_KIMD | 1,
+ KIMD_SHA_256 = CRYPT_S390_KIMD | 2,
++ KIMD_SHA_512 = CRYPT_S390_KIMD | 3,
+ };
+
+ /*
+@@ -92,6 +93,7 @@ enum crypt_s390_klmd_func {
+ KLMD_QUERY = CRYPT_S390_KLMD | 0,
+ KLMD_SHA_1 = CRYPT_S390_KLMD | 1,
+ KLMD_SHA_256 = CRYPT_S390_KLMD | 2,
++ KLMD_SHA_512 = CRYPT_S390_KLMD | 3,
+ };
+
+ /*
+diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c
+index ea22707..4aba83b 100644
+--- a/arch/s390/crypto/des_s390.c
++++ b/arch/s390/crypto/des_s390.c
+@@ -550,7 +550,7 @@ static struct crypto_alg cbc_des3_192_alg = {
+ }
+ };
+
+-static int init(void)
++static int des_s390_init(void)
+ {
+ int ret = 0;
+
+@@ -612,7 +612,7 @@ des_err:
+ goto out;
+ }
+
+-static void __exit fini(void)
++static void __exit des_s390_fini(void)
+ {
+ crypto_unregister_alg(&cbc_des3_192_alg);
+ crypto_unregister_alg(&ecb_des3_192_alg);
+@@ -625,8 +625,8 @@ static void __exit fini(void)
+ crypto_unregister_alg(&des_alg);
+ }
+
+-module_init(init);
+-module_exit(fini);
++module_init(des_s390_init);
++module_exit(des_s390_fini);
+
+ MODULE_ALIAS("des");
+ MODULE_ALIAS("des3_ede");
+diff --git a/arch/s390/crypto/sha.h b/arch/s390/crypto/sha.h
+new file mode 100644
+index 0000000..1ceafa5
+--- /dev/null
++++ b/arch/s390/crypto/sha.h
+@@ -0,0 +1,35 @@
++/*
++ * Cryptographic API.
++ *
++ * s390 generic implementation of the SHA Secure Hash Algorithms.
++ *
++ * Copyright IBM Corp. 2007
++ * Author(s): Jan Glauber (jang at de.ibm.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.
++ *
++ */
++#ifndef _CRYPTO_ARCH_S390_SHA_H
++#define _CRYPTO_ARCH_S390_SHA_H
++
++#include <linux/crypto.h>
++#include <crypto/sha.h>
++
++/* must be big enough for the largest SHA variant */
++#define SHA_MAX_STATE_SIZE 16
++#define SHA_MAX_BLOCK_SIZE SHA512_BLOCK_SIZE
++
++struct s390_sha_ctx {
++ u64 count; /* message length in bytes */
++ u32 state[SHA_MAX_STATE_SIZE];
++ u8 buf[2 * SHA_MAX_BLOCK_SIZE];
++ int func; /* KIMD function to use */
++};
++
++void s390_sha_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len);
++void s390_sha_final(struct crypto_tfm *tfm, u8 *out);
++
++#endif
+diff --git a/arch/s390/crypto/sha1_s390.c b/arch/s390/crypto/sha1_s390.c
+index 5a834f6..b3cb5a8 100644
+--- a/arch/s390/crypto/sha1_s390.c
++++ b/arch/s390/crypto/sha1_s390.c
+@@ -29,16 +29,11 @@
+ #include <crypto/sha.h>
+
+ #include "crypt_s390.h"
+-
+-struct s390_sha1_ctx {
+- u64 count; /* message length */
+- u32 state[5];
+- u8 buf[2 * SHA1_BLOCK_SIZE];
+-};
++#include "sha.h"
+
+ static void sha1_init(struct crypto_tfm *tfm)
+ {
+- struct s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
++ struct s390_sha_ctx *sctx = crypto_tfm_ctx(tfm);
+
+ sctx->state[0] = SHA1_H0;
+ sctx->state[1] = SHA1_H1;
+@@ -46,79 +41,7 @@ static void sha1_init(struct crypto_tfm *tfm)
+ sctx->state[3] = SHA1_H3;
+ sctx->state[4] = SHA1_H4;
+ sctx->count = 0;
+-}
+-
+-static void sha1_update(struct crypto_tfm *tfm, const u8 *data,
+- unsigned int len)
+-{
+- struct s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
+- unsigned int index;
+- int ret;
+-
+- /* how much is already in the buffer? */
+- index = sctx->count & 0x3f;
+-
+- sctx->count += len;
+-
+- if (index + len < SHA1_BLOCK_SIZE)
+- goto store;
+-
+- /* process one stored block */
+- if (index) {
+- memcpy(sctx->buf + index, data, SHA1_BLOCK_SIZE - index);
+- ret = crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buf,
+- SHA1_BLOCK_SIZE);
+- BUG_ON(ret != SHA1_BLOCK_SIZE);
+- data += SHA1_BLOCK_SIZE - index;
+- len -= SHA1_BLOCK_SIZE - index;
+- }
+-
+- /* process as many blocks as possible */
+- if (len >= SHA1_BLOCK_SIZE) {
+- ret = crypt_s390_kimd(KIMD_SHA_1, sctx->state, data,
+- len & ~(SHA1_BLOCK_SIZE - 1));
+- BUG_ON(ret != (len & ~(SHA1_BLOCK_SIZE - 1)));
+- data += ret;
+- len -= ret;
+- }
+-
+-store:
+- /* anything left? */
+- if (len)
+- memcpy(sctx->buf + index , data, len);
+-}
+-
+-/* Add padding and return the message digest. */
+-static void sha1_final(struct crypto_tfm *tfm, u8 *out)
+-{
+- struct s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
+- u64 bits;
+- unsigned int index, end;
+- int ret;
+-
+- /* must perform manual padding */
+- index = sctx->count & 0x3f;
+- end = (index < 56) ? SHA1_BLOCK_SIZE : (2 * SHA1_BLOCK_SIZE);
+-
+- /* start pad with 1 */
+- sctx->buf[index] = 0x80;
+-
+- /* pad with zeros */
+- index++;
+- memset(sctx->buf + index, 0x00, end - index - 8);
+-
+- /* append message length */
+- bits = sctx->count * 8;
+- memcpy(sctx->buf + end - 8, &bits, sizeof(bits));
+-
+- ret = crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buf, end);
+- BUG_ON(ret != end);
+-
+- /* copy digest to out */
+- memcpy(out, sctx->state, SHA1_DIGEST_SIZE);
+-
+- /* wipe context */
+- memset(sctx, 0, sizeof *sctx);
++ sctx->func = KIMD_SHA_1;
+ }
+
+ static struct crypto_alg alg = {
+@@ -127,33 +50,31 @@ static struct crypto_alg alg = {
+ .cra_priority = CRYPT_S390_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
+ .cra_blocksize = SHA1_BLOCK_SIZE,
+- .cra_ctxsize = sizeof(struct s390_sha1_ctx),
++ .cra_ctxsize = sizeof(struct s390_sha_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(alg.cra_list),
+ .cra_u = { .digest = {
+ .dia_digestsize = SHA1_DIGEST_SIZE,
+ .dia_init = sha1_init,
+- .dia_update = sha1_update,
+- .dia_final = sha1_final } }
++ .dia_update = s390_sha_update,
++ .dia_final = s390_sha_final } }
+ };
+
+-static int __init init(void)
++static int __init sha1_s390_init(void)
+ {
+ if (!crypt_s390_func_available(KIMD_SHA_1))
+ return -EOPNOTSUPP;
+-
+ return crypto_register_alg(&alg);
+ }
+
+-static void __exit fini(void)
++static void __exit sha1_s390_fini(void)
+ {
+ crypto_unregister_alg(&alg);
+ }
+
+-module_init(init);
+-module_exit(fini);
++module_init(sha1_s390_init);
++module_exit(sha1_s390_fini);
+
+ MODULE_ALIAS("sha1");
+-
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm");
+diff --git a/arch/s390/crypto/sha256_s390.c b/arch/s390/crypto/sha256_s390.c
+index ccf8633..19c03fb 100644
+--- a/arch/s390/crypto/sha256_s390.c
++++ b/arch/s390/crypto/sha256_s390.c
+@@ -22,16 +22,11 @@
+ #include <crypto/sha.h>
+
+ #include "crypt_s390.h"
+-
+-struct s390_sha256_ctx {
+- u64 count; /* message length */
+- u32 state[8];
+- u8 buf[2 * SHA256_BLOCK_SIZE];
+-};
++#include "sha.h"
+
+ static void sha256_init(struct crypto_tfm *tfm)
+ {
+- struct s390_sha256_ctx *sctx = crypto_tfm_ctx(tfm);
++ struct s390_sha_ctx *sctx = crypto_tfm_ctx(tfm);
+
+ sctx->state[0] = SHA256_H0;
+ sctx->state[1] = SHA256_H1;
+@@ -42,79 +37,7 @@ static void sha256_init(struct crypto_tfm *tfm)
+ sctx->state[6] = SHA256_H6;
+ sctx->state[7] = SHA256_H7;
+ sctx->count = 0;
+-}
+-
+-static void sha256_update(struct crypto_tfm *tfm, const u8 *data,
+- unsigned int len)
+-{
+- struct s390_sha256_ctx *sctx = crypto_tfm_ctx(tfm);
+- unsigned int index;
+- int ret;
+-
+- /* how much is already in the buffer? */
+- index = sctx->count & 0x3f;
+-
+- sctx->count += len;
+-
+- if ((index + len) < SHA256_BLOCK_SIZE)
+- goto store;
+-
+- /* process one stored block */
+- if (index) {
+- memcpy(sctx->buf + index, data, SHA256_BLOCK_SIZE - index);
+- ret = crypt_s390_kimd(KIMD_SHA_256, sctx->state, sctx->buf,
+- SHA256_BLOCK_SIZE);
+- BUG_ON(ret != SHA256_BLOCK_SIZE);
+- data += SHA256_BLOCK_SIZE - index;
+- len -= SHA256_BLOCK_SIZE - index;
+- }
+-
+- /* process as many blocks as possible */
+- if (len >= SHA256_BLOCK_SIZE) {
+- ret = crypt_s390_kimd(KIMD_SHA_256, sctx->state, data,
+- len & ~(SHA256_BLOCK_SIZE - 1));
+- BUG_ON(ret != (len & ~(SHA256_BLOCK_SIZE - 1)));
+- data += ret;
+- len -= ret;
+- }
+-
+-store:
+- /* anything left? */
+- if (len)
+- memcpy(sctx->buf + index , data, len);
+-}
+-
+-/* Add padding and return the message digest */
+-static void sha256_final(struct crypto_tfm *tfm, u8 *out)
+-{
+- struct s390_sha256_ctx *sctx = crypto_tfm_ctx(tfm);
+- u64 bits;
+- unsigned int index, end;
+- int ret;
+-
+- /* must perform manual padding */
+- index = sctx->count & 0x3f;
+- end = (index < 56) ? SHA256_BLOCK_SIZE : (2 * SHA256_BLOCK_SIZE);
+-
+- /* start pad with 1 */
+- sctx->buf[index] = 0x80;
+-
+- /* pad with zeros */
+- index++;
+- memset(sctx->buf + index, 0x00, end - index - 8);
+-
+- /* append message length */
+- bits = sctx->count * 8;
+- memcpy(sctx->buf + end - 8, &bits, sizeof(bits));
+-
+- ret = crypt_s390_kimd(KIMD_SHA_256, sctx->state, sctx->buf, end);
+- BUG_ON(ret != end);
+-
+- /* copy digest to out */
+- memcpy(out, sctx->state, SHA256_DIGEST_SIZE);
+-
+- /* wipe context */
+- memset(sctx, 0, sizeof *sctx);
++ sctx->func = KIMD_SHA_256;
+ }
+
+ static struct crypto_alg alg = {
+@@ -123,17 +46,17 @@ static struct crypto_alg alg = {
+ .cra_priority = CRYPT_S390_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
+ .cra_blocksize = SHA256_BLOCK_SIZE,
+- .cra_ctxsize = sizeof(struct s390_sha256_ctx),
++ .cra_ctxsize = sizeof(struct s390_sha_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(alg.cra_list),
+ .cra_u = { .digest = {
+ .dia_digestsize = SHA256_DIGEST_SIZE,
+ .dia_init = sha256_init,
+- .dia_update = sha256_update,
+- .dia_final = sha256_final } }
++ .dia_update = s390_sha_update,
++ .dia_final = s390_sha_final } }
+ };
+
+-static int init(void)
++static int sha256_s390_init(void)
+ {
+ if (!crypt_s390_func_available(KIMD_SHA_256))
+ return -EOPNOTSUPP;
+@@ -141,15 +64,14 @@ static int init(void)
+ return crypto_register_alg(&alg);
+ }
+
+-static void __exit fini(void)
++static void __exit sha256_s390_fini(void)
+ {
+ crypto_unregister_alg(&alg);
+ }
+
+-module_init(init);
+-module_exit(fini);
++module_init(sha256_s390_init);
++module_exit(sha256_s390_fini);
+
+ MODULE_ALIAS("sha256");
+-
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm");
+diff --git a/arch/s390/crypto/sha512_s390.c b/arch/s390/crypto/sha512_s390.c
+new file mode 100644
+index 0000000..23c7861
+--- /dev/null
++++ b/arch/s390/crypto/sha512_s390.c
+@@ -0,0 +1,114 @@
++/*
++ * Cryptographic API.
++ *
++ * s390 implementation of the SHA512 and SHA38 Secure Hash Algorithm.
++ *
++ * Copyright IBM Corp. 2007
++ * Author(s): Jan Glauber (jang at de.ibm.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/init.h>
++#include <linux/module.h>
++#include <linux/crypto.h>
++
++#include "sha.h"
++#include "crypt_s390.h"
++
++static void sha512_init(struct crypto_tfm *tfm)
++{
++ struct s390_sha_ctx *ctx = crypto_tfm_ctx(tfm);
++
++ *(__u64 *)&ctx->state[0] = 0x6a09e667f3bcc908ULL;
++ *(__u64 *)&ctx->state[2] = 0xbb67ae8584caa73bULL;
++ *(__u64 *)&ctx->state[4] = 0x3c6ef372fe94f82bULL;
++ *(__u64 *)&ctx->state[6] = 0xa54ff53a5f1d36f1ULL;
++ *(__u64 *)&ctx->state[8] = 0x510e527fade682d1ULL;
++ *(__u64 *)&ctx->state[10] = 0x9b05688c2b3e6c1fULL;
++ *(__u64 *)&ctx->state[12] = 0x1f83d9abfb41bd6bULL;
++ *(__u64 *)&ctx->state[14] = 0x5be0cd19137e2179ULL;
++ ctx->count = 0;
++ ctx->func = KIMD_SHA_512;
++}
++
++static struct crypto_alg sha512_alg = {
++ .cra_name = "sha512",
++ .cra_driver_name = "sha512-s390",
++ .cra_priority = CRYPT_S390_PRIORITY,
++ .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
++ .cra_blocksize = SHA512_BLOCK_SIZE,
++ .cra_ctxsize = sizeof(struct s390_sha_ctx),
++ .cra_module = THIS_MODULE,
++ .cra_list = LIST_HEAD_INIT(sha512_alg.cra_list),
++ .cra_u = { .digest = {
++ .dia_digestsize = SHA512_DIGEST_SIZE,
++ .dia_init = sha512_init,
++ .dia_update = s390_sha_update,
++ .dia_final = s390_sha_final } }
++};
++
++MODULE_ALIAS("sha512");
++
++static void sha384_init(struct crypto_tfm *tfm)
++{
++ struct s390_sha_ctx *ctx = crypto_tfm_ctx(tfm);
++
++ *(__u64 *)&ctx->state[0] = 0xcbbb9d5dc1059ed8ULL;
++ *(__u64 *)&ctx->state[2] = 0x629a292a367cd507ULL;
++ *(__u64 *)&ctx->state[4] = 0x9159015a3070dd17ULL;
++ *(__u64 *)&ctx->state[6] = 0x152fecd8f70e5939ULL;
++ *(__u64 *)&ctx->state[8] = 0x67332667ffc00b31ULL;
++ *(__u64 *)&ctx->state[10] = 0x8eb44a8768581511ULL;
++ *(__u64 *)&ctx->state[12] = 0xdb0c2e0d64f98fa7ULL;
++ *(__u64 *)&ctx->state[14] = 0x47b5481dbefa4fa4ULL;
++ ctx->count = 0;
++ ctx->func = KIMD_SHA_512;
++}
++
++static struct crypto_alg sha384_alg = {
++ .cra_name = "sha384",
++ .cra_driver_name = "sha384-s390",
++ .cra_priority = CRYPT_S390_PRIORITY,
++ .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
++ .cra_blocksize = SHA384_BLOCK_SIZE,
++ .cra_ctxsize = sizeof(struct s390_sha_ctx),
++ .cra_module = THIS_MODULE,
++ .cra_list = LIST_HEAD_INIT(sha384_alg.cra_list),
++ .cra_u = { .digest = {
++ .dia_digestsize = SHA384_DIGEST_SIZE,
++ .dia_init = sha384_init,
++ .dia_update = s390_sha_update,
++ .dia_final = s390_sha_final } }
++};
++
++MODULE_ALIAS("sha384");
++
++static int __init init(void)
++{
++ int ret;
++
++ if (!crypt_s390_func_available(KIMD_SHA_512))
++ return -EOPNOTSUPP;
++ if ((ret = crypto_register_alg(&sha512_alg)) < 0)
++ goto out;
++ if ((ret = crypto_register_alg(&sha384_alg)) < 0)
++ crypto_unregister_alg(&sha512_alg);
++out:
++ return ret;
++}
++
++static void __exit fini(void)
++{
++ crypto_unregister_alg(&sha512_alg);
++ crypto_unregister_alg(&sha384_alg);
++}
++
++module_init(init);
++module_exit(fini);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("SHA512 and SHA-384 Secure Hash Algorithm");
+diff --git a/arch/s390/crypto/sha_common.c b/arch/s390/crypto/sha_common.c
+new file mode 100644
+index 0000000..9d6eb8c
+--- /dev/null
++++ b/arch/s390/crypto/sha_common.c
+@@ -0,0 +1,97 @@
++/*
++ * Cryptographic API.
++ *
++ * s390 generic implementation of the SHA Secure Hash Algorithms.
++ *
++ * Copyright IBM Corp. 2007
++ * Author(s): Jan Glauber (jang at de.ibm.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/crypto.h>
++#include "sha.h"
++#include "crypt_s390.h"
++
++void s390_sha_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len)
++{
++ struct s390_sha_ctx *ctx = crypto_tfm_ctx(tfm);
++ unsigned int bsize = crypto_tfm_alg_blocksize(tfm);
++ unsigned int index;
++ int ret;
++
++ /* how much is already in the buffer? */
++ index = ctx->count & (bsize - 1);
++ ctx->count += len;
++
++ if ((index + len) < bsize)
++ goto store;
++
++ /* process one stored block */
++ if (index) {
++ memcpy(ctx->buf + index, data, bsize - index);
++ ret = crypt_s390_kimd(ctx->func, ctx->state, ctx->buf, bsize);
++ BUG_ON(ret != bsize);
++ data += bsize - index;
++ len -= bsize - index;
++ }
++
++ /* process as many blocks as possible */
++ if (len >= bsize) {
++ ret = crypt_s390_kimd(ctx->func, ctx->state, data,
++ len & ~(bsize - 1));
++ BUG_ON(ret != (len & ~(bsize - 1)));
++ data += ret;
++ len -= ret;
++ }
++store:
++ if (len)
++ memcpy(ctx->buf + index , data, len);
++}
++EXPORT_SYMBOL_GPL(s390_sha_update);
++
++void s390_sha_final(struct crypto_tfm *tfm, u8 *out)
++{
++ struct s390_sha_ctx *ctx = crypto_tfm_ctx(tfm);
++ unsigned int bsize = crypto_tfm_alg_blocksize(tfm);
++ u64 bits;
++ unsigned int index, end, plen;
++ int ret;
++
++ /* SHA-512 uses 128 bit padding length */
++ plen = (bsize > SHA256_BLOCK_SIZE) ? 16 : 8;
++
++ /* must perform manual padding */
++ index = ctx->count & (bsize - 1);
++ end = (index < bsize - plen) ? bsize : (2 * bsize);
++
++ /* start pad with 1 */
++ ctx->buf[index] = 0x80;
++ index++;
++
++ /* pad with zeros */
++ memset(ctx->buf + index, 0x00, end - index - 8);
++
++ /*
++ * Append message length. Well, SHA-512 wants a 128 bit lenght value,
++ * nevertheless we use u64, should be enough for now...
++ */
++ bits = ctx->count * 8;
++ memcpy(ctx->buf + end - 8, &bits, sizeof(bits));
++
++ ret = crypt_s390_kimd(ctx->func, ctx->state, ctx->buf, end);
++ BUG_ON(ret != end);
++
++ /* copy digest to out */
++ memcpy(out, ctx->state, crypto_hash_digestsize(crypto_hash_cast(tfm)));
++ /* wipe context */
++ memset(ctx, 0, sizeof *ctx);
++}
++EXPORT_SYMBOL_GPL(s390_sha_final);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("s390 SHA cipher common functions");
+diff --git a/arch/s390/defconfig b/arch/s390/defconfig
+index 62f6b5a..a72f208 100644
+--- a/arch/s390/defconfig
++++ b/arch/s390/defconfig
+@@ -3,6 +3,7 @@
+ # Linux kernel version: 2.6.25-rc4
+ # Wed Mar 5 11:22:59 2008
+ #
++CONFIG_SCHED_MC=y
+ CONFIG_MMU=y
+ CONFIG_ZONE_DMA=y
+ CONFIG_LOCKDEP_SUPPORT=y
+@@ -537,11 +538,9 @@ CONFIG_CTC=m
+ # CONFIG_SMSGIUCV is not set
+ # CONFIG_CLAW is not set
+ CONFIG_QETH=y
+-
+-#
+-# Gigabit Ethernet default settings
+-#
+-# CONFIG_QETH_IPV6 is not set
++CONFIG_QETH_L2=y
++CONFIG_QETH_L3=y
++CONFIG_QETH_IPV6=y
+ CONFIG_CCWGROUP=y
+ # CONFIG_PPP is not set
+ # CONFIG_SLIP is not set
+diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
+index 4d3e383..77051cd 100644
+--- a/arch/s390/kernel/Makefile
++++ b/arch/s390/kernel/Makefile
+@@ -11,7 +11,7 @@ CFLAGS_smp.o := -Wno-nonnull
+
+ obj-y := bitmap.o traps.o time.o process.o base.o early.o \
+ setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
+- semaphore.o s390_ext.o debug.o irq.o ipl.o dis.o diag.o
++ s390_ext.o debug.o irq.o ipl.o dis.o diag.o
+
+ obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o)
+ obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
+@@ -19,7 +19,7 @@ obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
+ extra-y += head.o init_task.o vmlinux.lds
+
+ obj-$(CONFIG_MODULES) += s390_ksyms.o module.o
+-obj-$(CONFIG_SMP) += smp.o
++obj-$(CONFIG_SMP) += smp.o topology.o
+
+ obj-$(CONFIG_AUDIT) += audit.o
+ compat-obj-$(CONFIG_AUDIT) += compat_audit.o
+diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
+index 50b85d0..d7f2222 100644
+--- a/arch/s390/kernel/compat_linux.c
++++ b/arch/s390/kernel/compat_linux.c
+@@ -62,7 +62,6 @@
+
+ #include <asm/types.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+
+ #include <net/scm.h>
+ #include <net/sock.h>
+diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h
+index e89f8c0..20723a0 100644
+--- a/arch/s390/kernel/compat_linux.h
++++ b/arch/s390/kernel/compat_linux.h
+@@ -162,4 +162,77 @@ struct ucontext32 {
+ compat_sigset_t uc_sigmask; /* mask last for extensibility */
+ };
+
++struct __sysctl_args32;
++struct stat64_emu31;
++struct mmap_arg_struct_emu31;
++struct fadvise64_64_args;
++struct old_sigaction32;
++struct old_sigaction32;
++
++long sys32_chown16(const char __user * filename, u16 user, u16 group);
++long sys32_lchown16(const char __user * filename, u16 user, u16 group);
++long sys32_fchown16(unsigned int fd, u16 user, u16 group);
++long sys32_setregid16(u16 rgid, u16 egid);
++long sys32_setgid16(u16 gid);
++long sys32_setreuid16(u16 ruid, u16 euid);
++long sys32_setuid16(u16 uid);
++long sys32_setresuid16(u16 ruid, u16 euid, u16 suid);
++long sys32_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user *suid);
++long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid);
++long sys32_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user *sgid);
++long sys32_setfsuid16(u16 uid);
++long sys32_setfsgid16(u16 gid);
++long sys32_getgroups16(int gidsetsize, u16 __user *grouplist);
++long sys32_setgroups16(int gidsetsize, u16 __user *grouplist);
++long sys32_getuid16(void);
++long sys32_geteuid16(void);
++long sys32_getgid16(void);
++long sys32_getegid16(void);
++long sys32_ipc(u32 call, int first, int second, int third, u32 ptr);
++long sys32_truncate64(const char __user * path, unsigned long high,
++ unsigned long low);
++long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low);
++long sys32_sched_rr_get_interval(compat_pid_t pid,
++ struct compat_timespec __user *interval);
++long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
++ compat_sigset_t __user *oset, size_t sigsetsize);
++long sys32_rt_sigpending(compat_sigset_t __user *set, size_t sigsetsize);
++long sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo);
++long sys32_execve(void);
++long sys32_init_module(void __user *umod, unsigned long len,
++ const char __user *uargs);
++long sys32_delete_module(const char __user *name_user, unsigned int flags);
++long sys32_gettimeofday(struct compat_timeval __user *tv,
++ struct timezone __user *tz);
++long sys32_settimeofday(struct compat_timeval __user *tv,
++ struct timezone __user *tz);
++long sys32_pause(void);
++long sys32_pread64(unsigned int fd, char __user *ubuf, size_t count,
++ u32 poshi, u32 poslo);
++long sys32_pwrite64(unsigned int fd, const char __user *ubuf,
++ size_t count, u32 poshi, u32 poslo);
++compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count);
++long sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset,
++ size_t count);
++long sys32_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset,
++ s32 count);
++long sys32_sysctl(struct __sysctl_args32 __user *args);
++long sys32_stat64(char __user * filename, struct stat64_emu31 __user * statbuf);
++long sys32_lstat64(char __user * filename,
++ struct stat64_emu31 __user * statbuf);
++long sys32_fstat64(unsigned long fd, struct stat64_emu31 __user * statbuf);
++long sys32_fstatat64(unsigned int dfd, char __user *filename,
++ struct stat64_emu31 __user* statbuf, int flag);
++unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg);
++long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg);
++long sys32_read(unsigned int fd, char __user * buf, size_t count);
++long sys32_write(unsigned int fd, char __user * buf, size_t count);
++long sys32_clone(void);
++long sys32_fadvise64(int fd, loff_t offset, size_t len, int advise);
++long sys32_fadvise64_64(struct fadvise64_64_args __user *args);
++long sys32_sigaction(int sig, const struct old_sigaction32 __user *act,
++ struct old_sigaction32 __user *oact);
++long sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
++ struct sigaction32 __user *oact, size_t sigsetsize);
++long sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss);
+ #endif /* _ASM_S390X_S390_H */
+diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
+index a5692c4..c7f02e7 100644
+--- a/arch/s390/kernel/compat_signal.c
++++ b/arch/s390/kernel/compat_signal.c
+@@ -29,6 +29,7 @@
+ #include <asm/lowcore.h>
+ #include "compat_linux.h"
+ #include "compat_ptrace.h"
++#include "entry.h"
+
+ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+@@ -428,6 +429,10 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
+ /* Default to using normal stack */
+ sp = (unsigned long) A(regs->gprs[15]);
+
++ /* Overflow on alternate signal stack gives SIGSEGV. */
++ if (on_sig_stack(sp) && !on_sig_stack((sp - frame_size) & -8UL))
++ return (void __user *) -1UL;
++
+ /* This is the X/Open sanctioned signal stack switching. */
+ if (ka->sa.sa_flags & SA_ONSTACK) {
+ if (! sas_ss_flags(sp))
+@@ -461,6 +466,9 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(sigframe32)))
+ goto give_sigsegv;
+
++ if (frame == (void __user *) -1UL)
++ goto give_sigsegv;
++
+ if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32))
+ goto give_sigsegv;
+
+@@ -514,6 +522,9 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(rt_sigframe32)))
+ goto give_sigsegv;
+
++ if (frame == (void __user *) -1UL)
++ goto give_sigsegv;
++
+ if (copy_siginfo_to_user32(&frame->info, info))
+ goto give_sigsegv;
+
+diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
+index 1b2f5ce..dff0568 100644
+--- a/arch/s390/kernel/debug.c
++++ b/arch/s390/kernel/debug.c
+@@ -17,7 +17,6 @@
+ #include <linux/ctype.h>
+ #include <linux/sysctl.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/fs.h>
+@@ -73,7 +72,7 @@ static ssize_t debug_input(struct file *file, const char __user *user_buf,
+ static int debug_open(struct inode *inode, struct file *file);
+ static int debug_close(struct inode *inode, struct file *file);
+ static debug_info_t* debug_info_create(char *name, int pages_per_area,
+- int nr_areas, int buf_size);
++ int nr_areas, int buf_size, mode_t mode);
+ static void debug_info_get(debug_info_t *);
+ static void debug_info_put(debug_info_t *);
+ static int debug_prolog_level_fn(debug_info_t * id,
+@@ -157,7 +156,7 @@ struct debug_view debug_sprintf_view = {
+ };
+
+ /* used by dump analysis tools to determine version of debug feature */
+-unsigned int debug_feature_version = __DEBUG_FEATURE_VERSION;
++static unsigned int __used debug_feature_version = __DEBUG_FEATURE_VERSION;
+
+ /* static globals */
+
+@@ -327,7 +326,8 @@ debug_info_free(debug_info_t* db_info){
+ */
+
+ static debug_info_t*
+-debug_info_create(char *name, int pages_per_area, int nr_areas, int buf_size)
++debug_info_create(char *name, int pages_per_area, int nr_areas, int buf_size,
++ mode_t mode)
+ {
+ debug_info_t* rc;
+
+@@ -336,6 +336,8 @@ debug_info_create(char *name, int pages_per_area, int nr_areas, int buf_size)
+ if(!rc)
+ goto out;
+
++ rc->mode = mode & ~S_IFMT;
++
+ /* create root directory */
+ rc->debugfs_root_entry = debugfs_create_dir(rc->name,
+ debug_debugfs_root_entry);
+@@ -676,23 +678,30 @@ debug_close(struct inode *inode, struct file *file)
+ }
+
+ /*
+- * debug_register:
+- * - creates and initializes debug area for the caller
+- * - returns handle for debug area
++ * debug_register_mode:
++ * - Creates and initializes debug area for the caller
++ * The mode parameter allows to specify access rights for the s390dbf files
++ * - Returns handle for debug area
+ */
+
+-debug_info_t*
+-debug_register (char *name, int pages_per_area, int nr_areas, int buf_size)
++debug_info_t *debug_register_mode(char *name, int pages_per_area, int nr_areas,
++ int buf_size, mode_t mode, uid_t uid,
++ gid_t gid)
+ {
+ debug_info_t *rc = NULL;
+
++ /* Since debugfs currently does not support uid/gid other than root, */
++ /* we do not allow gid/uid != 0 until we get support for that. */
++ if ((uid != 0) || (gid != 0))
++ printk(KERN_WARNING "debug: Warning - Currently only uid/gid "
++ "= 0 are supported. Using root as owner now!");
+ if (!initialized)
+ BUG();
+ mutex_lock(&debug_mutex);
+
+ /* create new debug_info */
+
+- rc = debug_info_create(name, pages_per_area, nr_areas, buf_size);
++ rc = debug_info_create(name, pages_per_area, nr_areas, buf_size, mode);
+ if(!rc)
+ goto out;
+ debug_register_view(rc, &debug_level_view);
+@@ -705,6 +714,20 @@ out:
+ mutex_unlock(&debug_mutex);
+ return rc;
+ }
++EXPORT_SYMBOL(debug_register_mode);
++
++/*
++ * debug_register:
++ * - creates and initializes debug area for the caller
++ * - returns handle for debug area
++ */
++
++debug_info_t *debug_register(char *name, int pages_per_area, int nr_areas,
++ int buf_size)
++{
++ return debug_register_mode(name, pages_per_area, nr_areas, buf_size,
++ S_IRUSR | S_IWUSR, 0, 0);
++}
+
+ /*
+ * debug_unregister:
+@@ -1073,15 +1096,16 @@ debug_register_view(debug_info_t * id, struct debug_view *view)
+ int rc = 0;
+ int i;
+ unsigned long flags;
+- mode_t mode = S_IFREG;
++ mode_t mode;
+ struct dentry *pde;
+
+ if (!id)
+ goto out;
+- if (view->prolog_proc || view->format_proc || view->header_proc)
+- mode |= S_IRUSR;
+- if (view->input_proc)
+- mode |= S_IWUSR;
++ mode = (id->mode | S_IFREG) & ~S_IXUGO;
++ if (!(view->prolog_proc || view->format_proc || view->header_proc))
++ mode &= ~(S_IRUSR | S_IRGRP | S_IROTH);
++ if (!view->input_proc)
++ mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
+ pde = debugfs_create_file(view->name, mode, id->debugfs_root_entry,
+ id , &debug_file_ops);
+ if (!pde){
+diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
+index 01832c4..540a67f 100644
+--- a/arch/s390/kernel/early.c
++++ b/arch/s390/kernel/early.c
+@@ -21,6 +21,7 @@
+ #include <asm/setup.h>
+ #include <asm/cpcmd.h>
+ #include <asm/sclp.h>
++#include "entry.h"
+
+ /*
+ * Create a Kernel NSS if the SAVESYS= parameter is defined
+diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h
+new file mode 100644
+index 0000000..6b18963
+--- /dev/null
++++ b/arch/s390/kernel/entry.h
+@@ -0,0 +1,60 @@
++#ifndef _ENTRY_H
++#define _ENTRY_H
++
++#include <linux/types.h>
++#include <linux/signal.h>
++#include <asm/ptrace.h>
++
++typedef void pgm_check_handler_t(struct pt_regs *, long);
++extern pgm_check_handler_t *pgm_check_table[128];
++pgm_check_handler_t do_protection_exception;
++pgm_check_handler_t do_dat_exception;
++
++extern int sysctl_userprocess_debug;
++
++void do_single_step(struct pt_regs *regs);
++void syscall_trace(struct pt_regs *regs, int entryexit);
++void kernel_stack_overflow(struct pt_regs * regs);
++void do_signal(struct pt_regs *regs);
++int handle_signal32(unsigned long sig, struct k_sigaction *ka,
++ siginfo_t *info, sigset_t *oldset, struct pt_regs *regs);
++
++void do_extint(struct pt_regs *regs, unsigned short code);
++int __cpuinit start_secondary(void *cpuvoid);
++void __init startup_init(void);
++void die(const char * str, struct pt_regs * regs, long err);
++
++struct new_utsname;
++struct mmap_arg_struct;
++struct fadvise64_64_args;
++struct old_sigaction;
++struct sel_arg_struct;
++
++long sys_pipe(unsigned long __user *fildes);
++long sys_mmap2(struct mmap_arg_struct __user *arg);
++long old_mmap(struct mmap_arg_struct __user *arg);
++long sys_ipc(uint call, int first, unsigned long second,
++ unsigned long third, void __user *ptr);
++long s390x_newuname(struct new_utsname __user *name);
++long s390x_personality(unsigned long personality);
++long s390_fadvise64(int fd, u32 offset_high, u32 offset_low,
++ size_t len, int advice);
++long s390_fadvise64_64(struct fadvise64_64_args __user *args);
++long s390_fallocate(int fd, int mode, loff_t offset, u32 len_high, u32 len_low);
++long sys_fork(void);
++long sys_clone(void);
++long sys_vfork(void);
++void execve_tail(void);
++long sys_execve(void);
++int sys_sigsuspend(int history0, int history1, old_sigset_t mask);
++long sys_sigaction(int sig, const struct old_sigaction __user *act,
++ struct old_sigaction __user *oact);
++long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss);
++long sys_sigreturn(void);
++long sys_rt_sigreturn(void);
++long sys32_sigreturn(void);
++long sys32_rt_sigreturn(void);
++long old_select(struct sel_arg_struct __user *arg);
++long sys_ptrace(long request, long pid, long addr, long data);
++
++#endif /* _ENTRY_H */
+diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
+index efde6e1..cd959c0 100644
+--- a/arch/s390/kernel/entry64.S
++++ b/arch/s390/kernel/entry64.S
+@@ -475,6 +475,7 @@ pgm_check_handler:
+ pgm_no_vtime:
+ #endif
+ lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
++ mvc SP_ARGS(8,%r15),__LC_LAST_BREAK
+ TRACE_IRQS_OFF
+ lgf %r3,__LC_PGM_ILC # load program interruption code
+ lghi %r8,0x7f
+@@ -847,6 +848,7 @@ stack_overflow:
+ je 0f
+ la %r1,__LC_SAVE_AREA+32
+ 0: mvc SP_R12(32,%r15),0(%r1) # move %r12-%r15 to stack
++ mvc SP_ARGS(8,%r15),__LC_LAST_BREAK
+ xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # clear back chain
+ la %r2,SP_PTREGS(%r15) # load pt_regs
+ jg kernel_stack_overflow
+diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
+index 375232c..5325424 100644
+--- a/arch/s390/kernel/ipl.c
++++ b/arch/s390/kernel/ipl.c
+@@ -655,7 +655,7 @@ static struct kobj_attribute reipl_type_attr =
+
+ static struct kset *reipl_kset;
+
+-void reipl_run(struct shutdown_trigger *trigger)
++static void reipl_run(struct shutdown_trigger *trigger)
+ {
+ struct ccw_dev_id devid;
+ static char buf[100];
+diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
+index c5549a2..ed04d13 100644
+--- a/arch/s390/kernel/kprobes.c
++++ b/arch/s390/kernel/kprobes.c
+@@ -360,7 +360,7 @@ no_kprobe:
+ * - When the probed function returns, this probe
+ * causes the handlers to fire
+ */
+-void kretprobe_trampoline_holder(void)
++static void __used kretprobe_trampoline_holder(void)
+ {
+ asm volatile(".global kretprobe_trampoline\n"
+ "kretprobe_trampoline: bcr 0,0\n");
+diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
+index ce20315..c1aff19 100644
+--- a/arch/s390/kernel/process.c
++++ b/arch/s390/kernel/process.c
+@@ -36,6 +36,8 @@
+ #include <linux/module.h>
+ #include <linux/notifier.h>
+ #include <linux/utsname.h>
++#include <linux/tick.h>
++#include <linux/elfcore.h>
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+ #include <asm/system.h>
+@@ -44,6 +46,7 @@
+ #include <asm/irq.h>
+ #include <asm/timer.h>
+ #include <asm/cpu.h>
++#include "entry.h"
+
+ asmlinkage void ret_from_fork(void) asm ("ret_from_fork");
+
+@@ -76,6 +79,7 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
+ * Need to know about CPUs going idle?
+ */
+ static ATOMIC_NOTIFIER_HEAD(idle_chain);
++DEFINE_PER_CPU(struct s390_idle_data, s390_idle);
+
+ int register_idle_notifier(struct notifier_block *nb)
+ {
+@@ -89,9 +93,33 @@ int unregister_idle_notifier(struct notifier_block *nb)
+ }
+ EXPORT_SYMBOL(unregister_idle_notifier);
+
+-void do_monitor_call(struct pt_regs *regs, long interruption_code)
++static int s390_idle_enter(void)
++{
++ struct s390_idle_data *idle;
++ int nr_calls = 0;
++ void *hcpu;
++ int rc;
++
++ hcpu = (void *)(long)smp_processor_id();
++ rc = __atomic_notifier_call_chain(&idle_chain, S390_CPU_IDLE, hcpu, -1,
++ &nr_calls);
++ if (rc == NOTIFY_BAD) {
++ nr_calls--;
++ __atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE,
++ hcpu, nr_calls, NULL);
++ return rc;
++ }
++ idle = &__get_cpu_var(s390_idle);
++ spin_lock(&idle->lock);
++ idle->idle_count++;
++ idle->in_idle = 1;
++ idle->idle_enter = get_clock();
++ spin_unlock(&idle->lock);
++ return NOTIFY_OK;
++}
++
++void s390_idle_leave(void)
+ {
+-#ifdef CONFIG_SMP
+ struct s390_idle_data *idle;
+
+ idle = &__get_cpu_var(s390_idle);
+@@ -99,10 +127,6 @@ void do_monitor_call(struct pt_regs *regs, long interruption_code)
+ idle->idle_time += get_clock() - idle->idle_enter;
+ idle->in_idle = 0;
+ spin_unlock(&idle->lock);
+-#endif
+- /* disable monitor call class 0 */
+- __ctl_clear_bit(8, 15);
+-
+ atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE,
+ (void *)(long) smp_processor_id());
+ }
+@@ -113,61 +137,30 @@ extern void s390_handle_mcck(void);
+ */
+ static void default_idle(void)
+ {
+- int cpu, rc;
+- int nr_calls = 0;
+- void *hcpu;
+-#ifdef CONFIG_SMP
+- struct s390_idle_data *idle;
+-#endif
+-
+ /* CPU is going idle. */
+- cpu = smp_processor_id();
+- hcpu = (void *)(long)cpu;
+ local_irq_disable();
+ if (need_resched()) {
+ local_irq_enable();
+ return;
+ }
+-
+- rc = __atomic_notifier_call_chain(&idle_chain, S390_CPU_IDLE, hcpu, -1,
+- &nr_calls);
+- if (rc == NOTIFY_BAD) {
+- nr_calls--;
+- __atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE,
+- hcpu, nr_calls, NULL);
++ if (s390_idle_enter() == NOTIFY_BAD) {
+ local_irq_enable();
+ return;
+ }
+-
+- /* enable monitor call class 0 */
+- __ctl_set_bit(8, 15);
+-
+ #ifdef CONFIG_HOTPLUG_CPU
+- if (cpu_is_offline(cpu)) {
++ if (cpu_is_offline(smp_processor_id())) {
+ preempt_enable_no_resched();
+ cpu_die();
+ }
+ #endif
+-
+ local_mcck_disable();
+ if (test_thread_flag(TIF_MCCK_PENDING)) {
+ local_mcck_enable();
+- /* disable monitor call class 0 */
+- __ctl_clear_bit(8, 15);
+- atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE,
+- hcpu);
++ s390_idle_leave();
+ local_irq_enable();
+ s390_handle_mcck();
+ return;
+ }
+-#ifdef CONFIG_SMP
+- idle = &__get_cpu_var(s390_idle);
+- spin_lock(&idle->lock);
+- idle->idle_count++;
+- idle->in_idle = 1;
+- idle->idle_enter = get_clock();
+- spin_unlock(&idle->lock);
+-#endif
+ trace_hardirqs_on();
+ /* Wait for external, I/O or machine check interrupt. */
+ __load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
+@@ -177,9 +170,10 @@ static void default_idle(void)
+ void cpu_idle(void)
+ {
+ for (;;) {
++ tick_nohz_stop_sched_tick();
+ while (!need_resched())
+ default_idle();
+-
++ tick_nohz_restart_sched_tick();
+ preempt_enable_no_resched();
+ schedule();
+ preempt_disable();
+@@ -201,6 +195,7 @@ void show_regs(struct pt_regs *regs)
+ /* Show stack backtrace if pt_regs is from kernel mode */
+ if (!(regs->psw.mask & PSW_MASK_PSTATE))
+ show_trace(NULL, (unsigned long *) regs->gprs[15]);
++ show_last_breaking_event(regs);
+ }
+
+ extern void kernel_thread_starter(void);
+diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
+index 6e036ba..58a0642 100644
+--- a/arch/s390/kernel/ptrace.c
++++ b/arch/s390/kernel/ptrace.c
+@@ -41,6 +41,7 @@
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+ #include <asm/unistd.h>
++#include "entry.h"
+
+ #ifdef CONFIG_COMPAT
+ #include "compat_ptrace.h"
+diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c
+index acf93db..e019b41 100644
+--- a/arch/s390/kernel/s390_ext.c
++++ b/arch/s390/kernel/s390_ext.c
+@@ -13,11 +13,12 @@
+ #include <linux/errno.h>
+ #include <linux/kernel_stat.h>
+ #include <linux/interrupt.h>
+-
++#include <asm/cpu.h>
+ #include <asm/lowcore.h>
+ #include <asm/s390_ext.h>
+ #include <asm/irq_regs.h>
+ #include <asm/irq.h>
++#include "entry.h"
+
+ /*
+ * ext_int_hash[index] is the start of the list for all external interrupts
+@@ -119,13 +120,10 @@ void do_extint(struct pt_regs *regs, unsigned short code)
+
+ old_regs = set_irq_regs(regs);
+ irq_enter();
+- asm volatile ("mc 0,0");
+- if (S390_lowcore.int_clock >= S390_lowcore.jiffy_timer)
+- /**
+- * Make sure that the i/o interrupt did not "overtake"
+- * the last HZ timer interrupt.
+- */
+- account_ticks(S390_lowcore.int_clock);
++ s390_idle_check();
++ if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
++ /* Serve timer interrupts first. */
++ clock_comparator_work();
+ kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++;
+ index = ext_hash(code);
+ for (p = ext_int_hash[index]; p; p = p->next) {
+diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c
+index 7234c73..48238a1 100644
+--- a/arch/s390/kernel/s390_ksyms.c
++++ b/arch/s390/kernel/s390_ksyms.c
+@@ -27,13 +27,6 @@ EXPORT_SYMBOL(_zb_findmap);
+ EXPORT_SYMBOL(_sb_findmap);
+
+ /*
+- * semaphore ops
+- */
+-EXPORT_SYMBOL(__up);
+-EXPORT_SYMBOL(__down);
+-EXPORT_SYMBOL(__down_interruptible);
+-
+-/*
+ * binfmt_elf loader
+ */
+ extern int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs);
+diff --git a/arch/s390/kernel/semaphore.c b/arch/s390/kernel/semaphore.c
+deleted file mode 100644
+index 191303f..0000000
+--- a/arch/s390/kernel/semaphore.c
++++ /dev/null
+@@ -1,108 +0,0 @@
+-/*
+- * linux/arch/s390/kernel/semaphore.c
+- *
+- * S390 version
+- * Copyright (C) 1998-2000 IBM Corporation
+- * Author(s): Martin Schwidefsky
+- *
+- * Derived from "linux/arch/i386/kernel/semaphore.c
+- * Copyright (C) 1999, Linus Torvalds
+- *
+- */
+-#include <linux/sched.h>
+-#include <linux/errno.h>
+-#include <linux/init.h>
+-
+-#include <asm/semaphore.h>
+-
+-/*
+- * Atomically update sem->count. Equivalent to:
+- * old_val = sem->count.counter;
+- * new_val = ((old_val >= 0) ? old_val : 0) + incr;
+- * sem->count.counter = new_val;
+- * return old_val;
+- */
+-static inline int __sem_update_count(struct semaphore *sem, int incr)
+-{
+- int old_val, new_val;
+-
+- asm volatile(
+- " l %0,0(%3)\n"
+- "0: ltr %1,%0\n"
+- " jhe 1f\n"
+- " lhi %1,0\n"
+- "1: ar %1,%4\n"
+- " cs %0,%1,0(%3)\n"
+- " jl 0b\n"
+- : "=&d" (old_val), "=&d" (new_val), "=m" (sem->count)
+- : "a" (&sem->count), "d" (incr), "m" (sem->count)
+- : "cc");
+- return old_val;
+-}
+-
+-/*
+- * The inline function up() incremented count but the result
+- * was <= 0. This indicates that some process is waiting on
+- * the semaphore. The semaphore is free and we'll wake the
+- * first sleeping process, so we set count to 1 unless some
+- * other cpu has called up in the meantime in which case
+- * we just increment count by 1.
+- */
+-void __up(struct semaphore *sem)
+-{
+- __sem_update_count(sem, 1);
+- wake_up(&sem->wait);
+-}
+-
+-/*
+- * The inline function down() decremented count and the result
+- * was < 0. The wait loop will atomically test and update the
+- * semaphore counter following the rules:
+- * count > 0: decrement count, wake up queue and exit.
+- * count <= 0: set count to -1, go to sleep.
+- */
+-void __sched __down(struct semaphore * sem)
+-{
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+-
+- __set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+- add_wait_queue_exclusive(&sem->wait, &wait);
+- while (__sem_update_count(sem, -1) <= 0) {
+- schedule();
+- set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+- }
+- remove_wait_queue(&sem->wait, &wait);
+- __set_task_state(tsk, TASK_RUNNING);
+- wake_up(&sem->wait);
+-}
+-
+-/*
+- * Same as __down() with an additional test for signals.
+- * If a signal is pending the count is updated as follows:
+- * count > 0: wake up queue and exit.
+- * count <= 0: set count to 0, wake up queue and exit.
+- */
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+- int retval = 0;
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+-
+- __set_task_state(tsk, TASK_INTERRUPTIBLE);
+- add_wait_queue_exclusive(&sem->wait, &wait);
+- while (__sem_update_count(sem, -1) <= 0) {
+- if (signal_pending(current)) {
+- __sem_update_count(sem, 0);
+- retval = -EINTR;
+- break;
+- }
+- schedule();
+- set_task_state(tsk, TASK_INTERRUPTIBLE);
+- }
+- remove_wait_queue(&sem->wait, &wait);
+- __set_task_state(tsk, TASK_RUNNING);
+- wake_up(&sem->wait);
+- return retval;
+-}
+-
+diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
+index 290e504..7141147 100644
+--- a/arch/s390/kernel/setup.c
++++ b/arch/s390/kernel/setup.c
+@@ -39,6 +39,7 @@
+ #include <linux/pfn.h>
+ #include <linux/ctype.h>
+ #include <linux/reboot.h>
++#include <linux/topology.h>
+
+ #include <asm/ipl.h>
+ #include <asm/uaccess.h>
+@@ -427,7 +428,7 @@ setup_lowcore(void)
+ lc->io_new_psw.mask = psw_kernel_bits;
+ lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;
+ lc->ipl_device = S390_lowcore.ipl_device;
+- lc->jiffy_timer = -1LL;
++ lc->clock_comparator = -1ULL;
+ lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
+ lc->async_stack = (unsigned long)
+ __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE;
+@@ -687,7 +688,7 @@ static __init unsigned int stfl(void)
+ return S390_lowcore.stfl_fac_list;
+ }
+
+-static __init int stfle(unsigned long long *list, int doublewords)
++static int __init __stfle(unsigned long long *list, int doublewords)
+ {
+ typedef struct { unsigned long long _[doublewords]; } addrtype;
+ register unsigned long __nr asm("0") = doublewords - 1;
+@@ -697,6 +698,13 @@ static __init int stfle(unsigned long long *list, int doublewords)
+ return __nr + 1;
+ }
+
++int __init stfle(unsigned long long *list, int doublewords)
++{
++ if (!(stfl() & (1UL << 24)))
++ return -EOPNOTSUPP;
++ return __stfle(list, doublewords);
++}
++
+ /*
+ * Setup hardware capabilities.
+ */
+@@ -741,7 +749,7 @@ static void __init setup_hwcaps(void)
+ * HWCAP_S390_DFP bit 6.
+ */
+ if ((elf_hwcap & (1UL << 2)) &&
+- stfle(&facility_list_extended, 1) > 0) {
++ __stfle(&facility_list_extended, 1) > 0) {
+ if (facility_list_extended & (1ULL << (64 - 43)))
+ elf_hwcap |= 1UL << 6;
+ }
+@@ -823,6 +831,7 @@ setup_arch(char **cmdline_p)
+
+ cpu_init();
+ __cpu_logical_map[0] = S390_lowcore.cpu_data.cpu_addr;
++ s390_init_cpu_topology();
+
+ /*
+ * Setup capabilities (ELF_HWCAP & ELF_PLATFORM).
+diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
+index 4449bf3..b976820 100644
+--- a/arch/s390/kernel/signal.c
++++ b/arch/s390/kernel/signal.c
+@@ -27,6 +27,7 @@
+ #include <asm/ucontext.h>
+ #include <asm/uaccess.h>
+ #include <asm/lowcore.h>
++#include "entry.h"
+
+ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+@@ -235,6 +236,10 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
+ /* Default to using normal stack */
+ sp = regs->gprs[15];
+
++ /* Overflow on alternate signal stack gives SIGSEGV. */
++ if (on_sig_stack(sp) && !on_sig_stack((sp - frame_size) & -8UL))
++ return (void __user *) -1UL;
++
+ /* This is the X/Open sanctioned signal stack switching. */
+ if (ka->sa.sa_flags & SA_ONSTACK) {
+ if (! sas_ss_flags(sp))
+@@ -270,6 +275,9 @@ static int setup_frame(int sig, struct k_sigaction *ka,
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(sigframe)))
+ goto give_sigsegv;
+
++ if (frame == (void __user *) -1UL)
++ goto give_sigsegv;
++
+ if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE))
+ goto give_sigsegv;
+
+@@ -327,6 +335,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(rt_sigframe)))
+ goto give_sigsegv;
+
++ if (frame == (void __user *) -1UL)
++ goto give_sigsegv;
++
+ if (copy_siginfo_to_user(&frame->info, info))
+ goto give_sigsegv;
+
+@@ -474,11 +485,6 @@ void do_signal(struct pt_regs *regs)
+ int ret;
+ #ifdef CONFIG_COMPAT
+ if (test_thread_flag(TIF_31BIT)) {
+- extern int handle_signal32(unsigned long sig,
+- struct k_sigaction *ka,
+- siginfo_t *info,
+- sigset_t *oldset,
+- struct pt_regs *regs);
+ ret = handle_signal32(signr, &ka, &info, oldset, regs);
+ }
+ else
+diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
+index 8f894d3..0dfa988 100644
+--- a/arch/s390/kernel/smp.c
++++ b/arch/s390/kernel/smp.c
+@@ -44,6 +44,7 @@
+ #include <asm/lowcore.h>
+ #include <asm/sclp.h>
+ #include <asm/cpu.h>
++#include "entry.h"
+
+ /*
+ * An array with a pointer the lowcore of every CPU.
+@@ -67,13 +68,12 @@ enum s390_cpu_state {
+ CPU_STATE_CONFIGURED,
+ };
+
+-#ifdef CONFIG_HOTPLUG_CPU
+-static DEFINE_MUTEX(smp_cpu_state_mutex);
+-#endif
++DEFINE_MUTEX(smp_cpu_state_mutex);
++int smp_cpu_polarization[NR_CPUS];
+ static int smp_cpu_state[NR_CPUS];
++static int cpu_management;
+
+ static DEFINE_PER_CPU(struct cpu, cpu_devices);
+-DEFINE_PER_CPU(struct s390_idle_data, s390_idle);
+
+ static void smp_ext_bitcall(int, ec_bit_sig);
+
+@@ -298,7 +298,7 @@ static void smp_ext_bitcall(int cpu, ec_bit_sig sig)
+ /*
+ * this function sends a 'purge tlb' signal to another CPU.
+ */
+-void smp_ptlb_callback(void *info)
++static void smp_ptlb_callback(void *info)
+ {
+ __tlb_flush_local();
+ }
+@@ -456,6 +456,7 @@ static int smp_rescan_cpus_sigp(cpumask_t avail)
+ if (cpu_known(cpu_id))
+ continue;
+ __cpu_logical_map[logical_cpu] = cpu_id;
++ smp_cpu_polarization[logical_cpu] = POLARIZATION_UNKNWN;
+ if (!cpu_stopped(logical_cpu))
+ continue;
+ cpu_set(logical_cpu, cpu_present_map);
+@@ -489,6 +490,7 @@ static int smp_rescan_cpus_sclp(cpumask_t avail)
+ if (cpu_known(cpu_id))
+ continue;
+ __cpu_logical_map[logical_cpu] = cpu_id;
++ smp_cpu_polarization[logical_cpu] = POLARIZATION_UNKNWN;
+ cpu_set(logical_cpu, cpu_present_map);
+ if (cpu >= info->configured)
+ smp_cpu_state[logical_cpu] = CPU_STATE_STANDBY;
+@@ -846,6 +848,7 @@ void __init smp_prepare_boot_cpu(void)
+ S390_lowcore.percpu_offset = __per_cpu_offset[0];
+ current_set[0] = current;
+ smp_cpu_state[0] = CPU_STATE_CONFIGURED;
++ smp_cpu_polarization[0] = POLARIZATION_UNKNWN;
+ spin_lock_init(&(&__get_cpu_var(s390_idle))->lock);
+ }
+
+@@ -897,15 +900,19 @@ static ssize_t cpu_configure_store(struct sys_device *dev, const char *buf,
+ case 0:
+ if (smp_cpu_state[cpu] == CPU_STATE_CONFIGURED) {
+ rc = sclp_cpu_deconfigure(__cpu_logical_map[cpu]);
+- if (!rc)
++ if (!rc) {
+ smp_cpu_state[cpu] = CPU_STATE_STANDBY;
++ smp_cpu_polarization[cpu] = POLARIZATION_UNKNWN;
++ }
+ }
+ break;
+ case 1:
+ if (smp_cpu_state[cpu] == CPU_STATE_STANDBY) {
+ rc = sclp_cpu_configure(__cpu_logical_map[cpu]);
+- if (!rc)
++ if (!rc) {
+ smp_cpu_state[cpu] = CPU_STATE_CONFIGURED;
++ smp_cpu_polarization[cpu] = POLARIZATION_UNKNWN;
++ }
+ }
+ break;
+ default:
+@@ -919,6 +926,34 @@ out:
+ static SYSDEV_ATTR(configure, 0644, cpu_configure_show, cpu_configure_store);
+ #endif /* CONFIG_HOTPLUG_CPU */
+
++static ssize_t cpu_polarization_show(struct sys_device *dev, char *buf)
++{
++ int cpu = dev->id;
++ ssize_t count;
++
++ mutex_lock(&smp_cpu_state_mutex);
++ switch (smp_cpu_polarization[cpu]) {
++ case POLARIZATION_HRZ:
++ count = sprintf(buf, "horizontal\n");
++ break;
++ case POLARIZATION_VL:
++ count = sprintf(buf, "vertical:low\n");
++ break;
++ case POLARIZATION_VM:
++ count = sprintf(buf, "vertical:medium\n");
++ break;
++ case POLARIZATION_VH:
++ count = sprintf(buf, "vertical:high\n");
++ break;
++ default:
++ count = sprintf(buf, "unknown\n");
++ break;
++ }
++ mutex_unlock(&smp_cpu_state_mutex);
++ return count;
++}
++static SYSDEV_ATTR(polarization, 0444, cpu_polarization_show, NULL);
++
+ static ssize_t show_cpu_address(struct sys_device *dev, char *buf)
+ {
+ return sprintf(buf, "%d\n", __cpu_logical_map[dev->id]);
+@@ -931,6 +966,7 @@ static struct attribute *cpu_common_attrs[] = {
+ &attr_configure.attr,
+ #endif
+ &attr_address.attr,
++ &attr_polarization.attr,
+ NULL,
+ };
+
+@@ -1075,11 +1111,48 @@ static ssize_t __ref rescan_store(struct sys_device *dev,
+ out:
+ put_online_cpus();
+ mutex_unlock(&smp_cpu_state_mutex);
++ if (!cpus_empty(newcpus))
++ topology_schedule_update();
+ return rc ? rc : count;
+ }
+ static SYSDEV_ATTR(rescan, 0200, NULL, rescan_store);
+ #endif /* CONFIG_HOTPLUG_CPU */
+
++static ssize_t dispatching_show(struct sys_device *dev, char *buf)
++{
++ ssize_t count;
++
++ mutex_lock(&smp_cpu_state_mutex);
++ count = sprintf(buf, "%d\n", cpu_management);
++ mutex_unlock(&smp_cpu_state_mutex);
++ return count;
++}
++
++static ssize_t dispatching_store(struct sys_device *dev, const char *buf,
++ size_t count)
++{
++ int val, rc;
++ char delim;
++
++ if (sscanf(buf, "%d %c", &val, &delim) != 1)
++ return -EINVAL;
++ if (val != 0 && val != 1)
++ return -EINVAL;
++ rc = 0;
++ mutex_lock(&smp_cpu_state_mutex);
++ get_online_cpus();
++ if (cpu_management == val)
++ goto out;
++ rc = topology_set_cpu_management(val);
++ if (!rc)
++ cpu_management = val;
++out:
++ put_online_cpus();
++ mutex_unlock(&smp_cpu_state_mutex);
++ return rc ? rc : count;
++}
++static SYSDEV_ATTR(dispatching, 0644, dispatching_show, dispatching_store);
++
+ static int __init topology_init(void)
+ {
+ int cpu;
+@@ -1093,6 +1166,10 @@ static int __init topology_init(void)
+ if (rc)
+ return rc;
+ #endif
++ rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj,
++ &attr_dispatching.attr);
++ if (rc)
++ return rc;
+ for_each_present_cpu(cpu) {
+ rc = smp_add_present_cpu(cpu);
+ if (rc)
+diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c
+index fefee99..988d0d6 100644
+--- a/arch/s390/kernel/sys_s390.c
++++ b/arch/s390/kernel/sys_s390.c
+@@ -29,8 +29,8 @@
+ #include <linux/personality.h>
+ #include <linux/unistd.h>
+ #include <linux/ipc.h>
+-
+ #include <asm/uaccess.h>
++#include "entry.h"
+
+ /*
+ * sys_pipe() is the normal C calling standard for creating
+diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
+index cb232c1..7aec676 100644
+--- a/arch/s390/kernel/time.c
++++ b/arch/s390/kernel/time.c
+@@ -30,7 +30,7 @@
+ #include <linux/timex.h>
+ #include <linux/notifier.h>
+ #include <linux/clocksource.h>
+-
++#include <linux/clockchips.h>
+ #include <asm/uaccess.h>
+ #include <asm/delay.h>
+ #include <asm/s390_ext.h>
+@@ -39,6 +39,7 @@
+ #include <asm/irq_regs.h>
+ #include <asm/timer.h>
+ #include <asm/etr.h>
++#include <asm/cio.h>
+
+ /* change this if you have some constant time drift */
+ #define USECS_PER_JIFFY ((unsigned long) 1000000/HZ)
+@@ -57,16 +58,16 @@
+
+ static ext_int_info_t ext_int_info_cc;
+ static ext_int_info_t ext_int_etr_cc;
+-static u64 init_timer_cc;
+ static u64 jiffies_timer_cc;
+-static u64 xtime_cc;
++
++static DEFINE_PER_CPU(struct clock_event_device, comparators);
+
+ /*
+ * Scheduler clock - returns current time in nanosec units.
+ */
+ unsigned long long sched_clock(void)
+ {
+- return ((get_clock() - jiffies_timer_cc) * 125) >> 9;
++ return ((get_clock_xt() - jiffies_timer_cc) * 125) >> 9;
+ }
+
+ /*
+@@ -95,162 +96,40 @@ void tod_to_timeval(__u64 todval, struct timespec *xtime)
+ #define s390_do_profile() do { ; } while(0)
+ #endif /* CONFIG_PROFILING */
+
+-/*
+- * Advance the per cpu tick counter up to the time given with the
+- * "time" argument. The per cpu update consists of accounting
+- * the virtual cpu time, calling update_process_times and calling
+- * the profiling hook. If xtime is before time it is advanced as well.
+- */
+-void account_ticks(u64 time)
++void clock_comparator_work(void)
+ {
+- __u32 ticks;
+- __u64 tmp;
+-
+- /* Calculate how many ticks have passed. */
+- if (time < S390_lowcore.jiffy_timer)
+- return;
+- tmp = time - S390_lowcore.jiffy_timer;
+- if (tmp >= 2*CLK_TICKS_PER_JIFFY) { /* more than two ticks ? */
+- ticks = __div(tmp, CLK_TICKS_PER_JIFFY) + 1;
+- S390_lowcore.jiffy_timer +=
+- CLK_TICKS_PER_JIFFY * (__u64) ticks;
+- } else if (tmp >= CLK_TICKS_PER_JIFFY) {
+- ticks = 2;
+- S390_lowcore.jiffy_timer += 2*CLK_TICKS_PER_JIFFY;
+- } else {
+- ticks = 1;
+- S390_lowcore.jiffy_timer += CLK_TICKS_PER_JIFFY;
+- }
+-
+-#ifdef CONFIG_SMP
+- /*
+- * Do not rely on the boot cpu to do the calls to do_timer.
+- * Spread it over all cpus instead.
+- */
+- write_seqlock(&xtime_lock);
+- if (S390_lowcore.jiffy_timer > xtime_cc) {
+- __u32 xticks;
+- tmp = S390_lowcore.jiffy_timer - xtime_cc;
+- if (tmp >= 2*CLK_TICKS_PER_JIFFY) {
+- xticks = __div(tmp, CLK_TICKS_PER_JIFFY);
+- xtime_cc += (__u64) xticks * CLK_TICKS_PER_JIFFY;
+- } else {
+- xticks = 1;
+- xtime_cc += CLK_TICKS_PER_JIFFY;
+- }
+- do_timer(xticks);
+- }
+- write_sequnlock(&xtime_lock);
+-#else
+- do_timer(ticks);
+-#endif
+-
+- while (ticks--)
+- update_process_times(user_mode(get_irq_regs()));
++ struct clock_event_device *cd;
+
++ S390_lowcore.clock_comparator = -1ULL;
++ set_clock_comparator(S390_lowcore.clock_comparator);
++ cd = &__get_cpu_var(comparators);
++ cd->event_handler(cd);
+ s390_do_profile();
+ }
+
+-#ifdef CONFIG_NO_IDLE_HZ
+-
+-#ifdef CONFIG_NO_IDLE_HZ_INIT
+-int sysctl_hz_timer = 0;
+-#else
+-int sysctl_hz_timer = 1;
+-#endif
+-
+-/*
+- * Stop the HZ tick on the current CPU.
+- * Only cpu_idle may call this function.
+- */
+-static void stop_hz_timer(void)
+-{
+- unsigned long flags;
+- unsigned long seq, next;
+- __u64 timer, todval;
+- int cpu = smp_processor_id();
+-
+- if (sysctl_hz_timer != 0)
+- return;
+-
+- cpu_set(cpu, nohz_cpu_mask);
+-
+- /*
+- * Leave the clock comparator set up for the next timer
+- * tick if either rcu or a softirq is pending.
+- */
+- if (rcu_needs_cpu(cpu) || local_softirq_pending()) {
+- cpu_clear(cpu, nohz_cpu_mask);
+- return;
+- }
+-
+- /*
+- * This cpu is going really idle. Set up the clock comparator
+- * for the next event.
+- */
+- next = next_timer_interrupt();
+- do {
+- seq = read_seqbegin_irqsave(&xtime_lock, flags);
+- timer = ((__u64) next) - ((__u64) jiffies) + jiffies_64;
+- } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
+- todval = -1ULL;
+- /* Be careful about overflows. */
+- if (timer < (-1ULL / CLK_TICKS_PER_JIFFY)) {
+- timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY;
+- if (timer >= jiffies_timer_cc)
+- todval = timer;
+- }
+- set_clock_comparator(todval);
+-}
+-
+ /*
+- * Start the HZ tick on the current CPU.
+- * Only cpu_idle may call this function.
++ * Fixup the clock comparator.
+ */
+-static void start_hz_timer(void)
++static void fixup_clock_comparator(unsigned long long delta)
+ {
+- if (!cpu_isset(smp_processor_id(), nohz_cpu_mask))
++ /* If nobody is waiting there's nothing to fix. */
++ if (S390_lowcore.clock_comparator == -1ULL)
+ return;
+- account_ticks(get_clock());
+- set_clock_comparator(S390_lowcore.jiffy_timer + CPU_DEVIATION);
+- cpu_clear(smp_processor_id(), nohz_cpu_mask);
+-}
+-
+-static int nohz_idle_notify(struct notifier_block *self,
+- unsigned long action, void *hcpu)
+-{
+- switch (action) {
+- case S390_CPU_IDLE:
+- stop_hz_timer();
+- break;
+- case S390_CPU_NOT_IDLE:
+- start_hz_timer();
+- break;
+- }
+- return NOTIFY_OK;
++ S390_lowcore.clock_comparator += delta;
++ set_clock_comparator(S390_lowcore.clock_comparator);
+ }
+
+-static struct notifier_block nohz_idle_nb = {
+- .notifier_call = nohz_idle_notify,
+-};
+-
+-static void __init nohz_init(void)
++static int s390_next_event(unsigned long delta,
++ struct clock_event_device *evt)
+ {
+- if (register_idle_notifier(&nohz_idle_nb))
+- panic("Couldn't register idle notifier");
++ S390_lowcore.clock_comparator = get_clock() + delta;
++ set_clock_comparator(S390_lowcore.clock_comparator);
++ return 0;
+ }
+
+-#endif
+-
+-/*
+- * Set up per cpu jiffy timer and set the clock comparator.
+- */
+-static void setup_jiffy_timer(void)
++static void s390_set_mode(enum clock_event_mode mode,
++ struct clock_event_device *evt)
+ {
+- /* Set up clock comparator to next jiffy. */
+- S390_lowcore.jiffy_timer =
+- jiffies_timer_cc + (jiffies_64 + 1) * CLK_TICKS_PER_JIFFY;
+- set_clock_comparator(S390_lowcore.jiffy_timer + CPU_DEVIATION);
+ }
+
+ /*
+@@ -259,7 +138,26 @@ static void setup_jiffy_timer(void)
+ */
+ void init_cpu_timer(void)
+ {
+- setup_jiffy_timer();
++ struct clock_event_device *cd;
++ int cpu;
++
++ S390_lowcore.clock_comparator = -1ULL;
++ set_clock_comparator(S390_lowcore.clock_comparator);
++
++ cpu = smp_processor_id();
++ cd = &per_cpu(comparators, cpu);
++ cd->name = "comparator";
++ cd->features = CLOCK_EVT_FEAT_ONESHOT;
++ cd->mult = 16777;
++ cd->shift = 12;
++ cd->min_delta_ns = 1;
++ cd->max_delta_ns = LONG_MAX;
++ cd->rating = 400;
++ cd->cpumask = cpumask_of_cpu(cpu);
++ cd->set_next_event = s390_next_event;
++ cd->set_mode = s390_set_mode;
++
++ clockevents_register_device(cd);
+
+ /* Enable clock comparator timer interrupt. */
+ __ctl_set_bit(0,11);
+@@ -270,8 +168,6 @@ void init_cpu_timer(void)
+
+ static void clock_comparator_interrupt(__u16 code)
+ {
+- /* set clock comparator for next tick */
+- set_clock_comparator(S390_lowcore.jiffy_timer + CPU_DEVIATION);
+ }
+
+ static void etr_reset(void);
+@@ -316,8 +212,9 @@ static struct clocksource clocksource_tod = {
+ */
+ void __init time_init(void)
+ {
++ u64 init_timer_cc;
++
+ init_timer_cc = reset_tod_clock();
+- xtime_cc = init_timer_cc + CLK_TICKS_PER_JIFFY;
+ jiffies_timer_cc = init_timer_cc - jiffies_64 * CLK_TICKS_PER_JIFFY;
+
+ /* set xtime */
+@@ -342,10 +239,6 @@ void __init time_init(void)
+ /* Enable TOD clock interrupts on the boot cpu. */
+ init_cpu_timer();
+
+-#ifdef CONFIG_NO_IDLE_HZ
+- nohz_init();
+-#endif
+-
+ #ifdef CONFIG_VIRT_TIMER
+ vtime_init();
+ #endif
+@@ -699,53 +592,49 @@ static int etr_aib_follows(struct etr_aib *a1, struct etr_aib *a2, int p)
+ }
+
+ /*
+- * The time is "clock". xtime is what we think the time is.
++ * The time is "clock". old is what we think the time is.
+ * Adjust the value by a multiple of jiffies and add the delta to ntp.
+ * "delay" is an approximation how long the synchronization took. If
+ * the time correction is positive, then "delay" is subtracted from
+ * the time difference and only the remaining part is passed to ntp.
+ */
+-static void etr_adjust_time(unsigned long long clock, unsigned long long delay)
++static unsigned long long etr_adjust_time(unsigned long long old,
++ unsigned long long clock,
++ unsigned long long delay)
+ {
+ unsigned long long delta, ticks;
+ struct timex adjust;
+
+- /*
+- * We don't have to take the xtime lock because the cpu
+- * executing etr_adjust_time is running disabled in
+- * tasklet context and all other cpus are looping in
+- * etr_sync_cpu_start.
+- */
+- if (clock > xtime_cc) {
++ if (clock > old) {
+ /* It is later than we thought. */
+- delta = ticks = clock - xtime_cc;
++ delta = ticks = clock - old;
+ delta = ticks = (delta < delay) ? 0 : delta - delay;
+ delta -= do_div(ticks, CLK_TICKS_PER_JIFFY);
+- init_timer_cc = init_timer_cc + delta;
+- jiffies_timer_cc = jiffies_timer_cc + delta;
+- xtime_cc = xtime_cc + delta;
+ adjust.offset = ticks * (1000000 / HZ);
+ } else {
+ /* It is earlier than we thought. */
+- delta = ticks = xtime_cc - clock;
++ delta = ticks = old - clock;
+ delta -= do_div(ticks, CLK_TICKS_PER_JIFFY);
+- init_timer_cc = init_timer_cc - delta;
+- jiffies_timer_cc = jiffies_timer_cc - delta;
+- xtime_cc = xtime_cc - delta;
++ delta = -delta;
+ adjust.offset = -ticks * (1000000 / HZ);
+ }
++ jiffies_timer_cc += delta;
+ if (adjust.offset != 0) {
+ printk(KERN_NOTICE "etr: time adjusted by %li micro-seconds\n",
+ adjust.offset);
+ adjust.modes = ADJ_OFFSET_SINGLESHOT;
+ do_adjtimex(&adjust);
+ }
++ return delta;
+ }
+
++static struct {
++ int in_sync;
++ unsigned long long fixup_cc;
++} etr_sync;
++
+ static void etr_sync_cpu_start(void *dummy)
+ {
+- int *in_sync = dummy;
+-
+ etr_enable_sync_clock();
+ /*
+ * This looks like a busy wait loop but it isn't. etr_sync_cpus
+@@ -753,7 +642,7 @@ static void etr_sync_cpu_start(void *dummy)
+ * __udelay will stop the cpu on an enabled wait psw until the
+ * TOD is running again.
+ */
+- while (*in_sync == 0) {
++ while (etr_sync.in_sync == 0) {
+ __udelay(1);
+ /*
+ * A different cpu changes *in_sync. Therefore use
+@@ -761,14 +650,14 @@ static void etr_sync_cpu_start(void *dummy)
+ */
+ barrier();
+ }
+- if (*in_sync != 1)
++ if (etr_sync.in_sync != 1)
+ /* Didn't work. Clear per-cpu in sync bit again. */
+ etr_disable_sync_clock(NULL);
+ /*
+ * This round of TOD syncing is done. Set the clock comparator
+ * to the next tick and let the processor continue.
+ */
+- setup_jiffy_timer();
++ fixup_clock_comparator(etr_sync.fixup_cc);
+ }
+
+ static void etr_sync_cpu_end(void *dummy)
+@@ -783,8 +672,8 @@ static void etr_sync_cpu_end(void *dummy)
+ static int etr_sync_clock(struct etr_aib *aib, int port)
+ {
+ struct etr_aib *sync_port;
+- unsigned long long clock, delay;
+- int in_sync, follows;
++ unsigned long long clock, old_clock, delay, delta;
++ int follows;
+ int rc;
+
+ /* Check if the current aib is adjacent to the sync port aib. */
+@@ -799,9 +688,9 @@ static int etr_sync_clock(struct etr_aib *aib, int port)
+ * successfully synced the clock. smp_call_function will
+ * return after all other cpus are in etr_sync_cpu_start.
+ */
+- in_sync = 0;
++ memset(&etr_sync, 0, sizeof(etr_sync));
+ preempt_disable();
+- smp_call_function(etr_sync_cpu_start,&in_sync,0,0);
++ smp_call_function(etr_sync_cpu_start, NULL, 0, 0);
+ local_irq_disable();
+ etr_enable_sync_clock();
+
+@@ -809,6 +698,7 @@ static int etr_sync_clock(struct etr_aib *aib, int port)
+ __ctl_set_bit(14, 21);
+ __ctl_set_bit(0, 29);
+ clock = ((unsigned long long) (aib->edf2.etv + 1)) << 32;
++ old_clock = get_clock();
+ if (set_clock(clock) == 0) {
+ __udelay(1); /* Wait for the clock to start. */
+ __ctl_clear_bit(0, 29);
+@@ -817,16 +707,17 @@ static int etr_sync_clock(struct etr_aib *aib, int port)
+ /* Adjust Linux timing variables. */
+ delay = (unsigned long long)
+ (aib->edf2.etv - sync_port->edf2.etv) << 32;
+- etr_adjust_time(clock, delay);
+- setup_jiffy_timer();
++ delta = etr_adjust_time(old_clock, clock, delay);
++ etr_sync.fixup_cc = delta;
++ fixup_clock_comparator(delta);
+ /* Verify that the clock is properly set. */
+ if (!etr_aib_follows(sync_port, aib, port)) {
+ /* Didn't work. */
+ etr_disable_sync_clock(NULL);
+- in_sync = -EAGAIN;
++ etr_sync.in_sync = -EAGAIN;
+ rc = -EAGAIN;
+ } else {
+- in_sync = 1;
++ etr_sync.in_sync = 1;
+ rc = 0;
+ }
+ } else {
+@@ -834,7 +725,7 @@ static int etr_sync_clock(struct etr_aib *aib, int port)
+ __ctl_clear_bit(0, 29);
+ __ctl_clear_bit(14, 21);
+ etr_disable_sync_clock(NULL);
+- in_sync = -EAGAIN;
++ etr_sync.in_sync = -EAGAIN;
+ rc = -EAGAIN;
+ }
+ local_irq_enable();
+diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
+new file mode 100644
+index 0000000..12b39b3
+--- /dev/null
++++ b/arch/s390/kernel/topology.c
+@@ -0,0 +1,314 @@
++/*
++ * Copyright IBM Corp. 2007
++ * Author(s): Heiko Carstens <heiko.carstens at de.ibm.com>
++ */
++
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/init.h>
++#include <linux/device.h>
++#include <linux/bootmem.h>
++#include <linux/sched.h>
++#include <linux/workqueue.h>
++#include <linux/cpu.h>
++#include <linux/smp.h>
++#include <asm/delay.h>
++#include <asm/s390_ext.h>
++#include <asm/sysinfo.h>
++
++#define CPU_BITS 64
++#define NR_MAG 6
++
++#define PTF_HORIZONTAL (0UL)
++#define PTF_VERTICAL (1UL)
++#define PTF_CHECK (2UL)
++
++struct tl_cpu {
++ unsigned char reserved0[4];
++ unsigned char :6;
++ unsigned char pp:2;
++ unsigned char reserved1;
++ unsigned short origin;
++ unsigned long mask[CPU_BITS / BITS_PER_LONG];
++};
++
++struct tl_container {
++ unsigned char reserved[8];
++};
++
++union tl_entry {
++ unsigned char nl;
++ struct tl_cpu cpu;
++ struct tl_container container;
++};
++
++struct tl_info {
++ unsigned char reserved0[2];
++ unsigned short length;
++ unsigned char mag[NR_MAG];
++ unsigned char reserved1;
++ unsigned char mnest;
++ unsigned char reserved2[4];
++ union tl_entry tle[0];
++};
++
++struct core_info {
++ struct core_info *next;
++ cpumask_t mask;
++};
++
++static void topology_work_fn(struct work_struct *work);
++static struct tl_info *tl_info;
++static struct core_info core_info;
++static int machine_has_topology;
++static int machine_has_topology_irq;
++static struct timer_list topology_timer;
++static void set_topology_timer(void);
++static DECLARE_WORK(topology_work, topology_work_fn);
++
++cpumask_t cpu_coregroup_map(unsigned int cpu)
++{
++ struct core_info *core = &core_info;
++ cpumask_t mask;
++
++ cpus_clear(mask);
++ if (!machine_has_topology)
++ return cpu_present_map;
++ mutex_lock(&smp_cpu_state_mutex);
++ while (core) {
++ if (cpu_isset(cpu, core->mask)) {
++ mask = core->mask;
++ break;
++ }
++ core = core->next;
++ }
++ mutex_unlock(&smp_cpu_state_mutex);
++ if (cpus_empty(mask))
++ mask = cpumask_of_cpu(cpu);
++ return mask;
++}
++
++static void add_cpus_to_core(struct tl_cpu *tl_cpu, struct core_info *core)
++{
++ unsigned int cpu;
++
++ for (cpu = find_first_bit(&tl_cpu->mask[0], CPU_BITS);
++ cpu < CPU_BITS;
++ cpu = find_next_bit(&tl_cpu->mask[0], CPU_BITS, cpu + 1))
++ {
++ unsigned int rcpu, lcpu;
++
++ rcpu = CPU_BITS - 1 - cpu + tl_cpu->origin;
++ for_each_present_cpu(lcpu) {
++ if (__cpu_logical_map[lcpu] == rcpu) {
++ cpu_set(lcpu, core->mask);
++ smp_cpu_polarization[lcpu] = tl_cpu->pp;
++ }
++ }
++ }
++}
++
++static void clear_cores(void)
++{
++ struct core_info *core = &core_info;
++
++ while (core) {
++ cpus_clear(core->mask);
++ core = core->next;
++ }
++}
++
++static union tl_entry *next_tle(union tl_entry *tle)
++{
++ if (tle->nl)
++ return (union tl_entry *)((struct tl_container *)tle + 1);
++ else
++ return (union tl_entry *)((struct tl_cpu *)tle + 1);
++}
++
++static void tl_to_cores(struct tl_info *info)
++{
++ union tl_entry *tle, *end;
++ struct core_info *core = &core_info;
++
++ mutex_lock(&smp_cpu_state_mutex);
++ clear_cores();
++ tle = info->tle;
++ end = (union tl_entry *)((unsigned long)info + info->length);
++ while (tle < end) {
++ switch (tle->nl) {
++ case 5:
++ case 4:
++ case 3:
++ case 2:
++ break;
++ case 1:
++ core = core->next;
++ break;
++ case 0:
++ add_cpus_to_core(&tle->cpu, core);
++ break;
++ default:
++ clear_cores();
++ machine_has_topology = 0;
++ return;
++ }
++ tle = next_tle(tle);
++ }
++ mutex_unlock(&smp_cpu_state_mutex);
++}
++
++static void topology_update_polarization_simple(void)
++{
++ int cpu;
++
++ mutex_lock(&smp_cpu_state_mutex);
++ for_each_present_cpu(cpu)
++ smp_cpu_polarization[cpu] = POLARIZATION_HRZ;
++ mutex_unlock(&smp_cpu_state_mutex);
++}
++
++static int ptf(unsigned long fc)
++{
++ int rc;
++
++ asm volatile(
++ " .insn rre,0xb9a20000,%1,%1\n"
++ " ipm %0\n"
++ " srl %0,28\n"
++ : "=d" (rc)
++ : "d" (fc) : "cc");
++ return rc;
++}
++
++int topology_set_cpu_management(int fc)
++{
++ int cpu;
++ int rc;
++
++ if (!machine_has_topology)
++ return -EOPNOTSUPP;
++ if (fc)
++ rc = ptf(PTF_VERTICAL);
++ else
++ rc = ptf(PTF_HORIZONTAL);
++ if (rc)
++ return -EBUSY;
++ for_each_present_cpu(cpu)
++ smp_cpu_polarization[cpu] = POLARIZATION_UNKNWN;
++ return rc;
++}
++
++void arch_update_cpu_topology(void)
++{
++ struct tl_info *info = tl_info;
++ struct sys_device *sysdev;
++ int cpu;
++
++ if (!machine_has_topology) {
++ topology_update_polarization_simple();
++ return;
++ }
++ stsi(info, 15, 1, 2);
++ tl_to_cores(info);
++ for_each_online_cpu(cpu) {
++ sysdev = get_cpu_sysdev(cpu);
++ kobject_uevent(&sysdev->kobj, KOBJ_CHANGE);
++ }
++}
++
++static void topology_work_fn(struct work_struct *work)
++{
++ arch_reinit_sched_domains();
++}
++
++void topology_schedule_update(void)
++{
++ schedule_work(&topology_work);
++}
++
++static void topology_timer_fn(unsigned long ignored)
++{
++ if (ptf(PTF_CHECK))
++ topology_schedule_update();
++ set_topology_timer();
++}
++
++static void set_topology_timer(void)
++{
++ topology_timer.function = topology_timer_fn;
++ topology_timer.data = 0;
++ topology_timer.expires = jiffies + 60 * HZ;
++ add_timer(&topology_timer);
++}
++
++static void topology_interrupt(__u16 code)
++{
++ schedule_work(&topology_work);
++}
++
++static int __init init_topology_update(void)
++{
++ int rc;
++
++ if (!machine_has_topology) {
++ topology_update_polarization_simple();
++ return 0;
++ }
++ init_timer_deferrable(&topology_timer);
++ if (machine_has_topology_irq) {
++ rc = register_external_interrupt(0x2005, topology_interrupt);
++ if (rc)
++ return rc;
++ ctl_set_bit(0, 8);
++ }
++ else
++ set_topology_timer();
++ return 0;
++}
++__initcall(init_topology_update);
++
++void __init s390_init_cpu_topology(void)
++{
++ unsigned long long facility_bits;
++ struct tl_info *info;
++ struct core_info *core;
++ int nr_cores;
++ int i;
++
++ if (stfle(&facility_bits, 1) <= 0)
++ return;
++ if (!(facility_bits & (1ULL << 52)) || !(facility_bits & (1ULL << 61)))
++ return;
++ machine_has_topology = 1;
++
++ if (facility_bits & (1ULL << 51))
++ machine_has_topology_irq = 1;
++
++ tl_info = alloc_bootmem_pages(PAGE_SIZE);
++ if (!tl_info)
++ goto error;
++ info = tl_info;
++ stsi(info, 15, 1, 2);
++
++ nr_cores = info->mag[NR_MAG - 2];
++ for (i = 0; i < info->mnest - 2; i++)
++ nr_cores *= info->mag[NR_MAG - 3 - i];
++
++ printk(KERN_INFO "CPU topology:");
++ for (i = 0; i < NR_MAG; i++)
++ printk(" %d", info->mag[i]);
++ printk(" / %d\n", info->mnest);
++
++ core = &core_info;
++ for (i = 0; i < nr_cores; i++) {
++ core->next = alloc_bootmem(sizeof(struct core_info));
++ core = core->next;
++ if (!core)
++ goto error;
++ }
++ return;
++error:
++ machine_has_topology = 0;
++ machine_has_topology_irq = 0;
++}
+diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
+index 60f728a..57b607b 100644
+--- a/arch/s390/kernel/traps.c
++++ b/arch/s390/kernel/traps.c
+@@ -42,11 +42,8 @@
+ #include <asm/s390_ext.h>
+ #include <asm/lowcore.h>
+ #include <asm/debug.h>
++#include "entry.h"
+
+-/* Called from entry.S only */
+-extern void handle_per_exception(struct pt_regs *regs);
+-
+-typedef void pgm_check_handler_t(struct pt_regs *, long);
+ pgm_check_handler_t *pgm_check_table[128];
+
+ #ifdef CONFIG_SYSCTL
+@@ -59,7 +56,6 @@ int sysctl_userprocess_debug = 0;
+
+ extern pgm_check_handler_t do_protection_exception;
+ extern pgm_check_handler_t do_dat_exception;
+-extern pgm_check_handler_t do_monitor_call;
+ extern pgm_check_handler_t do_asce_exception;
+
+ #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
+@@ -138,7 +134,6 @@ void show_trace(struct task_struct *task, unsigned long *stack)
+ else
+ __show_trace(sp, S390_lowcore.thread_info,
+ S390_lowcore.thread_info + THREAD_SIZE);
+- printk("\n");
+ if (!task)
+ task = current;
+ debug_show_held_locks(task);
+@@ -166,6 +161,15 @@ void show_stack(struct task_struct *task, unsigned long *sp)
+ show_trace(task, sp);
+ }
+
++#ifdef CONFIG_64BIT
++void show_last_breaking_event(struct pt_regs *regs)
++{
++ printk("Last Breaking-Event-Address:\n");
++ printk(" [<%016lx>] ", regs->args[0] & PSW_ADDR_INSN);
++ print_symbol("%s\n", regs->args[0] & PSW_ADDR_INSN);
++}
++#endif
++
+ /*
+ * The architecture-independent dump_stack generator
+ */
+@@ -739,6 +743,5 @@ void __init trap_init(void)
+ pgm_check_table[0x15] = &operand_exception;
+ pgm_check_table[0x1C] = &space_switch_exception;
+ pgm_check_table[0x1D] = &hfp_sqrt_exception;
+- pgm_check_table[0x40] = &do_monitor_call;
+ pfault_irq_init();
+ }
+diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c
+index 70f2a86..eae21a8 100644
+--- a/arch/s390/lib/delay.c
++++ b/arch/s390/lib/delay.c
+@@ -34,7 +34,7 @@ void __delay(unsigned long loops)
+ */
+ void __udelay(unsigned long usecs)
+ {
+- u64 end, time, jiffy_timer = 0;
++ u64 end, time, old_cc = 0;
+ unsigned long flags, cr0, mask, dummy;
+ int irq_context;
+
+@@ -43,8 +43,8 @@ void __udelay(unsigned long usecs)
+ local_bh_disable();
+ local_irq_save(flags);
+ if (raw_irqs_disabled_flags(flags)) {
+- jiffy_timer = S390_lowcore.jiffy_timer;
+- S390_lowcore.jiffy_timer = -1ULL - (4096 << 12);
++ old_cc = S390_lowcore.clock_comparator;
++ S390_lowcore.clock_comparator = -1ULL;
+ __ctl_store(cr0, 0, 0);
+ dummy = (cr0 & 0xffff00e0) | 0x00000800;
+ __ctl_load(dummy , 0, 0);
+@@ -55,8 +55,8 @@ void __udelay(unsigned long usecs)
+
+ end = get_clock() + ((u64) usecs << 12);
+ do {
+- time = end < S390_lowcore.jiffy_timer ?
+- end : S390_lowcore.jiffy_timer;
++ time = end < S390_lowcore.clock_comparator ?
++ end : S390_lowcore.clock_comparator;
+ set_clock_comparator(time);
+ trace_hardirqs_on();
+ __load_psw_mask(mask);
+@@ -65,10 +65,10 @@ void __udelay(unsigned long usecs)
+
+ if (raw_irqs_disabled_flags(flags)) {
+ __ctl_load(cr0, 0, 0);
+- S390_lowcore.jiffy_timer = jiffy_timer;
++ S390_lowcore.clock_comparator = old_cc;
+ }
+ if (!irq_context)
+ _local_bh_enable();
+- set_clock_comparator(S390_lowcore.jiffy_timer);
++ set_clock_comparator(S390_lowcore.clock_comparator);
+ local_irq_restore(flags);
+ }
+diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
+index 5efdfe9..d66215b 100644
+--- a/arch/s390/lib/uaccess_pt.c
++++ b/arch/s390/lib/uaccess_pt.c
+@@ -302,6 +302,10 @@ static size_t copy_in_user_pt(size_t n, void __user *to,
+ pte_t *pte_from, *pte_to;
+ int write_user;
+
++ if (segment_eq(get_fs(), KERNEL_DS)) {
++ memcpy((void __force *) to, (void __force *) from, n);
++ return 0;
++ }
+ done = 0;
+ retry:
+ spin_lock(&mm->page_table_lock);
+@@ -361,18 +365,10 @@ fault:
+ : "0" (-EFAULT), "d" (oparg), "a" (uaddr), \
+ "m" (*uaddr) : "cc" );
+
+-int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
++static int __futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
+ {
+ int oldval = 0, newval, ret;
+
+- spin_lock(¤t->mm->page_table_lock);
+- uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
+- if (!uaddr) {
+- spin_unlock(¤t->mm->page_table_lock);
+- return -EFAULT;
+- }
+- get_page(virt_to_page(uaddr));
+- spin_unlock(¤t->mm->page_table_lock);
+ switch (op) {
+ case FUTEX_OP_SET:
+ __futex_atomic_op("lr %2,%5\n",
+@@ -397,17 +393,17 @@ int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
+ default:
+ ret = -ENOSYS;
+ }
+- put_page(virt_to_page(uaddr));
+- *old = oldval;
++ if (ret == 0)
++ *old = oldval;
+ return ret;
+ }
+
+-int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
++int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
+ {
+ int ret;
+
+- if (!current->mm)
+- return -EFAULT;
++ if (segment_eq(get_fs(), KERNEL_DS))
++ return __futex_atomic_op_pt(op, uaddr, oparg, old);
+ spin_lock(¤t->mm->page_table_lock);
+ uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
+ if (!uaddr) {
+@@ -416,13 +412,40 @@ int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
+ }
+ get_page(virt_to_page(uaddr));
+ spin_unlock(¤t->mm->page_table_lock);
+- asm volatile(" cs %1,%4,0(%5)\n"
+- "0: lr %0,%1\n"
+- "1:\n"
+- EX_TABLE(0b,1b)
++ ret = __futex_atomic_op_pt(op, uaddr, oparg, old);
++ put_page(virt_to_page(uaddr));
++ return ret;
++}
++
++static int __futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
++{
++ int ret;
++
++ asm volatile("0: cs %1,%4,0(%5)\n"
++ "1: lr %0,%1\n"
++ "2:\n"
++ EX_TABLE(0b,2b) EX_TABLE(1b,2b)
+ : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
+ : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
+ : "cc", "memory" );
++ return ret;
++}
++
++int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
++{
++ int ret;
++
++ if (segment_eq(get_fs(), KERNEL_DS))
++ return __futex_atomic_cmpxchg_pt(uaddr, oldval, newval);
++ spin_lock(¤t->mm->page_table_lock);
++ uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
++ if (!uaddr) {
++ spin_unlock(¤t->mm->page_table_lock);
++ return -EFAULT;
++ }
++ get_page(virt_to_page(uaddr));
++ spin_unlock(¤t->mm->page_table_lock);
++ ret = __futex_atomic_cmpxchg_pt(uaddr, oldval, newval);
+ put_page(virt_to_page(uaddr));
+ return ret;
+ }
+diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c
+index 880b0eb..ed2af0a 100644
+--- a/arch/s390/mm/extmem.c
++++ b/arch/s390/mm/extmem.c
+@@ -289,22 +289,8 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
+
+ rc = add_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
+
+- switch (rc) {
+- case 0:
+- break;
+- case -ENOSPC:
+- PRINT_WARN("segment_load: not loading segment %s - overlaps "
+- "storage/segment\n", name);
+- goto out_free;
+- case -ERANGE:
+- PRINT_WARN("segment_load: not loading segment %s - exceeds "
+- "kernel mapping range\n", name);
+- goto out_free;
+- default:
+- PRINT_WARN("segment_load: not loading segment %s (rc: %d)\n",
+- name, rc);
++ if (rc)
+ goto out_free;
+- }
+
+ seg->res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+ if (seg->res == NULL) {
+@@ -582,8 +568,59 @@ out:
+ mutex_unlock(&dcss_lock);
+ }
+
++/*
++ * print appropriate error message for segment_load()/segment_type()
++ * return code
++ */
++void segment_warning(int rc, char *seg_name)
++{
++ switch (rc) {
++ case -ENOENT:
++ PRINT_WARN("cannot load/query segment %s, "
++ "does not exist\n", seg_name);
++ break;
++ case -ENOSYS:
++ PRINT_WARN("cannot load/query segment %s, "
++ "not running on VM\n", seg_name);
++ break;
++ case -EIO:
++ PRINT_WARN("cannot load/query segment %s, "
++ "hardware error\n", seg_name);
++ break;
++ case -ENOTSUPP:
++ PRINT_WARN("cannot load/query segment %s, "
++ "is a multi-part segment\n", seg_name);
++ break;
++ case -ENOSPC:
++ PRINT_WARN("cannot load/query segment %s, "
++ "overlaps with storage\n", seg_name);
++ break;
++ case -EBUSY:
++ PRINT_WARN("cannot load/query segment %s, "
++ "overlaps with already loaded dcss\n", seg_name);
++ break;
++ case -EPERM:
++ PRINT_WARN("cannot load/query segment %s, "
++ "already loaded in incompatible mode\n", seg_name);
++ break;
++ case -ENOMEM:
++ PRINT_WARN("cannot load/query segment %s, "
++ "out of memory\n", seg_name);
++ break;
++ case -ERANGE:
++ PRINT_WARN("cannot load/query segment %s, "
++ "exceeds kernel mapping range\n", seg_name);
++ break;
++ default:
++ PRINT_WARN("cannot load/query segment %s, "
++ "return value %i\n", seg_name, rc);
++ break;
++ }
++}
++
+ EXPORT_SYMBOL(segment_load);
+ EXPORT_SYMBOL(segment_unload);
+ EXPORT_SYMBOL(segment_save);
+ EXPORT_SYMBOL(segment_type);
+ EXPORT_SYMBOL(segment_modify_shared);
++EXPORT_SYMBOL(segment_warning);
+diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
+index ed13d42..2650f46 100644
+--- a/arch/s390/mm/fault.c
++++ b/arch/s390/mm/fault.c
+@@ -28,11 +28,11 @@
+ #include <linux/hardirq.h>
+ #include <linux/kprobes.h>
+ #include <linux/uaccess.h>
+-
+ #include <asm/system.h>
+ #include <asm/pgtable.h>
+ #include <asm/s390_ext.h>
+ #include <asm/mmu_context.h>
++#include "../kernel/entry.h"
+
+ #ifndef CONFIG_64BIT
+ #define __FAIL_ADDR_MASK 0x7ffff000
+@@ -50,8 +50,6 @@
+ extern int sysctl_userprocess_debug;
+ #endif
+
+-extern void die(const char *,struct pt_regs *,long);
+-
+ #ifdef CONFIG_KPROBES
+ static inline int notify_page_fault(struct pt_regs *regs, long err)
+ {
+@@ -245,11 +243,6 @@ static void do_sigbus(struct pt_regs *regs, unsigned long error_code,
+ }
+
+ #ifdef CONFIG_S390_EXEC_PROTECT
+-extern long sys_sigreturn(struct pt_regs *regs);
+-extern long sys_rt_sigreturn(struct pt_regs *regs);
+-extern long sys32_sigreturn(struct pt_regs *regs);
+-extern long sys32_rt_sigreturn(struct pt_regs *regs);
+-
+ static int signal_return(struct mm_struct *mm, struct pt_regs *regs,
+ unsigned long address, unsigned long error_code)
+ {
+@@ -270,15 +263,15 @@ static int signal_return(struct mm_struct *mm, struct pt_regs *regs,
+ #ifdef CONFIG_COMPAT
+ compat = test_tsk_thread_flag(current, TIF_31BIT);
+ if (compat && instruction == 0x0a77)
+- sys32_sigreturn(regs);
++ sys32_sigreturn();
+ else if (compat && instruction == 0x0aad)
+- sys32_rt_sigreturn(regs);
++ sys32_rt_sigreturn();
+ else
+ #endif
+ if (instruction == 0x0a77)
+- sys_sigreturn(regs);
++ sys_sigreturn();
+ else if (instruction == 0x0aad)
+- sys_rt_sigreturn(regs);
++ sys_rt_sigreturn();
+ else {
+ current->thread.prot_addr = address;
+ current->thread.trap_no = error_code;
+@@ -424,7 +417,7 @@ no_context:
+ }
+
+ void __kprobes do_protection_exception(struct pt_regs *regs,
+- unsigned long error_code)
++ long error_code)
+ {
+ /* Protection exception is supressing, decrement psw address. */
+ regs->psw.addr -= (error_code >> 16);
+@@ -440,7 +433,7 @@ void __kprobes do_protection_exception(struct pt_regs *regs,
+ do_exception(regs, 4, 1);
+ }
+
+-void __kprobes do_dat_exception(struct pt_regs *regs, unsigned long error_code)
++void __kprobes do_dat_exception(struct pt_regs *regs, long error_code)
+ {
+ do_exception(regs, error_code & 0xff, 0);
+ }
+diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
+index 8053245..202c952 100644
+--- a/arch/s390/mm/init.c
++++ b/arch/s390/mm/init.c
+@@ -50,7 +50,6 @@ void show_mem(void)
+
+ printk("Mem-info:\n");
+ show_free_areas();
+- printk("Free swap: %6ldkB\n", nr_swap_pages << (PAGE_SHIFT - 10));
+ i = max_mapnr;
+ while (i-- > 0) {
+ if (!pfn_valid(i))
+diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
+index 8d2cd1d..6a679c3 100644
+--- a/arch/sh/Kconfig
++++ b/arch/sh/Kconfig
+@@ -167,6 +167,12 @@ config CPU_SUBTYPE_SH7263
+ select CPU_SH2A
+ select CPU_HAS_FPU
+
++config CPU_SUBTYPE_MXG
++ bool "Support MX-G processor"
++ select CPU_SH2A
++ help
++ Select MX-G if running on an R8A03022BG part.
++
+ # SH-3 Processor Support
+
+ config CPU_SUBTYPE_SH7705
+@@ -270,6 +276,15 @@ config CPU_SUBTYPE_SH4_202
+
+ # SH-4A Processor Support
+
++config CPU_SUBTYPE_SH7723
++ bool "Support SH7723 processor"
++ select CPU_SH4A
++ select CPU_SHX2
++ select ARCH_SPARSEMEM_ENABLE
++ select SYS_SUPPORTS_NUMA
++ help
++ Select SH7723 if you have an SH-MobileR2 CPU.
++
+ config CPU_SUBTYPE_SH7763
+ bool "Support SH7763 processor"
+ select CPU_SH4A
+@@ -366,6 +381,14 @@ config SH_7619_SOLUTION_ENGINE
+ Select 7619 SolutionEngine if configuring for a Hitachi SH7619
+ evaluation board.
+
++config SH_7721_SOLUTION_ENGINE
++ bool "SolutionEngine7721"
++ select SOLUTION_ENGINE
++ depends on CPU_SUBTYPE_SH7721
++ help
++ Select 7721 SolutionEngine if configuring for a Hitachi SH7721
++ evaluation board.
++
+ config SH_7722_SOLUTION_ENGINE
+ bool "SolutionEngine7722"
+ select SOLUTION_ENGINE
+@@ -560,7 +583,7 @@ config SH_TMU
+ config SH_CMT
+ def_bool y
+ prompt "CMT timer support"
+- depends on CPU_SH2
++ depends on CPU_SH2 && !CPU_SUBTYPE_MXG
+ help
+ This enables the use of the CMT as the system timer.
+
+@@ -578,6 +601,7 @@ config SH_TIMER_IRQ
+ default "86" if CPU_SUBTYPE_SH7619
+ default "140" if CPU_SUBTYPE_SH7206
+ default "142" if CPU_SUBTYPE_SH7203
++ default "238" if CPU_SUBTYPE_MXG
+ default "16"
+
+ config SH_PCLK_FREQ
+@@ -585,10 +609,10 @@ config SH_PCLK_FREQ
+ default "27000000" if CPU_SUBTYPE_SH7343
+ default "31250000" if CPU_SUBTYPE_SH7619
+ default "32000000" if CPU_SUBTYPE_SH7722
+- default "33333333" if CPU_SUBTYPE_SH7770 || \
++ default "33333333" if CPU_SUBTYPE_SH7770 || CPU_SUBTYPE_SH7723 || \
+ CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7705 || \
+ CPU_SUBTYPE_SH7203 || CPU_SUBTYPE_SH7206 || \
+- CPU_SUBTYPE_SH7263
++ CPU_SUBTYPE_SH7263 || CPU_SUBTYPE_MXG
+ default "60000000" if CPU_SUBTYPE_SH7751 || CPU_SUBTYPE_SH7751R
+ default "66000000" if CPU_SUBTYPE_SH4_202
+ default "50000000"
+diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
+index 5dcb74b..d9d28f9 100644
+--- a/arch/sh/Kconfig.debug
++++ b/arch/sh/Kconfig.debug
+@@ -29,16 +29,17 @@ config EARLY_SCIF_CONSOLE
+ config EARLY_SCIF_CONSOLE_PORT
+ hex
+ depends on EARLY_SCIF_CONSOLE
+- default "0xffe00000" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7763
+- default "0xffe00000" if CPU_SUBTYPE_SH7722 || CPU_SUBTYPE_SH7366
+- default "0xffea0000" if CPU_SUBTYPE_SH7785
+- default "0xfffe8000" if CPU_SUBTYPE_SH7203
+- default "0xfffe9800" if CPU_SUBTYPE_SH7206 || CPU_SUBTYPE_SH7263
+- default "0xf8420000" if CPU_SUBTYPE_SH7619
+ default "0xa4400000" if CPU_SUBTYPE_SH7712 || CPU_SUBTYPE_SH7705
+ default "0xa4430000" if CPU_SUBTYPE_SH7720 || CPU_SUBTYPE_SH7721
++ default "0xf8420000" if CPU_SUBTYPE_SH7619
++ default "0xff804000" if CPU_SUBTYPE_MXG
+ default "0xffc30000" if CPU_SUBTYPE_SHX3
++ default "0xffe00000" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7763 || \
++ CPU_SUBTYPE_SH7722 || CPU_SUBTYPE_SH7366
+ default "0xffe80000" if CPU_SH4
++ default "0xffea0000" if CPU_SUBTYPE_SH7785
++ default "0xfffe8000" if CPU_SUBTYPE_SH7203
++ default "0xfffe9800" if CPU_SUBTYPE_SH7206 || CPU_SUBTYPE_SH7263
+ default "0x00000000"
+
+ config EARLY_PRINTK
+diff --git a/arch/sh/Makefile b/arch/sh/Makefile
+index cffc92b..bb06f83 100644
+--- a/arch/sh/Makefile
++++ b/arch/sh/Makefile
+@@ -107,6 +107,7 @@ machdir-$(CONFIG_SH_7722_SOLUTION_ENGINE) += se/7722
+ machdir-$(CONFIG_SH_7751_SOLUTION_ENGINE) += se/7751
+ machdir-$(CONFIG_SH_7780_SOLUTION_ENGINE) += se/7780
+ machdir-$(CONFIG_SH_7343_SOLUTION_ENGINE) += se/7343
++machdir-$(CONFIG_SH_7721_SOLUTION_ENGINE) += se/7721
+ machdir-$(CONFIG_SH_HP6XX) += hp6xx
+ machdir-$(CONFIG_SH_DREAMCAST) += dreamcast
+ machdir-$(CONFIG_SH_MPC1211) += mpc1211
+diff --git a/arch/sh/boards/renesas/migor/setup.c b/arch/sh/boards/renesas/migor/setup.c
+index 21ab8c8..00d52a2 100644
+--- a/arch/sh/boards/renesas/migor/setup.c
++++ b/arch/sh/boards/renesas/migor/setup.c
+@@ -10,8 +10,14 @@
+ #include <linux/init.h>
+ #include <linux/platform_device.h>
+ #include <linux/interrupt.h>
++#include <linux/input.h>
++#include <linux/mtd/physmap.h>
++#include <linux/mtd/nand.h>
++#include <linux/i2c.h>
+ #include <asm/machvec.h>
+ #include <asm/io.h>
++#include <asm/sh_keysc.h>
++#include <asm/migor.h>
+
+ /* Address IRQ Size Bus Description
+ * 0x00000000 64MB 16 NOR Flash (SP29PL256N)
+@@ -23,9 +29,9 @@
+
+ static struct resource smc91x_eth_resources[] = {
+ [0] = {
+- .name = "smc91x-regs" ,
+- .start = P2SEGADDR(0x10000300),
+- .end = P2SEGADDR(0x1000030f),
++ .name = "SMC91C111" ,
++ .start = 0x10000300,
++ .end = 0x1000030f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+@@ -40,19 +46,202 @@ static struct platform_device smc91x_eth_device = {
+ .resource = smc91x_eth_resources,
+ };
+
++static struct sh_keysc_info sh_keysc_info = {
++ .mode = SH_KEYSC_MODE_2, /* KEYOUT0->4, KEYIN1->5 */
++ .scan_timing = 3,
++ .delay = 5,
++ .keycodes = {
++ 0, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_ENTER,
++ 0, KEY_F, KEY_C, KEY_D, KEY_H, KEY_1,
++ 0, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6,
++ 0, KEY_7, KEY_8, KEY_9, KEY_S, KEY_0,
++ 0, KEY_P, KEY_STOP, KEY_REWIND, KEY_PLAY, KEY_FASTFORWARD,
++ },
++};
++
++static struct resource sh_keysc_resources[] = {
++ [0] = {
++ .start = 0x044b0000,
++ .end = 0x044b000f,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = 79,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device sh_keysc_device = {
++ .name = "sh_keysc",
++ .num_resources = ARRAY_SIZE(sh_keysc_resources),
++ .resource = sh_keysc_resources,
++ .dev = {
++ .platform_data = &sh_keysc_info,
++ },
++};
++
++static struct mtd_partition migor_nor_flash_partitions[] =
++{
++ {
++ .name = "uboot",
++ .offset = 0,
++ .size = (1 * 1024 * 1024),
++ .mask_flags = MTD_WRITEABLE, /* Read-only */
++ },
++ {
++ .name = "rootfs",
++ .offset = MTDPART_OFS_APPEND,
++ .size = (15 * 1024 * 1024),
++ },
++ {
++ .name = "other",
++ .offset = MTDPART_OFS_APPEND,
++ .size = MTDPART_SIZ_FULL,
++ },
++};
++
++static struct physmap_flash_data migor_nor_flash_data = {
++ .width = 2,
++ .parts = migor_nor_flash_partitions,
++ .nr_parts = ARRAY_SIZE(migor_nor_flash_partitions),
++};
++
++static struct resource migor_nor_flash_resources[] = {
++ [0] = {
++ .name = "NOR Flash",
++ .start = 0x00000000,
++ .end = 0x03ffffff,
++ .flags = IORESOURCE_MEM,
++ }
++};
++
++static struct platform_device migor_nor_flash_device = {
++ .name = "physmap-flash",
++ .resource = migor_nor_flash_resources,
++ .num_resources = ARRAY_SIZE(migor_nor_flash_resources),
++ .dev = {
++ .platform_data = &migor_nor_flash_data,
++ },
++};
++
++static struct mtd_partition migor_nand_flash_partitions[] = {
++ {
++ .name = "nanddata1",
++ .offset = 0x0,
++ .size = 512 * 1024 * 1024,
++ },
++ {
++ .name = "nanddata2",
++ .offset = MTDPART_OFS_APPEND,
++ .size = 512 * 1024 * 1024,
++ },
++};
++
++static void migor_nand_flash_cmd_ctl(struct mtd_info *mtd, int cmd,
++ unsigned int ctrl)
++{
++ struct nand_chip *chip = mtd->priv;
++
++ if (cmd == NAND_CMD_NONE)
++ return;
++
++ if (ctrl & NAND_CLE)
++ writeb(cmd, chip->IO_ADDR_W + 0x00400000);
++ else if (ctrl & NAND_ALE)
++ writeb(cmd, chip->IO_ADDR_W + 0x00800000);
++ else
++ writeb(cmd, chip->IO_ADDR_W);
++}
++
++static int migor_nand_flash_ready(struct mtd_info *mtd)
++{
++ return ctrl_inb(PORT_PADR) & 0x02; /* PTA1 */
++}
++
++struct platform_nand_data migor_nand_flash_data = {
++ .chip = {
++ .nr_chips = 1,
++ .partitions = migor_nand_flash_partitions,
++ .nr_partitions = ARRAY_SIZE(migor_nand_flash_partitions),
++ .chip_delay = 20,
++ .part_probe_types = (const char *[]) { "cmdlinepart", NULL },
++ },
++ .ctrl = {
++ .dev_ready = migor_nand_flash_ready,
++ .cmd_ctrl = migor_nand_flash_cmd_ctl,
++ },
++};
++
++static struct resource migor_nand_flash_resources[] = {
++ [0] = {
++ .name = "NAND Flash",
++ .start = 0x18000000,
++ .end = 0x18ffffff,
++ .flags = IORESOURCE_MEM,
++ },
++};
++
++static struct platform_device migor_nand_flash_device = {
++ .name = "gen_nand",
++ .resource = migor_nand_flash_resources,
++ .num_resources = ARRAY_SIZE(migor_nand_flash_resources),
++ .dev = {
++ .platform_data = &migor_nand_flash_data,
++ }
++};
++
+ static struct platform_device *migor_devices[] __initdata = {
+ &smc91x_eth_device,
++ &sh_keysc_device,
++ &migor_nor_flash_device,
++ &migor_nand_flash_device,
++};
++
++static struct i2c_board_info __initdata migor_i2c_devices[] = {
++ {
++ I2C_BOARD_INFO("rtc-rs5c372", 0x32),
++ .type = "rs5c372b",
++ },
++ {
++ I2C_BOARD_INFO("migor_ts", 0x51),
++ .irq = 38, /* IRQ6 */
++ },
+ };
+
+ static int __init migor_devices_setup(void)
+ {
++ i2c_register_board_info(0, migor_i2c_devices,
++ ARRAY_SIZE(migor_i2c_devices));
++
+ return platform_add_devices(migor_devices, ARRAY_SIZE(migor_devices));
+ }
+ __initcall(migor_devices_setup);
+
+ static void __init migor_setup(char **cmdline_p)
+ {
+- ctrl_outw(0x1000, 0xa4050110); /* Enable IRQ0 in PJCR */
++ /* SMC91C111 - Enable IRQ0 */
++ ctrl_outw(ctrl_inw(PORT_PJCR) & ~0x0003, PORT_PJCR);
++
++ /* KEYSC */
++ ctrl_outw(ctrl_inw(PORT_PYCR) & ~0x0fff, PORT_PYCR);
++ ctrl_outw(ctrl_inw(PORT_PZCR) & ~0x0ff0, PORT_PZCR);
++ ctrl_outw(ctrl_inw(PORT_PSELA) & ~0x4100, PORT_PSELA);
++ ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x4000, PORT_HIZCRA);
++ ctrl_outw(ctrl_inw(PORT_HIZCRC) & ~0xc000, PORT_HIZCRC);
++ ctrl_outl(ctrl_inl(MSTPCR2) & ~0x00004000, MSTPCR2);
++
++ /* NAND Flash */
++ ctrl_outw(ctrl_inw(PORT_PXCR) & 0x0fff, PORT_PXCR);
++ ctrl_outl((ctrl_inl(BSC_CS6ABCR) & ~0x00000600) | 0x00000200,
++ BSC_CS6ABCR);
++
++ /* I2C */
++ ctrl_outl(ctrl_inl(MSTPCR1) & ~0x00000200, MSTPCR1);
++
++ /* Touch Panel - Enable IRQ6 */
++ ctrl_outw(ctrl_inw(PORT_PZCR) & ~0xc, PORT_PZCR);
++ ctrl_outw((ctrl_inw(PORT_PSELA) | 0x8000), PORT_PSELA);
++ ctrl_outw((ctrl_inw(PORT_HIZCRC) & ~0x4000), PORT_HIZCRC);
+ }
+
+ static struct sh_machine_vector mv_migor __initmv = {
+diff --git a/arch/sh/boards/renesas/r7780rp/irq-r7780mp.c b/arch/sh/boards/renesas/r7780rp/irq-r7780mp.c
+index 1f8f073..68f0ad1 100644
+--- a/arch/sh/boards/renesas/r7780rp/irq-r7780mp.c
++++ b/arch/sh/boards/renesas/r7780rp/irq-r7780mp.c
+@@ -18,31 +18,44 @@ enum {
+ UNUSED = 0,
+
+ /* board specific interrupt sources */
+- AX88796, /* Ethernet controller */
+- CF, /* Compact Flash */
+- PSW, /* Push Switch */
+- EXT1, /* EXT1n IRQ */
+- EXT4, /* EXT4n IRQ */
++ CF, /* Compact Flash */
++ TP, /* Touch panel */
++ SCIF1, /* FPGA SCIF1 */
++ SCIF0, /* FPGA SCIF0 */
++ SMBUS, /* SMBUS */
++ RTC, /* RTC Alarm */
++ AX88796, /* Ethernet controller */
++ PSW, /* Push Switch */
++
++ /* external bus connector */
++ EXT1, EXT2, EXT4, EXT5, EXT6,
+ };
+
+ static struct intc_vect vectors[] __initdata = {
+ INTC_IRQ(CF, IRQ_CF),
+- INTC_IRQ(PSW, IRQ_PSW),
++ INTC_IRQ(TP, IRQ_TP),
++ INTC_IRQ(SCIF1, IRQ_SCIF1),
++ INTC_IRQ(SCIF0, IRQ_SCIF0),
++ INTC_IRQ(SMBUS, IRQ_SMBUS),
++ INTC_IRQ(RTC, IRQ_RTC),
+ INTC_IRQ(AX88796, IRQ_AX88796),
+- INTC_IRQ(EXT1, IRQ_EXT1),
+- INTC_IRQ(EXT4, IRQ_EXT4),
++ INTC_IRQ(PSW, IRQ_PSW),
++
++ INTC_IRQ(EXT1, IRQ_EXT1), INTC_IRQ(EXT2, IRQ_EXT2),
++ INTC_IRQ(EXT4, IRQ_EXT4), INTC_IRQ(EXT5, IRQ_EXT5),
++ INTC_IRQ(EXT6, IRQ_EXT6),
+ };
+
+ static struct intc_mask_reg mask_registers[] __initdata = {
+ { 0xa4000000, 0, 16, /* IRLMSK */
+- { 0, 0, 0, 0, CF, 0, 0, 0,
+- 0, 0, 0, EXT4, 0, EXT1, PSW, AX88796 } },
++ { SCIF0, SCIF1, RTC, 0, CF, 0, TP, SMBUS,
++ 0, EXT6, EXT5, EXT4, EXT2, EXT1, PSW, AX88796 } },
+ };
+
+ static unsigned char irl2irq[HL_NR_IRL] __initdata = {
+- 0, IRQ_CF, 0, 0,
+- 0, 0, 0, 0,
+- 0, IRQ_EXT4, 0, IRQ_EXT1,
++ 0, IRQ_CF, IRQ_TP, IRQ_SCIF1,
++ IRQ_SCIF0, IRQ_SMBUS, IRQ_RTC, IRQ_EXT6,
++ IRQ_EXT5, IRQ_EXT4, IRQ_EXT2, IRQ_EXT1,
+ 0, IRQ_AX88796, IRQ_PSW,
+ };
+
+diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c
+index 2f68bea..a5c5e92 100644
+--- a/arch/sh/boards/renesas/r7780rp/setup.c
++++ b/arch/sh/boards/renesas/r7780rp/setup.c
+@@ -4,7 +4,7 @@
+ * Renesas Solutions Highlander Support.
+ *
+ * Copyright (C) 2002 Atom Create Engineering Co., Ltd.
+- * Copyright (C) 2005 - 2007 Paul Mundt
++ * Copyright (C) 2005 - 2008 Paul Mundt
+ *
+ * This contains support for the R7780RP-1, R7780MP, and R7785RP
+ * Highlander modules.
+@@ -17,6 +17,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/ata_platform.h>
+ #include <linux/types.h>
++#include <linux/i2c.h>
+ #include <net/ax88796.h>
+ #include <asm/machvec.h>
+ #include <asm/r7780rp.h>
+@@ -176,11 +177,38 @@ static struct platform_device ax88796_device = {
+ .resource = ax88796_resources,
+ };
+
++static struct resource smbus_resources[] = {
++ [0] = {
++ .start = PA_SMCR,
++ .end = PA_SMCR + 0x100 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_SMBUS,
++ .end = IRQ_SMBUS,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device smbus_device = {
++ .name = "i2c-highlander",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(smbus_resources),
++ .resource = smbus_resources,
++};
++
++static struct i2c_board_info __initdata highlander_i2c_devices[] = {
++ {
++ I2C_BOARD_INFO("rtc-rs5c372", 0x32),
++ .type = "r2025sd",
++ },
++};
+
+ static struct platform_device *r7780rp_devices[] __initdata = {
+ &r8a66597_usb_host_device,
+ &m66592_usb_peripheral_device,
+ &heartbeat_device,
++ &smbus_device,
+ #ifndef CONFIG_SH_R7780RP
+ &ax88796_device,
+ #endif
+@@ -199,12 +227,20 @@ static struct trapped_io cf_trapped_io = {
+
+ static int __init r7780rp_devices_setup(void)
+ {
++ int ret = 0;
++
+ #ifndef CONFIG_SH_R7780RP
+ if (register_trapped_io(&cf_trapped_io) == 0)
+- platform_device_register(&cf_ide_device);
++ ret |= platform_device_register(&cf_ide_device);
+ #endif
+- return platform_add_devices(r7780rp_devices,
++
++ ret |= platform_add_devices(r7780rp_devices,
+ ARRAY_SIZE(r7780rp_devices));
++
++ ret |= i2c_register_board_info(0, highlander_i2c_devices,
++ ARRAY_SIZE(highlander_i2c_devices));
++
++ return ret;
+ }
+ device_initcall(r7780rp_devices_setup);
+
+diff --git a/arch/sh/boards/se/7721/Makefile b/arch/sh/boards/se/7721/Makefile
+new file mode 100644
+index 0000000..7f09030
+--- /dev/null
++++ b/arch/sh/boards/se/7721/Makefile
+@@ -0,0 +1 @@
++obj-y := setup.o irq.o
+diff --git a/arch/sh/boards/se/7721/irq.c b/arch/sh/boards/se/7721/irq.c
+new file mode 100644
+index 0000000..c4fdd62
+--- /dev/null
++++ b/arch/sh/boards/se/7721/irq.c
+@@ -0,0 +1,45 @@
++/*
++ * linux/arch/sh/boards/se/7721/irq.c
++ *
++ * Copyright (C) 2008 Renesas Solutions Corp.
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ */
++#include <linux/init.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <asm/se7721.h>
++
++enum {
++ UNUSED = 0,
++
++ /* board specific interrupt sources */
++ MRSHPC,
++};
++
++static struct intc_vect vectors[] __initdata = {
++ INTC_IRQ(MRSHPC, MRSHPC_IRQ0),
++};
++
++static struct intc_prio_reg prio_registers[] __initdata = {
++ { FPGA_ILSR6, 0, 8, 4, /* IRLMSK */
++ { 0, MRSHPC } },
++};
++
++static DECLARE_INTC_DESC(intc_desc, "SE7721", vectors,
++ NULL, NULL, prio_registers, NULL);
++
++/*
++ * Initialize IRQ setting
++ */
++void __init init_se7721_IRQ(void)
++{
++ /* PPCR */
++ ctrl_outw(ctrl_inw(0xa4050118) & ~0x00ff, 0xa4050118);
++
++ register_intc_controller(&intc_desc);
++ intc_set_priority(MRSHPC_IRQ0, 0xf - MRSHPC_IRQ0);
++}
+diff --git a/arch/sh/boards/se/7721/setup.c b/arch/sh/boards/se/7721/setup.c
+new file mode 100644
+index 0000000..1be3e92
+--- /dev/null
++++ b/arch/sh/boards/se/7721/setup.c
+@@ -0,0 +1,99 @@
++/*
++ * linux/arch/sh/boards/se/7721/setup.c
++ *
++ * Copyright (C) 2008 Renesas Solutions Corp.
++ *
++ * Hitachi UL SolutionEngine 7721 Support.
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ */
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <asm/machvec.h>
++#include <asm/se7721.h>
++#include <asm/io.h>
++#include <asm/heartbeat.h>
++
++static unsigned char heartbeat_bit_pos[] = { 8, 9, 10, 11, 12, 13, 14, 15 };
++
++static struct heartbeat_data heartbeat_data = {
++ .bit_pos = heartbeat_bit_pos,
++ .nr_bits = ARRAY_SIZE(heartbeat_bit_pos),
++ .regsize = 16,
++};
++
++static struct resource heartbeat_resources[] = {
++ [0] = {
++ .start = PA_LED,
++ .end = PA_LED,
++ .flags = IORESOURCE_MEM,
++ },
++};
++
++static struct platform_device heartbeat_device = {
++ .name = "heartbeat",
++ .id = -1,
++ .dev = {
++ .platform_data = &heartbeat_data,
++ },
++ .num_resources = ARRAY_SIZE(heartbeat_resources),
++ .resource = heartbeat_resources,
++};
++
++static struct resource cf_ide_resources[] = {
++ [0] = {
++ .start = PA_MRSHPC_IO + 0x1f0,
++ .end = PA_MRSHPC_IO + 0x1f0 + 8 ,
++ .flags = IORESOURCE_IO,
++ },
++ [1] = {
++ .start = PA_MRSHPC_IO + 0x1f0 + 0x206,
++ .end = PA_MRSHPC_IO + 0x1f0 + 8 + 0x206 + 8,
++ .flags = IORESOURCE_IO,
++ },
++ [2] = {
++ .start = MRSHPC_IRQ0,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device cf_ide_device = {
++ .name = "pata_platform",
++ .id = -1,
++ .num_resources = ARRAY_SIZE(cf_ide_resources),
++ .resource = cf_ide_resources,
++};
++
++static struct platform_device *se7721_devices[] __initdata = {
++ &cf_ide_device,
++ &heartbeat_device
++};
++
++static int __init se7721_devices_setup(void)
++{
++ return platform_add_devices(se7721_devices,
++ ARRAY_SIZE(se7721_devices));
++}
++device_initcall(se7721_devices_setup);
++
++static void __init se7721_setup(char **cmdline_p)
++{
++ /* for USB */
++ ctrl_outw(0x0000, 0xA405010C); /* PGCR */
++ ctrl_outw(0x0000, 0xA405010E); /* PHCR */
++ ctrl_outw(0x00AA, 0xA4050118); /* PPCR */
++ ctrl_outw(0x0000, 0xA4050124); /* PSELA */
++}
++
++/*
++ * The Machine Vector
++ */
++struct sh_machine_vector mv_se7721 __initmv = {
++ .mv_name = "Solution Engine 7721",
++ .mv_setup = se7721_setup,
++ .mv_nr_irqs = 109,
++ .mv_init_irq = init_se7721_IRQ,
++};
+diff --git a/arch/sh/boards/se/7722/setup.c b/arch/sh/boards/se/7722/setup.c
+index b1a3d9d..33f6ee7 100644
+--- a/arch/sh/boards/se/7722/setup.c
++++ b/arch/sh/boards/se/7722/setup.c
+@@ -13,10 +13,12 @@
+ #include <linux/init.h>
+ #include <linux/platform_device.h>
+ #include <linux/ata_platform.h>
++#include <linux/input.h>
+ #include <asm/machvec.h>
+ #include <asm/se7722.h>
+ #include <asm/io.h>
+ #include <asm/heartbeat.h>
++#include <asm/sh_keysc.h>
+
+ /* Heartbeat */
+ static struct heartbeat_data heartbeat_data = {
+@@ -92,10 +94,47 @@ static struct platform_device cf_ide_device = {
+ .resource = cf_ide_resources,
+ };
+
++static struct sh_keysc_info sh_keysc_info = {
++ .mode = SH_KEYSC_MODE_1, /* KEYOUT0->5, KEYIN0->4 */
++ .scan_timing = 3,
++ .delay = 5,
++ .keycodes = { /* SW1 -> SW30 */
++ KEY_A, KEY_B, KEY_C, KEY_D, KEY_E,
++ KEY_F, KEY_G, KEY_H, KEY_I, KEY_J,
++ KEY_K, KEY_L, KEY_M, KEY_N, KEY_O,
++ KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T,
++ KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y,
++ KEY_Z,
++ KEY_HOME, KEY_SLEEP, KEY_WAKEUP, KEY_COFFEE, /* life */
++ },
++};
++
++static struct resource sh_keysc_resources[] = {
++ [0] = {
++ .start = 0x044b0000,
++ .end = 0x044b000f,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = 79,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device sh_keysc_device = {
++ .name = "sh_keysc",
++ .num_resources = ARRAY_SIZE(sh_keysc_resources),
++ .resource = sh_keysc_resources,
++ .dev = {
++ .platform_data = &sh_keysc_info,
++ },
++};
++
+ static struct platform_device *se7722_devices[] __initdata = {
+ &heartbeat_device,
+ &smc91x_eth_device,
+ &cf_ide_device,
++ &sh_keysc_device,
+ };
+
+ static int __init se7722_devices_setup(void)
+@@ -136,6 +175,8 @@ static void __init se7722_setup(char **cmdline_p)
+ ctrl_outw(0x0A10, PORT_PSELA); /* BS,SHHID2 */
+ ctrl_outw(0x0000, PORT_PYCR);
+ ctrl_outw(0x0000, PORT_PZCR);
++ ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x4000, PORT_HIZCRA);
++ ctrl_outw(ctrl_inw(PORT_HIZCRC) & ~0xc000, PORT_HIZCRC);
+ }
+
+ /*
+diff --git a/arch/sh/configs/se7721_defconfig b/arch/sh/configs/se7721_defconfig
+new file mode 100644
+index 0000000..f3d4ca0
+--- /dev/null
++++ b/arch/sh/configs/se7721_defconfig
+@@ -0,0 +1,1085 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.25-rc5
++# Fri Mar 21 12:05:31 2008
++#
++CONFIG_SUPERH=y
++CONFIG_SUPERH32=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_ARCH_NO_VIRT_TO_BUS=y
++CONFIG_ARCH_SUPPORTS_AOUT=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++# CONFIG_LOCALVERSION_AUTO is not set
++# CONFIG_SWAP is not set
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_BSD_PROCESS_ACCT=y
++# CONFIG_BSD_PROCESS_ACCT_V3 is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_RT_GROUP_SCHED is not set
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++# CONFIG_BLK_DEV_INITRD is not set
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_EMBEDDED=y
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++# CONFIG_BUG is not set
++CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
++# CONFIG_BASE_FULL is not set
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++# CONFIG_SHMEM is not set
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_HAVE_KPROBES is not set
++# CONFIG_HAVE_KRETPROBES is not set
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++CONFIG_TINY_SHMEM=y
++CONFIG_BASE_SMALL=1
++CONFIG_MODULES=y
++# CONFIG_MODULE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++# CONFIG_IOSCHED_DEADLINE is not set
++# CONFIG_IOSCHED_CFQ is not set
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++CONFIG_DEFAULT_NOOP=y
++CONFIG_DEFAULT_IOSCHED="noop"
++CONFIG_CLASSIC_RCU=y
++
++#
++# System type
++#
++CONFIG_CPU_SH3=y
++# CONFIG_CPU_SUBTYPE_SH7619 is not set
++# CONFIG_CPU_SUBTYPE_SH7203 is not set
++# CONFIG_CPU_SUBTYPE_SH7206 is not set
++# CONFIG_CPU_SUBTYPE_SH7263 is not set
++# CONFIG_CPU_SUBTYPE_MXG is not set
++# CONFIG_CPU_SUBTYPE_SH7705 is not set
++# CONFIG_CPU_SUBTYPE_SH7706 is not set
++# CONFIG_CPU_SUBTYPE_SH7707 is not set
++# CONFIG_CPU_SUBTYPE_SH7708 is not set
++# CONFIG_CPU_SUBTYPE_SH7709 is not set
++# CONFIG_CPU_SUBTYPE_SH7710 is not set
++# CONFIG_CPU_SUBTYPE_SH7712 is not set
++# CONFIG_CPU_SUBTYPE_SH7720 is not set
++CONFIG_CPU_SUBTYPE_SH7721=y
++# CONFIG_CPU_SUBTYPE_SH7750 is not set
++# CONFIG_CPU_SUBTYPE_SH7091 is not set
++# CONFIG_CPU_SUBTYPE_SH7750R is not set
++# CONFIG_CPU_SUBTYPE_SH7750S is not set
++# CONFIG_CPU_SUBTYPE_SH7751 is not set
++# CONFIG_CPU_SUBTYPE_SH7751R is not set
++# CONFIG_CPU_SUBTYPE_SH7760 is not set
++# CONFIG_CPU_SUBTYPE_SH4_202 is not set
++# CONFIG_CPU_SUBTYPE_SH7763 is not set
++# CONFIG_CPU_SUBTYPE_SH7770 is not set
++# CONFIG_CPU_SUBTYPE_SH7780 is not set
++# CONFIG_CPU_SUBTYPE_SH7785 is not set
++# CONFIG_CPU_SUBTYPE_SHX3 is not set
++# CONFIG_CPU_SUBTYPE_SH7343 is not set
++# CONFIG_CPU_SUBTYPE_SH7722 is not set
++# CONFIG_CPU_SUBTYPE_SH7366 is not set
++# CONFIG_CPU_SUBTYPE_SH5_101 is not set
++# CONFIG_CPU_SUBTYPE_SH5_103 is not set
++
++#
++# Memory management options
++#
++CONFIG_QUICKLIST=y
++CONFIG_MMU=y
++CONFIG_PAGE_OFFSET=0x80000000
++CONFIG_MEMORY_START=0x0c000000
++CONFIG_MEMORY_SIZE=0x02000000
++CONFIG_29BIT=y
++CONFIG_VSYSCALL=y
++CONFIG_ARCH_FLATMEM_ENABLE=y
++CONFIG_ARCH_SPARSEMEM_ENABLE=y
++CONFIG_ARCH_SPARSEMEM_DEFAULT=y
++CONFIG_MAX_ACTIVE_REGIONS=1
++CONFIG_ARCH_POPULATES_NODE_MAP=y
++CONFIG_ARCH_SELECT_MEMORY_MODEL=y
++CONFIG_PAGE_SIZE_4KB=y
++# CONFIG_PAGE_SIZE_8KB is not set
++# CONFIG_PAGE_SIZE_64KB is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_SPARSEMEM_STATIC=y
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=0
++CONFIG_NR_QUICK=2
++
++#
++# Cache configuration
++#
++# CONFIG_SH_DIRECT_MAPPED is not set
++CONFIG_CACHE_WRITEBACK=y
++# CONFIG_CACHE_WRITETHROUGH is not set
++# CONFIG_CACHE_OFF is not set
++
++#
++# Processor features
++#
++CONFIG_CPU_LITTLE_ENDIAN=y
++# CONFIG_CPU_BIG_ENDIAN is not set
++# CONFIG_SH_FPU_EMU is not set
++# CONFIG_SH_DSP is not set
++# CONFIG_SH_ADC is not set
++CONFIG_CPU_HAS_INTEVT=y
++CONFIG_CPU_HAS_SR_RB=y
++CONFIG_CPU_HAS_DSP=y
++
++#
++# Board support
++#
++CONFIG_SOLUTION_ENGINE=y
++CONFIG_SH_7721_SOLUTION_ENGINE=y
++
++#
++# Timer and clock configuration
++#
++CONFIG_SH_TMU=y
++CONFIG_SH_TIMER_IRQ=16
++CONFIG_SH_PCLK_FREQ=33333333
++# CONFIG_TICK_ONESHOT is not set
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++
++#
++# CPU Frequency scaling
++#
++# CONFIG_CPU_FREQ is not set
++
++#
++# DMA support
++#
++# CONFIG_SH_DMA is not set
++
++#
++# Companion Chips
++#
++
++#
++# Additional SuperH Device Drivers
++#
++CONFIG_HEARTBEAT=y
++# CONFIG_PUSH_SWITCH is not set
++
++#
++# Kernel features
++#
++# CONFIG_HZ_100 is not set
++CONFIG_HZ_250=y
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=250
++# CONFIG_SCHED_HRTICK is not set
++# CONFIG_KEXEC is not set
++# CONFIG_CRASH_DUMP is not set
++# CONFIG_PREEMPT_NONE is not set
++CONFIG_PREEMPT_VOLUNTARY=y
++# CONFIG_PREEMPT is not set
++CONFIG_GUSA=y
++# CONFIG_GUSA_RB is not set
++
++#
++# Boot options
++#
++CONFIG_ZERO_PAGE_OFFSET=0x00001000
++CONFIG_BOOT_LINK_OFFSET=0x00800000
++CONFIG_CMDLINE_BOOL=y
++CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda2"
++
++#
++# Bus options
++#
++CONFIG_CF_ENABLER=y
++# CONFIG_CF_AREA5 is not set
++CONFIG_CF_AREA6=y
++CONFIG_CF_BASE_ADDR=0xb8000000
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Executable file formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++CONFIG_NET_KEY=y
++# CONFIG_NET_KEY_MIGRATE is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++CONFIG_IP_ADVANCED_ROUTER=y
++CONFIG_ASK_IP_FIB_HASH=y
++# CONFIG_IP_FIB_TRIE is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_MULTIPLE_TABLES=y
++CONFIG_IP_ROUTE_MULTIPATH=y
++CONFIG_IP_ROUTE_VERBOSE=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++CONFIG_IP_MROUTE=y
++CONFIG_IP_PIMSM_V1=y
++CONFIG_IP_PIMSM_V2=y
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++CONFIG_INET_AH=y
++CONFIG_INET_ESP=y
++CONFIG_INET_IPCOMP=y
++CONFIG_INET_XFRM_TUNNEL=y
++CONFIG_INET_TUNNEL=y
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++# CONFIG_INET_DIAG is not set
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++CONFIG_NET_SCHED=y
++
++#
++# Queueing/Scheduling
++#
++CONFIG_NET_SCH_CBQ=y
++CONFIG_NET_SCH_HTB=y
++CONFIG_NET_SCH_HFSC=y
++CONFIG_NET_SCH_PRIO=y
++# CONFIG_NET_SCH_RR is not set
++CONFIG_NET_SCH_RED=y
++CONFIG_NET_SCH_SFQ=y
++CONFIG_NET_SCH_TEQL=y
++CONFIG_NET_SCH_TBF=y
++CONFIG_NET_SCH_GRED=y
++CONFIG_NET_SCH_DSMARK=y
++CONFIG_NET_SCH_NETEM=y
++
++#
++# Classification
++#
++CONFIG_NET_CLS=y
++# CONFIG_NET_CLS_BASIC is not set
++CONFIG_NET_CLS_TCINDEX=y
++CONFIG_NET_CLS_ROUTE4=y
++CONFIG_NET_CLS_ROUTE=y
++CONFIG_NET_CLS_FW=y
++# CONFIG_NET_CLS_U32 is not set
++# CONFIG_NET_CLS_RSVP is not set
++# CONFIG_NET_CLS_RSVP6 is not set
++# CONFIG_NET_CLS_FLOW is not set
++# CONFIG_NET_EMATCH is not set
++# CONFIG_NET_CLS_ACT is not set
++CONFIG_NET_CLS_IND=y
++CONFIG_NET_SCH_FIFO=y
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++CONFIG_FIB_RULES=y
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_CFI_INTELEXT is not set
++CONFIG_MTD_CFI_AMDSTD=y
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++# CONFIG_BLK_DEV_RAM is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++CONFIG_SCSI_MULTI_LUN=y
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++# CONFIG_SCSI_LOWLEVEL is not set
++CONFIG_ATA=y
++# CONFIG_ATA_NONSTANDARD is not set
++# CONFIG_SATA_MV is not set
++CONFIG_PATA_PLATFORM=y
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_NET_ETHERNET is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_E1000E_ENABLED is not set
++CONFIG_NETDEV_10000=y
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ATKBD is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++# CONFIG_KEYBOARD_SH_KEYSC is not set
++CONFIG_INPUT_MOUSE=y
++# CONFIG_MOUSE_PS2 is not set
++# CONFIG_MOUSE_SERIAL is not set
++# CONFIG_MOUSE_APPLETOUCH is not set
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_SH_SCI=y
++CONFIG_SERIAL_SH_SCI_NR_UARTS=2
++CONFIG_SERIAL_SH_SCI_CONSOLE=y
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++# CONFIG_LEGACY_PTYS is not set
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++CONFIG_THERMAL=y
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++# CONFIG_USB_HIDINPUT_POWERBOOK is not set
++# CONFIG_HID_FF is not set
++# CONFIG_USB_HIDDEV is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
++
++#
++# Miscellaneous USB options
++#
++# CONFIG_USB_DEVICEFS is not set
++CONFIG_USB_DEVICE_CLASS=y
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_ONETOUCH is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=y
++
++#
++# LED drivers
++#
++
++#
++# LED Triggers
++#
++CONFIG_LEDS_TRIGGERS=y
++# CONFIG_LEDS_TRIGGER_TIMER is not set
++# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
++# CONFIG_RTC_CLASS is not set
++
++#
++# Userspace I/O
++#
++# CONFIG_UIO is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++CONFIG_EXT2_FS_POSIX_ACL=y
++CONFIG_EXT2_FS_SECURITY=y
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
++CONFIG_JBD=y
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++# CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_DNOTIFY is not set
++# CONFIG_INOTIFY is not set
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++# CONFIG_PROC_KCORE is not set
++CONFIG_PROC_SYSCTL=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLBFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++# CONFIG_NETWORK_FILESYSTEMS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++CONFIG_NLS_CODEPAGE_932=y
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++# CONFIG_DLM is not set
++
++#
++# Kernel hacking
++#
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++# CONFIG_DETECT_SOFTLOCKUP is not set
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_INFO=y
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
++# CONFIG_SH_STANDARD_BIOS is not set
++# CONFIG_EARLY_SCIF_CONSOLE is not set
++# CONFIG_DEBUG_BOOTMEM is not set
++# CONFIG_DEBUG_STACKOVERFLOW is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_4KSTACKS is not set
++# CONFIG_IRQSTACKS is not set
++# CONFIG_SH_KGDB is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_AEAD=y
++CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
++CONFIG_CRYPTO_HASH=y
++CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_HMAC=y
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++CONFIG_CRYPTO_SHA1=y
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_ECB is not set
++CONFIG_CRYPTO_CBC=y
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++CONFIG_CRYPTO_DEFLATE=y
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_TEST is not set
++CONFIG_CRYPTO_AUTHENC=y
++# CONFIG_CRYPTO_LZO is not set
++CONFIG_CRYPTO_HW=y
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_CRC_CCITT=y
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/sh/drivers/pci/pci-sh4.h b/arch/sh/drivers/pci/pci-sh4.h
+index 07e2950..a83dcf7 100644
+--- a/arch/sh/drivers/pci/pci-sh4.h
++++ b/arch/sh/drivers/pci/pci-sh4.h
+@@ -15,8 +15,6 @@
+ #define PCI_PROBE_BIOS 1
+ #define PCI_PROBE_CONF1 2
+ #define PCI_PROBE_CONF2 4
+-#define PCI_NO_SORT 0x100
+-#define PCI_BIOS_SORT 0x200
+ #define PCI_NO_CHECKS 0x400
+ #define PCI_ASSIGN_ROMS 0x1000
+ #define PCI_BIOS_IRQ_SCAN 0x2000
+diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32
+index 62bf373..4bbdce3 100644
+--- a/arch/sh/kernel/Makefile_32
++++ b/arch/sh/kernel/Makefile_32
+@@ -5,7 +5,7 @@
+ extra-y := head_32.o init_task.o vmlinux.lds
+
+ obj-y := debugtraps.o io.o io_generic.o irq.o machvec.o process_32.o \
+- ptrace_32.o semaphore.o setup.o signal_32.o sys_sh.o sys_sh32.o \
++ ptrace_32.o setup.o signal_32.o sys_sh.o sys_sh32.o \
+ syscalls_32.o time_32.o topology.o traps.o traps_32.o
+
+ obj-y += cpu/ timers/
+diff --git a/arch/sh/kernel/Makefile_64 b/arch/sh/kernel/Makefile_64
+index e01283d..6edf53b 100644
+--- a/arch/sh/kernel/Makefile_64
++++ b/arch/sh/kernel/Makefile_64
+@@ -1,7 +1,7 @@
+ extra-y := head_64.o init_task.o vmlinux.lds
+
+ obj-y := debugtraps.o io.o io_generic.o irq.o machvec.o process_64.o \
+- ptrace_64.o semaphore.o setup.o signal_64.o sys_sh.o sys_sh64.o \
++ ptrace_64.o setup.o signal_64.o sys_sh.o sys_sh64.o \
+ syscalls_64.o time_64.o topology.o traps.o traps_64.o
+
+ obj-y += cpu/ timers/
+diff --git a/arch/sh/kernel/cf-enabler.c b/arch/sh/kernel/cf-enabler.c
+index 1c3b996..01ff4d0 100644
+--- a/arch/sh/kernel/cf-enabler.c
++++ b/arch/sh/kernel/cf-enabler.c
+@@ -83,6 +83,8 @@ static int __init cf_init_default(void)
+ #include <asm/se.h>
+ #elif defined(CONFIG_SH_7722_SOLUTION_ENGINE)
+ #include <asm/se7722.h>
++#elif defined(CONFIG_SH_7721_SOLUTION_ENGINE)
++#include <asm/se7721.h>
+ #endif
+
+ /*
+@@ -99,7 +101,9 @@ static int __init cf_init_default(void)
+ * 0xB0600000 : I/O
+ */
+
+-#if defined(CONFIG_SH_SOLUTION_ENGINE) || defined(CONFIG_SH_7722_SOLUTION_ENGINE)
++#if defined(CONFIG_SH_SOLUTION_ENGINE) || \
++ defined(CONFIG_SH_7722_SOLUTION_ENGINE) || \
++ defined(CONFIG_SH_7721_SOLUTION_ENGINE)
+ static int __init cf_init_se(void)
+ {
+ if ((ctrl_inw(MRSHPC_CSR) & 0x000c) != 0)
+@@ -112,7 +116,7 @@ static int __init cf_init_se(void)
+ }
+
+ /*
+- * PC-Card window open
++ * PC-Card window open
+ * flag == COMMON/ATTRIBUTE/IO
+ */
+ /* common window open */
+@@ -122,7 +126,7 @@ static int __init cf_init_se(void)
+ ctrl_outw(0x0b00, MRSHPC_MW0CR2);
+ else
+ /* common mode & bus width 16bit SWAP = 0*/
+- ctrl_outw(0x0300, MRSHPC_MW0CR2);
++ ctrl_outw(0x0300, MRSHPC_MW0CR2);
+
+ /* attribute window open */
+ ctrl_outw(0x8a85, MRSHPC_MW1CR1);
+@@ -155,10 +159,9 @@ static int __init cf_init_se(void)
+
+ int __init cf_init(void)
+ {
+- if( mach_is_se() || mach_is_7722se() ){
++ if (mach_is_se() || mach_is_7722se() || mach_is_7721se())
+ return cf_init_se();
+- }
+-
++
+ return cf_init_default();
+ }
+
+diff --git a/arch/sh/kernel/cpu/sh2a/Makefile b/arch/sh/kernel/cpu/sh2a/Makefile
+index b279cdc..7e2b90c 100644
+--- a/arch/sh/kernel/cpu/sh2a/Makefile
++++ b/arch/sh/kernel/cpu/sh2a/Makefile
+@@ -8,6 +8,7 @@ common-y += $(addprefix ../sh2/, ex.o entry.o)
+
+ obj-$(CONFIG_SH_FPU) += fpu.o
+
+-obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o
+-obj-$(CONFIG_CPU_SUBTYPE_SH7203) += setup-sh7203.o clock-sh7203.o
+-obj-$(CONFIG_CPU_SUBTYPE_SH7263) += setup-sh7203.o clock-sh7203.o
++obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o
++obj-$(CONFIG_CPU_SUBTYPE_SH7203) += setup-sh7203.o clock-sh7203.o
++obj-$(CONFIG_CPU_SUBTYPE_SH7263) += setup-sh7203.o clock-sh7203.o
++obj-$(CONFIG_CPU_SUBTYPE_MXG) += setup-mxg.o clock-sh7206.o
+diff --git a/arch/sh/kernel/cpu/sh2a/probe.c b/arch/sh/kernel/cpu/sh2a/probe.c
+index 6910e26..6e79132 100644
+--- a/arch/sh/kernel/cpu/sh2a/probe.c
++++ b/arch/sh/kernel/cpu/sh2a/probe.c
+@@ -29,6 +29,9 @@ int __init detect_cpu_and_cache_system(void)
+ boot_cpu_data.type = CPU_SH7206;
+ /* While SH7206 has a DSP.. */
+ boot_cpu_data.flags |= CPU_HAS_DSP;
++#elif defined(CONFIG_CPU_SUBTYPE_MXG)
++ boot_cpu_data.type = CPU_MXG;
++ boot_cpu_data.flags |= CPU_HAS_DSP;
+ #endif
+
+ boot_cpu_data.dcache.ways = 4;
+diff --git a/arch/sh/kernel/cpu/sh2a/setup-mxg.c b/arch/sh/kernel/cpu/sh2a/setup-mxg.c
+new file mode 100644
+index 0000000..e611d79
+--- /dev/null
++++ b/arch/sh/kernel/cpu/sh2a/setup-mxg.c
+@@ -0,0 +1,168 @@
++/*
++ * Renesas MX-G (R8A03022BG) Setup
++ *
++ * Copyright (C) 2008 Paul Mundt
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ */
++#include <linux/platform_device.h>
++#include <linux/init.h>
++#include <linux/serial.h>
++#include <linux/serial_sci.h>
++
++enum {
++ UNUSED = 0,
++
++ /* interrupt sources */
++ IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
++ IRQ8, IRQ9, IRQ10, IRQ11, IRQ12, IRQ13, IRQ14, IRQ15,
++
++ PINT0, PINT1, PINT2, PINT3, PINT4, PINT5, PINT6, PINT7,
++
++ SINT8, SINT7, SINT6, SINT5, SINT4, SINT3, SINT2, SINT1,
++
++ SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI,
++ SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI,
++
++ MTU2_TGI0A, MTU2_TGI0B, MTU2_TGI0C, MTU2_TGI0D,
++ MTU2_TCI0V, MTU2_TGI0E, MTU2_TGI0F,
++ MTU2_TGI1A, MTU2_TGI1B, MTU2_TCI1V, MTU2_TCI1U,
++ MTU2_TGI2A, MTU2_TGI2B, MTU2_TCI2V, MTU2_TCI2U,
++ MTU2_TGI3A, MTU2_TGI3B, MTU2_TGI3C, MTU2_TGI3D, MTU2_TCI3V,
++ MTU2_TGI4A, MTU2_TGI4B, MTU2_TGI4C, MTU2_TGI4D, MTU2_TCI4V,
++ MTU2_TGI5U, MTU2_TGI5V, MTU2_TGI5W,
++
++ /* interrupt groups */
++ PINT, SCIF0, SCIF1,
++ MTU2_GROUP1, MTU2_GROUP2, MTU2_GROUP3, MTU2_GROUP4, MTU2_GROUP5
++};
++
++static struct intc_vect vectors[] __initdata = {
++ INTC_IRQ(IRQ0, 64), INTC_IRQ(IRQ1, 65),
++ INTC_IRQ(IRQ2, 66), INTC_IRQ(IRQ3, 67),
++ INTC_IRQ(IRQ4, 68), INTC_IRQ(IRQ5, 69),
++ INTC_IRQ(IRQ6, 70), INTC_IRQ(IRQ7, 71),
++ INTC_IRQ(IRQ8, 72), INTC_IRQ(IRQ9, 73),
++ INTC_IRQ(IRQ10, 74), INTC_IRQ(IRQ11, 75),
++ INTC_IRQ(IRQ12, 76), INTC_IRQ(IRQ13, 77),
++ INTC_IRQ(IRQ14, 78), INTC_IRQ(IRQ15, 79),
++
++ INTC_IRQ(PINT0, 80), INTC_IRQ(PINT1, 81),
++ INTC_IRQ(PINT2, 82), INTC_IRQ(PINT3, 83),
++ INTC_IRQ(PINT4, 84), INTC_IRQ(PINT5, 85),
++ INTC_IRQ(PINT6, 86), INTC_IRQ(PINT7, 87),
++
++ INTC_IRQ(SINT8, 94), INTC_IRQ(SINT7, 95),
++ INTC_IRQ(SINT6, 96), INTC_IRQ(SINT5, 97),
++ INTC_IRQ(SINT4, 98), INTC_IRQ(SINT3, 99),
++ INTC_IRQ(SINT2, 100), INTC_IRQ(SINT1, 101),
++
++ INTC_IRQ(SCIF0_RXI, 220), INTC_IRQ(SCIF0_TXI, 221),
++ INTC_IRQ(SCIF0_BRI, 222), INTC_IRQ(SCIF0_ERI, 223),
++ INTC_IRQ(SCIF1_RXI, 224), INTC_IRQ(SCIF1_TXI, 225),
++ INTC_IRQ(SCIF1_BRI, 226), INTC_IRQ(SCIF1_ERI, 227),
++
++ INTC_IRQ(MTU2_TGI0A, 228), INTC_IRQ(MTU2_TGI0B, 229),
++ INTC_IRQ(MTU2_TGI0C, 230), INTC_IRQ(MTU2_TGI0D, 231),
++ INTC_IRQ(MTU2_TCI0V, 232), INTC_IRQ(MTU2_TGI0E, 233),
++
++ INTC_IRQ(MTU2_TGI0F, 234), INTC_IRQ(MTU2_TGI1A, 235),
++ INTC_IRQ(MTU2_TGI1B, 236), INTC_IRQ(MTU2_TCI1V, 237),
++ INTC_IRQ(MTU2_TCI1U, 238), INTC_IRQ(MTU2_TGI2A, 239),
++
++ INTC_IRQ(MTU2_TGI2B, 240), INTC_IRQ(MTU2_TCI2V, 241),
++ INTC_IRQ(MTU2_TCI2U, 242), INTC_IRQ(MTU2_TGI3A, 243),
++
++ INTC_IRQ(MTU2_TGI3B, 244),
++ INTC_IRQ(MTU2_TGI3C, 245),
++
++ INTC_IRQ(MTU2_TGI3D, 246), INTC_IRQ(MTU2_TCI3V, 247),
++ INTC_IRQ(MTU2_TGI4A, 248), INTC_IRQ(MTU2_TGI4B, 249),
++ INTC_IRQ(MTU2_TGI4C, 250), INTC_IRQ(MTU2_TGI4D, 251),
++
++ INTC_IRQ(MTU2_TCI4V, 252), INTC_IRQ(MTU2_TGI5U, 253),
++ INTC_IRQ(MTU2_TGI5V, 254), INTC_IRQ(MTU2_TGI5W, 255),
++};
++
++static struct intc_group groups[] __initdata = {
++ INTC_GROUP(PINT, PINT0, PINT1, PINT2, PINT3,
++ PINT4, PINT5, PINT6, PINT7),
++ INTC_GROUP(MTU2_GROUP1, MTU2_TGI0A, MTU2_TGI0B, MTU2_TGI0C, MTU2_TGI0D,
++ MTU2_TCI0V, MTU2_TGI0E),
++ INTC_GROUP(MTU2_GROUP2, MTU2_TGI0F, MTU2_TGI1A, MTU2_TGI1B,
++ MTU2_TCI1V, MTU2_TCI1U, MTU2_TGI2A),
++ INTC_GROUP(MTU2_GROUP3, MTU2_TGI2B, MTU2_TCI2V, MTU2_TCI2U,
++ MTU2_TGI3A),
++ INTC_GROUP(MTU2_GROUP4, MTU2_TGI3D, MTU2_TCI3V, MTU2_TGI4A,
++ MTU2_TGI4B, MTU2_TGI4C, MTU2_TGI4D),
++ INTC_GROUP(MTU2_GROUP5, MTU2_TCI4V, MTU2_TGI5U, MTU2_TGI5V, MTU2_TGI5W),
++ INTC_GROUP(SCIF0, SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI),
++ INTC_GROUP(SCIF1, SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI),
++};
++
++static struct intc_prio_reg prio_registers[] __initdata = {
++ { 0xfffd9418, 0, 16, 4, /* IPR01 */ { IRQ0, IRQ1, IRQ2, IRQ3 } },
++ { 0xfffd941a, 0, 16, 4, /* IPR02 */ { IRQ4, IRQ5, IRQ6, IRQ7 } },
++ { 0xfffd941c, 0, 16, 4, /* IPR03 */ { IRQ8, IRQ9, IRQ10, IRQ11 } },
++ { 0xfffd941e, 0, 16, 4, /* IPR04 */ { IRQ12, IRQ13, IRQ14, IRQ15 } },
++ { 0xfffd9420, 0, 16, 4, /* IPR05 */ { PINT, 0, 0, 0 } },
++ { 0xfffd9800, 0, 16, 4, /* IPR06 */ { } },
++ { 0xfffd9802, 0, 16, 4, /* IPR07 */ { } },
++ { 0xfffd9804, 0, 16, 4, /* IPR08 */ { } },
++ { 0xfffd9806, 0, 16, 4, /* IPR09 */ { } },
++ { 0xfffd9808, 0, 16, 4, /* IPR10 */ { } },
++ { 0xfffd980a, 0, 16, 4, /* IPR11 */ { } },
++ { 0xfffd980c, 0, 16, 4, /* IPR12 */ { } },
++ { 0xfffd980e, 0, 16, 4, /* IPR13 */ { } },
++ { 0xfffd9810, 0, 16, 4, /* IPR14 */ { 0, 0, 0, SCIF0 } },
++ { 0xfffd9812, 0, 16, 4, /* IPR15 */
++ { SCIF1, MTU2_GROUP1, MTU2_GROUP2, MTU2_GROUP3 } },
++ { 0xfffd9814, 0, 16, 4, /* IPR16 */
++ { MTU2_TGI3B, MTU2_TGI3C, MTU2_GROUP4, MTU2_GROUP5 } },
++};
++
++static struct intc_mask_reg mask_registers[] __initdata = {
++ { 0xfffd9408, 0, 16, /* PINTER */
++ { 0, 0, 0, 0, 0, 0, 0, 0,
++ PINT7, PINT6, PINT5, PINT4, PINT3, PINT2, PINT1, PINT0 } },
++};
++
++static DECLARE_INTC_DESC(intc_desc, "mxg", vectors, groups,
++ mask_registers, prio_registers, NULL);
++
++static struct plat_sci_port sci_platform_data[] = {
++ {
++ .mapbase = 0xff804000,
++ .flags = UPF_BOOT_AUTOCONF,
++ .type = PORT_SCIF,
++ .irqs = { 223, 220, 221, 222 },
++ }, {
++ .flags = 0,
++ }
++};
++
++static struct platform_device sci_device = {
++ .name = "sh-sci",
++ .id = -1,
++ .dev = {
++ .platform_data = sci_platform_data,
++ },
++};
++
++static struct platform_device *mxg_devices[] __initdata = {
++ &sci_device,
++};
++
++static int __init mxg_devices_setup(void)
++{
++ return platform_add_devices(mxg_devices,
++ ARRAY_SIZE(mxg_devices));
++}
++__initcall(mxg_devices_setup);
++
++void __init plat_irq_setup(void)
++{
++ register_intc_controller(&intc_desc);
++}
+diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
+index 9e89984..ebceb0d 100644
+--- a/arch/sh/kernel/cpu/sh4/probe.c
++++ b/arch/sh/kernel/cpu/sh4/probe.c
+@@ -53,7 +53,7 @@ int __init detect_cpu_and_cache_system(void)
+ /*
+ * Setup some generic flags we can probe on SH-4A parts
+ */
+- if (((pvr >> 16) & 0xff) == 0x10) {
++ if (((pvr >> 24) & 0xff) == 0x10) {
+ if ((cvr & 0x10000000) == 0)
+ boot_cpu_data.flags |= CPU_HAS_DSP;
+
+@@ -126,17 +126,22 @@ int __init detect_cpu_and_cache_system(void)
+ CPU_HAS_LLSC;
+ break;
+ case 0x3008:
+- if (prr == 0xa0 || prr == 0xa1) {
+- boot_cpu_data.type = CPU_SH7722;
+- boot_cpu_data.icache.ways = 4;
+- boot_cpu_data.dcache.ways = 4;
+- boot_cpu_data.flags |= CPU_HAS_LLSC;
+- }
+- else if (prr == 0x70) {
++ boot_cpu_data.icache.ways = 4;
++ boot_cpu_data.dcache.ways = 4;
++ boot_cpu_data.flags |= CPU_HAS_LLSC;
++
++ switch (prr) {
++ case 0x50:
++ boot_cpu_data.type = CPU_SH7723;
++ boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_L2_CACHE;
++ break;
++ case 0x70:
+ boot_cpu_data.type = CPU_SH7366;
+- boot_cpu_data.icache.ways = 4;
+- boot_cpu_data.dcache.ways = 4;
+- boot_cpu_data.flags |= CPU_HAS_LLSC;
++ break;
++ case 0xa0:
++ case 0xa1:
++ boot_cpu_data.type = CPU_SH7722;
++ break;
+ }
+ break;
+ case 0x4000: /* 1st cut */
+@@ -215,6 +220,12 @@ int __init detect_cpu_and_cache_system(void)
+ * SH-4A's have an optional PIPT L2.
+ */
+ if (boot_cpu_data.flags & CPU_HAS_L2_CACHE) {
++ /* Bug if we can't decode the L2 info */
++ BUG_ON(!(cvr & 0xf));
++
++ /* Silicon and specifications have clearly never met.. */
++ cvr ^= 0xf;
++
+ /*
+ * Size calculation is much more sensible
+ * than it is for the L1.
+diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile
+index 5d890ac..a880e79 100644
+--- a/arch/sh/kernel/cpu/sh4a/Makefile
++++ b/arch/sh/kernel/cpu/sh4a/Makefile
+@@ -9,6 +9,7 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7780) += setup-sh7780.o
+ obj-$(CONFIG_CPU_SUBTYPE_SH7785) += setup-sh7785.o
+ obj-$(CONFIG_CPU_SUBTYPE_SH7343) += setup-sh7343.o
+ obj-$(CONFIG_CPU_SUBTYPE_SH7722) += setup-sh7722.o
++obj-$(CONFIG_CPU_SUBTYPE_SH7723) += setup-sh7723.o
+ obj-$(CONFIG_CPU_SUBTYPE_SH7366) += setup-sh7366.o
+ obj-$(CONFIG_CPU_SUBTYPE_SHX3) += setup-shx3.o
+
+@@ -22,6 +23,7 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o
+ clock-$(CONFIG_CPU_SUBTYPE_SH7785) := clock-sh7785.o
+ clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o
+ clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o
++clock-$(CONFIG_CPU_SUBTYPE_SH7723) := clock-sh7722.o
+ clock-$(CONFIG_CPU_SUBTYPE_SH7366) := clock-sh7722.o
+ clock-$(CONFIG_CPU_SUBTYPE_SHX3) := clock-shx3.o
+
+diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+index b98b4bc..0693140 100644
+--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
++++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+@@ -16,13 +16,12 @@
+
+ static struct resource usbf_resources[] = {
+ [0] = {
+- .name = "m66592_udc",
+- .start = 0xA4480000,
+- .end = 0xA44800FF,
++ .name = "USBF",
++ .start = 0x04480000,
++ .end = 0x044800FF,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+- .name = "m66592_udc",
+ .start = 65,
+ .end = 65,
+ .flags = IORESOURCE_IRQ,
+@@ -40,6 +39,26 @@ static struct platform_device usbf_device = {
+ .resource = usbf_resources,
+ };
+
++static struct resource iic_resources[] = {
++ [0] = {
++ .name = "IIC",
++ .start = 0x04470000,
++ .end = 0x04470017,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = 96,
++ .end = 99,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device iic_device = {
++ .name = "i2c-sh_mobile",
++ .num_resources = ARRAY_SIZE(iic_resources),
++ .resource = iic_resources,
++};
++
+ static struct plat_sci_port sci_platform_data[] = {
+ {
+ .mapbase = 0xffe00000,
+@@ -74,6 +93,7 @@ static struct platform_device sci_device = {
+
+ static struct platform_device *sh7722_devices[] __initdata = {
+ &usbf_device,
++ &iic_device,
+ &sci_device,
+ };
+
+diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
+new file mode 100644
+index 0000000..16925cf
+--- /dev/null
++++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
+@@ -0,0 +1,300 @@
++/*
++ * SH7723 Setup
++ *
++ * Copyright (C) 2008 Paul Mundt
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ */
++#include <linux/platform_device.h>
++#include <linux/init.h>
++#include <linux/serial.h>
++#include <linux/mm.h>
++#include <linux/serial_sci.h>
++#include <asm/mmzone.h>
++
++static struct plat_sci_port sci_platform_data[] = {
++ {
++ .mapbase = 0xa4e30000,
++ .flags = UPF_BOOT_AUTOCONF,
++ .type = PORT_SCI,
++ .irqs = { 56, 56, 56, 56 },
++ },{
++ .mapbase = 0xa4e40000,
++ .flags = UPF_BOOT_AUTOCONF,
++ .type = PORT_SCI,
++ .irqs = { 88, 88, 88, 88 },
++ },{
++ .mapbase = 0xa4e50000,
++ .flags = UPF_BOOT_AUTOCONF,
++ .type = PORT_SCI,
++ .irqs = { 109, 109, 109, 109 },
++ }, {
++ .flags = 0,
++ }
++};
++
++static struct platform_device sci_device = {
++ .name = "sh-sci",
++ .id = -1,
++ .dev = {
++ .platform_data = sci_platform_data,
++ },
++};
++
++static struct resource rtc_resources[] = {
++ [0] = {
++ .start = 0xa465fec0,
++ .end = 0xa465fec0 + 0x58 - 1,
++ .flags = IORESOURCE_IO,
++ },
++ [1] = {
++ /* Period IRQ */
++ .start = 69,
++ .flags = IORESOURCE_IRQ,
++ },
++ [2] = {
++ /* Carry IRQ */
++ .start = 70,
++ .flags = IORESOURCE_IRQ,
++ },
++ [3] = {
++ /* Alarm IRQ */
++ .start = 68,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device rtc_device = {
++ .name = "sh-rtc",
++ .id = -1,
++ .num_resources = ARRAY_SIZE(rtc_resources),
++ .resource = rtc_resources,
++};
++
++static struct platform_device *sh7723_devices[] __initdata = {
++ &sci_device,
++ &rtc_device,
++};
++
++static int __init sh7723_devices_setup(void)
++{
++ return platform_add_devices(sh7723_devices,
++ ARRAY_SIZE(sh7723_devices));
++}
++__initcall(sh7723_devices_setup);
++
++enum {
++ UNUSED=0,
++
++ /* interrupt sources */
++ IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
++ HUDI,
++ DMAC1A_DEI0,DMAC1A_DEI1,DMAC1A_DEI2,DMAC1A_DEI3,
++ _2DG_TRI,_2DG_INI,_2DG_CEI,
++ DMAC0A_DEI0,DMAC0A_DEI1,DMAC0A_DEI2,DMAC0A_DEI3,
++ VIO_CEUI,VIO_BEUI,VIO_VEU2HI,VIO_VOUI,
++ SCIFA_SCIFA0,
++ VPU_VPUI,
++ TPU_TPUI,
++ ADC_ADI,
++ USB_USI0,
++ RTC_ATI,RTC_PRI,RTC_CUI,
++ DMAC1B_DEI4,DMAC1B_DEI5,DMAC1B_DADERR,
++ DMAC0B_DEI4,DMAC0B_DEI5,DMAC0B_DADERR,
++ KEYSC_KEYI,
++ SCIF_SCIF0,SCIF_SCIF1,SCIF_SCIF2,
++ MSIOF_MSIOFI0,MSIOF_MSIOFI1,
++ SCIFA_SCIFA1,
++ FLCTL_FLSTEI,FLCTL_FLTENDI,FLCTL_FLTREQ0I,FLCTL_FLTREQ1I,
++ I2C_ALI,I2C_TACKI,I2C_WAITI,I2C_DTEI,
++ SDHI0_SDHII0,SDHI0_SDHII1,SDHI0_SDHII2,
++ CMT_CMTI,
++ TSIF_TSIFI,
++ SIU_SIUI,
++ SCIFA_SCIFA2,
++ TMU0_TUNI0, TMU0_TUNI1, TMU0_TUNI2,
++ IRDA_IRDAI,
++ ATAPI_ATAPII,
++ SDHI1_SDHII0,SDHI1_SDHII1,SDHI1_SDHII2,
++ VEU2H1_VEU2HI,
++ LCDC_LCDCI,
++ TMU1_TUNI0,TMU1_TUNI1,TMU1_TUNI2,
++
++ /* interrupt groups */
++ DMAC1A, DMAC0A, VIO, DMAC0B, FLCTL, I2C, _2DG,
++ SDHI1, RTC, DMAC1B, SDHI0,
++};
++
++static struct intc_vect vectors[] __initdata = {
++ INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620),
++ INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660),
++ INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0),
++ INTC_VECT(IRQ6, 0x6c0), INTC_VECT(IRQ7, 0x6e0),
++
++ INTC_VECT(DMAC1A_DEI0,0x700),
++ INTC_VECT(DMAC1A_DEI1,0x720),
++ INTC_VECT(DMAC1A_DEI2,0x740),
++ INTC_VECT(DMAC1A_DEI3,0x760),
++
++ INTC_VECT(_2DG_TRI, 0x780),
++ INTC_VECT(_2DG_INI, 0x7A0),
++ INTC_VECT(_2DG_CEI, 0x7C0),
++
++ INTC_VECT(DMAC0A_DEI0,0x800),
++ INTC_VECT(DMAC0A_DEI1,0x820),
++ INTC_VECT(DMAC0A_DEI2,0x840),
++ INTC_VECT(DMAC0A_DEI3,0x860),
++
++ INTC_VECT(VIO_CEUI,0x880),
++ INTC_VECT(VIO_BEUI,0x8A0),
++ INTC_VECT(VIO_VEU2HI,0x8C0),
++ INTC_VECT(VIO_VOUI,0x8E0),
++
++ INTC_VECT(SCIFA_SCIFA0,0x900),
++ INTC_VECT(VPU_VPUI,0x920),
++ INTC_VECT(TPU_TPUI,0x9A0),
++ INTC_VECT(ADC_ADI,0x9E0),
++ INTC_VECT(USB_USI0,0xA20),
++
++ INTC_VECT(RTC_ATI,0xA80),
++ INTC_VECT(RTC_PRI,0xAA0),
++ INTC_VECT(RTC_CUI,0xAC0),
++
++ INTC_VECT(DMAC1B_DEI4,0xB00),
++ INTC_VECT(DMAC1B_DEI5,0xB20),
++ INTC_VECT(DMAC1B_DADERR,0xB40),
++
++ INTC_VECT(DMAC0B_DEI4,0xB80),
++ INTC_VECT(DMAC0B_DEI5,0xBA0),
++ INTC_VECT(DMAC0B_DADERR,0xBC0),
++
++ INTC_VECT(KEYSC_KEYI,0xBE0),
++ INTC_VECT(SCIF_SCIF0,0xC00),
++ INTC_VECT(SCIF_SCIF1,0xC20),
++ INTC_VECT(SCIF_SCIF2,0xC40),
++ INTC_VECT(MSIOF_MSIOFI0,0xC80),
++ INTC_VECT(MSIOF_MSIOFI1,0xCA0),
++ INTC_VECT(SCIFA_SCIFA1,0xD00),
++
++ INTC_VECT(FLCTL_FLSTEI,0xD80),
++ INTC_VECT(FLCTL_FLTENDI,0xDA0),
++ INTC_VECT(FLCTL_FLTREQ0I,0xDC0),
++ INTC_VECT(FLCTL_FLTREQ1I,0xDE0),
++
++ INTC_VECT(I2C_ALI,0xE00),
++ INTC_VECT(I2C_TACKI,0xE20),
++ INTC_VECT(I2C_WAITI,0xE40),
++ INTC_VECT(I2C_DTEI,0xE60),
++
++ INTC_VECT(SDHI0_SDHII0,0xE80),
++ INTC_VECT(SDHI0_SDHII1,0xEA0),
++ INTC_VECT(SDHI0_SDHII2,0xEC0),
++
++ INTC_VECT(CMT_CMTI,0xF00),
++ INTC_VECT(TSIF_TSIFI,0xF20),
++ INTC_VECT(SIU_SIUI,0xF80),
++ INTC_VECT(SCIFA_SCIFA2,0xFA0),
++
++ INTC_VECT(TMU0_TUNI0,0x400),
++ INTC_VECT(TMU0_TUNI1,0x420),
++ INTC_VECT(TMU0_TUNI2,0x440),
++
++ INTC_VECT(IRDA_IRDAI,0x480),
++ INTC_VECT(ATAPI_ATAPII,0x4A0),
++
++ INTC_VECT(SDHI1_SDHII0,0x4E0),
++ INTC_VECT(SDHI1_SDHII1,0x500),
++ INTC_VECT(SDHI1_SDHII2,0x520),
++
++ INTC_VECT(VEU2H1_VEU2HI,0x560),
++ INTC_VECT(LCDC_LCDCI,0x580),
++
++ INTC_VECT(TMU1_TUNI0,0x920),
++ INTC_VECT(TMU1_TUNI1,0x940),
++ INTC_VECT(TMU1_TUNI2,0x960),
++
++};
++
++static struct intc_group groups[] __initdata = {
++ INTC_GROUP(DMAC1A,DMAC1A_DEI0,DMAC1A_DEI1,DMAC1A_DEI2,DMAC1A_DEI3),
++ INTC_GROUP(DMAC0A,DMAC0A_DEI0,DMAC0A_DEI1,DMAC0A_DEI2,DMAC0A_DEI3),
++ INTC_GROUP(VIO, VIO_CEUI,VIO_BEUI,VIO_VEU2HI,VIO_VOUI),
++ INTC_GROUP(DMAC0B, DMAC0B_DEI4,DMAC0B_DEI5,DMAC0B_DADERR),
++ INTC_GROUP(FLCTL,FLCTL_FLSTEI,FLCTL_FLTENDI,FLCTL_FLTREQ0I,FLCTL_FLTREQ1I),
++ INTC_GROUP(I2C,I2C_ALI,I2C_TACKI,I2C_WAITI,I2C_DTEI),
++ INTC_GROUP(_2DG, _2DG_TRI,_2DG_INI,_2DG_CEI),
++ INTC_GROUP(SDHI1, SDHI1_SDHII0,SDHI1_SDHII1,SDHI1_SDHII2),
++ INTC_GROUP(RTC, RTC_ATI,RTC_PRI,RTC_CUI),
++ INTC_GROUP(DMAC1B, DMAC1B_DEI4,DMAC1B_DEI5,DMAC1B_DADERR),
++ INTC_GROUP(SDHI0,SDHI0_SDHII0,SDHI0_SDHII1,SDHI0_SDHII2),
++};
++
++static struct intc_mask_reg mask_registers[] __initdata = {
++ { 0xa4080080, 0xa40800c0, 8, /* IMR0 / IMCR0 */
++ { 0, TMU1_TUNI2,TMU1_TUNI1,TMU1_TUNI0,0,SDHI1_SDHII2,SDHI1_SDHII1,SDHI1_SDHII0} },
++ { 0xa4080084, 0xa40800c4, 8, /* IMR1 / IMCR1 */
++ { VIO_VOUI, VIO_VEU2HI,VIO_BEUI,VIO_CEUI,DMAC0A_DEI3,DMAC0A_DEI2,DMAC0A_DEI1,DMAC0A_DEI0 } },
++ { 0xa4080088, 0xa40800c8, 8, /* IMR2 / IMCR2 */
++ { 0, 0, 0, VPU_VPUI,0,0,0,SCIFA_SCIFA0 } },
++ { 0xa408008c, 0xa40800cc, 8, /* IMR3 / IMCR3 */
++ { DMAC1A_DEI3,DMAC1A_DEI2,DMAC1A_DEI1,DMAC1A_DEI0,0,0,0,IRDA_IRDAI } },
++ { 0xa4080090, 0xa40800d0, 8, /* IMR4 / IMCR4 */
++ { 0,TMU0_TUNI2,TMU0_TUNI1,TMU0_TUNI0,VEU2H1_VEU2HI,0,0,LCDC_LCDCI } },
++ { 0xa4080094, 0xa40800d4, 8, /* IMR5 / IMCR5 */
++ { KEYSC_KEYI,DMAC0B_DADERR,DMAC0B_DEI5,DMAC0B_DEI4,0,SCIF_SCIF2,SCIF_SCIF1,SCIF_SCIF0 } },
++ { 0xa4080098, 0xa40800d8, 8, /* IMR6 / IMCR6 */
++ { 0,0,0,SCIFA_SCIFA1,ADC_ADI,0,MSIOF_MSIOFI1,MSIOF_MSIOFI0 } },
++ { 0xa408009c, 0xa40800dc, 8, /* IMR7 / IMCR7 */
++ { I2C_DTEI, I2C_WAITI, I2C_TACKI, I2C_ALI,
++ FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLTENDI, FLCTL_FLSTEI } },
++ { 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */
++ { 0,SDHI0_SDHII2,SDHI0_SDHII1,SDHI0_SDHII0,0,0,SCIFA_SCIFA2,SIU_SIUI } },
++ { 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */
++ { 0, 0, 0, CMT_CMTI, 0, 0, USB_USI0,0 } },
++ { 0xa40800a8, 0xa40800e8, 8, /* IMR10 / IMCR10 */
++ { 0, DMAC1B_DADERR,DMAC1B_DEI5,DMAC1B_DEI4,0,RTC_ATI,RTC_PRI,RTC_CUI } },
++ { 0xa40800ac, 0xa40800ec, 8, /* IMR11 / IMCR11 */
++ { 0,_2DG_CEI,_2DG_INI,_2DG_TRI,0,TPU_TPUI,0,TSIF_TSIFI } },
++ { 0xa40800b0, 0xa40800f0, 8, /* IMR12 / IMCR12 */
++ { 0,0,0,0,0,0,0,ATAPI_ATAPII } },
++ { 0xa4140044, 0xa4140064, 8, /* INTMSK00 / INTMSKCLR00 */
++ { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
++};
++
++static struct intc_prio_reg prio_registers[] __initdata = {
++ { 0xa4080000, 0, 16, 4, /* IPRA */ { TMU0_TUNI0, TMU0_TUNI1, TMU0_TUNI2, IRDA_IRDAI } },
++ { 0xa4080004, 0, 16, 4, /* IPRB */ { VEU2H1_VEU2HI, LCDC_LCDCI, DMAC1A, 0} },
++ { 0xa4080008, 0, 16, 4, /* IPRC */ { TMU1_TUNI0, TMU1_TUNI1, TMU1_TUNI2, 0} },
++ { 0xa408000c, 0, 16, 4, /* IPRD */ { } },
++ { 0xa4080010, 0, 16, 4, /* IPRE */ { DMAC0A, VIO, SCIFA_SCIFA0, VPU_VPUI } },
++ { 0xa4080014, 0, 16, 4, /* IPRF */ { KEYSC_KEYI, DMAC0B, USB_USI0, CMT_CMTI } },
++ { 0xa4080018, 0, 16, 4, /* IPRG */ { SCIF_SCIF0, SCIF_SCIF1, SCIF_SCIF2,0 } },
++ { 0xa408001c, 0, 16, 4, /* IPRH */ { MSIOF_MSIOFI0,MSIOF_MSIOFI1, FLCTL, I2C } },
++ { 0xa4080020, 0, 16, 4, /* IPRI */ { SCIFA_SCIFA1,0,TSIF_TSIFI,_2DG } },
++ { 0xa4080024, 0, 16, 4, /* IPRJ */ { ADC_ADI,0,SIU_SIUI,SDHI1 } },
++ { 0xa4080028, 0, 16, 4, /* IPRK */ { RTC,DMAC1B,0,SDHI0 } },
++ { 0xa408002c, 0, 16, 4, /* IPRL */ { SCIFA_SCIFA2,0,TPU_TPUI,ATAPI_ATAPII } },
++ { 0xa4140010, 0, 32, 4, /* INTPRI00 */
++ { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
++};
++
++static struct intc_sense_reg sense_registers[] __initdata = {
++ { 0xa414001c, 16, 2, /* ICR1 */
++ { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
++};
++
++static DECLARE_INTC_DESC(intc_desc, "sh7723", vectors, groups,
++ mask_registers, prio_registers, sense_registers);
++
++void __init plat_irq_setup(void)
++{
++ register_intc_controller(&intc_desc);
++}
++
++void __init plat_mem_setup(void)
++{
++ /* Register the URAM space as Node 1 */
++ setup_bootmem_node(1, 0x055f0000, 0x05610000);
++}
+diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
+index 07c988d..ae2b222 100644
+--- a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
++++ b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
+@@ -231,12 +231,6 @@ static struct intc_group groups[] __initdata = {
+ INTC_GROUP(GPIO, GPIO_CH0, GPIO_CH1, GPIO_CH2, GPIO_CH3),
+ };
+
+-static struct intc_prio priorities[] __initdata = {
+- INTC_PRIO(SCIF0, 3),
+- INTC_PRIO(SCIF1, 3),
+- INTC_PRIO(SCIF2, 3),
+-};
+-
+ static struct intc_mask_reg mask_registers[] __initdata = {
+ { 0xffd40038, 0xffd4003c, 32, /* INT2MSKR / INT2MSKCR */
+ { 0, 0, 0, 0, 0, 0, GPIO, 0,
+@@ -270,11 +264,10 @@ static struct intc_prio_reg prio_registers[] __initdata = {
+ { 0xffd400b4, 0, 32, 8, /* INT2PRI13 */ { 0, 0, STIF1, STIF0 } },
+ };
+
+-static DECLARE_INTC_DESC(intc_desc, "sh7763", vectors, groups, priorities,
++static DECLARE_INTC_DESC(intc_desc, "sh7763", vectors, groups,
+ mask_registers, prio_registers, NULL);
+
+ /* Support for external interrupt pins in IRQ mode */
+-
+ static struct intc_vect irq_vectors[] __initdata = {
+ INTC_VECT(IRQ0, 0x240), INTC_VECT(IRQ1, 0x280),
+ INTC_VECT(IRQ2, 0x2c0), INTC_VECT(IRQ3, 0x300),
+@@ -302,7 +295,6 @@ static DECLARE_INTC_DESC(intc_irq_desc, "sh7763-irq", irq_vectors,
+ irq_sense_registers);
+
+ /* External interrupt pins in IRL mode */
+-
+ static struct intc_vect irl_vectors[] __initdata = {
+ INTC_VECT(IRL_LLLL, 0x200), INTC_VECT(IRL_LLLH, 0x220),
+ INTC_VECT(IRL_LLHL, 0x240), INTC_VECT(IRL_LLHH, 0x260),
+diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7770.c b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
+index b9cec48..b73578e 100644
+--- a/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
++++ b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
+@@ -1,7 +1,7 @@
+ /*
+ * SH7770 Setup
+ *
+- * Copyright (C) 2006 Paul Mundt
++ * Copyright (C) 2006 - 2008 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+@@ -29,6 +29,41 @@ static struct plat_sci_port sci_platform_data[] = {
+ .type = PORT_SCIF,
+ .irqs = { 63, 63, 63, 63 },
+ }, {
++ .mapbase = 0xff926000,
++ .flags = UPF_BOOT_AUTOCONF,
++ .type = PORT_SCIF,
++ .irqs = { 64, 64, 64, 64 },
++ }, {
++ .mapbase = 0xff927000,
++ .flags = UPF_BOOT_AUTOCONF,
++ .type = PORT_SCIF,
++ .irqs = { 65, 65, 65, 65 },
++ }, {
++ .mapbase = 0xff928000,
++ .flags = UPF_BOOT_AUTOCONF,
++ .type = PORT_SCIF,
++ .irqs = { 66, 66, 66, 66 },
++ }, {
++ .mapbase = 0xff929000,
++ .flags = UPF_BOOT_AUTOCONF,
++ .type = PORT_SCIF,
++ .irqs = { 67, 67, 67, 67 },
++ }, {
++ .mapbase = 0xff92a000,
++ .flags = UPF_BOOT_AUTOCONF,
++ .type = PORT_SCIF,
++ .irqs = { 68, 68, 68, 68 },
++ }, {
++ .mapbase = 0xff92b000,
++ .flags = UPF_BOOT_AUTOCONF,
++ .type = PORT_SCIF,
++ .irqs = { 69, 69, 69, 69 },
++ }, {
++ .mapbase = 0xff92c000,
++ .flags = UPF_BOOT_AUTOCONF,
++ .type = PORT_SCIF,
++ .irqs = { 70, 70, 70, 70 },
++ }, {
+ .flags = 0,
+ }
+ };
+diff --git a/arch/sh/kernel/semaphore.c b/arch/sh/kernel/semaphore.c
+deleted file mode 100644
+index 184119e..0000000
+--- a/arch/sh/kernel/semaphore.c
++++ /dev/null
+@@ -1,139 +0,0 @@
+-/*
+- * Just taken from alpha implementation.
+- * This can't work well, perhaps.
+- */
+-/*
+- * Generic semaphore code. Buyer beware. Do your own
+- * specific changes in <asm/semaphore-helper.h>
+- */
+-
+-#include <linux/errno.h>
+-#include <linux/sched.h>
+-#include <linux/wait.h>
+-#include <linux/init.h>
+-#include <asm/semaphore.h>
+-#include <asm/semaphore-helper.h>
+-
+-DEFINE_SPINLOCK(semaphore_wake_lock);
+-
+-/*
+- * Semaphores are implemented using a two-way counter:
+- * The "count" variable is decremented for each process
+- * that tries to sleep, while the "waking" variable is
+- * incremented when the "up()" code goes to wake up waiting
+- * processes.
+- *
+- * Notably, the inline "up()" and "down()" functions can
+- * efficiently test if they need to do any extra work (up
+- * needs to do something only if count was negative before
+- * the increment operation.
+- *
+- * waking_non_zero() (from asm/semaphore.h) must execute
+- * atomically.
+- *
+- * When __up() is called, the count was negative before
+- * incrementing it, and we need to wake up somebody.
+- *
+- * This routine adds one to the count of processes that need to
+- * wake up and exit. ALL waiting processes actually wake up but
+- * only the one that gets to the "waking" field first will gate
+- * through and acquire the semaphore. The others will go back
+- * to sleep.
+- *
+- * Note that these functions are only called when there is
+- * contention on the lock, and as such all this is the
+- * "non-critical" part of the whole semaphore business. The
+- * critical part is the inline stuff in <asm/semaphore.h>
+- * where we want to avoid any extra jumps and calls.
+- */
+-void __up(struct semaphore *sem)
+-{
+- wake_one_more(sem);
+- wake_up(&sem->wait);
+-}
+-
+-/*
+- * Perform the "down" function. Return zero for semaphore acquired,
+- * return negative for signalled out of the function.
+- *
+- * If called from __down, the return is ignored and the wait loop is
+- * not interruptible. This means that a task waiting on a semaphore
+- * using "down()" cannot be killed until someone does an "up()" on
+- * the semaphore.
+- *
+- * If called from __down_interruptible, the return value gets checked
+- * upon return. If the return value is negative then the task continues
+- * with the negative value in the return register (it can be tested by
+- * the caller).
+- *
+- * Either form may be used in conjunction with "up()".
+- *
+- */
+-
+-#define DOWN_VAR \
+- struct task_struct *tsk = current; \
+- wait_queue_t wait; \
+- init_waitqueue_entry(&wait, tsk);
+-
+-#define DOWN_HEAD(task_state) \
+- \
+- \
+- tsk->state = (task_state); \
+- add_wait_queue(&sem->wait, &wait); \
+- \
+- /* \
+- * Ok, we're set up. sem->count is known to be less than zero \
+- * so we must wait. \
+- * \
+- * We can let go the lock for purposes of waiting. \
+- * We re-acquire it after awaking so as to protect \
+- * all semaphore operations. \
+- * \
+- * If "up()" is called before we call waking_non_zero() then \
+- * we will catch it right away. If it is called later then \
+- * we will have to go through a wakeup cycle to catch it. \
+- * \
+- * Multiple waiters contend for the semaphore lock to see \
+- * who gets to gate through and who has to wait some more. \
+- */ \
+- for (;;) {
+-
+-#define DOWN_TAIL(task_state) \
+- tsk->state = (task_state); \
+- } \
+- tsk->state = TASK_RUNNING; \
+- remove_wait_queue(&sem->wait, &wait);
+-
+-void __sched __down(struct semaphore * sem)
+-{
+- DOWN_VAR
+- DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+- if (waking_non_zero(sem))
+- break;
+- schedule();
+- DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+-}
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+- int ret = 0;
+- DOWN_VAR
+- DOWN_HEAD(TASK_INTERRUPTIBLE)
+-
+- ret = waking_non_zero_interruptible(sem, tsk);
+- if (ret)
+- {
+- if (ret == 1)
+- /* ret != 0 only if we get interrupted -arca */
+- ret = 0;
+- break;
+- }
+- schedule();
+- DOWN_TAIL(TASK_INTERRUPTIBLE)
+- return ret;
+-}
+-
+-int __down_trylock(struct semaphore * sem)
+-{
+- return waking_non_zero_trylock(sem);
+-}
+diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
+index ff4f54a..284f66f 100644
+--- a/arch/sh/kernel/setup.c
++++ b/arch/sh/kernel/setup.c
+@@ -23,6 +23,8 @@
+ #include <linux/kexec.h>
+ #include <linux/module.h>
+ #include <linux/smp.h>
++#include <linux/err.h>
++#include <linux/debugfs.h>
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
+ #include <asm/page.h>
+@@ -333,6 +335,7 @@ static const char *cpu_name[] = {
+ [CPU_SH7343] = "SH7343", [CPU_SH7785] = "SH7785",
+ [CPU_SH7722] = "SH7722", [CPU_SHX3] = "SH-X3",
+ [CPU_SH5_101] = "SH5-101", [CPU_SH5_103] = "SH5-103",
++ [CPU_MXG] = "MX-G", [CPU_SH7723] = "SH7723",
+ [CPU_SH7366] = "SH7366", [CPU_SH_NONE] = "Unknown"
+ };
+
+@@ -443,3 +446,15 @@ const struct seq_operations cpuinfo_op = {
+ .show = show_cpuinfo,
+ };
+ #endif /* CONFIG_PROC_FS */
++
++struct dentry *sh_debugfs_root;
++
++static int __init sh_debugfs_init(void)
++{
++ sh_debugfs_root = debugfs_create_dir("sh", NULL);
++ if (IS_ERR(sh_debugfs_root))
++ return PTR_ERR(sh_debugfs_root);
++
++ return 0;
++}
++arch_initcall(sh_debugfs_init);
+diff --git a/arch/sh/kernel/sh_ksyms_32.c b/arch/sh/kernel/sh_ksyms_32.c
+index 45bb333..6d40546 100644
+--- a/arch/sh/kernel/sh_ksyms_32.c
++++ b/arch/sh/kernel/sh_ksyms_32.c
+@@ -9,7 +9,6 @@
+ #include <linux/pci.h>
+ #include <linux/irq.h>
+ #include <asm/sections.h>
+-#include <asm/semaphore.h>
+ #include <asm/processor.h>
+ #include <asm/uaccess.h>
+ #include <asm/checksum.h>
+@@ -48,12 +47,6 @@ EXPORT_SYMBOL(__copy_user);
+ EXPORT_SYMBOL(get_vm_area);
+ #endif
+
+-/* semaphore exports */
+-EXPORT_SYMBOL(__up);
+-EXPORT_SYMBOL(__down);
+-EXPORT_SYMBOL(__down_interruptible);
+-EXPORT_SYMBOL(__down_trylock);
+-
+ EXPORT_SYMBOL(__udelay);
+ EXPORT_SYMBOL(__ndelay);
+ EXPORT_SYMBOL(__const_udelay);
+diff --git a/arch/sh/kernel/sh_ksyms_64.c b/arch/sh/kernel/sh_ksyms_64.c
+index b6410ce..a310c97 100644
+--- a/arch/sh/kernel/sh_ksyms_64.c
++++ b/arch/sh/kernel/sh_ksyms_64.c
+@@ -16,7 +16,6 @@
+ #include <linux/in6.h>
+ #include <linux/interrupt.h>
+ #include <linux/screen_info.h>
+-#include <asm/semaphore.h>
+ #include <asm/processor.h>
+ #include <asm/uaccess.h>
+ #include <asm/checksum.h>
+@@ -37,9 +36,6 @@ EXPORT_SYMBOL(csum_partial_copy_nocheck);
+ EXPORT_SYMBOL(screen_info);
+ #endif
+
+-EXPORT_SYMBOL(__down);
+-EXPORT_SYMBOL(__down_trylock);
+-EXPORT_SYMBOL(__up);
+ EXPORT_SYMBOL(__put_user_asm_l);
+ EXPORT_SYMBOL(__get_user_asm_l);
+ EXPORT_SYMBOL(copy_page);
+diff --git a/arch/sh/lib/clear_page.S b/arch/sh/lib/clear_page.S
+index 3539123..8342bfb 100644
+--- a/arch/sh/lib/clear_page.S
++++ b/arch/sh/lib/clear_page.S
+@@ -27,11 +27,11 @@ ENTRY(clear_page)
+ mov #0,r0
+ !
+ 1:
+-#if defined(CONFIG_CPU_SH3)
+- mov.l r0, at r4
+-#elif defined(CONFIG_CPU_SH4)
++#if defined(CONFIG_CPU_SH4)
+ movca.l r0, at r4
+ mov r4,r1
++#else
++ mov.l r0, at r4
+ #endif
+ add #32,r4
+ mov.l r0, at -r4
+diff --git a/arch/sh/lib/copy_page.S b/arch/sh/lib/copy_page.S
+index e002b91..5d12e65 100644
+--- a/arch/sh/lib/copy_page.S
++++ b/arch/sh/lib/copy_page.S
+@@ -41,11 +41,11 @@ ENTRY(copy_page)
+ mov.l @r11+,r5
+ mov.l @r11+,r6
+ mov.l @r11+,r7
+-#if defined(CONFIG_CPU_SH3)
+- mov.l r0, at r10
+-#elif defined(CONFIG_CPU_SH4)
++#if defined(CONFIG_CPU_SH4)
+ movca.l r0, at r10
+ mov r10,r0
++#else
++ mov.l r0, at r10
+ #endif
+ add #32,r10
+ mov.l r7, at -r10
+diff --git a/arch/sh/mm/cache-debugfs.c b/arch/sh/mm/cache-debugfs.c
+index db6d950..c5b56d5 100644
+--- a/arch/sh/mm/cache-debugfs.c
++++ b/arch/sh/mm/cache-debugfs.c
+@@ -127,13 +127,13 @@ static int __init cache_debugfs_init(void)
+ {
+ struct dentry *dcache_dentry, *icache_dentry;
+
+- dcache_dentry = debugfs_create_file("dcache", S_IRUSR, NULL,
++ dcache_dentry = debugfs_create_file("dcache", S_IRUSR, sh_debugfs_root,
+ (unsigned int *)CACHE_TYPE_DCACHE,
+ &cache_debugfs_fops);
+ if (IS_ERR(dcache_dentry))
+ return PTR_ERR(dcache_dentry);
+
+- icache_dentry = debugfs_create_file("icache", S_IRUSR, NULL,
++ icache_dentry = debugfs_create_file("icache", S_IRUSR, sh_debugfs_root,
+ (unsigned int *)CACHE_TYPE_ICACHE,
+ &cache_debugfs_fops);
+ if (IS_ERR(icache_dentry)) {
+diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c
+index ab81c60..0b0ec6e 100644
+--- a/arch/sh/mm/pmb.c
++++ b/arch/sh/mm/pmb.c
+@@ -393,7 +393,7 @@ static int __init pmb_debugfs_init(void)
+ struct dentry *dentry;
+
+ dentry = debugfs_create_file("pmb", S_IFREG | S_IRUGO,
+- NULL, NULL, &pmb_debugfs_fops);
++ sh_debugfs_root, NULL, &pmb_debugfs_fops);
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
+
+diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types
+index d63b93d..987c668 100644
+--- a/arch/sh/tools/mach-types
++++ b/arch/sh/tools/mach-types
+@@ -21,8 +21,9 @@ HD64465 HD64465
+ 7206SE SH_7206_SOLUTION_ENGINE
+ 7343SE SH_7343_SOLUTION_ENGINE
+ 7619SE SH_7619_SOLUTION_ENGINE
+-7722SE SH_7722_SOLUTION_ENGINE
+-7751SE SH_7751_SOLUTION_ENGINE
++7721SE SH_7721_SOLUTION_ENGINE
++7722SE SH_7722_SOLUTION_ENGINE
++7751SE SH_7751_SOLUTION_ENGINE
+ 7780SE SH_7780_SOLUTION_ENGINE
+ 7751SYSTEMH SH_7751_SYSTEMH
+ HP6XX SH_HP6XX
+diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
+index c40343c..49590f8 100644
+--- a/arch/sparc/Kconfig
++++ b/arch/sparc/Kconfig
+@@ -27,9 +27,6 @@ config ARCH_NO_VIRT_TO_BUS
+ config OF
+ def_bool y
+
+-config ARCH_SUPPORTS_AOUT
+- def_bool y
+-
+ config HZ
+ int
+ default 100
+@@ -257,15 +254,6 @@ config SPARC_LED
+
+ source "fs/Kconfig.binfmt"
+
+-config SUNOS_EMUL
+- bool "SunOS binary emulation"
+- help
+- This allows you to run most SunOS binaries. If you want to do this,
+- say Y here and place appropriate files in /usr/gnemul/sunos. See
+- <http://www.ultralinux.org/faq.html> for more information. If you
+- want to run SunOS binaries on an Ultra you must also say Y to
+- "Kernel support for 32-bit a.out binaries" above.
+-
+ source "mm/Kconfig"
+
+ endmenu
+diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig
+index f7a5091..6a2c57a 100644
+--- a/arch/sparc/defconfig
++++ b/arch/sparc/defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.23-rc1
+-# Wed Jul 25 15:30:21 2007
++# Linux kernel version: 2.6.25
++# Sun Apr 20 01:49:51 2008
+ #
+ CONFIG_MMU=y
+ CONFIG_HIGHMEM=y
+@@ -9,18 +9,15 @@ CONFIG_ZONE_DMA=y
+ CONFIG_GENERIC_ISA_DMA=y
+ CONFIG_ARCH_NO_VIRT_TO_BUS=y
+ CONFIG_OF=y
++CONFIG_HZ=100
+ CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+ #
+-# Code maturity level options
++# General setup
+ #
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_BROKEN_ON_SMP=y
+ CONFIG_INIT_ENV_ARG_LIMIT=32
+-
+-#
+-# General setup
+-#
+ CONFIG_LOCALVERSION=""
+ CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+@@ -29,12 +26,23 @@ CONFIG_SYSVIPC_SYSCTL=y
+ CONFIG_POSIX_MQUEUE=y
+ # CONFIG_BSD_PROCESS_ACCT is not set
+ # CONFIG_TASKSTATS is not set
+-# CONFIG_USER_NS is not set
+ # CONFIG_AUDIT is not set
+ # CONFIG_IKCONFIG is not set
+ CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_RT_GROUP_SCHED=y
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
+ CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
+ # CONFIG_RELAY is not set
++CONFIG_NAMESPACES=y
++# CONFIG_UTS_NS is not set
++# CONFIG_IPC_NS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
+ CONFIG_BLK_DEV_INITRD=y
+ CONFIG_INITRAMFS_SOURCE=""
+ # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+@@ -49,6 +57,7 @@ CONFIG_HOTPLUG=y
+ CONFIG_PRINTK=y
+ CONFIG_BUG=y
+ CONFIG_ELF_CORE=y
++CONFIG_COMPAT_BRK=y
+ CONFIG_BASE_FULL=y
+ CONFIG_FUTEX=y
+ CONFIG_ANON_INODES=y
+@@ -61,6 +70,13 @@ CONFIG_VM_EVENT_COUNTERS=y
+ CONFIG_SLAB=y
+ # CONFIG_SLUB is not set
+ # CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_HAVE_KPROBES is not set
++# CONFIG_HAVE_KRETPROBES is not set
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SLABINFO=y
+ CONFIG_RT_MUTEXES=y
+ # CONFIG_TINY_SHMEM is not set
+ CONFIG_BASE_SMALL=0
+@@ -88,6 +104,7 @@ CONFIG_IOSCHED_CFQ=y
+ CONFIG_DEFAULT_CFQ=y
+ # CONFIG_DEFAULT_NOOP is not set
+ CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_CLASSIC_RCU=y
+
+ #
+ # General machine setup
+@@ -113,14 +130,13 @@ CONFIG_SUN_PM=y
+ CONFIG_PCI=y
+ CONFIG_PCI_SYSCALL=y
+ # CONFIG_ARCH_SUPPORTS_MSI is not set
++CONFIG_PCI_LEGACY=y
+ # CONFIG_PCI_DEBUG is not set
+ # CONFIG_NO_DMA is not set
+ CONFIG_SUN_OPENPROMFS=m
+ # CONFIG_SPARC_LED is not set
+ CONFIG_BINFMT_ELF=y
+-CONFIG_BINFMT_AOUT=y
+ CONFIG_BINFMT_MISC=m
+-CONFIG_SUNOS_EMUL=y
+ CONFIG_SELECT_MEMORY_MODEL=y
+ CONFIG_FLATMEM_MANUAL=y
+ # CONFIG_DISCONTIGMEM_MANUAL is not set
+@@ -128,6 +144,7 @@ CONFIG_FLATMEM_MANUAL=y
+ CONFIG_FLATMEM=y
+ CONFIG_FLAT_NODE_MEM_MAP=y
+ # CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+ CONFIG_SPLIT_PTLOCK_CPUS=4
+ # CONFIG_RESOURCES_64BIT is not set
+ CONFIG_ZONE_DMA_FLAG=1
+@@ -148,6 +165,7 @@ CONFIG_XFRM=y
+ CONFIG_XFRM_USER=m
+ # CONFIG_XFRM_SUB_POLICY is not set
+ # CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
+ CONFIG_NET_KEY=m
+ # CONFIG_NET_KEY_MIGRATE is not set
+ CONFIG_INET=y
+@@ -170,6 +188,7 @@ CONFIG_INET_TUNNEL=y
+ CONFIG_INET_XFRM_MODE_TRANSPORT=y
+ CONFIG_INET_XFRM_MODE_TUNNEL=y
+ CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
+ CONFIG_INET_DIAG=y
+ CONFIG_INET_TCP_DIAG=y
+ # CONFIG_TCP_CONG_ADVANCED is not set
+@@ -191,8 +210,10 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=m
+ CONFIG_INET6_XFRM_MODE_BEET=m
+ # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+ CONFIG_IPV6_SIT=m
++CONFIG_IPV6_NDISC_NODETYPE=y
+ CONFIG_IPV6_TUNNEL=m
+ # CONFIG_IPV6_MULTIPLE_TABLES is not set
++# CONFIG_IPV6_MROUTE is not set
+ # CONFIG_NETWORK_SECMARK is not set
+ # CONFIG_NETFILTER is not set
+ # CONFIG_IP_DCCP is not set
+@@ -214,10 +235,6 @@ CONFIG_SCTP_HMAC_MD5=y
+ # CONFIG_LAPB is not set
+ # CONFIG_ECONET is not set
+ # CONFIG_WAN_ROUTER is not set
+-
+-#
+-# QoS and/or fair queueing
+-#
+ # CONFIG_NET_SCHED is not set
+
+ #
+@@ -225,6 +242,7 @@ CONFIG_SCTP_HMAC_MD5=y
+ #
+ CONFIG_NET_PKTGEN=m
+ # CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
+ # CONFIG_IRDA is not set
+ # CONFIG_BT is not set
+ CONFIG_AF_RXRPC=m
+@@ -248,6 +266,7 @@ CONFIG_AF_RXRPC=m
+ #
+ # Generic Driver Options
+ #
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+ CONFIG_STANDALONE=y
+ CONFIG_PREVENT_FIRMWARE_BUILD=y
+ # CONFIG_FW_LOADER is not set
+@@ -271,7 +290,7 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
+ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_COUNT=16
+ CONFIG_BLK_DEV_RAM_SIZE=4096
+-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
++# CONFIG_BLK_DEV_XIP is not set
+ # CONFIG_CDROM_PKTCDVD is not set
+ # CONFIG_ATA_OVER_ETH is not set
+ CONFIG_MISC_DEVICES=y
+@@ -279,6 +298,8 @@ CONFIG_MISC_DEVICES=y
+ # CONFIG_EEPROM_93CX6 is not set
+ # CONFIG_SGI_IOC4 is not set
+ # CONFIG_TIFM_CORE is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++CONFIG_HAVE_IDE=y
+ # CONFIG_IDE is not set
+
+ #
+@@ -318,6 +339,7 @@ CONFIG_SCSI_SPI_ATTRS=y
+ # CONFIG_SCSI_FC_ATTRS is not set
+ # CONFIG_SCSI_ISCSI_ATTRS is not set
+ # CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
+ CONFIG_SCSI_LOWLEVEL=y
+ # CONFIG_ISCSI_TCP is not set
+ # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+@@ -338,6 +360,7 @@ CONFIG_SCSI_LOWLEVEL=y
+ # CONFIG_SCSI_IPS is not set
+ # CONFIG_SCSI_INITIO is not set
+ # CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_MVSAS is not set
+ # CONFIG_SCSI_STEX is not set
+ # CONFIG_SCSI_SYM53C8XX_2 is not set
+ # CONFIG_SCSI_QLOGIC_1280 is not set
+@@ -353,14 +376,7 @@ CONFIG_SCSI_SUNESP=y
+ # CONFIG_SCSI_SRP is not set
+ # CONFIG_ATA is not set
+ # CONFIG_MD is not set
+-
+-#
+-# Fusion MPT device support
+-#
+ # CONFIG_FUSION is not set
+-# CONFIG_FUSION_SPI is not set
+-# CONFIG_FUSION_FC is not set
+-# CONFIG_FUSION_SAS is not set
+
+ #
+ # IEEE 1394 (FireWire) support
+@@ -375,6 +391,7 @@ CONFIG_DUMMY=m
+ # CONFIG_MACVLAN is not set
+ # CONFIG_EQUALIZER is not set
+ CONFIG_TUN=m
++# CONFIG_VETH is not set
+ # CONFIG_ARCNET is not set
+ # CONFIG_PHYLIB is not set
+ CONFIG_NET_ETHERNET=y
+@@ -388,11 +405,20 @@ CONFIG_SUNQE=m
+ # CONFIG_NET_VENDOR_3COM is not set
+ # CONFIG_NET_TULIP is not set
+ # CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+ # CONFIG_NET_PCI is not set
++# CONFIG_B44 is not set
+ CONFIG_NETDEV_1000=y
+ # CONFIG_ACENIC is not set
+ # CONFIG_DL2K is not set
+ # CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_E1000E_ENABLED is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
+ # CONFIG_MYRI_SBUS is not set
+ # CONFIG_NS83820 is not set
+ # CONFIG_HAMACHI is not set
+@@ -409,11 +435,15 @@ CONFIG_NETDEV_1000=y
+ CONFIG_NETDEV_10000=y
+ # CONFIG_CHELSIO_T1 is not set
+ # CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
+ # CONFIG_IXGB is not set
+ # CONFIG_S2IO is not set
+ # CONFIG_MYRI10GE is not set
+ # CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
+ # CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
+ # CONFIG_TR is not set
+
+ #
+@@ -421,13 +451,13 @@ CONFIG_NETDEV_10000=y
+ #
+ # CONFIG_WLAN_PRE80211 is not set
+ # CONFIG_WLAN_80211 is not set
++# CONFIG_IWLWIFI_LEDS is not set
+ # CONFIG_WAN is not set
+ # CONFIG_FDDI is not set
+ # CONFIG_HIPPI is not set
+ # CONFIG_PPP is not set
+ # CONFIG_SLIP is not set
+ # CONFIG_NET_FC is not set
+-# CONFIG_SHAPER is not set
+ # CONFIG_NETCONSOLE is not set
+ # CONFIG_NETPOLL is not set
+ # CONFIG_NET_POLL_CONTROLLER is not set
+@@ -449,7 +479,6 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y
+ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ CONFIG_INPUT_JOYDEV=m
+-# CONFIG_INPUT_TSDEV is not set
+ CONFIG_INPUT_EVDEV=m
+ CONFIG_INPUT_EVBUG=m
+
+@@ -498,6 +527,7 @@ CONFIG_VT_CONSOLE=y
+ CONFIG_HW_CONSOLE=y
+ # CONFIG_VT_HW_CONSOLE_BINDING is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_NOZOMI is not set
+
+ #
+ # Serial drivers
+@@ -519,7 +549,6 @@ CONFIG_UNIX98_PTYS=y
+ CONFIG_LEGACY_PTYS=y
+ CONFIG_LEGACY_PTY_COUNT=256
+ # CONFIG_IPMI_HANDLER is not set
+-# CONFIG_WATCHDOG is not set
+ CONFIG_HW_RANDOM=m
+ CONFIG_JS_RTC=m
+ # CONFIG_R3964 is not set
+@@ -538,9 +567,9 @@ CONFIG_DEVPORT=y
+ # CONFIG_POWER_SUPPLY is not set
+ CONFIG_HWMON=y
+ # CONFIG_HWMON_VID is not set
+-# CONFIG_SENSORS_ABITUGURU is not set
+-# CONFIG_SENSORS_ABITUGURU3 is not set
++# CONFIG_SENSORS_I5K_AMB is not set
+ # CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
+ # CONFIG_SENSORS_IT87 is not set
+ # CONFIG_SENSORS_PC87360 is not set
+ # CONFIG_SENSORS_PC87427 is not set
+@@ -553,6 +582,14 @@ CONFIG_HWMON=y
+ # CONFIG_SENSORS_W83627HF is not set
+ # CONFIG_SENSORS_W83627EHF is not set
+ # CONFIG_HWMON_DEBUG_CHIP is not set
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
+
+ #
+ # Multifunction device drivers
+@@ -569,15 +606,15 @@ CONFIG_HWMON=y
+ #
+ # Graphics support
+ #
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
+ # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+ #
+ # Display device support
+ #
+ # CONFIG_DISPLAY_SUPPORT is not set
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+-# CONFIG_FB is not set
+
+ #
+ # Console display driver support
+@@ -592,6 +629,7 @@ CONFIG_DUMMY_CONSOLE=y
+ CONFIG_HID_SUPPORT=y
+ CONFIG_HID=y
+ # CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
+ CONFIG_USB_SUPPORT=y
+ CONFIG_USB_ARCH_HAS_HCD=y
+ CONFIG_USB_ARCH_HAS_OHCI=y
+@@ -601,34 +639,14 @@ CONFIG_USB_ARCH_HAS_EHCI=y
+ #
+ # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+ #
+-
+-#
+-# USB Gadget Support
+-#
+ # CONFIG_USB_GADGET is not set
+ # CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
+ # CONFIG_NEW_LEDS is not set
+ # CONFIG_INFINIBAND is not set
+-
+-#
+-# Real Time Clock
+-#
+ # CONFIG_RTC_CLASS is not set
+
+ #
+-# DMA Engine support
+-#
+-# CONFIG_DMA_ENGINE is not set
+-
+-#
+-# DMA Clients
+-#
+-
+-#
+-# DMA Devices
+-#
+-
+-#
+ # Userspace I/O
+ #
+ # CONFIG_UIO is not set
+@@ -664,18 +682,14 @@ CONFIG_FS_MBCACHE=y
+ CONFIG_FS_POSIX_ACL=y
+ CONFIG_XFS_FS=m
+ CONFIG_XFS_QUOTA=y
+-CONFIG_XFS_SECURITY=y
+ CONFIG_XFS_POSIX_ACL=y
+ CONFIG_XFS_RT=y
+-# CONFIG_GFS2_FS is not set
+ # CONFIG_OCFS2_FS is not set
+-# CONFIG_MINIX_FS is not set
+-CONFIG_ROMFS_FS=m
++CONFIG_DNOTIFY=y
+ CONFIG_INOTIFY=y
+ CONFIG_INOTIFY_USER=y
+ # CONFIG_QUOTA is not set
+ CONFIG_QUOTACTL=y
+-CONFIG_DNOTIFY=y
+ CONFIG_AUTOFS_FS=m
+ CONFIG_AUTOFS4_FS=m
+ # CONFIG_FUSE_FS is not set
+@@ -704,7 +718,6 @@ CONFIG_PROC_SYSCTL=y
+ CONFIG_SYSFS=y
+ # CONFIG_TMPFS is not set
+ # CONFIG_HUGETLB_PAGE is not set
+-CONFIG_RAMFS=y
+ # CONFIG_CONFIGFS_FS is not set
+
+ #
+@@ -721,14 +734,13 @@ CONFIG_BEFS_FS=m
+ # CONFIG_EFS_FS is not set
+ # CONFIG_CRAMFS is not set
+ # CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
+ # CONFIG_HPFS_FS is not set
+ # CONFIG_QNX4FS_FS is not set
++CONFIG_ROMFS_FS=m
+ # CONFIG_SYSV_FS is not set
+ # CONFIG_UFS_FS is not set
+-
+-#
+-# Network File Systems
+-#
++CONFIG_NETWORK_FILESYSTEMS=y
+ CONFIG_NFS_FS=y
+ # CONFIG_NFS_V3 is not set
+ # CONFIG_NFS_V4 is not set
+@@ -760,10 +772,6 @@ CONFIG_AFS_FS=m
+ # CONFIG_PARTITION_ADVANCED is not set
+ CONFIG_MSDOS_PARTITION=y
+ CONFIG_SUN_PARTITION=y
+-
+-#
+-# Native Language Support
+-#
+ CONFIG_NLS=y
+ CONFIG_NLS_DEFAULT="iso8859-1"
+ # CONFIG_NLS_CODEPAGE_437 is not set
+@@ -804,21 +812,14 @@ CONFIG_NLS_DEFAULT="iso8859-1"
+ # CONFIG_NLS_KOI8_R is not set
+ # CONFIG_NLS_KOI8_U is not set
+ # CONFIG_NLS_UTF8 is not set
+-
+-#
+-# Distributed Lock Manager
+-#
+ # CONFIG_DLM is not set
+
+ #
+-# Instrumentation Support
+-#
+-# CONFIG_PROFILING is not set
+-
+-#
+ # Kernel hacking
+ #
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+ # CONFIG_PRINTK_TIME is not set
++# CONFIG_ENABLE_WARN_DEPRECATED is not set
+ CONFIG_ENABLE_MUST_CHECK=y
+ CONFIG_MAGIC_SYSRQ=y
+ # CONFIG_UNUSED_SYMBOLS is not set
+@@ -842,9 +843,12 @@ CONFIG_DEBUG_BUGVERBOSE=y
+ # CONFIG_DEBUG_INFO is not set
+ # CONFIG_DEBUG_VM is not set
+ # CONFIG_DEBUG_LIST is not set
+-CONFIG_FORCED_INLINING=y
++# CONFIG_DEBUG_SG is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
+ # CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
+ # CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
+ # CONFIG_DEBUG_STACK_USAGE is not set
+
+ #
+@@ -853,9 +857,12 @@ CONFIG_FORCED_INLINING=y
+ CONFIG_KEYS=y
+ # CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+ # CONFIG_SECURITY is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+ CONFIG_CRYPTO=y
+ CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_AEAD=y
+ CONFIG_CRYPTO_BLKCIPHER=y
++# CONFIG_CRYPTO_SEQIV is not set
+ CONFIG_CRYPTO_HASH=y
+ CONFIG_CRYPTO_MANAGER=y
+ CONFIG_CRYPTO_HMAC=y
+@@ -873,6 +880,10 @@ CONFIG_CRYPTO_ECB=m
+ CONFIG_CRYPTO_CBC=y
+ CONFIG_CRYPTO_PCBC=m
+ # CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_XTS is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_CCM is not set
+ # CONFIG_CRYPTO_CRYPTD is not set
+ CONFIG_CRYPTO_DES=y
+ # CONFIG_CRYPTO_FCRYPT is not set
+@@ -887,11 +898,15 @@ CONFIG_CRYPTO_CAST6=m
+ CONFIG_CRYPTO_ARC4=m
+ # CONFIG_CRYPTO_KHAZAD is not set
+ # CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SALSA20 is not set
+ CONFIG_CRYPTO_DEFLATE=y
+ CONFIG_CRYPTO_MICHAEL_MIC=m
+ CONFIG_CRYPTO_CRC32C=m
+ # CONFIG_CRYPTO_CAMELLIA is not set
+ # CONFIG_CRYPTO_TEST is not set
++CONFIG_CRYPTO_AUTHENC=y
++# CONFIG_CRYPTO_LZO is not set
+ # CONFIG_CRYPTO_HW is not set
+
+ #
+diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
+index bf1b15d..59700aa 100644
+--- a/arch/sparc/kernel/Makefile
++++ b/arch/sparc/kernel/Makefile
+@@ -9,10 +9,10 @@ EXTRA_AFLAGS := -ansi
+ IRQ_OBJS := irq.o sun4m_irq.o sun4c_irq.o sun4d_irq.o
+ obj-y := entry.o wof.o wuf.o etrap.o rtrap.o traps.o $(IRQ_OBJS) \
+ process.o signal.o ioport.o setup.o idprom.o \
+- sys_sparc.o sunos_asm.o systbls.o \
+- time.o windows.o cpu.o devices.o sclow.o \
+- tadpole.o tick14.o ptrace.o sys_solaris.o \
+- unaligned.o una_asm.o muldiv.o semaphore.o \
++ sys_sparc.o systbls.o \
++ time.o windows.o cpu.o devices.o \
++ tadpole.o tick14.o ptrace.o \
++ unaligned.o una_asm.o muldiv.o \
+ prom.o of_device.o devres.o
+
+ devres-y = ../../../kernel/irq/devres.o
+@@ -25,7 +25,3 @@ obj-$(CONFIG_PCI) += ebus.o
+ obj-$(CONFIG_SUN_PM) += apc.o pmc.o
+ obj-$(CONFIG_MODULES) += module.o sparc_ksyms.o
+ obj-$(CONFIG_SPARC_LED) += led.o
+-
+-ifdef CONFIG_SUNOS_EMUL
+-obj-y += sys_sunos.o sunos_ioctl.o
+-endif
+diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
+index c2eed8f..484c83d 100644
+--- a/arch/sparc/kernel/entry.S
++++ b/arch/sparc/kernel/entry.S
+@@ -1186,36 +1186,6 @@ srmmu_fault:
+
+ RESTORE_ALL
+
+-#ifdef CONFIG_SUNOS_EMUL
+- /* SunOS uses syscall zero as the 'indirect syscall' it looks
+- * like indir_syscall(scall_num, arg0, arg1, arg2...); etc.
+- * This is complete brain damage.
+- */
+- .globl sunos_indir
+-sunos_indir:
+- mov %o7, %l4
+- cmp %o0, NR_SYSCALLS
+- blu,a 1f
+- sll %o0, 0x2, %o0
+-
+- sethi %hi(sunos_nosys), %l6
+- b 2f
+- or %l6, %lo(sunos_nosys), %l6
+-
+-1:
+- set sunos_sys_table, %l7
+- ld [%l7 + %o0], %l6
+-
+-2:
+- mov %o1, %o0
+- mov %o2, %o1
+- mov %o3, %o2
+- mov %o4, %o3
+- mov %o5, %o4
+- call %l6
+- mov %l4, %o7
+-#endif
+-
+ .align 4
+ .globl sys_nis_syscall
+ sys_nis_syscall:
+@@ -1232,6 +1202,16 @@ sys_execve:
+ call sparc_execve
+ mov %l5, %o7
+
++ .globl sunos_execv
++sunos_execv:
++ st %g0, [%sp + STACKFRAME_SZ + PT_I2]
++
++ call sparc_execve
++ add %sp, STACKFRAME_SZ, %o0
++
++ b ret_sys_call
++ ld [%sp + STACKFRAME_SZ + PT_I0], %o0
++
+ .align 4
+ .globl sys_pipe
+ sys_pipe:
+@@ -1394,7 +1374,7 @@ ret_from_fork:
+ b ret_sys_call
+ ld [%sp + STACKFRAME_SZ + PT_I0], %o0
+
+- /* Linux native and SunOS system calls enter here... */
++ /* Linux native system calls enter here... */
+ .align 4
+ .globl linux_sparc_syscall
+ linux_sparc_syscall:
+@@ -1429,7 +1409,6 @@ syscall_is_too_hard:
+
+ st %o0, [%sp + STACKFRAME_SZ + PT_I0]
+
+- .globl ret_sys_call
+ ret_sys_call:
+ ld [%curptr + TI_FLAGS], %l6
+ cmp %o0, -ERESTART_RESTARTBLOCK
+@@ -1472,170 +1451,6 @@ linux_syscall_trace2:
+ st %l2, [%sp + STACKFRAME_SZ + PT_NPC]
+
+
+- /*
+- * Solaris system calls and indirect system calls enter here.
+- *
+- * I have named the solaris indirect syscalls like that because
+- * it seems like Solaris has some fast path syscalls that can
+- * be handled as indirect system calls. - mig
+- */
+-
+-linux_syscall_for_solaris:
+- sethi %hi(sys_call_table), %l7
+- b linux_sparc_syscall
+- or %l7, %lo(sys_call_table), %l7
+-
+- .align 4
+- .globl solaris_syscall
+-solaris_syscall:
+- cmp %g1,59
+- be linux_syscall_for_solaris
+- cmp %g1,2
+- be linux_syscall_for_solaris
+- cmp %g1,42
+- be linux_syscall_for_solaris
+- cmp %g1,119
+- be,a linux_syscall_for_solaris
+- mov 2, %g1
+-1:
+- SAVE_ALL_HEAD
+- rd %wim, %l3
+-
+- wr %l0, PSR_ET, %psr
+- nop
+- nop
+- mov %i0, %l5
+-
+- call do_solaris_syscall
+- add %sp, STACKFRAME_SZ, %o0
+-
+- st %o0, [%sp + STACKFRAME_SZ + PT_I0]
+- set PSR_C, %g2
+- cmp %o0, -ERESTART_RESTARTBLOCK
+- bgeu 1f
+- ld [%sp + STACKFRAME_SZ + PT_PSR], %g3
+-
+- /* System call success, clear Carry condition code. */
+- andn %g3, %g2, %g3
+- clr %l6
+- b 2f
+- st %g3, [%sp + STACKFRAME_SZ + PT_PSR]
+-
+-1:
+- /* System call failure, set Carry condition code.
+- * Also, get abs(errno) to return to the process.
+- */
+- sub %g0, %o0, %o0
+- mov 1, %l6
+- st %o0, [%sp + STACKFRAME_SZ + PT_I0]
+- or %g3, %g2, %g3
+- st %g3, [%sp + STACKFRAME_SZ + PT_PSR]
+-
+- /* Advance the pc and npc over the trap instruction.
+- * If the npc is unaligned (has a 1 in the lower byte), it means
+- * the kernel does not want us to play magic (ie, skipping over
+- * traps). Mainly when the Solaris code wants to set some PC and
+- * nPC (setcontext).
+- */
+-2:
+- ld [%sp + STACKFRAME_SZ + PT_NPC], %l1 /* pc = npc */
+- andcc %l1, 1, %g0
+- bne 1f
+- add %l1, 0x4, %l2 /* npc = npc+4 */
+- st %l1, [%sp + STACKFRAME_SZ + PT_PC]
+- b ret_trap_entry
+- st %l2, [%sp + STACKFRAME_SZ + PT_NPC]
+-
+- /* kernel knows what it is doing, fixup npc and continue */
+-1:
+- sub %l1, 1, %l1
+- b ret_trap_entry
+- st %l1, [%sp + STACKFRAME_SZ + PT_NPC]
+-
+-#ifndef CONFIG_SUNOS_EMUL
+- .align 4
+- .globl sunos_syscall
+-sunos_syscall:
+- SAVE_ALL_HEAD
+- rd %wim, %l3
+- wr %l0, PSR_ET, %psr
+- nop
+- nop
+- mov %i0, %l5
+- call do_sunos_syscall
+- add %sp, STACKFRAME_SZ, %o0
+-#endif
+-
+- /* {net, open}bsd system calls enter here... */
+- .align 4
+- .globl bsd_syscall
+-bsd_syscall:
+- /* Direct access to user regs, must faster. */
+- cmp %g1, NR_SYSCALLS
+- blu,a 1f
+- sll %g1, 2, %l4
+-
+- set sys_ni_syscall, %l7
+- b bsd_is_too_hard
+- nop
+-
+-1:
+- ld [%l7 + %l4], %l7
+-
+- .globl bsd_is_too_hard
+-bsd_is_too_hard:
+- rd %wim, %l3
+- SAVE_ALL
+-
+- wr %l0, PSR_ET, %psr
+- WRITE_PAUSE
+-
+-2:
+- mov %i0, %o0
+- mov %i1, %o1
+- mov %i2, %o2
+- mov %i0, %l5
+- mov %i3, %o3
+- mov %i4, %o4
+- call %l7
+- mov %i5, %o5
+-
+- st %o0, [%sp + STACKFRAME_SZ + PT_I0]
+- set PSR_C, %g2
+- cmp %o0, -ERESTART_RESTARTBLOCK
+- bgeu 1f
+- ld [%sp + STACKFRAME_SZ + PT_PSR], %g3
+-
+- /* System call success, clear Carry condition code. */
+- andn %g3, %g2, %g3
+- clr %l6
+- b 2f
+- st %g3, [%sp + STACKFRAME_SZ + PT_PSR]
+-
+-1:
+- /* System call failure, set Carry condition code.
+- * Also, get abs(errno) to return to the process.
+- */
+- sub %g0, %o0, %o0
+-#if 0 /* XXX todo XXX */
+- sethi %hi(bsd_xlatb_rorl), %o3
+- or %o3, %lo(bsd_xlatb_rorl), %o3
+- sll %o0, 2, %o0
+- ld [%o3 + %o0], %o0
+-#endif
+- mov 1, %l6
+- st %o0, [%sp + STACKFRAME_SZ + PT_I0]
+- or %g3, %g2, %g3
+- st %g3, [%sp + STACKFRAME_SZ + PT_PSR]
+-
+- /* Advance the pc and npc over the trap instruction. */
+-2:
+- ld [%sp + STACKFRAME_SZ + PT_NPC], %l1 /* pc = npc */
+- add %l1, 0x4, %l2 /* npc = npc+4 */
+- st %l1, [%sp + STACKFRAME_SZ + PT_PC]
+- b ret_trap_entry
+- st %l2, [%sp + STACKFRAME_SZ + PT_NPC]
+-
+ /* Saving and restoring the FPU state is best done from lowlevel code.
+ *
+ * void fpsave(unsigned long *fpregs, unsigned long *fsr,
+diff --git a/arch/sparc/kernel/errtbls.c b/arch/sparc/kernel/errtbls.c
+deleted file mode 100644
+index ed14df7..0000000
+--- a/arch/sparc/kernel/errtbls.c
++++ /dev/null
+@@ -1,144 +0,0 @@
+-/* errtbls.c: Error number conversion tables.
+- *
+- * Copyright (C) 1995, 2007 David S. Miller (davem at davemloft.net)
+- *
+- * Based upon preliminary work which is:
+- *
+- * Copyright (C) 1995 Adrian M. Rodriguez (adrian at remus.rutgers.edu)
+- */
+-
+-#include <asm/solerrno.h> /* Solaris errnos */
+-
+-/* Here is the table which converts between Linux error number values
+- * to the equivalent under Solaris. Note that since the Linux ones
+- * have been set up to match exactly those of SunOS, no translation
+- * table is needed for that OS.
+- */
+-
+-int solaris_errno[] = {
+- 0,
+- SOL_EPERM,
+- SOL_ENOENT,
+- SOL_ESRCH,
+- SOL_EINTR,
+- SOL_EIO,
+- SOL_ENXIO,
+- SOL_E2BIG,
+- SOL_ENOEXEC,
+- SOL_EBADF,
+- SOL_ECHILD,
+- SOL_EAGAIN,
+- SOL_ENOMEM,
+- SOL_EACCES,
+- SOL_EFAULT,
+- SOL_NOTBLK,
+- SOL_EBUSY,
+- SOL_EEXIST,
+- SOL_EXDEV,
+- SOL_ENODEV,
+- SOL_ENOTDIR,
+- SOL_EISDIR,
+- SOL_EINVAL,
+- SOL_ENFILE,
+- SOL_EMFILE,
+- SOL_ENOTTY,
+- SOL_ETXTBSY,
+- SOL_EFBIG,
+- SOL_ENOSPC,
+- SOL_ESPIPE,
+- SOL_EROFS,
+- SOL_EMLINK,
+- SOL_EPIPE,
+- SOL_EDOM,
+- SOL_ERANGE,
+- SOL_EWOULDBLOCK,
+- SOL_EINPROGRESS,
+- SOL_EALREADY,
+- SOL_ENOTSOCK,
+- SOL_EDESTADDRREQ,
+- SOL_EMSGSIZE,
+- SOL_EPROTOTYPE,
+- SOL_ENOPROTOOPT,
+- SOL_EPROTONOSUPPORT,
+- SOL_ESOCKTNOSUPPORT,
+- SOL_EOPNOTSUPP,
+- SOL_EPFNOSUPPORT,
+- SOL_EAFNOSUPPORT,
+- SOL_EADDRINUSE,
+- SOL_EADDRNOTAVAIL,
+- SOL_ENETDOWN,
+- SOL_ENETUNREACH,
+- SOL_ENETRESET,
+- SOL_ECONNABORTED,
+- SOL_ECONNRESET,
+- SOL_ENOBUFS,
+- SOL_EISCONN,
+- SOL_ENOTONN,
+- SOL_ESHUTDOWN,
+- SOL_ETOOMANYREFS,
+- SOL_ETIMEDOUT,
+- SOL_ECONNREFUSED,
+- SOL_ELOOP,
+- SOL_ENAMETOOLONG,
+- SOL_EHOSTDOWN,
+- SOL_EHOSTUNREACH,
+- SOL_ENOTEMPTY,
+- SOL_EPROCLIM,
+- SOL_EUSERS,
+- SOL_EDQUOT,
+- SOL_ESTALE,
+- SOL_EREMOTE,
+- SOL_ENOSTR,
+- SOL_ETIME,
+- SOL_ENOSR,
+- SOL_ENOMSG,
+- SOL_EBADMSG,
+- SOL_IDRM,
+- SOL_EDEADLK,
+- SOL_ENOLCK,
+- SOL_ENONET,
+- SOL_ERREMOTE,
+- SOL_ENOLINK,
+- SOL_EADV,
+- SOL_ESRMNT,
+- SOL_ECOMM,
+- SOL_EPROTO,
+- SOL_EMULTIHOP,
+- SOL_EINVAL, /* EDOTDOT XXX??? */
+- SOL_REMCHG,
+- SOL_NOSYS,
+- SOL_STRPIPE,
+- SOL_EOVERFLOW,
+- SOL_EBADFD,
+- SOL_ECHRNG,
+- SOL_EL2NSYNC,
+- SOL_EL3HLT,
+- SOL_EL3RST,
+- SOL_NRNG,
+- SOL_EUNATCH,
+- SOL_ENOCSI,
+- SOL_EL2HLT,
+- SOL_EBADE,
+- SOL_EBADR,
+- SOL_EXFULL,
+- SOL_ENOANO,
+- SOL_EBADRQC,
+- SOL_EBADSLT,
+- SOL_EDEADLOCK,
+- SOL_EBFONT,
+- SOL_ELIBEXEC,
+- SOL_ENODATA,
+- SOL_ELIBBAD,
+- SOL_ENOPKG,
+- SOL_ELIBACC,
+- SOL_ENOTUNIQ,
+- SOL_ERESTART,
+- SOL_EUCLEAN,
+- SOL_ENOTNAM,
+- SOL_ENAVAIL,
+- SOL_EISNAM,
+- SOL_EREMOTEIO,
+- SOL_EILSEQ,
+- SOL_ELIBMAX,
+- SOL_ELIBSCN,
+-};
+diff --git a/arch/sparc/kernel/head.S b/arch/sparc/kernel/head.S
+index 9a219e8..b7f1e81 100644
+--- a/arch/sparc/kernel/head.S
++++ b/arch/sparc/kernel/head.S
+@@ -78,11 +78,6 @@ sun4e_notsup:
+ .asciz "Sparc-Linux sun4e support does not exist\n\n"
+ .align 4
+
+-#ifndef CONFIG_SUNOS_EMUL
+-#undef SUNOS_SYSCALL_TRAP
+-#define SUNOS_SYSCALL_TRAP SUNOS_NO_SYSCALL_TRAP
+-#endif
+-
+ /* The Sparc trap table, bootloader gives us control at _start. */
+ .text
+ .globl start, _stext, _start, __stext
+@@ -158,7 +153,7 @@ t_bad6f:BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x7
+ t_bad74:BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
+ t_bad79:BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
+ t_bad7e:BAD_TRAP(0x7e) BAD_TRAP(0x7f)
+-t_sunos:SUNOS_SYSCALL_TRAP /* SunOS System Call */
++t_bad80:BAD_TRAP(0x80) /* SunOS System Call */
+ t_sbkpt:BREAKPOINT_TRAP /* Software Breakpoint/KGDB */
+ t_divz: TRAP_ENTRY(0x82, do_hw_divzero) /* Divide by zero trap */
+ t_flwin:TRAP_ENTRY(0x83, do_flush_windows) /* Flush Windows Trap */
+@@ -166,8 +161,8 @@ t_clwin:BAD_TRAP(0x84) /* Clean Windows Trap */
+ t_rchk: BAD_TRAP(0x85) /* Range Check */
+ t_funal:BAD_TRAP(0x86) /* Fix Unaligned Access Trap */
+ t_iovf: BAD_TRAP(0x87) /* Integer Overflow Trap */
+-t_slowl:SOLARIS_SYSCALL_TRAP /* Slowaris System Call */
+-t_netbs:NETBSD_SYSCALL_TRAP /* Net-B.S. System Call */
++t_bad88:BAD_TRAP(0x88) /* Slowaris System Call */
++t_bad89:BAD_TRAP(0x89) /* Net-B.S. System Call */
+ t_bad8a:BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c) BAD_TRAP(0x8d) BAD_TRAP(0x8e)
+ t_bad8f:BAD_TRAP(0x8f)
+ t_linux:LINUX_SYSCALL_TRAP /* Linux System Call */
+@@ -178,7 +173,7 @@ t_getcc:GETCC_TRAP /* Get Condition Codes */
+ t_setcc:SETCC_TRAP /* Set Condition Codes */
+ t_getpsr:GETPSR_TRAP /* Get PSR Register */
+ t_bada3:BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
+-t_slowi:INDIRECT_SOLARIS_SYSCALL(156)
++t_bada7:BAD_TRAP(0xa7)
+ t_bada8:BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
+ t_badac:BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
+ t_badb1:BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
+@@ -243,19 +238,19 @@ trapbase_cpu1:
+ BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
+ BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
+ BAD_TRAP(0x7e) BAD_TRAP(0x7f)
+- SUNOS_SYSCALL_TRAP
++ BAD_TRAP(0x80)
+ BREAKPOINT_TRAP
+ TRAP_ENTRY(0x82, do_hw_divzero)
+ TRAP_ENTRY(0x83, do_flush_windows) BAD_TRAP(0x84) BAD_TRAP(0x85)
+- BAD_TRAP(0x86) BAD_TRAP(0x87) SOLARIS_SYSCALL_TRAP
+- NETBSD_SYSCALL_TRAP BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
++ BAD_TRAP(0x86) BAD_TRAP(0x87) BAD_TRAP(0x88)
++ BAD_TRAP(0x89) BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
+ BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f)
+ LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
+ BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
+ BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
+ BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP
+ BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
+- INDIRECT_SOLARIS_SYSCALL(156) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
++ BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
+ BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
+ BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
+ BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
+@@ -311,19 +306,19 @@ trapbase_cpu2:
+ BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
+ BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
+ BAD_TRAP(0x7e) BAD_TRAP(0x7f)
+- SUNOS_SYSCALL_TRAP
++ BAD_TRAP(0x80)
+ BREAKPOINT_TRAP
+ TRAP_ENTRY(0x82, do_hw_divzero)
+ TRAP_ENTRY(0x83, do_flush_windows) BAD_TRAP(0x84) BAD_TRAP(0x85)
+- BAD_TRAP(0x86) BAD_TRAP(0x87) SOLARIS_SYSCALL_TRAP
+- NETBSD_SYSCALL_TRAP BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
++ BAD_TRAP(0x86) BAD_TRAP(0x87) BAD_TRAP(0x88)
++ BAD_TRAP(0x89) BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
+ BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f)
+ LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
+ BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
+ BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
+ BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP
+ BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
+- INDIRECT_SOLARIS_SYSCALL(156) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
++ BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
+ BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
+ BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
+ BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
+@@ -379,19 +374,19 @@ trapbase_cpu3:
+ BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
+ BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
+ BAD_TRAP(0x7e) BAD_TRAP(0x7f)
+- SUNOS_SYSCALL_TRAP
++ BAD_TRAP(0x80)
+ BREAKPOINT_TRAP
+ TRAP_ENTRY(0x82, do_hw_divzero)
+ TRAP_ENTRY(0x83, do_flush_windows) BAD_TRAP(0x84) BAD_TRAP(0x85)
+- BAD_TRAP(0x86) BAD_TRAP(0x87) SOLARIS_SYSCALL_TRAP
+- NETBSD_SYSCALL_TRAP BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
++ BAD_TRAP(0x86) BAD_TRAP(0x87) BAD_TRAP(0x88)
++ BAD_TRAP(0x89) BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c)
+ BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f)
+ LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
+ BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
+ BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
+ BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP
+ BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
+- INDIRECT_SOLARIS_SYSCALL(156) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
++ BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
+ BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
+ BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
+ BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
+diff --git a/arch/sparc/kernel/sclow.S b/arch/sparc/kernel/sclow.S
+deleted file mode 100644
+index 136e37c..0000000
+--- a/arch/sparc/kernel/sclow.S
++++ /dev/null
+@@ -1,86 +0,0 @@
+-/* sclow.S: Low level special syscall handling.
+- * Basically these are cases where we can completely
+- * handle the system call without saving any state
+- * because we know that the process will not sleep.
+- *
+- * Copyright (C) 1996 David S. Miller (davem at caip.rutgers.edu)
+- */
+-
+-#include <asm/ptrace.h>
+-#include <asm/asm-offsets.h>
+-#include <asm/errno.h>
+-#include <asm/winmacro.h>
+-#include <asm/thread_info.h>
+-#include <asm/psr.h>
+-#include <asm/page.h>
+-
+-#define CC_AND_RETT \
+- set PSR_C, %l4; \
+- andn %l0, %l4, %l4; \
+- wr %l4, 0x0, %psr; \
+- nop; nop; nop; \
+- jmp %l2; \
+- rett %l2 + 4;
+-
+-#define SC_AND_RETT \
+- set PSR_C, %l4; \
+- or %l0, %l4, %l4; \
+- wr %l4, 0x0, %psr; \
+- nop; nop; nop; \
+- jmp %l2; \
+- rett %l2 + 4;
+-
+-#define LABEL(func) func##_low
+-
+- .globl LABEL(sunosnop)
+-LABEL(sunosnop):
+- CC_AND_RETT
+-
+-#if (ASIZ_task_uid == 2 && ASIZ_task_euid == 2)
+- .globl LABEL(sunosgetuid)
+-LABEL(sunosgetuid):
+- LOAD_CURRENT(l4, l5)
+- ld [%l4 + TI_TASK], %l4
+- lduh [%l4 + AOFF_task_uid], %i0
+- lduh [%l4 + AOFF_task_euid], %i1
+- CC_AND_RETT
+-#endif
+-
+-#if (ASIZ_task_gid == 2 && ASIZ_task_egid == 2)
+- .globl LABEL(sunosgetgid)
+-LABEL(sunosgetgid):
+- LOAD_CURRENT(l4, l5)
+- ld [%l4 + TI_TASK], %l4
+- lduh [%l4 + AOFF_task_gid], %i0
+- lduh [%l4 + AOFF_task_egid], %i1
+- CC_AND_RETT
+-#endif
+-
+- .globl LABEL(sunosmctl)
+-LABEL(sunosmctl):
+- mov 0, %i0
+- CC_AND_RETT
+-
+- .globl LABEL(sunosgdtsize)
+-LABEL(sunosgdtsize):
+- mov 256, %i0
+- CC_AND_RETT
+-
+- .globl LABEL(getpagesize)
+-LABEL(getpagesize):
+- set PAGE_SIZE, %i0
+- CC_AND_RETT
+-
+- /* XXX sys_nice() XXX */
+- /* XXX sys_setpriority() XXX */
+- /* XXX sys_getpriority() XXX */
+- /* XXX sys_setregid() XXX */
+- /* XXX sys_setgid() XXX */
+- /* XXX sys_setreuid() XXX */
+- /* XXX sys_setuid() XXX */
+- /* XXX sys_setfsuid() XXX */
+- /* XXX sys_setfsgid() XXX */
+- /* XXX sys_setpgid() XXX */
+- /* XXX sys_getpgid() XXX */
+- /* XXX sys_setsid() XXX */
+- /* XXX sys_getsid() XXX */
+diff --git a/arch/sparc/kernel/semaphore.c b/arch/sparc/kernel/semaphore.c
+deleted file mode 100644
+index 0c37c1a..0000000
+--- a/arch/sparc/kernel/semaphore.c
++++ /dev/null
+@@ -1,155 +0,0 @@
+-/* $Id: semaphore.c,v 1.7 2001/04/18 21:06:05 davem Exp $ */
+-
+-/* sparc32 semaphore implementation, based on i386 version */
+-
+-#include <linux/sched.h>
+-#include <linux/errno.h>
+-#include <linux/init.h>
+-
+-#include <asm/semaphore.h>
+-
+-/*
+- * Semaphores are implemented using a two-way counter:
+- * The "count" variable is decremented for each process
+- * that tries to acquire the semaphore, while the "sleeping"
+- * variable is a count of such acquires.
+- *
+- * Notably, the inline "up()" and "down()" functions can
+- * efficiently test if they need to do any extra work (up
+- * needs to do something only if count was negative before
+- * the increment operation.
+- *
+- * "sleeping" and the contention routine ordering is
+- * protected by the semaphore spinlock.
+- *
+- * Note that these functions are only called when there is
+- * contention on the lock, and as such all this is the
+- * "non-critical" part of the whole semaphore business. The
+- * critical part is the inline stuff in <asm/semaphore.h>
+- * where we want to avoid any extra jumps and calls.
+- */
+-
+-/*
+- * Logic:
+- * - only on a boundary condition do we need to care. When we go
+- * from a negative count to a non-negative, we wake people up.
+- * - when we go from a non-negative count to a negative do we
+- * (a) synchronize with the "sleeper" count and (b) make sure
+- * that we're on the wakeup list before we synchronize so that
+- * we cannot lose wakeup events.
+- */
+-
+-void __up(struct semaphore *sem)
+-{
+- wake_up(&sem->wait);
+-}
+-
+-static DEFINE_SPINLOCK(semaphore_lock);
+-
+-void __sched __down(struct semaphore * sem)
+-{
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+- tsk->state = TASK_UNINTERRUPTIBLE;
+- add_wait_queue_exclusive(&sem->wait, &wait);
+-
+- spin_lock_irq(&semaphore_lock);
+- sem->sleepers++;
+- for (;;) {
+- int sleepers = sem->sleepers;
+-
+- /*
+- * Add "everybody else" into it. They aren't
+- * playing, because we own the spinlock.
+- */
+- if (!atomic24_add_negative(sleepers - 1, &sem->count)) {
+- sem->sleepers = 0;
+- break;
+- }
+- sem->sleepers = 1; /* us - see -1 above */
+- spin_unlock_irq(&semaphore_lock);
+-
+- schedule();
+- tsk->state = TASK_UNINTERRUPTIBLE;
+- spin_lock_irq(&semaphore_lock);
+- }
+- spin_unlock_irq(&semaphore_lock);
+- remove_wait_queue(&sem->wait, &wait);
+- tsk->state = TASK_RUNNING;
+- wake_up(&sem->wait);
+-}
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+- int retval = 0;
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+- tsk->state = TASK_INTERRUPTIBLE;
+- add_wait_queue_exclusive(&sem->wait, &wait);
+-
+- spin_lock_irq(&semaphore_lock);
+- sem->sleepers ++;
+- for (;;) {
+- int sleepers = sem->sleepers;
+-
+- /*
+- * With signals pending, this turns into
+- * the trylock failure case - we won't be
+- * sleeping, and we* can't get the lock as
+- * it has contention. Just correct the count
+- * and exit.
+- */
+- if (signal_pending(current)) {
+- retval = -EINTR;
+- sem->sleepers = 0;
+- atomic24_add(sleepers, &sem->count);
+- break;
+- }
+-
+- /*
+- * Add "everybody else" into it. They aren't
+- * playing, because we own the spinlock. The
+- * "-1" is because we're still hoping to get
+- * the lock.
+- */
+- if (!atomic24_add_negative(sleepers - 1, &sem->count)) {
+- sem->sleepers = 0;
+- break;
+- }
+- sem->sleepers = 1; /* us - see -1 above */
+- spin_unlock_irq(&semaphore_lock);
+-
+- schedule();
+- tsk->state = TASK_INTERRUPTIBLE;
+- spin_lock_irq(&semaphore_lock);
+- }
+- spin_unlock_irq(&semaphore_lock);
+- tsk->state = TASK_RUNNING;
+- remove_wait_queue(&sem->wait, &wait);
+- wake_up(&sem->wait);
+- return retval;
+-}
+-
+-/*
+- * Trylock failed - make sure we correct for
+- * having decremented the count.
+- */
+-int __down_trylock(struct semaphore * sem)
+-{
+- int sleepers;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&semaphore_lock, flags);
+- sleepers = sem->sleepers + 1;
+- sem->sleepers = 0;
+-
+- /*
+- * Add "everybody else" and us into it. They aren't
+- * playing, because we own the spinlock.
+- */
+- if (!atomic24_add_negative(sleepers, &sem->count))
+- wake_up(&sem->wait);
+-
+- spin_unlock_irqrestore(&semaphore_lock, flags);
+- return 1;
+-}
+diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c
+index 9994cac..3e849e8 100644
+--- a/arch/sparc/kernel/signal.c
++++ b/arch/sparc/kernel/signal.c
+@@ -22,7 +22,6 @@
+
+ #include <asm/uaccess.h>
+ #include <asm/ptrace.h>
+-#include <asm/svr4.h>
+ #include <asm/pgalloc.h>
+ #include <asm/pgtable.h>
+ #include <asm/cacheflush.h> /* flush_sig_insns */
+@@ -106,11 +105,6 @@ static int _sigpause_common(old_sigset_t set)
+ return -ERESTARTNOHAND;
+ }
+
+-asmlinkage int sys_sigpause(unsigned int set)
+-{
+- return _sigpause_common(set);
+-}
+-
+ asmlinkage int sys_sigsuspend(old_sigset_t set)
+ {
+ return _sigpause_common(set);
+@@ -454,7 +448,6 @@ setup_frame(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *old
+ break;
+ case SIGSYS:
+ if (info->si_code == (__SI_FAULT|0x100)) {
+- /* See sys_sunos.c */
+ sig_code = info->si_trapno;
+ break;
+ }
+@@ -676,291 +669,17 @@ sigsegv:
+ force_sigsegv(signo, current);
+ }
+
+-/* Setup a Solaris stack frame */
+-static inline void
+-setup_svr4_frame(struct sigaction *sa, unsigned long pc, unsigned long npc,
+- struct pt_regs *regs, int signr, sigset_t *oldset)
+-{
+- svr4_signal_frame_t __user *sfp;
+- svr4_gregset_t __user *gr;
+- svr4_siginfo_t __user *si;
+- svr4_mcontext_t __user *mc;
+- svr4_gwindows_t __user *gw;
+- svr4_ucontext_t __user *uc;
+- svr4_sigset_t setv;
+- struct thread_info *tp = current_thread_info();
+- int window = 0, err;
+-
+- synchronize_user_stack();
+- sfp = (svr4_signal_frame_t __user *)
+- get_sigframe(sa, regs, SVR4_SF_ALIGNED + sizeof(struct reg_window));
+-
+- if (invalid_frame_pointer(sfp, sizeof(*sfp)))
+- goto sigill_and_return;
+-
+- /* Start with a clean frame pointer and fill it */
+- err = __clear_user(sfp, sizeof(*sfp));
+-
+- /* Setup convenience variables */
+- si = &sfp->si;
+- uc = &sfp->uc;
+- gw = &sfp->gw;
+- mc = &uc->mcontext;
+- gr = &mc->greg;
+-
+- /* FIXME: where am I supposed to put this?
+- * sc->sigc_onstack = old_status;
+- * anyways, it does not look like it is used for anything at all.
+- */
+- setv.sigbits[0] = oldset->sig[0];
+- setv.sigbits[1] = oldset->sig[1];
+- if (_NSIG_WORDS >= 4) {
+- setv.sigbits[2] = oldset->sig[2];
+- setv.sigbits[3] = oldset->sig[3];
+- err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t));
+- } else
+- err |= __copy_to_user(&uc->sigmask, &setv,
+- 2 * sizeof(unsigned int));
+-
+- /* Store registers */
+- err |= __put_user(regs->pc, &((*gr)[SVR4_PC]));
+- err |= __put_user(regs->npc, &((*gr)[SVR4_NPC]));
+- err |= __put_user(regs->psr, &((*gr)[SVR4_PSR]));
+- err |= __put_user(regs->y, &((*gr)[SVR4_Y]));
+-
+- /* Copy g[1..7] and o[0..7] registers */
+- err |= __copy_to_user(&(*gr)[SVR4_G1], ®s->u_regs[UREG_G1],
+- sizeof(long) * 7);
+- err |= __copy_to_user(&(*gr)[SVR4_O0], ®s->u_regs[UREG_I0],
+- sizeof(long) * 8);
+-
+- /* Setup sigaltstack */
+- err |= __put_user(current->sas_ss_sp, &uc->stack.sp);
+- err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags);
+- err |= __put_user(current->sas_ss_size, &uc->stack.size);
+-
+- /* Save the currently window file: */
+-
+- /* 1. Link sfp->uc->gwins to our windows */
+- err |= __put_user(gw, &mc->gwin);
+-
+- /* 2. Number of windows to restore at setcontext(): */
+- err |= __put_user(tp->w_saved, &gw->count);
+-
+- /* 3. Save each valid window
+- * Currently, it makes a copy of the windows from the kernel copy.
+- * David's code for SunOS, makes the copy but keeps the pointer to
+- * the kernel. My version makes the pointer point to a userland
+- * copy of those. Mhm, I wonder if I shouldn't just ignore those
+- * on setcontext and use those that are on the kernel, the signal
+- * handler should not be modyfing those, mhm.
+- *
+- * These windows are just used in case synchronize_user_stack failed
+- * to flush the user windows.
+- */
+- for (window = 0; window < tp->w_saved; window++) {
+- err |= __put_user((int __user *) &(gw->win[window]), &gw->winptr[window]);
+- err |= __copy_to_user(&gw->win[window],
+- &tp->reg_window[window],
+- sizeof(svr4_rwindow_t));
+- err |= __put_user(0, gw->winptr[window]);
+- }
+-
+- /* 4. We just pay attention to the gw->count field on setcontext */
+- tp->w_saved = 0; /* So process is allowed to execute. */
+-
+- /* Setup the signal information. Solaris expects a bunch of
+- * information to be passed to the signal handler, we don't provide
+- * that much currently, should use siginfo.
+- */
+- err |= __put_user(signr, &si->siginfo.signo);
+- err |= __put_user(SVR4_SINOINFO, &si->siginfo.code);
+- if (err)
+- goto sigsegv;
+-
+- regs->u_regs[UREG_FP] = (unsigned long) sfp;
+- regs->pc = (unsigned long) sa->sa_handler;
+- regs->npc = (regs->pc + 4);
+-
+- /* Arguments passed to signal handler */
+- if (regs->u_regs[14]){
+- struct reg_window __user *rw = (struct reg_window __user *)
+- regs->u_regs[14];
+-
+- err |= __put_user(signr, &rw->ins[0]);
+- err |= __put_user(si, &rw->ins[1]);
+- err |= __put_user(uc, &rw->ins[2]);
+- err |= __put_user(sfp, &rw->ins[6]); /* frame pointer */
+- if (err)
+- goto sigsegv;
+-
+- regs->u_regs[UREG_I0] = signr;
+- regs->u_regs[UREG_I1] = (unsigned long) si;
+- regs->u_regs[UREG_I2] = (unsigned long) uc;
+- }
+- return;
+-
+-sigill_and_return:
+- do_exit(SIGILL);
+-sigsegv:
+- force_sigsegv(signr, current);
+-}
+-
+-asmlinkage int svr4_getcontext(svr4_ucontext_t __user *uc, struct pt_regs *regs)
+-{
+- svr4_gregset_t __user *gr;
+- svr4_mcontext_t __user *mc;
+- svr4_sigset_t setv;
+- int err = 0;
+-
+- synchronize_user_stack();
+-
+- if (current_thread_info()->w_saved)
+- return -EFAULT;
+-
+- err = clear_user(uc, sizeof(*uc));
+- if (err)
+- return -EFAULT;
+-
+- /* Setup convenience variables */
+- mc = &uc->mcontext;
+- gr = &mc->greg;
+-
+- setv.sigbits[0] = current->blocked.sig[0];
+- setv.sigbits[1] = current->blocked.sig[1];
+- if (_NSIG_WORDS >= 4) {
+- setv.sigbits[2] = current->blocked.sig[2];
+- setv.sigbits[3] = current->blocked.sig[3];
+- err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t));
+- } else
+- err |= __copy_to_user(&uc->sigmask, &setv,
+- 2 * sizeof(unsigned int));
+-
+- /* Store registers */
+- err |= __put_user(regs->pc, &uc->mcontext.greg[SVR4_PC]);
+- err |= __put_user(regs->npc, &uc->mcontext.greg[SVR4_NPC]);
+- err |= __put_user(regs->psr, &uc->mcontext.greg[SVR4_PSR]);
+- err |= __put_user(regs->y, &uc->mcontext.greg[SVR4_Y]);
+-
+- /* Copy g[1..7] and o[0..7] registers */
+- err |= __copy_to_user(&(*gr)[SVR4_G1], ®s->u_regs[UREG_G1],
+- sizeof(uint) * 7);
+- err |= __copy_to_user(&(*gr)[SVR4_O0], ®s->u_regs[UREG_I0],
+- sizeof(uint) * 8);
+-
+- /* Setup sigaltstack */
+- err |= __put_user(current->sas_ss_sp, &uc->stack.sp);
+- err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags);
+- err |= __put_user(current->sas_ss_size, &uc->stack.size);
+-
+- /* The register file is not saved
+- * we have already stuffed all of it with sync_user_stack
+- */
+- return (err ? -EFAULT : 0);
+-}
+-
+-/* Set the context for a svr4 application, this is Solaris way to sigreturn */
+-asmlinkage int svr4_setcontext(svr4_ucontext_t __user *c, struct pt_regs *regs)
+-{
+- svr4_gregset_t __user *gr;
+- unsigned long pc, npc, psr;
+- mm_segment_t old_fs;
+- sigset_t set;
+- svr4_sigset_t setv;
+- int err;
+- stack_t st;
+-
+- /* Fixme: restore windows, or is this already taken care of in
+- * svr4_setup_frame when sync_user_windows is done?
+- */
+- flush_user_windows();
+-
+- if (current_thread_info()->w_saved)
+- goto sigsegv_and_return;
+-
+- if (((unsigned long) c) & 3)
+- goto sigsegv_and_return;
+-
+- if (!__access_ok((unsigned long)c, sizeof(*c)))
+- goto sigsegv_and_return;
+-
+- /* Check for valid PC and nPC */
+- gr = &c->mcontext.greg;
+- err = __get_user(pc, &((*gr)[SVR4_PC]));
+- err |= __get_user(npc, &((*gr)[SVR4_NPC]));
+-
+- if ((pc | npc) & 3)
+- goto sigsegv_and_return;
+-
+- /* Retrieve information from passed ucontext */
+- /* note that nPC is ored a 1, this is used to inform entry.S */
+- /* that we don't want it to mess with our PC and nPC */
+-
+- /* This is pretty much atomic, no amount locking would prevent
+- * the races which exist anyways.
+- */
+- err |= __copy_from_user(&setv, &c->sigmask, sizeof(svr4_sigset_t));
+-
+- err |= __get_user(st.ss_sp, &c->stack.sp);
+- err |= __get_user(st.ss_flags, &c->stack.flags);
+- err |= __get_user(st.ss_size, &c->stack.size);
+-
+- if (err)
+- goto sigsegv_and_return;
+-
+- /* It is more difficult to avoid calling this function than to
+- call it and ignore errors. */
+- old_fs = get_fs();
+- set_fs(KERNEL_DS);
+- do_sigaltstack((const stack_t __user *) &st, NULL,
+- regs->u_regs[UREG_I6]);
+- set_fs(old_fs);
+-
+- set.sig[0] = setv.sigbits[0];
+- set.sig[1] = setv.sigbits[1];
+- if (_NSIG_WORDS >= 4) {
+- set.sig[2] = setv.sigbits[2];
+- set.sig[3] = setv.sigbits[3];
+- }
+- sigdelsetmask(&set, ~_BLOCKABLE);
+- spin_lock_irq(¤t->sighand->siglock);
+- current->blocked = set;
+- recalc_sigpending();
+- spin_unlock_irq(¤t->sighand->siglock);
+- regs->pc = pc;
+- regs->npc = npc | 1;
+- err |= __get_user(regs->y, &((*gr)[SVR4_Y]));
+- err |= __get_user(psr, &((*gr)[SVR4_PSR]));
+- regs->psr &= ~(PSR_ICC);
+- regs->psr |= (psr & PSR_ICC);
+-
+- /* Restore g[1..7] and o[0..7] registers */
+- err |= __copy_from_user(®s->u_regs[UREG_G1], &(*gr)[SVR4_G1],
+- sizeof(long) * 7);
+- err |= __copy_from_user(®s->u_regs[UREG_I0], &(*gr)[SVR4_O0],
+- sizeof(long) * 8);
+- return (err ? -EFAULT : 0);
+-
+-sigsegv_and_return:
+- force_sig(SIGSEGV, current);
+- return -EFAULT;
+-}
+-
+ static inline void
+ handle_signal(unsigned long signr, struct k_sigaction *ka,
+- siginfo_t *info, sigset_t *oldset, struct pt_regs *regs,
+- int svr4_signal)
++ siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
+ {
+- if (svr4_signal)
+- setup_svr4_frame(&ka->sa, regs->pc, regs->npc, regs, signr, oldset);
+- else {
+- if (ka->sa.sa_flags & SA_SIGINFO)
+- new_setup_rt_frame(ka, regs, signr, oldset, info);
+- else if (current->thread.new_signal)
+- new_setup_frame(ka, regs, signr, oldset);
+- else
+- setup_frame(&ka->sa, regs, signr, oldset, info);
+- }
++ if (ka->sa.sa_flags & SA_SIGINFO)
++ new_setup_rt_frame(ka, regs, signr, oldset, info);
++ else if (current->thread.new_signal)
++ new_setup_frame(ka, regs, signr, oldset);
++ else
++ setup_frame(&ka->sa, regs, signr, oldset, info);
++
+ spin_lock_irq(¤t->sighand->siglock);
+ sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NOMASK))
+@@ -1002,17 +721,6 @@ asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int rest
+ int signr;
+ sigset_t *oldset;
+
+- /*
+- * XXX Disable svr4 signal handling until solaris emulation works.
+- * It is buggy - Anton
+- */
+-#define SVR4_SIGNAL_BROKEN 1
+-#ifdef SVR4_SIGNAL_BROKEN
+- int svr4_signal = 0;
+-#else
+- int svr4_signal = current->personality == PER_SVR4;
+-#endif
+-
+ cookie.restart_syscall = restart_syscall;
+ cookie.orig_i0 = orig_i0;
+
+@@ -1025,8 +733,8 @@ asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int rest
+ if (signr > 0) {
+ if (cookie.restart_syscall)
+ syscall_restart(cookie.orig_i0, regs, &ka.sa);
+- handle_signal(signr, &ka, &info, oldset,
+- regs, svr4_signal);
++ handle_signal(signr, &ka, &info, oldset, regs);
++
+ /* a signal was successfully delivered; the saved
+ * sigmask will have been stored in the signal frame,
+ * and will be restored by sigreturn, so we can simply
+diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
+index c1025e5..0bcf98a 100644
+--- a/arch/sparc/kernel/sparc_ksyms.c
++++ b/arch/sparc/kernel/sparc_ksyms.c
+@@ -36,12 +36,10 @@
+ #include <asm/io.h>
+ #include <asm/irq.h>
+ #include <asm/idprom.h>
+-#include <asm/svr4.h>
+ #include <asm/head.h>
+ #include <asm/smp.h>
+ #include <asm/mostek.h>
+ #include <asm/ptrace.h>
+-#include <asm/user.h>
+ #include <asm/uaccess.h>
+ #include <asm/checksum.h>
+ #ifdef CONFIG_SBUS
+@@ -62,8 +60,6 @@ struct poll {
+ short revents;
+ };
+
+-extern int svr4_getcontext (svr4_ucontext_t *, struct pt_regs *);
+-extern int svr4_setcontext (svr4_ucontext_t *, struct pt_regs *);
+ extern void (*__copy_1page)(void *, const void *);
+ extern void __memmove(void *, const void *, __kernel_size_t);
+ extern void (*bzero_1page)(void *);
+@@ -107,11 +103,6 @@ EXPORT_SYMBOL(___rw_read_try);
+ EXPORT_SYMBOL(___rw_read_exit);
+ EXPORT_SYMBOL(___rw_write_enter);
+ #endif
+-/* semaphores */
+-EXPORT_SYMBOL(__up);
+-EXPORT_SYMBOL(__down);
+-EXPORT_SYMBOL(__down_trylock);
+-EXPORT_SYMBOL(__down_interruptible);
+
+ EXPORT_SYMBOL(sparc_valid_addr_bitmap);
+ EXPORT_SYMBOL(phys_base);
+@@ -209,10 +200,6 @@ EXPORT_SYMBOL(kmap_atomic);
+ EXPORT_SYMBOL(kunmap_atomic);
+ #endif
+
+-/* Solaris/SunOS binary compatibility */
+-EXPORT_SYMBOL(svr4_setcontext);
+-EXPORT_SYMBOL(svr4_getcontext);
+-
+ /* prom symbols */
+ EXPORT_SYMBOL(idprom);
+ EXPORT_SYMBOL(prom_root_node);
+diff --git a/arch/sparc/kernel/sunos_asm.S b/arch/sparc/kernel/sunos_asm.S
+deleted file mode 100644
+index 07fe860..0000000
+--- a/arch/sparc/kernel/sunos_asm.S
++++ /dev/null
+@@ -1,67 +0,0 @@
+-/* $Id: sunos_asm.S,v 1.15 2000/01/11 17:33:21 jj Exp $
+- * sunos_asm.S: SunOS system calls which must have a low-level
+- * entry point to operate correctly.
+- *
+- * Copyright (C) 1995 David S. Miller (davem at caip.rutgers.edu)
+- *
+- * Based upon preliminary work which is:
+- *
+- * Copyright (C) 1995 Adrian M. Rodriguez (adrian at remus.rutgers.edu)
+- */
+-
+-#include <asm/ptrace.h>
+-
+- .text
+- .align 4
+-
+- /* When calling ret_sys_call, %o0 should contain the same
+- * value as in [%sp + STACKFRAME_SZ + PT_I0] */
+-
+- /* SunOS getpid() returns pid in %o0 and ppid in %o1 */
+- .globl sunos_getpid
+-sunos_getpid:
+- call sys_getppid
+- nop
+-
+- call sys_getpid
+- st %o0, [%sp + STACKFRAME_SZ + PT_I1]
+-
+- b ret_sys_call
+- st %o0, [%sp + STACKFRAME_SZ + PT_I0]
+-
+- /* SunOS getuid() returns uid in %o0 and euid in %o1 */
+- .globl sunos_getuid
+-sunos_getuid:
+- call sys_geteuid16
+- nop
+-
+- call sys_getuid16
+- st %o0, [%sp + STACKFRAME_SZ + PT_I1]
+-
+- b ret_sys_call
+- st %o0, [%sp + STACKFRAME_SZ + PT_I0]
+-
+- /* SunOS getgid() returns gid in %o0 and egid in %o1 */
+- .globl sunos_getgid
+-sunos_getgid:
+- call sys_getegid16
+- nop
+-
+- call sys_getgid16
+- st %o0, [%sp + STACKFRAME_SZ + PT_I1]
+-
+- b ret_sys_call
+- st %o0, [%sp + STACKFRAME_SZ + PT_I0]
+-
+- /* SunOS's execv() call only specifies the argv argument, the
+- * environment settings are the same as the calling processes.
+- */
+- .globl sunos_execv
+-sunos_execv:
+- st %g0, [%sp + STACKFRAME_SZ + PT_I2]
+-
+- call sparc_execve
+- add %sp, STACKFRAME_SZ, %o0
+-
+- b ret_sys_call
+- ld [%sp + STACKFRAME_SZ + PT_I0], %o0
+diff --git a/arch/sparc/kernel/sunos_ioctl.c b/arch/sparc/kernel/sunos_ioctl.c
+deleted file mode 100644
+index e613cc6..0000000
+--- a/arch/sparc/kernel/sunos_ioctl.c
++++ /dev/null
+@@ -1,230 +0,0 @@
+-/* $Id: sunos_ioctl.c,v 1.34 2000/09/03 14:10:56 anton Exp $
+- * sunos_ioctl.c: The Linux Operating system: SunOS ioctl compatibility.
+- *
+- * Copyright (C) 1995 Miguel de Icaza (miguel at nuclecu.unam.mx)
+- * Copyright (C) 1995 David S. Miller (davem at caip.rutgers.edu)
+- */
+-
+-#include <asm/uaccess.h>
+-
+-#include <linux/sched.h>
+-#include <linux/errno.h>
+-#include <linux/string.h>
+-#include <linux/termios.h>
+-#include <linux/tty.h>
+-#include <linux/ioctl.h>
+-#include <linux/route.h>
+-#include <linux/sockios.h>
+-#include <linux/if.h>
+-#include <linux/netdevice.h>
+-#include <linux/if_arp.h>
+-#include <linux/fs.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+-#include <linux/syscalls.h>
+-#include <linux/file.h>
+-
+-#if 0
+-extern char sunkbd_type;
+-extern char sunkbd_layout;
+-#endif
+-
+-/* NR_OPEN is now larger and dynamic in recent kernels. */
+-#define SUNOS_NR_OPEN 256
+-
+-asmlinkage int sunos_ioctl (int fd, unsigned long cmd, unsigned long arg)
+-{
+- int ret = -EBADF;
+-
+- if (fd >= SUNOS_NR_OPEN || !fcheck(fd))
+- goto out;
+-
+- /* First handle an easy compat. case for tty ldisc. */
+- if (cmd == TIOCSETD) {
+- int __user *p;
+- int ntty = N_TTY, tmp;
+- mm_segment_t oldfs;
+-
+- p = (int __user *) arg;
+- ret = -EFAULT;
+- if (get_user(tmp, p))
+- goto out;
+- if (tmp == 2) {
+- oldfs = get_fs();
+- set_fs(KERNEL_DS);
+- ret = sys_ioctl(fd, cmd, (unsigned long) &ntty);
+- set_fs(oldfs);
+- ret = (ret == -EINVAL ? -EOPNOTSUPP : ret);
+- goto out;
+- }
+- }
+-
+- /* Binary compatibility is good American knowhow fuckin' up. */
+- if (cmd == TIOCNOTTY) {
+- ret = sys_setsid();
+- goto out;
+- }
+-
+- /* SunOS networking ioctls. */
+- switch (cmd) {
+- case _IOW('r', 10, struct rtentry):
+- ret = sys_ioctl(fd, SIOCADDRT, arg);
+- goto out;
+- case _IOW('r', 11, struct rtentry):
+- ret = sys_ioctl(fd, SIOCDELRT, arg);
+- goto out;
+- case _IOW('i', 12, struct ifreq):
+- ret = sys_ioctl(fd, SIOCSIFADDR, arg);
+- goto out;
+- case _IOWR('i', 13, struct ifreq):
+- ret = sys_ioctl(fd, SIOCGIFADDR, arg);
+- goto out;
+- case _IOW('i', 14, struct ifreq):
+- ret = sys_ioctl(fd, SIOCSIFDSTADDR, arg);
+- goto out;
+- case _IOWR('i', 15, struct ifreq):
+- ret = sys_ioctl(fd, SIOCGIFDSTADDR, arg);
+- goto out;
+- case _IOW('i', 16, struct ifreq):
+- ret = sys_ioctl(fd, SIOCSIFFLAGS, arg);
+- goto out;
+- case _IOWR('i', 17, struct ifreq):
+- ret = sys_ioctl(fd, SIOCGIFFLAGS, arg);
+- goto out;
+- case _IOW('i', 18, struct ifreq):
+- ret = sys_ioctl(fd, SIOCSIFMEM, arg);
+- goto out;
+- case _IOWR('i', 19, struct ifreq):
+- ret = sys_ioctl(fd, SIOCGIFMEM, arg);
+- goto out;
+- case _IOWR('i', 20, struct ifconf):
+- ret = sys_ioctl(fd, SIOCGIFCONF, arg);
+- goto out;
+- case _IOW('i', 21, struct ifreq): /* SIOCSIFMTU */
+- ret = sys_ioctl(fd, SIOCSIFMTU, arg);
+- goto out;
+- case _IOWR('i', 22, struct ifreq): /* SIOCGIFMTU */
+- ret = sys_ioctl(fd, SIOCGIFMTU, arg);
+- goto out;
+-
+- case _IOWR('i', 23, struct ifreq):
+- ret = sys_ioctl(fd, SIOCGIFBRDADDR, arg);
+- goto out;
+- case _IOW('i', 24, struct ifreq):
+- ret = sys_ioctl(fd, SIOCSIFBRDADDR, arg);
+- goto out;
+- case _IOWR('i', 25, struct ifreq):
+- ret = sys_ioctl(fd, SIOCGIFNETMASK, arg);
+- goto out;
+- case _IOW('i', 26, struct ifreq):
+- ret = sys_ioctl(fd, SIOCSIFNETMASK, arg);
+- goto out;
+- case _IOWR('i', 27, struct ifreq):
+- ret = sys_ioctl(fd, SIOCGIFMETRIC, arg);
+- goto out;
+- case _IOW('i', 28, struct ifreq):
+- ret = sys_ioctl(fd, SIOCSIFMETRIC, arg);
+- goto out;
+-
+- case _IOW('i', 30, struct arpreq):
+- ret = sys_ioctl(fd, SIOCSARP, arg);
+- goto out;
+- case _IOWR('i', 31, struct arpreq):
+- ret = sys_ioctl(fd, SIOCGARP, arg);
+- goto out;
+- case _IOW('i', 32, struct arpreq):
+- ret = sys_ioctl(fd, SIOCDARP, arg);
+- goto out;
+-
+- case _IOW('i', 40, struct ifreq): /* SIOCUPPER */
+- case _IOW('i', 41, struct ifreq): /* SIOCLOWER */
+- case _IOW('i', 44, struct ifreq): /* SIOCSETSYNC */
+- case _IOW('i', 45, struct ifreq): /* SIOCGETSYNC */
+- case _IOW('i', 46, struct ifreq): /* SIOCSSDSTATS */
+- case _IOW('i', 47, struct ifreq): /* SIOCSSESTATS */
+- case _IOW('i', 48, struct ifreq): /* SIOCSPROMISC */
+- ret = -EOPNOTSUPP;
+- goto out;
+-
+- case _IOW('i', 49, struct ifreq):
+- ret = sys_ioctl(fd, SIOCADDMULTI, arg);
+- goto out;
+- case _IOW('i', 50, struct ifreq):
+- ret = sys_ioctl(fd, SIOCDELMULTI, arg);
+- goto out;
+-
+- /* FDDI interface ioctls, unsupported. */
+-
+- case _IOW('i', 51, struct ifreq): /* SIOCFDRESET */
+- case _IOW('i', 52, struct ifreq): /* SIOCFDSLEEP */
+- case _IOW('i', 53, struct ifreq): /* SIOCSTRTFMWAR */
+- case _IOW('i', 54, struct ifreq): /* SIOCLDNSTRTFW */
+- case _IOW('i', 55, struct ifreq): /* SIOCGETFDSTAT */
+- case _IOW('i', 56, struct ifreq): /* SIOCFDNMIINT */
+- case _IOW('i', 57, struct ifreq): /* SIOCFDEXUSER */
+- case _IOW('i', 58, struct ifreq): /* SIOCFDGNETMAP */
+- case _IOW('i', 59, struct ifreq): /* SIOCFDGIOCTL */
+- printk("FDDI ioctl, returning EOPNOTSUPP\n");
+- ret = -EOPNOTSUPP;
+- goto out;
+-
+- case _IOW('t', 125, int):
+- /* More stupid tty sunos ioctls, just
+- * say it worked.
+- */
+- ret = 0;
+- goto out;
+- /* Non posix grp */
+- case _IOW('t', 118, int): {
+- int oldval, newval, __user *ptr;
+-
+- cmd = TIOCSPGRP;
+- ptr = (int __user *) arg;
+- ret = -EFAULT;
+- if (get_user(oldval, ptr))
+- goto out;
+- ret = sys_ioctl(fd, cmd, arg);
+- __get_user(newval, ptr);
+- if (newval == -1) {
+- __put_user(oldval, ptr);
+- ret = -EIO;
+- }
+- if (ret == -ENOTTY)
+- ret = -EIO;
+- goto out;
+- }
+-
+- case _IOR('t', 119, int): {
+- int oldval, newval, __user *ptr;
+-
+- cmd = TIOCGPGRP;
+- ptr = (int __user *) arg;
+- ret = -EFAULT;
+- if (get_user(oldval, ptr))
+- goto out;
+- ret = sys_ioctl(fd, cmd, arg);
+- __get_user(newval, ptr);
+- if (newval == -1) {
+- __put_user(oldval, ptr);
+- ret = -EIO;
+- }
+- if (ret == -ENOTTY)
+- ret = -EIO;
+- goto out;
+- }
+- }
+-
+-#if 0
+- if ((cmd & 0xff00) == ('k' << 8)) {
+- printk ("[[KBIO: %8.8x\n", (unsigned int) cmd);
+- }
+-#endif
+-
+- ret = sys_ioctl(fd, cmd, arg);
+- /* so stupid... */
+- ret = (ret == -EINVAL ? -EOPNOTSUPP : ret);
+-out:
+- return ret;
+-}
+-
+-
+diff --git a/arch/sparc/kernel/sys_solaris.c b/arch/sparc/kernel/sys_solaris.c
+deleted file mode 100644
+index 2226a59..0000000
+--- a/arch/sparc/kernel/sys_solaris.c
++++ /dev/null
+@@ -1,35 +0,0 @@
+-/*
+- * linux/arch/sparc/kernel/sys_solaris.c
+- *
+- * Copyright (C) 1996 Miguel de Icaza (miguel at nuclecu.unam.mx)
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/kernel.h>
+-#include <linux/string.h>
+-#include <linux/errno.h>
+-#include <linux/personality.h>
+-#include <linux/ptrace.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+-#include <linux/module.h>
+-
+-asmlinkage int
+-do_solaris_syscall (struct pt_regs *regs)
+-{
+- static int cnt = 0;
+- if (++cnt < 10) printk ("No solaris handler\n");
+- force_sig(SIGSEGV, current);
+- return 0;
+-}
+-
+-#ifndef CONFIG_SUNOS_EMUL
+-asmlinkage int
+-do_sunos_syscall (struct pt_regs *regs)
+-{
+- static int cnt = 0;
+- if (++cnt < 10) printk ("SunOS binary emulation not compiled in\n");
+- force_sig (SIGSEGV, current);
+- return 0;
+-}
+-#endif
+diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c
+deleted file mode 100644
+index f5b608b..0000000
+--- a/arch/sparc/kernel/sys_sunos.c
++++ /dev/null
+@@ -1,1210 +0,0 @@
+-/* $Id: sys_sunos.c,v 1.137 2002/02/08 03:57:14 davem Exp $
+- * sys_sunos.c: SunOS specific syscall compatibility support.
+- *
+- * Copyright (C) 1995 David S. Miller (davem at caip.rutgers.edu)
+- * Copyright (C) 1995 Miguel de Icaza (miguel at nuclecu.unam.mx)
+- *
+- * Based upon preliminary work which is:
+- *
+- * Copyright (C) 1995 Adrian M. Rodriguez (adrian at remus.rutgers.edu)
+- *
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/types.h>
+-#include <linux/mman.h>
+-#include <linux/mm.h>
+-#include <linux/swap.h>
+-#include <linux/fs.h>
+-#include <linux/file.h>
+-#include <linux/resource.h>
+-#include <linux/ipc.h>
+-#include <linux/shm.h>
+-#include <linux/msg.h>
+-#include <linux/sem.h>
+-#include <linux/signal.h>
+-#include <linux/uio.h>
+-#include <linux/utsname.h>
+-#include <linux/major.h>
+-#include <linux/stat.h>
+-#include <linux/slab.h>
+-#include <linux/pagemap.h>
+-#include <linux/capability.h>
+-#include <linux/errno.h>
+-#include <linux/smp.h>
+-#include <linux/smp_lock.h>
+-#include <linux/syscalls.h>
+-
+-#include <net/sock.h>
+-
+-#include <asm/uaccess.h>
+-#ifndef KERNEL_DS
+-#include <linux/segment.h>
+-#endif
+-
+-#include <asm/page.h>
+-#include <asm/pgtable.h>
+-#include <asm/pconf.h>
+-#include <asm/idprom.h> /* for gethostid() */
+-#include <asm/unistd.h>
+-#include <asm/system.h>
+-
+-/* For the nfs mount emulation */
+-#include <linux/socket.h>
+-#include <linux/in.h>
+-#include <linux/nfs.h>
+-#include <linux/nfs2.h>
+-#include <linux/nfs_mount.h>
+-
+-/* for sunos_select */
+-#include <linux/time.h>
+-#include <linux/personality.h>
+-
+-/* NR_OPEN is now larger and dynamic in recent kernels. */
+-#define SUNOS_NR_OPEN 256
+-
+-/* We use the SunOS mmap() semantics. */
+-asmlinkage unsigned long sunos_mmap(unsigned long addr, unsigned long len,
+- unsigned long prot, unsigned long flags,
+- unsigned long fd, unsigned long off)
+-{
+- struct file * file = NULL;
+- unsigned long retval, ret_type;
+-
+- if (flags & MAP_NORESERVE) {
+- static int cnt;
+- if (cnt++ < 10)
+- printk("%s: unimplemented SunOS MAP_NORESERVE mmap() flag\n",
+- current->comm);
+- flags &= ~MAP_NORESERVE;
+- }
+- retval = -EBADF;
+- if (!(flags & MAP_ANONYMOUS)) {
+- if (fd >= SUNOS_NR_OPEN)
+- goto out;
+- file = fget(fd);
+- if (!file)
+- goto out;
+- }
+-
+- retval = -EINVAL;
+- /* If this is ld.so or a shared library doing an mmap
+- * of /dev/zero, transform it into an anonymous mapping.
+- * SunOS is so stupid some times... hmph!
+- */
+- if (file) {
+- if (imajor(file->f_path.dentry->d_inode) == MEM_MAJOR &&
+- iminor(file->f_path.dentry->d_inode) == 5) {
+- flags |= MAP_ANONYMOUS;
+- fput(file);
+- file = NULL;
+- }
+- }
+- ret_type = flags & _MAP_NEW;
+- flags &= ~_MAP_NEW;
+-
+- if (!(flags & MAP_FIXED))
+- addr = 0;
+- else {
+- if (ARCH_SUN4C_SUN4 &&
+- (len > 0x20000000 ||
+- ((flags & MAP_FIXED) &&
+- addr < 0xe0000000 && addr + len > 0x20000000)))
+- goto out_putf;
+-
+- /* See asm-sparc/uaccess.h */
+- if (len > TASK_SIZE - PAGE_SIZE ||
+- addr + len > TASK_SIZE - PAGE_SIZE)
+- goto out_putf;
+- }
+-
+- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+- down_write(¤t->mm->mmap_sem);
+- retval = do_mmap(file, addr, len, prot, flags, off);
+- up_write(¤t->mm->mmap_sem);
+- if (!ret_type)
+- retval = ((retval < PAGE_OFFSET) ? 0 : retval);
+-
+-out_putf:
+- if (file)
+- fput(file);
+-out:
+- return retval;
+-}
+-
+-/* lmbench calls this, just say "yeah, ok" */
+-asmlinkage int sunos_mctl(unsigned long addr, unsigned long len, int function, char *arg)
+-{
+- return 0;
+-}
+-
+-/* SunOS is completely broken... it returns 0 on success, otherwise
+- * ENOMEM. For sys_sbrk() it wants the old brk value as a return
+- * on success and ENOMEM as before on failure.
+- */
+-asmlinkage int sunos_brk(unsigned long brk)
+-{
+- int freepages, retval = -ENOMEM;
+- unsigned long rlim;
+- unsigned long newbrk, oldbrk;
+-
+- down_write(¤t->mm->mmap_sem);
+- if (ARCH_SUN4C_SUN4) {
+- if (brk >= 0x20000000 && brk < 0xe0000000) {
+- goto out;
+- }
+- }
+-
+- if (brk < current->mm->end_code)
+- goto out;
+-
+- newbrk = PAGE_ALIGN(brk);
+- oldbrk = PAGE_ALIGN(current->mm->brk);
+- retval = 0;
+- if (oldbrk == newbrk) {
+- current->mm->brk = brk;
+- goto out;
+- }
+-
+- /*
+- * Always allow shrinking brk
+- */
+- if (brk <= current->mm->brk) {
+- current->mm->brk = brk;
+- do_munmap(current->mm, newbrk, oldbrk-newbrk);
+- goto out;
+- }
+- /*
+- * Check against rlimit and stack..
+- */
+- retval = -ENOMEM;
+- rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
+- if (rlim >= RLIM_INFINITY)
+- rlim = ~0;
+- if (brk - current->mm->end_code > rlim)
+- goto out;
+-
+- /*
+- * Check against existing mmap mappings.
+- */
+- if (find_vma_intersection(current->mm, oldbrk, newbrk+PAGE_SIZE))
+- goto out;
+-
+- /*
+- * stupid algorithm to decide if we have enough memory: while
+- * simple, it hopefully works in most obvious cases.. Easy to
+- * fool it, but this should catch most mistakes.
+- */
+- freepages = global_page_state(NR_FILE_PAGES);
+- freepages >>= 1;
+- freepages += nr_free_pages();
+- freepages += nr_swap_pages;
+- freepages -= num_physpages >> 4;
+- freepages -= (newbrk-oldbrk) >> PAGE_SHIFT;
+- if (freepages < 0)
+- goto out;
+- /*
+- * Ok, we have probably got enough memory - let it rip.
+- */
+- current->mm->brk = brk;
+- do_brk(oldbrk, newbrk-oldbrk);
+- retval = 0;
+-out:
+- up_write(¤t->mm->mmap_sem);
+- return retval;
+-}
+-
+-asmlinkage unsigned long sunos_sbrk(int increment)
+-{
+- int error;
+- unsigned long oldbrk;
+-
+- /* This should do it hopefully... */
+- lock_kernel();
+- oldbrk = current->mm->brk;
+- error = sunos_brk(((int) current->mm->brk) + increment);
+- if (!error)
+- error = oldbrk;
+- unlock_kernel();
+- return error;
+-}
+-
+-/* XXX Completely undocumented, and completely magic...
+- * XXX I believe it is to increase the size of the stack by
+- * XXX argument 'increment' and return the new end of stack
+- * XXX area. Wheee...
+- */
+-asmlinkage unsigned long sunos_sstk(int increment)
+-{
+- lock_kernel();
+- printk("%s: Call to sunos_sstk(increment<%d>) is unsupported\n",
+- current->comm, increment);
+- unlock_kernel();
+- return -1;
+-}
+-
+-/* Give hints to the kernel as to what paging strategy to use...
+- * Completely bogus, don't remind me.
+- */
+-#define VA_NORMAL 0 /* Normal vm usage expected */
+-#define VA_ABNORMAL 1 /* Abnormal/random vm usage probable */
+-#define VA_SEQUENTIAL 2 /* Accesses will be of a sequential nature */
+-#define VA_INVALIDATE 3 /* Page table entries should be flushed ??? */
+-static char *vstrings[] = {
+- "VA_NORMAL",
+- "VA_ABNORMAL",
+- "VA_SEQUENTIAL",
+- "VA_INVALIDATE",
+-};
+-
+-asmlinkage void sunos_vadvise(unsigned long strategy)
+-{
+- /* I wanna see who uses this... */
+- lock_kernel();
+- printk("%s: Advises us to use %s paging strategy\n",
+- current->comm,
+- strategy <= 3 ? vstrings[strategy] : "BOGUS");
+- unlock_kernel();
+-}
+-
+-/* This just wants the soft limit (ie. rlim_cur element) of the RLIMIT_NOFILE
+- * resource limit and is for backwards compatibility with older sunos
+- * revs.
+- */
+-asmlinkage long sunos_getdtablesize(void)
+-{
+- return SUNOS_NR_OPEN;
+-}
+-
+-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+-
+-asmlinkage unsigned long sunos_sigblock(unsigned long blk_mask)
+-{
+- unsigned long old;
+-
+- spin_lock_irq(¤t->sighand->siglock);
+- old = current->blocked.sig[0];
+- current->blocked.sig[0] |= (blk_mask & _BLOCKABLE);
+- recalc_sigpending();
+- spin_unlock_irq(¤t->sighand->siglock);
+- return old;
+-}
+-
+-asmlinkage unsigned long sunos_sigsetmask(unsigned long newmask)
+-{
+- unsigned long retval;
+-
+- spin_lock_irq(¤t->sighand->siglock);
+- retval = current->blocked.sig[0];
+- current->blocked.sig[0] = (newmask & _BLOCKABLE);
+- recalc_sigpending();
+- spin_unlock_irq(¤t->sighand->siglock);
+- return retval;
+-}
+-
+-/* SunOS getdents is very similar to the newer Linux (iBCS2 compliant) */
+-/* getdents system call, the format of the structure just has a different */
+-/* layout (d_off+d_ino instead of d_ino+d_off) */
+-struct sunos_dirent {
+- long d_off;
+- unsigned long d_ino;
+- unsigned short d_reclen;
+- unsigned short d_namlen;
+- char d_name[1];
+-};
+-
+-struct sunos_dirent_callback {
+- struct sunos_dirent __user *curr;
+- struct sunos_dirent __user *previous;
+- int count;
+- int error;
+-};
+-
+-#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
+-#define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
+-
+-static int sunos_filldir(void * __buf, const char * name, int namlen,
+- loff_t offset, u64 ino, unsigned int d_type)
+-{
+- struct sunos_dirent __user *dirent;
+- struct sunos_dirent_callback * buf = __buf;
+- unsigned long d_ino;
+- int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+-
+- buf->error = -EINVAL; /* only used if we fail.. */
+- if (reclen > buf->count)
+- return -EINVAL;
+- d_ino = ino;
+- if (sizeof(d_ino) < sizeof(ino) && d_ino != ino)
+- return -EOVERFLOW;
+- dirent = buf->previous;
+- if (dirent)
+- put_user(offset, &dirent->d_off);
+- dirent = buf->curr;
+- buf->previous = dirent;
+- put_user(d_ino, &dirent->d_ino);
+- put_user(namlen, &dirent->d_namlen);
+- put_user(reclen, &dirent->d_reclen);
+- copy_to_user(dirent->d_name, name, namlen);
+- put_user(0, dirent->d_name + namlen);
+- dirent = (void __user *) dirent + reclen;
+- buf->curr = dirent;
+- buf->count -= reclen;
+- return 0;
+-}
+-
+-asmlinkage int sunos_getdents(unsigned int fd, void __user *dirent, int cnt)
+-{
+- struct file * file;
+- struct sunos_dirent __user *lastdirent;
+- struct sunos_dirent_callback buf;
+- int error = -EBADF;
+-
+- if (fd >= SUNOS_NR_OPEN)
+- goto out;
+-
+- file = fget(fd);
+- if (!file)
+- goto out;
+-
+- error = -EINVAL;
+- if (cnt < (sizeof(struct sunos_dirent) + 255))
+- goto out_putf;
+-
+- buf.curr = (struct sunos_dirent __user *) dirent;
+- buf.previous = NULL;
+- buf.count = cnt;
+- buf.error = 0;
+-
+- error = vfs_readdir(file, sunos_filldir, &buf);
+- if (error < 0)
+- goto out_putf;
+-
+- lastdirent = buf.previous;
+- error = buf.error;
+- if (lastdirent) {
+- put_user(file->f_pos, &lastdirent->d_off);
+- error = cnt - buf.count;
+- }
+-
+-out_putf:
+- fput(file);
+-out:
+- return error;
+-}
+-
+-/* Old sunos getdirentries, severely broken compatibility stuff here. */
+-struct sunos_direntry {
+- unsigned long d_ino;
+- unsigned short d_reclen;
+- unsigned short d_namlen;
+- char d_name[1];
+-};
+-
+-struct sunos_direntry_callback {
+- struct sunos_direntry __user *curr;
+- struct sunos_direntry __user *previous;
+- int count;
+- int error;
+-};
+-
+-static int sunos_filldirentry(void * __buf, const char * name, int namlen,
+- loff_t offset, u64 ino, unsigned int d_type)
+-{
+- struct sunos_direntry __user *dirent;
+- struct sunos_direntry_callback *buf = __buf;
+- unsigned long d_ino;
+- int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+-
+- buf->error = -EINVAL; /* only used if we fail.. */
+- if (reclen > buf->count)
+- return -EINVAL;
+- d_ino = ino;
+- if (sizeof(d_ino) < sizeof(ino) && d_ino != ino)
+- return -EOVERFLOW;
+- dirent = buf->previous;
+- dirent = buf->curr;
+- buf->previous = dirent;
+- put_user(d_ino, &dirent->d_ino);
+- put_user(namlen, &dirent->d_namlen);
+- put_user(reclen, &dirent->d_reclen);
+- copy_to_user(dirent->d_name, name, namlen);
+- put_user(0, dirent->d_name + namlen);
+- dirent = (void __user *) dirent + reclen;
+- buf->curr = dirent;
+- buf->count -= reclen;
+- return 0;
+-}
+-
+-asmlinkage int sunos_getdirentries(unsigned int fd, void __user *dirent,
+- int cnt, unsigned int __user *basep)
+-{
+- struct file * file;
+- struct sunos_direntry __user *lastdirent;
+- struct sunos_direntry_callback buf;
+- int error = -EBADF;
+-
+- if (fd >= SUNOS_NR_OPEN)
+- goto out;
+-
+- file = fget(fd);
+- if (!file)
+- goto out;
+-
+- error = -EINVAL;
+- if (cnt < (sizeof(struct sunos_direntry) + 255))
+- goto out_putf;
+-
+- buf.curr = (struct sunos_direntry __user *) dirent;
+- buf.previous = NULL;
+- buf.count = cnt;
+- buf.error = 0;
+-
+- error = vfs_readdir(file, sunos_filldirentry, &buf);
+- if (error < 0)
+- goto out_putf;
+-
+- lastdirent = buf.previous;
+- error = buf.error;
+- if (lastdirent) {
+- put_user(file->f_pos, basep);
+- error = cnt - buf.count;
+- }
+-
+-out_putf:
+- fput(file);
+-out:
+- return error;
+-}
+-
+-struct sunos_utsname {
+- char sname[9];
+- char nname[9];
+- char nnext[56];
+- char rel[9];
+- char ver[9];
+- char mach[9];
+-};
+-
+-asmlinkage int sunos_uname(struct sunos_utsname __user *name)
+-{
+- int ret;
+- down_read(&uts_sem);
+- ret = copy_to_user(&name->sname[0], &utsname()->sysname[0],
+- sizeof(name->sname) - 1);
+- if (!ret) {
+- ret |= __copy_to_user(&name->nname[0], &utsname()->nodename[0],
+- sizeof(name->nname) - 1);
+- ret |= __put_user('\0', &name->nname[8]);
+- ret |= __copy_to_user(&name->rel[0], &utsname()->release[0],
+- sizeof(name->rel) - 1);
+- ret |= __copy_to_user(&name->ver[0], &utsname()->version[0],
+- sizeof(name->ver) - 1);
+- ret |= __copy_to_user(&name->mach[0], &utsname()->machine[0],
+- sizeof(name->mach) - 1);
+- }
+- up_read(&uts_sem);
+- return ret ? -EFAULT : 0;
+-}
+-
+-asmlinkage int sunos_nosys(void)
+-{
+- struct pt_regs *regs;
+- siginfo_t info;
+- static int cnt;
+-
+- lock_kernel();
+- regs = current->thread.kregs;
+- info.si_signo = SIGSYS;
+- info.si_errno = 0;
+- info.si_code = __SI_FAULT|0x100;
+- info.si_addr = (void __user *)regs->pc;
+- info.si_trapno = regs->u_regs[UREG_G1];
+- send_sig_info(SIGSYS, &info, current);
+- if (cnt++ < 4) {
+- printk("Process makes ni_syscall number %d, register dump:\n",
+- (int) regs->u_regs[UREG_G1]);
+- show_regs(regs);
+- }
+- unlock_kernel();
+- return -ENOSYS;
+-}
+-
+-/* This is not a real and complete implementation yet, just to keep
+- * the easy SunOS binaries happy.
+- */
+-asmlinkage int sunos_fpathconf(int fd, int name)
+-{
+- int ret;
+-
+- switch(name) {
+- case _PCONF_LINK:
+- ret = LINK_MAX;
+- break;
+- case _PCONF_CANON:
+- ret = MAX_CANON;
+- break;
+- case _PCONF_INPUT:
+- ret = MAX_INPUT;
+- break;
+- case _PCONF_NAME:
+- ret = NAME_MAX;
+- break;
+- case _PCONF_PATH:
+- ret = PATH_MAX;
+- break;
+- case _PCONF_PIPE:
+- ret = PIPE_BUF;
+- break;
+- case _PCONF_CHRESTRICT: /* XXX Investigate XXX */
+- ret = 1;
+- break;
+- case _PCONF_NOTRUNC: /* XXX Investigate XXX */
+- case _PCONF_VDISABLE:
+- ret = 0;
+- break;
+- default:
+- ret = -EINVAL;
+- break;
+- }
+- return ret;
+-}
+-
+-asmlinkage int sunos_pathconf(char __user *path, int name)
+-{
+- int ret;
+-
+- ret = sunos_fpathconf(0, name); /* XXX cheese XXX */
+- return ret;
+-}
+-
+-/* SunOS mount system call emulation */
+-
+-asmlinkage int sunos_select(int width, fd_set __user *inp, fd_set __user *outp,
+- fd_set __user *exp, struct timeval __user *tvp)
+-{
+- int ret;
+-
+- /* SunOS binaries expect that select won't change the tvp contents */
+- ret = sys_select (width, inp, outp, exp, tvp);
+- if (ret == -EINTR && tvp) {
+- time_t sec, usec;
+-
+- __get_user(sec, &tvp->tv_sec);
+- __get_user(usec, &tvp->tv_usec);
+-
+- if (sec == 0 && usec == 0)
+- ret = 0;
+- }
+- return ret;
+-}
+-
+-asmlinkage void sunos_nop(void)
+-{
+- return;
+-}
+-
+-/* SunOS mount/umount. */
+-#define SMNT_RDONLY 1
+-#define SMNT_NOSUID 2
+-#define SMNT_NEWTYPE 4
+-#define SMNT_GRPID 8
+-#define SMNT_REMOUNT 16
+-#define SMNT_NOSUB 32
+-#define SMNT_MULTI 64
+-#define SMNT_SYS5 128
+-
+-struct sunos_fh_t {
+- char fh_data [NFS_FHSIZE];
+-};
+-
+-struct sunos_nfs_mount_args {
+- struct sockaddr_in __user *addr; /* file server address */
+- struct nfs_fh __user *fh; /* File handle to be mounted */
+- int flags; /* flags */
+- int wsize; /* write size in bytes */
+- int rsize; /* read size in bytes */
+- int timeo; /* initial timeout in .1 secs */
+- int retrans; /* times to retry send */
+- char __user *hostname; /* server's hostname */
+- int acregmin; /* attr cache file min secs */
+- int acregmax; /* attr cache file max secs */
+- int acdirmin; /* attr cache dir min secs */
+- int acdirmax; /* attr cache dir max secs */
+- char __user *netname; /* server's netname */
+-};
+-
+-
+-/* Bind the socket on a local reserved port and connect it to the
+- * remote server. This on Linux/i386 is done by the mount program,
+- * not by the kernel.
+- */
+-static int
+-sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr)
+-{
+- struct sockaddr_in local;
+- struct sockaddr_in server;
+- int try_port;
+- struct socket *socket;
+- struct inode *inode;
+- struct file *file;
+- int ret, result = 0;
+-
+- file = fget(fd);
+- if (!file)
+- goto out;
+-
+- inode = file->f_path.dentry->d_inode;
+-
+- socket = SOCKET_I(inode);
+- local.sin_family = AF_INET;
+- local.sin_addr.s_addr = htonl(INADDR_ANY);
+-
+- /* IPPORT_RESERVED = 1024, can't find the definition in the kernel */
+- try_port = 1024;
+- do {
+- local.sin_port = htons (--try_port);
+- ret = socket->ops->bind(socket, (struct sockaddr*)&local,
+- sizeof(local));
+- } while (ret && try_port > (1024 / 2));
+-
+- if (ret)
+- goto out_putf;
+-
+- server.sin_family = AF_INET;
+- server.sin_addr = addr->sin_addr;
+- server.sin_port = NFS_PORT;
+-
+- /* Call sys_connect */
+- ret = socket->ops->connect (socket, (struct sockaddr *) &server,
+- sizeof (server), file->f_flags);
+- if (ret >= 0)
+- result = 1;
+-
+-out_putf:
+- fput(file);
+-out:
+- return result;
+-}
+-
+-static int get_default (int value, int def_value)
+-{
+- if (value)
+- return value;
+- else
+- return def_value;
+-}
+-
+-static int sunos_nfs_mount(char *dir_name, int linux_flags, void __user *data)
+-{
+- int server_fd, err;
+- char *the_name, *mount_page;
+- struct nfs_mount_data linux_nfs_mount;
+- struct sunos_nfs_mount_args sunos_mount;
+-
+- /* Ok, here comes the fun part: Linux's nfs mount needs a
+- * socket connection to the server, but SunOS mount does not
+- * require this, so we use the information on the destination
+- * address to create a socket and bind it to a reserved
+- * port on this system
+- */
+- if (copy_from_user(&sunos_mount, data, sizeof(sunos_mount)))
+- return -EFAULT;
+-
+- server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+- if (server_fd < 0)
+- return -ENXIO;
+-
+- if (copy_from_user(&linux_nfs_mount.addr,sunos_mount.addr,
+- sizeof(*sunos_mount.addr)) ||
+- copy_from_user(&linux_nfs_mount.root,sunos_mount.fh,
+- sizeof(*sunos_mount.fh))) {
+- sys_close (server_fd);
+- return -EFAULT;
+- }
+-
+- if (!sunos_nfs_get_server_fd (server_fd, &linux_nfs_mount.addr)){
+- sys_close (server_fd);
+- return -ENXIO;
+- }
+-
+- /* Now, bind it to a locally reserved port */
+- linux_nfs_mount.version = NFS_MOUNT_VERSION;
+- linux_nfs_mount.flags = sunos_mount.flags;
+- linux_nfs_mount.fd = server_fd;
+-
+- linux_nfs_mount.rsize = get_default (sunos_mount.rsize, 8192);
+- linux_nfs_mount.wsize = get_default (sunos_mount.wsize, 8192);
+- linux_nfs_mount.timeo = get_default (sunos_mount.timeo, 10);
+- linux_nfs_mount.retrans = sunos_mount.retrans;
+-
+- linux_nfs_mount.acregmin = sunos_mount.acregmin;
+- linux_nfs_mount.acregmax = sunos_mount.acregmax;
+- linux_nfs_mount.acdirmin = sunos_mount.acdirmin;
+- linux_nfs_mount.acdirmax = sunos_mount.acdirmax;
+-
+- the_name = getname(sunos_mount.hostname);
+- if (IS_ERR(the_name))
+- return PTR_ERR(the_name);
+-
+- strlcpy(linux_nfs_mount.hostname, the_name,
+- sizeof(linux_nfs_mount.hostname));
+- putname (the_name);
+-
+- mount_page = (char *) get_zeroed_page(GFP_KERNEL);
+- if (!mount_page)
+- return -ENOMEM;
+-
+- memcpy(mount_page, &linux_nfs_mount, sizeof(linux_nfs_mount));
+-
+- err = do_mount("", dir_name, "nfs", linux_flags, mount_page);
+-
+- free_page((unsigned long) mount_page);
+- return err;
+-}
+-
+-asmlinkage int
+-sunos_mount(char __user *type, char __user *dir, int flags, void __user *data)
+-{
+- int linux_flags = 0;
+- int ret = -EINVAL;
+- char *dev_fname = NULL;
+- char *dir_page, *type_page;
+-
+- if (!capable (CAP_SYS_ADMIN))
+- return -EPERM;
+-
+- lock_kernel();
+- /* We don't handle the integer fs type */
+- if ((flags & SMNT_NEWTYPE) == 0)
+- goto out;
+-
+- /* Do not allow for those flags we don't support */
+- if (flags & (SMNT_GRPID|SMNT_NOSUB|SMNT_MULTI|SMNT_SYS5))
+- goto out;
+-
+- if (flags & SMNT_REMOUNT)
+- linux_flags |= MS_REMOUNT;
+- if (flags & SMNT_RDONLY)
+- linux_flags |= MS_RDONLY;
+- if (flags & SMNT_NOSUID)
+- linux_flags |= MS_NOSUID;
+-
+- dir_page = getname(dir);
+- ret = PTR_ERR(dir_page);
+- if (IS_ERR(dir_page))
+- goto out;
+-
+- type_page = getname(type);
+- ret = PTR_ERR(type_page);
+- if (IS_ERR(type_page))
+- goto out1;
+-
+- if (strcmp(type_page, "ext2") == 0) {
+- dev_fname = getname(data);
+- } else if (strcmp(type_page, "iso9660") == 0) {
+- dev_fname = getname(data);
+- } else if (strcmp(type_page, "minix") == 0) {
+- dev_fname = getname(data);
+- } else if (strcmp(type_page, "nfs") == 0) {
+- ret = sunos_nfs_mount (dir_page, flags, data);
+- goto out2;
+- } else if (strcmp(type_page, "ufs") == 0) {
+- printk("Warning: UFS filesystem mounts unsupported.\n");
+- ret = -ENODEV;
+- goto out2;
+- } else if (strcmp(type_page, "proc")) {
+- ret = -ENODEV;
+- goto out2;
+- }
+- ret = PTR_ERR(dev_fname);
+- if (IS_ERR(dev_fname))
+- goto out2;
+- ret = do_mount(dev_fname, dir_page, type_page, linux_flags, NULL);
+- if (dev_fname)
+- putname(dev_fname);
+-out2:
+- putname(type_page);
+-out1:
+- putname(dir_page);
+-out:
+- unlock_kernel();
+- return ret;
+-}
+-
+-
+-asmlinkage int sunos_setpgrp(pid_t pid, pid_t pgid)
+-{
+- int ret;
+-
+- /* So stupid... */
+- if ((!pid || pid == current->pid) &&
+- !pgid) {
+- sys_setsid();
+- ret = 0;
+- } else {
+- ret = sys_setpgid(pid, pgid);
+- }
+- return ret;
+-}
+-
+-/* So stupid... */
+-asmlinkage int sunos_wait4(pid_t pid, unsigned int __user *stat_addr,
+- int options, struct rusage __user*ru)
+-{
+- int ret;
+-
+- ret = sys_wait4((pid ? pid : -1), stat_addr, options, ru);
+- return ret;
+-}
+-
+-asmlinkage int sunos_killpg(int pgrp, int sig)
+-{
+- int ret;
+-
+- rcu_read_lock();
+- ret = -EINVAL;
+- if (pgrp > 0)
+- ret = kill_pgrp(find_vpid(pgrp), sig, 0);
+- rcu_read_unlock();
+-
+- return ret;
+-}
+-
+-asmlinkage int sunos_audit(void)
+-{
+- lock_kernel();
+- printk ("sys_audit\n");
+- unlock_kernel();
+- return -1;
+-}
+-
+-asmlinkage unsigned long sunos_gethostid(void)
+-{
+- unsigned long ret;
+-
+- lock_kernel();
+- ret = ((unsigned long)idprom->id_machtype << 24) |
+- (unsigned long)idprom->id_sernum;
+- unlock_kernel();
+- return ret;
+-}
+-
+-/* sysconf options, for SunOS compatibility */
+-#define _SC_ARG_MAX 1
+-#define _SC_CHILD_MAX 2
+-#define _SC_CLK_TCK 3
+-#define _SC_NGROUPS_MAX 4
+-#define _SC_OPEN_MAX 5
+-#define _SC_JOB_CONTROL 6
+-#define _SC_SAVED_IDS 7
+-#define _SC_VERSION 8
+-
+-asmlinkage long sunos_sysconf (int name)
+-{
+- long ret;
+-
+- switch (name){
+- case _SC_ARG_MAX:
+- ret = ARG_MAX;
+- break;
+- case _SC_CHILD_MAX:
+- ret = current->signal->rlim[RLIMIT_NPROC].rlim_cur;
+- break;
+- case _SC_CLK_TCK:
+- ret = HZ;
+- break;
+- case _SC_NGROUPS_MAX:
+- ret = NGROUPS_MAX;
+- break;
+- case _SC_OPEN_MAX:
+- ret = current->signal->rlim[RLIMIT_NOFILE].rlim_cur;
+- break;
+- case _SC_JOB_CONTROL:
+- ret = 1; /* yes, we do support job control */
+- break;
+- case _SC_SAVED_IDS:
+- ret = 1; /* yes, we do support saved uids */
+- break;
+- case _SC_VERSION:
+- /* mhm, POSIX_VERSION is in /usr/include/unistd.h
+- * should it go on /usr/include/linux?
+- */
+- ret = 199009L;
+- break;
+- default:
+- ret = -1;
+- break;
+- };
+- return ret;
+-}
+-
+-asmlinkage int sunos_semsys(int op, unsigned long arg1, unsigned long arg2,
+- unsigned long arg3, void *ptr)
+-{
+- union semun arg4;
+- int ret;
+-
+- switch (op) {
+- case 0:
+- /* Most arguments match on a 1:1 basis but cmd doesn't */
+- switch(arg3) {
+- case 4:
+- arg3=GETPID; break;
+- case 5:
+- arg3=GETVAL; break;
+- case 6:
+- arg3=GETALL; break;
+- case 3:
+- arg3=GETNCNT; break;
+- case 7:
+- arg3=GETZCNT; break;
+- case 8:
+- arg3=SETVAL; break;
+- case 9:
+- arg3=SETALL; break;
+- }
+- /* sys_semctl(): */
+- /* value to modify semaphore to */
+- arg4.__pad = (void __user *) ptr;
+- ret = sys_semctl((int)arg1, (int)arg2, (int)arg3, arg4 );
+- break;
+- case 1:
+- /* sys_semget(): */
+- ret = sys_semget((key_t)arg1, (int)arg2, (int)arg3);
+- break;
+- case 2:
+- /* sys_semop(): */
+- ret = sys_semop((int)arg1, (struct sembuf __user *)arg2, (unsigned)arg3);
+- break;
+- default:
+- ret = -EINVAL;
+- break;
+- };
+- return ret;
+-}
+-
+-asmlinkage int sunos_msgsys(int op, unsigned long arg1, unsigned long arg2,
+- unsigned long arg3, unsigned long arg4)
+-{
+- struct sparc_stackf *sp;
+- unsigned long arg5;
+- int rval;
+-
+- switch(op) {
+- case 0:
+- rval = sys_msgget((key_t)arg1, (int)arg2);
+- break;
+- case 1:
+- rval = sys_msgctl((int)arg1, (int)arg2,
+- (struct msqid_ds __user *)arg3);
+- break;
+- case 2:
+- lock_kernel();
+- sp = (struct sparc_stackf *)current->thread.kregs->u_regs[UREG_FP];
+- arg5 = sp->xxargs[0];
+- unlock_kernel();
+- rval = sys_msgrcv((int)arg1, (struct msgbuf __user *)arg2,
+- (size_t)arg3, (long)arg4, (int)arg5);
+- break;
+- case 3:
+- rval = sys_msgsnd((int)arg1, (struct msgbuf __user *)arg2,
+- (size_t)arg3, (int)arg4);
+- break;
+- default:
+- rval = -EINVAL;
+- break;
+- }
+- return rval;
+-}
+-
+-asmlinkage int sunos_shmsys(int op, unsigned long arg1, unsigned long arg2,
+- unsigned long arg3)
+-{
+- unsigned long raddr;
+- int rval;
+-
+- switch(op) {
+- case 0:
+- /* do_shmat(): attach a shared memory area */
+- rval = do_shmat((int)arg1,(char __user *)arg2,(int)arg3,&raddr);
+- if (!rval)
+- rval = (int) raddr;
+- break;
+- case 1:
+- /* sys_shmctl(): modify shared memory area attr. */
+- rval = sys_shmctl((int)arg1,(int)arg2,(struct shmid_ds __user *)arg3);
+- break;
+- case 2:
+- /* sys_shmdt(): detach a shared memory area */
+- rval = sys_shmdt((char __user *)arg1);
+- break;
+- case 3:
+- /* sys_shmget(): get a shared memory area */
+- rval = sys_shmget((key_t)arg1,(int)arg2,(int)arg3);
+- break;
+- default:
+- rval = -EINVAL;
+- break;
+- };
+- return rval;
+-}
+-
+-#define SUNOS_EWOULDBLOCK 35
+-
+-/* see the sunos man page read(2v) for an explanation
+- of this garbage. We use O_NDELAY to mark
+- file descriptors that have been set non-blocking
+- using 4.2BSD style calls. (tridge) */
+-
+-static inline int check_nonblock(int ret, int fd)
+-{
+- if (ret == -EAGAIN) {
+- struct file * file = fget(fd);
+- if (file) {
+- if (file->f_flags & O_NDELAY)
+- ret = -SUNOS_EWOULDBLOCK;
+- fput(file);
+- }
+- }
+- return ret;
+-}
+-
+-asmlinkage int sunos_read(unsigned int fd, char __user *buf, int count)
+-{
+- int ret;
+-
+- ret = check_nonblock(sys_read(fd,buf,count),fd);
+- return ret;
+-}
+-
+-asmlinkage int sunos_readv(unsigned long fd, const struct iovec __user *vector,
+- long count)
+-{
+- int ret;
+-
+- ret = check_nonblock(sys_readv(fd,vector,count),fd);
+- return ret;
+-}
+-
+-asmlinkage int sunos_write(unsigned int fd, char __user *buf, int count)
+-{
+- int ret;
+-
+- ret = check_nonblock(sys_write(fd,buf,count),fd);
+- return ret;
+-}
+-
+-asmlinkage int sunos_writev(unsigned long fd,
+- const struct iovec __user *vector, long count)
+-{
+- int ret;
+-
+- ret = check_nonblock(sys_writev(fd,vector,count),fd);
+- return ret;
+-}
+-
+-asmlinkage int sunos_recv(int fd, void __user *ubuf, int size, unsigned flags)
+-{
+- int ret;
+-
+- ret = check_nonblock(sys_recv(fd,ubuf,size,flags),fd);
+- return ret;
+-}
+-
+-asmlinkage int sunos_send(int fd, void __user *buff, int len, unsigned flags)
+-{
+- int ret;
+-
+- ret = check_nonblock(sys_send(fd,buff,len,flags),fd);
+- return ret;
+-}
+-
+-asmlinkage int sunos_accept(int fd, struct sockaddr __user *sa,
+- int __user *addrlen)
+-{
+- int ret;
+-
+- while (1) {
+- ret = check_nonblock(sys_accept(fd,sa,addrlen),fd);
+- if (ret != -ENETUNREACH && ret != -EHOSTUNREACH)
+- break;
+- }
+-
+- return ret;
+-}
+-
+-#define SUNOS_SV_INTERRUPT 2
+-
+-asmlinkage int
+-sunos_sigaction(int sig, const struct old_sigaction __user *act,
+- struct old_sigaction __user *oact)
+-{
+- struct k_sigaction new_ka, old_ka;
+- int ret;
+-
+- if (act) {
+- old_sigset_t mask;
+-
+- if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
+- __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
+- __get_user(new_ka.sa.sa_flags, &act->sa_flags))
+- return -EFAULT;
+- __get_user(mask, &act->sa_mask);
+- new_ka.sa.sa_restorer = NULL;
+- new_ka.ka_restorer = NULL;
+- siginitset(&new_ka.sa.sa_mask, mask);
+- new_ka.sa.sa_flags ^= SUNOS_SV_INTERRUPT;
+- }
+-
+- ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+-
+- if (!ret && oact) {
+- /* In the clone() case we could copy half consistent
+- * state to the user, however this could sleep and
+- * deadlock us if we held the signal lock on SMP. So for
+- * now I take the easy way out and do no locking.
+- * But then again we don't support SunOS lwp's anyways ;-)
+- */
+- old_ka.sa.sa_flags ^= SUNOS_SV_INTERRUPT;
+- if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
+- __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+- __put_user(old_ka.sa.sa_flags, &oact->sa_flags))
+- return -EFAULT;
+- __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+- }
+-
+- return ret;
+-}
+-
+-
+-asmlinkage int sunos_setsockopt(int fd, int level, int optname,
+- char __user *optval, int optlen)
+-{
+- int tr_opt = optname;
+- int ret;
+-
+- if (level == SOL_IP) {
+- /* Multicast socketopts (ttl, membership) */
+- if (tr_opt >=2 && tr_opt <= 6)
+- tr_opt += 30;
+- }
+- ret = sys_setsockopt(fd, level, tr_opt, optval, optlen);
+- return ret;
+-}
+-
+-asmlinkage int sunos_getsockopt(int fd, int level, int optname,
+- char __user *optval, int __user *optlen)
+-{
+- int tr_opt = optname;
+- int ret;
+-
+- if (level == SOL_IP) {
+- /* Multicast socketopts (ttl, membership) */
+- if (tr_opt >=2 && tr_opt <= 6)
+- tr_opt += 30;
+- }
+- ret = sys_getsockopt(fd, level, tr_opt, optval, optlen);
+- return ret;
+-}
+diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
+index 9064485..5a7c4c8 100644
+--- a/arch/sparc/kernel/systbls.S
++++ b/arch/sparc/kernel/systbls.S
+@@ -81,124 +81,3 @@ sys_call_table:
+ /*305*/ .long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
+ /*310*/ .long sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
+ /*315*/ .long sys_timerfd_settime, sys_timerfd_gettime
+-
+-#ifdef CONFIG_SUNOS_EMUL
+- /* Now the SunOS syscall table. */
+-
+- .align 4
+- .globl sunos_sys_table
+-sunos_sys_table:
+-/*0*/ .long sunos_indir, sys_exit, sys_fork
+- .long sunos_read, sunos_write, sys_open
+- .long sys_close, sunos_wait4, sys_creat
+- .long sys_link, sys_unlink, sunos_execv
+- .long sys_chdir, sunos_nosys, sys_mknod
+- .long sys_chmod, sys_lchown16, sunos_brk
+- .long sunos_nosys, sys_lseek, sunos_getpid
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_getuid, sunos_nosys, sys_ptrace
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sys_access, sunos_nosys, sunos_nosys
+- .long sys_sync, sys_kill, sys_newstat
+- .long sunos_nosys, sys_newlstat, sys_dup
+- .long sys_pipe, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_getgid
+- .long sunos_nosys, sunos_nosys
+-/*50*/ .long sunos_nosys, sys_acct, sunos_nosys
+- .long sunos_mctl, sunos_ioctl, sys_reboot
+- .long sunos_nosys, sys_symlink, sys_readlink
+- .long sys_execve, sys_umask, sys_chroot
+- .long sys_newfstat, sunos_nosys, sys_getpagesize
+- .long sys_msync, sys_vfork, sunos_nosys
+- .long sunos_nosys, sunos_sbrk, sunos_sstk
+- .long sunos_mmap, sunos_vadvise, sys_munmap
+- .long sys_mprotect, sys_madvise, sys_vhangup
+- .long sunos_nosys, sys_mincore, sys_getgroups16
+- .long sys_setgroups16, sys_getpgrp, sunos_setpgrp
+- .long sys_setitimer, sunos_nosys, sys_swapon
+- .long sys_getitimer, sys_gethostname, sys_sethostname
+- .long sunos_getdtablesize, sys_dup2, sunos_nop
+- .long sys_fcntl, sunos_select, sunos_nop
+- .long sys_fsync, sys_setpriority, sys_socket
+- .long sys_connect, sunos_accept
+-/*100*/ .long sys_getpriority, sunos_send, sunos_recv
+- .long sunos_nosys, sys_bind, sunos_setsockopt
+- .long sys_listen, sunos_nosys, sunos_sigaction
+- .long sunos_sigblock, sunos_sigsetmask, sys_sigpause
+- .long sys_sigstack, sys_recvmsg, sys_sendmsg
+- .long sunos_nosys, sys_gettimeofday, sys_getrusage
+- .long sunos_getsockopt, sunos_nosys, sunos_readv
+- .long sunos_writev, sys_settimeofday, sys_fchown16
+- .long sys_fchmod, sys_recvfrom, sys_setreuid16
+- .long sys_setregid16, sys_rename, sys_truncate
+- .long sys_ftruncate, sys_flock, sunos_nosys
+- .long sys_sendto, sys_shutdown, sys_socketpair
+- .long sys_mkdir, sys_rmdir, sys_utimes
+- .long sys_sigreturn, sunos_nosys, sys_getpeername
+- .long sunos_gethostid, sunos_nosys, sys_getrlimit
+- .long sys_setrlimit, sunos_killpg, sunos_nosys
+- .long sunos_nosys, sunos_nosys
+-/*150*/ .long sys_getsockname, sunos_nosys, sunos_nosys
+- .long sys_poll, sunos_nosys, sunos_nosys
+- .long sunos_getdirentries, sys_statfs, sys_fstatfs
+- .long sys_oldumount, sunos_nosys, sunos_nosys
+- .long sys_getdomainname, sys_setdomainname
+- .long sunos_nosys, sys_quotactl, sunos_nosys
+- .long sunos_mount, sys_ustat, sunos_semsys
+- .long sunos_msgsys, sunos_shmsys, sunos_audit
+- .long sunos_nosys, sunos_getdents, sys_setsid
+- .long sys_fchdir, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sys_sigpending, sunos_nosys
+- .long sys_setpgid, sunos_pathconf, sunos_fpathconf
+- .long sunos_sysconf, sunos_uname, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+-/*200*/ .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys
+-/*250*/ .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys
+-/*260*/ .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys
+-/*270*/ .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys
+-/*280*/ .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys
+-/*290*/ .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys
+-/*300*/ .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys
+-/*310*/ .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys
+-
+-#endif
+diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
+index cfaf22c..53caacb 100644
+--- a/arch/sparc/kernel/time.c
++++ b/arch/sparc/kernel/time.c
+@@ -105,7 +105,7 @@ __volatile__ unsigned int *master_l10_limit;
+
+ #define TICK_SIZE (tick_nsec / 1000)
+
+-irqreturn_t timer_interrupt(int irq, void *dev_id)
++static irqreturn_t timer_interrupt(int dummy, void *dev_id)
+ {
+ /* last time the cmos clock got updated */
+ static long last_rtc_update;
+diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
+index 463d1be..8acc5cc 100644
+--- a/arch/sparc64/Kconfig
++++ b/arch/sparc64/Kconfig
+@@ -16,6 +16,7 @@ config SPARC64
+ bool
+ default y
+ select HAVE_IDE
++ select HAVE_LMB
+ help
+ SPARC is a family of RISC microprocessors designed and marketed by
+ Sun Microsystems, incorporated. This port covers the newer 64-bit
+@@ -87,9 +88,6 @@ config GENERIC_HARDIRQS_NO__DO_IRQ
+ bool
+ def_bool y
+
+-config ARCH_SUPPORTS_AOUT
+- def_bool y
+-
+ choice
+ prompt "Kernel page size"
+ default SPARC64_PAGE_SIZE_8KB
+@@ -147,11 +145,6 @@ config HOTPLUG_CPU
+
+ source "init/Kconfig"
+
+-config SYSVIPC_COMPAT
+- bool
+- depends on COMPAT && SYSVIPC
+- default y
+-
+ config GENERIC_HARDIRQS
+ bool
+ default y
+@@ -257,6 +250,26 @@ endchoice
+
+ endmenu
+
++config NUMA
++ bool "NUMA support"
++
++config NODES_SHIFT
++ int
++ default "4"
++ depends on NEED_MULTIPLE_NODES
++
++# Some NUMA nodes have memory ranges that span
++# other nodes. Even though a pfn is valid and
++# between a node's start and end pfns, it may not
++# reside on that node. See memmap_init_zone()
++# for details.
++config NODES_SPAN_OTHER_NODES
++ def_bool y
++ depends on NEED_MULTIPLE_NODES
++
++config ARCH_POPULATES_NODE_MAP
++ def_bool y
++
+ config ARCH_SELECT_MEMORY_MODEL
+ def_bool y
+
+@@ -379,6 +392,10 @@ config SUN_OPENPROMFS
+ To compile the /proc/openprom support as a module, choose M here: the
+ module will be called openpromfs. If unsure, choose M.
+
++menu "Executable file formats"
++
++source "fs/Kconfig.binfmt"
++
+ config SPARC32_COMPAT
+ bool "Kernel support for Linux/Sparc 32bit binary compatibility"
+ help
+@@ -391,37 +408,10 @@ config COMPAT
+ default y
+ select COMPAT_BINFMT_ELF
+
+-config BINFMT_AOUT32
+- bool "Kernel support for 32-bit (ie. SunOS) a.out binaries"
+- depends on SPARC32_COMPAT && ARCH_SUPPORTS_AOUT
+- help
+- This allows you to run 32-bit a.out format binaries on your Ultra.
+- If you want to run SunOS binaries (see SunOS binary emulation below)
+- or other a.out binaries, say Y. If unsure, say N.
+-
+-menu "Executable file formats"
+-
+-source "fs/Kconfig.binfmt"
+-
+-config SUNOS_EMUL
+- bool "SunOS binary emulation"
+- depends on BINFMT_AOUT32
+- help
+- This allows you to run most SunOS binaries. If you want to do this,
+- say Y here and place appropriate files in /usr/gnemul/sunos. See
+- <http://www.ultralinux.org/faq.html> for more information. If you
+- want to run SunOS binaries on an Ultra you must also say Y to
+- "Kernel support for 32-bit a.out binaries" above.
+-
+-config SOLARIS_EMUL
+- tristate "Solaris binary emulation (EXPERIMENTAL)"
+- depends on SPARC32_COMPAT && NET && EXPERIMENTAL
+- help
+- This is experimental code which will enable you to run (many)
+- Solaris binaries on your SPARC Linux machine.
+-
+- To compile this code as a module, choose M here: the
+- module will be called solaris.
++config SYSVIPC_COMPAT
++ bool
++ depends on COMPAT && SYSVIPC
++ default y
+
+ endmenu
+
+diff --git a/arch/sparc64/Makefile b/arch/sparc64/Makefile
+index f0c22f8..9cb75c8 100644
+--- a/arch/sparc64/Makefile
++++ b/arch/sparc64/Makefile
+@@ -27,7 +27,6 @@ endif
+ head-y := arch/sparc64/kernel/head.o arch/sparc64/kernel/init_task.o
+
+ core-y += arch/sparc64/kernel/ arch/sparc64/mm/
+-core-$(CONFIG_SOLARIS_EMUL) += arch/sparc64/solaris/
+ core-y += arch/sparc64/math-emu/
+ libs-y += arch/sparc64/prom/ arch/sparc64/lib/
+ drivers-$(CONFIG_OPROFILE) += arch/sparc64/oprofile/
+diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
+index 9d4bd22..92f7968 100644
+--- a/arch/sparc64/defconfig
++++ b/arch/sparc64/defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc3
+-# Wed Mar 26 04:33:35 2008
++# Linux kernel version: 2.6.25-numa
++# Wed Apr 23 04:49:08 2008
+ #
+ CONFIG_SPARC=y
+ CONFIG_SPARC64=y
+@@ -22,7 +22,6 @@ CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+ CONFIG_ARCH_NO_VIRT_TO_BUS=y
+ CONFIG_OF=y
+ CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+-CONFIG_ARCH_SUPPORTS_AOUT=y
+ CONFIG_SPARC64_PAGE_SIZE_8KB=y
+ # CONFIG_SPARC64_PAGE_SIZE_64KB is not set
+ # CONFIG_SPARC64_PAGE_SIZE_512KB is not set
+@@ -61,6 +60,7 @@ CONFIG_RT_GROUP_SCHED=y
+ CONFIG_USER_SCHED=y
+ # CONFIG_CGROUP_SCHED is not set
+ CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
+ CONFIG_RELAY=y
+ CONFIG_NAMESPACES=y
+ # CONFIG_UTS_NS is not set
+@@ -100,7 +100,9 @@ CONFIG_PROFILING=y
+ CONFIG_OPROFILE=m
+ CONFIG_HAVE_OPROFILE=y
+ CONFIG_KPROBES=y
++CONFIG_KRETPROBES=y
+ CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
+ CONFIG_PROC_PAGE_MONITOR=y
+ CONFIG_SLABINFO=y
+ CONFIG_RT_MUTEXES=y
+@@ -131,8 +133,6 @@ CONFIG_DEFAULT_AS=y
+ # CONFIG_DEFAULT_NOOP is not set
+ CONFIG_DEFAULT_IOSCHED="anticipatory"
+ CONFIG_CLASSIC_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-CONFIG_SYSVIPC_COMPAT=y
+ CONFIG_GENERIC_HARDIRQS=y
+
+ #
+@@ -152,6 +152,8 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
+ CONFIG_HUGETLB_PAGE_SIZE_4MB=y
+ # CONFIG_HUGETLB_PAGE_SIZE_512K is not set
+ # CONFIG_HUGETLB_PAGE_SIZE_64K is not set
++# CONFIG_NUMA is not set
++CONFIG_ARCH_POPULATES_NODE_MAP=y
+ CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+ CONFIG_ARCH_SPARSEMEM_ENABLE=y
+ CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+@@ -182,9 +184,6 @@ CONFIG_PCI_MSI=y
+ # CONFIG_PCI_LEGACY is not set
+ # CONFIG_PCI_DEBUG is not set
+ CONFIG_SUN_OPENPROMFS=m
+-CONFIG_SPARC32_COMPAT=y
+-CONFIG_COMPAT=y
+-# CONFIG_BINFMT_AOUT32 is not set
+
+ #
+ # Executable file formats
+@@ -192,13 +191,14 @@ CONFIG_COMPAT=y
+ CONFIG_BINFMT_ELF=y
+ CONFIG_COMPAT_BINFMT_ELF=y
+ CONFIG_BINFMT_MISC=m
+-CONFIG_SOLARIS_EMUL=y
++CONFIG_SPARC32_COMPAT=y
++CONFIG_COMPAT=y
++CONFIG_SYSVIPC_COMPAT=y
+ CONFIG_SCHED_SMT=y
+ CONFIG_SCHED_MC=y
+ # CONFIG_PREEMPT_NONE is not set
+ CONFIG_PREEMPT_VOLUNTARY=y
+ # CONFIG_PREEMPT is not set
+-# CONFIG_RCU_TRACE is not set
+ # CONFIG_CMDLINE_BOOL is not set
+
+ #
+@@ -263,8 +263,10 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=m
+ CONFIG_INET6_XFRM_MODE_BEET=m
+ # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+ CONFIG_IPV6_SIT=m
++CONFIG_IPV6_NDISC_NODETYPE=y
+ CONFIG_IPV6_TUNNEL=m
+ # CONFIG_IPV6_MULTIPLE_TABLES is not set
++# CONFIG_IPV6_MROUTE is not set
+ # CONFIG_NETWORK_SECMARK is not set
+ # CONFIG_NETFILTER is not set
+ CONFIG_IP_DCCP=m
+@@ -368,7 +370,7 @@ CONFIG_IDE=y
+ CONFIG_BLK_DEV_IDE=y
+
+ #
+-# Please see Documentation/ide.txt for help/info on IDE drives
++# Please see Documentation/ide/ide.txt for help/info on IDE drives
+ #
+ # CONFIG_BLK_DEV_IDE_SATA is not set
+ CONFIG_BLK_DEV_IDEDISK=y
+@@ -384,7 +386,6 @@ CONFIG_IDE_PROC_FS=y
+ #
+ # IDE chipset support/bugfixes
+ #
+-CONFIG_IDE_GENERIC=y
+ # CONFIG_BLK_DEV_PLATFORM is not set
+ CONFIG_BLK_DEV_IDEDMA_SFF=y
+
+@@ -422,7 +423,7 @@ CONFIG_BLK_DEV_ALI15X3=y
+ # CONFIG_BLK_DEV_VIA82CXXX is not set
+ # CONFIG_BLK_DEV_TC86C001 is not set
+ CONFIG_BLK_DEV_IDEDMA=y
+-CONFIG_IDE_ARCH_OBSOLETE_INIT=y
++# CONFIG_BLK_DEV_HD_ONLY is not set
+ # CONFIG_BLK_DEV_HD is not set
+
+ #
+@@ -588,7 +589,6 @@ CONFIG_E1000_NAPI=y
+ # CONFIG_SIS190 is not set
+ # CONFIG_SKGE is not set
+ # CONFIG_SKY2 is not set
+-# CONFIG_SK98LIN is not set
+ # CONFIG_VIA_VELOCITY is not set
+ CONFIG_TIGON3=m
+ CONFIG_BNX2=m
+@@ -613,6 +613,7 @@ CONFIG_NIU=m
+ #
+ # CONFIG_WLAN_PRE80211 is not set
+ # CONFIG_WLAN_80211 is not set
++# CONFIG_IWLWIFI_LEDS is not set
+
+ #
+ # USB Network Adapters
+@@ -788,7 +789,6 @@ CONFIG_I2C_ALGOBIT=y
+ # CONFIG_SENSORS_PCF8574 is not set
+ # CONFIG_PCF8575 is not set
+ # CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_TPS65010 is not set
+ # CONFIG_SENSORS_MAX6875 is not set
+ # CONFIG_SENSORS_TSL2550 is not set
+ # CONFIG_I2C_DEBUG_CORE is not set
+@@ -870,6 +870,7 @@ CONFIG_SSB_POSSIBLE=y
+ # Multifunction device drivers
+ #
+ # CONFIG_MFD_SM501 is not set
++# CONFIG_HTC_PASIC3 is not set
+
+ #
+ # Multimedia devices
+@@ -1220,10 +1221,6 @@ CONFIG_USB_STORAGE=m
+ # CONFIG_NEW_LEDS is not set
+ # CONFIG_INFINIBAND is not set
+ # CONFIG_RTC_CLASS is not set
+-
+-#
+-# Userspace I/O
+-#
+ # CONFIG_UIO is not set
+
+ #
+@@ -1400,6 +1397,7 @@ CONFIG_SCHEDSTATS=y
+ CONFIG_DEBUG_BUGVERBOSE=y
+ # CONFIG_DEBUG_INFO is not set
+ # CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_WRITECOUNT is not set
+ # CONFIG_DEBUG_LIST is not set
+ # CONFIG_DEBUG_SG is not set
+ # CONFIG_BOOT_PRINTK_DELAY is not set
+@@ -1426,53 +1424,82 @@ CONFIG_ASYNC_CORE=m
+ CONFIG_ASYNC_MEMCPY=m
+ CONFIG_ASYNC_XOR=m
+ CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
+ CONFIG_CRYPTO_ALGAPI=y
+ CONFIG_CRYPTO_AEAD=y
+ CONFIG_CRYPTO_BLKCIPHER=y
+-# CONFIG_CRYPTO_SEQIV is not set
+ CONFIG_CRYPTO_HASH=y
+ CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_GF128MUL=m
++CONFIG_CRYPTO_NULL=m
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_AUTHENC=y
++CONFIG_CRYPTO_TEST=m
++
++#
++# Authenticated Encryption with Associated Data
++#
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_SEQIV is not set
++
++#
++# Block modes
++#
++CONFIG_CRYPTO_CBC=y
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_CTS is not set
++CONFIG_CRYPTO_ECB=m
++CONFIG_CRYPTO_LRW=m
++CONFIG_CRYPTO_PCBC=m
++CONFIG_CRYPTO_XTS=m
++
++#
++# Hash modes
++#
+ CONFIG_CRYPTO_HMAC=y
+ CONFIG_CRYPTO_XCBC=y
+-CONFIG_CRYPTO_NULL=m
++
++#
++# Digest
++#
++CONFIG_CRYPTO_CRC32C=m
+ CONFIG_CRYPTO_MD4=y
+ CONFIG_CRYPTO_MD5=y
++CONFIG_CRYPTO_MICHAEL_MIC=m
+ CONFIG_CRYPTO_SHA1=y
+ CONFIG_CRYPTO_SHA256=m
+ CONFIG_CRYPTO_SHA512=m
+-CONFIG_CRYPTO_WP512=m
+ CONFIG_CRYPTO_TGR192=m
+-CONFIG_CRYPTO_GF128MUL=m
+-CONFIG_CRYPTO_ECB=m
+-CONFIG_CRYPTO_CBC=y
+-CONFIG_CRYPTO_PCBC=m
+-CONFIG_CRYPTO_LRW=m
+-CONFIG_CRYPTO_XTS=m
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_GCM is not set
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_CRYPTD is not set
+-CONFIG_CRYPTO_DES=y
+-CONFIG_CRYPTO_FCRYPT=m
+-CONFIG_CRYPTO_BLOWFISH=m
+-CONFIG_CRYPTO_TWOFISH=m
+-CONFIG_CRYPTO_TWOFISH_COMMON=m
+-CONFIG_CRYPTO_SERPENT=m
++CONFIG_CRYPTO_WP512=m
++
++#
++# Ciphers
++#
+ CONFIG_CRYPTO_AES=m
++CONFIG_CRYPTO_ANUBIS=m
++CONFIG_CRYPTO_ARC4=m
++CONFIG_CRYPTO_BLOWFISH=m
++CONFIG_CRYPTO_CAMELLIA=m
+ CONFIG_CRYPTO_CAST5=m
+ CONFIG_CRYPTO_CAST6=m
+-CONFIG_CRYPTO_TEA=m
+-CONFIG_CRYPTO_ARC4=m
++CONFIG_CRYPTO_DES=y
++CONFIG_CRYPTO_FCRYPT=m
+ CONFIG_CRYPTO_KHAZAD=m
+-CONFIG_CRYPTO_ANUBIS=m
+-CONFIG_CRYPTO_SEED=m
+ # CONFIG_CRYPTO_SALSA20 is not set
++CONFIG_CRYPTO_SEED=m
++CONFIG_CRYPTO_SERPENT=m
++CONFIG_CRYPTO_TEA=m
++CONFIG_CRYPTO_TWOFISH=m
++CONFIG_CRYPTO_TWOFISH_COMMON=m
++
++#
++# Compression
++#
+ CONFIG_CRYPTO_DEFLATE=y
+-CONFIG_CRYPTO_MICHAEL_MIC=m
+-CONFIG_CRYPTO_CRC32C=m
+-CONFIG_CRYPTO_CAMELLIA=m
+-CONFIG_CRYPTO_TEST=m
+-CONFIG_CRYPTO_AUTHENC=m
+ # CONFIG_CRYPTO_LZO is not set
+ CONFIG_CRYPTO_HW=y
+ # CONFIG_CRYPTO_DEV_HIFN_795X is not set
+@@ -1493,3 +1520,4 @@ CONFIG_PLIST=y
+ CONFIG_HAS_IOMEM=y
+ CONFIG_HAS_IOPORT=y
+ CONFIG_HAS_DMA=y
++CONFIG_HAVE_LMB=y
+diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
+index 1bf5b18..63c6ae0 100644
+--- a/arch/sparc64/kernel/Makefile
++++ b/arch/sparc64/kernel/Makefile
+@@ -10,7 +10,7 @@ extra-y := head.o init_task.o vmlinux.lds
+ obj-y := process.o setup.o cpu.o idprom.o \
+ traps.o auxio.o una_asm.o sysfs.o iommu.o \
+ irq.o ptrace.o time.o sys_sparc.o signal.o \
+- unaligned.o central.o pci.o starfire.o semaphore.o \
++ unaligned.o central.o pci.o starfire.o \
+ power.o sbus.o sparc64_ksyms.o chmc.o \
+ visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o
+
+@@ -21,7 +21,6 @@ obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o \
+ obj-$(CONFIG_PCI_MSI) += pci_msi.o
+ obj-$(CONFIG_SMP) += smp.o trampoline.o hvtramp.o
+ obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o
+-obj-$(CONFIG_BINFMT_AOUT32) += binfmt_aout32.o
+ obj-$(CONFIG_MODULES) += module.o
+ obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o
+ obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o
+@@ -30,11 +29,3 @@ obj-$(CONFIG_SUN_LDOMS) += ldc.o vio.o viohs.o ds.o
+ obj-$(CONFIG_AUDIT) += audit.o
+ obj-$(CONFIG_AUDIT)$(CONFIG_SPARC32_COMPAT) += compat_audit.o
+ obj-y += $(obj-yy)
+-
+-ifdef CONFIG_SUNOS_EMUL
+- obj-y += sys_sunos32.o sunos_ioctl32.o
+-else
+- ifdef CONFIG_SOLARIS_EMUL
+- obj-y += sys_sunos32.o sunos_ioctl32.o
+- endif
+-endif
+diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c
+deleted file mode 100644
+index 9877f2d..0000000
+--- a/arch/sparc64/kernel/binfmt_aout32.c
++++ /dev/null
+@@ -1,419 +0,0 @@
+-/*
+- * linux/fs/binfmt_aout.c
+- *
+- * Copyright (C) 1991, 1992, 1996 Linus Torvalds
+- *
+- * Hacked a bit by DaveM to make it work with 32-bit SunOS
+- * binaries on the sparc64 port.
+- */
+-
+-#include <linux/module.h>
+-
+-#include <linux/sched.h>
+-#include <linux/kernel.h>
+-#include <linux/mm.h>
+-#include <linux/mman.h>
+-#include <linux/a.out.h>
+-#include <linux/errno.h>
+-#include <linux/signal.h>
+-#include <linux/string.h>
+-#include <linux/fs.h>
+-#include <linux/file.h>
+-#include <linux/stat.h>
+-#include <linux/fcntl.h>
+-#include <linux/ptrace.h>
+-#include <linux/user.h>
+-#include <linux/slab.h>
+-#include <linux/binfmts.h>
+-#include <linux/personality.h>
+-#include <linux/init.h>
+-
+-#include <asm/system.h>
+-#include <asm/uaccess.h>
+-#include <asm/pgalloc.h>
+-#include <asm/mmu_context.h>
+-#include <asm/a.out-core.h>
+-
+-static int load_aout32_binary(struct linux_binprm *, struct pt_regs * regs);
+-static int load_aout32_library(struct file*);
+-static int aout32_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
+-
+-static struct linux_binfmt aout32_format = {
+- .module = THIS_MODULE,
+- .load_binary = load_aout32_binary,
+- .load_shlib = load_aout32_library,
+- .core_dump = aout32_core_dump,
+- .min_coredump = PAGE_SIZE,
+-};
+-
+-static void set_brk(unsigned long start, unsigned long end)
+-{
+- start = PAGE_ALIGN(start);
+- end = PAGE_ALIGN(end);
+- if (end <= start)
+- return;
+- down_write(¤t->mm->mmap_sem);
+- do_brk(start, end - start);
+- up_write(¤t->mm->mmap_sem);
+-}
+-
+-/*
+- * These are the only things you should do on a core-file: use only these
+- * macros to write out all the necessary info.
+- */
+-
+-static int dump_write(struct file *file, const void *addr, int nr)
+-{
+- return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
+-}
+-
+-#define DUMP_WRITE(addr, nr) \
+- if (!dump_write(file, (void *)(addr), (nr))) \
+- goto end_coredump;
+-
+-#define DUMP_SEEK(offset) \
+-if (file->f_op->llseek) { \
+- if (file->f_op->llseek(file,(offset),0) != (offset)) \
+- goto end_coredump; \
+-} else file->f_pos = (offset)
+-
+-/*
+- * Routine writes a core dump image in the current directory.
+- * Currently only a stub-function.
+- *
+- * Note that setuid/setgid files won't make a core-dump if the uid/gid
+- * changed due to the set[u|g]id. It's enforced by the "current->mm->dumpable"
+- * field, which also makes sure the core-dumps won't be recursive if the
+- * dumping of the process results in another error..
+- */
+-
+-static int aout32_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit)
+-{
+- mm_segment_t fs;
+- int has_dumped = 0;
+- unsigned long dump_start, dump_size;
+- struct user dump;
+-# define START_DATA(u) (u.u_tsize)
+-# define START_STACK(u) ((regs->u_regs[UREG_FP]) & ~(PAGE_SIZE - 1))
+-
+- fs = get_fs();
+- set_fs(KERNEL_DS);
+- has_dumped = 1;
+- current->flags |= PF_DUMPCORE;
+- strncpy(dump.u_comm, current->comm, sizeof(dump.u_comm));
+- dump.signal = signr;
+- aout_dump_thread(regs, &dump);
+-
+-/* If the size of the dump file exceeds the rlimit, then see what would happen
+- if we wrote the stack, but not the data area. */
+- if (dump.u_dsize + dump.u_ssize > limit)
+- dump.u_dsize = 0;
+-
+-/* Make sure we have enough room to write the stack and data areas. */
+- if (dump.u_ssize > limit)
+- dump.u_ssize = 0;
+-
+-/* make sure we actually have a data and stack area to dump */
+- set_fs(USER_DS);
+- if (!access_ok(VERIFY_READ, (void __user *) START_DATA(dump), dump.u_dsize))
+- dump.u_dsize = 0;
+- if (!access_ok(VERIFY_READ, (void __user *) START_STACK(dump), dump.u_ssize))
+- dump.u_ssize = 0;
+-
+- set_fs(KERNEL_DS);
+-/* struct user */
+- DUMP_WRITE(&dump,sizeof(dump));
+-/* now we start writing out the user space info */
+- set_fs(USER_DS);
+-/* Dump the data area */
+- if (dump.u_dsize != 0) {
+- dump_start = START_DATA(dump);
+- dump_size = dump.u_dsize;
+- DUMP_WRITE(dump_start,dump_size);
+- }
+-/* Now prepare to dump the stack area */
+- if (dump.u_ssize != 0) {
+- dump_start = START_STACK(dump);
+- dump_size = dump.u_ssize;
+- DUMP_WRITE(dump_start,dump_size);
+- }
+-/* Finally dump the task struct. Not be used by gdb, but could be useful */
+- set_fs(KERNEL_DS);
+- DUMP_WRITE(current,sizeof(*current));
+-end_coredump:
+- set_fs(fs);
+- return has_dumped;
+-}
+-
+-/*
+- * create_aout32_tables() parses the env- and arg-strings in new user
+- * memory and creates the pointer tables from them, and puts their
+- * addresses on the "stack", returning the new stack pointer value.
+- */
+-
+-static u32 __user *create_aout32_tables(char __user *p, struct linux_binprm *bprm)
+-{
+- u32 __user *argv;
+- u32 __user *envp;
+- u32 __user *sp;
+- int argc = bprm->argc;
+- int envc = bprm->envc;
+-
+- sp = (u32 __user *)((-(unsigned long)sizeof(char *))&(unsigned long)p);
+-
+- /* This imposes the proper stack alignment for a new process. */
+- sp = (u32 __user *) (((unsigned long) sp) & ~7);
+- if ((envc+argc+3)&1)
+- --sp;
+-
+- sp -= envc+1;
+- envp = sp;
+- sp -= argc+1;
+- argv = sp;
+- put_user(argc,--sp);
+- current->mm->arg_start = (unsigned long) p;
+- while (argc-->0) {
+- char c;
+- put_user(((u32)(unsigned long)(p)),argv++);
+- do {
+- get_user(c,p++);
+- } while (c);
+- }
+- put_user(0,argv);
+- current->mm->arg_end = current->mm->env_start = (unsigned long) p;
+- while (envc-->0) {
+- char c;
+- put_user(((u32)(unsigned long)(p)),envp++);
+- do {
+- get_user(c,p++);
+- } while (c);
+- }
+- put_user(0,envp);
+- current->mm->env_end = (unsigned long) p;
+- return sp;
+-}
+-
+-/*
+- * These are the functions used to load a.out style executables and shared
+- * libraries. There is no binary dependent code anywhere else.
+- */
+-
+-static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+-{
+- struct exec ex;
+- unsigned long error;
+- unsigned long fd_offset;
+- unsigned long rlim;
+- unsigned long orig_thr_flags;
+- int retval;
+-
+- ex = *((struct exec *) bprm->buf); /* exec-header */
+- if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
+- N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
+- N_TRSIZE(ex) || N_DRSIZE(ex) ||
+- bprm->file->f_path.dentry->d_inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
+- return -ENOEXEC;
+- }
+-
+- fd_offset = N_TXTOFF(ex);
+-
+- /* Check initial limits. This avoids letting people circumvent
+- * size limits imposed on them by creating programs with large
+- * arrays in the data or bss.
+- */
+- rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
+- if (rlim >= RLIM_INFINITY)
+- rlim = ~0;
+- if (ex.a_data + ex.a_bss > rlim)
+- return -ENOMEM;
+-
+- /* Flush all traces of the currently running executable */
+- retval = flush_old_exec(bprm);
+- if (retval)
+- return retval;
+-
+- /* OK, This is the point of no return */
+- set_personality(PER_SUNOS);
+-
+- current->mm->end_code = ex.a_text +
+- (current->mm->start_code = N_TXTADDR(ex));
+- current->mm->end_data = ex.a_data +
+- (current->mm->start_data = N_DATADDR(ex));
+- current->mm->brk = ex.a_bss +
+- (current->mm->start_brk = N_BSSADDR(ex));
+- current->mm->free_area_cache = current->mm->mmap_base;
+- current->mm->cached_hole_size = 0;
+-
+- current->mm->mmap = NULL;
+- compute_creds(bprm);
+- current->flags &= ~PF_FORKNOEXEC;
+- if (N_MAGIC(ex) == NMAGIC) {
+- loff_t pos = fd_offset;
+- /* Fuck me plenty... */
+- down_write(¤t->mm->mmap_sem);
+- error = do_brk(N_TXTADDR(ex), ex.a_text);
+- up_write(¤t->mm->mmap_sem);
+- bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex),
+- ex.a_text, &pos);
+- down_write(¤t->mm->mmap_sem);
+- error = do_brk(N_DATADDR(ex), ex.a_data);
+- up_write(¤t->mm->mmap_sem);
+- bprm->file->f_op->read(bprm->file, (char __user *)N_DATADDR(ex),
+- ex.a_data, &pos);
+- goto beyond_if;
+- }
+-
+- if (N_MAGIC(ex) == OMAGIC) {
+- loff_t pos = fd_offset;
+- down_write(¤t->mm->mmap_sem);
+- do_brk(N_TXTADDR(ex) & PAGE_MASK,
+- ex.a_text+ex.a_data + PAGE_SIZE - 1);
+- up_write(¤t->mm->mmap_sem);
+- bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex),
+- ex.a_text+ex.a_data, &pos);
+- } else {
+- static unsigned long error_time;
+- if ((ex.a_text & 0xfff || ex.a_data & 0xfff) &&
+- (N_MAGIC(ex) != NMAGIC) && (jiffies-error_time) > 5*HZ)
+- {
+- printk(KERN_NOTICE "executable not page aligned\n");
+- error_time = jiffies;
+- }
+-
+- if (!bprm->file->f_op->mmap) {
+- loff_t pos = fd_offset;
+- down_write(¤t->mm->mmap_sem);
+- do_brk(0, ex.a_text+ex.a_data);
+- up_write(¤t->mm->mmap_sem);
+- bprm->file->f_op->read(bprm->file,
+- (char __user *)N_TXTADDR(ex),
+- ex.a_text+ex.a_data, &pos);
+- goto beyond_if;
+- }
+-
+- down_write(¤t->mm->mmap_sem);
+- error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
+- PROT_READ | PROT_EXEC,
+- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
+- fd_offset);
+- up_write(¤t->mm->mmap_sem);
+-
+- if (error != N_TXTADDR(ex)) {
+- send_sig(SIGKILL, current, 0);
+- return error;
+- }
+-
+- down_write(¤t->mm->mmap_sem);
+- error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
+- PROT_READ | PROT_WRITE | PROT_EXEC,
+- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
+- fd_offset + ex.a_text);
+- up_write(¤t->mm->mmap_sem);
+- if (error != N_DATADDR(ex)) {
+- send_sig(SIGKILL, current, 0);
+- return error;
+- }
+- }
+-beyond_if:
+- set_binfmt(&aout32_format);
+-
+- set_brk(current->mm->start_brk, current->mm->brk);
+-
+- /* Make sure STACK_TOP returns the right thing. */
+- orig_thr_flags = current_thread_info()->flags;
+- current_thread_info()->flags |= _TIF_32BIT;
+-
+- retval = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);
+- if (retval < 0) {
+- current_thread_info()->flags = orig_thr_flags;
+-
+- /* Someone check-me: is this error path enough? */
+- send_sig(SIGKILL, current, 0);
+- return retval;
+- }
+-
+- current->mm->start_stack =
+- (unsigned long) create_aout32_tables((char __user *)bprm->p, bprm);
+- tsb_context_switch(current->mm);
+-
+- start_thread32(regs, ex.a_entry, current->mm->start_stack);
+- if (current->ptrace & PT_PTRACED)
+- send_sig(SIGTRAP, current, 0);
+- return 0;
+-}
+-
+-/* N.B. Move to .h file and use code in fs/binfmt_aout.c? */
+-static int load_aout32_library(struct file *file)
+-{
+- struct inode * inode;
+- unsigned long bss, start_addr, len;
+- unsigned long error;
+- int retval;
+- struct exec ex;
+-
+- inode = file->f_path.dentry->d_inode;
+-
+- retval = -ENOEXEC;
+- error = kernel_read(file, 0, (char *) &ex, sizeof(ex));
+- if (error != sizeof(ex))
+- goto out;
+-
+- /* We come in here for the regular a.out style of shared libraries */
+- if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) ||
+- N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
+- inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
+- goto out;
+- }
+-
+- if (N_MAGIC(ex) == ZMAGIC && N_TXTOFF(ex) &&
+- (N_TXTOFF(ex) < inode->i_sb->s_blocksize)) {
+- printk("N_TXTOFF < BLOCK_SIZE. Please convert library\n");
+- goto out;
+- }
+-
+- if (N_FLAGS(ex))
+- goto out;
+-
+- /* For QMAGIC, the starting address is 0x20 into the page. We mask
+- this off to get the starting address for the page */
+-
+- start_addr = ex.a_entry & 0xfffff000;
+-
+- /* Now use mmap to map the library into memory. */
+- down_write(¤t->mm->mmap_sem);
+- error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
+- PROT_READ | PROT_WRITE | PROT_EXEC,
+- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
+- N_TXTOFF(ex));
+- up_write(¤t->mm->mmap_sem);
+- retval = error;
+- if (error != start_addr)
+- goto out;
+-
+- len = PAGE_ALIGN(ex.a_text + ex.a_data);
+- bss = ex.a_text + ex.a_data + ex.a_bss;
+- if (bss > len) {
+- down_write(¤t->mm->mmap_sem);
+- error = do_brk(start_addr + len, bss - len);
+- up_write(¤t->mm->mmap_sem);
+- retval = error;
+- if (error != start_addr + len)
+- goto out;
+- }
+- retval = 0;
+-out:
+- return retval;
+-}
+-
+-static int __init init_aout32_binfmt(void)
+-{
+- return register_binfmt(&aout32_format);
+-}
+-
+-static void __exit exit_aout32_binfmt(void)
+-{
+- unregister_binfmt(&aout32_format);
+-}
+-
+-module_init(init_aout32_binfmt);
+-module_exit(exit_aout32_binfmt);
+diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c
+index 04ab81c..bc26322 100644
+--- a/arch/sparc64/kernel/ebus.c
++++ b/arch/sparc64/kernel/ebus.c
+@@ -396,6 +396,7 @@ static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_de
+ sd->op = &dev->ofdev;
+ sd->iommu = dev->bus->ofdev.dev.parent->archdata.iommu;
+ sd->stc = dev->bus->ofdev.dev.parent->archdata.stc;
++ sd->numa_node = dev->bus->ofdev.dev.parent->archdata.numa_node;
+
+ dev->ofdev.node = dp;
+ dev->ofdev.dev.parent = &dev->bus->ofdev.dev;
+diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
+index 49eca4b..fd06e93 100644
+--- a/arch/sparc64/kernel/entry.S
++++ b/arch/sparc64/kernel/entry.S
+@@ -47,7 +47,7 @@ do_fpdis:
+ ba,pt %xcc, etrap
+ 109: or %g7, %lo(109b), %g7
+ add %g0, %g0, %g0
+- ba,a,pt %xcc, rtrap_clr_l6
++ ba,a,pt %xcc, rtrap
+
+ 1: TRAP_LOAD_THREAD_REG(%g6, %g1)
+ ldub [%g6 + TI_FPSAVED], %g5
+@@ -226,7 +226,7 @@ fp_other_bounce:
+ call do_fpother
+ add %sp, PTREGS_OFF, %o0
+ ba,pt %xcc, rtrap
+- clr %l6
++ nop
+
+ .globl do_fpother_check_fitos
+ .align 32
+@@ -489,7 +489,7 @@ utrap_trap: /* %g3=handler,%g4=level */
+ call bad_trap
+ add %sp, PTREGS_OFF, %o0
+ ba,pt %xcc, rtrap
+- clr %l6
++ nop
+
+ invoke_utrap:
+ sllx %g3, 3, %g3
+@@ -607,7 +607,7 @@ __spitfire_cee_trap_continue:
+ call spitfire_access_error
+ add %sp, PTREGS_OFF, %o0
+ ba,pt %xcc, rtrap
+- clr %l6
++ nop
+
+ /* This is the trap handler entry point for ECC correctable
+ * errors. They are corrected, but we listen for the trap
+@@ -686,7 +686,7 @@ __spitfire_data_access_exception_tl1:
+ call spitfire_data_access_exception_tl1
+ add %sp, PTREGS_OFF, %o0
+ ba,pt %xcc, rtrap
+- clr %l6
++ nop
+
+ __spitfire_data_access_exception:
+ rdpr %pstate, %g4
+@@ -705,7 +705,7 @@ __spitfire_data_access_exception:
+ call spitfire_data_access_exception
+ add %sp, PTREGS_OFF, %o0
+ ba,pt %xcc, rtrap
+- clr %l6
++ nop
+
+ .globl __spitfire_insn_access_exception
+ .globl __spitfire_insn_access_exception_tl1
+@@ -725,7 +725,7 @@ __spitfire_insn_access_exception_tl1:
+ call spitfire_insn_access_exception_tl1
+ add %sp, PTREGS_OFF, %o0
+ ba,pt %xcc, rtrap
+- clr %l6
++ nop
+
+ __spitfire_insn_access_exception:
+ rdpr %pstate, %g4
+@@ -743,7 +743,7 @@ __spitfire_insn_access_exception:
+ call spitfire_insn_access_exception
+ add %sp, PTREGS_OFF, %o0
+ ba,pt %xcc, rtrap
+- clr %l6
++ nop
+
+ /* These get patched into the trap table at boot time
+ * once we know we have a cheetah processor.
+@@ -937,7 +937,7 @@ do_dcpe_tl1_fatal:
+ call cheetah_plus_parity_error
+ add %sp, PTREGS_OFF, %o1
+ ba,pt %xcc, rtrap
+- clr %l6
++ nop
+
+ do_icpe_tl1:
+ rdpr %tl, %g1 ! Save original trap level
+@@ -979,7 +979,7 @@ do_icpe_tl1_fatal:
+ call cheetah_plus_parity_error
+ add %sp, PTREGS_OFF, %o1
+ ba,pt %xcc, rtrap
+- clr %l6
++ nop
+
+ dcpe_icpe_tl1_common:
+ /* Flush D-cache, re-enable D/I caches in DCU and finally
+@@ -1281,7 +1281,7 @@ __do_privact:
+ call do_privact
+ add %sp, PTREGS_OFF, %o0
+ ba,pt %xcc, rtrap
+- clr %l6
++ nop
+
+ .globl do_mna
+ do_mna:
+@@ -1308,7 +1308,7 @@ do_mna:
+ call mem_address_unaligned
+ add %sp, PTREGS_OFF, %o0
+ ba,pt %xcc, rtrap
+- clr %l6
++ nop
+
+ .globl do_lddfmna
+ do_lddfmna:
+@@ -1326,7 +1326,7 @@ do_lddfmna:
+ call handle_lddfmna
+ add %sp, PTREGS_OFF, %o0
+ ba,pt %xcc, rtrap
+- clr %l6
++ nop
+
+ .globl do_stdfmna
+ do_stdfmna:
+@@ -1344,7 +1344,7 @@ do_stdfmna:
+ call handle_stdfmna
+ add %sp, PTREGS_OFF, %o0
+ ba,pt %xcc, rtrap
+- clr %l6
++ nop
+
+ .globl breakpoint_trap
+ breakpoint_trap:
+@@ -1353,63 +1353,6 @@ breakpoint_trap:
+ ba,pt %xcc, rtrap
+ nop
+
+-#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
+- defined(CONFIG_SOLARIS_EMUL_MODULE)
+- /* SunOS uses syscall zero as the 'indirect syscall' it looks
+- * like indir_syscall(scall_num, arg0, arg1, arg2...); etc.
+- * This is complete brain damage.
+- */
+- .globl sunos_indir
+-sunos_indir:
+- srl %o0, 0, %o0
+- mov %o7, %l4
+- cmp %o0, NR_SYSCALLS
+- blu,a,pt %icc, 1f
+- sll %o0, 0x2, %o0
+- sethi %hi(sunos_nosys), %l6
+- b,pt %xcc, 2f
+- or %l6, %lo(sunos_nosys), %l6
+-1: sethi %hi(sunos_sys_table), %l7
+- or %l7, %lo(sunos_sys_table), %l7
+- lduw [%l7 + %o0], %l6
+-2: mov %o1, %o0
+- mov %o2, %o1
+- mov %o3, %o2
+- mov %o4, %o3
+- mov %o5, %o4
+- call %l6
+- mov %l4, %o7
+-
+- .globl sunos_getpid
+-sunos_getpid:
+- call sys_getppid
+- nop
+- call sys_getpid
+- stx %o0, [%sp + PTREGS_OFF + PT_V9_I1]
+- b,pt %xcc, ret_sys_call
+- stx %o0, [%sp + PTREGS_OFF + PT_V9_I0]
+-
+- /* SunOS getuid() returns uid in %o0 and euid in %o1 */
+- .globl sunos_getuid
+-sunos_getuid:
+- call sys32_geteuid16
+- nop
+- call sys32_getuid16
+- stx %o0, [%sp + PTREGS_OFF + PT_V9_I1]
+- b,pt %xcc, ret_sys_call
+- stx %o0, [%sp + PTREGS_OFF + PT_V9_I0]
+-
+- /* SunOS getgid() returns gid in %o0 and egid in %o1 */
+- .globl sunos_getgid
+-sunos_getgid:
+- call sys32_getegid16
+- nop
+- call sys32_getgid16
+- stx %o0, [%sp + PTREGS_OFF + PT_V9_I1]
+- b,pt %xcc, ret_sys_call
+- stx %o0, [%sp + PTREGS_OFF + PT_V9_I0]
+-#endif
+-
+ /* SunOS's execv() call only specifies the argv argument, the
+ * environment settings are the same as the calling processes.
+ */
+@@ -1481,13 +1424,13 @@ sys32_rt_sigreturn:
+ 1: ldx [%curptr + TI_FLAGS], %l5
+ andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0
+ be,pt %icc, rtrap
+- clr %l6
++ nop
+ add %sp, PTREGS_OFF, %o0
+ call syscall_trace
+ mov 1, %o1
+
+ ba,pt %xcc, rtrap
+- clr %l6
++ nop
+
+ /* This is how fork() was meant to be done, 8 instruction entry.
+ *
+@@ -1591,7 +1534,7 @@ linux_syscall_trace:
+ mov %i4, %o4
+
+
+- /* Linux 32-bit and SunOS system calls enter here... */
++ /* Linux 32-bit system calls enter here... */
+ .align 32
+ .globl linux_sparc_syscall32
+ linux_sparc_syscall32:
+@@ -1614,9 +1557,9 @@ linux_sparc_syscall32:
+ srl %i3, 0, %o3 ! IEU0
+ ba,a,pt %xcc, 3f
+
+- /* Linux native and SunOS system calls enter here... */
++ /* Linux native system calls enter here... */
+ .align 32
+- .globl linux_sparc_syscall, ret_sys_call
++ .globl linux_sparc_syscall
+ linux_sparc_syscall:
+ /* Direct access to user regs, much faster. */
+ cmp %g1, NR_SYSCALLS ! IEU1 Group
+@@ -1662,7 +1605,7 @@ ret_sys_call:
+ bne,pn %icc, linux_syscall_trace2
+ add %l1, 0x4, %l2 ! npc = npc+4
+ stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
+- ba,pt %xcc, rtrap_clr_l6
++ ba,pt %xcc, rtrap
+ stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
+
+ 1:
+@@ -1673,7 +1616,6 @@ ret_sys_call:
+ sub %g0, %o0, %o0
+ or %g3, %g2, %g3
+ stx %o0, [%sp + PTREGS_OFF + PT_V9_I0]
+- mov 1, %l6
+ stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
+ bne,pn %icc, linux_syscall_trace2
+ add %l1, 0x4, %l2 ! npc = npc+4
+diff --git a/arch/sparc64/kernel/entry.h b/arch/sparc64/kernel/entry.h
+index 4a91e9c..32fbab6 100644
+--- a/arch/sparc64/kernel/entry.h
++++ b/arch/sparc64/kernel/entry.h
+@@ -20,7 +20,6 @@ extern void timer_interrupt(int irq, struct pt_regs *regs);
+
+ extern void do_notify_resume(struct pt_regs *regs,
+ unsigned long orig_i0,
+- int restart_syscall,
+ unsigned long thread_info_flags);
+
+ extern asmlinkage void syscall_trace(struct pt_regs *regs,
+diff --git a/arch/sparc64/kernel/etrap.S b/arch/sparc64/kernel/etrap.S
+index 4b2bf9e..b49d3b6 100644
+--- a/arch/sparc64/kernel/etrap.S
++++ b/arch/sparc64/kernel/etrap.S
+@@ -53,7 +53,11 @@ etrap_irq:
+ stx %g3, [%g2 + STACKFRAME_SZ + PT_V9_TPC]
+ rd %y, %g3
+ stx %g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC]
++ rdpr %tt, %g1
+ st %g3, [%g2 + STACKFRAME_SZ + PT_V9_Y]
++ sethi %hi(PT_REGS_MAGIC), %g3
++ or %g3, %g1, %g1
++ st %g1, [%g2 + STACKFRAME_SZ + PT_V9_MAGIC]
+
+ rdpr %cansave, %g1
+ brnz,pt %g1, etrap_save
+diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c
+index 756fa24..2a37a6c 100644
+--- a/arch/sparc64/kernel/iommu.c
++++ b/arch/sparc64/kernel/iommu.c
+@@ -173,9 +173,11 @@ void iommu_range_free(struct iommu *iommu, dma_addr_t dma_addr, unsigned long np
+ }
+
+ int iommu_table_init(struct iommu *iommu, int tsbsize,
+- u32 dma_offset, u32 dma_addr_mask)
++ u32 dma_offset, u32 dma_addr_mask,
++ int numa_node)
+ {
+- unsigned long i, tsbbase, order, sz, num_tsb_entries;
++ unsigned long i, order, sz, num_tsb_entries;
++ struct page *page;
+
+ num_tsb_entries = tsbsize / sizeof(iopte_t);
+
+@@ -188,11 +190,12 @@ int iommu_table_init(struct iommu *iommu, int tsbsize,
+ /* Allocate and initialize the free area map. */
+ sz = num_tsb_entries / 8;
+ sz = (sz + 7UL) & ~7UL;
+- iommu->arena.map = kzalloc(sz, GFP_KERNEL);
++ iommu->arena.map = kmalloc_node(sz, GFP_KERNEL, numa_node);
+ if (!iommu->arena.map) {
+ printk(KERN_ERR "IOMMU: Error, kmalloc(arena.map) failed.\n");
+ return -ENOMEM;
+ }
++ memset(iommu->arena.map, 0, sz);
+ iommu->arena.limit = num_tsb_entries;
+
+ if (tlb_type != hypervisor)
+@@ -201,21 +204,23 @@ int iommu_table_init(struct iommu *iommu, int tsbsize,
+ /* Allocate and initialize the dummy page which we
+ * set inactive IO PTEs to point to.
+ */
+- iommu->dummy_page = get_zeroed_page(GFP_KERNEL);
+- if (!iommu->dummy_page) {
++ page = alloc_pages_node(numa_node, GFP_KERNEL, 0);
++ if (!page) {
+ printk(KERN_ERR "IOMMU: Error, gfp(dummy_page) failed.\n");
+ goto out_free_map;
+ }
++ iommu->dummy_page = (unsigned long) page_address(page);
++ memset((void *)iommu->dummy_page, 0, PAGE_SIZE);
+ iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page);
+
+ /* Now allocate and setup the IOMMU page table itself. */
+ order = get_order(tsbsize);
+- tsbbase = __get_free_pages(GFP_KERNEL, order);
+- if (!tsbbase) {
++ page = alloc_pages_node(numa_node, GFP_KERNEL, order);
++ if (!page) {
+ printk(KERN_ERR "IOMMU: Error, gfp(tsb) failed.\n");
+ goto out_free_dummy_page;
+ }
+- iommu->page_table = (iopte_t *)tsbbase;
++ iommu->page_table = (iopte_t *)page_address(page);
+
+ for (i = 0; i < num_tsb_entries; i++)
+ iopte_make_dummy(iommu, &iommu->page_table[i]);
+@@ -276,20 +281,24 @@ static inline void iommu_free_ctx(struct iommu *iommu, int ctx)
+ static void *dma_4u_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_addrp, gfp_t gfp)
+ {
++ unsigned long flags, order, first_page;
+ struct iommu *iommu;
++ struct page *page;
++ int npages, nid;
+ iopte_t *iopte;
+- unsigned long flags, order, first_page;
+ void *ret;
+- int npages;
+
+ size = IO_PAGE_ALIGN(size);
+ order = get_order(size);
+ if (order >= 10)
+ return NULL;
+
+- first_page = __get_free_pages(gfp, order);
+- if (first_page == 0UL)
++ nid = dev->archdata.numa_node;
++ page = alloc_pages_node(nid, gfp, order);
++ if (unlikely(!page))
+ return NULL;
++
++ first_page = (unsigned long) page_address(page);
+ memset((char *)first_page, 0, PAGE_SIZE << order);
+
+ iommu = dev->archdata.iommu;
+diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c
+index b5f7b35..a2af5ed 100644
+--- a/arch/sparc64/kernel/isa.c
++++ b/arch/sparc64/kernel/isa.c
+@@ -92,6 +92,7 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
+ sd->op = &isa_dev->ofdev;
+ sd->iommu = isa_br->ofdev.dev.parent->archdata.iommu;
+ sd->stc = isa_br->ofdev.dev.parent->archdata.stc;
++ sd->numa_node = isa_br->ofdev.dev.parent->archdata.numa_node;
+
+ isa_dev->ofdev.node = dp;
+ isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev;
+diff --git a/arch/sparc64/kernel/mdesc.c b/arch/sparc64/kernel/mdesc.c
+index 9100835..dde52bc 100644
+--- a/arch/sparc64/kernel/mdesc.c
++++ b/arch/sparc64/kernel/mdesc.c
+@@ -1,10 +1,10 @@
+ /* mdesc.c: Sun4V machine description handling.
+ *
+- * Copyright (C) 2007 David S. Miller <davem at davemloft.net>
++ * Copyright (C) 2007, 2008 David S. Miller <davem at davemloft.net>
+ */
+ #include <linux/kernel.h>
+ #include <linux/types.h>
+-#include <linux/bootmem.h>
++#include <linux/lmb.h>
+ #include <linux/log2.h>
+ #include <linux/list.h>
+ #include <linux/slab.h>
+@@ -84,24 +84,28 @@ static void mdesc_handle_init(struct mdesc_handle *hp,
+ hp->handle_size = handle_size;
+ }
+
+-static struct mdesc_handle * __init mdesc_bootmem_alloc(unsigned int mdesc_size)
++static struct mdesc_handle * __init mdesc_lmb_alloc(unsigned int mdesc_size)
+ {
+- struct mdesc_handle *hp;
+ unsigned int handle_size, alloc_size;
++ struct mdesc_handle *hp;
++ unsigned long paddr;
+
+ handle_size = (sizeof(struct mdesc_handle) -
+ sizeof(struct mdesc_hdr) +
+ mdesc_size);
+ alloc_size = PAGE_ALIGN(handle_size);
+
+- hp = __alloc_bootmem(alloc_size, PAGE_SIZE, 0UL);
+- if (hp)
+- mdesc_handle_init(hp, handle_size, hp);
++ paddr = lmb_alloc(alloc_size, PAGE_SIZE);
+
++ hp = NULL;
++ if (paddr) {
++ hp = __va(paddr);
++ mdesc_handle_init(hp, handle_size, hp);
++ }
+ return hp;
+ }
+
+-static void mdesc_bootmem_free(struct mdesc_handle *hp)
++static void mdesc_lmb_free(struct mdesc_handle *hp)
+ {
+ unsigned int alloc_size, handle_size = hp->handle_size;
+ unsigned long start, end;
+@@ -124,9 +128,9 @@ static void mdesc_bootmem_free(struct mdesc_handle *hp)
+ }
+ }
+
+-static struct mdesc_mem_ops bootmem_mdesc_ops = {
+- .alloc = mdesc_bootmem_alloc,
+- .free = mdesc_bootmem_free,
++static struct mdesc_mem_ops lmb_mdesc_ops = {
++ .alloc = mdesc_lmb_alloc,
++ .free = mdesc_lmb_free,
+ };
+
+ static struct mdesc_handle *mdesc_kmalloc(unsigned int mdesc_size)
+@@ -888,7 +892,7 @@ void __init sun4v_mdesc_init(void)
+
+ printk("MDESC: Size is %lu bytes.\n", len);
+
+- hp = mdesc_alloc(len, &bootmem_mdesc_ops);
++ hp = mdesc_alloc(len, &lmb_mdesc_ops);
+ if (hp == NULL) {
+ prom_printf("MDESC: alloc of %lu bytes failed.\n", len);
+ prom_halt();
+diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
+index 0fd9db9..9e58e8c 100644
+--- a/arch/sparc64/kernel/of_device.c
++++ b/arch/sparc64/kernel/of_device.c
+@@ -6,6 +6,7 @@
+ #include <linux/mod_devicetable.h>
+ #include <linux/slab.h>
+ #include <linux/errno.h>
++#include <linux/irq.h>
+ #include <linux/of_device.h>
+ #include <linux/of_platform.h>
+
+@@ -660,6 +661,7 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
+ struct device_node *dp = op->node;
+ struct device_node *pp, *ip;
+ unsigned int orig_irq = irq;
++ int nid;
+
+ if (irq == 0xffffffff)
+ return irq;
+@@ -672,7 +674,7 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
+ printk("%s: direct translate %x --> %x\n",
+ dp->full_name, orig_irq, irq);
+
+- return irq;
++ goto out;
+ }
+
+ /* Something more complicated. Walk up to the root, applying
+@@ -744,6 +746,14 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
+ printk("%s: Apply IRQ trans [%s] %x --> %x\n",
+ op->node->full_name, ip->full_name, orig_irq, irq);
+
++out:
++ nid = of_node_to_nid(dp);
++ if (nid != -1) {
++ cpumask_t numa_mask = node_to_cpumask(nid);
++
++ irq_set_affinity(irq, numa_mask);
++ }
++
+ return irq;
+ }
+
+diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
+index 545356b..49f9127 100644
+--- a/arch/sparc64/kernel/pci.c
++++ b/arch/sparc64/kernel/pci.c
+@@ -369,10 +369,12 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
+ sd->host_controller = pbm;
+ sd->prom_node = node;
+ sd->op = of_find_device_by_node(node);
++ sd->numa_node = pbm->numa_node;
+
+ sd = &sd->op->dev.archdata;
+ sd->iommu = pbm->iommu;
+ sd->stc = &pbm->stc;
++ sd->numa_node = pbm->numa_node;
+
+ type = of_get_property(node, "device_type", NULL);
+ if (type == NULL)
+@@ -1159,6 +1161,16 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+ return 0;
+ }
+
++#ifdef CONFIG_NUMA
++int pcibus_to_node(struct pci_bus *pbus)
++{
++ struct pci_pbm_info *pbm = pbus->sysdata;
++
++ return pbm->numa_node;
++}
++EXPORT_SYMBOL(pcibus_to_node);
++#endif
++
+ /* Return the domain nuber for this pci bus */
+
+ int pci_domain_nr(struct pci_bus *pbus)
+diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c
+index 7571ed5..d23bb6f 100644
+--- a/arch/sparc64/kernel/pci_fire.c
++++ b/arch/sparc64/kernel/pci_fire.c
+@@ -71,7 +71,8 @@ static int pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm)
+ */
+ fire_write(iommu->iommu_flushinv, ~(u64)0);
+
+- err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask);
++ err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask,
++ pbm->numa_node);
+ if (err)
+ return err;
+
+@@ -449,6 +450,8 @@ static int __init pci_fire_pbm_init(struct pci_controller_info *p,
+ pbm->next = pci_pbm_root;
+ pci_pbm_root = pbm;
+
++ pbm->numa_node = -1;
++
+ pbm->scan_bus = pci_fire_scan_bus;
+ pbm->pci_ops = &sun4u_pci_ops;
+ pbm->config_space_reg_bits = 12;
+diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h
+index 4a50da1..218bac4 100644
+--- a/arch/sparc64/kernel/pci_impl.h
++++ b/arch/sparc64/kernel/pci_impl.h
+@@ -148,6 +148,8 @@ struct pci_pbm_info {
+ struct pci_bus *pci_bus;
+ void (*scan_bus)(struct pci_pbm_info *);
+ struct pci_ops *pci_ops;
++
++ int numa_node;
+ };
+
+ struct pci_controller_info {
+@@ -161,8 +163,6 @@ extern struct pci_pbm_info *pci_pbm_root;
+ extern int pci_num_pbms;
+
+ /* PCI bus scanning and fixup support. */
+-extern void pci_iommu_table_init(struct iommu *iommu, int tsbsize,
+- u32 dma_offset, u32 dma_addr_mask);
+ extern void pci_get_pbm_props(struct pci_pbm_info *pbm);
+ extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm);
+ extern void pci_determine_mem_io_space(struct pci_pbm_info *pbm);
+diff --git a/arch/sparc64/kernel/pci_msi.c b/arch/sparc64/kernel/pci_msi.c
+index d6d64b4..db5e8fd 100644
+--- a/arch/sparc64/kernel/pci_msi.c
++++ b/arch/sparc64/kernel/pci_msi.c
+@@ -279,11 +279,17 @@ static int bringup_one_msi_queue(struct pci_pbm_info *pbm,
+ unsigned long devino)
+ {
+ int irq = ops->msiq_build_irq(pbm, msiqid, devino);
+- int err;
++ int err, nid;
+
+ if (irq < 0)
+ return irq;
+
++ nid = pbm->numa_node;
++ if (nid != -1) {
++ cpumask_t numa_mask = node_to_cpumask(nid);
++
++ irq_set_affinity(irq, numa_mask);
++ }
+ err = request_irq(irq, sparc64_msiq_interrupt, 0,
+ "MSIQ",
+ &pbm->msiq_irq_cookies[msiqid - pbm->msiq_first]);
+diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
+index 0bad96e..994dbe0 100644
+--- a/arch/sparc64/kernel/pci_psycho.c
++++ b/arch/sparc64/kernel/pci_psycho.c
+@@ -848,7 +848,8 @@ static int psycho_iommu_init(struct pci_pbm_info *pbm)
+ /* Leave diag mode enabled for full-flushing done
+ * in pci_iommu.c
+ */
+- err = iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff);
++ err = iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff,
++ pbm->numa_node);
+ if (err)
+ return err;
+
+@@ -979,6 +980,8 @@ static void __init psycho_pbm_init(struct pci_controller_info *p,
+ pbm->next = pci_pbm_root;
+ pci_pbm_root = pbm;
+
++ pbm->numa_node = -1;
++
+ pbm->scan_bus = psycho_scan_bus;
+ pbm->pci_ops = &sun4u_pci_ops;
+ pbm->config_space_reg_bits = 8;
+diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
+index 1c5f5fa..4c34195 100644
+--- a/arch/sparc64/kernel/pci_sabre.c
++++ b/arch/sparc64/kernel/pci_sabre.c
+@@ -704,7 +704,7 @@ static int sabre_iommu_init(struct pci_pbm_info *pbm,
+ * in pci_iommu.c
+ */
+ err = iommu_table_init(iommu, tsbsize * 1024 * 8,
+- dvma_offset, dma_mask);
++ dvma_offset, dma_mask, pbm->numa_node);
+ if (err)
+ return err;
+
+@@ -737,6 +737,8 @@ static void __init sabre_pbm_init(struct pci_controller_info *p,
+ pbm->name = dp->full_name;
+ printk("%s: SABRE PCI Bus Module\n", pbm->name);
+
++ pbm->numa_node = -1;
++
+ pbm->scan_bus = sabre_scan_bus;
+ pbm->pci_ops = &sun4u_pci_ops;
+ pbm->config_space_reg_bits = 8;
+diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
+index e306093..615edd9 100644
+--- a/arch/sparc64/kernel/pci_schizo.c
++++ b/arch/sparc64/kernel/pci_schizo.c
+@@ -1220,7 +1220,8 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
+ /* Leave diag mode enabled for full-flushing done
+ * in pci_iommu.c
+ */
+- err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask);
++ err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask,
++ pbm->numa_node);
+ if (err)
+ return err;
+
+@@ -1379,6 +1380,8 @@ static int __init schizo_pbm_init(struct pci_controller_info *p,
+ pbm->next = pci_pbm_root;
+ pci_pbm_root = pbm;
+
++ pbm->numa_node = -1;
++
+ pbm->scan_bus = schizo_scan_bus;
+ pbm->pci_ops = &sun4u_pci_ops;
+ pbm->config_space_reg_bits = 8;
+diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
+index 0183970..e2bb979 100644
+--- a/arch/sparc64/kernel/pci_sun4v.c
++++ b/arch/sparc64/kernel/pci_sun4v.c
+@@ -127,10 +127,12 @@ static inline long iommu_batch_end(void)
+ static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_addrp, gfp_t gfp)
+ {
+- struct iommu *iommu;
+ unsigned long flags, order, first_page, npages, n;
++ struct iommu *iommu;
++ struct page *page;
+ void *ret;
+ long entry;
++ int nid;
+
+ size = IO_PAGE_ALIGN(size);
+ order = get_order(size);
+@@ -139,10 +141,12 @@ static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
+
+ npages = size >> IO_PAGE_SHIFT;
+
+- first_page = __get_free_pages(gfp, order);
+- if (unlikely(first_page == 0UL))
++ nid = dev->archdata.numa_node;
++ page = alloc_pages_node(nid, gfp, order);
++ if (unlikely(!page))
+ return NULL;
+
++ first_page = (unsigned long) page_address(page);
+ memset((char *)first_page, 0, PAGE_SIZE << order);
+
+ iommu = dev->archdata.iommu;
+@@ -899,6 +903,8 @@ static void __init pci_sun4v_pbm_init(struct pci_controller_info *p,
+ pbm->next = pci_pbm_root;
+ pci_pbm_root = pbm;
+
++ pbm->numa_node = of_node_to_nid(dp);
++
+ pbm->scan_bus = pci_sun4v_scan_bus;
+ pbm->pci_ops = &sun4v_pci_ops;
+ pbm->config_space_reg_bits = 12;
+@@ -913,6 +919,7 @@ static void __init pci_sun4v_pbm_init(struct pci_controller_info *p,
+ pbm->name = dp->full_name;
+
+ printk("%s: SUN4V PCI Bus Module\n", pbm->name);
++ printk("%s: On NUMA node %d\n", pbm->name, pbm->numa_node);
+
+ pci_determine_mem_io_space(pbm);
+
+diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c
+index 68964dd..ed03a18 100644
+--- a/arch/sparc64/kernel/prom.c
++++ b/arch/sparc64/kernel/prom.c
+@@ -19,8 +19,8 @@
+ #include <linux/types.h>
+ #include <linux/string.h>
+ #include <linux/mm.h>
+-#include <linux/bootmem.h>
+ #include <linux/module.h>
++#include <linux/lmb.h>
+
+ #include <asm/prom.h>
+ #include <asm/of_device.h>
+@@ -122,16 +122,20 @@ int of_find_in_proplist(const char *list, const char *match, int len)
+ }
+ EXPORT_SYMBOL(of_find_in_proplist);
+
+-static unsigned int prom_early_allocated;
++static unsigned int prom_early_allocated __initdata;
+
+ static void * __init prom_early_alloc(unsigned long size)
+ {
++ unsigned long paddr = lmb_alloc(size, SMP_CACHE_BYTES);
+ void *ret;
+
+- ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL);
+- if (ret != NULL)
+- memset(ret, 0, size);
++ if (!paddr) {
++ prom_printf("prom_early_alloc(%lu) failed\n");
++ prom_halt();
++ }
+
++ ret = __va(paddr);
++ memset(ret, 0, size);
+ prom_early_allocated += size;
+
+ return ret;
+diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S
+index 079d18a..ecf6753 100644
+--- a/arch/sparc64/kernel/rtrap.S
++++ b/arch/sparc64/kernel/rtrap.S
+@@ -18,12 +18,6 @@
+ #define RTRAP_PSTATE_IRQOFF (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV)
+ #define RTRAP_PSTATE_AG_IRQOFF (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG)
+
+- /* Register %l6 keeps track of whether we are returning
+- * from a system call or not. It is cleared if we call
+- * do_notify_resume, and it must not be otherwise modified
+- * until we fully commit to returning to userspace.
+- */
+-
+ .text
+ .align 32
+ __handle_softirq:
+@@ -56,14 +50,12 @@ __handle_user_windows:
+ be,pt %xcc, __handle_user_windows_continue
+ nop
+ mov %l5, %o1
+- mov %l6, %o2
+ add %sp, PTREGS_OFF, %o0
+- mov %l0, %o3
++ mov %l0, %o2
+
+ call do_notify_resume
+ wrpr %g0, RTRAP_PSTATE, %pstate
+ wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate
+- clr %l6
+ /* Signal delivery can modify pt_regs tstate, so we must
+ * reload it.
+ */
+@@ -99,14 +91,12 @@ __handle_perfctrs:
+ be,pt %xcc, __handle_perfctrs_continue
+ sethi %hi(TSTATE_PEF), %o0
+ mov %l5, %o1
+- mov %l6, %o2
+ add %sp, PTREGS_OFF, %o0
+- mov %l0, %o3
++ mov %l0, %o2
+ call do_notify_resume
+
+ wrpr %g0, RTRAP_PSTATE, %pstate
+ wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate
+- clr %l6
+ /* Signal delivery can modify pt_regs tstate, so we must
+ * reload it.
+ */
+@@ -127,13 +117,11 @@ __handle_userfpu:
+
+ __handle_signal:
+ mov %l5, %o1
+- mov %l6, %o2
+ add %sp, PTREGS_OFF, %o0
+- mov %l0, %o3
++ mov %l0, %o2
+ call do_notify_resume
+ wrpr %g0, RTRAP_PSTATE, %pstate
+ wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate
+- clr %l6
+
+ /* Signal delivery can modify pt_regs tstate, so we must
+ * reload it.
+@@ -145,9 +133,8 @@ __handle_signal:
+ andn %l1, %l4, %l1
+
+ .align 64
+- .globl rtrap_irq, rtrap_clr_l6, rtrap, irqsz_patchme, rtrap_xcall
++ .globl rtrap_irq, rtrap, irqsz_patchme, rtrap_xcall
+ rtrap_irq:
+-rtrap_clr_l6: clr %l6
+ rtrap:
+ #ifndef CONFIG_SMP
+ sethi %hi(per_cpu____cpu_data), %l0
+diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c
+index d1fb13b..fa2827c 100644
+--- a/arch/sparc64/kernel/sbus.c
++++ b/arch/sparc64/kernel/sbus.c
+@@ -544,6 +544,7 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus)
+
+ sbus->ofdev.dev.archdata.iommu = iommu;
+ sbus->ofdev.dev.archdata.stc = strbuf;
++ sbus->ofdev.dev.archdata.numa_node = -1;
+
+ reg_base = regs + SYSIO_IOMMUREG_BASE;
+ iommu->iommu_control = reg_base + IOMMU_CONTROL;
+@@ -575,7 +576,7 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus)
+ sbus->portid, regs);
+
+ /* Setup for TSB_SIZE=7, TBW_SIZE=0, MMU_DE=1, MMU_EN=1 */
+- if (iommu_table_init(iommu, IO_TSB_SIZE, MAP_BASE, 0xffffffff))
++ if (iommu_table_init(iommu, IO_TSB_SIZE, MAP_BASE, 0xffffffff, -1))
+ goto fatal_memory_error;
+
+ control = upa_readq(iommu->iommu_control);
+diff --git a/arch/sparc64/kernel/semaphore.c b/arch/sparc64/kernel/semaphore.c
+deleted file mode 100644
+index 9974a68..0000000
+--- a/arch/sparc64/kernel/semaphore.c
++++ /dev/null
+@@ -1,254 +0,0 @@
+-/* semaphore.c: Sparc64 semaphore implementation.
+- *
+- * This is basically the PPC semaphore scheme ported to use
+- * the sparc64 atomic instructions, so see the PPC code for
+- * credits.
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/errno.h>
+-#include <linux/init.h>
+-
+-/*
+- * Atomically update sem->count.
+- * This does the equivalent of the following:
+- *
+- * old_count = sem->count;
+- * tmp = MAX(old_count, 0) + incr;
+- * sem->count = tmp;
+- * return old_count;
+- */
+-static inline int __sem_update_count(struct semaphore *sem, int incr)
+-{
+- int old_count, tmp;
+-
+- __asm__ __volatile__("\n"
+-" ! __sem_update_count old_count(%0) tmp(%1) incr(%4) &sem->count(%3)\n"
+-"1: ldsw [%3], %0\n"
+-" mov %0, %1\n"
+-" cmp %0, 0\n"
+-" movl %%icc, 0, %1\n"
+-" add %1, %4, %1\n"
+-" cas [%3], %0, %1\n"
+-" cmp %0, %1\n"
+-" membar #StoreLoad | #StoreStore\n"
+-" bne,pn %%icc, 1b\n"
+-" nop\n"
+- : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
+- : "r" (&sem->count), "r" (incr), "m" (sem->count)
+- : "cc");
+-
+- return old_count;
+-}
+-
+-static void __up(struct semaphore *sem)
+-{
+- __sem_update_count(sem, 1);
+- wake_up(&sem->wait);
+-}
+-
+-void up(struct semaphore *sem)
+-{
+- /* This atomically does:
+- * old_val = sem->count;
+- * new_val = sem->count + 1;
+- * sem->count = new_val;
+- * if (old_val < 0)
+- * __up(sem);
+- *
+- * The (old_val < 0) test is equivalent to
+- * the more straightforward (new_val <= 0),
+- * but it is easier to test the former because
+- * of how the CAS instruction works.
+- */
+-
+- __asm__ __volatile__("\n"
+-" ! up sem(%0)\n"
+-" membar #StoreLoad | #LoadLoad\n"
+-"1: lduw [%0], %%g1\n"
+-" add %%g1, 1, %%g7\n"
+-" cas [%0], %%g1, %%g7\n"
+-" cmp %%g1, %%g7\n"
+-" bne,pn %%icc, 1b\n"
+-" addcc %%g7, 1, %%g0\n"
+-" membar #StoreLoad | #StoreStore\n"
+-" ble,pn %%icc, 3f\n"
+-" nop\n"
+-"2:\n"
+-" .subsection 2\n"
+-"3: mov %0, %%g1\n"
+-" save %%sp, -160, %%sp\n"
+-" call %1\n"
+-" mov %%g1, %%o0\n"
+-" ba,pt %%xcc, 2b\n"
+-" restore\n"
+-" .previous\n"
+- : : "r" (sem), "i" (__up)
+- : "g1", "g2", "g3", "g7", "memory", "cc");
+-}
+-
+-static void __sched __down(struct semaphore * sem)
+-{
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+-
+- tsk->state = TASK_UNINTERRUPTIBLE;
+- add_wait_queue_exclusive(&sem->wait, &wait);
+-
+- while (__sem_update_count(sem, -1) <= 0) {
+- schedule();
+- tsk->state = TASK_UNINTERRUPTIBLE;
+- }
+- remove_wait_queue(&sem->wait, &wait);
+- tsk->state = TASK_RUNNING;
+-
+- wake_up(&sem->wait);
+-}
+-
+-void __sched down(struct semaphore *sem)
+-{
+- might_sleep();
+- /* This atomically does:
+- * old_val = sem->count;
+- * new_val = sem->count - 1;
+- * sem->count = new_val;
+- * if (old_val < 1)
+- * __down(sem);
+- *
+- * The (old_val < 1) test is equivalent to
+- * the more straightforward (new_val < 0),
+- * but it is easier to test the former because
+- * of how the CAS instruction works.
+- */
+-
+- __asm__ __volatile__("\n"
+-" ! down sem(%0)\n"
+-"1: lduw [%0], %%g1\n"
+-" sub %%g1, 1, %%g7\n"
+-" cas [%0], %%g1, %%g7\n"
+-" cmp %%g1, %%g7\n"
+-" bne,pn %%icc, 1b\n"
+-" cmp %%g7, 1\n"
+-" membar #StoreLoad | #StoreStore\n"
+-" bl,pn %%icc, 3f\n"
+-" nop\n"
+-"2:\n"
+-" .subsection 2\n"
+-"3: mov %0, %%g1\n"
+-" save %%sp, -160, %%sp\n"
+-" call %1\n"
+-" mov %%g1, %%o0\n"
+-" ba,pt %%xcc, 2b\n"
+-" restore\n"
+-" .previous\n"
+- : : "r" (sem), "i" (__down)
+- : "g1", "g2", "g3", "g7", "memory", "cc");
+-}
+-
+-int down_trylock(struct semaphore *sem)
+-{
+- int ret;
+-
+- /* This atomically does:
+- * old_val = sem->count;
+- * new_val = sem->count - 1;
+- * if (old_val < 1) {
+- * ret = 1;
+- * } else {
+- * sem->count = new_val;
+- * ret = 0;
+- * }
+- *
+- * The (old_val < 1) test is equivalent to
+- * the more straightforward (new_val < 0),
+- * but it is easier to test the former because
+- * of how the CAS instruction works.
+- */
+-
+- __asm__ __volatile__("\n"
+-" ! down_trylock sem(%1) ret(%0)\n"
+-"1: lduw [%1], %%g1\n"
+-" sub %%g1, 1, %%g7\n"
+-" cmp %%g1, 1\n"
+-" bl,pn %%icc, 2f\n"
+-" mov 1, %0\n"
+-" cas [%1], %%g1, %%g7\n"
+-" cmp %%g1, %%g7\n"
+-" bne,pn %%icc, 1b\n"
+-" mov 0, %0\n"
+-" membar #StoreLoad | #StoreStore\n"
+-"2:\n"
+- : "=&r" (ret)
+- : "r" (sem)
+- : "g1", "g7", "memory", "cc");
+-
+- return ret;
+-}
+-
+-static int __sched __down_interruptible(struct semaphore * sem)
+-{
+- int retval = 0;
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+-
+- tsk->state = TASK_INTERRUPTIBLE;
+- add_wait_queue_exclusive(&sem->wait, &wait);
+-
+- while (__sem_update_count(sem, -1) <= 0) {
+- if (signal_pending(current)) {
+- __sem_update_count(sem, 0);
+- retval = -EINTR;
+- break;
+- }
+- schedule();
+- tsk->state = TASK_INTERRUPTIBLE;
+- }
+- tsk->state = TASK_RUNNING;
+- remove_wait_queue(&sem->wait, &wait);
+- wake_up(&sem->wait);
+- return retval;
+-}
+-
+-int __sched down_interruptible(struct semaphore *sem)
+-{
+- int ret = 0;
+-
+- might_sleep();
+- /* This atomically does:
+- * old_val = sem->count;
+- * new_val = sem->count - 1;
+- * sem->count = new_val;
+- * if (old_val < 1)
+- * ret = __down_interruptible(sem);
+- *
+- * The (old_val < 1) test is equivalent to
+- * the more straightforward (new_val < 0),
+- * but it is easier to test the former because
+- * of how the CAS instruction works.
+- */
+-
+- __asm__ __volatile__("\n"
+-" ! down_interruptible sem(%2) ret(%0)\n"
+-"1: lduw [%2], %%g1\n"
+-" sub %%g1, 1, %%g7\n"
+-" cas [%2], %%g1, %%g7\n"
+-" cmp %%g1, %%g7\n"
+-" bne,pn %%icc, 1b\n"
+-" cmp %%g7, 1\n"
+-" membar #StoreLoad | #StoreStore\n"
+-" bl,pn %%icc, 3f\n"
+-" nop\n"
+-"2:\n"
+-" .subsection 2\n"
+-"3: mov %2, %%g1\n"
+-" save %%sp, -160, %%sp\n"
+-" call %3\n"
+-" mov %%g1, %%o0\n"
+-" ba,pt %%xcc, 2b\n"
+-" restore\n"
+-" .previous\n"
+- : "=r" (ret)
+- : "0" (ret), "r" (sem), "i" (__down_interruptible)
+- : "g1", "g2", "g3", "g7", "memory", "cc");
+- return ret;
+-}
+diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
+index 6acb4c5..da5e6ee 100644
+--- a/arch/sparc64/kernel/setup.c
++++ b/arch/sparc64/kernel/setup.c
+@@ -82,7 +82,7 @@ unsigned long cmdline_memory_size = 0;
+ static struct console prom_early_console = {
+ .name = "earlyprom",
+ .write = prom_console_write,
+- .flags = CON_PRINTBUFFER | CON_BOOT,
++ .flags = CON_PRINTBUFFER | CON_BOOT | CON_ANYTIME,
+ .index = -1,
+ };
+
+@@ -281,6 +281,7 @@ void __init setup_arch(char **cmdline_p)
+ /* Initialize PROM console and command line. */
+ *cmdline_p = prom_getbootargs();
+ strcpy(boot_command_line, *cmdline_p);
++ parse_early_param();
+
+ boot_flags_init(*cmdline_p);
+ register_console(&prom_early_console);
+diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
+index 9d51956..77a3e85 100644
+--- a/arch/sparc64/kernel/signal.c
++++ b/arch/sparc64/kernel/signal.c
+@@ -25,7 +25,6 @@
+
+ #include <asm/uaccess.h>
+ #include <asm/ptrace.h>
+-#include <asm/svr4.h>
+ #include <asm/pgtable.h>
+ #include <asm/fpumacro.h>
+ #include <asm/uctx.h>
+@@ -511,15 +510,20 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ */
+-static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall)
++static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
+ {
+- siginfo_t info;
+ struct signal_deliver_cookie cookie;
+ struct k_sigaction ka;
+- int signr;
+ sigset_t *oldset;
++ siginfo_t info;
++ int signr, tt;
+
+- cookie.restart_syscall = restart_syscall;
++ tt = regs->magic & 0x1ff;
++ if (tt == 0x110 || tt == 0x111 || tt == 0x16d) {
++ regs->magic &= ~0x1ff;
++ cookie.restart_syscall = 1;
++ } else
++ cookie.restart_syscall = 0;
+ cookie.orig_i0 = orig_i0;
+
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+@@ -530,9 +534,8 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_s
+ #ifdef CONFIG_SPARC32_COMPAT
+ if (test_thread_flag(TIF_32BIT)) {
+ extern void do_signal32(sigset_t *, struct pt_regs *,
+- unsigned long, int);
+- do_signal32(oldset, regs, orig_i0,
+- cookie.restart_syscall);
++ struct signal_deliver_cookie *);
++ do_signal32(oldset, regs, &cookie);
+ return;
+ }
+ #endif
+@@ -540,7 +543,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_s
+ signr = get_signal_to_deliver(&info, &ka, regs, &cookie);
+ if (signr > 0) {
+ if (cookie.restart_syscall)
+- syscall_restart(orig_i0, regs, &ka.sa);
++ syscall_restart(cookie.orig_i0, regs, &ka.sa);
+ handle_signal(signr, &ka, &info, oldset, regs);
+
+ /* a signal was successfully delivered; the saved
+@@ -577,11 +580,10 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_s
+ }
+ }
+
+-void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall,
+- unsigned long thread_info_flags)
++void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags)
+ {
+ if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+- do_signal(regs, orig_i0, restart_syscall);
++ do_signal(regs, orig_i0);
+ }
+
+ void ptrace_signal_deliver(struct pt_regs *regs, void *cookie)
+diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
+index 8c1c121..43cdec6 100644
+--- a/arch/sparc64/kernel/signal32.c
++++ b/arch/sparc64/kernel/signal32.c
+@@ -23,7 +23,6 @@
+
+ #include <asm/uaccess.h>
+ #include <asm/ptrace.h>
+-#include <asm/svr4.h>
+ #include <asm/pgtable.h>
+ #include <asm/psrcompat.h>
+ #include <asm/fpumacro.h>
+@@ -798,281 +797,6 @@ sigsegv:
+ force_sigsegv(signo, current);
+ }
+
+-/* Setup a Solaris stack frame */
+-static void
+-setup_svr4_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc,
+- struct pt_regs *regs, int signr, sigset_t *oldset)
+-{
+- svr4_signal_frame_t __user *sfp;
+- svr4_gregset_t __user *gr;
+- svr4_siginfo_t __user *si;
+- svr4_mcontext_t __user *mc;
+- svr4_gwindows_t __user *gw;
+- svr4_ucontext_t __user *uc;
+- svr4_sigset_t setv;
+- unsigned int psr;
+- int i, err;
+-
+- synchronize_user_stack();
+- save_and_clear_fpu();
+-
+- regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
+- sfp = (svr4_signal_frame_t __user *)
+- get_sigframe(sa, regs,
+- sizeof(struct reg_window32) + SVR4_SF_ALIGNED);
+-
+- if (invalid_frame_pointer(sfp, sizeof(*sfp)))
+- do_exit(SIGILL);
+-
+- /* Start with a clean frame pointer and fill it */
+- err = clear_user(sfp, sizeof(*sfp));
+-
+- /* Setup convenience variables */
+- si = &sfp->si;
+- uc = &sfp->uc;
+- gw = &sfp->gw;
+- mc = &uc->mcontext;
+- gr = &mc->greg;
+-
+- /* FIXME: where am I supposed to put this?
+- * sc->sigc_onstack = old_status;
+- * anyways, it does not look like it is used for anything at all.
+- */
+- setv.sigbits[0] = oldset->sig[0];
+- setv.sigbits[1] = (oldset->sig[0] >> 32);
+- if (_NSIG_WORDS >= 2) {
+- setv.sigbits[2] = oldset->sig[1];
+- setv.sigbits[3] = (oldset->sig[1] >> 32);
+- err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t));
+- } else
+- err |= __copy_to_user(&uc->sigmask, &setv,
+- 2 * sizeof(unsigned int));
+-
+- /* Store registers */
+- if (test_thread_flag(TIF_32BIT)) {
+- regs->tpc &= 0xffffffff;
+- regs->tnpc &= 0xffffffff;
+- }
+- err |= __put_user(regs->tpc, &((*gr)[SVR4_PC]));
+- err |= __put_user(regs->tnpc, &((*gr)[SVR4_NPC]));
+- psr = tstate_to_psr(regs->tstate);
+- if (current_thread_info()->fpsaved[0] & FPRS_FEF)
+- psr |= PSR_EF;
+- err |= __put_user(psr, &((*gr)[SVR4_PSR]));
+- err |= __put_user(regs->y, &((*gr)[SVR4_Y]));
+-
+- /* Copy g[1..7] and o[0..7] registers */
+- for (i = 0; i < 7; i++)
+- err |= __put_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i);
+- for (i = 0; i < 8; i++)
+- err |= __put_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i);
+-
+- /* Setup sigaltstack */
+- err |= __put_user(current->sas_ss_sp, &uc->stack.sp);
+- err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags);
+- err |= __put_user(current->sas_ss_size, &uc->stack.size);
+-
+- /* Save the currently window file: */
+-
+- /* 1. Link sfp->uc->gwins to our windows */
+- err |= __put_user(ptr_to_compat(gw), &mc->gwin);
+-
+- /* 2. Number of windows to restore at setcontext (): */
+- err |= __put_user(get_thread_wsaved(), &gw->count);
+-
+- /* 3. We just pay attention to the gw->count field on setcontext */
+- set_thread_wsaved(0); /* So process is allowed to execute. */
+-
+- /* Setup the signal information. Solaris expects a bunch of
+- * information to be passed to the signal handler, we don't provide
+- * that much currently, should use siginfo.
+- */
+- err |= __put_user(signr, &si->siginfo.signo);
+- err |= __put_user(SVR4_SINOINFO, &si->siginfo.code);
+- if (err)
+- goto sigsegv;
+-
+- regs->u_regs[UREG_FP] = (unsigned long) sfp;
+- regs->tpc = (unsigned long) sa->sa_handler;
+- regs->tnpc = (regs->tpc + 4);
+- if (test_thread_flag(TIF_32BIT)) {
+- regs->tpc &= 0xffffffff;
+- regs->tnpc &= 0xffffffff;
+- }
+-
+- /* Arguments passed to signal handler */
+- if (regs->u_regs[14]){
+- struct reg_window32 __user *rw = (struct reg_window32 __user *)
+- (regs->u_regs[14] & 0x00000000ffffffffUL);
+-
+- err |= __put_user(signr, &rw->ins[0]);
+- err |= __put_user((u64)si, &rw->ins[1]);
+- err |= __put_user((u64)uc, &rw->ins[2]);
+- err |= __put_user((u64)sfp, &rw->ins[6]); /* frame pointer */
+- if (err)
+- goto sigsegv;
+-
+- regs->u_regs[UREG_I0] = signr;
+- regs->u_regs[UREG_I1] = (u32)(u64) si;
+- regs->u_regs[UREG_I2] = (u32)(u64) uc;
+- }
+- return;
+-
+-sigsegv:
+- force_sigsegv(signr, current);
+-}
+-
+-asmlinkage int
+-svr4_getcontext(svr4_ucontext_t __user *uc, struct pt_regs *regs)
+-{
+- svr4_gregset_t __user *gr;
+- svr4_mcontext_t __user *mc;
+- svr4_sigset_t setv;
+- int i, err;
+- u32 psr;
+-
+- synchronize_user_stack();
+- save_and_clear_fpu();
+-
+- if (get_thread_wsaved())
+- do_exit(SIGSEGV);
+-
+- err = clear_user(uc, sizeof(*uc));
+-
+- /* Setup convenience variables */
+- mc = &uc->mcontext;
+- gr = &mc->greg;
+-
+- setv.sigbits[0] = current->blocked.sig[0];
+- setv.sigbits[1] = (current->blocked.sig[0] >> 32);
+- if (_NSIG_WORDS >= 2) {
+- setv.sigbits[2] = current->blocked.sig[1];
+- setv.sigbits[3] = (current->blocked.sig[1] >> 32);
+- err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t));
+- } else
+- err |= __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned));
+-
+- /* Store registers */
+- if (test_thread_flag(TIF_32BIT)) {
+- regs->tpc &= 0xffffffff;
+- regs->tnpc &= 0xffffffff;
+- }
+- err |= __put_user(regs->tpc, &uc->mcontext.greg[SVR4_PC]);
+- err |= __put_user(regs->tnpc, &uc->mcontext.greg[SVR4_NPC]);
+-
+- psr = tstate_to_psr(regs->tstate) & ~PSR_EF;
+- if (current_thread_info()->fpsaved[0] & FPRS_FEF)
+- psr |= PSR_EF;
+- err |= __put_user(psr, &uc->mcontext.greg[SVR4_PSR]);
+-
+- err |= __put_user(regs->y, &uc->mcontext.greg[SVR4_Y]);
+-
+- /* Copy g[1..7] and o[0..7] registers */
+- for (i = 0; i < 7; i++)
+- err |= __put_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i);
+- for (i = 0; i < 8; i++)
+- err |= __put_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i);
+-
+- /* Setup sigaltstack */
+- err |= __put_user(current->sas_ss_sp, &uc->stack.sp);
+- err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags);
+- err |= __put_user(current->sas_ss_size, &uc->stack.size);
+-
+- /* The register file is not saved
+- * we have already stuffed all of it with sync_user_stack
+- */
+- return (err ? -EFAULT : 0);
+-}
+-
+-
+-/* Set the context for a svr4 application, this is Solaris way to sigreturn */
+-asmlinkage int svr4_setcontext(svr4_ucontext_t __user *c, struct pt_regs *regs)
+-{
+- svr4_gregset_t __user *gr;
+- mm_segment_t old_fs;
+- u32 pc, npc, psr, u_ss_sp;
+- sigset_t set;
+- svr4_sigset_t setv;
+- int i, err;
+- stack_t st;
+-
+- /* Fixme: restore windows, or is this already taken care of in
+- * svr4_setup_frame when sync_user_windows is done?
+- */
+- flush_user_windows();
+-
+- if (get_thread_wsaved())
+- goto sigsegv;
+-
+- if (((unsigned long) c) & 3){
+- printk("Unaligned structure passed\n");
+- goto sigsegv;
+- }
+-
+- if (!__access_ok(c, sizeof(*c))) {
+- /* Miguel, add nice debugging msg _here_. ;-) */
+- goto sigsegv;
+- }
+-
+- /* Check for valid PC and nPC */
+- gr = &c->mcontext.greg;
+- err = __get_user(pc, &((*gr)[SVR4_PC]));
+- err |= __get_user(npc, &((*gr)[SVR4_NPC]));
+- if ((pc | npc) & 3)
+- goto sigsegv;
+-
+- /* Retrieve information from passed ucontext */
+- /* note that nPC is ored a 1, this is used to inform entry.S */
+- /* that we don't want it to mess with our PC and nPC */
+-
+- err |= copy_from_user(&setv, &c->sigmask, sizeof(svr4_sigset_t));
+- set.sig[0] = setv.sigbits[0] | (((long)setv.sigbits[1]) << 32);
+- if (_NSIG_WORDS >= 2)
+- set.sig[1] = setv.sigbits[2] | (((long)setv.sigbits[3]) << 32);
+-
+- err |= __get_user(u_ss_sp, &c->stack.sp);
+- st.ss_sp = compat_ptr(u_ss_sp);
+- err |= __get_user(st.ss_flags, &c->stack.flags);
+- err |= __get_user(st.ss_size, &c->stack.size);
+- if (err)
+- goto sigsegv;
+-
+- /* It is more difficult to avoid calling this function than to
+- call it and ignore errors. */
+- old_fs = get_fs();
+- set_fs(KERNEL_DS);
+- do_sigaltstack((stack_t __user *) &st, NULL, regs->u_regs[UREG_I6]);
+- set_fs(old_fs);
+-
+- sigdelsetmask(&set, ~_BLOCKABLE);
+- spin_lock_irq(¤t->sighand->siglock);
+- current->blocked = set;
+- recalc_sigpending();
+- spin_unlock_irq(¤t->sighand->siglock);
+- regs->tpc = pc;
+- regs->tnpc = npc | 1;
+- if (test_thread_flag(TIF_32BIT)) {
+- regs->tpc &= 0xffffffff;
+- regs->tnpc &= 0xffffffff;
+- }
+- err |= __get_user(regs->y, &((*gr)[SVR4_Y]));
+- err |= __get_user(psr, &((*gr)[SVR4_PSR]));
+- regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC);
+- regs->tstate |= psr_to_tstate_icc(psr);
+-
+- /* Restore g[1..7] and o[0..7] registers */
+- for (i = 0; i < 7; i++)
+- err |= __get_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i);
+- for (i = 0; i < 8; i++)
+- err |= __get_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i);
+- if (err)
+- goto sigsegv;
+-
+- return -EINTR;
+-sigsegv:
+- return -EFAULT;
+-}
+-
+ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
+ unsigned long signr, sigset_t *oldset,
+ siginfo_t *info)
+@@ -1216,20 +940,14 @@ sigsegv:
+
+ static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,
+ siginfo_t *info,
+- sigset_t *oldset, struct pt_regs *regs,
+- int svr4_signal)
++ sigset_t *oldset, struct pt_regs *regs)
+ {
+- if (svr4_signal)
+- setup_svr4_frame32(&ka->sa, regs->tpc, regs->tnpc,
+- regs, signr, oldset);
+- else {
+- if (ka->sa.sa_flags & SA_SIGINFO)
+- setup_rt_frame32(ka, regs, signr, oldset, info);
+- else if (test_thread_flag(TIF_NEWSIGNALS))
+- new_setup_frame32(ka, regs, signr, oldset);
+- else
+- setup_frame32(&ka->sa, regs, signr, oldset, info);
+- }
++ if (ka->sa.sa_flags & SA_SIGINFO)
++ setup_rt_frame32(ka, regs, signr, oldset, info);
++ else if (test_thread_flag(TIF_NEWSIGNALS))
++ new_setup_frame32(ka, regs, signr, oldset);
++ else
++ setup_frame32(&ka->sa, regs, signr, oldset, info);
+ spin_lock_irq(¤t->sighand->siglock);
+ sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NOMASK))
+@@ -1264,23 +982,17 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs
+ * mistake.
+ */
+ void do_signal32(sigset_t *oldset, struct pt_regs * regs,
+- unsigned long orig_i0, int restart_syscall)
++ struct signal_deliver_cookie *cookie)
+ {
+- siginfo_t info;
+- struct signal_deliver_cookie cookie;
+ struct k_sigaction ka;
++ siginfo_t info;
+ int signr;
+- int svr4_signal = current->personality == PER_SVR4;
+
+- cookie.restart_syscall = restart_syscall;
+- cookie.orig_i0 = orig_i0;
+-
+- signr = get_signal_to_deliver(&info, &ka, regs, &cookie);
++ signr = get_signal_to_deliver(&info, &ka, regs, cookie);
+ if (signr > 0) {
+- if (cookie.restart_syscall)
+- syscall_restart32(orig_i0, regs, &ka.sa);
+- handle_signal32(signr, &ka, &info, oldset,
+- regs, svr4_signal);
++ if (cookie->restart_syscall)
++ syscall_restart32(cookie->orig_i0, regs, &ka.sa);
++ handle_signal32(signr, &ka, &info, oldset, regs);
+
+ /* a signal was successfully delivered; the saved
+ * sigmask will have been stored in the signal frame,
+@@ -1291,16 +1003,16 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs,
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ return;
+ }
+- if (cookie.restart_syscall &&
++ if (cookie->restart_syscall &&
+ (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
+ regs->u_regs[UREG_I0] == ERESTARTSYS ||
+ regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
+ /* replay the system call when we are done */
+- regs->u_regs[UREG_I0] = cookie.orig_i0;
++ regs->u_regs[UREG_I0] = cookie->orig_i0;
+ regs->tpc -= 4;
+ regs->tnpc -= 4;
+ }
+- if (cookie.restart_syscall &&
++ if (cookie->restart_syscall &&
+ regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
+ regs->u_regs[UREG_G1] = __NR_restart_syscall;
+ regs->tpc -= 4;
+diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
+index 59f020d..409dd71 100644
+--- a/arch/sparc64/kernel/smp.c
++++ b/arch/sparc64/kernel/smp.c
+@@ -20,7 +20,7 @@
+ #include <linux/cache.h>
+ #include <linux/jiffies.h>
+ #include <linux/profile.h>
+-#include <linux/bootmem.h>
++#include <linux/lmb.h>
+
+ #include <asm/head.h>
+ #include <asm/ptrace.h>
+@@ -866,14 +866,21 @@ void smp_call_function_client(int irq, struct pt_regs *regs)
+ void *info = call_data->info;
+
+ clear_softint(1 << irq);
++
++ irq_enter();
++
++ if (!call_data->wait) {
++ /* let initiator proceed after getting data */
++ atomic_inc(&call_data->finished);
++ }
++
++ func(info);
++
++ irq_exit();
++
+ if (call_data->wait) {
+ /* let initiator proceed only after completion */
+- func(info);
+ atomic_inc(&call_data->finished);
+- } else {
+- /* let initiator proceed after getting data */
+- atomic_inc(&call_data->finished);
+- func(info);
+ }
+ }
+
+@@ -1032,7 +1039,9 @@ void smp_receive_signal(int cpu)
+
+ void smp_receive_signal_client(int irq, struct pt_regs *regs)
+ {
++ irq_enter();
+ clear_softint(1 << irq);
++ irq_exit();
+ }
+
+ void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
+@@ -1040,6 +1049,8 @@ void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
+ struct mm_struct *mm;
+ unsigned long flags;
+
++ irq_enter();
++
+ clear_softint(1 << irq);
+
+ /* See if we need to allocate a new TLB context because
+@@ -1059,6 +1070,8 @@ void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
+ load_secondary_context(mm);
+ __flush_tlb_mm(CTX_HWBITS(mm->context),
+ SECONDARY_CONTEXT);
++
++ irq_exit();
+ }
+
+ void smp_new_mmu_context_version(void)
+@@ -1217,6 +1230,8 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs)
+ {
+ clear_softint(1 << irq);
+
++ irq_enter();
++
+ preempt_disable();
+
+ __asm__ __volatile__("flushw");
+@@ -1229,6 +1244,8 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs)
+ prom_world(0);
+
+ preempt_enable();
++
++ irq_exit();
+ }
+
+ /* /proc/profile writes can call this, don't __init it please. */
+@@ -1431,7 +1448,7 @@ EXPORT_SYMBOL(__per_cpu_shift);
+
+ void __init real_setup_per_cpu_areas(void)
+ {
+- unsigned long goal, size, i;
++ unsigned long paddr, goal, size, i;
+ char *ptr;
+
+ /* Copy section for each CPU (we discard the original) */
+@@ -1441,8 +1458,13 @@ void __init real_setup_per_cpu_areas(void)
+ for (size = PAGE_SIZE; size < goal; size <<= 1UL)
+ __per_cpu_shift++;
+
+- ptr = alloc_bootmem_pages(size * NR_CPUS);
++ paddr = lmb_alloc(size * NR_CPUS, PAGE_SIZE);
++ if (!paddr) {
++ prom_printf("Cannot allocate per-cpu memory.\n");
++ prom_halt();
++ }
+
++ ptr = __va(paddr);
+ __per_cpu_base = ptr - __per_cpu_start;
+
+ for (i = 0; i < NR_CPUS; i++, ptr += size)
+diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
+index 51fa773..6633659 100644
+--- a/arch/sparc64/kernel/sparc64_ksyms.c
++++ b/arch/sparc64/kernel/sparc64_ksyms.c
+@@ -33,13 +33,11 @@
+ #include <asm/io.h>
+ #include <asm/irq.h>
+ #include <asm/idprom.h>
+-#include <asm/svr4.h>
+ #include <asm/elf.h>
+ #include <asm/head.h>
+ #include <asm/smp.h>
+ #include <asm/mostek.h>
+ #include <asm/ptrace.h>
+-#include <asm/user.h>
+ #include <asm/uaccess.h>
+ #include <asm/checksum.h>
+ #include <asm/fpumacro.h>
+@@ -70,16 +68,9 @@ extern void *__memscan_zero(void *, size_t);
+ extern void *__memscan_generic(void *, int, size_t);
+ extern int __memcmp(const void *, const void *, __kernel_size_t);
+ extern __kernel_size_t strlen(const char *);
+-extern void linux_sparc_syscall(void);
+-extern void rtrap(void);
+ extern void show_regs(struct pt_regs *);
+-extern void solaris_syscall(void);
+ extern void syscall_trace(struct pt_regs *, int);
+-extern u32 sunos_sys_table[], sys_call_table32[];
+-extern void tl0_solaris(void);
+ extern void sys_sigsuspend(void);
+-extern int svr4_getcontext(svr4_ucontext_t *uc, struct pt_regs *regs);
+-extern int svr4_setcontext(svr4_ucontext_t *uc, struct pt_regs *regs);
+ extern int compat_sys_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
+ extern int (*handle_mathemu)(struct pt_regs *, struct fpustate *);
+ extern long sparc32_open(const char __user * filename, int flags, int mode);
+@@ -90,8 +81,6 @@ extern int __ashrdi3(int, int);
+
+ extern int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs);
+
+-extern unsigned int sys_call_table[];
+-
+ extern void xor_vis_2(unsigned long, unsigned long *, unsigned long *);
+ extern void xor_vis_3(unsigned long, unsigned long *, unsigned long *,
+ unsigned long *);
+@@ -130,12 +119,6 @@ EXPORT_SYMBOL(_mcount);
+
+ EXPORT_SYMBOL(sparc64_get_clock_tick);
+
+-/* semaphores */
+-EXPORT_SYMBOL(down);
+-EXPORT_SYMBOL(down_trylock);
+-EXPORT_SYMBOL(down_interruptible);
+-EXPORT_SYMBOL(up);
+-
+ /* RW semaphores */
+ EXPORT_SYMBOL(__down_read);
+ EXPORT_SYMBOL(__down_read_trylock);
+@@ -219,11 +202,6 @@ EXPORT_SYMBOL(pci_dma_supported);
+ /* I/O device mmaping on Sparc64. */
+ EXPORT_SYMBOL(io_remap_pfn_range);
+
+-#if defined(CONFIG_COMPAT) && defined(CONFIG_NET)
+-/* Solaris/SunOS binary compatibility */
+-EXPORT_SYMBOL(verify_compat_iovec);
+-#endif
+-
+ EXPORT_SYMBOL(dump_fpu);
+ EXPORT_SYMBOL(put_fs_struct);
+
+@@ -260,30 +238,6 @@ EXPORT_SYMBOL(strlen);
+ EXPORT_SYMBOL(__strlen_user);
+ EXPORT_SYMBOL(__strnlen_user);
+
+-#ifdef CONFIG_SOLARIS_EMUL_MODULE
+-EXPORT_SYMBOL(linux_sparc_syscall);
+-EXPORT_SYMBOL(rtrap);
+-EXPORT_SYMBOL(show_regs);
+-EXPORT_SYMBOL(solaris_syscall);
+-EXPORT_SYMBOL(syscall_trace);
+-EXPORT_SYMBOL(sunos_sys_table);
+-EXPORT_SYMBOL(sys_call_table32);
+-EXPORT_SYMBOL(tl0_solaris);
+-EXPORT_SYMBOL(sys_sigsuspend);
+-EXPORT_SYMBOL(sys_getppid);
+-EXPORT_SYMBOL(sys_getpid);
+-EXPORT_SYMBOL(sys_geteuid);
+-EXPORT_SYMBOL(sys_getuid);
+-EXPORT_SYMBOL(sys_getegid);
+-EXPORT_SYMBOL(sysctl_nr_open);
+-EXPORT_SYMBOL(sys_getgid);
+-EXPORT_SYMBOL(svr4_getcontext);
+-EXPORT_SYMBOL(svr4_setcontext);
+-EXPORT_SYMBOL(compat_sys_ioctl);
+-EXPORT_SYMBOL(sys_ioctl);
+-EXPORT_SYMBOL(sparc32_open);
+-#endif
+-
+ /* Special internal versions of library functions. */
+ EXPORT_SYMBOL(_clear_page);
+ EXPORT_SYMBOL(clear_user_page);
+@@ -340,9 +294,6 @@ EXPORT_SYMBOL(do_BUG);
+ /* for ns8703 */
+ EXPORT_SYMBOL(ns87303_lock);
+
+-/* for solaris compat module */
+-EXPORT_SYMBOL_GPL(sys_call_table);
+-
+ EXPORT_SYMBOL(tick_ops);
+
+ EXPORT_SYMBOL(xor_vis_2);
+diff --git a/arch/sparc64/kernel/stacktrace.c b/arch/sparc64/kernel/stacktrace.c
+index 84d39e8..01b52f5 100644
+--- a/arch/sparc64/kernel/stacktrace.c
++++ b/arch/sparc64/kernel/stacktrace.c
+@@ -20,6 +20,8 @@ void save_stack_trace(struct stack_trace *trace)
+ thread_base = (unsigned long) tp;
+ do {
+ struct reg_window *rw;
++ struct pt_regs *regs;
++ unsigned long pc;
+
+ /* Bogus frame pointer? */
+ if (fp < (thread_base + sizeof(struct thread_info)) ||
+@@ -27,11 +29,19 @@ void save_stack_trace(struct stack_trace *trace)
+ break;
+
+ rw = (struct reg_window *) fp;
++ regs = (struct pt_regs *) (rw + 1);
++
++ if ((regs->magic & ~0x1ff) == PT_REGS_MAGIC) {
++ pc = regs->tpc;
++ fp = regs->u_regs[UREG_I6] + STACK_BIAS;
++ } else {
++ pc = rw->ins[7];
++ fp = rw->ins[6] + STACK_BIAS;
++ }
++
+ if (trace->skip > 0)
+ trace->skip--;
+ else
+- trace->entries[trace->nr_entries++] = rw->ins[7];
+-
+- fp = rw->ins[6] + STACK_BIAS;
++ trace->entries[trace->nr_entries++] = pc;
+ } while (trace->nr_entries < trace->max_entries);
+ }
+diff --git a/arch/sparc64/kernel/sun4v_tlb_miss.S b/arch/sparc64/kernel/sun4v_tlb_miss.S
+index fd94305..e1fbf8c 100644
+--- a/arch/sparc64/kernel/sun4v_tlb_miss.S
++++ b/arch/sparc64/kernel/sun4v_tlb_miss.S
+@@ -262,7 +262,7 @@ sun4v_iacc:
+ mov %l5, %o2
+ call sun4v_insn_access_exception
+ add %sp, PTREGS_OFF, %o0
+- ba,a,pt %xcc, rtrap_clr_l6
++ ba,a,pt %xcc, rtrap
+
+ /* Instruction Access Exception, tl1. */
+ sun4v_iacc_tl1:
+@@ -278,7 +278,7 @@ sun4v_iacc_tl1:
+ mov %l5, %o2
+ call sun4v_insn_access_exception_tl1
+ add %sp, PTREGS_OFF, %o0
+- ba,a,pt %xcc, rtrap_clr_l6
++ ba,a,pt %xcc, rtrap
+
+ /* Data Access Exception, tl0. */
+ sun4v_dacc:
+@@ -294,7 +294,7 @@ sun4v_dacc:
+ mov %l5, %o2
+ call sun4v_data_access_exception
+ add %sp, PTREGS_OFF, %o0
+- ba,a,pt %xcc, rtrap_clr_l6
++ ba,a,pt %xcc, rtrap
+
+ /* Data Access Exception, tl1. */
+ sun4v_dacc_tl1:
+@@ -310,7 +310,7 @@ sun4v_dacc_tl1:
+ mov %l5, %o2
+ call sun4v_data_access_exception_tl1
+ add %sp, PTREGS_OFF, %o0
+- ba,a,pt %xcc, rtrap_clr_l6
++ ba,a,pt %xcc, rtrap
+
+ /* Memory Address Unaligned. */
+ sun4v_mna:
+@@ -344,7 +344,7 @@ sun4v_mna:
+ mov %l5, %o2
+ call sun4v_do_mna
+ add %sp, PTREGS_OFF, %o0
+- ba,a,pt %xcc, rtrap_clr_l6
++ ba,a,pt %xcc, rtrap
+
+ /* Privileged Action. */
+ sun4v_privact:
+@@ -352,7 +352,7 @@ sun4v_privact:
+ rd %pc, %g7
+ call do_privact
+ add %sp, PTREGS_OFF, %o0
+- ba,a,pt %xcc, rtrap_clr_l6
++ ba,a,pt %xcc, rtrap
+
+ /* Unaligned ldd float, tl0. */
+ sun4v_lddfmna:
+@@ -368,7 +368,7 @@ sun4v_lddfmna:
+ mov %l5, %o2
+ call handle_lddfmna
+ add %sp, PTREGS_OFF, %o0
+- ba,a,pt %xcc, rtrap_clr_l6
++ ba,a,pt %xcc, rtrap
+
+ /* Unaligned std float, tl0. */
+ sun4v_stdfmna:
+@@ -384,7 +384,7 @@ sun4v_stdfmna:
+ mov %l5, %o2
+ call handle_stdfmna
+ add %sp, PTREGS_OFF, %o0
+- ba,a,pt %xcc, rtrap_clr_l6
++ ba,a,pt %xcc, rtrap
+
+ #define BRANCH_ALWAYS 0x10680000
+ #define NOP 0x01000000
+diff --git a/arch/sparc64/kernel/sunos_ioctl32.c b/arch/sparc64/kernel/sunos_ioctl32.c
+deleted file mode 100644
+index 75d2bad..0000000
+--- a/arch/sparc64/kernel/sunos_ioctl32.c
++++ /dev/null
+@@ -1,275 +0,0 @@
+-/* $Id: sunos_ioctl32.c,v 1.11 2000/07/30 23:12:24 davem Exp $
+- * sunos_ioctl32.c: SunOS ioctl compatibility on sparc64.
+- *
+- * Copyright (C) 1995 Miguel de Icaza (miguel at nuclecu.unam.mx)
+- * Copyright (C) 1995, 1996, 1997 David S. Miller (davem at caip.rutgers.edu)
+- */
+-
+-#include <asm/uaccess.h>
+-
+-#include <linux/sched.h>
+-#include <linux/errno.h>
+-#include <linux/string.h>
+-#include <linux/termios.h>
+-#include <linux/tty.h>
+-#include <linux/ioctl.h>
+-#include <linux/route.h>
+-#include <linux/sockios.h>
+-#include <linux/if.h>
+-#include <linux/netdevice.h>
+-#include <linux/if_arp.h>
+-#include <linux/fs.h>
+-#include <linux/file.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+-#include <linux/syscalls.h>
+-#include <linux/compat.h>
+-
+-#define SUNOS_NR_OPEN 256
+-
+-struct rtentry32 {
+- u32 rt_pad1;
+- struct sockaddr rt_dst; /* target address */
+- struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */
+- struct sockaddr rt_genmask; /* target network mask (IP) */
+- unsigned short rt_flags;
+- short rt_pad2;
+- u32 rt_pad3;
+- unsigned char rt_tos;
+- unsigned char rt_class;
+- short rt_pad4;
+- short rt_metric; /* +1 for binary compatibility! */
+- /* char * */ u32 rt_dev; /* forcing the device at add */
+- u32 rt_mtu; /* per route MTU/Window */
+- u32 rt_window; /* Window clamping */
+- unsigned short rt_irtt; /* Initial RTT */
+-
+-};
+-
+-struct ifmap32 {
+- u32 mem_start;
+- u32 mem_end;
+- unsigned short base_addr;
+- unsigned char irq;
+- unsigned char dma;
+- unsigned char port;
+-};
+-
+-struct ifreq32 {
+-#define IFHWADDRLEN 6
+-#define IFNAMSIZ 16
+- union {
+- char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */
+- } ifr_ifrn;
+- union {
+- struct sockaddr ifru_addr;
+- struct sockaddr ifru_dstaddr;
+- struct sockaddr ifru_broadaddr;
+- struct sockaddr ifru_netmask;
+- struct sockaddr ifru_hwaddr;
+- short ifru_flags;
+- int ifru_ivalue;
+- int ifru_mtu;
+- struct ifmap32 ifru_map;
+- char ifru_slave[IFNAMSIZ]; /* Just fits the size */
+- compat_caddr_t ifru_data;
+- } ifr_ifru;
+-};
+-
+-struct ifconf32 {
+- int ifc_len; /* size of buffer */
+- compat_caddr_t ifcbuf;
+-};
+-
+-extern asmlinkage int compat_sys_ioctl(unsigned int, unsigned int, u32);
+-
+-asmlinkage int sunos_ioctl (int fd, u32 cmd, u32 arg)
+-{
+- int ret = -EBADF;
+-
+- if(fd >= SUNOS_NR_OPEN)
+- goto out;
+- if(!fcheck(fd))
+- goto out;
+-
+- if(cmd == TIOCSETD) {
+- mm_segment_t old_fs = get_fs();
+- int __user *p;
+- int ntty = N_TTY;
+- int tmp;
+-
+- p = (int __user *) (unsigned long) arg;
+- ret = -EFAULT;
+- if(get_user(tmp, p))
+- goto out;
+- if(tmp == 2) {
+- set_fs(KERNEL_DS);
+- ret = sys_ioctl(fd, cmd, (unsigned long) &ntty);
+- set_fs(old_fs);
+- ret = (ret == -EINVAL ? -EOPNOTSUPP : ret);
+- goto out;
+- }
+- }
+- if(cmd == TIOCNOTTY) {
+- ret = sys_setsid();
+- goto out;
+- }
+- switch(cmd) {
+- case _IOW('r', 10, struct rtentry32):
+- ret = compat_sys_ioctl(fd, SIOCADDRT, arg);
+- goto out;
+- case _IOW('r', 11, struct rtentry32):
+- ret = compat_sys_ioctl(fd, SIOCDELRT, arg);
+- goto out;
+-
+- case _IOW('i', 12, struct ifreq32):
+- ret = compat_sys_ioctl(fd, SIOCSIFADDR, arg);
+- goto out;
+- case _IOWR('i', 13, struct ifreq32):
+- ret = compat_sys_ioctl(fd, SIOCGIFADDR, arg);
+- goto out;
+- case _IOW('i', 14, struct ifreq32):
+- ret = compat_sys_ioctl(fd, SIOCSIFDSTADDR, arg);
+- goto out;
+- case _IOWR('i', 15, struct ifreq32):
+- ret = compat_sys_ioctl(fd, SIOCGIFDSTADDR, arg);
+- goto out;
+- case _IOW('i', 16, struct ifreq32):
+- ret = compat_sys_ioctl(fd, SIOCSIFFLAGS, arg);
+- goto out;
+- case _IOWR('i', 17, struct ifreq32):
+- ret = compat_sys_ioctl(fd, SIOCGIFFLAGS, arg);
+- goto out;
+- case _IOW('i', 18, struct ifreq32):
+- ret = compat_sys_ioctl(fd, SIOCSIFMEM, arg);
+- goto out;
+- case _IOWR('i', 19, struct ifreq32):
+- ret = compat_sys_ioctl(fd, SIOCGIFMEM, arg);
+- goto out;
+-
+- case _IOWR('i', 20, struct ifconf32):
+- ret = compat_sys_ioctl(fd, SIOCGIFCONF, arg);
+- goto out;
+-
+- case _IOW('i', 21, struct ifreq32):
+- ret = compat_sys_ioctl(fd, SIOCSIFMTU, arg);
+- goto out;
+-
+- case _IOWR('i', 22, struct ifreq32):
+- ret = compat_sys_ioctl(fd, SIOCGIFMTU, arg);
+- goto out;
+-
+- case _IOWR('i', 23, struct ifreq32):
+- ret = compat_sys_ioctl(fd, SIOCGIFBRDADDR, arg);
+- goto out;
+- case _IOW('i', 24, struct ifreq32):
+- ret = compat_sys_ioctl(fd, SIOCSIFBRDADDR, arg);
+- goto out;
+- case _IOWR('i', 25, struct ifreq32):
+- ret = compat_sys_ioctl(fd, SIOCGIFNETMASK, arg);
+- goto out;
+- case _IOW('i', 26, struct ifreq32):
+- ret = compat_sys_ioctl(fd, SIOCSIFNETMASK, arg);
+- goto out;
+- case _IOWR('i', 27, struct ifreq32):
+- ret = compat_sys_ioctl(fd, SIOCGIFMETRIC, arg);
+- goto out;
+- case _IOW('i', 28, struct ifreq32):
+- ret = compat_sys_ioctl(fd, SIOCSIFMETRIC, arg);
+- goto out;
+-
+- case _IOW('i', 30, struct arpreq):
+- ret = compat_sys_ioctl(fd, SIOCSARP, arg);
+- goto out;
+- case _IOWR('i', 31, struct arpreq):
+- ret = compat_sys_ioctl(fd, SIOCGARP, arg);
+- goto out;
+- case _IOW('i', 32, struct arpreq):
+- ret = compat_sys_ioctl(fd, SIOCDARP, arg);
+- goto out;
+-
+- case _IOW('i', 40, struct ifreq32): /* SIOCUPPER */
+- case _IOW('i', 41, struct ifreq32): /* SIOCLOWER */
+- case _IOW('i', 44, struct ifreq32): /* SIOCSETSYNC */
+- case _IOW('i', 45, struct ifreq32): /* SIOCGETSYNC */
+- case _IOW('i', 46, struct ifreq32): /* SIOCSSDSTATS */
+- case _IOW('i', 47, struct ifreq32): /* SIOCSSESTATS */
+- case _IOW('i', 48, struct ifreq32): /* SIOCSPROMISC */
+- ret = -EOPNOTSUPP;
+- goto out;
+-
+- case _IOW('i', 49, struct ifreq32):
+- ret = compat_sys_ioctl(fd, SIOCADDMULTI, arg);
+- goto out;
+- case _IOW('i', 50, struct ifreq32):
+- ret = compat_sys_ioctl(fd, SIOCDELMULTI, arg);
+- goto out;
+-
+- /* FDDI interface ioctls, unsupported. */
+-
+- case _IOW('i', 51, struct ifreq32): /* SIOCFDRESET */
+- case _IOW('i', 52, struct ifreq32): /* SIOCFDSLEEP */
+- case _IOW('i', 53, struct ifreq32): /* SIOCSTRTFMWAR */
+- case _IOW('i', 54, struct ifreq32): /* SIOCLDNSTRTFW */
+- case _IOW('i', 55, struct ifreq32): /* SIOCGETFDSTAT */
+- case _IOW('i', 56, struct ifreq32): /* SIOCFDNMIINT */
+- case _IOW('i', 57, struct ifreq32): /* SIOCFDEXUSER */
+- case _IOW('i', 58, struct ifreq32): /* SIOCFDGNETMAP */
+- case _IOW('i', 59, struct ifreq32): /* SIOCFDGIOCTL */
+- printk("FDDI ioctl, returning EOPNOTSUPP\n");
+- ret = -EOPNOTSUPP;
+- goto out;
+-
+- case _IOW('t', 125, int):
+- /* More stupid tty sunos ioctls, just
+- * say it worked.
+- */
+- ret = 0;
+- goto out;
+-
+- /* Non posix grp */
+- case _IOW('t', 118, int): {
+- int oldval, newval, __user *ptr;
+-
+- cmd = TIOCSPGRP;
+- ptr = (int __user *) (unsigned long) arg;
+- ret = -EFAULT;
+- if(get_user(oldval, ptr))
+- goto out;
+- ret = compat_sys_ioctl(fd, cmd, arg);
+- __get_user(newval, ptr);
+- if(newval == -1) {
+- __put_user(oldval, ptr);
+- ret = -EIO;
+- }
+- if(ret == -ENOTTY)
+- ret = -EIO;
+- goto out;
+- }
+-
+- case _IOR('t', 119, int): {
+- int oldval, newval, __user *ptr;
+-
+- cmd = TIOCGPGRP;
+- ptr = (int __user *) (unsigned long) arg;
+- ret = -EFAULT;
+- if(get_user(oldval, ptr))
+- goto out;
+- ret = compat_sys_ioctl(fd, cmd, arg);
+- __get_user(newval, ptr);
+- if(newval == -1) {
+- __put_user(oldval, ptr);
+- ret = -EIO;
+- }
+- if(ret == -ENOTTY)
+- ret = -EIO;
+- goto out;
+- }
+- };
+-
+- ret = compat_sys_ioctl(fd, cmd, arg);
+- /* so stupid... */
+- ret = (ret == -EINVAL ? -EOPNOTSUPP : ret);
+-out:
+- return ret;
+-}
+diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
+index f952745..8d4761f 100644
+--- a/arch/sparc64/kernel/sys_sparc.c
++++ b/arch/sparc64/kernel/sys_sparc.c
+@@ -454,8 +454,8 @@ asmlinkage long sys_ipc(unsigned int call, int first, unsigned long second,
+ err = sys_semget(first, (int)second, (int)third);
+ goto out;
+ case SEMCTL: {
+- err = sys_semctl(first, third,
+- (int)second | IPC_64,
++ err = sys_semctl(first, second,
++ (int)third | IPC_64,
+ (union semun) ptr);
+ goto out;
+ }
+@@ -720,44 +720,6 @@ out:
+ return err;
+ }
+
+-asmlinkage long solaris_syscall(struct pt_regs *regs)
+-{
+- static int count;
+-
+- regs->tpc = regs->tnpc;
+- regs->tnpc += 4;
+- if (test_thread_flag(TIF_32BIT)) {
+- regs->tpc &= 0xffffffff;
+- regs->tnpc &= 0xffffffff;
+- }
+- if (++count <= 5) {
+- printk ("For Solaris binary emulation you need solaris module loaded\n");
+- show_regs (regs);
+- }
+- send_sig(SIGSEGV, current, 1);
+-
+- return -ENOSYS;
+-}
+-
+-#ifndef CONFIG_SUNOS_EMUL
+-asmlinkage long sunos_syscall(struct pt_regs *regs)
+-{
+- static int count;
+-
+- regs->tpc = regs->tnpc;
+- regs->tnpc += 4;
+- if (test_thread_flag(TIF_32BIT)) {
+- regs->tpc &= 0xffffffff;
+- regs->tnpc &= 0xffffffff;
+- }
+- if (++count <= 20)
+- printk ("SunOS binary emulation not compiled in\n");
+- force_sig(SIGSEGV, current);
+-
+- return -ENOSYS;
+-}
+-#endif
+-
+ asmlinkage long sys_utrap_install(utrap_entry_t type,
+ utrap_handler_t new_p,
+ utrap_handler_t new_d,
+diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
+index 2455fa4..c1a61e9 100644
+--- a/arch/sparc64/kernel/sys_sparc32.c
++++ b/arch/sparc64/kernel/sys_sparc32.c
+@@ -55,7 +55,6 @@
+ #include <asm/types.h>
+ #include <asm/uaccess.h>
+ #include <asm/fpumacro.h>
+-#include <asm/semaphore.h>
+ #include <asm/mmu_context.h>
+ #include <asm/compat_signal.h>
+
+diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
+deleted file mode 100644
+index e91194f..0000000
+--- a/arch/sparc64/kernel/sys_sunos32.c
++++ /dev/null
+@@ -1,1359 +0,0 @@
+-/* $Id: sys_sunos32.c,v 1.64 2002/02/09 19:49:31 davem Exp $
+- * sys_sunos32.c: SunOS binary compatibility layer on sparc64.
+- *
+- * Copyright (C) 1995, 1996, 1997 David S. Miller (davem at caip.rutgers.edu)
+- * Copyright (C) 1995 Miguel de Icaza (miguel at nuclecu.unam.mx)
+- *
+- * Based upon preliminary work which is:
+- *
+- * Copyright (C) 1995 Adrian M. Rodriguez (adrian at remus.rutgers.edu)
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/types.h>
+-#include <linux/capability.h>
+-#include <linux/compat.h>
+-#include <linux/mman.h>
+-#include <linux/mm.h>
+-#include <linux/swap.h>
+-#include <linux/fs.h>
+-#include <linux/file.h>
+-#include <linux/resource.h>
+-#include <linux/ipc.h>
+-#include <linux/shm.h>
+-#include <linux/msg.h>
+-#include <linux/sem.h>
+-#include <linux/signal.h>
+-#include <linux/uio.h>
+-#include <linux/utsname.h>
+-#include <linux/major.h>
+-#include <linux/stat.h>
+-#include <linux/slab.h>
+-#include <linux/pagemap.h>
+-#include <linux/errno.h>
+-#include <linux/smp.h>
+-#include <linux/smp_lock.h>
+-#include <linux/syscalls.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/page.h>
+-#include <asm/pgtable.h>
+-#include <asm/pconf.h>
+-#include <asm/idprom.h> /* for gethostid() */
+-#include <asm/unistd.h>
+-#include <asm/system.h>
+-#include <asm/compat_signal.h>
+-
+-/* For the nfs mount emulation */
+-#include <linux/socket.h>
+-#include <linux/in.h>
+-#include <linux/nfs.h>
+-#include <linux/nfs2.h>
+-#include <linux/nfs_mount.h>
+-
+-/* for sunos_select */
+-#include <linux/time.h>
+-#include <linux/personality.h>
+-
+-/* For SOCKET_I */
+-#include <net/sock.h>
+-#include <net/compat.h>
+-
+-#define SUNOS_NR_OPEN 256
+-
+-asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 off)
+-{
+- struct file *file = NULL;
+- unsigned long retval, ret_type;
+-
+- if (flags & MAP_NORESERVE) {
+- static int cnt;
+- if (cnt++ < 10)
+- printk("%s: unimplemented SunOS MAP_NORESERVE mmap() flag\n",
+- current->comm);
+- flags &= ~MAP_NORESERVE;
+- }
+- retval = -EBADF;
+- if (!(flags & MAP_ANONYMOUS)) {
+- struct inode * inode;
+- if (fd >= SUNOS_NR_OPEN)
+- goto out;
+- file = fget(fd);
+- if (!file)
+- goto out;
+- inode = file->f_path.dentry->d_inode;
+- if (imajor(inode) == MEM_MAJOR && iminor(inode) == 5) {
+- flags |= MAP_ANONYMOUS;
+- fput(file);
+- file = NULL;
+- }
+- }
+-
+- retval = -EINVAL;
+- if (!(flags & MAP_FIXED))
+- addr = 0;
+- else if (len > 0xf0000000 || addr > 0xf0000000 - len)
+- goto out_putf;
+- ret_type = flags & _MAP_NEW;
+- flags &= ~_MAP_NEW;
+-
+- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+- down_write(¤t->mm->mmap_sem);
+- retval = do_mmap(file,
+- (unsigned long) addr, (unsigned long) len,
+- (unsigned long) prot, (unsigned long) flags,
+- (unsigned long) off);
+- up_write(¤t->mm->mmap_sem);
+- if (!ret_type)
+- retval = ((retval < 0xf0000000) ? 0 : retval);
+-out_putf:
+- if (file)
+- fput(file);
+-out:
+- return (u32) retval;
+-}
+-
+-asmlinkage int sunos_mctl(u32 addr, u32 len, int function, u32 arg)
+-{
+- return 0;
+-}
+-
+-asmlinkage int sunos_brk(u32 baddr)
+-{
+- int freepages, retval = -ENOMEM;
+- unsigned long rlim;
+- unsigned long newbrk, oldbrk, brk = (unsigned long) baddr;
+-
+- down_write(¤t->mm->mmap_sem);
+- if (brk < current->mm->end_code)
+- goto out;
+- newbrk = PAGE_ALIGN(brk);
+- oldbrk = PAGE_ALIGN(current->mm->brk);
+- retval = 0;
+- if (oldbrk == newbrk) {
+- current->mm->brk = brk;
+- goto out;
+- }
+- /* Always allow shrinking brk. */
+- if (brk <= current->mm->brk) {
+- current->mm->brk = brk;
+- do_munmap(current->mm, newbrk, oldbrk-newbrk);
+- goto out;
+- }
+- /* Check against rlimit and stack.. */
+- retval = -ENOMEM;
+- rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
+- if (rlim >= RLIM_INFINITY)
+- rlim = ~0;
+- if (brk - current->mm->end_code > rlim)
+- goto out;
+- /* Check against existing mmap mappings. */
+- if (find_vma_intersection(current->mm, oldbrk, newbrk+PAGE_SIZE))
+- goto out;
+- /* stupid algorithm to decide if we have enough memory: while
+- * simple, it hopefully works in most obvious cases.. Easy to
+- * fool it, but this should catch most mistakes.
+- */
+- freepages = global_page_state(NR_FILE_PAGES);
+- freepages >>= 1;
+- freepages += nr_free_pages();
+- freepages += nr_swap_pages;
+- freepages -= num_physpages >> 4;
+- freepages -= (newbrk-oldbrk) >> PAGE_SHIFT;
+- if (freepages < 0)
+- goto out;
+- /* Ok, we have probably got enough memory - let it rip. */
+- current->mm->brk = brk;
+- do_brk(oldbrk, newbrk-oldbrk);
+- retval = 0;
+-out:
+- up_write(¤t->mm->mmap_sem);
+- return retval;
+-}
+-
+-asmlinkage u32 sunos_sbrk(int increment)
+-{
+- int error, oldbrk;
+-
+- /* This should do it hopefully... */
+- oldbrk = (int)current->mm->brk;
+- error = sunos_brk(((int) current->mm->brk) + increment);
+- if (!error)
+- error = oldbrk;
+- return error;
+-}
+-
+-asmlinkage u32 sunos_sstk(int increment)
+-{
+- printk("%s: Call to sunos_sstk(increment<%d>) is unsupported\n",
+- current->comm, increment);
+-
+- return (u32)-1;
+-}
+-
+-/* Give hints to the kernel as to what paging strategy to use...
+- * Completely bogus, don't remind me.
+- */
+-#define VA_NORMAL 0 /* Normal vm usage expected */
+-#define VA_ABNORMAL 1 /* Abnormal/random vm usage probable */
+-#define VA_SEQUENTIAL 2 /* Accesses will be of a sequential nature */
+-#define VA_INVALIDATE 3 /* Page table entries should be flushed ??? */
+-static char *vstrings[] = {
+- "VA_NORMAL",
+- "VA_ABNORMAL",
+- "VA_SEQUENTIAL",
+- "VA_INVALIDATE",
+-};
+-
+-asmlinkage void sunos_vadvise(u32 strategy)
+-{
+- static int count;
+-
+- /* I wanna see who uses this... */
+- if (count++ < 5)
+- printk("%s: Advises us to use %s paging strategy\n",
+- current->comm,
+- strategy <= 3 ? vstrings[strategy] : "BOGUS");
+-}
+-
+-/* This just wants the soft limit (ie. rlim_cur element) of the RLIMIT_NOFILE
+- * resource limit and is for backwards compatibility with older sunos
+- * revs.
+- */
+-asmlinkage int sunos_getdtablesize(void)
+-{
+- return SUNOS_NR_OPEN;
+-}
+-
+-
+-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+-
+-asmlinkage u32 sunos_sigblock(u32 blk_mask)
+-{
+- u32 old;
+-
+- spin_lock_irq(¤t->sighand->siglock);
+- old = (u32) current->blocked.sig[0];
+- current->blocked.sig[0] |= (blk_mask & _BLOCKABLE);
+- recalc_sigpending();
+- spin_unlock_irq(¤t->sighand->siglock);
+- return old;
+-}
+-
+-asmlinkage u32 sunos_sigsetmask(u32 newmask)
+-{
+- u32 retval;
+-
+- spin_lock_irq(¤t->sighand->siglock);
+- retval = (u32) current->blocked.sig[0];
+- current->blocked.sig[0] = (newmask & _BLOCKABLE);
+- recalc_sigpending();
+- spin_unlock_irq(¤t->sighand->siglock);
+- return retval;
+-}
+-
+-/* SunOS getdents is very similar to the newer Linux (iBCS2 compliant) */
+-/* getdents system call, the format of the structure just has a different */
+-/* layout (d_off+d_ino instead of d_ino+d_off) */
+-struct sunos_dirent {
+- s32 d_off;
+- u32 d_ino;
+- u16 d_reclen;
+- u16 d_namlen;
+- char d_name[1];
+-};
+-
+-struct sunos_dirent_callback {
+- struct sunos_dirent __user *curr;
+- struct sunos_dirent __user *previous;
+- int count;
+- int error;
+-};
+-
+-#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
+-#define ROUND_UP(x) (((x)+sizeof(s32)-1) & ~(sizeof(s32)-1))
+-
+-static int sunos_filldir(void * __buf, const char * name, int namlen,
+- loff_t offset, ino_t ino, unsigned int d_type)
+-{
+- struct sunos_dirent __user *dirent;
+- struct sunos_dirent_callback * buf = (struct sunos_dirent_callback *) __buf;
+- int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+- u32 d_ino;
+-
+- buf->error = -EINVAL; /* only used if we fail.. */
+- if (reclen > buf->count)
+- return -EINVAL;
+- d_ino = ino;
+- if (sizeof(d_ino) < sizeof(ino) && d_ino != ino)
+- return -EOVERFLOW;
+- dirent = buf->previous;
+- if (dirent)
+- put_user(offset, &dirent->d_off);
+- dirent = buf->curr;
+- buf->previous = dirent;
+- put_user(d_ino, &dirent->d_ino);
+- put_user(namlen, &dirent->d_namlen);
+- put_user(reclen, &dirent->d_reclen);
+- if (copy_to_user(dirent->d_name, name, namlen))
+- return -EFAULT;
+- put_user(0, dirent->d_name + namlen);
+- dirent = (void __user *) dirent + reclen;
+- buf->curr = dirent;
+- buf->count -= reclen;
+- return 0;
+-}
+-
+-asmlinkage int sunos_getdents(unsigned int fd, void __user *dirent, int cnt)
+-{
+- struct file * file;
+- struct sunos_dirent __user *lastdirent;
+- struct sunos_dirent_callback buf;
+- int error = -EBADF;
+-
+- if (fd >= SUNOS_NR_OPEN)
+- goto out;
+-
+- file = fget(fd);
+- if (!file)
+- goto out;
+-
+- error = -EINVAL;
+- if (cnt < (sizeof(struct sunos_dirent) + 255))
+- goto out_putf;
+-
+- buf.curr = (struct sunos_dirent __user *) dirent;
+- buf.previous = NULL;
+- buf.count = cnt;
+- buf.error = 0;
+-
+- error = vfs_readdir(file, sunos_filldir, &buf);
+- if (error < 0)
+- goto out_putf;
+-
+- lastdirent = buf.previous;
+- error = buf.error;
+- if (lastdirent) {
+- put_user(file->f_pos, &lastdirent->d_off);
+- error = cnt - buf.count;
+- }
+-
+-out_putf:
+- fput(file);
+-out:
+- return error;
+-}
+-
+-/* Old sunos getdirentries, severely broken compatibility stuff here. */
+-struct sunos_direntry {
+- u32 d_ino;
+- u16 d_reclen;
+- u16 d_namlen;
+- char d_name[1];
+-};
+-
+-struct sunos_direntry_callback {
+- struct sunos_direntry __user *curr;
+- struct sunos_direntry __user *previous;
+- int count;
+- int error;
+-};
+-
+-static int sunos_filldirentry(void * __buf, const char * name, int namlen,
+- loff_t offset, ino_t ino, unsigned int d_type)
+-{
+- struct sunos_direntry __user *dirent;
+- struct sunos_direntry_callback * buf =
+- (struct sunos_direntry_callback *) __buf;
+- int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+- u32 d_ino;
+-
+- buf->error = -EINVAL; /* only used if we fail.. */
+- if (reclen > buf->count)
+- return -EINVAL;
+- d_ino = ino;
+- if (sizeof(d_ino) < sizeof(ino) && d_ino != ino)
+- return -EOVERFLOW;
+- dirent = buf->previous;
+- dirent = buf->curr;
+- buf->previous = dirent;
+- put_user(d_ino, &dirent->d_ino);
+- put_user(namlen, &dirent->d_namlen);
+- put_user(reclen, &dirent->d_reclen);
+- if (copy_to_user(dirent->d_name, name, namlen))
+- return -EFAULT;
+- put_user(0, dirent->d_name + namlen);
+- dirent = (void __user *) dirent + reclen;
+- buf->curr = dirent;
+- buf->count -= reclen;
+- return 0;
+-}
+-
+-asmlinkage int sunos_getdirentries(unsigned int fd,
+- void __user *dirent,
+- int cnt,
+- unsigned int __user *basep)
+-{
+- struct file * file;
+- struct sunos_direntry __user *lastdirent;
+- int error = -EBADF;
+- struct sunos_direntry_callback buf;
+-
+- if (fd >= SUNOS_NR_OPEN)
+- goto out;
+-
+- file = fget(fd);
+- if (!file)
+- goto out;
+-
+- error = -EINVAL;
+- if (cnt < (sizeof(struct sunos_direntry) + 255))
+- goto out_putf;
+-
+- buf.curr = (struct sunos_direntry __user *) dirent;
+- buf.previous = NULL;
+- buf.count = cnt;
+- buf.error = 0;
+-
+- error = vfs_readdir(file, sunos_filldirentry, &buf);
+- if (error < 0)
+- goto out_putf;
+-
+- lastdirent = buf.previous;
+- error = buf.error;
+- if (lastdirent) {
+- put_user(file->f_pos, basep);
+- error = cnt - buf.count;
+- }
+-
+-out_putf:
+- fput(file);
+-out:
+- return error;
+-}
+-
+-struct sunos_utsname {
+- char sname[9];
+- char nname[9];
+- char nnext[56];
+- char rel[9];
+- char ver[9];
+- char mach[9];
+-};
+-
+-asmlinkage int sunos_uname(struct sunos_utsname __user *name)
+-{
+- int ret;
+-
+- down_read(&uts_sem);
+- ret = copy_to_user(&name->sname[0], &utsname()->sysname[0],
+- sizeof(name->sname) - 1);
+- ret |= copy_to_user(&name->nname[0], &utsname()->nodename[0],
+- sizeof(name->nname) - 1);
+- ret |= put_user('\0', &name->nname[8]);
+- ret |= copy_to_user(&name->rel[0], &utsname()->release[0],
+- sizeof(name->rel) - 1);
+- ret |= copy_to_user(&name->ver[0], &utsname()->version[0],
+- sizeof(name->ver) - 1);
+- ret |= copy_to_user(&name->mach[0], &utsname()->machine[0],
+- sizeof(name->mach) - 1);
+- up_read(&uts_sem);
+- return (ret ? -EFAULT : 0);
+-}
+-
+-asmlinkage int sunos_nosys(void)
+-{
+- struct pt_regs *regs;
+- siginfo_t info;
+- static int cnt;
+-
+- regs = current_thread_info()->kregs;
+- if (test_thread_flag(TIF_32BIT)) {
+- regs->tpc &= 0xffffffff;
+- regs->tnpc &= 0xffffffff;
+- }
+- info.si_signo = SIGSYS;
+- info.si_errno = 0;
+- info.si_code = __SI_FAULT|0x100;
+- info.si_addr = (void __user *)regs->tpc;
+- info.si_trapno = regs->u_regs[UREG_G1];
+- send_sig_info(SIGSYS, &info, current);
+- if (cnt++ < 4) {
+- printk("Process makes ni_syscall number %d, register dump:\n",
+- (int) regs->u_regs[UREG_G1]);
+- show_regs(regs);
+- }
+- return -ENOSYS;
+-}
+-
+-/* This is not a real and complete implementation yet, just to keep
+- * the easy SunOS binaries happy.
+- */
+-asmlinkage int sunos_fpathconf(int fd, int name)
+-{
+- int ret;
+-
+- switch(name) {
+- case _PCONF_LINK:
+- ret = LINK_MAX;
+- break;
+- case _PCONF_CANON:
+- ret = MAX_CANON;
+- break;
+- case _PCONF_INPUT:
+- ret = MAX_INPUT;
+- break;
+- case _PCONF_NAME:
+- ret = NAME_MAX;
+- break;
+- case _PCONF_PATH:
+- ret = PATH_MAX;
+- break;
+- case _PCONF_PIPE:
+- ret = PIPE_BUF;
+- break;
+- case _PCONF_CHRESTRICT: /* XXX Investigate XXX */
+- ret = 1;
+- break;
+- case _PCONF_NOTRUNC: /* XXX Investigate XXX */
+- case _PCONF_VDISABLE:
+- ret = 0;
+- break;
+- default:
+- ret = -EINVAL;
+- break;
+- }
+- return ret;
+-}
+-
+-asmlinkage int sunos_pathconf(u32 u_path, int name)
+-{
+- int ret;
+-
+- ret = sunos_fpathconf(0, name); /* XXX cheese XXX */
+- return ret;
+-}
+-
+-asmlinkage int sunos_select(int width, u32 inp, u32 outp, u32 exp, u32 tvp_x)
+-{
+- int ret;
+-
+- /* SunOS binaries expect that select won't change the tvp contents */
+- ret = compat_sys_select(width, compat_ptr(inp), compat_ptr(outp),
+- compat_ptr(exp), compat_ptr(tvp_x));
+- if (ret == -EINTR && tvp_x) {
+- struct compat_timeval __user *tvp = compat_ptr(tvp_x);
+- time_t sec, usec;
+-
+- __get_user(sec, &tvp->tv_sec);
+- __get_user(usec, &tvp->tv_usec);
+- if (sec == 0 && usec == 0)
+- ret = 0;
+- }
+- return ret;
+-}
+-
+-asmlinkage void sunos_nop(void)
+-{
+- return;
+-}
+-
+-#if 0 /* This code doesn't translate user pointers correctly,
+- * disable for now. -DaveM
+- */
+-
+-/* XXXXXXXXXX SunOS mount/umount. XXXXXXXXXXX */
+-#define SMNT_RDONLY 1
+-#define SMNT_NOSUID 2
+-#define SMNT_NEWTYPE 4
+-#define SMNT_GRPID 8
+-#define SMNT_REMOUNT 16
+-#define SMNT_NOSUB 32
+-#define SMNT_MULTI 64
+-#define SMNT_SYS5 128
+-
+-struct sunos_fh_t {
+- char fh_data [NFS_FHSIZE];
+-};
+-
+-struct sunos_nfs_mount_args {
+- struct sockaddr_in *addr; /* file server address */
+- struct nfs_fh *fh; /* File handle to be mounted */
+- int flags; /* flags */
+- int wsize; /* write size in bytes */
+- int rsize; /* read size in bytes */
+- int timeo; /* initial timeout in .1 secs */
+- int retrans; /* times to retry send */
+- char *hostname; /* server's hostname */
+- int acregmin; /* attr cache file min secs */
+- int acregmax; /* attr cache file max secs */
+- int acdirmin; /* attr cache dir min secs */
+- int acdirmax; /* attr cache dir max secs */
+- char *netname; /* server's netname */
+-};
+-
+-
+-/* Bind the socket on a local reserved port and connect it to the
+- * remote server. This on Linux/i386 is done by the mount program,
+- * not by the kernel.
+- */
+-/* XXXXXXXXXXXXXXXXXXXX */
+-static int
+-sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr)
+-{
+- struct sockaddr_in local;
+- struct sockaddr_in server;
+- int try_port;
+- int ret;
+- struct socket *socket;
+- struct inode *inode;
+- struct file *file;
+-
+- file = fget(fd);
+- if (!file)
+- return 0;
+-
+- inode = file->f_path.dentry->d_inode;
+-
+- socket = SOCKET_I(inode);
+- local.sin_family = AF_INET;
+- local.sin_addr.s_addr = htonl(INADDR_ANY);
+-
+- /* IPPORT_RESERVED = 1024, can't find the definition in the kernel */
+- try_port = 1024;
+- do {
+- local.sin_port = htons (--try_port);
+- ret = socket->ops->bind(socket, (struct sockaddr*)&local,
+- sizeof(local));
+- } while (ret && try_port > (1024 / 2));
+-
+- if (ret) {
+- fput(file);
+- return 0;
+- }
+-
+- server.sin_family = AF_INET;
+- server.sin_addr = addr->sin_addr;
+- server.sin_port = NFS_PORT;
+-
+- /* Call sys_connect */
+- ret = socket->ops->connect (socket, (struct sockaddr *) &server,
+- sizeof (server), file->f_flags);
+- fput(file);
+- if (ret < 0)
+- return 0;
+- return 1;
+-}
+-
+-/* XXXXXXXXXXXXXXXXXXXX */
+-static int get_default (int value, int def_value)
+-{
+- if (value)
+- return value;
+- else
+- return def_value;
+-}
+-
+-/* XXXXXXXXXXXXXXXXXXXX */
+-static int sunos_nfs_mount(char *dir_name, int linux_flags, void __user *data)
+-{
+- int server_fd, err;
+- char *the_name, *mount_page;
+- struct nfs_mount_data linux_nfs_mount;
+- struct sunos_nfs_mount_args sunos_mount;
+-
+- /* Ok, here comes the fun part: Linux's nfs mount needs a
+- * socket connection to the server, but SunOS mount does not
+- * require this, so we use the information on the destination
+- * address to create a socket and bind it to a reserved
+- * port on this system
+- */
+- if (copy_from_user(&sunos_mount, data, sizeof(sunos_mount)))
+- return -EFAULT;
+-
+- server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+- if (server_fd < 0)
+- return -ENXIO;
+-
+- if (copy_from_user(&linux_nfs_mount.addr, sunos_mount.addr,
+- sizeof(*sunos_mount.addr)) ||
+- copy_from_user(&linux_nfs_mount.root, sunos_mount.fh,
+- sizeof(*sunos_mount.fh))) {
+- sys_close (server_fd);
+- return -EFAULT;
+- }
+-
+- if (!sunos_nfs_get_server_fd (server_fd, &linux_nfs_mount.addr)){
+- sys_close (server_fd);
+- return -ENXIO;
+- }
+-
+- /* Now, bind it to a locally reserved port */
+- linux_nfs_mount.version = NFS_MOUNT_VERSION;
+- linux_nfs_mount.flags = sunos_mount.flags;
+- linux_nfs_mount.fd = server_fd;
+-
+- linux_nfs_mount.rsize = get_default (sunos_mount.rsize, 8192);
+- linux_nfs_mount.wsize = get_default (sunos_mount.wsize, 8192);
+- linux_nfs_mount.timeo = get_default (sunos_mount.timeo, 10);
+- linux_nfs_mount.retrans = sunos_mount.retrans;
+-
+- linux_nfs_mount.acregmin = sunos_mount.acregmin;
+- linux_nfs_mount.acregmax = sunos_mount.acregmax;
+- linux_nfs_mount.acdirmin = sunos_mount.acdirmin;
+- linux_nfs_mount.acdirmax = sunos_mount.acdirmax;
+-
+- the_name = getname(sunos_mount.hostname);
+- if (IS_ERR(the_name))
+- return PTR_ERR(the_name);
+-
+- strlcpy(linux_nfs_mount.hostname, the_name,
+- sizeof(linux_nfs_mount.hostname));
+- putname (the_name);
+-
+- mount_page = (char *) get_zeroed_page(GFP_KERNEL);
+- if (!mount_page)
+- return -ENOMEM;
+-
+- memcpy(mount_page, &linux_nfs_mount, sizeof(linux_nfs_mount));
+-
+- err = do_mount("", dir_name, "nfs", linux_flags, mount_page);
+-
+- free_page((unsigned long) mount_page);
+- return err;
+-}
+-
+-/* XXXXXXXXXXXXXXXXXXXX */
+-asmlinkage int
+-sunos_mount(char *type, char *dir, int flags, void *data)
+-{
+- int linux_flags = 0;
+- int ret = -EINVAL;
+- char *dev_fname = 0;
+- char *dir_page, *type_page;
+-
+- if (!capable (CAP_SYS_ADMIN))
+- return -EPERM;
+-
+- /* We don't handle the integer fs type */
+- if ((flags & SMNT_NEWTYPE) == 0)
+- goto out;
+-
+- /* Do not allow for those flags we don't support */
+- if (flags & (SMNT_GRPID|SMNT_NOSUB|SMNT_MULTI|SMNT_SYS5))
+- goto out;
+-
+- if (flags & SMNT_REMOUNT)
+- linux_flags |= MS_REMOUNT;
+- if (flags & SMNT_RDONLY)
+- linux_flags |= MS_RDONLY;
+- if (flags & SMNT_NOSUID)
+- linux_flags |= MS_NOSUID;
+-
+- dir_page = getname(dir);
+- ret = PTR_ERR(dir_page);
+- if (IS_ERR(dir_page))
+- goto out;
+-
+- type_page = getname(type);
+- ret = PTR_ERR(type_page);
+- if (IS_ERR(type_page))
+- goto out1;
+-
+- if (strcmp(type_page, "ext2") == 0) {
+- dev_fname = getname(data);
+- } else if (strcmp(type_page, "iso9660") == 0) {
+- dev_fname = getname(data);
+- } else if (strcmp(type_page, "minix") == 0) {
+- dev_fname = getname(data);
+- } else if (strcmp(type_page, "nfs") == 0) {
+- ret = sunos_nfs_mount (dir_page, flags, data);
+- goto out2;
+- } else if (strcmp(type_page, "ufs") == 0) {
+- printk("Warning: UFS filesystem mounts unsupported.\n");
+- ret = -ENODEV;
+- goto out2;
+- } else if (strcmp(type_page, "proc")) {
+- ret = -ENODEV;
+- goto out2;
+- }
+- ret = PTR_ERR(dev_fname);
+- if (IS_ERR(dev_fname))
+- goto out2;
+- lock_kernel();
+- ret = do_mount(dev_fname, dir_page, type_page, linux_flags, NULL);
+- unlock_kernel();
+- if (dev_fname)
+- putname(dev_fname);
+-out2:
+- putname(type_page);
+-out1:
+- putname(dir_page);
+-out:
+- return ret;
+-}
+-#endif
+-
+-asmlinkage int sunos_setpgrp(pid_t pid, pid_t pgid)
+-{
+- int ret;
+-
+- /* So stupid... */
+- if ((!pid || pid == current->pid) &&
+- !pgid) {
+- sys_setsid();
+- ret = 0;
+- } else {
+- ret = sys_setpgid(pid, pgid);
+- }
+- return ret;
+-}
+-
+-/* So stupid... */
+-extern long compat_sys_wait4(compat_pid_t, compat_uint_t __user *, int,
+- struct compat_rusage __user *);
+-
+-asmlinkage int sunos_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options, struct compat_rusage __user *ru)
+-{
+- int ret;
+-
+- ret = compat_sys_wait4((pid ? pid : ((compat_pid_t)-1)),
+- stat_addr, options, ru);
+- return ret;
+-}
+-
+-asmlinkage int sunos_killpg(int pgrp, int sig)
+-{
+- int ret;
+-
+- rcu_read_lock();
+- ret = -EINVAL;
+- if (pgrp > 0)
+- ret = kill_pgrp(find_vpid(pgrp), sig, 0);
+- rcu_read_unlock();
+-
+- return ret;
+-}
+-
+-asmlinkage int sunos_audit(void)
+-{
+- printk ("sys_audit\n");
+- return -1;
+-}
+-
+-asmlinkage u32 sunos_gethostid(void)
+-{
+- u32 ret;
+-
+- ret = (((u32)idprom->id_machtype << 24) | ((u32)idprom->id_sernum));
+-
+- return ret;
+-}
+-
+-/* sysconf options, for SunOS compatibility */
+-#define _SC_ARG_MAX 1
+-#define _SC_CHILD_MAX 2
+-#define _SC_CLK_TCK 3
+-#define _SC_NGROUPS_MAX 4
+-#define _SC_OPEN_MAX 5
+-#define _SC_JOB_CONTROL 6
+-#define _SC_SAVED_IDS 7
+-#define _SC_VERSION 8
+-
+-asmlinkage s32 sunos_sysconf (int name)
+-{
+- s32 ret;
+-
+- switch (name){
+- case _SC_ARG_MAX:
+- ret = ARG_MAX;
+- break;
+- case _SC_CHILD_MAX:
+- ret = current->signal->rlim[RLIMIT_NPROC].rlim_cur;
+- break;
+- case _SC_CLK_TCK:
+- ret = HZ;
+- break;
+- case _SC_NGROUPS_MAX:
+- ret = NGROUPS_MAX;
+- break;
+- case _SC_OPEN_MAX:
+- ret = current->signal->rlim[RLIMIT_NOFILE].rlim_cur;
+- break;
+- case _SC_JOB_CONTROL:
+- ret = 1; /* yes, we do support job control */
+- break;
+- case _SC_SAVED_IDS:
+- ret = 1; /* yes, we do support saved uids */
+- break;
+- case _SC_VERSION:
+- /* mhm, POSIX_VERSION is in /usr/include/unistd.h
+- * should it go on /usr/include/linux?
+- */
+- ret = 199009;
+- break;
+- default:
+- ret = -1;
+- break;
+- };
+- return ret;
+-}
+-
+-asmlinkage int sunos_semsys(int op, u32 arg1, u32 arg2, u32 arg3, void __user *ptr)
+-{
+- union semun arg4;
+- int ret;
+-
+- switch (op) {
+- case 0:
+- /* Most arguments match on a 1:1 basis but cmd doesn't */
+- switch(arg3) {
+- case 4:
+- arg3=GETPID; break;
+- case 5:
+- arg3=GETVAL; break;
+- case 6:
+- arg3=GETALL; break;
+- case 3:
+- arg3=GETNCNT; break;
+- case 7:
+- arg3=GETZCNT; break;
+- case 8:
+- arg3=SETVAL; break;
+- case 9:
+- arg3=SETALL; break;
+- }
+- /* sys_semctl(): */
+- /* value to modify semaphore to */
+- arg4.__pad = ptr;
+- ret = sys_semctl((int)arg1, (int)arg2, (int)arg3, arg4);
+- break;
+- case 1:
+- /* sys_semget(): */
+- ret = sys_semget((key_t)arg1, (int)arg2, (int)arg3);
+- break;
+- case 2:
+- /* sys_semop(): */
+- ret = sys_semop((int)arg1, (struct sembuf __user *)(unsigned long)arg2,
+- (unsigned int) arg3);
+- break;
+- default:
+- ret = -EINVAL;
+- break;
+- };
+- return ret;
+-}
+-
+-struct msgbuf32 {
+- s32 mtype;
+- char mtext[1];
+-};
+-
+-struct ipc_perm32
+-{
+- key_t key;
+- compat_uid_t uid;
+- compat_gid_t gid;
+- compat_uid_t cuid;
+- compat_gid_t cgid;
+- compat_mode_t mode;
+- unsigned short seq;
+-};
+-
+-struct msqid_ds32
+-{
+- struct ipc_perm32 msg_perm;
+- u32 msg_first;
+- u32 msg_last;
+- compat_time_t msg_stime;
+- compat_time_t msg_rtime;
+- compat_time_t msg_ctime;
+- u32 wwait;
+- u32 rwait;
+- unsigned short msg_cbytes;
+- unsigned short msg_qnum;
+- unsigned short msg_qbytes;
+- compat_ipc_pid_t msg_lspid;
+- compat_ipc_pid_t msg_lrpid;
+-};
+-
+-static inline int sunos_msqid_get(struct msqid_ds32 __user *user,
+- struct msqid_ds *kern)
+-{
+- if (get_user(kern->msg_perm.key, &user->msg_perm.key) ||
+- __get_user(kern->msg_perm.uid, &user->msg_perm.uid) ||
+- __get_user(kern->msg_perm.gid, &user->msg_perm.gid) ||
+- __get_user(kern->msg_perm.cuid, &user->msg_perm.cuid) ||
+- __get_user(kern->msg_perm.cgid, &user->msg_perm.cgid) ||
+- __get_user(kern->msg_stime, &user->msg_stime) ||
+- __get_user(kern->msg_rtime, &user->msg_rtime) ||
+- __get_user(kern->msg_ctime, &user->msg_ctime) ||
+- __get_user(kern->msg_ctime, &user->msg_cbytes) ||
+- __get_user(kern->msg_ctime, &user->msg_qnum) ||
+- __get_user(kern->msg_ctime, &user->msg_qbytes) ||
+- __get_user(kern->msg_ctime, &user->msg_lspid) ||
+- __get_user(kern->msg_ctime, &user->msg_lrpid))
+- return -EFAULT;
+- return 0;
+-}
+-
+-static inline int sunos_msqid_put(struct msqid_ds32 __user *user,
+- struct msqid_ds *kern)
+-{
+- if (put_user(kern->msg_perm.key, &user->msg_perm.key) ||
+- __put_user(kern->msg_perm.uid, &user->msg_perm.uid) ||
+- __put_user(kern->msg_perm.gid, &user->msg_perm.gid) ||
+- __put_user(kern->msg_perm.cuid, &user->msg_perm.cuid) ||
+- __put_user(kern->msg_perm.cgid, &user->msg_perm.cgid) ||
+- __put_user(kern->msg_stime, &user->msg_stime) ||
+- __put_user(kern->msg_rtime, &user->msg_rtime) ||
+- __put_user(kern->msg_ctime, &user->msg_ctime) ||
+- __put_user(kern->msg_ctime, &user->msg_cbytes) ||
+- __put_user(kern->msg_ctime, &user->msg_qnum) ||
+- __put_user(kern->msg_ctime, &user->msg_qbytes) ||
+- __put_user(kern->msg_ctime, &user->msg_lspid) ||
+- __put_user(kern->msg_ctime, &user->msg_lrpid))
+- return -EFAULT;
+- return 0;
+-}
+-
+-static inline int sunos_msgbuf_get(struct msgbuf32 __user *user, struct msgbuf *kern, int len)
+-{
+- if (get_user(kern->mtype, &user->mtype) ||
+- __copy_from_user(kern->mtext, &user->mtext, len))
+- return -EFAULT;
+- return 0;
+-}
+-
+-static inline int sunos_msgbuf_put(struct msgbuf32 __user *user, struct msgbuf *kern, int len)
+-{
+- if (put_user(kern->mtype, &user->mtype) ||
+- __copy_to_user(user->mtext, kern->mtext, len))
+- return -EFAULT;
+- return 0;
+-}
+-
+-asmlinkage int sunos_msgsys(int op, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
+-{
+- struct sparc_stackf32 __user *sp;
+- struct msqid_ds kds;
+- struct msgbuf *kmbuf;
+- mm_segment_t old_fs = get_fs();
+- u32 arg5;
+- int rval;
+-
+- switch(op) {
+- case 0:
+- rval = sys_msgget((key_t)arg1, (int)arg2);
+- break;
+- case 1:
+- if (!sunos_msqid_get((struct msqid_ds32 __user *)(unsigned long)arg3, &kds)) {
+- set_fs(KERNEL_DS);
+- rval = sys_msgctl((int)arg1, (int)arg2,
+- (struct msqid_ds __user *)(unsigned long)arg3);
+- set_fs(old_fs);
+- if (!rval)
+- rval = sunos_msqid_put((struct msqid_ds32 __user *)(unsigned long)arg3,
+- &kds);
+- } else
+- rval = -EFAULT;
+- break;
+- case 2:
+- rval = -EFAULT;
+- kmbuf = kmalloc(sizeof(struct msgbuf) + arg3,
+- GFP_KERNEL);
+- if (!kmbuf)
+- break;
+- sp = (struct sparc_stackf32 __user *)
+- (current_thread_info()->kregs->u_regs[UREG_FP] & 0xffffffffUL);
+- if (get_user(arg5, &sp->xxargs[0])) {
+- rval = -EFAULT;
+- kfree(kmbuf);
+- break;
+- }
+- set_fs(KERNEL_DS);
+- rval = sys_msgrcv((int)arg1, (struct msgbuf __user *) kmbuf,
+- (size_t)arg3,
+- (long)arg4, (int)arg5);
+- set_fs(old_fs);
+- if (!rval)
+- rval = sunos_msgbuf_put((struct msgbuf32 __user *)(unsigned long)arg2,
+- kmbuf, arg3);
+- kfree(kmbuf);
+- break;
+- case 3:
+- rval = -EFAULT;
+- kmbuf = kmalloc(sizeof(struct msgbuf) + arg3,
+- GFP_KERNEL);
+- if (!kmbuf || sunos_msgbuf_get((struct msgbuf32 __user *)(unsigned long)arg2,
+- kmbuf, arg3))
+- break;
+- set_fs(KERNEL_DS);
+- rval = sys_msgsnd((int)arg1, (struct msgbuf __user *) kmbuf,
+- (size_t)arg3, (int)arg4);
+- set_fs(old_fs);
+- kfree(kmbuf);
+- break;
+- default:
+- rval = -EINVAL;
+- break;
+- }
+- return rval;
+-}
+-
+-struct shmid_ds32 {
+- struct ipc_perm32 shm_perm;
+- int shm_segsz;
+- compat_time_t shm_atime;
+- compat_time_t shm_dtime;
+- compat_time_t shm_ctime;
+- compat_ipc_pid_t shm_cpid;
+- compat_ipc_pid_t shm_lpid;
+- unsigned short shm_nattch;
+-};
+-
+-static inline int sunos_shmid_get(struct shmid_ds32 __user *user,
+- struct shmid_ds *kern)
+-{
+- if (get_user(kern->shm_perm.key, &user->shm_perm.key) ||
+- __get_user(kern->shm_perm.uid, &user->shm_perm.uid) ||
+- __get_user(kern->shm_perm.gid, &user->shm_perm.gid) ||
+- __get_user(kern->shm_perm.cuid, &user->shm_perm.cuid) ||
+- __get_user(kern->shm_perm.cgid, &user->shm_perm.cgid) ||
+- __get_user(kern->shm_segsz, &user->shm_segsz) ||
+- __get_user(kern->shm_atime, &user->shm_atime) ||
+- __get_user(kern->shm_dtime, &user->shm_dtime) ||
+- __get_user(kern->shm_ctime, &user->shm_ctime) ||
+- __get_user(kern->shm_cpid, &user->shm_cpid) ||
+- __get_user(kern->shm_lpid, &user->shm_lpid) ||
+- __get_user(kern->shm_nattch, &user->shm_nattch))
+- return -EFAULT;
+- return 0;
+-}
+-
+-static inline int sunos_shmid_put(struct shmid_ds32 __user *user,
+- struct shmid_ds *kern)
+-{
+- if (put_user(kern->shm_perm.key, &user->shm_perm.key) ||
+- __put_user(kern->shm_perm.uid, &user->shm_perm.uid) ||
+- __put_user(kern->shm_perm.gid, &user->shm_perm.gid) ||
+- __put_user(kern->shm_perm.cuid, &user->shm_perm.cuid) ||
+- __put_user(kern->shm_perm.cgid, &user->shm_perm.cgid) ||
+- __put_user(kern->shm_segsz, &user->shm_segsz) ||
+- __put_user(kern->shm_atime, &user->shm_atime) ||
+- __put_user(kern->shm_dtime, &user->shm_dtime) ||
+- __put_user(kern->shm_ctime, &user->shm_ctime) ||
+- __put_user(kern->shm_cpid, &user->shm_cpid) ||
+- __put_user(kern->shm_lpid, &user->shm_lpid) ||
+- __put_user(kern->shm_nattch, &user->shm_nattch))
+- return -EFAULT;
+- return 0;
+-}
+-
+-asmlinkage int sunos_shmsys(int op, u32 arg1, u32 arg2, u32 arg3)
+-{
+- struct shmid_ds ksds;
+- unsigned long raddr;
+- mm_segment_t old_fs = get_fs();
+- int rval;
+-
+- switch(op) {
+- case 0:
+- /* do_shmat(): attach a shared memory area */
+- rval = do_shmat((int)arg1,(char __user *)(unsigned long)arg2,(int)arg3,&raddr);
+- if (!rval)
+- rval = (int) raddr;
+- break;
+- case 1:
+- /* sys_shmctl(): modify shared memory area attr. */
+- if (!sunos_shmid_get((struct shmid_ds32 __user *)(unsigned long)arg3, &ksds)) {
+- set_fs(KERNEL_DS);
+- rval = sys_shmctl((int) arg1,(int) arg2,
+- (struct shmid_ds __user *) &ksds);
+- set_fs(old_fs);
+- if (!rval)
+- rval = sunos_shmid_put((struct shmid_ds32 __user *)(unsigned long)arg3,
+- &ksds);
+- } else
+- rval = -EFAULT;
+- break;
+- case 2:
+- /* sys_shmdt(): detach a shared memory area */
+- rval = sys_shmdt((char __user *)(unsigned long)arg1);
+- break;
+- case 3:
+- /* sys_shmget(): get a shared memory area */
+- rval = sys_shmget((key_t)arg1,(int)arg2,(int)arg3);
+- break;
+- default:
+- rval = -EINVAL;
+- break;
+- };
+- return rval;
+-}
+-
+-extern asmlinkage long sparc32_open(const char __user * filename, int flags, int mode);
+-
+-asmlinkage int sunos_open(u32 fname, int flags, int mode)
+-{
+- const char __user *filename = compat_ptr(fname);
+-
+- return sparc32_open(filename, flags, mode);
+-}
+-
+-#define SUNOS_EWOULDBLOCK 35
+-
+-/* see the sunos man page read(2v) for an explanation
+- of this garbage. We use O_NDELAY to mark
+- file descriptors that have been set non-blocking
+- using 4.2BSD style calls. (tridge) */
+-
+-static inline int check_nonblock(int ret, int fd)
+-{
+- if (ret == -EAGAIN) {
+- struct file * file = fget(fd);
+- if (file) {
+- if (file->f_flags & O_NDELAY)
+- ret = -SUNOS_EWOULDBLOCK;
+- fput(file);
+- }
+- }
+- return ret;
+-}
+-
+-asmlinkage int sunos_read(unsigned int fd, char __user *buf, u32 count)
+-{
+- int ret;
+-
+- ret = check_nonblock(sys_read(fd, buf, count), fd);
+- return ret;
+-}
+-
+-asmlinkage int sunos_readv(u32 fd, void __user *vector, s32 count)
+-{
+- int ret;
+-
+- ret = check_nonblock(compat_sys_readv(fd, vector, count), fd);
+- return ret;
+-}
+-
+-asmlinkage int sunos_write(unsigned int fd, char __user *buf, u32 count)
+-{
+- int ret;
+-
+- ret = check_nonblock(sys_write(fd, buf, count), fd);
+- return ret;
+-}
+-
+-asmlinkage int sunos_writev(u32 fd, void __user *vector, s32 count)
+-{
+- int ret;
+-
+- ret = check_nonblock(compat_sys_writev(fd, vector, count), fd);
+- return ret;
+-}
+-
+-asmlinkage int sunos_recv(u32 __fd, void __user *ubuf, int size, unsigned flags)
+-{
+- int ret, fd = (int) __fd;
+-
+- ret = check_nonblock(sys_recv(fd, ubuf, size, flags), fd);
+- return ret;
+-}
+-
+-asmlinkage int sunos_send(u32 __fd, void __user *buff, int len, unsigned flags)
+-{
+- int ret, fd = (int) __fd;
+-
+- ret = check_nonblock(sys_send(fd, buff, len, flags), fd);
+- return ret;
+-}
+-
+-asmlinkage int sunos_accept(u32 __fd, struct sockaddr __user *sa, int __user *addrlen)
+-{
+- int ret, fd = (int) __fd;
+-
+- while (1) {
+- ret = check_nonblock(sys_accept(fd, sa, addrlen), fd);
+- if (ret != -ENETUNREACH && ret != -EHOSTUNREACH)
+- break;
+- }
+- return ret;
+-}
+-
+-#define SUNOS_SV_INTERRUPT 2
+-
+-asmlinkage int sunos_sigaction (int sig,
+- struct old_sigaction32 __user *act,
+- struct old_sigaction32 __user *oact)
+-{
+- struct k_sigaction new_ka, old_ka;
+- int ret;
+-
+- if (act) {
+- compat_old_sigset_t mask;
+- u32 u_handler;
+-
+- if (get_user(u_handler, &act->sa_handler) ||
+- __get_user(new_ka.sa.sa_flags, &act->sa_flags))
+- return -EFAULT;
+- new_ka.sa.sa_handler = compat_ptr(u_handler);
+- __get_user(mask, &act->sa_mask);
+- new_ka.sa.sa_restorer = NULL;
+- new_ka.ka_restorer = NULL;
+- siginitset(&new_ka.sa.sa_mask, mask);
+- new_ka.sa.sa_flags ^= SUNOS_SV_INTERRUPT;
+- }
+-
+- ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+-
+- if (!ret && oact) {
+- old_ka.sa.sa_flags ^= SUNOS_SV_INTERRUPT;
+- if (put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler) ||
+- __put_user(old_ka.sa.sa_flags, &oact->sa_flags))
+- return -EFAULT;
+- __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+- }
+-
+- return ret;
+-}
+-
+-asmlinkage int sunos_setsockopt(u32 __fd, u32 __level, u32 __optname,
+- char __user *optval, u32 __optlen)
+-{
+- int fd = (int) __fd;
+- int level = (int) __level;
+- int optname = (int) __optname;
+- int optlen = (int) __optlen;
+- int tr_opt = optname;
+- int ret;
+-
+- if (level == SOL_IP) {
+- /* Multicast socketopts (ttl, membership) */
+- if (tr_opt >=2 && tr_opt <= 6)
+- tr_opt += 30;
+- }
+- ret = sys_setsockopt(fd, level, tr_opt,
+- optval, optlen);
+- return ret;
+-}
+-
+-asmlinkage int sunos_getsockopt(u32 __fd, u32 __level, u32 __optname,
+- char __user *optval, int __user *optlen)
+-{
+- int fd = (int) __fd;
+- int level = (int) __level;
+- int optname = (int) __optname;
+- int tr_opt = optname;
+- int ret;
+-
+- if (level == SOL_IP) {
+- /* Multicast socketopts (ttl, membership) */
+- if (tr_opt >=2 && tr_opt <= 6)
+- tr_opt += 30;
+- }
+- ret = compat_sys_getsockopt(fd, level, tr_opt,
+- optval, optlen);
+- return ret;
+-}
+diff --git a/arch/sparc64/kernel/sysfs.c b/arch/sparc64/kernel/sysfs.c
+index 52816c7..e885034 100644
+--- a/arch/sparc64/kernel/sysfs.c
++++ b/arch/sparc64/kernel/sysfs.c
+@@ -273,10 +273,22 @@ static void __init check_mmu_stats(void)
+ mmu_stats_supported = 1;
+ }
+
++static void register_nodes(void)
++{
++#ifdef CONFIG_NUMA
++ int i;
++
++ for (i = 0; i < MAX_NUMNODES; i++)
++ register_one_node(i);
++#endif
++}
++
+ static int __init topology_init(void)
+ {
+ int cpu;
+
++ register_nodes();
++
+ check_mmu_stats();
+
+ register_cpu_notifier(&sysfs_cpu_nb);
+diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
+index 6b9b718..a4fef2b 100644
+--- a/arch/sparc64/kernel/systbls.S
++++ b/arch/sparc64/kernel/systbls.S
+@@ -155,125 +155,3 @@ sys_call_table:
+ .word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
+ /*310*/ .word sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
+ .word sys_timerfd_settime, sys_timerfd_gettime
+-
+-#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
+- defined(CONFIG_SOLARIS_EMUL_MODULE)
+- /* Now the 32-bit SunOS syscall table. */
+-
+- .align 4
+- .globl sunos_sys_table
+-sunos_sys_table:
+-/*0*/ .word sunos_indir, sys32_exit, sys_fork
+- .word sunos_read, sunos_write, sunos_open
+- .word sys_close, sunos_wait4, sys_creat
+- .word sys_link, sys_unlink, sunos_execv
+- .word sys_chdir, sunos_nosys, sys32_mknod
+- .word sys_chmod, sys32_lchown16, sunos_brk
+- .word sunos_nosys, sys32_lseek, sunos_getpid
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_getuid, sunos_nosys, sys_ptrace
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sys_access, sunos_nosys, sunos_nosys
+- .word sys_sync, sys_kill, compat_sys_newstat
+- .word sunos_nosys, compat_sys_newlstat, sys_dup
+- .word sys_pipe, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_getgid
+- .word sunos_nosys, sunos_nosys
+-/*50*/ .word sunos_nosys, sys_acct, sunos_nosys
+- .word sunos_mctl, sunos_ioctl, sys_reboot
+- .word sunos_nosys, sys_symlink, sys_readlink
+- .word sys32_execve, sys_umask, sys_chroot
+- .word compat_sys_newfstat, sunos_nosys, sys_getpagesize
+- .word sys_msync, sys_vfork, sunos_nosys
+- .word sunos_nosys, sunos_sbrk, sunos_sstk
+- .word sunos_mmap, sunos_vadvise, sys_munmap
+- .word sys_mprotect, sys_madvise, sys_vhangup
+- .word sunos_nosys, sys_mincore, sys32_getgroups16
+- .word sys32_setgroups16, sys_getpgrp, sunos_setpgrp
+- .word compat_sys_setitimer, sunos_nosys, sys_swapon
+- .word compat_sys_getitimer, sys_gethostname, sys_sethostname
+- .word sunos_getdtablesize, sys_dup2, sunos_nop
+- .word compat_sys_fcntl, sunos_select, sunos_nop
+- .word sys_fsync, sys32_setpriority, sys32_socket
+- .word sys32_connect, sunos_accept
+-/*100*/ .word sys_getpriority, sunos_send, sunos_recv
+- .word sunos_nosys, sys32_bind, sunos_setsockopt
+- .word sys32_listen, sunos_nosys, sunos_sigaction
+- .word sunos_sigblock, sunos_sigsetmask, sys_sigpause
+- .word sys32_sigstack, sys32_recvmsg, sys32_sendmsg
+- .word sunos_nosys, sys32_gettimeofday, compat_sys_getrusage
+- .word sunos_getsockopt, sunos_nosys, sunos_readv
+- .word sunos_writev, sys32_settimeofday, sys32_fchown16
+- .word sys_fchmod, sys32_recvfrom, sys32_setreuid16
+- .word sys32_setregid16, sys_rename, sys_truncate
+- .word sys_ftruncate, sys_flock, sunos_nosys
+- .word sys32_sendto, sys32_shutdown, sys32_socketpair
+- .word sys_mkdir, sys_rmdir, sys32_utimes
+- .word sys32_sigreturn, sunos_nosys, sys32_getpeername
+- .word sunos_gethostid, sunos_nosys, compat_sys_getrlimit
+- .word compat_sys_setrlimit, sunos_killpg, sunos_nosys
+- .word sunos_nosys, sunos_nosys
+-/*150*/ .word sys32_getsockname, sunos_nosys, sunos_nosys
+- .word sys_poll, sunos_nosys, sunos_nosys
+- .word sunos_getdirentries, compat_sys_statfs, compat_sys_fstatfs
+- .word sys_oldumount, sunos_nosys, sunos_nosys
+- .word sys_getdomainname, sys_setdomainname
+- .word sunos_nosys, sys_quotactl, sunos_nosys
+- .word sunos_nosys, sys_ustat, sunos_semsys
+- .word sunos_nosys, sunos_shmsys, sunos_audit
+- .word sunos_nosys, sunos_getdents, sys_setsid
+- .word sys_fchdir, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, compat_sys_sigpending, sunos_nosys
+- .word sys_setpgid, sunos_pathconf, sunos_fpathconf
+- .word sunos_sysconf, sunos_uname, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+-/*200*/ .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys
+-/*250*/ .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys
+-/*260*/ .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys
+-/*270*/ .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys
+-/*280*/ .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys
+-/*290*/ .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys
+-/*300*/ .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys
+-/*310*/ .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys, sunos_nosys, sunos_nosys
+- .word sunos_nosys
+-
+-#endif
+diff --git a/arch/sparc64/kernel/systbls.h b/arch/sparc64/kernel/systbls.h
+index 8a0d20a..bc9f5da 100644
+--- a/arch/sparc64/kernel/systbls.h
++++ b/arch/sparc64/kernel/systbls.h
+@@ -27,8 +27,6 @@ extern asmlinkage unsigned long sys64_mremap(unsigned long addr,
+ unsigned long new_addr);
+ extern asmlinkage unsigned long c_sys_nis_syscall(struct pt_regs *regs);
+ extern asmlinkage long sys_getdomainname(char __user *name, int len);
+-extern asmlinkage long solaris_syscall(struct pt_regs *regs);
+-extern asmlinkage long sunos_syscall(struct pt_regs *regs);
+ extern asmlinkage long sys_utrap_install(utrap_entry_t type,
+ utrap_handler_t new_p,
+ utrap_handler_t new_d,
+diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
+index 96da847..d9b8d46 100644
+--- a/arch/sparc64/kernel/traps.c
++++ b/arch/sparc64/kernel/traps.c
+@@ -2091,9 +2091,8 @@ static void user_instruction_dump(unsigned int __user *pc)
+
+ void show_stack(struct task_struct *tsk, unsigned long *_ksp)
+ {
+- unsigned long pc, fp, thread_base, ksp;
++ unsigned long fp, thread_base, ksp;
+ struct thread_info *tp;
+- struct reg_window *rw;
+ int count = 0;
+
+ ksp = (unsigned long) _ksp;
+@@ -2117,15 +2116,27 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp)
+ printk("\n");
+ #endif
+ do {
++ struct reg_window *rw;
++ struct pt_regs *regs;
++ unsigned long pc;
++
+ /* Bogus frame pointer? */
+ if (fp < (thread_base + sizeof(struct thread_info)) ||
+ fp >= (thread_base + THREAD_SIZE))
+ break;
+ rw = (struct reg_window *)fp;
+- pc = rw->ins[7];
++ regs = (struct pt_regs *) (rw + 1);
++
++ if ((regs->magic & ~0x1ff) == PT_REGS_MAGIC) {
++ pc = regs->tpc;
++ fp = regs->u_regs[UREG_I6] + STACK_BIAS;
++ } else {
++ pc = rw->ins[7];
++ fp = rw->ins[6] + STACK_BIAS;
++ }
++
+ printk(" [%016lx] ", pc);
+ print_symbol("%s\n", pc);
+- fp = rw->ins[6] + STACK_BIAS;
+ } while (++count < 16);
+ #ifndef CONFIG_KALLSYMS
+ printk("\n");
+diff --git a/arch/sparc64/kernel/tsb.S b/arch/sparc64/kernel/tsb.S
+index 10adb2f..c499214 100644
+--- a/arch/sparc64/kernel/tsb.S
++++ b/arch/sparc64/kernel/tsb.S
+@@ -275,7 +275,7 @@ sparc64_realfault_common:
+ stx %l5, [%g6 + TI_FAULT_ADDR] ! Save fault address
+ call do_sparc64_fault ! Call fault handler
+ add %sp, PTREGS_OFF, %o0 ! Compute pt_regs arg
+- ba,pt %xcc, rtrap_clr_l6 ! Restore cpu state
++ ba,pt %xcc, rtrap ! Restore cpu state
+ nop ! Delay slot (fill me)
+
+ winfix_trampoline:
+diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S
+index 7575aa3..b0de4c0 100644
+--- a/arch/sparc64/kernel/ttable.S
++++ b/arch/sparc64/kernel/ttable.S
+@@ -117,16 +117,13 @@ tl0_f4o: FILL_4_OTHER
+ tl0_f5o: FILL_5_OTHER
+ tl0_f6o: FILL_6_OTHER
+ tl0_f7o: FILL_7_OTHER
+-tl0_sunos: SUNOS_SYSCALL_TRAP
++tl0_resv100: BTRAP(0x100)
+ tl0_bkpt: BREAKPOINT_TRAP
+ tl0_divz: TRAP(do_div0)
+ tl0_flushw: FLUSH_WINDOW_TRAP
+-tl0_resv104: BTRAP(0x104) BTRAP(0x105) BTRAP(0x106) BTRAP(0x107)
+- .globl tl0_solaris
+-tl0_solaris: SOLARIS_SYSCALL_TRAP
+-tl0_resv109: BTRAP(0x109)
+-tl0_resv10a: BTRAP(0x10a) BTRAP(0x10b) BTRAP(0x10c) BTRAP(0x10d) BTRAP(0x10e)
+-tl0_resv10f: BTRAP(0x10f)
++tl0_resv104: BTRAP(0x104) BTRAP(0x105) BTRAP(0x106) BTRAP(0x107) BTRAP(0x108)
++tl0_resv109: BTRAP(0x109) BTRAP(0x10a) BTRAP(0x10b) BTRAP(0x10c) BTRAP(0x10d)
++tl0_resv10e: BTRAP(0x10e) BTRAP(0x10f)
+ tl0_linux32: LINUX_32BIT_SYSCALL_TRAP
+ tl0_oldlinux64: LINUX_64BIT_SYSCALL_TRAP
+ tl0_resv112: TRAP_UTRAP(UT_TRAP_INSTRUCTION_18,0x112) TRAP_UTRAP(UT_TRAP_INSTRUCTION_19,0x113)
+@@ -139,8 +136,7 @@ tl0_resv11e: TRAP_UTRAP(UT_TRAP_INSTRUCTION_30,0x11e) TRAP_UTRAP(UT_TRAP_INSTRUC
+ tl0_getcc: GETCC_TRAP
+ tl0_setcc: SETCC_TRAP
+ tl0_getpsr: TRAP(do_getpsr)
+-tl0_resv123: BTRAP(0x123) BTRAP(0x124) BTRAP(0x125) BTRAP(0x126)
+-tl0_solindir: INDIRECT_SOLARIS_SYSCALL(156)
++tl0_resv123: BTRAP(0x123) BTRAP(0x124) BTRAP(0x125) BTRAP(0x126) BTRAP(0x127)
+ tl0_resv128: BTRAP(0x128) BTRAP(0x129) BTRAP(0x12a) BTRAP(0x12b) BTRAP(0x12c)
+ tl0_resv12d: BTRAP(0x12d) BTRAP(0x12e) BTRAP(0x12f) BTRAP(0x130) BTRAP(0x131)
+ tl0_resv132: BTRAP(0x132) BTRAP(0x133) BTRAP(0x134) BTRAP(0x135) BTRAP(0x136)
+diff --git a/arch/sparc64/kernel/winfixup.S b/arch/sparc64/kernel/winfixup.S
+index c4aa110..a6b0863 100644
+--- a/arch/sparc64/kernel/winfixup.S
++++ b/arch/sparc64/kernel/winfixup.S
+@@ -32,7 +32,7 @@ fill_fixup:
+ rd %pc, %g7
+ call do_sparc64_fault
+ add %sp, PTREGS_OFF, %o0
+- ba,pt %xcc, rtrap_clr_l6
++ ba,pt %xcc, rtrap
+ nop
+
+ /* Be very careful about usage of the trap globals here.
+@@ -100,7 +100,7 @@ spill_fixup_dax:
+ rd %pc, %g7
+ call do_sparc64_fault
+ add %sp, PTREGS_OFF, %o0
+- ba,a,pt %xcc, rtrap_clr_l6
++ ba,a,pt %xcc, rtrap
+
+ winfix_mna:
+ andn %g3, 0x7f, %g3
+@@ -122,12 +122,12 @@ fill_fixup_mna:
+ mov %l4, %o2
+ call sun4v_do_mna
+ mov %l5, %o1
+- ba,a,pt %xcc, rtrap_clr_l6
++ ba,a,pt %xcc, rtrap
+ 1: mov %l4, %o1
+ mov %l5, %o2
+ call mem_address_unaligned
+ nop
+- ba,a,pt %xcc, rtrap_clr_l6
++ ba,a,pt %xcc, rtrap
+
+ winfix_dax:
+ andn %g3, 0x7f, %g3
+@@ -150,7 +150,7 @@ fill_fixup_dax:
+ add %sp, PTREGS_OFF, %o0
+ call sun4v_data_access_exception
+ nop
+- ba,a,pt %xcc, rtrap_clr_l6
++ ba,a,pt %xcc, rtrap
+ 1: call spitfire_data_access_exception
+ nop
+- ba,a,pt %xcc, rtrap_clr_l6
++ ba,a,pt %xcc, rtrap
+diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
+index f37078d..177d8aa 100644
+--- a/arch/sparc64/mm/init.c
++++ b/arch/sparc64/mm/init.c
+@@ -24,6 +24,8 @@
+ #include <linux/cache.h>
+ #include <linux/sort.h>
+ #include <linux/percpu.h>
++#include <linux/lmb.h>
++#include <linux/mmzone.h>
+
+ #include <asm/head.h>
+ #include <asm/system.h>
+@@ -72,9 +74,7 @@ extern struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES];
+ #define MAX_BANKS 32
+
+ static struct linux_prom64_registers pavail[MAX_BANKS] __initdata;
+-static struct linux_prom64_registers pavail_rescan[MAX_BANKS] __initdata;
+ static int pavail_ents __initdata;
+-static int pavail_rescan_ents __initdata;
+
+ static int cmp_p64(const void *a, const void *b)
+ {
+@@ -715,285 +715,684 @@ out:
+ smp_new_mmu_context_version();
+ }
+
+-/* Find a free area for the bootmem map, avoiding the kernel image
+- * and the initial ramdisk.
+- */
+-static unsigned long __init choose_bootmap_pfn(unsigned long start_pfn,
+- unsigned long end_pfn)
++static int numa_enabled = 1;
++static int numa_debug;
++
++static int __init early_numa(char *p)
+ {
+- unsigned long avoid_start, avoid_end, bootmap_size;
+- int i;
++ if (!p)
++ return 0;
++
++ if (strstr(p, "off"))
++ numa_enabled = 0;
++
++ if (strstr(p, "debug"))
++ numa_debug = 1;
++
++ return 0;
++}
++early_param("numa", early_numa);
+
+- bootmap_size = bootmem_bootmap_pages(end_pfn - start_pfn);
+- bootmap_size <<= PAGE_SHIFT;
++#define numadbg(f, a...) \
++do { if (numa_debug) \
++ printk(KERN_INFO f, ## a); \
++} while (0)
+
+- avoid_start = avoid_end = 0;
++static void __init find_ramdisk(unsigned long phys_base)
++{
+ #ifdef CONFIG_BLK_DEV_INITRD
+- avoid_start = initrd_start;
+- avoid_end = PAGE_ALIGN(initrd_end);
++ if (sparc_ramdisk_image || sparc_ramdisk_image64) {
++ unsigned long ramdisk_image;
++
++ /* Older versions of the bootloader only supported a
++ * 32-bit physical address for the ramdisk image
++ * location, stored at sparc_ramdisk_image. Newer
++ * SILO versions set sparc_ramdisk_image to zero and
++ * provide a full 64-bit physical address at
++ * sparc_ramdisk_image64.
++ */
++ ramdisk_image = sparc_ramdisk_image;
++ if (!ramdisk_image)
++ ramdisk_image = sparc_ramdisk_image64;
++
++ /* Another bootloader quirk. The bootloader normalizes
++ * the physical address to KERNBASE, so we have to
++ * factor that back out and add in the lowest valid
++ * physical page address to get the true physical address.
++ */
++ ramdisk_image -= KERNBASE;
++ ramdisk_image += phys_base;
++
++ numadbg("Found ramdisk at physical address 0x%lx, size %u\n",
++ ramdisk_image, sparc_ramdisk_size);
++
++ initrd_start = ramdisk_image;
++ initrd_end = ramdisk_image + sparc_ramdisk_size;
++
++ lmb_reserve(initrd_start, initrd_end);
++ }
+ #endif
++}
+
+- for (i = 0; i < pavail_ents; i++) {
+- unsigned long start, end;
++struct node_mem_mask {
++ unsigned long mask;
++ unsigned long val;
++ unsigned long bootmem_paddr;
++};
++static struct node_mem_mask node_masks[MAX_NUMNODES];
++static int num_node_masks;
+
+- start = pavail[i].phys_addr;
+- end = start + pavail[i].reg_size;
++int numa_cpu_lookup_table[NR_CPUS];
++cpumask_t numa_cpumask_lookup_table[MAX_NUMNODES];
+
+- while (start < end) {
+- if (start >= kern_base &&
+- start < PAGE_ALIGN(kern_base + kern_size)) {
+- start = PAGE_ALIGN(kern_base + kern_size);
+- continue;
+- }
+- if (start >= avoid_start && start < avoid_end) {
+- start = avoid_end;
+- continue;
+- }
++#ifdef CONFIG_NEED_MULTIPLE_NODES
++static bootmem_data_t plat_node_bdata[MAX_NUMNODES];
+
+- if ((end - start) < bootmap_size)
+- break;
++struct mdesc_mblock {
++ u64 base;
++ u64 size;
++ u64 offset; /* RA-to-PA */
++};
++static struct mdesc_mblock *mblocks;
++static int num_mblocks;
+
+- if (start < kern_base &&
+- (start + bootmap_size) > kern_base) {
+- start = PAGE_ALIGN(kern_base + kern_size);
+- continue;
+- }
++static unsigned long ra_to_pa(unsigned long addr)
++{
++ int i;
+
+- if (start < avoid_start &&
+- (start + bootmap_size) > avoid_start) {
+- start = avoid_end;
+- continue;
+- }
++ for (i = 0; i < num_mblocks; i++) {
++ struct mdesc_mblock *m = &mblocks[i];
+
+- /* OK, it doesn't overlap anything, use it. */
+- return start >> PAGE_SHIFT;
++ if (addr >= m->base &&
++ addr < (m->base + m->size)) {
++ addr += m->offset;
++ break;
+ }
+ }
+-
+- prom_printf("Cannot find free area for bootmap, aborting.\n");
+- prom_halt();
++ return addr;
+ }
+
+-static void __init trim_pavail(unsigned long *cur_size_p,
+- unsigned long *end_of_phys_p)
++static int find_node(unsigned long addr)
+ {
+- unsigned long to_trim = *cur_size_p - cmdline_memory_size;
+- unsigned long avoid_start, avoid_end;
+ int i;
+
+- to_trim = PAGE_ALIGN(to_trim);
++ addr = ra_to_pa(addr);
++ for (i = 0; i < num_node_masks; i++) {
++ struct node_mem_mask *p = &node_masks[i];
+
+- avoid_start = avoid_end = 0;
+-#ifdef CONFIG_BLK_DEV_INITRD
+- avoid_start = initrd_start;
+- avoid_end = PAGE_ALIGN(initrd_end);
++ if ((addr & p->mask) == p->val)
++ return i;
++ }
++ return -1;
++}
++
++static unsigned long nid_range(unsigned long start, unsigned long end,
++ int *nid)
++{
++ *nid = find_node(start);
++ start += PAGE_SIZE;
++ while (start < end) {
++ int n = find_node(start);
++
++ if (n != *nid)
++ break;
++ start += PAGE_SIZE;
++ }
++
++ return start;
++}
++#else
++static unsigned long nid_range(unsigned long start, unsigned long end,
++ int *nid)
++{
++ *nid = 0;
++ return end;
++}
+ #endif
+
+- /* Trim some pavail[] entries in order to satisfy the
+- * requested "mem=xxx" kernel command line specification.
+- *
+- * We must not trim off the kernel image area nor the
+- * initial ramdisk range (if any). Also, we must not trim
+- * any pavail[] entry down to zero in order to preserve
+- * the invariant that all pavail[] entries have a non-zero
+- * size which is assumed by all of the code in here.
+- */
+- for (i = 0; i < pavail_ents; i++) {
+- unsigned long start, end, kern_end;
+- unsigned long trim_low, trim_high, n;
++/* This must be invoked after performing all of the necessary
++ * add_active_range() calls for 'nid'. We need to be able to get
++ * correct data from get_pfn_range_for_nid().
++ */
++static void __init allocate_node_data(int nid)
++{
++ unsigned long paddr, num_pages, start_pfn, end_pfn;
++ struct pglist_data *p;
++
++#ifdef CONFIG_NEED_MULTIPLE_NODES
++ paddr = lmb_alloc_nid(sizeof(struct pglist_data),
++ SMP_CACHE_BYTES, nid, nid_range);
++ if (!paddr) {
++ prom_printf("Cannot allocate pglist_data for nid[%d]\n", nid);
++ prom_halt();
++ }
++ NODE_DATA(nid) = __va(paddr);
++ memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
+
+- kern_end = PAGE_ALIGN(kern_base + kern_size);
++ NODE_DATA(nid)->bdata = &plat_node_bdata[nid];
++#endif
+
+- trim_low = start = pavail[i].phys_addr;
+- trim_high = end = start + pavail[i].reg_size;
++ p = NODE_DATA(nid);
+
+- if (kern_base >= start &&
+- kern_base < end) {
+- trim_low = kern_base;
+- if (kern_end >= end)
+- continue;
+- }
+- if (kern_end >= start &&
+- kern_end < end) {
+- trim_high = kern_end;
+- }
+- if (avoid_start &&
+- avoid_start >= start &&
+- avoid_start < end) {
+- if (trim_low > avoid_start)
+- trim_low = avoid_start;
+- if (avoid_end >= end)
+- continue;
+- }
+- if (avoid_end &&
+- avoid_end >= start &&
+- avoid_end < end) {
+- if (trim_high < avoid_end)
+- trim_high = avoid_end;
++ get_pfn_range_for_nid(nid, &start_pfn, &end_pfn);
++ p->node_start_pfn = start_pfn;
++ p->node_spanned_pages = end_pfn - start_pfn;
++
++ if (p->node_spanned_pages) {
++ num_pages = bootmem_bootmap_pages(p->node_spanned_pages);
++
++ paddr = lmb_alloc_nid(num_pages << PAGE_SHIFT, PAGE_SIZE, nid,
++ nid_range);
++ if (!paddr) {
++ prom_printf("Cannot allocate bootmap for nid[%d]\n",
++ nid);
++ prom_halt();
+ }
++ node_masks[nid].bootmem_paddr = paddr;
++ }
++}
++
++static void init_node_masks_nonnuma(void)
++{
++ int i;
++
++ numadbg("Initializing tables for non-numa.\n");
++
++ node_masks[0].mask = node_masks[0].val = 0;
++ num_node_masks = 1;
++
++ for (i = 0; i < NR_CPUS; i++)
++ numa_cpu_lookup_table[i] = 0;
++
++ numa_cpumask_lookup_table[0] = CPU_MASK_ALL;
++}
++
++#ifdef CONFIG_NEED_MULTIPLE_NODES
++struct pglist_data *node_data[MAX_NUMNODES];
++
++EXPORT_SYMBOL(numa_cpu_lookup_table);
++EXPORT_SYMBOL(numa_cpumask_lookup_table);
++EXPORT_SYMBOL(node_data);
++
++struct mdesc_mlgroup {
++ u64 node;
++ u64 latency;
++ u64 match;
++ u64 mask;
++};
++static struct mdesc_mlgroup *mlgroups;
++static int num_mlgroups;
++
++static int scan_pio_for_cfg_handle(struct mdesc_handle *md, u64 pio,
++ u32 cfg_handle)
++{
++ u64 arc;
+
+- if (trim_high <= trim_low)
++ mdesc_for_each_arc(arc, md, pio, MDESC_ARC_TYPE_FWD) {
++ u64 target = mdesc_arc_target(md, arc);
++ const u64 *val;
++
++ val = mdesc_get_property(md, target,
++ "cfg-handle", NULL);
++ if (val && *val == cfg_handle)
++ return 0;
++ }
++ return -ENODEV;
++}
++
++static int scan_arcs_for_cfg_handle(struct mdesc_handle *md, u64 grp,
++ u32 cfg_handle)
++{
++ u64 arc, candidate, best_latency = ~(u64)0;
++
++ candidate = MDESC_NODE_NULL;
++ mdesc_for_each_arc(arc, md, grp, MDESC_ARC_TYPE_FWD) {
++ u64 target = mdesc_arc_target(md, arc);
++ const char *name = mdesc_node_name(md, target);
++ const u64 *val;
++
++ if (strcmp(name, "pio-latency-group"))
+ continue;
+
+- if (trim_low == start && trim_high == end) {
+- /* Whole chunk is available for trimming.
+- * Trim all except one page, in order to keep
+- * entry non-empty.
+- */
+- n = (end - start) - PAGE_SIZE;
+- if (n > to_trim)
+- n = to_trim;
+-
+- if (n) {
+- pavail[i].phys_addr += n;
+- pavail[i].reg_size -= n;
+- to_trim -= n;
+- }
+- } else {
+- n = (trim_low - start);
+- if (n > to_trim)
+- n = to_trim;
+-
+- if (n) {
+- pavail[i].phys_addr += n;
+- pavail[i].reg_size -= n;
+- to_trim -= n;
+- }
+- if (to_trim) {
+- n = end - trim_high;
+- if (n > to_trim)
+- n = to_trim;
+- if (n) {
+- pavail[i].reg_size -= n;
+- to_trim -= n;
+- }
+- }
++ val = mdesc_get_property(md, target, "latency", NULL);
++ if (!val)
++ continue;
++
++ if (*val < best_latency) {
++ candidate = target;
++ best_latency = *val;
+ }
++ }
++
++ if (candidate == MDESC_NODE_NULL)
++ return -ENODEV;
++
++ return scan_pio_for_cfg_handle(md, candidate, cfg_handle);
++}
++
++int of_node_to_nid(struct device_node *dp)
++{
++ const struct linux_prom64_registers *regs;
++ struct mdesc_handle *md;
++ u32 cfg_handle;
++ int count, nid;
++ u64 grp;
+
+- if (!to_trim)
++ if (!mlgroups)
++ return -1;
++
++ regs = of_get_property(dp, "reg", NULL);
++ if (!regs)
++ return -1;
++
++ cfg_handle = (regs->phys_addr >> 32UL) & 0x0fffffff;
++
++ md = mdesc_grab();
++
++ count = 0;
++ nid = -1;
++ mdesc_for_each_node_by_name(md, grp, "group") {
++ if (!scan_arcs_for_cfg_handle(md, grp, cfg_handle)) {
++ nid = count;
+ break;
++ }
++ count++;
+ }
+
+- /* Recalculate. */
+- *cur_size_p = 0UL;
+- for (i = 0; i < pavail_ents; i++) {
+- *end_of_phys_p = pavail[i].phys_addr +
+- pavail[i].reg_size;
+- *cur_size_p += pavail[i].reg_size;
+- }
++ mdesc_release(md);
++
++ return nid;
+ }
+
+-/* About pages_avail, this is the value we will use to calculate
+- * the zholes_size[] argument given to free_area_init_node(). The
+- * page allocator uses this to calculate nr_kernel_pages,
+- * nr_all_pages and zone->present_pages. On NUMA it is used
+- * to calculate zone->min_unmapped_pages and zone->min_slab_pages.
+- *
+- * So this number should really be set to what the page allocator
+- * actually ends up with. This means:
+- * 1) It should include bootmem map pages, we'll release those.
+- * 2) It should not include the kernel image, except for the
+- * __init sections which we will also release.
+- * 3) It should include the initrd image, since we'll release
+- * that too.
+- */
+-static unsigned long __init bootmem_init(unsigned long *pages_avail,
+- unsigned long phys_base)
++static void add_node_ranges(void)
+ {
+- unsigned long bootmap_size, end_pfn;
+- unsigned long end_of_phys_memory = 0UL;
+- unsigned long bootmap_pfn, bytes_avail, size;
+ int i;
+
+- bytes_avail = 0UL;
+- for (i = 0; i < pavail_ents; i++) {
+- end_of_phys_memory = pavail[i].phys_addr +
+- pavail[i].reg_size;
+- bytes_avail += pavail[i].reg_size;
++ for (i = 0; i < lmb.memory.cnt; i++) {
++ unsigned long size = lmb_size_bytes(&lmb.memory, i);
++ unsigned long start, end;
++
++ start = lmb.memory.region[i].base;
++ end = start + size;
++ while (start < end) {
++ unsigned long this_end;
++ int nid;
++
++ this_end = nid_range(start, end, &nid);
++
++ numadbg("Adding active range nid[%d] "
++ "start[%lx] end[%lx]\n",
++ nid, start, this_end);
++
++ add_active_range(nid,
++ start >> PAGE_SHIFT,
++ this_end >> PAGE_SHIFT);
++
++ start = this_end;
++ }
+ }
++}
+
+- /* Determine the location of the initial ramdisk before trying
+- * to honor the "mem=xxx" command line argument. We must know
+- * where the kernel image and the ramdisk image are so that we
+- * do not trim those two areas from the physical memory map.
+- */
++static int __init grab_mlgroups(struct mdesc_handle *md)
++{
++ unsigned long paddr;
++ int count = 0;
++ u64 node;
++
++ mdesc_for_each_node_by_name(md, node, "memory-latency-group")
++ count++;
++ if (!count)
++ return -ENOENT;
++
++ paddr = lmb_alloc(count * sizeof(struct mdesc_mlgroup),
++ SMP_CACHE_BYTES);
++ if (!paddr)
++ return -ENOMEM;
++
++ mlgroups = __va(paddr);
++ num_mlgroups = count;
++
++ count = 0;
++ mdesc_for_each_node_by_name(md, node, "memory-latency-group") {
++ struct mdesc_mlgroup *m = &mlgroups[count++];
++ const u64 *val;
++
++ m->node = node;
++
++ val = mdesc_get_property(md, node, "latency", NULL);
++ m->latency = *val;
++ val = mdesc_get_property(md, node, "address-match", NULL);
++ m->match = *val;
++ val = mdesc_get_property(md, node, "address-mask", NULL);
++ m->mask = *val;
++
++ numadbg("MLGROUP[%d]: node[%lx] latency[%lx] "
++ "match[%lx] mask[%lx]\n",
++ count - 1, m->node, m->latency, m->match, m->mask);
++ }
+
+-#ifdef CONFIG_BLK_DEV_INITRD
+- /* Now have to check initial ramdisk, so that bootmap does not overwrite it */
+- if (sparc_ramdisk_image || sparc_ramdisk_image64) {
+- unsigned long ramdisk_image = sparc_ramdisk_image ?
+- sparc_ramdisk_image : sparc_ramdisk_image64;
+- ramdisk_image -= KERNBASE;
+- initrd_start = ramdisk_image + phys_base;
+- initrd_end = initrd_start + sparc_ramdisk_size;
+- if (initrd_end > end_of_phys_memory) {
+- printk(KERN_CRIT "initrd extends beyond end of memory "
+- "(0x%016lx > 0x%016lx)\ndisabling initrd\n",
+- initrd_end, end_of_phys_memory);
+- initrd_start = 0;
+- initrd_end = 0;
++ return 0;
++}
++
++static int __init grab_mblocks(struct mdesc_handle *md)
++{
++ unsigned long paddr;
++ int count = 0;
++ u64 node;
++
++ mdesc_for_each_node_by_name(md, node, "mblock")
++ count++;
++ if (!count)
++ return -ENOENT;
++
++ paddr = lmb_alloc(count * sizeof(struct mdesc_mblock),
++ SMP_CACHE_BYTES);
++ if (!paddr)
++ return -ENOMEM;
++
++ mblocks = __va(paddr);
++ num_mblocks = count;
++
++ count = 0;
++ mdesc_for_each_node_by_name(md, node, "mblock") {
++ struct mdesc_mblock *m = &mblocks[count++];
++ const u64 *val;
++
++ val = mdesc_get_property(md, node, "base", NULL);
++ m->base = *val;
++ val = mdesc_get_property(md, node, "size", NULL);
++ m->size = *val;
++ val = mdesc_get_property(md, node,
++ "address-congruence-offset", NULL);
++ m->offset = *val;
++
++ numadbg("MBLOCK[%d]: base[%lx] size[%lx] offset[%lx]\n",
++ count - 1, m->base, m->size, m->offset);
++ }
++
++ return 0;
++}
++
++static void __init numa_parse_mdesc_group_cpus(struct mdesc_handle *md,
++ u64 grp, cpumask_t *mask)
++{
++ u64 arc;
++
++ cpus_clear(*mask);
++
++ mdesc_for_each_arc(arc, md, grp, MDESC_ARC_TYPE_BACK) {
++ u64 target = mdesc_arc_target(md, arc);
++ const char *name = mdesc_node_name(md, target);
++ const u64 *id;
++
++ if (strcmp(name, "cpu"))
++ continue;
++ id = mdesc_get_property(md, target, "id", NULL);
++ if (*id < NR_CPUS)
++ cpu_set(*id, *mask);
++ }
++}
++
++static struct mdesc_mlgroup * __init find_mlgroup(u64 node)
++{
++ int i;
++
++ for (i = 0; i < num_mlgroups; i++) {
++ struct mdesc_mlgroup *m = &mlgroups[i];
++ if (m->node == node)
++ return m;
++ }
++ return NULL;
++}
++
++static int __init numa_attach_mlgroup(struct mdesc_handle *md, u64 grp,
++ int index)
++{
++ struct mdesc_mlgroup *candidate = NULL;
++ u64 arc, best_latency = ~(u64)0;
++ struct node_mem_mask *n;
++
++ mdesc_for_each_arc(arc, md, grp, MDESC_ARC_TYPE_FWD) {
++ u64 target = mdesc_arc_target(md, arc);
++ struct mdesc_mlgroup *m = find_mlgroup(target);
++ if (!m)
++ continue;
++ if (m->latency < best_latency) {
++ candidate = m;
++ best_latency = m->latency;
+ }
+ }
+-#endif
++ if (!candidate)
++ return -ENOENT;
++
++ if (num_node_masks != index) {
++ printk(KERN_ERR "Inconsistent NUMA state, "
++ "index[%d] != num_node_masks[%d]\n",
++ index, num_node_masks);
++ return -EINVAL;
++ }
+
+- if (cmdline_memory_size &&
+- bytes_avail > cmdline_memory_size)
+- trim_pavail(&bytes_avail,
+- &end_of_phys_memory);
++ n = &node_masks[num_node_masks++];
+
+- *pages_avail = bytes_avail >> PAGE_SHIFT;
++ n->mask = candidate->mask;
++ n->val = candidate->match;
+
+- end_pfn = end_of_phys_memory >> PAGE_SHIFT;
++ numadbg("NUMA NODE[%d]: mask[%lx] val[%lx] (latency[%lx])\n",
++ index, n->mask, n->val, candidate->latency);
+
+- /* Initialize the boot-time allocator. */
+- max_pfn = max_low_pfn = end_pfn;
+- min_low_pfn = (phys_base >> PAGE_SHIFT);
++ return 0;
++}
++
++static int __init numa_parse_mdesc_group(struct mdesc_handle *md, u64 grp,
++ int index)
++{
++ cpumask_t mask;
++ int cpu;
+
+- bootmap_pfn = choose_bootmap_pfn(min_low_pfn, end_pfn);
++ numa_parse_mdesc_group_cpus(md, grp, &mask);
+
+- bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn,
+- min_low_pfn, end_pfn);
++ for_each_cpu_mask(cpu, mask)
++ numa_cpu_lookup_table[cpu] = index;
++ numa_cpumask_lookup_table[index] = mask;
+
+- /* Now register the available physical memory with the
+- * allocator.
+- */
+- for (i = 0; i < pavail_ents; i++)
+- free_bootmem(pavail[i].phys_addr, pavail[i].reg_size);
++ if (numa_debug) {
++ printk(KERN_INFO "NUMA GROUP[%d]: cpus [ ", index);
++ for_each_cpu_mask(cpu, mask)
++ printk("%d ", cpu);
++ printk("]\n");
++ }
+
+-#ifdef CONFIG_BLK_DEV_INITRD
+- if (initrd_start) {
+- size = initrd_end - initrd_start;
++ return numa_attach_mlgroup(md, grp, index);
++}
++
++static int __init numa_parse_mdesc(void)
++{
++ struct mdesc_handle *md = mdesc_grab();
++ int i, err, count;
++ u64 node;
++
++ node = mdesc_node_by_name(md, MDESC_NODE_NULL, "latency-groups");
++ if (node == MDESC_NODE_NULL) {
++ mdesc_release(md);
++ return -ENOENT;
++ }
++
++ err = grab_mblocks(md);
++ if (err < 0)
++ goto out;
++
++ err = grab_mlgroups(md);
++ if (err < 0)
++ goto out;
++
++ count = 0;
++ mdesc_for_each_node_by_name(md, node, "group") {
++ err = numa_parse_mdesc_group(md, node, count);
++ if (err < 0)
++ break;
++ count++;
++ }
++
++ add_node_ranges();
++
++ for (i = 0; i < num_node_masks; i++) {
++ allocate_node_data(i);
++ node_set_online(i);
++ }
++
++ err = 0;
++out:
++ mdesc_release(md);
++ return err;
++}
++
++static int __init numa_parse_sun4u(void)
++{
++ return -1;
++}
+
+- /* Reserve the initrd image area. */
+- reserve_bootmem(initrd_start, size, BOOTMEM_DEFAULT);
++static int __init bootmem_init_numa(void)
++{
++ int err = -1;
+
+- initrd_start += PAGE_OFFSET;
+- initrd_end += PAGE_OFFSET;
++ numadbg("bootmem_init_numa()\n");
++
++ if (numa_enabled) {
++ if (tlb_type == hypervisor)
++ err = numa_parse_mdesc();
++ else
++ err = numa_parse_sun4u();
+ }
++ return err;
++}
++
++#else
++
++static int bootmem_init_numa(void)
++{
++ return -1;
++}
++
+ #endif
+- /* Reserve the kernel text/data/bss. */
+- reserve_bootmem(kern_base, kern_size, BOOTMEM_DEFAULT);
+- *pages_avail -= PAGE_ALIGN(kern_size) >> PAGE_SHIFT;
+-
+- /* Add back in the initmem pages. */
+- size = ((unsigned long)(__init_end) & PAGE_MASK) -
+- PAGE_ALIGN((unsigned long)__init_begin);
+- *pages_avail += size >> PAGE_SHIFT;
+-
+- /* Reserve the bootmem map. We do not account for it
+- * in pages_avail because we will release that memory
+- * in free_all_bootmem.
+- */
+- size = bootmap_size;
+- reserve_bootmem((bootmap_pfn << PAGE_SHIFT), size, BOOTMEM_DEFAULT);
+
+- for (i = 0; i < pavail_ents; i++) {
++static void __init bootmem_init_nonnuma(void)
++{
++ unsigned long top_of_ram = lmb_end_of_DRAM();
++ unsigned long total_ram = lmb_phys_mem_size();
++ unsigned int i;
++
++ numadbg("bootmem_init_nonnuma()\n");
++
++ printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
++ top_of_ram, total_ram);
++ printk(KERN_INFO "Memory hole size: %ldMB\n",
++ (top_of_ram - total_ram) >> 20);
++
++ init_node_masks_nonnuma();
++
++ for (i = 0; i < lmb.memory.cnt; i++) {
++ unsigned long size = lmb_size_bytes(&lmb.memory, i);
+ unsigned long start_pfn, end_pfn;
+
+- start_pfn = pavail[i].phys_addr >> PAGE_SHIFT;
+- end_pfn = (start_pfn + (pavail[i].reg_size >> PAGE_SHIFT));
+- memory_present(0, start_pfn, end_pfn);
++ if (!size)
++ continue;
++
++ start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT;
++ end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i);
++ add_active_range(0, start_pfn, end_pfn);
++ }
++
++ allocate_node_data(0);
++
++ node_set_online(0);
++}
++
++static void __init reserve_range_in_node(int nid, unsigned long start,
++ unsigned long end)
++{
++ numadbg(" reserve_range_in_node(nid[%d],start[%lx],end[%lx]\n",
++ nid, start, end);
++ while (start < end) {
++ unsigned long this_end;
++ int n;
++
++ this_end = nid_range(start, end, &n);
++ if (n == nid) {
++ numadbg(" MATCH reserving range [%lx:%lx]\n",
++ start, this_end);
++ reserve_bootmem_node(NODE_DATA(nid), start,
++ (this_end - start), BOOTMEM_DEFAULT);
++ } else
++ numadbg(" NO MATCH, advancing start to %lx\n",
++ this_end);
++
++ start = this_end;
++ }
++}
++
++static void __init trim_reserved_in_node(int nid)
++{
++ int i;
++
++ numadbg(" trim_reserved_in_node(%d)\n", nid);
++
++ for (i = 0; i < lmb.reserved.cnt; i++) {
++ unsigned long start = lmb.reserved.region[i].base;
++ unsigned long size = lmb_size_bytes(&lmb.reserved, i);
++ unsigned long end = start + size;
++
++ reserve_range_in_node(nid, start, end);
++ }
++}
++
++static void __init bootmem_init_one_node(int nid)
++{
++ struct pglist_data *p;
++
++ numadbg("bootmem_init_one_node(%d)\n", nid);
++
++ p = NODE_DATA(nid);
++
++ if (p->node_spanned_pages) {
++ unsigned long paddr = node_masks[nid].bootmem_paddr;
++ unsigned long end_pfn;
++
++ end_pfn = p->node_start_pfn + p->node_spanned_pages;
++
++ numadbg(" init_bootmem_node(%d, %lx, %lx, %lx)\n",
++ nid, paddr >> PAGE_SHIFT, p->node_start_pfn, end_pfn);
++
++ init_bootmem_node(p, paddr >> PAGE_SHIFT,
++ p->node_start_pfn, end_pfn);
++
++ numadbg(" free_bootmem_with_active_regions(%d, %lx)\n",
++ nid, end_pfn);
++ free_bootmem_with_active_regions(nid, end_pfn);
++
++ trim_reserved_in_node(nid);
++
++ numadbg(" sparse_memory_present_with_active_regions(%d)\n",
++ nid);
++ sparse_memory_present_with_active_regions(nid);
+ }
++}
++
++static unsigned long __init bootmem_init(unsigned long phys_base)
++{
++ unsigned long end_pfn;
++ int nid;
++
++ end_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT;
++ max_pfn = max_low_pfn = end_pfn;
++ min_low_pfn = (phys_base >> PAGE_SHIFT);
++
++ if (bootmem_init_numa() < 0)
++ bootmem_init_nonnuma();
++
++ /* XXX cpu notifier XXX */
++
++ for_each_online_node(nid)
++ bootmem_init_one_node(nid);
+
+ sparse_init();
+
+@@ -1289,7 +1688,7 @@ void __init setup_per_cpu_areas(void)
+
+ void __init paging_init(void)
+ {
+- unsigned long end_pfn, pages_avail, shift, phys_base;
++ unsigned long end_pfn, shift, phys_base;
+ unsigned long real_end, i;
+
+ /* These build time checkes make sure that the dcache_dirty_cpu()
+@@ -1330,12 +1729,26 @@ void __init paging_init(void)
+ sun4v_ktsb_init();
+ }
+
++ lmb_init();
++
+ /* Find available physical memory... */
+ read_obp_memory("available", &pavail[0], &pavail_ents);
+
+ phys_base = 0xffffffffffffffffUL;
+- for (i = 0; i < pavail_ents; i++)
++ for (i = 0; i < pavail_ents; i++) {
+ phys_base = min(phys_base, pavail[i].phys_addr);
++ lmb_add(pavail[i].phys_addr, pavail[i].reg_size);
++ }
++
++ lmb_reserve(kern_base, kern_size);
++
++ find_ramdisk(phys_base);
++
++ if (cmdline_memory_size)
++ lmb_enforce_memory_limit(phys_base + cmdline_memory_size);
++
++ lmb_analyze();
++ lmb_dump_all();
+
+ set_bit(0, mmu_context_bmap);
+
+@@ -1371,14 +1784,10 @@ void __init paging_init(void)
+ if (tlb_type == hypervisor)
+ sun4v_ktsb_register();
+
+- /* Setup bootmem... */
+- pages_avail = 0;
+- last_valid_pfn = end_pfn = bootmem_init(&pages_avail, phys_base);
+-
+- max_mapnr = last_valid_pfn;
+-
+- kernel_physical_mapping_init();
+-
++ /* We must setup the per-cpu areas before we pull in the
++ * PROM and the MDESC. The code there fills in cpu and
++ * other information into per-cpu data structures.
++ */
+ real_setup_per_cpu_areas();
+
+ prom_build_devicetree();
+@@ -1386,20 +1795,22 @@ void __init paging_init(void)
+ if (tlb_type == hypervisor)
+ sun4v_mdesc_init();
+
++ /* Setup bootmem... */
++ last_valid_pfn = end_pfn = bootmem_init(phys_base);
++
++#ifndef CONFIG_NEED_MULTIPLE_NODES
++ max_mapnr = last_valid_pfn;
++#endif
++ kernel_physical_mapping_init();
++
+ {
+- unsigned long zones_size[MAX_NR_ZONES];
+- unsigned long zholes_size[MAX_NR_ZONES];
+- int znum;
++ unsigned long max_zone_pfns[MAX_NR_ZONES];
+
+- for (znum = 0; znum < MAX_NR_ZONES; znum++)
+- zones_size[znum] = zholes_size[znum] = 0;
++ memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+
+- zones_size[ZONE_NORMAL] = end_pfn;
+- zholes_size[ZONE_NORMAL] = end_pfn - pages_avail;
++ max_zone_pfns[ZONE_NORMAL] = end_pfn;
+
+- free_area_init_node(0, &contig_page_data, zones_size,
+- __pa(PAGE_OFFSET) >> PAGE_SHIFT,
+- zholes_size);
++ free_area_init_nodes(max_zone_pfns);
+ }
+
+ printk("Booting Linux...\n");
+@@ -1408,21 +1819,52 @@ void __init paging_init(void)
+ cpu_probe();
+ }
+
+-static void __init taint_real_pages(void)
++int __init page_in_phys_avail(unsigned long paddr)
++{
++ int i;
++
++ paddr &= PAGE_MASK;
++
++ for (i = 0; i < pavail_ents; i++) {
++ unsigned long start, end;
++
++ start = pavail[i].phys_addr;
++ end = start + pavail[i].reg_size;
++
++ if (paddr >= start && paddr < end)
++ return 1;
++ }
++ if (paddr >= kern_base && paddr < (kern_base + kern_size))
++ return 1;
++#ifdef CONFIG_BLK_DEV_INITRD
++ if (paddr >= __pa(initrd_start) &&
++ paddr < __pa(PAGE_ALIGN(initrd_end)))
++ return 1;
++#endif
++
++ return 0;
++}
++
++static struct linux_prom64_registers pavail_rescan[MAX_BANKS] __initdata;
++static int pavail_rescan_ents __initdata;
++
++/* Certain OBP calls, such as fetching "available" properties, can
++ * claim physical memory. So, along with initializing the valid
++ * address bitmap, what we do here is refetch the physical available
++ * memory list again, and make sure it provides at least as much
++ * memory as 'pavail' does.
++ */
++static void setup_valid_addr_bitmap_from_pavail(void)
+ {
+ int i;
+
+ read_obp_memory("available", &pavail_rescan[0], &pavail_rescan_ents);
+
+- /* Find changes discovered in the physmem available rescan and
+- * reserve the lost portions in the bootmem maps.
+- */
+ for (i = 0; i < pavail_ents; i++) {
+ unsigned long old_start, old_end;
+
+ old_start = pavail[i].phys_addr;
+- old_end = old_start +
+- pavail[i].reg_size;
++ old_end = old_start + pavail[i].reg_size;
+ while (old_start < old_end) {
+ int n;
+
+@@ -1440,7 +1882,16 @@ static void __init taint_real_pages(void)
+ goto do_next_page;
+ }
+ }
+- reserve_bootmem(old_start, PAGE_SIZE, BOOTMEM_DEFAULT);
++
++ prom_printf("mem_init: Lost memory in pavail\n");
++ prom_printf("mem_init: OLD start[%lx] size[%lx]\n",
++ pavail[i].phys_addr,
++ pavail[i].reg_size);
++ prom_printf("mem_init: NEW start[%lx] size[%lx]\n",
++ pavail_rescan[i].phys_addr,
++ pavail_rescan[i].reg_size);
++ prom_printf("mem_init: Cannot continue, aborting.\n");
++ prom_halt();
+
+ do_next_page:
+ old_start += PAGE_SIZE;
+@@ -1448,32 +1899,6 @@ static void __init taint_real_pages(void)
+ }
+ }
+
+-int __init page_in_phys_avail(unsigned long paddr)
+-{
+- int i;
+-
+- paddr &= PAGE_MASK;
+-
+- for (i = 0; i < pavail_rescan_ents; i++) {
+- unsigned long start, end;
+-
+- start = pavail_rescan[i].phys_addr;
+- end = start + pavail_rescan[i].reg_size;
+-
+- if (paddr >= start && paddr < end)
+- return 1;
+- }
+- if (paddr >= kern_base && paddr < (kern_base + kern_size))
+- return 1;
+-#ifdef CONFIG_BLK_DEV_INITRD
+- if (paddr >= __pa(initrd_start) &&
+- paddr < __pa(PAGE_ALIGN(initrd_end)))
+- return 1;
+-#endif
+-
+- return 0;
+-}
+-
+ void __init mem_init(void)
+ {
+ unsigned long codepages, datapages, initpages;
+@@ -1496,14 +1921,26 @@ void __init mem_init(void)
+ addr += PAGE_SIZE;
+ }
+
+- taint_real_pages();
++ setup_valid_addr_bitmap_from_pavail();
+
+ high_memory = __va(last_valid_pfn << PAGE_SHIFT);
+
++#ifdef CONFIG_NEED_MULTIPLE_NODES
++ for_each_online_node(i) {
++ if (NODE_DATA(i)->node_spanned_pages != 0) {
++ totalram_pages +=
++ free_all_bootmem_node(NODE_DATA(i));
++ }
++ }
++#else
++ totalram_pages = free_all_bootmem();
++#endif
++
+ /* We subtract one to account for the mem_map_zero page
+ * allocated below.
+ */
+- totalram_pages = num_physpages = free_all_bootmem() - 1;
++ totalram_pages -= 1;
++ num_physpages = totalram_pages;
+
+ /*
+ * Set up the zero page, mark it reserved, so that page count
+diff --git a/arch/sparc64/mm/tsb.c b/arch/sparc64/mm/tsb.c
+index a3e6e4b..fe70c8a 100644
+--- a/arch/sparc64/mm/tsb.c
++++ b/arch/sparc64/mm/tsb.c
+@@ -321,7 +321,8 @@ retry_tsb_alloc:
+ if (new_size > (PAGE_SIZE * 2))
+ gfp_flags = __GFP_NOWARN | __GFP_NORETRY;
+
+- new_tsb = kmem_cache_alloc(tsb_caches[new_cache_index], gfp_flags);
++ new_tsb = kmem_cache_alloc_node(tsb_caches[new_cache_index],
++ gfp_flags, numa_node_id());
+ if (unlikely(!new_tsb)) {
+ /* Not being able to fork due to a high-order TSB
+ * allocation failure is very bad behavior. Just back
+diff --git a/arch/sparc64/mm/ultra.S b/arch/sparc64/mm/ultra.S
+index 2865c10..e686a67 100644
+--- a/arch/sparc64/mm/ultra.S
++++ b/arch/sparc64/mm/ultra.S
+@@ -476,7 +476,6 @@ xcall_sync_tick:
+ #endif
+ call smp_synchronize_tick_client
+ nop
+- clr %l6
+ b rtrap_xcall
+ ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
+
+@@ -511,7 +510,6 @@ xcall_report_regs:
+ #endif
+ call __show_regs
+ add %sp, PTREGS_OFF, %o0
+- clr %l6
+ /* Has to be a non-v9 branch due to the large distance. */
+ b rtrap_xcall
+ ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
+@@ -576,7 +574,7 @@ __hypervisor_tlb_xcall_error:
+ mov %l4, %o0
+ call hypervisor_tlbop_error_xcall
+ mov %l5, %o1
+- ba,a,pt %xcc, rtrap_clr_l6
++ ba,a,pt %xcc, rtrap
+
+ .globl __hypervisor_xcall_flush_tlb_mm
+ __hypervisor_xcall_flush_tlb_mm: /* 21 insns */
+diff --git a/arch/sparc64/solaris/Makefile b/arch/sparc64/solaris/Makefile
+deleted file mode 100644
+index 8c86630..0000000
+--- a/arch/sparc64/solaris/Makefile
++++ /dev/null
+@@ -1,10 +0,0 @@
+-#
+-# Makefile for the Solaris binary emulation.
+-#
+-
+-EXTRA_AFLAGS := -ansi
+-
+-solaris-objs := entry64.o fs.o misc.o signal.o systbl.o socket.o \
+- ioctl.o ipc.o socksys.o timod.o
+-
+-obj-$(CONFIG_SOLARIS_EMUL) += solaris.o
+diff --git a/arch/sparc64/solaris/conv.h b/arch/sparc64/solaris/conv.h
+deleted file mode 100644
+index 50e5823..0000000
+--- a/arch/sparc64/solaris/conv.h
++++ /dev/null
+@@ -1,38 +0,0 @@
+-/* $Id: conv.h,v 1.4 1998/08/15 20:42:51 davem Exp $
+- * conv.h: Utility macros for Solaris emulation
+- *
+- * Copyright (C) 1997 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
+- */
+-
+-/* #define DEBUG_SOLARIS */
+-#define DEBUG_SOLARIS_KMALLOC
+-
+-#ifndef __ASSEMBLY__
+-
+-#include <asm/unistd.h>
+-
+-/* Use this to get at 32-bit user passed pointers. */
+-#define A(__x) \
+-({ unsigned long __ret; \
+- __asm__ ("srl %0, 0, %0" \
+- : "=r" (__ret) \
+- : "0" (__x)); \
+- (void __user *)__ret; \
+-})
+-
+-extern unsigned sys_call_table[];
+-extern unsigned sys_call_table32[];
+-extern unsigned sunos_sys_table[];
+-
+-#define SYS(name) ((long)sys_call_table[__NR_##name])
+-#define SUNOS(x) ((long)sunos_sys_table[x])
+-
+-#ifdef DEBUG_SOLARIS
+-#define SOLD(s) printk("%s,%d,%s(): %s\n",__FILE__,__LINE__,__func__,(s))
+-#define SOLDD(s) printk("solaris: "); printk s
+-#else
+-#define SOLD(s)
+-#define SOLDD(s)
+-#endif
+-
+-#endif /* __ASSEMBLY__ */
+diff --git a/arch/sparc64/solaris/entry64.S b/arch/sparc64/solaris/entry64.S
+deleted file mode 100644
+index f170324..0000000
+--- a/arch/sparc64/solaris/entry64.S
++++ /dev/null
+@@ -1,223 +0,0 @@
+-/* $Id: entry64.S,v 1.7 2002/02/09 19:49:31 davem Exp $
+- * entry64.S: Solaris syscall emulation entry point.
+- *
+- * Copyright (C) 1996,1997,1998 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
+- * Copyright (C) 1995,1997 David S. Miller (davem at caip.rutgers.edu)
+- * Copyright (C) 1996 Miguel de Icaza (miguel at nuclecu.unam.mx)
+- */
+-
+-#include <linux/errno.h>
+-
+-#include <asm/head.h>
+-#include <asm/asi.h>
+-#include <asm/smp.h>
+-#include <asm/ptrace.h>
+-#include <asm/page.h>
+-#include <asm/signal.h>
+-#include <asm/pgtable.h>
+-#include <asm/processor.h>
+-#include <asm/thread_info.h>
+-
+-#include "conv.h"
+-
+-#define NR_SYSCALLS 256
+-
+- .text
+-solaris_syscall_trace:
+- add %sp, PTREGS_OFF, %o0
+- call syscall_trace
+- mov 0, %o1
+- srl %i0, 0, %o0
+- mov %i4, %o4
+- srl %i1, 0, %o1
+- mov %i5, %o5
+- andcc %l3, 1, %g0
+- be,pt %icc, 2f
+- srl %i2, 0, %o2
+- b,pt %xcc, 2f
+- add %sp, PTREGS_OFF, %o0
+-
+-solaris_sucks:
+-/* Solaris is a big system which needs to be able to do all the things
+- * in Inf+1 different ways */
+- add %i6, 0x5c, %o0
+- mov %i0, %g1
+- mov %i1, %i0
+- mov %i2, %i1
+- srl %o0, 0, %o0
+- mov %i3, %i2
+- movrz %g1, 256, %g1 /* Ensure we don't loop forever */
+- mov %i4, %i3
+- mov %i5, %i4
+- ba,pt %xcc, solaris_sparc_syscall
+-exen: lduwa [%o0] ASI_S, %i5
+-
+-exenf: ba,pt %xcc, solaris_sparc_syscall
+- clr %i5
+-
+-/* For shared binaries, binfmt_elf32 already sets up personality
+- and exec_domain. This is to handle static binaries as well */
+-solaris_reg:
+- call solaris_register
+- nop
+- ba,pt %xcc, 1f
+- mov %i4, %o4
+-
+-linux_syscall_for_solaris:
+- sethi %hi(sys_call_table32), %l6
+- or %l6, %lo(sys_call_table32), %l6
+- sll %l3, 2, %l4
+- ba,pt %xcc, 10f
+- lduw [%l6 + %l4], %l3
+-
+- /* Solaris system calls enter here... */
+- .align 32
+- .globl solaris_sparc_syscall, entry64_personality_patch
+-solaris_sparc_syscall:
+-entry64_personality_patch:
+- ldub [%g4 + 0x0], %l0
+- cmp %g1, 255
+- bg,pn %icc, solaris_unimplemented
+- srl %g1, 0, %g1
+- sethi %hi(solaris_sys_table), %l7
+- or %l7, %lo(solaris_sys_table), %l7
+- brz,pn %g1, solaris_sucks
+- mov %i4, %o4
+- sll %g1, 2, %l4
+- cmp %l0, 1
+- bne,pn %icc, solaris_reg
+-1: srl %i0, 0, %o0
+- lduw [%l7 + %l4], %l3
+- srl %i1, 0, %o1
+- ldx [%g6 + TI_FLAGS], %l5
+- cmp %l3, NR_SYSCALLS
+- bleu,a,pn %xcc, linux_syscall_for_solaris
+- nop
+- andcc %l3, 1, %g0
+- bne,a,pn %icc, 10f
+- add %sp, PTREGS_OFF, %o0
+-10: srl %i2, 0, %o2
+- mov %i5, %o5
+- andn %l3, 3, %l7
+- andcc %l5, _TIF_SYSCALL_TRACE, %g0
+- bne,pn %icc, solaris_syscall_trace
+- mov %i0, %l5
+-2: call %l7
+- srl %i3, 0, %o3
+-ret_from_solaris:
+- stx %o0, [%sp + PTREGS_OFF + PT_V9_I0]
+- ldx [%g6 + TI_FLAGS], %l6
+- sra %o0, 0, %o0
+- mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
+- ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3
+- cmp %o0, -ERESTART_RESTARTBLOCK
+- sllx %g2, 32, %g2
+- bgeu,pn %xcc, 1f
+- andcc %l6, _TIF_SYSCALL_TRACE, %l6
+-
+- /* System call success, clear Carry condition code. */
+- andn %g3, %g2, %g3
+- stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
+- bne,pn %icc, solaris_syscall_trace2
+- ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1
+- andcc %l1, 1, %g0
+- bne,pn %icc, 2f
+- clr %l6
+- add %l1, 0x4, %l2
+- stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC] ! pc = npc
+- call rtrap
+- stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] !npc = npc+4
+-
+- /* When tnpc & 1, this comes from setcontext and we don't want to advance pc */
+-2: andn %l1, 3, %l1
+- call rtrap
+- stx %l1, [%sp + PTREGS_OFF + PT_V9_TNPC] !npc = npc&~3
+-
+-1:
+- /* System call failure, set Carry condition code.
+- * Also, get abs(errno) to return to the process.
+- */
+- sub %g0, %o0, %o0
+- or %g3, %g2, %g3
+- cmp %o0, ERANGE /* 0-ERANGE are identity mapped */
+- bleu,pt %icc, 1f
+- cmp %o0, EMEDIUMTYPE
+- bgu,pn %icc, 1f
+- sethi %hi(solaris_err_table), %l6
+- sll %o0, 2, %o0
+- or %l6, %lo(solaris_err_table), %l6
+- ldsw [%l6 + %o0], %o0
+-1: stx %o0, [%sp + PTREGS_OFF + PT_V9_I0]
+- mov 1, %l6
+- stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
+- bne,pn %icc, solaris_syscall_trace2
+- ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1
+- andcc %l1, 1, %g0
+- bne,pn %icc, 2b
+- add %l1, 0x4, %l2
+- stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC] ! pc = npc
+- call rtrap
+- stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] !npc = npc+4
+-
+-solaris_syscall_trace2:
+- add %sp, PTREGS_OFF, %o0
+- call syscall_trace
+- mov 1, %o1
+- add %l1, 0x4, %l2 /* npc = npc+4 */
+- andcc %l1, 1, %g0
+- bne,pn %icc, 2b
+- nop
+- stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
+- call rtrap
+- stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
+-
+- /* This one is tricky, so that's why we do it in assembly */
+- .globl solaris_sigsuspend
+-solaris_sigsuspend:
+- call do_sol_sigsuspend
+- nop
+- brlz,pn %o0, ret_from_solaris
+- nop
+- call sys_sigsuspend
+- stx %o0, [%sp + PTREGS_OFF + PT_V9_I0]
+- b,pt %xcc, ret_from_solaris
+- nop
+-
+- .globl solaris_getpid
+-solaris_getpid:
+- call sys_getppid
+- nop
+- call sys_getpid
+- stx %o0, [%sp + PTREGS_OFF + PT_V9_I1]
+- b,pt %xcc, ret_from_solaris
+- nop
+-
+- .globl solaris_getuid
+-solaris_getuid:
+- call sys_geteuid
+- nop
+- call sys_getuid
+- stx %o1, [%sp + PTREGS_OFF + PT_V9_I1]
+- b,pt %xcc, ret_from_solaris
+- nop
+-
+- .globl solaris_getgid
+-solaris_getgid:
+- call sys_getegid
+- nop
+- call sys_getgid
+- stx %o1, [%sp + PTREGS_OFF + PT_V9_I1]
+- b,pt %xcc, ret_from_solaris
+- nop
+-
+- .globl solaris_unimplemented
+-solaris_unimplemented:
+- call do_sol_unimplemented
+- add %sp, PTREGS_OFF, %o0
+- ba,pt %xcc, ret_from_solaris
+- nop
+-
+- .section __ex_table,"a"
+- .align 4
+- .word exen, exenf
+-
+diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c
+deleted file mode 100644
+index 7d035f0..0000000
+--- a/arch/sparc64/solaris/fs.c
++++ /dev/null
+@@ -1,745 +0,0 @@
+-/* $Id: fs.c,v 1.27 2002/02/08 03:57:14 davem Exp $
+- * fs.c: fs related syscall emulation for Solaris
+- *
+- * Copyright (C) 1997,1998 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
+- *
+- * 1999-08-19 Implemented solaris F_FREESP (truncate)
+- * fcntl, by Jason Rappleye (rappleye at ccr.buffalo.edu)
+- */
+-
+-#include <linux/types.h>
+-#include <linux/sched.h>
+-#include <linux/slab.h>
+-#include <linux/capability.h>
+-#include <linux/fs.h>
+-#include <linux/namei.h>
+-#include <linux/mm.h>
+-#include <linux/file.h>
+-#include <linux/stat.h>
+-#include <linux/smp_lock.h>
+-#include <linux/limits.h>
+-#include <linux/resource.h>
+-#include <linux/quotaops.h>
+-#include <linux/mount.h>
+-#include <linux/vfs.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/string.h>
+-#include <asm/ptrace.h>
+-
+-#include "conv.h"
+-
+-#define R3_VERSION 1
+-#define R4_VERSION 2
+-
+-typedef struct {
+- s32 tv_sec;
+- s32 tv_nsec;
+-} timestruct_t;
+-
+-struct sol_stat {
+- u32 st_dev;
+- s32 st_pad1[3]; /* network id */
+- u32 st_ino;
+- u32 st_mode;
+- u32 st_nlink;
+- u32 st_uid;
+- u32 st_gid;
+- u32 st_rdev;
+- s32 st_pad2[2];
+- s32 st_size;
+- s32 st_pad3; /* st_size, off_t expansion */
+- timestruct_t st_atime;
+- timestruct_t st_mtime;
+- timestruct_t st_ctime;
+- s32 st_blksize;
+- s32 st_blocks;
+- char st_fstype[16];
+- s32 st_pad4[8]; /* expansion area */
+-};
+-
+-struct sol_stat64 {
+- u32 st_dev;
+- s32 st_pad1[3]; /* network id */
+- u64 st_ino;
+- u32 st_mode;
+- u32 st_nlink;
+- u32 st_uid;
+- u32 st_gid;
+- u32 st_rdev;
+- s32 st_pad2[2];
+- s64 st_size;
+- timestruct_t st_atime;
+- timestruct_t st_mtime;
+- timestruct_t st_ctime;
+- s64 st_blksize;
+- s32 st_blocks;
+- char st_fstype[16];
+- s32 st_pad4[4]; /* expansion area */
+-};
+-
+-#define UFSMAGIC (((unsigned)'u'<<24)||((unsigned)'f'<<16)||((unsigned)'s'<<8))
+-
+-static inline int putstat(struct sol_stat __user *ubuf, struct kstat *kbuf)
+-{
+- u32 ino;
+-
+- if (kbuf->size > MAX_NON_LFS ||
+- !sysv_valid_dev(kbuf->dev) ||
+- !sysv_valid_dev(kbuf->rdev))
+- return -EOVERFLOW;
+- ino = kbuf->ino;
+- if (sizeof(ino) < sizeof(kbuf->ino) && ino != kbuf->ino)
+- return -EOVERFLOW;
+- if (put_user (sysv_encode_dev(kbuf->dev), &ubuf->st_dev) ||
+- __put_user (ino, &ubuf->st_ino) ||
+- __put_user (kbuf->mode, &ubuf->st_mode) ||
+- __put_user (kbuf->nlink, &ubuf->st_nlink) ||
+- __put_user (kbuf->uid, &ubuf->st_uid) ||
+- __put_user (kbuf->gid, &ubuf->st_gid) ||
+- __put_user (sysv_encode_dev(kbuf->rdev), &ubuf->st_rdev) ||
+- __put_user (kbuf->size, &ubuf->st_size) ||
+- __put_user (kbuf->atime.tv_sec, &ubuf->st_atime.tv_sec) ||
+- __put_user (kbuf->atime.tv_nsec, &ubuf->st_atime.tv_nsec) ||
+- __put_user (kbuf->mtime.tv_sec, &ubuf->st_mtime.tv_sec) ||
+- __put_user (kbuf->mtime.tv_nsec, &ubuf->st_mtime.tv_nsec) ||
+- __put_user (kbuf->ctime.tv_sec, &ubuf->st_ctime.tv_sec) ||
+- __put_user (kbuf->ctime.tv_nsec, &ubuf->st_ctime.tv_nsec) ||
+- __put_user (kbuf->blksize, &ubuf->st_blksize) ||
+- __put_user (kbuf->blocks, &ubuf->st_blocks) ||
+- __put_user (UFSMAGIC, (unsigned __user *)ubuf->st_fstype))
+- return -EFAULT;
+- return 0;
+-}
+-
+-static inline int putstat64(struct sol_stat64 __user *ubuf, struct kstat *kbuf)
+-{
+- if (!sysv_valid_dev(kbuf->dev) || !sysv_valid_dev(kbuf->rdev))
+- return -EOVERFLOW;
+- if (put_user (sysv_encode_dev(kbuf->dev), &ubuf->st_dev) ||
+- __put_user (kbuf->ino, &ubuf->st_ino) ||
+- __put_user (kbuf->mode, &ubuf->st_mode) ||
+- __put_user (kbuf->nlink, &ubuf->st_nlink) ||
+- __put_user (kbuf->uid, &ubuf->st_uid) ||
+- __put_user (kbuf->gid, &ubuf->st_gid) ||
+- __put_user (sysv_encode_dev(kbuf->rdev), &ubuf->st_rdev) ||
+- __put_user (kbuf->size, &ubuf->st_size) ||
+- __put_user (kbuf->atime.tv_sec, &ubuf->st_atime.tv_sec) ||
+- __put_user (kbuf->atime.tv_nsec, &ubuf->st_atime.tv_nsec) ||
+- __put_user (kbuf->mtime.tv_sec, &ubuf->st_mtime.tv_sec) ||
+- __put_user (kbuf->mtime.tv_nsec, &ubuf->st_mtime.tv_nsec) ||
+- __put_user (kbuf->ctime.tv_sec, &ubuf->st_ctime.tv_sec) ||
+- __put_user (kbuf->ctime.tv_nsec, &ubuf->st_ctime.tv_nsec) ||
+- __put_user (kbuf->blksize, &ubuf->st_blksize) ||
+- __put_user (kbuf->blocks, &ubuf->st_blocks) ||
+- __put_user (UFSMAGIC, (unsigned __user *)ubuf->st_fstype))
+- return -EFAULT;
+- return 0;
+-}
+-
+-asmlinkage int solaris_stat(u32 filename, u32 statbuf)
+-{
+- struct kstat s;
+- int ret = vfs_stat(A(filename), &s);
+- if (!ret)
+- return putstat(A(statbuf), &s);
+- return ret;
+-}
+-
+-asmlinkage int solaris_xstat(int vers, u32 filename, u32 statbuf)
+-{
+- /* Solaris doesn't bother with looking at vers, so we do neither */
+- return solaris_stat(filename, statbuf);
+-}
+-
+-asmlinkage int solaris_stat64(u32 filename, u32 statbuf)
+-{
+- struct kstat s;
+- int ret = vfs_stat(A(filename), &s);
+- if (!ret)
+- return putstat64(A(statbuf), &s);
+- return ret;
+-}
+-
+-asmlinkage int solaris_lstat(u32 filename, u32 statbuf)
+-{
+- struct kstat s;
+- int ret = vfs_lstat(A(filename), &s);
+- if (!ret)
+- return putstat(A(statbuf), &s);
+- return ret;
+-}
+-
+-asmlinkage int solaris_lxstat(int vers, u32 filename, u32 statbuf)
+-{
+- return solaris_lstat(filename, statbuf);
+-}
+-
+-asmlinkage int solaris_lstat64(u32 filename, u32 statbuf)
+-{
+- struct kstat s;
+- int ret = vfs_lstat(A(filename), &s);
+- if (!ret)
+- return putstat64(A(statbuf), &s);
+- return ret;
+-}
+-
+-asmlinkage int solaris_fstat(unsigned int fd, u32 statbuf)
+-{
+- struct kstat s;
+- int ret = vfs_fstat(fd, &s);
+- if (!ret)
+- return putstat(A(statbuf), &s);
+- return ret;
+-}
+-
+-asmlinkage int solaris_fxstat(int vers, u32 fd, u32 statbuf)
+-{
+- return solaris_fstat(fd, statbuf);
+-}
+-
+-asmlinkage int solaris_fstat64(unsigned int fd, u32 statbuf)
+-{
+- struct kstat s;
+- int ret = vfs_fstat(fd, &s);
+- if (!ret)
+- return putstat64(A(statbuf), &s);
+- return ret;
+-}
+-
+-asmlinkage int solaris_mknod(u32 path, u32 mode, s32 dev)
+-{
+- int (*sys_mknod)(const char __user *,int,unsigned) =
+- (int (*)(const char __user *,int,unsigned))SYS(mknod);
+- int major = sysv_major(dev);
+- int minor = sysv_minor(dev);
+-
+- /* minor is guaranteed to be OK for MKDEV, major might be not */
+- if (major > 0xfff)
+- return -EINVAL;
+- return sys_mknod(A(path), mode, new_encode_dev(MKDEV(major,minor)));
+-}
+-
+-asmlinkage int solaris_xmknod(int vers, u32 path, u32 mode, s32 dev)
+-{
+- return solaris_mknod(path, mode, dev);
+-}
+-
+-asmlinkage int solaris_getdents64(unsigned int fd, void __user *dirent, unsigned int count)
+-{
+- int (*sys_getdents)(unsigned int, void __user *, unsigned int) =
+- (int (*)(unsigned int, void __user *, unsigned int))SYS(getdents);
+-
+- return sys_getdents(fd, dirent, count);
+-}
+-
+-/* This statfs thingie probably will go in the near future, but... */
+-
+-struct sol_statfs {
+- short f_type;
+- s32 f_bsize;
+- s32 f_frsize;
+- s32 f_blocks;
+- s32 f_bfree;
+- u32 f_files;
+- u32 f_ffree;
+- char f_fname[6];
+- char f_fpack[6];
+-};
+-
+-asmlinkage int solaris_statfs(u32 path, u32 buf, int len, int fstype)
+-{
+- int ret;
+- struct statfs s;
+- mm_segment_t old_fs = get_fs();
+- int (*sys_statfs)(const char __user *,struct statfs __user *) =
+- (int (*)(const char __user *,struct statfs __user *))SYS(statfs);
+- struct sol_statfs __user *ss = A(buf);
+-
+- if (len != sizeof(struct sol_statfs)) return -EINVAL;
+- if (!fstype) {
+- /* FIXME: mixing userland and kernel pointers */
+- set_fs (KERNEL_DS);
+- ret = sys_statfs(A(path), &s);
+- set_fs (old_fs);
+- if (!ret) {
+- if (put_user (s.f_type, &ss->f_type) ||
+- __put_user (s.f_bsize, &ss->f_bsize) ||
+- __put_user (0, &ss->f_frsize) ||
+- __put_user (s.f_blocks, &ss->f_blocks) ||
+- __put_user (s.f_bfree, &ss->f_bfree) ||
+- __put_user (s.f_files, &ss->f_files) ||
+- __put_user (s.f_ffree, &ss->f_ffree) ||
+- __clear_user (&ss->f_fname, 12))
+- return -EFAULT;
+- }
+- return ret;
+- }
+-/* Linux can't stat unmounted filesystems so we
+- * simply lie and claim 100MB of 1GB is free. Sorry.
+- */
+- if (put_user (fstype, &ss->f_type) ||
+- __put_user (1024, &ss->f_bsize) ||
+- __put_user (0, &ss->f_frsize) ||
+- __put_user (1024*1024, &ss->f_blocks) ||
+- __put_user (100*1024, &ss->f_bfree) ||
+- __put_user (60000, &ss->f_files) ||
+- __put_user (50000, &ss->f_ffree) ||
+- __clear_user (&ss->f_fname, 12))
+- return -EFAULT;
+- return 0;
+-}
+-
+-asmlinkage int solaris_fstatfs(u32 fd, u32 buf, int len, int fstype)
+-{
+- int ret;
+- struct statfs s;
+- mm_segment_t old_fs = get_fs();
+- int (*sys_fstatfs)(unsigned,struct statfs __user *) =
+- (int (*)(unsigned,struct statfs __user *))SYS(fstatfs);
+- struct sol_statfs __user *ss = A(buf);
+-
+- if (len != sizeof(struct sol_statfs)) return -EINVAL;
+- if (!fstype) {
+- set_fs (KERNEL_DS);
+- ret = sys_fstatfs(fd, &s);
+- set_fs (old_fs);
+- if (!ret) {
+- if (put_user (s.f_type, &ss->f_type) ||
+- __put_user (s.f_bsize, &ss->f_bsize) ||
+- __put_user (0, &ss->f_frsize) ||
+- __put_user (s.f_blocks, &ss->f_blocks) ||
+- __put_user (s.f_bfree, &ss->f_bfree) ||
+- __put_user (s.f_files, &ss->f_files) ||
+- __put_user (s.f_ffree, &ss->f_ffree) ||
+- __clear_user (&ss->f_fname, 12))
+- return -EFAULT;
+- }
+- return ret;
+- }
+- /* Otherwise fstatfs is the same as statfs */
+- return solaris_statfs(0, buf, len, fstype);
+-}
+-
+-struct sol_statvfs {
+- u32 f_bsize;
+- u32 f_frsize;
+- u32 f_blocks;
+- u32 f_bfree;
+- u32 f_bavail;
+- u32 f_files;
+- u32 f_ffree;
+- u32 f_favail;
+- u32 f_fsid;
+- char f_basetype[16];
+- u32 f_flag;
+- u32 f_namemax;
+- char f_fstr[32];
+- u32 f_filler[16];
+-};
+-
+-struct sol_statvfs64 {
+- u32 f_bsize;
+- u32 f_frsize;
+- u64 f_blocks;
+- u64 f_bfree;
+- u64 f_bavail;
+- u64 f_files;
+- u64 f_ffree;
+- u64 f_favail;
+- u32 f_fsid;
+- char f_basetype[16];
+- u32 f_flag;
+- u32 f_namemax;
+- char f_fstr[32];
+- u32 f_filler[16];
+-};
+-
+-static int report_statvfs(struct vfsmount *mnt, struct inode *inode, u32 buf)
+-{
+- struct kstatfs s;
+- int error;
+- struct sol_statvfs __user *ss = A(buf);
+-
+- error = vfs_statfs(mnt->mnt_root, &s);
+- if (!error) {
+- const char *p = mnt->mnt_sb->s_type->name;
+- int i = 0;
+- int j = strlen (p);
+-
+- if (j > 15) j = 15;
+- if (IS_RDONLY(inode)) i = 1;
+- if (mnt->mnt_flags & MNT_NOSUID) i |= 2;
+- if (!sysv_valid_dev(inode->i_sb->s_dev))
+- return -EOVERFLOW;
+- if (put_user (s.f_bsize, &ss->f_bsize) ||
+- __put_user (0, &ss->f_frsize) ||
+- __put_user (s.f_blocks, &ss->f_blocks) ||
+- __put_user (s.f_bfree, &ss->f_bfree) ||
+- __put_user (s.f_bavail, &ss->f_bavail) ||
+- __put_user (s.f_files, &ss->f_files) ||
+- __put_user (s.f_ffree, &ss->f_ffree) ||
+- __put_user (s.f_ffree, &ss->f_favail) ||
+- __put_user (sysv_encode_dev(inode->i_sb->s_dev), &ss->f_fsid) ||
+- __copy_to_user (ss->f_basetype,p,j) ||
+- __put_user (0, (char __user *)&ss->f_basetype[j]) ||
+- __put_user (s.f_namelen, &ss->f_namemax) ||
+- __put_user (i, &ss->f_flag) ||
+- __clear_user (&ss->f_fstr, 32))
+- return -EFAULT;
+- }
+- return error;
+-}
+-
+-static int report_statvfs64(struct vfsmount *mnt, struct inode *inode, u32 buf)
+-{
+- struct kstatfs s;
+- int error;
+- struct sol_statvfs64 __user *ss = A(buf);
+-
+- error = vfs_statfs(mnt->mnt_root, &s);
+- if (!error) {
+- const char *p = mnt->mnt_sb->s_type->name;
+- int i = 0;
+- int j = strlen (p);
+-
+- if (j > 15) j = 15;
+- if (IS_RDONLY(inode)) i = 1;
+- if (mnt->mnt_flags & MNT_NOSUID) i |= 2;
+- if (!sysv_valid_dev(inode->i_sb->s_dev))
+- return -EOVERFLOW;
+- if (put_user (s.f_bsize, &ss->f_bsize) ||
+- __put_user (0, &ss->f_frsize) ||
+- __put_user (s.f_blocks, &ss->f_blocks) ||
+- __put_user (s.f_bfree, &ss->f_bfree) ||
+- __put_user (s.f_bavail, &ss->f_bavail) ||
+- __put_user (s.f_files, &ss->f_files) ||
+- __put_user (s.f_ffree, &ss->f_ffree) ||
+- __put_user (s.f_ffree, &ss->f_favail) ||
+- __put_user (sysv_encode_dev(inode->i_sb->s_dev), &ss->f_fsid) ||
+- __copy_to_user (ss->f_basetype,p,j) ||
+- __put_user (0, (char __user *)&ss->f_basetype[j]) ||
+- __put_user (s.f_namelen, &ss->f_namemax) ||
+- __put_user (i, &ss->f_flag) ||
+- __clear_user (&ss->f_fstr, 32))
+- return -EFAULT;
+- }
+- return error;
+-}
+-
+-asmlinkage int solaris_statvfs(u32 path, u32 buf)
+-{
+- struct nameidata nd;
+- int error;
+-
+- error = user_path_walk(A(path),&nd);
+- if (!error) {
+- struct inode *inode = nd.path.dentry->d_inode;
+- error = report_statvfs(nd.path.mnt, inode, buf);
+- path_put(&nd.path);
+- }
+- return error;
+-}
+-
+-asmlinkage int solaris_fstatvfs(unsigned int fd, u32 buf)
+-{
+- struct file * file;
+- int error;
+-
+- error = -EBADF;
+- file = fget(fd);
+- if (file) {
+- error = report_statvfs(file->f_path.mnt, file->f_path.dentry->d_inode, buf);
+- fput(file);
+- }
+-
+- return error;
+-}
+-
+-asmlinkage int solaris_statvfs64(u32 path, u32 buf)
+-{
+- struct nameidata nd;
+- int error;
+-
+- lock_kernel();
+- error = user_path_walk(A(path), &nd);
+- if (!error) {
+- struct inode *inode = nd.path.dentry->d_inode;
+- error = report_statvfs64(nd.path.mnt, inode, buf);
+- path_put(&nd.path);
+- }
+- unlock_kernel();
+- return error;
+-}
+-
+-asmlinkage int solaris_fstatvfs64(unsigned int fd, u32 buf)
+-{
+- struct file * file;
+- int error;
+-
+- error = -EBADF;
+- file = fget(fd);
+- if (file) {
+- lock_kernel();
+- error = report_statvfs64(file->f_path.mnt, file->f_path.dentry->d_inode, buf);
+- unlock_kernel();
+- fput(file);
+- }
+- return error;
+-}
+-
+-extern asmlinkage long sparc32_open(const char * filename, int flags, int mode);
+-
+-asmlinkage int solaris_open(u32 fname, int flags, u32 mode)
+-{
+- const char *filename = (const char *)(long)fname;
+- int fl = flags & 0xf;
+-
+- /* Translate flags first. */
+- if (flags & 0x2000) fl |= O_LARGEFILE;
+- if (flags & 0x8050) fl |= O_SYNC;
+- if (flags & 0x80) fl |= O_NONBLOCK;
+- if (flags & 0x100) fl |= O_CREAT;
+- if (flags & 0x200) fl |= O_TRUNC;
+- if (flags & 0x400) fl |= O_EXCL;
+- if (flags & 0x800) fl |= O_NOCTTY;
+- flags = fl;
+-
+- return sparc32_open(filename, flags, mode);
+-}
+-
+-#define SOL_F_SETLK 6
+-#define SOL_F_SETLKW 7
+-#define SOL_F_FREESP 11
+-#define SOL_F_ISSTREAM 13
+-#define SOL_F_GETLK 14
+-#define SOL_F_PRIV 15
+-#define SOL_F_NPRIV 16
+-#define SOL_F_QUOTACTL 17
+-#define SOL_F_BLOCKS 18
+-#define SOL_F_BLKSIZE 19
+-#define SOL_F_GETOWN 23
+-#define SOL_F_SETOWN 24
+-
+-struct sol_flock {
+- short l_type;
+- short l_whence;
+- u32 l_start;
+- u32 l_len;
+- s32 l_sysid;
+- s32 l_pid;
+- s32 l_pad[4];
+-};
+-
+-asmlinkage int solaris_fcntl(unsigned fd, unsigned cmd, u32 arg)
+-{
+- int (*sys_fcntl)(unsigned,unsigned,unsigned long) =
+- (int (*)(unsigned,unsigned,unsigned long))SYS(fcntl);
+- int ret, flags;
+-
+- switch (cmd) {
+- case F_DUPFD:
+- case F_GETFD:
+- case F_SETFD: return sys_fcntl(fd, cmd, (unsigned long)arg);
+- case F_GETFL:
+- flags = sys_fcntl(fd, cmd, 0);
+- ret = flags & 0xf;
+- if (flags & O_SYNC) ret |= 0x8050;
+- if (flags & O_NONBLOCK) ret |= 0x80;
+- return ret;
+- case F_SETFL:
+- flags = arg & 0xf;
+- if (arg & 0x8050) flags |= O_SYNC;
+- if (arg & 0x80) flags |= O_NONBLOCK;
+- return sys_fcntl(fd, cmd, (long)flags);
+- case SOL_F_GETLK:
+- case SOL_F_SETLK:
+- case SOL_F_SETLKW:
+- {
+- struct flock f;
+- struct sol_flock __user *p = A(arg);
+- mm_segment_t old_fs = get_fs();
+-
+- switch (cmd) {
+- case SOL_F_GETLK: cmd = F_GETLK; break;
+- case SOL_F_SETLK: cmd = F_SETLK; break;
+- case SOL_F_SETLKW: cmd = F_SETLKW; break;
+- }
+-
+- if (get_user (f.l_type, &p->l_type) ||
+- __get_user (f.l_whence, &p->l_whence) ||
+- __get_user (f.l_start, &p->l_start) ||
+- __get_user (f.l_len, &p->l_len) ||
+- __get_user (f.l_pid, &p->l_sysid))
+- return -EFAULT;
+-
+- set_fs(KERNEL_DS);
+- ret = sys_fcntl(fd, cmd, (unsigned long)&f);
+- set_fs(old_fs);
+-
+- if (__put_user (f.l_type, &p->l_type) ||
+- __put_user (f.l_whence, &p->l_whence) ||
+- __put_user (f.l_start, &p->l_start) ||
+- __put_user (f.l_len, &p->l_len) ||
+- __put_user (f.l_pid, &p->l_pid) ||
+- __put_user (0, &p->l_sysid))
+- return -EFAULT;
+-
+- return ret;
+- }
+- case SOL_F_FREESP:
+- {
+- int length;
+- int (*sys_newftruncate)(unsigned int, unsigned long)=
+- (int (*)(unsigned int, unsigned long))SYS(ftruncate);
+-
+- if (get_user(length, &((struct sol_flock __user *)A(arg))->l_start))
+- return -EFAULT;
+-
+- return sys_newftruncate(fd, length);
+- }
+- };
+- return -EINVAL;
+-}
+-
+-asmlinkage int solaris_ulimit(int cmd, int val)
+-{
+- switch (cmd) {
+- case 1: /* UL_GETFSIZE - in 512B chunks */
+- return current->signal->rlim[RLIMIT_FSIZE].rlim_cur >> 9;
+- case 2: /* UL_SETFSIZE */
+- if ((unsigned long)val > (LONG_MAX>>9)) return -ERANGE;
+- val <<= 9;
+- task_lock(current->group_leader);
+- if (val > current->signal->rlim[RLIMIT_FSIZE].rlim_max) {
+- if (!capable(CAP_SYS_RESOURCE)) {
+- task_unlock(current->group_leader);
+- return -EPERM;
+- }
+- current->signal->rlim[RLIMIT_FSIZE].rlim_max = val;
+- }
+- current->signal->rlim[RLIMIT_FSIZE].rlim_cur = val;
+- task_unlock(current->group_leader);
+- return 0;
+- case 3: /* UL_GMEMLIM */
+- return current->signal->rlim[RLIMIT_DATA].rlim_cur;
+- case 4: /* UL_GDESLIM */
+- return sysctl_nr_open;
+- }
+- return -EINVAL;
+-}
+-
+-/* At least at the time I'm writing this, Linux doesn't have ACLs, so we
+- just fake this */
+-asmlinkage int solaris_acl(u32 filename, int cmd, int nentries, u32 aclbufp)
+-{
+- return -ENOSYS;
+-}
+-
+-asmlinkage int solaris_facl(unsigned int fd, int cmd, int nentries, u32 aclbufp)
+-{
+- return -ENOSYS;
+-}
+-
+-asmlinkage int solaris_pread(unsigned int fd, char __user *buf, u32 count, u32 pos)
+-{
+- ssize_t (*sys_pread64)(unsigned int, char __user *, size_t, loff_t) =
+- (ssize_t (*)(unsigned int, char __user *, size_t, loff_t))SYS(pread64);
+-
+- return sys_pread64(fd, buf, count, (loff_t)pos);
+-}
+-
+-asmlinkage int solaris_pwrite(unsigned int fd, char __user *buf, u32 count, u32 pos)
+-{
+- ssize_t (*sys_pwrite64)(unsigned int, char __user *, size_t, loff_t) =
+- (ssize_t (*)(unsigned int, char __user *, size_t, loff_t))SYS(pwrite64);
+-
+- return sys_pwrite64(fd, buf, count, (loff_t)pos);
+-}
+-
+-/* POSIX.1 names */
+-#define _PC_LINK_MAX 1
+-#define _PC_MAX_CANON 2
+-#define _PC_MAX_INPUT 3
+-#define _PC_NAME_MAX 4
+-#define _PC_PATH_MAX 5
+-#define _PC_PIPE_BUF 6
+-#define _PC_NO_TRUNC 7
+-#define _PC_VDISABLE 8
+-#define _PC_CHOWN_RESTRICTED 9
+-/* POSIX.4 names */
+-#define _PC_ASYNC_IO 10
+-#define _PC_PRIO_IO 11
+-#define _PC_SYNC_IO 12
+-#define _PC_LAST 12
+-
+-/* This is not a real and complete implementation yet, just to keep
+- * the easy Solaris binaries happy.
+- */
+-asmlinkage int solaris_fpathconf(int fd, int name)
+-{
+- int ret;
+-
+- switch(name) {
+- case _PC_LINK_MAX:
+- ret = LINK_MAX;
+- break;
+- case _PC_MAX_CANON:
+- ret = MAX_CANON;
+- break;
+- case _PC_MAX_INPUT:
+- ret = MAX_INPUT;
+- break;
+- case _PC_NAME_MAX:
+- ret = NAME_MAX;
+- break;
+- case _PC_PATH_MAX:
+- ret = PATH_MAX;
+- break;
+- case _PC_PIPE_BUF:
+- ret = PIPE_BUF;
+- break;
+- case _PC_CHOWN_RESTRICTED:
+- ret = 1;
+- break;
+- case _PC_NO_TRUNC:
+- case _PC_VDISABLE:
+- ret = 0;
+- break;
+- default:
+- ret = -EINVAL;
+- break;
+- }
+- return ret;
+-}
+-
+-asmlinkage int solaris_pathconf(u32 path, int name)
+-{
+- return solaris_fpathconf(0, name);
+-}
+-
+-/* solaris_llseek returns long long - quite difficult */
+-asmlinkage long solaris_llseek(struct pt_regs *regs, u32 off_hi, u32 off_lo, int whence)
+-{
+- int (*sys_llseek)(unsigned int, unsigned long, unsigned long, loff_t __user *, unsigned int) =
+- (int (*)(unsigned int, unsigned long, unsigned long, loff_t __user *, unsigned int))SYS(_llseek);
+- int ret;
+- mm_segment_t old_fs = get_fs();
+- loff_t retval;
+-
+- set_fs(KERNEL_DS);
+- ret = sys_llseek((unsigned int)regs->u_regs[UREG_I0], off_hi, off_lo, &retval, whence);
+- set_fs(old_fs);
+- if (ret < 0) return ret;
+- regs->u_regs[UREG_I1] = (u32)retval;
+- return (retval >> 32);
+-}
+-
+-/* Have to mask out all but lower 3 bits */
+-asmlinkage int solaris_access(u32 filename, long mode)
+-{
+- int (*sys_access)(const char __user *, int) =
+- (int (*)(const char __user *, int))SYS(access);
+-
+- return sys_access(A(filename), mode & 7);
+-}
+diff --git a/arch/sparc64/solaris/ioctl.c b/arch/sparc64/solaris/ioctl.c
+deleted file mode 100644
+index 8ad10a6..0000000
+--- a/arch/sparc64/solaris/ioctl.c
++++ /dev/null
+@@ -1,825 +0,0 @@
+-/* $Id: ioctl.c,v 1.17 2002/02/08 03:57:14 davem Exp $
+- * ioctl.c: Solaris ioctl emulation.
+- *
+- * Copyright (C) 1997 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
+- * Copyright (C) 1997,1998 Patrik Rak (prak3264 at ss1000.ms.mff.cuni.cz)
+- *
+- * Streams & timod emulation based on code
+- * Copyright (C) 1995, 1996 Mike Jagdis (jaggy at purplet.demon.co.uk)
+- *
+- * 1999-08-19 Implemented solaris 'm' (mag tape) and
+- * 'O' (openprom) ioctls, by Jason Rappleye
+- * (rappleye at ccr.buffalo.edu)
+- */
+-
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/smp.h>
+-#include <linux/smp_lock.h>
+-#include <linux/syscalls.h>
+-#include <linux/ioctl.h>
+-#include <linux/fs.h>
+-#include <linux/file.h>
+-#include <linux/netdevice.h>
+-#include <linux/mtio.h>
+-#include <linux/time.h>
+-#include <linux/rcupdate.h>
+-#include <linux/compat.h>
+-
+-#include <net/sock.h>
+-#include <net/net_namespace.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/termios.h>
+-#include <asm/openpromio.h>
+-
+-#include "conv.h"
+-#include "socksys.h"
+-
+-extern asmlinkage int compat_sys_ioctl(unsigned int fd, unsigned int cmd,
+- u32 arg);
+-asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
+-
+-extern int timod_putmsg(unsigned int fd, char __user *ctl_buf, int ctl_len,
+- char __user *data_buf, int data_len, int flags);
+-extern int timod_getmsg(unsigned int fd, char __user *ctl_buf, int ctl_maxlen, int __user *ctl_len,
+- char __user *data_buf, int data_maxlen, int __user *data_len, int *flags);
+-
+-/* termio* stuff {{{ */
+-
+-struct solaris_termios {
+- u32 c_iflag;
+- u32 c_oflag;
+- u32 c_cflag;
+- u32 c_lflag;
+- u8 c_cc[19];
+-};
+-
+-struct solaris_termio {
+- u16 c_iflag;
+- u16 c_oflag;
+- u16 c_cflag;
+- u16 c_lflag;
+- s8 c_line;
+- u8 c_cc[8];
+-};
+-
+-struct solaris_termiox {
+- u16 x_hflag;
+- u16 x_cflag;
+- u16 x_rflag[5];
+- u16 x_sflag;
+-};
+-
+-static u32 solaris_to_linux_cflag(u32 cflag)
+-{
+- cflag &= 0x7fdff000;
+- if (cflag & 0x200000) {
+- int baud = cflag & 0xf;
+- cflag &= ~0x20000f;
+- switch (baud) {
+- case 0: baud = B57600; break;
+- case 1: baud = B76800; break;
+- case 2: baud = B115200; break;
+- case 3: baud = B153600; break;
+- case 4: baud = B230400; break;
+- case 5: baud = B307200; break;
+- case 6: baud = B460800; break;
+- }
+- cflag |= CBAUDEX | baud;
+- }
+- return cflag;
+-}
+-
+-static u32 linux_to_solaris_cflag(u32 cflag)
+-{
+- cflag &= ~(CMSPAR | CIBAUD);
+- if (cflag & CBAUDEX) {
+- int baud = cflag & CBAUD;
+- cflag &= ~CBAUD;
+- switch (baud) {
+- case B57600: baud = 0; break;
+- case B76800: baud = 1; break;
+- case B115200: baud = 2; break;
+- case B153600: baud = 3; break;
+- case B230400: baud = 4; break;
+- case B307200: baud = 5; break;
+- case B460800: baud = 6; break;
+- case B614400: baud = 7; break;
+- case B921600: baud = 8; break;
+-#if 0
+- case B1843200: baud = 9; break;
+-#endif
+- }
+- cflag |= 0x200000 | baud;
+- }
+- return cflag;
+-}
+-
+-static inline int linux_to_solaris_termio(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+- struct solaris_termio __user *p = A(arg);
+- int ret;
+-
+- ret = sys_ioctl(fd, cmd, (unsigned long)p);
+- if (!ret) {
+- u32 cflag;
+-
+- if (__get_user (cflag, &p->c_cflag))
+- return -EFAULT;
+- cflag = linux_to_solaris_cflag(cflag);
+- if (__put_user (cflag, &p->c_cflag))
+- return -EFAULT;
+- }
+- return ret;
+-}
+-
+-static int solaris_to_linux_termio(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+- int ret;
+- struct solaris_termio s;
+- mm_segment_t old_fs = get_fs();
+-
+- if (copy_from_user (&s, (struct solaris_termio __user *)A(arg), sizeof(struct solaris_termio)))
+- return -EFAULT;
+- s.c_cflag = solaris_to_linux_cflag(s.c_cflag);
+- set_fs(KERNEL_DS);
+- ret = sys_ioctl(fd, cmd, (unsigned long)&s);
+- set_fs(old_fs);
+- return ret;
+-}
+-
+-static inline int linux_to_solaris_termios(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+- int ret;
+- struct solaris_termios s;
+- mm_segment_t old_fs = get_fs();
+-
+- set_fs(KERNEL_DS);
+- ret = sys_ioctl(fd, cmd, (unsigned long)&s);
+- set_fs(old_fs);
+- if (!ret) {
+- struct solaris_termios __user *p = A(arg);
+- if (put_user (s.c_iflag, &p->c_iflag) ||
+- __put_user (s.c_oflag, &p->c_oflag) ||
+- __put_user (linux_to_solaris_cflag(s.c_cflag), &p->c_cflag) ||
+- __put_user (s.c_lflag, &p->c_lflag) ||
+- __copy_to_user (p->c_cc, s.c_cc, 16) ||
+- __clear_user (p->c_cc + 16, 2))
+- return -EFAULT;
+- }
+- return ret;
+-}
+-
+-static int solaris_to_linux_termios(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+- int ret;
+- struct solaris_termios s;
+- struct solaris_termios __user *p = A(arg);
+- mm_segment_t old_fs = get_fs();
+-
+- set_fs(KERNEL_DS);
+- ret = sys_ioctl(fd, TCGETS, (unsigned long)&s);
+- set_fs(old_fs);
+- if (ret) return ret;
+- if (put_user (s.c_iflag, &p->c_iflag) ||
+- __put_user (s.c_oflag, &p->c_oflag) ||
+- __put_user (s.c_cflag, &p->c_cflag) ||
+- __put_user (s.c_lflag, &p->c_lflag) ||
+- __copy_from_user (s.c_cc, p->c_cc, 16))
+- return -EFAULT;
+- s.c_cflag = solaris_to_linux_cflag(s.c_cflag);
+- set_fs(KERNEL_DS);
+- ret = sys_ioctl(fd, cmd, (unsigned long)&s);
+- set_fs(old_fs);
+- return ret;
+-}
+-
+-static inline int solaris_T(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+- switch (cmd & 0xff) {
+- case 1: /* TCGETA */
+- return linux_to_solaris_termio(fd, TCGETA, arg);
+- case 2: /* TCSETA */
+- return solaris_to_linux_termio(fd, TCSETA, arg);
+- case 3: /* TCSETAW */
+- return solaris_to_linux_termio(fd, TCSETAW, arg);
+- case 4: /* TCSETAF */
+- return solaris_to_linux_termio(fd, TCSETAF, arg);
+- case 5: /* TCSBRK */
+- return sys_ioctl(fd, TCSBRK, arg);
+- case 6: /* TCXONC */
+- return sys_ioctl(fd, TCXONC, arg);
+- case 7: /* TCFLSH */
+- return sys_ioctl(fd, TCFLSH, arg);
+- case 13: /* TCGETS */
+- return linux_to_solaris_termios(fd, TCGETS, arg);
+- case 14: /* TCSETS */
+- return solaris_to_linux_termios(fd, TCSETS, arg);
+- case 15: /* TCSETSW */
+- return solaris_to_linux_termios(fd, TCSETSW, arg);
+- case 16: /* TCSETSF */
+- return solaris_to_linux_termios(fd, TCSETSF, arg);
+- case 103: /* TIOCSWINSZ */
+- return sys_ioctl(fd, TIOCSWINSZ, arg);
+- case 104: /* TIOCGWINSZ */
+- return sys_ioctl(fd, TIOCGWINSZ, arg);
+- }
+- return -ENOSYS;
+-}
+-
+-static inline int solaris_t(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+- switch (cmd & 0xff) {
+- case 20: /* TIOCGPGRP */
+- return sys_ioctl(fd, TIOCGPGRP, arg);
+- case 21: /* TIOCSPGRP */
+- return sys_ioctl(fd, TIOCSPGRP, arg);
+- }
+- return -ENOSYS;
+-}
+-
+-/* }}} */
+-
+-/* A pseudo STREAMS support {{{ */
+-
+-struct strioctl {
+- int cmd, timeout, len;
+- u32 data;
+-};
+-
+-struct solaris_si_sockparams {
+- int sp_family;
+- int sp_type;
+- int sp_protocol;
+-};
+-
+-struct solaris_o_si_udata {
+- int tidusize;
+- int addrsize;
+- int optsize;
+- int etsdusize;
+- int servtype;
+- int so_state;
+- int so_options;
+- int tsdusize;
+-};
+-
+-struct solaris_si_udata {
+- int tidusize;
+- int addrsize;
+- int optsize;
+- int etsdusize;
+- int servtype;
+- int so_state;
+- int so_options;
+- int tsdusize;
+- struct solaris_si_sockparams sockparams;
+-};
+-
+-#define SOLARIS_MODULE_TIMOD 0
+-#define SOLARIS_MODULE_SOCKMOD 1
+-#define SOLARIS_MODULE_MAX 2
+-
+-static struct module_info {
+- const char *name;
+- /* can be expanded further if needed */
+-} module_table[ SOLARIS_MODULE_MAX + 1 ] = {
+- /* the ordering here must match the module numbers above! */
+- { "timod" },
+- { "sockmod" },
+- { NULL }
+-};
+-
+-static inline int solaris_sockmod(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+- struct inode *ino;
+- struct fdtable *fdt;
+- /* I wonder which of these tests are superfluous... --patrik */
+- rcu_read_lock();
+- fdt = files_fdtable(current->files);
+- if (! fdt->fd[fd] ||
+- ! fdt->fd[fd]->f_path.dentry ||
+- ! (ino = fdt->fd[fd]->f_path.dentry->d_inode) ||
+- ! S_ISSOCK(ino->i_mode)) {
+- rcu_read_unlock();
+- return TBADF;
+- }
+- rcu_read_unlock();
+-
+- switch (cmd & 0xff) {
+- case 109: /* SI_SOCKPARAMS */
+- {
+- struct solaris_si_sockparams si;
+- if (copy_from_user (&si, A(arg), sizeof(si)))
+- return (EFAULT << 8) | TSYSERR;
+-
+- /* Should we modify socket ino->socket_i.ops and type? */
+- return 0;
+- }
+- case 110: /* SI_GETUDATA */
+- {
+- int etsdusize, servtype;
+- struct solaris_si_udata __user *p = A(arg);
+- switch (SOCKET_I(ino)->type) {
+- case SOCK_STREAM:
+- etsdusize = 1;
+- servtype = 2;
+- break;
+- default:
+- etsdusize = -2;
+- servtype = 3;
+- break;
+- }
+- if (put_user(16384, &p->tidusize) ||
+- __put_user(sizeof(struct sockaddr), &p->addrsize) ||
+- __put_user(-1, &p->optsize) ||
+- __put_user(etsdusize, &p->etsdusize) ||
+- __put_user(servtype, &p->servtype) ||
+- __put_user(0, &p->so_state) ||
+- __put_user(0, &p->so_options) ||
+- __put_user(16384, &p->tsdusize) ||
+- __put_user(SOCKET_I(ino)->ops->family, &p->sockparams.sp_family) ||
+- __put_user(SOCKET_I(ino)->type, &p->sockparams.sp_type) ||
+- __put_user(SOCKET_I(ino)->ops->family, &p->sockparams.sp_protocol))
+- return (EFAULT << 8) | TSYSERR;
+- return 0;
+- }
+- case 101: /* O_SI_GETUDATA */
+- {
+- int etsdusize, servtype;
+- struct solaris_o_si_udata __user *p = A(arg);
+- switch (SOCKET_I(ino)->type) {
+- case SOCK_STREAM:
+- etsdusize = 1;
+- servtype = 2;
+- break;
+- default:
+- etsdusize = -2;
+- servtype = 3;
+- break;
+- }
+- if (put_user(16384, &p->tidusize) ||
+- __put_user(sizeof(struct sockaddr), &p->addrsize) ||
+- __put_user(-1, &p->optsize) ||
+- __put_user(etsdusize, &p->etsdusize) ||
+- __put_user(servtype, &p->servtype) ||
+- __put_user(0, &p->so_state) ||
+- __put_user(0, &p->so_options) ||
+- __put_user(16384, &p->tsdusize))
+- return (EFAULT << 8) | TSYSERR;
+- return 0;
+- }
+- case 102: /* SI_SHUTDOWN */
+- case 103: /* SI_LISTEN */
+- case 104: /* SI_SETMYNAME */
+- case 105: /* SI_SETPEERNAME */
+- case 106: /* SI_GETINTRANSIT */
+- case 107: /* SI_TCL_LINK */
+- case 108: /* SI_TCL_UNLINK */
+- ;
+- }
+- return TNOTSUPPORT;
+-}
+-
+-static inline int solaris_timod(unsigned int fd, unsigned int cmd, u32 arg,
+- int len, int __user *len_p)
+-{
+- int ret;
+-
+- switch (cmd & 0xff) {
+- case 141: /* TI_OPTMGMT */
+- {
+- int i;
+- u32 prim;
+- SOLD("TI_OPMGMT entry");
+- ret = timod_putmsg(fd, A(arg), len, NULL, -1, 0);
+- SOLD("timod_putmsg() returned");
+- if (ret)
+- return (-ret << 8) | TSYSERR;
+- i = MSG_HIPRI;
+- SOLD("calling timod_getmsg()");
+- ret = timod_getmsg(fd, A(arg), len, len_p, NULL, -1, NULL, &i);
+- SOLD("timod_getmsg() returned");
+- if (ret)
+- return (-ret << 8) | TSYSERR;
+- SOLD("ret ok");
+- if (get_user(prim, (u32 __user *)A(arg)))
+- return (EFAULT << 8) | TSYSERR;
+- SOLD("got prim");
+- if (prim == T_ERROR_ACK) {
+- u32 tmp, tmp2;
+- SOLD("prim is T_ERROR_ACK");
+- if (get_user(tmp, (u32 __user *)A(arg)+3) ||
+- get_user(tmp2, (u32 __user *)A(arg)+2))
+- return (EFAULT << 8) | TSYSERR;
+- return (tmp2 << 8) | tmp;
+- }
+- SOLD("TI_OPMGMT return 0");
+- return 0;
+- }
+- case 142: /* TI_BIND */
+- {
+- int i;
+- u32 prim;
+- SOLD("TI_BIND entry");
+- ret = timod_putmsg(fd, A(arg), len, NULL, -1, 0);
+- SOLD("timod_putmsg() returned");
+- if (ret)
+- return (-ret << 8) | TSYSERR;
+- len = 1024; /* Solaris allows arbitrary return size */
+- i = MSG_HIPRI;
+- SOLD("calling timod_getmsg()");
+- ret = timod_getmsg(fd, A(arg), len, len_p, NULL, -1, NULL, &i);
+- SOLD("timod_getmsg() returned");
+- if (ret)
+- return (-ret << 8) | TSYSERR;
+- SOLD("ret ok");
+- if (get_user(prim, (u32 __user *)A(arg)))
+- return (EFAULT << 8) | TSYSERR;
+- SOLD("got prim");
+- if (prim == T_ERROR_ACK) {
+- u32 tmp, tmp2;
+- SOLD("prim is T_ERROR_ACK");
+- if (get_user(tmp, (u32 __user *)A(arg)+3) ||
+- get_user(tmp2, (u32 __user *)A(arg)+2))
+- return (EFAULT << 8) | TSYSERR;
+- return (tmp2 << 8) | tmp;
+- }
+- SOLD("no ERROR_ACK requested");
+- if (prim != T_OK_ACK)
+- return TBADSEQ;
+- SOLD("OK_ACK requested");
+- i = MSG_HIPRI;
+- SOLD("calling timod_getmsg()");
+- ret = timod_getmsg(fd, A(arg), len, len_p, NULL, -1, NULL, &i);
+- SOLD("timod_getmsg() returned");
+- if (ret)
+- return (-ret << 8) | TSYSERR;
+- SOLD("TI_BIND return ok");
+- return 0;
+- }
+- case 140: /* TI_GETINFO */
+- case 143: /* TI_UNBIND */
+- case 144: /* TI_GETMYNAME */
+- case 145: /* TI_GETPEERNAME */
+- case 146: /* TI_SETMYNAME */
+- case 147: /* TI_SETPEERNAME */
+- ;
+- }
+- return TNOTSUPPORT;
+-}
+-
+-static inline int solaris_S(struct file *filp, unsigned int fd, unsigned int cmd, u32 arg)
+-{
+- char *p;
+- int ret;
+- mm_segment_t old_fs;
+- struct strioctl si;
+- struct inode *ino;
+- struct sol_socket_struct *sock;
+- struct module_info *mi;
+-
+- ino = filp->f_path.dentry->d_inode;
+- if (!S_ISSOCK(ino->i_mode))
+- return -EBADF;
+- sock = filp->private_data;
+- if (! sock) {
+- printk("solaris_S: NULL private_data\n");
+- return -EBADF;
+- }
+- if (sock->magic != SOLARIS_SOCKET_MAGIC) {
+- printk("solaris_S: invalid magic\n");
+- return -EBADF;
+- }
+-
+-
+- switch (cmd & 0xff) {
+- case 1: /* I_NREAD */
+- return -ENOSYS;
+- case 2: /* I_PUSH */
+- {
+- p = getname (A(arg));
+- if (IS_ERR (p))
+- return PTR_ERR(p);
+- ret = -EINVAL;
+- for (mi = module_table; mi->name; mi++) {
+- if (strcmp(mi->name, p) == 0) {
+- sol_module m;
+- if (sock->modcount >= MAX_NR_STREAM_MODULES) {
+- ret = -ENXIO;
+- break;
+- }
+- m = (sol_module) (mi - module_table);
+- sock->module[sock->modcount++] = m;
+- ret = 0;
+- break;
+- }
+- }
+- putname (p);
+- return ret;
+- }
+- case 3: /* I_POP */
+- if (sock->modcount <= 0) return -EINVAL;
+- sock->modcount--;
+- return 0;
+- case 4: /* I_LOOK */
+- {
+- const char *p;
+- if (sock->modcount <= 0) return -EINVAL;
+- p = module_table[(unsigned)sock->module[sock->modcount]].name;
+- if (copy_to_user (A(arg), p, strlen(p)))
+- return -EFAULT;
+- return 0;
+- }
+- case 5: /* I_FLUSH */
+- return 0;
+- case 8: /* I_STR */
+- if (copy_from_user(&si, A(arg), sizeof(struct strioctl)))
+- return -EFAULT;
+- /* We ignore what module is actually at the top of stack. */
+- switch ((si.cmd >> 8) & 0xff) {
+- case 'I':
+- return solaris_sockmod(fd, si.cmd, si.data);
+- case 'T':
+- return solaris_timod(fd, si.cmd, si.data, si.len,
+- &((struct strioctl __user *)A(arg))->len);
+- default:
+- return solaris_ioctl(fd, si.cmd, si.data);
+- }
+- case 9: /* I_SETSIG */
+- return sys_ioctl(fd, FIOSETOWN, current->pid);
+- case 10: /* I_GETSIG */
+- old_fs = get_fs();
+- set_fs(KERNEL_DS);
+- sys_ioctl(fd, FIOGETOWN, (unsigned long)&ret);
+- set_fs(old_fs);
+- if (ret == current->pid) return 0x3ff;
+- else return -EINVAL;
+- case 11: /* I_FIND */
+- {
+- int i;
+- p = getname (A(arg));
+- if (IS_ERR (p))
+- return PTR_ERR(p);
+- ret = 0;
+- for (i = 0; i < sock->modcount; i++) {
+- unsigned m = sock->module[i];
+- if (strcmp(module_table[m].name, p) == 0) {
+- ret = 1;
+- break;
+- }
+- }
+- putname (p);
+- return ret;
+- }
+- case 19: /* I_SWROPT */
+- case 32: /* I_SETCLTIME */
+- return 0; /* Lie */
+- }
+- return -ENOSYS;
+-}
+-
+-static inline int solaris_s(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+- switch (cmd & 0xff) {
+- case 0: /* SIOCSHIWAT */
+- case 2: /* SIOCSLOWAT */
+- return 0; /* We don't support them */
+- case 1: /* SIOCGHIWAT */
+- case 3: /* SIOCGLOWAT */
+- if (put_user (0, (u32 __user *)A(arg)))
+- return -EFAULT;
+- return 0; /* Lie */
+- case 7: /* SIOCATMARK */
+- return sys_ioctl(fd, SIOCATMARK, arg);
+- case 8: /* SIOCSPGRP */
+- return sys_ioctl(fd, SIOCSPGRP, arg);
+- case 9: /* SIOCGPGRP */
+- return sys_ioctl(fd, SIOCGPGRP, arg);
+- }
+- return -ENOSYS;
+-}
+-
+-static inline int solaris_r(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+- switch (cmd & 0xff) {
+- case 10: /* SIOCADDRT */
+- return compat_sys_ioctl(fd, SIOCADDRT, arg);
+- case 11: /* SIOCDELRT */
+- return compat_sys_ioctl(fd, SIOCDELRT, arg);
+- }
+- return -ENOSYS;
+-}
+-
+-static inline int solaris_i(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+- switch (cmd & 0xff) {
+- case 12: /* SIOCSIFADDR */
+- return compat_sys_ioctl(fd, SIOCSIFADDR, arg);
+- case 13: /* SIOCGIFADDR */
+- return compat_sys_ioctl(fd, SIOCGIFADDR, arg);
+- case 14: /* SIOCSIFDSTADDR */
+- return compat_sys_ioctl(fd, SIOCSIFDSTADDR, arg);
+- case 15: /* SIOCGIFDSTADDR */
+- return compat_sys_ioctl(fd, SIOCGIFDSTADDR, arg);
+- case 16: /* SIOCSIFFLAGS */
+- return compat_sys_ioctl(fd, SIOCSIFFLAGS, arg);
+- case 17: /* SIOCGIFFLAGS */
+- return compat_sys_ioctl(fd, SIOCGIFFLAGS, arg);
+- case 18: /* SIOCSIFMEM */
+- return compat_sys_ioctl(fd, SIOCSIFMEM, arg);
+- case 19: /* SIOCGIFMEM */
+- return compat_sys_ioctl(fd, SIOCGIFMEM, arg);
+- case 20: /* SIOCGIFCONF */
+- return compat_sys_ioctl(fd, SIOCGIFCONF, arg);
+- case 21: /* SIOCSIFMTU */
+- return compat_sys_ioctl(fd, SIOCSIFMTU, arg);
+- case 22: /* SIOCGIFMTU */
+- return compat_sys_ioctl(fd, SIOCGIFMTU, arg);
+- case 23: /* SIOCGIFBRDADDR */
+- return compat_sys_ioctl(fd, SIOCGIFBRDADDR, arg);
+- case 24: /* SIOCSIFBRDADDR */
+- return compat_sys_ioctl(fd, SIOCSIFBRDADDR, arg);
+- case 25: /* SIOCGIFNETMASK */
+- return compat_sys_ioctl(fd, SIOCGIFNETMASK, arg);
+- case 26: /* SIOCSIFNETMASK */
+- return compat_sys_ioctl(fd, SIOCSIFNETMASK, arg);
+- case 27: /* SIOCGIFMETRIC */
+- return compat_sys_ioctl(fd, SIOCGIFMETRIC, arg);
+- case 28: /* SIOCSIFMETRIC */
+- return compat_sys_ioctl(fd, SIOCSIFMETRIC, arg);
+- case 30: /* SIOCSARP */
+- return compat_sys_ioctl(fd, SIOCSARP, arg);
+- case 31: /* SIOCGARP */
+- return compat_sys_ioctl(fd, SIOCGARP, arg);
+- case 32: /* SIOCDARP */
+- return compat_sys_ioctl(fd, SIOCDARP, arg);
+- case 52: /* SIOCGETNAME */
+- case 53: /* SIOCGETPEER */
+- {
+- struct sockaddr uaddr;
+- int uaddr_len = sizeof(struct sockaddr), ret;
+- long args[3];
+- mm_segment_t old_fs = get_fs();
+- int (*sys_socketcall)(int, unsigned long *) =
+- (int (*)(int, unsigned long *))SYS(socketcall);
+-
+- args[0] = fd; args[1] = (long)&uaddr; args[2] = (long)&uaddr_len;
+- set_fs(KERNEL_DS);
+- ret = sys_socketcall(((cmd & 0xff) == 52) ? SYS_GETSOCKNAME : SYS_GETPEERNAME,
+- args);
+- set_fs(old_fs);
+- if (ret >= 0) {
+- if (copy_to_user(A(arg), &uaddr, uaddr_len))
+- return -EFAULT;
+- }
+- return ret;
+- }
+-#if 0
+- case 86: /* SIOCSOCKSYS */
+- return socksys_syscall(fd, arg);
+-#endif
+- case 87: /* SIOCGIFNUM */
+- {
+- struct net_device *d;
+- int i = 0;
+-
+- read_lock_bh(&dev_base_lock);
+- for_each_netdev(&init_net, d)
+- i++;
+- read_unlock_bh(&dev_base_lock);
+-
+- if (put_user (i, (int __user *)A(arg)))
+- return -EFAULT;
+- return 0;
+- }
+- }
+- return -ENOSYS;
+-}
+-
+-static int solaris_m(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+- int ret;
+-
+- switch (cmd & 0xff) {
+- case 1: /* MTIOCTOP */
+- ret = sys_ioctl(fd, MTIOCTOP, (unsigned long)&arg);
+- break;
+- case 2: /* MTIOCGET */
+- ret = sys_ioctl(fd, MTIOCGET, (unsigned long)&arg);
+- break;
+- case 3: /* MTIOCGETDRIVETYPE */
+- case 4: /* MTIOCPERSISTENT */
+- case 5: /* MTIOCPERSISTENTSTATUS */
+- case 6: /* MTIOCLRERR */
+- case 7: /* MTIOCGUARANTEEDORDER */
+- case 8: /* MTIOCRESERVE */
+- case 9: /* MTIOCRELEASE */
+- case 10: /* MTIOCFORCERESERVE */
+- case 13: /* MTIOCSTATE */
+- case 14: /* MTIOCREADIGNOREILI */
+- case 15: /* MTIOCREADIGNOREEOFS */
+- case 16: /* MTIOCSHORTFMK */
+- default:
+- ret = -ENOSYS; /* linux doesn't support these */
+- break;
+- };
+-
+- return ret;
+-}
+-
+-static int solaris_O(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+- int ret = -EINVAL;
+-
+- switch (cmd & 0xff) {
+- case 1: /* OPROMGETOPT */
+- ret = sys_ioctl(fd, OPROMGETOPT, arg);
+- break;
+- case 2: /* OPROMSETOPT */
+- ret = sys_ioctl(fd, OPROMSETOPT, arg);
+- break;
+- case 3: /* OPROMNXTOPT */
+- ret = sys_ioctl(fd, OPROMNXTOPT, arg);
+- break;
+- case 4: /* OPROMSETOPT2 */
+- ret = sys_ioctl(fd, OPROMSETOPT2, arg);
+- break;
+- case 5: /* OPROMNEXT */
+- ret = sys_ioctl(fd, OPROMNEXT, arg);
+- break;
+- case 6: /* OPROMCHILD */
+- ret = sys_ioctl(fd, OPROMCHILD, arg);
+- break;
+- case 7: /* OPROMGETPROP */
+- ret = sys_ioctl(fd, OPROMGETPROP, arg);
+- break;
+- case 8: /* OPROMNXTPROP */
+- ret = sys_ioctl(fd, OPROMNXTPROP, arg);
+- break;
+- case 9: /* OPROMU2P */
+- ret = sys_ioctl(fd, OPROMU2P, arg);
+- break;
+- case 10: /* OPROMGETCONS */
+- ret = sys_ioctl(fd, OPROMGETCONS, arg);
+- break;
+- case 11: /* OPROMGETFBNAME */
+- ret = sys_ioctl(fd, OPROMGETFBNAME, arg);
+- break;
+- case 12: /* OPROMGETBOOTARGS */
+- ret = sys_ioctl(fd, OPROMGETBOOTARGS, arg);
+- break;
+- case 13: /* OPROMGETVERSION */
+- case 14: /* OPROMPATH2DRV */
+- case 15: /* OPROMDEV2PROMNAME */
+- case 16: /* OPROMPROM2DEVNAME */
+- case 17: /* OPROMGETPROPLEN */
+- default:
+- ret = -EINVAL;
+- break;
+- };
+- return ret;
+-}
+-
+-/* }}} */
+-
+-asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
+-{
+- struct file *filp;
+- int error = -EBADF;
+-
+- filp = fget(fd);
+- if (!filp)
+- goto out;
+-
+- lock_kernel();
+- error = -EFAULT;
+- switch ((cmd >> 8) & 0xff) {
+- case 'S': error = solaris_S(filp, fd, cmd, arg); break;
+- case 'T': error = solaris_T(fd, cmd, arg); break;
+- case 'i': error = solaris_i(fd, cmd, arg); break;
+- case 'r': error = solaris_r(fd, cmd, arg); break;
+- case 's': error = solaris_s(fd, cmd, arg); break;
+- case 't': error = solaris_t(fd, cmd, arg); break;
+- case 'f': error = sys_ioctl(fd, cmd, arg); break;
+- case 'm': error = solaris_m(fd, cmd, arg); break;
+- case 'O': error = solaris_O(fd, cmd, arg); break;
+- default:
+- error = -ENOSYS;
+- break;
+- }
+- unlock_kernel();
+- fput(filp);
+-out:
+- if (error == -ENOSYS) {
+- unsigned char c = cmd>>8;
+-
+- if (c < ' ' || c > 126) c = '.';
+- printk("solaris_ioctl: Unknown cmd fd(%d) cmd(%08x '%c') arg(%08x)\n",
+- (int)fd, (unsigned int)cmd, c, (unsigned int)arg);
+- error = -EINVAL;
+- }
+- return error;
+-}
+diff --git a/arch/sparc64/solaris/ipc.c b/arch/sparc64/solaris/ipc.c
+deleted file mode 100644
+index 499135f..0000000
+--- a/arch/sparc64/solaris/ipc.c
++++ /dev/null
+@@ -1,126 +0,0 @@
+-/* $Id: ipc.c,v 1.5 1999/12/09 00:41:00 davem Exp $
+- * ipc.c: Solaris IPC emulation
+- *
+- * Copyright (C) 1997 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/types.h>
+-#include <linux/wait.h>
+-#include <linux/mm.h>
+-#include <linux/shm.h>
+-#include <linux/sem.h>
+-#include <linux/msg.h>
+-#include <linux/ipc.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/string.h>
+-
+-#include "conv.h"
+-
+-struct solaris_ipc_perm {
+- s32 uid;
+- s32 gid;
+- s32 cuid;
+- s32 cgid;
+- u32 mode;
+- u32 seq;
+- int key;
+- s32 pad[4];
+-};
+-
+-struct solaris_shmid_ds {
+- struct solaris_ipc_perm shm_perm;
+- int shm_segsz;
+- u32 shm_amp;
+- unsigned short shm_lkcnt;
+- char __padxx[2];
+- s32 shm_lpid;
+- s32 shm_cpid;
+- u32 shm_nattch;
+- u32 shm_cnattch;
+- s32 shm_atime;
+- s32 shm_pad1;
+- s32 shm_dtime;
+- s32 shm_pad2;
+- s32 shm_ctime;
+- s32 shm_pad3;
+- unsigned short shm_cv;
+- char shm_pad4[2];
+- u32 shm_sptas;
+- s32 shm_pad5[2];
+-};
+-
+-asmlinkage long solaris_shmsys(int cmd, u32 arg1, u32 arg2, u32 arg3)
+-{
+- int (*sys_ipc)(unsigned,int,int,unsigned long,void __user *,long) =
+- (int (*)(unsigned,int,int,unsigned long,void __user *,long))SYS(ipc);
+- mm_segment_t old_fs;
+- unsigned long raddr;
+- int ret;
+-
+- switch (cmd) {
+- case 0: /* shmat */
+- old_fs = get_fs();
+- set_fs(KERNEL_DS);
+- ret = sys_ipc(SHMAT, arg1, arg3 & ~0x4000, (unsigned long)&raddr, A(arg2), 0);
+- set_fs(old_fs);
+- if (ret >= 0) return (u32)raddr;
+- else return ret;
+- case 1: /* shmctl */
+- switch (arg2) {
+- case 3: /* SHM_LOCK */
+- case 4: /* SHM_UNLOCK */
+- return sys_ipc(SHMCTL, arg1, (arg2 == 3) ? SHM_LOCK : SHM_UNLOCK, 0, NULL, 0);
+- case 10: /* IPC_RMID */
+- return sys_ipc(SHMCTL, arg1, IPC_RMID, 0, NULL, 0);
+- case 11: /* IPC_SET */
+- {
+- struct shmid_ds s;
+- struct solaris_shmid_ds __user *p = A(arg3);
+-
+- if (get_user (s.shm_perm.uid, &p->shm_perm.uid) ||
+- __get_user (s.shm_perm.gid, &p->shm_perm.gid) ||
+- __get_user (s.shm_perm.mode, &p->shm_perm.mode))
+- return -EFAULT;
+- old_fs = get_fs();
+- set_fs(KERNEL_DS);
+- ret = sys_ipc(SHMCTL, arg1, IPC_SET, 0, &s, 0);
+- set_fs(old_fs);
+- return ret;
+- }
+- case 12: /* IPC_STAT */
+- {
+- struct shmid_ds s;
+- struct solaris_shmid_ds __user *p = A(arg3);
+-
+- old_fs = get_fs();
+- set_fs(KERNEL_DS);
+- ret = sys_ipc(SHMCTL, arg1, IPC_SET, 0, &s, 0);
+- set_fs(old_fs);
+- if (put_user (s.shm_perm.uid, &(p->shm_perm.uid)) ||
+- __put_user (s.shm_perm.gid, &(p->shm_perm.gid)) ||
+- __put_user (s.shm_perm.cuid, &(p->shm_perm.cuid)) ||
+- __put_user (s.shm_perm.cgid, &(p->shm_perm.cgid)) ||
+- __put_user (s.shm_perm.mode, &(p->shm_perm.mode)) ||
+- __put_user (s.shm_perm.seq, &(p->shm_perm.seq)) ||
+- __put_user (s.shm_perm.key, &(p->shm_perm.key)) ||
+- __put_user (s.shm_segsz, &(p->shm_segsz)) ||
+- __put_user (s.shm_lpid, &(p->shm_lpid)) ||
+- __put_user (s.shm_cpid, &(p->shm_cpid)) ||
+- __put_user (s.shm_nattch, &(p->shm_nattch)) ||
+- __put_user (s.shm_atime, &(p->shm_atime)) ||
+- __put_user (s.shm_dtime, &(p->shm_dtime)) ||
+- __put_user (s.shm_ctime, &(p->shm_ctime)))
+- return -EFAULT;
+- return ret;
+- }
+- default: return -EINVAL;
+- }
+- case 2: /* shmdt */
+- return sys_ipc(SHMDT, 0, 0, 0, A(arg1), 0);
+- case 3: /* shmget */
+- return sys_ipc(SHMGET, arg1, arg2, arg3, NULL, 0);
+- }
+- return -EINVAL;
+-}
+diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
+deleted file mode 100644
+index d3e48e9..0000000
+--- a/arch/sparc64/solaris/misc.c
++++ /dev/null
+@@ -1,786 +0,0 @@
+-/* $Id: misc.c,v 1.36 2002/02/09 19:49:31 davem Exp $
+- * misc.c: Miscellaneous syscall emulation for Solaris
+- *
+- * Copyright (C) 1997,1998 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
+- */
+-
+-#include <linux/module.h>
+-#include <linux/types.h>
+-#include <linux/utsname.h>
+-#include <linux/limits.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+-#include <linux/tty.h>
+-#include <linux/mman.h>
+-#include <linux/file.h>
+-#include <linux/timex.h>
+-#include <linux/major.h>
+-#include <linux/compat.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/string.h>
+-#include <asm/oplib.h>
+-#include <asm/idprom.h>
+-#include <asm/smp.h>
+-#include <asm/prom.h>
+-
+-#include "conv.h"
+-
+-/* Conversion from Linux to Solaris errnos. 0-34 are identity mapped.
+- Some Linux errnos (EPROCLIM, EDOTDOT, ERREMOTE, EUCLEAN, ENOTNAM,
+- ENAVAIL, EISNAM, EREMOTEIO, ENOMEDIUM, EMEDIUMTYPE) have no Solaris
+- equivalents. I return EINVAL in that case, which is very wrong. If
+- someone suggest a better value for them, you're welcomed.
+- On the other side, Solaris ECANCELED and ENOTSUP have no Linux equivalents,
+- but that doesn't matter here. --jj */
+-int solaris_err_table[] = {
+-/* 0 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+-/* 10 */ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+-/* 20 */ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+-/* 30 */ 30, 31, 32, 33, 34, 22, 150, 149, 95, 96,
+-/* 40 */ 97, 98, 99, 120, 121, 122, 123, 124, 125, 126,
+-/* 50 */ 127, 128, 129, 130, 131, 132, 133, 134, 143, 144,
+-/* 60 */ 145, 146, 90, 78, 147, 148, 93, 22, 94, 49,
+-/* 70 */ 151, 66, 60, 62, 63, 35, 77, 36, 45, 46,
+-/* 80 */ 64, 22, 67, 68, 69, 70, 71, 74, 22, 82,
+-/* 90 */ 89, 92, 79, 81, 37, 38, 39, 40, 41, 42,
+-/* 100 */ 43, 44, 50, 51, 52, 53, 54, 55, 56, 57,
+-/* 110 */ 87, 61, 84, 65, 83, 80, 91, 22, 22, 22,
+-/* 120 */ 22, 22, 88, 86, 85, 22, 22,
+-};
+-
+-#define SOLARIS_NR_OPEN 256
+-
+-static u32 do_solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u64 off)
+-{
+- struct file *file = NULL;
+- unsigned long retval, ret_type;
+-
+- /* Do we need it here? */
+- set_personality(PER_SVR4);
+- if (flags & MAP_NORESERVE) {
+- static int cnt;
+-
+- if (cnt < 5) {
+- printk("%s: unimplemented Solaris MAP_NORESERVE mmap() flag\n",
+- current->comm);
+- cnt++;
+- }
+- flags &= ~MAP_NORESERVE;
+- }
+- retval = -EBADF;
+- if(!(flags & MAP_ANONYMOUS)) {
+- if(fd >= SOLARIS_NR_OPEN)
+- goto out;
+- file = fget(fd);
+- if (!file)
+- goto out;
+- else {
+- struct inode * inode = file->f_path.dentry->d_inode;
+- if(imajor(inode) == MEM_MAJOR &&
+- iminor(inode) == 5) {
+- flags |= MAP_ANONYMOUS;
+- fput(file);
+- file = NULL;
+- }
+- }
+- }
+-
+- retval = -EINVAL;
+- len = PAGE_ALIGN(len);
+- if(!(flags & MAP_FIXED))
+- addr = 0;
+- else if (len > STACK_TOP32 || addr > STACK_TOP32 - len)
+- goto out_putf;
+- ret_type = flags & _MAP_NEW;
+- flags &= ~_MAP_NEW;
+-
+- down_write(¤t->mm->mmap_sem);
+- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+- retval = do_mmap(file,
+- (unsigned long) addr, (unsigned long) len,
+- (unsigned long) prot, (unsigned long) flags, off);
+- up_write(¤t->mm->mmap_sem);
+- if(!ret_type)
+- retval = ((retval < STACK_TOP32) ? 0 : retval);
+-
+-out_putf:
+- if (file)
+- fput(file);
+-out:
+- return (u32) retval;
+-}
+-
+-asmlinkage u32 solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 off)
+-{
+- return do_solaris_mmap(addr, len, prot, flags, fd, (u64) off);
+-}
+-
+-asmlinkage u32 solaris_mmap64(struct pt_regs *regs, u32 len, u32 prot, u32 flags, u32 fd, u32 offhi)
+-{
+- u32 offlo;
+-
+- if (regs->u_regs[UREG_G1]) {
+- if (get_user (offlo, (u32 __user *)(long)((u32)regs->u_regs[UREG_I6] + 0x5c)))
+- return -EFAULT;
+- } else {
+- if (get_user (offlo, (u32 __user *)(long)((u32)regs->u_regs[UREG_I6] + 0x60)))
+- return -EFAULT;
+- }
+- return do_solaris_mmap((u32)regs->u_regs[UREG_I0], len, prot, flags, fd, (((u64)offhi)<<32)|offlo);
+-}
+-
+-asmlinkage int solaris_brk(u32 brk)
+-{
+- int (*sunos_brk)(u32) = (int (*)(u32))SUNOS(17);
+-
+- return sunos_brk(brk);
+-}
+-
+-static int __set_utsfield(char __user *to, int to_size,
+- const char *from, int from_size,
+- int dotchop, int countfrom)
+-{
+- int len = countfrom ? (to_size > from_size ?
+- from_size : to_size) : to_size;
+- int off;
+-
+- if (copy_to_user(to, from, len))
+- return -EFAULT;
+-
+- off = len < to_size? len: len - 1;
+- if (dotchop) {
+- const char *p = strnchr(from, len, '.');
+- if (p) off = p - from;
+- }
+-
+- if (__put_user('\0', to + off))
+- return -EFAULT;
+-
+- return 0;
+-}
+-
+-#define set_utsfield(to, from, dotchop, countfrom) \
+- __set_utsfield((to), sizeof(to), \
+- (from), sizeof(from), \
+- (dotchop), (countfrom))
+-
+-struct sol_uname {
+- char sysname[9];
+- char nodename[9];
+- char release[9];
+- char version[9];
+- char machine[9];
+-};
+-
+-struct sol_utsname {
+- char sysname[257];
+- char nodename[257];
+- char release[257];
+- char version[257];
+- char machine[257];
+-};
+-
+-static char *machine(void)
+-{
+- switch (sparc_cpu_model) {
+- case sun4: return "sun4";
+- case sun4c: return "sun4c";
+- case sun4e: return "sun4e";
+- case sun4m: return "sun4m";
+- case sun4d: return "sun4d";
+- case sun4u: return "sun4u";
+- default: return "sparc";
+- }
+-}
+-
+-static char *platform(char *buffer, int sz)
+-{
+- struct device_node *dp = of_find_node_by_path("/");
+- int len;
+-
+- *buffer = 0;
+- len = strlen(dp->name);
+- if (len > sz)
+- len = sz;
+- memcpy(buffer, dp->name, len);
+- buffer[len] = 0;
+- if (*buffer) {
+- char *p;
+-
+- for (p = buffer; *p; p++)
+- if (*p == '/' || *p == ' ') *p = '_';
+- return buffer;
+- }
+-
+- return "sun4u";
+-}
+-
+-static char *serial(char *buffer, int sz)
+-{
+- struct device_node *dp = of_find_node_by_path("/options");
+- int len;
+-
+- *buffer = 0;
+- if (dp) {
+- const char *val =
+- of_get_property(dp, "system-board-serial#", &len);
+-
+- if (val && len > 0) {
+- if (len > sz)
+- len = sz;
+- memcpy(buffer, val, len);
+- buffer[len] = 0;
+- }
+- }
+- if (!*buffer)
+- return "4512348717234";
+- else
+- return buffer;
+-}
+-
+-asmlinkage int solaris_utssys(u32 buf, u32 flags, int which, u32 buf2)
+-{
+- struct sol_uname __user *v = A(buf);
+- int err;
+-
+- switch (which) {
+- case 0: /* old uname */
+- /* Let's cheat */
+- err = set_utsfield(v->sysname, "SunOS", 1, 0);
+- down_read(&uts_sem);
+- err |= set_utsfield(v->nodename, utsname()->nodename,
+- 1, 1);
+- up_read(&uts_sem);
+- err |= set_utsfield(v->release, "2.6", 0, 0);
+- err |= set_utsfield(v->version, "Generic", 0, 0);
+- err |= set_utsfield(v->machine, machine(), 0, 0);
+- return (err ? -EFAULT : 0);
+- case 2: /* ustat */
+- return -ENOSYS;
+- case 3: /* fusers */
+- return -ENOSYS;
+- default:
+- return -ENOSYS;
+- }
+-}
+-
+-asmlinkage int solaris_utsname(u32 buf)
+-{
+- struct sol_utsname __user *v = A(buf);
+- int err;
+-
+- /* Why should we not lie a bit? */
+- down_read(&uts_sem);
+- err = set_utsfield(v->sysname, "SunOS", 0, 0);
+- err |= set_utsfield(v->nodename, utsname()->nodename, 1, 1);
+- err |= set_utsfield(v->release, "5.6", 0, 0);
+- err |= set_utsfield(v->version, "Generic", 0, 0);
+- err |= set_utsfield(v->machine, machine(), 0, 0);
+- up_read(&uts_sem);
+-
+- return (err ? -EFAULT : 0);
+-}
+-
+-#define SI_SYSNAME 1 /* return name of operating system */
+-#define SI_HOSTNAME 2 /* return name of node */
+-#define SI_RELEASE 3 /* return release of operating system */
+-#define SI_VERSION 4 /* return version field of utsname */
+-#define SI_MACHINE 5 /* return kind of machine */
+-#define SI_ARCHITECTURE 6 /* return instruction set arch */
+-#define SI_HW_SERIAL 7 /* return hardware serial number */
+-#define SI_HW_PROVIDER 8 /* return hardware manufacturer */
+-#define SI_SRPC_DOMAIN 9 /* return secure RPC domain */
+-#define SI_PLATFORM 513 /* return platform identifier */
+-
+-asmlinkage int solaris_sysinfo(int cmd, u32 buf, s32 count)
+-{
+- char *p, *q, *r;
+- char buffer[256];
+- int len;
+-
+- /* Again, we cheat :)) */
+- switch (cmd) {
+- case SI_SYSNAME: r = "SunOS"; break;
+- case SI_HOSTNAME:
+- r = buffer + 256;
+- down_read(&uts_sem);
+- for (p = utsname()->nodename, q = buffer;
+- q < r && *p && *p != '.'; *q++ = *p++);
+- up_read(&uts_sem);
+- *q = 0;
+- r = buffer;
+- break;
+- case SI_RELEASE: r = "5.6"; break;
+- case SI_MACHINE: r = machine(); break;
+- case SI_ARCHITECTURE: r = "sparc"; break;
+- case SI_HW_PROVIDER: r = "Sun_Microsystems"; break;
+- case SI_HW_SERIAL: r = serial(buffer, sizeof(buffer)); break;
+- case SI_PLATFORM: r = platform(buffer, sizeof(buffer)); break;
+- case SI_SRPC_DOMAIN: r = ""; break;
+- case SI_VERSION: r = "Generic"; break;
+- default: return -EINVAL;
+- }
+- len = strlen(r) + 1;
+- if (count < len) {
+- if (copy_to_user(A(buf), r, count - 1) ||
+- __put_user(0, (char __user *)A(buf) + count - 1))
+- return -EFAULT;
+- } else {
+- if (copy_to_user(A(buf), r, len))
+- return -EFAULT;
+- }
+- return len;
+-}
+-
+-#define SOLARIS_CONFIG_NGROUPS 2
+-#define SOLARIS_CONFIG_CHILD_MAX 3
+-#define SOLARIS_CONFIG_OPEN_FILES 4
+-#define SOLARIS_CONFIG_POSIX_VER 5
+-#define SOLARIS_CONFIG_PAGESIZE 6
+-#define SOLARIS_CONFIG_CLK_TCK 7
+-#define SOLARIS_CONFIG_XOPEN_VER 8
+-#define SOLARIS_CONFIG_PROF_TCK 10
+-#define SOLARIS_CONFIG_NPROC_CONF 11
+-#define SOLARIS_CONFIG_NPROC_ONLN 12
+-#define SOLARIS_CONFIG_AIO_LISTIO_MAX 13
+-#define SOLARIS_CONFIG_AIO_MAX 14
+-#define SOLARIS_CONFIG_AIO_PRIO_DELTA_MAX 15
+-#define SOLARIS_CONFIG_DELAYTIMER_MAX 16
+-#define SOLARIS_CONFIG_MQ_OPEN_MAX 17
+-#define SOLARIS_CONFIG_MQ_PRIO_MAX 18
+-#define SOLARIS_CONFIG_RTSIG_MAX 19
+-#define SOLARIS_CONFIG_SEM_NSEMS_MAX 20
+-#define SOLARIS_CONFIG_SEM_VALUE_MAX 21
+-#define SOLARIS_CONFIG_SIGQUEUE_MAX 22
+-#define SOLARIS_CONFIG_SIGRT_MIN 23
+-#define SOLARIS_CONFIG_SIGRT_MAX 24
+-#define SOLARIS_CONFIG_TIMER_MAX 25
+-#define SOLARIS_CONFIG_PHYS_PAGES 26
+-#define SOLARIS_CONFIG_AVPHYS_PAGES 27
+-
+-asmlinkage int solaris_sysconf(int id)
+-{
+- switch (id) {
+- case SOLARIS_CONFIG_NGROUPS: return NGROUPS_MAX;
+- case SOLARIS_CONFIG_CHILD_MAX:
+- return current->signal->rlim[RLIMIT_NPROC].rlim_cur;
+- case SOLARIS_CONFIG_OPEN_FILES:
+- return current->signal->rlim[RLIMIT_NOFILE].rlim_cur;
+- case SOLARIS_CONFIG_POSIX_VER: return 199309;
+- case SOLARIS_CONFIG_PAGESIZE: return PAGE_SIZE;
+- case SOLARIS_CONFIG_XOPEN_VER: return 3;
+- case SOLARIS_CONFIG_CLK_TCK:
+- case SOLARIS_CONFIG_PROF_TCK:
+- return sparc64_get_clock_tick(smp_processor_id());
+-#ifdef CONFIG_SMP
+- case SOLARIS_CONFIG_NPROC_CONF: return NR_CPUS;
+- case SOLARIS_CONFIG_NPROC_ONLN: return num_online_cpus();
+-#else
+- case SOLARIS_CONFIG_NPROC_CONF: return 1;
+- case SOLARIS_CONFIG_NPROC_ONLN: return 1;
+-#endif
+- case SOLARIS_CONFIG_SIGRT_MIN: return 37;
+- case SOLARIS_CONFIG_SIGRT_MAX: return 44;
+- case SOLARIS_CONFIG_PHYS_PAGES:
+- case SOLARIS_CONFIG_AVPHYS_PAGES:
+- {
+- struct sysinfo s;
+-
+- si_meminfo(&s);
+- if (id == SOLARIS_CONFIG_PHYS_PAGES)
+- return s.totalram >>= PAGE_SHIFT;
+- else
+- return s.freeram >>= PAGE_SHIFT;
+- }
+- /* XXX support these as well -jj */
+- case SOLARIS_CONFIG_AIO_LISTIO_MAX: return -EINVAL;
+- case SOLARIS_CONFIG_AIO_MAX: return -EINVAL;
+- case SOLARIS_CONFIG_AIO_PRIO_DELTA_MAX: return -EINVAL;
+- case SOLARIS_CONFIG_DELAYTIMER_MAX: return -EINVAL;
+- case SOLARIS_CONFIG_MQ_OPEN_MAX: return -EINVAL;
+- case SOLARIS_CONFIG_MQ_PRIO_MAX: return -EINVAL;
+- case SOLARIS_CONFIG_RTSIG_MAX: return -EINVAL;
+- case SOLARIS_CONFIG_SEM_NSEMS_MAX: return -EINVAL;
+- case SOLARIS_CONFIG_SEM_VALUE_MAX: return -EINVAL;
+- case SOLARIS_CONFIG_SIGQUEUE_MAX: return -EINVAL;
+- case SOLARIS_CONFIG_TIMER_MAX: return -EINVAL;
+- default: return -EINVAL;
+- }
+-}
+-
+-asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid)
+-{
+- int ret;
+-
+- switch (cmd) {
+- case 0: /* getpgrp */
+- return task_pgrp_vnr(current);
+- case 1: /* setpgrp */
+- {
+- int (*sys_setpgid)(pid_t,pid_t) =
+- (int (*)(pid_t,pid_t))SYS(setpgid);
+-
+- /* can anyone explain me the difference between
+- Solaris setpgrp and setsid? */
+- ret = sys_setpgid(0, 0);
+- if (ret) return ret;
+- proc_clear_tty(current);
+- return task_pgrp_vnr(current);
+- }
+- case 2: /* getsid */
+- {
+- int (*sys_getsid)(pid_t) = (int (*)(pid_t))SYS(getsid);
+- return sys_getsid(pid);
+- }
+- case 3: /* setsid */
+- {
+- int (*sys_setsid)(void) = (int (*)(void))SYS(setsid);
+- return sys_setsid();
+- }
+- case 4: /* getpgid */
+- {
+- int (*sys_getpgid)(pid_t) = (int (*)(pid_t))SYS(getpgid);
+- return sys_getpgid(pid);
+- }
+- case 5: /* setpgid */
+- {
+- int (*sys_setpgid)(pid_t,pid_t) =
+- (int (*)(pid_t,pid_t))SYS(setpgid);
+- return sys_setpgid(pid,pgid);
+- }
+- }
+- return -EINVAL;
+-}
+-
+-asmlinkage int solaris_gettimeofday(u32 tim)
+-{
+- int (*sys_gettimeofday)(struct timeval *, struct timezone *) =
+- (int (*)(struct timeval *, struct timezone *))SYS(gettimeofday);
+-
+- return sys_gettimeofday((struct timeval *)(u64)tim, NULL);
+-}
+-
+-#define RLIM_SOL_INFINITY32 0x7fffffff
+-#define RLIM_SOL_SAVED_MAX32 0x7ffffffe
+-#define RLIM_SOL_SAVED_CUR32 0x7ffffffd
+-#define RLIM_SOL_INFINITY ((u64)-3)
+-#define RLIM_SOL_SAVED_MAX ((u64)-2)
+-#define RLIM_SOL_SAVED_CUR ((u64)-1)
+-#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
+-#define RLIMIT_SOL_NOFILE 5
+-#define RLIMIT_SOL_VMEM 6
+-
+-struct rlimit32 {
+- u32 rlim_cur;
+- u32 rlim_max;
+-};
+-
+-asmlinkage int solaris_getrlimit(unsigned int resource, struct rlimit32 __user *rlim)
+-{
+- struct rlimit r;
+- int ret;
+- mm_segment_t old_fs = get_fs ();
+- int (*sys_getrlimit)(unsigned int, struct rlimit *) =
+- (int (*)(unsigned int, struct rlimit *))SYS(getrlimit);
+-
+- if (resource > RLIMIT_SOL_VMEM)
+- return -EINVAL;
+- switch (resource) {
+- case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break;
+- case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break;
+- default: break;
+- }
+- set_fs (KERNEL_DS);
+- ret = sys_getrlimit(resource, &r);
+- set_fs (old_fs);
+- if (!ret) {
+- if (r.rlim_cur == RLIM_INFINITY)
+- r.rlim_cur = RLIM_SOL_INFINITY32;
+- else if ((u64)r.rlim_cur > RLIM_SOL_INFINITY32)
+- r.rlim_cur = RLIM_SOL_SAVED_CUR32;
+- if (r.rlim_max == RLIM_INFINITY)
+- r.rlim_max = RLIM_SOL_INFINITY32;
+- else if ((u64)r.rlim_max > RLIM_SOL_INFINITY32)
+- r.rlim_max = RLIM_SOL_SAVED_MAX32;
+- ret = put_user (r.rlim_cur, &rlim->rlim_cur);
+- ret |= __put_user (r.rlim_max, &rlim->rlim_max);
+- }
+- return ret;
+-}
+-
+-asmlinkage int solaris_setrlimit(unsigned int resource, struct rlimit32 __user *rlim)
+-{
+- struct rlimit r, rold;
+- int ret;
+- mm_segment_t old_fs = get_fs ();
+- int (*sys_getrlimit)(unsigned int, struct rlimit __user *) =
+- (int (*)(unsigned int, struct rlimit __user *))SYS(getrlimit);
+- int (*sys_setrlimit)(unsigned int, struct rlimit __user *) =
+- (int (*)(unsigned int, struct rlimit __user *))SYS(setrlimit);
+-
+- if (resource > RLIMIT_SOL_VMEM)
+- return -EINVAL;
+- switch (resource) {
+- case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break;
+- case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break;
+- default: break;
+- }
+- if (get_user (r.rlim_cur, &rlim->rlim_cur) ||
+- __get_user (r.rlim_max, &rlim->rlim_max))
+- return -EFAULT;
+- set_fs (KERNEL_DS);
+- ret = sys_getrlimit(resource, &rold);
+- if (!ret) {
+- if (r.rlim_cur == RLIM_SOL_INFINITY32)
+- r.rlim_cur = RLIM_INFINITY;
+- else if (r.rlim_cur == RLIM_SOL_SAVED_CUR32)
+- r.rlim_cur = rold.rlim_cur;
+- else if (r.rlim_cur == RLIM_SOL_SAVED_MAX32)
+- r.rlim_cur = rold.rlim_max;
+- if (r.rlim_max == RLIM_SOL_INFINITY32)
+- r.rlim_max = RLIM_INFINITY;
+- else if (r.rlim_max == RLIM_SOL_SAVED_CUR32)
+- r.rlim_max = rold.rlim_cur;
+- else if (r.rlim_max == RLIM_SOL_SAVED_MAX32)
+- r.rlim_max = rold.rlim_max;
+- ret = sys_setrlimit(resource, &r);
+- }
+- set_fs (old_fs);
+- return ret;
+-}
+-
+-asmlinkage int solaris_getrlimit64(unsigned int resource, struct rlimit __user *rlim)
+-{
+- struct rlimit r;
+- int ret;
+- mm_segment_t old_fs = get_fs ();
+- int (*sys_getrlimit)(unsigned int, struct rlimit __user *) =
+- (int (*)(unsigned int, struct rlimit __user *))SYS(getrlimit);
+-
+- if (resource > RLIMIT_SOL_VMEM)
+- return -EINVAL;
+- switch (resource) {
+- case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break;
+- case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break;
+- default: break;
+- }
+- set_fs (KERNEL_DS);
+- ret = sys_getrlimit(resource, &r);
+- set_fs (old_fs);
+- if (!ret) {
+- if (r.rlim_cur == RLIM_INFINITY)
+- r.rlim_cur = RLIM_SOL_INFINITY;
+- if (r.rlim_max == RLIM_INFINITY)
+- r.rlim_max = RLIM_SOL_INFINITY;
+- ret = put_user (r.rlim_cur, &rlim->rlim_cur);
+- ret |= __put_user (r.rlim_max, &rlim->rlim_max);
+- }
+- return ret;
+-}
+-
+-asmlinkage int solaris_setrlimit64(unsigned int resource, struct rlimit __user *rlim)
+-{
+- struct rlimit r, rold;
+- int ret;
+- mm_segment_t old_fs = get_fs ();
+- int (*sys_getrlimit)(unsigned int, struct rlimit __user *) =
+- (int (*)(unsigned int, struct rlimit __user *))SYS(getrlimit);
+- int (*sys_setrlimit)(unsigned int, struct rlimit __user *) =
+- (int (*)(unsigned int, struct rlimit __user *))SYS(setrlimit);
+-
+- if (resource > RLIMIT_SOL_VMEM)
+- return -EINVAL;
+- switch (resource) {
+- case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break;
+- case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break;
+- default: break;
+- }
+- if (get_user (r.rlim_cur, &rlim->rlim_cur) ||
+- __get_user (r.rlim_max, &rlim->rlim_max))
+- return -EFAULT;
+- set_fs (KERNEL_DS);
+- ret = sys_getrlimit(resource, &rold);
+- if (!ret) {
+- if (r.rlim_cur == RLIM_SOL_INFINITY)
+- r.rlim_cur = RLIM_INFINITY;
+- else if (r.rlim_cur == RLIM_SOL_SAVED_CUR)
+- r.rlim_cur = rold.rlim_cur;
+- else if (r.rlim_cur == RLIM_SOL_SAVED_MAX)
+- r.rlim_cur = rold.rlim_max;
+- if (r.rlim_max == RLIM_SOL_INFINITY)
+- r.rlim_max = RLIM_INFINITY;
+- else if (r.rlim_max == RLIM_SOL_SAVED_CUR)
+- r.rlim_max = rold.rlim_cur;
+- else if (r.rlim_max == RLIM_SOL_SAVED_MAX)
+- r.rlim_max = rold.rlim_max;
+- ret = sys_setrlimit(resource, &r);
+- }
+- set_fs (old_fs);
+- return ret;
+-}
+-
+-struct sol_ntptimeval {
+- struct compat_timeval time;
+- s32 maxerror;
+- s32 esterror;
+-};
+-
+-struct sol_timex {
+- u32 modes;
+- s32 offset;
+- s32 freq;
+- s32 maxerror;
+- s32 esterror;
+- s32 status;
+- s32 constant;
+- s32 precision;
+- s32 tolerance;
+- s32 ppsfreq;
+- s32 jitter;
+- s32 shift;
+- s32 stabil;
+- s32 jitcnt;
+- s32 calcnt;
+- s32 errcnt;
+- s32 stbcnt;
+-};
+-
+-asmlinkage int solaris_ntp_gettime(struct sol_ntptimeval __user *ntp)
+-{
+- int (*sys_adjtimex)(struct timex __user *) =
+- (int (*)(struct timex __user *))SYS(adjtimex);
+- struct timex t;
+- int ret;
+- mm_segment_t old_fs = get_fs();
+-
+- set_fs(KERNEL_DS);
+- t.modes = 0;
+- ret = sys_adjtimex(&t);
+- set_fs(old_fs);
+- if (ret < 0)
+- return ret;
+- ret = put_user (t.time.tv_sec, &ntp->time.tv_sec);
+- ret |= __put_user (t.time.tv_usec, &ntp->time.tv_usec);
+- ret |= __put_user (t.maxerror, &ntp->maxerror);
+- ret |= __put_user (t.esterror, &ntp->esterror);
+- return ret;
+-}
+-
+-asmlinkage int solaris_ntp_adjtime(struct sol_timex __user *txp)
+-{
+- int (*sys_adjtimex)(struct timex __user *) =
+- (int (*)(struct timex __user *))SYS(adjtimex);
+- struct timex t;
+- int ret, err;
+- mm_segment_t old_fs = get_fs();
+-
+- ret = get_user (t.modes, &txp->modes);
+- ret |= __get_user (t.offset, &txp->offset);
+- ret |= __get_user (t.freq, &txp->freq);
+- ret |= __get_user (t.maxerror, &txp->maxerror);
+- ret |= __get_user (t.esterror, &txp->esterror);
+- ret |= __get_user (t.status, &txp->status);
+- ret |= __get_user (t.constant, &txp->constant);
+- set_fs(KERNEL_DS);
+- ret = sys_adjtimex(&t);
+- set_fs(old_fs);
+- if (ret < 0)
+- return ret;
+- err = put_user (t.offset, &txp->offset);
+- err |= __put_user (t.freq, &txp->freq);
+- err |= __put_user (t.maxerror, &txp->maxerror);
+- err |= __put_user (t.esterror, &txp->esterror);
+- err |= __put_user (t.status, &txp->status);
+- err |= __put_user (t.constant, &txp->constant);
+- err |= __put_user (t.precision, &txp->precision);
+- err |= __put_user (t.tolerance, &txp->tolerance);
+- err |= __put_user (t.ppsfreq, &txp->ppsfreq);
+- err |= __put_user (t.jitter, &txp->jitter);
+- err |= __put_user (t.shift, &txp->shift);
+- err |= __put_user (t.stabil, &txp->stabil);
+- err |= __put_user (t.jitcnt, &txp->jitcnt);
+- err |= __put_user (t.calcnt, &txp->calcnt);
+- err |= __put_user (t.errcnt, &txp->errcnt);
+- err |= __put_user (t.stbcnt, &txp->stbcnt);
+- if (err)
+- return -EFAULT;
+- return ret;
+-}
+-
+-asmlinkage int do_sol_unimplemented(struct pt_regs *regs)
+-{
+- printk ("Unimplemented Solaris syscall %d %08x %08x %08x %08x\n",
+- (int)regs->u_regs[UREG_G1],
+- (int)regs->u_regs[UREG_I0],
+- (int)regs->u_regs[UREG_I1],
+- (int)regs->u_regs[UREG_I2],
+- (int)regs->u_regs[UREG_I3]);
+- return -ENOSYS;
+-}
+-
+-asmlinkage void solaris_register(void)
+-{
+- set_personality(PER_SVR4);
+-}
+-
+-extern long solaris_to_linux_signals[], linux_to_solaris_signals[];
+-
+-struct exec_domain solaris_exec_domain = {
+- .name = "Solaris",
+- .handler = NULL,
+- .pers_low = 1, /* PER_SVR4 personality */
+- .pers_high = 1,
+- .signal_map = solaris_to_linux_signals,
+- .signal_invmap =linux_to_solaris_signals,
+- .module = THIS_MODULE,
+- .next = NULL
+-};
+-
+-extern int init_socksys(void);
+-
+-MODULE_AUTHOR("Jakub Jelinek (jj at ultra.linux.cz), Patrik Rak (prak3264 at ss1000.ms.mff.cuni.cz)");
+-MODULE_DESCRIPTION("Solaris binary emulation module");
+-MODULE_LICENSE("GPL");
+-
+-extern u32 tl0_solaris[8];
+-#define update_ttable(x) \
+- tl0_solaris[3] = (((long)(x) - (long)tl0_solaris - 3) >> 2) | 0x40000000; \
+- wmb(); \
+- __asm__ __volatile__ ("flush %0" : : "r" (&tl0_solaris[3]))
+-
+-extern u32 solaris_sparc_syscall[];
+-extern u32 solaris_syscall[];
+-extern void cleanup_socksys(void);
+-
+-extern u32 entry64_personality_patch;
+-
+-static int __init solaris_init(void)
+-{
+- int ret;
+-
+- SOLDD(("Solaris module at %p\n", solaris_sparc_syscall));
+- register_exec_domain(&solaris_exec_domain);
+- if ((ret = init_socksys())) {
+- unregister_exec_domain(&solaris_exec_domain);
+- return ret;
+- }
+- update_ttable(solaris_sparc_syscall);
+- entry64_personality_patch |=
+- (offsetof(struct task_struct, personality) +
+- (sizeof(unsigned long) - 1));
+- wmb();
+- __asm__ __volatile__("flush %0"
+- : : "r" (&entry64_personality_patch));
+- return 0;
+-}
+-
+-static void __exit solaris_exit(void)
+-{
+- update_ttable(solaris_syscall);
+- cleanup_socksys();
+- unregister_exec_domain(&solaris_exec_domain);
+-}
+-
+-module_init(solaris_init);
+-module_exit(solaris_exit);
+diff --git a/arch/sparc64/solaris/signal.c b/arch/sparc64/solaris/signal.c
+deleted file mode 100644
+index de10c97..0000000
+--- a/arch/sparc64/solaris/signal.c
++++ /dev/null
+@@ -1,429 +0,0 @@
+-/* $Id: signal.c,v 1.7 2000/09/05 21:44:54 davem Exp $
+- * signal.c: Signal emulation for Solaris
+- *
+- * Copyright (C) 1997 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
+- */
+-
+-#include <linux/types.h>
+-#include <linux/errno.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/svr4.h>
+-#include <asm/string.h>
+-
+-#include "conv.h"
+-#include "signal.h"
+-
+-#define _S(nr) (1L<<((nr)-1))
+-
+-#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
+-
+-long linux_to_solaris_signals[] = {
+- 0,
+- SOLARIS_SIGHUP, SOLARIS_SIGINT,
+- SOLARIS_SIGQUIT, SOLARIS_SIGILL,
+- SOLARIS_SIGTRAP, SOLARIS_SIGIOT,
+- SOLARIS_SIGEMT, SOLARIS_SIGFPE,
+- SOLARIS_SIGKILL, SOLARIS_SIGBUS,
+- SOLARIS_SIGSEGV, SOLARIS_SIGSYS,
+- SOLARIS_SIGPIPE, SOLARIS_SIGALRM,
+- SOLARIS_SIGTERM, SOLARIS_SIGURG,
+- SOLARIS_SIGSTOP, SOLARIS_SIGTSTP,
+- SOLARIS_SIGCONT, SOLARIS_SIGCLD,
+- SOLARIS_SIGTTIN, SOLARIS_SIGTTOU,
+- SOLARIS_SIGPOLL, SOLARIS_SIGXCPU,
+- SOLARIS_SIGXFSZ, SOLARIS_SIGVTALRM,
+- SOLARIS_SIGPROF, SOLARIS_SIGWINCH,
+- SOLARIS_SIGUSR1, SOLARIS_SIGUSR1,
+- SOLARIS_SIGUSR2, -1,
+-};
+-
+-long solaris_to_linux_signals[] = {
+- 0,
+- SIGHUP, SIGINT, SIGQUIT, SIGILL,
+- SIGTRAP, SIGIOT, SIGEMT, SIGFPE,
+- SIGKILL, SIGBUS, SIGSEGV, SIGSYS,
+- SIGPIPE, SIGALRM, SIGTERM, SIGUSR1,
+- SIGUSR2, SIGCHLD, -1, SIGWINCH,
+- SIGURG, SIGPOLL, SIGSTOP, SIGTSTP,
+- SIGCONT, SIGTTIN, SIGTTOU, SIGVTALRM,
+- SIGPROF, SIGXCPU, SIGXFSZ, -1,
+- -1, -1, -1, -1,
+- -1, -1, -1, -1,
+- -1, -1, -1, -1,
+-};
+-
+-static inline long mapsig(long sig)
+-{
+- if ((unsigned long)sig > SOLARIS_NSIGNALS)
+- return -EINVAL;
+- return solaris_to_linux_signals[sig];
+-}
+-
+-asmlinkage int solaris_kill(int pid, int sig)
+-{
+- int (*sys_kill)(int,int) =
+- (int (*)(int,int))SYS(kill);
+- int s = mapsig(sig);
+-
+- if (s < 0) return s;
+- return sys_kill(pid, s);
+-}
+-
+-static long sig_handler(int sig, u32 arg, int one_shot)
+-{
+- struct sigaction sa, old;
+- int ret;
+- mm_segment_t old_fs = get_fs();
+- int (*sys_sigaction)(int,struct sigaction __user *,struct sigaction __user *) =
+- (int (*)(int,struct sigaction __user *,struct sigaction __user *))SYS(sigaction);
+-
+- sigemptyset(&sa.sa_mask);
+- sa.sa_restorer = NULL;
+- sa.sa_handler = (__sighandler_t)A(arg);
+- sa.sa_flags = 0;
+- if (one_shot) sa.sa_flags = SA_ONESHOT | SA_NOMASK;
+- set_fs (KERNEL_DS);
+- ret = sys_sigaction(sig, (void __user *)&sa, (void __user *)&old);
+- set_fs (old_fs);
+- if (ret < 0) return ret;
+- return (u32)(unsigned long)old.sa_handler;
+-}
+-
+-static inline long solaris_signal(int sig, u32 arg)
+-{
+- return sig_handler (sig, arg, 1);
+-}
+-
+-static long solaris_sigset(int sig, u32 arg)
+-{
+- if (arg != 2) /* HOLD */ {
+- spin_lock_irq(¤t->sighand->siglock);
+- sigdelsetmask(¤t->blocked, _S(sig));
+- recalc_sigpending();
+- spin_unlock_irq(¤t->sighand->siglock);
+- return sig_handler (sig, arg, 0);
+- } else {
+- spin_lock_irq(¤t->sighand->siglock);
+- sigaddsetmask(¤t->blocked, (_S(sig) & ~_BLOCKABLE));
+- recalc_sigpending();
+- spin_unlock_irq(¤t->sighand->siglock);
+- return 0;
+- }
+-}
+-
+-static inline long solaris_sighold(int sig)
+-{
+- return solaris_sigset(sig, 2);
+-}
+-
+-static inline long solaris_sigrelse(int sig)
+-{
+- spin_lock_irq(¤t->sighand->siglock);
+- sigdelsetmask(¤t->blocked, _S(sig));
+- recalc_sigpending();
+- spin_unlock_irq(¤t->sighand->siglock);
+- return 0;
+-}
+-
+-static inline long solaris_sigignore(int sig)
+-{
+- return sig_handler(sig, (u32)(unsigned long)SIG_IGN, 0);
+-}
+-
+-static inline long solaris_sigpause(int sig)
+-{
+- printk ("Need to support solaris sigpause\n");
+- return -ENOSYS;
+-}
+-
+-asmlinkage long solaris_sigfunc(int sig, u32 arg)
+-{
+- int func = sig & ~0xff;
+-
+- sig = mapsig(sig & 0xff);
+- if (sig < 0) return sig;
+- switch (func) {
+- case 0: return solaris_signal(sig, arg);
+- case 0x100: return solaris_sigset(sig, arg);
+- case 0x200: return solaris_sighold(sig);
+- case 0x400: return solaris_sigrelse(sig);
+- case 0x800: return solaris_sigignore(sig);
+- case 0x1000: return solaris_sigpause(sig);
+- }
+- return -EINVAL;
+-}
+-
+-typedef struct {
+- u32 __sigbits[4];
+-} sol_sigset_t;
+-
+-static inline int mapin(u32 *p, sigset_t *q)
+-{
+- int i;
+- u32 x;
+- int sig;
+-
+- sigemptyset(q);
+- x = p[0];
+- for (i = 1; i <= SOLARIS_NSIGNALS; i++) {
+- if (x & 1) {
+- sig = solaris_to_linux_signals[i];
+- if (sig == -1)
+- return -EINVAL;
+- sigaddsetmask(q, (1L << (sig - 1)));
+- }
+- x >>= 1;
+- if (i == 32)
+- x = p[1];
+- }
+- return 0;
+-}
+-
+-static inline int mapout(sigset_t *q, u32 *p)
+-{
+- int i;
+- int sig;
+-
+- p[0] = 0;
+- p[1] = 0;
+- for (i = 1; i <= 32; i++) {
+- if (sigismember(q, sigmask(i))) {
+- sig = linux_to_solaris_signals[i];
+- if (sig == -1)
+- return -EINVAL;
+- if (sig > 32)
+- p[1] |= 1L << (sig - 33);
+- else
+- p[0] |= 1L << (sig - 1);
+- }
+- }
+- return 0;
+-}
+-
+-asmlinkage int solaris_sigprocmask(int how, u32 in, u32 out)
+-{
+- sigset_t in_s, *ins, out_s, *outs;
+- mm_segment_t old_fs = get_fs();
+- int ret;
+- int (*sys_sigprocmask)(int,sigset_t __user *,sigset_t __user *) =
+- (int (*)(int,sigset_t __user *,sigset_t __user *))SYS(sigprocmask);
+-
+- ins = NULL; outs = NULL;
+- if (in) {
+- u32 tmp[2];
+-
+- if (copy_from_user (tmp, (void __user *)A(in), 2*sizeof(u32)))
+- return -EFAULT;
+- ins = &in_s;
+- if (mapin (tmp, ins)) return -EINVAL;
+- }
+- if (out) outs = &out_s;
+- set_fs (KERNEL_DS);
+- ret = sys_sigprocmask((how == 3) ? SIG_SETMASK : how,
+- (void __user *)ins, (void __user *)outs);
+- set_fs (old_fs);
+- if (ret) return ret;
+- if (out) {
+- u32 tmp[4];
+-
+- tmp[2] = 0; tmp[3] = 0;
+- if (mapout (outs, tmp)) return -EINVAL;
+- if (copy_to_user((void __user *)A(out), tmp, 4*sizeof(u32)))
+- return -EFAULT;
+- }
+- return 0;
+-}
+-
+-asmlinkage long do_sol_sigsuspend(u32 mask)
+-{
+- sigset_t s;
+- u32 tmp[2];
+-
+- if (copy_from_user (tmp, (sol_sigset_t __user *)A(mask), 2*sizeof(u32)))
+- return -EFAULT;
+- if (mapin (tmp, &s)) return -EINVAL;
+- return (long)s.sig[0];
+-}
+-
+-struct sol_sigaction {
+- int sa_flags;
+- u32 sa_handler;
+- u32 sa_mask[4];
+- int sa_resv[2];
+-};
+-
+-asmlinkage int solaris_sigaction(int sig, u32 act, u32 old)
+-{
+- u32 tmp, tmp2[4];
+- struct sigaction s, s2;
+- int ret;
+- mm_segment_t old_fs = get_fs();
+- struct sol_sigaction __user *p = (void __user *)A(old);
+- int (*sys_sigaction)(int,struct sigaction __user *,struct sigaction __user *) =
+- (int (*)(int,struct sigaction __user *,struct sigaction __user *))SYS(sigaction);
+-
+- sig = mapsig(sig);
+- if (sig < 0) {
+- /* We cheat a little bit for Solaris only signals */
+- if (old && clear_user(p, sizeof(struct sol_sigaction)))
+- return -EFAULT;
+- return 0;
+- }
+- if (act) {
+- if (get_user (tmp, &p->sa_flags))
+- return -EFAULT;
+- s.sa_flags = 0;
+- if (tmp & SOLARIS_SA_ONSTACK) s.sa_flags |= SA_STACK;
+- if (tmp & SOLARIS_SA_RESTART) s.sa_flags |= SA_RESTART;
+- if (tmp & SOLARIS_SA_NODEFER) s.sa_flags |= SA_NOMASK;
+- if (tmp & SOLARIS_SA_RESETHAND) s.sa_flags |= SA_ONESHOT;
+- if (tmp & SOLARIS_SA_NOCLDSTOP) s.sa_flags |= SA_NOCLDSTOP;
+- if (get_user (tmp, &p->sa_handler) ||
+- copy_from_user (tmp2, &p->sa_mask, 2*sizeof(u32)))
+- return -EFAULT;
+- s.sa_handler = (__sighandler_t)A(tmp);
+- if (mapin (tmp2, &s.sa_mask)) return -EINVAL;
+- s.sa_restorer = NULL;
+- }
+- set_fs(KERNEL_DS);
+- ret = sys_sigaction(sig, act ? (void __user *)&s : NULL,
+- old ? (void __user *)&s2 : NULL);
+- set_fs(old_fs);
+- if (ret) return ret;
+- if (old) {
+- if (mapout (&s2.sa_mask, tmp2)) return -EINVAL;
+- tmp = 0; tmp2[2] = 0; tmp2[3] = 0;
+- if (s2.sa_flags & SA_STACK) tmp |= SOLARIS_SA_ONSTACK;
+- if (s2.sa_flags & SA_RESTART) tmp |= SOLARIS_SA_RESTART;
+- if (s2.sa_flags & SA_NOMASK) tmp |= SOLARIS_SA_NODEFER;
+- if (s2.sa_flags & SA_ONESHOT) tmp |= SOLARIS_SA_RESETHAND;
+- if (s2.sa_flags & SA_NOCLDSTOP) tmp |= SOLARIS_SA_NOCLDSTOP;
+- if (put_user (tmp, &p->sa_flags) ||
+- __put_user ((u32)(unsigned long)s2.sa_handler, &p->sa_handler) ||
+- copy_to_user (&p->sa_mask, tmp2, 4*sizeof(u32)))
+- return -EFAULT;
+- }
+- return 0;
+-}
+-
+-asmlinkage int solaris_sigpending(int which, u32 set)
+-{
+- sigset_t s;
+- u32 tmp[4];
+- switch (which) {
+- case 1: /* sigpending */
+- spin_lock_irq(¤t->sighand->siglock);
+- sigandsets(&s, ¤t->blocked, ¤t->pending.signal);
+- recalc_sigpending();
+- spin_unlock_irq(¤t->sighand->siglock);
+- break;
+- case 2: /* sigfillset - I just set signals which have linux equivalents */
+- sigfillset(&s);
+- break;
+- default: return -EINVAL;
+- }
+- if (mapout (&s, tmp)) return -EINVAL;
+- tmp[2] = 0; tmp[3] = 0;
+- if (copy_to_user ((u32 __user *)A(set), tmp, sizeof(tmp)))
+- return -EFAULT;
+- return 0;
+-}
+-
+-asmlinkage int solaris_wait(u32 stat_loc)
+-{
+- unsigned __user *p = (unsigned __user *)A(stat_loc);
+- int (*sys_wait4)(pid_t,unsigned __user *, int, struct rusage __user *) =
+- (int (*)(pid_t,unsigned __user *, int, struct rusage __user *))SYS(wait4);
+- int ret, status;
+-
+- ret = sys_wait4(-1, p, WUNTRACED, NULL);
+- if (ret >= 0 && stat_loc) {
+- if (get_user (status, p))
+- return -EFAULT;
+- if (((status - 1) & 0xffff) < 0xff)
+- status = linux_to_solaris_signals[status & 0x7f] & 0x7f;
+- else if ((status & 0xff) == 0x7f)
+- status = (linux_to_solaris_signals[(status >> 8) & 0xff] << 8) | 0x7f;
+- if (__put_user (status, p))
+- return -EFAULT;
+- }
+- return ret;
+-}
+-
+-asmlinkage int solaris_waitid(int idtype, s32 pid, u32 info, int options)
+-{
+- int (*sys_wait4)(pid_t,unsigned __user *, int, struct rusage __user *) =
+- (int (*)(pid_t,unsigned __user *, int, struct rusage __user *))SYS(wait4);
+- int opts, status, ret;
+-
+- switch (idtype) {
+- case 0: /* P_PID */ break;
+- case 1: /* P_PGID */ pid = -pid; break;
+- case 7: /* P_ALL */ pid = -1; break;
+- default: return -EINVAL;
+- }
+- opts = 0;
+- if (options & SOLARIS_WUNTRACED) opts |= WUNTRACED;
+- if (options & SOLARIS_WNOHANG) opts |= WNOHANG;
+- current->state = TASK_RUNNING;
+- ret = sys_wait4(pid, (unsigned int __user *)A(info), opts, NULL);
+- if (ret < 0) return ret;
+- if (info) {
+- struct sol_siginfo __user *s = (void __user *)A(info);
+-
+- if (get_user (status, (unsigned int __user *)A(info)))
+- return -EFAULT;
+-
+- if (__put_user (SOLARIS_SIGCLD, &s->si_signo) ||
+- __put_user (ret, &s->_data._proc._pid))
+- return -EFAULT;
+-
+- switch (status & 0xff) {
+- case 0: ret = SOLARIS_CLD_EXITED;
+- status = (status >> 8) & 0xff;
+- break;
+- case 0x7f:
+- status = (status >> 8) & 0xff;
+- switch (status) {
+- case SIGSTOP:
+- case SIGTSTP: ret = SOLARIS_CLD_STOPPED;
+- default: ret = SOLARIS_CLD_EXITED;
+- }
+- status = linux_to_solaris_signals[status];
+- break;
+- default:
+- if (status & 0x80) ret = SOLARIS_CLD_DUMPED;
+- else ret = SOLARIS_CLD_KILLED;
+- status = linux_to_solaris_signals[status & 0x7f];
+- break;
+- }
+-
+- if (__put_user (ret, &s->si_code) ||
+- __put_user (status, &s->_data._proc._pdata._cld._status))
+- return -EFAULT;
+- }
+- return 0;
+-}
+-
+-extern int svr4_setcontext(svr4_ucontext_t *c, struct pt_regs *regs);
+-extern int svr4_getcontext(svr4_ucontext_t *c, struct pt_regs *regs);
+-
+-asmlinkage int solaris_context(struct pt_regs *regs)
+-{
+- switch ((unsigned)regs->u_regs[UREG_I0]) {
+- case 0: /* getcontext */
+- return svr4_getcontext((svr4_ucontext_t *)(long)(u32)regs->u_regs[UREG_I1], regs);
+- case 1: /* setcontext */
+- return svr4_setcontext((svr4_ucontext_t *)(long)(u32)regs->u_regs[UREG_I1], regs);
+- default:
+- return -EINVAL;
+-
+- }
+-}
+-
+-asmlinkage int solaris_sigaltstack(u32 ss, u32 oss)
+-{
+-/* XXX Implement this soon */
+- return 0;
+-}
+diff --git a/arch/sparc64/solaris/signal.h b/arch/sparc64/solaris/signal.h
+deleted file mode 100644
+index e915708..0000000
+--- a/arch/sparc64/solaris/signal.h
++++ /dev/null
+@@ -1,108 +0,0 @@
+-/* $Id: signal.h,v 1.3 1998/04/12 06:20:33 davem Exp $
+- * signal.h: Signal emulation for Solaris
+- *
+- * Copyright (C) 1997 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
+- */
+-
+-#define SOLARIS_SIGHUP 1
+-#define SOLARIS_SIGINT 2
+-#define SOLARIS_SIGQUIT 3
+-#define SOLARIS_SIGILL 4
+-#define SOLARIS_SIGTRAP 5
+-#define SOLARIS_SIGIOT 6
+-#define SOLARIS_SIGEMT 7
+-#define SOLARIS_SIGFPE 8
+-#define SOLARIS_SIGKILL 9
+-#define SOLARIS_SIGBUS 10
+-#define SOLARIS_SIGSEGV 11
+-#define SOLARIS_SIGSYS 12
+-#define SOLARIS_SIGPIPE 13
+-#define SOLARIS_SIGALRM 14
+-#define SOLARIS_SIGTERM 15
+-#define SOLARIS_SIGUSR1 16
+-#define SOLARIS_SIGUSR2 17
+-#define SOLARIS_SIGCLD 18
+-#define SOLARIS_SIGPWR 19
+-#define SOLARIS_SIGWINCH 20
+-#define SOLARIS_SIGURG 21
+-#define SOLARIS_SIGPOLL 22
+-#define SOLARIS_SIGSTOP 23
+-#define SOLARIS_SIGTSTP 24
+-#define SOLARIS_SIGCONT 25
+-#define SOLARIS_SIGTTIN 26
+-#define SOLARIS_SIGTTOU 27
+-#define SOLARIS_SIGVTALRM 28
+-#define SOLARIS_SIGPROF 29
+-#define SOLARIS_SIGXCPU 30
+-#define SOLARIS_SIGXFSZ 31
+-#define SOLARIS_SIGWAITING 32
+-#define SOLARIS_SIGLWP 33
+-#define SOLARIS_SIGFREEZE 34
+-#define SOLARIS_SIGTHAW 35
+-#define SOLARIS_SIGCANCEL 36
+-#define SOLARIS_SIGRTMIN 37
+-#define SOLARIS_SIGRTMAX 44
+-#define SOLARIS_NSIGNALS 44
+-
+-
+-#define SOLARIS_SA_ONSTACK 1
+-#define SOLARIS_SA_RESETHAND 2
+-#define SOLARIS_SA_RESTART 4
+-#define SOLARIS_SA_SIGINFO 8
+-#define SOLARIS_SA_NODEFER 16
+-#define SOLARIS_SA_NOCLDWAIT 0x10000
+-#define SOLARIS_SA_NOCLDSTOP 0x20000
+-
+-struct sol_siginfo {
+- int si_signo;
+- int si_code;
+- int si_errno;
+- union {
+- char pad[128-3*sizeof(int)];
+- struct {
+- s32 _pid;
+- union {
+- struct {
+- s32 _uid;
+- s32 _value;
+- } _kill;
+- struct {
+- s32 _utime;
+- int _status;
+- s32 _stime;
+- } _cld;
+- } _pdata;
+- } _proc;
+- struct { /* SIGSEGV, SIGBUS, SIGILL and SIGFPE */
+- u32 _addr;
+- int _trapno;
+- } _fault;
+- struct { /* SIGPOLL, SIGXFSZ */
+- int _fd;
+- s32 _band;
+- } _file;
+- } _data;
+-};
+-
+-#define SOLARIS_WUNTRACED 0x04
+-#define SOLARIS_WNOHANG 0x40
+-#define SOLARIS_WEXITED 0x01
+-#define SOLARIS_WTRAPPED 0x02
+-#define SOLARIS_WSTOPPED WUNTRACED
+-#define SOLARIS_WCONTINUED 0x08
+-#define SOLARIS_WNOWAIT 0x80
+-
+-#define SOLARIS_TRAP_BRKPT 1
+-#define SOLARIS_TRAP_TRACE 2
+-#define SOLARIS_CLD_EXITED 1
+-#define SOLARIS_CLD_KILLED 2
+-#define SOLARIS_CLD_DUMPED 3
+-#define SOLARIS_CLD_TRAPPED 4
+-#define SOLARIS_CLD_STOPPED 5
+-#define SOLARIS_CLD_CONTINUED 6
+-#define SOLARIS_POLL_IN 1
+-#define SOLARIS_POLL_OUT 2
+-#define SOLARIS_POLL_MSG 3
+-#define SOLARIS_POLL_ERR 4
+-#define SOLARIS_POLL_PRI 5
+-#define SOLARIS_POLL_HUP 6
+diff --git a/arch/sparc64/solaris/socket.c b/arch/sparc64/solaris/socket.c
+deleted file mode 100644
+index cc69847..0000000
+--- a/arch/sparc64/solaris/socket.c
++++ /dev/null
+@@ -1,461 +0,0 @@
+-/* $Id: socket.c,v 1.6 2002/02/08 03:57:14 davem Exp $
+- * socket.c: Socket syscall emulation for Solaris 2.6+
+- *
+- * Copyright (C) 1998 Jakub Jelinek (jj at ultra.linux.cz)
+- *
+- * 1999-08-19 Fixed socketpair code
+- * Jason Rappleye (rappleye at ccr.buffalo.edu)
+- */
+-
+-#include <linux/types.h>
+-#include <linux/mm.h>
+-#include <linux/slab.h>
+-#include <linux/socket.h>
+-#include <linux/file.h>
+-#include <linux/net.h>
+-#include <linux/compat.h>
+-#include <net/compat.h>
+-#include <net/sock.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/string.h>
+-#include <asm/oplib.h>
+-#include <asm/idprom.h>
+-
+-#include "conv.h"
+-
+-#define SOCK_SOL_STREAM 2
+-#define SOCK_SOL_DGRAM 1
+-#define SOCK_SOL_RAW 4
+-#define SOCK_SOL_RDM 5
+-#define SOCK_SOL_SEQPACKET 6
+-
+-#define SOL_SO_SNDLOWAT 0x1003
+-#define SOL_SO_RCVLOWAT 0x1004
+-#define SOL_SO_SNDTIMEO 0x1005
+-#define SOL_SO_RCVTIMEO 0x1006
+-#define SOL_SO_STATE 0x2000
+-
+-#define SOL_SS_NDELAY 0x040
+-#define SOL_SS_NONBLOCK 0x080
+-#define SOL_SS_ASYNC 0x100
+-
+-#define SO_STATE 0x000e
+-
+-static int socket_check(int family, int type)
+-{
+- if (family != PF_UNIX && family != PF_INET)
+- return -ESOCKTNOSUPPORT;
+- switch (type) {
+- case SOCK_SOL_STREAM: type = SOCK_STREAM; break;
+- case SOCK_SOL_DGRAM: type = SOCK_DGRAM; break;
+- case SOCK_SOL_RAW: type = SOCK_RAW; break;
+- case SOCK_SOL_RDM: type = SOCK_RDM; break;
+- case SOCK_SOL_SEQPACKET: type = SOCK_SEQPACKET; break;
+- default: return -EINVAL;
+- }
+- return type;
+-}
+-
+-static int solaris_to_linux_sockopt(int optname)
+-{
+- switch (optname) {
+- case SOL_SO_SNDLOWAT: optname = SO_SNDLOWAT; break;
+- case SOL_SO_RCVLOWAT: optname = SO_RCVLOWAT; break;
+- case SOL_SO_SNDTIMEO: optname = SO_SNDTIMEO; break;
+- case SOL_SO_RCVTIMEO: optname = SO_RCVTIMEO; break;
+- case SOL_SO_STATE: optname = SO_STATE; break;
+- };
+-
+- return optname;
+-}
+-
+-asmlinkage int solaris_socket(int family, int type, int protocol)
+-{
+- int (*sys_socket)(int, int, int) =
+- (int (*)(int, int, int))SYS(socket);
+-
+- type = socket_check (family, type);
+- if (type < 0) return type;
+- return sys_socket(family, type, protocol);
+-}
+-
+-asmlinkage int solaris_socketpair(int *usockvec)
+-{
+- int (*sys_socketpair)(int, int, int, int *) =
+- (int (*)(int, int, int, int *))SYS(socketpair);
+-
+- /* solaris socketpair really only takes one arg at the syscall
+- * level, int * usockvec. The libs apparently take care of
+- * making sure that family==AF_UNIX and type==SOCK_STREAM. The
+- * pointer we really want ends up residing in the first (and
+- * supposedly only) argument.
+- */
+-
+- return sys_socketpair(AF_UNIX, SOCK_STREAM, 0, (int *)usockvec);
+-}
+-
+-asmlinkage int solaris_bind(int fd, struct sockaddr *addr, int addrlen)
+-{
+- int (*sys_bind)(int, struct sockaddr *, int) =
+- (int (*)(int, struct sockaddr *, int))SUNOS(104);
+-
+- return sys_bind(fd, addr, addrlen);
+-}
+-
+-asmlinkage int solaris_setsockopt(int fd, int level, int optname, u32 optval, int optlen)
+-{
+- int (*sunos_setsockopt)(int, int, int, u32, int) =
+- (int (*)(int, int, int, u32, int))SUNOS(105);
+-
+- optname = solaris_to_linux_sockopt(optname);
+- if (optname < 0)
+- return optname;
+- if (optname == SO_STATE)
+- return 0;
+-
+- return sunos_setsockopt(fd, level, optname, optval, optlen);
+-}
+-
+-asmlinkage int solaris_getsockopt(int fd, int level, int optname, u32 optval, u32 optlen)
+-{
+- int (*sunos_getsockopt)(int, int, int, u32, u32) =
+- (int (*)(int, int, int, u32, u32))SUNOS(118);
+-
+- optname = solaris_to_linux_sockopt(optname);
+- if (optname < 0)
+- return optname;
+-
+- if (optname == SO_STATE)
+- optname = SOL_SO_STATE;
+-
+- return sunos_getsockopt(fd, level, optname, optval, optlen);
+-}
+-
+-asmlinkage int solaris_connect(int fd, struct sockaddr __user *addr, int addrlen)
+-{
+- int (*sys_connect)(int, struct sockaddr __user *, int) =
+- (int (*)(int, struct sockaddr __user *, int))SYS(connect);
+-
+- return sys_connect(fd, addr, addrlen);
+-}
+-
+-asmlinkage int solaris_accept(int fd, struct sockaddr __user *addr, int __user *addrlen)
+-{
+- int (*sys_accept)(int, struct sockaddr __user *, int __user *) =
+- (int (*)(int, struct sockaddr __user *, int __user *))SYS(accept);
+-
+- return sys_accept(fd, addr, addrlen);
+-}
+-
+-asmlinkage int solaris_listen(int fd, int backlog)
+-{
+- int (*sys_listen)(int, int) =
+- (int (*)(int, int))SUNOS(106);
+-
+- return sys_listen(fd, backlog);
+-}
+-
+-asmlinkage int solaris_shutdown(int fd, int how)
+-{
+- int (*sys_shutdown)(int, int) =
+- (int (*)(int, int))SYS(shutdown);
+-
+- return sys_shutdown(fd, how);
+-}
+-
+-#define MSG_SOL_OOB 0x1
+-#define MSG_SOL_PEEK 0x2
+-#define MSG_SOL_DONTROUTE 0x4
+-#define MSG_SOL_EOR 0x8
+-#define MSG_SOL_CTRUNC 0x10
+-#define MSG_SOL_TRUNC 0x20
+-#define MSG_SOL_WAITALL 0x40
+-#define MSG_SOL_DONTWAIT 0x80
+-
+-static int solaris_to_linux_msgflags(int flags)
+-{
+- int fl = flags & (MSG_OOB|MSG_PEEK|MSG_DONTROUTE);
+-
+- if (flags & MSG_SOL_EOR) fl |= MSG_EOR;
+- if (flags & MSG_SOL_CTRUNC) fl |= MSG_CTRUNC;
+- if (flags & MSG_SOL_TRUNC) fl |= MSG_TRUNC;
+- if (flags & MSG_SOL_WAITALL) fl |= MSG_WAITALL;
+- if (flags & MSG_SOL_DONTWAIT) fl |= MSG_DONTWAIT;
+- return fl;
+-}
+-
+-static int linux_to_solaris_msgflags(int flags)
+-{
+- int fl = flags & (MSG_OOB|MSG_PEEK|MSG_DONTROUTE);
+-
+- if (flags & MSG_EOR) fl |= MSG_SOL_EOR;
+- if (flags & MSG_CTRUNC) fl |= MSG_SOL_CTRUNC;
+- if (flags & MSG_TRUNC) fl |= MSG_SOL_TRUNC;
+- if (flags & MSG_WAITALL) fl |= MSG_SOL_WAITALL;
+- if (flags & MSG_DONTWAIT) fl |= MSG_SOL_DONTWAIT;
+- return fl;
+-}
+-
+-asmlinkage int solaris_recvfrom(int s, char __user *buf, int len, int flags, u32 from, u32 fromlen)
+-{
+- int (*sys_recvfrom)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *) =
+- (int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *))SYS(recvfrom);
+-
+- return sys_recvfrom(s, buf, len, solaris_to_linux_msgflags(flags), A(from), A(fromlen));
+-}
+-
+-asmlinkage int solaris_recv(int s, char __user *buf, int len, int flags)
+-{
+- int (*sys_recvfrom)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *) =
+- (int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *))SYS(recvfrom);
+-
+- return sys_recvfrom(s, buf, len, solaris_to_linux_msgflags(flags), NULL, NULL);
+-}
+-
+-asmlinkage int solaris_sendto(int s, char __user *buf, int len, int flags, u32 to, u32 tolen)
+-{
+- int (*sys_sendto)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *) =
+- (int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *))SYS(sendto);
+-
+- return sys_sendto(s, buf, len, solaris_to_linux_msgflags(flags), A(to), A(tolen));
+-}
+-
+-asmlinkage int solaris_send(int s, char *buf, int len, int flags)
+-{
+- int (*sys_sendto)(int, void *, size_t, unsigned, struct sockaddr *, int *) =
+- (int (*)(int, void *, size_t, unsigned, struct sockaddr *, int *))SYS(sendto);
+-
+- return sys_sendto(s, buf, len, solaris_to_linux_msgflags(flags), NULL, NULL);
+-}
+-
+-asmlinkage int solaris_getpeername(int fd, struct sockaddr *addr, int *addrlen)
+-{
+- int (*sys_getpeername)(int, struct sockaddr *, int *) =
+- (int (*)(int, struct sockaddr *, int *))SYS(getpeername);
+-
+- return sys_getpeername(fd, addr, addrlen);
+-}
+-
+-asmlinkage int solaris_getsockname(int fd, struct sockaddr *addr, int *addrlen)
+-{
+- int (*sys_getsockname)(int, struct sockaddr *, int *) =
+- (int (*)(int, struct sockaddr *, int *))SYS(getsockname);
+-
+- return sys_getsockname(fd, addr, addrlen);
+-}
+-
+-/* XXX This really belongs in some header file... -DaveM */
+-#define MAX_SOCK_ADDR 128 /* 108 for Unix domain -
+- 16 for IP, 16 for IPX,
+- 24 for IPv6,
+- about 80 for AX.25 */
+-
+-struct sol_nmsghdr {
+- u32 msg_name;
+- int msg_namelen;
+- u32 msg_iov;
+- u32 msg_iovlen;
+- u32 msg_control;
+- u32 msg_controllen;
+- u32 msg_flags;
+-};
+-
+-struct sol_cmsghdr {
+- u32 cmsg_len;
+- int cmsg_level;
+- int cmsg_type;
+- unsigned char cmsg_data[0];
+-};
+-
+-static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg,
+- struct sol_nmsghdr __user *umsg)
+-{
+- u32 tmp1, tmp2, tmp3;
+- int err;
+-
+- err = get_user(tmp1, &umsg->msg_name);
+- err |= __get_user(tmp2, &umsg->msg_iov);
+- err |= __get_user(tmp3, &umsg->msg_control);
+- if (err)
+- return -EFAULT;
+-
+- kmsg->msg_name = A(tmp1);
+- kmsg->msg_iov = A(tmp2);
+- kmsg->msg_control = A(tmp3);
+-
+- err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
+- err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
+- err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
+-
+- kmsg->msg_flags = solaris_to_linux_msgflags(kmsg->msg_flags);
+-
+- return err;
+-}
+-
+-asmlinkage int solaris_sendmsg(int fd, struct sol_nmsghdr __user *user_msg, unsigned user_flags)
+-{
+- struct socket *sock;
+- char address[MAX_SOCK_ADDR];
+- struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
+- unsigned char ctl[sizeof(struct cmsghdr) + 20];
+- unsigned char *ctl_buf = ctl;
+- struct msghdr msg_sys;
+- int err, ctl_len, iov_size, total_len;
+-
+- err = -EFAULT;
+- if (msghdr_from_user32_to_kern(&msg_sys, user_msg))
+- goto out;
+-
+- sock = sockfd_lookup(fd, &err);
+- if (!sock)
+- goto out;
+-
+- /* do not move before msg_sys is valid */
+- err = -EMSGSIZE;
+- if (msg_sys.msg_iovlen > UIO_MAXIOV)
+- goto out_put;
+-
+- /* Check whether to allocate the iovec area*/
+- err = -ENOMEM;
+- iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
+- if (msg_sys.msg_iovlen > UIO_FASTIOV) {
+- iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
+- if (!iov)
+- goto out_put;
+- }
+-
+- err = verify_compat_iovec(&msg_sys, iov, address, VERIFY_READ);
+- if (err < 0)
+- goto out_freeiov;
+- total_len = err;
+-
+- err = -ENOBUFS;
+- if (msg_sys.msg_controllen > INT_MAX)
+- goto out_freeiov;
+-
+- ctl_len = msg_sys.msg_controllen;
+- if (ctl_len) {
+- struct sol_cmsghdr __user *ucmsg = msg_sys.msg_control;
+- unsigned long *kcmsg;
+- compat_size_t cmlen;
+-
+- err = -EINVAL;
+- if (ctl_len <= sizeof(compat_size_t))
+- goto out_freeiov;
+-
+- if (ctl_len > sizeof(ctl)) {
+- err = -ENOBUFS;
+- ctl_buf = kmalloc(ctl_len, GFP_KERNEL);
+- if (!ctl_buf)
+- goto out_freeiov;
+- }
+- __get_user(cmlen, &ucmsg->cmsg_len);
+- kcmsg = (unsigned long *) ctl_buf;
+- *kcmsg++ = (unsigned long)cmlen;
+- err = -EFAULT;
+- if (copy_from_user(kcmsg, &ucmsg->cmsg_level,
+- ctl_len - sizeof(compat_size_t)))
+- goto out_freectl;
+- msg_sys.msg_control = ctl_buf;
+- }
+- msg_sys.msg_flags = solaris_to_linux_msgflags(user_flags);
+-
+- if (sock->file->f_flags & O_NONBLOCK)
+- msg_sys.msg_flags |= MSG_DONTWAIT;
+- err = sock_sendmsg(sock, &msg_sys, total_len);
+-
+-out_freectl:
+- if (ctl_buf != ctl)
+- sock_kfree_s(sock->sk, ctl_buf, ctl_len);
+-out_freeiov:
+- if (iov != iovstack)
+- sock_kfree_s(sock->sk, iov, iov_size);
+-out_put:
+- sockfd_put(sock);
+-out:
+- return err;
+-}
+-
+-asmlinkage int solaris_recvmsg(int fd, struct sol_nmsghdr __user *user_msg, unsigned int user_flags)
+-{
+- struct socket *sock;
+- struct iovec iovstack[UIO_FASTIOV];
+- struct iovec *iov = iovstack;
+- struct msghdr msg_sys;
+- unsigned long cmsg_ptr;
+- int err, iov_size, total_len, len;
+-
+- /* kernel mode address */
+- char addr[MAX_SOCK_ADDR];
+-
+- /* user mode address pointers */
+- struct sockaddr __user *uaddr;
+- int __user *uaddr_len;
+-
+- if (msghdr_from_user32_to_kern(&msg_sys, user_msg))
+- return -EFAULT;
+-
+- sock = sockfd_lookup(fd, &err);
+- if (!sock)
+- goto out;
+-
+- err = -EMSGSIZE;
+- if (msg_sys.msg_iovlen > UIO_MAXIOV)
+- goto out_put;
+-
+- /* Check whether to allocate the iovec area*/
+- err = -ENOMEM;
+- iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
+- if (msg_sys.msg_iovlen > UIO_FASTIOV) {
+- iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
+- if (!iov)
+- goto out_put;
+- }
+-
+- /*
+- * Save the user-mode address (verify_iovec will change the
+- * kernel msghdr to use the kernel address space)
+- */
+-
+- uaddr = (void __user *) msg_sys.msg_name;
+- uaddr_len = &user_msg->msg_namelen;
+- err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
+- if (err < 0)
+- goto out_freeiov;
+- total_len = err;
+-
+- cmsg_ptr = (unsigned long) msg_sys.msg_control;
+- msg_sys.msg_flags = MSG_CMSG_COMPAT;
+-
+- if (sock->file->f_flags & O_NONBLOCK)
+- user_flags |= MSG_DONTWAIT;
+-
+- err = sock_recvmsg(sock, &msg_sys, total_len, user_flags);
+- if(err < 0)
+- goto out_freeiov;
+-
+- len = err;
+-
+- if (uaddr != NULL) {
+- err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len);
+- if (err < 0)
+- goto out_freeiov;
+- }
+- err = __put_user(linux_to_solaris_msgflags(msg_sys.msg_flags), &user_msg->msg_flags);
+- if (err)
+- goto out_freeiov;
+- err = __put_user((unsigned long)msg_sys.msg_control - cmsg_ptr,
+- &user_msg->msg_controllen);
+- if (err)
+- goto out_freeiov;
+- err = len;
+-
+-out_freeiov:
+- if (iov != iovstack)
+- sock_kfree_s(sock->sk, iov, iov_size);
+-out_put:
+- sockfd_put(sock);
+-out:
+- return err;
+-}
+diff --git a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c
+deleted file mode 100644
+index 7736411..0000000
+--- a/arch/sparc64/solaris/socksys.c
++++ /dev/null
+@@ -1,203 +0,0 @@
+-/* $Id: socksys.c,v 1.21 2002/02/08 03:57:14 davem Exp $
+- * socksys.c: /dev/inet/ stuff for Solaris emulation.
+- *
+- * Copyright (C) 1997 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
+- * Copyright (C) 1997, 1998 Patrik Rak (prak3264 at ss1000.ms.mff.cuni.cz)
+- * Copyright (C) 1995, 1996 Mike Jagdis (jaggy at purplet.demon.co.uk)
+- */
+-
+-/*
+- * Dave, _please_ give me specifications on this fscking mess so that I
+- * could at least get it into the state when it wouldn't screw the rest of
+- * the kernel over. socksys.c and timod.c _stink_ and we are not talking
+- * H2S here, it's isopropilmercaptan in concentrations way over LD50. -- AV
+- */
+-
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/smp.h>
+-#include <linux/ioctl.h>
+-#include <linux/fs.h>
+-#include <linux/file.h>
+-#include <linux/init.h>
+-#include <linux/poll.h>
+-#include <linux/slab.h>
+-#include <linux/syscalls.h>
+-#include <linux/in.h>
+-
+-#include <net/sock.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/termios.h>
+-
+-#include "conv.h"
+-#include "socksys.h"
+-
+-static int af_inet_protocols[] = {
+-IPPROTO_ICMP, IPPROTO_ICMP, IPPROTO_IGMP, IPPROTO_IPIP, IPPROTO_TCP,
+-IPPROTO_EGP, IPPROTO_PUP, IPPROTO_UDP, IPPROTO_IDP, IPPROTO_RAW,
+-0, 0, 0, 0, 0, 0,
+-};
+-
+-#ifndef DEBUG_SOLARIS_KMALLOC
+-
+-#define mykmalloc kmalloc
+-#define mykfree kfree
+-
+-#else
+-
+-extern void * mykmalloc(size_t s, gfp_t gfp);
+-extern void mykfree(void *);
+-
+-#endif
+-
+-static unsigned int (*sock_poll)(struct file *, poll_table *);
+-
+-static struct file_operations socksys_file_ops = {
+- /* Currently empty */
+-};
+-
+-static int socksys_open(struct inode * inode, struct file * filp)
+-{
+- int family, type, protocol, fd;
+- struct dentry *dentry;
+- int (*sys_socket)(int,int,int) =
+- (int (*)(int,int,int))SUNOS(97);
+- struct sol_socket_struct * sock;
+-
+- family = ((iminor(inode) >> 4) & 0xf);
+- switch (family) {
+- case AF_UNIX:
+- type = SOCK_STREAM;
+- protocol = 0;
+- break;
+- case AF_INET:
+- protocol = af_inet_protocols[iminor(inode) & 0xf];
+- switch (protocol) {
+- case IPPROTO_TCP: type = SOCK_STREAM; break;
+- case IPPROTO_UDP: type = SOCK_DGRAM; break;
+- default: type = SOCK_RAW; break;
+- }
+- break;
+- default:
+- type = SOCK_RAW;
+- protocol = 0;
+- break;
+- }
+-
+- fd = sys_socket(family, type, protocol);
+- if (fd < 0)
+- return fd;
+- /*
+- * N.B. The following operations are not legal!
+- *
+- * No shit. WTF is it supposed to do, anyway?
+- *
+- * Try instead:
+- * d_delete(filp->f_path.dentry), then d_instantiate with sock inode
+- */
+- dentry = filp->f_path.dentry;
+- filp->f_path.dentry = dget(fcheck(fd)->f_path.dentry);
+- filp->f_path.dentry->d_inode->i_rdev = inode->i_rdev;
+- filp->f_path.dentry->d_inode->i_flock = inode->i_flock;
+- SOCKET_I(filp->f_path.dentry->d_inode)->file = filp;
+- filp->f_op = &socksys_file_ops;
+- sock = (struct sol_socket_struct*)
+- mykmalloc(sizeof(struct sol_socket_struct), GFP_KERNEL);
+- if (!sock) return -ENOMEM;
+- SOLDD(("sock=%016lx(%016lx)\n", sock, filp));
+- sock->magic = SOLARIS_SOCKET_MAGIC;
+- sock->modcount = 0;
+- sock->state = TS_UNBND;
+- sock->offset = 0;
+- sock->pfirst = sock->plast = NULL;
+- filp->private_data = sock;
+- SOLDD(("filp->private_data %016lx\n", filp->private_data));
+-
+- sys_close(fd);
+- dput(dentry);
+- return 0;
+-}
+-
+-static int socksys_release(struct inode * inode, struct file * filp)
+-{
+- struct sol_socket_struct * sock;
+- struct T_primsg *it;
+-
+- /* XXX: check this */
+- sock = (struct sol_socket_struct *)filp->private_data;
+- SOLDD(("sock release %016lx(%016lx)\n", sock, filp));
+- it = sock->pfirst;
+- while (it) {
+- struct T_primsg *next = it->next;
+-
+- SOLDD(("socksys_release %016lx->%016lx\n", it, next));
+- mykfree((char*)it);
+- it = next;
+- }
+- filp->private_data = NULL;
+- SOLDD(("socksys_release %016lx\n", sock));
+- mykfree((char*)sock);
+- return 0;
+-}
+-
+-static unsigned int socksys_poll(struct file * filp, poll_table * wait)
+-{
+- struct inode *ino;
+- unsigned int mask = 0;
+-
+- ino=filp->f_path.dentry->d_inode;
+- if (ino && S_ISSOCK(ino->i_mode)) {
+- struct sol_socket_struct *sock;
+- sock = (struct sol_socket_struct*)filp->private_data;
+- if (sock && sock->pfirst) {
+- mask |= POLLIN | POLLRDNORM;
+- if (sock->pfirst->pri == MSG_HIPRI)
+- mask |= POLLPRI;
+- }
+- }
+- if (sock_poll)
+- mask |= (*sock_poll)(filp, wait);
+- return mask;
+-}
+-
+-static const struct file_operations socksys_fops = {
+- .open = socksys_open,
+- .release = socksys_release,
+-};
+-
+-int __init init_socksys(void)
+-{
+- int ret;
+- struct file * file;
+- int (*sys_socket)(int,int,int) =
+- (int (*)(int,int,int))SUNOS(97);
+- int (*sys_close)(unsigned int) =
+- (int (*)(unsigned int))SYS(close);
+-
+- ret = register_chrdev (30, "socksys", &socksys_fops);
+- if (ret < 0) {
+- printk ("Couldn't register socksys character device\n");
+- return ret;
+- }
+- ret = sys_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+- if (ret < 0) {
+- printk ("Couldn't create socket\n");
+- return ret;
+- }
+-
+- file = fcheck(ret);
+- /* N.B. Is this valid? Suppose the f_ops are in a module ... */
+- socksys_file_ops = *file->f_op;
+- sys_close(ret);
+- sock_poll = socksys_file_ops.poll;
+- socksys_file_ops.poll = socksys_poll;
+- socksys_file_ops.release = socksys_release;
+- return 0;
+-}
+-
+-void __exit cleanup_socksys(void)
+-{
+- unregister_chrdev(30, "socksys");
+-}
+diff --git a/arch/sparc64/solaris/socksys.h b/arch/sparc64/solaris/socksys.h
+deleted file mode 100644
+index 5d1b78e..0000000
+--- a/arch/sparc64/solaris/socksys.h
++++ /dev/null
+@@ -1,208 +0,0 @@
+-/* $Id: socksys.h,v 1.2 1998/03/26 08:46:07 jj Exp $
+- * socksys.h: Definitions for STREAMS modules emulation code.
+- *
+- * Copyright (C) 1998 Patrik Rak (prak3264 at ss1000.ms.mff.cuni.cz)
+- */
+-
+-#define MSG_HIPRI 0x01
+-#define MSG_ANY 0x02
+-#define MSG_BAND 0x04
+-
+-#define MORECTL 1
+-#define MOREDATA 2
+-
+-#define TBADADDR 1
+-#define TBADOPT 2
+-#define TACCES 3
+-#define TBADF 4
+-#define TNOADDR 5
+-#define TOUTSTATE 6
+-#define TBADSEQ 7
+-#define TSYSERR 8
+-#define TLOOK 9
+-#define TBADDATA 10
+-#define TBUFOVFLW 11
+-#define TFLOW 12
+-#define TNODATA 13
+-#define TNODIS 14
+-#define TNOUDERR 15
+-#define TBADFLAG 16
+-#define TNOREL 17
+-#define TNOTSUPPORT 18
+-#define TSTATECHNG 19
+-
+-#define T_CONN_REQ 0
+-#define T_CONN_RES 1
+-#define T_DISCON_REQ 2
+-#define T_DATA_REQ 3
+-#define T_EXDATA_REQ 4
+-#define T_INFO_REQ 5
+-#define T_BIND_REQ 6
+-#define T_UNBIND_REQ 7
+-#define T_UNITDATA_REQ 8
+-#define T_OPTMGMT_REQ 9
+-#define T_ORDREL_REQ 10
+-
+-#define T_CONN_IND 11
+-#define T_CONN_CON 12
+-#define T_DISCON_IND 13
+-#define T_DATA_IND 14
+-#define T_EXDATA_IND 15
+-#define T_INFO_ACK 16
+-#define T_BIND_ACK 17
+-#define T_ERROR_ACK 18
+-#define T_OK_ACK 19
+-#define T_UNITDATA_IND 20
+-#define T_UDERROR_IND 21
+-#define T_OPTMGMT_ACK 22
+-#define T_ORDREL_IND 23
+-
+-#define T_NEGOTIATE 0x0004
+-#define T_FAILURE 0x0040
+-
+-#define TS_UNBND 0 /* unbound */
+-#define TS_WACK_BREQ 1 /* waiting for T_BIND_REQ ack */
+-#define TS_WACK_UREQ 2 /* waiting for T_UNBIND_REQ ack */
+-#define TS_IDLE 3 /* idle */
+-#define TS_WACK_OPTREQ 4 /* waiting for T_OPTMGMT_REQ ack */
+-#define TS_WACK_CREQ 5 /* waiting for T_CONN_REQ ack */
+-#define TS_WCON_CREQ 6 /* waiting for T_CONN_REQ confirmation */
+-#define TS_WRES_CIND 7 /* waiting for T_CONN_IND */
+-#define TS_WACK_CRES 8 /* waiting for T_CONN_RES ack */
+-#define TS_DATA_XFER 9 /* data transfer */
+-#define TS_WIND_ORDREL 10 /* releasing read but not write */
+-#define TS_WREQ_ORDREL 11 /* wait to release write but not read */
+-#define TS_WACK_DREQ6 12 /* waiting for T_DISCON_REQ ack */
+-#define TS_WACK_DREQ7 13 /* waiting for T_DISCON_REQ ack */
+-#define TS_WACK_DREQ9 14 /* waiting for T_DISCON_REQ ack */
+-#define TS_WACK_DREQ10 15 /* waiting for T_DISCON_REQ ack */
+-#define TS_WACK_DREQ11 16 /* waiting for T_DISCON_REQ ack */
+-#define TS_NOSTATES 17
+-
+-struct T_conn_req {
+- s32 PRIM_type;
+- s32 DEST_length;
+- s32 DEST_offset;
+- s32 OPT_length;
+- s32 OPT_offset;
+-};
+-
+-struct T_bind_req {
+- s32 PRIM_type;
+- s32 ADDR_length;
+- s32 ADDR_offset;
+- u32 CONIND_number;
+-};
+-
+-struct T_unitdata_req {
+- s32 PRIM_type;
+- s32 DEST_length;
+- s32 DEST_offset;
+- s32 OPT_length;
+- s32 OPT_offset;
+-};
+-
+-struct T_optmgmt_req {
+- s32 PRIM_type;
+- s32 OPT_length;
+- s32 OPT_offset;
+- s32 MGMT_flags;
+-};
+-
+-struct T_bind_ack {
+- s32 PRIM_type;
+- s32 ADDR_length;
+- s32 ADDR_offset;
+- u32 CONIND_number;
+-};
+-
+-struct T_error_ack {
+- s32 PRIM_type;
+- s32 ERROR_prim;
+- s32 TLI_error;
+- s32 UNIX_error;
+-};
+-
+-struct T_ok_ack {
+- s32 PRIM_type;
+- s32 CORRECT_prim;
+-};
+-
+-struct T_conn_ind {
+- s32 PRIM_type;
+- s32 SRC_length;
+- s32 SRC_offset;
+- s32 OPT_length;
+- s32 OPT_offset;
+- s32 SEQ_number;
+-};
+-
+-struct T_conn_con {
+- s32 PRIM_type;
+- s32 RES_length;
+- s32 RES_offset;
+- s32 OPT_length;
+- s32 OPT_offset;
+-};
+-
+-struct T_discon_ind {
+- s32 PRIM_type;
+- s32 DISCON_reason;
+- s32 SEQ_number;
+-};
+-
+-struct T_unitdata_ind {
+- s32 PRIM_type;
+- s32 SRC_length;
+- s32 SRC_offset;
+- s32 OPT_length;
+- s32 OPT_offset;
+-};
+-
+-struct T_optmgmt_ack {
+- s32 PRIM_type;
+- s32 OPT_length;
+- s32 OPT_offset;
+- s32 MGMT_flags;
+-};
+-
+-struct opthdr {
+- s32 level;
+- s32 name;
+- s32 len;
+- char value[0];
+-};
+-
+-struct T_primsg {
+- struct T_primsg *next;
+- unsigned char pri;
+- unsigned char band;
+- int length;
+- s32 type;
+-};
+-
+-struct strbuf {
+- s32 maxlen;
+- s32 len;
+- u32 buf;
+-} ;
+-
+-/* Constants used by STREAMS modules emulation code */
+-
+-typedef char sol_module;
+-
+-#define MAX_NR_STREAM_MODULES 16
+-
+-/* Private data structure assigned to sockets. */
+-
+-struct sol_socket_struct {
+- int magic;
+- int modcount;
+- sol_module module[MAX_NR_STREAM_MODULES];
+- long state;
+- int offset;
+- struct T_primsg *pfirst, *plast;
+-};
+-
+-#define SOLARIS_SOCKET_MAGIC 0xADDED
+-
+diff --git a/arch/sparc64/solaris/systbl.S b/arch/sparc64/solaris/systbl.S
+deleted file mode 100644
+index 7043ca1..0000000
+--- a/arch/sparc64/solaris/systbl.S
++++ /dev/null
+@@ -1,285 +0,0 @@
+-/* $Id: systbl.S,v 1.11 2000/03/13 21:57:35 davem Exp $
+- * systbl.S: System call entry point table for Solaris compatibility.
+- *
+- * Copyright (C) 1997,1998 Jakub Jelinek (jj at sunsite.mff.cuni.cz)
+- * Copyright (C) 1996 Miguel de Icaza (miguel at nuclecu.unam.mx)
+- */
+-
+-#include <asm/unistd.h>
+-
+-/* Fall back to sys_call_table32 entry */
+-#define CHAIN(name) __NR_##name
+-
+-/* Pass pt_regs pointer as first argument */
+-#define REGS(name) name+1
+-
+-/* Hack till all be implemented */
+-#define solaris_getpmsg solaris_unimplemented
+-#define solaris_hrtsys solaris_unimplemented
+-#define solaris_msgsys solaris_unimplemented
+-#define solaris_putpmsg solaris_unimplemented
+-#define solaris_semsys solaris_unimplemented
+-
+- .data
+- .globl solaris_sys_table
+-solaris_sys_table:
+- .word solaris_unimplemented /* nosys 0 */
+- .word CHAIN(exit) /* exit d 1 */
+- .word CHAIN(fork) /* fork 2 */
+- .word CHAIN(read) /* read dpd 3 */
+- .word CHAIN(write) /* write dpd 4 */
+- .word solaris_open /* open soo 5 */
+- .word CHAIN(close) /* close d 6 */
+- .word solaris_wait /* wait xxx 7 */
+- .word CHAIN(creat) /* creat so 8 */
+- .word CHAIN(link) /* link ss 9 */
+- .word CHAIN(unlink) /* unlink s 10 */
+- .word solaris_unimplemented /* exec sxx 11 */
+- .word CHAIN(chdir) /* chdir s 12 */
+- .word CHAIN(time) /* time 13 */
+- .word solaris_mknod /* mknod sox 14 */
+- .word CHAIN(chmod) /* chmod so 15 */
+- .word CHAIN(chown) /* chown sdd 16 */
+- .word solaris_brk /* brk/break x 17 */
+- .word solaris_stat /* stat sp 18 */
+- .word CHAIN(lseek) /* seek/lseek ddd 19 */
+- .word solaris_getpid /* getpid 20 */
+- .word solaris_unimplemented /* mount 21 */
+- .word CHAIN(umount) /* umount s 22 */
+- .word CHAIN(setuid) /* setuid d 23 */
+- .word solaris_getuid /* getuid 24 */
+- .word CHAIN(stime) /* stime d 25 */
+-#if 0
+- .word solaris_ptrace /* ptrace xdxx 26 */
+-#else
+- .word CHAIN(ptrace) /* ptrace xdxx 26 */
+-#endif
+- .word CHAIN(alarm) /* alarm d 27 */
+- .word solaris_fstat /* fstat dp 28 */
+- .word CHAIN(pause) /* pause 29 */
+- .word CHAIN(utime) /* utime xx 30 */
+- .word solaris_unimplemented /* stty 31 */
+- .word solaris_unimplemented /* gtty 32 */
+- .word solaris_access /* access so 33 */
+- .word CHAIN(nice) /* nice d 34 */
+- .word solaris_statfs /* statfs spdd 35 */
+- .word CHAIN(sync) /* sync 36 */
+- .word solaris_kill /* kill dd 37 */
+- .word solaris_fstatfs /* fstatfs dpdd 38 */
+- .word solaris_procids /* pgrpsys ddd 39 */
+- .word solaris_unimplemented /* xenix 40 */
+- .word CHAIN(dup) /* dup d 41 */
+- .word CHAIN(pipe) /* pipe 42 */
+- .word CHAIN(times) /* times p 43 */
+- .word 44 /*CHAIN(profil)*/ /* prof xxxx 44 */
+- .word solaris_unimplemented /* lock/plock 45 */
+- .word CHAIN(setgid) /* setgid d 46 */
+- .word solaris_getgid /* getgid 47 */
+- .word solaris_sigfunc /* sigfunc xx 48 */
+- .word REGS(solaris_msgsys) /* msgsys dxddd 49 */
+- .word solaris_unimplemented /* syssun/3b 50 */
+- .word CHAIN(acct) /* acct/sysacct x 51 */
+- .word solaris_shmsys /* shmsys ddxo 52 */
+- .word REGS(solaris_semsys) /* semsys dddx 53 */
+- .word solaris_ioctl /* ioctl dxx 54 */
+- .word solaris_unimplemented /* uadmin xxx 55 */
+- .word solaris_unimplemented /* reserved:exch 56 */
+- .word solaris_utssys /* utssys x 57 */
+- .word CHAIN(fsync) /* fsync d 58 */
+- .word CHAIN(execve) /* execv spp 59 */
+- .word CHAIN(umask) /* umask o 60 */
+- .word CHAIN(chroot) /* chroot s 61 */
+- .word solaris_fcntl /* fcntl dxx 62 */
+- .word solaris_ulimit /* ulimit xx 63 */
+- .word solaris_unimplemented /* ? 64 */
+- .word solaris_unimplemented /* ? 65 */
+- .word solaris_unimplemented /* ? 66 */
+- .word solaris_unimplemented /* ? 67 */
+- .word solaris_unimplemented /* ? 68 */
+- .word solaris_unimplemented /* ? 69 */
+- .word solaris_unimplemented /* advfs 70 */
+- .word solaris_unimplemented /* unadvfs 71 */
+- .word solaris_unimplemented /* rmount 72 */
+- .word solaris_unimplemented /* rumount 73 */
+- .word solaris_unimplemented /* rfstart 74 */
+- .word solaris_unimplemented /* ? 75 */
+- .word solaris_unimplemented /* rdebug 76 */
+- .word solaris_unimplemented /* rfstop 77 */
+- .word solaris_unimplemented /* rfsys 78 */
+- .word CHAIN(rmdir) /* rmdir s 79 */
+- .word CHAIN(mkdir) /* mkdir so 80 */
+- .word CHAIN(getdents) /* getdents dxd 81 */
+- .word solaris_unimplemented /* libattach 82 */
+- .word solaris_unimplemented /* libdetach 83 */
+- .word CHAIN(sysfs) /* sysfs dxx 84 */
+- .word solaris_getmsg /* getmsg dxxx 85 */
+- .word solaris_putmsg /* putmsg dxxd 86 */
+- .word CHAIN(poll) /* poll xdd 87 */
+- .word solaris_lstat /* lstat sp 88 */
+- .word CHAIN(symlink) /* symlink ss 89 */
+- .word CHAIN(readlink) /* readlink spd 90 */
+- .word CHAIN(setgroups) /* setgroups dp 91 */
+- .word CHAIN(getgroups) /* getgroups dp 92 */
+- .word CHAIN(fchmod) /* fchmod do 93 */
+- .word CHAIN(fchown) /* fchown ddd 94 */
+- .word solaris_sigprocmask /* sigprocmask dxx 95 */
+- .word solaris_sigsuspend /* sigsuspend x 96 */
+- .word solaris_sigaltstack /* sigaltstack xx 97 */
+- .word solaris_sigaction /* sigaction dxx 98 */
+- .word solaris_sigpending /* sigpending dd 99 */
+- .word REGS(solaris_context) /* context 100 */
+- .word solaris_unimplemented /* evsys 101 */
+- .word solaris_unimplemented /* evtrapret 102 */
+- .word solaris_statvfs /* statvfs sp 103 */
+- .word solaris_fstatvfs /* fstatvfs dp 104 */
+- .word solaris_unimplemented /* unknown 105 */
+- .word solaris_unimplemented /* nfssys 106 */
+- .word solaris_waitid /* waitid ddxd 107 */
+- .word solaris_unimplemented /* sigsendsys ddd 108 */
+- .word REGS(solaris_hrtsys) /* hrtsys xxx 109 */
+- .word solaris_unimplemented /* acancel dxd 110 */
+- .word solaris_unimplemented /* async 111 */
+- .word solaris_unimplemented /* priocntlsys 112 */
+- .word solaris_pathconf /* pathconf sd 113 */
+- .word CHAIN(mincore) /* mincore d 114 */
+- .word solaris_mmap /* mmap xxxxdx 115 */
+- .word CHAIN(mprotect) /* mprotect xdx 116 */
+- .word CHAIN(munmap) /* munmap xd 117 */
+- .word solaris_fpathconf /* fpathconf dd 118 */
+- .word CHAIN(fork) /* fork 119 */
+- .word solaris_unimplemented /* fchdir d 120 */
+- .word CHAIN(readv) /* readv dxd 121 */
+- .word CHAIN(writev) /* writev dxd 122 */
+- .word solaris_xstat /* xstat dsx 123 */
+- .word solaris_lxstat /* lxstat dsx 124 */
+- .word solaris_fxstat /* fxstat ddx 125 */
+- .word solaris_xmknod /* xmknod dsox 126 */
+- .word solaris_unimplemented /* syslocal d 127 */
+- .word solaris_setrlimit /* setrlimit dp 128 */
+- .word solaris_getrlimit /* getrlimit dp 129 */
+- .word CHAIN(chown) /* lchown sdd 130 */
+- .word solaris_unimplemented /* memcntl 131 */
+- .word solaris_getpmsg /* getpmsg dxxxx 132 */
+- .word solaris_putpmsg /* putpmsg dxxdd 133 */
+- .word CHAIN(rename) /* rename ss 134 */
+- .word solaris_utsname /* uname x 135 */
+- .word solaris_unimplemented /* setegid 136 */
+- .word solaris_sysconf /* sysconfig d 137 */
+- .word solaris_unimplemented /* adjtime 138 */
+- .word solaris_sysinfo /* systeminfo dsd 139 */
+- .word solaris_unimplemented /* ? 140 */
+- .word solaris_unimplemented /* seteuid 141 */
+- .word solaris_unimplemented /* ? 142 */
+- .word solaris_unimplemented /* ? 143 */
+- .word solaris_unimplemented /* secsys dx 144 */
+- .word solaris_unimplemented /* filepriv sdxd 145 */
+- .word solaris_unimplemented /* procpriv dxd 146 */
+- .word solaris_unimplemented /* devstat sdx 147 */
+- .word solaris_unimplemented /* aclipc ddddx 148 */
+- .word solaris_unimplemented /* fdevstat ddx 149 */
+- .word solaris_unimplemented /* flvlfile ddx 150 */
+- .word solaris_unimplemented /* lvlfile sdx 151 */
+- .word solaris_unimplemented /* ? 152 */
+- .word solaris_unimplemented /* fchroot d 153 */
+- .word solaris_unimplemented /* lvlproc dx 154 */
+- .word solaris_unimplemented /* ? 155 */
+- .word solaris_gettimeofday /* gettimeofday x 156 */
+- .word CHAIN(getitimer) /* getitimer dx 157 */
+- .word CHAIN(setitimer) /* setitimer dxx 158 */
+- .word solaris_unimplemented /* lwp-xxx 159 */
+- .word solaris_unimplemented /* lwp-xxx 160 */
+- .word solaris_unimplemented /* lwp-xxx 161 */
+- .word solaris_unimplemented /* lwp-xxx 162 */
+- .word solaris_unimplemented /* lwp-xxx 163 */
+- .word solaris_unimplemented /* lwp-xxx 164 */
+- .word solaris_unimplemented /* lwp-xxx 165 */
+- .word solaris_unimplemented /* lwp-xxx 166 */
+- .word solaris_unimplemented /* lwp-xxx 167 */
+- .word solaris_unimplemented /* lwp-xxx 168 */
+- .word solaris_unimplemented /* lwp-xxx 169 */
+- .word solaris_unimplemented /* lwp-xxx 170 */
+- .word solaris_unimplemented /* lwp-xxx 171 */
+- .word solaris_unimplemented /* lwp-xxx 172 */
+- .word solaris_pread /* pread dpdd 173 */
+- .word solaris_pwrite /* pwrite dpdd 174 */
+- .word REGS(solaris_llseek) /* llseek dLd 175 */
+- .word solaris_unimplemented /* lwpself 176 */
+- .word solaris_unimplemented /* lwpinfo 177 */
+- .word solaris_unimplemented /* lwpprivate 178 */
+- .word solaris_unimplemented /* processorbind 179 */
+- .word solaris_unimplemented /* processorexbind 180 */
+- .word solaris_unimplemented /* 181 */
+- .word solaris_unimplemented /* sync_mailbox 182 */
+- .word solaris_unimplemented /* prepblock 183 */
+- .word solaris_unimplemented /* block 184 */
+- .word solaris_acl /* acl sddp 185 */
+- .word solaris_unimplemented /* unblock 186 */
+- .word solaris_unimplemented /* cancelblock 187 */
+- .word solaris_unimplemented /* ? 188 */
+- .word solaris_unimplemented /* xxxxx 189 */
+- .word solaris_unimplemented /* xxxxxe 190 */
+- .word solaris_unimplemented /* 191 */
+- .word solaris_unimplemented /* 192 */
+- .word solaris_unimplemented /* 193 */
+- .word solaris_unimplemented /* 194 */
+- .word solaris_unimplemented /* 195 */
+- .word solaris_unimplemented /* 196 */
+- .word solaris_unimplemented /* 197 */
+- .word solaris_unimplemented /* 198 */
+- .word CHAIN(nanosleep) /* nanosleep dd 199 */
+- .word solaris_facl /* facl dddp 200 */
+- .word solaris_unimplemented /* 201 */
+- .word CHAIN(setreuid) /* setreuid dd 202 */
+- .word CHAIN(setregid) /* setregid dd 203 */
+- .word solaris_unimplemented /* 204 */
+- .word solaris_unimplemented /* 205 */
+- .word solaris_unimplemented /* 206 */
+- .word solaris_unimplemented /* 207 */
+- .word solaris_unimplemented /* 208 */
+- .word solaris_unimplemented /* 209 */
+- .word solaris_unimplemented /* 210 */
+- .word solaris_unimplemented /* 211 */
+- .word solaris_unimplemented /* 212 */
+- .word solaris_getdents64 /* getdents64 dpd 213 */
+- .word REGS(solaris_mmap64) /* mmap64 xxxxdX 214 */
+- .word solaris_stat64 /* stat64 sP 215 */
+- .word solaris_lstat64 /* lstat64 sP 216 */
+- .word solaris_fstat64 /* fstat64 dP 217 */
+- .word solaris_statvfs64 /* statvfs64 sP 218 */
+- .word solaris_fstatvfs64 /* fstatvfs64 dP 219 */
+- .word solaris_setrlimit64 /* setrlimit64 dP 220 */
+- .word solaris_getrlimit64 /* getrlimit64 dP 221 */
+- .word CHAIN(pread64) /* pread64 dpdD 222 */
+- .word CHAIN(pwrite64) /* pwrite64 dpdD 223 */
+- .word CHAIN(creat) /* creat64 so 224 */
+- .word solaris_open /* open64 soo 225 */
+- .word solaris_unimplemented /* 226 */
+- .word solaris_unimplemented /* 227 */
+- .word solaris_unimplemented /* 228 */
+- .word solaris_unimplemented /* 229 */
+- .word solaris_socket /* socket ddd 230 */
+- .word solaris_socketpair /* socketpair dddp 231 */
+- .word solaris_bind /* bind dpd 232 */
+- .word solaris_listen /* listen dd 233 */
+- .word solaris_accept /* accept dpp 234 */
+- .word solaris_connect /* connect dpd 235 */
+- .word solaris_shutdown /* shutdown dd 236 */
+- .word solaris_recv /* recv dpdd 237 */
+- .word solaris_recvfrom /* recvfrom dpddpp 238 */
+- .word solaris_recvmsg /* recvmsg dpd 239 */
+- .word solaris_send /* send dpdd 240 */
+- .word solaris_sendmsg /* sendmsg dpd 241 */
+- .word solaris_sendto /* sendto dpddpd 242 */
+- .word solaris_getpeername /* getpeername dpp 243 */
+- .word solaris_getsockname /* getsockname dpp 244 */
+- .word solaris_getsockopt /* getsockopt dddpp 245 */
+- .word solaris_setsockopt /* setsockopt dddpp 246 */
+- .word solaris_unimplemented /* 247 */
+- .word solaris_ntp_gettime /* ntp_gettime p 248 */
+- .word solaris_ntp_adjtime /* ntp_adjtime p 249 */
+- .word solaris_unimplemented /* 250 */
+- .word solaris_unimplemented /* 251 */
+- .word solaris_unimplemented /* 252 */
+- .word solaris_unimplemented /* 253 */
+- .word solaris_unimplemented /* 254 */
+- .word solaris_unimplemented /* 255 */
+diff --git a/arch/sparc64/solaris/timod.c b/arch/sparc64/solaris/timod.c
+deleted file mode 100644
+index 15234fc..0000000
+--- a/arch/sparc64/solaris/timod.c
++++ /dev/null
+@@ -1,976 +0,0 @@
+-/* $Id: timod.c,v 1.19 2002/02/08 03:57:14 davem Exp $
+- * timod.c: timod emulation.
+- *
+- * Copyright (C) 1998 Patrik Rak (prak3264 at ss1000.ms.mff.cuni.cz)
+- *
+- * Streams & timod emulation based on code
+- * Copyright (C) 1995, 1996 Mike Jagdis (jaggy at purplet.demon.co.uk)
+- *
+- */
+-
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/smp.h>
+-#include <linux/smp_lock.h>
+-#include <linux/ioctl.h>
+-#include <linux/fs.h>
+-#include <linux/file.h>
+-#include <linux/netdevice.h>
+-#include <linux/poll.h>
+-
+-#include <net/sock.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/termios.h>
+-
+-#include "conv.h"
+-#include "socksys.h"
+-
+-asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
+-
+-static DEFINE_SPINLOCK(timod_pagelock);
+-static char * page = NULL ;
+-
+-#ifndef DEBUG_SOLARIS_KMALLOC
+-
+-#define mykmalloc kmalloc
+-#define mykfree kfree
+-
+-#else
+-
+-void * mykmalloc(size_t s, gfp_t gfp)
+-{
+- static char * page;
+- static size_t free;
+- void * r;
+- s = ((s + 63) & ~63);
+- if( s > PAGE_SIZE ) {
+- SOLD("too big size, calling real kmalloc");
+- return kmalloc(s, gfp);
+- }
+- if( s > free ) {
+- /* we are wasting memory, but we don't care */
+- page = (char *)__get_free_page(gfp);
+- free = PAGE_SIZE;
+- }
+- r = page;
+- page += s;
+- free -= s;
+- return r;
+-}
+-
+-void mykfree(void *p)
+-{
+-}
+-
+-#endif
+-
+-#ifndef DEBUG_SOLARIS
+-
+-#define BUF_SIZE PAGE_SIZE
+-#define PUT_MAGIC(a,m)
+-#define SCHECK_MAGIC(a,m)
+-#define BUF_OFFSET 0
+-#define MKCTL_TRAILER 0
+-
+-#else
+-
+-#define BUF_SIZE (PAGE_SIZE-2*sizeof(u64))
+-#define BUFPAGE_MAGIC 0xBADC0DEDDEADBABEL
+-#define MKCTL_MAGIC 0xDEADBABEBADC0DEDL
+-#define PUT_MAGIC(a,m) do{(*(u64*)(a))=(m);}while(0)
+-#define SCHECK_MAGIC(a,m) do{if((*(u64*)(a))!=(m))printk("%s,%u,%s(): magic %08x at %p corrupted!\n",\
+- __FILE__,__LINE__,__func__,(m),(a));}while(0)
+-#define BUF_OFFSET sizeof(u64)
+-#define MKCTL_TRAILER sizeof(u64)
+-
+-#endif
+-
+-static char *getpage( void )
+-{
+- char *r;
+- SOLD("getting page");
+- spin_lock(&timod_pagelock);
+- if (page) {
+- r = page;
+- page = NULL;
+- spin_unlock(&timod_pagelock);
+- SOLD("got cached");
+- return r + BUF_OFFSET;
+- }
+- spin_unlock(&timod_pagelock);
+- SOLD("getting new");
+- r = (char *)__get_free_page(GFP_KERNEL);
+- PUT_MAGIC(r,BUFPAGE_MAGIC);
+- PUT_MAGIC(r+PAGE_SIZE-sizeof(u64),BUFPAGE_MAGIC);
+- return r + BUF_OFFSET;
+-}
+-
+-static void putpage(char *p)
+-{
+- SOLD("putting page");
+- p = p - BUF_OFFSET;
+- SCHECK_MAGIC(p,BUFPAGE_MAGIC);
+- SCHECK_MAGIC(p+PAGE_SIZE-sizeof(u64),BUFPAGE_MAGIC);
+- spin_lock(&timod_pagelock);
+- if (page) {
+- spin_unlock(&timod_pagelock);
+- free_page((unsigned long)p);
+- SOLD("freed it");
+- } else {
+- page = p;
+- spin_unlock(&timod_pagelock);
+- SOLD("cached it");
+- }
+-}
+-
+-static struct T_primsg *timod_mkctl(int size)
+-{
+- struct T_primsg *it;
+-
+- SOLD("creating primsg");
+- it = (struct T_primsg *)mykmalloc(size+sizeof(*it)-sizeof(s32)+2*MKCTL_TRAILER, GFP_KERNEL);
+- if (it) {
+- SOLD("got it");
+- it->pri = MSG_HIPRI;
+- it->length = size;
+- PUT_MAGIC((char*)((u64)(((char *)&it->type)+size+7)&~7),MKCTL_MAGIC);
+- }
+- return it;
+-}
+-
+-static void timod_wake_socket(unsigned int fd)
+-{
+- struct socket *sock;
+- struct fdtable *fdt;
+-
+- SOLD("wakeing socket");
+- fdt = files_fdtable(current->files);
+- sock = SOCKET_I(fdt->fd[fd]->f_path.dentry->d_inode);
+- wake_up_interruptible(&sock->wait);
+- read_lock(&sock->sk->sk_callback_lock);
+- if (sock->fasync_list && !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
+- __kill_fasync(sock->fasync_list, SIGIO, POLL_IN);
+- read_unlock(&sock->sk->sk_callback_lock);
+- SOLD("done");
+-}
+-
+-static void timod_queue(unsigned int fd, struct T_primsg *it)
+-{
+- struct sol_socket_struct *sock;
+- struct fdtable *fdt;
+-
+- SOLD("queuing primsg");
+- fdt = files_fdtable(current->files);
+- sock = (struct sol_socket_struct *)fdt->fd[fd]->private_data;
+- it->next = sock->pfirst;
+- sock->pfirst = it;
+- if (!sock->plast)
+- sock->plast = it;
+- timod_wake_socket(fd);
+- SOLD("done");
+-}
+-
+-static void timod_queue_end(unsigned int fd, struct T_primsg *it)
+-{
+- struct sol_socket_struct *sock;
+- struct fdtable *fdt;
+-
+- SOLD("queuing primsg at end");
+- fdt = files_fdtable(current->files);
+- sock = (struct sol_socket_struct *)fdt->fd[fd]->private_data;
+- it->next = NULL;
+- if (sock->plast)
+- sock->plast->next = it;
+- else
+- sock->pfirst = it;
+- sock->plast = it;
+- SOLD("done");
+-}
+-
+-static void timod_error(unsigned int fd, int prim, int terr, int uerr)
+-{
+- struct T_primsg *it;
+-
+- SOLD("making error");
+- it = timod_mkctl(sizeof(struct T_error_ack));
+- if (it) {
+- struct T_error_ack *err = (struct T_error_ack *)&it->type;
+-
+- SOLD("got it");
+- err->PRIM_type = T_ERROR_ACK;
+- err->ERROR_prim = prim;
+- err->TLI_error = terr;
+- err->UNIX_error = uerr; /* FIXME: convert this */
+- timod_queue(fd, it);
+- }
+- SOLD("done");
+-}
+-
+-static void timod_ok(unsigned int fd, int prim)
+-{
+- struct T_primsg *it;
+- struct T_ok_ack *ok;
+-
+- SOLD("creating ok ack");
+- it = timod_mkctl(sizeof(*ok));
+- if (it) {
+- SOLD("got it");
+- ok = (struct T_ok_ack *)&it->type;
+- ok->PRIM_type = T_OK_ACK;
+- ok->CORRECT_prim = prim;
+- timod_queue(fd, it);
+- }
+- SOLD("done");
+-}
+-
+-static int timod_optmgmt(unsigned int fd, int flag, char __user *opt_buf, int opt_len, int do_ret)
+-{
+- int error, failed;
+- int ret_space, ret_len;
+- long args[5];
+- char *ret_pos,*ret_buf;
+- int (*sys_socketcall)(int, unsigned long *) =
+- (int (*)(int, unsigned long *))SYS(socketcall);
+- mm_segment_t old_fs = get_fs();
+-
+- SOLD("entry");
+- SOLDD(("fd %u flg %u buf %p len %u doret %u",fd,flag,opt_buf,opt_len,do_ret));
+- if (!do_ret && (!opt_buf || opt_len <= 0))
+- return 0;
+- SOLD("getting page");
+- ret_pos = ret_buf = getpage();
+- ret_space = BUF_SIZE;
+- ret_len = 0;
+-
+- error = failed = 0;
+- SOLD("looping");
+- while(opt_len >= sizeof(struct opthdr)) {
+- struct opthdr *opt;
+- int orig_opt_len;
+- SOLD("loop start");
+- opt = (struct opthdr *)ret_pos;
+- if (ret_space < sizeof(struct opthdr)) {
+- failed = TSYSERR;
+- break;
+- }
+- SOLD("getting opthdr");
+- if (copy_from_user(opt, opt_buf, sizeof(struct opthdr)) ||
+- opt->len > opt_len) {
+- failed = TBADOPT;
+- break;
+- }
+- SOLD("got opthdr");
+- if (flag == T_NEGOTIATE) {
+- char *buf;
+-
+- SOLD("handling T_NEGOTIATE");
+- buf = ret_pos + sizeof(struct opthdr);
+- if (ret_space < opt->len + sizeof(struct opthdr) ||
+- copy_from_user(buf, opt_buf+sizeof(struct opthdr), opt->len)) {
+- failed = TSYSERR;
+- break;
+- }
+- SOLD("got optdata");
+- args[0] = fd;
+- args[1] = opt->level;
+- args[2] = opt->name;
+- args[3] = (long)buf;
+- args[4] = opt->len;
+- SOLD("calling SETSOCKOPT");
+- set_fs(KERNEL_DS);
+- error = sys_socketcall(SYS_SETSOCKOPT, args);
+- set_fs(old_fs);
+- if (error) {
+- failed = TBADOPT;
+- break;
+- }
+- SOLD("SETSOCKOPT ok");
+- }
+- orig_opt_len = opt->len;
+- opt->len = ret_space - sizeof(struct opthdr);
+- if (opt->len < 0) {
+- failed = TSYSERR;
+- break;
+- }
+- args[0] = fd;
+- args[1] = opt->level;
+- args[2] = opt->name;
+- args[3] = (long)(ret_pos+sizeof(struct opthdr));
+- args[4] = (long)&opt->len;
+- SOLD("calling GETSOCKOPT");
+- set_fs(KERNEL_DS);
+- error = sys_socketcall(SYS_GETSOCKOPT, args);
+- set_fs(old_fs);
+- if (error) {
+- failed = TBADOPT;
+- break;
+- }
+- SOLD("GETSOCKOPT ok");
+- ret_space -= sizeof(struct opthdr) + opt->len;
+- ret_len += sizeof(struct opthdr) + opt->len;
+- ret_pos += sizeof(struct opthdr) + opt->len;
+- opt_len -= sizeof(struct opthdr) + orig_opt_len;
+- opt_buf += sizeof(struct opthdr) + orig_opt_len;
+- SOLD("loop end");
+- }
+- SOLD("loop done");
+- if (do_ret) {
+- SOLD("generating ret msg");
+- if (failed)
+- timod_error(fd, T_OPTMGMT_REQ, failed, -error);
+- else {
+- struct T_primsg *it;
+- it = timod_mkctl(sizeof(struct T_optmgmt_ack) + ret_len);
+- if (it) {
+- struct T_optmgmt_ack *ack =
+- (struct T_optmgmt_ack *)&it->type;
+- SOLD("got primsg");
+- ack->PRIM_type = T_OPTMGMT_ACK;
+- ack->OPT_length = ret_len;
+- ack->OPT_offset = sizeof(struct T_optmgmt_ack);
+- ack->MGMT_flags = (failed ? T_FAILURE : flag);
+- memcpy(((char*)ack)+sizeof(struct T_optmgmt_ack),
+- ret_buf, ret_len);
+- timod_queue(fd, it);
+- }
+- }
+- }
+- SOLDD(("put_page %p\n", ret_buf));
+- putpage(ret_buf);
+- SOLD("done");
+- return 0;
+-}
+-
+-int timod_putmsg(unsigned int fd, char __user *ctl_buf, int ctl_len,
+- char __user *data_buf, int data_len, int flags)
+-{
+- int ret, error, terror;
+- char *buf;
+- struct file *filp;
+- struct inode *ino;
+- struct fdtable *fdt;
+- struct sol_socket_struct *sock;
+- mm_segment_t old_fs = get_fs();
+- long args[6];
+- int (*sys_socketcall)(int, unsigned long __user *) =
+- (int (*)(int, unsigned long __user *))SYS(socketcall);
+- int (*sys_sendto)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int) =
+- (int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int))SYS(sendto);
+-
+- fdt = files_fdtable(current->files);
+- filp = fdt->fd[fd];
+- ino = filp->f_path.dentry->d_inode;
+- sock = (struct sol_socket_struct *)filp->private_data;
+- SOLD("entry");
+- if (get_user(ret, (int __user *)A(ctl_buf)))
+- return -EFAULT;
+- switch (ret) {
+- case T_BIND_REQ:
+- {
+- struct T_bind_req req;
+-
+- SOLDD(("bind %016lx(%016lx)\n", sock, filp));
+- SOLD("T_BIND_REQ");
+- if (sock->state != TS_UNBND) {
+- timod_error(fd, T_BIND_REQ, TOUTSTATE, 0);
+- return 0;
+- }
+- SOLD("state ok");
+- if (copy_from_user(&req, ctl_buf, sizeof(req))) {
+- timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT);
+- return 0;
+- }
+- SOLD("got ctl req");
+- if (req.ADDR_offset && req.ADDR_length) {
+- if (req.ADDR_length > BUF_SIZE) {
+- timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT);
+- return 0;
+- }
+- SOLD("req size ok");
+- buf = getpage();
+- if (copy_from_user(buf, ctl_buf + req.ADDR_offset, req.ADDR_length)) {
+- timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT);
+- putpage(buf);
+- return 0;
+- }
+- SOLD("got ctl data");
+- args[0] = fd;
+- args[1] = (long)buf;
+- args[2] = req.ADDR_length;
+- SOLD("calling BIND");
+- set_fs(KERNEL_DS);
+- error = sys_socketcall(SYS_BIND, args);
+- set_fs(old_fs);
+- putpage(buf);
+- SOLD("BIND returned");
+- } else
+- error = 0;
+- if (!error) {
+- struct T_primsg *it;
+- if (req.CONIND_number) {
+- args[0] = fd;
+- args[1] = req.CONIND_number;
+- SOLD("calling LISTEN");
+- set_fs(KERNEL_DS);
+- error = sys_socketcall(SYS_LISTEN, args);
+- set_fs(old_fs);
+- SOLD("LISTEN done");
+- }
+- it = timod_mkctl(sizeof(struct T_bind_ack)+sizeof(struct sockaddr));
+- if (it) {
+- struct T_bind_ack *ack;
+-
+- ack = (struct T_bind_ack *)&it->type;
+- ack->PRIM_type = T_BIND_ACK;
+- ack->ADDR_offset = sizeof(*ack);
+- ack->ADDR_length = sizeof(struct sockaddr);
+- ack->CONIND_number = req.CONIND_number;
+- args[0] = fd;
+- args[1] = (long)(ack+sizeof(*ack));
+- args[2] = (long)&ack->ADDR_length;
+- set_fs(KERNEL_DS);
+- sys_socketcall(SYS_GETSOCKNAME,args);
+- set_fs(old_fs);
+- sock->state = TS_IDLE;
+- timod_ok(fd, T_BIND_REQ);
+- timod_queue_end(fd, it);
+- SOLD("BIND done");
+- return 0;
+- }
+- }
+- SOLD("some error");
+- switch (error) {
+- case -EINVAL:
+- terror = TOUTSTATE;
+- error = 0;
+- break;
+- case -EACCES:
+- terror = TACCES;
+- error = 0;
+- break;
+- case -EADDRNOTAVAIL:
+- case -EADDRINUSE:
+- terror = TNOADDR;
+- error = 0;
+- break;
+- default:
+- terror = TSYSERR;
+- break;
+- }
+- timod_error(fd, T_BIND_REQ, terror, -error);
+- SOLD("BIND done");
+- return 0;
+- }
+- case T_CONN_REQ:
+- {
+- struct T_conn_req req;
+- unsigned short oldflags;
+- struct T_primsg *it;
+- SOLD("T_CONN_REQ");
+- if (sock->state != TS_UNBND && sock->state != TS_IDLE) {
+- timod_error(fd, T_CONN_REQ, TOUTSTATE, 0);
+- return 0;
+- }
+- SOLD("state ok");
+- if (copy_from_user(&req, ctl_buf, sizeof(req))) {
+- timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
+- return 0;
+- }
+- SOLD("got ctl req");
+- if (ctl_len > BUF_SIZE) {
+- timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
+- return 0;
+- }
+- SOLD("req size ok");
+- buf = getpage();
+- if (copy_from_user(buf, ctl_buf, ctl_len)) {
+- timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
+- putpage(buf);
+- return 0;
+- }
+-#ifdef DEBUG_SOLARIS
+- {
+- char * ptr = buf;
+- int len = ctl_len;
+- printk("returned data (%d bytes): ",len);
+- while( len-- ) {
+- if (!(len & 7))
+- printk(" ");
+- printk("%02x",(unsigned char)*ptr++);
+- }
+- printk("\n");
+- }
+-#endif
+- SOLD("got ctl data");
+- args[0] = fd;
+- args[1] = (long)buf+req.DEST_offset;
+- args[2] = req.DEST_length;
+- oldflags = filp->f_flags;
+- filp->f_flags &= ~O_NONBLOCK;
+- SOLD("calling CONNECT");
+- set_fs(KERNEL_DS);
+- error = sys_socketcall(SYS_CONNECT, args);
+- set_fs(old_fs);
+- filp->f_flags = oldflags;
+- SOLD("CONNECT done");
+- if (!error) {
+- struct T_conn_con *con;
+- SOLD("no error");
+- it = timod_mkctl(ctl_len);
+- if (!it) {
+- putpage(buf);
+- return -ENOMEM;
+- }
+- con = (struct T_conn_con *)&it->type;
+-#ifdef DEBUG_SOLARIS
+- {
+- char * ptr = buf;
+- int len = ctl_len;
+- printk("returned data (%d bytes): ",len);
+- while( len-- ) {
+- if (!(len & 7))
+- printk(" ");
+- printk("%02x",(unsigned char)*ptr++);
+- }
+- printk("\n");
+- }
+-#endif
+- memcpy(con, buf, ctl_len);
+- SOLD("copied ctl_buf");
+- con->PRIM_type = T_CONN_CON;
+- sock->state = TS_DATA_XFER;
+- } else {
+- struct T_discon_ind *dis;
+- SOLD("some error");
+- it = timod_mkctl(sizeof(*dis));
+- if (!it) {
+- putpage(buf);
+- return -ENOMEM;
+- }
+- SOLD("got primsg");
+- dis = (struct T_discon_ind *)&it->type;
+- dis->PRIM_type = T_DISCON_IND;
+- dis->DISCON_reason = -error; /* FIXME: convert this as in iABI_errors() */
+- dis->SEQ_number = 0;
+- }
+- putpage(buf);
+- timod_ok(fd, T_CONN_REQ);
+- it->pri = 0;
+- timod_queue_end(fd, it);
+- SOLD("CONNECT done");
+- return 0;
+- }
+- case T_OPTMGMT_REQ:
+- {
+- struct T_optmgmt_req req;
+- SOLD("OPTMGMT_REQ");
+- if (copy_from_user(&req, ctl_buf, sizeof(req)))
+- return -EFAULT;
+- SOLD("got req");
+- return timod_optmgmt(fd, req.MGMT_flags,
+- req.OPT_offset > 0 ? ctl_buf + req.OPT_offset : NULL,
+- req.OPT_length, 1);
+- }
+- case T_UNITDATA_REQ:
+- {
+- struct T_unitdata_req req;
+-
+- int err;
+- SOLD("T_UNITDATA_REQ");
+- if (sock->state != TS_IDLE && sock->state != TS_DATA_XFER) {
+- timod_error(fd, T_CONN_REQ, TOUTSTATE, 0);
+- return 0;
+- }
+- SOLD("state ok");
+- if (copy_from_user(&req, ctl_buf, sizeof(req))) {
+- timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
+- return 0;
+- }
+- SOLD("got ctl req");
+-#ifdef DEBUG_SOLARIS
+- {
+- char * ptr = ctl_buf+req.DEST_offset;
+- int len = req.DEST_length;
+- printk("socket address (%d bytes): ",len);
+- while( len-- ) {
+- char c;
+- if (get_user(c,ptr))
+- printk("??");
+- else
+- printk("%02x",(unsigned char)c);
+- ptr++;
+- }
+- printk("\n");
+- }
+-#endif
+- err = sys_sendto(fd, data_buf, data_len, 0, req.DEST_length > 0 ? (struct sockaddr __user *)(ctl_buf+req.DEST_offset) : NULL, req.DEST_length);
+- if (err == data_len)
+- return 0;
+- if(err >= 0) {
+- printk("timod: sendto failed to send all the data\n");
+- return 0;
+- }
+- timod_error(fd, T_CONN_REQ, TSYSERR, -err);
+- return 0;
+- }
+- default:
+- printk(KERN_INFO "timod_putmsg: unsupported command %u.\n", ret);
+- break;
+- }
+- return -EINVAL;
+-}
+-
+-int timod_getmsg(unsigned int fd, char __user *ctl_buf, int ctl_maxlen, s32 __user *ctl_len,
+- char __user *data_buf, int data_maxlen, s32 __user *data_len, int *flags_p)
+-{
+- int error;
+- int oldflags;
+- struct file *filp;
+- struct inode *ino;
+- struct fdtable *fdt;
+- struct sol_socket_struct *sock;
+- struct T_unitdata_ind udi;
+- mm_segment_t old_fs = get_fs();
+- long args[6];
+- char __user *tmpbuf;
+- int tmplen;
+- int (*sys_socketcall)(int, unsigned long __user *) =
+- (int (*)(int, unsigned long __user *))SYS(socketcall);
+- int (*sys_recvfrom)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *);
+-
+- SOLD("entry");
+- SOLDD(("%u %p %d %p %p %d %p %d\n", fd, ctl_buf, ctl_maxlen, ctl_len, data_buf, data_maxlen, data_len, *flags_p));
+- fdt = files_fdtable(current->files);
+- filp = fdt->fd[fd];
+- ino = filp->f_path.dentry->d_inode;
+- sock = (struct sol_socket_struct *)filp->private_data;
+- SOLDD(("%p %p\n", sock->pfirst, sock->pfirst ? sock->pfirst->next : NULL));
+- if ( ctl_maxlen > 0 && !sock->pfirst && SOCKET_I(ino)->type == SOCK_STREAM
+- && sock->state == TS_IDLE) {
+- SOLD("calling LISTEN");
+- args[0] = fd;
+- args[1] = -1;
+- set_fs(KERNEL_DS);
+- sys_socketcall(SYS_LISTEN, args);
+- set_fs(old_fs);
+- SOLD("LISTEN done");
+- }
+- if (!(filp->f_flags & O_NONBLOCK)) {
+- struct poll_wqueues wait_table;
+- poll_table *wait;
+-
+- poll_initwait(&wait_table);
+- wait = &wait_table.pt;
+- for(;;) {
+- SOLD("loop");
+- set_current_state(TASK_INTERRUPTIBLE);
+- /* ! ( l<0 || ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */
+- /* ( ! l<0 && ! ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */
+- /* ( l>=0 && ( ! l>=0 || ! ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */
+- /* ( l>=0 && ( l<0 || ( pfirst && ! (flags == HIPRI && pri != HIPRI) ) ) ) */
+- /* ( l>=0 && ( l<0 || ( pfirst && (flags != HIPRI || pri == HIPRI) ) ) ) */
+- /* ( l>=0 && ( pfirst && (flags != HIPRI || pri == HIPRI) ) ) */
+- if (ctl_maxlen >= 0 && sock->pfirst && (*flags_p != MSG_HIPRI || sock->pfirst->pri == MSG_HIPRI))
+- break;
+- SOLD("cond 1 passed");
+- if (
+- #if 1
+- *flags_p != MSG_HIPRI &&
+- #endif
+- ((filp->f_op->poll(filp, wait) & POLLIN) ||
+- (filp->f_op->poll(filp, NULL) & POLLIN) ||
+- signal_pending(current))
+- ) {
+- break;
+- }
+- if( *flags_p == MSG_HIPRI ) {
+- SOLD("avoiding lockup");
+- break ;
+- }
+- if(wait_table.error) {
+- SOLD("wait-table error");
+- poll_freewait(&wait_table);
+- return wait_table.error;
+- }
+- SOLD("scheduling");
+- schedule();
+- }
+- SOLD("loop done");
+- current->state = TASK_RUNNING;
+- poll_freewait(&wait_table);
+- if (signal_pending(current)) {
+- SOLD("signal pending");
+- return -EINTR;
+- }
+- }
+- if (ctl_maxlen >= 0 && sock->pfirst) {
+- struct T_primsg *it = sock->pfirst;
+- int l = min_t(int, ctl_maxlen, it->length);
+- SCHECK_MAGIC((char*)((u64)(((char *)&it->type)+sock->offset+it->length+7)&~7),MKCTL_MAGIC);
+- SOLD("purting ctl data");
+- if(copy_to_user(ctl_buf,
+- (char*)&it->type + sock->offset, l))
+- return -EFAULT;
+- SOLD("pur it");
+- if(put_user(l, ctl_len))
+- return -EFAULT;
+- SOLD("set ctl_len");
+- *flags_p = it->pri;
+- it->length -= l;
+- if (it->length) {
+- SOLD("more ctl");
+- sock->offset += l;
+- return MORECTL;
+- } else {
+- SOLD("removing message");
+- sock->pfirst = it->next;
+- if (!sock->pfirst)
+- sock->plast = NULL;
+- SOLDD(("getmsg kfree %016lx->%016lx\n", it, sock->pfirst));
+- mykfree(it);
+- sock->offset = 0;
+- SOLD("ctl done");
+- return 0;
+- }
+- }
+- *flags_p = 0;
+- if (ctl_maxlen >= 0) {
+- SOLD("ACCEPT perhaps?");
+- if (SOCKET_I(ino)->type == SOCK_STREAM && sock->state == TS_IDLE) {
+- struct T_conn_ind ind;
+- char *buf = getpage();
+- int len = BUF_SIZE;
+-
+- SOLD("trying ACCEPT");
+- if (put_user(ctl_maxlen - sizeof(ind), ctl_len))
+- return -EFAULT;
+- args[0] = fd;
+- args[1] = (long)buf;
+- args[2] = (long)&len;
+- oldflags = filp->f_flags;
+- filp->f_flags |= O_NONBLOCK;
+- SOLD("calling ACCEPT");
+- set_fs(KERNEL_DS);
+- error = sys_socketcall(SYS_ACCEPT, args);
+- set_fs(old_fs);
+- filp->f_flags = oldflags;
+- if (error < 0) {
+- SOLD("some error");
+- putpage(buf);
+- return error;
+- }
+- if (error) {
+- SOLD("connect");
+- putpage(buf);
+- if (sizeof(ind) > ctl_maxlen) {
+- SOLD("generating CONN_IND");
+- ind.PRIM_type = T_CONN_IND;
+- ind.SRC_length = len;
+- ind.SRC_offset = sizeof(ind);
+- ind.OPT_length = ind.OPT_offset = 0;
+- ind.SEQ_number = error;
+- if(copy_to_user(ctl_buf, &ind, sizeof(ind))||
+- put_user(sizeof(ind)+ind.SRC_length,ctl_len))
+- return -EFAULT;
+- SOLD("CONN_IND created");
+- }
+- if (data_maxlen >= 0)
+- put_user(0, data_len);
+- SOLD("CONN_IND done");
+- return 0;
+- }
+- if (len>ctl_maxlen) {
+- SOLD("data don't fit");
+- putpage(buf);
+- return -EFAULT; /* XXX - is this ok ? */
+- }
+- if(copy_to_user(ctl_buf,buf,len) || put_user(len,ctl_len)){
+- SOLD("can't copy data");
+- putpage(buf);
+- return -EFAULT;
+- }
+- SOLD("ACCEPT done");
+- putpage(buf);
+- }
+- }
+- SOLD("checking data req");
+- if (data_maxlen <= 0) {
+- if (data_maxlen == 0)
+- put_user(0, data_len);
+- if (ctl_maxlen >= 0)
+- put_user(0, ctl_len);
+- return -EAGAIN;
+- }
+- SOLD("wants data");
+- if (ctl_maxlen > sizeof(udi) && sock->state == TS_IDLE) {
+- SOLD("udi fits");
+- tmpbuf = ctl_buf + sizeof(udi);
+- tmplen = ctl_maxlen - sizeof(udi);
+- } else {
+- SOLD("udi does not fit");
+- tmpbuf = NULL;
+- tmplen = 0;
+- }
+- if (put_user(tmplen, ctl_len))
+- return -EFAULT;
+- SOLD("set ctl_len");
+- oldflags = filp->f_flags;
+- filp->f_flags |= O_NONBLOCK;
+- SOLD("calling recvfrom");
+- sys_recvfrom = (int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *))SYS(recvfrom);
+- error = sys_recvfrom(fd, data_buf, data_maxlen, 0, (struct sockaddr __user *)tmpbuf, ctl_len);
+- filp->f_flags = oldflags;
+- if (error < 0)
+- return error;
+- SOLD("error >= 0" ) ;
+- if (error && ctl_maxlen > sizeof(udi) && sock->state == TS_IDLE) {
+- SOLD("generating udi");
+- udi.PRIM_type = T_UNITDATA_IND;
+- if (get_user(udi.SRC_length, ctl_len))
+- return -EFAULT;
+- udi.SRC_offset = sizeof(udi);
+- udi.OPT_length = udi.OPT_offset = 0;
+- if (copy_to_user(ctl_buf, &udi, sizeof(udi)) ||
+- put_user(sizeof(udi)+udi.SRC_length, ctl_len))
+- return -EFAULT;
+- SOLD("udi done");
+- } else {
+- if (put_user(0, ctl_len))
+- return -EFAULT;
+- }
+- put_user(error, data_len);
+- SOLD("done");
+- return 0;
+-}
+-
+-asmlinkage int solaris_getmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
+-{
+- struct file *filp;
+- struct inode *ino;
+- struct strbuf __user *ctlptr;
+- struct strbuf __user *datptr;
+- struct strbuf ctl, dat;
+- int __user *flgptr;
+- int flags;
+- int error = -EBADF;
+- struct fdtable *fdt;
+-
+- SOLD("entry");
+- lock_kernel();
+- if (fd >= sysctl_nr_open)
+- goto out;
+-
+- fdt = files_fdtable(current->files);
+- filp = fdt->fd[fd];
+- if(!filp) goto out;
+-
+- ino = filp->f_path.dentry->d_inode;
+- if (!ino || !S_ISSOCK(ino->i_mode))
+- goto out;
+-
+- ctlptr = (struct strbuf __user *)A(arg1);
+- datptr = (struct strbuf __user *)A(arg2);
+- flgptr = (int __user *)A(arg3);
+-
+- error = -EFAULT;
+-
+- if (ctlptr) {
+- if (copy_from_user(&ctl,ctlptr,sizeof(struct strbuf)) ||
+- put_user(-1,&ctlptr->len))
+- goto out;
+- } else
+- ctl.maxlen = -1;
+-
+- if (datptr) {
+- if (copy_from_user(&dat,datptr,sizeof(struct strbuf)) ||
+- put_user(-1,&datptr->len))
+- goto out;
+- } else
+- dat.maxlen = -1;
+-
+- if (get_user(flags,flgptr))
+- goto out;
+-
+- switch (flags) {
+- case 0:
+- case MSG_HIPRI:
+- case MSG_ANY:
+- case MSG_BAND:
+- break;
+- default:
+- error = -EINVAL;
+- goto out;
+- }
+-
+- error = timod_getmsg(fd,A(ctl.buf),ctl.maxlen,&ctlptr->len,
+- A(dat.buf),dat.maxlen,&datptr->len,&flags);
+-
+- if (!error && put_user(flags,flgptr))
+- error = -EFAULT;
+-out:
+- unlock_kernel();
+- SOLD("done");
+- return error;
+-}
+-
+-asmlinkage int solaris_putmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
+-{
+- struct file *filp;
+- struct inode *ino;
+- struct strbuf __user *ctlptr;
+- struct strbuf __user *datptr;
+- struct strbuf ctl, dat;
+- int flags = (int) arg3;
+- int error = -EBADF;
+- struct fdtable *fdt;
+-
+- SOLD("entry");
+- lock_kernel();
+- if (fd >= sysctl_nr_open)
+- goto out;
+-
+- fdt = files_fdtable(current->files);
+- filp = fdt->fd[fd];
+- if(!filp) goto out;
+-
+- ino = filp->f_path.dentry->d_inode;
+- if (!ino) goto out;
+-
+- if (!S_ISSOCK(ino->i_mode) &&
+- (imajor(ino) != 30 || iminor(ino) != 1))
+- goto out;
+-
+- ctlptr = A(arg1);
+- datptr = A(arg2);
+-
+- error = -EFAULT;
+-
+- if (ctlptr) {
+- if (copy_from_user(&ctl,ctlptr,sizeof(ctl)))
+- goto out;
+- if (ctl.len < 0 && flags) {
+- error = -EINVAL;
+- goto out;
+- }
+- } else {
+- ctl.len = 0;
+- ctl.buf = 0;
+- }
+-
+- if (datptr) {
+- if (copy_from_user(&dat,datptr,sizeof(dat)))
+- goto out;
+- } else {
+- dat.len = 0;
+- dat.buf = 0;
+- }
+-
+- error = timod_putmsg(fd,A(ctl.buf),ctl.len,
+- A(dat.buf),dat.len,flags);
+-out:
+- unlock_kernel();
+- SOLD("done");
+- return error;
+-}
+diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386
+index 3cd8a04..e09edfa 100644
+--- a/arch/um/Kconfig.i386
++++ b/arch/um/Kconfig.i386
+@@ -19,10 +19,6 @@ config 64BIT
+ bool
+ default n
+
+-config SEMAPHORE_SLEEPERS
+- bool
+- default y
+-
+ config 3_LEVEL_PGTABLES
+ bool "Three-level pagetables (EXPERIMENTAL)"
+ default n
+diff --git a/arch/um/Kconfig.x86_64 b/arch/um/Kconfig.x86_64
+index 6533b34..3fbe69e 100644
+--- a/arch/um/Kconfig.x86_64
++++ b/arch/um/Kconfig.x86_64
+@@ -11,10 +11,6 @@ config RWSEM_GENERIC_SPINLOCK
+ bool
+ default y
+
+-config SEMAPHORE_SLEEPERS
+- bool
+- default y
+-
+ config 3_LEVEL_PGTABLES
+ bool
+ default y
+diff --git a/arch/um/sys-i386/ksyms.c b/arch/um/sys-i386/ksyms.c
+index 2a1eac1..bfbefd3 100644
+--- a/arch/um/sys-i386/ksyms.c
++++ b/arch/um/sys-i386/ksyms.c
+@@ -1,17 +1,5 @@
+ #include "linux/module.h"
+-#include "linux/in6.h"
+-#include "linux/rwsem.h"
+-#include "asm/byteorder.h"
+-#include "asm/delay.h"
+-#include "asm/semaphore.h"
+-#include "asm/uaccess.h"
+ #include "asm/checksum.h"
+-#include "asm/errno.h"
+-
+-EXPORT_SYMBOL(__down_failed);
+-EXPORT_SYMBOL(__down_failed_interruptible);
+-EXPORT_SYMBOL(__down_failed_trylock);
+-EXPORT_SYMBOL(__up_wakeup);
+
+ /* Networking helper routines. */
+ EXPORT_SYMBOL(csum_partial);
+diff --git a/arch/um/sys-ppc/Makefile b/arch/um/sys-ppc/Makefile
+index 0890152..b8bc844 100644
+--- a/arch/um/sys-ppc/Makefile
++++ b/arch/um/sys-ppc/Makefile
+@@ -3,7 +3,7 @@ OBJ = built-in.o
+ .S.o:
+ $(CC) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
+
+-OBJS = ptrace.o sigcontext.o semaphore.o checksum.o miscthings.o misc.o \
++OBJS = ptrace.o sigcontext.o checksum.o miscthings.o misc.o \
+ ptrace_user.o sysrq.o
+
+ EXTRA_AFLAGS := -DCONFIG_PPC32 -I. -I$(srctree)/arch/ppc/kernel
+@@ -20,10 +20,6 @@ ptrace_user.o: ptrace_user.c
+ sigcontext.o: sigcontext.c
+ $(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
+
+-semaphore.c:
+- rm -f $@
+- ln -s $(srctree)/arch/ppc/kernel/$@ $@
+-
+ checksum.S:
+ rm -f $@
+ ln -s $(srctree)/arch/ppc/lib/$@ $@
+@@ -66,4 +62,4 @@ misc.o: misc.S ppc_defs.h
+ $(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
+ rm -f asm
+
+-clean-files := $(OBJS) ppc_defs.h checksum.S semaphore.c mk_defs.c
++clean-files := $(OBJS) ppc_defs.h checksum.S mk_defs.c
+diff --git a/arch/um/sys-x86_64/ksyms.c b/arch/um/sys-x86_64/ksyms.c
+index 12c5936..4d7d1a8 100644
+--- a/arch/um/sys-x86_64/ksyms.c
++++ b/arch/um/sys-x86_64/ksyms.c
+@@ -1,16 +1,5 @@
+ #include "linux/module.h"
+-#include "linux/in6.h"
+-#include "linux/rwsem.h"
+-#include "asm/byteorder.h"
+-#include "asm/semaphore.h"
+-#include "asm/uaccess.h"
+-#include "asm/checksum.h"
+-#include "asm/errno.h"
+-
+-EXPORT_SYMBOL(__down_failed);
+-EXPORT_SYMBOL(__down_failed_interruptible);
+-EXPORT_SYMBOL(__down_failed_trylock);
+-EXPORT_SYMBOL(__up_wakeup);
++#include "asm/string.h"
+
+ /*XXX: we need them because they would be exported by x86_64 */
+ EXPORT_SYMBOL(__memcpy);
+diff --git a/arch/v850/kernel/Makefile b/arch/v850/kernel/Makefile
+index 3930482..da5889c 100644
+--- a/arch/v850/kernel/Makefile
++++ b/arch/v850/kernel/Makefile
+@@ -11,7 +11,7 @@
+
+ extra-y := head.o init_task.o vmlinux.lds
+
+-obj-y += intv.o entry.o process.o syscalls.o time.o semaphore.o setup.o \
++obj-y += intv.o entry.o process.o syscalls.o time.o setup.o \
+ signal.o irq.o mach.o ptrace.o bug.o
+ obj-$(CONFIG_MODULES) += module.o v850_ksyms.o
+ # chip-specific code
+diff --git a/arch/v850/kernel/semaphore.c b/arch/v850/kernel/semaphore.c
+deleted file mode 100644
+index fc89fd6..0000000
+--- a/arch/v850/kernel/semaphore.c
++++ /dev/null
+@@ -1,166 +0,0 @@
+-/*
+- * arch/v850/kernel/semaphore.c -- Semaphore support
+- *
+- * Copyright (C) 1998-2000 IBM Corporation
+- * Copyright (C) 1999 Linus Torvalds
+- *
+- * This file is subject to the terms and conditions of the GNU General
+- * Public License. See the file COPYING in the main directory of this
+- * archive for more details.
+- *
+- * This file is a copy of the s390 version, arch/s390/kernel/semaphore.c
+- * Author(s): Martin Schwidefsky
+- * which was derived from the i386 version, linux/arch/i386/kernel/semaphore.c
+- */
+-
+-#include <linux/errno.h>
+-#include <linux/sched.h>
+-#include <linux/init.h>
+-
+-#include <asm/semaphore.h>
+-
+-/*
+- * Semaphores are implemented using a two-way counter:
+- * The "count" variable is decremented for each process
+- * that tries to acquire the semaphore, while the "sleeping"
+- * variable is a count of such acquires.
+- *
+- * Notably, the inline "up()" and "down()" functions can
+- * efficiently test if they need to do any extra work (up
+- * needs to do something only if count was negative before
+- * the increment operation.
+- *
+- * "sleeping" and the contention routine ordering is
+- * protected by the semaphore spinlock.
+- *
+- * Note that these functions are only called when there is
+- * contention on the lock, and as such all this is the
+- * "non-critical" part of the whole semaphore business. The
+- * critical part is the inline stuff in <asm/semaphore.h>
+- * where we want to avoid any extra jumps and calls.
+- */
+-
+-/*
+- * Logic:
+- * - only on a boundary condition do we need to care. When we go
+- * from a negative count to a non-negative, we wake people up.
+- * - when we go from a non-negative count to a negative do we
+- * (a) synchronize with the "sleeper" count and (b) make sure
+- * that we're on the wakeup list before we synchronize so that
+- * we cannot lose wakeup events.
+- */
+-
+-void __up(struct semaphore *sem)
+-{
+- wake_up(&sem->wait);
+-}
+-
+-static DEFINE_SPINLOCK(semaphore_lock);
+-
+-void __sched __down(struct semaphore * sem)
+-{
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+- tsk->state = TASK_UNINTERRUPTIBLE;
+- add_wait_queue_exclusive(&sem->wait, &wait);
+-
+- spin_lock_irq(&semaphore_lock);
+- sem->sleepers++;
+- for (;;) {
+- int sleepers = sem->sleepers;
+-
+- /*
+- * Add "everybody else" into it. They aren't
+- * playing, because we own the spinlock.
+- */
+- if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+- sem->sleepers = 0;
+- break;
+- }
+- sem->sleepers = 1; /* us - see -1 above */
+- spin_unlock_irq(&semaphore_lock);
+-
+- schedule();
+- tsk->state = TASK_UNINTERRUPTIBLE;
+- spin_lock_irq(&semaphore_lock);
+- }
+- spin_unlock_irq(&semaphore_lock);
+- remove_wait_queue(&sem->wait, &wait);
+- tsk->state = TASK_RUNNING;
+- wake_up(&sem->wait);
+-}
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+- int retval = 0;
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+- tsk->state = TASK_INTERRUPTIBLE;
+- add_wait_queue_exclusive(&sem->wait, &wait);
+-
+- spin_lock_irq(&semaphore_lock);
+- sem->sleepers ++;
+- for (;;) {
+- int sleepers = sem->sleepers;
+-
+- /*
+- * With signals pending, this turns into
+- * the trylock failure case - we won't be
+- * sleeping, and we* can't get the lock as
+- * it has contention. Just correct the count
+- * and exit.
+- */
+- if (signal_pending(current)) {
+- retval = -EINTR;
+- sem->sleepers = 0;
+- atomic_add(sleepers, &sem->count);
+- break;
+- }
+-
+- /*
+- * Add "everybody else" into it. They aren't
+- * playing, because we own the spinlock. The
+- * "-1" is because we're still hoping to get
+- * the lock.
+- */
+- if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+- sem->sleepers = 0;
+- break;
+- }
+- sem->sleepers = 1; /* us - see -1 above */
+- spin_unlock_irq(&semaphore_lock);
+-
+- schedule();
+- tsk->state = TASK_INTERRUPTIBLE;
+- spin_lock_irq(&semaphore_lock);
+- }
+- spin_unlock_irq(&semaphore_lock);
+- tsk->state = TASK_RUNNING;
+- remove_wait_queue(&sem->wait, &wait);
+- wake_up(&sem->wait);
+- return retval;
+-}
+-
+-/*
+- * Trylock failed - make sure we correct for
+- * having decremented the count.
+- */
+-int __down_trylock(struct semaphore * sem)
+-{
+- unsigned long flags;
+- int sleepers;
+-
+- spin_lock_irqsave(&semaphore_lock, flags);
+- sleepers = sem->sleepers + 1;
+- sem->sleepers = 0;
+-
+- /*
+- * Add "everybody else" and us into it. They aren't
+- * playing, because we own the spinlock.
+- */
+- if (!atomic_add_negative(sleepers, &sem->count))
+- wake_up(&sem->wait);
+-
+- spin_unlock_irqrestore(&semaphore_lock, flags);
+- return 1;
+-}
+diff --git a/arch/v850/kernel/syscalls.c b/arch/v850/kernel/syscalls.c
+index 0a4df4d..003db9c 100644
+--- a/arch/v850/kernel/syscalls.c
++++ b/arch/v850/kernel/syscalls.c
+@@ -30,7 +30,6 @@
+ #include <linux/file.h>
+
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #include <asm/unistd.h>
+
+ /*
+diff --git a/arch/v850/kernel/v850_ksyms.c b/arch/v850/kernel/v850_ksyms.c
+index 93575fd..8d386a5 100644
+--- a/arch/v850/kernel/v850_ksyms.c
++++ b/arch/v850/kernel/v850_ksyms.c
+@@ -11,7 +11,6 @@
+ #include <asm/pgalloc.h>
+ #include <asm/irq.h>
+ #include <asm/io.h>
+-#include <asm/semaphore.h>
+ #include <asm/checksum.h>
+ #include <asm/current.h>
+
+@@ -34,12 +33,6 @@ EXPORT_SYMBOL (memset);
+ EXPORT_SYMBOL (memcpy);
+ EXPORT_SYMBOL (memmove);
+
+-/* semaphores */
+-EXPORT_SYMBOL (__down);
+-EXPORT_SYMBOL (__down_interruptible);
+-EXPORT_SYMBOL (__down_trylock);
+-EXPORT_SYMBOL (__up);
+-
+ /*
+ * libgcc functions - functions that are used internally by the
+ * compiler... (prototypes are not correct though, but that
+diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
+index 6c70fed..2fadf79 100644
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -23,6 +23,7 @@ config X86
+ select HAVE_KPROBES
+ select HAVE_KRETPROBES
+ select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64)
++ select HAVE_ARCH_KGDB if !X86_VOYAGER
+
+
+ config GENERIC_LOCKBREAK
+@@ -53,9 +54,6 @@ config STACKTRACE_SUPPORT
+ config HAVE_LATENCYTOP_SUPPORT
+ def_bool y
+
+-config SEMAPHORE_SLEEPERS
+- def_bool y
+-
+ config FAST_CMPXCHG_LOCAL
+ bool
+ default y
+@@ -117,7 +115,10 @@ config ARCH_HAS_CPU_RELAX
+ def_bool y
+
+ config HAVE_SETUP_PER_CPU_AREA
+- def_bool X86_64
++ def_bool X86_64 || (X86_SMP && !X86_VOYAGER)
++
++config HAVE_CPUMASK_OF_CPU_MAP
++ def_bool X86_64_SMP
+
+ config ARCH_HIBERNATION_POSSIBLE
+ def_bool y
+@@ -141,6 +142,9 @@ config AUDIT_ARCH
+ config ARCH_SUPPORTS_AOUT
+ def_bool y
+
++config ARCH_SUPPORTS_OPTIMIZED_INLINING
++ def_bool y
++
+ # Use the generic interrupt handling code in kernel/irq/:
+ config GENERIC_HARDIRQS
+ bool
+@@ -171,7 +175,7 @@ config X86_64_SMP
+ config X86_HT
+ bool
+ depends on SMP
+- depends on (X86_32 && !(X86_VISWS || X86_VOYAGER)) || (X86_64 && !MK8)
++ depends on (X86_32 && !(X86_VISWS || X86_VOYAGER)) || X86_64
+ default y
+
+ config X86_BIOS_REBOOT
+@@ -181,7 +185,7 @@ config X86_BIOS_REBOOT
+
+ config X86_TRAMPOLINE
+ bool
+- depends on X86_SMP || (X86_VOYAGER && SMP)
++ depends on X86_SMP || (X86_VOYAGER && SMP) || (64BIT && ACPI_SLEEP)
+ default y
+
+ config KTIME_SCALAR
+@@ -241,8 +245,7 @@ config X86_ELAN
+
+ config X86_VOYAGER
+ bool "Voyager (NCR)"
+- depends on X86_32
+- select SMP if !BROKEN
++ depends on X86_32 && (SMP || BROKEN)
+ help
+ Voyager is an MCA-based 32-way capable SMP architecture proprietary
+ to NCR Corp. Machine classes 345x/35xx/4100/51xx are Voyager-based.
+@@ -254,9 +257,8 @@ config X86_VOYAGER
+
+ config X86_NUMAQ
+ bool "NUMAQ (IBM/Sequent)"
+- select SMP
++ depends on SMP && X86_32
+ select NUMA
+- depends on X86_32
+ help
+ This option is used for getting Linux to run on a (IBM/Sequent) NUMA
+ multiquad box. This changes the way that processors are bootstrapped,
+@@ -327,8 +329,9 @@ config X86_RDC321X
+
+ config X86_VSMP
+ bool "Support for ScaleMP vSMP"
+- depends on X86_64 && PCI
+- help
++ select PARAVIRT
++ depends on X86_64
++ help
+ Support for ScaleMP vSMP systems. Say 'Y' here if this kernel is
+ supposed to run on these EM64T-based machines. Only choose this option
+ if you have one of these machines.
+@@ -383,6 +386,35 @@ config PARAVIRT
+
+ endif
+
++config MEMTEST_BOOTPARAM
++ bool "Memtest boot parameter"
++ depends on X86_64
++ default y
++ help
++ This option adds a kernel parameter 'memtest', which allows memtest
++ to be disabled at boot. If this option is selected, memtest
++ functionality can be disabled with memtest=0 on the kernel
++ command line. The purpose of this option is to allow a single
++ kernel image to be distributed with memtest built in, but not
++ necessarily enabled.
++
++ If you are unsure how to answer this question, answer Y.
++
++config MEMTEST_BOOTPARAM_VALUE
++ int "Memtest boot parameter default value (0-4)"
++ depends on MEMTEST_BOOTPARAM
++ range 0 4
++ default 0
++ help
++ This option sets the default value for the kernel parameter
++ 'memtest', which allows memtest to be disabled at boot. If this
++ option is set to 0 (zero), the memtest kernel parameter will
++ default to 0, disabling memtest at bootup. If this option is
++ set to 4, the memtest kernel parameter will default to 4,
++ enabling memtest at bootup, and use that as pattern number.
++
++ If you are unsure how to answer this question, answer 0.
++
+ config ACPI_SRAT
+ def_bool y
+ depends on X86_32 && ACPI && NUMA && (X86_SUMMIT || X86_GENERICARCH)
+@@ -507,7 +539,7 @@ config NR_CPUS
+
+ config SCHED_SMT
+ bool "SMT (Hyperthreading) scheduler support"
+- depends on (X86_64 && SMP) || (X86_32 && X86_HT)
++ depends on X86_HT
+ help
+ SMT scheduler support improves the CPU scheduler's decision making
+ when dealing with Intel Pentium 4 chips with HyperThreading at a
+@@ -517,7 +549,7 @@ config SCHED_SMT
+ config SCHED_MC
+ def_bool y
+ prompt "Multi-core scheduler support"
+- depends on (X86_64 && SMP) || (X86_32 && X86_HT)
++ depends on X86_HT
+ help
+ Multi-core scheduler support improves the CPU scheduler's decision
+ making when dealing with multi-core CPU chips at a cost of slightly
+@@ -877,6 +909,15 @@ config X86_64_ACPI_NUMA
+ help
+ Enable ACPI SRAT based node topology detection.
+
++# Some NUMA nodes have memory ranges that span
++# other nodes. Even though a pfn is valid and
++# between a node's start and end pfns, it may not
++# reside on that node. See memmap_init_zone()
++# for details.
++config NODES_SPAN_OTHER_NODES
++ def_bool y
++ depends on X86_64_ACPI_NUMA
++
+ config NUMA_EMU
+ bool "NUMA emulation"
+ depends on X86_64 && NUMA
+@@ -886,7 +927,7 @@ config NUMA_EMU
+ number of nodes. This is only useful for debugging.
+
+ config NODES_SHIFT
+- int
++ int "Max num nodes shift(1-15)"
+ range 1 15 if X86_64
+ default "6" if X86_64
+ default "4" if X86_NUMAQ
+@@ -1010,6 +1051,21 @@ config MTRR
+
+ See <file:Documentation/mtrr.txt> for more information.
+
++config X86_PAT
++ bool
++ prompt "x86 PAT support"
++ depends on MTRR
++ help
++ Use PAT attributes to setup page level cache control.
++
++ PATs are the modern equivalents of MTRRs and are much more
++ flexible than MTRRs.
++
++ Say N here if you see bootup problems (boot crash, boot hang,
++ spontaneous reboots) or a non-working video driver.
++
++ If unsure, say Y.
++
+ config EFI
+ def_bool n
+ prompt "EFI runtime service support"
+@@ -1078,6 +1134,7 @@ source kernel/Kconfig.hz
+
+ config KEXEC
+ bool "kexec system call"
++ depends on X86_64 || X86_BIOS_REBOOT
+ help
+ kexec is a system call that implements the ability to shutdown your
+ current kernel, and to start another kernel. It is like a reboot
+@@ -1379,7 +1436,7 @@ endmenu
+ menu "Bus options (PCI etc.)"
+
+ config PCI
+- bool "PCI support" if !X86_VISWS
++ bool "PCI support" if !X86_VISWS && !X86_VSMP
+ depends on !X86_VOYAGER
+ default y
+ select ARCH_SUPPORTS_MSI if (X86_LOCAL_APIC && X86_IO_APIC)
+diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu
+index 9304bfb..4da3cdb 100644
+--- a/arch/x86/Kconfig.cpu
++++ b/arch/x86/Kconfig.cpu
+@@ -21,8 +21,8 @@ config M386
+
+ Here are the settings recommended for greatest speed:
+ - "386" for the AMD/Cyrix/Intel 386DX/DXL/SL/SLC/SX, Cyrix/TI
+- 486DLC/DLC2, UMC 486SX-S and NexGen Nx586. Only "386" kernels
+- will run on a 386 class machine.
++ 486DLC/DLC2, and UMC 486SX-S. Only "386" kernels will run on a 386
++ class machine.
+ - "486" for the AMD/Cyrix/IBM/Intel 486DX/DX2/DX4 or
+ SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or U5S.
+ - "586" for generic Pentium CPUs lacking the TSC
+@@ -388,7 +388,7 @@ config X86_OOSTORE
+ #
+ config X86_P6_NOP
+ def_bool y
+- depends on (X86_64 || !X86_GENERIC) && (M686 || MPENTIUMII || MPENTIUMIII || MPENTIUMM || MCORE2 || MPENTIUM4)
++ depends on (X86_64 || !X86_GENERIC) && (M686 || MPENTIUMII || MPENTIUMIII || MPENTIUMM || MCORE2 || MPENTIUM4 || MPSC)
+
+ config X86_TSC
+ def_bool y
+diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
+index 702eb39..5b1979a 100644
+--- a/arch/x86/Kconfig.debug
++++ b/arch/x86/Kconfig.debug
+@@ -5,6 +5,17 @@ config TRACE_IRQFLAGS_SUPPORT
+
+ source "lib/Kconfig.debug"
+
++config NONPROMISC_DEVMEM
++ bool "Disable promiscuous /dev/mem"
++ help
++ The /dev/mem file by default only allows userspace access to PCI
++ space and the BIOS code and data regions. This is sufficient for
++ dosemu and X and all common users of /dev/mem. With this config
++ option, you allow userspace access to all of memory, including
++ kernel and userspace memory. Accidental access to this is
++ obviously disasterous, but specific access can be used by people
++ debugging the kernel.
++
+ config EARLY_PRINTK
+ bool "Early printk" if EMBEDDED
+ default y
+@@ -54,6 +65,18 @@ config DEBUG_PER_CPU_MAPS
+
+ Say N if unsure.
+
++config X86_PTDUMP
++ bool "Export kernel pagetable layout to userspace via debugfs"
++ depends on DEBUG_KERNEL
++ select DEBUG_FS
++ help
++ Say Y here if you want to show the kernel pagetable layout in a
++ debugfs file. This information is only useful for kernel developers
++ who are working in architecture specific areas of the kernel.
++ It is probably not a good idea to enable this feature in a production
++ kernel.
++ If in doubt, say "N"
++
+ config DEBUG_RODATA
+ bool "Write protect kernel read-only data structures"
+ default y
+@@ -64,6 +87,18 @@ config DEBUG_RODATA
+ data. This is recommended so that we can catch kernel bugs sooner.
+ If in doubt, say "Y".
+
++config DIRECT_GBPAGES
++ bool "Enable gbpages-mapped kernel pagetables"
++ depends on DEBUG_KERNEL && EXPERIMENTAL && X86_64
++ help
++ Enable gigabyte pages support (if the CPU supports it). This can
++ improve the kernel's performance a tiny bit by reducing TLB
++ pressure.
++
++ This is experimental code.
++
++ If in doubt, say "N".
++
+ config DEBUG_RODATA_TEST
+ bool "Testcase for the DEBUG_RODATA feature"
+ depends on DEBUG_RODATA
+@@ -82,8 +117,8 @@ config DEBUG_NX_TEST
+
+ config 4KSTACKS
+ bool "Use 4Kb for kernel stacks instead of 8Kb"
+- depends on DEBUG_KERNEL
+ depends on X86_32
++ default y
+ help
+ If you say Y here the kernel will use a 4Kb stacksize for the
+ kernel stack attached to each process/thread. This facilitates
+@@ -222,3 +257,16 @@ config CPA_DEBUG
+ Do change_page_attr() self-tests every 30 seconds.
+
+ endmenu
++
++config OPTIMIZE_INLINING
++ bool "Allow gcc to uninline functions marked 'inline'"
++ default y
++ help
++ This option determines if the kernel forces gcc to inline the functions
++ developers have marked 'inline'. Doing so takes away freedom from gcc to
++ do what it thinks is best, which is desirable for the gcc 3.x series of
++ compilers. The gcc 4.x series have a rewritten inlining algorithm and
++ disabling this option will generate a smaller kernel there. Hopefully
++ this algorithm is so good that allowing gcc4 to make the decision can
++ become the default in the future, until then this option is there to
++ test gcc for this.
+diff --git a/arch/x86/Makefile b/arch/x86/Makefile
+index f1e739a..3cff3c8 100644
+--- a/arch/x86/Makefile
++++ b/arch/x86/Makefile
+@@ -151,7 +151,6 @@ mflags-y += -Iinclude/asm-x86/mach-default
+ # 64 bit does not support subarch support - clear sub arch variables
+ fcore-$(CONFIG_X86_64) :=
+ mcore-$(CONFIG_X86_64) :=
+-mflags-$(CONFIG_X86_64) :=
+
+ KBUILD_CFLAGS += $(mflags-y)
+ KBUILD_AFLAGS += $(mflags-y)
+@@ -159,9 +158,9 @@ KBUILD_AFLAGS += $(mflags-y)
+ ###
+ # Kernel objects
+
+-head-y := arch/x86/kernel/head_$(BITS).o
+-head-$(CONFIG_X86_64) += arch/x86/kernel/head64.o
+-head-y += arch/x86/kernel/init_task.o
++head-y := arch/x86/kernel/head_$(BITS).o
++head-y += arch/x86/kernel/head$(BITS).o
++head-y += arch/x86/kernel/init_task.o
+
+ libs-y += arch/x86/lib/
+
+diff --git a/arch/x86/boot/.gitignore b/arch/x86/boot/.gitignore
+index b1bdc4c..172cf8a 100644
+--- a/arch/x86/boot/.gitignore
++++ b/arch/x86/boot/.gitignore
+@@ -1,7 +1,8 @@
+ bootsect
+ bzImage
++cpustr.h
++mkcpustr
++offsets.h
+ setup
+ setup.bin
+ setup.elf
+-cpustr.h
+-mkcpustr
+diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
+index f88458e..7ee102f 100644
+--- a/arch/x86/boot/Makefile
++++ b/arch/x86/boot/Makefile
+@@ -30,7 +30,7 @@ subdir- := compressed
+
+ setup-y += a20.o cmdline.o copy.o cpu.o cpucheck.o edd.o
+ setup-y += header.o main.o mca.o memory.o pm.o pmjump.o
+-setup-y += printf.o string.o tty.o video.o version.o
++setup-y += printf.o string.o tty.o video.o video-mode.o version.o
+ setup-$(CONFIG_X86_APM_BOOT) += apm.o
+ setup-$(CONFIG_X86_VOYAGER) += voyager.o
+
+@@ -94,6 +94,20 @@ $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
+
+ SETUP_OBJS = $(addprefix $(obj)/,$(setup-y))
+
++sed-offsets := -e 's/^00*/0/' \
++ -e 's/^\([0-9a-fA-F]*\) . \(input_data\|input_data_end\)$$/\#define \2 0x\1/p'
++
++quiet_cmd_offsets = OFFSETS $@
++ cmd_offsets = $(NM) $< | sed -n $(sed-offsets) > $@
++
++$(obj)/offsets.h: $(obj)/compressed/vmlinux FORCE
++ $(call if_changed,offsets)
++
++targets += offsets.h
++
++AFLAGS_header.o += -I$(obj)
++$(obj)/header.o: $(obj)/offsets.h
++
+ LDFLAGS_setup.elf := -T
+ $(obj)/setup.elf: $(src)/setup.ld $(SETUP_OBJS) FORCE
+ $(call if_changed,ld)
+diff --git a/arch/x86/boot/a20.c b/arch/x86/boot/a20.c
+index 31348d0..90943f8 100644
+--- a/arch/x86/boot/a20.c
++++ b/arch/x86/boot/a20.c
+@@ -9,8 +9,6 @@
+ * ----------------------------------------------------------------------- */
+
+ /*
+- * arch/i386/boot/a20.c
+- *
+ * Enable A20 gate (return -1 on failure)
+ */
+
+diff --git a/arch/x86/boot/apm.c b/arch/x86/boot/apm.c
+index c117c7f..7aa6033 100644
+--- a/arch/x86/boot/apm.c
++++ b/arch/x86/boot/apm.c
+@@ -12,8 +12,6 @@
+ * ----------------------------------------------------------------------- */
+
+ /*
+- * arch/i386/boot/apm.c
+- *
+ * Get APM BIOS information
+ */
+
+diff --git a/arch/x86/boot/bitops.h b/arch/x86/boot/bitops.h
+index 8dcc8dc..878e4b9 100644
+--- a/arch/x86/boot/bitops.h
++++ b/arch/x86/boot/bitops.h
+@@ -9,8 +9,6 @@
+ * ----------------------------------------------------------------------- */
+
+ /*
+- * arch/i386/boot/bitops.h
+- *
+ * Very simple bitops for the boot code.
+ */
+
+diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
+index 7822a49..a34b998 100644
+--- a/arch/x86/boot/boot.h
++++ b/arch/x86/boot/boot.h
+@@ -9,8 +9,6 @@
+ * ----------------------------------------------------------------------- */
+
+ /*
+- * arch/i386/boot/boot.h
+- *
+ * Header file for the real-mode kernel code
+ */
+
+@@ -286,6 +284,11 @@ int getchar_timeout(void);
+ /* video.c */
+ void set_video(void);
+
++/* video-mode.c */
++int set_mode(u16 mode);
++int mode_defined(u16 mode);
++void probe_cards(int unsafe);
++
+ /* video-vesa.c */
+ void vesa_store_edid(void);
+
+diff --git a/arch/x86/boot/cmdline.c b/arch/x86/boot/cmdline.c
+index 680408a..a1d3563 100644
+--- a/arch/x86/boot/cmdline.c
++++ b/arch/x86/boot/cmdline.c
+@@ -9,8 +9,6 @@
+ * ----------------------------------------------------------------------- */
+
+ /*
+- * arch/i386/boot/cmdline.c
+- *
+ * Simple command-line parser for early boot.
+ */
+
+diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
+index d2b9f3b..92fdd35 100644
+--- a/arch/x86/boot/compressed/Makefile
++++ b/arch/x86/boot/compressed/Makefile
+@@ -22,7 +22,7 @@ $(obj)/vmlinux: $(src)/vmlinux_$(BITS).lds $(obj)/head_$(BITS).o $(obj)/misc.o $
+ $(call if_changed,ld)
+ @:
+
+-OBJCOPYFLAGS_vmlinux.bin := -O binary -R .note -R .comment -S
++OBJCOPYFLAGS_vmlinux.bin := -R .comment -S
+ $(obj)/vmlinux.bin: vmlinux FORCE
+ $(call if_changed,objcopy)
+
+diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
+index 036e635..ba7736c 100644
+--- a/arch/x86/boot/compressed/head_32.S
++++ b/arch/x86/boot/compressed/head_32.S
+@@ -130,7 +130,7 @@ relocated:
+ /*
+ * Setup the stack for the decompressor
+ */
+- leal stack_end(%ebx), %esp
++ leal boot_stack_end(%ebx), %esp
+
+ /*
+ * Do the decompression, and jump to the new kernel..
+@@ -142,8 +142,8 @@ relocated:
+ pushl %eax # input_len
+ leal input_data(%ebx), %eax
+ pushl %eax # input_data
+- leal _end(%ebx), %eax
+- pushl %eax # end of the image as third argument
++ leal boot_heap(%ebx), %eax
++ pushl %eax # heap area as third argument
+ pushl %esi # real mode pointer as second arg
+ call decompress_kernel
+ addl $20, %esp
+@@ -181,7 +181,10 @@ relocated:
+ jmp *%ebp
+
+ .bss
++/* Stack and heap for uncompression */
+ .balign 4
+-stack:
+- .fill 4096, 1, 0
+-stack_end:
++boot_heap:
++ .fill BOOT_HEAP_SIZE, 1, 0
++boot_stack:
++ .fill BOOT_STACK_SIZE, 1, 0
++boot_stack_end:
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index e8657b9..d8819ef 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -28,6 +28,7 @@
+ #include <asm/segment.h>
+ #include <asm/pgtable.h>
+ #include <asm/page.h>
++#include <asm/boot.h>
+ #include <asm/msr.h>
+ #include <asm/asm-offsets.h>
+
+@@ -62,7 +63,7 @@ startup_32:
+ subl $1b, %ebp
+
+ /* setup a stack and make sure cpu supports long mode. */
+- movl $user_stack_end, %eax
++ movl $boot_stack_end, %eax
+ addl %ebp, %eax
+ movl %eax, %esp
+
+@@ -243,9 +244,9 @@ ENTRY(startup_64)
+ /* Copy the compressed kernel to the end of our buffer
+ * where decompression in place becomes safe.
+ */
+- leaq _end(%rip), %r8
+- leaq _end(%rbx), %r9
+- movq $_end /* - $startup_32 */, %rcx
++ leaq _end_before_pgt(%rip), %r8
++ leaq _end_before_pgt(%rbx), %r9
++ movq $_end_before_pgt /* - $startup_32 */, %rcx
+ 1: subq $8, %r8
+ subq $8, %r9
+ movq 0(%r8), %rax
+@@ -267,14 +268,14 @@ relocated:
+ */
+ xorq %rax, %rax
+ leaq _edata(%rbx), %rdi
+- leaq _end(%rbx), %rcx
++ leaq _end_before_pgt(%rbx), %rcx
+ subq %rdi, %rcx
+ cld
+ rep
+ stosb
+
+ /* Setup the stack */
+- leaq user_stack_end(%rip), %rsp
++ leaq boot_stack_end(%rip), %rsp
+
+ /* zero EFLAGS after setting rsp */
+ pushq $0
+@@ -285,7 +286,7 @@ relocated:
+ */
+ pushq %rsi # Save the real mode argument
+ movq %rsi, %rdi # real mode address
+- leaq _heap(%rip), %rsi # _heap
++ leaq boot_heap(%rip), %rsi # malloc area for uncompression
+ leaq input_data(%rip), %rdx # input_data
+ movl input_len(%rip), %eax
+ movq %rax, %rcx # input_len
+@@ -310,9 +311,12 @@ gdt:
+ .quad 0x0080890000000000 /* TS descriptor */
+ .quad 0x0000000000000000 /* TS continued */
+ gdt_end:
+- .bss
+-/* Stack for uncompression */
+- .balign 4
+-user_stack:
+- .fill 4096,4,0
+-user_stack_end:
++
++.bss
++/* Stack and heap for uncompression */
++.balign 4
++boot_heap:
++ .fill BOOT_HEAP_SIZE, 1, 0
++boot_stack:
++ .fill BOOT_STACK_SIZE, 1, 0
++boot_stack_end:
+diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
+index 8182e32..90456ce 100644
+--- a/arch/x86/boot/compressed/misc.c
++++ b/arch/x86/boot/compressed/misc.c
+@@ -15,6 +15,10 @@
+ * we just keep it from happening
+ */
+ #undef CONFIG_PARAVIRT
++#ifdef CONFIG_X86_32
++#define _ASM_DESC_H_ 1
++#endif
++
+ #ifdef CONFIG_X86_64
+ #define _LINUX_STRING_H_ 1
+ #define __LINUX_BITMAP_H 1
+@@ -22,6 +26,7 @@
+
+ #include <linux/linkage.h>
+ #include <linux/screen_info.h>
++#include <linux/elf.h>
+ #include <asm/io.h>
+ #include <asm/page.h>
+ #include <asm/boot.h>
+@@ -53,8 +58,8 @@
+ * 1 bit (last block flag)
+ * 2 bits (block type)
+ *
+- * 1 block occurs every 32K -1 bytes or when there 50% compression has been achieved.
+- * The smallest block type encoding is always used.
++ * 1 block occurs every 32K -1 bytes or when there 50% compression
++ * has been achieved. The smallest block type encoding is always used.
+ *
+ * stored:
+ * 32 bits length in bytes.
+@@ -90,9 +95,9 @@
+ *
+ * All of which is enough to compute an amount of extra data that is required
+ * to be safe. To avoid problems at the block level allocating 5 extra bytes
+- * per 32767 bytes of data is sufficient. To avoind problems internal to a block
+- * adding an extra 32767 bytes (the worst case uncompressed block size) is
+- * sufficient, to ensure that in the worst case the decompressed data for
++ * per 32767 bytes of data is sufficient. To avoind problems internal to a
++ * block adding an extra 32767 bytes (the worst case uncompressed block size)
++ * is sufficient, to ensure that in the worst case the decompressed data for
+ * block will stop the byte before the compressed data for a block begins.
+ * To avoid problems with the compressed data's meta information an extra 18
+ * bytes are needed. Leading to the formula:
+@@ -111,58 +116,66 @@
+ * gzip declarations
+ */
+
+-#define OF(args) args
+-#define STATIC static
++#define OF(args) args
++#define STATIC static
+
+ #undef memset
+ #undef memcpy
+-#define memzero(s, n) memset ((s), 0, (n))
++#define memzero(s, n) memset((s), 0, (n))
+
+-typedef unsigned char uch;
+-typedef unsigned short ush;
+-typedef unsigned long ulg;
++typedef unsigned char uch;
++typedef unsigned short ush;
++typedef unsigned long ulg;
+
+-#define WSIZE 0x80000000 /* Window size must be at least 32k,
+- * and a power of two
+- * We don't actually have a window just
+- * a huge output buffer so I report
+- * a 2G windows size, as that should
+- * always be larger than our output buffer.
+- */
++/*
++ * Window size must be at least 32k, and a power of two.
++ * We don't actually have a window just a huge output buffer,
++ * so we report a 2G window size, as that should always be
++ * larger than our output buffer:
++ */
++#define WSIZE 0x80000000
+
+-static uch *inbuf; /* input buffer */
+-static uch *window; /* Sliding window buffer, (and final output buffer) */
++/* Input buffer: */
++static unsigned char *inbuf;
+
+-static unsigned insize; /* valid bytes in inbuf */
+-static unsigned inptr; /* index of next byte to be processed in inbuf */
+-static unsigned outcnt; /* bytes in output buffer */
++/* Sliding window buffer (and final output buffer): */
++static unsigned char *window;
++
++/* Valid bytes in inbuf: */
++static unsigned insize;
++
++/* Index of next byte to be processed in inbuf: */
++static unsigned inptr;
++
++/* Bytes in output buffer: */
++static unsigned outcnt;
+
+ /* gzip flag byte */
+-#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
+-#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
+-#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
+-#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
+-#define COMMENT 0x10 /* bit 4 set: file comment present */
+-#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
+-#define RESERVED 0xC0 /* bit 6,7: reserved */
+-
+-#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
+-
++#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
++#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gz file */
++#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
++#define ORIG_NAM 0x08 /* bit 3 set: original file name present */
++#define COMMENT 0x10 /* bit 4 set: file comment present */
++#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
++#define RESERVED 0xC0 /* bit 6, 7: reserved */
++
++#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
++
+ /* Diagnostic functions */
+ #ifdef DEBUG
+-# define Assert(cond,msg) {if(!(cond)) error(msg);}
+-# define Trace(x) fprintf x
+-# define Tracev(x) {if (verbose) fprintf x ;}
+-# define Tracevv(x) {if (verbose>1) fprintf x ;}
+-# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+-# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
++# define Assert(cond, msg) do { if (!(cond)) error(msg); } while (0)
++# define Trace(x) do { fprintf x; } while (0)
++# define Tracev(x) do { if (verbose) fprintf x ; } while (0)
++# define Tracevv(x) do { if (verbose > 1) fprintf x ; } while (0)
++# define Tracec(c, x) do { if (verbose && (c)) fprintf x ; } while (0)
++# define Tracecv(c, x) do { if (verbose > 1 && (c)) fprintf x ; } while (0)
+ #else
+-# define Assert(cond,msg)
++# define Assert(cond, msg)
+ # define Trace(x)
+ # define Tracev(x)
+ # define Tracevv(x)
+-# define Tracec(c,x)
+-# define Tracecv(c,x)
++# define Tracec(c, x)
++# define Tracecv(c, x)
+ #endif
+
+ static int fill_inbuf(void);
+@@ -170,7 +183,7 @@ static void flush_window(void);
+ static void error(char *m);
+ static void gzip_mark(void **);
+ static void gzip_release(void **);
+-
++
+ /*
+ * This is set up by the setup-routine at boot-time
+ */
+@@ -185,7 +198,7 @@ static unsigned char *real_mode; /* Pointer to real-mode data */
+ extern unsigned char input_data[];
+ extern int input_len;
+
+-static long bytes_out = 0;
++static long bytes_out;
+
+ static void *malloc(int size);
+ static void free(void *where);
+@@ -204,13 +217,7 @@ static void putstr(const char *);
+ static memptr free_mem_ptr;
+ static memptr free_mem_end_ptr;
+
+-#ifdef CONFIG_X86_64
+-#define HEAP_SIZE 0x7000
+-#else
+-#define HEAP_SIZE 0x4000
+-#endif
+-
+-static char *vidmem = (char *)0xb8000;
++static char *vidmem;
+ static int vidport;
+ static int lines, cols;
+
+@@ -224,8 +231,10 @@ static void *malloc(int size)
+ {
+ void *p;
+
+- if (size <0) error("Malloc error");
+- if (free_mem_ptr <= 0) error("Memory error");
++ if (size < 0)
++ error("Malloc error");
++ if (free_mem_ptr <= 0)
++ error("Memory error");
+
+ free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
+
+@@ -251,19 +260,19 @@ static void gzip_release(void **ptr)
+ {
+ free_mem_ptr = (memptr) *ptr;
+ }
+-
++
+ static void scroll(void)
+ {
+ int i;
+
+- memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
+- for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
++ memcpy(vidmem, vidmem + cols * 2, (lines - 1) * cols * 2);
++ for (i = (lines - 1) * cols * 2; i < lines * cols * 2; i += 2)
+ vidmem[i] = ' ';
+ }
+
+ static void putstr(const char *s)
+ {
+- int x,y,pos;
++ int x, y, pos;
+ char c;
+
+ #ifdef CONFIG_X86_32
+@@ -274,18 +283,18 @@ static void putstr(const char *s)
+ x = RM_SCREEN_INFO.orig_x;
+ y = RM_SCREEN_INFO.orig_y;
+
+- while ( ( c = *s++ ) != '\0' ) {
+- if ( c == '\n' ) {
++ while ((c = *s++) != '\0') {
++ if (c == '\n') {
+ x = 0;
+- if ( ++y >= lines ) {
++ if (++y >= lines) {
+ scroll();
+ y--;
+ }
+ } else {
+ vidmem [(x + cols * y) * 2] = c;
+- if ( ++x >= cols ) {
++ if (++x >= cols) {
+ x = 0;
+- if ( ++y >= lines ) {
++ if (++y >= lines) {
+ scroll();
+ y--;
+ }
+@@ -303,22 +312,22 @@ static void putstr(const char *s)
+ outb(0xff & (pos >> 1), vidport+1);
+ }
+
+-static void* memset(void* s, int c, unsigned n)
++static void *memset(void *s, int c, unsigned n)
+ {
+ int i;
+ char *ss = s;
+
+- for (i=0;i<n;i++) ss[i] = c;
++ for (i = 0; i < n; i++) ss[i] = c;
+ return s;
+ }
+
+-static void* memcpy(void* dest, const void* src, unsigned n)
++static void *memcpy(void *dest, const void *src, unsigned n)
+ {
+ int i;
+ const char *s = src;
+ char *d = dest;
+
+- for (i=0;i<n;i++) d[i] = s[i];
++ for (i = 0; i < n; i++) d[i] = s[i];
+ return dest;
+ }
+
+@@ -341,9 +350,9 @@ static void flush_window(void)
+ /* With my window equal to my output buffer
+ * I only need to compute the crc here.
+ */
+- ulg c = crc; /* temporary variable */
++ unsigned long c = crc; /* temporary variable */
+ unsigned n;
+- uch *in, ch;
++ unsigned char *in, ch;
+
+ in = window;
+ for (n = 0; n < outcnt; n++) {
+@@ -351,7 +360,7 @@ static void flush_window(void)
+ c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+ }
+ crc = c;
+- bytes_out += (ulg)outcnt;
++ bytes_out += (unsigned long)outcnt;
+ outcnt = 0;
+ }
+
+@@ -365,9 +374,59 @@ static void error(char *x)
+ asm("hlt");
+ }
+
++static void parse_elf(void *output)
++{
++#ifdef CONFIG_X86_64
++ Elf64_Ehdr ehdr;
++ Elf64_Phdr *phdrs, *phdr;
++#else
++ Elf32_Ehdr ehdr;
++ Elf32_Phdr *phdrs, *phdr;
++#endif
++ void *dest;
++ int i;
++
++ memcpy(&ehdr, output, sizeof(ehdr));
++ if (ehdr.e_ident[EI_MAG0] != ELFMAG0 ||
++ ehdr.e_ident[EI_MAG1] != ELFMAG1 ||
++ ehdr.e_ident[EI_MAG2] != ELFMAG2 ||
++ ehdr.e_ident[EI_MAG3] != ELFMAG3) {
++ error("Kernel is not a valid ELF file");
++ return;
++ }
++
++ putstr("Parsing ELF... ");
++
++ phdrs = malloc(sizeof(*phdrs) * ehdr.e_phnum);
++ if (!phdrs)
++ error("Failed to allocate space for phdrs");
++
++ memcpy(phdrs, output + ehdr.e_phoff, sizeof(*phdrs) * ehdr.e_phnum);
++
++ for (i = 0; i < ehdr.e_phnum; i++) {
++ phdr = &phdrs[i];
++
++ switch (phdr->p_type) {
++ case PT_LOAD:
++#ifdef CONFIG_RELOCATABLE
++ dest = output;
++ dest += (phdr->p_paddr - LOAD_PHYSICAL_ADDR);
++#else
++ dest = (void *)(phdr->p_paddr);
++#endif
++ memcpy(dest,
++ output + phdr->p_offset,
++ phdr->p_filesz);
++ break;
++ default: /* Ignore other PT_* */ break;
++ }
++ }
++}
++
+ asmlinkage void decompress_kernel(void *rmode, memptr heap,
+- uch *input_data, unsigned long input_len,
+- uch *output)
++ unsigned char *input_data,
++ unsigned long input_len,
++ unsigned char *output)
+ {
+ real_mode = rmode;
+
+@@ -384,18 +443,18 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
+
+ window = output; /* Output buffer (Normally at 1M) */
+ free_mem_ptr = heap; /* Heap */
+- free_mem_end_ptr = heap + HEAP_SIZE;
++ free_mem_end_ptr = heap + BOOT_HEAP_SIZE;
+ inbuf = input_data; /* Input buffer */
+ insize = input_len;
+ inptr = 0;
+
+ #ifdef CONFIG_X86_64
+- if ((ulg)output & (__KERNEL_ALIGN - 1))
++ if ((unsigned long)output & (__KERNEL_ALIGN - 1))
+ error("Destination address not 2M aligned");
+- if ((ulg)output >= 0xffffffffffUL)
++ if ((unsigned long)output >= 0xffffffffffUL)
+ error("Destination address too large");
+ #else
+- if ((u32)output & (CONFIG_PHYSICAL_ALIGN -1))
++ if ((u32)output & (CONFIG_PHYSICAL_ALIGN - 1))
+ error("Destination address not CONFIG_PHYSICAL_ALIGN aligned");
+ if (heap > ((-__PAGE_OFFSET-(512<<20)-1) & 0x7fffffff))
+ error("Destination address too large");
+@@ -408,6 +467,7 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
+ makecrc();
+ putstr("\nDecompressing Linux... ");
+ gunzip();
++ parse_elf(output);
+ putstr("done.\nBooting the kernel.\n");
+ return;
+ }
+diff --git a/arch/x86/boot/compressed/vmlinux_64.lds b/arch/x86/boot/compressed/vmlinux_64.lds
+index 7e5c720..bef1ac8 100644
+--- a/arch/x86/boot/compressed/vmlinux_64.lds
++++ b/arch/x86/boot/compressed/vmlinux_64.lds
+@@ -39,10 +39,10 @@ SECTIONS
+ *(.bss.*)
+ *(COMMON)
+ . = ALIGN(8);
+- _end = . ;
++ _end_before_pgt = . ;
+ . = ALIGN(4096);
+ pgtable = . ;
+ . = . + 4096 * 6;
+- _heap = .;
++ _ebss = .;
+ }
+ }
+diff --git a/arch/x86/boot/copy.S b/arch/x86/boot/copy.S
+index ef127e5..ef50c84 100644
+--- a/arch/x86/boot/copy.S
++++ b/arch/x86/boot/copy.S
+@@ -9,8 +9,6 @@
+ * ----------------------------------------------------------------------- */
+
+ /*
+- * arch/i386/boot/copy.S
+- *
+ * Memory copy routines
+ */
+
+diff --git a/arch/x86/boot/cpucheck.c b/arch/x86/boot/cpucheck.c
+index 769065b..7804389 100644
+--- a/arch/x86/boot/cpucheck.c
++++ b/arch/x86/boot/cpucheck.c
+@@ -9,8 +9,6 @@
+ * ----------------------------------------------------------------------- */
+
+ /*
+- * arch/i386/boot/cpucheck.c
+- *
+ * Check for obligatory CPU features and abort if the features are not
+ * present. This code should be compilable as 16-, 32- or 64-bit
+ * code, so be very careful with types and inline assembly.
+@@ -56,27 +54,27 @@ static const u32 req_flags[NCAPINTS] =
+ REQUIRED_MASK7,
+ };
+
+-#define A32(a,b,c,d) (((d) << 24)+((c) << 16)+((b) << 8)+(a))
++#define A32(a, b, c, d) (((d) << 24)+((c) << 16)+((b) << 8)+(a))
+
+ static int is_amd(void)
+ {
+- return cpu_vendor[0] == A32('A','u','t','h') &&
+- cpu_vendor[1] == A32('e','n','t','i') &&
+- cpu_vendor[2] == A32('c','A','M','D');
++ return cpu_vendor[0] == A32('A', 'u', 't', 'h') &&
++ cpu_vendor[1] == A32('e', 'n', 't', 'i') &&
++ cpu_vendor[2] == A32('c', 'A', 'M', 'D');
+ }
+
+ static int is_centaur(void)
+ {
+- return cpu_vendor[0] == A32('C','e','n','t') &&
+- cpu_vendor[1] == A32('a','u','r','H') &&
+- cpu_vendor[2] == A32('a','u','l','s');
++ return cpu_vendor[0] == A32('C', 'e', 'n', 't') &&
++ cpu_vendor[1] == A32('a', 'u', 'r', 'H') &&
++ cpu_vendor[2] == A32('a', 'u', 'l', 's');
+ }
+
+ static int is_transmeta(void)
+ {
+- return cpu_vendor[0] == A32('G','e','n','u') &&
+- cpu_vendor[1] == A32('i','n','e','T') &&
+- cpu_vendor[2] == A32('M','x','8','6');
++ return cpu_vendor[0] == A32('G', 'e', 'n', 'u') &&
++ cpu_vendor[1] == A32('i', 'n', 'e', 'T') &&
++ cpu_vendor[2] == A32('M', 'x', '8', '6');
+ }
+
+ static int has_fpu(void)
+diff --git a/arch/x86/boot/edd.c b/arch/x86/boot/edd.c
+index 8721dc4..d84a48e 100644
+--- a/arch/x86/boot/edd.c
++++ b/arch/x86/boot/edd.c
+@@ -9,8 +9,6 @@
+ * ----------------------------------------------------------------------- */
+
+ /*
+- * arch/i386/boot/edd.c
+- *
+ * Get EDD BIOS disk information
+ */
+
+diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
+index 64ad901..6d2df8d 100644
+--- a/arch/x86/boot/header.S
++++ b/arch/x86/boot/header.S
+@@ -22,6 +22,7 @@
+ #include <asm/page.h>
+ #include <asm/setup.h>
+ #include "boot.h"
++#include "offsets.h"
+
+ SETUPSECTS = 4 /* default nr of setup-sectors */
+ BOOTSEG = 0x07C0 /* original address of boot-sector */
+@@ -119,7 +120,7 @@ _start:
+ # Part 2 of the header, from the old setup.S
+
+ .ascii "HdrS" # header signature
+- .word 0x0207 # header version number (>= 0x0105)
++ .word 0x0208 # header version number (>= 0x0105)
+ # or else old loadlin-1.5 will fail)
+ .globl realmode_swtch
+ realmode_swtch: .word 0, 0 # default_switch, SETUPSEG
+@@ -223,6 +224,9 @@ hardware_subarch: .long 0 # subarchitecture, added with 2.07
+
+ hardware_subarch_data: .quad 0
+
++payload_offset: .long input_data
++payload_length: .long input_data_end-input_data
++
+ # End of setup header #####################################################
+
+ .section ".inittext", "ax"
+diff --git a/arch/x86/boot/install.sh b/arch/x86/boot/install.sh
+index 88d7776..8d60ee1 100644
+--- a/arch/x86/boot/install.sh
++++ b/arch/x86/boot/install.sh
+@@ -1,7 +1,5 @@
+ #!/bin/sh
+ #
+-# arch/i386/boot/install.sh
+-#
+ # This file is subject to the terms and conditions of the GNU General Public
+ # License. See the file "COPYING" in the main directory of this archive
+ # for more details.
+diff --git a/arch/x86/boot/main.c b/arch/x86/boot/main.c
+index 7828da5..77569a4 100644
+--- a/arch/x86/boot/main.c
++++ b/arch/x86/boot/main.c
+@@ -9,8 +9,6 @@
+ * ----------------------------------------------------------------------- */
+
+ /*
+- * arch/i386/boot/main.c
+- *
+ * Main module for the real-mode kernel code
+ */
+
+diff --git a/arch/x86/boot/mca.c b/arch/x86/boot/mca.c
+index 68222f2..911eaae 100644
+--- a/arch/x86/boot/mca.c
++++ b/arch/x86/boot/mca.c
+@@ -9,8 +9,6 @@
+ * ----------------------------------------------------------------------- */
+
+ /*
+- * arch/i386/boot/mca.c
+- *
+ * Get the MCA system description table
+ */
+
+diff --git a/arch/x86/boot/memory.c b/arch/x86/boot/memory.c
+index e77d89f..acad32e 100644
+--- a/arch/x86/boot/memory.c
++++ b/arch/x86/boot/memory.c
+@@ -9,8 +9,6 @@
+ * ----------------------------------------------------------------------- */
+
+ /*
+- * arch/i386/boot/memory.c
+- *
+ * Memory detection code
+ */
+
+diff --git a/arch/x86/boot/pm.c b/arch/x86/boot/pm.c
+index 1a0f936..328956f 100644
+--- a/arch/x86/boot/pm.c
++++ b/arch/x86/boot/pm.c
+@@ -9,8 +9,6 @@
+ * ----------------------------------------------------------------------- */
+
+ /*
+- * arch/i386/boot/pm.c
+- *
+ * Prepare the machine for transition to protected mode.
+ */
+
+@@ -100,7 +98,7 @@ static void reset_coprocessor(void)
+ /*
+ * Set up the GDT
+ */
+-#define GDT_ENTRY(flags,base,limit) \
++#define GDT_ENTRY(flags, base, limit) \
+ (((u64)(base & 0xff000000) << 32) | \
+ ((u64)flags << 40) | \
+ ((u64)(limit & 0x00ff0000) << 32) | \
+diff --git a/arch/x86/boot/pmjump.S b/arch/x86/boot/pmjump.S
+index f5402d5..ab049d4 100644
+--- a/arch/x86/boot/pmjump.S
++++ b/arch/x86/boot/pmjump.S
+@@ -9,8 +9,6 @@
+ * ----------------------------------------------------------------------- */
+
+ /*
+- * arch/i386/boot/pmjump.S
+- *
+ * The actual transition into protected mode
+ */
+
+diff --git a/arch/x86/boot/printf.c b/arch/x86/boot/printf.c
+index 7e7e890..c1d00c0 100644
+--- a/arch/x86/boot/printf.c
++++ b/arch/x86/boot/printf.c
+@@ -9,8 +9,6 @@
+ * ----------------------------------------------------------------------- */
+
+ /*
+- * arch/i386/boot/printf.c
+- *
+ * Oh, it's a waste of space, but oh-so-yummy for debugging. This
+ * version of printf() does not include 64-bit support. "Live with
+ * it."
+diff --git a/arch/x86/boot/string.c b/arch/x86/boot/string.c
+index 481a220..f94b7a0 100644
+--- a/arch/x86/boot/string.c
++++ b/arch/x86/boot/string.c
+@@ -9,8 +9,6 @@
+ * ----------------------------------------------------------------------- */
+
+ /*
+- * arch/i386/boot/string.c
+- *
+ * Very basic string functions
+ */
+
+diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c
+index b424874..44dc192 100644
+--- a/arch/x86/boot/tools/build.c
++++ b/arch/x86/boot/tools/build.c
+@@ -50,6 +50,75 @@ typedef unsigned long u32;
+ u8 buf[SETUP_SECT_MAX*512];
+ int is_big_kernel;
+
++/*----------------------------------------------------------------------*/
++
++static const u32 crctab32[] = {
++ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
++ 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
++ 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
++ 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
++ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
++ 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
++ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
++ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
++ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
++ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
++ 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
++ 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
++ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
++ 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
++ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
++ 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
++ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
++ 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
++ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
++ 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
++ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
++ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
++ 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
++ 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
++ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
++ 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
++ 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
++ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
++ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
++ 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
++ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
++ 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
++ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
++ 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
++ 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
++ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
++ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
++ 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
++ 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
++ 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
++ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
++ 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
++ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
++ 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
++ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
++ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
++ 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
++ 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
++ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
++ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
++ 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
++ 0x2d02ef8d
++};
++
++static u32 partial_crc32_one(u8 c, u32 crc)
++{
++ return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
++}
++
++static u32 partial_crc32(const u8 *s, int len, u32 crc)
++{
++ while (len--)
++ crc = partial_crc32_one(*s++, crc);
++ return crc;
++}
++
+ static void die(const char * str, ...)
+ {
+ va_list args;
+@@ -74,6 +143,7 @@ int main(int argc, char ** argv)
+ FILE *file;
+ int fd;
+ void *kernel;
++ u32 crc = 0xffffffffUL;
+
+ if (argc > 2 && !strcmp(argv[1], "-b"))
+ {
+@@ -144,7 +214,8 @@ int main(int argc, char ** argv)
+ kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
+ if (kernel == MAP_FAILED)
+ die("Unable to mmap '%s': %m", argv[2]);
+- sys_size = (sz + 15) / 16;
++ /* Number of 16-byte paragraphs, including space for a 4-byte CRC */
++ sys_size = (sz + 15 + 4) / 16;
+ if (!is_big_kernel && sys_size > DEF_SYSSIZE)
+ die("System is too big. Try using bzImage or modules.");
+
+@@ -155,12 +226,27 @@ int main(int argc, char ** argv)
+ buf[0x1f6] = sys_size >> 16;
+ buf[0x1f7] = sys_size >> 24;
+
++ crc = partial_crc32(buf, i, crc);
+ if (fwrite(buf, 1, i, stdout) != i)
+ die("Writing setup failed");
+
+ /* Copy the kernel code */
++ crc = partial_crc32(kernel, sz, crc);
+ if (fwrite(kernel, 1, sz, stdout) != sz)
+ die("Writing kernel failed");
++
++ /* Add padding leaving 4 bytes for the checksum */
++ while (sz++ < (sys_size*16) - 4) {
++ crc = partial_crc32_one('\0', crc);
++ if (fwrite("\0", 1, 1, stdout) != 1)
++ die("Writing padding failed");
++ }
++
++ /* Write the CRC */
++ fprintf(stderr, "CRC %lx\n", crc);
++ if (fwrite(&crc, 1, 4, stdout) != 4)
++ die("Writing CRC failed");
++
+ close(fd);
+
+ /* Everything is OK */
+diff --git a/arch/x86/boot/tty.c b/arch/x86/boot/tty.c
+index f3f14bd..0be77b3 100644
+--- a/arch/x86/boot/tty.c
++++ b/arch/x86/boot/tty.c
+@@ -9,8 +9,6 @@
+ * ----------------------------------------------------------------------- */
+
+ /*
+- * arch/i386/boot/tty.c
+- *
+ * Very simple screen I/O
+ * XXX: Probably should add very simple serial I/O?
+ */
+diff --git a/arch/x86/boot/version.c b/arch/x86/boot/version.c
+index c61462f..2723d9b 100644
+--- a/arch/x86/boot/version.c
++++ b/arch/x86/boot/version.c
+@@ -9,8 +9,6 @@
+ * ----------------------------------------------------------------------- */
+
+ /*
+- * arch/i386/boot/version.c
+- *
+ * Kernel version string
+ */
+
+diff --git a/arch/x86/boot/video-bios.c b/arch/x86/boot/video-bios.c
+index ff664a1..49f26aa 100644
+--- a/arch/x86/boot/video-bios.c
++++ b/arch/x86/boot/video-bios.c
+@@ -9,8 +9,6 @@
+ * ----------------------------------------------------------------------- */
+
+ /*
+- * arch/i386/boot/video-bios.c
+- *
+ * Standard video BIOS modes
+ *
+ * We have two options for this; silent and scanned.
+@@ -50,6 +48,7 @@ static int set_bios_mode(u8 mode)
+ if (new_mode == mode)
+ return 0; /* Mode change OK */
+
++#ifndef _WAKEUP
+ if (new_mode != boot_params.screen_info.orig_video_mode) {
+ /* Mode setting failed, but we didn't end up where we
+ started. That's bad. Try to revert to the original
+@@ -59,13 +58,18 @@ static int set_bios_mode(u8 mode)
+ : "+a" (ax)
+ : : "ebx", "ecx", "edx", "esi", "edi");
+ }
++#endif
+ return -1;
+ }
+
+ static int bios_probe(void)
+ {
+ u8 mode;
++#ifdef _WAKEUP
++ u8 saved_mode = 0x03;
++#else
+ u8 saved_mode = boot_params.screen_info.orig_video_mode;
++#endif
+ u16 crtc;
+ struct mode_info *mi;
+ int nmodes = 0;
+diff --git a/arch/x86/boot/video-mode.c b/arch/x86/boot/video-mode.c
+new file mode 100644
+index 0000000..748e8d0
+--- /dev/null
++++ b/arch/x86/boot/video-mode.c
+@@ -0,0 +1,173 @@
++/* -*- linux-c -*- ------------------------------------------------------- *
++ *
++ * Copyright (C) 1991, 1992 Linus Torvalds
++ * Copyright 2007-2008 rPath, Inc. - All Rights Reserved
++ *
++ * This file is part of the Linux kernel, and is made available under
++ * the terms of the GNU General Public License version 2.
++ *
++ * ----------------------------------------------------------------------- */
++
++/*
++ * arch/i386/boot/video-mode.c
++ *
++ * Set the video mode. This is separated out into a different
++ * file in order to be shared with the ACPI wakeup code.
++ */
++
++#include "boot.h"
++#include "video.h"
++#include "vesa.h"
++
++/*
++ * Common variables
++ */
++int adapter; /* 0=CGA/MDA/HGC, 1=EGA, 2=VGA+ */
++u16 video_segment;
++int force_x, force_y; /* Don't query the BIOS for cols/rows */
++
++int do_restore; /* Screen contents changed during mode flip */
++int graphic_mode; /* Graphic mode with linear frame buffer */
++
++/* Probe the video drivers and have them generate their mode lists. */
++void probe_cards(int unsafe)
++{
++ struct card_info *card;
++ static u8 probed[2];
++
++ if (probed[unsafe])
++ return;
++
++ probed[unsafe] = 1;
++
++ for (card = video_cards; card < video_cards_end; card++) {
++ if (card->unsafe == unsafe) {
++ if (card->probe)
++ card->nmodes = card->probe();
++ else
++ card->nmodes = 0;
++ }
++ }
++}
++
++/* Test if a mode is defined */
++int mode_defined(u16 mode)
++{
++ struct card_info *card;
++ struct mode_info *mi;
++ int i;
++
++ for (card = video_cards; card < video_cards_end; card++) {
++ mi = card->modes;
++ for (i = 0; i < card->nmodes; i++, mi++) {
++ if (mi->mode == mode)
++ return 1;
++ }
++ }
++
++ return 0;
++}
++
++/* Set mode (without recalc) */
++static int raw_set_mode(u16 mode, u16 *real_mode)
++{
++ int nmode, i;
++ struct card_info *card;
++ struct mode_info *mi;
++
++ /* Drop the recalc bit if set */
++ mode &= ~VIDEO_RECALC;
++
++ /* Scan for mode based on fixed ID, position, or resolution */
++ nmode = 0;
++ for (card = video_cards; card < video_cards_end; card++) {
++ mi = card->modes;
++ for (i = 0; i < card->nmodes; i++, mi++) {
++ int visible = mi->x || mi->y;
++
++ if ((mode == nmode && visible) ||
++ mode == mi->mode ||
++ mode == (mi->y << 8)+mi->x) {
++ *real_mode = mi->mode;
++ return card->set_mode(mi);
++ }
++
++ if (visible)
++ nmode++;
++ }
++ }
++
++ /* Nothing found? Is it an "exceptional" (unprobed) mode? */
++ for (card = video_cards; card < video_cards_end; card++) {
++ if (mode >= card->xmode_first &&
++ mode < card->xmode_first+card->xmode_n) {
++ struct mode_info mix;
++ *real_mode = mix.mode = mode;
++ mix.x = mix.y = 0;
++ return card->set_mode(&mix);
++ }
++ }
++
++ /* Otherwise, failure... */
++ return -1;
++}
++
++/*
++ * Recalculate the vertical video cutoff (hack!)
++ */
++static void vga_recalc_vertical(void)
++{
++ unsigned int font_size, rows;
++ u16 crtc;
++ u8 pt, ov;
++
++ set_fs(0);
++ font_size = rdfs8(0x485); /* BIOS: font size (pixels) */
++ rows = force_y ? force_y : rdfs8(0x484)+1; /* Text rows */
++
++ rows *= font_size; /* Visible scan lines */
++ rows--; /* ... minus one */
++
++ crtc = vga_crtc();
++
++ pt = in_idx(crtc, 0x11);
++ pt &= ~0x80; /* Unlock CR0-7 */
++ out_idx(pt, crtc, 0x11);
++
++ out_idx((u8)rows, crtc, 0x12); /* Lower height register */
++
++ ov = in_idx(crtc, 0x07); /* Overflow register */
++ ov &= 0xbd;
++ ov |= (rows >> (8-1)) & 0x02;
++ ov |= (rows >> (9-6)) & 0x40;
++ out_idx(ov, crtc, 0x07);
++}
++
++/* Set mode (with recalc if specified) */
++int set_mode(u16 mode)
++{
++ int rv;
++ u16 real_mode;
++
++ /* Very special mode numbers... */
++ if (mode == VIDEO_CURRENT_MODE)
++ return 0; /* Nothing to do... */
++ else if (mode == NORMAL_VGA)
++ mode = VIDEO_80x25;
++ else if (mode == EXTENDED_VGA)
++ mode = VIDEO_8POINT;
++
++ rv = raw_set_mode(mode, &real_mode);
++ if (rv)
++ return rv;
++
++ if (mode & VIDEO_RECALC)
++ vga_recalc_vertical();
++
++ /* Save the canonical mode number for the kernel, not
++ an alias, size specification or menu position */
++#ifndef _WAKEUP
++ boot_params.hdr.vid_mode = real_mode;
++#endif
++ return 0;
++}
+diff --git a/arch/x86/boot/video-vesa.c b/arch/x86/boot/video-vesa.c
+index 419b5c2..401ad99 100644
+--- a/arch/x86/boot/video-vesa.c
++++ b/arch/x86/boot/video-vesa.c
+@@ -9,8 +9,6 @@
+ * ----------------------------------------------------------------------- */
+
+ /*
+- * arch/i386/boot/video-vesa.c
+- *
+ * VESA text modes
+ */
+
+@@ -24,7 +22,11 @@ static struct vesa_mode_info vminfo;
+
+ __videocard video_vesa;
+
++#ifndef _WAKEUP
+ static void vesa_store_mode_params_graphics(void);
++#else /* _WAKEUP */
++static inline void vesa_store_mode_params_graphics(void) {}
++#endif /* _WAKEUP */
+
+ static int vesa_probe(void)
+ {
+@@ -165,6 +167,8 @@ static int vesa_set_mode(struct mode_info *mode)
+ }
+
+
++#ifndef _WAKEUP
++
+ /* Switch DAC to 8-bit mode */
+ static void vesa_dac_set_8bits(void)
+ {
+@@ -288,6 +292,8 @@ void vesa_store_edid(void)
+ #endif /* CONFIG_FIRMWARE_EDID */
+ }
+
++#endif /* not _WAKEUP */
++
+ __videocard video_vesa =
+ {
+ .card_name = "VESA",
+diff --git a/arch/x86/boot/video-vga.c b/arch/x86/boot/video-vga.c
+index 7259387..40ecb8d 100644
+--- a/arch/x86/boot/video-vga.c
++++ b/arch/x86/boot/video-vga.c
+@@ -9,8 +9,6 @@
+ * ----------------------------------------------------------------------- */
+
+ /*
+- * arch/i386/boot/video-vga.c
+- *
+ * Common all-VGA modes
+ */
+
+@@ -210,6 +208,8 @@ static int vga_set_mode(struct mode_info *mode)
+ */
+ static int vga_probe(void)
+ {
++ u16 ega_bx;
++
+ static const char *card_name[] = {
+ "CGA/MDA/HGC", "EGA", "VGA"
+ };
+@@ -226,12 +226,16 @@ static int vga_probe(void)
+ u8 vga_flag;
+
+ asm(INT10
+- : "=b" (boot_params.screen_info.orig_video_ega_bx)
++ : "=b" (ega_bx)
+ : "a" (0x1200), "b" (0x10) /* Check EGA/VGA */
+ : "ecx", "edx", "esi", "edi");
+
++#ifndef _WAKEUP
++ boot_params.screen_info.orig_video_ega_bx = ega_bx;
++#endif
++
+ /* If we have MDA/CGA/HGC then BL will be unchanged at 0x10 */
+- if ((u8)boot_params.screen_info.orig_video_ega_bx != 0x10) {
++ if ((u8)ega_bx != 0x10) {
+ /* EGA/VGA */
+ asm(INT10
+ : "=a" (vga_flag)
+@@ -240,7 +244,9 @@ static int vga_probe(void)
+
+ if (vga_flag == 0x1a) {
+ adapter = ADAPTER_VGA;
++#ifndef _WAKEUP
+ boot_params.screen_info.orig_video_isVGA = 1;
++#endif
+ } else {
+ adapter = ADAPTER_EGA;
+ }
+diff --git a/arch/x86/boot/video.c b/arch/x86/boot/video.c
+index 696d08f..83598b2 100644
+--- a/arch/x86/boot/video.c
++++ b/arch/x86/boot/video.c
+@@ -9,8 +9,6 @@
+ * ----------------------------------------------------------------------- */
+
+ /*
+- * arch/i386/boot/video.c
+- *
+ * Select video mode
+ */
+
+@@ -18,21 +16,6 @@
+ #include "video.h"
+ #include "vesa.h"
+
+-/*
+- * Mode list variables
+- */
+-static struct card_info cards[]; /* List of cards to probe for */
+-
+-/*
+- * Common variables
+- */
+-int adapter; /* 0=CGA/MDA/HGC, 1=EGA, 2=VGA+ */
+-u16 video_segment;
+-int force_x, force_y; /* Don't query the BIOS for cols/rows */
+-
+-int do_restore = 0; /* Screen contents changed during mode flip */
+-int graphic_mode; /* Graphic mode with linear frame buffer */
+-
+ static void store_cursor_position(void)
+ {
+ u16 curpos;
+@@ -107,147 +90,6 @@ static void store_mode_params(void)
+ boot_params.screen_info.orig_video_lines = y;
+ }
+
+-/* Probe the video drivers and have them generate their mode lists. */
+-static void probe_cards(int unsafe)
+-{
+- struct card_info *card;
+- static u8 probed[2];
+-
+- if (probed[unsafe])
+- return;
+-
+- probed[unsafe] = 1;
+-
+- for (card = video_cards; card < video_cards_end; card++) {
+- if (card->unsafe == unsafe) {
+- if (card->probe)
+- card->nmodes = card->probe();
+- else
+- card->nmodes = 0;
+- }
+- }
+-}
+-
+-/* Test if a mode is defined */
+-int mode_defined(u16 mode)
+-{
+- struct card_info *card;
+- struct mode_info *mi;
+- int i;
+-
+- for (card = video_cards; card < video_cards_end; card++) {
+- mi = card->modes;
+- for (i = 0; i < card->nmodes; i++, mi++) {
+- if (mi->mode == mode)
+- return 1;
+- }
+- }
+-
+- return 0;
+-}
+-
+-/* Set mode (without recalc) */
+-static int raw_set_mode(u16 mode, u16 *real_mode)
+-{
+- int nmode, i;
+- struct card_info *card;
+- struct mode_info *mi;
+-
+- /* Drop the recalc bit if set */
+- mode &= ~VIDEO_RECALC;
+-
+- /* Scan for mode based on fixed ID, position, or resolution */
+- nmode = 0;
+- for (card = video_cards; card < video_cards_end; card++) {
+- mi = card->modes;
+- for (i = 0; i < card->nmodes; i++, mi++) {
+- int visible = mi->x || mi->y;
+-
+- if ((mode == nmode && visible) ||
+- mode == mi->mode ||
+- mode == (mi->y << 8)+mi->x) {
+- *real_mode = mi->mode;
+- return card->set_mode(mi);
+- }
+-
+- if (visible)
+- nmode++;
+- }
+- }
+-
+- /* Nothing found? Is it an "exceptional" (unprobed) mode? */
+- for (card = video_cards; card < video_cards_end; card++) {
+- if (mode >= card->xmode_first &&
+- mode < card->xmode_first+card->xmode_n) {
+- struct mode_info mix;
+- *real_mode = mix.mode = mode;
+- mix.x = mix.y = 0;
+- return card->set_mode(&mix);
+- }
+- }
+-
+- /* Otherwise, failure... */
+- return -1;
+-}
+-
+-/*
+- * Recalculate the vertical video cutoff (hack!)
+- */
+-static void vga_recalc_vertical(void)
+-{
+- unsigned int font_size, rows;
+- u16 crtc;
+- u8 pt, ov;
+-
+- set_fs(0);
+- font_size = rdfs8(0x485); /* BIOS: font size (pixels) */
+- rows = force_y ? force_y : rdfs8(0x484)+1; /* Text rows */
+-
+- rows *= font_size; /* Visible scan lines */
+- rows--; /* ... minus one */
+-
+- crtc = vga_crtc();
+-
+- pt = in_idx(crtc, 0x11);
+- pt &= ~0x80; /* Unlock CR0-7 */
+- out_idx(pt, crtc, 0x11);
+-
+- out_idx((u8)rows, crtc, 0x12); /* Lower height register */
+-
+- ov = in_idx(crtc, 0x07); /* Overflow register */
+- ov &= 0xbd;
+- ov |= (rows >> (8-1)) & 0x02;
+- ov |= (rows >> (9-6)) & 0x40;
+- out_idx(ov, crtc, 0x07);
+-}
+-
+-/* Set mode (with recalc if specified) */
+-static int set_mode(u16 mode)
+-{
+- int rv;
+- u16 real_mode;
+-
+- /* Very special mode numbers... */
+- if (mode == VIDEO_CURRENT_MODE)
+- return 0; /* Nothing to do... */
+- else if (mode == NORMAL_VGA)
+- mode = VIDEO_80x25;
+- else if (mode == EXTENDED_VGA)
+- mode = VIDEO_8POINT;
+-
+- rv = raw_set_mode(mode, &real_mode);
+- if (rv)
+- return rv;
+-
+- if (mode & VIDEO_RECALC)
+- vga_recalc_vertical();
+-
+- /* Save the canonical mode number for the kernel, not
+- an alias, size specification or menu position */
+- boot_params.hdr.vid_mode = real_mode;
+- return 0;
+-}
+-
+ static unsigned int get_entry(void)
+ {
+ char entry_buf[4];
+@@ -486,6 +328,7 @@ void set_video(void)
+ printf("Undefined video mode number: %x\n", mode);
+ mode = ASK_VGA;
+ }
++ boot_params.hdr.vid_mode = mode;
+ vesa_store_edid();
+ store_mode_params();
+
+diff --git a/arch/x86/boot/video.h b/arch/x86/boot/video.h
+index d69347f..ee63f5d 100644
+--- a/arch/x86/boot/video.h
++++ b/arch/x86/boot/video.h
+@@ -9,8 +9,6 @@
+ * ----------------------------------------------------------------------- */
+
+ /*
+- * arch/i386/boot/video.h
+- *
+ * Header file for the real-mode video probing code
+ */
+
+diff --git a/arch/x86/boot/voyager.c b/arch/x86/boot/voyager.c
+index 6499e32..433909d 100644
+--- a/arch/x86/boot/voyager.c
++++ b/arch/x86/boot/voyager.c
+@@ -9,8 +9,6 @@
+ * ----------------------------------------------------------------------- */
+
+ /*
+- * arch/i386/boot/voyager.c
+- *
+ * Get the Voyager config information
+ */
+
+diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig
+index 3df340b..ad7ddaa 100644
+--- a/arch/x86/configs/i386_defconfig
++++ b/arch/x86/configs/i386_defconfig
+@@ -1421,6 +1421,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
+ # CONFIG_DEBUG_VM is not set
+ # CONFIG_DEBUG_LIST is not set
+ # CONFIG_FRAME_POINTER is not set
++CONFIG_OPTIMIZE_INLINING=y
+ # CONFIG_RCU_TORTURE_TEST is not set
+ # CONFIG_LKDTM is not set
+ # CONFIG_FAULT_INJECTION is not set
+diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig
+index eef98cb..2d6f5b2 100644
+--- a/arch/x86/configs/x86_64_defconfig
++++ b/arch/x86/configs/x86_64_defconfig
+@@ -1346,6 +1346,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
+ # CONFIG_DEBUG_VM is not set
+ # CONFIG_DEBUG_LIST is not set
+ # CONFIG_FRAME_POINTER is not set
++CONFIG_OPTIMIZE_INLINING=y
+ # CONFIG_RCU_TORTURE_TEST is not set
+ # CONFIG_LKDTM is not set
+ # CONFIG_FAULT_INJECTION is not set
+diff --git a/arch/x86/crypto/aes-i586-asm_32.S b/arch/x86/crypto/aes-i586-asm_32.S
+index 1093bed..e41b147 100644
+--- a/arch/x86/crypto/aes-i586-asm_32.S
++++ b/arch/x86/crypto/aes-i586-asm_32.S
+@@ -289,7 +289,6 @@ aes_enc_blk:
+ pop %ebx
+ mov %r0,(%ebp)
+ pop %ebp
+- mov $1,%eax
+ ret
+
+ // AES (Rijndael) Decryption Subroutine
+@@ -365,6 +364,4 @@ aes_dec_blk:
+ pop %ebx
+ mov %r0,(%ebp)
+ pop %ebp
+- mov $1,%eax
+ ret
+-
+diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
+index 5e7771a..bbed3a2 100644
+--- a/arch/x86/ia32/ia32_signal.c
++++ b/arch/x86/ia32/ia32_signal.c
+@@ -468,7 +468,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
+ restorer = ka->sa.sa_restorer;
+ } else {
+ /* Return stub is in 32bit vsyscall page */
+- if (current->binfmt->hasvdso)
++ if (current->mm->context.vdso)
+ restorer = VDSO32_SYMBOL(current->mm->context.vdso,
+ sigreturn);
+ else
+@@ -499,11 +499,6 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
+ regs->cs = __USER32_CS;
+ regs->ss = __USER32_DS;
+
+- set_fs(USER_DS);
+- regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF);
+- if (test_thread_flag(TIF_SINGLESTEP))
+- ptrace_notify(SIGTRAP);
+-
+ #if DEBUG_SIG
+ printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
+ current->comm, current->pid, frame, regs->ip, frame->pretcode);
+@@ -599,11 +594,6 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ regs->cs = __USER32_CS;
+ regs->ss = __USER32_DS;
+
+- set_fs(USER_DS);
+- regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF);
+- if (test_thread_flag(TIF_SINGLESTEP))
+- ptrace_notify(SIGTRAP);
+-
+ #if DEBUG_SIG
+ printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
+ current->comm, current->pid, frame, regs->ip, frame->pretcode);
+diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
+index 8022d3c..b5e329d 100644
+--- a/arch/x86/ia32/ia32entry.S
++++ b/arch/x86/ia32/ia32entry.S
+@@ -162,12 +162,14 @@ sysenter_tracesys:
+ SAVE_REST
+ CLEAR_RREGS
+ movq %r9,R9(%rsp)
+- movq $-ENOSYS,RAX(%rsp) /* really needed? */
++ movq $-ENOSYS,RAX(%rsp)/* ptrace can change this for a bad syscall */
+ movq %rsp,%rdi /* &pt_regs -> arg1 */
+ call syscall_trace_enter
+ LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
+ RESTORE_REST
+ xchgl %ebp,%r9d
++ cmpl $(IA32_NR_syscalls-1),%eax
++ ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */
+ jmp sysenter_do_call
+ CFI_ENDPROC
+ ENDPROC(ia32_sysenter_target)
+@@ -261,13 +263,15 @@ cstar_tracesys:
+ SAVE_REST
+ CLEAR_RREGS
+ movq %r9,R9(%rsp)
+- movq $-ENOSYS,RAX(%rsp) /* really needed? */
++ movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
+ movq %rsp,%rdi /* &pt_regs -> arg1 */
+ call syscall_trace_enter
+ LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
+ RESTORE_REST
+ xchgl %ebp,%r9d
+ movl RSP-ARGOFFSET(%rsp), %r8d
++ cmpl $(IA32_NR_syscalls-1),%eax
++ ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */
+ jmp cstar_do_call
+ END(ia32_cstar_target)
+
+@@ -325,7 +329,7 @@ ENTRY(ia32_syscall)
+ jnz ia32_tracesys
+ ia32_do_syscall:
+ cmpl $(IA32_NR_syscalls-1),%eax
+- ja ia32_badsys
++ ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */
+ IA32_ARG_FIXUP
+ call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
+ ia32_sysret:
+@@ -335,7 +339,7 @@ ia32_sysret:
+ ia32_tracesys:
+ SAVE_REST
+ CLEAR_RREGS
+- movq $-ENOSYS,RAX(%rsp) /* really needed? */
++ movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
+ movq %rsp,%rdi /* &pt_regs -> arg1 */
+ call syscall_trace_enter
+ LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
+@@ -426,7 +430,7 @@ ia32_sys_call_table:
+ .quad sys_setuid16
+ .quad sys_getuid16
+ .quad compat_sys_stime /* stime */ /* 25 */
+- .quad sys32_ptrace /* ptrace */
++ .quad compat_sys_ptrace /* ptrace */
+ .quad sys_alarm
+ .quad sys_fstat /* (old)fstat */
+ .quad sys_pause
+diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c
+index abf71d2..f00afdf 100644
+--- a/arch/x86/ia32/sys_ia32.c
++++ b/arch/x86/ia32/sys_ia32.c
+@@ -26,51 +26,26 @@
+ #include <linux/file.h>
+ #include <linux/signal.h>
+ #include <linux/syscalls.h>
+-#include <linux/resource.h>
+ #include <linux/times.h>
+ #include <linux/utsname.h>
+-#include <linux/smp.h>
+ #include <linux/smp_lock.h>
+-#include <linux/sem.h>
+-#include <linux/msg.h>
+ #include <linux/mm.h>
+-#include <linux/shm.h>
+-#include <linux/slab.h>
+ #include <linux/uio.h>
+-#include <linux/nfs_fs.h>
+-#include <linux/quota.h>
+-#include <linux/module.h>
+-#include <linux/sunrpc/svc.h>
+-#include <linux/nfsd/nfsd.h>
+-#include <linux/nfsd/cache.h>
+-#include <linux/nfsd/xdr.h>
+-#include <linux/nfsd/syscall.h>
+ #include <linux/poll.h>
+ #include <linux/personality.h>
+ #include <linux/stat.h>
+-#include <linux/ipc.h>
+ #include <linux/rwsem.h>
+-#include <linux/binfmts.h>
+-#include <linux/init.h>
+-#include <linux/aio_abi.h>
+-#include <linux/aio.h>
+ #include <linux/compat.h>
+ #include <linux/vfs.h>
+ #include <linux/ptrace.h>
+ #include <linux/highuid.h>
+-#include <linux/vmalloc.h>
+-#include <linux/fsnotify.h>
+ #include <linux/sysctl.h>
+ #include <asm/mman.h>
+ #include <asm/types.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #include <asm/atomic.h>
+-#include <asm/ldt.h>
+-
+-#include <net/scm.h>
+-#include <net/sock.h>
+ #include <asm/ia32.h>
++#include <asm/vgtod.h>
+
+ #define AA(__x) ((unsigned long)(__x))
+
+@@ -804,11 +779,6 @@ asmlinkage long sys32_execve(char __user *name, compat_uptr_t __user *argv,
+ if (IS_ERR(filename))
+ return error;
+ error = compat_do_execve(filename, argv, envp, regs);
+- if (error == 0) {
+- task_lock(current);
+- current->ptrace &= ~PT_DTRACE;
+- task_unlock(current);
+- }
+ putname(filename);
+ return error;
+ }
+diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
+index 4eb5ce8..90e092d 100644
+--- a/arch/x86/kernel/Makefile
++++ b/arch/x86/kernel/Makefile
+@@ -2,8 +2,7 @@
+ # Makefile for the linux kernel.
+ #
+
+-extra-y := head_$(BITS).o init_task.o vmlinux.lds
+-extra-$(CONFIG_X86_64) += head64.o
++extra-y := head_$(BITS).o head$(BITS).o init_task.o vmlinux.lds
+
+ CPPFLAGS_vmlinux.lds += -U$(UTS_MACHINE)
+
+@@ -19,16 +18,18 @@ CFLAGS_tsc_64.o := $(nostackp)
+ obj-y := process_$(BITS).o signal_$(BITS).o entry_$(BITS).o
+ obj-y += traps_$(BITS).o irq_$(BITS).o
+ obj-y += time_$(BITS).o ioport.o ldt.o
+-obj-y += setup_$(BITS).o i8259_$(BITS).o
++obj-y += setup_$(BITS).o i8259_$(BITS).o setup.o
+ obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o
+ obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o
+ obj-$(CONFIG_X86_64) += syscall_64.o vsyscall_64.o setup64.o
+-obj-y += pci-dma_$(BITS).o bootflag.o e820_$(BITS).o
+-obj-y += quirks.o i8237.o topology.o kdebugfs.o
+-obj-y += alternative.o i8253.o
+-obj-$(CONFIG_X86_64) += pci-nommu_64.o bugs_64.o
++obj-y += bootflag.o e820_$(BITS).o
++obj-y += pci-dma.o quirks.o i8237.o topology.o kdebugfs.o
++obj-y += alternative.o i8253.o pci-nommu.o
++obj-$(CONFIG_X86_64) += bugs_64.o
+ obj-y += tsc_$(BITS).o io_delay.o rtc.o
+
++obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o
++obj-y += process.o
+ obj-y += i387.o
+ obj-y += ptrace.o
+ obj-y += ds.o
+@@ -47,11 +48,12 @@ obj-$(CONFIG_MICROCODE) += microcode.o
+ obj-$(CONFIG_PCI) += early-quirks.o
+ apm-y := apm_32.o
+ obj-$(CONFIG_APM) += apm.o
+-obj-$(CONFIG_X86_SMP) += smp_$(BITS).o smpboot_$(BITS).o tsc_sync.o
+-obj-$(CONFIG_X86_32_SMP) += smpcommon_32.o
+-obj-$(CONFIG_X86_64_SMP) += smp_64.o smpboot_64.o tsc_sync.o
++obj-$(CONFIG_X86_SMP) += smp.o
++obj-$(CONFIG_X86_SMP) += smpboot.o tsc_sync.o ipi.o tlb_$(BITS).o
++obj-$(CONFIG_X86_32_SMP) += smpcommon.o
++obj-$(CONFIG_X86_64_SMP) += tsc_sync.o smpcommon.o
+ obj-$(CONFIG_X86_TRAMPOLINE) += trampoline_$(BITS).o
+-obj-$(CONFIG_X86_MPPARSE) += mpparse_$(BITS).o
++obj-$(CONFIG_X86_MPPARSE) += mpparse.o
+ obj-$(CONFIG_X86_LOCAL_APIC) += apic_$(BITS).o nmi_$(BITS).o
+ obj-$(CONFIG_X86_IO_APIC) += io_apic_$(BITS).o
+ obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups_32.o
+@@ -60,12 +62,13 @@ obj-$(CONFIG_KEXEC) += relocate_kernel_$(BITS).o crash.o
+ obj-$(CONFIG_CRASH_DUMP) += crash_dump_$(BITS).o
+ obj-$(CONFIG_X86_NUMAQ) += numaq_32.o
+ obj-$(CONFIG_X86_SUMMIT_NUMA) += summit_32.o
+-obj-$(CONFIG_X86_VSMP) += vsmp_64.o
++obj-y += vsmp_64.o
+ obj-$(CONFIG_KPROBES) += kprobes.o
+ obj-$(CONFIG_MODULES) += module_$(BITS).o
+ obj-$(CONFIG_ACPI_SRAT) += srat_32.o
+ obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o
+ obj-$(CONFIG_DOUBLEFAULT) += doublefault_32.o
++obj-$(CONFIG_KGDB) += kgdb.o
+ obj-$(CONFIG_VM86) += vm86_32.o
+ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+
+@@ -89,7 +92,7 @@ scx200-y += scx200_32.o
+ ###
+ # 64 bit specific files
+ ifeq ($(CONFIG_X86_64),y)
+- obj-y += genapic_64.o genapic_flat_64.o
++ obj-y += genapic_64.o genapic_flat_64.o genx2apic_uv_x.o
+ obj-$(CONFIG_X86_PM_TIMER) += pmtimer_64.o
+ obj-$(CONFIG_AUDIT) += audit_64.o
+
+diff --git a/arch/x86/kernel/acpi/Makefile b/arch/x86/kernel/acpi/Makefile
+index 19d3d6e..7335959 100644
+--- a/arch/x86/kernel/acpi/Makefile
++++ b/arch/x86/kernel/acpi/Makefile
+@@ -1,7 +1,14 @@
++subdir- := realmode
++
+ obj-$(CONFIG_ACPI) += boot.o
+-obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup_$(BITS).o
++obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup_rm.o wakeup_$(BITS).o
+
+ ifneq ($(CONFIG_ACPI_PROCESSOR),)
+ obj-y += cstate.o processor.o
+ endif
+
++$(obj)/wakeup_rm.o: $(obj)/realmode/wakeup.bin
++
++$(obj)/realmode/wakeup.bin: FORCE
++ $(Q)$(MAKE) $(build)=$(obj)/realmode $@
++
+diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
+index 2cdc9de..977ed5c 100644
+--- a/arch/x86/kernel/acpi/boot.c
++++ b/arch/x86/kernel/acpi/boot.c
+@@ -39,6 +39,11 @@
+ #include <asm/apic.h>
+ #include <asm/io.h>
+ #include <asm/mpspec.h>
++#include <asm/smp.h>
++
++#ifdef CONFIG_X86_LOCAL_APIC
++# include <mach_apic.h>
++#endif
+
+ static int __initdata acpi_force = 0;
+
+@@ -52,9 +57,7 @@ EXPORT_SYMBOL(acpi_disabled);
+ #ifdef CONFIG_X86_64
+
+ #include <asm/proto.h>
+-
+-static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) { return 0; }
+-
++#include <asm/genapic.h>
+
+ #else /* X86 */
+
+@@ -111,7 +114,7 @@ char *__init __acpi_map_table(unsigned long phys_addr, unsigned long size)
+ if (!phys_addr || !size)
+ return NULL;
+
+- if (phys_addr+size <= (end_pfn_map << PAGE_SHIFT) + PAGE_SIZE)
++ if (phys_addr+size <= (max_pfn_mapped << PAGE_SHIFT) + PAGE_SIZE)
+ return __va(phys_addr);
+
+ return NULL;
+@@ -237,6 +240,16 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
+ return 0;
+ }
+
++static void __cpuinit acpi_register_lapic(int id, u8 enabled)
++{
++ if (!enabled) {
++ ++disabled_cpus;
++ return;
++ }
++
++ generic_processor_info(id, 0);
++}
++
+ static int __init
+ acpi_parse_lapic(struct acpi_subtable_header * header, const unsigned long end)
+ {
+@@ -256,8 +269,26 @@ acpi_parse_lapic(struct acpi_subtable_header * header, const unsigned long end)
+ * to not preallocating memory for all NR_CPUS
+ * when we use CPU hotplug.
+ */
+- mp_register_lapic(processor->id, /* APIC ID */
+- processor->lapic_flags & ACPI_MADT_ENABLED); /* Enabled? */
++ acpi_register_lapic(processor->id, /* APIC ID */
++ processor->lapic_flags & ACPI_MADT_ENABLED);
++
++ return 0;
++}
++
++static int __init
++acpi_parse_sapic(struct acpi_subtable_header *header, const unsigned long end)
++{
++ struct acpi_madt_local_sapic *processor = NULL;
++
++ processor = (struct acpi_madt_local_sapic *)header;
++
++ if (BAD_MADT_ENTRY(processor, end))
++ return -EINVAL;
++
++ acpi_table_print_madt_entry(header);
++
++ acpi_register_lapic((processor->id << 8) | processor->eid,/* APIC ID */
++ processor->lapic_flags & ACPI_MADT_ENABLED);
+
+ return 0;
+ }
+@@ -300,6 +331,8 @@ acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long e
+
+ #ifdef CONFIG_X86_IO_APIC
+
++struct mp_ioapic_routing mp_ioapic_routing[MAX_IO_APICS];
++
+ static int __init
+ acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
+ {
+@@ -532,7 +565,7 @@ static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu)
+ buffer.pointer = NULL;
+
+ tmp_map = cpu_present_map;
+- mp_register_lapic(physid, lapic->lapic_flags & ACPI_MADT_ENABLED);
++ acpi_register_lapic(physid, lapic->lapic_flags & ACPI_MADT_ENABLED);
+
+ /*
+ * If mp_register_lapic successfully generates a new logical cpu
+@@ -664,10 +697,6 @@ static int __init acpi_parse_hpet(struct acpi_table_header *table)
+ #define HPET_RESOURCE_NAME_SIZE 9
+ hpet_res = alloc_bootmem(sizeof(*hpet_res) + HPET_RESOURCE_NAME_SIZE);
+
+- if (!hpet_res)
+- return 0;
+-
+- memset(hpet_res, 0, sizeof(*hpet_res));
+ hpet_res->name = (void *)&hpet_res[1];
+ hpet_res->flags = IORESOURCE_MEM;
+ snprintf((char *)hpet_res->name, HPET_RESOURCE_NAME_SIZE, "HPET %u",
+@@ -732,6 +761,16 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table)
+ * Parse LAPIC entries in MADT
+ * returns 0 on success, < 0 on error
+ */
++
++static void __init acpi_register_lapic_address(unsigned long address)
++{
++ mp_lapic_addr = address;
++
++ set_fixmap_nocache(FIX_APIC_BASE, address);
++ if (boot_cpu_physical_apicid == -1U)
++ boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
++}
++
+ static int __init acpi_parse_madt_lapic_entries(void)
+ {
+ int count;
+@@ -753,10 +792,14 @@ static int __init acpi_parse_madt_lapic_entries(void)
+ return count;
+ }
+
+- mp_register_lapic_address(acpi_lapic_addr);
++ acpi_register_lapic_address(acpi_lapic_addr);
++
++ count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_SAPIC,
++ acpi_parse_sapic, MAX_APICS);
+
+- count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC, acpi_parse_lapic,
+- MAX_APICS);
++ if (!count)
++ count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC,
++ acpi_parse_lapic, MAX_APICS);
+ if (!count) {
+ printk(KERN_ERR PREFIX "No LAPIC entries present\n");
+ /* TBD: Cleanup to allow fallback to MPS */
+diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c
+index 8ca3557..c2502eb 100644
+--- a/arch/x86/kernel/acpi/cstate.c
++++ b/arch/x86/kernel/acpi/cstate.c
+@@ -1,6 +1,4 @@
+ /*
+- * arch/i386/kernel/acpi/cstate.c
+- *
+ * Copyright (C) 2005 Intel Corporation
+ * Venkatesh Pallipadi <venkatesh.pallipadi at intel.com>
+ * - Added _PDC for SMP C-states on Intel CPUs
+@@ -93,7 +91,7 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu,
+
+ /* Make sure we are running on right CPU */
+ saved_mask = current->cpus_allowed;
+- retval = set_cpus_allowed(current, cpumask_of_cpu(cpu));
++ retval = set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ if (retval)
+ return -1;
+
+@@ -130,7 +128,7 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu,
+ cx->address);
+
+ out:
+- set_cpus_allowed(current, saved_mask);
++ set_cpus_allowed_ptr(current, &saved_mask);
+ return retval;
+ }
+ EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_probe);
+diff --git a/arch/x86/kernel/acpi/processor.c b/arch/x86/kernel/acpi/processor.c
+index 324eb0c..de2d2e4 100644
+--- a/arch/x86/kernel/acpi/processor.c
++++ b/arch/x86/kernel/acpi/processor.c
+@@ -1,6 +1,4 @@
+ /*
+- * arch/i386/kernel/acpi/processor.c
+- *
+ * Copyright (C) 2005 Intel Corporation
+ * Venkatesh Pallipadi <venkatesh.pallipadi at intel.com>
+ * - Added _PDC for platforms with Intel CPUs
+diff --git a/arch/x86/kernel/acpi/realmode/.gitignore b/arch/x86/kernel/acpi/realmode/.gitignore
+new file mode 100644
+index 0000000..58f1f48
+--- /dev/null
++++ b/arch/x86/kernel/acpi/realmode/.gitignore
+@@ -0,0 +1,3 @@
++wakeup.bin
++wakeup.elf
++wakeup.lds
+diff --git a/arch/x86/kernel/acpi/realmode/Makefile b/arch/x86/kernel/acpi/realmode/Makefile
+new file mode 100644
+index 0000000..0929008
+--- /dev/null
++++ b/arch/x86/kernel/acpi/realmode/Makefile
+@@ -0,0 +1,57 @@
++#
++# arch/x86/kernel/acpi/realmode/Makefile
++#
++# This file is subject to the terms and conditions of the GNU General Public
++# License. See the file "COPYING" in the main directory of this archive
++# for more details.
++#
++
++targets := wakeup.bin wakeup.elf
++
++wakeup-y += wakeup.o wakemain.o video-mode.o copy.o
++
++# The link order of the video-*.o modules can matter. In particular,
++# video-vga.o *must* be listed first, followed by video-vesa.o.
++# Hardware-specific drivers should follow in the order they should be
++# probed, and video-bios.o should typically be last.
++wakeup-y += video-vga.o
++wakeup-y += video-vesa.o
++wakeup-y += video-bios.o
++
++targets += $(wakeup-y)
++
++bootsrc := $(src)/../../../boot
++
++# ---------------------------------------------------------------------------
++
++# How to compile the 16-bit code. Note we always compile for -march=i386,
++# that way we can complain to the user if the CPU is insufficient.
++# Compile with _SETUP since this is similar to the boot-time setup code.
++KBUILD_CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D_WAKEUP -D__KERNEL__ \
++ -I$(srctree)/$(bootsrc) \
++ $(cflags-y) \
++ -Wall -Wstrict-prototypes \
++ -march=i386 -mregparm=3 \
++ -include $(srctree)/$(bootsrc)/code16gcc.h \
++ -fno-strict-aliasing -fomit-frame-pointer \
++ $(call cc-option, -ffreestanding) \
++ $(call cc-option, -fno-toplevel-reorder,\
++ $(call cc-option, -fno-unit-at-a-time)) \
++ $(call cc-option, -fno-stack-protector) \
++ $(call cc-option, -mpreferred-stack-boundary=2)
++KBUILD_CFLAGS += $(call cc-option, -m32)
++KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
++
++WAKEUP_OBJS = $(addprefix $(obj)/,$(wakeup-y))
++
++LDFLAGS_wakeup.elf := -T
++
++CPPFLAGS_wakeup.lds += -P -C
++
++$(obj)/wakeup.elf: $(src)/wakeup.lds $(WAKEUP_OBJS) FORCE
++ $(call if_changed,ld)
++
++OBJCOPYFLAGS_wakeup.bin := -O binary
++
++$(obj)/wakeup.bin: $(obj)/wakeup.elf FORCE
++ $(call if_changed,objcopy)
+diff --git a/arch/x86/kernel/acpi/realmode/copy.S b/arch/x86/kernel/acpi/realmode/copy.S
+new file mode 100644
+index 0000000..dc59ebe
+--- /dev/null
++++ b/arch/x86/kernel/acpi/realmode/copy.S
+@@ -0,0 +1 @@
++#include "../../../boot/copy.S"
+diff --git a/arch/x86/kernel/acpi/realmode/video-bios.c b/arch/x86/kernel/acpi/realmode/video-bios.c
+new file mode 100644
+index 0000000..7deabc1
+--- /dev/null
++++ b/arch/x86/kernel/acpi/realmode/video-bios.c
+@@ -0,0 +1 @@
++#include "../../../boot/video-bios.c"
+diff --git a/arch/x86/kernel/acpi/realmode/video-mode.c b/arch/x86/kernel/acpi/realmode/video-mode.c
+new file mode 100644
+index 0000000..328ad20
+--- /dev/null
++++ b/arch/x86/kernel/acpi/realmode/video-mode.c
+@@ -0,0 +1 @@
++#include "../../../boot/video-mode.c"
+diff --git a/arch/x86/kernel/acpi/realmode/video-vesa.c b/arch/x86/kernel/acpi/realmode/video-vesa.c
+new file mode 100644
+index 0000000..9dbb967
+--- /dev/null
++++ b/arch/x86/kernel/acpi/realmode/video-vesa.c
+@@ -0,0 +1 @@
++#include "../../../boot/video-vesa.c"
+diff --git a/arch/x86/kernel/acpi/realmode/video-vga.c b/arch/x86/kernel/acpi/realmode/video-vga.c
+new file mode 100644
+index 0000000..bcc8125
+--- /dev/null
++++ b/arch/x86/kernel/acpi/realmode/video-vga.c
+@@ -0,0 +1 @@
++#include "../../../boot/video-vga.c"
+diff --git a/arch/x86/kernel/acpi/realmode/wakemain.c b/arch/x86/kernel/acpi/realmode/wakemain.c
+new file mode 100644
+index 0000000..883962d
+--- /dev/null
++++ b/arch/x86/kernel/acpi/realmode/wakemain.c
+@@ -0,0 +1,81 @@
++#include "wakeup.h"
++#include "boot.h"
++
++static void udelay(int loops)
++{
++ while (loops--)
++ io_delay(); /* Approximately 1 us */
++}
++
++static void beep(unsigned int hz)
++{
++ u8 enable;
++
++ if (!hz) {
++ enable = 0x00; /* Turn off speaker */
++ } else {
++ u16 div = 1193181/hz;
++
++ outb(0xb6, 0x43); /* Ctr 2, squarewave, load, binary */
++ io_delay();
++ outb(div, 0x42); /* LSB of counter */
++ io_delay();
++ outb(div >> 8, 0x42); /* MSB of counter */
++ io_delay();
++
++ enable = 0x03; /* Turn on speaker */
++ }
++ inb(0x61); /* Dummy read of System Control Port B */
++ io_delay();
++ outb(enable, 0x61); /* Enable timer 2 output to speaker */
++ io_delay();
++}
++
++#define DOT_HZ 880
++#define DASH_HZ 587
++#define US_PER_DOT 125000
++
++/* Okay, this is totally silly, but it's kind of fun. */
++static void send_morse(const char *pattern)
++{
++ char s;
++
++ while ((s = *pattern++)) {
++ switch (s) {
++ case '.':
++ beep(DOT_HZ);
++ udelay(US_PER_DOT);
++ beep(0);
++ udelay(US_PER_DOT);
++ break;
++ case '-':
++ beep(DASH_HZ);
++ udelay(US_PER_DOT * 3);
++ beep(0);
++ udelay(US_PER_DOT);
++ break;
++ default: /* Assume it's a space */
++ udelay(US_PER_DOT * 3);
++ break;
++ }
++ }
++}
++
++void main(void)
++{
++ /* Kill machine if structures are wrong */
++ if (wakeup_header.real_magic != 0x12345678)
++ while (1);
++
++ if (wakeup_header.realmode_flags & 4)
++ send_morse("...-");
++
++ if (wakeup_header.realmode_flags & 1)
++ asm volatile("lcallw $0xc000,$3");
++
++ if (wakeup_header.realmode_flags & 2) {
++ /* Need to call BIOS */
++ probe_cards(0);
++ set_mode(wakeup_header.video_mode);
++ }
++}
+diff --git a/arch/x86/kernel/acpi/realmode/wakeup.S b/arch/x86/kernel/acpi/realmode/wakeup.S
+new file mode 100644
+index 0000000..f9b77fb
+--- /dev/null
++++ b/arch/x86/kernel/acpi/realmode/wakeup.S
+@@ -0,0 +1,113 @@
++/*
++ * ACPI wakeup real mode startup stub
++ */
++#include <asm/segment.h>
++#include <asm/msr-index.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++
++ .code16
++ .section ".header", "a"
++
++/* This should match the structure in wakeup.h */
++ .globl wakeup_header
++wakeup_header:
++video_mode: .short 0 /* Video mode number */
++pmode_return: .byte 0x66, 0xea /* ljmpl */
++ .long 0 /* offset goes here */
++ .short __KERNEL_CS
++pmode_cr0: .long 0 /* Saved %cr0 */
++pmode_cr3: .long 0 /* Saved %cr3 */
++pmode_cr4: .long 0 /* Saved %cr4 */
++pmode_efer: .quad 0 /* Saved EFER */
++pmode_gdt: .quad 0
++realmode_flags: .long 0
++real_magic: .long 0
++trampoline_segment: .word 0
++signature: .long 0x51ee1111
++
++ .text
++ .globl _start
++ .code16
++wakeup_code:
++_start:
++ cli
++ cld
++
++ /* Set up segments */
++ movw %cs, %ax
++ movw %ax, %ds
++ movw %ax, %es
++ movw %ax, %ss
++
++ movl $wakeup_stack_end, %esp
++
++ /* Clear the EFLAGS */
++ pushl $0
++ popfl
++
++ /* Check header signature... */
++ movl signature, %eax
++ cmpl $0x51ee1111, %eax
++ jne bogus_real_magic
++
++ /* Check we really have everything... */
++ movl end_signature, %eax
++ cmpl $0x65a22c82, %eax
++ jne bogus_real_magic
++
++ /* Call the C code */
++ calll main
++
++ /* Do any other stuff... */
++
++#ifndef CONFIG_64BIT
++ /* This could also be done in C code... */
++ movl pmode_cr3, %eax
++ movl %eax, %cr3
++
++ movl pmode_cr4, %ecx
++ jecxz 1f
++ movl %ecx, %cr4
++1:
++ movl pmode_efer, %eax
++ movl pmode_efer + 4, %edx
++ movl %eax, %ecx
++ orl %edx, %ecx
++ jz 1f
++ movl $0xc0000080, %ecx
++ wrmsr
++1:
++
++ lgdtl pmode_gdt
++
++ /* This really couldn't... */
++ movl pmode_cr0, %eax
++ movl %eax, %cr0
++ jmp pmode_return
++#else
++ pushw $0
++ pushw trampoline_segment
++ pushw $0
++ lret
++#endif
++
++bogus_real_magic:
++1:
++ hlt
++ jmp 1b
++
++ .data
++ .balign 4
++ .globl HEAP, heap_end
++HEAP:
++ .long wakeup_heap
++heap_end:
++ .long wakeup_stack
++
++ .bss
++wakeup_heap:
++ .space 2048
++wakeup_stack:
++ .space 2048
++wakeup_stack_end:
+diff --git a/arch/x86/kernel/acpi/realmode/wakeup.h b/arch/x86/kernel/acpi/realmode/wakeup.h
+new file mode 100644
+index 0000000..ef8166f
+--- /dev/null
++++ b/arch/x86/kernel/acpi/realmode/wakeup.h
+@@ -0,0 +1,36 @@
++/*
++ * Definitions for the wakeup data structure at the head of the
++ * wakeup code.
++ */
++
++#ifndef ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H
++#define ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H
++
++#ifndef __ASSEMBLY__
++#include <linux/types.h>
++
++/* This must match data at wakeup.S */
++struct wakeup_header {
++ u16 video_mode; /* Video mode number */
++ u16 _jmp1; /* ljmpl opcode, 32-bit only */
++ u32 pmode_entry; /* Protected mode resume point, 32-bit only */
++ u16 _jmp2; /* CS value, 32-bit only */
++ u32 pmode_cr0; /* Protected mode cr0 */
++ u32 pmode_cr3; /* Protected mode cr3 */
++ u32 pmode_cr4; /* Protected mode cr4 */
++ u32 pmode_efer_low; /* Protected mode EFER */
++ u32 pmode_efer_high;
++ u64 pmode_gdt;
++ u32 realmode_flags;
++ u32 real_magic;
++ u16 trampoline_segment; /* segment with trampoline code, 64-bit only */
++ u32 signature; /* To check we have correct structure */
++} __attribute__((__packed__));
++
++extern struct wakeup_header wakeup_header;
++#endif
++
++#define HEADER_OFFSET 0x3f00
++#define WAKEUP_SIZE 0x4000
++
++#endif /* ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H */
+diff --git a/arch/x86/kernel/acpi/realmode/wakeup.lds.S b/arch/x86/kernel/acpi/realmode/wakeup.lds.S
+new file mode 100644
+index 0000000..22fab6c
+--- /dev/null
++++ b/arch/x86/kernel/acpi/realmode/wakeup.lds.S
+@@ -0,0 +1,61 @@
++/*
++ * wakeup.ld
++ *
++ * Linker script for the real-mode wakeup code
++ */
++#undef i386
++#include "wakeup.h"
++
++OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
++OUTPUT_ARCH(i386)
++ENTRY(_start)
++
++SECTIONS
++{
++ . = HEADER_OFFSET;
++ .header : {
++ *(.header)
++ }
++
++ . = 0;
++ .text : {
++ *(.text*)
++ }
++
++ . = ALIGN(16);
++ .rodata : {
++ *(.rodata*)
++ }
++
++ .videocards : {
++ video_cards = .;
++ *(.videocards)
++ video_cards_end = .;
++ }
++
++ . = ALIGN(16);
++ .data : {
++ *(.data*)
++ }
++
++ .signature : {
++ end_signature = .;
++ LONG(0x65a22c82)
++ }
++
++ . = ALIGN(16);
++ .bss : {
++ __bss_start = .;
++ *(.bss)
++ __bss_end = .;
++ }
++
++ . = ALIGN(16);
++ _end = .;
++
++ /DISCARD/ : {
++ *(.note*)
++ }
++
++ . = ASSERT(_end <= WAKEUP_SIZE, "Wakeup too big!");
++}
+diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
+index 6bc815c..afc25ee 100644
+--- a/arch/x86/kernel/acpi/sleep.c
++++ b/arch/x86/kernel/acpi/sleep.c
+@@ -10,30 +10,72 @@
+ #include <linux/dmi.h>
+ #include <linux/cpumask.h>
+
+-#include <asm/smp.h>
++#include "realmode/wakeup.h"
++#include "sleep.h"
+
+-/* address in low memory of the wakeup routine. */
+-unsigned long acpi_wakeup_address = 0;
++unsigned long acpi_wakeup_address;
+ unsigned long acpi_realmode_flags;
+-extern char wakeup_start, wakeup_end;
+
+-extern unsigned long acpi_copy_wakeup_routine(unsigned long);
++/* address in low memory of the wakeup routine. */
++static unsigned long acpi_realmode;
++
++#ifdef CONFIG_64BIT
++static char temp_stack[10240];
++#endif
+
+ /**
+ * acpi_save_state_mem - save kernel state
+ *
+ * Create an identity mapped page table and copy the wakeup routine to
+ * low memory.
++ *
++ * Note that this is too late to change acpi_wakeup_address.
+ */
+ int acpi_save_state_mem(void)
+ {
+- if (!acpi_wakeup_address) {
+- printk(KERN_ERR "Could not allocate memory during boot, S3 disabled\n");
++ struct wakeup_header *header;
++
++ if (!acpi_realmode) {
++ printk(KERN_ERR "Could not allocate memory during boot, "
++ "S3 disabled\n");
+ return -ENOMEM;
+ }
+- memcpy((void *)acpi_wakeup_address, &wakeup_start,
+- &wakeup_end - &wakeup_start);
+- acpi_copy_wakeup_routine(acpi_wakeup_address);
++ memcpy((void *)acpi_realmode, &wakeup_code_start, WAKEUP_SIZE);
++
++ header = (struct wakeup_header *)(acpi_realmode + HEADER_OFFSET);
++ if (header->signature != 0x51ee1111) {
++ printk(KERN_ERR "wakeup header does not match\n");
++ return -EINVAL;
++ }
++
++ header->video_mode = saved_video_mode;
++
++#ifndef CONFIG_64BIT
++ store_gdt((struct desc_ptr *)&header->pmode_gdt);
++
++ header->pmode_efer_low = nx_enabled;
++ if (header->pmode_efer_low & 1) {
++ /* This is strange, why not save efer, always? */
++ rdmsr(MSR_EFER, header->pmode_efer_low,
++ header->pmode_efer_high);
++ }
++#endif /* !CONFIG_64BIT */
++
++ header->pmode_cr0 = read_cr0();
++ header->pmode_cr4 = read_cr4();
++ header->realmode_flags = acpi_realmode_flags;
++ header->real_magic = 0x12345678;
++
++#ifndef CONFIG_64BIT
++ header->pmode_entry = (u32)&wakeup_pmode_return;
++ header->pmode_cr3 = (u32)(swsusp_pg_dir - __PAGE_OFFSET);
++ saved_magic = 0x12345678;
++#else /* CONFIG_64BIT */
++ header->trampoline_segment = setup_trampoline() >> 4;
++ init_rsp = (unsigned long)temp_stack + 4096;
++ initial_code = (unsigned long)wakeup_long64;
++ saved_magic = 0x123456789abcdef0;
++#endif /* CONFIG_64BIT */
+
+ return 0;
+ }
+@@ -56,15 +98,20 @@ void acpi_restore_state_mem(void)
+ */
+ void __init acpi_reserve_bootmem(void)
+ {
+- if ((&wakeup_end - &wakeup_start) > PAGE_SIZE*2) {
++ if ((&wakeup_code_end - &wakeup_code_start) > WAKEUP_SIZE) {
+ printk(KERN_ERR
+ "ACPI: Wakeup code way too big, S3 disabled.\n");
+ return;
+ }
+
+- acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE*2);
+- if (!acpi_wakeup_address)
++ acpi_realmode = (unsigned long)alloc_bootmem_low(WAKEUP_SIZE);
++
++ if (!acpi_realmode) {
+ printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n");
++ return;
++ }
++
++ acpi_wakeup_address = acpi_realmode;
+ }
+
+
+diff --git a/arch/x86/kernel/acpi/sleep.h b/arch/x86/kernel/acpi/sleep.h
+new file mode 100644
+index 0000000..adbcbaa
+--- /dev/null
++++ b/arch/x86/kernel/acpi/sleep.h
+@@ -0,0 +1,16 @@
++/*
++ * Variables and functions used by the code in sleep.c
++ */
++
++#include <asm/trampoline.h>
++
++extern char wakeup_code_start, wakeup_code_end;
++
++extern unsigned long saved_video_mode;
++extern long saved_magic;
++
++extern int wakeup_pmode_return;
++extern char swsusp_pg_dir[PAGE_SIZE];
++
++extern unsigned long acpi_copy_wakeup_routine(unsigned long);
++extern void wakeup_long64(void);
+diff --git a/arch/x86/kernel/acpi/sleep_32.c b/arch/x86/kernel/acpi/sleep_32.c
+deleted file mode 100644
+index 63fe552..0000000
+--- a/arch/x86/kernel/acpi/sleep_32.c
++++ /dev/null
+@@ -1,40 +0,0 @@
+-/*
+- * sleep.c - x86-specific ACPI sleep support.
+- *
+- * Copyright (C) 2001-2003 Patrick Mochel
+- * Copyright (C) 2001-2003 Pavel Machek <pavel at suse.cz>
+- */
+-
+-#include <linux/acpi.h>
+-#include <linux/bootmem.h>
+-#include <linux/dmi.h>
+-#include <linux/cpumask.h>
+-
+-#include <asm/smp.h>
+-
+-/* Ouch, we want to delete this. We already have better version in userspace, in
+- s2ram from suspend.sf.net project */
+-static __init int reset_videomode_after_s3(const struct dmi_system_id *d)
+-{
+- acpi_realmode_flags |= 2;
+- return 0;
+-}
+-
+-static __initdata struct dmi_system_id acpisleep_dmi_table[] = {
+- { /* Reset video mode after returning from ACPI S3 sleep */
+- .callback = reset_videomode_after_s3,
+- .ident = "Toshiba Satellite 4030cdt",
+- .matches = {
+- DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
+- },
+- },
+- {}
+-};
+-
+-static int __init acpisleep_dmi_init(void)
+-{
+- dmi_check_system(acpisleep_dmi_table);
+- return 0;
+-}
+-
+-core_initcall(acpisleep_dmi_init);
+diff --git a/arch/x86/kernel/acpi/wakeup_32.S b/arch/x86/kernel/acpi/wakeup_32.S
+index f53e327..a12e6a9 100644
+--- a/arch/x86/kernel/acpi/wakeup_32.S
++++ b/arch/x86/kernel/acpi/wakeup_32.S
+@@ -3,178 +3,12 @@
+ #include <asm/segment.h>
+ #include <asm/page.h>
+
+-#
+-# wakeup_code runs in real mode, and at unknown address (determined at run-time).
+-# Therefore it must only use relative jumps/calls.
+-#
+-# Do we need to deal with A20? It is okay: ACPI specs says A20 must be enabled
+-#
+-# If physical address of wakeup_code is 0x12345, BIOS should call us with
+-# cs = 0x1234, eip = 0x05
+-#
+-
+-#define BEEP \
+- inb $97, %al; \
+- outb %al, $0x80; \
+- movb $3, %al; \
+- outb %al, $97; \
+- outb %al, $0x80; \
+- movb $-74, %al; \
+- outb %al, $67; \
+- outb %al, $0x80; \
+- movb $-119, %al; \
+- outb %al, $66; \
+- outb %al, $0x80; \
+- movb $15, %al; \
+- outb %al, $66;
+-
+-ALIGN
+- .align 4096
+-ENTRY(wakeup_start)
+-wakeup_code:
+- wakeup_code_start = .
+- .code16
+-
+- cli
+- cld
+-
+- # setup data segment
+- movw %cs, %ax
+- movw %ax, %ds # Make ds:0 point to wakeup_start
+- movw %ax, %ss
+-
+- testl $4, realmode_flags - wakeup_code
+- jz 1f
+- BEEP
+-1:
+- mov $(wakeup_stack - wakeup_code), %sp # Private stack is needed for ASUS board
+-
+- pushl $0 # Kill any dangerous flags
+- popfl
+-
+- movl real_magic - wakeup_code, %eax
+- cmpl $0x12345678, %eax
+- jne bogus_real_magic
+-
+- testl $1, realmode_flags - wakeup_code
+- jz 1f
+- lcall $0xc000,$3
+- movw %cs, %ax
+- movw %ax, %ds # Bios might have played with that
+- movw %ax, %ss
+-1:
+-
+- testl $2, realmode_flags - wakeup_code
+- jz 1f
+- mov video_mode - wakeup_code, %ax
+- call mode_set
+-1:
+-
+- # set up page table
+- movl $swsusp_pg_dir-__PAGE_OFFSET, %eax
+- movl %eax, %cr3
+-
+- testl $1, real_efer_save_restore - wakeup_code
+- jz 4f
+- # restore efer setting
+- movl real_save_efer_edx - wakeup_code, %edx
+- movl real_save_efer_eax - wakeup_code, %eax
+- mov $0xc0000080, %ecx
+- wrmsr
+-4:
+- # make sure %cr4 is set correctly (features, etc)
+- movl real_save_cr4 - wakeup_code, %eax
+- movl %eax, %cr4
+-
+- # need a gdt -- use lgdtl to force 32-bit operands, in case
+- # the GDT is located past 16 megabytes.
+- lgdtl real_save_gdt - wakeup_code
+-
+- movl real_save_cr0 - wakeup_code, %eax
+- movl %eax, %cr0
+- jmp 1f
+-1:
+- movl real_magic - wakeup_code, %eax
+- cmpl $0x12345678, %eax
+- jne bogus_real_magic
+-
+- testl $8, realmode_flags - wakeup_code
+- jz 1f
+- BEEP
+-1:
+- ljmpl $__KERNEL_CS, $wakeup_pmode_return
+-
+-real_save_gdt: .word 0
+- .long 0
+-real_save_cr0: .long 0
+-real_save_cr3: .long 0
+-real_save_cr4: .long 0
+-real_magic: .long 0
+-video_mode: .long 0
+-realmode_flags: .long 0
+-real_efer_save_restore: .long 0
+-real_save_efer_edx: .long 0
+-real_save_efer_eax: .long 0
+-
+-bogus_real_magic:
+- jmp bogus_real_magic
+-
+-/* This code uses an extended set of video mode numbers. These include:
+- * Aliases for standard modes
+- * NORMAL_VGA (-1)
+- * EXTENDED_VGA (-2)
+- * ASK_VGA (-3)
+- * Video modes numbered by menu position -- NOT RECOMMENDED because of lack
+- * of compatibility when extending the table. These are between 0x00 and 0xff.
+- */
+-#define VIDEO_FIRST_MENU 0x0000
+-
+-/* Standard BIOS video modes (BIOS number + 0x0100) */
+-#define VIDEO_FIRST_BIOS 0x0100
+-
+-/* VESA BIOS video modes (VESA number + 0x0200) */
+-#define VIDEO_FIRST_VESA 0x0200
+-
+-/* Video7 special modes (BIOS number + 0x0900) */
+-#define VIDEO_FIRST_V7 0x0900
+-
+-# Setting of user mode (AX=mode ID) => CF=success
+-
+-# For now, we only handle VESA modes (0x0200..0x03ff). To handle other
+-# modes, we should probably compile in the video code from the boot
+-# directory.
+-mode_set:
+- movw %ax, %bx
+- subb $VIDEO_FIRST_VESA>>8, %bh
+- cmpb $2, %bh
+- jb check_vesa
+-
+-setbad:
+- clc
+- ret
+-
+-check_vesa:
+- orw $0x4000, %bx # Use linear frame buffer
+- movw $0x4f02, %ax # VESA BIOS mode set call
+- int $0x10
+- cmpw $0x004f, %ax # AL=4f if implemented
+- jnz setbad # AH=0 if OK
+-
+- stc
+- ret
++# Copyright 2003, 2008 Pavel Machek <pavel at suse.cz>, distribute under GPLv2
+
+ .code32
+ ALIGN
+
+-.org 0x800
+-wakeup_stack_begin: # Stack grows down
+-
+-.org 0xff0 # Just below end of page
+-wakeup_stack:
+-ENTRY(wakeup_end)
+-
+-.org 0x1000
+-
++ENTRY(wakeup_pmode_return)
+ wakeup_pmode_return:
+ movw $__KERNEL_DS, %ax
+ movw %ax, %ss
+@@ -187,7 +21,7 @@ wakeup_pmode_return:
+ lgdt saved_gdt
+ lidt saved_idt
+ lldt saved_ldt
+- ljmp $(__KERNEL_CS),$1f
++ ljmp $(__KERNEL_CS), $1f
+ 1:
+ movl %cr3, %eax
+ movl %eax, %cr3
+@@ -201,82 +35,41 @@ wakeup_pmode_return:
+ jne bogus_magic
+
+ # jump to place where we left off
+- movl saved_eip,%eax
++ movl saved_eip, %eax
+ jmp *%eax
+
+ bogus_magic:
+ jmp bogus_magic
+
+
+-##
+-# acpi_copy_wakeup_routine
+-#
+-# Copy the above routine to low memory.
+-#
+-# Parameters:
+-# %eax: place to copy wakeup routine to
+-#
+-# Returned address is location of code in low memory (past data and stack)
+-#
+-ENTRY(acpi_copy_wakeup_routine)
+
+- pushl %ebx
++save_registers:
+ sgdt saved_gdt
+ sidt saved_idt
+ sldt saved_ldt
+ str saved_tss
+
+- movl nx_enabled, %edx
+- movl %edx, real_efer_save_restore - wakeup_start (%eax)
+- testl $1, real_efer_save_restore - wakeup_start (%eax)
+- jz 2f
+- # save efer setting
+- pushl %eax
+- movl %eax, %ebx
+- mov $0xc0000080, %ecx
+- rdmsr
+- movl %edx, real_save_efer_edx - wakeup_start (%ebx)
+- movl %eax, real_save_efer_eax - wakeup_start (%ebx)
+- popl %eax
+-2:
+-
+- movl %cr3, %edx
+- movl %edx, real_save_cr3 - wakeup_start (%eax)
+- movl %cr4, %edx
+- movl %edx, real_save_cr4 - wakeup_start (%eax)
+- movl %cr0, %edx
+- movl %edx, real_save_cr0 - wakeup_start (%eax)
+- sgdt real_save_gdt - wakeup_start (%eax)
+-
+- movl saved_videomode, %edx
+- movl %edx, video_mode - wakeup_start (%eax)
+- movl acpi_realmode_flags, %edx
+- movl %edx, realmode_flags - wakeup_start (%eax)
+- movl $0x12345678, real_magic - wakeup_start (%eax)
+- movl $0x12345678, saved_magic
+- popl %ebx
+- ret
+-
+-save_registers:
+ leal 4(%esp), %eax
+ movl %eax, saved_context_esp
+- movl %ebx, saved_context_ebx
+- movl %ebp, saved_context_ebp
+- movl %esi, saved_context_esi
+- movl %edi, saved_context_edi
+- pushfl ; popl saved_context_eflags
+-
+- movl $ret_point, saved_eip
++ movl %ebx, saved_context_ebx
++ movl %ebp, saved_context_ebp
++ movl %esi, saved_context_esi
++ movl %edi, saved_context_edi
++ pushfl
++ popl saved_context_eflags
++
++ movl $ret_point, saved_eip
+ ret
+
+
+ restore_registers:
+- movl saved_context_ebp, %ebp
+- movl saved_context_ebx, %ebx
+- movl saved_context_esi, %esi
+- movl saved_context_edi, %edi
+- pushl saved_context_eflags ; popfl
+- ret
++ movl saved_context_ebp, %ebp
++ movl saved_context_ebx, %ebx
++ movl saved_context_esi, %esi
++ movl saved_context_edi, %edi
++ pushl saved_context_eflags
++ popfl
++ ret
+
+ ENTRY(do_suspend_lowlevel)
+ call save_processor_state
+diff --git a/arch/x86/kernel/acpi/wakeup_64.S b/arch/x86/kernel/acpi/wakeup_64.S
+index 2e1b9e0..bcc2934 100644
+--- a/arch/x86/kernel/acpi/wakeup_64.S
++++ b/arch/x86/kernel/acpi/wakeup_64.S
+@@ -7,191 +7,18 @@
+ #include <asm/asm-offsets.h>
+
+ # Copyright 2003 Pavel Machek <pavel at suse.cz>, distribute under GPLv2
+-#
+-# wakeup_code runs in real mode, and at unknown address (determined at run-time).
+-# Therefore it must only use relative jumps/calls.
+-#
+-# Do we need to deal with A20? It is okay: ACPI specs says A20 must be enabled
+-#
+-# If physical address of wakeup_code is 0x12345, BIOS should call us with
+-# cs = 0x1234, eip = 0x05
+-#
+-
+-#define BEEP \
+- inb $97, %al; \
+- outb %al, $0x80; \
+- movb $3, %al; \
+- outb %al, $97; \
+- outb %al, $0x80; \
+- movb $-74, %al; \
+- outb %al, $67; \
+- outb %al, $0x80; \
+- movb $-119, %al; \
+- outb %al, $66; \
+- outb %al, $0x80; \
+- movb $15, %al; \
+- outb %al, $66;
+-
+-
+-ALIGN
+- .align 16
+-ENTRY(wakeup_start)
+-wakeup_code:
+- wakeup_code_start = .
+- .code16
+-
+-# Running in *copy* of this code, somewhere in low 1MB.
+-
+- cli
+- cld
+- # setup data segment
+- movw %cs, %ax
+- movw %ax, %ds # Make ds:0 point to wakeup_start
+- movw %ax, %ss
+-
+- # Data segment must be set up before we can see whether to beep.
+- testl $4, realmode_flags - wakeup_code
+- jz 1f
+- BEEP
+-1:
+-
+- # Private stack is needed for ASUS board
+- mov $(wakeup_stack - wakeup_code), %sp
+-
+- pushl $0 # Kill any dangerous flags
+- popfl
+-
+- movl real_magic - wakeup_code, %eax
+- cmpl $0x12345678, %eax
+- jne bogus_real_magic
+-
+- testl $1, realmode_flags - wakeup_code
+- jz 1f
+- lcall $0xc000,$3
+- movw %cs, %ax
+- movw %ax, %ds # Bios might have played with that
+- movw %ax, %ss
+-1:
+-
+- testl $2, realmode_flags - wakeup_code
+- jz 1f
+- mov video_mode - wakeup_code, %ax
+- call mode_set
+-1:
+-
+- mov %ds, %ax # Find 32bit wakeup_code addr
+- movzx %ax, %esi # (Convert %ds:gdt to a liner ptr)
+- shll $4, %esi
+- # Fix up the vectors
+- addl %esi, wakeup_32_vector - wakeup_code
+- addl %esi, wakeup_long64_vector - wakeup_code
+- addl %esi, gdt_48a + 2 - wakeup_code # Fixup the gdt pointer
+-
+- lidtl %ds:idt_48a - wakeup_code
+- lgdtl %ds:gdt_48a - wakeup_code # load gdt with whatever is
+- # appropriate
+-
+- movl $1, %eax # protected mode (PE) bit
+- lmsw %ax # This is it!
+- jmp 1f
+-1:
+-
+- ljmpl *(wakeup_32_vector - wakeup_code)
+-
+- .balign 4
+-wakeup_32_vector:
+- .long wakeup_32 - wakeup_code
+- .word __KERNEL32_CS, 0
+-
+- .code32
+-wakeup_32:
+-# Running in this code, but at low address; paging is not yet turned on.
+-
+- movl $__KERNEL_DS, %eax
+- movl %eax, %ds
+-
+- /*
+- * Prepare for entering 64bits mode
+- */
+-
+- /* Enable PAE */
+- xorl %eax, %eax
+- btsl $5, %eax
+- movl %eax, %cr4
+-
+- /* Setup early boot stage 4 level pagetables */
+- leal (wakeup_level4_pgt - wakeup_code)(%esi), %eax
+- movl %eax, %cr3
+-
+- /* Check if nx is implemented */
+- movl $0x80000001, %eax
+- cpuid
+- movl %edx,%edi
+-
+- /* Enable Long Mode */
+- xorl %eax, %eax
+- btsl $_EFER_LME, %eax
+-
+- /* No Execute supported? */
+- btl $20,%edi
+- jnc 1f
+- btsl $_EFER_NX, %eax
+-
+- /* Make changes effective */
+-1: movl $MSR_EFER, %ecx
+- xorl %edx, %edx
+- wrmsr
+-
+- xorl %eax, %eax
+- btsl $31, %eax /* Enable paging and in turn activate Long Mode */
+- btsl $0, %eax /* Enable protected mode */
+-
+- /* Make changes effective */
+- movl %eax, %cr0
+-
+- /* At this point:
+- CR4.PAE must be 1
+- CS.L must be 0
+- CR3 must point to PML4
+- Next instruction must be a branch
+- This must be on identity-mapped page
+- */
+- /*
+- * At this point we're in long mode but in 32bit compatibility mode
+- * with EFER.LME = 1, CS.L = 0, CS.D = 1 (and in turn
+- * EFER.LMA = 1). Now we want to jump in 64bit mode, to do that we load
+- * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
+- */
+-
+- /* Finally jump in 64bit mode */
+- ljmp *(wakeup_long64_vector - wakeup_code)(%esi)
+-
+- .balign 4
+-wakeup_long64_vector:
+- .long wakeup_long64 - wakeup_code
+- .word __KERNEL_CS, 0
+
+ .code64
+-
+- /* Hooray, we are in Long 64-bit mode (but still running in
+- * low memory)
+- */
+-wakeup_long64:
+ /*
+- * We must switch to a new descriptor in kernel space for the GDT
+- * because soon the kernel won't have access anymore to the userspace
+- * addresses where we're currently running on. We have to do that here
+- * because in 32bit we couldn't load a 64bit linear address.
++ * Hooray, we are in Long 64-bit mode (but still running in low memory)
+ */
+- lgdt cpu_gdt_descr
+-
+- movq saved_magic, %rax
+- movq $0x123456789abcdef0, %rdx
+- cmpq %rdx, %rax
+- jne bogus_64_magic
++ENTRY(wakeup_long64)
++wakeup_long64:
++ movq saved_magic, %rax
++ movq $0x123456789abcdef0, %rdx
++ cmpq %rdx, %rax
++ jne bogus_64_magic
+
+- nop
+- nop
+ movw $__KERNEL_DS, %ax
+ movw %ax, %ss
+ movw %ax, %ds
+@@ -208,130 +35,8 @@ wakeup_long64:
+ movq saved_rip, %rax
+ jmp *%rax
+
+-.code32
+-
+- .align 64
+-gdta:
+- /* Its good to keep gdt in sync with one in trampoline.S */
+- .word 0, 0, 0, 0 # dummy
+- /* ??? Why I need the accessed bit set in order for this to work? */
+- .quad 0x00cf9b000000ffff # __KERNEL32_CS
+- .quad 0x00af9b000000ffff # __KERNEL_CS
+- .quad 0x00cf93000000ffff # __KERNEL_DS
+-
+-idt_48a:
+- .word 0 # idt limit = 0
+- .word 0, 0 # idt base = 0L
+-
+-gdt_48a:
+- .word 0x800 # gdt limit=2048,
+- # 256 GDT entries
+- .long gdta - wakeup_code # gdt base (relocated in later)
+-
+-real_magic: .quad 0
+-video_mode: .quad 0
+-realmode_flags: .quad 0
+-
+-.code16
+-bogus_real_magic:
+- jmp bogus_real_magic
+-
+-.code64
+ bogus_64_magic:
+- jmp bogus_64_magic
+-
+-/* This code uses an extended set of video mode numbers. These include:
+- * Aliases for standard modes
+- * NORMAL_VGA (-1)
+- * EXTENDED_VGA (-2)
+- * ASK_VGA (-3)
+- * Video modes numbered by menu position -- NOT RECOMMENDED because of lack
+- * of compatibility when extending the table. These are between 0x00 and 0xff.
+- */
+-#define VIDEO_FIRST_MENU 0x0000
+-
+-/* Standard BIOS video modes (BIOS number + 0x0100) */
+-#define VIDEO_FIRST_BIOS 0x0100
+-
+-/* VESA BIOS video modes (VESA number + 0x0200) */
+-#define VIDEO_FIRST_VESA 0x0200
+-
+-/* Video7 special modes (BIOS number + 0x0900) */
+-#define VIDEO_FIRST_V7 0x0900
+-
+-# Setting of user mode (AX=mode ID) => CF=success
+-
+-# For now, we only handle VESA modes (0x0200..0x03ff). To handle other
+-# modes, we should probably compile in the video code from the boot
+-# directory.
+-.code16
+-mode_set:
+- movw %ax, %bx
+- subb $VIDEO_FIRST_VESA>>8, %bh
+- cmpb $2, %bh
+- jb check_vesa
+-
+-setbad:
+- clc
+- ret
+-
+-check_vesa:
+- orw $0x4000, %bx # Use linear frame buffer
+- movw $0x4f02, %ax # VESA BIOS mode set call
+- int $0x10
+- cmpw $0x004f, %ax # AL=4f if implemented
+- jnz setbad # AH=0 if OK
+-
+- stc
+- ret
+-
+-wakeup_stack_begin: # Stack grows down
+-
+-.org 0xff0
+-wakeup_stack: # Just below end of page
+-
+-.org 0x1000
+-ENTRY(wakeup_level4_pgt)
+- .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
+- .fill 510,8,0
+- /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
+- .quad level3_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE
+-
+-ENTRY(wakeup_end)
+-
+-##
+-# acpi_copy_wakeup_routine
+-#
+-# Copy the above routine to low memory.
+-#
+-# Parameters:
+-# %rdi: place to copy wakeup routine to
+-#
+-# Returned address is location of code in low memory (past data and stack)
+-#
+- .code64
+-ENTRY(acpi_copy_wakeup_routine)
+- pushq %rax
+- pushq %rdx
+-
+- movl saved_video_mode, %edx
+- movl %edx, video_mode - wakeup_start (,%rdi)
+- movl acpi_realmode_flags, %edx
+- movl %edx, realmode_flags - wakeup_start (,%rdi)
+- movq $0x12345678, real_magic - wakeup_start (,%rdi)
+- movq $0x123456789abcdef0, %rdx
+- movq %rdx, saved_magic
+-
+- movq saved_magic, %rax
+- movq $0x123456789abcdef0, %rdx
+- cmpq %rdx, %rax
+- jne bogus_64_magic
+-
+- # restore the regs we used
+- popq %rdx
+- popq %rax
+-ENTRY(do_suspend_lowlevel_s4bios)
+- ret
++ jmp bogus_64_magic
+
+ .align 2
+ .p2align 4,,15
+@@ -414,7 +119,7 @@ do_suspend_lowlevel:
+ jmp restore_processor_state
+ .LFE5:
+ .Lfe5:
+- .size do_suspend_lowlevel,.Lfe5-do_suspend_lowlevel
++ .size do_suspend_lowlevel, .Lfe5-do_suspend_lowlevel
+
+ .data
+ ALIGN
+diff --git a/arch/x86/kernel/acpi/wakeup_rm.S b/arch/x86/kernel/acpi/wakeup_rm.S
+new file mode 100644
+index 0000000..6ff3b57
+--- /dev/null
++++ b/arch/x86/kernel/acpi/wakeup_rm.S
+@@ -0,0 +1,10 @@
++/*
++ * Wrapper script for the realmode binary as a transport object
++ * before copying to low memory.
++ */
++ .section ".rodata","a"
++ .globl wakeup_code_start, wakeup_code_end
++wakeup_code_start:
++ .incbin "arch/x86/kernel/acpi/realmode/wakeup.bin"
++wakeup_code_end:
++ .size wakeup_code_start, .-wakeup_code_start
+diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
+index 5fed98c..65c7857 100644
+--- a/arch/x86/kernel/alternative.c
++++ b/arch/x86/kernel/alternative.c
+@@ -11,6 +11,8 @@
+ #include <asm/mce.h>
+ #include <asm/nmi.h>
+ #include <asm/vsyscall.h>
++#include <asm/cacheflush.h>
++#include <asm/io.h>
+
+ #define MAX_PATCH_LEN (255-1)
+
+@@ -177,7 +179,7 @@ static const unsigned char*const * find_nop_table(void)
+ #endif /* CONFIG_X86_64 */
+
+ /* Use this to add nops to a buffer, then text_poke the whole buffer. */
+-static void add_nops(void *insns, unsigned int len)
++void add_nops(void *insns, unsigned int len)
+ {
+ const unsigned char *const *noptable = find_nop_table();
+
+@@ -190,6 +192,7 @@ static void add_nops(void *insns, unsigned int len)
+ len -= noplen;
+ }
+ }
++EXPORT_SYMBOL_GPL(add_nops);
+
+ extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
+ extern u8 *__smp_locks[], *__smp_locks_end[];
+@@ -205,7 +208,7 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
+ struct alt_instr *a;
+ char insnbuf[MAX_PATCH_LEN];
+
+- DPRINTK("%s: alt table %p -> %p\n", __FUNCTION__, start, end);
++ DPRINTK("%s: alt table %p -> %p\n", __func__, start, end);
+ for (a = start; a < end; a++) {
+ u8 *instr = a->instr;
+ BUG_ON(a->replacementlen > a->instrlen);
+@@ -217,13 +220,13 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
+ if (instr >= (u8 *)VSYSCALL_START && instr < (u8*)VSYSCALL_END) {
+ instr = __va(instr - (u8*)VSYSCALL_START + (u8*)__pa_symbol(&__vsyscall_0));
+ DPRINTK("%s: vsyscall fixup: %p => %p\n",
+- __FUNCTION__, a->instr, instr);
++ __func__, a->instr, instr);
+ }
+ #endif
+ memcpy(insnbuf, a->replacement, a->replacementlen);
+ add_nops(insnbuf + a->replacementlen,
+ a->instrlen - a->replacementlen);
+- text_poke(instr, insnbuf, a->instrlen);
++ text_poke_early(instr, insnbuf, a->instrlen);
+ }
+ }
+
+@@ -284,7 +287,6 @@ void alternatives_smp_module_add(struct module *mod, char *name,
+ void *text, void *text_end)
+ {
+ struct smp_alt_module *smp;
+- unsigned long flags;
+
+ if (noreplace_smp)
+ return;
+@@ -307,42 +309,40 @@ void alternatives_smp_module_add(struct module *mod, char *name,
+ smp->text = text;
+ smp->text_end = text_end;
+ DPRINTK("%s: locks %p -> %p, text %p -> %p, name %s\n",
+- __FUNCTION__, smp->locks, smp->locks_end,
++ __func__, smp->locks, smp->locks_end,
+ smp->text, smp->text_end, smp->name);
+
+- spin_lock_irqsave(&smp_alt, flags);
++ spin_lock(&smp_alt);
+ list_add_tail(&smp->next, &smp_alt_modules);
+ if (boot_cpu_has(X86_FEATURE_UP))
+ alternatives_smp_unlock(smp->locks, smp->locks_end,
+ smp->text, smp->text_end);
+- spin_unlock_irqrestore(&smp_alt, flags);
++ spin_unlock(&smp_alt);
+ }
+
+ void alternatives_smp_module_del(struct module *mod)
+ {
+ struct smp_alt_module *item;
+- unsigned long flags;
+
+ if (smp_alt_once || noreplace_smp)
+ return;
+
+- spin_lock_irqsave(&smp_alt, flags);
++ spin_lock(&smp_alt);
+ list_for_each_entry(item, &smp_alt_modules, next) {
+ if (mod != item->mod)
+ continue;
+ list_del(&item->next);
+- spin_unlock_irqrestore(&smp_alt, flags);
+- DPRINTK("%s: %s\n", __FUNCTION__, item->name);
++ spin_unlock(&smp_alt);
++ DPRINTK("%s: %s\n", __func__, item->name);
+ kfree(item);
+ return;
+ }
+- spin_unlock_irqrestore(&smp_alt, flags);
++ spin_unlock(&smp_alt);
+ }
+
+ void alternatives_smp_switch(int smp)
+ {
+ struct smp_alt_module *mod;
+- unsigned long flags;
+
+ #ifdef CONFIG_LOCKDEP
+ /*
+@@ -359,7 +359,7 @@ void alternatives_smp_switch(int smp)
+ return;
+ BUG_ON(!smp && (num_online_cpus() > 1));
+
+- spin_lock_irqsave(&smp_alt, flags);
++ spin_lock(&smp_alt);
+
+ /*
+ * Avoid unnecessary switches because it forces JIT based VMs to
+@@ -383,7 +383,7 @@ void alternatives_smp_switch(int smp)
+ mod->text, mod->text_end);
+ }
+ smp_mode = smp;
+- spin_unlock_irqrestore(&smp_alt, flags);
++ spin_unlock(&smp_alt);
+ }
+
+ #endif
+@@ -411,7 +411,7 @@ void apply_paravirt(struct paravirt_patch_site *start,
+
+ /* Pad the rest with nops */
+ add_nops(insnbuf + used, p->len - used);
+- text_poke(p->instr, insnbuf, p->len);
++ text_poke_early(p->instr, insnbuf, p->len);
+ }
+ }
+ extern struct paravirt_patch_site __start_parainstructions[],
+@@ -420,8 +420,6 @@ extern struct paravirt_patch_site __start_parainstructions[],
+
+ void __init alternative_instructions(void)
+ {
+- unsigned long flags;
+-
+ /* The patching is not fully atomic, so try to avoid local interruptions
+ that might execute the to be patched code.
+ Other CPUs are not running. */
+@@ -430,7 +428,6 @@ void __init alternative_instructions(void)
+ stop_mce();
+ #endif
+
+- local_irq_save(flags);
+ apply_alternatives(__alt_instructions, __alt_instructions_end);
+
+ /* switch to patch-once-at-boottime-only mode and free the
+@@ -462,7 +459,6 @@ void __init alternative_instructions(void)
+ }
+ #endif
+ apply_paravirt(__parainstructions, __parainstructions_end);
+- local_irq_restore(flags);
+
+ if (smp_alt_once)
+ free_init_pages("SMP alternatives",
+@@ -475,18 +471,70 @@ void __init alternative_instructions(void)
+ #endif
+ }
+
+-/*
+- * Warning:
++/**
++ * text_poke_early - Update instructions on a live kernel at boot time
++ * @addr: address to modify
++ * @opcode: source of the copy
++ * @len: length to copy
++ *
+ * When you use this code to patch more than one byte of an instruction
+ * you need to make sure that other CPUs cannot execute this code in parallel.
+- * Also no thread must be currently preempted in the middle of these instructions.
+- * And on the local CPU you need to be protected again NMI or MCE handlers
+- * seeing an inconsistent instruction while you patch.
++ * Also no thread must be currently preempted in the middle of these
++ * instructions. And on the local CPU you need to be protected again NMI or MCE
++ * handlers seeing an inconsistent instruction while you patch.
+ */
+-void __kprobes text_poke(void *addr, unsigned char *opcode, int len)
++void *text_poke_early(void *addr, const void *opcode, size_t len)
+ {
++ unsigned long flags;
++ local_irq_save(flags);
+ memcpy(addr, opcode, len);
++ local_irq_restore(flags);
++ sync_core();
++ /* Could also do a CLFLUSH here to speed up CPU recovery; but
++ that causes hangs on some VIA CPUs. */
++ return addr;
++}
++
++/**
++ * text_poke - Update instructions on a live kernel
++ * @addr: address to modify
++ * @opcode: source of the copy
++ * @len: length to copy
++ *
++ * Only atomic text poke/set should be allowed when not doing early patching.
++ * It means the size must be writable atomically and the address must be aligned
++ * in a way that permits an atomic write. It also makes sure we fit on a single
++ * page.
++ */
++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;
++
++ if (!core_kernel_text((unsigned long)addr)) {
++ pages[0] = vmalloc_to_page(addr);
++ pages[1] = vmalloc_to_page(addr + PAGE_SIZE);
++ } else {
++ pages[0] = virt_to_page(addr);
++ WARN_ON(!PageReserved(pages[0]));
++ pages[1] = virt_to_page(addr + PAGE_SIZE);
++ }
++ BUG_ON(!pages[0]);
++ if (!pages[1])
++ nr_pages = 1;
++ vaddr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL);
++ BUG_ON(!vaddr);
++ local_irq_save(flags);
++ memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len);
++ local_irq_restore(flags);
++ vunmap(vaddr);
+ sync_core();
+ /* Could also do a CLFLUSH here to speed up CPU recovery; but
+ that causes hangs on some VIA CPUs. */
++ for (i = 0; i < len; i++)
++ BUG_ON(((char *)addr)[i] != ((char *)opcode)[i]);
++ return addr;
+ }
+diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c
+index 00df126..479926d 100644
+--- a/arch/x86/kernel/aperture_64.c
++++ b/arch/x86/kernel/aperture_64.c
+@@ -27,11 +27,11 @@
+ #include <asm/k8.h>
+
+ int gart_iommu_aperture;
+-int gart_iommu_aperture_disabled __initdata = 0;
+-int gart_iommu_aperture_allowed __initdata = 0;
++int gart_iommu_aperture_disabled __initdata;
++int gart_iommu_aperture_allowed __initdata;
+
+ int fallback_aper_order __initdata = 1; /* 64MB */
+-int fallback_aper_force __initdata = 0;
++int fallback_aper_force __initdata;
+
+ int fix_aperture __initdata = 1;
+
+diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c
+index 35a568e..4b99b1b 100644
+--- a/arch/x86/kernel/apic_32.c
++++ b/arch/x86/kernel/apic_32.c
+@@ -50,6 +50,11 @@
+ # error SPURIOUS_APIC_VECTOR definition error
+ #endif
+
++unsigned long mp_lapic_addr;
++
++DEFINE_PER_CPU(u16, x86_bios_cpu_apicid) = BAD_APICID;
++EXPORT_PER_CPU_SYMBOL(x86_bios_cpu_apicid);
++
+ /*
+ * Knob to control our willingness to enable the local APIC.
+ *
+@@ -446,7 +451,8 @@ void __init setup_boot_APIC_clock(void)
+ }
+
+ /* Calculate the scaled math multiplication factor */
+- lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS, 32);
++ lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS,
++ lapic_clockevent.shift);
+ lapic_clockevent.max_delta_ns =
+ clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
+ lapic_clockevent.min_delta_ns =
+@@ -621,6 +627,35 @@ int setup_profiling_timer(unsigned int multiplier)
+ }
+
+ /*
++ * Setup extended LVT, AMD specific (K8, family 10h)
++ *
++ * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and
++ * MCE interrupts are supported. Thus MCE offset must be set to 0.
++ */
++
++#define APIC_EILVT_LVTOFF_MCE 0
++#define APIC_EILVT_LVTOFF_IBS 1
++
++static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask)
++{
++ unsigned long reg = (lvt_off << 4) + APIC_EILVT0;
++ unsigned int v = (mask << 16) | (msg_type << 8) | vector;
++ apic_write(reg, v);
++}
++
++u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask)
++{
++ setup_APIC_eilvt(APIC_EILVT_LVTOFF_MCE, vector, msg_type, mask);
++ return APIC_EILVT_LVTOFF_MCE;
++}
++
++u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask)
++{
++ setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask);
++ return APIC_EILVT_LVTOFF_IBS;
++}
++
++/*
+ * Local APIC start and shutdown
+ */
+
+@@ -868,12 +903,50 @@ void __init init_bsp_APIC(void)
+ apic_write_around(APIC_LVT1, value);
+ }
+
++static void __cpuinit lapic_setup_esr(void)
++{
++ unsigned long oldvalue, value, maxlvt;
++ if (lapic_is_integrated() && !esr_disable) {
++ /* !82489DX */
++ maxlvt = lapic_get_maxlvt();
++ if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
++ apic_write(APIC_ESR, 0);
++ oldvalue = apic_read(APIC_ESR);
++
++ /* enables sending errors */
++ value = ERROR_APIC_VECTOR;
++ apic_write_around(APIC_LVTERR, value);
++ /*
++ * spec says clear errors after enabling vector.
++ */
++ if (maxlvt > 3)
++ apic_write(APIC_ESR, 0);
++ value = apic_read(APIC_ESR);
++ if (value != oldvalue)
++ apic_printk(APIC_VERBOSE, "ESR value before enabling "
++ "vector: 0x%08lx after: 0x%08lx\n",
++ oldvalue, value);
++ } else {
++ if (esr_disable)
++ /*
++ * Something untraceable is creating bad interrupts on
++ * secondary quads ... for the moment, just leave the
++ * ESR disabled - we can't do anything useful with the
++ * errors anyway - mbligh
++ */
++ printk(KERN_INFO "Leaving ESR disabled.\n");
++ else
++ printk(KERN_INFO "No ESR for 82489DX.\n");
++ }
++}
++
++
+ /**
+ * setup_local_APIC - setup the local APIC
+ */
+ void __cpuinit setup_local_APIC(void)
+ {
+- unsigned long oldvalue, value, maxlvt, integrated;
++ unsigned long value, integrated;
+ int i, j;
+
+ /* Pound the ESR really hard over the head with a big hammer - mbligh */
+@@ -997,40 +1070,13 @@ void __cpuinit setup_local_APIC(void)
+ if (!integrated) /* 82489DX */
+ value |= APIC_LVT_LEVEL_TRIGGER;
+ apic_write_around(APIC_LVT1, value);
++}
+
+- if (integrated && !esr_disable) {
+- /* !82489DX */
+- maxlvt = lapic_get_maxlvt();
+- if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
+- apic_write(APIC_ESR, 0);
+- oldvalue = apic_read(APIC_ESR);
+-
+- /* enables sending errors */
+- value = ERROR_APIC_VECTOR;
+- apic_write_around(APIC_LVTERR, value);
+- /*
+- * spec says clear errors after enabling vector.
+- */
+- if (maxlvt > 3)
+- apic_write(APIC_ESR, 0);
+- value = apic_read(APIC_ESR);
+- if (value != oldvalue)
+- apic_printk(APIC_VERBOSE, "ESR value before enabling "
+- "vector: 0x%08lx after: 0x%08lx\n",
+- oldvalue, value);
+- } else {
+- if (esr_disable)
+- /*
+- * Something untraceable is creating bad interrupts on
+- * secondary quads ... for the moment, just leave the
+- * ESR disabled - we can't do anything useful with the
+- * errors anyway - mbligh
+- */
+- printk(KERN_INFO "Leaving ESR disabled.\n");
+- else
+- printk(KERN_INFO "No ESR for 82489DX.\n");
+- }
++void __cpuinit end_local_APIC_setup(void)
++{
++ unsigned long value;
+
++ lapic_setup_esr();
+ /* Disable the local apic timer */
+ value = apic_read(APIC_LVTT);
+ value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
+@@ -1147,7 +1193,7 @@ void __init init_apic_mappings(void)
+ * default configuration (or the MP table is broken).
+ */
+ if (boot_cpu_physical_apicid == -1U)
+- boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
++ boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
+
+ #ifdef CONFIG_X86_IO_APIC
+ {
+@@ -1185,6 +1231,9 @@ fake_ioapic_page:
+ * This initializes the IO-APIC and APIC hardware if this is
+ * a UP kernel.
+ */
++
++int apic_version[MAX_APICS];
++
+ int __init APIC_init_uniprocessor(void)
+ {
+ if (enable_local_apic < 0)
+@@ -1214,12 +1263,13 @@ int __init APIC_init_uniprocessor(void)
+ * might be zero if read from MP tables. Get it from LAPIC.
+ */
+ #ifdef CONFIG_CRASH_DUMP
+- boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
++ boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
+ #endif
+ phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
+
+ setup_local_APIC();
+
++ end_local_APIC_setup();
+ #ifdef CONFIG_X86_IO_APIC
+ if (smp_found_config)
+ if (!skip_ioapic_setup && nr_ioapics)
+@@ -1288,6 +1338,29 @@ void smp_error_interrupt(struct pt_regs *regs)
+ irq_exit();
+ }
+
++#ifdef CONFIG_SMP
++void __init smp_intr_init(void)
++{
++ /*
++ * IRQ0 must be given a fixed assignment and initialized,
++ * because it's used before the IO-APIC is set up.
++ */
++ set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]);
++
++ /*
++ * The reschedule interrupt is a CPU-to-CPU reschedule-helper
++ * IPI, driven by wakeup.
++ */
++ set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
++
++ /* IPI for invalidation */
++ set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
++
++ /* IPI for generic function call */
++ set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
++}
++#endif
++
+ /*
+ * Initialize APIC interrupts
+ */
+@@ -1394,6 +1467,88 @@ void disconnect_bsp_APIC(int virt_wire_setup)
+ }
+ }
+
++unsigned int __cpuinitdata maxcpus = NR_CPUS;
++
++void __cpuinit generic_processor_info(int apicid, int version)
++{
++ int cpu;
++ cpumask_t tmp_map;
++ physid_mask_t phys_cpu;
++
++ /*
++ * Validate version
++ */
++ if (version == 0x0) {
++ printk(KERN_WARNING "BIOS bug, APIC version is 0 for CPU#%d! "
++ "fixing up to 0x10. (tell your hw vendor)\n",
++ version);
++ version = 0x10;
++ }
++ apic_version[apicid] = version;
++
++ phys_cpu = apicid_to_cpu_present(apicid);
++ physids_or(phys_cpu_present_map, phys_cpu_present_map, phys_cpu);
++
++ if (num_processors >= NR_CPUS) {
++ printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
++ " Processor ignored.\n", NR_CPUS);
++ return;
++ }
++
++ if (num_processors >= maxcpus) {
++ printk(KERN_WARNING "WARNING: maxcpus limit of %i reached."
++ " Processor ignored.\n", maxcpus);
++ return;
++ }
++
++ num_processors++;
++ cpus_complement(tmp_map, cpu_present_map);
++ cpu = first_cpu(tmp_map);
++
++ if (apicid == boot_cpu_physical_apicid)
++ /*
++ * x86_bios_cpu_apicid is required to have processors listed
++ * in same order as logical cpu numbers. Hence the first
++ * entry is BSP, and so on.
++ */
++ cpu = 0;
++
++ /*
++ * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y
++ * but we need to work other dependencies like SMP_SUSPEND etc
++ * before this can be done without some confusion.
++ * if (CPU_HOTPLUG_ENABLED || num_processors > 8)
++ * - Ashok Raj <ashok.raj at intel.com>
++ */
++ if (num_processors > 8) {
++ switch (boot_cpu_data.x86_vendor) {
++ case X86_VENDOR_INTEL:
++ if (!APIC_XAPIC(version)) {
++ def_to_bigsmp = 0;
++ break;
++ }
++ /* If P4 and above fall through */
++ case X86_VENDOR_AMD:
++ def_to_bigsmp = 1;
++ }
++ }
++#ifdef CONFIG_SMP
++ /* are we being called early in kernel startup? */
++ if (x86_cpu_to_apicid_early_ptr) {
++ u16 *cpu_to_apicid = x86_cpu_to_apicid_early_ptr;
++ u16 *bios_cpu_apicid = x86_bios_cpu_apicid_early_ptr;
++
++ cpu_to_apicid[cpu] = apicid;
++ bios_cpu_apicid[cpu] = apicid;
++ } else {
++ per_cpu(x86_cpu_to_apicid, cpu) = apicid;
++ per_cpu(x86_bios_cpu_apicid, cpu) = apicid;
++ }
++#endif
++ cpu_set(cpu, cpu_possible_map);
++ cpu_set(cpu, cpu_present_map);
++}
++
+ /*
+ * Power management
+ */
+diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c
+index d8d03e0..5910020 100644
+--- a/arch/x86/kernel/apic_64.c
++++ b/arch/x86/kernel/apic_64.c
+@@ -34,13 +34,15 @@
+ #include <asm/mpspec.h>
+ #include <asm/hpet.h>
+ #include <asm/pgalloc.h>
+-#include <asm/mach_apic.h>
+ #include <asm/nmi.h>
+ #include <asm/idle.h>
+ #include <asm/proto.h>
+ #include <asm/timex.h>
+ #include <asm/apic.h>
+
++#include <mach_ipi.h>
++#include <mach_apic.h>
++
+ int disable_apic_timer __cpuinitdata;
+ static int apic_calibrate_pmtmr __initdata;
+ int disable_apic;
+@@ -83,6 +85,12 @@ static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
+
+ static unsigned long apic_phys;
+
++unsigned long mp_lapic_addr;
++
++DEFINE_PER_CPU(u16, x86_bios_cpu_apicid) = BAD_APICID;
++EXPORT_PER_CPU_SYMBOL(x86_bios_cpu_apicid);
++
++unsigned int __cpuinitdata maxcpus = NR_CPUS;
+ /*
+ * Get the LAPIC version
+ */
+@@ -352,7 +360,8 @@ static void __init calibrate_APIC_clock(void)
+ result / 1000 / 1000, result / 1000 % 1000);
+
+ /* Calculate the scaled math multiplication factor */
+- lapic_clockevent.mult = div_sc(result, NSEC_PER_SEC, 32);
++ lapic_clockevent.mult = div_sc(result, NSEC_PER_SEC,
++ lapic_clockevent.shift);
+ lapic_clockevent.max_delta_ns =
+ clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
+ lapic_clockevent.min_delta_ns =
+@@ -421,7 +430,7 @@ void __init setup_boot_APIC_clock(void)
+ * set the DUMMY flag again and force the broadcast mode in the
+ * clockevents layer.
+ */
+-void __cpuinit check_boot_apic_timer_broadcast(void)
++static void __cpuinit check_boot_apic_timer_broadcast(void)
+ {
+ if (!disable_apic_timer ||
+ (lapic_clockevent.features & CLOCK_EVT_FEAT_DUMMY))
+@@ -431,7 +440,8 @@ void __cpuinit check_boot_apic_timer_broadcast(void)
+ lapic_clockevent.features |= CLOCK_EVT_FEAT_DUMMY;
+
+ local_irq_enable();
+- clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE, &boot_cpu_id);
++ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
++ &boot_cpu_physical_apicid);
+ local_irq_disable();
+ }
+
+@@ -640,10 +650,10 @@ int __init verify_local_APIC(void)
+ /*
+ * The ID register is read/write in a real APIC.
+ */
+- reg0 = apic_read(APIC_ID);
++ reg0 = read_apic_id();
+ apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0);
+ apic_write(APIC_ID, reg0 ^ APIC_ID_MASK);
+- reg1 = apic_read(APIC_ID);
++ reg1 = read_apic_id();
+ apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg1);
+ apic_write(APIC_ID, reg0);
+ if (reg1 != (reg0 ^ APIC_ID_MASK))
+@@ -728,6 +738,7 @@ void __cpuinit setup_local_APIC(void)
+ unsigned int value;
+ int i, j;
+
++ preempt_disable();
+ value = apic_read(APIC_LVR);
+
+ BUILD_BUG_ON((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f);
+@@ -821,9 +832,10 @@ void __cpuinit setup_local_APIC(void)
+ else
+ value = APIC_DM_NMI | APIC_LVT_MASKED;
+ apic_write(APIC_LVT1, value);
++ preempt_enable();
+ }
+
+-void __cpuinit lapic_setup_esr(void)
++static void __cpuinit lapic_setup_esr(void)
+ {
+ unsigned maxlvt = lapic_get_maxlvt();
+
+@@ -857,10 +869,34 @@ static int __init detect_init_APIC(void)
+ }
+
+ mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
+- boot_cpu_id = 0;
++ boot_cpu_physical_apicid = 0;
+ return 0;
+ }
+
++void __init early_init_lapic_mapping(void)
++{
++ unsigned long apic_phys;
++
++ /*
++ * If no local APIC can be found then go out
++ * : it means there is no mpatable and MADT
++ */
++ if (!smp_found_config)
++ return;
++
++ apic_phys = mp_lapic_addr;
++
++ set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
++ apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
++ APIC_BASE, apic_phys);
++
++ /*
++ * Fetch the APIC ID of the BSP in case we have a
++ * default configuration (or the MP table is broken).
++ */
++ boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
++}
++
+ /**
+ * init_apic_mappings - initialize APIC mappings
+ */
+@@ -881,16 +917,11 @@ void __init init_apic_mappings(void)
+ apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
+ APIC_BASE, apic_phys);
+
+- /* Put local APIC into the resource map. */
+- lapic_resource.start = apic_phys;
+- lapic_resource.end = lapic_resource.start + PAGE_SIZE - 1;
+- insert_resource(&iomem_resource, &lapic_resource);
+-
+ /*
+ * Fetch the APIC ID of the BSP in case we have a
+ * default configuration (or the MP table is broken).
+ */
+- boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID));
++ boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
+ }
+
+ /*
+@@ -911,8 +942,8 @@ int __init APIC_init_uniprocessor(void)
+
+ verify_local_APIC();
+
+- phys_cpu_present_map = physid_mask_of_physid(boot_cpu_id);
+- apic_write(APIC_ID, SET_APIC_ID(boot_cpu_id));
++ phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
++ apic_write(APIC_ID, SET_APIC_ID(boot_cpu_physical_apicid));
+
+ setup_local_APIC();
+
+@@ -1029,6 +1060,52 @@ void disconnect_bsp_APIC(int virt_wire_setup)
+ apic_write(APIC_LVT1, value);
+ }
+
++void __cpuinit generic_processor_info(int apicid, int version)
++{
++ int cpu;
++ cpumask_t tmp_map;
++
++ if (num_processors >= NR_CPUS) {
++ printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
++ " Processor ignored.\n", NR_CPUS);
++ return;
++ }
++
++ if (num_processors >= maxcpus) {
++ printk(KERN_WARNING "WARNING: maxcpus limit of %i reached."
++ " Processor ignored.\n", maxcpus);
++ return;
++ }
++
++ num_processors++;
++ cpus_complement(tmp_map, cpu_present_map);
++ cpu = first_cpu(tmp_map);
++
++ physid_set(apicid, phys_cpu_present_map);
++ if (apicid == boot_cpu_physical_apicid) {
++ /*
++ * x86_bios_cpu_apicid is required to have processors listed
++ * in same order as logical cpu numbers. Hence the first
++ * entry is BSP, and so on.
++ */
++ cpu = 0;
++ }
++ /* are we being called early in kernel startup? */
++ if (x86_cpu_to_apicid_early_ptr) {
++ u16 *cpu_to_apicid = x86_cpu_to_apicid_early_ptr;
++ u16 *bios_cpu_apicid = x86_bios_cpu_apicid_early_ptr;
++
++ cpu_to_apicid[cpu] = apicid;
++ bios_cpu_apicid[cpu] = apicid;
++ } else {
++ per_cpu(x86_cpu_to_apicid, cpu) = apicid;
++ per_cpu(x86_bios_cpu_apicid, cpu) = apicid;
++ }
++
++ cpu_set(cpu, cpu_possible_map);
++ cpu_set(cpu, cpu_present_map);
++}
++
+ /*
+ * Power management
+ */
+@@ -1065,7 +1142,7 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state)
+
+ maxlvt = lapic_get_maxlvt();
+
+- apic_pm_state.apic_id = apic_read(APIC_ID);
++ apic_pm_state.apic_id = read_apic_id();
+ apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI);
+ apic_pm_state.apic_ldr = apic_read(APIC_LDR);
+ apic_pm_state.apic_dfr = apic_read(APIC_DFR);
+@@ -1180,9 +1257,19 @@ __cpuinit int apic_is_clustered_box(void)
+ {
+ int i, clusters, zeros;
+ unsigned id;
+- u16 *bios_cpu_apicid = x86_bios_cpu_apicid_early_ptr;
++ u16 *bios_cpu_apicid;
+ DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS);
+
++ /*
++ * there is not this kind of box with AMD CPU yet.
++ * Some AMD box with quadcore cpu and 8 sockets apicid
++ * will be [4, 0x23] or [8, 0x27] could be thought to
++ * vsmp box still need checking...
++ */
++ if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && !is_vsmp_box())
++ return 0;
++
++ bios_cpu_apicid = x86_bios_cpu_apicid_early_ptr;
+ bitmap_zero(clustermap, NUM_APIC_CLUSTERS);
+
+ for (i = 0; i < NR_CPUS; i++) {
+@@ -1219,6 +1306,12 @@ __cpuinit int apic_is_clustered_box(void)
+ ++zeros;
+ }
+
++ /* ScaleMP vSMPowered boxes have one cluster per board and TSCs are
++ * not guaranteed to be synced between boards
++ */
++ if (is_vsmp_box() && clusters > 1)
++ return 1;
++
+ /*
+ * If clusters > 2, then should be multi-chassis.
+ * May have to revisit this when multi-core + hyperthreaded CPUs come
+@@ -1290,3 +1383,21 @@ static __init int setup_apicpmtimer(char *s)
+ }
+ __setup("apicpmtimer", setup_apicpmtimer);
+
++static int __init lapic_insert_resource(void)
++{
++ if (!apic_phys)
++ return -1;
++
++ /* Put local APIC into the resource map. */
++ lapic_resource.start = apic_phys;
++ lapic_resource.end = lapic_resource.start + PAGE_SIZE - 1;
++ insert_resource(&iomem_resource, &lapic_resource);
++
++ return 0;
++}
++
++/*
++ * need call insert after e820_reserve_resources()
++ * that is using request_resource
++ */
++late_initcall(lapic_insert_resource);
+diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
+index d4438ef..f0030a0 100644
+--- a/arch/x86/kernel/apm_32.c
++++ b/arch/x86/kernel/apm_32.c
+@@ -2217,7 +2217,6 @@ static struct dmi_system_id __initdata apm_dmi_table[] = {
+ */
+ static int __init apm_init(void)
+ {
+- struct proc_dir_entry *apm_proc;
+ struct desc_struct *gdt;
+ int err;
+
+@@ -2322,9 +2321,7 @@ static int __init apm_init(void)
+ set_base(gdt[APM_DS >> 3],
+ __va((unsigned long)apm_info.bios.dseg << 4));
+
+- apm_proc = create_proc_entry("apm", 0, NULL);
+- if (apm_proc)
+- apm_proc->proc_fops = &apm_file_ops;
++ proc_create("apm", 0, NULL, &apm_file_ops);
+
+ kapmd_task = kthread_create(apm, NULL, "kapmd");
+ if (IS_ERR(kapmd_task)) {
+diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c
+index 8ea0401..670c3c3 100644
+--- a/arch/x86/kernel/asm-offsets_32.c
++++ b/arch/x86/kernel/asm-offsets_32.c
+@@ -10,7 +10,7 @@
+ #include <linux/personality.h>
+ #include <linux/suspend.h>
+ #include <asm/ucontext.h>
+-#include "sigframe_32.h"
++#include "sigframe.h"
+ #include <asm/pgtable.h>
+ #include <asm/fixmap.h>
+ #include <asm/processor.h>
+diff --git a/arch/x86/kernel/bugs_64.c b/arch/x86/kernel/bugs_64.c
+index 8f520f9..9a3ed06 100644
+--- a/arch/x86/kernel/bugs_64.c
++++ b/arch/x86/kernel/bugs_64.c
+@@ -9,13 +9,25 @@
+ #include <asm/bugs.h>
+ #include <asm/processor.h>
+ #include <asm/mtrr.h>
++#include <asm/cacheflush.h>
+
+ void __init check_bugs(void)
+ {
+- identify_cpu(&boot_cpu_data);
++ identify_boot_cpu();
+ #if !defined(CONFIG_SMP)
+ printk("CPU: ");
+ print_cpu_info(&boot_cpu_data);
+ #endif
+ alternative_instructions();
++
++ /*
++ * Make sure the first 2MB area is not mapped by huge pages
++ * There are typically fixed size MTRRs in there and overlapping
++ * MTRRs into large pages causes slow downs.
++ *
++ * Right now we don't do that with gbpages because there seems
++ * very little benefit for that case.
++ */
++ if (!direct_gbpages)
++ set_memory_4k((unsigned long)__va(0), 1);
+ }
+diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
+index a0c4d7c..a0c6f81 100644
+--- a/arch/x86/kernel/cpu/Makefile
++++ b/arch/x86/kernel/cpu/Makefile
+@@ -3,15 +3,14 @@
+ #
+
+ obj-y := intel_cacheinfo.o addon_cpuid_features.o
+-obj-y += feature_names.o
++obj-y += proc.o feature_names.o
+
+-obj-$(CONFIG_X86_32) += common.o proc.o bugs.o
++obj-$(CONFIG_X86_32) += common.o bugs.o
+ obj-$(CONFIG_X86_32) += amd.o
+ obj-$(CONFIG_X86_32) += cyrix.o
+ obj-$(CONFIG_X86_32) += centaur.o
+ obj-$(CONFIG_X86_32) += transmeta.o
+ obj-$(CONFIG_X86_32) += intel.o
+-obj-$(CONFIG_X86_32) += nexgen.o
+ obj-$(CONFIG_X86_32) += umc.o
+
+ obj-$(CONFIG_X86_MCE) += mcheck/
+diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
+index 693e353..2458668 100644
+--- a/arch/x86/kernel/cpu/amd.c
++++ b/arch/x86/kernel/cpu/amd.c
+@@ -4,8 +4,8 @@
+ #include <asm/io.h>
+ #include <asm/processor.h>
+ #include <asm/apic.h>
+-#include <asm/mach_apic.h>
+
++#include <mach_apic.h>
+ #include "cpu.h"
+
+ /*
+@@ -20,7 +20,7 @@
+ * the chip setting when fixing the bug but they also tweaked some
+ * performance at the same time..
+ */
+-
++
+ extern void vide(void);
+ __asm__(".align 4\nvide: ret");
+
+@@ -63,12 +63,12 @@ static __cpuinit int amd_apic_timer_broken(void)
+
+ int force_mwait __cpuinitdata;
+
+-void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
++static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
+ {
+ if (cpuid_eax(0x80000000) >= 0x80000007) {
+ c->x86_power = cpuid_edx(0x80000007);
+ if (c->x86_power & (1<<8))
+- set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability);
++ set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
+ }
+ }
+
+@@ -81,7 +81,8 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ #ifdef CONFIG_SMP
+ unsigned long long value;
+
+- /* Disable TLB flush filter by setting HWCR.FFDIS on K8
++ /*
++ * Disable TLB flush filter by setting HWCR.FFDIS on K8
+ * bit 6 of msr C001_0015
+ *
+ * Errata 63 for SH-B3 steppings
+@@ -102,15 +103,16 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ * no bus pipeline)
+ */
+
+- /* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
+- 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
+- clear_bit(0*32+31, c->x86_capability);
+-
++ /*
++ * Bit 31 in normal CPUID used for nonstandard 3DNow ID;
++ * 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway
++ */
++ clear_cpu_cap(c, 0*32+31);
++
+ r = get_model_name(c);
+
+- switch(c->x86)
+- {
+- case 4:
++ switch (c->x86) {
++ case 4:
+ /*
+ * General Systems BIOSen alias the cpu frequency registers
+ * of the Elan at 0x000df000. Unfortuantly, one of the Linux
+@@ -120,61 +122,60 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ #define CBAR (0xfffc) /* Configuration Base Address (32-bit) */
+ #define CBAR_ENB (0x80000000)
+ #define CBAR_KEY (0X000000CB)
+- if (c->x86_model==9 || c->x86_model == 10) {
++ if (c->x86_model == 9 || c->x86_model == 10) {
+ if (inl (CBAR) & CBAR_ENB)
+ outl (0 | CBAR_KEY, CBAR);
+ }
+ break;
+- case 5:
+- if( c->x86_model < 6 )
+- {
++ case 5:
++ if (c->x86_model < 6) {
+ /* Based on AMD doc 20734R - June 2000 */
+- if ( c->x86_model == 0 ) {
+- clear_bit(X86_FEATURE_APIC, c->x86_capability);
+- set_bit(X86_FEATURE_PGE, c->x86_capability);
++ if (c->x86_model == 0) {
++ clear_cpu_cap(c, X86_FEATURE_APIC);
++ set_cpu_cap(c, X86_FEATURE_PGE);
+ }
+ break;
+ }
+-
+- if ( c->x86_model == 6 && c->x86_mask == 1 ) {
++
++ if (c->x86_model == 6 && c->x86_mask == 1) {
+ const int K6_BUG_LOOP = 1000000;
+ int n;
+ void (*f_vide)(void);
+ unsigned long d, d2;
+-
++
+ printk(KERN_INFO "AMD K6 stepping B detected - ");
+-
++
+ /*
+- * It looks like AMD fixed the 2.6.2 bug and improved indirect
++ * It looks like AMD fixed the 2.6.2 bug and improved indirect
+ * calls at the same time.
+ */
+
+ n = K6_BUG_LOOP;
+ f_vide = vide;
+ rdtscl(d);
+- while (n--)
++ while (n--)
+ f_vide();
+ rdtscl(d2);
+ d = d2-d;
+
+- if (d > 20*K6_BUG_LOOP)
++ if (d > 20*K6_BUG_LOOP)
+ printk("system stability may be impaired when more than 32 MB are used.\n");
+- else
++ else
+ printk("probably OK (after B9730xxxx).\n");
+ printk(KERN_INFO "Please see http://membres.lycos.fr/poulot/k6bug.html\n");
+ }
+
+ /* K6 with old style WHCR */
+ if (c->x86_model < 8 ||
+- (c->x86_model== 8 && c->x86_mask < 8)) {
++ (c->x86_model == 8 && c->x86_mask < 8)) {
+ /* We can only write allocate on the low 508Mb */
+- if(mbytes>508)
+- mbytes=508;
++ if (mbytes > 508)
++ mbytes = 508;
+
+ rdmsr(MSR_K6_WHCR, l, h);
+- if ((l&0x0000FFFF)==0) {
++ if ((l&0x0000FFFF) == 0) {
+ unsigned long flags;
+- l=(1<<0)|((mbytes/4)<<1);
++ l = (1<<0)|((mbytes/4)<<1);
+ local_irq_save(flags);
+ wbinvd();
+ wrmsr(MSR_K6_WHCR, l, h);
+@@ -185,17 +186,17 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ break;
+ }
+
+- if ((c->x86_model == 8 && c->x86_mask >7) ||
++ if ((c->x86_model == 8 && c->x86_mask > 7) ||
+ c->x86_model == 9 || c->x86_model == 13) {
+ /* The more serious chips .. */
+
+- if(mbytes>4092)
+- mbytes=4092;
++ if (mbytes > 4092)
++ mbytes = 4092;
+
+ rdmsr(MSR_K6_WHCR, l, h);
+- if ((l&0xFFFF0000)==0) {
++ if ((l&0xFFFF0000) == 0) {
+ unsigned long flags;
+- l=((mbytes>>2)<<22)|(1<<16);
++ l = ((mbytes>>2)<<22)|(1<<16);
+ local_irq_save(flags);
+ wbinvd();
+ wrmsr(MSR_K6_WHCR, l, h);
+@@ -207,7 +208,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ /* Set MTRR capability flag if appropriate */
+ if (c->x86_model == 13 || c->x86_model == 9 ||
+ (c->x86_model == 8 && c->x86_mask >= 8))
+- set_bit(X86_FEATURE_K6_MTRR, c->x86_capability);
++ set_cpu_cap(c, X86_FEATURE_K6_MTRR);
+ break;
+ }
+
+@@ -217,10 +218,11 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ break;
+ }
+ break;
+- case 6: /* An Athlon/Duron */
+-
+- /* Bit 15 of Athlon specific MSR 15, needs to be 0
+- * to enable SSE on Palomino/Morgan/Barton CPU's.
++ case 6: /* An Athlon/Duron */
++
++ /*
++ * Bit 15 of Athlon specific MSR 15, needs to be 0
++ * to enable SSE on Palomino/Morgan/Barton CPU's.
+ * If the BIOS didn't enable it already, enable it here.
+ */
+ if (c->x86_model >= 6 && c->x86_model <= 10) {
+@@ -229,15 +231,16 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ rdmsr(MSR_K7_HWCR, l, h);
+ l &= ~0x00008000;
+ wrmsr(MSR_K7_HWCR, l, h);
+- set_bit(X86_FEATURE_XMM, c->x86_capability);
++ set_cpu_cap(c, X86_FEATURE_XMM);
+ }
+ }
+
+- /* It's been determined by AMD that Athlons since model 8 stepping 1
++ /*
++ * It's been determined by AMD that Athlons since model 8 stepping 1
+ * are more robust with CLK_CTL set to 200xxxxx instead of 600xxxxx
+ * As per AMD technical note 27212 0.2
+ */
+- if ((c->x86_model == 8 && c->x86_mask>=1) || (c->x86_model > 8)) {
++ if ((c->x86_model == 8 && c->x86_mask >= 1) || (c->x86_model > 8)) {
+ rdmsr(MSR_K7_CLK_CTL, l, h);
+ if ((l & 0xfff00000) != 0x20000000) {
+ printk ("CPU: CLK_CTL MSR was %x. Reprogramming to %x\n", l,
+@@ -253,20 +256,19 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ /* Use K8 tuning for Fam10h and Fam11h */
+ case 0x10:
+ case 0x11:
+- set_bit(X86_FEATURE_K8, c->x86_capability);
++ set_cpu_cap(c, X86_FEATURE_K8);
+ break;
+ case 6:
+- set_bit(X86_FEATURE_K7, c->x86_capability);
++ set_cpu_cap(c, X86_FEATURE_K7);
+ break;
+ }
+ if (c->x86 >= 6)
+- set_bit(X86_FEATURE_FXSAVE_LEAK, c->x86_capability);
++ set_cpu_cap(c, X86_FEATURE_FXSAVE_LEAK);
+
+ display_cacheinfo(c);
+
+- if (cpuid_eax(0x80000000) >= 0x80000008) {
++ if (cpuid_eax(0x80000000) >= 0x80000008)
+ c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
+- }
+
+ #ifdef CONFIG_X86_HT
+ /*
+@@ -302,20 +304,20 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+
+ /* K6s reports MCEs but don't actually have all the MSRs */
+ if (c->x86 < 6)
+- clear_bit(X86_FEATURE_MCE, c->x86_capability);
++ clear_cpu_cap(c, X86_FEATURE_MCE);
+
+ if (cpu_has_xmm2)
+- set_bit(X86_FEATURE_MFENCE_RDTSC, c->x86_capability);
++ set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
+ }
+
+-static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
++static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 *c, unsigned int size)
+ {
+ /* AMD errata T13 (order #21922) */
+ if ((c->x86 == 6)) {
+ if (c->x86_model == 3 && c->x86_mask == 0) /* Duron Rev A0 */
+ size = 64;
+ if (c->x86_model == 4 &&
+- (c->x86_mask==0 || c->x86_mask==1)) /* Tbird rev A1/A2 */
++ (c->x86_mask == 0 || c->x86_mask == 1)) /* Tbird rev A1/A2 */
+ size = 256;
+ }
+ return size;
+@@ -323,25 +325,22 @@ static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 * c, unsigned in
+
+ static struct cpu_dev amd_cpu_dev __cpuinitdata = {
+ .c_vendor = "AMD",
+- .c_ident = { "AuthenticAMD" },
++ .c_ident = { "AuthenticAMD" },
+ .c_models = {
+ { .vendor = X86_VENDOR_AMD, .family = 4, .model_names =
+ {
+ [3] = "486 DX/2",
+ [7] = "486 DX/2-WB",
+- [8] = "486 DX/4",
+- [9] = "486 DX/4-WB",
++ [8] = "486 DX/4",
++ [9] = "486 DX/4-WB",
+ [14] = "Am5x86-WT",
+- [15] = "Am5x86-WB"
++ [15] = "Am5x86-WB"
+ }
+ },
+ },
++ .c_early_init = early_init_amd,
+ .c_init = init_amd,
+ .c_size_cache = amd_size_cache,
+ };
+
+-int __init amd_init_cpu(void)
+-{
+- cpu_devs[X86_VENDOR_AMD] = &amd_cpu_dev;
+- return 0;
+-}
++cpu_vendor_dev_register(X86_VENDOR_AMD, &amd_cpu_dev);
+diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c
+index 9681fa1..e0f45ed 100644
+--- a/arch/x86/kernel/cpu/centaur.c
++++ b/arch/x86/kernel/cpu/centaur.c
+@@ -1,31 +1,34 @@
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/bitops.h>
++
+ #include <asm/processor.h>
+ #include <asm/msr.h>
+ #include <asm/e820.h>
+ #include <asm/mtrr.h>
++
+ #include "cpu.h"
+
+ #ifdef CONFIG_X86_OOSTORE
+
+ static u32 __cpuinit power2(u32 x)
+ {
+- u32 s=1;
+- while(s<=x)
+- s<<=1;
+- return s>>=1;
++ u32 s = 1;
++
++ while (s <= x)
++ s <<= 1;
++
++ return s >>= 1;
+ }
+
+
+ /*
+- * Set up an actual MCR
++ * Set up an actual MCR
+ */
+-
+ static void __cpuinit centaur_mcr_insert(int reg, u32 base, u32 size, int key)
+ {
+ u32 lo, hi;
+-
++
+ hi = base & ~0xFFF;
+ lo = ~(size-1); /* Size is a power of 2 so this makes a mask */
+ lo &= ~0xFFF; /* Remove the ctrl value bits */
+@@ -35,30 +38,28 @@ static void __cpuinit centaur_mcr_insert(int reg, u32 base, u32 size, int key)
+ }
+
+ /*
+- * Figure what we can cover with MCR's
++ * Figure what we can cover with MCR's
+ *
+- * Shortcut: We know you can't put 4Gig of RAM on a winchip
++ * Shortcut: We know you can't put 4Gig of RAM on a winchip
+ */
+-
+-static u32 __cpuinit ramtop(void) /* 16388 */
++static u32 __cpuinit ramtop(void)
+ {
+- int i;
+- u32 top = 0;
+ u32 clip = 0xFFFFFFFFUL;
+-
++ u32 top = 0;
++ int i;
++
+ for (i = 0; i < e820.nr_map; i++) {
+ unsigned long start, end;
+
+ if (e820.map[i].addr > 0xFFFFFFFFUL)
+ continue;
+ /*
+- * Don't MCR over reserved space. Ignore the ISA hole
+- * we frob around that catastrophe already
++ * Don't MCR over reserved space. Ignore the ISA hole
++ * we frob around that catastrophe already
+ */
+-
+- if (e820.map[i].type == E820_RESERVED)
+- {
+- if(e820.map[i].addr >= 0x100000UL && e820.map[i].addr < clip)
++ if (e820.map[i].type == E820_RESERVED) {
++ if (e820.map[i].addr >= 0x100000UL &&
++ e820.map[i].addr < clip)
+ clip = e820.map[i].addr;
+ continue;
+ }
+@@ -69,28 +70,27 @@ static u32 __cpuinit ramtop(void) /* 16388 */
+ if (end > top)
+ top = end;
+ }
+- /* Everything below 'top' should be RAM except for the ISA hole.
+- Because of the limited MCR's we want to map NV/ACPI into our
+- MCR range for gunk in RAM
+-
+- Clip might cause us to MCR insufficient RAM but that is an
+- acceptable failure mode and should only bite obscure boxes with
+- a VESA hole at 15Mb
+-
+- The second case Clip sometimes kicks in is when the EBDA is marked
+- as reserved. Again we fail safe with reasonable results
+- */
+-
+- if(top>clip)
+- top=clip;
+-
++ /*
++ * Everything below 'top' should be RAM except for the ISA hole.
++ * Because of the limited MCR's we want to map NV/ACPI into our
++ * MCR range for gunk in RAM
++ *
++ * Clip might cause us to MCR insufficient RAM but that is an
++ * acceptable failure mode and should only bite obscure boxes with
++ * a VESA hole at 15Mb
++ *
++ * The second case Clip sometimes kicks in is when the EBDA is marked
++ * as reserved. Again we fail safe with reasonable results
++ */
++ if (top > clip)
++ top = clip;
++
+ return top;
+ }
+
+ /*
+- * Compute a set of MCR's to give maximum coverage
++ * Compute a set of MCR's to give maximum coverage
+ */
+-
+ static int __cpuinit centaur_mcr_compute(int nr, int key)
+ {
+ u32 mem = ramtop();
+@@ -99,141 +99,131 @@ static int __cpuinit centaur_mcr_compute(int nr, int key)
+ u32 top = root;
+ u32 floor = 0;
+ int ct = 0;
+-
+- while(ct<nr)
+- {
++
++ while (ct < nr) {
+ u32 fspace = 0;
++ u32 high;
++ u32 low;
+
+ /*
+- * Find the largest block we will fill going upwards
++ * Find the largest block we will fill going upwards
+ */
+-
+- u32 high = power2(mem-top);
++ high = power2(mem-top);
+
+ /*
+- * Find the largest block we will fill going downwards
++ * Find the largest block we will fill going downwards
+ */
+-
+- u32 low = base/2;
++ low = base/2;
+
+ /*
+- * Don't fill below 1Mb going downwards as there
+- * is an ISA hole in the way.
+- */
+-
+- if(base <= 1024*1024)
++ * Don't fill below 1Mb going downwards as there
++ * is an ISA hole in the way.
++ */
++ if (base <= 1024*1024)
+ low = 0;
+-
++
+ /*
+- * See how much space we could cover by filling below
+- * the ISA hole
++ * See how much space we could cover by filling below
++ * the ISA hole
+ */
+-
+- if(floor == 0)
++
++ if (floor == 0)
+ fspace = 512*1024;
+- else if(floor ==512*1024)
++ else if (floor == 512*1024)
+ fspace = 128*1024;
+
+ /* And forget ROM space */
+-
++
+ /*
+- * Now install the largest coverage we get
++ * Now install the largest coverage we get
+ */
+-
+- if(fspace > high && fspace > low)
+- {
++ if (fspace > high && fspace > low) {
+ centaur_mcr_insert(ct, floor, fspace, key);
+ floor += fspace;
+- }
+- else if(high > low)
+- {
++ } else if (high > low) {
+ centaur_mcr_insert(ct, top, high, key);
+ top += high;
+- }
+- else if(low > 0)
+- {
++ } else if (low > 0) {
+ base -= low;
+ centaur_mcr_insert(ct, base, low, key);
+- }
+- else break;
++ } else
++ break;
+ ct++;
+ }
+ /*
+- * We loaded ct values. We now need to set the mask. The caller
+- * must do this bit.
++ * We loaded ct values. We now need to set the mask. The caller
++ * must do this bit.
+ */
+-
+ return ct;
+ }
+
+ static void __cpuinit centaur_create_optimal_mcr(void)
+ {
++ int used;
+ int i;
++
+ /*
+- * Allocate up to 6 mcrs to mark as much of ram as possible
+- * as write combining and weak write ordered.
++ * Allocate up to 6 mcrs to mark as much of ram as possible
++ * as write combining and weak write ordered.
+ *
+- * To experiment with: Linux never uses stack operations for
+- * mmio spaces so we could globally enable stack operation wc
++ * To experiment with: Linux never uses stack operations for
++ * mmio spaces so we could globally enable stack operation wc
+ *
+- * Load the registers with type 31 - full write combining, all
+- * writes weakly ordered.
++ * Load the registers with type 31 - full write combining, all
++ * writes weakly ordered.
+ */
+- int used = centaur_mcr_compute(6, 31);
++ used = centaur_mcr_compute(6, 31);
+
+ /*
+- * Wipe unused MCRs
++ * Wipe unused MCRs
+ */
+-
+- for(i=used;i<8;i++)
++ for (i = used; i < 8; i++)
+ wrmsr(MSR_IDT_MCR0+i, 0, 0);
+ }
+
+ static void __cpuinit winchip2_create_optimal_mcr(void)
+ {
+ u32 lo, hi;
++ int used;
+ int i;
+
+ /*
+- * Allocate up to 6 mcrs to mark as much of ram as possible
+- * as write combining, weak store ordered.
++ * Allocate up to 6 mcrs to mark as much of ram as possible
++ * as write combining, weak store ordered.
+ *
+- * Load the registers with type 25
+- * 8 - weak write ordering
+- * 16 - weak read ordering
+- * 1 - write combining
++ * Load the registers with type 25
++ * 8 - weak write ordering
++ * 16 - weak read ordering
++ * 1 - write combining
+ */
++ used = centaur_mcr_compute(6, 25);
+
+- int used = centaur_mcr_compute(6, 25);
+-
+ /*
+- * Mark the registers we are using.
++ * Mark the registers we are using.
+ */
+-
+ rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
+- for(i=0;i<used;i++)
+- lo|=1<<(9+i);
++ for (i = 0; i < used; i++)
++ lo |= 1<<(9+i);
+ wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
+-
++
+ /*
+- * Wipe unused MCRs
++ * Wipe unused MCRs
+ */
+-
+- for(i=used;i<8;i++)
++
++ for (i = used; i < 8; i++)
+ wrmsr(MSR_IDT_MCR0+i, 0, 0);
+ }
+
+ /*
+- * Handle the MCR key on the Winchip 2.
++ * Handle the MCR key on the Winchip 2.
+ */
+-
+ static void __cpuinit winchip2_unprotect_mcr(void)
+ {
+ u32 lo, hi;
+ u32 key;
+-
++
+ rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
+- lo&=~0x1C0; /* blank bits 8-6 */
++ lo &= ~0x1C0; /* blank bits 8-6 */
+ key = (lo>>17) & 7;
+ lo |= key<<6; /* replace with unlock key */
+ wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
+@@ -242,9 +232,9 @@ static void __cpuinit winchip2_unprotect_mcr(void)
+ static void __cpuinit winchip2_protect_mcr(void)
+ {
+ u32 lo, hi;
+-
++
+ rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
+- lo&=~0x1C0; /* blank bits 8-6 */
++ lo &= ~0x1C0; /* blank bits 8-6 */
+ wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
+ }
+ #endif /* CONFIG_X86_OOSTORE */
+@@ -267,17 +257,17 @@ static void __cpuinit init_c3(struct cpuinfo_x86 *c)
+
+ /* enable ACE unit, if present and disabled */
+ if ((tmp & (ACE_PRESENT | ACE_ENABLED)) == ACE_PRESENT) {
+- rdmsr (MSR_VIA_FCR, lo, hi);
++ rdmsr(MSR_VIA_FCR, lo, hi);
+ lo |= ACE_FCR; /* enable ACE unit */
+- wrmsr (MSR_VIA_FCR, lo, hi);
++ wrmsr(MSR_VIA_FCR, lo, hi);
+ printk(KERN_INFO "CPU: Enabled ACE h/w crypto\n");
+ }
+
+ /* enable RNG unit, if present and disabled */
+ if ((tmp & (RNG_PRESENT | RNG_ENABLED)) == RNG_PRESENT) {
+- rdmsr (MSR_VIA_RNG, lo, hi);
++ rdmsr(MSR_VIA_RNG, lo, hi);
+ lo |= RNG_ENABLE; /* enable RNG unit */
+- wrmsr (MSR_VIA_RNG, lo, hi);
++ wrmsr(MSR_VIA_RNG, lo, hi);
+ printk(KERN_INFO "CPU: Enabled h/w RNG\n");
+ }
+
+@@ -288,171 +278,183 @@ static void __cpuinit init_c3(struct cpuinfo_x86 *c)
+ }
+
+ /* Cyrix III family needs CX8 & PGE explicitly enabled. */
+- if (c->x86_model >=6 && c->x86_model <= 9) {
+- rdmsr (MSR_VIA_FCR, lo, hi);
++ if (c->x86_model >= 6 && c->x86_model <= 9) {
++ rdmsr(MSR_VIA_FCR, lo, hi);
+ lo |= (1<<1 | 1<<7);
+- wrmsr (MSR_VIA_FCR, lo, hi);
+- set_bit(X86_FEATURE_CX8, c->x86_capability);
++ wrmsr(MSR_VIA_FCR, lo, hi);
++ set_cpu_cap(c, X86_FEATURE_CX8);
+ }
+
+ /* Before Nehemiah, the C3's had 3dNOW! */
+- if (c->x86_model >=6 && c->x86_model <9)
+- set_bit(X86_FEATURE_3DNOW, c->x86_capability);
++ if (c->x86_model >= 6 && c->x86_model < 9)
++ set_cpu_cap(c, X86_FEATURE_3DNOW);
+
+ get_model_name(c);
+ display_cacheinfo(c);
+ }
+
++enum {
++ ECX8 = 1<<1,
++ EIERRINT = 1<<2,
++ DPM = 1<<3,
++ DMCE = 1<<4,
++ DSTPCLK = 1<<5,
++ ELINEAR = 1<<6,
++ DSMC = 1<<7,
++ DTLOCK = 1<<8,
++ EDCTLB = 1<<8,
++ EMMX = 1<<9,
++ DPDC = 1<<11,
++ EBRPRED = 1<<12,
++ DIC = 1<<13,
++ DDC = 1<<14,
++ DNA = 1<<15,
++ ERETSTK = 1<<16,
++ E2MMX = 1<<19,
++ EAMD3D = 1<<20,
++};
++
+ static void __cpuinit init_centaur(struct cpuinfo_x86 *c)
+ {
+- enum {
+- ECX8=1<<1,
+- EIERRINT=1<<2,
+- DPM=1<<3,
+- DMCE=1<<4,
+- DSTPCLK=1<<5,
+- ELINEAR=1<<6,
+- DSMC=1<<7,
+- DTLOCK=1<<8,
+- EDCTLB=1<<8,
+- EMMX=1<<9,
+- DPDC=1<<11,
+- EBRPRED=1<<12,
+- DIC=1<<13,
+- DDC=1<<14,
+- DNA=1<<15,
+- ERETSTK=1<<16,
+- E2MMX=1<<19,
+- EAMD3D=1<<20,
+- };
+
+ char *name;
+- u32 fcr_set=0;
+- u32 fcr_clr=0;
+- u32 lo,hi,newlo;
+- u32 aa,bb,cc,dd;
++ u32 fcr_set = 0;
++ u32 fcr_clr = 0;
++ u32 lo, hi, newlo;
++ u32 aa, bb, cc, dd;
+
+- /* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
+- 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
+- clear_bit(0*32+31, c->x86_capability);
++ /*
++ * Bit 31 in normal CPUID used for nonstandard 3DNow ID;
++ * 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway
++ */
++ clear_cpu_cap(c, 0*32+31);
+
+ switch (c->x86) {
+-
+- case 5:
+- switch(c->x86_model) {
+- case 4:
+- name="C6";
+- fcr_set=ECX8|DSMC|EDCTLB|EMMX|ERETSTK;
+- fcr_clr=DPDC;
+- printk(KERN_NOTICE "Disabling bugged TSC.\n");
+- clear_bit(X86_FEATURE_TSC, c->x86_capability);
++ case 5:
++ switch (c->x86_model) {
++ case 4:
++ name = "C6";
++ fcr_set = ECX8|DSMC|EDCTLB|EMMX|ERETSTK;
++ fcr_clr = DPDC;
++ printk(KERN_NOTICE "Disabling bugged TSC.\n");
++ clear_cpu_cap(c, X86_FEATURE_TSC);
+ #ifdef CONFIG_X86_OOSTORE
+- centaur_create_optimal_mcr();
+- /* Enable
+- write combining on non-stack, non-string
+- write combining on string, all types
+- weak write ordering
+-
+- The C6 original lacks weak read order
+-
+- Note 0x120 is write only on Winchip 1 */
+-
+- wrmsr(MSR_IDT_MCR_CTRL, 0x01F0001F, 0);
+-#endif
++ centaur_create_optimal_mcr();
++ /*
++ * Enable:
++ * write combining on non-stack, non-string
++ * write combining on string, all types
++ * weak write ordering
++ *
++ * The C6 original lacks weak read order
++ *
++ * Note 0x120 is write only on Winchip 1
++ */
++ wrmsr(MSR_IDT_MCR_CTRL, 0x01F0001F, 0);
++#endif
++ break;
++ case 8:
++ switch (c->x86_mask) {
++ default:
++ name = "2";
++ break;
++ case 7 ... 9:
++ name = "2A";
+ break;
+- case 8:
+- switch(c->x86_mask) {
+- default:
+- name="2";
+- break;
+- case 7 ... 9:
+- name="2A";
+- break;
+- case 10 ... 15:
+- name="2B";
+- break;
+- }
+- fcr_set=ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|E2MMX|EAMD3D;
+- fcr_clr=DPDC;
++ case 10 ... 15:
++ name = "2B";
++ break;
++ }
++ fcr_set = ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|
++ E2MMX|EAMD3D;
++ fcr_clr = DPDC;
+ #ifdef CONFIG_X86_OOSTORE
+- winchip2_unprotect_mcr();
+- winchip2_create_optimal_mcr();
+- rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
+- /* Enable
+- write combining on non-stack, non-string
+- write combining on string, all types
+- weak write ordering
+- */
+- lo|=31;
+- wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
+- winchip2_protect_mcr();
++ winchip2_unprotect_mcr();
++ winchip2_create_optimal_mcr();
++ rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
++ /*
++ * Enable:
++ * write combining on non-stack, non-string
++ * write combining on string, all types
++ * weak write ordering
++ */
++ lo |= 31;
++ wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
++ winchip2_protect_mcr();
+ #endif
+- break;
+- case 9:
+- name="3";
+- fcr_set=ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|E2MMX|EAMD3D;
+- fcr_clr=DPDC;
++ break;
++ case 9:
++ name = "3";
++ fcr_set = ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|
++ E2MMX|EAMD3D;
++ fcr_clr = DPDC;
+ #ifdef CONFIG_X86_OOSTORE
+- winchip2_unprotect_mcr();
+- winchip2_create_optimal_mcr();
+- rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
+- /* Enable
+- write combining on non-stack, non-string
+- write combining on string, all types
+- weak write ordering
+- */
+- lo|=31;
+- wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
+- winchip2_protect_mcr();
++ winchip2_unprotect_mcr();
++ winchip2_create_optimal_mcr();
++ rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
++ /*
++ * Enable:
++ * write combining on non-stack, non-string
++ * write combining on string, all types
++ * weak write ordering
++ */
++ lo |= 31;
++ wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
++ winchip2_protect_mcr();
+ #endif
+- break;
+- default:
+- name="??";
+- }
++ break;
++ default:
++ name = "??";
++ }
+
+- rdmsr(MSR_IDT_FCR1, lo, hi);
+- newlo=(lo|fcr_set) & (~fcr_clr);
++ rdmsr(MSR_IDT_FCR1, lo, hi);
++ newlo = (lo|fcr_set) & (~fcr_clr);
+
+- if (newlo!=lo) {
+- printk(KERN_INFO "Centaur FCR was 0x%X now 0x%X\n", lo, newlo );
+- wrmsr(MSR_IDT_FCR1, newlo, hi );
+- } else {
+- printk(KERN_INFO "Centaur FCR is 0x%X\n",lo);
+- }
+- /* Emulate MTRRs using Centaur's MCR. */
+- set_bit(X86_FEATURE_CENTAUR_MCR, c->x86_capability);
+- /* Report CX8 */
+- set_bit(X86_FEATURE_CX8, c->x86_capability);
+- /* Set 3DNow! on Winchip 2 and above. */
+- if (c->x86_model >=8)
+- set_bit(X86_FEATURE_3DNOW, c->x86_capability);
+- /* See if we can find out some more. */
+- if ( cpuid_eax(0x80000000) >= 0x80000005 ) {
+- /* Yes, we can. */
+- cpuid(0x80000005,&aa,&bb,&cc,&dd);
+- /* Add L1 data and code cache sizes. */
+- c->x86_cache_size = (cc>>24)+(dd>>24);
+- }
+- sprintf( c->x86_model_id, "WinChip %s", name );
+- break;
++ if (newlo != lo) {
++ printk(KERN_INFO "Centaur FCR was 0x%X now 0x%X\n",
++ lo, newlo);
++ wrmsr(MSR_IDT_FCR1, newlo, hi);
++ } else {
++ printk(KERN_INFO "Centaur FCR is 0x%X\n", lo);
++ }
++ /* Emulate MTRRs using Centaur's MCR. */
++ set_cpu_cap(c, X86_FEATURE_CENTAUR_MCR);
++ /* Report CX8 */
++ set_cpu_cap(c, X86_FEATURE_CX8);
++ /* Set 3DNow! on Winchip 2 and above. */
++ if (c->x86_model >= 8)
++ set_cpu_cap(c, X86_FEATURE_3DNOW);
++ /* See if we can find out some more. */
++ if (cpuid_eax(0x80000000) >= 0x80000005) {
++ /* Yes, we can. */
++ cpuid(0x80000005, &aa, &bb, &cc, &dd);
++ /* Add L1 data and code cache sizes. */
++ c->x86_cache_size = (cc>>24)+(dd>>24);
++ }
++ sprintf(c->x86_model_id, "WinChip %s", name);
++ break;
+
+- case 6:
+- init_c3(c);
+- break;
++ case 6:
++ init_c3(c);
++ break;
+ }
+ }
+
+-static unsigned int __cpuinit centaur_size_cache(struct cpuinfo_x86 * c, unsigned int size)
++static unsigned int __cpuinit
++centaur_size_cache(struct cpuinfo_x86 *c, unsigned int size)
+ {
+ /* VIA C3 CPUs (670-68F) need further shifting. */
+ if ((c->x86 == 6) && ((c->x86_model == 7) || (c->x86_model == 8)))
+ size >>= 8;
+
+- /* VIA also screwed up Nehemiah stepping 1, and made
+- it return '65KB' instead of '64KB'
+- - Note, it seems this may only be in engineering samples. */
+- if ((c->x86==6) && (c->x86_model==9) && (c->x86_mask==1) && (size==65))
+- size -=1;
++ /*
++ * There's also an erratum in Nehemiah stepping 1, which
++ * returns '65KB' instead of '64KB'
++ * - Note, it seems this may only be in engineering samples.
++ */
++ if ((c->x86 == 6) && (c->x86_model == 9) &&
++ (c->x86_mask == 1) && (size == 65))
++ size -= 1;
+
+ return size;
+ }
+@@ -464,8 +466,4 @@ static struct cpu_dev centaur_cpu_dev __cpuinitdata = {
+ .c_size_cache = centaur_size_cache,
+ };
+
+-int __init centaur_init_cpu(void)
+-{
+- cpu_devs[X86_VENDOR_CENTAUR] = ¢aur_cpu_dev;
+- return 0;
+-}
++cpu_vendor_dev_register(X86_VENDOR_CENTAUR, ¢aur_cpu_dev);
+diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
+index a38aafa..35b4f6a 100644
+--- a/arch/x86/kernel/cpu/common.c
++++ b/arch/x86/kernel/cpu/common.c
+@@ -5,7 +5,6 @@
+ #include <linux/module.h>
+ #include <linux/percpu.h>
+ #include <linux/bootmem.h>
+-#include <asm/semaphore.h>
+ #include <asm/processor.h>
+ #include <asm/i387.h>
+ #include <asm/msr.h>
+@@ -62,9 +61,9 @@ __u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata;
+ static int cachesize_override __cpuinitdata = -1;
+ static int disable_x86_serial_nr __cpuinitdata = 1;
+
+-struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {};
++struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {};
+
+-static void __cpuinit default_init(struct cpuinfo_x86 * c)
++static void __cpuinit default_init(struct cpuinfo_x86 *c)
+ {
+ /* Not much we can do here... */
+ /* Check if at least it has cpuid */
+@@ -81,11 +80,11 @@ static struct cpu_dev __cpuinitdata default_cpu = {
+ .c_init = default_init,
+ .c_vendor = "Unknown",
+ };
+-static struct cpu_dev * this_cpu __cpuinitdata = &default_cpu;
++static struct cpu_dev *this_cpu __cpuinitdata = &default_cpu;
+
+ static int __init cachesize_setup(char *str)
+ {
+- get_option (&str, &cachesize_override);
++ get_option(&str, &cachesize_override);
+ return 1;
+ }
+ __setup("cachesize=", cachesize_setup);
+@@ -107,12 +106,12 @@ int __cpuinit get_model_name(struct cpuinfo_x86 *c)
+ /* Intel chips right-justify this string for some dumb reason;
+ undo that brain damage */
+ p = q = &c->x86_model_id[0];
+- while ( *p == ' ' )
++ while (*p == ' ')
+ p++;
+- if ( p != q ) {
+- while ( *p )
++ if (p != q) {
++ while (*p)
+ *q++ = *p++;
+- while ( q <= &c->x86_model_id[48] )
++ while (q <= &c->x86_model_id[48])
+ *q++ = '\0'; /* Zero-pad the rest */
+ }
+
+@@ -130,7 +129,7 @@ void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
+ cpuid(0x80000005, &dummy, &dummy, &ecx, &edx);
+ printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n",
+ edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);
+- c->x86_cache_size=(ecx>>24)+(edx>>24);
++ c->x86_cache_size = (ecx>>24)+(edx>>24);
+ }
+
+ if (n < 0x80000006) /* Some chips just has a large L1. */
+@@ -138,16 +137,16 @@ void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
+
+ ecx = cpuid_ecx(0x80000006);
+ l2size = ecx >> 16;
+-
++
+ /* do processor-specific cache resizing */
+ if (this_cpu->c_size_cache)
+- l2size = this_cpu->c_size_cache(c,l2size);
++ l2size = this_cpu->c_size_cache(c, l2size);
+
+ /* Allow user to override all this if necessary. */
+ if (cachesize_override != -1)
+ l2size = cachesize_override;
+
+- if ( l2size == 0 )
++ if (l2size == 0)
+ return; /* Again, no L2 cache is possible */
+
+ c->x86_cache_size = l2size;
+@@ -156,16 +155,19 @@ void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
+ l2size, ecx & 0xFF);
+ }
+
+-/* Naming convention should be: <Name> [(<Codename>)] */
+-/* This table only is used unless init_<vendor>() below doesn't set it; */
+-/* in particular, if CPUID levels 0x80000002..4 are supported, this isn't used */
++/*
++ * Naming convention should be: <Name> [(<Codename>)]
++ * This table only is used unless init_<vendor>() below doesn't set it;
++ * in particular, if CPUID levels 0x80000002..4 are supported, this isn't used
++ *
++ */
+
+ /* Look up CPU names by table lookup. */
+ static char __cpuinit *table_lookup_model(struct cpuinfo_x86 *c)
+ {
+ struct cpu_model_info *info;
+
+- if ( c->x86_model >= 16 )
++ if (c->x86_model >= 16)
+ return NULL; /* Range check */
+
+ if (!this_cpu)
+@@ -190,9 +192,9 @@ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c, int early)
+
+ for (i = 0; i < X86_VENDOR_NUM; i++) {
+ if (cpu_devs[i]) {
+- if (!strcmp(v,cpu_devs[i]->c_ident[0]) ||
+- (cpu_devs[i]->c_ident[1] &&
+- !strcmp(v,cpu_devs[i]->c_ident[1]))) {
++ if (!strcmp(v, cpu_devs[i]->c_ident[0]) ||
++ (cpu_devs[i]->c_ident[1] &&
++ !strcmp(v, cpu_devs[i]->c_ident[1]))) {
+ c->x86_vendor = i;
+ if (!early)
+ this_cpu = cpu_devs[i];
+@@ -210,7 +212,7 @@ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c, int early)
+ }
+
+
+-static int __init x86_fxsr_setup(char * s)
++static int __init x86_fxsr_setup(char *s)
+ {
+ setup_clear_cpu_cap(X86_FEATURE_FXSR);
+ setup_clear_cpu_cap(X86_FEATURE_XMM);
+@@ -219,7 +221,7 @@ static int __init x86_fxsr_setup(char * s)
+ __setup("nofxsr", x86_fxsr_setup);
+
+
+-static int __init x86_sep_setup(char * s)
++static int __init x86_sep_setup(char *s)
+ {
+ setup_clear_cpu_cap(X86_FEATURE_SEP);
+ return 1;
+@@ -306,14 +308,30 @@ static void __cpuinit early_get_cap(struct cpuinfo_x86 *c)
+
+ }
+
+-}
++ clear_cpu_cap(c, X86_FEATURE_PAT);
++
++ switch (c->x86_vendor) {
++ case X86_VENDOR_AMD:
++ if (c->x86 >= 0xf && c->x86 <= 0x11)
++ set_cpu_cap(c, X86_FEATURE_PAT);
++ break;
++ case X86_VENDOR_INTEL:
++ if (c->x86 == 0xF || (c->x86 == 6 && c->x86_model >= 15))
++ set_cpu_cap(c, X86_FEATURE_PAT);
++ break;
++ }
+
+-/* Do minimum CPU detection early.
+- Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment.
+- The others are not touched to avoid unwanted side effects.
++}
+
+- WARNING: this function is only called on the BP. Don't add code here
+- that is supposed to run on all CPUs. */
++/*
++ * Do minimum CPU detection early.
++ * Fields really needed: vendor, cpuid_level, family, model, mask,
++ * cache alignment.
++ * The others are not touched to avoid unwanted side effects.
++ *
++ * WARNING: this function is only called on the BP. Don't add code here
++ * that is supposed to run on all CPUs.
++ */
+ static void __init early_cpu_detect(void)
+ {
+ struct cpuinfo_x86 *c = &boot_cpu_data;
+@@ -328,19 +346,14 @@ static void __init early_cpu_detect(void)
+
+ get_cpu_vendor(c, 1);
+
+- switch (c->x86_vendor) {
+- case X86_VENDOR_AMD:
+- early_init_amd(c);
+- break;
+- case X86_VENDOR_INTEL:
+- early_init_intel(c);
+- break;
+- }
++ if (c->x86_vendor != X86_VENDOR_UNKNOWN &&
++ cpu_devs[c->x86_vendor]->c_early_init)
++ cpu_devs[c->x86_vendor]->c_early_init(c);
+
+ early_get_cap(c);
+ }
+
+-static void __cpuinit generic_identify(struct cpuinfo_x86 * c)
++static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
+ {
+ u32 tfms, xlvl;
+ unsigned int ebx;
+@@ -351,13 +364,12 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 * c)
+ (unsigned int *)&c->x86_vendor_id[0],
+ (unsigned int *)&c->x86_vendor_id[8],
+ (unsigned int *)&c->x86_vendor_id[4]);
+-
++
+ get_cpu_vendor(c, 0);
+ /* Initialize the standard set of capabilities */
+ /* Note that the vendor-specific code below might override */
+-
+ /* Intel-defined flags: level 0x00000001 */
+- if ( c->cpuid_level >= 0x00000001 ) {
++ if (c->cpuid_level >= 0x00000001) {
+ u32 capability, excap;
+ cpuid(0x00000001, &tfms, &ebx, &excap, &capability);
+ c->x86_capability[0] = capability;
+@@ -369,12 +381,14 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 * c)
+ if (c->x86 >= 0x6)
+ c->x86_model += ((tfms >> 16) & 0xF) << 4;
+ c->x86_mask = tfms & 15;
++ c->initial_apicid = (ebx >> 24) & 0xFF;
+ #ifdef CONFIG_X86_HT
+- c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0);
++ c->apicid = phys_pkg_id(c->initial_apicid, 0);
++ c->phys_proc_id = c->initial_apicid;
+ #else
+- c->apicid = (ebx >> 24) & 0xFF;
++ c->apicid = c->initial_apicid;
+ #endif
+- if (c->x86_capability[0] & (1<<19))
++ if (test_cpu_cap(c, X86_FEATURE_CLFLSH))
+ c->x86_clflush_size = ((ebx >> 8) & 0xff) * 8;
+ } else {
+ /* Have CPUID level 0 only - unheard of */
+@@ -383,33 +397,42 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 * c)
+
+ /* AMD-defined flags: level 0x80000001 */
+ xlvl = cpuid_eax(0x80000000);
+- if ( (xlvl & 0xffff0000) == 0x80000000 ) {
+- if ( xlvl >= 0x80000001 ) {
++ if ((xlvl & 0xffff0000) == 0x80000000) {
++ if (xlvl >= 0x80000001) {
+ c->x86_capability[1] = cpuid_edx(0x80000001);
+ c->x86_capability[6] = cpuid_ecx(0x80000001);
+ }
+- if ( xlvl >= 0x80000004 )
++ if (xlvl >= 0x80000004)
+ get_model_name(c); /* Default name */
+ }
+
+ init_scattered_cpuid_features(c);
+ }
+
+-#ifdef CONFIG_X86_HT
+- c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff;
+-#endif
++ clear_cpu_cap(c, X86_FEATURE_PAT);
++
++ switch (c->x86_vendor) {
++ case X86_VENDOR_AMD:
++ if (c->x86 >= 0xf && c->x86 <= 0x11)
++ set_cpu_cap(c, X86_FEATURE_PAT);
++ break;
++ case X86_VENDOR_INTEL:
++ if (c->x86 == 0xF || (c->x86 == 6 && c->x86_model >= 15))
++ set_cpu_cap(c, X86_FEATURE_PAT);
++ break;
++ }
+ }
+
+ static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
+ {
+- if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr ) {
++ if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr) {
+ /* Disable processor serial number */
+- unsigned long lo,hi;
+- rdmsr(MSR_IA32_BBL_CR_CTL,lo,hi);
++ unsigned long lo, hi;
++ rdmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
+ lo |= 0x200000;
+- wrmsr(MSR_IA32_BBL_CR_CTL,lo,hi);
++ wrmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
+ printk(KERN_NOTICE "CPU serial number disabled.\n");
+- clear_bit(X86_FEATURE_PN, c->x86_capability);
++ clear_cpu_cap(c, X86_FEATURE_PN);
+
+ /* Disabling the serial number may affect the cpuid level */
+ c->cpuid_level = cpuid_eax(0);
+@@ -444,9 +467,11 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
+ memset(&c->x86_capability, 0, sizeof c->x86_capability);
+
+ if (!have_cpuid_p()) {
+- /* First of all, decide if this is a 486 or higher */
+- /* It's a 486 if we can modify the AC flag */
+- if ( flag_is_changeable_p(X86_EFLAGS_AC) )
++ /*
++ * First of all, decide if this is a 486 or higher
++ * It's a 486 if we can modify the AC flag
++ */
++ if (flag_is_changeable_p(X86_EFLAGS_AC))
+ c->x86 = 4;
+ else
+ c->x86 = 3;
+@@ -479,10 +504,10 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
+ */
+
+ /* If the model name is still unset, do table lookup. */
+- if ( !c->x86_model_id[0] ) {
++ if (!c->x86_model_id[0]) {
+ char *p;
+ p = table_lookup_model(c);
+- if ( p )
++ if (p)
+ strcpy(c->x86_model_id, p);
+ else
+ /* Last resort... */
+@@ -496,9 +521,9 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
+ * common between the CPUs. The first time this routine gets
+ * executed, c == &boot_cpu_data.
+ */
+- if ( c != &boot_cpu_data ) {
++ if (c != &boot_cpu_data) {
+ /* AND the already accumulated flags with these */
+- for ( i = 0 ; i < NCAPINTS ; i++ )
++ for (i = 0 ; i < NCAPINTS ; i++)
+ boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
+ }
+
+@@ -542,7 +567,7 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c)
+
+ if (smp_num_siblings == 1) {
+ printk(KERN_INFO "CPU: Hyper-Threading is disabled\n");
+- } else if (smp_num_siblings > 1 ) {
++ } else if (smp_num_siblings > 1) {
+
+ if (smp_num_siblings > NR_CPUS) {
+ printk(KERN_WARNING "CPU: Unsupported number of the "
+@@ -552,7 +577,7 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c)
+ }
+
+ index_msb = get_count_order(smp_num_siblings);
+- c->phys_proc_id = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);
++ c->phys_proc_id = phys_pkg_id(c->initial_apicid, index_msb);
+
+ printk(KERN_INFO "CPU: Physical Processor ID: %d\n",
+ c->phys_proc_id);
+@@ -563,7 +588,7 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c)
+
+ core_bits = get_count_order(c->x86_max_cores);
+
+- c->cpu_core_id = phys_pkg_id((ebx >> 24) & 0xFF, index_msb) &
++ c->cpu_core_id = phys_pkg_id(c->initial_apicid, index_msb) &
+ ((1 << core_bits) - 1);
+
+ if (c->x86_max_cores > 1)
+@@ -597,7 +622,7 @@ void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
+ else
+ printk("%s", c->x86_model_id);
+
+- if (c->x86_mask || c->cpuid_level >= 0)
++ if (c->x86_mask || c->cpuid_level >= 0)
+ printk(" stepping %02x\n", c->x86_mask);
+ else
+ printk("\n");
+@@ -616,23 +641,15 @@ __setup("clearcpuid=", setup_disablecpuid);
+
+ cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
+
+-/* This is hacky. :)
+- * We're emulating future behavior.
+- * In the future, the cpu-specific init functions will be called implicitly
+- * via the magic of initcalls.
+- * They will insert themselves into the cpu_devs structure.
+- * Then, when cpu_init() is called, we can just iterate over that array.
+- */
+ void __init early_cpu_init(void)
+ {
+- intel_cpu_init();
+- cyrix_init_cpu();
+- nsc_init_cpu();
+- amd_init_cpu();
+- centaur_init_cpu();
+- transmeta_init_cpu();
+- nexgen_init_cpu();
+- umc_init_cpu();
++ struct cpu_vendor_dev *cvdev;
++
++ for (cvdev = __x86cpuvendor_start ;
++ cvdev < __x86cpuvendor_end ;
++ cvdev++)
++ cpu_devs[cvdev->vendor] = cvdev->cpu_dev;
++
+ early_cpu_detect();
+ }
+
+@@ -666,7 +683,7 @@ void __cpuinit cpu_init(void)
+ {
+ int cpu = smp_processor_id();
+ struct task_struct *curr = current;
+- struct tss_struct * t = &per_cpu(init_tss, cpu);
++ struct tss_struct *t = &per_cpu(init_tss, cpu);
+ struct thread_struct *thread = &curr->thread;
+
+ if (cpu_test_and_set(cpu, cpu_initialized)) {
+@@ -692,7 +709,7 @@ void __cpuinit cpu_init(void)
+ enter_lazy_tlb(&init_mm, curr);
+
+ load_sp0(t, thread);
+- set_tss_desc(cpu,t);
++ set_tss_desc(cpu, t);
+ load_TR_desc();
+ load_LDT(&init_mm.context);
+
+diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h
+index e0b38c3..783691b 100644
+--- a/arch/x86/kernel/cpu/cpu.h
++++ b/arch/x86/kernel/cpu/cpu.h
+@@ -14,6 +14,7 @@ struct cpu_dev {
+
+ struct cpu_model_info c_models[4];
+
++ void (*c_early_init)(struct cpuinfo_x86 *c);
+ void (*c_init)(struct cpuinfo_x86 * c);
+ void (*c_identify)(struct cpuinfo_x86 * c);
+ unsigned int (*c_size_cache)(struct cpuinfo_x86 * c, unsigned int size);
+@@ -21,18 +22,17 @@ struct cpu_dev {
+
+ extern struct cpu_dev * cpu_devs [X86_VENDOR_NUM];
+
++struct cpu_vendor_dev {
++ int vendor;
++ struct cpu_dev *cpu_dev;
++};
++
++#define cpu_vendor_dev_register(cpu_vendor_id, cpu_dev) \
++ static struct cpu_vendor_dev __cpu_vendor_dev_##cpu_vendor_id __used \
++ __attribute__((__section__(".x86cpuvendor.init"))) = \
++ { cpu_vendor_id, cpu_dev }
++
++extern struct cpu_vendor_dev __x86cpuvendor_start[], __x86cpuvendor_end[];
++
+ extern int get_model_name(struct cpuinfo_x86 *c);
+ extern void display_cacheinfo(struct cpuinfo_x86 *c);
+-
+-extern void early_init_intel(struct cpuinfo_x86 *c);
+-extern void early_init_amd(struct cpuinfo_x86 *c);
+-
+-/* Specific CPU type init functions */
+-int intel_cpu_init(void);
+-int amd_init_cpu(void);
+-int cyrix_init_cpu(void);
+-int nsc_init_cpu(void);
+-int centaur_init_cpu(void);
+-int transmeta_init_cpu(void);
+-int nexgen_init_cpu(void);
+-int umc_init_cpu(void);
+diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
+index a962dcb..e2d870d 100644
+--- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
++++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
+@@ -192,9 +192,9 @@ static void drv_read(struct drv_cmd *cmd)
+ cpumask_t saved_mask = current->cpus_allowed;
+ cmd->val = 0;
+
+- set_cpus_allowed(current, cmd->mask);
++ set_cpus_allowed_ptr(current, &cmd->mask);
+ do_drv_read(cmd);
+- set_cpus_allowed(current, saved_mask);
++ set_cpus_allowed_ptr(current, &saved_mask);
+ }
+
+ static void drv_write(struct drv_cmd *cmd)
+@@ -203,30 +203,30 @@ static void drv_write(struct drv_cmd *cmd)
+ unsigned int i;
+
+ for_each_cpu_mask(i, cmd->mask) {
+- set_cpus_allowed(current, cpumask_of_cpu(i));
++ set_cpus_allowed_ptr(current, &cpumask_of_cpu(i));
+ do_drv_write(cmd);
+ }
+
+- set_cpus_allowed(current, saved_mask);
++ set_cpus_allowed_ptr(current, &saved_mask);
+ return;
+ }
+
+-static u32 get_cur_val(cpumask_t mask)
++static u32 get_cur_val(const cpumask_t *mask)
+ {
+ struct acpi_processor_performance *perf;
+ struct drv_cmd cmd;
+
+- if (unlikely(cpus_empty(mask)))
++ if (unlikely(cpus_empty(*mask)))
+ return 0;
+
+- switch (per_cpu(drv_data, first_cpu(mask))->cpu_feature) {
++ switch (per_cpu(drv_data, first_cpu(*mask))->cpu_feature) {
+ case SYSTEM_INTEL_MSR_CAPABLE:
+ cmd.type = SYSTEM_INTEL_MSR_CAPABLE;
+ cmd.addr.msr.reg = MSR_IA32_PERF_STATUS;
+ break;
+ case SYSTEM_IO_CAPABLE:
+ cmd.type = SYSTEM_IO_CAPABLE;
+- perf = per_cpu(drv_data, first_cpu(mask))->acpi_data;
++ perf = per_cpu(drv_data, first_cpu(*mask))->acpi_data;
+ cmd.addr.io.port = perf->control_register.address;
+ cmd.addr.io.bit_width = perf->control_register.bit_width;
+ break;
+@@ -234,7 +234,7 @@ static u32 get_cur_val(cpumask_t mask)
+ return 0;
+ }
+
+- cmd.mask = mask;
++ cmd.mask = *mask;
+
+ drv_read(&cmd);
+
+@@ -271,7 +271,7 @@ static unsigned int get_measured_perf(unsigned int cpu)
+ unsigned int retval;
+
+ saved_mask = current->cpus_allowed;
+- set_cpus_allowed(current, cpumask_of_cpu(cpu));
++ set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ if (get_cpu() != cpu) {
+ /* We were not able to run on requested processor */
+ put_cpu();
+@@ -329,7 +329,7 @@ static unsigned int get_measured_perf(unsigned int cpu)
+ retval = per_cpu(drv_data, cpu)->max_freq * perf_percent / 100;
+
+ put_cpu();
+- set_cpus_allowed(current, saved_mask);
++ set_cpus_allowed_ptr(current, &saved_mask);
+
+ dprintk("cpu %d: performance percent %d\n", cpu, perf_percent);
+ return retval;
+@@ -347,13 +347,13 @@ static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
+ return 0;
+ }
+
+- freq = extract_freq(get_cur_val(cpumask_of_cpu(cpu)), data);
++ freq = extract_freq(get_cur_val(&cpumask_of_cpu(cpu)), data);
+ dprintk("cur freq = %u\n", freq);
+
+ return freq;
+ }
+
+-static unsigned int check_freqs(cpumask_t mask, unsigned int freq,
++static unsigned int check_freqs(const cpumask_t *mask, unsigned int freq,
+ struct acpi_cpufreq_data *data)
+ {
+ unsigned int cur_freq;
+@@ -449,7 +449,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
+ drv_write(&cmd);
+
+ if (acpi_pstate_strict) {
+- if (!check_freqs(cmd.mask, freqs.new, data)) {
++ if (!check_freqs(&cmd.mask, freqs.new, data)) {
+ dprintk("acpi_cpufreq_target failed (%d)\n",
+ policy->cpu);
+ return -EAGAIN;
+diff --git a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
+index 14791ec..199e4e0 100644
+--- a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
++++ b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
+@@ -289,8 +289,8 @@ static int __init cpufreq_p4_init(void)
+ if (c->x86_vendor != X86_VENDOR_INTEL)
+ return -ENODEV;
+
+- if (!test_bit(X86_FEATURE_ACPI, c->x86_capability) ||
+- !test_bit(X86_FEATURE_ACC, c->x86_capability))
++ if (!test_cpu_cap(c, X86_FEATURE_ACPI) ||
++ !test_cpu_cap(c, X86_FEATURE_ACC))
+ return -ENODEV;
+
+ ret = cpufreq_register_driver(&p4clockmod_driver);
+diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
+index c99d59d..46d4034 100644
+--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
++++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
+@@ -478,12 +478,12 @@ static int core_voltage_post_transition(struct powernow_k8_data *data, u32 reqvi
+
+ static int check_supported_cpu(unsigned int cpu)
+ {
+- cpumask_t oldmask = CPU_MASK_ALL;
++ cpumask_t oldmask;
+ u32 eax, ebx, ecx, edx;
+ unsigned int rc = 0;
+
+ oldmask = current->cpus_allowed;
+- set_cpus_allowed(current, cpumask_of_cpu(cpu));
++ set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+
+ if (smp_processor_id() != cpu) {
+ printk(KERN_ERR PFX "limiting to cpu %u failed\n", cpu);
+@@ -528,7 +528,7 @@ static int check_supported_cpu(unsigned int cpu)
+ rc = 1;
+
+ out:
+- set_cpus_allowed(current, oldmask);
++ set_cpus_allowed_ptr(current, &oldmask);
+ return rc;
+ }
+
+@@ -1015,7 +1015,7 @@ static int transition_frequency_pstate(struct powernow_k8_data *data, unsigned i
+ /* Driver entry point to switch to the target frequency */
+ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsigned relation)
+ {
+- cpumask_t oldmask = CPU_MASK_ALL;
++ cpumask_t oldmask;
+ struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
+ u32 checkfid;
+ u32 checkvid;
+@@ -1030,7 +1030,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
+
+ /* only run on specific CPU from here on */
+ oldmask = current->cpus_allowed;
+- set_cpus_allowed(current, cpumask_of_cpu(pol->cpu));
++ set_cpus_allowed_ptr(current, &cpumask_of_cpu(pol->cpu));
+
+ if (smp_processor_id() != pol->cpu) {
+ printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
+@@ -1085,7 +1085,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
+ ret = 0;
+
+ err_out:
+- set_cpus_allowed(current, oldmask);
++ set_cpus_allowed_ptr(current, &oldmask);
+ return ret;
+ }
+
+@@ -1104,7 +1104,7 @@ static int powernowk8_verify(struct cpufreq_policy *pol)
+ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
+ {
+ struct powernow_k8_data *data;
+- cpumask_t oldmask = CPU_MASK_ALL;
++ cpumask_t oldmask;
+ int rc;
+
+ if (!cpu_online(pol->cpu))
+@@ -1145,7 +1145,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
+
+ /* only run on specific CPU from here on */
+ oldmask = current->cpus_allowed;
+- set_cpus_allowed(current, cpumask_of_cpu(pol->cpu));
++ set_cpus_allowed_ptr(current, &cpumask_of_cpu(pol->cpu));
+
+ if (smp_processor_id() != pol->cpu) {
+ printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
+@@ -1164,7 +1164,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
+ fidvid_msr_init();
+
+ /* run on any CPU again */
+- set_cpus_allowed(current, oldmask);
++ set_cpus_allowed_ptr(current, &oldmask);
+
+ if (cpu_family == CPU_HW_PSTATE)
+ pol->cpus = cpumask_of_cpu(pol->cpu);
+@@ -1205,7 +1205,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
+ return 0;
+
+ err_out:
+- set_cpus_allowed(current, oldmask);
++ set_cpus_allowed_ptr(current, &oldmask);
+ powernow_k8_cpu_exit_acpi(data);
+
+ kfree(data);
+@@ -1242,10 +1242,11 @@ static unsigned int powernowk8_get (unsigned int cpu)
+ if (!data)
+ return -EINVAL;
+
+- set_cpus_allowed(current, cpumask_of_cpu(cpu));
++ set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ if (smp_processor_id() != cpu) {
+- printk(KERN_ERR PFX "limiting to CPU %d failed in powernowk8_get\n", cpu);
+- set_cpus_allowed(current, oldmask);
++ printk(KERN_ERR PFX
++ "limiting to CPU %d failed in powernowk8_get\n", cpu);
++ set_cpus_allowed_ptr(current, &oldmask);
+ return 0;
+ }
+
+@@ -1253,13 +1254,14 @@ static unsigned int powernowk8_get (unsigned int cpu)
+ goto out;
+
+ if (cpu_family == CPU_HW_PSTATE)
+- khz = find_khz_freq_from_pstate(data->powernow_table, data->currpstate);
++ khz = find_khz_freq_from_pstate(data->powernow_table,
++ data->currpstate);
+ else
+ khz = find_khz_freq_from_fid(data->currfid);
+
+
+ out:
+- set_cpus_allowed(current, oldmask);
++ set_cpus_allowed_ptr(current, &oldmask);
+ return khz;
+ }
+
+diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
+index 3031f11..908dd34 100644
+--- a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
++++ b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
+@@ -315,7 +315,7 @@ static unsigned int get_cur_freq(unsigned int cpu)
+ cpumask_t saved_mask;
+
+ saved_mask = current->cpus_allowed;
+- set_cpus_allowed(current, cpumask_of_cpu(cpu));
++ set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ if (smp_processor_id() != cpu)
+ return 0;
+
+@@ -333,7 +333,7 @@ static unsigned int get_cur_freq(unsigned int cpu)
+ clock_freq = extract_clock(l, cpu, 1);
+ }
+
+- set_cpus_allowed(current, saved_mask);
++ set_cpus_allowed_ptr(current, &saved_mask);
+ return clock_freq;
+ }
+
+@@ -487,7 +487,7 @@ static int centrino_target (struct cpufreq_policy *policy,
+ else
+ cpu_set(j, set_mask);
+
+- set_cpus_allowed(current, set_mask);
++ set_cpus_allowed_ptr(current, &set_mask);
+ preempt_disable();
+ if (unlikely(!cpu_isset(smp_processor_id(), set_mask))) {
+ dprintk("couldn't limit to CPUs in this domain\n");
+@@ -555,7 +555,8 @@ static int centrino_target (struct cpufreq_policy *policy,
+
+ if (!cpus_empty(covered_cpus)) {
+ for_each_cpu_mask(j, covered_cpus) {
+- set_cpus_allowed(current, cpumask_of_cpu(j));
++ set_cpus_allowed_ptr(current,
++ &cpumask_of_cpu(j));
+ wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
+ }
+ }
+@@ -569,12 +570,12 @@ static int centrino_target (struct cpufreq_policy *policy,
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ }
+ }
+- set_cpus_allowed(current, saved_mask);
++ set_cpus_allowed_ptr(current, &saved_mask);
+ return 0;
+
+ migrate_end:
+ preempt_enable();
+- set_cpus_allowed(current, saved_mask);
++ set_cpus_allowed_ptr(current, &saved_mask);
+ return 0;
+ }
+
+diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
+index 14d68aa..1b50244 100644
+--- a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
++++ b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
+@@ -229,22 +229,22 @@ static unsigned int speedstep_detect_chipset (void)
+ return 0;
+ }
+
+-static unsigned int _speedstep_get(cpumask_t cpus)
++static unsigned int _speedstep_get(const cpumask_t *cpus)
+ {
+ unsigned int speed;
+ cpumask_t cpus_allowed;
+
+ cpus_allowed = current->cpus_allowed;
+- set_cpus_allowed(current, cpus);
++ set_cpus_allowed_ptr(current, cpus);
+ speed = speedstep_get_processor_frequency(speedstep_processor);
+- set_cpus_allowed(current, cpus_allowed);
++ set_cpus_allowed_ptr(current, &cpus_allowed);
+ dprintk("detected %u kHz as current frequency\n", speed);
+ return speed;
+ }
+
+ static unsigned int speedstep_get(unsigned int cpu)
+ {
+- return _speedstep_get(cpumask_of_cpu(cpu));
++ return _speedstep_get(&cpumask_of_cpu(cpu));
+ }
+
+ /**
+@@ -267,7 +267,7 @@ static int speedstep_target (struct cpufreq_policy *policy,
+ if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate))
+ return -EINVAL;
+
+- freqs.old = _speedstep_get(policy->cpus);
++ freqs.old = _speedstep_get(&policy->cpus);
+ freqs.new = speedstep_freqs[newstate].frequency;
+ freqs.cpu = policy->cpu;
+
+@@ -285,12 +285,12 @@ static int speedstep_target (struct cpufreq_policy *policy,
+ }
+
+ /* switch to physical CPU where state is to be changed */
+- set_cpus_allowed(current, policy->cpus);
++ set_cpus_allowed_ptr(current, &policy->cpus);
+
+ speedstep_set_state(newstate);
+
+ /* allow to be run on all CPUs */
+- set_cpus_allowed(current, cpus_allowed);
++ set_cpus_allowed_ptr(current, &cpus_allowed);
+
+ for_each_cpu_mask(i, policy->cpus) {
+ freqs.cpu = i;
+@@ -326,7 +326,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
+ #endif
+
+ cpus_allowed = current->cpus_allowed;
+- set_cpus_allowed(current, policy->cpus);
++ set_cpus_allowed_ptr(current, &policy->cpus);
+
+ /* detect low and high frequency and transition latency */
+ result = speedstep_get_freqs(speedstep_processor,
+@@ -334,12 +334,12 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
+ &speedstep_freqs[SPEEDSTEP_HIGH].frequency,
+ &policy->cpuinfo.transition_latency,
+ &speedstep_set_state);
+- set_cpus_allowed(current, cpus_allowed);
++ set_cpus_allowed_ptr(current, &cpus_allowed);
+ if (result)
+ return result;
+
+ /* get current speed setting */
+- speed = _speedstep_get(policy->cpus);
++ speed = _speedstep_get(&policy->cpus);
+ if (!speed)
+ return -EIO;
+
+diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c
+index 7139b02..3fd7a67 100644
+--- a/arch/x86/kernel/cpu/cyrix.c
++++ b/arch/x86/kernel/cpu/cyrix.c
+@@ -19,7 +19,7 @@ static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
+ {
+ unsigned char ccr2, ccr3;
+ unsigned long flags;
+-
++
+ /* we test for DEVID by checking whether CCR3 is writable */
+ local_irq_save(flags);
+ ccr3 = getCx86(CX86_CCR3);
+@@ -37,8 +37,7 @@ static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
+ setCx86(CX86_CCR2, ccr2);
+ *dir0 = 0xfe;
+ }
+- }
+- else {
++ } else {
+ setCx86(CX86_CCR3, ccr3); /* restore CCR3 */
+
+ /* read DIR0 and DIR1 CPU registers */
+@@ -86,7 +85,7 @@ static char cyrix_model_mult2[] __cpuinitdata = "12233445";
+ static void __cpuinit check_cx686_slop(struct cpuinfo_x86 *c)
+ {
+ unsigned long flags;
+-
++
+ if (Cx86_dir0_msb == 3) {
+ unsigned char ccr3, ccr5;
+
+@@ -132,7 +131,7 @@ static void __cpuinit set_cx86_memwb(void)
+ /* set 'Not Write-through' */
+ write_cr0(read_cr0() | X86_CR0_NW);
+ /* CCR2 bit 2: lock NW bit and set WT1 */
+- setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x14 );
++ setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x14);
+ }
+
+ static void __cpuinit set_cx86_inc(void)
+@@ -148,7 +147,7 @@ static void __cpuinit set_cx86_inc(void)
+ setCx86(CX86_PCR1, getCx86(CX86_PCR1) | 0x02);
+ /* PCR0 -- Performance Control */
+ /* Incrementor Margin 10 */
+- setCx86(CX86_PCR0, getCx86(CX86_PCR0) | 0x04);
++ setCx86(CX86_PCR0, getCx86(CX86_PCR0) | 0x04);
+ setCx86(CX86_CCR3, ccr3); /* disable MAPEN */
+ }
+
+@@ -167,16 +166,16 @@ static void __cpuinit geode_configure(void)
+
+ ccr3 = getCx86(CX86_CCR3);
+ setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */
+-
++
+
+ /* FPU fast, DTE cache, Mem bypass */
+ setCx86(CX86_CCR4, getCx86(CX86_CCR4) | 0x38);
+ setCx86(CX86_CCR3, ccr3); /* disable MAPEN */
+-
++
+ set_cx86_memwb();
+- set_cx86_reorder();
++ set_cx86_reorder();
+ set_cx86_inc();
+-
++
+ local_irq_restore(flags);
+ }
+
+@@ -187,14 +186,16 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
+ char *buf = c->x86_model_id;
+ const char *p = NULL;
+
+- /* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
+- 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
+- clear_bit(0*32+31, c->x86_capability);
++ /*
++ * Bit 31 in normal CPUID used for nonstandard 3DNow ID;
++ * 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway
++ */
++ clear_cpu_cap(c, 0*32+31);
+
+ /* Cyrix used bit 24 in extended (AMD) CPUID for Cyrix MMX extensions */
+- if ( test_bit(1*32+24, c->x86_capability) ) {
+- clear_bit(1*32+24, c->x86_capability);
+- set_bit(X86_FEATURE_CXMMX, c->x86_capability);
++ if (test_cpu_cap(c, 1*32+24)) {
++ clear_cpu_cap(c, 1*32+24);
++ set_cpu_cap(c, X86_FEATURE_CXMMX);
+ }
+
+ do_cyrix_devid(&dir0, &dir1);
+@@ -213,7 +214,7 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
+ * the model, multiplier and stepping. Black magic included,
+ * to make the silicon step/rev numbers match the printed ones.
+ */
+-
++
+ switch (dir0_msn) {
+ unsigned char tmp;
+
+@@ -241,7 +242,7 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
+ } else /* 686 */
+ p = Cx86_cb+1;
+ /* Emulate MTRRs using Cyrix's ARRs. */
+- set_bit(X86_FEATURE_CYRIX_ARR, c->x86_capability);
++ set_cpu_cap(c, X86_FEATURE_CYRIX_ARR);
+ /* 6x86's contain this bug */
+ c->coma_bug = 1;
+ break;
+@@ -250,17 +251,18 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
+ #ifdef CONFIG_PCI
+ {
+ u32 vendor, device;
+- /* It isn't really a PCI quirk directly, but the cure is the
+- same. The MediaGX has deep magic SMM stuff that handles the
+- SB emulation. It throws away the fifo on disable_dma() which
+- is wrong and ruins the audio.
+-
+- Bug2: VSA1 has a wrap bug so that using maximum sized DMA
+- causes bad things. According to NatSemi VSA2 has another
+- bug to do with 'hlt'. I've not seen any boards using VSA2
+- and X doesn't seem to support it either so who cares 8).
+- VSA1 we work around however.
+- */
++ /*
++ * It isn't really a PCI quirk directly, but the cure is the
++ * same. The MediaGX has deep magic SMM stuff that handles the
++ * SB emulation. It throws away the fifo on disable_dma() which
++ * is wrong and ruins the audio.
++ *
++ * Bug2: VSA1 has a wrap bug so that using maximum sized DMA
++ * causes bad things. According to NatSemi VSA2 has another
++ * bug to do with 'hlt'. I've not seen any boards using VSA2
++ * and X doesn't seem to support it either so who cares 8).
++ * VSA1 we work around however.
++ */
+
+ printk(KERN_INFO "Working around Cyrix MediaGX virtual DMA bugs.\n");
+ isa_dma_bridge_buggy = 2;
+@@ -273,55 +275,51 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
+
+ /*
+ * The 5510/5520 companion chips have a funky PIT.
+- */
++ */
+ if (vendor == PCI_VENDOR_ID_CYRIX &&
+ (device == PCI_DEVICE_ID_CYRIX_5510 || device == PCI_DEVICE_ID_CYRIX_5520))
+ mark_tsc_unstable("cyrix 5510/5520 detected");
+ }
+ #endif
+- c->x86_cache_size=16; /* Yep 16K integrated cache thats it */
++ c->x86_cache_size = 16; /* Yep 16K integrated cache thats it */
+
+ /* GXm supports extended cpuid levels 'ala' AMD */
+ if (c->cpuid_level == 2) {
+ /* Enable cxMMX extensions (GX1 Datasheet 54) */
+ setCx86(CX86_CCR7, getCx86(CX86_CCR7) | 1);
+-
++
+ /*
+ * GXm : 0x30 ... 0x5f GXm datasheet 51
+ * GXlv: 0x6x GXlv datasheet 54
+ * ? : 0x7x
+ * GX1 : 0x8x GX1 datasheet 56
+ */
+- if((0x30 <= dir1 && dir1 <= 0x6f) || (0x80 <=dir1 && dir1 <= 0x8f))
++ if ((0x30 <= dir1 && dir1 <= 0x6f) || (0x80 <= dir1 && dir1 <= 0x8f))
+ geode_configure();
+ get_model_name(c); /* get CPU marketing name */
+ return;
+- }
+- else { /* MediaGX */
++ } else { /* MediaGX */
+ Cx86_cb[2] = (dir0_lsn & 1) ? '3' : '4';
+ p = Cx86_cb+2;
+ c->x86_model = (dir1 & 0x20) ? 1 : 2;
+ }
+ break;
+
+- case 5: /* 6x86MX/M II */
+- if (dir1 > 7)
+- {
++ case 5: /* 6x86MX/M II */
++ if (dir1 > 7) {
+ dir0_msn++; /* M II */
+ /* Enable MMX extensions (App note 108) */
+ setCx86(CX86_CCR7, getCx86(CX86_CCR7)|1);
+- }
+- else
+- {
++ } else {
+ c->coma_bug = 1; /* 6x86MX, it has the bug. */
+ }
+ tmp = (!(dir0_lsn & 7) || dir0_lsn & 1) ? 2 : 0;
+ Cx86_cb[tmp] = cyrix_model_mult2[dir0_lsn & 7];
+ p = Cx86_cb+tmp;
+- if (((dir1 & 0x0f) > 4) || ((dir1 & 0xf0) == 0x20))
++ if (((dir1 & 0x0f) > 4) || ((dir1 & 0xf0) == 0x20))
+ (c->x86_model)++;
+ /* Emulate MTRRs using Cyrix's ARRs. */
+- set_bit(X86_FEATURE_CYRIX_ARR, c->x86_capability);
++ set_cpu_cap(c, X86_FEATURE_CYRIX_ARR);
+ break;
+
+ case 0xf: /* Cyrix 486 without DEVID registers */
+@@ -343,7 +341,8 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
+ break;
+ }
+ strcpy(buf, Cx86_model[dir0_msn & 7]);
+- if (p) strcat(buf, p);
++ if (p)
++ strcat(buf, p);
+ return;
+ }
+
+@@ -352,7 +351,8 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
+ */
+ static void __cpuinit init_nsc(struct cpuinfo_x86 *c)
+ {
+- /* There may be GX1 processors in the wild that are branded
++ /*
++ * There may be GX1 processors in the wild that are branded
+ * NSC and not Cyrix.
+ *
+ * This function only handles the GX processor, and kicks every
+@@ -377,7 +377,7 @@ static void __cpuinit init_nsc(struct cpuinfo_x86 *c)
+ * by the fact that they preserve the flags across the division of 5/2.
+ * PII and PPro exhibit this behavior too, but they have cpuid available.
+ */
+-
++
+ /*
+ * Perform the Cyrix 5/2 test. A Cyrix won't change
+ * the flags, while other 486 chips will.
+@@ -398,27 +398,26 @@ static inline int test_cyrix_52div(void)
+ return (unsigned char) (test >> 8) == 0x02;
+ }
+
+-static void __cpuinit cyrix_identify(struct cpuinfo_x86 * c)
++static void __cpuinit cyrix_identify(struct cpuinfo_x86 *c)
+ {
+ /* Detect Cyrix with disabled CPUID */
+- if ( c->x86 == 4 && test_cyrix_52div() ) {
++ if (c->x86 == 4 && test_cyrix_52div()) {
+ unsigned char dir0, dir1;
+-
++
+ strcpy(c->x86_vendor_id, "CyrixInstead");
+- c->x86_vendor = X86_VENDOR_CYRIX;
+-
+- /* Actually enable cpuid on the older cyrix */
+-
+- /* Retrieve CPU revisions */
+-
++ c->x86_vendor = X86_VENDOR_CYRIX;
++
++ /* Actually enable cpuid on the older cyrix */
++
++ /* Retrieve CPU revisions */
++
+ do_cyrix_devid(&dir0, &dir1);
+
+- dir0>>=4;
+-
++ dir0 >>= 4;
++
+ /* Check it is an affected model */
+-
+- if (dir0 == 5 || dir0 == 3)
+- {
++
++ if (dir0 == 5 || dir0 == 3) {
+ unsigned char ccr3;
+ unsigned long flags;
+ printk(KERN_INFO "Enabling CPUID on Cyrix processor.\n");
+@@ -434,26 +433,17 @@ static void __cpuinit cyrix_identify(struct cpuinfo_x86 * c)
+
+ static struct cpu_dev cyrix_cpu_dev __cpuinitdata = {
+ .c_vendor = "Cyrix",
+- .c_ident = { "CyrixInstead" },
++ .c_ident = { "CyrixInstead" },
+ .c_init = init_cyrix,
+ .c_identify = cyrix_identify,
+ };
+
+-int __init cyrix_init_cpu(void)
+-{
+- cpu_devs[X86_VENDOR_CYRIX] = &cyrix_cpu_dev;
+- return 0;
+-}
++cpu_vendor_dev_register(X86_VENDOR_CYRIX, &cyrix_cpu_dev);
+
+ static struct cpu_dev nsc_cpu_dev __cpuinitdata = {
+ .c_vendor = "NSC",
+- .c_ident = { "Geode by NSC" },
++ .c_ident = { "Geode by NSC" },
+ .c_init = init_nsc,
+ };
+
+-int __init nsc_init_cpu(void)
+-{
+- cpu_devs[X86_VENDOR_NSC] = &nsc_cpu_dev;
+- return 0;
+-}
+-
++cpu_vendor_dev_register(X86_VENDOR_NSC, &nsc_cpu_dev);
+diff --git a/arch/x86/kernel/cpu/feature_names.c b/arch/x86/kernel/cpu/feature_names.c
+index ee975ac..e43ad4a 100644
+--- a/arch/x86/kernel/cpu/feature_names.c
++++ b/arch/x86/kernel/cpu/feature_names.c
+@@ -4,7 +4,7 @@
+ * This file must not contain any executable code.
+ */
+
+-#include "asm/cpufeature.h"
++#include <asm/cpufeature.h>
+
+ /*
+ * These flag bits must match the definitions in <asm/cpufeature.h>.
+diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
+index fae31ce..fe9224c 100644
+--- a/arch/x86/kernel/cpu/intel.c
++++ b/arch/x86/kernel/cpu/intel.c
+@@ -30,7 +30,7 @@
+ struct movsl_mask movsl_mask __read_mostly;
+ #endif
+
+-void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
++static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
+ {
+ /* Netburst reports 64 bytes clflush size, but does IO in 128 bytes */
+ if (c->x86 == 15 && c->x86_cache_alignment == 64)
+@@ -45,7 +45,7 @@ void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
+ *
+ * This is called before we do cpu ident work
+ */
+-
++
+ int __cpuinit ppro_with_ram_bug(void)
+ {
+ /* Uses data from early_cpu_detect now */
+@@ -58,7 +58,7 @@ int __cpuinit ppro_with_ram_bug(void)
+ }
+ return 0;
+ }
+-
++
+
+ /*
+ * P4 Xeon errata 037 workaround.
+@@ -69,7 +69,7 @@ static void __cpuinit Intel_errata_workarounds(struct cpuinfo_x86 *c)
+ unsigned long lo, hi;
+
+ if ((c->x86 == 15) && (c->x86_model == 1) && (c->x86_mask == 1)) {
+- rdmsr (MSR_IA32_MISC_ENABLE, lo, hi);
++ rdmsr(MSR_IA32_MISC_ENABLE, lo, hi);
+ if ((lo & (1<<9)) == 0) {
+ printk (KERN_INFO "CPU: C0 stepping P4 Xeon detected.\n");
+ printk (KERN_INFO "CPU: Disabling hardware prefetching (Errata 037)\n");
+@@ -127,10 +127,10 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+ */
+ c->f00f_bug = 0;
+ if (!paravirt_enabled() && c->x86 == 5) {
+- static int f00f_workaround_enabled = 0;
++ static int f00f_workaround_enabled;
+
+ c->f00f_bug = 1;
+- if ( !f00f_workaround_enabled ) {
++ if (!f00f_workaround_enabled) {
+ trap_init_f00f_bug();
+ printk(KERN_NOTICE "Intel Pentium with F0 0F bug - workaround enabled.\n");
+ f00f_workaround_enabled = 1;
+@@ -139,20 +139,22 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+ #endif
+
+ l2 = init_intel_cacheinfo(c);
+- if (c->cpuid_level > 9 ) {
++ if (c->cpuid_level > 9) {
+ unsigned eax = cpuid_eax(10);
+ /* Check for version and the number of counters */
+ if ((eax & 0xff) && (((eax>>8) & 0xff) > 1))
+- set_bit(X86_FEATURE_ARCH_PERFMON, c->x86_capability);
++ set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON);
+ }
+
+ /* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it until model 3 mask 3 */
+ if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633)
+- clear_bit(X86_FEATURE_SEP, c->x86_capability);
++ clear_cpu_cap(c, X86_FEATURE_SEP);
+
+- /* Names for the Pentium II/Celeron processors
+- detectable only by also checking the cache size.
+- Dixon is NOT a Celeron. */
++ /*
++ * Names for the Pentium II/Celeron processors
++ * detectable only by also checking the cache size.
++ * Dixon is NOT a Celeron.
++ */
+ if (c->x86 == 6) {
+ switch (c->x86_model) {
+ case 5:
+@@ -163,14 +165,14 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+ p = "Mobile Pentium II (Dixon)";
+ }
+ break;
+-
++
+ case 6:
+ if (l2 == 128)
+ p = "Celeron (Mendocino)";
+ else if (c->x86_mask == 0 || c->x86_mask == 5)
+ p = "Celeron-A";
+ break;
+-
++
+ case 8:
+ if (l2 == 128)
+ p = "Celeron (Coppermine)";
+@@ -178,9 +180,9 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+ }
+ }
+
+- if ( p )
++ if (p)
+ strcpy(c->x86_model_id, p);
+-
++
+ c->x86_max_cores = num_cpu_cores(c);
+
+ detect_ht(c);
+@@ -207,28 +209,29 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+ #endif
+
+ if (cpu_has_xmm2)
+- set_bit(X86_FEATURE_LFENCE_RDTSC, c->x86_capability);
++ set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
+ if (c->x86 == 15) {
+- set_bit(X86_FEATURE_P4, c->x86_capability);
++ set_cpu_cap(c, X86_FEATURE_P4);
+ }
+- if (c->x86 == 6)
+- set_bit(X86_FEATURE_P3, c->x86_capability);
++ if (c->x86 == 6)
++ set_cpu_cap(c, X86_FEATURE_P3);
+ if (cpu_has_ds) {
+ unsigned int l1;
+ rdmsr(MSR_IA32_MISC_ENABLE, l1, l2);
+ if (!(l1 & (1<<11)))
+- set_bit(X86_FEATURE_BTS, c->x86_capability);
++ set_cpu_cap(c, X86_FEATURE_BTS);
+ if (!(l1 & (1<<12)))
+- set_bit(X86_FEATURE_PEBS, c->x86_capability);
++ set_cpu_cap(c, X86_FEATURE_PEBS);
+ }
+
+ if (cpu_has_bts)
+ ds_init_intel(c);
+ }
+
+-static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 * c, unsigned int size)
++static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 *c, unsigned int size)
+ {
+- /* Intel PIII Tualatin. This comes in two flavours.
++ /*
++ * Intel PIII Tualatin. This comes in two flavours.
+ * One has 256kb of cache, the other 512. We have no way
+ * to determine which, so we use a boottime override
+ * for the 512kb model, and assume 256 otherwise.
+@@ -240,42 +243,42 @@ static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 * c, unsigned
+
+ static struct cpu_dev intel_cpu_dev __cpuinitdata = {
+ .c_vendor = "Intel",
+- .c_ident = { "GenuineIntel" },
++ .c_ident = { "GenuineIntel" },
+ .c_models = {
+- { .vendor = X86_VENDOR_INTEL, .family = 4, .model_names =
+- {
+- [0] = "486 DX-25/33",
+- [1] = "486 DX-50",
+- [2] = "486 SX",
+- [3] = "486 DX/2",
+- [4] = "486 SL",
+- [5] = "486 SX/2",
+- [7] = "486 DX/2-WB",
+- [8] = "486 DX/4",
++ { .vendor = X86_VENDOR_INTEL, .family = 4, .model_names =
++ {
++ [0] = "486 DX-25/33",
++ [1] = "486 DX-50",
++ [2] = "486 SX",
++ [3] = "486 DX/2",
++ [4] = "486 SL",
++ [5] = "486 SX/2",
++ [7] = "486 DX/2-WB",
++ [8] = "486 DX/4",
+ [9] = "486 DX/4-WB"
+ }
+ },
+ { .vendor = X86_VENDOR_INTEL, .family = 5, .model_names =
+- {
+- [0] = "Pentium 60/66 A-step",
+- [1] = "Pentium 60/66",
++ {
++ [0] = "Pentium 60/66 A-step",
++ [1] = "Pentium 60/66",
+ [2] = "Pentium 75 - 200",
+- [3] = "OverDrive PODP5V83",
++ [3] = "OverDrive PODP5V83",
+ [4] = "Pentium MMX",
+- [7] = "Mobile Pentium 75 - 200",
++ [7] = "Mobile Pentium 75 - 200",
+ [8] = "Mobile Pentium MMX"
+ }
+ },
+ { .vendor = X86_VENDOR_INTEL, .family = 6, .model_names =
+- {
++ {
+ [0] = "Pentium Pro A-step",
+- [1] = "Pentium Pro",
+- [3] = "Pentium II (Klamath)",
+- [4] = "Pentium II (Deschutes)",
+- [5] = "Pentium II (Deschutes)",
++ [1] = "Pentium Pro",
++ [3] = "Pentium II (Klamath)",
++ [4] = "Pentium II (Deschutes)",
++ [5] = "Pentium II (Deschutes)",
+ [6] = "Mobile Pentium II",
+- [7] = "Pentium III (Katmai)",
+- [8] = "Pentium III (Coppermine)",
++ [7] = "Pentium III (Katmai)",
++ [8] = "Pentium III (Coppermine)",
+ [10] = "Pentium III (Cascades)",
+ [11] = "Pentium III (Tualatin)",
+ }
+@@ -290,15 +293,12 @@ static struct cpu_dev intel_cpu_dev __cpuinitdata = {
+ }
+ },
+ },
++ .c_early_init = early_init_intel,
+ .c_init = init_intel,
+ .c_size_cache = intel_size_cache,
+ };
+
+-__init int intel_cpu_init(void)
+-{
+- cpu_devs[X86_VENDOR_INTEL] = &intel_cpu_dev;
+- return 0;
+-}
++cpu_vendor_dev_register(X86_VENDOR_INTEL, &intel_cpu_dev);
+
+ #ifndef CONFIG_X86_CMPXCHG
+ unsigned long cmpxchg_386_u8(volatile void *ptr, u8 old, u8 new)
+@@ -364,5 +364,5 @@ unsigned long long cmpxchg_486_u64(volatile void *ptr, u64 old, u64 new)
+ EXPORT_SYMBOL(cmpxchg_486_u64);
+ #endif
+
+-// arch_initcall(intel_cpu_init);
++/* arch_initcall(intel_cpu_init); */
+
+diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
+index 1b88986..26d615d 100644
+--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
++++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
+@@ -129,7 +129,7 @@ struct _cpuid4_info {
+ union _cpuid4_leaf_ebx ebx;
+ union _cpuid4_leaf_ecx ecx;
+ unsigned long size;
+- cpumask_t shared_cpu_map;
++ cpumask_t shared_cpu_map; /* future?: only cpus/node is needed */
+ };
+
+ unsigned short num_cache_leaves;
+@@ -451,8 +451,8 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
+ }
+
+ /* pointer to _cpuid4_info array (for each cache leaf) */
+-static struct _cpuid4_info *cpuid4_info[NR_CPUS];
+-#define CPUID4_INFO_IDX(x,y) (&((cpuid4_info[x])[y]))
++static DEFINE_PER_CPU(struct _cpuid4_info *, cpuid4_info);
++#define CPUID4_INFO_IDX(x, y) (&((per_cpu(cpuid4_info, x))[y]))
+
+ #ifdef CONFIG_SMP
+ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
+@@ -474,7 +474,7 @@ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
+ if (cpu_data(i).apicid >> index_msb ==
+ c->apicid >> index_msb) {
+ cpu_set(i, this_leaf->shared_cpu_map);
+- if (i != cpu && cpuid4_info[i]) {
++ if (i != cpu && per_cpu(cpuid4_info, i)) {
+ sibling_leaf = CPUID4_INFO_IDX(i, index);
+ cpu_set(cpu, sibling_leaf->shared_cpu_map);
+ }
+@@ -505,8 +505,8 @@ static void __cpuinit free_cache_attributes(unsigned int cpu)
+ for (i = 0; i < num_cache_leaves; i++)
+ cache_remove_shared_cpu_map(cpu, i);
+
+- kfree(cpuid4_info[cpu]);
+- cpuid4_info[cpu] = NULL;
++ kfree(per_cpu(cpuid4_info, cpu));
++ per_cpu(cpuid4_info, cpu) = NULL;
+ }
+
+ static int __cpuinit detect_cache_attributes(unsigned int cpu)
+@@ -519,13 +519,13 @@ static int __cpuinit detect_cache_attributes(unsigned int cpu)
+ if (num_cache_leaves == 0)
+ return -ENOENT;
+
+- cpuid4_info[cpu] = kzalloc(
++ per_cpu(cpuid4_info, cpu) = kzalloc(
+ sizeof(struct _cpuid4_info) * num_cache_leaves, GFP_KERNEL);
+- if (cpuid4_info[cpu] == NULL)
++ if (per_cpu(cpuid4_info, cpu) == NULL)
+ return -ENOMEM;
+
+ oldmask = current->cpus_allowed;
+- retval = set_cpus_allowed(current, cpumask_of_cpu(cpu));
++ retval = set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ if (retval)
+ goto out;
+
+@@ -542,12 +542,12 @@ static int __cpuinit detect_cache_attributes(unsigned int cpu)
+ }
+ cache_shared_cpu_map_setup(cpu, j);
+ }
+- set_cpus_allowed(current, oldmask);
++ set_cpus_allowed_ptr(current, &oldmask);
+
+ out:
+ if (retval) {
+- kfree(cpuid4_info[cpu]);
+- cpuid4_info[cpu] = NULL;
++ kfree(per_cpu(cpuid4_info, cpu));
++ per_cpu(cpuid4_info, cpu) = NULL;
+ }
+
+ return retval;
+@@ -561,7 +561,7 @@ out:
+ extern struct sysdev_class cpu_sysdev_class; /* from drivers/base/cpu.c */
+
+ /* pointer to kobject for cpuX/cache */
+-static struct kobject * cache_kobject[NR_CPUS];
++static DEFINE_PER_CPU(struct kobject *, cache_kobject);
+
+ struct _index_kobject {
+ struct kobject kobj;
+@@ -570,8 +570,8 @@ struct _index_kobject {
+ };
+
+ /* pointer to array of kobjects for cpuX/cache/indexY */
+-static struct _index_kobject *index_kobject[NR_CPUS];
+-#define INDEX_KOBJECT_PTR(x,y) (&((index_kobject[x])[y]))
++static DEFINE_PER_CPU(struct _index_kobject *, index_kobject);
++#define INDEX_KOBJECT_PTR(x, y) (&((per_cpu(index_kobject, x))[y]))
+
+ #define show_one_plus(file_name, object, val) \
+ static ssize_t show_##file_name \
+@@ -591,11 +591,32 @@ static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf)
+ return sprintf (buf, "%luK\n", this_leaf->size / 1024);
+ }
+
+-static ssize_t show_shared_cpu_map(struct _cpuid4_info *this_leaf, char *buf)
++static ssize_t show_shared_cpu_map_func(struct _cpuid4_info *this_leaf,
++ int type, char *buf)
+ {
+- char mask_str[NR_CPUS];
+- cpumask_scnprintf(mask_str, NR_CPUS, this_leaf->shared_cpu_map);
+- return sprintf(buf, "%s\n", mask_str);
++ ptrdiff_t len = PTR_ALIGN(buf + PAGE_SIZE - 1, PAGE_SIZE) - buf;
++ int n = 0;
++
++ if (len > 1) {
++ cpumask_t *mask = &this_leaf->shared_cpu_map;
++
++ n = type?
++ cpulist_scnprintf(buf, len-2, *mask):
++ cpumask_scnprintf(buf, len-2, *mask);
++ buf[n++] = '\n';
++ buf[n] = '\0';
++ }
++ return n;
++}
++
++static inline ssize_t show_shared_cpu_map(struct _cpuid4_info *leaf, char *buf)
++{
++ return show_shared_cpu_map_func(leaf, 0, buf);
++}
++
++static inline ssize_t show_shared_cpu_list(struct _cpuid4_info *leaf, char *buf)
++{
++ return show_shared_cpu_map_func(leaf, 1, buf);
+ }
+
+ static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf) {
+@@ -633,6 +654,7 @@ define_one_ro(ways_of_associativity);
+ define_one_ro(number_of_sets);
+ define_one_ro(size);
+ define_one_ro(shared_cpu_map);
++define_one_ro(shared_cpu_list);
+
+ static struct attribute * default_attrs[] = {
+ &type.attr,
+@@ -643,6 +665,7 @@ static struct attribute * default_attrs[] = {
+ &number_of_sets.attr,
+ &size.attr,
+ &shared_cpu_map.attr,
++ &shared_cpu_list.attr,
+ NULL
+ };
+
+@@ -684,10 +707,10 @@ static struct kobj_type ktype_percpu_entry = {
+
+ static void __cpuinit cpuid4_cache_sysfs_exit(unsigned int cpu)
+ {
+- kfree(cache_kobject[cpu]);
+- kfree(index_kobject[cpu]);
+- cache_kobject[cpu] = NULL;
+- index_kobject[cpu] = NULL;
++ kfree(per_cpu(cache_kobject, cpu));
++ kfree(per_cpu(index_kobject, cpu));
++ per_cpu(cache_kobject, cpu) = NULL;
++ per_cpu(index_kobject, cpu) = NULL;
+ free_cache_attributes(cpu);
+ }
+
+@@ -703,13 +726,14 @@ static int __cpuinit cpuid4_cache_sysfs_init(unsigned int cpu)
+ return err;
+
+ /* Allocate all required memory */
+- cache_kobject[cpu] = kzalloc(sizeof(struct kobject), GFP_KERNEL);
+- if (unlikely(cache_kobject[cpu] == NULL))
++ per_cpu(cache_kobject, cpu) =
++ kzalloc(sizeof(struct kobject), GFP_KERNEL);
++ if (unlikely(per_cpu(cache_kobject, cpu) == NULL))
+ goto err_out;
+
+- index_kobject[cpu] = kzalloc(
++ per_cpu(index_kobject, cpu) = kzalloc(
+ sizeof(struct _index_kobject ) * num_cache_leaves, GFP_KERNEL);
+- if (unlikely(index_kobject[cpu] == NULL))
++ if (unlikely(per_cpu(index_kobject, cpu) == NULL))
+ goto err_out;
+
+ return 0;
+@@ -733,7 +757,8 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
+ if (unlikely(retval < 0))
+ return retval;
+
+- retval = kobject_init_and_add(cache_kobject[cpu], &ktype_percpu_entry,
++ retval = kobject_init_and_add(per_cpu(cache_kobject, cpu),
++ &ktype_percpu_entry,
+ &sys_dev->kobj, "%s", "cache");
+ if (retval < 0) {
+ cpuid4_cache_sysfs_exit(cpu);
+@@ -745,13 +770,14 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
+ this_object->cpu = cpu;
+ this_object->index = i;
+ retval = kobject_init_and_add(&(this_object->kobj),
+- &ktype_cache, cache_kobject[cpu],
++ &ktype_cache,
++ per_cpu(cache_kobject, cpu),
+ "index%1lu", i);
+ if (unlikely(retval)) {
+ for (j = 0; j < i; j++) {
+ kobject_put(&(INDEX_KOBJECT_PTR(cpu,j)->kobj));
+ }
+- kobject_put(cache_kobject[cpu]);
++ kobject_put(per_cpu(cache_kobject, cpu));
+ cpuid4_cache_sysfs_exit(cpu);
+ break;
+ }
+@@ -760,7 +786,7 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
+ if (!retval)
+ cpu_set(cpu, cache_dev_map);
+
+- kobject_uevent(cache_kobject[cpu], KOBJ_ADD);
++ kobject_uevent(per_cpu(cache_kobject, cpu), KOBJ_ADD);
+ return retval;
+ }
+
+@@ -769,7 +795,7 @@ static void __cpuinit cache_remove_dev(struct sys_device * sys_dev)
+ unsigned int cpu = sys_dev->id;
+ unsigned long i;
+
+- if (cpuid4_info[cpu] == NULL)
++ if (per_cpu(cpuid4_info, cpu) == NULL)
+ return;
+ if (!cpu_isset(cpu, cache_dev_map))
+ return;
+@@ -777,7 +803,7 @@ static void __cpuinit cache_remove_dev(struct sys_device * sys_dev)
+
+ for (i = 0; i < num_cache_leaves; i++)
+ kobject_put(&(INDEX_KOBJECT_PTR(cpu,i)->kobj));
+- kobject_put(cache_kobject[cpu]);
++ kobject_put(per_cpu(cache_kobject, cpu));
+ cpuid4_cache_sysfs_exit(cpu);
+ }
+
+diff --git a/arch/x86/kernel/cpu/mcheck/mce_32.c b/arch/x86/kernel/cpu/mcheck/mce_32.c
+index a5182dc..774d87c 100644
+--- a/arch/x86/kernel/cpu/mcheck/mce_32.c
++++ b/arch/x86/kernel/cpu/mcheck/mce_32.c
+@@ -10,20 +10,20 @@
+ #include <linux/smp.h>
+ #include <linux/thread_info.h>
+
+-#include <asm/processor.h>
++#include <asm/processor.h>
+ #include <asm/system.h>
+ #include <asm/mce.h>
+
+ #include "mce.h"
+
+-int mce_disabled = 0;
++int mce_disabled;
+ int nr_mce_banks;
+
+ EXPORT_SYMBOL_GPL(nr_mce_banks); /* non-fatal.o */
+
+ /* Handle unconfigured int18 (should never happen) */
+-static void unexpected_machine_check(struct pt_regs * regs, long error_code)
+-{
++static void unexpected_machine_check(struct pt_regs *regs, long error_code)
++{
+ printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).\n", smp_processor_id());
+ }
+
+@@ -33,30 +33,30 @@ void (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_mac
+ /* This has to be run for each processor */
+ void mcheck_init(struct cpuinfo_x86 *c)
+ {
+- if (mce_disabled==1)
++ if (mce_disabled == 1)
+ return;
+
+ switch (c->x86_vendor) {
+- case X86_VENDOR_AMD:
+- amd_mcheck_init(c);
+- break;
+-
+- case X86_VENDOR_INTEL:
+- if (c->x86==5)
+- intel_p5_mcheck_init(c);
+- if (c->x86==6)
+- intel_p6_mcheck_init(c);
+- if (c->x86==15)
+- intel_p4_mcheck_init(c);
+- break;
+-
+- case X86_VENDOR_CENTAUR:
+- if (c->x86==5)
+- winchip_mcheck_init(c);
+- break;
+-
+- default:
+- break;
++ case X86_VENDOR_AMD:
++ amd_mcheck_init(c);
++ break;
++
++ case X86_VENDOR_INTEL:
++ if (c->x86 == 5)
++ intel_p5_mcheck_init(c);
++ if (c->x86 == 6)
++ intel_p6_mcheck_init(c);
++ if (c->x86 == 15)
++ intel_p4_mcheck_init(c);
++ break;
++
++ case X86_VENDOR_CENTAUR:
++ if (c->x86 == 5)
++ winchip_mcheck_init(c);
++ break;
++
++ default:
++ break;
+ }
+ }
+
+diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c
+index 9a699ed..e07e8c0 100644
+--- a/arch/x86/kernel/cpu/mcheck/mce_64.c
++++ b/arch/x86/kernel/cpu/mcheck/mce_64.c
+@@ -49,7 +49,7 @@ static int banks;
+ static unsigned long bank[NR_BANKS] = { [0 ... NR_BANKS-1] = ~0UL };
+ static unsigned long notify_user;
+ static int rip_msr;
+-static int mce_bootlog = 1;
++static int mce_bootlog = -1;
+ static atomic_t mce_events;
+
+ static char trigger[128];
+@@ -471,13 +471,15 @@ static void mce_init(void *dummy)
+ static void __cpuinit mce_cpu_quirks(struct cpuinfo_x86 *c)
+ {
+ /* This should be disabled by the BIOS, but isn't always */
+- if (c->x86_vendor == X86_VENDOR_AMD && c->x86 == 15) {
+- /* disable GART TBL walk error reporting, which trips off
+- incorrectly with the IOMMU & 3ware & Cerberus. */
+- clear_bit(10, &bank[4]);
+- /* Lots of broken BIOS around that don't clear them
+- by default and leave crap in there. Don't log. */
+- mce_bootlog = 0;
++ if (c->x86_vendor == X86_VENDOR_AMD) {
++ if(c->x86 == 15)
++ /* disable GART TBL walk error reporting, which trips off
++ incorrectly with the IOMMU & 3ware & Cerberus. */
++ clear_bit(10, &bank[4]);
++ if(c->x86 <= 17 && mce_bootlog < 0)
++ /* Lots of broken BIOS around that don't clear them
++ by default and leave crap in there. Don't log. */
++ mce_bootlog = 0;
+ }
+
+ }
+diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
+index 32671da..7c9a813 100644
+--- a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
++++ b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
+@@ -251,18 +251,18 @@ struct threshold_attr {
+ ssize_t(*store) (struct threshold_block *, const char *, size_t count);
+ };
+
+-static cpumask_t affinity_set(unsigned int cpu)
++static void affinity_set(unsigned int cpu, cpumask_t *oldmask,
++ cpumask_t *newmask)
+ {
+- cpumask_t oldmask = current->cpus_allowed;
+- cpumask_t newmask = CPU_MASK_NONE;
+- cpu_set(cpu, newmask);
+- set_cpus_allowed(current, newmask);
+- return oldmask;
++ *oldmask = current->cpus_allowed;
++ cpus_clear(*newmask);
++ cpu_set(cpu, *newmask);
++ set_cpus_allowed_ptr(current, newmask);
+ }
+
+-static void affinity_restore(cpumask_t oldmask)
++static void affinity_restore(const cpumask_t *oldmask)
+ {
+- set_cpus_allowed(current, oldmask);
++ set_cpus_allowed_ptr(current, oldmask);
+ }
+
+ #define SHOW_FIELDS(name) \
+@@ -277,15 +277,15 @@ static ssize_t store_interrupt_enable(struct threshold_block *b,
+ const char *buf, size_t count)
+ {
+ char *end;
+- cpumask_t oldmask;
++ cpumask_t oldmask, newmask;
+ unsigned long new = simple_strtoul(buf, &end, 0);
+ if (end == buf)
+ return -EINVAL;
+ b->interrupt_enable = !!new;
+
+- oldmask = affinity_set(b->cpu);
++ affinity_set(b->cpu, &oldmask, &newmask);
+ threshold_restart_bank(b, 0, 0);
+- affinity_restore(oldmask);
++ affinity_restore(&oldmask);
+
+ return end - buf;
+ }
+@@ -294,7 +294,7 @@ static ssize_t store_threshold_limit(struct threshold_block *b,
+ const char *buf, size_t count)
+ {
+ char *end;
+- cpumask_t oldmask;
++ cpumask_t oldmask, newmask;
+ u16 old;
+ unsigned long new = simple_strtoul(buf, &end, 0);
+ if (end == buf)
+@@ -306,9 +306,9 @@ static ssize_t store_threshold_limit(struct threshold_block *b,
+ old = b->threshold_limit;
+ b->threshold_limit = new;
+
+- oldmask = affinity_set(b->cpu);
++ affinity_set(b->cpu, &oldmask, &newmask);
+ threshold_restart_bank(b, 0, old);
+- affinity_restore(oldmask);
++ affinity_restore(&oldmask);
+
+ return end - buf;
+ }
+@@ -316,10 +316,10 @@ static ssize_t store_threshold_limit(struct threshold_block *b,
+ static ssize_t show_error_count(struct threshold_block *b, char *buf)
+ {
+ u32 high, low;
+- cpumask_t oldmask;
+- oldmask = affinity_set(b->cpu);
++ cpumask_t oldmask, newmask;
++ affinity_set(b->cpu, &oldmask, &newmask);
+ rdmsr(b->address, low, high);
+- affinity_restore(oldmask);
++ affinity_restore(&oldmask);
+ return sprintf(buf, "%x\n",
+ (high & 0xFFF) - (THRESHOLD_MAX - b->threshold_limit));
+ }
+@@ -327,10 +327,10 @@ static ssize_t show_error_count(struct threshold_block *b, char *buf)
+ static ssize_t store_error_count(struct threshold_block *b,
+ const char *buf, size_t count)
+ {
+- cpumask_t oldmask;
+- oldmask = affinity_set(b->cpu);
++ cpumask_t oldmask, newmask;
++ affinity_set(b->cpu, &oldmask, &newmask);
+ threshold_restart_bank(b, 1, 0);
+- affinity_restore(oldmask);
++ affinity_restore(&oldmask);
+ return 1;
+ }
+
+@@ -468,7 +468,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
+ {
+ int i, err = 0;
+ struct threshold_bank *b = NULL;
+- cpumask_t oldmask = CPU_MASK_NONE;
++ cpumask_t oldmask, newmask;
+ char name[32];
+
+ sprintf(name, "threshold_bank%i", bank);
+@@ -519,10 +519,10 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
+
+ per_cpu(threshold_banks, cpu)[bank] = b;
+
+- oldmask = affinity_set(cpu);
++ affinity_set(cpu, &oldmask, &newmask);
+ err = allocate_threshold_blocks(cpu, bank, 0,
+ MSR_IA32_MC0_MISC + bank * 4);
+- affinity_restore(oldmask);
++ affinity_restore(&oldmask);
+
+ if (err)
+ goto out_free;
+diff --git a/arch/x86/kernel/cpu/mcheck/non-fatal.c b/arch/x86/kernel/cpu/mcheck/non-fatal.c
+index bf39409..00ccb6c 100644
+--- a/arch/x86/kernel/cpu/mcheck/non-fatal.c
++++ b/arch/x86/kernel/cpu/mcheck/non-fatal.c
+@@ -16,7 +16,7 @@
+ #include <linux/smp.h>
+ #include <linux/module.h>
+
+-#include <asm/processor.h>
++#include <asm/processor.h>
+ #include <asm/system.h>
+ #include <asm/msr.h>
+
+@@ -26,23 +26,26 @@ static int firstbank;
+
+ #define MCE_RATE 15*HZ /* timer rate is 15s */
+
+-static void mce_checkregs (void *info)
++static void mce_checkregs(void *info)
+ {
+ u32 low, high;
+ int i;
+
+- for (i=firstbank; i<nr_mce_banks; i++) {
+- rdmsr (MSR_IA32_MC0_STATUS+i*4, low, high);
++ for (i = firstbank; i < nr_mce_banks; i++) {
++ rdmsr(MSR_IA32_MC0_STATUS+i*4, low, high);
+
+ if (high & (1<<31)) {
+ printk(KERN_INFO "MCE: The hardware reports a non "
+ "fatal, correctable incident occurred on "
+ "CPU %d.\n",
+ smp_processor_id());
+- printk (KERN_INFO "Bank %d: %08x%08x\n", i, high, low);
++ printk(KERN_INFO "Bank %d: %08x%08x\n", i, high, low);
+
+- /* Scrub the error so we don't pick it up in MCE_RATE seconds time. */
+- wrmsr (MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
++ /*
++ * Scrub the error so we don't pick it up in MCE_RATE
++ * seconds time.
++ */
++ wrmsr(MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
+
+ /* Serialize */
+ wmb();
+@@ -55,10 +58,10 @@ static void mce_work_fn(struct work_struct *work);
+ static DECLARE_DELAYED_WORK(mce_work, mce_work_fn);
+
+ static void mce_work_fn(struct work_struct *work)
+-{
++{
+ on_each_cpu(mce_checkregs, NULL, 1, 1);
+ schedule_delayed_work(&mce_work, round_jiffies_relative(MCE_RATE));
+-}
++}
+
+ static int __init init_nonfatal_mce_checker(void)
+ {
+diff --git a/arch/x86/kernel/cpu/mcheck/p5.c b/arch/x86/kernel/cpu/mcheck/p5.c
+index a18310a..bfa5817 100644
+--- a/arch/x86/kernel/cpu/mcheck/p5.c
++++ b/arch/x86/kernel/cpu/mcheck/p5.c
+@@ -9,20 +9,20 @@
+ #include <linux/interrupt.h>
+ #include <linux/smp.h>
+
+-#include <asm/processor.h>
++#include <asm/processor.h>
+ #include <asm/system.h>
+ #include <asm/msr.h>
+
+ #include "mce.h"
+
+ /* Machine check handler for Pentium class Intel */
+-static void pentium_machine_check(struct pt_regs * regs, long error_code)
++static void pentium_machine_check(struct pt_regs *regs, long error_code)
+ {
+ u32 loaddr, hi, lotype;
+ rdmsr(MSR_IA32_P5_MC_ADDR, loaddr, hi);
+ rdmsr(MSR_IA32_P5_MC_TYPE, lotype, hi);
+ printk(KERN_EMERG "CPU#%d: Machine Check Exception: 0x%8X (type 0x%8X).\n", smp_processor_id(), loaddr, lotype);
+- if(lotype&(1<<5))
++ if (lotype&(1<<5))
+ printk(KERN_EMERG "CPU#%d: Possible thermal failure (CPU on fire ?).\n", smp_processor_id());
+ add_taint(TAINT_MACHINE_CHECK);
+ }
+@@ -31,13 +31,13 @@ static void pentium_machine_check(struct pt_regs * regs, long error_code)
+ void intel_p5_mcheck_init(struct cpuinfo_x86 *c)
+ {
+ u32 l, h;
+-
++
+ /*Check for MCE support */
+- if( !cpu_has(c, X86_FEATURE_MCE) )
+- return;
++ if (!cpu_has(c, X86_FEATURE_MCE))
++ return;
+
+ /* Default P5 to off as its often misconnected */
+- if(mce_disabled != -1)
++ if (mce_disabled != -1)
+ return;
+ machine_check_vector = pentium_machine_check;
+ wmb();
+@@ -47,7 +47,7 @@ void intel_p5_mcheck_init(struct cpuinfo_x86 *c)
+ rdmsr(MSR_IA32_P5_MC_TYPE, l, h);
+ printk(KERN_INFO "Intel old style machine check architecture supported.\n");
+
+- /* Enable MCE */
++ /* Enable MCE */
+ set_in_cr4(X86_CR4_MCE);
+ printk(KERN_INFO "Intel old style machine check reporting enabled on CPU#%d.\n", smp_processor_id());
+ }
+diff --git a/arch/x86/kernel/cpu/mcheck/p6.c b/arch/x86/kernel/cpu/mcheck/p6.c
+index 7434260..62efc9c 100644
+--- a/arch/x86/kernel/cpu/mcheck/p6.c
++++ b/arch/x86/kernel/cpu/mcheck/p6.c
+@@ -9,23 +9,23 @@
+ #include <linux/interrupt.h>
+ #include <linux/smp.h>
+
+-#include <asm/processor.h>
++#include <asm/processor.h>
+ #include <asm/system.h>
+ #include <asm/msr.h>
+
+ #include "mce.h"
+
+ /* Machine Check Handler For PII/PIII */
+-static void intel_machine_check(struct pt_regs * regs, long error_code)
++static void intel_machine_check(struct pt_regs *regs, long error_code)
+ {
+- int recover=1;
++ int recover = 1;
+ u32 alow, ahigh, high, low;
+ u32 mcgstl, mcgsth;
+ int i;
+
+- rdmsr (MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
++ rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
+ if (mcgstl & (1<<0)) /* Recoverable ? */
+- recover=0;
++ recover = 0;
+
+ printk(KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n",
+ smp_processor_id(), mcgsth, mcgstl);
+@@ -55,30 +55,30 @@ static void intel_machine_check(struct pt_regs * regs, long error_code)
+ }
+
+ if (recover & 2)
+- panic ("CPU context corrupt");
++ panic("CPU context corrupt");
+ if (recover & 1)
+- panic ("Unable to continue");
++ panic("Unable to continue");
+
+- printk (KERN_EMERG "Attempting to continue.\n");
+- /*
+- * Do not clear the MSR_IA32_MCi_STATUS if the error is not
++ printk(KERN_EMERG "Attempting to continue.\n");
++ /*
++ * Do not clear the MSR_IA32_MCi_STATUS if the error is not
+ * recoverable/continuable.This will allow BIOS to look at the MSRs
+ * for errors if the OS could not log the error.
+ */
+- for (i=0; i<nr_mce_banks; i++) {
++ for (i = 0; i < nr_mce_banks; i++) {
+ unsigned int msr;
+ msr = MSR_IA32_MC0_STATUS+i*4;
+- rdmsr (msr,low, high);
++ rdmsr(msr, low, high);
+ if (high & (1<<31)) {
+ /* Clear it */
+- wrmsr (msr, 0UL, 0UL);
++ wrmsr(msr, 0UL, 0UL);
+ /* Serialize */
+ wmb();
+ add_taint(TAINT_MACHINE_CHECK);
+ }
+ }
+ mcgstl &= ~(1<<2);
+- wrmsr (MSR_IA32_MCG_STATUS,mcgstl, mcgsth);
++ wrmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
+ }
+
+ /* Set up machine check reporting for processors with Intel style MCE */
+@@ -86,21 +86,21 @@ void intel_p6_mcheck_init(struct cpuinfo_x86 *c)
+ {
+ u32 l, h;
+ int i;
+-
++
+ /* Check for MCE support */
+ if (!cpu_has(c, X86_FEATURE_MCE))
+ return;
+
+ /* Check for PPro style MCA */
+- if (!cpu_has(c, X86_FEATURE_MCA))
++ if (!cpu_has(c, X86_FEATURE_MCA))
+ return;
+
+ /* Ok machine check is available */
+ machine_check_vector = intel_machine_check;
+ wmb();
+
+- printk (KERN_INFO "Intel machine check architecture supported.\n");
+- rdmsr (MSR_IA32_MCG_CAP, l, h);
++ printk(KERN_INFO "Intel machine check architecture supported.\n");
++ rdmsr(MSR_IA32_MCG_CAP, l, h);
+ if (l & (1<<8)) /* Control register present ? */
+ wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
+ nr_mce_banks = l & 0xff;
+@@ -110,13 +110,13 @@ void intel_p6_mcheck_init(struct cpuinfo_x86 *c)
+ * - MC0_CTL should not be written
+ * - Status registers on all banks should be cleared on reset
+ */
+- for (i=1; i<nr_mce_banks; i++)
+- wrmsr (MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
++ for (i = 1; i < nr_mce_banks; i++)
++ wrmsr(MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
+
+- for (i=0; i<nr_mce_banks; i++)
+- wrmsr (MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
++ for (i = 0; i < nr_mce_banks; i++)
++ wrmsr(MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
+
+- set_in_cr4 (X86_CR4_MCE);
+- printk (KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n",
++ set_in_cr4(X86_CR4_MCE);
++ printk(KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n",
+ smp_processor_id());
+ }
+diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c
+index 9b7e01d..1f4cc48 100644
+--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
++++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c
+@@ -1,5 +1,4 @@
+ /*
+- * linux/arch/i386/kernel/cpu/mcheck/therm_throt.c
+ *
+ * Thermal throttle event support code (such as syslog messaging and rate
+ * limiting) that was factored out from x86_64 (mce_intel.c) and i386 (p4.c).
+diff --git a/arch/x86/kernel/cpu/mcheck/winchip.c b/arch/x86/kernel/cpu/mcheck/winchip.c
+index 3d428d5..f2be3e1 100644
+--- a/arch/x86/kernel/cpu/mcheck/winchip.c
++++ b/arch/x86/kernel/cpu/mcheck/winchip.c
+@@ -8,14 +8,14 @@
+ #include <linux/kernel.h>
+ #include <linux/interrupt.h>
+
+-#include <asm/processor.h>
++#include <asm/processor.h>
+ #include <asm/system.h>
+ #include <asm/msr.h>
+
+ #include "mce.h"
+
+ /* Machine check handler for WinChip C6 */
+-static void winchip_machine_check(struct pt_regs * regs, long error_code)
++static void winchip_machine_check(struct pt_regs *regs, long error_code)
+ {
+ printk(KERN_EMERG "CPU0: Machine Check Exception.\n");
+ add_taint(TAINT_MACHINE_CHECK);
+@@ -28,8 +28,8 @@ void winchip_mcheck_init(struct cpuinfo_x86 *c)
+ machine_check_vector = winchip_machine_check;
+ wmb();
+ rdmsr(MSR_IDT_FCR1, lo, hi);
+- lo|= (1<<2); /* Enable EIERRINT (int 18 MCE) */
+- lo&= ~(1<<4); /* Enable MCE */
++ lo |= (1<<2); /* Enable EIERRINT (int 18 MCE) */
++ lo &= ~(1<<4); /* Enable MCE */
+ wrmsr(MSR_IDT_FCR1, lo, hi);
+ set_in_cr4(X86_CR4_MCE);
+ printk(KERN_INFO "Winchip machine check reporting enabled on CPU#0.\n");
+diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
+index 3e18db4..353efe4 100644
+--- a/arch/x86/kernel/cpu/mtrr/generic.c
++++ b/arch/x86/kernel/cpu/mtrr/generic.c
+@@ -11,6 +11,7 @@
+ #include <asm/cpufeature.h>
+ #include <asm/processor-flags.h>
+ #include <asm/tlbflush.h>
++#include <asm/pat.h>
+ #include "mtrr.h"
+
+ struct mtrr_state {
+@@ -35,6 +36,8 @@ static struct fixed_range_block fixed_range_blocks[] = {
+
+ static unsigned long smp_changes_mask;
+ static struct mtrr_state mtrr_state = {};
++static int mtrr_state_set;
++static u64 tom2;
+
+ #undef MODULE_PARAM_PREFIX
+ #define MODULE_PARAM_PREFIX "mtrr."
+@@ -42,6 +45,111 @@ static struct mtrr_state mtrr_state = {};
+ static int mtrr_show;
+ module_param_named(show, mtrr_show, bool, 0);
+
++/*
++ * Returns the effective MTRR type for the region
++ * Error returns:
++ * - 0xFE - when the range is "not entirely covered" by _any_ var range MTRR
++ * - 0xFF - when MTRR is not enabled
++ */
++u8 mtrr_type_lookup(u64 start, u64 end)
++{
++ int i;
++ u64 base, mask;
++ u8 prev_match, curr_match;
++
++ if (!mtrr_state_set)
++ return 0xFF;
++
++ if (!mtrr_state.enabled)
++ return 0xFF;
++
++ /* Make end inclusive end, instead of exclusive */
++ end--;
++
++ /* Look in fixed ranges. Just return the type as per start */
++ if (mtrr_state.have_fixed && (start < 0x100000)) {
++ int idx;
++
++ if (start < 0x80000) {
++ idx = 0;
++ idx += (start >> 16);
++ return mtrr_state.fixed_ranges[idx];
++ } else if (start < 0xC0000) {
++ idx = 1 * 8;
++ idx += ((start - 0x80000) >> 14);
++ return mtrr_state.fixed_ranges[idx];
++ } else if (start < 0x1000000) {
++ idx = 3 * 8;
++ idx += ((start - 0xC0000) >> 12);
++ return mtrr_state.fixed_ranges[idx];
++ }
++ }
++
++ /*
++ * Look in variable ranges
++ * Look of multiple ranges matching this address and pick type
++ * as per MTRR precedence
++ */
++ if (!mtrr_state.enabled & 2) {
++ return mtrr_state.def_type;
++ }
++
++ prev_match = 0xFF;
++ for (i = 0; i < num_var_ranges; ++i) {
++ unsigned short start_state, end_state;
++
++ if (!(mtrr_state.var_ranges[i].mask_lo & (1 << 11)))
++ continue;
++
++ base = (((u64)mtrr_state.var_ranges[i].base_hi) << 32) +
++ (mtrr_state.var_ranges[i].base_lo & PAGE_MASK);
++ mask = (((u64)mtrr_state.var_ranges[i].mask_hi) << 32) +
++ (mtrr_state.var_ranges[i].mask_lo & PAGE_MASK);
++
++ start_state = ((start & mask) == (base & mask));
++ end_state = ((end & mask) == (base & mask));
++ if (start_state != end_state)
++ return 0xFE;
++
++ if ((start & mask) != (base & mask)) {
++ continue;
++ }
++
++ curr_match = mtrr_state.var_ranges[i].base_lo & 0xff;
++ if (prev_match == 0xFF) {
++ prev_match = curr_match;
++ continue;
++ }
++
++ if (prev_match == MTRR_TYPE_UNCACHABLE ||
++ curr_match == MTRR_TYPE_UNCACHABLE) {
++ return MTRR_TYPE_UNCACHABLE;
++ }
++
++ if ((prev_match == MTRR_TYPE_WRBACK &&
++ curr_match == MTRR_TYPE_WRTHROUGH) ||
++ (prev_match == MTRR_TYPE_WRTHROUGH &&
++ curr_match == MTRR_TYPE_WRBACK)) {
++ prev_match = MTRR_TYPE_WRTHROUGH;
++ curr_match = MTRR_TYPE_WRTHROUGH;
++ }
++
++ if (prev_match != curr_match) {
++ return MTRR_TYPE_UNCACHABLE;
++ }
++ }
++
++ if (tom2) {
++ if (start >= (1ULL<<32) && (end < tom2))
++ return MTRR_TYPE_WRBACK;
++ }
++
++ if (prev_match != 0xFF)
++ return prev_match;
++
++ return mtrr_state.def_type;
++}
++
+ /* Get the MSR pair relating to a var range */
+ static void
+ get_mtrr_var_range(unsigned int index, struct mtrr_var_range *vr)
+@@ -79,12 +187,16 @@ static void print_fixed(unsigned base, unsigned step, const mtrr_type*types)
+ base, base + step - 1, mtrr_attrib_to_str(*types));
+ }
+
++static void prepare_set(void);
++static void post_set(void);
++
+ /* Grab all of the MTRR state for this CPU into *state */
+ void __init get_mtrr_state(void)
+ {
+ unsigned int i;
+ struct mtrr_var_range *vrs;
+ unsigned lo, dummy;
++ unsigned long flags;
+
+ vrs = mtrr_state.var_ranges;
+
+@@ -100,6 +212,15 @@ void __init get_mtrr_state(void)
+ mtrr_state.def_type = (lo & 0xff);
+ mtrr_state.enabled = (lo & 0xc00) >> 10;
+
++ if (amd_special_default_mtrr()) {
++ unsigned lo, hi;
++ /* TOP_MEM2 */
++ rdmsr(MSR_K8_TOP_MEM2, lo, hi);
++ tom2 = hi;
++ tom2 <<= 32;
++ tom2 |= lo;
++ tom2 &= 0xffffff8000000ULL;
++ }
+ if (mtrr_show) {
+ int high_width;
+
+@@ -130,7 +251,22 @@ void __init get_mtrr_state(void)
+ else
+ printk(KERN_INFO "MTRR %u disabled\n", i);
+ }
++ if (tom2) {
++ printk(KERN_INFO "TOM2: %016llx aka %lldM\n",
++ tom2, tom2>>20);
++ }
+ }
++ mtrr_state_set = 1;
++
++ /* PAT setup for BP. We need to go through sync steps here */
++ local_irq_save(flags);
++ prepare_set();
++
++ pat_init();
++
++ post_set();
++ local_irq_restore(flags);
++
+ }
+
+ /* Some BIOS's are fucked and don't set all MTRRs the same! */
+@@ -397,6 +533,9 @@ static void generic_set_all(void)
+ /* Actually set the state */
+ mask = set_mtrr_state();
+
++ /* also set PAT */
++ pat_init();
++
+ post_set();
+ local_irq_restore(flags);
+
+diff --git a/arch/x86/kernel/cpu/mtrr/if.c b/arch/x86/kernel/cpu/mtrr/if.c
+index 91e150a..1960f19 100644
+--- a/arch/x86/kernel/cpu/mtrr/if.c
++++ b/arch/x86/kernel/cpu/mtrr/if.c
+@@ -424,11 +424,10 @@ static int __init mtrr_if_init(void)
+ return -ENODEV;
+
+ proc_root_mtrr =
+- create_proc_entry("mtrr", S_IWUSR | S_IRUGO, &proc_root);
+- if (proc_root_mtrr) {
++ proc_create("mtrr", S_IWUSR | S_IRUGO, &proc_root, &mtrr_fops);
++
++ if (proc_root_mtrr)
+ proc_root_mtrr->owner = THIS_MODULE;
+- proc_root_mtrr->proc_fops = &mtrr_fops;
+- }
+ return 0;
+ }
+
+diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c
+index a6450b3..6a1e278 100644
+--- a/arch/x86/kernel/cpu/mtrr/main.c
++++ b/arch/x86/kernel/cpu/mtrr/main.c
+@@ -627,7 +627,7 @@ early_param("disable_mtrr_trim", disable_mtrr_trim_setup);
+ #define Tom2Enabled (1U << 21)
+ #define Tom2ForceMemTypeWB (1U << 22)
+
+-static __init int amd_special_default_mtrr(void)
++int __init amd_special_default_mtrr(void)
+ {
+ u32 l, h;
+
+diff --git a/arch/x86/kernel/cpu/mtrr/state.c b/arch/x86/kernel/cpu/mtrr/state.c
+index 9f8ba92..7f7e275 100644
+--- a/arch/x86/kernel/cpu/mtrr/state.c
++++ b/arch/x86/kernel/cpu/mtrr/state.c
+@@ -19,13 +19,15 @@ void set_mtrr_prepare_save(struct set_mtrr_context *ctxt)
+ if (use_intel() || is_cpu(CYRIX)) {
+
+ /* Save value of CR4 and clear Page Global Enable (bit 7) */
+- if ( cpu_has_pge ) {
++ if (cpu_has_pge) {
+ ctxt->cr4val = read_cr4();
+ write_cr4(ctxt->cr4val & ~X86_CR4_PGE);
+ }
+
+- /* Disable and flush caches. Note that wbinvd flushes the TLBs as
+- a side-effect */
++ /*
++ * Disable and flush caches. Note that wbinvd flushes the TLBs
++ * as a side-effect
++ */
+ cr0 = read_cr0() | X86_CR0_CD;
+ wbinvd();
+ write_cr0(cr0);
+@@ -42,7 +44,7 @@ void set_mtrr_prepare_save(struct set_mtrr_context *ctxt)
+
+ void set_mtrr_cache_disable(struct set_mtrr_context *ctxt)
+ {
+- if (use_intel())
++ if (use_intel())
+ /* Disable MTRRs, and set the default type to uncached */
+ mtrr_wrmsr(MTRRdefType_MSR, ctxt->deftype_lo & 0xf300UL,
+ ctxt->deftype_hi);
+@@ -66,12 +68,12 @@ void set_mtrr_done(struct set_mtrr_context *ctxt)
+ else
+ /* Cyrix ARRs - everything else was excluded at the top */
+ setCx86(CX86_CCR3, ctxt->ccr3);
+-
++
+ /* Enable caches */
+ write_cr0(read_cr0() & 0xbfffffff);
+
+ /* Restore value of CR4 */
+- if ( cpu_has_pge )
++ if (cpu_has_pge)
+ write_cr4(ctxt->cr4val);
+ }
+ /* Re-enable interrupts locally (if enabled previously) */
+diff --git a/arch/x86/kernel/cpu/nexgen.c b/arch/x86/kernel/cpu/nexgen.c
+deleted file mode 100644
+index 961fbe1..0000000
+--- a/arch/x86/kernel/cpu/nexgen.c
++++ /dev/null
+@@ -1,60 +0,0 @@
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/string.h>
+-#include <asm/processor.h>
+-
+-#include "cpu.h"
+-
+-/*
+- * Detect a NexGen CPU running without BIOS hypercode new enough
+- * to have CPUID. (Thanks to Herbert Oppmann)
+- */
+-
+-static int __cpuinit deep_magic_nexgen_probe(void)
+-{
+- int ret;
+-
+- __asm__ __volatile__ (
+- " movw $0x5555, %%ax\n"
+- " xorw %%dx,%%dx\n"
+- " movw $2, %%cx\n"
+- " divw %%cx\n"
+- " movl $0, %%eax\n"
+- " jnz 1f\n"
+- " movl $1, %%eax\n"
+- "1:\n"
+- : "=a" (ret) : : "cx", "dx" );
+- return ret;
+-}
+-
+-static void __cpuinit init_nexgen(struct cpuinfo_x86 * c)
+-{
+- c->x86_cache_size = 256; /* A few had 1 MB... */
+-}
+-
+-static void __cpuinit nexgen_identify(struct cpuinfo_x86 * c)
+-{
+- /* Detect NexGen with old hypercode */
+- if ( deep_magic_nexgen_probe() ) {
+- strcpy(c->x86_vendor_id, "NexGenDriven");
+- }
+-}
+-
+-static struct cpu_dev nexgen_cpu_dev __cpuinitdata = {
+- .c_vendor = "Nexgen",
+- .c_ident = { "NexGenDriven" },
+- .c_models = {
+- { .vendor = X86_VENDOR_NEXGEN,
+- .family = 5,
+- .model_names = { [1] = "Nx586" }
+- },
+- },
+- .c_init = init_nexgen,
+- .c_identify = nexgen_identify,
+-};
+-
+-int __init nexgen_init_cpu(void)
+-{
+- cpu_devs[X86_VENDOR_NEXGEN] = &nexgen_cpu_dev;
+- return 0;
+-}
+diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c
+index b943e10..f9ae93a 100644
+--- a/arch/x86/kernel/cpu/perfctr-watchdog.c
++++ b/arch/x86/kernel/cpu/perfctr-watchdog.c
+@@ -614,16 +614,6 @@ static struct wd_ops intel_arch_wd_ops __read_mostly = {
+ .evntsel = MSR_ARCH_PERFMON_EVENTSEL1,
+ };
+
+-static struct wd_ops coreduo_wd_ops = {
+- .reserve = single_msr_reserve,
+- .unreserve = single_msr_unreserve,
+- .setup = setup_intel_arch_watchdog,
+- .rearm = p6_rearm,
+- .stop = single_msr_stop_watchdog,
+- .perfctr = MSR_ARCH_PERFMON_PERFCTR0,
+- .evntsel = MSR_ARCH_PERFMON_EVENTSEL0,
+-};
+-
+ static void probe_nmi_watchdog(void)
+ {
+ switch (boot_cpu_data.x86_vendor) {
+@@ -637,8 +627,8 @@ static void probe_nmi_watchdog(void)
+ /* Work around Core Duo (Yonah) errata AE49 where perfctr1
+ doesn't have a working enable bit. */
+ if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 14) {
+- wd_ops = &coreduo_wd_ops;
+- break;
++ intel_arch_wd_ops.perfctr = MSR_ARCH_PERFMON_PERFCTR0;
++ intel_arch_wd_ops.evntsel = MSR_ARCH_PERFMON_EVENTSEL0;
+ }
+ if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
+ wd_ops = &intel_arch_wd_ops;
+diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c
+index af11d31..0d0d905 100644
+--- a/arch/x86/kernel/cpu/proc.c
++++ b/arch/x86/kernel/cpu/proc.c
+@@ -1,85 +1,145 @@
+ #include <linux/smp.h>
+ #include <linux/timex.h>
+ #include <linux/string.h>
+-#include <asm/semaphore.h>
+ #include <linux/seq_file.h>
+ #include <linux/cpufreq.h>
+
+ /*
+ * Get CPU information for use by the procfs.
+ */
++#ifdef CONFIG_X86_32
++static void show_cpuinfo_core(struct seq_file *m, struct cpuinfo_x86 *c,
++ unsigned int cpu)
++{
++#ifdef CONFIG_X86_HT
++ if (c->x86_max_cores * smp_num_siblings > 1) {
++ seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
++ seq_printf(m, "siblings\t: %d\n",
++ cpus_weight(per_cpu(cpu_core_map, cpu)));
++ seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
++ seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
++ seq_printf(m, "apicid\t\t: %d\n", c->apicid);
++ seq_printf(m, "initial apicid\t: %d\n", c->initial_apicid);
++ }
++#endif
++}
++
++static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c)
++{
++ /*
++ * We use exception 16 if we have hardware math and we've either seen
++ * it or the CPU claims it is internal
++ */
++ int fpu_exception = c->hard_math && (ignore_fpu_irq || cpu_has_fpu);
++ seq_printf(m,
++ "fdiv_bug\t: %s\n"
++ "hlt_bug\t\t: %s\n"
++ "f00f_bug\t: %s\n"
++ "coma_bug\t: %s\n"
++ "fpu\t\t: %s\n"
++ "fpu_exception\t: %s\n"
++ "cpuid level\t: %d\n"
++ "wp\t\t: %s\n",
++ c->fdiv_bug ? "yes" : "no",
++ c->hlt_works_ok ? "no" : "yes",
++ c->f00f_bug ? "yes" : "no",
++ c->coma_bug ? "yes" : "no",
++ c->hard_math ? "yes" : "no",
++ fpu_exception ? "yes" : "no",
++ c->cpuid_level,
++ c->wp_works_ok ? "yes" : "no");
++}
++#else
++static void show_cpuinfo_core(struct seq_file *m, struct cpuinfo_x86 *c,
++ unsigned int cpu)
++{
++#ifdef CONFIG_SMP
++ if (c->x86_max_cores * smp_num_siblings > 1) {
++ seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
++ seq_printf(m, "siblings\t: %d\n",
++ cpus_weight(per_cpu(cpu_core_map, cpu)));
++ seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
++ seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
++ seq_printf(m, "apicid\t\t: %d\n", c->apicid);
++ seq_printf(m, "initial apicid\t: %d\n", c->initial_apicid);
++ }
++#endif
++}
++
++static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c)
++{
++ seq_printf(m,
++ "fpu\t\t: yes\n"
++ "fpu_exception\t: yes\n"
++ "cpuid level\t: %d\n"
++ "wp\t\t: yes\n",
++ c->cpuid_level);
++}
++#endif
++
+ static int show_cpuinfo(struct seq_file *m, void *v)
+ {
+ struct cpuinfo_x86 *c = v;
+- int i, n = 0;
+- int fpu_exception;
++ unsigned int cpu = 0;
++ int i;
+
+ #ifdef CONFIG_SMP
+- n = c->cpu_index;
++ cpu = c->cpu_index;
+ #endif
+- seq_printf(m, "processor\t: %d\n"
+- "vendor_id\t: %s\n"
+- "cpu family\t: %d\n"
+- "model\t\t: %d\n"
+- "model name\t: %s\n",
+- n,
+- c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
+- c->x86,
+- c->x86_model,
+- c->x86_model_id[0] ? c->x86_model_id : "unknown");
++ seq_printf(m, "processor\t: %u\n"
++ "vendor_id\t: %s\n"
++ "cpu family\t: %d\n"
++ "model\t\t: %u\n"
++ "model name\t: %s\n",
++ cpu,
++ c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
++ c->x86,
++ c->x86_model,
++ c->x86_model_id[0] ? c->x86_model_id : "unknown");
+
+ if (c->x86_mask || c->cpuid_level >= 0)
+ seq_printf(m, "stepping\t: %d\n", c->x86_mask);
+ else
+ seq_printf(m, "stepping\t: unknown\n");
+
+- if ( cpu_has(c, X86_FEATURE_TSC) ) {
+- unsigned int freq = cpufreq_quick_get(n);
++ if (cpu_has(c, X86_FEATURE_TSC)) {
++ unsigned int freq = cpufreq_quick_get(cpu);
++
+ if (!freq)
+ freq = cpu_khz;
+ seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
+- freq / 1000, (freq % 1000));
++ freq / 1000, (freq % 1000));
+ }
+
+ /* Cache size */
+ if (c->x86_cache_size >= 0)
+ seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
+-#ifdef CONFIG_X86_HT
+- if (c->x86_max_cores * smp_num_siblings > 1) {
+- seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
+- seq_printf(m, "siblings\t: %d\n",
+- cpus_weight(per_cpu(cpu_core_map, n)));
+- seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
+- seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
+- }
+-#endif
+-
+- /* We use exception 16 if we have hardware math and we've either seen it or the CPU claims it is internal */
+- fpu_exception = c->hard_math && (ignore_fpu_irq || cpu_has_fpu);
+- seq_printf(m, "fdiv_bug\t: %s\n"
+- "hlt_bug\t\t: %s\n"
+- "f00f_bug\t: %s\n"
+- "coma_bug\t: %s\n"
+- "fpu\t\t: %s\n"
+- "fpu_exception\t: %s\n"
+- "cpuid level\t: %d\n"
+- "wp\t\t: %s\n"
+- "flags\t\t:",
+- c->fdiv_bug ? "yes" : "no",
+- c->hlt_works_ok ? "no" : "yes",
+- c->f00f_bug ? "yes" : "no",
+- c->coma_bug ? "yes" : "no",
+- c->hard_math ? "yes" : "no",
+- fpu_exception ? "yes" : "no",
+- c->cpuid_level,
+- c->wp_works_ok ? "yes" : "no");
+-
+- for ( i = 0 ; i < 32*NCAPINTS ; i++ )
+- if ( test_bit(i, c->x86_capability) &&
+- x86_cap_flags[i] != NULL )
++
++ show_cpuinfo_core(m, c, cpu);
++ show_cpuinfo_misc(m, c);
++
++ seq_printf(m, "flags\t\t:");
++ for (i = 0; i < 32*NCAPINTS; i++)
++ if (cpu_has(c, i) && x86_cap_flags[i] != NULL)
+ seq_printf(m, " %s", x86_cap_flags[i]);
+
+- for (i = 0; i < 32; i++)
++ seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
++ c->loops_per_jiffy/(500000/HZ),
++ (c->loops_per_jiffy/(5000/HZ)) % 100);
++
++#ifdef CONFIG_X86_64
++ if (c->x86_tlbsize > 0)
++ seq_printf(m, "TLB size\t: %d 4K pages\n", c->x86_tlbsize);
++#endif
++ seq_printf(m, "clflush size\t: %u\n", c->x86_clflush_size);
++#ifdef CONFIG_X86_64
++ seq_printf(m, "cache_alignment\t: %d\n", c->x86_cache_alignment);
++ seq_printf(m, "address sizes\t: %u bits physical, %u bits virtual\n",
++ c->x86_phys_bits, c->x86_virt_bits);
++#endif
++
++ seq_printf(m, "power management:");
++ for (i = 0; i < 32; i++) {
+ if (c->x86_power & (1 << i)) {
+ if (i < ARRAY_SIZE(x86_power_flags) &&
+ x86_power_flags[i])
+@@ -89,11 +149,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
+ else
+ seq_printf(m, " [%d]", i);
+ }
++ }
+
+- seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
+- c->loops_per_jiffy/(500000/HZ),
+- (c->loops_per_jiffy/(5000/HZ)) % 100);
+- seq_printf(m, "clflush size\t: %u\n\n", c->x86_clflush_size);
++ seq_printf(m, "\n\n");
+
+ return 0;
+ }
+@@ -106,14 +164,17 @@ static void *c_start(struct seq_file *m, loff_t *pos)
+ return &cpu_data(*pos);
+ return NULL;
+ }
++
+ static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+ {
+ *pos = next_cpu(*pos, cpu_online_map);
+ return c_start(m, pos);
+ }
++
+ static void c_stop(struct seq_file *m, void *v)
+ {
+ }
++
+ const struct seq_operations cpuinfo_op = {
+ .start = c_start,
+ .next = c_next,
+diff --git a/arch/x86/kernel/cpu/transmeta.c b/arch/x86/kernel/cpu/transmeta.c
+index e8b422c..b911a2c 100644
+--- a/arch/x86/kernel/cpu/transmeta.c
++++ b/arch/x86/kernel/cpu/transmeta.c
+@@ -18,8 +18,8 @@ static void __cpuinit init_transmeta(struct cpuinfo_x86 *c)
+ /* Print CMS and CPU revision */
+ max = cpuid_eax(0x80860000);
+ cpu_rev = 0;
+- if ( max >= 0x80860001 ) {
+- cpuid(0x80860001, &dummy, &cpu_rev, &cpu_freq, &cpu_flags);
++ if (max >= 0x80860001) {
++ cpuid(0x80860001, &dummy, &cpu_rev, &cpu_freq, &cpu_flags);
+ if (cpu_rev != 0x02000000) {
+ printk(KERN_INFO "CPU: Processor revision %u.%u.%u.%u, %u MHz\n",
+ (cpu_rev >> 24) & 0xff,
+@@ -29,7 +29,7 @@ static void __cpuinit init_transmeta(struct cpuinfo_x86 *c)
+ cpu_freq);
+ }
+ }
+- if ( max >= 0x80860002 ) {
++ if (max >= 0x80860002) {
+ cpuid(0x80860002, &new_cpu_rev, &cms_rev1, &cms_rev2, &dummy);
+ if (cpu_rev == 0x02000000) {
+ printk(KERN_INFO "CPU: Processor revision %08X, %u MHz\n",
+@@ -42,7 +42,7 @@ static void __cpuinit init_transmeta(struct cpuinfo_x86 *c)
+ cms_rev1 & 0xff,
+ cms_rev2);
+ }
+- if ( max >= 0x80860006 ) {
++ if (max >= 0x80860006) {
+ cpuid(0x80860003,
+ (void *)&cpu_info[0],
+ (void *)&cpu_info[4],
+@@ -74,23 +74,25 @@ static void __cpuinit init_transmeta(struct cpuinfo_x86 *c)
+ wrmsr(0x80860004, cap_mask, uk);
+
+ /* All Transmeta CPUs have a constant TSC */
+- set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability);
+-
++ set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
++
+ #ifdef CONFIG_SYSCTL
+- /* randomize_va_space slows us down enormously;
+- it probably triggers retranslation of x86->native bytecode */
++ /*
++ * randomize_va_space slows us down enormously;
++ * it probably triggers retranslation of x86->native bytecode
++ */
+ randomize_va_space = 0;
+ #endif
+ }
+
+-static void __cpuinit transmeta_identify(struct cpuinfo_x86 * c)
++static void __cpuinit transmeta_identify(struct cpuinfo_x86 *c)
+ {
+ u32 xlvl;
+
+ /* Transmeta-defined flags: level 0x80860001 */
+ xlvl = cpuid_eax(0x80860000);
+- if ( (xlvl & 0xffff0000) == 0x80860000 ) {
+- if ( xlvl >= 0x80860001 )
++ if ((xlvl & 0xffff0000) == 0x80860000) {
++ if (xlvl >= 0x80860001)
+ c->x86_capability[2] = cpuid_edx(0x80860001);
+ }
+ }
+@@ -102,8 +104,4 @@ static struct cpu_dev transmeta_cpu_dev __cpuinitdata = {
+ .c_identify = transmeta_identify,
+ };
+
+-int __init transmeta_init_cpu(void)
+-{
+- cpu_devs[X86_VENDOR_TRANSMETA] = &transmeta_cpu_dev;
+- return 0;
+-}
++cpu_vendor_dev_register(X86_VENDOR_TRANSMETA, &transmeta_cpu_dev);
+diff --git a/arch/x86/kernel/cpu/umc.c b/arch/x86/kernel/cpu/umc.c
+index a7a4e75..b1fc909 100644
+--- a/arch/x86/kernel/cpu/umc.c
++++ b/arch/x86/kernel/cpu/umc.c
+@@ -3,24 +3,23 @@
+ #include <asm/processor.h>
+ #include "cpu.h"
+
+-/* UMC chips appear to be only either 386 or 486, so no special init takes place.
++/*
++ * UMC chips appear to be only either 386 or 486,
++ * so no special init takes place.
+ */
+
+ static struct cpu_dev umc_cpu_dev __cpuinitdata = {
+ .c_vendor = "UMC",
+- .c_ident = { "UMC UMC UMC" },
++ .c_ident = { "UMC UMC UMC" },
+ .c_models = {
+ { .vendor = X86_VENDOR_UMC, .family = 4, .model_names =
+- {
+- [1] = "U5D",
+- [2] = "U5S",
++ {
++ [1] = "U5D",
++ [2] = "U5S",
+ }
+ },
+ },
+ };
+
+-int __init umc_init_cpu(void)
+-{
+- cpu_devs[X86_VENDOR_UMC] = &umc_cpu_dev;
+- return 0;
+-}
++cpu_vendor_dev_register(X86_VENDOR_UMC, &umc_cpu_dev);
++
+diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c
+index 288e7a6..daff52a 100644
+--- a/arch/x86/kernel/cpuid.c
++++ b/arch/x86/kernel/cpuid.c
+@@ -154,12 +154,10 @@ static int __cpuinit cpuid_class_cpu_callback(struct notifier_block *nfb,
+ err = cpuid_device_create(cpu);
+ break;
+ case CPU_UP_CANCELED:
++ case CPU_UP_CANCELED_FROZEN:
+ case CPU_DEAD:
+ cpuid_device_destroy(cpu);
+ break;
+- case CPU_UP_CANCELED_FROZEN:
+- destroy_suspended_device(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
+- break;
+ }
+ return err ? NOTIFY_BAD : NOTIFY_OK;
+ }
+diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
+index 9a5fa0a..2251d0a 100644
+--- a/arch/x86/kernel/crash.c
++++ b/arch/x86/kernel/crash.c
+@@ -26,11 +26,7 @@
+ #include <linux/kdebug.h>
+ #include <asm/smp.h>
+
+-#ifdef CONFIG_X86_32
+ #include <mach_ipi.h>
+-#else
+-#include <asm/mach_apic.h>
+-#endif
+
+ /* This keeps a track of which one is crashing cpu. */
+ static int crashing_cpu;
+diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c
+index dcd918c..11c11b8 100644
+--- a/arch/x86/kernel/ds.c
++++ b/arch/x86/kernel/ds.c
+@@ -220,11 +220,11 @@ int ds_allocate(void **dsp, size_t bts_size_in_bytes)
+
+ int ds_free(void **dsp)
+ {
+- if (*dsp)
++ if (*dsp) {
+ kfree((void *)get_bts_buffer_base(*dsp));
+- kfree(*dsp);
+- *dsp = NULL;
+-
++ kfree(*dsp);
++ *dsp = NULL;
++ }
+ return 0;
+ }
+
+diff --git a/arch/x86/kernel/e820_32.c b/arch/x86/kernel/e820_32.c
+index 80444c5..ed733e7 100644
+--- a/arch/x86/kernel/e820_32.c
++++ b/arch/x86/kernel/e820_32.c
+@@ -450,45 +450,32 @@ int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
+ * thinkpad 560x, for example, does not cooperate with the memory
+ * detection code.)
+ */
+-int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
++int __init copy_e820_map(struct e820entry *biosmap, int nr_map)
+ {
+ /* Only one memory region (or negative)? Ignore it */
+ if (nr_map < 2)
+ return -1;
+
+ do {
+- unsigned long long start = biosmap->addr;
+- unsigned long long size = biosmap->size;
+- unsigned long long end = start + size;
+- unsigned long type = biosmap->type;
++ u64 start = biosmap->addr;
++ u64 size = biosmap->size;
++ u64 end = start + size;
++ u32 type = biosmap->type;
+
+ /* Overflow in 64 bits? Ignore the memory map. */
+ if (start > end)
+ return -1;
+
+- /*
+- * Some BIOSes claim RAM in the 640k - 1M region.
+- * Not right. Fix it up.
+- */
+- if (type == E820_RAM) {
+- if (start < 0x100000ULL && end > 0xA0000ULL) {
+- if (start < 0xA0000ULL)
+- add_memory_region(start, 0xA0000ULL-start, type);
+- if (end <= 0x100000ULL)
+- continue;
+- start = 0x100000ULL;
+- size = end - start;
+- }
+- }
+ add_memory_region(start, size, type);
+- } while (biosmap++,--nr_map);
++ } while (biosmap++, --nr_map);
++
+ return 0;
+ }
+
+ /*
+ * Find the highest page frame number we have available
+ */
+-void __init find_max_pfn(void)
++void __init propagate_e820_map(void)
+ {
+ int i;
+
+@@ -717,7 +704,7 @@ static int __init parse_memmap(char *arg)
+ * size before original memory map is
+ * reset.
+ */
+- find_max_pfn();
++ propagate_e820_map();
+ saved_max_pfn = max_pfn;
+ #endif
+ e820.nr_map = 0;
+diff --git a/arch/x86/kernel/e820_64.c b/arch/x86/kernel/e820_64.c
+index 9be6971..cbd42e5 100644
+--- a/arch/x86/kernel/e820_64.c
++++ b/arch/x86/kernel/e820_64.c
+@@ -27,6 +27,7 @@
+ #include <asm/setup.h>
+ #include <asm/sections.h>
+ #include <asm/kdebug.h>
++#include <asm/trampoline.h>
+
+ struct e820map e820;
+
+@@ -36,11 +37,11 @@ struct e820map e820;
+ unsigned long end_pfn;
+
+ /*
+- * end_pfn only includes RAM, while end_pfn_map includes all e820 entries.
+- * The direct mapping extends to end_pfn_map, so that we can directly access
++ * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
++ * The direct mapping extends to max_pfn_mapped, so that we can directly access
+ * apertures, ACPI and other tables without having to play with fixmaps.
+ */
+-unsigned long end_pfn_map;
++unsigned long max_pfn_mapped;
+
+ /*
+ * Last pfn which the user wants to use.
+@@ -58,8 +59,8 @@ struct early_res {
+ };
+ static struct early_res early_res[MAX_EARLY_RES] __initdata = {
+ { 0, PAGE_SIZE, "BIOS data page" }, /* BIOS data page */
+-#ifdef CONFIG_SMP
+- { SMP_TRAMPOLINE_BASE, SMP_TRAMPOLINE_BASE + 2*PAGE_SIZE, "SMP_TRAMPOLINE" },
++#ifdef CONFIG_X86_TRAMPOLINE
++ { TRAMPOLINE_BASE, TRAMPOLINE_BASE + 2 * PAGE_SIZE, "TRAMPOLINE" },
+ #endif
+ {}
+ };
+@@ -95,7 +96,8 @@ void __init early_res_to_bootmem(void)
+ }
+
+ /* Check for already reserved areas */
+-static inline int bad_addr(unsigned long *addrp, unsigned long size)
++static inline int __init
++bad_addr(unsigned long *addrp, unsigned long size, unsigned long align)
+ {
+ int i;
+ unsigned long addr = *addrp, last;
+@@ -105,7 +107,7 @@ again:
+ for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
+ struct early_res *r = &early_res[i];
+ if (last >= r->start && addr < r->end) {
+- *addrp = addr = r->end;
++ *addrp = addr = round_up(r->end, align);
+ changed = 1;
+ goto again;
+ }
+@@ -113,6 +115,40 @@ again:
+ return changed;
+ }
+
++/* Check for already reserved areas */
++static inline int __init
++bad_addr_size(unsigned long *addrp, unsigned long *sizep, unsigned long align)
++{
++ int i;
++ unsigned long addr = *addrp, last;
++ unsigned long size = *sizep;
++ int changed = 0;
++again:
++ last = addr + size;
++ for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
++ struct early_res *r = &early_res[i];
++ if (last > r->start && addr < r->start) {
++ size = r->start - addr;
++ changed = 1;
++ goto again;
++ }
++ if (last > r->end && addr < r->end) {
++ addr = round_up(r->end, align);
++ size = last - addr;
++ changed = 1;
++ goto again;
++ }
++ if (last <= r->end && addr >= r->start) {
++ (*sizep)++;
++ return 0;
++ }
++ }
++ if (changed) {
++ *addrp = addr;
++ *sizep = size;
++ }
++ return changed;
++}
+ /*
+ * This function checks if any part of the range <start,end> is mapped
+ * with type.
+@@ -174,26 +210,27 @@ int __init e820_all_mapped(unsigned long start, unsigned long end,
+ * Find a free area with specified alignment in a specific range.
+ */
+ unsigned long __init find_e820_area(unsigned long start, unsigned long end,
+- unsigned size, unsigned long align)
++ unsigned long size, unsigned long align)
+ {
+ int i;
+- unsigned long mask = ~(align - 1);
+
+ for (i = 0; i < e820.nr_map; i++) {
+ struct e820entry *ei = &e820.map[i];
+- unsigned long addr = ei->addr, last;
++ unsigned long addr, last;
++ unsigned long ei_last;
+
+ if (ei->type != E820_RAM)
+ continue;
++ addr = round_up(ei->addr, align);
++ ei_last = ei->addr + ei->size;
+ if (addr < start)
+- addr = start;
+- if (addr > ei->addr + ei->size)
++ addr = round_up(start, align);
++ if (addr >= ei_last)
+ continue;
+- while (bad_addr(&addr, size) && addr+size <= ei->addr+ei->size)
++ while (bad_addr(&addr, size, align) && addr+size <= ei_last)
+ ;
+- addr = (addr + align - 1) & mask;
+ last = addr + size;
+- if (last > ei->addr + ei->size)
++ if (last > ei_last)
+ continue;
+ if (last > end)
+ continue;
+@@ -203,6 +240,40 @@ unsigned long __init find_e820_area(unsigned long start, unsigned long end,
+ }
+
+ /*
++ * Find next free range after *start
++ */
++unsigned long __init find_e820_area_size(unsigned long start,
++ unsigned long *sizep,
++ unsigned long align)
++{
++ int i;
++
++ for (i = 0; i < e820.nr_map; i++) {
++ struct e820entry *ei = &e820.map[i];
++ unsigned long addr, last;
++ unsigned long ei_last;
++
++ if (ei->type != E820_RAM)
++ continue;
++ addr = round_up(ei->addr, align);
++ ei_last = ei->addr + ei->size;
++ if (addr < start)
++ addr = round_up(start, align);
++ if (addr >= ei_last)
++ continue;
++ *sizep = ei_last - addr;
++ while (bad_addr_size(&addr, sizep, align) &&
++ addr + *sizep <= ei_last)
++ ;
++ last = addr + *sizep;
++ if (last > ei_last)
++ continue;
++ return addr;
++ }
++ return -1UL;
++
++}
++/*
+ * Find the highest page frame number we have available
+ */
+ unsigned long __init e820_end_of_ram(void)
+@@ -211,29 +282,29 @@ unsigned long __init e820_end_of_ram(void)
+
+ end_pfn = find_max_pfn_with_active_regions();
+
+- if (end_pfn > end_pfn_map)
+- end_pfn_map = end_pfn;
+- if (end_pfn_map > MAXMEM>>PAGE_SHIFT)
+- end_pfn_map = MAXMEM>>PAGE_SHIFT;
++ if (end_pfn > max_pfn_mapped)
++ max_pfn_mapped = end_pfn;
++ if (max_pfn_mapped > MAXMEM>>PAGE_SHIFT)
++ max_pfn_mapped = MAXMEM>>PAGE_SHIFT;
+ if (end_pfn > end_user_pfn)
+ end_pfn = end_user_pfn;
+- if (end_pfn > end_pfn_map)
+- end_pfn = end_pfn_map;
++ if (end_pfn > max_pfn_mapped)
++ end_pfn = max_pfn_mapped;
+
+- printk(KERN_INFO "end_pfn_map = %lu\n", end_pfn_map);
++ printk(KERN_INFO "max_pfn_mapped = %lu\n", max_pfn_mapped);
+ return end_pfn;
+ }
+
+ /*
+ * Mark e820 reserved areas as busy for the resource manager.
+ */
+-void __init e820_reserve_resources(struct resource *code_resource,
+- struct resource *data_resource, struct resource *bss_resource)
++void __init e820_reserve_resources(void)
+ {
+ int i;
++ struct resource *res;
++
++ res = alloc_bootmem_low(sizeof(struct resource) * e820.nr_map);
+ for (i = 0; i < e820.nr_map; i++) {
+- struct resource *res;
+- res = alloc_bootmem_low(sizeof(struct resource));
+ switch (e820.map[i].type) {
+ case E820_RAM: res->name = "System RAM"; break;
+ case E820_ACPI: res->name = "ACPI Tables"; break;
+@@ -243,21 +314,8 @@ void __init e820_reserve_resources(struct resource *code_resource,
+ res->start = e820.map[i].addr;
+ res->end = res->start + e820.map[i].size - 1;
+ res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+- request_resource(&iomem_resource, res);
+- if (e820.map[i].type == E820_RAM) {
+- /*
+- * We don't know which RAM region contains kernel data,
+- * so we try it repeatedly and let the resource manager
+- * test it.
+- */
+- request_resource(res, code_resource);
+- request_resource(res, data_resource);
+- request_resource(res, bss_resource);
+-#ifdef CONFIG_KEXEC
+- if (crashk_res.start != crashk_res.end)
+- request_resource(res, &crashk_res);
+-#endif
+- }
++ insert_resource(&iomem_resource, res);
++ res++;
+ }
+ }
+
+@@ -309,9 +367,9 @@ static int __init e820_find_active_region(const struct e820entry *ei,
+ if (*ei_startpfn >= *ei_endpfn)
+ return 0;
+
+- /* Check if end_pfn_map should be updated */
+- if (ei->type != E820_RAM && *ei_endpfn > end_pfn_map)
+- end_pfn_map = *ei_endpfn;
++ /* Check if max_pfn_mapped should be updated */
++ if (ei->type != E820_RAM && *ei_endpfn > max_pfn_mapped)
++ max_pfn_mapped = *ei_endpfn;
+
+ /* Skip if map is outside the node */
+ if (ei->type != E820_RAM || *ei_endpfn <= start_pfn ||
+@@ -634,10 +692,10 @@ static int __init copy_e820_map(struct e820entry *biosmap, int nr_map)
+ return -1;
+
+ do {
+- unsigned long start = biosmap->addr;
+- unsigned long size = biosmap->size;
+- unsigned long end = start + size;
+- unsigned long type = biosmap->type;
++ u64 start = biosmap->addr;
++ u64 size = biosmap->size;
++ u64 end = start + size;
++ u32 type = biosmap->type;
+
+ /* Overflow in 64 bits? Ignore the memory map. */
+ if (start > end)
+@@ -702,7 +760,7 @@ static int __init parse_memmap_opt(char *p)
+ saved_max_pfn = e820_end_of_ram();
+ remove_all_active_ranges();
+ #endif
+- end_pfn_map = 0;
++ max_pfn_mapped = 0;
+ e820.nr_map = 0;
+ userdef = 1;
+ return 0;
+diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
+index cff84cd..643fd86 100644
+--- a/arch/x86/kernel/early_printk.c
++++ b/arch/x86/kernel/early_printk.c
+@@ -13,7 +13,7 @@
+ #define VGABASE (__ISA_IO_base + 0xb8000)
+
+ static int max_ypos = 25, max_xpos = 80;
+-static int current_ypos = 25, current_xpos = 0;
++static int current_ypos = 25, current_xpos;
+
+ static void early_vga_write(struct console *con, const char *str, unsigned n)
+ {
+@@ -108,12 +108,12 @@ static __init void early_serial_init(char *s)
+
+ if (*s) {
+ unsigned port;
+- if (!strncmp(s,"0x",2)) {
++ if (!strncmp(s, "0x", 2)) {
+ early_serial_base = simple_strtoul(s, &e, 16);
+ } else {
+ static int bases[] = { 0x3f8, 0x2f8 };
+
+- if (!strncmp(s,"ttyS",4))
++ if (!strncmp(s, "ttyS", 4))
+ s += 4;
+ port = simple_strtoul(s, &e, 10);
+ if (port > 1 || s == e)
+@@ -194,7 +194,7 @@ static struct console simnow_console = {
+
+ /* Direct interface for emergencies */
+ static struct console *early_console = &early_vga_console;
+-static int early_console_initialized = 0;
++static int early_console_initialized;
+
+ void early_printk(const char *fmt, ...)
+ {
+@@ -202,9 +202,9 @@ void early_printk(const char *fmt, ...)
+ int n;
+ va_list ap;
+
+- va_start(ap,fmt);
+- n = vscnprintf(buf,512,fmt,ap);
+- early_console->write(early_console,buf,n);
++ va_start(ap, fmt);
++ n = vscnprintf(buf, 512, fmt, ap);
++ early_console->write(early_console, buf, n);
+ va_end(ap);
+ }
+
+@@ -229,15 +229,15 @@ static int __init setup_early_printk(char *buf)
+ early_serial_init(buf);
+ early_console = &early_serial_console;
+ } else if (!strncmp(buf, "vga", 3)
+- && boot_params.screen_info.orig_video_isVGA == 1) {
++ && boot_params.screen_info.orig_video_isVGA == 1) {
+ max_xpos = boot_params.screen_info.orig_video_cols;
+ max_ypos = boot_params.screen_info.orig_video_lines;
+ current_ypos = boot_params.screen_info.orig_y;
+ early_console = &early_vga_console;
+- } else if (!strncmp(buf, "simnow", 6)) {
+- simnow_init(buf + 6);
+- early_console = &simnow_console;
+- keep_early = 1;
++ } else if (!strncmp(buf, "simnow", 6)) {
++ simnow_init(buf + 6);
++ early_console = &simnow_console;
++ keep_early = 1;
+ #ifdef CONFIG_HVC_XEN
+ } else if (!strncmp(buf, "xen", 3)) {
+ early_console = &xenboot_console;
+diff --git a/arch/x86/kernel/efi.c b/arch/x86/kernel/efi.c
+index 759e02b..77d424c 100644
+--- a/arch/x86/kernel/efi.c
++++ b/arch/x86/kernel/efi.c
+@@ -383,6 +383,7 @@ static void __init runtime_code_page_mkexec(void)
+ {
+ efi_memory_desc_t *md;
+ void *p;
++ u64 addr, npages;
+
+ /* Make EFI runtime service code area executable */
+ for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+@@ -391,7 +392,10 @@ static void __init runtime_code_page_mkexec(void)
+ if (md->type != EFI_RUNTIME_SERVICES_CODE)
+ continue;
+
+- set_memory_x(md->virt_addr, md->num_pages);
++ addr = md->virt_addr;
++ npages = md->num_pages;
++ memrange_efi_to_native(&addr, &npages);
++ set_memory_x(addr, npages);
+ }
+ }
+
+@@ -408,7 +412,7 @@ void __init efi_enter_virtual_mode(void)
+ efi_memory_desc_t *md;
+ efi_status_t status;
+ unsigned long size;
+- u64 end, systab;
++ u64 end, systab, addr, npages;
+ void *p, *va;
+
+ efi.systab = NULL;
+@@ -420,7 +424,7 @@ void __init efi_enter_virtual_mode(void)
+ size = md->num_pages << EFI_PAGE_SHIFT;
+ end = md->phys_addr + size;
+
+- if ((end >> PAGE_SHIFT) <= max_pfn_mapped)
++ if (PFN_UP(end) <= max_pfn_mapped)
+ va = __va(md->phys_addr);
+ else
+ va = efi_ioremap(md->phys_addr, size);
+@@ -433,8 +437,12 @@ void __init efi_enter_virtual_mode(void)
+ continue;
+ }
+
+- if (!(md->attribute & EFI_MEMORY_WB))
+- set_memory_uc(md->virt_addr, md->num_pages);
++ if (!(md->attribute & EFI_MEMORY_WB)) {
++ addr = md->virt_addr;
++ npages = md->num_pages;
++ memrange_efi_to_native(&addr, &npages);
++ set_memory_uc(addr, npages);
++ }
+
+ systab = (u64) (unsigned long) efi_phys.systab;
+ if (md->phys_addr <= systab && systab < end) {
+diff --git a/arch/x86/kernel/efi_64.c b/arch/x86/kernel/efi_64.c
+index d143a1e..d0060fd 100644
+--- a/arch/x86/kernel/efi_64.c
++++ b/arch/x86/kernel/efi_64.c
+@@ -105,14 +105,14 @@ void __init efi_reserve_bootmem(void)
+
+ void __iomem * __init efi_ioremap(unsigned long phys_addr, unsigned long size)
+ {
+- static unsigned pages_mapped;
++ static unsigned pages_mapped __initdata;
+ unsigned i, pages;
++ unsigned long offset;
+
+- /* phys_addr and size must be page aligned */
+- if ((phys_addr & ~PAGE_MASK) || (size & ~PAGE_MASK))
+- return NULL;
++ pages = PFN_UP(phys_addr + size) - PFN_DOWN(phys_addr);
++ offset = phys_addr & ~PAGE_MASK;
++ phys_addr &= PAGE_MASK;
+
+- pages = size >> PAGE_SHIFT;
+ if (pages_mapped + pages > MAX_EFI_IO_PAGES)
+ return NULL;
+
+@@ -124,5 +124,5 @@ void __iomem * __init efi_ioremap(unsigned long phys_addr, unsigned long size)
+ }
+
+ return (void __iomem *)__fix_to_virt(FIX_EFI_IO_MAP_FIRST_PAGE - \
+- (pages_mapped - pages));
++ (pages_mapped - pages)) + offset;
+ }
+diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
+index 4b87c32..2a609dc 100644
+--- a/arch/x86/kernel/entry_32.S
++++ b/arch/x86/kernel/entry_32.S
+@@ -1,5 +1,4 @@
+ /*
+- * linux/arch/i386/entry.S
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+@@ -51,6 +50,7 @@
+ #include <asm/desc.h>
+ #include <asm/percpu.h>
+ #include <asm/dwarf2.h>
++#include <asm/processor-flags.h>
+ #include "irq_vectors.h"
+
+ /*
+@@ -68,13 +68,6 @@
+
+ #define nr_syscalls ((syscall_table_size)/4)
+
+-CF_MASK = 0x00000001
+-TF_MASK = 0x00000100
+-IF_MASK = 0x00000200
+-DF_MASK = 0x00000400
+-NT_MASK = 0x00004000
+-VM_MASK = 0x00020000
+-
+ #ifdef CONFIG_PREEMPT
+ #define preempt_stop(clobbers) DISABLE_INTERRUPTS(clobbers); TRACE_IRQS_OFF
+ #else
+@@ -84,7 +77,7 @@ VM_MASK = 0x00020000
+
+ .macro TRACE_IRQS_IRET
+ #ifdef CONFIG_TRACE_IRQFLAGS
+- testl $IF_MASK,PT_EFLAGS(%esp) # interrupts off?
++ testl $X86_EFLAGS_IF,PT_EFLAGS(%esp) # interrupts off?
+ jz 1f
+ TRACE_IRQS_ON
+ 1:
+@@ -246,7 +239,7 @@ ret_from_intr:
+ check_userspace:
+ movl PT_EFLAGS(%esp), %eax # mix EFLAGS and CS
+ movb PT_CS(%esp), %al
+- andl $(VM_MASK | SEGMENT_RPL_MASK), %eax
++ andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax
+ cmpl $USER_RPL, %eax
+ jb resume_kernel # not returning to v8086 or userspace
+
+@@ -271,7 +264,7 @@ need_resched:
+ movl TI_flags(%ebp), %ecx # need_resched set ?
+ testb $_TIF_NEED_RESCHED, %cl
+ jz restore_all
+- testl $IF_MASK,PT_EFLAGS(%esp) # interrupts off (exception path) ?
++ testl $X86_EFLAGS_IF,PT_EFLAGS(%esp) # interrupts off (exception path) ?
+ jz restore_all
+ call preempt_schedule_irq
+ jmp need_resched
+@@ -291,10 +284,10 @@ ENTRY(ia32_sysenter_target)
+ movl TSS_sysenter_sp0(%esp),%esp
+ sysenter_past_esp:
+ /*
+- * No need to follow this irqs on/off section: the syscall
+- * disabled irqs and here we enable it straight after entry:
++ * Interrupts are disabled here, but we can't trace it until
++ * enough kernel state to call TRACE_IRQS_OFF can be called - but
++ * we immediately enable interrupts at that point anyway.
+ */
+- ENABLE_INTERRUPTS(CLBR_NONE)
+ pushl $(__USER_DS)
+ CFI_ADJUST_CFA_OFFSET 4
+ /*CFI_REL_OFFSET ss, 0*/
+@@ -302,6 +295,7 @@ sysenter_past_esp:
+ CFI_ADJUST_CFA_OFFSET 4
+ CFI_REL_OFFSET esp, 0
+ pushfl
++ orl $X86_EFLAGS_IF, (%esp)
+ CFI_ADJUST_CFA_OFFSET 4
+ pushl $(__USER_CS)
+ CFI_ADJUST_CFA_OFFSET 4
+@@ -315,6 +309,11 @@ sysenter_past_esp:
+ CFI_ADJUST_CFA_OFFSET 4
+ CFI_REL_OFFSET eip, 0
+
++ pushl %eax
++ CFI_ADJUST_CFA_OFFSET 4
++ SAVE_ALL
++ ENABLE_INTERRUPTS(CLBR_NONE)
++
+ /*
+ * Load the potential sixth argument from user stack.
+ * Careful about security.
+@@ -322,14 +321,12 @@ sysenter_past_esp:
+ cmpl $__PAGE_OFFSET-3,%ebp
+ jae syscall_fault
+ 1: movl (%ebp),%ebp
++ movl %ebp,PT_EBP(%esp)
+ .section __ex_table,"a"
+ .align 4
+ .long 1b,syscall_fault
+ .previous
+
+- pushl %eax
+- CFI_ADJUST_CFA_OFFSET 4
+- SAVE_ALL
+ GET_THREAD_INFO(%ebp)
+
+ /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
+@@ -384,7 +381,7 @@ syscall_exit:
+ # setting need_resched or sigpending
+ # between sampling and the iret
+ TRACE_IRQS_OFF
+- testl $TF_MASK,PT_EFLAGS(%esp) # If tracing set singlestep flag on exit
++ testl $X86_EFLAGS_TF,PT_EFLAGS(%esp) # If tracing set singlestep flag on exit
+ jz no_singlestep
+ orl $_TIF_SINGLESTEP,TI_flags(%ebp)
+ no_singlestep:
+@@ -399,7 +396,7 @@ restore_all:
+ # See comments in process.c:copy_thread() for details.
+ movb PT_OLDSS(%esp), %ah
+ movb PT_CS(%esp), %al
+- andl $(VM_MASK | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
++ andl $(X86_EFLAGS_VM | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
+ cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax
+ CFI_REMEMBER_STATE
+ je ldt_ss # returning to user-space with LDT SS
+@@ -412,7 +409,7 @@ restore_nocheck_notrace:
+ irq_return:
+ INTERRUPT_RETURN
+ .section .fixup,"ax"
+-iret_exc:
++ENTRY(iret_exc)
+ pushl $0 # no error code
+ pushl $do_iret_error
+ jmp error_code
+@@ -486,7 +483,7 @@ work_resched:
+ work_notifysig: # deal with pending signals and
+ # notify-resume requests
+ #ifdef CONFIG_VM86
+- testl $VM_MASK, PT_EFLAGS(%esp)
++ testl $X86_EFLAGS_VM, PT_EFLAGS(%esp)
+ movl %esp, %eax
+ jne work_notifysig_v86 # returning to kernel-space or
+ # vm86-space
+@@ -543,9 +540,6 @@ END(syscall_exit_work)
+
+ RING0_INT_FRAME # can't unwind into user space anyway
+ syscall_fault:
+- pushl %eax # save orig_eax
+- CFI_ADJUST_CFA_OFFSET 4
+- SAVE_ALL
+ GET_THREAD_INFO(%ebp)
+ movl $-EFAULT,PT_EAX(%esp)
+ jmp resume_userspace
+@@ -1023,6 +1017,13 @@ ENTRY(kernel_thread_helper)
+ ENDPROC(kernel_thread_helper)
+
+ #ifdef CONFIG_XEN
++/* Xen doesn't set %esp to be precisely what the normal sysenter
++ entrypoint expects, so fix it up before using the normal path. */
++ENTRY(xen_sysenter_target)
++ RING0_INT_FRAME
++ addl $5*4, %esp /* remove xen-provided frame */
++ jmp sysenter_past_esp
++
+ ENTRY(xen_hypervisor_callback)
+ CFI_STARTPROC
+ pushl $0
+@@ -1041,8 +1042,9 @@ ENTRY(xen_hypervisor_callback)
+ cmpl $xen_iret_end_crit,%eax
+ jae 1f
+
+- call xen_iret_crit_fixup
++ jmp xen_iret_crit_fixup
+
++ENTRY(xen_do_upcall)
+ 1: mov %esp, %eax
+ call xen_evtchn_do_upcall
+ jmp ret_from_intr
+diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
+index c20c9e7..556a8df 100644
+--- a/arch/x86/kernel/entry_64.S
++++ b/arch/x86/kernel/entry_64.S
+@@ -319,19 +319,17 @@ badsys:
+ /* Do syscall tracing */
+ tracesys:
+ SAVE_REST
+- movq $-ENOSYS,RAX(%rsp)
++ movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
+ FIXUP_TOP_OF_STACK %rdi
+ movq %rsp,%rdi
+ call syscall_trace_enter
+ LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */
+ RESTORE_REST
+ cmpq $__NR_syscall_max,%rax
+- movq $-ENOSYS,%rcx
+- cmova %rcx,%rax
+- ja 1f
++ ja int_ret_from_sys_call /* RAX(%rsp) set to -ENOSYS above */
+ movq %r10,%rcx /* fixup for C */
+ call *sys_call_table(,%rax,8)
+-1: movq %rax,RAX-ARGOFFSET(%rsp)
++ movq %rax,RAX-ARGOFFSET(%rsp)
+ /* Use IRET because user could have changed frame */
+
+ /*
+diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c
+index 4ae7b64..021624c 100644
+--- a/arch/x86/kernel/genapic_64.c
++++ b/arch/x86/kernel/genapic_64.c
+@@ -15,6 +15,7 @@
+ #include <linux/kernel.h>
+ #include <linux/ctype.h>
+ #include <linux/init.h>
++#include <linux/hardirq.h>
+
+ #include <asm/smp.h>
+ #include <asm/ipi.h>
+@@ -24,20 +25,20 @@
+ #include <acpi/acpi_bus.h>
+ #endif
+
+-/* which logical CPU number maps to which CPU (physical APIC ID) */
+-u16 x86_cpu_to_apicid_init[NR_CPUS] __initdata
+- = { [0 ... NR_CPUS-1] = BAD_APICID };
+-void *x86_cpu_to_apicid_early_ptr;
+-DEFINE_PER_CPU(u16, x86_cpu_to_apicid) = BAD_APICID;
+-EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid);
++DEFINE_PER_CPU(int, x2apic_extra_bits);
+
+ struct genapic __read_mostly *genapic = &apic_flat;
+
++static enum uv_system_type uv_system_type;
++
+ /*
+ * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode.
+ */
+ void __init setup_apic_routing(void)
+ {
++ if (uv_system_type == UV_NON_UNIQUE_APIC)
++ genapic = &apic_x2apic_uv_x;
++ else
+ #ifdef CONFIG_ACPI
+ /*
+ * Quirk: some x86_64 machines can only use physical APIC mode
+@@ -50,7 +51,7 @@ void __init setup_apic_routing(void)
+ else
+ #endif
+
+- if (cpus_weight(cpu_possible_map) <= 8)
++ if (num_possible_cpus() <= 8)
+ genapic = &apic_flat;
+ else
+ genapic = &apic_physflat;
+@@ -64,3 +65,37 @@ void send_IPI_self(int vector)
+ {
+ __send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
+ }
++
++int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
++{
++ if (!strcmp(oem_id, "SGI")) {
++ if (!strcmp(oem_table_id, "UVL"))
++ uv_system_type = UV_LEGACY_APIC;
++ else if (!strcmp(oem_table_id, "UVX"))
++ uv_system_type = UV_X2APIC;
++ else if (!strcmp(oem_table_id, "UVH"))
++ uv_system_type = UV_NON_UNIQUE_APIC;
++ }
++ return 0;
++}
++
++unsigned int read_apic_id(void)
++{
++ unsigned int id;
++
++ WARN_ON(preemptible());
++ id = apic_read(APIC_ID);
++ if (uv_system_type >= UV_X2APIC)
++ id |= __get_cpu_var(x2apic_extra_bits);
++ return id;
++}
++
++enum uv_system_type get_uv_system_type(void)
++{
++ return uv_system_type;
++}
++
++int is_uv_system(void)
++{
++ return uv_system_type != UV_NONE;
++}
+diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c
+index 07352b7..1a9c688 100644
+--- a/arch/x86/kernel/genapic_flat_64.c
++++ b/arch/x86/kernel/genapic_flat_64.c
+@@ -97,7 +97,7 @@ static void flat_send_IPI_all(int vector)
+
+ static int flat_apic_id_registered(void)
+ {
+- return physid_isset(GET_APIC_ID(apic_read(APIC_ID)), phys_cpu_present_map);
++ return physid_isset(GET_APIC_ID(read_apic_id()), phys_cpu_present_map);
+ }
+
+ static unsigned int flat_cpu_mask_to_apicid(cpumask_t cpumask)
+@@ -138,12 +138,9 @@ static cpumask_t physflat_target_cpus(void)
+
+ static cpumask_t physflat_vector_allocation_domain(int cpu)
+ {
+- cpumask_t domain = CPU_MASK_NONE;
+- cpu_set(cpu, domain);
+- return domain;
++ return cpumask_of_cpu(cpu);
+ }
+
+-
+ static void physflat_send_IPI_mask(cpumask_t cpumask, int vector)
+ {
+ send_IPI_mask_sequence(cpumask, vector);
+diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c
+new file mode 100644
+index 0000000..ebf1390
+--- /dev/null
++++ b/arch/x86/kernel/genx2apic_uv_x.c
+@@ -0,0 +1,250 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * SGI UV APIC functions (note: not an Intel compatible APIC)
++ *
++ * Copyright (C) 2007 Silicon Graphics, Inc. All rights reserved.
++ */
++
++#include <linux/threads.h>
++#include <linux/cpumask.h>
++#include <linux/string.h>
++#include <linux/kernel.h>
++#include <linux/ctype.h>
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/bootmem.h>
++#include <linux/module.h>
++#include <asm/smp.h>
++#include <asm/ipi.h>
++#include <asm/genapic.h>
++#include <asm/uv/uv_mmrs.h>
++#include <asm/uv/uv_hub.h>
++
++DEFINE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
++EXPORT_PER_CPU_SYMBOL_GPL(__uv_hub_info);
++
++struct uv_blade_info *uv_blade_info;
++EXPORT_SYMBOL_GPL(uv_blade_info);
++
++short *uv_node_to_blade;
++EXPORT_SYMBOL_GPL(uv_node_to_blade);
++
++short *uv_cpu_to_blade;
++EXPORT_SYMBOL_GPL(uv_cpu_to_blade);
++
++short uv_possible_blades;
++EXPORT_SYMBOL_GPL(uv_possible_blades);
++
++/* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */
++
++static cpumask_t uv_target_cpus(void)
++{
++ return cpumask_of_cpu(0);
++}
++
++static cpumask_t uv_vector_allocation_domain(int cpu)
++{
++ cpumask_t domain = CPU_MASK_NONE;
++ cpu_set(cpu, domain);
++ return domain;
++}
++
++int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip)
++{
++ unsigned long val;
++ int nasid;
++
++ nasid = uv_apicid_to_nasid(phys_apicid);
++ val = (1UL << UVH_IPI_INT_SEND_SHFT) |
++ (phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) |
++ (((long)start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) |
++ APIC_DM_INIT;
++ uv_write_global_mmr64(nasid, UVH_IPI_INT, val);
++ mdelay(10);
++
++ val = (1UL << UVH_IPI_INT_SEND_SHFT) |
++ (phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) |
++ (((long)start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) |
++ APIC_DM_STARTUP;
++ uv_write_global_mmr64(nasid, UVH_IPI_INT, val);
++ return 0;
++}
++
++static void uv_send_IPI_one(int cpu, int vector)
++{
++ unsigned long val, apicid, lapicid;
++ int nasid;
++
++ apicid = per_cpu(x86_cpu_to_apicid, cpu); /* ZZZ - cache node-local ? */
++ lapicid = apicid & 0x3f; /* ZZZ macro needed */
++ nasid = uv_apicid_to_nasid(apicid);
++ val =
++ (1UL << UVH_IPI_INT_SEND_SHFT) | (lapicid <<
++ UVH_IPI_INT_APIC_ID_SHFT) |
++ (vector << UVH_IPI_INT_VECTOR_SHFT);
++ uv_write_global_mmr64(nasid, UVH_IPI_INT, val);
++}
++
++static void uv_send_IPI_mask(cpumask_t mask, int vector)
++{
++ unsigned int cpu;
++
++ for (cpu = 0; cpu < NR_CPUS; ++cpu)
++ if (cpu_isset(cpu, mask))
++ uv_send_IPI_one(cpu, vector);
++}
++
++static void uv_send_IPI_allbutself(int vector)
++{
++ cpumask_t mask = cpu_online_map;
++
++ cpu_clear(smp_processor_id(), mask);
++
++ if (!cpus_empty(mask))
++ uv_send_IPI_mask(mask, vector);
++}
++
++static void uv_send_IPI_all(int vector)
++{
++ uv_send_IPI_mask(cpu_online_map, vector);
++}
++
++static int uv_apic_id_registered(void)
++{
++ return 1;
++}
++
++static unsigned int uv_cpu_mask_to_apicid(cpumask_t cpumask)
++{
++ int cpu;
++
++ /*
++ * We're using fixed IRQ delivery, can only return one phys APIC ID.
++ * May as well be the first.
++ */
++ cpu = first_cpu(cpumask);
++ if ((unsigned)cpu < NR_CPUS)
++ return per_cpu(x86_cpu_to_apicid, cpu);
++ else
++ return BAD_APICID;
++}
++
++static unsigned int phys_pkg_id(int index_msb)
++{
++ return GET_APIC_ID(read_apic_id()) >> index_msb;
++}
++
++#ifdef ZZZ /* Needs x2apic patch */
++static void uv_send_IPI_self(int vector)
++{
++ apic_write(APIC_SELF_IPI, vector);
++}
++#endif
++
++struct genapic apic_x2apic_uv_x = {
++ .name = "UV large system",
++ .int_delivery_mode = dest_Fixed,
++ .int_dest_mode = (APIC_DEST_PHYSICAL != 0),
++ .target_cpus = uv_target_cpus,
++ .vector_allocation_domain = uv_vector_allocation_domain,/* Fixme ZZZ */
++ .apic_id_registered = uv_apic_id_registered,
++ .send_IPI_all = uv_send_IPI_all,
++ .send_IPI_allbutself = uv_send_IPI_allbutself,
++ .send_IPI_mask = uv_send_IPI_mask,
++ /* ZZZ.send_IPI_self = uv_send_IPI_self, */
++ .cpu_mask_to_apicid = uv_cpu_mask_to_apicid,
++ .phys_pkg_id = phys_pkg_id, /* Fixme ZZZ */
++};
++
++static __cpuinit void set_x2apic_extra_bits(int nasid)
++{
++ __get_cpu_var(x2apic_extra_bits) = ((nasid >> 1) << 6);
++}
++
++/*
++ * Called on boot cpu.
++ */
++static __init void uv_system_init(void)
++{
++ union uvh_si_addr_map_config_u m_n_config;
++ int bytes, nid, cpu, lcpu, nasid, last_nasid, blade;
++ unsigned long mmr_base;
++
++ m_n_config.v = uv_read_local_mmr(UVH_SI_ADDR_MAP_CONFIG);
++ mmr_base =
++ uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR) &
++ ~UV_MMR_ENABLE;
++ printk(KERN_DEBUG "UV: global MMR base 0x%lx\n", mmr_base);
++
++ last_nasid = -1;
++ for_each_possible_cpu(cpu) {
++ nid = cpu_to_node(cpu);
++ nasid = uv_apicid_to_nasid(per_cpu(x86_cpu_to_apicid, cpu));
++ if (nasid != last_nasid)
++ uv_possible_blades++;
++ last_nasid = nasid;
++ }
++ printk(KERN_DEBUG "UV: Found %d blades\n", uv_num_possible_blades());
++
++ bytes = sizeof(struct uv_blade_info) * uv_num_possible_blades();
++ uv_blade_info = alloc_bootmem_pages(bytes);
++
++ bytes = sizeof(uv_node_to_blade[0]) * num_possible_nodes();
++ uv_node_to_blade = alloc_bootmem_pages(bytes);
++ memset(uv_node_to_blade, 255, bytes);
++
++ bytes = sizeof(uv_cpu_to_blade[0]) * num_possible_cpus();
++ uv_cpu_to_blade = alloc_bootmem_pages(bytes);
++ memset(uv_cpu_to_blade, 255, bytes);
++
++ last_nasid = -1;
++ blade = -1;
++ lcpu = -1;
++ for_each_possible_cpu(cpu) {
++ nid = cpu_to_node(cpu);
++ nasid = uv_apicid_to_nasid(per_cpu(x86_cpu_to_apicid, cpu));
++ if (nasid != last_nasid) {
++ blade++;
++ lcpu = -1;
++ uv_blade_info[blade].nr_posible_cpus = 0;
++ uv_blade_info[blade].nr_online_cpus = 0;
++ }
++ last_nasid = nasid;
++ lcpu++;
++
++ uv_cpu_hub_info(cpu)->m_val = m_n_config.s.m_skt;
++ uv_cpu_hub_info(cpu)->n_val = m_n_config.s.n_skt;
++ uv_cpu_hub_info(cpu)->numa_blade_id = blade;
++ uv_cpu_hub_info(cpu)->blade_processor_id = lcpu;
++ uv_cpu_hub_info(cpu)->local_nasid = nasid;
++ uv_cpu_hub_info(cpu)->gnode_upper =
++ nasid & ~((1 << uv_hub_info->n_val) - 1);
++ uv_cpu_hub_info(cpu)->global_mmr_base = mmr_base;
++ uv_cpu_hub_info(cpu)->coherency_domain_number = 0;/* ZZZ */
++ uv_blade_info[blade].nasid = nasid;
++ uv_blade_info[blade].nr_posible_cpus++;
++ uv_node_to_blade[nid] = blade;
++ uv_cpu_to_blade[cpu] = blade;
++
++ printk(KERN_DEBUG "UV cpu %d, apicid 0x%x, nasid %d, nid %d\n",
++ cpu, per_cpu(x86_cpu_to_apicid, cpu), nasid, nid);
++ printk(KERN_DEBUG "UV lcpu %d, blade %d\n", lcpu, blade);
++ }
++}
++
++/*
++ * Called on each cpu to initialize the per_cpu UV data area.
++ */
++void __cpuinit uv_cpu_init(void)
++{
++ if (!uv_node_to_blade)
++ uv_system_init();
++
++ uv_blade_info[uv_numa_blade_id()].nr_online_cpus++;
++
++ if (get_uv_system_type() == UV_NON_UNIQUE_APIC)
++ set_x2apic_extra_bits(uv_hub_info->local_nasid);
++}
+diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c
+new file mode 100644
+index 0000000..3db0590
+--- /dev/null
++++ b/arch/x86/kernel/head32.c
+@@ -0,0 +1,14 @@
++/*
++ * linux/arch/i386/kernel/head32.c -- prepare to run common code
++ *
++ * Copyright (C) 2000 Andrea Arcangeli <andrea at suse.de> SuSE
++ * Copyright (C) 2007 Eric Biederman <ebiederm at xmission.com>
++ */
++
++#include <linux/init.h>
++#include <linux/start_kernel.h>
++
++void __init i386_start_kernel(void)
++{
++ start_kernel();
++}
+diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
+index ad24408..d31d6b7 100644
+--- a/arch/x86/kernel/head64.c
++++ b/arch/x86/kernel/head64.c
+@@ -22,6 +22,7 @@
+ #include <asm/sections.h>
+ #include <asm/kdebug.h>
+ #include <asm/e820.h>
++#include <asm/bios_ebda.h>
+
+ static void __init zap_identity_mappings(void)
+ {
+@@ -49,39 +50,73 @@ static void __init copy_bootdata(char *real_mode_data)
+ }
+ }
+
+-#define EBDA_ADDR_POINTER 0x40E
++#define BIOS_LOWMEM_KILOBYTES 0x413
+
+-static __init void reserve_ebda(void)
++/*
++ * The BIOS places the EBDA/XBDA at the top of conventional
++ * memory, and usually decreases the reported amount of
++ * conventional memory (int 0x12) too. This also contains a
++ * workaround for Dell systems that neglect to reserve EBDA.
++ * The same workaround also avoids a problem with the AMD768MPX
++ * chipset: reserve a page before VGA to prevent PCI prefetch
++ * into it (errata #56). Usually the page is reserved anyways,
++ * unless you have no PS/2 mouse plugged in.
++ */
++static void __init reserve_ebda_region(void)
+ {
+- unsigned ebda_addr, ebda_size;
++ unsigned int lowmem, ebda_addr;
++
++ /* To determine the position of the EBDA and the */
++ /* end of conventional memory, we need to look at */
++ /* the BIOS data area. In a paravirtual environment */
++ /* that area is absent. We'll just have to assume */
++ /* that the paravirt case can handle memory setup */
++ /* correctly, without our help. */
++ if (paravirt_enabled())
++ return;
+
+- /*
+- * there is a real-mode segmented pointer pointing to the
+- * 4K EBDA area at 0x40E
+- */
+- ebda_addr = *(unsigned short *)__va(EBDA_ADDR_POINTER);
+- ebda_addr <<= 4;
++ /* end of low (conventional) memory */
++ lowmem = *(unsigned short *)__va(BIOS_LOWMEM_KILOBYTES);
++ lowmem <<= 10;
+
+- if (!ebda_addr)
+- return;
++ /* start of EBDA area */
++ ebda_addr = get_bios_ebda();
+
+- ebda_size = *(unsigned short *)__va(ebda_addr);
++ /* Fixup: bios puts an EBDA in the top 64K segment */
++ /* of conventional memory, but does not adjust lowmem. */
++ if ((lowmem - ebda_addr) <= 0x10000)
++ lowmem = ebda_addr;
+
+- /* Round EBDA up to pages */
+- if (ebda_size == 0)
+- ebda_size = 1;
+- ebda_size <<= 10;
+- ebda_size = round_up(ebda_size + (ebda_addr & ~PAGE_MASK), PAGE_SIZE);
+- if (ebda_size > 64*1024)
+- ebda_size = 64*1024;
++ /* Fixup: bios does not report an EBDA at all. */
++ /* Some old Dells seem to need 4k anyhow (bugzilla 2990) */
++ if ((ebda_addr == 0) && (lowmem >= 0x9f000))
++ lowmem = 0x9f000;
+
+- reserve_early(ebda_addr, ebda_addr + ebda_size, "EBDA");
++ /* Paranoia: should never happen, but... */
++ if ((lowmem == 0) || (lowmem >= 0x100000))
++ lowmem = 0x9f000;
++
++ /* reserve all memory between lowmem and the 1MB mark */
++ reserve_early(lowmem, 0x100000, "BIOS reserved");
+ }
+
+ void __init x86_64_start_kernel(char * real_mode_data)
+ {
+ int i;
+
++ /*
++ * Build-time sanity checks on the kernel image and module
++ * area mappings. (these are purely build-time and produce no code)
++ */
++ BUILD_BUG_ON(MODULES_VADDR < KERNEL_IMAGE_START);
++ BUILD_BUG_ON(MODULES_VADDR-KERNEL_IMAGE_START < KERNEL_IMAGE_SIZE);
++ BUILD_BUG_ON(MODULES_LEN + KERNEL_IMAGE_SIZE > 2*PUD_SIZE);
++ BUILD_BUG_ON((KERNEL_IMAGE_START & ~PMD_MASK) != 0);
++ BUILD_BUG_ON((MODULES_VADDR & ~PMD_MASK) != 0);
++ BUILD_BUG_ON(!(MODULES_VADDR > __START_KERNEL));
++ BUILD_BUG_ON(!(((MODULES_END - 1) & PGDIR_MASK) ==
++ (__START_KERNEL & PGDIR_MASK)));
++
+ /* clear bss before set_intr_gate with early_idt_handler */
+ clear_bss();
+
+@@ -91,7 +126,7 @@ void __init x86_64_start_kernel(char * real_mode_data)
+ /* Cleanup the over mapped high alias */
+ cleanup_highmap();
+
+- for (i = 0; i < IDT_ENTRIES; i++) {
++ for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) {
+ #ifdef CONFIG_EARLY_PRINTK
+ set_intr_gate(i, &early_idt_handlers[i]);
+ #else
+@@ -110,6 +145,7 @@ void __init x86_64_start_kernel(char * real_mode_data)
+
+ reserve_early(__pa_symbol(&_text), __pa_symbol(&_end), "TEXT DATA BSS");
+
++#ifdef CONFIG_BLK_DEV_INITRD
+ /* Reserve INITRD */
+ if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {
+ unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
+@@ -117,8 +153,9 @@ void __init x86_64_start_kernel(char * real_mode_data)
+ unsigned long ramdisk_end = ramdisk_image + ramdisk_size;
+ reserve_early(ramdisk_image, ramdisk_end, "RAMDISK");
+ }
++#endif
+
+- reserve_ebda();
++ reserve_ebda_region();
+
+ /*
+ * At this point everything still needed from the boot loader
+diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
+index 74d87ea..90f038a 100644
+--- a/arch/x86/kernel/head_32.S
++++ b/arch/x86/kernel/head_32.S
+@@ -1,5 +1,4 @@
+ /*
+- * linux/arch/i386/kernel/head.S -- the 32-bit startup code.
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+@@ -450,7 +449,7 @@ is386: movl $2,%ecx # set MP
+ jmp initialize_secondary # all other CPUs call initialize_secondary
+ 1:
+ #endif /* CONFIG_SMP */
+- jmp start_kernel
++ jmp i386_start_kernel
+
+ /*
+ * We depend on ET to be correct. This checks for 287/387.
+diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
+index a007454..10a1955 100644
+--- a/arch/x86/kernel/head_64.S
++++ b/arch/x86/kernel/head_64.S
+@@ -132,10 +132,6 @@ ident_complete:
+ addq %rbp, trampoline_level4_pgt + 0(%rip)
+ addq %rbp, trampoline_level4_pgt + (511*8)(%rip)
+ #endif
+-#ifdef CONFIG_ACPI_SLEEP
+- addq %rbp, wakeup_level4_pgt + 0(%rip)
+- addq %rbp, wakeup_level4_pgt + (511*8)(%rip)
+-#endif
+
+ /* Due to ENTRY(), sometimes the empty space gets filled with
+ * zeros. Better take a jmp than relying on empty space being
+@@ -267,21 +263,16 @@ ENTRY(secondary_startup_64)
+ bad_address:
+ jmp bad_address
+
++ .section ".init.text","ax"
+ #ifdef CONFIG_EARLY_PRINTK
+-.macro early_idt_tramp first, last
+- .ifgt \last-\first
+- early_idt_tramp \first, \last-1
+- .endif
+- movl $\last,%esi
+- jmp early_idt_handler
+-.endm
+-
+ .globl early_idt_handlers
+ early_idt_handlers:
+- early_idt_tramp 0, 63
+- early_idt_tramp 64, 127
+- early_idt_tramp 128, 191
+- early_idt_tramp 192, 255
++ i = 0
++ .rept NUM_EXCEPTION_VECTORS
++ movl $i, %esi
++ jmp early_idt_handler
++ i = i + 1
++ .endr
+ #endif
+
+ ENTRY(early_idt_handler)
+@@ -327,6 +318,7 @@ early_idt_msg:
+ early_idt_ripmsg:
+ .asciz "RIP %s\n"
+ #endif /* CONFIG_EARLY_PRINTK */
++ .previous
+
+ .balign PAGE_SIZE
+
+@@ -383,12 +375,12 @@ NEXT_PAGE(level2_ident_pgt)
+
+ NEXT_PAGE(level2_kernel_pgt)
+ /*
+- * 128 MB kernel mapping. We spend a full page on this pagetable
++ * 512 MB kernel mapping. We spend a full page on this pagetable
+ * anyway.
+ *
+ * The kernel code+data+bss must not be bigger than that.
+ *
+- * (NOTE: at +128MB starts the module area, see MODULES_VADDR.
++ * (NOTE: at +512MB starts the module area, see MODULES_VADDR.
+ * If you want to increase this then increase MODULES_VADDR
+ * too.)
+ */
+diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
+index 36652ea..9007f9e 100644
+--- a/arch/x86/kernel/hpet.c
++++ b/arch/x86/kernel/hpet.c
+@@ -218,7 +218,7 @@ static void hpet_legacy_clockevent_register(void)
+ hpet_freq = 1000000000000000ULL;
+ do_div(hpet_freq, hpet_period);
+ hpet_clockevent.mult = div_sc((unsigned long) hpet_freq,
+- NSEC_PER_SEC, 32);
++ NSEC_PER_SEC, hpet_clockevent.shift);
+ /* Calculate the min / max delta */
+ hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
+ &hpet_clockevent);
+diff --git a/arch/x86/kernel/i386_ksyms_32.c b/arch/x86/kernel/i386_ksyms_32.c
+index 0616278..deb4378 100644
+--- a/arch/x86/kernel/i386_ksyms_32.c
++++ b/arch/x86/kernel/i386_ksyms_32.c
+@@ -1,13 +1,8 @@
+ #include <linux/module.h>
+-#include <asm/semaphore.h>
+ #include <asm/checksum.h>
+ #include <asm/desc.h>
+ #include <asm/pgtable.h>
+
+-EXPORT_SYMBOL(__down_failed);
+-EXPORT_SYMBOL(__down_failed_interruptible);
+-EXPORT_SYMBOL(__down_failed_trylock);
+-EXPORT_SYMBOL(__up_wakeup);
+ /* Networking helper routines. */
+ EXPORT_SYMBOL(csum_partial_copy_generic);
+
+diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
+index d2e39e6..db6839b 100644
+--- a/arch/x86/kernel/i387.c
++++ b/arch/x86/kernel/i387.c
+@@ -5,51 +5,48 @@
+ * General FPU state handling cleanups
+ * Gareth Hughes <gareth at valinux.com>, May 2000
+ */
+-
+-#include <linux/sched.h>
+ #include <linux/module.h>
+ #include <linux/regset.h>
++#include <linux/sched.h>
++
++#include <asm/sigcontext.h>
+ #include <asm/processor.h>
+-#include <asm/i387.h>
+ #include <asm/math_emu.h>
+-#include <asm/sigcontext.h>
+-#include <asm/user.h>
+-#include <asm/ptrace.h>
+ #include <asm/uaccess.h>
++#include <asm/ptrace.h>
++#include <asm/i387.h>
++#include <asm/user.h>
+
+ #ifdef CONFIG_X86_64
+-
+-#include <asm/sigcontext32.h>
+-#include <asm/user32.h>
+-
++# include <asm/sigcontext32.h>
++# include <asm/user32.h>
+ #else
+-
+-#define save_i387_ia32 save_i387
+-#define restore_i387_ia32 restore_i387
+-
+-#define _fpstate_ia32 _fpstate
+-#define user_i387_ia32_struct user_i387_struct
+-#define user32_fxsr_struct user_fxsr_struct
+-
++# define save_i387_ia32 save_i387
++# define restore_i387_ia32 restore_i387
++# define _fpstate_ia32 _fpstate
++# define user_i387_ia32_struct user_i387_struct
++# define user32_fxsr_struct user_fxsr_struct
+ #endif
+
+ #ifdef CONFIG_MATH_EMULATION
+-#define HAVE_HWFP (boot_cpu_data.hard_math)
++# define HAVE_HWFP (boot_cpu_data.hard_math)
+ #else
+-#define HAVE_HWFP 1
++# define HAVE_HWFP 1
+ #endif
+
+-static unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu;
++static unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu;
++unsigned int xstate_size;
++static struct i387_fxsave_struct fx_scratch __cpuinitdata;
+
+-void mxcsr_feature_mask_init(void)
++void __cpuinit mxcsr_feature_mask_init(void)
+ {
+ unsigned long mask = 0;
++
+ clts();
+ if (cpu_has_fxsr) {
+- memset(¤t->thread.i387.fxsave, 0,
+- sizeof(struct i387_fxsave_struct));
+- asm volatile("fxsave %0" : : "m" (current->thread.i387.fxsave));
+- mask = current->thread.i387.fxsave.mxcsr_mask;
++ memset(&fx_scratch, 0, sizeof(struct i387_fxsave_struct));
++ asm volatile("fxsave %0" : : "m" (fx_scratch));
++ mask = fx_scratch.mxcsr_mask;
+ if (mask == 0)
+ mask = 0x0000ffbf;
+ }
+@@ -57,6 +54,16 @@ void mxcsr_feature_mask_init(void)
+ stts();
+ }
+
++void __init init_thread_xstate(void)
++{
++ if (cpu_has_fxsr)
++ xstate_size = sizeof(struct i387_fxsave_struct);
++#ifdef CONFIG_X86_32
++ else
++ xstate_size = sizeof(struct i387_fsave_struct);
++#endif
++}
++
+ #ifdef CONFIG_X86_64
+ /*
+ * Called at bootup to set up the initial FPU state that is later cloned
+@@ -65,14 +72,11 @@ void mxcsr_feature_mask_init(void)
+ void __cpuinit fpu_init(void)
+ {
+ unsigned long oldcr0 = read_cr0();
+- extern void __bad_fxsave_alignment(void);
+
+- if (offsetof(struct task_struct, thread.i387.fxsave) & 15)
+- __bad_fxsave_alignment();
+ set_in_cr4(X86_CR4_OSFXSR);
+ set_in_cr4(X86_CR4_OSXMMEXCPT);
+
+- write_cr0(oldcr0 & ~((1UL<<3)|(1UL<<2))); /* clear TS and EM */
++ write_cr0(oldcr0 & ~(X86_CR0_TS|X86_CR0_EM)); /* clear TS and EM */
+
+ mxcsr_feature_mask_init();
+ /* clean state in init */
+@@ -87,32 +91,44 @@ void __cpuinit fpu_init(void)
+ * value at reset if we support XMM instructions and then
+ * remeber the current task has used the FPU.
+ */
+-void init_fpu(struct task_struct *tsk)
++int init_fpu(struct task_struct *tsk)
+ {
+ if (tsk_used_math(tsk)) {
+ if (tsk == current)
+ unlazy_fpu(tsk);
+- return;
++ return 0;
++ }
++
++ /*
++ * Memory allocation at the first usage of the FPU and other state.
++ */
++ if (!tsk->thread.xstate) {
++ tsk->thread.xstate = kmem_cache_alloc(task_xstate_cachep,
++ GFP_KERNEL);
++ if (!tsk->thread.xstate)
++ return -ENOMEM;
+ }
+
+ if (cpu_has_fxsr) {
+- memset(&tsk->thread.i387.fxsave, 0,
+- sizeof(struct i387_fxsave_struct));
+- tsk->thread.i387.fxsave.cwd = 0x37f;
++ struct i387_fxsave_struct *fx = &tsk->thread.xstate->fxsave;
++
++ memset(fx, 0, xstate_size);
++ fx->cwd = 0x37f;
+ if (cpu_has_xmm)
+- tsk->thread.i387.fxsave.mxcsr = MXCSR_DEFAULT;
++ fx->mxcsr = MXCSR_DEFAULT;
+ } else {
+- memset(&tsk->thread.i387.fsave, 0,
+- sizeof(struct i387_fsave_struct));
+- tsk->thread.i387.fsave.cwd = 0xffff037fu;
+- tsk->thread.i387.fsave.swd = 0xffff0000u;
+- tsk->thread.i387.fsave.twd = 0xffffffffu;
+- tsk->thread.i387.fsave.fos = 0xffff0000u;
++ struct i387_fsave_struct *fp = &tsk->thread.xstate->fsave;
++ memset(fp, 0, xstate_size);
++ fp->cwd = 0xffff037fu;
++ fp->swd = 0xffff0000u;
++ fp->twd = 0xffffffffu;
++ fp->fos = 0xffff0000u;
+ }
+ /*
+ * Only the device not available exception or ptrace can call init_fpu.
+ */
+ set_stopped_child_used_math(tsk);
++ return 0;
+ }
+
+ int fpregs_active(struct task_struct *target, const struct user_regset *regset)
+@@ -129,13 +145,17 @@ int xfpregs_get(struct task_struct *target, const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+ {
++ int ret;
++
+ if (!cpu_has_fxsr)
+ return -ENODEV;
+
+- init_fpu(target);
++ ret = init_fpu(target);
++ if (ret)
++ return ret;
+
+ return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+- &target->thread.i387.fxsave, 0, -1);
++ &target->thread.xstate->fxsave, 0, -1);
+ }
+
+ int xfpregs_set(struct task_struct *target, const struct user_regset *regset,
+@@ -147,16 +167,19 @@ int xfpregs_set(struct task_struct *target, const struct user_regset *regset,
+ if (!cpu_has_fxsr)
+ return -ENODEV;
+
+- init_fpu(target);
++ ret = init_fpu(target);
++ if (ret)
++ return ret;
++
+ set_stopped_child_used_math(target);
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+- &target->thread.i387.fxsave, 0, -1);
++ &target->thread.xstate->fxsave, 0, -1);
+
+ /*
+ * mxcsr reserved bits must be masked to zero for security reasons.
+ */
+- target->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask;
++ target->thread.xstate->fxsave.mxcsr &= mxcsr_feature_mask;
+
+ return ret;
+ }
+@@ -178,6 +201,7 @@ static inline unsigned short twd_i387_to_fxsr(unsigned short twd)
+ tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
+ tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
+ tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
++
+ return tmp;
+ }
+
+@@ -232,10 +256,10 @@ static inline u32 twd_fxsr_to_i387(struct i387_fxsave_struct *fxsave)
+ * FXSR floating point environment conversions.
+ */
+
+-static void convert_from_fxsr(struct user_i387_ia32_struct *env,
+- struct task_struct *tsk)
++static void
++convert_from_fxsr(struct user_i387_ia32_struct *env, struct task_struct *tsk)
+ {
+- struct i387_fxsave_struct *fxsave = &tsk->thread.i387.fxsave;
++ struct i387_fxsave_struct *fxsave = &tsk->thread.xstate->fxsave;
+ struct _fpreg *to = (struct _fpreg *) &env->st_space[0];
+ struct _fpxreg *from = (struct _fpxreg *) &fxsave->st_space[0];
+ int i;
+@@ -252,10 +276,11 @@ static void convert_from_fxsr(struct user_i387_ia32_struct *env,
+ * should be actually ds/cs at fpu exception time, but
+ * that information is not available in 64bit mode.
+ */
+- asm("mov %%ds,%0" : "=r" (env->fos));
+- asm("mov %%cs,%0" : "=r" (env->fcs));
++ asm("mov %%ds, %[fos]" : [fos] "=r" (env->fos));
++ asm("mov %%cs, %[fcs]" : [fcs] "=r" (env->fcs));
+ } else {
+ struct pt_regs *regs = task_pt_regs(tsk);
++
+ env->fos = 0xffff0000 | tsk->thread.ds;
+ env->fcs = regs->cs;
+ }
+@@ -274,7 +299,7 @@ static void convert_to_fxsr(struct task_struct *tsk,
+ const struct user_i387_ia32_struct *env)
+
+ {
+- struct i387_fxsave_struct *fxsave = &tsk->thread.i387.fxsave;
++ struct i387_fxsave_struct *fxsave = &tsk->thread.xstate->fxsave;
+ struct _fpreg *from = (struct _fpreg *) &env->st_space[0];
+ struct _fpxreg *to = (struct _fpxreg *) &fxsave->st_space[0];
+ int i;
+@@ -303,15 +328,20 @@ int fpregs_get(struct task_struct *target, const struct user_regset *regset,
+ void *kbuf, void __user *ubuf)
+ {
+ struct user_i387_ia32_struct env;
++ int ret;
+
+ if (!HAVE_HWFP)
+ return fpregs_soft_get(target, regset, pos, count, kbuf, ubuf);
+
+- init_fpu(target);
++ ret = init_fpu(target);
++ if (ret)
++ return ret;
+
+- if (!cpu_has_fxsr)
++ if (!cpu_has_fxsr) {
+ return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+- &target->thread.i387.fsave, 0, -1);
++ &target->thread.xstate->fsave, 0,
++ -1);
++ }
+
+ if (kbuf && pos == 0 && count == sizeof(env)) {
+ convert_from_fxsr(kbuf, target);
+@@ -319,6 +349,7 @@ int fpregs_get(struct task_struct *target, const struct user_regset *regset,
+ }
+
+ convert_from_fxsr(&env, target);
++
+ return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &env, 0, -1);
+ }
+
+@@ -332,12 +363,16 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,
+ if (!HAVE_HWFP)
+ return fpregs_soft_set(target, regset, pos, count, kbuf, ubuf);
+
+- init_fpu(target);
++ ret = init_fpu(target);
++ if (ret)
++ return ret;
++
+ set_stopped_child_used_math(target);
+
+- if (!cpu_has_fxsr)
++ if (!cpu_has_fxsr) {
+ return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+- &target->thread.i387.fsave, 0, -1);
++ &target->thread.xstate->fsave, 0, -1);
++ }
+
+ if (pos > 0 || count < sizeof(env))
+ convert_from_fxsr(&env, target);
+@@ -356,11 +391,11 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,
+ static inline int save_i387_fsave(struct _fpstate_ia32 __user *buf)
+ {
+ struct task_struct *tsk = current;
++ struct i387_fsave_struct *fp = &tsk->thread.xstate->fsave;
+
+ unlazy_fpu(tsk);
+- tsk->thread.i387.fsave.status = tsk->thread.i387.fsave.swd;
+- if (__copy_to_user(buf, &tsk->thread.i387.fsave,
+- sizeof(struct i387_fsave_struct)))
++ fp->status = fp->swd;
++ if (__copy_to_user(buf, fp, sizeof(struct i387_fsave_struct)))
+ return -1;
+ return 1;
+ }
+@@ -368,6 +403,7 @@ static inline int save_i387_fsave(struct _fpstate_ia32 __user *buf)
+ static int save_i387_fxsave(struct _fpstate_ia32 __user *buf)
+ {
+ struct task_struct *tsk = current;
++ struct i387_fxsave_struct *fx = &tsk->thread.xstate->fxsave;
+ struct user_i387_ia32_struct env;
+ int err = 0;
+
+@@ -377,12 +413,12 @@ static int save_i387_fxsave(struct _fpstate_ia32 __user *buf)
+ if (__copy_to_user(buf, &env, sizeof(env)))
+ return -1;
+
+- err |= __put_user(tsk->thread.i387.fxsave.swd, &buf->status);
++ err |= __put_user(fx->swd, &buf->status);
+ err |= __put_user(X86_FXSR_MAGIC, &buf->magic);
+ if (err)
+ return -1;
+
+- if (__copy_to_user(&buf->_fxsr_env[0], &tsk->thread.i387.fxsave,
++ if (__copy_to_user(&buf->_fxsr_env[0], fx,
+ sizeof(struct i387_fxsave_struct)))
+ return -1;
+ return 1;
+@@ -392,46 +428,48 @@ int save_i387_ia32(struct _fpstate_ia32 __user *buf)
+ {
+ if (!used_math())
+ return 0;
+-
+- /* This will cause a "finit" to be triggered by the next
++ /*
++ * This will cause a "finit" to be triggered by the next
+ * attempted FPU operation by the 'current' process.
+ */
+ clear_used_math();
+
+- if (HAVE_HWFP) {
+- if (cpu_has_fxsr) {
+- return save_i387_fxsave(buf);
+- } else {
+- return save_i387_fsave(buf);
+- }
+- } else {
++ if (!HAVE_HWFP) {
+ return fpregs_soft_get(current, NULL,
+ 0, sizeof(struct user_i387_ia32_struct),
+ NULL, buf) ? -1 : 1;
+ }
++
++ if (cpu_has_fxsr)
++ return save_i387_fxsave(buf);
++ else
++ return save_i387_fsave(buf);
+ }
+
+ static inline int restore_i387_fsave(struct _fpstate_ia32 __user *buf)
+ {
+ struct task_struct *tsk = current;
++
+ clear_fpu(tsk);
+- return __copy_from_user(&tsk->thread.i387.fsave, buf,
++ return __copy_from_user(&tsk->thread.xstate->fsave, buf,
+ sizeof(struct i387_fsave_struct));
+ }
+
+ static int restore_i387_fxsave(struct _fpstate_ia32 __user *buf)
+ {
+- int err;
+ struct task_struct *tsk = current;
+ struct user_i387_ia32_struct env;
++ int err;
++
+ clear_fpu(tsk);
+- err = __copy_from_user(&tsk->thread.i387.fxsave, &buf->_fxsr_env[0],
++ err = __copy_from_user(&tsk->thread.xstate->fxsave, &buf->_fxsr_env[0],
+ sizeof(struct i387_fxsave_struct));
+ /* mxcsr reserved bits must be masked to zero for security reasons */
+- tsk->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask;
++ tsk->thread.xstate->fxsave.mxcsr &= mxcsr_feature_mask;
+ if (err || __copy_from_user(&env, buf, sizeof(env)))
+ return 1;
+ convert_to_fxsr(tsk, &env);
++
+ return 0;
+ }
+
+@@ -440,17 +478,17 @@ int restore_i387_ia32(struct _fpstate_ia32 __user *buf)
+ int err;
+
+ if (HAVE_HWFP) {
+- if (cpu_has_fxsr) {
++ if (cpu_has_fxsr)
+ err = restore_i387_fxsave(buf);
+- } else {
++ else
+ err = restore_i387_fsave(buf);
+- }
+ } else {
+ err = fpregs_soft_set(current, NULL,
+ 0, sizeof(struct user_i387_ia32_struct),
+ NULL, buf) != 0;
+ }
+ set_used_math();
++
+ return err;
+ }
+
+@@ -463,8 +501,8 @@ int restore_i387_ia32(struct _fpstate_ia32 __user *buf)
+ */
+ int dump_fpu(struct pt_regs *regs, struct user_i387_struct *fpu)
+ {
+- int fpvalid;
+ struct task_struct *tsk = current;
++ int fpvalid;
+
+ fpvalid = !!used_math();
+ if (fpvalid)
+diff --git a/arch/x86/kernel/i8253.c b/arch/x86/kernel/i8253.c
+index 8540abe..c1b5e3e 100644
+--- a/arch/x86/kernel/i8253.c
++++ b/arch/x86/kernel/i8253.c
+@@ -115,7 +115,8 @@ void __init setup_pit_timer(void)
+ * IO_APIC has been initialized.
+ */
+ pit_clockevent.cpumask = cpumask_of_cpu(smp_processor_id());
+- pit_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, 32);
++ pit_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
++ pit_clockevent.shift);
+ pit_clockevent.max_delta_ns =
+ clockevent_delta2ns(0x7FFF, &pit_clockevent);
+ pit_clockevent.min_delta_ns =
+@@ -224,7 +225,8 @@ static int __init init_pit_clocksource(void)
+ pit_clockevent.mode != CLOCK_EVT_MODE_PERIODIC)
+ return 0;
+
+- clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE, 20);
++ clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE,
++ clocksource_pit.shift);
+ return clocksource_register(&clocksource_pit);
+ }
+ arch_initcall(init_pit_clocksource);
+diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c
+index 4ca5486..696b8e4 100644
+--- a/arch/x86/kernel/io_apic_32.c
++++ b/arch/x86/kernel/io_apic_32.c
+@@ -71,6 +71,16 @@ int sis_apic_bug = -1;
+ */
+ int nr_ioapic_registers[MAX_IO_APICS];
+
++/* I/O APIC entries */
++struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
++int nr_ioapics;
++
++/* MP IRQ source entries */
++struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
++
++/* # of MP IRQ source entries */
++int mp_irq_entries;
++
+ static int disable_timer_pin_1 __initdata;
+
+ /*
+@@ -810,10 +820,7 @@ static int __init find_isa_irq_pin(int irq, int type)
+ for (i = 0; i < mp_irq_entries; i++) {
+ int lbus = mp_irqs[i].mpc_srcbus;
+
+- if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
+- mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
+- mp_bus_id_to_type[lbus] == MP_BUS_MCA
+- ) &&
++ if (test_bit(lbus, mp_bus_not_pci) &&
+ (mp_irqs[i].mpc_irqtype == type) &&
+ (mp_irqs[i].mpc_srcbusirq == irq))
+
+@@ -829,10 +836,7 @@ static int __init find_isa_irq_apic(int irq, int type)
+ for (i = 0; i < mp_irq_entries; i++) {
+ int lbus = mp_irqs[i].mpc_srcbus;
+
+- if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
+- mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
+- mp_bus_id_to_type[lbus] == MP_BUS_MCA
+- ) &&
++ if (test_bit(lbus, mp_bus_not_pci) &&
+ (mp_irqs[i].mpc_irqtype == type) &&
+ (mp_irqs[i].mpc_srcbusirq == irq))
+ break;
+@@ -872,7 +876,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
+ mp_irqs[i].mpc_dstapic == MP_APIC_ALL)
+ break;
+
+- if ((mp_bus_id_to_type[lbus] == MP_BUS_PCI) &&
++ if (!test_bit(lbus, mp_bus_not_pci) &&
+ !mp_irqs[i].mpc_irqtype &&
+ (bus == lbus) &&
+ (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) {
+@@ -921,6 +925,7 @@ void __init setup_ioapic_dest(void)
+ }
+ #endif
+
++#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+ /*
+ * EISA Edge/Level control register, ELCR
+ */
+@@ -934,6 +939,13 @@ static int EISA_ELCR(unsigned int irq)
+ "Broken MPtable reports ISA irq %d\n", irq);
+ return 0;
+ }
++#endif
++
++/* ISA interrupts are always polarity zero edge triggered,
++ * when listed as conforming in the MP table. */
++
++#define default_ISA_trigger(idx) (0)
++#define default_ISA_polarity(idx) (0)
+
+ /* EISA interrupts are always polarity zero and can be edge or level
+ * trigger depending on the ELCR value. If an interrupt is listed as
+@@ -941,13 +953,7 @@ static int EISA_ELCR(unsigned int irq)
+ * be read in from the ELCR */
+
+ #define default_EISA_trigger(idx) (EISA_ELCR(mp_irqs[idx].mpc_srcbusirq))
+-#define default_EISA_polarity(idx) (0)
+-
+-/* ISA interrupts are always polarity zero edge triggered,
+- * when listed as conforming in the MP table. */
+-
+-#define default_ISA_trigger(idx) (0)
+-#define default_ISA_polarity(idx) (0)
++#define default_EISA_polarity(idx) default_ISA_polarity(idx)
+
+ /* PCI interrupts are always polarity one level triggered,
+ * when listed as conforming in the MP table. */
+@@ -959,7 +965,7 @@ static int EISA_ELCR(unsigned int irq)
+ * when listed as conforming in the MP table. */
+
+ #define default_MCA_trigger(idx) (1)
+-#define default_MCA_polarity(idx) (0)
++#define default_MCA_polarity(idx) default_ISA_polarity(idx)
+
+ static int MPBIOS_polarity(int idx)
+ {
+@@ -973,35 +979,9 @@ static int MPBIOS_polarity(int idx)
+ {
+ case 0: /* conforms, ie. bus-type dependent polarity */
+ {
+- switch (mp_bus_id_to_type[bus])
+- {
+- case MP_BUS_ISA: /* ISA pin */
+- {
+- polarity = default_ISA_polarity(idx);
+- break;
+- }
+- case MP_BUS_EISA: /* EISA pin */
+- {
+- polarity = default_EISA_polarity(idx);
+- break;
+- }
+- case MP_BUS_PCI: /* PCI pin */
+- {
+- polarity = default_PCI_polarity(idx);
+- break;
+- }
+- case MP_BUS_MCA: /* MCA pin */
+- {
+- polarity = default_MCA_polarity(idx);
+- break;
+- }
+- default:
+- {
+- printk(KERN_WARNING "broken BIOS!!\n");
+- polarity = 1;
+- break;
+- }
+- }
++ polarity = test_bit(bus, mp_bus_not_pci)?
++ default_ISA_polarity(idx):
++ default_PCI_polarity(idx);
+ break;
+ }
+ case 1: /* high active */
+@@ -1042,11 +1022,15 @@ static int MPBIOS_trigger(int idx)
+ {
+ case 0: /* conforms, ie. bus-type dependent */
+ {
++ trigger = test_bit(bus, mp_bus_not_pci)?
++ default_ISA_trigger(idx):
++ default_PCI_trigger(idx);
++#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+ switch (mp_bus_id_to_type[bus])
+ {
+ case MP_BUS_ISA: /* ISA pin */
+ {
+- trigger = default_ISA_trigger(idx);
++ /* set before the switch */
+ break;
+ }
+ case MP_BUS_EISA: /* EISA pin */
+@@ -1056,7 +1040,7 @@ static int MPBIOS_trigger(int idx)
+ }
+ case MP_BUS_PCI: /* PCI pin */
+ {
+- trigger = default_PCI_trigger(idx);
++ /* set before the switch */
+ break;
+ }
+ case MP_BUS_MCA: /* MCA pin */
+@@ -1071,6 +1055,7 @@ static int MPBIOS_trigger(int idx)
+ break;
+ }
+ }
++#endif
+ break;
+ }
+ case 1: /* edge */
+@@ -1120,39 +1105,22 @@ static int pin_2_irq(int idx, int apic, int pin)
+ if (mp_irqs[idx].mpc_dstirq != pin)
+ printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");
+
+- switch (mp_bus_id_to_type[bus])
+- {
+- case MP_BUS_ISA: /* ISA pin */
+- case MP_BUS_EISA:
+- case MP_BUS_MCA:
+- {
+- irq = mp_irqs[idx].mpc_srcbusirq;
+- break;
+- }
+- case MP_BUS_PCI: /* PCI pin */
+- {
+- /*
+- * PCI IRQs are mapped in order
+- */
+- i = irq = 0;
+- while (i < apic)
+- irq += nr_ioapic_registers[i++];
+- irq += pin;
+-
+- /*
+- * For MPS mode, so far only needed by ES7000 platform
+- */
+- if (ioapic_renumber_irq)
+- irq = ioapic_renumber_irq(apic, irq);
++ if (test_bit(bus, mp_bus_not_pci))
++ irq = mp_irqs[idx].mpc_srcbusirq;
++ else {
++ /*
++ * PCI IRQs are mapped in order
++ */
++ i = irq = 0;
++ while (i < apic)
++ irq += nr_ioapic_registers[i++];
++ irq += pin;
+
+- break;
+- }
+- default:
+- {
+- printk(KERN_ERR "unknown bus type %d.\n",bus);
+- irq = 0;
+- break;
+- }
++ /*
++ * For MPS mode, so far only needed by ES7000 platform
++ */
++ if (ioapic_renumber_irq)
++ irq = ioapic_renumber_irq(apic, irq);
+ }
+
+ /*
+@@ -1260,7 +1228,6 @@ static void __init setup_IO_APIC_irqs(void)
+ {
+ struct IO_APIC_route_entry entry;
+ int apic, pin, idx, irq, first_notcon = 1, vector;
+- unsigned long flags;
+
+ apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
+
+@@ -1326,9 +1293,7 @@ static void __init setup_IO_APIC_irqs(void)
+ if (!apic && (irq < 16))
+ disable_8259A_irq(irq);
+ }
+- spin_lock_irqsave(&ioapic_lock, flags);
+- __ioapic_write_entry(apic, pin, entry);
+- spin_unlock_irqrestore(&ioapic_lock, flags);
++ ioapic_write_entry(apic, pin, entry);
+ }
+ }
+
+@@ -1524,8 +1489,8 @@ void /*__init*/ print_local_APIC(void * dummy)
+
+ printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
+ smp_processor_id(), hard_smp_processor_id());
+- v = apic_read(APIC_ID);
+- printk(KERN_INFO "... APIC ID: %08x (%01x)\n", v, GET_APIC_ID(v));
++ printk(KERN_INFO "... APIC ID: %08x (%01x)\n", v,
++ GET_APIC_ID(read_apic_id()));
+ v = apic_read(APIC_LVR);
+ printk(KERN_INFO "... APIC VERSION: %08x\n", v);
+ ver = GET_APIC_VERSION(v);
+@@ -1734,7 +1699,7 @@ void disable_IO_APIC(void)
+ entry.delivery_mode = dest_ExtINT; /* ExtInt */
+ entry.vector = 0;
+ entry.dest.physical.physical_dest =
+- GET_APIC_ID(apic_read(APIC_ID));
++ GET_APIC_ID(read_apic_id());
+
+ /*
+ * Add it to the IO-APIC irq-routing table:
+@@ -2031,8 +1996,7 @@ static inline void init_IO_APIC_traps(void)
+ * 0x80, because int 0x80 is hm, kind of importantish. ;)
+ */
+ for (irq = 0; irq < NR_IRQS ; irq++) {
+- int tmp = irq;
+- if (IO_APIC_IRQ(tmp) && !irq_vector[tmp]) {
++ if (IO_APIC_IRQ(irq) && !irq_vector[irq]) {
+ /*
+ * Hmm.. We don't have an entry for this,
+ * so default to an old-fashioned 8259
+@@ -2104,7 +2068,7 @@ static void __init setup_nmi(void)
+ * cycles as some i82489DX-based boards have glue logic that keeps the
+ * 8259A interrupt line asserted until INTA. --macro
+ */
+-static inline void unlock_ExtINT_logic(void)
++static inline void __init unlock_ExtINT_logic(void)
+ {
+ int apic, pin, i;
+ struct IO_APIC_route_entry entry0, entry1;
+@@ -2156,8 +2120,6 @@ static inline void unlock_ExtINT_logic(void)
+ ioapic_write_entry(apic, pin, entry0);
+ }
+
+-int timer_uses_ioapic_pin_0;
+-
+ /*
+ * This code may look a bit paranoid, but it's supposed to cooperate with
+ * a wide range of boards and BIOS bugs. Fortunately only the timer IRQ
+@@ -2168,10 +2130,14 @@ static inline void __init check_timer(void)
+ {
+ int apic1, pin1, apic2, pin2;
+ int vector;
++ unsigned int ver;
+ unsigned long flags;
+
+ local_irq_save(flags);
+
++ ver = apic_read(APIC_LVR);
++ ver = GET_APIC_VERSION(ver);
++
+ /*
+ * get/set the timer IRQ vector:
+ */
+@@ -2184,11 +2150,15 @@ static inline void __init check_timer(void)
+ * mode for the 8259A whenever interrupts are routed
+ * through I/O APICs. Also IRQ0 has to be enabled in
+ * the 8259A which implies the virtual wire has to be
+- * disabled in the local APIC.
++ * disabled in the local APIC. Finally timer interrupts
++ * need to be acknowledged manually in the 8259A for
++ * timer_interrupt() and for the i82489DX when using
++ * the NMI watchdog.
+ */
+ apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
+ init_8259A(1);
+- timer_ack = 1;
++ timer_ack = !cpu_has_tsc;
++ timer_ack |= (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver));
+ if (timer_over_8254 > 0)
+ enable_8259A_irq(0);
+
+@@ -2197,9 +2167,6 @@ static inline void __init check_timer(void)
+ pin2 = ioapic_i8259.pin;
+ apic2 = ioapic_i8259.apic;
+
+- if (pin1 == 0)
+- timer_uses_ioapic_pin_0 = 1;
+-
+ printk(KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
+ vector, apic1, pin1, apic2, pin2);
+
+@@ -2789,7 +2756,6 @@ int __init io_apic_get_redir_entries (int ioapic)
+ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low)
+ {
+ struct IO_APIC_route_entry entry;
+- unsigned long flags;
+
+ if (!IO_APIC_IRQ(irq)) {
+ printk(KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
+@@ -2830,9 +2796,7 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
+ if (!ioapic && (irq < 16))
+ disable_8259A_irq(irq);
+
+- spin_lock_irqsave(&ioapic_lock, flags);
+- __ioapic_write_entry(ioapic, pin, entry);
+- spin_unlock_irqrestore(&ioapic_lock, flags);
++ ioapic_write_entry(ioapic, pin, entry);
+
+ return 0;
+ }
+diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c
+index 1627c0d..ef1a8df 100644
+--- a/arch/x86/kernel/io_apic_64.c
++++ b/arch/x86/kernel/io_apic_64.c
+@@ -43,13 +43,15 @@
+ #include <asm/smp.h>
+ #include <asm/desc.h>
+ #include <asm/proto.h>
+-#include <asm/mach_apic.h>
+ #include <asm/acpi.h>
+ #include <asm/dma.h>
+ #include <asm/nmi.h>
+ #include <asm/msidef.h>
+ #include <asm/hypertransport.h>
+
++#include <mach_ipi.h>
++#include <mach_apic.h>
++
+ struct irq_cfg {
+ cpumask_t domain;
+ cpumask_t old_domain;
+@@ -101,6 +103,16 @@ DEFINE_SPINLOCK(vector_lock);
+ */
+ int nr_ioapic_registers[MAX_IO_APICS];
+
++/* I/O APIC entries */
++struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
++int nr_ioapics;
++
++/* MP IRQ source entries */
++struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
++
++/* # of MP IRQ source entries */
++int mp_irq_entries;
++
+ /*
+ * Rough estimation of how many shared IRQs there are, can
+ * be changed anytime.
+@@ -155,11 +167,10 @@ static inline void io_apic_modify(unsigned int apic, unsigned int value)
+ writel(value, &io_apic->data);
+ }
+
+-static int io_apic_level_ack_pending(unsigned int irq)
++static bool io_apic_level_ack_pending(unsigned int irq)
+ {
+ struct irq_pin_list *entry;
+ unsigned long flags;
+- int pending = 0;
+
+ spin_lock_irqsave(&ioapic_lock, flags);
+ entry = irq_2_pin + irq;
+@@ -172,13 +183,17 @@ static int io_apic_level_ack_pending(unsigned int irq)
+ break;
+ reg = io_apic_read(entry->apic, 0x10 + pin*2);
+ /* Is the remote IRR bit set? */
+- pending |= (reg >> 14) & 1;
++ if ((reg >> 14) & 1) {
++ spin_unlock_irqrestore(&ioapic_lock, flags);
++ return true;
++ }
+ if (!entry->next)
+ break;
+ entry = irq_2_pin + entry->next;
+ }
+ spin_unlock_irqrestore(&ioapic_lock, flags);
+- return pending;
++
++ return false;
+ }
+
+ /*
+@@ -770,7 +785,7 @@ static void __clear_irq_vector(int irq)
+ per_cpu(vector_irq, cpu)[vector] = -1;
+
+ cfg->vector = 0;
+- cfg->domain = CPU_MASK_NONE;
++ cpus_clear(cfg->domain);
+ }
+
+ void __setup_vector_irq(int cpu)
+@@ -902,9 +917,8 @@ static void __init setup_IO_APIC_irqs(void)
+ static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector)
+ {
+ struct IO_APIC_route_entry entry;
+- unsigned long flags;
+
+- memset(&entry,0,sizeof(entry));
++ memset(&entry, 0, sizeof(entry));
+
+ disable_8259A_irq(0);
+
+@@ -932,10 +946,7 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, in
+ /*
+ * Add it to the IO-APIC irq-routing table:
+ */
+- spin_lock_irqsave(&ioapic_lock, flags);
+- io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
+- io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
+- spin_unlock_irqrestore(&ioapic_lock, flags);
++ ioapic_write_entry(apic, pin, entry);
+
+ enable_8259A_irq(0);
+ }
+@@ -1066,8 +1077,7 @@ void __apicdebuginit print_local_APIC(void * dummy)
+
+ printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
+ smp_processor_id(), hard_smp_processor_id());
+- v = apic_read(APIC_ID);
+- printk(KERN_INFO "... APIC ID: %08x (%01x)\n", v, GET_APIC_ID(v));
++ printk(KERN_INFO "... APIC ID: %08x (%01x)\n", v, GET_APIC_ID(read_apic_id()));
+ v = apic_read(APIC_LVR);
+ printk(KERN_INFO "... APIC VERSION: %08x\n", v);
+ ver = GET_APIC_VERSION(v);
+@@ -1261,7 +1271,7 @@ void disable_IO_APIC(void)
+ entry.dest_mode = 0; /* Physical */
+ entry.delivery_mode = dest_ExtINT; /* ExtInt */
+ entry.vector = 0;
+- entry.dest = GET_APIC_ID(apic_read(APIC_ID));
++ entry.dest = GET_APIC_ID(read_apic_id());
+
+ /*
+ * Add it to the IO-APIC irq-routing table:
+@@ -1352,9 +1362,7 @@ static int ioapic_retrigger_irq(unsigned int irq)
+ unsigned long flags;
+
+ spin_lock_irqsave(&vector_lock, flags);
+- cpus_clear(mask);
+- cpu_set(first_cpu(cfg->domain), mask);
+-
++ mask = cpumask_of_cpu(first_cpu(cfg->domain));
+ send_IPI_mask(mask, cfg->vector);
+ spin_unlock_irqrestore(&vector_lock, flags);
+
+@@ -1517,8 +1525,7 @@ static inline void init_IO_APIC_traps(void)
+ * 0x80, because int 0x80 is hm, kind of importantish. ;)
+ */
+ for (irq = 0; irq < NR_IRQS ; irq++) {
+- int tmp = irq;
+- if (IO_APIC_IRQ(tmp) && !irq_cfg[tmp].vector) {
++ if (IO_APIC_IRQ(irq) && !irq_cfg[irq].vector) {
+ /*
+ * Hmm.. We don't have an entry for this,
+ * so default to an old-fashioned 8259
+@@ -1592,22 +1599,19 @@ static void __init setup_nmi(void)
+ * cycles as some i82489DX-based boards have glue logic that keeps the
+ * 8259A interrupt line asserted until INTA. --macro
+ */
+-static inline void unlock_ExtINT_logic(void)
++static inline void __init unlock_ExtINT_logic(void)
+ {
+ int apic, pin, i;
+ struct IO_APIC_route_entry entry0, entry1;
+ unsigned char save_control, save_freq_select;
+- unsigned long flags;
+
+ pin = find_isa_irq_pin(8, mp_INT);
+ apic = find_isa_irq_apic(8, mp_INT);
+ if (pin == -1)
+ return;
+
+- spin_lock_irqsave(&ioapic_lock, flags);
+- *(((int *)&entry0) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
+- *(((int *)&entry0) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
+- spin_unlock_irqrestore(&ioapic_lock, flags);
++ entry0 = ioapic_read_entry(apic, pin);
++
+ clear_IO_APIC_pin(apic, pin);
+
+ memset(&entry1, 0, sizeof(entry1));
+@@ -1620,10 +1624,7 @@ static inline void unlock_ExtINT_logic(void)
+ entry1.trigger = 0;
+ entry1.vector = 0;
+
+- spin_lock_irqsave(&ioapic_lock, flags);
+- io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry1) + 1));
+- io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry1) + 0));
+- spin_unlock_irqrestore(&ioapic_lock, flags);
++ ioapic_write_entry(apic, pin, entry1);
+
+ save_control = CMOS_READ(RTC_CONTROL);
+ save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
+@@ -1642,10 +1643,7 @@ static inline void unlock_ExtINT_logic(void)
+ CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+ clear_IO_APIC_pin(apic, pin);
+
+- spin_lock_irqsave(&ioapic_lock, flags);
+- io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry0) + 1));
+- io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry0) + 0));
+- spin_unlock_irqrestore(&ioapic_lock, flags);
++ ioapic_write_entry(apic, pin, entry0);
+ }
+
+ /*
+@@ -2314,7 +2312,6 @@ static struct resource * __init ioapic_setup_resources(void)
+ res = (void *)mem;
+
+ if (mem != NULL) {
+- memset(mem, 0, n);
+ mem += sizeof(struct resource) * nr_ioapics;
+
+ for (i = 0; i < nr_ioapics; i++) {
+diff --git a/arch/x86/kernel/ipi.c b/arch/x86/kernel/ipi.c
+new file mode 100644
+index 0000000..c0df7b8
+--- /dev/null
++++ b/arch/x86/kernel/ipi.c
+@@ -0,0 +1,178 @@
++#include <linux/cpumask.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++
++#include <linux/mm.h>
++#include <linux/delay.h>
++#include <linux/spinlock.h>
++#include <linux/kernel_stat.h>
++#include <linux/mc146818rtc.h>
++#include <linux/cache.h>
++#include <linux/interrupt.h>
++#include <linux/cpu.h>
++#include <linux/module.h>
++
++#include <asm/smp.h>
++#include <asm/mtrr.h>
++#include <asm/tlbflush.h>
++#include <asm/mmu_context.h>
++#include <asm/apic.h>
++#include <asm/proto.h>
++
++#ifdef CONFIG_X86_32
++#include <mach_apic.h>
++/*
++ * the following functions deal with sending IPIs between CPUs.
++ *
++ * We use 'broadcast', CPU->CPU IPIs and self-IPIs too.
++ */
++
++static inline int __prepare_ICR(unsigned int shortcut, int vector)
++{
++ unsigned int icr = shortcut | APIC_DEST_LOGICAL;
++
++ switch (vector) {
++ default:
++ icr |= APIC_DM_FIXED | vector;
++ break;
++ case NMI_VECTOR:
++ icr |= APIC_DM_NMI;
++ break;
++ }
++ return icr;
++}
++
++static inline int __prepare_ICR2(unsigned int mask)
++{
++ return SET_APIC_DEST_FIELD(mask);
++}
++
++void __send_IPI_shortcut(unsigned int shortcut, int vector)
++{
++ /*
++ * Subtle. In the case of the 'never do double writes' workaround
++ * we have to lock out interrupts to be safe. As we don't care
++ * of the value read we use an atomic rmw access to avoid costly
++ * cli/sti. Otherwise we use an even cheaper single atomic write
++ * to the APIC.
++ */
++ unsigned int cfg;
++
++ /*
++ * Wait for idle.
++ */
++ apic_wait_icr_idle();
++
++ /*
++ * No need to touch the target chip field
++ */
++ cfg = __prepare_ICR(shortcut, vector);
++
++ /*
++ * Send the IPI. The write to APIC_ICR fires this off.
++ */
++ apic_write_around(APIC_ICR, cfg);
++}
++
++void send_IPI_self(int vector)
++{
++ __send_IPI_shortcut(APIC_DEST_SELF, vector);
++}
++
++/*
++ * This is used to send an IPI with no shorthand notation (the destination is
++ * specified in bits 56 to 63 of the ICR).
++ */
++static inline void __send_IPI_dest_field(unsigned long mask, int vector)
++{
++ unsigned long cfg;
++
++ /*
++ * Wait for idle.
++ */
++ if (unlikely(vector == NMI_VECTOR))
++ safe_apic_wait_icr_idle();
++ else
++ apic_wait_icr_idle();
++
++ /*
++ * prepare target chip field
++ */
++ cfg = __prepare_ICR2(mask);
++ apic_write_around(APIC_ICR2, cfg);
++
++ /*
++ * program the ICR
++ */
++ cfg = __prepare_ICR(0, vector);
++
++ /*
++ * Send the IPI. The write to APIC_ICR fires this off.
++ */
++ apic_write_around(APIC_ICR, cfg);
++}
++
++/*
++ * This is only used on smaller machines.
++ */
++void send_IPI_mask_bitmask(cpumask_t cpumask, int vector)
++{
++ unsigned long mask = cpus_addr(cpumask)[0];
++ unsigned long flags;
++
++ local_irq_save(flags);
++ WARN_ON(mask & ~cpus_addr(cpu_online_map)[0]);
++ __send_IPI_dest_field(mask, vector);
++ local_irq_restore(flags);
++}
++
++void send_IPI_mask_sequence(cpumask_t mask, int vector)
++{
++ unsigned long flags;
++ unsigned int query_cpu;
++
++ /*
++ * Hack. The clustered APIC addressing mode doesn't allow us to send
++ * to an arbitrary mask, so I do a unicasts to each CPU instead. This
++ * should be modified to do 1 message per cluster ID - mbligh
++ */
++
++ local_irq_save(flags);
++ for_each_possible_cpu(query_cpu) {
++ if (cpu_isset(query_cpu, mask)) {
++ __send_IPI_dest_field(cpu_to_logical_apicid(query_cpu),
++ vector);
++ }
++ }
++ local_irq_restore(flags);
++}
++
++/* must come after the send_IPI functions above for inlining */
++#include <mach_ipi.h>
++static int convert_apicid_to_cpu(int apic_id)
++{
++ int i;
++
++ for_each_possible_cpu(i) {
++ if (per_cpu(x86_cpu_to_apicid, i) == apic_id)
++ return i;
++ }
++ return -1;
++}
++
++int safe_smp_processor_id(void)
++{
++ int apicid, cpuid;
++
++ if (!boot_cpu_has(X86_FEATURE_APIC))
++ return 0;
++
++ apicid = hard_smp_processor_id();
++ if (apicid == BAD_APICID)
++ return 0;
++
++ cpuid = convert_apicid_to_cpu(apicid);
++
++ return cpuid >= 0 ? cpuid : 0;
++}
++#endif
+diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c
+index cef054b..00bda7b 100644
+--- a/arch/x86/kernel/irq_32.c
++++ b/arch/x86/kernel/irq_32.c
+@@ -79,7 +79,7 @@ unsigned int do_IRQ(struct pt_regs *regs)
+
+ if (unlikely((unsigned)irq >= NR_IRQS)) {
+ printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
+- __FUNCTION__, irq);
++ __func__, irq);
+ BUG();
+ }
+
+@@ -134,7 +134,7 @@ unsigned int do_IRQ(struct pt_regs *regs)
+ : "=a" (arg1), "=d" (arg2), "=b" (bx)
+ : "0" (irq), "1" (desc), "2" (isp),
+ "D" (desc->handle_irq)
+- : "memory", "cc"
++ : "memory", "cc", "ecx"
+ );
+ } else
+ #endif
+diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
+new file mode 100644
+index 0000000..f47f0eb
+--- /dev/null
++++ b/arch/x86/kernel/kgdb.c
+@@ -0,0 +1,567 @@
++/*
++ * 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, 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.
++ *
++ */
++
++/*
++ * Copyright (C) 2004 Amit S. Kale <amitkale at linsyssoft.com>
++ * Copyright (C) 2000-2001 VERITAS Software Corporation.
++ * Copyright (C) 2002 Andi Kleen, SuSE Labs
++ * Copyright (C) 2004 LinSysSoft Technologies Pvt. Ltd.
++ * Copyright (C) 2007 MontaVista Software, Inc.
++ * Copyright (C) 2007-2008 Jason Wessel, Wind River Systems, Inc.
++ */
++/****************************************************************************
++ * Contributor: Lake Stevens Instrument Division$
++ * Written by: Glenn Engel $
++ * Updated by: Amit Kale<akale at veritas.com>
++ * Updated by: Tom Rini <trini at kernel.crashing.org>
++ * Updated by: Jason Wessel <jason.wessel at windriver.com>
++ * Modified for 386 by Jim Kingdon, Cygnus Support.
++ * Origianl kgdb, compatibility with 2.1.xx kernel by
++ * David Grothe <dave at gcom.com>
++ * Integrated into 2.2.5 kernel by Tigran Aivazian <tigran at sco.com>
++ * X86_64 changes from Andi Kleen's patch merged by Jim Houston
++ */
++#include <linux/spinlock.h>
++#include <linux/kdebug.h>
++#include <linux/string.h>
++#include <linux/kernel.h>
++#include <linux/ptrace.h>
++#include <linux/sched.h>
++#include <linux/delay.h>
++#include <linux/kgdb.h>
++#include <linux/init.h>
++#include <linux/smp.h>
++#include <linux/nmi.h>
++
++#include <asm/apicdef.h>
++#include <asm/system.h>
++
++#include <mach_ipi.h>
++
++/*
++ * Put the error code here just in case the user cares:
++ */
++static int gdb_x86errcode;
++
++/*
++ * Likewise, the vector number here (since GDB only gets the signal
++ * number through the usual means, and that's not very specific):
++ */
++static int gdb_x86vector = -1;
++
++/**
++ * pt_regs_to_gdb_regs - Convert ptrace regs to GDB regs
++ * @gdb_regs: A pointer to hold the registers in the order GDB wants.
++ * @regs: The &struct pt_regs of the current process.
++ *
++ * Convert the pt_regs in @regs into the format for registers that
++ * GDB expects, stored in @gdb_regs.
++ */
++void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
++{
++ gdb_regs[GDB_AX] = regs->ax;
++ gdb_regs[GDB_BX] = regs->bx;
++ gdb_regs[GDB_CX] = regs->cx;
++ gdb_regs[GDB_DX] = regs->dx;
++ gdb_regs[GDB_SI] = regs->si;
++ gdb_regs[GDB_DI] = regs->di;
++ gdb_regs[GDB_BP] = regs->bp;
++ gdb_regs[GDB_PS] = regs->flags;
++ gdb_regs[GDB_PC] = regs->ip;
++#ifdef CONFIG_X86_32
++ gdb_regs[GDB_DS] = regs->ds;
++ gdb_regs[GDB_ES] = regs->es;
++ gdb_regs[GDB_CS] = regs->cs;
++ gdb_regs[GDB_SS] = __KERNEL_DS;
++ gdb_regs[GDB_FS] = 0xFFFF;
++ gdb_regs[GDB_GS] = 0xFFFF;
++#else
++ gdb_regs[GDB_R8] = regs->r8;
++ gdb_regs[GDB_R9] = regs->r9;
++ gdb_regs[GDB_R10] = regs->r10;
++ gdb_regs[GDB_R11] = regs->r11;
++ gdb_regs[GDB_R12] = regs->r12;
++ gdb_regs[GDB_R13] = regs->r13;
++ gdb_regs[GDB_R14] = regs->r14;
++ gdb_regs[GDB_R15] = regs->r15;
++#endif
++ gdb_regs[GDB_SP] = regs->sp;
++}
++
++/**
++ * sleeping_thread_to_gdb_regs - Convert ptrace regs to GDB regs
++ * @gdb_regs: A pointer to hold the registers in the order GDB wants.
++ * @p: The &struct task_struct of the desired process.
++ *
++ * Convert the register values of the sleeping process in @p to
++ * the format that GDB expects.
++ * This function is called when kgdb does not have access to the
++ * &struct pt_regs and therefore it should fill the gdb registers
++ * @gdb_regs with what has been saved in &struct thread_struct
++ * thread field during switch_to.
++ */
++void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
++{
++ gdb_regs[GDB_AX] = 0;
++ gdb_regs[GDB_BX] = 0;
++ gdb_regs[GDB_CX] = 0;
++ gdb_regs[GDB_DX] = 0;
++ gdb_regs[GDB_SI] = 0;
++ gdb_regs[GDB_DI] = 0;
++ gdb_regs[GDB_BP] = *(unsigned long *)p->thread.sp;
++#ifdef CONFIG_X86_32
++ gdb_regs[GDB_DS] = __KERNEL_DS;
++ gdb_regs[GDB_ES] = __KERNEL_DS;
++ gdb_regs[GDB_PS] = 0;
++ gdb_regs[GDB_CS] = __KERNEL_CS;
++ gdb_regs[GDB_PC] = p->thread.ip;
++ gdb_regs[GDB_SS] = __KERNEL_DS;
++ gdb_regs[GDB_FS] = 0xFFFF;
++ gdb_regs[GDB_GS] = 0xFFFF;
++#else
++ gdb_regs[GDB_PS] = *(unsigned long *)(p->thread.sp + 8);
++ gdb_regs[GDB_PC] = 0;
++ gdb_regs[GDB_R8] = 0;
++ gdb_regs[GDB_R9] = 0;
++ gdb_regs[GDB_R10] = 0;
++ gdb_regs[GDB_R11] = 0;
++ gdb_regs[GDB_R12] = 0;
++ gdb_regs[GDB_R13] = 0;
++ gdb_regs[GDB_R14] = 0;
++ gdb_regs[GDB_R15] = 0;
++#endif
++ gdb_regs[GDB_SP] = p->thread.sp;
++}
++
++/**
++ * gdb_regs_to_pt_regs - Convert GDB regs to ptrace regs.
++ * @gdb_regs: A pointer to hold the registers we've received from GDB.
++ * @regs: A pointer to a &struct pt_regs to hold these values in.
++ *
++ * Convert the GDB regs in @gdb_regs into the pt_regs, and store them
++ * in @regs.
++ */
++void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
++{
++ regs->ax = gdb_regs[GDB_AX];
++ regs->bx = gdb_regs[GDB_BX];
++ regs->cx = gdb_regs[GDB_CX];
++ regs->dx = gdb_regs[GDB_DX];
++ regs->si = gdb_regs[GDB_SI];
++ regs->di = gdb_regs[GDB_DI];
++ regs->bp = gdb_regs[GDB_BP];
++ regs->flags = gdb_regs[GDB_PS];
++ regs->ip = gdb_regs[GDB_PC];
++#ifdef CONFIG_X86_32
++ regs->ds = gdb_regs[GDB_DS];
++ regs->es = gdb_regs[GDB_ES];
++ regs->cs = gdb_regs[GDB_CS];
++#else
++ regs->r8 = gdb_regs[GDB_R8];
++ regs->r9 = gdb_regs[GDB_R9];
++ regs->r10 = gdb_regs[GDB_R10];
++ regs->r11 = gdb_regs[GDB_R11];
++ regs->r12 = gdb_regs[GDB_R12];
++ regs->r13 = gdb_regs[GDB_R13];
++ regs->r14 = gdb_regs[GDB_R14];
++ regs->r15 = gdb_regs[GDB_R15];
++#endif
++}
++
++static struct hw_breakpoint {
++ unsigned enabled;
++ unsigned type;
++ unsigned len;
++ unsigned long addr;
++} breakinfo[4];
++
++static void kgdb_correct_hw_break(void)
++{
++ unsigned long dr7;
++ int correctit = 0;
++ int breakbit;
++ int breakno;
++
++ get_debugreg(dr7, 7);
++ for (breakno = 0; breakno < 4; breakno++) {
++ breakbit = 2 << (breakno << 1);
++ if (!(dr7 & breakbit) && breakinfo[breakno].enabled) {
++ correctit = 1;
++ dr7 |= breakbit;
++ dr7 &= ~(0xf0000 << (breakno << 2));
++ dr7 |= ((breakinfo[breakno].len << 2) |
++ breakinfo[breakno].type) <<
++ ((breakno << 2) + 16);
++ if (breakno >= 0 && breakno <= 3)
++ set_debugreg(breakinfo[breakno].addr, breakno);
++
++ } else {
++ if ((dr7 & breakbit) && !breakinfo[breakno].enabled) {
++ correctit = 1;
++ dr7 &= ~breakbit;
++ dr7 &= ~(0xf0000 << (breakno << 2));
++ }
++ }
++ }
++ if (correctit)
++ set_debugreg(dr7, 7);
++}
++
++static int
++kgdb_remove_hw_break(unsigned long addr, int len, enum kgdb_bptype bptype)
++{
++ int i;
++
++ for (i = 0; i < 4; i++)
++ if (breakinfo[i].addr == addr && breakinfo[i].enabled)
++ break;
++ if (i == 4)
++ return -1;
++
++ breakinfo[i].enabled = 0;
++
++ return 0;
++}
++
++static void kgdb_remove_all_hw_break(void)
++{
++ int i;
++
++ for (i = 0; i < 4; i++)
++ memset(&breakinfo[i], 0, sizeof(struct hw_breakpoint));
++}
++
++static int
++kgdb_set_hw_break(unsigned long addr, int len, enum kgdb_bptype bptype)
++{
++ unsigned type;
++ int i;
++
++ for (i = 0; i < 4; i++)
++ if (!breakinfo[i].enabled)
++ break;
++ if (i == 4)
++ return -1;
++
++ switch (bptype) {
++ case BP_HARDWARE_BREAKPOINT:
++ type = 0;
++ len = 1;
++ break;
++ case BP_WRITE_WATCHPOINT:
++ type = 1;
++ break;
++ case BP_ACCESS_WATCHPOINT:
++ type = 3;
++ break;
++ default:
++ return -1;
++ }
++
++ if (len == 1 || len == 2 || len == 4)
++ breakinfo[i].len = len - 1;
++ else
++ return -1;
++
++ breakinfo[i].enabled = 1;
++ breakinfo[i].addr = addr;
++ breakinfo[i].type = type;
++
++ return 0;
++}
++
++/**
++ * kgdb_disable_hw_debug - Disable hardware debugging while we in kgdb.
++ * @regs: Current &struct pt_regs.
++ *
++ * This function will be called if the particular architecture must
++ * disable hardware debugging while it is processing gdb packets or
++ * handling exception.
++ */
++void kgdb_disable_hw_debug(struct pt_regs *regs)
++{
++ /* Disable hardware debugging while we are in kgdb: */
++ set_debugreg(0UL, 7);
++}
++
++/**
++ * kgdb_post_primary_code - Save error vector/code numbers.
++ * @regs: Original pt_regs.
++ * @e_vector: Original error vector.
++ * @err_code: Original error code.
++ *
++ * This is needed on architectures which support SMP and KGDB.
++ * This function is called after all the slave cpus have been put
++ * to a know spin state and the primary CPU has control over KGDB.
++ */
++void kgdb_post_primary_code(struct pt_regs *regs, int e_vector, int err_code)
++{
++ /* primary processor is completely in the debugger */
++ gdb_x86vector = e_vector;
++ gdb_x86errcode = err_code;
++}
++
++#ifdef CONFIG_SMP
++/**
++ * kgdb_roundup_cpus - Get other CPUs into a holding pattern
++ * @flags: Current IRQ state
++ *
++ * On SMP systems, we need to get the attention of the other CPUs
++ * and get them be in a known state. This should do what is needed
++ * to get the other CPUs to call kgdb_wait(). Note that on some arches,
++ * the NMI approach is not used for rounding up all the CPUs. For example,
++ * in case of MIPS, smp_call_function() is used to roundup CPUs. In
++ * this case, we have to make sure that interrupts are enabled before
++ * calling smp_call_function(). The argument to this function is
++ * the flags that will be used when restoring the interrupts. There is
++ * local_irq_save() call before kgdb_roundup_cpus().
++ *
++ * On non-SMP systems, this is not called.
++ */
++void kgdb_roundup_cpus(unsigned long flags)
++{
++ send_IPI_allbutself(APIC_DM_NMI);
++}
++#endif
++
++/**
++ * kgdb_arch_handle_exception - Handle architecture specific GDB packets.
++ * @vector: The error vector of the exception that happened.
++ * @signo: The signal number of the exception that happened.
++ * @err_code: The error code of the exception that happened.
++ * @remcom_in_buffer: The buffer of the packet we have read.
++ * @remcom_out_buffer: The buffer of %BUFMAX bytes to write a packet into.
++ * @regs: The &struct pt_regs of the current process.
++ *
++ * This function MUST handle the 'c' and 's' command packets,
++ * as well packets to set / remove a hardware breakpoint, if used.
++ * If there are additional packets which the hardware needs to handle,
++ * they are handled here. The code should return -1 if it wants to
++ * process more packets, and a %0 or %1 if it wants to exit from the
++ * kgdb callback.
++ */
++int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
++ char *remcomInBuffer, char *remcomOutBuffer,
++ struct pt_regs *linux_regs)
++{
++ unsigned long addr;
++ unsigned long dr6;
++ char *ptr;
++ int newPC;
++
++ switch (remcomInBuffer[0]) {
++ case 'c':
++ case 's':
++ /* try to read optional parameter, pc unchanged if no parm */
++ ptr = &remcomInBuffer[1];
++ if (kgdb_hex2long(&ptr, &addr))
++ linux_regs->ip = addr;
++ case 'D':
++ case 'k':
++ newPC = linux_regs->ip;
++
++ /* clear the trace bit */
++ linux_regs->flags &= ~X86_EFLAGS_TF;
++ atomic_set(&kgdb_cpu_doing_single_step, -1);
++
++ /* set the trace bit if we're stepping */
++ if (remcomInBuffer[0] == 's') {
++ linux_regs->flags |= X86_EFLAGS_TF;
++ kgdb_single_step = 1;
++ if (kgdb_contthread) {
++ atomic_set(&kgdb_cpu_doing_single_step,
++ raw_smp_processor_id());
++ }
++ }
++
++ get_debugreg(dr6, 6);
++ if (!(dr6 & 0x4000)) {
++ int breakno;
++
++ for (breakno = 0; breakno < 4; breakno++) {
++ if (dr6 & (1 << breakno) &&
++ breakinfo[breakno].type == 0) {
++ /* Set restore flag: */
++ linux_regs->flags |= X86_EFLAGS_RF;
++ break;
++ }
++ }
++ }
++ set_debugreg(0UL, 6);
++ kgdb_correct_hw_break();
++
++ return 0;
++ }
++
++ /* this means that we do not want to exit from the handler: */
++ return -1;
++}
++
++static inline int
++single_step_cont(struct pt_regs *regs, struct die_args *args)
++{
++ /*
++ * Single step exception from kernel space to user space so
++ * eat the exception and continue the process:
++ */
++ printk(KERN_ERR "KGDB: trap/step from kernel to user space, "
++ "resuming...\n");
++ kgdb_arch_handle_exception(args->trapnr, args->signr,
++ args->err, "c", "", regs);
++
++ return NOTIFY_STOP;
++}
++
++static int was_in_debug_nmi[NR_CPUS];
++
++static int __kgdb_notify(struct die_args *args, unsigned long cmd)
++{
++ struct pt_regs *regs = args->regs;
++
++ switch (cmd) {
++ case DIE_NMI:
++ if (atomic_read(&kgdb_active) != -1) {
++ /* KGDB CPU roundup */
++ kgdb_nmicallback(raw_smp_processor_id(), regs);
++ was_in_debug_nmi[raw_smp_processor_id()] = 1;
++ touch_nmi_watchdog();
++ return NOTIFY_STOP;
++ }
++ return NOTIFY_DONE;
++
++ case DIE_NMI_IPI:
++ if (atomic_read(&kgdb_active) != -1) {
++ /* KGDB CPU roundup */
++ kgdb_nmicallback(raw_smp_processor_id(), regs);
++ was_in_debug_nmi[raw_smp_processor_id()] = 1;
++ touch_nmi_watchdog();
++ }
++ return NOTIFY_DONE;
++
++ case DIE_NMIUNKNOWN:
++ if (was_in_debug_nmi[raw_smp_processor_id()]) {
++ was_in_debug_nmi[raw_smp_processor_id()] = 0;
++ return NOTIFY_STOP;
++ }
++ return NOTIFY_DONE;
++
++ case DIE_NMIWATCHDOG:
++ if (atomic_read(&kgdb_active) != -1) {
++ /* KGDB CPU roundup: */
++ kgdb_nmicallback(raw_smp_processor_id(), regs);
++ return NOTIFY_STOP;
++ }
++ /* Enter debugger: */
++ break;
++
++ case DIE_DEBUG:
++ if (atomic_read(&kgdb_cpu_doing_single_step) ==
++ raw_smp_processor_id() &&
++ user_mode(regs))
++ return single_step_cont(regs, args);
++ /* fall through */
++ default:
++ if (user_mode(regs))
++ return NOTIFY_DONE;
++ }
++
++ if (kgdb_handle_exception(args->trapnr, args->signr, args->err, regs))
++ return NOTIFY_DONE;
++
++ /* Must touch watchdog before return to normal operation */
++ touch_nmi_watchdog();
++ return NOTIFY_STOP;
++}
++
++static int
++kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr)
++{
++ unsigned long flags;
++ int ret;
++
++ local_irq_save(flags);
++ ret = __kgdb_notify(ptr, cmd);
++ local_irq_restore(flags);
++
++ return ret;
++}
++
++static struct notifier_block kgdb_notifier = {
++ .notifier_call = kgdb_notify,
++
++ /*
++ * Lowest-prio notifier priority, we want to be notified last:
++ */
++ .priority = -INT_MAX,
++};
++
++/**
++ * kgdb_arch_init - Perform any architecture specific initalization.
++ *
++ * This function will handle the initalization of any architecture
++ * specific callbacks.
++ */
++int kgdb_arch_init(void)
++{
++ return register_die_notifier(&kgdb_notifier);
++}
++
++/**
++ * kgdb_arch_exit - Perform any architecture specific uninitalization.
++ *
++ * This function will handle the uninitalization of any architecture
++ * specific callbacks, for dynamic registration and unregistration.
++ */
++void kgdb_arch_exit(void)
++{
++ unregister_die_notifier(&kgdb_notifier);
++}
++
++/**
++ *
++ * kgdb_skipexception - Bail out of KGDB when we've been triggered.
++ * @exception: Exception vector number
++ * @regs: Current &struct pt_regs.
++ *
++ * On some architectures we need to skip a breakpoint exception when
++ * it occurs after a breakpoint has been removed.
++ *
++ * Skip an int3 exception when it occurs after a breakpoint has been
++ * removed. Backtrack eip by 1 since the int3 would have caused it to
++ * increment by 1.
++ */
++int kgdb_skipexception(int exception, struct pt_regs *regs)
++{
++ if (exception == 3 && kgdb_isremovedbreak(regs->ip - 1)) {
++ regs->ip -= 1;
++ return 1;
++ }
++ return 0;
++}
++
++unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs)
++{
++ if (exception == 3)
++ return instruction_pointer(regs) - 1;
++ return instruction_pointer(regs);
++}
++
++struct kgdb_arch arch_kgdb_ops = {
++ /* Breakpoint instruction: */
++ .gdb_bpt_instr = { 0xcc },
++ .flags = KGDB_HW_BREAKPOINT,
++ .set_hw_breakpoint = kgdb_set_hw_break,
++ .remove_hw_breakpoint = kgdb_remove_hw_break,
++ .remove_all_hw_break = kgdb_remove_all_hw_break,
++ .correct_hw_break = kgdb_correct_hw_break,
++};
+diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
+index 34a5912..b8c6743 100644
+--- a/arch/x86/kernel/kprobes.c
++++ b/arch/x86/kernel/kprobes.c
+@@ -410,13 +410,13 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+ static void __kprobes clear_btf(void)
+ {
+ if (test_thread_flag(TIF_DEBUGCTLMSR))
+- wrmsrl(MSR_IA32_DEBUGCTLMSR, 0);
++ update_debugctlmsr(0);
+ }
+
+ static void __kprobes restore_btf(void)
+ {
+ if (test_thread_flag(TIF_DEBUGCTLMSR))
+- wrmsrl(MSR_IA32_DEBUGCTLMSR, current->thread.debugctlmsr);
++ update_debugctlmsr(current->thread.debugctlmsr);
+ }
+
+ static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+@@ -489,7 +489,7 @@ static int __kprobes reenter_kprobe(struct kprobe *p, struct pt_regs *regs,
+ break;
+ case KPROBE_HIT_SS:
+ if (p == kprobe_running()) {
+- regs->flags &= ~TF_MASK;
++ regs->flags &= ~X86_EFLAGS_TF;
+ regs->flags |= kcb->kprobe_saved_flags;
+ return 0;
+ } else {
+@@ -858,15 +858,15 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs)
+ if (!cur)
+ return 0;
+
++ resume_execution(cur, regs, kcb);
++ regs->flags |= kcb->kprobe_saved_flags;
++ trace_hardirqs_fixup_flags(regs->flags);
++
+ if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
+ kcb->kprobe_status = KPROBE_HIT_SSDONE;
+ cur->post_handler(cur, regs, 0);
+ }
+
+- resume_execution(cur, regs, kcb);
+- regs->flags |= kcb->kprobe_saved_flags;
+- trace_hardirqs_fixup_flags(regs->flags);
+-
+ /* Restore back the original saved kprobes variables and continue. */
+ if (kcb->kprobe_status == KPROBE_REENTER) {
+ restore_previous_kprobe(kcb);
+diff --git a/arch/x86/kernel/mca_32.c b/arch/x86/kernel/mca_32.c
+index 9482033..2dc1837 100644
+--- a/arch/x86/kernel/mca_32.c
++++ b/arch/x86/kernel/mca_32.c
+@@ -53,9 +53,9 @@
+ #include <linux/init.h>
+ #include <asm/arch_hooks.h>
+
+-static unsigned char which_scsi = 0;
++static unsigned char which_scsi;
+
+-int MCA_bus = 0;
++int MCA_bus;
+ EXPORT_SYMBOL(MCA_bus);
+
+ /*
+@@ -68,15 +68,17 @@ static DEFINE_SPINLOCK(mca_lock);
+
+ /* Build the status info for the adapter */
+
+-static void mca_configure_adapter_status(struct mca_device *mca_dev) {
++static void mca_configure_adapter_status(struct mca_device *mca_dev)
++{
+ mca_dev->status = MCA_ADAPTER_NONE;
+
+ mca_dev->pos_id = mca_dev->pos[0]
+ + (mca_dev->pos[1] << 8);
+
+- if(!mca_dev->pos_id && mca_dev->slot < MCA_MAX_SLOT_NR) {
++ if (!mca_dev->pos_id && mca_dev->slot < MCA_MAX_SLOT_NR) {
+
+- /* id = 0x0000 usually indicates hardware failure,
++ /*
++ * id = 0x0000 usually indicates hardware failure,
+ * however, ZP Gu (zpg at castle.net> reports that his 9556
+ * has 0x0000 as id and everything still works. There
+ * also seem to be an adapter with id = 0x0000; the
+@@ -87,9 +89,10 @@ static void mca_configure_adapter_status(struct mca_device *mca_dev) {
+ mca_dev->status = MCA_ADAPTER_ERROR;
+
+ return;
+- } else if(mca_dev->pos_id != 0xffff) {
++ } else if (mca_dev->pos_id != 0xffff) {
+
+- /* 0xffff usually indicates that there's no adapter,
++ /*
++ * 0xffff usually indicates that there's no adapter,
+ * however, some integrated adapters may have 0xffff as
+ * their id and still be valid. Examples are on-board
+ * VGA of the 55sx, the integrated SCSI of the 56 & 57,
+@@ -99,19 +102,19 @@ static void mca_configure_adapter_status(struct mca_device *mca_dev) {
+ mca_dev->status = MCA_ADAPTER_NORMAL;
+ }
+
+- if((mca_dev->pos_id == 0xffff ||
++ if ((mca_dev->pos_id == 0xffff ||
+ mca_dev->pos_id == 0x0000) && mca_dev->slot >= MCA_MAX_SLOT_NR) {
+ int j;
+
+- for(j = 2; j < 8; j++) {
+- if(mca_dev->pos[j] != 0xff) {
++ for (j = 2; j < 8; j++) {
++ if (mca_dev->pos[j] != 0xff) {
+ mca_dev->status = MCA_ADAPTER_NORMAL;
+ break;
+ }
+ }
+ }
+
+- if(!(mca_dev->pos[2] & MCA_ENABLED)) {
++ if (!(mca_dev->pos[2] & MCA_ENABLED)) {
+
+ /* enabled bit is in POS 2 */
+
+@@ -133,7 +136,7 @@ static struct resource mca_standard_resources[] = {
+
+ #define MCA_STANDARD_RESOURCES ARRAY_SIZE(mca_standard_resources)
+
+-/**
++/*
+ * mca_read_and_store_pos - read the POS registers into a memory buffer
+ * @pos: a char pointer to 8 bytes, contains the POS register value on
+ * successful return
+@@ -141,12 +144,14 @@ static struct resource mca_standard_resources[] = {
+ * Returns 1 if a card actually exists (i.e. the pos isn't
+ * all 0xff) or 0 otherwise
+ */
+-static int mca_read_and_store_pos(unsigned char *pos) {
++static int mca_read_and_store_pos(unsigned char *pos)
++{
+ int j;
+ int found = 0;
+
+- for(j=0; j<8; j++) {
+- if((pos[j] = inb_p(MCA_POS_REG(j))) != 0xff) {
++ for (j = 0; j < 8; j++) {
++ pos[j] = inb_p(MCA_POS_REG(j));
++ if (pos[j] != 0xff) {
+ /* 0xff all across means no device. 0x00 means
+ * something's broken, but a device is
+ * probably there. However, if you get 0x00
+@@ -167,11 +172,11 @@ static unsigned char mca_pc_read_pos(struct mca_device *mca_dev, int reg)
+ unsigned char byte;
+ unsigned long flags;
+
+- if(reg < 0 || reg >= 8)
++ if (reg < 0 || reg >= 8)
+ return 0;
+
+ spin_lock_irqsave(&mca_lock, flags);
+- if(mca_dev->pos_register) {
++ if (mca_dev->pos_register) {
+ /* Disable adapter setup, enable motherboard setup */
+
+ outb_p(0, MCA_ADAPTER_SETUP_REG);
+@@ -203,7 +208,7 @@ static void mca_pc_write_pos(struct mca_device *mca_dev, int reg,
+ {
+ unsigned long flags;
+
+- if(reg < 0 || reg >= 8)
++ if (reg < 0 || reg >= 8)
+ return;
+
+ spin_lock_irqsave(&mca_lock, flags);
+@@ -227,17 +232,17 @@ static void mca_pc_write_pos(struct mca_device *mca_dev, int reg,
+ }
+
+ /* for the primary MCA bus, we have identity transforms */
+-static int mca_dummy_transform_irq(struct mca_device * mca_dev, int irq)
++static int mca_dummy_transform_irq(struct mca_device *mca_dev, int irq)
+ {
+ return irq;
+ }
+
+-static int mca_dummy_transform_ioport(struct mca_device * mca_dev, int port)
++static int mca_dummy_transform_ioport(struct mca_device *mca_dev, int port)
+ {
+ return port;
+ }
+
+-static void *mca_dummy_transform_memory(struct mca_device * mca_dev, void *mem)
++static void *mca_dummy_transform_memory(struct mca_device *mca_dev, void *mem)
+ {
+ return mem;
+ }
+@@ -251,7 +256,8 @@ static int __init mca_init(void)
+ short mca_builtin_scsi_ports[] = {0xf7, 0xfd, 0x00};
+ struct mca_bus *bus;
+
+- /* WARNING: Be careful when making changes here. Putting an adapter
++ /*
++ * WARNING: Be careful when making changes here. Putting an adapter
+ * and the motherboard simultaneously into setup mode may result in
+ * damage to chips (according to The Indispensible PC Hardware Book
+ * by Hans-Peter Messmer). Also, we disable system interrupts (so
+@@ -283,7 +289,7 @@ static int __init mca_init(void)
+
+ /* get the motherboard device */
+ mca_dev = kzalloc(sizeof(struct mca_device), GFP_KERNEL);
+- if(unlikely(!mca_dev))
++ if (unlikely(!mca_dev))
+ goto out_nomem;
+
+ /*
+@@ -309,7 +315,7 @@ static int __init mca_init(void)
+ mca_register_device(MCA_PRIMARY_BUS, mca_dev);
+
+ mca_dev = kzalloc(sizeof(struct mca_device), GFP_ATOMIC);
+- if(unlikely(!mca_dev))
++ if (unlikely(!mca_dev))
+ goto out_unlock_nomem;
+
+ /* Put motherboard into video setup mode, read integrated video
+@@ -326,7 +332,8 @@ static int __init mca_init(void)
+ mca_dev->slot = MCA_INTEGVIDEO;
+ mca_register_device(MCA_PRIMARY_BUS, mca_dev);
+
+- /* Put motherboard into scsi setup mode, read integrated scsi
++ /*
++ * Put motherboard into scsi setup mode, read integrated scsi
+ * POS registers, and turn motherboard setup off.
+ *
+ * It seems there are two possible SCSI registers. Martin says that
+@@ -338,18 +345,18 @@ static int __init mca_init(void)
+ * machine.
+ */
+
+- for(i = 0; (which_scsi = mca_builtin_scsi_ports[i]) != 0; i++) {
++ for (i = 0; (which_scsi = mca_builtin_scsi_ports[i]) != 0; i++) {
+ outb_p(which_scsi, MCA_MOTHERBOARD_SETUP_REG);
+- if(mca_read_and_store_pos(pos))
++ if (mca_read_and_store_pos(pos))
+ break;
+ }
+- if(which_scsi) {
++ if (which_scsi) {
+ /* found a scsi card */
+ mca_dev = kzalloc(sizeof(struct mca_device), GFP_ATOMIC);
+- if(unlikely(!mca_dev))
++ if (unlikely(!mca_dev))
+ goto out_unlock_nomem;
+
+- for(j = 0; j < 8; j++)
++ for (j = 0; j < 8; j++)
+ mca_dev->pos[j] = pos[j];
+
+ mca_configure_adapter_status(mca_dev);
+@@ -364,21 +371,22 @@ static int __init mca_init(void)
+
+ outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG);
+
+- /* Now loop over MCA slots: put each adapter into setup mode, and
++ /*
++ * Now loop over MCA slots: put each adapter into setup mode, and
+ * read its POS registers. Then put adapter setup off.
+ */
+
+- for(i=0; i<MCA_MAX_SLOT_NR; i++) {
++ for (i = 0; i < MCA_MAX_SLOT_NR; i++) {
+ outb_p(0x8|(i&0xf), MCA_ADAPTER_SETUP_REG);
+- if(!mca_read_and_store_pos(pos))
++ if (!mca_read_and_store_pos(pos))
+ continue;
+
+ mca_dev = kzalloc(sizeof(struct mca_device), GFP_ATOMIC);
+- if(unlikely(!mca_dev))
++ if (unlikely(!mca_dev))
+ goto out_unlock_nomem;
+
+- for(j=0; j<8; j++)
+- mca_dev->pos[j]=pos[j];
++ for (j = 0; j < 8; j++)
++ mca_dev->pos[j] = pos[j];
+
+ mca_dev->driver_loaded = 0;
+ mca_dev->slot = i;
+@@ -414,20 +422,20 @@ mca_handle_nmi_device(struct mca_device *mca_dev, int check_flag)
+ {
+ int slot = mca_dev->slot;
+
+- if(slot == MCA_INTEGSCSI) {
++ if (slot == MCA_INTEGSCSI) {
+ printk(KERN_CRIT "NMI: caused by MCA integrated SCSI adapter (%s)\n",
+ mca_dev->name);
+- } else if(slot == MCA_INTEGVIDEO) {
++ } else if (slot == MCA_INTEGVIDEO) {
+ printk(KERN_CRIT "NMI: caused by MCA integrated video adapter (%s)\n",
+ mca_dev->name);
+- } else if(slot == MCA_MOTHERBOARD) {
++ } else if (slot == MCA_MOTHERBOARD) {
+ printk(KERN_CRIT "NMI: caused by motherboard (%s)\n",
+ mca_dev->name);
+ }
+
+ /* More info available in POS 6 and 7? */
+
+- if(check_flag) {
++ if (check_flag) {
+ unsigned char pos6, pos7;
+
+ pos6 = mca_device_read_pos(mca_dev, 6);
+@@ -447,8 +455,9 @@ static int __kprobes mca_handle_nmi_callback(struct device *dev, void *data)
+
+ pos5 = mca_device_read_pos(mca_dev, 5);
+
+- if(!(pos5 & 0x80)) {
+- /* Bit 7 of POS 5 is reset when this adapter has a hardware
++ if (!(pos5 & 0x80)) {
++ /*
++ * Bit 7 of POS 5 is reset when this adapter has a hardware
+ * error. Bit 7 it reset if there's error information
+ * available in POS 6 and 7.
+ */
+@@ -460,7 +469,8 @@ static int __kprobes mca_handle_nmi_callback(struct device *dev, void *data)
+
+ void __kprobes mca_handle_nmi(void)
+ {
+- /* First try - scan the various adapters and see if a specific
++ /*
++ * First try - scan the various adapters and see if a specific
+ * adapter was responsible for the error.
+ */
+ bus_for_each_dev(&mca_bus_type, NULL, NULL, mca_handle_nmi_callback);
+diff --git a/arch/x86/kernel/mfgpt_32.c b/arch/x86/kernel/mfgpt_32.c
+index b402c0f..cfc2648 100644
+--- a/arch/x86/kernel/mfgpt_32.c
++++ b/arch/x86/kernel/mfgpt_32.c
+@@ -364,7 +364,8 @@ int __init mfgpt_timer_setup(void)
+ geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_SETUP, val);
+
+ /* Set up the clock event */
+- mfgpt_clockevent.mult = div_sc(MFGPT_HZ, NSEC_PER_SEC, 32);
++ mfgpt_clockevent.mult = div_sc(MFGPT_HZ, NSEC_PER_SEC,
++ mfgpt_clockevent.shift);
+ mfgpt_clockevent.min_delta_ns = clockevent_delta2ns(0xF,
+ &mfgpt_clockevent);
+ mfgpt_clockevent.max_delta_ns = clockevent_delta2ns(0xFFFE,
+diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c
+index f2702d0..69729e3 100644
+--- a/arch/x86/kernel/microcode.c
++++ b/arch/x86/kernel/microcode.c
+@@ -290,7 +290,7 @@ static int get_maching_microcode(void *mc, int cpu)
+ }
+ return 0;
+ find:
+- pr_debug("microcode: CPU %d found a matching microcode update with"
++ pr_debug("microcode: CPU%d found a matching microcode update with"
+ " version 0x%x (current=0x%x)\n", cpu, mc_header->rev,uci->rev);
+ new_mc = vmalloc(total_size);
+ if (!new_mc) {
+@@ -336,11 +336,11 @@ static void apply_microcode(int cpu)
+
+ spin_unlock_irqrestore(µcode_update_lock, flags);
+ if (val[1] != uci->mc->hdr.rev) {
+- printk(KERN_ERR "microcode: CPU%d updated from revision "
++ printk(KERN_ERR "microcode: CPU%d update from revision "
+ "0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]);
+ return;
+ }
+- pr_debug("microcode: CPU%d updated from revision "
++ printk(KERN_INFO "microcode: CPU%d updated from revision "
+ "0x%x to 0x%x, date = %08x \n",
+ cpu_num, uci->rev, val[1], uci->mc->hdr.date);
+ uci->rev = val[1];
+@@ -402,7 +402,7 @@ static int do_microcode_update (void)
+
+ if (!uci->valid)
+ continue;
+- set_cpus_allowed(current, cpumask_of_cpu(cpu));
++ set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ error = get_maching_microcode(new_mc, cpu);
+ if (error < 0)
+ goto out;
+@@ -416,7 +416,7 @@ out:
+ vfree(new_mc);
+ if (cursor < 0)
+ error = cursor;
+- set_cpus_allowed(current, old);
++ set_cpus_allowed_ptr(current, &old);
+ return error;
+ }
+
+@@ -534,7 +534,7 @@ static int cpu_request_microcode(int cpu)
+ c->x86, c->x86_model, c->x86_mask);
+ error = request_firmware(&firmware, name, µcode_pdev->dev);
+ if (error) {
+- pr_debug("ucode data file %s load failed\n", name);
++ pr_debug("microcode: ucode data file %s load failed\n", name);
+ return error;
+ }
+ buf = firmware->data;
+@@ -579,7 +579,7 @@ static int apply_microcode_check_cpu(int cpu)
+ return 0;
+
+ old = current->cpus_allowed;
+- set_cpus_allowed(current, cpumask_of_cpu(cpu));
++ set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+
+ /* Check if the microcode we have in memory matches the CPU */
+ if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
+@@ -610,7 +610,7 @@ static int apply_microcode_check_cpu(int cpu)
+ " sig=0x%x, pf=0x%x, rev=0x%x\n",
+ cpu, uci->sig, uci->pf, uci->rev);
+
+- set_cpus_allowed(current, old);
++ set_cpus_allowed_ptr(current, &old);
+ return err;
+ }
+
+@@ -621,13 +621,13 @@ static void microcode_init_cpu(int cpu, int resume)
+
+ old = current->cpus_allowed;
+
+- set_cpus_allowed(current, cpumask_of_cpu(cpu));
++ set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ mutex_lock(µcode_mutex);
+ collect_cpu_info(cpu);
+ if (uci->valid && system_state == SYSTEM_RUNNING && !resume)
+ cpu_request_microcode(cpu);
+ mutex_unlock(µcode_mutex);
+- set_cpus_allowed(current, old);
++ set_cpus_allowed_ptr(current, &old);
+ }
+
+ static void microcode_fini_cpu(int cpu)
+@@ -657,14 +657,14 @@ static ssize_t reload_store(struct sys_device *dev, const char *buf, size_t sz)
+ old = current->cpus_allowed;
+
+ get_online_cpus();
+- set_cpus_allowed(current, cpumask_of_cpu(cpu));
++ set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+
+ mutex_lock(µcode_mutex);
+ if (uci->valid)
+ err = cpu_request_microcode(cpu);
+ mutex_unlock(µcode_mutex);
+ put_online_cpus();
+- set_cpus_allowed(current, old);
++ set_cpus_allowed_ptr(current, &old);
+ }
+ if (err)
+ return err;
+@@ -709,7 +709,7 @@ static int __mc_sysdev_add(struct sys_device *sys_dev, int resume)
+ if (!cpu_online(cpu))
+ return 0;
+
+- pr_debug("Microcode:CPU %d added\n", cpu);
++ pr_debug("microcode: CPU%d added\n", cpu);
+ memset(uci, 0, sizeof(*uci));
+
+ err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group);
+@@ -733,7 +733,7 @@ static int mc_sysdev_remove(struct sys_device *sys_dev)
+ if (!cpu_online(cpu))
+ return 0;
+
+- pr_debug("Microcode:CPU %d removed\n", cpu);
++ pr_debug("microcode: CPU%d removed\n", cpu);
+ microcode_fini_cpu(cpu);
+ sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
+ return 0;
+@@ -745,7 +745,7 @@ static int mc_sysdev_resume(struct sys_device *dev)
+
+ if (!cpu_online(cpu))
+ return 0;
+- pr_debug("Microcode:CPU %d resumed\n", cpu);
++ pr_debug("microcode: CPU%d resumed\n", cpu);
+ /* only CPU 0 will apply ucode here */
+ apply_microcode(0);
+ return 0;
+@@ -783,7 +783,7 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
+ }
+ case CPU_DOWN_FAILED_FROZEN:
+ if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group))
+- printk(KERN_ERR "Microcode: Failed to create the sysfs "
++ printk(KERN_ERR "microcode: Failed to create the sysfs "
+ "group for CPU%d\n", cpu);
+ break;
+ case CPU_DOWN_PREPARE:
+diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
+new file mode 100644
+index 0000000..3e2c54d
+--- /dev/null
++++ b/arch/x86/kernel/mpparse.c
+@@ -0,0 +1,1084 @@
++/*
++ * Intel Multiprocessor Specification 1.1 and 1.4
++ * compliant MP-table parsing routines.
++ *
++ * (c) 1995 Alan Cox, Building #3 <alan at redhat.com>
++ * (c) 1998, 1999, 2000 Ingo Molnar <mingo at redhat.com>
++ * (c) 2008 Alexey Starikovskiy <astarikovskiy at suse.de>
++ */
++
++#include <linux/mm.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/bootmem.h>
++#include <linux/kernel_stat.h>
++#include <linux/mc146818rtc.h>
++#include <linux/bitops.h>
++#include <linux/acpi.h>
++#include <linux/module.h>
++
++#include <asm/smp.h>
++#include <asm/mtrr.h>
++#include <asm/mpspec.h>
++#include <asm/pgalloc.h>
++#include <asm/io_apic.h>
++#include <asm/proto.h>
++#include <asm/acpi.h>
++#include <asm/bios_ebda.h>
++
++#include <mach_apic.h>
++#ifdef CONFIG_X86_32
++#include <mach_apicdef.h>
++#include <mach_mpparse.h>
++#endif
++
++/* Have we found an MP table */
++int smp_found_config;
++
++/*
++ * Various Linux-internal data structures created from the
++ * MP-table.
++ */
++#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
++int mp_bus_id_to_type[MAX_MP_BUSSES];
++#endif
++
++DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
++int mp_bus_id_to_pci_bus[MAX_MP_BUSSES] = {[0 ... MAX_MP_BUSSES - 1] = -1 };
++
++static int mp_current_pci_id;
++
++int pic_mode;
++
++/*
++ * Intel MP BIOS table parsing routines:
++ */
++
++/*
++ * Checksum an MP configuration block.
++ */
++
++static int __init mpf_checksum(unsigned char *mp, int len)
++{
++ int sum = 0;
++
++ while (len--)
++ sum += *mp++;
++
++ return sum & 0xFF;
++}
++
++#ifdef CONFIG_X86_NUMAQ
++/*
++ * Have to match translation table entries to main table entries by counter
++ * hence the mpc_record variable .... can't see a less disgusting way of
++ * doing this ....
++ */
++
++static int mpc_record;
++static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY]
++ __cpuinitdata;
++#endif
++
++static void __cpuinit MP_processor_info(struct mpc_config_processor *m)
++{
++ int apicid;
++ char *bootup_cpu = "";
++
++ if (!(m->mpc_cpuflag & CPU_ENABLED)) {
++ disabled_cpus++;
++ return;
++ }
++#ifdef CONFIG_X86_NUMAQ
++ apicid = mpc_apic_id(m, translation_table[mpc_record]);
++#else
++ apicid = m->mpc_apicid;
++#endif
++ if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
++ bootup_cpu = " (Bootup-CPU)";
++ boot_cpu_physical_apicid = m->mpc_apicid;
++ }
++
++ printk(KERN_INFO "Processor #%d%s\n", m->mpc_apicid, bootup_cpu);
++ generic_processor_info(apicid, m->mpc_apicver);
++}
++
++static void __init MP_bus_info(struct mpc_config_bus *m)
++{
++ char str[7];
++
++ memcpy(str, m->mpc_bustype, 6);
++ str[6] = 0;
++
++#ifdef CONFIG_X86_NUMAQ
++ mpc_oem_bus_info(m, str, translation_table[mpc_record]);
++#else
++ Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
++#endif
++
++#if MAX_MP_BUSSES < 256
++ if (m->mpc_busid >= MAX_MP_BUSSES) {
++ printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
++ " is too large, max. supported is %d\n",
++ m->mpc_busid, str, MAX_MP_BUSSES - 1);
++ return;
++ }
++#endif
++
++ if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA) - 1) == 0) {
++ set_bit(m->mpc_busid, mp_bus_not_pci);
++#if defined(CONFIG_EISA) || defined (CONFIG_MCA)
++ mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
++#endif
++ } else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI) - 1) == 0) {
++#ifdef CONFIG_X86_NUMAQ
++ mpc_oem_pci_bus(m, translation_table[mpc_record]);
++#endif
++ clear_bit(m->mpc_busid, mp_bus_not_pci);
++ mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
++ mp_current_pci_id++;
++#if defined(CONFIG_EISA) || defined (CONFIG_MCA)
++ mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
++ } else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA) - 1) == 0) {
++ mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
++ } else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA) - 1) == 0) {
++ mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
++#endif
++ } else
++ printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
++}
++
++#ifdef CONFIG_X86_IO_APIC
++
++static int bad_ioapic(unsigned long address)
++{
++ if (nr_ioapics >= MAX_IO_APICS) {
++ printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
++ "(found %d)\n", MAX_IO_APICS, nr_ioapics);
++ panic("Recompile kernel with bigger MAX_IO_APICS!\n");
++ }
++ if (!address) {
++ printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
++ " found in table, skipping!\n");
++ return 1;
++ }
++ return 0;
++}
++
++static void __init MP_ioapic_info(struct mpc_config_ioapic *m)
++{
++ if (!(m->mpc_flags & MPC_APIC_USABLE))
++ return;
++
++ printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n",
++ m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
++
++ if (bad_ioapic(m->mpc_apicaddr))
++ return;
++
++ mp_ioapics[nr_ioapics] = *m;
++ nr_ioapics++;
++}
++
++static void __init MP_intsrc_info(struct mpc_config_intsrc *m)
++{
++ mp_irqs[mp_irq_entries] = *m;
++ Dprintk("Int: type %d, pol %d, trig %d, bus %d,"
++ " IRQ %02x, APIC ID %x, APIC INT %02x\n",
++ m->mpc_irqtype, m->mpc_irqflag & 3,
++ (m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
++ m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
++ if (++mp_irq_entries == MAX_IRQ_SOURCES)
++ panic("Max # of irq sources exceeded!!\n");
++}
++
++#endif
++
++static void __init MP_lintsrc_info(struct mpc_config_lintsrc *m)
++{
++ Dprintk("Lint: type %d, pol %d, trig %d, bus %d,"
++ " IRQ %02x, APIC ID %x, APIC LINT %02x\n",
++ m->mpc_irqtype, m->mpc_irqflag & 3,
++ (m->mpc_irqflag >> 2) & 3, m->mpc_srcbusid,
++ m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
++}
++
++#ifdef CONFIG_X86_NUMAQ
++static void __init MP_translation_info(struct mpc_config_translation *m)
++{
++ printk(KERN_INFO
++ "Translation: record %d, type %d, quad %d, global %d, local %d\n",
++ mpc_record, m->trans_type, m->trans_quad, m->trans_global,
++ m->trans_local);
++
++ if (mpc_record >= MAX_MPC_ENTRY)
++ printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n");
++ else
++ translation_table[mpc_record] = m; /* stash this for later */
++ if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad))
++ node_set_online(m->trans_quad);
++}
++
++/*
++ * Read/parse the MPC oem tables
++ */
++
++static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable,
++ unsigned short oemsize)
++{
++ int count = sizeof(*oemtable); /* the header size */
++ unsigned char *oemptr = ((unsigned char *)oemtable) + count;
++
++ mpc_record = 0;
++ printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n",
++ oemtable);
++ if (memcmp(oemtable->oem_signature, MPC_OEM_SIGNATURE, 4)) {
++ printk(KERN_WARNING
++ "SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
++ oemtable->oem_signature[0], oemtable->oem_signature[1],
++ oemtable->oem_signature[2], oemtable->oem_signature[3]);
++ return;
++ }
++ if (mpf_checksum((unsigned char *)oemtable, oemtable->oem_length)) {
++ printk(KERN_WARNING "SMP oem mptable: checksum error!\n");
++ return;
++ }
++ while (count < oemtable->oem_length) {
++ switch (*oemptr) {
++ case MP_TRANSLATION:
++ {
++ struct mpc_config_translation *m =
++ (struct mpc_config_translation *)oemptr;
++ MP_translation_info(m);
++ oemptr += sizeof(*m);
++ count += sizeof(*m);
++ ++mpc_record;
++ break;
++ }
++ default:
++ {
++ printk(KERN_WARNING
++ "Unrecognised OEM table entry type! - %d\n",
++ (int)*oemptr);
++ return;
++ }
++ }
++ }
++}
++
++static inline void mps_oem_check(struct mp_config_table *mpc, char *oem,
++ char *productid)
++{
++ if (strncmp(oem, "IBM NUMA", 8))
++ printk("Warning! May not be a NUMA-Q system!\n");
++ if (mpc->mpc_oemptr)
++ smp_read_mpc_oem((struct mp_config_oemtable *)mpc->mpc_oemptr,
++ mpc->mpc_oemsize);
++}
++#endif /* CONFIG_X86_NUMAQ */
++
++/*
++ * Read/parse the MPC
++ */
++
++static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
++{
++ char str[16];
++ char oem[10];
++ int count = sizeof(*mpc);
++ unsigned char *mpt = ((unsigned char *)mpc) + count;
++
++ if (memcmp(mpc->mpc_signature, MPC_SIGNATURE, 4)) {
++ printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n",
++ mpc->mpc_signature[0], mpc->mpc_signature[1],
++ mpc->mpc_signature[2], mpc->mpc_signature[3]);
++ return 0;
++ }
++ if (mpf_checksum((unsigned char *)mpc, mpc->mpc_length)) {
++ printk(KERN_ERR "MPTABLE: checksum error!\n");
++ return 0;
++ }
++ if (mpc->mpc_spec != 0x01 && mpc->mpc_spec != 0x04) {
++ printk(KERN_ERR "MPTABLE: bad table version (%d)!!\n",
++ mpc->mpc_spec);
++ return 0;
++ }
++ if (!mpc->mpc_lapic) {
++ printk(KERN_ERR "MPTABLE: null local APIC address!\n");
++ return 0;
++ }
++ memcpy(oem, mpc->mpc_oem, 8);
++ oem[8] = 0;
++ printk(KERN_INFO "MPTABLE: OEM ID: %s ", oem);
++
++ memcpy(str, mpc->mpc_productid, 12);
++ str[12] = 0;
++ printk("Product ID: %s ", str);
++
++#ifdef CONFIG_X86_32
++ mps_oem_check(mpc, oem, str);
++#endif
++ printk(KERN_INFO "MPTABLE: Product ID: %s ", str);
++
++ printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->mpc_lapic);
++
++ /* save the local APIC address, it might be non-default */
++ if (!acpi_lapic)
++ mp_lapic_addr = mpc->mpc_lapic;
++
++ if (early)
++ return 1;
++
++ /*
++ * Now process the configuration blocks.
++ */
++#ifdef CONFIG_X86_NUMAQ
++ mpc_record = 0;
++#endif
++ while (count < mpc->mpc_length) {
++ switch (*mpt) {
++ case MP_PROCESSOR:
++ {
++ struct mpc_config_processor *m =
++ (struct mpc_config_processor *)mpt;
++ /* ACPI may have already provided this data */
++ if (!acpi_lapic)
++ MP_processor_info(m);
++ mpt += sizeof(*m);
++ count += sizeof(*m);
++ break;
++ }
++ case MP_BUS:
++ {
++ struct mpc_config_bus *m =
++ (struct mpc_config_bus *)mpt;
++ MP_bus_info(m);
++ mpt += sizeof(*m);
++ count += sizeof(*m);
++ break;
++ }
++ case MP_IOAPIC:
++ {
++#ifdef CONFIG_X86_IO_APIC
++ struct mpc_config_ioapic *m =
++ (struct mpc_config_ioapic *)mpt;
++ MP_ioapic_info(m);
++#endif
++ mpt += sizeof(struct mpc_config_ioapic);
++ count += sizeof(struct mpc_config_ioapic);
++ break;
++ }
++ case MP_INTSRC:
++ {
++#ifdef CONFIG_X86_IO_APIC
++ struct mpc_config_intsrc *m =
++ (struct mpc_config_intsrc *)mpt;
++
++ MP_intsrc_info(m);
++#endif
++ mpt += sizeof(struct mpc_config_intsrc);
++ count += sizeof(struct mpc_config_intsrc);
++ break;
++ }
++ case MP_LINTSRC:
++ {
++ struct mpc_config_lintsrc *m =
++ (struct mpc_config_lintsrc *)mpt;
++ MP_lintsrc_info(m);
++ mpt += sizeof(*m);
++ count += sizeof(*m);
++ break;
++ }
++ default:
++ /* wrong mptable */
++ printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n");
++ printk(KERN_ERR "type %x\n", *mpt);
++ print_hex_dump(KERN_ERR, " ", DUMP_PREFIX_ADDRESS, 16,
++ 1, mpc, mpc->mpc_length, 1);
++ count = mpc->mpc_length;
++ break;
++ }
++#ifdef CONFIG_X86_NUMAQ
++ ++mpc_record;
++#endif
++ }
++ setup_apic_routing();
++ if (!num_processors)
++ printk(KERN_ERR "MPTABLE: no processors registered!\n");
++ return num_processors;
++}
++
++#ifdef CONFIG_X86_IO_APIC
++
++static int __init ELCR_trigger(unsigned int irq)
++{
++ unsigned int port;
++
++ port = 0x4d0 + (irq >> 3);
++ return (inb(port) >> (irq & 7)) & 1;
++}
++
++static void __init construct_default_ioirq_mptable(int mpc_default_type)
++{
++ struct mpc_config_intsrc intsrc;
++ int i;
++ int ELCR_fallback = 0;
++
++ intsrc.mpc_type = MP_INTSRC;
++ intsrc.mpc_irqflag = 0; /* conforming */
++ intsrc.mpc_srcbus = 0;
++ intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid;
++
++ intsrc.mpc_irqtype = mp_INT;
++
++ /*
++ * If true, we have an ISA/PCI system with no IRQ entries
++ * in the MP table. To prevent the PCI interrupts from being set up
++ * incorrectly, we try to use the ELCR. The sanity check to see if
++ * there is good ELCR data is very simple - IRQ0, 1, 2 and 13 can
++ * never be level sensitive, so we simply see if the ELCR agrees.
++ * If it does, we assume it's valid.
++ */
++ if (mpc_default_type == 5) {
++ printk(KERN_INFO "ISA/PCI bus type with no IRQ information... "
++ "falling back to ELCR\n");
++
++ if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) ||
++ ELCR_trigger(13))
++ printk(KERN_ERR "ELCR contains invalid data... "
++ "not using ELCR\n");
++ else {
++ printk(KERN_INFO
++ "Using ELCR to identify PCI interrupts\n");
++ ELCR_fallback = 1;
++ }
++ }
++
++ for (i = 0; i < 16; i++) {
++ switch (mpc_default_type) {
++ case 2:
++ if (i == 0 || i == 13)
++ continue; /* IRQ0 & IRQ13 not connected */
++ /* fall through */
++ default:
++ if (i == 2)
++ continue; /* IRQ2 is never connected */
++ }
++
++ if (ELCR_fallback) {
++ /*
++ * If the ELCR indicates a level-sensitive interrupt, we
++ * copy that information over to the MP table in the
++ * irqflag field (level sensitive, active high polarity).
++ */
++ if (ELCR_trigger(i))
++ intsrc.mpc_irqflag = 13;
++ else
++ intsrc.mpc_irqflag = 0;
++ }
++
++ intsrc.mpc_srcbusirq = i;
++ intsrc.mpc_dstirq = i ? i : 2; /* IRQ0 to INTIN2 */
++ MP_intsrc_info(&intsrc);
++ }
++
++ intsrc.mpc_irqtype = mp_ExtINT;
++ intsrc.mpc_srcbusirq = 0;
++ intsrc.mpc_dstirq = 0; /* 8259A to INTIN0 */
++ MP_intsrc_info(&intsrc);
++}
++
++#endif
++
++static inline void __init construct_default_ISA_mptable(int mpc_default_type)
++{
++ struct mpc_config_processor processor;
++ struct mpc_config_bus bus;
++#ifdef CONFIG_X86_IO_APIC
++ struct mpc_config_ioapic ioapic;
++#endif
++ struct mpc_config_lintsrc lintsrc;
++ int linttypes[2] = { mp_ExtINT, mp_NMI };
++ int i;
++
++ /*
++ * local APIC has default address
++ */
++ mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
++
++ /*
++ * 2 CPUs, numbered 0 & 1.
++ */
++ processor.mpc_type = MP_PROCESSOR;
++ /* Either an integrated APIC or a discrete 82489DX. */
++ processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
++ processor.mpc_cpuflag = CPU_ENABLED;
++ processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
++ (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
++ processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
++ processor.mpc_reserved[0] = 0;
++ processor.mpc_reserved[1] = 0;
++ for (i = 0; i < 2; i++) {
++ processor.mpc_apicid = i;
++ MP_processor_info(&processor);
++ }
++
++ bus.mpc_type = MP_BUS;
++ bus.mpc_busid = 0;
++ switch (mpc_default_type) {
++ default:
++ printk(KERN_ERR "???\nUnknown standard configuration %d\n",
++ mpc_default_type);
++ /* fall through */
++ case 1:
++ case 5:
++ memcpy(bus.mpc_bustype, "ISA ", 6);
++ break;
++ case 2:
++ case 6:
++ case 3:
++ memcpy(bus.mpc_bustype, "EISA ", 6);
++ break;
++ case 4:
++ case 7:
++ memcpy(bus.mpc_bustype, "MCA ", 6);
++ }
++ MP_bus_info(&bus);
++ if (mpc_default_type > 4) {
++ bus.mpc_busid = 1;
++ memcpy(bus.mpc_bustype, "PCI ", 6);
++ MP_bus_info(&bus);
++ }
++
++#ifdef CONFIG_X86_IO_APIC
++ ioapic.mpc_type = MP_IOAPIC;
++ ioapic.mpc_apicid = 2;
++ ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
++ ioapic.mpc_flags = MPC_APIC_USABLE;
++ ioapic.mpc_apicaddr = 0xFEC00000;
++ MP_ioapic_info(&ioapic);
++
++ /*
++ * We set up most of the low 16 IO-APIC pins according to MPS rules.
++ */
++ construct_default_ioirq_mptable(mpc_default_type);
++#endif
++ lintsrc.mpc_type = MP_LINTSRC;
++ lintsrc.mpc_irqflag = 0; /* conforming */
++ lintsrc.mpc_srcbusid = 0;
++ lintsrc.mpc_srcbusirq = 0;
++ lintsrc.mpc_destapic = MP_APIC_ALL;
++ for (i = 0; i < 2; i++) {
++ lintsrc.mpc_irqtype = linttypes[i];
++ lintsrc.mpc_destapiclint = i;
++ MP_lintsrc_info(&lintsrc);
++ }
++}
++
++static struct intel_mp_floating *mpf_found;
++
++/*
++ * Scan the memory blocks for an SMP configuration block.
++ */
++static void __init __get_smp_config(unsigned early)
++{
++ struct intel_mp_floating *mpf = mpf_found;
++
++ if (acpi_lapic && early)
++ return;
++ /*
++ * ACPI supports both logical (e.g. Hyper-Threading) and physical
++ * processors, where MPS only supports physical.
++ */
++ if (acpi_lapic && acpi_ioapic) {
++ printk(KERN_INFO "Using ACPI (MADT) for SMP configuration "
++ "information\n");
++ return;
++ } else if (acpi_lapic)
++ printk(KERN_INFO "Using ACPI for processor (LAPIC) "
++ "configuration information\n");
++
++ printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n",
++ mpf->mpf_specification);
++#ifdef CONFIG_X86_32
++ if (mpf->mpf_feature2 & (1 << 7)) {
++ printk(KERN_INFO " IMCR and PIC compatibility mode.\n");
++ pic_mode = 1;
++ } else {
++ printk(KERN_INFO " Virtual Wire compatibility mode.\n");
++ pic_mode = 0;
++ }
++#endif
++ /*
++ * Now see if we need to read further.
++ */
++ if (mpf->mpf_feature1 != 0) {
++ if (early) {
++ /*
++ * local APIC has default address
++ */
++ mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
++ return;
++ }
++
++ printk(KERN_INFO "Default MP configuration #%d\n",
++ mpf->mpf_feature1);
++ construct_default_ISA_mptable(mpf->mpf_feature1);
++
++ } else if (mpf->mpf_physptr) {
++
++ /*
++ * Read the physical hardware table. Anything here will
++ * override the defaults.
++ */
++ if (!smp_read_mpc(phys_to_virt(mpf->mpf_physptr), early)) {
++ smp_found_config = 0;
++ printk(KERN_ERR
++ "BIOS bug, MP table errors detected!...\n");
++ printk(KERN_ERR "... disabling SMP support. "
++ "(tell your hw vendor)\n");
++ return;
++ }
++
++ if (early)
++ return;
++#ifdef CONFIG_X86_IO_APIC
++ /*
++ * If there are no explicit MP IRQ entries, then we are
++ * broken. We set up most of the low 16 IO-APIC pins to
++ * ISA defaults and hope it will work.
++ */
++ if (!mp_irq_entries) {
++ struct mpc_config_bus bus;
++
++ printk(KERN_ERR "BIOS bug, no explicit IRQ entries, "
++ "using default mptable. "
++ "(tell your hw vendor)\n");
++
++ bus.mpc_type = MP_BUS;
++ bus.mpc_busid = 0;
++ memcpy(bus.mpc_bustype, "ISA ", 6);
++ MP_bus_info(&bus);
++
++ construct_default_ioirq_mptable(0);
++ }
++#endif
++ } else
++ BUG();
++
++ if (!early)
++ printk(KERN_INFO "Processors: %d\n", num_processors);
++ /*
++ * Only use the first configuration found.
++ */
++}
++
++void __init early_get_smp_config(void)
++{
++ __get_smp_config(1);
++}
++
++void __init get_smp_config(void)
++{
++ __get_smp_config(0);
++}
++
++static int __init smp_scan_config(unsigned long base, unsigned long length,
++ unsigned reserve)
++{
++ unsigned int *bp = phys_to_virt(base);
++ struct intel_mp_floating *mpf;
++
++ Dprintk("Scan SMP from %p for %ld bytes.\n", bp, length);
++ BUILD_BUG_ON(sizeof(*mpf) != 16);
++
++ while (length > 0) {
++ mpf = (struct intel_mp_floating *)bp;
++ if ((*bp == SMP_MAGIC_IDENT) &&
++ (mpf->mpf_length == 1) &&
++ !mpf_checksum((unsigned char *)bp, 16) &&
++ ((mpf->mpf_specification == 1)
++ || (mpf->mpf_specification == 4))) {
++
++ smp_found_config = 1;
++ mpf_found = mpf;
++#ifdef CONFIG_X86_32
++ printk(KERN_INFO "found SMP MP-table at [%p] %08lx\n",
++ mpf, virt_to_phys(mpf));
++ reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE,
++ BOOTMEM_DEFAULT);
++ if (mpf->mpf_physptr) {
++ /*
++ * We cannot access to MPC table to compute
++ * table size yet, as only few megabytes from
++ * the bottom is mapped now.
++ * PC-9800's MPC table places on the very last
++ * of physical memory; so that simply reserving
++ * PAGE_SIZE from mpg->mpf_physptr yields BUG()
++ * in reserve_bootmem.
++ */
++ unsigned long size = PAGE_SIZE;
++ unsigned long end = max_low_pfn * PAGE_SIZE;
++ if (mpf->mpf_physptr + size > end)
++ size = end - mpf->mpf_physptr;
++ reserve_bootmem(mpf->mpf_physptr, size,
++ BOOTMEM_DEFAULT);
++ }
++
++#else
++ if (!reserve)
++ return 1;
++
++ reserve_bootmem_generic(virt_to_phys(mpf), PAGE_SIZE);
++ if (mpf->mpf_physptr)
++ reserve_bootmem_generic(mpf->mpf_physptr,
++ PAGE_SIZE);
++#endif
++ return 1;
++ }
++ bp += 4;
++ length -= 16;
++ }
++ return 0;
++}
++
++static void __init __find_smp_config(unsigned reserve)
++{
++ unsigned int address;
++
++ /*
++ * FIXME: Linux assumes you have 640K of base ram..
++ * this continues the error...
++ *
++ * 1) Scan the bottom 1K for a signature
++ * 2) Scan the top 1K of base RAM
++ * 3) Scan the 64K of bios
++ */
++ if (smp_scan_config(0x0, 0x400, reserve) ||
++ smp_scan_config(639 * 0x400, 0x400, reserve) ||
++ smp_scan_config(0xF0000, 0x10000, reserve))
++ return;
++ /*
++ * If it is an SMP machine we should know now, unless the
++ * configuration is in an EISA/MCA bus machine with an
++ * extended bios data area.
++ *
++ * there is a real-mode segmented pointer pointing to the
++ * 4K EBDA area at 0x40E, calculate and scan it here.
++ *
++ * NOTE! There are Linux loaders that will corrupt the EBDA
++ * area, and as such this kind of SMP config may be less
++ * trustworthy, simply because the SMP table may have been
++ * stomped on during early boot. These loaders are buggy and
++ * should be fixed.
++ *
++ * MP1.4 SPEC states to only scan first 1K of 4K EBDA.
++ */
++
++ address = get_bios_ebda();
++ if (address)
++ smp_scan_config(address, 0x400, reserve);
++}
++
++void __init early_find_smp_config(void)
++{
++ __find_smp_config(0);
++}
++
++void __init find_smp_config(void)
++{
++ __find_smp_config(1);
++}
++
++/* --------------------------------------------------------------------------
++ ACPI-based MP Configuration
++ -------------------------------------------------------------------------- */
++
++#ifdef CONFIG_ACPI
++
++#ifdef CONFIG_X86_IO_APIC
++
++#define MP_ISA_BUS 0
++
++extern struct mp_ioapic_routing mp_ioapic_routing[MAX_IO_APICS];
++
++static int mp_find_ioapic(int gsi)
++{
++ int i = 0;
++
++ /* Find the IOAPIC that manages this GSI. */
++ for (i = 0; i < nr_ioapics; i++) {
++ if ((gsi >= mp_ioapic_routing[i].gsi_base)
++ && (gsi <= mp_ioapic_routing[i].gsi_end))
++ return i;
++ }
++
++ printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
++ return -1;
++}
++
++static u8 __init uniq_ioapic_id(u8 id)
++{
++#ifdef CONFIG_X86_32
++ if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
++ !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
++ return io_apic_get_unique_id(nr_ioapics, id);
++ else
++ return id;
++#else
++ int i;
++ DECLARE_BITMAP(used, 256);
++ bitmap_zero(used, 256);
++ for (i = 0; i < nr_ioapics; i++) {
++ struct mpc_config_ioapic *ia = &mp_ioapics[i];
++ __set_bit(ia->mpc_apicid, used);
++ }
++ if (!test_bit(id, used))
++ return id;
++ return find_first_zero_bit(used, 256);
++#endif
++}
++
++void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
++{
++ int idx = 0;
++
++ if (bad_ioapic(address))
++ return;
++
++ idx = nr_ioapics;
++
++ mp_ioapics[idx].mpc_type = MP_IOAPIC;
++ mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE;
++ mp_ioapics[idx].mpc_apicaddr = address;
++
++ set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
++ mp_ioapics[idx].mpc_apicid = uniq_ioapic_id(id);
++#ifdef CONFIG_X86_32
++ mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
++#else
++ mp_ioapics[idx].mpc_apicver = 0;
++#endif
++ /*
++ * Build basic GSI lookup table to facilitate gsi->io_apic lookups
++ * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
++ */
++ mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid;
++ mp_ioapic_routing[idx].gsi_base = gsi_base;
++ mp_ioapic_routing[idx].gsi_end = gsi_base +
++ io_apic_get_redir_entries(idx);
++
++ printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
++ "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid,
++ mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr,
++ mp_ioapic_routing[idx].gsi_base, mp_ioapic_routing[idx].gsi_end);
++
++ nr_ioapics++;
++}
++
++void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
++{
++ struct mpc_config_intsrc intsrc;
++ int ioapic = -1;
++ int pin = -1;
++
++ /*
++ * Convert 'gsi' to 'ioapic.pin'.
++ */
++ ioapic = mp_find_ioapic(gsi);
++ if (ioapic < 0)
++ return;
++ pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
++
++ /*
++ * TBD: This check is for faulty timer entries, where the override
++ * erroneously sets the trigger to level, resulting in a HUGE
++ * increase of timer interrupts!
++ */
++ if ((bus_irq == 0) && (trigger == 3))
++ trigger = 1;
++
++ intsrc.mpc_type = MP_INTSRC;
++ intsrc.mpc_irqtype = mp_INT;
++ intsrc.mpc_irqflag = (trigger << 2) | polarity;
++ intsrc.mpc_srcbus = MP_ISA_BUS;
++ intsrc.mpc_srcbusirq = bus_irq; /* IRQ */
++ intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; /* APIC ID */
++ intsrc.mpc_dstirq = pin; /* INTIN# */
++
++ MP_intsrc_info(&intsrc);
++}
++
++int es7000_plat;
++
++void __init mp_config_acpi_legacy_irqs(void)
++{
++ struct mpc_config_intsrc intsrc;
++ int i = 0;
++ int ioapic = -1;
++
++#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
++ /*
++ * Fabricate the legacy ISA bus (bus #31).
++ */
++ mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA;
++#endif
++ set_bit(MP_ISA_BUS, mp_bus_not_pci);
++ Dprintk("Bus #%d is ISA\n", MP_ISA_BUS);
++
++ /*
++ * Older generations of ES7000 have no legacy identity mappings
++ */
++ if (es7000_plat == 1)
++ return;
++
++ /*
++ * Locate the IOAPIC that manages the ISA IRQs (0-15).
++ */
++ ioapic = mp_find_ioapic(0);
++ if (ioapic < 0)
++ return;
++
++ intsrc.mpc_type = MP_INTSRC;
++ intsrc.mpc_irqflag = 0; /* Conforming */
++ intsrc.mpc_srcbus = MP_ISA_BUS;
++#ifdef CONFIG_X86_IO_APIC
++ intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;
++#endif
++ /*
++ * Use the default configuration for the IRQs 0-15. Unless
++ * overridden by (MADT) interrupt source override entries.
++ */
++ for (i = 0; i < 16; i++) {
++ int idx;
++
++ for (idx = 0; idx < mp_irq_entries; idx++) {
++ struct mpc_config_intsrc *irq = mp_irqs + idx;
++
++ /* Do we already have a mapping for this ISA IRQ? */
++ if (irq->mpc_srcbus == MP_ISA_BUS
++ && irq->mpc_srcbusirq == i)
++ break;
++
++ /* Do we already have a mapping for this IOAPIC pin */
++ if ((irq->mpc_dstapic == intsrc.mpc_dstapic) &&
++ (irq->mpc_dstirq == i))
++ break;
++ }
++
++ if (idx != mp_irq_entries) {
++ printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i);
++ continue; /* IRQ already used */
++ }
++
++ intsrc.mpc_irqtype = mp_INT;
++ intsrc.mpc_srcbusirq = i; /* Identity mapped */
++ intsrc.mpc_dstirq = i;
++
++ MP_intsrc_info(&intsrc);
++ }
++}
++
++int mp_register_gsi(u32 gsi, int triggering, int polarity)
++{
++ int ioapic;
++ int ioapic_pin;
++#ifdef CONFIG_X86_32
++#define MAX_GSI_NUM 4096
++#define IRQ_COMPRESSION_START 64
++
++ static int pci_irq = IRQ_COMPRESSION_START;
++ /*
++ * Mapping between Global System Interrupts, which
++ * represent all possible interrupts, and IRQs
++ * assigned to actual devices.
++ */
++ static int gsi_to_irq[MAX_GSI_NUM];
++#else
++
++ if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
++ return gsi;
++#endif
++
++ /* Don't set up the ACPI SCI because it's already set up */
++ if (acpi_gbl_FADT.sci_interrupt == gsi)
++ return gsi;
++
++ ioapic = mp_find_ioapic(gsi);
++ if (ioapic < 0) {
++ printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
++ return gsi;
++ }
++
++ ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
++
++#ifdef CONFIG_X86_32
++ if (ioapic_renumber_irq)
++ gsi = ioapic_renumber_irq(ioapic, gsi);
++#endif
++
++ /*
++ * Avoid pin reprogramming. PRTs typically include entries
++ * with redundant pin->gsi mappings (but unique PCI devices);
++ * we only program the IOAPIC on the first.
++ */
++ if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
++ printk(KERN_ERR "Invalid reference to IOAPIC pin "
++ "%d-%d\n", mp_ioapic_routing[ioapic].apic_id,
++ ioapic_pin);
++ return gsi;
++ }
++ if (test_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed)) {
++ Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
++ mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
++#ifdef CONFIG_X86_32
++ return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]);
++#else
++ return gsi;
++#endif
++ }
++
++ set_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed);
++#ifdef CONFIG_X86_32
++ /*
++ * For GSI >= 64, use IRQ compression
++ */
++ if ((gsi >= IRQ_COMPRESSION_START)
++ && (triggering == ACPI_LEVEL_SENSITIVE)) {
++ /*
++ * For PCI devices assign IRQs in order, avoiding gaps
++ * due to unused I/O APIC pins.
++ */
++ int irq = gsi;
++ if (gsi < MAX_GSI_NUM) {
++ /*
++ * Retain the VIA chipset work-around (gsi > 15), but
++ * avoid a problem where the 8254 timer (IRQ0) is setup
++ * via an override (so it's not on pin 0 of the ioapic),
++ * and at the same time, the pin 0 interrupt is a PCI
++ * type. The gsi > 15 test could cause these two pins
++ * to be shared as IRQ0, and they are not shareable.
++ * So test for this condition, and if necessary, avoid
++ * the pin collision.
++ */
++ gsi = pci_irq++;
++ /*
++ * Don't assign IRQ used by ACPI SCI
++ */
++ if (gsi == acpi_gbl_FADT.sci_interrupt)
++ gsi = pci_irq++;
++ gsi_to_irq[irq] = gsi;
++ } else {
++ printk(KERN_ERR "GSI %u is too high\n", gsi);
++ return gsi;
++ }
++ }
++#endif
++ io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
++ triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
++ polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
++ return gsi;
++}
++
++#endif /* CONFIG_X86_IO_APIC */
++#endif /* CONFIG_ACPI */
+diff --git a/arch/x86/kernel/mpparse_32.c b/arch/x86/kernel/mpparse_32.c
+deleted file mode 100644
+index f349e68..0000000
+--- a/arch/x86/kernel/mpparse_32.c
++++ /dev/null
+@@ -1,1139 +0,0 @@
+-/*
+- * Intel Multiprocessor Specification 1.1 and 1.4
+- * compliant MP-table parsing routines.
+- *
+- * (c) 1995 Alan Cox, Building #3 <alan at redhat.com>
+- * (c) 1998, 1999, 2000 Ingo Molnar <mingo at redhat.com>
+- *
+- * Fixes
+- * Erich Boleyn : MP v1.4 and additional changes.
+- * Alan Cox : Added EBDA scanning
+- * Ingo Molnar : various cleanups and rewrites
+- * Maciej W. Rozycki: Bits for default MP configurations
+- * Paul Diefenbaugh: Added full ACPI support
+- */
+-
+-#include <linux/mm.h>
+-#include <linux/init.h>
+-#include <linux/acpi.h>
+-#include <linux/delay.h>
+-#include <linux/bootmem.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/bitops.h>
+-
+-#include <asm/smp.h>
+-#include <asm/acpi.h>
+-#include <asm/mtrr.h>
+-#include <asm/mpspec.h>
+-#include <asm/io_apic.h>
+-
+-#include <mach_apic.h>
+-#include <mach_apicdef.h>
+-#include <mach_mpparse.h>
+-#include <bios_ebda.h>
+-
+-/* Have we found an MP table */
+-int smp_found_config;
+-unsigned int __cpuinitdata maxcpus = NR_CPUS;
+-
+-/*
+- * Various Linux-internal data structures created from the
+- * MP-table.
+- */
+-int apic_version [MAX_APICS];
+-int mp_bus_id_to_type [MAX_MP_BUSSES];
+-int mp_bus_id_to_node [MAX_MP_BUSSES];
+-int mp_bus_id_to_local [MAX_MP_BUSSES];
+-int quad_local_to_mp_bus_id [NR_CPUS/4][4];
+-int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
+-static int mp_current_pci_id;
+-
+-/* I/O APIC entries */
+-struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
+-
+-/* # of MP IRQ source entries */
+-struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
+-
+-/* MP IRQ source entries */
+-int mp_irq_entries;
+-
+-int nr_ioapics;
+-
+-int pic_mode;
+-unsigned long mp_lapic_addr;
+-
+-unsigned int def_to_bigsmp = 0;
+-
+-/* Processor that is doing the boot up */
+-unsigned int boot_cpu_physical_apicid = -1U;
+-/* Internal processor count */
+-unsigned int num_processors;
+-
+-/* Bitmask of physically existing CPUs */
+-physid_mask_t phys_cpu_present_map;
+-
+-u8 bios_cpu_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
+-
+-/*
+- * Intel MP BIOS table parsing routines:
+- */
+-
+-
+-/*
+- * Checksum an MP configuration block.
+- */
+-
+-static int __init mpf_checksum(unsigned char *mp, int len)
+-{
+- int sum = 0;
+-
+- while (len--)
+- sum += *mp++;
+-
+- return sum & 0xFF;
+-}
+-
+-/*
+- * Have to match translation table entries to main table entries by counter
+- * hence the mpc_record variable .... can't see a less disgusting way of
+- * doing this ....
+- */
+-
+-static int mpc_record;
+-static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __cpuinitdata;
+-
+-static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
+-{
+- int ver, apicid;
+- physid_mask_t phys_cpu;
+-
+- if (!(m->mpc_cpuflag & CPU_ENABLED))
+- return;
+-
+- apicid = mpc_apic_id(m, translation_table[mpc_record]);
+-
+- if (m->mpc_featureflag&(1<<0))
+- Dprintk(" Floating point unit present.\n");
+- if (m->mpc_featureflag&(1<<7))
+- Dprintk(" Machine Exception supported.\n");
+- if (m->mpc_featureflag&(1<<8))
+- Dprintk(" 64 bit compare & exchange supported.\n");
+- if (m->mpc_featureflag&(1<<9))
+- Dprintk(" Internal APIC present.\n");
+- if (m->mpc_featureflag&(1<<11))
+- Dprintk(" SEP present.\n");
+- if (m->mpc_featureflag&(1<<12))
+- Dprintk(" MTRR present.\n");
+- if (m->mpc_featureflag&(1<<13))
+- Dprintk(" PGE present.\n");
+- if (m->mpc_featureflag&(1<<14))
+- Dprintk(" MCA present.\n");
+- if (m->mpc_featureflag&(1<<15))
+- Dprintk(" CMOV present.\n");
+- if (m->mpc_featureflag&(1<<16))
+- Dprintk(" PAT present.\n");
+- if (m->mpc_featureflag&(1<<17))
+- Dprintk(" PSE present.\n");
+- if (m->mpc_featureflag&(1<<18))
+- Dprintk(" PSN present.\n");
+- if (m->mpc_featureflag&(1<<19))
+- Dprintk(" Cache Line Flush Instruction present.\n");
+- /* 20 Reserved */
+- if (m->mpc_featureflag&(1<<21))
+- Dprintk(" Debug Trace and EMON Store present.\n");
+- if (m->mpc_featureflag&(1<<22))
+- Dprintk(" ACPI Thermal Throttle Registers present.\n");
+- if (m->mpc_featureflag&(1<<23))
+- Dprintk(" MMX present.\n");
+- if (m->mpc_featureflag&(1<<24))
+- Dprintk(" FXSR present.\n");
+- if (m->mpc_featureflag&(1<<25))
+- Dprintk(" XMM present.\n");
+- if (m->mpc_featureflag&(1<<26))
+- Dprintk(" Willamette New Instructions present.\n");
+- if (m->mpc_featureflag&(1<<27))
+- Dprintk(" Self Snoop present.\n");
+- if (m->mpc_featureflag&(1<<28))
+- Dprintk(" HT present.\n");
+- if (m->mpc_featureflag&(1<<29))
+- Dprintk(" Thermal Monitor present.\n");
+- /* 30, 31 Reserved */
+-
+-
+- if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
+- Dprintk(" Bootup CPU\n");
+- boot_cpu_physical_apicid = m->mpc_apicid;
+- }
+-
+- ver = m->mpc_apicver;
+-
+- /*
+- * Validate version
+- */
+- if (ver == 0x0) {
+- printk(KERN_WARNING "BIOS bug, APIC version is 0 for CPU#%d! "
+- "fixing up to 0x10. (tell your hw vendor)\n",
+- m->mpc_apicid);
+- ver = 0x10;
+- }
+- apic_version[m->mpc_apicid] = ver;
+-
+- phys_cpu = apicid_to_cpu_present(apicid);
+- physids_or(phys_cpu_present_map, phys_cpu_present_map, phys_cpu);
+-
+- if (num_processors >= NR_CPUS) {
+- printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
+- " Processor ignored.\n", NR_CPUS);
+- return;
+- }
+-
+- if (num_processors >= maxcpus) {
+- printk(KERN_WARNING "WARNING: maxcpus limit of %i reached."
+- " Processor ignored.\n", maxcpus);
+- return;
+- }
+-
+- cpu_set(num_processors, cpu_possible_map);
+- num_processors++;
+-
+- /*
+- * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y
+- * but we need to work other dependencies like SMP_SUSPEND etc
+- * before this can be done without some confusion.
+- * if (CPU_HOTPLUG_ENABLED || num_processors > 8)
+- * - Ashok Raj <ashok.raj at intel.com>
+- */
+- if (num_processors > 8) {
+- switch (boot_cpu_data.x86_vendor) {
+- case X86_VENDOR_INTEL:
+- if (!APIC_XAPIC(ver)) {
+- def_to_bigsmp = 0;
+- break;
+- }
+- /* If P4 and above fall through */
+- case X86_VENDOR_AMD:
+- def_to_bigsmp = 1;
+- }
+- }
+- bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
+-}
+-
+-static void __init MP_bus_info (struct mpc_config_bus *m)
+-{
+- char str[7];
+-
+- memcpy(str, m->mpc_bustype, 6);
+- str[6] = 0;
+-
+- mpc_oem_bus_info(m, str, translation_table[mpc_record]);
+-
+-#if MAX_MP_BUSSES < 256
+- if (m->mpc_busid >= MAX_MP_BUSSES) {
+- printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
+- " is too large, max. supported is %d\n",
+- m->mpc_busid, str, MAX_MP_BUSSES - 1);
+- return;
+- }
+-#endif
+-
+- if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) {
+- mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
+- } else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA)-1) == 0) {
+- mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
+- } else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI)-1) == 0) {
+- mpc_oem_pci_bus(m, translation_table[mpc_record]);
+- mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
+- mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
+- mp_current_pci_id++;
+- } else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) {
+- mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
+- } else {
+- printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
+- }
+-}
+-
+-static void __init MP_ioapic_info (struct mpc_config_ioapic *m)
+-{
+- if (!(m->mpc_flags & MPC_APIC_USABLE))
+- return;
+-
+- printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n",
+- m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
+- if (nr_ioapics >= MAX_IO_APICS) {
+- printk(KERN_CRIT "Max # of I/O APICs (%d) exceeded (found %d).\n",
+- MAX_IO_APICS, nr_ioapics);
+- panic("Recompile kernel with bigger MAX_IO_APICS!.\n");
+- }
+- if (!m->mpc_apicaddr) {
+- printk(KERN_ERR "WARNING: bogus zero I/O APIC address"
+- " found in MP table, skipping!\n");
+- return;
+- }
+- mp_ioapics[nr_ioapics] = *m;
+- nr_ioapics++;
+-}
+-
+-static void __init MP_intsrc_info (struct mpc_config_intsrc *m)
+-{
+- mp_irqs [mp_irq_entries] = *m;
+- Dprintk("Int: type %d, pol %d, trig %d, bus %d,"
+- " IRQ %02x, APIC ID %x, APIC INT %02x\n",
+- m->mpc_irqtype, m->mpc_irqflag & 3,
+- (m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
+- m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
+- if (++mp_irq_entries == MAX_IRQ_SOURCES)
+- panic("Max # of irq sources exceeded!!\n");
+-}
+-
+-static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m)
+-{
+- Dprintk("Lint: type %d, pol %d, trig %d, bus %d,"
+- " IRQ %02x, APIC ID %x, APIC LINT %02x\n",
+- m->mpc_irqtype, m->mpc_irqflag & 3,
+- (m->mpc_irqflag >> 2) &3, m->mpc_srcbusid,
+- m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
+-}
+-
+-#ifdef CONFIG_X86_NUMAQ
+-static void __init MP_translation_info (struct mpc_config_translation *m)
+-{
+- printk(KERN_INFO "Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type, m->trans_quad, m->trans_global, m->trans_local);
+-
+- if (mpc_record >= MAX_MPC_ENTRY)
+- printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n");
+- else
+- translation_table[mpc_record] = m; /* stash this for later */
+- if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad))
+- node_set_online(m->trans_quad);
+-}
+-
+-/*
+- * Read/parse the MPC oem tables
+- */
+-
+-static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, \
+- unsigned short oemsize)
+-{
+- int count = sizeof (*oemtable); /* the header size */
+- unsigned char *oemptr = ((unsigned char *)oemtable)+count;
+-
+- mpc_record = 0;
+- printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n", oemtable);
+- if (memcmp(oemtable->oem_signature,MPC_OEM_SIGNATURE,4))
+- {
+- printk(KERN_WARNING "SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
+- oemtable->oem_signature[0],
+- oemtable->oem_signature[1],
+- oemtable->oem_signature[2],
+- oemtable->oem_signature[3]);
+- return;
+- }
+- if (mpf_checksum((unsigned char *)oemtable,oemtable->oem_length))
+- {
+- printk(KERN_WARNING "SMP oem mptable: checksum error!\n");
+- return;
+- }
+- while (count < oemtable->oem_length) {
+- switch (*oemptr) {
+- case MP_TRANSLATION:
+- {
+- struct mpc_config_translation *m=
+- (struct mpc_config_translation *)oemptr;
+- MP_translation_info(m);
+- oemptr += sizeof(*m);
+- count += sizeof(*m);
+- ++mpc_record;
+- break;
+- }
+- default:
+- {
+- printk(KERN_WARNING "Unrecognised OEM table entry type! - %d\n", (int) *oemptr);
+- return;
+- }
+- }
+- }
+-}
+-
+-static inline void mps_oem_check(struct mp_config_table *mpc, char *oem,
+- char *productid)
+-{
+- if (strncmp(oem, "IBM NUMA", 8))
+- printk("Warning! May not be a NUMA-Q system!\n");
+- if (mpc->mpc_oemptr)
+- smp_read_mpc_oem((struct mp_config_oemtable *) mpc->mpc_oemptr,
+- mpc->mpc_oemsize);
+-}
+-#endif /* CONFIG_X86_NUMAQ */
+-
+-/*
+- * Read/parse the MPC
+- */
+-
+-static int __init smp_read_mpc(struct mp_config_table *mpc)
+-{
+- char str[16];
+- char oem[10];
+- int count=sizeof(*mpc);
+- unsigned char *mpt=((unsigned char *)mpc)+count;
+-
+- if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) {
+- printk(KERN_ERR "SMP mptable: bad signature [0x%x]!\n",
+- *(u32 *)mpc->mpc_signature);
+- return 0;
+- }
+- if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) {
+- printk(KERN_ERR "SMP mptable: checksum error!\n");
+- return 0;
+- }
+- if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) {
+- printk(KERN_ERR "SMP mptable: bad table version (%d)!!\n",
+- mpc->mpc_spec);
+- return 0;
+- }
+- if (!mpc->mpc_lapic) {
+- printk(KERN_ERR "SMP mptable: null local APIC address!\n");
+- return 0;
+- }
+- memcpy(oem,mpc->mpc_oem,8);
+- oem[8]=0;
+- printk(KERN_INFO "OEM ID: %s ",oem);
+-
+- memcpy(str,mpc->mpc_productid,12);
+- str[12]=0;
+- printk("Product ID: %s ",str);
+-
+- mps_oem_check(mpc, oem, str);
+-
+- printk("APIC at: 0x%X\n", mpc->mpc_lapic);
+-
+- /*
+- * Save the local APIC address (it might be non-default) -- but only
+- * if we're not using ACPI.
+- */
+- if (!acpi_lapic)
+- mp_lapic_addr = mpc->mpc_lapic;
+-
+- /*
+- * Now process the configuration blocks.
+- */
+- mpc_record = 0;
+- while (count < mpc->mpc_length) {
+- switch(*mpt) {
+- case MP_PROCESSOR:
+- {
+- struct mpc_config_processor *m=
+- (struct mpc_config_processor *)mpt;
+- /* ACPI may have already provided this data */
+- if (!acpi_lapic)
+- MP_processor_info(m);
+- mpt += sizeof(*m);
+- count += sizeof(*m);
+- break;
+- }
+- case MP_BUS:
+- {
+- struct mpc_config_bus *m=
+- (struct mpc_config_bus *)mpt;
+- MP_bus_info(m);
+- mpt += sizeof(*m);
+- count += sizeof(*m);
+- break;
+- }
+- case MP_IOAPIC:
+- {
+- struct mpc_config_ioapic *m=
+- (struct mpc_config_ioapic *)mpt;
+- MP_ioapic_info(m);
+- mpt+=sizeof(*m);
+- count+=sizeof(*m);
+- break;
+- }
+- case MP_INTSRC:
+- {
+- struct mpc_config_intsrc *m=
+- (struct mpc_config_intsrc *)mpt;
+-
+- MP_intsrc_info(m);
+- mpt+=sizeof(*m);
+- count+=sizeof(*m);
+- break;
+- }
+- case MP_LINTSRC:
+- {
+- struct mpc_config_lintsrc *m=
+- (struct mpc_config_lintsrc *)mpt;
+- MP_lintsrc_info(m);
+- mpt+=sizeof(*m);
+- count+=sizeof(*m);
+- break;
+- }
+- default:
+- {
+- count = mpc->mpc_length;
+- break;
+- }
+- }
+- ++mpc_record;
+- }
+- setup_apic_routing();
+- if (!num_processors)
+- printk(KERN_ERR "SMP mptable: no processors registered!\n");
+- return num_processors;
+-}
+-
+-static int __init ELCR_trigger(unsigned int irq)
+-{
+- unsigned int port;
+-
+- port = 0x4d0 + (irq >> 3);
+- return (inb(port) >> (irq & 7)) & 1;
+-}
+-
+-static void __init construct_default_ioirq_mptable(int mpc_default_type)
+-{
+- struct mpc_config_intsrc intsrc;
+- int i;
+- int ELCR_fallback = 0;
+-
+- intsrc.mpc_type = MP_INTSRC;
+- intsrc.mpc_irqflag = 0; /* conforming */
+- intsrc.mpc_srcbus = 0;
+- intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid;
+-
+- intsrc.mpc_irqtype = mp_INT;
+-
+- /*
+- * If true, we have an ISA/PCI system with no IRQ entries
+- * in the MP table. To prevent the PCI interrupts from being set up
+- * incorrectly, we try to use the ELCR. The sanity check to see if
+- * there is good ELCR data is very simple - IRQ0, 1, 2 and 13 can
+- * never be level sensitive, so we simply see if the ELCR agrees.
+- * If it does, we assume it's valid.
+- */
+- if (mpc_default_type == 5) {
+- printk(KERN_INFO "ISA/PCI bus type with no IRQ information... falling back to ELCR\n");
+-
+- if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) || ELCR_trigger(13))
+- printk(KERN_WARNING "ELCR contains invalid data... not using ELCR\n");
+- else {
+- printk(KERN_INFO "Using ELCR to identify PCI interrupts\n");
+- ELCR_fallback = 1;
+- }
+- }
+-
+- for (i = 0; i < 16; i++) {
+- switch (mpc_default_type) {
+- case 2:
+- if (i == 0 || i == 13)
+- continue; /* IRQ0 & IRQ13 not connected */
+- /* fall through */
+- default:
+- if (i == 2)
+- continue; /* IRQ2 is never connected */
+- }
+-
+- if (ELCR_fallback) {
+- /*
+- * If the ELCR indicates a level-sensitive interrupt, we
+- * copy that information over to the MP table in the
+- * irqflag field (level sensitive, active high polarity).
+- */
+- if (ELCR_trigger(i))
+- intsrc.mpc_irqflag = 13;
+- else
+- intsrc.mpc_irqflag = 0;
+- }
+-
+- intsrc.mpc_srcbusirq = i;
+- intsrc.mpc_dstirq = i ? i : 2; /* IRQ0 to INTIN2 */
+- MP_intsrc_info(&intsrc);
+- }
+-
+- intsrc.mpc_irqtype = mp_ExtINT;
+- intsrc.mpc_srcbusirq = 0;
+- intsrc.mpc_dstirq = 0; /* 8259A to INTIN0 */
+- MP_intsrc_info(&intsrc);
+-}
+-
+-static inline void __init construct_default_ISA_mptable(int mpc_default_type)
+-{
+- struct mpc_config_processor processor;
+- struct mpc_config_bus bus;
+- struct mpc_config_ioapic ioapic;
+- struct mpc_config_lintsrc lintsrc;
+- int linttypes[2] = { mp_ExtINT, mp_NMI };
+- int i;
+-
+- /*
+- * local APIC has default address
+- */
+- mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
+-
+- /*
+- * 2 CPUs, numbered 0 & 1.
+- */
+- processor.mpc_type = MP_PROCESSOR;
+- /* Either an integrated APIC or a discrete 82489DX. */
+- processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
+- processor.mpc_cpuflag = CPU_ENABLED;
+- processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
+- (boot_cpu_data.x86_model << 4) |
+- boot_cpu_data.x86_mask;
+- processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
+- processor.mpc_reserved[0] = 0;
+- processor.mpc_reserved[1] = 0;
+- for (i = 0; i < 2; i++) {
+- processor.mpc_apicid = i;
+- MP_processor_info(&processor);
+- }
+-
+- bus.mpc_type = MP_BUS;
+- bus.mpc_busid = 0;
+- switch (mpc_default_type) {
+- default:
+- printk("???\n");
+- printk(KERN_ERR "Unknown standard configuration %d\n",
+- mpc_default_type);
+- /* fall through */
+- case 1:
+- case 5:
+- memcpy(bus.mpc_bustype, "ISA ", 6);
+- break;
+- case 2:
+- case 6:
+- case 3:
+- memcpy(bus.mpc_bustype, "EISA ", 6);
+- break;
+- case 4:
+- case 7:
+- memcpy(bus.mpc_bustype, "MCA ", 6);
+- }
+- MP_bus_info(&bus);
+- if (mpc_default_type > 4) {
+- bus.mpc_busid = 1;
+- memcpy(bus.mpc_bustype, "PCI ", 6);
+- MP_bus_info(&bus);
+- }
+-
+- ioapic.mpc_type = MP_IOAPIC;
+- ioapic.mpc_apicid = 2;
+- ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
+- ioapic.mpc_flags = MPC_APIC_USABLE;
+- ioapic.mpc_apicaddr = 0xFEC00000;
+- MP_ioapic_info(&ioapic);
+-
+- /*
+- * We set up most of the low 16 IO-APIC pins according to MPS rules.
+- */
+- construct_default_ioirq_mptable(mpc_default_type);
+-
+- lintsrc.mpc_type = MP_LINTSRC;
+- lintsrc.mpc_irqflag = 0; /* conforming */
+- lintsrc.mpc_srcbusid = 0;
+- lintsrc.mpc_srcbusirq = 0;
+- lintsrc.mpc_destapic = MP_APIC_ALL;
+- for (i = 0; i < 2; i++) {
+- lintsrc.mpc_irqtype = linttypes[i];
+- lintsrc.mpc_destapiclint = i;
+- MP_lintsrc_info(&lintsrc);
+- }
+-}
+-
+-static struct intel_mp_floating *mpf_found;
+-
+-/*
+- * Scan the memory blocks for an SMP configuration block.
+- */
+-void __init get_smp_config (void)
+-{
+- struct intel_mp_floating *mpf = mpf_found;
+-
+- /*
+- * ACPI supports both logical (e.g. Hyper-Threading) and physical
+- * processors, where MPS only supports physical.
+- */
+- if (acpi_lapic && acpi_ioapic) {
+- printk(KERN_INFO "Using ACPI (MADT) for SMP configuration information\n");
+- return;
+- }
+- else if (acpi_lapic)
+- printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n");
+-
+- printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
+- if (mpf->mpf_feature2 & (1<<7)) {
+- printk(KERN_INFO " IMCR and PIC compatibility mode.\n");
+- pic_mode = 1;
+- } else {
+- printk(KERN_INFO " Virtual Wire compatibility mode.\n");
+- pic_mode = 0;
+- }
+-
+- /*
+- * Now see if we need to read further.
+- */
+- if (mpf->mpf_feature1 != 0) {
+-
+- printk(KERN_INFO "Default MP configuration #%d\n", mpf->mpf_feature1);
+- construct_default_ISA_mptable(mpf->mpf_feature1);
+-
+- } else if (mpf->mpf_physptr) {
+-
+- /*
+- * Read the physical hardware table. Anything here will
+- * override the defaults.
+- */
+- if (!smp_read_mpc(phys_to_virt(mpf->mpf_physptr))) {
+- smp_found_config = 0;
+- printk(KERN_ERR "BIOS bug, MP table errors detected!...\n");
+- printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n");
+- return;
+- }
+- /*
+- * If there are no explicit MP IRQ entries, then we are
+- * broken. We set up most of the low 16 IO-APIC pins to
+- * ISA defaults and hope it will work.
+- */
+- if (!mp_irq_entries) {
+- struct mpc_config_bus bus;
+-
+- printk(KERN_ERR "BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
+-
+- bus.mpc_type = MP_BUS;
+- bus.mpc_busid = 0;
+- memcpy(bus.mpc_bustype, "ISA ", 6);
+- MP_bus_info(&bus);
+-
+- construct_default_ioirq_mptable(0);
+- }
+-
+- } else
+- BUG();
+-
+- printk(KERN_INFO "Processors: %d\n", num_processors);
+- /*
+- * Only use the first configuration found.
+- */
+-}
+-
+-static int __init smp_scan_config (unsigned long base, unsigned long length)
+-{
+- unsigned long *bp = phys_to_virt(base);
+- struct intel_mp_floating *mpf;
+-
+- printk(KERN_INFO "Scan SMP from %p for %ld bytes.\n", bp,length);
+- if (sizeof(*mpf) != 16)
+- printk("Error: MPF size\n");
+-
+- while (length > 0) {
+- mpf = (struct intel_mp_floating *)bp;
+- if ((*bp == SMP_MAGIC_IDENT) &&
+- (mpf->mpf_length == 1) &&
+- !mpf_checksum((unsigned char *)bp, 16) &&
+- ((mpf->mpf_specification == 1)
+- || (mpf->mpf_specification == 4)) ) {
+-
+- smp_found_config = 1;
+- printk(KERN_INFO "found SMP MP-table at [%p] %08lx\n",
+- mpf, virt_to_phys(mpf));
+- reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE,
+- BOOTMEM_DEFAULT);
+- if (mpf->mpf_physptr) {
+- /*
+- * We cannot access to MPC table to compute
+- * table size yet, as only few megabytes from
+- * the bottom is mapped now.
+- * PC-9800's MPC table places on the very last
+- * of physical memory; so that simply reserving
+- * PAGE_SIZE from mpg->mpf_physptr yields BUG()
+- * in reserve_bootmem.
+- */
+- unsigned long size = PAGE_SIZE;
+- unsigned long end = max_low_pfn * PAGE_SIZE;
+- if (mpf->mpf_physptr + size > end)
+- size = end - mpf->mpf_physptr;
+- reserve_bootmem(mpf->mpf_physptr, size,
+- BOOTMEM_DEFAULT);
+- }
+-
+- mpf_found = mpf;
+- return 1;
+- }
+- bp += 4;
+- length -= 16;
+- }
+- return 0;
+-}
+-
+-void __init find_smp_config (void)
+-{
+- unsigned int address;
+-
+- /*
+- * FIXME: Linux assumes you have 640K of base ram..
+- * this continues the error...
+- *
+- * 1) Scan the bottom 1K for a signature
+- * 2) Scan the top 1K of base RAM
+- * 3) Scan the 64K of bios
+- */
+- if (smp_scan_config(0x0,0x400) ||
+- smp_scan_config(639*0x400,0x400) ||
+- smp_scan_config(0xF0000,0x10000))
+- return;
+- /*
+- * If it is an SMP machine we should know now, unless the
+- * configuration is in an EISA/MCA bus machine with an
+- * extended bios data area.
+- *
+- * there is a real-mode segmented pointer pointing to the
+- * 4K EBDA area at 0x40E, calculate and scan it here.
+- *
+- * NOTE! There are Linux loaders that will corrupt the EBDA
+- * area, and as such this kind of SMP config may be less
+- * trustworthy, simply because the SMP table may have been
+- * stomped on during early boot. These loaders are buggy and
+- * should be fixed.
+- *
+- * MP1.4 SPEC states to only scan first 1K of 4K EBDA.
+- */
+-
+- address = get_bios_ebda();
+- if (address)
+- smp_scan_config(address, 0x400);
+-}
+-
+-int es7000_plat;
+-
+-/* --------------------------------------------------------------------------
+- ACPI-based MP Configuration
+- -------------------------------------------------------------------------- */
+-
+-#ifdef CONFIG_ACPI
+-
+-void __init mp_register_lapic_address(u64 address)
+-{
+- mp_lapic_addr = (unsigned long) address;
+-
+- set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
+-
+- if (boot_cpu_physical_apicid == -1U)
+- boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
+-
+- Dprintk("Boot CPU = %d\n", boot_cpu_physical_apicid);
+-}
+-
+-void __cpuinit mp_register_lapic (u8 id, u8 enabled)
+-{
+- struct mpc_config_processor processor;
+- int boot_cpu = 0;
+-
+- if (MAX_APICS - id <= 0) {
+- printk(KERN_WARNING "Processor #%d invalid (max %d)\n",
+- id, MAX_APICS);
+- return;
+- }
+-
+- if (id == boot_cpu_physical_apicid)
+- boot_cpu = 1;
+-
+- processor.mpc_type = MP_PROCESSOR;
+- processor.mpc_apicid = id;
+- processor.mpc_apicver = GET_APIC_VERSION(apic_read(APIC_LVR));
+- processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0);
+- processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0);
+- processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
+- (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
+- processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
+- processor.mpc_reserved[0] = 0;
+- processor.mpc_reserved[1] = 0;
+-
+- MP_processor_info(&processor);
+-}
+-
+-#ifdef CONFIG_X86_IO_APIC
+-
+-#define MP_ISA_BUS 0
+-#define MP_MAX_IOAPIC_PIN 127
+-
+-static struct mp_ioapic_routing {
+- int apic_id;
+- int gsi_base;
+- int gsi_end;
+- u32 pin_programmed[4];
+-} mp_ioapic_routing[MAX_IO_APICS];
+-
+-static int mp_find_ioapic (int gsi)
+-{
+- int i = 0;
+-
+- /* Find the IOAPIC that manages this GSI. */
+- for (i = 0; i < nr_ioapics; i++) {
+- if ((gsi >= mp_ioapic_routing[i].gsi_base)
+- && (gsi <= mp_ioapic_routing[i].gsi_end))
+- return i;
+- }
+-
+- printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
+-
+- return -1;
+-}
+-
+-void __init mp_register_ioapic(u8 id, u32 address, u32 gsi_base)
+-{
+- int idx = 0;
+- int tmpid;
+-
+- if (nr_ioapics >= MAX_IO_APICS) {
+- printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
+- "(found %d)\n", MAX_IO_APICS, nr_ioapics);
+- panic("Recompile kernel with bigger MAX_IO_APICS!\n");
+- }
+- if (!address) {
+- printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
+- " found in MADT table, skipping!\n");
+- return;
+- }
+-
+- idx = nr_ioapics++;
+-
+- mp_ioapics[idx].mpc_type = MP_IOAPIC;
+- mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE;
+- mp_ioapics[idx].mpc_apicaddr = address;
+-
+- set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
+- if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
+- && !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
+- tmpid = io_apic_get_unique_id(idx, id);
+- else
+- tmpid = id;
+- if (tmpid == -1) {
+- nr_ioapics--;
+- return;
+- }
+- mp_ioapics[idx].mpc_apicid = tmpid;
+- mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
+-
+- /*
+- * Build basic GSI lookup table to facilitate gsi->io_apic lookups
+- * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
+- */
+- mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid;
+- mp_ioapic_routing[idx].gsi_base = gsi_base;
+- mp_ioapic_routing[idx].gsi_end = gsi_base +
+- io_apic_get_redir_entries(idx);
+-
+- printk("IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
+- "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid,
+- mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr,
+- mp_ioapic_routing[idx].gsi_base,
+- mp_ioapic_routing[idx].gsi_end);
+-}
+-
+-void __init
+-mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
+-{
+- struct mpc_config_intsrc intsrc;
+- int ioapic = -1;
+- int pin = -1;
+-
+- /*
+- * Convert 'gsi' to 'ioapic.pin'.
+- */
+- ioapic = mp_find_ioapic(gsi);
+- if (ioapic < 0)
+- return;
+- pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
+-
+- /*
+- * TBD: This check is for faulty timer entries, where the override
+- * erroneously sets the trigger to level, resulting in a HUGE
+- * increase of timer interrupts!
+- */
+- if ((bus_irq == 0) && (trigger == 3))
+- trigger = 1;
+-
+- intsrc.mpc_type = MP_INTSRC;
+- intsrc.mpc_irqtype = mp_INT;
+- intsrc.mpc_irqflag = (trigger << 2) | polarity;
+- intsrc.mpc_srcbus = MP_ISA_BUS;
+- intsrc.mpc_srcbusirq = bus_irq; /* IRQ */
+- intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; /* APIC ID */
+- intsrc.mpc_dstirq = pin; /* INTIN# */
+-
+- Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, %d-%d\n",
+- intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3,
+- (intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus,
+- intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, intsrc.mpc_dstirq);
+-
+- mp_irqs[mp_irq_entries] = intsrc;
+- if (++mp_irq_entries == MAX_IRQ_SOURCES)
+- panic("Max # of irq sources exceeded!\n");
+-}
+-
+-void __init mp_config_acpi_legacy_irqs (void)
+-{
+- struct mpc_config_intsrc intsrc;
+- int i = 0;
+- int ioapic = -1;
+-
+- /*
+- * Fabricate the legacy ISA bus (bus #31).
+- */
+- mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA;
+- Dprintk("Bus #%d is ISA\n", MP_ISA_BUS);
+-
+- /*
+- * Older generations of ES7000 have no legacy identity mappings
+- */
+- if (es7000_plat == 1)
+- return;
+-
+- /*
+- * Locate the IOAPIC that manages the ISA IRQs (0-15).
+- */
+- ioapic = mp_find_ioapic(0);
+- if (ioapic < 0)
+- return;
+-
+- intsrc.mpc_type = MP_INTSRC;
+- intsrc.mpc_irqflag = 0; /* Conforming */
+- intsrc.mpc_srcbus = MP_ISA_BUS;
+- intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;
+-
+- /*
+- * Use the default configuration for the IRQs 0-15. Unless
+- * overridden by (MADT) interrupt source override entries.
+- */
+- for (i = 0; i < 16; i++) {
+- int idx;
+-
+- for (idx = 0; idx < mp_irq_entries; idx++) {
+- struct mpc_config_intsrc *irq = mp_irqs + idx;
+-
+- /* Do we already have a mapping for this ISA IRQ? */
+- if (irq->mpc_srcbus == MP_ISA_BUS && irq->mpc_srcbusirq == i)
+- break;
+-
+- /* Do we already have a mapping for this IOAPIC pin */
+- if ((irq->mpc_dstapic == intsrc.mpc_dstapic) &&
+- (irq->mpc_dstirq == i))
+- break;
+- }
+-
+- if (idx != mp_irq_entries) {
+- printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i);
+- continue; /* IRQ already used */
+- }
+-
+- intsrc.mpc_irqtype = mp_INT;
+- intsrc.mpc_srcbusirq = i; /* Identity mapped */
+- intsrc.mpc_dstirq = i;
+-
+- Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, "
+- "%d-%d\n", intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3,
+- (intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus,
+- intsrc.mpc_srcbusirq, intsrc.mpc_dstapic,
+- intsrc.mpc_dstirq);
+-
+- mp_irqs[mp_irq_entries] = intsrc;
+- if (++mp_irq_entries == MAX_IRQ_SOURCES)
+- panic("Max # of irq sources exceeded!\n");
+- }
+-}
+-
+-#define MAX_GSI_NUM 4096
+-#define IRQ_COMPRESSION_START 64
+-
+-int mp_register_gsi(u32 gsi, int triggering, int polarity)
+-{
+- int ioapic = -1;
+- int ioapic_pin = 0;
+- int idx, bit = 0;
+- static int pci_irq = IRQ_COMPRESSION_START;
+- /*
+- * Mapping between Global System Interrupts, which
+- * represent all possible interrupts, and IRQs
+- * assigned to actual devices.
+- */
+- static int gsi_to_irq[MAX_GSI_NUM];
+-
+- /* Don't set up the ACPI SCI because it's already set up */
+- if (acpi_gbl_FADT.sci_interrupt == gsi)
+- return gsi;
+-
+- ioapic = mp_find_ioapic(gsi);
+- if (ioapic < 0) {
+- printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
+- return gsi;
+- }
+-
+- ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
+-
+- if (ioapic_renumber_irq)
+- gsi = ioapic_renumber_irq(ioapic, gsi);
+-
+- /*
+- * Avoid pin reprogramming. PRTs typically include entries
+- * with redundant pin->gsi mappings (but unique PCI devices);
+- * we only program the IOAPIC on the first.
+- */
+- bit = ioapic_pin % 32;
+- idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
+- if (idx > 3) {
+- printk(KERN_ERR "Invalid reference to IOAPIC pin "
+- "%d-%d\n", mp_ioapic_routing[ioapic].apic_id,
+- ioapic_pin);
+- return gsi;
+- }
+- if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
+- Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
+- mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
+- return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]);
+- }
+-
+- mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
+-
+- /*
+- * For GSI >= 64, use IRQ compression
+- */
+- if ((gsi >= IRQ_COMPRESSION_START)
+- && (triggering == ACPI_LEVEL_SENSITIVE)) {
+- /*
+- * For PCI devices assign IRQs in order, avoiding gaps
+- * due to unused I/O APIC pins.
+- */
+- int irq = gsi;
+- if (gsi < MAX_GSI_NUM) {
+- /*
+- * Retain the VIA chipset work-around (gsi > 15), but
+- * avoid a problem where the 8254 timer (IRQ0) is setup
+- * via an override (so it's not on pin 0 of the ioapic),
+- * and at the same time, the pin 0 interrupt is a PCI
+- * type. The gsi > 15 test could cause these two pins
+- * to be shared as IRQ0, and they are not shareable.
+- * So test for this condition, and if necessary, avoid
+- * the pin collision.
+- */
+- if (gsi > 15 || (gsi == 0 && !timer_uses_ioapic_pin_0))
+- gsi = pci_irq++;
+- /*
+- * Don't assign IRQ used by ACPI SCI
+- */
+- if (gsi == acpi_gbl_FADT.sci_interrupt)
+- gsi = pci_irq++;
+- gsi_to_irq[irq] = gsi;
+- } else {
+- printk(KERN_ERR "GSI %u is too high\n", gsi);
+- return gsi;
+- }
+- }
+-
+- io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
+- triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
+- polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
+- return gsi;
+-}
+-
+-#endif /* CONFIG_X86_IO_APIC */
+-#endif /* CONFIG_ACPI */
+diff --git a/arch/x86/kernel/mpparse_64.c b/arch/x86/kernel/mpparse_64.c
+deleted file mode 100644
+index 72ab140..0000000
+--- a/arch/x86/kernel/mpparse_64.c
++++ /dev/null
+@@ -1,867 +0,0 @@
+-/*
+- * Intel Multiprocessor Specification 1.1 and 1.4
+- * compliant MP-table parsing routines.
+- *
+- * (c) 1995 Alan Cox, Building #3 <alan at redhat.com>
+- * (c) 1998, 1999, 2000 Ingo Molnar <mingo at redhat.com>
+- *
+- * Fixes
+- * Erich Boleyn : MP v1.4 and additional changes.
+- * Alan Cox : Added EBDA scanning
+- * Ingo Molnar : various cleanups and rewrites
+- * Maciej W. Rozycki: Bits for default MP configurations
+- * Paul Diefenbaugh: Added full ACPI support
+- */
+-
+-#include <linux/mm.h>
+-#include <linux/init.h>
+-#include <linux/delay.h>
+-#include <linux/bootmem.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/acpi.h>
+-#include <linux/module.h>
+-
+-#include <asm/smp.h>
+-#include <asm/mtrr.h>
+-#include <asm/mpspec.h>
+-#include <asm/pgalloc.h>
+-#include <asm/io_apic.h>
+-#include <asm/proto.h>
+-#include <asm/acpi.h>
+-
+-/* Have we found an MP table */
+-int smp_found_config;
+-
+-/*
+- * Various Linux-internal data structures created from the
+- * MP-table.
+- */
+-DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
+-int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
+-
+-static int mp_current_pci_id = 0;
+-/* I/O APIC entries */
+-struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
+-
+-/* # of MP IRQ source entries */
+-struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
+-
+-/* MP IRQ source entries */
+-int mp_irq_entries;
+-
+-int nr_ioapics;
+-unsigned long mp_lapic_addr = 0;
+-
+-
+-
+-/* Processor that is doing the boot up */
+-unsigned int boot_cpu_id = -1U;
+-EXPORT_SYMBOL(boot_cpu_id);
+-
+-/* Internal processor count */
+-unsigned int num_processors;
+-
+-unsigned disabled_cpus __cpuinitdata;
+-
+-/* Bitmask of physically existing CPUs */
+-physid_mask_t phys_cpu_present_map = PHYSID_MASK_NONE;
+-
+-u16 x86_bios_cpu_apicid_init[NR_CPUS] __initdata
+- = { [0 ... NR_CPUS-1] = BAD_APICID };
+-void *x86_bios_cpu_apicid_early_ptr;
+-DEFINE_PER_CPU(u16, x86_bios_cpu_apicid) = BAD_APICID;
+-EXPORT_PER_CPU_SYMBOL(x86_bios_cpu_apicid);
+-
+-
+-/*
+- * Intel MP BIOS table parsing routines:
+- */
+-
+-/*
+- * Checksum an MP configuration block.
+- */
+-
+-static int __init mpf_checksum(unsigned char *mp, int len)
+-{
+- int sum = 0;
+-
+- while (len--)
+- sum += *mp++;
+-
+- return sum & 0xFF;
+-}
+-
+-static void __cpuinit MP_processor_info(struct mpc_config_processor *m)
+-{
+- int cpu;
+- cpumask_t tmp_map;
+- char *bootup_cpu = "";
+-
+- if (!(m->mpc_cpuflag & CPU_ENABLED)) {
+- disabled_cpus++;
+- return;
+- }
+- if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
+- bootup_cpu = " (Bootup-CPU)";
+- boot_cpu_id = m->mpc_apicid;
+- }
+-
+- printk(KERN_INFO "Processor #%d%s\n", m->mpc_apicid, bootup_cpu);
+-
+- if (num_processors >= NR_CPUS) {
+- printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
+- " Processor ignored.\n", NR_CPUS);
+- return;
+- }
+-
+- num_processors++;
+- cpus_complement(tmp_map, cpu_present_map);
+- cpu = first_cpu(tmp_map);
+-
+- physid_set(m->mpc_apicid, phys_cpu_present_map);
+- if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
+- /*
+- * x86_bios_cpu_apicid is required to have processors listed
+- * in same order as logical cpu numbers. Hence the first
+- * entry is BSP, and so on.
+- */
+- cpu = 0;
+- }
+- /* are we being called early in kernel startup? */
+- if (x86_cpu_to_apicid_early_ptr) {
+- u16 *cpu_to_apicid = x86_cpu_to_apicid_early_ptr;
+- u16 *bios_cpu_apicid = x86_bios_cpu_apicid_early_ptr;
+-
+- cpu_to_apicid[cpu] = m->mpc_apicid;
+- bios_cpu_apicid[cpu] = m->mpc_apicid;
+- } else {
+- per_cpu(x86_cpu_to_apicid, cpu) = m->mpc_apicid;
+- per_cpu(x86_bios_cpu_apicid, cpu) = m->mpc_apicid;
+- }
+-
+- cpu_set(cpu, cpu_possible_map);
+- cpu_set(cpu, cpu_present_map);
+-}
+-
+-static void __init MP_bus_info (struct mpc_config_bus *m)
+-{
+- char str[7];
+-
+- memcpy(str, m->mpc_bustype, 6);
+- str[6] = 0;
+- Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
+-
+- if (strncmp(str, "ISA", 3) == 0) {
+- set_bit(m->mpc_busid, mp_bus_not_pci);
+- } else if (strncmp(str, "PCI", 3) == 0) {
+- clear_bit(m->mpc_busid, mp_bus_not_pci);
+- mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
+- mp_current_pci_id++;
+- } else {
+- printk(KERN_ERR "Unknown bustype %s\n", str);
+- }
+-}
+-
+-static int bad_ioapic(unsigned long address)
+-{
+- if (nr_ioapics >= MAX_IO_APICS) {
+- printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
+- "(found %d)\n", MAX_IO_APICS, nr_ioapics);
+- panic("Recompile kernel with bigger MAX_IO_APICS!\n");
+- }
+- if (!address) {
+- printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
+- " found in table, skipping!\n");
+- return 1;
+- }
+- return 0;
+-}
+-
+-static void __init MP_ioapic_info (struct mpc_config_ioapic *m)
+-{
+- if (!(m->mpc_flags & MPC_APIC_USABLE))
+- return;
+-
+- printk("I/O APIC #%d at 0x%X.\n",
+- m->mpc_apicid, m->mpc_apicaddr);
+-
+- if (bad_ioapic(m->mpc_apicaddr))
+- return;
+-
+- mp_ioapics[nr_ioapics] = *m;
+- nr_ioapics++;
+-}
+-
+-static void __init MP_intsrc_info (struct mpc_config_intsrc *m)
+-{
+- mp_irqs [mp_irq_entries] = *m;
+- Dprintk("Int: type %d, pol %d, trig %d, bus %d,"
+- " IRQ %02x, APIC ID %x, APIC INT %02x\n",
+- m->mpc_irqtype, m->mpc_irqflag & 3,
+- (m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
+- m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
+- if (++mp_irq_entries >= MAX_IRQ_SOURCES)
+- panic("Max # of irq sources exceeded!!\n");
+-}
+-
+-static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m)
+-{
+- Dprintk("Lint: type %d, pol %d, trig %d, bus %d,"
+- " IRQ %02x, APIC ID %x, APIC LINT %02x\n",
+- m->mpc_irqtype, m->mpc_irqflag & 3,
+- (m->mpc_irqflag >> 2) &3, m->mpc_srcbusid,
+- m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
+-}
+-
+-/*
+- * Read/parse the MPC
+- */
+-
+-static int __init smp_read_mpc(struct mp_config_table *mpc)
+-{
+- char str[16];
+- int count=sizeof(*mpc);
+- unsigned char *mpt=((unsigned char *)mpc)+count;
+-
+- if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) {
+- printk("MPTABLE: bad signature [%c%c%c%c]!\n",
+- mpc->mpc_signature[0],
+- mpc->mpc_signature[1],
+- mpc->mpc_signature[2],
+- mpc->mpc_signature[3]);
+- return 0;
+- }
+- if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) {
+- printk("MPTABLE: checksum error!\n");
+- return 0;
+- }
+- if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) {
+- printk(KERN_ERR "MPTABLE: bad table version (%d)!!\n",
+- mpc->mpc_spec);
+- return 0;
+- }
+- if (!mpc->mpc_lapic) {
+- printk(KERN_ERR "MPTABLE: null local APIC address!\n");
+- return 0;
+- }
+- memcpy(str,mpc->mpc_oem,8);
+- str[8] = 0;
+- printk(KERN_INFO "MPTABLE: OEM ID: %s ",str);
+-
+- memcpy(str,mpc->mpc_productid,12);
+- str[12] = 0;
+- printk("MPTABLE: Product ID: %s ",str);
+-
+- printk("MPTABLE: APIC at: 0x%X\n",mpc->mpc_lapic);
+-
+- /* save the local APIC address, it might be non-default */
+- if (!acpi_lapic)
+- mp_lapic_addr = mpc->mpc_lapic;
+-
+- /*
+- * Now process the configuration blocks.
+- */
+- while (count < mpc->mpc_length) {
+- switch(*mpt) {
+- case MP_PROCESSOR:
+- {
+- struct mpc_config_processor *m=
+- (struct mpc_config_processor *)mpt;
+- if (!acpi_lapic)
+- MP_processor_info(m);
+- mpt += sizeof(*m);
+- count += sizeof(*m);
+- break;
+- }
+- case MP_BUS:
+- {
+- struct mpc_config_bus *m=
+- (struct mpc_config_bus *)mpt;
+- MP_bus_info(m);
+- mpt += sizeof(*m);
+- count += sizeof(*m);
+- break;
+- }
+- case MP_IOAPIC:
+- {
+- struct mpc_config_ioapic *m=
+- (struct mpc_config_ioapic *)mpt;
+- MP_ioapic_info(m);
+- mpt += sizeof(*m);
+- count += sizeof(*m);
+- break;
+- }
+- case MP_INTSRC:
+- {
+- struct mpc_config_intsrc *m=
+- (struct mpc_config_intsrc *)mpt;
+-
+- MP_intsrc_info(m);
+- mpt += sizeof(*m);
+- count += sizeof(*m);
+- break;
+- }
+- case MP_LINTSRC:
+- {
+- struct mpc_config_lintsrc *m=
+- (struct mpc_config_lintsrc *)mpt;
+- MP_lintsrc_info(m);
+- mpt += sizeof(*m);
+- count += sizeof(*m);
+- break;
+- }
+- }
+- }
+- setup_apic_routing();
+- if (!num_processors)
+- printk(KERN_ERR "MPTABLE: no processors registered!\n");
+- return num_processors;
+-}
+-
+-static int __init ELCR_trigger(unsigned int irq)
+-{
+- unsigned int port;
+-
+- port = 0x4d0 + (irq >> 3);
+- return (inb(port) >> (irq & 7)) & 1;
+-}
+-
+-static void __init construct_default_ioirq_mptable(int mpc_default_type)
+-{
+- struct mpc_config_intsrc intsrc;
+- int i;
+- int ELCR_fallback = 0;
+-
+- intsrc.mpc_type = MP_INTSRC;
+- intsrc.mpc_irqflag = 0; /* conforming */
+- intsrc.mpc_srcbus = 0;
+- intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid;
+-
+- intsrc.mpc_irqtype = mp_INT;
+-
+- /*
+- * If true, we have an ISA/PCI system with no IRQ entries
+- * in the MP table. To prevent the PCI interrupts from being set up
+- * incorrectly, we try to use the ELCR. The sanity check to see if
+- * there is good ELCR data is very simple - IRQ0, 1, 2 and 13 can
+- * never be level sensitive, so we simply see if the ELCR agrees.
+- * If it does, we assume it's valid.
+- */
+- if (mpc_default_type == 5) {
+- printk(KERN_INFO "ISA/PCI bus type with no IRQ information... falling back to ELCR\n");
+-
+- if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) || ELCR_trigger(13))
+- printk(KERN_ERR "ELCR contains invalid data... not using ELCR\n");
+- else {
+- printk(KERN_INFO "Using ELCR to identify PCI interrupts\n");
+- ELCR_fallback = 1;
+- }
+- }
+-
+- for (i = 0; i < 16; i++) {
+- switch (mpc_default_type) {
+- case 2:
+- if (i == 0 || i == 13)
+- continue; /* IRQ0 & IRQ13 not connected */
+- /* fall through */
+- default:
+- if (i == 2)
+- continue; /* IRQ2 is never connected */
+- }
+-
+- if (ELCR_fallback) {
+- /*
+- * If the ELCR indicates a level-sensitive interrupt, we
+- * copy that information over to the MP table in the
+- * irqflag field (level sensitive, active high polarity).
+- */
+- if (ELCR_trigger(i))
+- intsrc.mpc_irqflag = 13;
+- else
+- intsrc.mpc_irqflag = 0;
+- }
+-
+- intsrc.mpc_srcbusirq = i;
+- intsrc.mpc_dstirq = i ? i : 2; /* IRQ0 to INTIN2 */
+- MP_intsrc_info(&intsrc);
+- }
+-
+- intsrc.mpc_irqtype = mp_ExtINT;
+- intsrc.mpc_srcbusirq = 0;
+- intsrc.mpc_dstirq = 0; /* 8259A to INTIN0 */
+- MP_intsrc_info(&intsrc);
+-}
+-
+-static inline void __init construct_default_ISA_mptable(int mpc_default_type)
+-{
+- struct mpc_config_processor processor;
+- struct mpc_config_bus bus;
+- struct mpc_config_ioapic ioapic;
+- struct mpc_config_lintsrc lintsrc;
+- int linttypes[2] = { mp_ExtINT, mp_NMI };
+- int i;
+-
+- /*
+- * local APIC has default address
+- */
+- mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
+-
+- /*
+- * 2 CPUs, numbered 0 & 1.
+- */
+- processor.mpc_type = MP_PROCESSOR;
+- processor.mpc_apicver = 0;
+- processor.mpc_cpuflag = CPU_ENABLED;
+- processor.mpc_cpufeature = 0;
+- processor.mpc_featureflag = 0;
+- processor.mpc_reserved[0] = 0;
+- processor.mpc_reserved[1] = 0;
+- for (i = 0; i < 2; i++) {
+- processor.mpc_apicid = i;
+- MP_processor_info(&processor);
+- }
+-
+- bus.mpc_type = MP_BUS;
+- bus.mpc_busid = 0;
+- switch (mpc_default_type) {
+- default:
+- printk(KERN_ERR "???\nUnknown standard configuration %d\n",
+- mpc_default_type);
+- /* fall through */
+- case 1:
+- case 5:
+- memcpy(bus.mpc_bustype, "ISA ", 6);
+- break;
+- }
+- MP_bus_info(&bus);
+- if (mpc_default_type > 4) {
+- bus.mpc_busid = 1;
+- memcpy(bus.mpc_bustype, "PCI ", 6);
+- MP_bus_info(&bus);
+- }
+-
+- ioapic.mpc_type = MP_IOAPIC;
+- ioapic.mpc_apicid = 2;
+- ioapic.mpc_apicver = 0;
+- ioapic.mpc_flags = MPC_APIC_USABLE;
+- ioapic.mpc_apicaddr = 0xFEC00000;
+- MP_ioapic_info(&ioapic);
+-
+- /*
+- * We set up most of the low 16 IO-APIC pins according to MPS rules.
+- */
+- construct_default_ioirq_mptable(mpc_default_type);
+-
+- lintsrc.mpc_type = MP_LINTSRC;
+- lintsrc.mpc_irqflag = 0; /* conforming */
+- lintsrc.mpc_srcbusid = 0;
+- lintsrc.mpc_srcbusirq = 0;
+- lintsrc.mpc_destapic = MP_APIC_ALL;
+- for (i = 0; i < 2; i++) {
+- lintsrc.mpc_irqtype = linttypes[i];
+- lintsrc.mpc_destapiclint = i;
+- MP_lintsrc_info(&lintsrc);
+- }
+-}
+-
+-static struct intel_mp_floating *mpf_found;
+-
+-/*
+- * Scan the memory blocks for an SMP configuration block.
+- */
+-void __init get_smp_config (void)
+-{
+- struct intel_mp_floating *mpf = mpf_found;
+-
+- /*
+- * ACPI supports both logical (e.g. Hyper-Threading) and physical
+- * processors, where MPS only supports physical.
+- */
+- if (acpi_lapic && acpi_ioapic) {
+- printk(KERN_INFO "Using ACPI (MADT) for SMP configuration information\n");
+- return;
+- }
+- else if (acpi_lapic)
+- printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n");
+-
+- printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
+-
+- /*
+- * Now see if we need to read further.
+- */
+- if (mpf->mpf_feature1 != 0) {
+-
+- printk(KERN_INFO "Default MP configuration #%d\n", mpf->mpf_feature1);
+- construct_default_ISA_mptable(mpf->mpf_feature1);
+-
+- } else if (mpf->mpf_physptr) {
+-
+- /*
+- * Read the physical hardware table. Anything here will
+- * override the defaults.
+- */
+- if (!smp_read_mpc(phys_to_virt(mpf->mpf_physptr))) {
+- smp_found_config = 0;
+- printk(KERN_ERR "BIOS bug, MP table errors detected!...\n");
+- printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n");
+- return;
+- }
+- /*
+- * If there are no explicit MP IRQ entries, then we are
+- * broken. We set up most of the low 16 IO-APIC pins to
+- * ISA defaults and hope it will work.
+- */
+- if (!mp_irq_entries) {
+- struct mpc_config_bus bus;
+-
+- printk(KERN_ERR "BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
+-
+- bus.mpc_type = MP_BUS;
+- bus.mpc_busid = 0;
+- memcpy(bus.mpc_bustype, "ISA ", 6);
+- MP_bus_info(&bus);
+-
+- construct_default_ioirq_mptable(0);
+- }
+-
+- } else
+- BUG();
+-
+- printk(KERN_INFO "Processors: %d\n", num_processors);
+- /*
+- * Only use the first configuration found.
+- */
+-}
+-
+-static int __init smp_scan_config (unsigned long base, unsigned long length)
+-{
+- extern void __bad_mpf_size(void);
+- unsigned int *bp = phys_to_virt(base);
+- struct intel_mp_floating *mpf;
+-
+- Dprintk("Scan SMP from %p for %ld bytes.\n", bp,length);
+- if (sizeof(*mpf) != 16)
+- __bad_mpf_size();
+-
+- while (length > 0) {
+- mpf = (struct intel_mp_floating *)bp;
+- if ((*bp == SMP_MAGIC_IDENT) &&
+- (mpf->mpf_length == 1) &&
+- !mpf_checksum((unsigned char *)bp, 16) &&
+- ((mpf->mpf_specification == 1)
+- || (mpf->mpf_specification == 4)) ) {
+-
+- smp_found_config = 1;
+- reserve_bootmem_generic(virt_to_phys(mpf), PAGE_SIZE);
+- if (mpf->mpf_physptr)
+- reserve_bootmem_generic(mpf->mpf_physptr, PAGE_SIZE);
+- mpf_found = mpf;
+- return 1;
+- }
+- bp += 4;
+- length -= 16;
+- }
+- return 0;
+-}
+-
+-void __init find_smp_config(void)
+-{
+- unsigned int address;
+-
+- /*
+- * FIXME: Linux assumes you have 640K of base ram..
+- * this continues the error...
+- *
+- * 1) Scan the bottom 1K for a signature
+- * 2) Scan the top 1K of base RAM
+- * 3) Scan the 64K of bios
+- */
+- if (smp_scan_config(0x0,0x400) ||
+- smp_scan_config(639*0x400,0x400) ||
+- smp_scan_config(0xF0000,0x10000))
+- return;
+- /*
+- * If it is an SMP machine we should know now.
+- *
+- * there is a real-mode segmented pointer pointing to the
+- * 4K EBDA area at 0x40E, calculate and scan it here.
+- *
+- * NOTE! There are Linux loaders that will corrupt the EBDA
+- * area, and as such this kind of SMP config may be less
+- * trustworthy, simply because the SMP table may have been
+- * stomped on during early boot. These loaders are buggy and
+- * should be fixed.
+- */
+-
+- address = *(unsigned short *)phys_to_virt(0x40E);
+- address <<= 4;
+- if (smp_scan_config(address, 0x1000))
+- return;
+-
+- /* If we have come this far, we did not find an MP table */
+- printk(KERN_INFO "No mptable found.\n");
+-}
+-
+-/* --------------------------------------------------------------------------
+- ACPI-based MP Configuration
+- -------------------------------------------------------------------------- */
+-
+-#ifdef CONFIG_ACPI
+-
+-void __init mp_register_lapic_address(u64 address)
+-{
+- mp_lapic_addr = (unsigned long) address;
+- set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
+- if (boot_cpu_id == -1U)
+- boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID));
+-}
+-
+-void __cpuinit mp_register_lapic (u8 id, u8 enabled)
+-{
+- struct mpc_config_processor processor;
+- int boot_cpu = 0;
+-
+- if (id == boot_cpu_id)
+- boot_cpu = 1;
+-
+- processor.mpc_type = MP_PROCESSOR;
+- processor.mpc_apicid = id;
+- processor.mpc_apicver = 0;
+- processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0);
+- processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0);
+- processor.mpc_cpufeature = 0;
+- processor.mpc_featureflag = 0;
+- processor.mpc_reserved[0] = 0;
+- processor.mpc_reserved[1] = 0;
+-
+- MP_processor_info(&processor);
+-}
+-
+-#define MP_ISA_BUS 0
+-#define MP_MAX_IOAPIC_PIN 127
+-
+-static struct mp_ioapic_routing {
+- int apic_id;
+- int gsi_start;
+- int gsi_end;
+- u32 pin_programmed[4];
+-} mp_ioapic_routing[MAX_IO_APICS];
+-
+-static int mp_find_ioapic(int gsi)
+-{
+- int i = 0;
+-
+- /* Find the IOAPIC that manages this GSI. */
+- for (i = 0; i < nr_ioapics; i++) {
+- if ((gsi >= mp_ioapic_routing[i].gsi_start)
+- && (gsi <= mp_ioapic_routing[i].gsi_end))
+- return i;
+- }
+-
+- printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
+- return -1;
+-}
+-
+-static u8 uniq_ioapic_id(u8 id)
+-{
+- int i;
+- DECLARE_BITMAP(used, 256);
+- bitmap_zero(used, 256);
+- for (i = 0; i < nr_ioapics; i++) {
+- struct mpc_config_ioapic *ia = &mp_ioapics[i];
+- __set_bit(ia->mpc_apicid, used);
+- }
+- if (!test_bit(id, used))
+- return id;
+- return find_first_zero_bit(used, 256);
+-}
+-
+-void __init mp_register_ioapic(u8 id, u32 address, u32 gsi_base)
+-{
+- int idx = 0;
+-
+- if (bad_ioapic(address))
+- return;
+-
+- idx = nr_ioapics;
+-
+- mp_ioapics[idx].mpc_type = MP_IOAPIC;
+- mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE;
+- mp_ioapics[idx].mpc_apicaddr = address;
+-
+- set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
+- mp_ioapics[idx].mpc_apicid = uniq_ioapic_id(id);
+- mp_ioapics[idx].mpc_apicver = 0;
+-
+- /*
+- * Build basic IRQ lookup table to facilitate gsi->io_apic lookups
+- * and to prevent reprogramming of IOAPIC pins (PCI IRQs).
+- */
+- mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid;
+- mp_ioapic_routing[idx].gsi_start = gsi_base;
+- mp_ioapic_routing[idx].gsi_end = gsi_base +
+- io_apic_get_redir_entries(idx);
+-
+- printk(KERN_INFO "IOAPIC[%d]: apic_id %d, address 0x%x, "
+- "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid,
+- mp_ioapics[idx].mpc_apicaddr,
+- mp_ioapic_routing[idx].gsi_start,
+- mp_ioapic_routing[idx].gsi_end);
+-
+- nr_ioapics++;
+-}
+-
+-void __init
+-mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
+-{
+- struct mpc_config_intsrc intsrc;
+- int ioapic = -1;
+- int pin = -1;
+-
+- /*
+- * Convert 'gsi' to 'ioapic.pin'.
+- */
+- ioapic = mp_find_ioapic(gsi);
+- if (ioapic < 0)
+- return;
+- pin = gsi - mp_ioapic_routing[ioapic].gsi_start;
+-
+- /*
+- * TBD: This check is for faulty timer entries, where the override
+- * erroneously sets the trigger to level, resulting in a HUGE
+- * increase of timer interrupts!
+- */
+- if ((bus_irq == 0) && (trigger == 3))
+- trigger = 1;
+-
+- intsrc.mpc_type = MP_INTSRC;
+- intsrc.mpc_irqtype = mp_INT;
+- intsrc.mpc_irqflag = (trigger << 2) | polarity;
+- intsrc.mpc_srcbus = MP_ISA_BUS;
+- intsrc.mpc_srcbusirq = bus_irq; /* IRQ */
+- intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; /* APIC ID */
+- intsrc.mpc_dstirq = pin; /* INTIN# */
+-
+- Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, %d-%d\n",
+- intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3,
+- (intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus,
+- intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, intsrc.mpc_dstirq);
+-
+- mp_irqs[mp_irq_entries] = intsrc;
+- if (++mp_irq_entries == MAX_IRQ_SOURCES)
+- panic("Max # of irq sources exceeded!\n");
+-}
+-
+-void __init mp_config_acpi_legacy_irqs(void)
+-{
+- struct mpc_config_intsrc intsrc;
+- int i = 0;
+- int ioapic = -1;
+-
+- /*
+- * Fabricate the legacy ISA bus (bus #31).
+- */
+- set_bit(MP_ISA_BUS, mp_bus_not_pci);
+-
+- /*
+- * Locate the IOAPIC that manages the ISA IRQs (0-15).
+- */
+- ioapic = mp_find_ioapic(0);
+- if (ioapic < 0)
+- return;
+-
+- intsrc.mpc_type = MP_INTSRC;
+- intsrc.mpc_irqflag = 0; /* Conforming */
+- intsrc.mpc_srcbus = MP_ISA_BUS;
+- intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;
+-
+- /*
+- * Use the default configuration for the IRQs 0-15. Unless
+- * overridden by (MADT) interrupt source override entries.
+- */
+- for (i = 0; i < 16; i++) {
+- int idx;
+-
+- for (idx = 0; idx < mp_irq_entries; idx++) {
+- struct mpc_config_intsrc *irq = mp_irqs + idx;
+-
+- /* Do we already have a mapping for this ISA IRQ? */
+- if (irq->mpc_srcbus == MP_ISA_BUS && irq->mpc_srcbusirq == i)
+- break;
+-
+- /* Do we already have a mapping for this IOAPIC pin */
+- if ((irq->mpc_dstapic == intsrc.mpc_dstapic) &&
+- (irq->mpc_dstirq == i))
+- break;
+- }
+-
+- if (idx != mp_irq_entries) {
+- printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i);
+- continue; /* IRQ already used */
+- }
+-
+- intsrc.mpc_irqtype = mp_INT;
+- intsrc.mpc_srcbusirq = i; /* Identity mapped */
+- intsrc.mpc_dstirq = i;
+-
+- Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, "
+- "%d-%d\n", intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3,
+- (intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus,
+- intsrc.mpc_srcbusirq, intsrc.mpc_dstapic,
+- intsrc.mpc_dstirq);
+-
+- mp_irqs[mp_irq_entries] = intsrc;
+- if (++mp_irq_entries == MAX_IRQ_SOURCES)
+- panic("Max # of irq sources exceeded!\n");
+- }
+-}
+-
+-int mp_register_gsi(u32 gsi, int triggering, int polarity)
+-{
+- int ioapic = -1;
+- int ioapic_pin = 0;
+- int idx, bit = 0;
+-
+- if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
+- return gsi;
+-
+- /* Don't set up the ACPI SCI because it's already set up */
+- if (acpi_gbl_FADT.sci_interrupt == gsi)
+- return gsi;
+-
+- ioapic = mp_find_ioapic(gsi);
+- if (ioapic < 0) {
+- printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
+- return gsi;
+- }
+-
+- ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_start;
+-
+- /*
+- * Avoid pin reprogramming. PRTs typically include entries
+- * with redundant pin->gsi mappings (but unique PCI devices);
+- * we only program the IOAPIC on the first.
+- */
+- bit = ioapic_pin % 32;
+- idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
+- if (idx > 3) {
+- printk(KERN_ERR "Invalid reference to IOAPIC pin "
+- "%d-%d\n", mp_ioapic_routing[ioapic].apic_id,
+- ioapic_pin);
+- return gsi;
+- }
+- if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
+- Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
+- mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
+- return gsi;
+- }
+-
+- mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
+-
+- io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
+- triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
+- polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
+- return gsi;
+-}
+-#endif /*CONFIG_ACPI*/
+diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
+index af51ea8..1f3abe0 100644
+--- a/arch/x86/kernel/msr.c
++++ b/arch/x86/kernel/msr.c
+@@ -65,8 +65,8 @@ static loff_t msr_seek(struct file *file, loff_t offset, int orig)
+ return ret;
+ }
+
+-static ssize_t msr_read(struct file *file, char __user * buf,
+- size_t count, loff_t * ppos)
++static ssize_t msr_read(struct file *file, char __user *buf,
++ size_t count, loff_t *ppos)
+ {
+ u32 __user *tmp = (u32 __user *) buf;
+ u32 data[2];
+@@ -162,12 +162,10 @@ static int __cpuinit msr_class_cpu_callback(struct notifier_block *nfb,
+ err = msr_device_create(cpu);
+ break;
+ case CPU_UP_CANCELED:
++ case CPU_UP_CANCELED_FROZEN:
+ case CPU_DEAD:
+ msr_device_destroy(cpu);
+ break;
+- case CPU_UP_CANCELED_FROZEN:
+- destroy_suspended_device(msr_class, MKDEV(MSR_MAJOR, cpu));
+- break;
+ }
+ return err ? NOTIFY_BAD : NOTIFY_OK;
+ }
+diff --git a/arch/x86/kernel/nmi_32.c b/arch/x86/kernel/nmi_32.c
+index 6a0aa70..11b14bb 100644
+--- a/arch/x86/kernel/nmi_32.c
++++ b/arch/x86/kernel/nmi_32.c
+@@ -22,9 +22,11 @@
+ #include <linux/cpumask.h>
+ #include <linux/kernel_stat.h>
+ #include <linux/kdebug.h>
++#include <linux/slab.h>
+
+ #include <asm/smp.h>
+ #include <asm/nmi.h>
++#include <asm/timer.h>
+
+ #include "mach_traps.h"
+
+@@ -67,7 +69,7 @@ static __init void nmi_cpu_busy(void *data)
+ }
+ #endif
+
+-static int __init check_nmi_watchdog(void)
++int __init check_nmi_watchdog(void)
+ {
+ unsigned int *prev_nmi_count;
+ int cpu;
+@@ -80,7 +82,7 @@ static int __init check_nmi_watchdog(void)
+
+ prev_nmi_count = kmalloc(NR_CPUS * sizeof(int), GFP_KERNEL);
+ if (!prev_nmi_count)
+- return -1;
++ goto error;
+
+ printk(KERN_INFO "Testing NMI watchdog ... ");
+
+@@ -117,7 +119,7 @@ static int __init check_nmi_watchdog(void)
+ if (!atomic_read(&nmi_active)) {
+ kfree(prev_nmi_count);
+ atomic_set(&nmi_active, -1);
+- return -1;
++ goto error;
+ }
+ printk("OK.\n");
+
+@@ -128,9 +130,11 @@ static int __init check_nmi_watchdog(void)
+
+ kfree(prev_nmi_count);
+ return 0;
++error:
++ timer_ack = !cpu_has_tsc;
++
++ return -1;
+ }
+-/* This needs to happen later in boot so counters are working */
+-late_initcall(check_nmi_watchdog);
+
+ static int __init setup_nmi_watchdog(char *str)
+ {
+@@ -317,7 +321,8 @@ EXPORT_SYMBOL(touch_nmi_watchdog);
+
+ extern void die_nmi(struct pt_regs *, const char *msg);
+
+-__kprobes int nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
++notrace __kprobes int
++nmi_watchdog_tick(struct pt_regs *regs, unsigned reason)
+ {
+
+ /*
+diff --git a/arch/x86/kernel/nmi_64.c b/arch/x86/kernel/nmi_64.c
+index 9a4fde7..5a29ded 100644
+--- a/arch/x86/kernel/nmi_64.c
++++ b/arch/x86/kernel/nmi_64.c
+@@ -26,6 +26,8 @@
+ #include <asm/proto.h>
+ #include <asm/mce.h>
+
++#include <mach_traps.h>
++
+ int unknown_nmi_panic;
+ int nmi_watchdog_enabled;
+ int panic_on_unrecovered_nmi;
+@@ -311,7 +313,8 @@ void touch_nmi_watchdog(void)
+ }
+ EXPORT_SYMBOL(touch_nmi_watchdog);
+
+-int __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
++notrace __kprobes int
++nmi_watchdog_tick(struct pt_regs *regs, unsigned reason)
+ {
+ int sum;
+ int touched = 0;
+@@ -382,7 +385,8 @@ int __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
+
+ static unsigned ignore_nmis;
+
+-asmlinkage __kprobes void do_nmi(struct pt_regs * regs, long error_code)
++asmlinkage notrace __kprobes void
++do_nmi(struct pt_regs *regs, long error_code)
+ {
+ nmi_enter();
+ add_pda(__nmi_count,1);
+diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
+index 075962c..74f0c5e 100644
+--- a/arch/x86/kernel/paravirt.c
++++ b/arch/x86/kernel/paravirt.c
+@@ -206,13 +206,6 @@ static struct resource reserve_ioports = {
+ .flags = IORESOURCE_IO | IORESOURCE_BUSY,
+ };
+
+-static struct resource reserve_iomem = {
+- .start = 0,
+- .end = -1,
+- .name = "paravirt-iomem",
+- .flags = IORESOURCE_MEM | IORESOURCE_BUSY,
+-};
+-
+ /*
+ * Reserve the whole legacy IO space to prevent any legacy drivers
+ * from wasting time probing for their hardware. This is a fairly
+@@ -222,16 +215,7 @@ static struct resource reserve_iomem = {
+ */
+ int paravirt_disable_iospace(void)
+ {
+- int ret;
+-
+- ret = request_resource(&ioport_resource, &reserve_ioports);
+- if (ret == 0) {
+- ret = request_resource(&iomem_resource, &reserve_iomem);
+- if (ret)
+- release_resource(&reserve_ioports);
+- }
+-
+- return ret;
++ return request_resource(&ioport_resource, &reserve_ioports);
+ }
+
+ static DEFINE_PER_CPU(enum paravirt_lazy_mode, paravirt_lazy_mode) = PARAVIRT_LAZY_NONE;
+@@ -382,11 +366,13 @@ struct pv_mmu_ops pv_mmu_ops = {
+ .flush_tlb_single = native_flush_tlb_single,
+ .flush_tlb_others = native_flush_tlb_others,
+
+- .alloc_pt = paravirt_nop,
+- .alloc_pd = paravirt_nop,
+- .alloc_pd_clone = paravirt_nop,
+- .release_pt = paravirt_nop,
+- .release_pd = paravirt_nop,
++ .alloc_pte = paravirt_nop,
++ .alloc_pmd = paravirt_nop,
++ .alloc_pmd_clone = paravirt_nop,
++ .alloc_pud = paravirt_nop,
++ .release_pte = paravirt_nop,
++ .release_pmd = paravirt_nop,
++ .release_pud = paravirt_nop,
+
+ .set_pte = native_set_pte,
+ .set_pte_at = native_set_pte_at,
+diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
+index 1b5464c..e28ec49 100644
+--- a/arch/x86/kernel/pci-calgary_64.c
++++ b/arch/x86/kernel/pci-calgary_64.c
+@@ -43,6 +43,7 @@
+ #include <asm/system.h>
+ #include <asm/dma.h>
+ #include <asm/rio.h>
++#include <asm/bios_ebda.h>
+
+ #ifdef CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT
+ int use_calgary __read_mostly = 1;
+@@ -470,10 +471,11 @@ error:
+ return 0;
+ }
+
+-static dma_addr_t calgary_map_single(struct device *dev, void *vaddr,
++static dma_addr_t calgary_map_single(struct device *dev, phys_addr_t paddr,
+ size_t size, int direction)
+ {
+ dma_addr_t dma_handle = bad_dma_address;
++ void *vaddr = phys_to_virt(paddr);
+ unsigned long uaddr;
+ unsigned int npages;
+ struct iommu_table *tbl = find_iommu_table(dev);
+@@ -1232,8 +1234,7 @@ static int __init calgary_init(void)
+
+ error:
+ do {
+- dev = pci_get_device_reverse(PCI_VENDOR_ID_IBM,
+- PCI_ANY_ID, dev);
++ dev = pci_get_device(PCI_VENDOR_ID_IBM, PCI_ANY_ID, dev);
+ if (!dev)
+ break;
+ if (!is_cal_pci_dev(dev->device))
+diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
+new file mode 100644
+index 0000000..388b113
+--- /dev/null
++++ b/arch/x86/kernel/pci-dma.c
+@@ -0,0 +1,524 @@
++#include <linux/dma-mapping.h>
++#include <linux/dmar.h>
++#include <linux/bootmem.h>
++#include <linux/pci.h>
++
++#include <asm/proto.h>
++#include <asm/dma.h>
++#include <asm/gart.h>
++#include <asm/calgary.h>
++
++int forbid_dac __read_mostly;
++EXPORT_SYMBOL(forbid_dac);
++
++const struct dma_mapping_ops *dma_ops;
++EXPORT_SYMBOL(dma_ops);
++
++int iommu_sac_force __read_mostly = 0;
++
++#ifdef CONFIG_IOMMU_DEBUG
++int panic_on_overflow __read_mostly = 1;
++int force_iommu __read_mostly = 1;
++#else
++int panic_on_overflow __read_mostly = 0;
++int force_iommu __read_mostly = 0;
++#endif
++
++int iommu_merge __read_mostly = 0;
++
++int no_iommu __read_mostly;
++/* Set this to 1 if there is a HW IOMMU in the system */
++int iommu_detected __read_mostly = 0;
++
++/* This tells the BIO block layer to assume merging. Default to off
++ because we cannot guarantee merging later. */
++int iommu_bio_merge __read_mostly = 0;
++EXPORT_SYMBOL(iommu_bio_merge);
++
++dma_addr_t bad_dma_address __read_mostly = 0;
++EXPORT_SYMBOL(bad_dma_address);
++
++/* Dummy device used for NULL arguments (normally ISA). Better would
++ be probably a smaller DMA mask, but this is bug-to-bug compatible
++ to older i386. */
++struct device fallback_dev = {
++ .bus_id = "fallback device",
++ .coherent_dma_mask = DMA_32BIT_MASK,
++ .dma_mask = &fallback_dev.coherent_dma_mask,
++};
++
++int dma_set_mask(struct device *dev, u64 mask)
++{
++ if (!dev->dma_mask || !dma_supported(dev, mask))
++ return -EIO;
++
++ *dev->dma_mask = mask;
++
++ return 0;
++}
++EXPORT_SYMBOL(dma_set_mask);
++
++#ifdef CONFIG_X86_64
++static __initdata void *dma32_bootmem_ptr;
++static unsigned long dma32_bootmem_size __initdata = (128ULL<<20);
++
++static int __init parse_dma32_size_opt(char *p)
++{
++ if (!p)
++ return -EINVAL;
++ dma32_bootmem_size = memparse(p, &p);
++ return 0;
++}
++early_param("dma32_size", parse_dma32_size_opt);
++
++void __init dma32_reserve_bootmem(void)
++{
++ unsigned long size, align;
++ if (end_pfn <= MAX_DMA32_PFN)
++ return;
++
++ align = 64ULL<<20;
++ size = round_up(dma32_bootmem_size, align);
++ dma32_bootmem_ptr = __alloc_bootmem_nopanic(size, align,
++ __pa(MAX_DMA_ADDRESS));
++ if (dma32_bootmem_ptr)
++ dma32_bootmem_size = size;
++ else
++ dma32_bootmem_size = 0;
++}
++static void __init dma32_free_bootmem(void)
++{
++ int node;
++
++ if (end_pfn <= MAX_DMA32_PFN)
++ return;
++
++ if (!dma32_bootmem_ptr)
++ return;
++
++ for_each_online_node(node)
++ free_bootmem_node(NODE_DATA(node), __pa(dma32_bootmem_ptr),
++ dma32_bootmem_size);
++
++ dma32_bootmem_ptr = NULL;
++ dma32_bootmem_size = 0;
++}
++
++void __init pci_iommu_alloc(void)
++{
++ /* free the range so iommu could get some range less than 4G */
++ dma32_free_bootmem();
++ /*
++ * The order of these functions is important for
++ * fall-back/fail-over reasons
++ */
++#ifdef CONFIG_GART_IOMMU
++ gart_iommu_hole_init();
++#endif
++
++#ifdef CONFIG_CALGARY_IOMMU
++ detect_calgary();
++#endif
++
++ detect_intel_iommu();
++
++#ifdef CONFIG_SWIOTLB
++ pci_swiotlb_init();
++#endif
++}
++#endif
++
++/*
++ * See <Documentation/x86_64/boot-options.txt> for the iommu kernel parameter
++ * documentation.
++ */
++static __init int iommu_setup(char *p)
++{
++ iommu_merge = 1;
++
++ if (!p)
++ return -EINVAL;
++
++ while (*p) {
++ if (!strncmp(p, "off", 3))
++ no_iommu = 1;
++ /* gart_parse_options has more force support */
++ if (!strncmp(p, "force", 5))
++ force_iommu = 1;
++ if (!strncmp(p, "noforce", 7)) {
++ iommu_merge = 0;
++ force_iommu = 0;
++ }
++
++ if (!strncmp(p, "biomerge", 8)) {
++ iommu_bio_merge = 4096;
++ iommu_merge = 1;
++ force_iommu = 1;
++ }
++ if (!strncmp(p, "panic", 5))
++ panic_on_overflow = 1;
++ if (!strncmp(p, "nopanic", 7))
++ panic_on_overflow = 0;
++ if (!strncmp(p, "merge", 5)) {
++ iommu_merge = 1;
++ force_iommu = 1;
++ }
++ if (!strncmp(p, "nomerge", 7))
++ iommu_merge = 0;
++ if (!strncmp(p, "forcesac", 8))
++ iommu_sac_force = 1;
++ if (!strncmp(p, "allowdac", 8))
++ forbid_dac = 0;
++ if (!strncmp(p, "nodac", 5))
++ forbid_dac = -1;
++ if (!strncmp(p, "usedac", 6)) {
++ forbid_dac = -1;
++ return 1;
++ }
++#ifdef CONFIG_SWIOTLB
++ if (!strncmp(p, "soft", 4))
++ swiotlb = 1;
++#endif
++
++#ifdef CONFIG_GART_IOMMU
++ gart_parse_options(p);
++#endif
++
++#ifdef CONFIG_CALGARY_IOMMU
++ if (!strncmp(p, "calgary", 7))
++ use_calgary = 1;
++#endif /* CONFIG_CALGARY_IOMMU */
++
++ p += strcspn(p, ",");
++ if (*p == ',')
++ ++p;
++ }
++ return 0;
++}
++early_param("iommu", iommu_setup);
++
++#ifdef CONFIG_X86_32
++int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
++ dma_addr_t device_addr, size_t size, int flags)
++{
++ void __iomem *mem_base = NULL;
++ int pages = size >> PAGE_SHIFT;
++ int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
++
++ if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
++ goto out;
++ if (!size)
++ goto out;
++ if (dev->dma_mem)
++ goto out;
++
++ /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
++
++ mem_base = ioremap(bus_addr, size);
++ if (!mem_base)
++ goto out;
++
++ dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
++ if (!dev->dma_mem)
++ goto out;
++ dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
++ if (!dev->dma_mem->bitmap)
++ goto free1_out;
++
++ dev->dma_mem->virt_base = mem_base;
++ dev->dma_mem->device_base = device_addr;
++ dev->dma_mem->size = pages;
++ dev->dma_mem->flags = flags;
++
++ if (flags & DMA_MEMORY_MAP)
++ return DMA_MEMORY_MAP;
++
++ return DMA_MEMORY_IO;
++
++ free1_out:
++ kfree(dev->dma_mem);
++ out:
++ if (mem_base)
++ iounmap(mem_base);
++ return 0;
++}
++EXPORT_SYMBOL(dma_declare_coherent_memory);
++
++void dma_release_declared_memory(struct device *dev)
++{
++ struct dma_coherent_mem *mem = dev->dma_mem;
++
++ if (!mem)
++ return;
++ dev->dma_mem = NULL;
++ iounmap(mem->virt_base);
++ kfree(mem->bitmap);
++ kfree(mem);
++}
++EXPORT_SYMBOL(dma_release_declared_memory);
++
++void *dma_mark_declared_memory_occupied(struct device *dev,
++ dma_addr_t device_addr, size_t size)
++{
++ struct dma_coherent_mem *mem = dev->dma_mem;
++ int pos, err;
++ int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1);
++
++ pages >>= PAGE_SHIFT;
++
++ if (!mem)
++ return ERR_PTR(-EINVAL);
++
++ pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
++ err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
++ if (err != 0)
++ return ERR_PTR(err);
++ return mem->virt_base + (pos << PAGE_SHIFT);
++}
++EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
++
++static int dma_alloc_from_coherent_mem(struct device *dev, ssize_t size,
++ dma_addr_t *dma_handle, void **ret)
++{
++ struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
++ int order = get_order(size);
++
++ if (mem) {
++ int page = bitmap_find_free_region(mem->bitmap, mem->size,
++ order);
++ if (page >= 0) {
++ *dma_handle = mem->device_base + (page << PAGE_SHIFT);
++ *ret = mem->virt_base + (page << PAGE_SHIFT);
++ memset(*ret, 0, size);
++ }
++ if (mem->flags & DMA_MEMORY_EXCLUSIVE)
++ *ret = NULL;
++ }
++ return (mem != NULL);
++}
++
++static int dma_release_coherent(struct device *dev, int order, void *vaddr)
++{
++ struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
++
++ if (mem && vaddr >= mem->virt_base && vaddr <
++ (mem->virt_base + (mem->size << PAGE_SHIFT))) {
++ int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
++
++ bitmap_release_region(mem->bitmap, page, order);
++ return 1;
++ }
++ return 0;
++}
++#else
++#define dma_alloc_from_coherent_mem(dev, size, handle, ret) (0)
++#define dma_release_coherent(dev, order, vaddr) (0)
++#endif /* CONFIG_X86_32 */
++
++int dma_supported(struct device *dev, u64 mask)
++{
++#ifdef CONFIG_PCI
++ if (mask > 0xffffffff && forbid_dac > 0) {
++ printk(KERN_INFO "PCI: Disallowing DAC for device %s\n",
++ dev->bus_id);
++ return 0;
++ }
++#endif
++
++ if (dma_ops->dma_supported)
++ return dma_ops->dma_supported(dev, mask);
++
++ /* Copied from i386. Doesn't make much sense, because it will
++ only work for pci_alloc_coherent.
++ The caller just has to use GFP_DMA in this case. */
++ if (mask < DMA_24BIT_MASK)
++ return 0;
++
++ /* Tell the device to use SAC when IOMMU force is on. This
++ allows the driver to use cheaper accesses in some cases.
++
++ Problem with this is that if we overflow the IOMMU area and
++ return DAC as fallback address the device may not handle it
++ correctly.
++
++ As a special case some controllers have a 39bit address
++ mode that is as efficient as 32bit (aic79xx). Don't force
++ SAC for these. Assume all masks <= 40 bits are of this
++ type. Normally this doesn't make any difference, but gives
++ more gentle handling of IOMMU overflow. */
++ if (iommu_sac_force && (mask >= DMA_40BIT_MASK)) {
++ printk(KERN_INFO "%s: Force SAC with mask %Lx\n",
++ dev->bus_id, mask);
++ return 0;
++ }
++
++ return 1;
++}
++EXPORT_SYMBOL(dma_supported);
++
++/* Allocate DMA memory on node near device */
++noinline struct page *
++dma_alloc_pages(struct device *dev, gfp_t gfp, unsigned order)
++{
++ int node;
++
++ node = dev_to_node(dev);
++
++ return alloc_pages_node(node, gfp, order);
++}
++
++/*
++ * Allocate memory for a coherent mapping.
++ */
++void *
++dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
++ gfp_t gfp)
++{
++ void *memory = NULL;
++ struct page *page;
++ unsigned long dma_mask = 0;
++ dma_addr_t bus;
++
++ /* ignore region specifiers */
++ gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
++
++ if (dma_alloc_from_coherent_mem(dev, size, dma_handle, &memory))
++ return memory;
++
++ if (!dev)
++ dev = &fallback_dev;
++ dma_mask = dev->coherent_dma_mask;
++ if (dma_mask == 0)
++ dma_mask = DMA_32BIT_MASK;
++
++ /* Device not DMA able */
++ if (dev->dma_mask == NULL)
++ return NULL;
++
++ /* Don't invoke OOM killer */
++ gfp |= __GFP_NORETRY;
++
++#ifdef CONFIG_X86_64
++ /* Why <=? Even when the mask is smaller than 4GB it is often
++ larger than 16MB and in this case we have a chance of
++ finding fitting memory in the next higher zone first. If
++ not retry with true GFP_DMA. -AK */
++ if (dma_mask <= DMA_32BIT_MASK)
++ gfp |= GFP_DMA32;
++#endif
++
++ again:
++ page = dma_alloc_pages(dev, gfp, get_order(size));
++ if (page == NULL)
++ return NULL;
++
++ {
++ int high, mmu;
++ bus = page_to_phys(page);
++ memory = page_address(page);
++ high = (bus + size) >= dma_mask;
++ mmu = high;
++ if (force_iommu && !(gfp & GFP_DMA))
++ mmu = 1;
++ else if (high) {
++ free_pages((unsigned long)memory,
++ get_order(size));
++
++ /* Don't use the 16MB ZONE_DMA unless absolutely
++ needed. It's better to use remapping first. */
++ if (dma_mask < DMA_32BIT_MASK && !(gfp & GFP_DMA)) {
++ gfp = (gfp & ~GFP_DMA32) | GFP_DMA;
++ goto again;
++ }
++
++ /* Let low level make its own zone decisions */
++ gfp &= ~(GFP_DMA32|GFP_DMA);
++
++ if (dma_ops->alloc_coherent)
++ return dma_ops->alloc_coherent(dev, size,
++ dma_handle, gfp);
++ return NULL;
++ }
++
++ memset(memory, 0, size);
++ if (!mmu) {
++ *dma_handle = bus;
++ return memory;
++ }
++ }
++
++ if (dma_ops->alloc_coherent) {
++ free_pages((unsigned long)memory, get_order(size));
++ gfp &= ~(GFP_DMA|GFP_DMA32);
++ return dma_ops->alloc_coherent(dev, size, dma_handle, gfp);
++ }
++
++ if (dma_ops->map_simple) {
++ *dma_handle = dma_ops->map_simple(dev, virt_to_phys(memory),
++ size,
++ PCI_DMA_BIDIRECTIONAL);
++ if (*dma_handle != bad_dma_address)
++ return memory;
++ }
++
++ if (panic_on_overflow)
++ panic("dma_alloc_coherent: IOMMU overflow by %lu bytes\n",
++ (unsigned long)size);
++ free_pages((unsigned long)memory, get_order(size));
++ return NULL;
++}
++EXPORT_SYMBOL(dma_alloc_coherent);
++
++/*
++ * Unmap coherent memory.
++ * The caller must ensure that the device has finished accessing the mapping.
++ */
++void dma_free_coherent(struct device *dev, size_t size,
++ void *vaddr, dma_addr_t bus)
++{
++ int order = get_order(size);
++ WARN_ON(irqs_disabled()); /* for portability */
++ if (dma_release_coherent(dev, order, vaddr))
++ return;
++ if (dma_ops->unmap_single)
++ dma_ops->unmap_single(dev, bus, size, 0);
++ free_pages((unsigned long)vaddr, order);
++}
++EXPORT_SYMBOL(dma_free_coherent);
++
++static int __init pci_iommu_init(void)
++{
++#ifdef CONFIG_CALGARY_IOMMU
++ calgary_iommu_init();
++#endif
++
++ intel_iommu_init();
++
++#ifdef CONFIG_GART_IOMMU
++ gart_iommu_init();
++#endif
++
++ no_iommu_init();
++ return 0;
++}
++
++void pci_iommu_shutdown(void)
++{
++ gart_iommu_shutdown();
++}
++/* Must execute after PCI subsystem */
++fs_initcall(pci_iommu_init);
++
++#ifdef CONFIG_PCI
++/* Many VIA bridges seem to corrupt data for DAC. Disable it here */
++
++static __devinit void via_no_dac(struct pci_dev *dev)
++{
++ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && forbid_dac == 0) {
++ printk(KERN_INFO "PCI: VIA PCI bridge detected."
++ "Disabling DAC.\n");
++ forbid_dac = 1;
++ }
++}
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, via_no_dac);
++#endif
+diff --git a/arch/x86/kernel/pci-dma_32.c b/arch/x86/kernel/pci-dma_32.c
+deleted file mode 100644
+index 5133032..0000000
+--- a/arch/x86/kernel/pci-dma_32.c
++++ /dev/null
+@@ -1,177 +0,0 @@
+-/*
+- * Dynamic DMA mapping support.
+- *
+- * On i386 there is no hardware dynamic DMA address translation,
+- * so consistent alloc/free are merely page allocation/freeing.
+- * The rest of the dynamic DMA mapping interface is implemented
+- * in asm/pci.h.
+- */
+-
+-#include <linux/types.h>
+-#include <linux/mm.h>
+-#include <linux/string.h>
+-#include <linux/pci.h>
+-#include <linux/module.h>
+-#include <asm/io.h>
+-
+-struct dma_coherent_mem {
+- void *virt_base;
+- u32 device_base;
+- int size;
+- int flags;
+- unsigned long *bitmap;
+-};
+-
+-void *dma_alloc_coherent(struct device *dev, size_t size,
+- dma_addr_t *dma_handle, gfp_t gfp)
+-{
+- void *ret;
+- struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
+- int order = get_order(size);
+- /* ignore region specifiers */
+- gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
+-
+- if (mem) {
+- int page = bitmap_find_free_region(mem->bitmap, mem->size,
+- order);
+- if (page >= 0) {
+- *dma_handle = mem->device_base + (page << PAGE_SHIFT);
+- ret = mem->virt_base + (page << PAGE_SHIFT);
+- memset(ret, 0, size);
+- return ret;
+- }
+- if (mem->flags & DMA_MEMORY_EXCLUSIVE)
+- return NULL;
+- }
+-
+- if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
+- gfp |= GFP_DMA;
+-
+- ret = (void *)__get_free_pages(gfp, order);
+-
+- if (ret != NULL) {
+- memset(ret, 0, size);
+- *dma_handle = virt_to_phys(ret);
+- }
+- return ret;
+-}
+-EXPORT_SYMBOL(dma_alloc_coherent);
+-
+-void dma_free_coherent(struct device *dev, size_t size,
+- void *vaddr, dma_addr_t dma_handle)
+-{
+- struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
+- int order = get_order(size);
+-
+- WARN_ON(irqs_disabled()); /* for portability */
+- if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) {
+- int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
+-
+- bitmap_release_region(mem->bitmap, page, order);
+- } else
+- free_pages((unsigned long)vaddr, order);
+-}
+-EXPORT_SYMBOL(dma_free_coherent);
+-
+-int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+- dma_addr_t device_addr, size_t size, int flags)
+-{
+- void __iomem *mem_base = NULL;
+- int pages = size >> PAGE_SHIFT;
+- int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
+-
+- if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
+- goto out;
+- if (!size)
+- goto out;
+- if (dev->dma_mem)
+- goto out;
+-
+- /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
+-
+- mem_base = ioremap(bus_addr, size);
+- if (!mem_base)
+- goto out;
+-
+- dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
+- if (!dev->dma_mem)
+- goto out;
+- dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+- if (!dev->dma_mem->bitmap)
+- goto free1_out;
+-
+- dev->dma_mem->virt_base = mem_base;
+- dev->dma_mem->device_base = device_addr;
+- dev->dma_mem->size = pages;
+- dev->dma_mem->flags = flags;
+-
+- if (flags & DMA_MEMORY_MAP)
+- return DMA_MEMORY_MAP;
+-
+- return DMA_MEMORY_IO;
+-
+- free1_out:
+- kfree(dev->dma_mem);
+- out:
+- if (mem_base)
+- iounmap(mem_base);
+- return 0;
+-}
+-EXPORT_SYMBOL(dma_declare_coherent_memory);
+-
+-void dma_release_declared_memory(struct device *dev)
+-{
+- struct dma_coherent_mem *mem = dev->dma_mem;
+-
+- if(!mem)
+- return;
+- dev->dma_mem = NULL;
+- iounmap(mem->virt_base);
+- kfree(mem->bitmap);
+- kfree(mem);
+-}
+-EXPORT_SYMBOL(dma_release_declared_memory);
+-
+-void *dma_mark_declared_memory_occupied(struct device *dev,
+- dma_addr_t device_addr, size_t size)
+-{
+- struct dma_coherent_mem *mem = dev->dma_mem;
+- int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT;
+- int pos, err;
+-
+- if (!mem)
+- return ERR_PTR(-EINVAL);
+-
+- pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
+- err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
+- if (err != 0)
+- return ERR_PTR(err);
+- return mem->virt_base + (pos << PAGE_SHIFT);
+-}
+-EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
+-
+-#ifdef CONFIG_PCI
+-/* Many VIA bridges seem to corrupt data for DAC. Disable it here */
+-
+-int forbid_dac;
+-EXPORT_SYMBOL(forbid_dac);
+-
+-static __devinit void via_no_dac(struct pci_dev *dev)
+-{
+- if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && forbid_dac == 0) {
+- printk(KERN_INFO "PCI: VIA PCI bridge detected. Disabling DAC.\n");
+- forbid_dac = 1;
+- }
+-}
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, via_no_dac);
+-
+-static int check_iommu(char *s)
+-{
+- if (!strcmp(s, "usedac")) {
+- forbid_dac = -1;
+- return 1;
+- }
+- return 0;
+-}
+-__setup("iommu=", check_iommu);
+-#endif
+diff --git a/arch/x86/kernel/pci-dma_64.c b/arch/x86/kernel/pci-dma_64.c
+deleted file mode 100644
+index 375cb2b..0000000
+--- a/arch/x86/kernel/pci-dma_64.c
++++ /dev/null
+@@ -1,344 +0,0 @@
+-/*
+- * Dynamic DMA mapping support.
+- */
+-
+-#include <linux/types.h>
+-#include <linux/mm.h>
+-#include <linux/string.h>
+-#include <linux/pci.h>
+-#include <linux/module.h>
+-#include <linux/dmar.h>
+-#include <asm/io.h>
+-#include <asm/gart.h>
+-#include <asm/calgary.h>
+-
+-int iommu_merge __read_mostly = 0;
+-
+-dma_addr_t bad_dma_address __read_mostly;
+-EXPORT_SYMBOL(bad_dma_address);
+-
+-/* This tells the BIO block layer to assume merging. Default to off
+- because we cannot guarantee merging later. */
+-int iommu_bio_merge __read_mostly = 0;
+-EXPORT_SYMBOL(iommu_bio_merge);
+-
+-static int iommu_sac_force __read_mostly = 0;
+-
+-int no_iommu __read_mostly;
+-#ifdef CONFIG_IOMMU_DEBUG
+-int panic_on_overflow __read_mostly = 1;
+-int force_iommu __read_mostly = 1;
+-#else
+-int panic_on_overflow __read_mostly = 0;
+-int force_iommu __read_mostly= 0;
+-#endif
+-
+-/* Set this to 1 if there is a HW IOMMU in the system */
+-int iommu_detected __read_mostly = 0;
+-
+-/* Dummy device used for NULL arguments (normally ISA). Better would
+- be probably a smaller DMA mask, but this is bug-to-bug compatible
+- to i386. */
+-struct device fallback_dev = {
+- .bus_id = "fallback device",
+- .coherent_dma_mask = DMA_32BIT_MASK,
+- .dma_mask = &fallback_dev.coherent_dma_mask,
+-};
+-
+-/* Allocate DMA memory on node near device */
+-noinline static void *
+-dma_alloc_pages(struct device *dev, gfp_t gfp, unsigned order)
+-{
+- struct page *page;
+- int node;
+-
+- node = dev_to_node(dev);
+-
+- page = alloc_pages_node(node, gfp, order);
+- return page ? page_address(page) : NULL;
+-}
+-
+-/*
+- * Allocate memory for a coherent mapping.
+- */
+-void *
+-dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+- gfp_t gfp)
+-{
+- void *memory;
+- unsigned long dma_mask = 0;
+- u64 bus;
+-
+- if (!dev)
+- dev = &fallback_dev;
+- dma_mask = dev->coherent_dma_mask;
+- if (dma_mask == 0)
+- dma_mask = DMA_32BIT_MASK;
+-
+- /* Device not DMA able */
+- if (dev->dma_mask == NULL)
+- return NULL;
+-
+- /* Don't invoke OOM killer */
+- gfp |= __GFP_NORETRY;
+-
+- /* Kludge to make it bug-to-bug compatible with i386. i386
+- uses the normal dma_mask for alloc_coherent. */
+- dma_mask &= *dev->dma_mask;
+-
+- /* Why <=? Even when the mask is smaller than 4GB it is often
+- larger than 16MB and in this case we have a chance of
+- finding fitting memory in the next higher zone first. If
+- not retry with true GFP_DMA. -AK */
+- if (dma_mask <= DMA_32BIT_MASK)
+- gfp |= GFP_DMA32;
+-
+- again:
+- memory = dma_alloc_pages(dev, gfp, get_order(size));
+- if (memory == NULL)
+- return NULL;
+-
+- {
+- int high, mmu;
+- bus = virt_to_bus(memory);
+- high = (bus + size) >= dma_mask;
+- mmu = high;
+- if (force_iommu && !(gfp & GFP_DMA))
+- mmu = 1;
+- else if (high) {
+- free_pages((unsigned long)memory,
+- get_order(size));
+-
+- /* Don't use the 16MB ZONE_DMA unless absolutely
+- needed. It's better to use remapping first. */
+- if (dma_mask < DMA_32BIT_MASK && !(gfp & GFP_DMA)) {
+- gfp = (gfp & ~GFP_DMA32) | GFP_DMA;
+- goto again;
+- }
+-
+- /* Let low level make its own zone decisions */
+- gfp &= ~(GFP_DMA32|GFP_DMA);
+-
+- if (dma_ops->alloc_coherent)
+- return dma_ops->alloc_coherent(dev, size,
+- dma_handle, gfp);
+- return NULL;
+- }
+-
+- memset(memory, 0, size);
+- if (!mmu) {
+- *dma_handle = virt_to_bus(memory);
+- return memory;
+- }
+- }
+-
+- if (dma_ops->alloc_coherent) {
+- free_pages((unsigned long)memory, get_order(size));
+- gfp &= ~(GFP_DMA|GFP_DMA32);
+- return dma_ops->alloc_coherent(dev, size, dma_handle, gfp);
+- }
+-
+- if (dma_ops->map_simple) {
+- *dma_handle = dma_ops->map_simple(dev, memory,
+- size,
+- PCI_DMA_BIDIRECTIONAL);
+- if (*dma_handle != bad_dma_address)
+- return memory;
+- }
+-
+- if (panic_on_overflow)
+- panic("dma_alloc_coherent: IOMMU overflow by %lu bytes\n",size);
+- free_pages((unsigned long)memory, get_order(size));
+- return NULL;
+-}
+-EXPORT_SYMBOL(dma_alloc_coherent);
+-
+-/*
+- * Unmap coherent memory.
+- * The caller must ensure that the device has finished accessing the mapping.
+- */
+-void dma_free_coherent(struct device *dev, size_t size,
+- void *vaddr, dma_addr_t bus)
+-{
+- WARN_ON(irqs_disabled()); /* for portability */
+- if (dma_ops->unmap_single)
+- dma_ops->unmap_single(dev, bus, size, 0);
+- free_pages((unsigned long)vaddr, get_order(size));
+-}
+-EXPORT_SYMBOL(dma_free_coherent);
+-
+-static int forbid_dac __read_mostly;
+-
+-int dma_supported(struct device *dev, u64 mask)
+-{
+-#ifdef CONFIG_PCI
+- if (mask > 0xffffffff && forbid_dac > 0) {
+-
+-
+-
+- printk(KERN_INFO "PCI: Disallowing DAC for device %s\n", dev->bus_id);
+- return 0;
+- }
+-#endif
+-
+- if (dma_ops->dma_supported)
+- return dma_ops->dma_supported(dev, mask);
+-
+- /* Copied from i386. Doesn't make much sense, because it will
+- only work for pci_alloc_coherent.
+- The caller just has to use GFP_DMA in this case. */
+- if (mask < DMA_24BIT_MASK)
+- return 0;
+-
+- /* Tell the device to use SAC when IOMMU force is on. This
+- allows the driver to use cheaper accesses in some cases.
+-
+- Problem with this is that if we overflow the IOMMU area and
+- return DAC as fallback address the device may not handle it
+- correctly.
+-
+- As a special case some controllers have a 39bit address
+- mode that is as efficient as 32bit (aic79xx). Don't force
+- SAC for these. Assume all masks <= 40 bits are of this
+- type. Normally this doesn't make any difference, but gives
+- more gentle handling of IOMMU overflow. */
+- if (iommu_sac_force && (mask >= DMA_40BIT_MASK)) {
+- printk(KERN_INFO "%s: Force SAC with mask %Lx\n", dev->bus_id,mask);
+- return 0;
+- }
+-
+- return 1;
+-}
+-EXPORT_SYMBOL(dma_supported);
+-
+-int dma_set_mask(struct device *dev, u64 mask)
+-{
+- if (!dev->dma_mask || !dma_supported(dev, mask))
+- return -EIO;
+- *dev->dma_mask = mask;
+- return 0;
+-}
+-EXPORT_SYMBOL(dma_set_mask);
+-
+-/*
+- * See <Documentation/x86_64/boot-options.txt> for the iommu kernel parameter
+- * documentation.
+- */
+-static __init int iommu_setup(char *p)
+-{
+- iommu_merge = 1;
+-
+- if (!p)
+- return -EINVAL;
+-
+- while (*p) {
+- if (!strncmp(p,"off",3))
+- no_iommu = 1;
+- /* gart_parse_options has more force support */
+- if (!strncmp(p,"force",5))
+- force_iommu = 1;
+- if (!strncmp(p,"noforce",7)) {
+- iommu_merge = 0;
+- force_iommu = 0;
+- }
+-
+- if (!strncmp(p, "biomerge",8)) {
+- iommu_bio_merge = 4096;
+- iommu_merge = 1;
+- force_iommu = 1;
+- }
+- if (!strncmp(p, "panic",5))
+- panic_on_overflow = 1;
+- if (!strncmp(p, "nopanic",7))
+- panic_on_overflow = 0;
+- if (!strncmp(p, "merge",5)) {
+- iommu_merge = 1;
+- force_iommu = 1;
+- }
+- if (!strncmp(p, "nomerge",7))
+- iommu_merge = 0;
+- if (!strncmp(p, "forcesac",8))
+- iommu_sac_force = 1;
+- if (!strncmp(p, "allowdac", 8))
+- forbid_dac = 0;
+- if (!strncmp(p, "nodac", 5))
+- forbid_dac = -1;
+-
+-#ifdef CONFIG_SWIOTLB
+- if (!strncmp(p, "soft",4))
+- swiotlb = 1;
+-#endif
+-
+-#ifdef CONFIG_GART_IOMMU
+- gart_parse_options(p);
+-#endif
+-
+-#ifdef CONFIG_CALGARY_IOMMU
+- if (!strncmp(p, "calgary", 7))
+- use_calgary = 1;
+-#endif /* CONFIG_CALGARY_IOMMU */
+-
+- p += strcspn(p, ",");
+- if (*p == ',')
+- ++p;
+- }
+- return 0;
+-}
+-early_param("iommu", iommu_setup);
+-
+-void __init pci_iommu_alloc(void)
+-{
+- /*
+- * The order of these functions is important for
+- * fall-back/fail-over reasons
+- */
+-#ifdef CONFIG_GART_IOMMU
+- gart_iommu_hole_init();
+-#endif
+-
+-#ifdef CONFIG_CALGARY_IOMMU
+- detect_calgary();
+-#endif
+-
+- detect_intel_iommu();
+-
+-#ifdef CONFIG_SWIOTLB
+- pci_swiotlb_init();
+-#endif
+-}
+-
+-static int __init pci_iommu_init(void)
+-{
+-#ifdef CONFIG_CALGARY_IOMMU
+- calgary_iommu_init();
+-#endif
+-
+- intel_iommu_init();
+-
+-#ifdef CONFIG_GART_IOMMU
+- gart_iommu_init();
+-#endif
+-
+- no_iommu_init();
+- return 0;
+-}
+-
+-void pci_iommu_shutdown(void)
+-{
+- gart_iommu_shutdown();
+-}
+-
+-#ifdef CONFIG_PCI
+-/* Many VIA bridges seem to corrupt data for DAC. Disable it here */
+-
+-static __devinit void via_no_dac(struct pci_dev *dev)
+-{
+- if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && forbid_dac == 0) {
+- printk(KERN_INFO "PCI: VIA PCI bridge detected. Disabling DAC.\n");
+- forbid_dac = 1;
+- }
+-}
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, via_no_dac);
+-#endif
+-/* Must execute after PCI subsystem */
+-fs_initcall(pci_iommu_init);
+diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
+index 700e464..c07455d 100644
+--- a/arch/x86/kernel/pci-gart_64.c
++++ b/arch/x86/kernel/pci-gart_64.c
+@@ -264,9 +264,9 @@ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem,
+ }
+
+ static dma_addr_t
+-gart_map_simple(struct device *dev, char *buf, size_t size, int dir)
++gart_map_simple(struct device *dev, phys_addr_t paddr, size_t size, int dir)
+ {
+- dma_addr_t map = dma_map_area(dev, virt_to_bus(buf), size, dir);
++ dma_addr_t map = dma_map_area(dev, paddr, size, dir);
+
+ flush_gart();
+
+@@ -275,18 +275,17 @@ gart_map_simple(struct device *dev, char *buf, size_t size, int dir)
+
+ /* Map a single area into the IOMMU */
+ static dma_addr_t
+-gart_map_single(struct device *dev, void *addr, size_t size, int dir)
++gart_map_single(struct device *dev, phys_addr_t paddr, size_t size, int dir)
+ {
+- unsigned long phys_mem, bus;
++ unsigned long bus;
+
+ if (!dev)
+ dev = &fallback_dev;
+
+- phys_mem = virt_to_phys(addr);
+- if (!need_iommu(dev, phys_mem, size))
+- return phys_mem;
++ if (!need_iommu(dev, paddr, size))
++ return paddr;
+
+- bus = gart_map_simple(dev, addr, size, dir);
++ bus = gart_map_simple(dev, paddr, size, dir);
+
+ return bus;
+ }
+diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c
+new file mode 100644
+index 0000000..aec43d5
+--- /dev/null
++++ b/arch/x86/kernel/pci-nommu.c
+@@ -0,0 +1,100 @@
++/* Fallback functions when the main IOMMU code is not compiled in. This
++ code is roughly equivalent to i386. */
++#include <linux/mm.h>
++#include <linux/init.h>
++#include <linux/pci.h>
++#include <linux/string.h>
++#include <linux/dma-mapping.h>
++#include <linux/scatterlist.h>
++
++#include <asm/gart.h>
++#include <asm/processor.h>
++#include <asm/dma.h>
++
++static int
++check_addr(char *name, struct device *hwdev, dma_addr_t bus, size_t size)
++{
++ if (hwdev && bus + size > *hwdev->dma_mask) {
++ if (*hwdev->dma_mask >= DMA_32BIT_MASK)
++ printk(KERN_ERR
++ "nommu_%s: overflow %Lx+%zu of device mask %Lx\n",
++ name, (long long)bus, size,
++ (long long)*hwdev->dma_mask);
++ return 0;
++ }
++ return 1;
++}
++
++static dma_addr_t
++nommu_map_single(struct device *hwdev, phys_addr_t paddr, size_t size,
++ int direction)
++{
++ dma_addr_t bus = paddr;
++ WARN_ON(size == 0);
++ if (!check_addr("map_single", hwdev, bus, size))
++ return bad_dma_address;
++ flush_write_buffers();
++ return bus;
++}
++
++
++/* Map a set of buffers described by scatterlist in streaming
++ * mode for DMA. This is the scatter-gather version of the
++ * above pci_map_single interface. Here the scatter gather list
++ * elements are each tagged with the appropriate dma address
++ * and length. They are obtained via sg_dma_{address,length}(SG).
++ *
++ * NOTE: An implementation may be able to use a smaller number of
++ * DMA address/length pairs than there are SG table elements.
++ * (for example via virtual mapping capabilities)
++ * The routine returns the number of addr/length pairs actually
++ * used, at most nents.
++ *
++ * Device ownership issues as mentioned above for pci_map_single are
++ * the same here.
++ */
++static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg,
++ int nents, int direction)
++{
++ struct scatterlist *s;
++ int i;
++
++ WARN_ON(nents == 0 || sg[0].length == 0);
++
++ for_each_sg(sg, s, nents, i) {
++ BUG_ON(!sg_page(s));
++ s->dma_address = sg_phys(s);
++ if (!check_addr("map_sg", hwdev, s->dma_address, s->length))
++ return 0;
++ s->dma_length = s->length;
++ }
++ flush_write_buffers();
++ return nents;
++}
++
++/* Make sure we keep the same behaviour */
++static int nommu_mapping_error(dma_addr_t dma_addr)
++{
++#ifdef CONFIG_X86_32
++ return 0;
++#else
++ return (dma_addr == bad_dma_address);
++#endif
++}
++
++
++const struct dma_mapping_ops nommu_dma_ops = {
++ .map_single = nommu_map_single,
++ .map_sg = nommu_map_sg,
++ .mapping_error = nommu_mapping_error,
++ .is_phys = 1,
++};
++
++void __init no_iommu_init(void)
++{
++ if (dma_ops)
++ return;
++
++ force_iommu = 0; /* no HW IOMMU */
++ dma_ops = &nommu_dma_ops;
++}
+diff --git a/arch/x86/kernel/pci-nommu_64.c b/arch/x86/kernel/pci-nommu_64.c
+deleted file mode 100644
+index ab08e18..0000000
+--- a/arch/x86/kernel/pci-nommu_64.c
++++ /dev/null
+@@ -1,98 +0,0 @@
+-/* Fallback functions when the main IOMMU code is not compiled in. This
+- code is roughly equivalent to i386. */
+-#include <linux/mm.h>
+-#include <linux/init.h>
+-#include <linux/pci.h>
+-#include <linux/string.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/scatterlist.h>
+-
+-#include <asm/gart.h>
+-#include <asm/processor.h>
+-#include <asm/dma.h>
+-
+-static int
+-check_addr(char *name, struct device *hwdev, dma_addr_t bus, size_t size)
+-{
+- if (hwdev && bus + size > *hwdev->dma_mask) {
+- if (*hwdev->dma_mask >= DMA_32BIT_MASK)
+- printk(KERN_ERR
+- "nommu_%s: overflow %Lx+%zu of device mask %Lx\n",
+- name, (long long)bus, size,
+- (long long)*hwdev->dma_mask);
+- return 0;
+- }
+- return 1;
+-}
+-
+-static dma_addr_t
+-nommu_map_single(struct device *hwdev, void *ptr, size_t size,
+- int direction)
+-{
+- dma_addr_t bus = virt_to_bus(ptr);
+- if (!check_addr("map_single", hwdev, bus, size))
+- return bad_dma_address;
+- return bus;
+-}
+-
+-static void nommu_unmap_single(struct device *dev, dma_addr_t addr,size_t size,
+- int direction)
+-{
+-}
+-
+-/* Map a set of buffers described by scatterlist in streaming
+- * mode for DMA. This is the scatter-gather version of the
+- * above pci_map_single interface. Here the scatter gather list
+- * elements are each tagged with the appropriate dma address
+- * and length. They are obtained via sg_dma_{address,length}(SG).
+- *
+- * NOTE: An implementation may be able to use a smaller number of
+- * DMA address/length pairs than there are SG table elements.
+- * (for example via virtual mapping capabilities)
+- * The routine returns the number of addr/length pairs actually
+- * used, at most nents.
+- *
+- * Device ownership issues as mentioned above for pci_map_single are
+- * the same here.
+- */
+-static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg,
+- int nents, int direction)
+-{
+- struct scatterlist *s;
+- int i;
+-
+- for_each_sg(sg, s, nents, i) {
+- BUG_ON(!sg_page(s));
+- s->dma_address = virt_to_bus(sg_virt(s));
+- if (!check_addr("map_sg", hwdev, s->dma_address, s->length))
+- return 0;
+- s->dma_length = s->length;
+- }
+- return nents;
+-}
+-
+-/* Unmap a set of streaming mode DMA translations.
+- * Again, cpu read rules concerning calls here are the same as for
+- * pci_unmap_single() above.
+- */
+-static void nommu_unmap_sg(struct device *dev, struct scatterlist *sg,
+- int nents, int dir)
+-{
+-}
+-
+-const struct dma_mapping_ops nommu_dma_ops = {
+- .map_single = nommu_map_single,
+- .unmap_single = nommu_unmap_single,
+- .map_sg = nommu_map_sg,
+- .unmap_sg = nommu_unmap_sg,
+- .is_phys = 1,
+-};
+-
+-void __init no_iommu_init(void)
+-{
+- if (dma_ops)
+- return;
+-
+- force_iommu = 0; /* no HW IOMMU */
+- dma_ops = &nommu_dma_ops;
+-}
+diff --git a/arch/x86/kernel/pci-swiotlb_64.c b/arch/x86/kernel/pci-swiotlb_64.c
+index 82a0a67..490da7f 100644
+--- a/arch/x86/kernel/pci-swiotlb_64.c
++++ b/arch/x86/kernel/pci-swiotlb_64.c
+@@ -11,11 +11,18 @@
+
+ int swiotlb __read_mostly;
+
++static dma_addr_t
++swiotlb_map_single_phys(struct device *hwdev, phys_addr_t paddr, size_t size,
++ int direction)
++{
++ return swiotlb_map_single(hwdev, phys_to_virt(paddr), size, direction);
++}
++
+ const struct dma_mapping_ops swiotlb_dma_ops = {
+ .mapping_error = swiotlb_dma_mapping_error,
+ .alloc_coherent = swiotlb_alloc_coherent,
+ .free_coherent = swiotlb_free_coherent,
+- .map_single = swiotlb_map_single,
++ .map_single = swiotlb_map_single_phys,
+ .unmap_single = swiotlb_unmap_single,
+ .sync_single_for_cpu = swiotlb_sync_single_for_cpu,
+ .sync_single_for_device = swiotlb_sync_single_for_device,
+diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
+new file mode 100644
+index 0000000..3004d71
+--- /dev/null
++++ b/arch/x86/kernel/process.c
+@@ -0,0 +1,44 @@
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/smp.h>
++#include <linux/slab.h>
++#include <linux/sched.h>
++
++struct kmem_cache *task_xstate_cachep;
++
++int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
++{
++ *dst = *src;
++ if (src->thread.xstate) {
++ dst->thread.xstate = kmem_cache_alloc(task_xstate_cachep,
++ GFP_KERNEL);
++ if (!dst->thread.xstate)
++ return -ENOMEM;
++ WARN_ON((unsigned long)dst->thread.xstate & 15);
++ memcpy(dst->thread.xstate, src->thread.xstate, xstate_size);
++ }
++ return 0;
++}
++
++void free_thread_xstate(struct task_struct *tsk)
++{
++ if (tsk->thread.xstate) {
++ kmem_cache_free(task_xstate_cachep, tsk->thread.xstate);
++ tsk->thread.xstate = NULL;
++ }
++}
++
++void free_thread_info(struct thread_info *ti)
++{
++ free_thread_xstate(ti->task);
++ free_pages((unsigned long)ti, get_order(THREAD_SIZE));
++}
++
++void arch_task_cache_init(void)
++{
++ task_xstate_cachep =
++ kmem_cache_create("task_xstate", xstate_size,
++ __alignof__(union thread_xstate),
++ SLAB_PANIC, NULL);
++}
+diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
+index 43930e7..77de848 100644
+--- a/arch/x86/kernel/process_32.c
++++ b/arch/x86/kernel/process_32.c
+@@ -36,6 +36,7 @@
+ #include <linux/personality.h>
+ #include <linux/tick.h>
+ #include <linux/percpu.h>
++#include <linux/prctl.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -45,7 +46,6 @@
+ #include <asm/processor.h>
+ #include <asm/i387.h>
+ #include <asm/desc.h>
+-#include <asm/vm86.h>
+ #ifdef CONFIG_MATH_EMULATION
+ #include <asm/math_emu.h>
+ #endif
+@@ -113,20 +113,13 @@ void default_idle(void)
+
+ local_irq_disable();
+ if (!need_resched()) {
+- ktime_t t0, t1;
+- u64 t0n, t1n;
+-
+- t0 = ktime_get();
+- t0n = ktime_to_ns(t0);
+ safe_halt(); /* enables interrupts racelessly */
+ local_irq_disable();
+- t1 = ktime_get();
+- t1n = ktime_to_ns(t1);
+- sched_clock_idle_wakeup_event(t1n - t0n);
+ }
+ local_irq_enable();
+ current_thread_info()->status |= TS_POLLING;
+ } else {
++ local_irq_enable();
+ /* loop is done by the caller */
+ cpu_relax();
+ }
+@@ -142,6 +135,7 @@ EXPORT_SYMBOL(default_idle);
+ */
+ static void poll_idle(void)
+ {
++ local_irq_enable();
+ cpu_relax();
+ }
+
+@@ -248,8 +242,11 @@ void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
+ __monitor((void *)¤t_thread_info()->flags, 0, 0);
+ smp_mb();
+ if (!need_resched())
+- __mwait(ax, cx);
+- }
++ __sti_mwait(ax, cx);
++ else
++ local_irq_enable();
++ } else
++ local_irq_enable();
+ }
+
+ /* Default MONITOR/MWAIT with no hints, used for default C1 state */
+@@ -332,7 +329,7 @@ void __show_registers(struct pt_regs *regs, int all)
+ init_utsname()->version);
+
+ printk("EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n",
+- 0xffff & regs->cs, regs->ip, regs->flags,
++ (u16)regs->cs, regs->ip, regs->flags,
+ smp_processor_id());
+ print_symbol("EIP is at %s\n", regs->ip);
+
+@@ -341,8 +338,7 @@ void __show_registers(struct pt_regs *regs, int all)
+ printk("ESI: %08lx EDI: %08lx EBP: %08lx ESP: %08lx\n",
+ regs->si, regs->di, regs->bp, sp);
+ printk(" DS: %04x ES: %04x FS: %04x GS: %04x SS: %04x\n",
+- regs->ds & 0xffff, regs->es & 0xffff,
+- regs->fs & 0xffff, gs, ss);
++ (u16)regs->ds, (u16)regs->es, (u16)regs->fs, gs, ss);
+
+ if (!all)
+ return;
+@@ -513,11 +509,30 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
+ return err;
+ }
+
+-#ifdef CONFIG_SECCOMP
++void
++start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
++{
++ __asm__("movl %0, %%gs" :: "r"(0));
++ regs->fs = 0;
++ set_fs(USER_DS);
++ regs->ds = __USER_DS;
++ regs->es = __USER_DS;
++ regs->ss = __USER_DS;
++ regs->cs = __USER_CS;
++ regs->ip = new_ip;
++ regs->sp = new_sp;
++ /*
++ * Free the old FP and other extended state
++ */
++ free_thread_xstate(current);
++}
++EXPORT_SYMBOL_GPL(start_thread);
++
+ static void hard_disable_TSC(void)
+ {
+ write_cr4(read_cr4() | X86_CR4_TSD);
+ }
++
+ void disable_TSC(void)
+ {
+ preempt_disable();
+@@ -529,11 +544,47 @@ void disable_TSC(void)
+ hard_disable_TSC();
+ preempt_enable();
+ }
++
+ static void hard_enable_TSC(void)
+ {
+ write_cr4(read_cr4() & ~X86_CR4_TSD);
+ }
+-#endif /* CONFIG_SECCOMP */
++
++static void enable_TSC(void)
++{
++ preempt_disable();
++ if (test_and_clear_thread_flag(TIF_NOTSC))
++ /*
++ * Must flip the CPU state synchronously with
++ * TIF_NOTSC in the current running context.
++ */
++ hard_enable_TSC();
++ preempt_enable();
++}
++
++int get_tsc_mode(unsigned long adr)
++{
++ unsigned int val;
++
++ if (test_thread_flag(TIF_NOTSC))
++ val = PR_TSC_SIGSEGV;
++ else
++ val = PR_TSC_ENABLE;
++
++ return put_user(val, (unsigned int __user *)adr);
++}
++
++int set_tsc_mode(unsigned int val)
++{
++ if (val == PR_TSC_SIGSEGV)
++ disable_TSC();
++ else if (val == PR_TSC_ENABLE)
++ enable_TSC();
++ else
++ return -EINVAL;
++
++ return 0;
++}
+
+ static noinline void
+ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
+@@ -550,12 +601,12 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
+ /* we clear debugctl to make sure DS
+ * is not in use when we change it */
+ debugctl = 0;
+- wrmsrl(MSR_IA32_DEBUGCTLMSR, 0);
++ update_debugctlmsr(0);
+ wrmsr(MSR_IA32_DS_AREA, next->ds_area_msr, 0);
+ }
+
+ if (next->debugctlmsr != debugctl)
+- wrmsr(MSR_IA32_DEBUGCTLMSR, next->debugctlmsr, 0);
++ update_debugctlmsr(next->debugctlmsr);
+
+ if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
+ set_debugreg(next->debugreg0, 0);
+@@ -567,7 +618,6 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
+ set_debugreg(next->debugreg7, 7);
+ }
+
+-#ifdef CONFIG_SECCOMP
+ if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
+ test_tsk_thread_flag(next_p, TIF_NOTSC)) {
+ /* prev and next are different */
+@@ -576,7 +626,6 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
+ else
+ hard_enable_TSC();
+ }
+-#endif
+
+ #ifdef X86_BTS
+ if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS))
+@@ -658,7 +707,7 @@ struct task_struct * __switch_to(struct task_struct *prev_p, struct task_struct
+
+ /* we're going to use this soon, after a few expensive things */
+ if (next_p->fpu_counter > 5)
+- prefetch(&next->i387.fxsave);
++ prefetch(next->xstate);
+
+ /*
+ * Reload esp0.
+diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
+index 46c4c54..131c2ee 100644
+--- a/arch/x86/kernel/process_64.c
++++ b/arch/x86/kernel/process_64.c
+@@ -36,6 +36,7 @@
+ #include <linux/kprobes.h>
+ #include <linux/kdebug.h>
+ #include <linux/tick.h>
++#include <linux/prctl.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -107,16 +108,8 @@ void default_idle(void)
+ smp_mb();
+ local_irq_disable();
+ if (!need_resched()) {
+- ktime_t t0, t1;
+- u64 t0n, t1n;
+-
+- t0 = ktime_get();
+- t0n = ktime_to_ns(t0);
+ safe_halt(); /* enables interrupts racelessly */
+ local_irq_disable();
+- t1 = ktime_get();
+- t1n = ktime_to_ns(t1);
+- sched_clock_idle_wakeup_event(t1n - t0n);
+ }
+ local_irq_enable();
+ current_thread_info()->status |= TS_POLLING;
+@@ -528,6 +521,83 @@ out:
+ return err;
+ }
+
++void
++start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
++{
++ asm volatile("movl %0, %%fs; movl %0, %%es; movl %0, %%ds" :: "r"(0));
++ load_gs_index(0);
++ regs->ip = new_ip;
++ regs->sp = new_sp;
++ write_pda(oldrsp, new_sp);
++ regs->cs = __USER_CS;
++ regs->ss = __USER_DS;
++ regs->flags = 0x200;
++ set_fs(USER_DS);
++ /*
++ * Free the old FP and other extended state
++ */
++ free_thread_xstate(current);
++}
++EXPORT_SYMBOL_GPL(start_thread);
++
++static void hard_disable_TSC(void)
++{
++ write_cr4(read_cr4() | X86_CR4_TSD);
++}
++
++void disable_TSC(void)
++{
++ preempt_disable();
++ if (!test_and_set_thread_flag(TIF_NOTSC))
++ /*
++ * Must flip the CPU state synchronously with
++ * TIF_NOTSC in the current running context.
++ */
++ hard_disable_TSC();
++ preempt_enable();
++}
++
++static void hard_enable_TSC(void)
++{
++ write_cr4(read_cr4() & ~X86_CR4_TSD);
++}
++
++static void enable_TSC(void)
++{
++ preempt_disable();
++ if (test_and_clear_thread_flag(TIF_NOTSC))
++ /*
++ * Must flip the CPU state synchronously with
++ * TIF_NOTSC in the current running context.
++ */
++ hard_enable_TSC();
++ preempt_enable();
++}
++
++int get_tsc_mode(unsigned long adr)
++{
++ unsigned int val;
++
++ if (test_thread_flag(TIF_NOTSC))
++ val = PR_TSC_SIGSEGV;
++ else
++ val = PR_TSC_ENABLE;
++
++ return put_user(val, (unsigned int __user *)adr);
++}
++
++int set_tsc_mode(unsigned int val)
++{
++ if (val == PR_TSC_SIGSEGV)
++ disable_TSC();
++ else if (val == PR_TSC_ENABLE)
++ enable_TSC();
++ else
++ return -EINVAL;
++
++ return 0;
++}
++
+ /*
+ * This special macro can be used to load a debugging register
+ */
+@@ -548,12 +618,12 @@ static inline void __switch_to_xtra(struct task_struct *prev_p,
+ /* we clear debugctl to make sure DS
+ * is not in use when we change it */
+ debugctl = 0;
+- wrmsrl(MSR_IA32_DEBUGCTLMSR, 0);
++ update_debugctlmsr(0);
+ wrmsrl(MSR_IA32_DS_AREA, next->ds_area_msr);
+ }
+
+ if (next->debugctlmsr != debugctl)
+- wrmsrl(MSR_IA32_DEBUGCTLMSR, next->debugctlmsr);
++ update_debugctlmsr(next->debugctlmsr);
+
+ if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
+ loaddebug(next, 0);
+@@ -565,6 +635,15 @@ static inline void __switch_to_xtra(struct task_struct *prev_p,
+ loaddebug(next, 7);
+ }
+
++ if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
++ test_tsk_thread_flag(next_p, TIF_NOTSC)) {
++ /* prev and next are different */
++ if (test_tsk_thread_flag(next_p, TIF_NOTSC))
++ hard_disable_TSC();
++ else
++ hard_enable_TSC();
++ }
++
+ if (test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) {
+ /*
+ * Copy the relevant range of the IO bitmap.
+@@ -607,7 +686,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
+
+ /* we're going to use this soon, after a few expensive things */
+ if (next_p->fpu_counter>5)
+- prefetch(&next->i387.fxsave);
++ prefetch(next->xstate);
+
+ /*
+ * Reload esp0, LDT and the page table pointer:
+diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
+index eb92ccb..fb03ef3 100644
+--- a/arch/x86/kernel/ptrace.c
++++ b/arch/x86/kernel/ptrace.c
+@@ -1207,97 +1207,16 @@ static int genregs32_set(struct task_struct *target,
+ return ret;
+ }
+
+-static long ptrace32_siginfo(unsigned request, u32 pid, u32 addr, u32 data)
++long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
++ compat_ulong_t caddr, compat_ulong_t cdata)
+ {
+- siginfo_t __user *si = compat_alloc_user_space(sizeof(siginfo_t));
+- compat_siginfo_t __user *si32 = compat_ptr(data);
+- siginfo_t ssi;
+- int ret;
+-
+- if (request == PTRACE_SETSIGINFO) {
+- memset(&ssi, 0, sizeof(siginfo_t));
+- ret = copy_siginfo_from_user32(&ssi, si32);
+- if (ret)
+- return ret;
+- if (copy_to_user(si, &ssi, sizeof(siginfo_t)))
+- return -EFAULT;
+- }
+- ret = sys_ptrace(request, pid, addr, (unsigned long)si);
+- if (ret)
+- return ret;
+- if (request == PTRACE_GETSIGINFO) {
+- if (copy_from_user(&ssi, si, sizeof(siginfo_t)))
+- return -EFAULT;
+- ret = copy_siginfo_to_user32(si32, &ssi);
+- }
+- return ret;
+-}
+-
+-asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
+-{
+- struct task_struct *child;
+- struct pt_regs *childregs;
++ unsigned long addr = caddr;
++ unsigned long data = cdata;
+ void __user *datap = compat_ptr(data);
+ int ret;
+ __u32 val;
+
+ switch (request) {
+- case PTRACE_TRACEME:
+- case PTRACE_ATTACH:
+- case PTRACE_KILL:
+- case PTRACE_CONT:
+- case PTRACE_SINGLESTEP:
+- case PTRACE_SINGLEBLOCK:
+- case PTRACE_DETACH:
+- case PTRACE_SYSCALL:
+- case PTRACE_OLDSETOPTIONS:
+- case PTRACE_SETOPTIONS:
+- case PTRACE_SET_THREAD_AREA:
+- case PTRACE_GET_THREAD_AREA:
+-#ifdef X86_BTS
+- case PTRACE_BTS_CONFIG:
+- case PTRACE_BTS_STATUS:
+- case PTRACE_BTS_SIZE:
+- case PTRACE_BTS_GET:
+- case PTRACE_BTS_CLEAR:
+- case PTRACE_BTS_DRAIN:
+-#endif
+- return sys_ptrace(request, pid, addr, data);
+-
+- default:
+- return -EINVAL;
+-
+- case PTRACE_PEEKTEXT:
+- case PTRACE_PEEKDATA:
+- case PTRACE_POKEDATA:
+- case PTRACE_POKETEXT:
+- case PTRACE_POKEUSR:
+- case PTRACE_PEEKUSR:
+- case PTRACE_GETREGS:
+- case PTRACE_SETREGS:
+- case PTRACE_SETFPREGS:
+- case PTRACE_GETFPREGS:
+- case PTRACE_SETFPXREGS:
+- case PTRACE_GETFPXREGS:
+- case PTRACE_GETEVENTMSG:
+- break;
+-
+- case PTRACE_SETSIGINFO:
+- case PTRACE_GETSIGINFO:
+- return ptrace32_siginfo(request, pid, addr, data);
+- }
+-
+- child = ptrace_get_task_struct(pid);
+- if (IS_ERR(child))
+- return PTR_ERR(child);
+-
+- ret = ptrace_check_attach(child, request == PTRACE_KILL);
+- if (ret < 0)
+- goto out;
+-
+- childregs = task_pt_regs(child);
+-
+- switch (request) {
+ case PTRACE_PEEKUSR:
+ ret = getreg32(child, addr, &val);
+ if (ret == 0)
+@@ -1343,12 +1262,14 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
+ sizeof(struct user32_fxsr_struct),
+ datap);
+
++ case PTRACE_GET_THREAD_AREA:
++ case PTRACE_SET_THREAD_AREA:
++ return arch_ptrace(child, request, addr, data);
++
+ default:
+ return compat_ptrace_request(child, request, addr, data);
+ }
+
+- out:
+- put_task_struct(child);
+ return ret;
+ }
+
+@@ -1456,7 +1377,6 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code)
+ /* notification of system call entry/exit
+ * - triggered by current->work.syscall_trace
+ */
+-__attribute__((regparm(3)))
+ int do_syscall_trace(struct pt_regs *regs, int entryexit)
+ {
+ int is_sysemu = test_thread_flag(TIF_SYSCALL_EMU);
+diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
+index 484c4a8..1791a75 100644
+--- a/arch/x86/kernel/reboot.c
++++ b/arch/x86/kernel/reboot.c
+@@ -1,5 +1,4 @@
+ #include <linux/module.h>
+-#include <linux/init.h>
+ #include <linux/reboot.h>
+ #include <linux/init.h>
+ #include <linux/pm.h>
+@@ -9,6 +8,7 @@
+ #include <asm/apic.h>
+ #include <asm/desc.h>
+ #include <asm/hpet.h>
++#include <asm/pgtable.h>
+ #include <asm/reboot_fixups.h>
+ #include <asm/reboot.h>
+
+@@ -16,7 +16,6 @@
+ # include <linux/dmi.h>
+ # include <linux/ctype.h>
+ # include <linux/mc146818rtc.h>
+-# include <asm/pgtable.h>
+ #else
+ # include <asm/iommu.h>
+ #endif
+@@ -276,7 +275,7 @@ void machine_real_restart(unsigned char *code, int length)
+ /* Remap the kernel at virtual address zero, as well as offset zero
+ from the kernel segment. This assumes the kernel segment starts at
+ virtual address PAGE_OFFSET. */
+- memcpy(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
++ memcpy(swapper_pg_dir, swapper_pg_dir + KERNEL_PGD_BOUNDARY,
+ sizeof(swapper_pg_dir [0]) * KERNEL_PGD_PTRS);
+
+ /*
+@@ -412,16 +411,16 @@ static void native_machine_shutdown(void)
+ #ifdef CONFIG_X86_32
+ /* See if there has been given a command line override */
+ if ((reboot_cpu != -1) && (reboot_cpu < NR_CPUS) &&
+- cpu_isset(reboot_cpu, cpu_online_map))
++ cpu_online(reboot_cpu))
+ reboot_cpu_id = reboot_cpu;
+ #endif
+
+ /* Make certain the cpu I'm about to reboot on is online */
+- if (!cpu_isset(reboot_cpu_id, cpu_online_map))
++ if (!cpu_online(reboot_cpu_id))
+ reboot_cpu_id = smp_processor_id();
+
+ /* Make certain I only run on the appropriate processor */
+- set_cpus_allowed(current, cpumask_of_cpu(reboot_cpu_id));
++ set_cpus_allowed_ptr(current, &cpumask_of_cpu(reboot_cpu_id));
+
+ /* O.K Now that I'm on the appropriate processor,
+ * stop all of the others.
+diff --git a/arch/x86/kernel/relocate_kernel_32.S b/arch/x86/kernel/relocate_kernel_32.S
+index f151d6f..c30fe25 100644
+--- a/arch/x86/kernel/relocate_kernel_32.S
++++ b/arch/x86/kernel/relocate_kernel_32.S
+@@ -9,18 +9,19 @@
+ #include <linux/linkage.h>
+ #include <asm/page.h>
+ #include <asm/kexec.h>
++#include <asm/processor-flags.h>
++#include <asm/pgtable.h>
+
+ /*
+ * Must be relocatable PIC code callable as a C function
+ */
+
+ #define PTR(x) (x << 2)
+-#define PAGE_ALIGNED (1 << PAGE_SHIFT)
+-#define PAGE_ATTR 0x63 /* _PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY */
+-#define PAE_PGD_ATTR 0x01 /* _PAGE_PRESENT */
++#define PAGE_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
++#define PAE_PGD_ATTR (_PAGE_PRESENT)
+
+ .text
+- .align PAGE_ALIGNED
++ .align PAGE_SIZE
+ .globl relocate_kernel
+ relocate_kernel:
+ movl 8(%esp), %ebp /* list of pages */
+@@ -155,7 +156,7 @@ relocate_new_kernel:
+ movl %eax, %cr3
+
+ /* setup a new stack at the end of the physical control page */
+- lea 4096(%edi), %esp
++ lea PAGE_SIZE(%edi), %esp
+
+ /* jump to identity mapped page */
+ movl %edi, %eax
+@@ -168,16 +169,16 @@ identity_mapped:
+ pushl %edx
+
+ /* Set cr0 to a known state:
+- * 31 0 == Paging disabled
+- * 18 0 == Alignment check disabled
+- * 16 0 == Write protect disabled
+- * 3 0 == No task switch
+- * 2 0 == Don't do FP software emulation.
+- * 0 1 == Proctected mode enabled
++ * - Paging disabled
++ * - Alignment check disabled
++ * - Write protect disabled
++ * - No task switch
++ * - Don't do FP software emulation.
++ * - Proctected mode enabled
+ */
+ movl %cr0, %eax
+- andl $~((1<<31)|(1<<18)|(1<<16)|(1<<3)|(1<<2)), %eax
+- orl $(1<<0), %eax
++ andl $~(X86_CR0_PG | X86_CR0_AM | X86_CR0_WP | X86_CR0_TS | X86_CR0_EM), %eax
++ orl $(X86_CR0_PE), %eax
+ movl %eax, %cr0
+
+ /* clear cr4 if applicable */
+@@ -186,8 +187,7 @@ identity_mapped:
+ /* Set cr4 to a known state:
+ * Setting everything to zero seems safe.
+ */
+- movl %cr4, %eax
+- andl $0, %eax
++ xorl %eax, %eax
+ movl %eax, %cr4
+
+ jmp 1f
+diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S
+index 14e9587..f5afe66 100644
+--- a/arch/x86/kernel/relocate_kernel_64.S
++++ b/arch/x86/kernel/relocate_kernel_64.S
+@@ -9,17 +9,18 @@
+ #include <linux/linkage.h>
+ #include <asm/page.h>
+ #include <asm/kexec.h>
++#include <asm/processor-flags.h>
++#include <asm/pgtable.h>
+
+ /*
+ * Must be relocatable PIC code callable as a C function
+ */
+
+ #define PTR(x) (x << 3)
+-#define PAGE_ALIGNED (1 << PAGE_SHIFT)
+-#define PAGE_ATTR 0x63 /* _PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY */
++#define PAGE_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+
+ .text
+- .align PAGE_ALIGNED
++ .align PAGE_SIZE
+ .code64
+ .globl relocate_kernel
+ relocate_kernel:
+@@ -160,7 +161,7 @@ relocate_new_kernel:
+ movq %r9, %cr3
+
+ /* setup a new stack at the end of the physical control page */
+- lea 4096(%r8), %rsp
++ lea PAGE_SIZE(%r8), %rsp
+
+ /* jump to identity mapped page */
+ addq $(identity_mapped - relocate_kernel), %r8
+@@ -172,33 +173,22 @@ identity_mapped:
+ pushq %rdx
+
+ /* Set cr0 to a known state:
+- * 31 1 == Paging enabled
+- * 18 0 == Alignment check disabled
+- * 16 0 == Write protect disabled
+- * 3 0 == No task switch
+- * 2 0 == Don't do FP software emulation.
+- * 0 1 == Proctected mode enabled
++ * - Paging enabled
++ * - Alignment check disabled
++ * - Write protect disabled
++ * - No task switch
++ * - Don't do FP software emulation.
++ * - Proctected mode enabled
+ */
+ movq %cr0, %rax
+- andq $~((1<<18)|(1<<16)|(1<<3)|(1<<2)), %rax
+- orl $((1<<31)|(1<<0)), %eax
++ andq $~(X86_CR0_AM | X86_CR0_WP | X86_CR0_TS | X86_CR0_EM), %rax
++ orl $(X86_CR0_PG | X86_CR0_PE), %eax
+ movq %rax, %cr0
+
+ /* Set cr4 to a known state:
+- * 10 0 == xmm exceptions disabled
+- * 9 0 == xmm registers instructions disabled
+- * 8 0 == performance monitoring counter disabled
+- * 7 0 == page global disabled
+- * 6 0 == machine check exceptions disabled
+- * 5 1 == physical address extension enabled
+- * 4 0 == page size extensions disabled
+- * 3 0 == Debug extensions disabled
+- * 2 0 == Time stamp disable (disabled)
+- * 1 0 == Protected mode virtual interrupts disabled
+- * 0 0 == VME disabled
++ * - physical address extension enabled
+ */
+-
+- movq $((1<<5)), %rax
++ movq $X86_CR4_PAE, %rax
+ movq %rax, %cr4
+
+ jmp 1f
+diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c
+index eb9b1a1..9615eee 100644
+--- a/arch/x86/kernel/rtc.c
++++ b/arch/x86/kernel/rtc.c
+@@ -9,7 +9,6 @@
+ #include <asm/vsyscall.h>
+
+ #ifdef CONFIG_X86_32
+-# define CMOS_YEARS_OFFS 1900
+ /*
+ * This is a special lock that is owned by the CPU and holds the index
+ * register we are working with. It is required for NMI access to the
+@@ -17,14 +16,11 @@
+ */
+ volatile unsigned long cmos_lock = 0;
+ EXPORT_SYMBOL(cmos_lock);
+-#else
+-/*
+- * x86-64 systems only exists since 2002.
+- * This will work up to Dec 31, 2100
+- */
+-# define CMOS_YEARS_OFFS 2000
+ #endif
+
++/* For two digit years assume time is always after that */
++#define CMOS_YEARS_OFFS 2000
++
+ DEFINE_SPINLOCK(rtc_lock);
+ EXPORT_SYMBOL(rtc_lock);
+
+@@ -98,7 +94,7 @@ int mach_set_rtc_mmss(unsigned long nowtime)
+
+ unsigned long mach_get_cmos_time(void)
+ {
+- unsigned int year, mon, day, hour, min, sec, century = 0;
++ unsigned int status, year, mon, day, hour, min, sec, century = 0;
+
+ /*
+ * If UIP is clear, then we have >= 244 microseconds before
+@@ -116,14 +112,16 @@ unsigned long mach_get_cmos_time(void)
+ mon = CMOS_READ(RTC_MONTH);
+ year = CMOS_READ(RTC_YEAR);
+
+-#if defined(CONFIG_ACPI) && defined(CONFIG_X86_64)
+- /* CHECKME: Is this really 64bit only ??? */
++#ifdef CONFIG_ACPI
+ if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
+ acpi_gbl_FADT.century)
+ century = CMOS_READ(acpi_gbl_FADT.century);
+ #endif
+
+- if (RTC_ALWAYS_BCD || !(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)) {
++ status = CMOS_READ(RTC_CONTROL);
++ WARN_ON_ONCE(RTC_ALWAYS_BCD && (status & RTC_DM_BINARY));
++
++ if (RTC_ALWAYS_BCD || !(status & RTC_DM_BINARY)) {
+ BCD_TO_BIN(sec);
+ BCD_TO_BIN(min);
+ BCD_TO_BIN(hour);
+@@ -136,11 +134,8 @@ unsigned long mach_get_cmos_time(void)
+ BCD_TO_BIN(century);
+ year += century * 100;
+ printk(KERN_INFO "Extended CMOS year: %d\n", century * 100);
+- } else {
++ } else
+ year += CMOS_YEARS_OFFS;
+- if (year < 1970)
+- year += 100;
+- }
+
+ return mktime(year, mon, day, hour, min, sec);
+ }
+@@ -151,8 +146,8 @@ unsigned char rtc_cmos_read(unsigned char addr)
+ unsigned char val;
+
+ lock_cmos_prefix(addr);
+- outb_p(addr, RTC_PORT(0));
+- val = inb_p(RTC_PORT(1));
++ outb(addr, RTC_PORT(0));
++ val = inb(RTC_PORT(1));
+ lock_cmos_suffix(addr);
+ return val;
+ }
+@@ -161,8 +156,8 @@ EXPORT_SYMBOL(rtc_cmos_read);
+ void rtc_cmos_write(unsigned char val, unsigned char addr)
+ {
+ lock_cmos_prefix(addr);
+- outb_p(addr, RTC_PORT(0));
+- outb_p(val, RTC_PORT(1));
++ outb(addr, RTC_PORT(0));
++ outb(val, RTC_PORT(1));
+ lock_cmos_suffix(addr);
+ }
+ EXPORT_SYMBOL(rtc_cmos_write);
+diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
+new file mode 100644
+index 0000000..c0c68c1
+--- /dev/null
++++ b/arch/x86/kernel/setup.c
+@@ -0,0 +1,137 @@
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/bootmem.h>
++#include <linux/percpu.h>
++#include <asm/smp.h>
++#include <asm/percpu.h>
++#include <asm/sections.h>
++#include <asm/processor.h>
++#include <asm/setup.h>
++#include <asm/topology.h>
++#include <asm/mpspec.h>
++#include <asm/apicdef.h>
++
++unsigned int num_processors;
++unsigned disabled_cpus __cpuinitdata;
++/* Processor that is doing the boot up */
++unsigned int boot_cpu_physical_apicid = -1U;
++EXPORT_SYMBOL(boot_cpu_physical_apicid);
++
++DEFINE_PER_CPU(u16, x86_cpu_to_apicid) = BAD_APICID;
++EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid);
++
++/* Bitmask of physically existing CPUs */
++physid_mask_t phys_cpu_present_map;
++
++#if defined(CONFIG_HAVE_SETUP_PER_CPU_AREA) && defined(CONFIG_SMP)
++/*
++ * Copy data used in early init routines from the initial arrays to the
++ * per cpu data areas. These arrays then become expendable and the
++ * *_early_ptr's are zeroed indicating that the static arrays are gone.
++ */
++static void __init setup_per_cpu_maps(void)
++{
++ int cpu;
++
++ for_each_possible_cpu(cpu) {
++ per_cpu(x86_cpu_to_apicid, cpu) = x86_cpu_to_apicid_init[cpu];
++ per_cpu(x86_bios_cpu_apicid, cpu) =
++ x86_bios_cpu_apicid_init[cpu];
++#ifdef CONFIG_NUMA
++ per_cpu(x86_cpu_to_node_map, cpu) =
++ x86_cpu_to_node_map_init[cpu];
++#endif
++ }
++
++ /* indicate the early static arrays will soon be gone */
++ x86_cpu_to_apicid_early_ptr = NULL;
++ x86_bios_cpu_apicid_early_ptr = NULL;
++#ifdef CONFIG_NUMA
++ x86_cpu_to_node_map_early_ptr = NULL;
++#endif
++}
++
++#ifdef CONFIG_HAVE_CPUMASK_OF_CPU_MAP
++cpumask_t *cpumask_of_cpu_map __read_mostly;
++EXPORT_SYMBOL(cpumask_of_cpu_map);
++
++/* requires nr_cpu_ids to be initialized */
++static void __init setup_cpumask_of_cpu(void)
++{
++ int i;
++
++ /* alloc_bootmem zeroes memory */
++ cpumask_of_cpu_map = alloc_bootmem_low(sizeof(cpumask_t) * nr_cpu_ids);
++ for (i = 0; i < nr_cpu_ids; i++)
++ cpu_set(i, cpumask_of_cpu_map[i]);
++}
++#else
++static inline void setup_cpumask_of_cpu(void) { }
++#endif
++
++#ifdef CONFIG_X86_32
++/*
++ * Great future not-so-futuristic plan: make i386 and x86_64 do it
++ * the same way
++ */
++unsigned long __per_cpu_offset[NR_CPUS] __read_mostly;
++EXPORT_SYMBOL(__per_cpu_offset);
++#endif
++
++/*
++ * Great future plan:
++ * Declare PDA itself and support (irqstack,tss,pgd) as per cpu data.
++ * Always point %gs to its beginning
++ */
++void __init setup_per_cpu_areas(void)
++{
++ int i, highest_cpu = 0;
++ unsigned long size;
++
++#ifdef CONFIG_HOTPLUG_CPU
++ prefill_possible_map();
++#endif
++
++ /* Copy section for each CPU (we discard the original) */
++ size = PERCPU_ENOUGH_ROOM;
++ printk(KERN_INFO "PERCPU: Allocating %lu bytes of per cpu data\n",
++ size);
++
++ for_each_possible_cpu(i) {
++ char *ptr;
++#ifndef CONFIG_NEED_MULTIPLE_NODES
++ ptr = alloc_bootmem_pages(size);
++#else
++ int node = early_cpu_to_node(i);
++ if (!node_online(node) || !NODE_DATA(node)) {
++ ptr = alloc_bootmem_pages(size);
++ printk(KERN_INFO
++ "cpu %d has no node or node-local memory\n", i);
++ }
++ else
++ ptr = alloc_bootmem_pages_node(NODE_DATA(node), size);
++#endif
++ if (!ptr)
++ panic("Cannot allocate cpu data for CPU %d\n", i);
++#ifdef CONFIG_X86_64
++ cpu_pda(i)->data_offset = ptr - __per_cpu_start;
++#else
++ __per_cpu_offset[i] = ptr - __per_cpu_start;
++#endif
++ memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
++
++ highest_cpu = i;
++ }
++
++ nr_cpu_ids = highest_cpu + 1;
++ printk(KERN_DEBUG "NR_CPUS: %d, nr_cpu_ids: %d\n", NR_CPUS, nr_cpu_ids);
++
++ /* Setup percpu data maps */
++ setup_per_cpu_maps();
++
++ /* Setup cpumask_of_cpu map */
++ setup_cpumask_of_cpu();
++}
++
++#endif
+diff --git a/arch/x86/kernel/setup64.c b/arch/x86/kernel/setup64.c
+index e24c456..aee0e82 100644
+--- a/arch/x86/kernel/setup64.c
++++ b/arch/x86/kernel/setup64.c
+@@ -11,6 +11,7 @@
+ #include <linux/bootmem.h>
+ #include <linux/bitops.h>
+ #include <linux/module.h>
++#include <linux/kgdb.h>
+ #include <asm/pda.h>
+ #include <asm/pgtable.h>
+ #include <asm/processor.h>
+@@ -23,6 +24,7 @@
+ #include <asm/proto.h>
+ #include <asm/sections.h>
+ #include <asm/setup.h>
++#include <asm/genapic.h>
+
+ #ifndef CONFIG_DEBUG_BOOT_PARAMS
+ struct boot_params __initdata boot_params;
+@@ -72,8 +74,8 @@ int force_personality32 = 0;
+ Control non executable heap for 32bit processes.
+ To control the stack too use noexec=off
+
+-on PROT_READ does not imply PROT_EXEC for 32bit processes
+-off PROT_READ implies PROT_EXEC (default)
++on PROT_READ does not imply PROT_EXEC for 32bit processes (default)
++off PROT_READ implies PROT_EXEC
+ */
+ static int __init nonx32_setup(char *str)
+ {
+@@ -85,83 +87,6 @@ static int __init nonx32_setup(char *str)
+ }
+ __setup("noexec32=", nonx32_setup);
+
+-/*
+- * Copy data used in early init routines from the initial arrays to the
+- * per cpu data areas. These arrays then become expendable and the
+- * *_early_ptr's are zeroed indicating that the static arrays are gone.
+- */
+-static void __init setup_per_cpu_maps(void)
+-{
+- int cpu;
+-
+- for_each_possible_cpu(cpu) {
+-#ifdef CONFIG_SMP
+- if (per_cpu_offset(cpu)) {
+-#endif
+- per_cpu(x86_cpu_to_apicid, cpu) =
+- x86_cpu_to_apicid_init[cpu];
+- per_cpu(x86_bios_cpu_apicid, cpu) =
+- x86_bios_cpu_apicid_init[cpu];
+-#ifdef CONFIG_NUMA
+- per_cpu(x86_cpu_to_node_map, cpu) =
+- x86_cpu_to_node_map_init[cpu];
+-#endif
+-#ifdef CONFIG_SMP
+- }
+- else
+- printk(KERN_NOTICE "per_cpu_offset zero for cpu %d\n",
+- cpu);
+-#endif
+- }
+-
+- /* indicate the early static arrays will soon be gone */
+- x86_cpu_to_apicid_early_ptr = NULL;
+- x86_bios_cpu_apicid_early_ptr = NULL;
+-#ifdef CONFIG_NUMA
+- x86_cpu_to_node_map_early_ptr = NULL;
+-#endif
+-}
+-
+-/*
+- * Great future plan:
+- * Declare PDA itself and support (irqstack,tss,pgd) as per cpu data.
+- * Always point %gs to its beginning
+- */
+-void __init setup_per_cpu_areas(void)
+-{
+- int i;
+- unsigned long size;
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+- prefill_possible_map();
+-#endif
+-
+- /* Copy section for each CPU (we discard the original) */
+- size = PERCPU_ENOUGH_ROOM;
+-
+- printk(KERN_INFO "PERCPU: Allocating %lu bytes of per cpu data\n", size);
+- for_each_cpu_mask (i, cpu_possible_map) {
+- char *ptr;
+-#ifndef CONFIG_NEED_MULTIPLE_NODES
+- ptr = alloc_bootmem_pages(size);
+-#else
+- int node = early_cpu_to_node(i);
+-
+- if (!node_online(node) || !NODE_DATA(node))
+- ptr = alloc_bootmem_pages(size);
+- else
+- ptr = alloc_bootmem_pages_node(NODE_DATA(node), size);
+-#endif
+- if (!ptr)
+- panic("Cannot allocate cpu data for CPU %d\n", i);
+- cpu_pda(i)->data_offset = ptr - __per_cpu_start;
+- memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
+- }
+-
+- /* setup percpu data maps early */
+- setup_per_cpu_maps();
+-}
+-
+ void pda_init(int cpu)
+ {
+ struct x8664_pda *pda = cpu_pda(cpu);
+@@ -327,6 +252,17 @@ void __cpuinit cpu_init (void)
+ load_TR_desc();
+ load_LDT(&init_mm.context);
+
++#ifdef CONFIG_KGDB
++ /*
++ * If the kgdb is connected no debug regs should be altered. This
++ * is only applicable when KGDB and a KGDB I/O module are built
++ * into the kernel and you are using early debugging with
++ * kgdbwait. KGDB will control the kernel HW breakpoint registers.
++ */
++ if (kgdb_connected && arch_kgdb_ops.correct_hw_break)
++ arch_kgdb_ops.correct_hw_break();
++ else {
++#endif
+ /*
+ * Clear all 6 debug registers:
+ */
+@@ -337,8 +273,15 @@ void __cpuinit cpu_init (void)
+ set_debugreg(0UL, 3);
+ set_debugreg(0UL, 6);
+ set_debugreg(0UL, 7);
++#ifdef CONFIG_KGDB
++ /* If the kgdb is connected no debug regs should be altered. */
++ }
++#endif
+
+ fpu_init();
+
+ raw_local_save_flags(kernel_eflags);
++
++ if (is_uv_system())
++ uv_cpu_init();
+ }
+diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c
+index 2b3e5d4..44cc9b9 100644
+--- a/arch/x86/kernel/setup_32.c
++++ b/arch/x86/kernel/setup_32.c
+@@ -39,6 +39,7 @@
+ #include <linux/efi.h>
+ #include <linux/init.h>
+ #include <linux/edd.h>
++#include <linux/iscsi_ibft.h>
+ #include <linux/nodemask.h>
+ #include <linux/kexec.h>
+ #include <linux/crash_dump.h>
+@@ -62,8 +63,9 @@
+ #include <asm/io.h>
+ #include <asm/vmi.h>
+ #include <setup_arch.h>
+-#include <bios_ebda.h>
++#include <asm/bios_ebda.h>
+ #include <asm/cacheflush.h>
++#include <asm/processor.h>
+
+ /* This value is set up by the early boot code to point to the value
+ immediately after the boot time page tables. It contains a *physical*
+@@ -154,6 +156,8 @@ struct cpuinfo_x86 new_cpu_data __cpuinitdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+ struct cpuinfo_x86 boot_cpu_data __read_mostly = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+ EXPORT_SYMBOL(boot_cpu_data);
+
++unsigned int def_to_bigsmp;
++
+ #ifndef CONFIG_X86_PAE
+ unsigned long mmu_cr4_features;
+ #else
+@@ -189,7 +193,7 @@ EXPORT_SYMBOL(ist_info);
+ extern void early_cpu_init(void);
+ extern int root_mountflags;
+
+-unsigned long saved_videomode;
++unsigned long saved_video_mode;
+
+ #define RAMDISK_IMAGE_START_MASK 0x07FF
+ #define RAMDISK_PROMPT_FLAG 0x8000
+@@ -227,7 +231,7 @@ static inline void copy_edd(void)
+ }
+ #endif
+
+-int __initdata user_defined_memmap = 0;
++int __initdata user_defined_memmap;
+
+ /*
+ * "mem=nopentium" disables the 4MB page tables.
+@@ -385,19 +389,58 @@ unsigned long __init find_max_low_pfn(void)
+ return max_low_pfn;
+ }
+
++#define BIOS_LOWMEM_KILOBYTES 0x413
++
+ /*
+- * workaround for Dell systems that neglect to reserve EBDA
++ * The BIOS places the EBDA/XBDA at the top of conventional
++ * memory, and usually decreases the reported amount of
++ * conventional memory (int 0x12) too. This also contains a
++ * workaround for Dell systems that neglect to reserve EBDA.
++ * The same workaround also avoids a problem with the AMD768MPX
++ * chipset: reserve a page before VGA to prevent PCI prefetch
++ * into it (errata #56). Usually the page is reserved anyways,
++ * unless you have no PS/2 mouse plugged in.
+ */
+ static void __init reserve_ebda_region(void)
+ {
+- unsigned int addr;
+- addr = get_bios_ebda();
+- if (addr)
+- reserve_bootmem(addr, PAGE_SIZE, BOOTMEM_DEFAULT);
++ unsigned int lowmem, ebda_addr;
++
++ /* To determine the position of the EBDA and the */
++ /* end of conventional memory, we need to look at */
++ /* the BIOS data area. In a paravirtual environment */
++ /* that area is absent. We'll just have to assume */
++ /* that the paravirt case can handle memory setup */
++ /* correctly, without our help. */
++ if (paravirt_enabled())
++ return;
++
++ /* end of low (conventional) memory */
++ lowmem = *(unsigned short *)__va(BIOS_LOWMEM_KILOBYTES);
++ lowmem <<= 10;
++
++ /* start of EBDA area */
++ ebda_addr = get_bios_ebda();
++
++ /* Fixup: bios puts an EBDA in the top 64K segment */
++ /* of conventional memory, but does not adjust lowmem. */
++ if ((lowmem - ebda_addr) <= 0x10000)
++ lowmem = ebda_addr;
++
++ /* Fixup: bios does not report an EBDA at all. */
++ /* Some old Dells seem to need 4k anyhow (bugzilla 2990) */
++ if ((ebda_addr == 0) && (lowmem >= 0x9f000))
++ lowmem = 0x9f000;
++
++ /* Paranoia: should never happen, but... */
++ if ((lowmem == 0) || (lowmem >= 0x100000))
++ lowmem = 0x9f000;
++
++ /* reserve all memory between lowmem and the 1MB mark */
++ reserve_bootmem(lowmem, 0x100000 - lowmem, BOOTMEM_DEFAULT);
+ }
+
+ #ifndef CONFIG_NEED_MULTIPLE_NODES
+-void __init setup_bootmem_allocator(void);
++static void __init setup_bootmem_allocator(void);
+ static unsigned long __init setup_memory(void)
+ {
+ /*
+@@ -432,7 +475,7 @@ static unsigned long __init setup_memory(void)
+ return max_low_pfn;
+ }
+
+-void __init zone_sizes_init(void)
++static void __init zone_sizes_init(void)
+ {
+ unsigned long max_zone_pfns[MAX_NR_ZONES];
+ memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+@@ -617,16 +660,9 @@ void __init setup_bootmem_allocator(void)
+ */
+ reserve_bootmem(0, PAGE_SIZE, BOOTMEM_DEFAULT);
+
+- /* reserve EBDA region, it's a 4K region */
++ /* reserve EBDA region */
+ reserve_ebda_region();
+
+- /* could be an AMD 768MPX chipset. Reserve a page before VGA to prevent
+- PCI prefetch into it (errata #56). Usually the page is reserved anyways,
+- unless you have no PS/2 mouse plugged in. */
+- if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+- boot_cpu_data.x86 == 6)
+- reserve_bootmem(0xa0000 - 4096, 4096, BOOTMEM_DEFAULT);
+-
+ #ifdef CONFIG_SMP
+ /*
+ * But first pinch a few for the stack/trampoline stuff
+@@ -652,6 +688,8 @@ void __init setup_bootmem_allocator(void)
+ #endif
+ numa_kva_reserve();
+ reserve_crashkernel();
++
++ reserve_ibft_region();
+ }
+
+ /*
+@@ -687,6 +725,18 @@ char * __init __attribute__((weak)) memory_setup(void)
+ return machine_specific_memory_setup();
+ }
+
++#ifdef CONFIG_NUMA
++/*
++ * In the golden day, when everything among i386 and x86_64 will be
++ * integrated, this will not live here
++ */
++void *x86_cpu_to_node_map_early_ptr;
++int x86_cpu_to_node_map_init[NR_CPUS] = {
++ [0 ... NR_CPUS-1] = NUMA_NO_NODE
++};
++DEFINE_PER_CPU(int, x86_cpu_to_node_map) = NUMA_NO_NODE;
++#endif
++
+ /*
+ * Determine if we were loaded by an EFI loader. If so, then we have also been
+ * passed the efi memmap, systab, etc., so we should use these data structures
+@@ -714,7 +764,7 @@ void __init setup_arch(char **cmdline_p)
+ edid_info = boot_params.edid_info;
+ apm_info.bios = boot_params.apm_bios_info;
+ ist_info = boot_params.ist_info;
+- saved_videomode = boot_params.hdr.vid_mode;
++ saved_video_mode = boot_params.hdr.vid_mode;
+ if( boot_params.sys_desc_table.length != 0 ) {
+ set_mca_bus(boot_params.sys_desc_table.table[3] & 0x2);
+ machine_id = boot_params.sys_desc_table.table[0];
+@@ -763,10 +813,10 @@ void __init setup_arch(char **cmdline_p)
+ efi_init();
+
+ /* update e820 for memory not covered by WB MTRRs */
+- find_max_pfn();
++ propagate_e820_map();
+ mtrr_bp_init();
+ if (mtrr_trim_uncached_memory(max_pfn))
+- find_max_pfn();
++ propagate_e820_map();
+
+ max_low_pfn = setup_memory();
+
+@@ -820,6 +870,18 @@ void __init setup_arch(char **cmdline_p)
+
+ io_delay_init();
+
++#ifdef CONFIG_X86_SMP
++ /*
++ * setup to use the early static init tables during kernel startup
++ * X86_SMP will exclude sub-arches that don't deal well with it.
++ */
++ x86_cpu_to_apicid_early_ptr = (void *)x86_cpu_to_apicid_init;
++ x86_bios_cpu_apicid_early_ptr = (void *)x86_bios_cpu_apicid_init;
++#ifdef CONFIG_NUMA
++ x86_cpu_to_node_map_early_ptr = (void *)x86_cpu_to_node_map_init;
++#endif
++#endif
++
+ #ifdef CONFIG_X86_GENERICARCH
+ generic_apic_probe();
+ #endif
+diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c
+index f4f7ecf..17bdf23 100644
+--- a/arch/x86/kernel/setup_64.c
++++ b/arch/x86/kernel/setup_64.c
+@@ -33,6 +33,7 @@
+ #include <linux/acpi.h>
+ #include <linux/kallsyms.h>
+ #include <linux/edd.h>
++#include <linux/iscsi_ibft.h>
+ #include <linux/mmzone.h>
+ #include <linux/kexec.h>
+ #include <linux/cpufreq.h>
+@@ -58,7 +59,6 @@
+ #include <asm/mmu_context.h>
+ #include <asm/proto.h>
+ #include <asm/setup.h>
+-#include <asm/mach_apic.h>
+ #include <asm/numa.h>
+ #include <asm/sections.h>
+ #include <asm/dmi.h>
+@@ -66,7 +66,9 @@
+ #include <asm/mce.h>
+ #include <asm/ds.h>
+ #include <asm/topology.h>
++#include <asm/trampoline.h>
+
++#include <mach_apic.h>
+ #ifdef CONFIG_PARAVIRT
+ #include <asm/paravirt.h>
+ #else
+@@ -114,7 +116,7 @@ extern int root_mountflags;
+
+ char __initdata command_line[COMMAND_LINE_SIZE];
+
+-struct resource standard_io_resources[] = {
++static struct resource standard_io_resources[] = {
+ { .name = "dma1", .start = 0x00, .end = 0x1f,
+ .flags = IORESOURCE_BUSY | IORESOURCE_IO },
+ { .name = "pic1", .start = 0x20, .end = 0x21,
+@@ -248,6 +250,7 @@ static void __init reserve_crashkernel(void)
+ (unsigned long)(total_mem >> 20));
+ crashk_res.start = crash_base;
+ crashk_res.end = crash_base + crash_size - 1;
++ insert_resource(&iomem_resource, &crashk_res);
+ }
+ }
+ #else
+@@ -322,6 +325,11 @@ void __init setup_arch(char **cmdline_p)
+
+ finish_e820_parsing();
+
++ /* after parse_early_param, so could debug it */
++ insert_resource(&iomem_resource, &code_resource);
++ insert_resource(&iomem_resource, &data_resource);
++ insert_resource(&iomem_resource, &bss_resource);
++
+ early_gart_iommu_check();
+
+ e820_register_active_regions(0, 0, -1UL);
+@@ -341,10 +349,12 @@ void __init setup_arch(char **cmdline_p)
+
+ check_efer();
+
+- init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT));
++ max_pfn_mapped = init_memory_mapping(0, (max_pfn_mapped << PAGE_SHIFT));
+ if (efi_enabled)
+ efi_init();
+
++ vsmp_init();
++
+ dmi_scan_machine();
+
+ io_delay_init();
+@@ -389,6 +399,8 @@ void __init setup_arch(char **cmdline_p)
+
+ early_res_to_bootmem();
+
++ dma32_reserve_bootmem();
++
+ #ifdef CONFIG_ACPI_SLEEP
+ /*
+ * Reserve low memory region for sleep support.
+@@ -411,11 +423,14 @@ void __init setup_arch(char **cmdline_p)
+ unsigned long end_of_mem = end_pfn << PAGE_SHIFT;
+
+ if (ramdisk_end <= end_of_mem) {
+- reserve_bootmem_generic(ramdisk_image, ramdisk_size);
++ /*
++ * don't need to reserve again, already reserved early
++ * in x86_64_start_kernel, and early_res_to_bootmem
++ * convert that to reserved in bootmem
++ */
+ initrd_start = ramdisk_image + PAGE_OFFSET;
+ initrd_end = initrd_start+ramdisk_size;
+ } else {
+- /* Assumes everything on node 0 */
+ free_bootmem(ramdisk_image, ramdisk_size);
+ printk(KERN_ERR "initrd extends beyond end of memory "
+ "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+@@ -425,6 +440,9 @@ void __init setup_arch(char **cmdline_p)
+ }
+ #endif
+ reserve_crashkernel();
++
++ reserve_ibft_region();
++
+ paging_init();
+ map_vsyscall();
+
+@@ -450,7 +468,7 @@ void __init setup_arch(char **cmdline_p)
+ /*
+ * We trust e820 completely. No explicit ROM probing in memory.
+ */
+- e820_reserve_resources(&code_resource, &data_resource, &bss_resource);
++ e820_reserve_resources();
+ e820_mark_nosave_regions();
+
+ /* request I/O space for devices used on all i[345]86 PCs */
+@@ -552,9 +570,9 @@ static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c)
+ bits = c->x86_coreid_bits;
+
+ /* Low order bits define the core id (index of core in socket) */
+- c->cpu_core_id = c->phys_proc_id & ((1 << bits)-1);
+- /* Convert the APIC ID into the socket ID */
+- c->phys_proc_id = phys_pkg_id(bits);
++ c->cpu_core_id = c->initial_apicid & ((1 << bits)-1);
++ /* Convert the initial APIC ID into the socket ID */
++ c->phys_proc_id = c->initial_apicid >> bits;
+
+ #ifdef CONFIG_NUMA
+ node = c->phys_proc_id;
+@@ -571,7 +589,7 @@ static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c)
+ If that doesn't result in a usable node fall back to the
+ path for the previous case. */
+
+- int ht_nodeid = apicid - (cpu_data(0).phys_proc_id << bits);
++ int ht_nodeid = c->initial_apicid;
+
+ if (ht_nodeid >= 0 &&
+ apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
+@@ -677,7 +695,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+
+ /* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
+ 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
+- clear_bit(0*32+31, (unsigned long *)&c->x86_capability);
++ clear_cpu_cap(c, 0*32+31);
+
+ /* On C+ stepping K8 rep microcode works well for copy/memset */
+ level = cpuid_eax(1);
+@@ -721,6 +739,19 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+
+ if (amd_apic_timer_broken())
+ disable_apic_timer = 1;
++
++ if (c == &boot_cpu_data && c->x86 >= 0xf && c->x86 <= 0x11) {
++ unsigned long long tseg;
++
++ /*
++ * Split up direct mapping around the TSEG SMM area.
++ * Don't do it for gbpages because there seems very little
++ * benefit in doing so.
++ */
++ if (!rdmsrl_safe(MSR_K8_TSEG_ADDR, &tseg) &&
++ (tseg >> PMD_SHIFT) < (max_pfn_mapped >> (PMD_SHIFT-PAGE_SHIFT)))
++ set_memory_4k((unsigned long)__va(tseg), 1);
++ }
+ }
+
+ void __cpuinit detect_ht(struct cpuinfo_x86 *c)
+@@ -813,7 +844,7 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
+ {
+ if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
+ (c->x86 == 0x6 && c->x86_model >= 0x0e))
+- set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
++ set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
+ }
+
+ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+@@ -856,9 +887,6 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+
+ if (c->x86 == 15)
+ c->x86_cache_alignment = c->x86_clflush_size * 2;
+- if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
+- (c->x86 == 0x6 && c->x86_model >= 0x0e))
+- set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
+ if (c->x86 == 6)
+ set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+ set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
+@@ -867,6 +895,32 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+ srat_detect_node();
+ }
+
++static void __cpuinit early_init_centaur(struct cpuinfo_x86 *c)
++{
++ if (c->x86 == 0x6 && c->x86_model >= 0xf)
++ set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
++}
++
++static void __cpuinit init_centaur(struct cpuinfo_x86 *c)
++{
++ /* Cache sizes */
++ unsigned n;
++
++ n = c->extended_cpuid_level;
++ if (n >= 0x80000008) {
++ unsigned eax = cpuid_eax(0x80000008);
++ c->x86_virt_bits = (eax >> 8) & 0xff;
++ c->x86_phys_bits = eax & 0xff;
++ }
++
++ if (c->x86 == 0x6 && c->x86_model >= 0xf) {
++ c->x86_cache_alignment = c->x86_clflush_size * 2;
++ set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
++ set_cpu_cap(c, X86_FEATURE_REP_GOOD);
++ }
++ set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
++}
++
+ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
+ {
+ char *v = c->x86_vendor_id;
+@@ -875,6 +929,8 @@ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
+ c->x86_vendor = X86_VENDOR_AMD;
+ else if (!strcmp(v, "GenuineIntel"))
+ c->x86_vendor = X86_VENDOR_INTEL;
++ else if (!strcmp(v, "CentaurHauls"))
++ c->x86_vendor = X86_VENDOR_CENTAUR;
+ else
+ c->x86_vendor = X86_VENDOR_UNKNOWN;
+ }
+@@ -922,15 +978,16 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
+ c->x86 += (tfms >> 20) & 0xff;
+ if (c->x86 >= 0x6)
+ c->x86_model += ((tfms >> 16) & 0xF) << 4;
+- if (c->x86_capability[0] & (1<<19))
++ if (test_cpu_cap(c, X86_FEATURE_CLFLSH))
+ c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
+ } else {
+ /* Have CPUID level 0 only - unheard of */
+ c->x86 = 4;
+ }
+
++ c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xff;
+ #ifdef CONFIG_SMP
+- c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff;
++ c->phys_proc_id = c->initial_apicid;
+ #endif
+ /* AMD-defined flags: level 0x80000001 */
+ xlvl = cpuid_eax(0x80000000);
+@@ -956,12 +1013,22 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
+ if (c->extended_cpuid_level >= 0x80000007)
+ c->x86_power = cpuid_edx(0x80000007);
+
++
++ clear_cpu_cap(c, X86_FEATURE_PAT);
++
+ switch (c->x86_vendor) {
+ case X86_VENDOR_AMD:
+ early_init_amd(c);
++ if (c->x86 >= 0xf && c->x86 <= 0x11)
++ set_cpu_cap(c, X86_FEATURE_PAT);
+ break;
+ case X86_VENDOR_INTEL:
+ early_init_intel(c);
++ if (c->x86 == 0xF || (c->x86 == 6 && c->x86_model >= 15))
++ set_cpu_cap(c, X86_FEATURE_PAT);
++ break;
++ case X86_VENDOR_CENTAUR:
++ early_init_centaur(c);
+ break;
+ }
+
+@@ -999,6 +1066,10 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
+ init_intel(c);
+ break;
+
++ case X86_VENDOR_CENTAUR:
++ init_centaur(c);
++ break;
++
+ case X86_VENDOR_UNKNOWN:
+ default:
+ display_cacheinfo(c);
+@@ -1028,14 +1099,24 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
+ #endif
+ select_idle_routine(c);
+
+- if (c != &boot_cpu_data)
+- mtrr_ap_init();
+ #ifdef CONFIG_NUMA
+ numa_add_cpu(smp_processor_id());
+ #endif
+
+ }
+
++void __cpuinit identify_boot_cpu(void)
++{
++ identify_cpu(&boot_cpu_data);
++}
++
++void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
++{
++ BUG_ON(c == &boot_cpu_data);
++ identify_cpu(c);
++ mtrr_ap_init();
++}
++
+ static __init int setup_noclflush(char *arg)
+ {
+ setup_clear_cpu_cap(X86_FEATURE_CLFLSH);
+@@ -1064,123 +1145,3 @@ static __init int setup_disablecpuid(char *arg)
+ return 1;
+ }
+ __setup("clearcpuid=", setup_disablecpuid);
+-
+-/*
+- * Get CPU information for use by the procfs.
+- */
+-
+-static int show_cpuinfo(struct seq_file *m, void *v)
+-{
+- struct cpuinfo_x86 *c = v;
+- int cpu = 0, i;
+-
+-#ifdef CONFIG_SMP
+- cpu = c->cpu_index;
+-#endif
+-
+- seq_printf(m, "processor\t: %u\n"
+- "vendor_id\t: %s\n"
+- "cpu family\t: %d\n"
+- "model\t\t: %d\n"
+- "model name\t: %s\n",
+- (unsigned)cpu,
+- c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
+- c->x86,
+- (int)c->x86_model,
+- c->x86_model_id[0] ? c->x86_model_id : "unknown");
+-
+- if (c->x86_mask || c->cpuid_level >= 0)
+- seq_printf(m, "stepping\t: %d\n", c->x86_mask);
+- else
+- seq_printf(m, "stepping\t: unknown\n");
+-
+- if (cpu_has(c, X86_FEATURE_TSC)) {
+- unsigned int freq = cpufreq_quick_get((unsigned)cpu);
+-
+- if (!freq)
+- freq = cpu_khz;
+- seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
+- freq / 1000, (freq % 1000));
+- }
+-
+- /* Cache size */
+- if (c->x86_cache_size >= 0)
+- seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
+-
+-#ifdef CONFIG_SMP
+- if (smp_num_siblings * c->x86_max_cores > 1) {
+- seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
+- seq_printf(m, "siblings\t: %d\n",
+- cpus_weight(per_cpu(cpu_core_map, cpu)));
+- seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
+- seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
+- }
+-#endif
+-
+- seq_printf(m,
+- "fpu\t\t: yes\n"
+- "fpu_exception\t: yes\n"
+- "cpuid level\t: %d\n"
+- "wp\t\t: yes\n"
+- "flags\t\t:",
+- c->cpuid_level);
+-
+- for (i = 0; i < 32*NCAPINTS; i++)
+- if (cpu_has(c, i) && x86_cap_flags[i] != NULL)
+- seq_printf(m, " %s", x86_cap_flags[i]);
+-
+- seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
+- c->loops_per_jiffy/(500000/HZ),
+- (c->loops_per_jiffy/(5000/HZ)) % 100);
+-
+- if (c->x86_tlbsize > 0)
+- seq_printf(m, "TLB size\t: %d 4K pages\n", c->x86_tlbsize);
+- seq_printf(m, "clflush size\t: %d\n", c->x86_clflush_size);
+- seq_printf(m, "cache_alignment\t: %d\n", c->x86_cache_alignment);
+-
+- seq_printf(m, "address sizes\t: %u bits physical, %u bits virtual\n",
+- c->x86_phys_bits, c->x86_virt_bits);
+-
+- seq_printf(m, "power management:");
+- for (i = 0; i < 32; i++) {
+- if (c->x86_power & (1 << i)) {
+- if (i < ARRAY_SIZE(x86_power_flags) &&
+- x86_power_flags[i])
+- seq_printf(m, "%s%s",
+- x86_power_flags[i][0]?" ":"",
+- x86_power_flags[i]);
+- else
+- seq_printf(m, " [%d]", i);
+- }
+- }
+-
+- seq_printf(m, "\n\n");
+-
+- return 0;
+-}
+-
+-static void *c_start(struct seq_file *m, loff_t *pos)
+-{
+- if (*pos == 0) /* just in case, cpu 0 is not the first */
+- *pos = first_cpu(cpu_online_map);
+- if ((*pos) < NR_CPUS && cpu_online(*pos))
+- return &cpu_data(*pos);
+- return NULL;
+-}
+-
+-static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+-{
+- *pos = next_cpu(*pos, cpu_online_map);
+- return c_start(m, pos);
+-}
+-
+-static void c_stop(struct seq_file *m, void *v)
+-{
+-}
+-
+-const struct seq_operations cpuinfo_op = {
+- .start = c_start,
+- .next = c_next,
+- .stop = c_stop,
+- .show = show_cpuinfo,
+-};
+diff --git a/arch/x86/kernel/sigframe.h b/arch/x86/kernel/sigframe.h
+new file mode 100644
+index 0000000..72bbb51
+--- /dev/null
++++ b/arch/x86/kernel/sigframe.h
+@@ -0,0 +1,27 @@
++#ifdef CONFIG_X86_32
++struct sigframe {
++ char __user *pretcode;
++ int sig;
++ struct sigcontext sc;
++ struct _fpstate fpstate;
++ unsigned long extramask[_NSIG_WORDS-1];
++ char retcode[8];
++};
++
++struct rt_sigframe {
++ char __user *pretcode;
++ int sig;
++ struct siginfo __user *pinfo;
++ void __user *puc;
++ struct siginfo info;
++ struct ucontext uc;
++ struct _fpstate fpstate;
++ char retcode[8];
++};
++#else
++struct rt_sigframe {
++ char __user *pretcode;
++ struct ucontext uc;
++ struct siginfo info;
++};
++#endif
+diff --git a/arch/x86/kernel/sigframe_32.h b/arch/x86/kernel/sigframe_32.h
+deleted file mode 100644
+index 0b22217..0000000
+--- a/arch/x86/kernel/sigframe_32.h
++++ /dev/null
+@@ -1,21 +0,0 @@
+-struct sigframe
+-{
+- char __user *pretcode;
+- int sig;
+- struct sigcontext sc;
+- struct _fpstate fpstate;
+- unsigned long extramask[_NSIG_WORDS-1];
+- char retcode[8];
+-};
+-
+-struct rt_sigframe
+-{
+- char __user *pretcode;
+- int sig;
+- struct siginfo __user *pinfo;
+- void __user *puc;
+- struct siginfo info;
+- struct ucontext uc;
+- struct _fpstate fpstate;
+- char retcode[8];
+-};
+diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c
+index 0157a6f..8e05e7f 100644
+--- a/arch/x86/kernel/signal_32.c
++++ b/arch/x86/kernel/signal_32.c
+@@ -4,32 +4,44 @@
+ * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
+ * 2000-06-20 Pentium III FXSR, SSE support by Gareth Hughes
+ */
++#include <linux/list.h>
+
+-#include <linux/sched.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
++#include <linux/personality.h>
++#include <linux/binfmts.h>
++#include <linux/suspend.h>
+ #include <linux/kernel.h>
++#include <linux/ptrace.h>
+ #include <linux/signal.h>
++#include <linux/stddef.h>
++#include <linux/unistd.h>
+ #include <linux/errno.h>
++#include <linux/sched.h>
+ #include <linux/wait.h>
+-#include <linux/unistd.h>
+-#include <linux/stddef.h>
+-#include <linux/personality.h>
+-#include <linux/suspend.h>
+-#include <linux/ptrace.h>
+ #include <linux/elf.h>
+-#include <linux/binfmts.h>
++#include <linux/smp.h>
++#include <linux/mm.h>
++
+ #include <asm/processor.h>
+ #include <asm/ucontext.h>
+ #include <asm/uaccess.h>
+ #include <asm/i387.h>
+ #include <asm/vdso.h>
+-#include "sigframe_32.h"
+
+-#define DEBUG_SIG 0
++#include "sigframe.h"
+
+ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
++#define __FIX_EFLAGS (X86_EFLAGS_AC | X86_EFLAGS_OF | \
++ X86_EFLAGS_DF | X86_EFLAGS_TF | X86_EFLAGS_SF | \
++ X86_EFLAGS_ZF | X86_EFLAGS_AF | X86_EFLAGS_PF | \
++ X86_EFLAGS_CF)
++
++#ifdef CONFIG_X86_32
++# define FIX_EFLAGS (__FIX_EFLAGS | X86_EFLAGS_RF)
++#else
++# define FIX_EFLAGS __FIX_EFLAGS
++#endif
++
+ /*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+@@ -46,10 +58,11 @@ sys_sigsuspend(int history0, int history1, old_sigset_t mask)
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ set_thread_flag(TIF_RESTORE_SIGMASK);
++
+ return -ERESTARTNOHAND;
+ }
+
+-asmlinkage int
++asmlinkage int
+ sys_sigaction(int sig, const struct old_sigaction __user *act,
+ struct old_sigaction __user *oact)
+ {
+@@ -58,10 +71,12 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
+
+ if (act) {
+ old_sigset_t mask;
++
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
+ __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
+ __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
+ return -EFAULT;
++
+ __get_user(new_ka.sa.sa_flags, &act->sa_flags);
+ __get_user(mask, &act->sa_mask);
+ siginitset(&new_ka.sa.sa_mask, mask);
+@@ -74,6 +89,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
+ __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+ __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+ return -EFAULT;
++
+ __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+ __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+ }
+@@ -81,10 +97,12 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
+ return ret;
+ }
+
+-asmlinkage int
+-sys_sigaltstack(unsigned long bx)
++asmlinkage int sys_sigaltstack(unsigned long bx)
+ {
+- /* This is needed to make gcc realize it doesn't own the "struct pt_regs" */
++ /*
++ * This is needed to make gcc realize it doesn't own the
++ * "struct pt_regs"
++ */
+ struct pt_regs *regs = (struct pt_regs *)&bx;
+ const stack_t __user *uss = (const stack_t __user *)bx;
+ stack_t __user *uoss = (stack_t __user *)regs->cx;
+@@ -96,9 +114,9 @@ sys_sigaltstack(unsigned long bx)
+ /*
+ * Do a signal return; undo the signal stack.
+ */
+-
+ static int
+-restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax)
++restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
++ unsigned long *pax)
+ {
+ unsigned int err = 0;
+
+@@ -120,37 +138,29 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax
+ #define GET_SEG(seg) \
+ { unsigned short tmp; \
+ err |= __get_user(tmp, &sc->seg); \
+- loadsegment(seg,tmp); }
+-
+-#define FIX_EFLAGS (X86_EFLAGS_AC | X86_EFLAGS_RF | \
+- X86_EFLAGS_OF | X86_EFLAGS_DF | \
+- X86_EFLAGS_TF | X86_EFLAGS_SF | X86_EFLAGS_ZF | \
+- X86_EFLAGS_AF | X86_EFLAGS_PF | X86_EFLAGS_CF)
++ loadsegment(seg, tmp); }
+
+ GET_SEG(gs);
+ COPY_SEG(fs);
+ COPY_SEG(es);
+ COPY_SEG(ds);
+- COPY(di);
+- COPY(si);
+- COPY(bp);
+- COPY(sp);
+- COPY(bx);
+- COPY(dx);
+- COPY(cx);
+- COPY(ip);
++ COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
++ COPY(dx); COPY(cx); COPY(ip);
+ COPY_SEG_STRICT(cs);
+ COPY_SEG_STRICT(ss);
+-
++
+ {
+ unsigned int tmpflags;
++
+ err |= __get_user(tmpflags, &sc->flags);
+- regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
++ regs->flags = (regs->flags & ~FIX_EFLAGS) |
++ (tmpflags & FIX_EFLAGS);
+ regs->orig_ax = -1; /* disable syscall checks */
+ }
+
+ {
+- struct _fpstate __user * buf;
++ struct _fpstate __user *buf;
++
+ err |= __get_user(buf, &sc->fpstate);
+ if (buf) {
+ if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))
+@@ -158,6 +168,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax
+ err |= restore_i387(buf);
+ } else {
+ struct task_struct *me = current;
++
+ if (used_math()) {
+ clear_fpu(me);
+ clear_used_math();
+@@ -165,24 +176,26 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax
+ }
+ }
+
+- err |= __get_user(*peax, &sc->ax);
++ err |= __get_user(*pax, &sc->ax);
+ return err;
+
+ badframe:
+ return 1;
+ }
+
+-asmlinkage int sys_sigreturn(unsigned long __unused)
++asmlinkage unsigned long sys_sigreturn(unsigned long __unused)
+ {
+- struct pt_regs *regs = (struct pt_regs *) &__unused;
+- struct sigframe __user *frame = (struct sigframe __user *)(regs->sp - 8);
++ struct sigframe __user *frame;
++ struct pt_regs *regs;
++ unsigned long ax;
+ sigset_t set;
+- int ax;
++
++ regs = (struct pt_regs *) &__unused;
++ frame = (struct sigframe __user *)(regs->sp - 8);
+
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+- if (__get_user(set.sig[0], &frame->sc.oldmask)
+- || (_NSIG_WORDS > 1
++ if (__get_user(set.sig[0], &frame->sc.oldmask) || (_NSIG_WORDS > 1
+ && __copy_from_user(&set.sig[1], &frame->extramask,
+ sizeof(frame->extramask))))
+ goto badframe;
+@@ -192,33 +205,35 @@ asmlinkage int sys_sigreturn(unsigned long __unused)
+ current->blocked = set;
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+-
++
+ if (restore_sigcontext(regs, &frame->sc, &ax))
+ goto badframe;
+ return ax;
+
+ badframe:
+ if (show_unhandled_signals && printk_ratelimit()) {
+- printk("%s%s[%d] bad frame in sigreturn frame:%p ip:%lx"
+- " sp:%lx oeax:%lx",
++ printk(KERN_INFO "%s%s[%d] bad frame in sigreturn frame:"
++ "%p ip:%lx sp:%lx oeax:%lx",
+ task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG,
+ current->comm, task_pid_nr(current), frame, regs->ip,
+ regs->sp, regs->orig_ax);
+ print_vma_addr(" in ", regs->ip);
+- printk("\n");
++ printk(KERN_CONT "\n");
+ }
+
+ force_sig(SIGSEGV, current);
++
+ return 0;
+-}
++}
+
+ asmlinkage int sys_rt_sigreturn(unsigned long __unused)
+ {
+- struct pt_regs *regs = (struct pt_regs *) &__unused;
+- struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(regs->sp - 4);
++ struct pt_regs *regs = (struct pt_regs *)&__unused;
++ struct rt_sigframe __user *frame;
++ unsigned long ax;
+ sigset_t set;
+- int ax;
+
++ frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long));
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+@@ -229,7 +244,7 @@ asmlinkage int sys_rt_sigreturn(unsigned long __unused)
+ current->blocked = set;
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+-
++
+ if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
+ goto badframe;
+
+@@ -241,12 +256,11 @@ asmlinkage int sys_rt_sigreturn(unsigned long __unused)
+ badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+-}
++}
+
+ /*
+ * Set up a signal frame.
+ */
+-
+ static int
+ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate,
+ struct pt_regs *regs, unsigned long mask)
+@@ -277,9 +291,9 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate,
+
+ tmp = save_i387(fpstate);
+ if (tmp < 0)
+- err = 1;
++ err = 1;
+ else
+- err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate);
++ err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate);
+
+ /* non-iBCS2 extensions.. */
+ err |= __put_user(mask, &sc->oldmask);
+@@ -292,7 +306,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate,
+ * Determine which stack to use..
+ */
+ static inline void __user *
+-get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
++get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
+ {
+ unsigned long sp;
+
+@@ -310,32 +324,30 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
+ if (ka->sa.sa_flags & SA_ONSTACK) {
+ if (sas_ss_flags(sp) == 0)
+ sp = current->sas_ss_sp + current->sas_ss_size;
+- }
+-
+- /* This is the legacy signal stack switching. */
+- else if ((regs->ss & 0xffff) != __USER_DS &&
+- !(ka->sa.sa_flags & SA_RESTORER) &&
+- ka->sa.sa_restorer) {
+- sp = (unsigned long) ka->sa.sa_restorer;
++ } else {
++ /* This is the legacy signal stack switching. */
++ if ((regs->ss & 0xffff) != __USER_DS &&
++ !(ka->sa.sa_flags & SA_RESTORER) &&
++ ka->sa.sa_restorer)
++ sp = (unsigned long) ka->sa.sa_restorer;
+ }
+
+ sp -= frame_size;
+- /* Align the stack pointer according to the i386 ABI,
+- * i.e. so that on function entry ((sp + 4) & 15) == 0. */
++ /*
++ * Align the stack pointer according to the i386 ABI,
++ * i.e. so that on function entry ((sp + 4) & 15) == 0.
++ */
+ sp = ((sp + 4) & -16ul) - 4;
++
+ return (void __user *) sp;
+ }
+
+-/* These symbols are defined with the addresses in the vsyscall page.
+- See vsyscall-sigreturn.S. */
+-extern void __user __kernel_sigreturn;
+-extern void __user __kernel_rt_sigreturn;
+-
+-static int setup_frame(int sig, struct k_sigaction *ka,
+- sigset_t *set, struct pt_regs * regs)
++static int
++setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
++ struct pt_regs *regs)
+ {
+- void __user *restorer;
+ struct sigframe __user *frame;
++ void __user *restorer;
+ int err = 0;
+ int usig;
+
+@@ -365,7 +377,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
+ goto give_sigsegv;
+ }
+
+- if (current->binfmt->hasvdso)
++ if (current->mm->context.vdso)
+ restorer = VDSO32_SYMBOL(current->mm->context.vdso, sigreturn);
+ else
+ restorer = &frame->retcode;
+@@ -374,9 +386,9 @@ static int setup_frame(int sig, struct k_sigaction *ka,
+
+ /* Set up to return from userspace. */
+ err |= __put_user(restorer, &frame->pretcode);
+-
++
+ /*
+- * This is popl %eax ; movl $,%eax ; int $0x80
++ * This is popl %eax ; movl $__NR_sigreturn, %eax ; int $0x80
+ *
+ * WE DO NOT USE IT ANY MORE! It's only left here for historical
+ * reasons and because gdb uses it as a signature to notice
+@@ -390,32 +402,17 @@ static int setup_frame(int sig, struct k_sigaction *ka,
+ goto give_sigsegv;
+
+ /* Set up registers for signal handler */
+- regs->sp = (unsigned long) frame;
+- regs->ip = (unsigned long) ka->sa.sa_handler;
+- regs->ax = (unsigned long) sig;
+- regs->dx = (unsigned long) 0;
+- regs->cx = (unsigned long) 0;
++ regs->sp = (unsigned long)frame;
++ regs->ip = (unsigned long)ka->sa.sa_handler;
++ regs->ax = (unsigned long)sig;
++ regs->dx = 0;
++ regs->cx = 0;
+
+ regs->ds = __USER_DS;
+ regs->es = __USER_DS;
+ regs->ss = __USER_DS;
+ regs->cs = __USER_CS;
+
+- /*
+- * Clear TF when entering the signal handler, but
+- * notify any tracer that was single-stepping it.
+- * The tracer may want to single-step inside the
+- * handler too.
+- */
+- regs->flags &= ~(TF_MASK | X86_EFLAGS_DF);
+- if (test_thread_flag(TIF_SINGLESTEP))
+- ptrace_notify(SIGTRAP);
+-
+-#if DEBUG_SIG
+- printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
+- current->comm, current->pid, frame, regs->ip, frame->pretcode);
+-#endif
+-
+ return 0;
+
+ give_sigsegv:
+@@ -424,10 +421,10 @@ give_sigsegv:
+ }
+
+ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+- sigset_t *set, struct pt_regs * regs)
++ sigset_t *set, struct pt_regs *regs)
+ {
+- void __user *restorer;
+ struct rt_sigframe __user *frame;
++ void __user *restorer;
+ int err = 0;
+ int usig;
+
+@@ -457,7 +454,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ &frame->uc.uc_stack.ss_flags);
+ err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+ err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate,
+- regs, set->sig[0]);
++ regs, set->sig[0]);
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+ if (err)
+ goto give_sigsegv;
+@@ -467,9 +464,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ if (ka->sa.sa_flags & SA_RESTORER)
+ restorer = ka->sa.sa_restorer;
+ err |= __put_user(restorer, &frame->pretcode);
+-
++
+ /*
+- * This is movl $,%ax ; int $0x80
++ * This is movl $__NR_rt_sigreturn, %ax ; int $0x80
+ *
+ * WE DO NOT USE IT ANY MORE! It's only left here for historical
+ * reasons and because gdb uses it as a signature to notice
+@@ -483,32 +480,17 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ goto give_sigsegv;
+
+ /* Set up registers for signal handler */
+- regs->sp = (unsigned long) frame;
+- regs->ip = (unsigned long) ka->sa.sa_handler;
+- regs->ax = (unsigned long) usig;
+- regs->dx = (unsigned long) &frame->info;
+- regs->cx = (unsigned long) &frame->uc;
++ regs->sp = (unsigned long)frame;
++ regs->ip = (unsigned long)ka->sa.sa_handler;
++ regs->ax = (unsigned long)usig;
++ regs->dx = (unsigned long)&frame->info;
++ regs->cx = (unsigned long)&frame->uc;
+
+ regs->ds = __USER_DS;
+ regs->es = __USER_DS;
+ regs->ss = __USER_DS;
+ regs->cs = __USER_CS;
+
+- /*
+- * Clear TF when entering the signal handler, but
+- * notify any tracer that was single-stepping it.
+- * The tracer may want to single-step inside the
+- * handler too.
+- */
+- regs->flags &= ~(TF_MASK | X86_EFLAGS_DF);
+- if (test_thread_flag(TIF_SINGLESTEP))
+- ptrace_notify(SIGTRAP);
+-
+-#if DEBUG_SIG
+- printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
+- current->comm, current->pid, frame, regs->ip, frame->pretcode);
+-#endif
+-
+ return 0;
+
+ give_sigsegv:
+@@ -517,33 +499,33 @@ give_sigsegv:
+ }
+
+ /*
+- * OK, we're invoking a handler
+- */
+-
++ * OK, we're invoking a handler:
++ */
+ static int
+ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
+- sigset_t *oldset, struct pt_regs * regs)
++ sigset_t *oldset, struct pt_regs *regs)
+ {
+ int ret;
+
+ /* Are we from a system call? */
+- if (regs->orig_ax >= 0) {
++ if ((long)regs->orig_ax >= 0) {
+ /* If so, check system call restarting.. */
+ switch (regs->ax) {
+- case -ERESTART_RESTARTBLOCK:
+- case -ERESTARTNOHAND:
++ case -ERESTART_RESTARTBLOCK:
++ case -ERESTARTNOHAND:
++ regs->ax = -EINTR;
++ break;
++
++ case -ERESTARTSYS:
++ if (!(ka->sa.sa_flags & SA_RESTART)) {
+ regs->ax = -EINTR;
+ break;
+-
+- case -ERESTARTSYS:
+- if (!(ka->sa.sa_flags & SA_RESTART)) {
+- regs->ax = -EINTR;
+- break;
+- }
+- /* fallthrough */
+- case -ERESTARTNOINTR:
+- regs->ax = regs->orig_ax;
+- regs->ip -= 2;
++ }
++ /* fallthrough */
++ case -ERESTARTNOINTR:
++ regs->ax = regs->orig_ax;
++ regs->ip -= 2;
++ break;
+ }
+ }
+
+@@ -561,16 +543,32 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
+ else
+ ret = setup_frame(sig, ka, oldset, regs);
+
+- if (ret == 0) {
+- spin_lock_irq(¤t->sighand->siglock);
+- sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
+- if (!(ka->sa.sa_flags & SA_NODEFER))
+- sigaddset(¤t->blocked,sig);
+- recalc_sigpending();
+- spin_unlock_irq(¤t->sighand->siglock);
+- }
++ if (ret)
++ return ret;
+
+- return ret;
++ /*
++ * Clear the direction flag as per the ABI for function entry.
++ */
++ regs->flags &= ~X86_EFLAGS_DF;
++
++ /*
++ * Clear TF when entering the signal handler, but
++ * notify any tracer that was single-stepping it.
++ * The tracer may want to single-step inside the
++ * handler too.
++ */
++ regs->flags &= ~X86_EFLAGS_TF;
++ if (test_thread_flag(TIF_SINGLESTEP))
++ ptrace_notify(SIGTRAP);
++
++ spin_lock_irq(¤t->sighand->siglock);
++ sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask);
++ if (!(ka->sa.sa_flags & SA_NODEFER))
++ sigaddset(¤t->blocked, sig);
++ recalc_sigpending();
++ spin_unlock_irq(¤t->sighand->siglock);
++
++ return 0;
+ }
+
+ /*
+@@ -580,18 +578,17 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
+ */
+ static void do_signal(struct pt_regs *regs)
+ {
++ struct k_sigaction ka;
+ siginfo_t info;
+ int signr;
+- struct k_sigaction ka;
+ sigset_t *oldset;
+
+ /*
+- * We want the common case to go fast, which
+- * is why we may in certain cases get here from
+- * kernel mode. Just return without doing anything
+- * if so. vm86 regs switched out by assembly code
+- * before reaching here, so testing against kernel
+- * CS suffices.
++ * We want the common case to go fast, which is why we may in certain
++ * cases get here from kernel mode. Just return without doing anything
++ * if so.
++ * X86_32: vm86 regs switched out by assembly code before reaching
++ * here, so testing against kernel CS suffices.
+ */
+ if (!user_mode(regs))
+ return;
+@@ -603,29 +600,31 @@ static void do_signal(struct pt_regs *regs)
+
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+ if (signr > 0) {
+- /* Re-enable any watchpoints before delivering the
++ /*
++ * Re-enable any watchpoints before delivering the
+ * signal to user space. The processor register will
+ * have been cleared if the watchpoint triggered
+ * inside the kernel.
+ */
+- if (unlikely(current->thread.debugreg7))
++ if (current->thread.debugreg7)
+ set_debugreg(current->thread.debugreg7, 7);
+
+- /* Whee! Actually deliver the signal. */
++ /* Whee! Actually deliver the signal. */
+ if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
+- /* a signal was successfully delivered; the saved
++ /*
++ * a signal was successfully delivered; the saved
+ * sigmask will have been stored in the signal frame,
+ * and will be restored by sigreturn, so we can simply
+- * clear the TIF_RESTORE_SIGMASK flag */
++ * clear the TIF_RESTORE_SIGMASK flag
++ */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ }
+-
+ return;
+ }
+
+ /* Did we come from a system call? */
+- if (regs->orig_ax >= 0) {
++ if ((long)regs->orig_ax >= 0) {
+ /* Restart the system call - no handlers present */
+ switch (regs->ax) {
+ case -ERESTARTNOHAND:
+@@ -642,8 +641,10 @@ static void do_signal(struct pt_regs *regs)
+ }
+ }
+
+- /* if there's no signal to deliver, we just put the saved sigmask
+- * back */
++ /*
++ * If there's no signal to deliver, we just put the saved sigmask
++ * back.
++ */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
+@@ -654,13 +655,12 @@ static void do_signal(struct pt_regs *regs)
+ * notification of userspace execution resumption
+ * - triggered by the TIF_WORK_MASK flags
+ */
+-__attribute__((regparm(3)))
+-void do_notify_resume(struct pt_regs *regs, void *_unused,
+- __u32 thread_info_flags)
++void
++do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
+ {
+ /* Pending single-step? */
+ if (thread_info_flags & _TIF_SINGLESTEP) {
+- regs->flags |= TF_MASK;
++ regs->flags |= X86_EFLAGS_TF;
+ clear_thread_flag(TIF_SINGLESTEP);
+ }
+
+@@ -670,6 +670,6 @@ void do_notify_resume(struct pt_regs *regs, void *_unused,
+
+ if (thread_info_flags & _TIF_HRTICK_RESCHED)
+ hrtick_resched();
+-
++
+ clear_thread_flag(TIF_IRET);
+ }
+diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c
+index 1c83e51..ccb2a45 100644
+--- a/arch/x86/kernel/signal_64.c
++++ b/arch/x86/kernel/signal_64.c
+@@ -19,17 +19,28 @@
+ #include <linux/stddef.h>
+ #include <linux/personality.h>
+ #include <linux/compiler.h>
++#include <asm/processor.h>
+ #include <asm/ucontext.h>
+ #include <asm/uaccess.h>
+ #include <asm/i387.h>
+ #include <asm/proto.h>
+ #include <asm/ia32_unistd.h>
+ #include <asm/mce.h>
+-
+-/* #define DEBUG_SIG 1 */
++#include "sigframe.h"
+
+ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
++#define __FIX_EFLAGS (X86_EFLAGS_AC | X86_EFLAGS_OF | \
++ X86_EFLAGS_DF | X86_EFLAGS_TF | X86_EFLAGS_SF | \
++ X86_EFLAGS_ZF | X86_EFLAGS_AF | X86_EFLAGS_PF | \
++ X86_EFLAGS_CF)
++
++#ifdef CONFIG_X86_32
++# define FIX_EFLAGS (__FIX_EFLAGS | X86_EFLAGS_RF)
++#else
++# define FIX_EFLAGS __FIX_EFLAGS
++#endif
++
+ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *set, struct pt_regs * regs);
+ int ia32_setup_frame(int sig, struct k_sigaction *ka,
+@@ -46,16 +57,9 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
+ /*
+ * Do a signal return; undo the signal stack.
+ */
+-
+-struct rt_sigframe
+-{
+- char __user *pretcode;
+- struct ucontext uc;
+- struct siginfo info;
+-};
+-
+ static int
+-restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned long *prax)
++restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
++ unsigned long *pax)
+ {
+ unsigned int err = 0;
+
+@@ -87,7 +91,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned
+ {
+ unsigned int tmpflags;
+ err |= __get_user(tmpflags, &sc->flags);
+- regs->flags = (regs->flags & ~0x40DD5) | (tmpflags & 0x40DD5);
++ regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
+ regs->orig_ax = -1; /* disable syscall checks */
+ }
+
+@@ -108,7 +112,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned
+ }
+ }
+
+- err |= __get_user(*prax, &sc->ax);
++ err |= __get_user(*pax, &sc->ax);
+ return err;
+
+ badframe:
+@@ -121,13 +125,11 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
+ sigset_t set;
+ unsigned long ax;
+
+- frame = (struct rt_sigframe __user *)(regs->sp - 8);
+- if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) {
++ frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long));
++ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+- }
+- if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) {
++ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+ goto badframe;
+- }
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(¤t->sighand->siglock);
+@@ -138,10 +140,6 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
+ if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
+ goto badframe;
+
+-#ifdef DEBUG_SIG
+- printk("%d sigreturn ip:%lx sp:%lx frame:%p ax:%lx\n",current->pid,regs->ip,regs->sp,frame,ax);
+-#endif
+-
+ if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)
+ goto badframe;
+
+@@ -270,10 +268,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ if (err)
+ goto give_sigsegv;
+
+-#ifdef DEBUG_SIG
+- printk("%d old ip %lx old sp %lx old ax %lx\n", current->pid,regs->ip,regs->sp,regs->ax);
+-#endif
+-
+ /* Set up registers for signal handler */
+ regs->di = sig;
+ /* In case the signal handler was declared without prototypes */
+@@ -291,18 +285,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ even if the handler happens to be interrupting 32-bit code. */
+ regs->cs = __USER_CS;
+
+- /* This, by contrast, has nothing to do with segment registers -
+- see include/asm-x86_64/uaccess.h for details. */
+- set_fs(USER_DS);
+-
+- regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF);
+- if (test_thread_flag(TIF_SINGLESTEP))
+- ptrace_notify(SIGTRAP);
+-#ifdef DEBUG_SIG
+- printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%p\n",
+- current->comm, current->pid, frame, regs->ip, frame->pretcode);
+-#endif
+-
+ return 0;
+
+ give_sigsegv:
+@@ -345,35 +327,29 @@ static long current_syscall_ret(struct pt_regs *regs)
+
+ static int
+ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
+- sigset_t *oldset, struct pt_regs *regs)
++ sigset_t *oldset, struct pt_regs *regs)
+ {
+ int ret;
+
+-#ifdef DEBUG_SIG
+- printk("handle_signal pid:%d sig:%lu ip:%lx sp:%lx regs=%p\n",
+- current->pid, sig,
+- regs->ip, regs->sp, regs);
+-#endif
+-
+ /* Are we from a system call? */
+ if (current_syscall(regs) >= 0) {
+ /* If so, check system call restarting.. */
+ switch (current_syscall_ret(regs)) {
+- case -ERESTART_RESTARTBLOCK:
+- case -ERESTARTNOHAND:
+- regs->ax = -EINTR;
+- break;
++ case -ERESTART_RESTARTBLOCK:
++ case -ERESTARTNOHAND:
++ regs->ax = -EINTR;
++ break;
+
+- case -ERESTARTSYS:
+- if (!(ka->sa.sa_flags & SA_RESTART)) {
+- regs->ax = -EINTR;
+- break;
+- }
+- /* fallthrough */
+- case -ERESTARTNOINTR:
+- regs->ax = regs->orig_ax;
+- regs->ip -= 2;
++ case -ERESTARTSYS:
++ if (!(ka->sa.sa_flags & SA_RESTART)) {
++ regs->ax = -EINTR;
+ break;
++ }
++ /* fallthrough */
++ case -ERESTARTNOINTR:
++ regs->ax = regs->orig_ax;
++ regs->ip -= 2;
++ break;
+ }
+ }
+
+@@ -396,6 +372,28 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
+ ret = setup_rt_frame(sig, ka, info, oldset, regs);
+
+ if (ret == 0) {
++ /*
++ * This has nothing to do with segment registers,
++ * despite the name. This magic affects uaccess.h
++ * macros' behavior. Reset it to the normal setting.
++ */
++ set_fs(USER_DS);
++
++ /*
++ * Clear the direction flag as per the ABI for function entry.
++ */
++ regs->flags &= ~X86_EFLAGS_DF;
++
++ /*
++ * Clear TF when entering the signal handler, but
++ * notify any tracer that was single-stepping it.
++ * The tracer may want to single-step inside the
++ * handler too.
++ */
++ regs->flags &= ~X86_EFLAGS_TF;
++ if (test_thread_flag(TIF_SINGLESTEP))
++ ptrace_notify(SIGTRAP);
++
+ spin_lock_irq(¤t->sighand->siglock);
+ sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
+@@ -420,10 +418,11 @@ static void do_signal(struct pt_regs *regs)
+ sigset_t *oldset;
+
+ /*
+- * We want the common case to go fast, which
+- * is why we may in certain cases get here from
+- * kernel mode. Just return without doing anything
++ * We want the common case to go fast, which is why we may in certain
++ * cases get here from kernel mode. Just return without doing anything
+ * if so.
++ * X86_32: vm86 regs switched out by assembly code before reaching
++ * here, so testing against kernel CS suffices.
+ */
+ if (!user_mode(regs))
+ return;
+@@ -473,22 +472,19 @@ static void do_signal(struct pt_regs *regs)
+ }
+ }
+
+- /* if there's no signal to deliver, we just put the saved sigmask
+- back. */
++ /*
++ * If there's no signal to deliver, we just put the saved sigmask
++ * back.
++ */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
+ }
+ }
+
+-void
+-do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
++void do_notify_resume(struct pt_regs *regs, void *unused,
++ __u32 thread_info_flags)
+ {
+-#ifdef DEBUG_SIG
+- printk("do_notify_resume flags:%x ip:%lx sp:%lx caller:%p pending:%x\n",
+- thread_info_flags, regs->ip, regs->sp, __builtin_return_address(0),signal_pending(current));
+-#endif
+-
+ /* Pending single-step? */
+ if (thread_info_flags & _TIF_SINGLESTEP) {
+ regs->flags |= X86_EFLAGS_TF;
+@@ -502,7 +498,7 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
+ #endif /* CONFIG_X86_MCE */
+
+ /* deal with pending signal delivery */
+- if (thread_info_flags & (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK))
++ if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+ do_signal(regs);
+
+ if (thread_info_flags & _TIF_HRTICK_RESCHED)
+diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c
+new file mode 100644
+index 0000000..8f75893
+--- /dev/null
++++ b/arch/x86/kernel/smp.c
+@@ -0,0 +1,343 @@
++/*
++ * Intel SMP support routines.
++ *
++ * (c) 1995 Alan Cox, Building #3 <alan at redhat.com>
++ * (c) 1998-99, 2000 Ingo Molnar <mingo at redhat.com>
++ * (c) 2002,2003 Andi Kleen, SuSE Labs.
++ *
++ * i386 and x86_64 integration by Glauber Costa <gcosta at redhat.com>
++ *
++ * This code is released under the GNU General Public License version 2 or
++ * later.
++ */
++
++#include <linux/init.h>
++
++#include <linux/mm.h>
++#include <linux/delay.h>
++#include <linux/spinlock.h>
++#include <linux/kernel_stat.h>
++#include <linux/mc146818rtc.h>
++#include <linux/cache.h>
++#include <linux/interrupt.h>
++#include <linux/cpu.h>
++
++#include <asm/mtrr.h>
++#include <asm/tlbflush.h>
++#include <asm/mmu_context.h>
++#include <asm/proto.h>
++#include <mach_ipi.h>
++#include <mach_apic.h>
++/*
++ * Some notes on x86 processor bugs affecting SMP operation:
++ *
++ * Pentium, Pentium Pro, II, III (and all CPUs) have bugs.
++ * The Linux implications for SMP are handled as follows:
++ *
++ * Pentium III / [Xeon]
++ * None of the E1AP-E3AP errata are visible to the user.
++ *
++ * E1AP. see PII A1AP
++ * E2AP. see PII A2AP
++ * E3AP. see PII A3AP
++ *
++ * Pentium II / [Xeon]
++ * None of the A1AP-A3AP errata are visible to the user.
++ *
++ * A1AP. see PPro 1AP
++ * A2AP. see PPro 2AP
++ * A3AP. see PPro 7AP
++ *
++ * Pentium Pro
++ * None of 1AP-9AP errata are visible to the normal user,
++ * except occasional delivery of 'spurious interrupt' as trap #15.
++ * This is very rare and a non-problem.
++ *
++ * 1AP. Linux maps APIC as non-cacheable
++ * 2AP. worked around in hardware
++ * 3AP. fixed in C0 and above steppings microcode update.
++ * Linux does not use excessive STARTUP_IPIs.
++ * 4AP. worked around in hardware
++ * 5AP. symmetric IO mode (normal Linux operation) not affected.
++ * 'noapic' mode has vector 0xf filled out properly.
++ * 6AP. 'noapic' mode might be affected - fixed in later steppings
++ * 7AP. We do not assume writes to the LVT deassering IRQs
++ * 8AP. We do not enable low power mode (deep sleep) during MP bootup
++ * 9AP. We do not use mixed mode
++ *
++ * Pentium
++ * There is a marginal case where REP MOVS on 100MHz SMP
++ * machines with B stepping processors can fail. XXX should provide
++ * an L1cache=Writethrough or L1cache=off option.
++ *
++ * B stepping CPUs may hang. There are hardware work arounds
++ * for this. We warn about it in case your board doesn't have the work
++ * arounds. Basically that's so I can tell anyone with a B stepping
++ * CPU and SMP problems "tough".
++ *
++ * Specific items [From Pentium Processor Specification Update]
++ *
++ * 1AP. Linux doesn't use remote read
++ * 2AP. Linux doesn't trust APIC errors
++ * 3AP. We work around this
++ * 4AP. Linux never generated 3 interrupts of the same priority
++ * to cause a lost local interrupt.
++ * 5AP. Remote read is never used
++ * 6AP. not affected - worked around in hardware
++ * 7AP. not affected - worked around in hardware
++ * 8AP. worked around in hardware - we get explicit CS errors if not
++ * 9AP. only 'noapic' mode affected. Might generate spurious
++ * interrupts, we log only the first one and count the
++ * rest silently.
++ * 10AP. not affected - worked around in hardware
++ * 11AP. Linux reads the APIC between writes to avoid this, as per
++ * the documentation. Make sure you preserve this as it affects
++ * the C stepping chips too.
++ * 12AP. not affected - worked around in hardware
++ * 13AP. not affected - worked around in hardware
++ * 14AP. we always deassert INIT during bootup
++ * 15AP. not affected - worked around in hardware
++ * 16AP. not affected - worked around in hardware
++ * 17AP. not affected - worked around in hardware
++ * 18AP. not affected - worked around in hardware
++ * 19AP. not affected - worked around in BIOS
++ *
++ * If this sounds worrying believe me these bugs are either ___RARE___,
++ * or are signal timing bugs worked around in hardware and there's
++ * about nothing of note with C stepping upwards.
++ */
++
++/*
++ * this function sends a 'reschedule' IPI to another CPU.
++ * it goes straight through and wastes no time serializing
++ * anything. Worst case is that we lose a reschedule ...
++ */
++static void native_smp_send_reschedule(int cpu)
++{
++ if (unlikely(cpu_is_offline(cpu))) {
++ WARN_ON(1);
++ return;
++ }
++ send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR);
++}
++
++/*
++ * Structure and data for smp_call_function(). This is designed to minimise
++ * static memory requirements. It also looks cleaner.
++ */
++static DEFINE_SPINLOCK(call_lock);
++
++struct call_data_struct {
++ void (*func) (void *info);
++ void *info;
++ atomic_t started;
++ atomic_t finished;
++ int wait;
++};
++
++void lock_ipi_call_lock(void)
++{
++ spin_lock_irq(&call_lock);
++}
++
++void unlock_ipi_call_lock(void)
++{
++ spin_unlock_irq(&call_lock);
++}
++
++static struct call_data_struct *call_data;
++
++static void __smp_call_function(void (*func) (void *info), void *info,
++ int nonatomic, int wait)
++{
++ struct call_data_struct data;
++ int cpus = num_online_cpus() - 1;
++
++ if (!cpus)
++ return;
++
++ data.func = func;
++ data.info = info;
++ atomic_set(&data.started, 0);
++ data.wait = wait;
++ if (wait)
++ atomic_set(&data.finished, 0);
++
++ call_data = &data;
++ mb();
++
++ /* Send a message to all other CPUs and wait for them to respond */
++ send_IPI_allbutself(CALL_FUNCTION_VECTOR);
++
++ /* Wait for response */
++ while (atomic_read(&data.started) != cpus)
++ cpu_relax();
++
++ if (wait)
++ while (atomic_read(&data.finished) != cpus)
++ cpu_relax();
++}
++
++
++/**
++ * smp_call_function_mask(): Run a function on a set of other CPUs.
++ * @mask: The set of cpus to run on. Must not include the current cpu.
++ * @func: The function to run. This must be fast and non-blocking.
++ * @info: An arbitrary pointer to pass to the function.
++ * @wait: If true, wait (atomically) until function has completed on other CPUs.
++ *
++ * Returns 0 on success, else a negative status code.
++ *
++ * If @wait is true, then returns once @func has returned; otherwise
++ * it returns just before the target cpu calls @func.
++ *
++ * You must not call this function with disabled interrupts or from a
++ * hardware interrupt handler or from a bottom half handler.
++ */
++static int
++native_smp_call_function_mask(cpumask_t mask,
++ void (*func)(void *), void *info,
++ int wait)
++{
++ struct call_data_struct data;
++ cpumask_t allbutself;
++ int cpus;
++
++ /* Can deadlock when called with interrupts disabled */
++ WARN_ON(irqs_disabled());
++
++ /* Holding any lock stops cpus from going down. */
++ spin_lock(&call_lock);
++
++ allbutself = cpu_online_map;
++ cpu_clear(smp_processor_id(), allbutself);
++
++ cpus_and(mask, mask, allbutself);
++ cpus = cpus_weight(mask);
++
++ if (!cpus) {
++ spin_unlock(&call_lock);
++ return 0;
++ }
++
++ data.func = func;
++ data.info = info;
++ atomic_set(&data.started, 0);
++ data.wait = wait;
++ if (wait)
++ atomic_set(&data.finished, 0);
++
++ call_data = &data;
++ wmb();
++
++ /* Send a message to other CPUs */
++ if (cpus_equal(mask, allbutself))
++ send_IPI_allbutself(CALL_FUNCTION_VECTOR);
++ else
++ send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
++
++ /* Wait for response */
++ while (atomic_read(&data.started) != cpus)
++ cpu_relax();
++
++ if (wait)
++ while (atomic_read(&data.finished) != cpus)
++ cpu_relax();
++ spin_unlock(&call_lock);
++
++ return 0;
++}
++
++static void stop_this_cpu(void *dummy)
++{
++ local_irq_disable();
++ /*
++ * Remove this CPU:
++ */
++ cpu_clear(smp_processor_id(), cpu_online_map);
++ disable_local_APIC();
++ if (hlt_works(smp_processor_id()))
++ for (;;) halt();
++ for (;;);
++}
++
++/*
++ * this function calls the 'stop' function on all other CPUs in the system.
++ */
++
++static void native_smp_send_stop(void)
++{
++ int nolock;
++ unsigned long flags;
++
++ if (reboot_force)
++ return;
++
++ /* Don't deadlock on the call lock in panic */
++ nolock = !spin_trylock(&call_lock);
++ local_irq_save(flags);
++ __smp_call_function(stop_this_cpu, NULL, 0, 0);
++ if (!nolock)
++ spin_unlock(&call_lock);
++ disable_local_APIC();
++ local_irq_restore(flags);
++}
++
++/*
++ * Reschedule call back. Nothing to do,
++ * all the work is done automatically when
++ * we return from the interrupt.
++ */
++void smp_reschedule_interrupt(struct pt_regs *regs)
++{
++ ack_APIC_irq();
++#ifdef CONFIG_X86_32
++ __get_cpu_var(irq_stat).irq_resched_count++;
++#else
++ add_pda(irq_resched_count, 1);
++#endif
++}
++
++void smp_call_function_interrupt(struct pt_regs *regs)
++{
++ void (*func) (void *info) = call_data->func;
++ void *info = call_data->info;
++ int wait = call_data->wait;
++
++ ack_APIC_irq();
++ /*
++ * Notify initiating CPU that I've grabbed the data and am
++ * about to execute the function
++ */
++ mb();
++ atomic_inc(&call_data->started);
++ /*
++ * At this point the info structure may be out of scope unless wait==1
++ */
++ irq_enter();
++ (*func)(info);
++#ifdef CONFIG_X86_32
++ __get_cpu_var(irq_stat).irq_call_count++;
++#else
++ add_pda(irq_call_count, 1);
++#endif
++ irq_exit();
++
++ if (wait) {
++ mb();
++ atomic_inc(&call_data->finished);
++ }
++}
++
++struct smp_ops smp_ops = {
++ .smp_prepare_boot_cpu = native_smp_prepare_boot_cpu,
++ .smp_prepare_cpus = native_smp_prepare_cpus,
++ .cpu_up = native_cpu_up,
++ .smp_cpus_done = native_smp_cpus_done,
++
++ .smp_send_stop = native_smp_send_stop,
++ .smp_send_reschedule = native_smp_send_reschedule,
++ .smp_call_function_mask = native_smp_call_function_mask,
++};
++EXPORT_SYMBOL_GPL(smp_ops);
++
+diff --git a/arch/x86/kernel/smp_32.c b/arch/x86/kernel/smp_32.c
+deleted file mode 100644
+index dc0cde9..0000000
+--- a/arch/x86/kernel/smp_32.c
++++ /dev/null
+@@ -1,712 +0,0 @@
+-/*
+- * Intel SMP support routines.
+- *
+- * (c) 1995 Alan Cox, Building #3 <alan at redhat.com>
+- * (c) 1998-99, 2000 Ingo Molnar <mingo at redhat.com>
+- *
+- * This code is released under the GNU General Public License version 2 or
+- * later.
+- */
+-
+-#include <linux/init.h>
+-
+-#include <linux/mm.h>
+-#include <linux/delay.h>
+-#include <linux/spinlock.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/cache.h>
+-#include <linux/interrupt.h>
+-#include <linux/cpu.h>
+-#include <linux/module.h>
+-
+-#include <asm/mtrr.h>
+-#include <asm/tlbflush.h>
+-#include <asm/mmu_context.h>
+-#include <mach_apic.h>
+-
+-/*
+- * Some notes on x86 processor bugs affecting SMP operation:
+- *
+- * Pentium, Pentium Pro, II, III (and all CPUs) have bugs.
+- * The Linux implications for SMP are handled as follows:
+- *
+- * Pentium III / [Xeon]
+- * None of the E1AP-E3AP errata are visible to the user.
+- *
+- * E1AP. see PII A1AP
+- * E2AP. see PII A2AP
+- * E3AP. see PII A3AP
+- *
+- * Pentium II / [Xeon]
+- * None of the A1AP-A3AP errata are visible to the user.
+- *
+- * A1AP. see PPro 1AP
+- * A2AP. see PPro 2AP
+- * A3AP. see PPro 7AP
+- *
+- * Pentium Pro
+- * None of 1AP-9AP errata are visible to the normal user,
+- * except occasional delivery of 'spurious interrupt' as trap #15.
+- * This is very rare and a non-problem.
+- *
+- * 1AP. Linux maps APIC as non-cacheable
+- * 2AP. worked around in hardware
+- * 3AP. fixed in C0 and above steppings microcode update.
+- * Linux does not use excessive STARTUP_IPIs.
+- * 4AP. worked around in hardware
+- * 5AP. symmetric IO mode (normal Linux operation) not affected.
+- * 'noapic' mode has vector 0xf filled out properly.
+- * 6AP. 'noapic' mode might be affected - fixed in later steppings
+- * 7AP. We do not assume writes to the LVT deassering IRQs
+- * 8AP. We do not enable low power mode (deep sleep) during MP bootup
+- * 9AP. We do not use mixed mode
+- *
+- * Pentium
+- * There is a marginal case where REP MOVS on 100MHz SMP
+- * machines with B stepping processors can fail. XXX should provide
+- * an L1cache=Writethrough or L1cache=off option.
+- *
+- * B stepping CPUs may hang. There are hardware work arounds
+- * for this. We warn about it in case your board doesn't have the work
+- * arounds. Basically that's so I can tell anyone with a B stepping
+- * CPU and SMP problems "tough".
+- *
+- * Specific items [From Pentium Processor Specification Update]
+- *
+- * 1AP. Linux doesn't use remote read
+- * 2AP. Linux doesn't trust APIC errors
+- * 3AP. We work around this
+- * 4AP. Linux never generated 3 interrupts of the same priority
+- * to cause a lost local interrupt.
+- * 5AP. Remote read is never used
+- * 6AP. not affected - worked around in hardware
+- * 7AP. not affected - worked around in hardware
+- * 8AP. worked around in hardware - we get explicit CS errors if not
+- * 9AP. only 'noapic' mode affected. Might generate spurious
+- * interrupts, we log only the first one and count the
+- * rest silently.
+- * 10AP. not affected - worked around in hardware
+- * 11AP. Linux reads the APIC between writes to avoid this, as per
+- * the documentation. Make sure you preserve this as it affects
+- * the C stepping chips too.
+- * 12AP. not affected - worked around in hardware
+- * 13AP. not affected - worked around in hardware
+- * 14AP. we always deassert INIT during bootup
+- * 15AP. not affected - worked around in hardware
+- * 16AP. not affected - worked around in hardware
+- * 17AP. not affected - worked around in hardware
+- * 18AP. not affected - worked around in hardware
+- * 19AP. not affected - worked around in BIOS
+- *
+- * If this sounds worrying believe me these bugs are either ___RARE___,
+- * or are signal timing bugs worked around in hardware and there's
+- * about nothing of note with C stepping upwards.
+- */
+-
+-DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0, };
+-
+-/*
+- * the following functions deal with sending IPIs between CPUs.
+- *
+- * We use 'broadcast', CPU->CPU IPIs and self-IPIs too.
+- */
+-
+-static inline int __prepare_ICR (unsigned int shortcut, int vector)
+-{
+- unsigned int icr = shortcut | APIC_DEST_LOGICAL;
+-
+- switch (vector) {
+- default:
+- icr |= APIC_DM_FIXED | vector;
+- break;
+- case NMI_VECTOR:
+- icr |= APIC_DM_NMI;
+- break;
+- }
+- return icr;
+-}
+-
+-static inline int __prepare_ICR2 (unsigned int mask)
+-{
+- return SET_APIC_DEST_FIELD(mask);
+-}
+-
+-void __send_IPI_shortcut(unsigned int shortcut, int vector)
+-{
+- /*
+- * Subtle. In the case of the 'never do double writes' workaround
+- * we have to lock out interrupts to be safe. As we don't care
+- * of the value read we use an atomic rmw access to avoid costly
+- * cli/sti. Otherwise we use an even cheaper single atomic write
+- * to the APIC.
+- */
+- unsigned int cfg;
+-
+- /*
+- * Wait for idle.
+- */
+- apic_wait_icr_idle();
+-
+- /*
+- * No need to touch the target chip field
+- */
+- cfg = __prepare_ICR(shortcut, vector);
+-
+- /*
+- * Send the IPI. The write to APIC_ICR fires this off.
+- */
+- apic_write_around(APIC_ICR, cfg);
+-}
+-
+-void send_IPI_self(int vector)
+-{
+- __send_IPI_shortcut(APIC_DEST_SELF, vector);
+-}
+-
+-/*
+- * This is used to send an IPI with no shorthand notation (the destination is
+- * specified in bits 56 to 63 of the ICR).
+- */
+-static inline void __send_IPI_dest_field(unsigned long mask, int vector)
+-{
+- unsigned long cfg;
+-
+- /*
+- * Wait for idle.
+- */
+- if (unlikely(vector == NMI_VECTOR))
+- safe_apic_wait_icr_idle();
+- else
+- apic_wait_icr_idle();
+-
+- /*
+- * prepare target chip field
+- */
+- cfg = __prepare_ICR2(mask);
+- apic_write_around(APIC_ICR2, cfg);
+-
+- /*
+- * program the ICR
+- */
+- cfg = __prepare_ICR(0, vector);
+-
+- /*
+- * Send the IPI. The write to APIC_ICR fires this off.
+- */
+- apic_write_around(APIC_ICR, cfg);
+-}
+-
+-/*
+- * This is only used on smaller machines.
+- */
+-void send_IPI_mask_bitmask(cpumask_t cpumask, int vector)
+-{
+- unsigned long mask = cpus_addr(cpumask)[0];
+- unsigned long flags;
+-
+- local_irq_save(flags);
+- WARN_ON(mask & ~cpus_addr(cpu_online_map)[0]);
+- __send_IPI_dest_field(mask, vector);
+- local_irq_restore(flags);
+-}
+-
+-void send_IPI_mask_sequence(cpumask_t mask, int vector)
+-{
+- unsigned long flags;
+- unsigned int query_cpu;
+-
+- /*
+- * Hack. The clustered APIC addressing mode doesn't allow us to send
+- * to an arbitrary mask, so I do a unicasts to each CPU instead. This
+- * should be modified to do 1 message per cluster ID - mbligh
+- */
+-
+- local_irq_save(flags);
+- for_each_possible_cpu(query_cpu) {
+- if (cpu_isset(query_cpu, mask)) {
+- __send_IPI_dest_field(cpu_to_logical_apicid(query_cpu),
+- vector);
+- }
+- }
+- local_irq_restore(flags);
+-}
+-
+-#include <mach_ipi.h> /* must come after the send_IPI functions above for inlining */
+-
+-/*
+- * Smarter SMP flushing macros.
+- * c/o Linus Torvalds.
+- *
+- * These mean you can really definitely utterly forget about
+- * writing to user space from interrupts. (Its not allowed anyway).
+- *
+- * Optimizations Manfred Spraul <manfred at colorfullife.com>
+- */
+-
+-static cpumask_t flush_cpumask;
+-static struct mm_struct * flush_mm;
+-static unsigned long flush_va;
+-static DEFINE_SPINLOCK(tlbstate_lock);
+-
+-/*
+- * We cannot call mmdrop() because we are in interrupt context,
+- * instead update mm->cpu_vm_mask.
+- *
+- * We need to reload %cr3 since the page tables may be going
+- * away from under us..
+- */
+-void leave_mm(int cpu)
+-{
+- if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK)
+- BUG();
+- cpu_clear(cpu, per_cpu(cpu_tlbstate, cpu).active_mm->cpu_vm_mask);
+- load_cr3(swapper_pg_dir);
+-}
+-EXPORT_SYMBOL_GPL(leave_mm);
+-
+-/*
+- *
+- * The flush IPI assumes that a thread switch happens in this order:
+- * [cpu0: the cpu that switches]
+- * 1) switch_mm() either 1a) or 1b)
+- * 1a) thread switch to a different mm
+- * 1a1) cpu_clear(cpu, old_mm->cpu_vm_mask);
+- * Stop ipi delivery for the old mm. This is not synchronized with
+- * the other cpus, but smp_invalidate_interrupt ignore flush ipis
+- * for the wrong mm, and in the worst case we perform a superfluous
+- * tlb flush.
+- * 1a2) set cpu_tlbstate to TLBSTATE_OK
+- * Now the smp_invalidate_interrupt won't call leave_mm if cpu0
+- * was in lazy tlb mode.
+- * 1a3) update cpu_tlbstate[].active_mm
+- * Now cpu0 accepts tlb flushes for the new mm.
+- * 1a4) cpu_set(cpu, new_mm->cpu_vm_mask);
+- * Now the other cpus will send tlb flush ipis.
+- * 1a4) change cr3.
+- * 1b) thread switch without mm change
+- * cpu_tlbstate[].active_mm is correct, cpu0 already handles
+- * flush ipis.
+- * 1b1) set cpu_tlbstate to TLBSTATE_OK
+- * 1b2) test_and_set the cpu bit in cpu_vm_mask.
+- * Atomically set the bit [other cpus will start sending flush ipis],
+- * and test the bit.
+- * 1b3) if the bit was 0: leave_mm was called, flush the tlb.
+- * 2) switch %%esp, ie current
+- *
+- * The interrupt must handle 2 special cases:
+- * - cr3 is changed before %%esp, ie. it cannot use current->{active_,}mm.
+- * - the cpu performs speculative tlb reads, i.e. even if the cpu only
+- * runs in kernel space, the cpu could load tlb entries for user space
+- * pages.
+- *
+- * The good news is that cpu_tlbstate is local to each cpu, no
+- * write/read ordering problems.
+- */
+-
+-/*
+- * TLB flush IPI:
+- *
+- * 1) Flush the tlb entries if the cpu uses the mm that's being flushed.
+- * 2) Leave the mm if we are in the lazy tlb mode.
+- */
+-
+-void smp_invalidate_interrupt(struct pt_regs *regs)
+-{
+- unsigned long cpu;
+-
+- cpu = get_cpu();
+-
+- if (!cpu_isset(cpu, flush_cpumask))
+- goto out;
+- /*
+- * This was a BUG() but until someone can quote me the
+- * line from the intel manual that guarantees an IPI to
+- * multiple CPUs is retried _only_ on the erroring CPUs
+- * its staying as a return
+- *
+- * BUG();
+- */
+-
+- if (flush_mm == per_cpu(cpu_tlbstate, cpu).active_mm) {
+- if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) {
+- if (flush_va == TLB_FLUSH_ALL)
+- local_flush_tlb();
+- else
+- __flush_tlb_one(flush_va);
+- } else
+- leave_mm(cpu);
+- }
+- ack_APIC_irq();
+- smp_mb__before_clear_bit();
+- cpu_clear(cpu, flush_cpumask);
+- smp_mb__after_clear_bit();
+-out:
+- put_cpu_no_resched();
+- __get_cpu_var(irq_stat).irq_tlb_count++;
+-}
+-
+-void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm,
+- unsigned long va)
+-{
+- cpumask_t cpumask = *cpumaskp;
+-
+- /*
+- * A couple of (to be removed) sanity checks:
+- *
+- * - current CPU must not be in mask
+- * - mask must exist :)
+- */
+- BUG_ON(cpus_empty(cpumask));
+- BUG_ON(cpu_isset(smp_processor_id(), cpumask));
+- BUG_ON(!mm);
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+- /* If a CPU which we ran on has gone down, OK. */
+- cpus_and(cpumask, cpumask, cpu_online_map);
+- if (unlikely(cpus_empty(cpumask)))
+- return;
+-#endif
+-
+- /*
+- * i'm not happy about this global shared spinlock in the
+- * MM hot path, but we'll see how contended it is.
+- * AK: x86-64 has a faster method that could be ported.
+- */
+- spin_lock(&tlbstate_lock);
+-
+- flush_mm = mm;
+- flush_va = va;
+- cpus_or(flush_cpumask, cpumask, flush_cpumask);
+- /*
+- * We have to send the IPI only to
+- * CPUs affected.
+- */
+- send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR);
+-
+- while (!cpus_empty(flush_cpumask))
+- /* nothing. lockup detection does not belong here */
+- cpu_relax();
+-
+- flush_mm = NULL;
+- flush_va = 0;
+- spin_unlock(&tlbstate_lock);
+-}
+-
+-void flush_tlb_current_task(void)
+-{
+- struct mm_struct *mm = current->mm;
+- cpumask_t cpu_mask;
+-
+- preempt_disable();
+- cpu_mask = mm->cpu_vm_mask;
+- cpu_clear(smp_processor_id(), cpu_mask);
+-
+- local_flush_tlb();
+- if (!cpus_empty(cpu_mask))
+- flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
+- preempt_enable();
+-}
+-
+-void flush_tlb_mm (struct mm_struct * mm)
+-{
+- cpumask_t cpu_mask;
+-
+- preempt_disable();
+- cpu_mask = mm->cpu_vm_mask;
+- cpu_clear(smp_processor_id(), cpu_mask);
+-
+- if (current->active_mm == mm) {
+- if (current->mm)
+- local_flush_tlb();
+- else
+- leave_mm(smp_processor_id());
+- }
+- if (!cpus_empty(cpu_mask))
+- flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
+-
+- preempt_enable();
+-}
+-
+-void flush_tlb_page(struct vm_area_struct * vma, unsigned long va)
+-{
+- struct mm_struct *mm = vma->vm_mm;
+- cpumask_t cpu_mask;
+-
+- preempt_disable();
+- cpu_mask = mm->cpu_vm_mask;
+- cpu_clear(smp_processor_id(), cpu_mask);
+-
+- if (current->active_mm == mm) {
+- if(current->mm)
+- __flush_tlb_one(va);
+- else
+- leave_mm(smp_processor_id());
+- }
+-
+- if (!cpus_empty(cpu_mask))
+- flush_tlb_others(cpu_mask, mm, va);
+-
+- preempt_enable();
+-}
+-EXPORT_SYMBOL(flush_tlb_page);
+-
+-static void do_flush_tlb_all(void* info)
+-{
+- unsigned long cpu = smp_processor_id();
+-
+- __flush_tlb_all();
+- if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_LAZY)
+- leave_mm(cpu);
+-}
+-
+-void flush_tlb_all(void)
+-{
+- on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
+-}
+-
+-/*
+- * this function sends a 'reschedule' IPI to another CPU.
+- * it goes straight through and wastes no time serializing
+- * anything. Worst case is that we lose a reschedule ...
+- */
+-static void native_smp_send_reschedule(int cpu)
+-{
+- WARN_ON(cpu_is_offline(cpu));
+- send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR);
+-}
+-
+-/*
+- * Structure and data for smp_call_function(). This is designed to minimise
+- * static memory requirements. It also looks cleaner.
+- */
+-static DEFINE_SPINLOCK(call_lock);
+-
+-struct call_data_struct {
+- void (*func) (void *info);
+- void *info;
+- atomic_t started;
+- atomic_t finished;
+- int wait;
+-};
+-
+-void lock_ipi_call_lock(void)
+-{
+- spin_lock_irq(&call_lock);
+-}
+-
+-void unlock_ipi_call_lock(void)
+-{
+- spin_unlock_irq(&call_lock);
+-}
+-
+-static struct call_data_struct *call_data;
+-
+-static void __smp_call_function(void (*func) (void *info), void *info,
+- int nonatomic, int wait)
+-{
+- struct call_data_struct data;
+- int cpus = num_online_cpus() - 1;
+-
+- if (!cpus)
+- return;
+-
+- data.func = func;
+- data.info = info;
+- atomic_set(&data.started, 0);
+- data.wait = wait;
+- if (wait)
+- atomic_set(&data.finished, 0);
+-
+- call_data = &data;
+- mb();
+-
+- /* Send a message to all other CPUs and wait for them to respond */
+- send_IPI_allbutself(CALL_FUNCTION_VECTOR);
+-
+- /* Wait for response */
+- while (atomic_read(&data.started) != cpus)
+- cpu_relax();
+-
+- if (wait)
+- while (atomic_read(&data.finished) != cpus)
+- cpu_relax();
+-}
+-
+-
+-/**
+- * smp_call_function_mask(): Run a function on a set of other CPUs.
+- * @mask: The set of cpus to run on. Must not include the current cpu.
+- * @func: The function to run. This must be fast and non-blocking.
+- * @info: An arbitrary pointer to pass to the function.
+- * @wait: If true, wait (atomically) until function has completed on other CPUs.
+- *
+- * Returns 0 on success, else a negative status code.
+- *
+- * If @wait is true, then returns once @func has returned; otherwise
+- * it returns just before the target cpu calls @func.
+- *
+- * You must not call this function with disabled interrupts or from a
+- * hardware interrupt handler or from a bottom half handler.
+- */
+-static int
+-native_smp_call_function_mask(cpumask_t mask,
+- void (*func)(void *), void *info,
+- int wait)
+-{
+- struct call_data_struct data;
+- cpumask_t allbutself;
+- int cpus;
+-
+- /* Can deadlock when called with interrupts disabled */
+- WARN_ON(irqs_disabled());
+-
+- /* Holding any lock stops cpus from going down. */
+- spin_lock(&call_lock);
+-
+- allbutself = cpu_online_map;
+- cpu_clear(smp_processor_id(), allbutself);
+-
+- cpus_and(mask, mask, allbutself);
+- cpus = cpus_weight(mask);
+-
+- if (!cpus) {
+- spin_unlock(&call_lock);
+- return 0;
+- }
+-
+- data.func = func;
+- data.info = info;
+- atomic_set(&data.started, 0);
+- data.wait = wait;
+- if (wait)
+- atomic_set(&data.finished, 0);
+-
+- call_data = &data;
+- mb();
+-
+- /* Send a message to other CPUs */
+- if (cpus_equal(mask, allbutself))
+- send_IPI_allbutself(CALL_FUNCTION_VECTOR);
+- else
+- send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
+-
+- /* Wait for response */
+- while (atomic_read(&data.started) != cpus)
+- cpu_relax();
+-
+- if (wait)
+- while (atomic_read(&data.finished) != cpus)
+- cpu_relax();
+- spin_unlock(&call_lock);
+-
+- return 0;
+-}
+-
+-static void stop_this_cpu (void * dummy)
+-{
+- local_irq_disable();
+- /*
+- * Remove this CPU:
+- */
+- cpu_clear(smp_processor_id(), cpu_online_map);
+- disable_local_APIC();
+- if (cpu_data(smp_processor_id()).hlt_works_ok)
+- for(;;) halt();
+- for (;;);
+-}
+-
+-/*
+- * this function calls the 'stop' function on all other CPUs in the system.
+- */
+-
+-static void native_smp_send_stop(void)
+-{
+- /* Don't deadlock on the call lock in panic */
+- int nolock = !spin_trylock(&call_lock);
+- unsigned long flags;
+-
+- local_irq_save(flags);
+- __smp_call_function(stop_this_cpu, NULL, 0, 0);
+- if (!nolock)
+- spin_unlock(&call_lock);
+- disable_local_APIC();
+- local_irq_restore(flags);
+-}
+-
+-/*
+- * Reschedule call back. Nothing to do,
+- * all the work is done automatically when
+- * we return from the interrupt.
+- */
+-void smp_reschedule_interrupt(struct pt_regs *regs)
+-{
+- ack_APIC_irq();
+- __get_cpu_var(irq_stat).irq_resched_count++;
+-}
+-
+-void smp_call_function_interrupt(struct pt_regs *regs)
+-{
+- void (*func) (void *info) = call_data->func;
+- void *info = call_data->info;
+- int wait = call_data->wait;
+-
+- ack_APIC_irq();
+- /*
+- * Notify initiating CPU that I've grabbed the data and am
+- * about to execute the function
+- */
+- mb();
+- atomic_inc(&call_data->started);
+- /*
+- * At this point the info structure may be out of scope unless wait==1
+- */
+- irq_enter();
+- (*func)(info);
+- __get_cpu_var(irq_stat).irq_call_count++;
+- irq_exit();
+-
+- if (wait) {
+- mb();
+- atomic_inc(&call_data->finished);
+- }
+-}
+-
+-static int convert_apicid_to_cpu(int apic_id)
+-{
+- int i;
+-
+- for_each_possible_cpu(i) {
+- if (per_cpu(x86_cpu_to_apicid, i) == apic_id)
+- return i;
+- }
+- return -1;
+-}
+-
+-int safe_smp_processor_id(void)
+-{
+- int apicid, cpuid;
+-
+- if (!boot_cpu_has(X86_FEATURE_APIC))
+- return 0;
+-
+- apicid = hard_smp_processor_id();
+- if (apicid == BAD_APICID)
+- return 0;
+-
+- cpuid = convert_apicid_to_cpu(apicid);
+-
+- return cpuid >= 0 ? cpuid : 0;
+-}
+-
+-struct smp_ops smp_ops = {
+- .smp_prepare_boot_cpu = native_smp_prepare_boot_cpu,
+- .smp_prepare_cpus = native_smp_prepare_cpus,
+- .cpu_up = native_cpu_up,
+- .smp_cpus_done = native_smp_cpus_done,
+-
+- .smp_send_stop = native_smp_send_stop,
+- .smp_send_reschedule = native_smp_send_reschedule,
+- .smp_call_function_mask = native_smp_call_function_mask,
+-};
+-EXPORT_SYMBOL_GPL(smp_ops);
+diff --git a/arch/x86/kernel/smp_64.c b/arch/x86/kernel/smp_64.c
+deleted file mode 100644
+index 2fd74b0..0000000
+--- a/arch/x86/kernel/smp_64.c
++++ /dev/null
+@@ -1,530 +0,0 @@
+-/*
+- * Intel SMP support routines.
+- *
+- * (c) 1995 Alan Cox, Building #3 <alan at redhat.com>
+- * (c) 1998-99, 2000 Ingo Molnar <mingo at redhat.com>
+- * (c) 2002,2003 Andi Kleen, SuSE Labs.
+- *
+- * This code is released under the GNU General Public License version 2 or
+- * later.
+- */
+-
+-#include <linux/init.h>
+-
+-#include <linux/mm.h>
+-#include <linux/delay.h>
+-#include <linux/spinlock.h>
+-#include <linux/smp.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/interrupt.h>
+-
+-#include <asm/mtrr.h>
+-#include <asm/pgalloc.h>
+-#include <asm/tlbflush.h>
+-#include <asm/mach_apic.h>
+-#include <asm/mmu_context.h>
+-#include <asm/proto.h>
+-#include <asm/apicdef.h>
+-#include <asm/idle.h>
+-
+-/*
+- * Smarter SMP flushing macros.
+- * c/o Linus Torvalds.
+- *
+- * These mean you can really definitely utterly forget about
+- * writing to user space from interrupts. (Its not allowed anyway).
+- *
+- * Optimizations Manfred Spraul <manfred at colorfullife.com>
+- *
+- * More scalable flush, from Andi Kleen
+- *
+- * To avoid global state use 8 different call vectors.
+- * Each CPU uses a specific vector to trigger flushes on other
+- * CPUs. Depending on the received vector the target CPUs look into
+- * the right per cpu variable for the flush data.
+- *
+- * With more than 8 CPUs they are hashed to the 8 available
+- * vectors. The limited global vector space forces us to this right now.
+- * In future when interrupts are split into per CPU domains this could be
+- * fixed, at the cost of triggering multiple IPIs in some cases.
+- */
+-
+-union smp_flush_state {
+- struct {
+- cpumask_t flush_cpumask;
+- struct mm_struct *flush_mm;
+- unsigned long flush_va;
+- spinlock_t tlbstate_lock;
+- };
+- char pad[SMP_CACHE_BYTES];
+-} ____cacheline_aligned;
+-
+-/* State is put into the per CPU data section, but padded
+- to a full cache line because other CPUs can access it and we don't
+- want false sharing in the per cpu data segment. */
+-static DEFINE_PER_CPU(union smp_flush_state, flush_state);
+-
+-/*
+- * We cannot call mmdrop() because we are in interrupt context,
+- * instead update mm->cpu_vm_mask.
+- */
+-void leave_mm(int cpu)
+-{
+- if (read_pda(mmu_state) == TLBSTATE_OK)
+- BUG();
+- cpu_clear(cpu, read_pda(active_mm)->cpu_vm_mask);
+- load_cr3(swapper_pg_dir);
+-}
+-EXPORT_SYMBOL_GPL(leave_mm);
+-
+-/*
+- *
+- * The flush IPI assumes that a thread switch happens in this order:
+- * [cpu0: the cpu that switches]
+- * 1) switch_mm() either 1a) or 1b)
+- * 1a) thread switch to a different mm
+- * 1a1) cpu_clear(cpu, old_mm->cpu_vm_mask);
+- * Stop ipi delivery for the old mm. This is not synchronized with
+- * the other cpus, but smp_invalidate_interrupt ignore flush ipis
+- * for the wrong mm, and in the worst case we perform a superfluous
+- * tlb flush.
+- * 1a2) set cpu mmu_state to TLBSTATE_OK
+- * Now the smp_invalidate_interrupt won't call leave_mm if cpu0
+- * was in lazy tlb mode.
+- * 1a3) update cpu active_mm
+- * Now cpu0 accepts tlb flushes for the new mm.
+- * 1a4) cpu_set(cpu, new_mm->cpu_vm_mask);
+- * Now the other cpus will send tlb flush ipis.
+- * 1a4) change cr3.
+- * 1b) thread switch without mm change
+- * cpu active_mm is correct, cpu0 already handles
+- * flush ipis.
+- * 1b1) set cpu mmu_state to TLBSTATE_OK
+- * 1b2) test_and_set the cpu bit in cpu_vm_mask.
+- * Atomically set the bit [other cpus will start sending flush ipis],
+- * and test the bit.
+- * 1b3) if the bit was 0: leave_mm was called, flush the tlb.
+- * 2) switch %%esp, ie current
+- *
+- * The interrupt must handle 2 special cases:
+- * - cr3 is changed before %%esp, ie. it cannot use current->{active_,}mm.
+- * - the cpu performs speculative tlb reads, i.e. even if the cpu only
+- * runs in kernel space, the cpu could load tlb entries for user space
+- * pages.
+- *
+- * The good news is that cpu mmu_state is local to each cpu, no
+- * write/read ordering problems.
+- */
+-
+-/*
+- * TLB flush IPI:
+- *
+- * 1) Flush the tlb entries if the cpu uses the mm that's being flushed.
+- * 2) Leave the mm if we are in the lazy tlb mode.
+- *
+- * Interrupts are disabled.
+- */
+-
+-asmlinkage void smp_invalidate_interrupt(struct pt_regs *regs)
+-{
+- int cpu;
+- int sender;
+- union smp_flush_state *f;
+-
+- cpu = smp_processor_id();
+- /*
+- * orig_rax contains the negated interrupt vector.
+- * Use that to determine where the sender put the data.
+- */
+- sender = ~regs->orig_ax - INVALIDATE_TLB_VECTOR_START;
+- f = &per_cpu(flush_state, sender);
+-
+- if (!cpu_isset(cpu, f->flush_cpumask))
+- goto out;
+- /*
+- * This was a BUG() but until someone can quote me the
+- * line from the intel manual that guarantees an IPI to
+- * multiple CPUs is retried _only_ on the erroring CPUs
+- * its staying as a return
+- *
+- * BUG();
+- */
+-
+- if (f->flush_mm == read_pda(active_mm)) {
+- if (read_pda(mmu_state) == TLBSTATE_OK) {
+- if (f->flush_va == TLB_FLUSH_ALL)
+- local_flush_tlb();
+- else
+- __flush_tlb_one(f->flush_va);
+- } else
+- leave_mm(cpu);
+- }
+-out:
+- ack_APIC_irq();
+- cpu_clear(cpu, f->flush_cpumask);
+- add_pda(irq_tlb_count, 1);
+-}
+-
+-void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm,
+- unsigned long va)
+-{
+- int sender;
+- union smp_flush_state *f;
+- cpumask_t cpumask = *cpumaskp;
+-
+- /* Caller has disabled preemption */
+- sender = smp_processor_id() % NUM_INVALIDATE_TLB_VECTORS;
+- f = &per_cpu(flush_state, sender);
+-
+- /*
+- * Could avoid this lock when
+- * num_online_cpus() <= NUM_INVALIDATE_TLB_VECTORS, but it is
+- * probably not worth checking this for a cache-hot lock.
+- */
+- spin_lock(&f->tlbstate_lock);
+-
+- f->flush_mm = mm;
+- f->flush_va = va;
+- cpus_or(f->flush_cpumask, cpumask, f->flush_cpumask);
+-
+- /*
+- * We have to send the IPI only to
+- * CPUs affected.
+- */
+- send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR_START + sender);
+-
+- while (!cpus_empty(f->flush_cpumask))
+- cpu_relax();
+-
+- f->flush_mm = NULL;
+- f->flush_va = 0;
+- spin_unlock(&f->tlbstate_lock);
+-}
+-
+-int __cpuinit init_smp_flush(void)
+-{
+- int i;
+-
+- for_each_cpu_mask(i, cpu_possible_map) {
+- spin_lock_init(&per_cpu(flush_state, i).tlbstate_lock);
+- }
+- return 0;
+-}
+-core_initcall(init_smp_flush);
+-
+-void flush_tlb_current_task(void)
+-{
+- struct mm_struct *mm = current->mm;
+- cpumask_t cpu_mask;
+-
+- preempt_disable();
+- cpu_mask = mm->cpu_vm_mask;
+- cpu_clear(smp_processor_id(), cpu_mask);
+-
+- local_flush_tlb();
+- if (!cpus_empty(cpu_mask))
+- flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
+- preempt_enable();
+-}
+-
+-void flush_tlb_mm (struct mm_struct * mm)
+-{
+- cpumask_t cpu_mask;
+-
+- preempt_disable();
+- cpu_mask = mm->cpu_vm_mask;
+- cpu_clear(smp_processor_id(), cpu_mask);
+-
+- if (current->active_mm == mm) {
+- if (current->mm)
+- local_flush_tlb();
+- else
+- leave_mm(smp_processor_id());
+- }
+- if (!cpus_empty(cpu_mask))
+- flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
+-
+- preempt_enable();
+-}
+-
+-void flush_tlb_page(struct vm_area_struct * vma, unsigned long va)
+-{
+- struct mm_struct *mm = vma->vm_mm;
+- cpumask_t cpu_mask;
+-
+- preempt_disable();
+- cpu_mask = mm->cpu_vm_mask;
+- cpu_clear(smp_processor_id(), cpu_mask);
+-
+- if (current->active_mm == mm) {
+- if(current->mm)
+- __flush_tlb_one(va);
+- else
+- leave_mm(smp_processor_id());
+- }
+-
+- if (!cpus_empty(cpu_mask))
+- flush_tlb_others(cpu_mask, mm, va);
+-
+- preempt_enable();
+-}
+-
+-static void do_flush_tlb_all(void* info)
+-{
+- unsigned long cpu = smp_processor_id();
+-
+- __flush_tlb_all();
+- if (read_pda(mmu_state) == TLBSTATE_LAZY)
+- leave_mm(cpu);
+-}
+-
+-void flush_tlb_all(void)
+-{
+- on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
+-}
+-
+-/*
+- * this function sends a 'reschedule' IPI to another CPU.
+- * it goes straight through and wastes no time serializing
+- * anything. Worst case is that we lose a reschedule ...
+- */
+-
+-void smp_send_reschedule(int cpu)
+-{
+- send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR);
+-}
+-
+-/*
+- * Structure and data for smp_call_function(). This is designed to minimise
+- * static memory requirements. It also looks cleaner.
+- */
+-static DEFINE_SPINLOCK(call_lock);
+-
+-struct call_data_struct {
+- void (*func) (void *info);
+- void *info;
+- atomic_t started;
+- atomic_t finished;
+- int wait;
+-};
+-
+-static struct call_data_struct * call_data;
+-
+-void lock_ipi_call_lock(void)
+-{
+- spin_lock_irq(&call_lock);
+-}
+-
+-void unlock_ipi_call_lock(void)
+-{
+- spin_unlock_irq(&call_lock);
+-}
+-
+-/*
+- * this function sends a 'generic call function' IPI to all other CPU
+- * of the system defined in the mask.
+- */
+-static int __smp_call_function_mask(cpumask_t mask,
+- void (*func)(void *), void *info,
+- int wait)
+-{
+- struct call_data_struct data;
+- cpumask_t allbutself;
+- int cpus;
+-
+- allbutself = cpu_online_map;
+- cpu_clear(smp_processor_id(), allbutself);
+-
+- cpus_and(mask, mask, allbutself);
+- cpus = cpus_weight(mask);
+-
+- if (!cpus)
+- return 0;
+-
+- data.func = func;
+- data.info = info;
+- atomic_set(&data.started, 0);
+- data.wait = wait;
+- if (wait)
+- atomic_set(&data.finished, 0);
+-
+- call_data = &data;
+- wmb();
+-
+- /* Send a message to other CPUs */
+- if (cpus_equal(mask, allbutself))
+- send_IPI_allbutself(CALL_FUNCTION_VECTOR);
+- else
+- send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
+-
+- /* Wait for response */
+- while (atomic_read(&data.started) != cpus)
+- cpu_relax();
+-
+- if (!wait)
+- return 0;
+-
+- while (atomic_read(&data.finished) != cpus)
+- cpu_relax();
+-
+- return 0;
+-}
+-/**
+- * smp_call_function_mask(): Run a function on a set of other CPUs.
+- * @mask: The set of cpus to run on. Must not include the current cpu.
+- * @func: The function to run. This must be fast and non-blocking.
+- * @info: An arbitrary pointer to pass to the function.
+- * @wait: If true, wait (atomically) until function has completed on other CPUs.
+- *
+- * Returns 0 on success, else a negative status code.
+- *
+- * If @wait is true, then returns once @func has returned; otherwise
+- * it returns just before the target cpu calls @func.
+- *
+- * You must not call this function with disabled interrupts or from a
+- * hardware interrupt handler or from a bottom half handler.
+- */
+-int smp_call_function_mask(cpumask_t mask,
+- void (*func)(void *), void *info,
+- int wait)
+-{
+- int ret;
+-
+- /* Can deadlock when called with interrupts disabled */
+- WARN_ON(irqs_disabled());
+-
+- spin_lock(&call_lock);
+- ret = __smp_call_function_mask(mask, func, info, wait);
+- spin_unlock(&call_lock);
+- return ret;
+-}
+-EXPORT_SYMBOL(smp_call_function_mask);
+-
+-/*
+- * smp_call_function_single - Run a function on a specific CPU
+- * @func: The function to run. This must be fast and non-blocking.
+- * @info: An arbitrary pointer to pass to the function.
+- * @nonatomic: Currently unused.
+- * @wait: If true, wait until function has completed on other CPUs.
+- *
+- * Retrurns 0 on success, else a negative status code.
+- *
+- * Does not return until the remote CPU is nearly ready to execute <func>
+- * or is or has executed.
+- */
+-
+-int smp_call_function_single (int cpu, void (*func) (void *info), void *info,
+- int nonatomic, int wait)
+-{
+- /* prevent preemption and reschedule on another processor */
+- int ret, me = get_cpu();
+-
+- /* Can deadlock when called with interrupts disabled */
+- WARN_ON(irqs_disabled());
+-
+- if (cpu == me) {
+- local_irq_disable();
+- func(info);
+- local_irq_enable();
+- put_cpu();
+- return 0;
+- }
+-
+- ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait);
+-
+- put_cpu();
+- return ret;
+-}
+-EXPORT_SYMBOL(smp_call_function_single);
+-
+-/*
+- * smp_call_function - run a function on all other CPUs.
+- * @func: The function to run. This must be fast and non-blocking.
+- * @info: An arbitrary pointer to pass to the function.
+- * @nonatomic: currently unused.
+- * @wait: If true, wait (atomically) until function has completed on other
+- * CPUs.
+- *
+- * Returns 0 on success, else a negative status code. Does not return until
+- * remote CPUs are nearly ready to execute func or are or have executed.
+- *
+- * You must not call this function with disabled interrupts or from a
+- * hardware interrupt handler or from a bottom half handler.
+- * Actually there are a few legal cases, like panic.
+- */
+-int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
+- int wait)
+-{
+- return smp_call_function_mask(cpu_online_map, func, info, wait);
+-}
+-EXPORT_SYMBOL(smp_call_function);
+-
+-static void stop_this_cpu(void *dummy)
+-{
+- local_irq_disable();
+- /*
+- * Remove this CPU:
+- */
+- cpu_clear(smp_processor_id(), cpu_online_map);
+- disable_local_APIC();
+- for (;;)
+- halt();
+-}
+-
+-void smp_send_stop(void)
+-{
+- int nolock;
+- unsigned long flags;
+-
+- if (reboot_force)
+- return;
+-
+- /* Don't deadlock on the call lock in panic */
+- nolock = !spin_trylock(&call_lock);
+- local_irq_save(flags);
+- __smp_call_function_mask(cpu_online_map, stop_this_cpu, NULL, 0);
+- if (!nolock)
+- spin_unlock(&call_lock);
+- disable_local_APIC();
+- local_irq_restore(flags);
+-}
+-
+-/*
+- * Reschedule call back. Nothing to do,
+- * all the work is done automatically when
+- * we return from the interrupt.
+- */
+-asmlinkage void smp_reschedule_interrupt(void)
+-{
+- ack_APIC_irq();
+- add_pda(irq_resched_count, 1);
+-}
+-
+-asmlinkage void smp_call_function_interrupt(void)
+-{
+- void (*func) (void *info) = call_data->func;
+- void *info = call_data->info;
+- int wait = call_data->wait;
+-
+- ack_APIC_irq();
+- /*
+- * Notify initiating CPU that I've grabbed the data and am
+- * about to execute the function
+- */
+- mb();
+- atomic_inc(&call_data->started);
+- /*
+- * At this point the info structure may be out of scope unless wait==1
+- */
+- exit_idle();
+- irq_enter();
+- (*func)(info);
+- add_pda(irq_call_count, 1);
+- irq_exit();
+- if (wait) {
+- mb();
+- atomic_inc(&call_data->finished);
+- }
+-}
+-
+diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
+new file mode 100644
+index 0000000..04c662b
+--- /dev/null
++++ b/arch/x86/kernel/smpboot.c
+@@ -0,0 +1,1450 @@
++/*
++ * x86 SMP booting functions
++ *
++ * (c) 1995 Alan Cox, Building #3 <alan at redhat.com>
++ * (c) 1998, 1999, 2000 Ingo Molnar <mingo at redhat.com>
++ * Copyright 2001 Andi Kleen, SuSE Labs.
++ *
++ * Much of the core SMP work is based on previous work by Thomas Radke, to
++ * whom a great many thanks are extended.
++ *
++ * Thanks to Intel for making available several different Pentium,
++ * Pentium Pro and Pentium-II/Xeon MP machines.
++ * Original development of Linux SMP code supported by Caldera.
++ *
++ * This code is released under the GNU General Public License version 2 or
++ * later.
++ *
++ * Fixes
++ * Felix Koop : NR_CPUS used properly
++ * Jose Renau : Handle single CPU case.
++ * Alan Cox : By repeated request 8) - Total BogoMIPS report.
++ * Greg Wright : Fix for kernel stacks panic.
++ * Erich Boleyn : MP v1.4 and additional changes.
++ * Matthias Sattler : Changes for 2.1 kernel map.
++ * Michel Lespinasse : Changes for 2.1 kernel map.
++ * Michael Chastain : Change trampoline.S to gnu as.
++ * Alan Cox : Dumb bug: 'B' step PPro's are fine
++ * Ingo Molnar : Added APIC timers, based on code
++ * from Jose Renau
++ * Ingo Molnar : various cleanups and rewrites
++ * Tigran Aivazian : fixed "0.00 in /proc/uptime on SMP" bug.
++ * Maciej W. Rozycki : Bits for genuine 82489DX APICs
++ * Andi Kleen : Changed for SMP boot into long mode.
++ * Martin J. Bligh : Added support for multi-quad systems
++ * Dave Jones : Report invalid combinations of Athlon CPUs.
++ * Rusty Russell : Hacked into shape for new "hotplug" boot process.
++ * Andi Kleen : Converted to new state machine.
++ * Ashok Raj : CPU hotplug support
++ * Glauber Costa : i386 and x86_64 integration
++ */
++
++#include <linux/init.h>
++#include <linux/smp.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/percpu.h>
++#include <linux/bootmem.h>
++#include <linux/err.h>
++#include <linux/nmi.h>
++
++#include <asm/acpi.h>
++#include <asm/desc.h>
++#include <asm/nmi.h>
++#include <asm/irq.h>
++#include <asm/smp.h>
++#include <asm/trampoline.h>
++#include <asm/cpu.h>
++#include <asm/numa.h>
++#include <asm/pgtable.h>
++#include <asm/tlbflush.h>
++#include <asm/mtrr.h>
++#include <asm/nmi.h>
++#include <asm/vmi.h>
++#include <asm/genapic.h>
++#include <linux/mc146818rtc.h>
++
++#include <mach_apic.h>
++#include <mach_wakecpu.h>
++#include <smpboot_hooks.h>
++
++/*
++ * FIXME: For x86_64, those are defined in other files. But moving them here,
++ * would make the setup areas dependent on smp, which is a loss. When we
++ * integrate apic between arches, we can probably do a better job, but
++ * right now, they'll stay here -- glommer
++ */
++
++/* which logical CPU number maps to which CPU (physical APIC ID) */
++u16 x86_cpu_to_apicid_init[NR_CPUS] __initdata =
++ { [0 ... NR_CPUS-1] = BAD_APICID };
++void *x86_cpu_to_apicid_early_ptr;
++
++u16 x86_bios_cpu_apicid_init[NR_CPUS] __initdata
++ = { [0 ... NR_CPUS-1] = BAD_APICID };
++void *x86_bios_cpu_apicid_early_ptr;
++
++#ifdef CONFIG_X86_32
++u8 apicid_2_node[MAX_APICID];
++#endif
++
++/* State of each CPU */
++DEFINE_PER_CPU(int, cpu_state) = { 0 };
++
++/* Store all idle threads, this can be reused instead of creating
++* a new thread. Also avoids complicated thread destroy functionality
++* for idle threads.
++*/
++#ifdef CONFIG_HOTPLUG_CPU
++/*
++ * Needed only for CONFIG_HOTPLUG_CPU because __cpuinitdata is
++ * removed after init for !CONFIG_HOTPLUG_CPU.
++ */
++static DEFINE_PER_CPU(struct task_struct *, idle_thread_array);
++#define get_idle_for_cpu(x) (per_cpu(idle_thread_array, x))
++#define set_idle_for_cpu(x, p) (per_cpu(idle_thread_array, x) = (p))
++#else
++struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ;
++#define get_idle_for_cpu(x) (idle_thread_array[(x)])
++#define set_idle_for_cpu(x, p) (idle_thread_array[(x)] = (p))
++#endif
++
++/* Number of siblings per CPU package */
++int smp_num_siblings = 1;
++EXPORT_SYMBOL(smp_num_siblings);
++
++/* Last level cache ID of each logical CPU */
++DEFINE_PER_CPU(u16, cpu_llc_id) = BAD_APICID;
++
++/* bitmap of online cpus */
++cpumask_t cpu_online_map __read_mostly;
++EXPORT_SYMBOL(cpu_online_map);
++
++cpumask_t cpu_callin_map;
++cpumask_t cpu_callout_map;
++cpumask_t cpu_possible_map;
++EXPORT_SYMBOL(cpu_possible_map);
++
++/* representing HT siblings of each logical CPU */
++DEFINE_PER_CPU(cpumask_t, cpu_sibling_map);
++EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
++
++/* representing HT and core siblings of each logical CPU */
++DEFINE_PER_CPU(cpumask_t, cpu_core_map);
++EXPORT_PER_CPU_SYMBOL(cpu_core_map);
++
++/* Per CPU bogomips and other parameters */
++DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
++EXPORT_PER_CPU_SYMBOL(cpu_info);
++
++static atomic_t init_deasserted;
++
++static int boot_cpu_logical_apicid;
++
++/* representing cpus for which sibling maps can be computed */
++static cpumask_t cpu_sibling_setup_map;
++
++/* Set if we find a B stepping CPU */
++int __cpuinitdata smp_b_stepping;
++
++#if defined(CONFIG_NUMA) && defined(CONFIG_X86_32)
++
++/* which logical CPUs are on which nodes */
++cpumask_t node_to_cpumask_map[MAX_NUMNODES] __read_mostly =
++ { [0 ... MAX_NUMNODES-1] = CPU_MASK_NONE };
++EXPORT_SYMBOL(node_to_cpumask_map);
++/* which node each logical CPU is on */
++int cpu_to_node_map[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = 0 };
++EXPORT_SYMBOL(cpu_to_node_map);
++
++/* set up a mapping between cpu and node. */
++static void map_cpu_to_node(int cpu, int node)
++{
++ printk(KERN_INFO "Mapping cpu %d to node %d\n", cpu, node);
++ cpu_set(cpu, node_to_cpumask_map[node]);
++ cpu_to_node_map[cpu] = node;
++}
++
++/* undo a mapping between cpu and node. */
++static void unmap_cpu_to_node(int cpu)
++{
++ int node;
++
++ printk(KERN_INFO "Unmapping cpu %d from all nodes\n", cpu);
++ for (node = 0; node < MAX_NUMNODES; node++)
++ cpu_clear(cpu, node_to_cpumask_map[node]);
++ cpu_to_node_map[cpu] = 0;
++}
++#else /* !(CONFIG_NUMA && CONFIG_X86_32) */
++#define map_cpu_to_node(cpu, node) ({})
++#define unmap_cpu_to_node(cpu) ({})
++#endif
++
++#ifdef CONFIG_X86_32
++u8 cpu_2_logical_apicid[NR_CPUS] __read_mostly =
++ { [0 ... NR_CPUS-1] = BAD_APICID };
++
++static void map_cpu_to_logical_apicid(void)
++{
++ int cpu = smp_processor_id();
++ int apicid = logical_smp_processor_id();
++ int node = apicid_to_node(apicid);
++
++ if (!node_online(node))
++ node = first_online_node;
++
++ cpu_2_logical_apicid[cpu] = apicid;
++ map_cpu_to_node(cpu, node);
++}
++
++static void unmap_cpu_to_logical_apicid(int cpu)
++{
++ cpu_2_logical_apicid[cpu] = BAD_APICID;
++ unmap_cpu_to_node(cpu);
++}
++#else
++#define unmap_cpu_to_logical_apicid(cpu) do {} while (0)
++#define map_cpu_to_logical_apicid() do {} while (0)
++#endif
++
++/*
++ * Report back to the Boot Processor.
++ * Running on AP.
++ */
++static void __cpuinit smp_callin(void)
++{
++ int cpuid, phys_id;
++ unsigned long timeout;
++
++ /*
++ * If waken up by an INIT in an 82489DX configuration
++ * we may get here before an INIT-deassert IPI reaches
++ * our local APIC. We have to wait for the IPI or we'll
++ * lock up on an APIC access.
++ */
++ wait_for_init_deassert(&init_deasserted);
++
++ /*
++ * (This works even if the APIC is not enabled.)
++ */
++ phys_id = GET_APIC_ID(read_apic_id());
++ cpuid = smp_processor_id();
++ if (cpu_isset(cpuid, cpu_callin_map)) {
++ panic("%s: phys CPU#%d, CPU#%d already present??\n", __func__,
++ phys_id, cpuid);
++ }
++ Dprintk("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id);
++
++ /*
++ * STARTUP IPIs are fragile beasts as they might sometimes
++ * trigger some glue motherboard logic. Complete APIC bus
++ * silence for 1 second, this overestimates the time the
++ * boot CPU is spending to send the up to 2 STARTUP IPIs
++ * by a factor of two. This should be enough.
++ */
++
++ /*
++ * Waiting 2s total for startup (udelay is not yet working)
++ */
++ timeout = jiffies + 2*HZ;
++ while (time_before(jiffies, timeout)) {
++ /*
++ * Has the boot CPU finished it's STARTUP sequence?
++ */
++ if (cpu_isset(cpuid, cpu_callout_map))
++ break;
++ cpu_relax();
++ }
++
++ if (!time_before(jiffies, timeout)) {
++ panic("%s: CPU%d started up but did not get a callout!\n",
++ __func__, cpuid);
++ }
++
++ /*
++ * the boot CPU has finished the init stage and is spinning
++ * on callin_map until we finish. We are free to set up this
++ * CPU, first the APIC. (this is probably redundant on most
++ * boards)
++ */
++
++ Dprintk("CALLIN, before setup_local_APIC().\n");
++ smp_callin_clear_local_apic();
++ setup_local_APIC();
++ end_local_APIC_setup();
++ map_cpu_to_logical_apicid();
++
++ /*
++ * Get our bogomips.
++ *
++ * Need to enable IRQs because it can take longer and then
++ * the NMI watchdog might kill us.
++ */
++ local_irq_enable();
++ calibrate_delay();
++ local_irq_disable();
++ Dprintk("Stack at about %p\n", &cpuid);
++
++ /*
++ * Save our processor parameters
++ */
++ smp_store_cpu_info(cpuid);
++
++ /*
++ * Allow the master to continue.
++ */
++ cpu_set(cpuid, cpu_callin_map);
++}
++
++/*
++ * Activate a secondary processor.
++ */
++void __cpuinit start_secondary(void *unused)
++{
++ /*
++ * Don't put *anything* before cpu_init(), SMP booting is too
++ * fragile that we want to limit the things done here to the
++ * most necessary things.
++ */
++#ifdef CONFIG_VMI
++ vmi_bringup();
++#endif
++ cpu_init();
++ preempt_disable();
++ smp_callin();
++
++ /* otherwise gcc will move up smp_processor_id before the cpu_init */
++ barrier();
++ /*
++ * Check TSC synchronization with the BP:
++ */
++ check_tsc_sync_target();
++
++ if (nmi_watchdog == NMI_IO_APIC) {
++ disable_8259A_irq(0);
++ enable_NMI_through_LVT0();
++ enable_8259A_irq(0);
++ }
++
++ /* This must be done before setting cpu_online_map */
++ set_cpu_sibling_map(raw_smp_processor_id());
++ wmb();
++
++ /*
++ * We need to hold call_lock, so there is no inconsistency
++ * between the time smp_call_function() determines number of
++ * IPI recipients, and the time when the determination is made
++ * for which cpus receive the IPI. Holding this
++ * lock helps us to not include this cpu in a currently in progress
++ * smp_call_function().
++ */
++ lock_ipi_call_lock();
++#ifdef CONFIG_X86_64
++ spin_lock(&vector_lock);
++
++ /* Setup the per cpu irq handling data structures */
++ __setup_vector_irq(smp_processor_id());
++ /*
++ * Allow the master to continue.
++ */
++ spin_unlock(&vector_lock);
++#endif
++ cpu_set(smp_processor_id(), cpu_online_map);
++ unlock_ipi_call_lock();
++ per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
++
++ setup_secondary_clock();
++
++ wmb();
++ cpu_idle();
++}
++
++#ifdef CONFIG_X86_32
++/*
++ * Everything has been set up for the secondary
++ * CPUs - they just need to reload everything
++ * from the task structure
++ * This function must not return.
++ */
++void __devinit initialize_secondary(void)
++{
++ /*
++ * We don't actually need to load the full TSS,
++ * basically just the stack pointer and the ip.
++ */
++
++ asm volatile(
++ "movl %0,%%esp\n\t"
++ "jmp *%1"
++ :
++ :"m" (current->thread.sp), "m" (current->thread.ip));
++}
++#endif
++
++static void __cpuinit smp_apply_quirks(struct cpuinfo_x86 *c)
++{
++#ifdef CONFIG_X86_32
++ /*
++ * Mask B, Pentium, but not Pentium MMX
++ */
++ if (c->x86_vendor == X86_VENDOR_INTEL &&
++ c->x86 == 5 &&
++ c->x86_mask >= 1 && c->x86_mask <= 4 &&
++ c->x86_model <= 3)
++ /*
++ * Remember we have B step Pentia with bugs
++ */
++ smp_b_stepping = 1;
++
++ /*
++ * Certain Athlons might work (for various values of 'work') in SMP
++ * but they are not certified as MP capable.
++ */
++ if ((c->x86_vendor == X86_VENDOR_AMD) && (c->x86 == 6)) {
++
++ if (num_possible_cpus() == 1)
++ goto valid_k7;
++
++ /* Athlon 660/661 is valid. */
++ if ((c->x86_model == 6) && ((c->x86_mask == 0) ||
++ (c->x86_mask == 1)))
++ goto valid_k7;
++
++ /* Duron 670 is valid */
++ if ((c->x86_model == 7) && (c->x86_mask == 0))
++ goto valid_k7;
++
++ /*
++ * Athlon 662, Duron 671, and Athlon >model 7 have capability
++ * bit. It's worth noting that the A5 stepping (662) of some
++ * Athlon XP's have the MP bit set.
++ * See http://www.heise.de/newsticker/data/jow-18.10.01-000 for
++ * more.
++ */
++ if (((c->x86_model == 6) && (c->x86_mask >= 2)) ||
++ ((c->x86_model == 7) && (c->x86_mask >= 1)) ||
++ (c->x86_model > 7))
++ if (cpu_has_mp)
++ goto valid_k7;
++
++ /* If we get here, not a certified SMP capable AMD system. */
++ add_taint(TAINT_UNSAFE_SMP);
++ }
++
++valid_k7:
++ ;
++#endif
++}
++
++static void __cpuinit smp_checks(void)
++{
++ if (smp_b_stepping)
++ printk(KERN_WARNING "WARNING: SMP operation may be unreliable"
++ "with B stepping processors.\n");
++
++ /*
++ * Don't taint if we are running SMP kernel on a single non-MP
++ * approved Athlon
++ */
++ if (tainted & TAINT_UNSAFE_SMP) {
++ if (num_online_cpus())
++ printk(KERN_INFO "WARNING: This combination of AMD"
++ "processors is not suitable for SMP.\n");
++ else
++ tainted &= ~TAINT_UNSAFE_SMP;
++ }
++}
++
++/*
++ * The bootstrap kernel entry code has set these up. Save them for
++ * a given CPU
++ */
++
++void __cpuinit smp_store_cpu_info(int id)
++{
++ struct cpuinfo_x86 *c = &cpu_data(id);
++
++ *c = boot_cpu_data;
++ c->cpu_index = id;
++ if (id != 0)
++ identify_secondary_cpu(c);
++ smp_apply_quirks(c);
++}
++
++
++void __cpuinit set_cpu_sibling_map(int cpu)
++{
++ int i;
++ struct cpuinfo_x86 *c = &cpu_data(cpu);
++
++ cpu_set(cpu, cpu_sibling_setup_map);
++
++ if (smp_num_siblings > 1) {
++ for_each_cpu_mask(i, cpu_sibling_setup_map) {
++ if (c->phys_proc_id == cpu_data(i).phys_proc_id &&
++ c->cpu_core_id == cpu_data(i).cpu_core_id) {
++ cpu_set(i, per_cpu(cpu_sibling_map, cpu));
++ cpu_set(cpu, per_cpu(cpu_sibling_map, i));
++ cpu_set(i, per_cpu(cpu_core_map, cpu));
++ cpu_set(cpu, per_cpu(cpu_core_map, i));
++ cpu_set(i, c->llc_shared_map);
++ cpu_set(cpu, cpu_data(i).llc_shared_map);
++ }
++ }
++ } else {
++ cpu_set(cpu, per_cpu(cpu_sibling_map, cpu));
++ }
++
++ cpu_set(cpu, c->llc_shared_map);
++
++ if (current_cpu_data.x86_max_cores == 1) {
++ per_cpu(cpu_core_map, cpu) = per_cpu(cpu_sibling_map, cpu);
++ c->booted_cores = 1;
++ return;
++ }
++
++ for_each_cpu_mask(i, cpu_sibling_setup_map) {
++ if (per_cpu(cpu_llc_id, cpu) != BAD_APICID &&
++ per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) {
++ cpu_set(i, c->llc_shared_map);
++ cpu_set(cpu, cpu_data(i).llc_shared_map);
++ }
++ if (c->phys_proc_id == cpu_data(i).phys_proc_id) {
++ cpu_set(i, per_cpu(cpu_core_map, cpu));
++ cpu_set(cpu, per_cpu(cpu_core_map, i));
++ /*
++ * Does this new cpu bringup a new core?
++ */
++ if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1) {
++ /*
++ * for each core in package, increment
++ * the booted_cores for this new cpu
++ */
++ if (first_cpu(per_cpu(cpu_sibling_map, i)) == i)
++ c->booted_cores++;
++ /*
++ * increment the core count for all
++ * the other cpus in this package
++ */
++ if (i != cpu)
++ cpu_data(i).booted_cores++;
++ } else if (i != cpu && !c->booted_cores)
++ c->booted_cores = cpu_data(i).booted_cores;
++ }
++ }
++}
++
++/* maps the cpu to the sched domain representing multi-core */
++cpumask_t cpu_coregroup_map(int cpu)
++{
++ struct cpuinfo_x86 *c = &cpu_data(cpu);
++ /*
++ * For perf, we return last level cache shared map.
++ * And for power savings, we return cpu_core_map
++ */
++ if (sched_mc_power_savings || sched_smt_power_savings)
++ return per_cpu(cpu_core_map, cpu);
++ else
++ return c->llc_shared_map;
++}
++
++#ifdef CONFIG_X86_32
++/*
++ * We are called very early to get the low memory for the
++ * SMP bootup trampoline page.
++ */
++void __init smp_alloc_memory(void)
++{
++ trampoline_base = alloc_bootmem_low_pages(PAGE_SIZE);
++ /*
++ * Has to be in very low memory so we can execute
++ * real-mode AP code.
++ */
++ if (__pa(trampoline_base) >= 0x9F000)
++ BUG();
++}
++#endif
++
++static void impress_friends(void)
++{
++ int cpu;
++ unsigned long bogosum = 0;
++ /*
++ * Allow the user to impress friends.
++ */
++ Dprintk("Before bogomips.\n");
++ for_each_possible_cpu(cpu)
++ if (cpu_isset(cpu, cpu_callout_map))
++ bogosum += cpu_data(cpu).loops_per_jiffy;
++ printk(KERN_INFO
++ "Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
++ num_online_cpus(),
++ bogosum/(500000/HZ),
++ (bogosum/(5000/HZ))%100);
++
++ Dprintk("Before bogocount - setting activated=1.\n");
++}
++
++static inline void __inquire_remote_apic(int apicid)
++{
++ unsigned i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 };
++ char *names[] = { "ID", "VERSION", "SPIV" };
++ int timeout;
++ u32 status;
++
++ printk(KERN_INFO "Inquiring remote APIC #%d...\n", apicid);
++
++ for (i = 0; i < ARRAY_SIZE(regs); i++) {
++ printk(KERN_INFO "... APIC #%d %s: ", apicid, names[i]);
++
++ /*
++ * Wait for idle.
++ */
++ status = safe_apic_wait_icr_idle();
++ if (status)
++ printk(KERN_CONT
++ "a previous APIC delivery may have failed\n");
++
++ apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
++ apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]);
++
++ timeout = 0;
++ do {
++ udelay(100);
++ status = apic_read(APIC_ICR) & APIC_ICR_RR_MASK;
++ } while (status == APIC_ICR_RR_INPROG && timeout++ < 1000);
++
++ switch (status) {
++ case APIC_ICR_RR_VALID:
++ status = apic_read(APIC_RRR);
++ printk(KERN_CONT "%08x\n", status);
++ break;
++ default:
++ printk(KERN_CONT "failed\n");
++ }
++ }
++}
++
++#ifdef WAKE_SECONDARY_VIA_NMI
++/*
++ * Poke the other CPU in the eye via NMI to wake it up. Remember that the normal
++ * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this
++ * won't ... remember to clear down the APIC, etc later.
++ */
++static int __devinit
++wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
++{
++ unsigned long send_status, accept_status = 0;
++ int maxlvt;
++
++ /* Target chip */
++ apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(logical_apicid));
++
++ /* Boot on the stack */
++ /* Kick the second */
++ apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL);
++
++ Dprintk("Waiting for send to finish...\n");
++ send_status = safe_apic_wait_icr_idle();
++
++ /*
++ * Give the other CPU some time to accept the IPI.
++ */
++ udelay(200);
++ /*
++ * Due to the Pentium erratum 3AP.
++ */
++ maxlvt = lapic_get_maxlvt();
++ if (maxlvt > 3) {
++ apic_read_around(APIC_SPIV);
++ apic_write(APIC_ESR, 0);
++ }
++ accept_status = (apic_read(APIC_ESR) & 0xEF);
++ Dprintk("NMI sent.\n");
++
++ if (send_status)
++ printk(KERN_ERR "APIC never delivered???\n");
++ if (accept_status)
++ printk(KERN_ERR "APIC delivery error (%lx).\n", accept_status);
++
++ return (send_status | accept_status);
++}
++#endif /* WAKE_SECONDARY_VIA_NMI */
++
++#ifdef WAKE_SECONDARY_VIA_INIT
++static int __devinit
++wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
++{
++ unsigned long send_status, accept_status = 0;
++ int maxlvt, num_starts, j;
++
++ if (get_uv_system_type() == UV_NON_UNIQUE_APIC) {
++ send_status = uv_wakeup_secondary(phys_apicid, start_eip);
++ atomic_set(&init_deasserted, 1);
++ return send_status;
++ }
++
++ /*
++ * Be paranoid about clearing APIC errors.
++ */
++ if (APIC_INTEGRATED(apic_version[phys_apicid])) {
++ apic_read_around(APIC_SPIV);
++ apic_write(APIC_ESR, 0);
++ apic_read(APIC_ESR);
++ }
++
++ Dprintk("Asserting INIT.\n");
++
++ /*
++ * Turn INIT on target chip
++ */
++ apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
++
++ /*
++ * Send IPI
++ */
++ apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
++ | APIC_DM_INIT);
++
++ Dprintk("Waiting for send to finish...\n");
++ send_status = safe_apic_wait_icr_idle();
++
++ mdelay(10);
++
++ Dprintk("Deasserting INIT.\n");
++
++ /* Target chip */
++ apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
++
++ /* Send IPI */
++ apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
++
++ Dprintk("Waiting for send to finish...\n");
++ send_status = safe_apic_wait_icr_idle();
++
++ mb();
++ atomic_set(&init_deasserted, 1);
++
++ /*
++ * Should we send STARTUP IPIs ?
++ *
++ * Determine this based on the APIC version.
++ * If we don't have an integrated APIC, don't send the STARTUP IPIs.
++ */
++ if (APIC_INTEGRATED(apic_version[phys_apicid]))
++ num_starts = 2;
++ else
++ num_starts = 0;
++
++ /*
++ * Paravirt / VMI wants a startup IPI hook here to set up the
++ * target processor state.
++ */
++ startup_ipi_hook(phys_apicid, (unsigned long) start_secondary,
++#ifdef CONFIG_X86_64
++ (unsigned long)init_rsp);
++#else
++ (unsigned long)stack_start.sp);
++#endif
++
++ /*
++ * Run STARTUP IPI loop.
++ */
++ Dprintk("#startup loops: %d.\n", num_starts);
++
++ maxlvt = lapic_get_maxlvt();
++
++ for (j = 1; j <= num_starts; j++) {
++ Dprintk("Sending STARTUP #%d.\n", j);
++ apic_read_around(APIC_SPIV);
++ apic_write(APIC_ESR, 0);
++ apic_read(APIC_ESR);
++ Dprintk("After apic_write.\n");
++
++ /*
++ * STARTUP IPI
++ */
++
++ /* Target chip */
++ apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
++
++ /* Boot on the stack */
++ /* Kick the second */
++ apic_write_around(APIC_ICR, APIC_DM_STARTUP
++ | (start_eip >> 12));
++
++ /*
++ * Give the other CPU some time to accept the IPI.
++ */
++ udelay(300);
++
++ Dprintk("Startup point 1.\n");
++
++ Dprintk("Waiting for send to finish...\n");
++ send_status = safe_apic_wait_icr_idle();
++
++ /*
++ * Give the other CPU some time to accept the IPI.
++ */
++ udelay(200);
++ /*
++ * Due to the Pentium erratum 3AP.
++ */
++ if (maxlvt > 3) {
++ apic_read_around(APIC_SPIV);
++ apic_write(APIC_ESR, 0);
++ }
++ accept_status = (apic_read(APIC_ESR) & 0xEF);
++ if (send_status || accept_status)
++ break;
++ }
++ Dprintk("After Startup.\n");
++
++ if (send_status)
++ printk(KERN_ERR "APIC never delivered???\n");
++ if (accept_status)
++ printk(KERN_ERR "APIC delivery error (%lx).\n", accept_status);
++
++ return (send_status | accept_status);
++}
++#endif /* WAKE_SECONDARY_VIA_INIT */
++
++struct create_idle {
++ struct work_struct work;
++ struct task_struct *idle;
++ struct completion done;
++ int cpu;
++};
++
++static void __cpuinit do_fork_idle(struct work_struct *work)
++{
++ struct create_idle *c_idle =
++ container_of(work, struct create_idle, work);
++
++ c_idle->idle = fork_idle(c_idle->cpu);
++ complete(&c_idle->done);
++}
++
++static int __cpuinit do_boot_cpu(int apicid, int cpu)
++/*
++ * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
++ * (ie clustered apic addressing mode), this is a LOGICAL apic ID.
++ * Returns zero if CPU booted OK, else error code from wakeup_secondary_cpu.
++ */
++{
++ unsigned long boot_error = 0;
++ int timeout;
++ unsigned long start_ip;
++ unsigned short nmi_high = 0, nmi_low = 0;
++ struct create_idle c_idle = {
++ .cpu = cpu,
++ .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done),
++ };
++ INIT_WORK(&c_idle.work, do_fork_idle);
++#ifdef CONFIG_X86_64
++ /* allocate memory for gdts of secondary cpus. Hotplug is considered */
++ if (!cpu_gdt_descr[cpu].address &&
++ !(cpu_gdt_descr[cpu].address = get_zeroed_page(GFP_KERNEL))) {
++ printk(KERN_ERR "Failed to allocate GDT for CPU %d\n", cpu);
++ return -1;
++ }
++
++ /* Allocate node local memory for AP pdas */
++ if (cpu_pda(cpu) == &boot_cpu_pda[cpu]) {
++ struct x8664_pda *newpda, *pda;
++ int node = cpu_to_node(cpu);
++ pda = cpu_pda(cpu);
++ newpda = kmalloc_node(sizeof(struct x8664_pda), GFP_ATOMIC,
++ node);
++ if (newpda) {
++ memcpy(newpda, pda, sizeof(struct x8664_pda));
++ cpu_pda(cpu) = newpda;
++ } else
++ printk(KERN_ERR
++ "Could not allocate node local PDA for CPU %d on node %d\n",
++ cpu, node);
++ }
++#endif
++
++ alternatives_smp_switch(1);
++
++ c_idle.idle = get_idle_for_cpu(cpu);
++
++ /*
++ * We can't use kernel_thread since we must avoid to
++ * reschedule the child.
++ */
++ if (c_idle.idle) {
++ c_idle.idle->thread.sp = (unsigned long) (((struct pt_regs *)
++ (THREAD_SIZE + task_stack_page(c_idle.idle))) - 1);
++ init_idle(c_idle.idle, cpu);
++ goto do_rest;
++ }
++
++ if (!keventd_up() || current_is_keventd())
++ c_idle.work.func(&c_idle.work);
++ else {
++ schedule_work(&c_idle.work);
++ wait_for_completion(&c_idle.done);
++ }
++
++ if (IS_ERR(c_idle.idle)) {
++ printk("failed fork for CPU %d\n", cpu);
++ return PTR_ERR(c_idle.idle);
++ }
++
++ set_idle_for_cpu(cpu, c_idle.idle);
++do_rest:
++#ifdef CONFIG_X86_32
++ per_cpu(current_task, cpu) = c_idle.idle;
++ init_gdt(cpu);
++ early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
++ c_idle.idle->thread.ip = (unsigned long) start_secondary;
++ /* Stack for startup_32 can be just as for start_secondary onwards */
++ stack_start.sp = (void *) c_idle.idle->thread.sp;
++ irq_ctx_init(cpu);
++#else
++ cpu_pda(cpu)->pcurrent = c_idle.idle;
++ init_rsp = c_idle.idle->thread.sp;
++ load_sp0(&per_cpu(init_tss, cpu), &c_idle.idle->thread);
++ initial_code = (unsigned long)start_secondary;
++ clear_tsk_thread_flag(c_idle.idle, TIF_FORK);
++#endif
++
++ /* start_ip had better be page-aligned! */
++ start_ip = setup_trampoline();
++
++ /* So we see what's up */
++ printk(KERN_INFO "Booting processor %d/%d ip %lx\n",
++ cpu, apicid, start_ip);
++
++ /*
++ * This grunge runs the startup process for
++ * the targeted processor.
++ */
++
++ atomic_set(&init_deasserted, 0);
++
++ if (get_uv_system_type() != UV_NON_UNIQUE_APIC) {
++
++ Dprintk("Setting warm reset code and vector.\n");
++
++ store_NMI_vector(&nmi_high, &nmi_low);
++
++ smpboot_setup_warm_reset_vector(start_ip);
++ /*
++ * Be paranoid about clearing APIC errors.
++ */
++ apic_write(APIC_ESR, 0);
++ apic_read(APIC_ESR);
++ }
++
++ /*
++ * Starting actual IPI sequence...
++ */
++ boot_error = wakeup_secondary_cpu(apicid, start_ip);
++
++ if (!boot_error) {
++ /*
++ * allow APs to start initializing.
++ */
++ Dprintk("Before Callout %d.\n", cpu);
++ cpu_set(cpu, cpu_callout_map);
++ Dprintk("After Callout %d.\n", cpu);
++
++ /*
++ * Wait 5s total for a response
++ */
++ for (timeout = 0; timeout < 50000; timeout++) {
++ if (cpu_isset(cpu, cpu_callin_map))
++ break; /* It has booted */
++ udelay(100);
++ }
++
++ if (cpu_isset(cpu, cpu_callin_map)) {
++ /* number CPUs logically, starting from 1 (BSP is 0) */
++ Dprintk("OK.\n");
++ printk(KERN_INFO "CPU%d: ", cpu);
++ print_cpu_info(&cpu_data(cpu));
++ Dprintk("CPU has booted.\n");
++ } else {
++ boot_error = 1;
++ if (*((volatile unsigned char *)trampoline_base)
++ == 0xA5)
++ /* trampoline started but...? */
++ printk(KERN_ERR "Stuck ??\n");
++ else
++ /* trampoline code not run */
++ printk(KERN_ERR "Not responding.\n");
++ if (get_uv_system_type() != UV_NON_UNIQUE_APIC)
++ inquire_remote_apic(apicid);
++ }
++ }
++
++ if (boot_error) {
++ /* Try to put things back the way they were before ... */
++ unmap_cpu_to_logical_apicid(cpu);
++#ifdef CONFIG_X86_64
++ clear_node_cpumask(cpu); /* was set by numa_add_cpu */
++#endif
++ cpu_clear(cpu, cpu_callout_map); /* was set by do_boot_cpu() */
++ cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */
++ cpu_clear(cpu, cpu_possible_map);
++ cpu_clear(cpu, cpu_present_map);
++ per_cpu(x86_cpu_to_apicid, cpu) = BAD_APICID;
++ }
++
++ /* mark "stuck" area as not stuck */
++ *((volatile unsigned long *)trampoline_base) = 0;
++
++ /*
++ * Cleanup possible dangling ends...
++ */
++ smpboot_restore_warm_reset_vector();
++
++ return boot_error;
++}
++
++int __cpuinit native_cpu_up(unsigned int cpu)
++{
++ int apicid = cpu_present_to_apicid(cpu);
++ unsigned long flags;
++ int err;
++
++ WARN_ON(irqs_disabled());
++
++ Dprintk("++++++++++++++++++++=_---CPU UP %u\n", cpu);
++
++ if (apicid == BAD_APICID || apicid == boot_cpu_physical_apicid ||
++ !physid_isset(apicid, phys_cpu_present_map)) {
++ printk(KERN_ERR "%s: bad cpu %d\n", __func__, cpu);
++ return -EINVAL;
++ }
++
++ /*
++ * Already booted CPU?
++ */
++ if (cpu_isset(cpu, cpu_callin_map)) {
++ Dprintk("do_boot_cpu %d Already started\n", cpu);
++ return -ENOSYS;
++ }
++
++ /*
++ * Save current MTRR state in case it was changed since early boot
++ * (e.g. by the ACPI SMI) to initialize new CPUs with MTRRs in sync:
++ */
++ mtrr_save_state();
++
++ per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
++
++#ifdef CONFIG_X86_32
++ /* init low mem mapping */
++ clone_pgd_range(swapper_pg_dir, swapper_pg_dir + KERNEL_PGD_BOUNDARY,
++ min_t(unsigned long, KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY));
++ flush_tlb_all();
++#endif
++
++ err = do_boot_cpu(apicid, cpu);
++ if (err < 0) {
++ Dprintk("do_boot_cpu failed %d\n", err);
++ return err;
++ }
++
++ /*
++ * Check TSC synchronization with the AP (keep irqs disabled
++ * while doing so):
++ */
++ local_irq_save(flags);
++ check_tsc_sync_source(cpu);
++ local_irq_restore(flags);
++
++ while (!cpu_online(cpu)) {
++ cpu_relax();
++ touch_nmi_watchdog();
++ }
++
++ return 0;
++}
++
++/*
++ * Fall back to non SMP mode after errors.
++ *
++ * RED-PEN audit/test this more. I bet there is more state messed up here.
++ */
++static __init void disable_smp(void)
++{
++ cpu_present_map = cpumask_of_cpu(0);
++ cpu_possible_map = cpumask_of_cpu(0);
++#ifdef CONFIG_X86_32
++ smpboot_clear_io_apic_irqs();
++#endif
++ if (smp_found_config)
++ phys_cpu_present_map =
++ physid_mask_of_physid(boot_cpu_physical_apicid);
++ else
++ phys_cpu_present_map = physid_mask_of_physid(0);
++ map_cpu_to_logical_apicid();
++ cpu_set(0, per_cpu(cpu_sibling_map, 0));
++ cpu_set(0, per_cpu(cpu_core_map, 0));
++}
++
++/*
++ * Various sanity checks.
++ */
++static int __init smp_sanity_check(unsigned max_cpus)
++{
++ preempt_disable();
++ if (!physid_isset(hard_smp_processor_id(), phys_cpu_present_map)) {
++ printk(KERN_WARNING "weird, boot CPU (#%d) not listed"
++ "by the BIOS.\n", hard_smp_processor_id());
++ physid_set(hard_smp_processor_id(), phys_cpu_present_map);
++ }
++
++ /*
++ * If we couldn't find an SMP configuration at boot time,
++ * get out of here now!
++ */
++ if (!smp_found_config && !acpi_lapic) {
++ preempt_enable();
++ printk(KERN_NOTICE "SMP motherboard not detected.\n");
++ disable_smp();
++ if (APIC_init_uniprocessor())
++ printk(KERN_NOTICE "Local APIC not detected."
++ " Using dummy APIC emulation.\n");
++ return -1;
++ }
++
++ /*
++ * Should not be necessary because the MP table should list the boot
++ * CPU too, but we do it for the sake of robustness anyway.
++ */
++ if (!check_phys_apicid_present(boot_cpu_physical_apicid)) {
++ printk(KERN_NOTICE
++ "weird, boot CPU (#%d) not listed by the BIOS.\n",
++ boot_cpu_physical_apicid);
++ physid_set(hard_smp_processor_id(), phys_cpu_present_map);
++ }
++ preempt_enable();
++
++ /*
++ * If we couldn't find a local APIC, then get out of here now!
++ */
++ if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) &&
++ !cpu_has_apic) {
++ printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
++ boot_cpu_physical_apicid);
++ printk(KERN_ERR "... forcing use of dummy APIC emulation."
++ "(tell your hw vendor)\n");
++ smpboot_clear_io_apic();
++ return -1;
++ }
++
++ verify_local_APIC();
++
++ /*
++ * If SMP should be disabled, then really disable it!
++ */
++ if (!max_cpus) {
++ printk(KERN_INFO "SMP mode deactivated,"
++ "forcing use of dummy APIC emulation.\n");
++ smpboot_clear_io_apic();
++#ifdef CONFIG_X86_32
++ if (nmi_watchdog == NMI_LOCAL_APIC) {
++ printk(KERN_INFO "activating minimal APIC for"
++ "NMI watchdog use.\n");
++ connect_bsp_APIC();
++ setup_local_APIC();
++ end_local_APIC_setup();
++ }
++#endif
++ return -1;
++ }
++
++ return 0;
++}
++
++static void __init smp_cpu_index_default(void)
++{
++ int i;
++ struct cpuinfo_x86 *c;
++
++ for_each_possible_cpu(i) {
++ c = &cpu_data(i);
++ /* mark all to hotplug */
++ c->cpu_index = NR_CPUS;
++ }
++}
++
++/*
++ * Prepare for SMP bootup. The MP table or ACPI has been read
++ * earlier. Just do some sanity checking here and enable APIC mode.
++ */
++void __init native_smp_prepare_cpus(unsigned int max_cpus)
++{
++ nmi_watchdog_default();
++ smp_cpu_index_default();
++ current_cpu_data = boot_cpu_data;
++ cpu_callin_map = cpumask_of_cpu(0);
++ mb();
++ /*
++ * Setup boot CPU information
++ */
++ smp_store_cpu_info(0); /* Final full version of the data */
++ boot_cpu_logical_apicid = logical_smp_processor_id();
++ current_thread_info()->cpu = 0; /* needed? */
++ set_cpu_sibling_map(0);
++
++ if (smp_sanity_check(max_cpus) < 0) {
++ printk(KERN_INFO "SMP disabled\n");
++ disable_smp();
++ return;
++ }
++
++ preempt_disable();
++ if (GET_APIC_ID(read_apic_id()) != boot_cpu_physical_apicid) {
++ panic("Boot APIC ID in local APIC unexpected (%d vs %d)",
++ GET_APIC_ID(read_apic_id()), boot_cpu_physical_apicid);
++ /* Or can we switch back to PIC here? */
++ }
++ preempt_enable();
++
++#ifdef CONFIG_X86_32
++ connect_bsp_APIC();
++#endif
++ /*
++ * Switch from PIC to APIC mode.
++ */
++ setup_local_APIC();
++
++#ifdef CONFIG_X86_64
++ /*
++ * Enable IO APIC before setting up error vector
++ */
++ if (!skip_ioapic_setup && nr_ioapics)
++ enable_IO_APIC();
++#endif
++ end_local_APIC_setup();
++
++ map_cpu_to_logical_apicid();
++
++ setup_portio_remap();
++
++ smpboot_setup_io_apic();
++ /*
++ * Set up local APIC timer on boot CPU.
++ */
++
++ printk(KERN_INFO "CPU%d: ", 0);
++ print_cpu_info(&cpu_data(0));
++ setup_boot_clock();
++}
++/*
++ * Early setup to make printk work.
++ */
++void __init native_smp_prepare_boot_cpu(void)
++{
++ int me = smp_processor_id();
++#ifdef CONFIG_X86_32
++ init_gdt(me);
++ switch_to_new_gdt();
++#endif
++ /* already set me in cpu_online_map in boot_cpu_init() */
++ cpu_set(me, cpu_callout_map);
++ per_cpu(cpu_state, me) = CPU_ONLINE;
++}
++
++void __init native_smp_cpus_done(unsigned int max_cpus)
++{
++ Dprintk("Boot done.\n");
++
++ impress_friends();
++ smp_checks();
++#ifdef CONFIG_X86_IO_APIC
++ setup_ioapic_dest();
++#endif
++ check_nmi_watchdog();
++#ifdef CONFIG_X86_32
++ zap_low_mappings();
++#endif
++}
++
++#ifdef CONFIG_HOTPLUG_CPU
++
++# ifdef CONFIG_X86_32
++void cpu_exit_clear(void)
++{
++ int cpu = raw_smp_processor_id();
++
++ idle_task_exit();
++
++ cpu_uninit();
++ irq_ctx_exit(cpu);
++
++ cpu_clear(cpu, cpu_callout_map);
++ cpu_clear(cpu, cpu_callin_map);
++
++ unmap_cpu_to_logical_apicid(cpu);
++}
++# endif /* CONFIG_X86_32 */
++
++static void remove_siblinginfo(int cpu)
++{
++ int sibling;
++ struct cpuinfo_x86 *c = &cpu_data(cpu);
++
++ for_each_cpu_mask(sibling, per_cpu(cpu_core_map, cpu)) {
++ cpu_clear(cpu, per_cpu(cpu_core_map, sibling));
++ /*/
++ * last thread sibling in this cpu core going down
++ */
++ if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1)
++ cpu_data(sibling).booted_cores--;
++ }
++
++ for_each_cpu_mask(sibling, per_cpu(cpu_sibling_map, cpu))
++ cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling));
++ cpus_clear(per_cpu(cpu_sibling_map, cpu));
++ cpus_clear(per_cpu(cpu_core_map, cpu));
++ c->phys_proc_id = 0;
++ c->cpu_core_id = 0;
++ cpu_clear(cpu, cpu_sibling_setup_map);
++}
++
++int additional_cpus __initdata = -1;
++
++static __init int setup_additional_cpus(char *s)
++{
++ return s && get_option(&s, &additional_cpus) ? 0 : -EINVAL;
++}
++early_param("additional_cpus", setup_additional_cpus);
++
++/*
++ * cpu_possible_map should be static, it cannot change as cpu's
++ * are onlined, or offlined. The reason is per-cpu data-structures
++ * are allocated by some modules at init time, and dont expect to
++ * do this dynamically on cpu arrival/departure.
++ * cpu_present_map on the other hand can change dynamically.
++ * In case when cpu_hotplug is not compiled, then we resort to current
++ * behaviour, which is cpu_possible == cpu_present.
++ * - Ashok Raj
++ *
++ * Three ways to find out the number of additional hotplug CPUs:
++ * - If the BIOS specified disabled CPUs in ACPI/mptables use that.
++ * - The user can overwrite it with additional_cpus=NUM
++ * - Otherwise don't reserve additional CPUs.
++ * We do this because additional CPUs waste a lot of memory.
++ * -AK
++ */
++__init void prefill_possible_map(void)
++{
++ int i;
++ int possible;
++
++ if (additional_cpus == -1) {
++ if (disabled_cpus > 0)
++ additional_cpus = disabled_cpus;
++ else
++ additional_cpus = 0;
++ }
++ possible = num_processors + additional_cpus;
++ if (possible > NR_CPUS)
++ possible = NR_CPUS;
++
++ printk(KERN_INFO "SMP: Allowing %d CPUs, %d hotplug CPUs\n",
++ possible, max_t(int, possible - num_processors, 0));
++
++ for (i = 0; i < possible; i++)
++ cpu_set(i, cpu_possible_map);
++}
++
++static void __ref remove_cpu_from_maps(int cpu)
++{
++ cpu_clear(cpu, cpu_online_map);
++#ifdef CONFIG_X86_64
++ cpu_clear(cpu, cpu_callout_map);
++ cpu_clear(cpu, cpu_callin_map);
++ /* was set by cpu_init() */
++ clear_bit(cpu, (unsigned long *)&cpu_initialized);
++ clear_node_cpumask(cpu);
++#endif
++}
++
++int __cpu_disable(void)
++{
++ int cpu = smp_processor_id();
++
++ /*
++ * Perhaps use cpufreq to drop frequency, but that could go
++ * into generic code.
++ *
++ * We won't take down the boot processor on i386 due to some
++ * interrupts only being able to be serviced by the BSP.
++ * Especially so if we're not using an IOAPIC -zwane
++ */
++ if (cpu == 0)
++ return -EBUSY;
++
++ if (nmi_watchdog == NMI_LOCAL_APIC)
++ stop_apic_nmi_watchdog(NULL);
++ clear_local_APIC();
++
++ /*
++ * HACK:
++ * Allow any queued timer interrupts to get serviced
++ * This is only a temporary solution until we cleanup
++ * fixup_irqs as we do for IA64.
++ */
++ local_irq_enable();
++ mdelay(1);
++
++ local_irq_disable();
++ remove_siblinginfo(cpu);
++
++ /* It's now safe to remove this processor from the online map */
++ remove_cpu_from_maps(cpu);
++ fixup_irqs(cpu_online_map);
++ return 0;
++}
++
++void __cpu_die(unsigned int cpu)
++{
++ /* We don't do anything here: idle task is faking death itself. */
++ unsigned int i;
++
++ for (i = 0; i < 10; i++) {
++ /* They ack this in play_dead by setting CPU_DEAD */
++ if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
++ printk(KERN_INFO "CPU %d is now offline\n", cpu);
++ if (1 == num_online_cpus())
++ alternatives_smp_switch(0);
++ return;
++ }
++ msleep(100);
++ }
++ printk(KERN_ERR "CPU %u didn't die...\n", cpu);
++}
++#else /* ... !CONFIG_HOTPLUG_CPU */
++int __cpu_disable(void)
++{
++ return -ENOSYS;
++}
++
++void __cpu_die(unsigned int cpu)
++{
++ /* We said "no" in __cpu_disable */
++ BUG();
++}
++#endif
++
++/*
++ * If the BIOS enumerates physical processors before logical,
++ * maxcpus=N at enumeration-time can be used to disable HT.
++ */
++static int __init parse_maxcpus(char *arg)
++{
++ extern unsigned int maxcpus;
++
++ maxcpus = simple_strtoul(arg, NULL, 0);
++ return 0;
++}
++early_param("maxcpus", parse_maxcpus);
+diff --git a/arch/x86/kernel/smpboot_32.c b/arch/x86/kernel/smpboot_32.c
+deleted file mode 100644
+index 579b9b7..0000000
+--- a/arch/x86/kernel/smpboot_32.c
++++ /dev/null
+@@ -1,1320 +0,0 @@
+-/*
+- * x86 SMP booting functions
+- *
+- * (c) 1995 Alan Cox, Building #3 <alan at redhat.com>
+- * (c) 1998, 1999, 2000 Ingo Molnar <mingo at redhat.com>
+- *
+- * Much of the core SMP work is based on previous work by Thomas Radke, to
+- * whom a great many thanks are extended.
+- *
+- * Thanks to Intel for making available several different Pentium,
+- * Pentium Pro and Pentium-II/Xeon MP machines.
+- * Original development of Linux SMP code supported by Caldera.
+- *
+- * This code is released under the GNU General Public License version 2 or
+- * later.
+- *
+- * Fixes
+- * Felix Koop : NR_CPUS used properly
+- * Jose Renau : Handle single CPU case.
+- * Alan Cox : By repeated request 8) - Total BogoMIPS report.
+- * Greg Wright : Fix for kernel stacks panic.
+- * Erich Boleyn : MP v1.4 and additional changes.
+- * Matthias Sattler : Changes for 2.1 kernel map.
+- * Michel Lespinasse : Changes for 2.1 kernel map.
+- * Michael Chastain : Change trampoline.S to gnu as.
+- * Alan Cox : Dumb bug: 'B' step PPro's are fine
+- * Ingo Molnar : Added APIC timers, based on code
+- * from Jose Renau
+- * Ingo Molnar : various cleanups and rewrites
+- * Tigran Aivazian : fixed "0.00 in /proc/uptime on SMP" bug.
+- * Maciej W. Rozycki : Bits for genuine 82489DX APICs
+- * Martin J. Bligh : Added support for multi-quad systems
+- * Dave Jones : Report invalid combinations of Athlon CPUs.
+-* Rusty Russell : Hacked into shape for new "hotplug" boot process. */
+-
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/kernel.h>
+-
+-#include <linux/mm.h>
+-#include <linux/sched.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/bootmem.h>
+-#include <linux/notifier.h>
+-#include <linux/cpu.h>
+-#include <linux/percpu.h>
+-#include <linux/nmi.h>
+-
+-#include <linux/delay.h>
+-#include <linux/mc146818rtc.h>
+-#include <asm/tlbflush.h>
+-#include <asm/desc.h>
+-#include <asm/arch_hooks.h>
+-#include <asm/nmi.h>
+-
+-#include <mach_apic.h>
+-#include <mach_wakecpu.h>
+-#include <smpboot_hooks.h>
+-#include <asm/vmi.h>
+-#include <asm/mtrr.h>
+-
+-/* Set if we find a B stepping CPU */
+-static int __cpuinitdata smp_b_stepping;
+-
+-/* Number of siblings per CPU package */
+-int smp_num_siblings = 1;
+-EXPORT_SYMBOL(smp_num_siblings);
+-
+-/* Last level cache ID of each logical CPU */
+-DEFINE_PER_CPU(u8, cpu_llc_id) = BAD_APICID;
+-
+-/* representing HT siblings of each logical CPU */
+-DEFINE_PER_CPU(cpumask_t, cpu_sibling_map);
+-EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
+-
+-/* representing HT and core siblings of each logical CPU */
+-DEFINE_PER_CPU(cpumask_t, cpu_core_map);
+-EXPORT_PER_CPU_SYMBOL(cpu_core_map);
+-
+-/* bitmap of online cpus */
+-cpumask_t cpu_online_map __read_mostly;
+-EXPORT_SYMBOL(cpu_online_map);
+-
+-cpumask_t cpu_callin_map;
+-cpumask_t cpu_callout_map;
+-cpumask_t cpu_possible_map;
+-EXPORT_SYMBOL(cpu_possible_map);
+-static cpumask_t smp_commenced_mask;
+-
+-/* Per CPU bogomips and other parameters */
+-DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
+-EXPORT_PER_CPU_SYMBOL(cpu_info);
+-
+-/* which logical CPU number maps to which CPU (physical APIC ID) */
+-u8 x86_cpu_to_apicid_init[NR_CPUS] __initdata =
+- { [0 ... NR_CPUS-1] = BAD_APICID };
+-void *x86_cpu_to_apicid_early_ptr;
+-DEFINE_PER_CPU(u8, x86_cpu_to_apicid) = BAD_APICID;
+-EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid);
+-
+-u8 apicid_2_node[MAX_APICID];
+-
+-/*
+- * Trampoline 80x86 program as an array.
+- */
+-
+-extern const unsigned char trampoline_data [];
+-extern const unsigned char trampoline_end [];
+-static unsigned char *trampoline_base;
+-
+-static void map_cpu_to_logical_apicid(void);
+-
+-/* State of each CPU. */
+-DEFINE_PER_CPU(int, cpu_state) = { 0 };
+-
+-/*
+- * Currently trivial. Write the real->protected mode
+- * bootstrap into the page concerned. The caller
+- * has made sure it's suitably aligned.
+- */
+-
+-static unsigned long __cpuinit setup_trampoline(void)
+-{
+- memcpy(trampoline_base, trampoline_data, trampoline_end - trampoline_data);
+- return virt_to_phys(trampoline_base);
+-}
+-
+-/*
+- * We are called very early to get the low memory for the
+- * SMP bootup trampoline page.
+- */
+-void __init smp_alloc_memory(void)
+-{
+- trampoline_base = alloc_bootmem_low_pages(PAGE_SIZE);
+- /*
+- * Has to be in very low memory so we can execute
+- * real-mode AP code.
+- */
+- if (__pa(trampoline_base) >= 0x9F000)
+- BUG();
+-}
+-
+-/*
+- * The bootstrap kernel entry code has set these up. Save them for
+- * a given CPU
+- */
+-
+-void __cpuinit smp_store_cpu_info(int id)
+-{
+- struct cpuinfo_x86 *c = &cpu_data(id);
+-
+- *c = boot_cpu_data;
+- c->cpu_index = id;
+- if (id!=0)
+- identify_secondary_cpu(c);
+- /*
+- * Mask B, Pentium, but not Pentium MMX
+- */
+- if (c->x86_vendor == X86_VENDOR_INTEL &&
+- c->x86 == 5 &&
+- c->x86_mask >= 1 && c->x86_mask <= 4 &&
+- c->x86_model <= 3)
+- /*
+- * Remember we have B step Pentia with bugs
+- */
+- smp_b_stepping = 1;
+-
+- /*
+- * Certain Athlons might work (for various values of 'work') in SMP
+- * but they are not certified as MP capable.
+- */
+- if ((c->x86_vendor == X86_VENDOR_AMD) && (c->x86 == 6)) {
+-
+- if (num_possible_cpus() == 1)
+- goto valid_k7;
+-
+- /* Athlon 660/661 is valid. */
+- if ((c->x86_model==6) && ((c->x86_mask==0) || (c->x86_mask==1)))
+- goto valid_k7;
+-
+- /* Duron 670 is valid */
+- if ((c->x86_model==7) && (c->x86_mask==0))
+- goto valid_k7;
+-
+- /*
+- * Athlon 662, Duron 671, and Athlon >model 7 have capability bit.
+- * It's worth noting that the A5 stepping (662) of some Athlon XP's
+- * have the MP bit set.
+- * See http://www.heise.de/newsticker/data/jow-18.10.01-000 for more.
+- */
+- if (((c->x86_model==6) && (c->x86_mask>=2)) ||
+- ((c->x86_model==7) && (c->x86_mask>=1)) ||
+- (c->x86_model> 7))
+- if (cpu_has_mp)
+- goto valid_k7;
+-
+- /* If we get here, it's not a certified SMP capable AMD system. */
+- add_taint(TAINT_UNSAFE_SMP);
+- }
+-
+-valid_k7:
+- ;
+-}
+-
+-static atomic_t init_deasserted;
+-
+-static void __cpuinit smp_callin(void)
+-{
+- int cpuid, phys_id;
+- unsigned long timeout;
+-
+- /*
+- * If waken up by an INIT in an 82489DX configuration
+- * we may get here before an INIT-deassert IPI reaches
+- * our local APIC. We have to wait for the IPI or we'll
+- * lock up on an APIC access.
+- */
+- wait_for_init_deassert(&init_deasserted);
+-
+- /*
+- * (This works even if the APIC is not enabled.)
+- */
+- phys_id = GET_APIC_ID(apic_read(APIC_ID));
+- cpuid = smp_processor_id();
+- if (cpu_isset(cpuid, cpu_callin_map)) {
+- printk("huh, phys CPU#%d, CPU#%d already present??\n",
+- phys_id, cpuid);
+- BUG();
+- }
+- Dprintk("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id);
+-
+- /*
+- * STARTUP IPIs are fragile beasts as they might sometimes
+- * trigger some glue motherboard logic. Complete APIC bus
+- * silence for 1 second, this overestimates the time the
+- * boot CPU is spending to send the up to 2 STARTUP IPIs
+- * by a factor of two. This should be enough.
+- */
+-
+- /*
+- * Waiting 2s total for startup (udelay is not yet working)
+- */
+- timeout = jiffies + 2*HZ;
+- while (time_before(jiffies, timeout)) {
+- /*
+- * Has the boot CPU finished it's STARTUP sequence?
+- */
+- if (cpu_isset(cpuid, cpu_callout_map))
+- break;
+- rep_nop();
+- }
+-
+- if (!time_before(jiffies, timeout)) {
+- printk("BUG: CPU%d started up but did not get a callout!\n",
+- cpuid);
+- BUG();
+- }
+-
+- /*
+- * the boot CPU has finished the init stage and is spinning
+- * on callin_map until we finish. We are free to set up this
+- * CPU, first the APIC. (this is probably redundant on most
+- * boards)
+- */
+-
+- Dprintk("CALLIN, before setup_local_APIC().\n");
+- smp_callin_clear_local_apic();
+- setup_local_APIC();
+- map_cpu_to_logical_apicid();
+-
+- /*
+- * Get our bogomips.
+- */
+- calibrate_delay();
+- Dprintk("Stack at about %p\n",&cpuid);
+-
+- /*
+- * Save our processor parameters
+- */
+- smp_store_cpu_info(cpuid);
+-
+- /*
+- * Allow the master to continue.
+- */
+- cpu_set(cpuid, cpu_callin_map);
+-}
+-
+-static int cpucount;
+-
+-/* maps the cpu to the sched domain representing multi-core */
+-cpumask_t cpu_coregroup_map(int cpu)
+-{
+- struct cpuinfo_x86 *c = &cpu_data(cpu);
+- /*
+- * For perf, we return last level cache shared map.
+- * And for power savings, we return cpu_core_map
+- */
+- if (sched_mc_power_savings || sched_smt_power_savings)
+- return per_cpu(cpu_core_map, cpu);
+- else
+- return c->llc_shared_map;
+-}
+-
+-/* representing cpus for which sibling maps can be computed */
+-static cpumask_t cpu_sibling_setup_map;
+-
+-void __cpuinit set_cpu_sibling_map(int cpu)
+-{
+- int i;
+- struct cpuinfo_x86 *c = &cpu_data(cpu);
+-
+- cpu_set(cpu, cpu_sibling_setup_map);
+-
+- if (smp_num_siblings > 1) {
+- for_each_cpu_mask(i, cpu_sibling_setup_map) {
+- if (c->phys_proc_id == cpu_data(i).phys_proc_id &&
+- c->cpu_core_id == cpu_data(i).cpu_core_id) {
+- cpu_set(i, per_cpu(cpu_sibling_map, cpu));
+- cpu_set(cpu, per_cpu(cpu_sibling_map, i));
+- cpu_set(i, per_cpu(cpu_core_map, cpu));
+- cpu_set(cpu, per_cpu(cpu_core_map, i));
+- cpu_set(i, c->llc_shared_map);
+- cpu_set(cpu, cpu_data(i).llc_shared_map);
+- }
+- }
+- } else {
+- cpu_set(cpu, per_cpu(cpu_sibling_map, cpu));
+- }
+-
+- cpu_set(cpu, c->llc_shared_map);
+-
+- if (current_cpu_data.x86_max_cores == 1) {
+- per_cpu(cpu_core_map, cpu) = per_cpu(cpu_sibling_map, cpu);
+- c->booted_cores = 1;
+- return;
+- }
+-
+- for_each_cpu_mask(i, cpu_sibling_setup_map) {
+- if (per_cpu(cpu_llc_id, cpu) != BAD_APICID &&
+- per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) {
+- cpu_set(i, c->llc_shared_map);
+- cpu_set(cpu, cpu_data(i).llc_shared_map);
+- }
+- if (c->phys_proc_id == cpu_data(i).phys_proc_id) {
+- cpu_set(i, per_cpu(cpu_core_map, cpu));
+- cpu_set(cpu, per_cpu(cpu_core_map, i));
+- /*
+- * Does this new cpu bringup a new core?
+- */
+- if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1) {
+- /*
+- * for each core in package, increment
+- * the booted_cores for this new cpu
+- */
+- if (first_cpu(per_cpu(cpu_sibling_map, i)) == i)
+- c->booted_cores++;
+- /*
+- * increment the core count for all
+- * the other cpus in this package
+- */
+- if (i != cpu)
+- cpu_data(i).booted_cores++;
+- } else if (i != cpu && !c->booted_cores)
+- c->booted_cores = cpu_data(i).booted_cores;
+- }
+- }
+-}
+-
+-/*
+- * Activate a secondary processor.
+- */
+-static void __cpuinit start_secondary(void *unused)
+-{
+- /*
+- * Don't put *anything* before cpu_init(), SMP booting is too
+- * fragile that we want to limit the things done here to the
+- * most necessary things.
+- */
+-#ifdef CONFIG_VMI
+- vmi_bringup();
+-#endif
+- cpu_init();
+- preempt_disable();
+- smp_callin();
+- while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
+- rep_nop();
+- /*
+- * Check TSC synchronization with the BP:
+- */
+- check_tsc_sync_target();
+-
+- setup_secondary_clock();
+- if (nmi_watchdog == NMI_IO_APIC) {
+- disable_8259A_irq(0);
+- enable_NMI_through_LVT0();
+- enable_8259A_irq(0);
+- }
+- /*
+- * low-memory mappings have been cleared, flush them from
+- * the local TLBs too.
+- */
+- local_flush_tlb();
+-
+- /* This must be done before setting cpu_online_map */
+- set_cpu_sibling_map(raw_smp_processor_id());
+- wmb();
+-
+- /*
+- * We need to hold call_lock, so there is no inconsistency
+- * between the time smp_call_function() determines number of
+- * IPI recipients, and the time when the determination is made
+- * for which cpus receive the IPI. Holding this
+- * lock helps us to not include this cpu in a currently in progress
+- * smp_call_function().
+- */
+- lock_ipi_call_lock();
+- cpu_set(smp_processor_id(), cpu_online_map);
+- unlock_ipi_call_lock();
+- per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
+-
+- /* We can take interrupts now: we're officially "up". */
+- local_irq_enable();
+-
+- wmb();
+- cpu_idle();
+-}
+-
+-/*
+- * Everything has been set up for the secondary
+- * CPUs - they just need to reload everything
+- * from the task structure
+- * This function must not return.
+- */
+-void __devinit initialize_secondary(void)
+-{
+- /*
+- * We don't actually need to load the full TSS,
+- * basically just the stack pointer and the ip.
+- */
+-
+- asm volatile(
+- "movl %0,%%esp\n\t"
+- "jmp *%1"
+- :
+- :"m" (current->thread.sp),"m" (current->thread.ip));
+-}
+-
+-/* Static state in head.S used to set up a CPU */
+-extern struct {
+- void * sp;
+- unsigned short ss;
+-} stack_start;
+-
+-#ifdef CONFIG_NUMA
+-
+-/* which logical CPUs are on which nodes */
+-cpumask_t node_to_cpumask_map[MAX_NUMNODES] __read_mostly =
+- { [0 ... MAX_NUMNODES-1] = CPU_MASK_NONE };
+-EXPORT_SYMBOL(node_to_cpumask_map);
+-/* which node each logical CPU is on */
+-int cpu_to_node_map[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = 0 };
+-EXPORT_SYMBOL(cpu_to_node_map);
+-
+-/* set up a mapping between cpu and node. */
+-static inline void map_cpu_to_node(int cpu, int node)
+-{
+- printk("Mapping cpu %d to node %d\n", cpu, node);
+- cpu_set(cpu, node_to_cpumask_map[node]);
+- cpu_to_node_map[cpu] = node;
+-}
+-
+-/* undo a mapping between cpu and node. */
+-static inline void unmap_cpu_to_node(int cpu)
+-{
+- int node;
+-
+- printk("Unmapping cpu %d from all nodes\n", cpu);
+- for (node = 0; node < MAX_NUMNODES; node ++)
+- cpu_clear(cpu, node_to_cpumask_map[node]);
+- cpu_to_node_map[cpu] = 0;
+-}
+-#else /* !CONFIG_NUMA */
+-
+-#define map_cpu_to_node(cpu, node) ({})
+-#define unmap_cpu_to_node(cpu) ({})
+-
+-#endif /* CONFIG_NUMA */
+-
+-u8 cpu_2_logical_apicid[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
+-
+-static void map_cpu_to_logical_apicid(void)
+-{
+- int cpu = smp_processor_id();
+- int apicid = logical_smp_processor_id();
+- int node = apicid_to_node(apicid);
+-
+- if (!node_online(node))
+- node = first_online_node;
+-
+- cpu_2_logical_apicid[cpu] = apicid;
+- map_cpu_to_node(cpu, node);
+-}
+-
+-static void unmap_cpu_to_logical_apicid(int cpu)
+-{
+- cpu_2_logical_apicid[cpu] = BAD_APICID;
+- unmap_cpu_to_node(cpu);
+-}
+-
+-static inline void __inquire_remote_apic(int apicid)
+-{
+- int i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 };
+- char *names[] = { "ID", "VERSION", "SPIV" };
+- int timeout;
+- unsigned long status;
+-
+- printk("Inquiring remote APIC #%d...\n", apicid);
+-
+- for (i = 0; i < ARRAY_SIZE(regs); i++) {
+- printk("... APIC #%d %s: ", apicid, names[i]);
+-
+- /*
+- * Wait for idle.
+- */
+- status = safe_apic_wait_icr_idle();
+- if (status)
+- printk("a previous APIC delivery may have failed\n");
+-
+- apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
+- apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]);
+-
+- timeout = 0;
+- do {
+- udelay(100);
+- status = apic_read(APIC_ICR) & APIC_ICR_RR_MASK;
+- } while (status == APIC_ICR_RR_INPROG && timeout++ < 1000);
+-
+- switch (status) {
+- case APIC_ICR_RR_VALID:
+- status = apic_read(APIC_RRR);
+- printk("%lx\n", status);
+- break;
+- default:
+- printk("failed\n");
+- }
+- }
+-}
+-
+-#ifdef WAKE_SECONDARY_VIA_NMI
+-/*
+- * Poke the other CPU in the eye via NMI to wake it up. Remember that the normal
+- * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this
+- * won't ... remember to clear down the APIC, etc later.
+- */
+-static int __devinit
+-wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
+-{
+- unsigned long send_status, accept_status = 0;
+- int maxlvt;
+-
+- /* Target chip */
+- apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(logical_apicid));
+-
+- /* Boot on the stack */
+- /* Kick the second */
+- apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL);
+-
+- Dprintk("Waiting for send to finish...\n");
+- send_status = safe_apic_wait_icr_idle();
+-
+- /*
+- * Give the other CPU some time to accept the IPI.
+- */
+- udelay(200);
+- /*
+- * Due to the Pentium erratum 3AP.
+- */
+- maxlvt = lapic_get_maxlvt();
+- if (maxlvt > 3) {
+- apic_read_around(APIC_SPIV);
+- apic_write(APIC_ESR, 0);
+- }
+- accept_status = (apic_read(APIC_ESR) & 0xEF);
+- Dprintk("NMI sent.\n");
+-
+- if (send_status)
+- printk("APIC never delivered???\n");
+- if (accept_status)
+- printk("APIC delivery error (%lx).\n", accept_status);
+-
+- return (send_status | accept_status);
+-}
+-#endif /* WAKE_SECONDARY_VIA_NMI */
+-
+-#ifdef WAKE_SECONDARY_VIA_INIT
+-static int __devinit
+-wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
+-{
+- unsigned long send_status, accept_status = 0;
+- int maxlvt, num_starts, j;
+-
+- /*
+- * Be paranoid about clearing APIC errors.
+- */
+- if (APIC_INTEGRATED(apic_version[phys_apicid])) {
+- apic_read_around(APIC_SPIV);
+- apic_write(APIC_ESR, 0);
+- apic_read(APIC_ESR);
+- }
+-
+- Dprintk("Asserting INIT.\n");
+-
+- /*
+- * Turn INIT on target chip
+- */
+- apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+-
+- /*
+- * Send IPI
+- */
+- apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
+- | APIC_DM_INIT);
+-
+- Dprintk("Waiting for send to finish...\n");
+- send_status = safe_apic_wait_icr_idle();
+-
+- mdelay(10);
+-
+- Dprintk("Deasserting INIT.\n");
+-
+- /* Target chip */
+- apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+-
+- /* Send IPI */
+- apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
+-
+- Dprintk("Waiting for send to finish...\n");
+- send_status = safe_apic_wait_icr_idle();
+-
+- atomic_set(&init_deasserted, 1);
+-
+- /*
+- * Should we send STARTUP IPIs ?
+- *
+- * Determine this based on the APIC version.
+- * If we don't have an integrated APIC, don't send the STARTUP IPIs.
+- */
+- if (APIC_INTEGRATED(apic_version[phys_apicid]))
+- num_starts = 2;
+- else
+- num_starts = 0;
+-
+- /*
+- * Paravirt / VMI wants a startup IPI hook here to set up the
+- * target processor state.
+- */
+- startup_ipi_hook(phys_apicid, (unsigned long) start_secondary,
+- (unsigned long) stack_start.sp);
+-
+- /*
+- * Run STARTUP IPI loop.
+- */
+- Dprintk("#startup loops: %d.\n", num_starts);
+-
+- maxlvt = lapic_get_maxlvt();
+-
+- for (j = 1; j <= num_starts; j++) {
+- Dprintk("Sending STARTUP #%d.\n",j);
+- apic_read_around(APIC_SPIV);
+- apic_write(APIC_ESR, 0);
+- apic_read(APIC_ESR);
+- Dprintk("After apic_write.\n");
+-
+- /*
+- * STARTUP IPI
+- */
+-
+- /* Target chip */
+- apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+-
+- /* Boot on the stack */
+- /* Kick the second */
+- apic_write_around(APIC_ICR, APIC_DM_STARTUP
+- | (start_eip >> 12));
+-
+- /*
+- * Give the other CPU some time to accept the IPI.
+- */
+- udelay(300);
+-
+- Dprintk("Startup point 1.\n");
+-
+- Dprintk("Waiting for send to finish...\n");
+- send_status = safe_apic_wait_icr_idle();
+-
+- /*
+- * Give the other CPU some time to accept the IPI.
+- */
+- udelay(200);
+- /*
+- * Due to the Pentium erratum 3AP.
+- */
+- if (maxlvt > 3) {
+- apic_read_around(APIC_SPIV);
+- apic_write(APIC_ESR, 0);
+- }
+- accept_status = (apic_read(APIC_ESR) & 0xEF);
+- if (send_status || accept_status)
+- break;
+- }
+- Dprintk("After Startup.\n");
+-
+- if (send_status)
+- printk("APIC never delivered???\n");
+- if (accept_status)
+- printk("APIC delivery error (%lx).\n", accept_status);
+-
+- return (send_status | accept_status);
+-}
+-#endif /* WAKE_SECONDARY_VIA_INIT */
+-
+-extern cpumask_t cpu_initialized;
+-static inline int alloc_cpu_id(void)
+-{
+- cpumask_t tmp_map;
+- int cpu;
+- cpus_complement(tmp_map, cpu_present_map);
+- cpu = first_cpu(tmp_map);
+- if (cpu >= NR_CPUS)
+- return -ENODEV;
+- return cpu;
+-}
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-static struct task_struct * __cpuinitdata cpu_idle_tasks[NR_CPUS];
+-static inline struct task_struct * __cpuinit alloc_idle_task(int cpu)
+-{
+- struct task_struct *idle;
+-
+- if ((idle = cpu_idle_tasks[cpu]) != NULL) {
+- /* initialize thread_struct. we really want to avoid destroy
+- * idle tread
+- */
+- idle->thread.sp = (unsigned long)task_pt_regs(idle);
+- init_idle(idle, cpu);
+- return idle;
+- }
+- idle = fork_idle(cpu);
+-
+- if (!IS_ERR(idle))
+- cpu_idle_tasks[cpu] = idle;
+- return idle;
+-}
+-#else
+-#define alloc_idle_task(cpu) fork_idle(cpu)
+-#endif
+-
+-static int __cpuinit do_boot_cpu(int apicid, int cpu)
+-/*
+- * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
+- * (ie clustered apic addressing mode), this is a LOGICAL apic ID.
+- * Returns zero if CPU booted OK, else error code from wakeup_secondary_cpu.
+- */
+-{
+- struct task_struct *idle;
+- unsigned long boot_error;
+- int timeout;
+- unsigned long start_eip;
+- unsigned short nmi_high = 0, nmi_low = 0;
+-
+- /*
+- * Save current MTRR state in case it was changed since early boot
+- * (e.g. by the ACPI SMI) to initialize new CPUs with MTRRs in sync:
+- */
+- mtrr_save_state();
+-
+- /*
+- * We can't use kernel_thread since we must avoid to
+- * reschedule the child.
+- */
+- idle = alloc_idle_task(cpu);
+- if (IS_ERR(idle))
+- panic("failed fork for CPU %d", cpu);
+-
+- init_gdt(cpu);
+- per_cpu(current_task, cpu) = idle;
+- early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
+-
+- idle->thread.ip = (unsigned long) start_secondary;
+- /* start_eip had better be page-aligned! */
+- start_eip = setup_trampoline();
+-
+- ++cpucount;
+- alternatives_smp_switch(1);
+-
+- /* So we see what's up */
+- printk("Booting processor %d/%d ip %lx\n", cpu, apicid, start_eip);
+- /* Stack for startup_32 can be just as for start_secondary onwards */
+- stack_start.sp = (void *) idle->thread.sp;
+-
+- irq_ctx_init(cpu);
+-
+- per_cpu(x86_cpu_to_apicid, cpu) = apicid;
+- /*
+- * This grunge runs the startup process for
+- * the targeted processor.
+- */
+-
+- atomic_set(&init_deasserted, 0);
+-
+- Dprintk("Setting warm reset code and vector.\n");
+-
+- store_NMI_vector(&nmi_high, &nmi_low);
+-
+- smpboot_setup_warm_reset_vector(start_eip);
+-
+- /*
+- * Starting actual IPI sequence...
+- */
+- boot_error = wakeup_secondary_cpu(apicid, start_eip);
+-
+- if (!boot_error) {
+- /*
+- * allow APs to start initializing.
+- */
+- Dprintk("Before Callout %d.\n", cpu);
+- cpu_set(cpu, cpu_callout_map);
+- Dprintk("After Callout %d.\n", cpu);
+-
+- /*
+- * Wait 5s total for a response
+- */
+- for (timeout = 0; timeout < 50000; timeout++) {
+- if (cpu_isset(cpu, cpu_callin_map))
+- break; /* It has booted */
+- udelay(100);
+- }
+-
+- if (cpu_isset(cpu, cpu_callin_map)) {
+- /* number CPUs logically, starting from 1 (BSP is 0) */
+- Dprintk("OK.\n");
+- printk("CPU%d: ", cpu);
+- print_cpu_info(&cpu_data(cpu));
+- Dprintk("CPU has booted.\n");
+- } else {
+- boot_error= 1;
+- if (*((volatile unsigned char *)trampoline_base)
+- == 0xA5)
+- /* trampoline started but...? */
+- printk("Stuck ??\n");
+- else
+- /* trampoline code not run */
+- printk("Not responding.\n");
+- inquire_remote_apic(apicid);
+- }
+- }
+-
+- if (boot_error) {
+- /* Try to put things back the way they were before ... */
+- unmap_cpu_to_logical_apicid(cpu);
+- cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */
+- cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */
+- cpucount--;
+- } else {
+- per_cpu(x86_cpu_to_apicid, cpu) = apicid;
+- cpu_set(cpu, cpu_present_map);
+- }
+-
+- /* mark "stuck" area as not stuck */
+- *((volatile unsigned long *)trampoline_base) = 0;
+-
+- return boot_error;
+-}
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-void cpu_exit_clear(void)
+-{
+- int cpu = raw_smp_processor_id();
+-
+- idle_task_exit();
+-
+- cpucount --;
+- cpu_uninit();
+- irq_ctx_exit(cpu);
+-
+- cpu_clear(cpu, cpu_callout_map);
+- cpu_clear(cpu, cpu_callin_map);
+-
+- cpu_clear(cpu, smp_commenced_mask);
+- unmap_cpu_to_logical_apicid(cpu);
+-}
+-
+-struct warm_boot_cpu_info {
+- struct completion *complete;
+- struct work_struct task;
+- int apicid;
+- int cpu;
+-};
+-
+-static void __cpuinit do_warm_boot_cpu(struct work_struct *work)
+-{
+- struct warm_boot_cpu_info *info =
+- container_of(work, struct warm_boot_cpu_info, task);
+- do_boot_cpu(info->apicid, info->cpu);
+- complete(info->complete);
+-}
+-
+-static int __cpuinit __smp_prepare_cpu(int cpu)
+-{
+- DECLARE_COMPLETION_ONSTACK(done);
+- struct warm_boot_cpu_info info;
+- int apicid, ret;
+-
+- apicid = per_cpu(x86_cpu_to_apicid, cpu);
+- if (apicid == BAD_APICID) {
+- ret = -ENODEV;
+- goto exit;
+- }
+-
+- info.complete = &done;
+- info.apicid = apicid;
+- info.cpu = cpu;
+- INIT_WORK(&info.task, do_warm_boot_cpu);
+-
+- /* init low mem mapping */
+- clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
+- min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS));
+- flush_tlb_all();
+- schedule_work(&info.task);
+- wait_for_completion(&done);
+-
+- zap_low_mappings();
+- ret = 0;
+-exit:
+- return ret;
+-}
+-#endif
+-
+-/*
+- * Cycle through the processors sending APIC IPIs to boot each.
+- */
+-
+-static int boot_cpu_logical_apicid;
+-/* Where the IO area was mapped on multiquad, always 0 otherwise */
+-void *xquad_portio;
+-#ifdef CONFIG_X86_NUMAQ
+-EXPORT_SYMBOL(xquad_portio);
+-#endif
+-
+-static void __init smp_boot_cpus(unsigned int max_cpus)
+-{
+- int apicid, cpu, bit, kicked;
+- unsigned long bogosum = 0;
+-
+- /*
+- * Setup boot CPU information
+- */
+- smp_store_cpu_info(0); /* Final full version of the data */
+- printk("CPU%d: ", 0);
+- print_cpu_info(&cpu_data(0));
+-
+- boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
+- boot_cpu_logical_apicid = logical_smp_processor_id();
+- per_cpu(x86_cpu_to_apicid, 0) = boot_cpu_physical_apicid;
+-
+- current_thread_info()->cpu = 0;
+-
+- set_cpu_sibling_map(0);
+-
+- /*
+- * If we couldn't find an SMP configuration at boot time,
+- * get out of here now!
+- */
+- if (!smp_found_config && !acpi_lapic) {
+- printk(KERN_NOTICE "SMP motherboard not detected.\n");
+- smpboot_clear_io_apic_irqs();
+- phys_cpu_present_map = physid_mask_of_physid(0);
+- if (APIC_init_uniprocessor())
+- printk(KERN_NOTICE "Local APIC not detected."
+- " Using dummy APIC emulation.\n");
+- map_cpu_to_logical_apicid();
+- cpu_set(0, per_cpu(cpu_sibling_map, 0));
+- cpu_set(0, per_cpu(cpu_core_map, 0));
+- return;
+- }
+-
+- /*
+- * Should not be necessary because the MP table should list the boot
+- * CPU too, but we do it for the sake of robustness anyway.
+- * Makes no sense to do this check in clustered apic mode, so skip it
+- */
+- if (!check_phys_apicid_present(boot_cpu_physical_apicid)) {
+- printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
+- boot_cpu_physical_apicid);
+- physid_set(hard_smp_processor_id(), phys_cpu_present_map);
+- }
+-
+- /*
+- * If we couldn't find a local APIC, then get out of here now!
+- */
+- if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) && !cpu_has_apic) {
+- printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
+- boot_cpu_physical_apicid);
+- printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
+- smpboot_clear_io_apic_irqs();
+- phys_cpu_present_map = physid_mask_of_physid(0);
+- map_cpu_to_logical_apicid();
+- cpu_set(0, per_cpu(cpu_sibling_map, 0));
+- cpu_set(0, per_cpu(cpu_core_map, 0));
+- return;
+- }
+-
+- verify_local_APIC();
+-
+- /*
+- * If SMP should be disabled, then really disable it!
+- */
+- if (!max_cpus) {
+- smp_found_config = 0;
+- printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n");
+-
+- if (nmi_watchdog == NMI_LOCAL_APIC) {
+- printk(KERN_INFO "activating minimal APIC for NMI watchdog use.\n");
+- connect_bsp_APIC();
+- setup_local_APIC();
+- }
+- smpboot_clear_io_apic_irqs();
+- phys_cpu_present_map = physid_mask_of_physid(0);
+- map_cpu_to_logical_apicid();
+- cpu_set(0, per_cpu(cpu_sibling_map, 0));
+- cpu_set(0, per_cpu(cpu_core_map, 0));
+- return;
+- }
+-
+- connect_bsp_APIC();
+- setup_local_APIC();
+- map_cpu_to_logical_apicid();
+-
+-
+- setup_portio_remap();
+-
+- /*
+- * Scan the CPU present map and fire up the other CPUs via do_boot_cpu
+- *
+- * In clustered apic mode, phys_cpu_present_map is a constructed thus:
+- * bits 0-3 are quad0, 4-7 are quad1, etc. A perverse twist on the
+- * clustered apic ID.
+- */
+- Dprintk("CPU present map: %lx\n", physids_coerce(phys_cpu_present_map));
+-
+- kicked = 1;
+- for (bit = 0; kicked < NR_CPUS && bit < MAX_APICS; bit++) {
+- apicid = cpu_present_to_apicid(bit);
+- /*
+- * Don't even attempt to start the boot CPU!
+- */
+- if ((apicid == boot_cpu_apicid) || (apicid == BAD_APICID))
+- continue;
+-
+- if (!check_apicid_present(bit))
+- continue;
+- if (max_cpus <= cpucount+1)
+- continue;
+-
+- if (((cpu = alloc_cpu_id()) <= 0) || do_boot_cpu(apicid, cpu))
+- printk("CPU #%d not responding - cannot use it.\n",
+- apicid);
+- else
+- ++kicked;
+- }
+-
+- /*
+- * Cleanup possible dangling ends...
+- */
+- smpboot_restore_warm_reset_vector();
+-
+- /*
+- * Allow the user to impress friends.
+- */
+- Dprintk("Before bogomips.\n");
+- for_each_possible_cpu(cpu)
+- if (cpu_isset(cpu, cpu_callout_map))
+- bogosum += cpu_data(cpu).loops_per_jiffy;
+- printk(KERN_INFO
+- "Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
+- cpucount+1,
+- bogosum/(500000/HZ),
+- (bogosum/(5000/HZ))%100);
+-
+- Dprintk("Before bogocount - setting activated=1.\n");
+-
+- if (smp_b_stepping)
+- printk(KERN_WARNING "WARNING: SMP operation may be unreliable with B stepping processors.\n");
+-
+- /*
+- * Don't taint if we are running SMP kernel on a single non-MP
+- * approved Athlon
+- */
+- if (tainted & TAINT_UNSAFE_SMP) {
+- if (cpucount)
+- printk (KERN_INFO "WARNING: This combination of AMD processors is not suitable for SMP.\n");
+- else
+- tainted &= ~TAINT_UNSAFE_SMP;
+- }
+-
+- Dprintk("Boot done.\n");
+-
+- /*
+- * construct cpu_sibling_map, so that we can tell sibling CPUs
+- * efficiently.
+- */
+- for_each_possible_cpu(cpu) {
+- cpus_clear(per_cpu(cpu_sibling_map, cpu));
+- cpus_clear(per_cpu(cpu_core_map, cpu));
+- }
+-
+- cpu_set(0, per_cpu(cpu_sibling_map, 0));
+- cpu_set(0, per_cpu(cpu_core_map, 0));
+-
+- smpboot_setup_io_apic();
+-
+- setup_boot_clock();
+-}
+-
+-/* These are wrappers to interface to the new boot process. Someone
+- who understands all this stuff should rewrite it properly. --RR 15/Jul/02 */
+-void __init native_smp_prepare_cpus(unsigned int max_cpus)
+-{
+- smp_commenced_mask = cpumask_of_cpu(0);
+- cpu_callin_map = cpumask_of_cpu(0);
+- mb();
+- smp_boot_cpus(max_cpus);
+-}
+-
+-void __init native_smp_prepare_boot_cpu(void)
+-{
+- unsigned int cpu = smp_processor_id();
+-
+- init_gdt(cpu);
+- switch_to_new_gdt();
+-
+- cpu_set(cpu, cpu_online_map);
+- cpu_set(cpu, cpu_callout_map);
+- cpu_set(cpu, cpu_present_map);
+- cpu_set(cpu, cpu_possible_map);
+- __get_cpu_var(cpu_state) = CPU_ONLINE;
+-}
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-void remove_siblinginfo(int cpu)
+-{
+- int sibling;
+- struct cpuinfo_x86 *c = &cpu_data(cpu);
+-
+- for_each_cpu_mask(sibling, per_cpu(cpu_core_map, cpu)) {
+- cpu_clear(cpu, per_cpu(cpu_core_map, sibling));
+- /*/
+- * last thread sibling in this cpu core going down
+- */
+- if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1)
+- cpu_data(sibling).booted_cores--;
+- }
+-
+- for_each_cpu_mask(sibling, per_cpu(cpu_sibling_map, cpu))
+- cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling));
+- cpus_clear(per_cpu(cpu_sibling_map, cpu));
+- cpus_clear(per_cpu(cpu_core_map, cpu));
+- c->phys_proc_id = 0;
+- c->cpu_core_id = 0;
+- cpu_clear(cpu, cpu_sibling_setup_map);
+-}
+-
+-int __cpu_disable(void)
+-{
+- cpumask_t map = cpu_online_map;
+- int cpu = smp_processor_id();
+-
+- /*
+- * Perhaps use cpufreq to drop frequency, but that could go
+- * into generic code.
+- *
+- * We won't take down the boot processor on i386 due to some
+- * interrupts only being able to be serviced by the BSP.
+- * Especially so if we're not using an IOAPIC -zwane
+- */
+- if (cpu == 0)
+- return -EBUSY;
+- if (nmi_watchdog == NMI_LOCAL_APIC)
+- stop_apic_nmi_watchdog(NULL);
+- clear_local_APIC();
+- /* Allow any queued timer interrupts to get serviced */
+- local_irq_enable();
+- mdelay(1);
+- local_irq_disable();
+-
+- remove_siblinginfo(cpu);
+-
+- cpu_clear(cpu, map);
+- fixup_irqs(map);
+- /* It's now safe to remove this processor from the online map */
+- cpu_clear(cpu, cpu_online_map);
+- return 0;
+-}
+-
+-void __cpu_die(unsigned int cpu)
+-{
+- /* We don't do anything here: idle task is faking death itself. */
+- unsigned int i;
+-
+- for (i = 0; i < 10; i++) {
+- /* They ack this in play_dead by setting CPU_DEAD */
+- if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
+- printk ("CPU %d is now offline\n", cpu);
+- if (1 == num_online_cpus())
+- alternatives_smp_switch(0);
+- return;
+- }
+- msleep(100);
+- }
+- printk(KERN_ERR "CPU %u didn't die...\n", cpu);
+-}
+-#else /* ... !CONFIG_HOTPLUG_CPU */
+-int __cpu_disable(void)
+-{
+- return -ENOSYS;
+-}
+-
+-void __cpu_die(unsigned int cpu)
+-{
+- /* We said "no" in __cpu_disable */
+- BUG();
+-}
+-#endif /* CONFIG_HOTPLUG_CPU */
+-
+-int __cpuinit native_cpu_up(unsigned int cpu)
+-{
+- unsigned long flags;
+-#ifdef CONFIG_HOTPLUG_CPU
+- int ret = 0;
+-
+- /*
+- * We do warm boot only on cpus that had booted earlier
+- * Otherwise cold boot is all handled from smp_boot_cpus().
+- * cpu_callin_map is set during AP kickstart process. Its reset
+- * when a cpu is taken offline from cpu_exit_clear().
+- */
+- if (!cpu_isset(cpu, cpu_callin_map))
+- ret = __smp_prepare_cpu(cpu);
+-
+- if (ret)
+- return -EIO;
+-#endif
+-
+- /* In case one didn't come up */
+- if (!cpu_isset(cpu, cpu_callin_map)) {
+- printk(KERN_DEBUG "skipping cpu%d, didn't come online\n", cpu);
+- return -EIO;
+- }
+-
+- per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
+- /* Unleash the CPU! */
+- cpu_set(cpu, smp_commenced_mask);
+-
+- /*
+- * Check TSC synchronization with the AP (keep irqs disabled
+- * while doing so):
+- */
+- local_irq_save(flags);
+- check_tsc_sync_source(cpu);
+- local_irq_restore(flags);
+-
+- while (!cpu_isset(cpu, cpu_online_map)) {
+- cpu_relax();
+- touch_nmi_watchdog();
+- }
+-
+- return 0;
+-}
+-
+-void __init native_smp_cpus_done(unsigned int max_cpus)
+-{
+-#ifdef CONFIG_X86_IO_APIC
+- setup_ioapic_dest();
+-#endif
+- zap_low_mappings();
+-}
+-
+-void __init smp_intr_init(void)
+-{
+- /*
+- * IRQ0 must be given a fixed assignment and initialized,
+- * because it's used before the IO-APIC is set up.
+- */
+- set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]);
+-
+- /*
+- * The reschedule interrupt is a CPU-to-CPU reschedule-helper
+- * IPI, driven by wakeup.
+- */
+- set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
+-
+- /* IPI for invalidation */
+- set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
+-
+- /* IPI for generic function call */
+- set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
+-}
+-
+-/*
+- * If the BIOS enumerates physical processors before logical,
+- * maxcpus=N at enumeration-time can be used to disable HT.
+- */
+-static int __init parse_maxcpus(char *arg)
+-{
+- extern unsigned int maxcpus;
+-
+- maxcpus = simple_strtoul(arg, NULL, 0);
+- return 0;
+-}
+-early_param("maxcpus", parse_maxcpus);
+diff --git a/arch/x86/kernel/smpboot_64.c b/arch/x86/kernel/smpboot_64.c
+deleted file mode 100644
+index 0880f2c..0000000
+--- a/arch/x86/kernel/smpboot_64.c
++++ /dev/null
+@@ -1,1108 +0,0 @@
+-/*
+- * x86 SMP booting functions
+- *
+- * (c) 1995 Alan Cox, Building #3 <alan at redhat.com>
+- * (c) 1998, 1999, 2000 Ingo Molnar <mingo at redhat.com>
+- * Copyright 2001 Andi Kleen, SuSE Labs.
+- *
+- * Much of the core SMP work is based on previous work by Thomas Radke, to
+- * whom a great many thanks are extended.
+- *
+- * Thanks to Intel for making available several different Pentium,
+- * Pentium Pro and Pentium-II/Xeon MP machines.
+- * Original development of Linux SMP code supported by Caldera.
+- *
+- * This code is released under the GNU General Public License version 2
+- *
+- * Fixes
+- * Felix Koop : NR_CPUS used properly
+- * Jose Renau : Handle single CPU case.
+- * Alan Cox : By repeated request 8) - Total BogoMIP report.
+- * Greg Wright : Fix for kernel stacks panic.
+- * Erich Boleyn : MP v1.4 and additional changes.
+- * Matthias Sattler : Changes for 2.1 kernel map.
+- * Michel Lespinasse : Changes for 2.1 kernel map.
+- * Michael Chastain : Change trampoline.S to gnu as.
+- * Alan Cox : Dumb bug: 'B' step PPro's are fine
+- * Ingo Molnar : Added APIC timers, based on code
+- * from Jose Renau
+- * Ingo Molnar : various cleanups and rewrites
+- * Tigran Aivazian : fixed "0.00 in /proc/uptime on SMP" bug.
+- * Maciej W. Rozycki : Bits for genuine 82489DX APICs
+- * Andi Kleen : Changed for SMP boot into long mode.
+- * Rusty Russell : Hacked into shape for new "hotplug" boot process.
+- * Andi Kleen : Converted to new state machine.
+- * Various cleanups.
+- * Probably mostly hotplug CPU ready now.
+- * Ashok Raj : CPU hotplug support
+- */
+-
+-
+-#include <linux/init.h>
+-
+-#include <linux/mm.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/bootmem.h>
+-#include <linux/thread_info.h>
+-#include <linux/module.h>
+-#include <linux/delay.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/smp.h>
+-#include <linux/kdebug.h>
+-
+-#include <asm/mtrr.h>
+-#include <asm/pgalloc.h>
+-#include <asm/desc.h>
+-#include <asm/tlbflush.h>
+-#include <asm/proto.h>
+-#include <asm/nmi.h>
+-#include <asm/irq.h>
+-#include <asm/hw_irq.h>
+-#include <asm/numa.h>
+-
+-/* Number of siblings per CPU package */
+-int smp_num_siblings = 1;
+-EXPORT_SYMBOL(smp_num_siblings);
+-
+-/* Last level cache ID of each logical CPU */
+-DEFINE_PER_CPU(u16, cpu_llc_id) = BAD_APICID;
+-
+-/* Bitmask of currently online CPUs */
+-cpumask_t cpu_online_map __read_mostly;
+-
+-EXPORT_SYMBOL(cpu_online_map);
+-
+-/*
+- * Private maps to synchronize booting between AP and BP.
+- * Probably not needed anymore, but it makes for easier debugging. -AK
+- */
+-cpumask_t cpu_callin_map;
+-cpumask_t cpu_callout_map;
+-cpumask_t cpu_possible_map;
+-EXPORT_SYMBOL(cpu_possible_map);
+-
+-/* Per CPU bogomips and other parameters */
+-DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
+-EXPORT_PER_CPU_SYMBOL(cpu_info);
+-
+-/* Set when the idlers are all forked */
+-int smp_threads_ready;
+-
+-/* representing HT siblings of each logical CPU */
+-DEFINE_PER_CPU(cpumask_t, cpu_sibling_map);
+-EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
+-
+-/* representing HT and core siblings of each logical CPU */
+-DEFINE_PER_CPU(cpumask_t, cpu_core_map);
+-EXPORT_PER_CPU_SYMBOL(cpu_core_map);
+-
+-/*
+- * Trampoline 80x86 program as an array.
+- */
+-
+-extern const unsigned char trampoline_data[];
+-extern const unsigned char trampoline_end[];
+-
+-/* State of each CPU */
+-DEFINE_PER_CPU(int, cpu_state) = { 0 };
+-
+-/*
+- * Store all idle threads, this can be reused instead of creating
+- * a new thread. Also avoids complicated thread destroy functionality
+- * for idle threads.
+- */
+-#ifdef CONFIG_HOTPLUG_CPU
+-/*
+- * Needed only for CONFIG_HOTPLUG_CPU because __cpuinitdata is
+- * removed after init for !CONFIG_HOTPLUG_CPU.
+- */
+-static DEFINE_PER_CPU(struct task_struct *, idle_thread_array);
+-#define get_idle_for_cpu(x) (per_cpu(idle_thread_array, x))
+-#define set_idle_for_cpu(x,p) (per_cpu(idle_thread_array, x) = (p))
+-#else
+-struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ;
+-#define get_idle_for_cpu(x) (idle_thread_array[(x)])
+-#define set_idle_for_cpu(x,p) (idle_thread_array[(x)] = (p))
+-#endif
+-
+-
+-/*
+- * Currently trivial. Write the real->protected mode
+- * bootstrap into the page concerned. The caller
+- * has made sure it's suitably aligned.
+- */
+-
+-static unsigned long __cpuinit setup_trampoline(void)
+-{
+- void *tramp = __va(SMP_TRAMPOLINE_BASE);
+- memcpy(tramp, trampoline_data, trampoline_end - trampoline_data);
+- return virt_to_phys(tramp);
+-}
+-
+-/*
+- * The bootstrap kernel entry code has set these up. Save them for
+- * a given CPU
+- */
+-
+-static void __cpuinit smp_store_cpu_info(int id)
+-{
+- struct cpuinfo_x86 *c = &cpu_data(id);
+-
+- *c = boot_cpu_data;
+- c->cpu_index = id;
+- identify_cpu(c);
+- print_cpu_info(c);
+-}
+-
+-static atomic_t init_deasserted __cpuinitdata;
+-
+-/*
+- * Report back to the Boot Processor.
+- * Running on AP.
+- */
+-void __cpuinit smp_callin(void)
+-{
+- int cpuid, phys_id;
+- unsigned long timeout;
+-
+- /*
+- * If waken up by an INIT in an 82489DX configuration
+- * we may get here before an INIT-deassert IPI reaches
+- * our local APIC. We have to wait for the IPI or we'll
+- * lock up on an APIC access.
+- */
+- while (!atomic_read(&init_deasserted))
+- cpu_relax();
+-
+- /*
+- * (This works even if the APIC is not enabled.)
+- */
+- phys_id = GET_APIC_ID(apic_read(APIC_ID));
+- cpuid = smp_processor_id();
+- if (cpu_isset(cpuid, cpu_callin_map)) {
+- panic("smp_callin: phys CPU#%d, CPU#%d already present??\n",
+- phys_id, cpuid);
+- }
+- Dprintk("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id);
+-
+- /*
+- * STARTUP IPIs are fragile beasts as they might sometimes
+- * trigger some glue motherboard logic. Complete APIC bus
+- * silence for 1 second, this overestimates the time the
+- * boot CPU is spending to send the up to 2 STARTUP IPIs
+- * by a factor of two. This should be enough.
+- */
+-
+- /*
+- * Waiting 2s total for startup (udelay is not yet working)
+- */
+- timeout = jiffies + 2*HZ;
+- while (time_before(jiffies, timeout)) {
+- /*
+- * Has the boot CPU finished it's STARTUP sequence?
+- */
+- if (cpu_isset(cpuid, cpu_callout_map))
+- break;
+- cpu_relax();
+- }
+-
+- if (!time_before(jiffies, timeout)) {
+- panic("smp_callin: CPU%d started up but did not get a callout!\n",
+- cpuid);
+- }
+-
+- /*
+- * the boot CPU has finished the init stage and is spinning
+- * on callin_map until we finish. We are free to set up this
+- * CPU, first the APIC. (this is probably redundant on most
+- * boards)
+- */
+-
+- Dprintk("CALLIN, before setup_local_APIC().\n");
+- setup_local_APIC();
+- end_local_APIC_setup();
+-
+- /*
+- * Get our bogomips.
+- *
+- * Need to enable IRQs because it can take longer and then
+- * the NMI watchdog might kill us.
+- */
+- local_irq_enable();
+- calibrate_delay();
+- local_irq_disable();
+- Dprintk("Stack at about %p\n",&cpuid);
+-
+- /*
+- * Save our processor parameters
+- */
+- smp_store_cpu_info(cpuid);
+-
+- /*
+- * Allow the master to continue.
+- */
+- cpu_set(cpuid, cpu_callin_map);
+-}
+-
+-/* maps the cpu to the sched domain representing multi-core */
+-cpumask_t cpu_coregroup_map(int cpu)
+-{
+- struct cpuinfo_x86 *c = &cpu_data(cpu);
+- /*
+- * For perf, we return last level cache shared map.
+- * And for power savings, we return cpu_core_map
+- */
+- if (sched_mc_power_savings || sched_smt_power_savings)
+- return per_cpu(cpu_core_map, cpu);
+- else
+- return c->llc_shared_map;
+-}
+-
+-/* representing cpus for which sibling maps can be computed */
+-static cpumask_t cpu_sibling_setup_map;
+-
+-static inline void set_cpu_sibling_map(int cpu)
+-{
+- int i;
+- struct cpuinfo_x86 *c = &cpu_data(cpu);
+-
+- cpu_set(cpu, cpu_sibling_setup_map);
+-
+- if (smp_num_siblings > 1) {
+- for_each_cpu_mask(i, cpu_sibling_setup_map) {
+- if (c->phys_proc_id == cpu_data(i).phys_proc_id &&
+- c->cpu_core_id == cpu_data(i).cpu_core_id) {
+- cpu_set(i, per_cpu(cpu_sibling_map, cpu));
+- cpu_set(cpu, per_cpu(cpu_sibling_map, i));
+- cpu_set(i, per_cpu(cpu_core_map, cpu));
+- cpu_set(cpu, per_cpu(cpu_core_map, i));
+- cpu_set(i, c->llc_shared_map);
+- cpu_set(cpu, cpu_data(i).llc_shared_map);
+- }
+- }
+- } else {
+- cpu_set(cpu, per_cpu(cpu_sibling_map, cpu));
+- }
+-
+- cpu_set(cpu, c->llc_shared_map);
+-
+- if (current_cpu_data.x86_max_cores == 1) {
+- per_cpu(cpu_core_map, cpu) = per_cpu(cpu_sibling_map, cpu);
+- c->booted_cores = 1;
+- return;
+- }
+-
+- for_each_cpu_mask(i, cpu_sibling_setup_map) {
+- if (per_cpu(cpu_llc_id, cpu) != BAD_APICID &&
+- per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) {
+- cpu_set(i, c->llc_shared_map);
+- cpu_set(cpu, cpu_data(i).llc_shared_map);
+- }
+- if (c->phys_proc_id == cpu_data(i).phys_proc_id) {
+- cpu_set(i, per_cpu(cpu_core_map, cpu));
+- cpu_set(cpu, per_cpu(cpu_core_map, i));
+- /*
+- * Does this new cpu bringup a new core?
+- */
+- if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1) {
+- /*
+- * for each core in package, increment
+- * the booted_cores for this new cpu
+- */
+- if (first_cpu(per_cpu(cpu_sibling_map, i)) == i)
+- c->booted_cores++;
+- /*
+- * increment the core count for all
+- * the other cpus in this package
+- */
+- if (i != cpu)
+- cpu_data(i).booted_cores++;
+- } else if (i != cpu && !c->booted_cores)
+- c->booted_cores = cpu_data(i).booted_cores;
+- }
+- }
+-}
+-
+-/*
+- * Setup code on secondary processor (after comming out of the trampoline)
+- */
+-void __cpuinit start_secondary(void)
+-{
+- /*
+- * Dont put anything before smp_callin(), SMP
+- * booting is too fragile that we want to limit the
+- * things done here to the most necessary things.
+- */
+- cpu_init();
+- preempt_disable();
+- smp_callin();
+-
+- /* otherwise gcc will move up the smp_processor_id before the cpu_init */
+- barrier();
+-
+- /*
+- * Check TSC sync first:
+- */
+- check_tsc_sync_target();
+-
+- if (nmi_watchdog == NMI_IO_APIC) {
+- disable_8259A_irq(0);
+- enable_NMI_through_LVT0();
+- enable_8259A_irq(0);
+- }
+-
+- /*
+- * The sibling maps must be set before turing the online map on for
+- * this cpu
+- */
+- set_cpu_sibling_map(smp_processor_id());
+-
+- /*
+- * We need to hold call_lock, so there is no inconsistency
+- * between the time smp_call_function() determines number of
+- * IPI recipients, and the time when the determination is made
+- * for which cpus receive the IPI in genapic_flat.c. Holding this
+- * lock helps us to not include this cpu in a currently in progress
+- * smp_call_function().
+- */
+- lock_ipi_call_lock();
+- spin_lock(&vector_lock);
+-
+- /* Setup the per cpu irq handling data structures */
+- __setup_vector_irq(smp_processor_id());
+- /*
+- * Allow the master to continue.
+- */
+- cpu_set(smp_processor_id(), cpu_online_map);
+- per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
+- spin_unlock(&vector_lock);
+-
+- unlock_ipi_call_lock();
+-
+- setup_secondary_clock();
+-
+- cpu_idle();
+-}
+-
+-extern volatile unsigned long init_rsp;
+-extern void (*initial_code)(void);
+-
+-#ifdef APIC_DEBUG
+-static void inquire_remote_apic(int apicid)
+-{
+- unsigned i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 };
+- char *names[] = { "ID", "VERSION", "SPIV" };
+- int timeout;
+- u32 status;
+-
+- printk(KERN_INFO "Inquiring remote APIC #%d...\n", apicid);
+-
+- for (i = 0; i < ARRAY_SIZE(regs); i++) {
+- printk(KERN_INFO "... APIC #%d %s: ", apicid, names[i]);
+-
+- /*
+- * Wait for idle.
+- */
+- status = safe_apic_wait_icr_idle();
+- if (status)
+- printk(KERN_CONT
+- "a previous APIC delivery may have failed\n");
+-
+- apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
+- apic_write(APIC_ICR, APIC_DM_REMRD | regs[i]);
+-
+- timeout = 0;
+- do {
+- udelay(100);
+- status = apic_read(APIC_ICR) & APIC_ICR_RR_MASK;
+- } while (status == APIC_ICR_RR_INPROG && timeout++ < 1000);
+-
+- switch (status) {
+- case APIC_ICR_RR_VALID:
+- status = apic_read(APIC_RRR);
+- printk(KERN_CONT "%08x\n", status);
+- break;
+- default:
+- printk(KERN_CONT "failed\n");
+- }
+- }
+-}
+-#endif
+-
+-/*
+- * Kick the secondary to wake up.
+- */
+-static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int start_rip)
+-{
+- unsigned long send_status, accept_status = 0;
+- int maxlvt, num_starts, j;
+-
+- Dprintk("Asserting INIT.\n");
+-
+- /*
+- * Turn INIT on target chip
+- */
+- apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+-
+- /*
+- * Send IPI
+- */
+- apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
+- | APIC_DM_INIT);
+-
+- Dprintk("Waiting for send to finish...\n");
+- send_status = safe_apic_wait_icr_idle();
+-
+- mdelay(10);
+-
+- Dprintk("Deasserting INIT.\n");
+-
+- /* Target chip */
+- apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+-
+- /* Send IPI */
+- apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
+-
+- Dprintk("Waiting for send to finish...\n");
+- send_status = safe_apic_wait_icr_idle();
+-
+- mb();
+- atomic_set(&init_deasserted, 1);
+-
+- num_starts = 2;
+-
+- /*
+- * Run STARTUP IPI loop.
+- */
+- Dprintk("#startup loops: %d.\n", num_starts);
+-
+- maxlvt = lapic_get_maxlvt();
+-
+- for (j = 1; j <= num_starts; j++) {
+- Dprintk("Sending STARTUP #%d.\n",j);
+- apic_write(APIC_ESR, 0);
+- apic_read(APIC_ESR);
+- Dprintk("After apic_write.\n");
+-
+- /*
+- * STARTUP IPI
+- */
+-
+- /* Target chip */
+- apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+-
+- /* Boot on the stack */
+- /* Kick the second */
+- apic_write(APIC_ICR, APIC_DM_STARTUP | (start_rip >> 12));
+-
+- /*
+- * Give the other CPU some time to accept the IPI.
+- */
+- udelay(300);
+-
+- Dprintk("Startup point 1.\n");
+-
+- Dprintk("Waiting for send to finish...\n");
+- send_status = safe_apic_wait_icr_idle();
+-
+- /*
+- * Give the other CPU some time to accept the IPI.
+- */
+- udelay(200);
+- /*
+- * Due to the Pentium erratum 3AP.
+- */
+- if (maxlvt > 3) {
+- apic_write(APIC_ESR, 0);
+- }
+- accept_status = (apic_read(APIC_ESR) & 0xEF);
+- if (send_status || accept_status)
+- break;
+- }
+- Dprintk("After Startup.\n");
+-
+- if (send_status)
+- printk(KERN_ERR "APIC never delivered???\n");
+- if (accept_status)
+- printk(KERN_ERR "APIC delivery error (%lx).\n", accept_status);
+-
+- return (send_status | accept_status);
+-}
+-
+-struct create_idle {
+- struct work_struct work;
+- struct task_struct *idle;
+- struct completion done;
+- int cpu;
+-};
+-
+-static void __cpuinit do_fork_idle(struct work_struct *work)
+-{
+- struct create_idle *c_idle =
+- container_of(work, struct create_idle, work);
+-
+- c_idle->idle = fork_idle(c_idle->cpu);
+- complete(&c_idle->done);
+-}
+-
+-/*
+- * Boot one CPU.
+- */
+-static int __cpuinit do_boot_cpu(int cpu, int apicid)
+-{
+- unsigned long boot_error;
+- int timeout;
+- unsigned long start_rip;
+- struct create_idle c_idle = {
+- .cpu = cpu,
+- .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done),
+- };
+- INIT_WORK(&c_idle.work, do_fork_idle);
+-
+- /* allocate memory for gdts of secondary cpus. Hotplug is considered */
+- if (!cpu_gdt_descr[cpu].address &&
+- !(cpu_gdt_descr[cpu].address = get_zeroed_page(GFP_KERNEL))) {
+- printk(KERN_ERR "Failed to allocate GDT for CPU %d\n", cpu);
+- return -1;
+- }
+-
+- /* Allocate node local memory for AP pdas */
+- if (cpu_pda(cpu) == &boot_cpu_pda[cpu]) {
+- struct x8664_pda *newpda, *pda;
+- int node = cpu_to_node(cpu);
+- pda = cpu_pda(cpu);
+- newpda = kmalloc_node(sizeof (struct x8664_pda), GFP_ATOMIC,
+- node);
+- if (newpda) {
+- memcpy(newpda, pda, sizeof (struct x8664_pda));
+- cpu_pda(cpu) = newpda;
+- } else
+- printk(KERN_ERR
+- "Could not allocate node local PDA for CPU %d on node %d\n",
+- cpu, node);
+- }
+-
+- alternatives_smp_switch(1);
+-
+- c_idle.idle = get_idle_for_cpu(cpu);
+-
+- if (c_idle.idle) {
+- c_idle.idle->thread.sp = (unsigned long) (((struct pt_regs *)
+- (THREAD_SIZE + task_stack_page(c_idle.idle))) - 1);
+- init_idle(c_idle.idle, cpu);
+- goto do_rest;
+- }
+-
+- /*
+- * During cold boot process, keventd thread is not spun up yet.
+- * When we do cpu hot-add, we create idle threads on the fly, we should
+- * not acquire any attributes from the calling context. Hence the clean
+- * way to create kernel_threads() is to do that from keventd().
+- * We do the current_is_keventd() due to the fact that ACPI notifier
+- * was also queuing to keventd() and when the caller is already running
+- * in context of keventd(), we would end up with locking up the keventd
+- * thread.
+- */
+- if (!keventd_up() || current_is_keventd())
+- c_idle.work.func(&c_idle.work);
+- else {
+- schedule_work(&c_idle.work);
+- wait_for_completion(&c_idle.done);
+- }
+-
+- if (IS_ERR(c_idle.idle)) {
+- printk("failed fork for CPU %d\n", cpu);
+- return PTR_ERR(c_idle.idle);
+- }
+-
+- set_idle_for_cpu(cpu, c_idle.idle);
+-
+-do_rest:
+-
+- cpu_pda(cpu)->pcurrent = c_idle.idle;
+-
+- start_rip = setup_trampoline();
+-
+- init_rsp = c_idle.idle->thread.sp;
+- load_sp0(&per_cpu(init_tss, cpu), &c_idle.idle->thread);
+- initial_code = start_secondary;
+- clear_tsk_thread_flag(c_idle.idle, TIF_FORK);
+-
+- printk(KERN_INFO "Booting processor %d/%d APIC 0x%x\n", cpu,
+- cpus_weight(cpu_present_map),
+- apicid);
+-
+- /*
+- * This grunge runs the startup process for
+- * the targeted processor.
+- */
+-
+- atomic_set(&init_deasserted, 0);
+-
+- Dprintk("Setting warm reset code and vector.\n");
+-
+- CMOS_WRITE(0xa, 0xf);
+- local_flush_tlb();
+- Dprintk("1.\n");
+- *((volatile unsigned short *) phys_to_virt(0x469)) = start_rip >> 4;
+- Dprintk("2.\n");
+- *((volatile unsigned short *) phys_to_virt(0x467)) = start_rip & 0xf;
+- Dprintk("3.\n");
+-
+- /*
+- * Be paranoid about clearing APIC errors.
+- */
+- apic_write(APIC_ESR, 0);
+- apic_read(APIC_ESR);
+-
+- /*
+- * Status is now clean
+- */
+- boot_error = 0;
+-
+- /*
+- * Starting actual IPI sequence...
+- */
+- boot_error = wakeup_secondary_via_INIT(apicid, start_rip);
+-
+- if (!boot_error) {
+- /*
+- * allow APs to start initializing.
+- */
+- Dprintk("Before Callout %d.\n", cpu);
+- cpu_set(cpu, cpu_callout_map);
+- Dprintk("After Callout %d.\n", cpu);
+-
+- /*
+- * Wait 5s total for a response
+- */
+- for (timeout = 0; timeout < 50000; timeout++) {
+- if (cpu_isset(cpu, cpu_callin_map))
+- break; /* It has booted */
+- udelay(100);
+- }
+-
+- if (cpu_isset(cpu, cpu_callin_map)) {
+- /* number CPUs logically, starting from 1 (BSP is 0) */
+- Dprintk("CPU has booted.\n");
+- } else {
+- boot_error = 1;
+- if (*((volatile unsigned char *)phys_to_virt(SMP_TRAMPOLINE_BASE))
+- == 0xA5)
+- /* trampoline started but...? */
+- printk("Stuck ??\n");
+- else
+- /* trampoline code not run */
+- printk("Not responding.\n");
+-#ifdef APIC_DEBUG
+- inquire_remote_apic(apicid);
+-#endif
+- }
+- }
+- if (boot_error) {
+- cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */
+- clear_bit(cpu, (unsigned long *)&cpu_initialized); /* was set by cpu_init() */
+- clear_node_cpumask(cpu); /* was set by numa_add_cpu */
+- cpu_clear(cpu, cpu_present_map);
+- cpu_clear(cpu, cpu_possible_map);
+- per_cpu(x86_cpu_to_apicid, cpu) = BAD_APICID;
+- return -EIO;
+- }
+-
+- return 0;
+-}
+-
+-cycles_t cacheflush_time;
+-unsigned long cache_decay_ticks;
+-
+-/*
+- * Cleanup possible dangling ends...
+- */
+-static __cpuinit void smp_cleanup_boot(void)
+-{
+- /*
+- * Paranoid: Set warm reset code and vector here back
+- * to default values.
+- */
+- CMOS_WRITE(0, 0xf);
+-
+- /*
+- * Reset trampoline flag
+- */
+- *((volatile int *) phys_to_virt(0x467)) = 0;
+-}
+-
+-/*
+- * Fall back to non SMP mode after errors.
+- *
+- * RED-PEN audit/test this more. I bet there is more state messed up here.
+- */
+-static __init void disable_smp(void)
+-{
+- cpu_present_map = cpumask_of_cpu(0);
+- cpu_possible_map = cpumask_of_cpu(0);
+- if (smp_found_config)
+- phys_cpu_present_map = physid_mask_of_physid(boot_cpu_id);
+- else
+- phys_cpu_present_map = physid_mask_of_physid(0);
+- cpu_set(0, per_cpu(cpu_sibling_map, 0));
+- cpu_set(0, per_cpu(cpu_core_map, 0));
+-}
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-
+-int additional_cpus __initdata = -1;
+-
+-/*
+- * cpu_possible_map should be static, it cannot change as cpu's
+- * are onlined, or offlined. The reason is per-cpu data-structures
+- * are allocated by some modules at init time, and dont expect to
+- * do this dynamically on cpu arrival/departure.
+- * cpu_present_map on the other hand can change dynamically.
+- * In case when cpu_hotplug is not compiled, then we resort to current
+- * behaviour, which is cpu_possible == cpu_present.
+- * - Ashok Raj
+- *
+- * Three ways to find out the number of additional hotplug CPUs:
+- * - If the BIOS specified disabled CPUs in ACPI/mptables use that.
+- * - The user can overwrite it with additional_cpus=NUM
+- * - Otherwise don't reserve additional CPUs.
+- * We do this because additional CPUs waste a lot of memory.
+- * -AK
+- */
+-__init void prefill_possible_map(void)
+-{
+- int i;
+- int possible;
+-
+- if (additional_cpus == -1) {
+- if (disabled_cpus > 0)
+- additional_cpus = disabled_cpus;
+- else
+- additional_cpus = 0;
+- }
+- possible = num_processors + additional_cpus;
+- if (possible > NR_CPUS)
+- possible = NR_CPUS;
+-
+- printk(KERN_INFO "SMP: Allowing %d CPUs, %d hotplug CPUs\n",
+- possible,
+- max_t(int, possible - num_processors, 0));
+-
+- for (i = 0; i < possible; i++)
+- cpu_set(i, cpu_possible_map);
+-}
+-#endif
+-
+-/*
+- * Various sanity checks.
+- */
+-static int __init smp_sanity_check(unsigned max_cpus)
+-{
+- if (!physid_isset(hard_smp_processor_id(), phys_cpu_present_map)) {
+- printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
+- hard_smp_processor_id());
+- physid_set(hard_smp_processor_id(), phys_cpu_present_map);
+- }
+-
+- /*
+- * If we couldn't find an SMP configuration at boot time,
+- * get out of here now!
+- */
+- if (!smp_found_config) {
+- printk(KERN_NOTICE "SMP motherboard not detected.\n");
+- disable_smp();
+- if (APIC_init_uniprocessor())
+- printk(KERN_NOTICE "Local APIC not detected."
+- " Using dummy APIC emulation.\n");
+- return -1;
+- }
+-
+- /*
+- * Should not be necessary because the MP table should list the boot
+- * CPU too, but we do it for the sake of robustness anyway.
+- */
+- if (!physid_isset(boot_cpu_id, phys_cpu_present_map)) {
+- printk(KERN_NOTICE "weird, boot CPU (#%d) not listed by the BIOS.\n",
+- boot_cpu_id);
+- physid_set(hard_smp_processor_id(), phys_cpu_present_map);
+- }
+-
+- /*
+- * If we couldn't find a local APIC, then get out of here now!
+- */
+- if (!cpu_has_apic) {
+- printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
+- boot_cpu_id);
+- printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
+- nr_ioapics = 0;
+- return -1;
+- }
+-
+- /*
+- * If SMP should be disabled, then really disable it!
+- */
+- if (!max_cpus) {
+- printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n");
+- nr_ioapics = 0;
+- return -1;
+- }
+-
+- return 0;
+-}
+-
+-static void __init smp_cpu_index_default(void)
+-{
+- int i;
+- struct cpuinfo_x86 *c;
+-
+- for_each_cpu_mask(i, cpu_possible_map) {
+- c = &cpu_data(i);
+- /* mark all to hotplug */
+- c->cpu_index = NR_CPUS;
+- }
+-}
+-
+-/*
+- * Prepare for SMP bootup. The MP table or ACPI has been read
+- * earlier. Just do some sanity checking here and enable APIC mode.
+- */
+-void __init smp_prepare_cpus(unsigned int max_cpus)
+-{
+- nmi_watchdog_default();
+- smp_cpu_index_default();
+- current_cpu_data = boot_cpu_data;
+- current_thread_info()->cpu = 0; /* needed? */
+- set_cpu_sibling_map(0);
+-
+- if (smp_sanity_check(max_cpus) < 0) {
+- printk(KERN_INFO "SMP disabled\n");
+- disable_smp();
+- return;
+- }
+-
+-
+- /*
+- * Switch from PIC to APIC mode.
+- */
+- setup_local_APIC();
+-
+- /*
+- * Enable IO APIC before setting up error vector
+- */
+- if (!skip_ioapic_setup && nr_ioapics)
+- enable_IO_APIC();
+- end_local_APIC_setup();
+-
+- if (GET_APIC_ID(apic_read(APIC_ID)) != boot_cpu_id) {
+- panic("Boot APIC ID in local APIC unexpected (%d vs %d)",
+- GET_APIC_ID(apic_read(APIC_ID)), boot_cpu_id);
+- /* Or can we switch back to PIC here? */
+- }
+-
+- /*
+- * Now start the IO-APICs
+- */
+- if (!skip_ioapic_setup && nr_ioapics)
+- setup_IO_APIC();
+- else
+- nr_ioapics = 0;
+-
+- /*
+- * Set up local APIC timer on boot CPU.
+- */
+-
+- setup_boot_clock();
+-}
+-
+-/*
+- * Early setup to make printk work.
+- */
+-void __init smp_prepare_boot_cpu(void)
+-{
+- int me = smp_processor_id();
+- /* already set me in cpu_online_map in boot_cpu_init() */
+- cpu_set(me, cpu_callout_map);
+- per_cpu(cpu_state, me) = CPU_ONLINE;
+-}
+-
+-/*
+- * Entry point to boot a CPU.
+- */
+-int __cpuinit __cpu_up(unsigned int cpu)
+-{
+- int apicid = cpu_present_to_apicid(cpu);
+- unsigned long flags;
+- int err;
+-
+- WARN_ON(irqs_disabled());
+-
+- Dprintk("++++++++++++++++++++=_---CPU UP %u\n", cpu);
+-
+- if (apicid == BAD_APICID || apicid == boot_cpu_id ||
+- !physid_isset(apicid, phys_cpu_present_map)) {
+- printk("__cpu_up: bad cpu %d\n", cpu);
+- return -EINVAL;
+- }
+-
+- /*
+- * Already booted CPU?
+- */
+- if (cpu_isset(cpu, cpu_callin_map)) {
+- Dprintk("do_boot_cpu %d Already started\n", cpu);
+- return -ENOSYS;
+- }
+-
+- /*
+- * Save current MTRR state in case it was changed since early boot
+- * (e.g. by the ACPI SMI) to initialize new CPUs with MTRRs in sync:
+- */
+- mtrr_save_state();
+-
+- per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
+- /* Boot it! */
+- err = do_boot_cpu(cpu, apicid);
+- if (err < 0) {
+- Dprintk("do_boot_cpu failed %d\n", err);
+- return err;
+- }
+-
+- /* Unleash the CPU! */
+- Dprintk("waiting for cpu %d\n", cpu);
+-
+- /*
+- * Make sure and check TSC sync:
+- */
+- local_irq_save(flags);
+- check_tsc_sync_source(cpu);
+- local_irq_restore(flags);
+-
+- while (!cpu_isset(cpu, cpu_online_map))
+- cpu_relax();
+- err = 0;
+-
+- return err;
+-}
+-
+-/*
+- * Finish the SMP boot.
+- */
+-void __init smp_cpus_done(unsigned int max_cpus)
+-{
+- smp_cleanup_boot();
+- setup_ioapic_dest();
+- check_nmi_watchdog();
+-}
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-
+-static void remove_siblinginfo(int cpu)
+-{
+- int sibling;
+- struct cpuinfo_x86 *c = &cpu_data(cpu);
+-
+- for_each_cpu_mask(sibling, per_cpu(cpu_core_map, cpu)) {
+- cpu_clear(cpu, per_cpu(cpu_core_map, sibling));
+- /*
+- * last thread sibling in this cpu core going down
+- */
+- if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1)
+- cpu_data(sibling).booted_cores--;
+- }
+-
+- for_each_cpu_mask(sibling, per_cpu(cpu_sibling_map, cpu))
+- cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling));
+- cpus_clear(per_cpu(cpu_sibling_map, cpu));
+- cpus_clear(per_cpu(cpu_core_map, cpu));
+- c->phys_proc_id = 0;
+- c->cpu_core_id = 0;
+- cpu_clear(cpu, cpu_sibling_setup_map);
+-}
+-
+-static void __ref remove_cpu_from_maps(void)
+-{
+- int cpu = smp_processor_id();
+-
+- cpu_clear(cpu, cpu_callout_map);
+- cpu_clear(cpu, cpu_callin_map);
+- clear_bit(cpu, (unsigned long *)&cpu_initialized); /* was set by cpu_init() */
+- clear_node_cpumask(cpu);
+-}
+-
+-int __cpu_disable(void)
+-{
+- int cpu = smp_processor_id();
+-
+- /*
+- * Perhaps use cpufreq to drop frequency, but that could go
+- * into generic code.
+- *
+- * We won't take down the boot processor on i386 due to some
+- * interrupts only being able to be serviced by the BSP.
+- * Especially so if we're not using an IOAPIC -zwane
+- */
+- if (cpu == 0)
+- return -EBUSY;
+-
+- if (nmi_watchdog == NMI_LOCAL_APIC)
+- stop_apic_nmi_watchdog(NULL);
+- clear_local_APIC();
+-
+- /*
+- * HACK:
+- * Allow any queued timer interrupts to get serviced
+- * This is only a temporary solution until we cleanup
+- * fixup_irqs as we do for IA64.
+- */
+- local_irq_enable();
+- mdelay(1);
+-
+- local_irq_disable();
+- remove_siblinginfo(cpu);
+-
+- spin_lock(&vector_lock);
+- /* It's now safe to remove this processor from the online map */
+- cpu_clear(cpu, cpu_online_map);
+- spin_unlock(&vector_lock);
+- remove_cpu_from_maps();
+- fixup_irqs(cpu_online_map);
+- return 0;
+-}
+-
+-void __cpu_die(unsigned int cpu)
+-{
+- /* We don't do anything here: idle task is faking death itself. */
+- unsigned int i;
+-
+- for (i = 0; i < 10; i++) {
+- /* They ack this in play_dead by setting CPU_DEAD */
+- if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
+- printk ("CPU %d is now offline\n", cpu);
+- if (1 == num_online_cpus())
+- alternatives_smp_switch(0);
+- return;
+- }
+- msleep(100);
+- }
+- printk(KERN_ERR "CPU %u didn't die...\n", cpu);
+-}
+-
+-static __init int setup_additional_cpus(char *s)
+-{
+- return s && get_option(&s, &additional_cpus) ? 0 : -EINVAL;
+-}
+-early_param("additional_cpus", setup_additional_cpus);
+-
+-#else /* ... !CONFIG_HOTPLUG_CPU */
+-
+-int __cpu_disable(void)
+-{
+- return -ENOSYS;
+-}
+-
+-void __cpu_die(unsigned int cpu)
+-{
+- /* We said "no" in __cpu_disable */
+- BUG();
+-}
+-#endif /* CONFIG_HOTPLUG_CPU */
+diff --git a/arch/x86/kernel/smpcommon.c b/arch/x86/kernel/smpcommon.c
+new file mode 100644
+index 0000000..3449064
+--- /dev/null
++++ b/arch/x86/kernel/smpcommon.c
+@@ -0,0 +1,83 @@
++/*
++ * SMP stuff which is common to all sub-architectures.
++ */
++#include <linux/module.h>
++#include <asm/smp.h>
++
++#ifdef CONFIG_X86_32
++DEFINE_PER_CPU(unsigned long, this_cpu_off);
++EXPORT_PER_CPU_SYMBOL(this_cpu_off);
++
++/* Initialize the CPU's GDT. This is either the boot CPU doing itself
++ (still using the master per-cpu area), or a CPU doing it for a
++ secondary which will soon come up. */
++__cpuinit void init_gdt(int cpu)
++{
++ struct desc_struct *gdt = get_cpu_gdt_table(cpu);
++
++ pack_descriptor(&gdt[GDT_ENTRY_PERCPU],
++ __per_cpu_offset[cpu], 0xFFFFF,
++ 0x2 | DESCTYPE_S, 0x8);
++
++ gdt[GDT_ENTRY_PERCPU].s = 1;
++
++ per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu];
++ per_cpu(cpu_number, cpu) = cpu;
++}
++#endif
++
++/**
++ * smp_call_function(): Run a function on all other CPUs.
++ * @func: The function to run. This must be fast and non-blocking.
++ * @info: An arbitrary pointer to pass to the function.
++ * @nonatomic: Unused.
++ * @wait: If true, wait (atomically) until function has completed on other CPUs.
++ *
++ * Returns 0 on success, else a negative status code.
++ *
++ * If @wait is true, then returns once @func has returned; otherwise
++ * it returns just before the target cpu calls @func.
++ *
++ * You must not call this function with disabled interrupts or from a
++ * hardware interrupt handler or from a bottom half handler.
++ */
++int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
++ int wait)
++{
++ return smp_call_function_mask(cpu_online_map, func, info, wait);
++}
++EXPORT_SYMBOL(smp_call_function);
++
++/**
++ * smp_call_function_single - Run a function on a specific CPU
++ * @cpu: The target CPU. Cannot be the calling CPU.
++ * @func: The function to run. This must be fast and non-blocking.
++ * @info: An arbitrary pointer to pass to the function.
++ * @nonatomic: Unused.
++ * @wait: If true, wait until function has completed on other CPUs.
++ *
++ * Returns 0 on success, else a negative status code.
++ *
++ * If @wait is true, then returns once @func has returned; otherwise
++ * it returns just before the target cpu calls @func.
++ */
++int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
++ int nonatomic, int wait)
++{
++ /* prevent preemption and reschedule on another processor */
++ int ret;
++ int me = get_cpu();
++ if (cpu == me) {
++ local_irq_disable();
++ func(info);
++ local_irq_enable();
++ put_cpu();
++ return 0;
++ }
++
++ ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait);
++
++ put_cpu();
++ return ret;
++}
++EXPORT_SYMBOL(smp_call_function_single);
+diff --git a/arch/x86/kernel/smpcommon_32.c b/arch/x86/kernel/smpcommon_32.c
+index 8bc38af..8b13789 100644
+--- a/arch/x86/kernel/smpcommon_32.c
++++ b/arch/x86/kernel/smpcommon_32.c
+@@ -1,82 +1 @@
+-/*
+- * SMP stuff which is common to all sub-architectures.
+- */
+-#include <linux/module.h>
+-#include <asm/smp.h>
+
+-DEFINE_PER_CPU(unsigned long, this_cpu_off);
+-EXPORT_PER_CPU_SYMBOL(this_cpu_off);
+-
+-/* Initialize the CPU's GDT. This is either the boot CPU doing itself
+- (still using the master per-cpu area), or a CPU doing it for a
+- secondary which will soon come up. */
+-__cpuinit void init_gdt(int cpu)
+-{
+- struct desc_struct *gdt = get_cpu_gdt_table(cpu);
+-
+- pack_descriptor(&gdt[GDT_ENTRY_PERCPU],
+- __per_cpu_offset[cpu], 0xFFFFF,
+- 0x2 | DESCTYPE_S, 0x8);
+-
+- gdt[GDT_ENTRY_PERCPU].s = 1;
+-
+- per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu];
+- per_cpu(cpu_number, cpu) = cpu;
+-}
+-
+-
+-/**
+- * smp_call_function(): Run a function on all other CPUs.
+- * @func: The function to run. This must be fast and non-blocking.
+- * @info: An arbitrary pointer to pass to the function.
+- * @nonatomic: Unused.
+- * @wait: If true, wait (atomically) until function has completed on other CPUs.
+- *
+- * Returns 0 on success, else a negative status code.
+- *
+- * If @wait is true, then returns once @func has returned; otherwise
+- * it returns just before the target cpu calls @func.
+- *
+- * You must not call this function with disabled interrupts or from a
+- * hardware interrupt handler or from a bottom half handler.
+- */
+-int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
+- int wait)
+-{
+- return smp_call_function_mask(cpu_online_map, func, info, wait);
+-}
+-EXPORT_SYMBOL(smp_call_function);
+-
+-/**
+- * smp_call_function_single - Run a function on a specific CPU
+- * @cpu: The target CPU. Cannot be the calling CPU.
+- * @func: The function to run. This must be fast and non-blocking.
+- * @info: An arbitrary pointer to pass to the function.
+- * @nonatomic: Unused.
+- * @wait: If true, wait until function has completed on other CPUs.
+- *
+- * Returns 0 on success, else a negative status code.
+- *
+- * If @wait is true, then returns once @func has returned; otherwise
+- * it returns just before the target cpu calls @func.
+- */
+-int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
+- int nonatomic, int wait)
+-{
+- /* prevent preemption and reschedule on another processor */
+- int ret;
+- int me = get_cpu();
+- if (cpu == me) {
+- local_irq_disable();
+- func(info);
+- local_irq_enable();
+- put_cpu();
+- return 0;
+- }
+-
+- ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait);
+-
+- put_cpu();
+- return ret;
+-}
+-EXPORT_SYMBOL(smp_call_function_single);
+diff --git a/arch/x86/kernel/srat_32.c b/arch/x86/kernel/srat_32.c
+index b72e613..70e4a37 100644
+--- a/arch/x86/kernel/srat_32.c
++++ b/arch/x86/kernel/srat_32.c
+@@ -277,14 +277,14 @@ int __init get_memcfg_from_srat(void)
+ rsdp_address = acpi_os_get_root_pointer();
+ if (!rsdp_address) {
+ printk("%s: System description tables not found\n",
+- __FUNCTION__);
++ __func__);
+ goto out_err;
+ }
+
+- printk("%s: assigning address to rsdp\n", __FUNCTION__);
++ printk("%s: assigning address to rsdp\n", __func__);
+ rsdp = (struct acpi_table_rsdp *)(u32)rsdp_address;
+ if (!rsdp) {
+- printk("%s: Didn't find ACPI root!\n", __FUNCTION__);
++ printk("%s: Didn't find ACPI root!\n", __func__);
+ goto out_err;
+ }
+
+@@ -292,7 +292,7 @@ int __init get_memcfg_from_srat(void)
+ rsdp->oem_id);
+
+ if (strncmp(rsdp->signature, ACPI_SIG_RSDP,strlen(ACPI_SIG_RSDP))) {
+- printk(KERN_WARNING "%s: RSDP table signature incorrect\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: RSDP table signature incorrect\n", __func__);
+ goto out_err;
+ }
+
+@@ -302,7 +302,7 @@ int __init get_memcfg_from_srat(void)
+ if (!rsdt) {
+ printk(KERN_WARNING
+ "%s: ACPI: Invalid root system description tables (RSDT)\n",
+- __FUNCTION__);
++ __func__);
+ goto out_err;
+ }
+
+diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c
+index 071ff47..92c20fe 100644
+--- a/arch/x86/kernel/step.c
++++ b/arch/x86/kernel/step.c
+@@ -148,7 +148,7 @@ static void write_debugctlmsr(struct task_struct *child, unsigned long val)
+ if (child != current)
+ return;
+
+- wrmsrl(MSR_IA32_DEBUGCTLMSR, val);
++ update_debugctlmsr(val);
+ }
+
+ /*
+diff --git a/arch/x86/kernel/summit_32.c b/arch/x86/kernel/summit_32.c
+index 72f4634..ae75109 100644
+--- a/arch/x86/kernel/summit_32.c
++++ b/arch/x86/kernel/summit_32.c
+@@ -29,49 +29,54 @@
+ #include <linux/mm.h>
+ #include <linux/init.h>
+ #include <asm/io.h>
++#include <asm/bios_ebda.h>
+ #include <asm/mach-summit/mach_mpparse.h>
+
+ static struct rio_table_hdr *rio_table_hdr __initdata;
+ static struct scal_detail *scal_devs[MAX_NUMNODES] __initdata;
+ static struct rio_detail *rio_devs[MAX_NUMNODES*4] __initdata;
+
++static int mp_bus_id_to_node[MAX_MP_BUSSES] __initdata;
++
+ static int __init setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus)
+ {
+ int twister = 0, node = 0;
+ int i, bus, num_buses;
+
+- for(i = 0; i < rio_table_hdr->num_rio_dev; i++){
+- if (rio_devs[i]->node_id == rio_devs[wpeg_num]->owner_id){
++ for (i = 0; i < rio_table_hdr->num_rio_dev; i++) {
++ if (rio_devs[i]->node_id == rio_devs[wpeg_num]->owner_id) {
+ twister = rio_devs[i]->owner_id;
+ break;
+ }
+ }
+- if (i == rio_table_hdr->num_rio_dev){
+- printk(KERN_ERR "%s: Couldn't find owner Cyclone for Winnipeg!\n", __FUNCTION__);
++ if (i == rio_table_hdr->num_rio_dev) {
++ printk(KERN_ERR "%s: Couldn't find owner Cyclone for Winnipeg!\n", __func__);
+ return last_bus;
+ }
+
+- for(i = 0; i < rio_table_hdr->num_scal_dev; i++){
+- if (scal_devs[i]->node_id == twister){
++ for (i = 0; i < rio_table_hdr->num_scal_dev; i++) {
++ if (scal_devs[i]->node_id == twister) {
+ node = scal_devs[i]->node_id;
+ break;
+ }
+ }
+- if (i == rio_table_hdr->num_scal_dev){
+- printk(KERN_ERR "%s: Couldn't find owner Twister for Cyclone!\n", __FUNCTION__);
++ if (i == rio_table_hdr->num_scal_dev) {
++ printk(KERN_ERR "%s: Couldn't find owner Twister for Cyclone!\n", __func__);
+ return last_bus;
+ }
+
+- switch (rio_devs[wpeg_num]->type){
++ switch (rio_devs[wpeg_num]->type) {
+ case CompatWPEG:
+- /* The Compatibility Winnipeg controls the 2 legacy buses,
++ /*
++ * The Compatibility Winnipeg controls the 2 legacy buses,
+ * the 66MHz PCI bus [2 slots] and the 2 "extra" buses in case
+ * a PCI-PCI bridge card is used in either slot: total 5 buses.
+ */
+ num_buses = 5;
+ break;
+ case AltWPEG:
+- /* The Alternate Winnipeg controls the 2 133MHz buses [1 slot
++ /*
++ * The Alternate Winnipeg controls the 2 133MHz buses [1 slot
+ * each], their 2 "extra" buses, the 100MHz bus [2 slots] and
+ * the "extra" buses for each of those slots: total 7 buses.
+ */
+@@ -79,17 +84,18 @@ static int __init setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus)
+ break;
+ case LookOutAWPEG:
+ case LookOutBWPEG:
+- /* A Lookout Winnipeg controls 3 100MHz buses [2 slots each]
++ /*
++ * A Lookout Winnipeg controls 3 100MHz buses [2 slots each]
+ * & the "extra" buses for each of those slots: total 9 buses.
+ */
+ num_buses = 9;
+ break;
+ default:
+- printk(KERN_INFO "%s: Unsupported Winnipeg type!\n", __FUNCTION__);
++ printk(KERN_INFO "%s: Unsupported Winnipeg type!\n", __func__);
+ return last_bus;
+ }
+
+- for(bus = last_bus; bus < last_bus + num_buses; bus++)
++ for (bus = last_bus; bus < last_bus + num_buses; bus++)
+ mp_bus_id_to_node[bus] = node;
+ return bus;
+ }
+@@ -99,14 +105,14 @@ static int __init build_detail_arrays(void)
+ unsigned long ptr;
+ int i, scal_detail_size, rio_detail_size;
+
+- if (rio_table_hdr->num_scal_dev > MAX_NUMNODES){
+- printk(KERN_WARNING "%s: MAX_NUMNODES too low! Defined as %d, but system has %d nodes.\n", __FUNCTION__, MAX_NUMNODES, rio_table_hdr->num_scal_dev);
++ if (rio_table_hdr->num_scal_dev > MAX_NUMNODES) {
++ printk(KERN_WARNING "%s: MAX_NUMNODES too low! Defined as %d, but system has %d nodes.\n", __func__, MAX_NUMNODES, rio_table_hdr->num_scal_dev);
+ return 0;
+ }
+
+- switch (rio_table_hdr->version){
++ switch (rio_table_hdr->version) {
+ default:
+- printk(KERN_WARNING "%s: Invalid Rio Grande Table Version: %d\n", __FUNCTION__, rio_table_hdr->version);
++ printk(KERN_WARNING "%s: Invalid Rio Grande Table Version: %d\n", __func__, rio_table_hdr->version);
+ return 0;
+ case 2:
+ scal_detail_size = 11;
+@@ -119,10 +125,10 @@ static int __init build_detail_arrays(void)
+ }
+
+ ptr = (unsigned long)rio_table_hdr + 3;
+- for(i = 0; i < rio_table_hdr->num_scal_dev; i++, ptr += scal_detail_size)
++ for (i = 0; i < rio_table_hdr->num_scal_dev; i++, ptr += scal_detail_size)
+ scal_devs[i] = (struct scal_detail *)ptr;
+
+- for(i = 0; i < rio_table_hdr->num_rio_dev; i++, ptr += rio_detail_size)
++ for (i = 0; i < rio_table_hdr->num_rio_dev; i++, ptr += rio_detail_size)
+ rio_devs[i] = (struct rio_detail *)ptr;
+
+ return 1;
+@@ -135,14 +141,14 @@ void __init setup_summit(void)
+ int i, next_wpeg, next_bus = 0;
+
+ /* The pointer to the EBDA is stored in the word @ phys 0x40E(40:0E) */
+- ptr = *(unsigned short *)phys_to_virt(0x40Eul);
+- ptr = (unsigned long)phys_to_virt(ptr << 4);
++ ptr = get_bios_ebda();
++ ptr = (unsigned long)phys_to_virt(ptr);
+
+ rio_table_hdr = NULL;
+ offset = 0x180;
+- while (offset){
++ while (offset) {
+ /* The block id is stored in the 2nd word */
+- if (*((unsigned short *)(ptr + offset + 2)) == 0x4752){
++ if (*((unsigned short *)(ptr + offset + 2)) == 0x4752) {
+ /* set the pointer past the offset & block id */
+ rio_table_hdr = (struct rio_table_hdr *)(ptr + offset + 4);
+ break;
+@@ -150,8 +156,8 @@ void __init setup_summit(void)
+ /* The next offset is stored in the 1st word. 0 means no more */
+ offset = *((unsigned short *)(ptr + offset));
+ }
+- if (!rio_table_hdr){
+- printk(KERN_ERR "%s: Unable to locate Rio Grande Table in EBDA - bailing!\n", __FUNCTION__);
++ if (!rio_table_hdr) {
++ printk(KERN_ERR "%s: Unable to locate Rio Grande Table in EBDA - bailing!\n", __func__);
+ return;
+ }
+
+@@ -161,8 +167,8 @@ void __init setup_summit(void)
+ /* The first Winnipeg we're looking for has an index of 0 */
+ next_wpeg = 0;
+ do {
+- for(i = 0; i < rio_table_hdr->num_rio_dev; i++){
+- if (is_WPEG(rio_devs[i]) && rio_devs[i]->WP_index == next_wpeg){
++ for (i = 0; i < rio_table_hdr->num_rio_dev; i++) {
++ if (is_WPEG(rio_devs[i]) && rio_devs[i]->WP_index == next_wpeg) {
+ /* It's the Winnipeg we're looking for! */
+ next_bus = setup_pci_node_map_for_wpeg(i, next_bus);
+ next_wpeg++;
+diff --git a/arch/x86/kernel/syscall_64.c b/arch/x86/kernel/syscall_64.c
+index 9d498c2..170d43c 100644
+--- a/arch/x86/kernel/syscall_64.c
++++ b/arch/x86/kernel/syscall_64.c
+@@ -1,4 +1,4 @@
+-/* System call table for x86-64. */
++/* System call table for x86-64. */
+
+ #include <linux/linkage.h>
+ #include <linux/sys.h>
+@@ -7,20 +7,23 @@
+
+ #define __NO_STUBS
+
+-#define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ;
++#define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ;
+ #undef _ASM_X86_64_UNISTD_H_
+ #include <asm/unistd_64.h>
+
+ #undef __SYSCALL
+-#define __SYSCALL(nr, sym) [ nr ] = sym,
++#define __SYSCALL(nr, sym) [nr] = sym,
+ #undef _ASM_X86_64_UNISTD_H_
+
+-typedef void (*sys_call_ptr_t)(void);
++typedef void (*sys_call_ptr_t)(void);
+
+ extern void sys_ni_syscall(void);
+
+ const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
+- /* Smells like a like a compiler bug -- it doesn't work when the & below is removed. */
++ /*
++ *Smells like a like a compiler bug -- it doesn't work
++ *when the & below is removed.
++ */
+ [0 ... __NR_syscall_max] = &sys_ni_syscall,
+ #include <asm/unistd_64.h>
+ };
+diff --git a/arch/x86/kernel/test_nx.c b/arch/x86/kernel/test_nx.c
+index 10b8a6f..787a5e4 100644
+--- a/arch/x86/kernel/test_nx.c
++++ b/arch/x86/kernel/test_nx.c
+@@ -11,6 +11,8 @@
+ */
+ #include <linux/module.h>
+ #include <linux/sort.h>
++#include <linux/slab.h>
++
+ #include <asm/uaccess.h>
+ #include <asm/asm.h>
+
+diff --git a/arch/x86/kernel/tlb_32.c b/arch/x86/kernel/tlb_32.c
+new file mode 100644
+index 0000000..9bb2363
+--- /dev/null
++++ b/arch/x86/kernel/tlb_32.c
+@@ -0,0 +1,243 @@
++#include <linux/spinlock.h>
++#include <linux/cpu.h>
++#include <linux/interrupt.h>
++
++#include <asm/tlbflush.h>
++
++DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate)
++ ____cacheline_aligned = { &init_mm, 0, };
++
++/* must come after the send_IPI functions above for inlining */
++#include <mach_ipi.h>
++
++/*
++ * Smarter SMP flushing macros.
++ * c/o Linus Torvalds.
++ *
++ * These mean you can really definitely utterly forget about
++ * writing to user space from interrupts. (Its not allowed anyway).
++ *
++ * Optimizations Manfred Spraul <manfred at colorfullife.com>
++ */
++
++static cpumask_t flush_cpumask;
++static struct mm_struct *flush_mm;
++static unsigned long flush_va;
++static DEFINE_SPINLOCK(tlbstate_lock);
++
++/*
++ * We cannot call mmdrop() because we are in interrupt context,
++ * instead update mm->cpu_vm_mask.
++ *
++ * We need to reload %cr3 since the page tables may be going
++ * away from under us..
++ */
++void leave_mm(int cpu)
++{
++ if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK)
++ BUG();
++ cpu_clear(cpu, per_cpu(cpu_tlbstate, cpu).active_mm->cpu_vm_mask);
++ load_cr3(swapper_pg_dir);
++}
++EXPORT_SYMBOL_GPL(leave_mm);
++
++/*
++ *
++ * The flush IPI assumes that a thread switch happens in this order:
++ * [cpu0: the cpu that switches]
++ * 1) switch_mm() either 1a) or 1b)
++ * 1a) thread switch to a different mm
++ * 1a1) cpu_clear(cpu, old_mm->cpu_vm_mask);
++ * Stop ipi delivery for the old mm. This is not synchronized with
++ * the other cpus, but smp_invalidate_interrupt ignore flush ipis
++ * for the wrong mm, and in the worst case we perform a superfluous
++ * tlb flush.
++ * 1a2) set cpu_tlbstate to TLBSTATE_OK
++ * Now the smp_invalidate_interrupt won't call leave_mm if cpu0
++ * was in lazy tlb mode.
++ * 1a3) update cpu_tlbstate[].active_mm
++ * Now cpu0 accepts tlb flushes for the new mm.
++ * 1a4) cpu_set(cpu, new_mm->cpu_vm_mask);
++ * Now the other cpus will send tlb flush ipis.
++ * 1a4) change cr3.
++ * 1b) thread switch without mm change
++ * cpu_tlbstate[].active_mm is correct, cpu0 already handles
++ * flush ipis.
++ * 1b1) set cpu_tlbstate to TLBSTATE_OK
++ * 1b2) test_and_set the cpu bit in cpu_vm_mask.
++ * Atomically set the bit [other cpus will start sending flush ipis],
++ * and test the bit.
++ * 1b3) if the bit was 0: leave_mm was called, flush the tlb.
++ * 2) switch %%esp, ie current
++ *
++ * The interrupt must handle 2 special cases:
++ * - cr3 is changed before %%esp, ie. it cannot use current->{active_,}mm.
++ * - the cpu performs speculative tlb reads, i.e. even if the cpu only
++ * runs in kernel space, the cpu could load tlb entries for user space
++ * pages.
++ *
++ * The good news is that cpu_tlbstate is local to each cpu, no
++ * write/read ordering problems.
++ */
++
++/*
++ * TLB flush IPI:
++ *
++ * 1) Flush the tlb entries if the cpu uses the mm that's being flushed.
++ * 2) Leave the mm if we are in the lazy tlb mode.
++ */
++
++void smp_invalidate_interrupt(struct pt_regs *regs)
++{
++ unsigned long cpu;
++
++ cpu = get_cpu();
++
++ if (!cpu_isset(cpu, flush_cpumask))
++ goto out;
++ /*
++ * This was a BUG() but until someone can quote me the
++ * line from the intel manual that guarantees an IPI to
++ * multiple CPUs is retried _only_ on the erroring CPUs
++ * its staying as a return
++ *
++ * BUG();
++ */
++
++ if (flush_mm == per_cpu(cpu_tlbstate, cpu).active_mm) {
++ if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) {
++ if (flush_va == TLB_FLUSH_ALL)
++ local_flush_tlb();
++ else
++ __flush_tlb_one(flush_va);
++ } else
++ leave_mm(cpu);
++ }
++ ack_APIC_irq();
++ smp_mb__before_clear_bit();
++ cpu_clear(cpu, flush_cpumask);
++ smp_mb__after_clear_bit();
++out:
++ put_cpu_no_resched();
++ __get_cpu_var(irq_stat).irq_tlb_count++;
++}
++
++void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm,
++ unsigned long va)
++{
++ cpumask_t cpumask = *cpumaskp;
++
++ /*
++ * A couple of (to be removed) sanity checks:
++ *
++ * - current CPU must not be in mask
++ * - mask must exist :)
++ */
++ BUG_ON(cpus_empty(cpumask));
++ BUG_ON(cpu_isset(smp_processor_id(), cpumask));
++ BUG_ON(!mm);
++
++#ifdef CONFIG_HOTPLUG_CPU
++ /* If a CPU which we ran on has gone down, OK. */
++ cpus_and(cpumask, cpumask, cpu_online_map);
++ if (unlikely(cpus_empty(cpumask)))
++ return;
++#endif
++
++ /*
++ * i'm not happy about this global shared spinlock in the
++ * MM hot path, but we'll see how contended it is.
++ * AK: x86-64 has a faster method that could be ported.
++ */
++ spin_lock(&tlbstate_lock);
++
++ flush_mm = mm;
++ flush_va = va;
++ cpus_or(flush_cpumask, cpumask, flush_cpumask);
++ /*
++ * We have to send the IPI only to
++ * CPUs affected.
++ */
++ send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR);
++
++ while (!cpus_empty(flush_cpumask))
++ /* nothing. lockup detection does not belong here */
++ cpu_relax();
++
++ flush_mm = NULL;
++ flush_va = 0;
++ spin_unlock(&tlbstate_lock);
++}
++
++void flush_tlb_current_task(void)
++{
++ struct mm_struct *mm = current->mm;
++ cpumask_t cpu_mask;
++
++ preempt_disable();
++ cpu_mask = mm->cpu_vm_mask;
++ cpu_clear(smp_processor_id(), cpu_mask);
++
++ local_flush_tlb();
++ if (!cpus_empty(cpu_mask))
++ flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
++ preempt_enable();
++}
++
++void flush_tlb_mm(struct mm_struct *mm)
++{
++ cpumask_t cpu_mask;
++
++ preempt_disable();
++ cpu_mask = mm->cpu_vm_mask;
++ cpu_clear(smp_processor_id(), cpu_mask);
++
++ if (current->active_mm == mm) {
++ if (current->mm)
++ local_flush_tlb();
++ else
++ leave_mm(smp_processor_id());
++ }
++ if (!cpus_empty(cpu_mask))
++ flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
++
++ preempt_enable();
++}
++
++void flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
++{
++ struct mm_struct *mm = vma->vm_mm;
++ cpumask_t cpu_mask;
++
++ preempt_disable();
++ cpu_mask = mm->cpu_vm_mask;
++ cpu_clear(smp_processor_id(), cpu_mask);
++
++ if (current->active_mm == mm) {
++ if (current->mm)
++ __flush_tlb_one(va);
++ else
++ leave_mm(smp_processor_id());
++ }
++
++ if (!cpus_empty(cpu_mask))
++ flush_tlb_others(cpu_mask, mm, va);
++
++ preempt_enable();
++}
++EXPORT_SYMBOL(flush_tlb_page);
++
++static void do_flush_tlb_all(void *info)
++{
++ unsigned long cpu = smp_processor_id();
++
++ __flush_tlb_all();
++ if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_LAZY)
++ leave_mm(cpu);
++}
++
++void flush_tlb_all(void)
++{
++ on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
++}
++
+diff --git a/arch/x86/kernel/tlb_64.c b/arch/x86/kernel/tlb_64.c
+new file mode 100644
+index 0000000..a1f07d7
+--- /dev/null
++++ b/arch/x86/kernel/tlb_64.c
+@@ -0,0 +1,274 @@
++#include <linux/init.h>
++
++#include <linux/mm.h>
++#include <linux/delay.h>
++#include <linux/spinlock.h>
++#include <linux/smp.h>
++#include <linux/kernel_stat.h>
++#include <linux/mc146818rtc.h>
++#include <linux/interrupt.h>
++
++#include <asm/mtrr.h>
++#include <asm/pgalloc.h>
++#include <asm/tlbflush.h>
++#include <asm/mmu_context.h>
++#include <asm/proto.h>
++#include <asm/apicdef.h>
++#include <asm/idle.h>
++
++#include <mach_ipi.h>
++/*
++ * Smarter SMP flushing macros.
++ * c/o Linus Torvalds.
++ *
++ * These mean you can really definitely utterly forget about
++ * writing to user space from interrupts. (Its not allowed anyway).
++ *
++ * Optimizations Manfred Spraul <manfred at colorfullife.com>
++ *
++ * More scalable flush, from Andi Kleen
++ *
++ * To avoid global state use 8 different call vectors.
++ * Each CPU uses a specific vector to trigger flushes on other
++ * CPUs. Depending on the received vector the target CPUs look into
++ * the right per cpu variable for the flush data.
++ *
++ * With more than 8 CPUs they are hashed to the 8 available
++ * vectors. The limited global vector space forces us to this right now.
++ * In future when interrupts are split into per CPU domains this could be
++ * fixed, at the cost of triggering multiple IPIs in some cases.
++ */
++
++union smp_flush_state {
++ struct {
++ cpumask_t flush_cpumask;
++ struct mm_struct *flush_mm;
++ unsigned long flush_va;
++ spinlock_t tlbstate_lock;
++ };
++ char pad[SMP_CACHE_BYTES];
++} ____cacheline_aligned;
++
++/* State is put into the per CPU data section, but padded
++ to a full cache line because other CPUs can access it and we don't
++ want false sharing in the per cpu data segment. */
++static DEFINE_PER_CPU(union smp_flush_state, flush_state);
++
++/*
++ * We cannot call mmdrop() because we are in interrupt context,
++ * instead update mm->cpu_vm_mask.
++ */
++void leave_mm(int cpu)
++{
++ if (read_pda(mmu_state) == TLBSTATE_OK)
++ BUG();
++ cpu_clear(cpu, read_pda(active_mm)->cpu_vm_mask);
++ load_cr3(swapper_pg_dir);
++}
++EXPORT_SYMBOL_GPL(leave_mm);
++
++/*
++ *
++ * The flush IPI assumes that a thread switch happens in this order:
++ * [cpu0: the cpu that switches]
++ * 1) switch_mm() either 1a) or 1b)
++ * 1a) thread switch to a different mm
++ * 1a1) cpu_clear(cpu, old_mm->cpu_vm_mask);
++ * Stop ipi delivery for the old mm. This is not synchronized with
++ * the other cpus, but smp_invalidate_interrupt ignore flush ipis
++ * for the wrong mm, and in the worst case we perform a superfluous
++ * tlb flush.
++ * 1a2) set cpu mmu_state to TLBSTATE_OK
++ * Now the smp_invalidate_interrupt won't call leave_mm if cpu0
++ * was in lazy tlb mode.
++ * 1a3) update cpu active_mm
++ * Now cpu0 accepts tlb flushes for the new mm.
++ * 1a4) cpu_set(cpu, new_mm->cpu_vm_mask);
++ * Now the other cpus will send tlb flush ipis.
++ * 1a4) change cr3.
++ * 1b) thread switch without mm change
++ * cpu active_mm is correct, cpu0 already handles
++ * flush ipis.
++ * 1b1) set cpu mmu_state to TLBSTATE_OK
++ * 1b2) test_and_set the cpu bit in cpu_vm_mask.
++ * Atomically set the bit [other cpus will start sending flush ipis],
++ * and test the bit.
++ * 1b3) if the bit was 0: leave_mm was called, flush the tlb.
++ * 2) switch %%esp, ie current
++ *
++ * The interrupt must handle 2 special cases:
++ * - cr3 is changed before %%esp, ie. it cannot use current->{active_,}mm.
++ * - the cpu performs speculative tlb reads, i.e. even if the cpu only
++ * runs in kernel space, the cpu could load tlb entries for user space
++ * pages.
++ *
++ * The good news is that cpu mmu_state is local to each cpu, no
++ * write/read ordering problems.
++ */
++
++/*
++ * TLB flush IPI:
++ *
++ * 1) Flush the tlb entries if the cpu uses the mm that's being flushed.
++ * 2) Leave the mm if we are in the lazy tlb mode.
++ *
++ * Interrupts are disabled.
++ */
++
++asmlinkage void smp_invalidate_interrupt(struct pt_regs *regs)
++{
++ int cpu;
++ int sender;
++ union smp_flush_state *f;
++
++ cpu = smp_processor_id();
++ /*
++ * orig_rax contains the negated interrupt vector.
++ * Use that to determine where the sender put the data.
++ */
++ sender = ~regs->orig_ax - INVALIDATE_TLB_VECTOR_START;
++ f = &per_cpu(flush_state, sender);
++
++ if (!cpu_isset(cpu, f->flush_cpumask))
++ goto out;
++ /*
++ * This was a BUG() but until someone can quote me the
++ * line from the intel manual that guarantees an IPI to
++ * multiple CPUs is retried _only_ on the erroring CPUs
++ * its staying as a return
++ *
++ * BUG();
++ */
++
++ if (f->flush_mm == read_pda(active_mm)) {
++ if (read_pda(mmu_state) == TLBSTATE_OK) {
++ if (f->flush_va == TLB_FLUSH_ALL)
++ local_flush_tlb();
++ else
++ __flush_tlb_one(f->flush_va);
++ } else
++ leave_mm(cpu);
++ }
++out:
++ ack_APIC_irq();
++ cpu_clear(cpu, f->flush_cpumask);
++ add_pda(irq_tlb_count, 1);
++}
++
++void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm,
++ unsigned long va)
++{
++ int sender;
++ union smp_flush_state *f;
++ cpumask_t cpumask = *cpumaskp;
++
++ /* Caller has disabled preemption */
++ sender = smp_processor_id() % NUM_INVALIDATE_TLB_VECTORS;
++ f = &per_cpu(flush_state, sender);
++
++ /*
++ * Could avoid this lock when
++ * num_online_cpus() <= NUM_INVALIDATE_TLB_VECTORS, but it is
++ * probably not worth checking this for a cache-hot lock.
++ */
++ spin_lock(&f->tlbstate_lock);
++
++ f->flush_mm = mm;
++ f->flush_va = va;
++ cpus_or(f->flush_cpumask, cpumask, f->flush_cpumask);
++
++ /*
++ * We have to send the IPI only to
++ * CPUs affected.
++ */
++ send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR_START + sender);
++
++ while (!cpus_empty(f->flush_cpumask))
++ cpu_relax();
++
++ f->flush_mm = NULL;
++ f->flush_va = 0;
++ spin_unlock(&f->tlbstate_lock);
++}
++
++static int __cpuinit init_smp_flush(void)
++{
++ int i;
++
++ for_each_possible_cpu(i)
++ spin_lock_init(&per_cpu(flush_state, i).tlbstate_lock);
++
++ return 0;
++}
++core_initcall(init_smp_flush);
++
++void flush_tlb_current_task(void)
++{
++ struct mm_struct *mm = current->mm;
++ cpumask_t cpu_mask;
++
++ preempt_disable();
++ cpu_mask = mm->cpu_vm_mask;
++ cpu_clear(smp_processor_id(), cpu_mask);
++
++ local_flush_tlb();
++ if (!cpus_empty(cpu_mask))
++ flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
++ preempt_enable();
++}
++
++void flush_tlb_mm(struct mm_struct *mm)
++{
++ cpumask_t cpu_mask;
++
++ preempt_disable();
++ cpu_mask = mm->cpu_vm_mask;
++ cpu_clear(smp_processor_id(), cpu_mask);
++
++ if (current->active_mm == mm) {
++ if (current->mm)
++ local_flush_tlb();
++ else
++ leave_mm(smp_processor_id());
++ }
++ if (!cpus_empty(cpu_mask))
++ flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
++
++ preempt_enable();
++}
++
++void flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
++{
++ struct mm_struct *mm = vma->vm_mm;
++ cpumask_t cpu_mask;
++
++ preempt_disable();
++ cpu_mask = mm->cpu_vm_mask;
++ cpu_clear(smp_processor_id(), cpu_mask);
++
++ if (current->active_mm == mm) {
++ if (current->mm)
++ __flush_tlb_one(va);
++ else
++ leave_mm(smp_processor_id());
++ }
++
++ if (!cpus_empty(cpu_mask))
++ flush_tlb_others(cpu_mask, mm, va);
++
++ preempt_enable();
++}
++
++static void do_flush_tlb_all(void *info)
++{
++ unsigned long cpu = smp_processor_id();
++
++ __flush_tlb_all();
++ if (read_pda(mmu_state) == TLBSTATE_LAZY)
++ leave_mm(cpu);
++}
++
++void flush_tlb_all(void)
++{
++ on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
++}
+diff --git a/arch/x86/kernel/trampoline.c b/arch/x86/kernel/trampoline.c
+new file mode 100644
+index 0000000..abbf199
+--- /dev/null
++++ b/arch/x86/kernel/trampoline.c
+@@ -0,0 +1,18 @@
++#include <linux/io.h>
++
++#include <asm/trampoline.h>
++
++/* ready for x86_64, no harm for x86, since it will overwrite after alloc */
++unsigned char *trampoline_base = __va(TRAMPOLINE_BASE);
++
++/*
++ * Currently trivial. Write the real->protected mode
++ * bootstrap into the page concerned. The caller
++ * has made sure it's suitably aligned.
++ */
++unsigned long setup_trampoline(void)
++{
++ memcpy(trampoline_base, trampoline_data,
++ trampoline_end - trampoline_data);
++ return virt_to_phys(trampoline_base);
++}
+diff --git a/arch/x86/kernel/trampoline_32.S b/arch/x86/kernel/trampoline_32.S
+index 6458067..d8ccc3c 100644
+--- a/arch/x86/kernel/trampoline_32.S
++++ b/arch/x86/kernel/trampoline_32.S
+@@ -33,7 +33,7 @@
+
+ /* We can free up trampoline after bootup if cpu hotplug is not supported. */
+ #ifndef CONFIG_HOTPLUG_CPU
+-.section ".init.data","aw", at progbits
++.section ".cpuinit.data","aw", at progbits
+ #else
+ .section .rodata,"a", at progbits
+ #endif
+diff --git a/arch/x86/kernel/trampoline_64.S b/arch/x86/kernel/trampoline_64.S
+index 4aedd0b..894293c 100644
+--- a/arch/x86/kernel/trampoline_64.S
++++ b/arch/x86/kernel/trampoline_64.S
+@@ -30,12 +30,7 @@
+ #include <asm/msr.h>
+ #include <asm/segment.h>
+
+-/* We can free up trampoline after bootup if cpu hotplug is not supported. */
+-#ifndef CONFIG_HOTPLUG_CPU
+-.section .init.data, "aw", @progbits
+-#else
+ .section .rodata, "a", @progbits
+-#endif
+
+ .code16
+
+diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c
+index b22c01e..bde6f63 100644
+--- a/arch/x86/kernel/traps_32.c
++++ b/arch/x86/kernel/traps_32.c
+@@ -9,26 +9,28 @@
+ * 'Traps.c' handles hardware traps and faults after we have saved some
+ * state in 'asm.s'.
+ */
+-#include <linux/sched.h>
++#include <linux/interrupt.h>
++#include <linux/kallsyms.h>
++#include <linux/spinlock.h>
++#include <linux/highmem.h>
++#include <linux/kprobes.h>
++#include <linux/uaccess.h>
++#include <linux/utsname.h>
++#include <linux/kdebug.h>
+ #include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/ptrace.h>
+ #include <linux/string.h>
++#include <linux/unwind.h>
++#include <linux/delay.h>
+ #include <linux/errno.h>
++#include <linux/kexec.h>
++#include <linux/sched.h>
+ #include <linux/timer.h>
+-#include <linux/mm.h>
+ #include <linux/init.h>
+-#include <linux/delay.h>
+-#include <linux/spinlock.h>
+-#include <linux/interrupt.h>
+-#include <linux/highmem.h>
+-#include <linux/kallsyms.h>
+-#include <linux/ptrace.h>
+-#include <linux/utsname.h>
+-#include <linux/kprobes.h>
+-#include <linux/kexec.h>
+-#include <linux/unwind.h>
+-#include <linux/uaccess.h>
+-#include <linux/nmi.h>
+ #include <linux/bug.h>
++#include <linux/nmi.h>
++#include <linux/mm.h>
+
+ #ifdef CONFIG_EISA
+ #include <linux/ioport.h>
+@@ -43,21 +45,18 @@
+ #include <linux/edac.h>
+ #endif
+
++#include <asm/arch_hooks.h>
++#include <asm/stacktrace.h>
+ #include <asm/processor.h>
+-#include <asm/system.h>
+-#include <asm/io.h>
+-#include <asm/atomic.h>
+ #include <asm/debugreg.h>
++#include <asm/atomic.h>
++#include <asm/system.h>
++#include <asm/unwind.h>
+ #include <asm/desc.h>
+ #include <asm/i387.h>
+ #include <asm/nmi.h>
+-#include <asm/unwind.h>
+ #include <asm/smp.h>
+-#include <asm/arch_hooks.h>
+-#include <linux/kdebug.h>
+-#include <asm/stacktrace.h>
+-
+-#include <linux/module.h>
++#include <asm/io.h>
+
+ #include "mach_traps.h"
+
+@@ -69,7 +68,7 @@ EXPORT_SYMBOL_GPL(used_vectors);
+ asmlinkage int system_call(void);
+
+ /* Do we ignore FPU interrupts ? */
+-char ignore_fpu_irq = 0;
++char ignore_fpu_irq;
+
+ /*
+ * The IDT has to be page-aligned to simplify the Pentium
+@@ -105,12 +104,13 @@ static unsigned int code_bytes = 64;
+ void printk_address(unsigned long address, int reliable)
+ {
+ #ifdef CONFIG_KALLSYMS
+- unsigned long offset = 0, symsize;
++ char namebuf[KSYM_NAME_LEN];
++ unsigned long offset = 0;
++ unsigned long symsize;
+ const char *symname;
+- char *modname;
+- char *delim = ":";
+- char namebuf[128];
+ char reliab[4] = "";
++ char *delim = ":";
++ char *modname;
+
+ symname = kallsyms_lookup(address, &symsize, &offset,
+ &modname, namebuf);
+@@ -138,13 +138,14 @@ static inline int valid_stack_ptr(struct thread_info *tinfo, void *p, unsigned s
+
+ /* The form of the top of the frame on the stack */
+ struct stack_frame {
+- struct stack_frame *next_frame;
+- unsigned long return_address;
++ struct stack_frame *next_frame;
++ unsigned long return_address;
+ };
+
+-static inline unsigned long print_context_stack(struct thread_info *tinfo,
+- unsigned long *stack, unsigned long bp,
+- const struct stacktrace_ops *ops, void *data)
++static inline unsigned long
++print_context_stack(struct thread_info *tinfo,
++ unsigned long *stack, unsigned long bp,
++ const struct stacktrace_ops *ops, void *data)
+ {
+ struct stack_frame *frame = (struct stack_frame *)bp;
+
+@@ -166,7 +167,7 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo,
+ return bp;
+ }
+
+-#define MSG(msg) ops->warning(data, msg)
++#define MSG(msg) ops->warning(data, msg)
+
+ void dump_trace(struct task_struct *task, struct pt_regs *regs,
+ unsigned long *stack, unsigned long bp,
+@@ -177,6 +178,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
+
+ if (!stack) {
+ unsigned long dummy;
++
+ stack = &dummy;
+ if (task != current)
+ stack = (unsigned long *)task->thread.sp;
+@@ -186,7 +188,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
+ if (!bp) {
+ if (task == current) {
+ /* Grab bp right from our regs */
+- asm ("movl %%ebp, %0" : "=r" (bp) : );
++ asm("movl %%ebp, %0" : "=r" (bp) :);
+ } else {
+ /* bp is the last reg pushed by switch_to */
+ bp = *(unsigned long *) task->thread.sp;
+@@ -196,15 +198,18 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
+
+ while (1) {
+ struct thread_info *context;
++
+ context = (struct thread_info *)
+ ((unsigned long)stack & (~(THREAD_SIZE - 1)));
+ bp = print_context_stack(context, stack, bp, ops, data);
+- /* Should be after the line below, but somewhere
+- in early boot context comes out corrupted and we
+- can't reference it -AK */
++ /*
++ * Should be after the line below, but somewhere
++ * in early boot context comes out corrupted and we
++ * can't reference it:
++ */
+ if (ops->stack(data, "IRQ") < 0)
+ break;
+- stack = (unsigned long*)context->previous_esp;
++ stack = (unsigned long *)context->previous_esp;
+ if (!stack)
+ break;
+ touch_nmi_watchdog();
+@@ -243,15 +248,15 @@ static void print_trace_address(void *data, unsigned long addr, int reliable)
+ }
+
+ static const struct stacktrace_ops print_trace_ops = {
+- .warning = print_trace_warning,
+- .warning_symbol = print_trace_warning_symbol,
+- .stack = print_trace_stack,
+- .address = print_trace_address,
++ .warning = print_trace_warning,
++ .warning_symbol = print_trace_warning_symbol,
++ .stack = print_trace_stack,
++ .address = print_trace_address,
+ };
+
+ static void
+ show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
+- unsigned long *stack, unsigned long bp, char *log_lvl)
++ unsigned long *stack, unsigned long bp, char *log_lvl)
+ {
+ dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl);
+ printk("%s =======================\n", log_lvl);
+@@ -263,21 +268,22 @@ void show_trace(struct task_struct *task, struct pt_regs *regs,
+ show_trace_log_lvl(task, regs, stack, bp, "");
+ }
+
+-static void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
+- unsigned long *sp, unsigned long bp, char *log_lvl)
++static void
++show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
++ unsigned long *sp, unsigned long bp, char *log_lvl)
+ {
+ unsigned long *stack;
+ int i;
+
+ if (sp == NULL) {
+ if (task)
+- sp = (unsigned long*)task->thread.sp;
++ sp = (unsigned long *)task->thread.sp;
+ else
+ sp = (unsigned long *)&sp;
+ }
+
+ stack = sp;
+- for(i = 0; i < kstack_depth_to_print; i++) {
++ for (i = 0; i < kstack_depth_to_print; i++) {
+ if (kstack_end(stack))
+ break;
+ if (i && ((i % 8) == 0))
+@@ -285,6 +291,7 @@ static void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
+ printk("%08lx ", *stack++);
+ }
+ printk("\n%sCall Trace:\n", log_lvl);
++
+ show_trace_log_lvl(task, regs, sp, bp, log_lvl);
+ }
+
+@@ -299,8 +306,8 @@ void show_stack(struct task_struct *task, unsigned long *sp)
+ */
+ void dump_stack(void)
+ {
+- unsigned long stack;
+ unsigned long bp = 0;
++ unsigned long stack;
+
+ #ifdef CONFIG_FRAME_POINTER
+ if (!bp)
+@@ -312,6 +319,7 @@ void dump_stack(void)
+ init_utsname()->release,
+ (int)strcspn(init_utsname()->version, " "),
+ init_utsname()->version);
++
+ show_trace(current, NULL, &stack, bp);
+ }
+
+@@ -323,6 +331,7 @@ void show_registers(struct pt_regs *regs)
+
+ print_modules();
+ __show_registers(regs, 0);
++
+ printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)",
+ TASK_COMM_LEN, current->comm, task_pid_nr(current),
+ current_thread_info(), current, task_thread_info(current));
+@@ -331,10 +340,10 @@ void show_registers(struct pt_regs *regs)
+ * time of the fault..
+ */
+ if (!user_mode_vm(regs)) {
+- u8 *ip;
+ unsigned int code_prologue = code_bytes * 43 / 64;
+ unsigned int code_len = code_bytes;
+ unsigned char c;
++ u8 *ip;
+
+ printk("\n" KERN_EMERG "Stack: ");
+ show_stack_log_lvl(NULL, regs, ®s->sp, 0, KERN_EMERG);
+@@ -361,7 +370,7 @@ void show_registers(struct pt_regs *regs)
+ }
+ }
+ printk("\n");
+-}
++}
+
+ int is_valid_bugaddr(unsigned long ip)
+ {
+@@ -377,10 +386,10 @@ int is_valid_bugaddr(unsigned long ip)
+
+ static int die_counter;
+
+-int __kprobes __die(const char * str, struct pt_regs * regs, long err)
++int __kprobes __die(const char *str, struct pt_regs *regs, long err)
+ {
+- unsigned long sp;
+ unsigned short ss;
++ unsigned long sp;
+
+ printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter);
+ #ifdef CONFIG_PREEMPT
+@@ -395,8 +404,8 @@ int __kprobes __die(const char * str, struct pt_regs * regs, long err)
+ printk("\n");
+
+ if (notify_die(DIE_OOPS, str, regs, err,
+- current->thread.trap_no, SIGSEGV) !=
+- NOTIFY_STOP) {
++ current->thread.trap_no, SIGSEGV) != NOTIFY_STOP) {
++
+ show_registers(regs);
+ /* Executive summary in case the oops scrolled away */
+ sp = (unsigned long) (®s->sp);
+@@ -408,17 +417,18 @@ int __kprobes __die(const char * str, struct pt_regs * regs, long err)
+ printk(KERN_EMERG "EIP: [<%08lx>] ", regs->ip);
+ print_symbol("%s", regs->ip);
+ printk(" SS:ESP %04x:%08lx\n", ss, sp);
++
+ return 0;
+- } else {
+- return 1;
+ }
++
++ return 1;
+ }
+
+ /*
+- * This is gone through when something in the kernel has done something bad and
+- * is about to be terminated.
++ * This is gone through when something in the kernel has done something bad
++ * and is about to be terminated:
+ */
+-void die(const char * str, struct pt_regs * regs, long err)
++void die(const char *str, struct pt_regs *regs, long err)
+ {
+ static struct {
+ raw_spinlock_t lock;
+@@ -440,8 +450,9 @@ void die(const char * str, struct pt_regs * regs, long err)
+ die.lock_owner = smp_processor_id();
+ die.lock_owner_depth = 0;
+ bust_spinlocks(1);
+- } else
++ } else {
+ raw_local_irq_save(flags);
++ }
+
+ if (++die.lock_owner_depth < 3) {
+ report_bug(regs->ip, regs);
+@@ -474,19 +485,20 @@ void die(const char * str, struct pt_regs * regs, long err)
+ do_exit(SIGSEGV);
+ }
+
+-static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
++static inline void
++die_if_kernel(const char *str, struct pt_regs *regs, long err)
+ {
+ if (!user_mode_vm(regs))
+ die(str, regs, err);
+ }
+
+-static void __kprobes do_trap(int trapnr, int signr, char *str, int vm86,
+- struct pt_regs * regs, long error_code,
+- siginfo_t *info)
++static void __kprobes
++do_trap(int trapnr, int signr, char *str, int vm86, struct pt_regs *regs,
++ long error_code, siginfo_t *info)
+ {
+ struct task_struct *tsk = current;
+
+- if (regs->flags & VM_MASK) {
++ if (regs->flags & X86_VM_MASK) {
+ if (vm86)
+ goto vm86_trap;
+ goto trap_signal;
+@@ -495,111 +507,112 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, int vm86,
+ if (!user_mode(regs))
+ goto kernel_trap;
+
+- trap_signal: {
+- /*
+- * We want error_code and trap_no set for userspace faults and
+- * kernelspace faults which result in die(), but not
+- * kernelspace faults which are fixed up. die() gives the
+- * process no chance to handle the signal and notice the
+- * kernel fault information, so that won't result in polluting
+- * the information about previously queued, but not yet
+- * delivered, faults. See also do_general_protection below.
+- */
+- tsk->thread.error_code = error_code;
+- tsk->thread.trap_no = trapnr;
++trap_signal:
++ /*
++ * We want error_code and trap_no set for userspace faults and
++ * kernelspace faults which result in die(), but not
++ * kernelspace faults which are fixed up. die() gives the
++ * process no chance to handle the signal and notice the
++ * kernel fault information, so that won't result in polluting
++ * the information about previously queued, but not yet
++ * delivered, faults. See also do_general_protection below.
++ */
++ tsk->thread.error_code = error_code;
++ tsk->thread.trap_no = trapnr;
+
+- if (info)
+- force_sig_info(signr, info, tsk);
+- else
+- force_sig(signr, tsk);
+- return;
+- }
++ if (info)
++ force_sig_info(signr, info, tsk);
++ else
++ force_sig(signr, tsk);
++ return;
+
+- kernel_trap: {
+- if (!fixup_exception(regs)) {
+- tsk->thread.error_code = error_code;
+- tsk->thread.trap_no = trapnr;
+- die(str, regs, error_code);
+- }
+- return;
++kernel_trap:
++ if (!fixup_exception(regs)) {
++ tsk->thread.error_code = error_code;
++ tsk->thread.trap_no = trapnr;
++ die(str, regs, error_code);
+ }
++ return;
+
+- vm86_trap: {
+- int ret = handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, trapnr);
+- if (ret) goto trap_signal;
+- return;
+- }
++vm86_trap:
++ if (handle_vm86_trap((struct kernel_vm86_regs *) regs,
++ error_code, trapnr))
++ goto trap_signal;
++ return;
+ }
+
+-#define DO_ERROR(trapnr, signr, str, name) \
+-void do_##name(struct pt_regs * regs, long error_code) \
+-{ \
+- if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+- == NOTIFY_STOP) \
+- return; \
+- do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \
++#define DO_ERROR(trapnr, signr, str, name) \
++void do_##name(struct pt_regs *regs, long error_code) \
++{ \
++ if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
++ == NOTIFY_STOP) \
++ return; \
++ do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \
+ }
+
+-#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr, irq) \
+-void do_##name(struct pt_regs * regs, long error_code) \
+-{ \
+- siginfo_t info; \
+- if (irq) \
+- local_irq_enable(); \
+- info.si_signo = signr; \
+- info.si_errno = 0; \
+- info.si_code = sicode; \
+- info.si_addr = (void __user *)siaddr; \
+- if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+- == NOTIFY_STOP) \
+- return; \
+- do_trap(trapnr, signr, str, 0, regs, error_code, &info); \
++#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr, irq) \
++void do_##name(struct pt_regs *regs, long error_code) \
++{ \
++ siginfo_t info; \
++ if (irq) \
++ local_irq_enable(); \
++ info.si_signo = signr; \
++ info.si_errno = 0; \
++ info.si_code = sicode; \
++ info.si_addr = (void __user *)siaddr; \
++ if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
++ == NOTIFY_STOP) \
++ return; \
++ do_trap(trapnr, signr, str, 0, regs, error_code, &info); \
+ }
+
+-#define DO_VM86_ERROR(trapnr, signr, str, name) \
+-void do_##name(struct pt_regs * regs, long error_code) \
+-{ \
+- if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+- == NOTIFY_STOP) \
+- return; \
+- do_trap(trapnr, signr, str, 1, regs, error_code, NULL); \
++#define DO_VM86_ERROR(trapnr, signr, str, name) \
++void do_##name(struct pt_regs *regs, long error_code) \
++{ \
++ if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
++ == NOTIFY_STOP) \
++ return; \
++ do_trap(trapnr, signr, str, 1, regs, error_code, NULL); \
+ }
+
+-#define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
+-void do_##name(struct pt_regs * regs, long error_code) \
+-{ \
+- siginfo_t info; \
+- info.si_signo = signr; \
+- info.si_errno = 0; \
+- info.si_code = sicode; \
+- info.si_addr = (void __user *)siaddr; \
+- trace_hardirqs_fixup(); \
+- if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+- == NOTIFY_STOP) \
+- return; \
+- do_trap(trapnr, signr, str, 1, regs, error_code, &info); \
++#define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
++void do_##name(struct pt_regs *regs, long error_code) \
++{ \
++ siginfo_t info; \
++ info.si_signo = signr; \
++ info.si_errno = 0; \
++ info.si_code = sicode; \
++ info.si_addr = (void __user *)siaddr; \
++ trace_hardirqs_fixup(); \
++ if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
++ == NOTIFY_STOP) \
++ return; \
++ do_trap(trapnr, signr, str, 1, regs, error_code, &info); \
+ }
+
+-DO_VM86_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->ip)
++DO_VM86_ERROR_INFO(0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->ip)
+ #ifndef CONFIG_KPROBES
+-DO_VM86_ERROR( 3, SIGTRAP, "int3", int3)
++DO_VM86_ERROR(3, SIGTRAP, "int3", int3)
+ #endif
+-DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow)
+-DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds)
+-DO_ERROR_INFO( 6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip, 0)
+-DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun)
++DO_VM86_ERROR(4, SIGSEGV, "overflow", overflow)
++DO_VM86_ERROR(5, SIGSEGV, "bounds", bounds)
++DO_ERROR_INFO(6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip, 0)
++DO_ERROR(9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun)
+ DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
+ DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
+ DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
+ DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0, 0)
+-DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0, 1)
++DO_ERROR_INFO(32, SIGILL, "iret exception", iret_error, ILL_BADSTK, 0, 1)
+
+-void __kprobes do_general_protection(struct pt_regs * regs,
+- long error_code)
++void __kprobes do_general_protection(struct pt_regs *regs, long error_code)
+ {
+- int cpu = get_cpu();
+- struct tss_struct *tss = &per_cpu(init_tss, cpu);
+- struct thread_struct *thread = ¤t->thread;
++ struct thread_struct *thread;
++ struct tss_struct *tss;
++ int cpu;
++
++ cpu = get_cpu();
++ tss = &per_cpu(init_tss, cpu);
++ thread = ¤t->thread;
+
+ /*
+ * Perform the lazy TSS's I/O bitmap copy. If the TSS has an
+@@ -616,19 +629,21 @@ void __kprobes do_general_protection(struct pt_regs * regs,
+ * If the previously set map was extending to higher ports
+ * than the current one, pad extra space with 0xff (no access).
+ */
+- if (thread->io_bitmap_max < tss->io_bitmap_max)
++ if (thread->io_bitmap_max < tss->io_bitmap_max) {
+ memset((char *) tss->io_bitmap +
+ thread->io_bitmap_max, 0xff,
+ tss->io_bitmap_max - thread->io_bitmap_max);
++ }
+ tss->io_bitmap_max = thread->io_bitmap_max;
+ tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET;
+ tss->io_bitmap_owner = thread;
+ put_cpu();
++
+ return;
+ }
+ put_cpu();
+
+- if (regs->flags & VM_MASK)
++ if (regs->flags & X86_VM_MASK)
+ goto gp_in_vm86;
+
+ if (!user_mode(regs))
+@@ -636,6 +651,7 @@ void __kprobes do_general_protection(struct pt_regs * regs,
+
+ current->thread.error_code = error_code;
+ current->thread.trap_no = 13;
++
+ if (show_unhandled_signals && unhandled_signal(current, SIGSEGV) &&
+ printk_ratelimit()) {
+ printk(KERN_INFO
+@@ -665,22 +681,25 @@ gp_in_kernel:
+ }
+ }
+
+-static __kprobes void
+-mem_parity_error(unsigned char reason, struct pt_regs * regs)
++static notrace __kprobes void
++mem_parity_error(unsigned char reason, struct pt_regs *regs)
+ {
+- printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on "
+- "CPU %d.\n", reason, smp_processor_id());
+- printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n");
++ printk(KERN_EMERG
++ "Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
++ reason, smp_processor_id());
++
++ printk(KERN_EMERG
++ "You have some hardware problem, likely on the PCI bus.\n");
+
+ #if defined(CONFIG_EDAC)
+- if(edac_handler_set()) {
++ if (edac_handler_set()) {
+ edac_atomic_assert_error();
+ return;
+ }
+ #endif
+
+ if (panic_on_unrecovered_nmi)
+- panic("NMI: Not continuing");
++ panic("NMI: Not continuing");
+
+ printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
+
+@@ -688,8 +707,8 @@ mem_parity_error(unsigned char reason, struct pt_regs * regs)
+ clear_mem_error(reason);
+ }
+
+-static __kprobes void
+-io_check_error(unsigned char reason, struct pt_regs * regs)
++static notrace __kprobes void
++io_check_error(unsigned char reason, struct pt_regs *regs)
+ {
+ unsigned long i;
+
+@@ -699,44 +718,52 @@ io_check_error(unsigned char reason, struct pt_regs * regs)
+ /* Re-enable the IOCK line, wait for a few seconds */
+ reason = (reason & 0xf) | 8;
+ outb(reason, 0x61);
++
+ i = 2000;
+- while (--i) udelay(1000);
++ while (--i)
++ udelay(1000);
++
+ reason &= ~8;
+ outb(reason, 0x61);
+ }
+
+-static __kprobes void
+-unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
++static notrace __kprobes void
++unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
+ {
++ if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
++ return;
+ #ifdef CONFIG_MCA
+- /* Might actually be able to figure out what the guilty party
+- * is. */
+- if( MCA_bus ) {
++ /*
++ * Might actually be able to figure out what the guilty party
++ * is:
++ */
++ if (MCA_bus) {
+ mca_handle_nmi();
+ return;
+ }
+ #endif
+- printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on "
+- "CPU %d.\n", reason, smp_processor_id());
++ printk(KERN_EMERG
++ "Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
++ reason, smp_processor_id());
++
+ printk(KERN_EMERG "Do you have a strange power saving mode enabled?\n");
+ if (panic_on_unrecovered_nmi)
+- panic("NMI: Not continuing");
++ panic("NMI: Not continuing");
+
+ printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
+ }
+
+ static DEFINE_SPINLOCK(nmi_print_lock);
+
+-void __kprobes die_nmi(struct pt_regs *regs, const char *msg)
++void notrace __kprobes die_nmi(struct pt_regs *regs, const char *msg)
+ {
+- if (notify_die(DIE_NMIWATCHDOG, msg, regs, 0, 2, SIGINT) ==
+- NOTIFY_STOP)
++ if (notify_die(DIE_NMIWATCHDOG, msg, regs, 0, 2, SIGINT) == NOTIFY_STOP)
+ return;
+
+ spin_lock(&nmi_print_lock);
+ /*
+ * We are in trouble anyway, lets at least try
+- * to get a message out.
++ * to get a message out:
+ */
+ bust_spinlocks(1);
+ printk(KERN_EMERG "%s", msg);
+@@ -747,9 +774,10 @@ void __kprobes die_nmi(struct pt_regs *regs, const char *msg)
+ spin_unlock(&nmi_print_lock);
+ bust_spinlocks(0);
+
+- /* If we are in kernel we are probably nested up pretty bad
+- * and might aswell get out now while we still can.
+- */
++ /*
++ * If we are in kernel we are probably nested up pretty bad
++ * and might aswell get out now while we still can:
++ */
+ if (!user_mode_vm(regs)) {
+ current->thread.trap_no = 2;
+ crash_kexec(regs);
+@@ -758,14 +786,14 @@ void __kprobes die_nmi(struct pt_regs *regs, const char *msg)
+ do_exit(SIGSEGV);
+ }
+
+-static __kprobes void default_do_nmi(struct pt_regs * regs)
++static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
+ {
+ unsigned char reason = 0;
+
+- /* Only the BSP gets external NMIs from the system. */
++ /* Only the BSP gets external NMIs from the system: */
+ if (!smp_processor_id())
+ reason = get_nmi_reason();
+-
++
+ if (!(reason & 0xc0)) {
+ if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
+ == NOTIFY_STOP)
+@@ -778,8 +806,10 @@ static __kprobes void default_do_nmi(struct pt_regs * regs)
+ if (nmi_watchdog_tick(regs, reason))
+ return;
+ if (!do_nmi_callback(regs, smp_processor_id()))
+-#endif
+ unknown_nmi_error(reason, regs);
++#else
++ unknown_nmi_error(reason, regs);
++#endif
+
+ return;
+ }
+@@ -791,14 +821,14 @@ static __kprobes void default_do_nmi(struct pt_regs * regs)
+ io_check_error(reason, regs);
+ /*
+ * Reassert NMI in case it became active meanwhile
+- * as it's edge-triggered.
++ * as it's edge-triggered:
+ */
+ reassert_nmi();
+ }
+
+ static int ignore_nmis;
+
+-__kprobes void do_nmi(struct pt_regs * regs, long error_code)
++notrace __kprobes void do_nmi(struct pt_regs *regs, long error_code)
+ {
+ int cpu;
+
+@@ -834,9 +864,12 @@ void __kprobes do_int3(struct pt_regs *regs, long error_code)
+ if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
+ == NOTIFY_STOP)
+ return;
+- /* This is an interrupt gate, because kprobes wants interrupts
+- disabled. Normal trap handlers don't. */
++ /*
++ * This is an interrupt gate, because kprobes wants interrupts
++ * disabled. Normal trap handlers don't.
++ */
+ restore_interrupts(regs);
++
+ do_trap(3, SIGTRAP, "int3", 1, regs, error_code, NULL);
+ }
+ #endif
+@@ -851,7 +884,7 @@ void __kprobes do_int3(struct pt_regs *regs, long error_code)
+ * from user space. Such code must not hold kernel locks (since it
+ * can equally take a page fault), therefore it is safe to call
+ * force_sig_info even though that claims and releases locks.
+- *
++ *
+ * Code in ./signal.c ensures that the debug control register
+ * is restored before we deliver any signal, and therefore that
+ * user code runs with the correct debug control register even though
+@@ -863,10 +896,10 @@ void __kprobes do_int3(struct pt_regs *regs, long error_code)
+ * find every occurrence of the TF bit that could be saved away even
+ * by user code)
+ */
+-void __kprobes do_debug(struct pt_regs * regs, long error_code)
++void __kprobes do_debug(struct pt_regs *regs, long error_code)
+ {
+- unsigned int condition;
+ struct task_struct *tsk = current;
++ unsigned int condition;
+
+ trace_hardirqs_fixup();
+
+@@ -891,7 +924,7 @@ void __kprobes do_debug(struct pt_regs * regs, long error_code)
+ goto clear_dr7;
+ }
+
+- if (regs->flags & VM_MASK)
++ if (regs->flags & X86_VM_MASK)
+ goto debug_vm86;
+
+ /* Save debug status register where ptrace can see it */
+@@ -914,7 +947,8 @@ void __kprobes do_debug(struct pt_regs * regs, long error_code)
+ /* Ok, finally something we can handle */
+ send_sigtrap(tsk, regs, error_code);
+
+- /* Disable additional traps. They'll be re-enabled when
++ /*
++ * Disable additional traps. They'll be re-enabled when
+ * the signal is delivered.
+ */
+ clear_dr7:
+@@ -927,7 +961,7 @@ debug_vm86:
+
+ clear_TF_reenable:
+ set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
+- regs->flags &= ~TF_MASK;
++ regs->flags &= ~X86_EFLAGS_TF;
+ return;
+ }
+
+@@ -938,9 +972,10 @@ clear_TF_reenable:
+ */
+ void math_error(void __user *ip)
+ {
+- struct task_struct * task;
++ struct task_struct *task;
++ unsigned short cwd;
++ unsigned short swd;
+ siginfo_t info;
+- unsigned short cwd, swd;
+
+ /*
+ * Save the info for the exception handler and clear the error.
+@@ -966,36 +1001,36 @@ void math_error(void __user *ip)
+ cwd = get_fpu_cwd(task);
+ swd = get_fpu_swd(task);
+ switch (swd & ~cwd & 0x3f) {
+- case 0x000: /* No unmasked exception */
+- return;
+- default: /* Multiple exceptions */
+- break;
+- case 0x001: /* Invalid Op */
+- /*
+- * swd & 0x240 == 0x040: Stack Underflow
+- * swd & 0x240 == 0x240: Stack Overflow
+- * User must clear the SF bit (0x40) if set
+- */
+- info.si_code = FPE_FLTINV;
+- break;
+- case 0x002: /* Denormalize */
+- case 0x010: /* Underflow */
+- info.si_code = FPE_FLTUND;
+- break;
+- case 0x004: /* Zero Divide */
+- info.si_code = FPE_FLTDIV;
+- break;
+- case 0x008: /* Overflow */
+- info.si_code = FPE_FLTOVF;
+- break;
+- case 0x020: /* Precision */
+- info.si_code = FPE_FLTRES;
+- break;
++ case 0x000: /* No unmasked exception */
++ return;
++ default: /* Multiple exceptions */
++ break;
++ case 0x001: /* Invalid Op */
++ /*
++ * swd & 0x240 == 0x040: Stack Underflow
++ * swd & 0x240 == 0x240: Stack Overflow
++ * User must clear the SF bit (0x40) if set
++ */
++ info.si_code = FPE_FLTINV;
++ break;
++ case 0x002: /* Denormalize */
++ case 0x010: /* Underflow */
++ info.si_code = FPE_FLTUND;
++ break;
++ case 0x004: /* Zero Divide */
++ info.si_code = FPE_FLTDIV;
++ break;
++ case 0x008: /* Overflow */
++ info.si_code = FPE_FLTOVF;
++ break;
++ case 0x020: /* Precision */
++ info.si_code = FPE_FLTRES;
++ break;
+ }
+ force_sig_info(SIGFPE, &info, task);
+ }
+
+-void do_coprocessor_error(struct pt_regs * regs, long error_code)
++void do_coprocessor_error(struct pt_regs *regs, long error_code)
+ {
+ ignore_fpu_irq = 1;
+ math_error((void __user *)regs->ip);
+@@ -1003,9 +1038,9 @@ void do_coprocessor_error(struct pt_regs * regs, long error_code)
+
+ static void simd_math_error(void __user *ip)
+ {
+- struct task_struct * task;
+- siginfo_t info;
++ struct task_struct *task;
+ unsigned short mxcsr;
++ siginfo_t info;
+
+ /*
+ * Save the info for the exception handler and clear the error.
+@@ -1026,82 +1061,80 @@ static void simd_math_error(void __user *ip)
+ */
+ mxcsr = get_fpu_mxcsr(task);
+ switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) {
+- case 0x000:
+- default:
+- break;
+- case 0x001: /* Invalid Op */
+- info.si_code = FPE_FLTINV;
+- break;
+- case 0x002: /* Denormalize */
+- case 0x010: /* Underflow */
+- info.si_code = FPE_FLTUND;
+- break;
+- case 0x004: /* Zero Divide */
+- info.si_code = FPE_FLTDIV;
+- break;
+- case 0x008: /* Overflow */
+- info.si_code = FPE_FLTOVF;
+- break;
+- case 0x020: /* Precision */
+- info.si_code = FPE_FLTRES;
+- break;
++ case 0x000:
++ default:
++ break;
++ case 0x001: /* Invalid Op */
++ info.si_code = FPE_FLTINV;
++ break;
++ case 0x002: /* Denormalize */
++ case 0x010: /* Underflow */
++ info.si_code = FPE_FLTUND;
++ break;
++ case 0x004: /* Zero Divide */
++ info.si_code = FPE_FLTDIV;
++ break;
++ case 0x008: /* Overflow */
++ info.si_code = FPE_FLTOVF;
++ break;
++ case 0x020: /* Precision */
++ info.si_code = FPE_FLTRES;
++ break;
+ }
+ force_sig_info(SIGFPE, &info, task);
+ }
+
+-void do_simd_coprocessor_error(struct pt_regs * regs,
+- long error_code)
++void do_simd_coprocessor_error(struct pt_regs *regs, long error_code)
+ {
+ if (cpu_has_xmm) {
+ /* Handle SIMD FPU exceptions on PIII+ processors. */
+ ignore_fpu_irq = 1;
+ simd_math_error((void __user *)regs->ip);
+- } else {
+- /*
+- * Handle strange cache flush from user space exception
+- * in all other cases. This is undocumented behaviour.
+- */
+- if (regs->flags & VM_MASK) {
+- handle_vm86_fault((struct kernel_vm86_regs *)regs,
+- error_code);
+- return;
+- }
+- current->thread.trap_no = 19;
+- current->thread.error_code = error_code;
+- die_if_kernel("cache flush denied", regs, error_code);
+- force_sig(SIGSEGV, current);
++ return;
+ }
++ /*
++ * Handle strange cache flush from user space exception
++ * in all other cases. This is undocumented behaviour.
++ */
++ if (regs->flags & X86_VM_MASK) {
++ handle_vm86_fault((struct kernel_vm86_regs *)regs, error_code);
++ return;
++ }
++ current->thread.trap_no = 19;
++ current->thread.error_code = error_code;
++ die_if_kernel("cache flush denied", regs, error_code);
++ force_sig(SIGSEGV, current);
+ }
+
+-void do_spurious_interrupt_bug(struct pt_regs * regs,
+- long error_code)
++void do_spurious_interrupt_bug(struct pt_regs *regs, long error_code)
+ {
+ #if 0
+ /* No need to warn about this any longer. */
+- printk("Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
++ printk(KERN_INFO "Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
+ #endif
+ }
+
+-unsigned long patch_espfix_desc(unsigned long uesp,
+- unsigned long kesp)
++unsigned long patch_espfix_desc(unsigned long uesp, unsigned long kesp)
+ {
+ struct desc_struct *gdt = __get_cpu_var(gdt_page).gdt;
+ unsigned long base = (kesp - uesp) & -THREAD_SIZE;
+ unsigned long new_kesp = kesp - base;
+ unsigned long lim_pages = (new_kesp | (THREAD_SIZE - 1)) >> PAGE_SHIFT;
+ __u64 desc = *(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS];
++
+ /* Set up base for espfix segment */
+- desc &= 0x00f0ff0000000000ULL;
+- desc |= ((((__u64)base) << 16) & 0x000000ffffff0000ULL) |
++ desc &= 0x00f0ff0000000000ULL;
++ desc |= ((((__u64)base) << 16) & 0x000000ffffff0000ULL) |
+ ((((__u64)base) << 32) & 0xff00000000000000ULL) |
+ ((((__u64)lim_pages) << 32) & 0x000f000000000000ULL) |
+ (lim_pages & 0xffff);
+ *(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS] = desc;
++
+ return new_kesp;
+ }
+
+ /*
+- * 'math_state_restore()' saves the current math information in the
++ * 'math_state_restore()' saves the current math information in the
+ * old math state array, and gets the new ones from the current task
+ *
+ * Careful.. There are problems with IBM-designed IRQ13 behaviour.
+@@ -1115,9 +1148,22 @@ asmlinkage void math_state_restore(void)
+ struct thread_info *thread = current_thread_info();
+ struct task_struct *tsk = thread->task;
+
+- clts(); /* Allow maths ops (or we recurse) */
+- if (!tsk_used_math(tsk))
+- init_fpu(tsk);
++ if (!tsk_used_math(tsk)) {
++ local_irq_enable();
++ /*
++ * does a slab alloc which can sleep
++ */
++ if (init_fpu(tsk)) {
++ /*
++ * ran out of memory!
++ */
++ do_group_exit(SIGKILL);
++ return;
++ }
++ local_irq_disable();
++ }
++
++ clts(); /* Allow maths ops (or we recurse) */
+ restore_fpu(tsk);
+ thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */
+ tsk->fpu_counter++;
+@@ -1128,80 +1174,76 @@ EXPORT_SYMBOL_GPL(math_state_restore);
+
+ asmlinkage void math_emulate(long arg)
+ {
+- printk(KERN_EMERG "math-emulation not enabled and no coprocessor found.\n");
+- printk(KERN_EMERG "killing %s.\n",current->comm);
+- force_sig(SIGFPE,current);
++ printk(KERN_EMERG
++ "math-emulation not enabled and no coprocessor found.\n");
++ printk(KERN_EMERG "killing %s.\n", current->comm);
++ force_sig(SIGFPE, current);
+ schedule();
+ }
+
+ #endif /* CONFIG_MATH_EMULATION */
+
+-
+ void __init trap_init(void)
+ {
+ int i;
+
+ #ifdef CONFIG_EISA
+ void __iomem *p = early_ioremap(0x0FFFD9, 4);
+- if (readl(p) == 'E'+('I'<<8)+('S'<<16)+('A'<<24)) {
++
++ if (readl(p) == 'E' + ('I'<<8) + ('S'<<16) + ('A'<<24))
+ EISA_bus = 1;
+- }
+ early_iounmap(p, 4);
+ #endif
+
+ #ifdef CONFIG_X86_LOCAL_APIC
+ init_apic_mappings();
+ #endif
+-
+- set_trap_gate(0,÷_error);
+- set_intr_gate(1,&debug);
+- set_intr_gate(2,&nmi);
++ set_trap_gate(0, ÷_error);
++ set_intr_gate(1, &debug);
++ set_intr_gate(2, &nmi);
+ set_system_intr_gate(3, &int3); /* int3/4 can be called from all */
+- set_system_gate(4,&overflow);
+- set_trap_gate(5,&bounds);
+- set_trap_gate(6,&invalid_op);
+- set_trap_gate(7,&device_not_available);
+- set_task_gate(8,GDT_ENTRY_DOUBLEFAULT_TSS);
+- set_trap_gate(9,&coprocessor_segment_overrun);
+- set_trap_gate(10,&invalid_TSS);
+- set_trap_gate(11,&segment_not_present);
+- set_trap_gate(12,&stack_segment);
+- set_trap_gate(13,&general_protection);
+- set_intr_gate(14,&page_fault);
+- set_trap_gate(15,&spurious_interrupt_bug);
+- set_trap_gate(16,&coprocessor_error);
+- set_trap_gate(17,&alignment_check);
++ set_system_gate(4, &overflow);
++ set_trap_gate(5, &bounds);
++ set_trap_gate(6, &invalid_op);
++ set_trap_gate(7, &device_not_available);
++ set_task_gate(8, GDT_ENTRY_DOUBLEFAULT_TSS);
++ set_trap_gate(9, &coprocessor_segment_overrun);
++ set_trap_gate(10, &invalid_TSS);
++ set_trap_gate(11, &segment_not_present);
++ set_trap_gate(12, &stack_segment);
++ set_trap_gate(13, &general_protection);
++ set_intr_gate(14, &page_fault);
++ set_trap_gate(15, &spurious_interrupt_bug);
++ set_trap_gate(16, &coprocessor_error);
++ set_trap_gate(17, &alignment_check);
+ #ifdef CONFIG_X86_MCE
+- set_trap_gate(18,&machine_check);
++ set_trap_gate(18, &machine_check);
+ #endif
+- set_trap_gate(19,&simd_coprocessor_error);
++ set_trap_gate(19, &simd_coprocessor_error);
+
+- /*
+- * Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned.
+- * Generate a build-time error if the alignment is wrong.
+- */
+- BUILD_BUG_ON(offsetof(struct task_struct, thread.i387.fxsave) & 15);
+ if (cpu_has_fxsr) {
+ printk(KERN_INFO "Enabling fast FPU save and restore... ");
+ set_in_cr4(X86_CR4_OSFXSR);
+ printk("done.\n");
+ }
+ if (cpu_has_xmm) {
+- printk(KERN_INFO "Enabling unmasked SIMD FPU exception "
+- "support... ");
++ printk(KERN_INFO
++ "Enabling unmasked SIMD FPU exception support... ");
+ set_in_cr4(X86_CR4_OSXMMEXCPT);
+ printk("done.\n");
+ }
+
+- set_system_gate(SYSCALL_VECTOR,&system_call);
++ set_system_gate(SYSCALL_VECTOR, &system_call);
+
+- /* Reserve all the builtin and the syscall vector. */
++ /* Reserve all the builtin and the syscall vector: */
+ for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++)
+ set_bit(i, used_vectors);
++
+ set_bit(SYSCALL_VECTOR, used_vectors);
+
++ init_thread_xstate();
+ /*
+- * Should be a barrier for any external CPU state.
++ * Should be a barrier for any external CPU state:
+ */
+ cpu_init();
+
+@@ -1211,6 +1253,7 @@ void __init trap_init(void)
+ static int __init kstack_setup(char *s)
+ {
+ kstack_depth_to_print = simple_strtoul(s, NULL, 0);
++
+ return 1;
+ }
+ __setup("kstack=", kstack_setup);
+diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c
+index 0454666..adff76e 100644
+--- a/arch/x86/kernel/traps_64.c
++++ b/arch/x86/kernel/traps_64.c
+@@ -33,6 +33,8 @@
+ #include <linux/kdebug.h>
+ #include <linux/utsname.h>
+
++#include <mach_traps.h>
++
+ #if defined(CONFIG_EDAC)
+ #include <linux/edac.h>
+ #endif
+@@ -598,10 +600,16 @@ void die(const char * str, struct pt_regs * regs, long err)
+ oops_end(flags, regs, SIGSEGV);
+ }
+
+-void __kprobes die_nmi(char *str, struct pt_regs *regs, int do_panic)
++notrace __kprobes void
++die_nmi(char *str, struct pt_regs *regs, int do_panic)
+ {
+- unsigned long flags = oops_begin();
++ unsigned long flags;
++
++ if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, 2, SIGINT) ==
++ NOTIFY_STOP)
++ return;
+
++ flags = oops_begin();
+ /*
+ * We are in trouble anyway, lets at least try
+ * to get a message out.
+@@ -765,7 +773,7 @@ asmlinkage void __kprobes do_general_protection(struct pt_regs * regs,
+ die("general protection fault", regs, error_code);
+ }
+
+-static __kprobes void
++static notrace __kprobes void
+ mem_parity_error(unsigned char reason, struct pt_regs * regs)
+ {
+ printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n",
+@@ -789,7 +797,7 @@ mem_parity_error(unsigned char reason, struct pt_regs * regs)
+ outb(reason, 0x61);
+ }
+
+-static __kprobes void
++static notrace __kprobes void
+ io_check_error(unsigned char reason, struct pt_regs * regs)
+ {
+ printk("NMI: IOCK error (debug interrupt?)\n");
+@@ -803,9 +811,11 @@ io_check_error(unsigned char reason, struct pt_regs * regs)
+ outb(reason, 0x61);
+ }
+
+-static __kprobes void
++static notrace __kprobes void
+ unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
+ {
++ if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
++ return;
+ printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n",
+ reason);
+ printk(KERN_EMERG "Do you have a strange power saving mode enabled?\n");
+@@ -818,7 +828,7 @@ unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
+
+ /* Runs on IST stack. This code must keep interrupts off all the time.
+ Nested NMIs are prevented by the CPU. */
+-asmlinkage __kprobes void default_do_nmi(struct pt_regs *regs)
++asmlinkage notrace __kprobes void default_do_nmi(struct pt_regs *regs)
+ {
+ unsigned char reason = 0;
+ int cpu;
+@@ -1114,11 +1124,24 @@ asmlinkage void __attribute__((weak)) mce_threshold_interrupt(void)
+ asmlinkage void math_state_restore(void)
+ {
+ struct task_struct *me = current;
+- clts(); /* Allow maths ops (or we recurse) */
+
+- if (!used_math())
+- init_fpu(me);
+- restore_fpu_checking(&me->thread.i387.fxsave);
++ if (!used_math()) {
++ local_irq_enable();
++ /*
++ * does a slab alloc which can sleep
++ */
++ if (init_fpu(me)) {
++ /*
++ * ran out of memory!
++ */
++ do_group_exit(SIGKILL);
++ return;
++ }
++ local_irq_disable();
++ }
++
++ clts(); /* Allow maths ops (or we recurse) */
++ restore_fpu_checking(&me->thread.xstate->fxsave);
+ task_thread_info(me)->status |= TS_USEDFPU;
+ me->fpu_counter++;
+ }
+@@ -1154,6 +1177,10 @@ void __init trap_init(void)
+ #endif
+
+ /*
++ * initialize the per thread extended state:
++ */
++ init_thread_xstate();
++ /*
+ * Should be a barrier for any external CPU state.
+ */
+ cpu_init();
+diff --git a/arch/x86/kernel/tsc_32.c b/arch/x86/kernel/tsc_32.c
+index c2241e0..e479072 100644
+--- a/arch/x86/kernel/tsc_32.c
++++ b/arch/x86/kernel/tsc_32.c
+@@ -84,8 +84,8 @@ DEFINE_PER_CPU(unsigned long, cyc2ns);
+
+ static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
+ {
+- unsigned long flags, prev_scale, *scale;
+ unsigned long long tsc_now, ns_now;
++ unsigned long flags, *scale;
+
+ local_irq_save(flags);
+ sched_clock_idle_sleep_event();
+@@ -95,7 +95,6 @@ static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
+ rdtscll(tsc_now);
+ ns_now = __cycles_2_ns(tsc_now);
+
+- prev_scale = *scale;
+ if (cpu_khz)
+ *scale = (NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR)/cpu_khz;
+
+@@ -222,9 +221,9 @@ EXPORT_SYMBOL(recalibrate_cpu_khz);
+ * if the CPU frequency is scaled, TSC-based delays will need a different
+ * loops_per_jiffy value to function properly.
+ */
+-static unsigned int ref_freq = 0;
+-static unsigned long loops_per_jiffy_ref = 0;
+-static unsigned long cpu_khz_ref = 0;
++static unsigned int ref_freq;
++static unsigned long loops_per_jiffy_ref;
++static unsigned long cpu_khz_ref;
+
+ static int
+ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data)
+@@ -284,15 +283,28 @@ core_initcall(cpufreq_tsc);
+
+ /* clock source code */
+
+-static unsigned long current_tsc_khz = 0;
++static unsigned long current_tsc_khz;
++static struct clocksource clocksource_tsc;
+
++/*
++ * We compare the TSC to the cycle_last value in the clocksource
++ * structure to avoid a nasty time-warp issue. This can be observed in
++ * a very small window right after one CPU updated cycle_last under
++ * xtime lock and the other CPU reads a TSC value which is smaller
++ * than the cycle_last reference value due to a TSC which is slighty
++ * behind. This delta is nowhere else observable, but in that case it
++ * results in a forward time jump in the range of hours due to the
++ * unsigned delta calculation of the time keeping core code, which is
++ * necessary to support wrapping clocksources like pm timer.
++ */
+ static cycle_t read_tsc(void)
+ {
+ cycle_t ret;
+
+ rdtscll(ret);
+
+- return ret;
++ return ret >= clocksource_tsc.cycle_last ?
++ ret : clocksource_tsc.cycle_last;
+ }
+
+ static struct clocksource clocksource_tsc = {
+@@ -392,13 +404,15 @@ void __init tsc_init(void)
+ int cpu;
+
+ if (!cpu_has_tsc)
+- goto out_no_tsc;
++ return;
+
+ cpu_khz = calculate_cpu_khz();
+ tsc_khz = cpu_khz;
+
+- if (!cpu_khz)
+- goto out_no_tsc;
++ if (!cpu_khz) {
++ mark_tsc_unstable("could not calculate TSC khz");
++ return;
++ }
+
+ printk("Detected %lu.%03lu MHz processor.\n",
+ (unsigned long)cpu_khz / 1000,
+@@ -431,9 +445,4 @@ void __init tsc_init(void)
+ tsc_enabled = 1;
+
+ clocksource_register(&clocksource_tsc);
+-
+- return;
+-
+-out_no_tsc:
+- setup_clear_cpu_cap(X86_FEATURE_TSC);
+ }
+diff --git a/arch/x86/kernel/tsc_64.c b/arch/x86/kernel/tsc_64.c
+index d3bebaa..fcc16e5 100644
+--- a/arch/x86/kernel/tsc_64.c
++++ b/arch/x86/kernel/tsc_64.c
+@@ -11,6 +11,7 @@
+ #include <asm/hpet.h>
+ #include <asm/timex.h>
+ #include <asm/timer.h>
++#include <asm/vgtod.h>
+
+ static int notsc __initdata = 0;
+
+@@ -44,8 +45,8 @@ DEFINE_PER_CPU(unsigned long, cyc2ns);
+
+ static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
+ {
+- unsigned long flags, prev_scale, *scale;
+ unsigned long long tsc_now, ns_now;
++ unsigned long flags, *scale;
+
+ local_irq_save(flags);
+ sched_clock_idle_sleep_event();
+@@ -55,7 +56,6 @@ static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
+ rdtscll(tsc_now);
+ ns_now = __cycles_2_ns(tsc_now);
+
+- prev_scale = *scale;
+ if (cpu_khz)
+ *scale = (NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR)/cpu_khz;
+
+@@ -288,18 +288,34 @@ int __init notsc_setup(char *s)
+
+ __setup("notsc", notsc_setup);
+
++static struct clocksource clocksource_tsc;
+
+-/* clock source code: */
++/*
++ * We compare the TSC to the cycle_last value in the clocksource
++ * structure to avoid a nasty time-warp. This can be observed in a
++ * very small window right after one CPU updated cycle_last under
++ * xtime/vsyscall_gtod lock and the other CPU reads a TSC value which
++ * is smaller than the cycle_last reference value due to a TSC which
++ * is slighty behind. This delta is nowhere else observable, but in
++ * that case it results in a forward time jump in the range of hours
++ * due to the unsigned delta calculation of the time keeping core
++ * code, which is necessary to support wrapping clocksources like pm
++ * timer.
++ */
+ static cycle_t read_tsc(void)
+ {
+ cycle_t ret = (cycle_t)get_cycles();
+- return ret;
++
++ return ret >= clocksource_tsc.cycle_last ?
++ ret : clocksource_tsc.cycle_last;
+ }
+
+ static cycle_t __vsyscall_fn vread_tsc(void)
+ {
+ cycle_t ret = (cycle_t)vget_cycles();
+- return ret;
++
++ return ret >= __vsyscall_gtod_data.clock.cycle_last ?
++ ret : __vsyscall_gtod_data.clock.cycle_last;
+ }
+
+ static struct clocksource clocksource_tsc = {
+diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c
+index 738c210..38f566f 100644
+--- a/arch/x86/kernel/vm86_32.c
++++ b/arch/x86/kernel/vm86_32.c
+@@ -64,7 +64,7 @@
+
+
+ #define KVM86 ((struct kernel_vm86_struct *)regs)
+-#define VMPI KVM86->vm86plus
++#define VMPI KVM86->vm86plus
+
+
+ /*
+@@ -81,7 +81,7 @@
+ #define VFLAGS (*(unsigned short *)&(current->thread.v86flags))
+ #define VEFLAGS (current->thread.v86flags)
+
+-#define set_flags(X,new,mask) \
++#define set_flags(X, new, mask) \
+ ((X) = ((X) & ~(mask)) | ((new) & (mask)))
+
+ #define SAFE_MASK (0xDD5)
+@@ -93,8 +93,10 @@ static int copy_vm86_regs_to_user(struct vm86_regs __user *user,
+ {
+ int ret = 0;
+
+- /* kernel_vm86_regs is missing gs, so copy everything up to
+- (but not including) orig_eax, and then rest including orig_eax. */
++ /*
++ * kernel_vm86_regs is missing gs, so copy everything up to
++ * (but not including) orig_eax, and then rest including orig_eax.
++ */
+ ret += copy_to_user(user, regs, offsetof(struct kernel_vm86_regs, pt.orig_ax));
+ ret += copy_to_user(&user->orig_eax, ®s->pt.orig_ax,
+ sizeof(struct kernel_vm86_regs) -
+@@ -120,7 +122,7 @@ static int copy_vm86_regs_from_user(struct kernel_vm86_regs *regs,
+ return ret;
+ }
+
+-struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs)
++struct pt_regs *save_v86_state(struct kernel_vm86_regs *regs)
+ {
+ struct tss_struct *tss;
+ struct pt_regs *ret;
+@@ -137,9 +139,9 @@ struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs)
+ printk("no vm86_info: BAD\n");
+ do_exit(SIGSEGV);
+ }
+- set_flags(regs->pt.flags, VEFLAGS, VIF_MASK | current->thread.v86mask);
+- tmp = copy_vm86_regs_to_user(¤t->thread.vm86_info->regs,regs);
+- tmp += put_user(current->thread.screen_bitmap,¤t->thread.vm86_info->screen_bitmap);
++ set_flags(regs->pt.flags, VEFLAGS, X86_EFLAGS_VIF | current->thread.v86mask);
++ tmp = copy_vm86_regs_to_user(¤t->thread.vm86_info->regs, regs);
++ tmp += put_user(current->thread.screen_bitmap, ¤t->thread.vm86_info->screen_bitmap);
+ if (tmp) {
+ printk("vm86: could not access userspace vm86_info\n");
+ do_exit(SIGSEGV);
+@@ -237,20 +239,21 @@ asmlinkage int sys_vm86(struct pt_regs regs)
+
+ tsk = current;
+ switch (regs.bx) {
+- case VM86_REQUEST_IRQ:
+- case VM86_FREE_IRQ:
+- case VM86_GET_IRQ_BITS:
+- case VM86_GET_AND_RESET_IRQ:
+- ret = do_vm86_irq_handling(regs.bx, (int)regs.cx);
+- goto out;
+- case VM86_PLUS_INSTALL_CHECK:
+- /* NOTE: on old vm86 stuff this will return the error
+- from access_ok(), because the subfunction is
+- interpreted as (invalid) address to vm86_struct.
+- So the installation check works.
+- */
+- ret = 0;
+- goto out;
++ case VM86_REQUEST_IRQ:
++ case VM86_FREE_IRQ:
++ case VM86_GET_IRQ_BITS:
++ case VM86_GET_AND_RESET_IRQ:
++ ret = do_vm86_irq_handling(regs.bx, (int)regs.cx);
++ goto out;
++ case VM86_PLUS_INSTALL_CHECK:
++ /*
++ * NOTE: on old vm86 stuff this will return the error
++ * from access_ok(), because the subfunction is
++ * interpreted as (invalid) address to vm86_struct.
++ * So the installation check works.
++ */
++ ret = 0;
++ goto out;
+ }
+
+ /* we come here only for functions VM86_ENTER, VM86_ENTER_NO_BYPASS */
+@@ -296,21 +299,21 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
+ VEFLAGS = info->regs.pt.flags;
+ info->regs.pt.flags &= SAFE_MASK;
+ info->regs.pt.flags |= info->regs32->flags & ~SAFE_MASK;
+- info->regs.pt.flags |= VM_MASK;
++ info->regs.pt.flags |= X86_VM_MASK;
+
+ switch (info->cpu_type) {
+- case CPU_286:
+- tsk->thread.v86mask = 0;
+- break;
+- case CPU_386:
+- tsk->thread.v86mask = NT_MASK | IOPL_MASK;
+- break;
+- case CPU_486:
+- tsk->thread.v86mask = AC_MASK | NT_MASK | IOPL_MASK;
+- break;
+- default:
+- tsk->thread.v86mask = ID_MASK | AC_MASK | NT_MASK | IOPL_MASK;
+- break;
++ case CPU_286:
++ tsk->thread.v86mask = 0;
++ break;
++ case CPU_386:
++ tsk->thread.v86mask = X86_EFLAGS_NT | X86_EFLAGS_IOPL;
++ break;
++ case CPU_486:
++ tsk->thread.v86mask = X86_EFLAGS_AC | X86_EFLAGS_NT | X86_EFLAGS_IOPL;
++ break;
++ default:
++ tsk->thread.v86mask = X86_EFLAGS_ID | X86_EFLAGS_AC | X86_EFLAGS_NT | X86_EFLAGS_IOPL;
++ break;
+ }
+
+ /*
+@@ -346,9 +349,9 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
+ /* we never return here */
+ }
+
+-static inline void return_to_32bit(struct kernel_vm86_regs * regs16, int retval)
++static inline void return_to_32bit(struct kernel_vm86_regs *regs16, int retval)
+ {
+- struct pt_regs * regs32;
++ struct pt_regs *regs32;
+
+ regs32 = save_v86_state(regs16);
+ regs32->ax = retval;
+@@ -358,29 +361,30 @@ static inline void return_to_32bit(struct kernel_vm86_regs * regs16, int retval)
+ : : "r" (regs32), "r" (current_thread_info()));
+ }
+
+-static inline void set_IF(struct kernel_vm86_regs * regs)
++static inline void set_IF(struct kernel_vm86_regs *regs)
+ {
+- VEFLAGS |= VIF_MASK;
+- if (VEFLAGS & VIP_MASK)
++ VEFLAGS |= X86_EFLAGS_VIF;
++ if (VEFLAGS & X86_EFLAGS_VIP)
+ return_to_32bit(regs, VM86_STI);
+ }
+
+-static inline void clear_IF(struct kernel_vm86_regs * regs)
++static inline void clear_IF(struct kernel_vm86_regs *regs)
+ {
+- VEFLAGS &= ~VIF_MASK;
++ VEFLAGS &= ~X86_EFLAGS_VIF;
+ }
+
+-static inline void clear_TF(struct kernel_vm86_regs * regs)
++static inline void clear_TF(struct kernel_vm86_regs *regs)
+ {
+- regs->pt.flags &= ~TF_MASK;
++ regs->pt.flags &= ~X86_EFLAGS_TF;
+ }
+
+-static inline void clear_AC(struct kernel_vm86_regs * regs)
++static inline void clear_AC(struct kernel_vm86_regs *regs)
+ {
+- regs->pt.flags &= ~AC_MASK;
++ regs->pt.flags &= ~X86_EFLAGS_AC;
+ }
+
+-/* It is correct to call set_IF(regs) from the set_vflags_*
++/*
++ * It is correct to call set_IF(regs) from the set_vflags_*
+ * functions. However someone forgot to call clear_IF(regs)
+ * in the opposite case.
+ * After the command sequence CLI PUSHF STI POPF you should
+@@ -391,41 +395,41 @@ static inline void clear_AC(struct kernel_vm86_regs * regs)
+ * [KD]
+ */
+
+-static inline void set_vflags_long(unsigned long flags, struct kernel_vm86_regs * regs)
++static inline void set_vflags_long(unsigned long flags, struct kernel_vm86_regs *regs)
+ {
+ set_flags(VEFLAGS, flags, current->thread.v86mask);
+ set_flags(regs->pt.flags, flags, SAFE_MASK);
+- if (flags & IF_MASK)
++ if (flags & X86_EFLAGS_IF)
+ set_IF(regs);
+ else
+ clear_IF(regs);
+ }
+
+-static inline void set_vflags_short(unsigned short flags, struct kernel_vm86_regs * regs)
++static inline void set_vflags_short(unsigned short flags, struct kernel_vm86_regs *regs)
+ {
+ set_flags(VFLAGS, flags, current->thread.v86mask);
+ set_flags(regs->pt.flags, flags, SAFE_MASK);
+- if (flags & IF_MASK)
++ if (flags & X86_EFLAGS_IF)
+ set_IF(regs);
+ else
+ clear_IF(regs);
+ }
+
+-static inline unsigned long get_vflags(struct kernel_vm86_regs * regs)
++static inline unsigned long get_vflags(struct kernel_vm86_regs *regs)
+ {
+ unsigned long flags = regs->pt.flags & RETURN_MASK;
+
+- if (VEFLAGS & VIF_MASK)
+- flags |= IF_MASK;
+- flags |= IOPL_MASK;
++ if (VEFLAGS & X86_EFLAGS_VIF)
++ flags |= X86_EFLAGS_IF;
++ flags |= X86_EFLAGS_IOPL;
+ return flags | (VEFLAGS & current->thread.v86mask);
+ }
+
+-static inline int is_revectored(int nr, struct revectored_struct * bitmap)
++static inline int is_revectored(int nr, struct revectored_struct *bitmap)
+ {
+ __asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0"
+ :"=r" (nr)
+- :"m" (*bitmap),"r" (nr));
++ :"m" (*bitmap), "r" (nr));
+ return nr;
+ }
+
+@@ -437,7 +441,7 @@ static inline int is_revectored(int nr, struct revectored_struct * bitmap)
+ ptr--; \
+ if (put_user(__val, base + ptr) < 0) \
+ goto err_label; \
+- } while(0)
++ } while (0)
+
+ #define pushw(base, ptr, val, err_label) \
+ do { \
+@@ -448,7 +452,7 @@ static inline int is_revectored(int nr, struct revectored_struct * bitmap)
+ ptr--; \
+ if (put_user(val_byte(__val, 0), base + ptr) < 0) \
+ goto err_label; \
+- } while(0)
++ } while (0)
+
+ #define pushl(base, ptr, val, err_label) \
+ do { \
+@@ -465,7 +469,7 @@ static inline int is_revectored(int nr, struct revectored_struct * bitmap)
+ ptr--; \
+ if (put_user(val_byte(__val, 0), base + ptr) < 0) \
+ goto err_label; \
+- } while(0)
++ } while (0)
+
+ #define popb(base, ptr, err_label) \
+ ({ \
+@@ -512,7 +516,7 @@ static inline int is_revectored(int nr, struct revectored_struct * bitmap)
+ * in userspace is always better than an Oops anyway.) [KD]
+ */
+ static void do_int(struct kernel_vm86_regs *regs, int i,
+- unsigned char __user * ssp, unsigned short sp)
++ unsigned char __user *ssp, unsigned short sp)
+ {
+ unsigned long __user *intr_ptr;
+ unsigned long segoffs;
+@@ -521,7 +525,7 @@ static void do_int(struct kernel_vm86_regs *regs, int i,
+ goto cannot_handle;
+ if (is_revectored(i, &KVM86->int_revectored))
+ goto cannot_handle;
+- if (i==0x21 && is_revectored(AH(regs),&KVM86->int21_revectored))
++ if (i == 0x21 && is_revectored(AH(regs), &KVM86->int21_revectored))
+ goto cannot_handle;
+ intr_ptr = (unsigned long __user *) (i << 2);
+ if (get_user(segoffs, intr_ptr))
+@@ -543,30 +547,23 @@ cannot_handle:
+ return_to_32bit(regs, VM86_INTx + (i << 8));
+ }
+
+-int handle_vm86_trap(struct kernel_vm86_regs * regs, long error_code, int trapno)
++int handle_vm86_trap(struct kernel_vm86_regs *regs, long error_code, int trapno)
+ {
+ if (VMPI.is_vm86pus) {
+- if ( (trapno==3) || (trapno==1) )
++ if ((trapno == 3) || (trapno == 1))
+ return_to_32bit(regs, VM86_TRAP + (trapno << 8));
+ do_int(regs, trapno, (unsigned char __user *) (regs->pt.ss << 4), SP(regs));
+ return 0;
+ }
+- if (trapno !=1)
++ if (trapno != 1)
+ return 1; /* we let this handle by the calling routine */
+- if (current->ptrace & PT_PTRACED) {
+- unsigned long flags;
+- spin_lock_irqsave(¤t->sighand->siglock, flags);
+- sigdelset(¤t->blocked, SIGTRAP);
+- recalc_sigpending();
+- spin_unlock_irqrestore(¤t->sighand->siglock, flags);
+- }
+- send_sig(SIGTRAP, current, 1);
+ current->thread.trap_no = trapno;
+ current->thread.error_code = error_code;
++ force_sig(SIGTRAP, current);
+ return 0;
+ }
+
+-void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
++void handle_vm86_fault(struct kernel_vm86_regs *regs, long error_code)
+ {
+ unsigned char opcode;
+ unsigned char __user *csp;
+@@ -576,11 +573,11 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
+
+ #define CHECK_IF_IN_TRAP \
+ if (VMPI.vm86dbg_active && VMPI.vm86dbg_TFpendig) \
+- newflags |= TF_MASK
++ newflags |= X86_EFLAGS_TF
+ #define VM86_FAULT_RETURN do { \
+- if (VMPI.force_return_for_pic && (VEFLAGS & (IF_MASK | VIF_MASK))) \
++ if (VMPI.force_return_for_pic && (VEFLAGS & (X86_EFLAGS_IF | X86_EFLAGS_VIF))) \
+ return_to_32bit(regs, VM86_PICRETURN); \
+- if (orig_flags & TF_MASK) \
++ if (orig_flags & X86_EFLAGS_TF) \
+ handle_vm86_trap(regs, 0, 1); \
+ return; } while (0)
+
+@@ -595,17 +592,17 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
+ pref_done = 0;
+ do {
+ switch (opcode = popb(csp, ip, simulate_sigsegv)) {
+- case 0x66: /* 32-bit data */ data32=1; break;
+- case 0x67: /* 32-bit address */ break;
+- case 0x2e: /* CS */ break;
+- case 0x3e: /* DS */ break;
+- case 0x26: /* ES */ break;
+- case 0x36: /* SS */ break;
+- case 0x65: /* GS */ break;
+- case 0x64: /* FS */ break;
+- case 0xf2: /* repnz */ break;
+- case 0xf3: /* rep */ break;
+- default: pref_done = 1;
++ case 0x66: /* 32-bit data */ data32 = 1; break;
++ case 0x67: /* 32-bit address */ break;
++ case 0x2e: /* CS */ break;
++ case 0x3e: /* DS */ break;
++ case 0x26: /* ES */ break;
++ case 0x36: /* SS */ break;
++ case 0x65: /* GS */ break;
++ case 0x64: /* FS */ break;
++ case 0xf2: /* repnz */ break;
++ case 0xf3: /* rep */ break;
++ default: pref_done = 1;
+ }
+ } while (!pref_done);
+
+@@ -628,7 +625,7 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
+ {
+ unsigned long newflags;
+ if (data32) {
+- newflags=popl(ssp, sp, simulate_sigsegv);
++ newflags = popl(ssp, sp, simulate_sigsegv);
+ SP(regs) += 4;
+ } else {
+ newflags = popw(ssp, sp, simulate_sigsegv);
+@@ -636,20 +633,20 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
+ }
+ IP(regs) = ip;
+ CHECK_IF_IN_TRAP;
+- if (data32) {
++ if (data32)
+ set_vflags_long(newflags, regs);
+- } else {
++ else
+ set_vflags_short(newflags, regs);
+- }
++
+ VM86_FAULT_RETURN;
+ }
+
+ /* int xx */
+ case 0xcd: {
+- int intno=popb(csp, ip, simulate_sigsegv);
++ int intno = popb(csp, ip, simulate_sigsegv);
+ IP(regs) = ip;
+ if (VMPI.vm86dbg_active) {
+- if ( (1 << (intno &7)) & VMPI.vm86dbg_intxxtab[intno >> 3] )
++ if ((1 << (intno & 7)) & VMPI.vm86dbg_intxxtab[intno >> 3])
+ return_to_32bit(regs, VM86_INTx + (intno << 8));
+ }
+ do_int(regs, intno, ssp, sp);
+@@ -663,9 +660,9 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
+ unsigned long newcs;
+ unsigned long newflags;
+ if (data32) {
+- newip=popl(ssp, sp, simulate_sigsegv);
+- newcs=popl(ssp, sp, simulate_sigsegv);
+- newflags=popl(ssp, sp, simulate_sigsegv);
++ newip = popl(ssp, sp, simulate_sigsegv);
++ newcs = popl(ssp, sp, simulate_sigsegv);
++ newflags = popl(ssp, sp, simulate_sigsegv);
+ SP(regs) += 12;
+ } else {
+ newip = popw(ssp, sp, simulate_sigsegv);
+@@ -734,18 +731,18 @@ static struct vm86_irqs {
+ static DEFINE_SPINLOCK(irqbits_lock);
+ static int irqbits;
+
+-#define ALLOWED_SIGS ( 1 /* 0 = don't send a signal */ \
++#define ALLOWED_SIGS (1 /* 0 = don't send a signal */ \
+ | (1 << SIGUSR1) | (1 << SIGUSR2) | (1 << SIGIO) | (1 << SIGURG) \
+- | (1 << SIGUNUSED) )
+-
++ | (1 << SIGUNUSED))
++
+ static irqreturn_t irq_handler(int intno, void *dev_id)
+ {
+ int irq_bit;
+ unsigned long flags;
+
+- spin_lock_irqsave(&irqbits_lock, flags);
++ spin_lock_irqsave(&irqbits_lock, flags);
+ irq_bit = 1 << intno;
+- if ((irqbits & irq_bit) || ! vm86_irqs[intno].tsk)
++ if ((irqbits & irq_bit) || !vm86_irqs[intno].tsk)
+ goto out;
+ irqbits |= irq_bit;
+ if (vm86_irqs[intno].sig)
+@@ -759,7 +756,7 @@ static irqreturn_t irq_handler(int intno, void *dev_id)
+ return IRQ_HANDLED;
+
+ out:
+- spin_unlock_irqrestore(&irqbits_lock, flags);
++ spin_unlock_irqrestore(&irqbits_lock, flags);
+ return IRQ_NONE;
+ }
+
+@@ -770,9 +767,9 @@ static inline void free_vm86_irq(int irqnumber)
+ free_irq(irqnumber, NULL);
+ vm86_irqs[irqnumber].tsk = NULL;
+
+- spin_lock_irqsave(&irqbits_lock, flags);
++ spin_lock_irqsave(&irqbits_lock, flags);
+ irqbits &= ~(1 << irqnumber);
+- spin_unlock_irqrestore(&irqbits_lock, flags);
++ spin_unlock_irqrestore(&irqbits_lock, flags);
+ }
+
+ void release_vm86_irqs(struct task_struct *task)
+@@ -788,10 +785,10 @@ static inline int get_and_reset_irq(int irqnumber)
+ int bit;
+ unsigned long flags;
+ int ret = 0;
+-
++
+ if (invalid_vm86_irq(irqnumber)) return 0;
+ if (vm86_irqs[irqnumber].tsk != current) return 0;
+- spin_lock_irqsave(&irqbits_lock, flags);
++ spin_lock_irqsave(&irqbits_lock, flags);
+ bit = irqbits & (1 << irqnumber);
+ irqbits &= ~bit;
+ if (bit) {
+@@ -799,7 +796,7 @@ static inline int get_and_reset_irq(int irqnumber)
+ ret = 1;
+ }
+
+- spin_unlock_irqrestore(&irqbits_lock, flags);
++ spin_unlock_irqrestore(&irqbits_lock, flags);
+ return ret;
+ }
+
+diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c
+index 12affe1..956f389 100644
+--- a/arch/x86/kernel/vmi_32.c
++++ b/arch/x86/kernel/vmi_32.c
+@@ -320,7 +320,7 @@ static void check_zeroed_page(u32 pfn, int type, struct page *page)
+ * pdes need to be zeroed.
+ */
+ if (type & VMI_PAGE_CLONE)
+- limit = USER_PTRS_PER_PGD;
++ limit = KERNEL_PGD_BOUNDARY;
+ for (i = 0; i < limit; i++)
+ BUG_ON(ptr[i]);
+ }
+@@ -392,13 +392,13 @@ static void *vmi_kmap_atomic_pte(struct page *page, enum km_type type)
+ }
+ #endif
+
+-static void vmi_allocate_pt(struct mm_struct *mm, u32 pfn)
++static void vmi_allocate_pte(struct mm_struct *mm, u32 pfn)
+ {
+ vmi_set_page_type(pfn, VMI_PAGE_L1);
+ vmi_ops.allocate_page(pfn, VMI_PAGE_L1, 0, 0, 0);
+ }
+
+-static void vmi_allocate_pd(struct mm_struct *mm, u32 pfn)
++static void vmi_allocate_pmd(struct mm_struct *mm, u32 pfn)
+ {
+ /*
+ * This call comes in very early, before mem_map is setup.
+@@ -409,20 +409,20 @@ static void vmi_allocate_pd(struct mm_struct *mm, u32 pfn)
+ vmi_ops.allocate_page(pfn, VMI_PAGE_L2, 0, 0, 0);
+ }
+
+-static void vmi_allocate_pd_clone(u32 pfn, u32 clonepfn, u32 start, u32 count)
++static void vmi_allocate_pmd_clone(u32 pfn, u32 clonepfn, u32 start, u32 count)
+ {
+ vmi_set_page_type(pfn, VMI_PAGE_L2 | VMI_PAGE_CLONE);
+ vmi_check_page_type(clonepfn, VMI_PAGE_L2);
+ vmi_ops.allocate_page(pfn, VMI_PAGE_L2 | VMI_PAGE_CLONE, clonepfn, start, count);
+ }
+
+-static void vmi_release_pt(u32 pfn)
++static void vmi_release_pte(u32 pfn)
+ {
+ vmi_ops.release_page(pfn, VMI_PAGE_L1);
+ vmi_set_page_type(pfn, VMI_PAGE_NORMAL);
+ }
+
+-static void vmi_release_pd(u32 pfn)
++static void vmi_release_pmd(u32 pfn)
+ {
+ vmi_ops.release_page(pfn, VMI_PAGE_L2);
+ vmi_set_page_type(pfn, VMI_PAGE_NORMAL);
+@@ -871,15 +871,15 @@ static inline int __init activate_vmi(void)
+
+ vmi_ops.allocate_page = vmi_get_function(VMI_CALL_AllocatePage);
+ if (vmi_ops.allocate_page) {
+- pv_mmu_ops.alloc_pt = vmi_allocate_pt;
+- pv_mmu_ops.alloc_pd = vmi_allocate_pd;
+- pv_mmu_ops.alloc_pd_clone = vmi_allocate_pd_clone;
++ pv_mmu_ops.alloc_pte = vmi_allocate_pte;
++ pv_mmu_ops.alloc_pmd = vmi_allocate_pmd;
++ pv_mmu_ops.alloc_pmd_clone = vmi_allocate_pmd_clone;
+ }
+
+ vmi_ops.release_page = vmi_get_function(VMI_CALL_ReleasePage);
+ if (vmi_ops.release_page) {
+- pv_mmu_ops.release_pt = vmi_release_pt;
+- pv_mmu_ops.release_pd = vmi_release_pd;
++ pv_mmu_ops.release_pte = vmi_release_pte;
++ pv_mmu_ops.release_pmd = vmi_release_pmd;
+ }
+
+ /* Set linear is needed in all cases */
+diff --git a/arch/x86/kernel/vmlinux_32.lds.S b/arch/x86/kernel/vmlinux_32.lds.S
+index 2ffa965..ce5ed08 100644
+--- a/arch/x86/kernel/vmlinux_32.lds.S
++++ b/arch/x86/kernel/vmlinux_32.lds.S
+@@ -149,6 +149,11 @@ SECTIONS
+ *(.con_initcall.init)
+ __con_initcall_end = .;
+ }
++ .x86cpuvendor.init : AT(ADDR(.x86cpuvendor.init) - LOAD_OFFSET) {
++ __x86cpuvendor_start = .;
++ *(.x86cpuvendor.init)
++ __x86cpuvendor_end = .;
++ }
+ SECURITY_INIT
+ . = ALIGN(4);
+ .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) {
+diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S
+index fab1322..b7ab3c3 100644
+--- a/arch/x86/kernel/vmlinux_64.lds.S
++++ b/arch/x86/kernel/vmlinux_64.lds.S
+@@ -177,6 +177,11 @@ SECTIONS
+ *(.con_initcall.init)
+ }
+ __con_initcall_end = .;
++ __x86cpuvendor_start = .;
++ .x86cpuvendor.init : AT(ADDR(.x86cpuvendor.init) - LOAD_OFFSET) {
++ *(.x86cpuvendor.init)
++ }
++ __x86cpuvendor_end = .;
+ SECURITY_INIT
+
+ . = ALIGN(8);
+@@ -247,3 +252,9 @@ SECTIONS
+
+ DWARF_DEBUG
+ }
++
++/*
++ * Build-time check on the image size:
++ */
++ASSERT((_end - _text <= KERNEL_IMAGE_SIZE),
++ "kernel image bigger than KERNEL_IMAGE_SIZE")
+diff --git a/arch/x86/kernel/vsmp_64.c b/arch/x86/kernel/vsmp_64.c
+index d971210..caf2a26 100644
+--- a/arch/x86/kernel/vsmp_64.c
++++ b/arch/x86/kernel/vsmp_64.c
+@@ -8,6 +8,8 @@
+ *
+ * Ravikiran Thirumalai <kiran at scalemp.com>,
+ * Shai Fultheim <shai at scalemp.com>
++ * Paravirt ops integration: Glauber de Oliveira Costa <gcosta at redhat.com>,
++ * Ravikiran Thirumalai <kiran at scalemp.com>
+ */
+
+ #include <linux/init.h>
+@@ -15,38 +17,137 @@
+ #include <linux/pci_regs.h>
+ #include <asm/pci-direct.h>
+ #include <asm/io.h>
++#include <asm/paravirt.h>
+
+-static int __init vsmp_init(void)
++#if defined CONFIG_PCI && defined CONFIG_PARAVIRT
++/*
++ * Interrupt control on vSMPowered systems:
++ * ~AC is a shadow of IF. If IF is 'on' AC should be 'off'
++ * and vice versa.
++ */
++
++static unsigned long vsmp_save_fl(void)
+ {
+- void *address;
+- unsigned int cap, ctl;
++ unsigned long flags = native_save_fl();
+
+- if (!early_pci_allowed())
+- return 0;
++ if (!(flags & X86_EFLAGS_IF) || (flags & X86_EFLAGS_AC))
++ flags &= ~X86_EFLAGS_IF;
++ return flags;
++}
+
+- /* Check if we are running on a ScaleMP vSMP box */
+- if ((read_pci_config_16(0, 0x1f, 0, PCI_VENDOR_ID) !=
+- PCI_VENDOR_ID_SCALEMP) ||
+- (read_pci_config_16(0, 0x1f, 0, PCI_DEVICE_ID) !=
+- PCI_DEVICE_ID_SCALEMP_VSMP_CTL))
+- return 0;
++static void vsmp_restore_fl(unsigned long flags)
++{
++ if (flags & X86_EFLAGS_IF)
++ flags &= ~X86_EFLAGS_AC;
++ else
++ flags |= X86_EFLAGS_AC;
++ native_restore_fl(flags);
++}
++
++static void vsmp_irq_disable(void)
++{
++ unsigned long flags = native_save_fl();
++
++ native_restore_fl((flags & ~X86_EFLAGS_IF) | X86_EFLAGS_AC);
++}
++
++static void vsmp_irq_enable(void)
++{
++ unsigned long flags = native_save_fl();
++
++ native_restore_fl((flags | X86_EFLAGS_IF) & (~X86_EFLAGS_AC));
++}
++
++static unsigned __init vsmp_patch(u8 type, u16 clobbers, void *ibuf,
++ unsigned long addr, unsigned len)
++{
++ switch (type) {
++ case PARAVIRT_PATCH(pv_irq_ops.irq_enable):
++ case PARAVIRT_PATCH(pv_irq_ops.irq_disable):
++ case PARAVIRT_PATCH(pv_irq_ops.save_fl):
++ case PARAVIRT_PATCH(pv_irq_ops.restore_fl):
++ return paravirt_patch_default(type, clobbers, ibuf, addr, len);
++ default:
++ return native_patch(type, clobbers, ibuf, addr, len);
++ }
++
++}
++
++static void __init set_vsmp_pv_ops(void)
++{
++ void *address;
++ unsigned int cap, ctl, cfg;
+
+ /* set vSMP magic bits to indicate vSMP capable kernel */
+- address = ioremap(read_pci_config(0, 0x1f, 0, PCI_BASE_ADDRESS_0), 8);
++ cfg = read_pci_config(0, 0x1f, 0, PCI_BASE_ADDRESS_0);
++ address = early_ioremap(cfg, 8);
+ cap = readl(address);
+ ctl = readl(address + 4);
+ printk(KERN_INFO "vSMP CTL: capabilities:0x%08x control:0x%08x\n",
+ cap, ctl);
+ if (cap & ctl & (1 << 4)) {
+- /* Turn on vSMP IRQ fastpath handling (see system.h) */
++ /* Setup irq ops and turn on vSMP IRQ fastpath handling */
++ pv_irq_ops.irq_disable = vsmp_irq_disable;
++ pv_irq_ops.irq_enable = vsmp_irq_enable;
++ pv_irq_ops.save_fl = vsmp_save_fl;
++ pv_irq_ops.restore_fl = vsmp_restore_fl;
++ pv_init_ops.patch = vsmp_patch;
++
+ ctl &= ~(1 << 4);
+ writel(ctl, address + 4);
+ ctl = readl(address + 4);
+ printk(KERN_INFO "vSMP CTL: control set to:0x%08x\n", ctl);
+ }
+
+- iounmap(address);
++ early_iounmap(address, 8);
++}
++#else
++static void __init set_vsmp_pv_ops(void)
++{
++}
++#endif
++
++#ifdef CONFIG_PCI
++static int is_vsmp = -1;
++
++static void __init detect_vsmp_box(void)
++{
++ is_vsmp = 0;
++
++ if (!early_pci_allowed())
++ return;
++
++ /* Check if we are running on a ScaleMP vSMPowered box */
++ if (read_pci_config(0, 0x1f, 0, PCI_VENDOR_ID) ==
++ (PCI_VENDOR_ID_SCALEMP | (PCI_DEVICE_ID_SCALEMP_VSMP_CTL << 16)))
++ is_vsmp = 1;
++}
++
++int is_vsmp_box(void)
++{
++ if (is_vsmp != -1)
++ return is_vsmp;
++ else {
++ WARN_ON_ONCE(1);
++ return 0;
++ }
++}
++#else
++static int __init detect_vsmp_box(void)
++{
++}
++int is_vsmp_box(void)
++{
+ return 0;
+ }
++#endif
+
+-core_initcall(vsmp_init);
++void __init vsmp_init(void)
++{
++ detect_vsmp_box();
++ if (!is_vsmp_box())
++ return;
++
++ set_vsmp_pv_ops();
++ return;
++}
+diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
+index edff4c9..61efa2f 100644
+--- a/arch/x86/kernel/vsyscall_64.c
++++ b/arch/x86/kernel/vsyscall_64.c
+@@ -216,7 +216,7 @@ vgetcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
+ return 0;
+ }
+
+-long __vsyscall(3) venosys_1(void)
++static long __vsyscall(3) venosys_1(void)
+ {
+ return -ENOSYS;
+ }
+diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
+index a66e9c1..58882f9 100644
+--- a/arch/x86/kernel/x8664_ksyms_64.c
++++ b/arch/x86/kernel/x8664_ksyms_64.c
+@@ -4,7 +4,6 @@
+ #include <linux/module.h>
+ #include <linux/smp.h>
+
+-#include <asm/semaphore.h>
+ #include <asm/processor.h>
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -12,11 +11,6 @@
+
+ EXPORT_SYMBOL(kernel_thread);
+
+-EXPORT_SYMBOL(__down_failed);
+-EXPORT_SYMBOL(__down_failed_interruptible);
+-EXPORT_SYMBOL(__down_failed_trylock);
+-EXPORT_SYMBOL(__up_wakeup);
+-
+ EXPORT_SYMBOL(__get_user_1);
+ EXPORT_SYMBOL(__get_user_2);
+ EXPORT_SYMBOL(__get_user_4);
+@@ -35,15 +29,17 @@ EXPORT_SYMBOL(__copy_from_user_inatomic);
+ EXPORT_SYMBOL(copy_page);
+ EXPORT_SYMBOL(clear_page);
+
+-/* Export string functions. We normally rely on gcc builtin for most of these,
+- but gcc sometimes decides not to inline them. */
++/*
++ * Export string functions. We normally rely on gcc builtin for most of these,
++ * but gcc sometimes decides not to inline them.
++ */
+ #undef memcpy
+ #undef memset
+ #undef memmove
+
+-extern void * memset(void *,int,__kernel_size_t);
+-extern void * memcpy(void *,const void *,__kernel_size_t);
+-extern void * __memcpy(void *,const void *,__kernel_size_t);
++extern void *memset(void *, int, __kernel_size_t);
++extern void *memcpy(void *, const void *, __kernel_size_t);
++extern void *__memcpy(void *, const void *, __kernel_size_t);
+
+ EXPORT_SYMBOL(memset);
+ EXPORT_SYMBOL(memcpy);
+diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
+index 3335b45..af65b2d 100644
+--- a/arch/x86/lguest/boot.c
++++ b/arch/x86/lguest/boot.c
+@@ -661,7 +661,7 @@ static int lguest_clockevent_set_next_event(unsigned long delta,
+ if (delta < LG_CLOCK_MIN_DELTA) {
+ if (printk_ratelimit())
+ printk(KERN_DEBUG "%s: small delta %lu ns\n",
+- __FUNCTION__, delta);
++ __func__, delta);
+ return -ETIME;
+ }
+
+diff --git a/arch/x86/lib/memcpy_32.c b/arch/x86/lib/memcpy_32.c
+index 37756b6..5415a9d 100644
+--- a/arch/x86/lib/memcpy_32.c
++++ b/arch/x86/lib/memcpy_32.c
+@@ -25,7 +25,7 @@ void *memmove(void *dest, const void *src, size_t n)
+ int d0, d1, d2;
+
+ if (dest < src) {
+- memcpy(dest,src,n);
++ memcpy(dest, src, n);
+ } else {
+ __asm__ __volatile__(
+ "std\n\t"
+diff --git a/arch/x86/lib/memmove_64.c b/arch/x86/lib/memmove_64.c
+index 80175e4..0a33909 100644
+--- a/arch/x86/lib/memmove_64.c
++++ b/arch/x86/lib/memmove_64.c
+@@ -6,10 +6,10 @@
+ #include <linux/module.h>
+
+ #undef memmove
+-void *memmove(void * dest,const void *src,size_t count)
++void *memmove(void *dest, const void *src, size_t count)
+ {
+- if (dest < src) {
+- return memcpy(dest,src,count);
++ if (dest < src) {
++ return memcpy(dest, src, count);
+ } else {
+ char *p = dest + count;
+ const char *s = src + count;
+@@ -17,5 +17,5 @@ void *memmove(void * dest,const void *src,size_t count)
+ *--p = *--s;
+ }
+ return dest;
+-}
++}
+ EXPORT_SYMBOL(memmove);
+diff --git a/arch/x86/lib/mmx_32.c b/arch/x86/lib/mmx_32.c
+index cc9b4a4..c9f2d9b 100644
+--- a/arch/x86/lib/mmx_32.c
++++ b/arch/x86/lib/mmx_32.c
+@@ -1,32 +1,30 @@
+-#include <linux/types.h>
+-#include <linux/string.h>
+-#include <linux/sched.h>
+-#include <linux/hardirq.h>
+-#include <linux/module.h>
+-
+-#include <asm/asm.h>
+-#include <asm/i387.h>
+-
+-
+ /*
+ * MMX 3DNow! library helper functions
+ *
+ * To do:
+- * We can use MMX just for prefetch in IRQ's. This may be a win.
++ * We can use MMX just for prefetch in IRQ's. This may be a win.
+ * (reported so on K6-III)
+ * We should use a better code neutral filler for the short jump
+ * leal ebx. [ebx] is apparently best for K6-2, but Cyrix ??
+ * We also want to clobber the filler register so we don't get any
+- * register forwarding stalls on the filler.
++ * register forwarding stalls on the filler.
+ *
+ * Add *user handling. Checksums are not a win with MMX on any CPU
+ * tested so far for any MMX solution figured.
+ *
+- * 22/09/2000 - Arjan van de Ven
+- * Improved for non-egineering-sample Athlons
++ * 22/09/2000 - Arjan van de Ven
++ * Improved for non-egineering-sample Athlons
+ *
+ */
+-
++#include <linux/hardirq.h>
++#include <linux/string.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++
++#include <asm/i387.h>
++#include <asm/asm.h>
++
+ void *_mmx_memcpy(void *to, const void *from, size_t len)
+ {
+ void *p;
+@@ -51,12 +49,10 @@ void *_mmx_memcpy(void *to, const void *from, size_t len)
+ "3: movw $0x1AEB, 1b\n" /* jmp on 26 bytes */
+ " jmp 2b\n"
+ ".previous\n"
+- _ASM_EXTABLE(1b,3b)
+- : : "r" (from) );
+-
+-
+- for(; i>5; i--)
+- {
++ _ASM_EXTABLE(1b, 3b)
++ : : "r" (from));
++
++ for ( ; i > 5; i--) {
+ __asm__ __volatile__ (
+ "1: prefetch 320(%0)\n"
+ "2: movq (%0), %%mm0\n"
+@@ -79,14 +75,14 @@ void *_mmx_memcpy(void *to, const void *from, size_t len)
+ "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */
+ " jmp 2b\n"
+ ".previous\n"
+- _ASM_EXTABLE(1b,3b)
+- : : "r" (from), "r" (to) : "memory");
+- from+=64;
+- to+=64;
++ _ASM_EXTABLE(1b, 3b)
++ : : "r" (from), "r" (to) : "memory");
++
++ from += 64;
++ to += 64;
+ }
+
+- for(; i>0; i--)
+- {
++ for ( ; i > 0; i--) {
+ __asm__ __volatile__ (
+ " movq (%0), %%mm0\n"
+ " movq 8(%0), %%mm1\n"
+@@ -104,17 +100,20 @@ void *_mmx_memcpy(void *to, const void *from, size_t len)
+ " movq %%mm1, 40(%1)\n"
+ " movq %%mm2, 48(%1)\n"
+ " movq %%mm3, 56(%1)\n"
+- : : "r" (from), "r" (to) : "memory");
+- from+=64;
+- to+=64;
++ : : "r" (from), "r" (to) : "memory");
++
++ from += 64;
++ to += 64;
+ }
+ /*
+- * Now do the tail of the block
++ * Now do the tail of the block:
+ */
+- __memcpy(to, from, len&63);
++ __memcpy(to, from, len & 63);
+ kernel_fpu_end();
++
+ return p;
+ }
++EXPORT_SYMBOL(_mmx_memcpy);
+
+ #ifdef CONFIG_MK7
+
+@@ -128,13 +127,12 @@ static void fast_clear_page(void *page)
+ int i;
+
+ kernel_fpu_begin();
+-
++
+ __asm__ __volatile__ (
+ " pxor %%mm0, %%mm0\n" : :
+ );
+
+- for(i=0;i<4096/64;i++)
+- {
++ for (i = 0; i < 4096/64; i++) {
+ __asm__ __volatile__ (
+ " movntq %%mm0, (%0)\n"
+ " movntq %%mm0, 8(%0)\n"
+@@ -145,14 +143,15 @@ static void fast_clear_page(void *page)
+ " movntq %%mm0, 48(%0)\n"
+ " movntq %%mm0, 56(%0)\n"
+ : : "r" (page) : "memory");
+- page+=64;
++ page += 64;
+ }
+- /* since movntq is weakly-ordered, a "sfence" is needed to become
+- * ordered again.
++
++ /*
++ * Since movntq is weakly-ordered, a "sfence" is needed to become
++ * ordered again:
+ */
+- __asm__ __volatile__ (
+- " sfence \n" : :
+- );
++ __asm__ __volatile__("sfence\n"::);
++
+ kernel_fpu_end();
+ }
+
+@@ -162,10 +161,11 @@ static void fast_copy_page(void *to, void *from)
+
+ kernel_fpu_begin();
+
+- /* maybe the prefetch stuff can go before the expensive fnsave...
++ /*
++ * maybe the prefetch stuff can go before the expensive fnsave...
+ * but that is for later. -AV
+ */
+- __asm__ __volatile__ (
++ __asm__ __volatile__(
+ "1: prefetch (%0)\n"
+ " prefetch 64(%0)\n"
+ " prefetch 128(%0)\n"
+@@ -176,11 +176,9 @@ static void fast_copy_page(void *to, void *from)
+ "3: movw $0x1AEB, 1b\n" /* jmp on 26 bytes */
+ " jmp 2b\n"
+ ".previous\n"
+- _ASM_EXTABLE(1b,3b)
+- : : "r" (from) );
++ _ASM_EXTABLE(1b, 3b) : : "r" (from));
+
+- for(i=0; i<(4096-320)/64; i++)
+- {
++ for (i = 0; i < (4096-320)/64; i++) {
+ __asm__ __volatile__ (
+ "1: prefetch 320(%0)\n"
+ "2: movq (%0), %%mm0\n"
+@@ -203,13 +201,13 @@ static void fast_copy_page(void *to, void *from)
+ "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */
+ " jmp 2b\n"
+ ".previous\n"
+- _ASM_EXTABLE(1b,3b)
+- : : "r" (from), "r" (to) : "memory");
+- from+=64;
+- to+=64;
++ _ASM_EXTABLE(1b, 3b) : : "r" (from), "r" (to) : "memory");
++
++ from += 64;
++ to += 64;
+ }
+- for(i=(4096-320)/64; i<4096/64; i++)
+- {
++
++ for (i = (4096-320)/64; i < 4096/64; i++) {
+ __asm__ __volatile__ (
+ "2: movq (%0), %%mm0\n"
+ " movntq %%mm0, (%1)\n"
+@@ -227,37 +225,34 @@ static void fast_copy_page(void *to, void *from)
+ " movntq %%mm6, 48(%1)\n"
+ " movq 56(%0), %%mm7\n"
+ " movntq %%mm7, 56(%1)\n"
+- : : "r" (from), "r" (to) : "memory");
+- from+=64;
+- to+=64;
++ : : "r" (from), "r" (to) : "memory");
++ from += 64;
++ to += 64;
+ }
+- /* since movntq is weakly-ordered, a "sfence" is needed to become
+- * ordered again.
++ /*
++ * Since movntq is weakly-ordered, a "sfence" is needed to become
++ * ordered again:
+ */
+- __asm__ __volatile__ (
+- " sfence \n" : :
+- );
++ __asm__ __volatile__("sfence \n"::);
+ kernel_fpu_end();
+ }
+
+-#else
++#else /* CONFIG_MK7 */
+
+ /*
+ * Generic MMX implementation without K7 specific streaming
+ */
+-
+ static void fast_clear_page(void *page)
+ {
+ int i;
+-
++
+ kernel_fpu_begin();
+-
++
+ __asm__ __volatile__ (
+ " pxor %%mm0, %%mm0\n" : :
+ );
+
+- for(i=0;i<4096/128;i++)
+- {
++ for (i = 0; i < 4096/128; i++) {
+ __asm__ __volatile__ (
+ " movq %%mm0, (%0)\n"
+ " movq %%mm0, 8(%0)\n"
+@@ -275,8 +270,8 @@ static void fast_clear_page(void *page)
+ " movq %%mm0, 104(%0)\n"
+ " movq %%mm0, 112(%0)\n"
+ " movq %%mm0, 120(%0)\n"
+- : : "r" (page) : "memory");
+- page+=128;
++ : : "r" (page) : "memory");
++ page += 128;
+ }
+
+ kernel_fpu_end();
+@@ -285,8 +280,7 @@ static void fast_clear_page(void *page)
+ static void fast_copy_page(void *to, void *from)
+ {
+ int i;
+-
+-
++
+ kernel_fpu_begin();
+
+ __asm__ __volatile__ (
+@@ -300,11 +294,9 @@ static void fast_copy_page(void *to, void *from)
+ "3: movw $0x1AEB, 1b\n" /* jmp on 26 bytes */
+ " jmp 2b\n"
+ ".previous\n"
+- _ASM_EXTABLE(1b,3b)
+- : : "r" (from) );
++ _ASM_EXTABLE(1b, 3b) : : "r" (from));
+
+- for(i=0; i<4096/64; i++)
+- {
++ for (i = 0; i < 4096/64; i++) {
+ __asm__ __volatile__ (
+ "1: prefetch 320(%0)\n"
+ "2: movq (%0), %%mm0\n"
+@@ -327,60 +319,59 @@ static void fast_copy_page(void *to, void *from)
+ "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */
+ " jmp 2b\n"
+ ".previous\n"
+- _ASM_EXTABLE(1b,3b)
+- : : "r" (from), "r" (to) : "memory");
+- from+=64;
+- to+=64;
++ _ASM_EXTABLE(1b, 3b)
++ : : "r" (from), "r" (to) : "memory");
++
++ from += 64;
++ to += 64;
+ }
+ kernel_fpu_end();
+ }
+
+-
+-#endif
++#endif /* !CONFIG_MK7 */
+
+ /*
+- * Favour MMX for page clear and copy.
++ * Favour MMX for page clear and copy:
+ */
+-
+-static void slow_zero_page(void * page)
++static void slow_zero_page(void *page)
+ {
+ int d0, d1;
+- __asm__ __volatile__( \
+- "cld\n\t" \
+- "rep ; stosl" \
+- : "=&c" (d0), "=&D" (d1)
+- :"a" (0),"1" (page),"0" (1024)
+- :"memory");
++
++ __asm__ __volatile__(
++ "cld\n\t"
++ "rep ; stosl"
++
++ : "=&c" (d0), "=&D" (d1)
++ :"a" (0), "1" (page), "0" (1024)
++ :"memory");
+ }
+-
+-void mmx_clear_page(void * page)
++
++void mmx_clear_page(void *page)
+ {
+- if(unlikely(in_interrupt()))
++ if (unlikely(in_interrupt()))
+ slow_zero_page(page);
+ else
+ fast_clear_page(page);
+ }
++EXPORT_SYMBOL(mmx_clear_page);
+
+ static void slow_copy_page(void *to, void *from)
+ {
+ int d0, d1, d2;
+- __asm__ __volatile__( \
+- "cld\n\t" \
+- "rep ; movsl" \
+- : "=&c" (d0), "=&D" (d1), "=&S" (d2) \
+- : "0" (1024),"1" ((long) to),"2" ((long) from) \
++
++ __asm__ __volatile__(
++ "cld\n\t"
++ "rep ; movsl"
++ : "=&c" (d0), "=&D" (d1), "=&S" (d2)
++ : "0" (1024), "1" ((long) to), "2" ((long) from)
+ : "memory");
+ }
+-
+
+ void mmx_copy_page(void *to, void *from)
+ {
+- if(unlikely(in_interrupt()))
++ if (unlikely(in_interrupt()))
+ slow_copy_page(to, from);
+ else
+ fast_copy_page(to, from);
+ }
+-
+-EXPORT_SYMBOL(_mmx_memcpy);
+-EXPORT_SYMBOL(mmx_clear_page);
+ EXPORT_SYMBOL(mmx_copy_page);
+diff --git a/arch/x86/lib/semaphore_32.S b/arch/x86/lib/semaphore_32.S
+index 3899bd3..648fe47 100644
+--- a/arch/x86/lib/semaphore_32.S
++++ b/arch/x86/lib/semaphore_32.S
+@@ -30,89 +30,6 @@
+ * value or just clobbered..
+ */
+ .section .sched.text, "ax"
+-ENTRY(__down_failed)
+- CFI_STARTPROC
+- FRAME
+- pushl %edx
+- CFI_ADJUST_CFA_OFFSET 4
+- CFI_REL_OFFSET edx,0
+- pushl %ecx
+- CFI_ADJUST_CFA_OFFSET 4
+- CFI_REL_OFFSET ecx,0
+- call __down
+- popl %ecx
+- CFI_ADJUST_CFA_OFFSET -4
+- CFI_RESTORE ecx
+- popl %edx
+- CFI_ADJUST_CFA_OFFSET -4
+- CFI_RESTORE edx
+- ENDFRAME
+- ret
+- CFI_ENDPROC
+- ENDPROC(__down_failed)
+-
+-ENTRY(__down_failed_interruptible)
+- CFI_STARTPROC
+- FRAME
+- pushl %edx
+- CFI_ADJUST_CFA_OFFSET 4
+- CFI_REL_OFFSET edx,0
+- pushl %ecx
+- CFI_ADJUST_CFA_OFFSET 4
+- CFI_REL_OFFSET ecx,0
+- call __down_interruptible
+- popl %ecx
+- CFI_ADJUST_CFA_OFFSET -4
+- CFI_RESTORE ecx
+- popl %edx
+- CFI_ADJUST_CFA_OFFSET -4
+- CFI_RESTORE edx
+- ENDFRAME
+- ret
+- CFI_ENDPROC
+- ENDPROC(__down_failed_interruptible)
+-
+-ENTRY(__down_failed_trylock)
+- CFI_STARTPROC
+- FRAME
+- pushl %edx
+- CFI_ADJUST_CFA_OFFSET 4
+- CFI_REL_OFFSET edx,0
+- pushl %ecx
+- CFI_ADJUST_CFA_OFFSET 4
+- CFI_REL_OFFSET ecx,0
+- call __down_trylock
+- popl %ecx
+- CFI_ADJUST_CFA_OFFSET -4
+- CFI_RESTORE ecx
+- popl %edx
+- CFI_ADJUST_CFA_OFFSET -4
+- CFI_RESTORE edx
+- ENDFRAME
+- ret
+- CFI_ENDPROC
+- ENDPROC(__down_failed_trylock)
+-
+-ENTRY(__up_wakeup)
+- CFI_STARTPROC
+- FRAME
+- pushl %edx
+- CFI_ADJUST_CFA_OFFSET 4
+- CFI_REL_OFFSET edx,0
+- pushl %ecx
+- CFI_ADJUST_CFA_OFFSET 4
+- CFI_REL_OFFSET ecx,0
+- call __up
+- popl %ecx
+- CFI_ADJUST_CFA_OFFSET -4
+- CFI_RESTORE ecx
+- popl %edx
+- CFI_ADJUST_CFA_OFFSET -4
+- CFI_RESTORE edx
+- ENDFRAME
+- ret
+- CFI_ENDPROC
+- ENDPROC(__up_wakeup)
+
+ /*
+ * rw spinlock fallbacks
+diff --git a/arch/x86/lib/string_32.c b/arch/x86/lib/string_32.c
+index c2c0504..94972e7 100644
+--- a/arch/x86/lib/string_32.c
++++ b/arch/x86/lib/string_32.c
+@@ -14,25 +14,25 @@
+ #include <linux/module.h>
+
+ #ifdef __HAVE_ARCH_STRCPY
+-char *strcpy(char * dest,const char *src)
++char *strcpy(char *dest, const char *src)
+ {
+ int d0, d1, d2;
+- asm volatile( "1:\tlodsb\n\t"
++ asm volatile("1:\tlodsb\n\t"
+ "stosb\n\t"
+ "testb %%al,%%al\n\t"
+ "jne 1b"
+ : "=&S" (d0), "=&D" (d1), "=&a" (d2)
+- :"0" (src),"1" (dest) : "memory");
++ :"0" (src), "1" (dest) : "memory");
+ return dest;
+ }
+ EXPORT_SYMBOL(strcpy);
+ #endif
+
+ #ifdef __HAVE_ARCH_STRNCPY
+-char *strncpy(char * dest,const char *src,size_t count)
++char *strncpy(char *dest, const char *src, size_t count)
+ {
+ int d0, d1, d2, d3;
+- asm volatile( "1:\tdecl %2\n\t"
++ asm volatile("1:\tdecl %2\n\t"
+ "js 2f\n\t"
+ "lodsb\n\t"
+ "stosb\n\t"
+@@ -42,17 +42,17 @@ char *strncpy(char * dest,const char *src,size_t count)
+ "stosb\n"
+ "2:"
+ : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3)
+- :"0" (src),"1" (dest),"2" (count) : "memory");
++ :"0" (src), "1" (dest), "2" (count) : "memory");
+ return dest;
+ }
+ EXPORT_SYMBOL(strncpy);
+ #endif
+
+ #ifdef __HAVE_ARCH_STRCAT
+-char *strcat(char * dest,const char * src)
++char *strcat(char *dest, const char *src)
+ {
+ int d0, d1, d2, d3;
+- asm volatile( "repne\n\t"
++ asm volatile("repne\n\t"
+ "scasb\n\t"
+ "decl %1\n"
+ "1:\tlodsb\n\t"
+@@ -67,10 +67,10 @@ EXPORT_SYMBOL(strcat);
+ #endif
+
+ #ifdef __HAVE_ARCH_STRNCAT
+-char *strncat(char * dest,const char * src,size_t count)
++char *strncat(char *dest, const char *src, size_t count)
+ {
+ int d0, d1, d2, d3;
+- asm volatile( "repne\n\t"
++ asm volatile("repne\n\t"
+ "scasb\n\t"
+ "decl %1\n\t"
+ "movl %8,%3\n"
+@@ -83,7 +83,7 @@ char *strncat(char * dest,const char * src,size_t count)
+ "2:\txorl %2,%2\n\t"
+ "stosb"
+ : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
+- : "0" (src),"1" (dest),"2" (0),"3" (0xffffffffu), "g" (count)
++ : "0" (src), "1" (dest), "2" (0), "3" (0xffffffffu), "g" (count)
+ : "memory");
+ return dest;
+ }
+@@ -91,11 +91,11 @@ EXPORT_SYMBOL(strncat);
+ #endif
+
+ #ifdef __HAVE_ARCH_STRCMP
+-int strcmp(const char * cs,const char * ct)
++int strcmp(const char *cs, const char *ct)
+ {
+ int d0, d1;
+ int res;
+- asm volatile( "1:\tlodsb\n\t"
++ asm volatile("1:\tlodsb\n\t"
+ "scasb\n\t"
+ "jne 2f\n\t"
+ "testb %%al,%%al\n\t"
+@@ -106,7 +106,7 @@ int strcmp(const char * cs,const char * ct)
+ "orb $1,%%al\n"
+ "3:"
+ :"=a" (res), "=&S" (d0), "=&D" (d1)
+- :"1" (cs),"2" (ct)
++ :"1" (cs), "2" (ct)
+ :"memory");
+ return res;
+ }
+@@ -114,11 +114,11 @@ EXPORT_SYMBOL(strcmp);
+ #endif
+
+ #ifdef __HAVE_ARCH_STRNCMP
+-int strncmp(const char * cs,const char * ct,size_t count)
++int strncmp(const char *cs, const char *ct, size_t count)
+ {
+ int res;
+ int d0, d1, d2;
+- asm volatile( "1:\tdecl %3\n\t"
++ asm volatile("1:\tdecl %3\n\t"
+ "js 2f\n\t"
+ "lodsb\n\t"
+ "scasb\n\t"
+@@ -131,7 +131,7 @@ int strncmp(const char * cs,const char * ct,size_t count)
+ "orb $1,%%al\n"
+ "4:"
+ :"=a" (res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
+- :"1" (cs),"2" (ct),"3" (count)
++ :"1" (cs), "2" (ct), "3" (count)
+ :"memory");
+ return res;
+ }
+@@ -139,11 +139,11 @@ EXPORT_SYMBOL(strncmp);
+ #endif
+
+ #ifdef __HAVE_ARCH_STRCHR
+-char *strchr(const char * s, int c)
++char *strchr(const char *s, int c)
+ {
+ int d0;
+- char * res;
+- asm volatile( "movb %%al,%%ah\n"
++ char *res;
++ asm volatile("movb %%al,%%ah\n"
+ "1:\tlodsb\n\t"
+ "cmpb %%ah,%%al\n\t"
+ "je 2f\n\t"
+@@ -153,7 +153,7 @@ char *strchr(const char * s, int c)
+ "2:\tmovl %1,%0\n\t"
+ "decl %0"
+ :"=a" (res), "=&S" (d0)
+- :"1" (s),"0" (c)
++ :"1" (s), "0" (c)
+ :"memory");
+ return res;
+ }
+@@ -161,16 +161,16 @@ EXPORT_SYMBOL(strchr);
+ #endif
+
+ #ifdef __HAVE_ARCH_STRLEN
+-size_t strlen(const char * s)
++size_t strlen(const char *s)
+ {
+ int d0;
+ int res;
+- asm volatile( "repne\n\t"
++ asm volatile("repne\n\t"
+ "scasb\n\t"
+ "notl %0\n\t"
+ "decl %0"
+ :"=c" (res), "=&D" (d0)
+- :"1" (s),"a" (0), "0" (0xffffffffu)
++ :"1" (s), "a" (0), "0" (0xffffffffu)
+ :"memory");
+ return res;
+ }
+@@ -178,19 +178,19 @@ EXPORT_SYMBOL(strlen);
+ #endif
+
+ #ifdef __HAVE_ARCH_MEMCHR
+-void *memchr(const void *cs,int c,size_t count)
++void *memchr(const void *cs, int c, size_t count)
+ {
+ int d0;
+ void *res;
+ if (!count)
+ return NULL;
+- asm volatile( "repne\n\t"
++ asm volatile("repne\n\t"
+ "scasb\n\t"
+ "je 1f\n\t"
+ "movl $1,%0\n"
+ "1:\tdecl %0"
+ :"=D" (res), "=&c" (d0)
+- :"a" (c),"0" (cs),"1" (count)
++ :"a" (c), "0" (cs), "1" (count)
+ :"memory");
+ return res;
+ }
+@@ -198,7 +198,7 @@ EXPORT_SYMBOL(memchr);
+ #endif
+
+ #ifdef __HAVE_ARCH_MEMSCAN
+-void *memscan(void * addr, int c, size_t size)
++void *memscan(void *addr, int c, size_t size)
+ {
+ if (!size)
+ return addr;
+@@ -219,7 +219,7 @@ size_t strnlen(const char *s, size_t count)
+ {
+ int d0;
+ int res;
+- asm volatile( "movl %2,%0\n\t"
++ asm volatile("movl %2,%0\n\t"
+ "jmp 2f\n"
+ "1:\tcmpb $0,(%0)\n\t"
+ "je 3f\n\t"
+@@ -229,7 +229,7 @@ size_t strnlen(const char *s, size_t count)
+ "jne 1b\n"
+ "3:\tsubl %2,%0"
+ :"=a" (res), "=&d" (d0)
+- :"c" (s),"1" (count)
++ :"c" (s), "1" (count)
+ :"memory");
+ return res;
+ }
+diff --git a/arch/x86/lib/strstr_32.c b/arch/x86/lib/strstr_32.c
+index a3dafbf..42e8a50 100644
+--- a/arch/x86/lib/strstr_32.c
++++ b/arch/x86/lib/strstr_32.c
+@@ -1,9 +1,9 @@
+ #include <linux/string.h>
+
+-char * strstr(const char * cs,const char * ct)
++char *strstr(const char *cs, const char *ct)
+ {
+ int d0, d1;
+-register char * __res;
++register char *__res;
+ __asm__ __volatile__(
+ "movl %6,%%edi\n\t"
+ "repne\n\t"
+diff --git a/arch/x86/lib/thunk_64.S b/arch/x86/lib/thunk_64.S
+index 8b92d42..e009251 100644
+--- a/arch/x86/lib/thunk_64.S
++++ b/arch/x86/lib/thunk_64.S
+@@ -41,11 +41,6 @@
+ thunk rwsem_downgrade_thunk,rwsem_downgrade_wake
+ #endif
+
+- thunk __down_failed,__down
+- thunk_retrax __down_failed_interruptible,__down_interruptible
+- thunk_retrax __down_failed_trylock,__down_trylock
+- thunk __up_wakeup,__up
+-
+ #ifdef CONFIG_TRACE_IRQFLAGS
+ thunk trace_hardirqs_on_thunk,trace_hardirqs_on
+ thunk trace_hardirqs_off_thunk,trace_hardirqs_off
+diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
+index e849b99..24e6094 100644
+--- a/arch/x86/lib/usercopy_32.c
++++ b/arch/x86/lib/usercopy_32.c
+@@ -1,4 +1,4 @@
+-/*
++/*
+ * User address space access functions.
+ * The non inlined parts of asm-i386/uaccess.h are here.
+ *
+@@ -22,14 +22,14 @@ static inline int __movsl_is_ok(unsigned long a1, unsigned long a2, unsigned lon
+ #endif
+ return 1;
+ }
+-#define movsl_is_ok(a1,a2,n) \
+- __movsl_is_ok((unsigned long)(a1),(unsigned long)(a2),(n))
++#define movsl_is_ok(a1, a2, n) \
++ __movsl_is_ok((unsigned long)(a1), (unsigned long)(a2), (n))
+
+ /*
+ * Copy a null terminated string from userspace.
+ */
+
+-#define __do_strncpy_from_user(dst,src,count,res) \
++#define __do_strncpy_from_user(dst, src, count, res) \
+ do { \
+ int __d0, __d1, __d2; \
+ might_sleep(); \
+@@ -61,7 +61,7 @@ do { \
+ * least @count bytes long.
+ * @src: Source address, in user space.
+ * @count: Maximum number of bytes to copy, including the trailing NUL.
+- *
++ *
+ * Copies a NUL-terminated string from userspace to kernel space.
+ * Caller must check the specified block with access_ok() before calling
+ * this function.
+@@ -90,7 +90,7 @@ EXPORT_SYMBOL(__strncpy_from_user);
+ * least @count bytes long.
+ * @src: Source address, in user space.
+ * @count: Maximum number of bytes to copy, including the trailing NUL.
+- *
++ *
+ * Copies a NUL-terminated string from userspace to kernel space.
+ *
+ * On success, returns the length of the string (not including the trailing
+@@ -120,7 +120,7 @@ EXPORT_SYMBOL(strncpy_from_user);
+ do { \
+ int __d0; \
+ might_sleep(); \
+- __asm__ __volatile__( \
++ __asm__ __volatile__( \
+ "0: rep; stosl\n" \
+ " movl %2,%0\n" \
+ "1: rep; stosb\n" \
+@@ -333,17 +333,17 @@ __copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size)
+ __asm__ __volatile__(
+ " .align 2,0x90\n"
+ "0: movl 32(%4), %%eax\n"
+- " cmpl $67, %0\n"
+- " jbe 2f\n"
++ " cmpl $67, %0\n"
++ " jbe 2f\n"
+ "1: movl 64(%4), %%eax\n"
+- " .align 2,0x90\n"
+- "2: movl 0(%4), %%eax\n"
+- "21: movl 4(%4), %%edx\n"
+- " movl %%eax, 0(%3)\n"
+- " movl %%edx, 4(%3)\n"
+- "3: movl 8(%4), %%eax\n"
+- "31: movl 12(%4),%%edx\n"
+- " movl %%eax, 8(%3)\n"
++ " .align 2,0x90\n"
++ "2: movl 0(%4), %%eax\n"
++ "21: movl 4(%4), %%edx\n"
++ " movl %%eax, 0(%3)\n"
++ " movl %%edx, 4(%3)\n"
++ "3: movl 8(%4), %%eax\n"
++ "31: movl 12(%4),%%edx\n"
++ " movl %%eax, 8(%3)\n"
+ " movl %%edx, 12(%3)\n"
+ "4: movl 16(%4), %%eax\n"
+ "41: movl 20(%4), %%edx\n"
+@@ -369,38 +369,38 @@ __copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size)
+ "91: movl 60(%4), %%edx\n"
+ " movl %%eax, 56(%3)\n"
+ " movl %%edx, 60(%3)\n"
+- " addl $-64, %0\n"
+- " addl $64, %4\n"
+- " addl $64, %3\n"
+- " cmpl $63, %0\n"
+- " ja 0b\n"
+- "5: movl %0, %%eax\n"
+- " shrl $2, %0\n"
+- " andl $3, %%eax\n"
+- " cld\n"
+- "6: rep; movsl\n"
++ " addl $-64, %0\n"
++ " addl $64, %4\n"
++ " addl $64, %3\n"
++ " cmpl $63, %0\n"
++ " ja 0b\n"
++ "5: movl %0, %%eax\n"
++ " shrl $2, %0\n"
++ " andl $3, %%eax\n"
++ " cld\n"
++ "6: rep; movsl\n"
+ " movl %%eax,%0\n"
+- "7: rep; movsb\n"
+- "8:\n"
++ "7: rep; movsb\n"
++ "8:\n"
+ ".section .fixup,\"ax\"\n"
+- "9: lea 0(%%eax,%0,4),%0\n"
+- "16: pushl %0\n"
+- " pushl %%eax\n"
++ "9: lea 0(%%eax,%0,4),%0\n"
++ "16: pushl %0\n"
++ " pushl %%eax\n"
+ " xorl %%eax,%%eax\n"
+- " rep; stosb\n"
+- " popl %%eax\n"
+- " popl %0\n"
+- " jmp 8b\n"
+- ".previous\n"
++ " rep; stosb\n"
++ " popl %%eax\n"
++ " popl %0\n"
++ " jmp 8b\n"
++ ".previous\n"
+ ".section __ex_table,\"a\"\n"
+- " .align 4\n"
+- " .long 0b,16b\n"
++ " .align 4\n"
++ " .long 0b,16b\n"
+ " .long 1b,16b\n"
+ " .long 2b,16b\n"
+ " .long 21b,16b\n"
+- " .long 3b,16b\n"
++ " .long 3b,16b\n"
+ " .long 31b,16b\n"
+- " .long 4b,16b\n"
++ " .long 4b,16b\n"
+ " .long 41b,16b\n"
+ " .long 10b,16b\n"
+ " .long 51b,16b\n"
+@@ -412,9 +412,9 @@ __copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size)
+ " .long 81b,16b\n"
+ " .long 14b,16b\n"
+ " .long 91b,16b\n"
+- " .long 6b,9b\n"
+- " .long 7b,16b\n"
+- ".previous"
++ " .long 6b,9b\n"
++ " .long 7b,16b\n"
++ ".previous"
+ : "=&c"(size), "=&D" (d0), "=&S" (d1)
+ : "1"(to), "2"(from), "0"(size)
+ : "eax", "edx", "memory");
+@@ -429,7 +429,7 @@ __copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size)
+ static unsigned long __copy_user_zeroing_intel_nocache(void *to,
+ const void __user *from, unsigned long size)
+ {
+- int d0, d1;
++ int d0, d1;
+
+ __asm__ __volatile__(
+ " .align 2,0x90\n"
+@@ -526,7 +526,7 @@ static unsigned long __copy_user_zeroing_intel_nocache(void *to,
+ static unsigned long __copy_user_intel_nocache(void *to,
+ const void __user *from, unsigned long size)
+ {
+- int d0, d1;
++ int d0, d1;
+
+ __asm__ __volatile__(
+ " .align 2,0x90\n"
+@@ -629,7 +629,7 @@ unsigned long __copy_user_zeroing_intel_nocache(void *to,
+ #endif /* CONFIG_X86_INTEL_USERCOPY */
+
+ /* Generic arbitrary sized copy. */
+-#define __copy_user(to,from,size) \
++#define __copy_user(to, from, size) \
+ do { \
+ int __d0, __d1, __d2; \
+ __asm__ __volatile__( \
+@@ -665,7 +665,7 @@ do { \
+ : "memory"); \
+ } while (0)
+
+-#define __copy_user_zeroing(to,from,size) \
++#define __copy_user_zeroing(to, from, size) \
+ do { \
+ int __d0, __d1, __d2; \
+ __asm__ __volatile__( \
+@@ -712,7 +712,7 @@ unsigned long __copy_to_user_ll(void __user *to, const void *from,
+ {
+ #ifndef CONFIG_X86_WP_WORKS_OK
+ if (unlikely(boot_cpu_data.wp_works_ok == 0) &&
+- ((unsigned long )to) < TASK_SIZE) {
++ ((unsigned long)to) < TASK_SIZE) {
+ /*
+ * When we are in an atomic section (see
+ * mm/filemap.c:file_read_actor), return the full
+@@ -721,26 +721,26 @@ unsigned long __copy_to_user_ll(void __user *to, const void *from,
+ if (in_atomic())
+ return n;
+
+- /*
++ /*
+ * CPU does not honor the WP bit when writing
+ * from supervisory mode, and due to preemption or SMP,
+ * the page tables can change at any time.
+ * Do it manually. Manfred <manfred at colorfullife.com>
+ */
+ while (n) {
+- unsigned long offset = ((unsigned long)to)%PAGE_SIZE;
++ unsigned long offset = ((unsigned long)to)%PAGE_SIZE;
+ unsigned long len = PAGE_SIZE - offset;
+ int retval;
+ struct page *pg;
+ void *maddr;
+-
++
+ if (len > n)
+ len = n;
+
+ survive:
+ down_read(¤t->mm->mmap_sem);
+ retval = get_user_pages(current, current->mm,
+- (unsigned long )to, 1, 1, 0, &pg, NULL);
++ (unsigned long)to, 1, 1, 0, &pg, NULL);
+
+ if (retval == -ENOMEM && is_global_init(current)) {
+ up_read(¤t->mm->mmap_sem);
+@@ -750,8 +750,8 @@ survive:
+
+ if (retval != 1) {
+ up_read(¤t->mm->mmap_sem);
+- break;
+- }
++ break;
++ }
+
+ maddr = kmap_atomic(pg, KM_USER0);
+ memcpy(maddr + offset, from, len);
+@@ -802,12 +802,12 @@ unsigned long __copy_from_user_ll_nocache(void *to, const void __user *from,
+ unsigned long n)
+ {
+ #ifdef CONFIG_X86_INTEL_USERCOPY
+- if ( n > 64 && cpu_has_xmm2)
+- n = __copy_user_zeroing_intel_nocache(to, from, n);
++ if (n > 64 && cpu_has_xmm2)
++ n = __copy_user_zeroing_intel_nocache(to, from, n);
+ else
+ __copy_user_zeroing(to, from, n);
+ #else
+- __copy_user_zeroing(to, from, n);
++ __copy_user_zeroing(to, from, n);
+ #endif
+ return n;
+ }
+@@ -817,12 +817,12 @@ unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *fr
+ unsigned long n)
+ {
+ #ifdef CONFIG_X86_INTEL_USERCOPY
+- if ( n > 64 && cpu_has_xmm2)
+- n = __copy_user_intel_nocache(to, from, n);
++ if (n > 64 && cpu_has_xmm2)
++ n = __copy_user_intel_nocache(to, from, n);
+ else
+ __copy_user(to, from, n);
+ #else
+- __copy_user(to, from, n);
++ __copy_user(to, from, n);
+ #endif
+ return n;
+ }
+diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c
+index 292a225..95fc463 100644
+--- a/arch/x86/mach-generic/bigsmp.c
++++ b/arch/x86/mach-generic/bigsmp.c
+@@ -1,4 +1,4 @@
+-/*
++/*
+ * APIC driver for "bigsmp" XAPIC machines with more than 8 virtual CPUs.
+ * Drives the local APIC in "clustered mode".
+ */
+@@ -32,26 +32,26 @@ static int hp_ht_bigsmp(const struct dmi_system_id *d)
+
+
+ static const struct dmi_system_id bigsmp_dmi_table[] = {
+- { hp_ht_bigsmp, "HP ProLiant DL760 G2", {
+- DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
+- DMI_MATCH(DMI_BIOS_VERSION, "P44-"),
+- }},
+-
+- { hp_ht_bigsmp, "HP ProLiant DL740", {
+- DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
+- DMI_MATCH(DMI_BIOS_VERSION, "P47-"),
+- }},
++ { hp_ht_bigsmp, "HP ProLiant DL760 G2",
++ { DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
++ DMI_MATCH(DMI_BIOS_VERSION, "P44-"),}
++ },
++
++ { hp_ht_bigsmp, "HP ProLiant DL740",
++ { DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
++ DMI_MATCH(DMI_BIOS_VERSION, "P47-"),}
++ },
+ { }
+ };
+
+
+ static int probe_bigsmp(void)
+-{
++{
+ if (def_to_bigsmp)
+- dmi_bigsmp = 1;
++ dmi_bigsmp = 1;
+ else
+ dmi_check_system(bigsmp_dmi_table);
+- return dmi_bigsmp;
+-}
++ return dmi_bigsmp;
++}
+
+-struct genapic apic_bigsmp = APIC_INIT("bigsmp", probe_bigsmp);
++struct genapic apic_bigsmp = APIC_INIT("bigsmp", probe_bigsmp);
+diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c
+index 1af0cc7..9e835a1 100644
+--- a/arch/x86/mach-generic/default.c
++++ b/arch/x86/mach-generic/default.c
+@@ -1,4 +1,4 @@
+-/*
++/*
+ * Default generic APIC driver. This handles up to 8 CPUs.
+ */
+ #define APIC_DEFINITION 1
+@@ -19,8 +19,8 @@
+
+ /* should be called last. */
+ static int probe_default(void)
+-{
++{
+ return 1;
+-}
++}
+
+-struct genapic apic_default = APIC_INIT("default", probe_default);
++struct genapic apic_default = APIC_INIT("default", probe_default);
+diff --git a/arch/x86/mach-generic/probe.c b/arch/x86/mach-generic/probe.c
+index f410d3c..c5ae751 100644
+--- a/arch/x86/mach-generic/probe.c
++++ b/arch/x86/mach-generic/probe.c
+@@ -1,8 +1,9 @@
+-/* Copyright 2003 Andi Kleen, SuSE Labs.
+- * Subject to the GNU Public License, v.2
+- *
++/*
++ * Copyright 2003 Andi Kleen, SuSE Labs.
++ * Subject to the GNU Public License, v.2
++ *
+ * Generic x86 APIC driver probe layer.
+- */
++ */
+ #include <linux/threads.h>
+ #include <linux/cpumask.h>
+ #include <linux/string.h>
+@@ -24,7 +25,7 @@ struct genapic *genapic = &apic_default;
+
+ static struct genapic *apic_probe[] __initdata = {
+ &apic_summit,
+- &apic_bigsmp,
++ &apic_bigsmp,
+ &apic_es7000,
+ &apic_default, /* must be last */
+ NULL,
+@@ -69,7 +70,7 @@ void __init generic_bigsmp_probe(void)
+ }
+
+ void __init generic_apic_probe(void)
+-{
++{
+ if (!cmdline_apic) {
+ int i;
+ for (i = 0; apic_probe[i]; i++) {
+@@ -83,40 +84,40 @@ void __init generic_apic_probe(void)
+ panic("Didn't find an APIC driver");
+ }
+ printk(KERN_INFO "Using APIC driver %s\n", genapic->name);
+-}
++}
+
+ /* These functions can switch the APIC even after the initial ->probe() */
+
+ int __init mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid)
+-{
++{
+ int i;
+- for (i = 0; apic_probe[i]; ++i) {
+- if (apic_probe[i]->mps_oem_check(mpc,oem,productid)) {
++ for (i = 0; apic_probe[i]; ++i) {
++ if (apic_probe[i]->mps_oem_check(mpc, oem, productid)) {
+ if (!cmdline_apic) {
+ genapic = apic_probe[i];
+ printk(KERN_INFO "Switched to APIC driver `%s'.\n",
+ genapic->name);
+ }
+ return 1;
+- }
+- }
++ }
++ }
+ return 0;
+-}
++}
+
+ int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+ {
+ int i;
+- for (i = 0; apic_probe[i]; ++i) {
+- if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) {
++ for (i = 0; apic_probe[i]; ++i) {
++ if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) {
+ if (!cmdline_apic) {
+ genapic = apic_probe[i];
+ printk(KERN_INFO "Switched to APIC driver `%s'.\n",
+ genapic->name);
+ }
+ return 1;
+- }
+- }
+- return 0;
++ }
++ }
++ return 0;
+ }
+
+ int hard_smp_processor_id(void)
+diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c
+index 74883cc..a97ea0f 100644
+--- a/arch/x86/mach-generic/summit.c
++++ b/arch/x86/mach-generic/summit.c
+@@ -1,4 +1,4 @@
+-/*
++/*
+ * APIC driver for the IBM "Summit" chipset.
+ */
+ #define APIC_DEFINITION 1
+@@ -19,9 +19,9 @@
+ #include <asm/mach-summit/mach_mpparse.h>
+
+ static int probe_summit(void)
+-{
++{
+ /* probed later in mptable/ACPI hooks */
+ return 0;
+-}
++}
+
+-struct genapic apic_summit = APIC_INIT("summit", probe_summit);
++struct genapic apic_summit = APIC_INIT("summit", probe_summit);
+diff --git a/arch/x86/mach-rdc321x/Makefile b/arch/x86/mach-rdc321x/Makefile
+index 1faac81..8325b4c 100644
+--- a/arch/x86/mach-rdc321x/Makefile
++++ b/arch/x86/mach-rdc321x/Makefile
+@@ -1,5 +1,5 @@
+ #
+ # Makefile for the RDC321x specific parts of the kernel
+ #
+-obj-$(CONFIG_X86_RDC321X) := gpio.o platform.o wdt.o
++obj-$(CONFIG_X86_RDC321X) := gpio.o platform.o
+
+diff --git a/arch/x86/mach-rdc321x/wdt.c b/arch/x86/mach-rdc321x/wdt.c
+deleted file mode 100644
+index ec5625a..0000000
+--- a/arch/x86/mach-rdc321x/wdt.c
++++ /dev/null
+@@ -1,275 +0,0 @@
+-/*
+- * RDC321x watchdog driver
+- *
+- * Copyright (C) 2007 Florian Fainelli <florian at openwrt.org>
+- *
+- * This driver is highly inspired from the cpu5_wdt driver
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- *
+- */
+-
+-#include <linux/module.h>
+-#include <linux/moduleparam.h>
+-#include <linux/types.h>
+-#include <linux/errno.h>
+-#include <linux/miscdevice.h>
+-#include <linux/fs.h>
+-#include <linux/init.h>
+-#include <linux/ioport.h>
+-#include <linux/timer.h>
+-#include <linux/completion.h>
+-#include <linux/jiffies.h>
+-#include <linux/platform_device.h>
+-#include <linux/watchdog.h>
+-#include <linux/io.h>
+-#include <linux/uaccess.h>
+-
+-#include <asm/mach-rdc321x/rdc321x_defs.h>
+-
+-#define RDC_WDT_MASK 0x80000000 /* Mask */
+-#define RDC_WDT_EN 0x00800000 /* Enable bit */
+-#define RDC_WDT_WTI 0x00200000 /* Generate CPU reset/NMI/WDT on timeout */
+-#define RDC_WDT_RST 0x00100000 /* Reset bit */
+-#define RDC_WDT_WIF 0x00040000 /* WDT IRQ Flag */
+-#define RDC_WDT_IRT 0x00000100 /* IRQ Routing table */
+-#define RDC_WDT_CNT 0x00000001 /* WDT count */
+-
+-#define RDC_CLS_TMR 0x80003844 /* Clear timer */
+-
+-#define RDC_WDT_INTERVAL (HZ/10+1)
+-
+-int nowayout = WATCHDOG_NOWAYOUT;
+-module_param(nowayout, int, 0);
+-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+-
+-static int ticks = 1000;
+-
+-/* some device data */
+-
+-static struct {
+- struct completion stop;
+- volatile int running;
+- struct timer_list timer;
+- volatile int queue;
+- int default_ticks;
+- unsigned long inuse;
+-} rdc321x_wdt_device;
+-
+-/* generic helper functions */
+-
+-static void rdc321x_wdt_trigger(unsigned long unused)
+-{
+- if (rdc321x_wdt_device.running)
+- ticks--;
+-
+- /* keep watchdog alive */
+- outl(RDC_WDT_EN|inl(RDC3210_CFGREG_DATA), RDC3210_CFGREG_DATA);
+-
+- /* requeue?? */
+- if (rdc321x_wdt_device.queue && ticks)
+- mod_timer(&rdc321x_wdt_device.timer,
+- jiffies + RDC_WDT_INTERVAL);
+- else {
+- /* ticks doesn't matter anyway */
+- complete(&rdc321x_wdt_device.stop);
+- }
+-
+-}
+-
+-static void rdc321x_wdt_reset(void)
+-{
+- ticks = rdc321x_wdt_device.default_ticks;
+-}
+-
+-static void rdc321x_wdt_start(void)
+-{
+- if (!rdc321x_wdt_device.queue) {
+- rdc321x_wdt_device.queue = 1;
+-
+- /* Clear the timer */
+- outl(RDC_CLS_TMR, RDC3210_CFGREG_ADDR);
+-
+- /* Enable watchdog and set the timeout to 81.92 us */
+- outl(RDC_WDT_EN|RDC_WDT_CNT, RDC3210_CFGREG_DATA);
+-
+- mod_timer(&rdc321x_wdt_device.timer,
+- jiffies + RDC_WDT_INTERVAL);
+- }
+-
+- /* if process dies, counter is not decremented */
+- rdc321x_wdt_device.running++;
+-}
+-
+-static int rdc321x_wdt_stop(void)
+-{
+- if (rdc321x_wdt_device.running)
+- rdc321x_wdt_device.running = 0;
+-
+- ticks = rdc321x_wdt_device.default_ticks;
+-
+- return -EIO;
+-}
+-
+-/* filesystem operations */
+-
+-static int rdc321x_wdt_open(struct inode *inode, struct file *file)
+-{
+- if (test_and_set_bit(0, &rdc321x_wdt_device.inuse))
+- return -EBUSY;
+-
+- return nonseekable_open(inode, file);
+-}
+-
+-static int rdc321x_wdt_release(struct inode *inode, struct file *file)
+-{
+- clear_bit(0, &rdc321x_wdt_device.inuse);
+- return 0;
+-}
+-
+-static int rdc321x_wdt_ioctl(struct inode *inode, struct file *file,
+- unsigned int cmd, unsigned long arg)
+-{
+- void __user *argp = (void __user *)arg;
+- unsigned int value;
+- static struct watchdog_info ident = {
+- .options = WDIOF_CARDRESET,
+- .identity = "RDC321x WDT",
+- };
+-
+- switch (cmd) {
+- case WDIOC_KEEPALIVE:
+- rdc321x_wdt_reset();
+- break;
+- case WDIOC_GETSTATUS:
+- /* Read the value from the DATA register */
+- value = inl(RDC3210_CFGREG_DATA);
+- if (copy_to_user(argp, &value, sizeof(int)))
+- return -EFAULT;
+- break;
+- case WDIOC_GETSUPPORT:
+- if (copy_to_user(argp, &ident, sizeof(ident)))
+- return -EFAULT;
+- break;
+- case WDIOC_SETOPTIONS:
+- if (copy_from_user(&value, argp, sizeof(int)))
+- return -EFAULT;
+- switch (value) {
+- case WDIOS_ENABLECARD:
+- rdc321x_wdt_start();
+- break;
+- case WDIOS_DISABLECARD:
+- return rdc321x_wdt_stop();
+- default:
+- return -EINVAL;
+- }
+- break;
+- default:
+- return -ENOTTY;
+- }
+- return 0;
+-}
+-
+-static ssize_t rdc321x_wdt_write(struct file *file, const char __user *buf,
+- size_t count, loff_t *ppos)
+-{
+- if (!count)
+- return -EIO;
+-
+- rdc321x_wdt_reset();
+-
+- return count;
+-}
+-
+-static const struct file_operations rdc321x_wdt_fops = {
+- .owner = THIS_MODULE,
+- .llseek = no_llseek,
+- .ioctl = rdc321x_wdt_ioctl,
+- .open = rdc321x_wdt_open,
+- .write = rdc321x_wdt_write,
+- .release = rdc321x_wdt_release,
+-};
+-
+-static struct miscdevice rdc321x_wdt_misc = {
+- .minor = WATCHDOG_MINOR,
+- .name = "watchdog",
+- .fops = &rdc321x_wdt_fops,
+-};
+-
+-static int __devinit rdc321x_wdt_probe(struct platform_device *pdev)
+-{
+- int err;
+-
+- err = misc_register(&rdc321x_wdt_misc);
+- if (err < 0) {
+- printk(KERN_ERR PFX "watchdog misc_register failed\n");
+- return err;
+- }
+-
+- /* Reset the watchdog */
+- outl(RDC_WDT_RST, RDC3210_CFGREG_DATA);
+-
+- init_completion(&rdc321x_wdt_device.stop);
+- rdc321x_wdt_device.queue = 0;
+-
+- clear_bit(0, &rdc321x_wdt_device.inuse);
+-
+- setup_timer(&rdc321x_wdt_device.timer, rdc321x_wdt_trigger, 0);
+-
+- rdc321x_wdt_device.default_ticks = ticks;
+-
+- printk(KERN_INFO PFX "watchdog init success\n");
+-
+- return 0;
+-}
+-
+-static int rdc321x_wdt_remove(struct platform_device *pdev)
+-{
+- if (rdc321x_wdt_device.queue) {
+- rdc321x_wdt_device.queue = 0;
+- wait_for_completion(&rdc321x_wdt_device.stop);
+- }
+-
+- misc_deregister(&rdc321x_wdt_misc);
+-
+- return 0;
+-}
+-
+-static struct platform_driver rdc321x_wdt_driver = {
+- .probe = rdc321x_wdt_probe,
+- .remove = rdc321x_wdt_remove,
+- .driver = {
+- .owner = THIS_MODULE,
+- .name = "rdc321x-wdt",
+- },
+-};
+-
+-static int __init rdc321x_wdt_init(void)
+-{
+- return platform_driver_register(&rdc321x_wdt_driver);
+-}
+-
+-static void __exit rdc321x_wdt_exit(void)
+-{
+- platform_driver_unregister(&rdc321x_wdt_driver);
+-}
+-
+-module_init(rdc321x_wdt_init);
+-module_exit(rdc321x_wdt_exit);
+-
+-MODULE_AUTHOR("Florian Fainelli <florian at openwrt.org>");
+-MODULE_DESCRIPTION("RDC321x watchdog driver");
+-MODULE_LICENSE("GPL");
+-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+diff --git a/arch/x86/mach-visws/mpparse.c b/arch/x86/mach-visws/mpparse.c
+index 2a8456a..57484e9 100644
+--- a/arch/x86/mach-visws/mpparse.c
++++ b/arch/x86/mach-visws/mpparse.c
+@@ -11,22 +11,9 @@
+ /* Have we found an MP table */
+ int smp_found_config;
+
+-/*
+- * Various Linux-internal data structures created from the
+- * MP-table.
+- */
+-int apic_version [MAX_APICS];
+-
+ int pic_mode;
+-unsigned long mp_lapic_addr;
+-
+-/* Processor that is doing the boot up */
+-unsigned int boot_cpu_physical_apicid = -1U;
+-
+-/* Bitmask of physically existing CPUs */
+-physid_mask_t phys_cpu_present_map;
+
+-unsigned int __initdata maxcpus = NR_CPUS;
++extern unsigned int __cpuinitdata maxcpus;
+
+ /*
+ * The Visual Workstation is Intel MP compliant in the hardware
+diff --git a/arch/x86/mach-visws/visws_apic.c b/arch/x86/mach-visws/visws_apic.c
+index 710faf7..cef9cb1 100644
+--- a/arch/x86/mach-visws/visws_apic.c
++++ b/arch/x86/mach-visws/visws_apic.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/arch/i386/mach-visws/visws_apic.c
+- *
+ * Copyright (C) 1999 Bent Hagemark, Ingo Molnar
+ *
+ * SGI Visual Workstation interrupt controller
+diff --git a/arch/x86/mach-voyager/voyager_basic.c b/arch/x86/mach-voyager/voyager_basic.c
+index 6a949e4..46d6f80 100644
+--- a/arch/x86/mach-voyager/voyager_basic.c
++++ b/arch/x86/mach-voyager/voyager_basic.c
+@@ -2,8 +2,6 @@
+ *
+ * Author: J.E.J.Bottomley at HansenPartnership.com
+ *
+- * linux/arch/i386/kernel/voyager.c
+- *
+ * This file contains all the voyager specific routines for getting
+ * initialisation of the architecture to function. For additional
+ * features see:
+diff --git a/arch/x86/mach-voyager/voyager_cat.c b/arch/x86/mach-voyager/voyager_cat.c
+index 17a7904..ecab9ff 100644
+--- a/arch/x86/mach-voyager/voyager_cat.c
++++ b/arch/x86/mach-voyager/voyager_cat.c
+@@ -4,8 +4,6 @@
+ *
+ * Author: J.E.J.Bottomley at HansenPartnership.com
+ *
+- * linux/arch/i386/kernel/voyager_cat.c
+- *
+ * This file contains all the logic for manipulating the CAT bus
+ * in a level 5 machine.
+ *
+diff --git a/arch/x86/mach-voyager/voyager_smp.c b/arch/x86/mach-voyager/voyager_smp.c
+index 3cc8eb2..8acbf0c 100644
+--- a/arch/x86/mach-voyager/voyager_smp.c
++++ b/arch/x86/mach-voyager/voyager_smp.c
+@@ -4,8 +4,6 @@
+ *
+ * Author: J.E.J.Bottomley at HansenPartnership.com
+ *
+- * linux/arch/i386/kernel/voyager_smp.c
+- *
+ * This file provides all the same external entries as smp.c but uses
+ * the voyager hal to provide the functionality
+ */
+@@ -27,6 +25,7 @@
+ #include <asm/pgalloc.h>
+ #include <asm/tlbflush.h>
+ #include <asm/arch_hooks.h>
++#include <asm/trampoline.h>
+
+ /* TLB state -- visible externally, indexed physically */
+ DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) = { &init_mm, 0 };
+@@ -114,7 +113,7 @@ static inline void send_QIC_CPI(__u32 cpuset, __u8 cpi)
+ for_each_online_cpu(cpu) {
+ if (cpuset & (1 << cpu)) {
+ #ifdef VOYAGER_DEBUG
+- if (!cpu_isset(cpu, cpu_online_map))
++ if (!cpu_online(cpu))
+ VDEBUG(("CPU%d sending cpi %d to CPU%d not in "
+ "cpu_online_map\n",
+ hard_smp_processor_id(), cpi, cpu));
+@@ -207,11 +206,6 @@ static struct irq_chip vic_chip = {
+ /* used to count up as CPUs are brought on line (starts at 0) */
+ static int cpucount = 0;
+
+-/* steal a page from the bottom of memory for the trampoline and
+- * squirrel its address away here. This will be in kernel virtual
+- * space */
+-static __u32 trampoline_base;
+-
+ /* The per cpu profile stuff - used in smp_local_timer_interrupt */
+ static DEFINE_PER_CPU(int, prof_multiplier) = 1;
+ static DEFINE_PER_CPU(int, prof_old_multiplier) = 1;
+@@ -428,18 +422,6 @@ void __init smp_store_cpu_info(int id)
+ identify_secondary_cpu(c);
+ }
+
+-/* set up the trampoline and return the physical address of the code */
+-static __u32 __init setup_trampoline(void)
+-{
+- /* these two are global symbols in trampoline.S */
+- extern const __u8 trampoline_end[];
+- extern const __u8 trampoline_data[];
+-
+- memcpy((__u8 *) trampoline_base, trampoline_data,
+- trampoline_end - trampoline_data);
+- return virt_to_phys((__u8 *) trampoline_base);
+-}
+-
+ /* Routine initially called when a non-boot CPU is brought online */
+ static void __init start_secondary(void *unused)
+ {
+@@ -520,13 +502,6 @@ static void __init do_boot_cpu(__u8 cpu)
+ & ~(voyager_extended_vic_processors
+ & voyager_allowed_boot_processors);
+
+- /* This is an area in head.S which was used to set up the
+- * initial kernel stack. We need to alter this to give the
+- * booting CPU a new stack (taken from its idle process) */
+- extern struct {
+- __u8 *sp;
+- unsigned short ss;
+- } stack_start;
+ /* This is the format of the CPI IDT gate (in real mode) which
+ * we're hijacking to boot the CPU */
+ union IDTFormat {
+@@ -568,8 +543,8 @@ static void __init do_boot_cpu(__u8 cpu)
+ hijack_source.idt.Offset, stack_start.sp));
+
+ /* init lowmem identity mapping */
+- clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
+- min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS));
++ clone_pgd_range(swapper_pg_dir, swapper_pg_dir + KERNEL_PGD_BOUNDARY,
++ min_t(unsigned long, KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY));
+ flush_tlb_all();
+
+ if (quad_boot) {
+@@ -708,9 +683,9 @@ void __init smp_boot_cpus(void)
+ * Code added from smpboot.c */
+ {
+ unsigned long bogosum = 0;
+- for (i = 0; i < NR_CPUS; i++)
+- if (cpu_isset(i, cpu_online_map))
+- bogosum += cpu_data(i).loops_per_jiffy;
++
++ for_each_online_cpu(i)
++ bogosum += cpu_data(i).loops_per_jiffy;
+ printk(KERN_INFO "Total of %d processors activated "
+ "(%lu.%02lu BogoMIPS).\n",
+ cpucount + 1, bogosum / (500000 / HZ),
+@@ -1166,7 +1141,7 @@ void flush_tlb_all(void)
+ * is sorted out */
+ void __init smp_alloc_memory(void)
+ {
+- trampoline_base = (__u32) alloc_bootmem_low_pages(PAGE_SIZE);
++ trampoline_base = alloc_bootmem_low_pages(PAGE_SIZE);
+ if (__pa(trampoline_base) >= 0x93000)
+ BUG();
+ }
+@@ -1863,7 +1838,7 @@ static int __cpuinit voyager_cpu_up(unsigned int cpu)
+ return -EIO;
+ /* Unleash the CPU! */
+ cpu_set(cpu, smp_commenced_mask);
+- while (!cpu_isset(cpu, cpu_online_map))
++ while (!cpu_online(cpu))
+ mb();
+ return 0;
+ }
+diff --git a/arch/x86/mach-voyager/voyager_thread.c b/arch/x86/mach-voyager/voyager_thread.c
+index c69c931..15464a2 100644
+--- a/arch/x86/mach-voyager/voyager_thread.c
++++ b/arch/x86/mach-voyager/voyager_thread.c
+@@ -4,8 +4,6 @@
+ *
+ * Author: J.E.J.Bottomley at HansenPartnership.com
+ *
+- * linux/arch/i386/kernel/voyager_thread.c
+- *
+ * This module provides the machine status monitor thread for the
+ * voyager architecture. This allows us to monitor the machine
+ * environment (temp, voltage, fan function) and the front panel and
+diff --git a/arch/x86/math-emu/fpu_entry.c b/arch/x86/math-emu/fpu_entry.c
+index 760baee..6e38d87 100644
+--- a/arch/x86/math-emu/fpu_entry.c
++++ b/arch/x86/math-emu/fpu_entry.c
+@@ -276,6 +276,7 @@ asmlinkage void math_emulate(long arg)
+ entry_sel_off.offset = FPU_ORIG_EIP;
+ entry_sel_off.selector = FPU_CS;
+ entry_sel_off.opcode = (byte1 << 8) | FPU_modrm;
++ entry_sel_off.empty = 0;
+
+ FPU_rm = FPU_modrm & 7;
+
+@@ -677,7 +678,7 @@ int fpregs_soft_set(struct task_struct *target,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+ {
+- struct i387_soft_struct *s387 = &target->thread.i387.soft;
++ struct i387_soft_struct *s387 = &target->thread.xstate->soft;
+ void *space = s387->st_space;
+ int ret;
+ int offset, other, i, tags, regnr, tag, newtop;
+@@ -729,7 +730,7 @@ int fpregs_soft_get(struct task_struct *target,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+ {
+- struct i387_soft_struct *s387 = &target->thread.i387.soft;
++ struct i387_soft_struct *s387 = &target->thread.xstate->soft;
+ const void *space = s387->st_space;
+ int ret;
+ int offset = (S387->ftop & 7) * 10, other = 80 - offset;
+diff --git a/arch/x86/math-emu/fpu_system.h b/arch/x86/math-emu/fpu_system.h
+index a3ae28c..13488fa 100644
+--- a/arch/x86/math-emu/fpu_system.h
++++ b/arch/x86/math-emu/fpu_system.h
+@@ -35,8 +35,8 @@
+ #define SEG_EXPAND_DOWN(s) (((s).b & ((1 << 11) | (1 << 10))) \
+ == (1 << 10))
+
+-#define I387 (current->thread.i387)
+-#define FPU_info (I387.soft.info)
++#define I387 (current->thread.xstate)
++#define FPU_info (I387->soft.info)
+
+ #define FPU_CS (*(unsigned short *) &(FPU_info->___cs))
+ #define FPU_SS (*(unsigned short *) &(FPU_info->___ss))
+@@ -46,25 +46,25 @@
+ #define FPU_EIP (FPU_info->___eip)
+ #define FPU_ORIG_EIP (FPU_info->___orig_eip)
+
+-#define FPU_lookahead (I387.soft.lookahead)
++#define FPU_lookahead (I387->soft.lookahead)
+
+ /* nz if ip_offset and cs_selector are not to be set for the current
+ instruction. */
+-#define no_ip_update (*(u_char *)&(I387.soft.no_update))
+-#define FPU_rm (*(u_char *)&(I387.soft.rm))
++#define no_ip_update (*(u_char *)&(I387->soft.no_update))
++#define FPU_rm (*(u_char *)&(I387->soft.rm))
+
+ /* Number of bytes of data which can be legally accessed by the current
+ instruction. This only needs to hold a number <= 108, so a byte will do. */
+-#define access_limit (*(u_char *)&(I387.soft.alimit))
++#define access_limit (*(u_char *)&(I387->soft.alimit))
+
+-#define partial_status (I387.soft.swd)
+-#define control_word (I387.soft.cwd)
+-#define fpu_tag_word (I387.soft.twd)
+-#define registers (I387.soft.st_space)
+-#define top (I387.soft.ftop)
++#define partial_status (I387->soft.swd)
++#define control_word (I387->soft.cwd)
++#define fpu_tag_word (I387->soft.twd)
++#define registers (I387->soft.st_space)
++#define top (I387->soft.ftop)
+
+-#define instruction_address (*(struct address *)&I387.soft.fip)
+-#define operand_address (*(struct address *)&I387.soft.foo)
++#define instruction_address (*(struct address *)&I387->soft.fip)
++#define operand_address (*(struct address *)&I387->soft.foo)
+
+ #define FPU_access_ok(x,y,z) if ( !access_ok(x,y,z) ) \
+ math_abort(FPU_info,SIGSEGV)
+diff --git a/arch/x86/math-emu/reg_ld_str.c b/arch/x86/math-emu/reg_ld_str.c
+index 799d4af..d597fe7 100644
+--- a/arch/x86/math-emu/reg_ld_str.c
++++ b/arch/x86/math-emu/reg_ld_str.c
+@@ -383,15 +383,15 @@ int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat)
+ int exp;
+ FPU_REG tmp;
+
++ l[0] = 0;
++ l[1] = 0;
+ if (st0_tag == TAG_Valid) {
+ reg_copy(st0_ptr, &tmp);
+ exp = exponent(&tmp);
+
+ if (exp < DOUBLE_Emin) { /* It may be a denormal */
+ addexponent(&tmp, -DOUBLE_Emin + 52); /* largest exp to be 51 */
+-
+- denormal_arg:
+-
++denormal_arg:
+ if ((precision_loss = FPU_round_to_int(&tmp, st0_tag))) {
+ #ifdef PECULIAR_486
+ /* Did it round to a non-denormal ? */
+@@ -477,8 +477,7 @@ int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat)
+
+ /* This is a special case: see sec 16.2.5.1 of the 80486 book */
+ /* Overflow to infinity */
+- l[0] = 0x00000000; /* Set to */
+- l[1] = 0x7ff00000; /* + INF */
++ l[1] = 0x7ff00000; /* Set to + INF */
+ } else {
+ if (precision_loss) {
+ if (increment)
+@@ -492,8 +491,6 @@ int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat)
+ }
+ } else if (st0_tag == TAG_Zero) {
+ /* Number is zero */
+- l[0] = 0;
+- l[1] = 0;
+ } else if (st0_tag == TAG_Special) {
+ st0_tag = FPU_Special(st0_ptr);
+ if (st0_tag == TW_Denormal) {
+@@ -508,7 +505,6 @@ int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat)
+ reg_copy(st0_ptr, &tmp);
+ goto denormal_arg;
+ } else if (st0_tag == TW_Infinity) {
+- l[0] = 0;
+ l[1] = 0x7ff00000;
+ } else if (st0_tag == TW_NaN) {
+ /* Is it really a NaN ? */
+@@ -532,7 +528,6 @@ int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat)
+ EXCEPTION(EX_Invalid);
+ if (!(control_word & CW_Invalid))
+ return 0;
+- l[0] = 0;
+ l[1] = 0xfff80000;
+ }
+ }
+@@ -1185,8 +1180,8 @@ u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user *d)
+ control_word |= 0xffff0040;
+ partial_status = status_word() | 0xffff0000;
+ fpu_tag_word |= 0xffff0000;
+- I387.soft.fcs &= ~0xf8000000;
+- I387.soft.fos |= 0xffff0000;
++ I387->soft.fcs &= ~0xf8000000;
++ I387->soft.fos |= 0xffff0000;
+ #endif /* PECULIAR_486 */
+ if (__copy_to_user(d, &control_word, 7 * 4))
+ FPU_abort;
+diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile
+index 9832910..b7b3e4c 100644
+--- a/arch/x86/mm/Makefile
++++ b/arch/x86/mm/Makefile
+@@ -1,5 +1,17 @@
++obj-y := init_$(BITS).o fault.o ioremap.o extable.o pageattr.o mmap.o \
++ pat.o pgtable.o
++
++obj-$(CONFIG_X86_32) += pgtable_32.o
++
++obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
++obj-$(CONFIG_X86_PTDUMP) += dump_pagetables.o
++
++obj-$(CONFIG_HIGHMEM) += highmem_32.o
++
+ ifeq ($(CONFIG_X86_32),y)
+-include ${srctree}/arch/x86/mm/Makefile_32
++obj-$(CONFIG_NUMA) += discontig_32.o
+ else
+-include ${srctree}/arch/x86/mm/Makefile_64
++obj-$(CONFIG_NUMA) += numa_64.o
++obj-$(CONFIG_K8_NUMA) += k8topology_64.o
++obj-$(CONFIG_ACPI_NUMA) += srat_64.o
+ endif
+diff --git a/arch/x86/mm/Makefile_32 b/arch/x86/mm/Makefile_32
+deleted file mode 100644
+index c36ae88..0000000
+--- a/arch/x86/mm/Makefile_32
++++ /dev/null
+@@ -1,9 +0,0 @@
+-#
+-# Makefile for the linux i386-specific parts of the memory manager.
+-#
+-
+-obj-y := init_32.o pgtable_32.o fault.o ioremap.o extable.o pageattr.o mmap.o
+-
+-obj-$(CONFIG_NUMA) += discontig_32.o
+-obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
+-obj-$(CONFIG_HIGHMEM) += highmem_32.o
+diff --git a/arch/x86/mm/Makefile_64 b/arch/x86/mm/Makefile_64
+deleted file mode 100644
+index 688c8c2..0000000
+--- a/arch/x86/mm/Makefile_64
++++ /dev/null
+@@ -1,9 +0,0 @@
+-#
+-# Makefile for the linux x86_64-specific parts of the memory manager.
+-#
+-
+-obj-y := init_64.o fault.o ioremap.o extable.o pageattr.o mmap.o
+-obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
+-obj-$(CONFIG_NUMA) += numa_64.o
+-obj-$(CONFIG_K8_NUMA) += k8topology_64.o
+-obj-$(CONFIG_ACPI_NUMA) += srat_64.o
+diff --git a/arch/x86/mm/discontig_32.c b/arch/x86/mm/discontig_32.c
+index 8e25e06..1837885 100644
+--- a/arch/x86/mm/discontig_32.c
++++ b/arch/x86/mm/discontig_32.c
+@@ -37,7 +37,7 @@
+ #include <asm/e820.h>
+ #include <asm/setup.h>
+ #include <asm/mmzone.h>
+-#include <bios_ebda.h>
++#include <asm/bios_ebda.h>
+
+ struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
+ EXPORT_SYMBOL(node_data);
+@@ -120,7 +120,7 @@ int __init get_memcfg_numa_flat(void)
+ printk("NUMA - single node, flat memory mode\n");
+
+ /* Run the memory configuration and find the top of memory. */
+- find_max_pfn();
++ propagate_e820_map();
+ node_start_pfn[0] = 0;
+ node_end_pfn[0] = max_pfn;
+ memory_present(0, 0, max_pfn);
+@@ -134,7 +134,7 @@ int __init get_memcfg_numa_flat(void)
+ /*
+ * Find the highest page frame number we have available for the node
+ */
+-static void __init find_max_pfn_node(int nid)
++static void __init propagate_e820_map_node(int nid)
+ {
+ if (node_end_pfn[nid] > max_pfn)
+ node_end_pfn[nid] = max_pfn;
+@@ -379,7 +379,7 @@ unsigned long __init setup_memory(void)
+ printk("High memory starts at vaddr %08lx\n",
+ (ulong) pfn_to_kaddr(highstart_pfn));
+ for_each_online_node(nid)
+- find_max_pfn_node(nid);
++ propagate_e820_map_node(nid);
+
+ memset(NODE_DATA(0), 0, sizeof(struct pglist_data));
+ NODE_DATA(0)->bdata = &node0_bdata;
+diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c
+new file mode 100644
+index 0000000..2c24bea
+--- /dev/null
++++ b/arch/x86/mm/dump_pagetables.c
+@@ -0,0 +1,354 @@
++/*
++ * Debug helper to dump the current kernel pagetables of the system
++ * so that we can see what the various memory ranges are set to.
++ *
++ * (C) Copyright 2008 Intel Corporation
++ *
++ * Author: Arjan van de Ven <arjan at linux.intel.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; version 2
++ * of the License.
++ */
++
++#include <linux/debugfs.h>
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/seq_file.h>
++
++#include <asm/pgtable.h>
++
++/*
++ * The dumper groups pagetable entries of the same type into one, and for
++ * that it needs to keep some state when walking, and flush this state
++ * when a "break" in the continuity is found.
++ */
++struct pg_state {
++ int level;
++ pgprot_t current_prot;
++ unsigned long start_address;
++ unsigned long current_address;
++ const struct addr_marker *marker;
++};
++
++struct addr_marker {
++ unsigned long start_address;
++ const char *name;
++};
++
++/* Address space markers hints */
++static struct addr_marker address_markers[] = {
++ { 0, "User Space" },
++#ifdef CONFIG_X86_64
++ { 0x8000000000000000UL, "Kernel Space" },
++ { 0xffff810000000000UL, "Low Kernel Mapping" },
++ { VMALLOC_START, "vmalloc() Area" },
++ { VMEMMAP_START, "Vmemmap" },
++ { __START_KERNEL_map, "High Kernel Mapping" },
++ { MODULES_VADDR, "Modules" },
++ { MODULES_END, "End Modules" },
++#else
++ { PAGE_OFFSET, "Kernel Mapping" },
++ { 0/* VMALLOC_START */, "vmalloc() Area" },
++ { 0/*VMALLOC_END*/, "vmalloc() End" },
++# ifdef CONFIG_HIGHMEM
++ { 0/*PKMAP_BASE*/, "Persisent kmap() Area" },
++# endif
++ { 0/*FIXADDR_START*/, "Fixmap Area" },
++#endif
++ { -1, NULL } /* End of list */
++};
++
++/* Multipliers for offsets within the PTEs */
++#define PTE_LEVEL_MULT (PAGE_SIZE)
++#define PMD_LEVEL_MULT (PTRS_PER_PTE * PTE_LEVEL_MULT)
++#define PUD_LEVEL_MULT (PTRS_PER_PMD * PMD_LEVEL_MULT)
++#define PGD_LEVEL_MULT (PTRS_PER_PUD * PUD_LEVEL_MULT)
++
++/*
++ * Print a readable form of a pgprot_t to the seq_file
++ */
++static void printk_prot(struct seq_file *m, pgprot_t prot, int level)
++{
++ pgprotval_t pr = pgprot_val(prot);
++ static const char * const level_name[] =
++ { "cr3", "pgd", "pud", "pmd", "pte" };
++
++ if (!pgprot_val(prot)) {
++ /* Not present */
++ seq_printf(m, " ");
++ } else {
++ if (pr & _PAGE_USER)
++ seq_printf(m, "USR ");
++ else
++ seq_printf(m, " ");
++ if (pr & _PAGE_RW)
++ seq_printf(m, "RW ");
++ else
++ seq_printf(m, "ro ");
++ if (pr & _PAGE_PWT)
++ seq_printf(m, "PWT ");
++ else
++ seq_printf(m, " ");
++ if (pr & _PAGE_PCD)
++ seq_printf(m, "PCD ");
++ else
++ seq_printf(m, " ");
++
++ /* Bit 9 has a different meaning on level 3 vs 4 */
++ if (level <= 3) {
++ if (pr & _PAGE_PSE)
++ seq_printf(m, "PSE ");
++ else
++ seq_printf(m, " ");
++ } else {
++ if (pr & _PAGE_PAT)
++ seq_printf(m, "pat ");
++ else
++ seq_printf(m, " ");
++ }
++ if (pr & _PAGE_GLOBAL)
++ seq_printf(m, "GLB ");
++ else
++ seq_printf(m, " ");
++ if (pr & _PAGE_NX)
++ seq_printf(m, "NX ");
++ else
++ seq_printf(m, "x ");
++ }
++ seq_printf(m, "%s\n", level_name[level]);
++}
++
++/*
++ * On 64 bits, sign-extend the 48 bit address to 64 bit
++ */
++static unsigned long normalize_addr(unsigned long u)
++{
++#ifdef CONFIG_X86_64
++ return (signed long)(u << 16) >> 16;
++#else
++ return u;
++#endif
++}
++
++/*
++ * This function gets called on a break in a continuous series
++ * of PTE entries; the next one is different so we need to
++ * print what we collected so far.
++ */
++static void note_page(struct seq_file *m, struct pg_state *st,
++ pgprot_t new_prot, int level)
++{
++ pgprotval_t prot, cur;
++ static const char units[] = "KMGTPE";
++
++ /*
++ * If we have a "break" in the series, we need to flush the state that
++ * we have now. "break" is either changing perms, levels or
++ * address space marker.
++ */
++ prot = pgprot_val(new_prot) & ~(PTE_MASK);
++ cur = pgprot_val(st->current_prot) & ~(PTE_MASK);
++
++ if (!st->level) {
++ /* First entry */
++ st->current_prot = new_prot;
++ st->level = level;
++ st->marker = address_markers;
++ seq_printf(m, "---[ %s ]---\n", st->marker->name);
++ } else if (prot != cur || level != st->level ||
++ st->current_address >= st->marker[1].start_address) {
++ const char *unit = units;
++ unsigned long delta;
++
++ /*
++ * Now print the actual finished series
++ */
++ seq_printf(m, "0x%p-0x%p ",
++ (void *)st->start_address,
++ (void *)st->current_address);
++
++ delta = (st->current_address - st->start_address) >> 10;
++ while (!(delta & 1023) && unit[1]) {
++ delta >>= 10;
++ unit++;
++ }
++ seq_printf(m, "%9lu%c ", delta, *unit);
++ printk_prot(m, st->current_prot, st->level);
++
++ /*
++ * We print markers for special areas of address space,
++ * such as the start of vmalloc space etc.
++ * This helps in the interpretation.
++ */
++ if (st->current_address >= st->marker[1].start_address) {
++ st->marker++;
++ seq_printf(m, "---[ %s ]---\n", st->marker->name);
++ }
++
++ st->start_address = st->current_address;
++ st->current_prot = new_prot;
++ st->level = level;
++ }
++}
++
++static void walk_pte_level(struct seq_file *m, struct pg_state *st, pmd_t addr,
++ unsigned long P)
++{
++ int i;
++ pte_t *start;
++
++ start = (pte_t *) pmd_page_vaddr(addr);
++ for (i = 0; i < PTRS_PER_PTE; i++) {
++ pgprot_t prot = pte_pgprot(*start);
++
++ st->current_address = normalize_addr(P + i * PTE_LEVEL_MULT);
++ note_page(m, st, prot, 4);
++ start++;
++ }
++}
++
++#if PTRS_PER_PMD > 1
++
++static void walk_pmd_level(struct seq_file *m, struct pg_state *st, pud_t addr,
++ unsigned long P)
++{
++ int i;
++ pmd_t *start;
++
++ start = (pmd_t *) pud_page_vaddr(addr);
++ for (i = 0; i < PTRS_PER_PMD; i++) {
++ st->current_address = normalize_addr(P + i * PMD_LEVEL_MULT);
++ if (!pmd_none(*start)) {
++ pgprotval_t prot = pmd_val(*start) & ~PTE_MASK;
++
++ if (pmd_large(*start) || !pmd_present(*start))
++ note_page(m, st, __pgprot(prot), 3);
++ else
++ walk_pte_level(m, st, *start,
++ P + i * PMD_LEVEL_MULT);
++ } else
++ note_page(m, st, __pgprot(0), 3);
++ start++;
++ }
++}
++
++#else
++#define walk_pmd_level(m,s,a,p) walk_pte_level(m,s,__pmd(pud_val(a)),p)
++#define pud_large(a) pmd_large(__pmd(pud_val(a)))
++#define pud_none(a) pmd_none(__pmd(pud_val(a)))
++#endif
++
++#if PTRS_PER_PUD > 1
++
++static void walk_pud_level(struct seq_file *m, struct pg_state *st, pgd_t addr,
++ unsigned long P)
++{
++ int i;
++ pud_t *start;
++
++ start = (pud_t *) pgd_page_vaddr(addr);
++
++ for (i = 0; i < PTRS_PER_PUD; i++) {
++ st->current_address = normalize_addr(P + i * PUD_LEVEL_MULT);
++ if (!pud_none(*start)) {
++ pgprotval_t prot = pud_val(*start) & ~PTE_MASK;
++
++ if (pud_large(*start) || !pud_present(*start))
++ note_page(m, st, __pgprot(prot), 2);
++ else
++ walk_pmd_level(m, st, *start,
++ P + i * PUD_LEVEL_MULT);
++ } else
++ note_page(m, st, __pgprot(0), 2);
++
++ start++;
++ }
++}
++
++#else
++#define walk_pud_level(m,s,a,p) walk_pmd_level(m,s,__pud(pgd_val(a)),p)
++#define pgd_large(a) pud_large(__pud(pgd_val(a)))
++#define pgd_none(a) pud_none(__pud(pgd_val(a)))
++#endif
++
++static void walk_pgd_level(struct seq_file *m)
++{
++#ifdef CONFIG_X86_64
++ pgd_t *start = (pgd_t *) &init_level4_pgt;
++#else
++ pgd_t *start = swapper_pg_dir;
++#endif
++ int i;
++ struct pg_state st;
++
++ memset(&st, 0, sizeof(st));
++
++ for (i = 0; i < PTRS_PER_PGD; i++) {
++ st.current_address = normalize_addr(i * PGD_LEVEL_MULT);
++ if (!pgd_none(*start)) {
++ pgprotval_t prot = pgd_val(*start) & ~PTE_MASK;
++
++ if (pgd_large(*start) || !pgd_present(*start))
++ note_page(m, &st, __pgprot(prot), 1);
++ else
++ walk_pud_level(m, &st, *start,
++ i * PGD_LEVEL_MULT);
++ } else
++ note_page(m, &st, __pgprot(0), 1);
++
++ start++;
++ }
++
++ /* Flush out the last page */
++ st.current_address = normalize_addr(PTRS_PER_PGD*PGD_LEVEL_MULT);
++ note_page(m, &st, __pgprot(0), 0);
++}
++
++static int ptdump_show(struct seq_file *m, void *v)
++{
++ walk_pgd_level(m);
++ return 0;
++}
++
++static int ptdump_open(struct inode *inode, struct file *filp)
++{
++ return single_open(filp, ptdump_show, NULL);
++}
++
++static const struct file_operations ptdump_fops = {
++ .open = ptdump_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static int pt_dump_init(void)
++{
++ struct dentry *pe;
++
++#ifdef CONFIG_X86_32
++ /* Not a compile-time constant on x86-32 */
++ address_markers[2].start_address = VMALLOC_START;
++ address_markers[3].start_address = VMALLOC_END;
++# ifdef CONFIG_HIGHMEM
++ address_markers[4].start_address = PKMAP_BASE;
++ address_markers[5].start_address = FIXADDR_START;
++# else
++ address_markers[4].start_address = FIXADDR_START;
++# endif
++#endif
++
++ pe = debugfs_create_file("kernel_page_tables", 0600, NULL, NULL,
++ &ptdump_fops);
++ if (!pe)
++ return -ENOMEM;
++
++ return 0;
++}
++
++__initcall(pt_dump_init);
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Arjan van de Ven <arjan at linux.intel.com>");
++MODULE_DESCRIPTION("Kernel debugging helper that dumps pagetables");
+diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
+index ec08d83..fd7e179 100644
+--- a/arch/x86/mm/fault.c
++++ b/arch/x86/mm/fault.c
+@@ -639,7 +639,7 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
+ #ifdef CONFIG_X86_32
+ /* It's safe to allow irq's after cr2 has been saved and the vmalloc
+ fault has been handled. */
+- if (regs->flags & (X86_EFLAGS_IF|VM_MASK))
++ if (regs->flags & (X86_EFLAGS_IF | X86_VM_MASK))
+ local_irq_enable();
+
+ /*
+@@ -976,9 +976,5 @@ void vmalloc_sync_all(void)
+ if (address == start)
+ start = address + PGDIR_SIZE;
+ }
+- /* Check that there is no need to do the same for the modules area. */
+- BUILD_BUG_ON(!(MODULES_VADDR > __START_KERNEL));
+- BUILD_BUG_ON(!(((MODULES_END - 1) & PGDIR_MASK) ==
+- (__START_KERNEL & PGDIR_MASK)));
+ #endif
+ }
+diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
+index ee1091a..4a47618 100644
+--- a/arch/x86/mm/init_32.c
++++ b/arch/x86/mm/init_32.c
+@@ -1,5 +1,4 @@
+ /*
+- * linux/arch/i386/mm/init.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ *
+@@ -51,6 +50,8 @@
+
+ unsigned int __VMALLOC_RESERVE = 128 << 20;
+
++unsigned long max_pfn_mapped;
++
+ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+ unsigned long highstart_pfn, highend_pfn;
+
+@@ -70,7 +71,7 @@ static pmd_t * __init one_md_table_init(pgd_t *pgd)
+ if (!(pgd_val(*pgd) & _PAGE_PRESENT)) {
+ pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+
+- paravirt_alloc_pd(&init_mm, __pa(pmd_table) >> PAGE_SHIFT);
++ paravirt_alloc_pmd(&init_mm, __pa(pmd_table) >> PAGE_SHIFT);
+ set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
+ pud = pud_offset(pgd, 0);
+ BUG_ON(pmd_table != pmd_offset(pud, 0));
+@@ -99,7 +100,7 @@ static pte_t * __init one_page_table_init(pmd_t *pmd)
+ (pte_t *)alloc_bootmem_low_pages(PAGE_SIZE);
+ }
+
+- paravirt_alloc_pt(&init_mm, __pa(page_table) >> PAGE_SHIFT);
++ paravirt_alloc_pte(&init_mm, __pa(page_table) >> PAGE_SHIFT);
+ set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
+ BUG_ON(page_table != pte_offset_kernel(pmd, 0));
+ }
+@@ -179,8 +180,13 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
+ /*
+ * Map with big pages if possible, otherwise
+ * create normal page tables:
++ *
++ * Don't use a large page for the first 2/4MB of memory
++ * because there are often fixed size MTRRs in there
++ * and overlapping MTRRs into large pages can cause
++ * slowdowns.
+ */
+- if (cpu_has_pse) {
++ if (cpu_has_pse && !(pgd_idx == 0 && pmd_idx == 0)) {
+ unsigned int addr2;
+ pgprot_t prot = PAGE_KERNEL_LARGE;
+
+@@ -194,6 +200,7 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
+ set_pmd(pmd, pfn_pmd(pfn, prot));
+
+ pfn += PTRS_PER_PTE;
++ max_pfn_mapped = pfn;
+ continue;
+ }
+ pte = one_page_table_init(pmd);
+@@ -208,6 +215,7 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
+
+ set_pte(pte, pfn_pte(pfn, prot));
+ }
++ max_pfn_mapped = pfn;
+ }
+ }
+ }
+@@ -219,6 +227,25 @@ static inline int page_kills_ppro(unsigned long pagenr)
+ return 0;
+ }
+
++/*
++ * devmem_is_allowed() checks to see if /dev/mem access to a certain address
++ * is valid. The argument is a physical page number.
++ *
++ *
++ * On x86, access has to be given to the first megabyte of ram because that area
++ * contains bios code and data regions used by X and dosemu and similar apps.
++ * Access has to be given to non-kernel-ram areas as well, these contain the PCI
++ * mmio resources as well as potential bios/acpi data regions.
++ */
++int devmem_is_allowed(unsigned long pagenr)
++{
++ if (pagenr <= 256)
++ return 1;
++ if (!page_is_ram(pagenr))
++ return 1;
++ return 0;
++}
++
+ #ifdef CONFIG_HIGHMEM
+ pte_t *kmap_pte;
+ pgprot_t kmap_prot;
+@@ -357,7 +384,7 @@ void __init native_pagetable_setup_start(pgd_t *base)
+
+ pte_clear(NULL, va, pte);
+ }
+- paravirt_alloc_pd(&init_mm, __pa(base) >> PAGE_SHIFT);
++ paravirt_alloc_pmd(&init_mm, __pa(base) >> PAGE_SHIFT);
+ }
+
+ void __init native_pagetable_setup_done(pgd_t *base)
+@@ -449,7 +476,7 @@ void zap_low_mappings(void)
+ * Note that "pgd_clear()" doesn't do it for
+ * us, because pgd_clear() is a no-op on i386.
+ */
+- for (i = 0; i < USER_PTRS_PER_PGD; i++) {
++ for (i = 0; i < KERNEL_PGD_BOUNDARY; i++) {
+ #ifdef CONFIG_X86_PAE
+ set_pgd(swapper_pg_dir+i, __pgd(1 + __pa(empty_zero_page)));
+ #else
+@@ -539,9 +566,9 @@ void __init paging_init(void)
+
+ /*
+ * Test if the WP bit works in supervisor mode. It isn't supported on 386's
+- * and also on some strange 486's (NexGen etc.). All 586+'s are OK. This
+- * used to involve black magic jumps to work around some nasty CPU bugs,
+- * but fortunately the switch to using exceptions got rid of all that.
++ * and also on some strange 486's. All 586+'s are OK. This used to involve
++ * black magic jumps to work around some nasty CPU bugs, but fortunately the
++ * switch to using exceptions got rid of all that.
+ */
+ static void __init test_wp_bit(void)
+ {
+@@ -723,25 +750,17 @@ void mark_rodata_ro(void)
+ unsigned long start = PFN_ALIGN(_text);
+ unsigned long size = PFN_ALIGN(_etext) - start;
+
+-#ifndef CONFIG_KPROBES
+-#ifdef CONFIG_HOTPLUG_CPU
+- /* It must still be possible to apply SMP alternatives. */
+- if (num_possible_cpus() <= 1)
+-#endif
+- {
+- set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
+- printk(KERN_INFO "Write protecting the kernel text: %luk\n",
+- size >> 10);
++ set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
++ printk(KERN_INFO "Write protecting the kernel text: %luk\n",
++ size >> 10);
+
+ #ifdef CONFIG_CPA_DEBUG
+- printk(KERN_INFO "Testing CPA: Reverting %lx-%lx\n",
+- start, start+size);
+- set_pages_rw(virt_to_page(start), size>>PAGE_SHIFT);
++ printk(KERN_INFO "Testing CPA: Reverting %lx-%lx\n",
++ start, start+size);
++ set_pages_rw(virt_to_page(start), size>>PAGE_SHIFT);
+
+- printk(KERN_INFO "Testing CPA: write protecting again\n");
+- set_pages_ro(virt_to_page(start), size>>PAGE_SHIFT);
+-#endif
+- }
++ printk(KERN_INFO "Testing CPA: write protecting again\n");
++ set_pages_ro(virt_to_page(start), size>>PAGE_SHIFT);
+ #endif
+ start += size;
+ size = (unsigned long)__end_rodata - start;
+diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
+index a02a14f..0cca626 100644
+--- a/arch/x86/mm/init_64.c
++++ b/arch/x86/mm/init_64.c
+@@ -47,13 +47,30 @@
+ #include <asm/numa.h>
+ #include <asm/cacheflush.h>
+
+-const struct dma_mapping_ops *dma_ops;
+-EXPORT_SYMBOL(dma_ops);
+-
+ static unsigned long dma_reserve __initdata;
+
+ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+
++int direct_gbpages __meminitdata
++#ifdef CONFIG_DIRECT_GBPAGES
++ = 1
++#endif
++;
++
++static int __init parse_direct_gbpages_off(char *arg)
++{
++ direct_gbpages = 0;
++ return 0;
++}
++early_param("nogbpages", parse_direct_gbpages_off);
++
++static int __init parse_direct_gbpages_on(char *arg)
++{
++ direct_gbpages = 1;
++ return 0;
++}
++early_param("gbpages", parse_direct_gbpages_on);
++
+ /*
+ * NOTE: pagetable_init alloc all the fixmap pagetables contiguous on the
+ * physical space so we can cache the place of the first one and move
+@@ -69,9 +86,6 @@ void show_mem(void)
+
+ printk(KERN_INFO "Mem-info:\n");
+ show_free_areas();
+- printk(KERN_INFO "Free swap: %6ldkB\n",
+- nr_swap_pages << (PAGE_SHIFT-10));
+-
+ for_each_online_pgdat(pgdat) {
+ for (i = 0; i < pgdat->node_spanned_pages; ++i) {
+ /*
+@@ -121,7 +135,7 @@ static __init void *spp_getpage(void)
+ return ptr;
+ }
+
+-static __init void
++static void
+ set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot)
+ {
+ pgd_t *pgd;
+@@ -159,7 +173,7 @@ set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot)
+ new_pte = pfn_pte(phys >> PAGE_SHIFT, prot);
+
+ pte = pte_offset_kernel(pmd, vaddr);
+- if (!pte_none(*pte) &&
++ if (!pte_none(*pte) && pte_val(new_pte) &&
+ pte_val(*pte) != (pte_val(new_pte) & __supported_pte_mask))
+ pte_ERROR(*pte);
+ set_pte(pte, new_pte);
+@@ -200,8 +214,7 @@ void __init cleanup_highmap(void)
+ }
+
+ /* NOTE: this is meant to be run only at boot */
+-void __init
+-__set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
++void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
+ {
+ unsigned long address = __fix_to_virt(idx);
+
+@@ -296,7 +309,7 @@ __meminit void early_iounmap(void *addr, unsigned long size)
+ __flush_tlb_all();
+ }
+
+-static void __meminit
++static unsigned long __meminit
+ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end)
+ {
+ int i = pmd_index(address);
+@@ -318,21 +331,26 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end)
+ set_pte((pte_t *)pmd,
+ pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL_LARGE));
+ }
++ return address;
+ }
+
+-static void __meminit
++static unsigned long __meminit
+ phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end)
+ {
+ pmd_t *pmd = pmd_offset(pud, 0);
++ unsigned long last_map_addr;
++
+ spin_lock(&init_mm.page_table_lock);
+- phys_pmd_init(pmd, address, end);
++ last_map_addr = phys_pmd_init(pmd, address, end);
+ spin_unlock(&init_mm.page_table_lock);
+ __flush_tlb_all();
++ return last_map_addr;
+ }
+
+-static void __meminit
++static unsigned long __meminit
+ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end)
+ {
++ unsigned long last_map_addr = end;
+ int i = pud_index(addr);
+
+ for (; i < PTRS_PER_PUD; i++, addr = (addr & PUD_MASK) + PUD_SIZE) {
+@@ -350,7 +368,15 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end)
+ }
+
+ if (pud_val(*pud)) {
+- phys_pmd_update(pud, addr, end);
++ if (!pud_large(*pud))
++ last_map_addr = phys_pmd_update(pud, addr, end);
++ continue;
++ }
++
++ if (direct_gbpages) {
++ set_pte((pte_t *)pud,
++ pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL_LARGE));
++ last_map_addr = (addr & PUD_MASK) + PUD_SIZE;
+ continue;
+ }
+
+@@ -358,12 +384,14 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end)
+
+ spin_lock(&init_mm.page_table_lock);
+ set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE));
+- phys_pmd_init(pmd, addr, end);
++ last_map_addr = phys_pmd_init(pmd, addr, end);
+ spin_unlock(&init_mm.page_table_lock);
+
+ unmap_low_page(pmd);
+ }
+ __flush_tlb_all();
++
++ return last_map_addr >> PAGE_SHIFT;
+ }
+
+ static void __init find_early_table_space(unsigned long end)
+@@ -371,9 +399,11 @@ static void __init find_early_table_space(unsigned long end)
+ unsigned long puds, pmds, tables, start;
+
+ puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
+- pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
+- tables = round_up(puds * sizeof(pud_t), PAGE_SIZE) +
+- round_up(pmds * sizeof(pmd_t), PAGE_SIZE);
++ tables = round_up(puds * sizeof(pud_t), PAGE_SIZE);
++ if (!direct_gbpages) {
++ pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
++ tables += round_up(pmds * sizeof(pmd_t), PAGE_SIZE);
++ }
+
+ /*
+ * RED-PEN putting page tables only on node 0 could
+@@ -393,16 +423,135 @@ static void __init find_early_table_space(unsigned long end)
+ (table_start << PAGE_SHIFT) + tables);
+ }
+
++static void __init init_gbpages(void)
++{
++ if (direct_gbpages && cpu_has_gbpages)
++ printk(KERN_INFO "Using GB pages for direct mapping\n");
++ else
++ direct_gbpages = 0;
++}
++
++#ifdef CONFIG_MEMTEST_BOOTPARAM
++
++static void __init memtest(unsigned long start_phys, unsigned long size,
++ unsigned pattern)
++{
++ 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;
++
++ switch (pattern) {
++ case 0:
++ val = 0UL;
++ break;
++ case 1:
++ val = -1UL;
++ break;
++ case 2:
++ val = 0x5555555555555555UL;
++ break;
++ case 3:
++ val = 0xaaaaaaaaaaaaaaaaUL;
++ break;
++ default:
++ return;
++ }
++
++ incr = sizeof(unsigned long);
++ start_phys_aligned = ALIGN(start_phys, incr);
++ count = (size - (start_phys_aligned - start_phys))/incr;
++ start = __va(start_phys_aligned);
++ start_bad = 0;
++ last_bad = 0;
++
++ for (i = 0; i < count; i++)
++ start[i] = val;
++ 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 %016lx - %016lx reserved",
++ val, start_bad, last_bad + incr);
++ reserve_early(start_bad, last_bad - start_bad, "BAD RAM");
++ }
++ start_bad = last_bad = start_phys_aligned;
++ }
++ }
++ }
++ if (start_bad) {
++ printk(KERN_CONT "\n %016lx bad mem addr %016lx - %016lx reserved",
++ val, start_bad, last_bad + incr);
++ reserve_early(start_bad, last_bad - start_bad, "BAD RAM");
++ }
++
++}
++
++static int memtest_pattern __initdata = CONFIG_MEMTEST_BOOTPARAM_VALUE;
++
++static int __init parse_memtest(char *arg)
++{
++ if (arg)
++ memtest_pattern = simple_strtoul(arg, NULL, 0);
++ return 0;
++}
++
++early_param("memtest", parse_memtest);
++
++static void __init early_memtest(unsigned long start, unsigned long end)
++{
++ unsigned long t_start, t_size;
++ unsigned pattern;
++
++ 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 %016lx - %016lx pattern %d",
++ t_start, t_start + t_size, pattern);
++
++ memtest(t_start, t_size, pattern);
++
++ t_start += t_size;
++ }
++ }
++ printk(KERN_CONT "\n");
++}
++#else
++static void __init early_memtest(unsigned long start, unsigned long end)
++{
++}
++#endif
++
+ /*
+ * Setup the direct mapping of the physical memory at PAGE_OFFSET.
+ * This runs before bootmem is initialized and gets pages directly from
+ * the physical memory. To access them they are temporarily mapped.
+ */
+-void __init_refok init_memory_mapping(unsigned long start, unsigned long end)
++unsigned long __init_refok init_memory_mapping(unsigned long start, unsigned long end)
+ {
+- unsigned long next;
++ unsigned long next, last_map_addr = end;
++ unsigned long start_phys = start, end_phys = end;
+
+- pr_debug("init_memory_mapping\n");
++ printk(KERN_INFO "init_memory_mapping\n");
+
+ /*
+ * Find space for the kernel direct mapping tables.
+@@ -411,8 +560,10 @@ void __init_refok init_memory_mapping(unsigned long start, unsigned long end)
+ * memory mapped. Unfortunately this is done currently before the
+ * nodes are discovered.
+ */
+- if (!after_bootmem)
++ if (!after_bootmem) {
++ init_gbpages();
+ find_early_table_space(end);
++ }
+
+ start = (unsigned long)__va(start);
+ end = (unsigned long)__va(end);
+@@ -430,7 +581,7 @@ void __init_refok init_memory_mapping(unsigned long start, unsigned long end)
+ next = start + PGDIR_SIZE;
+ if (next > end)
+ next = end;
+- phys_pud_init(pud, __pa(start), __pa(next));
++ last_map_addr = phys_pud_init(pud, __pa(start), __pa(next));
+ if (!after_bootmem)
+ set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys));
+ unmap_low_page(pud);
+@@ -443,6 +594,11 @@ void __init_refok init_memory_mapping(unsigned long start, unsigned long end)
+ if (!after_bootmem)
+ reserve_early(table_start << PAGE_SHIFT,
+ table_end << PAGE_SHIFT, "PGTABLE");
++
++ if (!after_bootmem)
++ early_memtest(start_phys, end_phys);
++
++ return last_map_addr;
+ }
+
+ #ifndef CONFIG_NUMA
+@@ -482,11 +638,13 @@ int arch_add_memory(int nid, u64 start, u64 size)
+ {
+ struct pglist_data *pgdat = NODE_DATA(nid);
+ struct zone *zone = pgdat->node_zones + ZONE_NORMAL;
+- unsigned long start_pfn = start >> PAGE_SHIFT;
++ unsigned long last_mapped_pfn, start_pfn = start >> PAGE_SHIFT;
+ unsigned long nr_pages = size >> PAGE_SHIFT;
+ int ret;
+
+- init_memory_mapping(start, start + size-1);
++ last_mapped_pfn = init_memory_mapping(start, start + size-1);
++ if (last_mapped_pfn > max_pfn_mapped)
++ max_pfn_mapped = last_mapped_pfn;
+
+ ret = __add_pages(zone, start_pfn, nr_pages);
+ WARN_ON(1);
+@@ -505,6 +663,26 @@ EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
+
+ #endif /* CONFIG_MEMORY_HOTPLUG */
+
++/*
++ * devmem_is_allowed() checks to see if /dev/mem access to a certain address
++ * is valid. The argument is a physical page number.
++ *
++ *
++ * On x86, access has to be given to the first megabyte of ram because that area
++ * contains bios code and data regions used by X and dosemu and similar apps.
++ * Access has to be given to non-kernel-ram areas as well, these contain the PCI
++ * mmio resources as well as potential bios/acpi data regions.
++ */
++int devmem_is_allowed(unsigned long pagenr)
++{
++ if (pagenr <= 256)
++ return 1;
++ if (!page_is_ram(pagenr))
++ return 1;
++ return 0;
++}
++
++
+ static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel,
+ kcore_modules, kcore_vsyscall;
+
+@@ -596,24 +774,7 @@ EXPORT_SYMBOL_GPL(rodata_test_data);
+
+ void mark_rodata_ro(void)
+ {
+- unsigned long start = (unsigned long)_stext, end;
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+- /* It must still be possible to apply SMP alternatives. */
+- if (num_possible_cpus() > 1)
+- start = (unsigned long)_etext;
+-#endif
+-
+-#ifdef CONFIG_KPROBES
+- start = (unsigned long)__start_rodata;
+-#endif
+-
+- end = (unsigned long)__end_rodata;
+- start = (start + PAGE_SIZE - 1) & PAGE_MASK;
+- end &= PAGE_MASK;
+- if (end <= start)
+- return;
+-
++ unsigned long start = PFN_ALIGN(_stext), end = PFN_ALIGN(__end_rodata);
+
+ printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
+ (end - start) >> 10);
+@@ -636,6 +797,7 @@ void mark_rodata_ro(void)
+ set_memory_ro(start, (end-start) >> PAGE_SHIFT);
+ #endif
+ }
++
+ #endif
+
+ #ifdef CONFIG_BLK_DEV_INITRD
+@@ -657,7 +819,7 @@ void __init reserve_bootmem_generic(unsigned long phys, unsigned len)
+ * This can happen with kdump kernels when accessing
+ * firmware tables:
+ */
+- if (pfn < end_pfn_map)
++ if (pfn < max_pfn_mapped)
+ return;
+
+ printk(KERN_ERR "reserve_bootmem: illegal reserve %lx %u\n",
+diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
+index 794895c..d176b23 100644
+--- a/arch/x86/mm/ioremap.c
++++ b/arch/x86/mm/ioremap.c
+@@ -19,11 +19,7 @@
+ #include <asm/pgtable.h>
+ #include <asm/tlbflush.h>
+ #include <asm/pgalloc.h>
+-
+-enum ioremap_mode {
+- IOR_MODE_UNCACHED,
+- IOR_MODE_CACHED,
+-};
++#include <asm/pat.h>
+
+ #ifdef CONFIG_X86_64
+
+@@ -35,11 +31,23 @@ unsigned long __phys_addr(unsigned long x)
+ }
+ EXPORT_SYMBOL(__phys_addr);
+
++static inline int phys_addr_valid(unsigned long addr)
++{
++ return addr < (1UL << boot_cpu_data.x86_phys_bits);
++}
++
++#else
++
++static inline int phys_addr_valid(unsigned long addr)
++{
++ return 1;
++}
++
+ #endif
+
+ int page_is_ram(unsigned long pagenr)
+ {
+- unsigned long addr, end;
++ resource_size_t addr, end;
+ int i;
+
+ /*
+@@ -78,19 +86,22 @@ int page_is_ram(unsigned long pagenr)
+ * Fix up the linear direct mapping of the kernel to avoid cache attribute
+ * conflicts.
+ */
+-static int ioremap_change_attr(unsigned long vaddr, unsigned long size,
+- enum ioremap_mode mode)
++int ioremap_change_attr(unsigned long vaddr, unsigned long size,
++ unsigned long prot_val)
+ {
+ unsigned long nrpages = size >> PAGE_SHIFT;
+ int err;
+
+- switch (mode) {
+- case IOR_MODE_UNCACHED:
++ switch (prot_val) {
++ case _PAGE_CACHE_UC:
+ default:
+- err = set_memory_uc(vaddr, nrpages);
++ err = _set_memory_uc(vaddr, nrpages);
++ break;
++ case _PAGE_CACHE_WC:
++ err = _set_memory_wc(vaddr, nrpages);
+ break;
+- case IOR_MODE_CACHED:
+- err = set_memory_wb(vaddr, nrpages);
++ case _PAGE_CACHE_WB:
++ err = _set_memory_wb(vaddr, nrpages);
+ break;
+ }
+
+@@ -107,17 +118,27 @@ static int ioremap_change_attr(unsigned long vaddr, unsigned long size,
+ * caller shouldn't need to know that small detail.
+ */
+ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
+- enum ioremap_mode mode)
++ unsigned long prot_val)
+ {
+- unsigned long pfn, offset, last_addr, vaddr;
++ unsigned long pfn, offset, vaddr;
++ resource_size_t last_addr;
+ struct vm_struct *area;
++ unsigned long new_prot_val;
+ pgprot_t prot;
++ int retval;
+
+ /* Don't allow wraparound or zero size */
+ last_addr = phys_addr + size - 1;
+ if (!size || last_addr < phys_addr)
+ return NULL;
+
++ if (!phys_addr_valid(phys_addr)) {
++ printk(KERN_WARNING "ioremap: invalid physical address %llx\n",
++ (unsigned long long)phys_addr);
++ WARN_ON_ONCE(1);
++ return NULL;
++ }
++
+ /*
+ * Don't remap the low PCI/ISA area, it's always mapped..
+ */
+@@ -127,25 +148,14 @@ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
+ /*
+ * Don't allow anybody to remap normal RAM that we're using..
+ */
+- for (pfn = phys_addr >> PAGE_SHIFT; pfn < max_pfn_mapped &&
+- (pfn << PAGE_SHIFT) < last_addr; pfn++) {
+- if (page_is_ram(pfn) && pfn_valid(pfn) &&
+- !PageReserved(pfn_to_page(pfn)))
+- return NULL;
+- }
++ for (pfn = phys_addr >> PAGE_SHIFT;
++ (pfn << PAGE_SHIFT) < last_addr; pfn++) {
+
+- switch (mode) {
+- case IOR_MODE_UNCACHED:
+- default:
+- /*
+- * FIXME: we will use UC MINUS for now, as video fb drivers
+- * depend on it. Upcoming ioremap_wc() will fix this behavior.
+- */
+- prot = PAGE_KERNEL_UC_MINUS;
+- break;
+- case IOR_MODE_CACHED:
+- prot = PAGE_KERNEL;
+- break;
++ int is_ram = page_is_ram(pfn);
++
++ if (is_ram && pfn_valid(pfn) && !PageReserved(pfn_to_page(pfn)))
++ return NULL;
++ WARN_ON_ONCE(is_ram);
+ }
+
+ /*
+@@ -155,6 +165,50 @@ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
+ phys_addr &= PAGE_MASK;
+ size = PAGE_ALIGN(last_addr+1) - phys_addr;
+
++ retval = reserve_memtype(phys_addr, phys_addr + size,
++ prot_val, &new_prot_val);
++ if (retval) {
++ pr_debug("Warning: reserve_memtype returned %d\n", retval);
++ return NULL;
++ }
++
++ if (prot_val != new_prot_val) {
++ /*
++ * Do not fallback to certain memory types with certain
++ * requested type:
++ * - request is uncached, return cannot be write-back
++ * - request is uncached, return cannot be write-combine
++ * - request is write-combine, return cannot be write-back
++ */
++ if ((prot_val == _PAGE_CACHE_UC &&
++ (new_prot_val == _PAGE_CACHE_WB ||
++ new_prot_val == _PAGE_CACHE_WC)) ||
++ (prot_val == _PAGE_CACHE_WC &&
++ new_prot_val == _PAGE_CACHE_WB)) {
++ pr_debug(
++ "ioremap error for 0x%llx-0x%llx, requested 0x%lx, got 0x%lx\n",
++ (unsigned long long)phys_addr,
++ (unsigned long long)(phys_addr + size),
++ prot_val, new_prot_val);
++ free_memtype(phys_addr, phys_addr + size);
++ return NULL;
++ }
++ prot_val = new_prot_val;
++ }
++
++ switch (prot_val) {
++ case _PAGE_CACHE_UC:
++ default:
++ prot = PAGE_KERNEL_NOCACHE;
++ break;
++ case _PAGE_CACHE_WC:
++ prot = PAGE_KERNEL_WC;
++ break;
++ case _PAGE_CACHE_WB:
++ prot = PAGE_KERNEL;
++ break;
++ }
++
+ /*
+ * Ok, go for it..
+ */
+@@ -164,11 +218,13 @@ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
+ area->phys_addr = phys_addr;
+ vaddr = (unsigned long) area->addr;
+ if (ioremap_page_range(vaddr, vaddr + size, phys_addr, prot)) {
++ free_memtype(phys_addr, phys_addr + size);
+ free_vm_area(area);
+ return NULL;
+ }
+
+- if (ioremap_change_attr(vaddr, size, mode) < 0) {
++ if (ioremap_change_attr(vaddr, size, prot_val) < 0) {
++ free_memtype(phys_addr, phys_addr + size);
+ vunmap(area->addr);
+ return NULL;
+ }
+@@ -199,13 +255,32 @@ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
+ */
+ void __iomem *ioremap_nocache(resource_size_t phys_addr, unsigned long size)
+ {
+- return __ioremap(phys_addr, size, IOR_MODE_UNCACHED);
++ return __ioremap(phys_addr, size, _PAGE_CACHE_UC);
+ }
+ EXPORT_SYMBOL(ioremap_nocache);
+
++/**
++ * ioremap_wc - map memory into CPU space write combined
++ * @offset: bus address of the memory
++ * @size: size of the resource to map
++ *
++ * This version of ioremap ensures that the memory is marked write combining.
++ * Write combining allows faster writes to some hardware devices.
++ *
++ * Must be freed with iounmap.
++ */
++void __iomem *ioremap_wc(unsigned long phys_addr, unsigned long size)
++{
++ if (pat_wc_enabled)
++ return __ioremap(phys_addr, size, _PAGE_CACHE_WC);
++ else
++ return ioremap_nocache(phys_addr, size);
++}
++EXPORT_SYMBOL(ioremap_wc);
++
+ void __iomem *ioremap_cache(resource_size_t phys_addr, unsigned long size)
+ {
+- return __ioremap(phys_addr, size, IOR_MODE_CACHED);
++ return __ioremap(phys_addr, size, _PAGE_CACHE_WB);
+ }
+ EXPORT_SYMBOL(ioremap_cache);
+
+@@ -252,6 +327,8 @@ void iounmap(volatile void __iomem *addr)
+ return;
+ }
+
++ free_memtype(p->phys_addr, p->phys_addr + get_vm_area_size(p));
++
+ /* Finally remove it */
+ o = remove_vm_area((void *)addr);
+ BUG_ON(p != o || o == NULL);
+@@ -259,6 +336,35 @@ void iounmap(volatile void __iomem *addr)
+ }
+ EXPORT_SYMBOL(iounmap);
+
++/*
++ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
++ * access
++ */
++void *xlate_dev_mem_ptr(unsigned long phys)
++{
++ void *addr;
++ unsigned long start = phys & PAGE_MASK;
++
++ /* If page is RAM, we can use __va. Otherwise ioremap and unmap. */
++ if (page_is_ram(start >> PAGE_SHIFT))
++ return __va(phys);
++
++ addr = (void *)ioremap(start, PAGE_SIZE);
++ if (addr)
++ addr = (void *)((unsigned long)addr | (phys & ~PAGE_MASK));
++
++ return addr;
++}
++
++void unxlate_dev_mem_ptr(unsigned long phys, void *addr)
++{
++ if (page_is_ram(phys >> PAGE_SHIFT))
++ return;
++
++ iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
++ return;
++}
++
+ #ifdef CONFIG_X86_32
+
+ int __initdata early_ioremap_debug;
+@@ -272,8 +378,8 @@ static int __init early_ioremap_debug_setup(char *str)
+ early_param("early_ioremap_debug", early_ioremap_debug_setup);
+
+ static __initdata int after_paging_init;
+-static __initdata pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)]
+- __attribute__((aligned(PAGE_SIZE)));
++static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)]
++ __section(.bss.page_aligned);
+
+ static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
+ {
+@@ -330,7 +436,7 @@ void __init early_ioremap_clear(void)
+
+ pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
+ pmd_clear(pmd);
+- paravirt_release_pt(__pa(bm_pte) >> PAGE_SHIFT);
++ paravirt_release_pte(__pa(bm_pte) >> PAGE_SHIFT);
+ __flush_tlb_all();
+ }
+
+diff --git a/arch/x86/mm/k8topology_64.c b/arch/x86/mm/k8topology_64.c
+index 7a2ebce..86808e6 100644
+--- a/arch/x86/mm/k8topology_64.c
++++ b/arch/x86/mm/k8topology_64.c
+@@ -164,7 +164,7 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
+ if (!found)
+ return -1;
+
+- memnode_shift = compute_hash_shift(nodes, 8);
++ memnode_shift = compute_hash_shift(nodes, 8, NULL);
+ if (memnode_shift < 0) {
+ printk(KERN_ERR "No NUMA node hash function found. Contact maintainer\n");
+ return -1;
+diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c
+index 16b82ad..9a68922 100644
+--- a/arch/x86/mm/numa_64.c
++++ b/arch/x86/mm/numa_64.c
+@@ -31,13 +31,15 @@ bootmem_data_t plat_node_bdata[MAX_NUMNODES];
+
+ struct memnode memnode;
+
++#ifdef CONFIG_SMP
+ int x86_cpu_to_node_map_init[NR_CPUS] = {
+ [0 ... NR_CPUS-1] = NUMA_NO_NODE
+ };
+ void *x86_cpu_to_node_map_early_ptr;
++EXPORT_SYMBOL(x86_cpu_to_node_map_early_ptr);
++#endif
+ DEFINE_PER_CPU(int, x86_cpu_to_node_map) = NUMA_NO_NODE;
+ EXPORT_PER_CPU_SYMBOL(x86_cpu_to_node_map);
+-EXPORT_SYMBOL(x86_cpu_to_node_map_early_ptr);
+
+ s16 apicid_to_node[MAX_LOCAL_APIC] __cpuinitdata = {
+ [0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
+@@ -58,7 +60,7 @@ unsigned long __initdata nodemap_size;
+ * -1 if node overlap or lost ram (shift too big)
+ */
+ static int __init populate_memnodemap(const struct bootnode *nodes,
+- int numnodes, int shift)
++ int numnodes, int shift, int *nodeids)
+ {
+ unsigned long addr, end;
+ int i, res = -1;
+@@ -74,7 +76,12 @@ static int __init populate_memnodemap(const struct bootnode *nodes,
+ do {
+ if (memnodemap[addr >> shift] != NUMA_NO_NODE)
+ return -1;
+- memnodemap[addr >> shift] = i;
++
++ if (!nodeids)
++ memnodemap[addr >> shift] = i;
++ else
++ memnodemap[addr >> shift] = nodeids[i];
++
+ addr += (1UL << shift);
+ } while (addr < end);
+ res = 1;
+@@ -137,7 +144,8 @@ static int __init extract_lsb_from_nodes(const struct bootnode *nodes,
+ return i;
+ }
+
+-int __init compute_hash_shift(struct bootnode *nodes, int numnodes)
++int __init compute_hash_shift(struct bootnode *nodes, int numnodes,
++ int *nodeids)
+ {
+ int shift;
+
+@@ -147,7 +155,7 @@ int __init compute_hash_shift(struct bootnode *nodes, int numnodes)
+ printk(KERN_DEBUG "NUMA: Using %d for the hash shift.\n",
+ shift);
+
+- if (populate_memnodemap(nodes, numnodes, shift) != 1) {
++ if (populate_memnodemap(nodes, numnodes, shift, nodeids) != 1) {
+ printk(KERN_INFO "Your memory is not aligned you need to "
+ "rebuild your kernel with a bigger NODEMAPSIZE "
+ "shift=%d\n", shift);
+@@ -378,9 +386,10 @@ static int __init split_nodes_by_size(struct bootnode *nodes, u64 *addr,
+ * Sets up the system RAM area from start_pfn to end_pfn according to the
+ * numa=fake command-line option.
+ */
++static struct bootnode nodes[MAX_NUMNODES] __initdata;
++
+ static int __init numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
+ {
+- struct bootnode nodes[MAX_NUMNODES];
+ u64 size, addr = start_pfn << PAGE_SHIFT;
+ u64 max_addr = end_pfn << PAGE_SHIFT;
+ int num_nodes = 0, num = 0, coeff_flag, coeff = -1, i;
+@@ -460,7 +469,7 @@ done:
+ }
+ }
+ out:
+- memnode_shift = compute_hash_shift(nodes, num_nodes);
++ memnode_shift = compute_hash_shift(nodes, num_nodes, NULL);
+ if (memnode_shift < 0) {
+ memnode_shift = 0;
+ printk(KERN_ERR "No NUMA hash function found. NUMA emulation "
+@@ -548,8 +557,6 @@ void __cpuinit numa_set_node(int cpu, int node)
+ {
+ int *cpu_to_node_map = x86_cpu_to_node_map_early_ptr;
+
+- cpu_pda(cpu)->nodenumber = node;
+-
+ if(cpu_to_node_map)
+ cpu_to_node_map[cpu] = node;
+ else if(per_cpu_offset(cpu))
+diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
+index 7b79f6b..bd5e05c 100644
+--- a/arch/x86/mm/pageattr.c
++++ b/arch/x86/mm/pageattr.c
+@@ -9,6 +9,8 @@
+ #include <linux/slab.h>
+ #include <linux/mm.h>
+ #include <linux/interrupt.h>
++#include <linux/seq_file.h>
++#include <linux/debugfs.h>
+
+ #include <asm/e820.h>
+ #include <asm/processor.h>
+@@ -17,6 +19,7 @@
+ #include <asm/uaccess.h>
+ #include <asm/pgalloc.h>
+ #include <asm/proto.h>
++#include <asm/pat.h>
+
+ /*
+ * The current flushing context - we pass it instead of 5 arguments:
+@@ -28,6 +31,7 @@ struct cpa_data {
+ int numpages;
+ int flushtlb;
+ unsigned long pfn;
++ unsigned force_split : 1;
+ };
+
+ #ifdef CONFIG_X86_64
+@@ -259,6 +263,9 @@ try_preserve_large_page(pte_t *kpte, unsigned long address,
+ int i, do_split = 1;
+ unsigned int level;
+
++ if (cpa->force_split)
++ return 1;
++
+ spin_lock_irqsave(&pgd_lock, flags);
+ /*
+ * Check for races, another CPU might have split this page
+@@ -476,9 +483,7 @@ static int split_large_page(pte_t *kpte, unsigned long address)
+ goto out_unlock;
+
+ pbase = (pte_t *)page_address(base);
+-#ifdef CONFIG_X86_32
+- paravirt_alloc_pt(&init_mm, page_to_pfn(base));
+-#endif
++ paravirt_alloc_pte(&init_mm, page_to_pfn(base));
+ ref_prot = pte_pgprot(pte_clrhuge(*kpte));
+
+ #ifdef CONFIG_X86_64
+@@ -535,7 +540,7 @@ static int __change_page_attr(struct cpa_data *cpa, int primary)
+ repeat:
+ kpte = lookup_address(address, &level);
+ if (!kpte)
+- return primary ? -EINVAL : 0;
++ return 0;
+
+ old_pte = *kpte;
+ if (!pte_val(old_pte)) {
+@@ -693,7 +698,8 @@ static inline int cache_attr(pgprot_t attr)
+ }
+
+ static int change_page_attr_set_clr(unsigned long addr, int numpages,
+- pgprot_t mask_set, pgprot_t mask_clr)
++ pgprot_t mask_set, pgprot_t mask_clr,
++ int force_split)
+ {
+ struct cpa_data cpa;
+ int ret, cache, checkalias;
+@@ -704,7 +710,7 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages,
+ */
+ mask_set = canon_pgprot(mask_set);
+ mask_clr = canon_pgprot(mask_clr);
+- if (!pgprot_val(mask_set) && !pgprot_val(mask_clr))
++ if (!pgprot_val(mask_set) && !pgprot_val(mask_clr) && !force_split)
+ return 0;
+
+ /* Ensure we are PAGE_SIZE aligned */
+@@ -721,6 +727,7 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages,
+ cpa.mask_set = mask_set;
+ cpa.mask_clr = mask_clr;
+ cpa.flushtlb = 0;
++ cpa.force_split = force_split;
+
+ /* No alias checking for _NX bit modifications */
+ checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX;
+@@ -759,26 +766,61 @@ out:
+ static inline int change_page_attr_set(unsigned long addr, int numpages,
+ pgprot_t mask)
+ {
+- return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0));
++ return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0), 0);
+ }
+
+ static inline int change_page_attr_clear(unsigned long addr, int numpages,
+ pgprot_t mask)
+ {
+- return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask);
++ return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask, 0);
+ }
+
+-int set_memory_uc(unsigned long addr, int numpages)
++int _set_memory_uc(unsigned long addr, int numpages)
+ {
+ return change_page_attr_set(addr, numpages,
+- __pgprot(_PAGE_PCD));
++ __pgprot(_PAGE_CACHE_UC));
++}
++
++int set_memory_uc(unsigned long addr, int numpages)
++{
++ if (reserve_memtype(addr, addr + numpages * PAGE_SIZE,
++ _PAGE_CACHE_UC, NULL))
++ return -EINVAL;
++
++ return _set_memory_uc(addr, numpages);
+ }
+ EXPORT_SYMBOL(set_memory_uc);
+
+-int set_memory_wb(unsigned long addr, int numpages)
++int _set_memory_wc(unsigned long addr, int numpages)
++{
++ return change_page_attr_set(addr, numpages,
++ __pgprot(_PAGE_CACHE_WC));
++}
++
++int set_memory_wc(unsigned long addr, int numpages)
++{
++ if (!pat_wc_enabled)
++ return set_memory_uc(addr, numpages);
++
++ if (reserve_memtype(addr, addr + numpages * PAGE_SIZE,
++ _PAGE_CACHE_WC, NULL))
++ return -EINVAL;
++
++ return _set_memory_wc(addr, numpages);
++}
++EXPORT_SYMBOL(set_memory_wc);
++
++int _set_memory_wb(unsigned long addr, int numpages)
+ {
+ return change_page_attr_clear(addr, numpages,
+- __pgprot(_PAGE_PCD | _PAGE_PWT));
++ __pgprot(_PAGE_CACHE_MASK));
++}
++
++int set_memory_wb(unsigned long addr, int numpages)
++{
++ free_memtype(addr, addr + numpages * PAGE_SIZE);
++
++ return _set_memory_wb(addr, numpages);
+ }
+ EXPORT_SYMBOL(set_memory_wb);
+
+@@ -809,6 +851,12 @@ int set_memory_np(unsigned long addr, int numpages)
+ return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_PRESENT));
+ }
+
++int set_memory_4k(unsigned long addr, int numpages)
++{
++ return change_page_attr_set_clr(addr, numpages, __pgprot(0),
++ __pgprot(0), 1);
++}
++
+ int set_pages_uc(struct page *page, int numpages)
+ {
+ unsigned long addr = (unsigned long)page_address(page);
+@@ -918,6 +966,45 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
+ cpa_fill_pool(NULL);
+ }
+
++#ifdef CONFIG_DEBUG_FS
++static int dpa_show(struct seq_file *m, void *v)
++{
++ seq_puts(m, "DEBUG_PAGEALLOC\n");
++ seq_printf(m, "pool_size : %lu\n", pool_size);
++ seq_printf(m, "pool_pages : %lu\n", pool_pages);
++ seq_printf(m, "pool_low : %lu\n", pool_low);
++ seq_printf(m, "pool_used : %lu\n", pool_used);
++ seq_printf(m, "pool_failed : %lu\n", pool_failed);
++
++ return 0;
++}
++
++static int dpa_open(struct inode *inode, struct file *filp)
++{
++ return single_open(filp, dpa_show, NULL);
++}
++
++static const struct file_operations dpa_fops = {
++ .open = dpa_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static int __init debug_pagealloc_proc_init(void)
++{
++ struct dentry *de;
++
++ de = debugfs_create_file("debug_pagealloc", 0600, NULL, NULL,
++ &dpa_fops);
++ if (!de)
++ return -ENOMEM;
++
++ return 0;
++}
++__initcall(debug_pagealloc_proc_init);
++#endif
++
+ #ifdef CONFIG_HIBERNATION
+
+ bool kernel_page_present(struct page *page)
+diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
+new file mode 100644
+index 0000000..9851265
+--- /dev/null
++++ b/arch/x86/mm/pat.c
+@@ -0,0 +1,568 @@
++/*
++ * Handle caching attributes in page tables (PAT)
++ *
++ * Authors: Venkatesh Pallipadi <venkatesh.pallipadi at intel.com>
++ * Suresh B Siddha <suresh.b.siddha at intel.com>
++ *
++ * Loosely based on earlier PAT patchset from Eric Biederman and Andi Kleen.
++ */
++
++#include <linux/mm.h>
++#include <linux/kernel.h>
++#include <linux/gfp.h>
++#include <linux/fs.h>
++#include <linux/bootmem.h>
++
++#include <asm/msr.h>
++#include <asm/tlbflush.h>
++#include <asm/processor.h>
++#include <asm/pgtable.h>
++#include <asm/pat.h>
++#include <asm/e820.h>
++#include <asm/cacheflush.h>
++#include <asm/fcntl.h>
++#include <asm/mtrr.h>
++#include <asm/io.h>
++
++int pat_wc_enabled = 1;
++
++static u64 __read_mostly boot_pat_state;
++
++static int nopat(char *str)
++{
++ pat_wc_enabled = 0;
++ printk(KERN_INFO "x86: PAT support disabled.\n");
++
++ return 0;
++}
++early_param("nopat", nopat);
++
++static int pat_known_cpu(void)
++{
++ if (!pat_wc_enabled)
++ return 0;
++
++ if (cpu_has_pat)
++ return 1;
++
++ pat_wc_enabled = 0;
++ printk(KERN_INFO "CPU and/or kernel does not support PAT.\n");
++ return 0;
++}
++
++enum {
++ PAT_UC = 0, /* uncached */
++ PAT_WC = 1, /* Write combining */
++ PAT_WT = 4, /* Write Through */
++ PAT_WP = 5, /* Write Protected */
++ PAT_WB = 6, /* Write Back (default) */
++ PAT_UC_MINUS = 7, /* UC, but can be overriden by MTRR */
++};
++
++#define PAT(x,y) ((u64)PAT_ ## y << ((x)*8))
++
++void pat_init(void)
++{
++ u64 pat;
++
++#ifndef CONFIG_X86_PAT
++ nopat(NULL);
++#endif
++
++ /* Boot CPU enables PAT based on CPU feature */
++ if (!smp_processor_id() && !pat_known_cpu())
++ return;
++
++ /* APs enable PAT iff boot CPU has enabled it before */
++ if (smp_processor_id() && !pat_wc_enabled)
++ return;
++
++ /* Set PWT to Write-Combining. All other bits stay the same */
++ /*
++ * PTE encoding used in Linux:
++ * PAT
++ * |PCD
++ * ||PWT
++ * |||
++ * 000 WB _PAGE_CACHE_WB
++ * 001 WC _PAGE_CACHE_WC
++ * 010 UC- _PAGE_CACHE_UC_MINUS
++ * 011 UC _PAGE_CACHE_UC
++ * PAT bit unused
++ */
++ pat = PAT(0,WB) | PAT(1,WC) | PAT(2,UC_MINUS) | PAT(3,UC) |
++ PAT(4,WB) | PAT(5,WC) | PAT(6,UC_MINUS) | PAT(7,UC);
++
++ /* Boot CPU check */
++ if (!smp_processor_id()) {
++ rdmsrl(MSR_IA32_CR_PAT, boot_pat_state);
++ }
++
++ wrmsrl(MSR_IA32_CR_PAT, pat);
++ printk(KERN_INFO "x86 PAT enabled: cpu %d, old 0x%Lx, new 0x%Lx\n",
++ smp_processor_id(), boot_pat_state, pat);
++}
++
++#undef PAT
++
++static char *cattr_name(unsigned long flags)
++{
++ switch (flags & _PAGE_CACHE_MASK) {
++ case _PAGE_CACHE_UC: return "uncached";
++ case _PAGE_CACHE_UC_MINUS: return "uncached-minus";
++ case _PAGE_CACHE_WB: return "write-back";
++ case _PAGE_CACHE_WC: return "write-combining";
++ default: return "broken";
++ }
++}
++
++/*
++ * The global memtype list keeps track of memory type for specific
++ * physical memory areas. Conflicting memory types in different
++ * mappings can cause CPU cache corruption. To avoid this we keep track.
++ *
++ * The list is sorted based on starting address and can contain multiple
++ * entries for each address (this allows reference counting for overlapping
++ * areas). All the aliases have the same cache attributes of course.
++ * Zero attributes are represented as holes.
++ *
++ * Currently the data structure is a list because the number of mappings
++ * are expected to be relatively small. If this should be a problem
++ * it could be changed to a rbtree or similar.
++ *
++ * memtype_lock protects the whole list.
++ */
++
++struct memtype {
++ u64 start;
++ u64 end;
++ unsigned long type;
++ struct list_head nd;
++};
++
++static LIST_HEAD(memtype_list);
++static DEFINE_SPINLOCK(memtype_lock); /* protects memtype list */
++
++/*
++ * Does intersection of PAT memory type and MTRR memory type and returns
++ * the resulting memory type as PAT understands it.
++ * (Type in pat and mtrr will not have same value)
++ * The intersection is based on "Effective Memory Type" tables in IA-32
++ * SDM vol 3a
++ */
++static int pat_x_mtrr_type(u64 start, u64 end, unsigned long prot,
++ unsigned long *ret_prot)
++{
++ unsigned long pat_type;
++ u8 mtrr_type;
++
++ mtrr_type = mtrr_type_lookup(start, end);
++ if (mtrr_type == 0xFF) { /* MTRR not enabled */
++ *ret_prot = prot;
++ return 0;
++ }
++ if (mtrr_type == 0xFE) { /* MTRR match error */
++ *ret_prot = _PAGE_CACHE_UC;
++ return -1;
++ }
++ if (mtrr_type != MTRR_TYPE_UNCACHABLE &&
++ mtrr_type != MTRR_TYPE_WRBACK &&
++ mtrr_type != MTRR_TYPE_WRCOMB) { /* MTRR type unhandled */
++ *ret_prot = _PAGE_CACHE_UC;
++ return -1;
++ }
++
++ pat_type = prot & _PAGE_CACHE_MASK;
++ prot &= (~_PAGE_CACHE_MASK);
++
++ /* Currently doing intersection by hand. Optimize it later. */
++ if (pat_type == _PAGE_CACHE_WC) {
++ *ret_prot = prot | _PAGE_CACHE_WC;
++ } else if (pat_type == _PAGE_CACHE_UC_MINUS) {
++ *ret_prot = prot | _PAGE_CACHE_UC_MINUS;
++ } else if (pat_type == _PAGE_CACHE_UC ||
++ mtrr_type == MTRR_TYPE_UNCACHABLE) {
++ *ret_prot = prot | _PAGE_CACHE_UC;
++ } else if (mtrr_type == MTRR_TYPE_WRCOMB) {
++ *ret_prot = prot | _PAGE_CACHE_WC;
++ } else {
++ *ret_prot = prot | _PAGE_CACHE_WB;
++ }
++
++ return 0;
++}
++
++/*
++ * req_type typically has one of the:
++ * - _PAGE_CACHE_WB
++ * - _PAGE_CACHE_WC
++ * - _PAGE_CACHE_UC_MINUS
++ * - _PAGE_CACHE_UC
++ *
++ * req_type will have a special case value '-1', when requester want to inherit
++ * the memory type from mtrr (if WB), existing PAT, defaulting to UC_MINUS.
++ *
++ * If ret_type is NULL, function will return an error if it cannot reserve the
++ * region with req_type. If ret_type is non-null, function will return
++ * available type in ret_type in case of no error. In case of any error
++ * it will return a negative return value.
++ */
++int reserve_memtype(u64 start, u64 end, unsigned long req_type,
++ unsigned long *ret_type)
++{
++ struct memtype *new_entry = NULL;
++ struct memtype *parse;
++ unsigned long actual_type;
++ int err = 0;
++
++ /* Only track when pat_wc_enabled */
++ if (!pat_wc_enabled) {
++ /* This is identical to page table setting without PAT */
++ if (ret_type) {
++ if (req_type == -1) {
++ *ret_type = _PAGE_CACHE_WB;
++ } else {
++ *ret_type = req_type;
++ }
++ }
++ return 0;
++ }
++
++ /* Low ISA region is always mapped WB in page table. No need to track */
++ if (start >= ISA_START_ADDRESS && (end - 1) <= ISA_END_ADDRESS) {
++ if (ret_type)
++ *ret_type = _PAGE_CACHE_WB;
++
++ return 0;
++ }
++
++ if (req_type == -1) {
++ /*
++ * Special case where caller wants to inherit from mtrr or
++ * existing pat mapping, defaulting to UC_MINUS in case of
++ * no match.
++ */
++ u8 mtrr_type = mtrr_type_lookup(start, end);
++ if (mtrr_type == 0xFE) { /* MTRR match error */
++ err = -1;
++ }
++
++ if (mtrr_type == MTRR_TYPE_WRBACK) {
++ req_type = _PAGE_CACHE_WB;
++ actual_type = _PAGE_CACHE_WB;
++ } else {
++ req_type = _PAGE_CACHE_UC_MINUS;
++ actual_type = _PAGE_CACHE_UC_MINUS;
++ }
++ } else {
++ req_type &= _PAGE_CACHE_MASK;
++ err = pat_x_mtrr_type(start, end, req_type, &actual_type);
++ }
++
++ if (err) {
++ if (ret_type)
++ *ret_type = actual_type;
++
++ return -EINVAL;
++ }
++
++ new_entry = kmalloc(sizeof(struct memtype), GFP_KERNEL);
++ if (!new_entry)
++ return -ENOMEM;
++
++ new_entry->start = start;
++ new_entry->end = end;
++ new_entry->type = actual_type;
++
++ if (ret_type)
++ *ret_type = actual_type;
++
++ spin_lock(&memtype_lock);
++
++ /* Search for existing mapping that overlaps the current range */
++ list_for_each_entry(parse, &memtype_list, nd) {
++ struct memtype *saved_ptr;
++
++ if (parse->start >= end) {
++ pr_debug("New Entry\n");
++ list_add(&new_entry->nd, parse->nd.prev);
++ new_entry = NULL;
++ break;
++ }
++
++ if (start <= parse->start && end >= parse->start) {
++ if (actual_type != parse->type && ret_type) {
++ actual_type = parse->type;
++ *ret_type = actual_type;
++ new_entry->type = actual_type;
++ }
++
++ if (actual_type != parse->type) {
++ printk(
++ KERN_INFO "%s:%d conflicting memory types %Lx-%Lx %s<->%s\n",
++ current->comm, current->pid,
++ start, end,
++ cattr_name(actual_type),
++ cattr_name(parse->type));
++ err = -EBUSY;
++ break;
++ }
++
++ saved_ptr = parse;
++ /*
++ * Check to see whether the request overlaps more
++ * than one entry in the list
++ */
++ list_for_each_entry_continue(parse, &memtype_list, nd) {
++ if (end <= parse->start) {
++ break;
++ }
++
++ if (actual_type != parse->type) {
++ printk(
++ KERN_INFO "%s:%d conflicting memory types %Lx-%Lx %s<->%s\n",
++ current->comm, current->pid,
++ start, end,
++ cattr_name(actual_type),
++ cattr_name(parse->type));
++ err = -EBUSY;
++ break;
++ }
++ }
++
++ if (err) {
++ break;
++ }
++
++ pr_debug("Overlap at 0x%Lx-0x%Lx\n",
++ saved_ptr->start, saved_ptr->end);
++ /* No conflict. Go ahead and add this new entry */
++ list_add(&new_entry->nd, saved_ptr->nd.prev);
++ new_entry = NULL;
++ break;
++ }
++
++ if (start < parse->end) {
++ if (actual_type != parse->type && ret_type) {
++ actual_type = parse->type;
++ *ret_type = actual_type;
++ new_entry->type = actual_type;
++ }
++
++ if (actual_type != parse->type) {
++ printk(
++ KERN_INFO "%s:%d conflicting memory types %Lx-%Lx %s<->%s\n",
++ current->comm, current->pid,
++ start, end,
++ cattr_name(actual_type),
++ cattr_name(parse->type));
++ err = -EBUSY;
++ break;
++ }
++
++ saved_ptr = parse;
++ /*
++ * Check to see whether the request overlaps more
++ * than one entry in the list
++ */
++ list_for_each_entry_continue(parse, &memtype_list, nd) {
++ if (end <= parse->start) {
++ break;
++ }
++
++ if (actual_type != parse->type) {
++ printk(
++ KERN_INFO "%s:%d conflicting memory types %Lx-%Lx %s<->%s\n",
++ current->comm, current->pid,
++ start, end,
++ cattr_name(actual_type),
++ cattr_name(parse->type));
++ err = -EBUSY;
++ break;
++ }
++ }
++
++ if (err) {
++ break;
++ }
++
++ printk(KERN_INFO "Overlap at 0x%Lx-0x%Lx\n",
++ saved_ptr->start, saved_ptr->end);
++ /* No conflict. Go ahead and add this new entry */
++ list_add(&new_entry->nd, &saved_ptr->nd);
++ new_entry = NULL;
++ break;
++ }
++ }
++
++ if (err) {
++ printk(KERN_INFO
++ "reserve_memtype failed 0x%Lx-0x%Lx, track %s, req %s\n",
++ start, end, cattr_name(new_entry->type),
++ cattr_name(req_type));
++ kfree(new_entry);
++ spin_unlock(&memtype_lock);
++ return err;
++ }
++
++ if (new_entry) {
++ /* No conflict. Not yet added to the list. Add to the tail */
++ list_add_tail(&new_entry->nd, &memtype_list);
++ pr_debug("New Entry\n");
++ }
++
++ if (ret_type) {
++ pr_debug(
++ "reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s, ret %s\n",
++ start, end, cattr_name(actual_type),
++ cattr_name(req_type), cattr_name(*ret_type));
++ } else {
++ pr_debug(
++ "reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s\n",
++ start, end, cattr_name(actual_type),
++ cattr_name(req_type));
++ }
++
++ spin_unlock(&memtype_lock);
++ return err;
++}
++
++int free_memtype(u64 start, u64 end)
++{
++ struct memtype *ml;
++ int err = -EINVAL;
++
++ /* Only track when pat_wc_enabled */
++ if (!pat_wc_enabled) {
++ return 0;
++ }
++
++ /* Low ISA region is always mapped WB. No need to track */
++ if (start >= ISA_START_ADDRESS && end <= ISA_END_ADDRESS) {
++ return 0;
++ }
++
++ spin_lock(&memtype_lock);
++ list_for_each_entry(ml, &memtype_list, nd) {
++ if (ml->start == start && ml->end == end) {
++ list_del(&ml->nd);
++ kfree(ml);
++ err = 0;
++ break;
++ }
++ }
++ spin_unlock(&memtype_lock);
++
++ if (err) {
++ printk(KERN_INFO "%s:%d freeing invalid memtype %Lx-%Lx\n",
++ current->comm, current->pid, start, end);
++ }
++
++ pr_debug("free_memtype request 0x%Lx-0x%Lx\n", start, end);
++ return err;
++}
++
++
++/*
++ * /dev/mem mmap interface. The memtype used for mapping varies:
++ * - Use UC for mappings with O_SYNC flag
++ * - Without O_SYNC flag, if there is any conflict in reserve_memtype,
++ * inherit the memtype from existing mapping.
++ * - Else use UC_MINUS memtype (for backward compatibility with existing
++ * X drivers.
++ */
++pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
++ unsigned long size, pgprot_t vma_prot)
++{
++ return vma_prot;
++}
++
++int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
++ unsigned long size, pgprot_t *vma_prot)
++{
++ u64 offset = ((u64) pfn) << PAGE_SHIFT;
++ unsigned long flags = _PAGE_CACHE_UC_MINUS;
++ unsigned long ret_flags;
++ int retval;
++
++ if (file->f_flags & O_SYNC) {
++ flags = _PAGE_CACHE_UC;
++ }
++
++#ifdef CONFIG_X86_32
++ /*
++ * On the PPro and successors, the MTRRs are used to set
++ * memory types for physical addresses outside main memory,
++ * so blindly setting UC or PWT on those pages is wrong.
++ * For Pentiums and earlier, the surround logic should disable
++ * caching for the high addresses through the KEN pin, but
++ * we maintain the tradition of paranoia in this code.
++ */
++ if (!pat_wc_enabled &&
++ ! ( test_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability) ||
++ test_bit(X86_FEATURE_K6_MTRR, boot_cpu_data.x86_capability) ||
++ test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) ||
++ test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability)) &&
++ (pfn << PAGE_SHIFT) >= __pa(high_memory)) {
++ flags = _PAGE_CACHE_UC;
++ }
++#endif
++
++ /*
++ * With O_SYNC, we can only take UC mapping. Fail if we cannot.
++ * Without O_SYNC, we want to get
++ * - WB for WB-able memory and no other conflicting mappings
++ * - UC_MINUS for non-WB-able memory with no other conflicting mappings
++ * - Inherit from confliting mappings otherwise
++ */
++ if (flags != _PAGE_CACHE_UC_MINUS) {
++ retval = reserve_memtype(offset, offset + size, flags, NULL);
++ } else {
++ retval = reserve_memtype(offset, offset + size, -1, &ret_flags);
++ }
++
++ if (retval < 0)
++ return 0;
++
++ flags = ret_flags;
++
++ if (pfn <= max_pfn_mapped &&
++ ioremap_change_attr((unsigned long)__va(offset), size, flags) < 0) {
++ free_memtype(offset, offset + size);
++ printk(KERN_INFO
++ "%s:%d /dev/mem ioremap_change_attr failed %s for %Lx-%Lx\n",
++ current->comm, current->pid,
++ cattr_name(flags),
++ offset, offset + size);
++ return 0;
++ }
++
++ *vma_prot = __pgprot((pgprot_val(*vma_prot) & ~_PAGE_CACHE_MASK) |
++ flags);
++ return 1;
++}
++
++void map_devmem(unsigned long pfn, unsigned long size, pgprot_t vma_prot)
++{
++ u64 addr = (u64)pfn << PAGE_SHIFT;
++ unsigned long flags;
++ unsigned long want_flags = (pgprot_val(vma_prot) & _PAGE_CACHE_MASK);
++
++ reserve_memtype(addr, addr + size, want_flags, &flags);
++ if (flags != want_flags) {
++ printk(KERN_INFO
++ "%s:%d /dev/mem expected mapping type %s for %Lx-%Lx, got %s\n",
++ current->comm, current->pid,
++ cattr_name(want_flags),
++ addr, addr + size,
++ cattr_name(flags));
++ }
++}
++
++void unmap_devmem(unsigned long pfn, unsigned long size, pgprot_t vma_prot)
++{
++ u64 addr = (u64)pfn << PAGE_SHIFT;
++
++ free_memtype(addr, addr + size);
++}
++
+diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
+new file mode 100644
+index 0000000..5015976
+--- /dev/null
++++ b/arch/x86/mm/pgtable.c
+@@ -0,0 +1,276 @@
++#include <linux/mm.h>
++#include <asm/pgalloc.h>
++#include <asm/pgtable.h>
++#include <asm/tlb.h>
++
++pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
++{
++ return (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
++}
++
++pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
++{
++ struct page *pte;
++
++#ifdef CONFIG_HIGHPTE
++ pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT|__GFP_ZERO, 0);
++#else
++ pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
++#endif
++ if (pte)
++ pgtable_page_ctor(pte);
++ return pte;
++}
++
++void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
++{
++ pgtable_page_dtor(pte);
++ paravirt_release_pte(page_to_pfn(pte));
++ tlb_remove_page(tlb, pte);
++}
++
++#if PAGETABLE_LEVELS > 2
++void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
++{
++ paravirt_release_pmd(__pa(pmd) >> PAGE_SHIFT);
++ tlb_remove_page(tlb, virt_to_page(pmd));
++}
++
++#if PAGETABLE_LEVELS > 3
++void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud)
++{
++ paravirt_release_pud(__pa(pud) >> PAGE_SHIFT);
++ tlb_remove_page(tlb, virt_to_page(pud));
++}
++#endif /* PAGETABLE_LEVELS > 3 */
++#endif /* PAGETABLE_LEVELS > 2 */
++
++static inline void pgd_list_add(pgd_t *pgd)
++{
++ struct page *page = virt_to_page(pgd);
++
++ list_add(&page->lru, &pgd_list);
++}
++
++static inline void pgd_list_del(pgd_t *pgd)
++{
++ struct page *page = virt_to_page(pgd);
++
++ list_del(&page->lru);
++}
++
++#define UNSHARED_PTRS_PER_PGD \
++ (SHARED_KERNEL_PMD ? KERNEL_PGD_BOUNDARY : PTRS_PER_PGD)
++
++static void pgd_ctor(void *p)
++{
++ pgd_t *pgd = p;
++ unsigned long flags;
++
++ /* Clear usermode parts of PGD */
++ memset(pgd, 0, KERNEL_PGD_BOUNDARY*sizeof(pgd_t));
++
++ spin_lock_irqsave(&pgd_lock, flags);
++
++ /* If the pgd points to a shared pagetable level (either the
++ ptes in non-PAE, or shared PMD in PAE), then just copy the
++ references from swapper_pg_dir. */
++ if (PAGETABLE_LEVELS == 2 ||
++ (PAGETABLE_LEVELS == 3 && SHARED_KERNEL_PMD) ||
++ PAGETABLE_LEVELS == 4) {
++ clone_pgd_range(pgd + KERNEL_PGD_BOUNDARY,
++ swapper_pg_dir + KERNEL_PGD_BOUNDARY,
++ KERNEL_PGD_PTRS);
++ paravirt_alloc_pmd_clone(__pa(pgd) >> PAGE_SHIFT,
++ __pa(swapper_pg_dir) >> PAGE_SHIFT,
++ KERNEL_PGD_BOUNDARY,
++ KERNEL_PGD_PTRS);
++ }
++
++ /* list required to sync kernel mapping updates */
++ if (!SHARED_KERNEL_PMD)
++ pgd_list_add(pgd);
++
++ spin_unlock_irqrestore(&pgd_lock, flags);
++}
++
++static void pgd_dtor(void *pgd)
++{
++ unsigned long flags; /* can be called from interrupt context */
++
++ if (SHARED_KERNEL_PMD)
++ return;
++
++ spin_lock_irqsave(&pgd_lock, flags);
++ pgd_list_del(pgd);
++ spin_unlock_irqrestore(&pgd_lock, flags);
++}
++
++/*
++ * List of all pgd's needed for non-PAE so it can invalidate entries
++ * in both cached and uncached pgd's; not needed for PAE since the
++ * kernel pmd is shared. If PAE were not to share the pmd a similar
++ * tactic would be needed. This is essentially codepath-based locking
++ * against pageattr.c; it is the unique case in which a valid change
++ * of kernel pagetables can't be lazily synchronized by vmalloc faults.
++ * vmalloc faults work because attached pagetables are never freed.
++ * -- wli
++ */
++
++#ifdef CONFIG_X86_PAE
++/*
++ * Mop up any pmd pages which may still be attached to the pgd.
++ * Normally they will be freed by munmap/exit_mmap, but any pmd we
++ * preallocate which never got a corresponding vma will need to be
++ * freed manually.
++ */
++static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
++{
++ int i;
++
++ for(i = 0; i < UNSHARED_PTRS_PER_PGD; i++) {
++ pgd_t pgd = pgdp[i];
++
++ if (pgd_val(pgd) != 0) {
++ pmd_t *pmd = (pmd_t *)pgd_page_vaddr(pgd);
++
++ pgdp[i] = native_make_pgd(0);
++
++ paravirt_release_pmd(pgd_val(pgd) >> PAGE_SHIFT);
++ pmd_free(mm, pmd);
++ }
++ }
++}
++
++/*
++ * In PAE mode, we need to do a cr3 reload (=tlb flush) when
++ * updating the top-level pagetable entries to guarantee the
++ * processor notices the update. Since this is expensive, and
++ * all 4 top-level entries are used almost immediately in a
++ * new process's life, we just pre-populate them here.
++ *
++ * Also, if we're in a paravirt environment where the kernel pmd is
++ * not shared between pagetables (!SHARED_KERNEL_PMDS), we allocate
++ * and initialize the kernel pmds here.
++ */
++static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
++{
++ pud_t *pud;
++ unsigned long addr;
++ int i;
++
++ pud = pud_offset(pgd, 0);
++ for (addr = i = 0; i < UNSHARED_PTRS_PER_PGD;
++ i++, pud++, addr += PUD_SIZE) {
++ pmd_t *pmd = pmd_alloc_one(mm, addr);
++
++ if (!pmd) {
++ pgd_mop_up_pmds(mm, pgd);
++ return 0;
++ }
++
++ if (i >= KERNEL_PGD_BOUNDARY)
++ memcpy(pmd, (pmd_t *)pgd_page_vaddr(swapper_pg_dir[i]),
++ sizeof(pmd_t) * PTRS_PER_PMD);
++
++ pud_populate(mm, pud, pmd);
++ }
++
++ return 1;
++}
++
++void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd)
++{
++ paravirt_alloc_pmd(mm, __pa(pmd) >> PAGE_SHIFT);
++
++ /* Note: almost everything apart from _PAGE_PRESENT is
++ reserved at the pmd (PDPT) level. */
++ set_pud(pudp, __pud(__pa(pmd) | _PAGE_PRESENT));
++
++ /*
++ * According to Intel App note "TLBs, Paging-Structure Caches,
++ * and Their Invalidation", April 2007, document 317080-001,
++ * section 8.1: in PAE mode we explicitly have to flush the
++ * TLB via cr3 if the top-level pgd is changed...
++ */
++ if (mm == current->active_mm)
++ write_cr3(read_cr3());
++}
++#else /* !CONFIG_X86_PAE */
++/* No need to prepopulate any pagetable entries in non-PAE modes. */
++static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
++{
++ return 1;
++}
++
++static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgd)
++{
++}
++#endif /* CONFIG_X86_PAE */
++
++pgd_t *pgd_alloc(struct mm_struct *mm)
++{
++ pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
++
++ /* so that alloc_pmd can use it */
++ mm->pgd = pgd;
++ if (pgd)
++ pgd_ctor(pgd);
++
++ if (pgd && !pgd_prepopulate_pmd(mm, pgd)) {
++ pgd_dtor(pgd);
++ free_page((unsigned long)pgd);
++ pgd = NULL;
++ }
++
++ return pgd;
++}
++
++void pgd_free(struct mm_struct *mm, pgd_t *pgd)
++{
++ pgd_mop_up_pmds(mm, pgd);
++ pgd_dtor(pgd);
++ free_page((unsigned long)pgd);
++}
++
++int ptep_set_access_flags(struct vm_area_struct *vma,
++ unsigned long address, pte_t *ptep,
++ pte_t entry, int dirty)
++{
++ int changed = !pte_same(*ptep, entry);
++
++ if (changed && dirty) {
++ *ptep = entry;
++ pte_update_defer(vma->vm_mm, address, ptep);
++ flush_tlb_page(vma, address);
++ }
++
++ return changed;
++}
++
++int ptep_test_and_clear_young(struct vm_area_struct *vma,
++ unsigned long addr, pte_t *ptep)
++{
++ int ret = 0;
++
++ if (pte_young(*ptep))
++ ret = test_and_clear_bit(_PAGE_BIT_ACCESSED,
++ &ptep->pte);
++
++ if (ret)
++ pte_update(vma->vm_mm, addr, ptep);
++
++ return ret;
++}
++
++int ptep_clear_flush_young(struct vm_area_struct *vma,
++ unsigned long address, pte_t *ptep)
++{
++ int young;
++
++ young = ptep_test_and_clear_young(vma, address, ptep);
++ if (young)
++ flush_tlb_page(vma, address);
++
++ return young;
++}
+diff --git a/arch/x86/mm/pgtable_32.c b/arch/x86/mm/pgtable_32.c
+index 2f9e9af..9ee007b 100644
+--- a/arch/x86/mm/pgtable_32.c
++++ b/arch/x86/mm/pgtable_32.c
+@@ -1,7 +1,3 @@
+-/*
+- * linux/arch/i386/mm/pgtable.c
+- */
+-
+ #include <linux/sched.h>
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+@@ -36,7 +32,6 @@ void show_mem(void)
+
+ printk(KERN_INFO "Mem-info:\n");
+ show_free_areas();
+- printk(KERN_INFO "Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+ for_each_online_pgdat(pgdat) {
+ pgdat_resize_lock(pgdat, &flags);
+ for (i = 0; i < pgdat->node_spanned_pages; ++i) {
+@@ -178,206 +173,9 @@ void reserve_top_address(unsigned long reserve)
+ __VMALLOC_RESERVE += reserve;
+ }
+
+-pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+-{
+- return (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+-}
+-
+-pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
++int pmd_bad(pmd_t pmd)
+ {
+- struct page *pte;
++ WARN_ON_ONCE(pmd_bad_v1(pmd) != pmd_bad_v2(pmd));
+
+-#ifdef CONFIG_HIGHPTE
+- pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT|__GFP_ZERO, 0);
+-#else
+- pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
+-#endif
+- if (pte)
+- pgtable_page_ctor(pte);
+- return pte;
++ return pmd_bad_v1(pmd);
+ }
+-
+-/*
+- * List of all pgd's needed for non-PAE so it can invalidate entries
+- * in both cached and uncached pgd's; not needed for PAE since the
+- * kernel pmd is shared. If PAE were not to share the pmd a similar
+- * tactic would be needed. This is essentially codepath-based locking
+- * against pageattr.c; it is the unique case in which a valid change
+- * of kernel pagetables can't be lazily synchronized by vmalloc faults.
+- * vmalloc faults work because attached pagetables are never freed.
+- * -- wli
+- */
+-static inline void pgd_list_add(pgd_t *pgd)
+-{
+- struct page *page = virt_to_page(pgd);
+-
+- list_add(&page->lru, &pgd_list);
+-}
+-
+-static inline void pgd_list_del(pgd_t *pgd)
+-{
+- struct page *page = virt_to_page(pgd);
+-
+- list_del(&page->lru);
+-}
+-
+-#define UNSHARED_PTRS_PER_PGD \
+- (SHARED_KERNEL_PMD ? USER_PTRS_PER_PGD : PTRS_PER_PGD)
+-
+-static void pgd_ctor(void *p)
+-{
+- pgd_t *pgd = p;
+- unsigned long flags;
+-
+- /* Clear usermode parts of PGD */
+- memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
+-
+- spin_lock_irqsave(&pgd_lock, flags);
+-
+- /* If the pgd points to a shared pagetable level (either the
+- ptes in non-PAE, or shared PMD in PAE), then just copy the
+- references from swapper_pg_dir. */
+- if (PAGETABLE_LEVELS == 2 ||
+- (PAGETABLE_LEVELS == 3 && SHARED_KERNEL_PMD)) {
+- clone_pgd_range(pgd + USER_PTRS_PER_PGD,
+- swapper_pg_dir + USER_PTRS_PER_PGD,
+- KERNEL_PGD_PTRS);
+- paravirt_alloc_pd_clone(__pa(pgd) >> PAGE_SHIFT,
+- __pa(swapper_pg_dir) >> PAGE_SHIFT,
+- USER_PTRS_PER_PGD,
+- KERNEL_PGD_PTRS);
+- }
+-
+- /* list required to sync kernel mapping updates */
+- if (!SHARED_KERNEL_PMD)
+- pgd_list_add(pgd);
+-
+- spin_unlock_irqrestore(&pgd_lock, flags);
+-}
+-
+-static void pgd_dtor(void *pgd)
+-{
+- unsigned long flags; /* can be called from interrupt context */
+-
+- if (SHARED_KERNEL_PMD)
+- return;
+-
+- spin_lock_irqsave(&pgd_lock, flags);
+- pgd_list_del(pgd);
+- spin_unlock_irqrestore(&pgd_lock, flags);
+-}
+-
+-#ifdef CONFIG_X86_PAE
+-/*
+- * Mop up any pmd pages which may still be attached to the pgd.
+- * Normally they will be freed by munmap/exit_mmap, but any pmd we
+- * preallocate which never got a corresponding vma will need to be
+- * freed manually.
+- */
+-static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
+-{
+- int i;
+-
+- for(i = 0; i < UNSHARED_PTRS_PER_PGD; i++) {
+- pgd_t pgd = pgdp[i];
+-
+- if (pgd_val(pgd) != 0) {
+- pmd_t *pmd = (pmd_t *)pgd_page_vaddr(pgd);
+-
+- pgdp[i] = native_make_pgd(0);
+-
+- paravirt_release_pd(pgd_val(pgd) >> PAGE_SHIFT);
+- pmd_free(mm, pmd);
+- }
+- }
+-}
+-
+-/*
+- * In PAE mode, we need to do a cr3 reload (=tlb flush) when
+- * updating the top-level pagetable entries to guarantee the
+- * processor notices the update. Since this is expensive, and
+- * all 4 top-level entries are used almost immediately in a
+- * new process's life, we just pre-populate them here.
+- *
+- * Also, if we're in a paravirt environment where the kernel pmd is
+- * not shared between pagetables (!SHARED_KERNEL_PMDS), we allocate
+- * and initialize the kernel pmds here.
+- */
+-static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
+-{
+- pud_t *pud;
+- unsigned long addr;
+- int i;
+-
+- pud = pud_offset(pgd, 0);
+- for (addr = i = 0; i < UNSHARED_PTRS_PER_PGD;
+- i++, pud++, addr += PUD_SIZE) {
+- pmd_t *pmd = pmd_alloc_one(mm, addr);
+-
+- if (!pmd) {
+- pgd_mop_up_pmds(mm, pgd);
+- return 0;
+- }
+-
+- if (i >= USER_PTRS_PER_PGD)
+- memcpy(pmd, (pmd_t *)pgd_page_vaddr(swapper_pg_dir[i]),
+- sizeof(pmd_t) * PTRS_PER_PMD);
+-
+- pud_populate(mm, pud, pmd);
+- }
+-
+- return 1;
+-}
+-#else /* !CONFIG_X86_PAE */
+-/* No need to prepopulate any pagetable entries in non-PAE modes. */
+-static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
+-{
+- return 1;
+-}
+-
+-static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
+-{
+-}
+-#endif /* CONFIG_X86_PAE */
+-
+-pgd_t *pgd_alloc(struct mm_struct *mm)
+-{
+- pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
+-
+- /* so that alloc_pd can use it */
+- mm->pgd = pgd;
+- if (pgd)
+- pgd_ctor(pgd);
+-
+- if (pgd && !pgd_prepopulate_pmd(mm, pgd)) {
+- pgd_dtor(pgd);
+- free_page((unsigned long)pgd);
+- pgd = NULL;
+- }
+-
+- return pgd;
+-}
+-
+-void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+-{
+- pgd_mop_up_pmds(mm, pgd);
+- pgd_dtor(pgd);
+- free_page((unsigned long)pgd);
+-}
+-
+-void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
+-{
+- pgtable_page_dtor(pte);
+- paravirt_release_pt(page_to_pfn(pte));
+- tlb_remove_page(tlb, pte);
+-}
+-
+-#ifdef CONFIG_X86_PAE
+-
+-void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
+-{
+- paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT);
+- tlb_remove_page(tlb, virt_to_page(pmd));
+-}
+-
+-#endif
+diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c
+index 845001c..3890234 100644
+--- a/arch/x86/mm/srat_64.c
++++ b/arch/x86/mm/srat_64.c
+@@ -20,6 +20,7 @@
+ #include <asm/proto.h>
+ #include <asm/numa.h>
+ #include <asm/e820.h>
++#include <asm/genapic.h>
+
+ int acpi_numa __initdata;
+
+@@ -31,6 +32,10 @@ static struct bootnode nodes_add[MAX_NUMNODES];
+ static int found_add_area __initdata;
+ int hotadd_percent __initdata = 0;
+
++static int num_node_memblks __initdata;
++static struct bootnode node_memblk_range[NR_NODE_MEMBLKS] __initdata;
++static int memblk_nodeid[NR_NODE_MEMBLKS] __initdata;
++
+ /* Too small nodes confuse the VM badly. Usually they result
+ from BIOS bugs. */
+ #define NODE_MIN_SIZE (4*1024*1024)
+@@ -40,17 +45,17 @@ static __init int setup_node(int pxm)
+ return acpi_map_pxm_to_node(pxm);
+ }
+
+-static __init int conflicting_nodes(unsigned long start, unsigned long end)
++static __init int conflicting_memblks(unsigned long start, unsigned long end)
+ {
+ int i;
+- for_each_node_mask(i, nodes_parsed) {
+- struct bootnode *nd = &nodes[i];
++ for (i = 0; i < num_node_memblks; i++) {
++ struct bootnode *nd = &node_memblk_range[i];
+ if (nd->start == nd->end)
+ continue;
+ if (nd->end > start && nd->start < end)
+- return i;
++ return memblk_nodeid[i];
+ if (nd->end == end && nd->start == start)
+- return i;
++ return memblk_nodeid[i];
+ }
+ return -1;
+ }
+@@ -132,7 +137,6 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
+ int pxm, node;
+ int apic_id;
+
+- apic_id = pa->apic_id;
+ if (srat_disabled())
+ return;
+ if (pa->header.length != sizeof(struct acpi_srat_cpu_affinity)) {
+@@ -148,13 +152,18 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
+ bad_srat();
+ return;
+ }
++
++ if (is_uv_system())
++ apic_id = (pa->apic_id << 8) | pa->local_sapic_eid;
++ else
++ apic_id = pa->apic_id;
+ apicid_to_node[apic_id] = node;
+ acpi_numa = 1;
+ printk(KERN_INFO "SRAT: PXM %u -> APIC %u -> Node %u\n",
+ pxm, apic_id, node);
+ }
+
+-int update_end_of_memory(unsigned long end) {return -1;}
++static int update_end_of_memory(unsigned long end) {return -1;}
+ static int hotadd_enough_memory(struct bootnode *nd) {return 1;}
+ #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
+ static inline int save_add_info(void) {return 1;}
+@@ -253,7 +262,7 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
+ bad_srat();
+ return;
+ }
+- i = conflicting_nodes(start, end);
++ i = conflicting_memblks(start, end);
+ if (i == node) {
+ printk(KERN_WARNING
+ "SRAT: Warning: PXM %d (%lx-%lx) overlaps with itself (%Lx-%Lx)\n",
+@@ -278,10 +287,10 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
+ nd->end = end;
+ }
+
+- printk(KERN_INFO "SRAT: Node %u PXM %u %Lx-%Lx\n", node, pxm,
+- nd->start, nd->end);
+- e820_register_active_regions(node, nd->start >> PAGE_SHIFT,
+- nd->end >> PAGE_SHIFT);
++ printk(KERN_INFO "SRAT: Node %u PXM %u %lx-%lx\n", node, pxm,
++ start, end);
++ e820_register_active_regions(node, start >> PAGE_SHIFT,
++ end >> PAGE_SHIFT);
+ push_node_boundaries(node, nd->start >> PAGE_SHIFT,
+ nd->end >> PAGE_SHIFT);
+
+@@ -293,6 +302,11 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
+ if ((nd->start | nd->end) == 0)
+ node_clear(node, nodes_parsed);
+ }
++
++ node_memblk_range[num_node_memblks].start = start;
++ node_memblk_range[num_node_memblks].end = end;
++ memblk_nodeid[num_node_memblks] = node;
++ num_node_memblks++;
+ }
+
+ /* Sanity check to catch more bad SRATs (they are amazingly common).
+@@ -363,7 +377,8 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
+ return -1;
+ }
+
+- memnode_shift = compute_hash_shift(nodes, MAX_NUMNODES);
++ memnode_shift = compute_hash_shift(node_memblk_range, num_node_memblks,
++ memblk_nodeid);
+ if (memnode_shift < 0) {
+ printk(KERN_ERR
+ "SRAT: No NUMA node hash function found. Contact maintainer\n");
+diff --git a/arch/x86/oprofile/init.c b/arch/x86/oprofile/init.c
+index 5341d48..cdfe4c5 100644
+--- a/arch/x86/oprofile/init.c
++++ b/arch/x86/oprofile/init.c
+@@ -10,18 +10,19 @@
+ #include <linux/oprofile.h>
+ #include <linux/init.h>
+ #include <linux/errno.h>
+-
+-/* We support CPUs that have performance counters like the Pentium Pro
++
++/*
++ * We support CPUs that have performance counters like the Pentium Pro
+ * with the NMI mode driver.
+ */
+-
+-extern int op_nmi_init(struct oprofile_operations * ops);
+-extern int op_nmi_timer_init(struct oprofile_operations * ops);
++
++extern int op_nmi_init(struct oprofile_operations *ops);
++extern int op_nmi_timer_init(struct oprofile_operations *ops);
+ extern void op_nmi_exit(void);
+ extern void x86_backtrace(struct pt_regs * const regs, unsigned int depth);
+
+
+-int __init oprofile_arch_init(struct oprofile_operations * ops)
++int __init oprofile_arch_init(struct oprofile_operations *ops)
+ {
+ int ret;
+
+diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c
+index 1f11cf0..cc48d3f 100644
+--- a/arch/x86/oprofile/nmi_int.c
++++ b/arch/x86/oprofile/nmi_int.c
+@@ -23,8 +23,8 @@
+ #include "op_x86_model.h"
+
+ static struct op_x86_model_spec const *model;
+-static struct op_msrs cpu_msrs[NR_CPUS];
+-static unsigned long saved_lvtpc[NR_CPUS];
++static DEFINE_PER_CPU(struct op_msrs, cpu_msrs);
++static DEFINE_PER_CPU(unsigned long, saved_lvtpc);
+
+ static int nmi_start(void);
+ static void nmi_stop(void);
+@@ -89,7 +89,7 @@ static int profile_exceptions_notify(struct notifier_block *self,
+
+ switch (val) {
+ case DIE_NMI:
+- if (model->check_ctrs(args->regs, &cpu_msrs[cpu]))
++ if (model->check_ctrs(args->regs, &per_cpu(cpu_msrs, cpu)))
+ ret = NOTIFY_STOP;
+ break;
+ default:
+@@ -126,7 +126,7 @@ static void nmi_cpu_save_registers(struct op_msrs *msrs)
+ static void nmi_save_registers(void *dummy)
+ {
+ int cpu = smp_processor_id();
+- struct op_msrs *msrs = &cpu_msrs[cpu];
++ struct op_msrs *msrs = &per_cpu(cpu_msrs, cpu);
+ nmi_cpu_save_registers(msrs);
+ }
+
+@@ -134,10 +134,10 @@ static void free_msrs(void)
+ {
+ int i;
+ for_each_possible_cpu(i) {
+- kfree(cpu_msrs[i].counters);
+- cpu_msrs[i].counters = NULL;
+- kfree(cpu_msrs[i].controls);
+- cpu_msrs[i].controls = NULL;
++ kfree(per_cpu(cpu_msrs, i).counters);
++ per_cpu(cpu_msrs, i).counters = NULL;
++ kfree(per_cpu(cpu_msrs, i).controls);
++ per_cpu(cpu_msrs, i).controls = NULL;
+ }
+ }
+
+@@ -149,13 +149,15 @@ static int allocate_msrs(void)
+
+ int i;
+ for_each_possible_cpu(i) {
+- cpu_msrs[i].counters = kmalloc(counters_size, GFP_KERNEL);
+- if (!cpu_msrs[i].counters) {
++ per_cpu(cpu_msrs, i).counters = kmalloc(counters_size,
++ GFP_KERNEL);
++ if (!per_cpu(cpu_msrs, i).counters) {
+ success = 0;
+ break;
+ }
+- cpu_msrs[i].controls = kmalloc(controls_size, GFP_KERNEL);
+- if (!cpu_msrs[i].controls) {
++ per_cpu(cpu_msrs, i).controls = kmalloc(controls_size,
++ GFP_KERNEL);
++ if (!per_cpu(cpu_msrs, i).controls) {
+ success = 0;
+ break;
+ }
+@@ -170,11 +172,11 @@ static int allocate_msrs(void)
+ static void nmi_cpu_setup(void *dummy)
+ {
+ int cpu = smp_processor_id();
+- struct op_msrs *msrs = &cpu_msrs[cpu];
++ struct op_msrs *msrs = &per_cpu(cpu_msrs, cpu);
+ spin_lock(&oprofilefs_lock);
+ model->setup_ctrs(msrs);
+ spin_unlock(&oprofilefs_lock);
+- saved_lvtpc[cpu] = apic_read(APIC_LVTPC);
++ per_cpu(saved_lvtpc, cpu) = apic_read(APIC_LVTPC);
+ apic_write(APIC_LVTPC, APIC_DM_NMI);
+ }
+
+@@ -203,13 +205,15 @@ static int nmi_setup(void)
+ */
+
+ /* Assume saved/restored counters are the same on all CPUs */
+- model->fill_in_addresses(&cpu_msrs[0]);
++ model->fill_in_addresses(&per_cpu(cpu_msrs, 0));
+ for_each_possible_cpu(cpu) {
+ if (cpu != 0) {
+- memcpy(cpu_msrs[cpu].counters, cpu_msrs[0].counters,
++ memcpy(per_cpu(cpu_msrs, cpu).counters,
++ per_cpu(cpu_msrs, 0).counters,
+ sizeof(struct op_msr) * model->num_counters);
+
+- memcpy(cpu_msrs[cpu].controls, cpu_msrs[0].controls,
++ memcpy(per_cpu(cpu_msrs, cpu).controls,
++ per_cpu(cpu_msrs, 0).controls,
+ sizeof(struct op_msr) * model->num_controls);
+ }
+
+@@ -249,7 +253,7 @@ static void nmi_cpu_shutdown(void *dummy)
+ {
+ unsigned int v;
+ int cpu = smp_processor_id();
+- struct op_msrs *msrs = &cpu_msrs[cpu];
++ struct op_msrs *msrs = &__get_cpu_var(cpu_msrs);
+
+ /* restoring APIC_LVTPC can trigger an apic error because the delivery
+ * mode and vector nr combination can be illegal. That's by design: on
+@@ -258,23 +262,24 @@ static void nmi_cpu_shutdown(void *dummy)
+ */
+ v = apic_read(APIC_LVTERR);
+ apic_write(APIC_LVTERR, v | APIC_LVT_MASKED);
+- apic_write(APIC_LVTPC, saved_lvtpc[cpu]);
++ apic_write(APIC_LVTPC, per_cpu(saved_lvtpc, cpu));
+ apic_write(APIC_LVTERR, v);
+ nmi_restore_registers(msrs);
+ }
+
+ static void nmi_shutdown(void)
+ {
++ struct op_msrs *msrs = &__get_cpu_var(cpu_msrs);
+ nmi_enabled = 0;
+ on_each_cpu(nmi_cpu_shutdown, NULL, 0, 1);
+ unregister_die_notifier(&profile_exceptions_nb);
+- model->shutdown(cpu_msrs);
++ model->shutdown(msrs);
+ free_msrs();
+ }
+
+ static void nmi_cpu_start(void *dummy)
+ {
+- struct op_msrs const *msrs = &cpu_msrs[smp_processor_id()];
++ struct op_msrs const *msrs = &__get_cpu_var(cpu_msrs);
+ model->start(msrs);
+ }
+
+@@ -286,7 +291,7 @@ static int nmi_start(void)
+
+ static void nmi_cpu_stop(void *dummy)
+ {
+- struct op_msrs const *msrs = &cpu_msrs[smp_processor_id()];
++ struct op_msrs const *msrs = &__get_cpu_var(cpu_msrs);
+ model->stop(msrs);
+ }
+
+diff --git a/arch/x86/oprofile/nmi_timer_int.c b/arch/x86/oprofile/nmi_timer_int.c
+index 1418e36..e3ecb71 100644
+--- a/arch/x86/oprofile/nmi_timer_int.c
++++ b/arch/x86/oprofile/nmi_timer_int.c
+@@ -17,14 +17,14 @@
+ #include <asm/nmi.h>
+ #include <asm/apic.h>
+ #include <asm/ptrace.h>
+-
++
+ static int profile_timer_exceptions_notify(struct notifier_block *self,
+ unsigned long val, void *data)
+ {
+ struct die_args *args = (struct die_args *)data;
+ int ret = NOTIFY_DONE;
+
+- switch(val) {
++ switch (val) {
+ case DIE_NMI:
+ oprofile_add_sample(args->regs, 0);
+ ret = NOTIFY_STOP;
+@@ -56,7 +56,7 @@ static void timer_stop(void)
+ }
+
+
+-int __init op_nmi_timer_init(struct oprofile_operations * ops)
++int __init op_nmi_timer_init(struct oprofile_operations *ops)
+ {
+ if ((nmi_watchdog != NMI_IO_APIC) || (atomic_read(&nmi_active) <= 0))
+ return -ENODEV;
+diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c
+index c3ee433..3d53487 100644
+--- a/arch/x86/oprofile/op_model_athlon.c
++++ b/arch/x86/oprofile/op_model_athlon.c
+@@ -1,4 +1,4 @@
+-/**
++/*
+ * @file op_model_athlon.h
+ * athlon / K7 / K8 / Family 10h model-specific MSR operations
+ *
+@@ -14,28 +14,28 @@
+ #include <asm/ptrace.h>
+ #include <asm/msr.h>
+ #include <asm/nmi.h>
+-
++
+ #include "op_x86_model.h"
+ #include "op_counter.h"
+
+ #define NUM_COUNTERS 4
+ #define NUM_CONTROLS 4
+
+-#define CTR_IS_RESERVED(msrs,c) (msrs->counters[(c)].addr ? 1 : 0)
+-#define CTR_READ(l,h,msrs,c) do {rdmsr(msrs->counters[(c)].addr, (l), (h));} while (0)
+-#define CTR_WRITE(l,msrs,c) do {wrmsr(msrs->counters[(c)].addr, -(unsigned int)(l), -1);} while (0)
++#define CTR_IS_RESERVED(msrs, c) (msrs->counters[(c)].addr ? 1 : 0)
++#define CTR_READ(l, h, msrs, c) do {rdmsr(msrs->counters[(c)].addr, (l), (h)); } while (0)
++#define CTR_WRITE(l, msrs, c) do {wrmsr(msrs->counters[(c)].addr, -(unsigned int)(l), -1); } while (0)
+ #define CTR_OVERFLOWED(n) (!((n) & (1U<<31)))
+
+-#define CTRL_IS_RESERVED(msrs,c) (msrs->controls[(c)].addr ? 1 : 0)
+-#define CTRL_READ(l,h,msrs,c) do {rdmsr(msrs->controls[(c)].addr, (l), (h));} while (0)
+-#define CTRL_WRITE(l,h,msrs,c) do {wrmsr(msrs->controls[(c)].addr, (l), (h));} while (0)
++#define CTRL_IS_RESERVED(msrs, c) (msrs->controls[(c)].addr ? 1 : 0)
++#define CTRL_READ(l, h, msrs, c) do {rdmsr(msrs->controls[(c)].addr, (l), (h)); } while (0)
++#define CTRL_WRITE(l, h, msrs, c) do {wrmsr(msrs->controls[(c)].addr, (l), (h)); } while (0)
+ #define CTRL_SET_ACTIVE(n) (n |= (1<<22))
+ #define CTRL_SET_INACTIVE(n) (n &= ~(1<<22))
+ #define CTRL_CLEAR_LO(x) (x &= (1<<21))
+ #define CTRL_CLEAR_HI(x) (x &= 0xfffffcf0)
+ #define CTRL_SET_ENABLE(val) (val |= 1<<20)
+-#define CTRL_SET_USR(val,u) (val |= ((u & 1) << 16))
+-#define CTRL_SET_KERN(val,k) (val |= ((k & 1) << 17))
++#define CTRL_SET_USR(val, u) (val |= ((u & 1) << 16))
++#define CTRL_SET_KERN(val, k) (val |= ((k & 1) << 17))
+ #define CTRL_SET_UM(val, m) (val |= (m << 8))
+ #define CTRL_SET_EVENT_LOW(val, e) (val |= (e & 0xff))
+ #define CTRL_SET_EVENT_HIGH(val, e) (val |= ((e >> 8) & 0xf))
+@@ -43,19 +43,19 @@
+ #define CTRL_SET_GUEST_ONLY(val, h) (val |= ((h & 1) << 8))
+
+ static unsigned long reset_value[NUM_COUNTERS];
+-
++
+ static void athlon_fill_in_addresses(struct op_msrs * const msrs)
+ {
+ int i;
+
+- for (i=0; i < NUM_COUNTERS; i++) {
++ for (i = 0; i < NUM_COUNTERS; i++) {
+ if (reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i))
+ msrs->counters[i].addr = MSR_K7_PERFCTR0 + i;
+ else
+ msrs->counters[i].addr = 0;
+ }
+
+- for (i=0; i < NUM_CONTROLS; i++) {
++ for (i = 0; i < NUM_CONTROLS; i++) {
+ if (reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i))
+ msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i;
+ else
+@@ -63,15 +63,15 @@ static void athlon_fill_in_addresses(struct op_msrs * const msrs)
+ }
+ }
+
+-
++
+ static void athlon_setup_ctrs(struct op_msrs const * const msrs)
+ {
+ unsigned int low, high;
+ int i;
+-
++
+ /* clear all counters */
+ for (i = 0 ; i < NUM_CONTROLS; ++i) {
+- if (unlikely(!CTRL_IS_RESERVED(msrs,i)))
++ if (unlikely(!CTRL_IS_RESERVED(msrs, i)))
+ continue;
+ CTRL_READ(low, high, msrs, i);
+ CTRL_CLEAR_LO(low);
+@@ -81,14 +81,14 @@ static void athlon_setup_ctrs(struct op_msrs const * const msrs)
+
+ /* avoid a false detection of ctr overflows in NMI handler */
+ for (i = 0; i < NUM_COUNTERS; ++i) {
+- if (unlikely(!CTR_IS_RESERVED(msrs,i)))
++ if (unlikely(!CTR_IS_RESERVED(msrs, i)))
+ continue;
+ CTR_WRITE(1, msrs, i);
+ }
+
+ /* enable active counters */
+ for (i = 0; i < NUM_COUNTERS; ++i) {
+- if ((counter_config[i].enabled) && (CTR_IS_RESERVED(msrs,i))) {
++ if ((counter_config[i].enabled) && (CTR_IS_RESERVED(msrs, i))) {
+ reset_value[i] = counter_config[i].count;
+
+ CTR_WRITE(counter_config[i].count, msrs, i);
+@@ -112,7 +112,7 @@ static void athlon_setup_ctrs(struct op_msrs const * const msrs)
+ }
+ }
+
+-
++
+ static int athlon_check_ctrs(struct pt_regs * const regs,
+ struct op_msrs const * const msrs)
+ {
+@@ -133,7 +133,7 @@ static int athlon_check_ctrs(struct pt_regs * const regs,
+ return 1;
+ }
+
+-
++
+ static void athlon_start(struct op_msrs const * const msrs)
+ {
+ unsigned int low, high;
+@@ -150,7 +150,7 @@ static void athlon_start(struct op_msrs const * const msrs)
+
+ static void athlon_stop(struct op_msrs const * const msrs)
+ {
+- unsigned int low,high;
++ unsigned int low, high;
+ int i;
+
+ /* Subtle: stop on all counters to avoid race with
+@@ -169,11 +169,11 @@ static void athlon_shutdown(struct op_msrs const * const msrs)
+ int i;
+
+ for (i = 0 ; i < NUM_COUNTERS ; ++i) {
+- if (CTR_IS_RESERVED(msrs,i))
++ if (CTR_IS_RESERVED(msrs, i))
+ release_perfctr_nmi(MSR_K7_PERFCTR0 + i);
+ }
+ for (i = 0 ; i < NUM_CONTROLS ; ++i) {
+- if (CTRL_IS_RESERVED(msrs,i))
++ if (CTRL_IS_RESERVED(msrs, i))
+ release_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
+ }
+ }
+diff --git a/arch/x86/oprofile/op_model_ppro.c b/arch/x86/oprofile/op_model_ppro.c
+index c554f52..eff431f 100644
+--- a/arch/x86/oprofile/op_model_ppro.c
++++ b/arch/x86/oprofile/op_model_ppro.c
+@@ -1,4 +1,4 @@
+-/**
++/*
+ * @file op_model_ppro.h
+ * pentium pro / P6 model-specific MSR operations
+ *
+@@ -15,45 +15,45 @@
+ #include <asm/msr.h>
+ #include <asm/apic.h>
+ #include <asm/nmi.h>
+-
++
+ #include "op_x86_model.h"
+ #include "op_counter.h"
+
+ #define NUM_COUNTERS 2
+ #define NUM_CONTROLS 2
+
+-#define CTR_IS_RESERVED(msrs,c) (msrs->counters[(c)].addr ? 1 : 0)
+-#define CTR_READ(l,h,msrs,c) do {rdmsr(msrs->counters[(c)].addr, (l), (h));} while (0)
+-#define CTR_32BIT_WRITE(l,msrs,c) \
+- do {wrmsr(msrs->counters[(c)].addr, -(u32)(l), 0);} while (0)
++#define CTR_IS_RESERVED(msrs, c) (msrs->counters[(c)].addr ? 1 : 0)
++#define CTR_READ(l, h, msrs, c) do {rdmsr(msrs->counters[(c)].addr, (l), (h)); } while (0)
++#define CTR_32BIT_WRITE(l, msrs, c) \
++ do {wrmsr(msrs->counters[(c)].addr, -(u32)(l), 0); } while (0)
+ #define CTR_OVERFLOWED(n) (!((n) & (1U<<31)))
+
+-#define CTRL_IS_RESERVED(msrs,c) (msrs->controls[(c)].addr ? 1 : 0)
+-#define CTRL_READ(l,h,msrs,c) do {rdmsr((msrs->controls[(c)].addr), (l), (h));} while (0)
+-#define CTRL_WRITE(l,h,msrs,c) do {wrmsr((msrs->controls[(c)].addr), (l), (h));} while (0)
++#define CTRL_IS_RESERVED(msrs, c) (msrs->controls[(c)].addr ? 1 : 0)
++#define CTRL_READ(l, h, msrs, c) do {rdmsr((msrs->controls[(c)].addr), (l), (h)); } while (0)
++#define CTRL_WRITE(l, h, msrs, c) do {wrmsr((msrs->controls[(c)].addr), (l), (h)); } while (0)
+ #define CTRL_SET_ACTIVE(n) (n |= (1<<22))
+ #define CTRL_SET_INACTIVE(n) (n &= ~(1<<22))
+ #define CTRL_CLEAR(x) (x &= (1<<21))
+ #define CTRL_SET_ENABLE(val) (val |= 1<<20)
+-#define CTRL_SET_USR(val,u) (val |= ((u & 1) << 16))
+-#define CTRL_SET_KERN(val,k) (val |= ((k & 1) << 17))
++#define CTRL_SET_USR(val, u) (val |= ((u & 1) << 16))
++#define CTRL_SET_KERN(val, k) (val |= ((k & 1) << 17))
+ #define CTRL_SET_UM(val, m) (val |= (m << 8))
+ #define CTRL_SET_EVENT(val, e) (val |= e)
+
+ static unsigned long reset_value[NUM_COUNTERS];
+-
++
+ static void ppro_fill_in_addresses(struct op_msrs * const msrs)
+ {
+ int i;
+
+- for (i=0; i < NUM_COUNTERS; i++) {
++ for (i = 0; i < NUM_COUNTERS; i++) {
+ if (reserve_perfctr_nmi(MSR_P6_PERFCTR0 + i))
+ msrs->counters[i].addr = MSR_P6_PERFCTR0 + i;
+ else
+ msrs->counters[i].addr = 0;
+ }
+-
+- for (i=0; i < NUM_CONTROLS; i++) {
++
++ for (i = 0; i < NUM_CONTROLS; i++) {
+ if (reserve_evntsel_nmi(MSR_P6_EVNTSEL0 + i))
+ msrs->controls[i].addr = MSR_P6_EVNTSEL0 + i;
+ else
+@@ -69,23 +69,23 @@ static void ppro_setup_ctrs(struct op_msrs const * const msrs)
+
+ /* clear all counters */
+ for (i = 0 ; i < NUM_CONTROLS; ++i) {
+- if (unlikely(!CTRL_IS_RESERVED(msrs,i)))
++ if (unlikely(!CTRL_IS_RESERVED(msrs, i)))
+ continue;
+ CTRL_READ(low, high, msrs, i);
+ CTRL_CLEAR(low);
+ CTRL_WRITE(low, high, msrs, i);
+ }
+-
++
+ /* avoid a false detection of ctr overflows in NMI handler */
+ for (i = 0; i < NUM_COUNTERS; ++i) {
+- if (unlikely(!CTR_IS_RESERVED(msrs,i)))
++ if (unlikely(!CTR_IS_RESERVED(msrs, i)))
+ continue;
+ CTR_32BIT_WRITE(1, msrs, i);
+ }
+
+ /* enable active counters */
+ for (i = 0; i < NUM_COUNTERS; ++i) {
+- if ((counter_config[i].enabled) && (CTR_IS_RESERVED(msrs,i))) {
++ if ((counter_config[i].enabled) && (CTR_IS_RESERVED(msrs, i))) {
+ reset_value[i] = counter_config[i].count;
+
+ CTR_32BIT_WRITE(counter_config[i].count, msrs, i);
+@@ -104,13 +104,13 @@ static void ppro_setup_ctrs(struct op_msrs const * const msrs)
+ }
+ }
+
+-
++
+ static int ppro_check_ctrs(struct pt_regs * const regs,
+ struct op_msrs const * const msrs)
+ {
+ unsigned int low, high;
+ int i;
+-
++
+ for (i = 0 ; i < NUM_COUNTERS; ++i) {
+ if (!reset_value[i])
+ continue;
+@@ -135,10 +135,10 @@ static int ppro_check_ctrs(struct pt_regs * const regs,
+ return 1;
+ }
+
+-
++
+ static void ppro_start(struct op_msrs const * const msrs)
+ {
+- unsigned int low,high;
++ unsigned int low, high;
+ int i;
+
+ for (i = 0; i < NUM_COUNTERS; ++i) {
+@@ -153,7 +153,7 @@ static void ppro_start(struct op_msrs const * const msrs)
+
+ static void ppro_stop(struct op_msrs const * const msrs)
+ {
+- unsigned int low,high;
++ unsigned int low, high;
+ int i;
+
+ for (i = 0; i < NUM_COUNTERS; ++i) {
+@@ -170,11 +170,11 @@ static void ppro_shutdown(struct op_msrs const * const msrs)
+ int i;
+
+ for (i = 0 ; i < NUM_COUNTERS ; ++i) {
+- if (CTR_IS_RESERVED(msrs,i))
++ if (CTR_IS_RESERVED(msrs, i))
+ release_perfctr_nmi(MSR_P6_PERFCTR0 + i);
+ }
+ for (i = 0 ; i < NUM_CONTROLS ; ++i) {
+- if (CTRL_IS_RESERVED(msrs,i))
++ if (CTRL_IS_RESERVED(msrs, i))
+ release_evntsel_nmi(MSR_P6_EVNTSEL0 + i);
+ }
+ }
+diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
+index 378136f..2664cb3 100644
+--- a/arch/x86/pci/acpi.c
++++ b/arch/x86/pci/acpi.c
+@@ -151,7 +151,7 @@ adjust_transparent_bridge_resources(struct pci_bus *bus)
+
+ static void
+ get_current_resources(struct acpi_device *device, int busnum,
+- struct pci_bus *bus)
++ int domain, struct pci_bus *bus)
+ {
+ struct pci_root_info info;
+ size_t size;
+@@ -168,10 +168,10 @@ get_current_resources(struct acpi_device *device, int busnum,
+ if (!info.res)
+ goto res_alloc_fail;
+
+- info.name = kmalloc(12, GFP_KERNEL);
++ info.name = kmalloc(16, GFP_KERNEL);
+ if (!info.name)
+ goto name_alloc_fail;
+- sprintf(info.name, "PCI Bus #%02x", busnum);
++ sprintf(info.name, "PCI Bus %04x:%02x", domain, busnum);
+
+ info.res_num = 0;
+ acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
+@@ -247,7 +247,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
+ #endif
+
+ if (bus && (pci_probe & PCI_USE__CRS))
+- get_current_resources(device, busnum, bus);
++ get_current_resources(device, busnum, domain, bus);
+
+ return bus;
+ }
+@@ -278,8 +278,7 @@ static int __init pci_acpi_init(void)
+ printk(KERN_INFO "PCI: Routing PCI interrupts for all devices because \"pci=routeirq\" specified\n");
+ for_each_pci_dev(dev)
+ acpi_pci_irq_enable(dev);
+- } else
+- printk(KERN_INFO "PCI: If a device doesn't work, try \"pci=routeirq\". If it helps, post a report\n");
++ }
+
+ #ifdef CONFIG_X86_IO_APIC
+ if (acpi_ioapic)
+diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
+index 7b6e3bb..75fcc29 100644
+--- a/arch/x86/pci/common.c
++++ b/arch/x86/pci/common.c
+@@ -77,59 +77,6 @@ int pcibios_scanned;
+ */
+ DEFINE_SPINLOCK(pci_config_lock);
+
+-/*
+- * Several buggy motherboards address only 16 devices and mirror
+- * them to next 16 IDs. We try to detect this `feature' on all
+- * primary buses (those containing host bridges as they are
+- * expected to be unique) and remove the ghost devices.
+- */
+-
+-static void __devinit pcibios_fixup_ghosts(struct pci_bus *b)
+-{
+- struct list_head *ln, *mn;
+- struct pci_dev *d, *e;
+- int mirror = PCI_DEVFN(16,0);
+- int seen_host_bridge = 0;
+- int i;
+-
+- DBG("PCI: Scanning for ghost devices on bus %d\n", b->number);
+- list_for_each(ln, &b->devices) {
+- d = pci_dev_b(ln);
+- if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST)
+- seen_host_bridge++;
+- for (mn=ln->next; mn != &b->devices; mn=mn->next) {
+- e = pci_dev_b(mn);
+- if (e->devfn != d->devfn + mirror ||
+- e->vendor != d->vendor ||
+- e->device != d->device ||
+- e->class != d->class)
+- continue;
+- for(i=0; i<PCI_NUM_RESOURCES; i++)
+- if (e->resource[i].start != d->resource[i].start ||
+- e->resource[i].end != d->resource[i].end ||
+- e->resource[i].flags != d->resource[i].flags)
+- continue;
+- break;
+- }
+- if (mn == &b->devices)
+- return;
+- }
+- if (!seen_host_bridge)
+- return;
+- printk(KERN_WARNING "PCI: Ignoring ghost devices on bus %02x\n", b->number);
+-
+- ln = &b->devices;
+- while (ln->next != &b->devices) {
+- d = pci_dev_b(ln->next);
+- if (d->devfn >= mirror) {
+- list_del(&d->global_list);
+- list_del(&d->bus_list);
+- kfree(d);
+- } else
+- ln = ln->next;
+- }
+-}
+-
+ static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
+ {
+ struct resource *rom_r = &dev->resource[PCI_ROM_RESOURCE];
+@@ -152,7 +99,6 @@ void __devinit pcibios_fixup_bus(struct pci_bus *b)
+ {
+ struct pci_dev *dev;
+
+- pcibios_fixup_ghosts(b);
+ pci_read_bridge_bases(b);
+ list_for_each_entry(dev, &b->devices, bus_list)
+ pcibios_fixup_device_resources(dev);
+@@ -427,10 +373,6 @@ static int __init pcibios_init(void)
+
+ if (pci_bf_sort >= pci_force_bf)
+ pci_sort_breadthfirst();
+-#ifdef CONFIG_PCI_BIOS
+- if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT))
+- pcibios_sort();
+-#endif
+ return 0;
+ }
+
+@@ -455,9 +397,6 @@ char * __devinit pcibios_setup(char *str)
+ } else if (!strcmp(str, "nobios")) {
+ pci_probe &= ~PCI_PROBE_BIOS;
+ return NULL;
+- } else if (!strcmp(str, "nosort")) {
+- pci_probe |= PCI_NO_SORT;
+- return NULL;
+ } else if (!strcmp(str, "biosirq")) {
+ pci_probe |= PCI_BIOS_IRQ_SCAN;
+ return NULL;
+@@ -527,7 +466,7 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
+ {
+ int err;
+
+- if ((err = pcibios_enable_resources(dev, mask)) < 0)
++ if ((err = pci_enable_resources(dev, mask)) < 0)
+ return err;
+
+ if (!dev->msi_enabled)
+diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
+index 103b9df..94f6c73 100644
+--- a/arch/x86/pci/i386.c
++++ b/arch/x86/pci/i386.c
+@@ -30,6 +30,9 @@
+ #include <linux/init.h>
+ #include <linux/ioport.h>
+ #include <linux/errno.h>
++#include <linux/bootmem.h>
++
++#include <asm/pat.h>
+
+ #include "pci.h"
+
+@@ -238,44 +241,6 @@ void __init pcibios_resource_survey(void)
+ */
+ fs_initcall(pcibios_assign_resources);
+
+-int pcibios_enable_resources(struct pci_dev *dev, int mask)
+-{
+- u16 cmd, old_cmd;
+- int idx;
+- struct resource *r;
+-
+- pci_read_config_word(dev, PCI_COMMAND, &cmd);
+- old_cmd = cmd;
+- for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
+- /* Only set up the requested stuff */
+- if (!(mask & (1 << idx)))
+- continue;
+-
+- r = &dev->resource[idx];
+- if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
+- continue;
+- if ((idx == PCI_ROM_RESOURCE) &&
+- (!(r->flags & IORESOURCE_ROM_ENABLE)))
+- continue;
+- if (!r->start && r->end) {
+- printk(KERN_ERR "PCI: Device %s not available "
+- "because of resource %d collisions\n",
+- pci_name(dev), idx);
+- return -EINVAL;
+- }
+- if (r->flags & IORESOURCE_IO)
+- cmd |= PCI_COMMAND_IO;
+- if (r->flags & IORESOURCE_MEM)
+- cmd |= PCI_COMMAND_MEMORY;
+- }
+- if (cmd != old_cmd) {
+- printk("PCI: Enabling device %s (%04x -> %04x)\n",
+- pci_name(dev), old_cmd, cmd);
+- pci_write_config_word(dev, PCI_COMMAND, cmd);
+- }
+- return 0;
+-}
+-
+ /*
+ * If we set up a device for bus mastering, we need to check the latency
+ * timer as certain crappy BIOSes forget to set it properly.
+@@ -297,10 +262,35 @@ void pcibios_set_master(struct pci_dev *dev)
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
+ }
+
++static void pci_unmap_page_range(struct vm_area_struct *vma)
++{
++ u64 addr = (u64)vma->vm_pgoff << PAGE_SHIFT;
++ free_memtype(addr, addr + vma->vm_end - vma->vm_start);
++}
++
++static void pci_track_mmap_page_range(struct vm_area_struct *vma)
++{
++ u64 addr = (u64)vma->vm_pgoff << PAGE_SHIFT;
++ unsigned long flags = pgprot_val(vma->vm_page_prot)
++ & _PAGE_CACHE_MASK;
++
++ reserve_memtype(addr, addr + vma->vm_end - vma->vm_start, flags, NULL);
++}
++
++static struct vm_operations_struct pci_mmap_ops = {
++ .open = pci_track_mmap_page_range,
++ .close = pci_unmap_page_range,
++};
++
+ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state, int write_combine)
+ {
+ unsigned long prot;
++ u64 addr = vma->vm_pgoff << PAGE_SHIFT;
++ unsigned long len = vma->vm_end - vma->vm_start;
++ unsigned long flags;
++ unsigned long new_flags;
++ int retval;
+
+ /* I/O space cannot be accessed via normal processor loads and
+ * stores on this platform.
+@@ -308,21 +298,50 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+ if (mmap_state == pci_mmap_io)
+ return -EINVAL;
+
+- /* Leave vm_pgoff as-is, the PCI space address is the physical
+- * address on this platform.
+- */
+ prot = pgprot_val(vma->vm_page_prot);
+- if (boot_cpu_data.x86 > 3)
+- prot |= _PAGE_PCD | _PAGE_PWT;
++ if (pat_wc_enabled && write_combine)
++ prot |= _PAGE_CACHE_WC;
++ else if (boot_cpu_data.x86 > 3)
++ prot |= _PAGE_CACHE_UC;
++
+ vma->vm_page_prot = __pgprot(prot);
+
+- /* Write-combine setting is ignored, it is changed via the mtrr
+- * interfaces on this platform.
+- */
++ flags = pgprot_val(vma->vm_page_prot) & _PAGE_CACHE_MASK;
++ retval = reserve_memtype(addr, addr + len, flags, &new_flags);
++ if (retval)
++ return retval;
++
++ if (flags != new_flags) {
++ /*
++ * Do not fallback to certain memory types with certain
++ * requested type:
++ * - request is uncached, return cannot be write-back
++ * - request is uncached, return cannot be write-combine
++ * - request is write-combine, return cannot be write-back
++ */
++ if ((flags == _PAGE_CACHE_UC &&
++ (new_flags == _PAGE_CACHE_WB ||
++ new_flags == _PAGE_CACHE_WC)) ||
++ (flags == _PAGE_CACHE_WC &&
++ new_flags == _PAGE_CACHE_WB)) {
++ free_memtype(addr, addr+len);
++ return -EINVAL;
++ }
++ flags = new_flags;
++ }
++
++ if (vma->vm_pgoff <= max_pfn_mapped &&
++ ioremap_change_attr((unsigned long)__va(addr), len, flags)) {
++ free_memtype(addr, addr + len);
++ return -EINVAL;
++ }
++
+ if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot))
+ return -EAGAIN;
+
++ vma->vm_ops = &pci_mmap_ops;
++
+ return 0;
+ }
+diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
+index a871586..579745c 100644
+--- a/arch/x86/pci/irq.c
++++ b/arch/x86/pci/irq.c
+@@ -200,7 +200,7 @@ static int pirq_ali_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+ {
+ static const unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
+
+- WARN_ON_ONCE(pirq >= 16);
++ WARN_ON_ONCE(pirq > 16);
+ return irqmap[read_config_nybble(router, 0x48, pirq-1)];
+ }
+
+@@ -209,7 +209,7 @@ static int pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, i
+ static const unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
+ unsigned int val = irqmap[irq];
+
+- WARN_ON_ONCE(pirq >= 16);
++ WARN_ON_ONCE(pirq > 16);
+ if (val) {
+ write_config_nybble(router, 0x48, pirq-1, val);
+ return 1;
+@@ -260,7 +260,7 @@ static int pirq_via586_get(struct pci_dev *router, struct pci_dev *dev, int pirq
+ {
+ static const unsigned int pirqmap[5] = { 3, 2, 5, 1, 1 };
+
+- WARN_ON_ONCE(pirq >= 5);
++ WARN_ON_ONCE(pirq > 5);
+ return read_config_nybble(router, 0x55, pirqmap[pirq-1]);
+ }
+
+@@ -268,7 +268,7 @@ static int pirq_via586_set(struct pci_dev *router, struct pci_dev *dev, int pirq
+ {
+ static const unsigned int pirqmap[5] = { 3, 2, 5, 1, 1 };
+
+- WARN_ON_ONCE(pirq >= 5);
++ WARN_ON_ONCE(pirq > 5);
+ write_config_nybble(router, 0x55, pirqmap[pirq-1], irq);
+ return 1;
+ }
+@@ -282,7 +282,7 @@ static int pirq_ite_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+ {
+ static const unsigned char pirqmap[4] = { 1, 0, 2, 3 };
+
+- WARN_ON_ONCE(pirq >= 4);
++ WARN_ON_ONCE(pirq > 4);
+ return read_config_nybble(router,0x43, pirqmap[pirq-1]);
+ }
+
+@@ -290,7 +290,7 @@ static int pirq_ite_set(struct pci_dev *router, struct pci_dev *dev, int pirq, i
+ {
+ static const unsigned char pirqmap[4] = { 1, 0, 2, 3 };
+
+- WARN_ON_ONCE(pirq >= 4);
++ WARN_ON_ONCE(pirq > 4);
+ write_config_nybble(router, 0x43, pirqmap[pirq-1], irq);
+ return 1;
+ }
+diff --git a/arch/x86/pci/numa.c b/arch/x86/pci/numa.c
+index 55270c2..d9afbae 100644
+--- a/arch/x86/pci/numa.c
++++ b/arch/x86/pci/numa.c
+@@ -11,11 +11,41 @@
+ #define XQUAD_PORTIO_BASE 0xfe400000
+ #define XQUAD_PORTIO_QUAD 0x40000 /* 256k per quad. */
+
++int mp_bus_id_to_node[MAX_MP_BUSSES];
+ #define BUS2QUAD(global) (mp_bus_id_to_node[global])
++
++int mp_bus_id_to_local[MAX_MP_BUSSES];
+ #define BUS2LOCAL(global) (mp_bus_id_to_local[global])
++
++void mpc_oem_bus_info(struct mpc_config_bus *m, char *name,
++ struct mpc_config_translation *translation)
++{
++ int quad = translation->trans_quad;
++ int local = translation->trans_local;
++
++ mp_bus_id_to_node[m->mpc_busid] = quad;
++ mp_bus_id_to_local[m->mpc_busid] = local;
++ printk(KERN_INFO "Bus #%d is %s (node %d)\n",
++ m->mpc_busid, name, quad);
++}
++
++int quad_local_to_mp_bus_id [NR_CPUS/4][4];
+ #define QUADLOCAL2BUS(quad,local) (quad_local_to_mp_bus_id[quad][local])
++void mpc_oem_pci_bus(struct mpc_config_bus *m,
++ struct mpc_config_translation *translation)
++{
++ int quad = translation->trans_quad;
++ int local = translation->trans_local;
++
++ quad_local_to_mp_bus_id[quad][local] = m->mpc_busid;
++}
++
++/* Where the IO area was mapped on multiquad, always 0 otherwise */
++void *xquad_portio;
++#ifdef CONFIG_X86_NUMAQ
++EXPORT_SYMBOL(xquad_portio);
++#endif
+
+-extern void *xquad_portio; /* Where the IO area was mapped */
+ #define XQUAD_PORT_ADDR(port, quad) (xquad_portio + (XQUAD_PORTIO_QUAD*quad) + port)
+
+ #define PCI_CONF1_MQ_ADDRESS(bus, devfn, reg) \
+diff --git a/arch/x86/pci/pcbios.c b/arch/x86/pci/pcbios.c
+index 2f7109a..37472fc 100644
+--- a/arch/x86/pci/pcbios.c
++++ b/arch/x86/pci/pcbios.c
+@@ -152,28 +152,6 @@ static int __devinit check_pcibios(void)
+ return 0;
+ }
+
+-static int __devinit pci_bios_find_device (unsigned short vendor, unsigned short device_id,
+- unsigned short index, unsigned char *bus, unsigned char *device_fn)
+-{
+- unsigned short bx;
+- unsigned short ret;
+-
+- __asm__("lcall *(%%edi); cld\n\t"
+- "jc 1f\n\t"
+- "xor %%ah, %%ah\n"
+- "1:"
+- : "=b" (bx),
+- "=a" (ret)
+- : "1" (PCIBIOS_FIND_PCI_DEVICE),
+- "c" (device_id),
+- "d" (vendor),
+- "S" ((int) index),
+- "D" (&pci_indirect));
+- *bus = (bx >> 8) & 0xff;
+- *device_fn = bx & 0xff;
+- return (int) (ret & 0xff00) >> 8;
+-}
+-
+ static int pci_bios_read(unsigned int seg, unsigned int bus,
+ unsigned int devfn, int reg, int len, u32 *value)
+ {
+@@ -364,55 +342,6 @@ static struct pci_raw_ops * __devinit pci_find_bios(void)
+ }
+
+ /*
+- * Sort the device list according to PCI BIOS. Nasty hack, but since some
+- * fool forgot to define the `correct' device order in the PCI BIOS specs
+- * and we want to be (possibly bug-to-bug ;-]) compatible with older kernels
+- * which used BIOS ordering, we are bound to do this...
+- */
+-
+-void __devinit pcibios_sort(void)
+-{
+- LIST_HEAD(sorted_devices);
+- struct list_head *ln;
+- struct pci_dev *dev, *d;
+- int idx, found;
+- unsigned char bus, devfn;
+-
+- DBG("PCI: Sorting device list...\n");
+- while (!list_empty(&pci_devices)) {
+- ln = pci_devices.next;
+- dev = pci_dev_g(ln);
+- idx = found = 0;
+- while (pci_bios_find_device(dev->vendor, dev->device, idx, &bus, &devfn) == PCIBIOS_SUCCESSFUL) {
+- idx++;
+- list_for_each(ln, &pci_devices) {
+- d = pci_dev_g(ln);
+- if (d->bus->number == bus && d->devfn == devfn) {
+- list_move_tail(&d->global_list, &sorted_devices);
+- if (d == dev)
+- found = 1;
+- break;
+- }
+- }
+- if (ln == &pci_devices) {
+- printk(KERN_WARNING "PCI: BIOS reporting unknown device %02x:%02x\n", bus, devfn);
+- /*
+- * We must not continue scanning as several buggy BIOSes
+- * return garbage after the last device. Grr.
+- */
+- break;
+- }
+- }
+- if (!found) {
+- printk(KERN_WARNING "PCI: Device %s not found by BIOS\n",
+- pci_name(dev));
+- list_move_tail(&dev->global_list, &sorted_devices);
+- }
+- }
+- list_splice(&sorted_devices, &pci_devices);
+-}
+-
+-/*
+ * BIOS Functions for IRQ Routing
+ */
+
+@@ -495,7 +424,6 @@ void __init pci_pcbios_init(void)
+ {
+ if ((pci_probe & PCI_PROBE_BIOS)
+ && ((raw_pci_ops = pci_find_bios()))) {
+- pci_probe |= PCI_BIOS_SORT;
+ pci_bios_present = 1;
+ }
+ }
+diff --git a/arch/x86/pci/pci.h b/arch/x86/pci/pci.h
+index 3431518..c4bddae 100644
+--- a/arch/x86/pci/pci.h
++++ b/arch/x86/pci/pci.h
+@@ -19,8 +19,6 @@
+ #define PCI_PROBE_MASK 0x000f
+ #define PCI_PROBE_NOEARLY 0x0010
+
+-#define PCI_NO_SORT 0x0100
+-#define PCI_BIOS_SORT 0x0200
+ #define PCI_NO_CHECKS 0x0400
+ #define PCI_USE_PIRQ_MASK 0x0800
+ #define PCI_ASSIGN_ROMS 0x1000
+@@ -44,7 +42,6 @@ enum pci_bf_sort_state {
+ extern unsigned int pcibios_max_latency;
+
+ void pcibios_resource_survey(void);
+-int pcibios_enable_resources(struct pci_dev *, int);
+
+ /* pci-pc.c */
+
+@@ -101,7 +98,6 @@ extern int pci_direct_probe(void);
+ extern void pci_direct_init(int type);
+ extern void pci_pcbios_init(void);
+ extern void pci_mmcfg_init(int type);
+-extern void pcibios_sort(void);
+
+ /* pci-mmconfig.c */
+
+diff --git a/arch/x86/power/cpu_32.c b/arch/x86/power/cpu_32.c
+index 7f9c6da..7dc5d5c 100644
+--- a/arch/x86/power/cpu_32.c
++++ b/arch/x86/power/cpu_32.c
+@@ -27,17 +27,17 @@ static void __save_processor_state(struct saved_context *ctxt)
+ /*
+ * descriptor tables
+ */
+- store_gdt(&ctxt->gdt);
+- store_idt(&ctxt->idt);
+- store_tr(ctxt->tr);
++ store_gdt(&ctxt->gdt);
++ store_idt(&ctxt->idt);
++ store_tr(ctxt->tr);
+
+ /*
+ * segment registers
+ */
+- savesegment(es, ctxt->es);
+- savesegment(fs, ctxt->fs);
+- savesegment(gs, ctxt->gs);
+- savesegment(ss, ctxt->ss);
++ savesegment(es, ctxt->es);
++ savesegment(fs, ctxt->fs);
++ savesegment(gs, ctxt->gs);
++ savesegment(ss, ctxt->ss);
+
+ /*
+ * control registers
+@@ -48,10 +48,12 @@ static void __save_processor_state(struct saved_context *ctxt)
+ ctxt->cr4 = read_cr4();
+ }
+
++/* Needed by apm.c */
+ void save_processor_state(void)
+ {
+ __save_processor_state(&saved_context);
+ }
++EXPORT_SYMBOL(save_processor_state);
+
+ static void do_fpu_end(void)
+ {
+@@ -64,9 +66,14 @@ static void do_fpu_end(void)
+ static void fix_processor_context(void)
+ {
+ int cpu = smp_processor_id();
+- struct tss_struct * t = &per_cpu(init_tss, cpu);
++ struct tss_struct *t = &per_cpu(init_tss, cpu);
+
+- set_tss_desc(cpu,t); /* This just modifies memory; should not be necessary. But... This is necessary, because 386 hardware has concept of busy TSS or some similar stupidity. */
++ set_tss_desc(cpu, t); /*
++ * This just modifies memory; should not be
++ * necessary. But... This is necessary, because
++ * 386 hardware has concept of busy TSS or some
++ * similar stupidity.
++ */
+
+ load_TR_desc(); /* This does ltr */
+ load_LDT(¤t->active_mm->context); /* This does lldt */
+@@ -100,16 +107,16 @@ static void __restore_processor_state(struct saved_context *ctxt)
+ * now restore the descriptor tables to their proper values
+ * ltr is done i fix_processor_context().
+ */
+- load_gdt(&ctxt->gdt);
+- load_idt(&ctxt->idt);
++ load_gdt(&ctxt->gdt);
++ load_idt(&ctxt->idt);
+
+ /*
+ * segment registers
+ */
+- loadsegment(es, ctxt->es);
+- loadsegment(fs, ctxt->fs);
+- loadsegment(gs, ctxt->gs);
+- loadsegment(ss, ctxt->ss);
++ loadsegment(es, ctxt->es);
++ loadsegment(fs, ctxt->fs);
++ loadsegment(gs, ctxt->gs);
++ loadsegment(ss, ctxt->ss);
+
+ /*
+ * sysenter MSRs
+@@ -123,11 +130,9 @@ static void __restore_processor_state(struct saved_context *ctxt)
+ mcheck_init(&boot_cpu_data);
+ }
+
++/* Needed by apm.c */
+ void restore_processor_state(void)
+ {
+ __restore_processor_state(&saved_context);
+ }
+-
+-/* Needed by apm.c */
+-EXPORT_SYMBOL(save_processor_state);
+ EXPORT_SYMBOL(restore_processor_state);
+diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile
+index 0a8f474..b7ad9f8 100644
+--- a/arch/x86/vdso/Makefile
++++ b/arch/x86/vdso/Makefile
+@@ -37,9 +37,10 @@ $(obj)/%.so: OBJCOPYFLAGS := -S
+ $(obj)/%.so: $(obj)/%.so.dbg FORCE
+ $(call if_changed,objcopy)
+
+-CFL := $(PROFILING) -mcmodel=small -fPIC -g0 -O2 -fasynchronous-unwind-tables -m64
++CFL := $(PROFILING) -mcmodel=small -fPIC -O2 -fasynchronous-unwind-tables -m64 \
++ $(filter -g%,$(KBUILD_CFLAGS))
+
+-$(vobjs): KBUILD_CFLAGS = $(CFL)
++$(vobjs): KBUILD_CFLAGS += $(CFL)
+
+ targets += vdso-syms.lds
+ obj-$(VDSO64-y) += vdso-syms.lds
+diff --git a/arch/x86/vdso/vdso32-setup.c b/arch/x86/vdso/vdso32-setup.c
+index 348f134..e2af8ee 100644
+--- a/arch/x86/vdso/vdso32-setup.c
++++ b/arch/x86/vdso/vdso32-setup.c
+@@ -210,8 +210,12 @@ static int use_sysenter __read_mostly = -1;
+ /* May not be __init: called during resume */
+ void syscall32_cpu_init(void)
+ {
+- if (use_sysenter < 0)
+- use_sysenter = (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL);
++ if (use_sysenter < 0) {
++ if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
++ use_sysenter = 1;
++ if (boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR)
++ use_sysenter = 1;
++ }
+
+ /* Load these always in case some future AMD CPU supports
+ SYSENTER from compat mode too. */
+@@ -325,6 +329,9 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int exstack)
+ int ret = 0;
+ bool compat;
+
++ if (vdso_enabled == VDSO_DISABLED)
++ return 0;
++
+ down_write(&mm->mmap_sem);
+
+ /* Test compat mode once here, in case someone
+diff --git a/arch/x86/video/fbdev.c b/arch/x86/video/fbdev.c
+index 48fb38d..4db42bf 100644
+--- a/arch/x86/video/fbdev.c
++++ b/arch/x86/video/fbdev.c
+@@ -1,5 +1,4 @@
+ /*
+- * arch/i386/video/fbdev.c - i386 Framebuffer
+ *
+ * Copyright (C) 2007 Antonino Daplas <adaplas at gmail.com>
+ *
+diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig
+index 4d5f264..2e641be 100644
+--- a/arch/x86/xen/Kconfig
++++ b/arch/x86/xen/Kconfig
+@@ -6,7 +6,7 @@ config XEN
+ bool "Xen guest support"
+ select PARAVIRT
+ depends on X86_32
+- depends on X86_CMPXCHG && X86_TSC && !NEED_MULTIPLE_NODES && !(X86_VISWS || X86_VOYAGER)
++ depends on X86_CMPXCHG && X86_TSC && !(X86_VISWS || X86_VOYAGER)
+ help
+ This is the Linux Xen port. Enabling this will allow the
+ kernel to boot in a paravirtualized environment under the
+diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile
+index 343df24..3d8df98 100644
+--- a/arch/x86/xen/Makefile
++++ b/arch/x86/xen/Makefile
+@@ -1,4 +1,4 @@
+-obj-y := enlighten.o setup.o features.o multicalls.o mmu.o \
+- events.o time.o manage.o xen-asm.o
++obj-y := enlighten.o setup.o multicalls.o mmu.o \
++ time.o manage.o xen-asm.o grant-table.o
+
+ obj-$(CONFIG_SMP) += smp.o
+diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
+index 27ee26a..c8a56e4 100644
+--- a/arch/x86/xen/enlighten.c
++++ b/arch/x86/xen/enlighten.c
+@@ -25,6 +25,7 @@
+ #include <linux/mm.h>
+ #include <linux/page-flags.h>
+ #include <linux/highmem.h>
++#include <linux/console.h>
+
+ #include <xen/interface/xen.h>
+ #include <xen/interface/physdev.h>
+@@ -154,7 +155,8 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
+ if (*ax == 1)
+ maskedx = ~((1 << X86_FEATURE_APIC) | /* disable APIC */
+ (1 << X86_FEATURE_ACPI) | /* disable ACPI */
+- (1 << X86_FEATURE_SEP) | /* disable SEP */
++ (1 << X86_FEATURE_MCE) | /* disable MCE */
++ (1 << X86_FEATURE_MCA) | /* disable MCA */
+ (1 << X86_FEATURE_ACC)); /* thermal monitoring */
+
+ asm(XEN_EMULATE_PREFIX "cpuid"
+@@ -530,26 +532,37 @@ static void xen_apic_write(unsigned long reg, u32 val)
+ static void xen_flush_tlb(void)
+ {
+ struct mmuext_op *op;
+- struct multicall_space mcs = xen_mc_entry(sizeof(*op));
++ struct multicall_space mcs;
++
++ preempt_disable();
++
++ mcs = xen_mc_entry(sizeof(*op));
+
+ op = mcs.args;
+ op->cmd = MMUEXT_TLB_FLUSH_LOCAL;
+ MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
+
+ xen_mc_issue(PARAVIRT_LAZY_MMU);
++
++ preempt_enable();
+ }
+
+ static void xen_flush_tlb_single(unsigned long addr)
+ {
+ struct mmuext_op *op;
+- struct multicall_space mcs = xen_mc_entry(sizeof(*op));
++ struct multicall_space mcs;
++
++ preempt_disable();
+
++ mcs = xen_mc_entry(sizeof(*op));
+ op = mcs.args;
+ op->cmd = MMUEXT_INVLPG_LOCAL;
+ op->arg1.linear_addr = addr & PAGE_MASK;
+ MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
+
+ xen_mc_issue(PARAVIRT_LAZY_MMU);
++
++ preempt_enable();
+ }
+
+ static void xen_flush_tlb_others(const cpumask_t *cpus, struct mm_struct *mm,
+@@ -654,15 +667,17 @@ static void xen_write_cr3(unsigned long cr3)
+
+ /* Early in boot, while setting up the initial pagetable, assume
+ everything is pinned. */
+-static __init void xen_alloc_pt_init(struct mm_struct *mm, u32 pfn)
++static __init void xen_alloc_pte_init(struct mm_struct *mm, u32 pfn)
+ {
++#ifdef CONFIG_FLATMEM
+ BUG_ON(mem_map); /* should only be used early */
++#endif
+ make_lowmem_page_readonly(__va(PFN_PHYS(pfn)));
+ }
+
+-/* Early release_pt assumes that all pts are pinned, since there's
++/* Early release_pte assumes that all pts are pinned, since there's
+ only init_mm and anything attached to that is pinned. */
+-static void xen_release_pt_init(u32 pfn)
++static void xen_release_pte_init(u32 pfn)
+ {
+ make_lowmem_page_readwrite(__va(PFN_PHYS(pfn)));
+ }
+@@ -696,12 +711,12 @@ static void xen_alloc_ptpage(struct mm_struct *mm, u32 pfn, unsigned level)
+ }
+ }
+
+-static void xen_alloc_pt(struct mm_struct *mm, u32 pfn)
++static void xen_alloc_pte(struct mm_struct *mm, u32 pfn)
+ {
+ xen_alloc_ptpage(mm, pfn, PT_PTE);
+ }
+
+-static void xen_alloc_pd(struct mm_struct *mm, u32 pfn)
++static void xen_alloc_pmd(struct mm_struct *mm, u32 pfn)
+ {
+ xen_alloc_ptpage(mm, pfn, PT_PMD);
+ }
+@@ -721,12 +736,12 @@ static void xen_release_ptpage(u32 pfn, unsigned level)
+ }
+ }
+
+-static void xen_release_pt(u32 pfn)
++static void xen_release_pte(u32 pfn)
+ {
+ xen_release_ptpage(pfn, PT_PTE);
+ }
+
+-static void xen_release_pd(u32 pfn)
++static void xen_release_pmd(u32 pfn)
+ {
+ xen_release_ptpage(pfn, PT_PMD);
+ }
+@@ -848,10 +863,10 @@ static __init void xen_pagetable_setup_done(pgd_t *base)
+ {
+ /* This will work as long as patching hasn't happened yet
+ (which it hasn't) */
+- pv_mmu_ops.alloc_pt = xen_alloc_pt;
+- pv_mmu_ops.alloc_pd = xen_alloc_pd;
+- pv_mmu_ops.release_pt = xen_release_pt;
+- pv_mmu_ops.release_pd = xen_release_pd;
++ pv_mmu_ops.alloc_pte = xen_alloc_pte;
++ pv_mmu_ops.alloc_pmd = xen_alloc_pmd;
++ pv_mmu_ops.release_pte = xen_release_pte;
++ pv_mmu_ops.release_pmd = xen_release_pmd;
+ pv_mmu_ops.set_pte = xen_set_pte;
+
+ setup_shared_info();
+@@ -889,7 +904,6 @@ void __init xen_setup_vcpu_info_placement(void)
+ pv_irq_ops.irq_disable = xen_irq_disable_direct;
+ pv_irq_ops.irq_enable = xen_irq_enable_direct;
+ pv_mmu_ops.read_cr2 = xen_read_cr2_direct;
+- pv_cpu_ops.iret = xen_iret_direct;
+ }
+ }
+
+@@ -993,8 +1007,8 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = {
+ .read_tsc = native_read_tsc,
+ .read_pmc = native_read_pmc,
+
+- .iret = (void *)&hypercall_page[__HYPERVISOR_iret],
+- .irq_enable_syscall_ret = NULL, /* never called */
++ .iret = xen_iret,
++ .irq_enable_syscall_ret = xen_sysexit,
+
+ .load_tr_desc = paravirt_nop,
+ .set_ldt = xen_set_ldt,
+@@ -1059,11 +1073,11 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = {
+ .pte_update = paravirt_nop,
+ .pte_update_defer = paravirt_nop,
+
+- .alloc_pt = xen_alloc_pt_init,
+- .release_pt = xen_release_pt_init,
+- .alloc_pd = xen_alloc_pt_init,
+- .alloc_pd_clone = paravirt_nop,
+- .release_pd = xen_release_pt_init,
++ .alloc_pte = xen_alloc_pte_init,
++ .release_pte = xen_release_pte_init,
++ .alloc_pmd = xen_alloc_pte_init,
++ .alloc_pmd_clone = paravirt_nop,
++ .release_pmd = xen_release_pte_init,
+
+ #ifdef CONFIG_HIGHPTE
+ .kmap_atomic_pte = xen_kmap_atomic_pte,
+@@ -1228,6 +1242,9 @@ asmlinkage void __init xen_start_kernel(void)
+ ? __pa(xen_start_info->mod_start) : 0;
+ boot_params.hdr.ramdisk_size = xen_start_info->mod_len;
+
++ if (!is_initial_xendomain())
++ add_preferred_console("hvc", 0, NULL);
++
+ /* Start the world */
+ start_kernel();
+ }
+diff --git a/arch/x86/xen/events.c b/arch/x86/xen/events.c
+deleted file mode 100644
+index dcf613e..0000000
+--- a/arch/x86/xen/events.c
++++ /dev/null
+@@ -1,591 +0,0 @@
+-/*
+- * Xen event channels
+- *
+- * Xen models interrupts with abstract event channels. Because each
+- * domain gets 1024 event channels, but NR_IRQ is not that large, we
+- * must dynamically map irqs<->event channels. The event channels
+- * interface with the rest of the kernel by defining a xen interrupt
+- * chip. When an event is recieved, it is mapped to an irq and sent
+- * through the normal interrupt processing path.
+- *
+- * There are four kinds of events which can be mapped to an event
+- * channel:
+- *
+- * 1. Inter-domain notifications. This includes all the virtual
+- * device events, since they're driven by front-ends in another domain
+- * (typically dom0).
+- * 2. VIRQs, typically used for timers. These are per-cpu events.
+- * 3. IPIs.
+- * 4. Hardware interrupts. Not supported at present.
+- *
+- * Jeremy Fitzhardinge <jeremy at xensource.com>, XenSource Inc, 2007
+- */
+-
+-#include <linux/linkage.h>
+-#include <linux/interrupt.h>
+-#include <linux/irq.h>
+-#include <linux/module.h>
+-#include <linux/string.h>
+-
+-#include <asm/ptrace.h>
+-#include <asm/irq.h>
+-#include <asm/sync_bitops.h>
+-#include <asm/xen/hypercall.h>
+-#include <asm/xen/hypervisor.h>
+-
+-#include <xen/events.h>
+-#include <xen/interface/xen.h>
+-#include <xen/interface/event_channel.h>
+-
+-#include "xen-ops.h"
+-
+-/*
+- * This lock protects updates to the following mapping and reference-count
+- * arrays. The lock does not need to be acquired to read the mapping tables.
+- */
+-static DEFINE_SPINLOCK(irq_mapping_update_lock);
+-
+-/* IRQ <-> VIRQ mapping. */
+-static DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS]) = {[0 ... NR_VIRQS-1] = -1};
+-
+-/* IRQ <-> IPI mapping */
+-static DEFINE_PER_CPU(int, ipi_to_irq[XEN_NR_IPIS]) = {[0 ... XEN_NR_IPIS-1] = -1};
+-
+-/* Packed IRQ information: binding type, sub-type index, and event channel. */
+-struct packed_irq
+-{
+- unsigned short evtchn;
+- unsigned char index;
+- unsigned char type;
+-};
+-
+-static struct packed_irq irq_info[NR_IRQS];
+-
+-/* Binding types. */
+-enum {
+- IRQT_UNBOUND,
+- IRQT_PIRQ,
+- IRQT_VIRQ,
+- IRQT_IPI,
+- IRQT_EVTCHN
+-};
+-
+-/* Convenient shorthand for packed representation of an unbound IRQ. */
+-#define IRQ_UNBOUND mk_irq_info(IRQT_UNBOUND, 0, 0)
+-
+-static int evtchn_to_irq[NR_EVENT_CHANNELS] = {
+- [0 ... NR_EVENT_CHANNELS-1] = -1
+-};
+-static unsigned long cpu_evtchn_mask[NR_CPUS][NR_EVENT_CHANNELS/BITS_PER_LONG];
+-static u8 cpu_evtchn[NR_EVENT_CHANNELS];
+-
+-/* Reference counts for bindings to IRQs. */
+-static int irq_bindcount[NR_IRQS];
+-
+-/* Xen will never allocate port zero for any purpose. */
+-#define VALID_EVTCHN(chn) ((chn) != 0)
+-
+-/*
+- * Force a proper event-channel callback from Xen after clearing the
+- * callback mask. We do this in a very simple manner, by making a call
+- * down into Xen. The pending flag will be checked by Xen on return.
+- */
+-void force_evtchn_callback(void)
+-{
+- (void)HYPERVISOR_xen_version(0, NULL);
+-}
+-EXPORT_SYMBOL_GPL(force_evtchn_callback);
+-
+-static struct irq_chip xen_dynamic_chip;
+-
+-/* Constructor for packed IRQ information. */
+-static inline struct packed_irq mk_irq_info(u32 type, u32 index, u32 evtchn)
+-{
+- return (struct packed_irq) { evtchn, index, type };
+-}
+-
+-/*
+- * Accessors for packed IRQ information.
+- */
+-static inline unsigned int evtchn_from_irq(int irq)
+-{
+- return irq_info[irq].evtchn;
+-}
+-
+-static inline unsigned int index_from_irq(int irq)
+-{
+- return irq_info[irq].index;
+-}
+-
+-static inline unsigned int type_from_irq(int irq)
+-{
+- return irq_info[irq].type;
+-}
+-
+-static inline unsigned long active_evtchns(unsigned int cpu,
+- struct shared_info *sh,
+- unsigned int idx)
+-{
+- return (sh->evtchn_pending[idx] &
+- cpu_evtchn_mask[cpu][idx] &
+- ~sh->evtchn_mask[idx]);
+-}
+-
+-static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
+-{
+- int irq = evtchn_to_irq[chn];
+-
+- BUG_ON(irq == -1);
+-#ifdef CONFIG_SMP
+- irq_desc[irq].affinity = cpumask_of_cpu(cpu);
+-#endif
+-
+- __clear_bit(chn, cpu_evtchn_mask[cpu_evtchn[chn]]);
+- __set_bit(chn, cpu_evtchn_mask[cpu]);
+-
+- cpu_evtchn[chn] = cpu;
+-}
+-
+-static void init_evtchn_cpu_bindings(void)
+-{
+-#ifdef CONFIG_SMP
+- int i;
+- /* By default all event channels notify CPU#0. */
+- for (i = 0; i < NR_IRQS; i++)
+- irq_desc[i].affinity = cpumask_of_cpu(0);
+-#endif
+-
+- memset(cpu_evtchn, 0, sizeof(cpu_evtchn));
+- memset(cpu_evtchn_mask[0], ~0, sizeof(cpu_evtchn_mask[0]));
+-}
+-
+-static inline unsigned int cpu_from_evtchn(unsigned int evtchn)
+-{
+- return cpu_evtchn[evtchn];
+-}
+-
+-static inline void clear_evtchn(int port)
+-{
+- struct shared_info *s = HYPERVISOR_shared_info;
+- sync_clear_bit(port, &s->evtchn_pending[0]);
+-}
+-
+-static inline void set_evtchn(int port)
+-{
+- struct shared_info *s = HYPERVISOR_shared_info;
+- sync_set_bit(port, &s->evtchn_pending[0]);
+-}
+-
+-
+-/**
+- * notify_remote_via_irq - send event to remote end of event channel via irq
+- * @irq: irq of event channel to send event to
+- *
+- * Unlike notify_remote_via_evtchn(), this is safe to use across
+- * save/restore. Notifications on a broken connection are silently
+- * dropped.
+- */
+-void notify_remote_via_irq(int irq)
+-{
+- int evtchn = evtchn_from_irq(irq);
+-
+- if (VALID_EVTCHN(evtchn))
+- notify_remote_via_evtchn(evtchn);
+-}
+-EXPORT_SYMBOL_GPL(notify_remote_via_irq);
+-
+-static void mask_evtchn(int port)
+-{
+- struct shared_info *s = HYPERVISOR_shared_info;
+- sync_set_bit(port, &s->evtchn_mask[0]);
+-}
+-
+-static void unmask_evtchn(int port)
+-{
+- struct shared_info *s = HYPERVISOR_shared_info;
+- unsigned int cpu = get_cpu();
+-
+- BUG_ON(!irqs_disabled());
+-
+- /* Slow path (hypercall) if this is a non-local port. */
+- if (unlikely(cpu != cpu_from_evtchn(port))) {
+- struct evtchn_unmask unmask = { .port = port };
+- (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask);
+- } else {
+- struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu);
+-
+- sync_clear_bit(port, &s->evtchn_mask[0]);
+-
+- /*
+- * The following is basically the equivalent of
+- * 'hw_resend_irq'. Just like a real IO-APIC we 'lose
+- * the interrupt edge' if the channel is masked.
+- */
+- if (sync_test_bit(port, &s->evtchn_pending[0]) &&
+- !sync_test_and_set_bit(port / BITS_PER_LONG,
+- &vcpu_info->evtchn_pending_sel))
+- vcpu_info->evtchn_upcall_pending = 1;
+- }
+-
+- put_cpu();
+-}
+-
+-static int find_unbound_irq(void)
+-{
+- int irq;
+-
+- /* Only allocate from dynirq range */
+- for (irq = 0; irq < NR_IRQS; irq++)
+- if (irq_bindcount[irq] == 0)
+- break;
+-
+- if (irq == NR_IRQS)
+- panic("No available IRQ to bind to: increase NR_IRQS!\n");
+-
+- return irq;
+-}
+-
+-int bind_evtchn_to_irq(unsigned int evtchn)
+-{
+- int irq;
+-
+- spin_lock(&irq_mapping_update_lock);
+-
+- irq = evtchn_to_irq[evtchn];
+-
+- if (irq == -1) {
+- irq = find_unbound_irq();
+-
+- dynamic_irq_init(irq);
+- set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
+- handle_level_irq, "event");
+-
+- evtchn_to_irq[evtchn] = irq;
+- irq_info[irq] = mk_irq_info(IRQT_EVTCHN, 0, evtchn);
+- }
+-
+- irq_bindcount[irq]++;
+-
+- spin_unlock(&irq_mapping_update_lock);
+-
+- return irq;
+-}
+-EXPORT_SYMBOL_GPL(bind_evtchn_to_irq);
+-
+-static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
+-{
+- struct evtchn_bind_ipi bind_ipi;
+- int evtchn, irq;
+-
+- spin_lock(&irq_mapping_update_lock);
+-
+- irq = per_cpu(ipi_to_irq, cpu)[ipi];
+- if (irq == -1) {
+- irq = find_unbound_irq();
+- if (irq < 0)
+- goto out;
+-
+- dynamic_irq_init(irq);
+- set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
+- handle_level_irq, "ipi");
+-
+- bind_ipi.vcpu = cpu;
+- if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi,
+- &bind_ipi) != 0)
+- BUG();
+- evtchn = bind_ipi.port;
+-
+- evtchn_to_irq[evtchn] = irq;
+- irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn);
+-
+- per_cpu(ipi_to_irq, cpu)[ipi] = irq;
+-
+- bind_evtchn_to_cpu(evtchn, cpu);
+- }
+-
+- irq_bindcount[irq]++;
+-
+- out:
+- spin_unlock(&irq_mapping_update_lock);
+- return irq;
+-}
+-
+-
+-static int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
+-{
+- struct evtchn_bind_virq bind_virq;
+- int evtchn, irq;
+-
+- spin_lock(&irq_mapping_update_lock);
+-
+- irq = per_cpu(virq_to_irq, cpu)[virq];
+-
+- if (irq == -1) {
+- bind_virq.virq = virq;
+- bind_virq.vcpu = cpu;
+- if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
+- &bind_virq) != 0)
+- BUG();
+- evtchn = bind_virq.port;
+-
+- irq = find_unbound_irq();
+-
+- dynamic_irq_init(irq);
+- set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
+- handle_level_irq, "virq");
+-
+- evtchn_to_irq[evtchn] = irq;
+- irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn);
+-
+- per_cpu(virq_to_irq, cpu)[virq] = irq;
+-
+- bind_evtchn_to_cpu(evtchn, cpu);
+- }
+-
+- irq_bindcount[irq]++;
+-
+- spin_unlock(&irq_mapping_update_lock);
+-
+- return irq;
+-}
+-
+-static void unbind_from_irq(unsigned int irq)
+-{
+- struct evtchn_close close;
+- int evtchn = evtchn_from_irq(irq);
+-
+- spin_lock(&irq_mapping_update_lock);
+-
+- if (VALID_EVTCHN(evtchn) && (--irq_bindcount[irq] == 0)) {
+- close.port = evtchn;
+- if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
+- BUG();
+-
+- switch (type_from_irq(irq)) {
+- case IRQT_VIRQ:
+- per_cpu(virq_to_irq, cpu_from_evtchn(evtchn))
+- [index_from_irq(irq)] = -1;
+- break;
+- default:
+- break;
+- }
+-
+- /* Closed ports are implicitly re-bound to VCPU0. */
+- bind_evtchn_to_cpu(evtchn, 0);
+-
+- evtchn_to_irq[evtchn] = -1;
+- irq_info[irq] = IRQ_UNBOUND;
+-
+- dynamic_irq_init(irq);
+- }
+-
+- spin_unlock(&irq_mapping_update_lock);
+-}
+-
+-int bind_evtchn_to_irqhandler(unsigned int evtchn,
+- irq_handler_t handler,
+- unsigned long irqflags,
+- const char *devname, void *dev_id)
+-{
+- unsigned int irq;
+- int retval;
+-
+- irq = bind_evtchn_to_irq(evtchn);
+- retval = request_irq(irq, handler, irqflags, devname, dev_id);
+- if (retval != 0) {
+- unbind_from_irq(irq);
+- return retval;
+- }
+-
+- return irq;
+-}
+-EXPORT_SYMBOL_GPL(bind_evtchn_to_irqhandler);
+-
+-int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu,
+- irq_handler_t handler,
+- unsigned long irqflags, const char *devname, void *dev_id)
+-{
+- unsigned int irq;
+- int retval;
+-
+- irq = bind_virq_to_irq(virq, cpu);
+- retval = request_irq(irq, handler, irqflags, devname, dev_id);
+- if (retval != 0) {
+- unbind_from_irq(irq);
+- return retval;
+- }
+-
+- return irq;
+-}
+-EXPORT_SYMBOL_GPL(bind_virq_to_irqhandler);
+-
+-int bind_ipi_to_irqhandler(enum ipi_vector ipi,
+- unsigned int cpu,
+- irq_handler_t handler,
+- unsigned long irqflags,
+- const char *devname,
+- void *dev_id)
+-{
+- int irq, retval;
+-
+- irq = bind_ipi_to_irq(ipi, cpu);
+- if (irq < 0)
+- return irq;
+-
+- retval = request_irq(irq, handler, irqflags, devname, dev_id);
+- if (retval != 0) {
+- unbind_from_irq(irq);
+- return retval;
+- }
+-
+- return irq;
+-}
+-
+-void unbind_from_irqhandler(unsigned int irq, void *dev_id)
+-{
+- free_irq(irq, dev_id);
+- unbind_from_irq(irq);
+-}
+-EXPORT_SYMBOL_GPL(unbind_from_irqhandler);
+-
+-void xen_send_IPI_one(unsigned int cpu, enum ipi_vector vector)
+-{
+- int irq = per_cpu(ipi_to_irq, cpu)[vector];
+- BUG_ON(irq < 0);
+- notify_remote_via_irq(irq);
+-}
+-
+-
+-/*
+- * Search the CPUs pending events bitmasks. For each one found, map
+- * the event number to an irq, and feed it into do_IRQ() for
+- * handling.
+- *
+- * Xen uses a two-level bitmap to speed searching. The first level is
+- * a bitset of words which contain pending event bits. The second
+- * level is a bitset of pending events themselves.
+- */
+-void xen_evtchn_do_upcall(struct pt_regs *regs)
+-{
+- int cpu = get_cpu();
+- struct shared_info *s = HYPERVISOR_shared_info;
+- struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu);
+- unsigned long pending_words;
+-
+- vcpu_info->evtchn_upcall_pending = 0;
+-
+- /* NB. No need for a barrier here -- XCHG is a barrier on x86. */
+- pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0);
+- while (pending_words != 0) {
+- unsigned long pending_bits;
+- int word_idx = __ffs(pending_words);
+- pending_words &= ~(1UL << word_idx);
+-
+- while ((pending_bits = active_evtchns(cpu, s, word_idx)) != 0) {
+- int bit_idx = __ffs(pending_bits);
+- int port = (word_idx * BITS_PER_LONG) + bit_idx;
+- int irq = evtchn_to_irq[port];
+-
+- if (irq != -1) {
+- regs->orig_ax = ~irq;
+- do_IRQ(regs);
+- }
+- }
+- }
+-
+- put_cpu();
+-}
+-
+-/* Rebind an evtchn so that it gets delivered to a specific cpu */
+-static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
+-{
+- struct evtchn_bind_vcpu bind_vcpu;
+- int evtchn = evtchn_from_irq(irq);
+-
+- if (!VALID_EVTCHN(evtchn))
+- return;
+-
+- /* Send future instances of this interrupt to other vcpu. */
+- bind_vcpu.port = evtchn;
+- bind_vcpu.vcpu = tcpu;
+-
+- /*
+- * If this fails, it usually just indicates that we're dealing with a
+- * virq or IPI channel, which don't actually need to be rebound. Ignore
+- * it, but don't do the xenlinux-level rebind in that case.
+- */
+- if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0)
+- bind_evtchn_to_cpu(evtchn, tcpu);
+-}
+-
+-
+-static void set_affinity_irq(unsigned irq, cpumask_t dest)
+-{
+- unsigned tcpu = first_cpu(dest);
+- rebind_irq_to_cpu(irq, tcpu);
+-}
+-
+-static void enable_dynirq(unsigned int irq)
+-{
+- int evtchn = evtchn_from_irq(irq);
+-
+- if (VALID_EVTCHN(evtchn))
+- unmask_evtchn(evtchn);
+-}
+-
+-static void disable_dynirq(unsigned int irq)
+-{
+- int evtchn = evtchn_from_irq(irq);
+-
+- if (VALID_EVTCHN(evtchn))
+- mask_evtchn(evtchn);
+-}
+-
+-static void ack_dynirq(unsigned int irq)
+-{
+- int evtchn = evtchn_from_irq(irq);
+-
+- move_native_irq(irq);
+-
+- if (VALID_EVTCHN(evtchn))
+- clear_evtchn(evtchn);
+-}
+-
+-static int retrigger_dynirq(unsigned int irq)
+-{
+- int evtchn = evtchn_from_irq(irq);
+- int ret = 0;
+-
+- if (VALID_EVTCHN(evtchn)) {
+- set_evtchn(evtchn);
+- ret = 1;
+- }
+-
+- return ret;
+-}
+-
+-static struct irq_chip xen_dynamic_chip __read_mostly = {
+- .name = "xen-dyn",
+- .mask = disable_dynirq,
+- .unmask = enable_dynirq,
+- .ack = ack_dynirq,
+- .set_affinity = set_affinity_irq,
+- .retrigger = retrigger_dynirq,
+-};
+-
+-void __init xen_init_IRQ(void)
+-{
+- int i;
+-
+- init_evtchn_cpu_bindings();
+-
+- /* No event channels are 'live' right now. */
+- for (i = 0; i < NR_EVENT_CHANNELS; i++)
+- mask_evtchn(i);
+-
+- /* Dynamic IRQ space is currently unbound. Zero the refcnts. */
+- for (i = 0; i < NR_IRQS; i++)
+- irq_bindcount[i] = 0;
+-
+- irq_ctx_init(smp_processor_id());
+-}
+diff --git a/arch/x86/xen/features.c b/arch/x86/xen/features.c
+deleted file mode 100644
+index 0707714..0000000
+--- a/arch/x86/xen/features.c
++++ /dev/null
+@@ -1,29 +0,0 @@
+-/******************************************************************************
+- * features.c
+- *
+- * Xen feature flags.
+- *
+- * Copyright (c) 2006, Ian Campbell, XenSource Inc.
+- */
+-#include <linux/types.h>
+-#include <linux/cache.h>
+-#include <linux/module.h>
+-#include <asm/xen/hypervisor.h>
+-#include <xen/features.h>
+-
+-u8 xen_features[XENFEAT_NR_SUBMAPS * 32] __read_mostly;
+-EXPORT_SYMBOL_GPL(xen_features);
+-
+-void xen_setup_features(void)
+-{
+- struct xen_feature_info fi;
+- int i, j;
+-
+- for (i = 0; i < XENFEAT_NR_SUBMAPS; i++) {
+- fi.submap_idx = i;
+- if (HYPERVISOR_xen_version(XENVER_get_features, &fi) < 0)
+- break;
+- for (j = 0; j < 32; j++)
+- xen_features[i * 32 + j] = !!(fi.submap & 1<<j);
+- }
+-}
+diff --git a/arch/x86/xen/grant-table.c b/arch/x86/xen/grant-table.c
+new file mode 100644
+index 0000000..49ba9b5
+--- /dev/null
++++ b/arch/x86/xen/grant-table.c
+@@ -0,0 +1,91 @@
++/******************************************************************************
++ * grant_table.c
++ * x86 specific part
++ *
++ * Granting foreign access to our memory reservation.
++ *
++ * Copyright (c) 2005-2006, Christopher Clark
++ * Copyright (c) 2004-2005, K A Fraser
++ * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
++ * VA Linux Systems Japan. Split out x86 specific part.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/vmalloc.h>
++
++#include <xen/interface/xen.h>
++#include <xen/page.h>
++#include <xen/grant_table.h>
++
++#include <asm/pgtable.h>
++
++static int map_pte_fn(pte_t *pte, struct page *pmd_page,
++ unsigned long addr, void *data)
++{
++ unsigned long **frames = (unsigned long **)data;
++
++ set_pte_at(&init_mm, addr, pte, mfn_pte((*frames)[0], PAGE_KERNEL));
++ (*frames)++;
++ return 0;
++}
++
++static int unmap_pte_fn(pte_t *pte, struct page *pmd_page,
++ unsigned long addr, void *data)
++{
++
++ set_pte_at(&init_mm, addr, pte, __pte(0));
++ return 0;
++}
++
++int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
++ unsigned long max_nr_gframes,
++ struct grant_entry **__shared)
++{
++ int rc;
++ struct grant_entry *shared = *__shared;
++
++ if (shared == NULL) {
++ struct vm_struct *area =
++ xen_alloc_vm_area(PAGE_SIZE * max_nr_gframes);
++ BUG_ON(area == NULL);
++ shared = area->addr;
++ *__shared = shared;
++ }
++
++ rc = apply_to_page_range(&init_mm, (unsigned long)shared,
++ PAGE_SIZE * nr_gframes,
++ map_pte_fn, &frames);
++ return rc;
++}
++
++void arch_gnttab_unmap_shared(struct grant_entry *shared,
++ unsigned long nr_gframes)
++{
++ apply_to_page_range(&init_mm, (unsigned long)shared,
++ PAGE_SIZE * nr_gframes, unmap_pte_fn, NULL);
++}
+diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
+index 2a054ef..6cbcf65 100644
+--- a/arch/x86/xen/mmu.c
++++ b/arch/x86/xen/mmu.c
+@@ -156,6 +156,10 @@ void set_pte_mfn(unsigned long vaddr, unsigned long mfn, pgprot_t flags)
+ void xen_set_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pteval)
+ {
++ /* updates to init_mm may be done without lock */
++ if (mm == &init_mm)
++ preempt_disable();
++
+ if (mm == current->mm || mm == &init_mm) {
+ if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) {
+ struct multicall_space mcs;
+@@ -163,14 +167,61 @@ void xen_set_pte_at(struct mm_struct *mm, unsigned long addr,
+
+ MULTI_update_va_mapping(mcs.mc, addr, pteval, 0);
+ xen_mc_issue(PARAVIRT_LAZY_MMU);
+- return;
++ goto out;
+ } else
+ if (HYPERVISOR_update_va_mapping(addr, pteval, 0) == 0)
+- return;
++ goto out;
+ }
+ xen_set_pte(ptep, pteval);
++
++out:
++ if (mm == &init_mm)
++ preempt_enable();
++}
++
++pteval_t xen_pte_val(pte_t pte)
++{
++ pteval_t ret = pte.pte;
++
++ if (ret & _PAGE_PRESENT)
++ ret = machine_to_phys(XMADDR(ret)).paddr | _PAGE_PRESENT;
++
++ return ret;
++}
++
++pgdval_t xen_pgd_val(pgd_t pgd)
++{
++ pgdval_t ret = pgd.pgd;
++ if (ret & _PAGE_PRESENT)
++ ret = machine_to_phys(XMADDR(ret)).paddr | _PAGE_PRESENT;
++ return ret;
++}
++
++pte_t xen_make_pte(pteval_t pte)
++{
++ if (pte & _PAGE_PRESENT) {
++ pte = phys_to_machine(XPADDR(pte)).maddr;
++ pte &= ~(_PAGE_PCD | _PAGE_PWT);
++ }
++
++ return (pte_t){ .pte = pte };
+ }
+
++pgd_t xen_make_pgd(pgdval_t pgd)
++{
++ if (pgd & _PAGE_PRESENT)
++ pgd = phys_to_machine(XPADDR(pgd)).maddr;
++
++ return (pgd_t){ pgd };
++}
++
++pmdval_t xen_pmd_val(pmd_t pmd)
++{
++ pmdval_t ret = native_pmd_val(pmd);
++ if (ret & _PAGE_PRESENT)
++ ret = machine_to_phys(XMADDR(ret)).paddr | _PAGE_PRESENT;
++ return ret;
++}
+ #ifdef CONFIG_X86_PAE
+ void xen_set_pud(pud_t *ptr, pud_t val)
+ {
+@@ -214,100 +265,18 @@ void xen_pmd_clear(pmd_t *pmdp)
+ xen_set_pmd(pmdp, __pmd(0));
+ }
+
+-unsigned long long xen_pte_val(pte_t pte)
++pmd_t xen_make_pmd(pmdval_t pmd)
+ {
+- unsigned long long ret = 0;
+-
+- if (pte.pte_low) {
+- ret = ((unsigned long long)pte.pte_high << 32) | pte.pte_low;
+- ret = machine_to_phys(XMADDR(ret)).paddr | 1;
+- }
+-
+- return ret;
+-}
+-
+-unsigned long long xen_pmd_val(pmd_t pmd)
+-{
+- unsigned long long ret = pmd.pmd;
+- if (ret)
+- ret = machine_to_phys(XMADDR(ret)).paddr | 1;
+- return ret;
+-}
+-
+-unsigned long long xen_pgd_val(pgd_t pgd)
+-{
+- unsigned long long ret = pgd.pgd;
+- if (ret)
+- ret = machine_to_phys(XMADDR(ret)).paddr | 1;
+- return ret;
+-}
+-
+-pte_t xen_make_pte(unsigned long long pte)
+-{
+- if (pte & _PAGE_PRESENT) {
+- pte = phys_to_machine(XPADDR(pte)).maddr;
+- pte &= ~(_PAGE_PCD | _PAGE_PWT);
+- }
+-
+- return (pte_t){ .pte = pte };
+-}
+-
+-pmd_t xen_make_pmd(unsigned long long pmd)
+-{
+- if (pmd & 1)
++ if (pmd & _PAGE_PRESENT)
+ pmd = phys_to_machine(XPADDR(pmd)).maddr;
+
+- return (pmd_t){ pmd };
+-}
+-
+-pgd_t xen_make_pgd(unsigned long long pgd)
+-{
+- if (pgd & _PAGE_PRESENT)
+- pgd = phys_to_machine(XPADDR(pgd)).maddr;
+-
+- return (pgd_t){ pgd };
++ return native_make_pmd(pmd);
+ }
+ #else /* !PAE */
+ void xen_set_pte(pte_t *ptep, pte_t pte)
+ {
+ *ptep = pte;
+ }
+-
+-unsigned long xen_pte_val(pte_t pte)
+-{
+- unsigned long ret = pte.pte_low;
+-
+- if (ret & _PAGE_PRESENT)
+- ret = machine_to_phys(XMADDR(ret)).paddr;
+-
+- return ret;
+-}
+-
+-unsigned long xen_pgd_val(pgd_t pgd)
+-{
+- unsigned long ret = pgd.pgd;
+- if (ret)
+- ret = machine_to_phys(XMADDR(ret)).paddr | 1;
+- return ret;
+-}
+-
+-pte_t xen_make_pte(unsigned long pte)
+-{
+- if (pte & _PAGE_PRESENT) {
+- pte = phys_to_machine(XPADDR(pte)).maddr;
+- pte &= ~(_PAGE_PCD | _PAGE_PWT);
+- }
+-
+- return (pte_t){ pte };
+-}
+-
+-pgd_t xen_make_pgd(unsigned long pgd)
+-{
+- if (pgd & _PAGE_PRESENT)
+- pgd = phys_to_machine(XPADDR(pgd)).maddr;
+-
+- return (pgd_t){ pgd };
+-}
+ #endif /* CONFIG_X86_PAE */
+
+ /*
+diff --git a/arch/x86/xen/multicalls.c b/arch/x86/xen/multicalls.c
+index 5e6f36f..5791eb2 100644
+--- a/arch/x86/xen/multicalls.c
++++ b/arch/x86/xen/multicalls.c
+@@ -76,7 +76,7 @@ void xen_mc_flush(void)
+ if (ret) {
+ printk(KERN_ERR "%d multicall(s) failed: cpu %d\n",
+ ret, smp_processor_id());
+- for(i = 0; i < b->mcidx; i++) {
++ for (i = 0; i < b->mcidx; i++) {
+ printk(" call %2d/%d: op=%lu arg=[%lx] result=%ld\n",
+ i+1, b->mcidx,
+ b->debug[i].op,
+@@ -93,7 +93,7 @@ void xen_mc_flush(void)
+
+ local_irq_restore(flags);
+
+- for(i = 0; i < b->cbidx; i++) {
++ for (i = 0; i < b->cbidx; i++) {
+ struct callback *cb = &b->callbacks[i];
+
+ (*cb->fn)(cb->data);
+diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
+index 2341492..82517e4 100644
+--- a/arch/x86/xen/setup.c
++++ b/arch/x86/xen/setup.c
+@@ -16,6 +16,7 @@
+ #include <asm/xen/hypervisor.h>
+ #include <asm/xen/hypercall.h>
+
++#include <xen/interface/callback.h>
+ #include <xen/interface/physdev.h>
+ #include <xen/features.h>
+
+@@ -68,6 +69,24 @@ static void __init fiddle_vdso(void)
+ *mask |= 1 << VDSO_NOTE_NONEGSEG_BIT;
+ }
+
++void xen_enable_sysenter(void)
++{
++ int cpu = smp_processor_id();
++ extern void xen_sysenter_target(void);
++ /* Mask events on entry, even though they get enabled immediately */
++ static struct callback_register sysenter = {
++ .type = CALLBACKTYPE_sysenter,
++ .address = { __KERNEL_CS, (unsigned long)xen_sysenter_target },
++ .flags = CALLBACKF_mask_events,
++ };
++
++ if (!boot_cpu_has(X86_FEATURE_SEP) ||
++ HYPERVISOR_callback_op(CALLBACKOP_register, &sysenter) != 0) {
++ clear_cpu_cap(&cpu_data(cpu), X86_FEATURE_SEP);
++ clear_cpu_cap(&boot_cpu_data, X86_FEATURE_SEP);
++ }
++}
++
+ void __init xen_arch_setup(void)
+ {
+ struct physdev_set_iopl set_iopl;
+@@ -82,6 +101,8 @@ void __init xen_arch_setup(void)
+ HYPERVISOR_set_callbacks(__KERNEL_CS, (unsigned long)xen_hypervisor_callback,
+ __KERNEL_CS, (unsigned long)xen_failsafe_callback);
+
++ xen_enable_sysenter();
++
+ set_iopl.iopl = 1;
+ rc = HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl);
+ if (rc != 0)
+diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
+index aafc544..94e6900 100644
+--- a/arch/x86/xen/smp.c
++++ b/arch/x86/xen/smp.c
+@@ -35,9 +35,10 @@
+ #include "xen-ops.h"
+ #include "mmu.h"
+
+-static cpumask_t cpu_initialized_map;
+-static DEFINE_PER_CPU(int, resched_irq);
+-static DEFINE_PER_CPU(int, callfunc_irq);
++static cpumask_t xen_cpu_initialized_map;
++static DEFINE_PER_CPU(int, resched_irq) = -1;
++static DEFINE_PER_CPU(int, callfunc_irq) = -1;
++static DEFINE_PER_CPU(int, debug_irq) = -1;
+
+ /*
+ * Structure and data for smp_call_function(). This is designed to minimise
+@@ -72,6 +73,7 @@ static __cpuinit void cpu_bringup_and_idle(void)
+ int cpu = smp_processor_id();
+
+ cpu_init();
++ xen_enable_sysenter();
+
+ preempt_disable();
+ per_cpu(cpu_state, cpu) = CPU_ONLINE;
+@@ -88,9 +90,7 @@ static __cpuinit void cpu_bringup_and_idle(void)
+ static int xen_smp_intr_init(unsigned int cpu)
+ {
+ int rc;
+- const char *resched_name, *callfunc_name;
+-
+- per_cpu(resched_irq, cpu) = per_cpu(callfunc_irq, cpu) = -1;
++ const char *resched_name, *callfunc_name, *debug_name;
+
+ resched_name = kasprintf(GFP_KERNEL, "resched%d", cpu);
+ rc = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR,
+@@ -114,6 +114,14 @@ static int xen_smp_intr_init(unsigned int cpu)
+ goto fail;
+ per_cpu(callfunc_irq, cpu) = rc;
+
++ debug_name = kasprintf(GFP_KERNEL, "debug%d", cpu);
++ rc = bind_virq_to_irqhandler(VIRQ_DEBUG, cpu, xen_debug_interrupt,
++ IRQF_DISABLED | IRQF_PERCPU | IRQF_NOBALANCING,
++ debug_name, NULL);
++ if (rc < 0)
++ goto fail;
++ per_cpu(debug_irq, cpu) = rc;
++
+ return 0;
+
+ fail:
+@@ -121,6 +129,8 @@ static int xen_smp_intr_init(unsigned int cpu)
+ unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL);
+ if (per_cpu(callfunc_irq, cpu) >= 0)
+ unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
++ if (per_cpu(debug_irq, cpu) >= 0)
++ unbind_from_irqhandler(per_cpu(debug_irq, cpu), NULL);
+ return rc;
+ }
+
+@@ -179,11 +189,11 @@ void __init xen_smp_prepare_cpus(unsigned int max_cpus)
+ if (xen_smp_intr_init(0))
+ BUG();
+
+- cpu_initialized_map = cpumask_of_cpu(0);
++ xen_cpu_initialized_map = cpumask_of_cpu(0);
+
+ /* Restrict the possible_map according to max_cpus. */
+ while ((num_possible_cpus() > 1) && (num_possible_cpus() > max_cpus)) {
+- for (cpu = NR_CPUS-1; !cpu_isset(cpu, cpu_possible_map); cpu--)
++ for (cpu = NR_CPUS - 1; !cpu_possible(cpu); cpu--)
+ continue;
+ cpu_clear(cpu, cpu_possible_map);
+ }
+@@ -210,7 +220,7 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle)
+ struct vcpu_guest_context *ctxt;
+ struct gdt_page *gdt = &per_cpu(gdt_page, cpu);
+
+- if (cpu_test_and_set(cpu, cpu_initialized_map))
++ if (cpu_test_and_set(cpu, xen_cpu_initialized_map))
+ return 0;
+
+ ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
+diff --git a/arch/x86/xen/xen-asm.S b/arch/x86/xen/xen-asm.S
+index 6b71904..2497a30 100644
+--- a/arch/x86/xen/xen-asm.S
++++ b/arch/x86/xen/xen-asm.S
+@@ -108,6 +108,20 @@ ENDPATCH(xen_restore_fl_direct)
+ RELOC(xen_restore_fl_direct, 2b+1)
+
+ /*
++ We can't use sysexit directly, because we're not running in ring0.
++ But we can easily fake it up using iret. Assuming xen_sysexit
++ is jumped to with a standard stack frame, we can just strip it
++ back to a standard iret frame and use iret.
++ */
++ENTRY(xen_sysexit)
++ movl PT_EAX(%esp), %eax /* Shouldn't be necessary? */
++ orl $X86_EFLAGS_IF, PT_EFLAGS(%esp)
++ lea PT_EIP(%esp), %esp
++
++ jmp xen_iret
++ENDPROC(xen_sysexit)
++
++/*
+ This is run where a normal iret would be run, with the same stack setup:
+ 8: eflags
+ 4: cs
+@@ -135,13 +149,8 @@ ENDPATCH(xen_restore_fl_direct)
+ current stack state in whatever form its in, we keep things
+ simple by only using a single register which is pushed/popped
+ on the stack.
+-
+- Non-direct iret could be done in the same way, but it would
+- require an annoying amount of code duplication. We'll assume
+- that direct mode will be the common case once the hypervisor
+- support becomes commonplace.
+ */
+-ENTRY(xen_iret_direct)
++ENTRY(xen_iret)
+ /* test eflags for special cases */
+ testl $(X86_EFLAGS_VM | XEN_EFLAGS_NMI), 8(%esp)
+ jnz hyper_iret
+@@ -155,9 +164,9 @@ ENTRY(xen_iret_direct)
+ GET_THREAD_INFO(%eax)
+ movl TI_cpu(%eax),%eax
+ movl __per_cpu_offset(,%eax,4),%eax
+- lea per_cpu__xen_vcpu_info(%eax),%eax
++ mov per_cpu__xen_vcpu(%eax),%eax
+ #else
+- movl $per_cpu__xen_vcpu_info, %eax
++ movl per_cpu__xen_vcpu, %eax
+ #endif
+
+ /* check IF state we're restoring */
+@@ -189,8 +198,12 @@ iret_restore_end:
+ region is OK. */
+ je xen_hypervisor_callback
+
+- iret
++1: iret
+ xen_iret_end_crit:
++.section __ex_table,"a"
++ .align 4
++ .long 1b,iret_exc
++.previous
+
+ hyper_iret:
+ /* put this out of line since its very rarely used */
+@@ -224,9 +237,7 @@ hyper_iret:
+ ds } SAVE_ALL state
+ eax }
+ : :
+- ebx }
+- ----------------
+- return addr <- esp
++ ebx }<- esp
+ ----------------
+
+ In order to deliver the nested exception properly, we need to shift
+@@ -241,10 +252,8 @@ hyper_iret:
+ it's usermode state which we eventually need to restore.
+ */
+ ENTRY(xen_iret_crit_fixup)
+- /* offsets +4 for return address */
+-
+ /*
+- Paranoia: Make sure we're really coming from userspace.
++ Paranoia: Make sure we're really coming from kernel space.
+ One could imagine a case where userspace jumps into the
+ critical range address, but just before the CPU delivers a GP,
+ it decides to deliver an interrupt instead. Unlikely?
+@@ -253,32 +262,32 @@ ENTRY(xen_iret_crit_fixup)
+ jump instruction itself, not the destination, but some virtual
+ environments get this wrong.
+ */
+- movl PT_CS+4(%esp), %ecx
++ movl PT_CS(%esp), %ecx
+ andl $SEGMENT_RPL_MASK, %ecx
+ cmpl $USER_RPL, %ecx
+ je 2f
+
+- lea PT_ORIG_EAX+4(%esp), %esi
+- lea PT_EFLAGS+4(%esp), %edi
++ lea PT_ORIG_EAX(%esp), %esi
++ lea PT_EFLAGS(%esp), %edi
+
+ /* If eip is before iret_restore_end then stack
+ hasn't been restored yet. */
+ cmp $iret_restore_end, %eax
+ jae 1f
+
+- movl 0+4(%edi),%eax /* copy EAX */
+- movl %eax, PT_EAX+4(%esp)
++ movl 0+4(%edi),%eax /* copy EAX (just above top of frame) */
++ movl %eax, PT_EAX(%esp)
+
+ lea ESP_OFFSET(%edi),%edi /* move dest up over saved regs */
+
+ /* set up the copy */
+ 1: std
+- mov $(PT_EIP+4) / 4, %ecx /* copy ret+saved regs up to orig_eax */
++ mov $PT_EIP / 4, %ecx /* saved regs up to orig_eax */
+ rep movsl
+ cld
+
+ lea 4(%edi),%esp /* point esp to new frame */
+-2: ret
++2: jmp xen_do_upcall
+
+
+ /*
+diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
+index b02a909..f1063ae 100644
+--- a/arch/x86/xen/xen-ops.h
++++ b/arch/x86/xen/xen-ops.h
+@@ -2,6 +2,8 @@
+ #define XEN_OPS_H
+
+ #include <linux/init.h>
++#include <linux/irqreturn.h>
++#include <xen/xen-ops.h>
+
+ /* These are code, but not functions. Defined in entry.S */
+ extern const char xen_hypervisor_callback[];
+@@ -9,7 +11,6 @@ extern const char xen_failsafe_callback[];
+
+ void xen_copy_trap_info(struct trap_info *traps);
+
+-DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu);
+ DECLARE_PER_CPU(unsigned long, xen_cr3);
+ DECLARE_PER_CPU(unsigned long, xen_current_cr3);
+
+@@ -19,6 +20,7 @@ extern struct shared_info *HYPERVISOR_shared_info;
+ char * __init xen_memory_setup(void);
+ void __init xen_arch_setup(void);
+ void __init xen_init_IRQ(void);
++void xen_enable_sysenter(void);
+
+ void xen_setup_timer(int cpu);
+ void xen_setup_cpu_clockevents(void);
+@@ -28,6 +30,8 @@ unsigned long xen_get_wallclock(void);
+ int xen_set_wallclock(unsigned long time);
+ unsigned long long xen_sched_clock(void);
+
++irqreturn_t xen_debug_interrupt(int irq, void *dev_id);
++
+ bool xen_vcpu_stolen(int vcpu);
+
+ void xen_mark_init_mm_pinned(void);
+@@ -63,5 +67,7 @@ DECL_ASM(void, xen_irq_disable_direct, void);
+ DECL_ASM(unsigned long, xen_save_fl_direct, void);
+ DECL_ASM(void, xen_restore_fl_direct, unsigned long);
+
+-void xen_iret_direct(void);
++void xen_iret(void);
++void xen_sysexit(void);
++
+ #endif /* XEN_OPS_H */
+diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
+index f582d6a..7419dbc 100644
+--- a/arch/xtensa/kernel/Makefile
++++ b/arch/xtensa/kernel/Makefile
+@@ -5,7 +5,7 @@
+ extra-y := head.o vmlinux.lds
+
+
+-obj-y := align.o entry.o irq.o coprocessor.o process.o ptrace.o semaphore.o \
++obj-y := align.o entry.o irq.o coprocessor.o process.o ptrace.o \
+ setup.o signal.o syscall.o time.o traps.o vectors.o platform.o \
+ pci-dma.o init_task.o io.o
+
+diff --git a/arch/xtensa/kernel/semaphore.c b/arch/xtensa/kernel/semaphore.c
+deleted file mode 100644
+index 995c641..0000000
+--- a/arch/xtensa/kernel/semaphore.c
++++ /dev/null
+@@ -1,226 +0,0 @@
+-/*
+- * arch/xtensa/kernel/semaphore.c
+- *
+- * Generic semaphore code. Buyer beware. Do your own specific changes
+- * in <asm/semaphore-helper.h>
+- *
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License. See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (C) 2001 - 2005 Tensilica Inc.
+- *
+- * Joe Taylor <joe at tensilica.com, joetylr at yahoo.com>
+- * Chris Zankel <chris at zankel.net>
+- * Marc Gauthier<marc at tensilica.com, marc at alumni.uwaterloo.ca>
+- * Kevin Chea
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/wait.h>
+-#include <linux/init.h>
+-#include <asm/semaphore.h>
+-#include <asm/errno.h>
+-
+-/*
+- * These two _must_ execute atomically wrt each other.
+- */
+-
+-static __inline__ void wake_one_more(struct semaphore * sem)
+-{
+- atomic_inc((atomic_t *)&sem->sleepers);
+-}
+-
+-static __inline__ int waking_non_zero(struct semaphore *sem)
+-{
+- unsigned long flags;
+- int ret = 0;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- if (sem->sleepers > 0) {
+- sem->sleepers--;
+- ret = 1;
+- }
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+- return ret;
+-}
+-
+-/*
+- * waking_non_zero_interruptible:
+- * 1 got the lock
+- * 0 go to sleep
+- * -EINTR interrupted
+- *
+- * We must undo the sem->count down_interruptible() increment while we are
+- * protected by the spinlock in order to make atomic this atomic_inc() with the
+- * atomic_read() in wake_one_more(), otherwise we can race. -arca
+- */
+-
+-static __inline__ int waking_non_zero_interruptible(struct semaphore *sem,
+- struct task_struct *tsk)
+-{
+- unsigned long flags;
+- int ret = 0;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- if (sem->sleepers > 0) {
+- sem->sleepers--;
+- ret = 1;
+- } else if (signal_pending(tsk)) {
+- atomic_inc(&sem->count);
+- ret = -EINTR;
+- }
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+- return ret;
+-}
+-
+-/*
+- * waking_non_zero_trylock:
+- * 1 failed to lock
+- * 0 got the lock
+- *
+- * We must undo the sem->count down_trylock() increment while we are
+- * protected by the spinlock in order to make atomic this atomic_inc() with the
+- * atomic_read() in wake_one_more(), otherwise we can race. -arca
+- */
+-
+-static __inline__ int waking_non_zero_trylock(struct semaphore *sem)
+-{
+- unsigned long flags;
+- int ret = 1;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- if (sem->sleepers <= 0)
+- atomic_inc(&sem->count);
+- else {
+- sem->sleepers--;
+- ret = 0;
+- }
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+- return ret;
+-}
+-
+-DEFINE_SPINLOCK(semaphore_wake_lock);
+-
+-/*
+- * Semaphores are implemented using a two-way counter:
+- * The "count" variable is decremented for each process
+- * that tries to sleep, while the "waking" variable is
+- * incremented when the "up()" code goes to wake up waiting
+- * processes.
+- *
+- * Notably, the inline "up()" and "down()" functions can
+- * efficiently test if they need to do any extra work (up
+- * needs to do something only if count was negative before
+- * the increment operation.
+- *
+- * waking_non_zero() (from asm/semaphore.h) must execute
+- * atomically.
+- *
+- * When __up() is called, the count was negative before
+- * incrementing it, and we need to wake up somebody.
+- *
+- * This routine adds one to the count of processes that need to
+- * wake up and exit. ALL waiting processes actually wake up but
+- * only the one that gets to the "waking" field first will gate
+- * through and acquire the semaphore. The others will go back
+- * to sleep.
+- *
+- * Note that these functions are only called when there is
+- * contention on the lock, and as such all this is the
+- * "non-critical" part of the whole semaphore business. The
+- * critical part is the inline stuff in <asm/semaphore.h>
+- * where we want to avoid any extra jumps and calls.
+- */
+-
+-void __up(struct semaphore *sem)
+-{
+- wake_one_more(sem);
+- wake_up(&sem->wait);
+-}
+-
+-/*
+- * Perform the "down" function. Return zero for semaphore acquired,
+- * return negative for signalled out of the function.
+- *
+- * If called from __down, the return is ignored and the wait loop is
+- * not interruptible. This means that a task waiting on a semaphore
+- * using "down()" cannot be killed until someone does an "up()" on
+- * the semaphore.
+- *
+- * If called from __down_interruptible, the return value gets checked
+- * upon return. If the return value is negative then the task continues
+- * with the negative value in the return register (it can be tested by
+- * the caller).
+- *
+- * Either form may be used in conjunction with "up()".
+- *
+- */
+-
+-#define DOWN_VAR \
+- struct task_struct *tsk = current; \
+- wait_queue_t wait; \
+- init_waitqueue_entry(&wait, tsk);
+-
+-#define DOWN_HEAD(task_state) \
+- \
+- \
+- tsk->state = (task_state); \
+- add_wait_queue(&sem->wait, &wait); \
+- \
+- /* \
+- * Ok, we're set up. sem->count is known to be less than zero \
+- * so we must wait. \
+- * \
+- * We can let go the lock for purposes of waiting. \
+- * We re-acquire it after awaking so as to protect \
+- * all semaphore operations. \
+- * \
+- * If "up()" is called before we call waking_non_zero() then \
+- * we will catch it right away. If it is called later then \
+- * we will have to go through a wakeup cycle to catch it. \
+- * \
+- * Multiple waiters contend for the semaphore lock to see \
+- * who gets to gate through and who has to wait some more. \
+- */ \
+- for (;;) {
+-
+-#define DOWN_TAIL(task_state) \
+- tsk->state = (task_state); \
+- } \
+- tsk->state = TASK_RUNNING; \
+- remove_wait_queue(&sem->wait, &wait);
+-
+-void __sched __down(struct semaphore * sem)
+-{
+- DOWN_VAR
+- DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+- if (waking_non_zero(sem))
+- break;
+- schedule();
+- DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+-}
+-
+-int __sched __down_interruptible(struct semaphore * sem)
+-{
+- int ret = 0;
+- DOWN_VAR
+- DOWN_HEAD(TASK_INTERRUPTIBLE)
+-
+- ret = waking_non_zero_interruptible(sem, tsk);
+- if (ret)
+- {
+- if (ret == 1)
+- /* ret != 0 only if we get interrupted -arca */
+- ret = 0;
+- break;
+- }
+- schedule();
+- DOWN_TAIL(TASK_INTERRUPTIBLE)
+- return ret;
+-}
+-
+-int __down_trylock(struct semaphore * sem)
+-{
+- return waking_non_zero_trylock(sem);
+-}
+diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c
+index 60dbdb4..6e52cdd 100644
+--- a/arch/xtensa/kernel/xtensa_ksyms.c
++++ b/arch/xtensa/kernel/xtensa_ksyms.c
+@@ -26,7 +26,6 @@
+ #include <asm/io.h>
+ #include <asm/page.h>
+ #include <asm/pgalloc.h>
+-#include <asm/semaphore.h>
+ #ifdef CONFIG_BLK_DEV_FD
+ #include <asm/floppy.h>
+ #endif
+@@ -71,14 +70,6 @@ EXPORT_SYMBOL(__umodsi3);
+ EXPORT_SYMBOL(__udivdi3);
+ EXPORT_SYMBOL(__umoddi3);
+
+-/*
+- * Semaphore operations
+- */
+-EXPORT_SYMBOL(__down);
+-EXPORT_SYMBOL(__down_interruptible);
+-EXPORT_SYMBOL(__down_trylock);
+-EXPORT_SYMBOL(__up);
+-
+ #ifdef CONFIG_NET
+ /*
+ * Networking support
+diff --git a/block/Kconfig b/block/Kconfig
+index 7db9a41..3e97f2b 100644
+--- a/block/Kconfig
++++ b/block/Kconfig
+@@ -5,14 +5,18 @@ menuconfig BLOCK
+ bool "Enable the block layer" if EMBEDDED
+ default y
+ help
+- This permits the block layer to be removed from the kernel if it's not
+- needed (on some embedded devices for example). If this option is
+- disabled, then blockdev files will become unusable and some
+- filesystems (such as ext3) will become unavailable.
++ Provide block layer support for the kernel.
+
+- This option will also disable SCSI character devices and USB storage
+- since they make use of various block layer definitions and
+- facilities.
++ Disable this option to remove the block layer support from the
++ kernel. This may be useful for embedded devices.
++
++ If this option is disabled:
++
++ - block device files will become unusable
++ - some filesystems (such as ext3) will become unavailable.
++
++ Also, SCSI character devices and USB storage will be disabled since
++ they make use of various block layer definitions and facilities.
+
+ Say Y here unless you know you really don't want to mount disks and
+ suchlike.
+@@ -23,9 +27,20 @@ config LBD
+ bool "Support for Large Block Devices"
+ depends on !64BIT
+ help
+- Say Y here if you want to attach large (bigger than 2TB) discs to
+- your machine, or if you want to have a raid or loopback device
+- bigger than 2TB. Otherwise say N.
++ Enable block devices of size 2TB and larger.
++
++ This option is required to support the full capacity of large
++ (2TB+) block devices, including RAID, disk, Network Block Device,
++ Logical Volume Manager (LVM) and loopback.
++
++ For example, RAID devices are frequently bigger than the capacity
++ of the largest individual hard drive.
++
++ This option is not required if you have individual disk drives
++ which total 2TB+ and you are not aggregating the capacity into
++ a large block device (e.g. using RAID or LVM).
++
++ If unsure, say N.
+
+ config BLK_DEV_IO_TRACE
+ bool "Support for tracing block io actions"
+@@ -33,19 +48,21 @@ config BLK_DEV_IO_TRACE
+ select RELAY
+ select DEBUG_FS
+ help
+- Say Y here, if you want to be able to trace the block layer actions
++ Say Y here if you want to be able to trace the block layer actions
+ on a given queue. Tracing allows you to see any traffic happening
+- on a block device queue. For more information (and the user space
+- support tools needed), fetch the blktrace app from:
++ on a block device queue. For more information (and the userspace
++ support tools needed), fetch the blktrace tools from:
+
+ git://git.kernel.dk/blktrace.git
+
++ If unsure, say N.
++
+ config LSF
+ bool "Support for Large Single Files"
+ depends on !64BIT
+ help
+- Say Y here if you want to be able to handle very large files (bigger
+- than 2TB), otherwise say N.
++ Say Y here if you want to be able to handle very large files (2TB
++ and larger), otherwise say N.
+
+ If unsure, say Y.
+
+@@ -53,14 +70,16 @@ config BLK_DEV_BSG
+ bool "Block layer SG support v4 (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ ---help---
+- Saying Y here will enable generic SG (SCSI generic) v4 support
+- for any block device.
+-
+- Unlike SG v3 (aka block/scsi_ioctl.c drivers/scsi/sg.c), SG v4
+- can handle complicated SCSI commands: tagged variable length cdbs
+- with bidirectional data transfers and generic request/response
+- protocols (e.g. Task Management Functions and SMP in Serial
+- Attached SCSI).
++ Saying Y here will enable generic SG (SCSI generic) v4 support
++ for any block device.
++
++ Unlike SG v3 (aka block/scsi_ioctl.c drivers/scsi/sg.c), SG v4
++ can handle complicated SCSI commands: tagged variable length cdbs
++ with bidirectional data transfers and generic request/response
++ protocols (e.g. Task Management Functions and SMP in Serial
++ Attached SCSI).
++
++ If unsure, say N.
+
+ endif # BLOCK
+
+diff --git a/block/blk-map.c b/block/blk-map.c
+index c07d9c8..3c942bd 100644
+--- a/block/blk-map.c
++++ b/block/blk-map.c
+@@ -5,6 +5,7 @@
+ #include <linux/module.h>
+ #include <linux/bio.h>
+ #include <linux/blkdev.h>
++#include <scsi/sg.h> /* for struct sg_iovec */
+
+ #include "blk.h"
+
+@@ -140,25 +141,8 @@ int blk_rq_map_user(struct request_queue *q, struct request *rq,
+ ubuf += ret;
+ }
+
+- /*
+- * __blk_rq_map_user() copies the buffers if starting address
+- * or length isn't aligned to dma_pad_mask. As the copied
+- * buffer is always page aligned, we know that there's enough
+- * room for padding. Extend the last bio and update
+- * rq->data_len accordingly.
+- *
+- * On unmap, bio_uncopy_user() will use unmodified
+- * bio_map_data pointed to by bio->bi_private.
+- */
+- if (len & q->dma_pad_mask) {
+- unsigned int pad_len = (q->dma_pad_mask & ~len) + 1;
+- struct bio *tail = rq->biotail;
+-
+- tail->bi_io_vec[tail->bi_vcnt - 1].bv_len += pad_len;
+- tail->bi_size += pad_len;
+-
+- rq->extra_len += pad_len;
+- }
++ if (!bio_flagged(bio, BIO_USER_MAPPED))
++ rq->cmd_flags |= REQ_COPY_USER;
+
+ rq->buffer = rq->data = NULL;
+ return 0;
+@@ -194,15 +178,26 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
+ struct sg_iovec *iov, int iov_count, unsigned int len)
+ {
+ struct bio *bio;
++ int i, read = rq_data_dir(rq) == READ;
++ int unaligned = 0;
+
+ if (!iov || iov_count <= 0)
+ return -EINVAL;
+
+- /* we don't allow misaligned data like bio_map_user() does. If the
+- * user is using sg, they're expected to know the alignment constraints
+- * and respect them accordingly */
+- bio = bio_map_user_iov(q, NULL, iov, iov_count,
+- rq_data_dir(rq) == READ);
++ for (i = 0; i < iov_count; i++) {
++ unsigned long uaddr = (unsigned long)iov[i].iov_base;
++
++ if (uaddr & queue_dma_alignment(q)) {
++ unaligned = 1;
++ break;
++ }
++ }
++
++ if (unaligned || (q->dma_pad_mask & len))
++ bio = bio_copy_user_iov(q, iov, iov_count, read);
++ else
++ bio = bio_map_user_iov(q, NULL, iov, iov_count, read);
++
+ if (IS_ERR(bio))
+ return PTR_ERR(bio);
+
+@@ -212,6 +207,9 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
+ return -EINVAL;
+ }
+
++ if (!bio_flagged(bio, BIO_USER_MAPPED))
++ rq->cmd_flags |= REQ_COPY_USER;
++
+ bio_get(bio);
+ blk_rq_bio_prep(q, rq, bio);
+ rq->buffer = rq->data = NULL;
+diff --git a/block/blk-merge.c b/block/blk-merge.c
+index 0f58616..b5c5c4a 100644
+--- a/block/blk-merge.c
++++ b/block/blk-merge.c
+@@ -220,6 +220,15 @@ new_segment:
+ bvprv = bvec;
+ } /* segments in rq */
+
++
++ if (unlikely(rq->cmd_flags & REQ_COPY_USER) &&
++ (rq->data_len & q->dma_pad_mask)) {
++ unsigned int pad_len = (q->dma_pad_mask & ~rq->data_len) + 1;
++
++ sg->length += pad_len;
++ rq->extra_len += pad_len;
++ }
++
+ if (q->dma_drain_size && q->dma_drain_needed(rq)) {
+ if (rq->cmd_flags & REQ_RW)
+ memset(q->dma_drain_buffer, 0, q->dma_drain_size);
+diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
+index 54d0db1..fc41d83 100644
+--- a/block/blk-sysfs.c
++++ b/block/blk-sysfs.c
+@@ -276,9 +276,12 @@ int blk_register_queue(struct gendisk *disk)
+
+ struct request_queue *q = disk->queue;
+
+- if (!q || !q->request_fn)
++ if (WARN_ON(!q))
+ return -ENXIO;
+
++ if (!q->request_fn)
++ return 0;
++
+ ret = kobject_add(&q->kobj, kobject_get(&disk->dev.kobj),
+ "%s", "queue");
+ if (ret < 0)
+@@ -300,7 +303,10 @@ void blk_unregister_queue(struct gendisk *disk)
+ {
+ struct request_queue *q = disk->queue;
+
+- if (q && q->request_fn) {
++ if (WARN_ON(!q))
++ return;
++
++ if (q->request_fn) {
+ elv_unregister_queue(q);
+
+ kobject_uevent(&q->kobj, KOBJ_REMOVE);
+diff --git a/block/bsg.c b/block/bsg.c
+index 8917c51..f51172e 100644
+--- a/block/bsg.c
++++ b/block/bsg.c
+@@ -37,7 +37,6 @@ struct bsg_device {
+ struct list_head done_list;
+ struct hlist_node dev_list;
+ atomic_t ref_count;
+- int minor;
+ int queued_cmds;
+ int done_cmds;
+ wait_queue_head_t wq_done;
+@@ -368,7 +367,7 @@ static struct bsg_command *bsg_next_done_cmd(struct bsg_device *bd)
+
+ spin_lock_irq(&bd->lock);
+ if (bd->done_cmds) {
+- bc = list_entry(bd->done_list.next, struct bsg_command, list);
++ bc = list_first_entry(&bd->done_list, struct bsg_command, list);
+ list_del(&bc->list);
+ bd->done_cmds--;
+ }
+@@ -468,8 +467,6 @@ static int bsg_complete_all_commands(struct bsg_device *bd)
+
+ dprintk("%s: entered\n", bd->name);
+
+- set_bit(BSG_F_BLOCK, &bd->flags);
+-
+ /*
+ * wait for all commands to complete
+ */
+@@ -705,6 +702,7 @@ static struct bsg_device *bsg_alloc_device(void)
+ static int bsg_put_device(struct bsg_device *bd)
+ {
+ int ret = 0;
++ struct device *dev = bd->queue->bsg_dev.dev;
+
+ mutex_lock(&bsg_mutex);
+
+@@ -730,6 +728,7 @@ static int bsg_put_device(struct bsg_device *bd)
+ kfree(bd);
+ out:
+ mutex_unlock(&bsg_mutex);
++ put_device(dev);
+ return ret;
+ }
+
+@@ -738,24 +737,28 @@ static struct bsg_device *bsg_add_device(struct inode *inode,
+ struct file *file)
+ {
+ struct bsg_device *bd;
++ int ret;
+ #ifdef BSG_DEBUG
+ unsigned char buf[32];
+ #endif
++ ret = blk_get_queue(rq);
++ if (ret)
++ return ERR_PTR(-ENXIO);
+
+ bd = bsg_alloc_device();
+- if (!bd)
++ if (!bd) {
++ blk_put_queue(rq);
+ return ERR_PTR(-ENOMEM);
++ }
+
+ bd->queue = rq;
+- kobject_get(&rq->kobj);
+ bsg_set_block(bd, file);
+
+ atomic_set(&bd->ref_count, 1);
+- bd->minor = iminor(inode);
+ mutex_lock(&bsg_mutex);
+- hlist_add_head(&bd->dev_list, bsg_dev_idx_hash(bd->minor));
++ hlist_add_head(&bd->dev_list, bsg_dev_idx_hash(iminor(inode)));
+
+- strncpy(bd->name, rq->bsg_dev.class_dev->class_id, sizeof(bd->name) - 1);
++ strncpy(bd->name, rq->bsg_dev.class_dev->bus_id, sizeof(bd->name) - 1);
+ dprintk("bound to <%s>, max queue %d\n",
+ format_dev_t(buf, inode->i_rdev), bd->max_queue);
+
+@@ -763,23 +766,21 @@ static struct bsg_device *bsg_add_device(struct inode *inode,
+ return bd;
+ }
+
+-static struct bsg_device *__bsg_get_device(int minor)
++static struct bsg_device *__bsg_get_device(int minor, struct request_queue *q)
+ {
+- struct bsg_device *bd = NULL;
++ struct bsg_device *bd;
+ struct hlist_node *entry;
+
+ mutex_lock(&bsg_mutex);
+
+- hlist_for_each(entry, bsg_dev_idx_hash(minor)) {
+- bd = hlist_entry(entry, struct bsg_device, dev_list);
+- if (bd->minor == minor) {
++ hlist_for_each_entry(bd, entry, bsg_dev_idx_hash(minor), dev_list) {
++ if (bd->queue == q) {
+ atomic_inc(&bd->ref_count);
+- break;
++ goto found;
+ }
+-
+- bd = NULL;
+ }
+-
++ bd = NULL;
++found:
+ mutex_unlock(&bsg_mutex);
+ return bd;
+ }
+@@ -789,21 +790,27 @@ static struct bsg_device *bsg_get_device(struct inode *inode, struct file *file)
+ struct bsg_device *bd;
+ struct bsg_class_device *bcd;
+
+- bd = __bsg_get_device(iminor(inode));
+- if (bd)
+- return bd;
+-
+ /*
+ * find the class device
+ */
+ mutex_lock(&bsg_mutex);
+ bcd = idr_find(&bsg_minor_idr, iminor(inode));
++ if (bcd)
++ get_device(bcd->dev);
+ mutex_unlock(&bsg_mutex);
+
+ if (!bcd)
+ return ERR_PTR(-ENODEV);
+
+- return bsg_add_device(inode, bcd->queue, file);
++ bd = __bsg_get_device(iminor(inode), bcd->queue);
++ if (bd)
++ return bd;
++
++ bd = bsg_add_device(inode, bcd->queue, file);
++ if (IS_ERR(bd))
++ put_device(bcd->dev);
++
++ return bd;
+ }
+
+ static int bsg_open(struct inode *inode, struct file *file)
+@@ -939,10 +946,9 @@ void bsg_unregister_queue(struct request_queue *q)
+ mutex_lock(&bsg_mutex);
+ idr_remove(&bsg_minor_idr, bcd->minor);
+ sysfs_remove_link(&q->kobj, "bsg");
+- class_device_unregister(bcd->class_dev);
++ device_unregister(bcd->class_dev);
+ put_device(bcd->dev);
+ bcd->class_dev = NULL;
+- bcd->dev = NULL;
+ mutex_unlock(&bsg_mutex);
+ }
+ EXPORT_SYMBOL_GPL(bsg_unregister_queue);
+@@ -953,7 +959,7 @@ int bsg_register_queue(struct request_queue *q, struct device *gdev,
+ struct bsg_class_device *bcd;
+ dev_t dev;
+ int ret, minor;
+- struct class_device *class_dev = NULL;
++ struct device *class_dev = NULL;
+ const char *devname;
+
+ if (name)
+@@ -992,8 +998,7 @@ int bsg_register_queue(struct request_queue *q, struct device *gdev,
+ bcd->queue = q;
+ bcd->dev = get_device(gdev);
+ dev = MKDEV(bsg_major, bcd->minor);
+- class_dev = class_device_create(bsg_class, NULL, dev, gdev, "%s",
+- devname);
++ class_dev = device_create(bsg_class, gdev, dev, "%s", devname);
+ if (IS_ERR(class_dev)) {
+ ret = PTR_ERR(class_dev);
+ goto put_dev;
+@@ -1010,7 +1015,7 @@ int bsg_register_queue(struct request_queue *q, struct device *gdev,
+ return 0;
+
+ unregister_class_dev:
+- class_device_unregister(class_dev);
++ device_unregister(class_dev);
+ put_dev:
+ put_device(gdev);
+ remove_idr:
+diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
+index b733732..c70d0b6 100644
+--- a/block/compat_ioctl.c
++++ b/block/compat_ioctl.c
+@@ -624,7 +624,6 @@ static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file,
+ case HDIO_GET_IDENTITY:
+ case HDIO_DRIVE_TASK:
+ case HDIO_DRIVE_CMD:
+- case HDIO_SCAN_HWIF:
+ /* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */
+ case 0x330:
+ /* 0x02 -- Floppy ioctls */
+diff --git a/crypto/Kconfig b/crypto/Kconfig
+index 69f1be6..864456c 100644
+--- a/crypto/Kconfig
++++ b/crypto/Kconfig
+@@ -13,12 +13,14 @@ source "crypto/async_tx/Kconfig"
+ # Cryptographic API Configuration
+ #
+ menuconfig CRYPTO
+- bool "Cryptographic API"
++ tristate "Cryptographic API"
+ help
+ This option provides the core Cryptographic API.
+
+ if CRYPTO
+
++comment "Crypto core or helper"
++
+ config CRYPTO_ALGAPI
+ tristate
+ help
+@@ -32,15 +34,6 @@ config CRYPTO_BLKCIPHER
+ tristate
+ select CRYPTO_ALGAPI
+
+-config CRYPTO_SEQIV
+- tristate "Sequence Number IV Generator"
+- select CRYPTO_AEAD
+- select CRYPTO_BLKCIPHER
+- help
+- This IV generator generates an IV based on a sequence number by
+- xoring it with a salt. This algorithm is mainly useful for CTR
+- and similar modes.
+-
+ config CRYPTO_HASH
+ tristate
+ select CRYPTO_ALGAPI
+@@ -52,24 +45,15 @@ config CRYPTO_MANAGER
+ Create default cryptographic template instantiations such as
+ cbc(aes).
+
+-config CRYPTO_HMAC
+- tristate "HMAC support"
+- select CRYPTO_HASH
+- select CRYPTO_MANAGER
+- help
+- HMAC: Keyed-Hashing for Message Authentication (RFC2104).
+- This is required for IPSec.
+-
+-config CRYPTO_XCBC
+- tristate "XCBC support"
++config CRYPTO_GF128MUL
++ tristate "GF(2^128) multiplication functions (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+- select CRYPTO_HASH
+- select CRYPTO_MANAGER
+ help
+- XCBC: Keyed-Hashing with encryption algorithm
+- http://www.ietf.org/rfc/rfc3566.txt
+- http://csrc.nist.gov/encryption/modes/proposedmodes/
+- xcbc-mac/xcbc-mac-spec.pdf
++ Efficient table driven implementation of multiplications in the
++ field GF(2^128). This is needed by some cypher modes. This
++ option will be selected automatically if you select such a
++ cipher mode. Only select this option by hand if you expect to load
++ an external module that requires these functions.
+
+ config CRYPTO_NULL
+ tristate "Null algorithms"
+@@ -78,107 +62,98 @@ config CRYPTO_NULL
+ help
+ These are 'Null' algorithms, used by IPsec, which do nothing.
+
+-config CRYPTO_MD4
+- tristate "MD4 digest algorithm"
+- select CRYPTO_ALGAPI
+- help
+- MD4 message digest algorithm (RFC1320).
+-
+-config CRYPTO_MD5
+- tristate "MD5 digest algorithm"
+- select CRYPTO_ALGAPI
++config CRYPTO_CRYPTD
++ tristate "Software async crypto daemon"
++ select CRYPTO_BLKCIPHER
++ select CRYPTO_MANAGER
+ help
+- MD5 message digest algorithm (RFC1321).
++ This is a generic software asynchronous crypto daemon that
++ converts an arbitrary synchronous software crypto algorithm
++ into an asynchronous algorithm that executes in a kernel thread.
+
+-config CRYPTO_SHA1
+- tristate "SHA1 digest algorithm"
+- select CRYPTO_ALGAPI
++config CRYPTO_AUTHENC
++ tristate "Authenc support"
++ select CRYPTO_AEAD
++ select CRYPTO_BLKCIPHER
++ select CRYPTO_MANAGER
++ select CRYPTO_HASH
+ help
+- SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
++ Authenc: Combined mode wrapper for IPsec.
++ This is required for IPSec.
+
+-config CRYPTO_SHA256
+- tristate "SHA224 and SHA256 digest algorithm"
++config CRYPTO_TEST
++ tristate "Testing module"
++ depends on m
+ select CRYPTO_ALGAPI
++ select CRYPTO_AEAD
++ select CRYPTO_BLKCIPHER
+ help
+- SHA256 secure hash standard (DFIPS 180-2).
+-
+- This version of SHA implements a 256 bit hash with 128 bits of
+- security against collision attacks.
++ Quick & dirty crypto test module.
+
+- This code also includes SHA-224, a 224 bit hash with 112 bits
+- of security against collision attacks.
++comment "Authenticated Encryption with Associated Data"
+
+-config CRYPTO_SHA512
+- tristate "SHA384 and SHA512 digest algorithms"
+- select CRYPTO_ALGAPI
++config CRYPTO_CCM
++ tristate "CCM support"
++ select CRYPTO_CTR
++ select CRYPTO_AEAD
+ help
+- SHA512 secure hash standard (DFIPS 180-2).
+-
+- This version of SHA implements a 512 bit hash with 256 bits of
+- security against collision attacks.
+-
+- This code also includes SHA-384, a 384 bit hash with 192 bits
+- of security against collision attacks.
++ Support for Counter with CBC MAC. Required for IPsec.
+
+-config CRYPTO_WP512
+- tristate "Whirlpool digest algorithms"
+- select CRYPTO_ALGAPI
++config CRYPTO_GCM
++ tristate "GCM/GMAC support"
++ select CRYPTO_CTR
++ select CRYPTO_AEAD
++ select CRYPTO_GF128MUL
+ help
+- Whirlpool hash algorithm 512, 384 and 256-bit hashes
+-
+- Whirlpool-512 is part of the NESSIE cryptographic primitives.
+- Whirlpool will be part of the ISO/IEC 10118-3:2003(E) standard
+-
+- See also:
+- <http://planeta.terra.com.br/informatica/paulobarreto/WhirlpoolPage.html>
++ Support for Galois/Counter Mode (GCM) and Galois Message
++ Authentication Code (GMAC). Required for IPSec.
+
+-config CRYPTO_TGR192
+- tristate "Tiger digest algorithms"
+- select CRYPTO_ALGAPI
++config CRYPTO_SEQIV
++ tristate "Sequence Number IV Generator"
++ select CRYPTO_AEAD
++ select CRYPTO_BLKCIPHER
+ help
+- Tiger hash algorithm 192, 160 and 128-bit hashes
+-
+- Tiger is a hash function optimized for 64-bit processors while
+- still having decent performance on 32-bit processors.
+- Tiger was developed by Ross Anderson and Eli Biham.
+-
+- See also:
+- <http://www.cs.technion.ac.il/~biham/Reports/Tiger/>.
++ This IV generator generates an IV based on a sequence number by
++ xoring it with a salt. This algorithm is mainly useful for CTR
+
+-config CRYPTO_GF128MUL
+- tristate "GF(2^128) multiplication functions (EXPERIMENTAL)"
+- depends on EXPERIMENTAL
+- help
+- Efficient table driven implementation of multiplications in the
+- field GF(2^128). This is needed by some cypher modes. This
+- option will be selected automatically if you select such a
+- cipher mode. Only select this option by hand if you expect to load
+- an external module that requires these functions.
++comment "Block modes"
+
+-config CRYPTO_ECB
+- tristate "ECB support"
++config CRYPTO_CBC
++ tristate "CBC support"
+ select CRYPTO_BLKCIPHER
+ select CRYPTO_MANAGER
+ help
+- ECB: Electronic CodeBook mode
+- This is the simplest block cipher algorithm. It simply encrypts
+- the input block by block.
++ CBC: Cipher Block Chaining mode
++ This block cipher algorithm is required for IPSec.
+
+-config CRYPTO_CBC
+- tristate "CBC support"
++config CRYPTO_CTR
++ tristate "CTR support"
+ select CRYPTO_BLKCIPHER
++ select CRYPTO_SEQIV
+ select CRYPTO_MANAGER
+ help
+- CBC: Cipher Block Chaining mode
++ CTR: Counter mode
+ This block cipher algorithm is required for IPSec.
+
+-config CRYPTO_PCBC
+- tristate "PCBC support"
++config CRYPTO_CTS
++ tristate "CTS support"
++ select CRYPTO_BLKCIPHER
++ help
++ CTS: Cipher Text Stealing
++ This is the Cipher Text Stealing mode as described by
++ Section 8 of rfc2040 and referenced by rfc3962.
++ (rfc3962 includes errata information in its Appendix A)
++ This mode is required for Kerberos gss mechanism support
++ for AES encryption.
++
++config CRYPTO_ECB
++ tristate "ECB support"
+ select CRYPTO_BLKCIPHER
+ select CRYPTO_MANAGER
+ help
+- PCBC: Propagating Cipher Block Chaining mode
+- This block cipher algorithm is required for RxRPC.
++ ECB: Electronic CodeBook mode
++ This is the simplest block cipher algorithm. It simply encrypts
++ the input block by block.
+
+ config CRYPTO_LRW
+ tristate "LRW support (EXPERIMENTAL)"
+@@ -193,6 +168,14 @@ config CRYPTO_LRW
+ The first 128, 192 or 256 bits in the key are used for AES and the
+ rest is used to tie each cipher block to its logical position.
+
++config CRYPTO_PCBC
++ tristate "PCBC support"
++ select CRYPTO_BLKCIPHER
++ select CRYPTO_MANAGER
++ help
++ PCBC: Propagating Cipher Block Chaining mode
++ This block cipher algorithm is required for RxRPC.
++
+ config CRYPTO_XTS
+ tristate "XTS support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+@@ -204,149 +187,134 @@ config CRYPTO_XTS
+ key size 256, 384 or 512 bits. This implementation currently
+ can't handle a sectorsize which is not a multiple of 16 bytes.
+
+-config CRYPTO_CTR
+- tristate "CTR support"
+- select CRYPTO_BLKCIPHER
+- select CRYPTO_SEQIV
++comment "Hash modes"
++
++config CRYPTO_HMAC
++ tristate "HMAC support"
++ select CRYPTO_HASH
+ select CRYPTO_MANAGER
+ help
+- CTR: Counter mode
+- This block cipher algorithm is required for IPSec.
++ HMAC: Keyed-Hashing for Message Authentication (RFC2104).
++ This is required for IPSec.
+
+-config CRYPTO_GCM
+- tristate "GCM/GMAC support"
+- select CRYPTO_CTR
+- select CRYPTO_AEAD
+- select CRYPTO_GF128MUL
++config CRYPTO_XCBC
++ tristate "XCBC support"
++ depends on EXPERIMENTAL
++ select CRYPTO_HASH
++ select CRYPTO_MANAGER
+ help
+- Support for Galois/Counter Mode (GCM) and Galois Message
+- Authentication Code (GMAC). Required for IPSec.
++ XCBC: Keyed-Hashing with encryption algorithm
++ http://www.ietf.org/rfc/rfc3566.txt
++ http://csrc.nist.gov/encryption/modes/proposedmodes/
++ xcbc-mac/xcbc-mac-spec.pdf
+
+-config CRYPTO_CCM
+- tristate "CCM support"
+- select CRYPTO_CTR
+- select CRYPTO_AEAD
+- help
+- Support for Counter with CBC MAC. Required for IPsec.
++comment "Digest"
+
+-config CRYPTO_CRYPTD
+- tristate "Software async crypto daemon"
+- select CRYPTO_BLKCIPHER
+- select CRYPTO_MANAGER
++config CRYPTO_CRC32C
++ tristate "CRC32c CRC algorithm"
++ select CRYPTO_ALGAPI
++ select LIBCRC32C
+ help
+- This is a generic software asynchronous crypto daemon that
+- converts an arbitrary synchronous software crypto algorithm
+- into an asynchronous algorithm that executes in a kernel thread.
++ Castagnoli, et al Cyclic Redundancy-Check Algorithm. Used
++ by iSCSI for header and data digests and by others.
++ See Castagnoli93. This implementation uses lib/libcrc32c.
++ Module will be crc32c.
+
+-config CRYPTO_DES
+- tristate "DES and Triple DES EDE cipher algorithms"
++config CRYPTO_MD4
++ tristate "MD4 digest algorithm"
+ select CRYPTO_ALGAPI
+ help
+- DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
++ MD4 message digest algorithm (RFC1320).
+
+-config CRYPTO_FCRYPT
+- tristate "FCrypt cipher algorithm"
++config CRYPTO_MD5
++ tristate "MD5 digest algorithm"
+ select CRYPTO_ALGAPI
+- select CRYPTO_BLKCIPHER
+ help
+- FCrypt algorithm used by RxRPC.
++ MD5 message digest algorithm (RFC1321).
+
+-config CRYPTO_BLOWFISH
+- tristate "Blowfish cipher algorithm"
++config CRYPTO_MICHAEL_MIC
++ tristate "Michael MIC keyed digest algorithm"
+ select CRYPTO_ALGAPI
+ help
+- Blowfish cipher algorithm, by Bruce Schneier.
+-
+- This is a variable key length cipher which can use keys from 32
+- bits to 448 bits in length. It's fast, simple and specifically
+- designed for use on "large microprocessors".
+-
+- See also:
+- <http://www.schneier.com/blowfish.html>
++ Michael MIC is used for message integrity protection in TKIP
++ (IEEE 802.11i). This algorithm is required for TKIP, but it
++ should not be used for other purposes because of the weakness
++ of the algorithm.
+
+-config CRYPTO_TWOFISH
+- tristate "Twofish cipher algorithm"
++config CRYPTO_SHA1
++ tristate "SHA1 digest algorithm"
+ select CRYPTO_ALGAPI
+- select CRYPTO_TWOFISH_COMMON
+ help
+- Twofish cipher algorithm.
+-
+- Twofish was submitted as an AES (Advanced Encryption Standard)
+- candidate cipher by researchers at CounterPane Systems. It is a
+- 16 round block cipher supporting key sizes of 128, 192, and 256
+- bits.
+-
+- See also:
+- <http://www.schneier.com/twofish.html>
++ SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
+
+-config CRYPTO_TWOFISH_COMMON
+- tristate
++config CRYPTO_SHA256
++ tristate "SHA224 and SHA256 digest algorithm"
++ select CRYPTO_ALGAPI
+ help
+- Common parts of the Twofish cipher algorithm shared by the
+- generic c and the assembler implementations.
++ SHA256 secure hash standard (DFIPS 180-2).
+
+-config CRYPTO_TWOFISH_586
+- tristate "Twofish cipher algorithms (i586)"
+- depends on (X86 || UML_X86) && !64BIT
++ This version of SHA implements a 256 bit hash with 128 bits of
++ security against collision attacks.
++
++ This code also includes SHA-224, a 224 bit hash with 112 bits
++ of security against collision attacks.
++
++config CRYPTO_SHA512
++ tristate "SHA384 and SHA512 digest algorithms"
+ select CRYPTO_ALGAPI
+- select CRYPTO_TWOFISH_COMMON
+ help
+- Twofish cipher algorithm.
++ SHA512 secure hash standard (DFIPS 180-2).
+
+- Twofish was submitted as an AES (Advanced Encryption Standard)
+- candidate cipher by researchers at CounterPane Systems. It is a
+- 16 round block cipher supporting key sizes of 128, 192, and 256
+- bits.
++ This version of SHA implements a 512 bit hash with 256 bits of
++ security against collision attacks.
+
+- See also:
+- <http://www.schneier.com/twofish.html>
++ This code also includes SHA-384, a 384 bit hash with 192 bits
++ of security against collision attacks.
+
+-config CRYPTO_TWOFISH_X86_64
+- tristate "Twofish cipher algorithm (x86_64)"
+- depends on (X86 || UML_X86) && 64BIT
++config CRYPTO_TGR192
++ tristate "Tiger digest algorithms"
+ select CRYPTO_ALGAPI
+- select CRYPTO_TWOFISH_COMMON
+ help
+- Twofish cipher algorithm (x86_64).
++ Tiger hash algorithm 192, 160 and 128-bit hashes
+
+- Twofish was submitted as an AES (Advanced Encryption Standard)
+- candidate cipher by researchers at CounterPane Systems. It is a
+- 16 round block cipher supporting key sizes of 128, 192, and 256
+- bits.
++ Tiger is a hash function optimized for 64-bit processors while
++ still having decent performance on 32-bit processors.
++ Tiger was developed by Ross Anderson and Eli Biham.
+
+ See also:
+- <http://www.schneier.com/twofish.html>
++ <http://www.cs.technion.ac.il/~biham/Reports/Tiger/>.
+
+-config CRYPTO_SERPENT
+- tristate "Serpent cipher algorithm"
++config CRYPTO_WP512
++ tristate "Whirlpool digest algorithms"
+ select CRYPTO_ALGAPI
+ help
+- Serpent cipher algorithm, by Anderson, Biham & Knudsen.
++ Whirlpool hash algorithm 512, 384 and 256-bit hashes
+
+- Keys are allowed to be from 0 to 256 bits in length, in steps
+- of 8 bits. Also includes the 'Tnepres' algorithm, a reversed
+- variant of Serpent for compatibility with old kerneli.org code.
++ Whirlpool-512 is part of the NESSIE cryptographic primitives.
++ Whirlpool will be part of the ISO/IEC 10118-3:2003(E) standard
+
+ See also:
+- <http://www.cl.cam.ac.uk/~rja14/serpent.html>
++ <http://planeta.terra.com.br/informatica/paulobarreto/WhirlpoolPage.html>
++
++comment "Ciphers"
+
+ config CRYPTO_AES
+ tristate "AES cipher algorithms"
+ select CRYPTO_ALGAPI
+ help
+- AES cipher algorithms (FIPS-197). AES uses the Rijndael
++ AES cipher algorithms (FIPS-197). AES uses the Rijndael
+ algorithm.
+
+ Rijndael appears to be consistently a very good performer in
+- both hardware and software across a wide range of computing
+- environments regardless of its use in feedback or non-feedback
+- modes. Its key setup time is excellent, and its key agility is
+- good. Rijndael's very low memory requirements make it very well
+- suited for restricted-space environments, in which it also
+- demonstrates excellent performance. Rijndael's operations are
+- among the easiest to defend against power and timing attacks.
++ both hardware and software across a wide range of computing
++ environments regardless of its use in feedback or non-feedback
++ modes. Its key setup time is excellent, and its key agility is
++ good. Rijndael's very low memory requirements make it very well
++ suited for restricted-space environments, in which it also
++ demonstrates excellent performance. Rijndael's operations are
++ among the easiest to defend against power and timing attacks.
+
+- The AES specifies three key sizes: 128, 192 and 256 bits
++ The AES specifies three key sizes: 128, 192 and 256 bits
+
+ See <http://csrc.nist.gov/CryptoToolkit/aes/> for more information.
+
+@@ -356,19 +324,19 @@ config CRYPTO_AES_586
+ select CRYPTO_ALGAPI
+ select CRYPTO_AES
+ help
+- AES cipher algorithms (FIPS-197). AES uses the Rijndael
++ AES cipher algorithms (FIPS-197). AES uses the Rijndael
+ algorithm.
+
+ Rijndael appears to be consistently a very good performer in
+- both hardware and software across a wide range of computing
+- environments regardless of its use in feedback or non-feedback
+- modes. Its key setup time is excellent, and its key agility is
+- good. Rijndael's very low memory requirements make it very well
+- suited for restricted-space environments, in which it also
+- demonstrates excellent performance. Rijndael's operations are
+- among the easiest to defend against power and timing attacks.
++ both hardware and software across a wide range of computing
++ environments regardless of its use in feedback or non-feedback
++ modes. Its key setup time is excellent, and its key agility is
++ good. Rijndael's very low memory requirements make it very well
++ suited for restricted-space environments, in which it also
++ demonstrates excellent performance. Rijndael's operations are
++ among the easiest to defend against power and timing attacks.
+
+- The AES specifies three key sizes: 128, 192 and 256 bits
++ The AES specifies three key sizes: 128, 192 and 256 bits
+
+ See <http://csrc.nist.gov/encryption/aes/> for more information.
+
+@@ -378,22 +346,75 @@ config CRYPTO_AES_X86_64
+ select CRYPTO_ALGAPI
+ select CRYPTO_AES
+ help
+- AES cipher algorithms (FIPS-197). AES uses the Rijndael
++ AES cipher algorithms (FIPS-197). AES uses the Rijndael
+ algorithm.
+
+ Rijndael appears to be consistently a very good performer in
+- both hardware and software across a wide range of computing
+- environments regardless of its use in feedback or non-feedback
+- modes. Its key setup time is excellent, and its key agility is
+- good. Rijndael's very low memory requirements make it very well
+- suited for restricted-space environments, in which it also
+- demonstrates excellent performance. Rijndael's operations are
+- among the easiest to defend against power and timing attacks.
++ both hardware and software across a wide range of computing
++ environments regardless of its use in feedback or non-feedback
++ modes. Its key setup time is excellent, and its key agility is
++ good. Rijndael's very low memory requirements make it very well
++ suited for restricted-space environments, in which it also
++ demonstrates excellent performance. Rijndael's operations are
++ among the easiest to defend against power and timing attacks.
+
+- The AES specifies three key sizes: 128, 192 and 256 bits
++ The AES specifies three key sizes: 128, 192 and 256 bits
+
+ See <http://csrc.nist.gov/encryption/aes/> for more information.
+
++config CRYPTO_ANUBIS
++ tristate "Anubis cipher algorithm"
++ select CRYPTO_ALGAPI
++ help
++ Anubis cipher algorithm.
++
++ Anubis is a variable key length cipher which can use keys from
++ 128 bits to 320 bits in length. It was evaluated as a entrant
++ in the NESSIE competition.
++
++ See also:
++ <https://www.cosic.esat.kuleuven.ac.be/nessie/reports/>
++ <http://planeta.terra.com.br/informatica/paulobarreto/AnubisPage.html>
++
++config CRYPTO_ARC4
++ tristate "ARC4 cipher algorithm"
++ select CRYPTO_ALGAPI
++ help
++ ARC4 cipher algorithm.
++
++ ARC4 is a stream cipher using keys ranging from 8 bits to 2048
++ bits in length. This algorithm is required for driver-based
++ WEP, but it should not be for other purposes because of the
++ weakness of the algorithm.
++
++config CRYPTO_BLOWFISH
++ tristate "Blowfish cipher algorithm"
++ select CRYPTO_ALGAPI
++ help
++ Blowfish cipher algorithm, by Bruce Schneier.
++
++ This is a variable key length cipher which can use keys from 32
++ bits to 448 bits in length. It's fast, simple and specifically
++ designed for use on "large microprocessors".
++
++ See also:
++ <http://www.schneier.com/blowfish.html>
++
++config CRYPTO_CAMELLIA
++ tristate "Camellia cipher algorithms"
++ depends on CRYPTO
++ select CRYPTO_ALGAPI
++ help
++ Camellia cipher algorithms module.
++
++ Camellia is a symmetric key block cipher developed jointly
++ at NTT and Mitsubishi Electric Corporation.
++
++ The Camellia specifies three key sizes: 128, 192 and 256 bits.
++
++ See also:
++ <https://info.isl.ntt.co.jp/crypt/eng/camellia/index_s.html>
++
+ config CRYPTO_CAST5
+ tristate "CAST5 (CAST-128) cipher algorithm"
+ select CRYPTO_ALGAPI
+@@ -408,33 +429,18 @@ config CRYPTO_CAST6
+ The CAST6 encryption algorithm (synonymous with CAST-256) is
+ described in RFC2612.
+
+-config CRYPTO_TEA
+- tristate "TEA, XTEA and XETA cipher algorithms"
++config CRYPTO_DES
++ tristate "DES and Triple DES EDE cipher algorithms"
+ select CRYPTO_ALGAPI
+ help
+- TEA cipher algorithm.
+-
+- Tiny Encryption Algorithm is a simple cipher that uses
+- many rounds for security. It is very fast and uses
+- little memory.
+-
+- Xtendend Tiny Encryption Algorithm is a modification to
+- the TEA algorithm to address a potential key weakness
+- in the TEA algorithm.
+-
+- Xtendend Encryption Tiny Algorithm is a mis-implementation
+- of the XTEA algorithm for compatibility purposes.
++ DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
+
+-config CRYPTO_ARC4
+- tristate "ARC4 cipher algorithm"
++config CRYPTO_FCRYPT
++ tristate "FCrypt cipher algorithm"
+ select CRYPTO_ALGAPI
++ select CRYPTO_BLKCIPHER
+ help
+- ARC4 cipher algorithm.
+-
+- ARC4 is a stream cipher using keys ranging from 8 bits to 2048
+- bits in length. This algorithm is required for driver-based
+- WEP, but it should not be for other purposes because of the
+- weakness of the algorithm.
++ FCrypt algorithm used by RxRPC.
+
+ config CRYPTO_KHAZAD
+ tristate "Khazad cipher algorithm"
+@@ -449,34 +455,6 @@ config CRYPTO_KHAZAD
+ See also:
+ <http://planeta.terra.com.br/informatica/paulobarreto/KhazadPage.html>
+
+-config CRYPTO_ANUBIS
+- tristate "Anubis cipher algorithm"
+- select CRYPTO_ALGAPI
+- help
+- Anubis cipher algorithm.
+-
+- Anubis is a variable key length cipher which can use keys from
+- 128 bits to 320 bits in length. It was evaluated as a entrant
+- in the NESSIE competition.
+-
+- See also:
+- <https://www.cosic.esat.kuleuven.ac.be/nessie/reports/>
+- <http://planeta.terra.com.br/informatica/paulobarreto/AnubisPage.html>
+-
+-config CRYPTO_SEED
+- tristate "SEED cipher algorithm"
+- select CRYPTO_ALGAPI
+- help
+- SEED cipher algorithm (RFC4269).
+-
+- SEED is a 128-bit symmetric key block cipher that has been
+- developed by KISA (Korea Information Security Agency) as a
+- national standard encryption algorithm of the Republic of Korea.
+- It is a 16 round block cipher with the key size of 128 bit.
+-
+- See also:
+- <http://www.kisa.or.kr/kisa/seed/jsp/seed_eng.jsp>
+-
+ config CRYPTO_SALSA20
+ tristate "Salsa20 stream cipher algorithm (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+@@ -518,69 +496,115 @@ config CRYPTO_SALSA20_X86_64
+ The Salsa20 stream cipher algorithm is designed by Daniel J.
+ Bernstein <djb at cr.yp.to>. See <http://cr.yp.to/snuffle.html>
+
+-config CRYPTO_DEFLATE
+- tristate "Deflate compression algorithm"
++config CRYPTO_SEED
++ tristate "SEED cipher algorithm"
+ select CRYPTO_ALGAPI
+- select ZLIB_INFLATE
+- select ZLIB_DEFLATE
+ help
+- This is the Deflate algorithm (RFC1951), specified for use in
+- IPSec with the IPCOMP protocol (RFC3173, RFC2394).
+-
+- You will most probably want this if using IPSec.
++ SEED cipher algorithm (RFC4269).
+
+-config CRYPTO_MICHAEL_MIC
+- tristate "Michael MIC keyed digest algorithm"
++ SEED is a 128-bit symmetric key block cipher that has been
++ developed by KISA (Korea Information Security Agency) as a
++ national standard encryption algorithm of the Republic of Korea.
++ It is a 16 round block cipher with the key size of 128 bit.
++
++ See also:
++ <http://www.kisa.or.kr/kisa/seed/jsp/seed_eng.jsp>
++
++config CRYPTO_SERPENT
++ tristate "Serpent cipher algorithm"
+ select CRYPTO_ALGAPI
+ help
+- Michael MIC is used for message integrity protection in TKIP
+- (IEEE 802.11i). This algorithm is required for TKIP, but it
+- should not be used for other purposes because of the weakness
+- of the algorithm.
++ Serpent cipher algorithm, by Anderson, Biham & Knudsen.
+
+-config CRYPTO_CRC32C
+- tristate "CRC32c CRC algorithm"
++ Keys are allowed to be from 0 to 256 bits in length, in steps
++ of 8 bits. Also includes the 'Tnepres' algorithm, a reversed
++ variant of Serpent for compatibility with old kerneli.org code.
++
++ See also:
++ <http://www.cl.cam.ac.uk/~rja14/serpent.html>
++
++config CRYPTO_TEA
++ tristate "TEA, XTEA and XETA cipher algorithms"
+ select CRYPTO_ALGAPI
+- select LIBCRC32C
+ help
+- Castagnoli, et al Cyclic Redundancy-Check Algorithm. Used
+- by iSCSI for header and data digests and by others.
+- See Castagnoli93. This implementation uses lib/libcrc32c.
+- Module will be crc32c.
++ TEA cipher algorithm.
+
+-config CRYPTO_CAMELLIA
+- tristate "Camellia cipher algorithms"
+- depends on CRYPTO
++ Tiny Encryption Algorithm is a simple cipher that uses
++ many rounds for security. It is very fast and uses
++ little memory.
++
++ Xtendend Tiny Encryption Algorithm is a modification to
++ the TEA algorithm to address a potential key weakness
++ in the TEA algorithm.
++
++ Xtendend Encryption Tiny Algorithm is a mis-implementation
++ of the XTEA algorithm for compatibility purposes.
++
++config CRYPTO_TWOFISH
++ tristate "Twofish cipher algorithm"
+ select CRYPTO_ALGAPI
++ select CRYPTO_TWOFISH_COMMON
+ help
+- Camellia cipher algorithms module.
++ Twofish cipher algorithm.
+
+- Camellia is a symmetric key block cipher developed jointly
+- at NTT and Mitsubishi Electric Corporation.
++ Twofish was submitted as an AES (Advanced Encryption Standard)
++ candidate cipher by researchers at CounterPane Systems. It is a
++ 16 round block cipher supporting key sizes of 128, 192, and 256
++ bits.
+
+- The Camellia specifies three key sizes: 128, 192 and 256 bits.
++ See also:
++ <http://www.schneier.com/twofish.html>
++
++config CRYPTO_TWOFISH_COMMON
++ tristate
++ help
++ Common parts of the Twofish cipher algorithm shared by the
++ generic c and the assembler implementations.
++
++config CRYPTO_TWOFISH_586
++ tristate "Twofish cipher algorithms (i586)"
++ depends on (X86 || UML_X86) && !64BIT
++ select CRYPTO_ALGAPI
++ select CRYPTO_TWOFISH_COMMON
++ help
++ Twofish cipher algorithm.
++
++ Twofish was submitted as an AES (Advanced Encryption Standard)
++ candidate cipher by researchers at CounterPane Systems. It is a
++ 16 round block cipher supporting key sizes of 128, 192, and 256
++ bits.
+
+ See also:
+- <https://info.isl.ntt.co.jp/crypt/eng/camellia/index_s.html>
++ <http://www.schneier.com/twofish.html>
+
+-config CRYPTO_TEST
+- tristate "Testing module"
+- depends on m
++config CRYPTO_TWOFISH_X86_64
++ tristate "Twofish cipher algorithm (x86_64)"
++ depends on (X86 || UML_X86) && 64BIT
+ select CRYPTO_ALGAPI
+- select CRYPTO_AEAD
+- select CRYPTO_BLKCIPHER
++ select CRYPTO_TWOFISH_COMMON
+ help
+- Quick & dirty crypto test module.
++ Twofish cipher algorithm (x86_64).
+
+-config CRYPTO_AUTHENC
+- tristate "Authenc support"
+- select CRYPTO_AEAD
+- select CRYPTO_BLKCIPHER
+- select CRYPTO_MANAGER
+- select CRYPTO_HASH
++ Twofish was submitted as an AES (Advanced Encryption Standard)
++ candidate cipher by researchers at CounterPane Systems. It is a
++ 16 round block cipher supporting key sizes of 128, 192, and 256
++ bits.
++
++ See also:
++ <http://www.schneier.com/twofish.html>
++
++comment "Compression"
++
++config CRYPTO_DEFLATE
++ tristate "Deflate compression algorithm"
++ select CRYPTO_ALGAPI
++ select ZLIB_INFLATE
++ select ZLIB_DEFLATE
+ help
+- Authenc: Combined mode wrapper for IPsec.
+- This is required for IPSec.
++ This is the Deflate algorithm (RFC1951), specified for use in
++ IPSec with the IPCOMP protocol (RFC3173, RFC2394).
++
++ You will most probably want this if using IPSec.
+
+ config CRYPTO_LZO
+ tristate "LZO compression algorithm"
+diff --git a/crypto/Makefile b/crypto/Makefile
+index 7cf3625..ca02441 100644
+--- a/crypto/Makefile
++++ b/crypto/Makefile
+@@ -2,7 +2,8 @@
+ # Cryptographic API
+ #
+
+-obj-$(CONFIG_CRYPTO) += api.o cipher.o digest.o compress.o
++obj-$(CONFIG_CRYPTO) += crypto.o
++crypto-objs := api.o cipher.o digest.o compress.o
+
+ crypto_algapi-$(CONFIG_PROC_FS) += proc.o
+ crypto_algapi-objs := algapi.o scatterwalk.o $(crypto_algapi-y)
+@@ -28,13 +29,14 @@ obj-$(CONFIG_CRYPTO_MD4) += md4.o
+ obj-$(CONFIG_CRYPTO_MD5) += md5.o
+ obj-$(CONFIG_CRYPTO_SHA1) += sha1_generic.o
+ obj-$(CONFIG_CRYPTO_SHA256) += sha256_generic.o
+-obj-$(CONFIG_CRYPTO_SHA512) += sha512.o
++obj-$(CONFIG_CRYPTO_SHA512) += sha512_generic.o
+ obj-$(CONFIG_CRYPTO_WP512) += wp512.o
+ obj-$(CONFIG_CRYPTO_TGR192) += tgr192.o
+ obj-$(CONFIG_CRYPTO_GF128MUL) += gf128mul.o
+ obj-$(CONFIG_CRYPTO_ECB) += ecb.o
+ obj-$(CONFIG_CRYPTO_CBC) += cbc.o
+ obj-$(CONFIG_CRYPTO_PCBC) += pcbc.o
++obj-$(CONFIG_CRYPTO_CTS) += cts.o
+ obj-$(CONFIG_CRYPTO_LRW) += lrw.o
+ obj-$(CONFIG_CRYPTO_XTS) += xts.o
+ obj-$(CONFIG_CRYPTO_CTR) += ctr.o
+diff --git a/crypto/aes_generic.c b/crypto/aes_generic.c
+index cf30af7..136dc98 100644
+--- a/crypto/aes_generic.c
++++ b/crypto/aes_generic.c
+@@ -229,18 +229,29 @@ static void __init gen_tabs(void)
+ ctx->key_enc[8 * i + 15] = t; \
+ } while (0)
+
+-int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
++/**
++ * crypto_aes_expand_key - Expands the AES key as described in FIPS-197
++ * @ctx: The location where the computed key will be stored.
++ * @in_key: The supplied key.
++ * @key_len: The length of the supplied key.
++ *
++ * Returns 0 on success. The function fails only if an invalid key size (or
++ * pointer) is supplied.
++ * The expanded key size is 240 bytes (max of 14 rounds with a unique 16 bytes
++ * key schedule plus a 16 bytes key which is used before the first round).
++ * The decryption key is prepared for the "Equivalent Inverse Cipher" as
++ * described in FIPS-197. The first slot (16 bytes) of each key (enc or dec) is
++ * for the initial combination, the second slot for the first round and so on.
++ */
++int crypto_aes_expand_key(struct crypto_aes_ctx *ctx, const u8 *in_key,
+ unsigned int key_len)
+ {
+- struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+ const __le32 *key = (const __le32 *)in_key;
+- u32 *flags = &tfm->crt_flags;
+ u32 i, t, u, v, w, j;
+
+- if (key_len % 8) {
+- *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
++ if (key_len != AES_KEYSIZE_128 && key_len != AES_KEYSIZE_192 &&
++ key_len != AES_KEYSIZE_256)
+ return -EINVAL;
+- }
+
+ ctx->key_length = key_len;
+
+@@ -250,20 +261,20 @@ int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ ctx->key_dec[key_len + 27] = ctx->key_enc[3] = le32_to_cpu(key[3]);
+
+ switch (key_len) {
+- case 16:
++ case AES_KEYSIZE_128:
+ t = ctx->key_enc[3];
+ for (i = 0; i < 10; ++i)
+ loop4(i);
+ break;
+
+- case 24:
++ case AES_KEYSIZE_192:
+ ctx->key_enc[4] = le32_to_cpu(key[4]);
+ t = ctx->key_enc[5] = le32_to_cpu(key[5]);
+ for (i = 0; i < 8; ++i)
+ loop6(i);
+ break;
+
+- case 32:
++ case AES_KEYSIZE_256:
+ ctx->key_enc[4] = le32_to_cpu(key[4]);
+ ctx->key_enc[5] = le32_to_cpu(key[5]);
+ ctx->key_enc[6] = le32_to_cpu(key[6]);
+@@ -284,6 +295,33 @@ int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ }
+ return 0;
+ }
++EXPORT_SYMBOL_GPL(crypto_aes_expand_key);
++
++/**
++ * crypto_aes_set_key - Set the AES key.
++ * @tfm: The %crypto_tfm that is used in the context.
++ * @in_key: The input key.
++ * @key_len: The size of the key.
++ *
++ * Returns 0 on success, on failure the %CRYPTO_TFM_RES_BAD_KEY_LEN flag in tfm
++ * is set. The function uses crypto_aes_expand_key() to expand the key.
++ * &crypto_aes_ctx _must_ be the private data embedded in @tfm which is
++ * retrieved with crypto_tfm_ctx().
++ */
++int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
++ unsigned int key_len)
++{
++ struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
++ u32 *flags = &tfm->crt_flags;
++ int ret;
++
++ ret = crypto_aes_expand_key(ctx, in_key, key_len);
++ if (!ret)
++ return 0;
++
++ *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
++ return -EINVAL;
++}
+ EXPORT_SYMBOL_GPL(crypto_aes_set_key);
+
+ /* encrypt a block of text */
+diff --git a/crypto/anubis.c b/crypto/anubis.c
+index 4ff0e1e..e42c3a8 100644
+--- a/crypto/anubis.c
++++ b/crypto/anubis.c
+@@ -687,7 +687,7 @@ static struct crypto_alg anubis_alg = {
+ .cia_decrypt = anubis_decrypt } }
+ };
+
+-static int __init init(void)
++static int __init anubis_mod_init(void)
+ {
+ int ret = 0;
+
+@@ -695,13 +695,13 @@ static int __init init(void)
+ return ret;
+ }
+
+-static void __exit fini(void)
++static void __exit anubis_mod_fini(void)
+ {
+ crypto_unregister_alg(&anubis_alg);
+ }
+
+-module_init(init);
+-module_exit(fini);
++module_init(anubis_mod_init);
++module_exit(anubis_mod_fini);
+
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Anubis Cryptographic Algorithm");
+diff --git a/crypto/api.c b/crypto/api.c
+index a2496d1..0a0f41e 100644
+--- a/crypto/api.c
++++ b/crypto/api.c
+@@ -445,3 +445,6 @@ int crypto_has_alg(const char *name, u32 type, u32 mask)
+ return ret;
+ }
+ EXPORT_SYMBOL_GPL(crypto_has_alg);
++
++MODULE_DESCRIPTION("Cryptographic core API");
++MODULE_LICENSE("GPL");
+diff --git a/crypto/async_tx/async_memcpy.c b/crypto/async_tx/async_memcpy.c
+index 84caa4e..a5eda80 100644
+--- a/crypto/async_tx/async_memcpy.c
++++ b/crypto/async_tx/async_memcpy.c
+@@ -77,7 +77,7 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
+ /* if ack is already set then we cannot be sure
+ * we are referring to the correct operation
+ */
+- BUG_ON(depend_tx->ack);
++ BUG_ON(async_tx_test_ack(depend_tx));
+ if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
+ panic("%s: DMA_ERROR waiting for depend_tx\n",
+ __func__);
+diff --git a/crypto/async_tx/async_tx.c b/crypto/async_tx/async_tx.c
+index 2be3bae..c6e772f 100644
+--- a/crypto/async_tx/async_tx.c
++++ b/crypto/async_tx/async_tx.c
+@@ -89,13 +89,19 @@ dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
+ iter = tx;
+
+ /* find the root of the unsubmitted dependency chain */
+- while (iter->cookie == -EBUSY) {
++ do {
+ parent = iter->parent;
+- if (parent && parent->cookie == -EBUSY)
+- iter = iter->parent;
+- else
++ if (!parent)
+ break;
+- }
++ else
++ iter = parent;
++ } while (parent);
++
++ /* there is a small window for ->parent == NULL and
++ * ->cookie == -EBUSY
++ */
++ while (iter->cookie == -EBUSY)
++ cpu_relax();
+
+ status = dma_sync_wait(iter->chan, iter->cookie);
+ } while (status == DMA_IN_PROGRESS || (iter != tx));
+@@ -111,24 +117,33 @@ EXPORT_SYMBOL_GPL(dma_wait_for_async_tx);
+ void
+ async_tx_run_dependencies(struct dma_async_tx_descriptor *tx)
+ {
+- struct dma_async_tx_descriptor *dep_tx, *_dep_tx;
+- struct dma_device *dev;
++ struct dma_async_tx_descriptor *next = tx->next;
+ struct dma_chan *chan;
+
+- list_for_each_entry_safe(dep_tx, _dep_tx, &tx->depend_list,
+- depend_node) {
+- chan = dep_tx->chan;
+- dev = chan->device;
+- /* we can't depend on ourselves */
+- BUG_ON(chan == tx->chan);
+- list_del(&dep_tx->depend_node);
+- tx->tx_submit(dep_tx);
+-
+- /* we need to poke the engine as client code does not
+- * know about dependency submission events
+- */
+- dev->device_issue_pending(chan);
++ if (!next)
++ return;
++
++ tx->next = NULL;
++ chan = next->chan;
++
++ /* keep submitting up until a channel switch is detected
++ * in that case we will be called again as a result of
++ * processing the interrupt from async_tx_channel_switch
++ */
++ while (next && next->chan == chan) {
++ struct dma_async_tx_descriptor *_next;
++
++ spin_lock_bh(&next->lock);
++ next->parent = NULL;
++ _next = next->next;
++ next->next = NULL;
++ spin_unlock_bh(&next->lock);
++
++ next->tx_submit(next);
++ next = _next;
+ }
++
++ chan->device->device_issue_pending(chan);
+ }
+ EXPORT_SYMBOL_GPL(async_tx_run_dependencies);
+
+@@ -397,6 +412,92 @@ static void __exit async_tx_exit(void)
+ }
+ #endif
+
++
++/**
++ * async_tx_channel_switch - queue an interrupt descriptor with a dependency
++ * pre-attached.
++ * @depend_tx: the operation that must finish before the new operation runs
++ * @tx: the new operation
++ */
++static void
++async_tx_channel_switch(struct dma_async_tx_descriptor *depend_tx,
++ struct dma_async_tx_descriptor *tx)
++{
++ struct dma_chan *chan;
++ struct dma_device *device;
++ struct dma_async_tx_descriptor *intr_tx = (void *) ~0;
++
++ /* first check to see if we can still append to depend_tx */
++ spin_lock_bh(&depend_tx->lock);
++ if (depend_tx->parent && depend_tx->chan == tx->chan) {
++ tx->parent = depend_tx;
++ depend_tx->next = tx;
++ intr_tx = NULL;
++ }
++ spin_unlock_bh(&depend_tx->lock);
++
++ if (!intr_tx)
++ return;
++
++ chan = depend_tx->chan;
++ device = chan->device;
++
++ /* see if we can schedule an interrupt
++ * otherwise poll for completion
++ */
++ if (dma_has_cap(DMA_INTERRUPT, device->cap_mask))
++ intr_tx = device->device_prep_dma_interrupt(chan, 0);
++ else
++ intr_tx = NULL;
++
++ if (intr_tx) {
++ intr_tx->callback = NULL;
++ intr_tx->callback_param = NULL;
++ tx->parent = intr_tx;
++ /* safe to set ->next outside the lock since we know we are
++ * not submitted yet
++ */
++ intr_tx->next = tx;
++
++ /* check if we need to append */
++ spin_lock_bh(&depend_tx->lock);
++ if (depend_tx->parent) {
++ intr_tx->parent = depend_tx;
++ depend_tx->next = intr_tx;
++ async_tx_ack(intr_tx);
++ intr_tx = NULL;
++ }
++ spin_unlock_bh(&depend_tx->lock);
++
++ if (intr_tx) {
++ intr_tx->parent = NULL;
++ intr_tx->tx_submit(intr_tx);
++ async_tx_ack(intr_tx);
++ }
++ } else {
++ if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
++ panic("%s: DMA_ERROR waiting for depend_tx\n",
++ __func__);
++ tx->tx_submit(tx);
++ }
++}
++
++
++/**
++ * submit_disposition - while holding depend_tx->lock we must avoid submitting
++ * new operations to prevent a circular locking dependency with
++ * drivers that already hold a channel lock when calling
++ * async_tx_run_dependencies.
++ * @ASYNC_TX_SUBMITTED: we were able to append the new operation under the lock
++ * @ASYNC_TX_CHANNEL_SWITCH: when the lock is dropped schedule a channel switch
++ * @ASYNC_TX_DIRECT_SUBMIT: when the lock is dropped submit directly
++ */
++enum submit_disposition {
++ ASYNC_TX_SUBMITTED,
++ ASYNC_TX_CHANNEL_SWITCH,
++ ASYNC_TX_DIRECT_SUBMIT,
++};
++
+ void
+ async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx,
+ enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,
+@@ -405,28 +506,55 @@ async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx,
+ tx->callback = cb_fn;
+ tx->callback_param = cb_param;
+
+- /* set this new tx to run after depend_tx if:
+- * 1/ a dependency exists (depend_tx is !NULL)
+- * 2/ the tx can not be submitted to the current channel
+- */
+- if (depend_tx && depend_tx->chan != chan) {
+- /* if ack is already set then we cannot be sure
++ if (depend_tx) {
++ enum submit_disposition s;
++
++ /* sanity check the dependency chain:
++ * 1/ if ack is already set then we cannot be sure
+ * we are referring to the correct operation
++ * 2/ dependencies are 1:1 i.e. two transactions can
++ * not depend on the same parent
+ */
+- BUG_ON(depend_tx->ack);
++ BUG_ON(async_tx_test_ack(depend_tx) || depend_tx->next ||
++ tx->parent);
+
+- tx->parent = depend_tx;
++ /* the lock prevents async_tx_run_dependencies from missing
++ * the setting of ->next when ->parent != NULL
++ */
+ spin_lock_bh(&depend_tx->lock);
+- list_add_tail(&tx->depend_node, &depend_tx->depend_list);
+- if (depend_tx->cookie == 0) {
+- struct dma_chan *dep_chan = depend_tx->chan;
+- struct dma_device *dep_dev = dep_chan->device;
+- dep_dev->device_dependency_added(dep_chan);
++ if (depend_tx->parent) {
++ /* we have a parent so we can not submit directly
++ * if we are staying on the same channel: append
++ * else: channel switch
++ */
++ if (depend_tx->chan == chan) {
++ tx->parent = depend_tx;
++ depend_tx->next = tx;
++ s = ASYNC_TX_SUBMITTED;
++ } else
++ s = ASYNC_TX_CHANNEL_SWITCH;
++ } else {
++ /* we do not have a parent so we may be able to submit
++ * directly if we are staying on the same channel
++ */
++ if (depend_tx->chan == chan)
++ s = ASYNC_TX_DIRECT_SUBMIT;
++ else
++ s = ASYNC_TX_CHANNEL_SWITCH;
+ }
+ spin_unlock_bh(&depend_tx->lock);
+
+- /* schedule an interrupt to trigger the channel switch */
+- async_trigger_callback(ASYNC_TX_ACK, depend_tx, NULL, NULL);
++ switch (s) {
++ case ASYNC_TX_SUBMITTED:
++ break;
++ case ASYNC_TX_CHANNEL_SWITCH:
++ async_tx_channel_switch(depend_tx, tx);
++ break;
++ case ASYNC_TX_DIRECT_SUBMIT:
++ tx->parent = NULL;
++ tx->tx_submit(tx);
++ break;
++ }
+ } else {
+ tx->parent = NULL;
+ tx->tx_submit(tx);
+@@ -467,7 +595,7 @@ async_trigger_callback(enum async_tx_flags flags,
+ if (device && !dma_has_cap(DMA_INTERRUPT, device->cap_mask))
+ device = NULL;
+
+- tx = device ? device->device_prep_dma_interrupt(chan) : NULL;
++ tx = device ? device->device_prep_dma_interrupt(chan, 0) : NULL;
+ } else
+ tx = NULL;
+
+@@ -483,7 +611,7 @@ async_trigger_callback(enum async_tx_flags flags,
+ /* if ack is already set then we cannot be sure
+ * we are referring to the correct operation
+ */
+- BUG_ON(depend_tx->ack);
++ BUG_ON(async_tx_test_ack(depend_tx));
+ if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
+ panic("%s: DMA_ERROR waiting for depend_tx\n",
+ __func__);
+diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c
+index 1c445c7..3a0dddc 100644
+--- a/crypto/async_tx/async_xor.c
++++ b/crypto/async_tx/async_xor.c
+@@ -191,7 +191,7 @@ async_xor(struct page *dest, struct page **src_list, unsigned int offset,
+ /* if ack is already set then we cannot be sure
+ * we are referring to the correct operation
+ */
+- BUG_ON(depend_tx->ack);
++ BUG_ON(async_tx_test_ack(depend_tx));
+ if (dma_wait_for_async_tx(depend_tx) ==
+ DMA_ERROR)
+ panic("%s: DMA_ERROR waiting for "
+diff --git a/crypto/blowfish.c b/crypto/blowfish.c
+index 80c3fd8..6f5b487 100644
+--- a/crypto/blowfish.c
++++ b/crypto/blowfish.c
+@@ -465,18 +465,18 @@ static struct crypto_alg alg = {
+ .cia_decrypt = bf_decrypt } }
+ };
+
+-static int __init init(void)
++static int __init blowfish_mod_init(void)
+ {
+ return crypto_register_alg(&alg);
+ }
+
+-static void __exit fini(void)
++static void __exit blowfish_mod_fini(void)
+ {
+ crypto_unregister_alg(&alg);
+ }
+
+-module_init(init);
+-module_exit(fini);
++module_init(blowfish_mod_init);
++module_exit(blowfish_mod_fini);
+
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Blowfish Cipher Algorithm");
+diff --git a/crypto/cast5.c b/crypto/cast5.c
+index 13ea60a..8cbe28f 100644
+--- a/crypto/cast5.c
++++ b/crypto/cast5.c
+@@ -817,18 +817,18 @@ static struct crypto_alg alg = {
+ }
+ };
+
+-static int __init init(void)
++static int __init cast5_mod_init(void)
+ {
+ return crypto_register_alg(&alg);
+ }
+
+-static void __exit fini(void)
++static void __exit cast5_mod_fini(void)
+ {
+ crypto_unregister_alg(&alg);
+ }
+
+-module_init(init);
+-module_exit(fini);
++module_init(cast5_mod_init);
++module_exit(cast5_mod_fini);
+
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Cast5 Cipher Algorithm");
+diff --git a/crypto/cast6.c b/crypto/cast6.c
+index 5fd9420..007d02b 100644
+--- a/crypto/cast6.c
++++ b/crypto/cast6.c
+@@ -528,18 +528,18 @@ static struct crypto_alg alg = {
+ }
+ };
+
+-static int __init init(void)
++static int __init cast6_mod_init(void)
+ {
+ return crypto_register_alg(&alg);
+ }
+
+-static void __exit fini(void)
++static void __exit cast6_mod_fini(void)
+ {
+ crypto_unregister_alg(&alg);
+ }
+
+-module_init(init);
+-module_exit(fini);
++module_init(cast6_mod_init);
++module_exit(cast6_mod_fini);
+
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Cast6 Cipher Algorithm");
+diff --git a/crypto/crc32c.c b/crypto/crc32c.c
+index 0fa7443..0dcf64a 100644
+--- a/crypto/crc32c.c
++++ b/crypto/crc32c.c
+@@ -98,18 +98,18 @@ static struct crypto_alg alg = {
+ }
+ };
+
+-static int __init init(void)
++static int __init crc32c_mod_init(void)
+ {
+ return crypto_register_alg(&alg);
+ }
+
+-static void __exit fini(void)
++static void __exit crc32c_mod_fini(void)
+ {
+ crypto_unregister_alg(&alg);
+ }
+
+-module_init(init);
+-module_exit(fini);
++module_init(crc32c_mod_init);
++module_exit(crc32c_mod_fini);
+
+ MODULE_AUTHOR("Clay Haapala <chaapala at cisco.com>");
+ MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c");
+diff --git a/crypto/crypto_null.c b/crypto/crypto_null.c
+index ff7b3de..1f7d530 100644
+--- a/crypto/crypto_null.c
++++ b/crypto/crypto_null.c
+@@ -142,7 +142,7 @@ MODULE_ALIAS("compress_null");
+ MODULE_ALIAS("digest_null");
+ MODULE_ALIAS("cipher_null");
+
+-static int __init init(void)
++static int __init crypto_null_mod_init(void)
+ {
+ int ret = 0;
+
+@@ -174,7 +174,7 @@ out_unregister_cipher:
+ goto out;
+ }
+
+-static void __exit fini(void)
++static void __exit crypto_null_mod_fini(void)
+ {
+ crypto_unregister_alg(&compress_null);
+ crypto_unregister_alg(&digest_null);
+@@ -182,8 +182,8 @@ static void __exit fini(void)
+ crypto_unregister_alg(&cipher_null);
+ }
+
+-module_init(init);
+-module_exit(fini);
++module_init(crypto_null_mod_init);
++module_exit(crypto_null_mod_fini);
+
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Null Cryptographic Algorithms");
+diff --git a/crypto/cts.c b/crypto/cts.c
+new file mode 100644
+index 0000000..c4e70bf
+--- /dev/null
++++ b/crypto/cts.c
+@@ -0,0 +1,347 @@
++/*
++ * CTS: Cipher Text Stealing mode
++ *
++ * COPYRIGHT (c) 2008
++ * The Regents of the University of Michigan
++ * ALL RIGHTS RESERVED
++ *
++ * Permission is granted to use, copy, create derivative works
++ * and redistribute this software and such derivative works
++ * for any purpose, so long as the name of The University of
++ * Michigan is not used in any advertising or publicity
++ * pertaining to the use of distribution of this software
++ * without specific, written prior authorization. If the
++ * above copyright notice or any other identification of the
++ * University of Michigan is included in any copy of any
++ * portion of this software, then the disclaimer below must
++ * also be included.
++ *
++ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
++ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
++ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
++ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
++ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
++ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
++ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
++ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
++ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
++ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGES.
++ */
++
++/* Derived from various:
++ * Copyright (c) 2006 Herbert Xu <herbert at gondor.apana.org.au>
++ */
++
++/*
++ * This is the Cipher Text Stealing mode as described by
++ * Section 8 of rfc2040 and referenced by rfc3962.
++ * rfc3962 includes errata information in its Appendix A.
++ */
++
++#include <crypto/algapi.h>
++#include <linux/err.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/log2.h>
++#include <linux/module.h>
++#include <linux/scatterlist.h>
++#include <crypto/scatterwalk.h>
++#include <linux/slab.h>
++
++struct crypto_cts_ctx {
++ struct crypto_blkcipher *child;
++};
++
++static int crypto_cts_setkey(struct crypto_tfm *parent, const u8 *key,
++ unsigned int keylen)
++{
++ struct crypto_cts_ctx *ctx = crypto_tfm_ctx(parent);
++ struct crypto_blkcipher *child = ctx->child;
++ int err;
++
++ crypto_blkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
++ crypto_blkcipher_set_flags(child, crypto_tfm_get_flags(parent) &
++ CRYPTO_TFM_REQ_MASK);
++ err = crypto_blkcipher_setkey(child, key, keylen);
++ crypto_tfm_set_flags(parent, crypto_blkcipher_get_flags(child) &
++ CRYPTO_TFM_RES_MASK);
++ return err;
++}
++
++static int cts_cbc_encrypt(struct crypto_cts_ctx *ctx,
++ struct blkcipher_desc *desc,
++ struct scatterlist *dst,
++ struct scatterlist *src,
++ unsigned int offset,
++ unsigned int nbytes)
++{
++ int bsize = crypto_blkcipher_blocksize(desc->tfm);
++ u8 tmp[bsize], tmp2[bsize];
++ struct blkcipher_desc lcldesc;
++ struct scatterlist sgsrc[1], sgdst[1];
++ int lastn = nbytes - bsize;
++ u8 iv[bsize];
++ u8 s[bsize * 2], d[bsize * 2];
++ int err;
++
++ if (lastn < 0)
++ return -EINVAL;
++
++ memset(s, 0, sizeof(s));
++ scatterwalk_map_and_copy(s, src, offset, nbytes, 0);
++
++ memcpy(iv, desc->info, bsize);
++
++ lcldesc.tfm = ctx->child;
++ lcldesc.info = iv;
++ lcldesc.flags = desc->flags;
++
++ sg_set_buf(&sgsrc[0], s, bsize);
++ sg_set_buf(&sgdst[0], tmp, bsize);
++ err = crypto_blkcipher_encrypt_iv(&lcldesc, sgdst, sgsrc, bsize);
++
++ memcpy(d + bsize, tmp, lastn);
++
++ lcldesc.info = tmp;
++
++ sg_set_buf(&sgsrc[0], s + bsize, bsize);
++ sg_set_buf(&sgdst[0], tmp2, bsize);
++ err = crypto_blkcipher_encrypt_iv(&lcldesc, sgdst, sgsrc, bsize);
++
++ memcpy(d, tmp2, bsize);
++
++ scatterwalk_map_and_copy(d, dst, offset, nbytes, 1);
++
++ memcpy(desc->info, tmp2, bsize);
++
++ return err;
++}
++
++static int crypto_cts_encrypt(struct blkcipher_desc *desc,
++ struct scatterlist *dst, struct scatterlist *src,
++ unsigned int nbytes)
++{
++ struct crypto_cts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
++ int bsize = crypto_blkcipher_blocksize(desc->tfm);
++ int tot_blocks = (nbytes + bsize - 1) / bsize;
++ int cbc_blocks = tot_blocks > 2 ? tot_blocks - 2 : 0;
++ struct blkcipher_desc lcldesc;
++ int err;
++
++ lcldesc.tfm = ctx->child;
++ lcldesc.info = desc->info;
++ lcldesc.flags = desc->flags;
++
++ if (tot_blocks == 1) {
++ err = crypto_blkcipher_encrypt_iv(&lcldesc, dst, src, bsize);
++ } else if (nbytes <= bsize * 2) {
++ err = cts_cbc_encrypt(ctx, desc, dst, src, 0, nbytes);
++ } else {
++ /* do normal function for tot_blocks - 2 */
++ err = crypto_blkcipher_encrypt_iv(&lcldesc, dst, src,
++ cbc_blocks * bsize);
++ if (err == 0) {
++ /* do cts for final two blocks */
++ err = cts_cbc_encrypt(ctx, desc, dst, src,
++ cbc_blocks * bsize,
++ nbytes - (cbc_blocks * bsize));
++ }
++ }
++
++ return err;
++}
++
++static int cts_cbc_decrypt(struct crypto_cts_ctx *ctx,
++ struct blkcipher_desc *desc,
++ struct scatterlist *dst,
++ struct scatterlist *src,
++ unsigned int offset,
++ unsigned int nbytes)
++{
++ int bsize = crypto_blkcipher_blocksize(desc->tfm);
++ u8 tmp[bsize];
++ struct blkcipher_desc lcldesc;
++ struct scatterlist sgsrc[1], sgdst[1];
++ int lastn = nbytes - bsize;
++ u8 iv[bsize];
++ u8 s[bsize * 2], d[bsize * 2];
++ int err;
++
++ if (lastn < 0)
++ return -EINVAL;
++
++ scatterwalk_map_and_copy(s, src, offset, nbytes, 0);
++
++ lcldesc.tfm = ctx->child;
++ lcldesc.info = iv;
++ lcldesc.flags = desc->flags;
++
++ /* 1. Decrypt Cn-1 (s) to create Dn (tmp)*/
++ memset(iv, 0, sizeof(iv));
++ sg_set_buf(&sgsrc[0], s, bsize);
++ sg_set_buf(&sgdst[0], tmp, bsize);
++ err = crypto_blkcipher_decrypt_iv(&lcldesc, sgdst, sgsrc, bsize);
++ if (err)
++ return err;
++ /* 2. Pad Cn with zeros at the end to create C of length BB */
++ memset(iv, 0, sizeof(iv));
++ memcpy(iv, s + bsize, lastn);
++ /* 3. Exclusive-or Dn (tmp) with C (iv) to create Xn (tmp) */
++ crypto_xor(tmp, iv, bsize);
++ /* 4. Select the first Ln bytes of Xn (tmp) to create Pn */
++ memcpy(d + bsize, tmp, lastn);
++
++ /* 5. Append the tail (BB - Ln) bytes of Xn (tmp) to Cn to create En */
++ memcpy(s + bsize + lastn, tmp + lastn, bsize - lastn);
++ /* 6. Decrypt En to create Pn-1 */
++ memset(iv, 0, sizeof(iv));
++ sg_set_buf(&sgsrc[0], s + bsize, bsize);
++ sg_set_buf(&sgdst[0], d, bsize);
++ err = crypto_blkcipher_decrypt_iv(&lcldesc, sgdst, sgsrc, bsize);
++
++ /* XOR with previous block */
++ crypto_xor(d, desc->info, bsize);
++
++ scatterwalk_map_and_copy(d, dst, offset, nbytes, 1);
++
++ memcpy(desc->info, s, bsize);
++ return err;
++}
++
++static int crypto_cts_decrypt(struct blkcipher_desc *desc,
++ struct scatterlist *dst, struct scatterlist *src,
++ unsigned int nbytes)
++{
++ struct crypto_cts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
++ int bsize = crypto_blkcipher_blocksize(desc->tfm);
++ int tot_blocks = (nbytes + bsize - 1) / bsize;
++ int cbc_blocks = tot_blocks > 2 ? tot_blocks - 2 : 0;
++ struct blkcipher_desc lcldesc;
++ int err;
++
++ lcldesc.tfm = ctx->child;
++ lcldesc.info = desc->info;
++ lcldesc.flags = desc->flags;
++
++ if (tot_blocks == 1) {
++ err = crypto_blkcipher_decrypt_iv(&lcldesc, dst, src, bsize);
++ } else if (nbytes <= bsize * 2) {
++ err = cts_cbc_decrypt(ctx, desc, dst, src, 0, nbytes);
++ } else {
++ /* do normal function for tot_blocks - 2 */
++ err = crypto_blkcipher_decrypt_iv(&lcldesc, dst, src,
++ cbc_blocks * bsize);
++ if (err == 0) {
++ /* do cts for final two blocks */
++ err = cts_cbc_decrypt(ctx, desc, dst, src,
++ cbc_blocks * bsize,
++ nbytes - (cbc_blocks * bsize));
++ }
++ }
++ return err;
++}
++
++static int crypto_cts_init_tfm(struct crypto_tfm *tfm)
++{
++ struct crypto_instance *inst = (void *)tfm->__crt_alg;
++ struct crypto_spawn *spawn = crypto_instance_ctx(inst);
++ struct crypto_cts_ctx *ctx = crypto_tfm_ctx(tfm);
++ struct crypto_blkcipher *cipher;
++
++ cipher = crypto_spawn_blkcipher(spawn);
++ if (IS_ERR(cipher))
++ return PTR_ERR(cipher);
++
++ ctx->child = cipher;
++ return 0;
++}
++
++static void crypto_cts_exit_tfm(struct crypto_tfm *tfm)
++{
++ struct crypto_cts_ctx *ctx = crypto_tfm_ctx(tfm);
++ crypto_free_blkcipher(ctx->child);
++}
++
++static struct crypto_instance *crypto_cts_alloc(struct rtattr **tb)
++{
++ struct crypto_instance *inst;
++ struct crypto_alg *alg;
++ int err;
++
++ err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
++ if (err)
++ return ERR_PTR(err);
++
++ alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_BLKCIPHER,
++ CRYPTO_ALG_TYPE_MASK);
++ err = PTR_ERR(alg);
++ if (IS_ERR(alg))
++ return ERR_PTR(err);
++
++ inst = ERR_PTR(-EINVAL);
++ if (!is_power_of_2(alg->cra_blocksize))
++ goto out_put_alg;
++
++ inst = crypto_alloc_instance("cts", alg);
++ if (IS_ERR(inst))
++ goto out_put_alg;
++
++ inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
++ inst->alg.cra_priority = alg->cra_priority;
++ inst->alg.cra_blocksize = alg->cra_blocksize;
++ inst->alg.cra_alignmask = alg->cra_alignmask;
++ inst->alg.cra_type = &crypto_blkcipher_type;
++
++ /* We access the data as u32s when xoring. */
++ inst->alg.cra_alignmask |= __alignof__(u32) - 1;
++
++ inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
++ inst->alg.cra_blkcipher.min_keysize = alg->cra_blkcipher.min_keysize;
++ inst->alg.cra_blkcipher.max_keysize = alg->cra_blkcipher.max_keysize;
++
++ inst->alg.cra_blkcipher.geniv = "seqiv";
++
++ inst->alg.cra_ctxsize = sizeof(struct crypto_cts_ctx);
++
++ inst->alg.cra_init = crypto_cts_init_tfm;
++ inst->alg.cra_exit = crypto_cts_exit_tfm;
++
++ inst->alg.cra_blkcipher.setkey = crypto_cts_setkey;
++ inst->alg.cra_blkcipher.encrypt = crypto_cts_encrypt;
++ inst->alg.cra_blkcipher.decrypt = crypto_cts_decrypt;
++
++out_put_alg:
++ crypto_mod_put(alg);
++ return inst;
++}
++
++static void crypto_cts_free(struct crypto_instance *inst)
++{
++ crypto_drop_spawn(crypto_instance_ctx(inst));
++ kfree(inst);
++}
++
++static struct crypto_template crypto_cts_tmpl = {
++ .name = "cts",
++ .alloc = crypto_cts_alloc,
++ .free = crypto_cts_free,
++ .module = THIS_MODULE,
++};
++
++static int __init crypto_cts_module_init(void)
++{
++ return crypto_register_template(&crypto_cts_tmpl);
++}
++
++static void __exit crypto_cts_module_exit(void)
++{
++ crypto_unregister_template(&crypto_cts_tmpl);
++}
++
++module_init(crypto_cts_module_init);
++module_exit(crypto_cts_module_exit);
++
++MODULE_LICENSE("Dual BSD/GPL");
++MODULE_DESCRIPTION("CTS-CBC CipherText Stealing for CBC");
+diff --git a/crypto/deflate.c b/crypto/deflate.c
+index 6588bbf..9128da4 100644
+--- a/crypto/deflate.c
++++ b/crypto/deflate.c
+@@ -208,18 +208,18 @@ static struct crypto_alg alg = {
+ .coa_decompress = deflate_decompress } }
+ };
+
+-static int __init init(void)
++static int __init deflate_mod_init(void)
+ {
+ return crypto_register_alg(&alg);
+ }
+
+-static void __exit fini(void)
++static void __exit deflate_mod_fini(void)
+ {
+ crypto_unregister_alg(&alg);
+ }
+
+-module_init(init);
+-module_exit(fini);
++module_init(deflate_mod_init);
++module_exit(deflate_mod_fini);
+
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Deflate Compression Algorithm for IPCOMP");
+diff --git a/crypto/des_generic.c b/crypto/des_generic.c
+index 355ecb7..5d0e458 100644
+--- a/crypto/des_generic.c
++++ b/crypto/des_generic.c
+@@ -977,7 +977,7 @@ static struct crypto_alg des3_ede_alg = {
+
+ MODULE_ALIAS("des3_ede");
+
+-static int __init init(void)
++static int __init des_generic_mod_init(void)
+ {
+ int ret = 0;
+
+@@ -992,14 +992,14 @@ out:
+ return ret;
+ }
+
+-static void __exit fini(void)
++static void __exit des_generic_mod_fini(void)
+ {
+ crypto_unregister_alg(&des3_ede_alg);
+ crypto_unregister_alg(&des_alg);
+ }
+
+-module_init(init);
+-module_exit(fini);
++module_init(des_generic_mod_init);
++module_exit(des_generic_mod_fini);
+
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms");
+diff --git a/crypto/fcrypt.c b/crypto/fcrypt.c
+index a32cb68..1302f4c 100644
+--- a/crypto/fcrypt.c
++++ b/crypto/fcrypt.c
+@@ -405,18 +405,18 @@ static struct crypto_alg fcrypt_alg = {
+ .cia_decrypt = fcrypt_decrypt } }
+ };
+
+-static int __init init(void)
++static int __init fcrypt_mod_init(void)
+ {
+ return crypto_register_alg(&fcrypt_alg);
+ }
+
+-static void __exit fini(void)
++static void __exit fcrypt_mod_fini(void)
+ {
+ crypto_unregister_alg(&fcrypt_alg);
+ }
+
+-module_init(init);
+-module_exit(fini);
++module_init(fcrypt_mod_init);
++module_exit(fcrypt_mod_fini);
+
+ MODULE_LICENSE("Dual BSD/GPL");
+ MODULE_DESCRIPTION("FCrypt Cipher Algorithm");
+diff --git a/crypto/khazad.c b/crypto/khazad.c
+index 704ebfe..527e4e3 100644
+--- a/crypto/khazad.c
++++ b/crypto/khazad.c
+@@ -862,7 +862,7 @@ static struct crypto_alg khazad_alg = {
+ .cia_decrypt = khazad_decrypt } }
+ };
+
+-static int __init init(void)
++static int __init khazad_mod_init(void)
+ {
+ int ret = 0;
+
+@@ -870,14 +870,14 @@ static int __init init(void)
+ return ret;
+ }
+
+-static void __exit fini(void)
++static void __exit khazad_mod_fini(void)
+ {
+ crypto_unregister_alg(&khazad_alg);
+ }
+
+
+-module_init(init);
+-module_exit(fini);
++module_init(khazad_mod_init);
++module_exit(khazad_mod_fini);
+
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Khazad Cryptographic Algorithm");
+diff --git a/crypto/lrw.c b/crypto/lrw.c
+index 9d52e58..8ef664e 100644
+--- a/crypto/lrw.c
++++ b/crypto/lrw.c
+@@ -91,8 +91,9 @@ struct sinfo {
+
+ static inline void inc(be128 *iv)
+ {
+- if (!(iv->b = cpu_to_be64(be64_to_cpu(iv->b) + 1)))
+- iv->a = cpu_to_be64(be64_to_cpu(iv->a) + 1);
++ be64_add_cpu(&iv->b, 1);
++ if (!iv->b)
++ be64_add_cpu(&iv->a, 1);
+ }
+
+ static inline void lrw_round(struct sinfo *s, void *dst, const void *src)
+diff --git a/crypto/lzo.c b/crypto/lzo.c
+index 48c3288..b5e7707 100644
+--- a/crypto/lzo.c
++++ b/crypto/lzo.c
+@@ -89,18 +89,18 @@ static struct crypto_alg alg = {
+ .coa_decompress = lzo_decompress } }
+ };
+
+-static int __init init(void)
++static int __init lzo_mod_init(void)
+ {
+ return crypto_register_alg(&alg);
+ }
+
+-static void __exit fini(void)
++static void __exit lzo_mod_fini(void)
+ {
+ crypto_unregister_alg(&alg);
+ }
+
+-module_init(init);
+-module_exit(fini);
++module_init(lzo_mod_init);
++module_exit(lzo_mod_fini);
+
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("LZO Compression Algorithm");
+diff --git a/crypto/md4.c b/crypto/md4.c
+index c1bc71b..3c19aa0 100644
+--- a/crypto/md4.c
++++ b/crypto/md4.c
+@@ -233,18 +233,18 @@ static struct crypto_alg alg = {
+ .dia_final = md4_final } }
+ };
+
+-static int __init init(void)
++static int __init md4_mod_init(void)
+ {
+ return crypto_register_alg(&alg);
+ }
+
+-static void __exit fini(void)
++static void __exit md4_mod_fini(void)
+ {
+ crypto_unregister_alg(&alg);
+ }
+
+-module_init(init);
+-module_exit(fini);
++module_init(md4_mod_init);
++module_exit(md4_mod_fini);
+
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("MD4 Message Digest Algorithm");
+diff --git a/crypto/md5.c b/crypto/md5.c
+index 93d18e8..39268f3 100644
+--- a/crypto/md5.c
++++ b/crypto/md5.c
+@@ -228,18 +228,18 @@ static struct crypto_alg alg = {
+ .dia_final = md5_final } }
+ };
+
+-static int __init init(void)
++static int __init md5_mod_init(void)
+ {
+ return crypto_register_alg(&alg);
+ }
+
+-static void __exit fini(void)
++static void __exit md5_mod_fini(void)
+ {
+ crypto_unregister_alg(&alg);
+ }
+
+-module_init(init);
+-module_exit(fini);
++module_init(md5_mod_init);
++module_exit(md5_mod_fini);
+
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("MD5 Message Digest Algorithm");
+diff --git a/crypto/proc.c b/crypto/proc.c
+index 3d73323..02ff567 100644
+--- a/crypto/proc.c
++++ b/crypto/proc.c
+@@ -78,7 +78,7 @@ static int c_show(struct seq_file *m, void *p)
+ return 0;
+ }
+
+-static struct seq_operations crypto_seq_ops = {
++static const struct seq_operations crypto_seq_ops = {
+ .start = c_start,
+ .next = c_next,
+ .stop = c_stop,
+@@ -99,11 +99,7 @@ static const struct file_operations proc_crypto_ops = {
+
+ void __init crypto_init_proc(void)
+ {
+- struct proc_dir_entry *proc;
+-
+- proc = create_proc_entry("crypto", 0, NULL);
+- if (proc)
+- proc->proc_fops = &proc_crypto_ops;
++ proc_create("crypto", 0, NULL, &proc_crypto_ops);
+ }
+
+ void __exit crypto_exit_proc(void)
+diff --git a/crypto/salsa20_generic.c b/crypto/salsa20_generic.c
+index 1fa4e4d..b07d559 100644
+--- a/crypto/salsa20_generic.c
++++ b/crypto/salsa20_generic.c
+@@ -237,18 +237,18 @@ static struct crypto_alg alg = {
+ }
+ };
+
+-static int __init init(void)
++static int __init salsa20_generic_mod_init(void)
+ {
+ return crypto_register_alg(&alg);
+ }
+
+-static void __exit fini(void)
++static void __exit salsa20_generic_mod_fini(void)
+ {
+ crypto_unregister_alg(&alg);
+ }
+
+-module_init(init);
+-module_exit(fini);
++module_init(salsa20_generic_mod_init);
++module_exit(salsa20_generic_mod_fini);
+
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION ("Salsa20 stream cipher algorithm");
+diff --git a/crypto/serpent.c b/crypto/serpent.c
+index 2b0a19a..b651a55 100644
+--- a/crypto/serpent.c
++++ b/crypto/serpent.c
+@@ -557,7 +557,7 @@ static struct crypto_alg tnepres_alg = {
+ .cia_decrypt = tnepres_decrypt } }
+ };
+
+-static int __init init(void)
++static int __init serpent_mod_init(void)
+ {
+ int ret = crypto_register_alg(&serpent_alg);
+
+@@ -572,14 +572,14 @@ static int __init init(void)
+ return ret;
+ }
+
+-static void __exit fini(void)
++static void __exit serpent_mod_fini(void)
+ {
+ crypto_unregister_alg(&tnepres_alg);
+ crypto_unregister_alg(&serpent_alg);
+ }
+
+-module_init(init);
+-module_exit(fini);
++module_init(serpent_mod_init);
++module_exit(serpent_mod_fini);
+
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Serpent and tnepres (kerneli compatible serpent reversed) Cipher Algorithm");
+diff --git a/crypto/sha1_generic.c b/crypto/sha1_generic.c
+index 68c62f5..c7c6899 100644
+--- a/crypto/sha1_generic.c
++++ b/crypto/sha1_generic.c
+@@ -120,18 +120,18 @@ static struct crypto_alg alg = {
+ .dia_final = sha1_final } }
+ };
+
+-static int __init init(void)
++static int __init sha1_generic_mod_init(void)
+ {
+ return crypto_register_alg(&alg);
+ }
+
+-static void __exit fini(void)
++static void __exit sha1_generic_mod_fini(void)
+ {
+ crypto_unregister_alg(&alg);
+ }
+
+-module_init(init);
+-module_exit(fini);
++module_init(sha1_generic_mod_init);
++module_exit(sha1_generic_mod_fini);
+
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm");
+diff --git a/crypto/sha256_generic.c b/crypto/sha256_generic.c
+index 3cc93fd..5a8dd47 100644
+--- a/crypto/sha256_generic.c
++++ b/crypto/sha256_generic.c
+@@ -353,7 +353,7 @@ static struct crypto_alg sha224 = {
+ .dia_final = sha224_final } }
+ };
+
+-static int __init init(void)
++static int __init sha256_generic_mod_init(void)
+ {
+ int ret = 0;
+
+@@ -370,14 +370,14 @@ static int __init init(void)
+ return ret;
+ }
+
+-static void __exit fini(void)
++static void __exit sha256_generic_mod_fini(void)
+ {
+ crypto_unregister_alg(&sha224);
+ crypto_unregister_alg(&sha256);
+ }
+
+-module_init(init);
+-module_exit(fini);
++module_init(sha256_generic_mod_init);
++module_exit(sha256_generic_mod_fini);
+
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("SHA-224 and SHA-256 Secure Hash Algorithm");
+diff --git a/crypto/sha512.c b/crypto/sha512.c
+deleted file mode 100644
+index c39c803..0000000
+--- a/crypto/sha512.c
++++ /dev/null
+@@ -1,305 +0,0 @@
+-/* SHA-512 code by Jean-Luc Cooke <jlcooke at certainkey.com>
+- *
+- * Copyright (c) Jean-Luc Cooke <jlcooke at certainkey.com>
+- * Copyright (c) Andrew McDonald <andrew at mcdonald.org.uk>
+- * Copyright (c) 2003 Kyle McMartin <kyle at debian.org>
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the
+- * Free Software Foundation; either version 2, or (at your option) any
+- * later version.
+- *
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-#include <linux/mm.h>
+-#include <linux/init.h>
+-#include <linux/crypto.h>
+-#include <linux/types.h>
+-#include <crypto/sha.h>
+-
+-#include <asm/byteorder.h>
+-
+-struct sha512_ctx {
+- u64 state[8];
+- u32 count[4];
+- u8 buf[128];
+- u64 W[80];
+-};
+-
+-static inline u64 Ch(u64 x, u64 y, u64 z)
+-{
+- return z ^ (x & (y ^ z));
+-}
+-
+-static inline u64 Maj(u64 x, u64 y, u64 z)
+-{
+- return (x & y) | (z & (x | y));
+-}
+-
+-static inline u64 RORu64(u64 x, u64 y)
+-{
+- return (x >> y) | (x << (64 - y));
+-}
+-
+-static const u64 sha512_K[80] = {
+- 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
+- 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+- 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
+- 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+- 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
+- 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+- 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
+- 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+- 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
+- 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+- 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
+- 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+- 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
+- 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+- 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
+- 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+- 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
+- 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+- 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
+- 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+- 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
+- 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+- 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
+- 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+- 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
+- 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+- 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL,
+-};
+-
+-#define e0(x) (RORu64(x,28) ^ RORu64(x,34) ^ RORu64(x,39))
+-#define e1(x) (RORu64(x,14) ^ RORu64(x,18) ^ RORu64(x,41))
+-#define s0(x) (RORu64(x, 1) ^ RORu64(x, 8) ^ (x >> 7))
+-#define s1(x) (RORu64(x,19) ^ RORu64(x,61) ^ (x >> 6))
+-
+-static inline void LOAD_OP(int I, u64 *W, const u8 *input)
+-{
+- W[I] = __be64_to_cpu( ((__be64*)(input))[I] );
+-}
+-
+-static inline void BLEND_OP(int I, u64 *W)
+-{
+- W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
+-}
+-
+-static void
+-sha512_transform(u64 *state, u64 *W, const u8 *input)
+-{
+- u64 a, b, c, d, e, f, g, h, t1, t2;
+-
+- int i;
+-
+- /* load the input */
+- for (i = 0; i < 16; i++)
+- LOAD_OP(i, W, input);
+-
+- for (i = 16; i < 80; i++) {
+- BLEND_OP(i, W);
+- }
+-
+- /* load the state into our registers */
+- a=state[0]; b=state[1]; c=state[2]; d=state[3];
+- e=state[4]; f=state[5]; g=state[6]; h=state[7];
+-
+- /* now iterate */
+- for (i=0; i<80; i+=8) {
+- t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i ] + W[i ];
+- t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2;
+- t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[i+1];
+- t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2;
+- t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[i+2];
+- t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2;
+- t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[i+3];
+- t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2;
+- t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[i+4];
+- t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2;
+- t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[i+5];
+- t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2;
+- t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[i+6];
+- t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2;
+- t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[i+7];
+- t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2;
+- }
+-
+- state[0] += a; state[1] += b; state[2] += c; state[3] += d;
+- state[4] += e; state[5] += f; state[6] += g; state[7] += h;
+-
+- /* erase our data */
+- a = b = c = d = e = f = g = h = t1 = t2 = 0;
+-}
+-
+-static void
+-sha512_init(struct crypto_tfm *tfm)
+-{
+- struct sha512_ctx *sctx = crypto_tfm_ctx(tfm);
+- sctx->state[0] = SHA512_H0;
+- sctx->state[1] = SHA512_H1;
+- sctx->state[2] = SHA512_H2;
+- sctx->state[3] = SHA512_H3;
+- sctx->state[4] = SHA512_H4;
+- sctx->state[5] = SHA512_H5;
+- sctx->state[6] = SHA512_H6;
+- sctx->state[7] = SHA512_H7;
+- sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0;
+-}
+-
+-static void
+-sha384_init(struct crypto_tfm *tfm)
+-{
+- struct sha512_ctx *sctx = crypto_tfm_ctx(tfm);
+- sctx->state[0] = SHA384_H0;
+- sctx->state[1] = SHA384_H1;
+- sctx->state[2] = SHA384_H2;
+- sctx->state[3] = SHA384_H3;
+- sctx->state[4] = SHA384_H4;
+- sctx->state[5] = SHA384_H5;
+- sctx->state[6] = SHA384_H6;
+- sctx->state[7] = SHA384_H7;
+- sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0;
+-}
+-
+-static void
+-sha512_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len)
+-{
+- struct sha512_ctx *sctx = crypto_tfm_ctx(tfm);
+-
+- unsigned int i, index, part_len;
+-
+- /* Compute number of bytes mod 128 */
+- index = (unsigned int)((sctx->count[0] >> 3) & 0x7F);
+-
+- /* Update number of bits */
+- if ((sctx->count[0] += (len << 3)) < (len << 3)) {
+- if ((sctx->count[1] += 1) < 1)
+- if ((sctx->count[2] += 1) < 1)
+- sctx->count[3]++;
+- sctx->count[1] += (len >> 29);
+- }
+-
+- part_len = 128 - index;
+-
+- /* Transform as many times as possible. */
+- if (len >= part_len) {
+- memcpy(&sctx->buf[index], data, part_len);
+- sha512_transform(sctx->state, sctx->W, sctx->buf);
+-
+- for (i = part_len; i + 127 < len; i+=128)
+- sha512_transform(sctx->state, sctx->W, &data[i]);
+-
+- index = 0;
+- } else {
+- i = 0;
+- }
+-
+- /* Buffer remaining input */
+- memcpy(&sctx->buf[index], &data[i], len - i);
+-
+- /* erase our data */
+- memset(sctx->W, 0, sizeof(sctx->W));
+-}
+-
+-static void
+-sha512_final(struct crypto_tfm *tfm, u8 *hash)
+-{
+- struct sha512_ctx *sctx = crypto_tfm_ctx(tfm);
+- static u8 padding[128] = { 0x80, };
+- __be64 *dst = (__be64 *)hash;
+- __be32 bits[4];
+- unsigned int index, pad_len;
+- int i;
+-
+- /* Save number of bits */
+- bits[3] = cpu_to_be32(sctx->count[0]);
+- bits[2] = cpu_to_be32(sctx->count[1]);
+- bits[1] = cpu_to_be32(sctx->count[2]);
+- bits[0] = cpu_to_be32(sctx->count[3]);
+-
+- /* Pad out to 112 mod 128. */
+- index = (sctx->count[0] >> 3) & 0x7f;
+- pad_len = (index < 112) ? (112 - index) : ((128+112) - index);
+- sha512_update(tfm, padding, pad_len);
+-
+- /* Append length (before padding) */
+- sha512_update(tfm, (const u8 *)bits, sizeof(bits));
+-
+- /* Store state in digest */
+- for (i = 0; i < 8; i++)
+- dst[i] = cpu_to_be64(sctx->state[i]);
+-
+- /* Zeroize sensitive information. */
+- memset(sctx, 0, sizeof(struct sha512_ctx));
+-}
+-
+-static void sha384_final(struct crypto_tfm *tfm, u8 *hash)
+-{
+- u8 D[64];
+-
+- sha512_final(tfm, D);
+-
+- memcpy(hash, D, 48);
+- memset(D, 0, 64);
+-}
+-
+-static struct crypto_alg sha512 = {
+- .cra_name = "sha512",
+- .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
+- .cra_blocksize = SHA512_BLOCK_SIZE,
+- .cra_ctxsize = sizeof(struct sha512_ctx),
+- .cra_module = THIS_MODULE,
+- .cra_alignmask = 3,
+- .cra_list = LIST_HEAD_INIT(sha512.cra_list),
+- .cra_u = { .digest = {
+- .dia_digestsize = SHA512_DIGEST_SIZE,
+- .dia_init = sha512_init,
+- .dia_update = sha512_update,
+- .dia_final = sha512_final }
+- }
+-};
+-
+-static struct crypto_alg sha384 = {
+- .cra_name = "sha384",
+- .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
+- .cra_blocksize = SHA384_BLOCK_SIZE,
+- .cra_ctxsize = sizeof(struct sha512_ctx),
+- .cra_alignmask = 3,
+- .cra_module = THIS_MODULE,
+- .cra_list = LIST_HEAD_INIT(sha384.cra_list),
+- .cra_u = { .digest = {
+- .dia_digestsize = SHA384_DIGEST_SIZE,
+- .dia_init = sha384_init,
+- .dia_update = sha512_update,
+- .dia_final = sha384_final }
+- }
+-};
+-
+-MODULE_ALIAS("sha384");
+-
+-static int __init init(void)
+-{
+- int ret = 0;
+-
+- if ((ret = crypto_register_alg(&sha384)) < 0)
+- goto out;
+- if ((ret = crypto_register_alg(&sha512)) < 0)
+- crypto_unregister_alg(&sha384);
+-out:
+- return ret;
+-}
+-
+-static void __exit fini(void)
+-{
+- crypto_unregister_alg(&sha384);
+- crypto_unregister_alg(&sha512);
+-}
+-
+-module_init(init);
+-module_exit(fini);
+-
+-MODULE_LICENSE("GPL");
+-MODULE_DESCRIPTION("SHA-512 and SHA-384 Secure Hash Algorithms");
+diff --git a/crypto/sha512_generic.c b/crypto/sha512_generic.c
+new file mode 100644
+index 0000000..bc36861
+--- /dev/null
++++ b/crypto/sha512_generic.c
+@@ -0,0 +1,306 @@
++/* SHA-512 code by Jean-Luc Cooke <jlcooke at certainkey.com>
++ *
++ * Copyright (c) Jean-Luc Cooke <jlcooke at certainkey.com>
++ * Copyright (c) Andrew McDonald <andrew at mcdonald.org.uk>
++ * Copyright (c) 2003 Kyle McMartin <kyle at debian.org>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2, or (at your option) any
++ * later version.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/mm.h>
++#include <linux/init.h>
++#include <linux/crypto.h>
++#include <linux/types.h>
++#include <crypto/sha.h>
++
++#include <asm/byteorder.h>
++
++struct sha512_ctx {
++ u64 state[8];
++ u32 count[4];
++ u8 buf[128];
++ u64 W[80];
++};
++
++static inline u64 Ch(u64 x, u64 y, u64 z)
++{
++ return z ^ (x & (y ^ z));
++}
++
++static inline u64 Maj(u64 x, u64 y, u64 z)
++{
++ return (x & y) | (z & (x | y));
++}
++
++static inline u64 RORu64(u64 x, u64 y)
++{
++ return (x >> y) | (x << (64 - y));
++}
++
++static const u64 sha512_K[80] = {
++ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
++ 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
++ 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
++ 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
++ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
++ 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
++ 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
++ 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
++ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
++ 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
++ 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
++ 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
++ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
++ 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
++ 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
++ 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
++ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
++ 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
++ 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
++ 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
++ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
++ 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
++ 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
++ 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
++ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
++ 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
++ 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL,
++};
++
++#define e0(x) (RORu64(x,28) ^ RORu64(x,34) ^ RORu64(x,39))
++#define e1(x) (RORu64(x,14) ^ RORu64(x,18) ^ RORu64(x,41))
++#define s0(x) (RORu64(x, 1) ^ RORu64(x, 8) ^ (x >> 7))
++#define s1(x) (RORu64(x,19) ^ RORu64(x,61) ^ (x >> 6))
++
++static inline void LOAD_OP(int I, u64 *W, const u8 *input)
++{
++ W[I] = __be64_to_cpu( ((__be64*)(input))[I] );
++}
++
++static inline void BLEND_OP(int I, u64 *W)
++{
++ W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
++}
++
++static void
++sha512_transform(u64 *state, u64 *W, const u8 *input)
++{
++ u64 a, b, c, d, e, f, g, h, t1, t2;
++
++ int i;
++
++ /* load the input */
++ for (i = 0; i < 16; i++)
++ LOAD_OP(i, W, input);
++
++ for (i = 16; i < 80; i++) {
++ BLEND_OP(i, W);
++ }
++
++ /* load the state into our registers */
++ a=state[0]; b=state[1]; c=state[2]; d=state[3];
++ e=state[4]; f=state[5]; g=state[6]; h=state[7];
++
++ /* now iterate */
++ for (i=0; i<80; i+=8) {
++ t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i ] + W[i ];
++ t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2;
++ t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[i+1];
++ t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2;
++ t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[i+2];
++ t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2;
++ t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[i+3];
++ t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2;
++ t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[i+4];
++ t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2;
++ t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[i+5];
++ t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2;
++ t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[i+6];
++ t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2;
++ t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[i+7];
++ t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2;
++ }
++
++ state[0] += a; state[1] += b; state[2] += c; state[3] += d;
++ state[4] += e; state[5] += f; state[6] += g; state[7] += h;
++
++ /* erase our data */
++ a = b = c = d = e = f = g = h = t1 = t2 = 0;
++}
++
++static void
++sha512_init(struct crypto_tfm *tfm)
++{
++ struct sha512_ctx *sctx = crypto_tfm_ctx(tfm);
++ sctx->state[0] = SHA512_H0;
++ sctx->state[1] = SHA512_H1;
++ sctx->state[2] = SHA512_H2;
++ sctx->state[3] = SHA512_H3;
++ sctx->state[4] = SHA512_H4;
++ sctx->state[5] = SHA512_H5;
++ sctx->state[6] = SHA512_H6;
++ sctx->state[7] = SHA512_H7;
++ sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0;
++}
++
++static void
++sha384_init(struct crypto_tfm *tfm)
++{
++ struct sha512_ctx *sctx = crypto_tfm_ctx(tfm);
++ sctx->state[0] = SHA384_H0;
++ sctx->state[1] = SHA384_H1;
++ sctx->state[2] = SHA384_H2;
++ sctx->state[3] = SHA384_H3;
++ sctx->state[4] = SHA384_H4;
++ sctx->state[5] = SHA384_H5;
++ sctx->state[6] = SHA384_H6;
++ sctx->state[7] = SHA384_H7;
++ sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0;
++}
++
++static void
++sha512_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len)
++{
++ struct sha512_ctx *sctx = crypto_tfm_ctx(tfm);
++
++ unsigned int i, index, part_len;
++
++ /* Compute number of bytes mod 128 */
++ index = (unsigned int)((sctx->count[0] >> 3) & 0x7F);
++
++ /* Update number of bits */
++ if ((sctx->count[0] += (len << 3)) < (len << 3)) {
++ if ((sctx->count[1] += 1) < 1)
++ if ((sctx->count[2] += 1) < 1)
++ sctx->count[3]++;
++ sctx->count[1] += (len >> 29);
++ }
++
++ part_len = 128 - index;
++
++ /* Transform as many times as possible. */
++ if (len >= part_len) {
++ memcpy(&sctx->buf[index], data, part_len);
++ sha512_transform(sctx->state, sctx->W, sctx->buf);
++
++ for (i = part_len; i + 127 < len; i+=128)
++ sha512_transform(sctx->state, sctx->W, &data[i]);
++
++ index = 0;
++ } else {
++ i = 0;
++ }
++
++ /* Buffer remaining input */
++ memcpy(&sctx->buf[index], &data[i], len - i);
++
++ /* erase our data */
++ memset(sctx->W, 0, sizeof(sctx->W));
++}
++
++static void
++sha512_final(struct crypto_tfm *tfm, u8 *hash)
++{
++ struct sha512_ctx *sctx = crypto_tfm_ctx(tfm);
++ static u8 padding[128] = { 0x80, };
++ __be64 *dst = (__be64 *)hash;
++ __be32 bits[4];
++ unsigned int index, pad_len;
++ int i;
++
++ /* Save number of bits */
++ bits[3] = cpu_to_be32(sctx->count[0]);
++ bits[2] = cpu_to_be32(sctx->count[1]);
++ bits[1] = cpu_to_be32(sctx->count[2]);
++ bits[0] = cpu_to_be32(sctx->count[3]);
++
++ /* Pad out to 112 mod 128. */
++ index = (sctx->count[0] >> 3) & 0x7f;
++ pad_len = (index < 112) ? (112 - index) : ((128+112) - index);
++ sha512_update(tfm, padding, pad_len);
++
++ /* Append length (before padding) */
++ sha512_update(tfm, (const u8 *)bits, sizeof(bits));
++
++ /* Store state in digest */
++ for (i = 0; i < 8; i++)
++ dst[i] = cpu_to_be64(sctx->state[i]);
++
++ /* Zeroize sensitive information. */
++ memset(sctx, 0, sizeof(struct sha512_ctx));
++}
++
++static void sha384_final(struct crypto_tfm *tfm, u8 *hash)
++{
++ u8 D[64];
++
++ sha512_final(tfm, D);
++
++ memcpy(hash, D, 48);
++ memset(D, 0, 64);
++}
++
++static struct crypto_alg sha512 = {
++ .cra_name = "sha512",
++ .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
++ .cra_blocksize = SHA512_BLOCK_SIZE,
++ .cra_ctxsize = sizeof(struct sha512_ctx),
++ .cra_module = THIS_MODULE,
++ .cra_alignmask = 3,
++ .cra_list = LIST_HEAD_INIT(sha512.cra_list),
++ .cra_u = { .digest = {
++ .dia_digestsize = SHA512_DIGEST_SIZE,
++ .dia_init = sha512_init,
++ .dia_update = sha512_update,
++ .dia_final = sha512_final }
++ }
++};
++
++static struct crypto_alg sha384 = {
++ .cra_name = "sha384",
++ .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
++ .cra_blocksize = SHA384_BLOCK_SIZE,
++ .cra_ctxsize = sizeof(struct sha512_ctx),
++ .cra_alignmask = 3,
++ .cra_module = THIS_MODULE,
++ .cra_list = LIST_HEAD_INIT(sha384.cra_list),
++ .cra_u = { .digest = {
++ .dia_digestsize = SHA384_DIGEST_SIZE,
++ .dia_init = sha384_init,
++ .dia_update = sha512_update,
++ .dia_final = sha384_final }
++ }
++};
++
++static int __init sha512_generic_mod_init(void)
++{
++ int ret = 0;
++
++ if ((ret = crypto_register_alg(&sha384)) < 0)
++ goto out;
++ if ((ret = crypto_register_alg(&sha512)) < 0)
++ crypto_unregister_alg(&sha384);
++out:
++ return ret;
++}
++
++static void __exit sha512_generic_mod_fini(void)
++{
++ crypto_unregister_alg(&sha384);
++ crypto_unregister_alg(&sha512);
++}
++
++module_init(sha512_generic_mod_init);
++module_exit(sha512_generic_mod_fini);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("SHA-512 and SHA-384 Secure Hash Algorithms");
++
++MODULE_ALIAS("sha384");
++MODULE_ALIAS("sha512");
+diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
+index 1ab8c01..6beabc5 100644
+--- a/crypto/tcrypt.c
++++ b/crypto/tcrypt.c
+@@ -82,9 +82,8 @@ static char *check[] = {
+ "des", "md5", "des3_ede", "rot13", "sha1", "sha224", "sha256",
+ "blowfish", "twofish", "serpent", "sha384", "sha512", "md4", "aes",
+ "cast6", "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
+- "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
+ "khazad", "wp512", "wp384", "wp256", "tnepres", "xeta", "fcrypt",
+- "camellia", "seed", "salsa20", "lzo", NULL
++ "camellia", "seed", "salsa20", "lzo", "cts", NULL
+ };
+
+ static void hexdump(unsigned char *buf, unsigned int len)
+@@ -113,23 +112,11 @@ static void test_hash(char *algo, struct hash_testvec *template,
+ char result[64];
+ struct crypto_hash *tfm;
+ struct hash_desc desc;
+- struct hash_testvec *hash_tv;
+- unsigned int tsize;
+ int ret;
++ void *hash_buff;
+
+ printk("\ntesting %s\n", algo);
+
+- tsize = sizeof(struct hash_testvec);
+- tsize *= tcount;
+-
+- if (tsize > TVMEMSIZE) {
+- printk("template (%u) too big for tvmem (%u)\n", tsize, TVMEMSIZE);
+- return;
+- }
+-
+- memcpy(tvmem, template, tsize);
+- hash_tv = (void *)tvmem;
+-
+ tfm = crypto_alloc_hash(algo, 0, CRYPTO_ALG_ASYNC);
+ if (IS_ERR(tfm)) {
+ printk("failed to load transform for %s: %ld\n", algo,
+@@ -144,28 +131,36 @@ static void test_hash(char *algo, struct hash_testvec *template,
+ printk("test %u:\n", i + 1);
+ memset(result, 0, 64);
+
+- sg_init_one(&sg[0], hash_tv[i].plaintext, hash_tv[i].psize);
++ hash_buff = kzalloc(template[i].psize, GFP_KERNEL);
++ if (!hash_buff)
++ continue;
++
++ memcpy(hash_buff, template[i].plaintext, template[i].psize);
++ sg_init_one(&sg[0], hash_buff, template[i].psize);
+
+- if (hash_tv[i].ksize) {
+- ret = crypto_hash_setkey(tfm, hash_tv[i].key,
+- hash_tv[i].ksize);
++ if (template[i].ksize) {
++ ret = crypto_hash_setkey(tfm, template[i].key,
++ template[i].ksize);
+ if (ret) {
+ printk("setkey() failed ret=%d\n", ret);
++ kfree(hash_buff);
+ goto out;
+ }
+ }
+
+- ret = crypto_hash_digest(&desc, sg, hash_tv[i].psize, result);
++ ret = crypto_hash_digest(&desc, sg, template[i].psize, result);
+ if (ret) {
+ printk("digest () failed ret=%d\n", ret);
++ kfree(hash_buff);
+ goto out;
+ }
+
+ hexdump(result, crypto_hash_digestsize(tfm));
+ printk("%s\n",
+- memcmp(result, hash_tv[i].digest,
++ memcmp(result, template[i].digest,
+ crypto_hash_digestsize(tfm)) ?
+ "fail" : "pass");
++ kfree(hash_buff);
+ }
+
+ printk("testing %s across pages\n", algo);
+@@ -175,25 +170,25 @@ static void test_hash(char *algo, struct hash_testvec *template,
+
+ j = 0;
+ for (i = 0; i < tcount; i++) {
+- if (hash_tv[i].np) {
++ if (template[i].np) {
+ j++;
+ printk("test %u:\n", j);
+ memset(result, 0, 64);
+
+ temp = 0;
+- sg_init_table(sg, hash_tv[i].np);
+- for (k = 0; k < hash_tv[i].np; k++) {
++ sg_init_table(sg, template[i].np);
++ for (k = 0; k < template[i].np; k++) {
+ memcpy(&xbuf[IDX[k]],
+- hash_tv[i].plaintext + temp,
+- hash_tv[i].tap[k]);
+- temp += hash_tv[i].tap[k];
++ template[i].plaintext + temp,
++ template[i].tap[k]);
++ temp += template[i].tap[k];
+ sg_set_buf(&sg[k], &xbuf[IDX[k]],
+- hash_tv[i].tap[k]);
++ template[i].tap[k]);
+ }
+
+- if (hash_tv[i].ksize) {
+- ret = crypto_hash_setkey(tfm, hash_tv[i].key,
+- hash_tv[i].ksize);
++ if (template[i].ksize) {
++ ret = crypto_hash_setkey(tfm, template[i].key,
++ template[i].ksize);
+
+ if (ret) {
+ printk("setkey() failed ret=%d\n", ret);
+@@ -201,7 +196,7 @@ static void test_hash(char *algo, struct hash_testvec *template,
+ }
+ }
+
+- ret = crypto_hash_digest(&desc, sg, hash_tv[i].psize,
++ ret = crypto_hash_digest(&desc, sg, template[i].psize,
+ result);
+ if (ret) {
+ printk("digest () failed ret=%d\n", ret);
+@@ -210,7 +205,7 @@ static void test_hash(char *algo, struct hash_testvec *template,
+
+ hexdump(result, crypto_hash_digestsize(tfm));
+ printk("%s\n",
+- memcmp(result, hash_tv[i].digest,
++ memcmp(result, template[i].digest,
+ crypto_hash_digestsize(tfm)) ?
+ "fail" : "pass");
+ }
+@@ -224,17 +219,18 @@ static void test_aead(char *algo, int enc, struct aead_testvec *template,
+ unsigned int tcount)
+ {
+ unsigned int ret, i, j, k, temp;
+- unsigned int tsize;
+ char *q;
+ struct crypto_aead *tfm;
+ char *key;
+- struct aead_testvec *aead_tv;
+ struct aead_request *req;
+ struct scatterlist sg[8];
+ struct scatterlist asg[8];
+ const char *e;
+ struct tcrypt_result result;
+ unsigned int authsize;
++ void *input;
++ void *assoc;
++ char iv[MAX_IVLEN];
+
+ if (enc == ENCRYPT)
+ e = "encryption";
+@@ -243,18 +239,6 @@ static void test_aead(char *algo, int enc, struct aead_testvec *template,
+
+ printk(KERN_INFO "\ntesting %s %s\n", algo, e);
+
+- tsize = sizeof(struct aead_testvec);
+- tsize *= tcount;
+-
+- if (tsize > TVMEMSIZE) {
+- printk(KERN_INFO "template (%u) too big for tvmem (%u)\n",
+- tsize, TVMEMSIZE);
+- return;
+- }
+-
+- memcpy(tvmem, template, tsize);
+- aead_tv = (void *)tvmem;
+-
+ init_completion(&result.completion);
+
+ tfm = crypto_alloc_aead(algo, 0, 0);
+@@ -275,46 +259,68 @@ static void test_aead(char *algo, int enc, struct aead_testvec *template,
+ tcrypt_complete, &result);
+
+ for (i = 0, j = 0; i < tcount; i++) {
+- if (!aead_tv[i].np) {
++ if (!template[i].np) {
+ printk(KERN_INFO "test %u (%d bit key):\n",
+- ++j, aead_tv[i].klen * 8);
++ ++j, template[i].klen * 8);
++
++ /* some tepmplates have no input data but they will
++ * touch input
++ */
++ input = kzalloc(template[i].ilen + template[i].rlen, GFP_KERNEL);
++ if (!input)
++ continue;
++
++ assoc = kzalloc(template[i].alen, GFP_KERNEL);
++ if (!assoc) {
++ kfree(input);
++ continue;
++ }
++
++ memcpy(input, template[i].input, template[i].ilen);
++ memcpy(assoc, template[i].assoc, template[i].alen);
++ if (template[i].iv)
++ memcpy(iv, template[i].iv, MAX_IVLEN);
++ else
++ memset(iv, 0, MAX_IVLEN);
+
+ crypto_aead_clear_flags(tfm, ~0);
+- if (aead_tv[i].wk)
++ if (template[i].wk)
+ crypto_aead_set_flags(
+ tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+- key = aead_tv[i].key;
++
++ if (template[i].key)
++ key = template[i].key;
++ else
++ key = kzalloc(template[i].klen, GFP_KERNEL);
+
+ ret = crypto_aead_setkey(tfm, key,
+- aead_tv[i].klen);
++ template[i].klen);
+ if (ret) {
+ printk(KERN_INFO "setkey() failed flags=%x\n",
+ crypto_aead_get_flags(tfm));
+
+- if (!aead_tv[i].fail)
+- goto out;
++ if (!template[i].fail)
++ goto next_one;
+ }
+
+- authsize = abs(aead_tv[i].rlen - aead_tv[i].ilen);
++ authsize = abs(template[i].rlen - template[i].ilen);
+ ret = crypto_aead_setauthsize(tfm, authsize);
+ if (ret) {
+ printk(KERN_INFO
+ "failed to set authsize = %u\n",
+ authsize);
+- goto out;
++ goto next_one;
+ }
+
+- sg_init_one(&sg[0], aead_tv[i].input,
+- aead_tv[i].ilen + (enc ? authsize : 0));
++ sg_init_one(&sg[0], input,
++ template[i].ilen + (enc ? authsize : 0));
+
+- sg_init_one(&asg[0], aead_tv[i].assoc,
+- aead_tv[i].alen);
++ sg_init_one(&asg[0], assoc, template[i].alen);
+
+ aead_request_set_crypt(req, sg, sg,
+- aead_tv[i].ilen,
+- aead_tv[i].iv);
++ template[i].ilen, iv);
+
+- aead_request_set_assoc(req, asg, aead_tv[i].alen);
++ aead_request_set_assoc(req, asg, template[i].alen);
+
+ ret = enc ?
+ crypto_aead_encrypt(req) :
+@@ -335,15 +341,21 @@ static void test_aead(char *algo, int enc, struct aead_testvec *template,
+ default:
+ printk(KERN_INFO "%s () failed err=%d\n",
+ e, -ret);
+- goto out;
++ goto next_one;
+ }
+
+ q = kmap(sg_page(&sg[0])) + sg[0].offset;
+- hexdump(q, aead_tv[i].rlen);
++ hexdump(q, template[i].rlen);
+
+ printk(KERN_INFO "enc/dec: %s\n",
+- memcmp(q, aead_tv[i].result,
+- aead_tv[i].rlen) ? "fail" : "pass");
++ memcmp(q, template[i].result,
++ template[i].rlen) ? "fail" : "pass");
++ kunmap(sg_page(&sg[0]));
++next_one:
++ if (!template[i].key)
++ kfree(key);
++ kfree(assoc);
++ kfree(input);
+ }
+ }
+
+@@ -352,36 +364,41 @@ static void test_aead(char *algo, int enc, struct aead_testvec *template,
+ memset(axbuf, 0, XBUFSIZE);
+
+ for (i = 0, j = 0; i < tcount; i++) {
+- if (aead_tv[i].np) {
++ if (template[i].np) {
+ printk(KERN_INFO "test %u (%d bit key):\n",
+- ++j, aead_tv[i].klen * 8);
++ ++j, template[i].klen * 8);
++
++ if (template[i].iv)
++ memcpy(iv, template[i].iv, MAX_IVLEN);
++ else
++ memset(iv, 0, MAX_IVLEN);
+
+ crypto_aead_clear_flags(tfm, ~0);
+- if (aead_tv[i].wk)
++ if (template[i].wk)
+ crypto_aead_set_flags(
+ tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+- key = aead_tv[i].key;
++ key = template[i].key;
+
+- ret = crypto_aead_setkey(tfm, key, aead_tv[i].klen);
++ ret = crypto_aead_setkey(tfm, key, template[i].klen);
+ if (ret) {
+ printk(KERN_INFO "setkey() failed flags=%x\n",
+ crypto_aead_get_flags(tfm));
+
+- if (!aead_tv[i].fail)
++ if (!template[i].fail)
+ goto out;
+ }
+
+- sg_init_table(sg, aead_tv[i].np);
+- for (k = 0, temp = 0; k < aead_tv[i].np; k++) {
++ sg_init_table(sg, template[i].np);
++ for (k = 0, temp = 0; k < template[i].np; k++) {
+ memcpy(&xbuf[IDX[k]],
+- aead_tv[i].input + temp,
+- aead_tv[i].tap[k]);
+- temp += aead_tv[i].tap[k];
++ template[i].input + temp,
++ template[i].tap[k]);
++ temp += template[i].tap[k];
+ sg_set_buf(&sg[k], &xbuf[IDX[k]],
+- aead_tv[i].tap[k]);
++ template[i].tap[k]);
+ }
+
+- authsize = abs(aead_tv[i].rlen - aead_tv[i].ilen);
++ authsize = abs(template[i].rlen - template[i].ilen);
+ ret = crypto_aead_setauthsize(tfm, authsize);
+ if (ret) {
+ printk(KERN_INFO
+@@ -393,21 +410,21 @@ static void test_aead(char *algo, int enc, struct aead_testvec *template,
+ if (enc)
+ sg[k - 1].length += authsize;
+
+- sg_init_table(asg, aead_tv[i].anp);
+- for (k = 0, temp = 0; k < aead_tv[i].anp; k++) {
++ sg_init_table(asg, template[i].anp);
++ for (k = 0, temp = 0; k < template[i].anp; k++) {
+ memcpy(&axbuf[IDX[k]],
+- aead_tv[i].assoc + temp,
+- aead_tv[i].atap[k]);
+- temp += aead_tv[i].atap[k];
++ template[i].assoc + temp,
++ template[i].atap[k]);
++ temp += template[i].atap[k];
+ sg_set_buf(&asg[k], &axbuf[IDX[k]],
+- aead_tv[i].atap[k]);
++ template[i].atap[k]);
+ }
+
+ aead_request_set_crypt(req, sg, sg,
+- aead_tv[i].ilen,
+- aead_tv[i].iv);
++ template[i].ilen,
++ iv);
+
+- aead_request_set_assoc(req, asg, aead_tv[i].alen);
++ aead_request_set_assoc(req, asg, template[i].alen);
+
+ ret = enc ?
+ crypto_aead_encrypt(req) :
+@@ -431,18 +448,19 @@ static void test_aead(char *algo, int enc, struct aead_testvec *template,
+ goto out;
+ }
+
+- for (k = 0, temp = 0; k < aead_tv[i].np; k++) {
++ for (k = 0, temp = 0; k < template[i].np; k++) {
+ printk(KERN_INFO "page %u\n", k);
+ q = kmap(sg_page(&sg[k])) + sg[k].offset;
+- hexdump(q, aead_tv[i].tap[k]);
++ hexdump(q, template[i].tap[k]);
+ printk(KERN_INFO "%s\n",
+- memcmp(q, aead_tv[i].result + temp,
+- aead_tv[i].tap[k] -
+- (k < aead_tv[i].np - 1 || enc ?
++ memcmp(q, template[i].result + temp,
++ template[i].tap[k] -
++ (k < template[i].np - 1 || enc ?
+ 0 : authsize)) ?
+ "fail" : "pass");
+
+- temp += aead_tv[i].tap[k];
++ temp += template[i].tap[k];
++ kunmap(sg_page(&sg[k]));
+ }
+ }
+ }
+@@ -456,15 +474,14 @@ static void test_cipher(char *algo, int enc,
+ struct cipher_testvec *template, unsigned int tcount)
+ {
+ unsigned int ret, i, j, k, temp;
+- unsigned int tsize;
+ char *q;
+ struct crypto_ablkcipher *tfm;
+- char *key;
+- struct cipher_testvec *cipher_tv;
+ struct ablkcipher_request *req;
+ struct scatterlist sg[8];
+ const char *e;
+ struct tcrypt_result result;
++ void *data;
++ char iv[MAX_IVLEN];
+
+ if (enc == ENCRYPT)
+ e = "encryption";
+@@ -473,16 +490,7 @@ static void test_cipher(char *algo, int enc,
+
+ printk("\ntesting %s %s\n", algo, e);
+
+- tsize = sizeof (struct cipher_testvec);
+- if (tsize > TVMEMSIZE) {
+- printk("template (%u) too big for tvmem (%u)\n", tsize,
+- TVMEMSIZE);
+- return;
+- }
+- cipher_tv = (void *)tvmem;
+-
+ init_completion(&result.completion);
+-
+ tfm = crypto_alloc_ablkcipher(algo, 0, 0);
+
+ if (IS_ERR(tfm)) {
+@@ -502,35 +510,43 @@ static void test_cipher(char *algo, int enc,
+
+ j = 0;
+ for (i = 0; i < tcount; i++) {
+- memcpy(cipher_tv, &template[i], tsize);
+- if (!(cipher_tv->np)) {
++
++ data = kzalloc(template[i].ilen, GFP_KERNEL);
++ if (!data)
++ continue;
++
++ memcpy(data, template[i].input, template[i].ilen);
++ if (template[i].iv)
++ memcpy(iv, template[i].iv, MAX_IVLEN);
++ else
++ memset(iv, 0, MAX_IVLEN);
++
++ if (!(template[i].np)) {
+ j++;
+ printk("test %u (%d bit key):\n",
+- j, cipher_tv->klen * 8);
++ j, template[i].klen * 8);
+
+ crypto_ablkcipher_clear_flags(tfm, ~0);
+- if (cipher_tv->wk)
++ if (template[i].wk)
+ crypto_ablkcipher_set_flags(
+ tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+- key = cipher_tv->key;
+
+- ret = crypto_ablkcipher_setkey(tfm, key,
+- cipher_tv->klen);
++ ret = crypto_ablkcipher_setkey(tfm, template[i].key,
++ template[i].klen);
+ if (ret) {
+ printk("setkey() failed flags=%x\n",
+ crypto_ablkcipher_get_flags(tfm));
+
+- if (!cipher_tv->fail)
++ if (!template[i].fail) {
++ kfree(data);
+ goto out;
++ }
+ }
+
+- sg_init_one(&sg[0], cipher_tv->input,
+- cipher_tv->ilen);
++ sg_init_one(&sg[0], data, template[i].ilen);
+
+ ablkcipher_request_set_crypt(req, sg, sg,
+- cipher_tv->ilen,
+- cipher_tv->iv);
+-
++ template[i].ilen, iv);
+ ret = enc ?
+ crypto_ablkcipher_encrypt(req) :
+ crypto_ablkcipher_decrypt(req);
+@@ -549,16 +565,19 @@ static void test_cipher(char *algo, int enc,
+ /* fall through */
+ default:
+ printk("%s () failed err=%d\n", e, -ret);
++ kfree(data);
+ goto out;
+ }
+
+ q = kmap(sg_page(&sg[0])) + sg[0].offset;
+- hexdump(q, cipher_tv->rlen);
++ hexdump(q, template[i].rlen);
+
+ printk("%s\n",
+- memcmp(q, cipher_tv->result,
+- cipher_tv->rlen) ? "fail" : "pass");
++ memcmp(q, template[i].result,
++ template[i].rlen) ? "fail" : "pass");
++ kunmap(sg_page(&sg[0]));
+ }
++ kfree(data);
+ }
+
+ printk("\ntesting %s %s across pages (chunking)\n", algo, e);
+@@ -566,42 +585,53 @@ static void test_cipher(char *algo, int enc,
+
+ j = 0;
+ for (i = 0; i < tcount; i++) {
+- memcpy(cipher_tv, &template[i], tsize);
+- if (cipher_tv->np) {
++
++ data = kzalloc(template[i].ilen, GFP_KERNEL);
++ if (!data)
++ continue;
++
++ memcpy(data, template[i].input, template[i].ilen);
++
++ if (template[i].iv)
++ memcpy(iv, template[i].iv, MAX_IVLEN);
++ else
++ memset(iv, 0, MAX_IVLEN);
++
++ if (template[i].np) {
+ j++;
+ printk("test %u (%d bit key):\n",
+- j, cipher_tv->klen * 8);
++ j, template[i].klen * 8);
+
+ crypto_ablkcipher_clear_flags(tfm, ~0);
+- if (cipher_tv->wk)
++ if (template[i].wk)
+ crypto_ablkcipher_set_flags(
+ tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+- key = cipher_tv->key;
+
+- ret = crypto_ablkcipher_setkey(tfm, key,
+- cipher_tv->klen);
++ ret = crypto_ablkcipher_setkey(tfm, template[i].key,
++ template[i].klen);
+ if (ret) {
+ printk("setkey() failed flags=%x\n",
+- crypto_ablkcipher_get_flags(tfm));
++ crypto_ablkcipher_get_flags(tfm));
+
+- if (!cipher_tv->fail)
++ if (!template[i].fail) {
++ kfree(data);
+ goto out;
++ }
+ }
+
+ temp = 0;
+- sg_init_table(sg, cipher_tv->np);
+- for (k = 0; k < cipher_tv->np; k++) {
++ sg_init_table(sg, template[i].np);
++ for (k = 0; k < template[i].np; k++) {
+ memcpy(&xbuf[IDX[k]],
+- cipher_tv->input + temp,
+- cipher_tv->tap[k]);
+- temp += cipher_tv->tap[k];
++ template[i].input + temp,
++ template[i].tap[k]);
++ temp += template[i].tap[k];
+ sg_set_buf(&sg[k], &xbuf[IDX[k]],
+- cipher_tv->tap[k]);
++ template[i].tap[k]);
+ }
+
+ ablkcipher_request_set_crypt(req, sg, sg,
+- cipher_tv->ilen,
+- cipher_tv->iv);
++ template[i].ilen, iv);
+
+ ret = enc ?
+ crypto_ablkcipher_encrypt(req) :
+@@ -625,19 +655,19 @@ static void test_cipher(char *algo, int enc,
+ }
+
+ temp = 0;
+- for (k = 0; k < cipher_tv->np; k++) {
++ for (k = 0; k < template[i].np; k++) {
+ printk("page %u\n", k);
+ q = kmap(sg_page(&sg[k])) + sg[k].offset;
+- hexdump(q, cipher_tv->tap[k]);
++ hexdump(q, template[i].tap[k]);
+ printk("%s\n",
+- memcmp(q, cipher_tv->result + temp,
+- cipher_tv->tap[k]) ? "fail" :
++ memcmp(q, template[i].result + temp,
++ template[i].tap[k]) ? "fail" :
+ "pass");
+- temp += cipher_tv->tap[k];
++ temp += template[i].tap[k];
++ kunmap(sg_page(&sg[k]));
+ }
+ }
+ }
+-
+ out:
+ crypto_free_ablkcipher(tfm);
+ ablkcipher_request_free(req);
+@@ -721,15 +751,18 @@ out:
+ return ret;
+ }
+
++static u32 block_sizes[] = { 16, 64, 256, 1024, 8192, 0 };
++
+ static void test_cipher_speed(char *algo, int enc, unsigned int sec,
+ struct cipher_testvec *template,
+- unsigned int tcount, struct cipher_speed *speed)
++ unsigned int tcount, u8 *keysize)
+ {
+ unsigned int ret, i, j, iv_len;
+ unsigned char *key, *p, iv[128];
+ struct crypto_blkcipher *tfm;
+ struct blkcipher_desc desc;
+ const char *e;
++ u32 *b_size;
+
+ if (enc == ENCRYPT)
+ e = "encryption";
+@@ -748,52 +781,60 @@ static void test_cipher_speed(char *algo, int enc, unsigned int sec,
+ desc.tfm = tfm;
+ desc.flags = 0;
+
+- for (i = 0; speed[i].klen != 0; i++) {
+- if ((speed[i].blen + speed[i].klen) > TVMEMSIZE) {
+- printk("template (%u) too big for tvmem (%u)\n",
+- speed[i].blen + speed[i].klen, TVMEMSIZE);
+- goto out;
+- }
++ i = 0;
++ do {
++
++ b_size = block_sizes;
++ do {
++
++ if ((*keysize + *b_size) > TVMEMSIZE) {
++ printk("template (%u) too big for tvmem (%u)\n",
++ *keysize + *b_size, TVMEMSIZE);
++ goto out;
++ }
+
+- printk("test %u (%d bit key, %d byte blocks): ", i,
+- speed[i].klen * 8, speed[i].blen);
++ printk("test %u (%d bit key, %d byte blocks): ", i,
++ *keysize * 8, *b_size);
+
+- memset(tvmem, 0xff, speed[i].klen + speed[i].blen);
++ memset(tvmem, 0xff, *keysize + *b_size);
+
+- /* set key, plain text and IV */
+- key = (unsigned char *)tvmem;
+- for (j = 0; j < tcount; j++) {
+- if (template[j].klen == speed[i].klen) {
+- key = template[j].key;
+- break;
++ /* set key, plain text and IV */
++ key = (unsigned char *)tvmem;
++ for (j = 0; j < tcount; j++) {
++ if (template[j].klen == *keysize) {
++ key = template[j].key;
++ break;
++ }
+ }
+- }
+- p = (unsigned char *)tvmem + speed[i].klen;
++ p = (unsigned char *)tvmem + *keysize;
+
+- ret = crypto_blkcipher_setkey(tfm, key, speed[i].klen);
+- if (ret) {
+- printk("setkey() failed flags=%x\n",
+- crypto_blkcipher_get_flags(tfm));
+- goto out;
+- }
++ ret = crypto_blkcipher_setkey(tfm, key, *keysize);
++ if (ret) {
++ printk("setkey() failed flags=%x\n",
++ crypto_blkcipher_get_flags(tfm));
++ goto out;
++ }
+
+- iv_len = crypto_blkcipher_ivsize(tfm);
+- if (iv_len) {
+- memset(&iv, 0xff, iv_len);
+- crypto_blkcipher_set_iv(tfm, iv, iv_len);
+- }
++ iv_len = crypto_blkcipher_ivsize(tfm);
++ if (iv_len) {
++ memset(&iv, 0xff, iv_len);
++ crypto_blkcipher_set_iv(tfm, iv, iv_len);
++ }
+
+- if (sec)
+- ret = test_cipher_jiffies(&desc, enc, p, speed[i].blen,
+- sec);
+- else
+- ret = test_cipher_cycles(&desc, enc, p, speed[i].blen);
++ if (sec)
++ ret = test_cipher_jiffies(&desc, enc, p, *b_size, sec);
++ else
++ ret = test_cipher_cycles(&desc, enc, p, *b_size);
+
+- if (ret) {
+- printk("%s() failed flags=%x\n", e, desc.flags);
+- break;
+- }
+- }
++ if (ret) {
++ printk("%s() failed flags=%x\n", e, desc.flags);
++ break;
++ }
++ b_size++;
++ i++;
++ } while (*b_size);
++ keysize++;
++ } while (*keysize);
+
+ out:
+ crypto_free_blkcipher(tfm);
+@@ -1041,22 +1082,10 @@ static void test_comp(char *algo, struct comp_testvec *ctemplate,
+ unsigned int i;
+ char result[COMP_BUF_SIZE];
+ struct crypto_comp *tfm;
+- struct comp_testvec *tv;
+ unsigned int tsize;
+
+ printk("\ntesting %s compression\n", algo);
+
+- tsize = sizeof(struct comp_testvec);
+- tsize *= ctcount;
+- if (tsize > TVMEMSIZE) {
+- printk("template (%u) too big for tvmem (%u)\n", tsize,
+- TVMEMSIZE);
+- return;
+- }
+-
+- memcpy(tvmem, ctemplate, tsize);
+- tv = (void *)tvmem;
+-
+ tfm = crypto_alloc_comp(algo, 0, CRYPTO_ALG_ASYNC);
+ if (IS_ERR(tfm)) {
+ printk("failed to load transform for %s\n", algo);
+@@ -1069,8 +1098,8 @@ static void test_comp(char *algo, struct comp_testvec *ctemplate,
+ printk("test %u:\n", i + 1);
+ memset(result, 0, sizeof (result));
+
+- ilen = tv[i].inlen;
+- ret = crypto_comp_compress(tfm, tv[i].input,
++ ilen = ctemplate[i].inlen;
++ ret = crypto_comp_compress(tfm, ctemplate[i].input,
+ ilen, result, &dlen);
+ if (ret) {
+ printk("fail: ret=%d\n", ret);
+@@ -1078,7 +1107,7 @@ static void test_comp(char *algo, struct comp_testvec *ctemplate,
+ }
+ hexdump(result, dlen);
+ printk("%s (ratio %d:%d)\n",
+- memcmp(result, tv[i].output, dlen) ? "fail" : "pass",
++ memcmp(result, ctemplate[i].output, dlen) ? "fail" : "pass",
+ ilen, dlen);
+ }
+
+@@ -1092,17 +1121,14 @@ static void test_comp(char *algo, struct comp_testvec *ctemplate,
+ goto out;
+ }
+
+- memcpy(tvmem, dtemplate, tsize);
+- tv = (void *)tvmem;
+-
+ for (i = 0; i < dtcount; i++) {
+ int ilen, ret, dlen = COMP_BUF_SIZE;
+
+ printk("test %u:\n", i + 1);
+ memset(result, 0, sizeof (result));
+
+- ilen = tv[i].inlen;
+- ret = crypto_comp_decompress(tfm, tv[i].input,
++ ilen = dtemplate[i].inlen;
++ ret = crypto_comp_decompress(tfm, dtemplate[i].input,
+ ilen, result, &dlen);
+ if (ret) {
+ printk("fail: ret=%d\n", ret);
+@@ -1110,7 +1136,7 @@ static void test_comp(char *algo, struct comp_testvec *ctemplate,
+ }
+ hexdump(result, dlen);
+ printk("%s (ratio %d:%d)\n",
+- memcmp(result, tv[i].output, dlen) ? "fail" : "pass",
++ memcmp(result, dtemplate[i].output, dlen) ? "fail" : "pass",
+ ilen, dlen);
+ }
+ out:
+@@ -1301,6 +1327,12 @@ static void do_test(void)
+ test_cipher("ecb(seed)", DECRYPT, seed_dec_tv_template,
+ SEED_DEC_TEST_VECTORS);
+
++ //CTS
++ test_cipher("cts(cbc(aes))", ENCRYPT, cts_mode_enc_tv_template,
++ CTS_MODE_ENC_TEST_VECTORS);
++ test_cipher("cts(cbc(aes))", DECRYPT, cts_mode_dec_tv_template,
++ CTS_MODE_DEC_TEST_VECTORS);
++
+ test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
+ test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
+ test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS);
+@@ -1584,6 +1616,13 @@ static void do_test(void)
+ AES_CCM_DEC_TEST_VECTORS);
+ break;
+
++ case 38:
++ test_cipher("cts(cbc(aes))", ENCRYPT, cts_mode_enc_tv_template,
++ CTS_MODE_ENC_TEST_VECTORS);
++ test_cipher("cts(cbc(aes))", DECRYPT, cts_mode_dec_tv_template,
++ CTS_MODE_DEC_TEST_VECTORS);
++ break;
++
+ case 100:
+ test_hash("hmac(md5)", hmac_md5_tv_template,
+ HMAC_MD5_TEST_VECTORS);
+@@ -1621,89 +1660,85 @@ static void do_test(void)
+
+ case 200:
+ test_cipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0,
+- aes_speed_template);
++ speed_template_16_24_32);
+ test_cipher_speed("ecb(aes)", DECRYPT, sec, NULL, 0,
+- aes_speed_template);
++ speed_template_16_24_32);
+ test_cipher_speed("cbc(aes)", ENCRYPT, sec, NULL, 0,
+- aes_speed_template);
++ speed_template_16_24_32);
+ test_cipher_speed("cbc(aes)", DECRYPT, sec, NULL, 0,
+- aes_speed_template);
++ speed_template_16_24_32);
+ test_cipher_speed("lrw(aes)", ENCRYPT, sec, NULL, 0,
+- aes_lrw_speed_template);
++ speed_template_32_40_48);
+ test_cipher_speed("lrw(aes)", DECRYPT, sec, NULL, 0,
+- aes_lrw_speed_template);
++ speed_template_32_40_48);
+ test_cipher_speed("xts(aes)", ENCRYPT, sec, NULL, 0,
+- aes_xts_speed_template);
++ speed_template_32_48_64);
+ test_cipher_speed("xts(aes)", DECRYPT, sec, NULL, 0,
+- aes_xts_speed_template);
++ speed_template_32_48_64);
+ break;
+
+ case 201:
+ test_cipher_speed("ecb(des3_ede)", ENCRYPT, sec,
+- des3_ede_enc_tv_template,
+- DES3_EDE_ENC_TEST_VECTORS,
+- des3_ede_speed_template);
++ des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS,
++ speed_template_24);
+ test_cipher_speed("ecb(des3_ede)", DECRYPT, sec,
+- des3_ede_dec_tv_template,
+- DES3_EDE_DEC_TEST_VECTORS,
+- des3_ede_speed_template);
++ des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS,
++ speed_template_24);
+ test_cipher_speed("cbc(des3_ede)", ENCRYPT, sec,
+- des3_ede_enc_tv_template,
+- DES3_EDE_ENC_TEST_VECTORS,
+- des3_ede_speed_template);
++ des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS,
++ speed_template_24);
+ test_cipher_speed("cbc(des3_ede)", DECRYPT, sec,
+- des3_ede_dec_tv_template,
+- DES3_EDE_DEC_TEST_VECTORS,
+- des3_ede_speed_template);
++ des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS,
++ speed_template_24);
+ break;
+
+ case 202:
+ test_cipher_speed("ecb(twofish)", ENCRYPT, sec, NULL, 0,
+- twofish_speed_template);
++ speed_template_16_24_32);
+ test_cipher_speed("ecb(twofish)", DECRYPT, sec, NULL, 0,
+- twofish_speed_template);
++ speed_template_16_24_32);
+ test_cipher_speed("cbc(twofish)", ENCRYPT, sec, NULL, 0,
+- twofish_speed_template);
++ speed_template_16_24_32);
+ test_cipher_speed("cbc(twofish)", DECRYPT, sec, NULL, 0,
+- twofish_speed_template);
++ speed_template_16_24_32);
+ break;
+
+ case 203:
+ test_cipher_speed("ecb(blowfish)", ENCRYPT, sec, NULL, 0,
+- blowfish_speed_template);
++ speed_template_8_32);
+ test_cipher_speed("ecb(blowfish)", DECRYPT, sec, NULL, 0,
+- blowfish_speed_template);
++ speed_template_8_32);
+ test_cipher_speed("cbc(blowfish)", ENCRYPT, sec, NULL, 0,
+- blowfish_speed_template);
++ speed_template_8_32);
+ test_cipher_speed("cbc(blowfish)", DECRYPT, sec, NULL, 0,
+- blowfish_speed_template);
++ speed_template_8_32);
+ break;
+
+ case 204:
+ test_cipher_speed("ecb(des)", ENCRYPT, sec, NULL, 0,
+- des_speed_template);
++ speed_template_8);
+ test_cipher_speed("ecb(des)", DECRYPT, sec, NULL, 0,
+- des_speed_template);
++ speed_template_8);
+ test_cipher_speed("cbc(des)", ENCRYPT, sec, NULL, 0,
+- des_speed_template);
++ speed_template_8);
+ test_cipher_speed("cbc(des)", DECRYPT, sec, NULL, 0,
+- des_speed_template);
++ speed_template_8);
+ break;
+
+ case 205:
+ test_cipher_speed("ecb(camellia)", ENCRYPT, sec, NULL, 0,
+- camellia_speed_template);
++ speed_template_16_24_32);
+ test_cipher_speed("ecb(camellia)", DECRYPT, sec, NULL, 0,
+- camellia_speed_template);
++ speed_template_16_24_32);
+ test_cipher_speed("cbc(camellia)", ENCRYPT, sec, NULL, 0,
+- camellia_speed_template);
++ speed_template_16_24_32);
+ test_cipher_speed("cbc(camellia)", DECRYPT, sec, NULL, 0,
+- camellia_speed_template);
++ speed_template_16_24_32);
+ break;
+
+ case 206:
+ test_cipher_speed("salsa20", ENCRYPT, sec, NULL, 0,
+- salsa20_speed_template);
++ speed_template_16_32);
+ break;
+
+ case 300:
+@@ -1775,7 +1810,7 @@ static void do_test(void)
+ }
+ }
+
+-static int __init init(void)
++static int __init tcrypt_mod_init(void)
+ {
+ int err = -ENOMEM;
+
+@@ -1814,10 +1849,10 @@ static int __init init(void)
+ * If an init function is provided, an exit function must also be provided
+ * to allow module unload.
+ */
+-static void __exit fini(void) { }
++static void __exit tcrypt_mod_fini(void) { }
+
+-module_init(init);
+-module_exit(fini);
++module_init(tcrypt_mod_init);
++module_exit(tcrypt_mod_fini);
+
+ module_param(mode, int, 0);
+ module_param(sec, uint, 0);
+diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
+index f785e56..47bc0ec 100644
+--- a/crypto/tcrypt.h
++++ b/crypto/tcrypt.h
+@@ -31,9 +31,9 @@
+
+ struct hash_testvec {
+ /* only used with keyed hash algorithms */
+- char key[132] __attribute__ ((__aligned__(4)));
+- char plaintext[240];
+- char digest[MAX_DIGEST_SIZE];
++ char *key;
++ char *plaintext;
++ char *digest;
+ unsigned char tap[MAX_TAP];
+ unsigned char psize;
+ unsigned char np;
+@@ -41,10 +41,10 @@ struct hash_testvec {
+ };
+
+ struct cipher_testvec {
+- char key[MAX_KEYLEN] __attribute__ ((__aligned__(4)));
+- char iv[MAX_IVLEN];
+- char input[4100];
+- char result[4100];
++ char *key;
++ char *iv;
++ char *input;
++ char *result;
+ unsigned char tap[MAX_TAP];
+ int np;
+ unsigned char fail;
+@@ -55,11 +55,11 @@ struct cipher_testvec {
+ };
+
+ struct aead_testvec {
+- char key[MAX_KEYLEN] __attribute__ ((__aligned__(4)));
+- char iv[MAX_IVLEN];
+- char input[512];
+- char assoc[512];
+- char result[512];
++ char *key;
++ char *iv;
++ char *input;
++ char *assoc;
++ char *result;
+ unsigned char tap[MAX_TAP];
+ unsigned char atap[MAX_TAP];
+ int np;
+@@ -72,16 +72,13 @@ struct aead_testvec {
+ unsigned short rlen;
+ };
+
+-struct cipher_speed {
+- unsigned char klen;
+- unsigned int blen;
+-};
+-
+ struct hash_speed {
+ unsigned int blen; /* buffer length */
+ unsigned int plen; /* per-update length */
+ };
+
++static char zeroed_string[48];
++
+ /*
+ * MD4 test vectors from RFC1320
+ */
+@@ -90,41 +87,41 @@ struct hash_speed {
+ static struct hash_testvec md4_tv_template [] = {
+ {
+ .plaintext = "",
+- .digest = { 0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31,
+- 0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0 },
++ .digest = "\x31\xd6\xcf\xe0\xd1\x6a\xe9\x31"
++ "\xb7\x3c\x59\xd7\xe0\xc0\x89\xc0",
+ }, {
+ .plaintext = "a",
+ .psize = 1,
+- .digest = { 0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46,
+- 0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24 },
++ .digest = "\xbd\xe5\x2c\xb3\x1d\xe3\x3e\x46"
++ "\x24\x5e\x05\xfb\xdb\xd6\xfb\x24",
+ }, {
+ .plaintext = "abc",
+ .psize = 3,
+- .digest = { 0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52,
+- 0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d },
++ .digest = "\xa4\x48\x01\x7a\xaf\x21\xd8\x52"
++ "\x5f\xc1\x0a\xe8\x7a\xa6\x72\x9d",
+ }, {
+ .plaintext = "message digest",
+ .psize = 14,
+- .digest = { 0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8,
+- 0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b },
++ .digest = "\xd9\x13\x0a\x81\x64\x54\x9f\xe8"
++ "\x18\x87\x48\x06\xe1\xc7\x01\x4b",
+ }, {
+ .plaintext = "abcdefghijklmnopqrstuvwxyz",
+ .psize = 26,
+- .digest = { 0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd,
+- 0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9 },
++ .digest = "\xd7\x9e\x1c\x30\x8a\xa5\xbb\xcd"
++ "\xee\xa8\xed\x63\xdf\x41\x2d\xa9",
+ .np = 2,
+ .tap = { 13, 13 },
+ }, {
+ .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ .psize = 62,
+- .digest = { 0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35,
+- 0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4 },
++ .digest = "\x04\x3f\x85\x82\xf2\x41\xdb\x35"
++ "\x1c\xe6\x27\xe1\x53\xe7\xf0\xe4",
+ }, {
+ .plaintext = "123456789012345678901234567890123456789012345678901234567890123"
+- "45678901234567890",
++ "45678901234567890",
+ .psize = 80,
+- .digest = { 0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19,
+- 0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36 },
++ .digest = "\xe3\x3b\x4d\xdc\x9c\x38\xf2\x19"
++ "\x9c\x3e\x7b\x16\x4f\xcc\x05\x36",
+ },
+ };
+
+@@ -135,41 +132,41 @@ static struct hash_testvec md4_tv_template [] = {
+
+ static struct hash_testvec md5_tv_template[] = {
+ {
+- .digest = { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
+- 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e },
++ .digest = "\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04"
++ "\xe9\x80\x09\x98\xec\xf8\x42\x7e",
+ }, {
+ .plaintext = "a",
+ .psize = 1,
+- .digest = { 0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8,
+- 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 },
++ .digest = "\x0c\xc1\x75\xb9\xc0\xf1\xb6\xa8"
++ "\x31\xc3\x99\xe2\x69\x77\x26\x61",
+ }, {
+ .plaintext = "abc",
+ .psize = 3,
+- .digest = { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0,
+- 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 },
++ .digest = "\x90\x01\x50\x98\x3c\xd2\x4f\xb0"
++ "\xd6\x96\x3f\x7d\x28\xe1\x7f\x72",
+ }, {
+ .plaintext = "message digest",
+ .psize = 14,
+- .digest = { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d,
+- 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 },
++ .digest = "\xf9\x6b\x69\x7d\x7c\xb7\x93\x8d"
++ "\x52\x5a\x2f\x31\xaa\xf1\x61\xd0",
+ }, {
+ .plaintext = "abcdefghijklmnopqrstuvwxyz",
+ .psize = 26,
+- .digest = { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00,
+- 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b },
++ .digest = "\xc3\xfc\xd3\xd7\x61\x92\xe4\x00"
++ "\x7d\xfb\x49\x6c\xca\x67\xe1\x3b",
+ .np = 2,
+ .tap = {13, 13}
+ }, {
+ .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ .psize = 62,
+- .digest = { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5,
+- 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f },
++ .digest = "\xd1\x74\xab\x98\xd2\x77\xd9\xf5"
++ "\xa5\x61\x1c\x2c\x9f\x41\x9d\x9f",
+ }, {
+ .plaintext = "12345678901234567890123456789012345678901234567890123456789012"
+- "345678901234567890",
++ "345678901234567890",
+ .psize = 80,
+- .digest = { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55,
+- 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a },
++ .digest = "\x57\xed\xf4\xa2\x2b\xe3\xc9\x55"
++ "\xac\x49\xda\x2e\x21\x07\xb6\x7a",
+ }
+ };
+
+@@ -182,13 +179,13 @@ static struct hash_testvec sha1_tv_template[] = {
+ {
+ .plaintext = "abc",
+ .psize = 3,
+- .digest = { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e,
+- 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d },
++ .digest = "\xa9\x99\x3e\x36\x47\x06\x81\x6a\xba\x3e"
++ "\x25\x71\x78\x50\xc2\x6c\x9c\xd0\xd8\x9d",
+ }, {
+ .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ .psize = 56,
+- .digest = { 0x84, 0x98, 0x3e, 0x44, 0x1c, 0x3b, 0xd2, 0x6e, 0xba, 0xae,
+- 0x4a, 0xa1, 0xf9, 0x51, 0x29, 0xe5, 0xe5, 0x46, 0x70, 0xf1 },
++ .digest = "\x84\x98\x3e\x44\x1c\x3b\xd2\x6e\xba\xae"
++ "\x4a\xa1\xf9\x51\x29\xe5\xe5\x46\x70\xf1",
+ .np = 2,
+ .tap = { 28, 28 }
+ }
+@@ -204,18 +201,18 @@ static struct hash_testvec sha224_tv_template[] = {
+ {
+ .plaintext = "abc",
+ .psize = 3,
+- .digest = { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,
+- 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
+- 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,
+- 0xE3, 0x6C, 0x9D, 0xA7},
++ .digest = "\x23\x09\x7D\x22\x34\x05\xD8\x22"
++ "\x86\x42\xA4\x77\xBD\xA2\x55\xB3"
++ "\x2A\xAD\xBC\xE4\xBD\xA0\xB3\xF7"
++ "\xE3\x6C\x9D\xA7",
+ }, {
+ .plaintext =
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ .psize = 56,
+- .digest = { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC,
+- 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,
+- 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19,
+- 0x52, 0x52, 0x25, 0x25 },
++ .digest = "\x75\x38\x8B\x16\x51\x27\x76\xCC"
++ "\x5D\xBA\x5D\xA1\xFD\x89\x01\x50"
++ "\xB0\xC6\x45\x5C\xB4\xF5\x8B\x19"
++ "\x52\x52\x25\x25",
+ .np = 2,
+ .tap = { 28, 28 }
+ }
+@@ -230,17 +227,17 @@ static struct hash_testvec sha256_tv_template[] = {
+ {
+ .plaintext = "abc",
+ .psize = 3,
+- .digest = { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
+- 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
+- 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
+- 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad },
++ .digest = "\xba\x78\x16\xbf\x8f\x01\xcf\xea"
++ "\x41\x41\x40\xde\x5d\xae\x22\x23"
++ "\xb0\x03\x61\xa3\x96\x17\x7a\x9c"
++ "\xb4\x10\xff\x61\xf2\x00\x15\xad",
+ }, {
+ .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ .psize = 56,
+- .digest = { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
+- 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
+- 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
+- 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 },
++ .digest = "\x24\x8d\x6a\x61\xd2\x06\x38\xb8"
++ "\xe5\xc0\x26\x93\x0c\x3e\x60\x39"
++ "\xa3\x3c\xe4\x59\x64\xff\x21\x67"
++ "\xf6\xec\xed\xd4\x19\xdb\x06\xc1",
+ .np = 2,
+ .tap = { 28, 28 }
+ },
+@@ -255,41 +252,41 @@ static struct hash_testvec sha384_tv_template[] = {
+ {
+ .plaintext= "abc",
+ .psize = 3,
+- .digest = { 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b,
+- 0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07,
+- 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63,
+- 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed,
+- 0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23,
+- 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7 },
++ .digest = "\xcb\x00\x75\x3f\x45\xa3\x5e\x8b"
++ "\xb5\xa0\x3d\x69\x9a\xc6\x50\x07"
++ "\x27\x2c\x32\xab\x0e\xde\xd1\x63"
++ "\x1a\x8b\x60\x5a\x43\xff\x5b\xed"
++ "\x80\x86\x07\x2b\xa1\xe7\xcc\x23"
++ "\x58\xba\xec\xa1\x34\xc8\x25\xa7",
+ }, {
+ .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ .psize = 56,
+- .digest = { 0x33, 0x91, 0xfd, 0xdd, 0xfc, 0x8d, 0xc7, 0x39,
+- 0x37, 0x07, 0xa6, 0x5b, 0x1b, 0x47, 0x09, 0x39,
+- 0x7c, 0xf8, 0xb1, 0xd1, 0x62, 0xaf, 0x05, 0xab,
+- 0xfe, 0x8f, 0x45, 0x0d, 0xe5, 0xf3, 0x6b, 0xc6,
+- 0xb0, 0x45, 0x5a, 0x85, 0x20, 0xbc, 0x4e, 0x6f,
+- 0x5f, 0xe9, 0x5b, 0x1f, 0xe3, 0xc8, 0x45, 0x2b},
++ .digest = "\x33\x91\xfd\xdd\xfc\x8d\xc7\x39"
++ "\x37\x07\xa6\x5b\x1b\x47\x09\x39"
++ "\x7c\xf8\xb1\xd1\x62\xaf\x05\xab"
++ "\xfe\x8f\x45\x0d\xe5\xf3\x6b\xc6"
++ "\xb0\x45\x5a\x85\x20\xbc\x4e\x6f"
++ "\x5f\xe9\x5b\x1f\xe3\xc8\x45\x2b",
+ }, {
+ .plaintext = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+- "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
++ "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+ .psize = 112,
+- .digest = { 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8,
+- 0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47,
+- 0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2,
+- 0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12,
+- 0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9,
+- 0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39 },
++ .digest = "\x09\x33\x0c\x33\xf7\x11\x47\xe8"
++ "\x3d\x19\x2f\xc7\x82\xcd\x1b\x47"
++ "\x53\x11\x1b\x17\x3b\x3b\x05\xd2"
++ "\x2f\xa0\x80\x86\xe3\xb0\xf7\x12"
++ "\xfc\xc7\xc7\x1a\x55\x7e\x2d\xb9"
++ "\x66\xc3\xe9\xfa\x91\x74\x60\x39",
+ }, {
+ .plaintext = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd"
+- "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz",
++ "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz",
+ .psize = 104,
+- .digest = { 0x3d, 0x20, 0x89, 0x73, 0xab, 0x35, 0x08, 0xdb,
+- 0xbd, 0x7e, 0x2c, 0x28, 0x62, 0xba, 0x29, 0x0a,
+- 0xd3, 0x01, 0x0e, 0x49, 0x78, 0xc1, 0x98, 0xdc,
+- 0x4d, 0x8f, 0xd0, 0x14, 0xe5, 0x82, 0x82, 0x3a,
+- 0x89, 0xe1, 0x6f, 0x9b, 0x2a, 0x7b, 0xbc, 0x1a,
+- 0xc9, 0x38, 0xe2, 0xd1, 0x99, 0xe8, 0xbe, 0xa4 },
++ .digest = "\x3d\x20\x89\x73\xab\x35\x08\xdb"
++ "\xbd\x7e\x2c\x28\x62\xba\x29\x0a"
++ "\xd3\x01\x0e\x49\x78\xc1\x98\xdc"
++ "\x4d\x8f\xd0\x14\xe5\x82\x82\x3a"
++ "\x89\xe1\x6f\x9b\x2a\x7b\xbc\x1a"
++ "\xc9\x38\xe2\xd1\x99\xe8\xbe\xa4",
+ .np = 4,
+ .tap = { 26, 26, 26, 26 }
+ },
+@@ -304,49 +301,49 @@ static struct hash_testvec sha512_tv_template[] = {
+ {
+ .plaintext = "abc",
+ .psize = 3,
+- .digest = { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
+- 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
+- 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
+- 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
+- 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
+- 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
+- 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
+- 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f },
++ .digest = "\xdd\xaf\x35\xa1\x93\x61\x7a\xba"
++ "\xcc\x41\x73\x49\xae\x20\x41\x31"
++ "\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2"
++ "\x0a\x9e\xee\xe6\x4b\x55\xd3\x9a"
++ "\x21\x92\x99\x2a\x27\x4f\xc1\xa8"
++ "\x36\xba\x3c\x23\xa3\xfe\xeb\xbd"
++ "\x45\x4d\x44\x23\x64\x3c\xe8\x0e"
++ "\x2a\x9a\xc9\x4f\xa5\x4c\xa4\x9f",
+ }, {
+ .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ .psize = 56,
+- .digest = { 0x20, 0x4a, 0x8f, 0xc6, 0xdd, 0xa8, 0x2f, 0x0a,
+- 0x0c, 0xed, 0x7b, 0xeb, 0x8e, 0x08, 0xa4, 0x16,
+- 0x57, 0xc1, 0x6e, 0xf4, 0x68, 0xb2, 0x28, 0xa8,
+- 0x27, 0x9b, 0xe3, 0x31, 0xa7, 0x03, 0xc3, 0x35,
+- 0x96, 0xfd, 0x15, 0xc1, 0x3b, 0x1b, 0x07, 0xf9,
+- 0xaa, 0x1d, 0x3b, 0xea, 0x57, 0x78, 0x9c, 0xa0,
+- 0x31, 0xad, 0x85, 0xc7, 0xa7, 0x1d, 0xd7, 0x03,
+- 0x54, 0xec, 0x63, 0x12, 0x38, 0xca, 0x34, 0x45 },
++ .digest = "\x20\x4a\x8f\xc6\xdd\xa8\x2f\x0a"
++ "\x0c\xed\x7b\xeb\x8e\x08\xa4\x16"
++ "\x57\xc1\x6e\xf4\x68\xb2\x28\xa8"
++ "\x27\x9b\xe3\x31\xa7\x03\xc3\x35"
++ "\x96\xfd\x15\xc1\x3b\x1b\x07\xf9"
++ "\xaa\x1d\x3b\xea\x57\x78\x9c\xa0"
++ "\x31\xad\x85\xc7\xa7\x1d\xd7\x03"
++ "\x54\xec\x63\x12\x38\xca\x34\x45",
+ }, {
+ .plaintext = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+- "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
++ "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+ .psize = 112,
+- .digest = { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
+- 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
+- 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
+- 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
+- 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
+- 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
+- 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
+- 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 },
++ .digest = "\x8e\x95\x9b\x75\xda\xe3\x13\xda"
++ "\x8c\xf4\xf7\x28\x14\xfc\x14\x3f"
++ "\x8f\x77\x79\xc6\xeb\x9f\x7f\xa1"
++ "\x72\x99\xae\xad\xb6\x88\x90\x18"
++ "\x50\x1d\x28\x9e\x49\x00\xf7\xe4"
++ "\x33\x1b\x99\xde\xc4\xb5\x43\x3a"
++ "\xc7\xd3\x29\xee\xb6\xdd\x26\x54"
++ "\x5e\x96\xe5\x5b\x87\x4b\xe9\x09",
+ }, {
+ .plaintext = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd"
+- "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz",
++ "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz",
+ .psize = 104,
+- .digest = { 0x93, 0x0d, 0x0c, 0xef, 0xcb, 0x30, 0xff, 0x11,
+- 0x33, 0xb6, 0x89, 0x81, 0x21, 0xf1, 0xcf, 0x3d,
+- 0x27, 0x57, 0x8a, 0xfc, 0xaf, 0xe8, 0x67, 0x7c,
+- 0x52, 0x57, 0xcf, 0x06, 0x99, 0x11, 0xf7, 0x5d,
+- 0x8f, 0x58, 0x31, 0xb5, 0x6e, 0xbf, 0xda, 0x67,
+- 0xb2, 0x78, 0xe6, 0x6d, 0xff, 0x8b, 0x84, 0xfe,
+- 0x2b, 0x28, 0x70, 0xf7, 0x42, 0xa5, 0x80, 0xd8,
+- 0xed, 0xb4, 0x19, 0x87, 0x23, 0x28, 0x50, 0xc9 },
++ .digest = "\x93\x0d\x0c\xef\xcb\x30\xff\x11"
++ "\x33\xb6\x89\x81\x21\xf1\xcf\x3d"
++ "\x27\x57\x8a\xfc\xaf\xe8\x67\x7c"
++ "\x52\x57\xcf\x06\x99\x11\xf7\x5d"
++ "\x8f\x58\x31\xb5\x6e\xbf\xda\x67"
++ "\xb2\x78\xe6\x6d\xff\x8b\x84\xfe"
++ "\x2b\x28\x70\xf7\x42\xa5\x80\xd8"
++ "\xed\xb4\x19\x87\x23\x28\x50\xc9",
+ .np = 4,
+ .tap = { 26, 26, 26, 26 }
+ },
+@@ -364,95 +361,95 @@ static struct hash_testvec wp512_tv_template[] = {
+ {
+ .plaintext = "",
+ .psize = 0,
+- .digest = { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66,
+- 0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26,
+- 0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8,
+- 0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7,
+- 0x3E, 0x83, 0xBE, 0x69, 0x8B, 0x28, 0x8F, 0xEB,
+- 0xCF, 0x88, 0xE3, 0xE0, 0x3C, 0x4F, 0x07, 0x57,
+- 0xEA, 0x89, 0x64, 0xE5, 0x9B, 0x63, 0xD9, 0x37,
+- 0x08, 0xB1, 0x38, 0xCC, 0x42, 0xA6, 0x6E, 0xB3 },
++ .digest = "\x19\xFA\x61\xD7\x55\x22\xA4\x66"
++ "\x9B\x44\xE3\x9C\x1D\x2E\x17\x26"
++ "\xC5\x30\x23\x21\x30\xD4\x07\xF8"
++ "\x9A\xFE\xE0\x96\x49\x97\xF7\xA7"
++ "\x3E\x83\xBE\x69\x8B\x28\x8F\xEB"
++ "\xCF\x88\xE3\xE0\x3C\x4F\x07\x57"
++ "\xEA\x89\x64\xE5\x9B\x63\xD9\x37"
++ "\x08\xB1\x38\xCC\x42\xA6\x6E\xB3",
+
+
+ }, {
+ .plaintext = "a",
+ .psize = 1,
+- .digest = { 0x8A, 0xCA, 0x26, 0x02, 0x79, 0x2A, 0xEC, 0x6F,
+- 0x11, 0xA6, 0x72, 0x06, 0x53, 0x1F, 0xB7, 0xD7,
+- 0xF0, 0xDF, 0xF5, 0x94, 0x13, 0x14, 0x5E, 0x69,
+- 0x73, 0xC4, 0x50, 0x01, 0xD0, 0x08, 0x7B, 0x42,
+- 0xD1, 0x1B, 0xC6, 0x45, 0x41, 0x3A, 0xEF, 0xF6,
+- 0x3A, 0x42, 0x39, 0x1A, 0x39, 0x14, 0x5A, 0x59,
+- 0x1A, 0x92, 0x20, 0x0D, 0x56, 0x01, 0x95, 0xE5,
+- 0x3B, 0x47, 0x85, 0x84, 0xFD, 0xAE, 0x23, 0x1A },
++ .digest = "\x8A\xCA\x26\x02\x79\x2A\xEC\x6F"
++ "\x11\xA6\x72\x06\x53\x1F\xB7\xD7"
++ "\xF0\xDF\xF5\x94\x13\x14\x5E\x69"
++ "\x73\xC4\x50\x01\xD0\x08\x7B\x42"
++ "\xD1\x1B\xC6\x45\x41\x3A\xEF\xF6"
++ "\x3A\x42\x39\x1A\x39\x14\x5A\x59"
++ "\x1A\x92\x20\x0D\x56\x01\x95\xE5"
++ "\x3B\x47\x85\x84\xFD\xAE\x23\x1A",
+ }, {
+ .plaintext = "abc",
+ .psize = 3,
+- .digest = { 0x4E, 0x24, 0x48, 0xA4, 0xC6, 0xF4, 0x86, 0xBB,
+- 0x16, 0xB6, 0x56, 0x2C, 0x73, 0xB4, 0x02, 0x0B,
+- 0xF3, 0x04, 0x3E, 0x3A, 0x73, 0x1B, 0xCE, 0x72,
+- 0x1A, 0xE1, 0xB3, 0x03, 0xD9, 0x7E, 0x6D, 0x4C,
+- 0x71, 0x81, 0xEE, 0xBD, 0xB6, 0xC5, 0x7E, 0x27,
+- 0x7D, 0x0E, 0x34, 0x95, 0x71, 0x14, 0xCB, 0xD6,
+- 0xC7, 0x97, 0xFC, 0x9D, 0x95, 0xD8, 0xB5, 0x82,
+- 0xD2, 0x25, 0x29, 0x20, 0x76, 0xD4, 0xEE, 0xF5 },
++ .digest = "\x4E\x24\x48\xA4\xC6\xF4\x86\xBB"
++ "\x16\xB6\x56\x2C\x73\xB4\x02\x0B"
++ "\xF3\x04\x3E\x3A\x73\x1B\xCE\x72"
++ "\x1A\xE1\xB3\x03\xD9\x7E\x6D\x4C"
++ "\x71\x81\xEE\xBD\xB6\xC5\x7E\x27"
++ "\x7D\x0E\x34\x95\x71\x14\xCB\xD6"
++ "\xC7\x97\xFC\x9D\x95\xD8\xB5\x82"
++ "\xD2\x25\x29\x20\x76\xD4\xEE\xF5",
+ }, {
+ .plaintext = "message digest",
+ .psize = 14,
+- .digest = { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6,
+- 0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC,
+- 0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C,
+- 0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B,
+- 0x84, 0x21, 0x55, 0x76, 0x59, 0xEF, 0x55, 0xC1,
+- 0x06, 0xB4, 0xB5, 0x2A, 0xC5, 0xA4, 0xAA, 0xA6,
+- 0x92, 0xED, 0x92, 0x00, 0x52, 0x83, 0x8F, 0x33,
+- 0x62, 0xE8, 0x6D, 0xBD, 0x37, 0xA8, 0x90, 0x3E },
++ .digest = "\x37\x8C\x84\xA4\x12\x6E\x2D\xC6"
++ "\xE5\x6D\xCC\x74\x58\x37\x7A\xAC"
++ "\x83\x8D\x00\x03\x22\x30\xF5\x3C"
++ "\xE1\xF5\x70\x0C\x0F\xFB\x4D\x3B"
++ "\x84\x21\x55\x76\x59\xEF\x55\xC1"
++ "\x06\xB4\xB5\x2A\xC5\xA4\xAA\xA6"
++ "\x92\xED\x92\x00\x52\x83\x8F\x33"
++ "\x62\xE8\x6D\xBD\x37\xA8\x90\x3E",
+ }, {
+ .plaintext = "abcdefghijklmnopqrstuvwxyz",
+ .psize = 26,
+- .digest = { 0xF1, 0xD7, 0x54, 0x66, 0x26, 0x36, 0xFF, 0xE9,
+- 0x2C, 0x82, 0xEB, 0xB9, 0x21, 0x2A, 0x48, 0x4A,
+- 0x8D, 0x38, 0x63, 0x1E, 0xAD, 0x42, 0x38, 0xF5,
+- 0x44, 0x2E, 0xE1, 0x3B, 0x80, 0x54, 0xE4, 0x1B,
+- 0x08, 0xBF, 0x2A, 0x92, 0x51, 0xC3, 0x0B, 0x6A,
+- 0x0B, 0x8A, 0xAE, 0x86, 0x17, 0x7A, 0xB4, 0xA6,
+- 0xF6, 0x8F, 0x67, 0x3E, 0x72, 0x07, 0x86, 0x5D,
+- 0x5D, 0x98, 0x19, 0xA3, 0xDB, 0xA4, 0xEB, 0x3B },
++ .digest = "\xF1\xD7\x54\x66\x26\x36\xFF\xE9"
++ "\x2C\x82\xEB\xB9\x21\x2A\x48\x4A"
++ "\x8D\x38\x63\x1E\xAD\x42\x38\xF5"
++ "\x44\x2E\xE1\x3B\x80\x54\xE4\x1B"
++ "\x08\xBF\x2A\x92\x51\xC3\x0B\x6A"
++ "\x0B\x8A\xAE\x86\x17\x7A\xB4\xA6"
++ "\xF6\x8F\x67\x3E\x72\x07\x86\x5D"
++ "\x5D\x98\x19\xA3\xDB\xA4\xEB\x3B",
+ }, {
+ .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+- "abcdefghijklmnopqrstuvwxyz0123456789",
++ "abcdefghijklmnopqrstuvwxyz0123456789",
+ .psize = 62,
+- .digest = { 0xDC, 0x37, 0xE0, 0x08, 0xCF, 0x9E, 0xE6, 0x9B,
+- 0xF1, 0x1F, 0x00, 0xED, 0x9A, 0xBA, 0x26, 0x90,
+- 0x1D, 0xD7, 0xC2, 0x8C, 0xDE, 0xC0, 0x66, 0xCC,
+- 0x6A, 0xF4, 0x2E, 0x40, 0xF8, 0x2F, 0x3A, 0x1E,
+- 0x08, 0xEB, 0xA2, 0x66, 0x29, 0x12, 0x9D, 0x8F,
+- 0xB7, 0xCB, 0x57, 0x21, 0x1B, 0x92, 0x81, 0xA6,
+- 0x55, 0x17, 0xCC, 0x87, 0x9D, 0x7B, 0x96, 0x21,
+- 0x42, 0xC6, 0x5F, 0x5A, 0x7A, 0xF0, 0x14, 0x67 },
++ .digest = "\xDC\x37\xE0\x08\xCF\x9E\xE6\x9B"
++ "\xF1\x1F\x00\xED\x9A\xBA\x26\x90"
++ "\x1D\xD7\xC2\x8C\xDE\xC0\x66\xCC"
++ "\x6A\xF4\x2E\x40\xF8\x2F\x3A\x1E"
++ "\x08\xEB\xA2\x66\x29\x12\x9D\x8F"
++ "\xB7\xCB\x57\x21\x1B\x92\x81\xA6"
++ "\x55\x17\xCC\x87\x9D\x7B\x96\x21"
++ "\x42\xC6\x5F\x5A\x7A\xF0\x14\x67",
+ }, {
+ .plaintext = "1234567890123456789012345678901234567890"
+- "1234567890123456789012345678901234567890",
++ "1234567890123456789012345678901234567890",
+ .psize = 80,
+- .digest = { 0x46, 0x6E, 0xF1, 0x8B, 0xAB, 0xB0, 0x15, 0x4D,
+- 0x25, 0xB9, 0xD3, 0x8A, 0x64, 0x14, 0xF5, 0xC0,
+- 0x87, 0x84, 0x37, 0x2B, 0xCC, 0xB2, 0x04, 0xD6,
+- 0x54, 0x9C, 0x4A, 0xFA, 0xDB, 0x60, 0x14, 0x29,
+- 0x4D, 0x5B, 0xD8, 0xDF, 0x2A, 0x6C, 0x44, 0xE5,
+- 0x38, 0xCD, 0x04, 0x7B, 0x26, 0x81, 0xA5, 0x1A,
+- 0x2C, 0x60, 0x48, 0x1E, 0x88, 0xC5, 0xA2, 0x0B,
+- 0x2C, 0x2A, 0x80, 0xCF, 0x3A, 0x9A, 0x08, 0x3B },
++ .digest = "\x46\x6E\xF1\x8B\xAB\xB0\x15\x4D"
++ "\x25\xB9\xD3\x8A\x64\x14\xF5\xC0"
++ "\x87\x84\x37\x2B\xCC\xB2\x04\xD6"
++ "\x54\x9C\x4A\xFA\xDB\x60\x14\x29"
++ "\x4D\x5B\xD8\xDF\x2A\x6C\x44\xE5"
++ "\x38\xCD\x04\x7B\x26\x81\xA5\x1A"
++ "\x2C\x60\x48\x1E\x88\xC5\xA2\x0B"
++ "\x2C\x2A\x80\xCF\x3A\x9A\x08\x3B",
+ }, {
+ .plaintext = "abcdbcdecdefdefgefghfghighijhijk",
+ .psize = 32,
+- .digest = { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61,
+- 0xF5, 0xD6, 0xF0, 0xA0, 0xE4, 0x64, 0x4F, 0x48,
+- 0x8A, 0x7A, 0x5A, 0x52, 0xDE, 0xEE, 0x65, 0x62,
+- 0x07, 0xC5, 0x62, 0xF9, 0x88, 0xE9, 0x5C, 0x69,
+- 0x16, 0xBD, 0xC8, 0x03, 0x1B, 0xC5, 0xBE, 0x1B,
+- 0x7B, 0x94, 0x76, 0x39, 0xFE, 0x05, 0x0B, 0x56,
+- 0x93, 0x9B, 0xAA, 0xA0, 0xAD, 0xFF, 0x9A, 0xE6,
+- 0x74, 0x5B, 0x7B, 0x18, 0x1C, 0x3B, 0xE3, 0xFD },
++ .digest = "\x2A\x98\x7E\xA4\x0F\x91\x70\x61"
++ "\xF5\xD6\xF0\xA0\xE4\x64\x4F\x48"
++ "\x8A\x7A\x5A\x52\xDE\xEE\x65\x62"
++ "\x07\xC5\x62\xF9\x88\xE9\x5C\x69"
++ "\x16\xBD\xC8\x03\x1B\xC5\xBE\x1B"
++ "\x7B\x94\x76\x39\xFE\x05\x0B\x56"
++ "\x93\x9B\xAA\xA0\xAD\xFF\x9A\xE6"
++ "\x74\x5B\x7B\x18\x1C\x3B\xE3\xFD",
+ },
+ };
+
+@@ -462,79 +459,79 @@ static struct hash_testvec wp384_tv_template[] = {
+ {
+ .plaintext = "",
+ .psize = 0,
+- .digest = { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66,
+- 0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26,
+- 0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8,
+- 0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7,
+- 0x3E, 0x83, 0xBE, 0x69, 0x8B, 0x28, 0x8F, 0xEB,
+- 0xCF, 0x88, 0xE3, 0xE0, 0x3C, 0x4F, 0x07, 0x57 },
++ .digest = "\x19\xFA\x61\xD7\x55\x22\xA4\x66"
++ "\x9B\x44\xE3\x9C\x1D\x2E\x17\x26"
++ "\xC5\x30\x23\x21\x30\xD4\x07\xF8"
++ "\x9A\xFE\xE0\x96\x49\x97\xF7\xA7"
++ "\x3E\x83\xBE\x69\x8B\x28\x8F\xEB"
++ "\xCF\x88\xE3\xE0\x3C\x4F\x07\x57",
+
+
+ }, {
+ .plaintext = "a",
+ .psize = 1,
+- .digest = { 0x8A, 0xCA, 0x26, 0x02, 0x79, 0x2A, 0xEC, 0x6F,
+- 0x11, 0xA6, 0x72, 0x06, 0x53, 0x1F, 0xB7, 0xD7,
+- 0xF0, 0xDF, 0xF5, 0x94, 0x13, 0x14, 0x5E, 0x69,
+- 0x73, 0xC4, 0x50, 0x01, 0xD0, 0x08, 0x7B, 0x42,
+- 0xD1, 0x1B, 0xC6, 0x45, 0x41, 0x3A, 0xEF, 0xF6,
+- 0x3A, 0x42, 0x39, 0x1A, 0x39, 0x14, 0x5A, 0x59 },
++ .digest = "\x8A\xCA\x26\x02\x79\x2A\xEC\x6F"
++ "\x11\xA6\x72\x06\x53\x1F\xB7\xD7"
++ "\xF0\xDF\xF5\x94\x13\x14\x5E\x69"
++ "\x73\xC4\x50\x01\xD0\x08\x7B\x42"
++ "\xD1\x1B\xC6\x45\x41\x3A\xEF\xF6"
++ "\x3A\x42\x39\x1A\x39\x14\x5A\x59",
+ }, {
+ .plaintext = "abc",
+ .psize = 3,
+- .digest = { 0x4E, 0x24, 0x48, 0xA4, 0xC6, 0xF4, 0x86, 0xBB,
+- 0x16, 0xB6, 0x56, 0x2C, 0x73, 0xB4, 0x02, 0x0B,
+- 0xF3, 0x04, 0x3E, 0x3A, 0x73, 0x1B, 0xCE, 0x72,
+- 0x1A, 0xE1, 0xB3, 0x03, 0xD9, 0x7E, 0x6D, 0x4C,
+- 0x71, 0x81, 0xEE, 0xBD, 0xB6, 0xC5, 0x7E, 0x27,
+- 0x7D, 0x0E, 0x34, 0x95, 0x71, 0x14, 0xCB, 0xD6 },
++ .digest = "\x4E\x24\x48\xA4\xC6\xF4\x86\xBB"
++ "\x16\xB6\x56\x2C\x73\xB4\x02\x0B"
++ "\xF3\x04\x3E\x3A\x73\x1B\xCE\x72"
++ "\x1A\xE1\xB3\x03\xD9\x7E\x6D\x4C"
++ "\x71\x81\xEE\xBD\xB6\xC5\x7E\x27"
++ "\x7D\x0E\x34\x95\x71\x14\xCB\xD6",
+ }, {
+ .plaintext = "message digest",
+ .psize = 14,
+- .digest = { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6,
+- 0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC,
+- 0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C,
+- 0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B,
+- 0x84, 0x21, 0x55, 0x76, 0x59, 0xEF, 0x55, 0xC1,
+- 0x06, 0xB4, 0xB5, 0x2A, 0xC5, 0xA4, 0xAA, 0xA6 },
++ .digest = "\x37\x8C\x84\xA4\x12\x6E\x2D\xC6"
++ "\xE5\x6D\xCC\x74\x58\x37\x7A\xAC"
++ "\x83\x8D\x00\x03\x22\x30\xF5\x3C"
++ "\xE1\xF5\x70\x0C\x0F\xFB\x4D\x3B"
++ "\x84\x21\x55\x76\x59\xEF\x55\xC1"
++ "\x06\xB4\xB5\x2A\xC5\xA4\xAA\xA6",
+ }, {
+ .plaintext = "abcdefghijklmnopqrstuvwxyz",
+ .psize = 26,
+- .digest = { 0xF1, 0xD7, 0x54, 0x66, 0x26, 0x36, 0xFF, 0xE9,
+- 0x2C, 0x82, 0xEB, 0xB9, 0x21, 0x2A, 0x48, 0x4A,
+- 0x8D, 0x38, 0x63, 0x1E, 0xAD, 0x42, 0x38, 0xF5,
+- 0x44, 0x2E, 0xE1, 0x3B, 0x80, 0x54, 0xE4, 0x1B,
+- 0x08, 0xBF, 0x2A, 0x92, 0x51, 0xC3, 0x0B, 0x6A,
+- 0x0B, 0x8A, 0xAE, 0x86, 0x17, 0x7A, 0xB4, 0xA6 },
++ .digest = "\xF1\xD7\x54\x66\x26\x36\xFF\xE9"
++ "\x2C\x82\xEB\xB9\x21\x2A\x48\x4A"
++ "\x8D\x38\x63\x1E\xAD\x42\x38\xF5"
++ "\x44\x2E\xE1\x3B\x80\x54\xE4\x1B"
++ "\x08\xBF\x2A\x92\x51\xC3\x0B\x6A"
++ "\x0B\x8A\xAE\x86\x17\x7A\xB4\xA6",
+ }, {
+ .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+- "abcdefghijklmnopqrstuvwxyz0123456789",
++ "abcdefghijklmnopqrstuvwxyz0123456789",
+ .psize = 62,
+- .digest = { 0xDC, 0x37, 0xE0, 0x08, 0xCF, 0x9E, 0xE6, 0x9B,
+- 0xF1, 0x1F, 0x00, 0xED, 0x9A, 0xBA, 0x26, 0x90,
+- 0x1D, 0xD7, 0xC2, 0x8C, 0xDE, 0xC0, 0x66, 0xCC,
+- 0x6A, 0xF4, 0x2E, 0x40, 0xF8, 0x2F, 0x3A, 0x1E,
+- 0x08, 0xEB, 0xA2, 0x66, 0x29, 0x12, 0x9D, 0x8F,
+- 0xB7, 0xCB, 0x57, 0x21, 0x1B, 0x92, 0x81, 0xA6 },
++ .digest = "\xDC\x37\xE0\x08\xCF\x9E\xE6\x9B"
++ "\xF1\x1F\x00\xED\x9A\xBA\x26\x90"
++ "\x1D\xD7\xC2\x8C\xDE\xC0\x66\xCC"
++ "\x6A\xF4\x2E\x40\xF8\x2F\x3A\x1E"
++ "\x08\xEB\xA2\x66\x29\x12\x9D\x8F"
++ "\xB7\xCB\x57\x21\x1B\x92\x81\xA6",
+ }, {
+ .plaintext = "1234567890123456789012345678901234567890"
+- "1234567890123456789012345678901234567890",
++ "1234567890123456789012345678901234567890",
+ .psize = 80,
+- .digest = { 0x46, 0x6E, 0xF1, 0x8B, 0xAB, 0xB0, 0x15, 0x4D,
+- 0x25, 0xB9, 0xD3, 0x8A, 0x64, 0x14, 0xF5, 0xC0,
+- 0x87, 0x84, 0x37, 0x2B, 0xCC, 0xB2, 0x04, 0xD6,
+- 0x54, 0x9C, 0x4A, 0xFA, 0xDB, 0x60, 0x14, 0x29,
+- 0x4D, 0x5B, 0xD8, 0xDF, 0x2A, 0x6C, 0x44, 0xE5,
+- 0x38, 0xCD, 0x04, 0x7B, 0x26, 0x81, 0xA5, 0x1A },
++ .digest = "\x46\x6E\xF1\x8B\xAB\xB0\x15\x4D"
++ "\x25\xB9\xD3\x8A\x64\x14\xF5\xC0"
++ "\x87\x84\x37\x2B\xCC\xB2\x04\xD6"
++ "\x54\x9C\x4A\xFA\xDB\x60\x14\x29"
++ "\x4D\x5B\xD8\xDF\x2A\x6C\x44\xE5"
++ "\x38\xCD\x04\x7B\x26\x81\xA5\x1A",
+ }, {
+ .plaintext = "abcdbcdecdefdefgefghfghighijhijk",
+ .psize = 32,
+- .digest = { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61,
+- 0xF5, 0xD6, 0xF0, 0xA0, 0xE4, 0x64, 0x4F, 0x48,
+- 0x8A, 0x7A, 0x5A, 0x52, 0xDE, 0xEE, 0x65, 0x62,
+- 0x07, 0xC5, 0x62, 0xF9, 0x88, 0xE9, 0x5C, 0x69,
+- 0x16, 0xBD, 0xC8, 0x03, 0x1B, 0xC5, 0xBE, 0x1B,
+- 0x7B, 0x94, 0x76, 0x39, 0xFE, 0x05, 0x0B, 0x56 },
++ .digest = "\x2A\x98\x7E\xA4\x0F\x91\x70\x61"
++ "\xF5\xD6\xF0\xA0\xE4\x64\x4F\x48"
++ "\x8A\x7A\x5A\x52\xDE\xEE\x65\x62"
++ "\x07\xC5\x62\xF9\x88\xE9\x5C\x69"
++ "\x16\xBD\xC8\x03\x1B\xC5\xBE\x1B"
++ "\x7B\x94\x76\x39\xFE\x05\x0B\x56",
+ },
+ };
+
+@@ -544,63 +541,63 @@ static struct hash_testvec wp256_tv_template[] = {
+ {
+ .plaintext = "",
+ .psize = 0,
+- .digest = { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66,
+- 0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26,
+- 0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8,
+- 0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7 },
++ .digest = "\x19\xFA\x61\xD7\x55\x22\xA4\x66"
++ "\x9B\x44\xE3\x9C\x1D\x2E\x17\x26"
++ "\xC5\x30\x23\x21\x30\xD4\x07\xF8"
++ "\x9A\xFE\xE0\x96\x49\x97\xF7\xA7",
+
+
+ }, {
+ .plaintext = "a",
+ .psize = 1,
+- .digest = { 0x8A, 0xCA, 0x26, 0x02, 0x79, 0x2A, 0xEC, 0x6F,
+- 0x11, 0xA6, 0x72, 0x06, 0x53, 0x1F, 0xB7, 0xD7,
+- 0xF0, 0xDF, 0xF5, 0x94, 0x13, 0x14, 0x5E, 0x69,
+- 0x73, 0xC4, 0x50, 0x01, 0xD0, 0x08, 0x7B, 0x42 },
++ .digest = "\x8A\xCA\x26\x02\x79\x2A\xEC\x6F"
++ "\x11\xA6\x72\x06\x53\x1F\xB7\xD7"
++ "\xF0\xDF\xF5\x94\x13\x14\x5E\x69"
++ "\x73\xC4\x50\x01\xD0\x08\x7B\x42",
+ }, {
+ .plaintext = "abc",
+ .psize = 3,
+- .digest = { 0x4E, 0x24, 0x48, 0xA4, 0xC6, 0xF4, 0x86, 0xBB,
+- 0x16, 0xB6, 0x56, 0x2C, 0x73, 0xB4, 0x02, 0x0B,
+- 0xF3, 0x04, 0x3E, 0x3A, 0x73, 0x1B, 0xCE, 0x72,
+- 0x1A, 0xE1, 0xB3, 0x03, 0xD9, 0x7E, 0x6D, 0x4C },
++ .digest = "\x4E\x24\x48\xA4\xC6\xF4\x86\xBB"
++ "\x16\xB6\x56\x2C\x73\xB4\x02\x0B"
++ "\xF3\x04\x3E\x3A\x73\x1B\xCE\x72"
++ "\x1A\xE1\xB3\x03\xD9\x7E\x6D\x4C",
+ }, {
+ .plaintext = "message digest",
+ .psize = 14,
+- .digest = { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6,
+- 0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC,
+- 0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C,
+- 0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B },
++ .digest = "\x37\x8C\x84\xA4\x12\x6E\x2D\xC6"
++ "\xE5\x6D\xCC\x74\x58\x37\x7A\xAC"
++ "\x83\x8D\x00\x03\x22\x30\xF5\x3C"
++ "\xE1\xF5\x70\x0C\x0F\xFB\x4D\x3B",
+ }, {
+ .plaintext = "abcdefghijklmnopqrstuvwxyz",
+ .psize = 26,
+- .digest = { 0xF1, 0xD7, 0x54, 0x66, 0x26, 0x36, 0xFF, 0xE9,
+- 0x2C, 0x82, 0xEB, 0xB9, 0x21, 0x2A, 0x48, 0x4A,
+- 0x8D, 0x38, 0x63, 0x1E, 0xAD, 0x42, 0x38, 0xF5,
+- 0x44, 0x2E, 0xE1, 0x3B, 0x80, 0x54, 0xE4, 0x1B },
++ .digest = "\xF1\xD7\x54\x66\x26\x36\xFF\xE9"
++ "\x2C\x82\xEB\xB9\x21\x2A\x48\x4A"
++ "\x8D\x38\x63\x1E\xAD\x42\x38\xF5"
++ "\x44\x2E\xE1\x3B\x80\x54\xE4\x1B",
+ }, {
+ .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+- "abcdefghijklmnopqrstuvwxyz0123456789",
++ "abcdefghijklmnopqrstuvwxyz0123456789",
+ .psize = 62,
+- .digest = { 0xDC, 0x37, 0xE0, 0x08, 0xCF, 0x9E, 0xE6, 0x9B,
+- 0xF1, 0x1F, 0x00, 0xED, 0x9A, 0xBA, 0x26, 0x90,
+- 0x1D, 0xD7, 0xC2, 0x8C, 0xDE, 0xC0, 0x66, 0xCC,
+- 0x6A, 0xF4, 0x2E, 0x40, 0xF8, 0x2F, 0x3A, 0x1E },
++ .digest = "\xDC\x37\xE0\x08\xCF\x9E\xE6\x9B"
++ "\xF1\x1F\x00\xED\x9A\xBA\x26\x90"
++ "\x1D\xD7\xC2\x8C\xDE\xC0\x66\xCC"
++ "\x6A\xF4\x2E\x40\xF8\x2F\x3A\x1E",
+ }, {
+ .plaintext = "1234567890123456789012345678901234567890"
+- "1234567890123456789012345678901234567890",
++ "1234567890123456789012345678901234567890",
+ .psize = 80,
+- .digest = { 0x46, 0x6E, 0xF1, 0x8B, 0xAB, 0xB0, 0x15, 0x4D,
+- 0x25, 0xB9, 0xD3, 0x8A, 0x64, 0x14, 0xF5, 0xC0,
+- 0x87, 0x84, 0x37, 0x2B, 0xCC, 0xB2, 0x04, 0xD6,
+- 0x54, 0x9C, 0x4A, 0xFA, 0xDB, 0x60, 0x14, 0x29 },
++ .digest = "\x46\x6E\xF1\x8B\xAB\xB0\x15\x4D"
++ "\x25\xB9\xD3\x8A\x64\x14\xF5\xC0"
++ "\x87\x84\x37\x2B\xCC\xB2\x04\xD6"
++ "\x54\x9C\x4A\xFA\xDB\x60\x14\x29",
+ }, {
+ .plaintext = "abcdbcdecdefdefgefghfghighijhijk",
+ .psize = 32,
+- .digest = { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61,
+- 0xF5, 0xD6, 0xF0, 0xA0, 0xE4, 0x64, 0x4F, 0x48,
+- 0x8A, 0x7A, 0x5A, 0x52, 0xDE, 0xEE, 0x65, 0x62,
+- 0x07, 0xC5, 0x62, 0xF9, 0x88, 0xE9, 0x5C, 0x69 },
++ .digest = "\x2A\x98\x7E\xA4\x0F\x91\x70\x61"
++ "\xF5\xD6\xF0\xA0\xE4\x64\x4F\x48"
++ "\x8A\x7A\x5A\x52\xDE\xEE\x65\x62"
++ "\x07\xC5\x62\xF9\x88\xE9\x5C\x69",
+ },
+ };
+
+@@ -613,42 +610,42 @@ static struct hash_testvec tgr192_tv_template[] = {
+ {
+ .plaintext = "",
+ .psize = 0,
+- .digest = { 0x24, 0xf0, 0x13, 0x0c, 0x63, 0xac, 0x93, 0x32,
+- 0x16, 0x16, 0x6e, 0x76, 0xb1, 0xbb, 0x92, 0x5f,
+- 0xf3, 0x73, 0xde, 0x2d, 0x49, 0x58, 0x4e, 0x7a },
++ .digest = "\x24\xf0\x13\x0c\x63\xac\x93\x32"
++ "\x16\x16\x6e\x76\xb1\xbb\x92\x5f"
++ "\xf3\x73\xde\x2d\x49\x58\x4e\x7a",
+ }, {
+ .plaintext = "abc",
+ .psize = 3,
+- .digest = { 0xf2, 0x58, 0xc1, 0xe8, 0x84, 0x14, 0xab, 0x2a,
+- 0x52, 0x7a, 0xb5, 0x41, 0xff, 0xc5, 0xb8, 0xbf,
+- 0x93, 0x5f, 0x7b, 0x95, 0x1c, 0x13, 0x29, 0x51 },
++ .digest = "\xf2\x58\xc1\xe8\x84\x14\xab\x2a"
++ "\x52\x7a\xb5\x41\xff\xc5\xb8\xbf"
++ "\x93\x5f\x7b\x95\x1c\x13\x29\x51",
+ }, {
+ .plaintext = "Tiger",
+ .psize = 5,
+- .digest = { 0x9f, 0x00, 0xf5, 0x99, 0x07, 0x23, 0x00, 0xdd,
+- 0x27, 0x6a, 0xbb, 0x38, 0xc8, 0xeb, 0x6d, 0xec,
+- 0x37, 0x79, 0x0c, 0x11, 0x6f, 0x9d, 0x2b, 0xdf },
++ .digest = "\x9f\x00\xf5\x99\x07\x23\x00\xdd"
++ "\x27\x6a\xbb\x38\xc8\xeb\x6d\xec"
++ "\x37\x79\x0c\x11\x6f\x9d\x2b\xdf",
+ }, {
+ .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
+ .psize = 64,
+- .digest = { 0x87, 0xfb, 0x2a, 0x90, 0x83, 0x85, 0x1c, 0xf7,
+- 0x47, 0x0d, 0x2c, 0xf8, 0x10, 0xe6, 0xdf, 0x9e,
+- 0xb5, 0x86, 0x44, 0x50, 0x34, 0xa5, 0xa3, 0x86 },
++ .digest = "\x87\xfb\x2a\x90\x83\x85\x1c\xf7"
++ "\x47\x0d\x2c\xf8\x10\xe6\xdf\x9e"
++ "\xb5\x86\x44\x50\x34\xa5\xa3\x86",
+ }, {
+ .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789",
+ .psize = 64,
+- .digest = { 0x46, 0x7d, 0xb8, 0x08, 0x63, 0xeb, 0xce, 0x48,
+- 0x8d, 0xf1, 0xcd, 0x12, 0x61, 0x65, 0x5d, 0xe9,
+- 0x57, 0x89, 0x65, 0x65, 0x97, 0x5f, 0x91, 0x97 },
++ .digest = "\x46\x7d\xb8\x08\x63\xeb\xce\x48"
++ "\x8d\xf1\xcd\x12\x61\x65\x5d\xe9"
++ "\x57\x89\x65\x65\x97\x5f\x91\x97",
+ }, {
+ .plaintext = "Tiger - A Fast New Hash Function, "
+- "by Ross Anderson and Eli Biham, "
+- "proceedings of Fast Software Encryption 3, "
+- "Cambridge, 1996.",
++ "by Ross Anderson and Eli Biham, "
++ "proceedings of Fast Software Encryption 3, "
++ "Cambridge, 1996.",
+ .psize = 125,
+- .digest = { 0x3d, 0x9a, 0xeb, 0x03, 0xd1, 0xbd, 0x1a, 0x63,
+- 0x57, 0xb2, 0x77, 0x4d, 0xfd, 0x6d, 0x5b, 0x24,
+- 0xdd, 0x68, 0x15, 0x1d, 0x50, 0x39, 0x74, 0xfc },
++ .digest = "\x3d\x9a\xeb\x03\xd1\xbd\x1a\x63"
++ "\x57\xb2\x77\x4d\xfd\x6d\x5b\x24"
++ "\xdd\x68\x15\x1d\x50\x39\x74\xfc",
+ },
+ };
+
+@@ -658,42 +655,42 @@ static struct hash_testvec tgr160_tv_template[] = {
+ {
+ .plaintext = "",
+ .psize = 0,
+- .digest = { 0x24, 0xf0, 0x13, 0x0c, 0x63, 0xac, 0x93, 0x32,
+- 0x16, 0x16, 0x6e, 0x76, 0xb1, 0xbb, 0x92, 0x5f,
+- 0xf3, 0x73, 0xde, 0x2d },
++ .digest = "\x24\xf0\x13\x0c\x63\xac\x93\x32"
++ "\x16\x16\x6e\x76\xb1\xbb\x92\x5f"
++ "\xf3\x73\xde\x2d",
+ }, {
+ .plaintext = "abc",
+ .psize = 3,
+- .digest = { 0xf2, 0x58, 0xc1, 0xe8, 0x84, 0x14, 0xab, 0x2a,
+- 0x52, 0x7a, 0xb5, 0x41, 0xff, 0xc5, 0xb8, 0xbf,
+- 0x93, 0x5f, 0x7b, 0x95 },
++ .digest = "\xf2\x58\xc1\xe8\x84\x14\xab\x2a"
++ "\x52\x7a\xb5\x41\xff\xc5\xb8\xbf"
++ "\x93\x5f\x7b\x95",
+ }, {
+ .plaintext = "Tiger",
+ .psize = 5,
+- .digest = { 0x9f, 0x00, 0xf5, 0x99, 0x07, 0x23, 0x00, 0xdd,
+- 0x27, 0x6a, 0xbb, 0x38, 0xc8, 0xeb, 0x6d, 0xec,
+- 0x37, 0x79, 0x0c, 0x11 },
++ .digest = "\x9f\x00\xf5\x99\x07\x23\x00\xdd"
++ "\x27\x6a\xbb\x38\xc8\xeb\x6d\xec"
++ "\x37\x79\x0c\x11",
+ }, {
+ .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
+ .psize = 64,
+- .digest = { 0x87, 0xfb, 0x2a, 0x90, 0x83, 0x85, 0x1c, 0xf7,
+- 0x47, 0x0d, 0x2c, 0xf8, 0x10, 0xe6, 0xdf, 0x9e,
+- 0xb5, 0x86, 0x44, 0x50 },
++ .digest = "\x87\xfb\x2a\x90\x83\x85\x1c\xf7"
++ "\x47\x0d\x2c\xf8\x10\xe6\xdf\x9e"
++ "\xb5\x86\x44\x50",
+ }, {
+ .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789",
+ .psize = 64,
+- .digest = { 0x46, 0x7d, 0xb8, 0x08, 0x63, 0xeb, 0xce, 0x48,
+- 0x8d, 0xf1, 0xcd, 0x12, 0x61, 0x65, 0x5d, 0xe9,
+- 0x57, 0x89, 0x65, 0x65 },
++ .digest = "\x46\x7d\xb8\x08\x63\xeb\xce\x48"
++ "\x8d\xf1\xcd\x12\x61\x65\x5d\xe9"
++ "\x57\x89\x65\x65",
+ }, {
+ .plaintext = "Tiger - A Fast New Hash Function, "
+- "by Ross Anderson and Eli Biham, "
+- "proceedings of Fast Software Encryption 3, "
+- "Cambridge, 1996.",
++ "by Ross Anderson and Eli Biham, "
++ "proceedings of Fast Software Encryption 3, "
++ "Cambridge, 1996.",
+ .psize = 125,
+- .digest = { 0x3d, 0x9a, 0xeb, 0x03, 0xd1, 0xbd, 0x1a, 0x63,
+- 0x57, 0xb2, 0x77, 0x4d, 0xfd, 0x6d, 0x5b, 0x24,
+- 0xdd, 0x68, 0x15, 0x1d },
++ .digest = "\x3d\x9a\xeb\x03\xd1\xbd\x1a\x63"
++ "\x57\xb2\x77\x4d\xfd\x6d\x5b\x24"
++ "\xdd\x68\x15\x1d",
+ },
+ };
+
+@@ -703,36 +700,36 @@ static struct hash_testvec tgr128_tv_template[] = {
+ {
+ .plaintext = "",
+ .psize = 0,
+- .digest = { 0x24, 0xf0, 0x13, 0x0c, 0x63, 0xac, 0x93, 0x32,
+- 0x16, 0x16, 0x6e, 0x76, 0xb1, 0xbb, 0x92, 0x5f },
++ .digest = "\x24\xf0\x13\x0c\x63\xac\x93\x32"
++ "\x16\x16\x6e\x76\xb1\xbb\x92\x5f",
+ }, {
+ .plaintext = "abc",
+ .psize = 3,
+- .digest = { 0xf2, 0x58, 0xc1, 0xe8, 0x84, 0x14, 0xab, 0x2a,
+- 0x52, 0x7a, 0xb5, 0x41, 0xff, 0xc5, 0xb8, 0xbf },
++ .digest = "\xf2\x58\xc1\xe8\x84\x14\xab\x2a"
++ "\x52\x7a\xb5\x41\xff\xc5\xb8\xbf",
+ }, {
+ .plaintext = "Tiger",
+ .psize = 5,
+- .digest = { 0x9f, 0x00, 0xf5, 0x99, 0x07, 0x23, 0x00, 0xdd,
+- 0x27, 0x6a, 0xbb, 0x38, 0xc8, 0xeb, 0x6d, 0xec },
++ .digest = "\x9f\x00\xf5\x99\x07\x23\x00\xdd"
++ "\x27\x6a\xbb\x38\xc8\xeb\x6d\xec",
+ }, {
+ .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
+ .psize = 64,
+- .digest = { 0x87, 0xfb, 0x2a, 0x90, 0x83, 0x85, 0x1c, 0xf7,
+- 0x47, 0x0d, 0x2c, 0xf8, 0x10, 0xe6, 0xdf, 0x9e },
++ .digest = "\x87\xfb\x2a\x90\x83\x85\x1c\xf7"
++ "\x47\x0d\x2c\xf8\x10\xe6\xdf\x9e",
+ }, {
+ .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789",
+ .psize = 64,
+- .digest = { 0x46, 0x7d, 0xb8, 0x08, 0x63, 0xeb, 0xce, 0x48,
+- 0x8d, 0xf1, 0xcd, 0x12, 0x61, 0x65, 0x5d, 0xe9 },
++ .digest = "\x46\x7d\xb8\x08\x63\xeb\xce\x48"
++ "\x8d\xf1\xcd\x12\x61\x65\x5d\xe9",
+ }, {
+ .plaintext = "Tiger - A Fast New Hash Function, "
+- "by Ross Anderson and Eli Biham, "
+- "proceedings of Fast Software Encryption 3, "
+- "Cambridge, 1996.",
++ "by Ross Anderson and Eli Biham, "
++ "proceedings of Fast Software Encryption 3, "
++ "Cambridge, 1996.",
+ .psize = 125,
+- .digest = { 0x3d, 0x9a, 0xeb, 0x03, 0xd1, 0xbd, 0x1a, 0x63,
+- 0x57, 0xb2, 0x77, 0x4d, 0xfd, 0x6d, 0x5b, 0x24 },
++ .digest = "\x3d\x9a\xeb\x03\xd1\xbd\x1a\x63"
++ "\x57\xb2\x77\x4d\xfd\x6d\x5b\x24",
+ },
+ };
+
+@@ -745,59 +742,77 @@ static struct hash_testvec tgr128_tv_template[] = {
+ static struct hash_testvec hmac_md5_tv_template[] =
+ {
+ {
+- .key = { [0 ... 15] = 0x0b },
++ .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
+ .ksize = 16,
+ .plaintext = "Hi There",
+ .psize = 8,
+- .digest = { 0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c,
+- 0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d },
++ .digest = "\x92\x94\x72\x7a\x36\x38\xbb\x1c"
++ "\x13\xf4\x8e\xf8\x15\x8b\xfc\x9d",
+ }, {
+- .key = { 'J', 'e', 'f', 'e' },
++ .key = "Jefe",
+ .ksize = 4,
+ .plaintext = "what do ya want for nothing?",
+ .psize = 28,
+- .digest = { 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03,
+- 0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 },
++ .digest = "\x75\x0c\x78\x3e\x6a\xb0\xb5\x03"
++ "\xea\xa8\x6e\x31\x0a\x5d\xb7\x38",
+ .np = 2,
+ .tap = {14, 14}
+ }, {
+- .key = { [0 ... 15] = 0xaa },
++ .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
+ .ksize = 16,
+- .plaintext = { [0 ... 49] = 0xdd },
++ .plaintext = "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
++ "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
++ "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
++ "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd",
+ .psize = 50,
+- .digest = { 0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88,
+- 0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6 },
++ .digest = "\x56\xbe\x34\x52\x1d\x14\x4c\x88"
++ "\xdb\xb8\xc7\x33\xf0\xe8\xb3\xf6",
+ }, {
+- .key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+- 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, },
++ .key = "\x01\x02\x03\x04\x05\x06\x07\x08"
++ "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
++ "\x11\x12\x13\x14\x15\x16\x17\x18\x19",
+ .ksize = 25,
+- .plaintext = { [0 ... 49] = 0xcd },
++ .plaintext = "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
++ "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
++ "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
++ "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd",
+ .psize = 50,
+- .digest = { 0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea,
+- 0x3a, 0x75, 0x16, 0x47, 0x46, 0xff, 0xaa, 0x79 },
++ .digest = "\x69\x7e\xaf\x0a\xca\x3a\x3a\xea"
++ "\x3a\x75\x16\x47\x46\xff\xaa\x79",
+ }, {
+- .key = { [0 ... 15] = 0x0c },
++ .key = "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c",
+ .ksize = 16,
+ .plaintext = "Test With Truncation",
+ .psize = 20,
+- .digest = { 0x56, 0x46, 0x1e, 0xf2, 0x34, 0x2e, 0xdc, 0x00,
+- 0xf9, 0xba, 0xb9, 0x95, 0x69, 0x0e, 0xfd, 0x4c },
+- }, {
+- .key = { [0 ... 79] = 0xaa },
++ .digest = "\x56\x46\x1e\xf2\x34\x2e\xdc\x00"
++ "\xf9\xba\xb9\x95\x69\x0e\xfd\x4c",
++ }, {
++ .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa",
+ .ksize = 80,
+ .plaintext = "Test Using Larger Than Block-Size Key - Hash Key First",
+ .psize = 54,
+- .digest = { 0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f,
+- 0x0b, 0x62, 0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd },
+- }, {
+- .key = { [0 ... 79] = 0xaa },
++ .digest = "\x6b\x1a\xb7\xfe\x4b\xd7\xbf\x8f"
++ "\x0b\x62\xe6\xce\x61\xb9\xd0\xcd",
++ }, {
++ .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa",
+ .ksize = 80,
+ .plaintext = "Test Using Larger Than Block-Size Key and Larger Than One "
+- "Block-Size Data",
++ "Block-Size Data",
+ .psize = 73,
+- .digest = { 0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee,
+- 0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e },
++ .digest = "\x6f\x63\x0f\xad\x67\xcd\xa0\xee"
++ "\x1f\xb1\xf5\x62\xdb\x3a\xa5\x3e",
+ },
+ };
+
+@@ -808,60 +823,78 @@ static struct hash_testvec hmac_md5_tv_template[] =
+
+ static struct hash_testvec hmac_sha1_tv_template[] = {
+ {
+- .key = { [0 ... 19] = 0x0b },
++ .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
+ .ksize = 20,
+ .plaintext = "Hi There",
+ .psize = 8,
+- .digest = { 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64,
+- 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e, 0xf1,
+- 0x46, 0xbe },
++ .digest = "\xb6\x17\x31\x86\x55\x05\x72\x64"
++ "\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1"
++ "\x46\xbe",
+ }, {
+- .key = { 'J', 'e', 'f', 'e' },
++ .key = "Jefe",
+ .ksize = 4,
+ .plaintext = "what do ya want for nothing?",
+ .psize = 28,
+- .digest = { 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, 0xd2, 0x74,
+- 0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, 0x25, 0x9a, 0x7c, 0x79 },
++ .digest = "\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74"
++ "\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79",
+ .np = 2,
+ .tap = { 14, 14 }
+ }, {
+- .key = { [0 ... 19] = 0xaa },
++ .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
+ .ksize = 20,
+- .plaintext = { [0 ... 49] = 0xdd },
++ .plaintext = "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
++ "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
++ "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
++ "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd",
+ .psize = 50,
+- .digest = { 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, 0x91, 0xa3,
+- 0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f, 0x63, 0xf1, 0x75, 0xd3 },
++ .digest = "\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3"
++ "\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3",
+ }, {
+- .key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+- 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19 },
++ .key = "\x01\x02\x03\x04\x05\x06\x07\x08"
++ "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
++ "\x11\x12\x13\x14\x15\x16\x17\x18\x19",
+ .ksize = 25,
+- .plaintext = { [0 ... 49] = 0xcd },
++ .plaintext = "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
++ "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
++ "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
++ "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd",
+ .psize = 50,
+- .digest = { 0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6, 0xbc, 0x84,
+- 0x14, 0xf9, 0xbf, 0x50, 0xc8, 0x6c, 0x2d, 0x72, 0x35, 0xda },
++ .digest = "\x4c\x90\x07\xf4\x02\x62\x50\xc6\xbc\x84"
++ "\x14\xf9\xbf\x50\xc8\x6c\x2d\x72\x35\xda",
+ }, {
+- .key = { [0 ... 19] = 0x0c },
++ .key = "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c",
+ .ksize = 20,
+ .plaintext = "Test With Truncation",
+ .psize = 20,
+- .digest = { 0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2,
+- 0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04 },
+- }, {
+- .key = { [0 ... 79] = 0xaa },
++ .digest = "\x4c\x1a\x03\x42\x4b\x55\xe0\x7f\xe7\xf2"
++ "\x7b\xe1\xd5\x8b\xb9\x32\x4a\x9a\x5a\x04",
++ }, {
++ .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa",
+ .ksize = 80,
+ .plaintext = "Test Using Larger Than Block-Size Key - Hash Key First",
+ .psize = 54,
+- .digest = { 0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, 0x95, 0x70,
+- 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, 0xed, 0x40, 0x21, 0x12 },
+- }, {
+- .key = { [0 ... 79] = 0xaa },
++ .digest = "\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70"
++ "\x56\x37\xce\x8a\x3b\x55\xed\x40\x21\x12",
++ }, {
++ .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa",
+ .ksize = 80,
+ .plaintext = "Test Using Larger Than Block-Size Key and Larger Than One "
+- "Block-Size Data",
++ "Block-Size Data",
+ .psize = 73,
+- .digest = { 0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, 0x6b,
+- 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91 },
++ .digest = "\xe8\xe9\x9d\x0f\x45\x23\x7d\x78\x6d\x6b"
++ "\xba\xa7\x96\x5c\x78\x08\xbb\xff\x1a\x91",
+ },
+ };
+
+@@ -873,110 +906,110 @@ static struct hash_testvec hmac_sha1_tv_template[] = {
+
+ static struct hash_testvec hmac_sha224_tv_template[] = {
+ {
+- .key = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+- 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+- 0x0b, 0x0b, 0x0b, 0x0b },
++ .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
++ "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
++ "\x0b\x0b\x0b\x0b",
+ .ksize = 20,
+ /* ("Hi There") */
+- .plaintext = { 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 },
++ .plaintext = "\x48\x69\x20\x54\x68\x65\x72\x65",
+ .psize = 8,
+- .digest = { 0x89, 0x6f, 0xb1, 0x12, 0x8a, 0xbb, 0xdf, 0x19,
+- 0x68, 0x32, 0x10, 0x7c, 0xd4, 0x9d, 0xf3, 0x3f,
+- 0x47, 0xb4, 0xb1, 0x16, 0x99, 0x12, 0xba, 0x4f,
+- 0x53, 0x68, 0x4b, 0x22},
++ .digest = "\x89\x6f\xb1\x12\x8a\xbb\xdf\x19"
++ "\x68\x32\x10\x7c\xd4\x9d\xf3\x3f"
++ "\x47\xb4\xb1\x16\x99\x12\xba\x4f"
++ "\x53\x68\x4b\x22",
+ }, {
+- .key = { 0x4a, 0x65, 0x66, 0x65 }, /* ("Jefe") */
++ .key = "Jefe",
+ .ksize = 4,
+ /* ("what do ya want for nothing?") */
+- .plaintext = { 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20,
+- 0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20,
+- 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
+- 0x69, 0x6e, 0x67, 0x3f },
++ .plaintext = "\x77\x68\x61\x74\x20\x64\x6f\x20"
++ "\x79\x61\x20\x77\x61\x6e\x74\x20"
++ "\x66\x6f\x72\x20\x6e\x6f\x74\x68"
++ "\x69\x6e\x67\x3f",
+ .psize = 28,
+- .digest = { 0xa3, 0x0e, 0x01, 0x09, 0x8b, 0xc6, 0xdb, 0xbf,
+- 0x45, 0x69, 0x0f, 0x3a, 0x7e, 0x9e, 0x6d, 0x0f,
+- 0x8b, 0xbe, 0xa2, 0xa3, 0x9e, 0x61, 0x48, 0x00,
+- 0x8f, 0xd0, 0x5e, 0x44 },
++ .digest = "\xa3\x0e\x01\x09\x8b\xc6\xdb\xbf"
++ "\x45\x69\x0f\x3a\x7e\x9e\x6d\x0f"
++ "\x8b\xbe\xa2\xa3\x9e\x61\x48\x00"
++ "\x8f\xd0\x5e\x44",
+ .np = 4,
+ .tap = { 7, 7, 7, 7 }
+ }, {
+- .key = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa },
++ .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa",
+ .ksize = 131,
+ /* ("Test Using Larger Than Block-Size Key - Hash Key First") */
+- .plaintext = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69,
+- 0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65,
+- 0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42,
+- 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a,
+- 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x2d, 0x20,
+- 0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79,
+- 0x20, 0x46, 0x69, 0x72, 0x73, 0x74 },
++ .plaintext = "\x54\x65\x73\x74\x20\x55\x73\x69"
++ "\x6e\x67\x20\x4c\x61\x72\x67\x65"
++ "\x72\x20\x54\x68\x61\x6e\x20\x42"
++ "\x6c\x6f\x63\x6b\x2d\x53\x69\x7a"
++ "\x65\x20\x4b\x65\x79\x20\x2d\x20"
++ "\x48\x61\x73\x68\x20\x4b\x65\x79"
++ "\x20\x46\x69\x72\x73\x74",
+ .psize = 54,
+- .digest = { 0x95, 0xe9, 0xa0, 0xdb, 0x96, 0x20, 0x95, 0xad,
+- 0xae, 0xbe, 0x9b, 0x2d, 0x6f, 0x0d, 0xbc, 0xe2,
+- 0xd4, 0x99, 0xf1, 0x12, 0xf2, 0xd2, 0xb7, 0x27,
+- 0x3f, 0xa6, 0x87, 0x0e },
+- }, {
+- .key = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa },
++ .digest = "\x95\xe9\xa0\xdb\x96\x20\x95\xad"
++ "\xae\xbe\x9b\x2d\x6f\x0d\xbc\xe2"
++ "\xd4\x99\xf1\x12\xf2\xd2\xb7\x27"
++ "\x3f\xa6\x87\x0e",
++ }, {
++ .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa",
+ .ksize = 131,
+ /* ("This is a test using a larger than block-size key and a")
+ (" larger than block-size data. The key needs to be")
+ (" hashed before being used by the HMAC algorithm.") */
+- .plaintext = { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
+- 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75,
+- 0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x6c,
+- 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68,
+- 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+- 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6b, 0x65,
+- 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20,
+- 0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74,
+- 0x68, 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63,
+- 0x6b, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x64,
+- 0x61, 0x74, 0x61, 0x2e, 0x20, 0x54, 0x68, 0x65,
+- 0x20, 0x6b, 0x65, 0x79, 0x20, 0x6e, 0x65, 0x65,
+- 0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65,
+- 0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x64, 0x20,
+- 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x62,
+- 0x65, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x65,
+- 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65,
+- 0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x61, 0x6c,
+- 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2e },
++ .plaintext = "\x54\x68\x69\x73\x20\x69\x73\x20"
++ "\x61\x20\x74\x65\x73\x74\x20\x75"
++ "\x73\x69\x6e\x67\x20\x61\x20\x6c"
++ "\x61\x72\x67\x65\x72\x20\x74\x68"
++ "\x61\x6e\x20\x62\x6c\x6f\x63\x6b"
++ "\x2d\x73\x69\x7a\x65\x20\x6b\x65"
++ "\x79\x20\x61\x6e\x64\x20\x61\x20"
++ "\x6c\x61\x72\x67\x65\x72\x20\x74"
++ "\x68\x61\x6e\x20\x62\x6c\x6f\x63"
++ "\x6b\x2d\x73\x69\x7a\x65\x20\x64"
++ "\x61\x74\x61\x2e\x20\x54\x68\x65"
++ "\x20\x6b\x65\x79\x20\x6e\x65\x65"
++ "\x64\x73\x20\x74\x6f\x20\x62\x65"
++ "\x20\x68\x61\x73\x68\x65\x64\x20"
++ "\x62\x65\x66\x6f\x72\x65\x20\x62"
++ "\x65\x69\x6e\x67\x20\x75\x73\x65"
++ "\x64\x20\x62\x79\x20\x74\x68\x65"
++ "\x20\x48\x4d\x41\x43\x20\x61\x6c"
++ "\x67\x6f\x72\x69\x74\x68\x6d\x2e",
+ .psize = 152,
+- .digest = { 0x3a, 0x85, 0x41, 0x66, 0xac, 0x5d, 0x9f, 0x02,
+- 0x3f, 0x54, 0xd5, 0x17, 0xd0, 0xb3, 0x9d, 0xbd,
+- 0x94, 0x67, 0x70, 0xdb, 0x9c, 0x2b, 0x95, 0xc9,
+- 0xf6, 0xf5, 0x65, 0xd1 },
++ .digest = "\x3a\x85\x41\x66\xac\x5d\x9f\x02"
++ "\x3f\x54\xd5\x17\xd0\xb3\x9d\xbd"
++ "\x94\x67\x70\xdb\x9c\x2b\x95\xc9"
++ "\xf6\xf5\x65\xd1",
+ },
+ };
+
+@@ -988,112 +1021,136 @@ static struct hash_testvec hmac_sha224_tv_template[] = {
+
+ static struct hash_testvec hmac_sha256_tv_template[] = {
+ {
+- .key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+- 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+- 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20},
++ .key = "\x01\x02\x03\x04\x05\x06\x07\x08"
++ "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
++ "\x11\x12\x13\x14\x15\x16\x17\x18"
++ "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20",
+ .ksize = 32,
+ .plaintext = "abc",
+ .psize = 3,
+- .digest = { 0xa2, 0x1b, 0x1f, 0x5d, 0x4c, 0xf4, 0xf7, 0x3a,
+- 0x4d, 0xd9, 0x39, 0x75, 0x0f, 0x7a, 0x06, 0x6a,
+- 0x7f, 0x98, 0xcc, 0x13, 0x1c, 0xb1, 0x6a, 0x66,
+- 0x92, 0x75, 0x90, 0x21, 0xcf, 0xab, 0x81, 0x81 },
+- }, {
+- .key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+- 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+- 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20 },
++ .digest = "\xa2\x1b\x1f\x5d\x4c\xf4\xf7\x3a"
++ "\x4d\xd9\x39\x75\x0f\x7a\x06\x6a"
++ "\x7f\x98\xcc\x13\x1c\xb1\x6a\x66"
++ "\x92\x75\x90\x21\xcf\xab\x81\x81",
++ }, {
++ .key = "\x01\x02\x03\x04\x05\x06\x07\x08"
++ "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
++ "\x11\x12\x13\x14\x15\x16\x17\x18"
++ "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20",
+ .ksize = 32,
+ .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ .psize = 56,
+- .digest = { 0x10, 0x4f, 0xdc, 0x12, 0x57, 0x32, 0x8f, 0x08,
+- 0x18, 0x4b, 0xa7, 0x31, 0x31, 0xc5, 0x3c, 0xae,
+- 0xe6, 0x98, 0xe3, 0x61, 0x19, 0x42, 0x11, 0x49,
+- 0xea, 0x8c, 0x71, 0x24, 0x56, 0x69, 0x7d, 0x30 },
+- }, {
+- .key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+- 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+- 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20 },
++ .digest = "\x10\x4f\xdc\x12\x57\x32\x8f\x08"
++ "\x18\x4b\xa7\x31\x31\xc5\x3c\xae"
++ "\xe6\x98\xe3\x61\x19\x42\x11\x49"
++ "\xea\x8c\x71\x24\x56\x69\x7d\x30",
++ }, {
++ .key = "\x01\x02\x03\x04\x05\x06\x07\x08"
++ "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
++ "\x11\x12\x13\x14\x15\x16\x17\x18"
++ "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20",
+ .ksize = 32,
+ .plaintext = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+- "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
++ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ .psize = 112,
+- .digest = { 0x47, 0x03, 0x05, 0xfc, 0x7e, 0x40, 0xfe, 0x34,
+- 0xd3, 0xee, 0xb3, 0xe7, 0x73, 0xd9, 0x5a, 0xab,
+- 0x73, 0xac, 0xf0, 0xfd, 0x06, 0x04, 0x47, 0xa5,
+- 0xeb, 0x45, 0x95, 0xbf, 0x33, 0xa9, 0xd1, 0xa3 },
+- }, {
+- .key = { [0 ... 31] = 0x0b },
++ .digest = "\x47\x03\x05\xfc\x7e\x40\xfe\x34"
++ "\xd3\xee\xb3\xe7\x73\xd9\x5a\xab"
++ "\x73\xac\xf0\xfd\x06\x04\x47\xa5"
++ "\xeb\x45\x95\xbf\x33\xa9\xd1\xa3",
++ }, {
++ .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
++ "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
++ "\x0b\x0b\x0b\x0b\x0b\x0b",
+ .ksize = 32,
+ .plaintext = "Hi There",
+ .psize = 8,
+- .digest = { 0x19, 0x8a, 0x60, 0x7e, 0xb4, 0x4b, 0xfb, 0xc6,
+- 0x99, 0x03, 0xa0, 0xf1, 0xcf, 0x2b, 0xbd, 0xc5,
+- 0xba, 0x0a, 0xa3, 0xf3, 0xd9, 0xae, 0x3c, 0x1c,
+- 0x7a, 0x3b, 0x16, 0x96, 0xa0, 0xb6, 0x8c, 0xf7 },
++ .digest = "\x19\x8a\x60\x7e\xb4\x4b\xfb\xc6"
++ "\x99\x03\xa0\xf1\xcf\x2b\xbd\xc5"
++ "\xba\x0a\xa3\xf3\xd9\xae\x3c\x1c"
++ "\x7a\x3b\x16\x96\xa0\xb6\x8c\xf7",
+ }, {
+ .key = "Jefe",
+ .ksize = 4,
+ .plaintext = "what do ya want for nothing?",
+ .psize = 28,
+- .digest = { 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e,
+- 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7,
+- 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83,
+- 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43 },
++ .digest = "\x5b\xdc\xc1\x46\xbf\x60\x75\x4e"
++ "\x6a\x04\x24\x26\x08\x95\x75\xc7"
++ "\x5a\x00\x3f\x08\x9d\x27\x39\x83"
++ "\x9d\xec\x58\xb9\x64\xec\x38\x43",
+ .np = 2,
+ .tap = { 14, 14 }
+ }, {
+- .key = { [0 ... 31] = 0xaa },
++ .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
+ .ksize = 32,
+- .plaintext = { [0 ... 49] = 0xdd },
++ .plaintext = "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
++ "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
++ "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
++ "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd",
+ .psize = 50,
+- .digest = { 0xcd, 0xcb, 0x12, 0x20, 0xd1, 0xec, 0xcc, 0xea,
+- 0x91, 0xe5, 0x3a, 0xba, 0x30, 0x92, 0xf9, 0x62,
+- 0xe5, 0x49, 0xfe, 0x6c, 0xe9, 0xed, 0x7f, 0xdc,
+- 0x43, 0x19, 0x1f, 0xbd, 0xe4, 0x5c, 0x30, 0xb0 },
+- }, {
+- .key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+- 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+- 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+- 0x21, 0x22, 0x23, 0x24, 0x25 },
++ .digest = "\xcd\xcb\x12\x20\xd1\xec\xcc\xea"
++ "\x91\xe5\x3a\xba\x30\x92\xf9\x62"
++ "\xe5\x49\xfe\x6c\xe9\xed\x7f\xdc"
++ "\x43\x19\x1f\xbd\xe4\x5c\x30\xb0",
++ }, {
++ .key = "\x01\x02\x03\x04\x05\x06\x07\x08"
++ "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
++ "\x11\x12\x13\x14\x15\x16\x17\x18"
++ "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
++ "\x21\x22\x23\x24\x25",
+ .ksize = 37,
+- .plaintext = { [0 ... 49] = 0xcd },
++ .plaintext = "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
++ "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
++ "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
++ "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd",
+ .psize = 50,
+- .digest = { 0xd4, 0x63, 0x3c, 0x17, 0xf6, 0xfb, 0x8d, 0x74,
+- 0x4c, 0x66, 0xde, 0xe0, 0xf8, 0xf0, 0x74, 0x55,
+- 0x6e, 0xc4, 0xaf, 0x55, 0xef, 0x07, 0x99, 0x85,
+- 0x41, 0x46, 0x8e, 0xb4, 0x9b, 0xd2, 0xe9, 0x17 },
+- }, {
+- .key = { [0 ... 31] = 0x0c },
++ .digest = "\xd4\x63\x3c\x17\xf6\xfb\x8d\x74"
++ "\x4c\x66\xde\xe0\xf8\xf0\x74\x55"
++ "\x6e\xc4\xaf\x55\xef\x07\x99\x85"
++ "\x41\x46\x8e\xb4\x9b\xd2\xe9\x17",
++ }, {
++ .key = "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
++ "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
++ "\x0c\x0c\x0c\x0c\x0c\x0c",
+ .ksize = 32,
+ .plaintext = "Test With Truncation",
+ .psize = 20,
+- .digest = { 0x75, 0x46, 0xaf, 0x01, 0x84, 0x1f, 0xc0, 0x9b,
+- 0x1a, 0xb9, 0xc3, 0x74, 0x9a, 0x5f, 0x1c, 0x17,
+- 0xd4, 0xf5, 0x89, 0x66, 0x8a, 0x58, 0x7b, 0x27,
+- 0x00, 0xa9, 0xc9, 0x7c, 0x11, 0x93, 0xcf, 0x42 },
+- }, {
+- .key = { [0 ... 79] = 0xaa },
++ .digest = "\x75\x46\xaf\x01\x84\x1f\xc0\x9b"
++ "\x1a\xb9\xc3\x74\x9a\x5f\x1c\x17"
++ "\xd4\xf5\x89\x66\x8a\x58\x7b\x27"
++ "\x00\xa9\xc9\x7c\x11\x93\xcf\x42",
++ }, {
++ .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa",
+ .ksize = 80,
+ .plaintext = "Test Using Larger Than Block-Size Key - Hash Key First",
+ .psize = 54,
+- .digest = { 0x69, 0x53, 0x02, 0x5e, 0xd9, 0x6f, 0x0c, 0x09,
+- 0xf8, 0x0a, 0x96, 0xf7, 0x8e, 0x65, 0x38, 0xdb,
+- 0xe2, 0xe7, 0xb8, 0x20, 0xe3, 0xdd, 0x97, 0x0e,
+- 0x7d, 0xdd, 0x39, 0x09, 0x1b, 0x32, 0x35, 0x2f },
+- }, {
+- .key = { [0 ... 79] = 0xaa },
++ .digest = "\x69\x53\x02\x5e\xd9\x6f\x0c\x09"
++ "\xf8\x0a\x96\xf7\x8e\x65\x38\xdb"
++ "\xe2\xe7\xb8\x20\xe3\xdd\x97\x0e"
++ "\x7d\xdd\x39\x09\x1b\x32\x35\x2f",
++ }, {
++ .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa",
+ .ksize = 80,
+ .plaintext = "Test Using Larger Than Block-Size Key and Larger Than "
+- "One Block-Size Data",
++ "One Block-Size Data",
+ .psize = 73,
+- .digest = { 0x63, 0x55, 0xac, 0x22, 0xe8, 0x90, 0xd0, 0xa3,
+- 0xc8, 0x48, 0x1a, 0x5c, 0xa4, 0x82, 0x5b, 0xc8,
+- 0x84, 0xd3, 0xe7, 0xa1, 0xff, 0x98, 0xa2, 0xfc,
+- 0x2a, 0xc7, 0xd8, 0xe0, 0x64, 0xc3, 0xb2, 0xe6 },
++ .digest = "\x63\x55\xac\x22\xe8\x90\xd0\xa3"
++ "\xc8\x48\x1a\x5c\xa4\x82\x5b\xc8"
++ "\x84\xd3\xe7\xa1\xff\x98\xa2\xfc"
++ "\x2a\xc7\xd8\xe0\x64\xc3\xb2\xe6",
+ },
+ };
+
+@@ -1101,63 +1158,63 @@ static struct hash_testvec hmac_sha256_tv_template[] = {
+
+ static struct hash_testvec aes_xcbc128_tv_template[] = {
+ {
+- .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+- .plaintext = { [0 ... 15] = 0 },
+- .digest = { 0x75, 0xf0, 0x25, 0x1d, 0x52, 0x8a, 0xc0, 0x1c,
+- 0x45, 0x73, 0xdf, 0xd5, 0x84, 0xd7, 0x9f, 0x29 },
++ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
++ .plaintext = zeroed_string,
++ .digest = "\x75\xf0\x25\x1d\x52\x8a\xc0\x1c"
++ "\x45\x73\xdf\xd5\x84\xd7\x9f\x29",
+ .psize = 0,
+ .ksize = 16,
+ }, {
+- .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+- .plaintext = { 0x00, 0x01, 0x02 },
+- .digest = { 0x5b, 0x37, 0x65, 0x80, 0xae, 0x2f, 0x19, 0xaf,
+- 0xe7, 0x21, 0x9c, 0xee, 0xf1, 0x72, 0x75, 0x6f },
++ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
++ .plaintext = "\x00\x01\x02",
++ .digest = "\x5b\x37\x65\x80\xae\x2f\x19\xaf"
++ "\xe7\x21\x9c\xee\xf1\x72\x75\x6f",
+ .psize = 3,
+ .ksize = 16,
+ } , {
+- .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+- .plaintext = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+- .digest = { 0xd2, 0xa2, 0x46, 0xfa, 0x34, 0x9b, 0x68, 0xa7,
+- 0x99, 0x98, 0xa4, 0x39, 0x4f, 0xf7, 0xa2, 0x63 },
++ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
++ .plaintext = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
++ .digest = "\xd2\xa2\x46\xfa\x34\x9b\x68\xa7"
++ "\x99\x98\xa4\x39\x4f\xf7\xa2\x63",
+ .psize = 16,
+ .ksize = 16,
+ }, {
+- .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+- .plaintext = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13 },
+- .digest = { 0x47, 0xf5, 0x1b, 0x45, 0x64, 0x96, 0x62, 0x15,
+- 0xb8, 0x98, 0x5c, 0x63, 0x05, 0x5e, 0xd3, 0x08 },
++ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
++ .plaintext = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13",
++ .digest = "\x47\xf5\x1b\x45\x64\x96\x62\x15"
++ "\xb8\x98\x5c\x63\x05\x5e\xd3\x08",
+ .tap = { 10, 10 },
+ .psize = 20,
+ .np = 2,
+ .ksize = 16,
+ }, {
+- .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+- .plaintext = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+- .digest = { 0xf5, 0x4f, 0x0e, 0xc8, 0xd2, 0xb9, 0xf3, 0xd3,
+- 0x68, 0x07, 0x73, 0x4b, 0xd5, 0x28, 0x3f, 0xd4 },
++ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
++ .plaintext = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
++ .digest = "\xf5\x4f\x0e\xc8\xd2\xb9\xf3\xd3"
++ "\x68\x07\x73\x4b\xd5\x28\x3f\xd4",
+ .psize = 32,
+ .ksize = 16,
+ }, {
+- .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+- .plaintext = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+- 0x20, 0x21 },
+- .digest = { 0xbe, 0xcb, 0xb3, 0xbc, 0xcd, 0xb5, 0x18, 0xa3,
+- 0x06, 0x77, 0xd5, 0x48, 0x1f, 0xb6, 0xb4, 0xd8 },
++ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
++ .plaintext = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
++ "\x20\x21",
++ .digest = "\xbe\xcb\xb3\xbc\xcd\xb5\x18\xa3"
++ "\x06\x77\xd5\x48\x1f\xb6\xb4\xd8",
+ .tap = { 17, 17 },
+ .psize = 34,
+ .np = 2,
+@@ -1173,112 +1230,95 @@ static struct hash_testvec aes_xcbc128_tv_template[] = {
+
+ static struct hash_testvec hmac_sha384_tv_template[] = {
+ {
+- .key = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+- 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+- 0x0b, 0x0b, 0x0b, 0x0b }, // (20 bytes)
++ .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
++ "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
++ "\x0b\x0b\x0b\x0b",
+ .ksize = 20,
+- .plaintext = { 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 }, // ("Hi There")
++ .plaintext = "Hi There",
+ .psize = 8,
+- .digest = { 0xaf, 0xd0, 0x39, 0x44, 0xd8, 0x48, 0x95, 0x62,
+- 0x6b, 0x08, 0x25, 0xf4, 0xab, 0x46, 0x90, 0x7f,
+- 0x15, 0xf9, 0xda, 0xdb, 0xe4, 0x10, 0x1e, 0xc6,
+- 0x82, 0xaa, 0x03, 0x4c, 0x7c, 0xeb, 0xc5, 0x9c,
+- 0xfa, 0xea, 0x9e, 0xa9, 0x07, 0x6e, 0xde, 0x7f,
+- 0x4a, 0xf1, 0x52, 0xe8, 0xb2, 0xfa, 0x9c, 0xb6 },
+- }, {
+- .key = { 0x4a, 0x65, 0x66, 0x65 }, // ("Jefe")
++ .digest = "\xaf\xd0\x39\x44\xd8\x48\x95\x62"
++ "\x6b\x08\x25\xf4\xab\x46\x90\x7f"
++ "\x15\xf9\xda\xdb\xe4\x10\x1e\xc6"
++ "\x82\xaa\x03\x4c\x7c\xeb\xc5\x9c"
++ "\xfa\xea\x9e\xa9\x07\x6e\xde\x7f"
++ "\x4a\xf1\x52\xe8\xb2\xfa\x9c\xb6",
++ }, {
++ .key = "Jefe",
+ .ksize = 4,
+- .plaintext = { 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20,
+- 0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20, // ("what do ya want ")
+- 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
+- 0x69, 0x6e, 0x67, 0x3f }, // ("for nothing?")
++ .plaintext = "what do ya want for nothing?",
+ .psize = 28,
+- .digest = { 0xaf, 0x45, 0xd2, 0xe3, 0x76, 0x48, 0x40, 0x31,
+- 0x61, 0x7f, 0x78, 0xd2, 0xb5, 0x8a, 0x6b, 0x1b,
+- 0x9c, 0x7e, 0xf4, 0x64, 0xf5, 0xa0, 0x1b, 0x47,
+- 0xe4, 0x2e, 0xc3, 0x73, 0x63, 0x22, 0x44, 0x5e,
+- 0x8e, 0x22, 0x40, 0xca, 0x5e, 0x69, 0xe2, 0xc7,
+- 0x8b, 0x32, 0x39, 0xec, 0xfa, 0xb2, 0x16, 0x49 },
++ .digest = "\xaf\x45\xd2\xe3\x76\x48\x40\x31"
++ "\x61\x7f\x78\xd2\xb5\x8a\x6b\x1b"
++ "\x9c\x7e\xf4\x64\xf5\xa0\x1b\x47"
++ "\xe4\x2e\xc3\x73\x63\x22\x44\x5e"
++ "\x8e\x22\x40\xca\x5e\x69\xe2\xc7"
++ "\x8b\x32\x39\xec\xfa\xb2\x16\x49",
+ .np = 4,
+ .tap = { 7, 7, 7, 7 }
+ }, {
+- .key = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa }, // (131 bytes)
++ .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa",
+ .ksize = 131,
+- .plaintext = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69,
+- 0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65, // ("Test Using Large")
+- 0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42,
+- 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a, // ("r Than Block-Siz")
+- 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x2d, 0x20,
+- 0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79, // ("e Key - Hash Key")
+- 0x20, 0x46, 0x69, 0x72, 0x73, 0x74 }, // (" First")
++ .plaintext = "Test Using Larger Than Block-Siz"
++ "e Key - Hash Key First",
+ .psize = 54,
+- .digest = { 0x4e, 0xce, 0x08, 0x44, 0x85, 0x81, 0x3e, 0x90,
+- 0x88, 0xd2, 0xc6, 0x3a, 0x04, 0x1b, 0xc5, 0xb4,
+- 0x4f, 0x9e, 0xf1, 0x01, 0x2a, 0x2b, 0x58, 0x8f,
+- 0x3c, 0xd1, 0x1f, 0x05, 0x03, 0x3a, 0xc4, 0xc6,
+- 0x0c, 0x2e, 0xf6, 0xab, 0x40, 0x30, 0xfe, 0x82,
+- 0x96, 0x24, 0x8d, 0xf1, 0x63, 0xf4, 0x49, 0x52 },
+- }, {
+- .key = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa }, // (131 bytes)
++ .digest = "\x4e\xce\x08\x44\x85\x81\x3e\x90"
++ "\x88\xd2\xc6\x3a\x04\x1b\xc5\xb4"
++ "\x4f\x9e\xf1\x01\x2a\x2b\x58\x8f"
++ "\x3c\xd1\x1f\x05\x03\x3a\xc4\xc6"
++ "\x0c\x2e\xf6\xab\x40\x30\xfe\x82"
++ "\x96\x24\x8d\xf1\x63\xf4\x49\x52",
++ }, {
++ .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa",
+ .ksize = 131,
+- .plaintext = { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
+- 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75, // ("This is a test u")
+- 0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x6c,
+- 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68, // ("sing a larger th")
+- 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+- 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6b, 0x65, // ("an block-size ke")
+- 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20,
+- 0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, // ("y and a larger t")
+- 0x68, 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63,
+- 0x6b, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x64, // ("han block-size d")
+- 0x61, 0x74, 0x61, 0x2e, 0x20, 0x54, 0x68, 0x65,
+- 0x20, 0x6b, 0x65, 0x79, 0x20, 0x6e, 0x65, 0x65, // ("ata. The key nee")
+- 0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65,
+- 0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x64, 0x20, // ("ds to be hashed ")
+- 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x62,
+- 0x65, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x65, // ("before being use")
+- 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65,
+- 0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x61, 0x6c, // ("d by the HMAC al")
+- 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2e }, // ("gorithm.")
++ .plaintext = "This is a test u"
++ "sing a larger th"
++ "an block-size ke"
++ "y and a larger t"
++ "han block-size d"
++ "ata. The key nee"
++ "ds to be hashed "
++ "before being use"
++ "d by the HMAC al"
++ "gorithm.",
+ .psize = 152,
+- .digest = { 0x66, 0x17, 0x17, 0x8e, 0x94, 0x1f, 0x02, 0x0d,
+- 0x35, 0x1e, 0x2f, 0x25, 0x4e, 0x8f, 0xd3, 0x2c,
+- 0x60, 0x24, 0x20, 0xfe, 0xb0, 0xb8, 0xfb, 0x9a,
+- 0xdc, 0xce, 0xbb, 0x82, 0x46, 0x1e, 0x99, 0xc5,
+- 0xa6, 0x78, 0xcc, 0x31, 0xe7, 0x99, 0x17, 0x6d,
+- 0x38, 0x60, 0xe6, 0x11, 0x0c, 0x46, 0x52, 0x3e },
++ .digest = "\x66\x17\x17\x8e\x94\x1f\x02\x0d"
++ "\x35\x1e\x2f\x25\x4e\x8f\xd3\x2c"
++ "\x60\x24\x20\xfe\xb0\xb8\xfb\x9a"
++ "\xdc\xce\xbb\x82\x46\x1e\x99\xc5"
++ "\xa6\x78\xcc\x31\xe7\x99\x17\x6d"
++ "\x38\x60\xe6\x11\x0c\x46\x52\x3e",
+ },
+ };
+
+@@ -1290,120 +1330,106 @@ static struct hash_testvec hmac_sha384_tv_template[] = {
+
+ static struct hash_testvec hmac_sha512_tv_template[] = {
+ {
+- .key = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+- 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+- 0x0b, 0x0b, 0x0b, 0x0b }, // (20 bytes)
++ .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
++ "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
++ "\x0b\x0b\x0b\x0b",
+ .ksize = 20,
+- .plaintext = { 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 }, // ("Hi There")
++ .plaintext = "Hi There",
+ .psize = 8,
+- .digest = { 0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d,
+- 0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0,
+- 0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78,
+- 0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde,
+- 0xda, 0xa8, 0x33, 0xb7, 0xd6, 0xb8, 0xa7, 0x02,
+- 0x03, 0x8b, 0x27, 0x4e, 0xae, 0xa3, 0xf4, 0xe4,
+- 0xbe, 0x9d, 0x91, 0x4e, 0xeb, 0x61, 0xf1, 0x70,
+- 0x2e, 0x69, 0x6c, 0x20, 0x3a, 0x12, 0x68, 0x54 },
+- }, {
+- .key = { 0x4a, 0x65, 0x66, 0x65 }, // ("Jefe")
++ .digest = "\x87\xaa\x7c\xde\xa5\xef\x61\x9d"
++ "\x4f\xf0\xb4\x24\x1a\x1d\x6c\xb0"
++ "\x23\x79\xf4\xe2\xce\x4e\xc2\x78"
++ "\x7a\xd0\xb3\x05\x45\xe1\x7c\xde"
++ "\xda\xa8\x33\xb7\xd6\xb8\xa7\x02"
++ "\x03\x8b\x27\x4e\xae\xa3\xf4\xe4"
++ "\xbe\x9d\x91\x4e\xeb\x61\xf1\x70"
++ "\x2e\x69\x6c\x20\x3a\x12\x68\x54",
++ }, {
++ .key = "Jefe",
+ .ksize = 4,
+- .plaintext = { 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20,
+- 0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20, // ("what do ya want ")
+- 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
+- 0x69, 0x6e, 0x67, 0x3f }, // ("for nothing?")
++ .plaintext = "what do ya want for nothing?",
+ .psize = 28,
+- .digest = { 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2,
+- 0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3,
+- 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6,
+- 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54,
+- 0x97, 0x58, 0xbf, 0x75, 0xc0, 0x5a, 0x99, 0x4a,
+- 0x6d, 0x03, 0x4f, 0x65, 0xf8, 0xf0, 0xe6, 0xfd,
+- 0xca, 0xea, 0xb1, 0xa3, 0x4d, 0x4a, 0x6b, 0x4b,
+- 0x63, 0x6e, 0x07, 0x0a, 0x38, 0xbc, 0xe7, 0x37 },
++ .digest = "\x16\x4b\x7a\x7b\xfc\xf8\x19\xe2"
++ "\xe3\x95\xfb\xe7\x3b\x56\xe0\xa3"
++ "\x87\xbd\x64\x22\x2e\x83\x1f\xd6"
++ "\x10\x27\x0c\xd7\xea\x25\x05\x54"
++ "\x97\x58\xbf\x75\xc0\x5a\x99\x4a"
++ "\x6d\x03\x4f\x65\xf8\xf0\xe6\xfd"
++ "\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b"
++ "\x63\x6e\x07\x0a\x38\xbc\xe7\x37",
+ .np = 4,
+ .tap = { 7, 7, 7, 7 }
+ }, {
+- .key = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa }, // (131 bytes)
++ .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa",
+ .ksize = 131,
+- .plaintext = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69,
+- 0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65, // ("Test Using Large")
+- 0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42,
+- 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a, // ("r Than Block-Siz")
+- 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x2d, 0x20,
+- 0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79, // ("e Key - Hash Key")
+- 0x20, 0x46, 0x69, 0x72, 0x73, 0x74 }, // (" First")
++ .plaintext = "Test Using Large"
++ "r Than Block-Siz"
++ "e Key - Hash Key"
++ " First",
+ .psize = 54,
+- .digest = { 0x80, 0xb2, 0x42, 0x63, 0xc7, 0xc1, 0xa3, 0xeb,
+- 0xb7, 0x14, 0x93, 0xc1, 0xdd, 0x7b, 0xe8, 0xb4,
+- 0x9b, 0x46, 0xd1, 0xf4, 0x1b, 0x4a, 0xee, 0xc1,
+- 0x12, 0x1b, 0x01, 0x37, 0x83, 0xf8, 0xf3, 0x52,
+- 0x6b, 0x56, 0xd0, 0x37, 0xe0, 0x5f, 0x25, 0x98,
+- 0xbd, 0x0f, 0xd2, 0x21, 0x5d, 0x6a, 0x1e, 0x52,
+- 0x95, 0xe6, 0x4f, 0x73, 0xf6, 0x3f, 0x0a, 0xec,
+- 0x8b, 0x91, 0x5a, 0x98, 0x5d, 0x78, 0x65, 0x98 },
+- }, {
+- .key = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+- 0xaa, 0xaa, 0xaa }, // (131 bytes)
++ .digest = "\x80\xb2\x42\x63\xc7\xc1\xa3\xeb"
++ "\xb7\x14\x93\xc1\xdd\x7b\xe8\xb4"
++ "\x9b\x46\xd1\xf4\x1b\x4a\xee\xc1"
++ "\x12\x1b\x01\x37\x83\xf8\xf3\x52"
++ "\x6b\x56\xd0\x37\xe0\x5f\x25\x98"
++ "\xbd\x0f\xd2\x21\x5d\x6a\x1e\x52"
++ "\x95\xe6\x4f\x73\xf6\x3f\x0a\xec"
++ "\x8b\x91\x5a\x98\x5d\x78\x65\x98",
++ }, {
++ .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
++ "\xaa\xaa\xaa",
+ .ksize = 131,
+- .plaintext = { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
+- 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75, // ("This is a test u")
+- 0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x6c,
+- 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68, // ("sing a larger th")
+- 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+- 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6b, 0x65, // ("an block-size ke")
+- 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20,
+- 0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, // ("y and a larger t")
+- 0x68, 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63,
+- 0x6b, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x64, // ("han block-size d")
+- 0x61, 0x74, 0x61, 0x2e, 0x20, 0x54, 0x68, 0x65,
+- 0x20, 0x6b, 0x65, 0x79, 0x20, 0x6e, 0x65, 0x65, // ("ata. The key nee")
+- 0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65,
+- 0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x64, 0x20, // ("ds to be hashed ")
+- 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x62,
+- 0x65, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x65, // ("before being use")
+- 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65,
+- 0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x61, 0x6c, // ("d by the HMAC al")
+- 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2e }, // ("gorithm.")
++ .plaintext =
++ "This is a test u"
++ "sing a larger th"
++ "an block-size ke"
++ "y and a larger t"
++ "han block-size d"
++ "ata. The key nee"
++ "ds to be hashed "
++ "before being use"
++ "d by the HMAC al"
++ "gorithm.",
+ .psize = 152,
+- .digest = { 0xe3, 0x7b, 0x6a, 0x77, 0x5d, 0xc8, 0x7d, 0xba,
+- 0xa4, 0xdf, 0xa9, 0xf9, 0x6e, 0x5e, 0x3f, 0xfd,
+- 0xde, 0xbd, 0x71, 0xf8, 0x86, 0x72, 0x89, 0x86,
+- 0x5d, 0xf5, 0xa3, 0x2d, 0x20, 0xcd, 0xc9, 0x44,
+- 0xb6, 0x02, 0x2c, 0xac, 0x3c, 0x49, 0x82, 0xb1,
+- 0x0d, 0x5e, 0xeb, 0x55, 0xc3, 0xe4, 0xde, 0x15,
+- 0x13, 0x46, 0x76, 0xfb, 0x6d, 0xe0, 0x44, 0x60,
+- 0x65, 0xc9, 0x74, 0x40, 0xfa, 0x8c, 0x6a, 0x58 },
++ .digest = "\xe3\x7b\x6a\x77\x5d\xc8\x7d\xba"
++ "\xa4\xdf\xa9\xf9\x6e\x5e\x3f\xfd"
++ "\xde\xbd\x71\xf8\x86\x72\x89\x86"
++ "\x5d\xf5\xa3\x2d\x20\xcd\xc9\x44"
++ "\xb6\x02\x2c\xac\x3c\x49\x82\xb1"
++ "\x0d\x5e\xeb\x55\xc3\xe4\xde\x15"
++ "\x13\x46\x76\xfb\x6d\xe0\x44\x60"
++ "\x65\xc9\x74\x40\xfa\x8c\x6a\x58",
+ },
+ };
+
+@@ -1419,102 +1445,102 @@ static struct hash_testvec hmac_sha512_tv_template[] = {
+
+ static struct cipher_testvec des_enc_tv_template[] = {
+ { /* From Applied Cryptography */
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 },
++ .input = "\x01\x23\x45\x67\x89\xab\xcd\xe7",
+ .ilen = 8,
+- .result = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d },
++ .result = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d",
+ .rlen = 8,
+ }, { /* Same key, different plaintext block */
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .input = { 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 },
++ .input = "\x22\x33\x44\x55\x66\x77\x88\x99",
+ .ilen = 8,
+- .result = { 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b },
++ .result = "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b",
+ .rlen = 8,
+ }, { /* Sbox test from NBS */
+- .key = { 0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57 },
++ .key = "\x7c\xa1\x10\x45\x4a\x1a\x6e\x57",
+ .klen = 8,
+- .input = { 0x01, 0xa1, 0xd6, 0xd0, 0x39, 0x77, 0x67, 0x42 },
++ .input = "\x01\xa1\xd6\xd0\x39\x77\x67\x42",
+ .ilen = 8,
+- .result = { 0x69, 0x0f, 0x5b, 0x0d, 0x9a, 0x26, 0x93, 0x9b },
++ .result = "\x69\x0f\x5b\x0d\x9a\x26\x93\x9b",
+ .rlen = 8,
+ }, { /* Three blocks */
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+- 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
+- 0xca, 0xfe, 0xba, 0xbe, 0xfe, 0xed, 0xbe, 0xef },
++ .input = "\x01\x23\x45\x67\x89\xab\xcd\xe7"
++ "\x22\x33\x44\x55\x66\x77\x88\x99"
++ "\xca\xfe\xba\xbe\xfe\xed\xbe\xef",
+ .ilen = 24,
+- .result = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+- 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b,
+- 0xb4, 0x99, 0x26, 0xf7, 0x1f, 0xe1, 0xd4, 0x90 },
++ .result = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d"
++ "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b"
++ "\xb4\x99\x26\xf7\x1f\xe1\xd4\x90",
+ .rlen = 24,
+ }, { /* Weak key */
+ .fail = 1,
+ .wk = 1,
+- .key = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
++ .key = "\x01\x01\x01\x01\x01\x01\x01\x01",
+ .klen = 8,
+- .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 },
++ .input = "\x01\x23\x45\x67\x89\xab\xcd\xe7",
+ .ilen = 8,
+- .result = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d },
++ .result = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d",
+ .rlen = 8,
+ }, { /* Two blocks -- for testing encryption across pages */
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+- 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 },
++ .input = "\x01\x23\x45\x67\x89\xab\xcd\xe7"
++ "\x22\x33\x44\x55\x66\x77\x88\x99",
+ .ilen = 16,
+- .result = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+- 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b },
++ .result = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d"
++ "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b",
+ .rlen = 16,
+ .np = 2,
+ .tap = { 8, 8 }
+ }, { /* Four blocks -- for testing encryption with chunking */
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+- 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
+- 0xca, 0xfe, 0xba, 0xbe, 0xfe, 0xed, 0xbe, 0xef,
+- 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 },
++ .input = "\x01\x23\x45\x67\x89\xab\xcd\xe7"
++ "\x22\x33\x44\x55\x66\x77\x88\x99"
++ "\xca\xfe\xba\xbe\xfe\xed\xbe\xef"
++ "\x22\x33\x44\x55\x66\x77\x88\x99",
+ .ilen = 32,
+- .result = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+- 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b,
+- 0xb4, 0x99, 0x26, 0xf7, 0x1f, 0xe1, 0xd4, 0x90,
+- 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b },
++ .result = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d"
++ "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b"
++ "\xb4\x99\x26\xf7\x1f\xe1\xd4\x90"
++ "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b",
+ .rlen = 32,
+ .np = 3,
+ .tap = { 14, 10, 8 }
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+- 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
+- 0xca, 0xfe, 0xba, 0xbe, 0xfe, 0xed, 0xbe, 0xef },
++ .input = "\x01\x23\x45\x67\x89\xab\xcd\xe7"
++ "\x22\x33\x44\x55\x66\x77\x88\x99"
++ "\xca\xfe\xba\xbe\xfe\xed\xbe\xef",
+ .ilen = 24,
+- .result = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+- 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b,
+- 0xb4, 0x99, 0x26, 0xf7, 0x1f, 0xe1, 0xd4, 0x90 },
++ .result = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d"
++ "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b"
++ "\xb4\x99\x26\xf7\x1f\xe1\xd4\x90",
+ .rlen = 24,
+ .np = 4,
+ .tap = { 2, 1, 3, 18 }
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+- 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 },
++ .input = "\x01\x23\x45\x67\x89\xab\xcd\xe7"
++ "\x22\x33\x44\x55\x66\x77\x88\x99",
+ .ilen = 16,
+- .result = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+- 0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b },
++ .result = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d"
++ "\xf7\x9c\x89\x2a\x33\x8f\x4a\x8b",
+ .rlen = 16,
+ .np = 5,
+ .tap = { 2, 2, 2, 2, 8 }
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 },
++ .input = "\x01\x23\x45\x67\x89\xab\xcd\xe7",
+ .ilen = 8,
+- .result = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d },
++ .result = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d",
+ .rlen = 8,
+ .np = 8,
+ .tap = { 1, 1, 1, 1, 1, 1, 1, 1 }
+@@ -1523,38 +1549,38 @@ static struct cipher_testvec des_enc_tv_template[] = {
+
+ static struct cipher_testvec des_dec_tv_template[] = {
+ { /* From Applied Cryptography */
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .input = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d },
++ .input = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d",
+ .ilen = 8,
+- .result = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 },
++ .result = "\x01\x23\x45\x67\x89\xab\xcd\xe7",
+ .rlen = 8,
+ }, { /* Sbox test from NBS */
+- .key = { 0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57 },
++ .key = "\x7c\xa1\x10\x45\x4a\x1a\x6e\x57",
+ .klen = 8,
+- .input = { 0x69, 0x0f, 0x5b, 0x0d, 0x9a, 0x26, 0x93, 0x9b },
++ .input = "\x69\x0f\x5b\x0d\x9a\x26\x93\x9b",
+ .ilen = 8,
+- .result = { 0x01, 0xa1, 0xd6, 0xd0, 0x39, 0x77, 0x67, 0x42 },
++ .result = "\x01\xa1\xd6\xd0\x39\x77\x67\x42",
+ .rlen = 8,
+ }, { /* Two blocks, for chunking test */
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .input = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+- 0x69, 0x0f, 0x5b, 0x0d, 0x9a, 0x26, 0x93, 0x9b },
++ .input = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d"
++ "\x69\x0f\x5b\x0d\x9a\x26\x93\x9b",
+ .ilen = 16,
+- .result = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+- 0xa3, 0x99, 0x7b, 0xca, 0xaf, 0x69, 0xa0, 0xf5 },
++ .result = "\x01\x23\x45\x67\x89\xab\xcd\xe7"
++ "\xa3\x99\x7b\xca\xaf\x69\xa0\xf5",
+ .rlen = 16,
+ .np = 2,
+ .tap = { 8, 8 }
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .input = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d,
+- 0x69, 0x0f, 0x5b, 0x0d, 0x9a, 0x26, 0x93, 0x9b },
++ .input = "\xc9\x57\x44\x25\x6a\x5e\xd3\x1d"
++ "\x69\x0f\x5b\x0d\x9a\x26\x93\x9b",
+ .ilen = 16,
+- .result = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7,
+- 0xa3, 0x99, 0x7b, 0xca, 0xaf, 0x69, 0xa0, 0xf5 },
++ .result = "\x01\x23\x45\x67\x89\xab\xcd\xe7"
++ "\xa3\x99\x7b\xca\xaf\x69\xa0\xf5",
+ .rlen = 16,
+ .np = 3,
+ .tap = { 3, 12, 1 }
+@@ -1563,53 +1589,53 @@ static struct cipher_testvec des_dec_tv_template[] = {
+
+ static struct cipher_testvec des_cbc_enc_tv_template[] = {
+ { /* From OpenSSL */
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .iv = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+- .input = { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20,
+- 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
+- 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 },
++ .iv = "\xfe\xdc\xba\x98\x76\x54\x32\x10",
++ .input = "\x37\x36\x35\x34\x33\x32\x31\x20"
++ "\x4e\x6f\x77\x20\x69\x73\x20\x74"
++ "\x68\x65\x20\x74\x69\x6d\x65\x20",
+ .ilen = 24,
+- .result = { 0xcc, 0xd1, 0x73, 0xff, 0xab, 0x20, 0x39, 0xf4,
+- 0xac, 0xd8, 0xae, 0xfd, 0xdf, 0xd8, 0xa1, 0xeb,
+- 0x46, 0x8e, 0x91, 0x15, 0x78, 0x88, 0xba, 0x68 },
++ .result = "\xcc\xd1\x73\xff\xab\x20\x39\xf4"
++ "\xac\xd8\xae\xfd\xdf\xd8\xa1\xeb"
++ "\x46\x8e\x91\x15\x78\x88\xba\x68",
+ .rlen = 24,
+ }, { /* FIPS Pub 81 */
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .iv = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef },
+- .input = { 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 },
++ .iv = "\x12\x34\x56\x78\x90\xab\xcd\xef",
++ .input = "\x4e\x6f\x77\x20\x69\x73\x20\x74",
+ .ilen = 8,
+- .result = { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },
++ .result = "\xe5\xc7\xcd\xde\x87\x2b\xf2\x7c",
+ .rlen = 8,
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .iv = { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },
+- .input = { 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 },
++ .iv = "\xe5\xc7\xcd\xde\x87\x2b\xf2\x7c",
++ .input = "\x68\x65\x20\x74\x69\x6d\x65\x20",
+ .ilen = 8,
+- .result = { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
++ .result = "\x43\xe9\x34\x00\x8c\x38\x9c\x0f",
+ .rlen = 8,
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .iv = { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
+- .input = { 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 },
++ .iv = "\x43\xe9\x34\x00\x8c\x38\x9c\x0f",
++ .input = "\x66\x6f\x72\x20\x61\x6c\x6c\x20",
+ .ilen = 8,
+- .result = { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 },
++ .result = "\x68\x37\x88\x49\x9a\x7c\x05\xf6",
+ .rlen = 8,
+ }, { /* Copy of openssl vector for chunk testing */
+ /* From OpenSSL */
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .iv = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+- .input = { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20,
+- 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
+- 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 },
++ .iv = "\xfe\xdc\xba\x98\x76\x54\x32\x10",
++ .input = "\x37\x36\x35\x34\x33\x32\x31\x20"
++ "\x4e\x6f\x77\x20\x69\x73\x20\x74"
++ "\x68\x65\x20\x74\x69\x6d\x65\x20",
+ .ilen = 24,
+- .result = { 0xcc, 0xd1, 0x73, 0xff, 0xab, 0x20, 0x39, 0xf4,
+- 0xac, 0xd8, 0xae, 0xfd, 0xdf, 0xd8, 0xa1, 0xeb,
+- 0x46, 0x8e, 0x91, 0x15, 0x78, 0x88, 0xba, 0x68 },
++ .result = "\xcc\xd1\x73\xff\xab\x20\x39\xf4"
++ "\xac\xd8\xae\xfd\xdf\xd8\xa1\xeb"
++ "\x46\x8e\x91\x15\x78\x88\xba\x68",
+ .rlen = 24,
+ .np = 2,
+ .tap = { 13, 11 }
+@@ -1618,36 +1644,36 @@ static struct cipher_testvec des_cbc_enc_tv_template[] = {
+
+ static struct cipher_testvec des_cbc_dec_tv_template[] = {
+ { /* FIPS Pub 81 */
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .iv = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef },
+- .input = { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },
++ .iv = "\x12\x34\x56\x78\x90\xab\xcd\xef",
++ .input = "\xe5\xc7\xcd\xde\x87\x2b\xf2\x7c",
+ .ilen = 8,
+- .result = { 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 },
++ .result = "\x4e\x6f\x77\x20\x69\x73\x20\x74",
+ .rlen = 8,
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .iv = { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },
+- .input = { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
++ .iv = "\xe5\xc7\xcd\xde\x87\x2b\xf2\x7c",
++ .input = "\x43\xe9\x34\x00\x8c\x38\x9c\x0f",
+ .ilen = 8,
+- .result = { 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 },
++ .result = "\x68\x65\x20\x74\x69\x6d\x65\x20",
+ .rlen = 8,
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .iv = { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
+- .input = { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 },
++ .iv = "\x43\xe9\x34\x00\x8c\x38\x9c\x0f",
++ .input = "\x68\x37\x88\x49\x9a\x7c\x05\xf6",
+ .ilen = 8,
+- .result = { 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 },
++ .result = "\x66\x6f\x72\x20\x61\x6c\x6c\x20",
+ .rlen = 8,
+ }, { /* Copy of above, for chunk testing */
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .iv = { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
+- .input = { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 },
++ .iv = "\x43\xe9\x34\x00\x8c\x38\x9c\x0f",
++ .input = "\x68\x37\x88\x49\x9a\x7c\x05\xf6",
+ .ilen = 8,
+- .result = { 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 },
++ .result = "\x66\x6f\x72\x20\x61\x6c\x6c\x20",
+ .rlen = 8,
+ .np = 2,
+ .tap = { 4, 4 }
+@@ -1659,62 +1685,62 @@ static struct cipher_testvec des_cbc_dec_tv_template[] = {
+ */
+ static struct cipher_testvec des3_ede_enc_tv_template[] = {
+ { /* These are from openssl */
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+- 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef"
++ "\x55\x55\x55\x55\x55\x55\x55\x55"
++ "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ .klen = 24,
+- .input = { 0x73, 0x6f, 0x6d, 0x65, 0x64, 0x61, 0x74, 0x61 },
++ .input = "\x73\x6f\x6d\x65\x64\x61\x74\x61",
+ .ilen = 8,
+- .result = { 0x18, 0xd7, 0x48, 0xe5, 0x63, 0x62, 0x05, 0x72 },
++ .result = "\x18\xd7\x48\xe5\x63\x62\x05\x72",
+ .rlen = 8,
+ }, {
+- .key = { 0x03, 0x52, 0x02, 0x07, 0x67, 0x20, 0x82, 0x17,
+- 0x86, 0x02, 0x87, 0x66, 0x59, 0x08, 0x21, 0x98,
+- 0x64, 0x05, 0x6a, 0xbd, 0xfe, 0xa9, 0x34, 0x57 },
++ .key = "\x03\x52\x02\x07\x67\x20\x82\x17"
++ "\x86\x02\x87\x66\x59\x08\x21\x98"
++ "\x64\x05\x6a\xbd\xfe\xa9\x34\x57",
+ .klen = 24,
+- .input = { 0x73, 0x71, 0x75, 0x69, 0x67, 0x67, 0x6c, 0x65 },
++ .input = "\x73\x71\x75\x69\x67\x67\x6c\x65",
+ .ilen = 8,
+- .result = { 0xc0, 0x7d, 0x2a, 0x0f, 0xa5, 0x66, 0xfa, 0x30 },
++ .result = "\xc0\x7d\x2a\x0f\xa5\x66\xfa\x30",
+ .rlen = 8,
+ }, {
+- .key = { 0x10, 0x46, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20,
+- 0x91, 0x07, 0xd0, 0x15, 0x89, 0x19, 0x01, 0x01,
+- 0x19, 0x07, 0x92, 0x10, 0x98, 0x1a, 0x01, 0x01 },
++ .key = "\x10\x46\x10\x34\x89\x98\x80\x20"
++ "\x91\x07\xd0\x15\x89\x19\x01\x01"
++ "\x19\x07\x92\x10\x98\x1a\x01\x01",
+ .klen = 24,
+- .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .input = "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .ilen = 8,
+- .result = { 0xe1, 0xef, 0x62, 0xc3, 0x32, 0xfe, 0x82, 0x5b },
++ .result = "\xe1\xef\x62\xc3\x32\xfe\x82\x5b",
+ .rlen = 8,
+ },
+ };
+
+ static struct cipher_testvec des3_ede_dec_tv_template[] = {
+ { /* These are from openssl */
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+- 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef"
++ "\x55\x55\x55\x55\x55\x55\x55\x55"
++ "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ .klen = 24,
+- .input = { 0x18, 0xd7, 0x48, 0xe5, 0x63, 0x62, 0x05, 0x72 },
++ .input = "\x18\xd7\x48\xe5\x63\x62\x05\x72",
+ .ilen = 8,
+- .result = { 0x73, 0x6f, 0x6d, 0x65, 0x64, 0x61, 0x74, 0x61 },
++ .result = "\x73\x6f\x6d\x65\x64\x61\x74\x61",
+ .rlen = 8,
+ }, {
+- .key = { 0x03, 0x52, 0x02, 0x07, 0x67, 0x20, 0x82, 0x17,
+- 0x86, 0x02, 0x87, 0x66, 0x59, 0x08, 0x21, 0x98,
+- 0x64, 0x05, 0x6a, 0xbd, 0xfe, 0xa9, 0x34, 0x57 },
++ .key = "\x03\x52\x02\x07\x67\x20\x82\x17"
++ "\x86\x02\x87\x66\x59\x08\x21\x98"
++ "\x64\x05\x6a\xbd\xfe\xa9\x34\x57",
+ .klen = 24,
+- .input = { 0xc0, 0x7d, 0x2a, 0x0f, 0xa5, 0x66, 0xfa, 0x30 },
++ .input = "\xc0\x7d\x2a\x0f\xa5\x66\xfa\x30",
+ .ilen = 8,
+- .result = { 0x73, 0x71, 0x75, 0x69, 0x67, 0x67, 0x6c, 0x65 },
++ .result = "\x73\x71\x75\x69\x67\x67\x6c\x65",
+ .rlen = 8,
+ }, {
+- .key = { 0x10, 0x46, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20,
+- 0x91, 0x07, 0xd0, 0x15, 0x89, 0x19, 0x01, 0x01,
+- 0x19, 0x07, 0x92, 0x10, 0x98, 0x1a, 0x01, 0x01 },
++ .key = "\x10\x46\x10\x34\x89\x98\x80\x20"
++ "\x91\x07\xd0\x15\x89\x19\x01\x01"
++ "\x19\x07\x92\x10\x98\x1a\x01\x01",
+ .klen = 24,
+- .input = { 0xe1, 0xef, 0x62, 0xc3, 0x32, 0xfe, 0x82, 0x5b },
++ .input = "\xe1\xef\x62\xc3\x32\xfe\x82\x5b",
+ .ilen = 8,
+- .result = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .result = "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .rlen = 8,
+ },
+ };
+@@ -1729,148 +1755,148 @@ static struct cipher_testvec des3_ede_dec_tv_template[] = {
+
+ static struct cipher_testvec bf_enc_tv_template[] = {
+ { /* DES test vectors from OpenSSL */
+- .key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
++ .key = "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .klen = 8,
+- .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .input = "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .ilen = 8,
+- .result = { 0x4e, 0xf9, 0x97, 0x45, 0x61, 0x98, 0xdd, 0x78 },
++ .result = "\x4e\xf9\x97\x45\x61\x98\xdd\x78",
+ .rlen = 8,
+ }, {
+- .key = { 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e },
++ .key = "\x1f\x1f\x1f\x1f\x0e\x0e\x0e\x0e",
+ .klen = 8,
+- .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .input = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .ilen = 8,
+- .result = { 0xa7, 0x90, 0x79, 0x51, 0x08, 0xea, 0x3c, 0xae },
++ .result = "\xa7\x90\x79\x51\x08\xea\x3c\xae",
+ .rlen = 8,
+ }, {
+- .key = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
++ .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
+ .klen = 8,
+- .input = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++ .input = "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ .ilen = 8,
+- .result = { 0xe8, 0x7a, 0x24, 0x4e, 0x2c, 0xc8, 0x5e, 0x82 },
++ .result = "\xe8\x7a\x24\x4e\x2c\xc8\x5e\x82",
+ .rlen = 8,
+ }, { /* Vary the keylength... */
+- .key = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
+- 0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f },
++ .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87"
++ "\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f",
+ .klen = 16,
+- .input = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++ .input = "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ .ilen = 8,
+- .result = { 0x93, 0x14, 0x28, 0x87, 0xee, 0x3b, 0xe1, 0x5c },
++ .result = "\x93\x14\x28\x87\xee\x3b\xe1\x5c",
+ .rlen = 8,
+ }, {
+- .key = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
+- 0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f,
+- 0x00, 0x11, 0x22, 0x33, 0x44 },
++ .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87"
++ "\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f"
++ "\x00\x11\x22\x33\x44",
+ .klen = 21,
+- .input = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++ .input = "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ .ilen = 8,
+- .result = { 0xe6, 0xf5, 0x1e, 0xd7, 0x9b, 0x9d, 0xb2, 0x1f },
++ .result = "\xe6\xf5\x1e\xd7\x9b\x9d\xb2\x1f",
+ .rlen = 8,
+ }, { /* Generated with bf488 */
+- .key = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
+- 0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f,
+- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+- 0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f,
+- 0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76,
+- 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e,
+- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
++ .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87"
++ "\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f"
++ "\x00\x11\x22\x33\x44\x55\x66\x77"
++ "\x04\x68\x91\x04\xc2\xfd\x3b\x2f"
++ "\x58\x40\x23\x64\x1a\xba\x61\x76"
++ "\x1f\x1f\x1f\x1f\x0e\x0e\x0e\x0e"
++ "\xff\xff\xff\xff\xff\xff\xff\xff",
+ .klen = 56,
+- .input = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++ .input = "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ .ilen = 8,
+- .result = { 0xc0, 0x45, 0x04, 0x01, 0x2e, 0x4e, 0x1f, 0x53 },
++ .result = "\xc0\x45\x04\x01\x2e\x4e\x1f\x53",
+ .rlen = 8,
+ },
+ };
+
+ static struct cipher_testvec bf_dec_tv_template[] = {
+ { /* DES test vectors from OpenSSL */
+- .key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .key = "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .klen = 8,
+- .input = { 0x4e, 0xf9, 0x97, 0x45, 0x61, 0x98, 0xdd, 0x78 },
++ .input = "\x4e\xf9\x97\x45\x61\x98\xdd\x78",
+ .ilen = 8,
+- .result = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .result = "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .rlen = 8,
+ }, {
+- .key = { 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e },
++ .key = "\x1f\x1f\x1f\x1f\x0e\x0e\x0e\x0e",
+ .klen = 8,
+- .input = { 0xa7, 0x90, 0x79, 0x51, 0x08, 0xea, 0x3c, 0xae },
++ .input = "\xa7\x90\x79\x51\x08\xea\x3c\xae",
+ .ilen = 8,
+- .result = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .result = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .rlen = 8,
+ }, {
+- .key = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
++ .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
+ .klen = 8,
+- .input = { 0xe8, 0x7a, 0x24, 0x4e, 0x2c, 0xc8, 0x5e, 0x82 },
++ .input = "\xe8\x7a\x24\x4e\x2c\xc8\x5e\x82",
+ .ilen = 8,
+- .result = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++ .result = "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ .rlen = 8,
+ }, { /* Vary the keylength... */
+- .key = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
+- 0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f },
++ .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87"
++ "\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f",
+ .klen = 16,
+- .input = { 0x93, 0x14, 0x28, 0x87, 0xee, 0x3b, 0xe1, 0x5c },
++ .input = "\x93\x14\x28\x87\xee\x3b\xe1\x5c",
+ .ilen = 8,
+- .result = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++ .result = "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ .rlen = 8,
+ }, {
+- .key = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
+- 0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f,
+- 0x00, 0x11, 0x22, 0x33, 0x44 },
++ .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87"
++ "\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f"
++ "\x00\x11\x22\x33\x44",
+ .klen = 21,
+- .input = { 0xe6, 0xf5, 0x1e, 0xd7, 0x9b, 0x9d, 0xb2, 0x1f },
++ .input = "\xe6\xf5\x1e\xd7\x9b\x9d\xb2\x1f",
+ .ilen = 8,
+- .result = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++ .result = "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ .rlen = 8,
+ }, { /* Generated with bf488, using OpenSSL, Libgcrypt and Nettle */
+- .key = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
+- 0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f,
+- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+- 0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f,
+- 0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76,
+- 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e,
+- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
++ .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87"
++ "\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f"
++ "\x00\x11\x22\x33\x44\x55\x66\x77"
++ "\x04\x68\x91\x04\xc2\xfd\x3b\x2f"
++ "\x58\x40\x23\x64\x1a\xba\x61\x76"
++ "\x1f\x1f\x1f\x1f\x0e\x0e\x0e\x0e"
++ "\xff\xff\xff\xff\xff\xff\xff\xff",
+ .klen = 56,
+- .input = { 0xc0, 0x45, 0x04, 0x01, 0x2e, 0x4e, 0x1f, 0x53 },
++ .input = "\xc0\x45\x04\x01\x2e\x4e\x1f\x53",
+ .ilen = 8,
+- .result = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++ .result = "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ .rlen = 8,
+ },
+ };
+
+ static struct cipher_testvec bf_cbc_enc_tv_template[] = {
+ { /* From OpenSSL */
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+- 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef"
++ "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
+ .klen = 16,
+- .iv = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+- .input = { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20,
+- 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
+- 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20,
+- 0x66, 0x6f, 0x72, 0x20, 0x00, 0x00, 0x00, 0x00 },
++ .iv = "\xfe\xdc\xba\x98\x76\x54\x32\x10",
++ .input = "\x37\x36\x35\x34\x33\x32\x31\x20"
++ "\x4e\x6f\x77\x20\x69\x73\x20\x74"
++ "\x68\x65\x20\x74\x69\x6d\x65\x20"
++ "\x66\x6f\x72\x20\x00\x00\x00\x00",
+ .ilen = 32,
+- .result = { 0x6b, 0x77, 0xb4, 0xd6, 0x30, 0x06, 0xde, 0xe6,
+- 0x05, 0xb1, 0x56, 0xe2, 0x74, 0x03, 0x97, 0x93,
+- 0x58, 0xde, 0xb9, 0xe7, 0x15, 0x46, 0x16, 0xd9,
+- 0x59, 0xf1, 0x65, 0x2b, 0xd5, 0xff, 0x92, 0xcc },
++ .result = "\x6b\x77\xb4\xd6\x30\x06\xde\xe6"
++ "\x05\xb1\x56\xe2\x74\x03\x97\x93"
++ "\x58\xde\xb9\xe7\x15\x46\x16\xd9"
++ "\x59\xf1\x65\x2b\xd5\xff\x92\xcc",
+ .rlen = 32,
+ },
+ };
+
+ static struct cipher_testvec bf_cbc_dec_tv_template[] = {
+ { /* From OpenSSL */
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+- 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef"
++ "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
+ .klen = 16,
+- .iv = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+- .input = { 0x6b, 0x77, 0xb4, 0xd6, 0x30, 0x06, 0xde, 0xe6,
+- 0x05, 0xb1, 0x56, 0xe2, 0x74, 0x03, 0x97, 0x93,
+- 0x58, 0xde, 0xb9, 0xe7, 0x15, 0x46, 0x16, 0xd9,
+- 0x59, 0xf1, 0x65, 0x2b, 0xd5, 0xff, 0x92, 0xcc },
++ .iv = "\xfe\xdc\xba\x98\x76\x54\x32\x10",
++ .input = "\x6b\x77\xb4\xd6\x30\x06\xde\xe6"
++ "\x05\xb1\x56\xe2\x74\x03\x97\x93"
++ "\x58\xde\xb9\xe7\x15\x46\x16\xd9"
++ "\x59\xf1\x65\x2b\xd5\xff\x92\xcc",
+ .ilen = 32,
+- .result = { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20,
+- 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
+- 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20,
+- 0x66, 0x6f, 0x72, 0x20, 0x00, 0x00, 0x00, 0x00 },
++ .result = "\x37\x36\x35\x34\x33\x32\x31\x20"
++ "\x4e\x6f\x77\x20\x69\x73\x20\x74"
++ "\x68\x65\x20\x74\x69\x6d\x65\x20"
++ "\x66\x6f\x72\x20\x00\x00\x00\x00",
+ .rlen = 32,
+ },
+ };
+@@ -1885,158 +1911,158 @@ static struct cipher_testvec bf_cbc_dec_tv_template[] = {
+
+ static struct cipher_testvec tf_enc_tv_template[] = {
+ {
+- .key = { [0 ... 15] = 0x00 },
++ .key = zeroed_string,
+ .klen = 16,
+- .input = { [0 ... 15] = 0x00 },
++ .input = zeroed_string,
+ .ilen = 16,
+- .result = { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
+- 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
++ .result = "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32"
++ "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a",
+ .rlen = 16,
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+- 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef"
++ "\xfe\xdc\xba\x98\x76\x54\x32\x10"
++ "\x00\x11\x22\x33\x44\x55\x66\x77",
+ .klen = 24,
+- .input = { [0 ... 15] = 0x00 },
++ .input = zeroed_string,
+ .ilen = 16,
+- .result = { 0xcf, 0xd1, 0xd2, 0xe5, 0xa9, 0xbe, 0x9c, 0xdf,
+- 0x50, 0x1f, 0x13, 0xb8, 0x92, 0xbd, 0x22, 0x48 },
++ .result = "\xcf\xd1\xd2\xe5\xa9\xbe\x9c\xdf"
++ "\x50\x1f\x13\xb8\x92\xbd\x22\x48",
+ .rlen = 16,
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+- 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+- 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef"
++ "\xfe\xdc\xba\x98\x76\x54\x32\x10"
++ "\x00\x11\x22\x33\x44\x55\x66\x77"
++ "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+ .klen = 32,
+- .input = { [0 ... 15] = 0x00 },
++ .input = zeroed_string,
+ .ilen = 16,
+- .result = { 0x37, 0x52, 0x7b, 0xe0, 0x05, 0x23, 0x34, 0xb8,
+- 0x9f, 0x0c, 0xfc, 0xca, 0xe8, 0x7c, 0xfa, 0x20 },
++ .result = "\x37\x52\x7b\xe0\x05\x23\x34\xb8"
++ "\x9f\x0c\xfc\xca\xe8\x7c\xfa\x20",
+ .rlen = 16,
+ },
+ };
+
+ static struct cipher_testvec tf_dec_tv_template[] = {
+ {
+- .key = { [0 ... 15] = 0x00 },
++ .key = zeroed_string,
+ .klen = 16,
+- .input = { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
+- 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
++ .input = "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32"
++ "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a",
+ .ilen = 16,
+- .result = { [0 ... 15] = 0x00 },
++ .result = zeroed_string,
+ .rlen = 16,
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+- 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef"
++ "\xfe\xdc\xba\x98\x76\x54\x32\x10"
++ "\x00\x11\x22\x33\x44\x55\x66\x77",
+ .klen = 24,
+- .input = { 0xcf, 0xd1, 0xd2, 0xe5, 0xa9, 0xbe, 0x9c, 0xdf,
+- 0x50, 0x1f, 0x13, 0xb8, 0x92, 0xbd, 0x22, 0x48 },
++ .input = "\xcf\xd1\xd2\xe5\xa9\xbe\x9c\xdf"
++ "\x50\x1f\x13\xb8\x92\xbd\x22\x48",
+ .ilen = 16,
+- .result = { [0 ... 15] = 0x00 },
++ .result = zeroed_string,
+ .rlen = 16,
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+- 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+- 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef"
++ "\xfe\xdc\xba\x98\x76\x54\x32\x10"
++ "\x00\x11\x22\x33\x44\x55\x66\x77"
++ "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+ .klen = 32,
+- .input = { 0x37, 0x52, 0x7b, 0xe0, 0x05, 0x23, 0x34, 0xb8,
+- 0x9f, 0x0c, 0xfc, 0xca, 0xe8, 0x7c, 0xfa, 0x20 },
++ .input = "\x37\x52\x7b\xe0\x05\x23\x34\xb8"
++ "\x9f\x0c\xfc\xca\xe8\x7c\xfa\x20",
+ .ilen = 16,
+- .result = { [0 ... 15] = 0x00 },
++ .result = zeroed_string,
+ .rlen = 16,
+ },
+ };
+
+ static struct cipher_testvec tf_cbc_enc_tv_template[] = {
+ { /* Generated with Nettle */
+- .key = { [0 ... 15] = 0x00 },
++ .key = zeroed_string,
+ .klen = 16,
+- .iv = { [0 ... 15] = 0x00 },
+- .input = { [0 ... 15] = 0x00 },
++ .iv = zeroed_string,
++ .input = zeroed_string,
+ .ilen = 16,
+- .result = { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
+- 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
++ .result = "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32"
++ "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a",
+ .rlen = 16,
+ }, {
+- .key = { [0 ... 15] = 0x00 },
++ .key = zeroed_string,
+ .klen = 16,
+- .iv = { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
+- 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
+- .input = { [0 ... 15] = 0x00 },
++ .iv = "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32"
++ "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a",
++ .input = zeroed_string,
+ .ilen = 16,
+- .result = { 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
+- 0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 },
++ .result = "\xd4\x91\xdb\x16\xe7\xb1\xc3\x9e"
++ "\x86\xcb\x08\x6b\x78\x9f\x54\x19",
+ .rlen = 16,
+ }, {
+- .key = { [0 ... 15] = 0x00 },
++ .key = zeroed_string,
+ .klen = 16,
+- .iv = { 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
+- 0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 },
+- .input = { [0 ... 15] = 0x00 },
++ .iv = "\xd4\x91\xdb\x16\xe7\xb1\xc3\x9e"
++ "\x86\xcb\x08\x6b\x78\x9f\x54\x19",
++ .input = zeroed_string,
+ .ilen = 16,
+- .result = { 0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26,
+- 0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 },
++ .result = "\x05\xef\x8c\x61\xa8\x11\x58\x26"
++ "\x34\xba\x5c\xb7\x10\x6a\xa6\x41",
+ .rlen = 16,
+ }, {
+- .key = { [0 ... 15] = 0x00 },
++ .key = zeroed_string,
+ .klen = 16,
+- .iv = { [0 ... 15] = 0x00 },
+- .input = { [0 ... 47] = 0x00 },
++ .iv = zeroed_string,
++ .input = zeroed_string,
+ .ilen = 48,
+- .result = { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
+- 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a,
+- 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
+- 0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19,
+- 0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26,
+- 0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 },
++ .result = "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32"
++ "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a"
++ "\xd4\x91\xdb\x16\xe7\xb1\xc3\x9e"
++ "\x86\xcb\x08\x6b\x78\x9f\x54\x19"
++ "\x05\xef\x8c\x61\xa8\x11\x58\x26"
++ "\x34\xba\x5c\xb7\x10\x6a\xa6\x41",
+ .rlen = 48,
+ },
+ };
+
+ static struct cipher_testvec tf_cbc_dec_tv_template[] = {
+ { /* Reverse of the first four above */
+- .key = { [0 ... 15] = 0x00 },
++ .key = zeroed_string,
+ .klen = 16,
+- .iv = { [0 ... 15] = 0x00 },
+- .input = { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
+- 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
++ .iv = zeroed_string,
++ .input = "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32"
++ "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a",
+ .ilen = 16,
+- .result = { [0 ... 15] = 0x00 },
++ .result = zeroed_string,
+ .rlen = 16,
+ }, {
+- .key = { [0 ... 15] = 0x00 },
++ .key = zeroed_string,
+ .klen = 16,
+- .iv = { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
+- 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
+- .input = { 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
+- 0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 },
++ .iv = "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32"
++ "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a",
++ .input = "\xd4\x91\xdb\x16\xe7\xb1\xc3\x9e"
++ "\x86\xcb\x08\x6b\x78\x9f\x54\x19",
+ .ilen = 16,
+- .result = { [0 ... 15] = 0x00 },
++ .result = zeroed_string,
+ .rlen = 16,
+ }, {
+- .key = { [0 ... 15] = 0x00 },
++ .key = zeroed_string,
+ .klen = 16,
+- .iv = { 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
+- 0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19 },
+- .input = { 0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26,
+- 0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 },
++ .iv = "\xd4\x91\xdb\x16\xe7\xb1\xc3\x9e"
++ "\x86\xcb\x08\x6b\x78\x9f\x54\x19",
++ .input = "\x05\xef\x8c\x61\xa8\x11\x58\x26"
++ "\x34\xba\x5c\xb7\x10\x6a\xa6\x41",
+ .ilen = 16,
+- .result = { [0 ... 15] = 0x00 },
++ .result = zeroed_string,
+ .rlen = 16,
+ }, {
+- .key = { [0 ... 15] = 0x00 },
++ .key = zeroed_string,
+ .klen = 16,
+- .iv = { [0 ... 15] = 0x00 },
+- .input = { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
+- 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a,
+- 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
+- 0x86, 0xcb, 0x08, 0x6b, 0x78, 0x9f, 0x54, 0x19,
+- 0x05, 0xef, 0x8c, 0x61, 0xa8, 0x11, 0x58, 0x26,
+- 0x34, 0xba, 0x5c, 0xb7, 0x10, 0x6a, 0xa6, 0x41 },
++ .iv = zeroed_string,
++ .input = "\x9f\x58\x9f\x5c\xf6\x12\x2c\x32"
++ "\xb6\xbf\xec\x2f\x2a\xe8\xc3\x5a"
++ "\xd4\x91\xdb\x16\xe7\xb1\xc3\x9e"
++ "\x86\xcb\x08\x6b\x78\x9f\x54\x19"
++ "\x05\xef\x8c\x61\xa8\x11\x58\x26"
++ "\x34\xba\x5c\xb7\x10\x6a\xa6\x41",
+ .ilen = 48,
+- .result = { [0 ... 47] = 0x00 },
++ .result = zeroed_string,
+ .rlen = 48,
+ },
+ };
+@@ -2053,90 +2079,90 @@ static struct cipher_testvec tf_cbc_dec_tv_template[] = {
+
+ static struct cipher_testvec serpent_enc_tv_template[] = {
+ {
+- .input = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++ .input = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .ilen = 16,
+- .result = { 0x12, 0x07, 0xfc, 0xce, 0x9b, 0xd0, 0xd6, 0x47,
+- 0x6a, 0xe9, 0x8f, 0xbe, 0xd1, 0x43, 0xa0, 0xe2 },
++ .result = "\x12\x07\xfc\xce\x9b\xd0\xd6\x47"
++ "\x6a\xe9\x8f\xbe\xd1\x43\xa0\xe2",
+ .rlen = 16,
+ }, {
+- .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .klen = 16,
+- .input = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++ .input = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .ilen = 16,
+- .result = { 0x4c, 0x7d, 0x8a, 0x32, 0x80, 0x72, 0xa2, 0x2c,
+- 0x82, 0x3e, 0x4a, 0x1f, 0x3a, 0xcd, 0xa1, 0x6d },
++ .result = "\x4c\x7d\x8a\x32\x80\x72\xa2\x2c"
++ "\x82\x3e\x4a\x1f\x3a\xcd\xa1\x6d",
+ .rlen = 16,
+ }, {
+- .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ .klen = 32,
+- .input = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++ .input = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .ilen = 16,
+- .result = { 0xde, 0x26, 0x9f, 0xf8, 0x33, 0xe4, 0x32, 0xb8,
+- 0x5b, 0x2e, 0x88, 0xd2, 0x70, 0x1c, 0xe7, 0x5c },
++ .result = "\xde\x26\x9f\xf8\x33\xe4\x32\xb8"
++ "\x5b\x2e\x88\xd2\x70\x1c\xe7\x5c",
+ .rlen = 16,
+ }, {
+- .key = { [15] = 0x80 },
++ .key = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80",
+ .klen = 16,
+- .input = { [0 ... 15] = 0x00 },
++ .input = zeroed_string,
+ .ilen = 16,
+- .result = { 0xdd, 0xd2, 0x6b, 0x98, 0xa5, 0xff, 0xd8, 0x2c,
+- 0x05, 0x34, 0x5a, 0x9d, 0xad, 0xbf, 0xaf, 0x49},
++ .result = "\xdd\xd2\x6b\x98\xa5\xff\xd8\x2c"
++ "\x05\x34\x5a\x9d\xad\xbf\xaf\x49",
+ .rlen = 16,
+ },
+ };
+
+ static struct cipher_testvec tnepres_enc_tv_template[] = {
+ { /* KeySize=128, PT=0, I=1 */
+- .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+- .key = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .input = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
++ .key = "\x80\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .klen = 16,
+ .ilen = 16,
+- .result = { 0x49, 0xaf, 0xbf, 0xad, 0x9d, 0x5a, 0x34, 0x05,
+- 0x2c, 0xd8, 0xff, 0xa5, 0x98, 0x6b, 0xd2, 0xdd },
++ .result = "\x49\xaf\xbf\xad\x9d\x5a\x34\x05"
++ "\x2c\xd8\xff\xa5\x98\x6b\xd2\xdd",
+ .rlen = 16,
+ }, { /* KeySize=192, PT=0, I=1 */
+- .key = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .key = "\x80\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .klen = 24,
+- .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .input = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .ilen = 16,
+- .result = { 0xe7, 0x8e, 0x54, 0x02, 0xc7, 0x19, 0x55, 0x68,
+- 0xac, 0x36, 0x78, 0xf7, 0xa3, 0xf6, 0x0c, 0x66 },
++ .result = "\xe7\x8e\x54\x02\xc7\x19\x55\x68"
++ "\xac\x36\x78\xf7\xa3\xf6\x0c\x66",
+ .rlen = 16,
+ }, { /* KeySize=256, PT=0, I=1 */
+- .key = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .key = "\x80\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .klen = 32,
+- .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .input = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .ilen = 16,
+- .result = { 0xab, 0xed, 0x96, 0xe7, 0x66, 0xbf, 0x28, 0xcb,
+- 0xc0, 0xeb, 0xd2, 0x1a, 0x82, 0xef, 0x08, 0x19 },
++ .result = "\xab\xed\x96\xe7\x66\xbf\x28\xcb"
++ "\xc0\xeb\xd2\x1a\x82\xef\x08\x19",
+ .rlen = 16,
+ }, { /* KeySize=256, I=257 */
+- .key = { 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18,
+- 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10,
+- 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+- 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 },
++ .key = "\x1f\x1e\x1d\x1c\x1b\x1a\x19\x18"
++ "\x17\x16\x15\x14\x13\x12\x11\x10"
++ "\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08"
++ "\x07\x06\x05\x04\x03\x02\x01\x00",
+ .klen = 32,
+- .input = { 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+- 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 },
++ .input = "\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08"
++ "\x07\x06\x05\x04\x03\x02\x01\x00",
+ .ilen = 16,
+- .result = { 0x5c, 0xe7, 0x1c, 0x70, 0xd2, 0x88, 0x2e, 0x5b,
+- 0xb8, 0x32, 0xe4, 0x33, 0xf8, 0x9f, 0x26, 0xde },
++ .result = "\x5c\xe7\x1c\x70\xd2\x88\x2e\x5b"
++ "\xb8\x32\xe4\x33\xf8\x9f\x26\xde",
+ .rlen = 16,
+ },
+ };
+@@ -2144,82 +2170,82 @@ static struct cipher_testvec tnepres_enc_tv_template[] = {
+
+ static struct cipher_testvec serpent_dec_tv_template[] = {
+ {
+- .input = { 0x12, 0x07, 0xfc, 0xce, 0x9b, 0xd0, 0xd6, 0x47,
+- 0x6a, 0xe9, 0x8f, 0xbe, 0xd1, 0x43, 0xa0, 0xe2 },
++ .input = "\x12\x07\xfc\xce\x9b\xd0\xd6\x47"
++ "\x6a\xe9\x8f\xbe\xd1\x43\xa0\xe2",
+ .ilen = 16,
+- .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++ .result = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .rlen = 16,
+ }, {
+- .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .klen = 16,
+- .input = { 0x4c, 0x7d, 0x8a, 0x32, 0x80, 0x72, 0xa2, 0x2c,
+- 0x82, 0x3e, 0x4a, 0x1f, 0x3a, 0xcd, 0xa1, 0x6d },
++ .input = "\x4c\x7d\x8a\x32\x80\x72\xa2\x2c"
++ "\x82\x3e\x4a\x1f\x3a\xcd\xa1\x6d",
+ .ilen = 16,
+- .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++ .result = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .rlen = 16,
+ }, {
+- .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ .klen = 32,
+- .input = { 0xde, 0x26, 0x9f, 0xf8, 0x33, 0xe4, 0x32, 0xb8,
+- 0x5b, 0x2e, 0x88, 0xd2, 0x70, 0x1c, 0xe7, 0x5c },
++ .input = "\xde\x26\x9f\xf8\x33\xe4\x32\xb8"
++ "\x5b\x2e\x88\xd2\x70\x1c\xe7\x5c",
+ .ilen = 16,
+- .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++ .result = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .rlen = 16,
+ }, {
+- .key = { [15] = 0x80 },
++ .key = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80",
+ .klen = 16,
+- .input = { 0xdd, 0xd2, 0x6b, 0x98, 0xa5, 0xff, 0xd8, 0x2c,
+- 0x05, 0x34, 0x5a, 0x9d, 0xad, 0xbf, 0xaf, 0x49},
++ .input = "\xdd\xd2\x6b\x98\xa5\xff\xd8\x2c"
++ "\x05\x34\x5a\x9d\xad\xbf\xaf\x49",
+ .ilen = 16,
+- .result = { [0 ... 15] = 0x00 },
++ .result = zeroed_string,
+ .rlen = 16,
+ },
+ };
+
+ static struct cipher_testvec tnepres_dec_tv_template[] = {
+ {
+- .input = { 0x41, 0xcc, 0x6b, 0x31, 0x59, 0x31, 0x45, 0x97,
+- 0x6d, 0x6f, 0xbb, 0x38, 0x4b, 0x37, 0x21, 0x28 },
++ .input = "\x41\xcc\x6b\x31\x59\x31\x45\x97"
++ "\x6d\x6f\xbb\x38\x4b\x37\x21\x28",
+ .ilen = 16,
+- .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++ .result = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .rlen = 16,
+ }, {
+- .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .klen = 16,
+- .input = { 0xea, 0xf4, 0xd7, 0xfc, 0xd8, 0x01, 0x34, 0x47,
+- 0x81, 0x45, 0x0b, 0xfa, 0x0c, 0xd6, 0xad, 0x6e },
++ .input = "\xea\xf4\xd7\xfc\xd8\x01\x34\x47"
++ "\x81\x45\x0b\xfa\x0c\xd6\xad\x6e",
+ .ilen = 16,
+- .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++ .result = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .rlen = 16,
+ }, {
+- .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ .klen = 32,
+- .input = { 0x64, 0xa9, 0x1a, 0x37, 0xed, 0x9f, 0xe7, 0x49,
+- 0xa8, 0x4e, 0x76, 0xd6, 0xf5, 0x0d, 0x78, 0xee },
++ .input = "\x64\xa9\x1a\x37\xed\x9f\xe7\x49"
++ "\xa8\x4e\x76\xd6\xf5\x0d\x78\xee",
+ .ilen = 16,
+- .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++ .result = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .rlen = 16,
+ }, { /* KeySize=128, I=121 */
+- .key = { [15] = 0x80 },
++ .key = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80",
+ .klen = 16,
+- .input = { 0x3d, 0xda, 0xbf, 0xc0, 0x06, 0xda, 0xab, 0x06,
+- 0x46, 0x2a, 0xf4, 0xef, 0x81, 0x54, 0x4e, 0x26 },
++ .input = "\x3d\xda\xbf\xc0\x06\xda\xab\x06"
++ "\x46\x2a\xf4\xef\x81\x54\x4e\x26",
+ .ilen = 16,
+- .result = { [0 ... 15] = 0x00 },
++ .result = zeroed_string,
+ .rlen = 16,
+ },
+ };
+@@ -2231,68 +2257,68 @@ static struct cipher_testvec tnepres_dec_tv_template[] = {
+
+ static struct cipher_testvec cast6_enc_tv_template[] = {
+ {
+- .key = { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
+- 0x0a, 0xf7, 0x56, 0x47, 0xf2, 0x9f, 0x61, 0x5d },
++ .key = "\x23\x42\xbb\x9e\xfa\x38\x54\x2c"
++ "\x0a\xf7\x56\x47\xf2\x9f\x61\x5d",
+ .klen = 16,
+- .input = { [0 ... 15] = 0x00 },
++ .input = zeroed_string,
+ .ilen = 16,
+- .result = { 0xc8, 0x42, 0xa0, 0x89, 0x72, 0xb4, 0x3d, 0x20,
+- 0x83, 0x6c, 0x91, 0xd1, 0xb7, 0x53, 0x0f, 0x6b },
++ .result = "\xc8\x42\xa0\x89\x72\xb4\x3d\x20"
++ "\x83\x6c\x91\xd1\xb7\x53\x0f\x6b",
+ .rlen = 16,
+ }, {
+- .key = { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
+- 0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98,
+- 0xba, 0xc7, 0x7a, 0x77, 0x17, 0x94, 0x28, 0x63 },
++ .key = "\x23\x42\xbb\x9e\xfa\x38\x54\x2c"
++ "\xbe\xd0\xac\x83\x94\x0a\xc2\x98"
++ "\xba\xc7\x7a\x77\x17\x94\x28\x63",
+ .klen = 24,
+- .input = { [0 ... 15] = 0x00 },
++ .input = zeroed_string,
+ .ilen = 16,
+- .result = { 0x1b, 0x38, 0x6c, 0x02, 0x10, 0xdc, 0xad, 0xcb,
+- 0xdd, 0x0e, 0x41, 0xaa, 0x08, 0xa7, 0xa7, 0xe8 },
++ .result = "\x1b\x38\x6c\x02\x10\xdc\xad\xcb"
++ "\xdd\x0e\x41\xaa\x08\xa7\xa7\xe8",
+ .rlen = 16,
+ }, {
+- .key = { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
+- 0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98,
+- 0x8d, 0x7c, 0x47, 0xce, 0x26, 0x49, 0x08, 0x46,
+- 0x1c, 0xc1, 0xb5, 0x13, 0x7a, 0xe6, 0xb6, 0x04 },
++ .key = "\x23\x42\xbb\x9e\xfa\x38\x54\x2c"
++ "\xbe\xd0\xac\x83\x94\x0a\xc2\x98"
++ "\x8d\x7c\x47\xce\x26\x49\x08\x46"
++ "\x1c\xc1\xb5\x13\x7a\xe6\xb6\x04",
+ .klen = 32,
+- .input = { [0 ... 15] = 0x00 },
++ .input = zeroed_string,
+ .ilen = 16,
+- .result = { 0x4f, 0x6a, 0x20, 0x38, 0x28, 0x68, 0x97, 0xb9,
+- 0xc9, 0x87, 0x01, 0x36, 0x55, 0x33, 0x17, 0xfa },
++ .result = "\x4f\x6a\x20\x38\x28\x68\x97\xb9"
++ "\xc9\x87\x01\x36\x55\x33\x17\xfa",
+ .rlen = 16,
+ },
+ };
+
+ static struct cipher_testvec cast6_dec_tv_template[] = {
+ {
+- .key = { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
+- 0x0a, 0xf7, 0x56, 0x47, 0xf2, 0x9f, 0x61, 0x5d },
++ .key = "\x23\x42\xbb\x9e\xfa\x38\x54\x2c"
++ "\x0a\xf7\x56\x47\xf2\x9f\x61\x5d",
+ .klen = 16,
+- .input = { 0xc8, 0x42, 0xa0, 0x89, 0x72, 0xb4, 0x3d, 0x20,
+- 0x83, 0x6c, 0x91, 0xd1, 0xb7, 0x53, 0x0f, 0x6b },
++ .input = "\xc8\x42\xa0\x89\x72\xb4\x3d\x20"
++ "\x83\x6c\x91\xd1\xb7\x53\x0f\x6b",
+ .ilen = 16,
+- .result = { [0 ... 15] = 0x00 },
++ .result = zeroed_string,
+ .rlen = 16,
+ }, {
+- .key = { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
+- 0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98,
+- 0xba, 0xc7, 0x7a, 0x77, 0x17, 0x94, 0x28, 0x63 },
++ .key = "\x23\x42\xbb\x9e\xfa\x38\x54\x2c"
++ "\xbe\xd0\xac\x83\x94\x0a\xc2\x98"
++ "\xba\xc7\x7a\x77\x17\x94\x28\x63",
+ .klen = 24,
+- .input = { 0x1b, 0x38, 0x6c, 0x02, 0x10, 0xdc, 0xad, 0xcb,
+- 0xdd, 0x0e, 0x41, 0xaa, 0x08, 0xa7, 0xa7, 0xe8 },
++ .input = "\x1b\x38\x6c\x02\x10\xdc\xad\xcb"
++ "\xdd\x0e\x41\xaa\x08\xa7\xa7\xe8",
+ .ilen = 16,
+- .result = { [0 ... 15] = 0x00 },
++ .result = zeroed_string,
+ .rlen = 16,
+ }, {
+- .key = { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
+- 0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98,
+- 0x8d, 0x7c, 0x47, 0xce, 0x26, 0x49, 0x08, 0x46,
+- 0x1c, 0xc1, 0xb5, 0x13, 0x7a, 0xe6, 0xb6, 0x04 },
++ .key = "\x23\x42\xbb\x9e\xfa\x38\x54\x2c"
++ "\xbe\xd0\xac\x83\x94\x0a\xc2\x98"
++ "\x8d\x7c\x47\xce\x26\x49\x08\x46"
++ "\x1c\xc1\xb5\x13\x7a\xe6\xb6\x04",
+ .klen = 32,
+- .input = { 0x4f, 0x6a, 0x20, 0x38, 0x28, 0x68, 0x97, 0xb9,
+- 0xc9, 0x87, 0x01, 0x36, 0x55, 0x33, 0x17, 0xfa },
++ .input = "\x4f\x6a\x20\x38\x28\x68\x97\xb9"
++ "\xc9\x87\x01\x36\x55\x33\x17\xfa",
+ .ilen = 16,
+- .result = { [0 ... 15] = 0x00 },
++ .result = zeroed_string,
+ .rlen = 16,
+ },
+ };
+@@ -2318,238 +2344,238 @@ static struct cipher_testvec cast6_dec_tv_template[] = {
+
+ static struct cipher_testvec aes_enc_tv_template[] = {
+ { /* From FIPS-197 */
+- .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .klen = 16,
+- .input = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+- 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
++ .input = "\x00\x11\x22\x33\x44\x55\x66\x77"
++ "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+ .ilen = 16,
+- .result = { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
+- 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a },
++ .result = "\x69\xc4\xe0\xd8\x6a\x7b\x04\x30"
++ "\xd8\xcd\xb7\x80\x70\xb4\xc5\x5a",
+ .rlen = 16,
+ }, {
+- .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
++ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17",
+ .klen = 24,
+- .input = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+- 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
++ .input = "\x00\x11\x22\x33\x44\x55\x66\x77"
++ "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+ .ilen = 16,
+- .result = { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
+- 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 },
++ .result = "\xdd\xa9\x7c\xa4\x86\x4c\xdf\xe0"
++ "\x6e\xaf\x70\xa0\xec\x0d\x71\x91",
+ .rlen = 16,
+ }, {
+- .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ .klen = 32,
+- .input = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+- 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
++ .input = "\x00\x11\x22\x33\x44\x55\x66\x77"
++ "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+ .ilen = 16,
+- .result = { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
+- 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 },
++ .result = "\x8e\xa2\xb7\xca\x51\x67\x45\xbf"
++ "\xea\xfc\x49\x90\x4b\x49\x60\x89",
+ .rlen = 16,
+ },
+ };
+
+ static struct cipher_testvec aes_dec_tv_template[] = {
+ { /* From FIPS-197 */
+- .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .klen = 16,
+- .input = { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
+- 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a },
++ .input = "\x69\xc4\xe0\xd8\x6a\x7b\x04\x30"
++ "\xd8\xcd\xb7\x80\x70\xb4\xc5\x5a",
+ .ilen = 16,
+- .result = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+- 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
++ .result = "\x00\x11\x22\x33\x44\x55\x66\x77"
++ "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+ .rlen = 16,
+ }, {
+- .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
++ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17",
+ .klen = 24,
+- .input = { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
+- 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 },
++ .input = "\xdd\xa9\x7c\xa4\x86\x4c\xdf\xe0"
++ "\x6e\xaf\x70\xa0\xec\x0d\x71\x91",
+ .ilen = 16,
+- .result = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+- 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
++ .result = "\x00\x11\x22\x33\x44\x55\x66\x77"
++ "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+ .rlen = 16,
+ }, {
+- .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ .klen = 32,
+- .input = { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
+- 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 },
++ .input = "\x8e\xa2\xb7\xca\x51\x67\x45\xbf"
++ "\xea\xfc\x49\x90\x4b\x49\x60\x89",
+ .ilen = 16,
+- .result = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+- 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
++ .result = "\x00\x11\x22\x33\x44\x55\x66\x77"
++ "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+ .rlen = 16,
+ },
+ };
+
+ static struct cipher_testvec aes_cbc_enc_tv_template[] = {
+ { /* From RFC 3602 */
+- .key = { 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b,
+- 0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 },
++ .key = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
++ "\x51\x2e\x03\xd5\x34\x12\x00\x06",
+ .klen = 16,
+- .iv = { 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30,
+- 0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 },
+- .input = { "Single block msg" },
++ .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
++ "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
++ .input = "Single block msg",
+ .ilen = 16,
+- .result = { 0xe3, 0x53, 0x77, 0x9c, 0x10, 0x79, 0xae, 0xb8,
+- 0x27, 0x08, 0x94, 0x2d, 0xbe, 0x77, 0x18, 0x1a },
++ .result = "\xe3\x53\x77\x9c\x10\x79\xae\xb8"
++ "\x27\x08\x94\x2d\xbe\x77\x18\x1a",
+ .rlen = 16,
+ }, {
+- .key = { 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0,
+- 0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a },
++ .key = "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0"
++ "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a",
+ .klen = 16,
+- .iv = { 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28,
+- 0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 },
+- .input = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++ .iv = "\x56\x2e\x17\x99\x6d\x09\x3d\x28"
++ "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58",
++ .input = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ .ilen = 32,
+- .result = { 0xd2, 0x96, 0xcd, 0x94, 0xc2, 0xcc, 0xcf, 0x8a,
+- 0x3a, 0x86, 0x30, 0x28, 0xb5, 0xe1, 0xdc, 0x0a,
+- 0x75, 0x86, 0x60, 0x2d, 0x25, 0x3c, 0xff, 0xf9,
+- 0x1b, 0x82, 0x66, 0xbe, 0xa6, 0xd6, 0x1a, 0xb1 },
++ .result = "\xd2\x96\xcd\x94\xc2\xcc\xcf\x8a"
++ "\x3a\x86\x30\x28\xb5\xe1\xdc\x0a"
++ "\x75\x86\x60\x2d\x25\x3c\xff\xf9"
++ "\x1b\x82\x66\xbe\xa6\xd6\x1a\xb1",
+ .rlen = 32,
+ }, { /* From NIST SP800-38A */
+- .key = { 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
+- 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
+- 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b },
++ .key = "\x8e\x73\xb0\xf7\xda\x0e\x64\x52"
++ "\xc8\x10\xf3\x2b\x80\x90\x79\xe5"
++ "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b",
+ .klen = 24,
+- .iv = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+- .input = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+- 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+- 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+- 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+- 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+- 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+- 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+- 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
++ .iv = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
++ .input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
++ "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
++ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
++ "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
++ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
++ "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
++ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
++ "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+ .ilen = 64,
+- .result = { 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d,
+- 0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8,
+- 0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d, 0xed, 0xf4,
+- 0xe5, 0xe7, 0x38, 0x76, 0x3f, 0x69, 0x14, 0x5a,
+- 0x57, 0x1b, 0x24, 0x20, 0x12, 0xfb, 0x7a, 0xe0,
+- 0x7f, 0xa9, 0xba, 0xac, 0x3d, 0xf1, 0x02, 0xe0,
+- 0x08, 0xb0, 0xe2, 0x79, 0x88, 0x59, 0x88, 0x81,
+- 0xd9, 0x20, 0xa9, 0xe6, 0x4f, 0x56, 0x15, 0xcd },
++ .result = "\x4f\x02\x1d\xb2\x43\xbc\x63\x3d"
++ "\x71\x78\x18\x3a\x9f\xa0\x71\xe8"
++ "\xb4\xd9\xad\xa9\xad\x7d\xed\xf4"
++ "\xe5\xe7\x38\x76\x3f\x69\x14\x5a"
++ "\x57\x1b\x24\x20\x12\xfb\x7a\xe0"
++ "\x7f\xa9\xba\xac\x3d\xf1\x02\xe0"
++ "\x08\xb0\xe2\x79\x88\x59\x88\x81"
++ "\xd9\x20\xa9\xe6\x4f\x56\x15\xcd",
+ .rlen = 64,
+ }, {
+- .key = { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
+- 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
+- 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
+- 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 },
++ .key = "\x60\x3d\xeb\x10\x15\xca\x71\xbe"
++ "\x2b\x73\xae\xf0\x85\x7d\x77\x81"
++ "\x1f\x35\x2c\x07\x3b\x61\x08\xd7"
++ "\x2d\x98\x10\xa3\x09\x14\xdf\xf4",
+ .klen = 32,
+- .iv = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+- .input = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+- 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+- 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+- 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+- 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+- 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+- 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+- 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
++ .iv = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
++ .input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
++ "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
++ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
++ "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
++ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
++ "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
++ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
++ "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+ .ilen = 64,
+- .result = { 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba,
+- 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6,
+- 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d,
+- 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d,
+- 0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf,
+- 0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61,
+- 0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc,
+- 0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b },
++ .result = "\xf5\x8c\x4c\x04\xd6\xe5\xf1\xba"
++ "\x77\x9e\xab\xfb\x5f\x7b\xfb\xd6"
++ "\x9c\xfc\x4e\x96\x7e\xdb\x80\x8d"
++ "\x67\x9f\x77\x7b\xc6\x70\x2c\x7d"
++ "\x39\xf2\x33\x69\xa9\xd9\xba\xcf"
++ "\xa5\x30\xe2\x63\x04\x23\x14\x61"
++ "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc"
++ "\xda\x6c\x19\x07\x8c\x6a\x9d\x1b",
+ .rlen = 64,
+ },
+ };
+
+ static struct cipher_testvec aes_cbc_dec_tv_template[] = {
+ { /* From RFC 3602 */
+- .key = { 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b,
+- 0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 },
++ .key = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
++ "\x51\x2e\x03\xd5\x34\x12\x00\x06",
+ .klen = 16,
+- .iv = { 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30,
+- 0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 },
+- .input = { 0xe3, 0x53, 0x77, 0x9c, 0x10, 0x79, 0xae, 0xb8,
+- 0x27, 0x08, 0x94, 0x2d, 0xbe, 0x77, 0x18, 0x1a },
++ .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
++ "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
++ .input = "\xe3\x53\x77\x9c\x10\x79\xae\xb8"
++ "\x27\x08\x94\x2d\xbe\x77\x18\x1a",
+ .ilen = 16,
+- .result = { "Single block msg" },
++ .result = "Single block msg",
+ .rlen = 16,
+ }, {
+- .key = { 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0,
+- 0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a },
++ .key = "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0"
++ "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a",
+ .klen = 16,
+- .iv = { 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28,
+- 0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 },
+- .input = { 0xd2, 0x96, 0xcd, 0x94, 0xc2, 0xcc, 0xcf, 0x8a,
+- 0x3a, 0x86, 0x30, 0x28, 0xb5, 0xe1, 0xdc, 0x0a,
+- 0x75, 0x86, 0x60, 0x2d, 0x25, 0x3c, 0xff, 0xf9,
+- 0x1b, 0x82, 0x66, 0xbe, 0xa6, 0xd6, 0x1a, 0xb1 },
++ .iv = "\x56\x2e\x17\x99\x6d\x09\x3d\x28"
++ "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58",
++ .input = "\xd2\x96\xcd\x94\xc2\xcc\xcf\x8a"
++ "\x3a\x86\x30\x28\xb5\xe1\xdc\x0a"
++ "\x75\x86\x60\x2d\x25\x3c\xff\xf9"
++ "\x1b\x82\x66\xbe\xa6\xd6\x1a\xb1",
+ .ilen = 32,
+- .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++ .result = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ .rlen = 32,
+ }, { /* From NIST SP800-38A */
+- .key = { 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
+- 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
+- 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b },
++ .key = "\x8e\x73\xb0\xf7\xda\x0e\x64\x52"
++ "\xc8\x10\xf3\x2b\x80\x90\x79\xe5"
++ "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b",
+ .klen = 24,
+- .iv = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+- .input = { 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d,
+- 0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8,
+- 0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d, 0xed, 0xf4,
+- 0xe5, 0xe7, 0x38, 0x76, 0x3f, 0x69, 0x14, 0x5a,
+- 0x57, 0x1b, 0x24, 0x20, 0x12, 0xfb, 0x7a, 0xe0,
+- 0x7f, 0xa9, 0xba, 0xac, 0x3d, 0xf1, 0x02, 0xe0,
+- 0x08, 0xb0, 0xe2, 0x79, 0x88, 0x59, 0x88, 0x81,
+- 0xd9, 0x20, 0xa9, 0xe6, 0x4f, 0x56, 0x15, 0xcd },
++ .iv = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
++ .input = "\x4f\x02\x1d\xb2\x43\xbc\x63\x3d"
++ "\x71\x78\x18\x3a\x9f\xa0\x71\xe8"
++ "\xb4\xd9\xad\xa9\xad\x7d\xed\xf4"
++ "\xe5\xe7\x38\x76\x3f\x69\x14\x5a"
++ "\x57\x1b\x24\x20\x12\xfb\x7a\xe0"
++ "\x7f\xa9\xba\xac\x3d\xf1\x02\xe0"
++ "\x08\xb0\xe2\x79\x88\x59\x88\x81"
++ "\xd9\x20\xa9\xe6\x4f\x56\x15\xcd",
+ .ilen = 64,
+- .result = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+- 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+- 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+- 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+- 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+- 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+- 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+- 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
++ .result = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
++ "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
++ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
++ "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
++ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
++ "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
++ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
++ "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+ .rlen = 64,
+ }, {
+- .key = { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
+- 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
+- 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
+- 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 },
++ .key = "\x60\x3d\xeb\x10\x15\xca\x71\xbe"
++ "\x2b\x73\xae\xf0\x85\x7d\x77\x81"
++ "\x1f\x35\x2c\x07\x3b\x61\x08\xd7"
++ "\x2d\x98\x10\xa3\x09\x14\xdf\xf4",
+ .klen = 32,
+- .iv = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+- .input = { 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba,
+- 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6,
+- 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d,
+- 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d,
+- 0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf,
+- 0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61,
+- 0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc,
+- 0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b },
++ .iv = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
++ .input = "\xf5\x8c\x4c\x04\xd6\xe5\xf1\xba"
++ "\x77\x9e\xab\xfb\x5f\x7b\xfb\xd6"
++ "\x9c\xfc\x4e\x96\x7e\xdb\x80\x8d"
++ "\x67\x9f\x77\x7b\xc6\x70\x2c\x7d"
++ "\x39\xf2\x33\x69\xa9\xd9\xba\xcf"
++ "\xa5\x30\xe2\x63\x04\x23\x14\x61"
++ "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc"
++ "\xda\x6c\x19\x07\x8c\x6a\x9d\x1b",
+ .ilen = 64,
+- .result = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+- 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+- 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+- 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+- 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+- 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+- 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+- 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
++ .result = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
++ "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
++ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
++ "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
++ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
++ "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
++ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
++ "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+ .rlen = 64,
+ },
+ };
+@@ -2557,250 +2583,249 @@ static struct cipher_testvec aes_cbc_dec_tv_template[] = {
+ static struct cipher_testvec aes_lrw_enc_tv_template[] = {
+ /* from http://grouper.ieee.org/groups/1619/email/pdf00017.pdf */
+ { /* LRW-32-AES 1 */
+- .key = { 0x45, 0x62, 0xac, 0x25, 0xf8, 0x28, 0x17, 0x6d,
+- 0x4c, 0x26, 0x84, 0x14, 0xb5, 0x68, 0x01, 0x85,
+- 0x25, 0x8e, 0x2a, 0x05, 0xe7, 0x3e, 0x9d, 0x03,
+- 0xee, 0x5a, 0x83, 0x0c, 0xcc, 0x09, 0x4c, 0x87 },
++ .key = "\x45\x62\xac\x25\xf8\x28\x17\x6d"
++ "\x4c\x26\x84\x14\xb5\x68\x01\x85"
++ "\x25\x8e\x2a\x05\xe7\x3e\x9d\x03"
++ "\xee\x5a\x83\x0c\xcc\x09\x4c\x87",
+ .klen = 32,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+- .input = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+- 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x01",
++ .input = "\x30\x31\x32\x33\x34\x35\x36\x37"
++ "\x38\x39\x41\x42\x43\x44\x45\x46",
+ .ilen = 16,
+- .result = { 0xf1, 0xb2, 0x73, 0xcd, 0x65, 0xa3, 0xdf, 0x5f,
+- 0xe9, 0x5d, 0x48, 0x92, 0x54, 0x63, 0x4e, 0xb8 },
++ .result = "\xf1\xb2\x73\xcd\x65\xa3\xdf\x5f"
++ "\xe9\x5d\x48\x92\x54\x63\x4e\xb8",
+ .rlen = 16,
+ }, { /* LRW-32-AES 2 */
+- .key = { 0x59, 0x70, 0x47, 0x14, 0xf5, 0x57, 0x47, 0x8c,
+- 0xd7, 0x79, 0xe8, 0x0f, 0x54, 0x88, 0x79, 0x44,
+- 0x0d, 0x48, 0xf0, 0xb7, 0xb1, 0x5a, 0x53, 0xea,
+- 0x1c, 0xaa, 0x6b, 0x29, 0xc2, 0xca, 0xfb, 0xaf
+- },
++ .key = "\x59\x70\x47\x14\xf5\x57\x47\x8c"
++ "\xd7\x79\xe8\x0f\x54\x88\x79\x44"
++ "\x0d\x48\xf0\xb7\xb1\x5a\x53\xea"
++ "\x1c\xaa\x6b\x29\xc2\xca\xfb\xaf",
+ .klen = 32,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
+- .input = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+- 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x02",
++ .input = "\x30\x31\x32\x33\x34\x35\x36\x37"
++ "\x38\x39\x41\x42\x43\x44\x45\x46",
+ .ilen = 16,
+- .result = { 0x00, 0xc8, 0x2b, 0xae, 0x95, 0xbb, 0xcd, 0xe5,
+- 0x27, 0x4f, 0x07, 0x69, 0xb2, 0x60, 0xe1, 0x36 },
++ .result = "\x00\xc8\x2b\xae\x95\xbb\xcd\xe5"
++ "\x27\x4f\x07\x69\xb2\x60\xe1\x36",
+ .rlen = 16,
+ }, { /* LRW-32-AES 3 */
+- .key = { 0xd8, 0x2a, 0x91, 0x34, 0xb2, 0x6a, 0x56, 0x50,
+- 0x30, 0xfe, 0x69, 0xe2, 0x37, 0x7f, 0x98, 0x47,
+- 0xcd, 0xf9, 0x0b, 0x16, 0x0c, 0x64, 0x8f, 0xb6,
+- 0xb0, 0x0d, 0x0d, 0x1b, 0xae, 0x85, 0x87, 0x1f },
++ .key = "\xd8\x2a\x91\x34\xb2\x6a\x56\x50"
++ "\x30\xfe\x69\xe2\x37\x7f\x98\x47"
++ "\xcd\xf9\x0b\x16\x0c\x64\x8f\xb6"
++ "\xb0\x0d\x0d\x1b\xae\x85\x87\x1f",
+ .klen = 32,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+- .input = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+- 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x02\x00\x00\x00\x00",
++ .input = "\x30\x31\x32\x33\x34\x35\x36\x37"
++ "\x38\x39\x41\x42\x43\x44\x45\x46",
+ .ilen = 16,
+- .result = { 0x76, 0x32, 0x21, 0x83, 0xed, 0x8f, 0xf1, 0x82,
+- 0xf9, 0x59, 0x62, 0x03, 0x69, 0x0e, 0x5e, 0x01 },
++ .result = "\x76\x32\x21\x83\xed\x8f\xf1\x82"
++ "\xf9\x59\x62\x03\x69\x0e\x5e\x01",
+ .rlen = 16,
+ }, { /* LRW-32-AES 4 */
+- .key = { 0x0f, 0x6a, 0xef, 0xf8, 0xd3, 0xd2, 0xbb, 0x15,
+- 0x25, 0x83, 0xf7, 0x3c, 0x1f, 0x01, 0x28, 0x74,
+- 0xca, 0xc6, 0xbc, 0x35, 0x4d, 0x4a, 0x65, 0x54,
+- 0x90, 0xae, 0x61, 0xcf, 0x7b, 0xae, 0xbd, 0xcc,
+- 0xad, 0xe4, 0x94, 0xc5, 0x4a, 0x29, 0xae, 0x70 },
++ .key = "\x0f\x6a\xef\xf8\xd3\xd2\xbb\x15"
++ "\x25\x83\xf7\x3c\x1f\x01\x28\x74"
++ "\xca\xc6\xbc\x35\x4d\x4a\x65\x54"
++ "\x90\xae\x61\xcf\x7b\xae\xbd\xcc"
++ "\xad\xe4\x94\xc5\x4a\x29\xae\x70",
+ .klen = 40,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+- .input = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+- 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x01",
++ .input = "\x30\x31\x32\x33\x34\x35\x36\x37"
++ "\x38\x39\x41\x42\x43\x44\x45\x46",
+ .ilen = 16,
+- .result = { 0x9c, 0x0f, 0x15, 0x2f, 0x55, 0xa2, 0xd8, 0xf0,
+- 0xd6, 0x7b, 0x8f, 0x9e, 0x28, 0x22, 0xbc, 0x41 },
++ .result = "\x9c\x0f\x15\x2f\x55\xa2\xd8\xf0"
++ "\xd6\x7b\x8f\x9e\x28\x22\xbc\x41",
+ .rlen = 16,
+ }, { /* LRW-32-AES 5 */
+- .key = { 0x8a, 0xd4, 0xee, 0x10, 0x2f, 0xbd, 0x81, 0xff,
+- 0xf8, 0x86, 0xce, 0xac, 0x93, 0xc5, 0xad, 0xc6,
+- 0xa0, 0x19, 0x07, 0xc0, 0x9d, 0xf7, 0xbb, 0xdd,
+- 0x52, 0x13, 0xb2, 0xb7, 0xf0, 0xff, 0x11, 0xd8,
+- 0xd6, 0x08, 0xd0, 0xcd, 0x2e, 0xb1, 0x17, 0x6f },
++ .key = "\x8a\xd4\xee\x10\x2f\xbd\x81\xff"
++ "\xf8\x86\xce\xac\x93\xc5\xad\xc6"
++ "\xa0\x19\x07\xc0\x9d\xf7\xbb\xdd"
++ "\x52\x13\xb2\xb7\xf0\xff\x11\xd8"
++ "\xd6\x08\xd0\xcd\x2e\xb1\x17\x6f",
+ .klen = 40,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+- .input = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+- 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x02\x00\x00\x00\x00",
++ .input = "\x30\x31\x32\x33\x34\x35\x36\x37"
++ "\x38\x39\x41\x42\x43\x44\x45\x46",
+ .ilen = 16,
+- .result = { 0xd4, 0x27, 0x6a, 0x7f, 0x14, 0x91, 0x3d, 0x65,
+- 0xc8, 0x60, 0x48, 0x02, 0x87, 0xe3, 0x34, 0x06 },
++ .result = "\xd4\x27\x6a\x7f\x14\x91\x3d\x65"
++ "\xc8\x60\x48\x02\x87\xe3\x34\x06",
+ .rlen = 16,
+ }, { /* LRW-32-AES 6 */
+- .key = { 0xf8, 0xd4, 0x76, 0xff, 0xd6, 0x46, 0xee, 0x6c,
+- 0x23, 0x84, 0xcb, 0x1c, 0x77, 0xd6, 0x19, 0x5d,
+- 0xfe, 0xf1, 0xa9, 0xf3, 0x7b, 0xbc, 0x8d, 0x21,
+- 0xa7, 0x9c, 0x21, 0xf8, 0xcb, 0x90, 0x02, 0x89,
+- 0xa8, 0x45, 0x34, 0x8e, 0xc8, 0xc5, 0xb5, 0xf1,
+- 0x26, 0xf5, 0x0e, 0x76, 0xfe, 0xfd, 0x1b, 0x1e },
++ .key = "\xf8\xd4\x76\xff\xd6\x46\xee\x6c"
++ "\x23\x84\xcb\x1c\x77\xd6\x19\x5d"
++ "\xfe\xf1\xa9\xf3\x7b\xbc\x8d\x21"
++ "\xa7\x9c\x21\xf8\xcb\x90\x02\x89"
++ "\xa8\x45\x34\x8e\xc8\xc5\xb5\xf1"
++ "\x26\xf5\x0e\x76\xfe\xfd\x1b\x1e",
+ .klen = 48,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+- .input = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+- 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x01",
++ .input = "\x30\x31\x32\x33\x34\x35\x36\x37"
++ "\x38\x39\x41\x42\x43\x44\x45\x46",
+ .ilen = 16,
+- .result = { 0xbd, 0x06, 0xb8, 0xe1, 0xdb, 0x98, 0x89, 0x9e,
+- 0xc4, 0x98, 0xe4, 0x91, 0xcf, 0x1c, 0x70, 0x2b },
++ .result = "\xbd\x06\xb8\xe1\xdb\x98\x89\x9e"
++ "\xc4\x98\xe4\x91\xcf\x1c\x70\x2b",
+ .rlen = 16,
+ }, { /* LRW-32-AES 7 */
+- .key = { 0xfb, 0x76, 0x15, 0xb2, 0x3d, 0x80, 0x89, 0x1d,
+- 0xd4, 0x70, 0x98, 0x0b, 0xc7, 0x95, 0x84, 0xc8,
+- 0xb2, 0xfb, 0x64, 0xce, 0x60, 0x97, 0x87, 0x8d,
+- 0x17, 0xfc, 0xe4, 0x5a, 0x49, 0xe8, 0x30, 0xb7,
+- 0x6e, 0x78, 0x17, 0xe7, 0x2d, 0x5e, 0x12, 0xd4,
+- 0x60, 0x64, 0x04, 0x7a, 0xf1, 0x2f, 0x9e, 0x0c },
++ .key = "\xfb\x76\x15\xb2\x3d\x80\x89\x1d"
++ "\xd4\x70\x98\x0b\xc7\x95\x84\xc8"
++ "\xb2\xfb\x64\xce\x60\x97\x87\x8d"
++ "\x17\xfc\xe4\x5a\x49\xe8\x30\xb7"
++ "\x6e\x78\x17\xe7\x2d\x5e\x12\xd4"
++ "\x60\x64\x04\x7a\xf1\x2f\x9e\x0c",
+ .klen = 48,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+- .input = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+- 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x02\x00\x00\x00\x00",
++ .input = "\x30\x31\x32\x33\x34\x35\x36\x37"
++ "\x38\x39\x41\x42\x43\x44\x45\x46",
+ .ilen = 16,
+- .result = { 0x5b, 0x90, 0x8e, 0xc1, 0xab, 0xdd, 0x67, 0x5f,
+- 0x3d, 0x69, 0x8a, 0x95, 0x53, 0xc8, 0x9c, 0xe5 },
++ .result = "\x5b\x90\x8e\xc1\xab\xdd\x67\x5f"
++ "\x3d\x69\x8a\x95\x53\xc8\x9c\xe5",
+ .rlen = 16,
+ }, {
+ /* http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00173.html */
+- .key = { 0xf8, 0xd4, 0x76, 0xff, 0xd6, 0x46, 0xee, 0x6c,
+- 0x23, 0x84, 0xcb, 0x1c, 0x77, 0xd6, 0x19, 0x5d,
+- 0xfe, 0xf1, 0xa9, 0xf3, 0x7b, 0xbc, 0x8d, 0x21,
+- 0xa7, 0x9c, 0x21, 0xf8, 0xcb, 0x90, 0x02, 0x89,
+- 0xa8, 0x45, 0x34, 0x8e, 0xc8, 0xc5, 0xb5, 0xf1,
+- 0x26, 0xf5, 0x0e, 0x76, 0xfe, 0xfd, 0x1b, 0x1e },
++ .key = "\xf8\xd4\x76\xff\xd6\x46\xee\x6c"
++ "\x23\x84\xcb\x1c\x77\xd6\x19\x5d"
++ "\xfe\xf1\xa9\xf3\x7b\xbc\x8d\x21"
++ "\xa7\x9c\x21\xf8\xcb\x90\x02\x89"
++ "\xa8\x45\x34\x8e\xc8\xc5\xb5\xf1"
++ "\x26\xf5\x0e\x76\xfe\xfd\x1b\x1e",
+ .klen = 48,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+- .input = { 0x05, 0x11, 0xb7, 0x18, 0xab, 0xc6, 0x2d, 0xac,
+- 0x70, 0x5d, 0xf6, 0x22, 0x94, 0xcd, 0xe5, 0x6c,
+- 0x17, 0x6b, 0xf6, 0x1c, 0xf0, 0xf3, 0x6e, 0xf8,
+- 0x50, 0x38, 0x1f, 0x71, 0x49, 0xb6, 0x57, 0xd6,
+- 0x8f, 0xcb, 0x8d, 0x6b, 0xe3, 0xa6, 0x29, 0x90,
+- 0xfe, 0x2a, 0x62, 0x82, 0xae, 0x6d, 0x8b, 0xf6,
+- 0xad, 0x1e, 0x9e, 0x20, 0x5f, 0x38, 0xbe, 0x04,
+- 0xda, 0x10, 0x8e, 0xed, 0xa2, 0xa4, 0x87, 0xab,
+- 0xda, 0x6b, 0xb4, 0x0c, 0x75, 0xba, 0xd3, 0x7c,
+- 0xc9, 0xac, 0x42, 0x31, 0x95, 0x7c, 0xc9, 0x04,
+- 0xeb, 0xd5, 0x6e, 0x32, 0x69, 0x8a, 0xdb, 0xa6,
+- 0x15, 0xd7, 0x3f, 0x4f, 0x2f, 0x66, 0x69, 0x03,
+- 0x9c, 0x1f, 0x54, 0x0f, 0xde, 0x1f, 0xf3, 0x65,
+- 0x4c, 0x96, 0x12, 0xed, 0x7c, 0x92, 0x03, 0x01,
+- 0x6f, 0xbc, 0x35, 0x93, 0xac, 0xf1, 0x27, 0xf1,
+- 0xb4, 0x96, 0x82, 0x5a, 0x5f, 0xb0, 0xa0, 0x50,
+- 0x89, 0xa4, 0x8e, 0x66, 0x44, 0x85, 0xcc, 0xfd,
+- 0x33, 0x14, 0x70, 0xe3, 0x96, 0xb2, 0xc3, 0xd3,
+- 0xbb, 0x54, 0x5a, 0x1a, 0xf9, 0x74, 0xa2, 0xc5,
+- 0x2d, 0x64, 0x75, 0xdd, 0xb4, 0x54, 0xe6, 0x74,
+- 0x8c, 0xd3, 0x9d, 0x9e, 0x86, 0xab, 0x51, 0x53,
+- 0xb7, 0x93, 0x3e, 0x6f, 0xd0, 0x4e, 0x2c, 0x40,
+- 0xf6, 0xa8, 0x2e, 0x3e, 0x9d, 0xf4, 0x66, 0xa5,
+- 0x76, 0x12, 0x73, 0x44, 0x1a, 0x56, 0xd7, 0x72,
+- 0x88, 0xcd, 0x21, 0x8c, 0x4c, 0x0f, 0xfe, 0xda,
+- 0x95, 0xe0, 0x3a, 0xa6, 0xa5, 0x84, 0x46, 0xcd,
+- 0xd5, 0x3e, 0x9d, 0x3a, 0xe2, 0x67, 0xe6, 0x60,
+- 0x1a, 0xe2, 0x70, 0x85, 0x58, 0xc2, 0x1b, 0x09,
+- 0xe1, 0xd7, 0x2c, 0xca, 0xad, 0xa8, 0x8f, 0xf9,
+- 0xac, 0xb3, 0x0e, 0xdb, 0xca, 0x2e, 0xe2, 0xb8,
+- 0x51, 0x71, 0xd9, 0x3c, 0x6c, 0xf1, 0x56, 0xf8,
+- 0xea, 0x9c, 0xf1, 0xfb, 0x0c, 0xe6, 0xb7, 0x10,
+- 0x1c, 0xf8, 0xa9, 0x7c, 0xe8, 0x53, 0x35, 0xc1,
+- 0x90, 0x3e, 0x76, 0x4a, 0x74, 0xa4, 0x21, 0x2c,
+- 0xf6, 0x2c, 0x4e, 0x0f, 0x94, 0x3a, 0x88, 0x2e,
+- 0x41, 0x09, 0x6a, 0x33, 0x7d, 0xf6, 0xdd, 0x3f,
+- 0x8d, 0x23, 0x31, 0x74, 0x84, 0xeb, 0x88, 0x6e,
+- 0xcc, 0xb9, 0xbc, 0x22, 0x83, 0x19, 0x07, 0x22,
+- 0xa5, 0x2d, 0xdf, 0xa5, 0xf3, 0x80, 0x85, 0x78,
+- 0x84, 0x39, 0x6a, 0x6d, 0x6a, 0x99, 0x4f, 0xa5,
+- 0x15, 0xfe, 0x46, 0xb0, 0xe4, 0x6c, 0xa5, 0x41,
+- 0x3c, 0xce, 0x8f, 0x42, 0x60, 0x71, 0xa7, 0x75,
+- 0x08, 0x40, 0x65, 0x8a, 0x82, 0xbf, 0xf5, 0x43,
+- 0x71, 0x96, 0xa9, 0x4d, 0x44, 0x8a, 0x20, 0xbe,
+- 0xfa, 0x4d, 0xbb, 0xc0, 0x7d, 0x31, 0x96, 0x65,
+- 0xe7, 0x75, 0xe5, 0x3e, 0xfd, 0x92, 0x3b, 0xc9,
+- 0x55, 0xbb, 0x16, 0x7e, 0xf7, 0xc2, 0x8c, 0xa4,
+- 0x40, 0x1d, 0xe5, 0xef, 0x0e, 0xdf, 0xe4, 0x9a,
+- 0x62, 0x73, 0x65, 0xfd, 0x46, 0x63, 0x25, 0x3d,
+- 0x2b, 0xaf, 0xe5, 0x64, 0xfe, 0xa5, 0x5c, 0xcf,
+- 0x24, 0xf3, 0xb4, 0xac, 0x64, 0xba, 0xdf, 0x4b,
+- 0xc6, 0x96, 0x7d, 0x81, 0x2d, 0x8d, 0x97, 0xf7,
+- 0xc5, 0x68, 0x77, 0x84, 0x32, 0x2b, 0xcc, 0x85,
+- 0x74, 0x96, 0xf0, 0x12, 0x77, 0x61, 0xb9, 0xeb,
+- 0x71, 0xaa, 0x82, 0xcb, 0x1c, 0xdb, 0x89, 0xc8,
+- 0xc6, 0xb5, 0xe3, 0x5c, 0x7d, 0x39, 0x07, 0x24,
+- 0xda, 0x39, 0x87, 0x45, 0xc0, 0x2b, 0xbb, 0x01,
+- 0xac, 0xbc, 0x2a, 0x5c, 0x7f, 0xfc, 0xe8, 0xce,
+- 0x6d, 0x9c, 0x6f, 0xed, 0xd3, 0xc1, 0xa1, 0xd6,
+- 0xc5, 0x55, 0xa9, 0x66, 0x2f, 0xe1, 0xc8, 0x32,
+- 0xa6, 0x5d, 0xa4, 0x3a, 0x98, 0x73, 0xe8, 0x45,
+- 0xa4, 0xc7, 0xa8, 0xb4, 0xf6, 0x13, 0x03, 0xf6,
+- 0xe9, 0x2e, 0xc4, 0x29, 0x0f, 0x84, 0xdb, 0xc4,
+- 0x21, 0xc4, 0xc2, 0x75, 0x67, 0x89, 0x37, 0x0a },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x01",
++ .input = "\x05\x11\xb7\x18\xab\xc6\x2d\xac"
++ "\x70\x5d\xf6\x22\x94\xcd\xe5\x6c"
++ "\x17\x6b\xf6\x1c\xf0\xf3\x6e\xf8"
++ "\x50\x38\x1f\x71\x49\xb6\x57\xd6"
++ "\x8f\xcb\x8d\x6b\xe3\xa6\x29\x90"
++ "\xfe\x2a\x62\x82\xae\x6d\x8b\xf6"
++ "\xad\x1e\x9e\x20\x5f\x38\xbe\x04"
++ "\xda\x10\x8e\xed\xa2\xa4\x87\xab"
++ "\xda\x6b\xb4\x0c\x75\xba\xd3\x7c"
++ "\xc9\xac\x42\x31\x95\x7c\xc9\x04"
++ "\xeb\xd5\x6e\x32\x69\x8a\xdb\xa6"
++ "\x15\xd7\x3f\x4f\x2f\x66\x69\x03"
++ "\x9c\x1f\x54\x0f\xde\x1f\xf3\x65"
++ "\x4c\x96\x12\xed\x7c\x92\x03\x01"
++ "\x6f\xbc\x35\x93\xac\xf1\x27\xf1"
++ "\xb4\x96\x82\x5a\x5f\xb0\xa0\x50"
++ "\x89\xa4\x8e\x66\x44\x85\xcc\xfd"
++ "\x33\x14\x70\xe3\x96\xb2\xc3\xd3"
++ "\xbb\x54\x5a\x1a\xf9\x74\xa2\xc5"
++ "\x2d\x64\x75\xdd\xb4\x54\xe6\x74"
++ "\x8c\xd3\x9d\x9e\x86\xab\x51\x53"
++ "\xb7\x93\x3e\x6f\xd0\x4e\x2c\x40"
++ "\xf6\xa8\x2e\x3e\x9d\xf4\x66\xa5"
++ "\x76\x12\x73\x44\x1a\x56\xd7\x72"
++ "\x88\xcd\x21\x8c\x4c\x0f\xfe\xda"
++ "\x95\xe0\x3a\xa6\xa5\x84\x46\xcd"
++ "\xd5\x3e\x9d\x3a\xe2\x67\xe6\x60"
++ "\x1a\xe2\x70\x85\x58\xc2\x1b\x09"
++ "\xe1\xd7\x2c\xca\xad\xa8\x8f\xf9"
++ "\xac\xb3\x0e\xdb\xca\x2e\xe2\xb8"
++ "\x51\x71\xd9\x3c\x6c\xf1\x56\xf8"
++ "\xea\x9c\xf1\xfb\x0c\xe6\xb7\x10"
++ "\x1c\xf8\xa9\x7c\xe8\x53\x35\xc1"
++ "\x90\x3e\x76\x4a\x74\xa4\x21\x2c"
++ "\xf6\x2c\x4e\x0f\x94\x3a\x88\x2e"
++ "\x41\x09\x6a\x33\x7d\xf6\xdd\x3f"
++ "\x8d\x23\x31\x74\x84\xeb\x88\x6e"
++ "\xcc\xb9\xbc\x22\x83\x19\x07\x22"
++ "\xa5\x2d\xdf\xa5\xf3\x80\x85\x78"
++ "\x84\x39\x6a\x6d\x6a\x99\x4f\xa5"
++ "\x15\xfe\x46\xb0\xe4\x6c\xa5\x41"
++ "\x3c\xce\x8f\x42\x60\x71\xa7\x75"
++ "\x08\x40\x65\x8a\x82\xbf\xf5\x43"
++ "\x71\x96\xa9\x4d\x44\x8a\x20\xbe"
++ "\xfa\x4d\xbb\xc0\x7d\x31\x96\x65"
++ "\xe7\x75\xe5\x3e\xfd\x92\x3b\xc9"
++ "\x55\xbb\x16\x7e\xf7\xc2\x8c\xa4"
++ "\x40\x1d\xe5\xef\x0e\xdf\xe4\x9a"
++ "\x62\x73\x65\xfd\x46\x63\x25\x3d"
++ "\x2b\xaf\xe5\x64\xfe\xa5\x5c\xcf"
++ "\x24\xf3\xb4\xac\x64\xba\xdf\x4b"
++ "\xc6\x96\x7d\x81\x2d\x8d\x97\xf7"
++ "\xc5\x68\x77\x84\x32\x2b\xcc\x85"
++ "\x74\x96\xf0\x12\x77\x61\xb9\xeb"
++ "\x71\xaa\x82\xcb\x1c\xdb\x89\xc8"
++ "\xc6\xb5\xe3\x5c\x7d\x39\x07\x24"
++ "\xda\x39\x87\x45\xc0\x2b\xbb\x01"
++ "\xac\xbc\x2a\x5c\x7f\xfc\xe8\xce"
++ "\x6d\x9c\x6f\xed\xd3\xc1\xa1\xd6"
++ "\xc5\x55\xa9\x66\x2f\xe1\xc8\x32"
++ "\xa6\x5d\xa4\x3a\x98\x73\xe8\x45"
++ "\xa4\xc7\xa8\xb4\xf6\x13\x03\xf6"
++ "\xe9\x2e\xc4\x29\x0f\x84\xdb\xc4"
++ "\x21\xc4\xc2\x75\x67\x89\x37\x0a",
+ .ilen = 512,
+- .result = { 0x1a, 0x1d, 0xa9, 0x30, 0xad, 0xf9, 0x2f, 0x9b,
+- 0xb6, 0x1d, 0xae, 0xef, 0xf0, 0x2f, 0xf8, 0x5a,
+- 0x39, 0x3c, 0xbf, 0x2a, 0xb2, 0x45, 0xb2, 0x23,
+- 0x1b, 0x63, 0x3c, 0xcf, 0xaa, 0xbe, 0xcf, 0x4e,
+- 0xfa, 0xe8, 0x29, 0xc2, 0x20, 0x68, 0x2b, 0x3c,
+- 0x2e, 0x8b, 0xf7, 0x6e, 0x25, 0xbd, 0xe3, 0x3d,
+- 0x66, 0x27, 0xd6, 0xaf, 0xd6, 0x64, 0x3e, 0xe3,
+- 0xe8, 0x58, 0x46, 0x97, 0x39, 0x51, 0x07, 0xde,
+- 0xcb, 0x37, 0xbc, 0xa9, 0xc0, 0x5f, 0x75, 0xc3,
+- 0x0e, 0x84, 0x23, 0x1d, 0x16, 0xd4, 0x1c, 0x59,
+- 0x9c, 0x1a, 0x02, 0x55, 0xab, 0x3a, 0x97, 0x1d,
+- 0xdf, 0xdd, 0xc7, 0x06, 0x51, 0xd7, 0x70, 0xae,
+- 0x23, 0xc6, 0x8c, 0xf5, 0x1e, 0xa0, 0xe5, 0x82,
+- 0xb8, 0xb2, 0xbf, 0x04, 0xa0, 0x32, 0x8e, 0x68,
+- 0xeb, 0xaf, 0x6e, 0x2d, 0x94, 0x22, 0x2f, 0xce,
+- 0x4c, 0xb5, 0x59, 0xe2, 0xa2, 0x2f, 0xa0, 0x98,
+- 0x1a, 0x97, 0xc6, 0xd4, 0xb5, 0x00, 0x59, 0xf2,
+- 0x84, 0x14, 0x72, 0xb1, 0x9a, 0x6e, 0xa3, 0x7f,
+- 0xea, 0x20, 0xe7, 0xcb, 0x65, 0x77, 0x3a, 0xdf,
+- 0xc8, 0x97, 0x67, 0x15, 0xc2, 0x2a, 0x27, 0xcc,
+- 0x18, 0x55, 0xa1, 0x24, 0x0b, 0x24, 0x24, 0xaf,
+- 0x5b, 0xec, 0x68, 0xb8, 0xc8, 0xf5, 0xba, 0x63,
+- 0xff, 0xed, 0x89, 0xce, 0xd5, 0x3d, 0x88, 0xf3,
+- 0x25, 0xef, 0x05, 0x7c, 0x3a, 0xef, 0xeb, 0xd8,
+- 0x7a, 0x32, 0x0d, 0xd1, 0x1e, 0x58, 0x59, 0x99,
+- 0x90, 0x25, 0xb5, 0x26, 0xb0, 0xe3, 0x2b, 0x6c,
+- 0x4c, 0xa9, 0x8b, 0x84, 0x4f, 0x5e, 0x01, 0x50,
+- 0x41, 0x30, 0x58, 0xc5, 0x62, 0x74, 0x52, 0x1d,
+- 0x45, 0x24, 0x6a, 0x42, 0x64, 0x4f, 0x97, 0x1c,
+- 0xa8, 0x66, 0xb5, 0x6d, 0x79, 0xd4, 0x0d, 0x48,
+- 0xc5, 0x5f, 0xf3, 0x90, 0x32, 0xdd, 0xdd, 0xe1,
+- 0xe4, 0xa9, 0x9f, 0xfc, 0xc3, 0x52, 0x5a, 0x46,
+- 0xe4, 0x81, 0x84, 0x95, 0x36, 0x59, 0x7a, 0x6b,
+- 0xaa, 0xb3, 0x60, 0xad, 0xce, 0x9f, 0x9f, 0x28,
+- 0xe0, 0x01, 0x75, 0x22, 0xc4, 0x4e, 0xa9, 0x62,
+- 0x5c, 0x62, 0x0d, 0x00, 0xcb, 0x13, 0xe8, 0x43,
+- 0x72, 0xd4, 0x2d, 0x53, 0x46, 0xb5, 0xd1, 0x16,
+- 0x22, 0x18, 0xdf, 0x34, 0x33, 0xf5, 0xd6, 0x1c,
+- 0xb8, 0x79, 0x78, 0x97, 0x94, 0xff, 0x72, 0x13,
+- 0x4c, 0x27, 0xfc, 0xcb, 0xbf, 0x01, 0x53, 0xa6,
+- 0xb4, 0x50, 0x6e, 0xde, 0xdf, 0xb5, 0x43, 0xa4,
+- 0x59, 0xdf, 0x52, 0xf9, 0x7c, 0xe0, 0x11, 0x6f,
+- 0x2d, 0x14, 0x8e, 0x24, 0x61, 0x2c, 0xe1, 0x17,
+- 0xcc, 0xce, 0x51, 0x0c, 0x19, 0x8a, 0x82, 0x30,
+- 0x94, 0xd5, 0x3d, 0x6a, 0x53, 0x06, 0x5e, 0xbd,
+- 0xb7, 0xeb, 0xfa, 0xfd, 0x27, 0x51, 0xde, 0x85,
+- 0x1e, 0x86, 0x53, 0x11, 0x53, 0x94, 0x00, 0xee,
+- 0x2b, 0x8c, 0x08, 0x2a, 0xbf, 0xdd, 0xae, 0x11,
+- 0xcb, 0x1e, 0xa2, 0x07, 0x9a, 0x80, 0xcf, 0x62,
+- 0x9b, 0x09, 0xdc, 0x95, 0x3c, 0x96, 0x8e, 0xb1,
+- 0x09, 0xbd, 0xe4, 0xeb, 0xdb, 0xca, 0x70, 0x7a,
+- 0x9e, 0xfa, 0x31, 0x18, 0x45, 0x3c, 0x21, 0x33,
+- 0xb0, 0xb3, 0x2b, 0xea, 0xf3, 0x71, 0x2d, 0xe1,
+- 0x03, 0xad, 0x1b, 0x48, 0xd4, 0x67, 0x27, 0xf0,
+- 0x62, 0xe4, 0x3d, 0xfb, 0x9b, 0x08, 0x76, 0xe7,
+- 0xdd, 0x2b, 0x01, 0x39, 0x04, 0x5a, 0x58, 0x7a,
+- 0xf7, 0x11, 0x90, 0xec, 0xbd, 0x51, 0x5c, 0x32,
+- 0x6b, 0xd7, 0x35, 0x39, 0x02, 0x6b, 0xf2, 0xa6,
+- 0xd0, 0x0d, 0x07, 0xe1, 0x06, 0xc4, 0x5b, 0x7d,
+- 0xe4, 0x6a, 0xd7, 0xee, 0x15, 0x1f, 0x83, 0xb4,
+- 0xa3, 0xa7, 0x5e, 0xc3, 0x90, 0xb7, 0xef, 0xd3,
+- 0xb7, 0x4f, 0xf8, 0x92, 0x4c, 0xb7, 0x3c, 0x29,
+- 0xcd, 0x7e, 0x2b, 0x5d, 0x43, 0xea, 0x42, 0xe7,
+- 0x74, 0x3f, 0x7d, 0x58, 0x88, 0x75, 0xde, 0x3e },
++ .result = "\x1a\x1d\xa9\x30\xad\xf9\x2f\x9b"
++ "\xb6\x1d\xae\xef\xf0\x2f\xf8\x5a"
++ "\x39\x3c\xbf\x2a\xb2\x45\xb2\x23"
++ "\x1b\x63\x3c\xcf\xaa\xbe\xcf\x4e"
++ "\xfa\xe8\x29\xc2\x20\x68\x2b\x3c"
++ "\x2e\x8b\xf7\x6e\x25\xbd\xe3\x3d"
++ "\x66\x27\xd6\xaf\xd6\x64\x3e\xe3"
++ "\xe8\x58\x46\x97\x39\x51\x07\xde"
++ "\xcb\x37\xbc\xa9\xc0\x5f\x75\xc3"
++ "\x0e\x84\x23\x1d\x16\xd4\x1c\x59"
++ "\x9c\x1a\x02\x55\xab\x3a\x97\x1d"
++ "\xdf\xdd\xc7\x06\x51\xd7\x70\xae"
++ "\x23\xc6\x8c\xf5\x1e\xa0\xe5\x82"
++ "\xb8\xb2\xbf\x04\xa0\x32\x8e\x68"
++ "\xeb\xaf\x6e\x2d\x94\x22\x2f\xce"
++ "\x4c\xb5\x59\xe2\xa2\x2f\xa0\x98"
++ "\x1a\x97\xc6\xd4\xb5\x00\x59\xf2"
++ "\x84\x14\x72\xb1\x9a\x6e\xa3\x7f"
++ "\xea\x20\xe7\xcb\x65\x77\x3a\xdf"
++ "\xc8\x97\x67\x15\xc2\x2a\x27\xcc"
++ "\x18\x55\xa1\x24\x0b\x24\x24\xaf"
++ "\x5b\xec\x68\xb8\xc8\xf5\xba\x63"
++ "\xff\xed\x89\xce\xd5\x3d\x88\xf3"
++ "\x25\xef\x05\x7c\x3a\xef\xeb\xd8"
++ "\x7a\x32\x0d\xd1\x1e\x58\x59\x99"
++ "\x90\x25\xb5\x26\xb0\xe3\x2b\x6c"
++ "\x4c\xa9\x8b\x84\x4f\x5e\x01\x50"
++ "\x41\x30\x58\xc5\x62\x74\x52\x1d"
++ "\x45\x24\x6a\x42\x64\x4f\x97\x1c"
++ "\xa8\x66\xb5\x6d\x79\xd4\x0d\x48"
++ "\xc5\x5f\xf3\x90\x32\xdd\xdd\xe1"
++ "\xe4\xa9\x9f\xfc\xc3\x52\x5a\x46"
++ "\xe4\x81\x84\x95\x36\x59\x7a\x6b"
++ "\xaa\xb3\x60\xad\xce\x9f\x9f\x28"
++ "\xe0\x01\x75\x22\xc4\x4e\xa9\x62"
++ "\x5c\x62\x0d\x00\xcb\x13\xe8\x43"
++ "\x72\xd4\x2d\x53\x46\xb5\xd1\x16"
++ "\x22\x18\xdf\x34\x33\xf5\xd6\x1c"
++ "\xb8\x79\x78\x97\x94\xff\x72\x13"
++ "\x4c\x27\xfc\xcb\xbf\x01\x53\xa6"
++ "\xb4\x50\x6e\xde\xdf\xb5\x43\xa4"
++ "\x59\xdf\x52\xf9\x7c\xe0\x11\x6f"
++ "\x2d\x14\x8e\x24\x61\x2c\xe1\x17"
++ "\xcc\xce\x51\x0c\x19\x8a\x82\x30"
++ "\x94\xd5\x3d\x6a\x53\x06\x5e\xbd"
++ "\xb7\xeb\xfa\xfd\x27\x51\xde\x85"
++ "\x1e\x86\x53\x11\x53\x94\x00\xee"
++ "\x2b\x8c\x08\x2a\xbf\xdd\xae\x11"
++ "\xcb\x1e\xa2\x07\x9a\x80\xcf\x62"
++ "\x9b\x09\xdc\x95\x3c\x96\x8e\xb1"
++ "\x09\xbd\xe4\xeb\xdb\xca\x70\x7a"
++ "\x9e\xfa\x31\x18\x45\x3c\x21\x33"
++ "\xb0\xb3\x2b\xea\xf3\x71\x2d\xe1"
++ "\x03\xad\x1b\x48\xd4\x67\x27\xf0"
++ "\x62\xe4\x3d\xfb\x9b\x08\x76\xe7"
++ "\xdd\x2b\x01\x39\x04\x5a\x58\x7a"
++ "\xf7\x11\x90\xec\xbd\x51\x5c\x32"
++ "\x6b\xd7\x35\x39\x02\x6b\xf2\xa6"
++ "\xd0\x0d\x07\xe1\x06\xc4\x5b\x7d"
++ "\xe4\x6a\xd7\xee\x15\x1f\x83\xb4"
++ "\xa3\xa7\x5e\xc3\x90\xb7\xef\xd3"
++ "\xb7\x4f\xf8\x92\x4c\xb7\x3c\x29"
++ "\xcd\x7e\x2b\x5d\x43\xea\x42\xe7"
++ "\x74\x3f\x7d\x58\x88\x75\xde\x3e",
+ .rlen = 512,
+ }
+ };
+@@ -2809,250 +2834,249 @@ static struct cipher_testvec aes_lrw_dec_tv_template[] = {
+ /* from http://grouper.ieee.org/groups/1619/email/pdf00017.pdf */
+ /* same as enc vectors with input and result reversed */
+ { /* LRW-32-AES 1 */
+- .key = { 0x45, 0x62, 0xac, 0x25, 0xf8, 0x28, 0x17, 0x6d,
+- 0x4c, 0x26, 0x84, 0x14, 0xb5, 0x68, 0x01, 0x85,
+- 0x25, 0x8e, 0x2a, 0x05, 0xe7, 0x3e, 0x9d, 0x03,
+- 0xee, 0x5a, 0x83, 0x0c, 0xcc, 0x09, 0x4c, 0x87 },
++ .key = "\x45\x62\xac\x25\xf8\x28\x17\x6d"
++ "\x4c\x26\x84\x14\xb5\x68\x01\x85"
++ "\x25\x8e\x2a\x05\xe7\x3e\x9d\x03"
++ "\xee\x5a\x83\x0c\xcc\x09\x4c\x87",
+ .klen = 32,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+- .input = { 0xf1, 0xb2, 0x73, 0xcd, 0x65, 0xa3, 0xdf, 0x5f,
+- 0xe9, 0x5d, 0x48, 0x92, 0x54, 0x63, 0x4e, 0xb8 },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x01",
++ .input = "\xf1\xb2\x73\xcd\x65\xa3\xdf\x5f"
++ "\xe9\x5d\x48\x92\x54\x63\x4e\xb8",
+ .ilen = 16,
+- .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+- 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++ .result = "\x30\x31\x32\x33\x34\x35\x36\x37"
++ "\x38\x39\x41\x42\x43\x44\x45\x46",
+ .rlen = 16,
+ }, { /* LRW-32-AES 2 */
+- .key = { 0x59, 0x70, 0x47, 0x14, 0xf5, 0x57, 0x47, 0x8c,
+- 0xd7, 0x79, 0xe8, 0x0f, 0x54, 0x88, 0x79, 0x44,
+- 0x0d, 0x48, 0xf0, 0xb7, 0xb1, 0x5a, 0x53, 0xea,
+- 0x1c, 0xaa, 0x6b, 0x29, 0xc2, 0xca, 0xfb, 0xaf
+- },
++ .key = "\x59\x70\x47\x14\xf5\x57\x47\x8c"
++ "\xd7\x79\xe8\x0f\x54\x88\x79\x44"
++ "\x0d\x48\xf0\xb7\xb1\x5a\x53\xea"
++ "\x1c\xaa\x6b\x29\xc2\xca\xfb\xaf",
+ .klen = 32,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
+- .input = { 0x00, 0xc8, 0x2b, 0xae, 0x95, 0xbb, 0xcd, 0xe5,
+- 0x27, 0x4f, 0x07, 0x69, 0xb2, 0x60, 0xe1, 0x36 },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x02",
++ .input = "\x00\xc8\x2b\xae\x95\xbb\xcd\xe5"
++ "\x27\x4f\x07\x69\xb2\x60\xe1\x36",
+ .ilen = 16,
+- .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+- 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++ .result = "\x30\x31\x32\x33\x34\x35\x36\x37"
++ "\x38\x39\x41\x42\x43\x44\x45\x46",
+ .rlen = 16,
+ }, { /* LRW-32-AES 3 */
+- .key = { 0xd8, 0x2a, 0x91, 0x34, 0xb2, 0x6a, 0x56, 0x50,
+- 0x30, 0xfe, 0x69, 0xe2, 0x37, 0x7f, 0x98, 0x47,
+- 0xcd, 0xf9, 0x0b, 0x16, 0x0c, 0x64, 0x8f, 0xb6,
+- 0xb0, 0x0d, 0x0d, 0x1b, 0xae, 0x85, 0x87, 0x1f },
++ .key = "\xd8\x2a\x91\x34\xb2\x6a\x56\x50"
++ "\x30\xfe\x69\xe2\x37\x7f\x98\x47"
++ "\xcd\xf9\x0b\x16\x0c\x64\x8f\xb6"
++ "\xb0\x0d\x0d\x1b\xae\x85\x87\x1f",
+ .klen = 32,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+- .input = { 0x76, 0x32, 0x21, 0x83, 0xed, 0x8f, 0xf1, 0x82,
+- 0xf9, 0x59, 0x62, 0x03, 0x69, 0x0e, 0x5e, 0x01 },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x02\x00\x00\x00\x00",
++ .input = "\x76\x32\x21\x83\xed\x8f\xf1\x82"
++ "\xf9\x59\x62\x03\x69\x0e\x5e\x01",
+ .ilen = 16,
+- .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+- 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++ .result = "\x30\x31\x32\x33\x34\x35\x36\x37"
++ "\x38\x39\x41\x42\x43\x44\x45\x46",
+ .rlen = 16,
+ }, { /* LRW-32-AES 4 */
+- .key = { 0x0f, 0x6a, 0xef, 0xf8, 0xd3, 0xd2, 0xbb, 0x15,
+- 0x25, 0x83, 0xf7, 0x3c, 0x1f, 0x01, 0x28, 0x74,
+- 0xca, 0xc6, 0xbc, 0x35, 0x4d, 0x4a, 0x65, 0x54,
+- 0x90, 0xae, 0x61, 0xcf, 0x7b, 0xae, 0xbd, 0xcc,
+- 0xad, 0xe4, 0x94, 0xc5, 0x4a, 0x29, 0xae, 0x70 },
++ .key = "\x0f\x6a\xef\xf8\xd3\xd2\xbb\x15"
++ "\x25\x83\xf7\x3c\x1f\x01\x28\x74"
++ "\xca\xc6\xbc\x35\x4d\x4a\x65\x54"
++ "\x90\xae\x61\xcf\x7b\xae\xbd\xcc"
++ "\xad\xe4\x94\xc5\x4a\x29\xae\x70",
+ .klen = 40,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+- .input = { 0x9c, 0x0f, 0x15, 0x2f, 0x55, 0xa2, 0xd8, 0xf0,
+- 0xd6, 0x7b, 0x8f, 0x9e, 0x28, 0x22, 0xbc, 0x41 },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x01",
++ .input = "\x9c\x0f\x15\x2f\x55\xa2\xd8\xf0"
++ "\xd6\x7b\x8f\x9e\x28\x22\xbc\x41",
+ .ilen = 16,
+- .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+- 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++ .result = "\x30\x31\x32\x33\x34\x35\x36\x37"
++ "\x38\x39\x41\x42\x43\x44\x45\x46",
+ .rlen = 16,
+ }, { /* LRW-32-AES 5 */
+- .key = { 0x8a, 0xd4, 0xee, 0x10, 0x2f, 0xbd, 0x81, 0xff,
+- 0xf8, 0x86, 0xce, 0xac, 0x93, 0xc5, 0xad, 0xc6,
+- 0xa0, 0x19, 0x07, 0xc0, 0x9d, 0xf7, 0xbb, 0xdd,
+- 0x52, 0x13, 0xb2, 0xb7, 0xf0, 0xff, 0x11, 0xd8,
+- 0xd6, 0x08, 0xd0, 0xcd, 0x2e, 0xb1, 0x17, 0x6f },
++ .key = "\x8a\xd4\xee\x10\x2f\xbd\x81\xff"
++ "\xf8\x86\xce\xac\x93\xc5\xad\xc6"
++ "\xa0\x19\x07\xc0\x9d\xf7\xbb\xdd"
++ "\x52\x13\xb2\xb7\xf0\xff\x11\xd8"
++ "\xd6\x08\xd0\xcd\x2e\xb1\x17\x6f",
+ .klen = 40,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+- .input = { 0xd4, 0x27, 0x6a, 0x7f, 0x14, 0x91, 0x3d, 0x65,
+- 0xc8, 0x60, 0x48, 0x02, 0x87, 0xe3, 0x34, 0x06 },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x02\x00\x00\x00\x00",
++ .input = "\xd4\x27\x6a\x7f\x14\x91\x3d\x65"
++ "\xc8\x60\x48\x02\x87\xe3\x34\x06",
+ .ilen = 16,
+- .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+- 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++ .result = "\x30\x31\x32\x33\x34\x35\x36\x37"
++ "\x38\x39\x41\x42\x43\x44\x45\x46",
+ .rlen = 16,
+ }, { /* LRW-32-AES 6 */
+- .key = { 0xf8, 0xd4, 0x76, 0xff, 0xd6, 0x46, 0xee, 0x6c,
+- 0x23, 0x84, 0xcb, 0x1c, 0x77, 0xd6, 0x19, 0x5d,
+- 0xfe, 0xf1, 0xa9, 0xf3, 0x7b, 0xbc, 0x8d, 0x21,
+- 0xa7, 0x9c, 0x21, 0xf8, 0xcb, 0x90, 0x02, 0x89,
+- 0xa8, 0x45, 0x34, 0x8e, 0xc8, 0xc5, 0xb5, 0xf1,
+- 0x26, 0xf5, 0x0e, 0x76, 0xfe, 0xfd, 0x1b, 0x1e },
++ .key = "\xf8\xd4\x76\xff\xd6\x46\xee\x6c"
++ "\x23\x84\xcb\x1c\x77\xd6\x19\x5d"
++ "\xfe\xf1\xa9\xf3\x7b\xbc\x8d\x21"
++ "\xa7\x9c\x21\xf8\xcb\x90\x02\x89"
++ "\xa8\x45\x34\x8e\xc8\xc5\xb5\xf1"
++ "\x26\xf5\x0e\x76\xfe\xfd\x1b\x1e",
+ .klen = 48,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+- .input = { 0xbd, 0x06, 0xb8, 0xe1, 0xdb, 0x98, 0x89, 0x9e,
+- 0xc4, 0x98, 0xe4, 0x91, 0xcf, 0x1c, 0x70, 0x2b },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x01",
++ .input = "\xbd\x06\xb8\xe1\xdb\x98\x89\x9e"
++ "\xc4\x98\xe4\x91\xcf\x1c\x70\x2b",
+ .ilen = 16,
+- .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+- 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++ .result = "\x30\x31\x32\x33\x34\x35\x36\x37"
++ "\x38\x39\x41\x42\x43\x44\x45\x46",
+ .rlen = 16,
+ }, { /* LRW-32-AES 7 */
+- .key = { 0xfb, 0x76, 0x15, 0xb2, 0x3d, 0x80, 0x89, 0x1d,
+- 0xd4, 0x70, 0x98, 0x0b, 0xc7, 0x95, 0x84, 0xc8,
+- 0xb2, 0xfb, 0x64, 0xce, 0x60, 0x97, 0x87, 0x8d,
+- 0x17, 0xfc, 0xe4, 0x5a, 0x49, 0xe8, 0x30, 0xb7,
+- 0x6e, 0x78, 0x17, 0xe7, 0x2d, 0x5e, 0x12, 0xd4,
+- 0x60, 0x64, 0x04, 0x7a, 0xf1, 0x2f, 0x9e, 0x0c },
++ .key = "\xfb\x76\x15\xb2\x3d\x80\x89\x1d"
++ "\xd4\x70\x98\x0b\xc7\x95\x84\xc8"
++ "\xb2\xfb\x64\xce\x60\x97\x87\x8d"
++ "\x17\xfc\xe4\x5a\x49\xe8\x30\xb7"
++ "\x6e\x78\x17\xe7\x2d\x5e\x12\xd4"
++ "\x60\x64\x04\x7a\xf1\x2f\x9e\x0c",
+ .klen = 48,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
+- .input = { 0x5b, 0x90, 0x8e, 0xc1, 0xab, 0xdd, 0x67, 0x5f,
+- 0x3d, 0x69, 0x8a, 0x95, 0x53, 0xc8, 0x9c, 0xe5 },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x02\x00\x00\x00\x00",
++ .input = "\x5b\x90\x8e\xc1\xab\xdd\x67\x5f"
++ "\x3d\x69\x8a\x95\x53\xc8\x9c\xe5",
+ .ilen = 16,
+- .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+- 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
++ .result = "\x30\x31\x32\x33\x34\x35\x36\x37"
++ "\x38\x39\x41\x42\x43\x44\x45\x46",
+ .rlen = 16,
+ }, {
+ /* http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00173.html */
+- .key = { 0xf8, 0xd4, 0x76, 0xff, 0xd6, 0x46, 0xee, 0x6c,
+- 0x23, 0x84, 0xcb, 0x1c, 0x77, 0xd6, 0x19, 0x5d,
+- 0xfe, 0xf1, 0xa9, 0xf3, 0x7b, 0xbc, 0x8d, 0x21,
+- 0xa7, 0x9c, 0x21, 0xf8, 0xcb, 0x90, 0x02, 0x89,
+- 0xa8, 0x45, 0x34, 0x8e, 0xc8, 0xc5, 0xb5, 0xf1,
+- 0x26, 0xf5, 0x0e, 0x76, 0xfe, 0xfd, 0x1b, 0x1e },
++ .key = "\xf8\xd4\x76\xff\xd6\x46\xee\x6c"
++ "\x23\x84\xcb\x1c\x77\xd6\x19\x5d"
++ "\xfe\xf1\xa9\xf3\x7b\xbc\x8d\x21"
++ "\xa7\x9c\x21\xf8\xcb\x90\x02\x89"
++ "\xa8\x45\x34\x8e\xc8\xc5\xb5\xf1"
++ "\x26\xf5\x0e\x76\xfe\xfd\x1b\x1e",
+ .klen = 48,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+- .input = { 0x1a, 0x1d, 0xa9, 0x30, 0xad, 0xf9, 0x2f, 0x9b,
+- 0xb6, 0x1d, 0xae, 0xef, 0xf0, 0x2f, 0xf8, 0x5a,
+- 0x39, 0x3c, 0xbf, 0x2a, 0xb2, 0x45, 0xb2, 0x23,
+- 0x1b, 0x63, 0x3c, 0xcf, 0xaa, 0xbe, 0xcf, 0x4e,
+- 0xfa, 0xe8, 0x29, 0xc2, 0x20, 0x68, 0x2b, 0x3c,
+- 0x2e, 0x8b, 0xf7, 0x6e, 0x25, 0xbd, 0xe3, 0x3d,
+- 0x66, 0x27, 0xd6, 0xaf, 0xd6, 0x64, 0x3e, 0xe3,
+- 0xe8, 0x58, 0x46, 0x97, 0x39, 0x51, 0x07, 0xde,
+- 0xcb, 0x37, 0xbc, 0xa9, 0xc0, 0x5f, 0x75, 0xc3,
+- 0x0e, 0x84, 0x23, 0x1d, 0x16, 0xd4, 0x1c, 0x59,
+- 0x9c, 0x1a, 0x02, 0x55, 0xab, 0x3a, 0x97, 0x1d,
+- 0xdf, 0xdd, 0xc7, 0x06, 0x51, 0xd7, 0x70, 0xae,
+- 0x23, 0xc6, 0x8c, 0xf5, 0x1e, 0xa0, 0xe5, 0x82,
+- 0xb8, 0xb2, 0xbf, 0x04, 0xa0, 0x32, 0x8e, 0x68,
+- 0xeb, 0xaf, 0x6e, 0x2d, 0x94, 0x22, 0x2f, 0xce,
+- 0x4c, 0xb5, 0x59, 0xe2, 0xa2, 0x2f, 0xa0, 0x98,
+- 0x1a, 0x97, 0xc6, 0xd4, 0xb5, 0x00, 0x59, 0xf2,
+- 0x84, 0x14, 0x72, 0xb1, 0x9a, 0x6e, 0xa3, 0x7f,
+- 0xea, 0x20, 0xe7, 0xcb, 0x65, 0x77, 0x3a, 0xdf,
+- 0xc8, 0x97, 0x67, 0x15, 0xc2, 0x2a, 0x27, 0xcc,
+- 0x18, 0x55, 0xa1, 0x24, 0x0b, 0x24, 0x24, 0xaf,
+- 0x5b, 0xec, 0x68, 0xb8, 0xc8, 0xf5, 0xba, 0x63,
+- 0xff, 0xed, 0x89, 0xce, 0xd5, 0x3d, 0x88, 0xf3,
+- 0x25, 0xef, 0x05, 0x7c, 0x3a, 0xef, 0xeb, 0xd8,
+- 0x7a, 0x32, 0x0d, 0xd1, 0x1e, 0x58, 0x59, 0x99,
+- 0x90, 0x25, 0xb5, 0x26, 0xb0, 0xe3, 0x2b, 0x6c,
+- 0x4c, 0xa9, 0x8b, 0x84, 0x4f, 0x5e, 0x01, 0x50,
+- 0x41, 0x30, 0x58, 0xc5, 0x62, 0x74, 0x52, 0x1d,
+- 0x45, 0x24, 0x6a, 0x42, 0x64, 0x4f, 0x97, 0x1c,
+- 0xa8, 0x66, 0xb5, 0x6d, 0x79, 0xd4, 0x0d, 0x48,
+- 0xc5, 0x5f, 0xf3, 0x90, 0x32, 0xdd, 0xdd, 0xe1,
+- 0xe4, 0xa9, 0x9f, 0xfc, 0xc3, 0x52, 0x5a, 0x46,
+- 0xe4, 0x81, 0x84, 0x95, 0x36, 0x59, 0x7a, 0x6b,
+- 0xaa, 0xb3, 0x60, 0xad, 0xce, 0x9f, 0x9f, 0x28,
+- 0xe0, 0x01, 0x75, 0x22, 0xc4, 0x4e, 0xa9, 0x62,
+- 0x5c, 0x62, 0x0d, 0x00, 0xcb, 0x13, 0xe8, 0x43,
+- 0x72, 0xd4, 0x2d, 0x53, 0x46, 0xb5, 0xd1, 0x16,
+- 0x22, 0x18, 0xdf, 0x34, 0x33, 0xf5, 0xd6, 0x1c,
+- 0xb8, 0x79, 0x78, 0x97, 0x94, 0xff, 0x72, 0x13,
+- 0x4c, 0x27, 0xfc, 0xcb, 0xbf, 0x01, 0x53, 0xa6,
+- 0xb4, 0x50, 0x6e, 0xde, 0xdf, 0xb5, 0x43, 0xa4,
+- 0x59, 0xdf, 0x52, 0xf9, 0x7c, 0xe0, 0x11, 0x6f,
+- 0x2d, 0x14, 0x8e, 0x24, 0x61, 0x2c, 0xe1, 0x17,
+- 0xcc, 0xce, 0x51, 0x0c, 0x19, 0x8a, 0x82, 0x30,
+- 0x94, 0xd5, 0x3d, 0x6a, 0x53, 0x06, 0x5e, 0xbd,
+- 0xb7, 0xeb, 0xfa, 0xfd, 0x27, 0x51, 0xde, 0x85,
+- 0x1e, 0x86, 0x53, 0x11, 0x53, 0x94, 0x00, 0xee,
+- 0x2b, 0x8c, 0x08, 0x2a, 0xbf, 0xdd, 0xae, 0x11,
+- 0xcb, 0x1e, 0xa2, 0x07, 0x9a, 0x80, 0xcf, 0x62,
+- 0x9b, 0x09, 0xdc, 0x95, 0x3c, 0x96, 0x8e, 0xb1,
+- 0x09, 0xbd, 0xe4, 0xeb, 0xdb, 0xca, 0x70, 0x7a,
+- 0x9e, 0xfa, 0x31, 0x18, 0x45, 0x3c, 0x21, 0x33,
+- 0xb0, 0xb3, 0x2b, 0xea, 0xf3, 0x71, 0x2d, 0xe1,
+- 0x03, 0xad, 0x1b, 0x48, 0xd4, 0x67, 0x27, 0xf0,
+- 0x62, 0xe4, 0x3d, 0xfb, 0x9b, 0x08, 0x76, 0xe7,
+- 0xdd, 0x2b, 0x01, 0x39, 0x04, 0x5a, 0x58, 0x7a,
+- 0xf7, 0x11, 0x90, 0xec, 0xbd, 0x51, 0x5c, 0x32,
+- 0x6b, 0xd7, 0x35, 0x39, 0x02, 0x6b, 0xf2, 0xa6,
+- 0xd0, 0x0d, 0x07, 0xe1, 0x06, 0xc4, 0x5b, 0x7d,
+- 0xe4, 0x6a, 0xd7, 0xee, 0x15, 0x1f, 0x83, 0xb4,
+- 0xa3, 0xa7, 0x5e, 0xc3, 0x90, 0xb7, 0xef, 0xd3,
+- 0xb7, 0x4f, 0xf8, 0x92, 0x4c, 0xb7, 0x3c, 0x29,
+- 0xcd, 0x7e, 0x2b, 0x5d, 0x43, 0xea, 0x42, 0xe7,
+- 0x74, 0x3f, 0x7d, 0x58, 0x88, 0x75, 0xde, 0x3e },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x01",
++ .input = "\x1a\x1d\xa9\x30\xad\xf9\x2f\x9b"
++ "\xb6\x1d\xae\xef\xf0\x2f\xf8\x5a"
++ "\x39\x3c\xbf\x2a\xb2\x45\xb2\x23"
++ "\x1b\x63\x3c\xcf\xaa\xbe\xcf\x4e"
++ "\xfa\xe8\x29\xc2\x20\x68\x2b\x3c"
++ "\x2e\x8b\xf7\x6e\x25\xbd\xe3\x3d"
++ "\x66\x27\xd6\xaf\xd6\x64\x3e\xe3"
++ "\xe8\x58\x46\x97\x39\x51\x07\xde"
++ "\xcb\x37\xbc\xa9\xc0\x5f\x75\xc3"
++ "\x0e\x84\x23\x1d\x16\xd4\x1c\x59"
++ "\x9c\x1a\x02\x55\xab\x3a\x97\x1d"
++ "\xdf\xdd\xc7\x06\x51\xd7\x70\xae"
++ "\x23\xc6\x8c\xf5\x1e\xa0\xe5\x82"
++ "\xb8\xb2\xbf\x04\xa0\x32\x8e\x68"
++ "\xeb\xaf\x6e\x2d\x94\x22\x2f\xce"
++ "\x4c\xb5\x59\xe2\xa2\x2f\xa0\x98"
++ "\x1a\x97\xc6\xd4\xb5\x00\x59\xf2"
++ "\x84\x14\x72\xb1\x9a\x6e\xa3\x7f"
++ "\xea\x20\xe7\xcb\x65\x77\x3a\xdf"
++ "\xc8\x97\x67\x15\xc2\x2a\x27\xcc"
++ "\x18\x55\xa1\x24\x0b\x24\x24\xaf"
++ "\x5b\xec\x68\xb8\xc8\xf5\xba\x63"
++ "\xff\xed\x89\xce\xd5\x3d\x88\xf3"
++ "\x25\xef\x05\x7c\x3a\xef\xeb\xd8"
++ "\x7a\x32\x0d\xd1\x1e\x58\x59\x99"
++ "\x90\x25\xb5\x26\xb0\xe3\x2b\x6c"
++ "\x4c\xa9\x8b\x84\x4f\x5e\x01\x50"
++ "\x41\x30\x58\xc5\x62\x74\x52\x1d"
++ "\x45\x24\x6a\x42\x64\x4f\x97\x1c"
++ "\xa8\x66\xb5\x6d\x79\xd4\x0d\x48"
++ "\xc5\x5f\xf3\x90\x32\xdd\xdd\xe1"
++ "\xe4\xa9\x9f\xfc\xc3\x52\x5a\x46"
++ "\xe4\x81\x84\x95\x36\x59\x7a\x6b"
++ "\xaa\xb3\x60\xad\xce\x9f\x9f\x28"
++ "\xe0\x01\x75\x22\xc4\x4e\xa9\x62"
++ "\x5c\x62\x0d\x00\xcb\x13\xe8\x43"
++ "\x72\xd4\x2d\x53\x46\xb5\xd1\x16"
++ "\x22\x18\xdf\x34\x33\xf5\xd6\x1c"
++ "\xb8\x79\x78\x97\x94\xff\x72\x13"
++ "\x4c\x27\xfc\xcb\xbf\x01\x53\xa6"
++ "\xb4\x50\x6e\xde\xdf\xb5\x43\xa4"
++ "\x59\xdf\x52\xf9\x7c\xe0\x11\x6f"
++ "\x2d\x14\x8e\x24\x61\x2c\xe1\x17"
++ "\xcc\xce\x51\x0c\x19\x8a\x82\x30"
++ "\x94\xd5\x3d\x6a\x53\x06\x5e\xbd"
++ "\xb7\xeb\xfa\xfd\x27\x51\xde\x85"
++ "\x1e\x86\x53\x11\x53\x94\x00\xee"
++ "\x2b\x8c\x08\x2a\xbf\xdd\xae\x11"
++ "\xcb\x1e\xa2\x07\x9a\x80\xcf\x62"
++ "\x9b\x09\xdc\x95\x3c\x96\x8e\xb1"
++ "\x09\xbd\xe4\xeb\xdb\xca\x70\x7a"
++ "\x9e\xfa\x31\x18\x45\x3c\x21\x33"
++ "\xb0\xb3\x2b\xea\xf3\x71\x2d\xe1"
++ "\x03\xad\x1b\x48\xd4\x67\x27\xf0"
++ "\x62\xe4\x3d\xfb\x9b\x08\x76\xe7"
++ "\xdd\x2b\x01\x39\x04\x5a\x58\x7a"
++ "\xf7\x11\x90\xec\xbd\x51\x5c\x32"
++ "\x6b\xd7\x35\x39\x02\x6b\xf2\xa6"
++ "\xd0\x0d\x07\xe1\x06\xc4\x5b\x7d"
++ "\xe4\x6a\xd7\xee\x15\x1f\x83\xb4"
++ "\xa3\xa7\x5e\xc3\x90\xb7\xef\xd3"
++ "\xb7\x4f\xf8\x92\x4c\xb7\x3c\x29"
++ "\xcd\x7e\x2b\x5d\x43\xea\x42\xe7"
++ "\x74\x3f\x7d\x58\x88\x75\xde\x3e",
+ .ilen = 512,
+- .result = { 0x05, 0x11, 0xb7, 0x18, 0xab, 0xc6, 0x2d, 0xac,
+- 0x70, 0x5d, 0xf6, 0x22, 0x94, 0xcd, 0xe5, 0x6c,
+- 0x17, 0x6b, 0xf6, 0x1c, 0xf0, 0xf3, 0x6e, 0xf8,
+- 0x50, 0x38, 0x1f, 0x71, 0x49, 0xb6, 0x57, 0xd6,
+- 0x8f, 0xcb, 0x8d, 0x6b, 0xe3, 0xa6, 0x29, 0x90,
+- 0xfe, 0x2a, 0x62, 0x82, 0xae, 0x6d, 0x8b, 0xf6,
+- 0xad, 0x1e, 0x9e, 0x20, 0x5f, 0x38, 0xbe, 0x04,
+- 0xda, 0x10, 0x8e, 0xed, 0xa2, 0xa4, 0x87, 0xab,
+- 0xda, 0x6b, 0xb4, 0x0c, 0x75, 0xba, 0xd3, 0x7c,
+- 0xc9, 0xac, 0x42, 0x31, 0x95, 0x7c, 0xc9, 0x04,
+- 0xeb, 0xd5, 0x6e, 0x32, 0x69, 0x8a, 0xdb, 0xa6,
+- 0x15, 0xd7, 0x3f, 0x4f, 0x2f, 0x66, 0x69, 0x03,
+- 0x9c, 0x1f, 0x54, 0x0f, 0xde, 0x1f, 0xf3, 0x65,
+- 0x4c, 0x96, 0x12, 0xed, 0x7c, 0x92, 0x03, 0x01,
+- 0x6f, 0xbc, 0x35, 0x93, 0xac, 0xf1, 0x27, 0xf1,
+- 0xb4, 0x96, 0x82, 0x5a, 0x5f, 0xb0, 0xa0, 0x50,
+- 0x89, 0xa4, 0x8e, 0x66, 0x44, 0x85, 0xcc, 0xfd,
+- 0x33, 0x14, 0x70, 0xe3, 0x96, 0xb2, 0xc3, 0xd3,
+- 0xbb, 0x54, 0x5a, 0x1a, 0xf9, 0x74, 0xa2, 0xc5,
+- 0x2d, 0x64, 0x75, 0xdd, 0xb4, 0x54, 0xe6, 0x74,
+- 0x8c, 0xd3, 0x9d, 0x9e, 0x86, 0xab, 0x51, 0x53,
+- 0xb7, 0x93, 0x3e, 0x6f, 0xd0, 0x4e, 0x2c, 0x40,
+- 0xf6, 0xa8, 0x2e, 0x3e, 0x9d, 0xf4, 0x66, 0xa5,
+- 0x76, 0x12, 0x73, 0x44, 0x1a, 0x56, 0xd7, 0x72,
+- 0x88, 0xcd, 0x21, 0x8c, 0x4c, 0x0f, 0xfe, 0xda,
+- 0x95, 0xe0, 0x3a, 0xa6, 0xa5, 0x84, 0x46, 0xcd,
+- 0xd5, 0x3e, 0x9d, 0x3a, 0xe2, 0x67, 0xe6, 0x60,
+- 0x1a, 0xe2, 0x70, 0x85, 0x58, 0xc2, 0x1b, 0x09,
+- 0xe1, 0xd7, 0x2c, 0xca, 0xad, 0xa8, 0x8f, 0xf9,
+- 0xac, 0xb3, 0x0e, 0xdb, 0xca, 0x2e, 0xe2, 0xb8,
+- 0x51, 0x71, 0xd9, 0x3c, 0x6c, 0xf1, 0x56, 0xf8,
+- 0xea, 0x9c, 0xf1, 0xfb, 0x0c, 0xe6, 0xb7, 0x10,
+- 0x1c, 0xf8, 0xa9, 0x7c, 0xe8, 0x53, 0x35, 0xc1,
+- 0x90, 0x3e, 0x76, 0x4a, 0x74, 0xa4, 0x21, 0x2c,
+- 0xf6, 0x2c, 0x4e, 0x0f, 0x94, 0x3a, 0x88, 0x2e,
+- 0x41, 0x09, 0x6a, 0x33, 0x7d, 0xf6, 0xdd, 0x3f,
+- 0x8d, 0x23, 0x31, 0x74, 0x84, 0xeb, 0x88, 0x6e,
+- 0xcc, 0xb9, 0xbc, 0x22, 0x83, 0x19, 0x07, 0x22,
+- 0xa5, 0x2d, 0xdf, 0xa5, 0xf3, 0x80, 0x85, 0x78,
+- 0x84, 0x39, 0x6a, 0x6d, 0x6a, 0x99, 0x4f, 0xa5,
+- 0x15, 0xfe, 0x46, 0xb0, 0xe4, 0x6c, 0xa5, 0x41,
+- 0x3c, 0xce, 0x8f, 0x42, 0x60, 0x71, 0xa7, 0x75,
+- 0x08, 0x40, 0x65, 0x8a, 0x82, 0xbf, 0xf5, 0x43,
+- 0x71, 0x96, 0xa9, 0x4d, 0x44, 0x8a, 0x20, 0xbe,
+- 0xfa, 0x4d, 0xbb, 0xc0, 0x7d, 0x31, 0x96, 0x65,
+- 0xe7, 0x75, 0xe5, 0x3e, 0xfd, 0x92, 0x3b, 0xc9,
+- 0x55, 0xbb, 0x16, 0x7e, 0xf7, 0xc2, 0x8c, 0xa4,
+- 0x40, 0x1d, 0xe5, 0xef, 0x0e, 0xdf, 0xe4, 0x9a,
+- 0x62, 0x73, 0x65, 0xfd, 0x46, 0x63, 0x25, 0x3d,
+- 0x2b, 0xaf, 0xe5, 0x64, 0xfe, 0xa5, 0x5c, 0xcf,
+- 0x24, 0xf3, 0xb4, 0xac, 0x64, 0xba, 0xdf, 0x4b,
+- 0xc6, 0x96, 0x7d, 0x81, 0x2d, 0x8d, 0x97, 0xf7,
+- 0xc5, 0x68, 0x77, 0x84, 0x32, 0x2b, 0xcc, 0x85,
+- 0x74, 0x96, 0xf0, 0x12, 0x77, 0x61, 0xb9, 0xeb,
+- 0x71, 0xaa, 0x82, 0xcb, 0x1c, 0xdb, 0x89, 0xc8,
+- 0xc6, 0xb5, 0xe3, 0x5c, 0x7d, 0x39, 0x07, 0x24,
+- 0xda, 0x39, 0x87, 0x45, 0xc0, 0x2b, 0xbb, 0x01,
+- 0xac, 0xbc, 0x2a, 0x5c, 0x7f, 0xfc, 0xe8, 0xce,
+- 0x6d, 0x9c, 0x6f, 0xed, 0xd3, 0xc1, 0xa1, 0xd6,
+- 0xc5, 0x55, 0xa9, 0x66, 0x2f, 0xe1, 0xc8, 0x32,
+- 0xa6, 0x5d, 0xa4, 0x3a, 0x98, 0x73, 0xe8, 0x45,
+- 0xa4, 0xc7, 0xa8, 0xb4, 0xf6, 0x13, 0x03, 0xf6,
+- 0xe9, 0x2e, 0xc4, 0x29, 0x0f, 0x84, 0xdb, 0xc4,
+- 0x21, 0xc4, 0xc2, 0x75, 0x67, 0x89, 0x37, 0x0a },
++ .result = "\x05\x11\xb7\x18\xab\xc6\x2d\xac"
++ "\x70\x5d\xf6\x22\x94\xcd\xe5\x6c"
++ "\x17\x6b\xf6\x1c\xf0\xf3\x6e\xf8"
++ "\x50\x38\x1f\x71\x49\xb6\x57\xd6"
++ "\x8f\xcb\x8d\x6b\xe3\xa6\x29\x90"
++ "\xfe\x2a\x62\x82\xae\x6d\x8b\xf6"
++ "\xad\x1e\x9e\x20\x5f\x38\xbe\x04"
++ "\xda\x10\x8e\xed\xa2\xa4\x87\xab"
++ "\xda\x6b\xb4\x0c\x75\xba\xd3\x7c"
++ "\xc9\xac\x42\x31\x95\x7c\xc9\x04"
++ "\xeb\xd5\x6e\x32\x69\x8a\xdb\xa6"
++ "\x15\xd7\x3f\x4f\x2f\x66\x69\x03"
++ "\x9c\x1f\x54\x0f\xde\x1f\xf3\x65"
++ "\x4c\x96\x12\xed\x7c\x92\x03\x01"
++ "\x6f\xbc\x35\x93\xac\xf1\x27\xf1"
++ "\xb4\x96\x82\x5a\x5f\xb0\xa0\x50"
++ "\x89\xa4\x8e\x66\x44\x85\xcc\xfd"
++ "\x33\x14\x70\xe3\x96\xb2\xc3\xd3"
++ "\xbb\x54\x5a\x1a\xf9\x74\xa2\xc5"
++ "\x2d\x64\x75\xdd\xb4\x54\xe6\x74"
++ "\x8c\xd3\x9d\x9e\x86\xab\x51\x53"
++ "\xb7\x93\x3e\x6f\xd0\x4e\x2c\x40"
++ "\xf6\xa8\x2e\x3e\x9d\xf4\x66\xa5"
++ "\x76\x12\x73\x44\x1a\x56\xd7\x72"
++ "\x88\xcd\x21\x8c\x4c\x0f\xfe\xda"
++ "\x95\xe0\x3a\xa6\xa5\x84\x46\xcd"
++ "\xd5\x3e\x9d\x3a\xe2\x67\xe6\x60"
++ "\x1a\xe2\x70\x85\x58\xc2\x1b\x09"
++ "\xe1\xd7\x2c\xca\xad\xa8\x8f\xf9"
++ "\xac\xb3\x0e\xdb\xca\x2e\xe2\xb8"
++ "\x51\x71\xd9\x3c\x6c\xf1\x56\xf8"
++ "\xea\x9c\xf1\xfb\x0c\xe6\xb7\x10"
++ "\x1c\xf8\xa9\x7c\xe8\x53\x35\xc1"
++ "\x90\x3e\x76\x4a\x74\xa4\x21\x2c"
++ "\xf6\x2c\x4e\x0f\x94\x3a\x88\x2e"
++ "\x41\x09\x6a\x33\x7d\xf6\xdd\x3f"
++ "\x8d\x23\x31\x74\x84\xeb\x88\x6e"
++ "\xcc\xb9\xbc\x22\x83\x19\x07\x22"
++ "\xa5\x2d\xdf\xa5\xf3\x80\x85\x78"
++ "\x84\x39\x6a\x6d\x6a\x99\x4f\xa5"
++ "\x15\xfe\x46\xb0\xe4\x6c\xa5\x41"
++ "\x3c\xce\x8f\x42\x60\x71\xa7\x75"
++ "\x08\x40\x65\x8a\x82\xbf\xf5\x43"
++ "\x71\x96\xa9\x4d\x44\x8a\x20\xbe"
++ "\xfa\x4d\xbb\xc0\x7d\x31\x96\x65"
++ "\xe7\x75\xe5\x3e\xfd\x92\x3b\xc9"
++ "\x55\xbb\x16\x7e\xf7\xc2\x8c\xa4"
++ "\x40\x1d\xe5\xef\x0e\xdf\xe4\x9a"
++ "\x62\x73\x65\xfd\x46\x63\x25\x3d"
++ "\x2b\xaf\xe5\x64\xfe\xa5\x5c\xcf"
++ "\x24\xf3\xb4\xac\x64\xba\xdf\x4b"
++ "\xc6\x96\x7d\x81\x2d\x8d\x97\xf7"
++ "\xc5\x68\x77\x84\x32\x2b\xcc\x85"
++ "\x74\x96\xf0\x12\x77\x61\xb9\xeb"
++ "\x71\xaa\x82\xcb\x1c\xdb\x89\xc8"
++ "\xc6\xb5\xe3\x5c\x7d\x39\x07\x24"
++ "\xda\x39\x87\x45\xc0\x2b\xbb\x01"
++ "\xac\xbc\x2a\x5c\x7f\xfc\xe8\xce"
++ "\x6d\x9c\x6f\xed\xd3\xc1\xa1\xd6"
++ "\xc5\x55\xa9\x66\x2f\xe1\xc8\x32"
++ "\xa6\x5d\xa4\x3a\x98\x73\xe8\x45"
++ "\xa4\xc7\xa8\xb4\xf6\x13\x03\xf6"
++ "\xe9\x2e\xc4\x29\x0f\x84\xdb\xc4"
++ "\x21\xc4\xc2\x75\x67\x89\x37\x0a",
+ .rlen = 512,
+ }
+ };
+@@ -3060,196 +3084,196 @@ static struct cipher_testvec aes_lrw_dec_tv_template[] = {
+ static struct cipher_testvec aes_xts_enc_tv_template[] = {
+ /* http://grouper.ieee.org/groups/1619/email/pdf00086.pdf */
+ { /* XTS-AES 1 */
+- .key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .key = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .klen = 32,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+- .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
++ .input = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .ilen = 32,
+- .result = { 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec,
+- 0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92,
+- 0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85,
+- 0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e },
++ .result = "\x91\x7c\xf6\x9e\xbd\x68\xb2\xec"
++ "\x9b\x9f\xe9\xa3\xea\xdd\xa6\x92"
++ "\xcd\x43\xd2\xf5\x95\x98\xed\x85"
++ "\x8c\x02\xc2\x65\x2f\xbf\x92\x2e",
+ .rlen = 32,
+ }, { /* XTS-AES 2 */
+- .key = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+- 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
++ .key = "\x11\x11\x11\x11\x11\x11\x11\x11"
++ "\x11\x11\x11\x11\x11\x11\x11\x11"
++ "\x22\x22\x22\x22\x22\x22\x22\x22"
++ "\x22\x22\x22\x22\x22\x22\x22\x22",
+ .klen = 32,
+- .iv = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+- .input = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+- 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+- 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+- 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
++ .iv = "\x33\x33\x33\x33\x33\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
++ .input = "\x44\x44\x44\x44\x44\x44\x44\x44"
++ "\x44\x44\x44\x44\x44\x44\x44\x44"
++ "\x44\x44\x44\x44\x44\x44\x44\x44"
++ "\x44\x44\x44\x44\x44\x44\x44\x44",
+ .ilen = 32,
+- .result = { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e,
+- 0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b,
+- 0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4,
+- 0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 },
++ .result = "\xc4\x54\x18\x5e\x6a\x16\x93\x6e"
++ "\x39\x33\x40\x38\xac\xef\x83\x8b"
++ "\xfb\x18\x6f\xff\x74\x80\xad\xc4"
++ "\x28\x93\x82\xec\xd6\xd3\x94\xf0",
+ .rlen = 32,
+ }, { /* XTS-AES 3 */
+- .key = { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
+- 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
+- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
++ .key = "\xff\xfe\xfd\xfc\xfb\xfa\xf9\xf8"
++ "\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0"
++ "\x22\x22\x22\x22\x22\x22\x22\x22"
++ "\x22\x22\x22\x22\x22\x22\x22\x22",
+ .klen = 32,
+- .iv = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+- .input = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+- 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+- 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+- 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
++ .iv = "\x33\x33\x33\x33\x33\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
++ .input = "\x44\x44\x44\x44\x44\x44\x44\x44"
++ "\x44\x44\x44\x44\x44\x44\x44\x44"
++ "\x44\x44\x44\x44\x44\x44\x44\x44"
++ "\x44\x44\x44\x44\x44\x44\x44\x44",
+ .ilen = 32,
+- .result = { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a,
+- 0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2,
+- 0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53,
+- 0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 },
++ .result = "\xaf\x85\x33\x6b\x59\x7a\xfc\x1a"
++ "\x90\x0b\x2e\xb2\x1e\xc9\x49\xd2"
++ "\x92\xdf\x4c\x04\x7e\x0b\x21\x53"
++ "\x21\x86\xa5\x97\x1a\x22\x7a\x89",
+ .rlen = 32,
+ }, { /* XTS-AES 4 */
+- .key = { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45,
+- 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26,
+- 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93,
+- 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95 },
++ .key = "\x27\x18\x28\x18\x28\x45\x90\x45"
++ "\x23\x53\x60\x28\x74\x71\x35\x26"
++ "\x31\x41\x59\x26\x53\x58\x97\x93"
++ "\x23\x84\x62\x64\x33\x83\x27\x95",
+ .klen = 32,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+- .input = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+- 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+- 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+- 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+- 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+- 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+- 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+- 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+- 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+- 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+- 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+- 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+- 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+- 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+- 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+- 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+- 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+- 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+- 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+- 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+- 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+- 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+- 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+- 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+- 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+- 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+- 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+- 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+- 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+- 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+- 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+- 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+- 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+- 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+- 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+- 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+- 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+- 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+- 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+- 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+- 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+- 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+- 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+- 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+- 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+- 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+- 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+- 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+- 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
++ .input = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
++ "\x20\x21\x22\x23\x24\x25\x26\x27"
++ "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
++ "\x30\x31\x32\x33\x34\x35\x36\x37"
++ "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
++ "\x40\x41\x42\x43\x44\x45\x46\x47"
++ "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
++ "\x50\x51\x52\x53\x54\x55\x56\x57"
++ "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
++ "\x60\x61\x62\x63\x64\x65\x66\x67"
++ "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
++ "\x70\x71\x72\x73\x74\x75\x76\x77"
++ "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
++ "\x80\x81\x82\x83\x84\x85\x86\x87"
++ "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
++ "\x90\x91\x92\x93\x94\x95\x96\x97"
++ "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
++ "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
++ "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
++ "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
++ "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
++ "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++ "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
++ "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
++ "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
++ "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
++ "\xe8\xe9\xea\xeb\xec\xed\xee\xef"
++ "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
++ "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
++ "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
++ "\x20\x21\x22\x23\x24\x25\x26\x27"
++ "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
++ "\x30\x31\x32\x33\x34\x35\x36\x37"
++ "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
++ "\x40\x41\x42\x43\x44\x45\x46\x47"
++ "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
++ "\x50\x51\x52\x53\x54\x55\x56\x57"
++ "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
++ "\x60\x61\x62\x63\x64\x65\x66\x67"
++ "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
++ "\x70\x71\x72\x73\x74\x75\x76\x77"
++ "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
++ "\x80\x81\x82\x83\x84\x85\x86\x87"
++ "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
++ "\x90\x91\x92\x93\x94\x95\x96\x97"
++ "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
++ "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
++ "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
++ "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
++ "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
++ "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++ "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
++ "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
++ "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
++ "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
++ "\xe8\xe9\xea\xeb\xec\xed\xee\xef"
++ "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
++ "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+ .ilen = 512,
+- .result = { 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76,
+- 0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2,
+- 0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25,
+- 0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c,
+- 0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f,
+- 0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00,
+- 0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad,
+- 0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12,
+- 0x32, 0x80, 0x63, 0xfd, 0x2a, 0xab, 0x53, 0xe5,
+- 0xea, 0x1e, 0x0a, 0x9f, 0x33, 0x25, 0x00, 0xa5,
+- 0xdf, 0x94, 0x87, 0xd0, 0x7a, 0x5c, 0x92, 0xcc,
+- 0x51, 0x2c, 0x88, 0x66, 0xc7, 0xe8, 0x60, 0xce,
+- 0x93, 0xfd, 0xf1, 0x66, 0xa2, 0x49, 0x12, 0xb4,
+- 0x22, 0x97, 0x61, 0x46, 0xae, 0x20, 0xce, 0x84,
+- 0x6b, 0xb7, 0xdc, 0x9b, 0xa9, 0x4a, 0x76, 0x7a,
+- 0xae, 0xf2, 0x0c, 0x0d, 0x61, 0xad, 0x02, 0x65,
+- 0x5e, 0xa9, 0x2d, 0xc4, 0xc4, 0xe4, 0x1a, 0x89,
+- 0x52, 0xc6, 0x51, 0xd3, 0x31, 0x74, 0xbe, 0x51,
+- 0xa1, 0x0c, 0x42, 0x11, 0x10, 0xe6, 0xd8, 0x15,
+- 0x88, 0xed, 0xe8, 0x21, 0x03, 0xa2, 0x52, 0xd8,
+- 0xa7, 0x50, 0xe8, 0x76, 0x8d, 0xef, 0xff, 0xed,
+- 0x91, 0x22, 0x81, 0x0a, 0xae, 0xb9, 0x9f, 0x91,
+- 0x72, 0xaf, 0x82, 0xb6, 0x04, 0xdc, 0x4b, 0x8e,
+- 0x51, 0xbc, 0xb0, 0x82, 0x35, 0xa6, 0xf4, 0x34,
+- 0x13, 0x32, 0xe4, 0xca, 0x60, 0x48, 0x2a, 0x4b,
+- 0xa1, 0xa0, 0x3b, 0x3e, 0x65, 0x00, 0x8f, 0xc5,
+- 0xda, 0x76, 0xb7, 0x0b, 0xf1, 0x69, 0x0d, 0xb4,
+- 0xea, 0xe2, 0x9c, 0x5f, 0x1b, 0xad, 0xd0, 0x3c,
+- 0x5c, 0xcf, 0x2a, 0x55, 0xd7, 0x05, 0xdd, 0xcd,
+- 0x86, 0xd4, 0x49, 0x51, 0x1c, 0xeb, 0x7e, 0xc3,
+- 0x0b, 0xf1, 0x2b, 0x1f, 0xa3, 0x5b, 0x91, 0x3f,
+- 0x9f, 0x74, 0x7a, 0x8a, 0xfd, 0x1b, 0x13, 0x0e,
+- 0x94, 0xbf, 0xf9, 0x4e, 0xff, 0xd0, 0x1a, 0x91,
+- 0x73, 0x5c, 0xa1, 0x72, 0x6a, 0xcd, 0x0b, 0x19,
+- 0x7c, 0x4e, 0x5b, 0x03, 0x39, 0x36, 0x97, 0xe1,
+- 0x26, 0x82, 0x6f, 0xb6, 0xbb, 0xde, 0x8e, 0xcc,
+- 0x1e, 0x08, 0x29, 0x85, 0x16, 0xe2, 0xc9, 0xed,
+- 0x03, 0xff, 0x3c, 0x1b, 0x78, 0x60, 0xf6, 0xde,
+- 0x76, 0xd4, 0xce, 0xcd, 0x94, 0xc8, 0x11, 0x98,
+- 0x55, 0xef, 0x52, 0x97, 0xca, 0x67, 0xe9, 0xf3,
+- 0xe7, 0xff, 0x72, 0xb1, 0xe9, 0x97, 0x85, 0xca,
+- 0x0a, 0x7e, 0x77, 0x20, 0xc5, 0xb3, 0x6d, 0xc6,
+- 0xd7, 0x2c, 0xac, 0x95, 0x74, 0xc8, 0xcb, 0xbc,
+- 0x2f, 0x80, 0x1e, 0x23, 0xe5, 0x6f, 0xd3, 0x44,
+- 0xb0, 0x7f, 0x22, 0x15, 0x4b, 0xeb, 0xa0, 0xf0,
+- 0x8c, 0xe8, 0x89, 0x1e, 0x64, 0x3e, 0xd9, 0x95,
+- 0xc9, 0x4d, 0x9a, 0x69, 0xc9, 0xf1, 0xb5, 0xf4,
+- 0x99, 0x02, 0x7a, 0x78, 0x57, 0x2a, 0xee, 0xbd,
+- 0x74, 0xd2, 0x0c, 0xc3, 0x98, 0x81, 0xc2, 0x13,
+- 0xee, 0x77, 0x0b, 0x10, 0x10, 0xe4, 0xbe, 0xa7,
+- 0x18, 0x84, 0x69, 0x77, 0xae, 0x11, 0x9f, 0x7a,
+- 0x02, 0x3a, 0xb5, 0x8c, 0xca, 0x0a, 0xd7, 0x52,
+- 0xaf, 0xe6, 0x56, 0xbb, 0x3c, 0x17, 0x25, 0x6a,
+- 0x9f, 0x6e, 0x9b, 0xf1, 0x9f, 0xdd, 0x5a, 0x38,
+- 0xfc, 0x82, 0xbb, 0xe8, 0x72, 0xc5, 0x53, 0x9e,
+- 0xdb, 0x60, 0x9e, 0xf4, 0xf7, 0x9c, 0x20, 0x3e,
+- 0xbb, 0x14, 0x0f, 0x2e, 0x58, 0x3c, 0xb2, 0xad,
+- 0x15, 0xb4, 0xaa, 0x5b, 0x65, 0x50, 0x16, 0xa8,
+- 0x44, 0x92, 0x77, 0xdb, 0xd4, 0x77, 0xef, 0x2c,
+- 0x8d, 0x6c, 0x01, 0x7d, 0xb7, 0x38, 0xb1, 0x8d,
+- 0xeb, 0x4a, 0x42, 0x7d, 0x19, 0x23, 0xce, 0x3f,
+- 0xf2, 0x62, 0x73, 0x57, 0x79, 0xa4, 0x18, 0xf2,
+- 0x0a, 0x28, 0x2d, 0xf9, 0x20, 0x14, 0x7b, 0xea,
+- 0xbe, 0x42, 0x1e, 0xe5, 0x31, 0x9d, 0x05, 0x68 },
++ .result = "\x27\xa7\x47\x9b\xef\xa1\xd4\x76"
++ "\x48\x9f\x30\x8c\xd4\xcf\xa6\xe2"
++ "\xa9\x6e\x4b\xbe\x32\x08\xff\x25"
++ "\x28\x7d\xd3\x81\x96\x16\xe8\x9c"
++ "\xc7\x8c\xf7\xf5\xe5\x43\x44\x5f"
++ "\x83\x33\xd8\xfa\x7f\x56\x00\x00"
++ "\x05\x27\x9f\xa5\xd8\xb5\xe4\xad"
++ "\x40\xe7\x36\xdd\xb4\xd3\x54\x12"
++ "\x32\x80\x63\xfd\x2a\xab\x53\xe5"
++ "\xea\x1e\x0a\x9f\x33\x25\x00\xa5"
++ "\xdf\x94\x87\xd0\x7a\x5c\x92\xcc"
++ "\x51\x2c\x88\x66\xc7\xe8\x60\xce"
++ "\x93\xfd\xf1\x66\xa2\x49\x12\xb4"
++ "\x22\x97\x61\x46\xae\x20\xce\x84"
++ "\x6b\xb7\xdc\x9b\xa9\x4a\x76\x7a"
++ "\xae\xf2\x0c\x0d\x61\xad\x02\x65"
++ "\x5e\xa9\x2d\xc4\xc4\xe4\x1a\x89"
++ "\x52\xc6\x51\xd3\x31\x74\xbe\x51"
++ "\xa1\x0c\x42\x11\x10\xe6\xd8\x15"
++ "\x88\xed\xe8\x21\x03\xa2\x52\xd8"
++ "\xa7\x50\xe8\x76\x8d\xef\xff\xed"
++ "\x91\x22\x81\x0a\xae\xb9\x9f\x91"
++ "\x72\xaf\x82\xb6\x04\xdc\x4b\x8e"
++ "\x51\xbc\xb0\x82\x35\xa6\xf4\x34"
++ "\x13\x32\xe4\xca\x60\x48\x2a\x4b"
++ "\xa1\xa0\x3b\x3e\x65\x00\x8f\xc5"
++ "\xda\x76\xb7\x0b\xf1\x69\x0d\xb4"
++ "\xea\xe2\x9c\x5f\x1b\xad\xd0\x3c"
++ "\x5c\xcf\x2a\x55\xd7\x05\xdd\xcd"
++ "\x86\xd4\x49\x51\x1c\xeb\x7e\xc3"
++ "\x0b\xf1\x2b\x1f\xa3\x5b\x91\x3f"
++ "\x9f\x74\x7a\x8a\xfd\x1b\x13\x0e"
++ "\x94\xbf\xf9\x4e\xff\xd0\x1a\x91"
++ "\x73\x5c\xa1\x72\x6a\xcd\x0b\x19"
++ "\x7c\x4e\x5b\x03\x39\x36\x97\xe1"
++ "\x26\x82\x6f\xb6\xbb\xde\x8e\xcc"
++ "\x1e\x08\x29\x85\x16\xe2\xc9\xed"
++ "\x03\xff\x3c\x1b\x78\x60\xf6\xde"
++ "\x76\xd4\xce\xcd\x94\xc8\x11\x98"
++ "\x55\xef\x52\x97\xca\x67\xe9\xf3"
++ "\xe7\xff\x72\xb1\xe9\x97\x85\xca"
++ "\x0a\x7e\x77\x20\xc5\xb3\x6d\xc6"
++ "\xd7\x2c\xac\x95\x74\xc8\xcb\xbc"
++ "\x2f\x80\x1e\x23\xe5\x6f\xd3\x44"
++ "\xb0\x7f\x22\x15\x4b\xeb\xa0\xf0"
++ "\x8c\xe8\x89\x1e\x64\x3e\xd9\x95"
++ "\xc9\x4d\x9a\x69\xc9\xf1\xb5\xf4"
++ "\x99\x02\x7a\x78\x57\x2a\xee\xbd"
++ "\x74\xd2\x0c\xc3\x98\x81\xc2\x13"
++ "\xee\x77\x0b\x10\x10\xe4\xbe\xa7"
++ "\x18\x84\x69\x77\xae\x11\x9f\x7a"
++ "\x02\x3a\xb5\x8c\xca\x0a\xd7\x52"
++ "\xaf\xe6\x56\xbb\x3c\x17\x25\x6a"
++ "\x9f\x6e\x9b\xf1\x9f\xdd\x5a\x38"
++ "\xfc\x82\xbb\xe8\x72\xc5\x53\x9e"
++ "\xdb\x60\x9e\xf4\xf7\x9c\x20\x3e"
++ "\xbb\x14\x0f\x2e\x58\x3c\xb2\xad"
++ "\x15\xb4\xaa\x5b\x65\x50\x16\xa8"
++ "\x44\x92\x77\xdb\xd4\x77\xef\x2c"
++ "\x8d\x6c\x01\x7d\xb7\x38\xb1\x8d"
++ "\xeb\x4a\x42\x7d\x19\x23\xce\x3f"
++ "\xf2\x62\x73\x57\x79\xa4\x18\xf2"
++ "\x0a\x28\x2d\xf9\x20\x14\x7b\xea"
++ "\xbe\x42\x1e\xe5\x31\x9d\x05\x68",
+ .rlen = 512,
+ }
+ };
+@@ -3257,196 +3281,196 @@ static struct cipher_testvec aes_xts_enc_tv_template[] = {
+ static struct cipher_testvec aes_xts_dec_tv_template[] = {
+ /* http://grouper.ieee.org/groups/1619/email/pdf00086.pdf */
+ { /* XTS-AES 1 */
+- .key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .key = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .klen = 32,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+- .input = { 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec,
+- 0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92,
+- 0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85,
+- 0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
++ .input = "\x91\x7c\xf6\x9e\xbd\x68\xb2\xec"
++ "\x9b\x9f\xe9\xa3\xea\xdd\xa6\x92"
++ "\xcd\x43\xd2\xf5\x95\x98\xed\x85"
++ "\x8c\x02\xc2\x65\x2f\xbf\x92\x2e",
+ .ilen = 32,
+- .result = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .result = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .rlen = 32,
+ }, { /* XTS-AES 2 */
+- .key = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+- 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
++ .key = "\x11\x11\x11\x11\x11\x11\x11\x11"
++ "\x11\x11\x11\x11\x11\x11\x11\x11"
++ "\x22\x22\x22\x22\x22\x22\x22\x22"
++ "\x22\x22\x22\x22\x22\x22\x22\x22",
+ .klen = 32,
+- .iv = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+- .input = { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e,
+- 0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b,
+- 0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4,
+- 0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 },
++ .iv = "\x33\x33\x33\x33\x33\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
++ .input = "\xc4\x54\x18\x5e\x6a\x16\x93\x6e"
++ "\x39\x33\x40\x38\xac\xef\x83\x8b"
++ "\xfb\x18\x6f\xff\x74\x80\xad\xc4"
++ "\x28\x93\x82\xec\xd6\xd3\x94\xf0",
+ .ilen = 32,
+- .result = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+- 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+- 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+- 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
++ .result = "\x44\x44\x44\x44\x44\x44\x44\x44"
++ "\x44\x44\x44\x44\x44\x44\x44\x44"
++ "\x44\x44\x44\x44\x44\x44\x44\x44"
++ "\x44\x44\x44\x44\x44\x44\x44\x44",
+ .rlen = 32,
+ }, { /* XTS-AES 3 */
+- .key = { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
+- 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
+- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+- 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
++ .key = "\xff\xfe\xfd\xfc\xfb\xfa\xf9\xf8"
++ "\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0"
++ "\x22\x22\x22\x22\x22\x22\x22\x22"
++ "\x22\x22\x22\x22\x22\x22\x22\x22",
+ .klen = 32,
+- .iv = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+- .input = { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a,
+- 0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2,
+- 0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53,
+- 0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 },
++ .iv = "\x33\x33\x33\x33\x33\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
++ .input = "\xaf\x85\x33\x6b\x59\x7a\xfc\x1a"
++ "\x90\x0b\x2e\xb2\x1e\xc9\x49\xd2"
++ "\x92\xdf\x4c\x04\x7e\x0b\x21\x53"
++ "\x21\x86\xa5\x97\x1a\x22\x7a\x89",
+ .ilen = 32,
+- .result = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+- 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+- 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+- 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
++ .result = "\x44\x44\x44\x44\x44\x44\x44\x44"
++ "\x44\x44\x44\x44\x44\x44\x44\x44"
++ "\x44\x44\x44\x44\x44\x44\x44\x44"
++ "\x44\x44\x44\x44\x44\x44\x44\x44",
+ .rlen = 32,
+ }, { /* XTS-AES 4 */
+- .key = { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45,
+- 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26,
+- 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93,
+- 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95 },
++ .key = "\x27\x18\x28\x18\x28\x45\x90\x45"
++ "\x23\x53\x60\x28\x74\x71\x35\x26"
++ "\x31\x41\x59\x26\x53\x58\x97\x93"
++ "\x23\x84\x62\x64\x33\x83\x27\x95",
+ .klen = 32,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+- .input = { 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76,
+- 0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2,
+- 0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25,
+- 0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c,
+- 0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f,
+- 0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00,
+- 0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad,
+- 0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12,
+- 0x32, 0x80, 0x63, 0xfd, 0x2a, 0xab, 0x53, 0xe5,
+- 0xea, 0x1e, 0x0a, 0x9f, 0x33, 0x25, 0x00, 0xa5,
+- 0xdf, 0x94, 0x87, 0xd0, 0x7a, 0x5c, 0x92, 0xcc,
+- 0x51, 0x2c, 0x88, 0x66, 0xc7, 0xe8, 0x60, 0xce,
+- 0x93, 0xfd, 0xf1, 0x66, 0xa2, 0x49, 0x12, 0xb4,
+- 0x22, 0x97, 0x61, 0x46, 0xae, 0x20, 0xce, 0x84,
+- 0x6b, 0xb7, 0xdc, 0x9b, 0xa9, 0x4a, 0x76, 0x7a,
+- 0xae, 0xf2, 0x0c, 0x0d, 0x61, 0xad, 0x02, 0x65,
+- 0x5e, 0xa9, 0x2d, 0xc4, 0xc4, 0xe4, 0x1a, 0x89,
+- 0x52, 0xc6, 0x51, 0xd3, 0x31, 0x74, 0xbe, 0x51,
+- 0xa1, 0x0c, 0x42, 0x11, 0x10, 0xe6, 0xd8, 0x15,
+- 0x88, 0xed, 0xe8, 0x21, 0x03, 0xa2, 0x52, 0xd8,
+- 0xa7, 0x50, 0xe8, 0x76, 0x8d, 0xef, 0xff, 0xed,
+- 0x91, 0x22, 0x81, 0x0a, 0xae, 0xb9, 0x9f, 0x91,
+- 0x72, 0xaf, 0x82, 0xb6, 0x04, 0xdc, 0x4b, 0x8e,
+- 0x51, 0xbc, 0xb0, 0x82, 0x35, 0xa6, 0xf4, 0x34,
+- 0x13, 0x32, 0xe4, 0xca, 0x60, 0x48, 0x2a, 0x4b,
+- 0xa1, 0xa0, 0x3b, 0x3e, 0x65, 0x00, 0x8f, 0xc5,
+- 0xda, 0x76, 0xb7, 0x0b, 0xf1, 0x69, 0x0d, 0xb4,
+- 0xea, 0xe2, 0x9c, 0x5f, 0x1b, 0xad, 0xd0, 0x3c,
+- 0x5c, 0xcf, 0x2a, 0x55, 0xd7, 0x05, 0xdd, 0xcd,
+- 0x86, 0xd4, 0x49, 0x51, 0x1c, 0xeb, 0x7e, 0xc3,
+- 0x0b, 0xf1, 0x2b, 0x1f, 0xa3, 0x5b, 0x91, 0x3f,
+- 0x9f, 0x74, 0x7a, 0x8a, 0xfd, 0x1b, 0x13, 0x0e,
+- 0x94, 0xbf, 0xf9, 0x4e, 0xff, 0xd0, 0x1a, 0x91,
+- 0x73, 0x5c, 0xa1, 0x72, 0x6a, 0xcd, 0x0b, 0x19,
+- 0x7c, 0x4e, 0x5b, 0x03, 0x39, 0x36, 0x97, 0xe1,
+- 0x26, 0x82, 0x6f, 0xb6, 0xbb, 0xde, 0x8e, 0xcc,
+- 0x1e, 0x08, 0x29, 0x85, 0x16, 0xe2, 0xc9, 0xed,
+- 0x03, 0xff, 0x3c, 0x1b, 0x78, 0x60, 0xf6, 0xde,
+- 0x76, 0xd4, 0xce, 0xcd, 0x94, 0xc8, 0x11, 0x98,
+- 0x55, 0xef, 0x52, 0x97, 0xca, 0x67, 0xe9, 0xf3,
+- 0xe7, 0xff, 0x72, 0xb1, 0xe9, 0x97, 0x85, 0xca,
+- 0x0a, 0x7e, 0x77, 0x20, 0xc5, 0xb3, 0x6d, 0xc6,
+- 0xd7, 0x2c, 0xac, 0x95, 0x74, 0xc8, 0xcb, 0xbc,
+- 0x2f, 0x80, 0x1e, 0x23, 0xe5, 0x6f, 0xd3, 0x44,
+- 0xb0, 0x7f, 0x22, 0x15, 0x4b, 0xeb, 0xa0, 0xf0,
+- 0x8c, 0xe8, 0x89, 0x1e, 0x64, 0x3e, 0xd9, 0x95,
+- 0xc9, 0x4d, 0x9a, 0x69, 0xc9, 0xf1, 0xb5, 0xf4,
+- 0x99, 0x02, 0x7a, 0x78, 0x57, 0x2a, 0xee, 0xbd,
+- 0x74, 0xd2, 0x0c, 0xc3, 0x98, 0x81, 0xc2, 0x13,
+- 0xee, 0x77, 0x0b, 0x10, 0x10, 0xe4, 0xbe, 0xa7,
+- 0x18, 0x84, 0x69, 0x77, 0xae, 0x11, 0x9f, 0x7a,
+- 0x02, 0x3a, 0xb5, 0x8c, 0xca, 0x0a, 0xd7, 0x52,
+- 0xaf, 0xe6, 0x56, 0xbb, 0x3c, 0x17, 0x25, 0x6a,
+- 0x9f, 0x6e, 0x9b, 0xf1, 0x9f, 0xdd, 0x5a, 0x38,
+- 0xfc, 0x82, 0xbb, 0xe8, 0x72, 0xc5, 0x53, 0x9e,
+- 0xdb, 0x60, 0x9e, 0xf4, 0xf7, 0x9c, 0x20, 0x3e,
+- 0xbb, 0x14, 0x0f, 0x2e, 0x58, 0x3c, 0xb2, 0xad,
+- 0x15, 0xb4, 0xaa, 0x5b, 0x65, 0x50, 0x16, 0xa8,
+- 0x44, 0x92, 0x77, 0xdb, 0xd4, 0x77, 0xef, 0x2c,
+- 0x8d, 0x6c, 0x01, 0x7d, 0xb7, 0x38, 0xb1, 0x8d,
+- 0xeb, 0x4a, 0x42, 0x7d, 0x19, 0x23, 0xce, 0x3f,
+- 0xf2, 0x62, 0x73, 0x57, 0x79, 0xa4, 0x18, 0xf2,
+- 0x0a, 0x28, 0x2d, 0xf9, 0x20, 0x14, 0x7b, 0xea,
+- 0xbe, 0x42, 0x1e, 0xe5, 0x31, 0x9d, 0x05, 0x68 },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
++ .input = "\x27\xa7\x47\x9b\xef\xa1\xd4\x76"
++ "\x48\x9f\x30\x8c\xd4\xcf\xa6\xe2"
++ "\xa9\x6e\x4b\xbe\x32\x08\xff\x25"
++ "\x28\x7d\xd3\x81\x96\x16\xe8\x9c"
++ "\xc7\x8c\xf7\xf5\xe5\x43\x44\x5f"
++ "\x83\x33\xd8\xfa\x7f\x56\x00\x00"
++ "\x05\x27\x9f\xa5\xd8\xb5\xe4\xad"
++ "\x40\xe7\x36\xdd\xb4\xd3\x54\x12"
++ "\x32\x80\x63\xfd\x2a\xab\x53\xe5"
++ "\xea\x1e\x0a\x9f\x33\x25\x00\xa5"
++ "\xdf\x94\x87\xd0\x7a\x5c\x92\xcc"
++ "\x51\x2c\x88\x66\xc7\xe8\x60\xce"
++ "\x93\xfd\xf1\x66\xa2\x49\x12\xb4"
++ "\x22\x97\x61\x46\xae\x20\xce\x84"
++ "\x6b\xb7\xdc\x9b\xa9\x4a\x76\x7a"
++ "\xae\xf2\x0c\x0d\x61\xad\x02\x65"
++ "\x5e\xa9\x2d\xc4\xc4\xe4\x1a\x89"
++ "\x52\xc6\x51\xd3\x31\x74\xbe\x51"
++ "\xa1\x0c\x42\x11\x10\xe6\xd8\x15"
++ "\x88\xed\xe8\x21\x03\xa2\x52\xd8"
++ "\xa7\x50\xe8\x76\x8d\xef\xff\xed"
++ "\x91\x22\x81\x0a\xae\xb9\x9f\x91"
++ "\x72\xaf\x82\xb6\x04\xdc\x4b\x8e"
++ "\x51\xbc\xb0\x82\x35\xa6\xf4\x34"
++ "\x13\x32\xe4\xca\x60\x48\x2a\x4b"
++ "\xa1\xa0\x3b\x3e\x65\x00\x8f\xc5"
++ "\xda\x76\xb7\x0b\xf1\x69\x0d\xb4"
++ "\xea\xe2\x9c\x5f\x1b\xad\xd0\x3c"
++ "\x5c\xcf\x2a\x55\xd7\x05\xdd\xcd"
++ "\x86\xd4\x49\x51\x1c\xeb\x7e\xc3"
++ "\x0b\xf1\x2b\x1f\xa3\x5b\x91\x3f"
++ "\x9f\x74\x7a\x8a\xfd\x1b\x13\x0e"
++ "\x94\xbf\xf9\x4e\xff\xd0\x1a\x91"
++ "\x73\x5c\xa1\x72\x6a\xcd\x0b\x19"
++ "\x7c\x4e\x5b\x03\x39\x36\x97\xe1"
++ "\x26\x82\x6f\xb6\xbb\xde\x8e\xcc"
++ "\x1e\x08\x29\x85\x16\xe2\xc9\xed"
++ "\x03\xff\x3c\x1b\x78\x60\xf6\xde"
++ "\x76\xd4\xce\xcd\x94\xc8\x11\x98"
++ "\x55\xef\x52\x97\xca\x67\xe9\xf3"
++ "\xe7\xff\x72\xb1\xe9\x97\x85\xca"
++ "\x0a\x7e\x77\x20\xc5\xb3\x6d\xc6"
++ "\xd7\x2c\xac\x95\x74\xc8\xcb\xbc"
++ "\x2f\x80\x1e\x23\xe5\x6f\xd3\x44"
++ "\xb0\x7f\x22\x15\x4b\xeb\xa0\xf0"
++ "\x8c\xe8\x89\x1e\x64\x3e\xd9\x95"
++ "\xc9\x4d\x9a\x69\xc9\xf1\xb5\xf4"
++ "\x99\x02\x7a\x78\x57\x2a\xee\xbd"
++ "\x74\xd2\x0c\xc3\x98\x81\xc2\x13"
++ "\xee\x77\x0b\x10\x10\xe4\xbe\xa7"
++ "\x18\x84\x69\x77\xae\x11\x9f\x7a"
++ "\x02\x3a\xb5\x8c\xca\x0a\xd7\x52"
++ "\xaf\xe6\x56\xbb\x3c\x17\x25\x6a"
++ "\x9f\x6e\x9b\xf1\x9f\xdd\x5a\x38"
++ "\xfc\x82\xbb\xe8\x72\xc5\x53\x9e"
++ "\xdb\x60\x9e\xf4\xf7\x9c\x20\x3e"
++ "\xbb\x14\x0f\x2e\x58\x3c\xb2\xad"
++ "\x15\xb4\xaa\x5b\x65\x50\x16\xa8"
++ "\x44\x92\x77\xdb\xd4\x77\xef\x2c"
++ "\x8d\x6c\x01\x7d\xb7\x38\xb1\x8d"
++ "\xeb\x4a\x42\x7d\x19\x23\xce\x3f"
++ "\xf2\x62\x73\x57\x79\xa4\x18\xf2"
++ "\x0a\x28\x2d\xf9\x20\x14\x7b\xea"
++ "\xbe\x42\x1e\xe5\x31\x9d\x05\x68",
+ .ilen = 512,
+- .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+- 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+- 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+- 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+- 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+- 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+- 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+- 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+- 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+- 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+- 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+- 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+- 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+- 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+- 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+- 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+- 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+- 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+- 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+- 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+- 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+- 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+- 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+- 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+- 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+- 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+- 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+- 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+- 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+- 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+- 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+- 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+- 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+- 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+- 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+- 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+- 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+- 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+- 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+- 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+- 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+- 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+- 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+- 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+- 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+- 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+- 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+- 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+- 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff },
++ .result = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
++ "\x20\x21\x22\x23\x24\x25\x26\x27"
++ "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
++ "\x30\x31\x32\x33\x34\x35\x36\x37"
++ "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
++ "\x40\x41\x42\x43\x44\x45\x46\x47"
++ "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
++ "\x50\x51\x52\x53\x54\x55\x56\x57"
++ "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
++ "\x60\x61\x62\x63\x64\x65\x66\x67"
++ "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
++ "\x70\x71\x72\x73\x74\x75\x76\x77"
++ "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
++ "\x80\x81\x82\x83\x84\x85\x86\x87"
++ "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
++ "\x90\x91\x92\x93\x94\x95\x96\x97"
++ "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
++ "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
++ "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
++ "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
++ "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
++ "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++ "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
++ "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
++ "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
++ "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
++ "\xe8\xe9\xea\xeb\xec\xed\xee\xef"
++ "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
++ "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
++ "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
++ "\x20\x21\x22\x23\x24\x25\x26\x27"
++ "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
++ "\x30\x31\x32\x33\x34\x35\x36\x37"
++ "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
++ "\x40\x41\x42\x43\x44\x45\x46\x47"
++ "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
++ "\x50\x51\x52\x53\x54\x55\x56\x57"
++ "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
++ "\x60\x61\x62\x63\x64\x65\x66\x67"
++ "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
++ "\x70\x71\x72\x73\x74\x75\x76\x77"
++ "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
++ "\x80\x81\x82\x83\x84\x85\x86\x87"
++ "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
++ "\x90\x91\x92\x93\x94\x95\x96\x97"
++ "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
++ "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
++ "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
++ "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
++ "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
++ "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++ "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
++ "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
++ "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
++ "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
++ "\xe8\xe9\xea\xeb\xec\xed\xee\xef"
++ "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
++ "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+ .rlen = 512,
+ }
+ };
+@@ -3454,1836 +3478,1841 @@ static struct cipher_testvec aes_xts_dec_tv_template[] = {
+
+ static struct cipher_testvec aes_ctr_enc_tv_template[] = {
+ { /* From RFC 3686 */
+- .key = { 0xae, 0x68, 0x52, 0xf8, 0x12, 0x10, 0x67, 0xcc,
+- 0x4b, 0xf7, 0xa5, 0x76, 0x55, 0x77, 0xf3, 0x9e,
+- 0x00, 0x00, 0x00, 0x30 },
++ .key = "\xae\x68\x52\xf8\x12\x10\x67\xcc"
++ "\x4b\xf7\xa5\x76\x55\x77\xf3\x9e"
++ "\x00\x00\x00\x30",
+ .klen = 20,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+- .input = { "Single block msg" },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00",
++ .input = "Single block msg",
+ .ilen = 16,
+- .result = { 0xe4, 0x09, 0x5d, 0x4f, 0xb7, 0xa7, 0xb3, 0x79,
+- 0x2d, 0x61, 0x75, 0xa3, 0x26, 0x13, 0x11, 0xb8 },
++ .result = "\xe4\x09\x5d\x4f\xb7\xa7\xb3\x79"
++ "\x2d\x61\x75\xa3\x26\x13\x11\xb8",
+ .rlen = 16,
+ }, {
+- .key = { 0x7e, 0x24, 0x06, 0x78, 0x17, 0xfa, 0xe0, 0xd7,
+- 0x43, 0xd6, 0xce, 0x1f, 0x32, 0x53, 0x91, 0x63,
+- 0x00, 0x6c, 0xb6, 0xdb },
++ .key = "\x7e\x24\x06\x78\x17\xfa\xe0\xd7"
++ "\x43\xd6\xce\x1f\x32\x53\x91\x63"
++ "\x00\x6c\xb6\xdb",
+ .klen = 20,
+- .iv = { 0xc0, 0x54, 0x3b, 0x59, 0xda, 0x48, 0xd9, 0x0b },
+- .input = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+- .ilen = 32,
+- .result = { 0x51, 0x04, 0xa1, 0x06, 0x16, 0x8a, 0x72, 0xd9,
+- 0x79, 0x0d, 0x41, 0xee, 0x8e, 0xda, 0xd3, 0x88,
+- 0xeb, 0x2e, 0x1e, 0xfc, 0x46, 0xda, 0x57, 0xc8,
+- 0xfc, 0xe6, 0x30, 0xdf, 0x91, 0x41, 0xbe, 0x28 },
++ .iv = "\xc0\x54\x3b\x59\xda\x48\xd9\x0b",
++ .input = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
++ .ilen = 32,
++ .result = "\x51\x04\xa1\x06\x16\x8a\x72\xd9"
++ "\x79\x0d\x41\xee\x8e\xda\xd3\x88"
++ "\xeb\x2e\x1e\xfc\x46\xda\x57\xc8"
++ "\xfc\xe6\x30\xdf\x91\x41\xbe\x28",
+ .rlen = 32,
+ }, {
+- .key = { 0x16, 0xaf, 0x5b, 0x14, 0x5f, 0xc9, 0xf5, 0x79,
+- 0xc1, 0x75, 0xf9, 0x3e, 0x3b, 0xfb, 0x0e, 0xed,
+- 0x86, 0x3d, 0x06, 0xcc, 0xfd, 0xb7, 0x85, 0x15,
+- 0x00, 0x00, 0x00, 0x48 },
+- .klen = 28,
+- .iv = { 0x36, 0x73, 0x3c, 0x14, 0x7d, 0x6d, 0x93, 0xcb },
+- .input = { "Single block msg" },
+- .ilen = 16,
+- .result = { 0x4b, 0x55, 0x38, 0x4f, 0xe2, 0x59, 0xc9, 0xc8,
+- 0x4e, 0x79, 0x35, 0xa0, 0x03, 0xcb, 0xe9, 0x28 },
++ .key = "\x16\xaf\x5b\x14\x5f\xc9\xf5\x79"
++ "\xc1\x75\xf9\x3e\x3b\xfb\x0e\xed"
++ "\x86\x3d\x06\xcc\xfd\xb7\x85\x15"
++ "\x00\x00\x00\x48",
++ .klen = 28,
++ .iv = "\x36\x73\x3c\x14\x7d\x6d\x93\xcb",
++ .input = "Single block msg",
++ .ilen = 16,
++ .result = "\x4b\x55\x38\x4f\xe2\x59\xc9\xc8"
++ "\x4e\x79\x35\xa0\x03\xcb\xe9\x28",
+ .rlen = 16,
+ }, {
+- .key = { 0x7c, 0x5c, 0xb2, 0x40, 0x1b, 0x3d, 0xc3, 0x3c,
+- 0x19, 0xe7, 0x34, 0x08, 0x19, 0xe0, 0xf6, 0x9c,
+- 0x67, 0x8c, 0x3d, 0xb8, 0xe6, 0xf6, 0xa9, 0x1a,
+- 0x00, 0x96, 0xb0, 0x3b },
++ .key = "\x7c\x5c\xb2\x40\x1b\x3d\xc3\x3c"
++ "\x19\xe7\x34\x08\x19\xe0\xf6\x9c"
++ "\x67\x8c\x3d\xb8\xe6\xf6\xa9\x1a"
++ "\x00\x96\xb0\x3b",
+ .klen = 28,
+- .iv = { 0x02, 0x0c, 0x6e, 0xad, 0xc2, 0xcb, 0x50, 0x0d },
+- .input = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++ .iv = "\x02\x0c\x6e\xad\xc2\xcb\x50\x0d",
++ .input = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ .ilen = 32,
+- .result = { 0x45, 0x32, 0x43, 0xfc, 0x60, 0x9b, 0x23, 0x32,
+- 0x7e, 0xdf, 0xaa, 0xfa, 0x71, 0x31, 0xcd, 0x9f,
+- 0x84, 0x90, 0x70, 0x1c, 0x5a, 0xd4, 0xa7, 0x9c,
+- 0xfc, 0x1f, 0xe0, 0xff, 0x42, 0xf4, 0xfb, 0x00 },
+- .rlen = 32,
+- }, {
+- .key = { 0x77, 0x6b, 0xef, 0xf2, 0x85, 0x1d, 0xb0, 0x6f,
+- 0x4c, 0x8a, 0x05, 0x42, 0xc8, 0x69, 0x6f, 0x6c,
+- 0x6a, 0x81, 0xaf, 0x1e, 0xec, 0x96, 0xb4, 0xd3,
+- 0x7f, 0xc1, 0xd6, 0x89, 0xe6, 0xc1, 0xc1, 0x04,
+- 0x00, 0x00, 0x00, 0x60 },
++ .result = "\x45\x32\x43\xfc\x60\x9b\x23\x32"
++ "\x7e\xdf\xaa\xfa\x71\x31\xcd\x9f"
++ "\x84\x90\x70\x1c\x5a\xd4\xa7\x9c"
++ "\xfc\x1f\xe0\xff\x42\xf4\xfb\x00",
++ .rlen = 32,
++ }, {
++ .key = "\x77\x6b\xef\xf2\x85\x1d\xb0\x6f"
++ "\x4c\x8a\x05\x42\xc8\x69\x6f\x6c"
++ "\x6a\x81\xaf\x1e\xec\x96\xb4\xd3"
++ "\x7f\xc1\xd6\x89\xe6\xc1\xc1\x04"
++ "\x00\x00\x00\x60",
+ .klen = 36,
+- .iv = { 0xdb, 0x56, 0x72, 0xc9, 0x7a, 0xa8, 0xf0, 0xb2 },
+- .input = { "Single block msg" },
++ .iv = "\xdb\x56\x72\xc9\x7a\xa8\xf0\xb2",
++ .input = "Single block msg",
+ .ilen = 16,
+- .result = { 0x14, 0x5a, 0xd0, 0x1d, 0xbf, 0x82, 0x4e, 0xc7,
+- 0x56, 0x08, 0x63, 0xdc, 0x71, 0xe3, 0xe0, 0xc0 },
+- .rlen = 16,
+- }, {
+- .key = { 0xf6, 0xd6, 0x6d, 0x6b, 0xd5, 0x2d, 0x59, 0xbb,
+- 0x07, 0x96, 0x36, 0x58, 0x79, 0xef, 0xf8, 0x86,
+- 0xc6, 0x6d, 0xd5, 0x1a, 0x5b, 0x6a, 0x99, 0x74,
+- 0x4b, 0x50, 0x59, 0x0c, 0x87, 0xa2, 0x38, 0x84,
+- 0x00, 0xfa, 0xac, 0x24 },
+- .klen = 36,
+- .iv = { 0xc1, 0x58, 0x5e, 0xf1, 0x5a, 0x43, 0xd8, 0x75 },
+- .input = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++ .result = "\x14\x5a\xd0\x1d\xbf\x82\x4e\xc7"
++ "\x56\x08\x63\xdc\x71\xe3\xe0\xc0",
++ .rlen = 16,
++ }, {
++ .key = "\xf6\xd6\x6d\x6b\xd5\x2d\x59\xbb"
++ "\x07\x96\x36\x58\x79\xef\xf8\x86"
++ "\xc6\x6d\xd5\x1a\x5b\x6a\x99\x74"
++ "\x4b\x50\x59\x0c\x87\xa2\x38\x84"
++ "\x00\xfa\xac\x24",
++ .klen = 36,
++ .iv = "\xc1\x58\x5e\xf1\x5a\x43\xd8\x75",
++ .input = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ .ilen = 32,
+- .result = { 0xf0, 0x5e, 0x23, 0x1b, 0x38, 0x94, 0x61, 0x2c,
+- 0x49, 0xee, 0x00, 0x0b, 0x80, 0x4e, 0xb2, 0xa9,
+- 0xb8, 0x30, 0x6b, 0x50, 0x8f, 0x83, 0x9d, 0x6a,
+- 0x55, 0x30, 0x83, 0x1d, 0x93, 0x44, 0xaf, 0x1c },
++ .result = "\xf0\x5e\x23\x1b\x38\x94\x61\x2c"
++ "\x49\xee\x00\x0b\x80\x4e\xb2\xa9"
++ "\xb8\x30\x6b\x50\x8f\x83\x9d\x6a"
++ "\x55\x30\x83\x1d\x93\x44\xaf\x1c",
+ .rlen = 32,
+ }, {
+ // generated using Crypto++
+- .key = {
+- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+- 0x00, 0x00, 0x00, 0x00,
+- },
++ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
++ "\x00\x00\x00\x00",
+ .klen = 32 + 4,
+- .iv = {
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- },
+- .input = {
+- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+- 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+- 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+- 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+- 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+- 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+- 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+- 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+- 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+- 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+- 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+- 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+- 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+- 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+- 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+- 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+- 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+- 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+- 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+- 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+- 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+- 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+- 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+- 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+- 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+- 0x00, 0x03, 0x06, 0x09, 0x0c, 0x0f, 0x12, 0x15,
+- 0x18, 0x1b, 0x1e, 0x21, 0x24, 0x27, 0x2a, 0x2d,
+- 0x30, 0x33, 0x36, 0x39, 0x3c, 0x3f, 0x42, 0x45,
+- 0x48, 0x4b, 0x4e, 0x51, 0x54, 0x57, 0x5a, 0x5d,
+- 0x60, 0x63, 0x66, 0x69, 0x6c, 0x6f, 0x72, 0x75,
+- 0x78, 0x7b, 0x7e, 0x81, 0x84, 0x87, 0x8a, 0x8d,
+- 0x90, 0x93, 0x96, 0x99, 0x9c, 0x9f, 0xa2, 0xa5,
+- 0xa8, 0xab, 0xae, 0xb1, 0xb4, 0xb7, 0xba, 0xbd,
+- 0xc0, 0xc3, 0xc6, 0xc9, 0xcc, 0xcf, 0xd2, 0xd5,
+- 0xd8, 0xdb, 0xde, 0xe1, 0xe4, 0xe7, 0xea, 0xed,
+- 0xf0, 0xf3, 0xf6, 0xf9, 0xfc, 0xff, 0x02, 0x05,
+- 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17, 0x1a, 0x1d,
+- 0x20, 0x23, 0x26, 0x29, 0x2c, 0x2f, 0x32, 0x35,
+- 0x38, 0x3b, 0x3e, 0x41, 0x44, 0x47, 0x4a, 0x4d,
+- 0x50, 0x53, 0x56, 0x59, 0x5c, 0x5f, 0x62, 0x65,
+- 0x68, 0x6b, 0x6e, 0x71, 0x74, 0x77, 0x7a, 0x7d,
+- 0x80, 0x83, 0x86, 0x89, 0x8c, 0x8f, 0x92, 0x95,
+- 0x98, 0x9b, 0x9e, 0xa1, 0xa4, 0xa7, 0xaa, 0xad,
+- 0xb0, 0xb3, 0xb6, 0xb9, 0xbc, 0xbf, 0xc2, 0xc5,
+- 0xc8, 0xcb, 0xce, 0xd1, 0xd4, 0xd7, 0xda, 0xdd,
+- 0xe0, 0xe3, 0xe6, 0xe9, 0xec, 0xef, 0xf2, 0xf5,
+- 0xf8, 0xfb, 0xfe, 0x01, 0x04, 0x07, 0x0a, 0x0d,
+- 0x10, 0x13, 0x16, 0x19, 0x1c, 0x1f, 0x22, 0x25,
+- 0x28, 0x2b, 0x2e, 0x31, 0x34, 0x37, 0x3a, 0x3d,
+- 0x40, 0x43, 0x46, 0x49, 0x4c, 0x4f, 0x52, 0x55,
+- 0x58, 0x5b, 0x5e, 0x61, 0x64, 0x67, 0x6a, 0x6d,
+- 0x70, 0x73, 0x76, 0x79, 0x7c, 0x7f, 0x82, 0x85,
+- 0x88, 0x8b, 0x8e, 0x91, 0x94, 0x97, 0x9a, 0x9d,
+- 0xa0, 0xa3, 0xa6, 0xa9, 0xac, 0xaf, 0xb2, 0xb5,
+- 0xb8, 0xbb, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
+- 0xd0, 0xd3, 0xd6, 0xd9, 0xdc, 0xdf, 0xe2, 0xe5,
+- 0xe8, 0xeb, 0xee, 0xf1, 0xf4, 0xf7, 0xfa, 0xfd,
+- 0x00, 0x05, 0x0a, 0x0f, 0x14, 0x19, 0x1e, 0x23,
+- 0x28, 0x2d, 0x32, 0x37, 0x3c, 0x41, 0x46, 0x4b,
+- 0x50, 0x55, 0x5a, 0x5f, 0x64, 0x69, 0x6e, 0x73,
+- 0x78, 0x7d, 0x82, 0x87, 0x8c, 0x91, 0x96, 0x9b,
+- 0xa0, 0xa5, 0xaa, 0xaf, 0xb4, 0xb9, 0xbe, 0xc3,
+- 0xc8, 0xcd, 0xd2, 0xd7, 0xdc, 0xe1, 0xe6, 0xeb,
+- 0xf0, 0xf5, 0xfa, 0xff, 0x04, 0x09, 0x0e, 0x13,
+- 0x18, 0x1d, 0x22, 0x27, 0x2c, 0x31, 0x36, 0x3b,
+- 0x40, 0x45, 0x4a, 0x4f, 0x54, 0x59, 0x5e, 0x63,
+- 0x68, 0x6d, 0x72, 0x77, 0x7c, 0x81, 0x86, 0x8b,
+- 0x90, 0x95, 0x9a, 0x9f, 0xa4, 0xa9, 0xae, 0xb3,
+- 0xb8, 0xbd, 0xc2, 0xc7, 0xcc, 0xd1, 0xd6, 0xdb,
+- 0xe0, 0xe5, 0xea, 0xef, 0xf4, 0xf9, 0xfe, 0x03,
+- 0x08, 0x0d, 0x12, 0x17, 0x1c, 0x21, 0x26, 0x2b,
+- 0x30, 0x35, 0x3a, 0x3f, 0x44, 0x49, 0x4e, 0x53,
+- 0x58, 0x5d, 0x62, 0x67, 0x6c, 0x71, 0x76, 0x7b,
+- 0x80, 0x85, 0x8a, 0x8f, 0x94, 0x99, 0x9e, 0xa3,
+- 0xa8, 0xad, 0xb2, 0xb7, 0xbc, 0xc1, 0xc6, 0xcb,
+- 0xd0, 0xd5, 0xda, 0xdf, 0xe4, 0xe9, 0xee, 0xf3,
+- 0xf8, 0xfd, 0x02, 0x07, 0x0c, 0x11, 0x16, 0x1b,
+- 0x20, 0x25, 0x2a, 0x2f, 0x34, 0x39, 0x3e, 0x43,
+- 0x48, 0x4d, 0x52, 0x57, 0x5c, 0x61, 0x66, 0x6b,
+- 0x70, 0x75, 0x7a, 0x7f, 0x84, 0x89, 0x8e, 0x93,
+- 0x98, 0x9d, 0xa2, 0xa7, 0xac, 0xb1, 0xb6, 0xbb,
+- 0xc0, 0xc5, 0xca, 0xcf, 0xd4, 0xd9, 0xde, 0xe3,
+- 0xe8, 0xed, 0xf2, 0xf7, 0xfc, 0x01, 0x06, 0x0b,
+- 0x10, 0x15, 0x1a, 0x1f, 0x24, 0x29, 0x2e, 0x33,
+- 0x38, 0x3d, 0x42, 0x47, 0x4c, 0x51, 0x56, 0x5b,
+- 0x60, 0x65, 0x6a, 0x6f, 0x74, 0x79, 0x7e, 0x83,
+- 0x88, 0x8d, 0x92, 0x97, 0x9c, 0xa1, 0xa6, 0xab,
+- 0xb0, 0xb5, 0xba, 0xbf, 0xc4, 0xc9, 0xce, 0xd3,
+- 0xd8, 0xdd, 0xe2, 0xe7, 0xec, 0xf1, 0xf6, 0xfb,
+- 0x00, 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31,
+- 0x38, 0x3f, 0x46, 0x4d, 0x54, 0x5b, 0x62, 0x69,
+- 0x70, 0x77, 0x7e, 0x85, 0x8c, 0x93, 0x9a, 0xa1,
+- 0xa8, 0xaf, 0xb6, 0xbd, 0xc4, 0xcb, 0xd2, 0xd9,
+- 0xe0, 0xe7, 0xee, 0xf5, 0xfc, 0x03, 0x0a, 0x11,
+- 0x18, 0x1f, 0x26, 0x2d, 0x34, 0x3b, 0x42, 0x49,
+- 0x50, 0x57, 0x5e, 0x65, 0x6c, 0x73, 0x7a, 0x81,
+- 0x88, 0x8f, 0x96, 0x9d, 0xa4, 0xab, 0xb2, 0xb9,
+- 0xc0, 0xc7, 0xce, 0xd5, 0xdc, 0xe3, 0xea, 0xf1,
+- 0xf8, 0xff, 0x06, 0x0d, 0x14, 0x1b, 0x22, 0x29,
+- 0x30, 0x37, 0x3e, 0x45, 0x4c, 0x53, 0x5a, 0x61,
+- 0x68, 0x6f, 0x76, 0x7d, 0x84, 0x8b, 0x92, 0x99,
+- 0xa0, 0xa7, 0xae, 0xb5, 0xbc, 0xc3, 0xca, 0xd1,
+- 0xd8, 0xdf, 0xe6, 0xed, 0xf4, 0xfb, 0x02, 0x09,
+- 0x10, 0x17, 0x1e, 0x25, 0x2c, 0x33, 0x3a, 0x41,
+- 0x48, 0x4f, 0x56, 0x5d, 0x64, 0x6b, 0x72, 0x79,
+- 0x80, 0x87, 0x8e, 0x95, 0x9c, 0xa3, 0xaa, 0xb1,
+- 0xb8, 0xbf, 0xc6, 0xcd, 0xd4, 0xdb, 0xe2, 0xe9,
+- 0xf0, 0xf7, 0xfe, 0x05, 0x0c, 0x13, 0x1a, 0x21,
+- 0x28, 0x2f, 0x36, 0x3d, 0x44, 0x4b, 0x52, 0x59,
+- 0x60, 0x67, 0x6e, 0x75, 0x7c, 0x83, 0x8a, 0x91,
+- 0x98, 0x9f, 0xa6, 0xad, 0xb4, 0xbb, 0xc2, 0xc9,
+- 0xd0, 0xd7, 0xde, 0xe5, 0xec, 0xf3, 0xfa, 0x01,
+- 0x08, 0x0f, 0x16, 0x1d, 0x24, 0x2b, 0x32, 0x39,
+- 0x40, 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71,
+- 0x78, 0x7f, 0x86, 0x8d, 0x94, 0x9b, 0xa2, 0xa9,
+- 0xb0, 0xb7, 0xbe, 0xc5, 0xcc, 0xd3, 0xda, 0xe1,
+- 0xe8, 0xef, 0xf6, 0xfd, 0x04, 0x0b, 0x12, 0x19,
+- 0x20, 0x27, 0x2e, 0x35, 0x3c, 0x43, 0x4a, 0x51,
+- 0x58, 0x5f, 0x66, 0x6d, 0x74, 0x7b, 0x82, 0x89,
+- 0x90, 0x97, 0x9e, 0xa5, 0xac, 0xb3, 0xba, 0xc1,
+- 0xc8, 0xcf, 0xd6, 0xdd, 0xe4, 0xeb, 0xf2, 0xf9,
+- 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
+- 0x48, 0x51, 0x5a, 0x63, 0x6c, 0x75, 0x7e, 0x87,
+- 0x90, 0x99, 0xa2, 0xab, 0xb4, 0xbd, 0xc6, 0xcf,
+- 0xd8, 0xe1, 0xea, 0xf3, 0xfc, 0x05, 0x0e, 0x17,
+- 0x20, 0x29, 0x32, 0x3b, 0x44, 0x4d, 0x56, 0x5f,
+- 0x68, 0x71, 0x7a, 0x83, 0x8c, 0x95, 0x9e, 0xa7,
+- 0xb0, 0xb9, 0xc2, 0xcb, 0xd4, 0xdd, 0xe6, 0xef,
+- 0xf8, 0x01, 0x0a, 0x13, 0x1c, 0x25, 0x2e, 0x37,
+- 0x40, 0x49, 0x52, 0x5b, 0x64, 0x6d, 0x76, 0x7f,
+- 0x88, 0x91, 0x9a, 0xa3, 0xac, 0xb5, 0xbe, 0xc7,
+- 0xd0, 0xd9, 0xe2, 0xeb, 0xf4, 0xfd, 0x06, 0x0f,
+- 0x18, 0x21, 0x2a, 0x33, 0x3c, 0x45, 0x4e, 0x57,
+- 0x60, 0x69, 0x72, 0x7b, 0x84, 0x8d, 0x96, 0x9f,
+- 0xa8, 0xb1, 0xba, 0xc3, 0xcc, 0xd5, 0xde, 0xe7,
+- 0xf0, 0xf9, 0x02, 0x0b, 0x14, 0x1d, 0x26, 0x2f,
+- 0x38, 0x41, 0x4a, 0x53, 0x5c, 0x65, 0x6e, 0x77,
+- 0x80, 0x89, 0x92, 0x9b, 0xa4, 0xad, 0xb6, 0xbf,
+- 0xc8, 0xd1, 0xda, 0xe3, 0xec, 0xf5, 0xfe, 0x07,
+- 0x10, 0x19, 0x22, 0x2b, 0x34, 0x3d, 0x46, 0x4f,
+- 0x58, 0x61, 0x6a, 0x73, 0x7c, 0x85, 0x8e, 0x97,
+- 0xa0, 0xa9, 0xb2, 0xbb, 0xc4, 0xcd, 0xd6, 0xdf,
+- 0xe8, 0xf1, 0xfa, 0x03, 0x0c, 0x15, 0x1e, 0x27,
+- 0x30, 0x39, 0x42, 0x4b, 0x54, 0x5d, 0x66, 0x6f,
+- 0x78, 0x81, 0x8a, 0x93, 0x9c, 0xa5, 0xae, 0xb7,
+- 0xc0, 0xc9, 0xd2, 0xdb, 0xe4, 0xed, 0xf6, 0xff,
+- 0x08, 0x11, 0x1a, 0x23, 0x2c, 0x35, 0x3e, 0x47,
+- 0x50, 0x59, 0x62, 0x6b, 0x74, 0x7d, 0x86, 0x8f,
+- 0x98, 0xa1, 0xaa, 0xb3, 0xbc, 0xc5, 0xce, 0xd7,
+- 0xe0, 0xe9, 0xf2, 0xfb, 0x04, 0x0d, 0x16, 0x1f,
+- 0x28, 0x31, 0x3a, 0x43, 0x4c, 0x55, 0x5e, 0x67,
+- 0x70, 0x79, 0x82, 0x8b, 0x94, 0x9d, 0xa6, 0xaf,
+- 0xb8, 0xc1, 0xca, 0xd3, 0xdc, 0xe5, 0xee, 0xf7,
+- 0x00, 0x0b, 0x16, 0x21, 0x2c, 0x37, 0x42, 0x4d,
+- 0x58, 0x63, 0x6e, 0x79, 0x84, 0x8f, 0x9a, 0xa5,
+- 0xb0, 0xbb, 0xc6, 0xd1, 0xdc, 0xe7, 0xf2, 0xfd,
+- 0x08, 0x13, 0x1e, 0x29, 0x34, 0x3f, 0x4a, 0x55,
+- 0x60, 0x6b, 0x76, 0x81, 0x8c, 0x97, 0xa2, 0xad,
+- 0xb8, 0xc3, 0xce, 0xd9, 0xe4, 0xef, 0xfa, 0x05,
+- 0x10, 0x1b, 0x26, 0x31, 0x3c, 0x47, 0x52, 0x5d,
+- 0x68, 0x73, 0x7e, 0x89, 0x94, 0x9f, 0xaa, 0xb5,
+- 0xc0, 0xcb, 0xd6, 0xe1, 0xec, 0xf7, 0x02, 0x0d,
+- 0x18, 0x23, 0x2e, 0x39, 0x44, 0x4f, 0x5a, 0x65,
+- 0x70, 0x7b, 0x86, 0x91, 0x9c, 0xa7, 0xb2, 0xbd,
+- 0xc8, 0xd3, 0xde, 0xe9, 0xf4, 0xff, 0x0a, 0x15,
+- 0x20, 0x2b, 0x36, 0x41, 0x4c, 0x57, 0x62, 0x6d,
+- 0x78, 0x83, 0x8e, 0x99, 0xa4, 0xaf, 0xba, 0xc5,
+- 0xd0, 0xdb, 0xe6, 0xf1, 0xfc, 0x07, 0x12, 0x1d,
+- 0x28, 0x33, 0x3e, 0x49, 0x54, 0x5f, 0x6a, 0x75,
+- 0x80, 0x8b, 0x96, 0xa1, 0xac, 0xb7, 0xc2, 0xcd,
+- 0xd8, 0xe3, 0xee, 0xf9, 0x04, 0x0f, 0x1a, 0x25,
+- 0x30, 0x3b, 0x46, 0x51, 0x5c, 0x67, 0x72, 0x7d,
+- 0x88, 0x93, 0x9e, 0xa9, 0xb4, 0xbf, 0xca, 0xd5,
+- 0xe0, 0xeb, 0xf6, 0x01, 0x0c, 0x17, 0x22, 0x2d,
+- 0x38, 0x43, 0x4e, 0x59, 0x64, 0x6f, 0x7a, 0x85,
+- 0x90, 0x9b, 0xa6, 0xb1, 0xbc, 0xc7, 0xd2, 0xdd,
+- 0xe8, 0xf3, 0xfe, 0x09, 0x14, 0x1f, 0x2a, 0x35,
+- 0x40, 0x4b, 0x56, 0x61, 0x6c, 0x77, 0x82, 0x8d,
+- 0x98, 0xa3, 0xae, 0xb9, 0xc4, 0xcf, 0xda, 0xe5,
+- 0xf0, 0xfb, 0x06, 0x11, 0x1c, 0x27, 0x32, 0x3d,
+- 0x48, 0x53, 0x5e, 0x69, 0x74, 0x7f, 0x8a, 0x95,
+- 0xa0, 0xab, 0xb6, 0xc1, 0xcc, 0xd7, 0xe2, 0xed,
+- 0xf8, 0x03, 0x0e, 0x19, 0x24, 0x2f, 0x3a, 0x45,
+- 0x50, 0x5b, 0x66, 0x71, 0x7c, 0x87, 0x92, 0x9d,
+- 0xa8, 0xb3, 0xbe, 0xc9, 0xd4, 0xdf, 0xea, 0xf5,
+- 0x00, 0x0d, 0x1a, 0x27, 0x34, 0x41, 0x4e, 0x5b,
+- 0x68, 0x75, 0x82, 0x8f, 0x9c, 0xa9, 0xb6, 0xc3,
+- 0xd0, 0xdd, 0xea, 0xf7, 0x04, 0x11, 0x1e, 0x2b,
+- 0x38, 0x45, 0x52, 0x5f, 0x6c, 0x79, 0x86, 0x93,
+- 0xa0, 0xad, 0xba, 0xc7, 0xd4, 0xe1, 0xee, 0xfb,
+- 0x08, 0x15, 0x22, 0x2f, 0x3c, 0x49, 0x56, 0x63,
+- 0x70, 0x7d, 0x8a, 0x97, 0xa4, 0xb1, 0xbe, 0xcb,
+- 0xd8, 0xe5, 0xf2, 0xff, 0x0c, 0x19, 0x26, 0x33,
+- 0x40, 0x4d, 0x5a, 0x67, 0x74, 0x81, 0x8e, 0x9b,
+- 0xa8, 0xb5, 0xc2, 0xcf, 0xdc, 0xe9, 0xf6, 0x03,
+- 0x10, 0x1d, 0x2a, 0x37, 0x44, 0x51, 0x5e, 0x6b,
+- 0x78, 0x85, 0x92, 0x9f, 0xac, 0xb9, 0xc6, 0xd3,
+- 0xe0, 0xed, 0xfa, 0x07, 0x14, 0x21, 0x2e, 0x3b,
+- 0x48, 0x55, 0x62, 0x6f, 0x7c, 0x89, 0x96, 0xa3,
+- 0xb0, 0xbd, 0xca, 0xd7, 0xe4, 0xf1, 0xfe, 0x0b,
+- 0x18, 0x25, 0x32, 0x3f, 0x4c, 0x59, 0x66, 0x73,
+- 0x80, 0x8d, 0x9a, 0xa7, 0xb4, 0xc1, 0xce, 0xdb,
+- 0xe8, 0xf5, 0x02, 0x0f, 0x1c, 0x29, 0x36, 0x43,
+- 0x50, 0x5d, 0x6a, 0x77, 0x84, 0x91, 0x9e, 0xab,
+- 0xb8, 0xc5, 0xd2, 0xdf, 0xec, 0xf9, 0x06, 0x13,
+- 0x20, 0x2d, 0x3a, 0x47, 0x54, 0x61, 0x6e, 0x7b,
+- 0x88, 0x95, 0xa2, 0xaf, 0xbc, 0xc9, 0xd6, 0xe3,
+- 0xf0, 0xfd, 0x0a, 0x17, 0x24, 0x31, 0x3e, 0x4b,
+- 0x58, 0x65, 0x72, 0x7f, 0x8c, 0x99, 0xa6, 0xb3,
+- 0xc0, 0xcd, 0xda, 0xe7, 0xf4, 0x01, 0x0e, 0x1b,
+- 0x28, 0x35, 0x42, 0x4f, 0x5c, 0x69, 0x76, 0x83,
+- 0x90, 0x9d, 0xaa, 0xb7, 0xc4, 0xd1, 0xde, 0xeb,
+- 0xf8, 0x05, 0x12, 0x1f, 0x2c, 0x39, 0x46, 0x53,
+- 0x60, 0x6d, 0x7a, 0x87, 0x94, 0xa1, 0xae, 0xbb,
+- 0xc8, 0xd5, 0xe2, 0xef, 0xfc, 0x09, 0x16, 0x23,
+- 0x30, 0x3d, 0x4a, 0x57, 0x64, 0x71, 0x7e, 0x8b,
+- 0x98, 0xa5, 0xb2, 0xbf, 0xcc, 0xd9, 0xe6, 0xf3,
+- 0x00, 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69,
+- 0x78, 0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1,
+- 0xf0, 0xff, 0x0e, 0x1d, 0x2c, 0x3b, 0x4a, 0x59,
+- 0x68, 0x77, 0x86, 0x95, 0xa4, 0xb3, 0xc2, 0xd1,
+- 0xe0, 0xef, 0xfe, 0x0d, 0x1c, 0x2b, 0x3a, 0x49,
+- 0x58, 0x67, 0x76, 0x85, 0x94, 0xa3, 0xb2, 0xc1,
+- 0xd0, 0xdf, 0xee, 0xfd, 0x0c, 0x1b, 0x2a, 0x39,
+- 0x48, 0x57, 0x66, 0x75, 0x84, 0x93, 0xa2, 0xb1,
+- 0xc0, 0xcf, 0xde, 0xed, 0xfc, 0x0b, 0x1a, 0x29,
+- 0x38, 0x47, 0x56, 0x65, 0x74, 0x83, 0x92, 0xa1,
+- 0xb0, 0xbf, 0xce, 0xdd, 0xec, 0xfb, 0x0a, 0x19,
+- 0x28, 0x37, 0x46, 0x55, 0x64, 0x73, 0x82, 0x91,
+- 0xa0, 0xaf, 0xbe, 0xcd, 0xdc, 0xeb, 0xfa, 0x09,
+- 0x18, 0x27, 0x36, 0x45, 0x54, 0x63, 0x72, 0x81,
+- 0x90, 0x9f, 0xae, 0xbd, 0xcc, 0xdb, 0xea, 0xf9,
+- 0x08, 0x17, 0x26, 0x35, 0x44, 0x53, 0x62, 0x71,
+- 0x80, 0x8f, 0x9e, 0xad, 0xbc, 0xcb, 0xda, 0xe9,
+- 0xf8, 0x07, 0x16, 0x25, 0x34, 0x43, 0x52, 0x61,
+- 0x70, 0x7f, 0x8e, 0x9d, 0xac, 0xbb, 0xca, 0xd9,
+- 0xe8, 0xf7, 0x06, 0x15, 0x24, 0x33, 0x42, 0x51,
+- 0x60, 0x6f, 0x7e, 0x8d, 0x9c, 0xab, 0xba, 0xc9,
+- 0xd8, 0xe7, 0xf6, 0x05, 0x14, 0x23, 0x32, 0x41,
+- 0x50, 0x5f, 0x6e, 0x7d, 0x8c, 0x9b, 0xaa, 0xb9,
+- 0xc8, 0xd7, 0xe6, 0xf5, 0x04, 0x13, 0x22, 0x31,
+- 0x40, 0x4f, 0x5e, 0x6d, 0x7c, 0x8b, 0x9a, 0xa9,
+- 0xb8, 0xc7, 0xd6, 0xe5, 0xf4, 0x03, 0x12, 0x21,
+- 0x30, 0x3f, 0x4e, 0x5d, 0x6c, 0x7b, 0x8a, 0x99,
+- 0xa8, 0xb7, 0xc6, 0xd5, 0xe4, 0xf3, 0x02, 0x11,
+- 0x20, 0x2f, 0x3e, 0x4d, 0x5c, 0x6b, 0x7a, 0x89,
+- 0x98, 0xa7, 0xb6, 0xc5, 0xd4, 0xe3, 0xf2, 0x01,
+- 0x10, 0x1f, 0x2e, 0x3d, 0x4c, 0x5b, 0x6a, 0x79,
+- 0x88, 0x97, 0xa6, 0xb5, 0xc4, 0xd3, 0xe2, 0xf1,
+- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+- 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+- 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87,
+- 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f,
+- 0x20, 0x31, 0x42, 0x53, 0x64, 0x75, 0x86, 0x97,
+- 0xa8, 0xb9, 0xca, 0xdb, 0xec, 0xfd, 0x0e, 0x1f,
+- 0x30, 0x41, 0x52, 0x63, 0x74, 0x85, 0x96, 0xa7,
+- 0xb8, 0xc9, 0xda, 0xeb, 0xfc, 0x0d, 0x1e, 0x2f,
+- 0x40, 0x51, 0x62, 0x73, 0x84, 0x95, 0xa6, 0xb7,
+- 0xc8, 0xd9, 0xea, 0xfb, 0x0c, 0x1d, 0x2e, 0x3f,
+- 0x50, 0x61, 0x72, 0x83, 0x94, 0xa5, 0xb6, 0xc7,
+- 0xd8, 0xe9, 0xfa, 0x0b, 0x1c, 0x2d, 0x3e, 0x4f,
+- 0x60, 0x71, 0x82, 0x93, 0xa4, 0xb5, 0xc6, 0xd7,
+- 0xe8, 0xf9, 0x0a, 0x1b, 0x2c, 0x3d, 0x4e, 0x5f,
+- 0x70, 0x81, 0x92, 0xa3, 0xb4, 0xc5, 0xd6, 0xe7,
+- 0xf8, 0x09, 0x1a, 0x2b, 0x3c, 0x4d, 0x5e, 0x6f,
+- 0x80, 0x91, 0xa2, 0xb3, 0xc4, 0xd5, 0xe6, 0xf7,
+- 0x08, 0x19, 0x2a, 0x3b, 0x4c, 0x5d, 0x6e, 0x7f,
+- 0x90, 0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf6, 0x07,
+- 0x18, 0x29, 0x3a, 0x4b, 0x5c, 0x6d, 0x7e, 0x8f,
+- 0xa0, 0xb1, 0xc2, 0xd3, 0xe4, 0xf5, 0x06, 0x17,
+- 0x28, 0x39, 0x4a, 0x5b, 0x6c, 0x7d, 0x8e, 0x9f,
+- 0xb0, 0xc1, 0xd2, 0xe3, 0xf4, 0x05, 0x16, 0x27,
+- 0x38, 0x49, 0x5a, 0x6b, 0x7c, 0x8d, 0x9e, 0xaf,
+- 0xc0, 0xd1, 0xe2, 0xf3, 0x04, 0x15, 0x26, 0x37,
+- 0x48, 0x59, 0x6a, 0x7b, 0x8c, 0x9d, 0xae, 0xbf,
+- 0xd0, 0xe1, 0xf2, 0x03, 0x14, 0x25, 0x36, 0x47,
+- 0x58, 0x69, 0x7a, 0x8b, 0x9c, 0xad, 0xbe, 0xcf,
+- 0xe0, 0xf1, 0x02, 0x13, 0x24, 0x35, 0x46, 0x57,
+- 0x68, 0x79, 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf,
+- 0xf0, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67,
+- 0x78, 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef,
+- 0x00, 0x13, 0x26, 0x39, 0x4c, 0x5f, 0x72, 0x85,
+- 0x98, 0xab, 0xbe, 0xd1, 0xe4, 0xf7, 0x0a, 0x1d,
+- 0x30, 0x43, 0x56, 0x69, 0x7c, 0x8f, 0xa2, 0xb5,
+- 0xc8, 0xdb, 0xee, 0x01, 0x14, 0x27, 0x3a, 0x4d,
+- 0x60, 0x73, 0x86, 0x99, 0xac, 0xbf, 0xd2, 0xe5,
+- 0xf8, 0x0b, 0x1e, 0x31, 0x44, 0x57, 0x6a, 0x7d,
+- 0x90, 0xa3, 0xb6, 0xc9, 0xdc, 0xef, 0x02, 0x15,
+- 0x28, 0x3b, 0x4e, 0x61, 0x74, 0x87, 0x9a, 0xad,
+- 0xc0, 0xd3, 0xe6, 0xf9, 0x0c, 0x1f, 0x32, 0x45,
+- 0x58, 0x6b, 0x7e, 0x91, 0xa4, 0xb7, 0xca, 0xdd,
+- 0xf0, 0x03, 0x16, 0x29, 0x3c, 0x4f, 0x62, 0x75,
+- 0x88, 0x9b, 0xae, 0xc1, 0xd4, 0xe7, 0xfa, 0x0d,
+- 0x20, 0x33, 0x46, 0x59, 0x6c, 0x7f, 0x92, 0xa5,
+- 0xb8, 0xcb, 0xde, 0xf1, 0x04, 0x17, 0x2a, 0x3d,
+- 0x50, 0x63, 0x76, 0x89, 0x9c, 0xaf, 0xc2, 0xd5,
+- 0xe8, 0xfb, 0x0e, 0x21, 0x34, 0x47, 0x5a, 0x6d,
+- 0x80, 0x93, 0xa6, 0xb9, 0xcc, 0xdf, 0xf2, 0x05,
+- 0x18, 0x2b, 0x3e, 0x51, 0x64, 0x77, 0x8a, 0x9d,
+- 0xb0, 0xc3, 0xd6, 0xe9, 0xfc, 0x0f, 0x22, 0x35,
+- 0x48, 0x5b, 0x6e, 0x81, 0x94, 0xa7, 0xba, 0xcd,
+- 0xe0, 0xf3, 0x06, 0x19, 0x2c, 0x3f, 0x52, 0x65,
+- 0x78, 0x8b, 0x9e, 0xb1, 0xc4, 0xd7, 0xea, 0xfd,
+- 0x10, 0x23, 0x36, 0x49, 0x5c, 0x6f, 0x82, 0x95,
+- 0xa8, 0xbb, 0xce, 0xe1, 0xf4, 0x07, 0x1a, 0x2d,
+- 0x40, 0x53, 0x66, 0x79, 0x8c, 0x9f, 0xb2, 0xc5,
+- 0xd8, 0xeb, 0xfe, 0x11, 0x24, 0x37, 0x4a, 0x5d,
+- 0x70, 0x83, 0x96, 0xa9, 0xbc, 0xcf, 0xe2, 0xf5,
+- 0x08, 0x1b, 0x2e, 0x41, 0x54, 0x67, 0x7a, 0x8d,
+- 0xa0, 0xb3, 0xc6, 0xd9, 0xec, 0xff, 0x12, 0x25,
+- 0x38, 0x4b, 0x5e, 0x71, 0x84, 0x97, 0xaa, 0xbd,
+- 0xd0, 0xe3, 0xf6, 0x09, 0x1c, 0x2f, 0x42, 0x55,
+- 0x68, 0x7b, 0x8e, 0xa1, 0xb4, 0xc7, 0xda, 0xed,
+- 0x00, 0x15, 0x2a, 0x3f, 0x54, 0x69, 0x7e, 0x93,
+- 0xa8, 0xbd, 0xd2, 0xe7, 0xfc, 0x11, 0x26, 0x3b,
+- 0x50, 0x65, 0x7a, 0x8f, 0xa4, 0xb9, 0xce, 0xe3,
+- 0xf8, 0x0d, 0x22, 0x37, 0x4c, 0x61, 0x76, 0x8b,
+- 0xa0, 0xb5, 0xca, 0xdf, 0xf4, 0x09, 0x1e, 0x33,
+- 0x48, 0x5d, 0x72, 0x87, 0x9c, 0xb1, 0xc6, 0xdb,
+- 0xf0, 0x05, 0x1a, 0x2f, 0x44, 0x59, 0x6e, 0x83,
+- 0x98, 0xad, 0xc2, 0xd7, 0xec, 0x01, 0x16, 0x2b,
+- 0x40, 0x55, 0x6a, 0x7f, 0x94, 0xa9, 0xbe, 0xd3,
+- 0xe8, 0xfd, 0x12, 0x27, 0x3c, 0x51, 0x66, 0x7b,
+- 0x90, 0xa5, 0xba, 0xcf, 0xe4, 0xf9, 0x0e, 0x23,
+- 0x38, 0x4d, 0x62, 0x77, 0x8c, 0xa1, 0xb6, 0xcb,
+- 0xe0, 0xf5, 0x0a, 0x1f, 0x34, 0x49, 0x5e, 0x73,
+- 0x88, 0x9d, 0xb2, 0xc7, 0xdc, 0xf1, 0x06, 0x1b,
+- 0x30, 0x45, 0x5a, 0x6f, 0x84, 0x99, 0xae, 0xc3,
+- 0xd8, 0xed, 0x02, 0x17, 0x2c, 0x41, 0x56, 0x6b,
+- 0x80, 0x95, 0xaa, 0xbf, 0xd4, 0xe9, 0xfe, 0x13,
+- 0x28, 0x3d, 0x52, 0x67, 0x7c, 0x91, 0xa6, 0xbb,
+- 0xd0, 0xe5, 0xfa, 0x0f, 0x24, 0x39, 0x4e, 0x63,
+- 0x78, 0x8d, 0xa2, 0xb7, 0xcc, 0xe1, 0xf6, 0x0b,
+- 0x20, 0x35, 0x4a, 0x5f, 0x74, 0x89, 0x9e, 0xb3,
+- 0xc8, 0xdd, 0xf2, 0x07, 0x1c, 0x31, 0x46, 0x5b,
+- 0x70, 0x85, 0x9a, 0xaf, 0xc4, 0xd9, 0xee, 0x03,
+- 0x18, 0x2d, 0x42, 0x57, 0x6c, 0x81, 0x96, 0xab,
+- 0xc0, 0xd5, 0xea, 0xff, 0x14, 0x29, 0x3e, 0x53,
+- 0x68, 0x7d, 0x92, 0xa7, 0xbc, 0xd1, 0xe6, 0xfb,
+- 0x10, 0x25, 0x3a, 0x4f, 0x64, 0x79, 0x8e, 0xa3,
+- 0xb8, 0xcd, 0xe2, 0xf7, 0x0c, 0x21, 0x36, 0x4b,
+- 0x60, 0x75, 0x8a, 0x9f, 0xb4, 0xc9, 0xde, 0xf3,
+- 0x08, 0x1d, 0x32, 0x47, 0x5c, 0x71, 0x86, 0x9b,
+- 0xb0, 0xc5, 0xda, 0xef, 0x04, 0x19, 0x2e, 0x43,
+- 0x58, 0x6d, 0x82, 0x97, 0xac, 0xc1, 0xd6, 0xeb,
+- 0x00, 0x17, 0x2e, 0x45, 0x5c, 0x73, 0x8a, 0xa1,
+- 0xb8, 0xcf, 0xe6, 0xfd, 0x14, 0x2b, 0x42, 0x59,
+- 0x70, 0x87, 0x9e, 0xb5, 0xcc, 0xe3, 0xfa, 0x11,
+- 0x28, 0x3f, 0x56, 0x6d, 0x84, 0x9b, 0xb2, 0xc9,
+- 0xe0, 0xf7, 0x0e, 0x25, 0x3c, 0x53, 0x6a, 0x81,
+- 0x98, 0xaf, 0xc6, 0xdd, 0xf4, 0x0b, 0x22, 0x39,
+- 0x50, 0x67, 0x7e, 0x95, 0xac, 0xc3, 0xda, 0xf1,
+- 0x08, 0x1f, 0x36, 0x4d, 0x64, 0x7b, 0x92, 0xa9,
+- 0xc0, 0xd7, 0xee, 0x05, 0x1c, 0x33, 0x4a, 0x61,
+- 0x78, 0x8f, 0xa6, 0xbd, 0xd4, 0xeb, 0x02, 0x19,
+- 0x30, 0x47, 0x5e, 0x75, 0x8c, 0xa3, 0xba, 0xd1,
+- 0xe8, 0xff, 0x16, 0x2d, 0x44, 0x5b, 0x72, 0x89,
+- 0xa0, 0xb7, 0xce, 0xe5, 0xfc, 0x13, 0x2a, 0x41,
+- 0x58, 0x6f, 0x86, 0x9d, 0xb4, 0xcb, 0xe2, 0xf9,
+- 0x10, 0x27, 0x3e, 0x55, 0x6c, 0x83, 0x9a, 0xb1,
+- 0xc8, 0xdf, 0xf6, 0x0d, 0x24, 0x3b, 0x52, 0x69,
+- 0x80, 0x97, 0xae, 0xc5, 0xdc, 0xf3, 0x0a, 0x21,
+- 0x38, 0x4f, 0x66, 0x7d, 0x94, 0xab, 0xc2, 0xd9,
+- 0xf0, 0x07, 0x1e, 0x35, 0x4c, 0x63, 0x7a, 0x91,
+- 0xa8, 0xbf, 0xd6, 0xed, 0x04, 0x1b, 0x32, 0x49,
+- 0x60, 0x77, 0x8e, 0xa5, 0xbc, 0xd3, 0xea, 0x01,
+- 0x18, 0x2f, 0x46, 0x5d, 0x74, 0x8b, 0xa2, 0xb9,
+- 0xd0, 0xe7, 0xfe, 0x15, 0x2c, 0x43, 0x5a, 0x71,
+- 0x88, 0x9f, 0xb6, 0xcd, 0xe4, 0xfb, 0x12, 0x29,
+- 0x40, 0x57, 0x6e, 0x85, 0x9c, 0xb3, 0xca, 0xe1,
+- 0xf8, 0x0f, 0x26, 0x3d, 0x54, 0x6b, 0x82, 0x99,
+- 0xb0, 0xc7, 0xde, 0xf5, 0x0c, 0x23, 0x3a, 0x51,
+- 0x68, 0x7f, 0x96, 0xad, 0xc4, 0xdb, 0xf2, 0x09,
+- 0x20, 0x37, 0x4e, 0x65, 0x7c, 0x93, 0xaa, 0xc1,
+- 0xd8, 0xef, 0x06, 0x1d, 0x34, 0x4b, 0x62, 0x79,
+- 0x90, 0xa7, 0xbe, 0xd5, 0xec, 0x03, 0x1a, 0x31,
+- 0x48, 0x5f, 0x76, 0x8d, 0xa4, 0xbb, 0xd2, 0xe9,
+- 0x00, 0x19, 0x32, 0x4b, 0x64, 0x7d, 0x96, 0xaf,
+- 0xc8, 0xe1, 0xfa, 0x13, 0x2c, 0x45, 0x5e, 0x77,
+- 0x90, 0xa9, 0xc2, 0xdb, 0xf4, 0x0d, 0x26, 0x3f,
+- 0x58, 0x71, 0x8a, 0xa3, 0xbc, 0xd5, 0xee, 0x07,
+- 0x20, 0x39, 0x52, 0x6b, 0x84, 0x9d, 0xb6, 0xcf,
+- 0xe8, 0x01, 0x1a, 0x33, 0x4c, 0x65, 0x7e, 0x97,
+- 0xb0, 0xc9, 0xe2, 0xfb, 0x14, 0x2d, 0x46, 0x5f,
+- 0x78, 0x91, 0xaa, 0xc3, 0xdc, 0xf5, 0x0e, 0x27,
+- 0x40, 0x59, 0x72, 0x8b, 0xa4, 0xbd, 0xd6, 0xef,
+- 0x08, 0x21, 0x3a, 0x53, 0x6c, 0x85, 0x9e, 0xb7,
+- 0xd0, 0xe9, 0x02, 0x1b, 0x34, 0x4d, 0x66, 0x7f,
+- 0x98, 0xb1, 0xca, 0xe3, 0xfc, 0x15, 0x2e, 0x47,
+- 0x60, 0x79, 0x92, 0xab, 0xc4, 0xdd, 0xf6, 0x0f,
+- 0x28, 0x41, 0x5a, 0x73, 0x8c, 0xa5, 0xbe, 0xd7,
+- 0xf0, 0x09, 0x22, 0x3b, 0x54, 0x6d, 0x86, 0x9f,
+- 0xb8, 0xd1, 0xea, 0x03, 0x1c, 0x35, 0x4e, 0x67,
+- 0x80, 0x99, 0xb2, 0xcb, 0xe4, 0xfd, 0x16, 0x2f,
+- 0x48, 0x61, 0x7a, 0x93, 0xac, 0xc5, 0xde, 0xf7,
+- 0x10, 0x29, 0x42, 0x5b, 0x74, 0x8d, 0xa6, 0xbf,
+- 0xd8, 0xf1, 0x0a, 0x23, 0x3c, 0x55, 0x6e, 0x87,
+- 0xa0, 0xb9, 0xd2, 0xeb, 0x04, 0x1d, 0x36, 0x4f,
+- 0x68, 0x81, 0x9a, 0xb3, 0xcc, 0xe5, 0xfe, 0x17,
+- 0x30, 0x49, 0x62, 0x7b, 0x94, 0xad, 0xc6, 0xdf,
+- 0xf8, 0x11, 0x2a, 0x43, 0x5c, 0x75, 0x8e, 0xa7,
+- 0xc0, 0xd9, 0xf2, 0x0b, 0x24, 0x3d, 0x56, 0x6f,
+- 0x88, 0xa1, 0xba, 0xd3, 0xec, 0x05, 0x1e, 0x37,
+- 0x50, 0x69, 0x82, 0x9b, 0xb4, 0xcd, 0xe6, 0xff,
+- 0x18, 0x31, 0x4a, 0x63, 0x7c, 0x95, 0xae, 0xc7,
+- 0xe0, 0xf9, 0x12, 0x2b, 0x44, 0x5d, 0x76, 0x8f,
+- 0xa8, 0xc1, 0xda, 0xf3, 0x0c, 0x25, 0x3e, 0x57,
+- 0x70, 0x89, 0xa2, 0xbb, 0xd4, 0xed, 0x06, 0x1f,
+- 0x38, 0x51, 0x6a, 0x83, 0x9c, 0xb5, 0xce, 0xe7,
+- 0x00, 0x1b, 0x36, 0x51, 0x6c, 0x87, 0xa2, 0xbd,
+- 0xd8, 0xf3, 0x0e, 0x29, 0x44, 0x5f, 0x7a, 0x95,
+- 0xb0, 0xcb, 0xe6, 0x01, 0x1c, 0x37, 0x52, 0x6d,
+- 0x88, 0xa3, 0xbe, 0xd9, 0xf4, 0x0f, 0x2a, 0x45,
+- 0x60, 0x7b, 0x96, 0xb1, 0xcc, 0xe7, 0x02, 0x1d,
+- 0x38, 0x53, 0x6e, 0x89, 0xa4, 0xbf, 0xda, 0xf5,
+- 0x10, 0x2b, 0x46, 0x61, 0x7c, 0x97, 0xb2, 0xcd,
+- 0xe8, 0x03, 0x1e, 0x39, 0x54, 0x6f, 0x8a, 0xa5,
+- 0xc0, 0xdb, 0xf6, 0x11, 0x2c, 0x47, 0x62, 0x7d,
+- 0x98, 0xb3, 0xce, 0xe9, 0x04, 0x1f, 0x3a, 0x55,
+- 0x70, 0x8b, 0xa6, 0xc1, 0xdc, 0xf7, 0x12, 0x2d,
+- 0x48, 0x63, 0x7e, 0x99, 0xb4, 0xcf, 0xea, 0x05,
+- 0x20, 0x3b, 0x56, 0x71, 0x8c, 0xa7, 0xc2, 0xdd,
+- 0xf8, 0x13, 0x2e, 0x49, 0x64, 0x7f, 0x9a, 0xb5,
+- 0xd0, 0xeb, 0x06, 0x21, 0x3c, 0x57, 0x72, 0x8d,
+- 0xa8, 0xc3, 0xde, 0xf9, 0x14, 0x2f, 0x4a, 0x65,
+- 0x80, 0x9b, 0xb6, 0xd1, 0xec, 0x07, 0x22, 0x3d,
+- 0x58, 0x73, 0x8e, 0xa9, 0xc4, 0xdf, 0xfa, 0x15,
+- 0x30, 0x4b, 0x66, 0x81, 0x9c, 0xb7, 0xd2, 0xed,
+- 0x08, 0x23, 0x3e, 0x59, 0x74, 0x8f, 0xaa, 0xc5,
+- 0xe0, 0xfb, 0x16, 0x31, 0x4c, 0x67, 0x82, 0x9d,
+- 0xb8, 0xd3, 0xee, 0x09, 0x24, 0x3f, 0x5a, 0x75,
+- 0x90, 0xab, 0xc6, 0xe1, 0xfc, 0x17, 0x32, 0x4d,
+- 0x68, 0x83, 0x9e, 0xb9, 0xd4, 0xef, 0x0a, 0x25,
+- 0x40, 0x5b, 0x76, 0x91, 0xac, 0xc7, 0xe2, 0xfd,
+- 0x18, 0x33, 0x4e, 0x69, 0x84, 0x9f, 0xba, 0xd5,
+- 0xf0, 0x0b, 0x26, 0x41, 0x5c, 0x77, 0x92, 0xad,
+- 0xc8, 0xe3, 0xfe, 0x19, 0x34, 0x4f, 0x6a, 0x85,
+- 0xa0, 0xbb, 0xd6, 0xf1, 0x0c, 0x27, 0x42, 0x5d,
+- 0x78, 0x93, 0xae, 0xc9, 0xe4, 0xff, 0x1a, 0x35,
+- 0x50, 0x6b, 0x86, 0xa1, 0xbc, 0xd7, 0xf2, 0x0d,
+- 0x28, 0x43, 0x5e, 0x79, 0x94, 0xaf, 0xca, 0xe5,
+- 0x00, 0x1d, 0x3a, 0x57, 0x74, 0x91, 0xae, 0xcb,
+- 0xe8, 0x05, 0x22, 0x3f, 0x5c, 0x79, 0x96, 0xb3,
+- 0xd0, 0xed, 0x0a, 0x27, 0x44, 0x61, 0x7e, 0x9b,
+- 0xb8, 0xd5, 0xf2, 0x0f, 0x2c, 0x49, 0x66, 0x83,
+- 0xa0, 0xbd, 0xda, 0xf7, 0x14, 0x31, 0x4e, 0x6b,
+- 0x88, 0xa5, 0xc2, 0xdf, 0xfc, 0x19, 0x36, 0x53,
+- 0x70, 0x8d, 0xaa, 0xc7, 0xe4, 0x01, 0x1e, 0x3b,
+- 0x58, 0x75, 0x92, 0xaf, 0xcc, 0xe9, 0x06, 0x23,
+- 0x40, 0x5d, 0x7a, 0x97, 0xb4, 0xd1, 0xee, 0x0b,
+- 0x28, 0x45, 0x62, 0x7f, 0x9c, 0xb9, 0xd6, 0xf3,
+- 0x10, 0x2d, 0x4a, 0x67, 0x84, 0xa1, 0xbe, 0xdb,
+- 0xf8, 0x15, 0x32, 0x4f, 0x6c, 0x89, 0xa6, 0xc3,
+- 0xe0, 0xfd, 0x1a, 0x37, 0x54, 0x71, 0x8e, 0xab,
+- 0xc8, 0xe5, 0x02, 0x1f, 0x3c, 0x59, 0x76, 0x93,
+- 0xb0, 0xcd, 0xea, 0x07, 0x24, 0x41, 0x5e, 0x7b,
+- 0x98, 0xb5, 0xd2, 0xef, 0x0c, 0x29, 0x46, 0x63,
+- 0x80, 0x9d, 0xba, 0xd7, 0xf4, 0x11, 0x2e, 0x4b,
+- 0x68, 0x85, 0xa2, 0xbf, 0xdc, 0xf9, 0x16, 0x33,
+- 0x50, 0x6d, 0x8a, 0xa7, 0xc4, 0xe1, 0xfe, 0x1b,
+- 0x38, 0x55, 0x72, 0x8f, 0xac, 0xc9, 0xe6, 0x03,
+- 0x20, 0x3d, 0x5a, 0x77, 0x94, 0xb1, 0xce, 0xeb,
+- 0x08, 0x25, 0x42, 0x5f, 0x7c, 0x99, 0xb6, 0xd3,
+- 0xf0, 0x0d, 0x2a, 0x47, 0x64, 0x81, 0x9e, 0xbb,
+- 0xd8, 0xf5, 0x12, 0x2f, 0x4c, 0x69, 0x86, 0xa3,
+- 0xc0, 0xdd, 0xfa, 0x17, 0x34, 0x51, 0x6e, 0x8b,
+- 0xa8, 0xc5, 0xe2, 0xff, 0x1c, 0x39, 0x56, 0x73,
+- 0x90, 0xad, 0xca, 0xe7, 0x04, 0x21, 0x3e, 0x5b,
+- 0x78, 0x95, 0xb2, 0xcf, 0xec, 0x09, 0x26, 0x43,
+- 0x60, 0x7d, 0x9a, 0xb7, 0xd4, 0xf1, 0x0e, 0x2b,
+- 0x48, 0x65, 0x82, 0x9f, 0xbc, 0xd9, 0xf6, 0x13,
+- 0x30, 0x4d, 0x6a, 0x87, 0xa4, 0xc1, 0xde, 0xfb,
+- 0x18, 0x35, 0x52, 0x6f, 0x8c, 0xa9, 0xc6, 0xe3,
+- 0x00, 0x1f, 0x3e, 0x5d, 0x7c, 0x9b, 0xba, 0xd9,
+- 0xf8, 0x17, 0x36, 0x55, 0x74, 0x93, 0xb2, 0xd1,
+- 0xf0, 0x0f, 0x2e, 0x4d, 0x6c, 0x8b, 0xaa, 0xc9,
+- 0xe8, 0x07, 0x26, 0x45, 0x64, 0x83, 0xa2, 0xc1,
+- 0xe0, 0xff, 0x1e, 0x3d, 0x5c, 0x7b, 0x9a, 0xb9,
+- 0xd8, 0xf7, 0x16, 0x35, 0x54, 0x73, 0x92, 0xb1,
+- 0xd0, 0xef, 0x0e, 0x2d, 0x4c, 0x6b, 0x8a, 0xa9,
+- 0xc8, 0xe7, 0x06, 0x25, 0x44, 0x63, 0x82, 0xa1,
+- 0xc0, 0xdf, 0xfe, 0x1d, 0x3c, 0x5b, 0x7a, 0x99,
+- 0xb8, 0xd7, 0xf6, 0x15, 0x34, 0x53, 0x72, 0x91,
+- 0xb0, 0xcf, 0xee, 0x0d, 0x2c, 0x4b, 0x6a, 0x89,
+- 0xa8, 0xc7, 0xe6, 0x05, 0x24, 0x43, 0x62, 0x81,
+- 0xa0, 0xbf, 0xde, 0xfd, 0x1c, 0x3b, 0x5a, 0x79,
+- 0x98, 0xb7, 0xd6, 0xf5, 0x14, 0x33, 0x52, 0x71,
+- 0x90, 0xaf, 0xce, 0xed, 0x0c, 0x2b, 0x4a, 0x69,
+- 0x88, 0xa7, 0xc6, 0xe5, 0x04, 0x23, 0x42, 0x61,
+- 0x80, 0x9f, 0xbe, 0xdd, 0xfc, 0x1b, 0x3a, 0x59,
+- 0x78, 0x97, 0xb6, 0xd5, 0xf4, 0x13, 0x32, 0x51,
+- 0x70, 0x8f, 0xae, 0xcd, 0xec, 0x0b, 0x2a, 0x49,
+- 0x68, 0x87, 0xa6, 0xc5, 0xe4, 0x03, 0x22, 0x41,
+- 0x60, 0x7f, 0x9e, 0xbd, 0xdc, 0xfb, 0x1a, 0x39,
+- 0x58, 0x77, 0x96, 0xb5, 0xd4, 0xf3, 0x12, 0x31,
+- 0x50, 0x6f, 0x8e, 0xad, 0xcc, 0xeb, 0x0a, 0x29,
+- 0x48, 0x67, 0x86, 0xa5, 0xc4, 0xe3, 0x02, 0x21,
+- 0x40, 0x5f, 0x7e, 0x9d, 0xbc, 0xdb, 0xfa, 0x19,
+- 0x38, 0x57, 0x76, 0x95, 0xb4, 0xd3, 0xf2, 0x11,
+- 0x30, 0x4f, 0x6e, 0x8d, 0xac, 0xcb, 0xea, 0x09,
+- 0x28, 0x47, 0x66, 0x85, 0xa4, 0xc3, 0xe2, 0x01,
+- 0x20, 0x3f, 0x5e, 0x7d, 0x9c, 0xbb, 0xda, 0xf9,
+- 0x18, 0x37, 0x56, 0x75, 0x94, 0xb3, 0xd2, 0xf1,
+- 0x10, 0x2f, 0x4e, 0x6d, 0x8c, 0xab, 0xca, 0xe9,
+- 0x08, 0x27, 0x46, 0x65, 0x84, 0xa3, 0xc2, 0xe1,
+- 0x00, 0x21, 0x42, 0x63,
+- },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00",
++ .input =
++ "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
++ "\x20\x21\x22\x23\x24\x25\x26\x27"
++ "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
++ "\x30\x31\x32\x33\x34\x35\x36\x37"
++ "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
++ "\x40\x41\x42\x43\x44\x45\x46\x47"
++ "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
++ "\x50\x51\x52\x53\x54\x55\x56\x57"
++ "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
++ "\x60\x61\x62\x63\x64\x65\x66\x67"
++ "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
++ "\x70\x71\x72\x73\x74\x75\x76\x77"
++ "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
++ "\x80\x81\x82\x83\x84\x85\x86\x87"
++ "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
++ "\x90\x91\x92\x93\x94\x95\x96\x97"
++ "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
++ "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
++ "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
++ "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
++ "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
++ "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++ "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
++ "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
++ "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
++ "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
++ "\xe8\xe9\xea\xeb\xec\xed\xee\xef"
++ "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
++ "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
++ "\x00\x03\x06\x09\x0c\x0f\x12\x15"
++ "\x18\x1b\x1e\x21\x24\x27\x2a\x2d"
++ "\x30\x33\x36\x39\x3c\x3f\x42\x45"
++ "\x48\x4b\x4e\x51\x54\x57\x5a\x5d"
++ "\x60\x63\x66\x69\x6c\x6f\x72\x75"
++ "\x78\x7b\x7e\x81\x84\x87\x8a\x8d"
++ "\x90\x93\x96\x99\x9c\x9f\xa2\xa5"
++ "\xa8\xab\xae\xb1\xb4\xb7\xba\xbd"
++ "\xc0\xc3\xc6\xc9\xcc\xcf\xd2\xd5"
++ "\xd8\xdb\xde\xe1\xe4\xe7\xea\xed"
++ "\xf0\xf3\xf6\xf9\xfc\xff\x02\x05"
++ "\x08\x0b\x0e\x11\x14\x17\x1a\x1d"
++ "\x20\x23\x26\x29\x2c\x2f\x32\x35"
++ "\x38\x3b\x3e\x41\x44\x47\x4a\x4d"
++ "\x50\x53\x56\x59\x5c\x5f\x62\x65"
++ "\x68\x6b\x6e\x71\x74\x77\x7a\x7d"
++ "\x80\x83\x86\x89\x8c\x8f\x92\x95"
++ "\x98\x9b\x9e\xa1\xa4\xa7\xaa\xad"
++ "\xb0\xb3\xb6\xb9\xbc\xbf\xc2\xc5"
++ "\xc8\xcb\xce\xd1\xd4\xd7\xda\xdd"
++ "\xe0\xe3\xe6\xe9\xec\xef\xf2\xf5"
++ "\xf8\xfb\xfe\x01\x04\x07\x0a\x0d"
++ "\x10\x13\x16\x19\x1c\x1f\x22\x25"
++ "\x28\x2b\x2e\x31\x34\x37\x3a\x3d"
++ "\x40\x43\x46\x49\x4c\x4f\x52\x55"
++ "\x58\x5b\x5e\x61\x64\x67\x6a\x6d"
++ "\x70\x73\x76\x79\x7c\x7f\x82\x85"
++ "\x88\x8b\x8e\x91\x94\x97\x9a\x9d"
++ "\xa0\xa3\xa6\xa9\xac\xaf\xb2\xb5"
++ "\xb8\xbb\xbe\xc1\xc4\xc7\xca\xcd"
++ "\xd0\xd3\xd6\xd9\xdc\xdf\xe2\xe5"
++ "\xe8\xeb\xee\xf1\xf4\xf7\xfa\xfd"
++ "\x00\x05\x0a\x0f\x14\x19\x1e\x23"
++ "\x28\x2d\x32\x37\x3c\x41\x46\x4b"
++ "\x50\x55\x5a\x5f\x64\x69\x6e\x73"
++ "\x78\x7d\x82\x87\x8c\x91\x96\x9b"
++ "\xa0\xa5\xaa\xaf\xb4\xb9\xbe\xc3"
++ "\xc8\xcd\xd2\xd7\xdc\xe1\xe6\xeb"
++ "\xf0\xf5\xfa\xff\x04\x09\x0e\x13"
++ "\x18\x1d\x22\x27\x2c\x31\x36\x3b"
++ "\x40\x45\x4a\x4f\x54\x59\x5e\x63"
++ "\x68\x6d\x72\x77\x7c\x81\x86\x8b"
++ "\x90\x95\x9a\x9f\xa4\xa9\xae\xb3"
++ "\xb8\xbd\xc2\xc7\xcc\xd1\xd6\xdb"
++ "\xe0\xe5\xea\xef\xf4\xf9\xfe\x03"
++ "\x08\x0d\x12\x17\x1c\x21\x26\x2b"
++ "\x30\x35\x3a\x3f\x44\x49\x4e\x53"
++ "\x58\x5d\x62\x67\x6c\x71\x76\x7b"
++ "\x80\x85\x8a\x8f\x94\x99\x9e\xa3"
++ "\xa8\xad\xb2\xb7\xbc\xc1\xc6\xcb"
++ "\xd0\xd5\xda\xdf\xe4\xe9\xee\xf3"
++ "\xf8\xfd\x02\x07\x0c\x11\x16\x1b"
++ "\x20\x25\x2a\x2f\x34\x39\x3e\x43"
++ "\x48\x4d\x52\x57\x5c\x61\x66\x6b"
++ "\x70\x75\x7a\x7f\x84\x89\x8e\x93"
++ "\x98\x9d\xa2\xa7\xac\xb1\xb6\xbb"
++ "\xc0\xc5\xca\xcf\xd4\xd9\xde\xe3"
++ "\xe8\xed\xf2\xf7\xfc\x01\x06\x0b"
++ "\x10\x15\x1a\x1f\x24\x29\x2e\x33"
++ "\x38\x3d\x42\x47\x4c\x51\x56\x5b"
++ "\x60\x65\x6a\x6f\x74\x79\x7e\x83"
++ "\x88\x8d\x92\x97\x9c\xa1\xa6\xab"
++ "\xb0\xb5\xba\xbf\xc4\xc9\xce\xd3"
++ "\xd8\xdd\xe2\xe7\xec\xf1\xf6\xfb"
++ "\x00\x07\x0e\x15\x1c\x23\x2a\x31"
++ "\x38\x3f\x46\x4d\x54\x5b\x62\x69"
++ "\x70\x77\x7e\x85\x8c\x93\x9a\xa1"
++ "\xa8\xaf\xb6\xbd\xc4\xcb\xd2\xd9"
++ "\xe0\xe7\xee\xf5\xfc\x03\x0a\x11"
++ "\x18\x1f\x26\x2d\x34\x3b\x42\x49"
++ "\x50\x57\x5e\x65\x6c\x73\x7a\x81"
++ "\x88\x8f\x96\x9d\xa4\xab\xb2\xb9"
++ "\xc0\xc7\xce\xd5\xdc\xe3\xea\xf1"
++ "\xf8\xff\x06\x0d\x14\x1b\x22\x29"
++ "\x30\x37\x3e\x45\x4c\x53\x5a\x61"
++ "\x68\x6f\x76\x7d\x84\x8b\x92\x99"
++ "\xa0\xa7\xae\xb5\xbc\xc3\xca\xd1"
++ "\xd8\xdf\xe6\xed\xf4\xfb\x02\x09"
++ "\x10\x17\x1e\x25\x2c\x33\x3a\x41"
++ "\x48\x4f\x56\x5d\x64\x6b\x72\x79"
++ "\x80\x87\x8e\x95\x9c\xa3\xaa\xb1"
++ "\xb8\xbf\xc6\xcd\xd4\xdb\xe2\xe9"
++ "\xf0\xf7\xfe\x05\x0c\x13\x1a\x21"
++ "\x28\x2f\x36\x3d\x44\x4b\x52\x59"
++ "\x60\x67\x6e\x75\x7c\x83\x8a\x91"
++ "\x98\x9f\xa6\xad\xb4\xbb\xc2\xc9"
++ "\xd0\xd7\xde\xe5\xec\xf3\xfa\x01"
++ "\x08\x0f\x16\x1d\x24\x2b\x32\x39"
++ "\x40\x47\x4e\x55\x5c\x63\x6a\x71"
++ "\x78\x7f\x86\x8d\x94\x9b\xa2\xa9"
++ "\xb0\xb7\xbe\xc5\xcc\xd3\xda\xe1"
++ "\xe8\xef\xf6\xfd\x04\x0b\x12\x19"
++ "\x20\x27\x2e\x35\x3c\x43\x4a\x51"
++ "\x58\x5f\x66\x6d\x74\x7b\x82\x89"
++ "\x90\x97\x9e\xa5\xac\xb3\xba\xc1"
++ "\xc8\xcf\xd6\xdd\xe4\xeb\xf2\xf9"
++ "\x00\x09\x12\x1b\x24\x2d\x36\x3f"
++ "\x48\x51\x5a\x63\x6c\x75\x7e\x87"
++ "\x90\x99\xa2\xab\xb4\xbd\xc6\xcf"
++ "\xd8\xe1\xea\xf3\xfc\x05\x0e\x17"
++ "\x20\x29\x32\x3b\x44\x4d\x56\x5f"
++ "\x68\x71\x7a\x83\x8c\x95\x9e\xa7"
++ "\xb0\xb9\xc2\xcb\xd4\xdd\xe6\xef"
++ "\xf8\x01\x0a\x13\x1c\x25\x2e\x37"
++ "\x40\x49\x52\x5b\x64\x6d\x76\x7f"
++ "\x88\x91\x9a\xa3\xac\xb5\xbe\xc7"
++ "\xd0\xd9\xe2\xeb\xf4\xfd\x06\x0f"
++ "\x18\x21\x2a\x33\x3c\x45\x4e\x57"
++ "\x60\x69\x72\x7b\x84\x8d\x96\x9f"
++ "\xa8\xb1\xba\xc3\xcc\xd5\xde\xe7"
++ "\xf0\xf9\x02\x0b\x14\x1d\x26\x2f"
++ "\x38\x41\x4a\x53\x5c\x65\x6e\x77"
++ "\x80\x89\x92\x9b\xa4\xad\xb6\xbf"
++ "\xc8\xd1\xda\xe3\xec\xf5\xfe\x07"
++ "\x10\x19\x22\x2b\x34\x3d\x46\x4f"
++ "\x58\x61\x6a\x73\x7c\x85\x8e\x97"
++ "\xa0\xa9\xb2\xbb\xc4\xcd\xd6\xdf"
++ "\xe8\xf1\xfa\x03\x0c\x15\x1e\x27"
++ "\x30\x39\x42\x4b\x54\x5d\x66\x6f"
++ "\x78\x81\x8a\x93\x9c\xa5\xae\xb7"
++ "\xc0\xc9\xd2\xdb\xe4\xed\xf6\xff"
++ "\x08\x11\x1a\x23\x2c\x35\x3e\x47"
++ "\x50\x59\x62\x6b\x74\x7d\x86\x8f"
++ "\x98\xa1\xaa\xb3\xbc\xc5\xce\xd7"
++ "\xe0\xe9\xf2\xfb\x04\x0d\x16\x1f"
++ "\x28\x31\x3a\x43\x4c\x55\x5e\x67"
++ "\x70\x79\x82\x8b\x94\x9d\xa6\xaf"
++ "\xb8\xc1\xca\xd3\xdc\xe5\xee\xf7"
++ "\x00\x0b\x16\x21\x2c\x37\x42\x4d"
++ "\x58\x63\x6e\x79\x84\x8f\x9a\xa5"
++ "\xb0\xbb\xc6\xd1\xdc\xe7\xf2\xfd"
++ "\x08\x13\x1e\x29\x34\x3f\x4a\x55"
++ "\x60\x6b\x76\x81\x8c\x97\xa2\xad"
++ "\xb8\xc3\xce\xd9\xe4\xef\xfa\x05"
++ "\x10\x1b\x26\x31\x3c\x47\x52\x5d"
++ "\x68\x73\x7e\x89\x94\x9f\xaa\xb5"
++ "\xc0\xcb\xd6\xe1\xec\xf7\x02\x0d"
++ "\x18\x23\x2e\x39\x44\x4f\x5a\x65"
++ "\x70\x7b\x86\x91\x9c\xa7\xb2\xbd"
++ "\xc8\xd3\xde\xe9\xf4\xff\x0a\x15"
++ "\x20\x2b\x36\x41\x4c\x57\x62\x6d"
++ "\x78\x83\x8e\x99\xa4\xaf\xba\xc5"
++ "\xd0\xdb\xe6\xf1\xfc\x07\x12\x1d"
++ "\x28\x33\x3e\x49\x54\x5f\x6a\x75"
++ "\x80\x8b\x96\xa1\xac\xb7\xc2\xcd"
++ "\xd8\xe3\xee\xf9\x04\x0f\x1a\x25"
++ "\x30\x3b\x46\x51\x5c\x67\x72\x7d"
++ "\x88\x93\x9e\xa9\xb4\xbf\xca\xd5"
++ "\xe0\xeb\xf6\x01\x0c\x17\x22\x2d"
++ "\x38\x43\x4e\x59\x64\x6f\x7a\x85"
++ "\x90\x9b\xa6\xb1\xbc\xc7\xd2\xdd"
++ "\xe8\xf3\xfe\x09\x14\x1f\x2a\x35"
++ "\x40\x4b\x56\x61\x6c\x77\x82\x8d"
++ "\x98\xa3\xae\xb9\xc4\xcf\xda\xe5"
++ "\xf0\xfb\x06\x11\x1c\x27\x32\x3d"
++ "\x48\x53\x5e\x69\x74\x7f\x8a\x95"
++ "\xa0\xab\xb6\xc1\xcc\xd7\xe2\xed"
++ "\xf8\x03\x0e\x19\x24\x2f\x3a\x45"
++ "\x50\x5b\x66\x71\x7c\x87\x92\x9d"
++ "\xa8\xb3\xbe\xc9\xd4\xdf\xea\xf5"
++ "\x00\x0d\x1a\x27\x34\x41\x4e\x5b"
++ "\x68\x75\x82\x8f\x9c\xa9\xb6\xc3"
++ "\xd0\xdd\xea\xf7\x04\x11\x1e\x2b"
++ "\x38\x45\x52\x5f\x6c\x79\x86\x93"
++ "\xa0\xad\xba\xc7\xd4\xe1\xee\xfb"
++ "\x08\x15\x22\x2f\x3c\x49\x56\x63"
++ "\x70\x7d\x8a\x97\xa4\xb1\xbe\xcb"
++ "\xd8\xe5\xf2\xff\x0c\x19\x26\x33"
++ "\x40\x4d\x5a\x67\x74\x81\x8e\x9b"
++ "\xa8\xb5\xc2\xcf\xdc\xe9\xf6\x03"
++ "\x10\x1d\x2a\x37\x44\x51\x5e\x6b"
++ "\x78\x85\x92\x9f\xac\xb9\xc6\xd3"
++ "\xe0\xed\xfa\x07\x14\x21\x2e\x3b"
++ "\x48\x55\x62\x6f\x7c\x89\x96\xa3"
++ "\xb0\xbd\xca\xd7\xe4\xf1\xfe\x0b"
++ "\x18\x25\x32\x3f\x4c\x59\x66\x73"
++ "\x80\x8d\x9a\xa7\xb4\xc1\xce\xdb"
++ "\xe8\xf5\x02\x0f\x1c\x29\x36\x43"
++ "\x50\x5d\x6a\x77\x84\x91\x9e\xab"
++ "\xb8\xc5\xd2\xdf\xec\xf9\x06\x13"
++ "\x20\x2d\x3a\x47\x54\x61\x6e\x7b"
++ "\x88\x95\xa2\xaf\xbc\xc9\xd6\xe3"
++ "\xf0\xfd\x0a\x17\x24\x31\x3e\x4b"
++ "\x58\x65\x72\x7f\x8c\x99\xa6\xb3"
++ "\xc0\xcd\xda\xe7\xf4\x01\x0e\x1b"
++ "\x28\x35\x42\x4f\x5c\x69\x76\x83"
++ "\x90\x9d\xaa\xb7\xc4\xd1\xde\xeb"
++ "\xf8\x05\x12\x1f\x2c\x39\x46\x53"
++ "\x60\x6d\x7a\x87\x94\xa1\xae\xbb"
++ "\xc8\xd5\xe2\xef\xfc\x09\x16\x23"
++ "\x30\x3d\x4a\x57\x64\x71\x7e\x8b"
++ "\x98\xa5\xb2\xbf\xcc\xd9\xe6\xf3"
++ "\x00\x0f\x1e\x2d\x3c\x4b\x5a\x69"
++ "\x78\x87\x96\xa5\xb4\xc3\xd2\xe1"
++ "\xf0\xff\x0e\x1d\x2c\x3b\x4a\x59"
++ "\x68\x77\x86\x95\xa4\xb3\xc2\xd1"
++ "\xe0\xef\xfe\x0d\x1c\x2b\x3a\x49"
++ "\x58\x67\x76\x85\x94\xa3\xb2\xc1"
++ "\xd0\xdf\xee\xfd\x0c\x1b\x2a\x39"
++ "\x48\x57\x66\x75\x84\x93\xa2\xb1"
++ "\xc0\xcf\xde\xed\xfc\x0b\x1a\x29"
++ "\x38\x47\x56\x65\x74\x83\x92\xa1"
++ "\xb0\xbf\xce\xdd\xec\xfb\x0a\x19"
++ "\x28\x37\x46\x55\x64\x73\x82\x91"
++ "\xa0\xaf\xbe\xcd\xdc\xeb\xfa\x09"
++ "\x18\x27\x36\x45\x54\x63\x72\x81"
++ "\x90\x9f\xae\xbd\xcc\xdb\xea\xf9"
++ "\x08\x17\x26\x35\x44\x53\x62\x71"
++ "\x80\x8f\x9e\xad\xbc\xcb\xda\xe9"
++ "\xf8\x07\x16\x25\x34\x43\x52\x61"
++ "\x70\x7f\x8e\x9d\xac\xbb\xca\xd9"
++ "\xe8\xf7\x06\x15\x24\x33\x42\x51"
++ "\x60\x6f\x7e\x8d\x9c\xab\xba\xc9"
++ "\xd8\xe7\xf6\x05\x14\x23\x32\x41"
++ "\x50\x5f\x6e\x7d\x8c\x9b\xaa\xb9"
++ "\xc8\xd7\xe6\xf5\x04\x13\x22\x31"
++ "\x40\x4f\x5e\x6d\x7c\x8b\x9a\xa9"
++ "\xb8\xc7\xd6\xe5\xf4\x03\x12\x21"
++ "\x30\x3f\x4e\x5d\x6c\x7b\x8a\x99"
++ "\xa8\xb7\xc6\xd5\xe4\xf3\x02\x11"
++ "\x20\x2f\x3e\x4d\x5c\x6b\x7a\x89"
++ "\x98\xa7\xb6\xc5\xd4\xe3\xf2\x01"
++ "\x10\x1f\x2e\x3d\x4c\x5b\x6a\x79"
++ "\x88\x97\xa6\xb5\xc4\xd3\xe2\xf1"
++ "\x00\x11\x22\x33\x44\x55\x66\x77"
++ "\x88\x99\xaa\xbb\xcc\xdd\xee\xff"
++ "\x10\x21\x32\x43\x54\x65\x76\x87"
++ "\x98\xa9\xba\xcb\xdc\xed\xfe\x0f"
++ "\x20\x31\x42\x53\x64\x75\x86\x97"
++ "\xa8\xb9\xca\xdb\xec\xfd\x0e\x1f"
++ "\x30\x41\x52\x63\x74\x85\x96\xa7"
++ "\xb8\xc9\xda\xeb\xfc\x0d\x1e\x2f"
++ "\x40\x51\x62\x73\x84\x95\xa6\xb7"
++ "\xc8\xd9\xea\xfb\x0c\x1d\x2e\x3f"
++ "\x50\x61\x72\x83\x94\xa5\xb6\xc7"
++ "\xd8\xe9\xfa\x0b\x1c\x2d\x3e\x4f"
++ "\x60\x71\x82\x93\xa4\xb5\xc6\xd7"
++ "\xe8\xf9\x0a\x1b\x2c\x3d\x4e\x5f"
++ "\x70\x81\x92\xa3\xb4\xc5\xd6\xe7"
++ "\xf8\x09\x1a\x2b\x3c\x4d\x5e\x6f"
++ "\x80\x91\xa2\xb3\xc4\xd5\xe6\xf7"
++ "\x08\x19\x2a\x3b\x4c\x5d\x6e\x7f"
++ "\x90\xa1\xb2\xc3\xd4\xe5\xf6\x07"
++ "\x18\x29\x3a\x4b\x5c\x6d\x7e\x8f"
++ "\xa0\xb1\xc2\xd3\xe4\xf5\x06\x17"
++ "\x28\x39\x4a\x5b\x6c\x7d\x8e\x9f"
++ "\xb0\xc1\xd2\xe3\xf4\x05\x16\x27"
++ "\x38\x49\x5a\x6b\x7c\x8d\x9e\xaf"
++ "\xc0\xd1\xe2\xf3\x04\x15\x26\x37"
++ "\x48\x59\x6a\x7b\x8c\x9d\xae\xbf"
++ "\xd0\xe1\xf2\x03\x14\x25\x36\x47"
++ "\x58\x69\x7a\x8b\x9c\xad\xbe\xcf"
++ "\xe0\xf1\x02\x13\x24\x35\x46\x57"
++ "\x68\x79\x8a\x9b\xac\xbd\xce\xdf"
++ "\xf0\x01\x12\x23\x34\x45\x56\x67"
++ "\x78\x89\x9a\xab\xbc\xcd\xde\xef"
++ "\x00\x13\x26\x39\x4c\x5f\x72\x85"
++ "\x98\xab\xbe\xd1\xe4\xf7\x0a\x1d"
++ "\x30\x43\x56\x69\x7c\x8f\xa2\xb5"
++ "\xc8\xdb\xee\x01\x14\x27\x3a\x4d"
++ "\x60\x73\x86\x99\xac\xbf\xd2\xe5"
++ "\xf8\x0b\x1e\x31\x44\x57\x6a\x7d"
++ "\x90\xa3\xb6\xc9\xdc\xef\x02\x15"
++ "\x28\x3b\x4e\x61\x74\x87\x9a\xad"
++ "\xc0\xd3\xe6\xf9\x0c\x1f\x32\x45"
++ "\x58\x6b\x7e\x91\xa4\xb7\xca\xdd"
++ "\xf0\x03\x16\x29\x3c\x4f\x62\x75"
++ "\x88\x9b\xae\xc1\xd4\xe7\xfa\x0d"
++ "\x20\x33\x46\x59\x6c\x7f\x92\xa5"
++ "\xb8\xcb\xde\xf1\x04\x17\x2a\x3d"
++ "\x50\x63\x76\x89\x9c\xaf\xc2\xd5"
++ "\xe8\xfb\x0e\x21\x34\x47\x5a\x6d"
++ "\x80\x93\xa6\xb9\xcc\xdf\xf2\x05"
++ "\x18\x2b\x3e\x51\x64\x77\x8a\x9d"
++ "\xb0\xc3\xd6\xe9\xfc\x0f\x22\x35"
++ "\x48\x5b\x6e\x81\x94\xa7\xba\xcd"
++ "\xe0\xf3\x06\x19\x2c\x3f\x52\x65"
++ "\x78\x8b\x9e\xb1\xc4\xd7\xea\xfd"
++ "\x10\x23\x36\x49\x5c\x6f\x82\x95"
++ "\xa8\xbb\xce\xe1\xf4\x07\x1a\x2d"
++ "\x40\x53\x66\x79\x8c\x9f\xb2\xc5"
++ "\xd8\xeb\xfe\x11\x24\x37\x4a\x5d"
++ "\x70\x83\x96\xa9\xbc\xcf\xe2\xf5"
++ "\x08\x1b\x2e\x41\x54\x67\x7a\x8d"
++ "\xa0\xb3\xc6\xd9\xec\xff\x12\x25"
++ "\x38\x4b\x5e\x71\x84\x97\xaa\xbd"
++ "\xd0\xe3\xf6\x09\x1c\x2f\x42\x55"
++ "\x68\x7b\x8e\xa1\xb4\xc7\xda\xed"
++ "\x00\x15\x2a\x3f\x54\x69\x7e\x93"
++ "\xa8\xbd\xd2\xe7\xfc\x11\x26\x3b"
++ "\x50\x65\x7a\x8f\xa4\xb9\xce\xe3"
++ "\xf8\x0d\x22\x37\x4c\x61\x76\x8b"
++ "\xa0\xb5\xca\xdf\xf4\x09\x1e\x33"
++ "\x48\x5d\x72\x87\x9c\xb1\xc6\xdb"
++ "\xf0\x05\x1a\x2f\x44\x59\x6e\x83"
++ "\x98\xad\xc2\xd7\xec\x01\x16\x2b"
++ "\x40\x55\x6a\x7f\x94\xa9\xbe\xd3"
++ "\xe8\xfd\x12\x27\x3c\x51\x66\x7b"
++ "\x90\xa5\xba\xcf\xe4\xf9\x0e\x23"
++ "\x38\x4d\x62\x77\x8c\xa1\xb6\xcb"
++ "\xe0\xf5\x0a\x1f\x34\x49\x5e\x73"
++ "\x88\x9d\xb2\xc7\xdc\xf1\x06\x1b"
++ "\x30\x45\x5a\x6f\x84\x99\xae\xc3"
++ "\xd8\xed\x02\x17\x2c\x41\x56\x6b"
++ "\x80\x95\xaa\xbf\xd4\xe9\xfe\x13"
++ "\x28\x3d\x52\x67\x7c\x91\xa6\xbb"
++ "\xd0\xe5\xfa\x0f\x24\x39\x4e\x63"
++ "\x78\x8d\xa2\xb7\xcc\xe1\xf6\x0b"
++ "\x20\x35\x4a\x5f\x74\x89\x9e\xb3"
++ "\xc8\xdd\xf2\x07\x1c\x31\x46\x5b"
++ "\x70\x85\x9a\xaf\xc4\xd9\xee\x03"
++ "\x18\x2d\x42\x57\x6c\x81\x96\xab"
++ "\xc0\xd5\xea\xff\x14\x29\x3e\x53"
++ "\x68\x7d\x92\xa7\xbc\xd1\xe6\xfb"
++ "\x10\x25\x3a\x4f\x64\x79\x8e\xa3"
++ "\xb8\xcd\xe2\xf7\x0c\x21\x36\x4b"
++ "\x60\x75\x8a\x9f\xb4\xc9\xde\xf3"
++ "\x08\x1d\x32\x47\x5c\x71\x86\x9b"
++ "\xb0\xc5\xda\xef\x04\x19\x2e\x43"
++ "\x58\x6d\x82\x97\xac\xc1\xd6\xeb"
++ "\x00\x17\x2e\x45\x5c\x73\x8a\xa1"
++ "\xb8\xcf\xe6\xfd\x14\x2b\x42\x59"
++ "\x70\x87\x9e\xb5\xcc\xe3\xfa\x11"
++ "\x28\x3f\x56\x6d\x84\x9b\xb2\xc9"
++ "\xe0\xf7\x0e\x25\x3c\x53\x6a\x81"
++ "\x98\xaf\xc6\xdd\xf4\x0b\x22\x39"
++ "\x50\x67\x7e\x95\xac\xc3\xda\xf1"
++ "\x08\x1f\x36\x4d\x64\x7b\x92\xa9"
++ "\xc0\xd7\xee\x05\x1c\x33\x4a\x61"
++ "\x78\x8f\xa6\xbd\xd4\xeb\x02\x19"
++ "\x30\x47\x5e\x75\x8c\xa3\xba\xd1"
++ "\xe8\xff\x16\x2d\x44\x5b\x72\x89"
++ "\xa0\xb7\xce\xe5\xfc\x13\x2a\x41"
++ "\x58\x6f\x86\x9d\xb4\xcb\xe2\xf9"
++ "\x10\x27\x3e\x55\x6c\x83\x9a\xb1"
++ "\xc8\xdf\xf6\x0d\x24\x3b\x52\x69"
++ "\x80\x97\xae\xc5\xdc\xf3\x0a\x21"
++ "\x38\x4f\x66\x7d\x94\xab\xc2\xd9"
++ "\xf0\x07\x1e\x35\x4c\x63\x7a\x91"
++ "\xa8\xbf\xd6\xed\x04\x1b\x32\x49"
++ "\x60\x77\x8e\xa5\xbc\xd3\xea\x01"
++ "\x18\x2f\x46\x5d\x74\x8b\xa2\xb9"
++ "\xd0\xe7\xfe\x15\x2c\x43\x5a\x71"
++ "\x88\x9f\xb6\xcd\xe4\xfb\x12\x29"
++ "\x40\x57\x6e\x85\x9c\xb3\xca\xe1"
++ "\xf8\x0f\x26\x3d\x54\x6b\x82\x99"
++ "\xb0\xc7\xde\xf5\x0c\x23\x3a\x51"
++ "\x68\x7f\x96\xad\xc4\xdb\xf2\x09"
++ "\x20\x37\x4e\x65\x7c\x93\xaa\xc1"
++ "\xd8\xef\x06\x1d\x34\x4b\x62\x79"
++ "\x90\xa7\xbe\xd5\xec\x03\x1a\x31"
++ "\x48\x5f\x76\x8d\xa4\xbb\xd2\xe9"
++ "\x00\x19\x32\x4b\x64\x7d\x96\xaf"
++ "\xc8\xe1\xfa\x13\x2c\x45\x5e\x77"
++ "\x90\xa9\xc2\xdb\xf4\x0d\x26\x3f"
++ "\x58\x71\x8a\xa3\xbc\xd5\xee\x07"
++ "\x20\x39\x52\x6b\x84\x9d\xb6\xcf"
++ "\xe8\x01\x1a\x33\x4c\x65\x7e\x97"
++ "\xb0\xc9\xe2\xfb\x14\x2d\x46\x5f"
++ "\x78\x91\xaa\xc3\xdc\xf5\x0e\x27"
++ "\x40\x59\x72\x8b\xa4\xbd\xd6\xef"
++ "\x08\x21\x3a\x53\x6c\x85\x9e\xb7"
++ "\xd0\xe9\x02\x1b\x34\x4d\x66\x7f"
++ "\x98\xb1\xca\xe3\xfc\x15\x2e\x47"
++ "\x60\x79\x92\xab\xc4\xdd\xf6\x0f"
++ "\x28\x41\x5a\x73\x8c\xa5\xbe\xd7"
++ "\xf0\x09\x22\x3b\x54\x6d\x86\x9f"
++ "\xb8\xd1\xea\x03\x1c\x35\x4e\x67"
++ "\x80\x99\xb2\xcb\xe4\xfd\x16\x2f"
++ "\x48\x61\x7a\x93\xac\xc5\xde\xf7"
++ "\x10\x29\x42\x5b\x74\x8d\xa6\xbf"
++ "\xd8\xf1\x0a\x23\x3c\x55\x6e\x87"
++ "\xa0\xb9\xd2\xeb\x04\x1d\x36\x4f"
++ "\x68\x81\x9a\xb3\xcc\xe5\xfe\x17"
++ "\x30\x49\x62\x7b\x94\xad\xc6\xdf"
++ "\xf8\x11\x2a\x43\x5c\x75\x8e\xa7"
++ "\xc0\xd9\xf2\x0b\x24\x3d\x56\x6f"
++ "\x88\xa1\xba\xd3\xec\x05\x1e\x37"
++ "\x50\x69\x82\x9b\xb4\xcd\xe6\xff"
++ "\x18\x31\x4a\x63\x7c\x95\xae\xc7"
++ "\xe0\xf9\x12\x2b\x44\x5d\x76\x8f"
++ "\xa8\xc1\xda\xf3\x0c\x25\x3e\x57"
++ "\x70\x89\xa2\xbb\xd4\xed\x06\x1f"
++ "\x38\x51\x6a\x83\x9c\xb5\xce\xe7"
++ "\x00\x1b\x36\x51\x6c\x87\xa2\xbd"
++ "\xd8\xf3\x0e\x29\x44\x5f\x7a\x95"
++ "\xb0\xcb\xe6\x01\x1c\x37\x52\x6d"
++ "\x88\xa3\xbe\xd9\xf4\x0f\x2a\x45"
++ "\x60\x7b\x96\xb1\xcc\xe7\x02\x1d"
++ "\x38\x53\x6e\x89\xa4\xbf\xda\xf5"
++ "\x10\x2b\x46\x61\x7c\x97\xb2\xcd"
++ "\xe8\x03\x1e\x39\x54\x6f\x8a\xa5"
++ "\xc0\xdb\xf6\x11\x2c\x47\x62\x7d"
++ "\x98\xb3\xce\xe9\x04\x1f\x3a\x55"
++ "\x70\x8b\xa6\xc1\xdc\xf7\x12\x2d"
++ "\x48\x63\x7e\x99\xb4\xcf\xea\x05"
++ "\x20\x3b\x56\x71\x8c\xa7\xc2\xdd"
++ "\xf8\x13\x2e\x49\x64\x7f\x9a\xb5"
++ "\xd0\xeb\x06\x21\x3c\x57\x72\x8d"
++ "\xa8\xc3\xde\xf9\x14\x2f\x4a\x65"
++ "\x80\x9b\xb6\xd1\xec\x07\x22\x3d"
++ "\x58\x73\x8e\xa9\xc4\xdf\xfa\x15"
++ "\x30\x4b\x66\x81\x9c\xb7\xd2\xed"
++ "\x08\x23\x3e\x59\x74\x8f\xaa\xc5"
++ "\xe0\xfb\x16\x31\x4c\x67\x82\x9d"
++ "\xb8\xd3\xee\x09\x24\x3f\x5a\x75"
++ "\x90\xab\xc6\xe1\xfc\x17\x32\x4d"
++ "\x68\x83\x9e\xb9\xd4\xef\x0a\x25"
++ "\x40\x5b\x76\x91\xac\xc7\xe2\xfd"
++ "\x18\x33\x4e\x69\x84\x9f\xba\xd5"
++ "\xf0\x0b\x26\x41\x5c\x77\x92\xad"
++ "\xc8\xe3\xfe\x19\x34\x4f\x6a\x85"
++ "\xa0\xbb\xd6\xf1\x0c\x27\x42\x5d"
++ "\x78\x93\xae\xc9\xe4\xff\x1a\x35"
++ "\x50\x6b\x86\xa1\xbc\xd7\xf2\x0d"
++ "\x28\x43\x5e\x79\x94\xaf\xca\xe5"
++ "\x00\x1d\x3a\x57\x74\x91\xae\xcb"
++ "\xe8\x05\x22\x3f\x5c\x79\x96\xb3"
++ "\xd0\xed\x0a\x27\x44\x61\x7e\x9b"
++ "\xb8\xd5\xf2\x0f\x2c\x49\x66\x83"
++ "\xa0\xbd\xda\xf7\x14\x31\x4e\x6b"
++ "\x88\xa5\xc2\xdf\xfc\x19\x36\x53"
++ "\x70\x8d\xaa\xc7\xe4\x01\x1e\x3b"
++ "\x58\x75\x92\xaf\xcc\xe9\x06\x23"
++ "\x40\x5d\x7a\x97\xb4\xd1\xee\x0b"
++ "\x28\x45\x62\x7f\x9c\xb9\xd6\xf3"
++ "\x10\x2d\x4a\x67\x84\xa1\xbe\xdb"
++ "\xf8\x15\x32\x4f\x6c\x89\xa6\xc3"
++ "\xe0\xfd\x1a\x37\x54\x71\x8e\xab"
++ "\xc8\xe5\x02\x1f\x3c\x59\x76\x93"
++ "\xb0\xcd\xea\x07\x24\x41\x5e\x7b"
++ "\x98\xb5\xd2\xef\x0c\x29\x46\x63"
++ "\x80\x9d\xba\xd7\xf4\x11\x2e\x4b"
++ "\x68\x85\xa2\xbf\xdc\xf9\x16\x33"
++ "\x50\x6d\x8a\xa7\xc4\xe1\xfe\x1b"
++ "\x38\x55\x72\x8f\xac\xc9\xe6\x03"
++ "\x20\x3d\x5a\x77\x94\xb1\xce\xeb"
++ "\x08\x25\x42\x5f\x7c\x99\xb6\xd3"
++ "\xf0\x0d\x2a\x47\x64\x81\x9e\xbb"
++ "\xd8\xf5\x12\x2f\x4c\x69\x86\xa3"
++ "\xc0\xdd\xfa\x17\x34\x51\x6e\x8b"
++ "\xa8\xc5\xe2\xff\x1c\x39\x56\x73"
++ "\x90\xad\xca\xe7\x04\x21\x3e\x5b"
++ "\x78\x95\xb2\xcf\xec\x09\x26\x43"
++ "\x60\x7d\x9a\xb7\xd4\xf1\x0e\x2b"
++ "\x48\x65\x82\x9f\xbc\xd9\xf6\x13"
++ "\x30\x4d\x6a\x87\xa4\xc1\xde\xfb"
++ "\x18\x35\x52\x6f\x8c\xa9\xc6\xe3"
++ "\x00\x1f\x3e\x5d\x7c\x9b\xba\xd9"
++ "\xf8\x17\x36\x55\x74\x93\xb2\xd1"
++ "\xf0\x0f\x2e\x4d\x6c\x8b\xaa\xc9"
++ "\xe8\x07\x26\x45\x64\x83\xa2\xc1"
++ "\xe0\xff\x1e\x3d\x5c\x7b\x9a\xb9"
++ "\xd8\xf7\x16\x35\x54\x73\x92\xb1"
++ "\xd0\xef\x0e\x2d\x4c\x6b\x8a\xa9"
++ "\xc8\xe7\x06\x25\x44\x63\x82\xa1"
++ "\xc0\xdf\xfe\x1d\x3c\x5b\x7a\x99"
++ "\xb8\xd7\xf6\x15\x34\x53\x72\x91"
++ "\xb0\xcf\xee\x0d\x2c\x4b\x6a\x89"
++ "\xa8\xc7\xe6\x05\x24\x43\x62\x81"
++ "\xa0\xbf\xde\xfd\x1c\x3b\x5a\x79"
++ "\x98\xb7\xd6\xf5\x14\x33\x52\x71"
++ "\x90\xaf\xce\xed\x0c\x2b\x4a\x69"
++ "\x88\xa7\xc6\xe5\x04\x23\x42\x61"
++ "\x80\x9f\xbe\xdd\xfc\x1b\x3a\x59"
++ "\x78\x97\xb6\xd5\xf4\x13\x32\x51"
++ "\x70\x8f\xae\xcd\xec\x0b\x2a\x49"
++ "\x68\x87\xa6\xc5\xe4\x03\x22\x41"
++ "\x60\x7f\x9e\xbd\xdc\xfb\x1a\x39"
++ "\x58\x77\x96\xb5\xd4\xf3\x12\x31"
++ "\x50\x6f\x8e\xad\xcc\xeb\x0a\x29"
++ "\x48\x67\x86\xa5\xc4\xe3\x02\x21"
++ "\x40\x5f\x7e\x9d\xbc\xdb\xfa\x19"
++ "\x38\x57\x76\x95\xb4\xd3\xf2\x11"
++ "\x30\x4f\x6e\x8d\xac\xcb\xea\x09"
++ "\x28\x47\x66\x85\xa4\xc3\xe2\x01"
++ "\x20\x3f\x5e\x7d\x9c\xbb\xda\xf9"
++ "\x18\x37\x56\x75\x94\xb3\xd2\xf1"
++ "\x10\x2f\x4e\x6d\x8c\xab\xca\xe9"
++ "\x08\x27\x46\x65\x84\xa3\xc2\xe1"
++ "\x00\x21\x42\x63",
+ .ilen = 4100,
+- .result = {
+- 0xf0, 0x5c, 0x74, 0xad, 0x4e, 0xbc, 0x99, 0xe2,
+- 0xae, 0xff, 0x91, 0x3a, 0x44, 0xcf, 0x38, 0x32,
+- 0x1e, 0xad, 0xa7, 0xcd, 0xa1, 0x39, 0x95, 0xaa,
+- 0x10, 0xb1, 0xb3, 0x2e, 0x04, 0x31, 0x8f, 0x86,
+- 0xf2, 0x62, 0x74, 0x70, 0x0c, 0xa4, 0x46, 0x08,
+- 0xa8, 0xb7, 0x99, 0xa8, 0xe9, 0xd2, 0x73, 0x79,
+- 0x7e, 0x6e, 0xd4, 0x8f, 0x1e, 0xc7, 0x8e, 0x31,
+- 0x0b, 0xfa, 0x4b, 0xce, 0xfd, 0xf3, 0x57, 0x71,
+- 0xe9, 0x46, 0x03, 0xa5, 0x3d, 0x34, 0x00, 0xe2,
+- 0x18, 0xff, 0x75, 0x6d, 0x06, 0x2d, 0x00, 0xab,
+- 0xb9, 0x3e, 0x6c, 0x59, 0xc5, 0x84, 0x06, 0xb5,
+- 0x8b, 0xd0, 0x89, 0x9c, 0x4a, 0x79, 0x16, 0xc6,
+- 0x3d, 0x74, 0x54, 0xfa, 0x44, 0xcd, 0x23, 0x26,
+- 0x5c, 0xcf, 0x7e, 0x28, 0x92, 0x32, 0xbf, 0xdf,
+- 0xa7, 0x20, 0x3c, 0x74, 0x58, 0x2a, 0x9a, 0xde,
+- 0x61, 0x00, 0x1c, 0x4f, 0xff, 0x59, 0xc4, 0x22,
+- 0xac, 0x3c, 0xd0, 0xe8, 0x6c, 0xf9, 0x97, 0x1b,
+- 0x58, 0x9b, 0xad, 0x71, 0xe8, 0xa9, 0xb5, 0x0d,
+- 0xee, 0x2f, 0x04, 0x1f, 0x7f, 0xbc, 0x99, 0xee,
+- 0x84, 0xff, 0x42, 0x60, 0xdc, 0x3a, 0x18, 0xa5,
+- 0x81, 0xf9, 0xef, 0xdc, 0x7a, 0x0f, 0x65, 0x41,
+- 0x2f, 0xa3, 0xd3, 0xf9, 0xc2, 0xcb, 0xc0, 0x4d,
+- 0x8f, 0xd3, 0x76, 0x96, 0xad, 0x49, 0x6d, 0x38,
+- 0x3d, 0x39, 0x0b, 0x6c, 0x80, 0xb7, 0x54, 0x69,
+- 0xf0, 0x2c, 0x90, 0x02, 0x29, 0x0d, 0x1c, 0x12,
+- 0xad, 0x55, 0xc3, 0x8b, 0x68, 0xd9, 0xcc, 0xb3,
+- 0xb2, 0x64, 0x33, 0x90, 0x5e, 0xca, 0x4b, 0xe2,
+- 0xfb, 0x75, 0xdc, 0x63, 0xf7, 0x9f, 0x82, 0x74,
+- 0xf0, 0xc9, 0xaa, 0x7f, 0xe9, 0x2a, 0x9b, 0x33,
+- 0xbc, 0x88, 0x00, 0x7f, 0xca, 0xb2, 0x1f, 0x14,
+- 0xdb, 0xc5, 0x8e, 0x7b, 0x11, 0x3c, 0x3e, 0x08,
+- 0xf3, 0x83, 0xe8, 0xe0, 0x94, 0x86, 0x2e, 0x92,
+- 0x78, 0x6b, 0x01, 0xc9, 0xc7, 0x83, 0xba, 0x21,
+- 0x6a, 0x25, 0x15, 0x33, 0x4e, 0x45, 0x08, 0xec,
+- 0x35, 0xdb, 0xe0, 0x6e, 0x31, 0x51, 0x79, 0xa9,
+- 0x42, 0x44, 0x65, 0xc1, 0xa0, 0xf1, 0xf9, 0x2a,
+- 0x70, 0xd5, 0xb6, 0xc6, 0xc1, 0x8c, 0x39, 0xfc,
+- 0x25, 0xa6, 0x55, 0xd9, 0xdd, 0x2d, 0x4c, 0xec,
+- 0x49, 0xc6, 0xeb, 0x0e, 0xa8, 0x25, 0x2a, 0x16,
+- 0x1b, 0x66, 0x84, 0xda, 0xe2, 0x92, 0xe5, 0xc0,
+- 0xc8, 0x53, 0x07, 0xaf, 0x80, 0x84, 0xec, 0xfd,
+- 0xcd, 0xd1, 0x6e, 0xcd, 0x6f, 0x6a, 0xf5, 0x36,
+- 0xc5, 0x15, 0xe5, 0x25, 0x7d, 0x77, 0xd1, 0x1a,
+- 0x93, 0x36, 0xa9, 0xcf, 0x7c, 0xa4, 0x54, 0x4a,
+- 0x06, 0x51, 0x48, 0x4e, 0xf6, 0x59, 0x87, 0xd2,
+- 0x04, 0x02, 0xef, 0xd3, 0x44, 0xde, 0x76, 0x31,
+- 0xb3, 0x34, 0x17, 0x1b, 0x9d, 0x66, 0x11, 0x9f,
+- 0x1e, 0xcc, 0x17, 0xe9, 0xc7, 0x3c, 0x1b, 0xe7,
+- 0xcb, 0x50, 0x08, 0xfc, 0xdc, 0x2b, 0x24, 0xdb,
+- 0x65, 0x83, 0xd0, 0x3b, 0xe3, 0x30, 0xea, 0x94,
+- 0x6c, 0xe7, 0xe8, 0x35, 0x32, 0xc7, 0xdb, 0x64,
+- 0xb4, 0x01, 0xab, 0x36, 0x2c, 0x77, 0x13, 0xaf,
+- 0xf8, 0x2b, 0x88, 0x3f, 0x54, 0x39, 0xc4, 0x44,
+- 0xfe, 0xef, 0x6f, 0x68, 0x34, 0xbe, 0x0f, 0x05,
+- 0x16, 0x6d, 0xf6, 0x0a, 0x30, 0xe7, 0xe3, 0xed,
+- 0xc4, 0xde, 0x3c, 0x1b, 0x13, 0xd8, 0xdb, 0xfe,
+- 0x41, 0x62, 0xe5, 0x28, 0xd4, 0x8d, 0xa3, 0xc7,
+- 0x93, 0x97, 0xc6, 0x48, 0x45, 0x1d, 0x9f, 0x83,
+- 0xdf, 0x4b, 0x40, 0x3e, 0x42, 0x25, 0x87, 0x80,
+- 0x4c, 0x7d, 0xa8, 0xd4, 0x98, 0x23, 0x95, 0x75,
+- 0x41, 0x8c, 0xda, 0x41, 0x9b, 0xd4, 0xa7, 0x06,
+- 0xb5, 0xf1, 0x71, 0x09, 0x53, 0xbe, 0xca, 0xbf,
+- 0x32, 0x03, 0xed, 0xf0, 0x50, 0x1c, 0x56, 0x39,
+- 0x5b, 0xa4, 0x75, 0x18, 0xf7, 0x9b, 0x58, 0xef,
+- 0x53, 0xfc, 0x2a, 0x38, 0x23, 0x15, 0x75, 0xcd,
+- 0x45, 0xe5, 0x5a, 0x82, 0x55, 0xba, 0x21, 0xfa,
+- 0xd4, 0xbd, 0xc6, 0x94, 0x7c, 0xc5, 0x80, 0x12,
+- 0xf7, 0x4b, 0x32, 0xc4, 0x9a, 0x82, 0xd8, 0x28,
+- 0x8f, 0xd9, 0xc2, 0x0f, 0x60, 0x03, 0xbe, 0x5e,
+- 0x21, 0xd6, 0x5f, 0x58, 0xbf, 0x5c, 0xb1, 0x32,
+- 0x82, 0x8d, 0xa9, 0xe5, 0xf2, 0x66, 0x1a, 0xc0,
+- 0xa0, 0xbc, 0x58, 0x2f, 0x71, 0xf5, 0x2f, 0xed,
+- 0xd1, 0x26, 0xb9, 0xd8, 0x49, 0x5a, 0x07, 0x19,
+- 0x01, 0x7c, 0x59, 0xb0, 0xf8, 0xa4, 0xb7, 0xd3,
+- 0x7b, 0x1a, 0x8c, 0x38, 0xf4, 0x50, 0xa4, 0x59,
+- 0xb0, 0xcc, 0x41, 0x0b, 0x88, 0x7f, 0xe5, 0x31,
+- 0xb3, 0x42, 0xba, 0xa2, 0x7e, 0xd4, 0x32, 0x71,
+- 0x45, 0x87, 0x48, 0xa9, 0xc2, 0xf2, 0x89, 0xb3,
+- 0xe4, 0xa7, 0x7e, 0x52, 0x15, 0x61, 0xfa, 0xfe,
+- 0xc9, 0xdd, 0x81, 0xeb, 0x13, 0xab, 0xab, 0xc3,
+- 0x98, 0x59, 0xd8, 0x16, 0x3d, 0x14, 0x7a, 0x1c,
+- 0x3c, 0x41, 0x9a, 0x16, 0x16, 0x9b, 0xd2, 0xd2,
+- 0x69, 0x3a, 0x29, 0x23, 0xac, 0x86, 0x32, 0xa5,
+- 0x48, 0x9c, 0x9e, 0xf3, 0x47, 0x77, 0x81, 0x70,
+- 0x24, 0xe8, 0x85, 0xd2, 0xf5, 0xb5, 0xfa, 0xff,
+- 0x59, 0x6a, 0xd3, 0x50, 0x59, 0x43, 0x59, 0xde,
+- 0xd9, 0xf1, 0x55, 0xa5, 0x0c, 0xc3, 0x1a, 0x1a,
+- 0x18, 0x34, 0x0d, 0x1a, 0x63, 0x33, 0xed, 0x10,
+- 0xe0, 0x1d, 0x2a, 0x18, 0xd2, 0xc0, 0x54, 0xa8,
+- 0xca, 0xb5, 0x9a, 0xd3, 0xdd, 0xca, 0x45, 0x84,
+- 0x50, 0xe7, 0x0f, 0xfe, 0xa4, 0x99, 0x5a, 0xbe,
+- 0x43, 0x2d, 0x9a, 0xcb, 0x92, 0x3f, 0x5a, 0x1d,
+- 0x85, 0xd8, 0xc9, 0xdf, 0x68, 0xc9, 0x12, 0x80,
+- 0x56, 0x0c, 0xdc, 0x00, 0xdc, 0x3a, 0x7d, 0x9d,
+- 0xa3, 0xa2, 0xe8, 0x4d, 0xbf, 0xf9, 0x70, 0xa0,
+- 0xa4, 0x13, 0x4f, 0x6b, 0xaf, 0x0a, 0x89, 0x7f,
+- 0xda, 0xf0, 0xbf, 0x9b, 0xc8, 0x1d, 0xe5, 0xf8,
+- 0x2e, 0x8b, 0x07, 0xb5, 0x73, 0x1b, 0xcc, 0xa2,
+- 0xa6, 0xad, 0x30, 0xbc, 0x78, 0x3c, 0x5b, 0x10,
+- 0xfa, 0x5e, 0x62, 0x2d, 0x9e, 0x64, 0xb3, 0x33,
+- 0xce, 0xf9, 0x1f, 0x86, 0xe7, 0x8b, 0xa2, 0xb8,
+- 0xe8, 0x99, 0x57, 0x8c, 0x11, 0xed, 0x66, 0xd9,
+- 0x3c, 0x72, 0xb9, 0xc3, 0xe6, 0x4e, 0x17, 0x3a,
+- 0x6a, 0xcb, 0x42, 0x24, 0x06, 0xed, 0x3e, 0x4e,
+- 0xa3, 0xe8, 0x6a, 0x94, 0xda, 0x0d, 0x4e, 0xd5,
+- 0x14, 0x19, 0xcf, 0xb6, 0x26, 0xd8, 0x2e, 0xcc,
+- 0x64, 0x76, 0x38, 0x49, 0x4d, 0xfe, 0x30, 0x6d,
+- 0xe4, 0xc8, 0x8c, 0x7b, 0xc4, 0xe0, 0x35, 0xba,
+- 0x22, 0x6e, 0x76, 0xe1, 0x1a, 0xf2, 0x53, 0xc3,
+- 0x28, 0xa2, 0x82, 0x1f, 0x61, 0x69, 0xad, 0xc1,
+- 0x7b, 0x28, 0x4b, 0x1e, 0x6c, 0x85, 0x95, 0x9b,
+- 0x51, 0xb5, 0x17, 0x7f, 0x12, 0x69, 0x8c, 0x24,
+- 0xd5, 0xc7, 0x5a, 0x5a, 0x11, 0x54, 0xff, 0x5a,
+- 0xf7, 0x16, 0xc3, 0x91, 0xa6, 0xf0, 0xdc, 0x0a,
+- 0xb6, 0xa7, 0x4a, 0x0d, 0x7a, 0x58, 0xfe, 0xa5,
+- 0xf5, 0xcb, 0x8f, 0x7b, 0x0e, 0xea, 0x57, 0xe7,
+- 0xbd, 0x79, 0xd6, 0x1c, 0x88, 0x23, 0x6c, 0xf2,
+- 0x4d, 0x29, 0x77, 0x53, 0x35, 0x6a, 0x00, 0x8d,
+- 0xcd, 0xa3, 0x58, 0xbe, 0x77, 0x99, 0x18, 0xf8,
+- 0xe6, 0xe1, 0x8f, 0xe9, 0x37, 0x8f, 0xe3, 0xe2,
+- 0x5a, 0x8a, 0x93, 0x25, 0xaf, 0xf3, 0x78, 0x80,
+- 0xbe, 0xa6, 0x1b, 0xc6, 0xac, 0x8b, 0x1c, 0x91,
+- 0x58, 0xe1, 0x9f, 0x89, 0x35, 0x9d, 0x1d, 0x21,
+- 0x29, 0x9f, 0xf4, 0x99, 0x02, 0x27, 0x0f, 0xa8,
+- 0x4f, 0x79, 0x94, 0x2b, 0x33, 0x2c, 0xda, 0xa2,
+- 0x26, 0x39, 0x83, 0x94, 0xef, 0x27, 0xd8, 0x53,
+- 0x8f, 0x66, 0x0d, 0xe4, 0x41, 0x7d, 0x34, 0xcd,
+- 0x43, 0x7c, 0x95, 0x0a, 0x53, 0xef, 0x66, 0xda,
+- 0x7e, 0x9b, 0xf3, 0x93, 0xaf, 0xd0, 0x73, 0x71,
+- 0xba, 0x40, 0x9b, 0x74, 0xf8, 0xd7, 0xd7, 0x41,
+- 0x6d, 0xaf, 0x72, 0x9c, 0x8d, 0x21, 0x87, 0x3c,
+- 0xfd, 0x0a, 0x90, 0xa9, 0x47, 0x96, 0x9e, 0xd3,
+- 0x88, 0xee, 0x73, 0xcf, 0x66, 0x2f, 0x52, 0x56,
+- 0x6d, 0xa9, 0x80, 0x4c, 0xe2, 0x6f, 0x62, 0x88,
+- 0x3f, 0x0e, 0x54, 0x17, 0x48, 0x80, 0x5d, 0xd3,
+- 0xc3, 0xda, 0x25, 0x3d, 0xa1, 0xc8, 0xcb, 0x9f,
+- 0x9b, 0x70, 0xb3, 0xa1, 0xeb, 0x04, 0x52, 0xa1,
+- 0xf2, 0x22, 0x0f, 0xfc, 0xc8, 0x18, 0xfa, 0xf9,
+- 0x85, 0x9c, 0xf1, 0xac, 0xeb, 0x0c, 0x02, 0x46,
+- 0x75, 0xd2, 0xf5, 0x2c, 0xe3, 0xd2, 0x59, 0x94,
+- 0x12, 0xf3, 0x3c, 0xfc, 0xd7, 0x92, 0xfa, 0x36,
+- 0xba, 0x61, 0x34, 0x38, 0x7c, 0xda, 0x48, 0x3e,
+- 0x08, 0xc9, 0x39, 0x23, 0x5e, 0x02, 0x2c, 0x1a,
+- 0x18, 0x7e, 0xb4, 0xd9, 0xfd, 0x9e, 0x40, 0x02,
+- 0xb1, 0x33, 0x37, 0x32, 0xe7, 0xde, 0xd6, 0xd0,
+- 0x7c, 0x58, 0x65, 0x4b, 0xf8, 0x34, 0x27, 0x9c,
+- 0x44, 0xb4, 0xbd, 0xe9, 0xe9, 0x4c, 0x78, 0x7d,
+- 0x4b, 0x9f, 0xce, 0xb1, 0xcd, 0x47, 0xa5, 0x37,
+- 0xe5, 0x6d, 0xbd, 0xb9, 0x43, 0x94, 0x0a, 0xd4,
+- 0xd6, 0xf9, 0x04, 0x5f, 0xb5, 0x66, 0x6c, 0x1a,
+- 0x35, 0x12, 0xe3, 0x36, 0x28, 0x27, 0x36, 0x58,
+- 0x01, 0x2b, 0x79, 0xe4, 0xba, 0x6d, 0x10, 0x7d,
+- 0x65, 0xdf, 0x84, 0x95, 0xf4, 0xd5, 0xb6, 0x8f,
+- 0x2b, 0x9f, 0x96, 0x00, 0x86, 0x60, 0xf0, 0x21,
+- 0x76, 0xa8, 0x6a, 0x8c, 0x28, 0x1c, 0xb3, 0x6b,
+- 0x97, 0xd7, 0xb6, 0x53, 0x2a, 0xcc, 0xab, 0x40,
+- 0x9d, 0x62, 0x79, 0x58, 0x52, 0xe6, 0x65, 0xb7,
+- 0xab, 0x55, 0x67, 0x9c, 0x89, 0x7c, 0x03, 0xb0,
+- 0x73, 0x59, 0xc5, 0x81, 0xf5, 0x18, 0x17, 0x5c,
+- 0x89, 0xf3, 0x78, 0x35, 0x44, 0x62, 0x78, 0x72,
+- 0xd0, 0x96, 0xeb, 0x31, 0xe7, 0x87, 0x77, 0x14,
+- 0x99, 0x51, 0xf2, 0x59, 0x26, 0x9e, 0xb5, 0xa6,
+- 0x45, 0xfe, 0x6e, 0xbd, 0x07, 0x4c, 0x94, 0x5a,
+- 0xa5, 0x7d, 0xfc, 0xf1, 0x2b, 0x77, 0xe2, 0xfe,
+- 0x17, 0xd4, 0x84, 0xa0, 0xac, 0xb5, 0xc7, 0xda,
+- 0xa9, 0x1a, 0xb6, 0xf3, 0x74, 0x11, 0xb4, 0x9d,
+- 0xfb, 0x79, 0x2e, 0x04, 0x2d, 0x50, 0x28, 0x83,
+- 0xbf, 0xc6, 0x52, 0xd3, 0x34, 0xd6, 0xe8, 0x7a,
+- 0xb6, 0xea, 0xe7, 0xa8, 0x6c, 0x15, 0x1e, 0x2c,
+- 0x57, 0xbc, 0x48, 0x4e, 0x5f, 0x5c, 0xb6, 0x92,
+- 0xd2, 0x49, 0x77, 0x81, 0x6d, 0x90, 0x70, 0xae,
+- 0x98, 0xa1, 0x03, 0x0d, 0x6b, 0xb9, 0x77, 0x14,
+- 0xf1, 0x4e, 0x23, 0xd3, 0xf8, 0x68, 0xbd, 0xc2,
+- 0xfe, 0x04, 0xb7, 0x5c, 0xc5, 0x17, 0x60, 0x8f,
+- 0x65, 0x54, 0xa4, 0x7a, 0x42, 0xdc, 0x18, 0x0d,
+- 0xb5, 0xcf, 0x0f, 0xd3, 0xc7, 0x91, 0x66, 0x1b,
+- 0x45, 0x42, 0x27, 0x75, 0x50, 0xe5, 0xee, 0xb8,
+- 0x7f, 0x33, 0x2c, 0xba, 0x4a, 0x92, 0x4d, 0x2c,
+- 0x3c, 0xe3, 0x0d, 0x80, 0x01, 0xba, 0x0d, 0x29,
+- 0xd8, 0x3c, 0xe9, 0x13, 0x16, 0x57, 0xe6, 0xea,
+- 0x94, 0x52, 0xe7, 0x00, 0x4d, 0x30, 0xb0, 0x0f,
+- 0x35, 0xb8, 0xb8, 0xa7, 0xb1, 0xb5, 0x3b, 0x44,
+- 0xe1, 0x2f, 0xfd, 0x88, 0xed, 0x43, 0xe7, 0x52,
+- 0x10, 0x93, 0xb3, 0x8a, 0x30, 0x6b, 0x0a, 0xf7,
+- 0x23, 0xc6, 0x50, 0x9d, 0x4a, 0xb0, 0xde, 0xc3,
+- 0xdc, 0x9b, 0x2f, 0x01, 0x56, 0x36, 0x09, 0xc5,
+- 0x2f, 0x6b, 0xfe, 0xf1, 0xd8, 0x27, 0x45, 0x03,
+- 0x30, 0x5e, 0x5c, 0x5b, 0xb4, 0x62, 0x0e, 0x1a,
+- 0xa9, 0x21, 0x2b, 0x92, 0x94, 0x87, 0x62, 0x57,
+- 0x4c, 0x10, 0x74, 0x1a, 0xf1, 0x0a, 0xc5, 0x84,
+- 0x3b, 0x9e, 0x72, 0x02, 0xd7, 0xcc, 0x09, 0x56,
+- 0xbd, 0x54, 0xc1, 0xf0, 0xc3, 0xe3, 0xb3, 0xf8,
+- 0xd2, 0x0d, 0x61, 0xcb, 0xef, 0xce, 0x0d, 0x05,
+- 0xb0, 0x98, 0xd9, 0x8e, 0x4f, 0xf9, 0xbc, 0x93,
+- 0xa6, 0xea, 0xc8, 0xcf, 0x10, 0x53, 0x4b, 0xf1,
+- 0xec, 0xfc, 0x89, 0xf9, 0x64, 0xb0, 0x22, 0xbf,
+- 0x9e, 0x55, 0x46, 0x9f, 0x7c, 0x50, 0x8e, 0x84,
+- 0x54, 0x20, 0x98, 0xd7, 0x6c, 0x40, 0x1e, 0xdb,
+- 0x69, 0x34, 0x78, 0x61, 0x24, 0x21, 0x9c, 0x8a,
+- 0xb3, 0x62, 0x31, 0x8b, 0x6e, 0xf5, 0x2a, 0x35,
+- 0x86, 0x13, 0xb1, 0x6c, 0x64, 0x2e, 0x41, 0xa5,
+- 0x05, 0xf2, 0x42, 0xba, 0xd2, 0x3a, 0x0d, 0x8e,
+- 0x8a, 0x59, 0x94, 0x3c, 0xcf, 0x36, 0x27, 0x82,
+- 0xc2, 0x45, 0xee, 0x58, 0xcd, 0x88, 0xb4, 0xec,
+- 0xde, 0xb2, 0x96, 0x0a, 0xaf, 0x38, 0x6f, 0x88,
+- 0xd7, 0xd8, 0xe1, 0xdf, 0xb9, 0x96, 0xa9, 0x0a,
+- 0xb1, 0x95, 0x28, 0x86, 0x20, 0xe9, 0x17, 0x49,
+- 0xa2, 0x29, 0x38, 0xaa, 0xa5, 0xe9, 0x6e, 0xf1,
+- 0x19, 0x27, 0xc0, 0xd5, 0x2a, 0x22, 0xc3, 0x0b,
+- 0xdb, 0x7c, 0x73, 0x10, 0xb9, 0xba, 0x89, 0x76,
+- 0x54, 0xae, 0x7d, 0x71, 0xb3, 0x93, 0xf6, 0x32,
+- 0xe6, 0x47, 0x43, 0x55, 0xac, 0xa0, 0x0d, 0xc2,
+- 0x93, 0x27, 0x4a, 0x8e, 0x0e, 0x74, 0x15, 0xc7,
+- 0x0b, 0x85, 0xd9, 0x0c, 0xa9, 0x30, 0x7a, 0x3e,
+- 0xea, 0x8f, 0x85, 0x6d, 0x3a, 0x12, 0x4f, 0x72,
+- 0x69, 0x58, 0x7a, 0x80, 0xbb, 0xb5, 0x97, 0xf3,
+- 0xcf, 0x70, 0xd2, 0x5d, 0xdd, 0x4d, 0x21, 0x79,
+- 0x54, 0x4d, 0xe4, 0x05, 0xe8, 0xbd, 0xc2, 0x62,
+- 0xb1, 0x3b, 0x77, 0x1c, 0xd6, 0x5c, 0xf3, 0xa0,
+- 0x79, 0x00, 0xa8, 0x6c, 0x29, 0xd9, 0x18, 0x24,
+- 0x36, 0xa2, 0x46, 0xc0, 0x96, 0x65, 0x7f, 0xbd,
+- 0x2a, 0xed, 0x36, 0x16, 0x0c, 0xaa, 0x9f, 0xf4,
+- 0xc5, 0xb4, 0xe2, 0x12, 0xed, 0x69, 0xed, 0x4f,
+- 0x26, 0x2c, 0x39, 0x52, 0x89, 0x98, 0xe7, 0x2c,
+- 0x99, 0xa4, 0x9e, 0xa3, 0x9b, 0x99, 0x46, 0x7a,
+- 0x3a, 0xdc, 0xa8, 0x59, 0xa3, 0xdb, 0xc3, 0x3b,
+- 0x95, 0x0d, 0x3b, 0x09, 0x6e, 0xee, 0x83, 0x5d,
+- 0x32, 0x4d, 0xed, 0xab, 0xfa, 0x98, 0x14, 0x4e,
+- 0xc3, 0x15, 0x45, 0x53, 0x61, 0xc4, 0x93, 0xbd,
+- 0x90, 0xf4, 0x99, 0x95, 0x4c, 0xe6, 0x76, 0x92,
+- 0x29, 0x90, 0x46, 0x30, 0x92, 0x69, 0x7d, 0x13,
+- 0xf2, 0xa5, 0xcd, 0x69, 0x49, 0x44, 0xb2, 0x0f,
+- 0x63, 0x40, 0x36, 0x5f, 0x09, 0xe2, 0x78, 0xf8,
+- 0x91, 0xe3, 0xe2, 0xfa, 0x10, 0xf7, 0xc8, 0x24,
+- 0xa8, 0x89, 0x32, 0x5c, 0x37, 0x25, 0x1d, 0xb2,
+- 0xea, 0x17, 0x8a, 0x0a, 0xa9, 0x64, 0xc3, 0x7c,
+- 0x3c, 0x7c, 0xbd, 0xc6, 0x79, 0x34, 0xe7, 0xe2,
+- 0x85, 0x8e, 0xbf, 0xf8, 0xde, 0x92, 0xa0, 0xae,
+- 0x20, 0xc4, 0xf6, 0xbb, 0x1f, 0x38, 0x19, 0x0e,
+- 0xe8, 0x79, 0x9c, 0xa1, 0x23, 0xe9, 0x54, 0x7e,
+- 0x37, 0x2f, 0xe2, 0x94, 0x32, 0xaf, 0xa0, 0x23,
+- 0x49, 0xe4, 0xc0, 0xb3, 0xac, 0x00, 0x8f, 0x36,
+- 0x05, 0xc4, 0xa6, 0x96, 0xec, 0x05, 0x98, 0x4f,
+- 0x96, 0x67, 0x57, 0x1f, 0x20, 0x86, 0x1b, 0x2d,
+- 0x69, 0xe4, 0x29, 0x93, 0x66, 0x5f, 0xaf, 0x6b,
+- 0x88, 0x26, 0x2c, 0x67, 0x02, 0x4b, 0x52, 0xd0,
+- 0x83, 0x7a, 0x43, 0x1f, 0xc0, 0x71, 0x15, 0x25,
+- 0x77, 0x65, 0x08, 0x60, 0x11, 0x76, 0x4c, 0x8d,
+- 0xed, 0xa9, 0x27, 0xc6, 0xb1, 0x2a, 0x2c, 0x6a,
+- 0x4a, 0x97, 0xf5, 0xc6, 0xb7, 0x70, 0x42, 0xd3,
+- 0x03, 0xd1, 0x24, 0x95, 0xec, 0x6d, 0xab, 0x38,
+- 0x72, 0xce, 0xe2, 0x8b, 0x33, 0xd7, 0x51, 0x09,
+- 0xdc, 0x45, 0xe0, 0x09, 0x96, 0x32, 0xf3, 0xc4,
+- 0x84, 0xdc, 0x73, 0x73, 0x2d, 0x1b, 0x11, 0x98,
+- 0xc5, 0x0e, 0x69, 0x28, 0x94, 0xc7, 0xb5, 0x4d,
+- 0xc8, 0x8a, 0xd0, 0xaa, 0x13, 0x2e, 0x18, 0x74,
+- 0xdd, 0xd1, 0x1e, 0xf3, 0x90, 0xe8, 0xfc, 0x9a,
+- 0x72, 0x4a, 0x0e, 0xd1, 0xe4, 0xfb, 0x0d, 0x96,
+- 0xd1, 0x0c, 0x79, 0x85, 0x1b, 0x1c, 0xfe, 0xe1,
+- 0x62, 0x8f, 0x7a, 0x73, 0x32, 0xab, 0xc8, 0x18,
+- 0x69, 0xe3, 0x34, 0x30, 0xdf, 0x13, 0xa6, 0xe5,
+- 0xe8, 0x0e, 0x67, 0x7f, 0x81, 0x11, 0xb4, 0x60,
+- 0xc7, 0xbd, 0x79, 0x65, 0x50, 0xdc, 0xc4, 0x5b,
+- 0xde, 0x39, 0xa4, 0x01, 0x72, 0x63, 0xf3, 0xd1,
+- 0x64, 0x4e, 0xdf, 0xfc, 0x27, 0x92, 0x37, 0x0d,
+- 0x57, 0xcd, 0x11, 0x4f, 0x11, 0x04, 0x8e, 0x1d,
+- 0x16, 0xf7, 0xcd, 0x92, 0x9a, 0x99, 0x30, 0x14,
+- 0xf1, 0x7c, 0x67, 0x1b, 0x1f, 0x41, 0x0b, 0xe8,
+- 0x32, 0xe8, 0xb8, 0xc1, 0x4f, 0x54, 0x86, 0x4f,
+- 0xe5, 0x79, 0x81, 0x73, 0xcd, 0x43, 0x59, 0x68,
+- 0x73, 0x02, 0x3b, 0x78, 0x21, 0x72, 0x43, 0x00,
+- 0x49, 0x17, 0xf7, 0x00, 0xaf, 0x68, 0x24, 0x53,
+- 0x05, 0x0a, 0xc3, 0x33, 0xe0, 0x33, 0x3f, 0x69,
+- 0xd2, 0x84, 0x2f, 0x0b, 0xed, 0xde, 0x04, 0xf4,
+- 0x11, 0x94, 0x13, 0x69, 0x51, 0x09, 0x28, 0xde,
+- 0x57, 0x5c, 0xef, 0xdc, 0x9a, 0x49, 0x1c, 0x17,
+- 0x97, 0xf3, 0x96, 0xc1, 0x7f, 0x5d, 0x2e, 0x7d,
+- 0x55, 0xb8, 0xb3, 0x02, 0x09, 0xb3, 0x1f, 0xe7,
+- 0xc9, 0x8d, 0xa3, 0x36, 0x34, 0x8a, 0x77, 0x13,
+- 0x30, 0x63, 0x4c, 0xa5, 0xcd, 0xc3, 0xe0, 0x7e,
+- 0x05, 0xa1, 0x7b, 0x0c, 0xcb, 0x74, 0x47, 0x31,
+- 0x62, 0x03, 0x43, 0xf1, 0x87, 0xb4, 0xb0, 0x85,
+- 0x87, 0x8e, 0x4b, 0x25, 0xc7, 0xcf, 0xae, 0x4b,
+- 0x36, 0x46, 0x3e, 0x62, 0xbc, 0x6f, 0xeb, 0x5f,
+- 0x73, 0xac, 0xe6, 0x07, 0xee, 0xc1, 0xa1, 0xd6,
+- 0xc4, 0xab, 0xc9, 0xd6, 0x89, 0x45, 0xe1, 0xf1,
+- 0x04, 0x4e, 0x1a, 0x6f, 0xbb, 0x4f, 0x3a, 0xa3,
+- 0xa0, 0xcb, 0xa3, 0x0a, 0xd8, 0x71, 0x35, 0x55,
+- 0xe4, 0xbc, 0x2e, 0x04, 0x06, 0xe6, 0xff, 0x5b,
+- 0x1c, 0xc0, 0x11, 0x7c, 0xc5, 0x17, 0xf3, 0x38,
+- 0xcf, 0xe9, 0xba, 0x0f, 0x0e, 0xef, 0x02, 0xc2,
+- 0x8d, 0xc6, 0xbc, 0x4b, 0x67, 0x20, 0x95, 0xd7,
+- 0x2c, 0x45, 0x5b, 0x86, 0x44, 0x8c, 0x6f, 0x2e,
+- 0x7e, 0x9f, 0x1c, 0x77, 0xba, 0x6b, 0x0e, 0xa3,
+- 0x69, 0xdc, 0xab, 0x24, 0x57, 0x60, 0x47, 0xc1,
+- 0xd1, 0xa5, 0x9d, 0x23, 0xe6, 0xb1, 0x37, 0xfe,
+- 0x93, 0xd2, 0x4c, 0x46, 0xf9, 0x0c, 0xc6, 0xfb,
+- 0xd6, 0x9d, 0x99, 0x69, 0xab, 0x7a, 0x07, 0x0c,
+- 0x65, 0xe7, 0xc4, 0x08, 0x96, 0xe2, 0xa5, 0x01,
+- 0x3f, 0x46, 0x07, 0x05, 0x7e, 0xe8, 0x9a, 0x90,
+- 0x50, 0xdc, 0xe9, 0x7a, 0xea, 0xa1, 0x39, 0x6e,
+- 0x66, 0xe4, 0x6f, 0xa5, 0x5f, 0xb2, 0xd9, 0x5b,
+- 0xf5, 0xdb, 0x2a, 0x32, 0xf0, 0x11, 0x6f, 0x7c,
+- 0x26, 0x10, 0x8f, 0x3d, 0x80, 0xe9, 0x58, 0xf7,
+- 0xe0, 0xa8, 0x57, 0xf8, 0xdb, 0x0e, 0xce, 0x99,
+- 0x63, 0x19, 0x3d, 0xd5, 0xec, 0x1b, 0x77, 0x69,
+- 0x98, 0xf6, 0xe4, 0x5f, 0x67, 0x17, 0x4b, 0x09,
+- 0x85, 0x62, 0x82, 0x70, 0x18, 0xe2, 0x9a, 0x78,
+- 0xe2, 0x62, 0xbd, 0xb4, 0xf1, 0x42, 0xc6, 0xfb,
+- 0x08, 0xd0, 0xbd, 0xeb, 0x4e, 0x09, 0xf2, 0xc8,
+- 0x1e, 0xdc, 0x3d, 0x32, 0x21, 0x56, 0x9c, 0x4f,
+- 0x35, 0xf3, 0x61, 0x06, 0x72, 0x84, 0xc4, 0x32,
+- 0xf2, 0xf1, 0xfa, 0x0b, 0x2f, 0xc3, 0xdb, 0x02,
+- 0x04, 0xc2, 0xde, 0x57, 0x64, 0x60, 0x8d, 0xcf,
+- 0xcb, 0x86, 0x5d, 0x97, 0x3e, 0xb1, 0x9c, 0x01,
+- 0xd6, 0x28, 0x8f, 0x99, 0xbc, 0x46, 0xeb, 0x05,
+- 0xaf, 0x7e, 0xb8, 0x21, 0x2a, 0x56, 0x85, 0x1c,
+- 0xb3, 0x71, 0xa0, 0xde, 0xca, 0x96, 0xf1, 0x78,
+- 0x49, 0xa2, 0x99, 0x81, 0x80, 0x5c, 0x01, 0xf5,
+- 0xa0, 0xa2, 0x56, 0x63, 0xe2, 0x70, 0x07, 0xa5,
+- 0x95, 0xd6, 0x85, 0xeb, 0x36, 0x9e, 0xa9, 0x51,
+- 0x66, 0x56, 0x5f, 0x1d, 0x02, 0x19, 0xe2, 0xf6,
+- 0x4f, 0x73, 0x38, 0x09, 0x75, 0x64, 0x48, 0xe0,
+- 0xf1, 0x7e, 0x0e, 0xe8, 0x9d, 0xf9, 0xed, 0x94,
+- 0xfe, 0x16, 0x26, 0x62, 0x49, 0x74, 0xf4, 0xb0,
+- 0xd4, 0xa9, 0x6c, 0xb0, 0xfd, 0x53, 0xe9, 0x81,
+- 0xe0, 0x7a, 0xbf, 0xcf, 0xb5, 0xc4, 0x01, 0x81,
+- 0x79, 0x99, 0x77, 0x01, 0x3b, 0xe9, 0xa2, 0xb6,
+- 0xe6, 0x6a, 0x8a, 0x9e, 0x56, 0x1c, 0x8d, 0x1e,
+- 0x8f, 0x06, 0x55, 0x2c, 0x6c, 0xdc, 0x92, 0x87,
+- 0x64, 0x3b, 0x4b, 0x19, 0xa1, 0x13, 0x64, 0x1d,
+- 0x4a, 0xe9, 0xc0, 0x00, 0xb8, 0x95, 0xef, 0x6b,
+- 0x1a, 0x86, 0x6d, 0x37, 0x52, 0x02, 0xc2, 0xe0,
+- 0xc8, 0xbb, 0x42, 0x0c, 0x02, 0x21, 0x4a, 0xc9,
+- 0xef, 0xa0, 0x54, 0xe4, 0x5e, 0x16, 0x53, 0x81,
+- 0x70, 0x62, 0x10, 0xaf, 0xde, 0xb8, 0xb5, 0xd3,
+- 0xe8, 0x5e, 0x6c, 0xc3, 0x8a, 0x3e, 0x18, 0x07,
+- 0xf2, 0x2f, 0x7d, 0xa7, 0xe1, 0x3d, 0x4e, 0xb4,
+- 0x26, 0xa7, 0xa3, 0x93, 0x86, 0xb2, 0x04, 0x1e,
+- 0x53, 0x5d, 0x86, 0xd6, 0xde, 0x65, 0xca, 0xe3,
+- 0x4e, 0xc1, 0xcf, 0xef, 0xc8, 0x70, 0x1b, 0x83,
+- 0x13, 0xdd, 0x18, 0x8b, 0x0d, 0x76, 0xd2, 0xf6,
+- 0x37, 0x7a, 0x93, 0x7a, 0x50, 0x11, 0x9f, 0x96,
+- 0x86, 0x25, 0xfd, 0xac, 0xdc, 0xbe, 0x18, 0x93,
+- 0x19, 0x6b, 0xec, 0x58, 0x4f, 0xb9, 0x75, 0xa7,
+- 0xdd, 0x3f, 0x2f, 0xec, 0xc8, 0x5a, 0x84, 0xab,
+- 0xd5, 0xe4, 0x8a, 0x07, 0xf6, 0x4d, 0x23, 0xd6,
+- 0x03, 0xfb, 0x03, 0x6a, 0xea, 0x66, 0xbf, 0xd4,
+- 0xb1, 0x34, 0xfb, 0x78, 0xe9, 0x55, 0xdc, 0x7c,
+- 0x3d, 0x9c, 0xe5, 0x9a, 0xac, 0xc3, 0x7a, 0x80,
+- 0x24, 0x6d, 0xa0, 0xef, 0x25, 0x7c, 0xb7, 0xea,
+- 0xce, 0x4d, 0x5f, 0x18, 0x60, 0xce, 0x87, 0x22,
+- 0x66, 0x2f, 0xd5, 0xdd, 0xdd, 0x02, 0x21, 0x75,
+- 0x82, 0xa0, 0x1f, 0x58, 0xc6, 0xd3, 0x62, 0xf7,
+- 0x32, 0xd8, 0xaf, 0x1e, 0x07, 0x77, 0x51, 0x96,
+- 0xd5, 0x6b, 0x1e, 0x7e, 0x80, 0x02, 0xe8, 0x67,
+- 0xea, 0x17, 0x0b, 0x10, 0xd2, 0x3f, 0x28, 0x25,
+- 0x4f, 0x05, 0x77, 0x02, 0x14, 0x69, 0xf0, 0x2c,
+- 0xbe, 0x0c, 0xf1, 0x74, 0x30, 0xd1, 0xb9, 0x9b,
+- 0xfc, 0x8c, 0xbb, 0x04, 0x16, 0xd9, 0xba, 0xc3,
+- 0xbc, 0x91, 0x8a, 0xc4, 0x30, 0xa4, 0xb0, 0x12,
+- 0x4c, 0x21, 0x87, 0xcb, 0xc9, 0x1d, 0x16, 0x96,
+- 0x07, 0x6f, 0x23, 0x54, 0xb9, 0x6f, 0x79, 0xe5,
+- 0x64, 0xc0, 0x64, 0xda, 0xb1, 0xae, 0xdd, 0x60,
+- 0x6c, 0x1a, 0x9d, 0xd3, 0x04, 0x8e, 0x45, 0xb0,
+- 0x92, 0x61, 0xd0, 0x48, 0x81, 0xed, 0x5e, 0x1d,
+- 0xa0, 0xc9, 0xa4, 0x33, 0xc7, 0x13, 0x51, 0x5d,
+- 0x7f, 0x83, 0x73, 0xb6, 0x70, 0x18, 0x65, 0x3e,
+- 0x2f, 0x0e, 0x7a, 0x12, 0x39, 0x98, 0xab, 0xd8,
+- 0x7e, 0x6f, 0xa3, 0xd1, 0xba, 0x56, 0xad, 0xbd,
+- 0xf0, 0x03, 0x01, 0x1c, 0x85, 0x35, 0x9f, 0xeb,
+- 0x19, 0x63, 0xa1, 0xaf, 0xfe, 0x2d, 0x35, 0x50,
+- 0x39, 0xa0, 0x65, 0x7c, 0x95, 0x7e, 0x6b, 0xfe,
+- 0xc1, 0xac, 0x07, 0x7c, 0x98, 0x4f, 0xbe, 0x57,
+- 0xa7, 0x22, 0xec, 0xe2, 0x7e, 0x29, 0x09, 0x53,
+- 0xe8, 0xbf, 0xb4, 0x7e, 0x3f, 0x8f, 0xfc, 0x14,
+- 0xce, 0x54, 0xf9, 0x18, 0x58, 0xb5, 0xff, 0x44,
+- 0x05, 0x9d, 0xce, 0x1b, 0xb6, 0x82, 0x23, 0xc8,
+- 0x2e, 0xbc, 0x69, 0xbb, 0x4a, 0x29, 0x0f, 0x65,
+- 0x94, 0xf0, 0x63, 0x06, 0x0e, 0xef, 0x8c, 0xbd,
+- 0xff, 0xfd, 0xb0, 0x21, 0x6e, 0x57, 0x05, 0x75,
+- 0xda, 0xd5, 0xc4, 0xeb, 0x8d, 0x32, 0xf7, 0x50,
+- 0xd3, 0x6f, 0x22, 0xed, 0x5f, 0x8e, 0xa2, 0x5b,
+- 0x80, 0x8c, 0xc8, 0x78, 0x40, 0x24, 0x4b, 0x89,
+- 0x30, 0xce, 0x7a, 0x97, 0x0e, 0xc4, 0xaf, 0xef,
+- 0x9b, 0xb4, 0xcd, 0x66, 0x74, 0x14, 0x04, 0x2b,
+- 0xf7, 0xce, 0x0b, 0x1c, 0x6e, 0xc2, 0x78, 0x8c,
+- 0xca, 0xc5, 0xd0, 0x1c, 0x95, 0x4a, 0x91, 0x2d,
+- 0xa7, 0x20, 0xeb, 0x86, 0x52, 0xb7, 0x67, 0xd8,
+- 0x0c, 0xd6, 0x04, 0x14, 0xde, 0x51, 0x74, 0x75,
+- 0xe7, 0x11, 0xb4, 0x87, 0xa3, 0x3d, 0x2d, 0xad,
+- 0x4f, 0xef, 0xa0, 0x0f, 0x70, 0x00, 0x6d, 0x13,
+- 0x19, 0x1d, 0x41, 0x50, 0xe9, 0xd8, 0xf0, 0x32,
+- 0x71, 0xbc, 0xd3, 0x11, 0xf2, 0xac, 0xbe, 0xaf,
+- 0x75, 0x46, 0x65, 0x4e, 0x07, 0x34, 0x37, 0xa3,
+- 0x89, 0xfe, 0x75, 0xd4, 0x70, 0x4c, 0xc6, 0x3f,
+- 0x69, 0x24, 0x0e, 0x38, 0x67, 0x43, 0x8c, 0xde,
+- 0x06, 0xb5, 0xb8, 0xe7, 0xc4, 0xf0, 0x41, 0x8f,
+- 0xf0, 0xbd, 0x2f, 0x0b, 0xb9, 0x18, 0xf8, 0xde,
+- 0x64, 0xb1, 0xdb, 0xee, 0x00, 0x50, 0x77, 0xe1,
+- 0xc7, 0xff, 0xa6, 0xfa, 0xdd, 0x70, 0xf4, 0xe3,
+- 0x93, 0xe9, 0x77, 0x35, 0x3d, 0x4b, 0x2f, 0x2b,
+- 0x6d, 0x55, 0xf0, 0xfc, 0x88, 0x54, 0x4e, 0x89,
+- 0xc1, 0x8a, 0x23, 0x31, 0x2d, 0x14, 0x2a, 0xb8,
+- 0x1b, 0x15, 0xdd, 0x9e, 0x6e, 0x7b, 0xda, 0x05,
+- 0x91, 0x7d, 0x62, 0x64, 0x96, 0x72, 0xde, 0xfc,
+- 0xc1, 0xec, 0xf0, 0x23, 0x51, 0x6f, 0xdb, 0x5b,
+- 0x1d, 0x08, 0x57, 0xce, 0x09, 0xb8, 0xf6, 0xcd,
+- 0x8d, 0x95, 0xf2, 0x20, 0xbf, 0x0f, 0x20, 0x57,
+- 0x98, 0x81, 0x84, 0x4f, 0x15, 0x5c, 0x76, 0xe7,
+- 0x3e, 0x0a, 0x3a, 0x6c, 0xc4, 0x8a, 0xbe, 0x78,
+- 0x74, 0x77, 0xc3, 0x09, 0x4b, 0x5d, 0x48, 0xe4,
+- 0xc8, 0xcb, 0x0b, 0xea, 0x17, 0x28, 0xcf, 0xcf,
+- 0x31, 0x32, 0x44, 0xa4, 0xe5, 0x0e, 0x1a, 0x98,
+- 0x94, 0xc4, 0xf0, 0xff, 0xae, 0x3e, 0x44, 0xe8,
+- 0xa5, 0xb3, 0xb5, 0x37, 0x2f, 0xe8, 0xaf, 0x6f,
+- 0x28, 0xc1, 0x37, 0x5f, 0x31, 0xd2, 0xb9, 0x33,
+- 0xb1, 0xb2, 0x52, 0x94, 0x75, 0x2c, 0x29, 0x59,
+- 0x06, 0xc2, 0x25, 0xe8, 0x71, 0x65, 0x4e, 0xed,
+- 0xc0, 0x9c, 0xb1, 0xbb, 0x25, 0xdc, 0x6c, 0xe7,
+- 0x4b, 0xa5, 0x7a, 0x54, 0x7a, 0x60, 0xff, 0x7a,
+- 0xe0, 0x50, 0x40, 0x96, 0x35, 0x63, 0xe4, 0x0b,
+- 0x76, 0xbd, 0xa4, 0x65, 0x00, 0x1b, 0x57, 0x88,
+- 0xae, 0xed, 0x39, 0x88, 0x42, 0x11, 0x3c, 0xed,
+- 0x85, 0x67, 0x7d, 0xb9, 0x68, 0x82, 0xe9, 0x43,
+- 0x3c, 0x47, 0x53, 0xfa, 0xe8, 0xf8, 0x9f, 0x1f,
+- 0x9f, 0xef, 0x0f, 0xf7, 0x30, 0xd9, 0x30, 0x0e,
+- 0xb9, 0x9f, 0x69, 0x18, 0x2f, 0x7e, 0xf8, 0xf8,
+- 0xf8, 0x8c, 0x0f, 0xd4, 0x02, 0x4d, 0xea, 0xcd,
+- 0x0a, 0x9c, 0x6f, 0x71, 0x6d, 0x5a, 0x4c, 0x60,
+- 0xce, 0x20, 0x56, 0x32, 0xc6, 0xc5, 0x99, 0x1f,
+- 0x09, 0xe6, 0x4e, 0x18, 0x1a, 0x15, 0x13, 0xa8,
+- 0x7d, 0xb1, 0x6b, 0xc0, 0xb2, 0x6d, 0xf8, 0x26,
+- 0x66, 0xf8, 0x3d, 0x18, 0x74, 0x70, 0x66, 0x7a,
+- 0x34, 0x17, 0xde, 0xba, 0x47, 0xf1, 0x06, 0x18,
+- 0xcb, 0xaf, 0xeb, 0x4a, 0x1e, 0x8f, 0xa7, 0x77,
+- 0xe0, 0x3b, 0x78, 0x62, 0x66, 0xc9, 0x10, 0xea,
+- 0x1f, 0xb7, 0x29, 0x0a, 0x45, 0xa1, 0x1d, 0x1e,
+- 0x1d, 0xe2, 0x65, 0x61, 0x50, 0x9c, 0xd7, 0x05,
+- 0xf2, 0x0b, 0x5b, 0x12, 0x61, 0x02, 0xc8, 0xe5,
+- 0x63, 0x4f, 0x20, 0x0c, 0x07, 0x17, 0x33, 0x5e,
+- 0x03, 0x9a, 0x53, 0x0f, 0x2e, 0x55, 0xfe, 0x50,
+- 0x43, 0x7d, 0xd0, 0xb6, 0x7e, 0x5a, 0xda, 0xae,
+- 0x58, 0xef, 0x15, 0xa9, 0x83, 0xd9, 0x46, 0xb1,
+- 0x42, 0xaa, 0xf5, 0x02, 0x6c, 0xce, 0x92, 0x06,
+- 0x1b, 0xdb, 0x66, 0x45, 0x91, 0x79, 0xc2, 0x2d,
+- 0xe6, 0x53, 0xd3, 0x14, 0xfd, 0xbb, 0x44, 0x63,
+- 0xc6, 0xd7, 0x3d, 0x7a, 0x0c, 0x75, 0x78, 0x9d,
+- 0x5c, 0xa6, 0x39, 0xb3, 0xe5, 0x63, 0xca, 0x8b,
+- 0xfe, 0xd3, 0xef, 0x60, 0x83, 0xf6, 0x8e, 0x70,
+- 0xb6, 0x67, 0xc7, 0x77, 0xed, 0x23, 0xef, 0x4c,
+- 0xf0, 0xed, 0x2d, 0x07, 0x59, 0x6f, 0xc1, 0x01,
+- 0x34, 0x37, 0x08, 0xab, 0xd9, 0x1f, 0x09, 0xb1,
+- 0xce, 0x5b, 0x17, 0xff, 0x74, 0xf8, 0x9c, 0xd5,
+- 0x2c, 0x56, 0x39, 0x79, 0x0f, 0x69, 0x44, 0x75,
+- 0x58, 0x27, 0x01, 0xc4, 0xbf, 0xa7, 0xa1, 0x1d,
+- 0x90, 0x17, 0x77, 0x86, 0x5a, 0x3f, 0xd9, 0xd1,
+- 0x0e, 0xa0, 0x10, 0xf8, 0xec, 0x1e, 0xa5, 0x7f,
+- 0x5e, 0x36, 0xd1, 0xe3, 0x04, 0x2c, 0x70, 0xf7,
+- 0x8e, 0xc0, 0x98, 0x2f, 0x6c, 0x94, 0x2b, 0x41,
+- 0xb7, 0x60, 0x00, 0xb7, 0x2e, 0xb8, 0x02, 0x8d,
+- 0xb8, 0xb0, 0xd3, 0x86, 0xba, 0x1d, 0xd7, 0x90,
+- 0xd6, 0xb6, 0xe1, 0xfc, 0xd7, 0xd8, 0x28, 0x06,
+- 0x63, 0x9b, 0xce, 0x61, 0x24, 0x79, 0xc0, 0x70,
+- 0x52, 0xd0, 0xb6, 0xd4, 0x28, 0x95, 0x24, 0x87,
+- 0x03, 0x1f, 0xb7, 0x9a, 0xda, 0xa3, 0xfb, 0x52,
+- 0x5b, 0x68, 0xe7, 0x4c, 0x8c, 0x24, 0xe1, 0x42,
+- 0xf7, 0xd5, 0xfd, 0xad, 0x06, 0x32, 0x9f, 0xba,
+- 0xc1, 0xfc, 0xdd, 0xc6, 0xfc, 0xfc, 0xb3, 0x38,
+- 0x74, 0x56, 0x58, 0x40, 0x02, 0x37, 0x52, 0x2c,
+- 0x55, 0xcc, 0xb3, 0x9e, 0x7a, 0xe9, 0xd4, 0x38,
+- 0x41, 0x5e, 0x0c, 0x35, 0xe2, 0x11, 0xd1, 0x13,
+- 0xf8, 0xb7, 0x8d, 0x72, 0x6b, 0x22, 0x2a, 0xb0,
+- 0xdb, 0x08, 0xba, 0x35, 0xb9, 0x3f, 0xc8, 0xd3,
+- 0x24, 0x90, 0xec, 0x58, 0xd2, 0x09, 0xc7, 0x2d,
+- 0xed, 0x38, 0x80, 0x36, 0x72, 0x43, 0x27, 0x49,
+- 0x4a, 0x80, 0x8a, 0xa2, 0xe8, 0xd3, 0xda, 0x30,
+- 0x7d, 0xb6, 0x82, 0x37, 0x86, 0x92, 0x86, 0x3e,
+- 0x08, 0xb2, 0x28, 0x5a, 0x55, 0x44, 0x24, 0x7d,
+- 0x40, 0x48, 0x8a, 0xb6, 0x89, 0x58, 0x08, 0xa0,
+- 0xd6, 0x6d, 0x3a, 0x17, 0xbf, 0xf6, 0x54, 0xa2,
+- 0xf5, 0xd3, 0x8c, 0x0f, 0x78, 0x12, 0x57, 0x8b,
+- 0xd5, 0xc2, 0xfd, 0x58, 0x5b, 0x7f, 0x38, 0xe3,
+- 0xcc, 0xb7, 0x7c, 0x48, 0xb3, 0x20, 0xe8, 0x81,
+- 0x14, 0x32, 0x45, 0x05, 0xe0, 0xdb, 0x9f, 0x75,
+- 0x85, 0xb4, 0x6a, 0xfc, 0x95, 0xe3, 0x54, 0x22,
+- 0x12, 0xee, 0x30, 0xfe, 0xd8, 0x30, 0xef, 0x34,
+- 0x50, 0xab, 0x46, 0x30, 0x98, 0x2f, 0xb7, 0xc0,
+- 0x15, 0xa2, 0x83, 0xb6, 0xf2, 0x06, 0x21, 0xa2,
+- 0xc3, 0x26, 0x37, 0x14, 0xd1, 0x4d, 0xb5, 0x10,
+- 0x52, 0x76, 0x4d, 0x6a, 0xee, 0xb5, 0x2b, 0x15,
+- 0xb7, 0xf9, 0x51, 0xe8, 0x2a, 0xaf, 0xc7, 0xfa,
+- 0x77, 0xaf, 0xb0, 0x05, 0x4d, 0xd1, 0x68, 0x8e,
+- 0x74, 0x05, 0x9f, 0x9d, 0x93, 0xa5, 0x3e, 0x7f,
+- 0x4e, 0x5f, 0x9d, 0xcb, 0x09, 0xc7, 0x83, 0xe3,
+- 0x02, 0x9d, 0x27, 0x1f, 0xef, 0x85, 0x05, 0x8d,
+- 0xec, 0x55, 0x88, 0x0f, 0x0d, 0x7c, 0x4c, 0xe8,
+- 0xa1, 0x75, 0xa0, 0xd8, 0x06, 0x47, 0x14, 0xef,
+- 0xaa, 0x61, 0xcf, 0x26, 0x15, 0xad, 0xd8, 0xa3,
+- 0xaa, 0x75, 0xf2, 0x78, 0x4a, 0x5a, 0x61, 0xdf,
+- 0x8b, 0xc7, 0x04, 0xbc, 0xb2, 0x32, 0xd2, 0x7e,
+- 0x42, 0xee, 0xb4, 0x2f, 0x51, 0xff, 0x7b, 0x2e,
+- 0xd3, 0x02, 0xe8, 0xdc, 0x5d, 0x0d, 0x50, 0xdc,
+- 0xae, 0xb7, 0x46, 0xf9, 0xa8, 0xe6, 0xd0, 0x16,
+- 0xcc, 0xe6, 0x2c, 0x81, 0xc7, 0xad, 0xe9, 0xf0,
+- 0x05, 0x72, 0x6d, 0x3d, 0x0a, 0x7a, 0xa9, 0x02,
+- 0xac, 0x82, 0x93, 0x6e, 0xb6, 0x1c, 0x28, 0xfc,
+- 0x44, 0x12, 0xfb, 0x73, 0x77, 0xd4, 0x13, 0x39,
+- 0x29, 0x88, 0x8a, 0xf3, 0x5c, 0xa6, 0x36, 0xa0,
+- 0x2a, 0xed, 0x7e, 0xb1, 0x1d, 0xd6, 0x4c, 0x6b,
+- 0x41, 0x01, 0x18, 0x5d, 0x5d, 0x07, 0x97, 0xa6,
+- 0x4b, 0xef, 0x31, 0x18, 0xea, 0xac, 0xb1, 0x84,
+- 0x21, 0xed, 0xda, 0x86,
+- },
++ .result =
++ "\xf0\x5c\x74\xad\x4e\xbc\x99\xe2"
++ "\xae\xff\x91\x3a\x44\xcf\x38\x32"
++ "\x1e\xad\xa7\xcd\xa1\x39\x95\xaa"
++ "\x10\xb1\xb3\x2e\x04\x31\x8f\x86"
++ "\xf2\x62\x74\x70\x0c\xa4\x46\x08"
++ "\xa8\xb7\x99\xa8\xe9\xd2\x73\x79"
++ "\x7e\x6e\xd4\x8f\x1e\xc7\x8e\x31"
++ "\x0b\xfa\x4b\xce\xfd\xf3\x57\x71"
++ "\xe9\x46\x03\xa5\x3d\x34\x00\xe2"
++ "\x18\xff\x75\x6d\x06\x2d\x00\xab"
++ "\xb9\x3e\x6c\x59\xc5\x84\x06\xb5"
++ "\x8b\xd0\x89\x9c\x4a\x79\x16\xc6"
++ "\x3d\x74\x54\xfa\x44\xcd\x23\x26"
++ "\x5c\xcf\x7e\x28\x92\x32\xbf\xdf"
++ "\xa7\x20\x3c\x74\x58\x2a\x9a\xde"
++ "\x61\x00\x1c\x4f\xff\x59\xc4\x22"
++ "\xac\x3c\xd0\xe8\x6c\xf9\x97\x1b"
++ "\x58\x9b\xad\x71\xe8\xa9\xb5\x0d"
++ "\xee\x2f\x04\x1f\x7f\xbc\x99\xee"
++ "\x84\xff\x42\x60\xdc\x3a\x18\xa5"
++ "\x81\xf9\xef\xdc\x7a\x0f\x65\x41"
++ "\x2f\xa3\xd3\xf9\xc2\xcb\xc0\x4d"
++ "\x8f\xd3\x76\x96\xad\x49\x6d\x38"
++ "\x3d\x39\x0b\x6c\x80\xb7\x54\x69"
++ "\xf0\x2c\x90\x02\x29\x0d\x1c\x12"
++ "\xad\x55\xc3\x8b\x68\xd9\xcc\xb3"
++ "\xb2\x64\x33\x90\x5e\xca\x4b\xe2"
++ "\xfb\x75\xdc\x63\xf7\x9f\x82\x74"
++ "\xf0\xc9\xaa\x7f\xe9\x2a\x9b\x33"
++ "\xbc\x88\x00\x7f\xca\xb2\x1f\x14"
++ "\xdb\xc5\x8e\x7b\x11\x3c\x3e\x08"
++ "\xf3\x83\xe8\xe0\x94\x86\x2e\x92"
++ "\x78\x6b\x01\xc9\xc7\x83\xba\x21"
++ "\x6a\x25\x15\x33\x4e\x45\x08\xec"
++ "\x35\xdb\xe0\x6e\x31\x51\x79\xa9"
++ "\x42\x44\x65\xc1\xa0\xf1\xf9\x2a"
++ "\x70\xd5\xb6\xc6\xc1\x8c\x39\xfc"
++ "\x25\xa6\x55\xd9\xdd\x2d\x4c\xec"
++ "\x49\xc6\xeb\x0e\xa8\x25\x2a\x16"
++ "\x1b\x66\x84\xda\xe2\x92\xe5\xc0"
++ "\xc8\x53\x07\xaf\x80\x84\xec\xfd"
++ "\xcd\xd1\x6e\xcd\x6f\x6a\xf5\x36"
++ "\xc5\x15\xe5\x25\x7d\x77\xd1\x1a"
++ "\x93\x36\xa9\xcf\x7c\xa4\x54\x4a"
++ "\x06\x51\x48\x4e\xf6\x59\x87\xd2"
++ "\x04\x02\xef\xd3\x44\xde\x76\x31"
++ "\xb3\x34\x17\x1b\x9d\x66\x11\x9f"
++ "\x1e\xcc\x17\xe9\xc7\x3c\x1b\xe7"
++ "\xcb\x50\x08\xfc\xdc\x2b\x24\xdb"
++ "\x65\x83\xd0\x3b\xe3\x30\xea\x94"
++ "\x6c\xe7\xe8\x35\x32\xc7\xdb\x64"
++ "\xb4\x01\xab\x36\x2c\x77\x13\xaf"
++ "\xf8\x2b\x88\x3f\x54\x39\xc4\x44"
++ "\xfe\xef\x6f\x68\x34\xbe\x0f\x05"
++ "\x16\x6d\xf6\x0a\x30\xe7\xe3\xed"
++ "\xc4\xde\x3c\x1b\x13\xd8\xdb\xfe"
++ "\x41\x62\xe5\x28\xd4\x8d\xa3\xc7"
++ "\x93\x97\xc6\x48\x45\x1d\x9f\x83"
++ "\xdf\x4b\x40\x3e\x42\x25\x87\x80"
++ "\x4c\x7d\xa8\xd4\x98\x23\x95\x75"
++ "\x41\x8c\xda\x41\x9b\xd4\xa7\x06"
++ "\xb5\xf1\x71\x09\x53\xbe\xca\xbf"
++ "\x32\x03\xed\xf0\x50\x1c\x56\x39"
++ "\x5b\xa4\x75\x18\xf7\x9b\x58\xef"
++ "\x53\xfc\x2a\x38\x23\x15\x75\xcd"
++ "\x45\xe5\x5a\x82\x55\xba\x21\xfa"
++ "\xd4\xbd\xc6\x94\x7c\xc5\x80\x12"
++ "\xf7\x4b\x32\xc4\x9a\x82\xd8\x28"
++ "\x8f\xd9\xc2\x0f\x60\x03\xbe\x5e"
++ "\x21\xd6\x5f\x58\xbf\x5c\xb1\x32"
++ "\x82\x8d\xa9\xe5\xf2\x66\x1a\xc0"
++ "\xa0\xbc\x58\x2f\x71\xf5\x2f\xed"
++ "\xd1\x26\xb9\xd8\x49\x5a\x07\x19"
++ "\x01\x7c\x59\xb0\xf8\xa4\xb7\xd3"
++ "\x7b\x1a\x8c\x38\xf4\x50\xa4\x59"
++ "\xb0\xcc\x41\x0b\x88\x7f\xe5\x31"
++ "\xb3\x42\xba\xa2\x7e\xd4\x32\x71"
++ "\x45\x87\x48\xa9\xc2\xf2\x89\xb3"
++ "\xe4\xa7\x7e\x52\x15\x61\xfa\xfe"
++ "\xc9\xdd\x81\xeb\x13\xab\xab\xc3"
++ "\x98\x59\xd8\x16\x3d\x14\x7a\x1c"
++ "\x3c\x41\x9a\x16\x16\x9b\xd2\xd2"
++ "\x69\x3a\x29\x23\xac\x86\x32\xa5"
++ "\x48\x9c\x9e\xf3\x47\x77\x81\x70"
++ "\x24\xe8\x85\xd2\xf5\xb5\xfa\xff"
++ "\x59\x6a\xd3\x50\x59\x43\x59\xde"
++ "\xd9\xf1\x55\xa5\x0c\xc3\x1a\x1a"
++ "\x18\x34\x0d\x1a\x63\x33\xed\x10"
++ "\xe0\x1d\x2a\x18\xd2\xc0\x54\xa8"
++ "\xca\xb5\x9a\xd3\xdd\xca\x45\x84"
++ "\x50\xe7\x0f\xfe\xa4\x99\x5a\xbe"
++ "\x43\x2d\x9a\xcb\x92\x3f\x5a\x1d"
++ "\x85\xd8\xc9\xdf\x68\xc9\x12\x80"
++ "\x56\x0c\xdc\x00\xdc\x3a\x7d\x9d"
++ "\xa3\xa2\xe8\x4d\xbf\xf9\x70\xa0"
++ "\xa4\x13\x4f\x6b\xaf\x0a\x89\x7f"
++ "\xda\xf0\xbf\x9b\xc8\x1d\xe5\xf8"
++ "\x2e\x8b\x07\xb5\x73\x1b\xcc\xa2"
++ "\xa6\xad\x30\xbc\x78\x3c\x5b\x10"
++ "\xfa\x5e\x62\x2d\x9e\x64\xb3\x33"
++ "\xce\xf9\x1f\x86\xe7\x8b\xa2\xb8"
++ "\xe8\x99\x57\x8c\x11\xed\x66\xd9"
++ "\x3c\x72\xb9\xc3\xe6\x4e\x17\x3a"
++ "\x6a\xcb\x42\x24\x06\xed\x3e\x4e"
++ "\xa3\xe8\x6a\x94\xda\x0d\x4e\xd5"
++ "\x14\x19\xcf\xb6\x26\xd8\x2e\xcc"
++ "\x64\x76\x38\x49\x4d\xfe\x30\x6d"
++ "\xe4\xc8\x8c\x7b\xc4\xe0\x35\xba"
++ "\x22\x6e\x76\xe1\x1a\xf2\x53\xc3"
++ "\x28\xa2\x82\x1f\x61\x69\xad\xc1"
++ "\x7b\x28\x4b\x1e\x6c\x85\x95\x9b"
++ "\x51\xb5\x17\x7f\x12\x69\x8c\x24"
++ "\xd5\xc7\x5a\x5a\x11\x54\xff\x5a"
++ "\xf7\x16\xc3\x91\xa6\xf0\xdc\x0a"
++ "\xb6\xa7\x4a\x0d\x7a\x58\xfe\xa5"
++ "\xf5\xcb\x8f\x7b\x0e\xea\x57\xe7"
++ "\xbd\x79\xd6\x1c\x88\x23\x6c\xf2"
++ "\x4d\x29\x77\x53\x35\x6a\x00\x8d"
++ "\xcd\xa3\x58\xbe\x77\x99\x18\xf8"
++ "\xe6\xe1\x8f\xe9\x37\x8f\xe3\xe2"
++ "\x5a\x8a\x93\x25\xaf\xf3\x78\x80"
++ "\xbe\xa6\x1b\xc6\xac\x8b\x1c\x91"
++ "\x58\xe1\x9f\x89\x35\x9d\x1d\x21"
++ "\x29\x9f\xf4\x99\x02\x27\x0f\xa8"
++ "\x4f\x79\x94\x2b\x33\x2c\xda\xa2"
++ "\x26\x39\x83\x94\xef\x27\xd8\x53"
++ "\x8f\x66\x0d\xe4\x41\x7d\x34\xcd"
++ "\x43\x7c\x95\x0a\x53\xef\x66\xda"
++ "\x7e\x9b\xf3\x93\xaf\xd0\x73\x71"
++ "\xba\x40\x9b\x74\xf8\xd7\xd7\x41"
++ "\x6d\xaf\x72\x9c\x8d\x21\x87\x3c"
++ "\xfd\x0a\x90\xa9\x47\x96\x9e\xd3"
++ "\x88\xee\x73\xcf\x66\x2f\x52\x56"
++ "\x6d\xa9\x80\x4c\xe2\x6f\x62\x88"
++ "\x3f\x0e\x54\x17\x48\x80\x5d\xd3"
++ "\xc3\xda\x25\x3d\xa1\xc8\xcb\x9f"
++ "\x9b\x70\xb3\xa1\xeb\x04\x52\xa1"
++ "\xf2\x22\x0f\xfc\xc8\x18\xfa\xf9"
++ "\x85\x9c\xf1\xac\xeb\x0c\x02\x46"
++ "\x75\xd2\xf5\x2c\xe3\xd2\x59\x94"
++ "\x12\xf3\x3c\xfc\xd7\x92\xfa\x36"
++ "\xba\x61\x34\x38\x7c\xda\x48\x3e"
++ "\x08\xc9\x39\x23\x5e\x02\x2c\x1a"
++ "\x18\x7e\xb4\xd9\xfd\x9e\x40\x02"
++ "\xb1\x33\x37\x32\xe7\xde\xd6\xd0"
++ "\x7c\x58\x65\x4b\xf8\x34\x27\x9c"
++ "\x44\xb4\xbd\xe9\xe9\x4c\x78\x7d"
++ "\x4b\x9f\xce\xb1\xcd\x47\xa5\x37"
++ "\xe5\x6d\xbd\xb9\x43\x94\x0a\xd4"
++ "\xd6\xf9\x04\x5f\xb5\x66\x6c\x1a"
++ "\x35\x12\xe3\x36\x28\x27\x36\x58"
++ "\x01\x2b\x79\xe4\xba\x6d\x10\x7d"
++ "\x65\xdf\x84\x95\xf4\xd5\xb6\x8f"
++ "\x2b\x9f\x96\x00\x86\x60\xf0\x21"
++ "\x76\xa8\x6a\x8c\x28\x1c\xb3\x6b"
++ "\x97\xd7\xb6\x53\x2a\xcc\xab\x40"
++ "\x9d\x62\x79\x58\x52\xe6\x65\xb7"
++ "\xab\x55\x67\x9c\x89\x7c\x03\xb0"
++ "\x73\x59\xc5\x81\xf5\x18\x17\x5c"
++ "\x89\xf3\x78\x35\x44\x62\x78\x72"
++ "\xd0\x96\xeb\x31\xe7\x87\x77\x14"
++ "\x99\x51\xf2\x59\x26\x9e\xb5\xa6"
++ "\x45\xfe\x6e\xbd\x07\x4c\x94\x5a"
++ "\xa5\x7d\xfc\xf1\x2b\x77\xe2\xfe"
++ "\x17\xd4\x84\xa0\xac\xb5\xc7\xda"
++ "\xa9\x1a\xb6\xf3\x74\x11\xb4\x9d"
++ "\xfb\x79\x2e\x04\x2d\x50\x28\x83"
++ "\xbf\xc6\x52\xd3\x34\xd6\xe8\x7a"
++ "\xb6\xea\xe7\xa8\x6c\x15\x1e\x2c"
++ "\x57\xbc\x48\x4e\x5f\x5c\xb6\x92"
++ "\xd2\x49\x77\x81\x6d\x90\x70\xae"
++ "\x98\xa1\x03\x0d\x6b\xb9\x77\x14"
++ "\xf1\x4e\x23\xd3\xf8\x68\xbd\xc2"
++ "\xfe\x04\xb7\x5c\xc5\x17\x60\x8f"
++ "\x65\x54\xa4\x7a\x42\xdc\x18\x0d"
++ "\xb5\xcf\x0f\xd3\xc7\x91\x66\x1b"
++ "\x45\x42\x27\x75\x50\xe5\xee\xb8"
++ "\x7f\x33\x2c\xba\x4a\x92\x4d\x2c"
++ "\x3c\xe3\x0d\x80\x01\xba\x0d\x29"
++ "\xd8\x3c\xe9\x13\x16\x57\xe6\xea"
++ "\x94\x52\xe7\x00\x4d\x30\xb0\x0f"
++ "\x35\xb8\xb8\xa7\xb1\xb5\x3b\x44"
++ "\xe1\x2f\xfd\x88\xed\x43\xe7\x52"
++ "\x10\x93\xb3\x8a\x30\x6b\x0a\xf7"
++ "\x23\xc6\x50\x9d\x4a\xb0\xde\xc3"
++ "\xdc\x9b\x2f\x01\x56\x36\x09\xc5"
++ "\x2f\x6b\xfe\xf1\xd8\x27\x45\x03"
++ "\x30\x5e\x5c\x5b\xb4\x62\x0e\x1a"
++ "\xa9\x21\x2b\x92\x94\x87\x62\x57"
++ "\x4c\x10\x74\x1a\xf1\x0a\xc5\x84"
++ "\x3b\x9e\x72\x02\xd7\xcc\x09\x56"
++ "\xbd\x54\xc1\xf0\xc3\xe3\xb3\xf8"
++ "\xd2\x0d\x61\xcb\xef\xce\x0d\x05"
++ "\xb0\x98\xd9\x8e\x4f\xf9\xbc\x93"
++ "\xa6\xea\xc8\xcf\x10\x53\x4b\xf1"
++ "\xec\xfc\x89\xf9\x64\xb0\x22\xbf"
++ "\x9e\x55\x46\x9f\x7c\x50\x8e\x84"
++ "\x54\x20\x98\xd7\x6c\x40\x1e\xdb"
++ "\x69\x34\x78\x61\x24\x21\x9c\x8a"
++ "\xb3\x62\x31\x8b\x6e\xf5\x2a\x35"
++ "\x86\x13\xb1\x6c\x64\x2e\x41\xa5"
++ "\x05\xf2\x42\xba\xd2\x3a\x0d\x8e"
++ "\x8a\x59\x94\x3c\xcf\x36\x27\x82"
++ "\xc2\x45\xee\x58\xcd\x88\xb4\xec"
++ "\xde\xb2\x96\x0a\xaf\x38\x6f\x88"
++ "\xd7\xd8\xe1\xdf\xb9\x96\xa9\x0a"
++ "\xb1\x95\x28\x86\x20\xe9\x17\x49"
++ "\xa2\x29\x38\xaa\xa5\xe9\x6e\xf1"
++ "\x19\x27\xc0\xd5\x2a\x22\xc3\x0b"
++ "\xdb\x7c\x73\x10\xb9\xba\x89\x76"
++ "\x54\xae\x7d\x71\xb3\x93\xf6\x32"
++ "\xe6\x47\x43\x55\xac\xa0\x0d\xc2"
++ "\x93\x27\x4a\x8e\x0e\x74\x15\xc7"
++ "\x0b\x85\xd9\x0c\xa9\x30\x7a\x3e"
++ "\xea\x8f\x85\x6d\x3a\x12\x4f\x72"
++ "\x69\x58\x7a\x80\xbb\xb5\x97\xf3"
++ "\xcf\x70\xd2\x5d\xdd\x4d\x21\x79"
++ "\x54\x4d\xe4\x05\xe8\xbd\xc2\x62"
++ "\xb1\x3b\x77\x1c\xd6\x5c\xf3\xa0"
++ "\x79\x00\xa8\x6c\x29\xd9\x18\x24"
++ "\x36\xa2\x46\xc0\x96\x65\x7f\xbd"
++ "\x2a\xed\x36\x16\x0c\xaa\x9f\xf4"
++ "\xc5\xb4\xe2\x12\xed\x69\xed\x4f"
++ "\x26\x2c\x39\x52\x89\x98\xe7\x2c"
++ "\x99\xa4\x9e\xa3\x9b\x99\x46\x7a"
++ "\x3a\xdc\xa8\x59\xa3\xdb\xc3\x3b"
++ "\x95\x0d\x3b\x09\x6e\xee\x83\x5d"
++ "\x32\x4d\xed\xab\xfa\x98\x14\x4e"
++ "\xc3\x15\x45\x53\x61\xc4\x93\xbd"
++ "\x90\xf4\x99\x95\x4c\xe6\x76\x92"
++ "\x29\x90\x46\x30\x92\x69\x7d\x13"
++ "\xf2\xa5\xcd\x69\x49\x44\xb2\x0f"
++ "\x63\x40\x36\x5f\x09\xe2\x78\xf8"
++ "\x91\xe3\xe2\xfa\x10\xf7\xc8\x24"
++ "\xa8\x89\x32\x5c\x37\x25\x1d\xb2"
++ "\xea\x17\x8a\x0a\xa9\x64\xc3\x7c"
++ "\x3c\x7c\xbd\xc6\x79\x34\xe7\xe2"
++ "\x85\x8e\xbf\xf8\xde\x92\xa0\xae"
++ "\x20\xc4\xf6\xbb\x1f\x38\x19\x0e"
++ "\xe8\x79\x9c\xa1\x23\xe9\x54\x7e"
++ "\x37\x2f\xe2\x94\x32\xaf\xa0\x23"
++ "\x49\xe4\xc0\xb3\xac\x00\x8f\x36"
++ "\x05\xc4\xa6\x96\xec\x05\x98\x4f"
++ "\x96\x67\x57\x1f\x20\x86\x1b\x2d"
++ "\x69\xe4\x29\x93\x66\x5f\xaf\x6b"
++ "\x88\x26\x2c\x67\x02\x4b\x52\xd0"
++ "\x83\x7a\x43\x1f\xc0\x71\x15\x25"
++ "\x77\x65\x08\x60\x11\x76\x4c\x8d"
++ "\xed\xa9\x27\xc6\xb1\x2a\x2c\x6a"
++ "\x4a\x97\xf5\xc6\xb7\x70\x42\xd3"
++ "\x03\xd1\x24\x95\xec\x6d\xab\x38"
++ "\x72\xce\xe2\x8b\x33\xd7\x51\x09"
++ "\xdc\x45\xe0\x09\x96\x32\xf3\xc4"
++ "\x84\xdc\x73\x73\x2d\x1b\x11\x98"
++ "\xc5\x0e\x69\x28\x94\xc7\xb5\x4d"
++ "\xc8\x8a\xd0\xaa\x13\x2e\x18\x74"
++ "\xdd\xd1\x1e\xf3\x90\xe8\xfc\x9a"
++ "\x72\x4a\x0e\xd1\xe4\xfb\x0d\x96"
++ "\xd1\x0c\x79\x85\x1b\x1c\xfe\xe1"
++ "\x62\x8f\x7a\x73\x32\xab\xc8\x18"
++ "\x69\xe3\x34\x30\xdf\x13\xa6\xe5"
++ "\xe8\x0e\x67\x7f\x81\x11\xb4\x60"
++ "\xc7\xbd\x79\x65\x50\xdc\xc4\x5b"
++ "\xde\x39\xa4\x01\x72\x63\xf3\xd1"
++ "\x64\x4e\xdf\xfc\x27\x92\x37\x0d"
++ "\x57\xcd\x11\x4f\x11\x04\x8e\x1d"
++ "\x16\xf7\xcd\x92\x9a\x99\x30\x14"
++ "\xf1\x7c\x67\x1b\x1f\x41\x0b\xe8"
++ "\x32\xe8\xb8\xc1\x4f\x54\x86\x4f"
++ "\xe5\x79\x81\x73\xcd\x43\x59\x68"
++ "\x73\x02\x3b\x78\x21\x72\x43\x00"
++ "\x49\x17\xf7\x00\xaf\x68\x24\x53"
++ "\x05\x0a\xc3\x33\xe0\x33\x3f\x69"
++ "\xd2\x84\x2f\x0b\xed\xde\x04\xf4"
++ "\x11\x94\x13\x69\x51\x09\x28\xde"
++ "\x57\x5c\xef\xdc\x9a\x49\x1c\x17"
++ "\x97\xf3\x96\xc1\x7f\x5d\x2e\x7d"
++ "\x55\xb8\xb3\x02\x09\xb3\x1f\xe7"
++ "\xc9\x8d\xa3\x36\x34\x8a\x77\x13"
++ "\x30\x63\x4c\xa5\xcd\xc3\xe0\x7e"
++ "\x05\xa1\x7b\x0c\xcb\x74\x47\x31"
++ "\x62\x03\x43\xf1\x87\xb4\xb0\x85"
++ "\x87\x8e\x4b\x25\xc7\xcf\xae\x4b"
++ "\x36\x46\x3e\x62\xbc\x6f\xeb\x5f"
++ "\x73\xac\xe6\x07\xee\xc1\xa1\xd6"
++ "\xc4\xab\xc9\xd6\x89\x45\xe1\xf1"
++ "\x04\x4e\x1a\x6f\xbb\x4f\x3a\xa3"
++ "\xa0\xcb\xa3\x0a\xd8\x71\x35\x55"
++ "\xe4\xbc\x2e\x04\x06\xe6\xff\x5b"
++ "\x1c\xc0\x11\x7c\xc5\x17\xf3\x38"
++ "\xcf\xe9\xba\x0f\x0e\xef\x02\xc2"
++ "\x8d\xc6\xbc\x4b\x67\x20\x95\xd7"
++ "\x2c\x45\x5b\x86\x44\x8c\x6f\x2e"
++ "\x7e\x9f\x1c\x77\xba\x6b\x0e\xa3"
++ "\x69\xdc\xab\x24\x57\x60\x47\xc1"
++ "\xd1\xa5\x9d\x23\xe6\xb1\x37\xfe"
++ "\x93\xd2\x4c\x46\xf9\x0c\xc6\xfb"
++ "\xd6\x9d\x99\x69\xab\x7a\x07\x0c"
++ "\x65\xe7\xc4\x08\x96\xe2\xa5\x01"
++ "\x3f\x46\x07\x05\x7e\xe8\x9a\x90"
++ "\x50\xdc\xe9\x7a\xea\xa1\x39\x6e"
++ "\x66\xe4\x6f\xa5\x5f\xb2\xd9\x5b"
++ "\xf5\xdb\x2a\x32\xf0\x11\x6f\x7c"
++ "\x26\x10\x8f\x3d\x80\xe9\x58\xf7"
++ "\xe0\xa8\x57\xf8\xdb\x0e\xce\x99"
++ "\x63\x19\x3d\xd5\xec\x1b\x77\x69"
++ "\x98\xf6\xe4\x5f\x67\x17\x4b\x09"
++ "\x85\x62\x82\x70\x18\xe2\x9a\x78"
++ "\xe2\x62\xbd\xb4\xf1\x42\xc6\xfb"
++ "\x08\xd0\xbd\xeb\x4e\x09\xf2\xc8"
++ "\x1e\xdc\x3d\x32\x21\x56\x9c\x4f"
++ "\x35\xf3\x61\x06\x72\x84\xc4\x32"
++ "\xf2\xf1\xfa\x0b\x2f\xc3\xdb\x02"
++ "\x04\xc2\xde\x57\x64\x60\x8d\xcf"
++ "\xcb\x86\x5d\x97\x3e\xb1\x9c\x01"
++ "\xd6\x28\x8f\x99\xbc\x46\xeb\x05"
++ "\xaf\x7e\xb8\x21\x2a\x56\x85\x1c"
++ "\xb3\x71\xa0\xde\xca\x96\xf1\x78"
++ "\x49\xa2\x99\x81\x80\x5c\x01\xf5"
++ "\xa0\xa2\x56\x63\xe2\x70\x07\xa5"
++ "\x95\xd6\x85\xeb\x36\x9e\xa9\x51"
++ "\x66\x56\x5f\x1d\x02\x19\xe2\xf6"
++ "\x4f\x73\x38\x09\x75\x64\x48\xe0"
++ "\xf1\x7e\x0e\xe8\x9d\xf9\xed\x94"
++ "\xfe\x16\x26\x62\x49\x74\xf4\xb0"
++ "\xd4\xa9\x6c\xb0\xfd\x53\xe9\x81"
++ "\xe0\x7a\xbf\xcf\xb5\xc4\x01\x81"
++ "\x79\x99\x77\x01\x3b\xe9\xa2\xb6"
++ "\xe6\x6a\x8a\x9e\x56\x1c\x8d\x1e"
++ "\x8f\x06\x55\x2c\x6c\xdc\x92\x87"
++ "\x64\x3b\x4b\x19\xa1\x13\x64\x1d"
++ "\x4a\xe9\xc0\x00\xb8\x95\xef\x6b"
++ "\x1a\x86\x6d\x37\x52\x02\xc2\xe0"
++ "\xc8\xbb\x42\x0c\x02\x21\x4a\xc9"
++ "\xef\xa0\x54\xe4\x5e\x16\x53\x81"
++ "\x70\x62\x10\xaf\xde\xb8\xb5\xd3"
++ "\xe8\x5e\x6c\xc3\x8a\x3e\x18\x07"
++ "\xf2\x2f\x7d\xa7\xe1\x3d\x4e\xb4"
++ "\x26\xa7\xa3\x93\x86\xb2\x04\x1e"
++ "\x53\x5d\x86\xd6\xde\x65\xca\xe3"
++ "\x4e\xc1\xcf\xef\xc8\x70\x1b\x83"
++ "\x13\xdd\x18\x8b\x0d\x76\xd2\xf6"
++ "\x37\x7a\x93\x7a\x50\x11\x9f\x96"
++ "\x86\x25\xfd\xac\xdc\xbe\x18\x93"
++ "\x19\x6b\xec\x58\x4f\xb9\x75\xa7"
++ "\xdd\x3f\x2f\xec\xc8\x5a\x84\xab"
++ "\xd5\xe4\x8a\x07\xf6\x4d\x23\xd6"
++ "\x03\xfb\x03\x6a\xea\x66\xbf\xd4"
++ "\xb1\x34\xfb\x78\xe9\x55\xdc\x7c"
++ "\x3d\x9c\xe5\x9a\xac\xc3\x7a\x80"
++ "\x24\x6d\xa0\xef\x25\x7c\xb7\xea"
++ "\xce\x4d\x5f\x18\x60\xce\x87\x22"
++ "\x66\x2f\xd5\xdd\xdd\x02\x21\x75"
++ "\x82\xa0\x1f\x58\xc6\xd3\x62\xf7"
++ "\x32\xd8\xaf\x1e\x07\x77\x51\x96"
++ "\xd5\x6b\x1e\x7e\x80\x02\xe8\x67"
++ "\xea\x17\x0b\x10\xd2\x3f\x28\x25"
++ "\x4f\x05\x77\x02\x14\x69\xf0\x2c"
++ "\xbe\x0c\xf1\x74\x30\xd1\xb9\x9b"
++ "\xfc\x8c\xbb\x04\x16\xd9\xba\xc3"
++ "\xbc\x91\x8a\xc4\x30\xa4\xb0\x12"
++ "\x4c\x21\x87\xcb\xc9\x1d\x16\x96"
++ "\x07\x6f\x23\x54\xb9\x6f\x79\xe5"
++ "\x64\xc0\x64\xda\xb1\xae\xdd\x60"
++ "\x6c\x1a\x9d\xd3\x04\x8e\x45\xb0"
++ "\x92\x61\xd0\x48\x81\xed\x5e\x1d"
++ "\xa0\xc9\xa4\x33\xc7\x13\x51\x5d"
++ "\x7f\x83\x73\xb6\x70\x18\x65\x3e"
++ "\x2f\x0e\x7a\x12\x39\x98\xab\xd8"
++ "\x7e\x6f\xa3\xd1\xba\x56\xad\xbd"
++ "\xf0\x03\x01\x1c\x85\x35\x9f\xeb"
++ "\x19\x63\xa1\xaf\xfe\x2d\x35\x50"
++ "\x39\xa0\x65\x7c\x95\x7e\x6b\xfe"
++ "\xc1\xac\x07\x7c\x98\x4f\xbe\x57"
++ "\xa7\x22\xec\xe2\x7e\x29\x09\x53"
++ "\xe8\xbf\xb4\x7e\x3f\x8f\xfc\x14"
++ "\xce\x54\xf9\x18\x58\xb5\xff\x44"
++ "\x05\x9d\xce\x1b\xb6\x82\x23\xc8"
++ "\x2e\xbc\x69\xbb\x4a\x29\x0f\x65"
++ "\x94\xf0\x63\x06\x0e\xef\x8c\xbd"
++ "\xff\xfd\xb0\x21\x6e\x57\x05\x75"
++ "\xda\xd5\xc4\xeb\x8d\x32\xf7\x50"
++ "\xd3\x6f\x22\xed\x5f\x8e\xa2\x5b"
++ "\x80\x8c\xc8\x78\x40\x24\x4b\x89"
++ "\x30\xce\x7a\x97\x0e\xc4\xaf\xef"
++ "\x9b\xb4\xcd\x66\x74\x14\x04\x2b"
++ "\xf7\xce\x0b\x1c\x6e\xc2\x78\x8c"
++ "\xca\xc5\xd0\x1c\x95\x4a\x91\x2d"
++ "\xa7\x20\xeb\x86\x52\xb7\x67\xd8"
++ "\x0c\xd6\x04\x14\xde\x51\x74\x75"
++ "\xe7\x11\xb4\x87\xa3\x3d\x2d\xad"
++ "\x4f\xef\xa0\x0f\x70\x00\x6d\x13"
++ "\x19\x1d\x41\x50\xe9\xd8\xf0\x32"
++ "\x71\xbc\xd3\x11\xf2\xac\xbe\xaf"
++ "\x75\x46\x65\x4e\x07\x34\x37\xa3"
++ "\x89\xfe\x75\xd4\x70\x4c\xc6\x3f"
++ "\x69\x24\x0e\x38\x67\x43\x8c\xde"
++ "\x06\xb5\xb8\xe7\xc4\xf0\x41\x8f"
++ "\xf0\xbd\x2f\x0b\xb9\x18\xf8\xde"
++ "\x64\xb1\xdb\xee\x00\x50\x77\xe1"
++ "\xc7\xff\xa6\xfa\xdd\x70\xf4\xe3"
++ "\x93\xe9\x77\x35\x3d\x4b\x2f\x2b"
++ "\x6d\x55\xf0\xfc\x88\x54\x4e\x89"
++ "\xc1\x8a\x23\x31\x2d\x14\x2a\xb8"
++ "\x1b\x15\xdd\x9e\x6e\x7b\xda\x05"
++ "\x91\x7d\x62\x64\x96\x72\xde\xfc"
++ "\xc1\xec\xf0\x23\x51\x6f\xdb\x5b"
++ "\x1d\x08\x57\xce\x09\xb8\xf6\xcd"
++ "\x8d\x95\xf2\x20\xbf\x0f\x20\x57"
++ "\x98\x81\x84\x4f\x15\x5c\x76\xe7"
++ "\x3e\x0a\x3a\x6c\xc4\x8a\xbe\x78"
++ "\x74\x77\xc3\x09\x4b\x5d\x48\xe4"
++ "\xc8\xcb\x0b\xea\x17\x28\xcf\xcf"
++ "\x31\x32\x44\xa4\xe5\x0e\x1a\x98"
++ "\x94\xc4\xf0\xff\xae\x3e\x44\xe8"
++ "\xa5\xb3\xb5\x37\x2f\xe8\xaf\x6f"
++ "\x28\xc1\x37\x5f\x31\xd2\xb9\x33"
++ "\xb1\xb2\x52\x94\x75\x2c\x29\x59"
++ "\x06\xc2\x25\xe8\x71\x65\x4e\xed"
++ "\xc0\x9c\xb1\xbb\x25\xdc\x6c\xe7"
++ "\x4b\xa5\x7a\x54\x7a\x60\xff\x7a"
++ "\xe0\x50\x40\x96\x35\x63\xe4\x0b"
++ "\x76\xbd\xa4\x65\x00\x1b\x57\x88"
++ "\xae\xed\x39\x88\x42\x11\x3c\xed"
++ "\x85\x67\x7d\xb9\x68\x82\xe9\x43"
++ "\x3c\x47\x53\xfa\xe8\xf8\x9f\x1f"
++ "\x9f\xef\x0f\xf7\x30\xd9\x30\x0e"
++ "\xb9\x9f\x69\x18\x2f\x7e\xf8\xf8"
++ "\xf8\x8c\x0f\xd4\x02\x4d\xea\xcd"
++ "\x0a\x9c\x6f\x71\x6d\x5a\x4c\x60"
++ "\xce\x20\x56\x32\xc6\xc5\x99\x1f"
++ "\x09\xe6\x4e\x18\x1a\x15\x13\xa8"
++ "\x7d\xb1\x6b\xc0\xb2\x6d\xf8\x26"
++ "\x66\xf8\x3d\x18\x74\x70\x66\x7a"
++ "\x34\x17\xde\xba\x47\xf1\x06\x18"
++ "\xcb\xaf\xeb\x4a\x1e\x8f\xa7\x77"
++ "\xe0\x3b\x78\x62\x66\xc9\x10\xea"
++ "\x1f\xb7\x29\x0a\x45\xa1\x1d\x1e"
++ "\x1d\xe2\x65\x61\x50\x9c\xd7\x05"
++ "\xf2\x0b\x5b\x12\x61\x02\xc8\xe5"
++ "\x63\x4f\x20\x0c\x07\x17\x33\x5e"
++ "\x03\x9a\x53\x0f\x2e\x55\xfe\x50"
++ "\x43\x7d\xd0\xb6\x7e\x5a\xda\xae"
++ "\x58\xef\x15\xa9\x83\xd9\x46\xb1"
++ "\x42\xaa\xf5\x02\x6c\xce\x92\x06"
++ "\x1b\xdb\x66\x45\x91\x79\xc2\x2d"
++ "\xe6\x53\xd3\x14\xfd\xbb\x44\x63"
++ "\xc6\xd7\x3d\x7a\x0c\x75\x78\x9d"
++ "\x5c\xa6\x39\xb3\xe5\x63\xca\x8b"
++ "\xfe\xd3\xef\x60\x83\xf6\x8e\x70"
++ "\xb6\x67\xc7\x77\xed\x23\xef\x4c"
++ "\xf0\xed\x2d\x07\x59\x6f\xc1\x01"
++ "\x34\x37\x08\xab\xd9\x1f\x09\xb1"
++ "\xce\x5b\x17\xff\x74\xf8\x9c\xd5"
++ "\x2c\x56\x39\x79\x0f\x69\x44\x75"
++ "\x58\x27\x01\xc4\xbf\xa7\xa1\x1d"
++ "\x90\x17\x77\x86\x5a\x3f\xd9\xd1"
++ "\x0e\xa0\x10\xf8\xec\x1e\xa5\x7f"
++ "\x5e\x36\xd1\xe3\x04\x2c\x70\xf7"
++ "\x8e\xc0\x98\x2f\x6c\x94\x2b\x41"
++ "\xb7\x60\x00\xb7\x2e\xb8\x02\x8d"
++ "\xb8\xb0\xd3\x86\xba\x1d\xd7\x90"
++ "\xd6\xb6\xe1\xfc\xd7\xd8\x28\x06"
++ "\x63\x9b\xce\x61\x24\x79\xc0\x70"
++ "\x52\xd0\xb6\xd4\x28\x95\x24\x87"
++ "\x03\x1f\xb7\x9a\xda\xa3\xfb\x52"
++ "\x5b\x68\xe7\x4c\x8c\x24\xe1\x42"
++ "\xf7\xd5\xfd\xad\x06\x32\x9f\xba"
++ "\xc1\xfc\xdd\xc6\xfc\xfc\xb3\x38"
++ "\x74\x56\x58\x40\x02\x37\x52\x2c"
++ "\x55\xcc\xb3\x9e\x7a\xe9\xd4\x38"
++ "\x41\x5e\x0c\x35\xe2\x11\xd1\x13"
++ "\xf8\xb7\x8d\x72\x6b\x22\x2a\xb0"
++ "\xdb\x08\xba\x35\xb9\x3f\xc8\xd3"
++ "\x24\x90\xec\x58\xd2\x09\xc7\x2d"
++ "\xed\x38\x80\x36\x72\x43\x27\x49"
++ "\x4a\x80\x8a\xa2\xe8\xd3\xda\x30"
++ "\x7d\xb6\x82\x37\x86\x92\x86\x3e"
++ "\x08\xb2\x28\x5a\x55\x44\x24\x7d"
++ "\x40\x48\x8a\xb6\x89\x58\x08\xa0"
++ "\xd6\x6d\x3a\x17\xbf\xf6\x54\xa2"
++ "\xf5\xd3\x8c\x0f\x78\x12\x57\x8b"
++ "\xd5\xc2\xfd\x58\x5b\x7f\x38\xe3"
++ "\xcc\xb7\x7c\x48\xb3\x20\xe8\x81"
++ "\x14\x32\x45\x05\xe0\xdb\x9f\x75"
++ "\x85\xb4\x6a\xfc\x95\xe3\x54\x22"
++ "\x12\xee\x30\xfe\xd8\x30\xef\x34"
++ "\x50\xab\x46\x30\x98\x2f\xb7\xc0"
++ "\x15\xa2\x83\xb6\xf2\x06\x21\xa2"
++ "\xc3\x26\x37\x14\xd1\x4d\xb5\x10"
++ "\x52\x76\x4d\x6a\xee\xb5\x2b\x15"
++ "\xb7\xf9\x51\xe8\x2a\xaf\xc7\xfa"
++ "\x77\xaf\xb0\x05\x4d\xd1\x68\x8e"
++ "\x74\x05\x9f\x9d\x93\xa5\x3e\x7f"
++ "\x4e\x5f\x9d\xcb\x09\xc7\x83\xe3"
++ "\x02\x9d\x27\x1f\xef\x85\x05\x8d"
++ "\xec\x55\x88\x0f\x0d\x7c\x4c\xe8"
++ "\xa1\x75\xa0\xd8\x06\x47\x14\xef"
++ "\xaa\x61\xcf\x26\x15\xad\xd8\xa3"
++ "\xaa\x75\xf2\x78\x4a\x5a\x61\xdf"
++ "\x8b\xc7\x04\xbc\xb2\x32\xd2\x7e"
++ "\x42\xee\xb4\x2f\x51\xff\x7b\x2e"
++ "\xd3\x02\xe8\xdc\x5d\x0d\x50\xdc"
++ "\xae\xb7\x46\xf9\xa8\xe6\xd0\x16"
++ "\xcc\xe6\x2c\x81\xc7\xad\xe9\xf0"
++ "\x05\x72\x6d\x3d\x0a\x7a\xa9\x02"
++ "\xac\x82\x93\x6e\xb6\x1c\x28\xfc"
++ "\x44\x12\xfb\x73\x77\xd4\x13\x39"
++ "\x29\x88\x8a\xf3\x5c\xa6\x36\xa0"
++ "\x2a\xed\x7e\xb1\x1d\xd6\x4c\x6b"
++ "\x41\x01\x18\x5d\x5d\x07\x97\xa6"
++ "\x4b\xef\x31\x18\xea\xac\xb1\x84"
++ "\x21\xed\xda\x86",
+ .rlen = 4100,
+ },
+ };
+
+ static struct cipher_testvec aes_ctr_dec_tv_template[] = {
+ { /* From RFC 3686 */
+- .key = { 0xae, 0x68, 0x52, 0xf8, 0x12, 0x10, 0x67, 0xcc,
+- 0x4b, 0xf7, 0xa5, 0x76, 0x55, 0x77, 0xf3, 0x9e,
+- 0x00, 0x00, 0x00, 0x30 },
++ .key = "\xae\x68\x52\xf8\x12\x10\x67\xcc"
++ "\x4b\xf7\xa5\x76\x55\x77\xf3\x9e"
++ "\x00\x00\x00\x30",
+ .klen = 20,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+- .input = { 0xe4, 0x09, 0x5d, 0x4f, 0xb7, 0xa7, 0xb3, 0x79,
+- 0x2d, 0x61, 0x75, 0xa3, 0x26, 0x13, 0x11, 0xb8 },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00",
++ .input = "\xe4\x09\x5d\x4f\xb7\xa7\xb3\x79"
++ "\x2d\x61\x75\xa3\x26\x13\x11\xb8",
+ .ilen = 16,
+- .result = { "Single block msg" },
++ .result = "Single block msg",
+ .rlen = 16,
+ }, {
+- .key = { 0x7e, 0x24, 0x06, 0x78, 0x17, 0xfa, 0xe0, 0xd7,
+- 0x43, 0xd6, 0xce, 0x1f, 0x32, 0x53, 0x91, 0x63,
+- 0x00, 0x6c, 0xb6, 0xdb },
++ .key = "\x7e\x24\x06\x78\x17\xfa\xe0\xd7"
++ "\x43\xd6\xce\x1f\x32\x53\x91\x63"
++ "\x00\x6c\xb6\xdb",
+ .klen = 20,
+- .iv = { 0xc0, 0x54, 0x3b, 0x59, 0xda, 0x48, 0xd9, 0x0b },
+- .input = { 0x51, 0x04, 0xa1, 0x06, 0x16, 0x8a, 0x72, 0xd9,
+- 0x79, 0x0d, 0x41, 0xee, 0x8e, 0xda, 0xd3, 0x88,
+- 0xeb, 0x2e, 0x1e, 0xfc, 0x46, 0xda, 0x57, 0xc8,
+- 0xfc, 0xe6, 0x30, 0xdf, 0x91, 0x41, 0xbe, 0x28 },
+- .ilen = 32,
+- .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++ .iv = "\xc0\x54\x3b\x59\xda\x48\xd9\x0b",
++ .input = "\x51\x04\xa1\x06\x16\x8a\x72\xd9"
++ "\x79\x0d\x41\xee\x8e\xda\xd3\x88"
++ "\xeb\x2e\x1e\xfc\x46\xda\x57\xc8"
++ "\xfc\xe6\x30\xdf\x91\x41\xbe\x28",
++ .ilen = 32,
++ .result = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ .rlen = 32,
+ }, {
+- .key = { 0x16, 0xaf, 0x5b, 0x14, 0x5f, 0xc9, 0xf5, 0x79,
+- 0xc1, 0x75, 0xf9, 0x3e, 0x3b, 0xfb, 0x0e, 0xed,
+- 0x86, 0x3d, 0x06, 0xcc, 0xfd, 0xb7, 0x85, 0x15,
+- 0x00, 0x00, 0x00, 0x48 },
+- .klen = 28,
+- .iv = { 0x36, 0x73, 0x3c, 0x14, 0x7d, 0x6d, 0x93, 0xcb },
+- .input = { 0x4b, 0x55, 0x38, 0x4f, 0xe2, 0x59, 0xc9, 0xc8,
+- 0x4e, 0x79, 0x35, 0xa0, 0x03, 0xcb, 0xe9, 0x28 },
+- .ilen = 16,
+- .result = { "Single block msg" },
++ .key = "\x16\xaf\x5b\x14\x5f\xc9\xf5\x79"
++ "\xc1\x75\xf9\x3e\x3b\xfb\x0e\xed"
++ "\x86\x3d\x06\xcc\xfd\xb7\x85\x15"
++ "\x00\x00\x00\x48",
++ .klen = 28,
++ .iv = "\x36\x73\x3c\x14\x7d\x6d\x93\xcb",
++ .input = "\x4b\x55\x38\x4f\xe2\x59\xc9\xc8"
++ "\x4e\x79\x35\xa0\x03\xcb\xe9\x28",
++ .ilen = 16,
++ .result = "Single block msg",
+ .rlen = 16,
+ }, {
+- .key = { 0x7c, 0x5c, 0xb2, 0x40, 0x1b, 0x3d, 0xc3, 0x3c,
+- 0x19, 0xe7, 0x34, 0x08, 0x19, 0xe0, 0xf6, 0x9c,
+- 0x67, 0x8c, 0x3d, 0xb8, 0xe6, 0xf6, 0xa9, 0x1a,
+- 0x00, 0x96, 0xb0, 0x3b },
++ .key = "\x7c\x5c\xb2\x40\x1b\x3d\xc3\x3c"
++ "\x19\xe7\x34\x08\x19\xe0\xf6\x9c"
++ "\x67\x8c\x3d\xb8\xe6\xf6\xa9\x1a"
++ "\x00\x96\xb0\x3b",
+ .klen = 28,
+- .iv = { 0x02, 0x0c, 0x6e, 0xad, 0xc2, 0xcb, 0x50, 0x0d },
+- .input = { 0x45, 0x32, 0x43, 0xfc, 0x60, 0x9b, 0x23, 0x32,
+- 0x7e, 0xdf, 0xaa, 0xfa, 0x71, 0x31, 0xcd, 0x9f,
+- 0x84, 0x90, 0x70, 0x1c, 0x5a, 0xd4, 0xa7, 0x9c,
+- 0xfc, 0x1f, 0xe0, 0xff, 0x42, 0xf4, 0xfb, 0x00 },
++ .iv = "\x02\x0c\x6e\xad\xc2\xcb\x50\x0d",
++ .input = "\x45\x32\x43\xfc\x60\x9b\x23\x32"
++ "\x7e\xdf\xaa\xfa\x71\x31\xcd\x9f"
++ "\x84\x90\x70\x1c\x5a\xd4\xa7\x9c"
++ "\xfc\x1f\xe0\xff\x42\xf4\xfb\x00",
+ .ilen = 32,
+- .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+- .rlen = 32,
++ .result = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
++ .rlen = 32,
+ }, {
+- .key = { 0x77, 0x6b, 0xef, 0xf2, 0x85, 0x1d, 0xb0, 0x6f,
+- 0x4c, 0x8a, 0x05, 0x42, 0xc8, 0x69, 0x6f, 0x6c,
+- 0x6a, 0x81, 0xaf, 0x1e, 0xec, 0x96, 0xb4, 0xd3,
+- 0x7f, 0xc1, 0xd6, 0x89, 0xe6, 0xc1, 0xc1, 0x04,
+- 0x00, 0x00, 0x00, 0x60 },
++ .key = "\x77\x6b\xef\xf2\x85\x1d\xb0\x6f"
++ "\x4c\x8a\x05\x42\xc8\x69\x6f\x6c"
++ "\x6a\x81\xaf\x1e\xec\x96\xb4\xd3"
++ "\x7f\xc1\xd6\x89\xe6\xc1\xc1\x04"
++ "\x00\x00\x00\x60",
+ .klen = 36,
+- .iv = { 0xdb, 0x56, 0x72, 0xc9, 0x7a, 0xa8, 0xf0, 0xb2 },
+- .input = { 0x14, 0x5a, 0xd0, 0x1d, 0xbf, 0x82, 0x4e, 0xc7,
+- 0x56, 0x08, 0x63, 0xdc, 0x71, 0xe3, 0xe0, 0xc0 },
++ .iv = "\xdb\x56\x72\xc9\x7a\xa8\xf0\xb2",
++ .input = "\x14\x5a\xd0\x1d\xbf\x82\x4e\xc7"
++ "\x56\x08\x63\xdc\x71\xe3\xe0\xc0",
+ .ilen = 16,
+- .result = { "Single block msg" },
+- .rlen = 16,
+- }, {
+- .key = { 0xf6, 0xd6, 0x6d, 0x6b, 0xd5, 0x2d, 0x59, 0xbb,
+- 0x07, 0x96, 0x36, 0x58, 0x79, 0xef, 0xf8, 0x86,
+- 0xc6, 0x6d, 0xd5, 0x1a, 0x5b, 0x6a, 0x99, 0x74,
+- 0x4b, 0x50, 0x59, 0x0c, 0x87, 0xa2, 0x38, 0x84,
+- 0x00, 0xfa, 0xac, 0x24 },
+- .klen = 36,
+- .iv = { 0xc1, 0x58, 0x5e, 0xf1, 0x5a, 0x43, 0xd8, 0x75 },
+- .input = { 0xf0, 0x5e, 0x23, 0x1b, 0x38, 0x94, 0x61, 0x2c,
+- 0x49, 0xee, 0x00, 0x0b, 0x80, 0x4e, 0xb2, 0xa9,
+- 0xb8, 0x30, 0x6b, 0x50, 0x8f, 0x83, 0x9d, 0x6a,
+- 0x55, 0x30, 0x83, 0x1d, 0x93, 0x44, 0xaf, 0x1c },
++ .result = "Single block msg",
++ .rlen = 16,
++ }, {
++ .key = "\xf6\xd6\x6d\x6b\xd5\x2d\x59\xbb"
++ "\x07\x96\x36\x58\x79\xef\xf8\x86"
++ "\xc6\x6d\xd5\x1a\x5b\x6a\x99\x74"
++ "\x4b\x50\x59\x0c\x87\xa2\x38\x84"
++ "\x00\xfa\xac\x24",
++ .klen = 36,
++ .iv = "\xc1\x58\x5e\xf1\x5a\x43\xd8\x75",
++ .input = "\xf0\x5e\x23\x1b\x38\x94\x61\x2c"
++ "\x49\xee\x00\x0b\x80\x4e\xb2\xa9"
++ "\xb8\x30\x6b\x50\x8f\x83\x9d\x6a"
++ "\x55\x30\x83\x1d\x93\x44\xaf\x1c",
+ .ilen = 32,
+- .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++ .result = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ .rlen = 32,
+ },
+ };
+
+ static struct aead_testvec aes_gcm_enc_tv_template[] = {
+ { /* From McGrew & Viega - http://citeseer.ist.psu.edu/656989.html */
++ .key = zeroed_string,
+ .klen = 16,
+- .result = { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
+- 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
++ .result = "\x58\xe2\xfc\xce\xfa\x7e\x30\x61"
++ "\x36\x7f\x1d\x57\xa4\xe7\x45\x5a",
+ .rlen = 16,
+ }, {
++ .key = zeroed_string,
+ .klen = 16,
++ .input = zeroed_string,
+ .ilen = 16,
+- .result = { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
+- 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78,
+- 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
+- 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
++ .result = "\x03\x88\xda\xce\x60\xb6\xa3\x92"
++ "\xf3\x28\xc2\xb9\x71\xb2\xfe\x78"
++ "\xab\x6e\x47\xd4\x2c\xec\x13\xbd"
++ "\xf5\x3a\x67\xb2\x12\x57\xbd\xdf",
+ .rlen = 32,
+ }, {
+- .key = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+- 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
++ .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
++ "\x6d\x6a\x8f\x94\x67\x30\x83\x08",
+ .klen = 16,
+- .iv = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+- 0xde, 0xca, 0xf8, 0x88 },
+- .input = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+- 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+- 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+- 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+- 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+- 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+- 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+- 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
++ .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
++ "\xde\xca\xf8\x88",
++ .input = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
++ "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
++ "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
++ "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
++ "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
++ "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
++ "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
++ "\xba\x63\x7b\x39\x1a\xaf\xd2\x55",
+ .ilen = 64,
+- .result = { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+- 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+- 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+- 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+- 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+- 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+- 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+- 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85,
+- 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
+- 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
++ .result = "\x42\x83\x1e\xc2\x21\x77\x74\x24"
++ "\x4b\x72\x21\xb7\x84\xd0\xd4\x9c"
++ "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0"
++ "\x35\xc1\x7e\x23\x29\xac\xa1\x2e"
++ "\x21\xd5\x14\xb2\x54\x66\x93\x1c"
++ "\x7d\x8f\x6a\x5a\xac\x84\xaa\x05"
++ "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97"
++ "\x3d\x58\xe0\x91\x47\x3f\x59\x85"
++ "\x4d\x5c\x2a\xf3\x27\xcd\x64\xa6"
++ "\x2c\xf3\x5a\xbd\x2b\xa6\xfa\xb4",
+ .rlen = 80,
+ }, {
+- .key = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+- 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
++ .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
++ "\x6d\x6a\x8f\x94\x67\x30\x83\x08",
+ .klen = 16,
+- .iv = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+- 0xde, 0xca, 0xf8, 0x88 },
+- .input = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+- 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+- 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+- 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+- 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+- 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+- 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+- 0xba, 0x63, 0x7b, 0x39 },
++ .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
++ "\xde\xca\xf8\x88",
++ .input = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
++ "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
++ "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
++ "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
++ "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
++ "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
++ "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
++ "\xba\x63\x7b\x39",
+ .ilen = 60,
+- .assoc = { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+- 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+- 0xab, 0xad, 0xda, 0xd2 },
++ .assoc = "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
++ "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
++ "\xab\xad\xda\xd2",
+ .alen = 20,
+- .result = { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+- 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+- 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+- 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+- 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+- 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+- 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+- 0x3d, 0x58, 0xe0, 0x91,
+- 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
+- 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
++ .result = "\x42\x83\x1e\xc2\x21\x77\x74\x24"
++ "\x4b\x72\x21\xb7\x84\xd0\xd4\x9c"
++ "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0"
++ "\x35\xc1\x7e\x23\x29\xac\xa1\x2e"
++ "\x21\xd5\x14\xb2\x54\x66\x93\x1c"
++ "\x7d\x8f\x6a\x5a\xac\x84\xaa\x05"
++ "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97"
++ "\x3d\x58\xe0\x91"
++ "\x5b\xc9\x4f\xbc\x32\x21\xa5\xdb"
++ "\x94\xfa\xe9\x5a\xe7\x12\x1a\x47",
+ .rlen = 76,
+ }, {
++ .key = zeroed_string,
+ .klen = 24,
+- .result = { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
+- 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
++ .result = "\xcd\x33\xb2\x8a\xc7\x73\xf7\x4b"
++ "\xa0\x0e\xd1\xf3\x12\x57\x24\x35",
+ .rlen = 16,
+ }, {
++ .key = zeroed_string,
+ .klen = 24,
++ .input = zeroed_string,
+ .ilen = 16,
+- .result = { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
+- 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00,
+- 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
+- 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
++ .result = "\x98\xe7\x24\x7c\x07\xf0\xfe\x41"
++ "\x1c\x26\x7e\x43\x84\xb0\xf6\x00"
++ "\x2f\xf5\x8d\x80\x03\x39\x27\xab"
++ "\x8e\xf4\xd4\x58\x75\x14\xf0\xfb",
+ .rlen = 32,
+ }, {
+- .key = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+- 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+- 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c },
++ .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
++ "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
++ "\xfe\xff\xe9\x92\x86\x65\x73\x1c",
+ .klen = 24,
+- .iv = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+- 0xde, 0xca, 0xf8, 0x88 },
+- .input = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+- 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+- 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+- 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+- 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+- 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+- 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+- 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
++ .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
++ "\xde\xca\xf8\x88",
++ .input = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
++ "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
++ "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
++ "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
++ "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
++ "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
++ "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
++ "\xba\x63\x7b\x39\x1a\xaf\xd2\x55",
+ .ilen = 64,
+- .result = { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
+- 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
+- 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
+- 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
+- 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
+- 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
+- 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
+- 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56,
+- 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
+- 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
++ .result = "\x39\x80\xca\x0b\x3c\x00\xe8\x41"
++ "\xeb\x06\xfa\xc4\x87\x2a\x27\x57"
++ "\x85\x9e\x1c\xea\xa6\xef\xd9\x84"
++ "\x62\x85\x93\xb4\x0c\xa1\xe1\x9c"
++ "\x7d\x77\x3d\x00\xc1\x44\xc5\x25"
++ "\xac\x61\x9d\x18\xc8\x4a\x3f\x47"
++ "\x18\xe2\x44\x8b\x2f\xe3\x24\xd9"
++ "\xcc\xda\x27\x10\xac\xad\xe2\x56"
++ "\x99\x24\xa7\xc8\x58\x73\x36\xbf"
++ "\xb1\x18\x02\x4d\xb8\x67\x4a\x14",
+ .rlen = 80,
+ }, {
+- .key = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+- 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+- 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c },
++ .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
++ "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
++ "\xfe\xff\xe9\x92\x86\x65\x73\x1c",
+ .klen = 24,
+- .iv = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+- 0xde, 0xca, 0xf8, 0x88 },
+- .input = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+- 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+- 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+- 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+- 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+- 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+- 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+- 0xba, 0x63, 0x7b, 0x39 },
++ .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
++ "\xde\xca\xf8\x88",
++ .input = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
++ "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
++ "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
++ "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
++ "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
++ "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
++ "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
++ "\xba\x63\x7b\x39",
+ .ilen = 60,
+- .assoc = { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+- 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+- 0xab, 0xad, 0xda, 0xd2 },
++ .assoc = "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
++ "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
++ "\xab\xad\xda\xd2",
+ .alen = 20,
+- .result = { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
+- 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
+- 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
+- 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
+- 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
+- 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
+- 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
+- 0xcc, 0xda, 0x27, 0x10,
+- 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
+- 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
++ .result = "\x39\x80\xca\x0b\x3c\x00\xe8\x41"
++ "\xeb\x06\xfa\xc4\x87\x2a\x27\x57"
++ "\x85\x9e\x1c\xea\xa6\xef\xd9\x84"
++ "\x62\x85\x93\xb4\x0c\xa1\xe1\x9c"
++ "\x7d\x77\x3d\x00\xc1\x44\xc5\x25"
++ "\xac\x61\x9d\x18\xc8\x4a\x3f\x47"
++ "\x18\xe2\x44\x8b\x2f\xe3\x24\xd9"
++ "\xcc\xda\x27\x10"
++ "\x25\x19\x49\x8e\x80\xf1\x47\x8f"
++ "\x37\xba\x55\xbd\x6d\x27\x61\x8c",
+ .rlen = 76,
+ .np = 2,
+ .tap = { 32, 28 },
+ .anp = 2,
+ .atap = { 8, 12 }
+ }, {
++ .key = zeroed_string,
+ .klen = 32,
+- .result = { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
+- 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
++ .result = "\x53\x0f\x8a\xfb\xc7\x45\x36\xb9"
++ "\xa9\x63\xb4\xf1\xc4\xcb\x73\x8b",
+ .rlen = 16,
+ }
+ };
+
+ static struct aead_testvec aes_gcm_dec_tv_template[] = {
+ { /* From McGrew & Viega - http://citeseer.ist.psu.edu/656989.html */
++ .key = zeroed_string,
+ .klen = 32,
+- .input = { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
+- 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18,
+- 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
+- 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
++ .input = "\xce\xa7\x40\x3d\x4d\x60\x6b\x6e"
++ "\x07\x4e\xc5\xd3\xba\xf3\x9d\x18"
++ "\xd0\xd1\xc8\xa7\x99\x99\x6b\xf0"
++ "\x26\x5b\x98\xb5\xd4\x8a\xb9\x19",
+ .ilen = 32,
++ .result = zeroed_string,
+ .rlen = 16,
+ }, {
+- .key = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+- 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+- 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+- 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
++ .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
++ "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
++ "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
++ "\x6d\x6a\x8f\x94\x67\x30\x83\x08",
+ .klen = 32,
+- .iv = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+- 0xde, 0xca, 0xf8, 0x88 },
+- .input = { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
+- 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
+- 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
+- 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
+- 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
+- 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
+- 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
+- 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad,
+- 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
+- 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
++ .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
++ "\xde\xca\xf8\x88",
++ .input = "\x52\x2d\xc1\xf0\x99\x56\x7d\x07"
++ "\xf4\x7f\x37\xa3\x2a\x84\x42\x7d"
++ "\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9"
++ "\x75\x98\xa2\xbd\x25\x55\xd1\xaa"
++ "\x8c\xb0\x8e\x48\x59\x0d\xbb\x3d"
++ "\xa7\xb0\x8b\x10\x56\x82\x88\x38"
++ "\xc5\xf6\x1e\x63\x93\xba\x7a\x0a"
++ "\xbc\xc9\xf6\x62\x89\x80\x15\xad"
++ "\xb0\x94\xda\xc5\xd9\x34\x71\xbd"
++ "\xec\x1a\x50\x22\x70\xe3\xcc\x6c",
+ .ilen = 80,
+- .result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+- 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+- 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+- 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+- 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+- 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+- 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+- 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
++ .result = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
++ "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
++ "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
++ "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
++ "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
++ "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
++ "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
++ "\xba\x63\x7b\x39\x1a\xaf\xd2\x55",
+ .rlen = 64,
+ }, {
+- .key = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+- 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+- 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+- 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
++ .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
++ "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
++ "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
++ "\x6d\x6a\x8f\x94\x67\x30\x83\x08",
+ .klen = 32,
+- .iv = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+- 0xde, 0xca, 0xf8, 0x88 },
+- .input = { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
+- 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
+- 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
+- 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
+- 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
+- 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
+- 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
+- 0xbc, 0xc9, 0xf6, 0x62,
+- 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
+- 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
++ .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
++ "\xde\xca\xf8\x88",
++ .input = "\x52\x2d\xc1\xf0\x99\x56\x7d\x07"
++ "\xf4\x7f\x37\xa3\x2a\x84\x42\x7d"
++ "\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9"
++ "\x75\x98\xa2\xbd\x25\x55\xd1\xaa"
++ "\x8c\xb0\x8e\x48\x59\x0d\xbb\x3d"
++ "\xa7\xb0\x8b\x10\x56\x82\x88\x38"
++ "\xc5\xf6\x1e\x63\x93\xba\x7a\x0a"
++ "\xbc\xc9\xf6\x62"
++ "\x76\xfc\x6e\xce\x0f\x4e\x17\x68"
++ "\xcd\xdf\x88\x53\xbb\x2d\x55\x1b",
+ .ilen = 76,
+- .assoc = { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+- 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+- 0xab, 0xad, 0xda, 0xd2 },
++ .assoc = "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
++ "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
++ "\xab\xad\xda\xd2",
+ .alen = 20,
+- .result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+- 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+- 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+- 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+- 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+- 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+- 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+- 0xba, 0x63, 0x7b, 0x39 },
++ .result = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
++ "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
++ "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
++ "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
++ "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
++ "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
++ "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
++ "\xba\x63\x7b\x39",
+ .rlen = 60,
+ .np = 2,
+ .tap = { 48, 28 },
+ .anp = 3,
+ .atap = { 8, 8, 4 }
+ }, {
+- .key = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+- 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
++ .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
++ "\x6d\x6a\x8f\x94\x67\x30\x83\x08",
+ .klen = 16,
+- .iv = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+- 0xde, 0xca, 0xf8, 0x88 },
+- .input = { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+- 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+- 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+- 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+- 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+- 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+- 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+- 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85,
+- 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
+- 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
++ .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
++ "\xde\xca\xf8\x88",
++ .input = "\x42\x83\x1e\xc2\x21\x77\x74\x24"
++ "\x4b\x72\x21\xb7\x84\xd0\xd4\x9c"
++ "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0"
++ "\x35\xc1\x7e\x23\x29\xac\xa1\x2e"
++ "\x21\xd5\x14\xb2\x54\x66\x93\x1c"
++ "\x7d\x8f\x6a\x5a\xac\x84\xaa\x05"
++ "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97"
++ "\x3d\x58\xe0\x91\x47\x3f\x59\x85"
++ "\x4d\x5c\x2a\xf3\x27\xcd\x64\xa6"
++ "\x2c\xf3\x5a\xbd\x2b\xa6\xfa\xb4",
+ .ilen = 80,
+- .result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+- 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+- 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+- 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+- 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+- 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+- 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+- 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
++ .result = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
++ "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
++ "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
++ "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
++ "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
++ "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
++ "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
++ "\xba\x63\x7b\x39\x1a\xaf\xd2\x55",
+ .rlen = 64,
+ }, {
+- .key = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+- 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
++ .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
++ "\x6d\x6a\x8f\x94\x67\x30\x83\x08",
+ .klen = 16,
+- .iv = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+- 0xde, 0xca, 0xf8, 0x88 },
+- .input = { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+- 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+- 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+- 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+- 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+- 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+- 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+- 0x3d, 0x58, 0xe0, 0x91,
+- 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
+- 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
++ .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
++ "\xde\xca\xf8\x88",
++ .input = "\x42\x83\x1e\xc2\x21\x77\x74\x24"
++ "\x4b\x72\x21\xb7\x84\xd0\xd4\x9c"
++ "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0"
++ "\x35\xc1\x7e\x23\x29\xac\xa1\x2e"
++ "\x21\xd5\x14\xb2\x54\x66\x93\x1c"
++ "\x7d\x8f\x6a\x5a\xac\x84\xaa\x05"
++ "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97"
++ "\x3d\x58\xe0\x91"
++ "\x5b\xc9\x4f\xbc\x32\x21\xa5\xdb"
++ "\x94\xfa\xe9\x5a\xe7\x12\x1a\x47",
+ .ilen = 76,
+- .assoc = { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+- 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+- 0xab, 0xad, 0xda, 0xd2 },
++ .assoc = "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
++ "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
++ "\xab\xad\xda\xd2",
+ .alen = 20,
+- .result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+- 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+- 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+- 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+- 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+- 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+- 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+- 0xba, 0x63, 0x7b, 0x39 },
++ .result = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
++ "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
++ "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
++ "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
++ "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
++ "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
++ "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
++ "\xba\x63\x7b\x39",
+ .rlen = 60,
+ }, {
++ .key = zeroed_string,
+ .klen = 24,
+- .input = { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
+- 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00,
+- 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
+- 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
++ .input = "\x98\xe7\x24\x7c\x07\xf0\xfe\x41"
++ "\x1c\x26\x7e\x43\x84\xb0\xf6\x00"
++ "\x2f\xf5\x8d\x80\x03\x39\x27\xab"
++ "\x8e\xf4\xd4\x58\x75\x14\xf0\xfb",
+ .ilen = 32,
++ .result = zeroed_string,
+ .rlen = 16,
+ }, {
+- .key = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+- 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+- 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c },
++ .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
++ "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
++ "\xfe\xff\xe9\x92\x86\x65\x73\x1c",
+ .klen = 24,
+- .iv = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+- 0xde, 0xca, 0xf8, 0x88 },
+- .input = { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
+- 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
+- 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
+- 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
+- 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
+- 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
+- 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
+- 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56,
+- 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
+- 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
++ .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
++ "\xde\xca\xf8\x88",
++ .input = "\x39\x80\xca\x0b\x3c\x00\xe8\x41"
++ "\xeb\x06\xfa\xc4\x87\x2a\x27\x57"
++ "\x85\x9e\x1c\xea\xa6\xef\xd9\x84"
++ "\x62\x85\x93\xb4\x0c\xa1\xe1\x9c"
++ "\x7d\x77\x3d\x00\xc1\x44\xc5\x25"
++ "\xac\x61\x9d\x18\xc8\x4a\x3f\x47"
++ "\x18\xe2\x44\x8b\x2f\xe3\x24\xd9"
++ "\xcc\xda\x27\x10\xac\xad\xe2\x56"
++ "\x99\x24\xa7\xc8\x58\x73\x36\xbf"
++ "\xb1\x18\x02\x4d\xb8\x67\x4a\x14",
+ .ilen = 80,
+- .result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+- 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+- 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+- 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+- 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+- 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+- 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+- 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
++ .result = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
++ "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
++ "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
++ "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
++ "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
++ "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
++ "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
++ "\xba\x63\x7b\x39\x1a\xaf\xd2\x55",
+ .rlen = 64,
+ }, {
+- .key = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+- 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+- 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c },
++ .key = "\xfe\xff\xe9\x92\x86\x65\x73\x1c"
++ "\x6d\x6a\x8f\x94\x67\x30\x83\x08"
++ "\xfe\xff\xe9\x92\x86\x65\x73\x1c",
+ .klen = 24,
+- .iv = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+- 0xde, 0xca, 0xf8, 0x88 },
+- .input = { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
+- 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
+- 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
+- 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
+- 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
+- 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
+- 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
+- 0xcc, 0xda, 0x27, 0x10,
+- 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
+- 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
++ .iv = "\xca\xfe\xba\xbe\xfa\xce\xdb\xad"
++ "\xde\xca\xf8\x88",
++ .input = "\x39\x80\xca\x0b\x3c\x00\xe8\x41"
++ "\xeb\x06\xfa\xc4\x87\x2a\x27\x57"
++ "\x85\x9e\x1c\xea\xa6\xef\xd9\x84"
++ "\x62\x85\x93\xb4\x0c\xa1\xe1\x9c"
++ "\x7d\x77\x3d\x00\xc1\x44\xc5\x25"
++ "\xac\x61\x9d\x18\xc8\x4a\x3f\x47"
++ "\x18\xe2\x44\x8b\x2f\xe3\x24\xd9"
++ "\xcc\xda\x27\x10"
++ "\x25\x19\x49\x8e\x80\xf1\x47\x8f"
++ "\x37\xba\x55\xbd\x6d\x27\x61\x8c",
+ .ilen = 76,
+- .assoc = { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+- 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+- 0xab, 0xad, 0xda, 0xd2 },
++ .assoc = "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
++ "\xfe\xed\xfa\xce\xde\xad\xbe\xef"
++ "\xab\xad\xda\xd2",
+ .alen = 20,
+- .result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+- 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+- 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+- 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+- 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+- 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+- 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+- 0xba, 0x63, 0x7b, 0x39 },
++ .result = "\xd9\x31\x32\x25\xf8\x84\x06\xe5"
++ "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
++ "\x86\xa7\xa9\x53\x15\x34\xf7\xda"
++ "\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
++ "\x1c\x3c\x0c\x95\x95\x68\x09\x53"
++ "\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
++ "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57"
++ "\xba\x63\x7b\x39",
+ .rlen = 60,
+ }
+ };
+
+ static struct aead_testvec aes_ccm_enc_tv_template[] = {
+ { /* From RFC 3610 */
+- .key = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+- 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
++ .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++ "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
+ .klen = 16,
+- .iv = { 0x01, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00,
+- 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
+- .assoc = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
++ .iv = "\x01\x00\x00\x00\x03\x02\x01\x00"
++ "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00",
++ .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07",
+ .alen = 8,
+- .input = { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e },
++ .input = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e",
+ .ilen = 23,
+- .result = { 0x58, 0x8c, 0x97, 0x9a, 0x61, 0xc6, 0x63, 0xd2,
+- 0xf0, 0x66, 0xd0, 0xc2, 0xc0, 0xf9, 0x89, 0x80,
+- 0x6d, 0x5f, 0x6b, 0x61, 0xda, 0xc3, 0x84, 0x17,
+- 0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0 },
++ .result = "\x58\x8c\x97\x9a\x61\xc6\x63\xd2"
++ "\xf0\x66\xd0\xc2\xc0\xf9\x89\x80"
++ "\x6d\x5f\x6b\x61\xda\xc3\x84\x17"
++ "\xe8\xd1\x2c\xfd\xf9\x26\xe0",
+ .rlen = 31,
+ }, {
+- .key = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+- 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
++ .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++ "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
+ .klen = 16,
+- .iv = { 0x01, 0x00, 0x00, 0x00, 0x07, 0x06, 0x05, 0x04,
+- 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
+- .assoc = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b },
++ .iv = "\x01\x00\x00\x00\x07\x06\x05\x04"
++ "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00",
++ .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b",
+ .alen = 12,
+- .input = { 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+- 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
+- 0x1c, 0x1d, 0x1e, 0x1f },
++ .input = "\x0c\x0d\x0e\x0f\x10\x11\x12\x13"
++ "\x14\x15\x16\x17\x18\x19\x1a\x1b"
++ "\x1c\x1d\x1e\x1f",
+ .ilen = 20,
+- .result = { 0xdc, 0xf1, 0xfb, 0x7b, 0x5d, 0x9e, 0x23, 0xfb,
+- 0x9d, 0x4e, 0x13, 0x12, 0x53, 0x65, 0x8a, 0xd8,
+- 0x6e, 0xbd, 0xca, 0x3e, 0x51, 0xe8, 0x3f, 0x07,
+- 0x7d, 0x9c, 0x2d, 0x93 },
++ .result = "\xdc\xf1\xfb\x7b\x5d\x9e\x23\xfb"
++ "\x9d\x4e\x13\x12\x53\x65\x8a\xd8"
++ "\x6e\xbd\xca\x3e\x51\xe8\x3f\x07"
++ "\x7d\x9c\x2d\x93",
+ .rlen = 28,
+ }, {
+- .key = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+- 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
++ .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++ "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
+ .klen = 16,
+- .iv = { 0x01, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x09, 0x08,
+- 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
+- .assoc = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
++ .iv = "\x01\x00\x00\x00\x0b\x0a\x09\x08"
++ "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00",
++ .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07",
+ .alen = 8,
+- .input = { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+- 0x20 },
++ .input = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
++ "\x20",
+ .ilen = 25,
+- .result = { 0x82, 0x53, 0x1a, 0x60, 0xcc, 0x24, 0x94, 0x5a,
+- 0x4b, 0x82, 0x79, 0x18, 0x1a, 0xb5, 0xc8, 0x4d,
+- 0xf2, 0x1c, 0xe7, 0xf9, 0xb7, 0x3f, 0x42, 0xe1,
+- 0x97, 0xea, 0x9c, 0x07, 0xe5, 0x6b, 0x5e, 0xb1,
+- 0x7e, 0x5f, 0x4e },
++ .result = "\x82\x53\x1a\x60\xcc\x24\x94\x5a"
++ "\x4b\x82\x79\x18\x1a\xb5\xc8\x4d"
++ "\xf2\x1c\xe7\xf9\xb7\x3f\x42\xe1"
++ "\x97\xea\x9c\x07\xe5\x6b\x5e\xb1"
++ "\x7e\x5f\x4e",
+ .rlen = 35,
+ }, {
+- .key = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+- 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
++ .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++ "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
+ .klen = 16,
+- .iv = { 0x01, 0x00, 0x00, 0x00, 0x0c, 0x0b, 0x0a, 0x09,
+- 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
+- .assoc = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b },
++ .iv = "\x01\x00\x00\x00\x0c\x0b\x0a\x09"
++ "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00",
++ .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b",
+ .alen = 12,
+- .input = { 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+- 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
+- 0x1c, 0x1d, 0x1e },
++ .input = "\x0c\x0d\x0e\x0f\x10\x11\x12\x13"
++ "\x14\x15\x16\x17\x18\x19\x1a\x1b"
++ "\x1c\x1d\x1e",
+ .ilen = 19,
+- .result = { 0x07, 0x34, 0x25, 0x94, 0x15, 0x77, 0x85, 0x15,
+- 0x2b, 0x07, 0x40, 0x98, 0x33, 0x0a, 0xbb, 0x14,
+- 0x1b, 0x94, 0x7b, 0x56, 0x6a, 0xa9, 0x40, 0x6b,
+- 0x4d, 0x99, 0x99, 0x88, 0xdd },
++ .result = "\x07\x34\x25\x94\x15\x77\x85\x15"
++ "\x2b\x07\x40\x98\x33\x0a\xbb\x14"
++ "\x1b\x94\x7b\x56\x6a\xa9\x40\x6b"
++ "\x4d\x99\x99\x88\xdd",
+ .rlen = 29,
+ }, {
+- .key = { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
+- 0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
++ .key = "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3"
++ "\x25\xa7\x62\x36\xdf\x93\xcc\x6b",
+ .klen = 16,
+- .iv = { 0x01, 0x00, 0x33, 0x56, 0x8e, 0xf7, 0xb2, 0x63,
+- 0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
+- .assoc = { 0x63, 0x01, 0x8f, 0x76, 0xdc, 0x8a, 0x1b, 0xcb },
++ .iv = "\x01\x00\x33\x56\x8e\xf7\xb2\x63"
++ "\x3c\x96\x96\x76\x6c\xfa\x00\x00",
++ .assoc = "\x63\x01\x8f\x76\xdc\x8a\x1b\xcb",
+ .alen = 8,
+- .input = { 0x90, 0x20, 0xea, 0x6f, 0x91, 0xbd, 0xd8, 0x5a,
+- 0xfa, 0x00, 0x39, 0xba, 0x4b, 0xaf, 0xf9, 0xbf,
+- 0xb7, 0x9c, 0x70, 0x28, 0x94, 0x9c, 0xd0, 0xec },
++ .input = "\x90\x20\xea\x6f\x91\xbd\xd8\x5a"
++ "\xfa\x00\x39\xba\x4b\xaf\xf9\xbf"
++ "\xb7\x9c\x70\x28\x94\x9c\xd0\xec",
+ .ilen = 24,
+- .result = { 0x4c, 0xcb, 0x1e, 0x7c, 0xa9, 0x81, 0xbe, 0xfa,
+- 0xa0, 0x72, 0x6c, 0x55, 0xd3, 0x78, 0x06, 0x12,
+- 0x98, 0xc8, 0x5c, 0x92, 0x81, 0x4a, 0xbc, 0x33,
+- 0xc5, 0x2e, 0xe8, 0x1d, 0x7d, 0x77, 0xc0, 0x8a },
++ .result = "\x4c\xcb\x1e\x7c\xa9\x81\xbe\xfa"
++ "\xa0\x72\x6c\x55\xd3\x78\x06\x12"
++ "\x98\xc8\x5c\x92\x81\x4a\xbc\x33"
++ "\xc5\x2e\xe8\x1d\x7d\x77\xc0\x8a",
+ .rlen = 32,
+ }, {
+- .key = { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
+- 0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
++ .key = "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3"
++ "\x25\xa7\x62\x36\xdf\x93\xcc\x6b",
+ .klen = 16,
+- .iv = { 0x01, 0x00, 0xd5, 0x60, 0x91, 0x2d, 0x3f, 0x70,
+- 0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
+- .assoc = { 0xcd, 0x90, 0x44, 0xd2, 0xb7, 0x1f, 0xdb, 0x81,
+- 0x20, 0xea, 0x60, 0xc0 },
++ .iv = "\x01\x00\xd5\x60\x91\x2d\x3f\x70"
++ "\x3c\x96\x96\x76\x6c\xfa\x00\x00",
++ .assoc = "\xcd\x90\x44\xd2\xb7\x1f\xdb\x81"
++ "\x20\xea\x60\xc0",
+ .alen = 12,
+- .input = { 0x64, 0x35, 0xac, 0xba, 0xfb, 0x11, 0xa8, 0x2e,
+- 0x2f, 0x07, 0x1d, 0x7c, 0xa4, 0xa5, 0xeb, 0xd9,
+- 0x3a, 0x80, 0x3b, 0xa8, 0x7f },
++ .input = "\x64\x35\xac\xba\xfb\x11\xa8\x2e"
++ "\x2f\x07\x1d\x7c\xa4\xa5\xeb\xd9"
++ "\x3a\x80\x3b\xa8\x7f",
+ .ilen = 21,
+- .result = { 0x00, 0x97, 0x69, 0xec, 0xab, 0xdf, 0x48, 0x62,
+- 0x55, 0x94, 0xc5, 0x92, 0x51, 0xe6, 0x03, 0x57,
+- 0x22, 0x67, 0x5e, 0x04, 0xc8, 0x47, 0x09, 0x9e,
+- 0x5a, 0xe0, 0x70, 0x45, 0x51 },
++ .result = "\x00\x97\x69\xec\xab\xdf\x48\x62"
++ "\x55\x94\xc5\x92\x51\xe6\x03\x57"
++ "\x22\x67\x5e\x04\xc8\x47\x09\x9e"
++ "\x5a\xe0\x70\x45\x51",
+ .rlen = 29,
+ }, {
+- .key = { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
+- 0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
++ .key = "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3"
++ "\x25\xa7\x62\x36\xdf\x93\xcc\x6b",
+ .klen = 16,
+- .iv = { 0x01, 0x00, 0x42, 0xff, 0xf8, 0xf1, 0x95, 0x1c,
+- 0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
+- .assoc = { 0xd8, 0x5b, 0xc7, 0xe6, 0x9f, 0x94, 0x4f, 0xb8 },
++ .iv = "\x01\x00\x42\xff\xf8\xf1\x95\x1c"
++ "\x3c\x96\x96\x76\x6c\xfa\x00\x00",
++ .assoc = "\xd8\x5b\xc7\xe6\x9f\x94\x4f\xb8",
+ .alen = 8,
+- .input = { 0x8a, 0x19, 0xb9, 0x50, 0xbc, 0xf7, 0x1a, 0x01,
+- 0x8e, 0x5e, 0x67, 0x01, 0xc9, 0x17, 0x87, 0x65,
+- 0x98, 0x09, 0xd6, 0x7d, 0xbe, 0xdd, 0x18 },
++ .input = "\x8a\x19\xb9\x50\xbc\xf7\x1a\x01"
++ "\x8e\x5e\x67\x01\xc9\x17\x87\x65"
++ "\x98\x09\xd6\x7d\xbe\xdd\x18",
+ .ilen = 23,
+- .result = { 0xbc, 0x21, 0x8d, 0xaa, 0x94, 0x74, 0x27, 0xb6,
+- 0xdb, 0x38, 0x6a, 0x99, 0xac, 0x1a, 0xef, 0x23,
+- 0xad, 0xe0, 0xb5, 0x29, 0x39, 0xcb, 0x6a, 0x63,
+- 0x7c, 0xf9, 0xbe, 0xc2, 0x40, 0x88, 0x97, 0xc6,
+- 0xba },
++ .result = "\xbc\x21\x8d\xaa\x94\x74\x27\xb6"
++ "\xdb\x38\x6a\x99\xac\x1a\xef\x23"
++ "\xad\xe0\xb5\x29\x39\xcb\x6a\x63"
++ "\x7c\xf9\xbe\xc2\x40\x88\x97\xc6"
++ "\xba",
+ .rlen = 33,
+ },
+ };
+
+ static struct aead_testvec aes_ccm_dec_tv_template[] = {
+ { /* From RFC 3610 */
+- .key = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+- 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
++ .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++ "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
+ .klen = 16,
+- .iv = { 0x01, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00,
+- 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
+- .assoc = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
++ .iv = "\x01\x00\x00\x00\x03\x02\x01\x00"
++ "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00",
++ .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07",
+ .alen = 8,
+- .input = { 0x58, 0x8c, 0x97, 0x9a, 0x61, 0xc6, 0x63, 0xd2,
+- 0xf0, 0x66, 0xd0, 0xc2, 0xc0, 0xf9, 0x89, 0x80,
+- 0x6d, 0x5f, 0x6b, 0x61, 0xda, 0xc3, 0x84, 0x17,
+- 0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0 },
++ .input = "\x58\x8c\x97\x9a\x61\xc6\x63\xd2"
++ "\xf0\x66\xd0\xc2\xc0\xf9\x89\x80"
++ "\x6d\x5f\x6b\x61\xda\xc3\x84\x17"
++ "\xe8\xd1\x2c\xfd\xf9\x26\xe0",
+ .ilen = 31,
+- .result = { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e },
++ .result = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e",
+ .rlen = 23,
+ }, {
+- .key = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+- 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
++ .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++ "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
+ .klen = 16,
+- .iv = { 0x01, 0x00, 0x00, 0x00, 0x07, 0x06, 0x05, 0x04,
+- 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
+- .assoc = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b },
++ .iv = "\x01\x00\x00\x00\x07\x06\x05\x04"
++ "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00",
++ .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b",
+ .alen = 12,
+- .input = { 0xdc, 0xf1, 0xfb, 0x7b, 0x5d, 0x9e, 0x23, 0xfb,
+- 0x9d, 0x4e, 0x13, 0x12, 0x53, 0x65, 0x8a, 0xd8,
+- 0x6e, 0xbd, 0xca, 0x3e, 0x51, 0xe8, 0x3f, 0x07,
+- 0x7d, 0x9c, 0x2d, 0x93 },
++ .input = "\xdc\xf1\xfb\x7b\x5d\x9e\x23\xfb"
++ "\x9d\x4e\x13\x12\x53\x65\x8a\xd8"
++ "\x6e\xbd\xca\x3e\x51\xe8\x3f\x07"
++ "\x7d\x9c\x2d\x93",
+ .ilen = 28,
+- .result = { 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+- 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
+- 0x1c, 0x1d, 0x1e, 0x1f },
++ .result = "\x0c\x0d\x0e\x0f\x10\x11\x12\x13"
++ "\x14\x15\x16\x17\x18\x19\x1a\x1b"
++ "\x1c\x1d\x1e\x1f",
+ .rlen = 20,
+ }, {
+- .key = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+- 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
++ .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++ "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
+ .klen = 16,
+- .iv = { 0x01, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x09, 0x08,
+- 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
+- .assoc = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
++ .iv = "\x01\x00\x00\x00\x0b\x0a\x09\x08"
++ "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00",
++ .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07",
+ .alen = 8,
+- .input = { 0x82, 0x53, 0x1a, 0x60, 0xcc, 0x24, 0x94, 0x5a,
+- 0x4b, 0x82, 0x79, 0x18, 0x1a, 0xb5, 0xc8, 0x4d,
+- 0xf2, 0x1c, 0xe7, 0xf9, 0xb7, 0x3f, 0x42, 0xe1,
+- 0x97, 0xea, 0x9c, 0x07, 0xe5, 0x6b, 0x5e, 0xb1,
+- 0x7e, 0x5f, 0x4e },
++ .input = "\x82\x53\x1a\x60\xcc\x24\x94\x5a"
++ "\x4b\x82\x79\x18\x1a\xb5\xc8\x4d"
++ "\xf2\x1c\xe7\xf9\xb7\x3f\x42\xe1"
++ "\x97\xea\x9c\x07\xe5\x6b\x5e\xb1"
++ "\x7e\x5f\x4e",
+ .ilen = 35,
+- .result = { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+- 0x20 },
++ .result = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
++ "\x20",
+ .rlen = 25,
+ }, {
+- .key = { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+- 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
++ .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++ "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
+ .klen = 16,
+- .iv = { 0x01, 0x00, 0x00, 0x00, 0x0c, 0x0b, 0x0a, 0x09,
+- 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
+- .assoc = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b },
++ .iv = "\x01\x00\x00\x00\x0c\x0b\x0a\x09"
++ "\xa0\xa1\xa2\xa3\xa4\xa5\x00\x00",
++ .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b",
+ .alen = 12,
+- .input = { 0x07, 0x34, 0x25, 0x94, 0x15, 0x77, 0x85, 0x15,
+- 0x2b, 0x07, 0x40, 0x98, 0x33, 0x0a, 0xbb, 0x14,
+- 0x1b, 0x94, 0x7b, 0x56, 0x6a, 0xa9, 0x40, 0x6b,
+- 0x4d, 0x99, 0x99, 0x88, 0xdd },
++ .input = "\x07\x34\x25\x94\x15\x77\x85\x15"
++ "\x2b\x07\x40\x98\x33\x0a\xbb\x14"
++ "\x1b\x94\x7b\x56\x6a\xa9\x40\x6b"
++ "\x4d\x99\x99\x88\xdd",
+ .ilen = 29,
+- .result = { 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+- 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
+- 0x1c, 0x1d, 0x1e },
++ .result = "\x0c\x0d\x0e\x0f\x10\x11\x12\x13"
++ "\x14\x15\x16\x17\x18\x19\x1a\x1b"
++ "\x1c\x1d\x1e",
+ .rlen = 19,
+ }, {
+- .key = { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
+- 0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
++ .key = "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3"
++ "\x25\xa7\x62\x36\xdf\x93\xcc\x6b",
+ .klen = 16,
+- .iv = { 0x01, 0x00, 0x33, 0x56, 0x8e, 0xf7, 0xb2, 0x63,
+- 0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
+- .assoc = { 0x63, 0x01, 0x8f, 0x76, 0xdc, 0x8a, 0x1b, 0xcb },
++ .iv = "\x01\x00\x33\x56\x8e\xf7\xb2\x63"
++ "\x3c\x96\x96\x76\x6c\xfa\x00\x00",
++ .assoc = "\x63\x01\x8f\x76\xdc\x8a\x1b\xcb",
+ .alen = 8,
+- .input = { 0x4c, 0xcb, 0x1e, 0x7c, 0xa9, 0x81, 0xbe, 0xfa,
+- 0xa0, 0x72, 0x6c, 0x55, 0xd3, 0x78, 0x06, 0x12,
+- 0x98, 0xc8, 0x5c, 0x92, 0x81, 0x4a, 0xbc, 0x33,
+- 0xc5, 0x2e, 0xe8, 0x1d, 0x7d, 0x77, 0xc0, 0x8a },
++ .input = "\x4c\xcb\x1e\x7c\xa9\x81\xbe\xfa"
++ "\xa0\x72\x6c\x55\xd3\x78\x06\x12"
++ "\x98\xc8\x5c\x92\x81\x4a\xbc\x33"
++ "\xc5\x2e\xe8\x1d\x7d\x77\xc0\x8a",
+ .ilen = 32,
+- .result = { 0x90, 0x20, 0xea, 0x6f, 0x91, 0xbd, 0xd8, 0x5a,
+- 0xfa, 0x00, 0x39, 0xba, 0x4b, 0xaf, 0xf9, 0xbf,
+- 0xb7, 0x9c, 0x70, 0x28, 0x94, 0x9c, 0xd0, 0xec },
++ .result = "\x90\x20\xea\x6f\x91\xbd\xd8\x5a"
++ "\xfa\x00\x39\xba\x4b\xaf\xf9\xbf"
++ "\xb7\x9c\x70\x28\x94\x9c\xd0\xec",
+ .rlen = 24,
+ }, {
+- .key = { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
+- 0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
++ .key = "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3"
++ "\x25\xa7\x62\x36\xdf\x93\xcc\x6b",
+ .klen = 16,
+- .iv = { 0x01, 0x00, 0xd5, 0x60, 0x91, 0x2d, 0x3f, 0x70,
+- 0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
+- .assoc = { 0xcd, 0x90, 0x44, 0xd2, 0xb7, 0x1f, 0xdb, 0x81,
+- 0x20, 0xea, 0x60, 0xc0 },
++ .iv = "\x01\x00\xd5\x60\x91\x2d\x3f\x70"
++ "\x3c\x96\x96\x76\x6c\xfa\x00\x00",
++ .assoc = "\xcd\x90\x44\xd2\xb7\x1f\xdb\x81"
++ "\x20\xea\x60\xc0",
+ .alen = 12,
+- .input = { 0x00, 0x97, 0x69, 0xec, 0xab, 0xdf, 0x48, 0x62,
+- 0x55, 0x94, 0xc5, 0x92, 0x51, 0xe6, 0x03, 0x57,
+- 0x22, 0x67, 0x5e, 0x04, 0xc8, 0x47, 0x09, 0x9e,
+- 0x5a, 0xe0, 0x70, 0x45, 0x51 },
++ .input = "\x00\x97\x69\xec\xab\xdf\x48\x62"
++ "\x55\x94\xc5\x92\x51\xe6\x03\x57"
++ "\x22\x67\x5e\x04\xc8\x47\x09\x9e"
++ "\x5a\xe0\x70\x45\x51",
+ .ilen = 29,
+- .result = { 0x64, 0x35, 0xac, 0xba, 0xfb, 0x11, 0xa8, 0x2e,
+- 0x2f, 0x07, 0x1d, 0x7c, 0xa4, 0xa5, 0xeb, 0xd9,
+- 0x3a, 0x80, 0x3b, 0xa8, 0x7f },
++ .result = "\x64\x35\xac\xba\xfb\x11\xa8\x2e"
++ "\x2f\x07\x1d\x7c\xa4\xa5\xeb\xd9"
++ "\x3a\x80\x3b\xa8\x7f",
+ .rlen = 21,
+ }, {
+- .key = { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
+- 0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
++ .key = "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3"
++ "\x25\xa7\x62\x36\xdf\x93\xcc\x6b",
+ .klen = 16,
+- .iv = { 0x01, 0x00, 0x42, 0xff, 0xf8, 0xf1, 0x95, 0x1c,
+- 0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
+- .assoc = { 0xd8, 0x5b, 0xc7, 0xe6, 0x9f, 0x94, 0x4f, 0xb8 },
++ .iv = "\x01\x00\x42\xff\xf8\xf1\x95\x1c"
++ "\x3c\x96\x96\x76\x6c\xfa\x00\x00",
++ .assoc = "\xd8\x5b\xc7\xe6\x9f\x94\x4f\xb8",
+ .alen = 8,
+- .input = { 0xbc, 0x21, 0x8d, 0xaa, 0x94, 0x74, 0x27, 0xb6,
+- 0xdb, 0x38, 0x6a, 0x99, 0xac, 0x1a, 0xef, 0x23,
+- 0xad, 0xe0, 0xb5, 0x29, 0x39, 0xcb, 0x6a, 0x63,
+- 0x7c, 0xf9, 0xbe, 0xc2, 0x40, 0x88, 0x97, 0xc6,
+- 0xba },
++ .input = "\xbc\x21\x8d\xaa\x94\x74\x27\xb6"
++ "\xdb\x38\x6a\x99\xac\x1a\xef\x23"
++ "\xad\xe0\xb5\x29\x39\xcb\x6a\x63"
++ "\x7c\xf9\xbe\xc2\x40\x88\x97\xc6"
++ "\xba",
+ .ilen = 33,
+- .result = { 0x8a, 0x19, 0xb9, 0x50, 0xbc, 0xf7, 0x1a, 0x01,
+- 0x8e, 0x5e, 0x67, 0x01, 0xc9, 0x17, 0x87, 0x65,
+- 0x98, 0x09, 0xd6, 0x7d, 0xbe, 0xdd, 0x18 },
++ .result = "\x8a\x19\xb9\x50\xbc\xf7\x1a\x01"
++ "\x8e\x5e\x67\x01\xc9\x17\x87\x65"
++ "\x98\x09\xd6\x7d\xbe\xdd\x18",
+ .rlen = 23,
+ },
+ };
+@@ -5294,54 +5323,54 @@ static struct aead_testvec aes_ccm_dec_tv_template[] = {
+
+ static struct cipher_testvec cast5_enc_tv_template[] = {
+ {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
+- 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9a },
++ .key = "\x01\x23\x45\x67\x12\x34\x56\x78"
++ "\x23\x45\x67\x89\x34\x56\x78\x9a",
+ .klen = 16,
+- .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .input = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .ilen = 8,
+- .result = { 0x23, 0x8b, 0x4f, 0xe5, 0x84, 0x7e, 0x44, 0xb2 },
++ .result = "\x23\x8b\x4f\xe5\x84\x7e\x44\xb2",
+ .rlen = 8,
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
+- 0x23, 0x45 },
++ .key = "\x01\x23\x45\x67\x12\x34\x56\x78"
++ "\x23\x45",
+ .klen = 10,
+- .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .input = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .ilen = 8,
+- .result = { 0xeb, 0x6a, 0x71, 0x1a, 0x2c, 0x02, 0x27, 0x1b },
++ .result = "\xeb\x6a\x71\x1a\x2c\x02\x27\x1b",
+ .rlen = 8,
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x12 },
++ .key = "\x01\x23\x45\x67\x12",
+ .klen = 5,
+- .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .input = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .ilen = 8,
+- .result = { 0x7a, 0xc8, 0x16, 0xd1, 0x6e, 0x9b, 0x30, 0x2e },
++ .result = "\x7a\xc8\x16\xd1\x6e\x9b\x30\x2e",
+ .rlen = 8,
+ },
+ };
+
+ static struct cipher_testvec cast5_dec_tv_template[] = {
+ {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
+- 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9a },
++ .key = "\x01\x23\x45\x67\x12\x34\x56\x78"
++ "\x23\x45\x67\x89\x34\x56\x78\x9a",
+ .klen = 16,
+- .input = { 0x23, 0x8b, 0x4f, 0xe5, 0x84, 0x7e, 0x44, 0xb2 },
++ .input = "\x23\x8b\x4f\xe5\x84\x7e\x44\xb2",
+ .ilen = 8,
+- .result = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .result = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .rlen = 8,
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
+- 0x23, 0x45 },
++ .key = "\x01\x23\x45\x67\x12\x34\x56\x78"
++ "\x23\x45",
+ .klen = 10,
+- .input = { 0xeb, 0x6a, 0x71, 0x1a, 0x2c, 0x02, 0x27, 0x1b },
++ .input = "\xeb\x6a\x71\x1a\x2c\x02\x27\x1b",
+ .ilen = 8,
+- .result = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .result = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .rlen = 8,
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x12 },
++ .key = "\x01\x23\x45\x67\x12",
+ .klen = 5,
+- .input = { 0x7a, 0xc8, 0x16, 0xd1, 0x6e, 0x9b, 0x30, 0x2e },
++ .input = "\x7a\xc8\x16\xd1\x6e\x9b\x30\x2e",
+ .ilen = 8,
+- .result = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .result = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .rlen = 8,
+ },
+ };
+@@ -5354,132 +5383,132 @@ static struct cipher_testvec cast5_dec_tv_template[] = {
+
+ static struct cipher_testvec arc4_enc_tv_template[] = {
+ {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .input = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .ilen = 8,
+- .result = { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 },
++ .result = "\x75\xb7\x87\x80\x99\xe0\xc5\x96",
+ .rlen = 8,
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .input = "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .ilen = 8,
+- .result = { 0x74, 0x94, 0xc2, 0xe7, 0x10, 0x4b, 0x08, 0x79 },
++ .result = "\x74\x94\xc2\xe7\x10\x4b\x08\x79",
+ .rlen = 8,
+ }, {
+- .key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .key = "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .klen = 8,
+- .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .input = "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .ilen = 8,
+- .result = { 0xde, 0x18, 0x89, 0x41, 0xa3, 0x37, 0x5d, 0x3a },
++ .result = "\xde\x18\x89\x41\xa3\x37\x5d\x3a",
+ .rlen = 8,
+ }, {
+- .key = { 0xef, 0x01, 0x23, 0x45},
++ .key = "\xef\x01\x23\x45",
+ .klen = 4,
+- .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00 },
++ .input = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00",
+ .ilen = 20,
+- .result = { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf,
+- 0xbd, 0x61, 0x5a, 0x11, 0x62, 0xe1, 0xc7, 0xba,
+- 0x36, 0xb6, 0x78, 0x58 },
++ .result = "\xd6\xa1\x41\xa7\xec\x3c\x38\xdf"
++ "\xbd\x61\x5a\x11\x62\xe1\xc7\xba"
++ "\x36\xb6\x78\x58",
+ .rlen = 20,
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .input = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+- 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+- 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+- 0x12, 0x34, 0x56, 0x78 },
++ .input = "\x12\x34\x56\x78\x9A\xBC\xDE\xF0"
++ "\x12\x34\x56\x78\x9A\xBC\xDE\xF0"
++ "\x12\x34\x56\x78\x9A\xBC\xDE\xF0"
++ "\x12\x34\x56\x78",
+ .ilen = 28,
+- .result = { 0x66, 0xa0, 0x94, 0x9f, 0x8a, 0xf7, 0xd6, 0x89,
+- 0x1f, 0x7f, 0x83, 0x2b, 0xa8, 0x33, 0xc0, 0x0c,
+- 0x89, 0x2e, 0xbe, 0x30, 0x14, 0x3c, 0xe2, 0x87,
+- 0x40, 0x01, 0x1e, 0xcf },
++ .result = "\x66\xa0\x94\x9f\x8a\xf7\xd6\x89"
++ "\x1f\x7f\x83\x2b\xa8\x33\xc0\x0c"
++ "\x89\x2e\xbe\x30\x14\x3c\xe2\x87"
++ "\x40\x01\x1e\xcf",
+ .rlen = 28,
+ }, {
+- .key = { 0xef, 0x01, 0x23, 0x45 },
++ .key = "\xef\x01\x23\x45",
+ .klen = 4,
+- .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00 },
++ .input = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00",
+ .ilen = 10,
+- .result = { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf,
+- 0xbd, 0x61 },
++ .result = "\xd6\xa1\x41\xa7\xec\x3c\x38\xdf"
++ "\xbd\x61",
+ .rlen = 10,
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .key = "\x01\x23\x45\x67\x89\xAB\xCD\xEF"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .klen = 16,
+- .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
++ .input = "\x01\x23\x45\x67\x89\xAB\xCD\xEF",
+ .ilen = 8,
+- .result = { 0x69, 0x72, 0x36, 0x59, 0x1B, 0x52, 0x42, 0xB1 },
++ .result = "\x69\x72\x36\x59\x1B\x52\x42\xB1",
+ .rlen = 8,
+ },
+ };
+
+ static struct cipher_testvec arc4_dec_tv_template[] = {
+ {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .input = { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 },
++ .input = "\x75\xb7\x87\x80\x99\xe0\xc5\x96",
+ .ilen = 8,
+- .result = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .result = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .rlen = 8,
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .input = { 0x74, 0x94, 0xc2, 0xe7, 0x10, 0x4b, 0x08, 0x79 },
++ .input = "\x74\x94\xc2\xe7\x10\x4b\x08\x79",
+ .ilen = 8,
+- .result = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .result = "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .rlen = 8,
+ }, {
+- .key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .key = "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .klen = 8,
+- .input = { 0xde, 0x18, 0x89, 0x41, 0xa3, 0x37, 0x5d, 0x3a },
++ .input = "\xde\x18\x89\x41\xa3\x37\x5d\x3a",
+ .ilen = 8,
+- .result = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .result = "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .rlen = 8,
+ }, {
+- .key = { 0xef, 0x01, 0x23, 0x45},
++ .key = "\xef\x01\x23\x45",
+ .klen = 4,
+- .input = { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf,
+- 0xbd, 0x61, 0x5a, 0x11, 0x62, 0xe1, 0xc7, 0xba,
+- 0x36, 0xb6, 0x78, 0x58 },
++ .input = "\xd6\xa1\x41\xa7\xec\x3c\x38\xdf"
++ "\xbd\x61\x5a\x11\x62\xe1\xc7\xba"
++ "\x36\xb6\x78\x58",
+ .ilen = 20,
+- .result = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00 },
++ .result = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00",
+ .rlen = 20,
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef",
+ .klen = 8,
+- .input = { 0x66, 0xa0, 0x94, 0x9f, 0x8a, 0xf7, 0xd6, 0x89,
+- 0x1f, 0x7f, 0x83, 0x2b, 0xa8, 0x33, 0xc0, 0x0c,
+- 0x89, 0x2e, 0xbe, 0x30, 0x14, 0x3c, 0xe2, 0x87,
+- 0x40, 0x01, 0x1e, 0xcf },
++ .input = "\x66\xa0\x94\x9f\x8a\xf7\xd6\x89"
++ "\x1f\x7f\x83\x2b\xa8\x33\xc0\x0c"
++ "\x89\x2e\xbe\x30\x14\x3c\xe2\x87"
++ "\x40\x01\x1e\xcf",
+ .ilen = 28,
+- .result = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+- 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+- 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+- 0x12, 0x34, 0x56, 0x78 },
++ .result = "\x12\x34\x56\x78\x9A\xBC\xDE\xF0"
++ "\x12\x34\x56\x78\x9A\xBC\xDE\xF0"
++ "\x12\x34\x56\x78\x9A\xBC\xDE\xF0"
++ "\x12\x34\x56\x78",
+ .rlen = 28,
+ }, {
+- .key = { 0xef, 0x01, 0x23, 0x45 },
++ .key = "\xef\x01\x23\x45",
+ .klen = 4,
+- .input = { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf,
+- 0xbd, 0x61 },
++ .input = "\xd6\xa1\x41\xa7\xec\x3c\x38\xdf"
++ "\xbd\x61",
+ .ilen = 10,
+- .result = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00 },
++ .result = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00",
+ .rlen = 10,
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .key = "\x01\x23\x45\x67\x89\xAB\xCD\xEF"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .klen = 16,
+- .input = { 0x69, 0x72, 0x36, 0x59, 0x1B, 0x52, 0x42, 0xB1 },
++ .input = "\x69\x72\x36\x59\x1B\x52\x42\xB1",
+ .ilen = 8,
+- .result = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
++ .result = "\x01\x23\x45\x67\x89\xAB\xCD\xEF",
+ .rlen = 8,
+ },
+ };
+@@ -5492,86 +5521,86 @@ static struct cipher_testvec arc4_dec_tv_template[] = {
+
+ static struct cipher_testvec tea_enc_tv_template[] = {
+ {
+- .key = { [0 ... 15] = 0x00 },
++ .key = zeroed_string,
+ .klen = 16,
+- .input = { [0 ... 8] = 0x00 },
++ .input = zeroed_string,
+ .ilen = 8,
+- .result = { 0x0a, 0x3a, 0xea, 0x41, 0x40, 0xa9, 0xba, 0x94 },
++ .result = "\x0a\x3a\xea\x41\x40\xa9\xba\x94",
+ .rlen = 8,
+ }, {
+- .key = { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+- 0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
++ .key = "\x2b\x02\x05\x68\x06\x14\x49\x76"
++ "\x77\x5d\x0e\x26\x6c\x28\x78\x43",
+ .klen = 16,
+- .input = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
++ .input = "\x74\x65\x73\x74\x20\x6d\x65\x2e",
+ .ilen = 8,
+- .result = { 0x77, 0x5d, 0x2a, 0x6a, 0xf6, 0xce, 0x92, 0x09 },
++ .result = "\x77\x5d\x2a\x6a\xf6\xce\x92\x09",
+ .rlen = 8,
+ }, {
+- .key = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+- 0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
++ .key = "\x09\x65\x43\x11\x66\x44\x39\x25"
++ "\x51\x3a\x16\x10\x0a\x08\x12\x6e",
+ .klen = 16,
+- .input = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
+- 0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
++ .input = "\x6c\x6f\x6e\x67\x65\x72\x5f\x74"
++ "\x65\x73\x74\x5f\x76\x65\x63\x74",
+ .ilen = 16,
+- .result = { 0xbe, 0x7a, 0xbb, 0x81, 0x95, 0x2d, 0x1f, 0x1e,
+- 0xdd, 0x89, 0xa1, 0x25, 0x04, 0x21, 0xdf, 0x95 },
++ .result = "\xbe\x7a\xbb\x81\x95\x2d\x1f\x1e"
++ "\xdd\x89\xa1\x25\x04\x21\xdf\x95",
+ .rlen = 16,
+ }, {
+- .key = { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+- 0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
++ .key = "\x4d\x76\x32\x17\x05\x3f\x75\x2c"
++ "\x5d\x04\x16\x36\x15\x72\x63\x2f",
+ .klen = 16,
+- .input = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
+- 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+- 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
+- 0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
++ .input = "\x54\x65\x61\x20\x69\x73\x20\x67"
++ "\x6f\x6f\x64\x20\x66\x6f\x72\x20"
++ "\x79\x6f\x75\x21\x21\x21\x20\x72"
++ "\x65\x61\x6c\x6c\x79\x21\x21\x21",
+ .ilen = 32,
+- .result = { 0xe0, 0x4d, 0x5d, 0x3c, 0xb7, 0x8c, 0x36, 0x47,
+- 0x94, 0x18, 0x95, 0x91, 0xa9, 0xfc, 0x49, 0xf8,
+- 0x44, 0xd1, 0x2d, 0xc2, 0x99, 0xb8, 0x08, 0x2a,
+- 0x07, 0x89, 0x73, 0xc2, 0x45, 0x92, 0xc6, 0x90 },
++ .result = "\xe0\x4d\x5d\x3c\xb7\x8c\x36\x47"
++ "\x94\x18\x95\x91\xa9\xfc\x49\xf8"
++ "\x44\xd1\x2d\xc2\x99\xb8\x08\x2a"
++ "\x07\x89\x73\xc2\x45\x92\xc6\x90",
+ .rlen = 32,
+ }
+ };
+
+ static struct cipher_testvec tea_dec_tv_template[] = {
+ {
+- .key = { [0 ... 15] = 0x00 },
++ .key = zeroed_string,
+ .klen = 16,
+- .input = { 0x0a, 0x3a, 0xea, 0x41, 0x40, 0xa9, 0xba, 0x94 },
++ .input = "\x0a\x3a\xea\x41\x40\xa9\xba\x94",
+ .ilen = 8,
+- .result = { [0 ... 8] = 0x00 },
++ .result = zeroed_string,
+ .rlen = 8,
+ }, {
+- .key = { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+- 0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
++ .key = "\x2b\x02\x05\x68\x06\x14\x49\x76"
++ "\x77\x5d\x0e\x26\x6c\x28\x78\x43",
+ .klen = 16,
+- .input = { 0x77, 0x5d, 0x2a, 0x6a, 0xf6, 0xce, 0x92, 0x09 },
++ .input = "\x77\x5d\x2a\x6a\xf6\xce\x92\x09",
+ .ilen = 8,
+- .result = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
++ .result = "\x74\x65\x73\x74\x20\x6d\x65\x2e",
+ .rlen = 8,
+ }, {
+- .key = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+- 0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
++ .key = "\x09\x65\x43\x11\x66\x44\x39\x25"
++ "\x51\x3a\x16\x10\x0a\x08\x12\x6e",
+ .klen = 16,
+- .input = { 0xbe, 0x7a, 0xbb, 0x81, 0x95, 0x2d, 0x1f, 0x1e,
+- 0xdd, 0x89, 0xa1, 0x25, 0x04, 0x21, 0xdf, 0x95 },
++ .input = "\xbe\x7a\xbb\x81\x95\x2d\x1f\x1e"
++ "\xdd\x89\xa1\x25\x04\x21\xdf\x95",
+ .ilen = 16,
+- .result = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
+- 0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
++ .result = "\x6c\x6f\x6e\x67\x65\x72\x5f\x74"
++ "\x65\x73\x74\x5f\x76\x65\x63\x74",
+ .rlen = 16,
+ }, {
+- .key = { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+- 0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
++ .key = "\x4d\x76\x32\x17\x05\x3f\x75\x2c"
++ "\x5d\x04\x16\x36\x15\x72\x63\x2f",
+ .klen = 16,
+- .input = { 0xe0, 0x4d, 0x5d, 0x3c, 0xb7, 0x8c, 0x36, 0x47,
+- 0x94, 0x18, 0x95, 0x91, 0xa9, 0xfc, 0x49, 0xf8,
+- 0x44, 0xd1, 0x2d, 0xc2, 0x99, 0xb8, 0x08, 0x2a,
+- 0x07, 0x89, 0x73, 0xc2, 0x45, 0x92, 0xc6, 0x90 },
++ .input = "\xe0\x4d\x5d\x3c\xb7\x8c\x36\x47"
++ "\x94\x18\x95\x91\xa9\xfc\x49\xf8"
++ "\x44\xd1\x2d\xc2\x99\xb8\x08\x2a"
++ "\x07\x89\x73\xc2\x45\x92\xc6\x90",
+ .ilen = 32,
+- .result = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
+- 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+- 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
+- 0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
++ .result = "\x54\x65\x61\x20\x69\x73\x20\x67"
++ "\x6f\x6f\x64\x20\x66\x6f\x72\x20"
++ "\x79\x6f\x75\x21\x21\x21\x20\x72"
++ "\x65\x61\x6c\x6c\x79\x21\x21\x21",
+ .rlen = 32,
+ }
+ };
+@@ -5584,86 +5613,86 @@ static struct cipher_testvec tea_dec_tv_template[] = {
+
+ static struct cipher_testvec xtea_enc_tv_template[] = {
+ {
+- .key = { [0 ... 15] = 0x00 },
++ .key = zeroed_string,
+ .klen = 16,
+- .input = { [0 ... 8] = 0x00 },
++ .input = zeroed_string,
+ .ilen = 8,
+- .result = { 0xd8, 0xd4, 0xe9, 0xde, 0xd9, 0x1e, 0x13, 0xf7 },
++ .result = "\xd8\xd4\xe9\xde\xd9\x1e\x13\xf7",
+ .rlen = 8,
+ }, {
+- .key = { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+- 0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
++ .key = "\x2b\x02\x05\x68\x06\x14\x49\x76"
++ "\x77\x5d\x0e\x26\x6c\x28\x78\x43",
+ .klen = 16,
+- .input = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
++ .input = "\x74\x65\x73\x74\x20\x6d\x65\x2e",
+ .ilen = 8,
+- .result = { 0x94, 0xeb, 0xc8, 0x96, 0x84, 0x6a, 0x49, 0xa8 },
++ .result = "\x94\xeb\xc8\x96\x84\x6a\x49\xa8",
+ .rlen = 8,
+ }, {
+- .key = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+- 0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
++ .key = "\x09\x65\x43\x11\x66\x44\x39\x25"
++ "\x51\x3a\x16\x10\x0a\x08\x12\x6e",
+ .klen = 16,
+- .input = { 0x3e, 0xce, 0xae, 0x22, 0x60, 0x56, 0xa8, 0x9d,
+- 0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
++ .input = "\x6c\x6f\x6e\x67\x65\x72\x5f\x74"
++ "\x65\x73\x74\x5f\x76\x65\x63\x74",
+ .ilen = 16,
+- .result = { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea,
+- 0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c },
++ .result = "\x3e\xce\xae\x22\x60\x56\xa8\x9d"
++ "\x77\x4d\xd4\xb4\x87\x24\xe3\x9a",
+ .rlen = 16,
+ }, {
+- .key = { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+- 0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
++ .key = "\x4d\x76\x32\x17\x05\x3f\x75\x2c"
++ "\x5d\x04\x16\x36\x15\x72\x63\x2f",
+ .klen = 16,
+- .input = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
+- 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+- 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
+- 0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
++ .input = "\x54\x65\x61\x20\x69\x73\x20\x67"
++ "\x6f\x6f\x64\x20\x66\x6f\x72\x20"
++ "\x79\x6f\x75\x21\x21\x21\x20\x72"
++ "\x65\x61\x6c\x6c\x79\x21\x21\x21",
+ .ilen = 32,
+- .result = { 0x99, 0x81, 0x9f, 0x5d, 0x6f, 0x4b, 0x31, 0x3a,
+- 0x86, 0xff, 0x6f, 0xd0, 0xe3, 0x87, 0x70, 0x07,
+- 0x4d, 0xb8, 0xcf, 0xf3, 0x99, 0x50, 0xb3, 0xd4,
+- 0x73, 0xa2, 0xfa, 0xc9, 0x16, 0x59, 0x5d, 0x81 },
++ .result = "\x99\x81\x9f\x5d\x6f\x4b\x31\x3a"
++ "\x86\xff\x6f\xd0\xe3\x87\x70\x07"
++ "\x4d\xb8\xcf\xf3\x99\x50\xb3\xd4"
++ "\x73\xa2\xfa\xc9\x16\x59\x5d\x81",
+ .rlen = 32,
+ }
+ };
+
+ static struct cipher_testvec xtea_dec_tv_template[] = {
+ {
+- .key = { [0 ... 15] = 0x00 },
++ .key = zeroed_string,
+ .klen = 16,
+- .input = { 0xd8, 0xd4, 0xe9, 0xde, 0xd9, 0x1e, 0x13, 0xf7 },
++ .input = "\xd8\xd4\xe9\xde\xd9\x1e\x13\xf7",
+ .ilen = 8,
+- .result = { [0 ... 8] = 0x00 },
++ .result = zeroed_string,
+ .rlen = 8,
+ }, {
+- .key = { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+- 0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
++ .key = "\x2b\x02\x05\x68\x06\x14\x49\x76"
++ "\x77\x5d\x0e\x26\x6c\x28\x78\x43",
+ .klen = 16,
+- .input = { 0x94, 0xeb, 0xc8, 0x96, 0x84, 0x6a, 0x49, 0xa8 },
++ .input = "\x94\xeb\xc8\x96\x84\x6a\x49\xa8",
+ .ilen = 8,
+- .result = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
++ .result = "\x74\x65\x73\x74\x20\x6d\x65\x2e",
+ .rlen = 8,
+ }, {
+- .key = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+- 0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
++ .key = "\x09\x65\x43\x11\x66\x44\x39\x25"
++ "\x51\x3a\x16\x10\x0a\x08\x12\x6e",
+ .klen = 16,
+- .input = { 0x3e, 0xce, 0xae, 0x22, 0x60, 0x56, 0xa8, 0x9d,
+- 0x77, 0x4d, 0xd4, 0xb4, 0x87, 0x24, 0xe3, 0x9a },
++ .input = "\x3e\xce\xae\x22\x60\x56\xa8\x9d"
++ "\x77\x4d\xd4\xb4\x87\x24\xe3\x9a",
+ .ilen = 16,
+- .result = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
+- 0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
++ .result = "\x6c\x6f\x6e\x67\x65\x72\x5f\x74"
++ "\x65\x73\x74\x5f\x76\x65\x63\x74",
+ .rlen = 16,
+ }, {
+- .key = { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+- 0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
++ .key = "\x4d\x76\x32\x17\x05\x3f\x75\x2c"
++ "\x5d\x04\x16\x36\x15\x72\x63\x2f",
+ .klen = 16,
+- .input = { 0x99, 0x81, 0x9f, 0x5d, 0x6f, 0x4b, 0x31, 0x3a,
+- 0x86, 0xff, 0x6f, 0xd0, 0xe3, 0x87, 0x70, 0x07,
+- 0x4d, 0xb8, 0xcf, 0xf3, 0x99, 0x50, 0xb3, 0xd4,
+- 0x73, 0xa2, 0xfa, 0xc9, 0x16, 0x59, 0x5d, 0x81 },
++ .input = "\x99\x81\x9f\x5d\x6f\x4b\x31\x3a"
++ "\x86\xff\x6f\xd0\xe3\x87\x70\x07"
++ "\x4d\xb8\xcf\xf3\x99\x50\xb3\xd4"
++ "\x73\xa2\xfa\xc9\x16\x59\x5d\x81",
+ .ilen = 32,
+- .result = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
+- 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+- 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
+- 0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
++ .result = "\x54\x65\x61\x20\x69\x73\x20\x67"
++ "\x6f\x6f\x64\x20\x66\x6f\x72\x20"
++ "\x79\x6f\x75\x21\x21\x21\x20\x72"
++ "\x65\x61\x6c\x6c\x79\x21\x21\x21",
+ .rlen = 32,
+ }
+ };
+@@ -5676,92 +5705,92 @@ static struct cipher_testvec xtea_dec_tv_template[] = {
+
+ static struct cipher_testvec khazad_enc_tv_template[] = {
+ {
+- .key = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .key = "\x80\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .klen = 16,
+- .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .input = "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .ilen = 8,
+- .result = { 0x49, 0xa4, 0xce, 0x32, 0xac, 0x19, 0x0e, 0x3f },
++ .result = "\x49\xa4\xce\x32\xac\x19\x0e\x3f",
+ .rlen = 8,
+ }, {
+- .key = { 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
+- 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38 },
++ .key = "\x38\x38\x38\x38\x38\x38\x38\x38"
++ "\x38\x38\x38\x38\x38\x38\x38\x38",
+ .klen = 16,
+- .input = { 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38 },
++ .input = "\x38\x38\x38\x38\x38\x38\x38\x38",
+ .ilen = 8,
+- .result = { 0x7e, 0x82, 0x12, 0xa1, 0Xd9, 0X5b, 0Xe4, 0Xf9 },
++ .result = "\x7e\x82\x12\xa1\xd9\x5b\xe4\xf9",
+ .rlen = 8,
+ }, {
+- .key = { 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2,
+- 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2 },
++ .key = "\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2"
++ "\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2",
+ .klen = 16,
+- .input = { 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2 },
++ .input = "\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2",
+ .ilen = 8,
+- .result = { 0Xaa, 0Xbe, 0Xc1, 0X95, 0Xc5, 0X94, 0X1a, 0X9c },
++ .result = "\xaa\xbe\xc1\x95\xc5\x94\x1a\x9c",
+ .rlen = 8,
+ }, {
+- .key = { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f,
+- 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f },
++ .key = "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f"
++ "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f",
+ .klen = 16,
+- .input = { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f },
++ .input = "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f",
+ .ilen = 8,
+- .result = { 0X04, 0X74, 0Xf5, 0X70, 0X50, 0X16, 0Xd3, 0Xb8 },
++ .result = "\x04\x74\xf5\x70\x50\x16\xd3\xb8",
+ .rlen = 8,
+ }, {
+- .key = { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f,
+- 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f },
++ .key = "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f"
++ "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f",
+ .klen = 16,
+- .input = { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f ,
+- 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f },
++ .input = "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f"
++ "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f",
+ .ilen = 16,
+- .result = { 0X04, 0X74, 0Xf5, 0X70, 0X50, 0X16, 0Xd3, 0Xb8 ,
+- 0X04, 0X74, 0Xf5, 0X70, 0X50, 0X16, 0Xd3, 0Xb8 },
++ .result = "\x04\x74\xf5\x70\x50\x16\xd3\xb8"
++ "\x04\x74\xf5\x70\x50\x16\xd3\xb8",
+ .rlen = 16,
+ },
+ };
+
+ static struct cipher_testvec khazad_dec_tv_template[] = {
+ {
+- .key = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .key = "\x80\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .klen = 16,
+- .input = { 0X49, 0Xa4, 0Xce, 0X32, 0Xac, 0X19, 0X0e, 0X3f },
++ .input = "\x49\xa4\xce\x32\xac\x19\x0e\x3f",
+ .ilen = 8,
+- .result = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .result = "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .rlen = 8,
+ }, {
+- .key = { 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
+- 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38 },
++ .key = "\x38\x38\x38\x38\x38\x38\x38\x38"
++ "\x38\x38\x38\x38\x38\x38\x38\x38",
+ .klen = 16,
+- .input = { 0X7e, 0X82, 0X12, 0Xa1, 0Xd9, 0X5b, 0Xe4, 0Xf9 },
++ .input = "\x7e\x82\x12\xa1\xd9\x5b\xe4\xf9",
+ .ilen = 8,
+- .result = { 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38 },
++ .result = "\x38\x38\x38\x38\x38\x38\x38\x38",
+ .rlen = 8,
+ }, {
+- .key = { 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2,
+- 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2 },
++ .key = "\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2"
++ "\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2",
+ .klen = 16,
+- .input = { 0Xaa, 0Xbe, 0Xc1, 0X95, 0Xc5, 0X94, 0X1a, 0X9c },
++ .input = "\xaa\xbe\xc1\x95\xc5\x94\x1a\x9c",
+ .ilen = 8,
+- .result = { 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2 },
++ .result = "\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2",
+ .rlen = 8,
+ }, {
+- .key = { 0x2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f,
+- 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f },
++ .key = "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f"
++ "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f",
+ .klen = 16,
+- .input = { 0X04, 0X74, 0Xf5, 0X70, 0X50, 0X16, 0Xd3, 0Xb8 },
++ .input = "\x04\x74\xf5\x70\x50\x16\xd3\xb8",
+ .ilen = 8,
+- .result = { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f },
++ .result = "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f",
+ .rlen = 8,
+ }, {
+- .key = { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f,
+- 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f },
++ .key = "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f"
++ "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f",
+ .klen = 16,
+- .input = { 0X04, 0X74, 0Xf5, 0X70, 0X50, 0X16, 0Xd3, 0Xb8 ,
+- 0X04, 0X74, 0Xf5, 0X70, 0X50, 0X16, 0Xd3, 0Xb8 },
++ .input = "\x04\x74\xf5\x70\x50\x16\xd3\xb8"
++ "\x04\x74\xf5\x70\x50\x16\xd3\xb8",
+ .ilen = 16,
+- .result = { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f ,
+- 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f },
++ .result = "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f"
++ "\x2f\x2f\x2f\x2f\x2f\x2f\x2f\x2f",
+ .rlen = 16,
+ },
+ };
+@@ -5777,196 +5806,196 @@ static struct cipher_testvec khazad_dec_tv_template[] = {
+
+ static struct cipher_testvec anubis_enc_tv_template[] = {
+ {
+- .key = { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+- 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },
++ .key = "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
++ "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe",
+ .klen = 16,
+- .input = { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+- 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },
++ .input = "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
++ "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe",
+ .ilen = 16,
+- .result = { 0x6d, 0xc5, 0xda, 0xa2, 0x26, 0x7d, 0x62, 0x6f,
+- 0x08, 0xb7, 0x52, 0x8e, 0x6e, 0x6e, 0x86, 0x90 },
++ .result = "\x6d\xc5\xda\xa2\x26\x7d\x62\x6f"
++ "\x08\xb7\x52\x8e\x6e\x6e\x86\x90",
+ .rlen = 16,
+ }, {
+
+- .key = { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+- 0x03, 0x03, 0x03, 0x03 },
++ .key = "\x03\x03\x03\x03\x03\x03\x03\x03"
++ "\x03\x03\x03\x03\x03\x03\x03\x03"
++ "\x03\x03\x03\x03",
+ .klen = 20,
+- .input = { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 },
++ .input = "\x03\x03\x03\x03\x03\x03\x03\x03"
++ "\x03\x03\x03\x03\x03\x03\x03\x03",
+ .ilen = 16,
+- .result = { 0xdb, 0xf1, 0x42, 0xf4, 0xd1, 0x8a, 0xc7, 0x49,
+- 0x87, 0x41, 0x6f, 0x82, 0x0a, 0x98, 0x64, 0xae },
++ .result = "\xdb\xf1\x42\xf4\xd1\x8a\xc7\x49"
++ "\x87\x41\x6f\x82\x0a\x98\x64\xae",
+ .rlen = 16,
+ }, {
+- .key = { 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
+- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
+- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
+- 0x24, 0x24, 0x24, 0x24 },
++ .key = "\x24\x24\x24\x24\x24\x24\x24\x24"
++ "\x24\x24\x24\x24\x24\x24\x24\x24"
++ "\x24\x24\x24\x24\x24\x24\x24\x24"
++ "\x24\x24\x24\x24",
+ .klen = 28,
+- .input = { 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
+- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24 },
++ .input = "\x24\x24\x24\x24\x24\x24\x24\x24"
++ "\x24\x24\x24\x24\x24\x24\x24\x24",
+ .ilen = 16,
+- .result = { 0xfd, 0x1b, 0x4a, 0xe3, 0xbf, 0xf0, 0xad, 0x3d,
+- 0x06, 0xd3, 0x61, 0x27, 0xfd, 0x13, 0x9e, 0xde },
++ .result = "\xfd\x1b\x4a\xe3\xbf\xf0\xad\x3d"
++ "\x06\xd3\x61\x27\xfd\x13\x9e\xde",
+ .rlen = 16,
+ }, {
+- .key = { 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
+- 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
+- 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
+- 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25 },
++ .key = "\x25\x25\x25\x25\x25\x25\x25\x25"
++ "\x25\x25\x25\x25\x25\x25\x25\x25"
++ "\x25\x25\x25\x25\x25\x25\x25\x25"
++ "\x25\x25\x25\x25\x25\x25\x25\x25",
+ .klen = 32,
+- .input = { 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
+- 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25 },
++ .input = "\x25\x25\x25\x25\x25\x25\x25\x25"
++ "\x25\x25\x25\x25\x25\x25\x25\x25",
+ .ilen = 16,
+- .result = { 0x1a, 0x91, 0xfb, 0x2b, 0xb7, 0x78, 0x6b, 0xc4,
+- 0x17, 0xd9, 0xff, 0x40, 0x3b, 0x0e, 0xe5, 0xfe },
++ .result = "\x1a\x91\xfb\x2b\xb7\x78\x6b\xc4"
++ "\x17\xd9\xff\x40\x3b\x0e\xe5\xfe",
+ .rlen = 16,
+ }, {
+- .key = { 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+- 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+- 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+- 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+- 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35 },
++ .key = "\x35\x35\x35\x35\x35\x35\x35\x35"
++ "\x35\x35\x35\x35\x35\x35\x35\x35"
++ "\x35\x35\x35\x35\x35\x35\x35\x35"
++ "\x35\x35\x35\x35\x35\x35\x35\x35"
++ "\x35\x35\x35\x35\x35\x35\x35\x35",
+ .klen = 40,
+- .input = { 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+- 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35 },
++ .input = "\x35\x35\x35\x35\x35\x35\x35\x35"
++ "\x35\x35\x35\x35\x35\x35\x35\x35",
+ .ilen = 16,
+- .result = { 0xa5, 0x2c, 0x85, 0x6f, 0x9c, 0xba, 0xa0, 0x97,
+- 0x9e, 0xc6, 0x84, 0x0f, 0x17, 0x21, 0x07, 0xee },
++ .result = "\xa5\x2c\x85\x6f\x9c\xba\xa0\x97"
++ "\x9e\xc6\x84\x0f\x17\x21\x07\xee",
+ .rlen = 16,
+ },
+ };
+
+ static struct cipher_testvec anubis_dec_tv_template[] = {
+ {
+- .key = { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+- 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },
++ .key = "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
++ "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe",
+ .klen = 16,
+- .input = { 0x6d, 0xc5, 0xda, 0xa2, 0x26, 0x7d, 0x62, 0x6f,
+- 0x08, 0xb7, 0x52, 0x8e, 0x6e, 0x6e, 0x86, 0x90 },
++ .input = "\x6d\xc5\xda\xa2\x26\x7d\x62\x6f"
++ "\x08\xb7\x52\x8e\x6e\x6e\x86\x90",
+ .ilen = 16,
+- .result = { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+- 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },
++ .result = "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
++ "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe",
+ .rlen = 16,
+ }, {
+
+- .key = { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+- 0x03, 0x03, 0x03, 0x03 },
++ .key = "\x03\x03\x03\x03\x03\x03\x03\x03"
++ "\x03\x03\x03\x03\x03\x03\x03\x03"
++ "\x03\x03\x03\x03",
+ .klen = 20,
+- .input = { 0xdb, 0xf1, 0x42, 0xf4, 0xd1, 0x8a, 0xc7, 0x49,
+- 0x87, 0x41, 0x6f, 0x82, 0x0a, 0x98, 0x64, 0xae },
++ .input = "\xdb\xf1\x42\xf4\xd1\x8a\xc7\x49"
++ "\x87\x41\x6f\x82\x0a\x98\x64\xae",
+ .ilen = 16,
+- .result = { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 },
++ .result = "\x03\x03\x03\x03\x03\x03\x03\x03"
++ "\x03\x03\x03\x03\x03\x03\x03\x03",
+ .rlen = 16,
+ }, {
+- .key = { 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
+- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
+- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
+- 0x24, 0x24, 0x24, 0x24 },
++ .key = "\x24\x24\x24\x24\x24\x24\x24\x24"
++ "\x24\x24\x24\x24\x24\x24\x24\x24"
++ "\x24\x24\x24\x24\x24\x24\x24\x24"
++ "\x24\x24\x24\x24",
+ .klen = 28,
+- .input = { 0xfd, 0x1b, 0x4a, 0xe3, 0xbf, 0xf0, 0xad, 0x3d,
+- 0x06, 0xd3, 0x61, 0x27, 0xfd, 0x13, 0x9e, 0xde },
++ .input = "\xfd\x1b\x4a\xe3\xbf\xf0\xad\x3d"
++ "\x06\xd3\x61\x27\xfd\x13\x9e\xde",
+ .ilen = 16,
+- .result = { 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
+- 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24 },
++ .result = "\x24\x24\x24\x24\x24\x24\x24\x24"
++ "\x24\x24\x24\x24\x24\x24\x24\x24",
+ .rlen = 16,
+ }, {
+- .key = { 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
+- 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
+- 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
+- 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25 },
++ .key = "\x25\x25\x25\x25\x25\x25\x25\x25"
++ "\x25\x25\x25\x25\x25\x25\x25\x25"
++ "\x25\x25\x25\x25\x25\x25\x25\x25"
++ "\x25\x25\x25\x25\x25\x25\x25\x25",
+ .klen = 32,
+- .input = { 0x1a, 0x91, 0xfb, 0x2b, 0xb7, 0x78, 0x6b, 0xc4,
+- 0x17, 0xd9, 0xff, 0x40, 0x3b, 0x0e, 0xe5, 0xfe },
++ .input = "\x1a\x91\xfb\x2b\xb7\x78\x6b\xc4"
++ "\x17\xd9\xff\x40\x3b\x0e\xe5\xfe",
+ .ilen = 16,
+- .result = { 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
+- 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25 },
++ .result = "\x25\x25\x25\x25\x25\x25\x25\x25"
++ "\x25\x25\x25\x25\x25\x25\x25\x25",
+ .rlen = 16,
+ }, {
+- .key = { 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+- 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+- 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+- 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+- 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35 },
+- .input = { 0xa5, 0x2c, 0x85, 0x6f, 0x9c, 0xba, 0xa0, 0x97,
+- 0x9e, 0xc6, 0x84, 0x0f, 0x17, 0x21, 0x07, 0xee },
++ .key = "\x35\x35\x35\x35\x35\x35\x35\x35"
++ "\x35\x35\x35\x35\x35\x35\x35\x35"
++ "\x35\x35\x35\x35\x35\x35\x35\x35"
++ "\x35\x35\x35\x35\x35\x35\x35\x35"
++ "\x35\x35\x35\x35\x35\x35\x35\x35",
++ .input = "\xa5\x2c\x85\x6f\x9c\xba\xa0\x97"
++ "\x9e\xc6\x84\x0f\x17\x21\x07\xee",
+ .klen = 40,
+ .ilen = 16,
+- .result = { 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+- 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35 },
++ .result = "\x35\x35\x35\x35\x35\x35\x35\x35"
++ "\x35\x35\x35\x35\x35\x35\x35\x35",
+ .rlen = 16,
+ },
+ };
+
+ static struct cipher_testvec anubis_cbc_enc_tv_template[] = {
+ {
+- .key = { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+- 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },
++ .key = "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
++ "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe",
+ .klen = 16,
+- .input = { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+- 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+- 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+- 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },
++ .input = "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
++ "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
++ "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
++ "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe",
+ .ilen = 32,
+- .result = { 0x6d, 0xc5, 0xda, 0xa2, 0x26, 0x7d, 0x62, 0x6f,
+- 0x08, 0xb7, 0x52, 0x8e, 0x6e, 0x6e, 0x86, 0x90,
+- 0x86, 0xd8, 0xb5, 0x6f, 0x98, 0x5e, 0x8a, 0x66,
+- 0x4f, 0x1f, 0x78, 0xa1, 0xbb, 0x37, 0xf1, 0xbe },
++ .result = "\x6d\xc5\xda\xa2\x26\x7d\x62\x6f"
++ "\x08\xb7\x52\x8e\x6e\x6e\x86\x90"
++ "\x86\xd8\xb5\x6f\x98\x5e\x8a\x66"
++ "\x4f\x1f\x78\xa1\xbb\x37\xf1\xbe",
+ .rlen = 32,
+ }, {
+- .key = { 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+- 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+- 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+- 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+- 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35 },
++ .key = "\x35\x35\x35\x35\x35\x35\x35\x35"
++ "\x35\x35\x35\x35\x35\x35\x35\x35"
++ "\x35\x35\x35\x35\x35\x35\x35\x35"
++ "\x35\x35\x35\x35\x35\x35\x35\x35"
++ "\x35\x35\x35\x35\x35\x35\x35\x35",
+ .klen = 40,
+- .input = { 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+- 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+- 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+- 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35 },
++ .input = "\x35\x35\x35\x35\x35\x35\x35\x35"
++ "\x35\x35\x35\x35\x35\x35\x35\x35"
++ "\x35\x35\x35\x35\x35\x35\x35\x35"
++ "\x35\x35\x35\x35\x35\x35\x35\x35",
+ .ilen = 32,
+- .result = { 0xa5, 0x2c, 0x85, 0x6f, 0x9c, 0xba, 0xa0, 0x97,
+- 0x9e, 0xc6, 0x84, 0x0f, 0x17, 0x21, 0x07, 0xee,
+- 0xa2, 0xbc, 0x06, 0x98, 0xc6, 0x4b, 0xda, 0x75,
+- 0x2e, 0xaa, 0xbe, 0x58, 0xce, 0x01, 0x5b, 0xc7 },
++ .result = "\xa5\x2c\x85\x6f\x9c\xba\xa0\x97"
++ "\x9e\xc6\x84\x0f\x17\x21\x07\xee"
++ "\xa2\xbc\x06\x98\xc6\x4b\xda\x75"
++ "\x2e\xaa\xbe\x58\xce\x01\x5b\xc7",
+ .rlen = 32,
+ },
+ };
+
+ static struct cipher_testvec anubis_cbc_dec_tv_template[] = {
+ {
+- .key = { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+- 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },
++ .key = "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
++ "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe",
+ .klen = 16,
+- .input = { 0x6d, 0xc5, 0xda, 0xa2, 0x26, 0x7d, 0x62, 0x6f,
+- 0x08, 0xb7, 0x52, 0x8e, 0x6e, 0x6e, 0x86, 0x90,
+- 0x86, 0xd8, 0xb5, 0x6f, 0x98, 0x5e, 0x8a, 0x66,
+- 0x4f, 0x1f, 0x78, 0xa1, 0xbb, 0x37, 0xf1, 0xbe },
++ .input = "\x6d\xc5\xda\xa2\x26\x7d\x62\x6f"
++ "\x08\xb7\x52\x8e\x6e\x6e\x86\x90"
++ "\x86\xd8\xb5\x6f\x98\x5e\x8a\x66"
++ "\x4f\x1f\x78\xa1\xbb\x37\xf1\xbe",
+ .ilen = 32,
+- .result = { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+- 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+- 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+- 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },
++ .result = "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
++ "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
++ "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
++ "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe",
+ .rlen = 32,
+ }, {
+- .key = { 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+- 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+- 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+- 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+- 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35 },
++ .key = "\x35\x35\x35\x35\x35\x35\x35\x35"
++ "\x35\x35\x35\x35\x35\x35\x35\x35"
++ "\x35\x35\x35\x35\x35\x35\x35\x35"
++ "\x35\x35\x35\x35\x35\x35\x35\x35"
++ "\x35\x35\x35\x35\x35\x35\x35\x35",
+ .klen = 40,
+- .input = { 0xa5, 0x2c, 0x85, 0x6f, 0x9c, 0xba, 0xa0, 0x97,
+- 0x9e, 0xc6, 0x84, 0x0f, 0x17, 0x21, 0x07, 0xee,
+- 0xa2, 0xbc, 0x06, 0x98, 0xc6, 0x4b, 0xda, 0x75,
+- 0x2e, 0xaa, 0xbe, 0x58, 0xce, 0x01, 0x5b, 0xc7 },
++ .input = "\xa5\x2c\x85\x6f\x9c\xba\xa0\x97"
++ "\x9e\xc6\x84\x0f\x17\x21\x07\xee"
++ "\xa2\xbc\x06\x98\xc6\x4b\xda\x75"
++ "\x2e\xaa\xbe\x58\xce\x01\x5b\xc7",
+ .ilen = 32,
+- .result = { 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+- 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+- 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+- 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35 },
++ .result = "\x35\x35\x35\x35\x35\x35\x35\x35"
++ "\x35\x35\x35\x35\x35\x35\x35\x35"
++ "\x35\x35\x35\x35\x35\x35\x35\x35"
++ "\x35\x35\x35\x35\x35\x35\x35\x35",
+ .rlen = 32,
+ },
+ };
+@@ -5979,86 +6008,86 @@ static struct cipher_testvec anubis_cbc_dec_tv_template[] = {
+
+ static struct cipher_testvec xeta_enc_tv_template[] = {
+ {
+- .key = { [0 ... 15] = 0x00 },
++ .key = zeroed_string,
+ .klen = 16,
+- .input = { [0 ... 8] = 0x00 },
++ .input = zeroed_string,
+ .ilen = 8,
+- .result = { 0xaa, 0x22, 0x96, 0xe5, 0x6c, 0x61, 0xf3, 0x45 },
++ .result = "\xaa\x22\x96\xe5\x6c\x61\xf3\x45",
+ .rlen = 8,
+ }, {
+- .key = { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+- 0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
++ .key = "\x2b\x02\x05\x68\x06\x14\x49\x76"
++ "\x77\x5d\x0e\x26\x6c\x28\x78\x43",
+ .klen = 16,
+- .input = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
++ .input = "\x74\x65\x73\x74\x20\x6d\x65\x2e",
+ .ilen = 8,
+- .result = { 0x82, 0x3e, 0xeb, 0x35, 0xdc, 0xdd, 0xd9, 0xc3 },
++ .result = "\x82\x3e\xeb\x35\xdc\xdd\xd9\xc3",
+ .rlen = 8,
+ }, {
+- .key = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+- 0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
++ .key = "\x09\x65\x43\x11\x66\x44\x39\x25"
++ "\x51\x3a\x16\x10\x0a\x08\x12\x6e",
+ .klen = 16,
+- .input = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
+- 0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
++ .input = "\x6c\x6f\x6e\x67\x65\x72\x5f\x74"
++ "\x65\x73\x74\x5f\x76\x65\x63\x74",
+ .ilen = 16,
+- .result = { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea,
+- 0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c },
++ .result = "\xe2\x04\xdb\xf2\x89\x85\x9e\xea"
++ "\x61\x35\xaa\xed\xb5\xcb\x71\x2c",
+ .rlen = 16,
+ }, {
+- .key = { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+- 0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
++ .key = "\x4d\x76\x32\x17\x05\x3f\x75\x2c"
++ "\x5d\x04\x16\x36\x15\x72\x63\x2f",
+ .klen = 16,
+- .input = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
+- 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+- 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
+- 0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
++ .input = "\x54\x65\x61\x20\x69\x73\x20\x67"
++ "\x6f\x6f\x64\x20\x66\x6f\x72\x20"
++ "\x79\x6f\x75\x21\x21\x21\x20\x72"
++ "\x65\x61\x6c\x6c\x79\x21\x21\x21",
+ .ilen = 32,
+- .result = { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1,
+- 0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4,
+- 0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f,
+- 0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 },
++ .result = "\x0b\x03\xcd\x8a\xbe\x95\xfd\xb1"
++ "\xc1\x44\x91\x0b\xa5\xc9\x1b\xb4"
++ "\xa9\xda\x1e\x9e\xb1\x3e\x2a\x8f"
++ "\xea\xa5\x6a\x85\xd1\xf4\xa8\xa5",
+ .rlen = 32,
+ }
+ };
+
+ static struct cipher_testvec xeta_dec_tv_template[] = {
+ {
+- .key = { [0 ... 15] = 0x00 },
++ .key = zeroed_string,
+ .klen = 16,
+- .input = { 0xaa, 0x22, 0x96, 0xe5, 0x6c, 0x61, 0xf3, 0x45 },
++ .input = "\xaa\x22\x96\xe5\x6c\x61\xf3\x45",
+ .ilen = 8,
+- .result = { [0 ... 8] = 0x00 },
++ .result = zeroed_string,
+ .rlen = 8,
+ }, {
+- .key = { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+- 0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
++ .key = "\x2b\x02\x05\x68\x06\x14\x49\x76"
++ "\x77\x5d\x0e\x26\x6c\x28\x78\x43",
+ .klen = 16,
+- .input = { 0x82, 0x3e, 0xeb, 0x35, 0xdc, 0xdd, 0xd9, 0xc3 },
++ .input = "\x82\x3e\xeb\x35\xdc\xdd\xd9\xc3",
+ .ilen = 8,
+- .result = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
++ .result = "\x74\x65\x73\x74\x20\x6d\x65\x2e",
+ .rlen = 8,
+ }, {
+- .key = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+- 0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
++ .key = "\x09\x65\x43\x11\x66\x44\x39\x25"
++ "\x51\x3a\x16\x10\x0a\x08\x12\x6e",
+ .klen = 16,
+- .input = { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea,
+- 0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c },
++ .input = "\xe2\x04\xdb\xf2\x89\x85\x9e\xea"
++ "\x61\x35\xaa\xed\xb5\xcb\x71\x2c",
+ .ilen = 16,
+- .result = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
+- 0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
++ .result = "\x6c\x6f\x6e\x67\x65\x72\x5f\x74"
++ "\x65\x73\x74\x5f\x76\x65\x63\x74",
+ .rlen = 16,
+ }, {
+- .key = { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+- 0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
++ .key = "\x4d\x76\x32\x17\x05\x3f\x75\x2c"
++ "\x5d\x04\x16\x36\x15\x72\x63\x2f",
+ .klen = 16,
+- .input = { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1,
+- 0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4,
+- 0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f,
+- 0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 },
++ .input = "\x0b\x03\xcd\x8a\xbe\x95\xfd\xb1"
++ "\xc1\x44\x91\x0b\xa5\xc9\x1b\xb4"
++ "\xa9\xda\x1e\x9e\xb1\x3e\x2a\x8f"
++ "\xea\xa5\x6a\x85\xd1\xf4\xa8\xa5",
+ .ilen = 32,
+- .result = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
+- 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+- 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
+- 0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
++ .result = "\x54\x65\x61\x20\x69\x73\x20\x67"
++ "\x6f\x6f\x64\x20\x66\x6f\x72\x20"
++ "\x79\x6f\x75\x21\x21\x21\x20\x72"
++ "\x65\x61\x6c\x6c\x79\x21\x21\x21",
+ .rlen = 32,
+ }
+ };
+@@ -6071,59 +6100,59 @@ static struct cipher_testvec xeta_dec_tv_template[] = {
+
+ static struct cipher_testvec fcrypt_pcbc_enc_tv_template[] = {
+ { /* http://www.openafs.org/pipermail/openafs-devel/2000-December/005320.html */
+- .key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .key = "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .klen = 8,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+- .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00",
++ .input = "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .ilen = 8,
+- .result = { 0x0E, 0x09, 0x00, 0xC7, 0x3E, 0xF7, 0xED, 0x41 },
++ .result = "\x0E\x09\x00\xC7\x3E\xF7\xED\x41",
+ .rlen = 8,
+ }, {
+- .key = { 0x11, 0x44, 0x77, 0xAA, 0xDD, 0x00, 0x33, 0x66 },
++ .key = "\x11\x44\x77\xAA\xDD\x00\x33\x66",
+ .klen = 8,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+- .input = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0 },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00",
++ .input = "\x12\x34\x56\x78\x9A\xBC\xDE\xF0",
+ .ilen = 8,
+- .result = { 0xD8, 0xED, 0x78, 0x74, 0x77, 0xEC, 0x06, 0x80 },
++ .result = "\xD8\xED\x78\x74\x77\xEC\x06\x80",
+ .rlen = 8,
+ }, { /* From Arla */
+- .key = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
++ .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
+ .klen = 8,
+- .iv = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++ .iv = "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ .input = "The quick brown fox jumps over the lazy dogs.\0\0",
+ .ilen = 48,
+- .result = { 0x00, 0xf0, 0xe, 0x11, 0x75, 0xe6, 0x23, 0x82,
+- 0xee, 0xac, 0x98, 0x62, 0x44, 0x51, 0xe4, 0x84,
+- 0xc3, 0x59, 0xd8, 0xaa, 0x64, 0x60, 0xae, 0xf7,
+- 0xd2, 0xd9, 0x13, 0x79, 0x72, 0xa3, 0x45, 0x03,
+- 0x23, 0xb5, 0x62, 0xd7, 0x0c, 0xf5, 0x27, 0xd1,
+- 0xf8, 0x91, 0x3c, 0xac, 0x44, 0x22, 0x92, 0xef },
++ .result = "\x00\xf0\x0e\x11\x75\xe6\x23\x82"
++ "\xee\xac\x98\x62\x44\x51\xe4\x84"
++ "\xc3\x59\xd8\xaa\x64\x60\xae\xf7"
++ "\xd2\xd9\x13\x79\x72\xa3\x45\x03"
++ "\x23\xb5\x62\xd7\x0c\xf5\x27\xd1"
++ "\xf8\x91\x3c\xac\x44\x22\x92\xef",
+ .rlen = 48,
+ }, {
+- .key = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++ .key = "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ .klen = 8,
+- .iv = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
++ .iv = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
+ .input = "The quick brown fox jumps over the lazy dogs.\0\0",
+ .ilen = 48,
+- .result = { 0xca, 0x90, 0xf5, 0x9d, 0xcb, 0xd4, 0xd2, 0x3c,
+- 0x01, 0x88, 0x7f, 0x3e, 0x31, 0x6e, 0x62, 0x9d,
+- 0xd8, 0xe0, 0x57, 0xa3, 0x06, 0x3a, 0x42, 0x58,
+- 0x2a, 0x28, 0xfe, 0x72, 0x52, 0x2f, 0xdd, 0xe0,
+- 0x19, 0x89, 0x09, 0x1c, 0x2a, 0x8e, 0x8c, 0x94,
+- 0xfc, 0xc7, 0x68, 0xe4, 0x88, 0xaa, 0xde, 0x0f },
++ .result = "\xca\x90\xf5\x9d\xcb\xd4\xd2\x3c"
++ "\x01\x88\x7f\x3e\x31\x6e\x62\x9d"
++ "\xd8\xe0\x57\xa3\x06\x3a\x42\x58"
++ "\x2a\x28\xfe\x72\x52\x2f\xdd\xe0"
++ "\x19\x89\x09\x1c\x2a\x8e\x8c\x94"
++ "\xfc\xc7\x68\xe4\x88\xaa\xde\x0f",
+ .rlen = 48,
+ }, { /* split-page version */
+- .key = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++ .key = "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ .klen = 8,
+- .iv = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
++ .iv = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
+ .input = "The quick brown fox jumps over the lazy dogs.\0\0",
+ .ilen = 48,
+- .result = { 0xca, 0x90, 0xf5, 0x9d, 0xcb, 0xd4, 0xd2, 0x3c,
+- 0x01, 0x88, 0x7f, 0x3e, 0x31, 0x6e, 0x62, 0x9d,
+- 0xd8, 0xe0, 0x57, 0xa3, 0x06, 0x3a, 0x42, 0x58,
+- 0x2a, 0x28, 0xfe, 0x72, 0x52, 0x2f, 0xdd, 0xe0,
+- 0x19, 0x89, 0x09, 0x1c, 0x2a, 0x8e, 0x8c, 0x94,
+- 0xfc, 0xc7, 0x68, 0xe4, 0x88, 0xaa, 0xde, 0x0f },
++ .result = "\xca\x90\xf5\x9d\xcb\xd4\xd2\x3c"
++ "\x01\x88\x7f\x3e\x31\x6e\x62\x9d"
++ "\xd8\xe0\x57\xa3\x06\x3a\x42\x58"
++ "\x2a\x28\xfe\x72\x52\x2f\xdd\xe0"
++ "\x19\x89\x09\x1c\x2a\x8e\x8c\x94"
++ "\xfc\xc7\x68\xe4\x88\xaa\xde\x0f",
+ .rlen = 48,
+ .np = 2,
+ .tap = { 20, 28 },
+@@ -6132,57 +6161,57 @@ static struct cipher_testvec fcrypt_pcbc_enc_tv_template[] = {
+
+ static struct cipher_testvec fcrypt_pcbc_dec_tv_template[] = {
+ { /* http://www.openafs.org/pipermail/openafs-devel/2000-December/005320.html */
+- .key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .key = "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .klen = 8,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+- .input = { 0x0E, 0x09, 0x00, 0xC7, 0x3E, 0xF7, 0xED, 0x41 },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00",
++ .input = "\x0E\x09\x00\xC7\x3E\xF7\xED\x41",
+ .ilen = 8,
+- .result = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .result = "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .rlen = 8,
+ }, {
+- .key = { 0x11, 0x44, 0x77, 0xAA, 0xDD, 0x00, 0x33, 0x66 },
++ .key = "\x11\x44\x77\xAA\xDD\x00\x33\x66",
+ .klen = 8,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+- .input = { 0xD8, 0xED, 0x78, 0x74, 0x77, 0xEC, 0x06, 0x80 },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00",
++ .input = "\xD8\xED\x78\x74\x77\xEC\x06\x80",
+ .ilen = 8,
+- .result = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0 },
++ .result = "\x12\x34\x56\x78\x9A\xBC\xDE\xF0",
+ .rlen = 8,
+ }, { /* From Arla */
+- .key = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
++ .key = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
+ .klen = 8,
+- .iv = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+- .input = { 0x00, 0xf0, 0xe, 0x11, 0x75, 0xe6, 0x23, 0x82,
+- 0xee, 0xac, 0x98, 0x62, 0x44, 0x51, 0xe4, 0x84,
+- 0xc3, 0x59, 0xd8, 0xaa, 0x64, 0x60, 0xae, 0xf7,
+- 0xd2, 0xd9, 0x13, 0x79, 0x72, 0xa3, 0x45, 0x03,
+- 0x23, 0xb5, 0x62, 0xd7, 0x0c, 0xf5, 0x27, 0xd1,
+- 0xf8, 0x91, 0x3c, 0xac, 0x44, 0x22, 0x92, 0xef },
++ .iv = "\xfe\xdc\xba\x98\x76\x54\x32\x10",
++ .input = "\x00\xf0\x0e\x11\x75\xe6\x23\x82"
++ "\xee\xac\x98\x62\x44\x51\xe4\x84"
++ "\xc3\x59\xd8\xaa\x64\x60\xae\xf7"
++ "\xd2\xd9\x13\x79\x72\xa3\x45\x03"
++ "\x23\xb5\x62\xd7\x0c\xf5\x27\xd1"
++ "\xf8\x91\x3c\xac\x44\x22\x92\xef",
+ .ilen = 48,
+ .result = "The quick brown fox jumps over the lazy dogs.\0\0",
+ .rlen = 48,
+ }, {
+- .key = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++ .key = "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ .klen = 8,
+- .iv = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
+- .input = { 0xca, 0x90, 0xf5, 0x9d, 0xcb, 0xd4, 0xd2, 0x3c,
+- 0x01, 0x88, 0x7f, 0x3e, 0x31, 0x6e, 0x62, 0x9d,
+- 0xd8, 0xe0, 0x57, 0xa3, 0x06, 0x3a, 0x42, 0x58,
+- 0x2a, 0x28, 0xfe, 0x72, 0x52, 0x2f, 0xdd, 0xe0,
+- 0x19, 0x89, 0x09, 0x1c, 0x2a, 0x8e, 0x8c, 0x94,
+- 0xfc, 0xc7, 0x68, 0xe4, 0x88, 0xaa, 0xde, 0x0f },
++ .iv = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
++ .input = "\xca\x90\xf5\x9d\xcb\xd4\xd2\x3c"
++ "\x01\x88\x7f\x3e\x31\x6e\x62\x9d"
++ "\xd8\xe0\x57\xa3\x06\x3a\x42\x58"
++ "\x2a\x28\xfe\x72\x52\x2f\xdd\xe0"
++ "\x19\x89\x09\x1c\x2a\x8e\x8c\x94"
++ "\xfc\xc7\x68\xe4\x88\xaa\xde\x0f",
+ .ilen = 48,
+ .result = "The quick brown fox jumps over the lazy dogs.\0\0",
+ .rlen = 48,
+ }, { /* split-page version */
+- .key = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++ .key = "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ .klen = 8,
+- .iv = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
+- .input = { 0xca, 0x90, 0xf5, 0x9d, 0xcb, 0xd4, 0xd2, 0x3c,
+- 0x01, 0x88, 0x7f, 0x3e, 0x31, 0x6e, 0x62, 0x9d,
+- 0xd8, 0xe0, 0x57, 0xa3, 0x06, 0x3a, 0x42, 0x58,
+- 0x2a, 0x28, 0xfe, 0x72, 0x52, 0x2f, 0xdd, 0xe0,
+- 0x19, 0x89, 0x09, 0x1c, 0x2a, 0x8e, 0x8c, 0x94,
+- 0xfc, 0xc7, 0x68, 0xe4, 0x88, 0xaa, 0xde, 0x0f },
++ .iv = "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87",
++ .input = "\xca\x90\xf5\x9d\xcb\xd4\xd2\x3c"
++ "\x01\x88\x7f\x3e\x31\x6e\x62\x9d"
++ "\xd8\xe0\x57\xa3\x06\x3a\x42\x58"
++ "\x2a\x28\xfe\x72\x52\x2f\xdd\xe0"
++ "\x19\x89\x09\x1c\x2a\x8e\x8c\x94"
++ "\xfc\xc7\x68\xe4\x88\xaa\xde\x0f",
+ .ilen = 48,
+ .result = "The quick brown fox jumps over the lazy dogs.\0\0",
+ .rlen = 48,
+@@ -6201,136 +6230,136 @@ static struct cipher_testvec fcrypt_pcbc_dec_tv_template[] = {
+
+ static struct cipher_testvec camellia_enc_tv_template[] = {
+ {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+- 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef"
++ "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ .klen = 16,
+- .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+- 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++ .input = "\x01\x23\x45\x67\x89\xab\xcd\xef"
++ "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ .ilen = 16,
+- .result = { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73,
+- 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 },
++ .result = "\x67\x67\x31\x38\x54\x96\x69\x73"
++ "\x08\x57\x06\x56\x48\xea\xbe\x43",
+ .rlen = 16,
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+- 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef"
++ "\xfe\xdc\xba\x98\x76\x54\x32\x10"
++ "\x00\x11\x22\x33\x44\x55\x66\x77",
+ .klen = 24,
+- .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+- 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++ .input = "\x01\x23\x45\x67\x89\xab\xcd\xef"
++ "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ .ilen = 16,
+- .result = { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8,
+- 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 },
++ .result = "\xb4\x99\x34\x01\xb3\xe9\x96\xf8"
++ "\x4e\xe5\xce\xe7\xd7\x9b\x09\xb9",
+ .rlen = 16,
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+- 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+- 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef"
++ "\xfe\xdc\xba\x98\x76\x54\x32\x10"
++ "\x00\x11\x22\x33\x44\x55\x66\x77"
++ "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+ .klen = 32,
+- .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+- 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++ .input = "\x01\x23\x45\x67\x89\xab\xcd\xef"
++ "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ .ilen = 16,
+- .result = { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c,
+- 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 },
++ .result = "\x9a\xcc\x23\x7d\xff\x16\xd7\x6c"
++ "\x20\xef\x7c\x91\x9e\x3a\x75\x09",
+ .rlen = 16,
+ },
+ };
+
+ static struct cipher_testvec camellia_dec_tv_template[] = {
+ {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+- 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef"
++ "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ .klen = 16,
+- .input = { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73,
+- 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 },
++ .input = "\x67\x67\x31\x38\x54\x96\x69\x73"
++ "\x08\x57\x06\x56\x48\xea\xbe\x43",
+ .ilen = 16,
+- .result = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+- 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++ .result = "\x01\x23\x45\x67\x89\xab\xcd\xef"
++ "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ .rlen = 16,
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+- 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef"
++ "\xfe\xdc\xba\x98\x76\x54\x32\x10"
++ "\x00\x11\x22\x33\x44\x55\x66\x77",
+ .klen = 24,
+- .input = { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8,
+- 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 },
++ .input = "\xb4\x99\x34\x01\xb3\xe9\x96\xf8"
++ "\x4e\xe5\xce\xe7\xd7\x9b\x09\xb9",
+ .ilen = 16,
+- .result = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+- 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++ .result = "\x01\x23\x45\x67\x89\xab\xcd\xef"
++ "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ .rlen = 16,
+ }, {
+- .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+- 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+- 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
++ .key = "\x01\x23\x45\x67\x89\xab\xcd\xef"
++ "\xfe\xdc\xba\x98\x76\x54\x32\x10"
++ "\x00\x11\x22\x33\x44\x55\x66\x77"
++ "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+ .klen = 32,
+- .input = { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c,
+- 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 },
++ .input = "\x9a\xcc\x23\x7d\xff\x16\xd7\x6c"
++ "\x20\xef\x7c\x91\x9e\x3a\x75\x09",
+ .ilen = 16,
+- .result = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+- 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
++ .result = "\x01\x23\x45\x67\x89\xab\xcd\xef"
++ "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+ .rlen = 16,
+ },
+ };
+
+ static struct cipher_testvec camellia_cbc_enc_tv_template[] = {
+ {
+- .key = { 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b,
+- 0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 },
++ .key = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
++ "\x51\x2e\x03\xd5\x34\x12\x00\x06",
+ .klen = 16,
+- .iv = { 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30,
+- 0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 },
+- .input = { "Single block msg" },
++ .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
++ "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
++ .input = "Single block msg",
+ .ilen = 16,
+- .result = { 0xea, 0x32, 0x12, 0x76, 0x3b, 0x50, 0x10, 0xe7,
+- 0x18, 0xf6, 0xfd, 0x5d, 0xf6, 0x8f, 0x13, 0x51 },
++ .result = "\xea\x32\x12\x76\x3b\x50\x10\xe7"
++ "\x18\xf6\xfd\x5d\xf6\x8f\x13\x51",
+ .rlen = 16,
+ }, {
+- .key = { 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0,
+- 0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a },
++ .key = "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0"
++ "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a",
+ .klen = 16,
+- .iv = { 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28,
+- 0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 },
+- .input = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++ .iv = "\x56\x2e\x17\x99\x6d\x09\x3d\x28"
++ "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58",
++ .input = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ .ilen = 32,
+- .result = { 0xa5, 0xdf, 0x6e, 0x50, 0xda, 0x70, 0x6c, 0x01,
+- 0x4a, 0xab, 0xf3, 0xf2, 0xd6, 0xfc, 0x6c, 0xfd,
+- 0x19, 0xb4, 0x3e, 0x57, 0x1c, 0x02, 0x5e, 0xa0,
+- 0x15, 0x78, 0xe0, 0x5e, 0xf2, 0xcb, 0x87, 0x16 },
++ .result = "\xa5\xdf\x6e\x50\xda\x70\x6c\x01"
++ "\x4a\xab\xf3\xf2\xd6\xfc\x6c\xfd"
++ "\x19\xb4\x3e\x57\x1c\x02\x5e\xa0"
++ "\x15\x78\xe0\x5e\xf2\xcb\x87\x16",
+ .rlen = 32,
+ },
+ };
+
+ static struct cipher_testvec camellia_cbc_dec_tv_template[] = {
+ {
+- .key = { 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b,
+- 0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 },
++ .key = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
++ "\x51\x2e\x03\xd5\x34\x12\x00\x06",
+ .klen = 16,
+- .iv = { 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30,
+- 0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 },
+- .input = { 0xea, 0x32, 0x12, 0x76, 0x3b, 0x50, 0x10, 0xe7,
+- 0x18, 0xf6, 0xfd, 0x5d, 0xf6, 0x8f, 0x13, 0x51 },
++ .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
++ "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
++ .input = "\xea\x32\x12\x76\x3b\x50\x10\xe7"
++ "\x18\xf6\xfd\x5d\xf6\x8f\x13\x51",
+ .ilen = 16,
+- .result = { "Single block msg" },
++ .result = "Single block msg",
+ .rlen = 16,
+ }, {
+- .key = { 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0,
+- 0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a },
++ .key = "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0"
++ "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a",
+ .klen = 16,
+- .iv = { 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28,
+- 0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 },
+- .input = { 0xa5, 0xdf, 0x6e, 0x50, 0xda, 0x70, 0x6c, 0x01,
+- 0x4a, 0xab, 0xf3, 0xf2, 0xd6, 0xfc, 0x6c, 0xfd,
+- 0x19, 0xb4, 0x3e, 0x57, 0x1c, 0x02, 0x5e, 0xa0,
+- 0x15, 0x78, 0xe0, 0x5e, 0xf2, 0xcb, 0x87, 0x16 },
++ .iv = "\x56\x2e\x17\x99\x6d\x09\x3d\x28"
++ "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58",
++ .input = "\xa5\xdf\x6e\x50\xda\x70\x6c\x01"
++ "\x4a\xab\xf3\xf2\xd6\xfc\x6c\xfd"
++ "\x19\xb4\x3e\x57\x1c\x02\x5e\xa0"
++ "\x15\x78\xe0\x5e\xf2\xcb\x87\x16",
+ .ilen = 32,
+- .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++ .result = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ .rlen = 32,
+ },
+ };
+@@ -6343,84 +6372,84 @@ static struct cipher_testvec camellia_cbc_dec_tv_template[] = {
+
+ static struct cipher_testvec seed_enc_tv_template[] = {
+ {
+- .key = { [0 ... 15] = 0x00 },
++ .key = zeroed_string,
+ .klen = 16,
+- .input = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++ .input = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .ilen = 16,
+- .result = { 0x5e, 0xba, 0xc6, 0xe0, 0x05, 0x4e, 0x16, 0x68,
+- 0x19, 0xaf, 0xf1, 0xcc, 0x6d, 0x34, 0x6c, 0xdb },
++ .result = "\x5e\xba\xc6\xe0\x05\x4e\x16\x68"
++ "\x19\xaf\xf1\xcc\x6d\x34\x6c\xdb",
+ .rlen = 16,
+ }, {
+- .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .klen = 16,
+- .input = { [0 ... 15] = 0x00 },
++ .input = zeroed_string,
+ .ilen = 16,
+- .result = { 0xc1, 0x1f, 0x22, 0xf2, 0x01, 0x40, 0x50, 0x50,
+- 0x84, 0x48, 0x35, 0x97, 0xe4, 0x37, 0x0f, 0x43 },
++ .result = "\xc1\x1f\x22\xf2\x01\x40\x50\x50"
++ "\x84\x48\x35\x97\xe4\x37\x0f\x43",
+ .rlen = 16,
+ }, {
+- .key = { 0x47, 0x06, 0x48, 0x08, 0x51, 0xe6, 0x1b, 0xe8,
+- 0x5d, 0x74, 0xbf, 0xb3, 0xfd, 0x95, 0x61, 0x85 },
++ .key = "\x47\x06\x48\x08\x51\xe6\x1b\xe8"
++ "\x5d\x74\xbf\xb3\xfd\x95\x61\x85",
+ .klen = 16,
+- .input = { 0x83, 0xa2, 0xf8, 0xa2, 0x88, 0x64, 0x1f, 0xb9,
+- 0xa4, 0xe9, 0xa5, 0xcc, 0x2f, 0x13, 0x1c, 0x7d },
++ .input = "\x83\xa2\xf8\xa2\x88\x64\x1f\xb9"
++ "\xa4\xe9\xa5\xcc\x2f\x13\x1c\x7d",
+ .ilen = 16,
+- .result = { 0xee, 0x54, 0xd1, 0x3e, 0xbc, 0xae, 0x70, 0x6d,
+- 0x22, 0x6b, 0xc3, 0x14, 0x2c, 0xd4, 0x0d, 0x4a },
++ .result = "\xee\x54\xd1\x3e\xbc\xae\x70\x6d"
++ "\x22\x6b\xc3\x14\x2c\xd4\x0d\x4a",
+ .rlen = 16,
+ }, {
+- .key = { 0x28, 0xdb, 0xc3, 0xbc, 0x49, 0xff, 0xd8, 0x7d,
+- 0xcf, 0xa5, 0x09, 0xb1, 0x1d, 0x42, 0x2b, 0xe7 },
++ .key = "\x28\xdb\xc3\xbc\x49\xff\xd8\x7d"
++ "\xcf\xa5\x09\xb1\x1d\x42\x2b\xe7",
+ .klen = 16,
+- .input = { 0xb4, 0x1e, 0x6b, 0xe2, 0xeb, 0xa8, 0x4a, 0x14,
+- 0x8e, 0x2e, 0xed, 0x84, 0x59, 0x3c, 0x5e, 0xc7 },
++ .input = "\xb4\x1e\x6b\xe2\xeb\xa8\x4a\x14"
++ "\x8e\x2e\xed\x84\x59\x3c\x5e\xc7",
+ .ilen = 16,
+- .result = { 0x9b, 0x9b, 0x7b, 0xfc, 0xd1, 0x81, 0x3c, 0xb9,
+- 0x5d, 0x0b, 0x36, 0x18, 0xf4, 0x0f, 0x51, 0x22 },
++ .result = "\x9b\x9b\x7b\xfc\xd1\x81\x3c\xb9"
++ "\x5d\x0b\x36\x18\xf4\x0f\x51\x22",
+ .rlen = 16,
+ }
+ };
+
+ static struct cipher_testvec seed_dec_tv_template[] = {
+ {
+- .key = { [0 ... 15] = 0x00 },
++ .key = zeroed_string,
+ .klen = 16,
+- .input = { 0x5e, 0xba, 0xc6, 0xe0, 0x05, 0x4e, 0x16, 0x68,
+- 0x19, 0xaf, 0xf1, 0xcc, 0x6d, 0x34, 0x6c, 0xdb },
++ .input = "\x5e\xba\xc6\xe0\x05\x4e\x16\x68"
++ "\x19\xaf\xf1\xcc\x6d\x34\x6c\xdb",
+ .ilen = 16,
+- .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++ .result = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .rlen = 16,
+ }, {
+- .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .klen = 16,
+- .input = { 0xc1, 0x1f, 0x22, 0xf2, 0x01, 0x40, 0x50, 0x50,
+- 0x84, 0x48, 0x35, 0x97, 0xe4, 0x37, 0x0f, 0x43 },
++ .input = "\xc1\x1f\x22\xf2\x01\x40\x50\x50"
++ "\x84\x48\x35\x97\xe4\x37\x0f\x43",
+ .ilen = 16,
+- .result = { [0 ... 15] = 0x00 },
++ .result = zeroed_string,
+ .rlen = 16,
+ }, {
+- .key = { 0x47, 0x06, 0x48, 0x08, 0x51, 0xe6, 0x1b, 0xe8,
+- 0x5d, 0x74, 0xbf, 0xb3, 0xfd, 0x95, 0x61, 0x85 },
++ .key = "\x47\x06\x48\x08\x51\xe6\x1b\xe8"
++ "\x5d\x74\xbf\xb3\xfd\x95\x61\x85",
+ .klen = 16,
+- .input = { 0xee, 0x54, 0xd1, 0x3e, 0xbc, 0xae, 0x70, 0x6d,
+- 0x22, 0x6b, 0xc3, 0x14, 0x2c, 0xd4, 0x0d, 0x4a },
++ .input = "\xee\x54\xd1\x3e\xbc\xae\x70\x6d"
++ "\x22\x6b\xc3\x14\x2c\xd4\x0d\x4a",
+ .ilen = 16,
+- .result = { 0x83, 0xa2, 0xf8, 0xa2, 0x88, 0x64, 0x1f, 0xb9,
+- 0xa4, 0xe9, 0xa5, 0xcc, 0x2f, 0x13, 0x1c, 0x7d },
++ .result = "\x83\xa2\xf8\xa2\x88\x64\x1f\xb9"
++ "\xa4\xe9\xa5\xcc\x2f\x13\x1c\x7d",
+ .rlen = 16,
+ }, {
+- .key = { 0x28, 0xdb, 0xc3, 0xbc, 0x49, 0xff, 0xd8, 0x7d,
+- 0xcf, 0xa5, 0x09, 0xb1, 0x1d, 0x42, 0x2b, 0xe7 },
++ .key = "\x28\xdb\xc3\xbc\x49\xff\xd8\x7d"
++ "\xcf\xa5\x09\xb1\x1d\x42\x2b\xe7",
+ .klen = 16,
+- .input = { 0x9b, 0x9b, 0x7b, 0xfc, 0xd1, 0x81, 0x3c, 0xb9,
+- 0x5d, 0x0b, 0x36, 0x18, 0xf4, 0x0f, 0x51, 0x22 },
++ .input = "\x9b\x9b\x7b\xfc\xd1\x81\x3c\xb9"
++ "\x5d\x0b\x36\x18\xf4\x0f\x51\x22",
+ .ilen = 16,
+- .result = { 0xb4, 0x1e, 0x6b, 0xe2, 0xeb, 0xa8, 0x4a, 0x14,
+- 0x8e, 0x2e, 0xed, 0x84, 0x59, 0x3c, 0x5e, 0xc7 },
++ .result = "\xb4\x1e\x6b\xe2\xeb\xa8\x4a\x14"
++ "\x8e\x2e\xed\x84\x59\x3c\x5e\xc7",
+ .rlen = 16,
+ }
+ };
+@@ -6433,1204 +6462,1376 @@ static struct cipher_testvec salsa20_stream_enc_tv_template[] = {
+ * of input length.
+ */
+ { /* Set 3, vector 0 */
+- .key = {
+- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+- },
++ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F",
+ .klen = 16,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+- .input = {
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00",
++ .input = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00",
+ .ilen = 39,
+- .result = {
+- 0x2D, 0xD5, 0xC3, 0xF7, 0xBA, 0x2B, 0x20, 0xF7,
+- 0x68, 0x02, 0x41, 0x0C, 0x68, 0x86, 0x88, 0x89,
+- 0x5A, 0xD8, 0xC1, 0xBD, 0x4E, 0xA6, 0xC9, 0xB1,
+- 0x40, 0xFB, 0x9B, 0x90, 0xE2, 0x10, 0x49, 0xBF,
+- 0x58, 0x3F, 0x52, 0x79, 0x70, 0xEB, 0xC1,
+- },
++ .result = "\x2D\xD5\xC3\xF7\xBA\x2B\x20\xF7"
++ "\x68\x02\x41\x0C\x68\x86\x88\x89"
++ "\x5A\xD8\xC1\xBD\x4E\xA6\xC9\xB1"
++ "\x40\xFB\x9B\x90\xE2\x10\x49\xBF"
++ "\x58\x3F\x52\x79\x70\xEB\xC1",
+ .rlen = 39,
+ }, { /* Set 5, vector 0 */
+- .key = {
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+- },
++ .key = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .klen = 16,
+- .iv = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+- .input = {
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- },
++ .iv = "\x80\x00\x00\x00\x00\x00\x00\x00",
++ .input = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .ilen = 64,
+- .result = {
+- 0xB6, 0x6C, 0x1E, 0x44, 0x46, 0xDD, 0x95, 0x57,
+- 0xE5, 0x78, 0xE2, 0x23, 0xB0, 0xB7, 0x68, 0x01,
+- 0x7B, 0x23, 0xB2, 0x67, 0xBB, 0x02, 0x34, 0xAE,
+- 0x46, 0x26, 0xBF, 0x44, 0x3F, 0x21, 0x97, 0x76,
+- 0x43, 0x6F, 0xB1, 0x9F, 0xD0, 0xE8, 0x86, 0x6F,
+- 0xCD, 0x0D, 0xE9, 0xA9, 0x53, 0x8F, 0x4A, 0x09,
+- 0xCA, 0x9A, 0xC0, 0x73, 0x2E, 0x30, 0xBC, 0xF9,
+- 0x8E, 0x4F, 0x13, 0xE4, 0xB9, 0xE2, 0x01, 0xD9,
+- },
++ .result = "\xB6\x6C\x1E\x44\x46\xDD\x95\x57"
++ "\xE5\x78\xE2\x23\xB0\xB7\x68\x01"
++ "\x7B\x23\xB2\x67\xBB\x02\x34\xAE"
++ "\x46\x26\xBF\x44\x3F\x21\x97\x76"
++ "\x43\x6F\xB1\x9F\xD0\xE8\x86\x6F"
++ "\xCD\x0D\xE9\xA9\x53\x8F\x4A\x09"
++ "\xCA\x9A\xC0\x73\x2E\x30\xBC\xF9"
++ "\x8E\x4F\x13\xE4\xB9\xE2\x01\xD9",
+ .rlen = 64,
+ }, { /* Set 3, vector 27 */
+- .key = {
+- 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22,
+- 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,
+- 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
+- 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A
+- },
++ .key = "\x1B\x1C\x1D\x1E\x1F\x20\x21\x22"
++ "\x23\x24\x25\x26\x27\x28\x29\x2A"
++ "\x2B\x2C\x2D\x2E\x2F\x30\x31\x32"
++ "\x33\x34\x35\x36\x37\x38\x39\x3A",
+ .klen = 32,
+- .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+- .input = {
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00",
++ .input = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00",
+ .ilen = 111,
+- .result = {
+- 0xAE, 0x39, 0x50, 0x8E, 0xAC, 0x9A, 0xEC, 0xE7,
+- 0xBF, 0x97, 0xBB, 0x20, 0xB9, 0xDE, 0xE4, 0x1F,
+- 0x87, 0xD9, 0x47, 0xF8, 0x28, 0x91, 0x35, 0x98,
+- 0xDB, 0x72, 0xCC, 0x23, 0x29, 0x48, 0x56, 0x5E,
+- 0x83, 0x7E, 0x0B, 0xF3, 0x7D, 0x5D, 0x38, 0x7B,
+- 0x2D, 0x71, 0x02, 0xB4, 0x3B, 0xB5, 0xD8, 0x23,
+- 0xB0, 0x4A, 0xDF, 0x3C, 0xEC, 0xB6, 0xD9, 0x3B,
+- 0x9B, 0xA7, 0x52, 0xBE, 0xC5, 0xD4, 0x50, 0x59,
+-
+- 0x15, 0x14, 0xB4, 0x0E, 0x40, 0xE6, 0x53, 0xD1,
+- 0x83, 0x9C, 0x5B, 0xA0, 0x92, 0x29, 0x6B, 0x5E,
+- 0x96, 0x5B, 0x1E, 0x2F, 0xD3, 0xAC, 0xC1, 0x92,
+- 0xB1, 0x41, 0x3F, 0x19, 0x2F, 0xC4, 0x3B, 0xC6,
+- 0x95, 0x46, 0x45, 0x54, 0xE9, 0x75, 0x03, 0x08,
+- 0x44, 0xAF, 0xE5, 0x8A, 0x81, 0x12, 0x09,
+- },
++ .result = "\xAE\x39\x50\x8E\xAC\x9A\xEC\xE7"
++ "\xBF\x97\xBB\x20\xB9\xDE\xE4\x1F"
++ "\x87\xD9\x47\xF8\x28\x91\x35\x98"
++ "\xDB\x72\xCC\x23\x29\x48\x56\x5E"
++ "\x83\x7E\x0B\xF3\x7D\x5D\x38\x7B"
++ "\x2D\x71\x02\xB4\x3B\xB5\xD8\x23"
++ "\xB0\x4A\xDF\x3C\xEC\xB6\xD9\x3B"
++ "\x9B\xA7\x52\xBE\xC5\xD4\x50\x59"
++ "\x15\x14\xB4\x0E\x40\xE6\x53\xD1"
++ "\x83\x9C\x5B\xA0\x92\x29\x6B\x5E"
++ "\x96\x5B\x1E\x2F\xD3\xAC\xC1\x92"
++ "\xB1\x41\x3F\x19\x2F\xC4\x3B\xC6"
++ "\x95\x46\x45\x54\xE9\x75\x03\x08"
++ "\x44\xAF\xE5\x8A\x81\x12\x09",
+ .rlen = 111,
+-
+ }, { /* Set 5, vector 27 */
+- .key = {
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+- },
++ .key = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .klen = 32,
+- .iv = { 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00 },
+- .input = {
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+-
+- 0x00,
+- },
++ .iv = "\x00\x00\x00\x10\x00\x00\x00\x00",
++ .input = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00",
+ .ilen = 129,
+- .result = {
+- 0xD2, 0xDB, 0x1A, 0x5C, 0xF1, 0xC1, 0xAC, 0xDB,
+- 0xE8, 0x1A, 0x7A, 0x43, 0x40, 0xEF, 0x53, 0x43,
+- 0x5E, 0x7F, 0x4B, 0x1A, 0x50, 0x52, 0x3F, 0x8D,
+- 0x28, 0x3D, 0xCF, 0x85, 0x1D, 0x69, 0x6E, 0x60,
+- 0xF2, 0xDE, 0x74, 0x56, 0x18, 0x1B, 0x84, 0x10,
+- 0xD4, 0x62, 0xBA, 0x60, 0x50, 0xF0, 0x61, 0xF2,
+- 0x1C, 0x78, 0x7F, 0xC1, 0x24, 0x34, 0xAF, 0x58,
+- 0xBF, 0x2C, 0x59, 0xCA, 0x90, 0x77, 0xF3, 0xB0,
+-
+- 0x5B, 0x4A, 0xDF, 0x89, 0xCE, 0x2C, 0x2F, 0xFC,
+- 0x67, 0xF0, 0xE3, 0x45, 0xE8, 0xB3, 0xB3, 0x75,
+- 0xA0, 0x95, 0x71, 0xA1, 0x29, 0x39, 0x94, 0xCA,
+- 0x45, 0x2F, 0xBD, 0xCB, 0x10, 0xB6, 0xBE, 0x9F,
+- 0x8E, 0xF9, 0xB2, 0x01, 0x0A, 0x5A, 0x0A, 0xB7,
+- 0x6B, 0x9D, 0x70, 0x8E, 0x4B, 0xD6, 0x2F, 0xCD,
+- 0x2E, 0x40, 0x48, 0x75, 0xE9, 0xE2, 0x21, 0x45,
+- 0x0B, 0xC9, 0xB6, 0xB5, 0x66, 0xBC, 0x9A, 0x59,
+-
+- 0x5A,
+- },
++ .result = "\xD2\xDB\x1A\x5C\xF1\xC1\xAC\xDB"
++ "\xE8\x1A\x7A\x43\x40\xEF\x53\x43"
++ "\x5E\x7F\x4B\x1A\x50\x52\x3F\x8D"
++ "\x28\x3D\xCF\x85\x1D\x69\x6E\x60"
++ "\xF2\xDE\x74\x56\x18\x1B\x84\x10"
++ "\xD4\x62\xBA\x60\x50\xF0\x61\xF2"
++ "\x1C\x78\x7F\xC1\x24\x34\xAF\x58"
++ "\xBF\x2C\x59\xCA\x90\x77\xF3\xB0"
++ "\x5B\x4A\xDF\x89\xCE\x2C\x2F\xFC"
++ "\x67\xF0\xE3\x45\xE8\xB3\xB3\x75"
++ "\xA0\x95\x71\xA1\x29\x39\x94\xCA"
++ "\x45\x2F\xBD\xCB\x10\xB6\xBE\x9F"
++ "\x8E\xF9\xB2\x01\x0A\x5A\x0A\xB7"
++ "\x6B\x9D\x70\x8E\x4B\xD6\x2F\xCD"
++ "\x2E\x40\x48\x75\xE9\xE2\x21\x45"
++ "\x0B\xC9\xB6\xB5\x66\xBC\x9A\x59"
++ "\x5A",
+ .rlen = 129,
+ }, { /* large test vector generated using Crypto++ */
+- .key = {
+- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+- },
++ .key = "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ .klen = 32,
+- .iv = {
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- },
+- .input = {
+- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+- 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+- 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+- 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+- 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+- 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+- 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+- 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+- 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+- 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+- 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+- 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+- 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+- 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+- 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+- 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+- 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+- 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+- 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+- 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+- 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+- 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+- 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+- 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+- 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+- 0x00, 0x03, 0x06, 0x09, 0x0c, 0x0f, 0x12, 0x15,
+- 0x18, 0x1b, 0x1e, 0x21, 0x24, 0x27, 0x2a, 0x2d,
+- 0x30, 0x33, 0x36, 0x39, 0x3c, 0x3f, 0x42, 0x45,
+- 0x48, 0x4b, 0x4e, 0x51, 0x54, 0x57, 0x5a, 0x5d,
+- 0x60, 0x63, 0x66, 0x69, 0x6c, 0x6f, 0x72, 0x75,
+- 0x78, 0x7b, 0x7e, 0x81, 0x84, 0x87, 0x8a, 0x8d,
+- 0x90, 0x93, 0x96, 0x99, 0x9c, 0x9f, 0xa2, 0xa5,
+- 0xa8, 0xab, 0xae, 0xb1, 0xb4, 0xb7, 0xba, 0xbd,
+- 0xc0, 0xc3, 0xc6, 0xc9, 0xcc, 0xcf, 0xd2, 0xd5,
+- 0xd8, 0xdb, 0xde, 0xe1, 0xe4, 0xe7, 0xea, 0xed,
+- 0xf0, 0xf3, 0xf6, 0xf9, 0xfc, 0xff, 0x02, 0x05,
+- 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17, 0x1a, 0x1d,
+- 0x20, 0x23, 0x26, 0x29, 0x2c, 0x2f, 0x32, 0x35,
+- 0x38, 0x3b, 0x3e, 0x41, 0x44, 0x47, 0x4a, 0x4d,
+- 0x50, 0x53, 0x56, 0x59, 0x5c, 0x5f, 0x62, 0x65,
+- 0x68, 0x6b, 0x6e, 0x71, 0x74, 0x77, 0x7a, 0x7d,
+- 0x80, 0x83, 0x86, 0x89, 0x8c, 0x8f, 0x92, 0x95,
+- 0x98, 0x9b, 0x9e, 0xa1, 0xa4, 0xa7, 0xaa, 0xad,
+- 0xb0, 0xb3, 0xb6, 0xb9, 0xbc, 0xbf, 0xc2, 0xc5,
+- 0xc8, 0xcb, 0xce, 0xd1, 0xd4, 0xd7, 0xda, 0xdd,
+- 0xe0, 0xe3, 0xe6, 0xe9, 0xec, 0xef, 0xf2, 0xf5,
+- 0xf8, 0xfb, 0xfe, 0x01, 0x04, 0x07, 0x0a, 0x0d,
+- 0x10, 0x13, 0x16, 0x19, 0x1c, 0x1f, 0x22, 0x25,
+- 0x28, 0x2b, 0x2e, 0x31, 0x34, 0x37, 0x3a, 0x3d,
+- 0x40, 0x43, 0x46, 0x49, 0x4c, 0x4f, 0x52, 0x55,
+- 0x58, 0x5b, 0x5e, 0x61, 0x64, 0x67, 0x6a, 0x6d,
+- 0x70, 0x73, 0x76, 0x79, 0x7c, 0x7f, 0x82, 0x85,
+- 0x88, 0x8b, 0x8e, 0x91, 0x94, 0x97, 0x9a, 0x9d,
+- 0xa0, 0xa3, 0xa6, 0xa9, 0xac, 0xaf, 0xb2, 0xb5,
+- 0xb8, 0xbb, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
+- 0xd0, 0xd3, 0xd6, 0xd9, 0xdc, 0xdf, 0xe2, 0xe5,
+- 0xe8, 0xeb, 0xee, 0xf1, 0xf4, 0xf7, 0xfa, 0xfd,
+- 0x00, 0x05, 0x0a, 0x0f, 0x14, 0x19, 0x1e, 0x23,
+- 0x28, 0x2d, 0x32, 0x37, 0x3c, 0x41, 0x46, 0x4b,
+- 0x50, 0x55, 0x5a, 0x5f, 0x64, 0x69, 0x6e, 0x73,
+- 0x78, 0x7d, 0x82, 0x87, 0x8c, 0x91, 0x96, 0x9b,
+- 0xa0, 0xa5, 0xaa, 0xaf, 0xb4, 0xb9, 0xbe, 0xc3,
+- 0xc8, 0xcd, 0xd2, 0xd7, 0xdc, 0xe1, 0xe6, 0xeb,
+- 0xf0, 0xf5, 0xfa, 0xff, 0x04, 0x09, 0x0e, 0x13,
+- 0x18, 0x1d, 0x22, 0x27, 0x2c, 0x31, 0x36, 0x3b,
+- 0x40, 0x45, 0x4a, 0x4f, 0x54, 0x59, 0x5e, 0x63,
+- 0x68, 0x6d, 0x72, 0x77, 0x7c, 0x81, 0x86, 0x8b,
+- 0x90, 0x95, 0x9a, 0x9f, 0xa4, 0xa9, 0xae, 0xb3,
+- 0xb8, 0xbd, 0xc2, 0xc7, 0xcc, 0xd1, 0xd6, 0xdb,
+- 0xe0, 0xe5, 0xea, 0xef, 0xf4, 0xf9, 0xfe, 0x03,
+- 0x08, 0x0d, 0x12, 0x17, 0x1c, 0x21, 0x26, 0x2b,
+- 0x30, 0x35, 0x3a, 0x3f, 0x44, 0x49, 0x4e, 0x53,
+- 0x58, 0x5d, 0x62, 0x67, 0x6c, 0x71, 0x76, 0x7b,
+- 0x80, 0x85, 0x8a, 0x8f, 0x94, 0x99, 0x9e, 0xa3,
+- 0xa8, 0xad, 0xb2, 0xb7, 0xbc, 0xc1, 0xc6, 0xcb,
+- 0xd0, 0xd5, 0xda, 0xdf, 0xe4, 0xe9, 0xee, 0xf3,
+- 0xf8, 0xfd, 0x02, 0x07, 0x0c, 0x11, 0x16, 0x1b,
+- 0x20, 0x25, 0x2a, 0x2f, 0x34, 0x39, 0x3e, 0x43,
+- 0x48, 0x4d, 0x52, 0x57, 0x5c, 0x61, 0x66, 0x6b,
+- 0x70, 0x75, 0x7a, 0x7f, 0x84, 0x89, 0x8e, 0x93,
+- 0x98, 0x9d, 0xa2, 0xa7, 0xac, 0xb1, 0xb6, 0xbb,
+- 0xc0, 0xc5, 0xca, 0xcf, 0xd4, 0xd9, 0xde, 0xe3,
+- 0xe8, 0xed, 0xf2, 0xf7, 0xfc, 0x01, 0x06, 0x0b,
+- 0x10, 0x15, 0x1a, 0x1f, 0x24, 0x29, 0x2e, 0x33,
+- 0x38, 0x3d, 0x42, 0x47, 0x4c, 0x51, 0x56, 0x5b,
+- 0x60, 0x65, 0x6a, 0x6f, 0x74, 0x79, 0x7e, 0x83,
+- 0x88, 0x8d, 0x92, 0x97, 0x9c, 0xa1, 0xa6, 0xab,
+- 0xb0, 0xb5, 0xba, 0xbf, 0xc4, 0xc9, 0xce, 0xd3,
+- 0xd8, 0xdd, 0xe2, 0xe7, 0xec, 0xf1, 0xf6, 0xfb,
+- 0x00, 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31,
+- 0x38, 0x3f, 0x46, 0x4d, 0x54, 0x5b, 0x62, 0x69,
+- 0x70, 0x77, 0x7e, 0x85, 0x8c, 0x93, 0x9a, 0xa1,
+- 0xa8, 0xaf, 0xb6, 0xbd, 0xc4, 0xcb, 0xd2, 0xd9,
+- 0xe0, 0xe7, 0xee, 0xf5, 0xfc, 0x03, 0x0a, 0x11,
+- 0x18, 0x1f, 0x26, 0x2d, 0x34, 0x3b, 0x42, 0x49,
+- 0x50, 0x57, 0x5e, 0x65, 0x6c, 0x73, 0x7a, 0x81,
+- 0x88, 0x8f, 0x96, 0x9d, 0xa4, 0xab, 0xb2, 0xb9,
+- 0xc0, 0xc7, 0xce, 0xd5, 0xdc, 0xe3, 0xea, 0xf1,
+- 0xf8, 0xff, 0x06, 0x0d, 0x14, 0x1b, 0x22, 0x29,
+- 0x30, 0x37, 0x3e, 0x45, 0x4c, 0x53, 0x5a, 0x61,
+- 0x68, 0x6f, 0x76, 0x7d, 0x84, 0x8b, 0x92, 0x99,
+- 0xa0, 0xa7, 0xae, 0xb5, 0xbc, 0xc3, 0xca, 0xd1,
+- 0xd8, 0xdf, 0xe6, 0xed, 0xf4, 0xfb, 0x02, 0x09,
+- 0x10, 0x17, 0x1e, 0x25, 0x2c, 0x33, 0x3a, 0x41,
+- 0x48, 0x4f, 0x56, 0x5d, 0x64, 0x6b, 0x72, 0x79,
+- 0x80, 0x87, 0x8e, 0x95, 0x9c, 0xa3, 0xaa, 0xb1,
+- 0xb8, 0xbf, 0xc6, 0xcd, 0xd4, 0xdb, 0xe2, 0xe9,
+- 0xf0, 0xf7, 0xfe, 0x05, 0x0c, 0x13, 0x1a, 0x21,
+- 0x28, 0x2f, 0x36, 0x3d, 0x44, 0x4b, 0x52, 0x59,
+- 0x60, 0x67, 0x6e, 0x75, 0x7c, 0x83, 0x8a, 0x91,
+- 0x98, 0x9f, 0xa6, 0xad, 0xb4, 0xbb, 0xc2, 0xc9,
+- 0xd0, 0xd7, 0xde, 0xe5, 0xec, 0xf3, 0xfa, 0x01,
+- 0x08, 0x0f, 0x16, 0x1d, 0x24, 0x2b, 0x32, 0x39,
+- 0x40, 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71,
+- 0x78, 0x7f, 0x86, 0x8d, 0x94, 0x9b, 0xa2, 0xa9,
+- 0xb0, 0xb7, 0xbe, 0xc5, 0xcc, 0xd3, 0xda, 0xe1,
+- 0xe8, 0xef, 0xf6, 0xfd, 0x04, 0x0b, 0x12, 0x19,
+- 0x20, 0x27, 0x2e, 0x35, 0x3c, 0x43, 0x4a, 0x51,
+- 0x58, 0x5f, 0x66, 0x6d, 0x74, 0x7b, 0x82, 0x89,
+- 0x90, 0x97, 0x9e, 0xa5, 0xac, 0xb3, 0xba, 0xc1,
+- 0xc8, 0xcf, 0xd6, 0xdd, 0xe4, 0xeb, 0xf2, 0xf9,
+- 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
+- 0x48, 0x51, 0x5a, 0x63, 0x6c, 0x75, 0x7e, 0x87,
+- 0x90, 0x99, 0xa2, 0xab, 0xb4, 0xbd, 0xc6, 0xcf,
+- 0xd8, 0xe1, 0xea, 0xf3, 0xfc, 0x05, 0x0e, 0x17,
+- 0x20, 0x29, 0x32, 0x3b, 0x44, 0x4d, 0x56, 0x5f,
+- 0x68, 0x71, 0x7a, 0x83, 0x8c, 0x95, 0x9e, 0xa7,
+- 0xb0, 0xb9, 0xc2, 0xcb, 0xd4, 0xdd, 0xe6, 0xef,
+- 0xf8, 0x01, 0x0a, 0x13, 0x1c, 0x25, 0x2e, 0x37,
+- 0x40, 0x49, 0x52, 0x5b, 0x64, 0x6d, 0x76, 0x7f,
+- 0x88, 0x91, 0x9a, 0xa3, 0xac, 0xb5, 0xbe, 0xc7,
+- 0xd0, 0xd9, 0xe2, 0xeb, 0xf4, 0xfd, 0x06, 0x0f,
+- 0x18, 0x21, 0x2a, 0x33, 0x3c, 0x45, 0x4e, 0x57,
+- 0x60, 0x69, 0x72, 0x7b, 0x84, 0x8d, 0x96, 0x9f,
+- 0xa8, 0xb1, 0xba, 0xc3, 0xcc, 0xd5, 0xde, 0xe7,
+- 0xf0, 0xf9, 0x02, 0x0b, 0x14, 0x1d, 0x26, 0x2f,
+- 0x38, 0x41, 0x4a, 0x53, 0x5c, 0x65, 0x6e, 0x77,
+- 0x80, 0x89, 0x92, 0x9b, 0xa4, 0xad, 0xb6, 0xbf,
+- 0xc8, 0xd1, 0xda, 0xe3, 0xec, 0xf5, 0xfe, 0x07,
+- 0x10, 0x19, 0x22, 0x2b, 0x34, 0x3d, 0x46, 0x4f,
+- 0x58, 0x61, 0x6a, 0x73, 0x7c, 0x85, 0x8e, 0x97,
+- 0xa0, 0xa9, 0xb2, 0xbb, 0xc4, 0xcd, 0xd6, 0xdf,
+- 0xe8, 0xf1, 0xfa, 0x03, 0x0c, 0x15, 0x1e, 0x27,
+- 0x30, 0x39, 0x42, 0x4b, 0x54, 0x5d, 0x66, 0x6f,
+- 0x78, 0x81, 0x8a, 0x93, 0x9c, 0xa5, 0xae, 0xb7,
+- 0xc0, 0xc9, 0xd2, 0xdb, 0xe4, 0xed, 0xf6, 0xff,
+- 0x08, 0x11, 0x1a, 0x23, 0x2c, 0x35, 0x3e, 0x47,
+- 0x50, 0x59, 0x62, 0x6b, 0x74, 0x7d, 0x86, 0x8f,
+- 0x98, 0xa1, 0xaa, 0xb3, 0xbc, 0xc5, 0xce, 0xd7,
+- 0xe0, 0xe9, 0xf2, 0xfb, 0x04, 0x0d, 0x16, 0x1f,
+- 0x28, 0x31, 0x3a, 0x43, 0x4c, 0x55, 0x5e, 0x67,
+- 0x70, 0x79, 0x82, 0x8b, 0x94, 0x9d, 0xa6, 0xaf,
+- 0xb8, 0xc1, 0xca, 0xd3, 0xdc, 0xe5, 0xee, 0xf7,
+- 0x00, 0x0b, 0x16, 0x21, 0x2c, 0x37, 0x42, 0x4d,
+- 0x58, 0x63, 0x6e, 0x79, 0x84, 0x8f, 0x9a, 0xa5,
+- 0xb0, 0xbb, 0xc6, 0xd1, 0xdc, 0xe7, 0xf2, 0xfd,
+- 0x08, 0x13, 0x1e, 0x29, 0x34, 0x3f, 0x4a, 0x55,
+- 0x60, 0x6b, 0x76, 0x81, 0x8c, 0x97, 0xa2, 0xad,
+- 0xb8, 0xc3, 0xce, 0xd9, 0xe4, 0xef, 0xfa, 0x05,
+- 0x10, 0x1b, 0x26, 0x31, 0x3c, 0x47, 0x52, 0x5d,
+- 0x68, 0x73, 0x7e, 0x89, 0x94, 0x9f, 0xaa, 0xb5,
+- 0xc0, 0xcb, 0xd6, 0xe1, 0xec, 0xf7, 0x02, 0x0d,
+- 0x18, 0x23, 0x2e, 0x39, 0x44, 0x4f, 0x5a, 0x65,
+- 0x70, 0x7b, 0x86, 0x91, 0x9c, 0xa7, 0xb2, 0xbd,
+- 0xc8, 0xd3, 0xde, 0xe9, 0xf4, 0xff, 0x0a, 0x15,
+- 0x20, 0x2b, 0x36, 0x41, 0x4c, 0x57, 0x62, 0x6d,
+- 0x78, 0x83, 0x8e, 0x99, 0xa4, 0xaf, 0xba, 0xc5,
+- 0xd0, 0xdb, 0xe6, 0xf1, 0xfc, 0x07, 0x12, 0x1d,
+- 0x28, 0x33, 0x3e, 0x49, 0x54, 0x5f, 0x6a, 0x75,
+- 0x80, 0x8b, 0x96, 0xa1, 0xac, 0xb7, 0xc2, 0xcd,
+- 0xd8, 0xe3, 0xee, 0xf9, 0x04, 0x0f, 0x1a, 0x25,
+- 0x30, 0x3b, 0x46, 0x51, 0x5c, 0x67, 0x72, 0x7d,
+- 0x88, 0x93, 0x9e, 0xa9, 0xb4, 0xbf, 0xca, 0xd5,
+- 0xe0, 0xeb, 0xf6, 0x01, 0x0c, 0x17, 0x22, 0x2d,
+- 0x38, 0x43, 0x4e, 0x59, 0x64, 0x6f, 0x7a, 0x85,
+- 0x90, 0x9b, 0xa6, 0xb1, 0xbc, 0xc7, 0xd2, 0xdd,
+- 0xe8, 0xf3, 0xfe, 0x09, 0x14, 0x1f, 0x2a, 0x35,
+- 0x40, 0x4b, 0x56, 0x61, 0x6c, 0x77, 0x82, 0x8d,
+- 0x98, 0xa3, 0xae, 0xb9, 0xc4, 0xcf, 0xda, 0xe5,
+- 0xf0, 0xfb, 0x06, 0x11, 0x1c, 0x27, 0x32, 0x3d,
+- 0x48, 0x53, 0x5e, 0x69, 0x74, 0x7f, 0x8a, 0x95,
+- 0xa0, 0xab, 0xb6, 0xc1, 0xcc, 0xd7, 0xe2, 0xed,
+- 0xf8, 0x03, 0x0e, 0x19, 0x24, 0x2f, 0x3a, 0x45,
+- 0x50, 0x5b, 0x66, 0x71, 0x7c, 0x87, 0x92, 0x9d,
+- 0xa8, 0xb3, 0xbe, 0xc9, 0xd4, 0xdf, 0xea, 0xf5,
+- 0x00, 0x0d, 0x1a, 0x27, 0x34, 0x41, 0x4e, 0x5b,
+- 0x68, 0x75, 0x82, 0x8f, 0x9c, 0xa9, 0xb6, 0xc3,
+- 0xd0, 0xdd, 0xea, 0xf7, 0x04, 0x11, 0x1e, 0x2b,
+- 0x38, 0x45, 0x52, 0x5f, 0x6c, 0x79, 0x86, 0x93,
+- 0xa0, 0xad, 0xba, 0xc7, 0xd4, 0xe1, 0xee, 0xfb,
+- 0x08, 0x15, 0x22, 0x2f, 0x3c, 0x49, 0x56, 0x63,
+- 0x70, 0x7d, 0x8a, 0x97, 0xa4, 0xb1, 0xbe, 0xcb,
+- 0xd8, 0xe5, 0xf2, 0xff, 0x0c, 0x19, 0x26, 0x33,
+- 0x40, 0x4d, 0x5a, 0x67, 0x74, 0x81, 0x8e, 0x9b,
+- 0xa8, 0xb5, 0xc2, 0xcf, 0xdc, 0xe9, 0xf6, 0x03,
+- 0x10, 0x1d, 0x2a, 0x37, 0x44, 0x51, 0x5e, 0x6b,
+- 0x78, 0x85, 0x92, 0x9f, 0xac, 0xb9, 0xc6, 0xd3,
+- 0xe0, 0xed, 0xfa, 0x07, 0x14, 0x21, 0x2e, 0x3b,
+- 0x48, 0x55, 0x62, 0x6f, 0x7c, 0x89, 0x96, 0xa3,
+- 0xb0, 0xbd, 0xca, 0xd7, 0xe4, 0xf1, 0xfe, 0x0b,
+- 0x18, 0x25, 0x32, 0x3f, 0x4c, 0x59, 0x66, 0x73,
+- 0x80, 0x8d, 0x9a, 0xa7, 0xb4, 0xc1, 0xce, 0xdb,
+- 0xe8, 0xf5, 0x02, 0x0f, 0x1c, 0x29, 0x36, 0x43,
+- 0x50, 0x5d, 0x6a, 0x77, 0x84, 0x91, 0x9e, 0xab,
+- 0xb8, 0xc5, 0xd2, 0xdf, 0xec, 0xf9, 0x06, 0x13,
+- 0x20, 0x2d, 0x3a, 0x47, 0x54, 0x61, 0x6e, 0x7b,
+- 0x88, 0x95, 0xa2, 0xaf, 0xbc, 0xc9, 0xd6, 0xe3,
+- 0xf0, 0xfd, 0x0a, 0x17, 0x24, 0x31, 0x3e, 0x4b,
+- 0x58, 0x65, 0x72, 0x7f, 0x8c, 0x99, 0xa6, 0xb3,
+- 0xc0, 0xcd, 0xda, 0xe7, 0xf4, 0x01, 0x0e, 0x1b,
+- 0x28, 0x35, 0x42, 0x4f, 0x5c, 0x69, 0x76, 0x83,
+- 0x90, 0x9d, 0xaa, 0xb7, 0xc4, 0xd1, 0xde, 0xeb,
+- 0xf8, 0x05, 0x12, 0x1f, 0x2c, 0x39, 0x46, 0x53,
+- 0x60, 0x6d, 0x7a, 0x87, 0x94, 0xa1, 0xae, 0xbb,
+- 0xc8, 0xd5, 0xe2, 0xef, 0xfc, 0x09, 0x16, 0x23,
+- 0x30, 0x3d, 0x4a, 0x57, 0x64, 0x71, 0x7e, 0x8b,
+- 0x98, 0xa5, 0xb2, 0xbf, 0xcc, 0xd9, 0xe6, 0xf3,
+- 0x00, 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69,
+- 0x78, 0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1,
+- 0xf0, 0xff, 0x0e, 0x1d, 0x2c, 0x3b, 0x4a, 0x59,
+- 0x68, 0x77, 0x86, 0x95, 0xa4, 0xb3, 0xc2, 0xd1,
+- 0xe0, 0xef, 0xfe, 0x0d, 0x1c, 0x2b, 0x3a, 0x49,
+- 0x58, 0x67, 0x76, 0x85, 0x94, 0xa3, 0xb2, 0xc1,
+- 0xd0, 0xdf, 0xee, 0xfd, 0x0c, 0x1b, 0x2a, 0x39,
+- 0x48, 0x57, 0x66, 0x75, 0x84, 0x93, 0xa2, 0xb1,
+- 0xc0, 0xcf, 0xde, 0xed, 0xfc, 0x0b, 0x1a, 0x29,
+- 0x38, 0x47, 0x56, 0x65, 0x74, 0x83, 0x92, 0xa1,
+- 0xb0, 0xbf, 0xce, 0xdd, 0xec, 0xfb, 0x0a, 0x19,
+- 0x28, 0x37, 0x46, 0x55, 0x64, 0x73, 0x82, 0x91,
+- 0xa0, 0xaf, 0xbe, 0xcd, 0xdc, 0xeb, 0xfa, 0x09,
+- 0x18, 0x27, 0x36, 0x45, 0x54, 0x63, 0x72, 0x81,
+- 0x90, 0x9f, 0xae, 0xbd, 0xcc, 0xdb, 0xea, 0xf9,
+- 0x08, 0x17, 0x26, 0x35, 0x44, 0x53, 0x62, 0x71,
+- 0x80, 0x8f, 0x9e, 0xad, 0xbc, 0xcb, 0xda, 0xe9,
+- 0xf8, 0x07, 0x16, 0x25, 0x34, 0x43, 0x52, 0x61,
+- 0x70, 0x7f, 0x8e, 0x9d, 0xac, 0xbb, 0xca, 0xd9,
+- 0xe8, 0xf7, 0x06, 0x15, 0x24, 0x33, 0x42, 0x51,
+- 0x60, 0x6f, 0x7e, 0x8d, 0x9c, 0xab, 0xba, 0xc9,
+- 0xd8, 0xe7, 0xf6, 0x05, 0x14, 0x23, 0x32, 0x41,
+- 0x50, 0x5f, 0x6e, 0x7d, 0x8c, 0x9b, 0xaa, 0xb9,
+- 0xc8, 0xd7, 0xe6, 0xf5, 0x04, 0x13, 0x22, 0x31,
+- 0x40, 0x4f, 0x5e, 0x6d, 0x7c, 0x8b, 0x9a, 0xa9,
+- 0xb8, 0xc7, 0xd6, 0xe5, 0xf4, 0x03, 0x12, 0x21,
+- 0x30, 0x3f, 0x4e, 0x5d, 0x6c, 0x7b, 0x8a, 0x99,
+- 0xa8, 0xb7, 0xc6, 0xd5, 0xe4, 0xf3, 0x02, 0x11,
+- 0x20, 0x2f, 0x3e, 0x4d, 0x5c, 0x6b, 0x7a, 0x89,
+- 0x98, 0xa7, 0xb6, 0xc5, 0xd4, 0xe3, 0xf2, 0x01,
+- 0x10, 0x1f, 0x2e, 0x3d, 0x4c, 0x5b, 0x6a, 0x79,
+- 0x88, 0x97, 0xa6, 0xb5, 0xc4, 0xd3, 0xe2, 0xf1,
+- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+- 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+- 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87,
+- 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f,
+- 0x20, 0x31, 0x42, 0x53, 0x64, 0x75, 0x86, 0x97,
+- 0xa8, 0xb9, 0xca, 0xdb, 0xec, 0xfd, 0x0e, 0x1f,
+- 0x30, 0x41, 0x52, 0x63, 0x74, 0x85, 0x96, 0xa7,
+- 0xb8, 0xc9, 0xda, 0xeb, 0xfc, 0x0d, 0x1e, 0x2f,
+- 0x40, 0x51, 0x62, 0x73, 0x84, 0x95, 0xa6, 0xb7,
+- 0xc8, 0xd9, 0xea, 0xfb, 0x0c, 0x1d, 0x2e, 0x3f,
+- 0x50, 0x61, 0x72, 0x83, 0x94, 0xa5, 0xb6, 0xc7,
+- 0xd8, 0xe9, 0xfa, 0x0b, 0x1c, 0x2d, 0x3e, 0x4f,
+- 0x60, 0x71, 0x82, 0x93, 0xa4, 0xb5, 0xc6, 0xd7,
+- 0xe8, 0xf9, 0x0a, 0x1b, 0x2c, 0x3d, 0x4e, 0x5f,
+- 0x70, 0x81, 0x92, 0xa3, 0xb4, 0xc5, 0xd6, 0xe7,
+- 0xf8, 0x09, 0x1a, 0x2b, 0x3c, 0x4d, 0x5e, 0x6f,
+- 0x80, 0x91, 0xa2, 0xb3, 0xc4, 0xd5, 0xe6, 0xf7,
+- 0x08, 0x19, 0x2a, 0x3b, 0x4c, 0x5d, 0x6e, 0x7f,
+- 0x90, 0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf6, 0x07,
+- 0x18, 0x29, 0x3a, 0x4b, 0x5c, 0x6d, 0x7e, 0x8f,
+- 0xa0, 0xb1, 0xc2, 0xd3, 0xe4, 0xf5, 0x06, 0x17,
+- 0x28, 0x39, 0x4a, 0x5b, 0x6c, 0x7d, 0x8e, 0x9f,
+- 0xb0, 0xc1, 0xd2, 0xe3, 0xf4, 0x05, 0x16, 0x27,
+- 0x38, 0x49, 0x5a, 0x6b, 0x7c, 0x8d, 0x9e, 0xaf,
+- 0xc0, 0xd1, 0xe2, 0xf3, 0x04, 0x15, 0x26, 0x37,
+- 0x48, 0x59, 0x6a, 0x7b, 0x8c, 0x9d, 0xae, 0xbf,
+- 0xd0, 0xe1, 0xf2, 0x03, 0x14, 0x25, 0x36, 0x47,
+- 0x58, 0x69, 0x7a, 0x8b, 0x9c, 0xad, 0xbe, 0xcf,
+- 0xe0, 0xf1, 0x02, 0x13, 0x24, 0x35, 0x46, 0x57,
+- 0x68, 0x79, 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf,
+- 0xf0, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67,
+- 0x78, 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef,
+- 0x00, 0x13, 0x26, 0x39, 0x4c, 0x5f, 0x72, 0x85,
+- 0x98, 0xab, 0xbe, 0xd1, 0xe4, 0xf7, 0x0a, 0x1d,
+- 0x30, 0x43, 0x56, 0x69, 0x7c, 0x8f, 0xa2, 0xb5,
+- 0xc8, 0xdb, 0xee, 0x01, 0x14, 0x27, 0x3a, 0x4d,
+- 0x60, 0x73, 0x86, 0x99, 0xac, 0xbf, 0xd2, 0xe5,
+- 0xf8, 0x0b, 0x1e, 0x31, 0x44, 0x57, 0x6a, 0x7d,
+- 0x90, 0xa3, 0xb6, 0xc9, 0xdc, 0xef, 0x02, 0x15,
+- 0x28, 0x3b, 0x4e, 0x61, 0x74, 0x87, 0x9a, 0xad,
+- 0xc0, 0xd3, 0xe6, 0xf9, 0x0c, 0x1f, 0x32, 0x45,
+- 0x58, 0x6b, 0x7e, 0x91, 0xa4, 0xb7, 0xca, 0xdd,
+- 0xf0, 0x03, 0x16, 0x29, 0x3c, 0x4f, 0x62, 0x75,
+- 0x88, 0x9b, 0xae, 0xc1, 0xd4, 0xe7, 0xfa, 0x0d,
+- 0x20, 0x33, 0x46, 0x59, 0x6c, 0x7f, 0x92, 0xa5,
+- 0xb8, 0xcb, 0xde, 0xf1, 0x04, 0x17, 0x2a, 0x3d,
+- 0x50, 0x63, 0x76, 0x89, 0x9c, 0xaf, 0xc2, 0xd5,
+- 0xe8, 0xfb, 0x0e, 0x21, 0x34, 0x47, 0x5a, 0x6d,
+- 0x80, 0x93, 0xa6, 0xb9, 0xcc, 0xdf, 0xf2, 0x05,
+- 0x18, 0x2b, 0x3e, 0x51, 0x64, 0x77, 0x8a, 0x9d,
+- 0xb0, 0xc3, 0xd6, 0xe9, 0xfc, 0x0f, 0x22, 0x35,
+- 0x48, 0x5b, 0x6e, 0x81, 0x94, 0xa7, 0xba, 0xcd,
+- 0xe0, 0xf3, 0x06, 0x19, 0x2c, 0x3f, 0x52, 0x65,
+- 0x78, 0x8b, 0x9e, 0xb1, 0xc4, 0xd7, 0xea, 0xfd,
+- 0x10, 0x23, 0x36, 0x49, 0x5c, 0x6f, 0x82, 0x95,
+- 0xa8, 0xbb, 0xce, 0xe1, 0xf4, 0x07, 0x1a, 0x2d,
+- 0x40, 0x53, 0x66, 0x79, 0x8c, 0x9f, 0xb2, 0xc5,
+- 0xd8, 0xeb, 0xfe, 0x11, 0x24, 0x37, 0x4a, 0x5d,
+- 0x70, 0x83, 0x96, 0xa9, 0xbc, 0xcf, 0xe2, 0xf5,
+- 0x08, 0x1b, 0x2e, 0x41, 0x54, 0x67, 0x7a, 0x8d,
+- 0xa0, 0xb3, 0xc6, 0xd9, 0xec, 0xff, 0x12, 0x25,
+- 0x38, 0x4b, 0x5e, 0x71, 0x84, 0x97, 0xaa, 0xbd,
+- 0xd0, 0xe3, 0xf6, 0x09, 0x1c, 0x2f, 0x42, 0x55,
+- 0x68, 0x7b, 0x8e, 0xa1, 0xb4, 0xc7, 0xda, 0xed,
+- 0x00, 0x15, 0x2a, 0x3f, 0x54, 0x69, 0x7e, 0x93,
+- 0xa8, 0xbd, 0xd2, 0xe7, 0xfc, 0x11, 0x26, 0x3b,
+- 0x50, 0x65, 0x7a, 0x8f, 0xa4, 0xb9, 0xce, 0xe3,
+- 0xf8, 0x0d, 0x22, 0x37, 0x4c, 0x61, 0x76, 0x8b,
+- 0xa0, 0xb5, 0xca, 0xdf, 0xf4, 0x09, 0x1e, 0x33,
+- 0x48, 0x5d, 0x72, 0x87, 0x9c, 0xb1, 0xc6, 0xdb,
+- 0xf0, 0x05, 0x1a, 0x2f, 0x44, 0x59, 0x6e, 0x83,
+- 0x98, 0xad, 0xc2, 0xd7, 0xec, 0x01, 0x16, 0x2b,
+- 0x40, 0x55, 0x6a, 0x7f, 0x94, 0xa9, 0xbe, 0xd3,
+- 0xe8, 0xfd, 0x12, 0x27, 0x3c, 0x51, 0x66, 0x7b,
+- 0x90, 0xa5, 0xba, 0xcf, 0xe4, 0xf9, 0x0e, 0x23,
+- 0x38, 0x4d, 0x62, 0x77, 0x8c, 0xa1, 0xb6, 0xcb,
+- 0xe0, 0xf5, 0x0a, 0x1f, 0x34, 0x49, 0x5e, 0x73,
+- 0x88, 0x9d, 0xb2, 0xc7, 0xdc, 0xf1, 0x06, 0x1b,
+- 0x30, 0x45, 0x5a, 0x6f, 0x84, 0x99, 0xae, 0xc3,
+- 0xd8, 0xed, 0x02, 0x17, 0x2c, 0x41, 0x56, 0x6b,
+- 0x80, 0x95, 0xaa, 0xbf, 0xd4, 0xe9, 0xfe, 0x13,
+- 0x28, 0x3d, 0x52, 0x67, 0x7c, 0x91, 0xa6, 0xbb,
+- 0xd0, 0xe5, 0xfa, 0x0f, 0x24, 0x39, 0x4e, 0x63,
+- 0x78, 0x8d, 0xa2, 0xb7, 0xcc, 0xe1, 0xf6, 0x0b,
+- 0x20, 0x35, 0x4a, 0x5f, 0x74, 0x89, 0x9e, 0xb3,
+- 0xc8, 0xdd, 0xf2, 0x07, 0x1c, 0x31, 0x46, 0x5b,
+- 0x70, 0x85, 0x9a, 0xaf, 0xc4, 0xd9, 0xee, 0x03,
+- 0x18, 0x2d, 0x42, 0x57, 0x6c, 0x81, 0x96, 0xab,
+- 0xc0, 0xd5, 0xea, 0xff, 0x14, 0x29, 0x3e, 0x53,
+- 0x68, 0x7d, 0x92, 0xa7, 0xbc, 0xd1, 0xe6, 0xfb,
+- 0x10, 0x25, 0x3a, 0x4f, 0x64, 0x79, 0x8e, 0xa3,
+- 0xb8, 0xcd, 0xe2, 0xf7, 0x0c, 0x21, 0x36, 0x4b,
+- 0x60, 0x75, 0x8a, 0x9f, 0xb4, 0xc9, 0xde, 0xf3,
+- 0x08, 0x1d, 0x32, 0x47, 0x5c, 0x71, 0x86, 0x9b,
+- 0xb0, 0xc5, 0xda, 0xef, 0x04, 0x19, 0x2e, 0x43,
+- 0x58, 0x6d, 0x82, 0x97, 0xac, 0xc1, 0xd6, 0xeb,
+- 0x00, 0x17, 0x2e, 0x45, 0x5c, 0x73, 0x8a, 0xa1,
+- 0xb8, 0xcf, 0xe6, 0xfd, 0x14, 0x2b, 0x42, 0x59,
+- 0x70, 0x87, 0x9e, 0xb5, 0xcc, 0xe3, 0xfa, 0x11,
+- 0x28, 0x3f, 0x56, 0x6d, 0x84, 0x9b, 0xb2, 0xc9,
+- 0xe0, 0xf7, 0x0e, 0x25, 0x3c, 0x53, 0x6a, 0x81,
+- 0x98, 0xaf, 0xc6, 0xdd, 0xf4, 0x0b, 0x22, 0x39,
+- 0x50, 0x67, 0x7e, 0x95, 0xac, 0xc3, 0xda, 0xf1,
+- 0x08, 0x1f, 0x36, 0x4d, 0x64, 0x7b, 0x92, 0xa9,
+- 0xc0, 0xd7, 0xee, 0x05, 0x1c, 0x33, 0x4a, 0x61,
+- 0x78, 0x8f, 0xa6, 0xbd, 0xd4, 0xeb, 0x02, 0x19,
+- 0x30, 0x47, 0x5e, 0x75, 0x8c, 0xa3, 0xba, 0xd1,
+- 0xe8, 0xff, 0x16, 0x2d, 0x44, 0x5b, 0x72, 0x89,
+- 0xa0, 0xb7, 0xce, 0xe5, 0xfc, 0x13, 0x2a, 0x41,
+- 0x58, 0x6f, 0x86, 0x9d, 0xb4, 0xcb, 0xe2, 0xf9,
+- 0x10, 0x27, 0x3e, 0x55, 0x6c, 0x83, 0x9a, 0xb1,
+- 0xc8, 0xdf, 0xf6, 0x0d, 0x24, 0x3b, 0x52, 0x69,
+- 0x80, 0x97, 0xae, 0xc5, 0xdc, 0xf3, 0x0a, 0x21,
+- 0x38, 0x4f, 0x66, 0x7d, 0x94, 0xab, 0xc2, 0xd9,
+- 0xf0, 0x07, 0x1e, 0x35, 0x4c, 0x63, 0x7a, 0x91,
+- 0xa8, 0xbf, 0xd6, 0xed, 0x04, 0x1b, 0x32, 0x49,
+- 0x60, 0x77, 0x8e, 0xa5, 0xbc, 0xd3, 0xea, 0x01,
+- 0x18, 0x2f, 0x46, 0x5d, 0x74, 0x8b, 0xa2, 0xb9,
+- 0xd0, 0xe7, 0xfe, 0x15, 0x2c, 0x43, 0x5a, 0x71,
+- 0x88, 0x9f, 0xb6, 0xcd, 0xe4, 0xfb, 0x12, 0x29,
+- 0x40, 0x57, 0x6e, 0x85, 0x9c, 0xb3, 0xca, 0xe1,
+- 0xf8, 0x0f, 0x26, 0x3d, 0x54, 0x6b, 0x82, 0x99,
+- 0xb0, 0xc7, 0xde, 0xf5, 0x0c, 0x23, 0x3a, 0x51,
+- 0x68, 0x7f, 0x96, 0xad, 0xc4, 0xdb, 0xf2, 0x09,
+- 0x20, 0x37, 0x4e, 0x65, 0x7c, 0x93, 0xaa, 0xc1,
+- 0xd8, 0xef, 0x06, 0x1d, 0x34, 0x4b, 0x62, 0x79,
+- 0x90, 0xa7, 0xbe, 0xd5, 0xec, 0x03, 0x1a, 0x31,
+- 0x48, 0x5f, 0x76, 0x8d, 0xa4, 0xbb, 0xd2, 0xe9,
+- 0x00, 0x19, 0x32, 0x4b, 0x64, 0x7d, 0x96, 0xaf,
+- 0xc8, 0xe1, 0xfa, 0x13, 0x2c, 0x45, 0x5e, 0x77,
+- 0x90, 0xa9, 0xc2, 0xdb, 0xf4, 0x0d, 0x26, 0x3f,
+- 0x58, 0x71, 0x8a, 0xa3, 0xbc, 0xd5, 0xee, 0x07,
+- 0x20, 0x39, 0x52, 0x6b, 0x84, 0x9d, 0xb6, 0xcf,
+- 0xe8, 0x01, 0x1a, 0x33, 0x4c, 0x65, 0x7e, 0x97,
+- 0xb0, 0xc9, 0xe2, 0xfb, 0x14, 0x2d, 0x46, 0x5f,
+- 0x78, 0x91, 0xaa, 0xc3, 0xdc, 0xf5, 0x0e, 0x27,
+- 0x40, 0x59, 0x72, 0x8b, 0xa4, 0xbd, 0xd6, 0xef,
+- 0x08, 0x21, 0x3a, 0x53, 0x6c, 0x85, 0x9e, 0xb7,
+- 0xd0, 0xe9, 0x02, 0x1b, 0x34, 0x4d, 0x66, 0x7f,
+- 0x98, 0xb1, 0xca, 0xe3, 0xfc, 0x15, 0x2e, 0x47,
+- 0x60, 0x79, 0x92, 0xab, 0xc4, 0xdd, 0xf6, 0x0f,
+- 0x28, 0x41, 0x5a, 0x73, 0x8c, 0xa5, 0xbe, 0xd7,
+- 0xf0, 0x09, 0x22, 0x3b, 0x54, 0x6d, 0x86, 0x9f,
+- 0xb8, 0xd1, 0xea, 0x03, 0x1c, 0x35, 0x4e, 0x67,
+- 0x80, 0x99, 0xb2, 0xcb, 0xe4, 0xfd, 0x16, 0x2f,
+- 0x48, 0x61, 0x7a, 0x93, 0xac, 0xc5, 0xde, 0xf7,
+- 0x10, 0x29, 0x42, 0x5b, 0x74, 0x8d, 0xa6, 0xbf,
+- 0xd8, 0xf1, 0x0a, 0x23, 0x3c, 0x55, 0x6e, 0x87,
+- 0xa0, 0xb9, 0xd2, 0xeb, 0x04, 0x1d, 0x36, 0x4f,
+- 0x68, 0x81, 0x9a, 0xb3, 0xcc, 0xe5, 0xfe, 0x17,
+- 0x30, 0x49, 0x62, 0x7b, 0x94, 0xad, 0xc6, 0xdf,
+- 0xf8, 0x11, 0x2a, 0x43, 0x5c, 0x75, 0x8e, 0xa7,
+- 0xc0, 0xd9, 0xf2, 0x0b, 0x24, 0x3d, 0x56, 0x6f,
+- 0x88, 0xa1, 0xba, 0xd3, 0xec, 0x05, 0x1e, 0x37,
+- 0x50, 0x69, 0x82, 0x9b, 0xb4, 0xcd, 0xe6, 0xff,
+- 0x18, 0x31, 0x4a, 0x63, 0x7c, 0x95, 0xae, 0xc7,
+- 0xe0, 0xf9, 0x12, 0x2b, 0x44, 0x5d, 0x76, 0x8f,
+- 0xa8, 0xc1, 0xda, 0xf3, 0x0c, 0x25, 0x3e, 0x57,
+- 0x70, 0x89, 0xa2, 0xbb, 0xd4, 0xed, 0x06, 0x1f,
+- 0x38, 0x51, 0x6a, 0x83, 0x9c, 0xb5, 0xce, 0xe7,
+- 0x00, 0x1b, 0x36, 0x51, 0x6c, 0x87, 0xa2, 0xbd,
+- 0xd8, 0xf3, 0x0e, 0x29, 0x44, 0x5f, 0x7a, 0x95,
+- 0xb0, 0xcb, 0xe6, 0x01, 0x1c, 0x37, 0x52, 0x6d,
+- 0x88, 0xa3, 0xbe, 0xd9, 0xf4, 0x0f, 0x2a, 0x45,
+- 0x60, 0x7b, 0x96, 0xb1, 0xcc, 0xe7, 0x02, 0x1d,
+- 0x38, 0x53, 0x6e, 0x89, 0xa4, 0xbf, 0xda, 0xf5,
+- 0x10, 0x2b, 0x46, 0x61, 0x7c, 0x97, 0xb2, 0xcd,
+- 0xe8, 0x03, 0x1e, 0x39, 0x54, 0x6f, 0x8a, 0xa5,
+- 0xc0, 0xdb, 0xf6, 0x11, 0x2c, 0x47, 0x62, 0x7d,
+- 0x98, 0xb3, 0xce, 0xe9, 0x04, 0x1f, 0x3a, 0x55,
+- 0x70, 0x8b, 0xa6, 0xc1, 0xdc, 0xf7, 0x12, 0x2d,
+- 0x48, 0x63, 0x7e, 0x99, 0xb4, 0xcf, 0xea, 0x05,
+- 0x20, 0x3b, 0x56, 0x71, 0x8c, 0xa7, 0xc2, 0xdd,
+- 0xf8, 0x13, 0x2e, 0x49, 0x64, 0x7f, 0x9a, 0xb5,
+- 0xd0, 0xeb, 0x06, 0x21, 0x3c, 0x57, 0x72, 0x8d,
+- 0xa8, 0xc3, 0xde, 0xf9, 0x14, 0x2f, 0x4a, 0x65,
+- 0x80, 0x9b, 0xb6, 0xd1, 0xec, 0x07, 0x22, 0x3d,
+- 0x58, 0x73, 0x8e, 0xa9, 0xc4, 0xdf, 0xfa, 0x15,
+- 0x30, 0x4b, 0x66, 0x81, 0x9c, 0xb7, 0xd2, 0xed,
+- 0x08, 0x23, 0x3e, 0x59, 0x74, 0x8f, 0xaa, 0xc5,
+- 0xe0, 0xfb, 0x16, 0x31, 0x4c, 0x67, 0x82, 0x9d,
+- 0xb8, 0xd3, 0xee, 0x09, 0x24, 0x3f, 0x5a, 0x75,
+- 0x90, 0xab, 0xc6, 0xe1, 0xfc, 0x17, 0x32, 0x4d,
+- 0x68, 0x83, 0x9e, 0xb9, 0xd4, 0xef, 0x0a, 0x25,
+- 0x40, 0x5b, 0x76, 0x91, 0xac, 0xc7, 0xe2, 0xfd,
+- 0x18, 0x33, 0x4e, 0x69, 0x84, 0x9f, 0xba, 0xd5,
+- 0xf0, 0x0b, 0x26, 0x41, 0x5c, 0x77, 0x92, 0xad,
+- 0xc8, 0xe3, 0xfe, 0x19, 0x34, 0x4f, 0x6a, 0x85,
+- 0xa0, 0xbb, 0xd6, 0xf1, 0x0c, 0x27, 0x42, 0x5d,
+- 0x78, 0x93, 0xae, 0xc9, 0xe4, 0xff, 0x1a, 0x35,
+- 0x50, 0x6b, 0x86, 0xa1, 0xbc, 0xd7, 0xf2, 0x0d,
+- 0x28, 0x43, 0x5e, 0x79, 0x94, 0xaf, 0xca, 0xe5,
+- 0x00, 0x1d, 0x3a, 0x57, 0x74, 0x91, 0xae, 0xcb,
+- 0xe8, 0x05, 0x22, 0x3f, 0x5c, 0x79, 0x96, 0xb3,
+- 0xd0, 0xed, 0x0a, 0x27, 0x44, 0x61, 0x7e, 0x9b,
+- 0xb8, 0xd5, 0xf2, 0x0f, 0x2c, 0x49, 0x66, 0x83,
+- 0xa0, 0xbd, 0xda, 0xf7, 0x14, 0x31, 0x4e, 0x6b,
+- 0x88, 0xa5, 0xc2, 0xdf, 0xfc, 0x19, 0x36, 0x53,
+- 0x70, 0x8d, 0xaa, 0xc7, 0xe4, 0x01, 0x1e, 0x3b,
+- 0x58, 0x75, 0x92, 0xaf, 0xcc, 0xe9, 0x06, 0x23,
+- 0x40, 0x5d, 0x7a, 0x97, 0xb4, 0xd1, 0xee, 0x0b,
+- 0x28, 0x45, 0x62, 0x7f, 0x9c, 0xb9, 0xd6, 0xf3,
+- 0x10, 0x2d, 0x4a, 0x67, 0x84, 0xa1, 0xbe, 0xdb,
+- 0xf8, 0x15, 0x32, 0x4f, 0x6c, 0x89, 0xa6, 0xc3,
+- 0xe0, 0xfd, 0x1a, 0x37, 0x54, 0x71, 0x8e, 0xab,
+- 0xc8, 0xe5, 0x02, 0x1f, 0x3c, 0x59, 0x76, 0x93,
+- 0xb0, 0xcd, 0xea, 0x07, 0x24, 0x41, 0x5e, 0x7b,
+- 0x98, 0xb5, 0xd2, 0xef, 0x0c, 0x29, 0x46, 0x63,
+- 0x80, 0x9d, 0xba, 0xd7, 0xf4, 0x11, 0x2e, 0x4b,
+- 0x68, 0x85, 0xa2, 0xbf, 0xdc, 0xf9, 0x16, 0x33,
+- 0x50, 0x6d, 0x8a, 0xa7, 0xc4, 0xe1, 0xfe, 0x1b,
+- 0x38, 0x55, 0x72, 0x8f, 0xac, 0xc9, 0xe6, 0x03,
+- 0x20, 0x3d, 0x5a, 0x77, 0x94, 0xb1, 0xce, 0xeb,
+- 0x08, 0x25, 0x42, 0x5f, 0x7c, 0x99, 0xb6, 0xd3,
+- 0xf0, 0x0d, 0x2a, 0x47, 0x64, 0x81, 0x9e, 0xbb,
+- 0xd8, 0xf5, 0x12, 0x2f, 0x4c, 0x69, 0x86, 0xa3,
+- 0xc0, 0xdd, 0xfa, 0x17, 0x34, 0x51, 0x6e, 0x8b,
+- 0xa8, 0xc5, 0xe2, 0xff, 0x1c, 0x39, 0x56, 0x73,
+- 0x90, 0xad, 0xca, 0xe7, 0x04, 0x21, 0x3e, 0x5b,
+- 0x78, 0x95, 0xb2, 0xcf, 0xec, 0x09, 0x26, 0x43,
+- 0x60, 0x7d, 0x9a, 0xb7, 0xd4, 0xf1, 0x0e, 0x2b,
+- 0x48, 0x65, 0x82, 0x9f, 0xbc, 0xd9, 0xf6, 0x13,
+- 0x30, 0x4d, 0x6a, 0x87, 0xa4, 0xc1, 0xde, 0xfb,
+- 0x18, 0x35, 0x52, 0x6f, 0x8c, 0xa9, 0xc6, 0xe3,
+- 0x00, 0x1f, 0x3e, 0x5d, 0x7c, 0x9b, 0xba, 0xd9,
+- 0xf8, 0x17, 0x36, 0x55, 0x74, 0x93, 0xb2, 0xd1,
+- 0xf0, 0x0f, 0x2e, 0x4d, 0x6c, 0x8b, 0xaa, 0xc9,
+- 0xe8, 0x07, 0x26, 0x45, 0x64, 0x83, 0xa2, 0xc1,
+- 0xe0, 0xff, 0x1e, 0x3d, 0x5c, 0x7b, 0x9a, 0xb9,
+- 0xd8, 0xf7, 0x16, 0x35, 0x54, 0x73, 0x92, 0xb1,
+- 0xd0, 0xef, 0x0e, 0x2d, 0x4c, 0x6b, 0x8a, 0xa9,
+- 0xc8, 0xe7, 0x06, 0x25, 0x44, 0x63, 0x82, 0xa1,
+- 0xc0, 0xdf, 0xfe, 0x1d, 0x3c, 0x5b, 0x7a, 0x99,
+- 0xb8, 0xd7, 0xf6, 0x15, 0x34, 0x53, 0x72, 0x91,
+- 0xb0, 0xcf, 0xee, 0x0d, 0x2c, 0x4b, 0x6a, 0x89,
+- 0xa8, 0xc7, 0xe6, 0x05, 0x24, 0x43, 0x62, 0x81,
+- 0xa0, 0xbf, 0xde, 0xfd, 0x1c, 0x3b, 0x5a, 0x79,
+- 0x98, 0xb7, 0xd6, 0xf5, 0x14, 0x33, 0x52, 0x71,
+- 0x90, 0xaf, 0xce, 0xed, 0x0c, 0x2b, 0x4a, 0x69,
+- 0x88, 0xa7, 0xc6, 0xe5, 0x04, 0x23, 0x42, 0x61,
+- 0x80, 0x9f, 0xbe, 0xdd, 0xfc, 0x1b, 0x3a, 0x59,
+- 0x78, 0x97, 0xb6, 0xd5, 0xf4, 0x13, 0x32, 0x51,
+- 0x70, 0x8f, 0xae, 0xcd, 0xec, 0x0b, 0x2a, 0x49,
+- 0x68, 0x87, 0xa6, 0xc5, 0xe4, 0x03, 0x22, 0x41,
+- 0x60, 0x7f, 0x9e, 0xbd, 0xdc, 0xfb, 0x1a, 0x39,
+- 0x58, 0x77, 0x96, 0xb5, 0xd4, 0xf3, 0x12, 0x31,
+- 0x50, 0x6f, 0x8e, 0xad, 0xcc, 0xeb, 0x0a, 0x29,
+- 0x48, 0x67, 0x86, 0xa5, 0xc4, 0xe3, 0x02, 0x21,
+- 0x40, 0x5f, 0x7e, 0x9d, 0xbc, 0xdb, 0xfa, 0x19,
+- 0x38, 0x57, 0x76, 0x95, 0xb4, 0xd3, 0xf2, 0x11,
+- 0x30, 0x4f, 0x6e, 0x8d, 0xac, 0xcb, 0xea, 0x09,
+- 0x28, 0x47, 0x66, 0x85, 0xa4, 0xc3, 0xe2, 0x01,
+- 0x20, 0x3f, 0x5e, 0x7d, 0x9c, 0xbb, 0xda, 0xf9,
+- 0x18, 0x37, 0x56, 0x75, 0x94, 0xb3, 0xd2, 0xf1,
+- 0x10, 0x2f, 0x4e, 0x6d, 0x8c, 0xab, 0xca, 0xe9,
+- 0x08, 0x27, 0x46, 0x65, 0x84, 0xa3, 0xc2, 0xe1,
+- 0x00, 0x21, 0x42, 0x63,
+- },
++ .iv = "\x00\x00\x00\x00\x00\x00\x00\x00"
++ "\x00\x00\x00\x00\x00\x00\x00\x00",
++ .input =
++ "\x00\x01\x02\x03\x04\x05\x06\x07"
++ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
++ "\x10\x11\x12\x13\x14\x15\x16\x17"
++ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
++ "\x20\x21\x22\x23\x24\x25\x26\x27"
++ "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
++ "\x30\x31\x32\x33\x34\x35\x36\x37"
++ "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
++ "\x40\x41\x42\x43\x44\x45\x46\x47"
++ "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
++ "\x50\x51\x52\x53\x54\x55\x56\x57"
++ "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
++ "\x60\x61\x62\x63\x64\x65\x66\x67"
++ "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
++ "\x70\x71\x72\x73\x74\x75\x76\x77"
++ "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
++ "\x80\x81\x82\x83\x84\x85\x86\x87"
++ "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
++ "\x90\x91\x92\x93\x94\x95\x96\x97"
++ "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
++ "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
++ "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
++ "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
++ "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
++ "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
++ "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
++ "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
++ "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
++ "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
++ "\xe8\xe9\xea\xeb\xec\xed\xee\xef"
++ "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
++ "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
++ "\x00\x03\x06\x09\x0c\x0f\x12\x15"
++ "\x18\x1b\x1e\x21\x24\x27\x2a\x2d"
++ "\x30\x33\x36\x39\x3c\x3f\x42\x45"
++ "\x48\x4b\x4e\x51\x54\x57\x5a\x5d"
++ "\x60\x63\x66\x69\x6c\x6f\x72\x75"
++ "\x78\x7b\x7e\x81\x84\x87\x8a\x8d"
++ "\x90\x93\x96\x99\x9c\x9f\xa2\xa5"
++ "\xa8\xab\xae\xb1\xb4\xb7\xba\xbd"
++ "\xc0\xc3\xc6\xc9\xcc\xcf\xd2\xd5"
++ "\xd8\xdb\xde\xe1\xe4\xe7\xea\xed"
++ "\xf0\xf3\xf6\xf9\xfc\xff\x02\x05"
++ "\x08\x0b\x0e\x11\x14\x17\x1a\x1d"
++ "\x20\x23\x26\x29\x2c\x2f\x32\x35"
++ "\x38\x3b\x3e\x41\x44\x47\x4a\x4d"
++ "\x50\x53\x56\x59\x5c\x5f\x62\x65"
++ "\x68\x6b\x6e\x71\x74\x77\x7a\x7d"
++ "\x80\x83\x86\x89\x8c\x8f\x92\x95"
++ "\x98\x9b\x9e\xa1\xa4\xa7\xaa\xad"
++ "\xb0\xb3\xb6\xb9\xbc\xbf\xc2\xc5"
++ "\xc8\xcb\xce\xd1\xd4\xd7\xda\xdd"
++ "\xe0\xe3\xe6\xe9\xec\xef\xf2\xf5"
++ "\xf8\xfb\xfe\x01\x04\x07\x0a\x0d"
++ "\x10\x13\x16\x19\x1c\x1f\x22\x25"
++ "\x28\x2b\x2e\x31\x34\x37\x3a\x3d"
++ "\x40\x43\x46\x49\x4c\x4f\x52\x55"
++ "\x58\x5b\x5e\x61\x64\x67\x6a\x6d"
++ "\x70\x73\x76\x79\x7c\x7f\x82\x85"
++ "\x88\x8b\x8e\x91\x94\x97\x9a\x9d"
++ "\xa0\xa3\xa6\xa9\xac\xaf\xb2\xb5"
++ "\xb8\xbb\xbe\xc1\xc4\xc7\xca\xcd"
++ "\xd0\xd3\xd6\xd9\xdc\xdf\xe2\xe5"
++ "\xe8\xeb\xee\xf1\xf4\xf7\xfa\xfd"
++ "\x00\x05\x0a\x0f\x14\x19\x1e\x23"
++ "\x28\x2d\x32\x37\x3c\x41\x46\x4b"
++ "\x50\x55\x5a\x5f\x64\x69\x6e\x73"
++ "\x78\x7d\x82\x87\x8c\x91\x96\x9b"
++ "\xa0\xa5\xaa\xaf\xb4\xb9\xbe\xc3"
++ "\xc8\xcd\xd2\xd7\xdc\xe1\xe6\xeb"
++ "\xf0\xf5\xfa\xff\x04\x09\x0e\x13"
++ "\x18\x1d\x22\x27\x2c\x31\x36\x3b"
++ "\x40\x45\x4a\x4f\x54\x59\x5e\x63"
++ "\x68\x6d\x72\x77\x7c\x81\x86\x8b"
++ "\x90\x95\x9a\x9f\xa4\xa9\xae\xb3"
++ "\xb8\xbd\xc2\xc7\xcc\xd1\xd6\xdb"
++ "\xe0\xe5\xea\xef\xf4\xf9\xfe\x03"
++ "\x08\x0d\x12\x17\x1c\x21\x26\x2b"
++ "\x30\x35\x3a\x3f\x44\x49\x4e\x53"
++ "\x58\x5d\x62\x67\x6c\x71\x76\x7b"
++ "\x80\x85\x8a\x8f\x94\x99\x9e\xa3"
++ "\xa8\xad\xb2\xb7\xbc\xc1\xc6\xcb"
++ "\xd0\xd5\xda\xdf\xe4\xe9\xee\xf3"
++ "\xf8\xfd\x02\x07\x0c\x11\x16\x1b"
++ "\x20\x25\x2a\x2f\x34\x39\x3e\x43"
++ "\x48\x4d\x52\x57\x5c\x61\x66\x6b"
++ "\x70\x75\x7a\x7f\x84\x89\x8e\x93"
++ "\x98\x9d\xa2\xa7\xac\xb1\xb6\xbb"
++ "\xc0\xc5\xca\xcf\xd4\xd9\xde\xe3"
++ "\xe8\xed\xf2\xf7\xfc\x01\x06\x0b"
++ "\x10\x15\x1a\x1f\x24\x29\x2e\x33"
++ "\x38\x3d\x42\x47\x4c\x51\x56\x5b"
++ "\x60\x65\x6a\x6f\x74\x79\x7e\x83"
++ "\x88\x8d\x92\x97\x9c\xa1\xa6\xab"
++ "\xb0\xb5\xba\xbf\xc4\xc9\xce\xd3"
++ "\xd8\xdd\xe2\xe7\xec\xf1\xf6\xfb"
++ "\x00\x07\x0e\x15\x1c\x23\x2a\x31"
++ "\x38\x3f\x46\x4d\x54\x5b\x62\x69"
++ "\x70\x77\x7e\x85\x8c\x93\x9a\xa1"
++ "\xa8\xaf\xb6\xbd\xc4\xcb\xd2\xd9"
++ "\xe0\xe7\xee\xf5\xfc\x03\x0a\x11"
++ "\x18\x1f\x26\x2d\x34\x3b\x42\x49"
++ "\x50\x57\x5e\x65\x6c\x73\x7a\x81"
++ "\x88\x8f\x96\x9d\xa4\xab\xb2\xb9"
++ "\xc0\xc7\xce\xd5\xdc\xe3\xea\xf1"
++ "\xf8\xff\x06\x0d\x14\x1b\x22\x29"
++ "\x30\x37\x3e\x45\x4c\x53\x5a\x61"
++ "\x68\x6f\x76\x7d\x84\x8b\x92\x99"
++ "\xa0\xa7\xae\xb5\xbc\xc3\xca\xd1"
++ "\xd8\xdf\xe6\xed\xf4\xfb\x02\x09"
++ "\x10\x17\x1e\x25\x2c\x33\x3a\x41"
++ "\x48\x4f\x56\x5d\x64\x6b\x72\x79"
++ "\x80\x87\x8e\x95\x9c\xa3\xaa\xb1"
++ "\xb8\xbf\xc6\xcd\xd4\xdb\xe2\xe9"
++ "\xf0\xf7\xfe\x05\x0c\x13\x1a\x21"
++ "\x28\x2f\x36\x3d\x44\x4b\x52\x59"
++ "\x60\x67\x6e\x75\x7c\x83\x8a\x91"
++ "\x98\x9f\xa6\xad\xb4\xbb\xc2\xc9"
++ "\xd0\xd7\xde\xe5\xec\xf3\xfa\x01"
++ "\x08\x0f\x16\x1d\x24\x2b\x32\x39"
++ "\x40\x47\x4e\x55\x5c\x63\x6a\x71"
++ "\x78\x7f\x86\x8d\x94\x9b\xa2\xa9"
++ "\xb0\xb7\xbe\xc5\xcc\xd3\xda\xe1"
++ "\xe8\xef\xf6\xfd\x04\x0b\x12\x19"
++ "\x20\x27\x2e\x35\x3c\x43\x4a\x51"
++ "\x58\x5f\x66\x6d\x74\x7b\x82\x89"
++ "\x90\x97\x9e\xa5\xac\xb3\xba\xc1"
++ "\xc8\xcf\xd6\xdd\xe4\xeb\xf2\xf9"
++ "\x00\x09\x12\x1b\x24\x2d\x36\x3f"
++ "\x48\x51\x5a\x63\x6c\x75\x7e\x87"
++ "\x90\x99\xa2\xab\xb4\xbd\xc6\xcf"
++ "\xd8\xe1\xea\xf3\xfc\x05\x0e\x17"
++ "\x20\x29\x32\x3b\x44\x4d\x56\x5f"
++ "\x68\x71\x7a\x83\x8c\x95\x9e\xa7"
++ "\xb0\xb9\xc2\xcb\xd4\xdd\xe6\xef"
++ "\xf8\x01\x0a\x13\x1c\x25\x2e\x37"
++ "\x40\x49\x52\x5b\x64\x6d\x76\x7f"
++ "\x88\x91\x9a\xa3\xac\xb5\xbe\xc7"
++ "\xd0\xd9\xe2\xeb\xf4\xfd\x06\x0f"
++ "\x18\x21\x2a\x33\x3c\x45\x4e\x57"
++ "\x60\x69\x72\x7b\x84\x8d\x96\x9f"
++ "\xa8\xb1\xba\xc3\xcc\xd5\xde\xe7"
++ "\xf0\xf9\x02\x0b\x14\x1d\x26\x2f"
++ "\x38\x41\x4a\x53\x5c\x65\x6e\x77"
++ "\x80\x89\x92\x9b\xa4\xad\xb6\xbf"
++ "\xc8\xd1\xda\xe3\xec\xf5\xfe\x07"
++ "\x10\x19\x22\x2b\x34\x3d\x46\x4f"
++ "\x58\x61\x6a\x73\x7c\x85\x8e\x97"
++ "\xa0\xa9\xb2\xbb\xc4\xcd\xd6\xdf"
++ "\xe8\xf1\xfa\x03\x0c\x15\x1e\x27"
++ "\x30\x39\x42\x4b\x54\x5d\x66\x6f"
++ "\x78\x81\x8a\x93\x9c\xa5\xae\xb7"
++ "\xc0\xc9\xd2\xdb\xe4\xed\xf6\xff"
++ "\x08\x11\x1a\x23\x2c\x35\x3e\x47"
++ "\x50\x59\x62\x6b\x74\x7d\x86\x8f"
++ "\x98\xa1\xaa\xb3\xbc\xc5\xce\xd7"
++ "\xe0\xe9\xf2\xfb\x04\x0d\x16\x1f"
++ "\x28\x31\x3a\x43\x4c\x55\x5e\x67"
++ "\x70\x79\x82\x8b\x94\x9d\xa6\xaf"
++ "\xb8\xc1\xca\xd3\xdc\xe5\xee\xf7"
++ "\x00\x0b\x16\x21\x2c\x37\x42\x4d"
++ "\x58\x63\x6e\x79\x84\x8f\x9a\xa5"
++ "\xb0\xbb\xc6\xd1\xdc\xe7\xf2\xfd"
++ "\x08\x13\x1e\x29\x34\x3f\x4a\x55"
++ "\x60\x6b\x76\x81\x8c\x97\xa2\xad"
++ "\xb8\xc3\xce\xd9\xe4\xef\xfa\x05"
++ "\x10\x1b\x26\x31\x3c\x47\x52\x5d"
++ "\x68\x73\x7e\x89\x94\x9f\xaa\xb5"
++ "\xc0\xcb\xd6\xe1\xec\xf7\x02\x0d"
++ "\x18\x23\x2e\x39\x44\x4f\x5a\x65"
++ "\x70\x7b\x86\x91\x9c\xa7\xb2\xbd"
++ "\xc8\xd3\xde\xe9\xf4\xff\x0a\x15"
++ "\x20\x2b\x36\x41\x4c\x57\x62\x6d"
++ "\x78\x83\x8e\x99\xa4\xaf\xba\xc5"
++ "\xd0\xdb\xe6\xf1\xfc\x07\x12\x1d"
++ "\x28\x33\x3e\x49\x54\x5f\x6a\x75"
++ "\x80\x8b\x96\xa1\xac\xb7\xc2\xcd"
++ "\xd8\xe3\xee\xf9\x04\x0f\x1a\x25"
++ "\x30\x3b\x46\x51\x5c\x67\x72\x7d"
++ "\x88\x93\x9e\xa9\xb4\xbf\xca\xd5"
++ "\xe0\xeb\xf6\x01\x0c\x17\x22\x2d"
++ "\x38\x43\x4e\x59\x64\x6f\x7a\x85"
++ "\x90\x9b\xa6\xb1\xbc\xc7\xd2\xdd"
++ "\xe8\xf3\xfe\x09\x14\x1f\x2a\x35"
++ "\x40\x4b\x56\x61\x6c\x77\x82\x8d"
++ "\x98\xa3\xae\xb9\xc4\xcf\xda\xe5"
++ "\xf0\xfb\x06\x11\x1c\x27\x32\x3d"
++ "\x48\x53\x5e\x69\x74\x7f\x8a\x95"
++ "\xa0\xab\xb6\xc1\xcc\xd7\xe2\xed"
++ "\xf8\x03\x0e\x19\x24\x2f\x3a\x45"
++ "\x50\x5b\x66\x71\x7c\x87\x92\x9d"
++ "\xa8\xb3\xbe\xc9\xd4\xdf\xea\xf5"
++ "\x00\x0d\x1a\x27\x34\x41\x4e\x5b"
++ "\x68\x75\x82\x8f\x9c\xa9\xb6\xc3"
++ "\xd0\xdd\xea\xf7\x04\x11\x1e\x2b"
++ "\x38\x45\x52\x5f\x6c\x79\x86\x93"
++ "\xa0\xad\xba\xc7\xd4\xe1\xee\xfb"
++ "\x08\x15\x22\x2f\x3c\x49\x56\x63"
++ "\x70\x7d\x8a\x97\xa4\xb1\xbe\xcb"
++ "\xd8\xe5\xf2\xff\x0c\x19\x26\x33"
++ "\x40\x4d\x5a\x67\x74\x81\x8e\x9b"
++ "\xa8\xb5\xc2\xcf\xdc\xe9\xf6\x03"
++ "\x10\x1d\x2a\x37\x44\x51\x5e\x6b"
++ "\x78\x85\x92\x9f\xac\xb9\xc6\xd3"
++ "\xe0\xed\xfa\x07\x14\x21\x2e\x3b"
++ "\x48\x55\x62\x6f\x7c\x89\x96\xa3"
++ "\xb0\xbd\xca\xd7\xe4\xf1\xfe\x0b"
++ "\x18\x25\x32\x3f\x4c\x59\x66\x73"
++ "\x80\x8d\x9a\xa7\xb4\xc1\xce\xdb"
++ "\xe8\xf5\x02\x0f\x1c\x29\x36\x43"
++ "\x50\x5d\x6a\x77\x84\x91\x9e\xab"
++ "\xb8\xc5\xd2\xdf\xec\xf9\x06\x13"
++ "\x20\x2d\x3a\x47\x54\x61\x6e\x7b"
++ "\x88\x95\xa2\xaf\xbc\xc9\xd6\xe3"
++ "\xf0\xfd\x0a\x17\x24\x31\x3e\x4b"
++ "\x58\x65\x72\x7f\x8c\x99\xa6\xb3"
++ "\xc0\xcd\xda\xe7\xf4\x01\x0e\x1b"
++ "\x28\x35\x42\x4f\x5c\x69\x76\x83"
++ "\x90\x9d\xaa\xb7\xc4\xd1\xde\xeb"
++ "\xf8\x05\x12\x1f\x2c\x39\x46\x53"
++ "\x60\x6d\x7a\x87\x94\xa1\xae\xbb"
++ "\xc8\xd5\xe2\xef\xfc\x09\x16\x23"
++ "\x30\x3d\x4a\x57\x64\x71\x7e\x8b"
++ "\x98\xa5\xb2\xbf\xcc\xd9\xe6\xf3"
++ "\x00\x0f\x1e\x2d\x3c\x4b\x5a\x69"
++ "\x78\x87\x96\xa5\xb4\xc3\xd2\xe1"
++ "\xf0\xff\x0e\x1d\x2c\x3b\x4a\x59"
++ "\x68\x77\x86\x95\xa4\xb3\xc2\xd1"
++ "\xe0\xef\xfe\x0d\x1c\x2b\x3a\x49"
++ "\x58\x67\x76\x85\x94\xa3\xb2\xc1"
++ "\xd0\xdf\xee\xfd\x0c\x1b\x2a\x39"
++ "\x48\x57\x66\x75\x84\x93\xa2\xb1"
++ "\xc0\xcf\xde\xed\xfc\x0b\x1a\x29"
++ "\x38\x47\x56\x65\x74\x83\x92\xa1"
++ "\xb0\xbf\xce\xdd\xec\xfb\x0a\x19"
++ "\x28\x37\x46\x55\x64\x73\x82\x91"
++ "\xa0\xaf\xbe\xcd\xdc\xeb\xfa\x09"
++ "\x18\x27\x36\x45\x54\x63\x72\x81"
++ "\x90\x9f\xae\xbd\xcc\xdb\xea\xf9"
++ "\x08\x17\x26\x35\x44\x53\x62\x71"
++ "\x80\x8f\x9e\xad\xbc\xcb\xda\xe9"
++ "\xf8\x07\x16\x25\x34\x43\x52\x61"
++ "\x70\x7f\x8e\x9d\xac\xbb\xca\xd9"
++ "\xe8\xf7\x06\x15\x24\x33\x42\x51"
++ "\x60\x6f\x7e\x8d\x9c\xab\xba\xc9"
++ "\xd8\xe7\xf6\x05\x14\x23\x32\x41"
++ "\x50\x5f\x6e\x7d\x8c\x9b\xaa\xb9"
++ "\xc8\xd7\xe6\xf5\x04\x13\x22\x31"
++ "\x40\x4f\x5e\x6d\x7c\x8b\x9a\xa9"
++ "\xb8\xc7\xd6\xe5\xf4\x03\x12\x21"
++ "\x30\x3f\x4e\x5d\x6c\x7b\x8a\x99"
++ "\xa8\xb7\xc6\xd5\xe4\xf3\x02\x11"
++ "\x20\x2f\x3e\x4d\x5c\x6b\x7a\x89"
++ "\x98\xa7\xb6\xc5\xd4\xe3\xf2\x01"
++ "\x10\x1f\x2e\x3d\x4c\x5b\x6a\x79"
++ "\x88\x97\xa6\xb5\xc4\xd3\xe2\xf1"
++ "\x00\x11\x22\x33\x44\x55\x66\x77"
++ "\x88\x99\xaa\xbb\xcc\xdd\xee\xff"
++ "\x10\x21\x32\x43\x54\x65\x76\x87"
++ "\x98\xa9\xba\xcb\xdc\xed\xfe\x0f"
++ "\x20\x31\x42\x53\x64\x75\x86\x97"
++ "\xa8\xb9\xca\xdb\xec\xfd\x0e\x1f"
++ "\x30\x41\x52\x63\x74\x85\x96\xa7"
++ "\xb8\xc9\xda\xeb\xfc\x0d\x1e\x2f"
++ "\x40\x51\x62\x73\x84\x95\xa6\xb7"
++ "\xc8\xd9\xea\xfb\x0c\x1d\x2e\x3f"
++ "\x50\x61\x72\x83\x94\xa5\xb6\xc7"
++ "\xd8\xe9\xfa\x0b\x1c\x2d\x3e\x4f"
++ "\x60\x71\x82\x93\xa4\xb5\xc6\xd7"
++ "\xe8\xf9\x0a\x1b\x2c\x3d\x4e\x5f"
++ "\x70\x81\x92\xa3\xb4\xc5\xd6\xe7"
++ "\xf8\x09\x1a\x2b\x3c\x4d\x5e\x6f"
++ "\x80\x91\xa2\xb3\xc4\xd5\xe6\xf7"
++ "\x08\x19\x2a\x3b\x4c\x5d\x6e\x7f"
++ "\x90\xa1\xb2\xc3\xd4\xe5\xf6\x07"
++ "\x18\x29\x3a\x4b\x5c\x6d\x7e\x8f"
++ "\xa0\xb1\xc2\xd3\xe4\xf5\x06\x17"
++ "\x28\x39\x4a\x5b\x6c\x7d\x8e\x9f"
++ "\xb0\xc1\xd2\xe3\xf4\x05\x16\x27"
++ "\x38\x49\x5a\x6b\x7c\x8d\x9e\xaf"
++ "\xc0\xd1\xe2\xf3\x04\x15\x26\x37"
++ "\x48\x59\x6a\x7b\x8c\x9d\xae\xbf"
++ "\xd0\xe1\xf2\x03\x14\x25\x36\x47"
++ "\x58\x69\x7a\x8b\x9c\xad\xbe\xcf"
++ "\xe0\xf1\x02\x13\x24\x35\x46\x57"
++ "\x68\x79\x8a\x9b\xac\xbd\xce\xdf"
++ "\xf0\x01\x12\x23\x34\x45\x56\x67"
++ "\x78\x89\x9a\xab\xbc\xcd\xde\xef"
++ "\x00\x13\x26\x39\x4c\x5f\x72\x85"
++ "\x98\xab\xbe\xd1\xe4\xf7\x0a\x1d"
++ "\x30\x43\x56\x69\x7c\x8f\xa2\xb5"
++ "\xc8\xdb\xee\x01\x14\x27\x3a\x4d"
++ "\x60\x73\x86\x99\xac\xbf\xd2\xe5"
++ "\xf8\x0b\x1e\x31\x44\x57\x6a\x7d"
++ "\x90\xa3\xb6\xc9\xdc\xef\x02\x15"
++ "\x28\x3b\x4e\x61\x74\x87\x9a\xad"
++ "\xc0\xd3\xe6\xf9\x0c\x1f\x32\x45"
++ "\x58\x6b\x7e\x91\xa4\xb7\xca\xdd"
++ "\xf0\x03\x16\x29\x3c\x4f\x62\x75"
++ "\x88\x9b\xae\xc1\xd4\xe7\xfa\x0d"
++ "\x20\x33\x46\x59\x6c\x7f\x92\xa5"
++ "\xb8\xcb\xde\xf1\x04\x17\x2a\x3d"
++ "\x50\x63\x76\x89\x9c\xaf\xc2\xd5"
++ "\xe8\xfb\x0e\x21\x34\x47\x5a\x6d"
++ "\x80\x93\xa6\xb9\xcc\xdf\xf2\x05"
++ "\x18\x2b\x3e\x51\x64\x77\x8a\x9d"
++ "\xb0\xc3\xd6\xe9\xfc\x0f\x22\x35"
++ "\x48\x5b\x6e\x81\x94\xa7\xba\xcd"
++ "\xe0\xf3\x06\x19\x2c\x3f\x52\x65"
++ "\x78\x8b\x9e\xb1\xc4\xd7\xea\xfd"
++ "\x10\x23\x36\x49\x5c\x6f\x82\x95"
++ "\xa8\xbb\xce\xe1\xf4\x07\x1a\x2d"
++ "\x40\x53\x66\x79\x8c\x9f\xb2\xc5"
++ "\xd8\xeb\xfe\x11\x24\x37\x4a\x5d"
++ "\x70\x83\x96\xa9\xbc\xcf\xe2\xf5"
++ "\x08\x1b\x2e\x41\x54\x67\x7a\x8d"
++ "\xa0\xb3\xc6\xd9\xec\xff\x12\x25"
++ "\x38\x4b\x5e\x71\x84\x97\xaa\xbd"
++ "\xd0\xe3\xf6\x09\x1c\x2f\x42\x55"
++ "\x68\x7b\x8e\xa1\xb4\xc7\xda\xed"
++ "\x00\x15\x2a\x3f\x54\x69\x7e\x93"
++ "\xa8\xbd\xd2\xe7\xfc\x11\x26\x3b"
++ "\x50\x65\x7a\x8f\xa4\xb9\xce\xe3"
++ "\xf8\x0d\x22\x37\x4c\x61\x76\x8b"
++ "\xa0\xb5\xca\xdf\xf4\x09\x1e\x33"
++ "\x48\x5d\x72\x87\x9c\xb1\xc6\xdb"
++ "\xf0\x05\x1a\x2f\x44\x59\x6e\x83"
++ "\x98\xad\xc2\xd7\xec\x01\x16\x2b"
++ "\x40\x55\x6a\x7f\x94\xa9\xbe\xd3"
++ "\xe8\xfd\x12\x27\x3c\x51\x66\x7b"
++ "\x90\xa5\xba\xcf\xe4\xf9\x0e\x23"
++ "\x38\x4d\x62\x77\x8c\xa1\xb6\xcb"
++ "\xe0\xf5\x0a\x1f\x34\x49\x5e\x73"
++ "\x88\x9d\xb2\xc7\xdc\xf1\x06\x1b"
++ "\x30\x45\x5a\x6f\x84\x99\xae\xc3"
++ "\xd8\xed\x02\x17\x2c\x41\x56\x6b"
++ "\x80\x95\xaa\xbf\xd4\xe9\xfe\x13"
++ "\x28\x3d\x52\x67\x7c\x91\xa6\xbb"
++ "\xd0\xe5\xfa\x0f\x24\x39\x4e\x63"
++ "\x78\x8d\xa2\xb7\xcc\xe1\xf6\x0b"
++ "\x20\x35\x4a\x5f\x74\x89\x9e\xb3"
++ "\xc8\xdd\xf2\x07\x1c\x31\x46\x5b"
++ "\x70\x85\x9a\xaf\xc4\xd9\xee\x03"
++ "\x18\x2d\x42\x57\x6c\x81\x96\xab"
++ "\xc0\xd5\xea\xff\x14\x29\x3e\x53"
++ "\x68\x7d\x92\xa7\xbc\xd1\xe6\xfb"
++ "\x10\x25\x3a\x4f\x64\x79\x8e\xa3"
++ "\xb8\xcd\xe2\xf7\x0c\x21\x36\x4b"
++ "\x60\x75\x8a\x9f\xb4\xc9\xde\xf3"
++ "\x08\x1d\x32\x47\x5c\x71\x86\x9b"
++ "\xb0\xc5\xda\xef\x04\x19\x2e\x43"
++ "\x58\x6d\x82\x97\xac\xc1\xd6\xeb"
++ "\x00\x17\x2e\x45\x5c\x73\x8a\xa1"
++ "\xb8\xcf\xe6\xfd\x14\x2b\x42\x59"
++ "\x70\x87\x9e\xb5\xcc\xe3\xfa\x11"
++ "\x28\x3f\x56\x6d\x84\x9b\xb2\xc9"
++ "\xe0\xf7\x0e\x25\x3c\x53\x6a\x81"
++ "\x98\xaf\xc6\xdd\xf4\x0b\x22\x39"
++ "\x50\x67\x7e\x95\xac\xc3\xda\xf1"
++ "\x08\x1f\x36\x4d\x64\x7b\x92\xa9"
++ "\xc0\xd7\xee\x05\x1c\x33\x4a\x61"
++ "\x78\x8f\xa6\xbd\xd4\xeb\x02\x19"
++ "\x30\x47\x5e\x75\x8c\xa3\xba\xd1"
++ "\xe8\xff\x16\x2d\x44\x5b\x72\x89"
++ "\xa0\xb7\xce\xe5\xfc\x13\x2a\x41"
++ "\x58\x6f\x86\x9d\xb4\xcb\xe2\xf9"
++ "\x10\x27\x3e\x55\x6c\x83\x9a\xb1"
++ "\xc8\xdf\xf6\x0d\x24\x3b\x52\x69"
++ "\x80\x97\xae\xc5\xdc\xf3\x0a\x21"
++ "\x38\x4f\x66\x7d\x94\xab\xc2\xd9"
++ "\xf0\x07\x1e\x35\x4c\x63\x7a\x91"
++ "\xa8\xbf\xd6\xed\x04\x1b\x32\x49"
++ "\x60\x77\x8e\xa5\xbc\xd3\xea\x01"
++ "\x18\x2f\x46\x5d\x74\x8b\xa2\xb9"
++ "\xd0\xe7\xfe\x15\x2c\x43\x5a\x71"
++ "\x88\x9f\xb6\xcd\xe4\xfb\x12\x29"
++ "\x40\x57\x6e\x85\x9c\xb3\xca\xe1"
++ "\xf8\x0f\x26\x3d\x54\x6b\x82\x99"
++ "\xb0\xc7\xde\xf5\x0c\x23\x3a\x51"
++ "\x68\x7f\x96\xad\xc4\xdb\xf2\x09"
++ "\x20\x37\x4e\x65\x7c\x93\xaa\xc1"
++ "\xd8\xef\x06\x1d\x34\x4b\x62\x79"
++ "\x90\xa7\xbe\xd5\xec\x03\x1a\x31"
++ "\x48\x5f\x76\x8d\xa4\xbb\xd2\xe9"
++ "\x00\x19\x32\x4b\x64\x7d\x96\xaf"
++ "\xc8\xe1\xfa\x13\x2c\x45\x5e\x77"
++ "\x90\xa9\xc2\xdb\xf4\x0d\x26\x3f"
++ "\x58\x71\x8a\xa3\xbc\xd5\xee\x07"
++ "\x20\x39\x52\x6b\x84\x9d\xb6\xcf"
++ "\xe8\x01\x1a\x33\x4c\x65\x7e\x97"
++ "\xb0\xc9\xe2\xfb\x14\x2d\x46\x5f"
++ "\x78\x91\xaa\xc3\xdc\xf5\x0e\x27"
++ "\x40\x59\x72\x8b\xa4\xbd\xd6\xef"
++ "\x08\x21\x3a\x53\x6c\x85\x9e\xb7"
++ "\xd0\xe9\x02\x1b\x34\x4d\x66\x7f"
++ "\x98\xb1\xca\xe3\xfc\x15\x2e\x47"
++ "\x60\x79\x92\xab\xc4\xdd\xf6\x0f"
++ "\x28\x41\x5a\x73\x8c\xa5\xbe\xd7"
++ "\xf0\x09\x22\x3b\x54\x6d\x86\x9f"
++ "\xb8\xd1\xea\x03\x1c\x35\x4e\x67"
++ "\x80\x99\xb2\xcb\xe4\xfd\x16\x2f"
++ "\x48\x61\x7a\x93\xac\xc5\xde\xf7"
++ "\x10\x29\x42\x5b\x74\x8d\xa6\xbf"
++ "\xd8\xf1\x0a\x23\x3c\x55\x6e\x87"
++ "\xa0\xb9\xd2\xeb\x04\x1d\x36\x4f"
++ "\x68\x81\x9a\xb3\xcc\xe5\xfe\x17"
++ "\x30\x49\x62\x7b\x94\xad\xc6\xdf"
++ "\xf8\x11\x2a\x43\x5c\x75\x8e\xa7"
++ "\xc0\xd9\xf2\x0b\x24\x3d\x56\x6f"
++ "\x88\xa1\xba\xd3\xec\x05\x1e\x37"
++ "\x50\x69\x82\x9b\xb4\xcd\xe6\xff"
++ "\x18\x31\x4a\x63\x7c\x95\xae\xc7"
++ "\xe0\xf9\x12\x2b\x44\x5d\x76\x8f"
++ "\xa8\xc1\xda\xf3\x0c\x25\x3e\x57"
++ "\x70\x89\xa2\xbb\xd4\xed\x06\x1f"
++ "\x38\x51\x6a\x83\x9c\xb5\xce\xe7"
++ "\x00\x1b\x36\x51\x6c\x87\xa2\xbd"
++ "\xd8\xf3\x0e\x29\x44\x5f\x7a\x95"
++ "\xb0\xcb\xe6\x01\x1c\x37\x52\x6d"
++ "\x88\xa3\xbe\xd9\xf4\x0f\x2a\x45"
++ "\x60\x7b\x96\xb1\xcc\xe7\x02\x1d"
++ "\x38\x53\x6e\x89\xa4\xbf\xda\xf5"
++ "\x10\x2b\x46\x61\x7c\x97\xb2\xcd"
++ "\xe8\x03\x1e\x39\x54\x6f\x8a\xa5"
++ "\xc0\xdb\xf6\x11\x2c\x47\x62\x7d"
++ "\x98\xb3\xce\xe9\x04\x1f\x3a\x55"
++ "\x70\x8b\xa6\xc1\xdc\xf7\x12\x2d"
++ "\x48\x63\x7e\x99\xb4\xcf\xea\x05"
++ "\x20\x3b\x56\x71\x8c\xa7\xc2\xdd"
++ "\xf8\x13\x2e\x49\x64\x7f\x9a\xb5"
++ "\xd0\xeb\x06\x21\x3c\x57\x72\x8d"
++ "\xa8\xc3\xde\xf9\x14\x2f\x4a\x65"
++ "\x80\x9b\xb6\xd1\xec\x07\x22\x3d"
++ "\x58\x73\x8e\xa9\xc4\xdf\xfa\x15"
++ "\x30\x4b\x66\x81\x9c\xb7\xd2\xed"
++ "\x08\x23\x3e\x59\x74\x8f\xaa\xc5"
++ "\xe0\xfb\x16\x31\x4c\x67\x82\x9d"
++ "\xb8\xd3\xee\x09\x24\x3f\x5a\x75"
++ "\x90\xab\xc6\xe1\xfc\x17\x32\x4d"
++ "\x68\x83\x9e\xb9\xd4\xef\x0a\x25"
++ "\x40\x5b\x76\x91\xac\xc7\xe2\xfd"
++ "\x18\x33\x4e\x69\x84\x9f\xba\xd5"
++ "\xf0\x0b\x26\x41\x5c\x77\x92\xad"
++ "\xc8\xe3\xfe\x19\x34\x4f\x6a\x85"
++ "\xa0\xbb\xd6\xf1\x0c\x27\x42\x5d"
++ "\x78\x93\xae\xc9\xe4\xff\x1a\x35"
++ "\x50\x6b\x86\xa1\xbc\xd7\xf2\x0d"
++ "\x28\x43\x5e\x79\x94\xaf\xca\xe5"
++ "\x00\x1d\x3a\x57\x74\x91\xae\xcb"
++ "\xe8\x05\x22\x3f\x5c\x79\x96\xb3"
++ "\xd0\xed\x0a\x27\x44\x61\x7e\x9b"
++ "\xb8\xd5\xf2\x0f\x2c\x49\x66\x83"
++ "\xa0\xbd\xda\xf7\x14\x31\x4e\x6b"
++ "\x88\xa5\xc2\xdf\xfc\x19\x36\x53"
++ "\x70\x8d\xaa\xc7\xe4\x01\x1e\x3b"
++ "\x58\x75\x92\xaf\xcc\xe9\x06\x23"
++ "\x40\x5d\x7a\x97\xb4\xd1\xee\x0b"
++ "\x28\x45\x62\x7f\x9c\xb9\xd6\xf3"
++ "\x10\x2d\x4a\x67\x84\xa1\xbe\xdb"
++ "\xf8\x15\x32\x4f\x6c\x89\xa6\xc3"
++ "\xe0\xfd\x1a\x37\x54\x71\x8e\xab"
++ "\xc8\xe5\x02\x1f\x3c\x59\x76\x93"
++ "\xb0\xcd\xea\x07\x24\x41\x5e\x7b"
++ "\x98\xb5\xd2\xef\x0c\x29\x46\x63"
++ "\x80\x9d\xba\xd7\xf4\x11\x2e\x4b"
++ "\x68\x85\xa2\xbf\xdc\xf9\x16\x33"
++ "\x50\x6d\x8a\xa7\xc4\xe1\xfe\x1b"
++ "\x38\x55\x72\x8f\xac\xc9\xe6\x03"
++ "\x20\x3d\x5a\x77\x94\xb1\xce\xeb"
++ "\x08\x25\x42\x5f\x7c\x99\xb6\xd3"
++ "\xf0\x0d\x2a\x47\x64\x81\x9e\xbb"
++ "\xd8\xf5\x12\x2f\x4c\x69\x86\xa3"
++ "\xc0\xdd\xfa\x17\x34\x51\x6e\x8b"
++ "\xa8\xc5\xe2\xff\x1c\x39\x56\x73"
++ "\x90\xad\xca\xe7\x04\x21\x3e\x5b"
++ "\x78\x95\xb2\xcf\xec\x09\x26\x43"
++ "\x60\x7d\x9a\xb7\xd4\xf1\x0e\x2b"
++ "\x48\x65\x82\x9f\xbc\xd9\xf6\x13"
++ "\x30\x4d\x6a\x87\xa4\xc1\xde\xfb"
++ "\x18\x35\x52\x6f\x8c\xa9\xc6\xe3"
++ "\x00\x1f\x3e\x5d\x7c\x9b\xba\xd9"
++ "\xf8\x17\x36\x55\x74\x93\xb2\xd1"
++ "\xf0\x0f\x2e\x4d\x6c\x8b\xaa\xc9"
++ "\xe8\x07\x26\x45\x64\x83\xa2\xc1"
++ "\xe0\xff\x1e\x3d\x5c\x7b\x9a\xb9"
++ "\xd8\xf7\x16\x35\x54\x73\x92\xb1"
++ "\xd0\xef\x0e\x2d\x4c\x6b\x8a\xa9"
++ "\xc8\xe7\x06\x25\x44\x63\x82\xa1"
++ "\xc0\xdf\xfe\x1d\x3c\x5b\x7a\x99"
++ "\xb8\xd7\xf6\x15\x34\x53\x72\x91"
++ "\xb0\xcf\xee\x0d\x2c\x4b\x6a\x89"
++ "\xa8\xc7\xe6\x05\x24\x43\x62\x81"
++ "\xa0\xbf\xde\xfd\x1c\x3b\x5a\x79"
++ "\x98\xb7\xd6\xf5\x14\x33\x52\x71"
++ "\x90\xaf\xce\xed\x0c\x2b\x4a\x69"
++ "\x88\xa7\xc6\xe5\x04\x23\x42\x61"
++ "\x80\x9f\xbe\xdd\xfc\x1b\x3a\x59"
++ "\x78\x97\xb6\xd5\xf4\x13\x32\x51"
++ "\x70\x8f\xae\xcd\xec\x0b\x2a\x49"
++ "\x68\x87\xa6\xc5\xe4\x03\x22\x41"
++ "\x60\x7f\x9e\xbd\xdc\xfb\x1a\x39"
++ "\x58\x77\x96\xb5\xd4\xf3\x12\x31"
++ "\x50\x6f\x8e\xad\xcc\xeb\x0a\x29"
++ "\x48\x67\x86\xa5\xc4\xe3\x02\x21"
++ "\x40\x5f\x7e\x9d\xbc\xdb\xfa\x19"
++ "\x38\x57\x76\x95\xb4\xd3\xf2\x11"
++ "\x30\x4f\x6e\x8d\xac\xcb\xea\x09"
++ "\x28\x47\x66\x85\xa4\xc3\xe2\x01"
++ "\x20\x3f\x5e\x7d\x9c\xbb\xda\xf9"
++ "\x18\x37\x56\x75\x94\xb3\xd2\xf1"
++ "\x10\x2f\x4e\x6d\x8c\xab\xca\xe9"
++ "\x08\x27\x46\x65\x84\xa3\xc2\xe1"
++ "\x00\x21\x42\x63",
+ .ilen = 4100,
+- .result = {
+- 0xb5, 0x81, 0xf5, 0x64, 0x18, 0x73, 0xe3, 0xf0,
+- 0x4c, 0x13, 0xf2, 0x77, 0x18, 0x60, 0x65, 0x5e,
+- 0x29, 0x01, 0xce, 0x98, 0x55, 0x53, 0xf9, 0x0c,
+- 0x2a, 0x08, 0xd5, 0x09, 0xb3, 0x57, 0x55, 0x56,
+- 0xc5, 0xe9, 0x56, 0x90, 0xcb, 0x6a, 0xa3, 0xc0,
+- 0xff, 0xc4, 0x79, 0xb4, 0xd2, 0x97, 0x5d, 0xc4,
+- 0x43, 0xd1, 0xfe, 0x94, 0x7b, 0x88, 0x06, 0x5a,
+- 0xb2, 0x9e, 0x2c, 0xfc, 0x44, 0x03, 0xb7, 0x90,
+- 0xa0, 0xc1, 0xba, 0x6a, 0x33, 0xb8, 0xc7, 0xb2,
+- 0x9d, 0xe1, 0x12, 0x4f, 0xc0, 0x64, 0xd4, 0x01,
+- 0xfe, 0x8c, 0x7a, 0x66, 0xf7, 0xe6, 0x5a, 0x91,
+- 0xbb, 0xde, 0x56, 0x86, 0xab, 0x65, 0x21, 0x30,
+- 0x00, 0x84, 0x65, 0x24, 0xa5, 0x7d, 0x85, 0xb4,
+- 0xe3, 0x17, 0xed, 0x3a, 0xb7, 0x6f, 0xb4, 0x0b,
+- 0x0b, 0xaf, 0x15, 0xae, 0x5a, 0x8f, 0xf2, 0x0c,
+- 0x2f, 0x27, 0xf4, 0x09, 0xd8, 0xd2, 0x96, 0xb7,
+- 0x71, 0xf2, 0xc5, 0x99, 0x4d, 0x7e, 0x7f, 0x75,
+- 0x77, 0x89, 0x30, 0x8b, 0x59, 0xdb, 0xa2, 0xb2,
+- 0xa0, 0xf3, 0x19, 0x39, 0x2b, 0xc5, 0x7e, 0x3f,
+- 0x4f, 0xd9, 0xd3, 0x56, 0x28, 0x97, 0x44, 0xdc,
+- 0xc0, 0x8b, 0x77, 0x24, 0xd9, 0x52, 0xe7, 0xc5,
+- 0xaf, 0xf6, 0x7d, 0x59, 0xb2, 0x44, 0x05, 0x1d,
+- 0xb1, 0xb0, 0x11, 0xa5, 0x0f, 0xec, 0x33, 0xe1,
+- 0x6d, 0x1b, 0x4e, 0x1f, 0xff, 0x57, 0x91, 0xb4,
+- 0x5b, 0x9a, 0x96, 0xc5, 0x53, 0xbc, 0xae, 0x20,
+- 0x3c, 0xbb, 0x14, 0xe2, 0xe8, 0x22, 0x33, 0xc1,
+- 0x5e, 0x76, 0x9e, 0x46, 0x99, 0xf6, 0x2a, 0x15,
+- 0xc6, 0x97, 0x02, 0xa0, 0x66, 0x43, 0xd1, 0xa6,
+- 0x31, 0xa6, 0x9f, 0xfb, 0xf4, 0xd3, 0x69, 0xe5,
+- 0xcd, 0x76, 0x95, 0xb8, 0x7a, 0x82, 0x7f, 0x21,
+- 0x45, 0xff, 0x3f, 0xce, 0x55, 0xf6, 0x95, 0x10,
+- 0x08, 0x77, 0x10, 0x43, 0xc6, 0xf3, 0x09, 0xe5,
+- 0x68, 0xe7, 0x3c, 0xad, 0x00, 0x52, 0x45, 0x0d,
+- 0xfe, 0x2d, 0xc6, 0xc2, 0x94, 0x8c, 0x12, 0x1d,
+- 0xe6, 0x25, 0xae, 0x98, 0x12, 0x8e, 0x19, 0x9c,
+- 0x81, 0x68, 0xb1, 0x11, 0xf6, 0x69, 0xda, 0xe3,
+- 0x62, 0x08, 0x18, 0x7a, 0x25, 0x49, 0x28, 0xac,
+- 0xba, 0x71, 0x12, 0x0b, 0xe4, 0xa2, 0xe5, 0xc7,
+- 0x5d, 0x8e, 0xec, 0x49, 0x40, 0x21, 0xbf, 0x5a,
+- 0x98, 0xf3, 0x02, 0x68, 0x55, 0x03, 0x7f, 0x8a,
+- 0xe5, 0x94, 0x0c, 0x32, 0x5c, 0x07, 0x82, 0x63,
+- 0xaf, 0x6f, 0x91, 0x40, 0x84, 0x8e, 0x52, 0x25,
+- 0xd0, 0xb0, 0x29, 0x53, 0x05, 0xe2, 0x50, 0x7a,
+- 0x34, 0xeb, 0xc9, 0x46, 0x20, 0xa8, 0x3d, 0xde,
+- 0x7f, 0x16, 0x5f, 0x36, 0xc5, 0x2e, 0xdc, 0xd1,
+- 0x15, 0x47, 0xc7, 0x50, 0x40, 0x6d, 0x91, 0xc5,
+- 0xe7, 0x93, 0x95, 0x1a, 0xd3, 0x57, 0xbc, 0x52,
+- 0x33, 0xee, 0x14, 0x19, 0x22, 0x52, 0x89, 0xa7,
+- 0x4a, 0x25, 0x56, 0x77, 0x4b, 0xca, 0xcf, 0x0a,
+- 0xe1, 0xf5, 0x35, 0x85, 0x30, 0x7e, 0x59, 0x4a,
+- 0xbd, 0x14, 0x5b, 0xdf, 0xe3, 0x46, 0xcb, 0xac,
+- 0x1f, 0x6c, 0x96, 0x0e, 0xf4, 0x81, 0xd1, 0x99,
+- 0xca, 0x88, 0x63, 0x3d, 0x02, 0x58, 0x6b, 0xa9,
+- 0xe5, 0x9f, 0xb3, 0x00, 0xb2, 0x54, 0xc6, 0x74,
+- 0x1c, 0xbf, 0x46, 0xab, 0x97, 0xcc, 0xf8, 0x54,
+- 0x04, 0x07, 0x08, 0x52, 0xe6, 0xc0, 0xda, 0x93,
+- 0x74, 0x7d, 0x93, 0x99, 0x5d, 0x78, 0x68, 0xa6,
+- 0x2e, 0x6b, 0xd3, 0x6a, 0x69, 0xcc, 0x12, 0x6b,
+- 0xd4, 0xc7, 0xa5, 0xc6, 0xe7, 0xf6, 0x03, 0x04,
+- 0x5d, 0xcd, 0x61, 0x5e, 0x17, 0x40, 0xdc, 0xd1,
+- 0x5c, 0xf5, 0x08, 0xdf, 0x5c, 0x90, 0x85, 0xa4,
+- 0xaf, 0xf6, 0x78, 0xbb, 0x0d, 0xf1, 0xf4, 0xa4,
+- 0x54, 0x26, 0x72, 0x9e, 0x61, 0xfa, 0x86, 0xcf,
+- 0xe8, 0x9e, 0xa1, 0xe0, 0xc7, 0x48, 0x23, 0xae,
+- 0x5a, 0x90, 0xae, 0x75, 0x0a, 0x74, 0x18, 0x89,
+- 0x05, 0xb1, 0x92, 0xb2, 0x7f, 0xd0, 0x1b, 0xa6,
+- 0x62, 0x07, 0x25, 0x01, 0xc7, 0xc2, 0x4f, 0xf9,
+- 0xe8, 0xfe, 0x63, 0x95, 0x80, 0x07, 0xb4, 0x26,
+- 0xcc, 0xd1, 0x26, 0xb6, 0xc4, 0x3f, 0x9e, 0xcb,
+- 0x8e, 0x3b, 0x2e, 0x44, 0x16, 0xd3, 0x10, 0x9a,
+- 0x95, 0x08, 0xeb, 0xc8, 0xcb, 0xeb, 0xbf, 0x6f,
+- 0x0b, 0xcd, 0x1f, 0xc8, 0xca, 0x86, 0xaa, 0xec,
+- 0x33, 0xe6, 0x69, 0xf4, 0x45, 0x25, 0x86, 0x3a,
+- 0x22, 0x94, 0x4f, 0x00, 0x23, 0x6a, 0x44, 0xc2,
+- 0x49, 0x97, 0x33, 0xab, 0x36, 0x14, 0x0a, 0x70,
+- 0x24, 0xc3, 0xbe, 0x04, 0x3b, 0x79, 0xa0, 0xf9,
+- 0xb8, 0xe7, 0x76, 0x29, 0x22, 0x83, 0xd7, 0xf2,
+- 0x94, 0xf4, 0x41, 0x49, 0xba, 0x5f, 0x7b, 0x07,
+- 0xb5, 0xfb, 0xdb, 0x03, 0x1a, 0x9f, 0xb6, 0x4c,
+- 0xc2, 0x2e, 0x37, 0x40, 0x49, 0xc3, 0x38, 0x16,
+- 0xe2, 0x4f, 0x77, 0x82, 0xb0, 0x68, 0x4c, 0x71,
+- 0x1d, 0x57, 0x61, 0x9c, 0xd9, 0x4e, 0x54, 0x99,
+- 0x47, 0x13, 0x28, 0x73, 0x3c, 0xbb, 0x00, 0x90,
+- 0xf3, 0x4d, 0xc9, 0x0e, 0xfd, 0xe7, 0xb1, 0x71,
+- 0xd3, 0x15, 0x79, 0xbf, 0xcc, 0x26, 0x2f, 0xbd,
+- 0xad, 0x6c, 0x50, 0x69, 0x6c, 0x3e, 0x6d, 0x80,
+- 0x9a, 0xea, 0x78, 0xaf, 0x19, 0xb2, 0x0d, 0x4d,
+- 0xad, 0x04, 0x07, 0xae, 0x22, 0x90, 0x4a, 0x93,
+- 0x32, 0x0e, 0x36, 0x9b, 0x1b, 0x46, 0xba, 0x3b,
+- 0xb4, 0xac, 0xc6, 0xd1, 0xa2, 0x31, 0x53, 0x3b,
+- 0x2a, 0x3d, 0x45, 0xfe, 0x03, 0x61, 0x10, 0x85,
+- 0x17, 0x69, 0xa6, 0x78, 0xcc, 0x6c, 0x87, 0x49,
+- 0x53, 0xf9, 0x80, 0x10, 0xde, 0x80, 0xa2, 0x41,
+- 0x6a, 0xc3, 0x32, 0x02, 0xad, 0x6d, 0x3c, 0x56,
+- 0x00, 0x71, 0x51, 0x06, 0xa7, 0xbd, 0xfb, 0xef,
+- 0x3c, 0xb5, 0x9f, 0xfc, 0x48, 0x7d, 0x53, 0x7c,
+- 0x66, 0xb0, 0x49, 0x23, 0xc4, 0x47, 0x10, 0x0e,
+- 0xe5, 0x6c, 0x74, 0x13, 0xe6, 0xc5, 0x3f, 0xaa,
+- 0xde, 0xff, 0x07, 0x44, 0xdd, 0x56, 0x1b, 0xad,
+- 0x09, 0x77, 0xfb, 0x5b, 0x12, 0xb8, 0x0d, 0x38,
+- 0x17, 0x37, 0x35, 0x7b, 0x9b, 0xbc, 0xfe, 0xd4,
+- 0x7e, 0x8b, 0xda, 0x7e, 0x5b, 0x04, 0xa7, 0x22,
+- 0xa7, 0x31, 0xa1, 0x20, 0x86, 0xc7, 0x1b, 0x99,
+- 0xdb, 0xd1, 0x89, 0xf4, 0x94, 0xa3, 0x53, 0x69,
+- 0x8d, 0xe7, 0xe8, 0x74, 0x11, 0x8d, 0x74, 0xd6,
+- 0x07, 0x37, 0x91, 0x9f, 0xfd, 0x67, 0x50, 0x3a,
+- 0xc9, 0xe1, 0xf4, 0x36, 0xd5, 0xa0, 0x47, 0xd1,
+- 0xf9, 0xe5, 0x39, 0xa3, 0x31, 0xac, 0x07, 0x36,
+- 0x23, 0xf8, 0x66, 0x18, 0x14, 0x28, 0x34, 0x0f,
+- 0xb8, 0xd0, 0xe7, 0x29, 0xb3, 0x04, 0x4b, 0x55,
+- 0x01, 0x41, 0xb2, 0x75, 0x8d, 0xcb, 0x96, 0x85,
+- 0x3a, 0xfb, 0xab, 0x2b, 0x9e, 0xfa, 0x58, 0x20,
+- 0x44, 0x1f, 0xc0, 0x14, 0x22, 0x75, 0x61, 0xe8,
+- 0xaa, 0x19, 0xcf, 0xf1, 0x82, 0x56, 0xf4, 0xd7,
+- 0x78, 0x7b, 0x3d, 0x5f, 0xb3, 0x9e, 0x0b, 0x8a,
+- 0x57, 0x50, 0xdb, 0x17, 0x41, 0x65, 0x4d, 0xa3,
+- 0x02, 0xc9, 0x9c, 0x9c, 0x53, 0xfb, 0x39, 0x39,
+- 0x9b, 0x1d, 0x72, 0x24, 0xda, 0xb7, 0x39, 0xbe,
+- 0x13, 0x3b, 0xfa, 0x29, 0xda, 0x9e, 0x54, 0x64,
+- 0x6e, 0xba, 0xd8, 0xa1, 0xcb, 0xb3, 0x36, 0xfa,
+- 0xcb, 0x47, 0x85, 0xe9, 0x61, 0x38, 0xbc, 0xbe,
+- 0xc5, 0x00, 0x38, 0x2a, 0x54, 0xf7, 0xc4, 0xb9,
+- 0xb3, 0xd3, 0x7b, 0xa0, 0xa0, 0xf8, 0x72, 0x7f,
+- 0x8c, 0x8e, 0x82, 0x0e, 0xc6, 0x1c, 0x75, 0x9d,
+- 0xca, 0x8e, 0x61, 0x87, 0xde, 0xad, 0x80, 0xd2,
+- 0xf5, 0xf9, 0x80, 0xef, 0x15, 0x75, 0xaf, 0xf5,
+- 0x80, 0xfb, 0xff, 0x6d, 0x1e, 0x25, 0xb7, 0x40,
+- 0x61, 0x6a, 0x39, 0x5a, 0x6a, 0xb5, 0x31, 0xab,
+- 0x97, 0x8a, 0x19, 0x89, 0x44, 0x40, 0xc0, 0xa6,
+- 0xb4, 0x4e, 0x30, 0x32, 0x7b, 0x13, 0xe7, 0x67,
+- 0xa9, 0x8b, 0x57, 0x04, 0xc2, 0x01, 0xa6, 0xf4,
+- 0x28, 0x99, 0xad, 0x2c, 0x76, 0xa3, 0x78, 0xc2,
+- 0x4a, 0xe6, 0xca, 0x5c, 0x50, 0x6a, 0xc1, 0xb0,
+- 0x62, 0x4b, 0x10, 0x8e, 0x7c, 0x17, 0x43, 0xb3,
+- 0x17, 0x66, 0x1c, 0x3e, 0x8d, 0x69, 0xf0, 0x5a,
+- 0x71, 0xf5, 0x97, 0xdc, 0xd1, 0x45, 0xdd, 0x28,
+- 0xf3, 0x5d, 0xdf, 0x53, 0x7b, 0x11, 0xe5, 0xbc,
+- 0x4c, 0xdb, 0x1b, 0x51, 0x6b, 0xe9, 0xfb, 0x3d,
+- 0xc1, 0xc3, 0x2c, 0xb9, 0x71, 0xf5, 0xb6, 0xb2,
+- 0x13, 0x36, 0x79, 0x80, 0x53, 0xe8, 0xd3, 0xa6,
+- 0x0a, 0xaf, 0xfd, 0x56, 0x97, 0xf7, 0x40, 0x8e,
+- 0x45, 0xce, 0xf8, 0xb0, 0x9e, 0x5c, 0x33, 0x82,
+- 0xb0, 0x44, 0x56, 0xfc, 0x05, 0x09, 0xe9, 0x2a,
+- 0xac, 0x26, 0x80, 0x14, 0x1d, 0xc8, 0x3a, 0x35,
+- 0x4c, 0x82, 0x97, 0xfd, 0x76, 0xb7, 0xa9, 0x0a,
+- 0x35, 0x58, 0x79, 0x8e, 0x0f, 0x66, 0xea, 0xaf,
+- 0x51, 0x6c, 0x09, 0xa9, 0x6e, 0x9b, 0xcb, 0x9a,
+- 0x31, 0x47, 0xa0, 0x2f, 0x7c, 0x71, 0xb4, 0x4a,
+- 0x11, 0xaa, 0x8c, 0x66, 0xc5, 0x64, 0xe6, 0x3a,
+- 0x54, 0xda, 0x24, 0x6a, 0xc4, 0x41, 0x65, 0x46,
+- 0x82, 0xa0, 0x0a, 0x0f, 0x5f, 0xfb, 0x25, 0xd0,
+- 0x2c, 0x91, 0xa7, 0xee, 0xc4, 0x81, 0x07, 0x86,
+- 0x75, 0x5e, 0x33, 0x69, 0x97, 0xe4, 0x2c, 0xa8,
+- 0x9d, 0x9f, 0x0b, 0x6a, 0xbe, 0xad, 0x98, 0xda,
+- 0x6d, 0x94, 0x41, 0xda, 0x2c, 0x1e, 0x89, 0xc4,
+- 0xc2, 0xaf, 0x1e, 0x00, 0x05, 0x0b, 0x83, 0x60,
+- 0xbd, 0x43, 0xea, 0x15, 0x23, 0x7f, 0xb9, 0xac,
+- 0xee, 0x4f, 0x2c, 0xaf, 0x2a, 0xf3, 0xdf, 0xd0,
+- 0xf3, 0x19, 0x31, 0xbb, 0x4a, 0x74, 0x84, 0x17,
+- 0x52, 0x32, 0x2c, 0x7d, 0x61, 0xe4, 0xcb, 0xeb,
+- 0x80, 0x38, 0x15, 0x52, 0xcb, 0x6f, 0xea, 0xe5,
+- 0x73, 0x9c, 0xd9, 0x24, 0x69, 0xc6, 0x95, 0x32,
+- 0x21, 0xc8, 0x11, 0xe4, 0xdc, 0x36, 0xd7, 0x93,
+- 0x38, 0x66, 0xfb, 0xb2, 0x7f, 0x3a, 0xb9, 0xaf,
+- 0x31, 0xdd, 0x93, 0x75, 0x78, 0x8a, 0x2c, 0x94,
+- 0x87, 0x1a, 0x58, 0xec, 0x9e, 0x7d, 0x4d, 0xba,
+- 0xe1, 0xe5, 0x4d, 0xfc, 0xbc, 0xa4, 0x2a, 0x14,
+- 0xef, 0xcc, 0xa7, 0xec, 0xab, 0x43, 0x09, 0x18,
+- 0xd3, 0xab, 0x68, 0xd1, 0x07, 0x99, 0x44, 0x47,
+- 0xd6, 0x83, 0x85, 0x3b, 0x30, 0xea, 0xa9, 0x6b,
+- 0x63, 0xea, 0xc4, 0x07, 0xfb, 0x43, 0x2f, 0xa4,
+- 0xaa, 0xb0, 0xab, 0x03, 0x89, 0xce, 0x3f, 0x8c,
+- 0x02, 0x7c, 0x86, 0x54, 0xbc, 0x88, 0xaf, 0x75,
+- 0xd2, 0xdc, 0x63, 0x17, 0xd3, 0x26, 0xf6, 0x96,
+- 0xa9, 0x3c, 0xf1, 0x61, 0x8c, 0x11, 0x18, 0xcc,
+- 0xd6, 0xea, 0x5b, 0xe2, 0xcd, 0xf0, 0xf1, 0xb2,
+- 0xe5, 0x35, 0x90, 0x1f, 0x85, 0x4c, 0x76, 0x5b,
+- 0x66, 0xce, 0x44, 0xa4, 0x32, 0x9f, 0xe6, 0x7b,
+- 0x71, 0x6e, 0x9f, 0x58, 0x15, 0x67, 0x72, 0x87,
+- 0x64, 0x8e, 0x3a, 0x44, 0x45, 0xd4, 0x76, 0xfa,
+- 0xc2, 0xf6, 0xef, 0x85, 0x05, 0x18, 0x7a, 0x9b,
+- 0xba, 0x41, 0x54, 0xac, 0xf0, 0xfc, 0x59, 0x12,
+- 0x3f, 0xdf, 0xa0, 0xe5, 0x8a, 0x65, 0xfd, 0x3a,
+- 0x62, 0x8d, 0x83, 0x2c, 0x03, 0xbe, 0x05, 0x76,
+- 0x2e, 0x53, 0x49, 0x97, 0x94, 0x33, 0xae, 0x40,
+- 0x81, 0x15, 0xdb, 0x6e, 0xad, 0xaa, 0xf5, 0x4b,
+- 0xe3, 0x98, 0x70, 0xdf, 0xe0, 0x7c, 0xcd, 0xdb,
+- 0x02, 0xd4, 0x7d, 0x2f, 0xc1, 0xe6, 0xb4, 0xf3,
+- 0xd7, 0x0d, 0x7a, 0xd9, 0x23, 0x9e, 0x87, 0x2d,
+- 0xce, 0x87, 0xad, 0xcc, 0x72, 0x05, 0x00, 0x29,
+- 0xdc, 0x73, 0x7f, 0x64, 0xc1, 0x15, 0x0e, 0xc2,
+- 0xdf, 0xa7, 0x5f, 0xeb, 0x41, 0xa1, 0xcd, 0xef,
+- 0x5c, 0x50, 0x79, 0x2a, 0x56, 0x56, 0x71, 0x8c,
+- 0xac, 0xc0, 0x79, 0x50, 0x69, 0xca, 0x59, 0x32,
+- 0x65, 0xf2, 0x54, 0xe4, 0x52, 0x38, 0x76, 0xd1,
+- 0x5e, 0xde, 0x26, 0x9e, 0xfb, 0x75, 0x2e, 0x11,
+- 0xb5, 0x10, 0xf4, 0x17, 0x73, 0xf5, 0x89, 0xc7,
+- 0x4f, 0x43, 0x5c, 0x8e, 0x7c, 0xb9, 0x05, 0x52,
+- 0x24, 0x40, 0x99, 0xfe, 0x9b, 0x85, 0x0b, 0x6c,
+- 0x22, 0x3e, 0x8b, 0xae, 0x86, 0xa1, 0xd2, 0x79,
+- 0x05, 0x68, 0x6b, 0xab, 0xe3, 0x41, 0x49, 0xed,
+- 0x15, 0xa1, 0x8d, 0x40, 0x2d, 0x61, 0xdf, 0x1a,
+- 0x59, 0xc9, 0x26, 0x8b, 0xef, 0x30, 0x4c, 0x88,
+- 0x4b, 0x10, 0xf8, 0x8d, 0xa6, 0x92, 0x9f, 0x4b,
+- 0xf3, 0xc4, 0x53, 0x0b, 0x89, 0x5d, 0x28, 0x92,
+- 0xcf, 0x78, 0xb2, 0xc0, 0x5d, 0xed, 0x7e, 0xfc,
+- 0xc0, 0x12, 0x23, 0x5f, 0x5a, 0x78, 0x86, 0x43,
+- 0x6e, 0x27, 0xf7, 0x5a, 0xa7, 0x6a, 0xed, 0x19,
+- 0x04, 0xf0, 0xb3, 0x12, 0xd1, 0xbd, 0x0e, 0x89,
+- 0x6e, 0xbc, 0x96, 0xa8, 0xd8, 0x49, 0x39, 0x9f,
+- 0x7e, 0x67, 0xf0, 0x2e, 0x3e, 0x01, 0xa9, 0xba,
+- 0xec, 0x8b, 0x62, 0x8e, 0xcb, 0x4a, 0x70, 0x43,
+- 0xc7, 0xc2, 0xc4, 0xca, 0x82, 0x03, 0x73, 0xe9,
+- 0x11, 0xdf, 0xcf, 0x54, 0xea, 0xc9, 0xb0, 0x95,
+- 0x51, 0xc0, 0x13, 0x3d, 0x92, 0x05, 0xfa, 0xf4,
+- 0xa9, 0x34, 0xc8, 0xce, 0x6c, 0x3d, 0x54, 0xcc,
+- 0xc4, 0xaf, 0xf1, 0xdc, 0x11, 0x44, 0x26, 0xa2,
+- 0xaf, 0xf1, 0x85, 0x75, 0x7d, 0x03, 0x61, 0x68,
+- 0x4e, 0x78, 0xc6, 0x92, 0x7d, 0x86, 0x7d, 0x77,
+- 0xdc, 0x71, 0x72, 0xdb, 0xc6, 0xae, 0xa1, 0xcb,
+- 0x70, 0x9a, 0x0b, 0x19, 0xbe, 0x4a, 0x6c, 0x2a,
+- 0xe2, 0xba, 0x6c, 0x64, 0x9a, 0x13, 0x28, 0xdf,
+- 0x85, 0x75, 0xe6, 0x43, 0xf6, 0x87, 0x08, 0x68,
+- 0x6e, 0xba, 0x6e, 0x79, 0x9f, 0x04, 0xbc, 0x23,
+- 0x50, 0xf6, 0x33, 0x5c, 0x1f, 0x24, 0x25, 0xbe,
+- 0x33, 0x47, 0x80, 0x45, 0x56, 0xa3, 0xa7, 0xd7,
+- 0x7a, 0xb1, 0x34, 0x0b, 0x90, 0x3c, 0x9c, 0xad,
+- 0x44, 0x5f, 0x9e, 0x0e, 0x9d, 0xd4, 0xbd, 0x93,
+- 0x5e, 0xfa, 0x3c, 0xe0, 0xb0, 0xd9, 0xed, 0xf3,
+- 0xd6, 0x2e, 0xff, 0x24, 0xd8, 0x71, 0x6c, 0xed,
+- 0xaf, 0x55, 0xeb, 0x22, 0xac, 0x93, 0x68, 0x32,
+- 0x05, 0x5b, 0x47, 0xdd, 0xc6, 0x4a, 0xcb, 0xc7,
+- 0x10, 0xe1, 0x3c, 0x92, 0x1a, 0xf3, 0x23, 0x78,
+- 0x2b, 0xa1, 0xd2, 0x80, 0xf4, 0x12, 0xb1, 0x20,
+- 0x8f, 0xff, 0x26, 0x35, 0xdd, 0xfb, 0xc7, 0x4e,
+- 0x78, 0xf1, 0x2d, 0x50, 0x12, 0x77, 0xa8, 0x60,
+- 0x7c, 0x0f, 0xf5, 0x16, 0x2f, 0x63, 0x70, 0x2a,
+- 0xc0, 0x96, 0x80, 0x4e, 0x0a, 0xb4, 0x93, 0x35,
+- 0x5d, 0x1d, 0x3f, 0x56, 0xf7, 0x2f, 0xbb, 0x90,
+- 0x11, 0x16, 0x8f, 0xa2, 0xec, 0x47, 0xbe, 0xac,
+- 0x56, 0x01, 0x26, 0x56, 0xb1, 0x8c, 0xb2, 0x10,
+- 0xf9, 0x1a, 0xca, 0xf5, 0xd1, 0xb7, 0x39, 0x20,
+- 0x63, 0xf1, 0x69, 0x20, 0x4f, 0x13, 0x12, 0x1f,
+- 0x5b, 0x65, 0xfc, 0x98, 0xf7, 0xc4, 0x7a, 0xbe,
+- 0xf7, 0x26, 0x4d, 0x2b, 0x84, 0x7b, 0x42, 0xad,
+- 0xd8, 0x7a, 0x0a, 0xb4, 0xd8, 0x74, 0xbf, 0xc1,
+- 0xf0, 0x6e, 0xb4, 0x29, 0xa3, 0xbb, 0xca, 0x46,
+- 0x67, 0x70, 0x6a, 0x2d, 0xce, 0x0e, 0xa2, 0x8a,
+- 0xa9, 0x87, 0xbf, 0x05, 0xc4, 0xc1, 0x04, 0xa3,
+- 0xab, 0xd4, 0x45, 0x43, 0x8c, 0xb6, 0x02, 0xb0,
+- 0x41, 0xc8, 0xfc, 0x44, 0x3d, 0x59, 0xaa, 0x2e,
+- 0x44, 0x21, 0x2a, 0x8d, 0x88, 0x9d, 0x57, 0xf4,
+- 0xa0, 0x02, 0x77, 0xb8, 0xa6, 0xa0, 0xe6, 0x75,
+- 0x5c, 0x82, 0x65, 0x3e, 0x03, 0x5c, 0x29, 0x8f,
+- 0x38, 0x55, 0xab, 0x33, 0x26, 0xef, 0x9f, 0x43,
+- 0x52, 0xfd, 0x68, 0xaf, 0x36, 0xb4, 0xbb, 0x9a,
+- 0x58, 0x09, 0x09, 0x1b, 0xc3, 0x65, 0x46, 0x46,
+- 0x1d, 0xa7, 0x94, 0x18, 0x23, 0x50, 0x2c, 0xca,
+- 0x2c, 0x55, 0x19, 0x97, 0x01, 0x9d, 0x93, 0x3b,
+- 0x63, 0x86, 0xf2, 0x03, 0x67, 0x45, 0xd2, 0x72,
+- 0x28, 0x52, 0x6c, 0xf4, 0xe3, 0x1c, 0xb5, 0x11,
+- 0x13, 0xf1, 0xeb, 0x21, 0xc7, 0xd9, 0x56, 0x82,
+- 0x2b, 0x82, 0x39, 0xbd, 0x69, 0x54, 0xed, 0x62,
+- 0xc3, 0xe2, 0xde, 0x73, 0xd4, 0x6a, 0x12, 0xae,
+- 0x13, 0x21, 0x7f, 0x4b, 0x5b, 0xfc, 0xbf, 0xe8,
+- 0x2b, 0xbe, 0x56, 0xba, 0x68, 0x8b, 0x9a, 0xb1,
+- 0x6e, 0xfa, 0xbf, 0x7e, 0x5a, 0x4b, 0xf1, 0xac,
+- 0x98, 0x65, 0x85, 0xd1, 0x93, 0x53, 0xd3, 0x7b,
+- 0x09, 0xdd, 0x4b, 0x10, 0x6d, 0x84, 0xb0, 0x13,
+- 0x65, 0xbd, 0xcf, 0x52, 0x09, 0xc4, 0x85, 0xe2,
+- 0x84, 0x74, 0x15, 0x65, 0xb7, 0xf7, 0x51, 0xaf,
+- 0x55, 0xad, 0xa4, 0xd1, 0x22, 0x54, 0x70, 0x94,
+- 0xa0, 0x1c, 0x90, 0x41, 0xfd, 0x99, 0xd7, 0x5a,
+- 0x31, 0xef, 0xaa, 0x25, 0xd0, 0x7f, 0x4f, 0xea,
+- 0x1d, 0x55, 0x42, 0xe5, 0x49, 0xb0, 0xd0, 0x46,
+- 0x62, 0x36, 0x43, 0xb2, 0x82, 0x15, 0x75, 0x50,
+- 0xa4, 0x72, 0xeb, 0x54, 0x27, 0x1f, 0x8a, 0xe4,
+- 0x7d, 0xe9, 0x66, 0xc5, 0xf1, 0x53, 0xa4, 0xd1,
+- 0x0c, 0xeb, 0xb8, 0xf8, 0xbc, 0xd4, 0xe2, 0xe7,
+- 0xe1, 0xf8, 0x4b, 0xcb, 0xa9, 0xa1, 0xaf, 0x15,
+- 0x83, 0xcb, 0x72, 0xd0, 0x33, 0x79, 0x00, 0x2d,
+- 0x9f, 0xd7, 0xf1, 0x2e, 0x1e, 0x10, 0xe4, 0x45,
+- 0xc0, 0x75, 0x3a, 0x39, 0xea, 0x68, 0xf7, 0x5d,
+- 0x1b, 0x73, 0x8f, 0xe9, 0x8e, 0x0f, 0x72, 0x47,
+- 0xae, 0x35, 0x0a, 0x31, 0x7a, 0x14, 0x4d, 0x4a,
+- 0x6f, 0x47, 0xf7, 0x7e, 0x91, 0x6e, 0x74, 0x8b,
+- 0x26, 0x47, 0xf9, 0xc3, 0xf9, 0xde, 0x70, 0xf5,
+- 0x61, 0xab, 0xa9, 0x27, 0x9f, 0x82, 0xe4, 0x9c,
+- 0x89, 0x91, 0x3f, 0x2e, 0x6a, 0xfd, 0xb5, 0x49,
+- 0xe9, 0xfd, 0x59, 0x14, 0x36, 0x49, 0x40, 0x6d,
+- 0x32, 0xd8, 0x85, 0x42, 0xf3, 0xa5, 0xdf, 0x0c,
+- 0xa8, 0x27, 0xd7, 0x54, 0xe2, 0x63, 0x2f, 0xf2,
+- 0x7e, 0x8b, 0x8b, 0xe7, 0xf1, 0x9a, 0x95, 0x35,
+- 0x43, 0xdc, 0x3a, 0xe4, 0xb6, 0xf4, 0xd0, 0xdf,
+- 0x9c, 0xcb, 0x94, 0xf3, 0x21, 0xa0, 0x77, 0x50,
+- 0xe2, 0xc6, 0xc4, 0xc6, 0x5f, 0x09, 0x64, 0x5b,
+- 0x92, 0x90, 0xd8, 0xe1, 0xd1, 0xed, 0x4b, 0x42,
+- 0xd7, 0x37, 0xaf, 0x65, 0x3d, 0x11, 0x39, 0xb6,
+- 0x24, 0x8a, 0x60, 0xae, 0xd6, 0x1e, 0xbf, 0x0e,
+- 0x0d, 0xd7, 0xdc, 0x96, 0x0e, 0x65, 0x75, 0x4e,
+- 0x29, 0x06, 0x9d, 0xa4, 0x51, 0x3a, 0x10, 0x63,
+- 0x8f, 0x17, 0x07, 0xd5, 0x8e, 0x3c, 0xf4, 0x28,
+- 0x00, 0x5a, 0x5b, 0x05, 0x19, 0xd8, 0xc0, 0x6c,
+- 0xe5, 0x15, 0xe4, 0x9c, 0x9d, 0x71, 0x9d, 0x5e,
+- 0x94, 0x29, 0x1a, 0xa7, 0x80, 0xfa, 0x0e, 0x33,
+- 0x03, 0xdd, 0xb7, 0x3e, 0x9a, 0xa9, 0x26, 0x18,
+- 0x37, 0xa9, 0x64, 0x08, 0x4d, 0x94, 0x5a, 0x88,
+- 0xca, 0x35, 0xce, 0x81, 0x02, 0xe3, 0x1f, 0x1b,
+- 0x89, 0x1a, 0x77, 0x85, 0xe3, 0x41, 0x6d, 0x32,
+- 0x42, 0x19, 0x23, 0x7d, 0xc8, 0x73, 0xee, 0x25,
+- 0x85, 0x0d, 0xf8, 0x31, 0x25, 0x79, 0x1b, 0x6f,
+- 0x79, 0x25, 0xd2, 0xd8, 0xd4, 0x23, 0xfd, 0xf7,
+- 0x82, 0x36, 0x6a, 0x0c, 0x46, 0x22, 0x15, 0xe9,
+- 0xff, 0x72, 0x41, 0x91, 0x91, 0x7d, 0x3a, 0xb7,
+- 0xdd, 0x65, 0x99, 0x70, 0xf6, 0x8d, 0x84, 0xf8,
+- 0x67, 0x15, 0x20, 0x11, 0xd6, 0xb2, 0x55, 0x7b,
+- 0xdb, 0x87, 0xee, 0xef, 0x55, 0x89, 0x2a, 0x59,
+- 0x2b, 0x07, 0x8f, 0x43, 0x8a, 0x59, 0x3c, 0x01,
+- 0x8b, 0x65, 0x54, 0xa1, 0x66, 0xd5, 0x38, 0xbd,
+- 0xc6, 0x30, 0xa9, 0xcc, 0x49, 0xb6, 0xa8, 0x1b,
+- 0xb8, 0xc0, 0x0e, 0xe3, 0x45, 0x28, 0xe2, 0xff,
+- 0x41, 0x9f, 0x7e, 0x7c, 0xd1, 0xae, 0x9e, 0x25,
+- 0x3f, 0x4c, 0x7c, 0x7c, 0xf4, 0xa8, 0x26, 0x4d,
+- 0x5c, 0xfd, 0x4b, 0x27, 0x18, 0xf9, 0x61, 0x76,
+- 0x48, 0xba, 0x0c, 0x6b, 0xa9, 0x4d, 0xfc, 0xf5,
+- 0x3b, 0x35, 0x7e, 0x2f, 0x4a, 0xa9, 0xc2, 0x9a,
+- 0xae, 0xab, 0x86, 0x09, 0x89, 0xc9, 0xc2, 0x40,
+- 0x39, 0x2c, 0x81, 0xb3, 0xb8, 0x17, 0x67, 0xc2,
+- 0x0d, 0x32, 0x4a, 0x3a, 0x67, 0x81, 0xd7, 0x1a,
+- 0x34, 0x52, 0xc5, 0xdb, 0x0a, 0xf5, 0x63, 0x39,
+- 0xea, 0x1f, 0xe1, 0x7c, 0xa1, 0x9e, 0xc1, 0x35,
+- 0xe3, 0xb1, 0x18, 0x45, 0x67, 0xf9, 0x22, 0x38,
+- 0x95, 0xd9, 0x34, 0x34, 0x86, 0xc6, 0x41, 0x94,
+- 0x15, 0xf9, 0x5b, 0x41, 0xa6, 0x87, 0x8b, 0xf8,
+- 0xd5, 0xe1, 0x1b, 0xe2, 0x5b, 0xf3, 0x86, 0x10,
+- 0xff, 0xe6, 0xae, 0x69, 0x76, 0xbc, 0x0d, 0xb4,
+- 0x09, 0x90, 0x0c, 0xa2, 0x65, 0x0c, 0xad, 0x74,
+- 0xf5, 0xd7, 0xff, 0xda, 0xc1, 0xce, 0x85, 0xbe,
+- 0x00, 0xa7, 0xff, 0x4d, 0x2f, 0x65, 0xd3, 0x8c,
+- 0x86, 0x2d, 0x05, 0xe8, 0xed, 0x3e, 0x6b, 0x8b,
+- 0x0f, 0x3d, 0x83, 0x8c, 0xf1, 0x1d, 0x5b, 0x96,
+- 0x2e, 0xb1, 0x9c, 0xc2, 0x98, 0xe1, 0x70, 0xb9,
+- 0xba, 0x5c, 0x8a, 0x43, 0xd6, 0x34, 0xa7, 0x2d,
+- 0xc9, 0x92, 0xae, 0xf2, 0xa5, 0x7b, 0x05, 0x49,
+- 0xa7, 0x33, 0x34, 0x86, 0xca, 0xe4, 0x96, 0x23,
+- 0x76, 0x5b, 0xf2, 0xc6, 0xf1, 0x51, 0x28, 0x42,
+- 0x7b, 0xcc, 0x76, 0x8f, 0xfa, 0xa2, 0xad, 0x31,
+- 0xd4, 0xd6, 0x7a, 0x6d, 0x25, 0x25, 0x54, 0xe4,
+- 0x3f, 0x50, 0x59, 0xe1, 0x5c, 0x05, 0xb7, 0x27,
+- 0x48, 0xbf, 0x07, 0xec, 0x1b, 0x13, 0xbe, 0x2b,
+- 0xa1, 0x57, 0x2b, 0xd5, 0xab, 0xd7, 0xd0, 0x4c,
+- 0x1e, 0xcb, 0x71, 0x9b, 0xc5, 0x90, 0x85, 0xd3,
+- 0xde, 0x59, 0xec, 0x71, 0xeb, 0x89, 0xbb, 0xd0,
+- 0x09, 0x50, 0xe1, 0x16, 0x3f, 0xfd, 0x1c, 0x34,
+- 0xc3, 0x1c, 0xa1, 0x10, 0x77, 0x53, 0x98, 0xef,
+- 0xf2, 0xfd, 0xa5, 0x01, 0x59, 0xc2, 0x9b, 0x26,
+- 0xc7, 0x42, 0xd9, 0x49, 0xda, 0x58, 0x2b, 0x6e,
+- 0x9f, 0x53, 0x19, 0x76, 0x7e, 0xd9, 0xc9, 0x0e,
+- 0x68, 0xc8, 0x7f, 0x51, 0x22, 0x42, 0xef, 0x49,
+- 0xa4, 0x55, 0xb6, 0x36, 0xac, 0x09, 0xc7, 0x31,
+- 0x88, 0x15, 0x4b, 0x2e, 0x8f, 0x3a, 0x08, 0xf7,
+- 0xd8, 0xf7, 0xa8, 0xc5, 0xa9, 0x33, 0xa6, 0x45,
+- 0xe4, 0xc4, 0x94, 0x76, 0xf3, 0x0d, 0x8f, 0x7e,
+- 0xc8, 0xf6, 0xbc, 0x23, 0x0a, 0xb6, 0x4c, 0xd3,
+- 0x6a, 0xcd, 0x36, 0xc2, 0x90, 0x5c, 0x5c, 0x3c,
+- 0x65, 0x7b, 0xc2, 0xd6, 0xcc, 0xe6, 0x0d, 0x87,
+- 0x73, 0x2e, 0x71, 0x79, 0x16, 0x06, 0x63, 0x28,
+- 0x09, 0x15, 0xd8, 0x89, 0x38, 0x38, 0x3d, 0xb5,
+- 0x42, 0x1c, 0x08, 0x24, 0xf7, 0x2a, 0xd2, 0x9d,
+- 0xc8, 0xca, 0xef, 0xf9, 0x27, 0xd8, 0x07, 0x86,
+- 0xf7, 0x43, 0x0b, 0x55, 0x15, 0x3f, 0x9f, 0x83,
+- 0xef, 0xdc, 0x49, 0x9d, 0x2a, 0xc1, 0x54, 0x62,
+- 0xbd, 0x9b, 0x66, 0x55, 0x9f, 0xb7, 0x12, 0xf3,
+- 0x1b, 0x4d, 0x9d, 0x2a, 0x5c, 0xed, 0x87, 0x75,
+- 0x87, 0x26, 0xec, 0x61, 0x2c, 0xb4, 0x0f, 0x89,
+- 0xb0, 0xfb, 0x2e, 0x68, 0x5d, 0x15, 0xc7, 0x8d,
+- 0x2e, 0xc0, 0xd9, 0xec, 0xaf, 0x4f, 0xd2, 0x25,
+- 0x29, 0xe8, 0xd2, 0x26, 0x2b, 0x67, 0xe9, 0xfc,
+- 0x2b, 0xa8, 0x67, 0x96, 0x12, 0x1f, 0x5b, 0x96,
+- 0xc6, 0x14, 0x53, 0xaf, 0x44, 0xea, 0xd6, 0xe2,
+- 0x94, 0x98, 0xe4, 0x12, 0x93, 0x4c, 0x92, 0xe0,
+- 0x18, 0xa5, 0x8d, 0x2d, 0xe4, 0x71, 0x3c, 0x47,
+- 0x4c, 0xf7, 0xe6, 0x47, 0x9e, 0xc0, 0x68, 0xdf,
+- 0xd4, 0xf5, 0x5a, 0x74, 0xb1, 0x2b, 0x29, 0x03,
+- 0x19, 0x07, 0xaf, 0x90, 0x62, 0x5c, 0x68, 0x98,
+- 0x48, 0x16, 0x11, 0x02, 0x9d, 0xee, 0xb4, 0x9b,
+- 0xe5, 0x42, 0x7f, 0x08, 0xfd, 0x16, 0x32, 0x0b,
+- 0xd0, 0xb3, 0xfa, 0x2b, 0xb7, 0x99, 0xf9, 0x29,
+- 0xcd, 0x20, 0x45, 0x9f, 0xb3, 0x1a, 0x5d, 0xa2,
+- 0xaf, 0x4d, 0xe0, 0xbd, 0x42, 0x0d, 0xbc, 0x74,
+- 0x99, 0x9c, 0x8e, 0x53, 0x1a, 0xb4, 0x3e, 0xbd,
+- 0xa2, 0x9a, 0x2d, 0xf7, 0xf8, 0x39, 0x0f, 0x67,
+- 0x63, 0xfc, 0x6b, 0xc0, 0xaf, 0xb3, 0x4b, 0x4f,
+- 0x55, 0xc4, 0xcf, 0xa7, 0xc8, 0x04, 0x11, 0x3e,
+- 0x14, 0x32, 0xbb, 0x1b, 0x38, 0x77, 0xd6, 0x7f,
+- 0x54, 0x4c, 0xdf, 0x75, 0xf3, 0x07, 0x2d, 0x33,
+- 0x9b, 0xa8, 0x20, 0xe1, 0x7b, 0x12, 0xb5, 0xf3,
+- 0xef, 0x2f, 0xce, 0x72, 0xe5, 0x24, 0x60, 0xc1,
+- 0x30, 0xe2, 0xab, 0xa1, 0x8e, 0x11, 0x09, 0xa8,
+- 0x21, 0x33, 0x44, 0xfe, 0x7f, 0x35, 0x32, 0x93,
+- 0x39, 0xa7, 0xad, 0x8b, 0x79, 0x06, 0xb2, 0xcb,
+- 0x4e, 0xa9, 0x5f, 0xc7, 0xba, 0x74, 0x29, 0xec,
+- 0x93, 0xa0, 0x4e, 0x54, 0x93, 0xc0, 0xbc, 0x55,
+- 0x64, 0xf0, 0x48, 0xe5, 0x57, 0x99, 0xee, 0x75,
+- 0xd6, 0x79, 0x0f, 0x66, 0xb7, 0xc6, 0x57, 0x76,
+- 0xf7, 0xb7, 0xf3, 0x9c, 0xc5, 0x60, 0xe8, 0x7f,
+- 0x83, 0x76, 0xd6, 0x0e, 0xaa, 0xe6, 0x90, 0x39,
+- 0x1d, 0xa6, 0x32, 0x6a, 0x34, 0xe3, 0x55, 0xf8,
+- 0x58, 0xa0, 0x58, 0x7d, 0x33, 0xe0, 0x22, 0x39,
+- 0x44, 0x64, 0x87, 0x86, 0x5a, 0x2f, 0xa7, 0x7e,
+- 0x0f, 0x38, 0xea, 0xb0, 0x30, 0xcc, 0x61, 0xa5,
+- 0x6a, 0x32, 0xae, 0x1e, 0xf7, 0xe9, 0xd0, 0xa9,
+- 0x0c, 0x32, 0x4b, 0xb5, 0x49, 0x28, 0xab, 0x85,
+- 0x2f, 0x8e, 0x01, 0x36, 0x38, 0x52, 0xd0, 0xba,
+- 0xd6, 0x02, 0x78, 0xf8, 0x0e, 0x3e, 0x9c, 0x8b,
+- 0x6b, 0x45, 0x99, 0x3f, 0x5c, 0xfe, 0x58, 0xf1,
+- 0x5c, 0x94, 0x04, 0xe1, 0xf5, 0x18, 0x6d, 0x51,
+- 0xb2, 0x5d, 0x18, 0x20, 0xb6, 0xc2, 0x9a, 0x42,
+- 0x1d, 0xb3, 0xab, 0x3c, 0xb6, 0x3a, 0x13, 0x03,
+- 0xb2, 0x46, 0x82, 0x4f, 0xfc, 0x64, 0xbc, 0x4f,
+- 0xca, 0xfa, 0x9c, 0xc0, 0xd5, 0xa7, 0xbd, 0x11,
+- 0xb7, 0xe4, 0x5a, 0xf6, 0x6f, 0x4d, 0x4d, 0x54,
+- 0xea, 0xa4, 0x98, 0x66, 0xd4, 0x22, 0x3b, 0xd3,
+- 0x8f, 0x34, 0x47, 0xd9, 0x7c, 0xf4, 0x72, 0x3b,
+- 0x4d, 0x02, 0x77, 0xf6, 0xd6, 0xdd, 0x08, 0x0a,
+- 0x81, 0xe1, 0x86, 0x89, 0x3e, 0x56, 0x10, 0x3c,
+- 0xba, 0xd7, 0x81, 0x8c, 0x08, 0xbc, 0x8b, 0xe2,
+- 0x53, 0xec, 0xa7, 0x89, 0xee, 0xc8, 0x56, 0xb5,
+- 0x36, 0x2c, 0xb2, 0x03, 0xba, 0x99, 0xdd, 0x7c,
+- 0x48, 0xa0, 0xb0, 0xbc, 0x91, 0x33, 0xe9, 0xa8,
+- 0xcb, 0xcd, 0xcf, 0x59, 0x5f, 0x1f, 0x15, 0xe2,
+- 0x56, 0xf5, 0x4e, 0x01, 0x35, 0x27, 0x45, 0x77,
+- 0x47, 0xc8, 0xbc, 0xcb, 0x7e, 0x39, 0xc1, 0x97,
+- 0x28, 0xd3, 0x84, 0xfc, 0x2c, 0x3e, 0xc8, 0xad,
+- 0x9c, 0xf8, 0x8a, 0x61, 0x9c, 0x28, 0xaa, 0xc5,
+- 0x99, 0x20, 0x43, 0x85, 0x9d, 0xa5, 0xe2, 0x8b,
+- 0xb8, 0xae, 0xeb, 0xd0, 0x32, 0x0d, 0x52, 0x78,
+- 0x09, 0x56, 0x3f, 0xc7, 0xd8, 0x7e, 0x26, 0xfc,
+- 0x37, 0xfb, 0x6f, 0x04, 0xfc, 0xfa, 0x92, 0x10,
+- 0xac, 0xf8, 0x3e, 0x21, 0xdc, 0x8c, 0x21, 0x16,
+- 0x7d, 0x67, 0x6e, 0xf6, 0xcd, 0xda, 0xb6, 0x98,
+- 0x23, 0xab, 0x23, 0x3c, 0xb2, 0x10, 0xa0, 0x53,
+- 0x5a, 0x56, 0x9f, 0xc5, 0xd0, 0xff, 0xbb, 0xe4,
+- 0x98, 0x3c, 0x69, 0x1e, 0xdb, 0x38, 0x8f, 0x7e,
+- 0x0f, 0xd2, 0x98, 0x88, 0x81, 0x8b, 0x45, 0x67,
+- 0xea, 0x33, 0xf1, 0xeb, 0xe9, 0x97, 0x55, 0x2e,
+- 0xd9, 0xaa, 0xeb, 0x5a, 0xec, 0xda, 0xe1, 0x68,
+- 0xa8, 0x9d, 0x3c, 0x84, 0x7c, 0x05, 0x3d, 0x62,
+- 0x87, 0x8f, 0x03, 0x21, 0x28, 0x95, 0x0c, 0x89,
+- 0x25, 0x22, 0x4a, 0xb0, 0x93, 0xa9, 0x50, 0xa2,
+- 0x2f, 0x57, 0x6e, 0x18, 0x42, 0x19, 0x54, 0x0c,
+- 0x55, 0x67, 0xc6, 0x11, 0x49, 0xf4, 0x5c, 0xd2,
+- 0xe9, 0x3d, 0xdd, 0x8b, 0x48, 0x71, 0x21, 0x00,
+- 0xc3, 0x9a, 0x6c, 0x85, 0x74, 0x28, 0x83, 0x4a,
+- 0x1b, 0x31, 0x05, 0xe1, 0x06, 0x92, 0xe7, 0xda,
+- 0x85, 0x73, 0x78, 0x45, 0x20, 0x7f, 0xae, 0x13,
+- 0x7c, 0x33, 0x06, 0x22, 0xf4, 0x83, 0xf9, 0x35,
+- 0x3f, 0x6c, 0x71, 0xa8, 0x4e, 0x48, 0xbe, 0x9b,
+- 0xce, 0x8a, 0xba, 0xda, 0xbe, 0x28, 0x08, 0xf7,
+- 0xe2, 0x14, 0x8c, 0x71, 0xea, 0x72, 0xf9, 0x33,
+- 0xf2, 0x88, 0x3f, 0xd7, 0xbb, 0x69, 0x6c, 0x29,
+- 0x19, 0xdc, 0x84, 0xce, 0x1f, 0x12, 0x4f, 0xc8,
+- 0xaf, 0xa5, 0x04, 0xba, 0x5a, 0xab, 0xb0, 0xd9,
+- 0x14, 0x1f, 0x6c, 0x68, 0x98, 0x39, 0x89, 0x7a,
+- 0xd9, 0xd8, 0x2f, 0xdf, 0xa8, 0x47, 0x4a, 0x25,
+- 0xe2, 0xfb, 0x33, 0xf4, 0x59, 0x78, 0xe1, 0x68,
+- 0x85, 0xcf, 0xfe, 0x59, 0x20, 0xd4, 0x05, 0x1d,
+- 0x80, 0x99, 0xae, 0xbc, 0xca, 0xae, 0x0f, 0x2f,
+- 0x65, 0x43, 0x34, 0x8e, 0x7e, 0xac, 0xd3, 0x93,
+- 0x2f, 0xac, 0x6d, 0x14, 0x3d, 0x02, 0x07, 0x70,
+- 0x9d, 0xa4, 0xf3, 0x1b, 0x5c, 0x36, 0xfc, 0x01,
+- 0x73, 0x34, 0x85, 0x0c, 0x6c, 0xd6, 0xf1, 0xbd,
+- 0x3f, 0xdf, 0xee, 0xf5, 0xd9, 0xba, 0x56, 0xef,
+- 0xf4, 0x9b, 0x6b, 0xee, 0x9f, 0x5a, 0x78, 0x6d,
+- 0x32, 0x19, 0xf4, 0xf7, 0xf8, 0x4c, 0x69, 0x0b,
+- 0x4b, 0xbc, 0xbb, 0xb7, 0xf2, 0x85, 0xaf, 0x70,
+- 0x75, 0x24, 0x6c, 0x54, 0xa7, 0x0e, 0x4d, 0x1d,
+- 0x01, 0xbf, 0x08, 0xac, 0xcf, 0x7f, 0x2c, 0xe3,
+- 0x14, 0x89, 0x5e, 0x70, 0x5a, 0x99, 0x92, 0xcd,
+- 0x01, 0x84, 0xc8, 0xd2, 0xab, 0xe5, 0x4f, 0x58,
+- 0xe7, 0x0f, 0x2f, 0x0e, 0xff, 0x68, 0xea, 0xfd,
+- 0x15, 0xb3, 0x17, 0xe6, 0xb0, 0xe7, 0x85, 0xd8,
+- 0x23, 0x2e, 0x05, 0xc7, 0xc9, 0xc4, 0x46, 0x1f,
+- 0xe1, 0x9e, 0x49, 0x20, 0x23, 0x24, 0x4d, 0x7e,
+- 0x29, 0x65, 0xff, 0xf4, 0xb6, 0xfd, 0x1a, 0x85,
+- 0xc4, 0x16, 0xec, 0xfc, 0xea, 0x7b, 0xd6, 0x2c,
+- 0x43, 0xf8, 0xb7, 0xbf, 0x79, 0xc0, 0x85, 0xcd,
+- 0xef, 0xe1, 0x98, 0xd3, 0xa5, 0xf7, 0x90, 0x8c,
+- 0xe9, 0x7f, 0x80, 0x6b, 0xd2, 0xac, 0x4c, 0x30,
+- 0xa7, 0xc6, 0x61, 0x6c, 0xd2, 0xf9, 0x2c, 0xff,
+- 0x30, 0xbc, 0x22, 0x81, 0x7d, 0x93, 0x12, 0xe4,
+- 0x0a, 0xcd, 0xaf, 0xdd, 0xe8, 0xab, 0x0a, 0x1e,
+- 0x13, 0xa4, 0x27, 0xc3, 0x5f, 0xf7, 0x4b, 0xbb,
+- 0x37, 0x09, 0x4b, 0x91, 0x6f, 0x92, 0x4f, 0xaf,
+- 0x52, 0xee, 0xdf, 0xef, 0x09, 0x6f, 0xf7, 0x5c,
+- 0x6e, 0x12, 0x17, 0x72, 0x63, 0x57, 0xc7, 0xba,
+- 0x3b, 0x6b, 0x38, 0x32, 0x73, 0x1b, 0x9c, 0x80,
+- 0xc1, 0x7a, 0xc6, 0xcf, 0xcd, 0x35, 0xc0, 0x6b,
+- 0x31, 0x1a, 0x6b, 0xe9, 0xd8, 0x2c, 0x29, 0x3f,
+- 0x96, 0xfb, 0xb6, 0xcd, 0x13, 0x91, 0x3b, 0xc2,
+- 0xd2, 0xa3, 0x31, 0x8d, 0xa4, 0xcd, 0x57, 0xcd,
+- 0x13, 0x3d, 0x64, 0xfd, 0x06, 0xce, 0xe6, 0xdc,
+- 0x0c, 0x24, 0x43, 0x31, 0x40, 0x57, 0xf1, 0x72,
+- 0x17, 0xe3, 0x3a, 0x63, 0x6d, 0x35, 0xcf, 0x5d,
+- 0x97, 0x40, 0x59, 0xdd, 0xf7, 0x3c, 0x02, 0xf7,
+- 0x1c, 0x7e, 0x05, 0xbb, 0xa9, 0x0d, 0x01, 0xb1,
+- 0x8e, 0xc0, 0x30, 0xa9, 0x53, 0x24, 0xc9, 0x89,
+- 0x84, 0x6d, 0xaa, 0xd0, 0xcd, 0x91, 0xc2, 0x4d,
+- 0x91, 0xb0, 0x89, 0xe2, 0xbf, 0x83, 0x44, 0xaa,
+- 0x28, 0x72, 0x23, 0xa0, 0xc2, 0xad, 0xad, 0x1c,
+- 0xfc, 0x3f, 0x09, 0x7a, 0x0b, 0xdc, 0xc5, 0x1b,
+- 0x87, 0x13, 0xc6, 0x5b, 0x59, 0x8d, 0xf2, 0xc8,
+- 0xaf, 0xdf, 0x11, 0x95,
+- },
++ .result =
++ "\xb5\x81\xf5\x64\x18\x73\xe3\xf0"
++ "\x4c\x13\xf2\x77\x18\x60\x65\x5e"
++ "\x29\x01\xce\x98\x55\x53\xf9\x0c"
++ "\x2a\x08\xd5\x09\xb3\x57\x55\x56"
++ "\xc5\xe9\x56\x90\xcb\x6a\xa3\xc0"
++ "\xff\xc4\x79\xb4\xd2\x97\x5d\xc4"
++ "\x43\xd1\xfe\x94\x7b\x88\x06\x5a"
++ "\xb2\x9e\x2c\xfc\x44\x03\xb7\x90"
++ "\xa0\xc1\xba\x6a\x33\xb8\xc7\xb2"
++ "\x9d\xe1\x12\x4f\xc0\x64\xd4\x01"
++ "\xfe\x8c\x7a\x66\xf7\xe6\x5a\x91"
++ "\xbb\xde\x56\x86\xab\x65\x21\x30"
++ "\x00\x84\x65\x24\xa5\x7d\x85\xb4"
++ "\xe3\x17\xed\x3a\xb7\x6f\xb4\x0b"
++ "\x0b\xaf\x15\xae\x5a\x8f\xf2\x0c"
++ "\x2f\x27\xf4\x09\xd8\xd2\x96\xb7"
++ "\x71\xf2\xc5\x99\x4d\x7e\x7f\x75"
++ "\x77\x89\x30\x8b\x59\xdb\xa2\xb2"
++ "\xa0\xf3\x19\x39\x2b\xc5\x7e\x3f"
++ "\x4f\xd9\xd3\x56\x28\x97\x44\xdc"
++ "\xc0\x8b\x77\x24\xd9\x52\xe7\xc5"
++ "\xaf\xf6\x7d\x59\xb2\x44\x05\x1d"
++ "\xb1\xb0\x11\xa5\x0f\xec\x33\xe1"
++ "\x6d\x1b\x4e\x1f\xff\x57\x91\xb4"
++ "\x5b\x9a\x96\xc5\x53\xbc\xae\x20"
++ "\x3c\xbb\x14\xe2\xe8\x22\x33\xc1"
++ "\x5e\x76\x9e\x46\x99\xf6\x2a\x15"
++ "\xc6\x97\x02\xa0\x66\x43\xd1\xa6"
++ "\x31\xa6\x9f\xfb\xf4\xd3\x69\xe5"
++ "\xcd\x76\x95\xb8\x7a\x82\x7f\x21"
++ "\x45\xff\x3f\xce\x55\xf6\x95\x10"
++ "\x08\x77\x10\x43\xc6\xf3\x09\xe5"
++ "\x68\xe7\x3c\xad\x00\x52\x45\x0d"
++ "\xfe\x2d\xc6\xc2\x94\x8c\x12\x1d"
++ "\xe6\x25\xae\x98\x12\x8e\x19\x9c"
++ "\x81\x68\xb1\x11\xf6\x69\xda\xe3"
++ "\x62\x08\x18\x7a\x25\x49\x28\xac"
++ "\xba\x71\x12\x0b\xe4\xa2\xe5\xc7"
++ "\x5d\x8e\xec\x49\x40\x21\xbf\x5a"
++ "\x98\xf3\x02\x68\x55\x03\x7f\x8a"
++ "\xe5\x94\x0c\x32\x5c\x07\x82\x63"
++ "\xaf\x6f\x91\x40\x84\x8e\x52\x25"
++ "\xd0\xb0\x29\x53\x05\xe2\x50\x7a"
++ "\x34\xeb\xc9\x46\x20\xa8\x3d\xde"
++ "\x7f\x16\x5f\x36\xc5\x2e\xdc\xd1"
++ "\x15\x47\xc7\x50\x40\x6d\x91\xc5"
++ "\xe7\x93\x95\x1a\xd3\x57\xbc\x52"
++ "\x33\xee\x14\x19\x22\x52\x89\xa7"
++ "\x4a\x25\x56\x77\x4b\xca\xcf\x0a"
++ "\xe1\xf5\x35\x85\x30\x7e\x59\x4a"
++ "\xbd\x14\x5b\xdf\xe3\x46\xcb\xac"
++ "\x1f\x6c\x96\x0e\xf4\x81\xd1\x99"
++ "\xca\x88\x63\x3d\x02\x58\x6b\xa9"
++ "\xe5\x9f\xb3\x00\xb2\x54\xc6\x74"
++ "\x1c\xbf\x46\xab\x97\xcc\xf8\x54"
++ "\x04\x07\x08\x52\xe6\xc0\xda\x93"
++ "\x74\x7d\x93\x99\x5d\x78\x68\xa6"
++ "\x2e\x6b\xd3\x6a\x69\xcc\x12\x6b"
++ "\xd4\xc7\xa5\xc6\xe7\xf6\x03\x04"
++ "\x5d\xcd\x61\x5e\x17\x40\xdc\xd1"
++ "\x5c\xf5\x08\xdf\x5c\x90\x85\xa4"
++ "\xaf\xf6\x78\xbb\x0d\xf1\xf4\xa4"
++ "\x54\x26\x72\x9e\x61\xfa\x86\xcf"
++ "\xe8\x9e\xa1\xe0\xc7\x48\x23\xae"
++ "\x5a\x90\xae\x75\x0a\x74\x18\x89"
++ "\x05\xb1\x92\xb2\x7f\xd0\x1b\xa6"
++ "\x62\x07\x25\x01\xc7\xc2\x4f\xf9"
++ "\xe8\xfe\x63\x95\x80\x07\xb4\x26"
++ "\xcc\xd1\x26\xb6\xc4\x3f\x9e\xcb"
++ "\x8e\x3b\x2e\x44\x16\xd3\x10\x9a"
++ "\x95\x08\xeb\xc8\xcb\xeb\xbf\x6f"
++ "\x0b\xcd\x1f\xc8\xca\x86\xaa\xec"
++ "\x33\xe6\x69\xf4\x45\x25\x86\x3a"
++ "\x22\x94\x4f\x00\x23\x6a\x44\xc2"
++ "\x49\x97\x33\xab\x36\x14\x0a\x70"
++ "\x24\xc3\xbe\x04\x3b\x79\xa0\xf9"
++ "\xb8\xe7\x76\x29\x22\x83\xd7\xf2"
++ "\x94\xf4\x41\x49\xba\x5f\x7b\x07"
++ "\xb5\xfb\xdb\x03\x1a\x9f\xb6\x4c"
++ "\xc2\x2e\x37\x40\x49\xc3\x38\x16"
++ "\xe2\x4f\x77\x82\xb0\x68\x4c\x71"
++ "\x1d\x57\x61\x9c\xd9\x4e\x54\x99"
++ "\x47\x13\x28\x73\x3c\xbb\x00\x90"
++ "\xf3\x4d\xc9\x0e\xfd\xe7\xb1\x71"
++ "\xd3\x15\x79\xbf\xcc\x26\x2f\xbd"
++ "\xad\x6c\x50\x69\x6c\x3e\x6d\x80"
++ "\x9a\xea\x78\xaf\x19\xb2\x0d\x4d"
++ "\xad\x04\x07\xae\x22\x90\x4a\x93"
++ "\x32\x0e\x36\x9b\x1b\x46\xba\x3b"
++ "\xb4\xac\xc6\xd1\xa2\x31\x53\x3b"
++ "\x2a\x3d\x45\xfe\x03\x61\x10\x85"
++ "\x17\x69\xa6\x78\xcc\x6c\x87\x49"
++ "\x53\xf9\x80\x10\xde\x80\xa2\x41"
++ "\x6a\xc3\x32\x02\xad\x6d\x3c\x56"
++ "\x00\x71\x51\x06\xa7\xbd\xfb\xef"
++ "\x3c\xb5\x9f\xfc\x48\x7d\x53\x7c"
++ "\x66\xb0\x49\x23\xc4\x47\x10\x0e"
++ "\xe5\x6c\x74\x13\xe6\xc5\x3f\xaa"
++ "\xde\xff\x07\x44\xdd\x56\x1b\xad"
++ "\x09\x77\xfb\x5b\x12\xb8\x0d\x38"
++ "\x17\x37\x35\x7b\x9b\xbc\xfe\xd4"
++ "\x7e\x8b\xda\x7e\x5b\x04\xa7\x22"
++ "\xa7\x31\xa1\x20\x86\xc7\x1b\x99"
++ "\xdb\xd1\x89\xf4\x94\xa3\x53\x69"
++ "\x8d\xe7\xe8\x74\x11\x8d\x74\xd6"
++ "\x07\x37\x91\x9f\xfd\x67\x50\x3a"
++ "\xc9\xe1\xf4\x36\xd5\xa0\x47\xd1"
++ "\xf9\xe5\x39\xa3\x31\xac\x07\x36"
++ "\x23\xf8\x66\x18\x14\x28\x34\x0f"
++ "\xb8\xd0\xe7\x29\xb3\x04\x4b\x55"
++ "\x01\x41\xb2\x75\x8d\xcb\x96\x85"
++ "\x3a\xfb\xab\x2b\x9e\xfa\x58\x20"
++ "\x44\x1f\xc0\x14\x22\x75\x61\xe8"
++ "\xaa\x19\xcf\xf1\x82\x56\xf4\xd7"
++ "\x78\x7b\x3d\x5f\xb3\x9e\x0b\x8a"
++ "\x57\x50\xdb\x17\x41\x65\x4d\xa3"
++ "\x02\xc9\x9c\x9c\x53\xfb\x39\x39"
++ "\x9b\x1d\x72\x24\xda\xb7\x39\xbe"
++ "\x13\x3b\xfa\x29\xda\x9e\x54\x64"
++ "\x6e\xba\xd8\xa1\xcb\xb3\x36\xfa"
++ "\xcb\x47\x85\xe9\x61\x38\xbc\xbe"
++ "\xc5\x00\x38\x2a\x54\xf7\xc4\xb9"
++ "\xb3\xd3\x7b\xa0\xa0\xf8\x72\x7f"
++ "\x8c\x8e\x82\x0e\xc6\x1c\x75\x9d"
++ "\xca\x8e\x61\x87\xde\xad\x80\xd2"
++ "\xf5\xf9\x80\xef\x15\x75\xaf\xf5"
++ "\x80\xfb\xff\x6d\x1e\x25\xb7\x40"
++ "\x61\x6a\x39\x5a\x6a\xb5\x31\xab"
++ "\x97\x8a\x19\x89\x44\x40\xc0\xa6"
++ "\xb4\x4e\x30\x32\x7b\x13\xe7\x67"
++ "\xa9\x8b\x57\x04\xc2\x01\xa6\xf4"
++ "\x28\x99\xad\x2c\x76\xa3\x78\xc2"
++ "\x4a\xe6\xca\x5c\x50\x6a\xc1\xb0"
++ "\x62\x4b\x10\x8e\x7c\x17\x43\xb3"
++ "\x17\x66\x1c\x3e\x8d\x69\xf0\x5a"
++ "\x71\xf5\x97\xdc\xd1\x45\xdd\x28"
++ "\xf3\x5d\xdf\x53\x7b\x11\xe5\xbc"
++ "\x4c\xdb\x1b\x51\x6b\xe9\xfb\x3d"
++ "\xc1\xc3\x2c\xb9\x71\xf5\xb6\xb2"
++ "\x13\x36\x79\x80\x53\xe8\xd3\xa6"
++ "\x0a\xaf\xfd\x56\x97\xf7\x40\x8e"
++ "\x45\xce\xf8\xb0\x9e\x5c\x33\x82"
++ "\xb0\x44\x56\xfc\x05\x09\xe9\x2a"
++ "\xac\x26\x80\x14\x1d\xc8\x3a\x35"
++ "\x4c\x82\x97\xfd\x76\xb7\xa9\x0a"
++ "\x35\x58\x79\x8e\x0f\x66\xea\xaf"
++ "\x51\x6c\x09\xa9\x6e\x9b\xcb\x9a"
++ "\x31\x47\xa0\x2f\x7c\x71\xb4\x4a"
++ "\x11\xaa\x8c\x66\xc5\x64\xe6\x3a"
++ "\x54\xda\x24\x6a\xc4\x41\x65\x46"
++ "\x82\xa0\x0a\x0f\x5f\xfb\x25\xd0"
++ "\x2c\x91\xa7\xee\xc4\x81\x07\x86"
++ "\x75\x5e\x33\x69\x97\xe4\x2c\xa8"
++ "\x9d\x9f\x0b\x6a\xbe\xad\x98\xda"
++ "\x6d\x94\x41\xda\x2c\x1e\x89\xc4"
++ "\xc2\xaf\x1e\x00\x05\x0b\x83\x60"
++ "\xbd\x43\xea\x15\x23\x7f\xb9\xac"
++ "\xee\x4f\x2c\xaf\x2a\xf3\xdf\xd0"
++ "\xf3\x19\x31\xbb\x4a\x74\x84\x17"
++ "\x52\x32\x2c\x7d\x61\xe4\xcb\xeb"
++ "\x80\x38\x15\x52\xcb\x6f\xea\xe5"
++ "\x73\x9c\xd9\x24\x69\xc6\x95\x32"
++ "\x21\xc8\x11\xe4\xdc\x36\xd7\x93"
++ "\x38\x66\xfb\xb2\x7f\x3a\xb9\xaf"
++ "\x31\xdd\x93\x75\x78\x8a\x2c\x94"
++ "\x87\x1a\x58\xec\x9e\x7d\x4d\xba"
++ "\xe1\xe5\x4d\xfc\xbc\xa4\x2a\x14"
++ "\xef\xcc\xa7\xec\xab\x43\x09\x18"
++ "\xd3\xab\x68\xd1\x07\x99\x44\x47"
++ "\xd6\x83\x85\x3b\x30\xea\xa9\x6b"
++ "\x63\xea\xc4\x07\xfb\x43\x2f\xa4"
++ "\xaa\xb0\xab\x03\x89\xce\x3f\x8c"
++ "\x02\x7c\x86\x54\xbc\x88\xaf\x75"
++ "\xd2\xdc\x63\x17\xd3\x26\xf6\x96"
++ "\xa9\x3c\xf1\x61\x8c\x11\x18\xcc"
++ "\xd6\xea\x5b\xe2\xcd\xf0\xf1\xb2"
++ "\xe5\x35\x90\x1f\x85\x4c\x76\x5b"
++ "\x66\xce\x44\xa4\x32\x9f\xe6\x7b"
++ "\x71\x6e\x9f\x58\x15\x67\x72\x87"
++ "\x64\x8e\x3a\x44\x45\xd4\x76\xfa"
++ "\xc2\xf6\xef\x85\x05\x18\x7a\x9b"
++ "\xba\x41\x54\xac\xf0\xfc\x59\x12"
++ "\x3f\xdf\xa0\xe5\x8a\x65\xfd\x3a"
++ "\x62\x8d\x83\x2c\x03\xbe\x05\x76"
++ "\x2e\x53\x49\x97\x94\x33\xae\x40"
++ "\x81\x15\xdb\x6e\xad\xaa\xf5\x4b"
++ "\xe3\x98\x70\xdf\xe0\x7c\xcd\xdb"
++ "\x02\xd4\x7d\x2f\xc1\xe6\xb4\xf3"
++ "\xd7\x0d\x7a\xd9\x23\x9e\x87\x2d"
++ "\xce\x87\xad\xcc\x72\x05\x00\x29"
++ "\xdc\x73\x7f\x64\xc1\x15\x0e\xc2"
++ "\xdf\xa7\x5f\xeb\x41\xa1\xcd\xef"
++ "\x5c\x50\x79\x2a\x56\x56\x71\x8c"
++ "\xac\xc0\x79\x50\x69\xca\x59\x32"
++ "\x65\xf2\x54\xe4\x52\x38\x76\xd1"
++ "\x5e\xde\x26\x9e\xfb\x75\x2e\x11"
++ "\xb5\x10\xf4\x17\x73\xf5\x89\xc7"
++ "\x4f\x43\x5c\x8e\x7c\xb9\x05\x52"
++ "\x24\x40\x99\xfe\x9b\x85\x0b\x6c"
++ "\x22\x3e\x8b\xae\x86\xa1\xd2\x79"
++ "\x05\x68\x6b\xab\xe3\x41\x49\xed"
++ "\x15\xa1\x8d\x40\x2d\x61\xdf\x1a"
++ "\x59\xc9\x26\x8b\xef\x30\x4c\x88"
++ "\x4b\x10\xf8\x8d\xa6\x92\x9f\x4b"
++ "\xf3\xc4\x53\x0b\x89\x5d\x28\x92"
++ "\xcf\x78\xb2\xc0\x5d\xed\x7e\xfc"
++ "\xc0\x12\x23\x5f\x5a\x78\x86\x43"
++ "\x6e\x27\xf7\x5a\xa7\x6a\xed\x19"
++ "\x04\xf0\xb3\x12\xd1\xbd\x0e\x89"
++ "\x6e\xbc\x96\xa8\xd8\x49\x39\x9f"
++ "\x7e\x67\xf0\x2e\x3e\x01\xa9\xba"
++ "\xec\x8b\x62\x8e\xcb\x4a\x70\x43"
++ "\xc7\xc2\xc4\xca\x82\x03\x73\xe9"
++ "\x11\xdf\xcf\x54\xea\xc9\xb0\x95"
++ "\x51\xc0\x13\x3d\x92\x05\xfa\xf4"
++ "\xa9\x34\xc8\xce\x6c\x3d\x54\xcc"
++ "\xc4\xaf\xf1\xdc\x11\x44\x26\xa2"
++ "\xaf\xf1\x85\x75\x7d\x03\x61\x68"
++ "\x4e\x78\xc6\x92\x7d\x86\x7d\x77"
++ "\xdc\x71\x72\xdb\xc6\xae\xa1\xcb"
++ "\x70\x9a\x0b\x19\xbe\x4a\x6c\x2a"
++ "\xe2\xba\x6c\x64\x9a\x13\x28\xdf"
++ "\x85\x75\xe6\x43\xf6\x87\x08\x68"
++ "\x6e\xba\x6e\x79\x9f\x04\xbc\x23"
++ "\x50\xf6\x33\x5c\x1f\x24\x25\xbe"
++ "\x33\x47\x80\x45\x56\xa3\xa7\xd7"
++ "\x7a\xb1\x34\x0b\x90\x3c\x9c\xad"
++ "\x44\x5f\x9e\x0e\x9d\xd4\xbd\x93"
++ "\x5e\xfa\x3c\xe0\xb0\xd9\xed\xf3"
++ "\xd6\x2e\xff\x24\xd8\x71\x6c\xed"
++ "\xaf\x55\xeb\x22\xac\x93\x68\x32"
++ "\x05\x5b\x47\xdd\xc6\x4a\xcb\xc7"
++ "\x10\xe1\x3c\x92\x1a\xf3\x23\x78"
++ "\x2b\xa1\xd2\x80\xf4\x12\xb1\x20"
++ "\x8f\xff\x26\x35\xdd\xfb\xc7\x4e"
++ "\x78\xf1\x2d\x50\x12\x77\xa8\x60"
++ "\x7c\x0f\xf5\x16\x2f\x63\x70\x2a"
++ "\xc0\x96\x80\x4e\x0a\xb4\x93\x35"
++ "\x5d\x1d\x3f\x56\xf7\x2f\xbb\x90"
++ "\x11\x16\x8f\xa2\xec\x47\xbe\xac"
++ "\x56\x01\x26\x56\xb1\x8c\xb2\x10"
++ "\xf9\x1a\xca\xf5\xd1\xb7\x39\x20"
++ "\x63\xf1\x69\x20\x4f\x13\x12\x1f"
++ "\x5b\x65\xfc\x98\xf7\xc4\x7a\xbe"
++ "\xf7\x26\x4d\x2b\x84\x7b\x42\xad"
++ "\xd8\x7a\x0a\xb4\xd8\x74\xbf\xc1"
++ "\xf0\x6e\xb4\x29\xa3\xbb\xca\x46"
++ "\x67\x70\x6a\x2d\xce\x0e\xa2\x8a"
++ "\xa9\x87\xbf\x05\xc4\xc1\x04\xa3"
++ "\xab\xd4\x45\x43\x8c\xb6\x02\xb0"
++ "\x41\xc8\xfc\x44\x3d\x59\xaa\x2e"
++ "\x44\x21\x2a\x8d\x88\x9d\x57\xf4"
++ "\xa0\x02\x77\xb8\xa6\xa0\xe6\x75"
++ "\x5c\x82\x65\x3e\x03\x5c\x29\x8f"
++ "\x38\x55\xab\x33\x26\xef\x9f\x43"
++ "\x52\xfd\x68\xaf\x36\xb4\xbb\x9a"
++ "\x58\x09\x09\x1b\xc3\x65\x46\x46"
++ "\x1d\xa7\x94\x18\x23\x50\x2c\xca"
++ "\x2c\x55\x19\x97\x01\x9d\x93\x3b"
++ "\x63\x86\xf2\x03\x67\x45\xd2\x72"
++ "\x28\x52\x6c\xf4\xe3\x1c\xb5\x11"
++ "\x13\xf1\xeb\x21\xc7\xd9\x56\x82"
++ "\x2b\x82\x39\xbd\x69\x54\xed\x62"
++ "\xc3\xe2\xde\x73\xd4\x6a\x12\xae"
++ "\x13\x21\x7f\x4b\x5b\xfc\xbf\xe8"
++ "\x2b\xbe\x56\xba\x68\x8b\x9a\xb1"
++ "\x6e\xfa\xbf\x7e\x5a\x4b\xf1\xac"
++ "\x98\x65\x85\xd1\x93\x53\xd3\x7b"
++ "\x09\xdd\x4b\x10\x6d\x84\xb0\x13"
++ "\x65\xbd\xcf\x52\x09\xc4\x85\xe2"
++ "\x84\x74\x15\x65\xb7\xf7\x51\xaf"
++ "\x55\xad\xa4\xd1\x22\x54\x70\x94"
++ "\xa0\x1c\x90\x41\xfd\x99\xd7\x5a"
++ "\x31\xef\xaa\x25\xd0\x7f\x4f\xea"
++ "\x1d\x55\x42\xe5\x49\xb0\xd0\x46"
++ "\x62\x36\x43\xb2\x82\x15\x75\x50"
++ "\xa4\x72\xeb\x54\x27\x1f\x8a\xe4"
++ "\x7d\xe9\x66\xc5\xf1\x53\xa4\xd1"
++ "\x0c\xeb\xb8\xf8\xbc\xd4\xe2\xe7"
++ "\xe1\xf8\x4b\xcb\xa9\xa1\xaf\x15"
++ "\x83\xcb\x72\xd0\x33\x79\x00\x2d"
++ "\x9f\xd7\xf1\x2e\x1e\x10\xe4\x45"
++ "\xc0\x75\x3a\x39\xea\x68\xf7\x5d"
++ "\x1b\x73\x8f\xe9\x8e\x0f\x72\x47"
++ "\xae\x35\x0a\x31\x7a\x14\x4d\x4a"
++ "\x6f\x47\xf7\x7e\x91\x6e\x74\x8b"
++ "\x26\x47\xf9\xc3\xf9\xde\x70\xf5"
++ "\x61\xab\xa9\x27\x9f\x82\xe4\x9c"
++ "\x89\x91\x3f\x2e\x6a\xfd\xb5\x49"
++ "\xe9\xfd\x59\x14\x36\x49\x40\x6d"
++ "\x32\xd8\x85\x42\xf3\xa5\xdf\x0c"
++ "\xa8\x27\xd7\x54\xe2\x63\x2f\xf2"
++ "\x7e\x8b\x8b\xe7\xf1\x9a\x95\x35"
++ "\x43\xdc\x3a\xe4\xb6\xf4\xd0\xdf"
++ "\x9c\xcb\x94\xf3\x21\xa0\x77\x50"
++ "\xe2\xc6\xc4\xc6\x5f\x09\x64\x5b"
++ "\x92\x90\xd8\xe1\xd1\xed\x4b\x42"
++ "\xd7\x37\xaf\x65\x3d\x11\x39\xb6"
++ "\x24\x8a\x60\xae\xd6\x1e\xbf\x0e"
++ "\x0d\xd7\xdc\x96\x0e\x65\x75\x4e"
++ "\x29\x06\x9d\xa4\x51\x3a\x10\x63"
++ "\x8f\x17\x07\xd5\x8e\x3c\xf4\x28"
++ "\x00\x5a\x5b\x05\x19\xd8\xc0\x6c"
++ "\xe5\x15\xe4\x9c\x9d\x71\x9d\x5e"
++ "\x94\x29\x1a\xa7\x80\xfa\x0e\x33"
++ "\x03\xdd\xb7\x3e\x9a\xa9\x26\x18"
++ "\x37\xa9\x64\x08\x4d\x94\x5a\x88"
++ "\xca\x35\xce\x81\x02\xe3\x1f\x1b"
++ "\x89\x1a\x77\x85\xe3\x41\x6d\x32"
++ "\x42\x19\x23\x7d\xc8\x73\xee\x25"
++ "\x85\x0d\xf8\x31\x25\x79\x1b\x6f"
++ "\x79\x25\xd2\xd8\xd4\x23\xfd\xf7"
++ "\x82\x36\x6a\x0c\x46\x22\x15\xe9"
++ "\xff\x72\x41\x91\x91\x7d\x3a\xb7"
++ "\xdd\x65\x99\x70\xf6\x8d\x84\xf8"
++ "\x67\x15\x20\x11\xd6\xb2\x55\x7b"
++ "\xdb\x87\xee\xef\x55\x89\x2a\x59"
++ "\x2b\x07\x8f\x43\x8a\x59\x3c\x01"
++ "\x8b\x65\x54\xa1\x66\xd5\x38\xbd"
++ "\xc6\x30\xa9\xcc\x49\xb6\xa8\x1b"
++ "\xb8\xc0\x0e\xe3\x45\x28\xe2\xff"
++ "\x41\x9f\x7e\x7c\xd1\xae\x9e\x25"
++ "\x3f\x4c\x7c\x7c\xf4\xa8\x26\x4d"
++ "\x5c\xfd\x4b\x27\x18\xf9\x61\x76"
++ "\x48\xba\x0c\x6b\xa9\x4d\xfc\xf5"
++ "\x3b\x35\x7e\x2f\x4a\xa9\xc2\x9a"
++ "\xae\xab\x86\x09\x89\xc9\xc2\x40"
++ "\x39\x2c\x81\xb3\xb8\x17\x67\xc2"
++ "\x0d\x32\x4a\x3a\x67\x81\xd7\x1a"
++ "\x34\x52\xc5\xdb\x0a\xf5\x63\x39"
++ "\xea\x1f\xe1\x7c\xa1\x9e\xc1\x35"
++ "\xe3\xb1\x18\x45\x67\xf9\x22\x38"
++ "\x95\xd9\x34\x34\x86\xc6\x41\x94"
++ "\x15\xf9\x5b\x41\xa6\x87\x8b\xf8"
++ "\xd5\xe1\x1b\xe2\x5b\xf3\x86\x10"
++ "\xff\xe6\xae\x69\x76\xbc\x0d\xb4"
++ "\x09\x90\x0c\xa2\x65\x0c\xad\x74"
++ "\xf5\xd7\xff\xda\xc1\xce\x85\xbe"
++ "\x00\xa7\xff\x4d\x2f\x65\xd3\x8c"
++ "\x86\x2d\x05\xe8\xed\x3e\x6b\x8b"
++ "\x0f\x3d\x83\x8c\xf1\x1d\x5b\x96"
++ "\x2e\xb1\x9c\xc2\x98\xe1\x70\xb9"
++ "\xba\x5c\x8a\x43\xd6\x34\xa7\x2d"
++ "\xc9\x92\xae\xf2\xa5\x7b\x05\x49"
++ "\xa7\x33\x34\x86\xca\xe4\x96\x23"
++ "\x76\x5b\xf2\xc6\xf1\x51\x28\x42"
++ "\x7b\xcc\x76\x8f\xfa\xa2\xad\x31"
++ "\xd4\xd6\x7a\x6d\x25\x25\x54\xe4"
++ "\x3f\x50\x59\xe1\x5c\x05\xb7\x27"
++ "\x48\xbf\x07\xec\x1b\x13\xbe\x2b"
++ "\xa1\x57\x2b\xd5\xab\xd7\xd0\x4c"
++ "\x1e\xcb\x71\x9b\xc5\x90\x85\xd3"
++ "\xde\x59\xec\x71\xeb\x89\xbb\xd0"
++ "\x09\x50\xe1\x16\x3f\xfd\x1c\x34"
++ "\xc3\x1c\xa1\x10\x77\x53\x98\xef"
++ "\xf2\xfd\xa5\x01\x59\xc2\x9b\x26"
++ "\xc7\x42\xd9\x49\xda\x58\x2b\x6e"
++ "\x9f\x53\x19\x76\x7e\xd9\xc9\x0e"
++ "\x68\xc8\x7f\x51\x22\x42\xef\x49"
++ "\xa4\x55\xb6\x36\xac\x09\xc7\x31"
++ "\x88\x15\x4b\x2e\x8f\x3a\x08\xf7"
++ "\xd8\xf7\xa8\xc5\xa9\x33\xa6\x45"
++ "\xe4\xc4\x94\x76\xf3\x0d\x8f\x7e"
++ "\xc8\xf6\xbc\x23\x0a\xb6\x4c\xd3"
++ "\x6a\xcd\x36\xc2\x90\x5c\x5c\x3c"
++ "\x65\x7b\xc2\xd6\xcc\xe6\x0d\x87"
++ "\x73\x2e\x71\x79\x16\x06\x63\x28"
++ "\x09\x15\xd8\x89\x38\x38\x3d\xb5"
++ "\x42\x1c\x08\x24\xf7\x2a\xd2\x9d"
++ "\xc8\xca\xef\xf9\x27\xd8\x07\x86"
++ "\xf7\x43\x0b\x55\x15\x3f\x9f\x83"
++ "\xef\xdc\x49\x9d\x2a\xc1\x54\x62"
++ "\xbd\x9b\x66\x55\x9f\xb7\x12\xf3"
++ "\x1b\x4d\x9d\x2a\x5c\xed\x87\x75"
++ "\x87\x26\xec\x61\x2c\xb4\x0f\x89"
++ "\xb0\xfb\x2e\x68\x5d\x15\xc7\x8d"
++ "\x2e\xc0\xd9\xec\xaf\x4f\xd2\x25"
++ "\x29\xe8\xd2\x26\x2b\x67\xe9\xfc"
++ "\x2b\xa8\x67\x96\x12\x1f\x5b\x96"
++ "\xc6\x14\x53\xaf\x44\xea\xd6\xe2"
++ "\x94\x98\xe4\x12\x93\x4c\x92\xe0"
++ "\x18\xa5\x8d\x2d\xe4\x71\x3c\x47"
++ "\x4c\xf7\xe6\x47\x9e\xc0\x68\xdf"
++ "\xd4\xf5\x5a\x74\xb1\x2b\x29\x03"
++ "\x19\x07\xaf\x90\x62\x5c\x68\x98"
++ "\x48\x16\x11\x02\x9d\xee\xb4\x9b"
++ "\xe5\x42\x7f\x08\xfd\x16\x32\x0b"
++ "\xd0\xb3\xfa\x2b\xb7\x99\xf9\x29"
++ "\xcd\x20\x45\x9f\xb3\x1a\x5d\xa2"
++ "\xaf\x4d\xe0\xbd\x42\x0d\xbc\x74"
++ "\x99\x9c\x8e\x53\x1a\xb4\x3e\xbd"
++ "\xa2\x9a\x2d\xf7\xf8\x39\x0f\x67"
++ "\x63\xfc\x6b\xc0\xaf\xb3\x4b\x4f"
++ "\x55\xc4\xcf\xa7\xc8\x04\x11\x3e"
++ "\x14\x32\xbb\x1b\x38\x77\xd6\x7f"
++ "\x54\x4c\xdf\x75\xf3\x07\x2d\x33"
++ "\x9b\xa8\x20\xe1\x7b\x12\xb5\xf3"
++ "\xef\x2f\xce\x72\xe5\x24\x60\xc1"
++ "\x30\xe2\xab\xa1\x8e\x11\x09\xa8"
++ "\x21\x33\x44\xfe\x7f\x35\x32\x93"
++ "\x39\xa7\xad\x8b\x79\x06\xb2\xcb"
++ "\x4e\xa9\x5f\xc7\xba\x74\x29\xec"
++ "\x93\xa0\x4e\x54\x93\xc0\xbc\x55"
++ "\x64\xf0\x48\xe5\x57\x99\xee\x75"
++ "\xd6\x79\x0f\x66\xb7\xc6\x57\x76"
++ "\xf7\xb7\xf3\x9c\xc5\x60\xe8\x7f"
++ "\x83\x76\xd6\x0e\xaa\xe6\x90\x39"
++ "\x1d\xa6\x32\x6a\x34\xe3\x55\xf8"
++ "\x58\xa0\x58\x7d\x33\xe0\x22\x39"
++ "\x44\x64\x87\x86\x5a\x2f\xa7\x7e"
++ "\x0f\x38\xea\xb0\x30\xcc\x61\xa5"
++ "\x6a\x32\xae\x1e\xf7\xe9\xd0\xa9"
++ "\x0c\x32\x4b\xb5\x49\x28\xab\x85"
++ "\x2f\x8e\x01\x36\x38\x52\xd0\xba"
++ "\xd6\x02\x78\xf8\x0e\x3e\x9c\x8b"
++ "\x6b\x45\x99\x3f\x5c\xfe\x58\xf1"
++ "\x5c\x94\x04\xe1\xf5\x18\x6d\x51"
++ "\xb2\x5d\x18\x20\xb6\xc2\x9a\x42"
++ "\x1d\xb3\xab\x3c\xb6\x3a\x13\x03"
++ "\xb2\x46\x82\x4f\xfc\x64\xbc\x4f"
++ "\xca\xfa\x9c\xc0\xd5\xa7\xbd\x11"
++ "\xb7\xe4\x5a\xf6\x6f\x4d\x4d\x54"
++ "\xea\xa4\x98\x66\xd4\x22\x3b\xd3"
++ "\x8f\x34\x47\xd9\x7c\xf4\x72\x3b"
++ "\x4d\x02\x77\xf6\xd6\xdd\x08\x0a"
++ "\x81\xe1\x86\x89\x3e\x56\x10\x3c"
++ "\xba\xd7\x81\x8c\x08\xbc\x8b\xe2"
++ "\x53\xec\xa7\x89\xee\xc8\x56\xb5"
++ "\x36\x2c\xb2\x03\xba\x99\xdd\x7c"
++ "\x48\xa0\xb0\xbc\x91\x33\xe9\xa8"
++ "\xcb\xcd\xcf\x59\x5f\x1f\x15\xe2"
++ "\x56\xf5\x4e\x01\x35\x27\x45\x77"
++ "\x47\xc8\xbc\xcb\x7e\x39\xc1\x97"
++ "\x28\xd3\x84\xfc\x2c\x3e\xc8\xad"
++ "\x9c\xf8\x8a\x61\x9c\x28\xaa\xc5"
++ "\x99\x20\x43\x85\x9d\xa5\xe2\x8b"
++ "\xb8\xae\xeb\xd0\x32\x0d\x52\x78"
++ "\x09\x56\x3f\xc7\xd8\x7e\x26\xfc"
++ "\x37\xfb\x6f\x04\xfc\xfa\x92\x10"
++ "\xac\xf8\x3e\x21\xdc\x8c\x21\x16"
++ "\x7d\x67\x6e\xf6\xcd\xda\xb6\x98"
++ "\x23\xab\x23\x3c\xb2\x10\xa0\x53"
++ "\x5a\x56\x9f\xc5\xd0\xff\xbb\xe4"
++ "\x98\x3c\x69\x1e\xdb\x38\x8f\x7e"
++ "\x0f\xd2\x98\x88\x81\x8b\x45\x67"
++ "\xea\x33\xf1\xeb\xe9\x97\x55\x2e"
++ "\xd9\xaa\xeb\x5a\xec\xda\xe1\x68"
++ "\xa8\x9d\x3c\x84\x7c\x05\x3d\x62"
++ "\x87\x8f\x03\x21\x28\x95\x0c\x89"
++ "\x25\x22\x4a\xb0\x93\xa9\x50\xa2"
++ "\x2f\x57\x6e\x18\x42\x19\x54\x0c"
++ "\x55\x67\xc6\x11\x49\xf4\x5c\xd2"
++ "\xe9\x3d\xdd\x8b\x48\x71\x21\x00"
++ "\xc3\x9a\x6c\x85\x74\x28\x83\x4a"
++ "\x1b\x31\x05\xe1\x06\x92\xe7\xda"
++ "\x85\x73\x78\x45\x20\x7f\xae\x13"
++ "\x7c\x33\x06\x22\xf4\x83\xf9\x35"
++ "\x3f\x6c\x71\xa8\x4e\x48\xbe\x9b"
++ "\xce\x8a\xba\xda\xbe\x28\x08\xf7"
++ "\xe2\x14\x8c\x71\xea\x72\xf9\x33"
++ "\xf2\x88\x3f\xd7\xbb\x69\x6c\x29"
++ "\x19\xdc\x84\xce\x1f\x12\x4f\xc8"
++ "\xaf\xa5\x04\xba\x5a\xab\xb0\xd9"
++ "\x14\x1f\x6c\x68\x98\x39\x89\x7a"
++ "\xd9\xd8\x2f\xdf\xa8\x47\x4a\x25"
++ "\xe2\xfb\x33\xf4\x59\x78\xe1\x68"
++ "\x85\xcf\xfe\x59\x20\xd4\x05\x1d"
++ "\x80\x99\xae\xbc\xca\xae\x0f\x2f"
++ "\x65\x43\x34\x8e\x7e\xac\xd3\x93"
++ "\x2f\xac\x6d\x14\x3d\x02\x07\x70"
++ "\x9d\xa4\xf3\x1b\x5c\x36\xfc\x01"
++ "\x73\x34\x85\x0c\x6c\xd6\xf1\xbd"
++ "\x3f\xdf\xee\xf5\xd9\xba\x56\xef"
++ "\xf4\x9b\x6b\xee\x9f\x5a\x78\x6d"
++ "\x32\x19\xf4\xf7\xf8\x4c\x69\x0b"
++ "\x4b\xbc\xbb\xb7\xf2\x85\xaf\x70"
++ "\x75\x24\x6c\x54\xa7\x0e\x4d\x1d"
++ "\x01\xbf\x08\xac\xcf\x7f\x2c\xe3"
++ "\x14\x89\x5e\x70\x5a\x99\x92\xcd"
++ "\x01\x84\xc8\xd2\xab\xe5\x4f\x58"
++ "\xe7\x0f\x2f\x0e\xff\x68\xea\xfd"
++ "\x15\xb3\x17\xe6\xb0\xe7\x85\xd8"
++ "\x23\x2e\x05\xc7\xc9\xc4\x46\x1f"
++ "\xe1\x9e\x49\x20\x23\x24\x4d\x7e"
++ "\x29\x65\xff\xf4\xb6\xfd\x1a\x85"
++ "\xc4\x16\xec\xfc\xea\x7b\xd6\x2c"
++ "\x43\xf8\xb7\xbf\x79\xc0\x85\xcd"
++ "\xef\xe1\x98\xd3\xa5\xf7\x90\x8c"
++ "\xe9\x7f\x80\x6b\xd2\xac\x4c\x30"
++ "\xa7\xc6\x61\x6c\xd2\xf9\x2c\xff"
++ "\x30\xbc\x22\x81\x7d\x93\x12\xe4"
++ "\x0a\xcd\xaf\xdd\xe8\xab\x0a\x1e"
++ "\x13\xa4\x27\xc3\x5f\xf7\x4b\xbb"
++ "\x37\x09\x4b\x91\x6f\x92\x4f\xaf"
++ "\x52\xee\xdf\xef\x09\x6f\xf7\x5c"
++ "\x6e\x12\x17\x72\x63\x57\xc7\xba"
++ "\x3b\x6b\x38\x32\x73\x1b\x9c\x80"
++ "\xc1\x7a\xc6\xcf\xcd\x35\xc0\x6b"
++ "\x31\x1a\x6b\xe9\xd8\x2c\x29\x3f"
++ "\x96\xfb\xb6\xcd\x13\x91\x3b\xc2"
++ "\xd2\xa3\x31\x8d\xa4\xcd\x57\xcd"
++ "\x13\x3d\x64\xfd\x06\xce\xe6\xdc"
++ "\x0c\x24\x43\x31\x40\x57\xf1\x72"
++ "\x17\xe3\x3a\x63\x6d\x35\xcf\x5d"
++ "\x97\x40\x59\xdd\xf7\x3c\x02\xf7"
++ "\x1c\x7e\x05\xbb\xa9\x0d\x01\xb1"
++ "\x8e\xc0\x30\xa9\x53\x24\xc9\x89"
++ "\x84\x6d\xaa\xd0\xcd\x91\xc2\x4d"
++ "\x91\xb0\x89\xe2\xbf\x83\x44\xaa"
++ "\x28\x72\x23\xa0\xc2\xad\xad\x1c"
++ "\xfc\x3f\x09\x7a\x0b\xdc\xc5\x1b"
++ "\x87\x13\xc6\x5b\x59\x8d\xf2\xc8"
++ "\xaf\xdf\x11\x95",
+ .rlen = 4100,
+ },
+ };
+
+ /*
++ * CTS (Cipher Text Stealing) mode tests
++ */
++#define CTS_MODE_ENC_TEST_VECTORS 6
++#define CTS_MODE_DEC_TEST_VECTORS 6
++static struct cipher_testvec cts_mode_enc_tv_template[] = {
++ { /* from rfc3962 */
++ .klen = 16,
++ .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++ "\x74\x65\x72\x69\x79\x61\x6b\x69",
++ .ilen = 17,
++ .input = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++ "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++ "\x20",
++ .rlen = 17,
++ .result = "\xc6\x35\x35\x68\xf2\xbf\x8c\xb4"
++ "\xd8\xa5\x80\x36\x2d\xa7\xff\x7f"
++ "\x97",
++ }, {
++ .klen = 16,
++ .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++ "\x74\x65\x72\x69\x79\x61\x6b\x69",
++ .ilen = 31,
++ .input = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++ "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++ "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++ "\x20\x47\x61\x75\x27\x73\x20",
++ .rlen = 31,
++ .result = "\xfc\x00\x78\x3e\x0e\xfd\xb2\xc1"
++ "\xd4\x45\xd4\xc8\xef\xf7\xed\x22"
++ "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++ "\xc0\x7b\x25\xe2\x5e\xcf\xe5",
++ }, {
++ .klen = 16,
++ .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++ "\x74\x65\x72\x69\x79\x61\x6b\x69",
++ .ilen = 32,
++ .input = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++ "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++ "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++ "\x20\x47\x61\x75\x27\x73\x20\x43",
++ .rlen = 32,
++ .result = "\x39\x31\x25\x23\xa7\x86\x62\xd5"
++ "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8"
++ "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++ "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84",
++ }, {
++ .klen = 16,
++ .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++ "\x74\x65\x72\x69\x79\x61\x6b\x69",
++ .ilen = 47,
++ .input = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++ "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++ "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++ "\x20\x47\x61\x75\x27\x73\x20\x43"
++ "\x68\x69\x63\x6b\x65\x6e\x2c\x20"
++ "\x70\x6c\x65\x61\x73\x65\x2c",
++ .rlen = 47,
++ .result = "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++ "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
++ "\xb3\xff\xfd\x94\x0c\x16\xa1\x8c"
++ "\x1b\x55\x49\xd2\xf8\x38\x02\x9e"
++ "\x39\x31\x25\x23\xa7\x86\x62\xd5"
++ "\xbe\x7f\xcb\xcc\x98\xeb\xf5",
++ }, {
++ .klen = 16,
++ .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++ "\x74\x65\x72\x69\x79\x61\x6b\x69",
++ .ilen = 48,
++ .input = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++ "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++ "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++ "\x20\x47\x61\x75\x27\x73\x20\x43"
++ "\x68\x69\x63\x6b\x65\x6e\x2c\x20"
++ "\x70\x6c\x65\x61\x73\x65\x2c\x20",
++ .rlen = 48,
++ .result = "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++ "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
++ "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0"
++ "\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8"
++ "\x39\x31\x25\x23\xa7\x86\x62\xd5"
++ "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8",
++ }, {
++ .klen = 16,
++ .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++ "\x74\x65\x72\x69\x79\x61\x6b\x69",
++ .ilen = 64,
++ .input = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++ "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++ "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++ "\x20\x47\x61\x75\x27\x73\x20\x43"
++ "\x68\x69\x63\x6b\x65\x6e\x2c\x20"
++ "\x70\x6c\x65\x61\x73\x65\x2c\x20"
++ "\x61\x6e\x64\x20\x77\x6f\x6e\x74"
++ "\x6f\x6e\x20\x73\x6f\x75\x70\x2e",
++ .rlen = 64,
++ .result = "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++ "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
++ "\x39\x31\x25\x23\xa7\x86\x62\xd5"
++ "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8"
++ "\x48\x07\xef\xe8\x36\xee\x89\xa5"
++ "\x26\x73\x0d\xbc\x2f\x7b\xc8\x40"
++ "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0"
++ "\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8",
++ }
++};
++
++static struct cipher_testvec cts_mode_dec_tv_template[] = {
++ { /* from rfc3962 */
++ .klen = 16,
++ .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++ "\x74\x65\x72\x69\x79\x61\x6b\x69",
++ .rlen = 17,
++ .result = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++ "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++ "\x20",
++ .ilen = 17,
++ .input = "\xc6\x35\x35\x68\xf2\xbf\x8c\xb4"
++ "\xd8\xa5\x80\x36\x2d\xa7\xff\x7f"
++ "\x97",
++ }, {
++ .klen = 16,
++ .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++ "\x74\x65\x72\x69\x79\x61\x6b\x69",
++ .rlen = 31,
++ .result = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++ "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++ "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++ "\x20\x47\x61\x75\x27\x73\x20",
++ .ilen = 31,
++ .input = "\xfc\x00\x78\x3e\x0e\xfd\xb2\xc1"
++ "\xd4\x45\xd4\xc8\xef\xf7\xed\x22"
++ "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++ "\xc0\x7b\x25\xe2\x5e\xcf\xe5",
++ }, {
++ .klen = 16,
++ .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++ "\x74\x65\x72\x69\x79\x61\x6b\x69",
++ .rlen = 32,
++ .result = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++ "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++ "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++ "\x20\x47\x61\x75\x27\x73\x20\x43",
++ .ilen = 32,
++ .input = "\x39\x31\x25\x23\xa7\x86\x62\xd5"
++ "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8"
++ "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++ "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84",
++ }, {
++ .klen = 16,
++ .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++ "\x74\x65\x72\x69\x79\x61\x6b\x69",
++ .rlen = 47,
++ .result = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++ "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++ "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++ "\x20\x47\x61\x75\x27\x73\x20\x43"
++ "\x68\x69\x63\x6b\x65\x6e\x2c\x20"
++ "\x70\x6c\x65\x61\x73\x65\x2c",
++ .ilen = 47,
++ .input = "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++ "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
++ "\xb3\xff\xfd\x94\x0c\x16\xa1\x8c"
++ "\x1b\x55\x49\xd2\xf8\x38\x02\x9e"
++ "\x39\x31\x25\x23\xa7\x86\x62\xd5"
++ "\xbe\x7f\xcb\xcc\x98\xeb\xf5",
++ }, {
++ .klen = 16,
++ .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++ "\x74\x65\x72\x69\x79\x61\x6b\x69",
++ .rlen = 48,
++ .result = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++ "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++ "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++ "\x20\x47\x61\x75\x27\x73\x20\x43"
++ "\x68\x69\x63\x6b\x65\x6e\x2c\x20"
++ "\x70\x6c\x65\x61\x73\x65\x2c\x20",
++ .ilen = 48,
++ .input = "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++ "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
++ "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0"
++ "\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8"
++ "\x39\x31\x25\x23\xa7\x86\x62\xd5"
++ "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8",
++ }, {
++ .klen = 16,
++ .key = "\x63\x68\x69\x63\x6b\x65\x6e\x20"
++ "\x74\x65\x72\x69\x79\x61\x6b\x69",
++ .rlen = 64,
++ .result = "\x49\x20\x77\x6f\x75\x6c\x64\x20"
++ "\x6c\x69\x6b\x65\x20\x74\x68\x65"
++ "\x20\x47\x65\x6e\x65\x72\x61\x6c"
++ "\x20\x47\x61\x75\x27\x73\x20\x43"
++ "\x68\x69\x63\x6b\x65\x6e\x2c\x20"
++ "\x70\x6c\x65\x61\x73\x65\x2c\x20"
++ "\x61\x6e\x64\x20\x77\x6f\x6e\x74"
++ "\x6f\x6e\x20\x73\x6f\x75\x70\x2e",
++ .ilen = 64,
++ .input = "\x97\x68\x72\x68\xd6\xec\xcc\xc0"
++ "\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
++ "\x39\x31\x25\x23\xa7\x86\x62\xd5"
++ "\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8"
++ "\x48\x07\xef\xe8\x36\xee\x89\xa5"
++ "\x26\x73\x0d\xbc\x2f\x7b\xc8\x40"
++ "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0"
++ "\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8",
++ }
++};
++
++/*
+ * Compression stuff.
+ */
+ #define COMP_BUF_SIZE 512
+@@ -7652,35 +7853,35 @@ static struct comp_testvec deflate_comp_tv_template[] = {
+ {
+ .inlen = 70,
+ .outlen = 38,
+- .input = "Join us now and share the software "
+- "Join us now and share the software ",
+- .output = { 0xf3, 0xca, 0xcf, 0xcc, 0x53, 0x28, 0x2d, 0x56,
+- 0xc8, 0xcb, 0x2f, 0x57, 0x48, 0xcc, 0x4b, 0x51,
+- 0x28, 0xce, 0x48, 0x2c, 0x4a, 0x55, 0x28, 0xc9,
+- 0x48, 0x55, 0x28, 0xce, 0x4f, 0x2b, 0x29, 0x07,
+- 0x71, 0xbc, 0x08, 0x2b, 0x01, 0x00 },
++ .input = "Join us now and share the software "
++ "Join us now and share the software ",
++ .output = "\xf3\xca\xcf\xcc\x53\x28\x2d\x56"
++ "\xc8\xcb\x2f\x57\x48\xcc\x4b\x51"
++ "\x28\xce\x48\x2c\x4a\x55\x28\xc9"
++ "\x48\x55\x28\xce\x4f\x2b\x29\x07"
++ "\x71\xbc\x08\x2b\x01\x00",
+ }, {
+ .inlen = 191,
+ .outlen = 122,
+ .input = "This document describes a compression method based on the DEFLATE"
+- "compression algorithm. This document defines the application of "
+- "the DEFLATE algorithm to the IP Payload Compression Protocol.",
+- .output = { 0x5d, 0x8d, 0x31, 0x0e, 0xc2, 0x30, 0x10, 0x04,
+- 0xbf, 0xb2, 0x2f, 0xc8, 0x1f, 0x10, 0x04, 0x09,
+- 0x89, 0xc2, 0x85, 0x3f, 0x70, 0xb1, 0x2f, 0xf8,
+- 0x24, 0xdb, 0x67, 0xd9, 0x47, 0xc1, 0xef, 0x49,
+- 0x68, 0x12, 0x51, 0xae, 0x76, 0x67, 0xd6, 0x27,
+- 0x19, 0x88, 0x1a, 0xde, 0x85, 0xab, 0x21, 0xf2,
+- 0x08, 0x5d, 0x16, 0x1e, 0x20, 0x04, 0x2d, 0xad,
+- 0xf3, 0x18, 0xa2, 0x15, 0x85, 0x2d, 0x69, 0xc4,
+- 0x42, 0x83, 0x23, 0xb6, 0x6c, 0x89, 0x71, 0x9b,
+- 0xef, 0xcf, 0x8b, 0x9f, 0xcf, 0x33, 0xca, 0x2f,
+- 0xed, 0x62, 0xa9, 0x4c, 0x80, 0xff, 0x13, 0xaf,
+- 0x52, 0x37, 0xed, 0x0e, 0x52, 0x6b, 0x59, 0x02,
+- 0xd9, 0x4e, 0xe8, 0x7a, 0x76, 0x1d, 0x02, 0x98,
+- 0xfe, 0x8a, 0x87, 0x83, 0xa3, 0x4f, 0x56, 0x8a,
+- 0xb8, 0x9e, 0x8e, 0x5c, 0x57, 0xd3, 0xa0, 0x79,
+- 0xfa, 0x02 },
++ "compression algorithm. This document defines the application of "
++ "the DEFLATE algorithm to the IP Payload Compression Protocol.",
++ .output = "\x5d\x8d\x31\x0e\xc2\x30\x10\x04"
++ "\xbf\xb2\x2f\xc8\x1f\x10\x04\x09"
++ "\x89\xc2\x85\x3f\x70\xb1\x2f\xf8"
++ "\x24\xdb\x67\xd9\x47\xc1\xef\x49"
++ "\x68\x12\x51\xae\x76\x67\xd6\x27"
++ "\x19\x88\x1a\xde\x85\xab\x21\xf2"
++ "\x08\x5d\x16\x1e\x20\x04\x2d\xad"
++ "\xf3\x18\xa2\x15\x85\x2d\x69\xc4"
++ "\x42\x83\x23\xb6\x6c\x89\x71\x9b"
++ "\xef\xcf\x8b\x9f\xcf\x33\xca\x2f"
++ "\xed\x62\xa9\x4c\x80\xff\x13\xaf"
++ "\x52\x37\xed\x0e\x52\x6b\x59\x02"
++ "\xd9\x4e\xe8\x7a\x76\x1d\x02\x98"
++ "\xfe\x8a\x87\x83\xa3\x4f\x56\x8a"
++ "\xb8\x9e\x8e\x5c\x57\xd3\xa0\x79"
++ "\xfa\x02",
+ },
+ };
+
+@@ -7688,35 +7889,35 @@ static struct comp_testvec deflate_decomp_tv_template[] = {
+ {
+ .inlen = 122,
+ .outlen = 191,
+- .input = { 0x5d, 0x8d, 0x31, 0x0e, 0xc2, 0x30, 0x10, 0x04,
+- 0xbf, 0xb2, 0x2f, 0xc8, 0x1f, 0x10, 0x04, 0x09,
+- 0x89, 0xc2, 0x85, 0x3f, 0x70, 0xb1, 0x2f, 0xf8,
+- 0x24, 0xdb, 0x67, 0xd9, 0x47, 0xc1, 0xef, 0x49,
+- 0x68, 0x12, 0x51, 0xae, 0x76, 0x67, 0xd6, 0x27,
+- 0x19, 0x88, 0x1a, 0xde, 0x85, 0xab, 0x21, 0xf2,
+- 0x08, 0x5d, 0x16, 0x1e, 0x20, 0x04, 0x2d, 0xad,
+- 0xf3, 0x18, 0xa2, 0x15, 0x85, 0x2d, 0x69, 0xc4,
+- 0x42, 0x83, 0x23, 0xb6, 0x6c, 0x89, 0x71, 0x9b,
+- 0xef, 0xcf, 0x8b, 0x9f, 0xcf, 0x33, 0xca, 0x2f,
+- 0xed, 0x62, 0xa9, 0x4c, 0x80, 0xff, 0x13, 0xaf,
+- 0x52, 0x37, 0xed, 0x0e, 0x52, 0x6b, 0x59, 0x02,
+- 0xd9, 0x4e, 0xe8, 0x7a, 0x76, 0x1d, 0x02, 0x98,
+- 0xfe, 0x8a, 0x87, 0x83, 0xa3, 0x4f, 0x56, 0x8a,
+- 0xb8, 0x9e, 0x8e, 0x5c, 0x57, 0xd3, 0xa0, 0x79,
+- 0xfa, 0x02 },
++ .input = "\x5d\x8d\x31\x0e\xc2\x30\x10\x04"
++ "\xbf\xb2\x2f\xc8\x1f\x10\x04\x09"
++ "\x89\xc2\x85\x3f\x70\xb1\x2f\xf8"
++ "\x24\xdb\x67\xd9\x47\xc1\xef\x49"
++ "\x68\x12\x51\xae\x76\x67\xd6\x27"
++ "\x19\x88\x1a\xde\x85\xab\x21\xf2"
++ "\x08\x5d\x16\x1e\x20\x04\x2d\xad"
++ "\xf3\x18\xa2\x15\x85\x2d\x69\xc4"
++ "\x42\x83\x23\xb6\x6c\x89\x71\x9b"
++ "\xef\xcf\x8b\x9f\xcf\x33\xca\x2f"
++ "\xed\x62\xa9\x4c\x80\xff\x13\xaf"
++ "\x52\x37\xed\x0e\x52\x6b\x59\x02"
++ "\xd9\x4e\xe8\x7a\x76\x1d\x02\x98"
++ "\xfe\x8a\x87\x83\xa3\x4f\x56\x8a"
++ "\xb8\x9e\x8e\x5c\x57\xd3\xa0\x79"
++ "\xfa\x02",
+ .output = "This document describes a compression method based on the DEFLATE"
+- "compression algorithm. This document defines the application of "
+- "the DEFLATE algorithm to the IP Payload Compression Protocol.",
++ "compression algorithm. This document defines the application of "
++ "the DEFLATE algorithm to the IP Payload Compression Protocol.",
+ }, {
+ .inlen = 38,
+ .outlen = 70,
+- .input = { 0xf3, 0xca, 0xcf, 0xcc, 0x53, 0x28, 0x2d, 0x56,
+- 0xc8, 0xcb, 0x2f, 0x57, 0x48, 0xcc, 0x4b, 0x51,
+- 0x28, 0xce, 0x48, 0x2c, 0x4a, 0x55, 0x28, 0xc9,
+- 0x48, 0x55, 0x28, 0xce, 0x4f, 0x2b, 0x29, 0x07,
+- 0x71, 0xbc, 0x08, 0x2b, 0x01, 0x00 },
++ .input = "\xf3\xca\xcf\xcc\x53\x28\x2d\x56"
++ "\xc8\xcb\x2f\x57\x48\xcc\x4b\x51"
++ "\x28\xce\x48\x2c\x4a\x55\x28\xc9"
++ "\x48\x55\x28\xce\x4f\x2b\x29\x07"
++ "\x71\xbc\x08\x2b\x01\x00",
+ .output = "Join us now and share the software "
+- "Join us now and share the software ",
++ "Join us now and share the software ",
+ },
+ };
+
+@@ -7731,36 +7932,36 @@ static struct comp_testvec lzo_comp_tv_template[] = {
+ .inlen = 70,
+ .outlen = 46,
+ .input = "Join us now and share the software "
+- "Join us now and share the software ",
+- .output = { 0x00, 0x0d, 0x4a, 0x6f, 0x69, 0x6e, 0x20, 0x75,
+- 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x61, 0x6e,
+- 0x64, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x20,
+- 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x66, 0x74,
+- 0x77, 0x70, 0x01, 0x01, 0x4a, 0x6f, 0x69, 0x6e,
+- 0x3d, 0x88, 0x00, 0x11, 0x00, 0x00 },
++ "Join us now and share the software ",
++ .output = "\x00\x0d\x4a\x6f\x69\x6e\x20\x75"
++ "\x73\x20\x6e\x6f\x77\x20\x61\x6e"
++ "\x64\x20\x73\x68\x61\x72\x65\x20"
++ "\x74\x68\x65\x20\x73\x6f\x66\x74"
++ "\x77\x70\x01\x01\x4a\x6f\x69\x6e"
++ "\x3d\x88\x00\x11\x00\x00",
+ }, {
+ .inlen = 159,
+ .outlen = 133,
+ .input = "This document describes a compression method based on the LZO "
+- "compression algorithm. This document defines the application of "
+- "the LZO algorithm used in UBIFS.",
+- .output = { 0x00, 0x2b, 0x54, 0x68, 0x69, 0x73, 0x20, 0x64,
+- 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20,
+- 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65,
+- 0x73, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x70,
+- 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20,
+- 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x20, 0x62,
+- 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20,
+- 0x74, 0x68, 0x65, 0x20, 0x4c, 0x5a, 0x4f, 0x2b,
+- 0x8c, 0x00, 0x0d, 0x61, 0x6c, 0x67, 0x6f, 0x72,
+- 0x69, 0x74, 0x68, 0x6d, 0x2e, 0x20, 0x20, 0x54,
+- 0x68, 0x69, 0x73, 0x2a, 0x54, 0x01, 0x02, 0x66,
+- 0x69, 0x6e, 0x65, 0x73, 0x94, 0x06, 0x05, 0x61,
+- 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x76,
+- 0x0a, 0x6f, 0x66, 0x88, 0x02, 0x60, 0x09, 0x27,
+- 0xf0, 0x00, 0x0c, 0x20, 0x75, 0x73, 0x65, 0x64,
+- 0x20, 0x69, 0x6e, 0x20, 0x55, 0x42, 0x49, 0x46,
+- 0x53, 0x2e, 0x11, 0x00, 0x00 },
++ "compression algorithm. This document defines the application of "
++ "the LZO algorithm used in UBIFS.",
++ .output = "\x00\x2b\x54\x68\x69\x73\x20\x64"
++ "\x6f\x63\x75\x6d\x65\x6e\x74\x20"
++ "\x64\x65\x73\x63\x72\x69\x62\x65"
++ "\x73\x20\x61\x20\x63\x6f\x6d\x70"
++ "\x72\x65\x73\x73\x69\x6f\x6e\x20"
++ "\x6d\x65\x74\x68\x6f\x64\x20\x62"
++ "\x61\x73\x65\x64\x20\x6f\x6e\x20"
++ "\x74\x68\x65\x20\x4c\x5a\x4f\x2b"
++ "\x8c\x00\x0d\x61\x6c\x67\x6f\x72"
++ "\x69\x74\x68\x6d\x2e\x20\x20\x54"
++ "\x68\x69\x73\x2a\x54\x01\x02\x66"
++ "\x69\x6e\x65\x73\x94\x06\x05\x61"
++ "\x70\x70\x6c\x69\x63\x61\x74\x76"
++ "\x0a\x6f\x66\x88\x02\x60\x09\x27"
++ "\xf0\x00\x0c\x20\x75\x73\x65\x64"
++ "\x20\x69\x6e\x20\x55\x42\x49\x46"
++ "\x53\x2e\x11\x00\x00",
+ },
+ };
+
+@@ -7768,37 +7969,37 @@ static struct comp_testvec lzo_decomp_tv_template[] = {
+ {
+ .inlen = 133,
+ .outlen = 159,
+- .input = { 0x00, 0x2b, 0x54, 0x68, 0x69, 0x73, 0x20, 0x64,
+- 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20,
+- 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65,
+- 0x73, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x70,
+- 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20,
+- 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x20, 0x62,
+- 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20,
+- 0x74, 0x68, 0x65, 0x20, 0x4c, 0x5a, 0x4f, 0x2b,
+- 0x8c, 0x00, 0x0d, 0x61, 0x6c, 0x67, 0x6f, 0x72,
+- 0x69, 0x74, 0x68, 0x6d, 0x2e, 0x20, 0x20, 0x54,
+- 0x68, 0x69, 0x73, 0x2a, 0x54, 0x01, 0x02, 0x66,
+- 0x69, 0x6e, 0x65, 0x73, 0x94, 0x06, 0x05, 0x61,
+- 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x76,
+- 0x0a, 0x6f, 0x66, 0x88, 0x02, 0x60, 0x09, 0x27,
+- 0xf0, 0x00, 0x0c, 0x20, 0x75, 0x73, 0x65, 0x64,
+- 0x20, 0x69, 0x6e, 0x20, 0x55, 0x42, 0x49, 0x46,
+- 0x53, 0x2e, 0x11, 0x00, 0x00 },
++ .input = "\x00\x2b\x54\x68\x69\x73\x20\x64"
++ "\x6f\x63\x75\x6d\x65\x6e\x74\x20"
++ "\x64\x65\x73\x63\x72\x69\x62\x65"
++ "\x73\x20\x61\x20\x63\x6f\x6d\x70"
++ "\x72\x65\x73\x73\x69\x6f\x6e\x20"
++ "\x6d\x65\x74\x68\x6f\x64\x20\x62"
++ "\x61\x73\x65\x64\x20\x6f\x6e\x20"
++ "\x74\x68\x65\x20\x4c\x5a\x4f\x2b"
++ "\x8c\x00\x0d\x61\x6c\x67\x6f\x72"
++ "\x69\x74\x68\x6d\x2e\x20\x20\x54"
++ "\x68\x69\x73\x2a\x54\x01\x02\x66"
++ "\x69\x6e\x65\x73\x94\x06\x05\x61"
++ "\x70\x70\x6c\x69\x63\x61\x74\x76"
++ "\x0a\x6f\x66\x88\x02\x60\x09\x27"
++ "\xf0\x00\x0c\x20\x75\x73\x65\x64"
++ "\x20\x69\x6e\x20\x55\x42\x49\x46"
++ "\x53\x2e\x11\x00\x00",
+ .output = "This document describes a compression method based on the LZO "
+- "compression algorithm. This document defines the application of "
+- "the LZO algorithm used in UBIFS.",
++ "compression algorithm. This document defines the application of "
++ "the LZO algorithm used in UBIFS.",
+ }, {
+ .inlen = 46,
+ .outlen = 70,
+- .input = { 0x00, 0x0d, 0x4a, 0x6f, 0x69, 0x6e, 0x20, 0x75,
+- 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x61, 0x6e,
+- 0x64, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x20,
+- 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x66, 0x74,
+- 0x77, 0x70, 0x01, 0x01, 0x4a, 0x6f, 0x69, 0x6e,
+- 0x3d, 0x88, 0x00, 0x11, 0x00, 0x00 },
++ .input = "\x00\x0d\x4a\x6f\x69\x6e\x20\x75"
++ "\x73\x20\x6e\x6f\x77\x20\x61\x6e"
++ "\x64\x20\x73\x68\x61\x72\x65\x20"
++ "\x74\x68\x65\x20\x73\x6f\x66\x74"
++ "\x77\x70\x01\x01\x4a\x6f\x69\x6e"
++ "\x3d\x88\x00\x11\x00\x00",
+ .output = "Join us now and share the software "
+- "Join us now and share the software ",
++ "Join us now and share the software ",
+ },
+ };
+
+@@ -7809,46 +8010,46 @@ static struct comp_testvec lzo_decomp_tv_template[] = {
+
+ static struct hash_testvec michael_mic_tv_template[] = {
+ {
+- .key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++ .key = "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .ksize = 8,
+- .plaintext = { },
++ .plaintext = zeroed_string,
+ .psize = 0,
+- .digest = { 0x82, 0x92, 0x5c, 0x1c, 0xa1, 0xd1, 0x30, 0xb8 }
++ .digest = "\x82\x92\x5c\x1c\xa1\xd1\x30\xb8",
+ },
+ {
+- .key = { 0x82, 0x92, 0x5c, 0x1c, 0xa1, 0xd1, 0x30, 0xb8 },
++ .key = "\x82\x92\x5c\x1c\xa1\xd1\x30\xb8",
+ .ksize = 8,
+- .plaintext = { 'M' },
++ .plaintext = "M",
+ .psize = 1,
+- .digest = { 0x43, 0x47, 0x21, 0xca, 0x40, 0x63, 0x9b, 0x3f }
++ .digest = "\x43\x47\x21\xca\x40\x63\x9b\x3f",
+ },
+ {
+- .key = { 0x43, 0x47, 0x21, 0xca, 0x40, 0x63, 0x9b, 0x3f },
++ .key = "\x43\x47\x21\xca\x40\x63\x9b\x3f",
+ .ksize = 8,
+- .plaintext = { 'M', 'i' },
++ .plaintext = "Mi",
+ .psize = 2,
+- .digest = { 0xe8, 0xf9, 0xbe, 0xca, 0xe9, 0x7e, 0x5d, 0x29 }
++ .digest = "\xe8\xf9\xbe\xca\xe9\x7e\x5d\x29",
+ },
+ {
+- .key = { 0xe8, 0xf9, 0xbe, 0xca, 0xe9, 0x7e, 0x5d, 0x29 },
++ .key = "\xe8\xf9\xbe\xca\xe9\x7e\x5d\x29",
+ .ksize = 8,
+- .plaintext = { 'M', 'i', 'c' },
++ .plaintext = "Mic",
+ .psize = 3,
+- .digest = { 0x90, 0x03, 0x8f, 0xc6, 0xcf, 0x13, 0xc1, 0xdb }
++ .digest = "\x90\x03\x8f\xc6\xcf\x13\xc1\xdb",
+ },
+ {
+- .key = { 0x90, 0x03, 0x8f, 0xc6, 0xcf, 0x13, 0xc1, 0xdb },
++ .key = "\x90\x03\x8f\xc6\xcf\x13\xc1\xdb",
+ .ksize = 8,
+- .plaintext = { 'M', 'i', 'c', 'h' },
++ .plaintext = "Mich",
+ .psize = 4,
+- .digest = { 0xd5, 0x5e, 0x10, 0x05, 0x10, 0x12, 0x89, 0x86 }
++ .digest = "\xd5\x5e\x10\x05\x10\x12\x89\x86",
+ },
+ {
+- .key = { 0xd5, 0x5e, 0x10, 0x05, 0x10, 0x12, 0x89, 0x86 },
++ .key = "\xd5\x5e\x10\x05\x10\x12\x89\x86",
+ .ksize = 8,
+- .plaintext = { 'M', 'i', 'c', 'h', 'a', 'e', 'l' },
++ .plaintext = "Michael",
+ .psize = 7,
+- .digest = { 0x0a, 0x94, 0x2b, 0x12, 0x4e, 0xca, 0xa5, 0x46 },
++ .digest = "\x0a\x94\x2b\x12\x4e\xca\xa5\x46",
+ }
+ };
+
+@@ -7860,170 +8061,170 @@ static struct hash_testvec michael_mic_tv_template[] = {
+ static struct hash_testvec crc32c_tv_template[] = {
+ {
+ .psize = 0,
+- .digest = { 0x00, 0x00, 0x00, 0x00 }
++ .digest = "\x00\x00\x00\x00",
+ },
+ {
+- .key = { 0x87, 0xa9, 0xcb, 0xed },
++ .key = "\x87\xa9\xcb\xed",
+ .ksize = 4,
+ .psize = 0,
+- .digest = { 0x78, 0x56, 0x34, 0x12 },
++ .digest = "\x78\x56\x34\x12",
+ },
+ {
+- .key = { 0xff, 0xff, 0xff, 0xff },
++ .key = "\xff\xff\xff\xff",
+ .ksize = 4,
+- .plaintext = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+- 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+- 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+- 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28 },
++ .plaintext = "\x01\x02\x03\x04\x05\x06\x07\x08"
++ "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
++ "\x11\x12\x13\x14\x15\x16\x17\x18"
++ "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
++ "\x21\x22\x23\x24\x25\x26\x27\x28",
+ .psize = 40,
+- .digest = { 0x7f, 0x15, 0x2c, 0x0e }
++ .digest = "\x7f\x15\x2c\x0e",
+ },
+ {
+- .key = { 0xff, 0xff, 0xff, 0xff },
++ .key = "\xff\xff\xff\xff",
+ .ksize = 4,
+- .plaintext = { 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+- 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
+- 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
+- 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+- 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50 },
++ .plaintext = "\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"
++ "\x31\x32\x33\x34\x35\x36\x37\x38"
++ "\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
++ "\x41\x42\x43\x44\x45\x46\x47\x48"
++ "\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50",
+ .psize = 40,
+- .digest = { 0xf6, 0xeb, 0x80, 0xe9 }
++ .digest = "\xf6\xeb\x80\xe9",
+ },
+ {
+- .key = { 0xff, 0xff, 0xff, 0xff },
++ .key = "\xff\xff\xff\xff",
+ .ksize = 4,
+- .plaintext = { 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+- 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60,
+- 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+- 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
+- 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78 },
++ .plaintext = "\x51\x52\x53\x54\x55\x56\x57\x58"
++ "\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
++ "\x61\x62\x63\x64\x65\x66\x67\x68"
++ "\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70"
++ "\x71\x72\x73\x74\x75\x76\x77\x78",
+ .psize = 40,
+- .digest = { 0xed, 0xbd, 0x74, 0xde }
++ .digest = "\xed\xbd\x74\xde",
+ },
+ {
+- .key = { 0xff, 0xff, 0xff, 0xff },
++ .key = "\xff\xff\xff\xff",
+ .ksize = 4,
+- .plaintext = { 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80,
+- 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+- 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
+- 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+- 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0 },
++ .plaintext = "\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
++ "\x81\x82\x83\x84\x85\x86\x87\x88"
++ "\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90"
++ "\x91\x92\x93\x94\x95\x96\x97\x98"
++ "\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0",
+ .psize = 40,
+- .digest = { 0x62, 0xc8, 0x79, 0xd5 }
++ .digest = "\x62\xc8\x79\xd5",
+ },
+ {
+- .key = { 0xff, 0xff, 0xff, 0xff },
++ .key = "\xff\xff\xff\xff",
+ .ksize = 4,
+- .plaintext = { 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
+- 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
+- 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
+- 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0,
+- 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8 },
++ .plaintext = "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8"
++ "\xa9\xaa\xab\xac\xad\xae\xaf\xb0"
++ "\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8"
++ "\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
++ "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8",
+ .psize = 40,
+- .digest = { 0xd0, 0x9a, 0x97, 0xba }
++ .digest = "\xd0\x9a\x97\xba",
+ },
+ {
+- .key = { 0xff, 0xff, 0xff, 0xff },
++ .key = "\xff\xff\xff\xff",
+ .ksize = 4,
+- .plaintext = { 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
+- 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
+- 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
+- 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
+- 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0 },
++ .plaintext = "\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0"
++ "\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8"
++ "\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
++ "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8"
++ "\xe9\xea\xeb\xec\xed\xee\xef\xf0",
+ .psize = 40,
+- .digest = { 0x13, 0xd9, 0x29, 0x2b }
++ .digest = "\x13\xd9\x29\x2b",
+ },
+ {
+- .key = { 0x80, 0xea, 0xd3, 0xf1 },
++ .key = "\x80\xea\xd3\xf1",
+ .ksize = 4,
+- .plaintext = { 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+- 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
+- 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
+- 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+- 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50 },
++ .plaintext = "\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"
++ "\x31\x32\x33\x34\x35\x36\x37\x38"
++ "\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
++ "\x41\x42\x43\x44\x45\x46\x47\x48"
++ "\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50",
+ .psize = 40,
+- .digest = { 0x0c, 0xb5, 0xe2, 0xa2 }
++ .digest = "\x0c\xb5\xe2\xa2",
+ },
+ {
+- .key = { 0xf3, 0x4a, 0x1d, 0x5d },
++ .key = "\xf3\x4a\x1d\x5d",
+ .ksize = 4,
+- .plaintext = { 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+- 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60,
+- 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+- 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
+- 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78 },
++ .plaintext = "\x51\x52\x53\x54\x55\x56\x57\x58"
++ "\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
++ "\x61\x62\x63\x64\x65\x66\x67\x68"
++ "\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70"
++ "\x71\x72\x73\x74\x75\x76\x77\x78",
+ .psize = 40,
+- .digest = { 0xd1, 0x7f, 0xfb, 0xa6 }
++ .digest = "\xd1\x7f\xfb\xa6",
+ },
+ {
+- .key = { 0x2e, 0x80, 0x04, 0x59 },
++ .key = "\x2e\x80\x04\x59",
+ .ksize = 4,
+- .plaintext = { 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80,
+- 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+- 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
+- 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+- 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0 },
++ .plaintext = "\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
++ "\x81\x82\x83\x84\x85\x86\x87\x88"
++ "\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90"
++ "\x91\x92\x93\x94\x95\x96\x97\x98"
++ "\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0",
+ .psize = 40,
+- .digest = { 0x59, 0x33, 0xe6, 0x7a }
++ .digest = "\x59\x33\xe6\x7a",
+ },
+ {
+- .key = { 0xa6, 0xcc, 0x19, 0x85 },
++ .key = "\xa6\xcc\x19\x85",
+ .ksize = 4,
+- .plaintext = { 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
+- 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
+- 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
+- 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0,
+- 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8 },
++ .plaintext = "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8"
++ "\xa9\xaa\xab\xac\xad\xae\xaf\xb0"
++ "\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8"
++ "\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
++ "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8",
+ .psize = 40,
+- .digest = { 0xbe, 0x03, 0x01, 0xd2 }
++ .digest = "\xbe\x03\x01\xd2",
+ },
+ {
+- .key = { 0x41, 0xfc, 0xfe, 0x2d },
++ .key = "\x41\xfc\xfe\x2d",
+ .ksize = 4,
+- .plaintext = { 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
+- 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
+- 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
+- 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
+- 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0 },
++ .plaintext = "\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0"
++ "\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8"
++ "\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
++ "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8"
++ "\xe9\xea\xeb\xec\xed\xee\xef\xf0",
+ .psize = 40,
+- .digest = { 0x75, 0xd3, 0xc5, 0x24 }
++ .digest = "\x75\xd3\xc5\x24",
+ },
+ {
+- .key = { 0xff, 0xff, 0xff, 0xff },
++ .key = "\xff\xff\xff\xff",
+ .ksize = 4,
+- .plaintext = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+- 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+- 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+- 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+- 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+- 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
+- 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
+- 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+- 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
+- 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+- 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60,
+- 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+- 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
+- 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+- 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80,
+- 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+- 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
+- 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+- 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0,
+- 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
+- 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
+- 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
+- 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0,
+- 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
+- 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
+- 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
+- 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
+- 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
+- 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0 },
++ .plaintext = "\x01\x02\x03\x04\x05\x06\x07\x08"
++ "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
++ "\x11\x12\x13\x14\x15\x16\x17\x18"
++ "\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
++ "\x21\x22\x23\x24\x25\x26\x27\x28"
++ "\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"
++ "\x31\x32\x33\x34\x35\x36\x37\x38"
++ "\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
++ "\x41\x42\x43\x44\x45\x46\x47\x48"
++ "\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50"
++ "\x51\x52\x53\x54\x55\x56\x57\x58"
++ "\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
++ "\x61\x62\x63\x64\x65\x66\x67\x68"
++ "\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70"
++ "\x71\x72\x73\x74\x75\x76\x77\x78"
++ "\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
++ "\x81\x82\x83\x84\x85\x86\x87\x88"
++ "\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90"
++ "\x91\x92\x93\x94\x95\x96\x97\x98"
++ "\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"
++ "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8"
++ "\xa9\xaa\xab\xac\xad\xae\xaf\xb0"
++ "\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8"
++ "\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
++ "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8"
++ "\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0"
++ "\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8"
++ "\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
++ "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8"
++ "\xe9\xea\xeb\xec\xed\xee\xef\xf0",
+ .psize = 240,
+- .digest = { 0x75, 0xd3, 0xc5, 0x24 },
++ .digest = "\x75\xd3\xc5\x24",
+ .np = 2,
+ .tap = { 31, 209 }
+ },
+@@ -8032,134 +8233,19 @@ static struct hash_testvec crc32c_tv_template[] = {
+ /*
+ * Cipher speed tests
+ */
+-static struct cipher_speed aes_speed_template[] = {
+- { .klen = 16, .blen = 16, },
+- { .klen = 16, .blen = 64, },
+- { .klen = 16, .blen = 256, },
+- { .klen = 16, .blen = 1024, },
+- { .klen = 16, .blen = 8192, },
+- { .klen = 24, .blen = 16, },
+- { .klen = 24, .blen = 64, },
+- { .klen = 24, .blen = 256, },
+- { .klen = 24, .blen = 1024, },
+- { .klen = 24, .blen = 8192, },
+- { .klen = 32, .blen = 16, },
+- { .klen = 32, .blen = 64, },
+- { .klen = 32, .blen = 256, },
+- { .klen = 32, .blen = 1024, },
+- { .klen = 32, .blen = 8192, },
+-
+- /* End marker */
+- { .klen = 0, .blen = 0, }
+-};
+-
+-static struct cipher_speed aes_lrw_speed_template[] = {
+- { .klen = 32, .blen = 16, },
+- { .klen = 32, .blen = 64, },
+- { .klen = 32, .blen = 256, },
+- { .klen = 32, .blen = 1024, },
+- { .klen = 32, .blen = 8192, },
+- { .klen = 40, .blen = 16, },
+- { .klen = 40, .blen = 64, },
+- { .klen = 40, .blen = 256, },
+- { .klen = 40, .blen = 1024, },
+- { .klen = 40, .blen = 8192, },
+- { .klen = 48, .blen = 16, },
+- { .klen = 48, .blen = 64, },
+- { .klen = 48, .blen = 256, },
+- { .klen = 48, .blen = 1024, },
+- { .klen = 48, .blen = 8192, },
+-
+- /* End marker */
+- { .klen = 0, .blen = 0, }
+-};
+-
+-static struct cipher_speed aes_xts_speed_template[] = {
+- { .klen = 32, .blen = 16, },
+- { .klen = 32, .blen = 64, },
+- { .klen = 32, .blen = 256, },
+- { .klen = 32, .blen = 1024, },
+- { .klen = 32, .blen = 8192, },
+- { .klen = 48, .blen = 16, },
+- { .klen = 48, .blen = 64, },
+- { .klen = 48, .blen = 256, },
+- { .klen = 48, .blen = 1024, },
+- { .klen = 48, .blen = 8192, },
+- { .klen = 64, .blen = 16, },
+- { .klen = 64, .blen = 64, },
+- { .klen = 64, .blen = 256, },
+- { .klen = 64, .blen = 1024, },
+- { .klen = 64, .blen = 8192, },
+-
+- /* End marker */
+- { .klen = 0, .blen = 0, }
+-};
+-
+-static struct cipher_speed des3_ede_speed_template[] = {
+- { .klen = 24, .blen = 16, },
+- { .klen = 24, .blen = 64, },
+- { .klen = 24, .blen = 256, },
+- { .klen = 24, .blen = 1024, },
+- { .klen = 24, .blen = 8192, },
+-
+- /* End marker */
+- { .klen = 0, .blen = 0, }
+-};
+-
+-static struct cipher_speed twofish_speed_template[] = {
+- { .klen = 16, .blen = 16, },
+- { .klen = 16, .blen = 64, },
+- { .klen = 16, .blen = 256, },
+- { .klen = 16, .blen = 1024, },
+- { .klen = 16, .blen = 8192, },
+- { .klen = 24, .blen = 16, },
+- { .klen = 24, .blen = 64, },
+- { .klen = 24, .blen = 256, },
+- { .klen = 24, .blen = 1024, },
+- { .klen = 24, .blen = 8192, },
+- { .klen = 32, .blen = 16, },
+- { .klen = 32, .blen = 64, },
+- { .klen = 32, .blen = 256, },
+- { .klen = 32, .blen = 1024, },
+- { .klen = 32, .blen = 8192, },
+-
+- /* End marker */
+- { .klen = 0, .blen = 0, }
+-};
+-
+-static struct cipher_speed blowfish_speed_template[] = {
+- /* Don't support blowfish keys > 256 bit in this test */
+- { .klen = 8, .blen = 16, },
+- { .klen = 8, .blen = 64, },
+- { .klen = 8, .blen = 256, },
+- { .klen = 8, .blen = 1024, },
+- { .klen = 8, .blen = 8192, },
+- { .klen = 32, .blen = 16, },
+- { .klen = 32, .blen = 64, },
+- { .klen = 32, .blen = 256, },
+- { .klen = 32, .blen = 1024, },
+- { .klen = 32, .blen = 8192, },
+-
+- /* End marker */
+- { .klen = 0, .blen = 0, }
+-};
+-
+-static struct cipher_speed des_speed_template[] = {
+- { .klen = 8, .blen = 16, },
+- { .klen = 8, .blen = 64, },
+- { .klen = 8, .blen = 256, },
+- { .klen = 8, .blen = 1024, },
+- { .klen = 8, .blen = 8192, },
+-
+- /* End marker */
+- { .klen = 0, .blen = 0, }
+-};
++static u8 speed_template_8[] = {8, 0};
++static u8 speed_template_24[] = {24, 0};
++static u8 speed_template_8_32[] = {8, 32, 0};
++static u8 speed_template_16_32[] = {16, 32, 0};
++static u8 speed_template_16_24_32[] = {16, 24, 32, 0};
++static u8 speed_template_32_40_48[] = {32, 40, 48, 0};
++static u8 speed_template_32_48_64[] = {32, 48, 64, 0};
+
+ /*
+ * Digest speed tests
+ */
+ static struct hash_speed generic_hash_speed_template[] = {
+- { .blen = 16, .plen = 16, },
++ { .blen = 16, .plen = 16, },
+ { .blen = 64, .plen = 16, },
+ { .blen = 64, .plen = 64, },
+ { .blen = 256, .plen = 16, },
+@@ -8186,41 +8272,4 @@ static struct hash_speed generic_hash_speed_template[] = {
+ { .blen = 0, .plen = 0, }
+ };
+
+-static struct cipher_speed camellia_speed_template[] = {
+- { .klen = 16, .blen = 16, },
+- { .klen = 16, .blen = 64, },
+- { .klen = 16, .blen = 256, },
+- { .klen = 16, .blen = 1024, },
+- { .klen = 16, .blen = 8192, },
+- { .klen = 24, .blen = 16, },
+- { .klen = 24, .blen = 64, },
+- { .klen = 24, .blen = 256, },
+- { .klen = 24, .blen = 1024, },
+- { .klen = 24, .blen = 8192, },
+- { .klen = 32, .blen = 16, },
+- { .klen = 32, .blen = 64, },
+- { .klen = 32, .blen = 256, },
+- { .klen = 32, .blen = 1024, },
+- { .klen = 32, .blen = 8192, },
+-
+- /* End marker */
+- { .klen = 0, .blen = 0, }
+-};
+-
+-static struct cipher_speed salsa20_speed_template[] = {
+- { .klen = 16, .blen = 16, },
+- { .klen = 16, .blen = 64, },
+- { .klen = 16, .blen = 256, },
+- { .klen = 16, .blen = 1024, },
+- { .klen = 16, .blen = 8192, },
+- { .klen = 32, .blen = 16, },
+- { .klen = 32, .blen = 64, },
+- { .klen = 32, .blen = 256, },
+- { .klen = 32, .blen = 1024, },
+- { .klen = 32, .blen = 8192, },
+-
+- /* End marker */
+- { .klen = 0, .blen = 0, }
+-};
+-
+ #endif /* _CRYPTO_TCRYPT_H */
+diff --git a/crypto/tea.c b/crypto/tea.c
+index 6893b3f..412bc74 100644
+--- a/crypto/tea.c
++++ b/crypto/tea.c
+@@ -267,7 +267,7 @@ static struct crypto_alg xeta_alg = {
+ .cia_decrypt = xeta_decrypt } }
+ };
+
+-static int __init init(void)
++static int __init tea_mod_init(void)
+ {
+ int ret = 0;
+
+@@ -292,7 +292,7 @@ out:
+ return ret;
+ }
+
+-static void __exit fini(void)
++static void __exit tea_mod_fini(void)
+ {
+ crypto_unregister_alg(&tea_alg);
+ crypto_unregister_alg(&xtea_alg);
+@@ -302,8 +302,8 @@ static void __exit fini(void)
+ MODULE_ALIAS("xtea");
+ MODULE_ALIAS("xeta");
+
+-module_init(init);
+-module_exit(fini);
++module_init(tea_mod_init);
++module_exit(tea_mod_fini);
+
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("TEA, XTEA & XETA Cryptographic Algorithms");
+diff --git a/crypto/tgr192.c b/crypto/tgr192.c
+index 2e7ea16..a92414f 100644
+--- a/crypto/tgr192.c
++++ b/crypto/tgr192.c
+@@ -663,7 +663,7 @@ static struct crypto_alg tgr128 = {
+ .dia_final = tgr128_final}}
+ };
+
+-static int __init init(void)
++static int __init tgr192_mod_init(void)
+ {
+ int ret = 0;
+
+@@ -688,7 +688,7 @@ static int __init init(void)
+ return ret;
+ }
+
+-static void __exit fini(void)
++static void __exit tgr192_mod_fini(void)
+ {
+ crypto_unregister_alg(&tgr192);
+ crypto_unregister_alg(&tgr160);
+@@ -698,8 +698,8 @@ static void __exit fini(void)
+ MODULE_ALIAS("tgr160");
+ MODULE_ALIAS("tgr128");
+
+-module_init(init);
+-module_exit(fini);
++module_init(tgr192_mod_init);
++module_exit(tgr192_mod_fini);
+
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Tiger Message Digest Algorithm");
+diff --git a/crypto/twofish.c b/crypto/twofish.c
+index 4979a2b..dfcda23 100644
+--- a/crypto/twofish.c
++++ b/crypto/twofish.c
+@@ -197,18 +197,18 @@ static struct crypto_alg alg = {
+ .cia_decrypt = twofish_decrypt } }
+ };
+
+-static int __init init(void)
++static int __init twofish_mod_init(void)
+ {
+ return crypto_register_alg(&alg);
+ }
+
+-static void __exit fini(void)
++static void __exit twofish_mod_fini(void)
+ {
+ crypto_unregister_alg(&alg);
+ }
+
+-module_init(init);
+-module_exit(fini);
++module_init(twofish_mod_init);
++module_exit(twofish_mod_fini);
+
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION ("Twofish Cipher Algorithm");
+diff --git a/crypto/wp512.c b/crypto/wp512.c
+index f746952..bff2856 100644
+--- a/crypto/wp512.c
++++ b/crypto/wp512.c
+@@ -1146,7 +1146,7 @@ static struct crypto_alg wp256 = {
+ .dia_final = wp256_final } }
+ };
+
+-static int __init init(void)
++static int __init wp512_mod_init(void)
+ {
+ int ret = 0;
+
+@@ -1172,7 +1172,7 @@ out:
+ return ret;
+ }
+
+-static void __exit fini(void)
++static void __exit wp512_mod_fini(void)
+ {
+ crypto_unregister_alg(&wp512);
+ crypto_unregister_alg(&wp384);
+@@ -1182,8 +1182,8 @@ static void __exit fini(void)
+ MODULE_ALIAS("wp384");
+ MODULE_ALIAS("wp256");
+
+-module_init(init);
+-module_exit(fini);
++module_init(wp512_mod_init);
++module_exit(wp512_mod_fini);
+
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Whirlpool Message Digest Algorithm");
+diff --git a/drivers/Kconfig b/drivers/Kconfig
+index 3a0e354..80f0ec9 100644
+--- a/drivers/Kconfig
++++ b/drivers/Kconfig
+@@ -97,4 +97,6 @@ source "drivers/dca/Kconfig"
+ source "drivers/auxdisplay/Kconfig"
+
+ source "drivers/uio/Kconfig"
++
++source "drivers/xen/Kconfig"
+ endmenu
+diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
+index 76b9bea..43a95e5 100644
+--- a/drivers/acpi/ac.c
++++ b/drivers/acpi/ac.c
+@@ -63,7 +63,7 @@ static int acpi_ac_add(struct acpi_device *device);
+ static int acpi_ac_remove(struct acpi_device *device, int type);
+ static int acpi_ac_resume(struct acpi_device *device);
+
+-const static struct acpi_device_id ac_device_ids[] = {
++static const struct acpi_device_id ac_device_ids[] = {
+ {"ACPI0003", 0},
+ {"", 0},
+ };
+diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
+index a697fb6..a498a6c 100644
+--- a/drivers/acpi/osl.c
++++ b/drivers/acpi/osl.c
+@@ -4,6 +4,8 @@
+ * Copyright (C) 2000 Andrew Henroid
+ * Copyright (C) 2001, 2002 Andy Grover <andrew.grover at intel.com>
+ * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh at intel.com>
++ * Copyright (c) 2008 Intel Corporation
++ * Author: Matthew Wilcox <willy at linux.intel.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+@@ -37,15 +39,18 @@
+ #include <linux/workqueue.h>
+ #include <linux/nmi.h>
+ #include <linux/acpi.h>
+-#include <acpi/acpi.h>
+-#include <asm/io.h>
+-#include <acpi/acpi_bus.h>
+-#include <acpi/processor.h>
+-#include <asm/uaccess.h>
+-
+ #include <linux/efi.h>
+ #include <linux/ioport.h>
+ #include <linux/list.h>
++#include <linux/jiffies.h>
++#include <linux/semaphore.h>
++
++#include <asm/io.h>
++#include <asm/uaccess.h>
++
++#include <acpi/acpi.h>
++#include <acpi/acpi_bus.h>
++#include <acpi/processor.h>
+
+ #define _COMPONENT ACPI_OS_SERVICES
+ ACPI_MODULE_NAME("osl");
+@@ -764,7 +769,6 @@ acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle)
+ {
+ struct semaphore *sem = NULL;
+
+-
+ sem = acpi_os_allocate(sizeof(struct semaphore));
+ if (!sem)
+ return AE_NO_MEMORY;
+@@ -791,12 +795,12 @@ acpi_status acpi_os_delete_semaphore(acpi_handle handle)
+ {
+ struct semaphore *sem = (struct semaphore *)handle;
+
+-
+ if (!sem)
+ return AE_BAD_PARAMETER;
+
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle));
+
++ BUG_ON(!list_empty(&sem->wait_list));
+ kfree(sem);
+ sem = NULL;
+
+@@ -804,21 +808,15 @@ acpi_status acpi_os_delete_semaphore(acpi_handle handle)
+ }
+
+ /*
+- * TODO: The kernel doesn't have a 'down_timeout' function -- had to
+- * improvise. The process is to sleep for one scheduler quantum
+- * until the semaphore becomes available. Downside is that this
+- * may result in starvation for timeout-based waits when there's
+- * lots of semaphore activity.
+- *
+ * TODO: Support for units > 1?
+ */
+ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
+ {
+ acpi_status status = AE_OK;
+ struct semaphore *sem = (struct semaphore *)handle;
++ long jiffies;
+ int ret = 0;
+
+-
+ if (!sem || (units < 1))
+ return AE_BAD_PARAMETER;
+
+@@ -828,58 +826,14 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n",
+ handle, units, timeout));
+
+- /*
+- * This can be called during resume with interrupts off.
+- * Like boot-time, we should be single threaded and will
+- * always get the lock if we try -- timeout or not.
+- * If this doesn't succeed, then we will oops courtesy of
+- * might_sleep() in down().
+- */
+- if (!down_trylock(sem))
+- return AE_OK;
+-
+- switch (timeout) {
+- /*
+- * No Wait:
+- * --------
+- * A zero timeout value indicates that we shouldn't wait - just
+- * acquire the semaphore if available otherwise return AE_TIME
+- * (a.k.a. 'would block').
+- */
+- case 0:
+- if (down_trylock(sem))
+- status = AE_TIME;
+- break;
+-
+- /*
+- * Wait Indefinitely:
+- * ------------------
+- */
+- case ACPI_WAIT_FOREVER:
+- down(sem);
+- break;
+-
+- /*
+- * Wait w/ Timeout:
+- * ----------------
+- */
+- default:
+- // TODO: A better timeout algorithm?
+- {
+- int i = 0;
+- static const int quantum_ms = 1000 / HZ;
+-
+- ret = down_trylock(sem);
+- for (i = timeout; (i > 0 && ret != 0); i -= quantum_ms) {
+- schedule_timeout_interruptible(1);
+- ret = down_trylock(sem);
+- }
+-
+- if (ret != 0)
+- status = AE_TIME;
+- }
+- break;
+- }
++ if (timeout == ACPI_WAIT_FOREVER)
++ jiffies = MAX_SCHEDULE_TIMEOUT;
++ else
++ jiffies = msecs_to_jiffies(timeout);
++
++ ret = down_timeout(sem, jiffies);
++ if (ret)
++ status = AE_TIME;
+
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
+@@ -902,7 +856,6 @@ acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units)
+ {
+ struct semaphore *sem = (struct semaphore *)handle;
+
+-
+ if (!sem || (units < 1))
+ return AE_BAD_PARAMETER;
+
+diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
+index 1b8e592..0bba3a9 100644
+--- a/drivers/acpi/processor_throttling.c
++++ b/drivers/acpi/processor_throttling.c
+@@ -838,10 +838,10 @@ static int acpi_processor_get_throttling(struct acpi_processor *pr)
+ * Migrate task to the cpu pointed by pr.
+ */
+ saved_mask = current->cpus_allowed;
+- set_cpus_allowed(current, cpumask_of_cpu(pr->id));
++ set_cpus_allowed_ptr(current, &cpumask_of_cpu(pr->id));
+ ret = pr->throttling.acpi_processor_get_throttling(pr);
+ /* restore the previous state */
+- set_cpus_allowed(current, saved_mask);
++ set_cpus_allowed_ptr(current, &saved_mask);
+
+ return ret;
+ }
+@@ -1025,7 +1025,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
+ * it can be called only for the cpu pointed by pr.
+ */
+ if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
+- set_cpus_allowed(current, cpumask_of_cpu(pr->id));
++ set_cpus_allowed_ptr(current, &cpumask_of_cpu(pr->id));
+ ret = p_throttling->acpi_processor_set_throttling(pr,
+ t_state.target_state);
+ } else {
+@@ -1056,7 +1056,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
+ continue;
+ }
+ t_state.cpu = i;
+- set_cpus_allowed(current, cpumask_of_cpu(i));
++ set_cpus_allowed_ptr(current, &cpumask_of_cpu(i));
+ ret = match_pr->throttling.
+ acpi_processor_set_throttling(
+ match_pr, t_state.target_state);
+@@ -1074,7 +1074,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
+ &t_state);
+ }
+ /* restore the previous state */
+- set_cpus_allowed(current, saved_mask);
++ set_cpus_allowed_ptr(current, &saved_mask);
+ return ret;
+ }
+
+diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
+index 25aba69..292aa9a 100644
+--- a/drivers/ata/Kconfig
++++ b/drivers/ata/Kconfig
+@@ -28,7 +28,7 @@ config ATA_NONSTANDARD
+ default n
+
+ config ATA_ACPI
+- bool
++ bool "ATA ACPI Support"
+ depends on ACPI && PCI
+ select ACPI_DOCK
+ default y
+@@ -41,6 +41,13 @@ config ATA_ACPI
+ You can disable this at kernel boot time by using the
+ option libata.noacpi=1
+
++config SATA_PMP
++ bool "SATA Port Multiplier support"
++ default y
++ help
++ This option adds support for SATA Port Multipliers
++ (the SATA version of an ethernet hub, or SAS expander).
++
+ config SATA_AHCI
+ tristate "AHCI SATA support"
+ depends on PCI
+@@ -49,6 +56,43 @@ config SATA_AHCI
+
+ If unsure, say N.
+
++config SATA_SIL24
++ tristate "Silicon Image 3124/3132 SATA support"
++ depends on PCI
++ help
++ This option enables support for Silicon Image 3124/3132 Serial ATA.
++
++ If unsure, say N.
++
++config SATA_FSL
++ tristate "Freescale 3.0Gbps SATA support"
++ depends on FSL_SOC
++ help
++ This option enables support for Freescale 3.0Gbps SATA controller.
++ It can be found on MPC837x and MPC8315.
++
++ If unsure, say N.
++
++config ATA_SFF
++ bool "ATA SFF support"
++ default y
++ help
++ This option adds support for ATA controllers with SFF
++ compliant or similar programming interface.
++
++ SFF is the legacy IDE interface that has been around since
++ the dawn of time. Almost all PATA controllers have an
++ SFF interface. Many SATA controllers have an SFF interface
++ when configured into a legacy compatibility mode.
++
++ For users with exclusively modern controllers like AHCI,
++ Silicon Image 3124, or Marvell 6440, you may choose to
++ disable this uneeded SFF support.
++
++ If unsure, say Y.
++
++if ATA_SFF
++
+ config SATA_SVW
+ tristate "ServerWorks Frodo / Apple K2 SATA support"
+ depends on PCI
+@@ -125,14 +169,6 @@ config SATA_SIL
+
+ If unsure, say N.
+
+-config SATA_SIL24
+- tristate "Silicon Image 3124/3132 SATA support"
+- depends on PCI
+- help
+- This option enables support for Silicon Image 3124/3132 Serial ATA.
+-
+- If unsure, say N.
+-
+ config SATA_SIS
+ tristate "SiS 964/965/966/180 SATA support"
+ depends on PCI
+@@ -183,15 +219,6 @@ config PATA_ACPI
+ firmware in the BIOS. This driver can sometimes handle
+ otherwise unsupported hardware.
+
+-config SATA_FSL
+- tristate "Freescale 3.0Gbps SATA support"
+- depends on FSL_SOC
+- help
+- This option enables support for Freescale 3.0Gbps SATA controller.
+- It can be found on MPC837x and MPC8315.
+-
+- If unsure, say N.
+-
+ config PATA_ALI
+ tristate "ALi PATA support (Experimental)"
+ depends on PCI && EXPERIMENTAL
+@@ -679,4 +706,5 @@ config PATA_BF54X
+
+ If unsure, say N.
+
++endif # ATA_SFF
+ endif # ATA
+diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
+index 0511e6f..1fbc2aa 100644
+--- a/drivers/ata/Makefile
++++ b/drivers/ata/Makefile
+@@ -78,6 +78,7 @@ obj-$(CONFIG_ATA_GENERIC) += ata_generic.o
+ # Should be last libata driver
+ obj-$(CONFIG_PATA_LEGACY) += pata_legacy.o
+
+-libata-objs := libata-core.o libata-scsi.o libata-sff.o libata-eh.o \
+- libata-pmp.o
++libata-objs := libata-core.o libata-scsi.o libata-eh.o
++libata-$(CONFIG_ATA_SFF) += libata-sff.o
++libata-$(CONFIG_SATA_PMP) += libata-pmp.o
+ libata-$(CONFIG_ATA_ACPI) += libata-acpi.o
+diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
+index b1eb4e2..7c4f886 100644
+--- a/drivers/ata/ahci.c
++++ b/drivers/ata/ahci.c
+@@ -62,7 +62,6 @@ enum {
+ AHCI_MAX_PORTS = 32,
+ AHCI_MAX_SG = 168, /* hardware max is 64K */
+ AHCI_DMA_BOUNDARY = 0xffffffff,
+- AHCI_USE_CLUSTERING = 1,
+ AHCI_MAX_CMDS = 32,
+ AHCI_CMD_SZ = 32,
+ AHCI_CMD_SLOT_SZ = AHCI_MAX_CMDS * AHCI_CMD_SZ,
+@@ -198,7 +197,6 @@ enum {
+ ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+ ATA_FLAG_ACPI_SATA | ATA_FLAG_AN |
+ ATA_FLAG_IPM,
+- AHCI_LFLAG_COMMON = ATA_LFLAG_SKIP_D2H_BSY,
+
+ ICH_MAP = 0x90, /* ICH MAP register */
+ };
+@@ -245,19 +243,24 @@ static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
+ static int ahci_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
+ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
+-static void ahci_irq_clear(struct ata_port *ap);
++static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc);
+ static int ahci_port_start(struct ata_port *ap);
+ static void ahci_port_stop(struct ata_port *ap);
+-static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
+ static void ahci_qc_prep(struct ata_queued_cmd *qc);
+-static u8 ahci_check_status(struct ata_port *ap);
+ static void ahci_freeze(struct ata_port *ap);
+ static void ahci_thaw(struct ata_port *ap);
+ static void ahci_pmp_attach(struct ata_port *ap);
+ static void ahci_pmp_detach(struct ata_port *ap);
++static int ahci_softreset(struct ata_link *link, unsigned int *class,
++ unsigned long deadline);
++static int ahci_hardreset(struct ata_link *link, unsigned int *class,
++ unsigned long deadline);
++static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
++ unsigned long deadline);
++static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
++ unsigned long deadline);
++static void ahci_postreset(struct ata_link *link, unsigned int *class);
+ static void ahci_error_handler(struct ata_port *ap);
+-static void ahci_vt8251_error_handler(struct ata_port *ap);
+-static void ahci_p5wdh_error_handler(struct ata_port *ap);
+ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
+ static int ahci_port_resume(struct ata_port *ap);
+ static void ahci_dev_config(struct ata_device *dev);
+@@ -270,135 +273,60 @@ static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
+ static int ahci_pci_device_resume(struct pci_dev *pdev);
+ #endif
+
+-static struct class_device_attribute *ahci_shost_attrs[] = {
+- &class_device_attr_link_power_management_policy,
++static struct device_attribute *ahci_shost_attrs[] = {
++ &dev_attr_link_power_management_policy,
+ NULL
+ };
+
+ static struct scsi_host_template ahci_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .change_queue_depth = ata_scsi_change_queue_depth,
++ ATA_NCQ_SHT(DRV_NAME),
+ .can_queue = AHCI_MAX_CMDS - 1,
+- .this_id = ATA_SHT_THIS_ID,
+ .sg_tablesize = AHCI_MAX_SG,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = AHCI_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+ .dma_boundary = AHCI_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
+ .shost_attrs = ahci_shost_attrs,
+ };
+
+-static const struct ata_port_operations ahci_ops = {
+- .check_status = ahci_check_status,
+- .check_altstatus = ahci_check_status,
+- .dev_select = ata_noop_dev_select,
+-
+- .dev_config = ahci_dev_config,
+-
+- .tf_read = ahci_tf_read,
++static struct ata_port_operations ahci_ops = {
++ .inherits = &sata_pmp_port_ops,
+
+ .qc_defer = sata_pmp_qc_defer_cmd_switch,
+ .qc_prep = ahci_qc_prep,
+ .qc_issue = ahci_qc_issue,
+-
+- .irq_clear = ahci_irq_clear,
+-
+- .scr_read = ahci_scr_read,
+- .scr_write = ahci_scr_write,
++ .qc_fill_rtf = ahci_qc_fill_rtf,
+
+ .freeze = ahci_freeze,
+ .thaw = ahci_thaw,
+-
++ .softreset = ahci_softreset,
++ .hardreset = ahci_hardreset,
++ .postreset = ahci_postreset,
++ .pmp_softreset = ahci_softreset,
+ .error_handler = ahci_error_handler,
+ .post_internal_cmd = ahci_post_internal_cmd,
+-
+- .pmp_attach = ahci_pmp_attach,
+- .pmp_detach = ahci_pmp_detach,
+-
+-#ifdef CONFIG_PM
+- .port_suspend = ahci_port_suspend,
+- .port_resume = ahci_port_resume,
+-#endif
+- .enable_pm = ahci_enable_alpm,
+- .disable_pm = ahci_disable_alpm,
+-
+- .port_start = ahci_port_start,
+- .port_stop = ahci_port_stop,
+-};
+-
+-static const struct ata_port_operations ahci_vt8251_ops = {
+- .check_status = ahci_check_status,
+- .check_altstatus = ahci_check_status,
+- .dev_select = ata_noop_dev_select,
+-
+- .tf_read = ahci_tf_read,
+-
+- .qc_defer = sata_pmp_qc_defer_cmd_switch,
+- .qc_prep = ahci_qc_prep,
+- .qc_issue = ahci_qc_issue,
+-
+- .irq_clear = ahci_irq_clear,
++ .dev_config = ahci_dev_config,
+
+ .scr_read = ahci_scr_read,
+ .scr_write = ahci_scr_write,
+-
+- .freeze = ahci_freeze,
+- .thaw = ahci_thaw,
+-
+- .error_handler = ahci_vt8251_error_handler,
+- .post_internal_cmd = ahci_post_internal_cmd,
+-
+ .pmp_attach = ahci_pmp_attach,
+ .pmp_detach = ahci_pmp_detach,
+
++ .enable_pm = ahci_enable_alpm,
++ .disable_pm = ahci_disable_alpm,
+ #ifdef CONFIG_PM
+ .port_suspend = ahci_port_suspend,
+ .port_resume = ahci_port_resume,
+ #endif
+-
+ .port_start = ahci_port_start,
+ .port_stop = ahci_port_stop,
+ };
+
+-static const struct ata_port_operations ahci_p5wdh_ops = {
+- .check_status = ahci_check_status,
+- .check_altstatus = ahci_check_status,
+- .dev_select = ata_noop_dev_select,
+-
+- .tf_read = ahci_tf_read,
+-
+- .qc_defer = sata_pmp_qc_defer_cmd_switch,
+- .qc_prep = ahci_qc_prep,
+- .qc_issue = ahci_qc_issue,
+-
+- .irq_clear = ahci_irq_clear,
+-
+- .scr_read = ahci_scr_read,
+- .scr_write = ahci_scr_write,
+-
+- .freeze = ahci_freeze,
+- .thaw = ahci_thaw,
+-
+- .error_handler = ahci_p5wdh_error_handler,
+- .post_internal_cmd = ahci_post_internal_cmd,
+-
+- .pmp_attach = ahci_pmp_attach,
+- .pmp_detach = ahci_pmp_detach,
+-
+-#ifdef CONFIG_PM
+- .port_suspend = ahci_port_suspend,
+- .port_resume = ahci_port_resume,
+-#endif
++static struct ata_port_operations ahci_vt8251_ops = {
++ .inherits = &ahci_ops,
++ .hardreset = ahci_vt8251_hardreset,
++};
+
+- .port_start = ahci_port_start,
+- .port_stop = ahci_port_stop,
++static struct ata_port_operations ahci_p5wdh_ops = {
++ .inherits = &ahci_ops,
++ .hardreset = ahci_p5wdh_hardreset,
+ };
+
+ #define AHCI_HFLAGS(flags) .private_data = (void *)(flags)
+@@ -407,7 +335,6 @@ static const struct ata_port_info ahci_port_info[] = {
+ /* board_ahci */
+ {
+ .flags = AHCI_FLAG_COMMON,
+- .link_flags = AHCI_LFLAG_COMMON,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &ahci_ops,
+@@ -416,7 +343,6 @@ static const struct ata_port_info ahci_port_info[] = {
+ {
+ AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
+ .flags = AHCI_FLAG_COMMON,
+- .link_flags = AHCI_LFLAG_COMMON | ATA_LFLAG_HRST_TO_RESUME,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &ahci_vt8251_ops,
+@@ -425,7 +351,6 @@ static const struct ata_port_info ahci_port_info[] = {
+ {
+ AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR),
+ .flags = AHCI_FLAG_COMMON,
+- .link_flags = AHCI_LFLAG_COMMON,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &ahci_ops,
+@@ -436,7 +361,6 @@ static const struct ata_port_info ahci_port_info[] = {
+ AHCI_HFLAG_32BIT_ONLY |
+ AHCI_HFLAG_SECT255 | AHCI_HFLAG_NO_PMP),
+ .flags = AHCI_FLAG_COMMON,
+- .link_flags = AHCI_LFLAG_COMMON,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &ahci_ops,
+@@ -447,7 +371,6 @@ static const struct ata_port_info ahci_port_info[] = {
+ AHCI_HFLAG_MV_PATA),
+ .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
+- .link_flags = AHCI_LFLAG_COMMON,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &ahci_ops,
+@@ -457,7 +380,6 @@ static const struct ata_port_info ahci_port_info[] = {
+ AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL |
+ AHCI_HFLAG_NO_PMP),
+ .flags = AHCI_FLAG_COMMON,
+- .link_flags = AHCI_LFLAG_COMMON,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &ahci_ops,
+@@ -634,16 +556,27 @@ static inline void __iomem *ahci_port_base(struct ata_port *ap)
+
+ static void ahci_enable_ahci(void __iomem *mmio)
+ {
++ int i;
+ u32 tmp;
+
+ /* turn on AHCI_EN */
+ tmp = readl(mmio + HOST_CTL);
+- if (!(tmp & HOST_AHCI_EN)) {
++ if (tmp & HOST_AHCI_EN)
++ return;
++
++ /* Some controllers need AHCI_EN to be written multiple times.
++ * Try a few times before giving up.
++ */
++ for (i = 0; i < 5; i++) {
+ tmp |= HOST_AHCI_EN;
+ writel(tmp, mmio + HOST_CTL);
+ tmp = readl(mmio + HOST_CTL); /* flush && sanity check */
+- WARN_ON(!(tmp & HOST_AHCI_EN));
++ if (tmp & HOST_AHCI_EN)
++ return;
++ msleep(10);
+ }
++
++ WARN_ON(1);
+ }
+
+ /**
+@@ -1255,13 +1188,14 @@ static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
+
+ static int ahci_kick_engine(struct ata_port *ap, int force_restart)
+ {
+- void __iomem *port_mmio = ap->ioaddr.cmd_addr;
++ void __iomem *port_mmio = ahci_port_base(ap);
+ struct ahci_host_priv *hpriv = ap->host->private_data;
++ u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
+ u32 tmp;
+ int busy, rc;
+
+ /* do we need to kick the port? */
+- busy = ahci_check_status(ap) & (ATA_BUSY | ATA_DRQ);
++ busy = status & (ATA_BUSY | ATA_DRQ);
+ if (!busy && !force_restart)
+ return 0;
+
+@@ -1328,10 +1262,21 @@ static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp,
+ return 0;
+ }
+
+-static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
+- int pmp, unsigned long deadline)
++static int ahci_check_ready(struct ata_link *link)
++{
++ void __iomem *port_mmio = ahci_port_base(link->ap);
++ u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
++
++ if (!(status & ATA_BUSY))
++ return 1;
++ return 0;
++}
++
++static int ahci_softreset(struct ata_link *link, unsigned int *class,
++ unsigned long deadline)
+ {
+ struct ata_port *ap = link->ap;
++ int pmp = sata_srst_pmp(link);
+ const char *reason = NULL;
+ unsigned long now, msecs;
+ struct ata_taskfile tf;
+@@ -1339,12 +1284,6 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
+
+ DPRINTK("ENTER\n");
+
+- if (ata_link_offline(link)) {
+- DPRINTK("PHY reports no device\n");
+- *class = ATA_DEV_NONE;
+- return 0;
+- }
+-
+ /* prepare for SRST (AHCI-1.1 10.4.1) */
+ rc = ahci_kick_engine(ap, 1);
+ if (rc && rc != -EOPNOTSUPP)
+@@ -1374,10 +1313,8 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
+ tf.ctl &= ~ATA_SRST;
+ ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0);
+
+- /* wait a while before checking status */
+- ata_wait_after_reset(ap, deadline);
+-
+- rc = ata_wait_ready(ap, deadline);
++ /* wait for link to become ready */
++ rc = ata_wait_after_reset(link, deadline, ahci_check_ready);
+ /* link occupied, -ENODEV too is an error */
+ if (rc) {
+ reason = "device not ready";
+@@ -1393,24 +1330,15 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
+ return rc;
+ }
+
+-static int ahci_softreset(struct ata_link *link, unsigned int *class,
+- unsigned long deadline)
+-{
+- int pmp = 0;
+-
+- if (link->ap->flags & ATA_FLAG_PMP)
+- pmp = SATA_PMP_CTRL_PORT;
+-
+- return ahci_do_softreset(link, class, pmp, deadline);
+-}
+-
+ static int ahci_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline)
+ {
++ const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
+ struct ata_port *ap = link->ap;
+ struct ahci_port_priv *pp = ap->private_data;
+ u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
+ struct ata_taskfile tf;
++ bool online;
+ int rc;
+
+ DPRINTK("ENTER\n");
+@@ -1422,14 +1350,13 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class,
+ tf.command = 0x80;
+ ata_tf_to_fis(&tf, 0, 0, d2h_fis);
+
+- rc = sata_std_hardreset(link, class, deadline);
++ rc = sata_link_hardreset(link, timing, deadline, &online,
++ ahci_check_ready);
+
+ ahci_start_engine(ap);
+
+- if (rc == 0 && ata_link_online(link))
++ if (online)
+ *class = ahci_dev_classify(ap);
+- if (rc != -EAGAIN && *class == ATA_DEV_UNKNOWN)
+- *class = ATA_DEV_NONE;
+
+ DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
+ return rc;
+@@ -1439,7 +1366,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline)
+ {
+ struct ata_port *ap = link->ap;
+- u32 serror;
++ bool online;
+ int rc;
+
+ DPRINTK("ENTER\n");
+@@ -1447,11 +1374,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
+ ahci_stop_engine(ap);
+
+ rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
+- deadline);
+-
+- /* vt8251 needs SError cleared for the port to operate */
+- ahci_scr_read(ap, SCR_ERROR, &serror);
+- ahci_scr_write(ap, SCR_ERROR, serror);
++ deadline, &online, NULL);
+
+ ahci_start_engine(ap);
+
+@@ -1460,7 +1383,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
+ /* vt8251 doesn't clear BSY on signature FIS reception,
+ * request follow-up softreset.
+ */
+- return rc ?: -EAGAIN;
++ return online ? -EAGAIN : rc;
+ }
+
+ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
+@@ -1470,6 +1393,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
+ struct ahci_port_priv *pp = ap->private_data;
+ u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
+ struct ata_taskfile tf;
++ bool online;
+ int rc;
+
+ ahci_stop_engine(ap);
+@@ -1480,16 +1404,10 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
+ ata_tf_to_fis(&tf, 0, 0, d2h_fis);
+
+ rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
+- deadline);
++ deadline, &online, NULL);
+
+ ahci_start_engine(ap);
+
+- if (rc || ata_link_offline(link))
+- return rc;
+-
+- /* spec mandates ">= 2ms" before checking status */
+- msleep(150);
+-
+ /* The pseudo configuration device on SIMG4726 attached to
+ * ASUS P5W-DH Deluxe doesn't send signature FIS after
+ * hardreset if no device is attached to the first downstream
+@@ -1503,11 +1421,13 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
+ * have to be reset again. For most cases, this should
+ * suffice while making probing snappish enough.
+ */
+- rc = ata_wait_ready(ap, jiffies + 2 * HZ);
+- if (rc)
+- ahci_kick_engine(ap, 0);
+-
+- return 0;
++ if (online) {
++ rc = ata_wait_after_reset(link, jiffies + 2 * HZ,
++ ahci_check_ready);
++ if (rc)
++ ahci_kick_engine(ap, 0);
++ }
++ return rc;
+ }
+
+ static void ahci_postreset(struct ata_link *link, unsigned int *class)
+@@ -1530,27 +1450,6 @@ static void ahci_postreset(struct ata_link *link, unsigned int *class)
+ }
+ }
+
+-static int ahci_pmp_softreset(struct ata_link *link, unsigned int *class,
+- unsigned long deadline)
+-{
+- return ahci_do_softreset(link, class, link->pmp, deadline);
+-}
+-
+-static u8 ahci_check_status(struct ata_port *ap)
+-{
+- void __iomem *mmio = ap->ioaddr.cmd_addr;
+-
+- return readl(mmio + PORT_TFDATA) & 0xFF;
+-}
+-
+-static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+-{
+- struct ahci_port_priv *pp = ap->private_data;
+- u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
+-
+- ata_tf_from_fis(d2h_fis, tf);
+-}
+-
+ static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
+ {
+ struct scatterlist *sg;
+@@ -1663,27 +1562,27 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
+ u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK);
+
+ active_ehi->err_mask |= AC_ERR_HSM;
+- active_ehi->action |= ATA_EH_SOFTRESET;
++ active_ehi->action |= ATA_EH_RESET;
+ ata_ehi_push_desc(active_ehi,
+ "unknown FIS %08x %08x %08x %08x" ,
+ unk[0], unk[1], unk[2], unk[3]);
+ }
+
+- if (ap->nr_pmp_links && (irq_stat & PORT_IRQ_BAD_PMP)) {
++ if (sata_pmp_attached(ap) && (irq_stat & PORT_IRQ_BAD_PMP)) {
+ active_ehi->err_mask |= AC_ERR_HSM;
+- active_ehi->action |= ATA_EH_SOFTRESET;
++ active_ehi->action |= ATA_EH_RESET;
+ ata_ehi_push_desc(active_ehi, "incorrect PMP");
+ }
+
+ if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) {
+ host_ehi->err_mask |= AC_ERR_HOST_BUS;
+- host_ehi->action |= ATA_EH_SOFTRESET;
++ host_ehi->action |= ATA_EH_RESET;
+ ata_ehi_push_desc(host_ehi, "host bus error");
+ }
+
+ if (irq_stat & PORT_IRQ_IF_ERR) {
+ host_ehi->err_mask |= AC_ERR_ATA_BUS;
+- host_ehi->action |= ATA_EH_SOFTRESET;
++ host_ehi->action |= ATA_EH_RESET;
+ ata_ehi_push_desc(host_ehi, "interface fatal error");
+ }
+
+@@ -1704,7 +1603,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
+
+ static void ahci_port_intr(struct ata_port *ap)
+ {
+- void __iomem *port_mmio = ap->ioaddr.cmd_addr;
++ void __iomem *port_mmio = ahci_port_base(ap);
+ struct ata_eh_info *ehi = &ap->link.eh_info;
+ struct ahci_port_priv *pp = ap->private_data;
+ struct ahci_host_priv *hpriv = ap->host->private_data;
+@@ -1766,21 +1665,16 @@ static void ahci_port_intr(struct ata_port *ap)
+ else
+ qc_active = readl(port_mmio + PORT_CMD_ISSUE);
+
+- rc = ata_qc_complete_multiple(ap, qc_active, NULL);
++ rc = ata_qc_complete_multiple(ap, qc_active);
+
+ /* while resetting, invalid completions are expected */
+ if (unlikely(rc < 0 && !resetting)) {
+ ehi->err_mask |= AC_ERR_HSM;
+- ehi->action |= ATA_EH_SOFTRESET;
++ ehi->action |= ATA_EH_RESET;
+ ata_port_freeze(ap);
+ }
+ }
+
+-static void ahci_irq_clear(struct ata_port *ap)
+-{
+- /* TODO */
+-}
+-
+ static irqreturn_t ahci_interrupt(int irq, void *dev_instance)
+ {
+ struct ata_host *host = dev_instance;
+@@ -1854,6 +1748,15 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
+ return 0;
+ }
+
++static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
++{
++ struct ahci_port_priv *pp = qc->ap->private_data;
++ u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
++
++ ata_tf_from_fis(d2h_fis, &qc->result_tf);
++ return true;
++}
++
+ static void ahci_freeze(struct ata_port *ap)
+ {
+ void __iomem *port_mmio = ahci_port_base(ap);
+@@ -1886,37 +1789,7 @@ static void ahci_error_handler(struct ata_port *ap)
+ ahci_start_engine(ap);
+ }
+
+- /* perform recovery */
+- sata_pmp_do_eh(ap, ata_std_prereset, ahci_softreset,
+- ahci_hardreset, ahci_postreset,
+- sata_pmp_std_prereset, ahci_pmp_softreset,
+- sata_pmp_std_hardreset, sata_pmp_std_postreset);
+-}
+-
+-static void ahci_vt8251_error_handler(struct ata_port *ap)
+-{
+- if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
+- /* restart engine */
+- ahci_stop_engine(ap);
+- ahci_start_engine(ap);
+- }
+-
+- /* perform recovery */
+- ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_vt8251_hardreset,
+- ahci_postreset);
+-}
+-
+-static void ahci_p5wdh_error_handler(struct ata_port *ap)
+-{
+- if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
+- /* restart engine */
+- ahci_stop_engine(ap);
+- ahci_start_engine(ap);
+- }
+-
+- /* perform recovery */
+- ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_p5wdh_hardreset,
+- ahci_postreset);
++ sata_pmp_error_handler(ap);
+ }
+
+ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
+@@ -1961,7 +1834,7 @@ static int ahci_port_resume(struct ata_port *ap)
+ ahci_power_up(ap);
+ ahci_start_port(ap);
+
+- if (ap->nr_pmp_links)
++ if (sata_pmp_attached(ap))
+ ahci_pmp_attach(ap);
+ else
+ ahci_pmp_detach(ap);
+@@ -2324,7 +2197,6 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+- void __iomem *port_mmio = ahci_port_base(ap);
+
+ ata_port_pbar_desc(ap, AHCI_PCI_BAR, -1, "abar");
+ ata_port_pbar_desc(ap, AHCI_PCI_BAR,
+@@ -2333,12 +2205,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ /* set initial link pm policy */
+ ap->pm_policy = NOT_AVAILABLE;
+
+- /* standard SATA port setup */
+- if (hpriv->port_map & (1 << i))
+- ap->ioaddr.cmd_addr = port_mmio;
+-
+ /* disabled/not-implemented port */
+- else
++ if (!(hpriv->port_map & (1 << i)))
+ ap->ops = &ata_dummy_port_ops;
+ }
+
+diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
+index 2053420..47aeccd 100644
+--- a/drivers/ata/ata_generic.c
++++ b/drivers/ata/ata_generic.c
+@@ -95,53 +95,13 @@ static int generic_set_mode(struct ata_link *link, struct ata_device **unused)
+ }
+
+ static struct scsi_host_template generic_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations generic_port_ops = {
+- .set_mode = generic_set_mode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_bmdma_port_ops,
+ .cable_detect = ata_cable_unknown,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .set_mode = generic_set_mode,
+ };
+
+ static int all_generic_ide; /* Set to claim all devices */
+@@ -160,7 +120,6 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
+ {
+ u16 command;
+ static const struct ata_port_info info = {
+- .sht = &generic_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -191,9 +150,9 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
+ return -ENODEV;
+
+ if (dev->vendor == PCI_VENDOR_ID_AL)
+- ata_pci_clear_simplex(dev);
++ ata_pci_bmdma_clear_simplex(dev);
+
+- return ata_pci_init_one(dev, ppi);
++ return ata_pci_sff_init_one(dev, ppi, &generic_sht, NULL);
+ }
+
+ static struct pci_device_id ata_generic[] = {
+diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
+index fae8404..ea2c764 100644
+--- a/drivers/ata/ata_piix.c
++++ b/drivers/ata/ata_piix.c
+@@ -100,13 +100,11 @@ enum {
+ PIIX_IOCFG = 0x54, /* IDE I/O configuration register */
+ ICH5_PMR = 0x90, /* port mapping register */
+ ICH5_PCS = 0x92, /* port control and status */
+- PIIX_SCC = 0x0A, /* sub-class code register */
+ PIIX_SIDPR_BAR = 5,
+ PIIX_SIDPR_LEN = 16,
+ PIIX_SIDPR_IDX = 0,
+ PIIX_SIDPR_DATA = 4,
+
+- PIIX_FLAG_AHCI = (1 << 27), /* AHCI possible */
+ PIIX_FLAG_CHECKINTR = (1 << 28), /* make sure PCI INTx enabled */
+ PIIX_FLAG_SIDPR = (1 << 29), /* SATA idx/data pair regs */
+
+@@ -140,12 +138,11 @@ enum piix_controller_ids {
+ ich_pata_100, /* ICH up to UDMA 100 */
+ ich5_sata,
+ ich6_sata,
+- ich6_sata_ahci,
+- ich6m_sata_ahci,
+- ich8_sata_ahci,
++ ich6m_sata,
++ ich8_sata,
+ ich8_2port_sata,
+- ich8m_apple_sata_ahci, /* locks up on second port enable */
+- tolapai_sata_ahci,
++ ich8m_apple_sata, /* locks up on second port enable */
++ tolapai_sata,
+ piix_pata_vmw, /* PIIX4 for VMware, spurious DMA_ERR */
+ };
+
+@@ -162,7 +159,7 @@ struct piix_host_priv {
+
+ static int piix_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent);
+-static void piix_pata_error_handler(struct ata_port *ap);
++static int piix_pata_prereset(struct ata_link *link, unsigned long deadline);
+ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev);
+ static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev);
+ static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev);
+@@ -170,7 +167,6 @@ static int ich_pata_cable_detect(struct ata_port *ap);
+ static u8 piix_vmw_bmdma_status(struct ata_port *ap);
+ static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val);
+ static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val);
+-static void piix_sidpr_error_handler(struct ata_port *ap);
+ #ifdef CONFIG_PM
+ static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
+ static int piix_pci_device_resume(struct pci_dev *pdev);
+@@ -236,25 +232,27 @@ static const struct pci_device_id piix_pci_tbl[] = {
+ /* 82801FB/FW (ICH6/ICH6W) */
+ { 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
+ /* 82801FR/FRW (ICH6R/ICH6RW) */
+- { 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+- /* 82801FBM ICH6M (ICH6R with only port 0 and 2 implemented) */
+- { 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci },
++ { 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
++ /* 82801FBM ICH6M (ICH6R with only port 0 and 2 implemented).
++ * Attach iff the controller is in IDE mode. */
++ { 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID,
++ PCI_CLASS_STORAGE_IDE << 8, 0xffff00, ich6m_sata },
+ /* 82801GB/GR/GH (ICH7, identical to ICH6) */
+- { 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
++ { 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
+ /* 2801GBM/GHM (ICH7M, identical to ICH6M) */
+- { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci },
++ { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata },
+ /* Enterprise Southbridge 2 (631xESB/632xESB) */
+- { 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
++ { 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
+ /* SATA Controller 1 IDE (ICH8) */
+- { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
++ { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+ /* SATA Controller 2 IDE (ICH8) */
+ { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+ /* Mobile SATA Controller IDE (ICH8M) */
+- { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
++ { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+ /* Mobile SATA Controller IDE (ICH8M), Apple */
+- { 0x8086, 0x2828, 0x106b, 0x00a0, 0, 0, ich8m_apple_sata_ahci },
++ { 0x8086, 0x2828, 0x106b, 0x00a0, 0, 0, ich8m_apple_sata },
+ /* SATA Controller IDE (ICH9) */
+- { 0x8086, 0x2920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
++ { 0x8086, 0x2920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+ /* SATA Controller IDE (ICH9) */
+ { 0x8086, 0x2921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+ /* SATA Controller IDE (ICH9) */
+@@ -264,15 +262,15 @@ static const struct pci_device_id piix_pci_tbl[] = {
+ /* SATA Controller IDE (ICH9M) */
+ { 0x8086, 0x292d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+ /* SATA Controller IDE (ICH9M) */
+- { 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
++ { 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+ /* SATA Controller IDE (Tolapai) */
+- { 0x8086, 0x5028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, tolapai_sata_ahci },
++ { 0x8086, 0x5028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, tolapai_sata },
+ /* SATA Controller IDE (ICH10) */
+- { 0x8086, 0x3a00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
++ { 0x8086, 0x3a00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+ /* SATA Controller IDE (ICH10) */
+ { 0x8086, 0x3a06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+ /* SATA Controller IDE (ICH10) */
+- { 0x8086, 0x3a20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
++ { 0x8086, 0x3a20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+ /* SATA Controller IDE (ICH10) */
+ { 0x8086, 0x3a26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+
+@@ -291,170 +289,37 @@ static struct pci_driver piix_pci_driver = {
+ };
+
+ static struct scsi_host_template piix_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static const struct ata_port_operations piix_pata_ops = {
++static struct ata_port_operations piix_pata_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .cable_detect = ata_cable_40wire,
+ .set_piomode = piix_set_piomode,
+ .set_dmamode = piix_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = piix_pata_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
++ .prereset = piix_pata_prereset,
++};
+
+- .port_start = ata_port_start,
++static struct ata_port_operations piix_vmw_ops = {
++ .inherits = &piix_pata_ops,
++ .bmdma_status = piix_vmw_bmdma_status,
+ };
+
+-static const struct ata_port_operations ich_pata_ops = {
+- .set_piomode = piix_set_piomode,
+- .set_dmamode = ich_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = piix_pata_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++static struct ata_port_operations ich_pata_ops = {
++ .inherits = &piix_pata_ops,
+ .cable_detect = ich_pata_cable_detect,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_port_start,
++ .set_dmamode = ich_set_dmamode,
+ };
+
+-static const struct ata_port_operations piix_sata_ops = {
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_port_start,
++static struct ata_port_operations piix_sata_ops = {
++ .inherits = &ata_bmdma_port_ops,
+ };
+
+-static const struct ata_port_operations piix_vmw_ops = {
+- .set_piomode = piix_set_piomode,
+- .set_dmamode = piix_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = piix_vmw_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = piix_pata_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_port_start,
+-};
+-
+-static const struct ata_port_operations piix_sidpr_sata_ops = {
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
++static struct ata_port_operations piix_sidpr_sata_ops = {
++ .inherits = &piix_sata_ops,
++ .hardreset = sata_std_hardreset,
+ .scr_read = piix_sidpr_scr_read,
+ .scr_write = piix_sidpr_scr_write,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = piix_sidpr_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_port_start,
+ };
+
+ static const struct piix_map_db ich5_map_db = {
+@@ -553,12 +418,11 @@ static const struct piix_map_db tolapai_map_db = {
+ static const struct piix_map_db *piix_map_db_table[] = {
+ [ich5_sata] = &ich5_map_db,
+ [ich6_sata] = &ich6_map_db,
+- [ich6_sata_ahci] = &ich6_map_db,
+- [ich6m_sata_ahci] = &ich6m_map_db,
+- [ich8_sata_ahci] = &ich8_map_db,
++ [ich6m_sata] = &ich6m_map_db,
++ [ich8_sata] = &ich8_map_db,
+ [ich8_2port_sata] = &ich8_2port_map_db,
+- [ich8m_apple_sata_ahci] = &ich8m_apple_map_db,
+- [tolapai_sata_ahci] = &tolapai_map_db,
++ [ich8m_apple_sata] = &ich8m_apple_map_db,
++ [tolapai_sata] = &tolapai_map_db,
+ };
+
+ static struct ata_port_info piix_port_info[] = {
+@@ -624,28 +488,18 @@ static struct ata_port_info piix_port_info[] = {
+ .port_ops = &piix_sata_ops,
+ },
+
+- [ich6_sata_ahci] =
+- {
+- .flags = PIIX_SATA_FLAGS | PIIX_FLAG_AHCI,
+- .pio_mask = 0x1f, /* pio0-4 */
+- .mwdma_mask = 0x07, /* mwdma0-2 */
+- .udma_mask = ATA_UDMA6,
+- .port_ops = &piix_sata_ops,
+- },
+-
+- [ich6m_sata_ahci] =
++ [ich6m_sata] =
+ {
+- .flags = PIIX_SATA_FLAGS | PIIX_FLAG_AHCI,
++ .flags = PIIX_SATA_FLAGS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &piix_sata_ops,
+ },
+
+- [ich8_sata_ahci] =
++ [ich8_sata] =
+ {
+- .flags = PIIX_SATA_FLAGS | PIIX_FLAG_AHCI |
+- PIIX_FLAG_SIDPR,
++ .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = ATA_UDMA6,
+@@ -654,27 +508,25 @@ static struct ata_port_info piix_port_info[] = {
+
+ [ich8_2port_sata] =
+ {
+- .flags = PIIX_SATA_FLAGS | PIIX_FLAG_AHCI |
+- PIIX_FLAG_SIDPR,
++ .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &piix_sata_ops,
+ },
+
+- [tolapai_sata_ahci] =
++ [tolapai_sata] =
+ {
+- .flags = PIIX_SATA_FLAGS | PIIX_FLAG_AHCI,
++ .flags = PIIX_SATA_FLAGS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &piix_sata_ops,
+ },
+
+- [ich8m_apple_sata_ahci] =
++ [ich8m_apple_sata] =
+ {
+- .flags = PIIX_SATA_FLAGS | PIIX_FLAG_AHCI |
+- PIIX_FLAG_SIDPR,
++ .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = ATA_UDMA6,
+@@ -683,7 +535,6 @@ static struct ata_port_info piix_port_info[] = {
+
+ [piix_pata_vmw] =
+ {
+- .sht = &piix_sht,
+ .flags = PIIX_PATA_FLAGS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
+@@ -722,6 +573,7 @@ static const struct ich_laptop ich_laptop[] = {
+ { 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */
+ { 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */
+ { 0x24CA, 0x1025, 0x0061 }, /* ICH4 on ACER Aspire 2023WLMi */
++ { 0x2653, 0x1043, 0x82D8 }, /* ICH6M on Asus Eee 701 */
+ /* end marker */
+ { 0, }
+ };
+@@ -776,13 +628,7 @@ static int piix_pata_prereset(struct ata_link *link, unsigned long deadline)
+
+ if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no]))
+ return -ENOENT;
+- return ata_std_prereset(link, deadline);
+-}
+-
+-static void piix_pata_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, piix_pata_prereset, ata_std_softreset, NULL,
+- ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -1168,35 +1014,6 @@ static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val)
+ return 0;
+ }
+
+-static int piix_sidpr_hardreset(struct ata_link *link, unsigned int *class,
+- unsigned long deadline)
+-{
+- const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
+- int rc;
+-
+- /* do hardreset */
+- rc = sata_link_hardreset(link, timing, deadline);
+- if (rc) {
+- ata_link_printk(link, KERN_ERR,
+- "COMRESET failed (errno=%d)\n", rc);
+- return rc;
+- }
+-
+- /* TODO: phy layer with polling, timeouts, etc. */
+- if (ata_link_offline(link)) {
+- *class = ATA_DEV_NONE;
+- return 0;
+- }
+-
+- return -EAGAIN;
+-}
+-
+-static void piix_sidpr_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
+- piix_sidpr_hardreset, ata_std_postreset);
+-}
+-
+ #ifdef CONFIG_PM
+ static int piix_broken_suspend(void)
+ {
+@@ -1633,6 +1450,16 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
+ if (rc)
+ return rc;
+
++ /* ICH6R may be driven by either ata_piix or ahci driver
++ * regardless of BIOS configuration. Make sure AHCI mode is
++ * off.
++ */
++ if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == 0x2652) {
++ int rc = piix_disable_ahci(pdev);
++ if (rc)
++ return rc;
++ }
++
+ /* SATA map init can change port_info, do it before prepping host */
+ hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
+ if (!hpriv)
+@@ -1642,22 +1469,12 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
+ hpriv->map = piix_init_sata_map(pdev, port_info,
+ piix_map_db_table[ent->driver_data]);
+
+- rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
++ rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
+ if (rc)
+ return rc;
+ host->private_data = hpriv;
+
+ /* initialize controller */
+- if (port_flags & PIIX_FLAG_AHCI) {
+- u8 tmp;
+- pci_read_config_byte(pdev, PIIX_SCC, &tmp);
+- if (tmp == PIIX_AHCI_DEVICE) {
+- rc = piix_disable_ahci(pdev);
+- if (rc)
+- return rc;
+- }
+- }
+-
+ if (port_flags & ATA_FLAG_SATA) {
+ piix_init_pcs(host, piix_map_db_table[ent->driver_data]);
+ piix_init_sidpr(host);
+@@ -1686,7 +1503,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
+ }
+
+ pci_set_master(pdev);
+- return ata_pci_activate_sff_host(host, ata_interrupt, &piix_sht);
++ return ata_pci_sff_activate_host(host, ata_sff_interrupt, &piix_sht);
+ }
+
+ static int __init piix_init(void)
+diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
+index bf98a56..70b77e0 100644
+--- a/drivers/ata/libata-acpi.c
++++ b/drivers/ata/libata-acpi.c
+@@ -77,7 +77,7 @@ void ata_acpi_associate_sata_port(struct ata_port *ap)
+ {
+ WARN_ON(!(ap->flags & ATA_FLAG_ACPI_SATA));
+
+- if (!ap->nr_pmp_links) {
++ if (!sata_pmp_attached(ap)) {
+ acpi_integer adr = SATA_ADR(ap->port_no, NO_PORT_MULT);
+
+ ap->link.device->acpi_handle =
+@@ -227,11 +227,9 @@ void ata_acpi_associate(struct ata_host *host)
+ acpi_install_notify_handler(ap->acpi_handle,
+ ACPI_SYSTEM_NOTIFY,
+ ata_acpi_ap_notify, ap);
+-#if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE)
+ /* we might be on a docking station */
+ register_hotplug_dock_device(ap->acpi_handle,
+ ata_acpi_ap_notify, ap);
+-#endif
+ }
+
+ for (j = 0; j < ata_link_max_devices(&ap->link); j++) {
+@@ -241,11 +239,9 @@ void ata_acpi_associate(struct ata_host *host)
+ acpi_install_notify_handler(dev->acpi_handle,
+ ACPI_SYSTEM_NOTIFY,
+ ata_acpi_dev_notify, dev);
+-#if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE)
+ /* we might be on a docking station */
+ register_hotplug_dock_device(dev->acpi_handle,
+ ata_acpi_dev_notify, dev);
+-#endif
+ }
+ }
+ }
+@@ -839,7 +835,8 @@ void ata_acpi_on_resume(struct ata_port *ap)
+ */
+ ata_link_for_each_dev(dev, &ap->link) {
+ ata_acpi_clear_gtf(dev);
+- if (ata_dev_get_GTF(dev, NULL) >= 0)
++ if (ata_dev_enabled(dev) &&
++ ata_dev_get_GTF(dev, NULL) >= 0)
+ dev->flags |= ATA_DFLAG_ACPI_PENDING;
+ }
+ } else {
+@@ -849,7 +846,8 @@ void ata_acpi_on_resume(struct ata_port *ap)
+ */
+ ata_link_for_each_dev(dev, &ap->link) {
+ ata_acpi_clear_gtf(dev);
+- dev->flags |= ATA_DFLAG_ACPI_PENDING;
++ if (ata_dev_enabled(dev))
++ dev->flags |= ATA_DFLAG_ACPI_PENDING;
+ }
+ }
+ }
+diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
+index be95fdb..51b7d2f 100644
+--- a/drivers/ata/libata-core.c
++++ b/drivers/ata/libata-core.c
+@@ -46,7 +46,6 @@
+ #include <linux/init.h>
+ #include <linux/list.h>
+ #include <linux/mm.h>
+-#include <linux/highmem.h>
+ #include <linux/spinlock.h>
+ #include <linux/blkdev.h>
+ #include <linux/delay.h>
+@@ -62,7 +61,6 @@
+ #include <scsi/scsi_cmnd.h>
+ #include <scsi/scsi_host.h>
+ #include <linux/libata.h>
+-#include <asm/semaphore.h>
+ #include <asm/byteorder.h>
+ #include <linux/cdrom.h>
+
+@@ -74,6 +72,19 @@ const unsigned long sata_deb_timing_normal[] = { 5, 100, 2000 };
+ const unsigned long sata_deb_timing_hotplug[] = { 25, 500, 2000 };
+ const unsigned long sata_deb_timing_long[] = { 100, 2000, 5000 };
+
++const struct ata_port_operations ata_base_port_ops = {
++ .prereset = ata_std_prereset,
++ .postreset = ata_std_postreset,
++ .error_handler = ata_std_error_handler,
++};
++
++const struct ata_port_operations sata_port_ops = {
++ .inherits = &ata_base_port_ops,
++
++ .qc_defer = ata_std_qc_defer,
++ .hardreset = sata_std_hardreset,
++};
++
+ static unsigned int ata_dev_init_params(struct ata_device *dev,
+ u16 heads, u16 sectors);
+ static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
+@@ -1043,50 +1054,6 @@ static void ata_lpm_disable(struct ata_host *host)
+ }
+ #endif /* CONFIG_PM */
+
+-
+-/**
+- * ata_devchk - PATA device presence detection
+- * @ap: ATA channel to examine
+- * @device: Device to examine (starting at zero)
+- *
+- * This technique was originally described in
+- * Hale Landis's ATADRVR (www.ata-atapi.com), and
+- * later found its way into the ATA/ATAPI spec.
+- *
+- * Write a pattern to the ATA shadow registers,
+- * and if a device is present, it will respond by
+- * correctly storing and echoing back the
+- * ATA shadow register contents.
+- *
+- * LOCKING:
+- * caller.
+- */
+-
+-static unsigned int ata_devchk(struct ata_port *ap, unsigned int device)
+-{
+- struct ata_ioports *ioaddr = &ap->ioaddr;
+- u8 nsect, lbal;
+-
+- ap->ops->dev_select(ap, device);
+-
+- iowrite8(0x55, ioaddr->nsect_addr);
+- iowrite8(0xaa, ioaddr->lbal_addr);
+-
+- iowrite8(0xaa, ioaddr->nsect_addr);
+- iowrite8(0x55, ioaddr->lbal_addr);
+-
+- iowrite8(0x55, ioaddr->nsect_addr);
+- iowrite8(0xaa, ioaddr->lbal_addr);
+-
+- nsect = ioread8(ioaddr->nsect_addr);
+- lbal = ioread8(ioaddr->lbal_addr);
+-
+- if ((nsect == 0x55) && (lbal == 0xaa))
+- return 1; /* we found a device */
+-
+- return 0; /* nothing found */
+-}
+-
+ /**
+ * ata_dev_classify - determine device type based on ATA-spec signature
+ * @tf: ATA taskfile register set for device to be identified
+@@ -1147,75 +1114,6 @@ unsigned int ata_dev_classify(const struct ata_taskfile *tf)
+ }
+
+ /**
+- * ata_dev_try_classify - Parse returned ATA device signature
+- * @dev: ATA device to classify (starting at zero)
+- * @present: device seems present
+- * @r_err: Value of error register on completion
+- *
+- * After an event -- SRST, E.D.D., or SATA COMRESET -- occurs,
+- * an ATA/ATAPI-defined set of values is placed in the ATA
+- * shadow registers, indicating the results of device detection
+- * and diagnostics.
+- *
+- * Select the ATA device, and read the values from the ATA shadow
+- * registers. Then parse according to the Error register value,
+- * and the spec-defined values examined by ata_dev_classify().
+- *
+- * LOCKING:
+- * caller.
+- *
+- * RETURNS:
+- * Device type - %ATA_DEV_ATA, %ATA_DEV_ATAPI or %ATA_DEV_NONE.
+- */
+-unsigned int ata_dev_try_classify(struct ata_device *dev, int present,
+- u8 *r_err)
+-{
+- struct ata_port *ap = dev->link->ap;
+- struct ata_taskfile tf;
+- unsigned int class;
+- u8 err;
+-
+- ap->ops->dev_select(ap, dev->devno);
+-
+- memset(&tf, 0, sizeof(tf));
+-
+- ap->ops->tf_read(ap, &tf);
+- err = tf.feature;
+- if (r_err)
+- *r_err = err;
+-
+- /* see if device passed diags: continue and warn later */
+- if (err == 0)
+- /* diagnostic fail : do nothing _YET_ */
+- dev->horkage |= ATA_HORKAGE_DIAGNOSTIC;
+- else if (err == 1)
+- /* do nothing */ ;
+- else if ((dev->devno == 0) && (err == 0x81))
+- /* do nothing */ ;
+- else
+- return ATA_DEV_NONE;
+-
+- /* determine if device is ATA or ATAPI */
+- class = ata_dev_classify(&tf);
+-
+- if (class == ATA_DEV_UNKNOWN) {
+- /* If the device failed diagnostic, it's likely to
+- * have reported incorrect device signature too.
+- * Assume ATA device if the device seems present but
+- * device signature is invalid with diagnostic
+- * failure.
+- */
+- if (present && (dev->horkage & ATA_HORKAGE_DIAGNOSTIC))
+- class = ATA_DEV_ATA;
+- else
+- class = ATA_DEV_NONE;
+- } else if ((class == ATA_DEV_ATA) && (ata_chk_status(ap) == 0))
+- class = ATA_DEV_NONE;
+-
+- return class;
+-}
+-
+-/**
+ * ata_id_string - Convert IDENTIFY DEVICE page into string
+ * @id: IDENTIFY DEVICE results we will examine
+ * @s: string into which data is output
+@@ -1293,7 +1191,7 @@ static u64 ata_id_n_sectors(const u16 *id)
+ }
+ }
+
+-static u64 ata_tf_to_lba48(struct ata_taskfile *tf)
++u64 ata_tf_to_lba48(const struct ata_taskfile *tf)
+ {
+ u64 sectors = 0;
+
+@@ -1304,10 +1202,10 @@ static u64 ata_tf_to_lba48(struct ata_taskfile *tf)
+ sectors |= (tf->lbam & 0xff) << 8;
+ sectors |= (tf->lbal & 0xff);
+
+- return ++sectors;
++ return sectors;
+ }
+
+-static u64 ata_tf_to_lba(struct ata_taskfile *tf)
++u64 ata_tf_to_lba(const struct ata_taskfile *tf)
+ {
+ u64 sectors = 0;
+
+@@ -1316,7 +1214,7 @@ static u64 ata_tf_to_lba(struct ata_taskfile *tf)
+ sectors |= (tf->lbam & 0xff) << 8;
+ sectors |= (tf->lbal & 0xff);
+
+- return ++sectors;
++ return sectors;
+ }
+
+ /**
+@@ -1361,9 +1259,9 @@ static int ata_read_native_max_address(struct ata_device *dev, u64 *max_sectors)
+ }
+
+ if (lba48)
+- *max_sectors = ata_tf_to_lba48(&tf);
++ *max_sectors = ata_tf_to_lba48(&tf) + 1;
+ else
+- *max_sectors = ata_tf_to_lba(&tf);
++ *max_sectors = ata_tf_to_lba(&tf) + 1;
+ if (dev->horkage & ATA_HORKAGE_HPA_SIZE)
+ (*max_sectors)--;
+ return 0;
+@@ -1523,89 +1421,6 @@ static int ata_hpa_resize(struct ata_device *dev)
+ }
+
+ /**
+- * ata_noop_dev_select - Select device 0/1 on ATA bus
+- * @ap: ATA channel to manipulate
+- * @device: ATA device (numbered from zero) to select
+- *
+- * This function performs no actual function.
+- *
+- * May be used as the dev_select() entry in ata_port_operations.
+- *
+- * LOCKING:
+- * caller.
+- */
+-void ata_noop_dev_select(struct ata_port *ap, unsigned int device)
+-{
+-}
+-
+-
+-/**
+- * ata_std_dev_select - Select device 0/1 on ATA bus
+- * @ap: ATA channel to manipulate
+- * @device: ATA device (numbered from zero) to select
+- *
+- * Use the method defined in the ATA specification to
+- * make either device 0, or device 1, active on the
+- * ATA channel. Works with both PIO and MMIO.
+- *
+- * May be used as the dev_select() entry in ata_port_operations.
+- *
+- * LOCKING:
+- * caller.
+- */
+-
+-void ata_std_dev_select(struct ata_port *ap, unsigned int device)
+-{
+- u8 tmp;
+-
+- if (device == 0)
+- tmp = ATA_DEVICE_OBS;
+- else
+- tmp = ATA_DEVICE_OBS | ATA_DEV1;
+-
+- iowrite8(tmp, ap->ioaddr.device_addr);
+- ata_pause(ap); /* needed; also flushes, for mmio */
+-}
+-
+-/**
+- * ata_dev_select - Select device 0/1 on ATA bus
+- * @ap: ATA channel to manipulate
+- * @device: ATA device (numbered from zero) to select
+- * @wait: non-zero to wait for Status register BSY bit to clear
+- * @can_sleep: non-zero if context allows sleeping
+- *
+- * Use the method defined in the ATA specification to
+- * make either device 0, or device 1, active on the
+- * ATA channel.
+- *
+- * This is a high-level version of ata_std_dev_select(),
+- * which additionally provides the services of inserting
+- * the proper pauses and status polling, where needed.
+- *
+- * LOCKING:
+- * caller.
+- */
+-
+-void ata_dev_select(struct ata_port *ap, unsigned int device,
+- unsigned int wait, unsigned int can_sleep)
+-{
+- if (ata_msg_probe(ap))
+- ata_port_printk(ap, KERN_INFO, "ata_dev_select: ENTER, "
+- "device %u, wait %u\n", device, wait);
+-
+- if (wait)
+- ata_wait_idle(ap);
+-
+- ap->ops->dev_select(ap, device);
+-
+- if (wait) {
+- if (can_sleep && ap->link.device[device].class == ATA_DEV_ATAPI)
+- msleep(150);
+- ata_wait_idle(ap);
+- }
+-}
+-
+-/**
+ * ata_dump_id - IDENTIFY DEVICE info debugging output
+ * @id: IDENTIFY DEVICE page to dump
+ *
+@@ -1732,8 +1547,7 @@ unsigned long ata_id_xfermask(const u16 *id)
+ * LOCKING:
+ * Inherited from caller.
+ */
+-static void ata_pio_queue_task(struct ata_port *ap, void *data,
+- unsigned long delay)
++void ata_pio_queue_task(struct ata_port *ap, void *data, unsigned long delay)
+ {
+ ap->port_task_data = data;
+
+@@ -2097,7 +1911,6 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
+ if (ata_msg_ctl(ap))
+ ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __func__);
+
+- ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
+ retry:
+ ata_tf_init(dev, &tf);
+
+@@ -2464,7 +2277,7 @@ int ata_dev_configure(struct ata_device *dev)
+ * changed notifications and ATAPI ANs.
+ */
+ if ((ap->flags & ATA_FLAG_AN) && ata_id_has_atapi_AN(id) &&
+- (!ap->nr_pmp_links ||
++ (!sata_pmp_attached(ap) ||
+ sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf) == 0)) {
+ unsigned int err_mask;
+
+@@ -2558,9 +2371,6 @@ int ata_dev_configure(struct ata_device *dev)
+ }
+ }
+
+- if (ata_msg_probe(ap))
+- ata_dev_printk(dev, KERN_DEBUG, "%s: EXIT, drv_stat = 0x%x\n",
+- __func__, ata_chk_status(ap));
+ return 0;
+
+ err_out_nosup:
+@@ -2806,7 +2616,7 @@ void ata_port_probe(struct ata_port *ap)
+ * LOCKING:
+ * None.
+ */
+-void sata_print_link_status(struct ata_link *link)
++static void sata_print_link_status(struct ata_link *link)
+ {
+ u32 sstatus, scontrol, tmp;
+
+@@ -2962,7 +2772,7 @@ static int __sata_set_spd_needed(struct ata_link *link, u32 *scontrol)
+ * RETURNS:
+ * 1 if SATA spd configuration is needed, 0 otherwise.
+ */
+-int sata_set_spd_needed(struct ata_link *link)
++static int sata_set_spd_needed(struct ata_link *link)
+ {
+ u32 scontrol;
+
+@@ -3321,16 +3131,21 @@ static int ata_dev_set_mode(struct ata_device *dev)
+ if (rc)
+ return rc;
+
+- /* Old CFA may refuse this command, which is just fine */
+- if (dev->xfer_shift == ATA_SHIFT_PIO && ata_id_is_cfa(dev->id))
+- ign_dev_err = 1;
+-
+- /* Some very old devices and some bad newer ones fail any kind of
+- SET_XFERMODE request but support PIO0-2 timings and no IORDY */
+- if (dev->xfer_shift == ATA_SHIFT_PIO && !ata_id_has_iordy(dev->id) &&
+- dev->pio_mode <= XFER_PIO_2)
+- ign_dev_err = 1;
+-
++ if (dev->xfer_shift == ATA_SHIFT_PIO) {
++ /* Old CFA may refuse this command, which is just fine */
++ if (ata_id_is_cfa(dev->id))
++ ign_dev_err = 1;
++ /* Catch several broken garbage emulations plus some pre
++ ATA devices */
++ if (ata_id_major_version(dev->id) == 0 &&
++ dev->pio_mode <= XFER_PIO_2)
++ ign_dev_err = 1;
++ /* Some very old devices and some bad newer ones fail
++ any kind of SET_XFERMODE request but support PIO0-2
++ timings and no IORDY */
++ if (!ata_id_has_iordy(dev->id) && dev->pio_mode <= XFER_PIO_2)
++ ign_dev_err = 1;
++ }
+ /* Early MWDMA devices do DMA but don't allow DMA mode setting.
+ Don't fail an MWDMA0 set IFF the device indicates it is in MWDMA0 */
+ if (dev->xfer_shift == ATA_SHIFT_MWDMA &&
+@@ -3474,170 +3289,73 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
+ }
+
+ /**
+- * ata_tf_to_host - issue ATA taskfile to host controller
+- * @ap: port to which command is being issued
+- * @tf: ATA taskfile register set
+- *
+- * Issues ATA taskfile register set to ATA host controller,
+- * with proper synchronization with interrupt handler and
+- * other threads.
+- *
+- * LOCKING:
+- * spin_lock_irqsave(host lock)
+- */
+-
+-static inline void ata_tf_to_host(struct ata_port *ap,
+- const struct ata_taskfile *tf)
+-{
+- ap->ops->tf_load(ap, tf);
+- ap->ops->exec_command(ap, tf);
+-}
+-
+-/**
+- * ata_busy_sleep - sleep until BSY clears, or timeout
+- * @ap: port containing status register to be polled
+- * @tmout_pat: impatience timeout
+- * @tmout: overall timeout
+- *
+- * Sleep until ATA Status register bit BSY clears,
+- * or a timeout occurs.
+- *
+- * LOCKING:
+- * Kernel thread context (may sleep).
+- *
+- * RETURNS:
+- * 0 on success, -errno otherwise.
+- */
+-int ata_busy_sleep(struct ata_port *ap,
+- unsigned long tmout_pat, unsigned long tmout)
+-{
+- unsigned long timer_start, timeout;
+- u8 status;
+-
+- status = ata_busy_wait(ap, ATA_BUSY, 300);
+- timer_start = jiffies;
+- timeout = timer_start + tmout_pat;
+- while (status != 0xff && (status & ATA_BUSY) &&
+- time_before(jiffies, timeout)) {
+- msleep(50);
+- status = ata_busy_wait(ap, ATA_BUSY, 3);
+- }
+-
+- if (status != 0xff && (status & ATA_BUSY))
+- ata_port_printk(ap, KERN_WARNING,
+- "port is slow to respond, please be patient "
+- "(Status 0x%x)\n", status);
+-
+- timeout = timer_start + tmout;
+- while (status != 0xff && (status & ATA_BUSY) &&
+- time_before(jiffies, timeout)) {
+- msleep(50);
+- status = ata_chk_status(ap);
+- }
+-
+- if (status == 0xff)
+- return -ENODEV;
+-
+- if (status & ATA_BUSY) {
+- ata_port_printk(ap, KERN_ERR, "port failed to respond "
+- "(%lu secs, Status 0x%x)\n",
+- tmout / HZ, status);
+- return -EBUSY;
+- }
+-
+- return 0;
+-}
+-
+-/**
+- * ata_wait_after_reset - wait before checking status after reset
+- * @ap: port containing status register to be polled
++ * ata_wait_ready - wait for link to become ready
++ * @link: link to be waited on
+ * @deadline: deadline jiffies for the operation
++ * @check_ready: callback to check link readiness
+ *
+- * After reset, we need to pause a while before reading status.
+- * Also, certain combination of controller and device report 0xff
+- * for some duration (e.g. until SATA PHY is up and running)
+- * which is interpreted as empty port in ATA world. This
+- * function also waits for such devices to get out of 0xff
+- * status.
++ * Wait for @link to become ready. @check_ready should return
++ * positive number if @link is ready, 0 if it isn't, -ENODEV if
++ * link doesn't seem to be occupied, other errno for other error
++ * conditions.
+ *
+- * LOCKING:
+- * Kernel thread context (may sleep).
+- */
+-void ata_wait_after_reset(struct ata_port *ap, unsigned long deadline)
+-{
+- unsigned long until = jiffies + ATA_TMOUT_FF_WAIT;
+-
+- if (time_before(until, deadline))
+- deadline = until;
+-
+- /* Spec mandates ">= 2ms" before checking status. We wait
+- * 150ms, because that was the magic delay used for ATAPI
+- * devices in Hale Landis's ATADRVR, for the period of time
+- * between when the ATA command register is written, and then
+- * status is checked. Because waiting for "a while" before
+- * checking status is fine, post SRST, we perform this magic
+- * delay here as well.
+- *
+- * Old drivers/ide uses the 2mS rule and then waits for ready.
+- */
+- msleep(150);
+-
+- /* Wait for 0xff to clear. Some SATA devices take a long time
+- * to clear 0xff after reset. For example, HHD424020F7SV00
+- * iVDR needs >= 800ms while. Quantum GoVault needs even more
+- * than that.
+- *
+- * Note that some PATA controllers (pata_ali) explode if
+- * status register is read more than once when there's no
+- * device attached.
+- */
+- if (ap->flags & ATA_FLAG_SATA) {
+- while (1) {
+- u8 status = ata_chk_status(ap);
+-
+- if (status != 0xff || time_after(jiffies, deadline))
+- return;
+-
+- msleep(50);
+- }
+- }
+-}
+-
+-/**
+- * ata_wait_ready - sleep until BSY clears, or timeout
+- * @ap: port containing status register to be polled
+- * @deadline: deadline jiffies for the operation
+- *
+- * Sleep until ATA Status register bit BSY clears, or timeout
+- * occurs.
++ * Transient -ENODEV conditions are allowed for
++ * ATA_TMOUT_FF_WAIT.
+ *
+ * LOCKING:
+- * Kernel thread context (may sleep).
++ * EH context.
+ *
+ * RETURNS:
+- * 0 on success, -errno otherwise.
++ * 0 if @linke is ready before @deadline; otherwise, -errno.
+ */
+-int ata_wait_ready(struct ata_port *ap, unsigned long deadline)
++int ata_wait_ready(struct ata_link *link, unsigned long deadline,
++ int (*check_ready)(struct ata_link *link))
+ {
+ unsigned long start = jiffies;
++ unsigned long nodev_deadline = start + ATA_TMOUT_FF_WAIT;
+ int warned = 0;
+
++ if (time_after(nodev_deadline, deadline))
++ nodev_deadline = deadline;
++
+ while (1) {
+- u8 status = ata_chk_status(ap);
+ unsigned long now = jiffies;
++ int ready, tmp;
+
+- if (!(status & ATA_BUSY))
++ ready = tmp = check_ready(link);
++ if (ready > 0)
+ return 0;
+- if (!ata_link_online(&ap->link) && status == 0xff)
+- return -ENODEV;
++
++ /* -ENODEV could be transient. Ignore -ENODEV if link
++ * is online. Also, some SATA devices take a long
++ * time to clear 0xff after reset. For example,
++ * HHD424020F7SV00 iVDR needs >= 800ms while Quantum
++ * GoVault needs even more than that. Wait for
++ * ATA_TMOUT_FF_WAIT on -ENODEV if link isn't offline.
++ *
++ * Note that some PATA controllers (pata_ali) explode
++ * if status register is read more than once when
++ * there's no device attached.
++ */
++ if (ready == -ENODEV) {
++ if (ata_link_online(link))
++ ready = 0;
++ else if ((link->ap->flags & ATA_FLAG_SATA) &&
++ !ata_link_offline(link) &&
++ time_before(now, nodev_deadline))
++ ready = 0;
++ }
++
++ if (ready)
++ return ready;
+ if (time_after(now, deadline))
+ return -EBUSY;
+
+ if (!warned && time_after(now, start + 5 * HZ) &&
+ (deadline - now > 3 * HZ)) {
+- ata_port_printk(ap, KERN_WARNING,
+- "port is slow to respond, please be patient "
+- "(Status 0x%x)\n", status);
++ ata_link_printk(link, KERN_WARNING,
++ "link is slow to respond, please be patient "
++ "(ready=%d)\n", tmp);
+ warned = 1;
+ }
+
+@@ -3645,179 +3363,26 @@ int ata_wait_ready(struct ata_port *ap, unsigned long deadline)
+ }
+ }
+
+-static int ata_bus_post_reset(struct ata_port *ap, unsigned int devmask,
+- unsigned long deadline)
+-{
+- struct ata_ioports *ioaddr = &ap->ioaddr;
+- unsigned int dev0 = devmask & (1 << 0);
+- unsigned int dev1 = devmask & (1 << 1);
+- int rc, ret = 0;
+-
+- /* if device 0 was found in ata_devchk, wait for its
+- * BSY bit to clear
+- */
+- if (dev0) {
+- rc = ata_wait_ready(ap, deadline);
+- if (rc) {
+- if (rc != -ENODEV)
+- return rc;
+- ret = rc;
+- }
+- }
+-
+- /* if device 1 was found in ata_devchk, wait for register
+- * access briefly, then wait for BSY to clear.
+- */
+- if (dev1) {
+- int i;
+-
+- ap->ops->dev_select(ap, 1);
+-
+- /* Wait for register access. Some ATAPI devices fail
+- * to set nsect/lbal after reset, so don't waste too
+- * much time on it. We're gonna wait for !BSY anyway.
+- */
+- for (i = 0; i < 2; i++) {
+- u8 nsect, lbal;
+-
+- nsect = ioread8(ioaddr->nsect_addr);
+- lbal = ioread8(ioaddr->lbal_addr);
+- if ((nsect == 1) && (lbal == 1))
+- break;
+- msleep(50); /* give drive a breather */
+- }
+-
+- rc = ata_wait_ready(ap, deadline);
+- if (rc) {
+- if (rc != -ENODEV)
+- return rc;
+- ret = rc;
+- }
+- }
+-
+- /* is all this really necessary? */
+- ap->ops->dev_select(ap, 0);
+- if (dev1)
+- ap->ops->dev_select(ap, 1);
+- if (dev0)
+- ap->ops->dev_select(ap, 0);
+-
+- return ret;
+-}
+-
+-static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask,
+- unsigned long deadline)
+-{
+- struct ata_ioports *ioaddr = &ap->ioaddr;
+-
+- DPRINTK("ata%u: bus reset via SRST\n", ap->print_id);
+-
+- /* software reset. causes dev0 to be selected */
+- iowrite8(ap->ctl, ioaddr->ctl_addr);
+- udelay(20); /* FIXME: flush */
+- iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
+- udelay(20); /* FIXME: flush */
+- iowrite8(ap->ctl, ioaddr->ctl_addr);
+-
+- /* wait a while before checking status */
+- ata_wait_after_reset(ap, deadline);
+-
+- /* Before we perform post reset processing we want to see if
+- * the bus shows 0xFF because the odd clown forgets the D7
+- * pulldown resistor.
+- */
+- if (ata_chk_status(ap) == 0xFF)
+- return -ENODEV;
+-
+- return ata_bus_post_reset(ap, devmask, deadline);
+-}
+-
+ /**
+- * ata_bus_reset - reset host port and associated ATA channel
+- * @ap: port to reset
++ * ata_wait_after_reset - wait for link to become ready after reset
++ * @link: link to be waited on
++ * @deadline: deadline jiffies for the operation
++ * @check_ready: callback to check link readiness
+ *
+- * This is typically the first time we actually start issuing
+- * commands to the ATA channel. We wait for BSY to clear, then
+- * issue EXECUTE DEVICE DIAGNOSTIC command, polling for its
+- * result. Determine what devices, if any, are on the channel
+- * by looking at the device 0/1 error register. Look at the signature
+- * stored in each device's taskfile registers, to determine if
+- * the device is ATA or ATAPI.
++ * Wait for @link to become ready after reset.
+ *
+ * LOCKING:
+- * PCI/etc. bus probe sem.
+- * Obtains host lock.
++ * EH context.
+ *
+- * SIDE EFFECTS:
+- * Sets ATA_FLAG_DISABLED if bus reset fails.
++ * RETURNS:
++ * 0 if @linke is ready before @deadline; otherwise, -errno.
+ */
+-
+-void ata_bus_reset(struct ata_port *ap)
++int ata_wait_after_reset(struct ata_link *link, unsigned long deadline,
++ int (*check_ready)(struct ata_link *link))
+ {
+- struct ata_device *device = ap->link.device;
+- struct ata_ioports *ioaddr = &ap->ioaddr;
+- unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
+- u8 err;
+- unsigned int dev0, dev1 = 0, devmask = 0;
+- int rc;
+-
+- DPRINTK("ENTER, host %u, port %u\n", ap->print_id, ap->port_no);
+-
+- /* determine if device 0/1 are present */
+- if (ap->flags & ATA_FLAG_SATA_RESET)
+- dev0 = 1;
+- else {
+- dev0 = ata_devchk(ap, 0);
+- if (slave_possible)
+- dev1 = ata_devchk(ap, 1);
+- }
+-
+- if (dev0)
+- devmask |= (1 << 0);
+- if (dev1)
+- devmask |= (1 << 1);
++ msleep(ATA_WAIT_AFTER_RESET_MSECS);
+
+- /* select device 0 again */
+- ap->ops->dev_select(ap, 0);
+-
+- /* issue bus reset */
+- if (ap->flags & ATA_FLAG_SRST) {
+- rc = ata_bus_softreset(ap, devmask, jiffies + 40 * HZ);
+- if (rc && rc != -ENODEV)
+- goto err_out;
+- }
+-
+- /*
+- * determine by signature whether we have ATA or ATAPI devices
+- */
+- device[0].class = ata_dev_try_classify(&device[0], dev0, &err);
+- if ((slave_possible) && (err != 0x81))
+- device[1].class = ata_dev_try_classify(&device[1], dev1, &err);
+-
+- /* is double-select really necessary? */
+- if (device[1].class != ATA_DEV_NONE)
+- ap->ops->dev_select(ap, 1);
+- if (device[0].class != ATA_DEV_NONE)
+- ap->ops->dev_select(ap, 0);
+-
+- /* if no devices were detected, disable this port */
+- if ((device[0].class == ATA_DEV_NONE) &&
+- (device[1].class == ATA_DEV_NONE))
+- goto err_out;
+-
+- if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) {
+- /* set up device control for ATA_FLAG_SATA_RESET */
+- iowrite8(ap->ctl, ioaddr->ctl_addr);
+- }
+-
+- DPRINTK("EXIT\n");
+- return;
+-
+-err_out:
+- ata_port_printk(ap, KERN_ERR, "disabling port\n");
+- ata_port_disable(ap);
+-
+- DPRINTK("EXIT\n");
++ return ata_wait_ready(link, deadline, check_ready);
+ }
+
+ /**
+@@ -3906,7 +3471,7 @@ int sata_link_debounce(struct ata_link *link, const unsigned long *params,
+ int sata_link_resume(struct ata_link *link, const unsigned long *params,
+ unsigned long deadline)
+ {
+- u32 scontrol;
++ u32 scontrol, serror;
+ int rc;
+
+ if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol)))
+@@ -3922,7 +3487,25 @@ int sata_link_resume(struct ata_link *link, const unsigned long *params,
+ */
+ msleep(200);
+
+- return sata_link_debounce(link, params, deadline);
++ if ((rc = sata_link_debounce(link, params, deadline)))
++ return rc;
++
++ /* Clear SError. PMP and some host PHYs require this to
++ * operate and clearing should be done before checking PHY
++ * online status to avoid race condition (hotplugging between
++ * link resume and status check).
++ */
++ if (!(rc = sata_scr_read(link, SCR_ERROR, &serror)))
++ rc = sata_scr_write(link, SCR_ERROR, serror);
++ if (rc == 0 || rc == -EINVAL) {
++ unsigned long flags;
++
++ spin_lock_irqsave(link->ap->lock, flags);
++ link->eh_info.serror = 0;
++ spin_unlock_irqrestore(link->ap->lock, flags);
++ rc = 0;
++ }
++ return rc;
+ }
+
+ /**
+@@ -3949,17 +3532,6 @@ int ata_std_prereset(struct ata_link *link, unsigned long deadline)
+ const unsigned long *timing = sata_ehc_deb_timing(ehc);
+ int rc;
+
+- /* handle link resume */
+- if ((ehc->i.flags & ATA_EHI_RESUME_LINK) &&
+- (link->flags & ATA_LFLAG_HRST_TO_RESUME))
+- ehc->i.action |= ATA_EH_HARDRESET;
+-
+- /* Some PMPs don't work with only SRST, force hardreset if PMP
+- * is supported.
+- */
+- if (ap->flags & ATA_FLAG_PMP)
+- ehc->i.action |= ATA_EH_HARDRESET;
+-
+ /* if we're about to do hardreset, nothing more to do */
+ if (ehc->i.action & ATA_EH_HARDRESET)
+ return 0;
+@@ -3973,88 +3545,30 @@ int ata_std_prereset(struct ata_link *link, unsigned long deadline)
+ "link for reset (errno=%d)\n", rc);
+ }
+
+- /* Wait for !BSY if the controller can wait for the first D2H
+- * Reg FIS and we don't know that no device is attached.
+- */
+- if (!(link->flags & ATA_LFLAG_SKIP_D2H_BSY) && !ata_link_offline(link)) {
+- rc = ata_wait_ready(ap, deadline);
+- if (rc && rc != -ENODEV) {
+- ata_link_printk(link, KERN_WARNING, "device not ready "
+- "(errno=%d), forcing hardreset\n", rc);
+- ehc->i.action |= ATA_EH_HARDRESET;
+- }
+- }
++ /* no point in trying softreset on offline link */
++ if (ata_link_offline(link))
++ ehc->i.action &= ~ATA_EH_SOFTRESET;
+
+ return 0;
+ }
+
+ /**
+- * ata_std_softreset - reset host port via ATA SRST
+- * @link: ATA link to reset
+- * @classes: resulting classes of attached devices
+- * @deadline: deadline jiffies for the operation
+- *
+- * Reset host port using ATA SRST.
+- *
+- * LOCKING:
+- * Kernel thread context (may sleep)
+- *
+- * RETURNS:
+- * 0 on success, -errno otherwise.
+- */
+-int ata_std_softreset(struct ata_link *link, unsigned int *classes,
+- unsigned long deadline)
+-{
+- struct ata_port *ap = link->ap;
+- unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
+- unsigned int devmask = 0;
+- int rc;
+- u8 err;
+-
+- DPRINTK("ENTER\n");
+-
+- if (ata_link_offline(link)) {
+- classes[0] = ATA_DEV_NONE;
+- goto out;
+- }
+-
+- /* determine if device 0/1 are present */
+- if (ata_devchk(ap, 0))
+- devmask |= (1 << 0);
+- if (slave_possible && ata_devchk(ap, 1))
+- devmask |= (1 << 1);
+-
+- /* select device 0 again */
+- ap->ops->dev_select(ap, 0);
+-
+- /* issue bus reset */
+- DPRINTK("about to softreset, devmask=%x\n", devmask);
+- rc = ata_bus_softreset(ap, devmask, deadline);
+- /* if link is occupied, -ENODEV too is an error */
+- if (rc && (rc != -ENODEV || sata_scr_valid(link))) {
+- ata_link_printk(link, KERN_ERR, "SRST failed (errno=%d)\n", rc);
+- return rc;
+- }
+-
+- /* determine by signature whether we have ATA or ATAPI devices */
+- classes[0] = ata_dev_try_classify(&link->device[0],
+- devmask & (1 << 0), &err);
+- if (slave_possible && err != 0x81)
+- classes[1] = ata_dev_try_classify(&link->device[1],
+- devmask & (1 << 1), &err);
+-
+- out:
+- DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
+- return 0;
+-}
+-
+-/**
+ * sata_link_hardreset - reset link via SATA phy reset
+ * @link: link to reset
+ * @timing: timing parameters { interval, duratinon, timeout } in msec
+ * @deadline: deadline jiffies for the operation
++ * @online: optional out parameter indicating link onlineness
++ * @check_ready: optional callback to check link readiness
+ *
+ * SATA phy-reset @link using DET bits of SControl register.
++ * After hardreset, link readiness is waited upon using
++ * ata_wait_ready() if @check_ready is specified. LLDs are
++ * allowed to not specify @check_ready and wait itself after this
++ * function returns. Device classification is LLD's
++ * responsibility.
++ *
++ * *@online is set to one iff reset succeeded and @link is online
++ * after reset.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep)
+@@ -4063,13 +3577,17 @@ int ata_std_softreset(struct ata_link *link, unsigned int *classes,
+ * 0 on success, -errno otherwise.
+ */
+ int sata_link_hardreset(struct ata_link *link, const unsigned long *timing,
+- unsigned long deadline)
++ unsigned long deadline,
++ bool *online, int (*check_ready)(struct ata_link *))
+ {
+ u32 scontrol;
+ int rc;
+
+ DPRINTK("ENTER\n");
+
++ if (online)
++ *online = false;
++
+ if (sata_set_spd_needed(link)) {
+ /* SATA spec says nothing about how to reconfigure
+ * spd. To be on the safe side, turn off phy during
+@@ -4103,77 +3621,69 @@ int sata_link_hardreset(struct ata_link *link, const unsigned long *timing,
+
+ /* bring link back */
+ rc = sata_link_resume(link, timing, deadline);
++ if (rc)
++ goto out;
++ /* if link is offline nothing more to do */
++ if (ata_link_offline(link))
++ goto out;
++
++ /* Link is online. From this point, -ENODEV too is an error. */
++ if (online)
++ *online = true;
++
++ if (sata_pmp_supported(link->ap) && ata_is_host_link(link)) {
++ /* If PMP is supported, we have to do follow-up SRST.
++ * Some PMPs don't send D2H Reg FIS after hardreset if
++ * the first port is empty. Wait only for
++ * ATA_TMOUT_PMP_SRST_WAIT.
++ */
++ if (check_ready) {
++ unsigned long pmp_deadline;
++
++ pmp_deadline = jiffies + ATA_TMOUT_PMP_SRST_WAIT;
++ if (time_after(pmp_deadline, deadline))
++ pmp_deadline = deadline;
++ ata_wait_ready(link, pmp_deadline, check_ready);
++ }
++ rc = -EAGAIN;
++ goto out;
++ }
++
++ rc = 0;
++ if (check_ready)
++ rc = ata_wait_ready(link, deadline, check_ready);
+ out:
++ if (rc && rc != -EAGAIN)
++ ata_link_printk(link, KERN_ERR,
++ "COMRESET failed (errno=%d)\n", rc);
+ DPRINTK("EXIT, rc=%d\n", rc);
+ return rc;
+ }
+
+ /**
+- * sata_std_hardreset - reset host port via SATA phy reset
++ * sata_std_hardreset - COMRESET w/o waiting or classification
+ * @link: link to reset
+ * @class: resulting class of attached device
+ * @deadline: deadline jiffies for the operation
+ *
+- * SATA phy-reset host port using DET bits of SControl register,
+- * wait for !BSY and classify the attached device.
++ * Standard SATA COMRESET w/o waiting or classification.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep)
+ *
+ * RETURNS:
+- * 0 on success, -errno otherwise.
++ * 0 if link offline, -EAGAIN if link online, -errno on errors.
+ */
+ int sata_std_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline)
+ {
+- struct ata_port *ap = link->ap;
+ const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
++ bool online;
+ int rc;
+
+- DPRINTK("ENTER\n");
+-
+ /* do hardreset */
+- rc = sata_link_hardreset(link, timing, deadline);
+- if (rc) {
+- ata_link_printk(link, KERN_ERR,
+- "COMRESET failed (errno=%d)\n", rc);
+- return rc;
+- }
+-
+- /* TODO: phy layer with polling, timeouts, etc. */
+- if (ata_link_offline(link)) {
+- *class = ATA_DEV_NONE;
+- DPRINTK("EXIT, link offline\n");
+- return 0;
+- }
+-
+- /* wait a while before checking status */
+- ata_wait_after_reset(ap, deadline);
+-
+- /* If PMP is supported, we have to do follow-up SRST. Note
+- * that some PMPs don't send D2H Reg FIS after hardreset at
+- * all if the first port is empty. Wait for it just for a
+- * second and request follow-up SRST.
+- */
+- if (ap->flags & ATA_FLAG_PMP) {
+- ata_wait_ready(ap, jiffies + HZ);
+- return -EAGAIN;
+- }
+-
+- rc = ata_wait_ready(ap, deadline);
+- /* link occupied, -ENODEV too is an error */
+- if (rc) {
+- ata_link_printk(link, KERN_ERR,
+- "COMRESET failed (errno=%d)\n", rc);
+- return rc;
+- }
+-
+- ap->ops->dev_select(ap, 0); /* probably unnecessary */
+-
+- *class = ata_dev_try_classify(link->device, 1, NULL);
+-
+- DPRINTK("EXIT, class=%u\n", *class);
+- return 0;
++ rc = sata_link_hardreset(link, timing, deadline, &online, NULL);
++ return online ? -EAGAIN : rc;
+ }
+
+ /**
+@@ -4190,35 +3700,11 @@ int sata_std_hardreset(struct ata_link *link, unsigned int *class,
+ */
+ void ata_std_postreset(struct ata_link *link, unsigned int *classes)
+ {
+- struct ata_port *ap = link->ap;
+- u32 serror;
+-
+ DPRINTK("ENTER\n");
+
+ /* print link status */
+ sata_print_link_status(link);
+
+- /* clear SError */
+- if (sata_scr_read(link, SCR_ERROR, &serror) == 0)
+- sata_scr_write(link, SCR_ERROR, serror);
+- link->eh_info.serror = 0;
+-
+- /* is double-select really necessary? */
+- if (classes[0] != ATA_DEV_NONE)
+- ap->ops->dev_select(ap, 1);
+- if (classes[1] != ATA_DEV_NONE)
+- ap->ops->dev_select(ap, 0);
+-
+- /* bail out if no device is present */
+- if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
+- DPRINTK("EXIT, no device\n");
+- return;
+- }
+-
+- /* set up device control */
+- if (ap->ioaddr.ctl_addr)
+- iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
+-
+ DPRINTK("EXIT\n");
+ }
+
+@@ -4528,6 +4014,53 @@ static int ata_is_40wire(struct ata_device *dev)
+ }
+
+ /**
++ * cable_is_40wire - 40/80/SATA decider
++ * @ap: port to consider
++ *
++ * This function encapsulates the policy for speed management
++ * in one place. At the moment we don't cache the result but
++ * there is a good case for setting ap->cbl to the result when
++ * we are called with unknown cables (and figuring out if it
++ * impacts hotplug at all).
++ *
++ * Return 1 if the cable appears to be 40 wire.
++ */
++
++static int cable_is_40wire(struct ata_port *ap)
++{
++ struct ata_link *link;
++ struct ata_device *dev;
++
++ /* If the controller thinks we are 40 wire, we are */
++ if (ap->cbl == ATA_CBL_PATA40)
++ return 1;
++ /* If the controller thinks we are 80 wire, we are */
++ if (ap->cbl == ATA_CBL_PATA80 || ap->cbl == ATA_CBL_SATA)
++ return 0;
++ /* If the system is known to be 40 wire short cable (eg laptop),
++ then we allow 80 wire modes even if the drive isn't sure */
++ if (ap->cbl == ATA_CBL_PATA40_SHORT)
++ return 0;
++ /* If the controller doesn't know we scan
++
++ - Note: We look for all 40 wire detects at this point.
++ Any 80 wire detect is taken to be 80 wire cable
++ because
++ - In many setups only the one drive (slave if present)
++ will give a valid detect
++ - If you have a non detect capable drive you don't
++ want it to colour the choice
++ */
++ ata_port_for_each_link(link, ap) {
++ ata_link_for_each_dev(dev, link) {
++ if (!ata_is_40wire(dev))
++ return 0;
++ }
++ }
++ return 1;
++}
++
++/**
+ * ata_dev_xfermask - Compute supported xfermask of the given device
+ * @dev: Device to compute xfermask for
+ *
+@@ -4595,10 +4128,7 @@ static void ata_dev_xfermask(struct ata_device *dev)
+ */
+ if (xfer_mask & (0xF8 << ATA_SHIFT_UDMA))
+ /* UDMA/44 or higher would be available */
+- if ((ap->cbl == ATA_CBL_PATA40) ||
+- (ata_is_40wire(dev) &&
+- (ap->cbl == ATA_CBL_PATA_UNK ||
+- ap->cbl == ATA_CBL_PATA80))) {
++ if (cable_is_40wire(ap)) {
+ ata_dev_printk(dev, KERN_WARNING,
+ "limited to UDMA/33 due to 40-wire cable\n");
+ xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
+@@ -4759,112 +4289,6 @@ void ata_sg_clean(struct ata_queued_cmd *qc)
+ }
+
+ /**
+- * ata_fill_sg - Fill PCI IDE PRD table
+- * @qc: Metadata associated with taskfile to be transferred
+- *
+- * Fill PCI IDE PRD (scatter-gather) table with segments
+- * associated with the current disk command.
+- *
+- * LOCKING:
+- * spin_lock_irqsave(host lock)
+- *
+- */
+-static void ata_fill_sg(struct ata_queued_cmd *qc)
+-{
+- struct ata_port *ap = qc->ap;
+- struct scatterlist *sg;
+- unsigned int si, pi;
+-
+- pi = 0;
+- for_each_sg(qc->sg, sg, qc->n_elem, si) {
+- u32 addr, offset;
+- u32 sg_len, len;
+-
+- /* determine if physical DMA addr spans 64K boundary.
+- * Note h/w doesn't support 64-bit, so we unconditionally
+- * truncate dma_addr_t to u32.
+- */
+- addr = (u32) sg_dma_address(sg);
+- sg_len = sg_dma_len(sg);
+-
+- while (sg_len) {
+- offset = addr & 0xffff;
+- len = sg_len;
+- if ((offset + sg_len) > 0x10000)
+- len = 0x10000 - offset;
+-
+- ap->prd[pi].addr = cpu_to_le32(addr);
+- ap->prd[pi].flags_len = cpu_to_le32(len & 0xffff);
+- VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len);
+-
+- pi++;
+- sg_len -= len;
+- addr += len;
+- }
+- }
+-
+- ap->prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+-}
+-
+-/**
+- * ata_fill_sg_dumb - Fill PCI IDE PRD table
+- * @qc: Metadata associated with taskfile to be transferred
+- *
+- * Fill PCI IDE PRD (scatter-gather) table with segments
+- * associated with the current disk command. Perform the fill
+- * so that we avoid writing any length 64K records for
+- * controllers that don't follow the spec.
+- *
+- * LOCKING:
+- * spin_lock_irqsave(host lock)
+- *
+- */
+-static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)
+-{
+- struct ata_port *ap = qc->ap;
+- struct scatterlist *sg;
+- unsigned int si, pi;
+-
+- pi = 0;
+- for_each_sg(qc->sg, sg, qc->n_elem, si) {
+- u32 addr, offset;
+- u32 sg_len, len, blen;
+-
+- /* determine if physical DMA addr spans 64K boundary.
+- * Note h/w doesn't support 64-bit, so we unconditionally
+- * truncate dma_addr_t to u32.
+- */
+- addr = (u32) sg_dma_address(sg);
+- sg_len = sg_dma_len(sg);
+-
+- while (sg_len) {
+- offset = addr & 0xffff;
+- len = sg_len;
+- if ((offset + sg_len) > 0x10000)
+- len = 0x10000 - offset;
+-
+- blen = len & 0xffff;
+- ap->prd[pi].addr = cpu_to_le32(addr);
+- if (blen == 0) {
+- /* Some PATA chipsets like the CS5530 can't
+- cope with 0x0000 meaning 64K as the spec says */
+- ap->prd[pi].flags_len = cpu_to_le32(0x8000);
+- blen = 0x8000;
+- ap->prd[++pi].addr = cpu_to_le32(addr + 0x8000);
+- }
+- ap->prd[pi].flags_len = cpu_to_le32(blen);
+- VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len);
+-
+- pi++;
+- sg_len -= len;
+- addr += len;
+- }
+- }
+-
+- ap->prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+-}
+-
+-/**
+ * ata_check_atapi_dma - Check whether ATAPI DMA can be supported
+ * @qc: Metadata associated with taskfile to check
+ *
+@@ -4924,40 +4348,6 @@ int ata_std_qc_defer(struct ata_queued_cmd *qc)
+ return ATA_DEFER_LINK;
+ }
+
+-/**
+- * ata_qc_prep - Prepare taskfile for submission
+- * @qc: Metadata associated with taskfile to be prepared
+- *
+- * Prepare ATA taskfile for submission.
+- *
+- * LOCKING:
+- * spin_lock_irqsave(host lock)
+- */
+-void ata_qc_prep(struct ata_queued_cmd *qc)
+-{
+- if (!(qc->flags & ATA_QCFLAG_DMAMAP))
+- return;
+-
+- ata_fill_sg(qc);
+-}
+-
+-/**
+- * ata_dumb_qc_prep - Prepare taskfile for submission
+- * @qc: Metadata associated with taskfile to be prepared
+- *
+- * Prepare ATA taskfile for submission.
+- *
+- * LOCKING:
+- * spin_lock_irqsave(host lock)
+- */
+-void ata_dumb_qc_prep(struct ata_queued_cmd *qc)
+-{
+- if (!(qc->flags & ATA_QCFLAG_DMAMAP))
+- return;
+-
+- ata_fill_sg_dumb(qc);
+-}
+-
+ void ata_noop_qc_prep(struct ata_queued_cmd *qc) { }
+
+ /**
+@@ -5036,698 +4426,6 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
+ }
+
+ /**
+- * ata_data_xfer - Transfer data by PIO
+- * @dev: device to target
+- * @buf: data buffer
+- * @buflen: buffer length
+- * @rw: read/write
+- *
+- * Transfer data from/to the device data register by PIO.
+- *
+- * LOCKING:
+- * Inherited from caller.
+- *
+- * RETURNS:
+- * Bytes consumed.
+- */
+-unsigned int ata_data_xfer(struct ata_device *dev, unsigned char *buf,
+- unsigned int buflen, int rw)
+-{
+- struct ata_port *ap = dev->link->ap;
+- void __iomem *data_addr = ap->ioaddr.data_addr;
+- unsigned int words = buflen >> 1;
+-
+- /* Transfer multiple of 2 bytes */
+- if (rw == READ)
+- ioread16_rep(data_addr, buf, words);
+- else
+- iowrite16_rep(data_addr, buf, words);
+-
+- /* Transfer trailing 1 byte, if any. */
+- if (unlikely(buflen & 0x01)) {
+- __le16 align_buf[1] = { 0 };
+- unsigned char *trailing_buf = buf + buflen - 1;
+-
+- if (rw == READ) {
+- align_buf[0] = cpu_to_le16(ioread16(data_addr));
+- memcpy(trailing_buf, align_buf, 1);
+- } else {
+- memcpy(align_buf, trailing_buf, 1);
+- iowrite16(le16_to_cpu(align_buf[0]), data_addr);
+- }
+- words++;
+- }
+-
+- return words << 1;
+-}
+-
+-/**
+- * ata_data_xfer_noirq - Transfer data by PIO
+- * @dev: device to target
+- * @buf: data buffer
+- * @buflen: buffer length
+- * @rw: read/write
+- *
+- * Transfer data from/to the device data register by PIO. Do the
+- * transfer with interrupts disabled.
+- *
+- * LOCKING:
+- * Inherited from caller.
+- *
+- * RETURNS:
+- * Bytes consumed.
+- */
+-unsigned int ata_data_xfer_noirq(struct ata_device *dev, unsigned char *buf,
+- unsigned int buflen, int rw)
+-{
+- unsigned long flags;
+- unsigned int consumed;
+-
+- local_irq_save(flags);
+- consumed = ata_data_xfer(dev, buf, buflen, rw);
+- local_irq_restore(flags);
+-
+- return consumed;
+-}
+-
+-
+-/**
+- * ata_pio_sector - Transfer a sector of data.
+- * @qc: Command on going
+- *
+- * Transfer qc->sect_size bytes of data from/to the ATA device.
+- *
+- * LOCKING:
+- * Inherited from caller.
+- */
+-
+-static void ata_pio_sector(struct ata_queued_cmd *qc)
+-{
+- int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
+- struct ata_port *ap = qc->ap;
+- struct page *page;
+- unsigned int offset;
+- unsigned char *buf;
+-
+- if (qc->curbytes == qc->nbytes - qc->sect_size)
+- ap->hsm_task_state = HSM_ST_LAST;
+-
+- page = sg_page(qc->cursg);
+- offset = qc->cursg->offset + qc->cursg_ofs;
+-
+- /* get the current page and offset */
+- page = nth_page(page, (offset >> PAGE_SHIFT));
+- offset %= PAGE_SIZE;
+-
+- DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
+-
+- if (PageHighMem(page)) {
+- unsigned long flags;
+-
+- /* FIXME: use a bounce buffer */
+- local_irq_save(flags);
+- buf = kmap_atomic(page, KM_IRQ0);
+-
+- /* do the actual data transfer */
+- ap->ops->data_xfer(qc->dev, buf + offset, qc->sect_size, do_write);
+-
+- kunmap_atomic(buf, KM_IRQ0);
+- local_irq_restore(flags);
+- } else {
+- buf = page_address(page);
+- ap->ops->data_xfer(qc->dev, buf + offset, qc->sect_size, do_write);
+- }
+-
+- qc->curbytes += qc->sect_size;
+- qc->cursg_ofs += qc->sect_size;
+-
+- if (qc->cursg_ofs == qc->cursg->length) {
+- qc->cursg = sg_next(qc->cursg);
+- qc->cursg_ofs = 0;
+- }
+-}
+-
+-/**
+- * ata_pio_sectors - Transfer one or many sectors.
+- * @qc: Command on going
+- *
+- * Transfer one or many sectors of data from/to the
+- * ATA device for the DRQ request.
+- *
+- * LOCKING:
+- * Inherited from caller.
+- */
+-
+-static void ata_pio_sectors(struct ata_queued_cmd *qc)
+-{
+- if (is_multi_taskfile(&qc->tf)) {
+- /* READ/WRITE MULTIPLE */
+- unsigned int nsect;
+-
+- WARN_ON(qc->dev->multi_count == 0);
+-
+- nsect = min((qc->nbytes - qc->curbytes) / qc->sect_size,
+- qc->dev->multi_count);
+- while (nsect--)
+- ata_pio_sector(qc);
+- } else
+- ata_pio_sector(qc);
+-
+- ata_altstatus(qc->ap); /* flush */
+-}
+-
+-/**
+- * atapi_send_cdb - Write CDB bytes to hardware
+- * @ap: Port to which ATAPI device is attached.
+- * @qc: Taskfile currently active
+- *
+- * When device has indicated its readiness to accept
+- * a CDB, this function is called. Send the CDB.
+- *
+- * LOCKING:
+- * caller.
+- */
+-
+-static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)
+-{
+- /* send SCSI cdb */
+- DPRINTK("send cdb\n");
+- WARN_ON(qc->dev->cdb_len < 12);
+-
+- ap->ops->data_xfer(qc->dev, qc->cdb, qc->dev->cdb_len, 1);
+- ata_altstatus(ap); /* flush */
+-
+- switch (qc->tf.protocol) {
+- case ATAPI_PROT_PIO:
+- ap->hsm_task_state = HSM_ST;
+- break;
+- case ATAPI_PROT_NODATA:
+- ap->hsm_task_state = HSM_ST_LAST;
+- break;
+- case ATAPI_PROT_DMA:
+- ap->hsm_task_state = HSM_ST_LAST;
+- /* initiate bmdma */
+- ap->ops->bmdma_start(qc);
+- break;
+- }
+-}
+-
+-/**
+- * __atapi_pio_bytes - Transfer data from/to the ATAPI device.
+- * @qc: Command on going
+- * @bytes: number of bytes
+- *
+- * Transfer Transfer data from/to the ATAPI device.
+- *
+- * LOCKING:
+- * Inherited from caller.
+- *
+- */
+-static int __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
+-{
+- int rw = (qc->tf.flags & ATA_TFLAG_WRITE) ? WRITE : READ;
+- struct ata_port *ap = qc->ap;
+- struct ata_device *dev = qc->dev;
+- struct ata_eh_info *ehi = &dev->link->eh_info;
+- struct scatterlist *sg;
+- struct page *page;
+- unsigned char *buf;
+- unsigned int offset, count, consumed;
+-
+-next_sg:
+- sg = qc->cursg;
+- if (unlikely(!sg)) {
+- ata_ehi_push_desc(ehi, "unexpected or too much trailing data "
+- "buf=%u cur=%u bytes=%u",
+- qc->nbytes, qc->curbytes, bytes);
+- return -1;
+- }
+-
+- page = sg_page(sg);
+- offset = sg->offset + qc->cursg_ofs;
+-
+- /* get the current page and offset */
+- page = nth_page(page, (offset >> PAGE_SHIFT));
+- offset %= PAGE_SIZE;
+-
+- /* don't overrun current sg */
+- count = min(sg->length - qc->cursg_ofs, bytes);
+-
+- /* don't cross page boundaries */
+- count = min(count, (unsigned int)PAGE_SIZE - offset);
+-
+- DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
+-
+- if (PageHighMem(page)) {
+- unsigned long flags;
+-
+- /* FIXME: use bounce buffer */
+- local_irq_save(flags);
+- buf = kmap_atomic(page, KM_IRQ0);
+-
+- /* do the actual data transfer */
+- consumed = ap->ops->data_xfer(dev, buf + offset, count, rw);
+-
+- kunmap_atomic(buf, KM_IRQ0);
+- local_irq_restore(flags);
+- } else {
+- buf = page_address(page);
+- consumed = ap->ops->data_xfer(dev, buf + offset, count, rw);
+- }
+-
+- bytes -= min(bytes, consumed);
+- qc->curbytes += count;
+- qc->cursg_ofs += count;
+-
+- if (qc->cursg_ofs == sg->length) {
+- qc->cursg = sg_next(qc->cursg);
+- qc->cursg_ofs = 0;
+- }
+-
+- /* consumed can be larger than count only for the last transfer */
+- WARN_ON(qc->cursg && count != consumed);
+-
+- if (bytes)
+- goto next_sg;
+- return 0;
+-}
+-
+-/**
+- * atapi_pio_bytes - Transfer data from/to the ATAPI device.
+- * @qc: Command on going
+- *
+- * Transfer Transfer data from/to the ATAPI device.
+- *
+- * LOCKING:
+- * Inherited from caller.
+- */
+-
+-static void atapi_pio_bytes(struct ata_queued_cmd *qc)
+-{
+- struct ata_port *ap = qc->ap;
+- struct ata_device *dev = qc->dev;
+- struct ata_eh_info *ehi = &dev->link->eh_info;
+- unsigned int ireason, bc_lo, bc_hi, bytes;
+- int i_write, do_write = (qc->tf.flags & ATA_TFLAG_WRITE) ? 1 : 0;
+-
+- /* Abuse qc->result_tf for temp storage of intermediate TF
+- * here to save some kernel stack usage.
+- * For normal completion, qc->result_tf is not relevant. For
+- * error, qc->result_tf is later overwritten by ata_qc_complete().
+- * So, the correctness of qc->result_tf is not affected.
+- */
+- ap->ops->tf_read(ap, &qc->result_tf);
+- ireason = qc->result_tf.nsect;
+- bc_lo = qc->result_tf.lbam;
+- bc_hi = qc->result_tf.lbah;
+- bytes = (bc_hi << 8) | bc_lo;
+-
+- /* shall be cleared to zero, indicating xfer of data */
+- if (unlikely(ireason & (1 << 0)))
+- goto atapi_check;
+-
+- /* make sure transfer direction matches expected */
+- i_write = ((ireason & (1 << 1)) == 0) ? 1 : 0;
+- if (unlikely(do_write != i_write))
+- goto atapi_check;
+-
+- if (unlikely(!bytes))
+- goto atapi_check;
+-
+- VPRINTK("ata%u: xfering %d bytes\n", ap->print_id, bytes);
+-
+- if (unlikely(__atapi_pio_bytes(qc, bytes)))
+- goto err_out;
+- ata_altstatus(ap); /* flush */
+-
+- return;
+-
+- atapi_check:
+- ata_ehi_push_desc(ehi, "ATAPI check failed (ireason=0x%x bytes=%u)",
+- ireason, bytes);
+- err_out:
+- qc->err_mask |= AC_ERR_HSM;
+- ap->hsm_task_state = HSM_ST_ERR;
+-}
+-
+-/**
+- * ata_hsm_ok_in_wq - Check if the qc can be handled in the workqueue.
+- * @ap: the target ata_port
+- * @qc: qc on going
+- *
+- * RETURNS:
+- * 1 if ok in workqueue, 0 otherwise.
+- */
+-
+-static inline int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *qc)
+-{
+- if (qc->tf.flags & ATA_TFLAG_POLLING)
+- return 1;
+-
+- if (ap->hsm_task_state == HSM_ST_FIRST) {
+- if (qc->tf.protocol == ATA_PROT_PIO &&
+- (qc->tf.flags & ATA_TFLAG_WRITE))
+- return 1;
+-
+- if (ata_is_atapi(qc->tf.protocol) &&
+- !(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+- return 1;
+- }
+-
+- return 0;
+-}
+-
+-/**
+- * ata_hsm_qc_complete - finish a qc running on standard HSM
+- * @qc: Command to complete
+- * @in_wq: 1 if called from workqueue, 0 otherwise
+- *
+- * Finish @qc which is running on standard HSM.
+- *
+- * LOCKING:
+- * If @in_wq is zero, spin_lock_irqsave(host lock).
+- * Otherwise, none on entry and grabs host lock.
+- */
+-static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
+-{
+- struct ata_port *ap = qc->ap;
+- unsigned long flags;
+-
+- if (ap->ops->error_handler) {
+- if (in_wq) {
+- spin_lock_irqsave(ap->lock, flags);
+-
+- /* EH might have kicked in while host lock is
+- * released.
+- */
+- qc = ata_qc_from_tag(ap, qc->tag);
+- if (qc) {
+- if (likely(!(qc->err_mask & AC_ERR_HSM))) {
+- ap->ops->irq_on(ap);
+- ata_qc_complete(qc);
+- } else
+- ata_port_freeze(ap);
+- }
+-
+- spin_unlock_irqrestore(ap->lock, flags);
+- } else {
+- if (likely(!(qc->err_mask & AC_ERR_HSM)))
+- ata_qc_complete(qc);
+- else
+- ata_port_freeze(ap);
+- }
+- } else {
+- if (in_wq) {
+- spin_lock_irqsave(ap->lock, flags);
+- ap->ops->irq_on(ap);
+- ata_qc_complete(qc);
+- spin_unlock_irqrestore(ap->lock, flags);
+- } else
+- ata_qc_complete(qc);
+- }
+-}
+-
+-/**
+- * ata_hsm_move - move the HSM to the next state.
+- * @ap: the target ata_port
+- * @qc: qc on going
+- * @status: current device status
+- * @in_wq: 1 if called from workqueue, 0 otherwise
+- *
+- * RETURNS:
+- * 1 when poll next status needed, 0 otherwise.
+- */
+-int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
+- u8 status, int in_wq)
+-{
+- unsigned long flags = 0;
+- int poll_next;
+-
+- WARN_ON((qc->flags & ATA_QCFLAG_ACTIVE) == 0);
+-
+- /* Make sure ata_qc_issue_prot() does not throw things
+- * like DMA polling into the workqueue. Notice that
+- * in_wq is not equivalent to (qc->tf.flags & ATA_TFLAG_POLLING).
+- */
+- WARN_ON(in_wq != ata_hsm_ok_in_wq(ap, qc));
+-
+-fsm_start:
+- DPRINTK("ata%u: protocol %d task_state %d (dev_stat 0x%X)\n",
+- ap->print_id, qc->tf.protocol, ap->hsm_task_state, status);
+-
+- switch (ap->hsm_task_state) {
+- case HSM_ST_FIRST:
+- /* Send first data block or PACKET CDB */
+-
+- /* If polling, we will stay in the work queue after
+- * sending the data. Otherwise, interrupt handler
+- * takes over after sending the data.
+- */
+- poll_next = (qc->tf.flags & ATA_TFLAG_POLLING);
+-
+- /* check device status */
+- if (unlikely((status & ATA_DRQ) == 0)) {
+- /* handle BSY=0, DRQ=0 as error */
+- if (likely(status & (ATA_ERR | ATA_DF)))
+- /* device stops HSM for abort/error */
+- qc->err_mask |= AC_ERR_DEV;
+- else
+- /* HSM violation. Let EH handle this */
+- qc->err_mask |= AC_ERR_HSM;
+-
+- ap->hsm_task_state = HSM_ST_ERR;
+- goto fsm_start;
+- }
+-
+- /* Device should not ask for data transfer (DRQ=1)
+- * when it finds something wrong.
+- * We ignore DRQ here and stop the HSM by
+- * changing hsm_task_state to HSM_ST_ERR and
+- * let the EH abort the command or reset the device.
+- */
+- if (unlikely(status & (ATA_ERR | ATA_DF))) {
+- /* Some ATAPI tape drives forget to clear the ERR bit
+- * when doing the next command (mostly request sense).
+- * We ignore ERR here to workaround and proceed sending
+- * the CDB.
+- */
+- if (!(qc->dev->horkage & ATA_HORKAGE_STUCK_ERR)) {
+- ata_port_printk(ap, KERN_WARNING,
+- "DRQ=1 with device error, "
+- "dev_stat 0x%X\n", status);
+- qc->err_mask |= AC_ERR_HSM;
+- ap->hsm_task_state = HSM_ST_ERR;
+- goto fsm_start;
+- }
+- }
+-
+- /* Send the CDB (atapi) or the first data block (ata pio out).
+- * During the state transition, interrupt handler shouldn't
+- * be invoked before the data transfer is complete and
+- * hsm_task_state is changed. Hence, the following locking.
+- */
+- if (in_wq)
+- spin_lock_irqsave(ap->lock, flags);
+-
+- if (qc->tf.protocol == ATA_PROT_PIO) {
+- /* PIO data out protocol.
+- * send first data block.
+- */
+-
+- /* ata_pio_sectors() might change the state
+- * to HSM_ST_LAST. so, the state is changed here
+- * before ata_pio_sectors().
+- */
+- ap->hsm_task_state = HSM_ST;
+- ata_pio_sectors(qc);
+- } else
+- /* send CDB */
+- atapi_send_cdb(ap, qc);
+-
+- if (in_wq)
+- spin_unlock_irqrestore(ap->lock, flags);
+-
+- /* if polling, ata_pio_task() handles the rest.
+- * otherwise, interrupt handler takes over from here.
+- */
+- break;
+-
+- case HSM_ST:
+- /* complete command or read/write the data register */
+- if (qc->tf.protocol == ATAPI_PROT_PIO) {
+- /* ATAPI PIO protocol */
+- if ((status & ATA_DRQ) == 0) {
+- /* No more data to transfer or device error.
+- * Device error will be tagged in HSM_ST_LAST.
+- */
+- ap->hsm_task_state = HSM_ST_LAST;
+- goto fsm_start;
+- }
+-
+- /* Device should not ask for data transfer (DRQ=1)
+- * when it finds something wrong.
+- * We ignore DRQ here and stop the HSM by
+- * changing hsm_task_state to HSM_ST_ERR and
+- * let the EH abort the command or reset the device.
+- */
+- if (unlikely(status & (ATA_ERR | ATA_DF))) {
+- ata_port_printk(ap, KERN_WARNING, "DRQ=1 with "
+- "device error, dev_stat 0x%X\n",
+- status);
+- qc->err_mask |= AC_ERR_HSM;
+- ap->hsm_task_state = HSM_ST_ERR;
+- goto fsm_start;
+- }
+-
+- atapi_pio_bytes(qc);
+-
+- if (unlikely(ap->hsm_task_state == HSM_ST_ERR))
+- /* bad ireason reported by device */
+- goto fsm_start;
+-
+- } else {
+- /* ATA PIO protocol */
+- if (unlikely((status & ATA_DRQ) == 0)) {
+- /* handle BSY=0, DRQ=0 as error */
+- if (likely(status & (ATA_ERR | ATA_DF)))
+- /* device stops HSM for abort/error */
+- qc->err_mask |= AC_ERR_DEV;
+- else
+- /* HSM violation. Let EH handle this.
+- * Phantom devices also trigger this
+- * condition. Mark hint.
+- */
+- qc->err_mask |= AC_ERR_HSM |
+- AC_ERR_NODEV_HINT;
+-
+- ap->hsm_task_state = HSM_ST_ERR;
+- goto fsm_start;
+- }
+-
+- /* For PIO reads, some devices may ask for
+- * data transfer (DRQ=1) alone with ERR=1.
+- * We respect DRQ here and transfer one
+- * block of junk data before changing the
+- * hsm_task_state to HSM_ST_ERR.
+- *
+- * For PIO writes, ERR=1 DRQ=1 doesn't make
+- * sense since the data block has been
+- * transferred to the device.
+- */
+- if (unlikely(status & (ATA_ERR | ATA_DF))) {
+- /* data might be corrputed */
+- qc->err_mask |= AC_ERR_DEV;
+-
+- if (!(qc->tf.flags & ATA_TFLAG_WRITE)) {
+- ata_pio_sectors(qc);
+- status = ata_wait_idle(ap);
+- }
+-
+- if (status & (ATA_BUSY | ATA_DRQ))
+- qc->err_mask |= AC_ERR_HSM;
+-
+- /* ata_pio_sectors() might change the
+- * state to HSM_ST_LAST. so, the state
+- * is changed after ata_pio_sectors().
+- */
+- ap->hsm_task_state = HSM_ST_ERR;
+- goto fsm_start;
+- }
+-
+- ata_pio_sectors(qc);
+-
+- if (ap->hsm_task_state == HSM_ST_LAST &&
+- (!(qc->tf.flags & ATA_TFLAG_WRITE))) {
+- /* all data read */
+- status = ata_wait_idle(ap);
+- goto fsm_start;
+- }
+- }
+-
+- poll_next = 1;
+- break;
+-
+- case HSM_ST_LAST:
+- if (unlikely(!ata_ok(status))) {
+- qc->err_mask |= __ac_err_mask(status);
+- ap->hsm_task_state = HSM_ST_ERR;
+- goto fsm_start;
+- }
+-
+- /* no more data to transfer */
+- DPRINTK("ata%u: dev %u command complete, drv_stat 0x%x\n",
+- ap->print_id, qc->dev->devno, status);
+-
+- WARN_ON(qc->err_mask);
+-
+- ap->hsm_task_state = HSM_ST_IDLE;
+-
+- /* complete taskfile transaction */
+- ata_hsm_qc_complete(qc, in_wq);
+-
+- poll_next = 0;
+- break;
+-
+- case HSM_ST_ERR:
+- /* make sure qc->err_mask is available to
+- * know what's wrong and recover
+- */
+- WARN_ON(qc->err_mask == 0);
+-
+- ap->hsm_task_state = HSM_ST_IDLE;
+-
+- /* complete taskfile transaction */
+- ata_hsm_qc_complete(qc, in_wq);
+-
+- poll_next = 0;
+- break;
+- default:
+- poll_next = 0;
+- BUG();
+- }
+-
+- return poll_next;
+-}
+-
+-static void ata_pio_task(struct work_struct *work)
+-{
+- struct ata_port *ap =
+- container_of(work, struct ata_port, port_task.work);
+- struct ata_queued_cmd *qc = ap->port_task_data;
+- u8 status;
+- int poll_next;
+-
+-fsm_start:
+- WARN_ON(ap->hsm_task_state == HSM_ST_IDLE);
+-
+- /*
+- * This is purely heuristic. This is a fast path.
+- * Sometimes when we enter, BSY will be cleared in
+- * a chk-status or two. If not, the drive is probably seeking
+- * or something. Snooze for a couple msecs, then
+- * chk-status again. If still busy, queue delayed work.
+- */
+- status = ata_busy_wait(ap, ATA_BUSY, 5);
+- if (status & ATA_BUSY) {
+- msleep(2);
+- status = ata_busy_wait(ap, ATA_BUSY, 10);
+- if (status & ATA_BUSY) {
+- ata_pio_queue_task(ap, qc, ATA_SHORT_PAUSE);
+- return;
+- }
+- }
+-
+- /* move the HSM */
+- poll_next = ata_hsm_move(ap, qc, status, 1);
+-
+- /* another command or interrupt handler
+- * may be running at this point.
+- */
+- if (poll_next)
+- goto fsm_start;
+-}
+-
+-/**
+ * ata_qc_new - Request an available ATA command, for queueing
+ * @ap: Port associated with device @dev
+ * @dev: Device from whom we request an available command structure
+@@ -5850,7 +4548,7 @@ static void fill_result_tf(struct ata_queued_cmd *qc)
+ struct ata_port *ap = qc->ap;
+
+ qc->result_tf.flags = qc->tf.flags;
+- ap->ops->tf_read(ap, &qc->result_tf);
++ ap->ops->qc_fill_rtf(qc);
+ }
+
+ static void ata_verify_xfer(struct ata_queued_cmd *qc)
+@@ -5960,7 +4658,6 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
+ * ata_qc_complete_multiple - Complete multiple qcs successfully
+ * @ap: port in question
+ * @qc_active: new qc_active mask
+- * @finish_qc: LLDD callback invoked before completing a qc
+ *
+ * Complete in-flight commands. This functions is meant to be
+ * called from low-level driver's interrupt routine to complete
+@@ -5973,8 +4670,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
+ * RETURNS:
+ * Number of completed commands on success, -errno otherwise.
+ */
+-int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active,
+- void (*finish_qc)(struct ata_queued_cmd *))
++int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active)
+ {
+ int nr_done = 0;
+ u32 done_mask;
+@@ -5995,8 +4691,6 @@ int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active,
+ continue;
+
+ if ((qc = ata_qc_from_tag(ap, i))) {
+- if (finish_qc)
+- finish_qc(qc);
+ ata_qc_complete(qc);
+ nr_done++;
+ }
+@@ -6055,9 +4749,9 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
+ if (ata_sg_setup(qc))
+ goto sg_err;
+
+- /* if device is sleeping, schedule softreset and abort the link */
++ /* if device is sleeping, schedule reset and abort the link */
+ if (unlikely(qc->dev->flags & ATA_DFLAG_SLEEPING)) {
+- link->eh_info.action |= ATA_EH_SOFTRESET;
++ link->eh_info.action |= ATA_EH_RESET;
+ ata_ehi_push_desc(&link->eh_info, "waking up from sleep");
+ ata_link_abort(link);
+ return;
+@@ -6077,285 +4771,6 @@ err:
+ }
+
+ /**
+- * ata_qc_issue_prot - issue taskfile to device in proto-dependent manner
+- * @qc: command to issue to device
+- *
+- * Using various libata functions and hooks, this function
+- * starts an ATA command. ATA commands are grouped into
+- * classes called "protocols", and issuing each type of protocol
+- * is slightly different.
+- *
+- * May be used as the qc_issue() entry in ata_port_operations.
+- *
+- * LOCKING:
+- * spin_lock_irqsave(host lock)
+- *
+- * RETURNS:
+- * Zero on success, AC_ERR_* mask on failure
+- */
+-
+-unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
+-{
+- struct ata_port *ap = qc->ap;
+-
+- /* Use polling pio if the LLD doesn't handle
+- * interrupt driven pio and atapi CDB interrupt.
+- */
+- if (ap->flags & ATA_FLAG_PIO_POLLING) {
+- switch (qc->tf.protocol) {
+- case ATA_PROT_PIO:
+- case ATA_PROT_NODATA:
+- case ATAPI_PROT_PIO:
+- case ATAPI_PROT_NODATA:
+- qc->tf.flags |= ATA_TFLAG_POLLING;
+- break;
+- case ATAPI_PROT_DMA:
+- if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
+- /* see ata_dma_blacklisted() */
+- BUG();
+- break;
+- default:
+- break;
+- }
+- }
+-
+- /* select the device */
+- ata_dev_select(ap, qc->dev->devno, 1, 0);
+-
+- /* start the command */
+- switch (qc->tf.protocol) {
+- case ATA_PROT_NODATA:
+- if (qc->tf.flags & ATA_TFLAG_POLLING)
+- ata_qc_set_polling(qc);
+-
+- ata_tf_to_host(ap, &qc->tf);
+- ap->hsm_task_state = HSM_ST_LAST;
+-
+- if (qc->tf.flags & ATA_TFLAG_POLLING)
+- ata_pio_queue_task(ap, qc, 0);
+-
+- break;
+-
+- case ATA_PROT_DMA:
+- WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
+-
+- ap->ops->tf_load(ap, &qc->tf); /* load tf registers */
+- ap->ops->bmdma_setup(qc); /* set up bmdma */
+- ap->ops->bmdma_start(qc); /* initiate bmdma */
+- ap->hsm_task_state = HSM_ST_LAST;
+- break;
+-
+- case ATA_PROT_PIO:
+- if (qc->tf.flags & ATA_TFLAG_POLLING)
+- ata_qc_set_polling(qc);
+-
+- ata_tf_to_host(ap, &qc->tf);
+-
+- if (qc->tf.flags & ATA_TFLAG_WRITE) {
+- /* PIO data out protocol */
+- ap->hsm_task_state = HSM_ST_FIRST;
+- ata_pio_queue_task(ap, qc, 0);
+-
+- /* always send first data block using
+- * the ata_pio_task() codepath.
+- */
+- } else {
+- /* PIO data in protocol */
+- ap->hsm_task_state = HSM_ST;
+-
+- if (qc->tf.flags & ATA_TFLAG_POLLING)
+- ata_pio_queue_task(ap, qc, 0);
+-
+- /* if polling, ata_pio_task() handles the rest.
+- * otherwise, interrupt handler takes over from here.
+- */
+- }
+-
+- break;
+-
+- case ATAPI_PROT_PIO:
+- case ATAPI_PROT_NODATA:
+- if (qc->tf.flags & ATA_TFLAG_POLLING)
+- ata_qc_set_polling(qc);
+-
+- ata_tf_to_host(ap, &qc->tf);
+-
+- ap->hsm_task_state = HSM_ST_FIRST;
+-
+- /* send cdb by polling if no cdb interrupt */
+- if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) ||
+- (qc->tf.flags & ATA_TFLAG_POLLING))
+- ata_pio_queue_task(ap, qc, 0);
+- break;
+-
+- case ATAPI_PROT_DMA:
+- WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
+-
+- ap->ops->tf_load(ap, &qc->tf); /* load tf registers */
+- ap->ops->bmdma_setup(qc); /* set up bmdma */
+- ap->hsm_task_state = HSM_ST_FIRST;
+-
+- /* send cdb by polling if no cdb interrupt */
+- if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+- ata_pio_queue_task(ap, qc, 0);
+- break;
+-
+- default:
+- WARN_ON(1);
+- return AC_ERR_SYSTEM;
+- }
+-
+- return 0;
+-}
+-
+-/**
+- * ata_host_intr - Handle host interrupt for given (port, task)
+- * @ap: Port on which interrupt arrived (possibly...)
+- * @qc: Taskfile currently active in engine
+- *
+- * Handle host interrupt for given queued command. Currently,
+- * only DMA interrupts are handled. All other commands are
+- * handled via polling with interrupts disabled (nIEN bit).
+- *
+- * LOCKING:
+- * spin_lock_irqsave(host lock)
+- *
+- * RETURNS:
+- * One if interrupt was handled, zero if not (shared irq).
+- */
+-
+-inline unsigned int ata_host_intr(struct ata_port *ap,
+- struct ata_queued_cmd *qc)
+-{
+- struct ata_eh_info *ehi = &ap->link.eh_info;
+- u8 status, host_stat = 0;
+-
+- VPRINTK("ata%u: protocol %d task_state %d\n",
+- ap->print_id, qc->tf.protocol, ap->hsm_task_state);
+-
+- /* Check whether we are expecting interrupt in this state */
+- switch (ap->hsm_task_state) {
+- case HSM_ST_FIRST:
+- /* Some pre-ATAPI-4 devices assert INTRQ
+- * at this state when ready to receive CDB.
+- */
+-
+- /* Check the ATA_DFLAG_CDB_INTR flag is enough here.
+- * The flag was turned on only for atapi devices. No
+- * need to check ata_is_atapi(qc->tf.protocol) again.
+- */
+- if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+- goto idle_irq;
+- break;
+- case HSM_ST_LAST:
+- if (qc->tf.protocol == ATA_PROT_DMA ||
+- qc->tf.protocol == ATAPI_PROT_DMA) {
+- /* check status of DMA engine */
+- host_stat = ap->ops->bmdma_status(ap);
+- VPRINTK("ata%u: host_stat 0x%X\n",
+- ap->print_id, host_stat);
+-
+- /* if it's not our irq... */
+- if (!(host_stat & ATA_DMA_INTR))
+- goto idle_irq;
+-
+- /* before we do anything else, clear DMA-Start bit */
+- ap->ops->bmdma_stop(qc);
+-
+- if (unlikely(host_stat & ATA_DMA_ERR)) {
+- /* error when transfering data to/from memory */
+- qc->err_mask |= AC_ERR_HOST_BUS;
+- ap->hsm_task_state = HSM_ST_ERR;
+- }
+- }
+- break;
+- case HSM_ST:
+- break;
+- default:
+- goto idle_irq;
+- }
+-
+- /* check altstatus */
+- status = ata_altstatus(ap);
+- if (status & ATA_BUSY)
+- goto idle_irq;
+-
+- /* check main status, clearing INTRQ */
+- status = ata_chk_status(ap);
+- if (unlikely(status & ATA_BUSY))
+- goto idle_irq;
+-
+- /* ack bmdma irq events */
+- ap->ops->irq_clear(ap);
+-
+- ata_hsm_move(ap, qc, status, 0);
+-
+- if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
+- qc->tf.protocol == ATAPI_PROT_DMA))
+- ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
+-
+- return 1; /* irq handled */
+-
+-idle_irq:
+- ap->stats.idle_irq++;
+-
+-#ifdef ATA_IRQ_TRAP
+- if ((ap->stats.idle_irq % 1000) == 0) {
+- ata_chk_status(ap);
+- ap->ops->irq_clear(ap);
+- ata_port_printk(ap, KERN_WARNING, "irq trap\n");
+- return 1;
+- }
+-#endif
+- return 0; /* irq not handled */
+-}
+-
+-/**
+- * ata_interrupt - Default ATA host interrupt handler
+- * @irq: irq line (unused)
+- * @dev_instance: pointer to our ata_host information structure
+- *
+- * Default interrupt handler for PCI IDE devices. Calls
+- * ata_host_intr() for each port that is not disabled.
+- *
+- * LOCKING:
+- * Obtains host lock during operation.
+- *
+- * RETURNS:
+- * IRQ_NONE or IRQ_HANDLED.
+- */
+-
+-irqreturn_t ata_interrupt(int irq, void *dev_instance)
+-{
+- struct ata_host *host = dev_instance;
+- unsigned int i;
+- unsigned int handled = 0;
+- unsigned long flags;
+-
+- /* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */
+- spin_lock_irqsave(&host->lock, flags);
+-
+- for (i = 0; i < host->n_ports; i++) {
+- struct ata_port *ap;
+-
+- ap = host->ports[i];
+- if (ap &&
+- !(ap->flags & ATA_FLAG_DISABLED)) {
+- struct ata_queued_cmd *qc;
+-
+- qc = ata_qc_from_tag(ap, ap->link.active_tag);
+- if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
+- (qc->flags & ATA_QCFLAG_ACTIVE))
+- handled |= ata_host_intr(ap, qc);
+- }
+- }
+-
+- spin_unlock_irqrestore(&host->lock, flags);
+-
+- return IRQ_RETVAL(handled);
+-}
+-
+-/**
+ * sata_scr_valid - test whether SCRs are accessible
+ * @link: ATA link to test SCR accessibility for
+ *
+@@ -6513,32 +4928,6 @@ int ata_link_offline(struct ata_link *link)
+ return 0;
+ }
+
+-int ata_flush_cache(struct ata_device *dev)
+-{
+- unsigned int err_mask;
+- u8 cmd;
+-
+- if (!ata_try_flush_cache(dev))
+- return 0;
+-
+- if (dev->flags & ATA_DFLAG_FLUSH_EXT)
+- cmd = ATA_CMD_FLUSH_EXT;
+- else
+- cmd = ATA_CMD_FLUSH;
+-
+- /* This is wrong. On a failed flush we get back the LBA of the lost
+- sector and we should (assuming it wasn't aborted as unknown) issue
+- a further flush command to continue the writeback until it
+- does not error */
+- err_mask = ata_do_simple_cmd(dev, cmd);
+- if (err_mask) {
+- ata_dev_printk(dev, KERN_ERR, "failed to flush cache\n");
+- return -EIO;
+- }
+-
+- return 0;
+-}
+-
+ #ifdef CONFIG_PM
+ static int ata_host_request_pm(struct ata_host *host, pm_message_t mesg,
+ unsigned int action, unsigned int ehi_flags,
+@@ -6634,7 +5023,7 @@ int ata_host_suspend(struct ata_host *host, pm_message_t mesg)
+ */
+ void ata_host_resume(struct ata_host *host)
+ {
+- ata_host_request_pm(host, PMSG_ON, ATA_EH_SOFTRESET,
++ ata_host_request_pm(host, PMSG_ON, ATA_EH_RESET,
+ ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0);
+ host->dev->power.power_state = PMSG_ON;
+
+@@ -6809,7 +5198,9 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
+ ap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR | ATA_MSG_WARN;
+ #endif
+
++#ifdef CONFIG_ATA_SFF
+ INIT_DELAYED_WORK(&ap->port_task, ata_pio_task);
++#endif
+ INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug);
+ INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan);
+ INIT_LIST_HEAD(&ap->eh_done_q);
+@@ -6959,8 +5350,6 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev,
+
+ if (!host->ops && (pi->port_ops != &ata_dummy_port_ops))
+ host->ops = pi->port_ops;
+- if (!host->private_data && pi->private_data)
+- host->private_data = pi->private_data;
+ }
+
+ return host;
+@@ -6985,6 +5374,56 @@ static void ata_host_stop(struct device *gendev, void *res)
+ }
+
+ /**
++ * ata_finalize_port_ops - finalize ata_port_operations
++ * @ops: ata_port_operations to finalize
++ *
++ * An ata_port_operations can inherit from another ops and that
++ * ops can again inherit from another. This can go on as many
++ * times as necessary as long as there is no loop in the
++ * inheritance chain.
++ *
++ * Ops tables are finalized when the host is started. NULL or
++ * unspecified entries are inherited from the closet ancestor
++ * which has the method and the entry is populated with it.
++ * After finalization, the ops table directly points to all the
++ * methods and ->inherits is no longer necessary and cleared.
++ *
++ * Using ATA_OP_NULL, inheriting ops can force a method to NULL.
++ *
++ * LOCKING:
++ * None.
++ */
++static void ata_finalize_port_ops(struct ata_port_operations *ops)
++{
++ static spinlock_t lock = SPIN_LOCK_UNLOCKED;
++ const struct ata_port_operations *cur;
++ void **begin = (void **)ops;
++ void **end = (void **)&ops->inherits;
++ void **pp;
++
++ if (!ops || !ops->inherits)
++ return;
++
++ spin_lock(&lock);
++
++ for (cur = ops->inherits; cur; cur = cur->inherits) {
++ void **inherit = (void **)cur;
++
++ for (pp = begin; pp < end; pp++, inherit++)
++ if (!*pp)
++ *pp = *inherit;
++ }
++
++ for (pp = begin; pp < end; pp++)
++ if (IS_ERR(*pp))
++ *pp = NULL;
++
++ ops->inherits = NULL;
++
++ spin_unlock(&lock);
++}
++
++/**
+ * ata_host_start - start and freeze ports of an ATA host
+ * @host: ATA host to start ports for
+ *
+@@ -7009,9 +5448,13 @@ int ata_host_start(struct ata_host *host)
+ if (host->flags & ATA_HOST_STARTED)
+ return 0;
+
++ ata_finalize_port_ops(host->ops);
++
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+
++ ata_finalize_port_ops(ap->ops);
++
+ if (!host->ops && !ata_port_is_dummy(ap))
+ host->ops = ap->ops;
+
+@@ -7073,7 +5516,7 @@ int ata_host_start(struct ata_host *host)
+ */
+ /* KILLME - the only user left is ipr */
+ void ata_host_init(struct ata_host *host, struct device *dev,
+- unsigned long flags, const struct ata_port_operations *ops)
++ unsigned long flags, struct ata_port_operations *ops)
+ {
+ spin_lock_init(&host->lock);
+ host->dev = dev;
+@@ -7169,9 +5612,8 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
+ /* kick EH for boot probing */
+ spin_lock_irqsave(ap->lock, flags);
+
+- ehi->probe_mask =
+- (1 << ata_link_max_devices(&ap->link)) - 1;
+- ehi->action |= ATA_EH_SOFTRESET;
++ ehi->probe_mask |= ATA_ALL_DEVICES;
++ ehi->action |= ATA_EH_RESET;
+ ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
+
+ ap->pflags &= ~ATA_PFLAG_INITIALIZING;
+@@ -7336,33 +5778,6 @@ void ata_host_detach(struct ata_host *host)
+ ata_acpi_dissociate(host);
+ }
+
+-/**
+- * ata_std_ports - initialize ioaddr with standard port offsets.
+- * @ioaddr: IO address structure to be initialized
+- *
+- * Utility function which initializes data_addr, error_addr,
+- * feature_addr, nsect_addr, lbal_addr, lbam_addr, lbah_addr,
+- * device_addr, status_addr, and command_addr to standard offsets
+- * relative to cmd_addr.
+- *
+- * Does not set ctl_addr, altstatus_addr, bmdma_addr, or scr_addr.
+- */
+-
+-void ata_std_ports(struct ata_ioports *ioaddr)
+-{
+- ioaddr->data_addr = ioaddr->cmd_addr + ATA_REG_DATA;
+- ioaddr->error_addr = ioaddr->cmd_addr + ATA_REG_ERR;
+- ioaddr->feature_addr = ioaddr->cmd_addr + ATA_REG_FEATURE;
+- ioaddr->nsect_addr = ioaddr->cmd_addr + ATA_REG_NSECT;
+- ioaddr->lbal_addr = ioaddr->cmd_addr + ATA_REG_LBAL;
+- ioaddr->lbam_addr = ioaddr->cmd_addr + ATA_REG_LBAM;
+- ioaddr->lbah_addr = ioaddr->cmd_addr + ATA_REG_LBAH;
+- ioaddr->device_addr = ioaddr->cmd_addr + ATA_REG_DEVICE;
+- ioaddr->status_addr = ioaddr->cmd_addr + ATA_REG_STATUS;
+- ioaddr->command_addr = ioaddr->cmd_addr + ATA_REG_CMD;
+-}
+-
+-
+ #ifdef CONFIG_PCI
+
+ /**
+@@ -7749,33 +6164,20 @@ u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
+ /*
+ * Dummy port_ops
+ */
+-static void ata_dummy_noret(struct ata_port *ap) { }
+-static int ata_dummy_ret0(struct ata_port *ap) { return 0; }
+-static void ata_dummy_qc_noret(struct ata_queued_cmd *qc) { }
+-
+-static u8 ata_dummy_check_status(struct ata_port *ap)
++static unsigned int ata_dummy_qc_issue(struct ata_queued_cmd *qc)
+ {
+- return ATA_DRDY;
++ return AC_ERR_SYSTEM;
+ }
+
+-static unsigned int ata_dummy_qc_issue(struct ata_queued_cmd *qc)
++static void ata_dummy_error_handler(struct ata_port *ap)
+ {
+- return AC_ERR_SYSTEM;
++ /* truly dummy */
+ }
+
+-const struct ata_port_operations ata_dummy_port_ops = {
+- .check_status = ata_dummy_check_status,
+- .check_altstatus = ata_dummy_check_status,
+- .dev_select = ata_noop_dev_select,
++struct ata_port_operations ata_dummy_port_ops = {
+ .qc_prep = ata_noop_qc_prep,
+ .qc_issue = ata_dummy_qc_issue,
+- .freeze = ata_dummy_noret,
+- .thaw = ata_dummy_noret,
+- .error_handler = ata_dummy_noret,
+- .post_internal_cmd = ata_dummy_qc_noret,
+- .irq_clear = ata_dummy_noret,
+- .port_start = ata_dummy_ret0,
+- .port_stop = ata_dummy_noret,
++ .error_handler = ata_dummy_error_handler,
+ };
+
+ const struct ata_port_info ata_dummy_port_info = {
+@@ -7791,10 +6193,11 @@ const struct ata_port_info ata_dummy_port_info = {
+ EXPORT_SYMBOL_GPL(sata_deb_timing_normal);
+ EXPORT_SYMBOL_GPL(sata_deb_timing_hotplug);
+ EXPORT_SYMBOL_GPL(sata_deb_timing_long);
++EXPORT_SYMBOL_GPL(ata_base_port_ops);
++EXPORT_SYMBOL_GPL(sata_port_ops);
+ EXPORT_SYMBOL_GPL(ata_dummy_port_ops);
+ EXPORT_SYMBOL_GPL(ata_dummy_port_info);
+ EXPORT_SYMBOL_GPL(ata_std_bios_param);
+-EXPORT_SYMBOL_GPL(ata_std_ports);
+ EXPORT_SYMBOL_GPL(ata_host_init);
+ EXPORT_SYMBOL_GPL(ata_host_alloc);
+ EXPORT_SYMBOL_GPL(ata_host_alloc_pinfo);
+@@ -7803,15 +6206,8 @@ EXPORT_SYMBOL_GPL(ata_host_register);
+ EXPORT_SYMBOL_GPL(ata_host_activate);
+ EXPORT_SYMBOL_GPL(ata_host_detach);
+ EXPORT_SYMBOL_GPL(ata_sg_init);
+-EXPORT_SYMBOL_GPL(ata_hsm_move);
+ EXPORT_SYMBOL_GPL(ata_qc_complete);
+ EXPORT_SYMBOL_GPL(ata_qc_complete_multiple);
+-EXPORT_SYMBOL_GPL(ata_qc_issue_prot);
+-EXPORT_SYMBOL_GPL(ata_tf_load);
+-EXPORT_SYMBOL_GPL(ata_tf_read);
+-EXPORT_SYMBOL_GPL(ata_noop_dev_select);
+-EXPORT_SYMBOL_GPL(ata_std_dev_select);
+-EXPORT_SYMBOL_GPL(sata_print_link_status);
+ EXPORT_SYMBOL_GPL(atapi_cmd_type);
+ EXPORT_SYMBOL_GPL(ata_tf_to_fis);
+ EXPORT_SYMBOL_GPL(ata_tf_from_fis);
+@@ -7822,37 +6218,17 @@ EXPORT_SYMBOL_GPL(ata_xfer_mode2mask);
+ EXPORT_SYMBOL_GPL(ata_xfer_mode2shift);
+ EXPORT_SYMBOL_GPL(ata_mode_string);
+ EXPORT_SYMBOL_GPL(ata_id_xfermask);
+-EXPORT_SYMBOL_GPL(ata_check_status);
+-EXPORT_SYMBOL_GPL(ata_altstatus);
+-EXPORT_SYMBOL_GPL(ata_exec_command);
+ EXPORT_SYMBOL_GPL(ata_port_start);
+-EXPORT_SYMBOL_GPL(ata_sff_port_start);
+-EXPORT_SYMBOL_GPL(ata_interrupt);
+ EXPORT_SYMBOL_GPL(ata_do_set_mode);
+-EXPORT_SYMBOL_GPL(ata_data_xfer);
+-EXPORT_SYMBOL_GPL(ata_data_xfer_noirq);
+ EXPORT_SYMBOL_GPL(ata_std_qc_defer);
+-EXPORT_SYMBOL_GPL(ata_qc_prep);
+-EXPORT_SYMBOL_GPL(ata_dumb_qc_prep);
+ EXPORT_SYMBOL_GPL(ata_noop_qc_prep);
+-EXPORT_SYMBOL_GPL(ata_bmdma_setup);
+-EXPORT_SYMBOL_GPL(ata_bmdma_start);
+-EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear);
+-EXPORT_SYMBOL_GPL(ata_bmdma_status);
+-EXPORT_SYMBOL_GPL(ata_bmdma_stop);
+-EXPORT_SYMBOL_GPL(ata_bmdma_freeze);
+-EXPORT_SYMBOL_GPL(ata_bmdma_thaw);
+-EXPORT_SYMBOL_GPL(ata_bmdma_drive_eh);
+-EXPORT_SYMBOL_GPL(ata_bmdma_error_handler);
+-EXPORT_SYMBOL_GPL(ata_bmdma_post_internal_cmd);
+ EXPORT_SYMBOL_GPL(ata_port_probe);
+ EXPORT_SYMBOL_GPL(ata_dev_disable);
+ EXPORT_SYMBOL_GPL(sata_set_spd);
++EXPORT_SYMBOL_GPL(ata_wait_after_reset);
+ EXPORT_SYMBOL_GPL(sata_link_debounce);
+ EXPORT_SYMBOL_GPL(sata_link_resume);
+-EXPORT_SYMBOL_GPL(ata_bus_reset);
+ EXPORT_SYMBOL_GPL(ata_std_prereset);
+-EXPORT_SYMBOL_GPL(ata_std_softreset);
+ EXPORT_SYMBOL_GPL(sata_link_hardreset);
+ EXPORT_SYMBOL_GPL(sata_std_hardreset);
+ EXPORT_SYMBOL_GPL(ata_std_postreset);
+@@ -7861,15 +6237,11 @@ EXPORT_SYMBOL_GPL(ata_dev_pair);
+ EXPORT_SYMBOL_GPL(ata_port_disable);
+ EXPORT_SYMBOL_GPL(ata_ratelimit);
+ EXPORT_SYMBOL_GPL(ata_wait_register);
+-EXPORT_SYMBOL_GPL(ata_busy_sleep);
+-EXPORT_SYMBOL_GPL(ata_wait_after_reset);
+-EXPORT_SYMBOL_GPL(ata_wait_ready);
+ EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
+ EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
+ EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
+ EXPORT_SYMBOL_GPL(ata_scsi_slave_destroy);
+ EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth);
+-EXPORT_SYMBOL_GPL(ata_host_intr);
+ EXPORT_SYMBOL_GPL(sata_scr_valid);
+ EXPORT_SYMBOL_GPL(sata_scr_read);
+ EXPORT_SYMBOL_GPL(sata_scr_write);
+@@ -7892,11 +6264,6 @@ EXPORT_SYMBOL_GPL(ata_timing_cycle2mode);
+
+ #ifdef CONFIG_PCI
+ EXPORT_SYMBOL_GPL(pci_test_config_bits);
+-EXPORT_SYMBOL_GPL(ata_pci_init_sff_host);
+-EXPORT_SYMBOL_GPL(ata_pci_init_bmdma);
+-EXPORT_SYMBOL_GPL(ata_pci_prepare_sff_host);
+-EXPORT_SYMBOL_GPL(ata_pci_activate_sff_host);
+-EXPORT_SYMBOL_GPL(ata_pci_init_one);
+ EXPORT_SYMBOL_GPL(ata_pci_remove_one);
+ #ifdef CONFIG_PM
+ EXPORT_SYMBOL_GPL(ata_pci_device_do_suspend);
+@@ -7904,16 +6271,8 @@ EXPORT_SYMBOL_GPL(ata_pci_device_do_resume);
+ EXPORT_SYMBOL_GPL(ata_pci_device_suspend);
+ EXPORT_SYMBOL_GPL(ata_pci_device_resume);
+ #endif /* CONFIG_PM */
+-EXPORT_SYMBOL_GPL(ata_pci_default_filter);
+-EXPORT_SYMBOL_GPL(ata_pci_clear_simplex);
+ #endif /* CONFIG_PCI */
+
+-EXPORT_SYMBOL_GPL(sata_pmp_qc_defer_cmd_switch);
+-EXPORT_SYMBOL_GPL(sata_pmp_std_prereset);
+-EXPORT_SYMBOL_GPL(sata_pmp_std_hardreset);
+-EXPORT_SYMBOL_GPL(sata_pmp_std_postreset);
+-EXPORT_SYMBOL_GPL(sata_pmp_do_eh);
+-
+ EXPORT_SYMBOL_GPL(__ata_ehi_push_desc);
+ EXPORT_SYMBOL_GPL(ata_ehi_push_desc);
+ EXPORT_SYMBOL_GPL(ata_ehi_clear_desc);
+@@ -7931,8 +6290,7 @@ EXPORT_SYMBOL_GPL(ata_eh_thaw_port);
+ EXPORT_SYMBOL_GPL(ata_eh_qc_complete);
+ EXPORT_SYMBOL_GPL(ata_eh_qc_retry);
+ EXPORT_SYMBOL_GPL(ata_do_eh);
+-EXPORT_SYMBOL_GPL(ata_irq_on);
+-EXPORT_SYMBOL_GPL(ata_dev_try_classify);
++EXPORT_SYMBOL_GPL(ata_std_error_handler);
+
+ EXPORT_SYMBOL_GPL(ata_cable_40wire);
+ EXPORT_SYMBOL_GPL(ata_cable_80wire);
+diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
+index a583032..61dcd00 100644
+--- a/drivers/ata/libata-eh.c
++++ b/drivers/ata/libata-eh.c
+@@ -873,9 +873,9 @@ int sata_async_notification(struct ata_port *ap)
+ if (rc == 0)
+ sata_scr_write(&ap->link, SCR_NOTIFICATION, sntf);
+
+- if (!ap->nr_pmp_links || rc) {
++ if (!sata_pmp_attached(ap) || rc) {
+ /* PMP is not attached or SNTF is not available */
+- if (!ap->nr_pmp_links) {
++ if (!sata_pmp_attached(ap)) {
+ /* PMP is not attached. Check whether ATAPI
+ * AN is configured. If so, notify media
+ * change.
+@@ -1079,19 +1079,6 @@ void ata_eh_about_to_do(struct ata_link *link, struct ata_device *dev,
+
+ spin_lock_irqsave(ap->lock, flags);
+
+- /* Reset is represented by combination of actions and EHI
+- * flags. Suck in all related bits before clearing eh_info to
+- * avoid losing requested action.
+- */
+- if (action & ATA_EH_RESET_MASK) {
+- ehc->i.action |= ehi->action & ATA_EH_RESET_MASK;
+- ehc->i.flags |= ehi->flags & ATA_EHI_RESET_MODIFIER_MASK;
+-
+- /* make sure all reset actions are cleared & clear EHI flags */
+- action |= ATA_EH_RESET_MASK;
+- ehi->flags &= ~ATA_EHI_RESET_MODIFIER_MASK;
+- }
+-
+ ata_eh_clear_action(link, dev, ehi, action);
+
+ if (!(ehc->i.flags & ATA_EHI_QUIET))
+@@ -1117,12 +1104,6 @@ void ata_eh_done(struct ata_link *link, struct ata_device *dev,
+ {
+ struct ata_eh_context *ehc = &link->eh_context;
+
+- /* if reset is complete, clear all reset actions & reset modifier */
+- if (action & ATA_EH_RESET_MASK) {
+- action |= ATA_EH_RESET_MASK;
+- ehc->i.flags &= ~ATA_EHI_RESET_MODIFIER_MASK;
+- }
+-
+ ata_eh_clear_action(link, dev, &ehc->i, action);
+ }
+
+@@ -1329,20 +1310,20 @@ static void ata_eh_analyze_serror(struct ata_link *link)
+
+ if (serror & SERR_PERSISTENT) {
+ err_mask |= AC_ERR_ATA_BUS;
+- action |= ATA_EH_HARDRESET;
++ action |= ATA_EH_RESET;
+ }
+ if (serror &
+ (SERR_DATA_RECOVERED | SERR_COMM_RECOVERED | SERR_DATA)) {
+ err_mask |= AC_ERR_ATA_BUS;
+- action |= ATA_EH_SOFTRESET;
++ action |= ATA_EH_RESET;
+ }
+ if (serror & SERR_PROTOCOL) {
+ err_mask |= AC_ERR_HSM;
+- action |= ATA_EH_SOFTRESET;
++ action |= ATA_EH_RESET;
+ }
+ if (serror & SERR_INTERNAL) {
+ err_mask |= AC_ERR_SYSTEM;
+- action |= ATA_EH_HARDRESET;
++ action |= ATA_EH_RESET;
+ }
+
+ /* Determine whether a hotplug event has occurred. Both
+@@ -1421,6 +1402,7 @@ static void ata_eh_analyze_ncq_error(struct ata_link *link)
+ /* we've got the perpetrator, condemn it */
+ qc = __ata_qc_from_tag(ap, tag);
+ memcpy(&qc->result_tf, &tf, sizeof(tf));
++ qc->result_tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
+ qc->err_mask |= AC_ERR_DEV | AC_ERR_NCQ;
+ ehc->i.err_mask &= ~AC_ERR_DEV;
+ }
+@@ -1448,7 +1430,7 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
+
+ if ((stat & (ATA_BUSY | ATA_DRQ | ATA_DRDY)) != ATA_DRDY) {
+ qc->err_mask |= AC_ERR_HSM;
+- return ATA_EH_SOFTRESET;
++ return ATA_EH_RESET;
+ }
+
+ if (stat & (ATA_ERR | ATA_DF))
+@@ -1484,7 +1466,7 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
+ }
+
+ if (qc->err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT | AC_ERR_ATA_BUS))
+- action |= ATA_EH_SOFTRESET;
++ action |= ATA_EH_RESET;
+
+ return action;
+ }
+@@ -1685,7 +1667,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
+ if (verdict & ATA_EH_SPDN_SPEED_DOWN) {
+ /* speed down SATA link speed if possible */
+ if (sata_down_spd_limit(link) == 0) {
+- action |= ATA_EH_HARDRESET;
++ action |= ATA_EH_RESET;
+ goto done;
+ }
+
+@@ -1705,7 +1687,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
+ dev->spdn_cnt++;
+
+ if (ata_down_xfermask_limit(dev, sel) == 0) {
+- action |= ATA_EH_SOFTRESET;
++ action |= ATA_EH_RESET;
+ goto done;
+ }
+ }
+@@ -1719,7 +1701,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
+ (dev->xfer_shift != ATA_SHIFT_PIO)) {
+ if (ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO) == 0) {
+ dev->spdn_cnt = 0;
+- action |= ATA_EH_SOFTRESET;
++ action |= ATA_EH_RESET;
+ goto done;
+ }
+ }
+@@ -1764,9 +1746,9 @@ static void ata_eh_link_autopsy(struct ata_link *link)
+ ehc->i.serror |= serror;
+ ata_eh_analyze_serror(link);
+ } else if (rc != -EOPNOTSUPP) {
+- /* SError read failed, force hardreset and probing */
+- ata_ehi_schedule_probe(&ehc->i);
+- ehc->i.action |= ATA_EH_HARDRESET;
++ /* SError read failed, force reset and probing */
++ ehc->i.probe_mask |= ATA_ALL_DEVICES;
++ ehc->i.action |= ATA_EH_RESET;
+ ehc->i.err_mask |= AC_ERR_OTHER;
+ }
+
+@@ -1804,6 +1786,11 @@ static void ata_eh_link_autopsy(struct ata_link *link)
+ if (qc->flags & ATA_QCFLAG_SENSE_VALID)
+ qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER);
+
++ /* determine whether the command is worth retrying */
++ if (!(qc->err_mask & AC_ERR_INVALID) &&
++ ((qc->flags & ATA_QCFLAG_IO) || qc->err_mask != AC_ERR_DEV))
++ qc->flags |= ATA_QCFLAG_RETRY;
++
+ /* accumulate error info */
+ ehc->i.dev = qc->dev;
+ all_err_mask |= qc->err_mask;
+@@ -1814,7 +1801,7 @@ static void ata_eh_link_autopsy(struct ata_link *link)
+ /* enforce default EH actions */
+ if (ap->pflags & ATA_PFLAG_FROZEN ||
+ all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
+- ehc->i.action |= ATA_EH_SOFTRESET;
++ ehc->i.action |= ATA_EH_RESET;
+ else if (((eflags & ATA_EFLAG_IS_IO) && all_err_mask) ||
+ (!(eflags & ATA_EFLAG_IS_IO) && (all_err_mask & ~AC_ERR_DEV)))
+ ehc->i.action |= ATA_EH_REVALIDATE;
+@@ -1867,7 +1854,7 @@ void ata_eh_autopsy(struct ata_port *ap)
+ /* Autopsy of fanout ports can affect host link autopsy.
+ * Perform host link autopsy last.
+ */
+- if (ap->nr_pmp_links)
++ if (sata_pmp_attached(ap))
+ ata_eh_link_autopsy(&ap->link);
+ }
+
+@@ -2066,41 +2053,29 @@ static int ata_do_reset(struct ata_link *link, ata_reset_fn_t reset,
+ classes[dev->devno] = ATA_DEV_UNKNOWN;
+
+ rc = reset(link, classes, deadline);
+- if (rc)
+- return rc;
+
+- /* If any class isn't ATA_DEV_UNKNOWN, consider classification
+- * is complete and convert all ATA_DEV_UNKNOWN to
+- * ATA_DEV_NONE.
+- */
++ /* convert all ATA_DEV_UNKNOWN to ATA_DEV_NONE */
+ ata_link_for_each_dev(dev, link)
+- if (classes[dev->devno] != ATA_DEV_UNKNOWN)
+- break;
+-
+- if (dev) {
+- ata_link_for_each_dev(dev, link) {
+- if (classes[dev->devno] == ATA_DEV_UNKNOWN)
+- classes[dev->devno] = ATA_DEV_NONE;
+- }
+- }
++ if (classes[dev->devno] == ATA_DEV_UNKNOWN)
++ classes[dev->devno] = ATA_DEV_NONE;
+
+- return 0;
++ return rc;
+ }
+
+ static int ata_eh_followup_srst_needed(struct ata_link *link,
+ int rc, int classify,
+ const unsigned int *classes)
+ {
+- if (link->flags & ATA_LFLAG_NO_SRST)
++ if ((link->flags & ATA_LFLAG_NO_SRST) || ata_link_offline(link))
+ return 0;
+- if (rc == -EAGAIN)
+- return 1;
++ if (rc == -EAGAIN) {
++ if (classify)
++ return 1;
++ rc = 0;
++ }
+ if (rc != 0)
+ return 0;
+- if ((link->ap->flags & ATA_FLAG_PMP) && ata_is_host_link(link))
+- return 1;
+- if (classify && !(link->flags & ATA_LFLAG_ASSUME_CLASS) &&
+- classes[0] == ATA_DEV_UNKNOWN)
++ if (sata_pmp_supported(link->ap) && ata_is_host_link(link))
+ return 1;
+ return 0;
+ }
+@@ -2118,7 +2093,6 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ int try = 0;
+ struct ata_device *dev;
+ unsigned long deadline, now;
+- unsigned int tmp_action;
+ ata_reset_fn_t reset;
+ unsigned long flags;
+ u32 sstatus;
+@@ -2129,7 +2103,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ ap->pflags |= ATA_PFLAG_RESETTING;
+ spin_unlock_irqrestore(ap->lock, flags);
+
+- ata_eh_about_to_do(link, NULL, ehc->i.action & ATA_EH_RESET_MASK);
++ ata_eh_about_to_do(link, NULL, ATA_EH_RESET);
+
+ ata_link_for_each_dev(dev, link) {
+ /* If we issue an SRST then an ATA drive (not ATAPI)
+@@ -2159,17 +2133,20 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ goto done;
+ }
+
+- /* Determine which reset to use and record in ehc->i.action.
+- * prereset() may examine and modify it.
+- */
+- if (softreset && (!hardreset || (!(lflags & ATA_LFLAG_NO_SRST) &&
+- !sata_set_spd_needed(link) &&
+- !(ehc->i.action & ATA_EH_HARDRESET))))
+- tmp_action = ATA_EH_SOFTRESET;
+- else
+- tmp_action = ATA_EH_HARDRESET;
+-
+- ehc->i.action = (ehc->i.action & ~ATA_EH_RESET_MASK) | tmp_action;
++ /* prefer hardreset */
++ ehc->i.action &= ~ATA_EH_RESET;
++ if (hardreset) {
++ reset = hardreset;
++ ehc->i.action = ATA_EH_HARDRESET;
++ } else if (softreset) {
++ reset = softreset;
++ ehc->i.action = ATA_EH_SOFTRESET;
++ } else {
++ ata_link_printk(link, KERN_ERR, "BUG: no reset method, "
++ "please report to linux-ide at vger.kernel.org\n");
++ dump_stack();
++ return -EINVAL;
++ }
+
+ if (prereset) {
+ rc = prereset(link, jiffies + ATA_EH_PRERESET_TIMEOUT);
+@@ -2177,7 +2154,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ if (rc == -ENOENT) {
+ ata_link_printk(link, KERN_DEBUG,
+ "port disabled. ignoring.\n");
+- ehc->i.action &= ~ATA_EH_RESET_MASK;
++ ehc->i.action &= ~ATA_EH_RESET;
+
+ ata_link_for_each_dev(dev, link)
+ classes[dev->devno] = ATA_DEV_NONE;
+@@ -2190,12 +2167,8 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ }
+ }
+
+- /* prereset() might have modified ehc->i.action */
+- if (ehc->i.action & ATA_EH_HARDRESET)
+- reset = hardreset;
+- else if (ehc->i.action & ATA_EH_SOFTRESET)
+- reset = softreset;
+- else {
++ /* prereset() might have cleared ATA_EH_RESET */
++ if (!(ehc->i.action & ATA_EH_RESET)) {
+ /* prereset told us not to reset, bang classes and return */
+ ata_link_for_each_dev(dev, link)
+ classes[dev->devno] = ATA_DEV_NONE;
+@@ -2203,14 +2176,6 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ goto out;
+ }
+
+- /* did prereset() screw up? if so, fix up to avoid oopsing */
+- if (!reset) {
+- if (softreset)
+- reset = softreset;
+- else
+- reset = hardreset;
+- }
+-
+ retry:
+ deadline = jiffies + ata_eh_reset_timeouts[try++];
+
+@@ -2240,7 +2205,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ goto fail;
+ }
+
+- ata_eh_about_to_do(link, NULL, ATA_EH_RESET_MASK);
++ ata_eh_about_to_do(link, NULL, ATA_EH_RESET);
+ rc = ata_do_reset(link, reset, classes, deadline);
+ }
+
+@@ -2248,21 +2213,6 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ if (rc && rc != -EAGAIN)
+ goto fail;
+
+- /* was classification successful? */
+- if (classify && classes[0] == ATA_DEV_UNKNOWN &&
+- !(lflags & ATA_LFLAG_ASSUME_CLASS)) {
+- if (try < max_tries) {
+- ata_link_printk(link, KERN_WARNING,
+- "classification failed\n");
+- rc = -EINVAL;
+- goto fail;
+- }
+-
+- ata_link_printk(link, KERN_WARNING,
+- "classfication failed, assuming ATA\n");
+- lflags |= ATA_LFLAG_ASSUME_ATA;
+- }
+-
+ done:
+ ata_link_for_each_dev(dev, link) {
+ /* After the reset, the device state is PIO 0 and the
+@@ -2290,7 +2240,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ postreset(link, classes);
+
+ /* reset successful, schedule revalidation */
+- ata_eh_done(link, NULL, ehc->i.action & ATA_EH_RESET_MASK);
++ ata_eh_done(link, NULL, ATA_EH_RESET);
+ ehc->i.action |= ATA_EH_REVALIDATE;
+
+ rc = 0;
+@@ -2305,6 +2255,11 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ return rc;
+
+ fail:
++ /* if SCR isn't accessible on a fan-out port, PMP needs to be reset */
++ if (!ata_is_host_link(link) &&
++ sata_scr_read(link, SCR_STATUS, &sstatus))
++ rc = -ERESTART;
++
+ if (rc == -ERESTART || try >= max_tries)
+ goto out;
+
+@@ -2515,6 +2470,7 @@ static int ata_link_nr_vacant(struct ata_link *link)
+
+ static int ata_eh_skip_recovery(struct ata_link *link)
+ {
++ struct ata_port *ap = link->ap;
+ struct ata_eh_context *ehc = &link->eh_context;
+ struct ata_device *dev;
+
+@@ -2522,9 +2478,13 @@ static int ata_eh_skip_recovery(struct ata_link *link)
+ if (link->flags & ATA_LFLAG_DISABLED)
+ return 1;
+
+- /* thaw frozen port, resume link and recover failed devices */
+- if ((link->ap->pflags & ATA_PFLAG_FROZEN) ||
+- (ehc->i.flags & ATA_EHI_RESUME_LINK) || ata_link_nr_enabled(link))
++ /* thaw frozen port and recover failed devices */
++ if ((ap->pflags & ATA_PFLAG_FROZEN) || ata_link_nr_enabled(link))
++ return 0;
++
++ /* reset at least once if reset is requested */
++ if ((ehc->i.action & ATA_EH_RESET) &&
++ !(ehc->i.flags & ATA_EHI_DID_RESET))
+ return 0;
+
+ /* skip if class codes for all vacant slots are ATA_DEV_NONE */
+@@ -2548,7 +2508,7 @@ static int ata_eh_schedule_probe(struct ata_device *dev)
+ ata_eh_detach_dev(dev);
+ ata_dev_init(dev);
+ ehc->did_probe_mask |= (1 << dev->devno);
+- ehc->i.action |= ATA_EH_SOFTRESET;
++ ehc->i.action |= ATA_EH_RESET;
+ ehc->saved_xfer_mode[dev->devno] = 0;
+ ehc->saved_ncq_enabled &= ~(1 << dev->devno);
+
+@@ -2592,12 +2552,7 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
+
+ return 1;
+ } else {
+- /* soft didn't work? be haaaaard */
+- if (ehc->i.flags & ATA_EHI_DID_RESET)
+- ehc->i.action |= ATA_EH_HARDRESET;
+- else
+- ehc->i.action |= ATA_EH_SOFTRESET;
+-
++ ehc->i.action |= ATA_EH_RESET;
+ return 0;
+ }
+ }
+@@ -2690,7 +2645,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
+ ehc->i.action = 0;
+
+ /* do we need to reset? */
+- if (ehc->i.action & ATA_EH_RESET_MASK)
++ if (ehc->i.action & ATA_EH_RESET)
+ reset = 1;
+
+ ata_link_for_each_dev(dev, link)
+@@ -2702,13 +2657,13 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
+ /* if PMP is attached, this function only deals with
+ * downstream links, port should stay thawed.
+ */
+- if (!ap->nr_pmp_links)
++ if (!sata_pmp_attached(ap))
+ ata_eh_freeze_port(ap);
+
+ ata_port_for_each_link(link, ap) {
+ struct ata_eh_context *ehc = &link->eh_context;
+
+- if (!(ehc->i.action & ATA_EH_RESET_MASK))
++ if (!(ehc->i.action & ATA_EH_RESET))
+ continue;
+
+ rc = ata_eh_reset(link, ata_link_nr_vacant(link),
+@@ -2721,7 +2676,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
+ }
+ }
+
+- if (!ap->nr_pmp_links)
++ if (!sata_pmp_attached(ap))
+ ata_eh_thaw_port(ap);
+ }
+
+@@ -2765,7 +2720,7 @@ dev_fail:
+ /* PMP reset requires working host port.
+ * Can't retry if it's frozen.
+ */
+- if (ap->nr_pmp_links)
++ if (sata_pmp_attached(ap))
+ goto out;
+ break;
+ }
+@@ -2817,18 +2772,11 @@ void ata_eh_finish(struct ata_port *ap)
+ /* FIXME: Once EH migration is complete,
+ * generate sense data in this function,
+ * considering both err_mask and tf.
+- *
+- * There's no point in retrying invalid
+- * (detected by libata) and non-IO device
+- * errors (rejected by device). Finish them
+- * immediately.
+ */
+- if ((qc->err_mask & AC_ERR_INVALID) ||
+- (!(qc->flags & ATA_QCFLAG_IO) &&
+- qc->err_mask == AC_ERR_DEV))
+- ata_eh_qc_complete(qc);
+- else
++ if (qc->flags & ATA_QCFLAG_RETRY)
+ ata_eh_qc_retry(qc);
++ else
++ ata_eh_qc_complete(qc);
+ } else {
+ if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
+ ata_eh_qc_complete(qc);
+@@ -2848,6 +2796,7 @@ void ata_eh_finish(struct ata_port *ap)
+ /**
+ * ata_do_eh - do standard error handling
+ * @ap: host port to handle error for
++ *
+ * @prereset: prereset method (can be NULL)
+ * @softreset: softreset method (can be NULL)
+ * @hardreset: hardreset method (can be NULL)
+@@ -2878,6 +2827,27 @@ void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+ ata_eh_finish(ap);
+ }
+
++/**
++ * ata_std_error_handler - standard error handler
++ * @ap: host port to handle error for
++ *
++ * Standard error handler
++ *
++ * LOCKING:
++ * Kernel thread context (may sleep).
++ */
++void ata_std_error_handler(struct ata_port *ap)
++{
++ struct ata_port_operations *ops = ap->ops;
++ ata_reset_fn_t hardreset = ops->hardreset;
++
++ /* ignore built-in hardreset if SCR access is not available */
++ if (ata_is_builtin_hardreset(hardreset) && !sata_scr_valid(&ap->link))
++ hardreset = NULL;
++
++ ata_do_eh(ap, ops->prereset, ops->softreset, hardreset, ops->postreset);
++}
++
+ #ifdef CONFIG_PM
+ /**
+ * ata_eh_handle_port_suspend - perform port suspend operation
+diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
+index d91f509..ff1822a 100644
+--- a/drivers/ata/libata-pmp.c
++++ b/drivers/ata/libata-pmp.c
+@@ -11,6 +11,14 @@
+ #include <linux/libata.h>
+ #include "libata.h"
+
++const struct ata_port_operations sata_pmp_port_ops = {
++ .inherits = &sata_port_ops,
++ .pmp_prereset = ata_std_prereset,
++ .pmp_hardreset = sata_std_hardreset,
++ .pmp_postreset = ata_std_postreset,
++ .error_handler = sata_pmp_error_handler,
++};
++
+ /**
+ * sata_pmp_read - read PMP register
+ * @link: link to read PMP register for
+@@ -176,140 +184,6 @@ int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val)
+ }
+
+ /**
+- * sata_pmp_std_prereset - prepare PMP link for reset
+- * @link: link to be reset
+- * @deadline: deadline jiffies for the operation
+- *
+- * @link is about to be reset. Initialize it.
+- *
+- * LOCKING:
+- * Kernel thread context (may sleep)
+- *
+- * RETURNS:
+- * 0 on success, -errno otherwise.
+- */
+-int sata_pmp_std_prereset(struct ata_link *link, unsigned long deadline)
+-{
+- struct ata_eh_context *ehc = &link->eh_context;
+- const unsigned long *timing = sata_ehc_deb_timing(ehc);
+- int rc;
+-
+- /* force HRST? */
+- if (link->flags & ATA_LFLAG_NO_SRST)
+- ehc->i.action |= ATA_EH_HARDRESET;
+-
+- /* handle link resume */
+- if ((ehc->i.flags & ATA_EHI_RESUME_LINK) &&
+- (link->flags & ATA_LFLAG_HRST_TO_RESUME))
+- ehc->i.action |= ATA_EH_HARDRESET;
+-
+- /* if we're about to do hardreset, nothing more to do */
+- if (ehc->i.action & ATA_EH_HARDRESET)
+- return 0;
+-
+- /* resume link */
+- rc = sata_link_resume(link, timing, deadline);
+- if (rc) {
+- /* phy resume failed */
+- ata_link_printk(link, KERN_WARNING, "failed to resume link "
+- "for reset (errno=%d)\n", rc);
+- return rc;
+- }
+-
+- /* clear SError bits including .X which blocks the port when set */
+- rc = sata_scr_write(link, SCR_ERROR, 0xffffffff);
+- if (rc) {
+- ata_link_printk(link, KERN_ERR,
+- "failed to clear SError (errno=%d)\n", rc);
+- return rc;
+- }
+-
+- return 0;
+-}
+-
+-/**
+- * sata_pmp_std_hardreset - standard hardreset method for PMP link
+- * @link: link to be reset
+- * @class: resulting class of attached device
+- * @deadline: deadline jiffies for the operation
+- *
+- * Hardreset PMP port @link. Note that this function doesn't
+- * wait for BSY clearance. There simply isn't a generic way to
+- * wait the event. Instead, this function return -EAGAIN thus
+- * telling libata-EH to followup with softreset.
+- *
+- * LOCKING:
+- * Kernel thread context (may sleep)
+- *
+- * RETURNS:
+- * 0 on success, -errno otherwise.
+- */
+-int sata_pmp_std_hardreset(struct ata_link *link, unsigned int *class,
+- unsigned long deadline)
+-{
+- const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
+- u32 tmp;
+- int rc;
+-
+- DPRINTK("ENTER\n");
+-
+- /* do hardreset */
+- rc = sata_link_hardreset(link, timing, deadline);
+- if (rc) {
+- ata_link_printk(link, KERN_ERR,
+- "COMRESET failed (errno=%d)\n", rc);
+- goto out;
+- }
+-
+- /* clear SError bits including .X which blocks the port when set */
+- rc = sata_scr_write(link, SCR_ERROR, 0xffffffff);
+- if (rc) {
+- ata_link_printk(link, KERN_ERR, "failed to clear SError "
+- "during hardreset (errno=%d)\n", rc);
+- goto out;
+- }
+-
+- /* if device is present, follow up with srst to wait for !BSY */
+- if (ata_link_online(link))
+- rc = -EAGAIN;
+- out:
+- /* if SCR isn't accessible, we need to reset the PMP */
+- if (rc && rc != -EAGAIN && sata_scr_read(link, SCR_STATUS, &tmp))
+- rc = -ERESTART;
+-
+- DPRINTK("EXIT, rc=%d\n", rc);
+- return rc;
+-}
+-
+-/**
+- * ata_std_postreset - standard postreset method for PMP link
+- * @link: the target ata_link
+- * @classes: classes of attached devices
+- *
+- * This function is invoked after a successful reset. Note that
+- * the device might have been reset more than once using
+- * different reset methods before postreset is invoked.
+- *
+- * LOCKING:
+- * Kernel thread context (may sleep)
+- */
+-void sata_pmp_std_postreset(struct ata_link *link, unsigned int *class)
+-{
+- u32 serror;
+-
+- DPRINTK("ENTER\n");
+-
+- /* clear SError */
+- if (sata_scr_read(link, SCR_ERROR, &serror) == 0)
+- sata_scr_write(link, SCR_ERROR, serror);
+-
+- /* print link status */
+- sata_print_link_status(link);
+-
+- DPRINTK("EXIT\n");
+-}
+-
+-/**
+ * sata_pmp_read_gscr - read GSCR block of SATA PMP
+ * @dev: PMP device
+ * @gscr: buffer to read GSCR block into
+@@ -444,9 +318,8 @@ static int sata_pmp_init_links(struct ata_port *ap, int nr_ports)
+ struct ata_eh_context *ehc = &link->eh_context;
+
+ link->flags = 0;
+- ehc->i.probe_mask |= 1;
+- ehc->i.action |= ATA_EH_SOFTRESET;
+- ehc->i.flags |= ATA_EHI_RESUME_LINK;
++ ehc->i.probe_mask |= ATA_ALL_DEVICES;
++ ehc->i.action |= ATA_EH_RESET;
+ }
+
+ return 0;
+@@ -462,9 +335,6 @@ static void sata_pmp_quirks(struct ata_port *ap)
+ if (vendor == 0x1095 && devid == 0x3726) {
+ /* sil3726 quirks */
+ ata_port_for_each_link(link, ap) {
+- /* SError.N need a kick in the ass to get working */
+- link->flags |= ATA_LFLAG_HRST_TO_RESUME;
+-
+ /* class code report is unreliable */
+ if (link->pmp < 5)
+ link->flags |= ATA_LFLAG_ASSUME_ATA;
+@@ -477,9 +347,6 @@ static void sata_pmp_quirks(struct ata_port *ap)
+ } else if (vendor == 0x1095 && devid == 0x4723) {
+ /* sil4723 quirks */
+ ata_port_for_each_link(link, ap) {
+- /* SError.N need a kick in the ass to get working */
+- link->flags |= ATA_LFLAG_HRST_TO_RESUME;
+-
+ /* class code report is unreliable */
+ if (link->pmp < 2)
+ link->flags |= ATA_LFLAG_ASSUME_ATA;
+@@ -492,9 +359,6 @@ static void sata_pmp_quirks(struct ata_port *ap)
+ } else if (vendor == 0x1095 && devid == 0x4726) {
+ /* sil4726 quirks */
+ ata_port_for_each_link(link, ap) {
+- /* SError.N need a kick in the ass to get working */
+- link->flags |= ATA_LFLAG_HRST_TO_RESUME;
+-
+ /* Class code report is unreliable and SRST
+ * times out under certain configurations.
+ * Config device can be at port 0 or 5 and
+@@ -522,13 +386,6 @@ static void sata_pmp_quirks(struct ata_port *ap)
+ * otherwise. Don't try hard to recover it.
+ */
+ ap->pmp_link[ap->nr_pmp_links - 1].flags |= ATA_LFLAG_NO_RETRY;
+- } else if (vendor == 0x11ab && devid == 0x4140) {
+- /* Marvell 88SM4140 quirks. Fan-out ports require PHY
+- * reset to work; other than that, it behaves very
+- * nicely.
+- */
+- ata_port_for_each_link(link, ap)
+- link->flags |= ATA_LFLAG_HRST_TO_RESUME;
+ }
+ }
+
+@@ -554,7 +411,7 @@ int sata_pmp_attach(struct ata_device *dev)
+ int rc;
+
+ /* is it hanging off the right place? */
+- if (!(ap->flags & ATA_FLAG_PMP)) {
++ if (!sata_pmp_supported(ap)) {
+ ata_dev_printk(dev, KERN_ERR,
+ "host does not support Port Multiplier\n");
+ return -EINVAL;
+@@ -840,13 +697,12 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
+ retry:
+ ehc->classes[0] = ATA_DEV_UNKNOWN;
+
+- if (ehc->i.action & ATA_EH_RESET_MASK) {
++ if (ehc->i.action & ATA_EH_RESET) {
+ struct ata_link *tlink;
+
+ ata_eh_freeze_port(ap);
+
+ /* reset */
+- ehc->i.action = ATA_EH_HARDRESET;
+ rc = ata_eh_reset(link, 0, prereset, softreset, hardreset,
+ postreset);
+ if (rc) {
+@@ -858,8 +714,12 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
+ ata_eh_thaw_port(ap);
+
+ /* PMP is reset, SErrors cannot be trusted, scan all */
+- ata_port_for_each_link(tlink, ap)
+- ata_ehi_schedule_probe(&tlink->eh_context.i);
++ ata_port_for_each_link(tlink, ap) {
++ struct ata_eh_context *ehc = &tlink->eh_context;
++
++ ehc->i.probe_mask |= ATA_ALL_DEVICES;
++ ehc->i.action |= ATA_EH_RESET;
++ }
+ }
+
+ /* If revalidation is requested, revalidate and reconfigure;
+@@ -874,7 +734,7 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
+ tries--;
+
+ if (rc == -ENODEV) {
+- ehc->i.probe_mask |= 1;
++ ehc->i.probe_mask |= ATA_ALL_DEVICES;
+ detach = 1;
+ /* give it just two more chances */
+ tries = min(tries, 2);
+@@ -890,11 +750,11 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
+ reval_failed = 1;
+
+ ata_dev_printk(dev, KERN_WARNING,
+- "retrying hardreset%s\n",
++ "retrying reset%s\n",
+ sleep ? " in 5 secs" : "");
+ if (sleep)
+ ssleep(5);
+- ehc->i.action |= ATA_EH_HARDRESET;
++ ehc->i.action |= ATA_EH_RESET;
+ goto retry;
+ } else {
+ ata_dev_printk(dev, KERN_ERR, "failed to recover PMP "
+@@ -938,10 +798,8 @@ static int sata_pmp_eh_handle_disabled_links(struct ata_port *ap)
+ /* Some PMPs require hardreset sequence to get
+ * SError.N working.
+ */
+- if ((link->flags & ATA_LFLAG_HRST_TO_RESUME) &&
+- (link->eh_context.i.flags & ATA_EHI_RESUME_LINK))
+- sata_link_hardreset(link, sata_deb_timing_normal,
+- jiffies + ATA_TMOUT_INTERNAL_QUICK);
++ sata_link_hardreset(link, sata_deb_timing_normal,
++ jiffies + ATA_TMOUT_INTERNAL_QUICK, NULL, NULL);
+
+ /* unconditionally clear SError.N */
+ rc = sata_scr_write(link, SCR_ERROR, SERR_PHYRDY_CHG);
+@@ -987,14 +845,6 @@ static int sata_pmp_handle_link_fail(struct ata_link *link, int *link_tries)
+ /**
+ * sata_pmp_eh_recover - recover PMP-enabled port
+ * @ap: ATA port to recover
+- * @prereset: prereset method (can be NULL)
+- * @softreset: softreset method
+- * @hardreset: hardreset method
+- * @postreset: postreset method (can be NULL)
+- * @pmp_prereset: PMP prereset method (can be NULL)
+- * @pmp_softreset: PMP softreset method (can be NULL)
+- * @pmp_hardreset: PMP hardreset method (can be NULL)
+- * @pmp_postreset: PMP postreset method (can be NULL)
+ *
+ * Drive EH recovery operation for PMP enabled port @ap. This
+ * function recovers host and PMP ports with proper retrials and
+@@ -1007,12 +857,9 @@ static int sata_pmp_handle_link_fail(struct ata_link *link, int *link_tries)
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+-static int sata_pmp_eh_recover(struct ata_port *ap,
+- ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
+- ata_reset_fn_t hardreset, ata_postreset_fn_t postreset,
+- ata_prereset_fn_t pmp_prereset, ata_reset_fn_t pmp_softreset,
+- ata_reset_fn_t pmp_hardreset, ata_postreset_fn_t pmp_postreset)
++static int sata_pmp_eh_recover(struct ata_port *ap)
+ {
++ struct ata_port_operations *ops = ap->ops;
+ int pmp_tries, link_tries[SATA_PMP_MAX_PORTS];
+ struct ata_link *pmp_link = &ap->link;
+ struct ata_device *pmp_dev = pmp_link->device;
+@@ -1029,9 +876,9 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
+
+ retry:
+ /* PMP attached? */
+- if (!ap->nr_pmp_links) {
+- rc = ata_eh_recover(ap, prereset, softreset, hardreset,
+- postreset, NULL);
++ if (!sata_pmp_attached(ap)) {
++ rc = ata_eh_recover(ap, ops->prereset, ops->softreset,
++ ops->hardreset, ops->postreset, NULL);
+ if (rc) {
+ ata_link_for_each_dev(dev, &ap->link)
+ ata_dev_disable(dev);
+@@ -1049,8 +896,8 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
+ }
+
+ /* recover pmp */
+- rc = sata_pmp_eh_recover_pmp(ap, prereset, softreset, hardreset,
+- postreset);
++ rc = sata_pmp_eh_recover_pmp(ap, ops->prereset, ops->softreset,
++ ops->hardreset, ops->postreset);
+ if (rc)
+ goto pmp_fail;
+
+@@ -1060,8 +907,8 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
+ goto pmp_fail;
+
+ /* recover links */
+- rc = ata_eh_recover(ap, pmp_prereset, pmp_softreset, pmp_hardreset,
+- pmp_postreset, &link);
++ rc = ata_eh_recover(ap, ops->pmp_prereset, ops->pmp_softreset,
++ ops->pmp_hardreset, ops->pmp_postreset, &link);
+ if (rc)
+ goto link_fail;
+
+@@ -1124,7 +971,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
+
+ link_fail:
+ if (sata_pmp_handle_link_fail(link, link_tries)) {
+- pmp_ehc->i.action |= ATA_EH_HARDRESET;
++ pmp_ehc->i.action |= ATA_EH_RESET;
+ goto retry;
+ }
+
+@@ -1136,13 +983,13 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
+ if (ap->pflags & ATA_PFLAG_UNLOADING)
+ return rc;
+
+- if (!ap->nr_pmp_links)
++ if (!sata_pmp_attached(ap))
+ goto retry;
+
+ if (--pmp_tries) {
+ ata_port_printk(ap, KERN_WARNING,
+ "failed to recover PMP, retrying in 5 secs\n");
+- pmp_ehc->i.action |= ATA_EH_HARDRESET;
++ pmp_ehc->i.action |= ATA_EH_RESET;
+ ssleep(5);
+ goto retry;
+ }
+@@ -1157,16 +1004,8 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
+ }
+
+ /**
+- * sata_pmp_do_eh - do standard error handling for PMP-enabled host
++ * sata_pmp_error_handler - do standard error handling for PMP-enabled host
+ * @ap: host port to handle error for
+- * @prereset: prereset method (can be NULL)
+- * @softreset: softreset method
+- * @hardreset: hardreset method
+- * @postreset: postreset method (can be NULL)
+- * @pmp_prereset: PMP prereset method (can be NULL)
+- * @pmp_softreset: PMP softreset method (can be NULL)
+- * @pmp_hardreset: PMP hardreset method (can be NULL)
+- * @pmp_postreset: PMP postreset method (can be NULL)
+ *
+ * Perform standard error handling sequence for PMP-enabled host
+ * @ap.
+@@ -1174,16 +1013,14 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
+ * LOCKING:
+ * Kernel thread context (may sleep).
+ */
+-void sata_pmp_do_eh(struct ata_port *ap,
+- ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
+- ata_reset_fn_t hardreset, ata_postreset_fn_t postreset,
+- ata_prereset_fn_t pmp_prereset, ata_reset_fn_t pmp_softreset,
+- ata_reset_fn_t pmp_hardreset, ata_postreset_fn_t pmp_postreset)
++void sata_pmp_error_handler(struct ata_port *ap)
+ {
+ ata_eh_autopsy(ap);
+ ata_eh_report(ap);
+- sata_pmp_eh_recover(ap, prereset, softreset, hardreset, postreset,
+- pmp_prereset, pmp_softreset, pmp_hardreset,
+- pmp_postreset);
++ sata_pmp_eh_recover(ap);
+ ata_eh_finish(ap);
+ }
++
++EXPORT_SYMBOL_GPL(sata_pmp_port_ops);
++EXPORT_SYMBOL_GPL(sata_pmp_qc_defer_cmd_switch);
++EXPORT_SYMBOL_GPL(sata_pmp_error_handler);
+diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
+index 1579539..a34f324 100644
+--- a/drivers/ata/libata-scsi.c
++++ b/drivers/ata/libata-scsi.c
+@@ -131,10 +131,11 @@ static const char *ata_scsi_lpm_get(enum link_pm policy)
+ return NULL;
+ }
+
+-static ssize_t ata_scsi_lpm_put(struct class_device *class_dev,
+- const char *buf, size_t count)
++static ssize_t ata_scsi_lpm_put(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+- struct Scsi_Host *shost = class_to_shost(class_dev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct ata_port *ap = ata_shost_to_port(shost);
+ enum link_pm policy = 0;
+ int i;
+@@ -162,9 +163,9 @@ static ssize_t ata_scsi_lpm_put(struct class_device *class_dev,
+ }
+
+ static ssize_t
+-ata_scsi_lpm_show(struct class_device *class_dev, char *buf)
++ata_scsi_lpm_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(class_dev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct ata_port *ap = ata_shost_to_port(shost);
+ const char *policy =
+ ata_scsi_lpm_get(ap->pm_policy);
+@@ -174,9 +175,9 @@ ata_scsi_lpm_show(struct class_device *class_dev, char *buf)
+
+ return snprintf(buf, 23, "%s\n", policy);
+ }
+-CLASS_DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR,
++DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR,
+ ata_scsi_lpm_show, ata_scsi_lpm_put);
+-EXPORT_SYMBOL_GPL(class_device_attr_link_power_management_policy);
++EXPORT_SYMBOL_GPL(dev_attr_link_power_management_policy);
+
+ static void ata_scsi_invalid_field(struct scsi_cmnd *cmd,
+ void (*done)(struct scsi_cmnd *))
+@@ -2332,11 +2333,7 @@ void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
+ {
+ cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+
+- cmd->sense_buffer[0] = 0x70; /* fixed format, current */
+- cmd->sense_buffer[2] = sk;
+- cmd->sense_buffer[7] = 18 - 8; /* additional sense length */
+- cmd->sense_buffer[12] = asc;
+- cmd->sense_buffer[13] = ascq;
++ scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq);
+ }
+
+ /**
+@@ -2393,7 +2390,10 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
+ /* FIXME: is this needed? */
+ memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
+
+- ap->ops->tf_read(ap, &qc->tf);
++#ifdef CONFIG_ATA_SFF
++ if (ap->ops->sff_tf_read)
++ ap->ops->sff_tf_read(ap, &qc->tf);
++#endif
+
+ /* fill these in, for the case where they are -not- overwritten */
+ cmd->sense_buffer[0] = 0x70;
+@@ -2615,7 +2615,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
+
+ static struct ata_device *ata_find_dev(struct ata_port *ap, int devno)
+ {
+- if (ap->nr_pmp_links == 0) {
++ if (!sata_pmp_attached(ap)) {
+ if (likely(devno < ata_link_max_devices(&ap->link)))
+ return &ap->link.device[devno];
+ } else {
+@@ -2632,7 +2632,7 @@ static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap,
+ int devno;
+
+ /* skip commands not addressed to targets we simulate */
+- if (ap->nr_pmp_links == 0) {
++ if (!sata_pmp_attached(ap)) {
+ if (unlikely(scsidev->channel || scsidev->lun))
+ return NULL;
+ devno = scsidev->id;
+@@ -3490,7 +3490,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
+ if (lun != SCAN_WILD_CARD && lun)
+ return -EINVAL;
+
+- if (ap->nr_pmp_links == 0) {
++ if (!sata_pmp_attached(ap)) {
+ if (channel != SCAN_WILD_CARD && channel)
+ return -EINVAL;
+ devno = id;
+@@ -3507,8 +3507,8 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
+
+ ata_port_for_each_link(link, ap) {
+ struct ata_eh_info *ehi = &link->eh_info;
+- ehi->probe_mask |= (1 << ata_link_max_devices(link)) - 1;
+- ehi->action |= ATA_EH_SOFTRESET;
++ ehi->probe_mask |= ATA_ALL_DEVICES;
++ ehi->action |= ATA_EH_RESET;
+ }
+ } else {
+ struct ata_device *dev = ata_find_dev(ap, devno);
+@@ -3516,8 +3516,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
+ if (dev) {
+ struct ata_eh_info *ehi = &dev->link->eh_info;
+ ehi->probe_mask |= 1 << dev->devno;
+- ehi->action |= ATA_EH_SOFTRESET;
+- ehi->flags |= ATA_EHI_RESUME_LINK;
++ ehi->action |= ATA_EH_RESET;
+ } else
+ rc = -EINVAL;
+ }
+diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
+index 20dc572..2ec65a8 100644
+--- a/drivers/ata/libata-sff.c
++++ b/drivers/ata/libata-sff.c
+@@ -35,11 +35,377 @@
+ #include <linux/kernel.h>
+ #include <linux/pci.h>
+ #include <linux/libata.h>
++#include <linux/highmem.h>
+
+ #include "libata.h"
+
++const struct ata_port_operations ata_sff_port_ops = {
++ .inherits = &ata_base_port_ops,
++
++ .qc_prep = ata_sff_qc_prep,
++ .qc_issue = ata_sff_qc_issue,
++ .qc_fill_rtf = ata_sff_qc_fill_rtf,
++
++ .freeze = ata_sff_freeze,
++ .thaw = ata_sff_thaw,
++ .prereset = ata_sff_prereset,
++ .softreset = ata_sff_softreset,
++ .hardreset = sata_sff_hardreset,
++ .postreset = ata_sff_postreset,
++ .error_handler = ata_sff_error_handler,
++ .post_internal_cmd = ata_sff_post_internal_cmd,
++
++ .sff_dev_select = ata_sff_dev_select,
++ .sff_check_status = ata_sff_check_status,
++ .sff_tf_load = ata_sff_tf_load,
++ .sff_tf_read = ata_sff_tf_read,
++ .sff_exec_command = ata_sff_exec_command,
++ .sff_data_xfer = ata_sff_data_xfer,
++ .sff_irq_on = ata_sff_irq_on,
++ .sff_irq_clear = ata_sff_irq_clear,
++
++ .port_start = ata_sff_port_start,
++};
++
++const struct ata_port_operations ata_bmdma_port_ops = {
++ .inherits = &ata_sff_port_ops,
++
++ .mode_filter = ata_bmdma_mode_filter,
++
++ .bmdma_setup = ata_bmdma_setup,
++ .bmdma_start = ata_bmdma_start,
++ .bmdma_stop = ata_bmdma_stop,
++ .bmdma_status = ata_bmdma_status,
++};
++
++/**
++ * ata_fill_sg - Fill PCI IDE PRD table
++ * @qc: Metadata associated with taskfile to be transferred
++ *
++ * Fill PCI IDE PRD (scatter-gather) table with segments
++ * associated with the current disk command.
++ *
++ * LOCKING:
++ * spin_lock_irqsave(host lock)
++ *
++ */
++static void ata_fill_sg(struct ata_queued_cmd *qc)
++{
++ struct ata_port *ap = qc->ap;
++ struct scatterlist *sg;
++ unsigned int si, pi;
++
++ pi = 0;
++ for_each_sg(qc->sg, sg, qc->n_elem, si) {
++ u32 addr, offset;
++ u32 sg_len, len;
++
++ /* determine if physical DMA addr spans 64K boundary.
++ * Note h/w doesn't support 64-bit, so we unconditionally
++ * truncate dma_addr_t to u32.
++ */
++ addr = (u32) sg_dma_address(sg);
++ sg_len = sg_dma_len(sg);
++
++ while (sg_len) {
++ offset = addr & 0xffff;
++ len = sg_len;
++ if ((offset + sg_len) > 0x10000)
++ len = 0x10000 - offset;
++
++ ap->prd[pi].addr = cpu_to_le32(addr);
++ ap->prd[pi].flags_len = cpu_to_le32(len & 0xffff);
++ VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len);
++
++ pi++;
++ sg_len -= len;
++ addr += len;
++ }
++ }
++
++ ap->prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
++}
++
++/**
++ * ata_fill_sg_dumb - Fill PCI IDE PRD table
++ * @qc: Metadata associated with taskfile to be transferred
++ *
++ * Fill PCI IDE PRD (scatter-gather) table with segments
++ * associated with the current disk command. Perform the fill
++ * so that we avoid writing any length 64K records for
++ * controllers that don't follow the spec.
++ *
++ * LOCKING:
++ * spin_lock_irqsave(host lock)
++ *
++ */
++static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)
++{
++ struct ata_port *ap = qc->ap;
++ struct scatterlist *sg;
++ unsigned int si, pi;
++
++ pi = 0;
++ for_each_sg(qc->sg, sg, qc->n_elem, si) {
++ u32 addr, offset;
++ u32 sg_len, len, blen;
++
++ /* determine if physical DMA addr spans 64K boundary.
++ * Note h/w doesn't support 64-bit, so we unconditionally
++ * truncate dma_addr_t to u32.
++ */
++ addr = (u32) sg_dma_address(sg);
++ sg_len = sg_dma_len(sg);
++
++ while (sg_len) {
++ offset = addr & 0xffff;
++ len = sg_len;
++ if ((offset + sg_len) > 0x10000)
++ len = 0x10000 - offset;
++
++ blen = len & 0xffff;
++ ap->prd[pi].addr = cpu_to_le32(addr);
++ if (blen == 0) {
++ /* Some PATA chipsets like the CS5530 can't
++ cope with 0x0000 meaning 64K as the spec says */
++ ap->prd[pi].flags_len = cpu_to_le32(0x8000);
++ blen = 0x8000;
++ ap->prd[++pi].addr = cpu_to_le32(addr + 0x8000);
++ }
++ ap->prd[pi].flags_len = cpu_to_le32(blen);
++ VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len);
++
++ pi++;
++ sg_len -= len;
++ addr += len;
++ }
++ }
++
++ ap->prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
++}
++
++/**
++ * ata_sff_qc_prep - Prepare taskfile for submission
++ * @qc: Metadata associated with taskfile to be prepared
++ *
++ * Prepare ATA taskfile for submission.
++ *
++ * LOCKING:
++ * spin_lock_irqsave(host lock)
++ */
++void ata_sff_qc_prep(struct ata_queued_cmd *qc)
++{
++ if (!(qc->flags & ATA_QCFLAG_DMAMAP))
++ return;
++
++ ata_fill_sg(qc);
++}
++
++/**
++ * ata_sff_dumb_qc_prep - Prepare taskfile for submission
++ * @qc: Metadata associated with taskfile to be prepared
++ *
++ * Prepare ATA taskfile for submission.
++ *
++ * LOCKING:
++ * spin_lock_irqsave(host lock)
++ */
++void ata_sff_dumb_qc_prep(struct ata_queued_cmd *qc)
++{
++ if (!(qc->flags & ATA_QCFLAG_DMAMAP))
++ return;
++
++ ata_fill_sg_dumb(qc);
++}
++
++/**
++ * ata_sff_check_status - Read device status reg & clear interrupt
++ * @ap: port where the device is
++ *
++ * Reads ATA taskfile status register for currently-selected device
++ * and return its value. This also clears pending interrupts
++ * from this device
++ *
++ * LOCKING:
++ * Inherited from caller.
++ */
++u8 ata_sff_check_status(struct ata_port *ap)
++{
++ return ioread8(ap->ioaddr.status_addr);
++}
++
++/**
++ * ata_sff_altstatus - Read device alternate status reg
++ * @ap: port where the device is
++ *
++ * Reads ATA taskfile alternate status register for
++ * currently-selected device and return its value.
++ *
++ * Note: may NOT be used as the check_altstatus() entry in
++ * ata_port_operations.
++ *
++ * LOCKING:
++ * Inherited from caller.
++ */
++u8 ata_sff_altstatus(struct ata_port *ap)
++{
++ if (ap->ops->sff_check_altstatus)
++ return ap->ops->sff_check_altstatus(ap);
++
++ return ioread8(ap->ioaddr.altstatus_addr);
++}
++
++/**
++ * ata_sff_busy_sleep - sleep until BSY clears, or timeout
++ * @ap: port containing status register to be polled
++ * @tmout_pat: impatience timeout
++ * @tmout: overall timeout
++ *
++ * Sleep until ATA Status register bit BSY clears,
++ * or a timeout occurs.
++ *
++ * LOCKING:
++ * Kernel thread context (may sleep).
++ *
++ * RETURNS:
++ * 0 on success, -errno otherwise.
++ */
++int ata_sff_busy_sleep(struct ata_port *ap,
++ unsigned long tmout_pat, unsigned long tmout)
++{
++ unsigned long timer_start, timeout;
++ u8 status;
++
++ status = ata_sff_busy_wait(ap, ATA_BUSY, 300);
++ timer_start = jiffies;
++ timeout = timer_start + tmout_pat;
++ while (status != 0xff && (status & ATA_BUSY) &&
++ time_before(jiffies, timeout)) {
++ msleep(50);
++ status = ata_sff_busy_wait(ap, ATA_BUSY, 3);
++ }
++
++ if (status != 0xff && (status & ATA_BUSY))
++ ata_port_printk(ap, KERN_WARNING,
++ "port is slow to respond, please be patient "
++ "(Status 0x%x)\n", status);
++
++ timeout = timer_start + tmout;
++ while (status != 0xff && (status & ATA_BUSY) &&
++ time_before(jiffies, timeout)) {
++ msleep(50);
++ status = ap->ops->sff_check_status(ap);
++ }
++
++ if (status == 0xff)
++ return -ENODEV;
++
++ if (status & ATA_BUSY) {
++ ata_port_printk(ap, KERN_ERR, "port failed to respond "
++ "(%lu secs, Status 0x%x)\n",
++ tmout / HZ, status);
++ return -EBUSY;
++ }
++
++ return 0;
++}
++
++static int ata_sff_check_ready(struct ata_link *link)
++{
++ u8 status = link->ap->ops->sff_check_status(link->ap);
++
++ if (!(status & ATA_BUSY))
++ return 1;
++ if (status == 0xff)
++ return -ENODEV;
++ return 0;
++}
++
++/**
++ * ata_sff_wait_ready - sleep until BSY clears, or timeout
++ * @link: SFF link to wait ready status for
++ * @deadline: deadline jiffies for the operation
++ *
++ * Sleep until ATA Status register bit BSY clears, or timeout
++ * occurs.
++ *
++ * LOCKING:
++ * Kernel thread context (may sleep).
++ *
++ * RETURNS:
++ * 0 on success, -errno otherwise.
++ */
++int ata_sff_wait_ready(struct ata_link *link, unsigned long deadline)
++{
++ return ata_wait_ready(link, deadline, ata_sff_check_ready);
++}
++
++/**
++ * ata_sff_dev_select - Select device 0/1 on ATA bus
++ * @ap: ATA channel to manipulate
++ * @device: ATA device (numbered from zero) to select
++ *
++ * Use the method defined in the ATA specification to
++ * make either device 0, or device 1, active on the
++ * ATA channel. Works with both PIO and MMIO.
++ *
++ * May be used as the dev_select() entry in ata_port_operations.
++ *
++ * LOCKING:
++ * caller.
++ */
++void ata_sff_dev_select(struct ata_port *ap, unsigned int device)
++{
++ u8 tmp;
++
++ if (device == 0)
++ tmp = ATA_DEVICE_OBS;
++ else
++ tmp = ATA_DEVICE_OBS | ATA_DEV1;
++
++ iowrite8(tmp, ap->ioaddr.device_addr);
++ ata_sff_pause(ap); /* needed; also flushes, for mmio */
++}
++
++/**
++ * ata_dev_select - Select device 0/1 on ATA bus
++ * @ap: ATA channel to manipulate
++ * @device: ATA device (numbered from zero) to select
++ * @wait: non-zero to wait for Status register BSY bit to clear
++ * @can_sleep: non-zero if context allows sleeping
++ *
++ * Use the method defined in the ATA specification to
++ * make either device 0, or device 1, active on the
++ * ATA channel.
++ *
++ * This is a high-level version of ata_sff_dev_select(), which
++ * additionally provides the services of inserting the proper
++ * pauses and status polling, where needed.
++ *
++ * LOCKING:
++ * caller.
++ */
++void ata_dev_select(struct ata_port *ap, unsigned int device,
++ unsigned int wait, unsigned int can_sleep)
++{
++ if (ata_msg_probe(ap))
++ ata_port_printk(ap, KERN_INFO, "ata_dev_select: ENTER, "
++ "device %u, wait %u\n", device, wait);
++
++ if (wait)
++ ata_wait_idle(ap);
++
++ ap->ops->sff_dev_select(ap, device);
++
++ if (wait) {
++ if (can_sleep && ap->link.device[device].class == ATA_DEV_ATAPI)
++ msleep(150);
++ ata_wait_idle(ap);
++ }
++}
++
+ /**
+- * ata_irq_on - Enable interrupts on a port.
++ * ata_sff_irq_on - Enable interrupts on a port.
+ * @ap: Port on which interrupts are enabled.
+ *
+ * Enable interrupts on a legacy IDE device using MMIO or PIO,
+@@ -48,7 +414,7 @@
+ * LOCKING:
+ * Inherited from caller.
+ */
+-u8 ata_irq_on(struct ata_port *ap)
++u8 ata_sff_irq_on(struct ata_port *ap)
+ {
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+ u8 tmp;
+@@ -60,13 +426,34 @@ u8 ata_irq_on(struct ata_port *ap)
+ iowrite8(ap->ctl, ioaddr->ctl_addr);
+ tmp = ata_wait_idle(ap);
+
+- ap->ops->irq_clear(ap);
++ ap->ops->sff_irq_clear(ap);
+
+ return tmp;
+ }
+
+ /**
+- * ata_tf_load - send taskfile registers to host controller
++ * ata_sff_irq_clear - Clear PCI IDE BMDMA interrupt.
++ * @ap: Port associated with this ATA transaction.
++ *
++ * Clear interrupt and error flags in DMA status register.
++ *
++ * May be used as the irq_clear() entry in ata_port_operations.
++ *
++ * LOCKING:
++ * spin_lock_irqsave(host lock)
++ */
++void ata_sff_irq_clear(struct ata_port *ap)
++{
++ void __iomem *mmio = ap->ioaddr.bmdma_addr;
++
++ if (!mmio)
++ return;
++
++ iowrite8(ioread8(mmio + ATA_DMA_STATUS), mmio + ATA_DMA_STATUS);
++}
++
++/**
++ * ata_sff_tf_load - send taskfile registers to host controller
+ * @ap: Port to which output is sent
+ * @tf: ATA taskfile register set
+ *
+@@ -75,8 +462,7 @@ u8 ata_irq_on(struct ata_port *ap)
+ * LOCKING:
+ * Inherited from caller.
+ */
+-
+-void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
++void ata_sff_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
+ {
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+ unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+@@ -126,26 +512,7 @@ void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
+ }
+
+ /**
+- * ata_exec_command - issue ATA command to host controller
+- * @ap: port to which command is being issued
+- * @tf: ATA taskfile register set
+- *
+- * Issues ATA command, with proper synchronization with interrupt
+- * handler / other threads.
+- *
+- * LOCKING:
+- * spin_lock_irqsave(host lock)
+- */
+-void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
+-{
+- DPRINTK("ata%u: cmd 0x%X\n", ap->print_id, tf->command);
+-
+- iowrite8(tf->command, ap->ioaddr.command_addr);
+- ata_pause(ap);
+-}
+-
+-/**
+- * ata_tf_read - input device's ATA taskfile shadow registers
++ * ata_sff_tf_read - input device's ATA taskfile shadow registers
+ * @ap: Port from which input is read
+ * @tf: ATA taskfile register set for storing input
+ *
+@@ -157,11 +524,11 @@ void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
+ * LOCKING:
+ * Inherited from caller.
+ */
+-void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
++void ata_sff_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+ {
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+
+- tf->command = ata_check_status(ap);
++ tf->command = ata_sff_check_status(ap);
+ tf->feature = ioread8(ioaddr->error_addr);
+ tf->nsect = ioread8(ioaddr->nsect_addr);
+ tf->lbal = ioread8(ioaddr->lbal_addr);
+@@ -185,165 +552,1028 @@ void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+ }
+
+ /**
+- * ata_check_status - Read device status reg & clear interrupt
+- * @ap: port where the device is
++ * ata_sff_exec_command - issue ATA command to host controller
++ * @ap: port to which command is being issued
++ * @tf: ATA taskfile register set
+ *
+- * Reads ATA taskfile status register for currently-selected device
+- * and return its value. This also clears pending interrupts
+- * from this device
++ * Issues ATA command, with proper synchronization with interrupt
++ * handler / other threads.
+ *
+ * LOCKING:
+- * Inherited from caller.
++ * spin_lock_irqsave(host lock)
+ */
+-u8 ata_check_status(struct ata_port *ap)
++void ata_sff_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
+ {
+- return ioread8(ap->ioaddr.status_addr);
++ DPRINTK("ata%u: cmd 0x%X\n", ap->print_id, tf->command);
++
++ iowrite8(tf->command, ap->ioaddr.command_addr);
++ ata_sff_pause(ap);
+ }
+
+ /**
+- * ata_altstatus - Read device alternate status reg
+- * @ap: port where the device is
++ * ata_tf_to_host - issue ATA taskfile to host controller
++ * @ap: port to which command is being issued
++ * @tf: ATA taskfile register set
+ *
+- * Reads ATA taskfile alternate status register for
+- * currently-selected device and return its value.
++ * Issues ATA taskfile register set to ATA host controller,
++ * with proper synchronization with interrupt handler and
++ * other threads.
+ *
+- * Note: may NOT be used as the check_altstatus() entry in
+- * ata_port_operations.
++ * LOCKING:
++ * spin_lock_irqsave(host lock)
++ */
++static inline void ata_tf_to_host(struct ata_port *ap,
++ const struct ata_taskfile *tf)
++{
++ ap->ops->sff_tf_load(ap, tf);
++ ap->ops->sff_exec_command(ap, tf);
++}
++
++/**
++ * ata_sff_data_xfer - Transfer data by PIO
++ * @dev: device to target
++ * @buf: data buffer
++ * @buflen: buffer length
++ * @rw: read/write
++ *
++ * Transfer data from/to the device data register by PIO.
+ *
+ * LOCKING:
+ * Inherited from caller.
++ *
++ * RETURNS:
++ * Bytes consumed.
+ */
+-u8 ata_altstatus(struct ata_port *ap)
++unsigned int ata_sff_data_xfer(struct ata_device *dev, unsigned char *buf,
++ unsigned int buflen, int rw)
+ {
+- if (ap->ops->check_altstatus)
+- return ap->ops->check_altstatus(ap);
++ struct ata_port *ap = dev->link->ap;
++ void __iomem *data_addr = ap->ioaddr.data_addr;
++ unsigned int words = buflen >> 1;
+
+- return ioread8(ap->ioaddr.altstatus_addr);
++ /* Transfer multiple of 2 bytes */
++ if (rw == READ)
++ ioread16_rep(data_addr, buf, words);
++ else
++ iowrite16_rep(data_addr, buf, words);
++
++ /* Transfer trailing 1 byte, if any. */
++ if (unlikely(buflen & 0x01)) {
++ __le16 align_buf[1] = { 0 };
++ unsigned char *trailing_buf = buf + buflen - 1;
++
++ if (rw == READ) {
++ align_buf[0] = cpu_to_le16(ioread16(data_addr));
++ memcpy(trailing_buf, align_buf, 1);
++ } else {
++ memcpy(align_buf, trailing_buf, 1);
++ iowrite16(le16_to_cpu(align_buf[0]), data_addr);
++ }
++ words++;
++ }
++
++ return words << 1;
+ }
+
+ /**
+- * ata_bmdma_setup - Set up PCI IDE BMDMA transaction
+- * @qc: Info associated with this ATA transaction.
++ * ata_sff_data_xfer_noirq - Transfer data by PIO
++ * @dev: device to target
++ * @buf: data buffer
++ * @buflen: buffer length
++ * @rw: read/write
++ *
++ * Transfer data from/to the device data register by PIO. Do the
++ * transfer with interrupts disabled.
+ *
+ * LOCKING:
+- * spin_lock_irqsave(host lock)
++ * Inherited from caller.
++ *
++ * RETURNS:
++ * Bytes consumed.
+ */
+-void ata_bmdma_setup(struct ata_queued_cmd *qc)
++unsigned int ata_sff_data_xfer_noirq(struct ata_device *dev, unsigned char *buf,
++ unsigned int buflen, int rw)
++{
++ unsigned long flags;
++ unsigned int consumed;
++
++ local_irq_save(flags);
++ consumed = ata_sff_data_xfer(dev, buf, buflen, rw);
++ local_irq_restore(flags);
++
++ return consumed;
++}
++
++/**
++ * ata_pio_sector - Transfer a sector of data.
++ * @qc: Command on going
++ *
++ * Transfer qc->sect_size bytes of data from/to the ATA device.
++ *
++ * LOCKING:
++ * Inherited from caller.
++ */
++static void ata_pio_sector(struct ata_queued_cmd *qc)
+ {
++ int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
+ struct ata_port *ap = qc->ap;
+- unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
+- u8 dmactl;
++ struct page *page;
++ unsigned int offset;
++ unsigned char *buf;
+
+- /* load PRD table addr. */
+- mb(); /* make sure PRD table writes are visible to controller */
+- iowrite32(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
++ if (qc->curbytes == qc->nbytes - qc->sect_size)
++ ap->hsm_task_state = HSM_ST_LAST;
+
+- /* specify data direction, triple-check start bit is clear */
+- dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+- dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
+- if (!rw)
+- dmactl |= ATA_DMA_WR;
+- iowrite8(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
++ page = sg_page(qc->cursg);
++ offset = qc->cursg->offset + qc->cursg_ofs;
+
+- /* issue r/w command */
+- ap->ops->exec_command(ap, &qc->tf);
++ /* get the current page and offset */
++ page = nth_page(page, (offset >> PAGE_SHIFT));
++ offset %= PAGE_SIZE;
++
++ DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
++
++ if (PageHighMem(page)) {
++ unsigned long flags;
++
++ /* FIXME: use a bounce buffer */
++ local_irq_save(flags);
++ buf = kmap_atomic(page, KM_IRQ0);
++
++ /* do the actual data transfer */
++ ap->ops->sff_data_xfer(qc->dev, buf + offset, qc->sect_size,
++ do_write);
++
++ kunmap_atomic(buf, KM_IRQ0);
++ local_irq_restore(flags);
++ } else {
++ buf = page_address(page);
++ ap->ops->sff_data_xfer(qc->dev, buf + offset, qc->sect_size,
++ do_write);
++ }
++
++ qc->curbytes += qc->sect_size;
++ qc->cursg_ofs += qc->sect_size;
++
++ if (qc->cursg_ofs == qc->cursg->length) {
++ qc->cursg = sg_next(qc->cursg);
++ qc->cursg_ofs = 0;
++ }
+ }
+
+ /**
+- * ata_bmdma_start - Start a PCI IDE BMDMA transaction
+- * @qc: Info associated with this ATA transaction.
++ * ata_pio_sectors - Transfer one or many sectors.
++ * @qc: Command on going
++ *
++ * Transfer one or many sectors of data from/to the
++ * ATA device for the DRQ request.
+ *
+ * LOCKING:
+- * spin_lock_irqsave(host lock)
++ * Inherited from caller.
+ */
+-void ata_bmdma_start(struct ata_queued_cmd *qc)
++static void ata_pio_sectors(struct ata_queued_cmd *qc)
++{
++ if (is_multi_taskfile(&qc->tf)) {
++ /* READ/WRITE MULTIPLE */
++ unsigned int nsect;
++
++ WARN_ON(qc->dev->multi_count == 0);
++
++ nsect = min((qc->nbytes - qc->curbytes) / qc->sect_size,
++ qc->dev->multi_count);
++ while (nsect--)
++ ata_pio_sector(qc);
++ } else
++ ata_pio_sector(qc);
++
++ ata_sff_altstatus(qc->ap); /* flush */
++}
++
++/**
++ * atapi_send_cdb - Write CDB bytes to hardware
++ * @ap: Port to which ATAPI device is attached.
++ * @qc: Taskfile currently active
++ *
++ * When device has indicated its readiness to accept
++ * a CDB, this function is called. Send the CDB.
++ *
++ * LOCKING:
++ * caller.
++ */
++static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)
++{
++ /* send SCSI cdb */
++ DPRINTK("send cdb\n");
++ WARN_ON(qc->dev->cdb_len < 12);
++
++ ap->ops->sff_data_xfer(qc->dev, qc->cdb, qc->dev->cdb_len, 1);
++ ata_sff_altstatus(ap); /* flush */
++
++ switch (qc->tf.protocol) {
++ case ATAPI_PROT_PIO:
++ ap->hsm_task_state = HSM_ST;
++ break;
++ case ATAPI_PROT_NODATA:
++ ap->hsm_task_state = HSM_ST_LAST;
++ break;
++ case ATAPI_PROT_DMA:
++ ap->hsm_task_state = HSM_ST_LAST;
++ /* initiate bmdma */
++ ap->ops->bmdma_start(qc);
++ break;
++ }
++}
++
++/**
++ * __atapi_pio_bytes - Transfer data from/to the ATAPI device.
++ * @qc: Command on going
++ * @bytes: number of bytes
++ *
++ * Transfer Transfer data from/to the ATAPI device.
++ *
++ * LOCKING:
++ * Inherited from caller.
++ *
++ */
++static int __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
+ {
++ int rw = (qc->tf.flags & ATA_TFLAG_WRITE) ? WRITE : READ;
+ struct ata_port *ap = qc->ap;
+- u8 dmactl;
++ struct ata_device *dev = qc->dev;
++ struct ata_eh_info *ehi = &dev->link->eh_info;
++ struct scatterlist *sg;
++ struct page *page;
++ unsigned char *buf;
++ unsigned int offset, count, consumed;
++
++next_sg:
++ sg = qc->cursg;
++ if (unlikely(!sg)) {
++ ata_ehi_push_desc(ehi, "unexpected or too much trailing data "
++ "buf=%u cur=%u bytes=%u",
++ qc->nbytes, qc->curbytes, bytes);
++ return -1;
++ }
+
+- /* start host DMA transaction */
+- dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+- iowrite8(dmactl | ATA_DMA_START, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
++ page = sg_page(sg);
++ offset = sg->offset + qc->cursg_ofs;
+
+- /* Strictly, one may wish to issue an ioread8() here, to
+- * flush the mmio write. However, control also passes
+- * to the hardware at this point, and it will interrupt
+- * us when we are to resume control. So, in effect,
+- * we don't care when the mmio write flushes.
+- * Further, a read of the DMA status register _immediately_
+- * following the write may not be what certain flaky hardware
+- * is expected, so I think it is best to not add a readb()
+- * without first all the MMIO ATA cards/mobos.
+- * Or maybe I'm just being paranoid.
+- *
+- * FIXME: The posting of this write means I/O starts are
+- * unneccessarily delayed for MMIO
++ /* get the current page and offset */
++ page = nth_page(page, (offset >> PAGE_SHIFT));
++ offset %= PAGE_SIZE;
++
++ /* don't overrun current sg */
++ count = min(sg->length - qc->cursg_ofs, bytes);
++
++ /* don't cross page boundaries */
++ count = min(count, (unsigned int)PAGE_SIZE - offset);
++
++ DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
++
++ if (PageHighMem(page)) {
++ unsigned long flags;
++
++ /* FIXME: use bounce buffer */
++ local_irq_save(flags);
++ buf = kmap_atomic(page, KM_IRQ0);
++
++ /* do the actual data transfer */
++ consumed = ap->ops->sff_data_xfer(dev, buf + offset, count, rw);
++
++ kunmap_atomic(buf, KM_IRQ0);
++ local_irq_restore(flags);
++ } else {
++ buf = page_address(page);
++ consumed = ap->ops->sff_data_xfer(dev, buf + offset, count, rw);
++ }
++
++ bytes -= min(bytes, consumed);
++ qc->curbytes += count;
++ qc->cursg_ofs += count;
++
++ if (qc->cursg_ofs == sg->length) {
++ qc->cursg = sg_next(qc->cursg);
++ qc->cursg_ofs = 0;
++ }
++
++ /* consumed can be larger than count only for the last transfer */
++ WARN_ON(qc->cursg && count != consumed);
++
++ if (bytes)
++ goto next_sg;
++ return 0;
++}
++
++/**
++ * atapi_pio_bytes - Transfer data from/to the ATAPI device.
++ * @qc: Command on going
++ *
++ * Transfer Transfer data from/to the ATAPI device.
++ *
++ * LOCKING:
++ * Inherited from caller.
++ */
++static void atapi_pio_bytes(struct ata_queued_cmd *qc)
++{
++ struct ata_port *ap = qc->ap;
++ struct ata_device *dev = qc->dev;
++ struct ata_eh_info *ehi = &dev->link->eh_info;
++ unsigned int ireason, bc_lo, bc_hi, bytes;
++ int i_write, do_write = (qc->tf.flags & ATA_TFLAG_WRITE) ? 1 : 0;
++
++ /* Abuse qc->result_tf for temp storage of intermediate TF
++ * here to save some kernel stack usage.
++ * For normal completion, qc->result_tf is not relevant. For
++ * error, qc->result_tf is later overwritten by ata_qc_complete().
++ * So, the correctness of qc->result_tf is not affected.
+ */
++ ap->ops->sff_tf_read(ap, &qc->result_tf);
++ ireason = qc->result_tf.nsect;
++ bc_lo = qc->result_tf.lbam;
++ bc_hi = qc->result_tf.lbah;
++ bytes = (bc_hi << 8) | bc_lo;
++
++ /* shall be cleared to zero, indicating xfer of data */
++ if (unlikely(ireason & (1 << 0)))
++ goto atapi_check;
++
++ /* make sure transfer direction matches expected */
++ i_write = ((ireason & (1 << 1)) == 0) ? 1 : 0;
++ if (unlikely(do_write != i_write))
++ goto atapi_check;
++
++ if (unlikely(!bytes))
++ goto atapi_check;
++
++ VPRINTK("ata%u: xfering %d bytes\n", ap->print_id, bytes);
++
++ if (unlikely(__atapi_pio_bytes(qc, bytes)))
++ goto err_out;
++ ata_sff_altstatus(ap); /* flush */
++
++ return;
++
++ atapi_check:
++ ata_ehi_push_desc(ehi, "ATAPI check failed (ireason=0x%x bytes=%u)",
++ ireason, bytes);
++ err_out:
++ qc->err_mask |= AC_ERR_HSM;
++ ap->hsm_task_state = HSM_ST_ERR;
+ }
+
+ /**
+- * ata_bmdma_irq_clear - Clear PCI IDE BMDMA interrupt.
+- * @ap: Port associated with this ATA transaction.
++ * ata_hsm_ok_in_wq - Check if the qc can be handled in the workqueue.
++ * @ap: the target ata_port
++ * @qc: qc on going
+ *
+- * Clear interrupt and error flags in DMA status register.
++ * RETURNS:
++ * 1 if ok in workqueue, 0 otherwise.
++ */
++static inline int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *qc)
++{
++ if (qc->tf.flags & ATA_TFLAG_POLLING)
++ return 1;
++
++ if (ap->hsm_task_state == HSM_ST_FIRST) {
++ if (qc->tf.protocol == ATA_PROT_PIO &&
++ (qc->tf.flags & ATA_TFLAG_WRITE))
++ return 1;
++
++ if (ata_is_atapi(qc->tf.protocol) &&
++ !(qc->dev->flags & ATA_DFLAG_CDB_INTR))
++ return 1;
++ }
++
++ return 0;
++}
++
++/**
++ * ata_hsm_qc_complete - finish a qc running on standard HSM
++ * @qc: Command to complete
++ * @in_wq: 1 if called from workqueue, 0 otherwise
+ *
+- * May be used as the irq_clear() entry in ata_port_operations.
++ * Finish @qc which is running on standard HSM.
+ *
+ * LOCKING:
+- * spin_lock_irqsave(host lock)
++ * If @in_wq is zero, spin_lock_irqsave(host lock).
++ * Otherwise, none on entry and grabs host lock.
+ */
+-void ata_bmdma_irq_clear(struct ata_port *ap)
++static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
+ {
+- void __iomem *mmio = ap->ioaddr.bmdma_addr;
++ struct ata_port *ap = qc->ap;
++ unsigned long flags;
+
+- if (!mmio)
+- return;
++ if (ap->ops->error_handler) {
++ if (in_wq) {
++ spin_lock_irqsave(ap->lock, flags);
++
++ /* EH might have kicked in while host lock is
++ * released.
++ */
++ qc = ata_qc_from_tag(ap, qc->tag);
++ if (qc) {
++ if (likely(!(qc->err_mask & AC_ERR_HSM))) {
++ ap->ops->sff_irq_on(ap);
++ ata_qc_complete(qc);
++ } else
++ ata_port_freeze(ap);
++ }
++
++ spin_unlock_irqrestore(ap->lock, flags);
++ } else {
++ if (likely(!(qc->err_mask & AC_ERR_HSM)))
++ ata_qc_complete(qc);
++ else
++ ata_port_freeze(ap);
++ }
++ } else {
++ if (in_wq) {
++ spin_lock_irqsave(ap->lock, flags);
++ ap->ops->sff_irq_on(ap);
++ ata_qc_complete(qc);
++ spin_unlock_irqrestore(ap->lock, flags);
++ } else
++ ata_qc_complete(qc);
++ }
++}
+
+- iowrite8(ioread8(mmio + ATA_DMA_STATUS), mmio + ATA_DMA_STATUS);
++/**
++ * ata_sff_hsm_move - move the HSM to the next state.
++ * @ap: the target ata_port
++ * @qc: qc on going
++ * @status: current device status
++ * @in_wq: 1 if called from workqueue, 0 otherwise
++ *
++ * RETURNS:
++ * 1 when poll next status needed, 0 otherwise.
++ */
++int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
++ u8 status, int in_wq)
++{
++ unsigned long flags = 0;
++ int poll_next;
++
++ WARN_ON((qc->flags & ATA_QCFLAG_ACTIVE) == 0);
++
++ /* Make sure ata_sff_qc_issue() does not throw things
++ * like DMA polling into the workqueue. Notice that
++ * in_wq is not equivalent to (qc->tf.flags & ATA_TFLAG_POLLING).
++ */
++ WARN_ON(in_wq != ata_hsm_ok_in_wq(ap, qc));
++
++fsm_start:
++ DPRINTK("ata%u: protocol %d task_state %d (dev_stat 0x%X)\n",
++ ap->print_id, qc->tf.protocol, ap->hsm_task_state, status);
++
++ switch (ap->hsm_task_state) {
++ case HSM_ST_FIRST:
++ /* Send first data block or PACKET CDB */
++
++ /* If polling, we will stay in the work queue after
++ * sending the data. Otherwise, interrupt handler
++ * takes over after sending the data.
++ */
++ poll_next = (qc->tf.flags & ATA_TFLAG_POLLING);
++
++ /* check device status */
++ if (unlikely((status & ATA_DRQ) == 0)) {
++ /* handle BSY=0, DRQ=0 as error */
++ if (likely(status & (ATA_ERR | ATA_DF)))
++ /* device stops HSM for abort/error */
++ qc->err_mask |= AC_ERR_DEV;
++ else
++ /* HSM violation. Let EH handle this */
++ qc->err_mask |= AC_ERR_HSM;
++
++ ap->hsm_task_state = HSM_ST_ERR;
++ goto fsm_start;
++ }
++
++ /* Device should not ask for data transfer (DRQ=1)
++ * when it finds something wrong.
++ * We ignore DRQ here and stop the HSM by
++ * changing hsm_task_state to HSM_ST_ERR and
++ * let the EH abort the command or reset the device.
++ */
++ if (unlikely(status & (ATA_ERR | ATA_DF))) {
++ /* Some ATAPI tape drives forget to clear the ERR bit
++ * when doing the next command (mostly request sense).
++ * We ignore ERR here to workaround and proceed sending
++ * the CDB.
++ */
++ if (!(qc->dev->horkage & ATA_HORKAGE_STUCK_ERR)) {
++ ata_port_printk(ap, KERN_WARNING,
++ "DRQ=1 with device error, "
++ "dev_stat 0x%X\n", status);
++ qc->err_mask |= AC_ERR_HSM;
++ ap->hsm_task_state = HSM_ST_ERR;
++ goto fsm_start;
++ }
++ }
++
++ /* Send the CDB (atapi) or the first data block (ata pio out).
++ * During the state transition, interrupt handler shouldn't
++ * be invoked before the data transfer is complete and
++ * hsm_task_state is changed. Hence, the following locking.
++ */
++ if (in_wq)
++ spin_lock_irqsave(ap->lock, flags);
++
++ if (qc->tf.protocol == ATA_PROT_PIO) {
++ /* PIO data out protocol.
++ * send first data block.
++ */
++
++ /* ata_pio_sectors() might change the state
++ * to HSM_ST_LAST. so, the state is changed here
++ * before ata_pio_sectors().
++ */
++ ap->hsm_task_state = HSM_ST;
++ ata_pio_sectors(qc);
++ } else
++ /* send CDB */
++ atapi_send_cdb(ap, qc);
++
++ if (in_wq)
++ spin_unlock_irqrestore(ap->lock, flags);
++
++ /* if polling, ata_pio_task() handles the rest.
++ * otherwise, interrupt handler takes over from here.
++ */
++ break;
++
++ case HSM_ST:
++ /* complete command or read/write the data register */
++ if (qc->tf.protocol == ATAPI_PROT_PIO) {
++ /* ATAPI PIO protocol */
++ if ((status & ATA_DRQ) == 0) {
++ /* No more data to transfer or device error.
++ * Device error will be tagged in HSM_ST_LAST.
++ */
++ ap->hsm_task_state = HSM_ST_LAST;
++ goto fsm_start;
++ }
++
++ /* Device should not ask for data transfer (DRQ=1)
++ * when it finds something wrong.
++ * We ignore DRQ here and stop the HSM by
++ * changing hsm_task_state to HSM_ST_ERR and
++ * let the EH abort the command or reset the device.
++ */
++ if (unlikely(status & (ATA_ERR | ATA_DF))) {
++ ata_port_printk(ap, KERN_WARNING, "DRQ=1 with "
++ "device error, dev_stat 0x%X\n",
++ status);
++ qc->err_mask |= AC_ERR_HSM;
++ ap->hsm_task_state = HSM_ST_ERR;
++ goto fsm_start;
++ }
++
++ atapi_pio_bytes(qc);
++
++ if (unlikely(ap->hsm_task_state == HSM_ST_ERR))
++ /* bad ireason reported by device */
++ goto fsm_start;
++
++ } else {
++ /* ATA PIO protocol */
++ if (unlikely((status & ATA_DRQ) == 0)) {
++ /* handle BSY=0, DRQ=0 as error */
++ if (likely(status & (ATA_ERR | ATA_DF)))
++ /* device stops HSM for abort/error */
++ qc->err_mask |= AC_ERR_DEV;
++ else
++ /* HSM violation. Let EH handle this.
++ * Phantom devices also trigger this
++ * condition. Mark hint.
++ */
++ qc->err_mask |= AC_ERR_HSM |
++ AC_ERR_NODEV_HINT;
++
++ ap->hsm_task_state = HSM_ST_ERR;
++ goto fsm_start;
++ }
++
++ /* For PIO reads, some devices may ask for
++ * data transfer (DRQ=1) alone with ERR=1.
++ * We respect DRQ here and transfer one
++ * block of junk data before changing the
++ * hsm_task_state to HSM_ST_ERR.
++ *
++ * For PIO writes, ERR=1 DRQ=1 doesn't make
++ * sense since the data block has been
++ * transferred to the device.
++ */
++ if (unlikely(status & (ATA_ERR | ATA_DF))) {
++ /* data might be corrputed */
++ qc->err_mask |= AC_ERR_DEV;
++
++ if (!(qc->tf.flags & ATA_TFLAG_WRITE)) {
++ ata_pio_sectors(qc);
++ status = ata_wait_idle(ap);
++ }
++
++ if (status & (ATA_BUSY | ATA_DRQ))
++ qc->err_mask |= AC_ERR_HSM;
++
++ /* ata_pio_sectors() might change the
++ * state to HSM_ST_LAST. so, the state
++ * is changed after ata_pio_sectors().
++ */
++ ap->hsm_task_state = HSM_ST_ERR;
++ goto fsm_start;
++ }
++
++ ata_pio_sectors(qc);
++
++ if (ap->hsm_task_state == HSM_ST_LAST &&
++ (!(qc->tf.flags & ATA_TFLAG_WRITE))) {
++ /* all data read */
++ status = ata_wait_idle(ap);
++ goto fsm_start;
++ }
++ }
++
++ poll_next = 1;
++ break;
++
++ case HSM_ST_LAST:
++ if (unlikely(!ata_ok(status))) {
++ qc->err_mask |= __ac_err_mask(status);
++ ap->hsm_task_state = HSM_ST_ERR;
++ goto fsm_start;
++ }
++
++ /* no more data to transfer */
++ DPRINTK("ata%u: dev %u command complete, drv_stat 0x%x\n",
++ ap->print_id, qc->dev->devno, status);
++
++ WARN_ON(qc->err_mask & (AC_ERR_DEV | AC_ERR_HSM));
++
++ ap->hsm_task_state = HSM_ST_IDLE;
++
++ /* complete taskfile transaction */
++ ata_hsm_qc_complete(qc, in_wq);
++
++ poll_next = 0;
++ break;
++
++ case HSM_ST_ERR:
++ /* make sure qc->err_mask is available to
++ * know what's wrong and recover
++ */
++ WARN_ON(!(qc->err_mask & (AC_ERR_DEV | AC_ERR_HSM)));
++
++ ap->hsm_task_state = HSM_ST_IDLE;
++
++ /* complete taskfile transaction */
++ ata_hsm_qc_complete(qc, in_wq);
++
++ poll_next = 0;
++ break;
++ default:
++ poll_next = 0;
++ BUG();
++ }
++
++ return poll_next;
++}
++
++void ata_pio_task(struct work_struct *work)
++{
++ struct ata_port *ap =
++ container_of(work, struct ata_port, port_task.work);
++ struct ata_queued_cmd *qc = ap->port_task_data;
++ u8 status;
++ int poll_next;
++
++fsm_start:
++ WARN_ON(ap->hsm_task_state == HSM_ST_IDLE);
++
++ /*
++ * This is purely heuristic. This is a fast path.
++ * Sometimes when we enter, BSY will be cleared in
++ * a chk-status or two. If not, the drive is probably seeking
++ * or something. Snooze for a couple msecs, then
++ * chk-status again. If still busy, queue delayed work.
++ */
++ status = ata_sff_busy_wait(ap, ATA_BUSY, 5);
++ if (status & ATA_BUSY) {
++ msleep(2);
++ status = ata_sff_busy_wait(ap, ATA_BUSY, 10);
++ if (status & ATA_BUSY) {
++ ata_pio_queue_task(ap, qc, ATA_SHORT_PAUSE);
++ return;
++ }
++ }
++
++ /* move the HSM */
++ poll_next = ata_sff_hsm_move(ap, qc, status, 1);
++
++ /* another command or interrupt handler
++ * may be running at this point.
++ */
++ if (poll_next)
++ goto fsm_start;
+ }
+
+ /**
+- * ata_bmdma_status - Read PCI IDE BMDMA status
+- * @ap: Port associated with this ATA transaction.
++ * ata_sff_qc_issue - issue taskfile to device in proto-dependent manner
++ * @qc: command to issue to device
+ *
+- * Read and return BMDMA status register.
++ * Using various libata functions and hooks, this function
++ * starts an ATA command. ATA commands are grouped into
++ * classes called "protocols", and issuing each type of protocol
++ * is slightly different.
+ *
+- * May be used as the bmdma_status() entry in ata_port_operations.
++ * May be used as the qc_issue() entry in ata_port_operations.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
++ *
++ * RETURNS:
++ * Zero on success, AC_ERR_* mask on failure
+ */
+-u8 ata_bmdma_status(struct ata_port *ap)
++unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
+ {
+- return ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
++ struct ata_port *ap = qc->ap;
++
++ /* Use polling pio if the LLD doesn't handle
++ * interrupt driven pio and atapi CDB interrupt.
++ */
++ if (ap->flags & ATA_FLAG_PIO_POLLING) {
++ switch (qc->tf.protocol) {
++ case ATA_PROT_PIO:
++ case ATA_PROT_NODATA:
++ case ATAPI_PROT_PIO:
++ case ATAPI_PROT_NODATA:
++ qc->tf.flags |= ATA_TFLAG_POLLING;
++ break;
++ case ATAPI_PROT_DMA:
++ if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
++ /* see ata_dma_blacklisted() */
++ BUG();
++ break;
++ default:
++ break;
++ }
++ }
++
++ /* select the device */
++ ata_dev_select(ap, qc->dev->devno, 1, 0);
++
++ /* start the command */
++ switch (qc->tf.protocol) {
++ case ATA_PROT_NODATA:
++ if (qc->tf.flags & ATA_TFLAG_POLLING)
++ ata_qc_set_polling(qc);
++
++ ata_tf_to_host(ap, &qc->tf);
++ ap->hsm_task_state = HSM_ST_LAST;
++
++ if (qc->tf.flags & ATA_TFLAG_POLLING)
++ ata_pio_queue_task(ap, qc, 0);
++
++ break;
++
++ case ATA_PROT_DMA:
++ WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
++
++ ap->ops->sff_tf_load(ap, &qc->tf); /* load tf registers */
++ ap->ops->bmdma_setup(qc); /* set up bmdma */
++ ap->ops->bmdma_start(qc); /* initiate bmdma */
++ ap->hsm_task_state = HSM_ST_LAST;
++ break;
++
++ case ATA_PROT_PIO:
++ if (qc->tf.flags & ATA_TFLAG_POLLING)
++ ata_qc_set_polling(qc);
++
++ ata_tf_to_host(ap, &qc->tf);
++
++ if (qc->tf.flags & ATA_TFLAG_WRITE) {
++ /* PIO data out protocol */
++ ap->hsm_task_state = HSM_ST_FIRST;
++ ata_pio_queue_task(ap, qc, 0);
++
++ /* always send first data block using
++ * the ata_pio_task() codepath.
++ */
++ } else {
++ /* PIO data in protocol */
++ ap->hsm_task_state = HSM_ST;
++
++ if (qc->tf.flags & ATA_TFLAG_POLLING)
++ ata_pio_queue_task(ap, qc, 0);
++
++ /* if polling, ata_pio_task() handles the rest.
++ * otherwise, interrupt handler takes over from here.
++ */
++ }
++
++ break;
++
++ case ATAPI_PROT_PIO:
++ case ATAPI_PROT_NODATA:
++ if (qc->tf.flags & ATA_TFLAG_POLLING)
++ ata_qc_set_polling(qc);
++
++ ata_tf_to_host(ap, &qc->tf);
++
++ ap->hsm_task_state = HSM_ST_FIRST;
++
++ /* send cdb by polling if no cdb interrupt */
++ if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) ||
++ (qc->tf.flags & ATA_TFLAG_POLLING))
++ ata_pio_queue_task(ap, qc, 0);
++ break;
++
++ case ATAPI_PROT_DMA:
++ WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
++
++ ap->ops->sff_tf_load(ap, &qc->tf); /* load tf registers */
++ ap->ops->bmdma_setup(qc); /* set up bmdma */
++ ap->hsm_task_state = HSM_ST_FIRST;
++
++ /* send cdb by polling if no cdb interrupt */
++ if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
++ ata_pio_queue_task(ap, qc, 0);
++ break;
++
++ default:
++ WARN_ON(1);
++ return AC_ERR_SYSTEM;
++ }
++
++ return 0;
+ }
+
+ /**
+- * ata_bmdma_stop - Stop PCI IDE BMDMA transfer
+- * @qc: Command we are ending DMA for
++ * ata_sff_qc_fill_rtf - fill result TF using ->sff_tf_read
++ * @qc: qc to fill result TF for
+ *
+- * Clears the ATA_DMA_START flag in the dma control register
++ * @qc is finished and result TF needs to be filled. Fill it
++ * using ->sff_tf_read.
+ *
+- * May be used as the bmdma_stop() entry in ata_port_operations.
++ * LOCKING:
++ * spin_lock_irqsave(host lock)
++ *
++ * RETURNS:
++ * true indicating that result TF is successfully filled.
++ */
++bool ata_sff_qc_fill_rtf(struct ata_queued_cmd *qc)
++{
++ qc->ap->ops->sff_tf_read(qc->ap, &qc->result_tf);
++ return true;
++}
++
++/**
++ * ata_sff_host_intr - Handle host interrupt for given (port, task)
++ * @ap: Port on which interrupt arrived (possibly...)
++ * @qc: Taskfile currently active in engine
++ *
++ * Handle host interrupt for given queued command. Currently,
++ * only DMA interrupts are handled. All other commands are
++ * handled via polling with interrupts disabled (nIEN bit).
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
++ *
++ * RETURNS:
++ * One if interrupt was handled, zero if not (shared irq).
+ */
+-void ata_bmdma_stop(struct ata_queued_cmd *qc)
++inline unsigned int ata_sff_host_intr(struct ata_port *ap,
++ struct ata_queued_cmd *qc)
+ {
+- struct ata_port *ap = qc->ap;
+- void __iomem *mmio = ap->ioaddr.bmdma_addr;
++ struct ata_eh_info *ehi = &ap->link.eh_info;
++ u8 status, host_stat = 0;
+
+- /* clear start/stop bit */
+- iowrite8(ioread8(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
+- mmio + ATA_DMA_CMD);
++ VPRINTK("ata%u: protocol %d task_state %d\n",
++ ap->print_id, qc->tf.protocol, ap->hsm_task_state);
+
+- /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
+- ata_altstatus(ap); /* dummy read */
++ /* Check whether we are expecting interrupt in this state */
++ switch (ap->hsm_task_state) {
++ case HSM_ST_FIRST:
++ /* Some pre-ATAPI-4 devices assert INTRQ
++ * at this state when ready to receive CDB.
++ */
++
++ /* Check the ATA_DFLAG_CDB_INTR flag is enough here.
++ * The flag was turned on only for atapi devices. No
++ * need to check ata_is_atapi(qc->tf.protocol) again.
++ */
++ if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
++ goto idle_irq;
++ break;
++ case HSM_ST_LAST:
++ if (qc->tf.protocol == ATA_PROT_DMA ||
++ qc->tf.protocol == ATAPI_PROT_DMA) {
++ /* check status of DMA engine */
++ host_stat = ap->ops->bmdma_status(ap);
++ VPRINTK("ata%u: host_stat 0x%X\n",
++ ap->print_id, host_stat);
++
++ /* if it's not our irq... */
++ if (!(host_stat & ATA_DMA_INTR))
++ goto idle_irq;
++
++ /* before we do anything else, clear DMA-Start bit */
++ ap->ops->bmdma_stop(qc);
++
++ if (unlikely(host_stat & ATA_DMA_ERR)) {
++ /* error when transfering data to/from memory */
++ qc->err_mask |= AC_ERR_HOST_BUS;
++ ap->hsm_task_state = HSM_ST_ERR;
++ }
++ }
++ break;
++ case HSM_ST:
++ break;
++ default:
++ goto idle_irq;
++ }
++
++ /* check altstatus */
++ status = ata_sff_altstatus(ap);
++ if (status & ATA_BUSY)
++ goto idle_irq;
++
++ /* check main status, clearing INTRQ */
++ status = ap->ops->sff_check_status(ap);
++ if (unlikely(status & ATA_BUSY))
++ goto idle_irq;
++
++ /* ack bmdma irq events */
++ ap->ops->sff_irq_clear(ap);
++
++ ata_sff_hsm_move(ap, qc, status, 0);
++
++ if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
++ qc->tf.protocol == ATAPI_PROT_DMA))
++ ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
++
++ return 1; /* irq handled */
++
++idle_irq:
++ ap->stats.idle_irq++;
++
++#ifdef ATA_IRQ_TRAP
++ if ((ap->stats.idle_irq % 1000) == 0) {
++ ap->ops->sff_check_status(ap);
++ ap->ops->sff_irq_clear(ap);
++ ata_port_printk(ap, KERN_WARNING, "irq trap\n");
++ return 1;
++ }
++#endif
++ return 0; /* irq not handled */
++}
++
++/**
++ * ata_sff_interrupt - Default ATA host interrupt handler
++ * @irq: irq line (unused)
++ * @dev_instance: pointer to our ata_host information structure
++ *
++ * Default interrupt handler for PCI IDE devices. Calls
++ * ata_sff_host_intr() for each port that is not disabled.
++ *
++ * LOCKING:
++ * Obtains host lock during operation.
++ *
++ * RETURNS:
++ * IRQ_NONE or IRQ_HANDLED.
++ */
++irqreturn_t ata_sff_interrupt(int irq, void *dev_instance)
++{
++ struct ata_host *host = dev_instance;
++ unsigned int i;
++ unsigned int handled = 0;
++ unsigned long flags;
++
++ /* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */
++ spin_lock_irqsave(&host->lock, flags);
++
++ for (i = 0; i < host->n_ports; i++) {
++ struct ata_port *ap;
++
++ ap = host->ports[i];
++ if (ap &&
++ !(ap->flags & ATA_FLAG_DISABLED)) {
++ struct ata_queued_cmd *qc;
++
++ qc = ata_qc_from_tag(ap, ap->link.active_tag);
++ if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
++ (qc->flags & ATA_QCFLAG_ACTIVE))
++ handled |= ata_sff_host_intr(ap, qc);
++ }
++ }
++
++ spin_unlock_irqrestore(&host->lock, flags);
++
++ return IRQ_RETVAL(handled);
+ }
+
+ /**
+- * ata_bmdma_freeze - Freeze BMDMA controller port
++ * ata_sff_freeze - Freeze SFF controller port
+ * @ap: port to freeze
+ *
+ * Freeze BMDMA controller port.
+@@ -351,7 +1581,7 @@ void ata_bmdma_stop(struct ata_queued_cmd *qc)
+ * LOCKING:
+ * Inherited from caller.
+ */
+-void ata_bmdma_freeze(struct ata_port *ap)
++void ata_sff_freeze(struct ata_port *ap)
+ {
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+
+@@ -365,51 +1595,412 @@ void ata_bmdma_freeze(struct ata_port *ap)
+ * ATA_NIEN manipulation. Also, many controllers fail to mask
+ * previously pending IRQ on ATA_NIEN assertion. Clear it.
+ */
+- ata_chk_status(ap);
++ ap->ops->sff_check_status(ap);
+
+- ap->ops->irq_clear(ap);
++ ap->ops->sff_irq_clear(ap);
+ }
+
+ /**
+- * ata_bmdma_thaw - Thaw BMDMA controller port
++ * ata_sff_thaw - Thaw SFF controller port
+ * @ap: port to thaw
+ *
+- * Thaw BMDMA controller port.
++ * Thaw SFF controller port.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+-void ata_bmdma_thaw(struct ata_port *ap)
++void ata_sff_thaw(struct ata_port *ap)
+ {
+ /* clear & re-enable interrupts */
+- ata_chk_status(ap);
+- ap->ops->irq_clear(ap);
+- ap->ops->irq_on(ap);
++ ap->ops->sff_check_status(ap);
++ ap->ops->sff_irq_clear(ap);
++ ap->ops->sff_irq_on(ap);
++}
++
++/**
++ * ata_sff_prereset - prepare SFF link for reset
++ * @link: SFF link to be reset
++ * @deadline: deadline jiffies for the operation
++ *
++ * SFF link @link is about to be reset. Initialize it. It first
++ * calls ata_std_prereset() and wait for !BSY if the port is
++ * being softreset.
++ *
++ * LOCKING:
++ * Kernel thread context (may sleep)
++ *
++ * RETURNS:
++ * 0 on success, -errno otherwise.
++ */
++int ata_sff_prereset(struct ata_link *link, unsigned long deadline)
++{
++ struct ata_eh_context *ehc = &link->eh_context;
++ int rc;
++
++ rc = ata_std_prereset(link, deadline);
++ if (rc)
++ return rc;
++
++ /* if we're about to do hardreset, nothing more to do */
++ if (ehc->i.action & ATA_EH_HARDRESET)
++ return 0;
++
++ /* wait for !BSY if we don't know that no device is attached */
++ if (!ata_link_offline(link)) {
++ rc = ata_sff_wait_ready(link, deadline);
++ if (rc && rc != -ENODEV) {
++ ata_link_printk(link, KERN_WARNING, "device not ready "
++ "(errno=%d), forcing hardreset\n", rc);
++ ehc->i.action |= ATA_EH_HARDRESET;
++ }
++ }
++
++ return 0;
++}
++
++/**
++ * ata_devchk - PATA device presence detection
++ * @ap: ATA channel to examine
++ * @device: Device to examine (starting at zero)
++ *
++ * This technique was originally described in
++ * Hale Landis's ATADRVR (www.ata-atapi.com), and
++ * later found its way into the ATA/ATAPI spec.
++ *
++ * Write a pattern to the ATA shadow registers,
++ * and if a device is present, it will respond by
++ * correctly storing and echoing back the
++ * ATA shadow register contents.
++ *
++ * LOCKING:
++ * caller.
++ */
++static unsigned int ata_devchk(struct ata_port *ap, unsigned int device)
++{
++ struct ata_ioports *ioaddr = &ap->ioaddr;
++ u8 nsect, lbal;
++
++ ap->ops->sff_dev_select(ap, device);
++
++ iowrite8(0x55, ioaddr->nsect_addr);
++ iowrite8(0xaa, ioaddr->lbal_addr);
++
++ iowrite8(0xaa, ioaddr->nsect_addr);
++ iowrite8(0x55, ioaddr->lbal_addr);
++
++ iowrite8(0x55, ioaddr->nsect_addr);
++ iowrite8(0xaa, ioaddr->lbal_addr);
++
++ nsect = ioread8(ioaddr->nsect_addr);
++ lbal = ioread8(ioaddr->lbal_addr);
++
++ if ((nsect == 0x55) && (lbal == 0xaa))
++ return 1; /* we found a device */
++
++ return 0; /* nothing found */
++}
++
++/**
++ * ata_sff_dev_classify - Parse returned ATA device signature
++ * @dev: ATA device to classify (starting at zero)
++ * @present: device seems present
++ * @r_err: Value of error register on completion
++ *
++ * After an event -- SRST, E.D.D., or SATA COMRESET -- occurs,
++ * an ATA/ATAPI-defined set of values is placed in the ATA
++ * shadow registers, indicating the results of device detection
++ * and diagnostics.
++ *
++ * Select the ATA device, and read the values from the ATA shadow
++ * registers. Then parse according to the Error register value,
++ * and the spec-defined values examined by ata_dev_classify().
++ *
++ * LOCKING:
++ * caller.
++ *
++ * RETURNS:
++ * Device type - %ATA_DEV_ATA, %ATA_DEV_ATAPI or %ATA_DEV_NONE.
++ */
++unsigned int ata_sff_dev_classify(struct ata_device *dev, int present,
++ u8 *r_err)
++{
++ struct ata_port *ap = dev->link->ap;
++ struct ata_taskfile tf;
++ unsigned int class;
++ u8 err;
++
++ ap->ops->sff_dev_select(ap, dev->devno);
++
++ memset(&tf, 0, sizeof(tf));
++
++ ap->ops->sff_tf_read(ap, &tf);
++ err = tf.feature;
++ if (r_err)
++ *r_err = err;
++
++ /* see if device passed diags: continue and warn later */
++ if (err == 0)
++ /* diagnostic fail : do nothing _YET_ */
++ dev->horkage |= ATA_HORKAGE_DIAGNOSTIC;
++ else if (err == 1)
++ /* do nothing */ ;
++ else if ((dev->devno == 0) && (err == 0x81))
++ /* do nothing */ ;
++ else
++ return ATA_DEV_NONE;
++
++ /* determine if device is ATA or ATAPI */
++ class = ata_dev_classify(&tf);
++
++ if (class == ATA_DEV_UNKNOWN) {
++ /* If the device failed diagnostic, it's likely to
++ * have reported incorrect device signature too.
++ * Assume ATA device if the device seems present but
++ * device signature is invalid with diagnostic
++ * failure.
++ */
++ if (present && (dev->horkage & ATA_HORKAGE_DIAGNOSTIC))
++ class = ATA_DEV_ATA;
++ else
++ class = ATA_DEV_NONE;
++ } else if ((class == ATA_DEV_ATA) &&
++ (ap->ops->sff_check_status(ap) == 0))
++ class = ATA_DEV_NONE;
++
++ return class;
++}
++
++/**
++ * ata_sff_wait_after_reset - wait for devices to become ready after reset
++ * @link: SFF link which is just reset
++ * @devmask: mask of present devices
++ * @deadline: deadline jiffies for the operation
++ *
++ * Wait devices attached to SFF @link to become ready after
++ * reset. It contains preceding 150ms wait to avoid accessing TF
++ * status register too early.
++ *
++ * LOCKING:
++ * Kernel thread context (may sleep).
++ *
++ * RETURNS:
++ * 0 on success, -ENODEV if some or all of devices in @devmask
++ * don't seem to exist. -errno on other errors.
++ */
++int ata_sff_wait_after_reset(struct ata_link *link, unsigned int devmask,
++ unsigned long deadline)
++{
++ struct ata_port *ap = link->ap;
++ struct ata_ioports *ioaddr = &ap->ioaddr;
++ unsigned int dev0 = devmask & (1 << 0);
++ unsigned int dev1 = devmask & (1 << 1);
++ int rc, ret = 0;
++
++ msleep(ATA_WAIT_AFTER_RESET_MSECS);
++
++ /* always check readiness of the master device */
++ rc = ata_sff_wait_ready(link, deadline);
++ /* -ENODEV means the odd clown forgot the D7 pulldown resistor
++ * and TF status is 0xff, bail out on it too.
++ */
++ if (rc)
++ return rc;
++
++ /* if device 1 was found in ata_devchk, wait for register
++ * access briefly, then wait for BSY to clear.
++ */
++ if (dev1) {
++ int i;
++
++ ap->ops->sff_dev_select(ap, 1);
++
++ /* Wait for register access. Some ATAPI devices fail
++ * to set nsect/lbal after reset, so don't waste too
++ * much time on it. We're gonna wait for !BSY anyway.
++ */
++ for (i = 0; i < 2; i++) {
++ u8 nsect, lbal;
++
++ nsect = ioread8(ioaddr->nsect_addr);
++ lbal = ioread8(ioaddr->lbal_addr);
++ if ((nsect == 1) && (lbal == 1))
++ break;
++ msleep(50); /* give drive a breather */
++ }
++
++ rc = ata_sff_wait_ready(link, deadline);
++ if (rc) {
++ if (rc != -ENODEV)
++ return rc;
++ ret = rc;
++ }
++ }
++
++ /* is all this really necessary? */
++ ap->ops->sff_dev_select(ap, 0);
++ if (dev1)
++ ap->ops->sff_dev_select(ap, 1);
++ if (dev0)
++ ap->ops->sff_dev_select(ap, 0);
++
++ return ret;
++}
++
++static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask,
++ unsigned long deadline)
++{
++ struct ata_ioports *ioaddr = &ap->ioaddr;
++
++ DPRINTK("ata%u: bus reset via SRST\n", ap->print_id);
++
++ /* software reset. causes dev0 to be selected */
++ iowrite8(ap->ctl, ioaddr->ctl_addr);
++ udelay(20); /* FIXME: flush */
++ iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
++ udelay(20); /* FIXME: flush */
++ iowrite8(ap->ctl, ioaddr->ctl_addr);
++
++ /* wait the port to become ready */
++ return ata_sff_wait_after_reset(&ap->link, devmask, deadline);
++}
++
++/**
++ * ata_sff_softreset - reset host port via ATA SRST
++ * @link: ATA link to reset
++ * @classes: resulting classes of attached devices
++ * @deadline: deadline jiffies for the operation
++ *
++ * Reset host port using ATA SRST.
++ *
++ * LOCKING:
++ * Kernel thread context (may sleep)
++ *
++ * RETURNS:
++ * 0 on success, -errno otherwise.
++ */
++int ata_sff_softreset(struct ata_link *link, unsigned int *classes,
++ unsigned long deadline)
++{
++ struct ata_port *ap = link->ap;
++ unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
++ unsigned int devmask = 0;
++ int rc;
++ u8 err;
++
++ DPRINTK("ENTER\n");
++
++ /* determine if device 0/1 are present */
++ if (ata_devchk(ap, 0))
++ devmask |= (1 << 0);
++ if (slave_possible && ata_devchk(ap, 1))
++ devmask |= (1 << 1);
++
++ /* select device 0 again */
++ ap->ops->sff_dev_select(ap, 0);
++
++ /* issue bus reset */
++ DPRINTK("about to softreset, devmask=%x\n", devmask);
++ rc = ata_bus_softreset(ap, devmask, deadline);
++ /* if link is occupied, -ENODEV too is an error */
++ if (rc && (rc != -ENODEV || sata_scr_valid(link))) {
++ ata_link_printk(link, KERN_ERR, "SRST failed (errno=%d)\n", rc);
++ return rc;
++ }
++
++ /* determine by signature whether we have ATA or ATAPI devices */
++ classes[0] = ata_sff_dev_classify(&link->device[0],
++ devmask & (1 << 0), &err);
++ if (slave_possible && err != 0x81)
++ classes[1] = ata_sff_dev_classify(&link->device[1],
++ devmask & (1 << 1), &err);
++
++ DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
++ return 0;
++}
++
++/**
++ * sata_sff_hardreset - reset host port via SATA phy reset
++ * @link: link to reset
++ * @class: resulting class of attached device
++ * @deadline: deadline jiffies for the operation
++ *
++ * SATA phy-reset host port using DET bits of SControl register,
++ * wait for !BSY and classify the attached device.
++ *
++ * LOCKING:
++ * Kernel thread context (may sleep)
++ *
++ * RETURNS:
++ * 0 on success, -errno otherwise.
++ */
++int sata_sff_hardreset(struct ata_link *link, unsigned int *class,
++ unsigned long deadline)
++{
++ struct ata_eh_context *ehc = &link->eh_context;
++ const unsigned long *timing = sata_ehc_deb_timing(ehc);
++ bool online;
++ int rc;
++
++ rc = sata_link_hardreset(link, timing, deadline, &online,
++ ata_sff_check_ready);
++ if (online)
++ *class = ata_sff_dev_classify(link->device, 1, NULL);
++
++ DPRINTK("EXIT, class=%u\n", *class);
++ return rc;
+ }
+
+ /**
+- * ata_bmdma_drive_eh - Perform EH with given methods for BMDMA controller
++ * ata_sff_postreset - SFF postreset callback
++ * @link: the target SFF ata_link
++ * @classes: classes of attached devices
++ *
++ * This function is invoked after a successful reset. It first
++ * calls ata_std_postreset() and performs SFF specific postreset
++ * processing.
++ *
++ * LOCKING:
++ * Kernel thread context (may sleep)
++ */
++void ata_sff_postreset(struct ata_link *link, unsigned int *classes)
++{
++ struct ata_port *ap = link->ap;
++
++ ata_std_postreset(link, classes);
++
++ /* is double-select really necessary? */
++ if (classes[0] != ATA_DEV_NONE)
++ ap->ops->sff_dev_select(ap, 1);
++ if (classes[1] != ATA_DEV_NONE)
++ ap->ops->sff_dev_select(ap, 0);
++
++ /* bail out if no device is present */
++ if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
++ DPRINTK("EXIT, no device\n");
++ return;
++ }
++
++ /* set up device control */
++ if (ap->ioaddr.ctl_addr)
++ iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
++}
++
++/**
++ * ata_sff_error_handler - Stock error handler for BMDMA controller
+ * @ap: port to handle error for
+- * @prereset: prereset method (can be NULL)
+- * @softreset: softreset method (can be NULL)
+- * @hardreset: hardreset method (can be NULL)
+- * @postreset: postreset method (can be NULL)
+ *
+- * Handle error for ATA BMDMA controller. It can handle both
++ * Stock error handler for SFF controller. It can handle both
+ * PATA and SATA controllers. Many controllers should be able to
+ * use this EH as-is or with some added handling before and
+ * after.
+ *
+- * This function is intended to be used for constructing
+- * ->error_handler callback by low level drivers.
+- *
+ * LOCKING:
+ * Kernel thread context (may sleep)
+ */
+-void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+- ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
+- ata_postreset_fn_t postreset)
++void ata_sff_error_handler(struct ata_port *ap)
+ {
++ ata_reset_fn_t softreset = ap->ops->softreset;
++ ata_reset_fn_t hardreset = ap->ops->hardreset;
+ struct ata_queued_cmd *qc;
+ unsigned long flags;
+ int thaw = 0;
+@@ -423,7 +2014,8 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+
+ ap->hsm_task_state = HSM_ST_IDLE;
+
+- if (qc && (qc->tf.protocol == ATA_PROT_DMA ||
++ if (ap->ioaddr.bmdma_addr &&
++ qc && (qc->tf.protocol == ATA_PROT_DMA ||
+ qc->tf.protocol == ATAPI_PROT_DMA)) {
+ u8 host_stat;
+
+@@ -442,9 +2034,9 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+ ap->ops->bmdma_stop(qc);
+ }
+
+- ata_altstatus(ap);
+- ata_chk_status(ap);
+- ap->ops->irq_clear(ap);
++ ata_sff_altstatus(ap);
++ ap->ops->sff_check_status(ap);
++ ap->ops->sff_irq_clear(ap);
+
+ spin_unlock_irqrestore(ap->lock, flags);
+
+@@ -452,40 +2044,27 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+ ata_eh_thaw_port(ap);
+
+ /* PIO and DMA engines have been stopped, perform recovery */
+- ata_do_eh(ap, prereset, softreset, hardreset, postreset);
+-}
+-
+-/**
+- * ata_bmdma_error_handler - Stock error handler for BMDMA controller
+- * @ap: port to handle error for
+- *
+- * Stock error handler for BMDMA controller.
+- *
+- * LOCKING:
+- * Kernel thread context (may sleep)
+- */
+-void ata_bmdma_error_handler(struct ata_port *ap)
+-{
+- ata_reset_fn_t softreset = NULL, hardreset = NULL;
+
+- if (ap->ioaddr.ctl_addr)
+- softreset = ata_std_softreset;
+- if (sata_scr_valid(&ap->link))
+- hardreset = sata_std_hardreset;
++ /* Ignore ata_sff_softreset if ctl isn't accessible and
++ * built-in hardresets if SCR access isn't available.
++ */
++ if (softreset == ata_sff_softreset && !ap->ioaddr.ctl_addr)
++ softreset = NULL;
++ if (ata_is_builtin_hardreset(hardreset) && !sata_scr_valid(&ap->link))
++ hardreset = NULL;
+
+- ata_bmdma_drive_eh(ap, ata_std_prereset, softreset, hardreset,
+- ata_std_postreset);
++ ata_do_eh(ap, ap->ops->prereset, softreset, hardreset,
++ ap->ops->postreset);
+ }
+
+ /**
+- * ata_bmdma_post_internal_cmd - Stock post_internal_cmd for
+- * BMDMA controller
++ * ata_sff_post_internal_cmd - Stock post_internal_cmd for SFF controller
+ * @qc: internal command to clean up
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep)
+ */
+-void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
++void ata_sff_post_internal_cmd(struct ata_queued_cmd *qc)
+ {
+ if (qc->ap->ioaddr.bmdma_addr)
+ ata_bmdma_stop(qc);
+@@ -504,7 +2083,6 @@ void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
+ * LOCKING:
+ * Inherited from caller.
+ */
+-
+ int ata_sff_port_start(struct ata_port *ap)
+ {
+ if (ap->ioaddr.bmdma_addr)
+@@ -512,24 +2090,262 @@ int ata_sff_port_start(struct ata_port *ap)
+ return 0;
+ }
+
+-#ifdef CONFIG_PCI
++/**
++ * ata_sff_std_ports - initialize ioaddr with standard port offsets.
++ * @ioaddr: IO address structure to be initialized
++ *
++ * Utility function which initializes data_addr, error_addr,
++ * feature_addr, nsect_addr, lbal_addr, lbam_addr, lbah_addr,
++ * device_addr, status_addr, and command_addr to standard offsets
++ * relative to cmd_addr.
++ *
++ * Does not set ctl_addr, altstatus_addr, bmdma_addr, or scr_addr.
++ */
++void ata_sff_std_ports(struct ata_ioports *ioaddr)
++{
++ ioaddr->data_addr = ioaddr->cmd_addr + ATA_REG_DATA;
++ ioaddr->error_addr = ioaddr->cmd_addr + ATA_REG_ERR;
++ ioaddr->feature_addr = ioaddr->cmd_addr + ATA_REG_FEATURE;
++ ioaddr->nsect_addr = ioaddr->cmd_addr + ATA_REG_NSECT;
++ ioaddr->lbal_addr = ioaddr->cmd_addr + ATA_REG_LBAL;
++ ioaddr->lbam_addr = ioaddr->cmd_addr + ATA_REG_LBAM;
++ ioaddr->lbah_addr = ioaddr->cmd_addr + ATA_REG_LBAH;
++ ioaddr->device_addr = ioaddr->cmd_addr + ATA_REG_DEVICE;
++ ioaddr->status_addr = ioaddr->cmd_addr + ATA_REG_STATUS;
++ ioaddr->command_addr = ioaddr->cmd_addr + ATA_REG_CMD;
++}
+
+-static int ata_resources_present(struct pci_dev *pdev, int port)
++unsigned long ata_bmdma_mode_filter(struct ata_device *adev,
++ unsigned long xfer_mask)
+ {
+- int i;
++ /* Filter out DMA modes if the device has been configured by
++ the BIOS as PIO only */
+
+- /* Check the PCI resources for this channel are enabled */
+- port = port * 2;
+- for (i = 0; i < 2; i ++) {
+- if (pci_resource_start(pdev, port + i) == 0 ||
+- pci_resource_len(pdev, port + i) == 0)
+- return 0;
++ if (adev->link->ap->ioaddr.bmdma_addr == NULL)
++ xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
++ return xfer_mask;
++}
++
++/**
++ * ata_bmdma_setup - Set up PCI IDE BMDMA transaction
++ * @qc: Info associated with this ATA transaction.
++ *
++ * LOCKING:
++ * spin_lock_irqsave(host lock)
++ */
++void ata_bmdma_setup(struct ata_queued_cmd *qc)
++{
++ struct ata_port *ap = qc->ap;
++ unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
++ u8 dmactl;
++
++ /* load PRD table addr. */
++ mb(); /* make sure PRD table writes are visible to controller */
++ iowrite32(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
++
++ /* specify data direction, triple-check start bit is clear */
++ dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
++ dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
++ if (!rw)
++ dmactl |= ATA_DMA_WR;
++ iowrite8(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
++
++ /* issue r/w command */
++ ap->ops->sff_exec_command(ap, &qc->tf);
++}
++
++/**
++ * ata_bmdma_start - Start a PCI IDE BMDMA transaction
++ * @qc: Info associated with this ATA transaction.
++ *
++ * LOCKING:
++ * spin_lock_irqsave(host lock)
++ */
++void ata_bmdma_start(struct ata_queued_cmd *qc)
++{
++ struct ata_port *ap = qc->ap;
++ u8 dmactl;
++
++ /* start host DMA transaction */
++ dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
++ iowrite8(dmactl | ATA_DMA_START, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
++
++ /* Strictly, one may wish to issue an ioread8() here, to
++ * flush the mmio write. However, control also passes
++ * to the hardware at this point, and it will interrupt
++ * us when we are to resume control. So, in effect,
++ * we don't care when the mmio write flushes.
++ * Further, a read of the DMA status register _immediately_
++ * following the write may not be what certain flaky hardware
++ * is expected, so I think it is best to not add a readb()
++ * without first all the MMIO ATA cards/mobos.
++ * Or maybe I'm just being paranoid.
++ *
++ * FIXME: The posting of this write means I/O starts are
++ * unneccessarily delayed for MMIO
++ */
++}
++
++/**
++ * ata_bmdma_stop - Stop PCI IDE BMDMA transfer
++ * @qc: Command we are ending DMA for
++ *
++ * Clears the ATA_DMA_START flag in the dma control register
++ *
++ * May be used as the bmdma_stop() entry in ata_port_operations.
++ *
++ * LOCKING:
++ * spin_lock_irqsave(host lock)
++ */
++void ata_bmdma_stop(struct ata_queued_cmd *qc)
++{
++ struct ata_port *ap = qc->ap;
++ void __iomem *mmio = ap->ioaddr.bmdma_addr;
++
++ /* clear start/stop bit */
++ iowrite8(ioread8(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
++ mmio + ATA_DMA_CMD);
++
++ /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
++ ata_sff_altstatus(ap); /* dummy read */
++}
++
++/**
++ * ata_bmdma_status - Read PCI IDE BMDMA status
++ * @ap: Port associated with this ATA transaction.
++ *
++ * Read and return BMDMA status register.
++ *
++ * May be used as the bmdma_status() entry in ata_port_operations.
++ *
++ * LOCKING:
++ * spin_lock_irqsave(host lock)
++ */
++u8 ata_bmdma_status(struct ata_port *ap)
++{
++ return ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
++}
++
++/**
++ * ata_bus_reset - reset host port and associated ATA channel
++ * @ap: port to reset
++ *
++ * This is typically the first time we actually start issuing
++ * commands to the ATA channel. We wait for BSY to clear, then
++ * issue EXECUTE DEVICE DIAGNOSTIC command, polling for its
++ * result. Determine what devices, if any, are on the channel
++ * by looking at the device 0/1 error register. Look at the signature
++ * stored in each device's taskfile registers, to determine if
++ * the device is ATA or ATAPI.
++ *
++ * LOCKING:
++ * PCI/etc. bus probe sem.
++ * Obtains host lock.
++ *
++ * SIDE EFFECTS:
++ * Sets ATA_FLAG_DISABLED if bus reset fails.
++ *
++ * DEPRECATED:
++ * This function is only for drivers which still use old EH and
++ * will be removed soon.
++ */
++void ata_bus_reset(struct ata_port *ap)
++{
++ struct ata_device *device = ap->link.device;
++ struct ata_ioports *ioaddr = &ap->ioaddr;
++ unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
++ u8 err;
++ unsigned int dev0, dev1 = 0, devmask = 0;
++ int rc;
++
++ DPRINTK("ENTER, host %u, port %u\n", ap->print_id, ap->port_no);
++
++ /* determine if device 0/1 are present */
++ if (ap->flags & ATA_FLAG_SATA_RESET)
++ dev0 = 1;
++ else {
++ dev0 = ata_devchk(ap, 0);
++ if (slave_possible)
++ dev1 = ata_devchk(ap, 1);
+ }
+- return 1;
++
++ if (dev0)
++ devmask |= (1 << 0);
++ if (dev1)
++ devmask |= (1 << 1);
++
++ /* select device 0 again */
++ ap->ops->sff_dev_select(ap, 0);
++
++ /* issue bus reset */
++ if (ap->flags & ATA_FLAG_SRST) {
++ rc = ata_bus_softreset(ap, devmask, jiffies + 40 * HZ);
++ if (rc && rc != -ENODEV)
++ goto err_out;
++ }
++
++ /*
++ * determine by signature whether we have ATA or ATAPI devices
++ */
++ device[0].class = ata_sff_dev_classify(&device[0], dev0, &err);
++ if ((slave_possible) && (err != 0x81))
++ device[1].class = ata_sff_dev_classify(&device[1], dev1, &err);
++
++ /* is double-select really necessary? */
++ if (device[1].class != ATA_DEV_NONE)
++ ap->ops->sff_dev_select(ap, 1);
++ if (device[0].class != ATA_DEV_NONE)
++ ap->ops->sff_dev_select(ap, 0);
++
++ /* if no devices were detected, disable this port */
++ if ((device[0].class == ATA_DEV_NONE) &&
++ (device[1].class == ATA_DEV_NONE))
++ goto err_out;
++
++ if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) {
++ /* set up device control for ATA_FLAG_SATA_RESET */
++ iowrite8(ap->ctl, ioaddr->ctl_addr);
++ }
++
++ DPRINTK("EXIT\n");
++ return;
++
++err_out:
++ ata_port_printk(ap, KERN_ERR, "disabling port\n");
++ ata_port_disable(ap);
++
++ DPRINTK("EXIT\n");
+ }
+
++#ifdef CONFIG_PCI
++
+ /**
+- * ata_pci_init_bmdma - acquire PCI BMDMA resources and init ATA host
++ * ata_pci_bmdma_clear_simplex - attempt to kick device out of simplex
++ * @pdev: PCI device
++ *
++ * Some PCI ATA devices report simplex mode but in fact can be told to
++ * enter non simplex mode. This implements the necessary logic to
++ * perform the task on such devices. Calling it on other devices will
++ * have -undefined- behaviour.
++ */
++int ata_pci_bmdma_clear_simplex(struct pci_dev *pdev)
++{
++ unsigned long bmdma = pci_resource_start(pdev, 4);
++ u8 simplex;
++
++ if (bmdma == 0)
++ return -ENOENT;
++
++ simplex = inb(bmdma + 0x02);
++ outb(simplex & 0x60, bmdma + 0x02);
++ simplex = inb(bmdma + 0x02);
++ if (simplex & 0x80)
++ return -EOPNOTSUPP;
++ return 0;
++}
++
++/**
++ * ata_pci_bmdma_init - acquire PCI BMDMA resources and init ATA host
+ * @host: target ATA host
+ *
+ * Acquire PCI BMDMA resources and initialize @host accordingly.
+@@ -540,7 +2356,7 @@ static int ata_resources_present(struct pci_dev *pdev, int port)
+ * RETURNS:
+ * 0 on success, -errno otherwise.
+ */
+-int ata_pci_init_bmdma(struct ata_host *host)
++int ata_pci_bmdma_init(struct ata_host *host)
+ {
+ struct device *gdev = host->dev;
+ struct pci_dev *pdev = to_pci_dev(gdev);
+@@ -585,8 +2401,22 @@ int ata_pci_init_bmdma(struct ata_host *host)
+ return 0;
+ }
+
++static int ata_resources_present(struct pci_dev *pdev, int port)
++{
++ int i;
++
++ /* Check the PCI resources for this channel are enabled */
++ port = port * 2;
++ for (i = 0; i < 2; i ++) {
++ if (pci_resource_start(pdev, port + i) == 0 ||
++ pci_resource_len(pdev, port + i) == 0)
++ return 0;
++ }
++ return 1;
++}
++
+ /**
+- * ata_pci_init_sff_host - acquire native PCI ATA resources and init host
++ * ata_pci_sff_init_host - acquire native PCI ATA resources and init host
+ * @host: target ATA host
+ *
+ * Acquire native PCI ATA resources for @host and initialize the
+@@ -604,7 +2434,7 @@ int ata_pci_init_bmdma(struct ata_host *host)
+ * 0 if at least one port is initialized, -ENODEV if no port is
+ * available.
+ */
+-int ata_pci_init_sff_host(struct ata_host *host)
++int ata_pci_sff_init_host(struct ata_host *host)
+ {
+ struct device *gdev = host->dev;
+ struct pci_dev *pdev = to_pci_dev(gdev);
+@@ -646,7 +2476,7 @@ int ata_pci_init_sff_host(struct ata_host *host)
+ ap->ioaddr.altstatus_addr =
+ ap->ioaddr.ctl_addr = (void __iomem *)
+ ((unsigned long)iomap[base + 1] | ATA_PCI_CTL_OFS);
+- ata_std_ports(&ap->ioaddr);
++ ata_sff_std_ports(&ap->ioaddr);
+
+ ata_port_desc(ap, "cmd 0x%llx ctl 0x%llx",
+ (unsigned long long)pci_resource_start(pdev, base),
+@@ -664,7 +2494,7 @@ int ata_pci_init_sff_host(struct ata_host *host)
+ }
+
+ /**
+- * ata_pci_prepare_sff_host - helper to prepare native PCI ATA host
++ * ata_pci_sff_prepare_host - helper to prepare native PCI ATA host
+ * @pdev: target PCI device
+ * @ppi: array of port_info, must be enough for two ports
+ * @r_host: out argument for the initialized ATA host
+@@ -678,7 +2508,7 @@ int ata_pci_init_sff_host(struct ata_host *host)
+ * RETURNS:
+ * 0 on success, -errno otherwise.
+ */
+-int ata_pci_prepare_sff_host(struct pci_dev *pdev,
++int ata_pci_sff_prepare_host(struct pci_dev *pdev,
+ const struct ata_port_info * const * ppi,
+ struct ata_host **r_host)
+ {
+@@ -696,12 +2526,12 @@ int ata_pci_prepare_sff_host(struct pci_dev *pdev,
+ goto err_out;
+ }
+
+- rc = ata_pci_init_sff_host(host);
++ rc = ata_pci_sff_init_host(host);
+ if (rc)
+ goto err_out;
+
+ /* init DMA related stuff */
+- rc = ata_pci_init_bmdma(host);
++ rc = ata_pci_bmdma_init(host);
+ if (rc)
+ goto err_bmdma;
+
+@@ -722,7 +2552,7 @@ int ata_pci_prepare_sff_host(struct pci_dev *pdev,
+ }
+
+ /**
+- * ata_pci_activate_sff_host - start SFF host, request IRQ and register it
++ * ata_pci_sff_activate_host - start SFF host, request IRQ and register it
+ * @host: target SFF ATA host
+ * @irq_handler: irq_handler used when requesting IRQ(s)
+ * @sht: scsi_host_template to use when registering the host
+@@ -737,7 +2567,7 @@ int ata_pci_prepare_sff_host(struct pci_dev *pdev,
+ * RETURNS:
+ * 0 on success, -errno otherwise.
+ */
+-int ata_pci_activate_sff_host(struct ata_host *host,
++int ata_pci_sff_activate_host(struct ata_host *host,
+ irq_handler_t irq_handler,
+ struct scsi_host_template *sht)
+ {
+@@ -815,9 +2645,11 @@ int ata_pci_activate_sff_host(struct ata_host *host,
+ }
+
+ /**
+- * ata_pci_init_one - Initialize/register PCI IDE host controller
++ * ata_pci_sff_init_one - Initialize/register PCI IDE host controller
+ * @pdev: Controller to be initialized
+ * @ppi: array of port_info, must be enough for two ports
++ * @sht: scsi_host_template to use when registering the host
++ * @host_priv: host private_data
+ *
+ * This is a helper function which can be called from a driver's
+ * xxx_init_one() probe function if the hardware uses traditional
+@@ -837,8 +2669,9 @@ int ata_pci_activate_sff_host(struct ata_host *host,
+ * RETURNS:
+ * Zero on success, negative on errno-based value on error.
+ */
+-int ata_pci_init_one(struct pci_dev *pdev,
+- const struct ata_port_info * const * ppi)
++int ata_pci_sff_init_one(struct pci_dev *pdev,
++ const struct ata_port_info * const * ppi,
++ struct scsi_host_template *sht, void *host_priv)
+ {
+ struct device *dev = &pdev->dev;
+ const struct ata_port_info *pi = NULL;
+@@ -869,13 +2702,13 @@ int ata_pci_init_one(struct pci_dev *pdev,
+ goto out;
+
+ /* prepare and activate SFF host */
+- rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
++ rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
+ if (rc)
+ goto out;
++ host->private_data = host_priv;
+
+ pci_set_master(pdev);
+- rc = ata_pci_activate_sff_host(host, pi->port_ops->irq_handler,
+- pi->sht);
++ rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht);
+ out:
+ if (rc == 0)
+ devres_remove_group(&pdev->dev, NULL);
+@@ -885,41 +2718,52 @@ int ata_pci_init_one(struct pci_dev *pdev,
+ return rc;
+ }
+
+-/**
+- * ata_pci_clear_simplex - attempt to kick device out of simplex
+- * @pdev: PCI device
+- *
+- * Some PCI ATA devices report simplex mode but in fact can be told to
+- * enter non simplex mode. This implements the necessary logic to
+- * perform the task on such devices. Calling it on other devices will
+- * have -undefined- behaviour.
+- */
+-
+-int ata_pci_clear_simplex(struct pci_dev *pdev)
+-{
+- unsigned long bmdma = pci_resource_start(pdev, 4);
+- u8 simplex;
+-
+- if (bmdma == 0)
+- return -ENOENT;
+-
+- simplex = inb(bmdma + 0x02);
+- outb(simplex & 0x60, bmdma + 0x02);
+- simplex = inb(bmdma + 0x02);
+- if (simplex & 0x80)
+- return -EOPNOTSUPP;
+- return 0;
+-}
+-
+-unsigned long ata_pci_default_filter(struct ata_device *adev, unsigned long xfer_mask)
+-{
+- /* Filter out DMA modes if the device has been configured by
+- the BIOS as PIO only */
+-
+- if (adev->link->ap->ioaddr.bmdma_addr == NULL)
+- xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
+- return xfer_mask;
+-}
+-
+ #endif /* CONFIG_PCI */
+
++EXPORT_SYMBOL_GPL(ata_sff_port_ops);
++EXPORT_SYMBOL_GPL(ata_bmdma_port_ops);
++EXPORT_SYMBOL_GPL(ata_sff_qc_prep);
++EXPORT_SYMBOL_GPL(ata_sff_dumb_qc_prep);
++EXPORT_SYMBOL_GPL(ata_sff_dev_select);
++EXPORT_SYMBOL_GPL(ata_sff_check_status);
++EXPORT_SYMBOL_GPL(ata_sff_altstatus);
++EXPORT_SYMBOL_GPL(ata_sff_busy_sleep);
++EXPORT_SYMBOL_GPL(ata_sff_wait_ready);
++EXPORT_SYMBOL_GPL(ata_sff_tf_load);
++EXPORT_SYMBOL_GPL(ata_sff_tf_read);
++EXPORT_SYMBOL_GPL(ata_sff_exec_command);
++EXPORT_SYMBOL_GPL(ata_sff_data_xfer);
++EXPORT_SYMBOL_GPL(ata_sff_data_xfer_noirq);
++EXPORT_SYMBOL_GPL(ata_sff_irq_on);
++EXPORT_SYMBOL_GPL(ata_sff_irq_clear);
++EXPORT_SYMBOL_GPL(ata_sff_hsm_move);
++EXPORT_SYMBOL_GPL(ata_sff_qc_issue);
++EXPORT_SYMBOL_GPL(ata_sff_qc_fill_rtf);
++EXPORT_SYMBOL_GPL(ata_sff_host_intr);
++EXPORT_SYMBOL_GPL(ata_sff_interrupt);
++EXPORT_SYMBOL_GPL(ata_sff_freeze);
++EXPORT_SYMBOL_GPL(ata_sff_thaw);
++EXPORT_SYMBOL_GPL(ata_sff_prereset);
++EXPORT_SYMBOL_GPL(ata_sff_dev_classify);
++EXPORT_SYMBOL_GPL(ata_sff_wait_after_reset);
++EXPORT_SYMBOL_GPL(ata_sff_softreset);
++EXPORT_SYMBOL_GPL(sata_sff_hardreset);
++EXPORT_SYMBOL_GPL(ata_sff_postreset);
++EXPORT_SYMBOL_GPL(ata_sff_error_handler);
++EXPORT_SYMBOL_GPL(ata_sff_post_internal_cmd);
++EXPORT_SYMBOL_GPL(ata_sff_port_start);
++EXPORT_SYMBOL_GPL(ata_sff_std_ports);
++EXPORT_SYMBOL_GPL(ata_bmdma_mode_filter);
++EXPORT_SYMBOL_GPL(ata_bmdma_setup);
++EXPORT_SYMBOL_GPL(ata_bmdma_start);
++EXPORT_SYMBOL_GPL(ata_bmdma_stop);
++EXPORT_SYMBOL_GPL(ata_bmdma_status);
++EXPORT_SYMBOL_GPL(ata_bus_reset);
++#ifdef CONFIG_PCI
++EXPORT_SYMBOL_GPL(ata_pci_bmdma_clear_simplex);
++EXPORT_SYMBOL_GPL(ata_pci_bmdma_init);
++EXPORT_SYMBOL_GPL(ata_pci_sff_init_host);
++EXPORT_SYMBOL_GPL(ata_pci_sff_prepare_host);
++EXPORT_SYMBOL_GPL(ata_pci_sff_activate_host);
++EXPORT_SYMBOL_GPL(ata_pci_sff_init_one);
++#endif /* CONFIG_PCI */
+diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
+index aa884f7..ae2cfd9 100644
+--- a/drivers/ata/libata.h
++++ b/drivers/ata/libata.h
+@@ -38,6 +38,17 @@ struct ata_scsi_args {
+ void (*done)(struct scsi_cmnd *);
+ };
+
++static inline int ata_is_builtin_hardreset(ata_reset_fn_t reset)
++{
++ if (reset == sata_std_hardreset)
++ return 1;
++#ifdef CONFIG_ATA_SFF
++ if (reset == sata_sff_hardreset)
++ return 1;
++#endif
++ return 0;
++}
++
+ /* libata-core.c */
+ enum {
+ /* flags for ata_dev_read_id() */
+@@ -61,12 +72,16 @@ extern int libata_fua;
+ extern int libata_noacpi;
+ extern int libata_allow_tpm;
+ extern void ata_force_cbl(struct ata_port *ap);
++extern u64 ata_tf_to_lba(const struct ata_taskfile *tf);
++extern u64 ata_tf_to_lba48(const struct ata_taskfile *tf);
+ extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
+ extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
+ u64 block, u32 n_block, unsigned int tf_flags,
+ unsigned int tag);
+ extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev);
+ extern void ata_dev_disable(struct ata_device *dev);
++extern void ata_pio_queue_task(struct ata_port *ap, void *data,
++ unsigned long delay);
+ extern void ata_port_flush_task(struct ata_port *ap);
+ extern unsigned ata_exec_internal(struct ata_device *dev,
+ struct ata_taskfile *tf, const u8 *cdb,
+@@ -77,6 +92,8 @@ extern unsigned ata_exec_internal_sg(struct ata_device *dev,
+ int dma_dir, struct scatterlist *sg,
+ unsigned int n_elem, unsigned long timeout);
+ extern unsigned int ata_do_simple_cmd(struct ata_device *dev, u8 cmd);
++extern int ata_wait_ready(struct ata_link *link, unsigned long deadline,
++ int (*check_ready)(struct ata_link *link));
+ extern int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
+ unsigned int flags, u16 *id);
+ extern int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags);
+@@ -84,17 +101,13 @@ extern int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
+ unsigned int readid_flags);
+ extern int ata_dev_configure(struct ata_device *dev);
+ extern int sata_down_spd_limit(struct ata_link *link);
+-extern int sata_set_spd_needed(struct ata_link *link);
+ extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel);
+ extern void ata_sg_clean(struct ata_queued_cmd *qc);
+ extern void ata_qc_free(struct ata_queued_cmd *qc);
+ extern void ata_qc_issue(struct ata_queued_cmd *qc);
+ extern void __ata_qc_complete(struct ata_queued_cmd *qc);
+ extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
+-extern void ata_dev_select(struct ata_port *ap, unsigned int device,
+- unsigned int wait, unsigned int can_sleep);
+ extern void swap_buf_le16(u16 *buf, unsigned int buf_words);
+-extern int ata_flush_cache(struct ata_device *dev);
+ extern void ata_dev_init(struct ata_device *dev);
+ extern void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp);
+ extern int sata_link_init_spd(struct ata_link *link);
+@@ -165,11 +178,6 @@ extern void ata_schedule_scsi_eh(struct Scsi_Host *shost);
+ extern void ata_scsi_dev_rescan(struct work_struct *work);
+ extern int ata_bus_probe(struct ata_port *ap);
+
+-/* libata-pmp.c */
+-extern int sata_pmp_scr_read(struct ata_link *link, int reg, u32 *val);
+-extern int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val);
+-extern int sata_pmp_attach(struct ata_device *dev);
+-
+ /* libata-eh.c */
+ extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
+ extern void ata_scsi_error(struct Scsi_Host *host);
+@@ -193,8 +201,34 @@ extern int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
+ struct ata_link **r_failed_disk);
+ extern void ata_eh_finish(struct ata_port *ap);
+
++/* libata-pmp.c */
++#ifdef CONFIG_SATA_PMP
++extern int sata_pmp_scr_read(struct ata_link *link, int reg, u32 *val);
++extern int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val);
++extern int sata_pmp_attach(struct ata_device *dev);
++#else /* CONFIG_SATA_PMP */
++static inline int sata_pmp_scr_read(struct ata_link *link, int reg, u32 *val)
++{
++ return -EINVAL;
++}
++
++static inline int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val)
++{
++ return -EINVAL;
++}
++
++static inline int sata_pmp_attach(struct ata_device *dev)
++{
++ return -EINVAL;
++}
++#endif /* CONFIG_SATA_PMP */
++
+ /* libata-sff.c */
++#ifdef CONFIG_ATA_SFF
++extern void ata_dev_select(struct ata_port *ap, unsigned int device,
++ unsigned int wait, unsigned int can_sleep);
+ extern u8 ata_irq_on(struct ata_port *ap);
+-
++extern void ata_pio_task(struct work_struct *work);
++#endif /* CONFIG_ATA_SFF */
+
+ #endif /* __LIBATA_H__ */
+diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c
+index bdc3b9d..c5f91e6 100644
+--- a/drivers/ata/pata_acpi.c
++++ b/drivers/ata/pata_acpi.c
+@@ -47,7 +47,7 @@ static int pacpi_pre_reset(struct ata_link *link, unsigned long deadline)
+ if (ap->acpi_handle == NULL || ata_acpi_gtm(ap, &acpi->gtm) < 0)
+ return -ENODEV;
+
+- return ata_std_prereset(link, deadline);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -68,20 +68,6 @@ static int pacpi_cable_detect(struct ata_port *ap)
+ }
+
+ /**
+- * pacpi_error_handler - Setup and error handler
+- * @ap: Port to handle
+- *
+- * LOCKING:
+- * None (inherited from caller).
+- */
+-
+-static void pacpi_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, pacpi_pre_reset, ata_std_softreset, NULL,
+- ata_std_postreset);
+-}
+-
+-/**
+ * pacpi_discover_modes - filter non ACPI modes
+ * @adev: ATA device
+ * @mask: proposed modes
+@@ -120,7 +106,7 @@ static unsigned long pacpi_discover_modes(struct ata_port *ap, struct ata_device
+ static unsigned long pacpi_mode_filter(struct ata_device *adev, unsigned long mask)
+ {
+ struct pata_acpi *acpi = adev->link->ap->private_data;
+- return ata_pci_default_filter(adev, mask & acpi->mask[adev->devno]);
++ return ata_bmdma_mode_filter(adev, mask & acpi->mask[adev->devno]);
+ }
+
+ /**
+@@ -176,7 +162,7 @@ static void pacpi_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ /**
+- * pacpi_qc_issue_prot - command issue
++ * pacpi_qc_issue - command issue
+ * @qc: command pending
+ *
+ * Called when the libata layer is about to issue a command. We wrap
+@@ -184,14 +170,14 @@ static void pacpi_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ * neccessary.
+ */
+
+-static unsigned int pacpi_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int pacpi_qc_issue(struct ata_queued_cmd *qc)
+ {
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+ struct pata_acpi *acpi = ap->private_data;
+
+ if (acpi->gtm.flags & 0x10)
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+
+ if (adev != acpi->last) {
+ pacpi_set_piomode(ap, adev);
+@@ -199,7 +185,7 @@ static unsigned int pacpi_qc_issue_prot(struct ata_queued_cmd *qc)
+ pacpi_set_dmamode(ap, adev);
+ acpi->last = adev;
+ }
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ /**
+@@ -232,57 +218,17 @@ static int pacpi_port_start(struct ata_port *ap)
+ }
+
+ static struct scsi_host_template pacpi_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- /* Use standard CHS mapping rules */
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static const struct ata_port_operations pacpi_ops = {
++static struct ata_port_operations pacpi_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .qc_issue = pacpi_qc_issue,
++ .cable_detect = pacpi_cable_detect,
++ .mode_filter = pacpi_mode_filter,
+ .set_piomode = pacpi_set_piomode,
+ .set_dmamode = pacpi_set_dmamode,
+- .mode_filter = pacpi_mode_filter,
+-
+- /* Task file is PCI ATA format, use helpers */
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = pacpi_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = pacpi_cable_detect,
+-
+- /* BMDMA handling is PCI ATA format, use helpers */
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = pacpi_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- /* Timeout handling */
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- /* Generic PATA PCI ATA helpers */
++ .prereset = pacpi_pre_reset,
+ .port_start = pacpi_port_start,
+ };
+
+@@ -304,7 +250,6 @@ static const struct ata_port_operations pacpi_ops = {
+ static int pacpi_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info = {
+- .sht = &pacpi_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+
+ .pio_mask = 0x1f,
+@@ -314,7 +259,7 @@ static int pacpi_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+ .port_ops = &pacpi_ops,
+ };
+ const struct ata_port_info *ppi[] = { &info, NULL };
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &pacpi_sht, NULL);
+ }
+
+ static const struct pci_device_id pacpi_pci_tbl[] = {
+diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c
+index 511a830..fcabe46 100644
+--- a/drivers/ata/pata_ali.c
++++ b/drivers/ata/pata_ali.c
+@@ -121,7 +121,7 @@ static unsigned long ali_20_filter(struct ata_device *adev, unsigned long mask)
+ ata_id_c_string(adev->id, model_num, ATA_ID_PROD, sizeof(model_num));
+ if (strstr(model_num, "WDC"))
+ return mask &= ~ATA_MASK_UDMA;
+- return ata_pci_default_filter(adev, mask);
++ return ata_bmdma_mode_filter(adev, mask);
+ }
+
+ /**
+@@ -339,21 +339,7 @@ static int ali_check_atapi_dma(struct ata_queued_cmd *qc)
+ }
+
+ static struct scsi_host_template ali_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ /*
+@@ -361,29 +347,15 @@ static struct scsi_host_template ali_sht = {
+ */
+
+ static struct ata_port_operations ali_early_port_ops = {
+- .set_piomode = ali_set_piomode,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_sff_port_ops,
+ .cable_detect = ata_cable_40wire,
++ .set_piomode = ali_set_piomode,
++};
+
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++static const struct ata_port_operations ali_dma_base_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .set_piomode = ali_set_piomode,
++ .set_dmamode = ali_set_dmamode,
+ };
+
+ /*
+@@ -391,115 +363,31 @@ static struct ata_port_operations ali_early_port_ops = {
+ * detect
+ */
+ static struct ata_port_operations ali_20_port_ops = {
+- .set_piomode = ali_set_piomode,
+- .set_dmamode = ali_set_dmamode,
++ .inherits = &ali_dma_base_ops,
++ .cable_detect = ata_cable_40wire,
+ .mode_filter = ali_20_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+ .check_atapi_dma = ali_check_atapi_dma,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+ .dev_config = ali_lock_sectors,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /*
+ * Port operations for DMA capable ALi with cable detect
+ */
+ static struct ata_port_operations ali_c2_port_ops = {
+- .set_piomode = ali_set_piomode,
+- .set_dmamode = ali_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
++ .inherits = &ali_dma_base_ops,
+ .check_atapi_dma = ali_check_atapi_dma,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+- .dev_config = ali_lock_sectors,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .cable_detect = ali_c2_cable_detect,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .dev_config = ali_lock_sectors,
+ };
+
+ /*
+ * Port operations for DMA capable ALi with cable detect and LBA48
+ */
+ static struct ata_port_operations ali_c5_port_ops = {
+- .set_piomode = ali_set_piomode,
+- .set_dmamode = ali_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
++ .inherits = &ali_dma_base_ops,
+ .check_atapi_dma = ali_check_atapi_dma,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+ .dev_config = ali_warn_atapi_dma,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .cable_detect = ali_c2_cable_detect,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+
+@@ -561,7 +449,7 @@ static void ali_init_chipset(struct pci_dev *pdev)
+ }
+ pci_dev_put(isa_bridge);
+ pci_dev_put(north);
+- ata_pci_clear_simplex(pdev);
++ ata_pci_bmdma_clear_simplex(pdev);
+ }
+ /**
+ * ali_init_one - discovery callback
+@@ -575,14 +463,12 @@ static void ali_init_chipset(struct pci_dev *pdev)
+ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info_early = {
+- .sht = &ali_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .port_ops = &ali_early_port_ops
+ };
+ /* Revision 0x20 added DMA */
+ static const struct ata_port_info info_20 = {
+- .sht = &ali_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -590,7 +476,6 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ };
+ /* Revision 0x20 with support logic added UDMA */
+ static const struct ata_port_info info_20_udma = {
+- .sht = &ali_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -599,7 +484,6 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ };
+ /* Revision 0xC2 adds UDMA66 */
+ static const struct ata_port_info info_c2 = {
+- .sht = &ali_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -608,7 +492,6 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ };
+ /* Revision 0xC3 is UDMA66 for now */
+ static const struct ata_port_info info_c3 = {
+- .sht = &ali_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -617,7 +500,6 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ };
+ /* Revision 0xC4 is UDMA100 */
+ static const struct ata_port_info info_c4 = {
+- .sht = &ali_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -626,7 +508,6 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ };
+ /* Revision 0xC5 is UDMA133 with LBA48 DMA */
+ static const struct ata_port_info info_c5 = {
+- .sht = &ali_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -637,6 +518,11 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ const struct ata_port_info *ppi[] = { NULL, NULL };
+ u8 tmp;
+ struct pci_dev *isa_bridge;
++ int rc;
++
++ rc = pcim_enable_device(pdev);
++ if (rc)
++ return rc;
+
+ /*
+ * The chipset revision selects the driver operations and
+@@ -666,14 +552,21 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ ppi[0] = &info_20_udma;
+ pci_dev_put(isa_bridge);
+ }
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &ali_sht, NULL);
+ }
+
+ #ifdef CONFIG_PM
+ static int ali_reinit_one(struct pci_dev *pdev)
+ {
++ struct ata_host *host = dev_get_drvdata(&pdev->dev);
++ int rc;
++
++ rc = ata_pci_device_do_resume(pdev);
++ if (rc)
++ return rc;
+ ali_init_chipset(pdev);
+- return ata_pci_device_resume(pdev);
++ ata_host_resume(host);
++ return 0;
+ }
+ #endif
+
+diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
+index 4b8d9b5..26665c3 100644
+--- a/drivers/ata/pata_amd.c
++++ b/drivers/ata/pata_amd.c
+@@ -56,7 +56,9 @@ static void timing_setup(struct ata_port *ap, struct ata_device *adev, int offse
+ u8 t;
+
+ T = 1000000000 / amd_clock;
+- UT = T / min_t(int, max_t(int, clock, 1), 2);
++ UT = T;
++ if (clock >= 2)
++ UT = T / 2;
+
+ if (ata_timing_compute(adev, speed, &at, T, UT) < 0) {
+ dev_printk(KERN_ERR, &pdev->dev, "unknown mode %d.\n", speed);
+@@ -141,13 +143,7 @@ static int amd_pre_reset(struct ata_link *link, unsigned long deadline)
+ if (!pci_test_config_bits(pdev, &amd_enable_bits[ap->port_no]))
+ return -ENOENT;
+
+- return ata_std_prereset(link, deadline);
+-}
+-
+-static void amd_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, amd_pre_reset, ata_std_softreset, NULL,
+- ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ static int amd_cable_detect(struct ata_port *ap)
+@@ -297,14 +293,7 @@ static int nv_pre_reset(struct ata_link *link, unsigned long deadline)
+ if (!pci_test_config_bits(pdev, &nv_enable_bits[ap->port_no]))
+ return -ENOENT;
+
+- return ata_std_prereset(link, deadline);
+-}
+-
+-static void nv_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, nv_pre_reset,
+- ata_std_softreset, NULL,
+- ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -353,228 +342,66 @@ static void nv_host_stop(struct ata_host *host)
+ }
+
+ static struct scsi_host_template amd_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
++};
++
++static const struct ata_port_operations amd_base_port_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .prereset = amd_pre_reset,
+ };
+
+ static struct ata_port_operations amd33_port_ops = {
++ .inherits = &amd_base_port_ops,
++ .cable_detect = ata_cable_40wire,
+ .set_piomode = amd33_set_piomode,
+ .set_dmamode = amd33_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = amd_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ static struct ata_port_operations amd66_port_ops = {
++ .inherits = &amd_base_port_ops,
++ .cable_detect = ata_cable_unknown,
+ .set_piomode = amd66_set_piomode,
+ .set_dmamode = amd66_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = amd_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_unknown,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ static struct ata_port_operations amd100_port_ops = {
++ .inherits = &amd_base_port_ops,
++ .cable_detect = ata_cable_unknown,
+ .set_piomode = amd100_set_piomode,
+ .set_dmamode = amd100_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = amd_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_unknown,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ static struct ata_port_operations amd133_port_ops = {
++ .inherits = &amd_base_port_ops,
++ .cable_detect = amd_cable_detect,
+ .set_piomode = amd133_set_piomode,
+ .set_dmamode = amd133_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = amd_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = amd_cable_detect,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
++};
+
+- .port_start = ata_sff_port_start,
++static const struct ata_port_operations nv_base_port_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .cable_detect = ata_cable_ignore,
++ .mode_filter = nv_mode_filter,
++ .prereset = nv_pre_reset,
++ .host_stop = nv_host_stop,
+ };
+
+ static struct ata_port_operations nv100_port_ops = {
++ .inherits = &nv_base_port_ops,
+ .set_piomode = nv100_set_piomode,
+ .set_dmamode = nv100_set_dmamode,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = nv_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_ignore,
+- .mode_filter = nv_mode_filter,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+- .host_stop = nv_host_stop,
+ };
+
+ static struct ata_port_operations nv133_port_ops = {
++ .inherits = &nv_base_port_ops,
+ .set_piomode = nv133_set_piomode,
+ .set_dmamode = nv133_set_dmamode,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = nv_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_ignore,
+- .mode_filter = nv_mode_filter,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+- .host_stop = nv_host_stop,
+ };
+
+ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info[10] = {
+ { /* 0: AMD 7401 */
+- .sht = &amd_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07, /* No SWDMA */
+@@ -582,7 +409,6 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ .port_ops = &amd33_port_ops
+ },
+ { /* 1: Early AMD7409 - no swdma */
+- .sht = &amd_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -590,7 +416,6 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ .port_ops = &amd66_port_ops
+ },
+ { /* 2: AMD 7409, no swdma errata */
+- .sht = &amd_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -598,7 +423,6 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ .port_ops = &amd66_port_ops
+ },
+ { /* 3: AMD 7411 */
+- .sht = &amd_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -606,7 +430,6 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ .port_ops = &amd100_port_ops
+ },
+ { /* 4: AMD 7441 */
+- .sht = &amd_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -614,7 +437,6 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ .port_ops = &amd100_port_ops
+ },
+ { /* 5: AMD 8111*/
+- .sht = &amd_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -622,7 +444,6 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ .port_ops = &amd133_port_ops
+ },
+ { /* 6: AMD 8111 UDMA 100 (Serenade) */
+- .sht = &amd_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -630,7 +451,6 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ .port_ops = &amd133_port_ops
+ },
+ { /* 7: Nvidia Nforce */
+- .sht = &amd_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -638,7 +458,6 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ .port_ops = &nv100_port_ops
+ },
+ { /* 8: Nvidia Nforce2 and later */
+- .sht = &amd_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -646,7 +465,6 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ .port_ops = &nv133_port_ops
+ },
+ { /* 9: AMD CS5536 (Geode companion) */
+- .sht = &amd_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -654,15 +472,20 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ .port_ops = &amd100_port_ops
+ }
+ };
+- struct ata_port_info pi;
+- const struct ata_port_info *ppi[] = { &pi, NULL };
++ const struct ata_port_info *ppi[] = { NULL, NULL };
+ static int printed_version;
+ int type = id->driver_data;
++ void *hpriv = NULL;
+ u8 fifo;
++ int rc;
+
+ if (!printed_version++)
+ dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+
++ rc = pcim_enable_device(pdev);
++ if (rc)
++ return rc;
++
+ pci_read_config_byte(pdev, 0x41, &fifo);
+
+ /* Check for AMD7409 without swdma errata and if found adjust type */
+@@ -677,10 +500,10 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ /*
+ * Okay, type is determined now. Apply type-specific workarounds.
+ */
+- pi = info[type];
++ ppi[0] = &info[type];
+
+ if (type < 3)
+- ata_pci_clear_simplex(pdev);
++ ata_pci_bmdma_clear_simplex(pdev);
+
+ /* Check for AMD7411 */
+ if (type == 3)
+@@ -696,16 +519,23 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ u32 udma;
+
+ pci_read_config_dword(pdev, 0x60, &udma);
+- pi.private_data = (void *)(unsigned long)udma;
++ hpriv = (void *)(unsigned long)udma;
+ }
+
+ /* And fire it up */
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &amd_sht, hpriv);
+ }
+
+ #ifdef CONFIG_PM
+ static int amd_reinit_one(struct pci_dev *pdev)
+ {
++ struct ata_host *host = dev_get_drvdata(&pdev->dev);
++ int rc;
++
++ rc = ata_pci_device_do_resume(pdev);
++ if (rc)
++ return rc;
++
+ if (pdev->vendor == PCI_VENDOR_ID_AMD) {
+ u8 fifo;
+ pci_read_config_byte(pdev, 0x41, &fifo);
+@@ -716,9 +546,11 @@ static int amd_reinit_one(struct pci_dev *pdev)
+ pci_write_config_byte(pdev, 0x41, fifo | 0xF0);
+ if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7409 ||
+ pdev->device == PCI_DEVICE_ID_AMD_COBRA_7401)
+- ata_pci_clear_simplex(pdev);
++ ata_pci_bmdma_clear_simplex(pdev);
+ }
+- return ata_pci_device_resume(pdev);
++
++ ata_host_resume(host);
++ return 0;
+ }
+ #endif
+
+diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c
+index d421831..0f513bc 100644
+--- a/drivers/ata/pata_artop.c
++++ b/drivers/ata/pata_artop.c
+@@ -52,22 +52,7 @@ static int artop6210_pre_reset(struct ata_link *link, unsigned long deadline)
+ if (!pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no]))
+ return -ENOENT;
+
+- return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- * artop6210_error_handler - Probe specified port on PATA host controller
+- * @ap: Port to probe
+- *
+- * LOCKING:
+- * None (inherited from caller).
+- */
+-
+-static void artop6210_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, artop6210_pre_reset,
+- ata_std_softreset, NULL,
+- ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -93,7 +78,7 @@ static int artop6260_pre_reset(struct ata_link *link, unsigned long deadline)
+ if (pdev->device % 1 && !pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no]))
+ return -ENOENT;
+
+- return ata_std_prereset(link, deadline);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -114,21 +99,6 @@ static int artop6260_cable_detect(struct ata_port *ap)
+ }
+
+ /**
+- * artop6260_error_handler - Probe specified port on PATA host controller
+- * @ap: Port to probe
+- *
+- * LOCKING:
+- * None (inherited from caller).
+- */
+-
+-static void artop6260_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, artop6260_pre_reset,
+- ata_std_softreset, NULL,
+- ata_std_postreset);
+-}
+-
+-/**
+ * artop6210_load_piomode - Load a set of PATA PIO timings
+ * @ap: Port whose timings we are configuring
+ * @adev: Device
+@@ -314,85 +284,23 @@ static void artop6260_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+ }
+
+ static struct scsi_host_template artop_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static const struct ata_port_operations artop6210_ops = {
++static struct ata_port_operations artop6210_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .cable_detect = ata_cable_40wire,
+ .set_piomode = artop6210_set_piomode,
+ .set_dmamode = artop6210_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = artop6210_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .prereset = artop6210_pre_reset,
+ };
+
+-static const struct ata_port_operations artop6260_ops = {
++static struct ata_port_operations artop6260_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .cable_detect = artop6260_cable_detect,
+ .set_piomode = artop6260_set_piomode,
+ .set_dmamode = artop6260_set_dmamode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = artop6260_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = artop6260_cable_detect,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .prereset = artop6260_pre_reset,
+ };
+
+
+@@ -414,7 +322,6 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ static int printed_version;
+ static const struct ata_port_info info_6210 = {
+- .sht = &artop_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+@@ -422,7 +329,6 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+ .port_ops = &artop6210_ops,
+ };
+ static const struct ata_port_info info_626x = {
+- .sht = &artop_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+@@ -430,7 +336,6 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+ .port_ops = &artop6260_ops,
+ };
+ static const struct ata_port_info info_628x = {
+- .sht = &artop_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+@@ -438,7 +343,6 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+ .port_ops = &artop6260_ops,
+ };
+ static const struct ata_port_info info_628x_fast = {
+- .sht = &artop_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+@@ -446,11 +350,16 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+ .port_ops = &artop6260_ops,
+ };
+ const struct ata_port_info *ppi[] = { NULL, NULL };
++ int rc;
+
+ if (!printed_version++)
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "version " DRV_VERSION "\n");
+
++ rc = pcim_enable_device(pdev);
++ if (rc)
++ return rc;
++
+ if (id->driver_data == 0) { /* 6210 variant */
+ ppi[0] = &info_6210;
+ ppi[1] = &ata_dummy_port_info;
+@@ -491,7 +400,7 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+
+ BUG_ON(ppi[0] == NULL);
+
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &artop_sht, NULL);
+ }
+
+ static const struct pci_device_id artop_pci_tbl[] = {
+diff --git a/drivers/ata/pata_at32.c b/drivers/ata/pata_at32.c
+index db057b1..5e10438 100644
+--- a/drivers/ata/pata_at32.c
++++ b/drivers/ata/pata_at32.c
+@@ -166,52 +166,14 @@ static void pata_at32_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+ }
+
+-static void pata_at32_irq_clear(struct ata_port *ap)
+-{
+- /* No DMA controller yet */
+-}
+-
+ static struct scsi_host_template at32_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_PIO_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations at32_port_ops = {
+- .set_piomode = pata_at32_set_piomode,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .exec_command = ata_exec_command,
+- .check_status = ata_check_status,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_sff_port_ops,
+ .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_clear = pata_at32_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .set_piomode = pata_at32_set_piomode,
+ };
+
+ static int __init pata_at32_init_one(struct device *dev,
+@@ -261,7 +223,7 @@ static int __init pata_at32_init_one(struct device *dev,
+ host->private_data = info;
+
+ /* Register ATA device and return */
+- return ata_host_activate(host, info->irq, ata_interrupt,
++ return ata_host_activate(host, info->irq, ata_sff_interrupt,
+ IRQF_SHARED | IRQF_TRIGGER_RISING,
+ &at32_sht);
+ }
+@@ -419,6 +381,9 @@ static int __exit pata_at32_remove(struct platform_device *pdev)
+ return 0;
+ }
+
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:at32_ide");
++
+ static struct platform_driver pata_at32_driver = {
+ .remove = __exit_p(pata_at32_remove),
+ .driver = {
+diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
+index 408bdc1..78738fb 100644
+--- a/drivers/ata/pata_atiixp.c
++++ b/drivers/ata/pata_atiixp.c
+@@ -45,12 +45,7 @@ static int atiixp_pre_reset(struct ata_link *link, unsigned long deadline)
+ if (!pci_test_config_bits(pdev, &atiixp_enable_bits[ap->port_no]))
+ return -ENOENT;
+
+- return ata_std_prereset(link, deadline);
+-}
+-
+-static void atiixp_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, atiixp_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ static int atiixp_cable_detect(struct ata_port *ap)
+@@ -221,60 +216,26 @@ static void atiixp_bmdma_stop(struct ata_queued_cmd *qc)
+ }
+
+ static struct scsi_host_template atiixp_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
++ ATA_BMDMA_SHT(DRV_NAME),
+ .sg_tablesize = LIBATA_DUMB_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
+ };
+
+ static struct ata_port_operations atiixp_port_ops = {
+- .set_piomode = atiixp_set_piomode,
+- .set_dmamode = atiixp_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = atiixp_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = atiixp_cable_detect,
++ .inherits = &ata_bmdma_port_ops,
+
+- .bmdma_setup = ata_bmdma_setup,
++ .qc_prep = ata_sff_dumb_qc_prep,
+ .bmdma_start = atiixp_bmdma_start,
+ .bmdma_stop = atiixp_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+
+- .qc_prep = ata_dumb_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .cable_detect = atiixp_cable_detect,
++ .set_piomode = atiixp_set_piomode,
++ .set_dmamode = atiixp_set_dmamode,
++ .prereset = atiixp_pre_reset,
+ };
+
+ static int atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info = {
+- .sht = &atiixp_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x06, /* No MWDMA0 support */
+@@ -282,7 +243,7 @@ static int atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ .port_ops = &atiixp_port_ops
+ };
+ const struct ata_port_info *ppi[] = { &info, NULL };
+- return ata_pci_init_one(dev, ppi);
++ return ata_pci_sff_init_one(dev, ppi, &atiixp_sht, NULL);
+ }
+
+ static const struct pci_device_id atiixp[] = {
+diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c
+index 7f87f10..a75de06 100644
+--- a/drivers/ata/pata_bf54x.c
++++ b/drivers/ata/pata_bf54x.c
+@@ -674,7 +674,7 @@ static void read_atapi_data(void __iomem *base,
+ * @ap: Port to which output is sent
+ * @tf: ATA taskfile register set
+ *
+- * Note: Original code is ata_tf_load().
++ * Note: Original code is ata_sff_tf_load().
+ */
+
+ static void bfin_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
+@@ -745,7 +745,7 @@ static u8 bfin_check_status(struct ata_port *ap)
+ * @ap: Port from which input is read
+ * @tf: ATA taskfile register set for storing input
+ *
+- * Note: Original code is ata_tf_read().
++ * Note: Original code is ata_sff_tf_read().
+ */
+
+ static void bfin_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+@@ -775,7 +775,7 @@ static void bfin_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+ * @ap: port to which command is being issued
+ * @tf: ATA taskfile register set
+ *
+- * Note: Original code is ata_exec_command().
++ * Note: Original code is ata_sff_exec_command().
+ */
+
+ static void bfin_exec_command(struct ata_port *ap,
+@@ -785,7 +785,7 @@ static void bfin_exec_command(struct ata_port *ap,
+ dev_dbg(ap->dev, "ata%u: cmd 0x%X\n", ap->print_id, tf->command);
+
+ write_atapi_register(base, ATA_REG_CMD, tf->command);
+- ata_pause(ap);
++ ata_sff_pause(ap);
+ }
+
+ /**
+@@ -800,14 +800,14 @@ static u8 bfin_check_altstatus(struct ata_port *ap)
+ }
+
+ /**
+- * bfin_std_dev_select - Select device 0/1 on ATA bus
++ * bfin_dev_select - Select device 0/1 on ATA bus
+ * @ap: ATA channel to manipulate
+ * @device: ATA device (numbered from zero) to select
+ *
+- * Note: Original code is ata_std_dev_select().
++ * Note: Original code is ata_sff_dev_select().
+ */
+
+-static void bfin_std_dev_select(struct ata_port *ap, unsigned int device)
++static void bfin_dev_select(struct ata_port *ap, unsigned int device)
+ {
+ void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
+ u8 tmp;
+@@ -818,7 +818,7 @@ static void bfin_std_dev_select(struct ata_port *ap, unsigned int device)
+ tmp = ATA_DEVICE_OBS | ATA_DEV1;
+
+ write_atapi_register(base, ATA_REG_DEVICE, tmp);
+- ata_pause(ap);
++ ata_sff_pause(ap);
+ }
+
+ /**
+@@ -977,7 +977,7 @@ static unsigned int bfin_devchk(struct ata_port *ap,
+ void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
+ u8 nsect, lbal;
+
+- bfin_std_dev_select(ap, device);
++ bfin_dev_select(ap, device);
+
+ write_atapi_register(base, ATA_REG_NSECT, 0x55);
+ write_atapi_register(base, ATA_REG_LBAL, 0xaa);
+@@ -1014,7 +1014,7 @@ static void bfin_bus_post_reset(struct ata_port *ap, unsigned int devmask)
+ * BSY bit to clear
+ */
+ if (dev0)
+- ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
++ ata_sff_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+
+ /* if device 1 was found in ata_devchk, wait for
+ * register access, then wait for BSY to clear
+@@ -1023,7 +1023,7 @@ static void bfin_bus_post_reset(struct ata_port *ap, unsigned int devmask)
+ while (dev1) {
+ u8 nsect, lbal;
+
+- bfin_std_dev_select(ap, 1);
++ bfin_dev_select(ap, 1);
+ nsect = read_atapi_register(base, ATA_REG_NSECT);
+ lbal = read_atapi_register(base, ATA_REG_LBAL);
+ if ((nsect == 1) && (lbal == 1))
+@@ -1035,14 +1035,14 @@ static void bfin_bus_post_reset(struct ata_port *ap, unsigned int devmask)
+ msleep(50); /* give drive a breather */
+ }
+ if (dev1)
+- ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
++ ata_sff_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+
+ /* is all this really necessary? */
+- bfin_std_dev_select(ap, 0);
++ bfin_dev_select(ap, 0);
+ if (dev1)
+- bfin_std_dev_select(ap, 1);
++ bfin_dev_select(ap, 1);
+ if (dev0)
+- bfin_std_dev_select(ap, 0);
++ bfin_dev_select(ap, 0);
+ }
+
+ /**
+@@ -1088,26 +1088,21 @@ static unsigned int bfin_bus_softreset(struct ata_port *ap,
+ }
+
+ /**
+- * bfin_std_softreset - reset host port via ATA SRST
++ * bfin_softreset - reset host port via ATA SRST
+ * @ap: port to reset
+ * @classes: resulting classes of attached devices
+ *
+- * Note: Original code is ata_std_softreset().
++ * Note: Original code is ata_sff_softreset().
+ */
+
+-static int bfin_std_softreset(struct ata_link *link, unsigned int *classes,
+- unsigned long deadline)
++static int bfin_softreset(struct ata_link *link, unsigned int *classes,
++ unsigned long deadline)
+ {
+ struct ata_port *ap = link->ap;
+ unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
+ unsigned int devmask = 0, err_mask;
+ u8 err;
+
+- if (ata_link_offline(link)) {
+- classes[0] = ATA_DEV_NONE;
+- goto out;
+- }
+-
+ /* determine if device 0/1 are present */
+ if (bfin_devchk(ap, 0))
+ devmask |= (1 << 0);
+@@ -1115,7 +1110,7 @@ static int bfin_std_softreset(struct ata_link *link, unsigned int *classes,
+ devmask |= (1 << 1);
+
+ /* select device 0 again */
+- bfin_std_dev_select(ap, 0);
++ bfin_dev_select(ap, 0);
+
+ /* issue bus reset */
+ err_mask = bfin_bus_softreset(ap, devmask);
+@@ -1126,13 +1121,12 @@ static int bfin_std_softreset(struct ata_link *link, unsigned int *classes,
+ }
+
+ /* determine by signature whether we have ATA or ATAPI devices */
+- classes[0] = ata_dev_try_classify(&ap->link.device[0],
++ classes[0] = ata_sff_dev_classify(&ap->link.device[0],
+ devmask & (1 << 0), &err);
+ if (slave_possible && err != 0x81)
+- classes[1] = ata_dev_try_classify(&ap->link.device[1],
++ classes[1] = ata_sff_dev_classify(&ap->link.device[1],
+ devmask & (1 << 1), &err);
+
+- out:
+ return 0;
+ }
+
+@@ -1167,7 +1161,7 @@ static unsigned char bfin_bmdma_status(struct ata_port *ap)
+ * @buflen: buffer length
+ * @write_data: read/write
+ *
+- * Note: Original code is ata_data_xfer().
++ * Note: Original code is ata_sff_data_xfer().
+ */
+
+ static unsigned int bfin_data_xfer(struct ata_device *dev, unsigned char *buf,
+@@ -1206,7 +1200,7 @@ static unsigned int bfin_data_xfer(struct ata_device *dev, unsigned char *buf,
+ * bfin_irq_clear - Clear ATAPI interrupt.
+ * @ap: Port associated with this ATA transaction.
+ *
+- * Note: Original code is ata_bmdma_irq_clear().
++ * Note: Original code is ata_sff_irq_clear().
+ */
+
+ static void bfin_irq_clear(struct ata_port *ap)
+@@ -1223,7 +1217,7 @@ static void bfin_irq_clear(struct ata_port *ap)
+ * bfin_irq_on - Enable interrupts on a port.
+ * @ap: Port on which interrupts are enabled.
+ *
+- * Note: Original code is ata_irq_on().
++ * Note: Original code is ata_sff_irq_on().
+ */
+
+ static unsigned char bfin_irq_on(struct ata_port *ap)
+@@ -1244,13 +1238,13 @@ static unsigned char bfin_irq_on(struct ata_port *ap)
+ }
+
+ /**
+- * bfin_bmdma_freeze - Freeze DMA controller port
++ * bfin_freeze - Freeze DMA controller port
+ * @ap: port to freeze
+ *
+- * Note: Original code is ata_bmdma_freeze().
++ * Note: Original code is ata_sff_freeze().
+ */
+
+-static void bfin_bmdma_freeze(struct ata_port *ap)
++static void bfin_freeze(struct ata_port *ap)
+ {
+ void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
+
+@@ -1264,19 +1258,19 @@ static void bfin_bmdma_freeze(struct ata_port *ap)
+ * ATA_NIEN manipulation. Also, many controllers fail to mask
+ * previously pending IRQ on ATA_NIEN assertion. Clear it.
+ */
+- ata_chk_status(ap);
++ ap->ops->sff_check_status(ap);
+
+ bfin_irq_clear(ap);
+ }
+
+ /**
+- * bfin_bmdma_thaw - Thaw DMA controller port
++ * bfin_thaw - Thaw DMA controller port
+ * @ap: port to thaw
+ *
+- * Note: Original code is ata_bmdma_thaw().
++ * Note: Original code is ata_sff_thaw().
+ */
+
+-void bfin_bmdma_thaw(struct ata_port *ap)
++void bfin_thaw(struct ata_port *ap)
+ {
+ bfin_check_status(ap);
+ bfin_irq_clear(ap);
+@@ -1284,14 +1278,14 @@ void bfin_bmdma_thaw(struct ata_port *ap)
+ }
+
+ /**
+- * bfin_std_postreset - standard postreset callback
++ * bfin_postreset - standard postreset callback
+ * @ap: the target ata_port
+ * @classes: classes of attached devices
+ *
+- * Note: Original code is ata_std_postreset().
++ * Note: Original code is ata_sff_postreset().
+ */
+
+-static void bfin_std_postreset(struct ata_link *link, unsigned int *classes)
++static void bfin_postreset(struct ata_link *link, unsigned int *classes)
+ {
+ struct ata_port *ap = link->ap;
+ void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
+@@ -1301,9 +1295,9 @@ static void bfin_std_postreset(struct ata_link *link, unsigned int *classes)
+
+ /* is double-select really necessary? */
+ if (classes[0] != ATA_DEV_NONE)
+- bfin_std_dev_select(ap, 1);
++ bfin_dev_select(ap, 1);
+ if (classes[1] != ATA_DEV_NONE)
+- bfin_std_dev_select(ap, 0);
++ bfin_dev_select(ap, 0);
+
+ /* bail out if no device is present */
+ if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
+@@ -1314,17 +1308,6 @@ static void bfin_std_postreset(struct ata_link *link, unsigned int *classes)
+ write_atapi_register(base, ATA_REG_CTRL, ap->ctl);
+ }
+
+-/**
+- * bfin_error_handler - Stock error handler for DMA controller
+- * @ap: port to handle error for
+- */
+-
+-static void bfin_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, ata_std_prereset, bfin_std_softreset, NULL,
+- bfin_std_postreset);
+-}
+-
+ static void bfin_port_stop(struct ata_port *ap)
+ {
+ dev_dbg(ap->dev, "in atapi port stop\n");
+@@ -1357,51 +1340,40 @@ static int bfin_port_start(struct ata_port *ap)
+ }
+
+ static struct scsi_host_template bfin_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
++ ATA_BASE_SHT(DRV_NAME),
+ .sg_tablesize = SG_NONE,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+ .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
+ };
+
+ static const struct ata_port_operations bfin_pata_ops = {
++ .inherits = &ata_sff_port_ops,
++
+ .set_piomode = bfin_set_piomode,
+ .set_dmamode = bfin_set_dmamode,
+
+- .tf_load = bfin_tf_load,
+- .tf_read = bfin_tf_read,
+- .exec_command = bfin_exec_command,
+- .check_status = bfin_check_status,
+- .check_altstatus = bfin_check_altstatus,
+- .dev_select = bfin_std_dev_select,
++ .sff_tf_load = bfin_tf_load,
++ .sff_tf_read = bfin_tf_read,
++ .sff_exec_command = bfin_exec_command,
++ .sff_check_status = bfin_check_status,
++ .sff_check_altstatus = bfin_check_altstatus,
++ .sff_dev_select = bfin_dev_select,
+
+ .bmdma_setup = bfin_bmdma_setup,
+ .bmdma_start = bfin_bmdma_start,
+ .bmdma_stop = bfin_bmdma_stop,
+ .bmdma_status = bfin_bmdma_status,
+- .data_xfer = bfin_data_xfer,
++ .sff_data_xfer = bfin_data_xfer,
+
+ .qc_prep = ata_noop_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+
+- .freeze = bfin_bmdma_freeze,
+- .thaw = bfin_bmdma_thaw,
+- .error_handler = bfin_error_handler,
++ .freeze = bfin_freeze,
++ .thaw = bfin_thaw,
++ .softreset = bfin_softreset,
++ .postreset = bfin_postreset,
+ .post_internal_cmd = bfin_bmdma_stop,
+
+- .irq_handler = ata_interrupt,
+- .irq_clear = bfin_irq_clear,
+- .irq_on = bfin_irq_on,
++ .sff_irq_clear = bfin_irq_clear,
++ .sff_irq_on = bfin_irq_on,
+
+ .port_start = bfin_port_start,
+ .port_stop = bfin_port_stop,
+@@ -1409,7 +1381,6 @@ static const struct ata_port_operations bfin_pata_ops = {
+
+ static struct ata_port_info bfin_port_info[] = {
+ {
+- .sht = &bfin_sht,
+ .flags = ATA_FLAG_SLAVE_POSS
+ | ATA_FLAG_MMIO
+ | ATA_FLAG_NO_LEGACY,
+@@ -1446,7 +1417,7 @@ static int bfin_reset_controller(struct ata_host *host)
+ count = 10000000;
+ do {
+ status = read_atapi_register(base, ATA_REG_STATUS);
+- } while (count-- && (status & ATA_BUSY));
++ } while (--count && (status & ATA_BUSY));
+
+ /* Enable only ATAPI Device interrupt */
+ ATAPI_SET_INT_MASK(base, 1);
+@@ -1536,7 +1507,7 @@ static int __devinit bfin_atapi_probe(struct platform_device *pdev)
+ }
+
+ if (ata_host_activate(host, platform_get_irq(pdev, 0),
+- ata_interrupt, IRQF_SHARED, &bfin_sht) != 0) {
++ ata_sff_interrupt, IRQF_SHARED, &bfin_sht) != 0) {
+ peripheral_free_list(atapi_io_port);
+ dev_err(&pdev->dev, "Fail to attach ATAPI device\n");
+ return -ENODEV;
+@@ -1630,3 +1601,4 @@ MODULE_AUTHOR("Sonic Zhang <sonic.zhang at analog.com>");
+ MODULE_DESCRIPTION("PATA driver for blackfin 54x ATAPI controller");
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION(DRV_VERSION);
++MODULE_ALIAS("platform:" DRV_NAME);
+diff --git a/drivers/ata/pata_cmd640.c b/drivers/ata/pata_cmd640.c
+index 43d198f..2de30b9 100644
+--- a/drivers/ata/pata_cmd640.c
++++ b/drivers/ata/pata_cmd640.c
+@@ -107,8 +107,8 @@ static void cmd640_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ pci_write_config_byte(pdev, arttim + 1, (t.active << 4) | t.recover);
+ } else {
+ /* Save the shared timings for channel, they will be loaded
+- by qc_issue_prot. Reloading the setup time is expensive
+- so we keep a merged one loaded */
++ by qc_issue. Reloading the setup time is expensive so we
++ keep a merged one loaded */
+ pci_read_config_byte(pdev, ARTIM23, ®);
+ reg &= 0x3F;
+ reg |= t.setup;
+@@ -119,14 +119,14 @@ static void cmd640_set_piomode(struct ata_port *ap, struct ata_device *adev)
+
+
+ /**
+- * cmd640_qc_issue_prot - command preparation hook
++ * cmd640_qc_issue - command preparation hook
+ * @qc: Command to be issued
+ *
+ * Channel 1 has shared timings. We must reprogram the
+ * clock each drive 2/3 switch we do.
+ */
+
+-static unsigned int cmd640_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int cmd640_qc_issue(struct ata_queued_cmd *qc)
+ {
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+@@ -137,7 +137,7 @@ static unsigned int cmd640_qc_issue_prot(struct ata_queued_cmd *qc)
+ pci_write_config_byte(pdev, DRWTIM23, timing->reg58[adev->devno]);
+ timing->last = adev->devno;
+ }
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ /**
+@@ -166,53 +166,16 @@ static int cmd640_port_start(struct ata_port *ap)
+ }
+
+ static struct scsi_host_template cmd640_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations cmd640_port_ops = {
+- .set_piomode = cmd640_set_piomode,
+- .mode_filter = ata_pci_default_filter,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_bmdma_port_ops,
++ /* In theory xfer_noirq is not needed once we kill the prefetcher */
++ .sff_data_xfer = ata_sff_data_xfer_noirq,
++ .qc_issue = cmd640_qc_issue,
+ .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = cmd640_qc_issue_prot,
+-
+- /* In theory this is not needed once we kill the prefetcher */
+- .data_xfer = ata_data_xfer_noirq,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
++ .set_piomode = cmd640_set_piomode,
+ .port_start = cmd640_port_start,
+ };
+
+@@ -248,26 +211,36 @@ static void cmd640_hardware_init(struct pci_dev *pdev)
+ static int cmd640_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info = {
+- .sht = &cmd640_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .port_ops = &cmd640_port_ops
+ };
+ const struct ata_port_info *ppi[] = { &info, NULL };
++ int rc;
++
++ rc = pcim_enable_device(pdev);
++ if (rc)
++ return rc;
+
+ cmd640_hardware_init(pdev);
+- return ata_pci_init_one(pdev, ppi);
++
++ return ata_pci_sff_init_one(pdev, ppi, &cmd640_sht, NULL);
+ }
+
++#ifdef CONFIG_PM
+ static int cmd640_reinit_one(struct pci_dev *pdev)
+ {
++ struct ata_host *host = dev_get_drvdata(&pdev->dev);
++ int rc;
++
++ rc = ata_pci_device_do_resume(pdev);
++ if (rc)
++ return rc;
+ cmd640_hardware_init(pdev);
+-#ifdef CONFIG_PM
+- return ata_pci_device_resume(pdev);
+-#else
++ ata_host_resume(host);
+ return 0;
+-#endif
+ }
++#endif
+
+ static const struct pci_device_id cmd640[] = {
+ { PCI_VDEVICE(CMD, 0x640), 0 },
+@@ -281,8 +254,8 @@ static struct pci_driver cmd640_pci_driver = {
+ .remove = ata_pci_remove_one,
+ #ifdef CONFIG_PM
+ .suspend = ata_pci_device_suspend,
+-#endif
+ .resume = cmd640_reinit_one,
++#endif
+ };
+
+ static int __init cmd640_init(void)
+diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
+index 7acbbd9..ddd09b7 100644
+--- a/drivers/ata/pata_cmd64x.c
++++ b/drivers/ata/pata_cmd64x.c
+@@ -266,120 +266,30 @@ static void cmd646r1_bmdma_stop(struct ata_queued_cmd *qc)
+ }
+
+ static struct scsi_host_template cmd64x_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static struct ata_port_operations cmd64x_port_ops = {
++static const struct ata_port_operations cmd64x_base_ops = {
++ .inherits = &ata_bmdma_port_ops,
+ .set_piomode = cmd64x_set_piomode,
+ .set_dmamode = cmd64x_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_port_start,
+ };
+
+-static struct ata_port_operations cmd646r1_port_ops = {
+- .set_piomode = cmd64x_set_piomode,
+- .set_dmamode = cmd64x_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++static struct ata_port_operations cmd64x_port_ops = {
++ .inherits = &cmd64x_base_ops,
+ .cable_detect = ata_cable_40wire,
++};
+
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
++static struct ata_port_operations cmd646r1_port_ops = {
++ .inherits = &cmd64x_base_ops,
+ .bmdma_stop = cmd646r1_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_port_start,
++ .cable_detect = ata_cable_40wire,
+ };
+
+ static struct ata_port_operations cmd648_port_ops = {
+- .set_piomode = cmd64x_set_piomode,
+- .set_dmamode = cmd64x_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = cmd648_cable_detect,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
++ .inherits = &cmd64x_base_ops,
+ .bmdma_stop = cmd648_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_port_start,
++ .cable_detect = cmd648_cable_detect,
+ };
+
+ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+@@ -388,21 +298,18 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+
+ static const struct ata_port_info cmd_info[6] = {
+ { /* CMD 643 - no UDMA */
+- .sht = &cmd64x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .port_ops = &cmd64x_port_ops
+ },
+ { /* CMD 646 with broken UDMA */
+- .sht = &cmd64x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .port_ops = &cmd64x_port_ops
+ },
+ { /* CMD 646 with working UDMA */
+- .sht = &cmd64x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -410,14 +317,12 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ .port_ops = &cmd64x_port_ops
+ },
+ { /* CMD 646 rev 1 */
+- .sht = &cmd64x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .port_ops = &cmd646r1_port_ops
+ },
+ { /* CMD 648 */
+- .sht = &cmd64x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -425,7 +330,6 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ .port_ops = &cmd648_port_ops
+ },
+ { /* CMD 649 */
+- .sht = &cmd64x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -435,12 +339,17 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ };
+ const struct ata_port_info *ppi[] = { &cmd_info[id->driver_data], NULL };
+ u8 mrdmode;
++ int rc;
++
++ rc = pcim_enable_device(pdev);
++ if (rc)
++ return rc;
+
+ pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev);
+ class_rev &= 0xFF;
+
+ if (id->driver_data == 0) /* 643 */
+- ata_pci_clear_simplex(pdev);
++ ata_pci_bmdma_clear_simplex(pdev);
+
+ if (pdev->device == PCI_DEVICE_ID_CMD_646) {
+ /* Does UDMA work ? */
+@@ -464,13 +373,20 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ pci_write_config_byte(pdev, UDIDETCR0, 0xF0);
+ #endif
+
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &cmd64x_sht, NULL);
+ }
+
+ #ifdef CONFIG_PM
+ static int cmd64x_reinit_one(struct pci_dev *pdev)
+ {
++ struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ u8 mrdmode;
++ int rc;
++
++ rc = ata_pci_device_do_resume(pdev);
++ if (rc)
++ return rc;
++
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
+ pci_read_config_byte(pdev, MRDMODE, &mrdmode);
+ mrdmode &= ~ 0x30; /* IRQ set up */
+@@ -479,7 +395,8 @@ static int cmd64x_reinit_one(struct pci_dev *pdev)
+ #ifdef CONFIG_PPC
+ pci_write_config_byte(pdev, UDIDETCR0, 0xF0);
+ #endif
+- return ata_pci_device_resume(pdev);
++ ata_host_resume(host);
++ return 0;
+ }
+ #endif
+
+diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
+index 7ed279b..1186bcd 100644
+--- a/drivers/ata/pata_cs5520.c
++++ b/drivers/ata/pata_cs5520.c
+@@ -140,51 +140,16 @@ static void cs5520_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ static struct scsi_host_template cs5520_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
++ ATA_BMDMA_SHT(DRV_NAME),
+ .sg_tablesize = LIBATA_DUMB_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
+ };
+
+ static struct ata_port_operations cs5520_port_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .qc_prep = ata_sff_dumb_qc_prep,
++ .cable_detect = ata_cable_40wire,
+ .set_piomode = cs5520_set_piomode,
+ .set_dmamode = cs5520_set_dmamode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_dumb_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+@@ -203,6 +168,10 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
+ struct ata_ioports *ioaddr;
+ int i, rc;
+
++ rc = pcim_enable_device(pdev);
++ if (rc)
++ return rc;
++
+ /* IDE port enable bits */
+ pci_read_config_byte(pdev, 0x60, &pcicfg);
+
+@@ -258,7 +227,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
+ ioaddr->ctl_addr = iomap[1];
+ ioaddr->altstatus_addr = iomap[1];
+ ioaddr->bmdma_addr = iomap[4];
+- ata_std_ports(ioaddr);
++ ata_sff_std_ports(ioaddr);
+
+ ata_port_desc(host->ports[0],
+ "cmd 0x%x ctl 0x%x", cmd_port[0], ctl_port[0]);
+@@ -269,7 +238,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
+ ioaddr->ctl_addr = iomap[3];
+ ioaddr->altstatus_addr = iomap[3];
+ ioaddr->bmdma_addr = iomap[4] + 8;
+- ata_std_ports(ioaddr);
++ ata_sff_std_ports(ioaddr);
+
+ ata_port_desc(host->ports[1],
+ "cmd 0x%x ctl 0x%x", cmd_port[1], ctl_port[1]);
+@@ -289,7 +258,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
+ continue;
+
+ rc = devm_request_irq(&pdev->dev, irq[ap->port_no],
+- ata_interrupt, 0, DRV_NAME, host);
++ ata_sff_interrupt, 0, DRV_NAME, host);
+ if (rc)
+ return rc;
+
+@@ -310,11 +279,20 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
+
+ static int cs5520_reinit_one(struct pci_dev *pdev)
+ {
++ struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ u8 pcicfg;
++ int rc;
++
++ rc = ata_pci_device_do_resume(pdev);
++ if (rc)
++ return rc;
++
+ pci_read_config_byte(pdev, 0x60, &pcicfg);
+ if ((pcicfg & 0x40) == 0)
+ pci_write_config_byte(pdev, 0x60, pcicfg | 0x40);
+- return ata_pci_device_resume(pdev);
++
++ ata_host_resume(host);
++ return 0;
+ }
+
+ /**
+diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c
+index e1818fd..744beeb 100644
+--- a/drivers/ata/pata_cs5530.c
++++ b/drivers/ata/pata_cs5530.c
+@@ -133,7 +133,7 @@ static void cs5530_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ /**
+- * cs5530_qc_issue_prot - command issue
++ * cs5530_qc_issue - command issue
+ * @qc: command pending
+ *
+ * Called when the libata layer is about to issue a command. We wrap
+@@ -142,7 +142,7 @@ static void cs5530_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ * one MWDMA/UDMA bit.
+ */
+
+-static unsigned int cs5530_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int cs5530_qc_issue(struct ata_queued_cmd *qc)
+ {
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+@@ -157,59 +157,23 @@ static unsigned int cs5530_qc_issue_prot(struct ata_queued_cmd *qc)
+ cs5530_set_dmamode(ap, adev);
+ }
+
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ static struct scsi_host_template cs5530_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_DUMB_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
++ .sg_tablesize = LIBATA_DUMB_MAX_PRD,
+ };
+
+ static struct ata_port_operations cs5530_port_ops = {
+- .set_piomode = cs5530_set_piomode,
+- .set_dmamode = cs5530_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_dumb_qc_prep,
+- .qc_issue = cs5530_qc_issue_prot,
++ .inherits = &ata_bmdma_port_ops,
+
+- .data_xfer = ata_data_xfer,
++ .qc_prep = ata_sff_dumb_qc_prep,
++ .qc_issue = cs5530_qc_issue,
+
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .cable_detect = ata_cable_40wire,
++ .set_piomode = cs5530_set_piomode,
++ .set_dmamode = cs5530_set_dmamode,
+ };
+
+ static const struct dmi_system_id palmax_dmi_table[] = {
+@@ -334,7 +298,6 @@ fail_put:
+ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info = {
+- .sht = &cs5530_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -343,12 +306,16 @@ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ };
+ /* The docking connector doesn't do UDMA, and it seems not MWDMA */
+ static const struct ata_port_info info_palmax_secondary = {
+- .sht = &cs5530_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .port_ops = &cs5530_port_ops
+ };
+ const struct ata_port_info *ppi[] = { &info, NULL };
++ int rc;
++
++ rc = pcim_enable_device(pdev);
++ if (rc)
++ return rc;
+
+ /* Chip initialisation */
+ if (cs5530_init_chip())
+@@ -358,16 +325,25 @@ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ ppi[1] = &info_palmax_secondary;
+
+ /* Now kick off ATA set up */
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &cs5530_sht, NULL);
+ }
+
+ #ifdef CONFIG_PM
+ static int cs5530_reinit_one(struct pci_dev *pdev)
+ {
++ struct ata_host *host = dev_get_drvdata(&pdev->dev);
++ int rc;
++
++ rc = ata_pci_device_do_resume(pdev);
++ if (rc)
++ return rc;
++
+ /* If we fail on resume we are doomed */
+ if (cs5530_init_chip())
+- BUG();
+- return ata_pci_device_resume(pdev);
++ return -EIO;
++
++ ata_host_resume(host);
++ return 0;
+ }
+ #endif /* CONFIG_PM */
+
+diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c
+index 0132453..f1b6556 100644
+--- a/drivers/ata/pata_cs5535.c
++++ b/drivers/ata/pata_cs5535.c
+@@ -158,55 +158,14 @@ static void cs5535_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ static struct scsi_host_template cs5535_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations cs5535_port_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .cable_detect = cs5535_cable_detect,
+ .set_piomode = cs5535_set_piomode,
+ .set_dmamode = cs5535_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = cs5535_cable_detect,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /**
+@@ -222,7 +181,6 @@ static struct ata_port_operations cs5535_port_ops = {
+ static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info = {
+- .sht = &cs5535_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -241,7 +199,7 @@ static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ rdmsr(ATAC_CH0D1_PIO, timings, dummy);
+ if (CS5535_BAD_PIO(timings))
+ wrmsr(ATAC_CH0D1_PIO, 0xF7F4F7F4UL, 0);
+- return ata_pci_init_one(dev, ppi);
++ return ata_pci_sff_init_one(dev, ppi, &cs5535_sht, NULL);
+ }
+
+ static const struct pci_device_id cs5535[] = {
+diff --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c
+index 1c4ff9b..73f8332 100644
+--- a/drivers/ata/pata_cs5536.c
++++ b/drivers/ata/pata_cs5536.c
+@@ -221,55 +221,14 @@ static void cs5536_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ static struct scsi_host_template cs5536_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations cs5536_port_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .cable_detect = cs5536_cable_detect,
+ .set_piomode = cs5536_set_piomode,
+ .set_dmamode = cs5536_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = cs5536_cable_detect,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_port_start,
+ };
+
+ /**
+@@ -282,7 +241,6 @@ static struct ata_port_operations cs5536_port_ops = {
+ static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info = {
+- .sht = &cs5536_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -303,7 +261,7 @@ static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ return -ENODEV;
+ }
+
+- return ata_pci_init_one(dev, ppi);
++ return ata_pci_sff_init_one(dev, ppi, &cs5536_sht, NULL);
+ }
+
+ static const struct pci_device_id cs5536[] = {
+diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c
+index fc5f9c4..a9c3218 100644
+--- a/drivers/ata/pata_cypress.c
++++ b/drivers/ata/pata_cypress.c
+@@ -110,61 +110,19 @@ static void cy82c693_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ static struct scsi_host_template cy82c693_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations cy82c693_port_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .cable_detect = ata_cable_40wire,
+ .set_piomode = cy82c693_set_piomode,
+ .set_dmamode = cy82c693_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ static int cy82c693_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info = {
+- .sht = &cy82c693_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -178,7 +136,7 @@ static int cy82c693_init_one(struct pci_dev *pdev, const struct pci_device_id *i
+ if (PCI_FUNC(pdev->devfn) != 1)
+ return -ENODEV;
+
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &cy82c693_sht, NULL);
+ }
+
+ static const struct pci_device_id cy82c693[] = {
+diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c
+index dc33220..9fba829 100644
+--- a/drivers/ata/pata_efar.c
++++ b/drivers/ata/pata_efar.c
+@@ -45,20 +45,7 @@ static int efar_pre_reset(struct ata_link *link, unsigned long deadline)
+ if (!pci_test_config_bits(pdev, &efar_enable_bits[ap->port_no]))
+ return -ENOENT;
+
+- return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- * efar_probe_reset - Probe specified port on PATA host controller
+- * @ap: Port to probe
+- *
+- * LOCKING:
+- * None (inherited from caller).
+- */
+-
+-static void efar_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, efar_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -233,53 +220,15 @@ static void efar_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+ }
+
+ static struct scsi_host_template efar_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static const struct ata_port_operations efar_ops = {
++static struct ata_port_operations efar_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .cable_detect = efar_cable_detect,
+ .set_piomode = efar_set_piomode,
+ .set_dmamode = efar_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = efar_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = efar_cable_detect,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .prereset = efar_pre_reset,
+ };
+
+
+@@ -301,7 +250,6 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ static int printed_version;
+ static const struct ata_port_info info = {
+- .sht = &efar_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma1-2 */
+@@ -314,7 +262,7 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "version " DRV_VERSION "\n");
+
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &efar_sht, NULL);
+ }
+
+ static const struct pci_device_id efar_pci_tbl[] = {
+diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c
+index a742efa..f2b83ea 100644
+--- a/drivers/ata/pata_hpt366.c
++++ b/drivers/ata/pata_hpt366.c
+@@ -184,7 +184,7 @@ static unsigned long hpt366_filter(struct ata_device *adev, unsigned long mask)
+ if (hpt_dma_blacklisted(adev, "UDMA4", bad_ata66_4))
+ mask &= ~(0xF0 << ATA_SHIFT_UDMA);
+ }
+- return ata_pci_default_filter(adev, mask);
++ return ata_bmdma_mode_filter(adev, mask);
+ }
+
+ /**
+@@ -290,21 +290,7 @@ static void hpt366_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ static struct scsi_host_template hpt36x_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ /*
+@@ -312,37 +298,11 @@ static struct scsi_host_template hpt36x_sht = {
+ */
+
+ static struct ata_port_operations hpt366_port_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .cable_detect = hpt36x_cable_detect,
++ .mode_filter = hpt366_filter,
+ .set_piomode = hpt366_set_piomode,
+ .set_dmamode = hpt366_set_dmamode,
+- .mode_filter = hpt366_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = hpt36x_cable_detect,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /**
+@@ -390,18 +350,22 @@ static void hpt36x_init_chipset(struct pci_dev *dev)
+ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info_hpt366 = {
+- .sht = &hpt36x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = ATA_UDMA4,
+ .port_ops = &hpt366_port_ops
+ };
+- struct ata_port_info info = info_hpt366;
+- const struct ata_port_info *ppi[] = { &info, NULL };
++ const struct ata_port_info *ppi[] = { &info_hpt366, NULL };
+
++ void *hpriv = NULL;
+ u32 class_rev;
+ u32 reg1;
++ int rc;
++
++ rc = pcim_enable_device(dev);
++ if (rc)
++ return rc;
+
+ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+ class_rev &= 0xFF;
+@@ -419,24 +383,31 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ /* info_hpt366 is safe against re-entry so we can scribble on it */
+ switch((reg1 & 0x700) >> 8) {
+ case 5:
+- info.private_data = &hpt366_40;
++ hpriv = &hpt366_40;
+ break;
+ case 9:
+- info.private_data = &hpt366_25;
++ hpriv = &hpt366_25;
+ break;
+ default:
+- info.private_data = &hpt366_33;
++ hpriv = &hpt366_33;
+ break;
+ }
+ /* Now kick off ATA set up */
+- return ata_pci_init_one(dev, ppi);
++ return ata_pci_sff_init_one(dev, ppi, &hpt36x_sht, hpriv);
+ }
+
+ #ifdef CONFIG_PM
+ static int hpt36x_reinit_one(struct pci_dev *dev)
+ {
++ struct ata_host *host = dev_get_drvdata(&dev->dev);
++ int rc;
++
++ rc = ata_pci_device_do_resume(dev);
++ if (rc)
++ return rc;
+ hpt36x_init_chipset(dev);
+- return ata_pci_device_resume(dev);
++ ata_host_resume(host);
++ return 0;
+ }
+ #endif
+
+diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
+index 9a10878..4216399 100644
+--- a/drivers/ata/pata_hpt37x.c
++++ b/drivers/ata/pata_hpt37x.c
+@@ -283,7 +283,7 @@ static unsigned long hpt370_filter(struct ata_device *adev, unsigned long mask)
+ if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5))
+ mask &= ~(0xE0 << ATA_SHIFT_UDMA);
+ }
+- return ata_pci_default_filter(adev, mask);
++ return ata_bmdma_mode_filter(adev, mask);
+ }
+
+ /**
+@@ -299,7 +299,7 @@ static unsigned long hpt370a_filter(struct ata_device *adev, unsigned long mask)
+ if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5))
+ mask &= ~(0xE0 << ATA_SHIFT_UDMA);
+ }
+- return ata_pci_default_filter(adev, mask);
++ return ata_bmdma_mode_filter(adev, mask);
+ }
+
+ /**
+@@ -338,22 +338,10 @@ static int hpt37x_pre_reset(struct ata_link *link, unsigned long deadline)
+ pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
+ udelay(100);
+
+- return ata_std_prereset(link, deadline);
++ return ata_sff_prereset(link, deadline);
+ }
+
+-/**
+- * hpt37x_error_handler - reset the hpt374
+- * @ap: ATA port to reset
+- *
+- * Perform probe for HPT37x, except for HPT374 channel 2
+- */
+-
+-static void hpt37x_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, hpt37x_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+-}
+-
+-static int hpt374_pre_reset(struct ata_link *link, unsigned long deadline)
++static int hpt374_fn1_pre_reset(struct ata_link *link, unsigned long deadline)
+ {
+ static const struct pci_bits hpt37x_enable_bits[] = {
+ { 0x50, 1, 0x04, 0x04 },
+@@ -386,26 +374,7 @@ static int hpt374_pre_reset(struct ata_link *link, unsigned long deadline)
+ pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
+ udelay(100);
+
+- return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- * hpt374_error_handler - reset the hpt374
+- * @classes:
+- *
+- * The 374 cable detect is a little different due to the extra
+- * channels. The function 0 channels work like usual but function 1
+- * is special
+- */
+-
+-static void hpt374_error_handler(struct ata_port *ap)
+-{
+- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+-
+- if (!(PCI_FUNC(pdev->devfn) & 1))
+- hpt37x_error_handler(ap);
+- else
+- ata_bmdma_drive_eh(ap, hpt374_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -619,21 +588,7 @@ static void hpt37x_bmdma_stop(struct ata_queued_cmd *qc)
+
+
+ static struct scsi_host_template hpt37x_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ /*
+@@ -641,36 +596,15 @@ static struct scsi_host_template hpt37x_sht = {
+ */
+
+ static struct ata_port_operations hpt370_port_ops = {
+- .set_piomode = hpt370_set_piomode,
+- .set_dmamode = hpt370_set_dmamode,
+- .mode_filter = hpt370_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
++ .inherits = &ata_bmdma_port_ops,
+
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = hpt37x_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+-
+- .bmdma_setup = ata_bmdma_setup,
+ .bmdma_start = hpt370_bmdma_start,
+ .bmdma_stop = hpt370_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+
+- .port_start = ata_sff_port_start,
++ .mode_filter = hpt370_filter,
++ .set_piomode = hpt370_set_piomode,
++ .set_dmamode = hpt370_set_dmamode,
++ .prereset = hpt37x_pre_reset,
+ };
+
+ /*
+@@ -678,36 +612,8 @@ static struct ata_port_operations hpt370_port_ops = {
+ */
+
+ static struct ata_port_operations hpt370a_port_ops = {
+- .set_piomode = hpt370_set_piomode,
+- .set_dmamode = hpt370_set_dmamode,
++ .inherits = &hpt370_port_ops,
+ .mode_filter = hpt370a_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = hpt37x_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = hpt370_bmdma_start,
+- .bmdma_stop = hpt370_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /*
+@@ -716,74 +622,23 @@ static struct ata_port_operations hpt370a_port_ops = {
+ */
+
+ static struct ata_port_operations hpt372_port_ops = {
+- .set_piomode = hpt372_set_piomode,
+- .set_dmamode = hpt372_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
++ .inherits = &ata_bmdma_port_ops,
+
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = hpt37x_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+ .bmdma_stop = hpt37x_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+
+- .port_start = ata_sff_port_start,
++ .set_piomode = hpt372_set_piomode,
++ .set_dmamode = hpt372_set_dmamode,
++ .prereset = hpt37x_pre_reset,
+ };
+
+ /*
+ * Configuration for HPT374. Mode setting works like 372 and friends
+- * but we have a different cable detection procedure.
++ * but we have a different cable detection procedure for function 1.
+ */
+
+-static struct ata_port_operations hpt374_port_ops = {
+- .set_piomode = hpt372_set_piomode,
+- .set_dmamode = hpt372_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = hpt374_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = hpt37x_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++static struct ata_port_operations hpt374_fn1_port_ops = {
++ .inherits = &hpt372_port_ops,
++ .prereset = hpt374_fn1_pre_reset,
+ };
+
+ /**
+@@ -897,7 +752,6 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ /* HPT370 - UDMA100 */
+ static const struct ata_port_info info_hpt370 = {
+- .sht = &hpt37x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -906,7 +760,6 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ };
+ /* HPT370A - UDMA100 */
+ static const struct ata_port_info info_hpt370a = {
+- .sht = &hpt37x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -915,7 +768,6 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ };
+ /* HPT370 - UDMA100 */
+ static const struct ata_port_info info_hpt370_33 = {
+- .sht = &hpt37x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -924,7 +776,6 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ };
+ /* HPT370A - UDMA100 */
+ static const struct ata_port_info info_hpt370a_33 = {
+- .sht = &hpt37x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -933,28 +784,31 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ };
+ /* HPT371, 372 and friends - UDMA133 */
+ static const struct ata_port_info info_hpt372 = {
+- .sht = &hpt37x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &hpt372_port_ops
+ };
+- /* HPT374 - UDMA100 */
+- static const struct ata_port_info info_hpt374 = {
+- .sht = &hpt37x_sht,
++ /* HPT374 - UDMA100, function 1 uses different prereset method */
++ static const struct ata_port_info info_hpt374_fn0 = {
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = ATA_UDMA5,
+- .port_ops = &hpt374_port_ops
++ .port_ops = &hpt372_port_ops
++ };
++ static const struct ata_port_info info_hpt374_fn1 = {
++ .flags = ATA_FLAG_SLAVE_POSS,
++ .pio_mask = 0x1f,
++ .mwdma_mask = 0x07,
++ .udma_mask = ATA_UDMA5,
++ .port_ops = &hpt374_fn1_port_ops
+ };
+
+ static const int MHz[4] = { 33, 40, 50, 66 };
+- const struct ata_port_info *port;
+ void *private_data = NULL;
+- struct ata_port_info port_info;
+- const struct ata_port_info *ppi[] = { &port_info, NULL };
++ const struct ata_port_info *ppi[] = { NULL, NULL };
+
+ u8 irqmask;
+ u32 class_rev;
+@@ -966,6 +820,11 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+
+ const struct hpt_chip *chip_table;
+ int clock_slot;
++ int rc;
++
++ rc = pcim_enable_device(dev);
++ if (rc)
++ return rc;
+
+ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+ class_rev &= 0xFF;
+@@ -981,17 +840,17 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+
+ switch(class_rev) {
+ case 3:
+- port = &info_hpt370;
++ ppi[0] = &info_hpt370;
+ chip_table = &hpt370;
+ prefer_dpll = 0;
+ break;
+ case 4:
+- port = &info_hpt370a;
++ ppi[0] = &info_hpt370a;
+ chip_table = &hpt370a;
+ prefer_dpll = 0;
+ break;
+ case 5:
+- port = &info_hpt372;
++ ppi[0] = &info_hpt372;
+ chip_table = &hpt372;
+ break;
+ default:
+@@ -1004,21 +863,21 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ /* 372N if rev >= 2*/
+ if (class_rev >= 2)
+ return -ENODEV;
+- port = &info_hpt372;
++ ppi[0] = &info_hpt372;
+ chip_table = &hpt372a;
+ break;
+ case PCI_DEVICE_ID_TTI_HPT302:
+ /* 302N if rev > 1 */
+ if (class_rev > 1)
+ return -ENODEV;
+- port = &info_hpt372;
++ ppi[0] = &info_hpt372;
+ /* Check this */
+ chip_table = &hpt302;
+ break;
+ case PCI_DEVICE_ID_TTI_HPT371:
+ if (class_rev > 1)
+ return -ENODEV;
+- port = &info_hpt372;
++ ppi[0] = &info_hpt372;
+ chip_table = &hpt371;
+ /* Single channel device, master is not present
+ but the BIOS (or us for non x86) must mark it
+@@ -1029,7 +888,10 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ break;
+ case PCI_DEVICE_ID_TTI_HPT374:
+ chip_table = &hpt374;
+- port = &info_hpt374;
++ if (!(PCI_FUNC(dev->devfn) & 1))
++ *ppi = &info_hpt374_fn0;
++ else
++ *ppi = &info_hpt374_fn1;
+ break;
+ default:
+ printk(KERN_ERR "pata_hpt37x: PCI table is bogus please report (%d).\n", dev->device);
+@@ -1108,7 +970,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ int dpll, adjust;
+
+ /* Compute DPLL */
+- dpll = (port->udma_mask & 0xC0) ? 3 : 2;
++ dpll = (ppi[0]->udma_mask & 0xC0) ? 3 : 2;
+
+ f_low = (MHz[clock_slot] * 48) / MHz[dpll];
+ f_high = f_low + 2;
+@@ -1148,19 +1010,16 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ * about lack of UDMA133 support on lower clocks
+ */
+
+- if (clock_slot < 2 && port == &info_hpt370)
+- port = &info_hpt370_33;
+- if (clock_slot < 2 && port == &info_hpt370a)
+- port = &info_hpt370a_33;
++ if (clock_slot < 2 && ppi[0] == &info_hpt370)
++ ppi[0] = &info_hpt370_33;
++ if (clock_slot < 2 && ppi[0] == &info_hpt370a)
++ ppi[0] = &info_hpt370a_33;
+ printk(KERN_INFO "pata_hpt37x: %s using %dMHz bus clock.\n",
+ chip_table->name, MHz[clock_slot]);
+ }
+
+ /* Now kick off ATA set up */
+- port_info = *port;
+- port_info.private_data = private_data;
+-
+- return ata_pci_init_one(dev, ppi);
++ return ata_pci_sff_init_one(dev, ppi, &hpt37x_sht, private_data);
+ }
+
+ static const struct pci_device_id hpt37x[] = {
+diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c
+index 9f1c084..d5c9fd7 100644
+--- a/drivers/ata/pata_hpt3x2n.c
++++ b/drivers/ata/pata_hpt3x2n.c
+@@ -148,7 +148,7 @@ static int hpt3x2n_cable_detect(struct ata_port *ap)
+ * Reset the hardware and state machine,
+ */
+
+-static int hpt3xn_pre_reset(struct ata_link *link, unsigned long deadline)
++static int hpt3x2n_pre_reset(struct ata_link *link, unsigned long deadline)
+ {
+ struct ata_port *ap = link->ap;
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+@@ -156,19 +156,7 @@ static int hpt3xn_pre_reset(struct ata_link *link, unsigned long deadline)
+ pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
+ udelay(100);
+
+- return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- * hpt3x2n_error_handler - probe the hpt3x2n bus
+- * @ap: ATA port to reset
+- *
+- * Perform the probe reset handling for the 3x2N
+- */
+-
+-static void hpt3x2n_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, hpt3xn_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -320,7 +308,7 @@ static int hpt3x2n_use_dpll(struct ata_port *ap, int writing)
+ return 0;
+ }
+
+-static unsigned int hpt3x2n_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int hpt3x2n_qc_issue(struct ata_queued_cmd *qc)
+ {
+ struct ata_taskfile *tf = &qc->tf;
+ struct ata_port *ap = qc->ap;
+@@ -335,25 +323,11 @@ static unsigned int hpt3x2n_qc_issue_prot(struct ata_queued_cmd *qc)
+ hpt3x2n_set_clock(ap, 0x23);
+ }
+ }
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ static struct scsi_host_template hpt3x2n_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ /*
+@@ -361,37 +335,15 @@ static struct scsi_host_template hpt3x2n_sht = {
+ */
+
+ static struct ata_port_operations hpt3x2n_port_ops = {
+- .set_piomode = hpt3x2n_set_piomode,
+- .set_dmamode = hpt3x2n_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = hpt3x2n_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = hpt3x2n_cable_detect,
++ .inherits = &ata_bmdma_port_ops,
+
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+ .bmdma_stop = hpt3x2n_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = hpt3x2n_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
++ .qc_issue = hpt3x2n_qc_issue,
+
+- .port_start = ata_sff_port_start,
++ .cable_detect = hpt3x2n_cable_detect,
++ .set_piomode = hpt3x2n_set_piomode,
++ .set_dmamode = hpt3x2n_set_dmamode,
++ .prereset = hpt3x2n_pre_reset,
+ };
+
+ /**
+@@ -488,15 +440,13 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ /* HPT372N and friends - UDMA133 */
+ static const struct ata_port_info info = {
+- .sht = &hpt3x2n_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &hpt3x2n_port_ops
+ };
+- struct ata_port_info port = info;
+- const struct ata_port_info *ppi[] = { &port, NULL };
++ const struct ata_port_info *ppi[] = { &info, NULL };
+
+ u8 irqmask;
+ u32 class_rev;
+@@ -505,6 +455,12 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ unsigned int f_low, f_high;
+ int adjust;
+ unsigned long iobase = pci_resource_start(dev, 4);
++ void *hpriv = NULL;
++ int rc;
++
++ rc = pcim_enable_device(dev);
++ if (rc)
++ return rc;
+
+ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+ class_rev &= 0xFF;
+@@ -586,9 +542,8 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ pci_mhz);
+ /* Set our private data up. We only need a few flags so we use
+ it directly */
+- port.private_data = NULL;
+ if (pci_mhz > 60) {
+- port.private_data = (void *)PCI66;
++ hpriv = (void *)PCI66;
+ /*
+ * On HPT371N, if ATA clock is 66 MHz we must set bit 2 in
+ * the MISC. register to stretch the UltraDMA Tss timing.
+@@ -599,7 +554,7 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ }
+
+ /* Now kick off ATA set up */
+- return ata_pci_init_one(dev, ppi);
++ return ata_pci_sff_init_one(dev, ppi, &hpt3x2n_sht, hpriv);
+ }
+
+ static const struct pci_device_id hpt3x2n[] = {
+diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c
+index cb8bdb6..f11a320 100644
+--- a/drivers/ata/pata_hpt3x3.c
++++ b/drivers/ata/pata_hpt3x3.c
+@@ -102,58 +102,17 @@ static int hpt3x3_atapi_dma(struct ata_queued_cmd *qc)
+ }
+
+ static struct scsi_host_template hpt3x3_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations hpt3x3_port_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .check_atapi_dma= hpt3x3_atapi_dma,
++ .cable_detect = ata_cable_40wire,
+ .set_piomode = hpt3x3_set_piomode,
+ #if defined(CONFIG_PATA_HPT3X3_DMA)
+ .set_dmamode = hpt3x3_set_dmamode,
+ #endif
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .check_atapi_dma= hpt3x3_atapi_dma,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /**
+@@ -189,7 +148,6 @@ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ static int printed_version;
+ static const struct ata_port_info info = {
+- .sht = &hpt3x3_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ #if defined(CONFIG_PATA_HPT3X3_DMA)
+@@ -244,15 +202,15 @@ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ ioaddr->altstatus_addr =
+ ioaddr->ctl_addr = base + offset_ctl[i];
+ ioaddr->scr_addr = NULL;
+- ata_std_ports(ioaddr);
++ ata_sff_std_ports(ioaddr);
+ ioaddr->bmdma_addr = base + 8 * i;
+
+ ata_port_pbar_desc(ap, 4, -1, "ioport");
+ ata_port_pbar_desc(ap, 4, offset_cmd[i], "cmd");
+ }
+ pci_set_master(pdev);
+- return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+- &hpt3x3_sht);
++ return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
++ IRQF_SHARED, &hpt3x3_sht);
+ }
+
+ #ifdef CONFIG_PM
+diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c
+index f97068b..1713843 100644
+--- a/drivers/ata/pata_icside.c
++++ b/drivers/ata/pata_icside.c
+@@ -250,7 +250,7 @@ static void pata_icside_bmdma_setup(struct ata_queued_cmd *qc)
+ set_dma_mode(state->dma, write ? DMA_MODE_WRITE : DMA_MODE_READ);
+
+ /* issue r/w command */
+- ap->ops->exec_command(ap, &qc->tf);
++ ap->ops->sff_exec_command(ap, &qc->tf);
+ }
+
+ static void pata_icside_bmdma_start(struct ata_queued_cmd *qc)
+@@ -270,7 +270,7 @@ static void pata_icside_bmdma_stop(struct ata_queued_cmd *qc)
+ disable_dma(state->dma);
+
+ /* see ata_bmdma_stop */
+- ata_altstatus(ap);
++ ata_sff_altstatus(ap);
+ }
+
+ static u8 pata_icside_bmdma_status(struct ata_port *ap)
+@@ -305,35 +305,18 @@ static int icside_dma_init(struct pata_icside_info *info)
+
+
+ static struct scsi_host_template pata_icside_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
++ ATA_BASE_SHT(DRV_NAME),
+ .sg_tablesize = PATA_ICSIDE_MAX_SG,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+ .dma_boundary = ~0, /* no dma boundaries */
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
+ };
+
+-/* wish this was exported from libata-core */
+-static void ata_dummy_noret(struct ata_port *port)
+-{
+-}
+-
+ static void pata_icside_postreset(struct ata_link *link, unsigned int *classes)
+ {
+ struct ata_port *ap = link->ap;
+ struct pata_icside_state *state = ap->host->private_data;
+
+ if (classes[0] != ATA_DEV_NONE || classes[1] != ATA_DEV_NONE)
+- return ata_std_postreset(link, classes);
++ return ata_sff_postreset(link, classes);
+
+ state->port[ap->port_no].disabled = 1;
+
+@@ -349,42 +332,20 @@ static void pata_icside_postreset(struct ata_link *link, unsigned int *classes)
+ }
+ }
+
+-static void pata_icside_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL,
+- pata_icside_postreset);
+-}
+-
+ static struct ata_port_operations pata_icside_port_ops = {
+- .set_dmamode = pata_icside_set_dmamode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .exec_command = ata_exec_command,
+- .check_status = ata_check_status,
+- .dev_select = ata_std_dev_select,
+-
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = pata_icside_bmdma_setup,
+- .bmdma_start = pata_icside_bmdma_start,
+-
+- .data_xfer = ata_data_xfer_noirq,
+-
++ .inherits = &ata_sff_port_ops,
+ /* no need to build any PRD tables for DMA */
+ .qc_prep = ata_noop_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = pata_icside_error_handler,
+- .post_internal_cmd = pata_icside_bmdma_stop,
+-
+- .irq_clear = ata_dummy_noret,
+- .irq_on = ata_irq_on,
+-
++ .sff_data_xfer = ata_sff_data_xfer_noirq,
++ .bmdma_setup = pata_icside_bmdma_setup,
++ .bmdma_start = pata_icside_bmdma_start,
+ .bmdma_stop = pata_icside_bmdma_stop,
+ .bmdma_status = pata_icside_bmdma_status,
++
++ .cable_detect = ata_cable_40wire,
++ .set_dmamode = pata_icside_set_dmamode,
++ .postreset = pata_icside_postreset,
++ .post_internal_cmd = pata_icside_bmdma_stop,
+ };
+
+ static void __devinit
+@@ -520,7 +481,7 @@ static int __devinit pata_icside_add_ports(struct pata_icside_info *info)
+ pata_icside_setup_ioaddr(ap, info->base, info, info->port[i]);
+ }
+
+- return ata_host_activate(host, ec->irq, ata_interrupt, 0,
++ return ata_host_activate(host, ec->irq, ata_sff_interrupt, 0,
+ &pata_icside_sht);
+ }
+
+diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c
+index 4320e79..6a111ba 100644
+--- a/drivers/ata/pata_isapnp.c
++++ b/drivers/ata/pata_isapnp.c
+@@ -20,45 +20,12 @@
+ #define DRV_VERSION "0.2.2"
+
+ static struct scsi_host_template isapnp_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_PIO_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations isapnp_port_ops = {
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_sff_port_ops,
+ .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /**
+@@ -83,7 +50,7 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev
+
+ if (pnp_irq_valid(idev, 0)) {
+ irq = pnp_irq(idev, 0);
+- handler = ata_interrupt;
++ handler = ata_sff_interrupt;
+ }
+
+ /* allocate host */
+@@ -111,7 +78,7 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev
+ ap->ioaddr.ctl_addr = ctl_addr;
+ }
+
+- ata_std_ports(&ap->ioaddr);
++ ata_sff_std_ports(&ap->ioaddr);
+
+ ata_port_desc(ap, "cmd 0x%llx ctl 0x%llx",
+ (unsigned long long)pnp_port_start(idev, 0),
+diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c
+index e0c2cc2..c113d7c 100644
+--- a/drivers/ata/pata_it8213.c
++++ b/drivers/ata/pata_it8213.c
+@@ -40,20 +40,7 @@ static int it8213_pre_reset(struct ata_link *link, unsigned long deadline)
+ if (!pci_test_config_bits(pdev, &it8213_enable_bits[ap->port_no]))
+ return -ENOENT;
+
+- return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- * it8213_error_handler - Probe specified port on PATA host controller
+- * @ap: Port to probe
+- *
+- * LOCKING:
+- * None (inherited from caller).
+- */
+-
+-static void it8213_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, it8213_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -243,53 +230,16 @@ static void it8213_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+ }
+
+ static struct scsi_host_template it8213_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .max_sectors = ATA_MAX_SECTORS,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static const struct ata_port_operations it8213_ops = {
++
++static struct ata_port_operations it8213_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .cable_detect = it8213_cable_detect,
+ .set_piomode = it8213_set_piomode,
+ .set_dmamode = it8213_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = it8213_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = it8213_cable_detect,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .prereset = it8213_pre_reset,
+ };
+
+
+@@ -311,7 +261,6 @@ static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *en
+ {
+ static int printed_version;
+ static const struct ata_port_info info = {
+- .sht = &it8213_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+@@ -325,7 +274,7 @@ static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *en
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "version " DRV_VERSION "\n");
+
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &it8213_sht, NULL);
+ }
+
+ static const struct pci_device_id it8213_pci_tbl[] = {
+diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
+index 257951d..e108169 100644
+--- a/drivers/ata/pata_it821x.c
++++ b/drivers/ata/pata_it821x.c
+@@ -395,11 +395,11 @@ static void it821x_passthru_dev_select(struct ata_port *ap,
+ it821x_program(ap, adev, itdev->pio[adev->devno]);
+ itdev->last_device = device;
+ }
+- ata_std_dev_select(ap, device);
++ ata_sff_dev_select(ap, device);
+ }
+
+ /**
+- * it821x_smart_qc_issue_prot - wrap qc issue prot
++ * it821x_smart_qc_issue - wrap qc issue prot
+ * @qc: command
+ *
+ * Wrap the command issue sequence for the IT821x. We need to
+@@ -407,7 +407,7 @@ static void it821x_passthru_dev_select(struct ata_port *ap,
+ * usual happenings kick off
+ */
+
+-static unsigned int it821x_smart_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int it821x_smart_qc_issue(struct ata_queued_cmd *qc)
+ {
+ switch(qc->tf.command)
+ {
+@@ -427,14 +427,14 @@ static unsigned int it821x_smart_qc_issue_prot(struct ata_queued_cmd *qc)
+ case ATA_CMD_ID_ATA:
+ /* Arguably should just no-op this one */
+ case ATA_CMD_SET_FEATURES:
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+ printk(KERN_DEBUG "it821x: can't process command 0x%02X\n", qc->tf.command);
+ return AC_ERR_DEV;
+ }
+
+ /**
+- * it821x_passthru_qc_issue_prot - wrap qc issue prot
++ * it821x_passthru_qc_issue - wrap qc issue prot
+ * @qc: command
+ *
+ * Wrap the command issue sequence for the IT821x. We need to
+@@ -442,10 +442,10 @@ static unsigned int it821x_smart_qc_issue_prot(struct ata_queued_cmd *qc)
+ * usual happenings kick off
+ */
+
+-static unsigned int it821x_passthru_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int it821x_passthru_qc_issue(struct ata_queued_cmd *qc)
+ {
+ it821x_passthru_dev_select(qc->ap, qc->dev->devno);
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ /**
+@@ -632,89 +632,34 @@ static int it821x_port_start(struct ata_port *ap)
+ }
+
+ static struct scsi_host_template it821x_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations it821x_smart_port_ops = {
+- .set_mode = it821x_smart_set_mode,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .mode_filter = ata_pci_default_filter,
++ .inherits = &ata_bmdma_port_ops,
+
+- .check_status = ata_check_status,
+ .check_atapi_dma= it821x_check_atapi_dma,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+- .dev_config = it821x_dev_config,
++ .qc_issue = it821x_smart_qc_issue,
+
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .cable_detect = it821x_ident_hack,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = it821x_smart_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
++ .set_mode = it821x_smart_set_mode,
++ .dev_config = it821x_dev_config,
+
+ .port_start = it821x_port_start,
+ };
+
+ static struct ata_port_operations it821x_passthru_port_ops = {
+- .set_piomode = it821x_passthru_set_piomode,
+- .set_dmamode = it821x_passthru_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
++ .inherits = &ata_bmdma_port_ops,
+
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+ .check_atapi_dma= it821x_check_atapi_dma,
+- .dev_select = it821x_passthru_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_unknown,
+-
+- .bmdma_setup = ata_bmdma_setup,
++ .sff_dev_select = it821x_passthru_dev_select,
+ .bmdma_start = it821x_passthru_bmdma_start,
+ .bmdma_stop = it821x_passthru_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = it821x_passthru_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
++ .qc_issue = it821x_passthru_qc_issue,
+
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_handler = ata_interrupt,
+- .irq_on = ata_irq_on,
++ .cable_detect = ata_cable_unknown,
++ .set_piomode = it821x_passthru_set_piomode,
++ .set_dmamode = it821x_passthru_set_dmamode,
+
+ .port_start = it821x_port_start,
+ };
+@@ -742,14 +687,12 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ u8 conf;
+
+ static const struct ata_port_info info_smart = {
+- .sht = &it821x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .port_ops = &it821x_smart_port_ops
+ };
+ static const struct ata_port_info info_passthru = {
+- .sht = &it821x_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -759,6 +702,11 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+
+ const struct ata_port_info *ppi[] = { NULL, NULL };
+ static char *mode[2] = { "pass through", "smart" };
++ int rc;
++
++ rc = pcim_enable_device(pdev);
++ if (rc)
++ return rc;
+
+ /* Force the card into bypass mode if so requested */
+ if (it8212_noraid) {
+@@ -774,16 +722,23 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ else
+ ppi[0] = &info_smart;
+
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &it821x_sht, NULL);
+ }
+
+ #ifdef CONFIG_PM
+ static int it821x_reinit_one(struct pci_dev *pdev)
+ {
++ struct ata_host *host = dev_get_drvdata(&pdev->dev);
++ int rc;
++
++ rc = ata_pci_device_do_resume(pdev);
++ if (rc)
++ return rc;
+ /* Resume - turn raid back off if need be */
+ if (it8212_noraid)
+ it821x_disable_raid(pdev);
+- return ata_pci_device_resume(pdev);
++ ata_host_resume(host);
++ return rc;
+ }
+ #endif
+
+diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
+index 030878f..de8d186 100644
+--- a/drivers/ata/pata_ixp4xx_cf.c
++++ b/drivers/ata/pata_ixp4xx_cf.c
+@@ -88,48 +88,14 @@ static unsigned int ixp4xx_mmio_data_xfer(struct ata_device *dev,
+ }
+
+ static struct scsi_host_template ixp4xx_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_PIO_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations ixp4xx_port_ops = {
+- .set_mode = ixp4xx_set_mode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .exec_command = ata_exec_command,
+- .check_status = ata_check_status,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ixp4xx_mmio_data_xfer,
++ .inherits = &ata_sff_port_ops,
++ .sff_data_xfer = ixp4xx_mmio_data_xfer,
+ .cable_detect = ata_cable_40wire,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_port_start,
++ .set_mode = ixp4xx_set_mode,
+ };
+
+ static void ixp4xx_setup_port(struct ata_port *ap,
+@@ -144,7 +110,7 @@ static void ixp4xx_setup_port(struct ata_port *ap,
+ ioaddr->altstatus_addr = data->cs1 + 0x06;
+ ioaddr->ctl_addr = data->cs1 + 0x06;
+
+- ata_std_ports(ioaddr);
++ ata_sff_std_ports(ioaddr);
+
+ #ifndef __ARMEB__
+
+@@ -220,7 +186,7 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)
+ dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+
+ /* activate host */
+- return ata_host_activate(host, irq, ata_interrupt, 0, &ixp4xx_sht);
++ return ata_host_activate(host, irq, ata_sff_interrupt, 0, &ixp4xx_sht);
+ }
+
+ static __devexit int ixp4xx_pata_remove(struct platform_device *dev)
+@@ -255,6 +221,7 @@ MODULE_AUTHOR("Alessandro Zummo <a.zummo at towertech.it>");
+ MODULE_DESCRIPTION("low-level driver for ixp4xx Compact Flash PATA");
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION(DRV_VERSION);
++MODULE_ALIAS("platform:" DRV_NAME);
+
+ module_init(ixp4xx_pata_init);
+ module_exit(ixp4xx_pata_exit);
+diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c
+index 00bbbbd..73b7596 100644
+--- a/drivers/ata/pata_jmicron.c
++++ b/drivers/ata/pata_jmicron.c
+@@ -102,73 +102,18 @@ static int jmicron_pre_reset(struct ata_link *link, unsigned long deadline)
+ ap->cbl = ATA_CBL_SATA;
+ break;
+ }
+- return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- * jmicron_error_handler - Setup and error handler
+- * @ap: Port to handle
+- *
+- * LOCKING:
+- * None (inherited from caller).
+- */
+-
+-static void jmicron_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, jmicron_pre_reset, ata_std_softreset, NULL,
+- ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /* No PIO or DMA methods needed for this device */
+
+ static struct scsi_host_template jmicron_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- /* Use standard CHS mapping rules */
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static const struct ata_port_operations jmicron_ops = {
+- /* Task file is PCI ATA format, use helpers */
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = jmicron_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+-
+- /* BMDMA handling is PCI ATA format, use helpers */
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- /* IRQ-related hooks */
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- /* Generic PATA PCI ATA helpers */
+- .port_start = ata_port_start,
++static struct ata_port_operations jmicron_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .prereset = jmicron_pre_reset,
+ };
+
+
+@@ -189,7 +134,6 @@ static const struct ata_port_operations jmicron_ops = {
+ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info = {
+- .sht = &jmicron_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+
+ .pio_mask = 0x1f,
+@@ -200,7 +144,7 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i
+ };
+ const struct ata_port_info *ppi[] = { &info, NULL };
+
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &jmicron_sht, NULL);
+ }
+
+ static const struct pci_device_id jmicron_pci_tbl[] = {
+diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
+index 50fe08e..7af4b29 100644
+--- a/drivers/ata/pata_legacy.c
++++ b/drivers/ata/pata_legacy.c
+@@ -208,21 +208,12 @@ static int legacy_set_mode(struct ata_link *link, struct ata_device **unused)
+ }
+
+ static struct scsi_host_template legacy_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_PIO_SHT(DRV_NAME),
++};
++
++static const struct ata_port_operations legacy_base_port_ops = {
++ .inherits = &ata_sff_port_ops,
++ .cable_detect = ata_cable_40wire,
+ };
+
+ /*
+@@ -234,55 +225,14 @@ static struct scsi_host_template legacy_sht = {
+ */
+
+ static struct ata_port_operations simple_port_ops = {
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer_noirq,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .inherits = &legacy_base_port_ops,
++ .sff_data_xfer = ata_sff_data_xfer_noirq,
+ };
+
+ static struct ata_port_operations legacy_port_ops = {
++ .inherits = &legacy_base_port_ops,
++ .sff_data_xfer = ata_sff_data_xfer_noirq,
+ .set_mode = legacy_set_mode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+- .cable_detect = ata_cable_40wire,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer_noirq,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /*
+@@ -367,36 +317,15 @@ static unsigned int pdc_data_xfer_vlb(struct ata_device *dev,
+ }
+ local_irq_restore(flags);
+ } else
+- buflen = ata_data_xfer_noirq(dev, buf, buflen, rw);
++ buflen = ata_sff_data_xfer_noirq(dev, buf, buflen, rw);
+
+ return buflen;
+ }
+
+ static struct ata_port_operations pdc20230_port_ops = {
++ .inherits = &legacy_base_port_ops,
+ .set_piomode = pdc20230_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = pdc_data_xfer_vlb,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .sff_data_xfer = pdc_data_xfer_vlb,
+ };
+
+ /*
+@@ -427,30 +356,8 @@ static void ht6560a_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ static struct ata_port_operations ht6560a_port_ops = {
++ .inherits = &legacy_base_port_ops,
+ .set_piomode = ht6560a_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer, /* Check vlb/noirq */
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /*
+@@ -492,30 +399,8 @@ static void ht6560b_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ static struct ata_port_operations ht6560b_port_ops = {
++ .inherits = &legacy_base_port_ops,
+ .set_piomode = ht6560b_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer, /* FIXME: Check 32bit and noirq */
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /*
+@@ -613,30 +498,8 @@ static void opti82c611a_set_piomode(struct ata_port *ap,
+
+
+ static struct ata_port_operations opti82c611a_port_ops = {
++ .inherits = &legacy_base_port_ops,
+ .set_piomode = opti82c611a_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /*
+@@ -716,7 +579,7 @@ static void opti82c46x_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ /**
+- * opt82c465mv_qc_issue_prot - command issue
++ * opt82c465mv_qc_issue - command issue
+ * @qc: command pending
+ *
+ * Called when the libata layer is about to issue a command. We wrap
+@@ -730,7 +593,7 @@ static void opti82c46x_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ * FIXME: dual channel needs ->serialize support
+ */
+
+-static unsigned int opti82c46x_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int opti82c46x_qc_issue(struct ata_queued_cmd *qc)
+ {
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+@@ -741,34 +604,13 @@ static unsigned int opti82c46x_qc_issue_prot(struct ata_queued_cmd *qc)
+ && ap->host->private_data != NULL)
+ opti82c46x_set_piomode(ap, adev);
+
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ static struct ata_port_operations opti82c46x_port_ops = {
++ .inherits = &legacy_base_port_ops,
+ .set_piomode = opti82c46x_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = opti82c46x_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .qc_issue = opti82c46x_qc_issue,
+ };
+
+ static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev)
+@@ -802,7 +644,7 @@ static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ * @irq: interrupt line
+ *
+ * In dual channel mode the 6580 has one clock per channel and we have
+- * to software clockswitch in qc_issue_prot.
++ * to software clockswitch in qc_issue.
+ */
+
+ static void qdi6580dp_set_piomode(struct ata_port *ap, struct ata_device *adev)
+@@ -868,14 +710,14 @@ static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ /**
+- * qdi_qc_issue_prot - command issue
++ * qdi_qc_issue - command issue
+ * @qc: command pending
+ *
+ * Called when the libata layer is about to issue a command. We wrap
+ * this interface so that we can load the correct ATA timings.
+ */
+
+-static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int qdi_qc_issue(struct ata_queued_cmd *qc)
+ {
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+@@ -888,7 +730,7 @@ static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
+ 2 * ap->port_no);
+ }
+ }
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ static unsigned int vlb32_data_xfer(struct ata_device *adev, unsigned char *buf,
+@@ -917,7 +759,7 @@ static unsigned int vlb32_data_xfer(struct ata_device *adev, unsigned char *buf,
+ }
+ return (buflen + 3) & ~3;
+ } else
+- return ata_data_xfer(adev, buf, buflen, rw);
++ return ata_sff_data_xfer(adev, buf, buflen, rw);
+ }
+
+ static int qdi_port(struct platform_device *dev,
+@@ -930,84 +772,22 @@ static int qdi_port(struct platform_device *dev,
+ }
+
+ static struct ata_port_operations qdi6500_port_ops = {
++ .inherits = &legacy_base_port_ops,
+ .set_piomode = qdi6500_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = qdi_qc_issue_prot,
+-
+- .data_xfer = vlb32_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .qc_issue = qdi_qc_issue,
++ .sff_data_xfer = vlb32_data_xfer,
+ };
+
+ static struct ata_port_operations qdi6580_port_ops = {
++ .inherits = &legacy_base_port_ops,
+ .set_piomode = qdi6580_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = vlb32_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .sff_data_xfer = vlb32_data_xfer,
+ };
+
+ static struct ata_port_operations qdi6580dp_port_ops = {
++ .inherits = &legacy_base_port_ops,
+ .set_piomode = qdi6580dp_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = qdi_qc_issue_prot,
+-
+- .data_xfer = vlb32_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .sff_data_xfer = vlb32_data_xfer,
+ };
+
+ static DEFINE_SPINLOCK(winbond_lock);
+@@ -1076,29 +856,9 @@ static int winbond_port(struct platform_device *dev,
+ }
+
+ static struct ata_port_operations winbond_port_ops = {
++ .inherits = &legacy_base_port_ops,
+ .set_piomode = winbond_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = vlb32_data_xfer,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .sff_data_xfer = vlb32_data_xfer,
+ };
+
+ static struct legacy_controller controllers[] = {
+@@ -1256,13 +1016,13 @@ static __init int legacy_init_one(struct legacy_probe *probe)
+ ap->ioaddr.cmd_addr = io_addr;
+ ap->ioaddr.altstatus_addr = ctrl_addr;
+ ap->ioaddr.ctl_addr = ctrl_addr;
+- ata_std_ports(&ap->ioaddr);
++ ata_sff_std_ports(&ap->ioaddr);
+ ap->host->private_data = ld;
+
+ ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io, io + 0x0206);
+
+- ret = ata_host_activate(host, probe->irq, ata_interrupt, 0,
+- &legacy_sht);
++ ret = ata_host_activate(host, probe->irq, ata_sff_interrupt, 0,
++ &legacy_sht);
+ if (ret)
+ goto fail;
+ ld->platform_dev = pdev;
+diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c
+index a81f25d..24a011b 100644
+--- a/drivers/ata/pata_marvell.c
++++ b/drivers/ata/pata_marvell.c
+@@ -55,7 +55,7 @@ static int marvell_pre_reset(struct ata_link *link, unsigned long deadline)
+ (!(devices & 0x10))) /* PATA enable ? */
+ return -ENOENT;
+
+- return ata_std_prereset(link, deadline);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ static int marvell_cable_detect(struct ata_port *ap)
+@@ -75,71 +75,16 @@ static int marvell_cable_detect(struct ata_port *ap)
+ return 0; /* Our BUG macro needs the right markup */
+ }
+
+-/**
+- * marvell_error_handler - Setup and error handler
+- * @ap: Port to handle
+- *
+- * LOCKING:
+- * None (inherited from caller).
+- */
+-
+-static void marvell_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, marvell_pre_reset, ata_std_softreset, NULL,
+- ata_std_postreset);
+-}
+-
+ /* No PIO or DMA methods needed for this device */
+
+ static struct scsi_host_template marvell_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- /* Use standard CHS mapping rules */
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static const struct ata_port_operations marvell_ops = {
+- /* Task file is PCI ATA format, use helpers */
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = marvell_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++static struct ata_port_operations marvell_ops = {
++ .inherits = &ata_bmdma_port_ops,
+ .cable_detect = marvell_cable_detect,
+-
+- /* BMDMA handling is PCI ATA format, use helpers */
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- /* Timeout handling */
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- /* Generic PATA PCI ATA helpers */
+- .port_start = ata_sff_port_start,
++ .prereset = marvell_pre_reset,
+ };
+
+
+@@ -160,7 +105,6 @@ static const struct ata_port_operations marvell_ops = {
+ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info = {
+- .sht = &marvell_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+
+ .pio_mask = 0x1f,
+@@ -170,7 +114,6 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i
+ .port_ops = &marvell_ops,
+ };
+ static const struct ata_port_info info_sata = {
+- .sht = &marvell_sht,
+ /* Slave possible as its magically mapped not real */
+ .flags = ATA_FLAG_SLAVE_POSS,
+
+@@ -185,7 +128,7 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i
+ if (pdev->device == 0x6101)
+ ppi[1] = &ata_dummy_port_info;
+
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &marvell_sht, NULL);
+ }
+
+ static const struct pci_device_id marvell_pci_tbl[] = {
+diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
+index 5413ebf..bc79df6 100644
+--- a/drivers/ata/pata_mpc52xx.c
++++ b/drivers/ata/pata_mpc52xx.c
+@@ -252,53 +252,19 @@ mpc52xx_ata_dev_select(struct ata_port *ap, unsigned int device)
+ if (device != priv->csel)
+ mpc52xx_ata_apply_timings(priv, device);
+
+- ata_std_dev_select(ap,device);
++ ata_sff_dev_select(ap,device);
+ }
+
+-static void
+-mpc52xx_ata_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL,
+- ata_std_postreset);
+-}
+-
+-
+-
+ static struct scsi_host_template mpc52xx_ata_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .max_sectors = ATA_MAX_SECTORS,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .bios_param = ata_std_bios_param,
++ ATA_PIO_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations mpc52xx_ata_port_ops = {
+- .set_piomode = mpc52xx_ata_set_piomode,
+- .dev_select = mpc52xx_ata_dev_select,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = mpc52xx_ata_error_handler,
++ .inherits = &ata_sff_port_ops,
++ .sff_dev_select = mpc52xx_ata_dev_select,
+ .cable_detect = ata_cable_40wire,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+- .port_start = ata_port_start,
++ .set_piomode = mpc52xx_ata_set_piomode,
++ .post_internal_cmd = ATA_OP_NULL,
+ };
+
+ static int __devinit
+@@ -339,7 +305,7 @@ mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv,
+ ata_port_desc(ap, "ata_regs 0x%lx", raw_ata_regs);
+
+ /* activate host */
+- return ata_host_activate(host, priv->ata_irq, ata_interrupt, 0,
++ return ata_host_activate(host, priv->ata_irq, ata_sff_interrupt, 0,
+ &mpc52xx_ata_sht);
+ }
+
+diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c
+index c0d9e0c..7d7e3fd 100644
+--- a/drivers/ata/pata_mpiix.c
++++ b/drivers/ata/pata_mpiix.c
+@@ -55,21 +55,7 @@ static int mpiix_pre_reset(struct ata_link *link, unsigned long deadline)
+ if (!pci_test_config_bits(pdev, &mpiix_enable_bits))
+ return -ENOENT;
+
+- return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- * mpiix_error_handler - probe reset
+- * @ap: ATA port
+- *
+- * Perform the ATA probe and bus reset sequence plus specific handling
+- * for this hardware. The MPIIX has the enable bits in a different place
+- * to PIIX4 and friends. As a pure PIO device it has no cable detect
+- */
+-
+-static void mpiix_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, mpiix_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -83,8 +69,8 @@ static void mpiix_error_handler(struct ata_port *ap)
+ *
+ * This would get very ugly because we can only program timing for one
+ * device at a time, the other gets PIO0. Fortunately libata calls
+- * our qc_issue_prot command before a command is issued so we can
+- * flip the timings back and forth to reduce the pain.
++ * our qc_issue command before a command is issued so we can flip the
++ * timings back and forth to reduce the pain.
+ */
+
+ static void mpiix_set_piomode(struct ata_port *ap, struct ata_device *adev)
+@@ -124,7 +110,7 @@ static void mpiix_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ /**
+- * mpiix_qc_issue_prot - command issue
++ * mpiix_qc_issue - command issue
+ * @qc: command pending
+ *
+ * Called when the libata layer is about to issue a command. We wrap
+@@ -134,7 +120,7 @@ static void mpiix_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ * be made PIO0.
+ */
+
+-static unsigned int mpiix_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int mpiix_qc_issue(struct ata_queued_cmd *qc)
+ {
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+@@ -147,50 +133,19 @@ static unsigned int mpiix_qc_issue_prot(struct ata_queued_cmd *qc)
+ if (adev->pio_mode && adev != ap->private_data)
+ mpiix_set_piomode(ap, adev);
+
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ static struct scsi_host_template mpiix_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_PIO_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations mpiix_port_ops = {
+- .set_piomode = mpiix_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = mpiix_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_sff_port_ops,
++ .qc_issue = mpiix_qc_issue,
+ .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = mpiix_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .set_piomode = mpiix_set_piomode,
++ .prereset = mpiix_pre_reset,
+ };
+
+ static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+@@ -252,10 +207,10 @@ static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ ap->ioaddr.altstatus_addr = ctl_addr;
+
+ /* Let libata fill in the port details */
+- ata_std_ports(&ap->ioaddr);
++ ata_sff_std_ports(&ap->ioaddr);
+
+ /* activate host */
+- return ata_host_activate(host, irq, ata_interrupt, IRQF_SHARED,
++ return ata_host_activate(host, irq, ata_sff_interrupt, IRQF_SHARED,
+ &mpiix_sht);
+ }
+
+diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c
+index 25c922a..d9719c8 100644
+--- a/drivers/ata/pata_netcell.c
++++ b/drivers/ata/pata_netcell.c
+@@ -21,54 +21,12 @@
+ /* No PIO or DMA methods needed for this device */
+
+ static struct scsi_host_template netcell_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- /* Use standard CHS mapping rules */
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static const struct ata_port_operations netcell_ops = {
+- /* Task file is PCI ATA format, use helpers */
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++static struct ata_port_operations netcell_ops = {
++ .inherits = &ata_bmdma_port_ops,
+ .cable_detect = ata_cable_80wire,
+-
+- /* BMDMA handling is PCI ATA format, use helpers */
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- /* IRQ-related hooks */
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- /* Generic PATA PCI ATA helpers */
+- .port_start = ata_sff_port_start,
+ };
+
+
+@@ -90,7 +48,6 @@ static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ {
+ static int printed_version;
+ static const struct ata_port_info info = {
+- .sht = &netcell_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ /* Actually we don't really care about these as the
+ firmware deals with it */
+@@ -100,16 +57,21 @@ static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ .port_ops = &netcell_ops,
+ };
+ const struct ata_port_info *port_info[] = { &info, NULL };
++ int rc;
+
+ if (!printed_version++)
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "version " DRV_VERSION "\n");
+
++ rc = pcim_enable_device(pdev);
++ if (rc)
++ return rc;
++
+ /* Any chip specific setup/optimisation/messages here */
+- ata_pci_clear_simplex(pdev);
++ ata_pci_bmdma_clear_simplex(pdev);
+
+ /* And let the library code do the work */
+- return ata_pci_init_one(pdev, port_info);
++ return ata_pci_sff_init_one(pdev, port_info, &netcell_sht, NULL);
+ }
+
+ static const struct pci_device_id netcell_pci_tbl[] = {
+diff --git a/drivers/ata/pata_ninja32.c b/drivers/ata/pata_ninja32.c
+index 15dd649..565e67c 100644
+--- a/drivers/ata/pata_ninja32.c
++++ b/drivers/ata/pata_ninja32.c
+@@ -73,60 +73,20 @@ static void ninja32_dev_select(struct ata_port *ap, unsigned int device)
+ struct ata_device *adev = &ap->link.device[device];
+ if (ap->private_data != adev) {
+ iowrite8(0xd6, ap->ioaddr.bmdma_addr + 0x1f);
+- ata_std_dev_select(ap, device);
++ ata_sff_dev_select(ap, device);
+ ninja32_set_piomode(ap, adev);
+ }
+ }
+
+ static struct scsi_host_template ninja32_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations ninja32_port_ops = {
+- .set_piomode = ninja32_set_piomode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ninja32_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_bmdma_port_ops,
++ .sff_dev_select = ninja32_dev_select,
+ .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .set_piomode = ninja32_set_piomode,
+ };
+
+ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+@@ -172,7 +132,7 @@ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ ap->ioaddr.ctl_addr = base + 0x1E;
+ ap->ioaddr.altstatus_addr = base + 0x1E;
+ ap->ioaddr.bmdma_addr = base;
+- ata_std_ports(&ap->ioaddr);
++ ata_sff_std_ports(&ap->ioaddr);
+
+ iowrite8(0x05, base + 0x01); /* Enable interrupt lines */
+ iowrite8(0xBE, base + 0x02); /* Burst, ?? setup */
+@@ -182,7 +142,7 @@ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ iowrite8(0xa4, base + 0x1c); /* Unknown */
+ iowrite8(0x83, base + 0x1d); /* BMDMA control: WAIT0 */
+ /* FIXME: Should we disable them at remove ? */
+- return ata_host_activate(host, dev->irq, ata_interrupt,
++ return ata_host_activate(host, dev->irq, ata_sff_interrupt,
+ IRQF_SHARED, &ninja32_sht);
+ }
+
+diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c
+index 9fe66fd..76d2455 100644
+--- a/drivers/ata/pata_ns87410.c
++++ b/drivers/ata/pata_ns87410.c
+@@ -50,21 +50,7 @@ static int ns87410_pre_reset(struct ata_link *link, unsigned long deadline)
+ if (!pci_test_config_bits(pdev, &ns87410_enable_bits[ap->port_no]))
+ return -ENOENT;
+
+- return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- * ns87410_error_handler - probe reset
+- * @ap: ATA port
+- *
+- * Perform the ATA probe and bus reset sequence plus specific handling
+- * for this hardware. The MPIIX has the enable bits in a different place
+- * to PIIX4 and friends. As a pure PIO device it has no cable detect
+- */
+-
+-static void ns87410_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, ns87410_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -119,7 +105,7 @@ static void ns87410_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ /**
+- * ns87410_qc_issue_prot - command issue
++ * ns87410_qc_issue - command issue
+ * @qc: command pending
+ *
+ * Called when the libata layer is about to issue a command. We wrap
+@@ -127,7 +113,7 @@ static void ns87410_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ * necessary.
+ */
+
+-static unsigned int ns87410_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int ns87410_qc_issue(struct ata_queued_cmd *qc)
+ {
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+@@ -140,64 +126,30 @@ static unsigned int ns87410_qc_issue_prot(struct ata_queued_cmd *qc)
+ if (adev->pio_mode && adev != ap->private_data)
+ ns87410_set_piomode(ap, adev);
+
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ static struct scsi_host_template ns87410_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_PIO_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations ns87410_port_ops = {
+- .set_piomode = ns87410_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ns87410_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_sff_port_ops,
++ .qc_issue = ns87410_qc_issue,
+ .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ns87410_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .set_piomode = ns87410_set_piomode,
++ .prereset = ns87410_pre_reset,
+ };
+
+ static int ns87410_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info = {
+- .sht = &ns87410_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x0F,
+ .port_ops = &ns87410_port_ops
+ };
+ const struct ata_port_info *ppi[] = { &info, NULL };
+- return ata_pci_init_one(dev, ppi);
++ return ata_pci_sff_init_one(dev, ppi, &ns87410_sht, NULL);
+ }
+
+ static const struct pci_device_id ns87410[] = {
+diff --git a/drivers/ata/pata_ns87415.c b/drivers/ata/pata_ns87415.c
+index d0e2e50..ae92b00 100644
+--- a/drivers/ata/pata_ns87415.c
++++ b/drivers/ata/pata_ns87415.c
+@@ -138,7 +138,7 @@ static void ns87415_bmdma_setup(struct ata_queued_cmd *qc)
+ dmactl |= ATA_DMA_WR;
+ iowrite8(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+ /* issue r/w command */
+- ap->ops->exec_command(ap, &qc->tf);
++ ap->ops->sff_exec_command(ap, &qc->tf);
+ }
+
+ /**
+@@ -172,14 +172,14 @@ static void ns87415_bmdma_stop(struct ata_queued_cmd *qc)
+ }
+
+ /**
+- * ns87415_bmdma_irq_clear - Clear interrupt
++ * ns87415_irq_clear - Clear interrupt
+ * @ap: Channel to clear
+ *
+ * Erratum: Due to a chip bug regisers 02 and 0A bit 1 and 2 (the
+ * error bits) are reset by writing to register 00 or 08.
+ */
+
+-static void ns87415_bmdma_irq_clear(struct ata_port *ap)
++static void ns87415_irq_clear(struct ata_port *ap)
+ {
+ void __iomem *mmio = ap->ioaddr.bmdma_addr;
+
+@@ -297,90 +297,32 @@ static u8 ns87560_bmdma_status(struct ata_port *ap)
+ {
+ return ns87560_read_buggy(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+ }
+-
+-static const struct ata_port_operations ns87560_pata_ops = {
+- .set_piomode = ns87415_set_piomode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ns87560_tf_read,
+- .check_status = ns87560_check_status,
+- .check_atapi_dma = ns87415_check_atapi_dma,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ns87415_bmdma_setup,
+- .bmdma_start = ns87415_bmdma_start,
+- .bmdma_stop = ns87415_bmdma_stop,
+- .bmdma_status = ns87560_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ns87415_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+-};
+-
+ #endif /* 87560 SuperIO Support */
+
++static struct ata_port_operations ns87415_pata_ops = {
++ .inherits = &ata_bmdma_port_ops,
+
+-static const struct ata_port_operations ns87415_pata_ops = {
+- .set_piomode = ns87415_set_piomode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+ .check_atapi_dma = ns87415_check_atapi_dma,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+ .bmdma_setup = ns87415_bmdma_setup,
+ .bmdma_start = ns87415_bmdma_start,
+ .bmdma_stop = ns87415_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
++ .sff_irq_clear = ns87415_irq_clear,
+
+- .irq_handler = ata_interrupt,
+- .irq_clear = ns87415_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
++ .cable_detect = ata_cable_40wire,
++ .set_piomode = ns87415_set_piomode,
++};
+
+- .port_start = ata_sff_port_start,
++#if defined(CONFIG_SUPERIO)
++static struct ata_port_operations ns87560_pata_ops = {
++ .inherits = &ns87415_pata_ops,
++ .sff_tf_read = ns87560_tf_read,
++ .sff_check_status = ns87560_check_status,
++ .bmdma_status = ns87560_bmdma_status,
+ };
++#endif
+
+ static struct scsi_host_template ns87415_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+
+@@ -403,16 +345,15 @@ static int ns87415_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ {
+ static int printed_version;
+ static const struct ata_port_info info = {
+- .sht = &ns87415_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .port_ops = &ns87415_pata_ops,
+ };
+ const struct ata_port_info *ppi[] = { &info, NULL };
++ int rc;
+ #if defined(CONFIG_SUPERIO)
+ static const struct ata_port_info info87560 = {
+- .sht = &ns87415_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+@@ -425,11 +366,16 @@ static int ns87415_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ if (!printed_version++)
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "version " DRV_VERSION "\n");
++
++ rc = pcim_enable_device(pdev);
++ if (rc)
++ return rc;
++
+ /* Select 512 byte sectors */
+ pci_write_config_byte(pdev, 0x55, 0xEE);
+ /* Select PIO0 8bit clocking */
+ pci_write_config_byte(pdev, 0x54, 0xB7);
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &ns87415_sht, NULL);
+ }
+
+ static const struct pci_device_id ns87415_pci_tbl[] = {
+diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
+index 44da09a..e678af3 100644
+--- a/drivers/ata/pata_oldpiix.c
++++ b/drivers/ata/pata_oldpiix.c
+@@ -47,21 +47,7 @@ static int oldpiix_pre_reset(struct ata_link *link, unsigned long deadline)
+ if (!pci_test_config_bits(pdev, &oldpiix_enable_bits[ap->port_no]))
+ return -ENOENT;
+
+- return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- * oldpiix_pata_error_handler - Probe specified port on PATA host controller
+- * @ap: Port to probe
+- * @classes:
+- *
+- * LOCKING:
+- * None (inherited from caller).
+- */
+-
+-static void oldpiix_pata_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, oldpiix_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -195,7 +181,7 @@ static void oldpiix_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+ }
+
+ /**
+- * oldpiix_qc_issue_prot - command issue
++ * oldpiix_qc_issue - command issue
+ * @qc: command pending
+ *
+ * Called when the libata layer is about to issue a command. We wrap
+@@ -205,7 +191,7 @@ static void oldpiix_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+ * be made PIO0.
+ */
+
+-static unsigned int oldpiix_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int oldpiix_qc_issue(struct ata_queued_cmd *qc)
+ {
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+@@ -215,58 +201,21 @@ static unsigned int oldpiix_qc_issue_prot(struct ata_queued_cmd *qc)
+ if (adev->dma_mode)
+ oldpiix_set_dmamode(ap, adev);
+ }
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+
+ static struct scsi_host_template oldpiix_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static const struct ata_port_operations oldpiix_pata_ops = {
++static struct ata_port_operations oldpiix_pata_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .qc_issue = oldpiix_qc_issue,
++ .cable_detect = ata_cable_40wire,
+ .set_piomode = oldpiix_set_piomode,
+ .set_dmamode = oldpiix_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = oldpiix_pata_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = oldpiix_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .prereset = oldpiix_pre_reset,
+ };
+
+
+@@ -289,7 +238,6 @@ static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ {
+ static int printed_version;
+ static const struct ata_port_info info = {
+- .sht = &oldpiix_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma1-2 */
+@@ -301,7 +249,7 @@ static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "version " DRV_VERSION "\n");
+
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &oldpiix_sht, NULL);
+ }
+
+ static const struct pci_device_id oldpiix_pci_tbl[] = {
+diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c
+index 8f79447..fb2cf66 100644
+--- a/drivers/ata/pata_opti.c
++++ b/drivers/ata/pata_opti.c
+@@ -64,22 +64,7 @@ static int opti_pre_reset(struct ata_link *link, unsigned long deadline)
+ if (!pci_test_config_bits(pdev, &opti_enable_bits[ap->port_no]))
+ return -ENOENT;
+
+- return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- * opti_probe_reset - probe reset
+- * @ap: ATA port
+- *
+- * Perform the ATA probe and bus reset sequence plus specific handling
+- * for this hardware. The Opti needs little handling - we have no UDMA66
+- * capability that needs cable detection. All we must do is check the port
+- * is enabled.
+- */
+-
+-static void opti_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, opti_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -165,58 +150,19 @@ static void opti_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ static struct scsi_host_template opti_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_PIO_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations opti_port_ops = {
+- .set_piomode = opti_set_piomode,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = opti_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_sff_port_ops,
+ .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .set_piomode = opti_set_piomode,
++ .prereset = opti_pre_reset,
+ };
+
+ static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info = {
+- .sht = &opti_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .port_ops = &opti_port_ops
+@@ -227,7 +173,7 @@ static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ if (!printed_version++)
+ dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");
+
+- return ata_pci_init_one(dev, ppi);
++ return ata_pci_sff_init_one(dev, ppi, &opti_sht, NULL);
+ }
+
+ static const struct pci_device_id opti[] = {
+diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c
+index f9b485a..4cd7444 100644
+--- a/drivers/ata/pata_optidma.c
++++ b/drivers/ata/pata_optidma.c
+@@ -64,22 +64,7 @@ static int optidma_pre_reset(struct ata_link *link, unsigned long deadline)
+ if (ap->port_no && !pci_test_config_bits(pdev, &optidma_enable_bits))
+ return -ENOENT;
+
+- return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- * optidma_probe_reset - probe reset
+- * @ap: ATA port
+- *
+- * Perform the ATA probe and bus reset sequence plus specific handling
+- * for this hardware. The Opti needs little handling - we have no UDMA66
+- * capability that needs cable detection. All we must do is check the port
+- * is enabled.
+- */
+-
+-static void optidma_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, optidma_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -350,89 +335,22 @@ static int optidma_set_mode(struct ata_link *link, struct ata_device **r_failed)
+ }
+
+ static struct scsi_host_template optidma_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations optidma_port_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .cable_detect = ata_cable_40wire,
+ .set_piomode = optidma_set_pio_mode,
+ .set_dmamode = optidma_set_dma_mode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .error_handler = optidma_error_handler,
+ .set_mode = optidma_set_mode,
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .prereset = optidma_pre_reset,
+ };
+
+ static struct ata_port_operations optiplus_port_ops = {
++ .inherits = &optidma_port_ops,
+ .set_piomode = optiplus_set_pio_mode,
+ .set_dmamode = optiplus_set_dma_mode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .error_handler = optidma_error_handler,
+- .set_mode = optidma_set_mode,
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /**
+@@ -481,14 +399,12 @@ done_nomsg: /* Wrong chip revision */
+ static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info_82c700 = {
+- .sht = &optidma_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .port_ops = &optidma_port_ops
+ };
+ static const struct ata_port_info info_82c700_udma = {
+- .sht = &optidma_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -497,10 +413,15 @@ static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ };
+ const struct ata_port_info *ppi[] = { &info_82c700, NULL };
+ static int printed_version;
++ int rc;
+
+ if (!printed_version++)
+ dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");
+
++ rc = pcim_enable_device(dev);
++ if (rc)
++ return rc;
++
+ /* Fixed location chipset magic */
+ inw(0x1F1);
+ inw(0x1F1);
+@@ -509,7 +430,7 @@ static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ if (optiplus_with_udma(dev))
+ ppi[0] = &info_82c700_udma;
+
+- return ata_pci_init_one(dev, ppi);
++ return ata_pci_sff_init_one(dev, ppi, &optidma_sht, NULL);
+ }
+
+ static const struct pci_device_id optidma[] = {
+diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
+index 3e7f6a9..3d39f9d 100644
+--- a/drivers/ata/pata_pcmcia.c
++++ b/drivers/ata/pata_pcmcia.c
+@@ -128,71 +128,21 @@ static unsigned int ata_data_xfer_8bit(struct ata_device *dev,
+
+
+ static struct scsi_host_template pcmcia_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_PIO_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations pcmcia_port_ops = {
+- .set_mode = pcmcia_set_mode,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_sff_port_ops,
++ .sff_data_xfer = ata_sff_data_xfer_noirq,
+ .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer_noirq,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .set_mode = pcmcia_set_mode,
+ };
+
+ static struct ata_port_operations pcmcia_8bit_port_ops = {
+- .set_mode = pcmcia_set_mode_8bit,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_sff_port_ops,
++ .sff_data_xfer = ata_data_xfer_8bit,
+ .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer_8bit,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .set_mode = pcmcia_set_mode_8bit,
+ };
+
+ #define CS_CHECK(fn, ret) \
+@@ -373,13 +323,13 @@ next_entry:
+ ap->ioaddr.cmd_addr = io_addr + 0x10 * p;
+ ap->ioaddr.altstatus_addr = ctl_addr + 0x10 * p;
+ ap->ioaddr.ctl_addr = ctl_addr + 0x10 * p;
+- ata_std_ports(&ap->ioaddr);
++ ata_sff_std_ports(&ap->ioaddr);
+
+ ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io_base, ctl_base);
+ }
+
+ /* activate */
+- ret = ata_host_activate(host, pdev->irq.AssignedIRQ, ata_interrupt,
++ ret = ata_host_activate(host, pdev->irq.AssignedIRQ, ata_sff_interrupt,
+ IRQF_SHARED, &pcmcia_sht);
+ if (ret)
+ goto failed;
+diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c
+index 511c89b..0e1c2c1 100644
+--- a/drivers/ata/pata_pdc2027x.c
++++ b/drivers/ata/pata_pdc2027x.c
+@@ -63,7 +63,7 @@ enum {
+ };
+
+ static int pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+-static void pdc2027x_error_handler(struct ata_port *ap);
++static int pdc2027x_prereset(struct ata_link *link, unsigned long deadline);
+ static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev);
+ static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev);
+ static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc);
+@@ -129,84 +129,22 @@ static struct pci_driver pdc2027x_pci_driver = {
+ };
+
+ static struct scsi_host_template pdc2027x_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations pdc2027x_pata100_ops = {
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
++ .inherits = &ata_bmdma_port_ops,
+ .check_atapi_dma = pdc2027x_check_atapi_dma,
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = pdc2027x_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .cable_detect = pdc2027x_cable_detect,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .prereset = pdc2027x_prereset,
+ };
+
+ static struct ata_port_operations pdc2027x_pata133_ops = {
++ .inherits = &pdc2027x_pata100_ops,
++ .mode_filter = pdc2027x_mode_filter,
+ .set_piomode = pdc2027x_set_piomode,
+ .set_dmamode = pdc2027x_set_dmamode,
+ .set_mode = pdc2027x_set_mode,
+- .mode_filter = pdc2027x_mode_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .check_atapi_dma = pdc2027x_check_atapi_dma,
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = pdc2027x_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = pdc2027x_cable_detect,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ static struct ata_port_info pdc2027x_port_info[] = {
+@@ -310,22 +248,7 @@ static int pdc2027x_prereset(struct ata_link *link, unsigned long deadline)
+ /* Check whether port enabled */
+ if (!pdc2027x_port_enabled(link->ap))
+ return -ENOENT;
+- return ata_std_prereset(link, deadline);
+-}
+-
+-/**
+- * pdc2027x_error_handler - Perform reset on PATA port and classify
+- * @ap: Port to reset
+- *
+- * Reset PATA phy and classify attached devices.
+- *
+- * LOCKING:
+- * None (inherited from caller).
+- */
+-
+-static void pdc2027x_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, pdc2027x_prereset, ata_std_softreset, NULL, ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+@@ -342,7 +265,7 @@ static unsigned long pdc2027x_mode_filter(struct ata_device *adev, unsigned long
+ struct ata_device *pair = ata_dev_pair(adev);
+
+ if (adev->class != ATA_DEV_ATA || adev->devno == 0 || pair == NULL)
+- return ata_pci_default_filter(adev, mask);
++ return ata_bmdma_mode_filter(adev, mask);
+
+ /* Check for slave of a Maxtor at UDMA6 */
+ ata_id_c_string(pair->id, model_num, ATA_ID_PROD,
+@@ -351,7 +274,7 @@ static unsigned long pdc2027x_mode_filter(struct ata_device *adev, unsigned long
+ if (strstr(model_num, "Maxtor") == NULL && pair->dma_mode == XFER_UDMA_6)
+ mask &= ~ (1 << (6 + ATA_SHIFT_UDMA));
+
+- return ata_pci_default_filter(adev, mask);
++ return ata_bmdma_mode_filter(adev, mask);
+ }
+
+ /**
+@@ -836,8 +759,8 @@ static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_de
+ return -EIO;
+
+ pci_set_master(pdev);
+- return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+- &pdc2027x_sht);
++ return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
++ IRQF_SHARED, &pdc2027x_sht);
+ }
+
+ /**
+diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c
+index 3ed8667..d267306 100644
+--- a/drivers/ata/pata_pdc202xx_old.c
++++ b/drivers/ata/pata_pdc202xx_old.c
+@@ -262,94 +262,34 @@ static int pdc2026x_check_atapi_dma(struct ata_queued_cmd *qc)
+ }
+
+ static struct scsi_host_template pdc202xx_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations pdc2024x_port_ops = {
+- .set_piomode = pdc202xx_set_piomode,
+- .set_dmamode = pdc202xx_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .inherits = &ata_bmdma_port_ops,
++
++ .cable_detect = ata_cable_40wire,
++ .set_piomode = pdc202xx_set_piomode,
++ .set_dmamode = pdc202xx_set_dmamode,
+ };
+
+ static struct ata_port_operations pdc2026x_port_ops = {
+- .set_piomode = pdc202xx_set_piomode,
+- .set_dmamode = pdc202xx_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+- .dev_config = pdc2026x_dev_config,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = pdc2026x_cable_detect,
+-
+- .check_atapi_dma= pdc2026x_check_atapi_dma,
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = pdc2026x_bmdma_start,
+- .bmdma_stop = pdc2026x_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = pdc2026x_port_start,
++ .inherits = &pdc2024x_port_ops,
++
++ .check_atapi_dma = pdc2026x_check_atapi_dma,
++ .bmdma_start = pdc2026x_bmdma_start,
++ .bmdma_stop = pdc2026x_bmdma_stop,
++
++ .cable_detect = pdc2026x_cable_detect,
++ .dev_config = pdc2026x_dev_config,
++
++ .port_start = pdc2026x_port_start,
+ };
+
+ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info[3] = {
+ {
+- .sht = &pdc202xx_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -357,7 +297,6 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id
+ .port_ops = &pdc2024x_port_ops
+ },
+ {
+- .sht = &pdc202xx_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -365,7 +304,6 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id
+ .port_ops = &pdc2026x_port_ops
+ },
+ {
+- .sht = &pdc202xx_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -386,7 +324,7 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id
+ return -ENODEV;
+ }
+ }
+- return ata_pci_init_one(dev, ppi);
++ return ata_pci_sff_init_one(dev, ppi, &pdc202xx_sht, NULL);
+ }
+
+ static const struct pci_device_id pdc202xx[] = {
+diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
+index aad7adc..8f65ad6 100644
+--- a/drivers/ata/pata_platform.c
++++ b/drivers/ata/pata_platform.c
+@@ -46,50 +46,16 @@ static int pata_platform_set_mode(struct ata_link *link, struct ata_device **unu
+ return 0;
+ }
+
+-static int ata_dummy_ret0(struct ata_port *ap) { return 0; }
+-
+ static struct scsi_host_template pata_platform_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_PIO_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations pata_platform_port_ops = {
+- .set_mode = pata_platform_set_mode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_sff_port_ops,
++ .sff_data_xfer = ata_sff_data_xfer_noirq,
+ .cable_detect = ata_cable_unknown,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer_noirq,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_dummy_ret0,
++ .set_mode = pata_platform_set_mode,
++ .port_start = ATA_OP_NULL,
+ };
+
+ static void pata_platform_setup_port(struct ata_ioports *ioaddr,
+@@ -210,7 +176,7 @@ int __devinit __pata_platform_probe(struct device *dev,
+ (unsigned long long)ctl_res->start);
+
+ /* activate */
+- return ata_host_activate(host, irq, irq ? ata_interrupt : NULL,
++ return ata_host_activate(host, irq, irq ? ata_sff_interrupt : NULL,
+ irq_flags, &pata_platform_sht);
+ }
+ EXPORT_SYMBOL_GPL(__pata_platform_probe);
+@@ -311,3 +277,4 @@ MODULE_AUTHOR("Paul Mundt");
+ MODULE_DESCRIPTION("low-level driver for platform device ATA");
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION(DRV_VERSION);
++MODULE_ALIAS("platform:" DRV_NAME);
+diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c
+index 9f308ed..bf45cf0 100644
+--- a/drivers/ata/pata_qdi.c
++++ b/drivers/ata/pata_qdi.c
+@@ -102,14 +102,14 @@ static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ /**
+- * qdi_qc_issue_prot - command issue
++ * qdi_qc_issue - command issue
+ * @qc: command pending
+ *
+ * Called when the libata layer is about to issue a command. We wrap
+ * this interface so that we can load the correct ATA timings.
+ */
+
+-static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int qdi_qc_issue(struct ata_queued_cmd *qc)
+ {
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+@@ -121,7 +121,7 @@ static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
+ outb(qdi->clock[adev->devno], qdi->timing);
+ }
+ }
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ static unsigned int qdi_data_xfer(struct ata_device *dev, unsigned char *buf,
+@@ -148,79 +148,26 @@ static unsigned int qdi_data_xfer(struct ata_device *dev, unsigned char *buf,
+ buflen += 4 - slop;
+ }
+ } else
+- buflen = ata_data_xfer(dev, buf, buflen, rw);
++ buflen = ata_sff_data_xfer(dev, buf, buflen, rw);
+
+ return buflen;
+ }
+
+ static struct scsi_host_template qdi_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_PIO_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations qdi6500_port_ops = {
+- .set_piomode = qdi6500_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_sff_port_ops,
++ .qc_issue = qdi_qc_issue,
++ .sff_data_xfer = qdi_data_xfer,
+ .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = qdi_qc_issue_prot,
+-
+- .data_xfer = qdi_data_xfer,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .set_piomode = qdi6500_set_piomode,
+ };
+
+ static struct ata_port_operations qdi6580_port_ops = {
++ .inherits = &qdi6500_port_ops,
+ .set_piomode = qdi6580_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = qdi_qc_issue_prot,
+-
+- .data_xfer = qdi_data_xfer,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /**
+@@ -276,7 +223,7 @@ static __init int qdi_init_one(unsigned long port, int type, unsigned long io, i
+ ap->ioaddr.cmd_addr = io_addr;
+ ap->ioaddr.altstatus_addr = ctl_addr;
+ ap->ioaddr.ctl_addr = ctl_addr;
+- ata_std_ports(&ap->ioaddr);
++ ata_sff_std_ports(&ap->ioaddr);
+
+ ata_port_desc(ap, "cmd %lx ctl %lx", io, ctl);
+
+@@ -292,7 +239,7 @@ static __init int qdi_init_one(unsigned long port, int type, unsigned long io, i
+ printk(KERN_INFO DRV_NAME": qd%d at 0x%lx.\n", type, io);
+
+ /* activate */
+- ret = ata_host_activate(host, irq, ata_interrupt, 0, &qdi_sht);
++ ret = ata_host_activate(host, irq, ata_sff_interrupt, 0, &qdi_sht);
+ if (ret)
+ goto fail;
+
+diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c
+index 8109b08..1c0d9fa 100644
+--- a/drivers/ata/pata_radisys.c
++++ b/drivers/ata/pata_radisys.c
+@@ -156,7 +156,7 @@ static void radisys_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+ }
+
+ /**
+- * radisys_qc_issue_prot - command issue
++ * radisys_qc_issue - command issue
+ * @qc: command pending
+ *
+ * Called when the libata layer is about to issue a command. We wrap
+@@ -166,7 +166,7 @@ static void radisys_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+ * be made PIO0.
+ */
+
+-static unsigned int radisys_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int radisys_qc_issue(struct ata_queued_cmd *qc)
+ {
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+@@ -180,58 +180,20 @@ static unsigned int radisys_qc_issue_prot(struct ata_queued_cmd *qc)
+ radisys_set_piomode(ap, adev);
+ }
+ }
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+
+ static struct scsi_host_template radisys_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static const struct ata_port_operations radisys_pata_ops = {
++static struct ata_port_operations radisys_pata_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .qc_issue = radisys_qc_issue,
++ .cable_detect = ata_cable_unknown,
+ .set_piomode = radisys_set_piomode,
+ .set_dmamode = radisys_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_unknown,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = radisys_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+
+@@ -254,7 +216,6 @@ static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ {
+ static int printed_version;
+ static const struct ata_port_info info = {
+- .sht = &radisys_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma1-2 */
+@@ -267,7 +228,7 @@ static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *e
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "version " DRV_VERSION "\n");
+
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &radisys_sht, NULL);
+ }
+
+ static const struct pci_device_id radisys_pci_tbl[] = {
+diff --git a/drivers/ata/pata_rb500_cf.c b/drivers/ata/pata_rb500_cf.c
+index 4ce9b03..4345174 100644
+--- a/drivers/ata/pata_rb500_cf.c
++++ b/drivers/ata/pata_rb500_cf.c
+@@ -57,7 +57,7 @@ static inline void rb500_pata_finish_io(struct ata_port *ap)
+ struct ata_host *ah = ap->host;
+ struct rb500_cf_info *info = ah->private_data;
+
+- ata_altstatus(ap);
++ ata_sff_altstatus(ap);
+ ndelay(RB500_CF_IO_DELAY);
+
+ set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
+@@ -109,7 +109,7 @@ static irqreturn_t rb500_pata_irq_handler(int irq, void *dev_instance)
+ if (gpio_get_value(info->gpio_line)) {
+ set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW);
+ if (!info->frozen)
+- ata_interrupt(info->irq, dev_instance);
++ ata_sff_interrupt(info->irq, dev_instance);
+ } else {
+ set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
+ }
+@@ -117,58 +117,18 @@ static irqreturn_t rb500_pata_irq_handler(int irq, void *dev_instance)
+ return IRQ_HANDLED;
+ }
+
+-static void rb500_pata_irq_clear(struct ata_port *ap)
+-{
+-}
+-
+-static int rb500_pata_port_start(struct ata_port *ap)
+-{
+- return 0;
+-}
+-
+ static struct ata_port_operations rb500_pata_port_ops = {
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+-
+- .exec_command = rb500_pata_exec_command,
+- .check_status = ata_check_status,
+- .dev_select = ata_std_dev_select,
+-
+- .data_xfer = rb500_pata_data_xfer,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
++ .inherits = &ata_sff_port_ops,
++ .sff_exec_command = rb500_pata_exec_command,
++ .sff_data_xfer = rb500_pata_data_xfer,
+ .freeze = rb500_pata_freeze,
+ .thaw = rb500_pata_thaw,
+- .error_handler = ata_bmdma_error_handler,
+-
+- .irq_handler = rb500_pata_irq_handler,
+- .irq_clear = rb500_pata_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = rb500_pata_port_start,
+ };
+
+ /* ------------------------------------------------------------------------ */
+
+ static struct scsi_host_template rb500_pata_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
+- .proc_name = DRV_NAME,
+-
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
++ ATA_PIO_SHT(DRV_NAME),
+ };
+
+ /* ------------------------------------------------------------------------ */
+@@ -188,7 +148,7 @@ static void rb500_pata_setup_ports(struct ata_host *ah)
+ ap->ioaddr.ctl_addr = info->iobase + RB500_CF_REG_CTRL;
+ ap->ioaddr.altstatus_addr = info->iobase + RB500_CF_REG_CTRL;
+
+- ata_std_ports(&ap->ioaddr);
++ ata_sff_std_ports(&ap->ioaddr);
+
+ ap->ioaddr.data_addr = info->iobase + RB500_CF_REG_DATA;
+ }
+@@ -279,6 +239,9 @@ static __devexit int rb500_pata_driver_remove(struct platform_device *pdev)
+ return 0;
+ }
+
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:" DRV_NAME);
++
+ static struct platform_driver rb500_pata_platform_driver = {
+ .probe = rb500_pata_driver_probe,
+ .remove = __devexit_p(rb500_pata_driver_remove),
+diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c
+index ba8a31c..7dfd1f3 100644
+--- a/drivers/ata/pata_rz1000.c
++++ b/drivers/ata/pata_rz1000.c
+@@ -53,53 +53,13 @@ static int rz1000_set_mode(struct ata_link *link, struct ata_device **unused)
+
+
+ static struct scsi_host_template rz1000_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_PIO_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations rz1000_port_ops = {
+- .set_mode = rz1000_set_mode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_sff_port_ops,
+ .cable_detect = ata_cable_40wire,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .set_mode = rz1000_set_mode,
+ };
+
+ static int rz1000_fifo_disable(struct pci_dev *pdev)
+@@ -129,7 +89,6 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en
+ {
+ static int printed_version;
+ static const struct ata_port_info info = {
+- .sht = &rz1000_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .port_ops = &rz1000_port_ops
+@@ -140,7 +99,7 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en
+ printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+
+ if (rz1000_fifo_disable(pdev) == 0)
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &rz1000_sht, NULL);
+
+ printk(KERN_ERR DRV_NAME ": failed to disable read-ahead on chipset..\n");
+ /* Not safe to use so skip */
+diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c
+index 725a858..cbab397 100644
+--- a/drivers/ata/pata_sc1200.c
++++ b/drivers/ata/pata_sc1200.c
+@@ -151,7 +151,7 @@ static void sc1200_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ /**
+- * sc1200_qc_issue_prot - command issue
++ * sc1200_qc_issue - command issue
+ * @qc: command pending
+ *
+ * Called when the libata layer is about to issue a command. We wrap
+@@ -160,7 +160,7 @@ static void sc1200_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ * one MWDMA/UDMA bit.
+ */
+
+-static unsigned int sc1200_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int sc1200_qc_issue(struct ata_queued_cmd *qc)
+ {
+ struct ata_port *ap = qc->ap;
+ struct ata_device *adev = qc->dev;
+@@ -175,59 +175,21 @@ static unsigned int sc1200_qc_issue_prot(struct ata_queued_cmd *qc)
+ sc1200_set_dmamode(ap, adev);
+ }
+
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ static struct scsi_host_template sc1200_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_DUMB_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
++ .sg_tablesize = LIBATA_DUMB_MAX_PRD,
+ };
+
+ static struct ata_port_operations sc1200_port_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .qc_prep = ata_sff_dumb_qc_prep,
++ .qc_issue = sc1200_qc_issue,
++ .cable_detect = ata_cable_40wire,
+ .set_piomode = sc1200_set_piomode,
+ .set_dmamode = sc1200_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_dumb_qc_prep,
+- .qc_issue = sc1200_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /**
+@@ -242,7 +204,6 @@ static struct ata_port_operations sc1200_port_ops = {
+ static int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info = {
+- .sht = &sc1200_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -252,7 +213,7 @@ static int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ /* Can't enable port 2 yet, see top comments */
+ const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info };
+
+- return ata_pci_init_one(dev, ppi);
++ return ata_pci_sff_init_one(dev, ppi, &sc1200_sht, NULL);
+ }
+
+ static const struct pci_device_id sc1200[] = {
+diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c
+index 6c016de..e965b25 100644
+--- a/drivers/ata/pata_scc.c
++++ b/drivers/ata/pata_scc.c
+@@ -266,7 +266,7 @@ unsigned long scc_mode_filter(struct ata_device *adev, unsigned long mask)
+ printk(KERN_INFO "%s: limit ATAPI UDMA to UDMA4\n", DRV_NAME);
+ mask &= ~(0xE0 << ATA_SHIFT_UDMA);
+ }
+- return ata_pci_default_filter(adev, mask);
++ return ata_bmdma_mode_filter(adev, mask);
+ }
+
+ /**
+@@ -274,7 +274,7 @@ unsigned long scc_mode_filter(struct ata_device *adev, unsigned long mask)
+ * @ap: Port to which output is sent
+ * @tf: ATA taskfile register set
+ *
+- * Note: Original code is ata_tf_load().
++ * Note: Original code is ata_sff_tf_load().
+ */
+
+ static void scc_tf_load (struct ata_port *ap, const struct ata_taskfile *tf)
+@@ -341,7 +341,7 @@ static u8 scc_check_status (struct ata_port *ap)
+ * @ap: Port from which input is read
+ * @tf: ATA taskfile register set for storing input
+ *
+- * Note: Original code is ata_tf_read().
++ * Note: Original code is ata_sff_tf_read().
+ */
+
+ static void scc_tf_read (struct ata_port *ap, struct ata_taskfile *tf)
+@@ -373,7 +373,7 @@ static void scc_tf_read (struct ata_port *ap, struct ata_taskfile *tf)
+ * @ap: port to which command is being issued
+ * @tf: ATA taskfile register set
+ *
+- * Note: Original code is ata_exec_command().
++ * Note: Original code is ata_sff_exec_command().
+ */
+
+ static void scc_exec_command (struct ata_port *ap,
+@@ -382,7 +382,7 @@ static void scc_exec_command (struct ata_port *ap,
+ DPRINTK("ata%u: cmd 0x%X\n", ap->print_id, tf->command);
+
+ out_be32(ap->ioaddr.command_addr, tf->command);
+- ata_pause(ap);
++ ata_sff_pause(ap);
+ }
+
+ /**
+@@ -396,14 +396,14 @@ static u8 scc_check_altstatus (struct ata_port *ap)
+ }
+
+ /**
+- * scc_std_dev_select - Select device 0/1 on ATA bus
++ * scc_dev_select - Select device 0/1 on ATA bus
+ * @ap: ATA channel to manipulate
+ * @device: ATA device (numbered from zero) to select
+ *
+- * Note: Original code is ata_std_dev_select().
++ * Note: Original code is ata_sff_dev_select().
+ */
+
+-static void scc_std_dev_select (struct ata_port *ap, unsigned int device)
++static void scc_dev_select (struct ata_port *ap, unsigned int device)
+ {
+ u8 tmp;
+
+@@ -413,7 +413,7 @@ static void scc_std_dev_select (struct ata_port *ap, unsigned int device)
+ tmp = ATA_DEVICE_OBS | ATA_DEV1;
+
+ out_be32(ap->ioaddr.device_addr, tmp);
+- ata_pause(ap);
++ ata_sff_pause(ap);
+ }
+
+ /**
+@@ -441,7 +441,7 @@ static void scc_bmdma_setup (struct ata_queued_cmd *qc)
+ out_be32(mmio + SCC_DMA_CMD, dmactl);
+
+ /* issue r/w command */
+- ap->ops->exec_command(ap, &qc->tf);
++ ap->ops->sff_exec_command(ap, &qc->tf);
+ }
+
+ /**
+@@ -476,7 +476,7 @@ static unsigned int scc_devchk (struct ata_port *ap,
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+ u8 nsect, lbal;
+
+- ap->ops->dev_select(ap, device);
++ ap->ops->sff_dev_select(ap, device);
+
+ out_be32(ioaddr->nsect_addr, 0x55);
+ out_be32(ioaddr->lbal_addr, 0xaa);
+@@ -497,57 +497,78 @@ static unsigned int scc_devchk (struct ata_port *ap,
+ }
+
+ /**
+- * scc_bus_post_reset - PATA device post reset
++ * scc_wait_after_reset - wait for devices to become ready after reset
+ *
+- * Note: Original code is ata_bus_post_reset().
++ * Note: Original code is ata_sff_wait_after_reset
+ */
+
+-static int scc_bus_post_reset(struct ata_port *ap, unsigned int devmask,
+- unsigned long deadline)
++int scc_wait_after_reset(struct ata_link *link, unsigned int devmask,
++ unsigned long deadline)
+ {
++ struct ata_port *ap = link->ap;
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+ unsigned int dev0 = devmask & (1 << 0);
+ unsigned int dev1 = devmask & (1 << 1);
+- int rc;
+-
+- /* if device 0 was found in ata_devchk, wait for its
+- * BSY bit to clear
++ int rc, ret = 0;
++
++ /* Spec mandates ">= 2ms" before checking status. We wait
++ * 150ms, because that was the magic delay used for ATAPI
++ * devices in Hale Landis's ATADRVR, for the period of time
++ * between when the ATA command register is written, and then
++ * status is checked. Because waiting for "a while" before
++ * checking status is fine, post SRST, we perform this magic
++ * delay here as well.
++ *
++ * Old drivers/ide uses the 2mS rule and then waits for ready.
+ */
+- if (dev0) {
+- rc = ata_wait_ready(ap, deadline);
+- if (rc && rc != -ENODEV)
+- return rc;
+- }
++ msleep(150);
+
+- /* if device 1 was found in ata_devchk, wait for
+- * register access, then wait for BSY to clear
++ /* always check readiness of the master device */
++ rc = ata_sff_wait_ready(link, deadline);
++ /* -ENODEV means the odd clown forgot the D7 pulldown resistor
++ * and TF status is 0xff, bail out on it too.
+ */
+- while (dev1) {
+- u8 nsect, lbal;
++ if (rc)
++ return rc;
+
+- ap->ops->dev_select(ap, 1);
+- nsect = in_be32(ioaddr->nsect_addr);
+- lbal = in_be32(ioaddr->lbal_addr);
+- if ((nsect == 1) && (lbal == 1))
+- break;
+- if (time_after(jiffies, deadline))
+- return -EBUSY;
+- msleep(50); /* give drive a breather */
+- }
++ /* if device 1 was found in ata_devchk, wait for register
++ * access briefly, then wait for BSY to clear.
++ */
+ if (dev1) {
+- rc = ata_wait_ready(ap, deadline);
+- if (rc && rc != -ENODEV)
+- return rc;
++ int i;
++
++ ap->ops->sff_dev_select(ap, 1);
++
++ /* Wait for register access. Some ATAPI devices fail
++ * to set nsect/lbal after reset, so don't waste too
++ * much time on it. We're gonna wait for !BSY anyway.
++ */
++ for (i = 0; i < 2; i++) {
++ u8 nsect, lbal;
++
++ nsect = in_be32(ioaddr->nsect_addr);
++ lbal = in_be32(ioaddr->lbal_addr);
++ if ((nsect == 1) && (lbal == 1))
++ break;
++ msleep(50); /* give drive a breather */
++ }
++
++ rc = ata_sff_wait_ready(link, deadline);
++ if (rc) {
++ if (rc != -ENODEV)
++ return rc;
++ ret = rc;
++ }
+ }
+
+ /* is all this really necessary? */
+- ap->ops->dev_select(ap, 0);
++ ap->ops->sff_dev_select(ap, 0);
+ if (dev1)
+- ap->ops->dev_select(ap, 1);
++ ap->ops->sff_dev_select(ap, 1);
+ if (dev0)
+- ap->ops->dev_select(ap, 0);
++ ap->ops->sff_dev_select(ap, 0);
+
+- return 0;
++ return ret;
+ }
+
+ /**
+@@ -570,32 +591,22 @@ static unsigned int scc_bus_softreset(struct ata_port *ap, unsigned int devmask,
+ udelay(20);
+ out_be32(ioaddr->ctl_addr, ap->ctl);
+
+- /* wait a while before checking status */
+- ata_wait_after_reset(ap, deadline);
+-
+- /* Before we perform post reset processing we want to see if
+- * the bus shows 0xFF because the odd clown forgets the D7
+- * pulldown resistor.
+- */
+- if (scc_check_status(ap) == 0xFF)
+- return 0;
+-
+- scc_bus_post_reset(ap, devmask, deadline);
++ scc_wait_after_reset(&ap->link, devmask, deadline);
+
+ return 0;
+ }
+
+ /**
+- * scc_std_softreset - reset host port via ATA SRST
++ * scc_softreset - reset host port via ATA SRST
+ * @ap: port to reset
+ * @classes: resulting classes of attached devices
+ * @deadline: deadline jiffies for the operation
+ *
+- * Note: Original code is ata_std_softreset().
++ * Note: Original code is ata_sff_softreset().
+ */
+
+-static int scc_std_softreset(struct ata_link *link, unsigned int *classes,
+- unsigned long deadline)
++static int scc_softreset(struct ata_link *link, unsigned int *classes,
++ unsigned long deadline)
+ {
+ struct ata_port *ap = link->ap;
+ unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
+@@ -604,11 +615,6 @@ static int scc_std_softreset(struct ata_link *link, unsigned int *classes,
+
+ DPRINTK("ENTER\n");
+
+- if (ata_link_offline(link)) {
+- classes[0] = ATA_DEV_NONE;
+- goto out;
+- }
+-
+ /* determine if device 0/1 are present */
+ if (scc_devchk(ap, 0))
+ devmask |= (1 << 0);
+@@ -616,7 +622,7 @@ static int scc_std_softreset(struct ata_link *link, unsigned int *classes,
+ devmask |= (1 << 1);
+
+ /* select device 0 again */
+- ap->ops->dev_select(ap, 0);
++ ap->ops->sff_dev_select(ap, 0);
+
+ /* issue bus reset */
+ DPRINTK("about to softreset, devmask=%x\n", devmask);
+@@ -628,13 +634,12 @@ static int scc_std_softreset(struct ata_link *link, unsigned int *classes,
+ }
+
+ /* determine by signature whether we have ATA or ATAPI devices */
+- classes[0] = ata_dev_try_classify(&ap->link.device[0],
++ classes[0] = ata_sff_dev_classify(&ap->link.device[0],
+ devmask & (1 << 0), &err);
+ if (slave_possible && err != 0x81)
+- classes[1] = ata_dev_try_classify(&ap->link.device[1],
++ classes[1] = ata_sff_dev_classify(&ap->link.device[1],
+ devmask & (1 << 1), &err);
+
+- out:
+ DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
+ return 0;
+ }
+@@ -695,7 +700,7 @@ static void scc_bmdma_stop (struct ata_queued_cmd *qc)
+ printk(KERN_WARNING "%s: Internal Bus Error\n", DRV_NAME);
+ out_be32(bmid_base + SCC_DMA_INTST, INTSTS_BMSINT);
+ /* TBD: SW reset */
+- scc_std_softreset(&ap->link, &classes, deadline);
++ scc_softreset(&ap->link, &classes, deadline);
+ continue;
+ }
+
+@@ -721,7 +726,7 @@ static void scc_bmdma_stop (struct ata_queued_cmd *qc)
+ in_be32(bmid_base + SCC_DMA_CMD) & ~ATA_DMA_START);
+
+ /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
+- ata_altstatus(ap); /* dummy read */
++ ata_sff_altstatus(ap); /* dummy read */
+ }
+
+ /**
+@@ -742,7 +747,7 @@ static u8 scc_bmdma_status (struct ata_port *ap)
+ return host_stat;
+
+ /* errata A252,A308 workaround: Step4 */
+- if ((ata_altstatus(ap) & ATA_ERR) && (int_status & INTSTS_INTRQ))
++ if ((ata_sff_altstatus(ap) & ATA_ERR) && (int_status & INTSTS_INTRQ))
+ return (host_stat | ATA_DMA_INTR);
+
+ /* errata A308 workaround Step5 */
+@@ -773,7 +778,7 @@ static u8 scc_bmdma_status (struct ata_port *ap)
+ * @buflen: buffer length
+ * @rw: read/write
+ *
+- * Note: Original code is ata_data_xfer().
++ * Note: Original code is ata_sff_data_xfer().
+ */
+
+ static unsigned int scc_data_xfer (struct ata_device *dev, unsigned char *buf,
+@@ -782,28 +787,28 @@ static unsigned int scc_data_xfer (struct ata_device *dev, unsigned char *buf,
+ struct ata_port *ap = dev->link->ap;
+ unsigned int words = buflen >> 1;
+ unsigned int i;
+- u16 *buf16 = (u16 *) buf;
++ __le16 *buf16 = (__le16 *) buf;
+ void __iomem *mmio = ap->ioaddr.data_addr;
+
+ /* Transfer multiple of 2 bytes */
+ if (rw == READ)
+ for (i = 0; i < words; i++)
+- buf16[i] = le16_to_cpu(in_be32(mmio));
++ buf16[i] = cpu_to_le16(in_be32(mmio));
+ else
+ for (i = 0; i < words; i++)
+- out_be32(mmio, cpu_to_le16(buf16[i]));
++ out_be32(mmio, le16_to_cpu(buf16[i]));
+
+ /* Transfer trailing 1 byte, if any. */
+ if (unlikely(buflen & 0x01)) {
+- u16 align_buf[1] = { 0 };
++ __le16 align_buf[1] = { 0 };
+ unsigned char *trailing_buf = buf + buflen - 1;
+
+ if (rw == READ) {
+- align_buf[0] = le16_to_cpu(in_be32(mmio));
++ align_buf[0] = cpu_to_le16(in_be32(mmio));
+ memcpy(trailing_buf, align_buf, 1);
+ } else {
+ memcpy(align_buf, trailing_buf, 1);
+- out_be32(mmio, cpu_to_le16(align_buf[0]));
++ out_be32(mmio, le16_to_cpu(align_buf[0]));
+ }
+ words++;
+ }
+@@ -815,7 +820,7 @@ static unsigned int scc_data_xfer (struct ata_device *dev, unsigned char *buf,
+ * scc_irq_on - Enable interrupts on a port.
+ * @ap: Port on which interrupts are enabled.
+ *
+- * Note: Original code is ata_irq_on().
++ * Note: Original code is ata_sff_irq_on().
+ */
+
+ static u8 scc_irq_on (struct ata_port *ap)
+@@ -829,19 +834,19 @@ static u8 scc_irq_on (struct ata_port *ap)
+ out_be32(ioaddr->ctl_addr, ap->ctl);
+ tmp = ata_wait_idle(ap);
+
+- ap->ops->irq_clear(ap);
++ ap->ops->sff_irq_clear(ap);
+
+ return tmp;
+ }
+
+ /**
+- * scc_bmdma_freeze - Freeze BMDMA controller port
++ * scc_freeze - Freeze BMDMA controller port
+ * @ap: port to freeze
+ *
+- * Note: Original code is ata_bmdma_freeze().
++ * Note: Original code is ata_sff_freeze().
+ */
+
+-static void scc_bmdma_freeze (struct ata_port *ap)
++static void scc_freeze (struct ata_port *ap)
+ {
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+
+@@ -854,9 +859,9 @@ static void scc_bmdma_freeze (struct ata_port *ap)
+ * ATA_NIEN manipulation. Also, many controllers fail to mask
+ * previously pending IRQ on ATA_NIEN assertion. Clear it.
+ */
+- ata_chk_status(ap);
++ ap->ops->sff_check_status(ap);
+
+- ap->ops->irq_clear(ap);
++ ap->ops->sff_irq_clear(ap);
+ }
+
+ /**
+@@ -868,18 +873,18 @@ static void scc_bmdma_freeze (struct ata_port *ap)
+ static int scc_pata_prereset(struct ata_link *link, unsigned long deadline)
+ {
+ link->ap->cbl = ATA_CBL_PATA80;
+- return ata_std_prereset(link, deadline);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ /**
+- * scc_std_postreset - standard postreset callback
++ * scc_postreset - standard postreset callback
+ * @ap: the target ata_port
+ * @classes: classes of attached devices
+ *
+- * Note: Original code is ata_std_postreset().
++ * Note: Original code is ata_sff_postreset().
+ */
+
+-static void scc_std_postreset(struct ata_link *link, unsigned int *classes)
++static void scc_postreset(struct ata_link *link, unsigned int *classes)
+ {
+ struct ata_port *ap = link->ap;
+
+@@ -887,9 +892,9 @@ static void scc_std_postreset(struct ata_link *link, unsigned int *classes)
+
+ /* is double-select really necessary? */
+ if (classes[0] != ATA_DEV_NONE)
+- ap->ops->dev_select(ap, 1);
++ ap->ops->sff_dev_select(ap, 1);
+ if (classes[1] != ATA_DEV_NONE)
+- ap->ops->dev_select(ap, 0);
++ ap->ops->sff_dev_select(ap, 0);
+
+ /* bail out if no device is present */
+ if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
+@@ -905,24 +910,13 @@ static void scc_std_postreset(struct ata_link *link, unsigned int *classes)
+ }
+
+ /**
+- * scc_error_handler - Stock error handler for BMDMA controller
+- * @ap: port to handle error for
+- */
+-
+-static void scc_error_handler (struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, scc_pata_prereset, scc_std_softreset, NULL,
+- scc_std_postreset);
+-}
+-
+-/**
+- * scc_bmdma_irq_clear - Clear PCI IDE BMDMA interrupt.
++ * scc_irq_clear - Clear PCI IDE BMDMA interrupt.
+ * @ap: Port associated with this ATA transaction.
+ *
+- * Note: Original code is ata_bmdma_irq_clear().
++ * Note: Original code is ata_sff_irq_clear().
+ */
+
+-static void scc_bmdma_irq_clear (struct ata_port *ap)
++static void scc_irq_clear (struct ata_port *ap)
+ {
+ void __iomem *mmio = ap->ioaddr.bmdma_addr;
+
+@@ -968,52 +962,37 @@ static void scc_port_stop (struct ata_port *ap)
+ }
+
+ static struct scsi_host_template scc_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static const struct ata_port_operations scc_pata_ops = {
++static struct ata_port_operations scc_pata_ops = {
++ .inherits = &ata_bmdma_port_ops,
++
+ .set_piomode = scc_set_piomode,
+ .set_dmamode = scc_set_dmamode,
+ .mode_filter = scc_mode_filter,
+
+- .tf_load = scc_tf_load,
+- .tf_read = scc_tf_read,
+- .exec_command = scc_exec_command,
+- .check_status = scc_check_status,
+- .check_altstatus = scc_check_altstatus,
+- .dev_select = scc_std_dev_select,
++ .sff_tf_load = scc_tf_load,
++ .sff_tf_read = scc_tf_read,
++ .sff_exec_command = scc_exec_command,
++ .sff_check_status = scc_check_status,
++ .sff_check_altstatus = scc_check_altstatus,
++ .sff_dev_select = scc_dev_select,
+
+ .bmdma_setup = scc_bmdma_setup,
+ .bmdma_start = scc_bmdma_start,
+ .bmdma_stop = scc_bmdma_stop,
+ .bmdma_status = scc_bmdma_status,
+- .data_xfer = scc_data_xfer,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .freeze = scc_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
++ .sff_data_xfer = scc_data_xfer,
+
+- .error_handler = scc_error_handler,
++ .freeze = scc_freeze,
++ .prereset = scc_pata_prereset,
++ .softreset = scc_softreset,
++ .postreset = scc_postreset,
+ .post_internal_cmd = scc_bmdma_stop,
+
+- .irq_clear = scc_bmdma_irq_clear,
+- .irq_on = scc_irq_on,
++ .sff_irq_clear = scc_irq_clear,
++ .sff_irq_on = scc_irq_on,
+
+ .port_start = scc_port_start,
+ .port_stop = scc_port_stop,
+@@ -1166,8 +1145,8 @@ static int scc_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+ if (rc)
+ return rc;
+
+- return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+- &scc_sht);
++ return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
++ IRQF_SHARED, &scc_sht);
+ }
+
+ static struct pci_driver scc_pci_driver = {
+diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c
+index a589c0f..ffd26d0 100644
+--- a/drivers/ata/pata_serverworks.c
++++ b/drivers/ata/pata_serverworks.c
+@@ -199,7 +199,7 @@ static unsigned long serverworks_osb4_filter(struct ata_device *adev, unsigned l
+ {
+ if (adev->class == ATA_DEV_ATA)
+ mask &= ~ATA_MASK_UDMA;
+- return ata_pci_default_filter(adev, mask);
++ return ata_bmdma_mode_filter(adev, mask);
+ }
+
+
+@@ -219,7 +219,7 @@ static unsigned long serverworks_csb_filter(struct ata_device *adev, unsigned lo
+
+ /* Disk, UDMA */
+ if (adev->class != ATA_DEV_ATA)
+- return ata_pci_default_filter(adev, mask);
++ return ata_bmdma_mode_filter(adev, mask);
+
+ /* Actually do need to check */
+ ata_id_c_string(adev->id, model_num, ATA_ID_PROD, sizeof(model_num));
+@@ -228,7 +228,7 @@ static unsigned long serverworks_csb_filter(struct ata_device *adev, unsigned lo
+ if (!strcmp(p, model_num))
+ mask &= ~(0xE0 << ATA_SHIFT_UDMA);
+ }
+- return ata_pci_default_filter(adev, mask);
++ return ata_bmdma_mode_filter(adev, mask);
+ }
+
+ /**
+@@ -298,89 +298,20 @@ static void serverworks_set_dmamode(struct ata_port *ap, struct ata_device *adev
+ }
+
+ static struct scsi_host_template serverworks_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations serverworks_osb4_port_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .cable_detect = serverworks_cable_detect,
++ .mode_filter = serverworks_osb4_filter,
+ .set_piomode = serverworks_set_piomode,
+ .set_dmamode = serverworks_set_dmamode,
+- .mode_filter = serverworks_osb4_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = serverworks_cable_detect,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ static struct ata_port_operations serverworks_csb_port_ops = {
+- .set_piomode = serverworks_set_piomode,
+- .set_dmamode = serverworks_set_dmamode,
++ .inherits = &serverworks_osb4_port_ops,
+ .mode_filter = serverworks_csb_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = serverworks_cable_detect,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ static int serverworks_fixup_osb4(struct pci_dev *pdev)
+@@ -468,28 +399,24 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id
+ {
+ static const struct ata_port_info info[4] = {
+ { /* OSB4 */
+- .sht = &serverworks_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x07,
+ .port_ops = &serverworks_osb4_port_ops
+ }, { /* OSB4 no UDMA */
+- .sht = &serverworks_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = 0x00,
+ .port_ops = &serverworks_osb4_port_ops
+ }, { /* CSB5 */
+- .sht = &serverworks_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = ATA_UDMA4,
+ .port_ops = &serverworks_csb_port_ops
+ }, { /* CSB5 - later revisions*/
+- .sht = &serverworks_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -498,6 +425,11 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id
+ }
+ };
+ const struct ata_port_info *ppi[] = { &info[id->driver_data], NULL };
++ int rc;
++
++ rc = pcim_enable_device(pdev);
++ if (rc)
++ return rc;
+
+ /* Force master latency timer to 64 PCI clocks */
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
+@@ -527,24 +459,30 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id
+ serverworks_fixup_ht1000(pdev);
+
+ if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
+- ata_pci_clear_simplex(pdev);
++ ata_pci_bmdma_clear_simplex(pdev);
+
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &serverworks_sht, NULL);
+ }
+
+ #ifdef CONFIG_PM
+ static int serverworks_reinit_one(struct pci_dev *pdev)
+ {
++ struct ata_host *host = dev_get_drvdata(&pdev->dev);
++ int rc;
++
++ rc = ata_pci_device_do_resume(pdev);
++ if (rc)
++ return rc;
++
+ /* Force master latency timer to 64 PCI clocks */
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
+
+- switch (pdev->device)
+- {
++ switch (pdev->device) {
+ case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE:
+ serverworks_fixup_osb4(pdev);
+ break;
+ case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
+- ata_pci_clear_simplex(pdev);
++ ata_pci_bmdma_clear_simplex(pdev);
+ /* fall through */
+ case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE:
+ case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2:
+@@ -554,7 +492,9 @@ static int serverworks_reinit_one(struct pci_dev *pdev)
+ serverworks_fixup_ht1000(pdev);
+ break;
+ }
+- return ata_pci_device_resume(pdev);
++
++ ata_host_resume(host);
++ return 0;
+ }
+ #endif
+
+diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
+index 7c5b2dd..720b864 100644
+--- a/drivers/ata/pata_sil680.c
++++ b/drivers/ata/pata_sil680.c
+@@ -192,54 +192,14 @@ static void sil680_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ static struct scsi_host_template sil680_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations sil680_port_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .cable_detect = sil680_cable_detect,
+ .set_piomode = sil680_set_piomode,
+ .set_dmamode = sil680_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = sil680_cable_detect,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ /**
+@@ -322,7 +282,6 @@ static int __devinit sil680_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info = {
+- .sht = &sil680_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -330,7 +289,6 @@ static int __devinit sil680_init_one(struct pci_dev *pdev,
+ .port_ops = &sil680_port_ops
+ };
+ static const struct ata_port_info info_slow = {
+- .sht = &sil680_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -346,6 +304,10 @@ static int __devinit sil680_init_one(struct pci_dev *pdev,
+ if (!printed_version++)
+ dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+
++ rc = pcim_enable_device(pdev);
++ if (rc)
++ return rc;
++
+ switch (sil680_init_chip(pdev, &try_mmio)) {
+ case 0:
+ ppi[0] = &info_slow;
+@@ -388,28 +350,33 @@ static int __devinit sil680_init_one(struct pci_dev *pdev,
+ host->ports[0]->ioaddr.cmd_addr = mmio_base + 0x80;
+ host->ports[0]->ioaddr.ctl_addr = mmio_base + 0x8a;
+ host->ports[0]->ioaddr.altstatus_addr = mmio_base + 0x8a;
+- ata_std_ports(&host->ports[0]->ioaddr);
++ ata_sff_std_ports(&host->ports[0]->ioaddr);
+ host->ports[1]->ioaddr.bmdma_addr = mmio_base + 0x08;
+ host->ports[1]->ioaddr.cmd_addr = mmio_base + 0xc0;
+ host->ports[1]->ioaddr.ctl_addr = mmio_base + 0xca;
+ host->ports[1]->ioaddr.altstatus_addr = mmio_base + 0xca;
+- ata_std_ports(&host->ports[1]->ioaddr);
++ ata_sff_std_ports(&host->ports[1]->ioaddr);
+
+ /* Register & activate */
+- return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+- &sil680_sht);
++ return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
++ IRQF_SHARED, &sil680_sht);
+
+ use_ioports:
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &sil680_sht, NULL);
+ }
+
+ #ifdef CONFIG_PM
+ static int sil680_reinit_one(struct pci_dev *pdev)
+ {
+- int try_mmio;
++ struct ata_host *host = dev_get_drvdata(&pdev->dev);
++ int try_mmio, rc;
+
++ rc = ata_pci_device_do_resume(pdev);
++ if (rc)
++ return rc;
+ sil680_init_chip(pdev, &try_mmio);
+- return ata_pci_device_resume(pdev);
++ ata_host_resume(host);
++ return 0;
+ }
+ #endif
+
+diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
+index dc7e915..e82c66e 100644
+--- a/drivers/ata/pata_sis.c
++++ b/drivers/ata/pata_sis.c
+@@ -156,24 +156,11 @@ static int sis_pre_reset(struct ata_link *link, unsigned long deadline)
+ /* Clear the FIFO settings. We can't enable the FIFO until
+ we know we are poking at a disk */
+ pci_write_config_byte(pdev, 0x4B, 0);
+- return ata_std_prereset(link, deadline);
++ return ata_sff_prereset(link, deadline);
+ }
+
+
+ /**
+- * sis_error_handler - Probe specified port on PATA host controller
+- * @ap: Port to probe
+- *
+- * LOCKING:
+- * None (inherited from caller).
+- */
+-
+-static void sis_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, sis_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+-}
+-
+-/**
+ * sis_set_fifo - Set RWP fifo bits for this device
+ * @ap: Port
+ * @adev: Device
+@@ -514,217 +501,57 @@ static void sis_133_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+ }
+
+ static struct scsi_host_template sis_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static const struct ata_port_operations sis_133_ops = {
++static struct ata_port_operations sis_133_for_sata_ops = {
++ .inherits = &ata_bmdma_port_ops,
+ .set_piomode = sis_133_set_piomode,
+ .set_dmamode = sis_133_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = sis_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .cable_detect = sis_133_cable_detect,
++};
+
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++static struct ata_port_operations sis_base_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .prereset = sis_pre_reset,
+ };
+
+-static const struct ata_port_operations sis_133_for_sata_ops = {
++static struct ata_port_operations sis_133_ops = {
++ .inherits = &sis_base_ops,
+ .set_piomode = sis_133_set_piomode,
+ .set_dmamode = sis_133_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .cable_detect = sis_133_cable_detect,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+-static const struct ata_port_operations sis_133_early_ops = {
++static struct ata_port_operations sis_133_early_ops = {
++ .inherits = &sis_base_ops,
+ .set_piomode = sis_100_set_piomode,
+ .set_dmamode = sis_133_early_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = sis_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .cable_detect = sis_66_cable_detect,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+-static const struct ata_port_operations sis_100_ops = {
++static struct ata_port_operations sis_100_ops = {
++ .inherits = &sis_base_ops,
+ .set_piomode = sis_100_set_piomode,
+ .set_dmamode = sis_100_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = sis_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .cable_detect = sis_66_cable_detect,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+-static const struct ata_port_operations sis_66_ops = {
++static struct ata_port_operations sis_66_ops = {
++ .inherits = &sis_base_ops,
+ .set_piomode = sis_old_set_piomode,
+ .set_dmamode = sis_66_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+ .cable_detect = sis_66_cable_detect,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = sis_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+-static const struct ata_port_operations sis_old_ops = {
++static struct ata_port_operations sis_old_ops = {
++ .inherits = &sis_base_ops,
+ .set_piomode = sis_old_set_piomode,
+ .set_dmamode = sis_old_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = sis_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
+ };
+
+ static const struct ata_port_info sis_info = {
+- .sht = &sis_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07,
+@@ -732,7 +559,6 @@ static const struct ata_port_info sis_info = {
+ .port_ops = &sis_old_ops,
+ };
+ static const struct ata_port_info sis_info33 = {
+- .sht = &sis_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07,
+@@ -740,42 +566,36 @@ static const struct ata_port_info sis_info33 = {
+ .port_ops = &sis_old_ops,
+ };
+ static const struct ata_port_info sis_info66 = {
+- .sht = &sis_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = ATA_UDMA4, /* UDMA 66 */
+ .port_ops = &sis_66_ops,
+ };
+ static const struct ata_port_info sis_info100 = {
+- .sht = &sis_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = ATA_UDMA5,
+ .port_ops = &sis_100_ops,
+ };
+ static const struct ata_port_info sis_info100_early = {
+- .sht = &sis_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .udma_mask = ATA_UDMA5,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .port_ops = &sis_66_ops,
+ };
+ static const struct ata_port_info sis_info133 = {
+- .sht = &sis_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &sis_133_ops,
+ };
+ const struct ata_port_info sis_info133_for_sata = {
+- .sht = &sis_sht,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &sis_133_for_sata_ops,
+ };
+ static const struct ata_port_info sis_info133_early = {
+- .sht = &sis_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = ATA_UDMA6,
+@@ -857,11 +677,11 @@ static void sis_fixup(struct pci_dev *pdev, struct sis_chipset *sis)
+ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ static int printed_version;
+- struct ata_port_info port;
+- const struct ata_port_info *ppi[] = { &port, NULL };
++ const struct ata_port_info *ppi[] = { NULL, NULL };
+ struct pci_dev *host = NULL;
+ struct sis_chipset *chipset = NULL;
+ struct sis_chipset *sets;
++ int rc;
+
+ static struct sis_chipset sis_chipsets[] = {
+
+@@ -914,8 +734,11 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+ dev_printk(KERN_DEBUG, &pdev->dev,
+ "version " DRV_VERSION "\n");
+
+- /* We have to find the bridge first */
++ rc = pcim_enable_device(pdev);
++ if (rc)
++ return rc;
+
++ /* We have to find the bridge first */
+ for (sets = &sis_chipsets[0]; sets->device; sets++) {
+ host = pci_get_device(PCI_VENDOR_ID_SI, sets->device, NULL);
+ if (host != NULL) {
+@@ -994,12 +817,11 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+ if (chipset == NULL)
+ return -ENODEV;
+
+- port = *chipset->info;
+- port.private_data = chipset;
++ ppi[0] = chipset->info;
+
+ sis_fixup(pdev, chipset);
+
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &sis_sht, chipset);
+ }
+
+ static const struct pci_device_id sis_pci_tbl[] = {
+diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
+index 81ef207..70d94fb 100644
+--- a/drivers/ata/pata_sl82c105.c
++++ b/drivers/ata/pata_sl82c105.c
+@@ -60,13 +60,7 @@ static int sl82c105_pre_reset(struct ata_link *link, unsigned long deadline)
+
+ if (ap->port_no && !pci_test_config_bits(pdev, &sl82c105_enable_bits[ap->port_no]))
+ return -ENOENT;
+- return ata_std_prereset(link, deadline);
+-}
+-
+-
+-static void sl82c105_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, sl82c105_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+
+@@ -235,55 +229,17 @@ static int sl82c105_qc_defer(struct ata_queued_cmd *qc)
+ }
+
+ static struct scsi_host_template sl82c105_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations sl82c105_port_ops = {
+- .set_piomode = sl82c105_set_piomode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = sl82c105_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
++ .inherits = &ata_bmdma_port_ops,
++ .qc_defer = sl82c105_qc_defer,
+ .bmdma_start = sl82c105_bmdma_start,
+ .bmdma_stop = sl82c105_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_defer = sl82c105_qc_defer,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .cable_detect = ata_cable_40wire,
++ .set_piomode = sl82c105_set_piomode,
++ .prereset = sl82c105_pre_reset,
+ };
+
+ /**
+@@ -327,14 +283,12 @@ static int sl82c105_bridge_revision(struct pci_dev *pdev)
+ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info_dma = {
+- .sht = &sl82c105_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .port_ops = &sl82c105_port_ops
+ };
+ static const struct ata_port_info info_early = {
+- .sht = &sl82c105_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .port_ops = &sl82c105_port_ops
+@@ -344,6 +298,11 @@ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id
+ NULL };
+ u32 val;
+ int rev;
++ int rc;
++
++ rc = pcim_enable_device(dev);
++ if (rc)
++ return rc;
+
+ rev = sl82c105_bridge_revision(dev);
+
+@@ -358,7 +317,7 @@ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id
+ val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16;
+ pci_write_config_dword(dev, 0x40, val);
+
+- return ata_pci_init_one(dev, ppi);
++ return ata_pci_sff_init_one(dev, ppi, &sl82c105_sht, NULL);
+ }
+
+ static const struct pci_device_id sl82c105[] = {
+diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c
+index 403eafc..b181261 100644
+--- a/drivers/ata/pata_triflex.c
++++ b/drivers/ata/pata_triflex.c
+@@ -66,16 +66,11 @@ static int triflex_prereset(struct ata_link *link, unsigned long deadline)
+ if (!pci_test_config_bits(pdev, &triflex_enable_bits[ap->port_no]))
+ return -ENOENT;
+
+- return ata_std_prereset(link, deadline);
++ return ata_sff_prereset(link, deadline);
+ }
+
+
+
+-static void triflex_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, triflex_prereset, ata_std_softreset, NULL, ata_std_postreset);
+-}
+-
+ /**
+ * triflex_load_timing - timing configuration
+ * @ap: ATA interface
+@@ -180,60 +175,21 @@ static void triflex_bmdma_stop(struct ata_queued_cmd *qc)
+ }
+
+ static struct scsi_host_template triflex_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations triflex_port_ops = {
+- .set_piomode = triflex_set_piomode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = triflex_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_40wire,
+-
+- .bmdma_setup = ata_bmdma_setup,
++ .inherits = &ata_bmdma_port_ops,
+ .bmdma_start = triflex_bmdma_start,
+ .bmdma_stop = triflex_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .cable_detect = ata_cable_40wire,
++ .set_piomode = triflex_set_piomode,
++ .prereset = triflex_prereset,
+ };
+
+ static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ static const struct ata_port_info info = {
+- .sht = &triflex_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -245,7 +201,7 @@ static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ if (!printed_version++)
+ dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");
+
+- return ata_pci_init_one(dev, ppi);
++ return ata_pci_sff_init_one(dev, ppi, &triflex_sht, NULL);
+ }
+
+ static const struct pci_device_id triflex[] = {
+diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
+index d119a68..d484074 100644
+--- a/drivers/ata/pata_via.c
++++ b/drivers/ata/pata_via.c
+@@ -210,23 +210,11 @@ static int via_pre_reset(struct ata_link *link, unsigned long deadline)
+ return -ENOENT;
+ }
+
+- return ata_std_prereset(link, deadline);
++ return ata_sff_prereset(link, deadline);
+ }
+
+
+ /**
+- * via_error_handler - reset for VIA chips
+- * @ap: ATA port
+- *
+- * Handle the reset callback for the later chips with cable detect
+- */
+-
+-static void via_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, via_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
+-}
+-
+-/**
+ * via_do_set_mode - set initial PIO mode data
+ * @ap: ATA interface
+ * @adev: ATA device
+@@ -335,89 +323,20 @@ static void via_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ }
+
+ static struct scsi_host_template via_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations via_port_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .cable_detect = via_cable_detect,
+ .set_piomode = via_set_piomode,
+ .set_dmamode = via_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = via_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = via_cable_detect,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .prereset = via_pre_reset,
+ };
+
+ static struct ata_port_operations via_port_ops_noirq = {
+- .set_piomode = via_set_piomode,
+- .set_dmamode = via_set_dmamode,
+- .mode_filter = ata_pci_default_filter,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = via_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = via_cable_detect,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = ata_data_xfer_noirq,
+-
+- .irq_handler = ata_interrupt,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .inherits = &via_port_ops,
++ .sff_data_xfer = ata_sff_data_xfer_noirq,
+ };
+
+ /**
+@@ -467,7 +386,6 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ /* Early VIA without UDMA support */
+ static const struct ata_port_info via_mwdma_info = {
+- .sht = &via_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -475,7 +393,6 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ };
+ /* Ditto with IRQ masking required */
+ static const struct ata_port_info via_mwdma_info_borked = {
+- .sht = &via_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -483,7 +400,6 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ };
+ /* VIA UDMA 33 devices (and borked 66) */
+ static const struct ata_port_info via_udma33_info = {
+- .sht = &via_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -492,7 +408,6 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ };
+ /* VIA UDMA 66 devices */
+ static const struct ata_port_info via_udma66_info = {
+- .sht = &via_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -501,7 +416,6 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ };
+ /* VIA UDMA 100 devices */
+ static const struct ata_port_info via_udma100_info = {
+- .sht = &via_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+@@ -510,24 +424,27 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ };
+ /* UDMA133 with bad AST (All current 133) */
+ static const struct ata_port_info via_udma133_info = {
+- .sht = &via_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
+ .udma_mask = ATA_UDMA6, /* FIXME: should check north bridge */
+ .port_ops = &via_port_ops
+ };
+- struct ata_port_info type;
+- const struct ata_port_info *ppi[] = { &type, NULL };
++ const struct ata_port_info *ppi[] = { NULL, NULL };
+ struct pci_dev *isa = NULL;
+ const struct via_isa_bridge *config;
+ static int printed_version;
+ u8 enable;
+ u32 timing;
++ int rc;
+
+ if (!printed_version++)
+ dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+
++ rc = pcim_enable_device(pdev);
++ if (rc)
++ return rc;
++
+ /* To find out how the IDE will behave and what features we
+ actually have to look at the bridge not the IDE controller */
+ for (config = via_isa_bridges; config->id; config++)
+@@ -561,25 +478,25 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ switch(config->flags & VIA_UDMA) {
+ case VIA_UDMA_NONE:
+ if (config->flags & VIA_NO_UNMASK)
+- type = via_mwdma_info_borked;
++ ppi[0] = &via_mwdma_info_borked;
+ else
+- type = via_mwdma_info;
++ ppi[0] = &via_mwdma_info;
+ break;
+ case VIA_UDMA_33:
+- type = via_udma33_info;
++ ppi[0] = &via_udma33_info;
+ break;
+ case VIA_UDMA_66:
+- type = via_udma66_info;
++ ppi[0] = &via_udma66_info;
+ /* The 66 MHz devices require we enable the clock */
+ pci_read_config_dword(pdev, 0x50, &timing);
+ timing |= 0x80008;
+ pci_write_config_dword(pdev, 0x50, timing);
+ break;
+ case VIA_UDMA_100:
+- type = via_udma100_info;
++ ppi[0] = &via_udma100_info;
+ break;
+ case VIA_UDMA_133:
+- type = via_udma133_info;
++ ppi[0] = &via_udma133_info;
+ break;
+ default:
+ WARN_ON(1);
+@@ -594,9 +511,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ }
+
+ /* We have established the device type, now fire it up */
+- type.private_data = (void *)config;
+-
+- return ata_pci_init_one(pdev, ppi);
++ return ata_pci_sff_init_one(pdev, ppi, &via_sht, (void *)config);
+ }
+
+ #ifdef CONFIG_PM
+@@ -615,6 +530,11 @@ static int via_reinit_one(struct pci_dev *pdev)
+ u32 timing;
+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ const struct via_isa_bridge *config = host->private_data;
++ int rc;
++
++ rc = ata_pci_device_do_resume(pdev);
++ if (rc)
++ return rc;
+
+ via_config_fifo(pdev, config->flags);
+
+@@ -630,7 +550,9 @@ static int via_reinit_one(struct pci_dev *pdev)
+ timing &= ~0x80008;
+ pci_write_config_dword(pdev, 0x50, timing);
+ }
+- return ata_pci_device_resume(pdev);
++
++ ata_host_resume(host);
++ return 0;
+ }
+ #endif
+
+diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c
+index 99c92ed..6e52a35 100644
+--- a/drivers/ata/pata_winbond.c
++++ b/drivers/ata/pata_winbond.c
+@@ -116,53 +116,20 @@ static unsigned int winbond_data_xfer(struct ata_device *dev,
+ buflen += 4 - slop;
+ }
+ } else
+- buflen = ata_data_xfer(dev, buf, buflen, rw);
++ buflen = ata_sff_data_xfer(dev, buf, buflen, rw);
+
+ return buflen;
+ }
+
+ static struct scsi_host_template winbond_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_PIO_SHT(DRV_NAME),
+ };
+
+ static struct ata_port_operations winbond_port_ops = {
+- .set_piomode = winbond_set_piomode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
++ .inherits = &ata_sff_port_ops,
++ .sff_data_xfer = winbond_data_xfer,
+ .cable_detect = ata_cable_40wire,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+-
+- .data_xfer = winbond_data_xfer,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_sff_port_start,
++ .set_piomode = winbond_set_piomode,
+ };
+
+ /**
+@@ -231,7 +198,7 @@ static __init int winbond_init_one(unsigned long port)
+ ap->ioaddr.cmd_addr = cmd_addr;
+ ap->ioaddr.altstatus_addr = ctl_addr;
+ ap->ioaddr.ctl_addr = ctl_addr;
+- ata_std_ports(&ap->ioaddr);
++ ata_sff_std_ports(&ap->ioaddr);
+
+ /* hook in a private data structure per channel */
+ host->private_data = &winbond_data[nr_winbond_host];
+@@ -239,7 +206,7 @@ static __init int winbond_init_one(unsigned long port)
+ winbond_data[nr_winbond_host].platform_dev = pdev;
+
+ /* activate */
+- rc = ata_host_activate(host, 14 + i, ata_interrupt, 0,
++ rc = ata_host_activate(host, 14 + i, ata_sff_interrupt, 0,
+ &winbond_sht);
+ if (rc)
+ goto err_unregister;
+diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
+index 8e1b7e9..be53545 100644
+--- a/drivers/ata/pdc_adma.c
++++ b/drivers/ata/pdc_adma.c
+@@ -131,56 +131,33 @@ struct adma_port_priv {
+ static int adma_ata_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent);
+ static int adma_port_start(struct ata_port *ap);
+-static void adma_host_stop(struct ata_host *host);
+ static void adma_port_stop(struct ata_port *ap);
+ static void adma_qc_prep(struct ata_queued_cmd *qc);
+ static unsigned int adma_qc_issue(struct ata_queued_cmd *qc);
+ static int adma_check_atapi_dma(struct ata_queued_cmd *qc);
+-static void adma_bmdma_stop(struct ata_queued_cmd *qc);
+-static u8 adma_bmdma_status(struct ata_port *ap);
+-static void adma_irq_clear(struct ata_port *ap);
+ static void adma_freeze(struct ata_port *ap);
+ static void adma_thaw(struct ata_port *ap);
+-static void adma_error_handler(struct ata_port *ap);
++static int adma_prereset(struct ata_link *link, unsigned long deadline);
+
+ static struct scsi_host_template adma_ata_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
+- .proc_name = DRV_NAME,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
++ ATA_BASE_SHT(DRV_NAME),
+ .sg_tablesize = LIBATA_MAX_PRD,
+ .dma_boundary = ADMA_DMA_BOUNDARY,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .use_clustering = ENABLE_CLUSTERING,
+- .emulated = ATA_SHT_EMULATED,
+ };
+
+-static const struct ata_port_operations adma_ata_ops = {
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .exec_command = ata_exec_command,
+- .check_status = ata_check_status,
+- .dev_select = ata_std_dev_select,
++static struct ata_port_operations adma_ata_ops = {
++ .inherits = &ata_sff_port_ops,
++
+ .check_atapi_dma = adma_check_atapi_dma,
+- .data_xfer = ata_data_xfer,
+ .qc_prep = adma_qc_prep,
+ .qc_issue = adma_qc_issue,
++
+ .freeze = adma_freeze,
+ .thaw = adma_thaw,
+- .error_handler = adma_error_handler,
+- .irq_clear = adma_irq_clear,
+- .irq_on = ata_irq_on,
++ .prereset = adma_prereset,
++
+ .port_start = adma_port_start,
+ .port_stop = adma_port_stop,
+- .host_stop = adma_host_stop,
+- .bmdma_stop = adma_bmdma_stop,
+- .bmdma_status = adma_bmdma_status,
+ };
+
+ static struct ata_port_info adma_port_info[] = {
+@@ -213,21 +190,6 @@ static int adma_check_atapi_dma(struct ata_queued_cmd *qc)
+ return 1; /* ATAPI DMA not yet supported */
+ }
+
+-static void adma_bmdma_stop(struct ata_queued_cmd *qc)
+-{
+- /* nothing */
+-}
+-
+-static u8 adma_bmdma_status(struct ata_port *ap)
+-{
+- return 0;
+-}
+-
+-static void adma_irq_clear(struct ata_port *ap)
+-{
+- /* nothing */
+-}
+-
+ static void adma_reset_engine(struct ata_port *ap)
+ {
+ void __iomem *chan = ADMA_PORT_REGS(ap);
+@@ -246,7 +208,7 @@ static void adma_reinit_engine(struct ata_port *ap)
+
+ /* mask/clear ATA interrupts */
+ writeb(ATA_NIEN, ap->ioaddr.ctl_addr);
+- ata_check_status(ap);
++ ata_sff_check_status(ap);
+
+ /* reset the ADMA engine */
+ adma_reset_engine(ap);
+@@ -281,7 +243,7 @@ static void adma_freeze(struct ata_port *ap)
+
+ /* mask/clear ATA interrupts */
+ writeb(ATA_NIEN, ap->ioaddr.ctl_addr);
+- ata_check_status(ap);
++ ata_sff_check_status(ap);
+
+ /* reset ADMA to idle state */
+ writew(aPIOMD4 | aNIEN | aRSTADM, chan + ADMA_CONTROL);
+@@ -304,13 +266,7 @@ static int adma_prereset(struct ata_link *link, unsigned long deadline)
+ pp->state = adma_state_mmio;
+ adma_reinit_engine(ap);
+
+- return ata_std_prereset(link, deadline);
+-}
+-
+-static void adma_error_handler(struct ata_port *ap)
+-{
+- ata_do_eh(ap, adma_prereset, ata_std_softreset, NULL,
+- ata_std_postreset);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ static int adma_fill_sg(struct ata_queued_cmd *qc)
+@@ -366,7 +322,7 @@ static void adma_qc_prep(struct ata_queued_cmd *qc)
+
+ adma_enter_reg_mode(qc->ap);
+ if (qc->tf.protocol != ATA_PROT_DMA) {
+- ata_qc_prep(qc);
++ ata_sff_qc_prep(qc);
+ return;
+ }
+
+@@ -465,7 +421,7 @@ static unsigned int adma_qc_issue(struct ata_queued_cmd *qc)
+ }
+
+ pp->state = adma_state_mmio;
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ static inline unsigned int adma_intr_pkt(struct ata_host *host)
+@@ -536,7 +492,7 @@ static inline unsigned int adma_intr_mmio(struct ata_host *host)
+ if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
+
+ /* check main status, clearing INTRQ */
+- u8 status = ata_check_status(ap);
++ u8 status = ata_sff_check_status(ap);
+ if ((status & ATA_BUSY))
+ continue;
+ DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
+@@ -633,14 +589,6 @@ static void adma_port_stop(struct ata_port *ap)
+ adma_reset_engine(ap);
+ }
+
+-static void adma_host_stop(struct ata_host *host)
+-{
+- unsigned int port_no;
+-
+- for (port_no = 0; port_no < ADMA_PORTS; ++port_no)
+- adma_reset_engine(host->ports[port_no]);
+-}
+-
+ static void adma_host_init(struct ata_host *host, unsigned int chip_id)
+ {
+ unsigned int port_no;
+diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
+index 9d1e3ca..fddd346 100644
+--- a/drivers/ata/sata_fsl.c
++++ b/drivers/ata/sata_fsl.c
+@@ -35,7 +35,6 @@ enum {
+ SATA_FSL_HOST_FLAGS = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+ ATA_FLAG_NCQ),
+- SATA_FSL_HOST_LFLAGS = ATA_LFLAG_SKIP_D2H_BSY,
+
+ SATA_FSL_MAX_CMDS = SATA_FSL_QUEUE_DEPTH,
+ SATA_FSL_CMD_HDR_SIZE = 16, /* 4 DWORDS */
+@@ -245,17 +244,6 @@ struct sata_fsl_port_priv {
+ dma_addr_t cmdslot_paddr;
+ struct command_desc *cmdentry;
+ dma_addr_t cmdentry_paddr;
+-
+- /*
+- * SATA FSL controller has a Status FIS which should contain the
+- * received D2H FIS & taskfile registers. This SFIS is present in
+- * the command descriptor, and to have a ready reference to it,
+- * we are caching it here, quite similar to what is done in H/W on
+- * AHCI compliant devices by copying taskfile fields to a 32-bit
+- * register.
+- */
+-
+- struct ata_taskfile tf;
+ };
+
+ /*
+@@ -465,6 +453,20 @@ static unsigned int sata_fsl_qc_issue(struct ata_queued_cmd *qc)
+ return 0;
+ }
+
++static bool sata_fsl_qc_fill_rtf(struct ata_queued_cmd *qc)
++{
++ struct sata_fsl_port_priv *pp = qc->ap->private_data;
++ struct sata_fsl_host_priv *host_priv = qc->ap->host->private_data;
++ void __iomem *hcr_base = host_priv->hcr_base;
++ unsigned int tag = sata_fsl_tag(qc->tag, hcr_base);
++ struct command_desc *cd;
++
++ cd = pp->cmdentry + tag;
++
++ ata_tf_from_fis(cd->sfis, &qc->result_tf);
++ return true;
++}
++
+ static int sata_fsl_scr_write(struct ata_port *ap, unsigned int sc_reg_in,
+ u32 val)
+ {
+@@ -556,38 +558,6 @@ static void sata_fsl_thaw(struct ata_port *ap)
+ ioread32(hcr_base + HCONTROL), ioread32(hcr_base + HSTATUS));
+ }
+
+-/*
+- * NOTE : 1st D2H FIS from device does not update sfis in command descriptor.
+- */
+-static inline void sata_fsl_cache_taskfile_from_d2h_fis(struct ata_queued_cmd
+- *qc,
+- struct ata_port *ap)
+-{
+- struct sata_fsl_port_priv *pp = ap->private_data;
+- struct sata_fsl_host_priv *host_priv = ap->host->private_data;
+- void __iomem *hcr_base = host_priv->hcr_base;
+- unsigned int tag = sata_fsl_tag(qc->tag, hcr_base);
+- struct command_desc *cd;
+-
+- cd = pp->cmdentry + tag;
+-
+- ata_tf_from_fis(cd->sfis, &pp->tf);
+-}
+-
+-static u8 sata_fsl_check_status(struct ata_port *ap)
+-{
+- struct sata_fsl_port_priv *pp = ap->private_data;
+-
+- return pp->tf.command;
+-}
+-
+-static void sata_fsl_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+-{
+- struct sata_fsl_port_priv *pp = ap->private_data;
+-
+- *tf = pp->tf;
+-}
+-
+ static int sata_fsl_port_start(struct ata_port *ap)
+ {
+ struct device *dev = ap->host->dev;
+@@ -708,6 +678,15 @@ static unsigned int sata_fsl_dev_classify(struct ata_port *ap)
+ return ata_dev_classify(&tf);
+ }
+
++static int sata_fsl_prereset(struct ata_linke *link, unsigned long deadline)
++{
++ /* FIXME: Never skip softreset, sata_fsl_softreset() is
++ * combination of soft and hard resets. sata_fsl_softreset()
++ * needs to be splitted into soft and hard resets.
++ */
++ return 0;
++}
++
+ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline)
+ {
+@@ -913,16 +892,6 @@ err:
+ return -EIO;
+ }
+
+-static void sata_fsl_error_handler(struct ata_port *ap)
+-{
+-
+- DPRINTK("in xx_error_handler\n");
+-
+- /* perform recovery */
+- ata_do_eh(ap, ata_std_prereset, sata_fsl_softreset, sata_std_hardreset,
+- ata_std_postreset);
+-}
+-
+ static void sata_fsl_post_internal_cmd(struct ata_queued_cmd *qc)
+ {
+ if (qc->flags & ATA_QCFLAG_FAILED)
+@@ -934,11 +903,6 @@ static void sata_fsl_post_internal_cmd(struct ata_queued_cmd *qc)
+ }
+ }
+
+-static void sata_fsl_irq_clear(struct ata_port *ap)
+-{
+- /* unused */
+-}
+-
+ static void sata_fsl_error_intr(struct ata_port *ap)
+ {
+ struct ata_link *link = &ap->link;
+@@ -996,7 +960,7 @@ static void sata_fsl_error_intr(struct ata_port *ap)
+ /* handle fatal errors */
+ if (hstatus & FATAL_ERROR_DECODE) {
+ err_mask |= AC_ERR_ATA_BUS;
+- action |= ATA_EH_SOFTRESET;
++ action |= ATA_EH_RESET;
+ /* how will fatal error interrupts be completed ?? */
+ freeze = 1;
+ }
+@@ -1013,10 +977,9 @@ static void sata_fsl_error_intr(struct ata_port *ap)
+ /* record error info */
+ qc = ata_qc_from_tag(ap, link->active_tag);
+
+- if (qc) {
+- sata_fsl_cache_taskfile_from_d2h_fis(qc, qc->ap);
++ if (qc)
+ qc->err_mask |= err_mask;
+- } else
++ else
+ ehi->err_mask |= err_mask;
+
+ ehi->action |= action;
+@@ -1029,14 +992,6 @@ static void sata_fsl_error_intr(struct ata_port *ap)
+ ata_port_abort(ap);
+ }
+
+-static void sata_fsl_qc_complete(struct ata_queued_cmd *qc)
+-{
+- if (qc->flags & ATA_QCFLAG_RESULT_TF) {
+- DPRINTK("xx_qc_complete called\n");
+- sata_fsl_cache_taskfile_from_d2h_fis(qc, qc->ap);
+- }
+-}
+-
+ static void sata_fsl_host_intr(struct ata_port *ap)
+ {
+ struct ata_link *link = &ap->link;
+@@ -1077,10 +1032,8 @@ static void sata_fsl_host_intr(struct ata_port *ap)
+ for (i = 0; i < SATA_FSL_QUEUE_DEPTH; i++) {
+ if (qc_active & (1 << i)) {
+ qc = ata_qc_from_tag(ap, i);
+- if (qc) {
+- sata_fsl_qc_complete(qc);
++ if (qc)
+ ata_qc_complete(qc);
+- }
+ DPRINTK
+ ("completing ncq cmd,tag=%d,CC=0x%x,CA=0x%x\n",
+ i, ioread32(hcr_base + CC),
+@@ -1096,10 +1049,8 @@ static void sata_fsl_host_intr(struct ata_port *ap)
+ DPRINTK("completing non-ncq cmd, tag=%d,CC=0x%x\n",
+ link->active_tag, ioread32(hcr_base + CC));
+
+- if (qc) {
+- sata_fsl_qc_complete(qc);
++ if (qc)
+ ata_qc_complete(qc);
+- }
+ } else {
+ /* Spurious Interrupt!! */
+ DPRINTK("spurious interrupt!!, CC = 0x%x\n",
+@@ -1197,41 +1148,26 @@ static int sata_fsl_init_controller(struct ata_host *host)
+ * scsi mid-layer and libata interface structures
+ */
+ static struct scsi_host_template sata_fsl_sht = {
+- .module = THIS_MODULE,
+- .name = "sata_fsl",
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .change_queue_depth = ata_scsi_change_queue_depth,
++ ATA_NCQ_SHT("sata_fsl"),
+ .can_queue = SATA_FSL_QUEUE_DEPTH,
+- .this_id = ATA_SHT_THIS_ID,
+ .sg_tablesize = SATA_FSL_MAX_PRD_USABLE,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = "sata_fsl",
+ .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
+ };
+
+ static const struct ata_port_operations sata_fsl_ops = {
+- .check_status = sata_fsl_check_status,
+- .check_altstatus = sata_fsl_check_status,
+- .dev_select = ata_noop_dev_select,
+-
+- .tf_read = sata_fsl_tf_read,
++ .inherits = &sata_port_ops,
+
+ .qc_prep = sata_fsl_qc_prep,
+ .qc_issue = sata_fsl_qc_issue,
+- .irq_clear = sata_fsl_irq_clear,
++ .qc_fill_rtf = sata_fsl_qc_fill_rtf,
+
+ .scr_read = sata_fsl_scr_read,
+ .scr_write = sata_fsl_scr_write,
+
+ .freeze = sata_fsl_freeze,
+ .thaw = sata_fsl_thaw,
+- .error_handler = sata_fsl_error_handler,
++ .prereset = sata_fsl_prereset,
++ .softreset = sata_fsl_softreset,
+ .post_internal_cmd = sata_fsl_post_internal_cmd,
+
+ .port_start = sata_fsl_port_start,
+@@ -1241,7 +1177,6 @@ static const struct ata_port_operations sata_fsl_ops = {
+ static const struct ata_port_info sata_fsl_port_info[] = {
+ {
+ .flags = SATA_FSL_HOST_FLAGS,
+- .link_flags = SATA_FSL_HOST_LFLAGS,
+ .pio_mask = 0x1f, /* pio 0-4 */
+ .udma_mask = 0x7f, /* udma 0-6 */
+ .port_ops = &sata_fsl_ops,
+@@ -1297,11 +1232,6 @@ static int sata_fsl_probe(struct of_device *ofdev,
+ /* host->iomap is not used currently */
+ host->private_data = host_priv;
+
+- /* setup port(s) */
+-
+- host->ports[0]->ioaddr.cmd_addr = host_priv->hcr_base;
+- host->ports[0]->ioaddr.scr_addr = host_priv->ssr_base;
+-
+ /* initialize host controller */
+ sata_fsl_init_controller(host);
+
+diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
+index 59e65ed..d27bb9a 100644
+--- a/drivers/ata/sata_inic162x.c
++++ b/drivers/ata/sata_inic162x.c
+@@ -109,21 +109,7 @@ struct inic_port_priv {
+ };
+
+ static struct scsi_host_template inic_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static const int scr_map[] = {
+@@ -236,7 +222,7 @@ static void inic_bmdma_setup(struct ata_queued_cmd *qc)
+ writeb(pp->cached_prdctl, port_base + PORT_PRD_CTL);
+
+ /* issue r/w command */
+- ap->ops->exec_command(ap, &qc->tf);
++ ap->ops->sff_exec_command(ap, &qc->tf);
+ }
+
+ static void inic_bmdma_start(struct ata_queued_cmd *qc)
+@@ -266,11 +252,6 @@ static u8 inic_bmdma_status(struct ata_port *ap)
+ return ATA_DMA_INTR;
+ }
+
+-static void inic_irq_clear(struct ata_port *ap)
+-{
+- /* noop */
+-}
+-
+ static void inic_host_intr(struct ata_port *ap)
+ {
+ void __iomem *port_base = inic_port_base(ap);
+@@ -286,14 +267,14 @@ static void inic_host_intr(struct ata_port *ap)
+ ata_qc_from_tag(ap, ap->link.active_tag);
+
+ if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) {
+- ata_chk_status(ap); /* clear ATA interrupt */
++ ap->ops->sff_check_status(ap); /* clear ATA interrupt */
+ return;
+ }
+
+- if (likely(ata_host_intr(ap, qc)))
++ if (likely(ata_sff_host_intr(ap, qc)))
+ return;
+
+- ata_chk_status(ap); /* clear ATA interrupt */
++ ap->ops->sff_check_status(ap); /* clear ATA interrupt */
+ ata_port_printk(ap, KERN_WARNING, "unhandled "
+ "interrupt, irq_stat=%x\n", irq_stat);
+ return;
+@@ -370,12 +351,12 @@ static unsigned int inic_qc_issue(struct ata_queued_cmd *qc)
+ */
+ if (unlikely(qc->tf.command == ATA_CMD_ID_ATA ||
+ qc->tf.command == ATA_CMD_ID_ATAPI)) {
+- u8 stat = ata_chk_status(ap);
++ u8 stat = ap->ops->sff_check_status(ap);
+ if (stat == 0x7f || stat == 0xff)
+ return AC_ERR_HSM;
+ }
+
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ static void inic_freeze(struct ata_port *ap)
+@@ -384,7 +365,7 @@ static void inic_freeze(struct ata_port *ap)
+
+ __inic_set_pirq_mask(ap, PIRQ_MASK_FREEZE);
+
+- ata_chk_status(ap);
++ ap->ops->sff_check_status(ap);
+ writeb(0xff, port_base + PORT_IRQ_STAT);
+
+ readb(port_base + PORT_IRQ_STAT); /* flush */
+@@ -394,7 +375,7 @@ static void inic_thaw(struct ata_port *ap)
+ {
+ void __iomem *port_base = inic_port_base(ap);
+
+- ata_chk_status(ap);
++ ap->ops->sff_check_status(ap);
+ writeb(0xff, port_base + PORT_IRQ_STAT);
+
+ __inic_set_pirq_mask(ap, PIRQ_MASK_OTHER);
+@@ -436,10 +417,8 @@ static int inic_hardreset(struct ata_link *link, unsigned int *class,
+ if (ata_link_online(link)) {
+ struct ata_taskfile tf;
+
+- /* wait a while before checking status */
+- ata_wait_after_reset(ap, deadline);
+-
+- rc = ata_wait_ready(ap, deadline);
++ /* wait for link to become ready */
++ rc = ata_sff_wait_after_reset(link, 1, deadline);
+ /* link occupied, -ENODEV too is an error */
+ if (rc) {
+ ata_link_printk(link, KERN_WARNING, "device not ready "
+@@ -447,10 +426,8 @@ static int inic_hardreset(struct ata_link *link, unsigned int *class,
+ return rc;
+ }
+
+- ata_tf_read(ap, &tf);
++ ata_sff_tf_read(ap, &tf);
+ *class = ata_dev_classify(&tf);
+- if (*class == ATA_DEV_UNKNOWN)
+- *class = ATA_DEV_NONE;
+ }
+
+ return 0;
+@@ -471,8 +448,7 @@ static void inic_error_handler(struct ata_port *ap)
+ spin_unlock_irqrestore(ap->lock, flags);
+
+ /* PIO and DMA engines have been stopped, perform recovery */
+- ata_do_eh(ap, ata_std_prereset, NULL, inic_hardreset,
+- ata_std_postreset);
++ ata_std_error_handler(ap);
+ }
+
+ static void inic_post_internal_cmd(struct ata_queued_cmd *qc)
+@@ -541,35 +517,26 @@ static int inic_port_start(struct ata_port *ap)
+ }
+
+ static struct ata_port_operations inic_port_ops = {
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .scr_read = inic_scr_read,
+- .scr_write = inic_scr_write,
++ .inherits = &ata_sff_port_ops,
+
+ .bmdma_setup = inic_bmdma_setup,
+ .bmdma_start = inic_bmdma_start,
+ .bmdma_stop = inic_bmdma_stop,
+ .bmdma_status = inic_bmdma_status,
+-
+- .irq_clear = inic_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .qc_prep = ata_qc_prep,
+ .qc_issue = inic_qc_issue,
+- .data_xfer = ata_data_xfer,
+
+ .freeze = inic_freeze,
+ .thaw = inic_thaw,
++ .softreset = ATA_OP_NULL, /* softreset is broken */
++ .hardreset = inic_hardreset,
+ .error_handler = inic_error_handler,
+ .post_internal_cmd = inic_post_internal_cmd,
+ .dev_config = inic_dev_config,
+
+- .port_resume = inic_port_resume,
++ .scr_read = inic_scr_read,
++ .scr_write = inic_scr_write,
+
++ .port_resume = inic_port_resume,
+ .port_start = inic_port_start,
+ };
+
+@@ -692,7 +659,7 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ ((unsigned long)iomap[2 * i + 1] | ATA_PCI_CTL_OFS);
+ port->scr_addr = iomap[MMIO_BAR] + offset + PORT_SCR;
+
+- ata_std_ports(port);
++ ata_sff_std_ports(port);
+
+ ata_port_pbar_desc(ap, MMIO_BAR, -1, "mmio");
+ ata_port_pbar_desc(ap, MMIO_BAR, offset, "port");
+diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
+index 6ebebde..26a6337 100644
+--- a/drivers/ata/sata_mv.c
++++ b/drivers/ata/sata_mv.c
+@@ -1,6 +1,7 @@
+ /*
+ * sata_mv.c - Marvell SATA support
+ *
++ * Copyright 2008: Marvell Corporation, all rights reserved.
+ * Copyright 2005: EMC Corporation, all rights reserved.
+ * Copyright 2005 Red Hat, Inc. All rights reserved.
+ *
+@@ -22,45 +23,34 @@
+ */
+
+ /*
+- sata_mv TODO list:
+-
+- 1) Needs a full errata audit for all chipsets. I implemented most
+- of the errata workarounds found in the Marvell vendor driver, but
+- I distinctly remember a couple workarounds (one related to PCI-X)
+- are still needed.
+-
+- 2) Improve/fix IRQ and error handling sequences.
+-
+- 3) ATAPI support (Marvell claims the 60xx/70xx chips can do it).
+-
+- 4) Think about TCQ support here, and for libata in general
+- with controllers that suppport it via host-queuing hardware
+- (a software-only implementation could be a nightmare).
+-
+- 5) Investigate problems with PCI Message Signalled Interrupts (MSI).
+-
+- 6) Add port multiplier support (intermediate)
+-
+- 8) Develop a low-power-consumption strategy, and implement it.
+-
+- 9) [Experiment, low priority] See if ATAPI can be supported using
+- "unknown FIS" or "vendor-specific FIS" support, or something creative
+- like that.
+-
+- 10) [Experiment, low priority] Investigate interrupt coalescing.
+- Quite often, especially with PCI Message Signalled Interrupts (MSI),
+- the overhead reduced by interrupt mitigation is quite often not
+- worth the latency cost.
+-
+- 11) [Experiment, Marvell value added] Is it possible to use target
+- mode to cross-connect two Linux boxes with Marvell cards? If so,
+- creating LibATA target mode support would be very interesting.
+-
+- Target mode, for those without docs, is the ability to directly
+- connect two SATA controllers.
+-
+-*/
+-
++ * sata_mv TODO list:
++ *
++ * --> Errata workaround for NCQ device errors.
++ *
++ * --> More errata workarounds for PCI-X.
++ *
++ * --> Complete a full errata audit for all chipsets to identify others.
++ *
++ * --> ATAPI support (Marvell claims the 60xx/70xx chips can do it).
++ *
++ * --> Investigate problems with PCI Message Signalled Interrupts (MSI).
++ *
++ * --> Cache frequently-accessed registers in mv_port_priv to reduce overhead.
++ *
++ * --> Develop a low-power-consumption strategy, and implement it.
++ *
++ * --> [Experiment, low priority] Investigate interrupt coalescing.
++ * Quite often, especially with PCI Message Signalled Interrupts (MSI),
++ * the overhead reduced by interrupt mitigation is quite often not
++ * worth the latency cost.
++ *
++ * --> [Experiment, Marvell value added] Is it possible to use target
++ * mode to cross-connect two Linux boxes with Marvell cards? If so,
++ * creating LibATA target mode support would be very interesting.
++ *
++ * Target mode, for those without docs, is the ability to directly
++ * connect two SATA ports.
++ */
+
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+@@ -74,6 +64,7 @@
+ #include <linux/device.h>
+ #include <linux/platform_device.h>
+ #include <linux/ata_platform.h>
++#include <linux/mbus.h>
+ #include <scsi/scsi_host.h>
+ #include <scsi/scsi_cmnd.h>
+ #include <scsi/scsi_device.h>
+@@ -121,17 +112,17 @@ enum {
+ MV_MAX_SG_CT = 256,
+ MV_SG_TBL_SZ = (16 * MV_MAX_SG_CT),
+
+- MV_PORTS_PER_HC = 4,
+- /* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */
++ /* Determine hc from 0-7 port: hc = port >> MV_PORT_HC_SHIFT */
+ MV_PORT_HC_SHIFT = 2,
+- /* == (port % MV_PORTS_PER_HC) to determine hard port from 0-7 port */
+- MV_PORT_MASK = 3,
++ MV_PORTS_PER_HC = (1 << MV_PORT_HC_SHIFT), /* 4 */
++ /* Determine hc port from 0-7 port: hardport = port & MV_PORT_MASK */
++ MV_PORT_MASK = (MV_PORTS_PER_HC - 1), /* 3 */
+
+ /* Host Flags */
+ MV_FLAG_DUAL_HC = (1 << 30), /* two SATA Host Controllers */
+ MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */
+ /* SoC integrated controllers, no PCI interface */
+- MV_FLAG_SOC = (1 << 28),
++ MV_FLAG_SOC = (1 << 28),
+
+ MV_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
+@@ -141,6 +132,7 @@ enum {
+ CRQB_FLAG_READ = (1 << 0),
+ CRQB_TAG_SHIFT = 1,
+ CRQB_IOID_SHIFT = 6, /* CRQB Gen-II/IIE IO Id shift */
++ CRQB_PMP_SHIFT = 12, /* CRQB Gen-II/IIE PMP shift */
+ CRQB_HOSTQ_SHIFT = 17, /* CRQB Gen-II/IIE HostQueTag shift */
+ CRQB_CMD_ADDR_SHIFT = 8,
+ CRQB_CMD_CS = (0x2 << 11),
+@@ -184,8 +176,8 @@ enum {
+ HC_MAIN_IRQ_MASK_OFS = 0x1d64,
+ HC_SOC_MAIN_IRQ_CAUSE_OFS = 0x20020,
+ HC_SOC_MAIN_IRQ_MASK_OFS = 0x20024,
+- PORT0_ERR = (1 << 0), /* shift by port # */
+- PORT0_DONE = (1 << 1), /* shift by port # */
++ ERR_IRQ = (1 << 0), /* shift by port # */
++ DONE_IRQ = (1 << 1), /* shift by port # */
+ HC0_IRQ_PEND = 0x1ff, /* bits 0-8 = HC0's ports */
+ HC_SHIFT = 9, /* bits 9-17 = HC1's ports */
+ PCI_ERR = (1 << 18),
+@@ -199,8 +191,9 @@ enum {
+ TWSI_INT = (1 << 24),
+ HC_MAIN_RSVD = (0x7f << 25), /* bits 31-25 */
+ HC_MAIN_RSVD_5 = (0x1fff << 19), /* bits 31-19 */
+- HC_MAIN_RSVD_SOC = (0x3fffffb << 6), /* bits 31-9, 7-6 */
++ HC_MAIN_RSVD_SOC = (0x3fffffb << 6), /* bits 31-9, 7-6 */
+ HC_MAIN_MASKED_IRQS = (TRAN_LO_DONE | TRAN_HI_DONE |
++ PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE |
+ PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT |
+ HC_MAIN_RSVD),
+ HC_MAIN_MASKED_IRQS_5 = (PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE |
+@@ -211,8 +204,8 @@ enum {
+ HC_CFG_OFS = 0,
+
+ HC_IRQ_CAUSE_OFS = 0x14,
+- CRPB_DMA_DONE = (1 << 0), /* shift by port # */
+- HC_IRQ_COAL = (1 << 4), /* IRQ coalescing */
++ DMA_IRQ = (1 << 0), /* shift by port # */
++ HC_COAL_IRQ = (1 << 4), /* IRQ coalescing */
+ DEV_IRQ = (1 << 8), /* shift by port # */
+
+ /* Shadow block registers */
+@@ -223,13 +216,24 @@ enum {
+ SATA_STATUS_OFS = 0x300, /* ctrl, err regs follow status */
+ SATA_ACTIVE_OFS = 0x350,
+ SATA_FIS_IRQ_CAUSE_OFS = 0x364,
++
++ LTMODE_OFS = 0x30c,
++ LTMODE_BIT8 = (1 << 8), /* unknown, but necessary */
++
+ PHY_MODE3 = 0x310,
+ PHY_MODE4 = 0x314,
+ PHY_MODE2 = 0x330,
++ SATA_IFCTL_OFS = 0x344,
++ SATA_IFSTAT_OFS = 0x34c,
++ VENDOR_UNIQUE_FIS_OFS = 0x35c,
++
++ FIS_CFG_OFS = 0x360,
++ FIS_CFG_SINGLE_SYNC = (1 << 16), /* SYNC on DMA activation */
++
+ MV5_PHY_MODE = 0x74,
+ MV5_LT_MODE = 0x30,
+ MV5_PHY_CTL = 0x0C,
+- SATA_INTERFACE_CTL = 0x050,
++ SATA_INTERFACE_CFG = 0x050,
+
+ MV_M2_PREAMP_MASK = 0x7e0,
+
+@@ -240,6 +244,8 @@ enum {
+ EDMA_CFG_NCQ_GO_ON_ERR = (1 << 14), /* continue on error */
+ EDMA_CFG_RD_BRST_EXT = (1 << 11), /* read burst 512B */
+ EDMA_CFG_WR_BUFF_LEN = (1 << 13), /* write buffer 512B */
++ EDMA_CFG_EDMA_FBS = (1 << 16), /* EDMA FIS-Based Switching */
++ EDMA_CFG_FBS = (1 << 26), /* FIS-Based Switching */
+
+ EDMA_ERR_IRQ_CAUSE_OFS = 0x8,
+ EDMA_ERR_IRQ_MASK_OFS = 0xc,
+@@ -298,6 +304,7 @@ enum {
+ EDMA_ERR_LNK_DATA_RX |
+ EDMA_ERR_LNK_DATA_TX |
+ EDMA_ERR_TRANS_PROTO,
++
+ EDMA_EH_FREEZE_5 = EDMA_ERR_D_PAR |
+ EDMA_ERR_PRD_PAR |
+ EDMA_ERR_DEV_DCON |
+@@ -329,6 +336,8 @@ enum {
+ EDMA_IORDY_TMOUT = 0x34,
+ EDMA_ARB_CFG = 0x38,
+
++ GEN_II_NCQ_MAX_SECTORS = 256, /* max sects/io on Gen2 w/NCQ */
++
+ /* Host private flags (hp_flags) */
+ MV_HP_FLAG_MSI = (1 << 0),
+ MV_HP_ERRATA_50XXB0 = (1 << 1),
+@@ -344,7 +353,6 @@ enum {
+ /* Port private flags (pp_flags) */
+ MV_PP_FLAG_EDMA_EN = (1 << 0), /* is EDMA engine enabled? */
+ MV_PP_FLAG_NCQ_EN = (1 << 1), /* is EDMA set up for NCQ? */
+- MV_PP_FLAG_HAD_A_RESET = (1 << 2), /* 1st hard reset complete? */
+ };
+
+ #define IS_GEN_I(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_I)
+@@ -352,6 +360,9 @@ enum {
+ #define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
+ #define HAS_PCI(host) (!((host)->ports[0]->flags & MV_FLAG_SOC))
+
++#define WINDOW_CTRL(i) (0x20030 + ((i) << 4))
++#define WINDOW_BASE(i) (0x20034 + ((i) << 4))
++
+ enum {
+ /* DMA boundary 0xffff is required by the s/g splitting
+ * we need on /length/ in mv_fill-sg().
+@@ -461,7 +472,6 @@ struct mv_hw_ops {
+ void (*reset_bus)(struct ata_host *host, void __iomem *mmio);
+ };
+
+-static void mv_irq_clear(struct ata_port *ap);
+ static int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val);
+ static int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
+ static int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val);
+@@ -471,7 +481,8 @@ static void mv_port_stop(struct ata_port *ap);
+ static void mv_qc_prep(struct ata_queued_cmd *qc);
+ static void mv_qc_prep_iie(struct ata_queued_cmd *qc);
+ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
+-static void mv_error_handler(struct ata_port *ap);
++static int mv_hardreset(struct ata_link *link, unsigned int *class,
++ unsigned long deadline);
+ static void mv_eh_freeze(struct ata_port *ap);
+ static void mv_eh_thaw(struct ata_port *ap);
+ static void mv6_dev_config(struct ata_device *dev);
+@@ -504,72 +515,46 @@ static void mv_soc_reset_flash(struct mv_host_priv *hpriv,
+ void __iomem *mmio);
+ static void mv_soc_reset_bus(struct ata_host *host, void __iomem *mmio);
+ static void mv_reset_pci_bus(struct ata_host *host, void __iomem *mmio);
+-static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
++static void mv_reset_channel(struct mv_host_priv *hpriv, void __iomem *mmio,
+ unsigned int port_no);
+-static void mv_edma_cfg(struct mv_port_priv *pp, struct mv_host_priv *hpriv,
+- void __iomem *port_mmio, int want_ncq);
+-static int __mv_stop_dma(struct ata_port *ap);
++static int mv_stop_edma(struct ata_port *ap);
++static int mv_stop_edma_engine(void __iomem *port_mmio);
++static void mv_edma_cfg(struct ata_port *ap, int want_ncq);
++
++static void mv_pmp_select(struct ata_port *ap, int pmp);
++static int mv_pmp_hardreset(struct ata_link *link, unsigned int *class,
++ unsigned long deadline);
++static int mv_softreset(struct ata_link *link, unsigned int *class,
++ unsigned long deadline);
+
+ /* .sg_tablesize is (MV_MAX_SG_CT / 2) in the structures below
+ * because we have to allow room for worst case splitting of
+ * PRDs for 64K boundaries in mv_fill_sg().
+ */
+ static struct scsi_host_template mv5_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
++ ATA_BASE_SHT(DRV_NAME),
+ .sg_tablesize = MV_MAX_SG_CT / 2,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = 1,
+- .proc_name = DRV_NAME,
+ .dma_boundary = MV_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
+ };
+
+ static struct scsi_host_template mv6_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .change_queue_depth = ata_scsi_change_queue_depth,
++ ATA_NCQ_SHT(DRV_NAME),
+ .can_queue = MV_MAX_Q_DEPTH - 1,
+- .this_id = ATA_SHT_THIS_ID,
+ .sg_tablesize = MV_MAX_SG_CT / 2,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = 1,
+- .proc_name = DRV_NAME,
+ .dma_boundary = MV_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
+ };
+
+-static const struct ata_port_operations mv5_ops = {
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .cable_detect = ata_cable_sata,
++static struct ata_port_operations mv5_ops = {
++ .inherits = &ata_sff_port_ops,
+
+ .qc_prep = mv_qc_prep,
+ .qc_issue = mv_qc_issue,
+- .data_xfer = ata_data_xfer,
+
+- .irq_clear = mv_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .error_handler = mv_error_handler,
+ .freeze = mv_eh_freeze,
+ .thaw = mv_eh_thaw,
++ .hardreset = mv_hardreset,
++ .error_handler = ata_std_error_handler, /* avoid SFF EH */
++ .post_internal_cmd = ATA_OP_NULL,
+
+ .scr_read = mv5_scr_read,
+ .scr_write = mv5_scr_write,
+@@ -578,61 +563,24 @@ static const struct ata_port_operations mv5_ops = {
+ .port_stop = mv_port_stop,
+ };
+
+-static const struct ata_port_operations mv6_ops = {
++static struct ata_port_operations mv6_ops = {
++ .inherits = &mv5_ops,
++ .qc_defer = sata_pmp_qc_defer_cmd_switch,
+ .dev_config = mv6_dev_config,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .cable_detect = ata_cable_sata,
+-
+- .qc_prep = mv_qc_prep,
+- .qc_issue = mv_qc_issue,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_clear = mv_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .error_handler = mv_error_handler,
+- .freeze = mv_eh_freeze,
+- .thaw = mv_eh_thaw,
+- .qc_defer = ata_std_qc_defer,
+-
+ .scr_read = mv_scr_read,
+ .scr_write = mv_scr_write,
+
+- .port_start = mv_port_start,
+- .port_stop = mv_port_stop,
++ .pmp_hardreset = mv_pmp_hardreset,
++ .pmp_softreset = mv_softreset,
++ .softreset = mv_softreset,
++ .error_handler = sata_pmp_error_handler,
+ };
+
+-static const struct ata_port_operations mv_iie_ops = {
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .cable_detect = ata_cable_sata,
+-
++static struct ata_port_operations mv_iie_ops = {
++ .inherits = &mv6_ops,
++ .qc_defer = ata_std_qc_defer, /* FIS-based switching */
++ .dev_config = ATA_OP_NULL,
+ .qc_prep = mv_qc_prep_iie,
+- .qc_issue = mv_qc_issue,
+- .data_xfer = ata_data_xfer,
+-
+- .irq_clear = mv_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .error_handler = mv_error_handler,
+- .freeze = mv_eh_freeze,
+- .thaw = mv_eh_thaw,
+- .qc_defer = ata_std_qc_defer,
+-
+- .scr_read = mv_scr_read,
+- .scr_write = mv_scr_write,
+-
+- .port_start = mv_port_start,
+- .port_stop = mv_port_stop,
+ };
+
+ static const struct ata_port_info mv_port_info[] = {
+@@ -656,6 +604,7 @@ static const struct ata_port_info mv_port_info[] = {
+ },
+ { /* chip_604x */
+ .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS |
++ ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA |
+ ATA_FLAG_NCQ,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = ATA_UDMA6,
+@@ -663,6 +612,7 @@ static const struct ata_port_info mv_port_info[] = {
+ },
+ { /* chip_608x */
+ .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS |
++ ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA |
+ ATA_FLAG_NCQ | MV_FLAG_DUAL_HC,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = ATA_UDMA6,
+@@ -670,6 +620,7 @@ static const struct ata_port_info mv_port_info[] = {
+ },
+ { /* chip_6042 */
+ .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS |
++ ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA |
+ ATA_FLAG_NCQ,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = ATA_UDMA6,
+@@ -677,16 +628,19 @@ static const struct ata_port_info mv_port_info[] = {
+ },
+ { /* chip_7042 */
+ .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS |
++ ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA |
+ ATA_FLAG_NCQ,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &mv_iie_ops,
+ },
+ { /* chip_soc */
+- .flags = MV_COMMON_FLAGS | MV_FLAG_SOC,
+- .pio_mask = 0x1f, /* pio0-4 */
+- .udma_mask = ATA_UDMA6,
+- .port_ops = &mv_iie_ops,
++ .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS |
++ ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA |
++ ATA_FLAG_NCQ | MV_FLAG_SOC,
++ .pio_mask = 0x1f, /* pio0-4 */
++ .udma_mask = ATA_UDMA6,
++ .port_ops = &mv_iie_ops,
+ },
+ };
+
+@@ -757,11 +711,6 @@ static inline void writelfl(unsigned long data, void __iomem *addr)
+ (void) readl(addr); /* flush to avoid PCI posted write */
+ }
+
+-static inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc)
+-{
+- return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ));
+-}
+-
+ static inline unsigned int mv_hc_from_port(unsigned int port)
+ {
+ return port >> MV_PORT_HC_SHIFT;
+@@ -772,6 +721,29 @@ static inline unsigned int mv_hardport_from_port(unsigned int port)
+ return port & MV_PORT_MASK;
+ }
+
++/*
++ * Consolidate some rather tricky bit shift calculations.
++ * This is hot-path stuff, so not a function.
++ * Simple code, with two return values, so macro rather than inline.
++ *
++ * port is the sole input, in range 0..7.
++ * shift is one output, for use with the main_cause and main_mask registers.
++ * hardport is the other output, in range 0..3
++ *
++ * Note that port and hardport may be the same variable in some cases.
++ */
++#define MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport) \
++{ \
++ shift = mv_hc_from_port(port) * HC_SHIFT; \
++ hardport = mv_hardport_from_port(port); \
++ shift += hardport * 2; \
++}
++
++static inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc)
++{
++ return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ));
++}
++
+ static inline void __iomem *mv_hc_base_from_port(void __iomem *base,
+ unsigned int port)
+ {
+@@ -785,6 +757,14 @@ static inline void __iomem *mv_port_base(void __iomem *base, unsigned int port)
+ (mv_hardport_from_port(port) * MV_PORT_REG_SZ);
+ }
+
++static void __iomem *mv5_phy_base(void __iomem *mmio, unsigned int port)
++{
++ void __iomem *hc_mmio = mv_hc_base_from_port(mmio, port);
++ unsigned long ofs = (mv_hardport_from_port(port) + 1) * 0x100UL;
++
++ return hc_mmio + ofs;
++}
++
+ static inline void __iomem *mv_host_base(struct ata_host *host)
+ {
+ struct mv_host_priv *hpriv = host->private_data;
+@@ -801,10 +781,6 @@ static inline int mv_get_hc_count(unsigned long port_flags)
+ return ((port_flags & MV_FLAG_DUAL_HC) ? 2 : 1);
+ }
+
+-static void mv_irq_clear(struct ata_port *ap)
+-{
+-}
+-
+ static void mv_set_edma_ptrs(void __iomem *port_mmio,
+ struct mv_host_priv *hpriv,
+ struct mv_port_priv *pp)
+@@ -814,7 +790,8 @@ static void mv_set_edma_ptrs(void __iomem *port_mmio,
+ /*
+ * initialize request queue
+ */
+- index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT;
++ pp->req_idx &= MV_MAX_Q_DEPTH_MASK; /* paranoia */
++ index = pp->req_idx << EDMA_REQ_Q_PTR_SHIFT;
+
+ WARN_ON(pp->crqb_dma & 0x3ff);
+ writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
+@@ -830,7 +807,8 @@ static void mv_set_edma_ptrs(void __iomem *port_mmio,
+ /*
+ * initialize response queue
+ */
+- index = (pp->resp_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_RSP_Q_PTR_SHIFT;
++ pp->resp_idx &= MV_MAX_Q_DEPTH_MASK; /* paranoia */
++ index = pp->resp_idx << EDMA_RSP_Q_PTR_SHIFT;
+
+ WARN_ON(pp->crpb_dma & 0xff);
+ writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
+@@ -864,13 +842,13 @@ static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio,
+ if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
+ int using_ncq = ((pp->pp_flags & MV_PP_FLAG_NCQ_EN) != 0);
+ if (want_ncq != using_ncq)
+- __mv_stop_dma(ap);
++ mv_stop_edma(ap);
+ }
+ if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) {
+ struct mv_host_priv *hpriv = ap->host->private_data;
+- int hard_port = mv_hardport_from_port(ap->port_no);
++ int hardport = mv_hardport_from_port(ap->port_no);
+ void __iomem *hc_mmio = mv_hc_base_from_port(
+- mv_host_base(ap->host), hard_port);
++ mv_host_base(ap->host), hardport);
+ u32 hc_irq_cause, ipending;
+
+ /* clear EDMA event indicators, if any */
+@@ -878,14 +856,13 @@ static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio,
+
+ /* clear EDMA interrupt indicator, if any */
+ hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
+- ipending = (DEV_IRQ << hard_port) |
+- (CRPB_DMA_DONE << hard_port);
++ ipending = (DEV_IRQ | DMA_IRQ) << hardport;
+ if (hc_irq_cause & ipending) {
+ writelfl(hc_irq_cause & ~ipending,
+ hc_mmio + HC_IRQ_CAUSE_OFS);
+ }
+
+- mv_edma_cfg(pp, hpriv, port_mmio, want_ncq);
++ mv_edma_cfg(ap, want_ncq);
+
+ /* clear FIS IRQ Cause */
+ writelfl(0, port_mmio + SATA_FIS_IRQ_CAUSE_OFS);
+@@ -895,62 +872,45 @@ static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio,
+ writelfl(EDMA_EN, port_mmio + EDMA_CMD_OFS);
+ pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
+ }
+- WARN_ON(!(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS)));
+ }
+
+ /**
+- * __mv_stop_dma - Disable eDMA engine
+- * @ap: ATA channel to manipulate
+- *
+- * Verify the local cache of the eDMA state is accurate with a
+- * WARN_ON.
++ * mv_stop_edma_engine - Disable eDMA engine
++ * @port_mmio: io base address
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+-static int __mv_stop_dma(struct ata_port *ap)
++static int mv_stop_edma_engine(void __iomem *port_mmio)
+ {
+- void __iomem *port_mmio = mv_ap_base(ap);
+- struct mv_port_priv *pp = ap->private_data;
+- u32 reg;
+- int i, err = 0;
++ int i;
+
+- if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
+- /* Disable EDMA if active. The disable bit auto clears.
+- */
+- writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
+- pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+- } else {
+- WARN_ON(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
+- }
++ /* Disable eDMA. The disable bit auto clears. */
++ writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
+
+- /* now properly wait for the eDMA to stop */
+- for (i = 1000; i > 0; i--) {
+- reg = readl(port_mmio + EDMA_CMD_OFS);
++ /* Wait for the chip to confirm eDMA is off. */
++ for (i = 10000; i > 0; i--) {
++ u32 reg = readl(port_mmio + EDMA_CMD_OFS);
+ if (!(reg & EDMA_EN))
+- break;
+-
+- udelay(100);
+- }
+-
+- if (reg & EDMA_EN) {
+- ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
+- err = -EIO;
++ return 0;
++ udelay(10);
+ }
+-
+- return err;
++ return -EIO;
+ }
+
+-static int mv_stop_dma(struct ata_port *ap)
++static int mv_stop_edma(struct ata_port *ap)
+ {
+- unsigned long flags;
+- int rc;
+-
+- spin_lock_irqsave(&ap->host->lock, flags);
+- rc = __mv_stop_dma(ap);
+- spin_unlock_irqrestore(&ap->host->lock, flags);
++ void __iomem *port_mmio = mv_ap_base(ap);
++ struct mv_port_priv *pp = ap->private_data;
+
+- return rc;
++ if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN))
++ return 0;
++ pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
++ if (mv_stop_edma_engine(port_mmio)) {
++ ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
++ return -EIO;
++ }
++ return 0;
+ }
+
+ #ifdef ATA_DEBUG
+@@ -1074,18 +1034,56 @@ static int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
+ static void mv6_dev_config(struct ata_device *adev)
+ {
+ /*
++ * Deal with Gen-II ("mv6") hardware quirks/restrictions:
++ *
++ * Gen-II does not support NCQ over a port multiplier
++ * (no FIS-based switching).
++ *
+ * We don't have hob_nsect when doing NCQ commands on Gen-II.
+ * See mv_qc_prep() for more info.
+ */
+- if (adev->flags & ATA_DFLAG_NCQ)
+- if (adev->max_sectors > ATA_MAX_SECTORS)
+- adev->max_sectors = ATA_MAX_SECTORS;
++ if (adev->flags & ATA_DFLAG_NCQ) {
++ if (sata_pmp_attached(adev->link->ap)) {
++ adev->flags &= ~ATA_DFLAG_NCQ;
++ ata_dev_printk(adev, KERN_INFO,
++ "NCQ disabled for command-based switching\n");
++ } else if (adev->max_sectors > GEN_II_NCQ_MAX_SECTORS) {
++ adev->max_sectors = GEN_II_NCQ_MAX_SECTORS;
++ ata_dev_printk(adev, KERN_INFO,
++ "max_sectors limited to %u for NCQ\n",
++ adev->max_sectors);
++ }
++ }
++}
++
++static void mv_config_fbs(void __iomem *port_mmio, int enable_fbs)
++{
++ u32 old_fcfg, new_fcfg, old_ltmode, new_ltmode;
++ /*
++ * Various bit settings required for operation
++ * in FIS-based switching (fbs) mode on GenIIe:
++ */
++ old_fcfg = readl(port_mmio + FIS_CFG_OFS);
++ old_ltmode = readl(port_mmio + LTMODE_OFS);
++ if (enable_fbs) {
++ new_fcfg = old_fcfg | FIS_CFG_SINGLE_SYNC;
++ new_ltmode = old_ltmode | LTMODE_BIT8;
++ } else { /* disable fbs */
++ new_fcfg = old_fcfg & ~FIS_CFG_SINGLE_SYNC;
++ new_ltmode = old_ltmode & ~LTMODE_BIT8;
++ }
++ if (new_fcfg != old_fcfg)
++ writelfl(new_fcfg, port_mmio + FIS_CFG_OFS);
++ if (new_ltmode != old_ltmode)
++ writelfl(new_ltmode, port_mmio + LTMODE_OFS);
+ }
+
+-static void mv_edma_cfg(struct mv_port_priv *pp, struct mv_host_priv *hpriv,
+- void __iomem *port_mmio, int want_ncq)
++static void mv_edma_cfg(struct ata_port *ap, int want_ncq)
+ {
+ u32 cfg;
++ struct mv_port_priv *pp = ap->private_data;
++ struct mv_host_priv *hpriv = ap->host->private_data;
++ void __iomem *port_mmio = mv_ap_base(ap);
+
+ /* set up non-NCQ EDMA configuration */
+ cfg = EDMA_CFG_Q_DEPTH; /* always 0x1f for *all* chips */
+@@ -1101,6 +1099,13 @@ static void mv_edma_cfg(struct mv_port_priv *pp, struct mv_host_priv *hpriv,
+ cfg |= (1 << 22); /* enab 4-entry host queue cache */
+ cfg |= (1 << 18); /* enab early completion */
+ cfg |= (1 << 17); /* enab cut-through (dis stor&forwrd) */
++
++ if (want_ncq && sata_pmp_attached(ap)) {
++ cfg |= EDMA_CFG_EDMA_FBS; /* FIS-based switching */
++ mv_config_fbs(port_mmio, 1);
++ } else {
++ mv_config_fbs(port_mmio, 0);
++ }
+ }
+
+ if (want_ncq) {
+@@ -1156,8 +1161,6 @@ static int mv_port_start(struct ata_port *ap)
+ struct device *dev = ap->host->dev;
+ struct mv_host_priv *hpriv = ap->host->private_data;
+ struct mv_port_priv *pp;
+- void __iomem *port_mmio = mv_ap_base(ap);
+- unsigned long flags;
+ int tag;
+
+ pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
+@@ -1190,18 +1193,6 @@ static int mv_port_start(struct ata_port *ap)
+ pp->sg_tbl_dma[tag] = pp->sg_tbl_dma[0];
+ }
+ }
+-
+- spin_lock_irqsave(&ap->host->lock, flags);
+-
+- mv_edma_cfg(pp, hpriv, port_mmio, 0);
+- mv_set_edma_ptrs(port_mmio, hpriv, pp);
+-
+- spin_unlock_irqrestore(&ap->host->lock, flags);
+-
+- /* Don't turn on EDMA here...do it before DMA commands only. Else
+- * we'll be unable to send non-data, PIO, etc due to restricted access
+- * to shadow regs.
+- */
+ return 0;
+
+ out_port_free_dma_mem:
+@@ -1220,7 +1211,7 @@ out_port_free_dma_mem:
+ */
+ static void mv_port_stop(struct ata_port *ap)
+ {
+- mv_stop_dma(ap);
++ mv_stop_edma(ap);
+ mv_port_free_dma_mem(ap);
+ }
+
+@@ -1306,9 +1297,10 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
+ flags |= CRQB_FLAG_READ;
+ WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
+ flags |= qc->tag << CRQB_TAG_SHIFT;
++ flags |= (qc->dev->link->pmp & 0xf) << CRQB_PMP_SHIFT;
+
+ /* get current queue index from software */
+- in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
++ in_index = pp->req_idx;
+
+ pp->crqb[in_index].sg_addr =
+ cpu_to_le32(pp->sg_tbl_dma[qc->tag] & 0xffffffff);
+@@ -1390,17 +1382,17 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
+ (qc->tf.protocol != ATA_PROT_NCQ))
+ return;
+
+- /* Fill in Gen IIE command request block
+- */
++ /* Fill in Gen IIE command request block */
+ if (!(qc->tf.flags & ATA_TFLAG_WRITE))
+ flags |= CRQB_FLAG_READ;
+
+ WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
+ flags |= qc->tag << CRQB_TAG_SHIFT;
+ flags |= qc->tag << CRQB_HOSTQ_SHIFT;
++ flags |= (qc->dev->link->pmp & 0xf) << CRQB_PMP_SHIFT;
+
+ /* get current queue index from software */
+- in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
++ in_index = pp->req_idx;
+
+ crqb = (struct mv_crqb_iie *) &pp->crqb[in_index];
+ crqb->addr = cpu_to_le32(pp->sg_tbl_dma[qc->tag] & 0xffffffff);
+@@ -1455,19 +1447,20 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
+
+ if ((qc->tf.protocol != ATA_PROT_DMA) &&
+ (qc->tf.protocol != ATA_PROT_NCQ)) {
+- /* We're about to send a non-EDMA capable command to the
++ /*
++ * We're about to send a non-EDMA capable command to the
+ * port. Turn off EDMA so there won't be problems accessing
+ * shadow block, etc registers.
+ */
+- __mv_stop_dma(ap);
+- return ata_qc_issue_prot(qc);
++ mv_stop_edma(ap);
++ mv_pmp_select(ap, qc->dev->link->pmp);
++ return ata_sff_qc_issue(qc);
+ }
+
+ mv_start_dma(ap, port_mmio, pp, qc->tf.protocol);
+
+- pp->req_idx++;
+-
+- in_index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT;
++ pp->req_idx = (pp->req_idx + 1) & MV_MAX_Q_DEPTH_MASK;
++ in_index = pp->req_idx << EDMA_REQ_Q_PTR_SHIFT;
+
+ /* and write the request in pointer to kick the EDMA to life */
+ writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | in_index,
+@@ -1476,16 +1469,51 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
+ return 0;
+ }
+
++static struct ata_queued_cmd *mv_get_active_qc(struct ata_port *ap)
++{
++ struct mv_port_priv *pp = ap->private_data;
++ struct ata_queued_cmd *qc;
++
++ if (pp->pp_flags & MV_PP_FLAG_NCQ_EN)
++ return NULL;
++ qc = ata_qc_from_tag(ap, ap->link.active_tag);
++ if (qc && (qc->tf.flags & ATA_TFLAG_POLLING))
++ qc = NULL;
++ return qc;
++}
++
++static void mv_unexpected_intr(struct ata_port *ap)
++{
++ struct mv_port_priv *pp = ap->private_data;
++ struct ata_eh_info *ehi = &ap->link.eh_info;
++ char *when = "";
++
++ /*
++ * We got a device interrupt from something that
++ * was supposed to be using EDMA or polling.
++ */
++ ata_ehi_clear_desc(ehi);
++ if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
++ when = " while EDMA enabled";
++ } else {
++ struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->link.active_tag);
++ if (qc && (qc->tf.flags & ATA_TFLAG_POLLING))
++ when = " while polling";
++ }
++ ata_ehi_push_desc(ehi, "unexpected device interrupt%s", when);
++ ehi->err_mask |= AC_ERR_OTHER;
++ ehi->action |= ATA_EH_RESET;
++ ata_port_freeze(ap);
++}
++
+ /**
+ * mv_err_intr - Handle error interrupts on the port
+ * @ap: ATA channel to manipulate
+- * @reset_allowed: bool: 0 == don't trigger from reset here
++ * @qc: affected command (non-NCQ), or NULL
+ *
+- * In most cases, just clear the interrupt and move on. However,
+- * some cases require an eDMA reset, which is done right before
+- * the COMRESET in mv_phy_reset(). The SERR case requires a
+- * clear of pending errors in the SATA SERROR register. Finally,
+- * if the port disabled DMA, update our cached copy to match.
++ * Most cases require a full reset of the chip's state machine,
++ * which also performs a COMRESET.
++ * Also, if the port disabled DMA, update our cached copy to match.
+ *
+ * LOCKING:
+ * Inherited from caller.
+@@ -1496,75 +1524,73 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
+ u32 edma_err_cause, eh_freeze_mask, serr = 0;
+ struct mv_port_priv *pp = ap->private_data;
+ struct mv_host_priv *hpriv = ap->host->private_data;
+- unsigned int edma_enabled = (pp->pp_flags & MV_PP_FLAG_EDMA_EN);
+ unsigned int action = 0, err_mask = 0;
+ struct ata_eh_info *ehi = &ap->link.eh_info;
+
+ ata_ehi_clear_desc(ehi);
+
+- if (!edma_enabled) {
+- /* just a guess: do we need to do this? should we
+- * expand this, and do it in all cases?
+- */
+- sata_scr_read(&ap->link, SCR_ERROR, &serr);
+- sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
+- }
+-
++ /*
++ * Read and clear the err_cause bits. This won't actually
++ * clear for some errors (eg. SError), but we will be doing
++ * a hard reset in those cases regardless, which *will* clear it.
++ */
+ edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
++ writelfl(~edma_err_cause, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+
+- ata_ehi_push_desc(ehi, "edma_err 0x%08x", edma_err_cause);
++ ata_ehi_push_desc(ehi, "edma_err_cause=%08x", edma_err_cause);
+
+ /*
+- * all generations share these EDMA error cause bits
++ * All generations share these EDMA error cause bits:
+ */
+-
+ if (edma_err_cause & EDMA_ERR_DEV)
+ err_mask |= AC_ERR_DEV;
+ if (edma_err_cause & (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR |
+ EDMA_ERR_CRQB_PAR | EDMA_ERR_CRPB_PAR |
+ EDMA_ERR_INTRL_PAR)) {
+ err_mask |= AC_ERR_ATA_BUS;
+- action |= ATA_EH_HARDRESET;
++ action |= ATA_EH_RESET;
+ ata_ehi_push_desc(ehi, "parity error");
+ }
+ if (edma_err_cause & (EDMA_ERR_DEV_DCON | EDMA_ERR_DEV_CON)) {
+ ata_ehi_hotplugged(ehi);
+ ata_ehi_push_desc(ehi, edma_err_cause & EDMA_ERR_DEV_DCON ?
+ "dev disconnect" : "dev connect");
+- action |= ATA_EH_HARDRESET;
++ action |= ATA_EH_RESET;
+ }
+
++ /*
++ * Gen-I has a different SELF_DIS bit,
++ * different FREEZE bits, and no SERR bit:
++ */
+ if (IS_GEN_I(hpriv)) {
+ eh_freeze_mask = EDMA_EH_FREEZE_5;
+-
+ if (edma_err_cause & EDMA_ERR_SELF_DIS_5) {
+- pp = ap->private_data;
+ pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+ ata_ehi_push_desc(ehi, "EDMA self-disable");
+ }
+ } else {
+ eh_freeze_mask = EDMA_EH_FREEZE;
+-
+ if (edma_err_cause & EDMA_ERR_SELF_DIS) {
+- pp = ap->private_data;
+ pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+ ata_ehi_push_desc(ehi, "EDMA self-disable");
+ }
+-
+ if (edma_err_cause & EDMA_ERR_SERR) {
+- sata_scr_read(&ap->link, SCR_ERROR, &serr);
+- sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
+- err_mask = AC_ERR_ATA_BUS;
+- action |= ATA_EH_HARDRESET;
++ /*
++ * Ensure that we read our own SCR, not a pmp link SCR:
++ */
++ ap->ops->scr_read(ap, SCR_ERROR, &serr);
++ /*
++ * Don't clear SError here; leave it for libata-eh:
++ */
++ ata_ehi_push_desc(ehi, "SError=%08x", serr);
++ err_mask |= AC_ERR_ATA_BUS;
++ action |= ATA_EH_RESET;
+ }
+ }
+
+- /* Clear EDMA now that SERR cleanup done */
+- writelfl(~edma_err_cause, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+-
+ if (!err_mask) {
+ err_mask = AC_ERR_OTHER;
+- action |= ATA_EH_HARDRESET;
++ action |= ATA_EH_RESET;
+ }
+
+ ehi->serror |= serr;
+@@ -1581,178 +1607,151 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
+ ata_port_abort(ap);
+ }
+
+-static void mv_intr_pio(struct ata_port *ap)
++static void mv_process_crpb_response(struct ata_port *ap,
++ struct mv_crpb *response, unsigned int tag, int ncq_enabled)
+ {
+- struct ata_queued_cmd *qc;
+- u8 ata_status;
++ struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag);
+
+- /* ignore spurious intr if drive still BUSY */
+- ata_status = readb(ap->ioaddr.status_addr);
+- if (unlikely(ata_status & ATA_BUSY))
+- return;
+-
+- /* get active ATA command */
+- qc = ata_qc_from_tag(ap, ap->link.active_tag);
+- if (unlikely(!qc)) /* no active tag */
+- return;
+- if (qc->tf.flags & ATA_TFLAG_POLLING) /* polling; we don't own qc */
+- return;
+-
+- /* and finally, complete the ATA command */
+- qc->err_mask |= ac_err_mask(ata_status);
+- ata_qc_complete(qc);
++ if (qc) {
++ u8 ata_status;
++ u16 edma_status = le16_to_cpu(response->flags);
++ /*
++ * edma_status from a response queue entry:
++ * LSB is from EDMA_ERR_IRQ_CAUSE_OFS (non-NCQ only).
++ * MSB is saved ATA status from command completion.
++ */
++ if (!ncq_enabled) {
++ u8 err_cause = edma_status & 0xff & ~EDMA_ERR_DEV;
++ if (err_cause) {
++ /*
++ * Error will be seen/handled by mv_err_intr().
++ * So do nothing at all here.
++ */
++ return;
++ }
++ }
++ ata_status = edma_status >> CRPB_FLAG_STATUS_SHIFT;
++ qc->err_mask |= ac_err_mask(ata_status);
++ ata_qc_complete(qc);
++ } else {
++ ata_port_printk(ap, KERN_ERR, "%s: no qc for tag=%d\n",
++ __func__, tag);
++ }
+ }
+
+-static void mv_intr_edma(struct ata_port *ap)
++static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp)
+ {
+ void __iomem *port_mmio = mv_ap_base(ap);
+ struct mv_host_priv *hpriv = ap->host->private_data;
+- struct mv_port_priv *pp = ap->private_data;
+- struct ata_queued_cmd *qc;
+- u32 out_index, in_index;
++ u32 in_index;
+ bool work_done = false;
++ int ncq_enabled = (pp->pp_flags & MV_PP_FLAG_NCQ_EN);
+
+- /* get h/w response queue pointer */
++ /* Get the hardware queue position index */
+ in_index = (readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS)
+ >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
+
+- while (1) {
+- u16 status;
++ /* Process new responses from since the last time we looked */
++ while (in_index != pp->resp_idx) {
+ unsigned int tag;
++ struct mv_crpb *response = &pp->crpb[pp->resp_idx];
+
+- /* get s/w response queue last-read pointer, and compare */
+- out_index = pp->resp_idx & MV_MAX_Q_DEPTH_MASK;
+- if (in_index == out_index)
+- break;
++ pp->resp_idx = (pp->resp_idx + 1) & MV_MAX_Q_DEPTH_MASK;
+
+- /* 50xx: get active ATA command */
+- if (IS_GEN_I(hpriv))
++ if (IS_GEN_I(hpriv)) {
++ /* 50xx: no NCQ, only one command active at a time */
+ tag = ap->link.active_tag;
+-
+- /* Gen II/IIE: get active ATA command via tag, to enable
+- * support for queueing. this works transparently for
+- * queued and non-queued modes.
+- */
+- else
+- tag = le16_to_cpu(pp->crpb[out_index].id) & 0x1f;
+-
+- qc = ata_qc_from_tag(ap, tag);
+-
+- /* For non-NCQ mode, the lower 8 bits of status
+- * are from EDMA_ERR_IRQ_CAUSE_OFS,
+- * which should be zero if all went well.
+- */
+- status = le16_to_cpu(pp->crpb[out_index].flags);
+- if ((status & 0xff) && !(pp->pp_flags & MV_PP_FLAG_NCQ_EN)) {
+- mv_err_intr(ap, qc);
+- return;
+- }
+-
+- /* and finally, complete the ATA command */
+- if (qc) {
+- qc->err_mask |=
+- ac_err_mask(status >> CRPB_FLAG_STATUS_SHIFT);
+- ata_qc_complete(qc);
++ } else {
++ /* Gen II/IIE: get command tag from CRPB entry */
++ tag = le16_to_cpu(response->id) & 0x1f;
+ }
+-
+- /* advance software response queue pointer, to
+- * indicate (after the loop completes) to hardware
+- * that we have consumed a response queue entry.
+- */
++ mv_process_crpb_response(ap, response, tag, ncq_enabled);
+ work_done = true;
+- pp->resp_idx++;
+ }
+
++ /* Update the software queue position index in hardware */
+ if (work_done)
+ writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) |
+- (out_index << EDMA_RSP_Q_PTR_SHIFT),
++ (pp->resp_idx << EDMA_RSP_Q_PTR_SHIFT),
+ port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+ }
+
+ /**
+ * mv_host_intr - Handle all interrupts on the given host controller
+ * @host: host specific structure
+- * @relevant: port error bits relevant to this host controller
+- * @hc: which host controller we're to look at
+- *
+- * Read then write clear the HC interrupt status then walk each
+- * port connected to the HC and see if it needs servicing. Port
+- * success ints are reported in the HC interrupt status reg, the
+- * port error ints are reported in the higher level main
+- * interrupt status register and thus are passed in via the
+- * 'relevant' argument.
++ * @main_cause: Main interrupt cause register for the chip.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+-static void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc)
++static int mv_host_intr(struct ata_host *host, u32 main_cause)
+ {
+ struct mv_host_priv *hpriv = host->private_data;
+- void __iomem *mmio = hpriv->base;
+- void __iomem *hc_mmio = mv_hc_base(mmio, hc);
+- u32 hc_irq_cause;
+- int port, port0, last_port;
+-
+- if (hc == 0)
+- port0 = 0;
+- else
+- port0 = MV_PORTS_PER_HC;
++ void __iomem *mmio = hpriv->base, *hc_mmio = NULL;
++ u32 hc_irq_cause = 0;
++ unsigned int handled = 0, port;
+
+- if (HAS_PCI(host))
+- last_port = port0 + MV_PORTS_PER_HC;
+- else
+- last_port = port0 + hpriv->n_ports;
+- /* we'll need the HC success int register in most cases */
+- hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
+- if (!hc_irq_cause)
+- return;
+-
+- writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
+-
+- VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n",
+- hc, relevant, hc_irq_cause);
+-
+- for (port = port0; port < last_port; port++) {
++ for (port = 0; port < hpriv->n_ports; port++) {
+ struct ata_port *ap = host->ports[port];
+ struct mv_port_priv *pp;
+- int have_err_bits, hard_port, shift;
+-
+- if ((!ap) || (ap->flags & ATA_FLAG_DISABLED))
++ unsigned int shift, hardport, port_cause;
++ /*
++ * When we move to the second hc, flag our cached
++ * copies of hc_mmio (and hc_irq_cause) as invalid again.
++ */
++ if (port == MV_PORTS_PER_HC)
++ hc_mmio = NULL;
++ /*
++ * Do nothing if port is not interrupting or is disabled:
++ */
++ MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport);
++ port_cause = (main_cause >> shift) & (DONE_IRQ | ERR_IRQ);
++ if (!port_cause || !ap || (ap->flags & ATA_FLAG_DISABLED))
+ continue;
+-
+- pp = ap->private_data;
+-
+- shift = port << 1; /* (port * 2) */
+- if (port >= MV_PORTS_PER_HC) {
+- shift++; /* skip bit 8 in the HC Main IRQ reg */
++ /*
++ * Each hc within the host has its own hc_irq_cause register.
++ * We defer reading it until we know we need it, right now:
++ *
++ * FIXME later: we don't really need to read this register
++ * (some logic changes required below if we go that way),
++ * because it doesn't tell us anything new. But we do need
++ * to write to it, outside the top of this loop,
++ * to reset the interrupt triggers for next time.
++ */
++ if (!hc_mmio) {
++ hc_mmio = mv_hc_base_from_port(mmio, port);
++ hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
++ writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
++ handled = 1;
+ }
+- have_err_bits = ((PORT0_ERR << shift) & relevant);
+-
+- if (unlikely(have_err_bits)) {
+- struct ata_queued_cmd *qc;
+-
+- qc = ata_qc_from_tag(ap, ap->link.active_tag);
+- if (qc && (qc->tf.flags & ATA_TFLAG_POLLING))
+- continue;
+-
+- mv_err_intr(ap, qc);
+- continue;
++ /*
++ * Process completed CRPB response(s) before other events.
++ */
++ pp = ap->private_data;
++ if (hc_irq_cause & (DMA_IRQ << hardport)) {
++ if (pp->pp_flags & MV_PP_FLAG_EDMA_EN)
++ mv_process_crpb_entries(ap, pp);
+ }
+-
+- hard_port = mv_hardport_from_port(port); /* range 0..3 */
+-
+- if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
+- if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause)
+- mv_intr_edma(ap);
+- } else {
+- if ((DEV_IRQ << hard_port) & hc_irq_cause)
+- mv_intr_pio(ap);
++ /*
++ * Handle chip-reported errors, or continue on to handle PIO.
++ */
++ if (unlikely(port_cause & ERR_IRQ)) {
++ mv_err_intr(ap, mv_get_active_qc(ap));
++ } else if (hc_irq_cause & (DEV_IRQ << hardport)) {
++ if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) {
++ struct ata_queued_cmd *qc = mv_get_active_qc(ap);
++ if (qc) {
++ ata_sff_host_intr(ap, qc);
++ continue;
++ }
++ }
++ mv_unexpected_intr(ap);
+ }
+ }
+- VPRINTK("EXIT\n");
++ return handled;
+ }
+
+-static void mv_pci_error(struct ata_host *host, void __iomem *mmio)
++static int mv_pci_error(struct ata_host *host, void __iomem *mmio)
+ {
+ struct mv_host_priv *hpriv = host->private_data;
+ struct ata_port *ap;
+@@ -1780,7 +1779,7 @@ static void mv_pci_error(struct ata_host *host, void __iomem *mmio)
+ ata_ehi_push_desc(ehi,
+ "PCI err cause 0x%08x", err_cause);
+ err_mask = AC_ERR_HOST_BUS;
+- ehi->action = ATA_EH_HARDRESET;
++ ehi->action = ATA_EH_RESET;
+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
+ if (qc)
+ qc->err_mask |= err_mask;
+@@ -1790,6 +1789,7 @@ static void mv_pci_error(struct ata_host *host, void __iomem *mmio)
+ ata_port_freeze(ap);
+ }
+ }
++ return 1; /* handled */
+ }
+
+ /**
+@@ -1810,51 +1810,26 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
+ {
+ struct ata_host *host = dev_instance;
+ struct mv_host_priv *hpriv = host->private_data;
+- unsigned int hc, handled = 0, n_hcs;
+- void __iomem *mmio = hpriv->base;
+- u32 irq_stat, irq_mask;
++ unsigned int handled = 0;
++ u32 main_cause, main_mask;
+
+ spin_lock(&host->lock);
+-
+- irq_stat = readl(hpriv->main_cause_reg_addr);
+- irq_mask = readl(hpriv->main_mask_reg_addr);
+-
+- /* check the cases where we either have nothing pending or have read
+- * a bogus register value which can indicate HW removal or PCI fault
++ main_cause = readl(hpriv->main_cause_reg_addr);
++ main_mask = readl(hpriv->main_mask_reg_addr);
++ /*
++ * Deal with cases where we either have nothing pending, or have read
++ * a bogus register value which can indicate HW removal or PCI fault.
+ */
+- if (!(irq_stat & irq_mask) || (0xffffffffU == irq_stat))
+- goto out_unlock;
+-
+- n_hcs = mv_get_hc_count(host->ports[0]->flags);
+-
+- if (unlikely((irq_stat & PCI_ERR) && HAS_PCI(host))) {
+- mv_pci_error(host, mmio);
+- handled = 1;
+- goto out_unlock; /* skip all other HC irq handling */
+- }
+-
+- for (hc = 0; hc < n_hcs; hc++) {
+- u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT));
+- if (relevant) {
+- mv_host_intr(host, relevant, hc);
+- handled = 1;
+- }
++ if ((main_cause & main_mask) && (main_cause != 0xffffffffU)) {
++ if (unlikely((main_cause & PCI_ERR) && HAS_PCI(host)))
++ handled = mv_pci_error(host, hpriv->base);
++ else
++ handled = mv_host_intr(host, main_cause);
+ }
+-
+-out_unlock:
+ spin_unlock(&host->lock);
+-
+ return IRQ_RETVAL(handled);
+ }
+
+-static void __iomem *mv5_phy_base(void __iomem *mmio, unsigned int port)
+-{
+- void __iomem *hc_mmio = mv_hc_base_from_port(mmio, port);
+- unsigned long ofs = (mv_hardport_from_port(port) + 1) * 0x100UL;
+-
+- return hc_mmio + ofs;
+-}
+-
+ static unsigned int mv5_scr_offset(unsigned int sc_reg_in)
+ {
+ unsigned int ofs;
+@@ -1980,9 +1955,12 @@ static void mv5_reset_hc_port(struct mv_host_priv *hpriv, void __iomem *mmio,
+ {
+ void __iomem *port_mmio = mv_port_base(mmio, port);
+
+- writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
+-
+- mv_channel_reset(hpriv, mmio, port);
++ /*
++ * The datasheet warns against setting ATA_RST when EDMA is active
++ * (but doesn't say what the problem might be). So we first try
++ * to disable the EDMA engine before doing the ATA_RST operation.
++ */
++ mv_reset_channel(hpriv, mmio, port);
+
+ ZERO(0x028); /* command */
+ writel(0x11f, port_mmio + EDMA_CFG_OFS);
+@@ -2200,14 +2178,15 @@ static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
+ m4 = readl(port_mmio + PHY_MODE4);
+
+ if (hp_flags & MV_HP_ERRATA_60X1B2)
+- tmp = readl(port_mmio + 0x310);
++ tmp = readl(port_mmio + PHY_MODE3);
+
++ /* workaround for errata FEr SATA#10 (part 1) */
+ m4 = (m4 & ~(1 << 1)) | (1 << 0);
+
+ writel(m4, port_mmio + PHY_MODE4);
+
+ if (hp_flags & MV_HP_ERRATA_60X1B2)
+- writel(tmp, port_mmio + 0x310);
++ writel(tmp, port_mmio + PHY_MODE3);
+ }
+
+ /* Revert values of pre-emphasis and signal amps to the saved ones */
+@@ -2255,9 +2234,12 @@ static void mv_soc_reset_hc_port(struct mv_host_priv *hpriv,
+ {
+ void __iomem *port_mmio = mv_port_base(mmio, port);
+
+- writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
+-
+- mv_channel_reset(hpriv, mmio, port);
++ /*
++ * The datasheet warns against setting ATA_RST when EDMA is active
++ * (but doesn't say what the problem might be). So we first try
++ * to disable the EDMA engine before doing the ATA_RST operation.
++ */
++ mv_reset_channel(hpriv, mmio, port);
+
+ ZERO(0x028); /* command */
+ writel(0x101f, port_mmio + EDMA_CFG_OFS);
+@@ -2314,25 +2296,39 @@ static void mv_soc_reset_bus(struct ata_host *host, void __iomem *mmio)
+ return;
+ }
+
+-static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
++static void mv_setup_ifctl(void __iomem *port_mmio, int want_gen2i)
++{
++ u32 ifctl = readl(port_mmio + SATA_INTERFACE_CFG);
++
++ ifctl = (ifctl & 0xf7f) | 0x9b1000; /* from chip spec */
++ if (want_gen2i)
++ ifctl |= (1 << 7); /* enable gen2i speed */
++ writelfl(ifctl, port_mmio + SATA_INTERFACE_CFG);
++}
++
++/*
++ * Caller must ensure that EDMA is not active,
++ * by first doing mv_stop_edma() where needed.
++ */
++static void mv_reset_channel(struct mv_host_priv *hpriv, void __iomem *mmio,
+ unsigned int port_no)
+ {
+ void __iomem *port_mmio = mv_port_base(mmio, port_no);
+
++ mv_stop_edma_engine(port_mmio);
+ writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
+
+- if (IS_GEN_II(hpriv)) {
+- u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
+- ifctl |= (1 << 7); /* enable gen2i speed */
+- ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
+- writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
++ if (!IS_GEN_I(hpriv)) {
++ /* Enable 3.0gb/s link speed */
++ mv_setup_ifctl(port_mmio, 1);
+ }
+-
+- udelay(25); /* allow reset propagation */
+-
+- /* Spec never mentions clearing the bit. Marvell's driver does
+- * clear the bit, however.
++ /*
++ * Strobing ATA_RST here causes a hard reset of the SATA transport,
++ * link, and physical layers. It resets all SATA interface registers
++ * (except for SATA_INTERFACE_CFG), and issues a COMRESET to the dev.
+ */
++ writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
++ udelay(25); /* allow reset propagation */
+ writelfl(0, port_mmio + EDMA_CMD_OFS);
+
+ hpriv->ops->phy_errata(hpriv, mmio, port_no);
+@@ -2341,136 +2337,32 @@ static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
+ mdelay(1);
+ }
+
+-/**
+- * mv_phy_reset - Perform eDMA reset followed by COMRESET
+- * @ap: ATA channel to manipulate
+- *
+- * Part of this is taken from __sata_phy_reset and modified to
+- * not sleep since this routine gets called from interrupt level.
+- *
+- * LOCKING:
+- * Inherited from caller. This is coded to safe to call at
+- * interrupt level, i.e. it does not sleep.
+- */
+-static void mv_phy_reset(struct ata_port *ap, unsigned int *class,
+- unsigned long deadline)
++static void mv_pmp_select(struct ata_port *ap, int pmp)
+ {
+- struct mv_port_priv *pp = ap->private_data;
+- struct mv_host_priv *hpriv = ap->host->private_data;
+- void __iomem *port_mmio = mv_ap_base(ap);
+- int retry = 5;
+- u32 sstatus;
+-
+- VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio);
+-
+-#ifdef DEBUG
+- {
+- u32 sstatus, serror, scontrol;
+-
+- mv_scr_read(ap, SCR_STATUS, &sstatus);
+- mv_scr_read(ap, SCR_ERROR, &serror);
+- mv_scr_read(ap, SCR_CONTROL, &scontrol);
+- DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x "
+- "SCtrl 0x%08x\n", sstatus, serror, scontrol);
+- }
+-#endif
+-
+- /* Issue COMRESET via SControl */
+-comreset_retry:
+- sata_scr_write_flush(&ap->link, SCR_CONTROL, 0x301);
+- msleep(1);
+-
+- sata_scr_write_flush(&ap->link, SCR_CONTROL, 0x300);
+- msleep(20);
+-
+- do {
+- sata_scr_read(&ap->link, SCR_STATUS, &sstatus);
+- if (((sstatus & 0x3) == 3) || ((sstatus & 0x3) == 0))
+- break;
+-
+- msleep(1);
+- } while (time_before(jiffies, deadline));
+-
+- /* work around errata */
+- if (IS_GEN_II(hpriv) &&
+- (sstatus != 0x0) && (sstatus != 0x113) && (sstatus != 0x123) &&
+- (retry-- > 0))
+- goto comreset_retry;
+-
+-#ifdef DEBUG
+- {
+- u32 sstatus, serror, scontrol;
+-
+- mv_scr_read(ap, SCR_STATUS, &sstatus);
+- mv_scr_read(ap, SCR_ERROR, &serror);
+- mv_scr_read(ap, SCR_CONTROL, &scontrol);
+- DPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x "
+- "SCtrl 0x%08x\n", sstatus, serror, scontrol);
+- }
+-#endif
+-
+- if (ata_link_offline(&ap->link)) {
+- *class = ATA_DEV_NONE;
+- return;
+- }
++ if (sata_pmp_supported(ap)) {
++ void __iomem *port_mmio = mv_ap_base(ap);
++ u32 reg = readl(port_mmio + SATA_IFCTL_OFS);
++ int old = reg & 0xf;
+
+- /* even after SStatus reflects that device is ready,
+- * it seems to take a while for link to be fully
+- * established (and thus Status no longer 0x80/0x7F),
+- * so we poll a bit for that, here.
+- */
+- retry = 20;
+- while (1) {
+- u8 drv_stat = ata_check_status(ap);
+- if ((drv_stat != 0x80) && (drv_stat != 0x7f))
+- break;
+- msleep(500);
+- if (retry-- <= 0)
+- break;
+- if (time_after(jiffies, deadline))
+- break;
++ if (old != pmp) {
++ reg = (reg & ~0xf) | pmp;
++ writelfl(reg, port_mmio + SATA_IFCTL_OFS);
++ }
+ }
+-
+- /* FIXME: if we passed the deadline, the following
+- * code probably produces an invalid result
+- */
+-
+- /* finally, read device signature from TF registers */
+- *class = ata_dev_try_classify(ap->link.device, 1, NULL);
+-
+- writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+-
+- WARN_ON(pp->pp_flags & MV_PP_FLAG_EDMA_EN);
+-
+- VPRINTK("EXIT\n");
+ }
+
+-static int mv_prereset(struct ata_link *link, unsigned long deadline)
++static int mv_pmp_hardreset(struct ata_link *link, unsigned int *class,
++ unsigned long deadline)
+ {
+- struct ata_port *ap = link->ap;
+- struct mv_port_priv *pp = ap->private_data;
+- struct ata_eh_context *ehc = &link->eh_context;
+- int rc;
+-
+- rc = mv_stop_dma(ap);
+- if (rc)
+- ehc->i.action |= ATA_EH_HARDRESET;
+-
+- if (!(pp->pp_flags & MV_PP_FLAG_HAD_A_RESET)) {
+- pp->pp_flags |= MV_PP_FLAG_HAD_A_RESET;
+- ehc->i.action |= ATA_EH_HARDRESET;
+- }
+-
+- /* if we're about to do hardreset, nothing more to do */
+- if (ehc->i.action & ATA_EH_HARDRESET)
+- return 0;
+-
+- if (ata_link_online(link))
+- rc = ata_wait_ready(ap, deadline);
+- else
+- rc = -ENODEV;
++ mv_pmp_select(link->ap, sata_srst_pmp(link));
++ return sata_std_hardreset(link, class, deadline);
++}
+
+- return rc;
++static int mv_softreset(struct ata_link *link, unsigned int *class,
++ unsigned long deadline)
++{
++ mv_pmp_select(link->ap, sata_srst_pmp(link));
++ return ata_sff_softreset(link, class, deadline);
+ }
+
+ static int mv_hardreset(struct ata_link *link, unsigned int *class,
+@@ -2478,97 +2370,77 @@ static int mv_hardreset(struct ata_link *link, unsigned int *class,
+ {
+ struct ata_port *ap = link->ap;
+ struct mv_host_priv *hpriv = ap->host->private_data;
++ struct mv_port_priv *pp = ap->private_data;
+ void __iomem *mmio = hpriv->base;
++ int rc, attempts = 0, extra = 0;
++ u32 sstatus;
++ bool online;
+
+- mv_stop_dma(ap);
+-
+- mv_channel_reset(hpriv, mmio, ap->port_no);
+-
+- mv_phy_reset(ap, class, deadline);
+-
+- return 0;
+-}
+-
+-static void mv_postreset(struct ata_link *link, unsigned int *classes)
+-{
+- struct ata_port *ap = link->ap;
+- u32 serr;
+-
+- /* print link status */
+- sata_print_link_status(link);
+-
+- /* clear SError */
+- sata_scr_read(link, SCR_ERROR, &serr);
+- sata_scr_write_flush(link, SCR_ERROR, serr);
++ mv_reset_channel(hpriv, mmio, ap->port_no);
++ pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+
+- /* bail out if no device is present */
+- if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
+- DPRINTK("EXIT, no device\n");
+- return;
+- }
++ /* Workaround for errata FEr SATA#10 (part 2) */
++ do {
++ const unsigned long *timing =
++ sata_ehc_deb_timing(&link->eh_context);
+
+- /* set up device control */
+- iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
+-}
++ rc = sata_link_hardreset(link, timing, deadline + extra,
++ &online, NULL);
++ if (rc)
++ return rc;
++ sata_scr_read(link, SCR_STATUS, &sstatus);
++ if (!IS_GEN_I(hpriv) && ++attempts >= 5 && sstatus == 0x121) {
++ /* Force 1.5gb/s link speed and try again */
++ mv_setup_ifctl(mv_ap_base(ap), 0);
++ if (time_after(jiffies + HZ, deadline))
++ extra = HZ; /* only extend it once, max */
++ }
++ } while (sstatus != 0x0 && sstatus != 0x113 && sstatus != 0x123);
+
+-static void mv_error_handler(struct ata_port *ap)
+-{
+- ata_do_eh(ap, mv_prereset, ata_std_softreset,
+- mv_hardreset, mv_postreset);
++ return rc;
+ }
+
+ static void mv_eh_freeze(struct ata_port *ap)
+ {
+ struct mv_host_priv *hpriv = ap->host->private_data;
+- unsigned int hc = (ap->port_no > 3) ? 1 : 0;
+- u32 tmp, mask;
+- unsigned int shift;
++ unsigned int shift, hardport, port = ap->port_no;
++ u32 main_mask;
+
+ /* FIXME: handle coalescing completion events properly */
+
+- shift = ap->port_no * 2;
+- if (hc > 0)
+- shift++;
+-
+- mask = 0x3 << shift;
++ mv_stop_edma(ap);
++ MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport);
+
+ /* disable assertion of portN err, done events */
+- tmp = readl(hpriv->main_mask_reg_addr);
+- writelfl(tmp & ~mask, hpriv->main_mask_reg_addr);
++ main_mask = readl(hpriv->main_mask_reg_addr);
++ main_mask &= ~((DONE_IRQ | ERR_IRQ) << shift);
++ writelfl(main_mask, hpriv->main_mask_reg_addr);
+ }
+
+ static void mv_eh_thaw(struct ata_port *ap)
+ {
+ struct mv_host_priv *hpriv = ap->host->private_data;
+- void __iomem *mmio = hpriv->base;
+- unsigned int hc = (ap->port_no > 3) ? 1 : 0;
+- void __iomem *hc_mmio = mv_hc_base(mmio, hc);
++ unsigned int shift, hardport, port = ap->port_no;
++ void __iomem *hc_mmio = mv_hc_base_from_port(hpriv->base, port);
+ void __iomem *port_mmio = mv_ap_base(ap);
+- u32 tmp, mask, hc_irq_cause;
+- unsigned int shift, hc_port_no = ap->port_no;
++ u32 main_mask, hc_irq_cause;
+
+ /* FIXME: handle coalescing completion events properly */
+
+- shift = ap->port_no * 2;
+- if (hc > 0) {
+- shift++;
+- hc_port_no -= 4;
+- }
+-
+- mask = 0x3 << shift;
++ MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport);
+
+ /* clear EDMA errors on this port */
+ writel(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+
+ /* clear pending irq events */
+ hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
+- hc_irq_cause &= ~(1 << hc_port_no); /* clear CRPB-done */
+- hc_irq_cause &= ~(1 << (hc_port_no + 8)); /* clear Device int */
+- writel(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
++ hc_irq_cause &= ~((DEV_IRQ | DMA_IRQ) << hardport);
++ writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
+
+ /* enable assertion of portN err, done events */
+- tmp = readl(hpriv->main_mask_reg_addr);
+- writelfl(tmp | mask, hpriv->main_mask_reg_addr);
++ main_mask = readl(hpriv->main_mask_reg_addr);
++ main_mask |= ((DONE_IRQ | ERR_IRQ) << shift);
++ writelfl(main_mask, hpriv->main_mask_reg_addr);
+ }
+
+ /**
+@@ -2779,19 +2651,17 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
+
+ rc = mv_chip_id(host, board_idx);
+ if (rc)
+- goto done;
++ goto done;
+
+ if (HAS_PCI(host)) {
+- hpriv->main_cause_reg_addr = hpriv->base +
+- HC_MAIN_IRQ_CAUSE_OFS;
+- hpriv->main_mask_reg_addr = hpriv->base + HC_MAIN_IRQ_MASK_OFS;
++ hpriv->main_cause_reg_addr = mmio + HC_MAIN_IRQ_CAUSE_OFS;
++ hpriv->main_mask_reg_addr = mmio + HC_MAIN_IRQ_MASK_OFS;
+ } else {
+- hpriv->main_cause_reg_addr = hpriv->base +
+- HC_SOC_MAIN_IRQ_CAUSE_OFS;
+- hpriv->main_mask_reg_addr = hpriv->base +
+- HC_SOC_MAIN_IRQ_MASK_OFS;
++ hpriv->main_cause_reg_addr = mmio + HC_SOC_MAIN_IRQ_CAUSE_OFS;
++ hpriv->main_mask_reg_addr = mmio + HC_SOC_MAIN_IRQ_MASK_OFS;
+ }
+- /* global interrupt mask */
++
++ /* global interrupt mask: 0 == mask everything */
+ writel(0, hpriv->main_mask_reg_addr);
+
+ n_hc = mv_get_hc_count(host->ports[0]->flags);
+@@ -2808,19 +2678,6 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
+ hpriv->ops->enable_leds(hpriv, mmio);
+
+ for (port = 0; port < host->n_ports; port++) {
+- if (IS_GEN_II(hpriv)) {
+- void __iomem *port_mmio = mv_port_base(mmio, port);
+-
+- u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
+- ifctl |= (1 << 7); /* enable gen2i speed */
+- ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
+- writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
+- }
+-
+- hpriv->ops->phy_errata(hpriv, mmio, port);
+- }
+-
+- for (port = 0; port < host->n_ports; port++) {
+ struct ata_port *ap = host->ports[port];
+ void __iomem *port_mmio = mv_port_base(mmio, port);
+
+@@ -2897,6 +2754,27 @@ static int mv_create_dma_pools(struct mv_host_priv *hpriv, struct device *dev)
+ return 0;
+ }
+
++static void mv_conf_mbus_windows(struct mv_host_priv *hpriv,
++ struct mbus_dram_target_info *dram)
++{
++ int i;
++
++ for (i = 0; i < 4; i++) {
++ writel(0, hpriv->base + WINDOW_CTRL(i));
++ writel(0, hpriv->base + WINDOW_BASE(i));
++ }
++
++ for (i = 0; i < dram->num_cs; i++) {
++ struct mbus_dram_window *cs = dram->cs + i;
++
++ writel(((cs->size - 1) & 0xffff0000) |
++ (cs->mbus_attr << 8) |
++ (dram->mbus_dram_target_id << 4) | 1,
++ hpriv->base + WINDOW_CTRL(i));
++ writel(cs->base, hpriv->base + WINDOW_BASE(i));
++ }
++}
++
+ /**
+ * mv_platform_probe - handle a positive probe of an soc Marvell
+ * host
+@@ -2951,6 +2829,12 @@ static int mv_platform_probe(struct platform_device *pdev)
+ res->end - res->start + 1);
+ hpriv->base -= MV_SATAHC0_REG_BASE;
+
++ /*
++ * (Re-)program MBUS remapping windows if we are asked to.
++ */
++ if (mv_platform_data->dram != NULL)
++ mv_conf_mbus_windows(hpriv, mv_platform_data->dram);
++
+ rc = mv_create_dma_pools(hpriv, &pdev->dev);
+ if (rc)
+ return rc;
+@@ -3192,7 +3076,7 @@ MODULE_DESCRIPTION("SCSI low-level driver for Marvell SATA controllers");
+ MODULE_LICENSE("GPL");
+ MODULE_DEVICE_TABLE(pci, mv_pci_tbl);
+ MODULE_VERSION(DRV_VERSION);
+-MODULE_ALIAS("platform:sata_mv");
++MODULE_ALIAS("platform:" DRV_NAME);
+
+ #ifdef CONFIG_PCI
+ module_param(msi, int, 0444);
+diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
+index ed5473b..858f706 100644
+--- a/drivers/ata/sata_nv.c
++++ b/drivers/ata/sata_nv.c
+@@ -309,7 +309,8 @@ static void nv_nf2_freeze(struct ata_port *ap);
+ static void nv_nf2_thaw(struct ata_port *ap);
+ static void nv_ck804_freeze(struct ata_port *ap);
+ static void nv_ck804_thaw(struct ata_port *ap);
+-static void nv_error_handler(struct ata_port *ap);
++static int nv_hardreset(struct ata_link *link, unsigned int *class,
++ unsigned long deadline);
+ static int nv_adma_slave_config(struct scsi_device *sdev);
+ static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc);
+ static void nv_adma_qc_prep(struct ata_queued_cmd *qc);
+@@ -385,157 +386,60 @@ static struct pci_driver nv_pci_driver = {
+ };
+
+ static struct scsi_host_template nv_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+ static struct scsi_host_template nv_adma_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .change_queue_depth = ata_scsi_change_queue_depth,
++ ATA_NCQ_SHT(DRV_NAME),
+ .can_queue = NV_ADMA_MAX_CPBS,
+- .this_id = ATA_SHT_THIS_ID,
+ .sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+ .dma_boundary = NV_ADMA_DMA_BOUNDARY,
+ .slave_configure = nv_adma_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
+ };
+
+ static struct scsi_host_template nv_swncq_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .change_queue_depth = ata_scsi_change_queue_depth,
++ ATA_NCQ_SHT(DRV_NAME),
+ .can_queue = ATA_MAX_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+ .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+ .dma_boundary = ATA_DMA_BOUNDARY,
+ .slave_configure = nv_swncq_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
+ };
+
+-static const struct ata_port_operations nv_generic_ops = {
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .exec_command = ata_exec_command,
+- .check_status = ata_check_status,
+- .dev_select = ata_std_dev_select,
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = nv_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .data_xfer = ata_data_xfer,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
++static struct ata_port_operations nv_generic_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .hardreset = nv_hardreset,
+ .scr_read = nv_scr_read,
+ .scr_write = nv_scr_write,
+- .port_start = ata_port_start,
+ };
+
+-static const struct ata_port_operations nv_nf2_ops = {
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .exec_command = ata_exec_command,
+- .check_status = ata_check_status,
+- .dev_select = ata_std_dev_select,
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
++static struct ata_port_operations nv_nf2_ops = {
++ .inherits = &nv_generic_ops,
+ .freeze = nv_nf2_freeze,
+ .thaw = nv_nf2_thaw,
+- .error_handler = nv_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .data_xfer = ata_data_xfer,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+- .scr_read = nv_scr_read,
+- .scr_write = nv_scr_write,
+- .port_start = ata_port_start,
+ };
+
+-static const struct ata_port_operations nv_ck804_ops = {
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .exec_command = ata_exec_command,
+- .check_status = ata_check_status,
+- .dev_select = ata_std_dev_select,
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
++static struct ata_port_operations nv_ck804_ops = {
++ .inherits = &nv_generic_ops,
+ .freeze = nv_ck804_freeze,
+ .thaw = nv_ck804_thaw,
+- .error_handler = nv_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .data_xfer = ata_data_xfer,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+- .scr_read = nv_scr_read,
+- .scr_write = nv_scr_write,
+- .port_start = ata_port_start,
+ .host_stop = nv_ck804_host_stop,
+ };
+
+-static const struct ata_port_operations nv_adma_ops = {
+- .tf_load = ata_tf_load,
+- .tf_read = nv_adma_tf_read,
++static struct ata_port_operations nv_adma_ops = {
++ .inherits = &nv_generic_ops,
++
+ .check_atapi_dma = nv_adma_check_atapi_dma,
+- .exec_command = ata_exec_command,
+- .check_status = ata_check_status,
+- .dev_select = ata_std_dev_select,
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
++ .sff_tf_read = nv_adma_tf_read,
+ .qc_defer = ata_std_qc_defer,
+ .qc_prep = nv_adma_qc_prep,
+ .qc_issue = nv_adma_qc_issue,
++ .sff_irq_clear = nv_adma_irq_clear,
++
+ .freeze = nv_adma_freeze,
+ .thaw = nv_adma_thaw,
+ .error_handler = nv_adma_error_handler,
+ .post_internal_cmd = nv_adma_post_internal_cmd,
+- .data_xfer = ata_data_xfer,
+- .irq_clear = nv_adma_irq_clear,
+- .irq_on = ata_irq_on,
+- .scr_read = nv_scr_read,
+- .scr_write = nv_scr_write,
++
+ .port_start = nv_adma_port_start,
+ .port_stop = nv_adma_port_stop,
+ #ifdef CONFIG_PM
+@@ -545,28 +449,17 @@ static const struct ata_port_operations nv_adma_ops = {
+ .host_stop = nv_adma_host_stop,
+ };
+
+-static const struct ata_port_operations nv_swncq_ops = {
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .exec_command = ata_exec_command,
+- .check_status = ata_check_status,
+- .dev_select = ata_std_dev_select,
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
++static struct ata_port_operations nv_swncq_ops = {
++ .inherits = &nv_generic_ops,
++
+ .qc_defer = ata_std_qc_defer,
+ .qc_prep = nv_swncq_qc_prep,
+ .qc_issue = nv_swncq_qc_issue,
++
+ .freeze = nv_mcp55_freeze,
+ .thaw = nv_mcp55_thaw,
+ .error_handler = nv_swncq_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .data_xfer = ata_data_xfer,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+- .scr_read = nv_scr_read,
+- .scr_write = nv_scr_write,
++
+ #ifdef CONFIG_PM
+ .port_suspend = nv_swncq_port_suspend,
+ .port_resume = nv_swncq_port_resume,
+@@ -574,63 +467,61 @@ static const struct ata_port_operations nv_swncq_ops = {
+ .port_start = nv_swncq_port_start,
+ };
+
++struct nv_pi_priv {
++ irq_handler_t irq_handler;
++ struct scsi_host_template *sht;
++};
++
++#define NV_PI_PRIV(_irq_handler, _sht) \
++ &(struct nv_pi_priv){ .irq_handler = _irq_handler, .sht = _sht }
++
+ static const struct ata_port_info nv_port_info[] = {
+ /* generic */
+ {
+- .sht = &nv_sht,
+ .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+- .link_flags = ATA_LFLAG_HRST_TO_RESUME,
+ .pio_mask = NV_PIO_MASK,
+ .mwdma_mask = NV_MWDMA_MASK,
+ .udma_mask = NV_UDMA_MASK,
+ .port_ops = &nv_generic_ops,
+- .irq_handler = nv_generic_interrupt,
++ .private_data = NV_PI_PRIV(nv_generic_interrupt, &nv_sht),
+ },
+ /* nforce2/3 */
+ {
+- .sht = &nv_sht,
+ .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+- .link_flags = ATA_LFLAG_HRST_TO_RESUME,
+ .pio_mask = NV_PIO_MASK,
+ .mwdma_mask = NV_MWDMA_MASK,
+ .udma_mask = NV_UDMA_MASK,
+ .port_ops = &nv_nf2_ops,
+- .irq_handler = nv_nf2_interrupt,
++ .private_data = NV_PI_PRIV(nv_nf2_interrupt, &nv_sht),
+ },
+ /* ck804 */
+ {
+- .sht = &nv_sht,
+ .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+- .link_flags = ATA_LFLAG_HRST_TO_RESUME,
+ .pio_mask = NV_PIO_MASK,
+ .mwdma_mask = NV_MWDMA_MASK,
+ .udma_mask = NV_UDMA_MASK,
+ .port_ops = &nv_ck804_ops,
+- .irq_handler = nv_ck804_interrupt,
++ .private_data = NV_PI_PRIV(nv_ck804_interrupt, &nv_sht),
+ },
+ /* ADMA */
+ {
+- .sht = &nv_adma_sht,
+ .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_MMIO | ATA_FLAG_NCQ,
+- .link_flags = ATA_LFLAG_HRST_TO_RESUME,
+ .pio_mask = NV_PIO_MASK,
+ .mwdma_mask = NV_MWDMA_MASK,
+ .udma_mask = NV_UDMA_MASK,
+ .port_ops = &nv_adma_ops,
+- .irq_handler = nv_adma_interrupt,
++ .private_data = NV_PI_PRIV(nv_adma_interrupt, &nv_adma_sht),
+ },
+ /* SWNCQ */
+ {
+- .sht = &nv_swncq_sht,
+ .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_NCQ,
+- .link_flags = ATA_LFLAG_HRST_TO_RESUME,
+ .pio_mask = NV_PIO_MASK,
+ .mwdma_mask = NV_MWDMA_MASK,
+ .udma_mask = NV_UDMA_MASK,
+ .port_ops = &nv_swncq_ops,
+- .irq_handler = nv_swncq_interrupt,
++ .private_data = NV_PI_PRIV(nv_swncq_interrupt, &nv_swncq_sht),
+ },
+ };
+
+@@ -640,8 +531,8 @@ MODULE_LICENSE("GPL");
+ MODULE_DEVICE_TABLE(pci, nv_pci_tbl);
+ MODULE_VERSION(DRV_VERSION);
+
+-static int adma_enabled = 1;
+-static int swncq_enabled;
++static int adma_enabled;
++static int swncq_enabled = 1;
+
+ static void nv_adma_register_mode(struct ata_port *ap)
+ {
+@@ -839,7 +730,7 @@ static void nv_adma_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+ ADMA mode could abort outstanding commands. */
+ nv_adma_register_mode(ap);
+
+- ata_tf_read(ap, tf);
++ ata_sff_tf_read(ap, tf);
+ }
+
+ static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, __le16 *cpb)
+@@ -929,7 +820,7 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
+ "notifier for tag %d with no cmd?\n",
+ cpb_num);
+ ehi->err_mask |= AC_ERR_HSM;
+- ehi->action |= ATA_EH_SOFTRESET;
++ ehi->action |= ATA_EH_RESET;
+ ata_port_freeze(ap);
+ return 1;
+ }
+@@ -953,12 +844,12 @@ static int nv_host_intr(struct ata_port *ap, u8 irq_stat)
+
+ /* DEV interrupt w/ no active qc? */
+ if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) {
+- ata_check_status(ap);
++ ata_sff_check_status(ap);
+ return 1;
+ }
+
+ /* handle interrupt */
+- return ata_host_intr(ap, qc);
++ return ata_sff_host_intr(ap, qc);
+ }
+
+ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
+@@ -1137,7 +1028,7 @@ static void nv_adma_irq_clear(struct ata_port *ap)
+ u32 notifier_clears[2];
+
+ if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) {
+- ata_bmdma_irq_clear(ap);
++ ata_sff_irq_clear(ap);
+ return;
+ }
+
+@@ -1168,7 +1059,7 @@ static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc)
+ struct nv_adma_port_priv *pp = qc->ap->private_data;
+
+ if (pp->flags & NV_ADMA_PORT_REGISTER_MODE)
+- ata_bmdma_post_internal_cmd(qc);
++ ata_sff_post_internal_cmd(qc);
+ }
+
+ static int nv_adma_port_start(struct ata_port *ap)
+@@ -1445,7 +1336,7 @@ static void nv_adma_qc_prep(struct ata_queued_cmd *qc)
+ BUG_ON(!(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) &&
+ (qc->flags & ATA_QCFLAG_DMAMAP));
+ nv_adma_register_mode(qc->ap);
+- ata_qc_prep(qc);
++ ata_sff_qc_prep(qc);
+ return;
+ }
+
+@@ -1504,7 +1395,7 @@ static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc)
+ BUG_ON(!(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) &&
+ (qc->flags & ATA_QCFLAG_DMAMAP));
+ nv_adma_register_mode(qc->ap);
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ } else
+ nv_adma_mode(qc->ap);
+
+@@ -1545,11 +1436,11 @@ static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance)
+
+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
+ if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
+- handled += ata_host_intr(ap, qc);
++ handled += ata_sff_host_intr(ap, qc);
+ else
+ // No request pending? Clear interrupt status
+ // anyway, in case there's one pending.
+- ap->ops->check_status(ap);
++ ap->ops->sff_check_status(ap);
+ }
+
+ }
+@@ -1680,7 +1571,7 @@ static void nv_mcp55_freeze(struct ata_port *ap)
+ mask = readl(mmio_base + NV_INT_ENABLE_MCP55);
+ mask &= ~(NV_INT_ALL_MCP55 << shift);
+ writel(mask, mmio_base + NV_INT_ENABLE_MCP55);
+- ata_bmdma_freeze(ap);
++ ata_sff_freeze(ap);
+ }
+
+ static void nv_mcp55_thaw(struct ata_port *ap)
+@@ -1694,25 +1585,22 @@ static void nv_mcp55_thaw(struct ata_port *ap)
+ mask = readl(mmio_base + NV_INT_ENABLE_MCP55);
+ mask |= (NV_INT_MASK_MCP55 << shift);
+ writel(mask, mmio_base + NV_INT_ENABLE_MCP55);
+- ata_bmdma_thaw(ap);
++ ata_sff_thaw(ap);
+ }
+
+ static int nv_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline)
+ {
+- unsigned int dummy;
++ int rc;
+
+ /* SATA hardreset fails to retrieve proper device signature on
+- * some controllers. Don't classify on hardreset. For more
+- * info, see http://bugzilla.kernel.org/show_bug.cgi?id=3352
++ * some controllers. Request follow up SRST. For more info,
++ * see http://bugzilla.kernel.org/show_bug.cgi?id=3352
+ */
+- return sata_std_hardreset(link, &dummy, deadline);
+-}
+-
+-static void nv_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
+- nv_hardreset, ata_std_postreset);
++ rc = sata_sff_hardreset(link, class, deadline);
++ if (rc)
++ return rc;
++ return -EAGAIN;
+ }
+
+ static void nv_adma_error_handler(struct ata_port *ap)
+@@ -1768,8 +1656,7 @@ static void nv_adma_error_handler(struct ata_port *ap)
+ readw(mmio + NV_ADMA_CTL); /* flush posted write */
+ }
+
+- ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
+- nv_hardreset, ata_std_postreset);
++ ata_sff_error_handler(ap);
+ }
+
+ static void nv_swncq_qc_to_dq(struct ata_port *ap, struct ata_queued_cmd *qc)
+@@ -1855,7 +1742,7 @@ static void nv_swncq_ncq_stop(struct ata_port *ap)
+ pp->dhfis_bits, pp->dmafis_bits, pp->sdbfis_bits);
+
+ ata_port_printk(ap, KERN_ERR, "ATA_REG 0x%X ERR_REG 0x%X\n",
+- ap->ops->check_status(ap),
++ ap->ops->sff_check_status(ap),
+ ioread8(ap->ioaddr.error_addr));
+
+ sactive = readl(pp->sactive_block);
+@@ -1881,7 +1768,7 @@ static void nv_swncq_ncq_stop(struct ata_port *ap)
+ }
+
+ nv_swncq_pp_reinit(ap);
+- ap->ops->irq_clear(ap);
++ ap->ops->sff_irq_clear(ap);
+ __ata_bmdma_stop(ap);
+ nv_swncq_irq_clear(ap, 0xffff);
+ }
+@@ -1892,11 +1779,10 @@ static void nv_swncq_error_handler(struct ata_port *ap)
+
+ if (ap->link.sactive) {
+ nv_swncq_ncq_stop(ap);
+- ehc->i.action |= ATA_EH_HARDRESET;
++ ehc->i.action |= ATA_EH_RESET;
+ }
+
+- ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
+- nv_hardreset, ata_std_postreset);
++ ata_sff_error_handler(ap);
+ }
+
+ #ifdef CONFIG_PM
+@@ -2042,7 +1928,7 @@ static int nv_swncq_port_start(struct ata_port *ap)
+ static void nv_swncq_qc_prep(struct ata_queued_cmd *qc)
+ {
+ if (qc->tf.protocol != ATA_PROT_NCQ) {
+- ata_qc_prep(qc);
++ ata_sff_qc_prep(qc);
+ return;
+ }
+
+@@ -2104,8 +1990,8 @@ static unsigned int nv_swncq_issue_atacmd(struct ata_port *ap,
+ pp->dmafis_bits &= ~(1 << qc->tag);
+ pp->qc_active |= (0x1 << qc->tag);
+
+- ap->ops->tf_load(ap, &qc->tf); /* load tf registers */
+- ap->ops->exec_command(ap, &qc->tf);
++ ap->ops->sff_tf_load(ap, &qc->tf); /* load tf registers */
++ ap->ops->sff_exec_command(ap, &qc->tf);
+
+ DPRINTK("Issued tag %u\n", qc->tag);
+
+@@ -2118,7 +2004,7 @@ static unsigned int nv_swncq_qc_issue(struct ata_queued_cmd *qc)
+ struct nv_swncq_port_priv *pp = ap->private_data;
+
+ if (qc->tf.protocol != ATA_PROT_NCQ)
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+
+ DPRINTK("Enter\n");
+
+@@ -2173,11 +2059,11 @@ static int nv_swncq_sdbfis(struct ata_port *ap)
+ ata_ehi_clear_desc(ehi);
+ ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
+ ehi->err_mask |= AC_ERR_HOST_BUS;
+- ehi->action |= ATA_EH_SOFTRESET;
++ ehi->action |= ATA_EH_RESET;
+ return -EINVAL;
+ }
+
+- ap->ops->irq_clear(ap);
++ ap->ops->sff_irq_clear(ap);
+ __ata_bmdma_stop(ap);
+
+ sactive = readl(pp->sactive_block);
+@@ -2188,7 +2074,7 @@ static int nv_swncq_sdbfis(struct ata_port *ap)
+ ata_ehi_push_desc(ehi, "illegal SWNCQ:qc_active transition"
+ "(%08x->%08x)", pp->qc_active, sactive);
+ ehi->err_mask |= AC_ERR_HSM;
+- ehi->action |= ATA_EH_HARDRESET;
++ ehi->action |= ATA_EH_RESET;
+ return -EINVAL;
+ }
+ for (i = 0; i < ATA_MAX_QUEUE; i++) {
+@@ -2299,7 +2185,7 @@ static void nv_swncq_host_interrupt(struct ata_port *ap, u16 fis)
+ u8 ata_stat;
+ int rc = 0;
+
+- ata_stat = ap->ops->check_status(ap);
++ ata_stat = ap->ops->sff_check_status(ap);
+ nv_swncq_irq_clear(ap, fis);
+ if (!fis)
+ return;
+@@ -2324,7 +2210,7 @@ static void nv_swncq_host_interrupt(struct ata_port *ap, u16 fis)
+ ata_ehi_push_desc(ehi, "Ata error. fis:0x%X", fis);
+ ehi->err_mask |= AC_ERR_DEV;
+ ehi->serror |= serror;
+- ehi->action |= ATA_EH_SOFTRESET;
++ ehi->action |= ATA_EH_RESET;
+ ata_port_freeze(ap);
+ return;
+ }
+@@ -2356,13 +2242,13 @@ static void nv_swncq_host_interrupt(struct ata_port *ap, u16 fis)
+ if (pp->ncq_flags & (ncq_saw_sdb | ncq_saw_backout)) {
+ ata_ehi_push_desc(ehi, "illegal fis transaction");
+ ehi->err_mask |= AC_ERR_HSM;
+- ehi->action |= ATA_EH_HARDRESET;
++ ehi->action |= ATA_EH_RESET;
+ goto irq_error;
+ }
+
+ if (!(fis & NV_SWNCQ_IRQ_DMASETUP) &&
+ !(pp->ncq_flags & ncq_saw_dmas)) {
+- ata_stat = ap->ops->check_status(ap);
++ ata_stat = ap->ops->sff_check_status(ap);
+ if (ata_stat & ATA_BUSY)
+ goto irq_exit;
+
+@@ -2429,6 +2315,7 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ static int printed_version;
+ const struct ata_port_info *ppi[] = { NULL, NULL };
++ struct nv_pi_priv *ipriv;
+ struct ata_host *host;
+ struct nv_host_priv *hpriv;
+ int rc;
+@@ -2465,7 +2352,8 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ }
+
+ ppi[0] = &nv_port_info[type];
+- rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
++ ipriv = ppi[0]->private_data;
++ rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
+ if (rc)
+ return rc;
+
+@@ -2503,8 +2391,8 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ nv_swncq_host_init(host);
+
+ pci_set_master(pdev);
+- return ata_host_activate(host, pdev->irq, ppi[0]->irq_handler,
+- IRQF_SHARED, ppi[0]->sht);
++ return ata_host_activate(host, pdev->irq, ipriv->irq_handler,
++ IRQF_SHARED, ipriv->sht);
+ }
+
+ #ifdef CONFIG_PM
+@@ -2600,5 +2488,5 @@ module_exit(nv_exit);
+ module_param_named(adma, adma_enabled, bool, 0444);
+ MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: true)");
+ module_param_named(swncq, swncq_enabled, bool, 0444);
+-MODULE_PARM_DESC(swncq, "Enable use of SWNCQ (Default: false)");
++MODULE_PARM_DESC(swncq, "Enable use of SWNCQ (Default: true)");
+
+diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
+index 11c1afe..5a10dc5 100644
+--- a/drivers/ata/sata_promise.c
++++ b/drivers/ata/sata_promise.c
+@@ -143,103 +143,57 @@ static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile
+ static int pdc_check_atapi_dma(struct ata_queued_cmd *qc);
+ static int pdc_old_sata_check_atapi_dma(struct ata_queued_cmd *qc);
+ static void pdc_irq_clear(struct ata_port *ap);
+-static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
++static unsigned int pdc_qc_issue(struct ata_queued_cmd *qc);
+ static void pdc_freeze(struct ata_port *ap);
+ static void pdc_sata_freeze(struct ata_port *ap);
+ static void pdc_thaw(struct ata_port *ap);
+ static void pdc_sata_thaw(struct ata_port *ap);
+-static void pdc_pata_error_handler(struct ata_port *ap);
+-static void pdc_sata_error_handler(struct ata_port *ap);
++static void pdc_error_handler(struct ata_port *ap);
+ static void pdc_post_internal_cmd(struct ata_queued_cmd *qc);
+ static int pdc_pata_cable_detect(struct ata_port *ap);
+ static int pdc_sata_cable_detect(struct ata_port *ap);
+
+ static struct scsi_host_template pdc_ata_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
++ ATA_BASE_SHT(DRV_NAME),
+ .sg_tablesize = PDC_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+ .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
+ };
+
+-static const struct ata_port_operations pdc_sata_ops = {
+- .tf_load = pdc_tf_load_mmio,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = pdc_exec_command_mmio,
+- .dev_select = ata_std_dev_select,
+- .check_atapi_dma = pdc_check_atapi_dma,
++static const struct ata_port_operations pdc_common_ops = {
++ .inherits = &ata_sff_port_ops,
+
++ .sff_tf_load = pdc_tf_load_mmio,
++ .sff_exec_command = pdc_exec_command_mmio,
++ .check_atapi_dma = pdc_check_atapi_dma,
+ .qc_prep = pdc_qc_prep,
+- .qc_issue = pdc_qc_issue_prot,
+- .freeze = pdc_sata_freeze,
+- .thaw = pdc_sata_thaw,
+- .error_handler = pdc_sata_error_handler,
+- .post_internal_cmd = pdc_post_internal_cmd,
+- .cable_detect = pdc_sata_cable_detect,
+- .data_xfer = ata_data_xfer,
+- .irq_clear = pdc_irq_clear,
+- .irq_on = ata_irq_on,
++ .qc_issue = pdc_qc_issue,
++ .sff_irq_clear = pdc_irq_clear,
+
+- .scr_read = pdc_sata_scr_read,
+- .scr_write = pdc_sata_scr_write,
+- .port_start = pdc_sata_port_start,
++ .post_internal_cmd = pdc_post_internal_cmd,
++ .error_handler = pdc_error_handler,
+ };
+
+-/* First-generation chips need a more restrictive ->check_atapi_dma op */
+-static const struct ata_port_operations pdc_old_sata_ops = {
+- .tf_load = pdc_tf_load_mmio,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = pdc_exec_command_mmio,
+- .dev_select = ata_std_dev_select,
+- .check_atapi_dma = pdc_old_sata_check_atapi_dma,
+-
+- .qc_prep = pdc_qc_prep,
+- .qc_issue = pdc_qc_issue_prot,
++static struct ata_port_operations pdc_sata_ops = {
++ .inherits = &pdc_common_ops,
++ .cable_detect = pdc_sata_cable_detect,
+ .freeze = pdc_sata_freeze,
+ .thaw = pdc_sata_thaw,
+- .error_handler = pdc_sata_error_handler,
+- .post_internal_cmd = pdc_post_internal_cmd,
+- .cable_detect = pdc_sata_cable_detect,
+- .data_xfer = ata_data_xfer,
+- .irq_clear = pdc_irq_clear,
+- .irq_on = ata_irq_on,
+-
+ .scr_read = pdc_sata_scr_read,
+ .scr_write = pdc_sata_scr_write,
+ .port_start = pdc_sata_port_start,
+ };
+
+-static const struct ata_port_operations pdc_pata_ops = {
+- .tf_load = pdc_tf_load_mmio,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = pdc_exec_command_mmio,
+- .dev_select = ata_std_dev_select,
+- .check_atapi_dma = pdc_check_atapi_dma,
++/* First-generation chips need a more restrictive ->check_atapi_dma op */
++static struct ata_port_operations pdc_old_sata_ops = {
++ .inherits = &pdc_sata_ops,
++ .check_atapi_dma = pdc_old_sata_check_atapi_dma,
++};
+
+- .qc_prep = pdc_qc_prep,
+- .qc_issue = pdc_qc_issue_prot,
++static struct ata_port_operations pdc_pata_ops = {
++ .inherits = &pdc_common_ops,
++ .cable_detect = pdc_pata_cable_detect,
+ .freeze = pdc_freeze,
+ .thaw = pdc_thaw,
+- .error_handler = pdc_pata_error_handler,
+- .post_internal_cmd = pdc_post_internal_cmd,
+- .cable_detect = pdc_pata_cable_detect,
+- .data_xfer = ata_data_xfer,
+- .irq_clear = pdc_irq_clear,
+- .irq_on = ata_irq_on,
+-
+ .port_start = pdc_common_port_start,
+ };
+
+@@ -451,7 +405,7 @@ static void pdc_atapi_pkt(struct ata_queued_cmd *qc)
+ u8 *cdb = qc->cdb;
+ struct pdc_port_priv *pp = ap->private_data;
+ u8 *buf = pp->pkt;
+- u32 *buf32 = (u32 *) buf;
++ __le32 *buf32 = (__le32 *) buf;
+ unsigned int dev_sel, feature;
+
+ /* set control bits (byte 0), zero delay seq id (byte 3),
+@@ -738,24 +692,12 @@ static void pdc_sata_thaw(struct ata_port *ap)
+ readl(host_mmio + hotplug_offset); /* flush */
+ }
+
+-static void pdc_common_error_handler(struct ata_port *ap, ata_reset_fn_t hardreset)
++static void pdc_error_handler(struct ata_port *ap)
+ {
+ if (!(ap->pflags & ATA_PFLAG_FROZEN))
+ pdc_reset_port(ap);
+
+- /* perform recovery */
+- ata_do_eh(ap, ata_std_prereset, ata_std_softreset, hardreset,
+- ata_std_postreset);
+-}
+-
+-static void pdc_pata_error_handler(struct ata_port *ap)
+-{
+- pdc_common_error_handler(ap, NULL);
+-}
+-
+-static void pdc_sata_error_handler(struct ata_port *ap)
+-{
+- pdc_common_error_handler(ap, sata_std_hardreset);
++ ata_std_error_handler(ap);
+ }
+
+ static void pdc_post_internal_cmd(struct ata_queued_cmd *qc)
+@@ -952,7 +894,7 @@ static inline void pdc_packet_start(struct ata_queued_cmd *qc)
+ readl(ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */
+ }
+
+-static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int pdc_qc_issue(struct ata_queued_cmd *qc)
+ {
+ switch (qc->tf.protocol) {
+ case ATAPI_PROT_NODATA:
+@@ -972,20 +914,20 @@ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
+ break;
+ }
+
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
+ {
+ WARN_ON(tf->protocol == ATA_PROT_DMA || tf->protocol == ATAPI_PROT_DMA);
+- ata_tf_load(ap, tf);
++ ata_sff_tf_load(ap, tf);
+ }
+
+ static void pdc_exec_command_mmio(struct ata_port *ap,
+ const struct ata_taskfile *tf)
+ {
+ WARN_ON(tf->protocol == ATA_PROT_DMA || tf->protocol == ATAPI_PROT_DMA);
+- ata_exec_command(ap, tf);
++ ata_sff_exec_command(ap, tf);
+ }
+
+ static int pdc_check_atapi_dma(struct ata_queued_cmd *qc)
+diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
+index 91cc12c..1600107 100644
+--- a/drivers/ata/sata_qstor.c
++++ b/drivers/ata/sata_qstor.c
+@@ -121,50 +121,38 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc);
+ static int qs_check_atapi_dma(struct ata_queued_cmd *qc);
+ static void qs_bmdma_stop(struct ata_queued_cmd *qc);
+ static u8 qs_bmdma_status(struct ata_port *ap);
+-static void qs_irq_clear(struct ata_port *ap);
+ static void qs_freeze(struct ata_port *ap);
+ static void qs_thaw(struct ata_port *ap);
++static int qs_prereset(struct ata_link *link, unsigned long deadline);
+ static void qs_error_handler(struct ata_port *ap);
+
+ static struct scsi_host_template qs_ata_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
++ ATA_BASE_SHT(DRV_NAME),
+ .sg_tablesize = QS_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ENABLE_CLUSTERING,
+- .proc_name = DRV_NAME,
+ .dma_boundary = QS_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
+ };
+
+-static const struct ata_port_operations qs_ata_ops = {
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
++static struct ata_port_operations qs_ata_ops = {
++ .inherits = &ata_sff_port_ops,
++
+ .check_atapi_dma = qs_check_atapi_dma,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
++ .bmdma_stop = qs_bmdma_stop,
++ .bmdma_status = qs_bmdma_status,
+ .qc_prep = qs_qc_prep,
+ .qc_issue = qs_qc_issue,
+- .data_xfer = ata_data_xfer,
++
+ .freeze = qs_freeze,
+ .thaw = qs_thaw,
++ .prereset = qs_prereset,
++ .softreset = ATA_OP_NULL,
+ .error_handler = qs_error_handler,
+- .irq_clear = qs_irq_clear,
+- .irq_on = ata_irq_on,
++ .post_internal_cmd = ATA_OP_NULL,
++
+ .scr_read = qs_scr_read,
+ .scr_write = qs_scr_write,
++
+ .port_start = qs_port_start,
+ .host_stop = qs_host_stop,
+- .bmdma_stop = qs_bmdma_stop,
+- .bmdma_status = qs_bmdma_status,
+ };
+
+ static const struct ata_port_info qs_port_info[] = {
+@@ -211,11 +199,6 @@ static u8 qs_bmdma_status(struct ata_port *ap)
+ return 0;
+ }
+
+-static void qs_irq_clear(struct ata_port *ap)
+-{
+- /* nothing */
+-}
+-
+ static inline void qs_enter_reg_mode(struct ata_port *ap)
+ {
+ u8 __iomem *chan = qs_mmio_base(ap->host) + (ap->port_no * 0x4000);
+@@ -256,7 +239,7 @@ static int qs_prereset(struct ata_link *link, unsigned long deadline)
+ struct ata_port *ap = link->ap;
+
+ qs_reset_channel_logic(ap);
+- return ata_std_prereset(link, deadline);
++ return ata_sff_prereset(link, deadline);
+ }
+
+ static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
+@@ -270,8 +253,7 @@ static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
+ static void qs_error_handler(struct ata_port *ap)
+ {
+ qs_enter_reg_mode(ap);
+- ata_do_eh(ap, qs_prereset, NULL, sata_std_hardreset,
+- ata_std_postreset);
++ ata_std_error_handler(ap);
+ }
+
+ static int qs_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
+@@ -321,7 +303,7 @@ static void qs_qc_prep(struct ata_queued_cmd *qc)
+
+ qs_enter_reg_mode(qc->ap);
+ if (qc->tf.protocol != ATA_PROT_DMA) {
+- ata_qc_prep(qc);
++ ata_sff_qc_prep(qc);
+ return;
+ }
+
+@@ -380,7 +362,7 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc)
+ }
+
+ pp->state = qs_state_mmio;
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ static void qs_do_or_die(struct ata_queued_cmd *qc, u8 status)
+@@ -469,7 +451,7 @@ static inline unsigned int qs_intr_mmio(struct ata_host *host)
+ * and pretend we knew it was ours.. (ugh).
+ * This does not affect packet mode.
+ */
+- ata_check_status(ap);
++ ata_sff_check_status(ap);
+ handled = 1;
+ continue;
+ }
+@@ -477,7 +459,7 @@ static inline unsigned int qs_intr_mmio(struct ata_host *host)
+ if (!pp || pp->state != qs_state_mmio)
+ continue;
+ if (!(qc->tf.flags & ATA_TFLAG_POLLING))
+- handled |= ata_host_intr(ap, qc);
++ handled |= ata_sff_host_intr(ap, qc);
+ }
+ }
+ return handled;
+diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
+index 0b8191b..88bf421 100644
+--- a/drivers/ata/sata_sil.c
++++ b/drivers/ata/sata_sil.c
+@@ -60,7 +60,6 @@ enum {
+
+ SIL_DFL_PORT_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_MMIO,
+- SIL_DFL_LINK_FLAGS = ATA_LFLAG_HRST_TO_RESUME,
+
+ /*
+ * Controller IDs
+@@ -168,54 +167,23 @@ static struct pci_driver sil_pci_driver = {
+ };
+
+ static struct scsi_host_template sil_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static const struct ata_port_operations sil_ops = {
++static struct ata_port_operations sil_ops = {
++ .inherits = &ata_bmdma_port_ops,
+ .dev_config = sil_dev_config,
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+ .set_mode = sil_set_mode,
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+ .freeze = sil_freeze,
+ .thaw = sil_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+ .scr_read = sil_scr_read,
+ .scr_write = sil_scr_write,
+- .port_start = ata_port_start,
+ };
+
+ static const struct ata_port_info sil_port_info[] = {
+ /* sil_3112 */
+ {
+ .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE,
+- .link_flags = SIL_DFL_LINK_FLAGS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = ATA_UDMA5,
+@@ -225,7 +193,6 @@ static const struct ata_port_info sil_port_info[] = {
+ {
+ .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE |
+ SIL_FLAG_NO_SATA_IRQ,
+- .link_flags = SIL_DFL_LINK_FLAGS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = ATA_UDMA5,
+@@ -234,7 +201,6 @@ static const struct ata_port_info sil_port_info[] = {
+ /* sil_3512 */
+ {
+ .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
+- .link_flags = SIL_DFL_LINK_FLAGS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = ATA_UDMA5,
+@@ -243,7 +209,6 @@ static const struct ata_port_info sil_port_info[] = {
+ /* sil_3114 */
+ {
+ .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
+- .link_flags = SIL_DFL_LINK_FLAGS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = ATA_UDMA5,
+@@ -404,7 +369,7 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
+
+ if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) {
+ /* this sometimes happens, just clear IRQ */
+- ata_chk_status(ap);
++ ap->ops->sff_check_status(ap);
+ return;
+ }
+
+@@ -440,15 +405,15 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
+ }
+
+ /* check main status, clearing INTRQ */
+- status = ata_chk_status(ap);
++ status = ap->ops->sff_check_status(ap);
+ if (unlikely(status & ATA_BUSY))
+ goto err_hsm;
+
+ /* ack bmdma irq events */
+- ata_bmdma_irq_clear(ap);
++ ata_sff_irq_clear(ap);
+
+ /* kick HSM in the ass */
+- ata_hsm_move(ap, qc, status, 0);
++ ata_sff_hsm_move(ap, qc, status, 0);
+
+ if (unlikely(qc->err_mask) && ata_is_dma(qc->tf.protocol))
+ ata_ehi_push_desc(ehi, "BMDMA2 stat 0x%x", bmdma2);
+@@ -515,8 +480,8 @@ static void sil_thaw(struct ata_port *ap)
+ u32 tmp;
+
+ /* clear IRQ */
+- ata_chk_status(ap);
+- ata_bmdma_irq_clear(ap);
++ ap->ops->sff_check_status(ap);
++ ata_sff_irq_clear(ap);
+
+ /* turn on SATA IRQ if supported */
+ if (!(ap->flags & SIL_FLAG_NO_SATA_IRQ))
+@@ -690,7 +655,7 @@ static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ ioaddr->ctl_addr = mmio_base + sil_port[i].ctl;
+ ioaddr->bmdma_addr = mmio_base + sil_port[i].bmdma;
+ ioaddr->scr_addr = mmio_base + sil_port[i].scr;
+- ata_std_ports(ioaddr);
++ ata_sff_std_ports(ioaddr);
+
+ ata_port_pbar_desc(ap, SIL_MMIO_BAR, -1, "mmio");
+ ata_port_pbar_desc(ap, SIL_MMIO_BAR, sil_port[i].tf, "tf");
+diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
+index df7988d..27a1101 100644
+--- a/drivers/ata/sata_sil24.c
++++ b/drivers/ata/sata_sil24.c
+@@ -254,7 +254,6 @@ enum {
+ ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+ ATA_FLAG_NCQ | ATA_FLAG_ACPI_SATA |
+ ATA_FLAG_AN | ATA_FLAG_PMP,
+- SIL24_COMMON_LFLAGS = ATA_LFLAG_SKIP_D2H_BSY,
+ SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */
+
+ IRQ_STAT_4PORTS = 0xf,
+@@ -286,45 +285,45 @@ static struct sil24_cerr_info {
+ "device error via D2H FIS" },
+ [PORT_CERR_SDB] = { AC_ERR_DEV, 0,
+ "device error via SDB FIS" },
+- [PORT_CERR_DATA] = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET,
++ [PORT_CERR_DATA] = { AC_ERR_ATA_BUS, ATA_EH_RESET,
+ "error in data FIS" },
+- [PORT_CERR_SEND] = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET,
++ [PORT_CERR_SEND] = { AC_ERR_ATA_BUS, ATA_EH_RESET,
+ "failed to transmit command FIS" },
+- [PORT_CERR_INCONSISTENT] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
++ [PORT_CERR_INCONSISTENT] = { AC_ERR_HSM, ATA_EH_RESET,
+ "protocol mismatch" },
+- [PORT_CERR_DIRECTION] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
++ [PORT_CERR_DIRECTION] = { AC_ERR_HSM, ATA_EH_RESET,
+ "data directon mismatch" },
+- [PORT_CERR_UNDERRUN] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
++ [PORT_CERR_UNDERRUN] = { AC_ERR_HSM, ATA_EH_RESET,
+ "ran out of SGEs while writing" },
+- [PORT_CERR_OVERRUN] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
++ [PORT_CERR_OVERRUN] = { AC_ERR_HSM, ATA_EH_RESET,
+ "ran out of SGEs while reading" },
+- [PORT_CERR_PKT_PROT] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
++ [PORT_CERR_PKT_PROT] = { AC_ERR_HSM, ATA_EH_RESET,
+ "invalid data directon for ATAPI CDB" },
+- [PORT_CERR_SGT_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET,
++ [PORT_CERR_SGT_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_RESET,
+ "SGT not on qword boundary" },
+- [PORT_CERR_SGT_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
++ [PORT_CERR_SGT_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
+ "PCI target abort while fetching SGT" },
+- [PORT_CERR_SGT_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
++ [PORT_CERR_SGT_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
+ "PCI master abort while fetching SGT" },
+- [PORT_CERR_SGT_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
++ [PORT_CERR_SGT_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
+ "PCI parity error while fetching SGT" },
+- [PORT_CERR_CMD_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET,
++ [PORT_CERR_CMD_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_RESET,
+ "PRB not on qword boundary" },
+- [PORT_CERR_CMD_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
++ [PORT_CERR_CMD_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
+ "PCI target abort while fetching PRB" },
+- [PORT_CERR_CMD_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
++ [PORT_CERR_CMD_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
+ "PCI master abort while fetching PRB" },
+- [PORT_CERR_CMD_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
++ [PORT_CERR_CMD_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
+ "PCI parity error while fetching PRB" },
+- [PORT_CERR_XFR_UNDEF] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
++ [PORT_CERR_XFR_UNDEF] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
+ "undefined error while transferring data" },
+- [PORT_CERR_XFR_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
++ [PORT_CERR_XFR_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
+ "PCI target abort while transferring data" },
+- [PORT_CERR_XFR_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
++ [PORT_CERR_XFR_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
+ "PCI master abort while transferring data" },
+- [PORT_CERR_XFR_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
++ [PORT_CERR_XFR_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
+ "PCI parity error while transferring data" },
+- [PORT_CERR_SENDSERVICE] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
++ [PORT_CERR_SENDSERVICE] = { AC_ERR_HSM, ATA_EH_RESET,
+ "FIS received while sending service FIS" },
+ };
+
+@@ -337,23 +336,26 @@ static struct sil24_cerr_info {
+ struct sil24_port_priv {
+ union sil24_cmd_block *cmd_block; /* 32 cmd blocks */
+ dma_addr_t cmd_block_dma; /* DMA base addr for them */
+- struct ata_taskfile tf; /* Cached taskfile registers */
+ int do_port_rst;
+ };
+
+ static void sil24_dev_config(struct ata_device *dev);
+-static u8 sil24_check_status(struct ata_port *ap);
+ static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val);
+ static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val);
+-static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
+ static int sil24_qc_defer(struct ata_queued_cmd *qc);
+ static void sil24_qc_prep(struct ata_queued_cmd *qc);
+ static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc);
+-static void sil24_irq_clear(struct ata_port *ap);
++static bool sil24_qc_fill_rtf(struct ata_queued_cmd *qc);
+ static void sil24_pmp_attach(struct ata_port *ap);
+ static void sil24_pmp_detach(struct ata_port *ap);
+ static void sil24_freeze(struct ata_port *ap);
+ static void sil24_thaw(struct ata_port *ap);
++static int sil24_softreset(struct ata_link *link, unsigned int *class,
++ unsigned long deadline);
++static int sil24_hardreset(struct ata_link *link, unsigned int *class,
++ unsigned long deadline);
++static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class,
++ unsigned long deadline);
+ static void sil24_error_handler(struct ata_port *ap);
+ static void sil24_post_internal_cmd(struct ata_queued_cmd *qc);
+ static int sil24_port_start(struct ata_port *ap);
+@@ -386,52 +388,36 @@ static struct pci_driver sil24_pci_driver = {
+ };
+
+ static struct scsi_host_template sil24_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .change_queue_depth = ata_scsi_change_queue_depth,
++ ATA_NCQ_SHT(DRV_NAME),
+ .can_queue = SIL24_MAX_CMDS,
+- .this_id = ATA_SHT_THIS_ID,
+ .sg_tablesize = SIL24_MAX_SGE,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+ .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
+ };
+
+-static const struct ata_port_operations sil24_ops = {
+- .dev_config = sil24_dev_config,
+-
+- .check_status = sil24_check_status,
+- .check_altstatus = sil24_check_status,
+- .dev_select = ata_noop_dev_select,
+-
+- .tf_read = sil24_tf_read,
++static struct ata_port_operations sil24_ops = {
++ .inherits = &sata_pmp_port_ops,
+
+ .qc_defer = sil24_qc_defer,
+ .qc_prep = sil24_qc_prep,
+ .qc_issue = sil24_qc_issue,
++ .qc_fill_rtf = sil24_qc_fill_rtf,
+
+- .irq_clear = sil24_irq_clear,
++ .freeze = sil24_freeze,
++ .thaw = sil24_thaw,
++ .softreset = sil24_softreset,
++ .hardreset = sil24_hardreset,
++ .pmp_softreset = sil24_softreset,
++ .pmp_hardreset = sil24_pmp_hardreset,
++ .error_handler = sil24_error_handler,
++ .post_internal_cmd = sil24_post_internal_cmd,
++ .dev_config = sil24_dev_config,
+
+ .scr_read = sil24_scr_read,
+ .scr_write = sil24_scr_write,
+-
+ .pmp_attach = sil24_pmp_attach,
+ .pmp_detach = sil24_pmp_detach,
+
+- .freeze = sil24_freeze,
+- .thaw = sil24_thaw,
+- .error_handler = sil24_error_handler,
+- .post_internal_cmd = sil24_post_internal_cmd,
+-
+ .port_start = sil24_port_start,
+-
+ #ifdef CONFIG_PM
+ .port_resume = sil24_port_resume,
+ #endif
+@@ -449,7 +435,6 @@ static const struct ata_port_info sil24_port_info[] = {
+ {
+ .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) |
+ SIL24_FLAG_PCIX_IRQ_WOC,
+- .link_flags = SIL24_COMMON_LFLAGS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = ATA_UDMA5, /* udma0-5 */
+@@ -458,7 +443,6 @@ static const struct ata_port_info sil24_port_info[] = {
+ /* sil_3132 */
+ {
+ .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2),
+- .link_flags = SIL24_COMMON_LFLAGS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = ATA_UDMA5, /* udma0-5 */
+@@ -467,7 +451,6 @@ static const struct ata_port_info sil24_port_info[] = {
+ /* sil_3131/sil_3531 */
+ {
+ .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1),
+- .link_flags = SIL24_COMMON_LFLAGS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = ATA_UDMA5, /* udma0-5 */
+@@ -482,9 +465,19 @@ static int sil24_tag(int tag)
+ return tag;
+ }
+
++static unsigned long sil24_port_offset(struct ata_port *ap)
++{
++ return ap->port_no * PORT_REGS_SIZE;
++}
++
++static void __iomem *sil24_port_base(struct ata_port *ap)
++{
++ return ap->host->iomap[SIL24_PORT_BAR] + sil24_port_offset(ap);
++}
++
+ static void sil24_dev_config(struct ata_device *dev)
+ {
+- void __iomem *port = dev->link->ap->ioaddr.cmd_addr;
++ void __iomem *port = sil24_port_base(dev->link->ap);
+
+ if (dev->cdb_len == 16)
+ writel(PORT_CS_CDB16, port + PORT_CTRL_STAT);
+@@ -494,7 +487,7 @@ static void sil24_dev_config(struct ata_device *dev)
+
+ static void sil24_read_tf(struct ata_port *ap, int tag, struct ata_taskfile *tf)
+ {
+- void __iomem *port = ap->ioaddr.cmd_addr;
++ void __iomem *port = sil24_port_base(ap);
+ struct sil24_prb __iomem *prb;
+ u8 fis[6 * 4];
+
+@@ -503,12 +496,6 @@ static void sil24_read_tf(struct ata_port *ap, int tag, struct ata_taskfile *tf)
+ ata_tf_from_fis(fis, tf);
+ }
+
+-static u8 sil24_check_status(struct ata_port *ap)
+-{
+- struct sil24_port_priv *pp = ap->private_data;
+- return pp->tf.command;
+-}
+-
+ static int sil24_scr_map[] = {
+ [SCR_CONTROL] = 0,
+ [SCR_STATUS] = 1,
+@@ -518,7 +505,7 @@ static int sil24_scr_map[] = {
+
+ static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val)
+ {
+- void __iomem *scr_addr = ap->ioaddr.scr_addr;
++ void __iomem *scr_addr = sil24_port_base(ap) + PORT_SCONTROL;
+
+ if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
+ void __iomem *addr;
+@@ -531,7 +518,7 @@ static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val)
+
+ static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
+ {
+- void __iomem *scr_addr = ap->ioaddr.scr_addr;
++ void __iomem *scr_addr = sil24_port_base(ap) + PORT_SCONTROL;
+
+ if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
+ void __iomem *addr;
+@@ -542,15 +529,9 @@ static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
+ return -EINVAL;
+ }
+
+-static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+-{
+- struct sil24_port_priv *pp = ap->private_data;
+- *tf = pp->tf;
+-}
+-
+ static void sil24_config_port(struct ata_port *ap)
+ {
+- void __iomem *port = ap->ioaddr.cmd_addr;
++ void __iomem *port = sil24_port_base(ap);
+
+ /* configure IRQ WoC */
+ if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC)
+@@ -575,7 +556,7 @@ static void sil24_config_port(struct ata_port *ap)
+
+ static void sil24_config_pmp(struct ata_port *ap, int attached)
+ {
+- void __iomem *port = ap->ioaddr.cmd_addr;
++ void __iomem *port = sil24_port_base(ap);
+
+ if (attached)
+ writel(PORT_CS_PMP_EN, port + PORT_CTRL_STAT);
+@@ -585,7 +566,7 @@ static void sil24_config_pmp(struct ata_port *ap, int attached)
+
+ static void sil24_clear_pmp(struct ata_port *ap)
+ {
+- void __iomem *port = ap->ioaddr.cmd_addr;
++ void __iomem *port = sil24_port_base(ap);
+ int i;
+
+ writel(PORT_CS_PMP_RESUME, port + PORT_CTRL_CLR);
+@@ -600,12 +581,12 @@ static void sil24_clear_pmp(struct ata_port *ap)
+
+ static int sil24_init_port(struct ata_port *ap)
+ {
+- void __iomem *port = ap->ioaddr.cmd_addr;
++ void __iomem *port = sil24_port_base(ap);
+ struct sil24_port_priv *pp = ap->private_data;
+ u32 tmp;
+
+ /* clear PMP error status */
+- if (ap->nr_pmp_links)
++ if (sata_pmp_attached(ap))
+ sil24_clear_pmp(ap);
+
+ writel(PORT_CS_INIT, port + PORT_CTRL_STAT);
+@@ -616,7 +597,7 @@ static int sil24_init_port(struct ata_port *ap)
+
+ if ((tmp & (PORT_CS_INIT | PORT_CS_RDY)) != PORT_CS_RDY) {
+ pp->do_port_rst = 1;
+- ap->link.eh_context.i.action |= ATA_EH_HARDRESET;
++ ap->link.eh_context.i.action |= ATA_EH_RESET;
+ return -EIO;
+ }
+
+@@ -628,7 +609,7 @@ static int sil24_exec_polled_cmd(struct ata_port *ap, int pmp,
+ int is_cmd, u32 ctrl,
+ unsigned long timeout_msec)
+ {
+- void __iomem *port = ap->ioaddr.cmd_addr;
++ void __iomem *port = sil24_port_base(ap);
+ struct sil24_port_priv *pp = ap->private_data;
+ struct sil24_prb *prb = &pp->cmd_block[0].ata.prb;
+ dma_addr_t paddr = pp->cmd_block_dma;
+@@ -670,10 +651,11 @@ static int sil24_exec_polled_cmd(struct ata_port *ap, int pmp,
+ return rc;
+ }
+
+-static int sil24_do_softreset(struct ata_link *link, unsigned int *class,
+- int pmp, unsigned long deadline)
++static int sil24_softreset(struct ata_link *link, unsigned int *class,
++ unsigned long deadline)
+ {
+ struct ata_port *ap = link->ap;
++ int pmp = sata_srst_pmp(link);
+ unsigned long timeout_msec = 0;
+ struct ata_taskfile tf;
+ const char *reason;
+@@ -681,12 +663,6 @@ static int sil24_do_softreset(struct ata_link *link, unsigned int *class,
+
+ DPRINTK("ENTER\n");
+
+- if (ata_link_offline(link)) {
+- DPRINTK("PHY reports no device\n");
+- *class = ATA_DEV_NONE;
+- goto out;
+- }
+-
+ /* put the port into known state */
+ if (sil24_init_port(ap)) {
+ reason = "port not ready";
+@@ -711,10 +687,6 @@ static int sil24_do_softreset(struct ata_link *link, unsigned int *class,
+ sil24_read_tf(ap, 0, &tf);
+ *class = ata_dev_classify(&tf);
+
+- if (*class == ATA_DEV_UNKNOWN)
+- *class = ATA_DEV_NONE;
+-
+- out:
+ DPRINTK("EXIT, class=%u\n", *class);
+ return 0;
+
+@@ -723,17 +695,11 @@ static int sil24_do_softreset(struct ata_link *link, unsigned int *class,
+ return -EIO;
+ }
+
+-static int sil24_softreset(struct ata_link *link, unsigned int *class,
+- unsigned long deadline)
+-{
+- return sil24_do_softreset(link, class, SATA_PMP_CTRL_PORT, deadline);
+-}
+-
+ static int sil24_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline)
+ {
+ struct ata_port *ap = link->ap;
+- void __iomem *port = ap->ioaddr.cmd_addr;
++ void __iomem *port = sil24_port_base(ap);
+ struct sil24_port_priv *pp = ap->private_data;
+ int did_port_rst = 0;
+ const char *reason;
+@@ -911,7 +877,7 @@ static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc)
+ {
+ struct ata_port *ap = qc->ap;
+ struct sil24_port_priv *pp = ap->private_data;
+- void __iomem *port = ap->ioaddr.cmd_addr;
++ void __iomem *port = sil24_port_base(ap);
+ unsigned int tag = sil24_tag(qc->tag);
+ dma_addr_t paddr;
+ void __iomem *activate;
+@@ -925,9 +891,10 @@ static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc)
+ return 0;
+ }
+
+-static void sil24_irq_clear(struct ata_port *ap)
++static bool sil24_qc_fill_rtf(struct ata_queued_cmd *qc)
+ {
+- /* unused */
++ sil24_read_tf(qc->ap, qc->tag, &qc->result_tf);
++ return true;
+ }
+
+ static void sil24_pmp_attach(struct ata_port *ap)
+@@ -942,12 +909,6 @@ static void sil24_pmp_detach(struct ata_port *ap)
+ sil24_config_pmp(ap, 0);
+ }
+
+-static int sil24_pmp_softreset(struct ata_link *link, unsigned int *class,
+- unsigned long deadline)
+-{
+- return sil24_do_softreset(link, class, link->pmp, deadline);
+-}
+-
+ static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline)
+ {
+@@ -960,12 +921,12 @@ static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class,
+ return rc;
+ }
+
+- return sata_pmp_std_hardreset(link, class, deadline);
++ return sata_std_hardreset(link, class, deadline);
+ }
+
+ static void sil24_freeze(struct ata_port *ap)
+ {
+- void __iomem *port = ap->ioaddr.cmd_addr;
++ void __iomem *port = sil24_port_base(ap);
+
+ /* Port-wide IRQ mask in HOST_CTRL doesn't really work, clear
+ * PORT_IRQ_ENABLE instead.
+@@ -975,7 +936,7 @@ static void sil24_freeze(struct ata_port *ap)
+
+ static void sil24_thaw(struct ata_port *ap)
+ {
+- void __iomem *port = ap->ioaddr.cmd_addr;
++ void __iomem *port = sil24_port_base(ap);
+ u32 tmp;
+
+ /* clear IRQ */
+@@ -988,7 +949,7 @@ static void sil24_thaw(struct ata_port *ap)
+
+ static void sil24_error_intr(struct ata_port *ap)
+ {
+- void __iomem *port = ap->ioaddr.cmd_addr;
++ void __iomem *port = sil24_port_base(ap);
+ struct sil24_port_priv *pp = ap->private_data;
+ struct ata_queued_cmd *qc = NULL;
+ struct ata_link *link;
+@@ -1022,7 +983,7 @@ static void sil24_error_intr(struct ata_port *ap)
+
+ if (irq_stat & PORT_IRQ_UNK_FIS) {
+ ehi->err_mask |= AC_ERR_HSM;
+- ehi->action |= ATA_EH_SOFTRESET;
++ ehi->action |= ATA_EH_RESET;
+ ata_ehi_push_desc(ehi, "unknown FIS");
+ freeze = 1;
+ }
+@@ -1043,14 +1004,14 @@ static void sil24_error_intr(struct ata_port *ap)
+ */
+ if (ap->nr_active_links >= 3) {
+ ehi->err_mask |= AC_ERR_OTHER;
+- ehi->action |= ATA_EH_HARDRESET;
++ ehi->action |= ATA_EH_RESET;
+ ata_ehi_push_desc(ehi, "PMP DMA CS errata");
+ pp->do_port_rst = 1;
+ freeze = 1;
+ }
+
+ /* find out the offending link and qc */
+- if (ap->nr_pmp_links) {
++ if (sata_pmp_attached(ap)) {
+ context = readl(port + PORT_CONTEXT);
+ pmp = (context >> 5) & 0xf;
+
+@@ -1064,7 +1025,7 @@ static void sil24_error_intr(struct ata_port *ap)
+ irq_stat);
+ } else {
+ err_mask |= AC_ERR_HSM;
+- action |= ATA_EH_HARDRESET;
++ action |= ATA_EH_RESET;
+ freeze = 1;
+ }
+ } else
+@@ -1078,28 +1039,27 @@ static void sil24_error_intr(struct ata_port *ap)
+ if (ci && ci->desc) {
+ err_mask |= ci->err_mask;
+ action |= ci->action;
+- if (action & ATA_EH_RESET_MASK)
++ if (action & ATA_EH_RESET)
+ freeze = 1;
+ ata_ehi_push_desc(ehi, "%s", ci->desc);
+ } else {
+ err_mask |= AC_ERR_OTHER;
+- action |= ATA_EH_SOFTRESET;
++ action |= ATA_EH_RESET;
+ freeze = 1;
+ ata_ehi_push_desc(ehi, "unknown command error %d",
+ cerr);
+ }
+
+ /* record error info */
+- if (qc) {
+- sil24_read_tf(ap, qc->tag, &pp->tf);
++ if (qc)
+ qc->err_mask |= err_mask;
+- } else
++ else
+ ehi->err_mask |= err_mask;
+
+ ehi->action |= action;
+
+ /* if PMP, resume */
+- if (ap->nr_pmp_links)
++ if (sata_pmp_attached(ap))
+ writel(PORT_CS_PMP_RESUME, port + PORT_CTRL_STAT);
+ }
+
+@@ -1114,18 +1074,9 @@ static void sil24_error_intr(struct ata_port *ap)
+ }
+ }
+
+-static void sil24_finish_qc(struct ata_queued_cmd *qc)
+-{
+- struct ata_port *ap = qc->ap;
+- struct sil24_port_priv *pp = ap->private_data;
+-
+- if (qc->flags & ATA_QCFLAG_RESULT_TF)
+- sil24_read_tf(ap, qc->tag, &pp->tf);
+-}
+-
+ static inline void sil24_host_intr(struct ata_port *ap)
+ {
+- void __iomem *port = ap->ioaddr.cmd_addr;
++ void __iomem *port = sil24_port_base(ap);
+ u32 slot_stat, qc_active;
+ int rc;
+
+@@ -1147,13 +1098,13 @@ static inline void sil24_host_intr(struct ata_port *ap)
+ }
+
+ qc_active = slot_stat & ~HOST_SSTAT_ATTN;
+- rc = ata_qc_complete_multiple(ap, qc_active, sil24_finish_qc);
++ rc = ata_qc_complete_multiple(ap, qc_active);
+ if (rc > 0)
+ return;
+ if (rc < 0) {
+ struct ata_eh_info *ehi = &ap->link.eh_info;
+ ehi->err_mask |= AC_ERR_HSM;
+- ehi->action |= ATA_EH_SOFTRESET;
++ ehi->action |= ATA_EH_RESET;
+ ata_port_freeze(ap);
+ return;
+ }
+@@ -1209,11 +1160,7 @@ static void sil24_error_handler(struct ata_port *ap)
+ if (sil24_init_port(ap))
+ ata_eh_freeze_port(ap);
+
+- /* perform recovery */
+- sata_pmp_do_eh(ap, ata_std_prereset, sil24_softreset, sil24_hardreset,
+- ata_std_postreset, sata_pmp_std_prereset,
+- sil24_pmp_softreset, sil24_pmp_hardreset,
+- sata_pmp_std_postreset);
++ sata_pmp_error_handler(ap);
+
+ pp->do_port_rst = 0;
+ }
+@@ -1239,8 +1186,6 @@ static int sil24_port_start(struct ata_port *ap)
+ if (!pp)
+ return -ENOMEM;
+
+- pp->tf.command = ATA_DRDY;
+-
+ cb = dmam_alloc_coherent(dev, cb_size, &cb_dma, GFP_KERNEL);
+ if (!cb)
+ return -ENOMEM;
+@@ -1251,6 +1196,9 @@ static int sil24_port_start(struct ata_port *ap)
+
+ ap->private_data = pp;
+
++ ata_port_pbar_desc(ap, SIL24_HOST_BAR, -1, "host");
++ ata_port_pbar_desc(ap, SIL24_PORT_BAR, sil24_port_offset(ap), "port");
++
+ return 0;
+ }
+
+@@ -1269,7 +1217,8 @@ static void sil24_init_controller(struct ata_host *host)
+ /* init ports */
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+- void __iomem *port = ap->ioaddr.cmd_addr;
++ void __iomem *port = sil24_port_base(ap);
++
+
+ /* Initial PHY setting */
+ writel(0x20c, port + PORT_PHY_CFG);
+@@ -1302,7 +1251,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ const struct ata_port_info *ppi[] = { &pi, NULL };
+ void __iomem * const *iomap;
+ struct ata_host *host;
+- int i, rc;
++ int rc;
+ u32 tmp;
+
+ /* cause link error if sil24_cmd_block is sized wrongly */
+@@ -1342,18 +1291,6 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ return -ENOMEM;
+ host->iomap = iomap;
+
+- for (i = 0; i < host->n_ports; i++) {
+- struct ata_port *ap = host->ports[i];
+- size_t offset = ap->port_no * PORT_REGS_SIZE;
+- void __iomem *port = iomap[SIL24_PORT_BAR] + offset;
+-
+- host->ports[i]->ioaddr.cmd_addr = port;
+- host->ports[i]->ioaddr.scr_addr = port + PORT_SCONTROL;
+-
+- ata_port_pbar_desc(ap, SIL24_HOST_BAR, -1, "host");
+- ata_port_pbar_desc(ap, SIL24_PORT_BAR, offset, "port");
+- }
+-
+ /* configure and activate the device */
+ if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+ rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c
+index a01260a..1010b30 100644
+--- a/drivers/ata/sata_sis.c
++++ b/drivers/ata/sata_sis.c
+@@ -86,45 +86,13 @@ static struct pci_driver sis_pci_driver = {
+ };
+
+ static struct scsi_host_template sis_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static const struct ata_port_operations sis_ops = {
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
++static struct ata_port_operations sis_ops = {
++ .inherits = &ata_bmdma_port_ops,
+ .scr_read = sis_scr_read,
+ .scr_write = sis_scr_write,
+- .port_start = ata_port_start,
+ };
+
+ static const struct ata_port_info sis_port_info = {
+@@ -174,7 +142,7 @@ static u32 sis_scr_cfg_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
+ u8 pmr;
+
+ if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */
+- return 0xffffffff;
++ return -EINVAL;
+
+ pci_read_config_byte(pdev, SIS_PMR, &pmr);
+
+@@ -190,14 +158,14 @@ static u32 sis_scr_cfg_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
+ return 0;
+ }
+
+-static void sis_scr_cfg_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
++static int sis_scr_cfg_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
+ {
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg);
+ u8 pmr;
+
+ if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */
+- return;
++ return -EINVAL;
+
+ pci_read_config_byte(pdev, SIS_PMR, &pmr);
+
+@@ -206,6 +174,8 @@ static void sis_scr_cfg_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
+ if ((pdev->device == 0x0182) || (pdev->device == 0x0183) ||
+ (pdev->device == 0x1182) || (pmr & SIS_PMR_COMBINED))
+ pci_write_config_dword(pdev, cfg_addr+0x10, val);
++
++ return 0;
+ }
+
+ static int sis_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
+@@ -243,14 +213,14 @@ static int sis_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
+ pci_read_config_byte(pdev, SIS_PMR, &pmr);
+
+ if (ap->flags & SIS_FLAG_CFGSCR)
+- sis_scr_cfg_write(ap, sc_reg, val);
++ return sis_scr_cfg_write(ap, sc_reg, val);
+ else {
+ iowrite32(val, ap->ioaddr.scr_addr + (sc_reg * 4));
+ if ((pdev->device == 0x0182) || (pdev->device == 0x0183) ||
+ (pdev->device == 0x1182) || (pmr & SIS_PMR_COMBINED))
+ iowrite32(val, ap->ioaddr.scr_addr + (sc_reg * 4)+0x10);
++ return 0;
+ }
+- return 0;
+ }
+
+ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+@@ -341,7 +311,7 @@ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ break;
+ }
+
+- rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
++ rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
+ if (rc)
+ return rc;
+
+@@ -359,8 +329,8 @@ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+
+ pci_set_master(pdev);
+ pci_intx(pdev, 1);
+- return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+- &sis_sht);
++ return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
++ IRQF_SHARED, &sis_sht);
+ }
+
+ static int __init sis_init(void)
+diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
+index 019e367..16aa683 100644
+--- a/drivers/ata/sata_svw.c
++++ b/drivers/ata/sata_svw.c
+@@ -233,7 +233,7 @@ static void k2_bmdma_setup_mmio(struct ata_queued_cmd *qc)
+
+ /* issue r/w command if this is not a ATA DMA command*/
+ if (qc->tf.protocol != ATA_PROT_DMA)
+- ap->ops->exec_command(ap, &qc->tf);
++ ap->ops->sff_exec_command(ap, &qc->tf);
+ }
+
+ /**
+@@ -269,7 +269,7 @@ static void k2_bmdma_start_mmio(struct ata_queued_cmd *qc)
+ and the start command. */
+ /* issue r/w command if the access is to ATA*/
+ if (qc->tf.protocol == ATA_PROT_DMA)
+- ap->ops->exec_command(ap, &qc->tf);
++ ap->ops->sff_exec_command(ap, &qc->tf);
+ }
+
+
+@@ -327,50 +327,23 @@ static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start,
+
+
+ static struct scsi_host_template k2_sata_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
++ ATA_BMDMA_SHT(DRV_NAME),
+ #ifdef CONFIG_PPC_OF
+ .proc_info = k2_sata_proc_info,
+ #endif
+- .bios_param = ata_std_bios_param,
+ };
+
+
+-static const struct ata_port_operations k2_sata_ops = {
+- .tf_load = k2_sata_tf_load,
+- .tf_read = k2_sata_tf_read,
+- .check_status = k2_stat_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
++static struct ata_port_operations k2_sata_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .sff_tf_load = k2_sata_tf_load,
++ .sff_tf_read = k2_sata_tf_read,
++ .sff_check_status = k2_stat_check_status,
+ .check_atapi_dma = k2_sata_check_atapi_dma,
+ .bmdma_setup = k2_bmdma_setup_mmio,
+ .bmdma_start = k2_bmdma_start_mmio,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+ .scr_read = k2_sata_scr_read,
+ .scr_write = k2_sata_scr_write,
+- .port_start = ata_port_start,
+ };
+
+ static const struct ata_port_info k2_port_info[] = {
+@@ -519,8 +492,8 @@ static int k2_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *en
+ writel(0x0, mmio_base + K2_SATA_SIM_OFFSET);
+
+ pci_set_master(pdev);
+- return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+- &k2_sata_sht);
++ return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
++ IRQF_SHARED, &k2_sata_sht);
+ }
+
+ /* 0x240 is device ID for Apple K2 device
+diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
+index e3d56bc..ec04b8d 100644
+--- a/drivers/ata/sata_sx4.c
++++ b/drivers/ata/sata_sx4.c
+@@ -232,40 +232,30 @@ static void pdc20621_get_from_dimm(struct ata_host *host,
+ static void pdc20621_put_to_dimm(struct ata_host *host,
+ void *psource, u32 offset, u32 size);
+ static void pdc20621_irq_clear(struct ata_port *ap);
+-static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc);
++static unsigned int pdc20621_qc_issue(struct ata_queued_cmd *qc);
+
+
+ static struct scsi_host_template pdc_sata_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
++ ATA_BASE_SHT(DRV_NAME),
+ .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+ .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
+ };
+
+-static const struct ata_port_operations pdc_20621_ops = {
+- .tf_load = pdc_tf_load_mmio,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = pdc_exec_command_mmio,
+- .dev_select = ata_std_dev_select,
++/* TODO: inherit from base port_ops after converting to new EH */
++static struct ata_port_operations pdc_20621_ops = {
++ .sff_tf_load = pdc_tf_load_mmio,
++ .sff_tf_read = ata_sff_tf_read,
++ .sff_check_status = ata_sff_check_status,
++ .sff_exec_command = pdc_exec_command_mmio,
++ .sff_dev_select = ata_sff_dev_select,
+ .phy_reset = pdc_20621_phy_reset,
+ .qc_prep = pdc20621_qc_prep,
+- .qc_issue = pdc20621_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
++ .qc_issue = pdc20621_qc_issue,
++ .qc_fill_rtf = ata_sff_qc_fill_rtf,
++ .sff_data_xfer = ata_sff_data_xfer,
+ .eng_timeout = pdc_eng_timeout,
+- .irq_clear = pdc20621_irq_clear,
+- .irq_on = ata_irq_on,
++ .sff_irq_clear = pdc20621_irq_clear,
++ .sff_irq_on = ata_sff_irq_on,
+ .port_start = pdc_port_start,
+ };
+
+@@ -475,7 +465,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
+ void __iomem *dimm_mmio = ap->host->iomap[PDC_DIMM_BAR];
+ unsigned int portno = ap->port_no;
+ unsigned int i, si, idx, total_len = 0, sgt_len;
+- u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
++ __le32 *buf = (__le32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
+
+ WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
+
+@@ -693,7 +683,7 @@ static void pdc20621_packet_start(struct ata_queued_cmd *qc)
+ }
+ }
+
+-static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc)
++static unsigned int pdc20621_qc_issue(struct ata_queued_cmd *qc)
+ {
+ switch (qc->tf.protocol) {
+ case ATA_PROT_DMA:
+@@ -709,7 +699,7 @@ static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc)
+ break;
+ }
+
+- return ata_qc_issue_prot(qc);
++ return ata_sff_qc_issue(qc);
+ }
+
+ static inline unsigned int pdc20621_host_intr(struct ata_port *ap,
+@@ -781,7 +771,7 @@ static inline unsigned int pdc20621_host_intr(struct ata_port *ap,
+ /* command completion, but no data xfer */
+ } else if (qc->tf.protocol == ATA_PROT_NODATA) {
+
+- status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
++ status = ata_sff_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+ DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
+ qc->err_mask |= ac_err_mask(status);
+ ata_qc_complete(qc);
+@@ -890,7 +880,7 @@ static void pdc_eng_timeout(struct ata_port *ap)
+ break;
+
+ default:
+- drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
++ drv_stat = ata_sff_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+
+ ata_port_printk(ap, KERN_ERR,
+ "unknown timeout, cmd 0x%x stat 0x%x\n",
+@@ -909,7 +899,7 @@ static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
+ {
+ WARN_ON(tf->protocol == ATA_PROT_DMA ||
+ tf->protocol == ATA_PROT_NODATA);
+- ata_tf_load(ap, tf);
++ ata_sff_tf_load(ap, tf);
+ }
+
+
+@@ -917,7 +907,7 @@ static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile
+ {
+ WARN_ON(tf->protocol == ATA_PROT_DMA ||
+ tf->protocol == ATA_PROT_NODATA);
+- ata_exec_command(ap, tf);
++ ata_sff_exec_command(ap, tf);
+ }
+
+
+diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c
+index e710e71..f277cea 100644
+--- a/drivers/ata/sata_uli.c
++++ b/drivers/ata/sata_uli.c
+@@ -76,50 +76,13 @@ static struct pci_driver uli_pci_driver = {
+ };
+
+ static struct scsi_host_template uli_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static const struct ata_port_operations uli_ops = {
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
++static struct ata_port_operations uli_ops = {
++ .inherits = &ata_bmdma_port_ops,
+ .scr_read = uli_scr_read,
+ .scr_write = uli_scr_write,
+-
+- .port_start = ata_port_start,
+ };
+
+ static const struct ata_port_info uli_port_info = {
+@@ -212,11 +175,11 @@ static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ host->private_data = hpriv;
+
+ /* the first two ports are standard SFF */
+- rc = ata_pci_init_sff_host(host);
++ rc = ata_pci_sff_init_host(host);
+ if (rc)
+ return rc;
+
+- rc = ata_pci_init_bmdma(host);
++ rc = ata_pci_bmdma_init(host);
+ if (rc)
+ return rc;
+
+@@ -237,7 +200,7 @@ static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ ((unsigned long)iomap[1] | ATA_PCI_CTL_OFS) + 4;
+ ioaddr->bmdma_addr = iomap[4] + 16;
+ hpriv->scr_cfg_addr[2] = ULI5287_BASE + ULI5287_OFFS*4;
+- ata_std_ports(ioaddr);
++ ata_sff_std_ports(ioaddr);
+
+ ata_port_desc(host->ports[2],
+ "cmd 0x%llx ctl 0x%llx bmdma 0x%llx",
+@@ -252,7 +215,7 @@ static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ ((unsigned long)iomap[3] | ATA_PCI_CTL_OFS) + 4;
+ ioaddr->bmdma_addr = iomap[4] + 24;
+ hpriv->scr_cfg_addr[3] = ULI5287_BASE + ULI5287_OFFS*5;
+- ata_std_ports(ioaddr);
++ ata_sff_std_ports(ioaddr);
+
+ ata_port_desc(host->ports[2],
+ "cmd 0x%llx ctl 0x%llx bmdma 0x%llx",
+@@ -279,8 +242,8 @@ static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+
+ pci_set_master(pdev);
+ pci_intx(pdev, 1);
+- return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+- &uli_sht);
++ return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
++ IRQF_SHARED, &uli_sht);
+ }
+
+ static int __init uli_init(void)
+diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
+index 0d03f44..96deeb3 100644
+--- a/drivers/ata/sata_via.c
++++ b/drivers/ata/sata_via.c
+@@ -71,7 +71,7 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+ static int svia_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
+ static int svia_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
+ static void svia_noop_freeze(struct ata_port *ap);
+-static void vt6420_error_handler(struct ata_port *ap);
++static int vt6420_prereset(struct ata_link *link, unsigned long deadline);
+ static int vt6421_pata_cable_detect(struct ata_port *ap);
+ static void vt6421_set_pio_mode(struct ata_port *ap, struct ata_device *adev);
+ static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev);
+@@ -100,110 +100,26 @@ static struct pci_driver svia_pci_driver = {
+ };
+
+ static struct scsi_host_template svia_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+-static const struct ata_port_operations vt6420_sata_ops = {
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
++static struct ata_port_operations vt6420_sata_ops = {
++ .inherits = &ata_bmdma_port_ops,
+ .freeze = svia_noop_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = vt6420_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_port_start,
++ .prereset = vt6420_prereset,
+ };
+
+-static const struct ata_port_operations vt6421_pata_ops = {
++static struct ata_port_operations vt6421_pata_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .cable_detect = vt6421_pata_cable_detect,
+ .set_piomode = vt6421_set_pio_mode,
+ .set_dmamode = vt6421_set_dma_mode,
+-
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = vt6421_pata_cable_detect,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
+- .port_start = ata_port_start,
+ };
+
+-static const struct ata_port_operations vt6421_sata_ops = {
+- .tf_load = ata_tf_load,
+- .tf_read = ata_tf_read,
+- .check_status = ata_check_status,
+- .exec_command = ata_exec_command,
+- .dev_select = ata_std_dev_select,
+-
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+-
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
+-
+- .freeze = ata_bmdma_freeze,
+- .thaw = ata_bmdma_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .cable_detect = ata_cable_sata,
+-
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+-
++static struct ata_port_operations vt6421_sata_ops = {
++ .inherits = &ata_bmdma_port_ops,
+ .scr_read = svia_scr_read,
+ .scr_write = svia_scr_write,
+-
+- .port_start = ata_port_start,
+ };
+
+ static const struct ata_port_info vt6420_port_info = {
+@@ -257,8 +173,8 @@ static void svia_noop_freeze(struct ata_port *ap)
+ /* Some VIA controllers choke if ATA_NIEN is manipulated in
+ * certain way. Leave it alone and just clear pending IRQ.
+ */
+- ata_chk_status(ap);
+- ata_bmdma_irq_clear(ap);
++ ap->ops->sff_check_status(ap);
++ ata_sff_irq_clear(ap);
+ }
+
+ /**
+@@ -320,23 +236,17 @@ static int vt6420_prereset(struct ata_link *link, unsigned long deadline)
+
+ if (!online) {
+ /* tell EH to bail */
+- ehc->i.action &= ~ATA_EH_RESET_MASK;
++ ehc->i.action &= ~ATA_EH_RESET;
+ return 0;
+ }
+
+ skip_scr:
+ /* wait for !BSY */
+- ata_wait_ready(ap, deadline);
++ ata_sff_wait_ready(link, deadline);
+
+ return 0;
+ }
+
+-static void vt6420_error_handler(struct ata_port *ap)
+-{
+- ata_bmdma_drive_eh(ap, vt6420_prereset, ata_std_softreset, NULL,
+- ata_std_postreset);
+-}
+-
+ static int vt6421_pata_cable_detect(struct ata_port *ap)
+ {
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+@@ -394,7 +304,7 @@ static void vt6421_init_addrs(struct ata_port *ap)
+ ioaddr->bmdma_addr = bmdma_addr;
+ ioaddr->scr_addr = vt6421_scr_addr(iomap[5], ap->port_no);
+
+- ata_std_ports(ioaddr);
++ ata_sff_std_ports(ioaddr);
+
+ ata_port_pbar_desc(ap, ap->port_no, -1, "port");
+ ata_port_pbar_desc(ap, 4, ap->port_no * 8, "bmdma");
+@@ -406,7 +316,7 @@ static int vt6420_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
+ struct ata_host *host;
+ int rc;
+
+- rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
++ rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
+ if (rc)
+ return rc;
+ *r_host = host;
+@@ -538,8 +448,8 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ svia_configure(pdev);
+
+ pci_set_master(pdev);
+- return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+- &svia_sht);
++ return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
++ IRQF_SHARED, &svia_sht);
+ }
+
+ static int __init svia_init(void)
+diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c
+index 95ae3ed..f3d635c 100644
+--- a/drivers/ata/sata_vsc.c
++++ b/drivers/ata/sata_vsc.c
+@@ -200,7 +200,7 @@ static void vsc_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+ u16 nsect, lbal, lbam, lbah, feature;
+
+- tf->command = ata_check_status(ap);
++ tf->command = ata_sff_check_status(ap);
+ tf->device = readw(ioaddr->device_addr);
+ feature = readw(ioaddr->error_addr);
+ nsect = readw(ioaddr->nsect_addr);
+@@ -243,7 +243,7 @@ static void vsc_port_intr(u8 port_status, struct ata_port *ap)
+
+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
+ if (qc && likely(!(qc->tf.flags & ATA_TFLAG_POLLING)))
+- handled = ata_host_intr(ap, qc);
++ handled = ata_sff_host_intr(ap, qc);
+
+ /* We received an interrupt during a polled command,
+ * or some other spurious condition. Interrupt reporting
+@@ -251,7 +251,7 @@ static void vsc_port_intr(u8 port_status, struct ata_port *ap)
+ * simply clear the interrupt
+ */
+ if (unlikely(!handled))
+- ata_chk_status(ap);
++ ap->ops->sff_check_status(ap);
+ }
+
+ /*
+@@ -300,46 +300,18 @@ out:
+
+
+ static struct scsi_host_template vsc_sata_sht = {
+- .module = THIS_MODULE,
+- .name = DRV_NAME,
+- .ioctl = ata_scsi_ioctl,
+- .queuecommand = ata_scsi_queuecmd,
+- .can_queue = ATA_DEF_QUEUE,
+- .this_id = ATA_SHT_THIS_ID,
+- .sg_tablesize = LIBATA_MAX_PRD,
+- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+- .emulated = ATA_SHT_EMULATED,
+- .use_clustering = ATA_SHT_USE_CLUSTERING,
+- .proc_name = DRV_NAME,
+- .dma_boundary = ATA_DMA_BOUNDARY,
+- .slave_configure = ata_scsi_slave_config,
+- .slave_destroy = ata_scsi_slave_destroy,
+- .bios_param = ata_std_bios_param,
++ ATA_BMDMA_SHT(DRV_NAME),
+ };
+
+
+-static const struct ata_port_operations vsc_sata_ops = {
+- .tf_load = vsc_sata_tf_load,
+- .tf_read = vsc_sata_tf_read,
+- .exec_command = ata_exec_command,
+- .check_status = ata_check_status,
+- .dev_select = ata_std_dev_select,
+- .bmdma_setup = ata_bmdma_setup,
+- .bmdma_start = ata_bmdma_start,
+- .bmdma_stop = ata_bmdma_stop,
+- .bmdma_status = ata_bmdma_status,
+- .qc_prep = ata_qc_prep,
+- .qc_issue = ata_qc_issue_prot,
+- .data_xfer = ata_data_xfer,
++static struct ata_port_operations vsc_sata_ops = {
++ .inherits = &ata_bmdma_port_ops,
++ .sff_tf_load = vsc_sata_tf_load,
++ .sff_tf_read = vsc_sata_tf_read,
+ .freeze = vsc_freeze,
+ .thaw = vsc_thaw,
+- .error_handler = ata_bmdma_error_handler,
+- .post_internal_cmd = ata_bmdma_post_internal_cmd,
+- .irq_clear = ata_bmdma_irq_clear,
+- .irq_on = ata_irq_on,
+ .scr_read = vsc_sata_scr_read,
+ .scr_write = vsc_sata_scr_write,
+- .port_start = ata_port_start,
+ };
+
+ static void __devinit vsc_sata_setup_port(struct ata_ioports *port,
+diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
+index 7b44a59..5aa12b0 100644
+--- a/drivers/atm/ambassador.c
++++ b/drivers/atm/ambassador.c
+@@ -437,7 +437,7 @@ static inline void dump_skb (char * prefix, unsigned int vc, struct sk_buff * sk
+
+ /* see limitations under Hardware Features */
+
+-static inline int check_area (void * start, size_t length) {
++static int check_area (void * start, size_t length) {
+ // assumes length > 0
+ const u32 fourmegmask = -1 << 22;
+ const u32 twofivesixmask = -1 << 8;
+@@ -456,7 +456,7 @@ static inline int check_area (void * start, size_t length) {
+
+ /********** free an skb (as per ATM device driver documentation) **********/
+
+-static inline void amb_kfree_skb (struct sk_buff * skb) {
++static void amb_kfree_skb (struct sk_buff * skb) {
+ if (ATM_SKB(skb)->vcc->pop) {
+ ATM_SKB(skb)->vcc->pop (ATM_SKB(skb)->vcc, skb);
+ } else {
+@@ -466,7 +466,7 @@ static inline void amb_kfree_skb (struct sk_buff * skb) {
+
+ /********** TX completion **********/
+
+-static inline void tx_complete (amb_dev * dev, tx_out * tx) {
++static void tx_complete (amb_dev * dev, tx_out * tx) {
+ tx_simple * tx_descr = bus_to_virt (tx->handle);
+ struct sk_buff * skb = tx_descr->skb;
+
+@@ -643,7 +643,7 @@ static int command_do (amb_dev * dev, command * cmd) {
+
+ /********** TX queue pair **********/
+
+-static inline int tx_give (amb_dev * dev, tx_in * tx) {
++static int tx_give (amb_dev * dev, tx_in * tx) {
+ amb_txq * txq = &dev->txq;
+ unsigned long flags;
+
+@@ -675,7 +675,7 @@ static inline int tx_give (amb_dev * dev, tx_in * tx) {
+ }
+ }
+
+-static inline int tx_take (amb_dev * dev) {
++static int tx_take (amb_dev * dev) {
+ amb_txq * txq = &dev->txq;
+ unsigned long flags;
+
+@@ -703,7 +703,7 @@ static inline int tx_take (amb_dev * dev) {
+
+ /********** RX queue pairs **********/
+
+-static inline int rx_give (amb_dev * dev, rx_in * rx, unsigned char pool) {
++static int rx_give (amb_dev * dev, rx_in * rx, unsigned char pool) {
+ amb_rxq * rxq = &dev->rxq[pool];
+ unsigned long flags;
+
+@@ -728,7 +728,7 @@ static inline int rx_give (amb_dev * dev, rx_in * rx, unsigned char pool) {
+ }
+ }
+
+-static inline int rx_take (amb_dev * dev, unsigned char pool) {
++static int rx_take (amb_dev * dev, unsigned char pool) {
+ amb_rxq * rxq = &dev->rxq[pool];
+ unsigned long flags;
+
+@@ -761,7 +761,7 @@ static inline int rx_take (amb_dev * dev, unsigned char pool) {
+ /********** RX Pool handling **********/
+
+ /* pre: buffers_wanted = 0, post: pending = 0 */
+-static inline void drain_rx_pool (amb_dev * dev, unsigned char pool) {
++static void drain_rx_pool (amb_dev * dev, unsigned char pool) {
+ amb_rxq * rxq = &dev->rxq[pool];
+
+ PRINTD (DBG_FLOW|DBG_POOL, "drain_rx_pool %p %hu", dev, pool);
+@@ -796,7 +796,7 @@ static void drain_rx_pools (amb_dev * dev) {
+ drain_rx_pool (dev, pool);
+ }
+
+-static inline void fill_rx_pool (amb_dev * dev, unsigned char pool,
++static void fill_rx_pool (amb_dev * dev, unsigned char pool,
+ gfp_t priority)
+ {
+ rx_in rx;
+@@ -846,7 +846,7 @@ static void fill_rx_pools (amb_dev * dev) {
+
+ /********** enable host interrupts **********/
+
+-static inline void interrupts_on (amb_dev * dev) {
++static void interrupts_on (amb_dev * dev) {
+ wr_plain (dev, offsetof(amb_mem, interrupt_control),
+ rd_plain (dev, offsetof(amb_mem, interrupt_control))
+ | AMB_INTERRUPT_BITS);
+@@ -854,7 +854,7 @@ static inline void interrupts_on (amb_dev * dev) {
+
+ /********** disable host interrupts **********/
+
+-static inline void interrupts_off (amb_dev * dev) {
++static void interrupts_off (amb_dev * dev) {
+ wr_plain (dev, offsetof(amb_mem, interrupt_control),
+ rd_plain (dev, offsetof(amb_mem, interrupt_control))
+ &~ AMB_INTERRUPT_BITS);
+diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c
+index 9b2cf25..c0ac728 100644
+--- a/drivers/atm/horizon.c
++++ b/drivers/atm/horizon.c
+@@ -424,7 +424,7 @@ static inline void FLUSH_RX_CHANNEL (hrz_dev * dev, u16 channel) {
+ return;
+ }
+
+-static inline void WAIT_FLUSH_RX_COMPLETE (hrz_dev * dev) {
++static void WAIT_FLUSH_RX_COMPLETE (hrz_dev * dev) {
+ while (rd_regw (dev, RX_CHANNEL_PORT_OFF) & FLUSH_CHANNEL)
+ ;
+ return;
+@@ -435,7 +435,7 @@ static inline void SELECT_RX_CHANNEL (hrz_dev * dev, u16 channel) {
+ return;
+ }
+
+-static inline void WAIT_UPDATE_COMPLETE (hrz_dev * dev) {
++static void WAIT_UPDATE_COMPLETE (hrz_dev * dev) {
+ while (rd_regw (dev, RX_CHANNEL_PORT_OFF) & RX_CHANNEL_UPDATE_IN_PROGRESS)
+ ;
+ return;
+@@ -796,7 +796,7 @@ static void hrz_change_vc_qos (ATM_RXER * rxer, MAAL_QOS * qos) {
+
+ /********** free an skb (as per ATM device driver documentation) **********/
+
+-static inline void hrz_kfree_skb (struct sk_buff * skb) {
++static void hrz_kfree_skb (struct sk_buff * skb) {
+ if (ATM_SKB(skb)->vcc->pop) {
+ ATM_SKB(skb)->vcc->pop (ATM_SKB(skb)->vcc, skb);
+ } else {
+@@ -1076,7 +1076,7 @@ static void rx_schedule (hrz_dev * dev, int irq) {
+
+ /********** handle RX bus master complete events **********/
+
+-static inline void rx_bus_master_complete_handler (hrz_dev * dev) {
++static void rx_bus_master_complete_handler (hrz_dev * dev) {
+ if (test_bit (rx_busy, &dev->flags)) {
+ rx_schedule (dev, 1);
+ } else {
+@@ -1089,7 +1089,7 @@ static inline void rx_bus_master_complete_handler (hrz_dev * dev) {
+
+ /********** (queue to) become the next TX thread **********/
+
+-static inline int tx_hold (hrz_dev * dev) {
++static int tx_hold (hrz_dev * dev) {
+ PRINTD (DBG_TX, "sleeping at tx lock %p %lu", dev, dev->flags);
+ wait_event_interruptible(dev->tx_queue, (!test_and_set_bit(tx_busy, &dev->flags)));
+ PRINTD (DBG_TX, "woken at tx lock %p %lu", dev, dev->flags);
+@@ -1232,7 +1232,7 @@ static void tx_schedule (hrz_dev * const dev, int irq) {
+
+ /********** handle TX bus master complete events **********/
+
+-static inline void tx_bus_master_complete_handler (hrz_dev * dev) {
++static void tx_bus_master_complete_handler (hrz_dev * dev) {
+ if (test_bit (tx_busy, &dev->flags)) {
+ tx_schedule (dev, 1);
+ } else {
+@@ -1246,7 +1246,7 @@ static inline void tx_bus_master_complete_handler (hrz_dev * dev) {
+ /********** move RX Q pointer to next item in circular buffer **********/
+
+ // called only from IRQ sub-handler
+-static inline u32 rx_queue_entry_next (hrz_dev * dev) {
++static u32 rx_queue_entry_next (hrz_dev * dev) {
+ u32 rx_queue_entry;
+ spin_lock (&dev->mem_lock);
+ rx_queue_entry = rd_mem (dev, &dev->rx_q_entry->entry);
+@@ -1270,7 +1270,7 @@ static inline void rx_disabled_handler (hrz_dev * dev) {
+ /********** handle RX data received by device **********/
+
+ // called from IRQ handler
+-static inline void rx_data_av_handler (hrz_dev * dev) {
++static void rx_data_av_handler (hrz_dev * dev) {
+ u32 rx_queue_entry;
+ u32 rx_queue_entry_flags;
+ u16 rx_len;
+@@ -1394,7 +1394,7 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id)
+ irq_ok = 0;
+ while ((int_source = rd_regl (dev, INT_SOURCE_REG_OFF)
+ & INTERESTING_INTERRUPTS)) {
+- // In the interests of fairness, the (inline) handlers below are
++ // In the interests of fairness, the handlers below are
+ // called in sequence and without immediate return to the head of
+ // the while loop. This is only of issue for slow hosts (or when
+ // debugging messages are on). Really slow hosts may find a fast
+@@ -1458,7 +1458,7 @@ static void do_housekeeping (unsigned long arg) {
+ /********** find an idle channel for TX and set it up **********/
+
+ // called with tx_busy set
+-static inline short setup_idle_tx_channel (hrz_dev * dev, hrz_vcc * vcc) {
++static short setup_idle_tx_channel (hrz_dev * dev, hrz_vcc * vcc) {
+ unsigned short idle_channels;
+ short tx_channel = -1;
+ unsigned int spin_count;
+@@ -1777,13 +1777,13 @@ static void hrz_reset (const hrz_dev * dev) {
+
+ /********** read the burnt in address **********/
+
+-static inline void WRITE_IT_WAIT (const hrz_dev *dev, u32 ctrl)
++static void WRITE_IT_WAIT (const hrz_dev *dev, u32 ctrl)
+ {
+ wr_regl (dev, CONTROL_0_REG, ctrl);
+ udelay (5);
+ }
+
+-static inline void CLOCK_IT (const hrz_dev *dev, u32 ctrl)
++static void CLOCK_IT (const hrz_dev *dev, u32 ctrl)
+ {
+ // DI must be valid around rising SK edge
+ WRITE_IT_WAIT(dev, ctrl & ~SEEPROM_SK);
+diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
+index 670c093..5c28ca7 100644
+--- a/drivers/atm/iphase.c
++++ b/drivers/atm/iphase.c
+@@ -60,7 +60,8 @@
+ #include <asm/uaccess.h>
+ #include <asm/string.h>
+ #include <asm/byteorder.h>
+-#include <linux/vmalloc.h>
++#include <linux/vmalloc.h>
++#include <linux/jiffies.h>
+ #include "iphase.h"
+ #include "suni.h"
+ #define swap(x) (((x & 0xff) << 8) | ((x & 0xff00) >> 8))
+@@ -189,7 +190,7 @@ static u16 get_desc (IADEV *dev, struct ia_vcc *iavcc) {
+ int ltimeout;
+
+ ia_hack_tcq (dev);
+- if(((jiffies - timer)>50)||((dev->ffL.tcq_rd==dev->host_tcq_wr))){
++ if((time_after(jiffies,timer+50)) || ((dev->ffL.tcq_rd==dev->host_tcq_wr))) {
+ timer = jiffies;
+ i=0;
+ while (i < dev->num_tx_desc) {
+@@ -1225,7 +1226,7 @@ static void rx_intr(struct atm_dev *dev)
+ iadev->rx_tmp_jif = jiffies;
+ iadev->rxing = 0;
+ }
+- else if (((jiffies - iadev->rx_tmp_jif) > 50) &&
++ else if ((time_after(jiffies, iadev->rx_tmp_jif + 50)) &&
+ ((iadev->rx_pkt_cnt - iadev->rx_tmp_cnt) == 0)) {
+ for (i = 1; i <= iadev->num_rx_desc; i++)
+ free_desc(dev, i);
+diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c
+index 0c205b0..38c769f 100644
+--- a/drivers/atm/nicstar.c
++++ b/drivers/atm/nicstar.c
+@@ -125,85 +125,6 @@
+ #define ATM_SKB(s) (&(s)->atm)
+ #endif
+
+- /* Spinlock debugging stuff */
+-#ifdef NS_DEBUG_SPINLOCKS /* See nicstar.h */
+-#define ns_grab_int_lock(card,flags) \
+- do { \
+- unsigned long nsdsf, nsdsf2; \
+- local_irq_save(flags); \
+- save_flags(nsdsf); cli();\
+- if (nsdsf & (1<<9)) printk ("nicstar.c: ints %sabled -> enabled.\n", \
+- (flags)&(1<<9)?"en":"dis"); \
+- if (spin_is_locked(&(card)->int_lock) && \
+- (card)->cpu_int == smp_processor_id()) { \
+- printk("nicstar.c: line %d (cpu %d) int_lock already locked at line %d (cpu %d)\n", \
+- __LINE__, smp_processor_id(), (card)->has_int_lock, \
+- (card)->cpu_int); \
+- printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \
+- } \
+- if (spin_is_locked(&(card)->res_lock) && \
+- (card)->cpu_res == smp_processor_id()) { \
+- printk("nicstar.c: line %d (cpu %d) res_lock locked at line %d (cpu %d)(trying int)\n", \
+- __LINE__, smp_processor_id(), (card)->has_res_lock, \
+- (card)->cpu_res); \
+- printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \
+- } \
+- spin_lock_irq(&(card)->int_lock); \
+- (card)->has_int_lock = __LINE__; \
+- (card)->cpu_int = smp_processor_id(); \
+- restore_flags(nsdsf); } while (0)
+-#define ns_grab_res_lock(card,flags) \
+- do { \
+- unsigned long nsdsf, nsdsf2; \
+- local_irq_save(flags); \
+- save_flags(nsdsf); cli();\
+- if (nsdsf & (1<<9)) printk ("nicstar.c: ints %sabled -> enabled.\n", \
+- (flags)&(1<<9)?"en":"dis"); \
+- if (spin_is_locked(&(card)->res_lock) && \
+- (card)->cpu_res == smp_processor_id()) { \
+- printk("nicstar.c: line %d (cpu %d) res_lock already locked at line %d (cpu %d)\n", \
+- __LINE__, smp_processor_id(), (card)->has_res_lock, \
+- (card)->cpu_res); \
+- printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \
+- } \
+- spin_lock_irq(&(card)->res_lock); \
+- (card)->has_res_lock = __LINE__; \
+- (card)->cpu_res = smp_processor_id(); \
+- restore_flags(nsdsf); } while (0)
+-#define ns_grab_scq_lock(card,scq,flags) \
+- do { \
+- unsigned long nsdsf, nsdsf2; \
+- local_irq_save(flags); \
+- save_flags(nsdsf); cli();\
+- if (nsdsf & (1<<9)) printk ("nicstar.c: ints %sabled -> enabled.\n", \
+- (flags)&(1<<9)?"en":"dis"); \
+- if (spin_is_locked(&(scq)->lock) && \
+- (scq)->cpu_lock == smp_processor_id()) { \
+- printk("nicstar.c: line %d (cpu %d) this scq_lock already locked at line %d (cpu %d)\n", \
+- __LINE__, smp_processor_id(), (scq)->has_lock, \
+- (scq)->cpu_lock); \
+- printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \
+- } \
+- if (spin_is_locked(&(card)->res_lock) && \
+- (card)->cpu_res == smp_processor_id()) { \
+- printk("nicstar.c: line %d (cpu %d) res_lock locked at line %d (cpu %d)(trying scq)\n", \
+- __LINE__, smp_processor_id(), (card)->has_res_lock, \
+- (card)->cpu_res); \
+- printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \
+- } \
+- spin_lock_irq(&(scq)->lock); \
+- (scq)->has_lock = __LINE__; \
+- (scq)->cpu_lock = smp_processor_id(); \
+- restore_flags(nsdsf); } while (0)
+-#else /* !NS_DEBUG_SPINLOCKS */
+-#define ns_grab_int_lock(card,flags) \
+- spin_lock_irqsave(&(card)->int_lock,(flags))
+-#define ns_grab_res_lock(card,flags) \
+- spin_lock_irqsave(&(card)->res_lock,(flags))
+-#define ns_grab_scq_lock(card,scq,flags) \
+- spin_lock_irqsave(&(scq)->lock,flags)
+-#endif /* NS_DEBUG_SPINLOCKS */
+-
+
+ /* Function declarations ******************************************************/
+
+@@ -422,7 +343,7 @@ static u32 ns_read_sram(ns_dev *card, u32 sram_address)
+ sram_address <<= 2;
+ sram_address &= 0x0007FFFC; /* address must be dword aligned */
+ sram_address |= 0x50000000; /* SRAM read command */
+- ns_grab_res_lock(card, flags);
++ spin_lock_irqsave(&card->res_lock, flags);
+ while (CMD_BUSY(card));
+ writel(sram_address, card->membase + CMD);
+ while (CMD_BUSY(card));
+@@ -440,7 +361,7 @@ static void ns_write_sram(ns_dev *card, u32 sram_address, u32 *value, int count)
+ count--; /* count range now is 0..3 instead of 1..4 */
+ c = count;
+ c <<= 2; /* to use increments of 4 */
+- ns_grab_res_lock(card, flags);
++ spin_lock_irqsave(&card->res_lock, flags);
+ while (CMD_BUSY(card));
+ for (i = 0; i <= c; i += 4)
+ writel(*(value++), card->membase + i);
+@@ -1166,7 +1087,7 @@ static void push_rxbufs(ns_dev *card, struct sk_buff *skb)
+ card->lbfqc += 2;
+ }
+
+- ns_grab_res_lock(card, flags);
++ spin_lock_irqsave(&card->res_lock, flags);
+
+ while (CMD_BUSY(card));
+ writel(addr2, card->membase + DR3);
+@@ -1206,7 +1127,7 @@ static irqreturn_t ns_irq_handler(int irq, void *dev_id)
+
+ PRINTK("nicstar%d: NICStAR generated an interrupt\n", card->index);
+
+- ns_grab_int_lock(card, flags);
++ spin_lock_irqsave(&card->int_lock, flags);
+
+ stat_r = readl(card->membase + STAT);
+
+@@ -1585,7 +1506,7 @@ static void ns_close(struct atm_vcc *vcc)
+ unsigned long flags;
+
+ addr = NS_RCT + (vcc->vpi << card->vcibits | vcc->vci) * NS_RCT_ENTRY_SIZE;
+- ns_grab_res_lock(card, flags);
++ spin_lock_irqsave(&card->res_lock, flags);
+ while(CMD_BUSY(card));
+ writel(NS_CMD_CLOSE_CONNECTION | addr << 2, card->membase + CMD);
+ spin_unlock_irqrestore(&card->res_lock, flags);
+@@ -1607,7 +1528,7 @@ static void ns_close(struct atm_vcc *vcc)
+ NS_SKB(iovb)->iovcnt);
+ NS_SKB(iovb)->iovcnt = 0;
+ NS_SKB(iovb)->vcc = NULL;
+- ns_grab_int_lock(card, flags);
++ spin_lock_irqsave(&card->int_lock, flags);
+ recycle_iov_buf(card, iovb);
+ spin_unlock_irqrestore(&card->int_lock, flags);
+ vc->rx_iov = NULL;
+@@ -1629,7 +1550,7 @@ static void ns_close(struct atm_vcc *vcc)
+
+ for (;;)
+ {
+- ns_grab_scq_lock(card, scq, flags);
++ spin_lock_irqsave(&scq->lock, flags);
+ scqep = scq->next;
+ if (scqep == scq->base)
+ scqep = scq->last;
+@@ -1691,7 +1612,7 @@ static void ns_close(struct atm_vcc *vcc)
+ unsigned long flags;
+ scq_info *scq = card->scq0;
+
+- ns_grab_scq_lock(card, scq, flags);
++ spin_lock_irqsave(&scq->lock, flags);
+
+ for(i = 0; i < scq->num_entries; i++) {
+ if(scq->skb[i] && ATM_SKB(scq->skb[i])->vcc == vcc) {
+@@ -1892,7 +1813,7 @@ static int push_scqe(ns_dev *card, vc_map *vc, scq_info *scq, ns_scqe *tbd,
+ u32 data;
+ int index;
+
+- ns_grab_scq_lock(card, scq, flags);
++ spin_lock_irqsave(&scq->lock, flags);
+ while (scq->tail == scq->next)
+ {
+ if (in_interrupt()) {
+@@ -1904,7 +1825,7 @@ static int push_scqe(ns_dev *card, vc_map *vc, scq_info *scq, ns_scqe *tbd,
+ scq->full = 1;
+ spin_unlock_irqrestore(&scq->lock, flags);
+ interruptible_sleep_on_timeout(&scq->scqfull_waitq, SCQFULL_TIMEOUT);
+- ns_grab_scq_lock(card, scq, flags);
++ spin_lock_irqsave(&scq->lock, flags);
+
+ if (scq->full) {
+ spin_unlock_irqrestore(&scq->lock, flags);
+@@ -1953,7 +1874,7 @@ static int push_scqe(ns_dev *card, vc_map *vc, scq_info *scq, ns_scqe *tbd,
+ if (has_run++) break;
+ spin_unlock_irqrestore(&scq->lock, flags);
+ interruptible_sleep_on_timeout(&scq->scqfull_waitq, SCQFULL_TIMEOUT);
+- ns_grab_scq_lock(card, scq, flags);
++ spin_lock_irqsave(&scq->lock, flags);
+ }
+
+ if (!scq->full)
+@@ -2090,7 +2011,7 @@ static void drain_scq(ns_dev *card, scq_info *scq, int pos)
+ return;
+ }
+
+- ns_grab_scq_lock(card, scq, flags);
++ spin_lock_irqsave(&scq->lock, flags);
+ i = (int) (scq->tail - scq->base);
+ if (++i == scq->num_entries)
+ i = 0;
+@@ -2898,7 +2819,7 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
+ {
+ struct sk_buff *hb;
+
+- ns_grab_int_lock(card, flags);
++ spin_lock_irqsave(&card->int_lock, flags);
+ hb = skb_dequeue(&card->hbpool.queue);
+ card->hbpool.count--;
+ spin_unlock_irqrestore(&card->int_lock, flags);
+@@ -2917,7 +2838,7 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
+ if (hb == NULL)
+ return -ENOMEM;
+ NS_SKB_CB(hb)->buf_type = BUF_NONE;
+- ns_grab_int_lock(card, flags);
++ spin_lock_irqsave(&card->int_lock, flags);
+ skb_queue_tail(&card->hbpool.queue, hb);
+ card->hbpool.count++;
+ spin_unlock_irqrestore(&card->int_lock, flags);
+@@ -2929,7 +2850,7 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
+ {
+ struct sk_buff *iovb;
+
+- ns_grab_int_lock(card, flags);
++ spin_lock_irqsave(&card->int_lock, flags);
+ iovb = skb_dequeue(&card->iovpool.queue);
+ card->iovpool.count--;
+ spin_unlock_irqrestore(&card->int_lock, flags);
+@@ -2948,7 +2869,7 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
+ if (iovb == NULL)
+ return -ENOMEM;
+ NS_SKB_CB(iovb)->buf_type = BUF_NONE;
+- ns_grab_int_lock(card, flags);
++ spin_lock_irqsave(&card->int_lock, flags);
+ skb_queue_tail(&card->iovpool.queue, iovb);
+ card->iovpool.count++;
+ spin_unlock_irqrestore(&card->int_lock, flags);
+@@ -2995,7 +2916,7 @@ static void ns_poll(unsigned long arg)
+ /* Probably it isn't worth spinning */
+ continue;
+ }
+- ns_grab_int_lock(card, flags);
++ spin_lock_irqsave(&card->int_lock, flags);
+
+ stat_w = 0;
+ stat_r = readl(card->membase + STAT);
+@@ -3062,7 +2983,7 @@ static void ns_phy_put(struct atm_dev *dev, unsigned char value,
+ unsigned long flags;
+
+ card = dev->dev_data;
+- ns_grab_res_lock(card, flags);
++ spin_lock_irqsave(&card->res_lock, flags);
+ while(CMD_BUSY(card));
+ writel((unsigned long) value, card->membase + DR0);
+ writel(NS_CMD_WRITE_UTILITY | 0x00000200 | (addr & 0x000000FF),
+@@ -3079,7 +3000,7 @@ static unsigned char ns_phy_get(struct atm_dev *dev, unsigned long addr)
+ unsigned long data;
+
+ card = dev->dev_data;
+- ns_grab_res_lock(card, flags);
++ spin_lock_irqsave(&card->res_lock, flags);
+ while(CMD_BUSY(card));
+ writel(NS_CMD_READ_UTILITY | 0x00000200 | (addr & 0x000000FF),
+ card->membase + CMD);
+diff --git a/drivers/atm/nicstar.h b/drivers/atm/nicstar.h
+index 5997bcb..6010e3d 100644
+--- a/drivers/atm/nicstar.h
++++ b/drivers/atm/nicstar.h
+@@ -28,8 +28,6 @@
+
+ /* Options ********************************************************************/
+
+-#undef NS_DEBUG_SPINLOCKS
+-
+ #define NS_MAX_CARDS 4 /* Maximum number of NICStAR based cards
+ controlled by the device driver. Must
+ be <= 5 */
+@@ -721,10 +719,6 @@ typedef struct scq_info
+ wait_queue_head_t scqfull_waitq;
+ volatile char full; /* SCQ full indicator */
+ spinlock_t lock; /* SCQ spinlock */
+-#ifdef NS_DEBUG_SPINLOCKS
+- volatile long has_lock;
+- volatile int cpu_lock;
+-#endif /* NS_DEBUG_SPINLOCKS */
+ } scq_info;
+
+
+@@ -810,12 +804,6 @@ typedef struct ns_dev
+ unsigned intcnt; /* Interrupt counter */
+ spinlock_t int_lock; /* Interrupt lock */
+ spinlock_t res_lock; /* Card resource lock */
+-#ifdef NS_DEBUG_SPINLOCKS
+- volatile long has_int_lock;
+- volatile int cpu_int;
+- volatile long has_res_lock;
+- volatile int cpu_res;
+-#endif /* NS_DEBUG_SPINLOCKS */
+ } ns_dev;
+
+
+diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
+index 3b43e8a..f57652d 100644
+--- a/drivers/base/attribute_container.c
++++ b/drivers/base/attribute_container.c
+@@ -27,21 +27,21 @@
+ struct internal_container {
+ struct klist_node node;
+ struct attribute_container *cont;
+- struct class_device classdev;
++ struct device classdev;
+ };
+
+ static void internal_container_klist_get(struct klist_node *n)
+ {
+ struct internal_container *ic =
+ container_of(n, struct internal_container, node);
+- class_device_get(&ic->classdev);
++ get_device(&ic->classdev);
+ }
+
+ static void internal_container_klist_put(struct klist_node *n)
+ {
+ struct internal_container *ic =
+ container_of(n, struct internal_container, node);
+- class_device_put(&ic->classdev);
++ put_device(&ic->classdev);
+ }
+
+
+@@ -53,7 +53,7 @@ static void internal_container_klist_put(struct klist_node *n)
+ * Returns the container associated with this classdev.
+ */
+ struct attribute_container *
+-attribute_container_classdev_to_container(struct class_device *classdev)
++attribute_container_classdev_to_container(struct device *classdev)
+ {
+ struct internal_container *ic =
+ container_of(classdev, struct internal_container, classdev);
+@@ -110,11 +110,11 @@ attribute_container_unregister(struct attribute_container *cont)
+ EXPORT_SYMBOL_GPL(attribute_container_unregister);
+
+ /* private function used as class release */
+-static void attribute_container_release(struct class_device *classdev)
++static void attribute_container_release(struct device *classdev)
+ {
+ struct internal_container *ic
+ = container_of(classdev, struct internal_container, classdev);
+- struct device *dev = classdev->dev;
++ struct device *dev = classdev->parent;
+
+ kfree(ic);
+ put_device(dev);
+@@ -129,12 +129,12 @@ static void attribute_container_release(struct class_device *classdev)
+ * This function allocates storage for the class device(s) to be
+ * attached to dev (one for each matching attribute_container). If no
+ * fn is provided, the code will simply register the class device via
+- * class_device_add. If a function is provided, it is expected to add
++ * device_add. If a function is provided, it is expected to add
+ * the class device at the appropriate time. One of the things that
+ * might be necessary is to allocate and initialise the classdev and
+ * then add it a later time. To do this, call this routine for
+ * allocation and initialisation and then use
+- * attribute_container_device_trigger() to call class_device_add() on
++ * attribute_container_device_trigger() to call device_add() on
+ * it. Note: after this, the class device contains a reference to dev
+ * which is not relinquished until the release of the classdev.
+ */
+@@ -142,7 +142,7 @@ void
+ attribute_container_add_device(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *,
+- struct class_device *))
++ struct device *))
+ {
+ struct attribute_container *cont;
+
+@@ -163,11 +163,11 @@ attribute_container_add_device(struct device *dev,
+ }
+
+ ic->cont = cont;
+- class_device_initialize(&ic->classdev);
+- ic->classdev.dev = get_device(dev);
++ device_initialize(&ic->classdev);
++ ic->classdev.parent = get_device(dev);
+ ic->classdev.class = cont->class;
+- cont->class->release = attribute_container_release;
+- strcpy(ic->classdev.class_id, dev->bus_id);
++ cont->class->dev_release = attribute_container_release;
++ strcpy(ic->classdev.bus_id, dev->bus_id);
+ if (fn)
+ fn(cont, dev, &ic->classdev);
+ else
+@@ -195,20 +195,19 @@ attribute_container_add_device(struct device *dev,
+ * @fn: A function to call to remove the device
+ *
+ * This routine triggers device removal. If fn is NULL, then it is
+- * simply done via class_device_unregister (note that if something
++ * simply done via device_unregister (note that if something
+ * still has a reference to the classdev, then the memory occupied
+ * will not be freed until the classdev is released). If you want a
+ * two phase release: remove from visibility and then delete the
+ * device, then you should use this routine with a fn that calls
+- * class_device_del() and then use
+- * attribute_container_device_trigger() to do the final put on the
+- * classdev.
++ * device_del() and then use attribute_container_device_trigger()
++ * to do the final put on the classdev.
+ */
+ void
+ attribute_container_remove_device(struct device *dev,
+ void (*fn)(struct attribute_container *,
+ struct device *,
+- struct class_device *))
++ struct device *))
+ {
+ struct attribute_container *cont;
+
+@@ -224,14 +223,14 @@ attribute_container_remove_device(struct device *dev,
+ continue;
+
+ klist_for_each_entry(ic, &cont->containers, node, &iter) {
+- if (dev != ic->classdev.dev)
++ if (dev != ic->classdev.parent)
+ continue;
+ klist_del(&ic->node);
+ if (fn)
+ fn(cont, dev, &ic->classdev);
+ else {
+ attribute_container_remove_attrs(&ic->classdev);
+- class_device_unregister(&ic->classdev);
++ device_unregister(&ic->classdev);
+ }
+ }
+ }
+@@ -252,7 +251,7 @@ void
+ attribute_container_device_trigger(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *,
+- struct class_device *))
++ struct device *))
+ {
+ struct attribute_container *cont;
+
+@@ -270,7 +269,7 @@ attribute_container_device_trigger(struct device *dev,
+ }
+
+ klist_for_each_entry(ic, &cont->containers, node, &iter) {
+- if (dev == ic->classdev.dev)
++ if (dev == ic->classdev.parent)
+ fn(cont, dev, &ic->classdev);
+ }
+ }
+@@ -313,11 +312,11 @@ attribute_container_trigger(struct device *dev,
+ * attributes listed in the container
+ */
+ int
+-attribute_container_add_attrs(struct class_device *classdev)
++attribute_container_add_attrs(struct device *classdev)
+ {
+ struct attribute_container *cont =
+ attribute_container_classdev_to_container(classdev);
+- struct class_device_attribute **attrs = cont->attrs;
++ struct device_attribute **attrs = cont->attrs;
+ int i, error;
+
+ BUG_ON(attrs && cont->grp);
+@@ -329,7 +328,7 @@ attribute_container_add_attrs(struct class_device *classdev)
+ return sysfs_create_group(&classdev->kobj, cont->grp);
+
+ for (i = 0; attrs[i]; i++) {
+- error = class_device_create_file(classdev, attrs[i]);
++ error = device_create_file(classdev, attrs[i]);
+ if (error)
+ return error;
+ }
+@@ -338,18 +337,18 @@ attribute_container_add_attrs(struct class_device *classdev)
+ }
+
+ /**
+- * attribute_container_add_class_device - same function as class_device_add
++ * attribute_container_add_class_device - same function as device_add
+ *
+ * @classdev: the class device to add
+ *
+- * This performs essentially the same function as class_device_add except for
++ * This performs essentially the same function as device_add except for
+ * attribute containers, namely add the classdev to the system and then
+ * create the attribute files
+ */
+ int
+-attribute_container_add_class_device(struct class_device *classdev)
++attribute_container_add_class_device(struct device *classdev)
+ {
+- int error = class_device_add(classdev);
++ int error = device_add(classdev);
+ if (error)
+ return error;
+ return attribute_container_add_attrs(classdev);
+@@ -364,7 +363,7 @@ attribute_container_add_class_device(struct class_device *classdev)
+ int
+ attribute_container_add_class_device_adapter(struct attribute_container *cont,
+ struct device *dev,
+- struct class_device *classdev)
++ struct device *classdev)
+ {
+ return attribute_container_add_class_device(classdev);
+ }
+@@ -376,11 +375,11 @@ attribute_container_add_class_device_adapter(struct attribute_container *cont,
+ *
+ */
+ void
+-attribute_container_remove_attrs(struct class_device *classdev)
++attribute_container_remove_attrs(struct device *classdev)
+ {
+ struct attribute_container *cont =
+ attribute_container_classdev_to_container(classdev);
+- struct class_device_attribute **attrs = cont->attrs;
++ struct device_attribute **attrs = cont->attrs;
+ int i;
+
+ if (!attrs && !cont->grp)
+@@ -392,7 +391,7 @@ attribute_container_remove_attrs(struct class_device *classdev)
+ }
+
+ for (i = 0; attrs[i]; i++)
+- class_device_remove_file(classdev, attrs[i]);
++ device_remove_file(classdev, attrs[i]);
+ }
+
+ /**
+@@ -401,13 +400,13 @@ attribute_container_remove_attrs(struct class_device *classdev)
+ * @classdev: the class device
+ *
+ * This function simply removes all the attribute files and then calls
+- * class_device_del.
++ * device_del.
+ */
+ void
+-attribute_container_class_device_del(struct class_device *classdev)
++attribute_container_class_device_del(struct device *classdev)
+ {
+ attribute_container_remove_attrs(classdev);
+- class_device_del(classdev);
++ device_del(classdev);
+ }
+
+ /**
+@@ -419,16 +418,16 @@ attribute_container_class_device_del(struct class_device *classdev)
+ * Looks up the device in the container's list of class devices and returns
+ * the corresponding class_device.
+ */
+-struct class_device *
++struct device *
+ attribute_container_find_class_device(struct attribute_container *cont,
+ struct device *dev)
+ {
+- struct class_device *cdev = NULL;
++ struct device *cdev = NULL;
+ struct internal_container *ic;
+ struct klist_iter iter;
+
+ klist_for_each_entry(ic, &cont->containers, node, &iter) {
+- if (ic->classdev.dev == dev) {
++ if (ic->classdev.parent == dev) {
+ cdev = &ic->classdev;
+ /* FIXME: must exit iterator then break */
+ klist_iter_exit(&iter);
+diff --git a/drivers/base/bus.c b/drivers/base/bus.c
+index 2d207ad..ef522ae 100644
+--- a/drivers/base/bus.c
++++ b/drivers/base/bus.c
+@@ -79,7 +79,7 @@ static void driver_release(struct kobject *kobj)
+ {
+ struct driver_private *drv_priv = to_driver(kobj);
+
+- pr_debug("driver: '%s': %s\n", kobject_name(kobj), __FUNCTION__);
++ pr_debug("driver: '%s': %s\n", kobject_name(kobj), __func__);
+ kfree(drv_priv);
+ }
+
+@@ -505,14 +505,11 @@ void bus_attach_device(struct device *dev)
+ int ret = 0;
+
+ if (bus) {
+- dev->is_registered = 1;
+ if (bus->p->drivers_autoprobe)
+ ret = device_attach(dev);
+ WARN_ON(ret < 0);
+ if (ret >= 0)
+ klist_add_tail(&dev->knode_bus, &bus->p->klist_devices);
+- else
+- dev->is_registered = 0;
+ }
+ }
+
+@@ -533,10 +530,9 @@ void bus_remove_device(struct device *dev)
+ sysfs_remove_link(&dev->bus->p->devices_kset->kobj,
+ dev->bus_id);
+ device_remove_attrs(dev->bus, dev);
+- if (dev->is_registered) {
+- dev->is_registered = 0;
++ if (klist_node_attached(&dev->knode_bus))
+ klist_del(&dev->knode_bus);
+- }
++
+ pr_debug("bus: '%s': remove device %s\n",
+ dev->bus->name, dev->bus_id);
+ device_release_driver(dev);
+@@ -682,19 +678,19 @@ int bus_add_driver(struct device_driver *drv)
+ error = driver_create_file(drv, &driver_attr_uevent);
+ if (error) {
+ printk(KERN_ERR "%s: uevent attr (%s) failed\n",
+- __FUNCTION__, drv->name);
++ __func__, drv->name);
+ }
+ error = driver_add_attrs(bus, drv);
+ if (error) {
+ /* How the hell do we get out of this pickle? Give up */
+ printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
+- __FUNCTION__, drv->name);
++ __func__, drv->name);
+ }
+ error = add_bind_files(drv);
+ if (error) {
+ /* Ditto */
+ printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
+- __FUNCTION__, drv->name);
++ __func__, drv->name);
+ }
+
+ kobject_uevent(&priv->kobj, KOBJ_ADD);
+diff --git a/drivers/base/class.c b/drivers/base/class.c
+index 9d91537..b490179 100644
+--- a/drivers/base/class.c
++++ b/drivers/base/class.c
+@@ -175,13 +175,13 @@ void class_unregister(struct class *cls)
+
+ static void class_create_release(struct class *cls)
+ {
+- pr_debug("%s called for %s\n", __FUNCTION__, cls->name);
++ pr_debug("%s called for %s\n", __func__, cls->name);
+ kfree(cls);
+ }
+
+ static void class_device_create_release(struct class_device *class_dev)
+ {
+- pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
++ pr_debug("%s called for %s\n", __func__, class_dev->class_id);
+ kfree(class_dev);
+ }
+
+@@ -189,7 +189,7 @@ static void class_device_create_release(struct class_device *class_dev)
+ static int class_device_create_uevent(struct class_device *class_dev,
+ struct kobj_uevent_env *env)
+ {
+- pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
++ pr_debug("%s called for %s\n", __func__, class_dev->class_id);
+ return 0;
+ }
+
+@@ -415,7 +415,7 @@ static int class_uevent(struct kset *kset, struct kobject *kobj,
+ struct device *dev = class_dev->dev;
+ int retval = 0;
+
+- pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);
++ pr_debug("%s - name = %s\n", __func__, class_dev->class_id);
+
+ if (MAJOR(class_dev->devt)) {
+ add_uevent_var(env, "MAJOR=%u", MAJOR(class_dev->devt));
+diff --git a/drivers/base/core.c b/drivers/base/core.c
+index 24198ad..9248e09 100644
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -20,7 +20,7 @@
+ #include <linux/notifier.h>
+ #include <linux/genhd.h>
+ #include <linux/kallsyms.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+
+ #include "base.h"
+ #include "power/power.h"
+@@ -207,7 +207,7 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
+ retval = dev->bus->uevent(dev, env);
+ if (retval)
+ pr_debug("device: '%s': %s: bus uevent() returned %d\n",
+- dev->bus_id, __FUNCTION__, retval);
++ dev->bus_id, __func__, retval);
+ }
+
+ /* have the class specific function add its stuff */
+@@ -216,7 +216,7 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
+ if (retval)
+ pr_debug("device: '%s': %s: class uevent() "
+ "returned %d\n", dev->bus_id,
+- __FUNCTION__, retval);
++ __func__, retval);
+ }
+
+ /* have the device type specific fuction add its stuff */
+@@ -225,7 +225,7 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
+ if (retval)
+ pr_debug("device: '%s': %s: dev_type uevent() "
+ "returned %d\n", dev->bus_id,
+- __FUNCTION__, retval);
++ __func__, retval);
+ }
+
+ return retval;
+@@ -782,7 +782,7 @@ int device_add(struct device *dev)
+ goto Done;
+ }
+
+- pr_debug("device: '%s': %s\n", dev->bus_id, __FUNCTION__);
++ pr_debug("device: '%s': %s\n", dev->bus_id, __func__);
+
+ parent = get_device(dev->parent);
+ setup_parent(dev, parent);
+@@ -817,13 +817,12 @@ int device_add(struct device *dev)
+ error = device_add_attrs(dev);
+ if (error)
+ goto AttrsError;
+- error = dpm_sysfs_add(dev);
+- if (error)
+- goto PMError;
+- device_pm_add(dev);
+ error = bus_add_device(dev);
+ if (error)
+ goto BusError;
++ error = device_pm_add(dev);
++ if (error)
++ goto PMError;
+ kobject_uevent(&dev->kobj, KOBJ_ADD);
+ bus_attach_device(dev);
+ if (parent)
+@@ -843,9 +842,9 @@ int device_add(struct device *dev)
+ Done:
+ put_device(dev);
+ return error;
+- BusError:
+- device_pm_remove(dev);
+ PMError:
++ bus_remove_device(dev);
++ BusError:
+ if (dev->bus)
+ blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+ BUS_NOTIFY_DEL_DEVICE, dev);
+@@ -981,7 +980,7 @@ void device_del(struct device *dev)
+ */
+ void device_unregister(struct device *dev)
+ {
+- pr_debug("device: '%s': %s\n", dev->bus_id, __FUNCTION__);
++ pr_debug("device: '%s': %s\n", dev->bus_id, __func__);
+ device_del(dev);
+ put_device(dev);
+ }
+@@ -1076,7 +1075,7 @@ EXPORT_SYMBOL_GPL(device_remove_file);
+
+ static void device_create_release(struct device *dev)
+ {
+- pr_debug("device: '%s': %s\n", dev->bus_id, __FUNCTION__);
++ pr_debug("device: '%s': %s\n", dev->bus_id, __func__);
+ kfree(dev);
+ }
+
+@@ -1164,35 +1163,6 @@ void device_destroy(struct class *class, dev_t devt)
+ }
+ EXPORT_SYMBOL_GPL(device_destroy);
+
+-#ifdef CONFIG_PM_SLEEP
+-/**
+- * destroy_suspended_device - asks the PM core to remove a suspended device
+- * @class: pointer to the struct class that this device was registered with
+- * @devt: the dev_t of the device that was previously registered
+- *
+- * This call notifies the PM core of the necessity to unregister a suspended
+- * device created with a call to device_create() (devices cannot be
+- * unregistered directly while suspended, since the PM core holds their
+- * semaphores at that time).
+- *
+- * It can only be called within the scope of a system sleep transition. In
+- * practice this means it has to be directly or indirectly invoked either by
+- * a suspend or resume method, or by the PM core (e.g. via
+- * disable_nonboot_cpus() or enable_nonboot_cpus()).
+- */
+-void destroy_suspended_device(struct class *class, dev_t devt)
+-{
+- struct device *dev;
+-
+- dev = class_find_device(class, &devt, __match_devt);
+- if (dev) {
+- device_pm_schedule_removal(dev);
+- put_device(dev);
+- }
+-}
+-EXPORT_SYMBOL_GPL(destroy_suspended_device);
+-#endif /* CONFIG_PM_SLEEP */
+-
+ /**
+ * device_rename - renames a device
+ * @dev: the pointer to the struct device to be renamed
+@@ -1210,7 +1180,7 @@ int device_rename(struct device *dev, char *new_name)
+ return -EINVAL;
+
+ pr_debug("device: '%s': %s: renaming to '%s'\n", dev->bus_id,
+- __FUNCTION__, new_name);
++ __func__, new_name);
+
+ #ifdef CONFIG_SYSFS_DEPRECATED
+ if ((dev->class) && (dev->parent))
+@@ -1249,7 +1219,7 @@ int device_rename(struct device *dev, char *new_name)
+ dev->bus_id);
+ if (error) {
+ dev_err(dev, "%s: sysfs_create_symlink failed (%d)\n",
+- __FUNCTION__, error);
++ __func__, error);
+ }
+ }
+ #endif
+@@ -1325,7 +1295,7 @@ int device_move(struct device *dev, struct device *new_parent)
+ new_parent_kobj = get_device_parent(dev, new_parent);
+
+ pr_debug("device: '%s': %s: moving to '%s'\n", dev->bus_id,
+- __FUNCTION__, new_parent ? new_parent->bus_id : "<NULL>");
++ __func__, new_parent ? new_parent->bus_id : "<NULL>");
+ error = kobject_move(&dev->kobj, new_parent_kobj);
+ if (error) {
+ cleanup_glue_dir(dev, new_parent_kobj);
+diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
+index 499b003..6fe4174 100644
+--- a/drivers/base/cpu.c
++++ b/drivers/base/cpu.c
+@@ -28,7 +28,7 @@ static ssize_t show_online(struct sys_device *dev, char *buf)
+ return sprintf(buf, "%u\n", !!cpu_online(cpu->sysdev.id));
+ }
+
+-static ssize_t store_online(struct sys_device *dev, const char *buf,
++static ssize_t __ref store_online(struct sys_device *dev, const char *buf,
+ size_t count)
+ {
+ struct cpu *cpu = container_of(dev, struct cpu, sysdev);
+@@ -55,7 +55,7 @@ static ssize_t store_online(struct sys_device *dev, const char *buf,
+ }
+ static SYSDEV_ATTR(online, 0644, show_online, store_online);
+
+-static void __devinit register_cpu_control(struct cpu *cpu)
++static void __cpuinit register_cpu_control(struct cpu *cpu)
+ {
+ sysdev_create_file(&cpu->sysdev, &attr_online);
+ }
+@@ -103,6 +103,51 @@ static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL);
+ #endif
+
+ /*
++ * Print cpu online, possible, present, and system maps
++ */
++static ssize_t print_cpus_map(char *buf, cpumask_t *map)
++{
++ int n = cpulist_scnprintf(buf, PAGE_SIZE-2, *map);
++
++ buf[n++] = '\n';
++ buf[n] = '\0';
++ return n;
++}
++
++#define print_cpus_func(type) \
++static ssize_t print_cpus_##type(struct sysdev_class *class, char *buf) \
++{ \
++ return print_cpus_map(buf, &cpu_##type##_map); \
++} \
++struct sysdev_class_attribute attr_##type##_map = \
++ _SYSDEV_CLASS_ATTR(type, 0444, print_cpus_##type, NULL)
++
++print_cpus_func(online);
++print_cpus_func(possible);
++print_cpus_func(present);
++
++struct sysdev_class_attribute *cpu_state_attr[] = {
++ &attr_online_map,
++ &attr_possible_map,
++ &attr_present_map,
++};
++
++static int cpu_states_init(void)
++{
++ int i;
++ int err = 0;
++
++ for (i = 0; i < ARRAY_SIZE(cpu_state_attr); i++) {
++ int ret;
++ ret = sysdev_class_create_file(&cpu_sysdev_class,
++ cpu_state_attr[i]);
++ if (!err)
++ err = ret;
++ }
++ return err;
++}
++
++/*
+ * register_cpu - Setup a sysfs device for a CPU.
+ * @cpu - cpu->hotpluggable field set to 1 will generate a control file in
+ * sysfs for this CPU.
+@@ -147,6 +192,9 @@ int __init cpu_dev_init(void)
+ int err;
+
+ err = sysdev_class_register(&cpu_sysdev_class);
++ if (!err)
++ err = cpu_states_init();
++
+ #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
+ if (!err)
+ err = sched_create_sysfs_power_savings_entries(&cpu_sysdev_class);
+diff --git a/drivers/base/dd.c b/drivers/base/dd.c
+index a5cde94..3ac443b 100644
+--- a/drivers/base/dd.c
++++ b/drivers/base/dd.c
+@@ -30,12 +30,12 @@ static void driver_bound(struct device *dev)
+ {
+ if (klist_node_attached(&dev->knode_driver)) {
+ printk(KERN_WARNING "%s: device %s already bound\n",
+- __FUNCTION__, kobject_name(&dev->kobj));
++ __func__, kobject_name(&dev->kobj));
+ return;
+ }
+
+ pr_debug("driver: '%s': %s: bound to device '%s'\n", dev->bus_id,
+- __FUNCTION__, dev->driver->name);
++ __func__, dev->driver->name);
+
+ if (dev->bus)
+ blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+@@ -104,13 +104,13 @@ static int really_probe(struct device *dev, struct device_driver *drv)
+
+ atomic_inc(&probe_count);
+ pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
+- drv->bus->name, __FUNCTION__, drv->name, dev->bus_id);
++ drv->bus->name, __func__, drv->name, dev->bus_id);
+ WARN_ON(!list_empty(&dev->devres_head));
+
+ dev->driver = drv;
+ if (driver_sysfs_add(dev)) {
+ printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
+- __FUNCTION__, dev->bus_id);
++ __func__, dev->bus_id);
+ goto probe_failed;
+ }
+
+@@ -127,7 +127,7 @@ static int really_probe(struct device *dev, struct device_driver *drv)
+ driver_bound(dev);
+ ret = 1;
+ pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
+- drv->bus->name, __FUNCTION__, dev->bus_id, drv->name);
++ drv->bus->name, __func__, dev->bus_id, drv->name);
+ goto done;
+
+ probe_failed:
+@@ -160,7 +160,7 @@ done:
+ */
+ int driver_probe_done(void)
+ {
+- pr_debug("%s: probe_count = %d\n", __FUNCTION__,
++ pr_debug("%s: probe_count = %d\n", __func__,
+ atomic_read(&probe_count));
+ if (atomic_read(&probe_count))
+ return -EBUSY;
+@@ -194,7 +194,7 @@ int driver_probe_device(struct device_driver *drv, struct device *dev)
+ goto done;
+
+ pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
+- drv->bus->name, __FUNCTION__, dev->bus_id, drv->name);
++ drv->bus->name, __func__, dev->bus_id, drv->name);
+
+ ret = really_probe(dev, drv);
+
+diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
+index 4a1b9bf..1fef7df 100644
+--- a/drivers/base/firmware_class.c
++++ b/drivers/base/firmware_class.c
+@@ -156,7 +156,7 @@ static ssize_t firmware_loading_store(struct device *dev,
+ }
+ /* fallthrough */
+ default:
+- printk(KERN_ERR "%s: unexpected value (%d)\n", __FUNCTION__,
++ printk(KERN_ERR "%s: unexpected value (%d)\n", __func__,
+ loading);
+ /* fallthrough */
+ case -1:
+@@ -209,7 +209,7 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
+ new_size = ALIGN(min_size, PAGE_SIZE);
+ new_data = vmalloc(new_size);
+ if (!new_data) {
+- printk(KERN_ERR "%s: unable to alloc buffer\n", __FUNCTION__);
++ printk(KERN_ERR "%s: unable to alloc buffer\n", __func__);
+ /* Make sure that we don't keep incomplete data */
+ fw_load_abort(fw_priv);
+ return -ENOMEM;
+@@ -307,7 +307,7 @@ static int fw_register_device(struct device **dev_p, const char *fw_name,
+ *dev_p = NULL;
+
+ if (!fw_priv || !f_dev) {
+- printk(KERN_ERR "%s: kmalloc failed\n", __FUNCTION__);
++ printk(KERN_ERR "%s: kmalloc failed\n", __func__);
+ retval = -ENOMEM;
+ goto error_kfree;
+ }
+@@ -328,7 +328,7 @@ static int fw_register_device(struct device **dev_p, const char *fw_name,
+ retval = device_register(f_dev);
+ if (retval) {
+ printk(KERN_ERR "%s: device_register failed\n",
+- __FUNCTION__);
++ __func__);
+ goto error_kfree;
+ }
+ *dev_p = f_dev;
+@@ -362,14 +362,14 @@ static int fw_setup_device(struct firmware *fw, struct device **dev_p,
+ retval = sysfs_create_bin_file(&f_dev->kobj, &fw_priv->attr_data);
+ if (retval) {
+ printk(KERN_ERR "%s: sysfs_create_bin_file failed\n",
+- __FUNCTION__);
++ __func__);
+ goto error_unreg;
+ }
+
+ retval = device_create_file(f_dev, &dev_attr_loading);
+ if (retval) {
+ printk(KERN_ERR "%s: device_create_file failed\n",
+- __FUNCTION__);
++ __func__);
+ goto error_unreg;
+ }
+
+@@ -399,7 +399,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
+ *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
+ if (!firmware) {
+ printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n",
+- __FUNCTION__);
++ __func__);
+ retval = -ENOMEM;
+ goto out;
+ }
+@@ -570,13 +570,13 @@ firmware_class_init(void)
+ int error;
+ error = class_register(&firmware_class);
+ if (error) {
+- printk(KERN_ERR "%s: class_register failed\n", __FUNCTION__);
++ printk(KERN_ERR "%s: class_register failed\n", __func__);
+ return error;
+ }
+ error = class_create_file(&firmware_class, &class_attr_timeout);
+ if (error) {
+ printk(KERN_ERR "%s: class_create_file failed\n",
+- __FUNCTION__);
++ __func__);
+ class_unregister(&firmware_class);
+ }
+ return error;
+diff --git a/drivers/base/memory.c b/drivers/base/memory.c
+index 7ae413f..8ce6de5 100644
+--- a/drivers/base/memory.c
++++ b/drivers/base/memory.c
+@@ -20,6 +20,7 @@
+ #include <linux/kobject.h>
+ #include <linux/memory_hotplug.h>
+ #include <linux/mm.h>
++#include <linux/mutex.h>
+ #include <asm/atomic.h>
+ #include <asm/uaccess.h>
+
+@@ -61,8 +62,8 @@ void unregister_memory_notifier(struct notifier_block *nb)
+ /*
+ * register_memory - Setup a sysfs device for a memory block
+ */
+-int register_memory(struct memory_block *memory, struct mem_section *section,
+- struct node *root)
++static
++int register_memory(struct memory_block *memory, struct mem_section *section)
+ {
+ int error;
+
+@@ -70,26 +71,18 @@ int register_memory(struct memory_block *memory, struct mem_section *section,
+ memory->sysdev.id = __section_nr(section);
+
+ error = sysdev_register(&memory->sysdev);
+-
+- if (root && !error)
+- error = sysfs_create_link(&root->sysdev.kobj,
+- &memory->sysdev.kobj,
+- kobject_name(&memory->sysdev.kobj));
+-
+ return error;
+ }
+
+ static void
+-unregister_memory(struct memory_block *memory, struct mem_section *section,
+- struct node *root)
++unregister_memory(struct memory_block *memory, struct mem_section *section)
+ {
+ BUG_ON(memory->sysdev.cls != &memory_sysdev_class);
+ BUG_ON(memory->sysdev.id != __section_nr(section));
+
++ /* drop the ref. we got in remove_memory_block() */
++ kobject_put(&memory->sysdev.kobj);
+ sysdev_unregister(&memory->sysdev);
+- if (root)
+- sysfs_remove_link(&root->sysdev.kobj,
+- kobject_name(&memory->sysdev.kobj));
+ }
+
+ /*
+@@ -193,7 +186,7 @@ memory_block_action(struct memory_block *mem, unsigned long action)
+ break;
+ default:
+ printk(KERN_WARNING "%s(%p, %ld) unknown action: %ld\n",
+- __FUNCTION__, mem, action, action);
++ __func__, mem, action, action);
+ WARN_ON(1);
+ ret = -EINVAL;
+ }
+@@ -205,7 +198,7 @@ static int memory_block_change_state(struct memory_block *mem,
+ unsigned long to_state, unsigned long from_state_req)
+ {
+ int ret = 0;
+- down(&mem->state_sem);
++ mutex_lock(&mem->state_mutex);
+
+ if (mem->state != from_state_req) {
+ ret = -EINVAL;
+@@ -217,7 +210,7 @@ static int memory_block_change_state(struct memory_block *mem,
+ mem->state = to_state;
+
+ out:
+- up(&mem->state_sem);
++ mutex_unlock(&mem->state_mutex);
+ return ret;
+ }
+
+@@ -341,10 +334,10 @@ static int add_memory_block(unsigned long node_id, struct mem_section *section,
+
+ mem->phys_index = __section_nr(section);
+ mem->state = state;
+- init_MUTEX(&mem->state_sem);
++ mutex_init(&mem->state_mutex);
+ mem->phys_device = phys_device;
+
+- ret = register_memory(mem, section, NULL);
++ ret = register_memory(mem, section);
+ if (!ret)
+ ret = mem_create_simple_file(mem, phys_index);
+ if (!ret)
+@@ -395,7 +388,7 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,
+ mem_remove_simple_file(mem, phys_index);
+ mem_remove_simple_file(mem, state);
+ mem_remove_simple_file(mem, phys_device);
+- unregister_memory(mem, section, NULL);
++ unregister_memory(mem, section);
+
+ return 0;
+ }
+@@ -451,6 +444,6 @@ int __init memory_dev_init(void)
+ ret = err;
+ out:
+ if (ret)
+- printk(KERN_ERR "%s() failed: %d\n", __FUNCTION__, ret);
++ printk(KERN_ERR "%s() failed: %d\n", __func__, ret);
+ return ret;
+ }
+diff --git a/drivers/base/node.c b/drivers/base/node.c
+index e59861f..12fde2d 100644
+--- a/drivers/base/node.c
++++ b/drivers/base/node.c
+@@ -19,21 +19,34 @@ static struct sysdev_class node_class = {
+ };
+
+
+-static ssize_t node_read_cpumap(struct sys_device * dev, char * buf)
++static ssize_t node_read_cpumap(struct sys_device *dev, int type, char *buf)
+ {
+ struct node *node_dev = to_node(dev);
+- cpumask_t mask = node_to_cpumask(node_dev->sysdev.id);
++ node_to_cpumask_ptr(mask, node_dev->sysdev.id);
+ int len;
+
+- /* 2004/06/03: buf currently PAGE_SIZE, need > 1 char per 4 bits. */
+- BUILD_BUG_ON(MAX_NUMNODES/4 > PAGE_SIZE/2);
++ /* 2008/04/07: buf currently PAGE_SIZE, need 9 chars per 32 bits. */
++ BUILD_BUG_ON((NR_CPUS/32 * 9) > (PAGE_SIZE-1));
+
+- len = cpumask_scnprintf(buf, PAGE_SIZE-1, mask);
+- len += sprintf(buf + len, "\n");
++ len = type?
++ cpulist_scnprintf(buf, PAGE_SIZE-2, *mask):
++ cpumask_scnprintf(buf, PAGE_SIZE-2, *mask);
++ buf[len++] = '\n';
++ buf[len] = '\0';
+ return len;
+ }
+
+-static SYSDEV_ATTR(cpumap, S_IRUGO, node_read_cpumap, NULL);
++static inline ssize_t node_read_cpumask(struct sys_device *dev, char *buf)
++{
++ return node_read_cpumap(dev, 0, buf);
++}
++static inline ssize_t node_read_cpulist(struct sys_device *dev, char *buf)
++{
++ return node_read_cpumap(dev, 1, buf);
++}
++
++static SYSDEV_ATTR(cpumap, S_IRUGO, node_read_cpumask, NULL);
++static SYSDEV_ATTR(cpulist, S_IRUGO, node_read_cpulist, NULL);
+
+ #define K(x) ((x) << (PAGE_SHIFT - 10))
+ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
+@@ -149,6 +162,7 @@ int register_node(struct node *node, int num, struct node *parent)
+
+ if (!error){
+ sysdev_create_file(&node->sysdev, &attr_cpumap);
++ sysdev_create_file(&node->sysdev, &attr_cpulist);
+ sysdev_create_file(&node->sysdev, &attr_meminfo);
+ sysdev_create_file(&node->sysdev, &attr_numastat);
+ sysdev_create_file(&node->sysdev, &attr_distance);
+@@ -166,6 +180,7 @@ int register_node(struct node *node, int num, struct node *parent)
+ void unregister_node(struct node *node)
+ {
+ sysdev_remove_file(&node->sysdev, &attr_cpumap);
++ sysdev_remove_file(&node->sysdev, &attr_cpulist);
+ sysdev_remove_file(&node->sysdev, &attr_meminfo);
+ sysdev_remove_file(&node->sysdev, &attr_numastat);
+ sysdev_remove_file(&node->sysdev, &attr_distance);
+diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
+index d887d5c..7b76fd3 100644
+--- a/drivers/base/power/main.c
++++ b/drivers/base/power/main.c
+@@ -50,26 +50,37 @@
+ LIST_HEAD(dpm_active);
+ static LIST_HEAD(dpm_off);
+ static LIST_HEAD(dpm_off_irq);
+-static LIST_HEAD(dpm_destroy);
+
+ static DEFINE_MUTEX(dpm_list_mtx);
+
+-static DECLARE_RWSEM(pm_sleep_rwsem);
+-
+-int (*platform_enable_wakeup)(struct device *dev, int is_on);
++/* 'true' if all devices have been suspended, protected by dpm_list_mtx */
++static bool all_sleeping;
+
+ /**
+ * device_pm_add - add a device to the list of active devices
+ * @dev: Device to be added to the list
+ */
+-void device_pm_add(struct device *dev)
++int device_pm_add(struct device *dev)
+ {
++ int error;
++
+ pr_debug("PM: Adding info for %s:%s\n",
+ dev->bus ? dev->bus->name : "No Bus",
+ kobject_name(&dev->kobj));
+ mutex_lock(&dpm_list_mtx);
+- list_add_tail(&dev->power.entry, &dpm_active);
++ if ((dev->parent && dev->parent->power.sleeping) || all_sleeping) {
++ if (dev->parent->power.sleeping)
++ dev_warn(dev, "parent %s is sleeping\n",
++ dev->parent->bus_id);
++ else
++ dev_warn(dev, "all devices are sleeping\n");
++ WARN_ON(true);
++ }
++ error = dpm_sysfs_add(dev);
++ if (!error)
++ list_add_tail(&dev->power.entry, &dpm_active);
+ mutex_unlock(&dpm_list_mtx);
++ return error;
+ }
+
+ /**
+@@ -89,50 +100,6 @@ void device_pm_remove(struct device *dev)
+ mutex_unlock(&dpm_list_mtx);
+ }
+
+-/**
+- * device_pm_schedule_removal - schedule the removal of a suspended device
+- * @dev: Device to destroy
+- *
+- * Moves the device to the dpm_destroy list for further processing by
+- * unregister_dropped_devices().
+- */
+-void device_pm_schedule_removal(struct device *dev)
+-{
+- pr_debug("PM: Preparing for removal: %s:%s\n",
+- dev->bus ? dev->bus->name : "No Bus",
+- kobject_name(&dev->kobj));
+- mutex_lock(&dpm_list_mtx);
+- list_move_tail(&dev->power.entry, &dpm_destroy);
+- mutex_unlock(&dpm_list_mtx);
+-}
+-EXPORT_SYMBOL_GPL(device_pm_schedule_removal);
+-
+-/**
+- * pm_sleep_lock - mutual exclusion for registration and suspend
+- *
+- * Returns 0 if no suspend is underway and device registration
+- * may proceed, otherwise -EBUSY.
+- */
+-int pm_sleep_lock(void)
+-{
+- if (down_read_trylock(&pm_sleep_rwsem))
+- return 0;
+-
+- return -EBUSY;
+-}
+-
+-/**
+- * pm_sleep_unlock - mutual exclusion for registration and suspend
+- *
+- * This routine undoes the effect of device_pm_add_lock
+- * when a device's registration is complete.
+- */
+-void pm_sleep_unlock(void)
+-{
+- up_read(&pm_sleep_rwsem);
+-}
+-
+-
+ /*------------------------- Resume routines -------------------------*/
+
+ /**
+@@ -242,11 +209,13 @@ static int resume_device(struct device *dev)
+ static void dpm_resume(void)
+ {
+ mutex_lock(&dpm_list_mtx);
++ all_sleeping = false;
+ while(!list_empty(&dpm_off)) {
+ struct list_head *entry = dpm_off.next;
+ struct device *dev = to_device(entry);
+
+ list_move_tail(entry, &dpm_active);
++ dev->power.sleeping = false;
+ mutex_unlock(&dpm_list_mtx);
+ resume_device(dev);
+ mutex_lock(&dpm_list_mtx);
+@@ -255,26 +224,6 @@ static void dpm_resume(void)
+ }
+
+ /**
+- * unregister_dropped_devices - Unregister devices scheduled for removal
+- *
+- * Unregister all devices on the dpm_destroy list.
+- */
+-static void unregister_dropped_devices(void)
+-{
+- mutex_lock(&dpm_list_mtx);
+- while (!list_empty(&dpm_destroy)) {
+- struct list_head *entry = dpm_destroy.next;
+- struct device *dev = to_device(entry);
+-
+- mutex_unlock(&dpm_list_mtx);
+- /* This also removes the device from the list */
+- device_unregister(dev);
+- mutex_lock(&dpm_list_mtx);
+- }
+- mutex_unlock(&dpm_list_mtx);
+-}
+-
+-/**
+ * device_resume - Restore state of each device in system.
+ *
+ * Resume all the devices, unlock them all, and allow new
+@@ -284,8 +233,6 @@ void device_resume(void)
+ {
+ might_sleep();
+ dpm_resume();
+- unregister_dropped_devices();
+- up_write(&pm_sleep_rwsem);
+ }
+ EXPORT_SYMBOL_GPL(device_resume);
+
+@@ -377,11 +324,6 @@ static int suspend_device(struct device *dev, pm_message_t state)
+
+ down(&dev->sem);
+
+- if (dev->power.power_state.event) {
+- dev_dbg(dev, "PM: suspend %d-->%d\n",
+- dev->power.power_state.event, state.event);
+- }
+-
+ if (dev->class && dev->class->suspend) {
+ suspend_device_dbg(dev, state, "class ");
+ error = dev->class->suspend(dev, state);
+@@ -426,6 +368,9 @@ static int dpm_suspend(pm_message_t state)
+ struct list_head *entry = dpm_active.prev;
+ struct device *dev = to_device(entry);
+
++ WARN_ON(dev->parent && dev->parent->power.sleeping);
++
++ dev->power.sleeping = true;
+ mutex_unlock(&dpm_list_mtx);
+ error = suspend_device(dev, state);
+ mutex_lock(&dpm_list_mtx);
+@@ -437,11 +382,14 @@ static int dpm_suspend(pm_message_t state)
+ (error == -EAGAIN ?
+ " (please convert to suspend_late)" :
+ ""));
++ dev->power.sleeping = false;
+ break;
+ }
+ if (!list_empty(&dev->power.entry))
+ list_move(&dev->power.entry, &dpm_off);
+ }
++ if (!error)
++ all_sleeping = true;
+ mutex_unlock(&dpm_list_mtx);
+
+ return error;
+@@ -459,7 +407,6 @@ int device_suspend(pm_message_t state)
+ int error;
+
+ might_sleep();
+- down_write(&pm_sleep_rwsem);
+ error = dpm_suspend(state);
+ if (error)
+ device_resume();
+diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
+index e32d3bd..a6894f2 100644
+--- a/drivers/base/power/power.h
++++ b/drivers/base/power/power.h
+@@ -11,30 +11,13 @@ static inline struct device *to_device(struct list_head *entry)
+ return container_of(entry, struct device, power.entry);
+ }
+
+-extern void device_pm_add(struct device *);
++extern int device_pm_add(struct device *);
+ extern void device_pm_remove(struct device *);
+-extern int pm_sleep_lock(void);
+-extern void pm_sleep_unlock(void);
+
+ #else /* CONFIG_PM_SLEEP */
+
+-
+-static inline void device_pm_add(struct device *dev)
+-{
+-}
+-
+-static inline void device_pm_remove(struct device *dev)
+-{
+-}
+-
+-static inline int pm_sleep_lock(void)
+-{
+- return 0;
+-}
+-
+-static inline void pm_sleep_unlock(void)
+-{
+-}
++static inline int device_pm_add(struct device *dev) { return 0; }
++static inline void device_pm_remove(struct device *dev) {}
+
+ #endif
+
+diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
+index f2ed179..d11f74b 100644
+--- a/drivers/base/power/sysfs.c
++++ b/drivers/base/power/sysfs.c
+@@ -6,6 +6,8 @@
+ #include <linux/string.h>
+ #include "power.h"
+
++int (*platform_enable_wakeup)(struct device *dev, int is_on);
++
+
+ /*
+ * wakeup - Report/change current wakeup option for device
+diff --git a/drivers/base/sys.c b/drivers/base/sys.c
+index 8e13fd9..4fbb56b 100644
+--- a/drivers/base/sys.c
++++ b/drivers/base/sys.c
+@@ -167,6 +167,22 @@ int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv)
+ {
+ int err = 0;
+
++ if (!cls) {
++ printk(KERN_WARNING "sysdev: invalid class passed to "
++ "sysdev_driver_register!\n");
++ WARN_ON(1);
++ return -EINVAL;
++ }
++
++ /* Check whether this driver has already been added to a class. */
++ if ((drv->entry.next != drv->entry.prev) ||
++ (drv->entry.next != NULL)) {
++ printk(KERN_WARNING "sysdev: class %s: driver (%p) has already"
++ " been registered to a class, something is wrong, but "
++ "will forge on!\n", cls->name, drv);
++ WARN_ON(1);
++ }
++
+ mutex_lock(&sysdev_drivers_lock);
+ if (cls && kset_get(&cls->kset)) {
+ list_add_tail(&drv->entry, &cls->drivers);
+@@ -179,7 +195,7 @@ int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv)
+ }
+ } else {
+ err = -EINVAL;
+- printk(KERN_ERR "%s: invalid device class\n", __FUNCTION__);
++ printk(KERN_ERR "%s: invalid device class\n", __func__);
+ WARN_ON(1);
+ }
+ mutex_unlock(&sysdev_drivers_lock);
+diff --git a/drivers/base/topology.c b/drivers/base/topology.c
+index e1d3ad4..fdf4044 100644
+--- a/drivers/base/topology.c
++++ b/drivers/base/topology.c
+@@ -40,15 +40,38 @@ static ssize_t show_##name(struct sys_device *dev, char *buf) \
+ return sprintf(buf, "%d\n", topology_##name(cpu)); \
+ }
+
+-#define define_siblings_show_func(name) \
+-static ssize_t show_##name(struct sys_device *dev, char *buf) \
++static ssize_t show_cpumap(int type, cpumask_t *mask, char *buf)
++{
++ ptrdiff_t len = PTR_ALIGN(buf + PAGE_SIZE - 1, PAGE_SIZE) - buf;
++ int n = 0;
++
++ if (len > 1) {
++ n = type?
++ cpulist_scnprintf(buf, len-2, *mask):
++ cpumask_scnprintf(buf, len-2, *mask);
++ buf[n++] = '\n';
++ buf[n] = '\0';
++ }
++ return n;
++}
++
++#define define_siblings_show_map(name) \
++static inline ssize_t show_##name(struct sys_device *dev, char *buf) \
+ { \
+- ssize_t len = -1; \
+ unsigned int cpu = dev->id; \
+- len = cpumask_scnprintf(buf, NR_CPUS+1, topology_##name(cpu)); \
+- return (len + sprintf(buf + len, "\n")); \
++ return show_cpumap(0, &(topology_##name(cpu)), buf); \
+ }
+
++#define define_siblings_show_list(name) \
++static inline ssize_t show_##name##_list(struct sys_device *dev, char *buf) \
++{ \
++ unsigned int cpu = dev->id; \
++ return show_cpumap(1, &(topology_##name(cpu)), buf); \
++}
++
++#define define_siblings_show_func(name) \
++ define_siblings_show_map(name); define_siblings_show_list(name)
++
+ #ifdef topology_physical_package_id
+ define_id_show_func(physical_package_id);
+ define_one_ro(physical_package_id);
+@@ -68,7 +91,9 @@ define_one_ro(core_id);
+ #ifdef topology_thread_siblings
+ define_siblings_show_func(thread_siblings);
+ define_one_ro(thread_siblings);
+-#define ref_thread_siblings_attr &attr_thread_siblings.attr,
++define_one_ro(thread_siblings_list);
++#define ref_thread_siblings_attr \
++ &attr_thread_siblings.attr, &attr_thread_siblings_list.attr,
+ #else
+ #define ref_thread_siblings_attr
+ #endif
+@@ -76,7 +101,9 @@ define_one_ro(thread_siblings);
+ #ifdef topology_core_siblings
+ define_siblings_show_func(core_siblings);
+ define_one_ro(core_siblings);
+-#define ref_core_siblings_attr &attr_core_siblings.attr,
++define_one_ro(core_siblings_list);
++#define ref_core_siblings_attr \
++ &attr_core_siblings.attr, &attr_core_siblings_list.attr,
+ #else
+ #define ref_core_siblings_attr
+ #endif
+diff --git a/drivers/base/transport_class.c b/drivers/base/transport_class.c
+index 40bca48..84997ef 100644
+--- a/drivers/base/transport_class.c
++++ b/drivers/base/transport_class.c
+@@ -66,7 +66,7 @@ EXPORT_SYMBOL_GPL(transport_class_unregister);
+
+ static int anon_transport_dummy_function(struct transport_container *tc,
+ struct device *dev,
+- struct class_device *cdev)
++ struct device *cdev)
+ {
+ /* do nothing */
+ return 0;
+@@ -108,13 +108,14 @@ EXPORT_SYMBOL_GPL(anon_transport_class_register);
+ */
+ void anon_transport_class_unregister(struct anon_transport_class *atc)
+ {
+- attribute_container_unregister(&atc->container);
++ if (unlikely(attribute_container_unregister(&atc->container)))
++ BUG();
+ }
+ EXPORT_SYMBOL_GPL(anon_transport_class_unregister);
+
+ static int transport_setup_classdev(struct attribute_container *cont,
+ struct device *dev,
+- struct class_device *classdev)
++ struct device *classdev)
+ {
+ struct transport_class *tclass = class_to_transport_class(cont->class);
+ struct transport_container *tcont = attribute_container_to_transport_container(cont);
+@@ -148,7 +149,7 @@ EXPORT_SYMBOL_GPL(transport_setup_device);
+
+ static int transport_add_class_device(struct attribute_container *cont,
+ struct device *dev,
+- struct class_device *classdev)
++ struct device *classdev)
+ {
+ int error = attribute_container_add_class_device(classdev);
+ struct transport_container *tcont =
+@@ -180,7 +181,7 @@ EXPORT_SYMBOL_GPL(transport_add_device);
+
+ static int transport_configure(struct attribute_container *cont,
+ struct device *dev,
+- struct class_device *cdev)
++ struct device *cdev)
+ {
+ struct transport_class *tclass = class_to_transport_class(cont->class);
+ struct transport_container *tcont = attribute_container_to_transport_container(cont);
+@@ -211,7 +212,7 @@ EXPORT_SYMBOL_GPL(transport_configure_device);
+
+ static int transport_remove_classdev(struct attribute_container *cont,
+ struct device *dev,
+- struct class_device *classdev)
++ struct device *classdev)
+ {
+ struct transport_container *tcont =
+ attribute_container_to_transport_container(cont);
+@@ -250,12 +251,12 @@ EXPORT_SYMBOL_GPL(transport_remove_device);
+
+ static void transport_destroy_classdev(struct attribute_container *cont,
+ struct device *dev,
+- struct class_device *classdev)
++ struct device *classdev)
+ {
+ struct transport_class *tclass = class_to_transport_class(cont->class);
+
+ if (tclass->remove != anon_transport_dummy_function)
+- class_device_put(classdev);
++ put_device(classdev);
+ }
+
+
+diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c
+index 8460ef7..18d243c 100644
+--- a/drivers/block/aoe/aoenet.c
++++ b/drivers/block/aoe/aoenet.c
+@@ -115,7 +115,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
+ struct aoe_hdr *h;
+ u32 n;
+
+- if (ifp->nd_net != &init_net)
++ if (dev_net(ifp) != &init_net)
+ goto exit;
+
+ skb = skb_share_check(skb, GFP_ATOMIC);
+diff --git a/drivers/block/brd.c b/drivers/block/brd.c
+index 8536480..7bd7663 100644
+--- a/drivers/block/brd.c
++++ b/drivers/block/brd.c
+@@ -108,7 +108,7 @@ static struct page *brd_insert_page(struct brd_device *brd, sector_t sector)
+ #ifndef CONFIG_BLK_DEV_XIP
+ gfp_flags |= __GFP_HIGHMEM;
+ #endif
+- page = alloc_page(GFP_NOIO | __GFP_HIGHMEM | __GFP_ZERO);
++ page = alloc_page(gfp_flags);
+ if (!page)
+ return NULL;
+
+diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
+index 9c9627e..cf6083a 100644
+--- a/drivers/block/cciss.c
++++ b/drivers/block/cciss.c
+@@ -1349,6 +1349,10 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
+ spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
+ h->drv[drv_index].busy_configuring = 1;
+ spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
++
++ /* deregister_disk sets h->drv[drv_index].queue = NULL */
++ /* which keeps the interrupt handler from starting */
++ /* the queue. */
+ ret = deregister_disk(h->gendisk[drv_index],
+ &h->drv[drv_index], 0);
+ h->drv[drv_index].busy_configuring = 0;
+@@ -1419,6 +1423,10 @@ geo_inq:
+ blk_queue_hardsect_size(disk->queue,
+ hba[ctlr]->drv[drv_index].block_size);
+
++ /* Make sure all queue data is written out before */
++ /* setting h->drv[drv_index].queue, as setting this */
++ /* allows the interrupt handler to start the queue */
++ wmb();
+ h->drv[drv_index].queue = disk->queue;
+ add_disk(disk);
+ }
+@@ -3520,10 +3528,17 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
+ continue;
+ blk_queue_hardsect_size(q, drv->block_size);
+ set_capacity(disk, drv->nr_blocks);
+- add_disk(disk);
+ j++;
+ } while (j <= hba[i]->highest_lun);
+
++ /* Make sure all queue data is written out before */
++ /* interrupt handler, triggered by add_disk, */
++ /* is allowed to start them. */
++ wmb();
++
++ for (j = 0; j <= hba[i]->highest_lun; j++)
++ add_disk(hba[i]->gendisk[j]);
++
+ return 1;
+
+ clean4:
+diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
+index 45ac093..e4bf9a1 100644
+--- a/drivers/block/cciss_scsi.c
++++ b/drivers/block/cciss_scsi.c
+@@ -1349,9 +1349,9 @@ cciss_unregister_scsi(int ctlr)
+ /* set scsi_host to NULL so our detect routine will
+ find us on register */
+ sa->scsi_host = NULL;
++ spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+ scsi_cmd_stack_free(ctlr);
+ kfree(sa);
+- spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+ }
+
+ static int
+diff --git a/drivers/block/cryptoloop.c b/drivers/block/cryptoloop.c
+index 2411678..8b6bb76 100644
+--- a/drivers/block/cryptoloop.c
++++ b/drivers/block/cryptoloop.c
+@@ -27,7 +27,6 @@
+ #include <linux/blkdev.h>
+ #include <linux/loop.h>
+ #include <linux/scatterlist.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+
+ MODULE_LICENSE("GPL");
+diff --git a/drivers/block/loop.c b/drivers/block/loop.c
+index 91ebb00..f7f1635 100644
+--- a/drivers/block/loop.c
++++ b/drivers/block/loop.c
+@@ -82,6 +82,9 @@
+ static LIST_HEAD(loop_devices);
+ static DEFINE_MUTEX(loop_devices_mutex);
+
++static int max_part;
++static int part_shift;
++
+ /*
+ * Transfer functions
+ */
+@@ -692,6 +695,8 @@ static int loop_change_fd(struct loop_device *lo, struct file *lo_file,
+ goto out_putf;
+
+ fput(old_file);
++ if (max_part > 0)
++ ioctl_by_bdev(bdev, BLKRRPART, 0);
+ return 0;
+
+ out_putf:
+@@ -819,6 +824,8 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
+ }
+ lo->lo_state = Lo_bound;
+ wake_up_process(lo->lo_thread);
++ if (max_part > 0)
++ ioctl_by_bdev(bdev, BLKRRPART, 0);
+ return 0;
+
+ out_clr:
+@@ -919,6 +926,8 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
+ fput(filp);
+ /* This is safe: open() is still holding a reference. */
+ module_put(THIS_MODULE);
++ if (max_part > 0)
++ ioctl_by_bdev(bdev, BLKRRPART, 0);
+ return 0;
+ }
+
+@@ -1360,6 +1369,8 @@ static struct block_device_operations lo_fops = {
+ static int max_loop;
+ module_param(max_loop, int, 0);
+ MODULE_PARM_DESC(max_loop, "Maximum number of loop devices");
++module_param(max_part, int, 0);
++MODULE_PARM_DESC(max_part, "Maximum number of partitions per loop device");
+ MODULE_LICENSE("GPL");
+ MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR);
+
+@@ -1412,7 +1423,7 @@ static struct loop_device *loop_alloc(int i)
+ if (!lo->lo_queue)
+ goto out_free_dev;
+
+- disk = lo->lo_disk = alloc_disk(1);
++ disk = lo->lo_disk = alloc_disk(1 << part_shift);
+ if (!disk)
+ goto out_free_queue;
+
+@@ -1422,7 +1433,7 @@ static struct loop_device *loop_alloc(int i)
+ init_waitqueue_head(&lo->lo_event);
+ spin_lock_init(&lo->lo_lock);
+ disk->major = LOOP_MAJOR;
+- disk->first_minor = i;
++ disk->first_minor = i << part_shift;
+ disk->fops = &lo_fops;
+ disk->private_data = lo;
+ disk->queue = lo->lo_queue;
+@@ -1502,7 +1513,12 @@ static int __init loop_init(void)
+ * themselves and have kernel automatically instantiate actual
+ * device on-demand.
+ */
+- if (max_loop > 1UL << MINORBITS)
++
++ part_shift = 0;
++ if (max_part > 0)
++ part_shift = fls(max_part);
++
++ if (max_loop > 1UL << (MINORBITS - part_shift))
+ return -EINVAL;
+
+ if (max_loop) {
+@@ -1510,7 +1526,7 @@ static int __init loop_init(void)
+ range = max_loop;
+ } else {
+ nr = 8;
+- range = 1UL << MINORBITS;
++ range = 1UL << (MINORBITS - part_shift);
+ }
+
+ if (register_blkdev(LOOP_MAJOR, "loop"))
+@@ -1549,7 +1565,7 @@ static void __exit loop_exit(void)
+ unsigned long range;
+ struct loop_device *lo, *next;
+
+- range = max_loop ? max_loop : 1UL << MINORBITS;
++ range = max_loop ? max_loop : 1UL << (MINORBITS - part_shift);
+
+ list_for_each_entry_safe(lo, next, &loop_devices, lo_list)
+ loop_del_one(lo);
+diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
+index cd5674b..a18e1ca 100644
+--- a/drivers/block/sx8.c
++++ b/drivers/block/sx8.c
+@@ -79,9 +79,9 @@ MODULE_PARM_DESC(max_queue, "Maximum number of queued commands. (min==1, max==30
+
+ /* note: prints function name for you */
+ #ifdef CARM_DEBUG
+-#define DPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
++#define DPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args)
+ #ifdef CARM_VERBOSE_DEBUG
+-#define VPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
++#define VPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args)
+ #else
+ #define VPRINTK(fmt, args...)
+ #endif /* CARM_VERBOSE_DEBUG */
+@@ -96,7 +96,7 @@ MODULE_PARM_DESC(max_queue, "Maximum number of queued commands. (min==1, max==30
+ #define assert(expr) \
+ if(unlikely(!(expr))) { \
+ printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \
+- #expr,__FILE__,__FUNCTION__,__LINE__); \
++ #expr, __FILE__, __func__, __LINE__); \
+ }
+ #endif
+
+diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
+index 41ca721..ebfe038 100644
+--- a/drivers/block/viodasd.c
++++ b/drivers/block/viodasd.c
+@@ -69,7 +69,7 @@ MODULE_LICENSE("GPL");
+ enum {
+ PARTITION_SHIFT = 3,
+ MAX_DISKNO = HVMAXARCHITECTEDVIRTUALDISKS,
+- MAX_DISK_NAME = sizeof(((struct gendisk *)0)->disk_name)
++ MAX_DISK_NAME = FIELD_SIZEOF(struct gendisk, disk_name)
+ };
+
+ static DEFINE_SPINLOCK(viodasd_spinlock);
+diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
+index 9c6f3f9..d771da8 100644
+--- a/drivers/block/xen-blkfront.c
++++ b/drivers/block/xen-blkfront.c
+@@ -47,6 +47,7 @@
+
+ #include <xen/interface/grant_table.h>
+ #include <xen/interface/io/blkif.h>
++#include <xen/interface/io/protocols.h>
+
+ #include <asm/xen/hypervisor.h>
+
+@@ -74,7 +75,6 @@ static struct block_device_operations xlvbd_block_fops;
+ struct blkfront_info
+ {
+ struct xenbus_device *xbdev;
+- dev_t dev;
+ struct gendisk *gd;
+ int vdevice;
+ blkif_vdev_t handle;
+@@ -88,6 +88,7 @@ struct blkfront_info
+ struct blk_shadow shadow[BLK_RING_SIZE];
+ unsigned long shadow_free;
+ int feature_barrier;
++ int is_ready;
+
+ /**
+ * The number of people holding this device open. We won't allow a
+@@ -614,6 +615,12 @@ again:
+ message = "writing event-channel";
+ goto abort_transaction;
+ }
++ err = xenbus_printf(xbt, dev->nodename, "protocol", "%s",
++ XEN_IO_PROTO_ABI_NATIVE);
++ if (err) {
++ message = "writing protocol";
++ goto abort_transaction;
++ }
+
+ err = xenbus_transaction_end(xbt, 0);
+ if (err) {
+@@ -833,6 +840,8 @@ static void blkfront_connect(struct blkfront_info *info)
+ spin_unlock_irq(&blkif_io_lock);
+
+ add_disk(info->gd);
++
++ info->is_ready = 1;
+ }
+
+ /**
+@@ -896,7 +905,7 @@ static void backend_changed(struct xenbus_device *dev,
+ break;
+
+ case XenbusStateClosing:
+- bd = bdget(info->dev);
++ bd = bdget_disk(info->gd, 0);
+ if (bd == NULL)
+ xenbus_dev_fatal(dev, -ENODEV, "bdget failed");
+
+@@ -925,6 +934,13 @@ static int blkfront_remove(struct xenbus_device *dev)
+ return 0;
+ }
+
++static int blkfront_is_ready(struct xenbus_device *dev)
++{
++ struct blkfront_info *info = dev->dev.driver_data;
++
++ return info->is_ready;
++}
++
+ static int blkif_open(struct inode *inode, struct file *filep)
+ {
+ struct blkfront_info *info = inode->i_bdev->bd_disk->private_data;
+@@ -971,6 +987,7 @@ static struct xenbus_driver blkfront = {
+ .remove = blkfront_remove,
+ .resume = blkfront_resume,
+ .otherend_changed = backend_changed,
++ .is_ready = blkfront_is_ready,
+ };
+
+ static int __init xlblk_init(void)
+@@ -998,3 +1015,5 @@ module_exit(xlblk_exit);
+ MODULE_DESCRIPTION("Xen virtual block device frontend");
+ MODULE_LICENSE("GPL");
+ MODULE_ALIAS_BLOCKDEV_MAJOR(XENVBD_MAJOR);
++MODULE_ALIAS("xen:vbd");
++MODULE_ALIAS("xenblk");
+diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
+index 8b884f8..192522e 100644
+--- a/drivers/bluetooth/hci_usb.c
++++ b/drivers/bluetooth/hci_usb.c
+@@ -62,13 +62,13 @@
+ #define URB_ZERO_PACKET 0
+ #endif
+
+-static int ignore = 0;
+-static int ignore_dga = 0;
+-static int ignore_csr = 0;
+-static int ignore_sniffer = 0;
+-static int disable_scofix = 0;
+-static int force_scofix = 0;
+-static int reset = 0;
++static int ignore;
++static int ignore_dga;
++static int ignore_csr;
++static int ignore_sniffer;
++static int disable_scofix;
++static int force_scofix;
++static int reset;
+
+ #ifdef CONFIG_BT_HCIUSB_SCO
+ static int isoc = 2;
+@@ -265,7 +265,7 @@ static int hci_usb_intr_rx_submit(struct hci_usb *husb)
+ BT_ERR("%s intr rx submit failed urb %p err %d",
+ husb->hdev->name, urb, err);
+ _urb_unlink(_urb);
+- _urb_free(_urb);
++ kfree(_urb);
+ kfree(buf);
+ }
+ return err;
+@@ -302,7 +302,7 @@ static int hci_usb_bulk_rx_submit(struct hci_usb *husb)
+ BT_ERR("%s bulk rx submit failed urb %p err %d",
+ husb->hdev->name, urb, err);
+ _urb_unlink(_urb);
+- _urb_free(_urb);
++ kfree(_urb);
+ kfree(buf);
+ }
+ return err;
+@@ -353,7 +353,7 @@ static int hci_usb_isoc_rx_submit(struct hci_usb *husb)
+ BT_ERR("%s isoc rx submit failed urb %p err %d",
+ husb->hdev->name, urb, err);
+ _urb_unlink(_urb);
+- _urb_free(_urb);
++ kfree(_urb);
+ kfree(buf);
+ }
+ return err;
+@@ -431,7 +431,7 @@ static void hci_usb_unlink_urbs(struct hci_usb *husb)
+ husb->hdev->name, _urb, _urb->type, urb);
+ kfree(urb->setup_packet);
+ kfree(urb->transfer_buffer);
+- _urb_free(_urb);
++ kfree(_urb);
+ }
+ }
+ }
+@@ -490,7 +490,7 @@ static inline int hci_usb_send_ctrl(struct hci_usb *husb, struct sk_buff *skb)
+
+ dr = kmalloc(sizeof(*dr), GFP_ATOMIC);
+ if (!dr) {
+- _urb_free(_urb);
++ kfree(_urb);
+ return -ENOMEM;
+ }
+ } else
+diff --git a/drivers/bluetooth/hci_usb.h b/drivers/bluetooth/hci_usb.h
+index 56cd3a9..414080a 100644
+--- a/drivers/bluetooth/hci_usb.h
++++ b/drivers/bluetooth/hci_usb.h
+@@ -60,11 +60,6 @@ struct _urb {
+ struct urb urb;
+ };
+
+-static inline void _urb_free(struct _urb *_urb)
+-{
+- kfree(_urb);
+-}
+-
+ static inline void _urb_queue_init(struct _urb_queue *q)
+ {
+ INIT_LIST_HEAD(&q->head);
+diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
+index 12f5bae..ac38290 100644
+--- a/drivers/cdrom/cdrom.c
++++ b/drivers/cdrom/cdrom.c
+@@ -360,10 +360,9 @@ static int cdrom_mrw_exit(struct cdrom_device_info *cdi);
+
+ static int cdrom_get_disc_info(struct cdrom_device_info *cdi, disc_information *di);
+
+-#ifdef CONFIG_SYSCTL
+ static void cdrom_sysctl_register(void);
+-#endif /* CONFIG_SYSCTL */
+-static struct cdrom_device_info *topCdromPtr;
++
++static LIST_HEAD(cdrom_list);
+
+ static int cdrom_dummy_generic_packet(struct cdrom_device_info *cdi,
+ struct packet_command *cgc)
+@@ -394,13 +393,11 @@ int register_cdrom(struct cdrom_device_info *cdi)
+ cdinfo(CD_OPEN, "entering register_cdrom\n");
+
+ if (cdo->open == NULL || cdo->release == NULL)
+- return -2;
++ return -EINVAL;
+ if (!banner_printed) {
+ printk(KERN_INFO "Uniform CD-ROM driver " REVISION "\n");
+ banner_printed = 1;
+-#ifdef CONFIG_SYSCTL
+ cdrom_sysctl_register();
+-#endif /* CONFIG_SYSCTL */
+ }
+
+ ENSURE(drive_status, CDC_DRIVE_STATUS );
+@@ -439,35 +436,18 @@ int register_cdrom(struct cdrom_device_info *cdi)
+
+ cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
+ mutex_lock(&cdrom_mutex);
+- cdi->next = topCdromPtr;
+- topCdromPtr = cdi;
++ list_add(&cdi->list, &cdrom_list);
+ mutex_unlock(&cdrom_mutex);
+ return 0;
+ }
+ #undef ENSURE
+
+-int unregister_cdrom(struct cdrom_device_info *unreg)
++void unregister_cdrom(struct cdrom_device_info *cdi)
+ {
+- struct cdrom_device_info *cdi, *prev;
+ cdinfo(CD_OPEN, "entering unregister_cdrom\n");
+
+- prev = NULL;
+ mutex_lock(&cdrom_mutex);
+- cdi = topCdromPtr;
+- while (cdi && cdi != unreg) {
+- prev = cdi;
+- cdi = cdi->next;
+- }
+-
+- if (cdi == NULL) {
+- mutex_unlock(&cdrom_mutex);
+- return -2;
+- }
+- if (prev)
+- prev->next = cdi->next;
+- else
+- topCdromPtr = cdi->next;
+-
++ list_del(&cdi->list);
+ mutex_unlock(&cdrom_mutex);
+
+ if (cdi->exit)
+@@ -475,34 +455,43 @@ int unregister_cdrom(struct cdrom_device_info *unreg)
+
+ cdi->ops->n_minors--;
+ cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name);
+- return 0;
+ }
+
+ int cdrom_get_media_event(struct cdrom_device_info *cdi,
+ struct media_event_desc *med)
+ {
+ struct packet_command cgc;
+- unsigned char buffer[8];
+- struct event_header *eh = (struct event_header *) buffer;
++ unsigned char *buffer;
++ struct event_header *eh;
++ int ret = 1;
+
+- init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
++ buffer = kmalloc(8, GFP_KERNEL);
++ if (!buffer)
++ return -ENOMEM;
++
++ eh = (struct event_header *)buffer;
++
++ init_cdrom_command(&cgc, buffer, 8, CGC_DATA_READ);
+ cgc.cmd[0] = GPCMD_GET_EVENT_STATUS_NOTIFICATION;
+ cgc.cmd[1] = 1; /* IMMED */
+ cgc.cmd[4] = 1 << 4; /* media event */
+- cgc.cmd[8] = sizeof(buffer);
++ cgc.cmd[8] = 8;
+ cgc.quiet = 1;
+
+ if (cdi->ops->generic_packet(cdi, &cgc))
+- return 1;
++ goto err;
+
+ if (be16_to_cpu(eh->data_len) < sizeof(*med))
+- return 1;
++ goto err;
+
+ if (eh->nea || eh->notification_class != 0x4)
+- return 1;
++ goto err;
+
+- memcpy(med, &buffer[sizeof(*eh)], sizeof(*med));
+- return 0;
++ memcpy(med, buffer + sizeof(*eh), sizeof(*med));
++ ret = 0;
++err:
++ kfree(buffer);
++ return ret;
+ }
+
+ /*
+@@ -512,68 +501,82 @@ int cdrom_get_media_event(struct cdrom_device_info *cdi,
+ static int cdrom_mrw_probe_pc(struct cdrom_device_info *cdi)
+ {
+ struct packet_command cgc;
+- char buffer[16];
++ char *buffer;
++ int ret = 1;
+
+- init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
++ buffer = kmalloc(16, GFP_KERNEL);
++ if (!buffer)
++ return -ENOMEM;
++
++ init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
+
+ cgc.timeout = HZ;
+ cgc.quiet = 1;
+
+ if (!cdrom_mode_sense(cdi, &cgc, MRW_MODE_PC, 0)) {
+ cdi->mrw_mode_page = MRW_MODE_PC;
+- return 0;
++ ret = 0;
+ } else if (!cdrom_mode_sense(cdi, &cgc, MRW_MODE_PC_PRE1, 0)) {
+ cdi->mrw_mode_page = MRW_MODE_PC_PRE1;
+- return 0;
++ ret = 0;
+ }
+-
+- return 1;
++ kfree(buffer);
++ return ret;
+ }
+
+ static int cdrom_is_mrw(struct cdrom_device_info *cdi, int *write)
+ {
+ struct packet_command cgc;
+ struct mrw_feature_desc *mfd;
+- unsigned char buffer[16];
++ unsigned char *buffer;
+ int ret;
+
+ *write = 0;
++ buffer = kmalloc(16, GFP_KERNEL);
++ if (!buffer)
++ return -ENOMEM;
+
+- init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
++ init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
+
+ cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
+ cgc.cmd[3] = CDF_MRW;
+- cgc.cmd[8] = sizeof(buffer);
++ cgc.cmd[8] = 16;
+ cgc.quiet = 1;
+
+ if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
+- return ret;
++ goto err;
+
+ mfd = (struct mrw_feature_desc *)&buffer[sizeof(struct feature_header)];
+- if (be16_to_cpu(mfd->feature_code) != CDF_MRW)
+- return 1;
++ if (be16_to_cpu(mfd->feature_code) != CDF_MRW) {
++ ret = 1;
++ goto err;
++ }
+ *write = mfd->write;
+
+ if ((ret = cdrom_mrw_probe_pc(cdi))) {
+ *write = 0;
+- return ret;
+ }
+-
+- return 0;
++err:
++ kfree(buffer);
++ return ret;
+ }
+
+ static int cdrom_mrw_bgformat(struct cdrom_device_info *cdi, int cont)
+ {
+ struct packet_command cgc;
+- unsigned char buffer[12];
++ unsigned char *buffer;
+ int ret;
+
+ printk(KERN_INFO "cdrom: %sstarting format\n", cont ? "Re" : "");
+
++ buffer = kmalloc(12, GFP_KERNEL);
++ if (!buffer)
++ return -ENOMEM;
++
+ /*
+ * FmtData bit set (bit 4), format type is 1
+ */
+- init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_WRITE);
++ init_cdrom_command(&cgc, buffer, 12, CGC_DATA_WRITE);
+ cgc.cmd[0] = GPCMD_FORMAT_UNIT;
+ cgc.cmd[1] = (1 << 4) | 1;
+
+@@ -600,6 +603,7 @@ static int cdrom_mrw_bgformat(struct cdrom_device_info *cdi, int cont)
+ if (ret)
+ printk(KERN_INFO "cdrom: bgformat failed\n");
+
++ kfree(buffer);
+ return ret;
+ }
+
+@@ -659,16 +663,17 @@ static int cdrom_mrw_set_lba_space(struct cdrom_device_info *cdi, int space)
+ {
+ struct packet_command cgc;
+ struct mode_page_header *mph;
+- char buffer[16];
++ char *buffer;
+ int ret, offset, size;
+
+- init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
++ buffer = kmalloc(16, GFP_KERNEL);
++ if (!buffer)
++ return -ENOMEM;
+
+- cgc.buffer = buffer;
+- cgc.buflen = sizeof(buffer);
++ init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
+
+ if ((ret = cdrom_mode_sense(cdi, &cgc, cdi->mrw_mode_page, 0)))
+- return ret;
++ goto err;
+
+ mph = (struct mode_page_header *) buffer;
+ offset = be16_to_cpu(mph->desc_length);
+@@ -678,55 +683,70 @@ static int cdrom_mrw_set_lba_space(struct cdrom_device_info *cdi, int space)
+ cgc.buflen = size;
+
+ if ((ret = cdrom_mode_select(cdi, &cgc)))
+- return ret;
++ goto err;
+
+ printk(KERN_INFO "cdrom: %s: mrw address space %s selected\n", cdi->name, mrw_address_space[space]);
+- return 0;
++ ret = 0;
++err:
++ kfree(buffer);
++ return ret;
+ }
+
+ static int cdrom_get_random_writable(struct cdrom_device_info *cdi,
+ struct rwrt_feature_desc *rfd)
+ {
+ struct packet_command cgc;
+- char buffer[24];
++ char *buffer;
+ int ret;
+
+- init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
++ buffer = kmalloc(24, GFP_KERNEL);
++ if (!buffer)
++ return -ENOMEM;
++
++ init_cdrom_command(&cgc, buffer, 24, CGC_DATA_READ);
+
+ cgc.cmd[0] = GPCMD_GET_CONFIGURATION; /* often 0x46 */
+ cgc.cmd[3] = CDF_RWRT; /* often 0x0020 */
+- cgc.cmd[8] = sizeof(buffer); /* often 0x18 */
++ cgc.cmd[8] = 24; /* often 0x18 */
+ cgc.quiet = 1;
+
+ if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
+- return ret;
++ goto err;
+
+ memcpy(rfd, &buffer[sizeof(struct feature_header)], sizeof (*rfd));
+- return 0;
++ ret = 0;
++err:
++ kfree(buffer);
++ return ret;
+ }
+
+ static int cdrom_has_defect_mgt(struct cdrom_device_info *cdi)
+ {
+ struct packet_command cgc;
+- char buffer[16];
++ char *buffer;
+ __be16 *feature_code;
+ int ret;
+
+- init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
++ buffer = kmalloc(16, GFP_KERNEL);
++ if (!buffer)
++ return -ENOMEM;
++
++ init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
+
+ cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
+ cgc.cmd[3] = CDF_HWDM;
+- cgc.cmd[8] = sizeof(buffer);
++ cgc.cmd[8] = 16;
+ cgc.quiet = 1;
+
+ if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
+- return ret;
++ goto err;
+
+ feature_code = (__be16 *) &buffer[sizeof(struct feature_header)];
+ if (be16_to_cpu(*feature_code) == CDF_HWDM)
+- return 0;
+-
+- return 1;
++ ret = 0;
++err:
++ kfree(buffer);
++ return ret;
+ }
+
+
+@@ -817,10 +837,14 @@ static int cdrom_mrw_open_write(struct cdrom_device_info *cdi)
+ static int mo_open_write(struct cdrom_device_info *cdi)
+ {
+ struct packet_command cgc;
+- char buffer[255];
++ char *buffer;
+ int ret;
+
+- init_cdrom_command(&cgc, &buffer, 4, CGC_DATA_READ);
++ buffer = kmalloc(255, GFP_KERNEL);
++ if (!buffer)
++ return -ENOMEM;
++
++ init_cdrom_command(&cgc, buffer, 4, CGC_DATA_READ);
+ cgc.quiet = 1;
+
+ /*
+@@ -837,10 +861,15 @@ static int mo_open_write(struct cdrom_device_info *cdi)
+ }
+
+ /* drive gave us no info, let the user go ahead */
+- if (ret)
+- return 0;
++ if (ret) {
++ ret = 0;
++ goto err;
++ }
+
+- return buffer[3] & 0x80;
++ ret = buffer[3] & 0x80;
++err:
++ kfree(buffer);
++ return ret;
+ }
+
+ static int cdrom_ram_open_write(struct cdrom_device_info *cdi)
+@@ -863,15 +892,19 @@ static int cdrom_ram_open_write(struct cdrom_device_info *cdi)
+ static void cdrom_mmc3_profile(struct cdrom_device_info *cdi)
+ {
+ struct packet_command cgc;
+- char buffer[32];
++ char *buffer;
+ int ret, mmc3_profile;
+
+- init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
++ buffer = kmalloc(32, GFP_KERNEL);
++ if (!buffer)
++ return;
++
++ init_cdrom_command(&cgc, buffer, 32, CGC_DATA_READ);
+
+ cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
+ cgc.cmd[1] = 0;
+ cgc.cmd[2] = cgc.cmd[3] = 0; /* Starting Feature Number */
+- cgc.cmd[8] = sizeof(buffer); /* Allocation Length */
++ cgc.cmd[8] = 32; /* Allocation Length */
+ cgc.quiet = 1;
+
+ if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
+@@ -880,6 +913,7 @@ static void cdrom_mmc3_profile(struct cdrom_device_info *cdi)
+ mmc3_profile = (buffer[6] << 8) | buffer[7];
+
+ cdi->mmc3_profile = mmc3_profile;
++ kfree(buffer);
+ }
+
+ static int cdrom_is_dvd_rw(struct cdrom_device_info *cdi)
+@@ -1594,12 +1628,15 @@ static void setup_send_key(struct packet_command *cgc, unsigned agid, unsigned t
+ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
+ {
+ int ret;
+- u_char buf[20];
++ u_char *buf;
+ struct packet_command cgc;
+ struct cdrom_device_ops *cdo = cdi->ops;
+- rpc_state_t rpc_state;
++ rpc_state_t *rpc_state;
++
++ buf = kzalloc(20, GFP_KERNEL);
++ if (!buf)
++ return -ENOMEM;
+
+- memset(buf, 0, sizeof(buf));
+ init_cdrom_command(&cgc, buf, 0, CGC_DATA_READ);
+
+ switch (ai->type) {
+@@ -1610,7 +1647,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
+ setup_report_key(&cgc, ai->lsa.agid, 0);
+
+ if ((ret = cdo->generic_packet(cdi, &cgc)))
+- return ret;
++ goto err;
+
+ ai->lsa.agid = buf[7] >> 6;
+ /* Returning data, let host change state */
+@@ -1621,7 +1658,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
+ setup_report_key(&cgc, ai->lsk.agid, 2);
+
+ if ((ret = cdo->generic_packet(cdi, &cgc)))
+- return ret;
++ goto err;
+
+ copy_key(ai->lsk.key, &buf[4]);
+ /* Returning data, let host change state */
+@@ -1632,7 +1669,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
+ setup_report_key(&cgc, ai->lsc.agid, 1);
+
+ if ((ret = cdo->generic_packet(cdi, &cgc)))
+- return ret;
++ goto err;
+
+ copy_chal(ai->lsc.chal, &buf[4]);
+ /* Returning data, let host change state */
+@@ -1649,7 +1686,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
+ cgc.cmd[2] = ai->lstk.lba >> 24;
+
+ if ((ret = cdo->generic_packet(cdi, &cgc)))
+- return ret;
++ goto err;
+
+ ai->lstk.cpm = (buf[4] >> 7) & 1;
+ ai->lstk.cp_sec = (buf[4] >> 6) & 1;
+@@ -1663,7 +1700,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
+ setup_report_key(&cgc, ai->lsasf.agid, 5);
+
+ if ((ret = cdo->generic_packet(cdi, &cgc)))
+- return ret;
++ goto err;
+
+ ai->lsasf.asf = buf[7] & 1;
+ break;
+@@ -1676,7 +1713,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
+ copy_chal(&buf[4], ai->hsc.chal);
+
+ if ((ret = cdo->generic_packet(cdi, &cgc)))
+- return ret;
++ goto err;
+
+ ai->type = DVD_LU_SEND_KEY1;
+ break;
+@@ -1689,7 +1726,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
+
+ if ((ret = cdo->generic_packet(cdi, &cgc))) {
+ ai->type = DVD_AUTH_FAILURE;
+- return ret;
++ goto err;
+ }
+ ai->type = DVD_AUTH_ESTABLISHED;
+ break;
+@@ -1700,24 +1737,23 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
+ cdinfo(CD_DVD, "entering DVD_INVALIDATE_AGID\n");
+ setup_report_key(&cgc, ai->lsa.agid, 0x3f);
+ if ((ret = cdo->generic_packet(cdi, &cgc)))
+- return ret;
++ goto err;
+ break;
+
+ /* Get region settings */
+ case DVD_LU_SEND_RPC_STATE:
+ cdinfo(CD_DVD, "entering DVD_LU_SEND_RPC_STATE\n");
+ setup_report_key(&cgc, 0, 8);
+- memset(&rpc_state, 0, sizeof(rpc_state_t));
+- cgc.buffer = (char *) &rpc_state;
+
+ if ((ret = cdo->generic_packet(cdi, &cgc)))
+- return ret;
++ goto err;
+
+- ai->lrpcs.type = rpc_state.type_code;
+- ai->lrpcs.vra = rpc_state.vra;
+- ai->lrpcs.ucca = rpc_state.ucca;
+- ai->lrpcs.region_mask = rpc_state.region_mask;
+- ai->lrpcs.rpc_scheme = rpc_state.rpc_scheme;
++ rpc_state = (rpc_state_t *)buf;
++ ai->lrpcs.type = rpc_state->type_code;
++ ai->lrpcs.vra = rpc_state->vra;
++ ai->lrpcs.ucca = rpc_state->ucca;
++ ai->lrpcs.region_mask = rpc_state->region_mask;
++ ai->lrpcs.rpc_scheme = rpc_state->rpc_scheme;
+ break;
+
+ /* Set region settings */
+@@ -1728,20 +1764,23 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
+ buf[4] = ai->hrpcs.pdrc;
+
+ if ((ret = cdo->generic_packet(cdi, &cgc)))
+- return ret;
++ goto err;
+ break;
+
+ default:
+ cdinfo(CD_WARNING, "Invalid DVD key ioctl (%d)\n", ai->type);
+- return -ENOTTY;
++ ret = -ENOTTY;
++ goto err;
+ }
+-
+- return 0;
++ ret = 0;
++err:
++ kfree(buf);
++ return ret;
+ }
+
+ static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
+ {
+- unsigned char buf[21], *base;
++ unsigned char *buf, *base;
+ struct dvd_layer *layer;
+ struct packet_command cgc;
+ struct cdrom_device_ops *cdo = cdi->ops;
+@@ -1750,7 +1789,11 @@ static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
+ if (layer_num >= DVD_LAYERS)
+ return -EINVAL;
+
+- init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
++ buf = kmalloc(21, GFP_KERNEL);
++ if (!buf)
++ return -ENOMEM;
++
++ init_cdrom_command(&cgc, buf, 21, CGC_DATA_READ);
+ cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
+ cgc.cmd[6] = layer_num;
+ cgc.cmd[7] = s->type;
+@@ -1762,7 +1805,7 @@ static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
+ cgc.quiet = 1;
+
+ if ((ret = cdo->generic_packet(cdi, &cgc)))
+- return ret;
++ goto err;
+
+ base = &buf[4];
+ layer = &s->physical.layer[layer_num];
+@@ -1786,17 +1829,24 @@ static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
+ layer->end_sector_l0 = base[13] << 16 | base[14] << 8 | base[15];
+ layer->bca = base[16] >> 7;
+
+- return 0;
++ ret = 0;
++err:
++ kfree(buf);
++ return ret;
+ }
+
+ static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s)
+ {
+ int ret;
+- u_char buf[8];
++ u_char *buf;
+ struct packet_command cgc;
+ struct cdrom_device_ops *cdo = cdi->ops;
+
+- init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
++ buf = kmalloc(8, GFP_KERNEL);
++ if (!buf)
++ return -ENOMEM;
++
++ init_cdrom_command(&cgc, buf, 8, CGC_DATA_READ);
+ cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
+ cgc.cmd[6] = s->copyright.layer_num;
+ cgc.cmd[7] = s->type;
+@@ -1804,12 +1854,15 @@ static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s)
+ cgc.cmd[9] = cgc.buflen & 0xff;
+
+ if ((ret = cdo->generic_packet(cdi, &cgc)))
+- return ret;
++ goto err;
+
+ s->copyright.cpst = buf[4];
+ s->copyright.rmi = buf[5];
+
+- return 0;
++ ret = 0;
++err:
++ kfree(buf);
++ return ret;
+ }
+
+ static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s)
+@@ -1841,26 +1894,33 @@ static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s)
+ static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s)
+ {
+ int ret;
+- u_char buf[4 + 188];
++ u_char *buf;
+ struct packet_command cgc;
+ struct cdrom_device_ops *cdo = cdi->ops;
+
+- init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
++ buf = kmalloc(4 + 188, GFP_KERNEL);
++ if (!buf)
++ return -ENOMEM;
++
++ init_cdrom_command(&cgc, buf, 4 + 188, CGC_DATA_READ);
+ cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
+ cgc.cmd[7] = s->type;
+ cgc.cmd[9] = cgc.buflen & 0xff;
+
+ if ((ret = cdo->generic_packet(cdi, &cgc)))
+- return ret;
++ goto err;
+
+ s->bca.len = buf[0] << 8 | buf[1];
+ if (s->bca.len < 12 || s->bca.len > 188) {
+ cdinfo(CD_WARNING, "Received invalid BCA length (%d)\n", s->bca.len);
+- return -EIO;
++ ret = -EIO;
++ goto err;
+ }
+ memcpy(s->bca.value, &buf[4], s->bca.len);
+-
+- return 0;
++ ret = 0;
++err:
++ kfree(buf);
++ return ret;
+ }
+
+ static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s)
+@@ -1960,9 +2020,13 @@ static int cdrom_read_subchannel(struct cdrom_device_info *cdi,
+ {
+ struct cdrom_device_ops *cdo = cdi->ops;
+ struct packet_command cgc;
+- char buffer[32];
++ char *buffer;
+ int ret;
+
++ buffer = kmalloc(32, GFP_KERNEL);
++ if (!buffer)
++ return -ENOMEM;
++
+ init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
+ cgc.cmd[0] = GPCMD_READ_SUBCHANNEL;
+ cgc.cmd[1] = 2; /* MSF addressing */
+@@ -1971,7 +2035,7 @@ static int cdrom_read_subchannel(struct cdrom_device_info *cdi,
+ cgc.cmd[8] = 16;
+
+ if ((ret = cdo->generic_packet(cdi, &cgc)))
+- return ret;
++ goto err;
+
+ subchnl->cdsc_audiostatus = cgc.buffer[1];
+ subchnl->cdsc_format = CDROM_MSF;
+@@ -1986,7 +2050,10 @@ static int cdrom_read_subchannel(struct cdrom_device_info *cdi,
+ subchnl->cdsc_absaddr.msf.second = cgc.buffer[10];
+ subchnl->cdsc_absaddr.msf.frame = cgc.buffer[11];
+
+- return 0;
++ ret = 0;
++err:
++ kfree(buffer);
++ return ret;
+ }
+
+ /*
+@@ -3309,7 +3376,7 @@ static int cdrom_print_info(const char *header, int val, char *info,
+
+ *pos += ret;
+
+- for (cdi = topCdromPtr; cdi; cdi = cdi->next) {
++ list_for_each_entry(cdi, &cdrom_list, list) {
+ switch (option) {
+ case CTL_NAME:
+ ret = scnprintf(info + *pos, max_size - *pos,
+@@ -3430,7 +3497,8 @@ static void cdrom_update_settings(void)
+ {
+ struct cdrom_device_info *cdi;
+
+- for (cdi = topCdromPtr; cdi != NULL; cdi = cdi->next) {
++ mutex_lock(&cdrom_mutex);
++ list_for_each_entry(cdi, &cdrom_list, list) {
+ if (autoclose && CDROM_CAN(CDC_CLOSE_TRAY))
+ cdi->options |= CDO_AUTO_CLOSE;
+ else if (!autoclose)
+@@ -3448,6 +3516,7 @@ static void cdrom_update_settings(void)
+ else
+ cdi->options &= ~CDO_CHECK_TYPE;
+ }
++ mutex_unlock(&cdrom_mutex);
+ }
+
+ static int cdrom_sysctl_handler(ctl_table *ctl, int write, struct file * filp,
+@@ -3571,22 +3640,29 @@ static void cdrom_sysctl_unregister(void)
+ unregister_sysctl_table(cdrom_sysctl_header);
+ }
+
++#else /* CONFIG_SYSCTL */
++
++static void cdrom_sysctl_register(void)
++{
++}
++
++static void cdrom_sysctl_unregister(void)
++{
++}
++
+ #endif /* CONFIG_SYSCTL */
+
+ static int __init cdrom_init(void)
+ {
+-#ifdef CONFIG_SYSCTL
+ cdrom_sysctl_register();
+-#endif
++
+ return 0;
+ }
+
+ static void __exit cdrom_exit(void)
+ {
+ printk(KERN_INFO "Uniform CD-ROM driver unloaded\n");
+-#ifdef CONFIG_SYSCTL
+ cdrom_sysctl_unregister();
+-#endif
+ }
+
+ module_init(cdrom_init);
+diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
+index 4e2bbcc..71ec426 100644
+--- a/drivers/cdrom/gdrom.c
++++ b/drivers/cdrom/gdrom.c
+@@ -827,7 +827,9 @@ static int __devexit remove_gdrom(struct platform_device *devptr)
+ del_gendisk(gd.disk);
+ if (gdrom_major)
+ unregister_blkdev(gdrom_major, GDROM_DEV_NAME);
+- return unregister_cdrom(gd.cd_info);
++ unregister_cdrom(gd.cd_info);
++
++ return 0;
+ }
+
+ static struct platform_driver gdrom_driver = {
+diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
+index cac06bc..b74b6c2 100644
+--- a/drivers/cdrom/viocd.c
++++ b/drivers/cdrom/viocd.c
+@@ -650,10 +650,7 @@ static int viocd_remove(struct vio_dev *vdev)
+ {
+ struct disk_info *d = &viocd_diskinfo[vdev->unit_address];
+
+- if (unregister_cdrom(&d->viocd_info) != 0)
+- printk(VIOCD_KERN_WARNING
+- "Cannot unregister viocd CD-ROM %s!\n",
+- d->viocd_info.name);
++ unregister_cdrom(&d->viocd_info);
+ del_gendisk(d->viocd_disk);
+ blk_cleanup_queue(d->viocd_disk->queue);
+ put_disk(d->viocd_disk);
+diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
+index 47c6be8..2906ee7 100644
+--- a/drivers/char/Kconfig
++++ b/drivers/char/Kconfig
+@@ -481,6 +481,34 @@ config BRIQ_PANEL
+
+ It's safe to say N here.
+
++config BFIN_OTP
++ tristate "Blackfin On-Chip OTP Memory Support"
++ depends on BLACKFIN && (BF52x || BF54x)
++ default y
++ help
++ If you say Y here, you will get support for a character device
++ interface into the One Time Programmable memory pages that are
++ stored on the Blackfin processor. This will not get you access
++ to the secure memory pages however. You will need to write your
++ own secure code and reader for that.
++
++ To compile this driver as a module, choose M here: the module
++ will be called bfin-otp.
++
++ If unsure, it is safe to say Y.
++
++config BFIN_OTP_WRITE_ENABLE
++ bool "Enable writing support of OTP pages"
++ depends on BFIN_OTP
++ default n
++ help
++ If you say Y here, you will enable support for writing of the
++ OTP pages. This is dangerous by nature as you can only program
++ the pages once, so only enable this option when you actually
++ need it so as to not inadvertently clobber data.
++
++ If unsure, say N.
++
+ config PRINTER
+ tristate "Parallel printer support"
+ depends on PARPORT
+@@ -706,7 +734,7 @@ config NVRAM
+
+ config RTC
+ tristate "Enhanced Real Time Clock Support"
+- depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC && !FRV && !ARM && !SUPERH && !S390
++ depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC && !FRV && !ARM && !SUPERH && !S390 && !AVR32
+ ---help---
+ If you say Y here and create a character special file /dev/rtc with
+ major number 10 and minor number 135 using mknod ("man mknod"), you
+@@ -776,7 +804,7 @@ config SGI_IP27_RTC
+
+ config GEN_RTC
+ tristate "Generic /dev/rtc emulation"
+- depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH
++ depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH && !AVR32
+ ---help---
+ If you say Y here and create a character special file /dev/rtc with
+ major number 10 and minor number 135 using mknod ("man mknod"), you
+diff --git a/drivers/char/Makefile b/drivers/char/Makefile
+index 5407b76..4c1c584 100644
+--- a/drivers/char/Makefile
++++ b/drivers/char/Makefile
+@@ -59,6 +59,7 @@ obj-$(CONFIG_VIOTAPE) += viotape.o
+ obj-$(CONFIG_HVCS) += hvcs.o
+ obj-$(CONFIG_SGI_MBCS) += mbcs.o
+ obj-$(CONFIG_BRIQ_PANEL) += briq_panel.o
++obj-$(CONFIG_BFIN_OTP) += bfin-otp.o
+
+ obj-$(CONFIG_PRINTER) += lp.o
+ obj-$(CONFIG_TIPAR) += tipar.o
+diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
+index d286699..96bdb92 100644
+--- a/drivers/char/agp/amd-k7-agp.c
++++ b/drivers/char/agp/amd-k7-agp.c
+@@ -436,8 +436,9 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
+ system controller may experience noise due to strong drive strengths
+ */
+ if (agp_bridge->dev->device == PCI_DEVICE_ID_AMD_FE_GATE_7006) {
+- u8 cap_ptr=0;
+ struct pci_dev *gfxcard=NULL;
++
++ cap_ptr = 0;
+ while (!cap_ptr) {
+ gfxcard = pci_get_class(PCI_CLASS_DISPLAY_VGA<<8, gfxcard);
+ if (!gfxcard) {
+diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c
+index 55d7a82..857b262 100644
+--- a/drivers/char/agp/frontend.c
++++ b/drivers/char/agp/frontend.c
+@@ -967,7 +967,7 @@ int agpioc_chipset_flush_wrap(struct agp_file_private *priv)
+ return 0;
+ }
+
+-static int agp_ioctl(struct inode *inode, struct file *file,
++static long agp_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+ {
+ struct agp_file_private *curr_priv = file->private_data;
+@@ -1058,7 +1058,7 @@ static const struct file_operations agp_fops =
+ .llseek = no_llseek,
+ .read = agp_read,
+ .write = agp_write,
+- .ioctl = agp_ioctl,
++ .unlocked_ioctl = agp_ioctl,
+ #ifdef CONFIG_COMPAT
+ .compat_ioctl = compat_agp_ioctl,
+ #endif
+diff --git a/drivers/char/bfin-otp.c b/drivers/char/bfin-otp.c
+new file mode 100644
+index 0000000..0a01329
+--- /dev/null
++++ b/drivers/char/bfin-otp.c
+@@ -0,0 +1,189 @@
++/*
++ * Blackfin On-Chip OTP Memory Interface
++ * Supports BF52x/BF54x
++ *
++ * Copyright 2007-2008 Analog Devices Inc.
++ *
++ * Enter bugs at http://blackfin.uclinux.org/
++ *
++ * Licensed under the GPL-2 or later.
++ */
++
++#include <linux/device.h>
++#include <linux/errno.h>
++#include <linux/fs.h>
++#include <linux/init.h>
++#include <linux/miscdevice.h>
++#include <linux/module.h>
++#include <linux/mutex.h>
++#include <linux/types.h>
++
++#include <asm/blackfin.h>
++#include <asm/uaccess.h>
++
++#define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args)
++#define stampit() stamp("here i am")
++#define pr_init(fmt, args...) ({ static const __initconst char __fmt[] = fmt; printk(__fmt, ## args); })
++
++#define DRIVER_NAME "bfin-otp"
++#define PFX DRIVER_NAME ": "
++
++static DEFINE_MUTEX(bfin_otp_lock);
++
++/* OTP Boot ROM functions */
++#define _BOOTROM_OTP_COMMAND 0xEF000018
++#define _BOOTROM_OTP_READ 0xEF00001A
++#define _BOOTROM_OTP_WRITE 0xEF00001C
++
++static u32 (* const otp_command)(u32 command, u32 value) = (void *)_BOOTROM_OTP_COMMAND;
++static u32 (* const otp_read)(u32 page, u32 flags, u64 *page_content) = (void *)_BOOTROM_OTP_READ;
++static u32 (* const otp_write)(u32 page, u32 flags, u64 *page_content) = (void *)_BOOTROM_OTP_WRITE;
++
++/* otp_command(): defines for "command" */
++#define OTP_INIT 0x00000001
++#define OTP_CLOSE 0x00000002
++
++/* otp_{read,write}(): defines for "flags" */
++#define OTP_LOWER_HALF 0x00000000 /* select upper/lower 64-bit half (bit 0) */
++#define OTP_UPPER_HALF 0x00000001
++#define OTP_NO_ECC 0x00000010 /* do not use ECC */
++#define OTP_LOCK 0x00000020 /* sets page protection bit for page */
++#define OTP_ACCESS_READ 0x00001000
++#define OTP_ACCESS_READWRITE 0x00002000
++
++/* Return values for all functions */
++#define OTP_SUCCESS 0x00000000
++#define OTP_MASTER_ERROR 0x001
++#define OTP_WRITE_ERROR 0x003
++#define OTP_READ_ERROR 0x005
++#define OTP_ACC_VIO_ERROR 0x009
++#define OTP_DATA_MULT_ERROR 0x011
++#define OTP_ECC_MULT_ERROR 0x021
++#define OTP_PREV_WR_ERROR 0x041
++#define OTP_DATA_SB_WARN 0x100
++#define OTP_ECC_SB_WARN 0x200
++
++/**
++ * bfin_otp_read - Read OTP pages
++ *
++ * All reads must be in half page chunks (half page == 64 bits).
++ */
++static ssize_t bfin_otp_read(struct file *file, char __user *buff, size_t count, loff_t *pos)
++{
++ ssize_t bytes_done;
++ u32 page, flags, ret;
++ u64 content;
++
++ stampit();
++
++ if (count % sizeof(u64))
++ return -EMSGSIZE;
++
++ if (mutex_lock_interruptible(&bfin_otp_lock))
++ return -ERESTARTSYS;
++
++ bytes_done = 0;
++ page = *pos / (sizeof(u64) * 2);
++ while (bytes_done < count) {
++ flags = (*pos % (sizeof(u64) * 2) ? OTP_UPPER_HALF : OTP_LOWER_HALF);
++ stamp("processing page %i (%s)", page, (flags == OTP_UPPER_HALF ? "upper" : "lower"));
++ ret = otp_read(page, flags, &content);
++ if (ret & OTP_MASTER_ERROR) {
++ bytes_done = -EIO;
++ break;
++ }
++ if (copy_to_user(buff + bytes_done, &content, sizeof(content))) {
++ bytes_done = -EFAULT;
++ break;
++ }
++ if (flags == OTP_UPPER_HALF)
++ ++page;
++ bytes_done += sizeof(content);
++ *pos += sizeof(content);
++ }
++
++ mutex_unlock(&bfin_otp_lock);
++
++ return bytes_done;
++}
++
++#ifdef CONFIG_BFIN_OTP_WRITE_ENABLE
++/**
++ * bfin_otp_write - Write OTP pages
++ *
++ * All writes must be in half page chunks (half page == 64 bits).
++ */
++static ssize_t bfin_otp_write(struct file *filp, const char __user *buff, size_t count, loff_t *pos)
++{
++ stampit();
++
++ if (count % sizeof(u64))
++ return -EMSGSIZE;
++
++ if (mutex_lock_interruptible(&bfin_otp_lock))
++ return -ERESTARTSYS;
++
++ /* need otp_init() documentation before this can be implemented */
++
++ mutex_unlock(&bfin_otp_lock);
++
++ return -EINVAL;
++}
++#else
++# define bfin_otp_write NULL
++#endif
++
++static struct file_operations bfin_otp_fops = {
++ .owner = THIS_MODULE,
++ .read = bfin_otp_read,
++ .write = bfin_otp_write,
++};
++
++static struct miscdevice bfin_otp_misc_device = {
++ .minor = MISC_DYNAMIC_MINOR,
++ .name = DRIVER_NAME,
++ .fops = &bfin_otp_fops,
++};
++
++/**
++ * bfin_otp_init - Initialize module
++ *
++ * Registers the device and notifier handler. Actual device
++ * initialization is handled by bfin_otp_open().
++ */
++static int __init bfin_otp_init(void)
++{
++ int ret;
++
++ stampit();
++
++ ret = misc_register(&bfin_otp_misc_device);
++ if (ret) {
++ pr_init(KERN_ERR PFX "unable to register a misc device\n");
++ return ret;
++ }
++
++ pr_init(KERN_INFO PFX "initialized\n");
++
++ return 0;
++}
++
++/**
++ * bfin_otp_exit - Deinitialize module
++ *
++ * Unregisters the device and notifier handler. Actual device
++ * deinitialization is handled by bfin_otp_close().
++ */
++static void __exit bfin_otp_exit(void)
++{
++ stampit();
++
++ misc_deregister(&bfin_otp_misc_device);
++}
++
++module_init(bfin_otp_init);
++module_exit(bfin_otp_exit);
++
++MODULE_AUTHOR("Mike Frysinger <vapier at gentoo.org>");
++MODULE_DESCRIPTION("Blackfin OTP Memory Interface");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c
+index 141f4df..b710426 100644
+--- a/drivers/char/drm/ati_pcigart.c
++++ b/drivers/char/drm/ati_pcigart.c
+@@ -167,13 +167,6 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
+ page_base += ATI_PCIGART_PAGE_SIZE;
+ }
+ }
+-
+- if (gart_info->gart_table_location == DRM_ATI_GART_MAIN)
+- dma_sync_single_for_device(&dev->pdev->dev,
+- bus_address,
+- max_pages * sizeof(u32),
+- PCI_DMA_TODEVICE);
+-
+ ret = 1;
+
+ #if defined(__i386__) || defined(__x86_64__)
+diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
+index 3a05c6d..6874f31 100644
+--- a/drivers/char/drm/drm.h
++++ b/drivers/char/drm/drm.h
+@@ -471,6 +471,7 @@ struct drm_irq_busid {
+ enum drm_vblank_seq_type {
+ _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
+ _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
++ _DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */
+ _DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */
+ _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */
+ _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
+@@ -503,6 +504,21 @@ union drm_wait_vblank {
+ struct drm_wait_vblank_reply reply;
+ };
+
++enum drm_modeset_ctl_cmd {
++ _DRM_PRE_MODESET = 1,
++ _DRM_POST_MODESET = 2,
++};
++
++/**
++ * DRM_IOCTL_MODESET_CTL ioctl argument type
++ *
++ * \sa drmModesetCtl().
++ */
++struct drm_modeset_ctl {
++ unsigned long arg;
++ enum drm_modeset_ctl_cmd cmd;
++};
++
+ /**
+ * DRM_IOCTL_AGP_ENABLE ioctl argument type.
+ *
+@@ -587,6 +603,7 @@ struct drm_set_version {
+ #define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, struct drm_client)
+ #define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats)
+ #define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version)
++#define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl)
+
+ #define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique)
+ #define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth)
+diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
+index 8ea9dd1..ecee354 100644
+--- a/drivers/char/drm/drmP.h
++++ b/drivers/char/drm/drmP.h
+@@ -100,10 +100,8 @@ struct drm_device;
+ #define DRIVER_HAVE_DMA 0x20
+ #define DRIVER_HAVE_IRQ 0x40
+ #define DRIVER_IRQ_SHARED 0x80
+-#define DRIVER_IRQ_VBL 0x100
+ #define DRIVER_DMA_QUEUE 0x200
+ #define DRIVER_FB_DMA 0x400
+-#define DRIVER_IRQ_VBL2 0x800
+
+ /***********************************************************************/
+ /** \name Begin the DRM... */
+@@ -379,13 +377,12 @@ struct drm_buf_entry {
+ struct drm_file {
+ int authenticated;
+ int master;
+- int minor;
+ pid_t pid;
+ uid_t uid;
+ drm_magic_t magic;
+ unsigned long ioctl_count;
+ struct list_head lhead;
+- struct drm_head *head;
++ struct drm_minor *minor;
+ int remove_auth_on_close;
+ unsigned long lock_count;
+ struct file *filp;
+@@ -580,10 +577,52 @@ struct drm_driver {
+ int (*context_dtor) (struct drm_device *dev, int context);
+ int (*kernel_context_switch) (struct drm_device *dev, int old,
+ int new);
+- void (*kernel_context_switch_unlock) (struct drm_device *dev);
+- int (*vblank_wait) (struct drm_device *dev, unsigned int *sequence);
+- int (*vblank_wait2) (struct drm_device *dev, unsigned int *sequence);
+- int (*dri_library_name) (struct drm_device *dev, char *buf);
++ void (*kernel_context_switch_unlock) (struct drm_device * dev);
++ /**
++ * get_vblank_counter - get raw hardware vblank counter
++ * @dev: DRM device
++ * @crtc: counter to fetch
++ *
++ * Driver callback for fetching a raw hardware vblank counter
++ * for @crtc. If a device doesn't have a hardware counter, the
++ * driver can simply return the value of drm_vblank_count and
++ * make the enable_vblank() and disable_vblank() hooks into no-ops,
++ * leaving interrupts enabled at all times.
++ *
++ * Wraparound handling and loss of events due to modesetting is dealt
++ * with in the DRM core code.
++ *
++ * RETURNS
++ * Raw vblank counter value.
++ */
++ u32 (*get_vblank_counter) (struct drm_device *dev, int crtc);
++
++ /**
++ * enable_vblank - enable vblank interrupt events
++ * @dev: DRM device
++ * @crtc: which irq to enable
++ *
++ * Enable vblank interrupts for @crtc. If the device doesn't have
++ * a hardware vblank counter, this routine should be a no-op, since
++ * interrupts will have to stay on to keep the count accurate.
++ *
++ * RETURNS
++ * Zero on success, appropriate errno if the given @crtc's vblank
++ * interrupt cannot be enabled.
++ */
++ int (*enable_vblank) (struct drm_device *dev, int crtc);
++
++ /**
++ * disable_vblank - disable vblank interrupt events
++ * @dev: DRM device
++ * @crtc: which irq to enable
++ *
++ * Disable vblank interrupts for @crtc. If the device doesn't have
++ * a hardware vblank counter, this routine should be a no-op, since
++ * interrupts will have to stay on to keep the count accurate.
++ */
++ void (*disable_vblank) (struct drm_device *dev, int crtc);
++ int (*dri_library_name) (struct drm_device *dev, char * buf);
+
+ /**
+ * Called by \c drm_device_is_agp. Typically used to determine if a
+@@ -602,7 +641,7 @@ struct drm_driver {
+
+ irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
+ void (*irq_preinstall) (struct drm_device *dev);
+- void (*irq_postinstall) (struct drm_device *dev);
++ int (*irq_postinstall) (struct drm_device *dev);
+ void (*irq_uninstall) (struct drm_device *dev);
+ void (*reclaim_buffers) (struct drm_device *dev,
+ struct drm_file * file_priv);
+@@ -630,17 +669,19 @@ struct drm_driver {
+ struct pci_driver pci_driver;
+ };
+
++#define DRM_MINOR_UNASSIGNED 0
++#define DRM_MINOR_LEGACY 1
++
+ /**
+- * DRM head structure. This structure represent a video head on a card
+- * that may contain multiple heads. Embed one per head of these in the
+- * private drm_device structure.
++ * DRM minor structure. This structure represents a drm minor number.
+ */
+-struct drm_head {
+- int minor; /**< Minor device number */
++struct drm_minor {
++ int index; /**< Minor device number */
++ int type; /**< Control or render */
++ dev_t device; /**< Device number for mknod */
++ struct device kdev; /**< Linux device */
+ struct drm_device *dev;
+ struct proc_dir_entry *dev_root; /**< proc directory entry */
+- dev_t device; /**< Device number for mknod */
+- struct class_device *dev_class;
+ };
+
+ /**
+@@ -648,7 +689,6 @@ struct drm_head {
+ * may contain multiple heads.
+ */
+ struct drm_device {
+- struct device dev; /**< Linux device */
+ char *unique; /**< Unique identifier: e.g., busid */
+ int unique_len; /**< Length of unique field */
+ char *devname; /**< For /proc/interrupts */
+@@ -730,13 +770,21 @@ struct drm_device {
+ /** \name VBLANK IRQ support */
+ /*@{ */
+
+- wait_queue_head_t vbl_queue; /**< VBLANK wait queue */
+- atomic_t vbl_received;
+- atomic_t vbl_received2; /**< number of secondary VBLANK interrupts */
++ wait_queue_head_t *vbl_queue; /**< VBLANK wait queue */
++ atomic_t *_vblank_count; /**< number of VBLANK interrupts (driver must alloc the right number of counters) */
+ spinlock_t vbl_lock;
+- struct list_head vbl_sigs; /**< signal list to send on VBLANK */
+- struct list_head vbl_sigs2; /**< signals to send on secondary VBLANK */
+- unsigned int vbl_pending;
++ struct list_head *vbl_sigs; /**< signal list to send on VBLANK */
++ atomic_t vbl_signal_pending; /* number of signals pending on all crtcs*/
++ atomic_t *vblank_refcount; /* number of users of vblank interrupts per crtc */
++ u32 *last_vblank; /* protected by dev->vbl_lock, used */
++ /* for wraparound handling */
++ u32 *vblank_offset; /* used to track how many vblanks */
++ int *vblank_enabled; /* so we don't call enable more than
++ once per disable */
++ u32 *vblank_premodeset; /* were lost during modeset */
++ struct timer_list vblank_disable_timer;
++
++ unsigned long max_vblank_count; /**< size of vblank counter register */
+ spinlock_t tasklet_lock; /**< For drm_locked_tasklet */
+ void (*locked_tasklet_func)(struct drm_device *dev);
+
+@@ -756,6 +804,7 @@ struct drm_device {
+ #ifdef __alpha__
+ struct pci_controller *hose;
+ #endif
++ int num_crtcs; /**< Number of CRTCs on this device */
+ struct drm_sg_mem *sg; /**< Scatter gather memory */
+ void *dev_private; /**< device private data */
+ struct drm_sigdata sigdata; /**< For block_all_signals */
+@@ -764,7 +813,7 @@ struct drm_device {
+ struct drm_driver *driver;
+ drm_local_map_t *agp_buffer_map;
+ unsigned int agp_buffer_token;
+- struct drm_head primary; /**< primary screen head */
++ struct drm_minor *primary; /**< render type primary screen head */
+
+ /** \name Drawable information */
+ /*@{ */
+@@ -990,11 +1039,19 @@ extern void drm_driver_irq_preinstall(struct drm_device *dev);
+ extern void drm_driver_irq_postinstall(struct drm_device *dev);
+ extern void drm_driver_irq_uninstall(struct drm_device *dev);
+
+-extern int drm_wait_vblank(struct drm_device *dev, void *data,
+- struct drm_file *file_priv);
+-extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
+-extern void drm_vbl_send_signals(struct drm_device *dev);
++extern int drm_vblank_init(struct drm_device *dev, int num_crtcs);
++extern int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *filp);
++extern int drm_vblank_wait(struct drm_device * dev, unsigned int *vbl_seq);
+ extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*));
++extern u32 drm_vblank_count(struct drm_device *dev, int crtc);
++extern void drm_update_vblank_count(struct drm_device *dev, int crtc);
++extern void drm_handle_vblank(struct drm_device *dev, int crtc);
++extern int drm_vblank_get(struct drm_device *dev, int crtc);
++extern void drm_vblank_put(struct drm_device *dev, int crtc);
++
++ /* Modesetting support */
++extern int drm_modeset_ctl(struct drm_device *dev, void *data,
++ struct drm_file *file_priv);
+
+ /* AGP/GART support (drm_agpsupport.h) */
+ extern struct drm_agp_head *drm_agp_init(struct drm_device *dev);
+@@ -1031,23 +1088,20 @@ extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle);
+ extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
+ struct drm_driver *driver);
+ extern int drm_put_dev(struct drm_device *dev);
+-extern int drm_put_head(struct drm_head *head);
++extern int drm_put_minor(struct drm_minor **minor);
+ extern unsigned int drm_debug;
+-extern unsigned int drm_cards_limit;
+-extern struct drm_head **drm_heads;
++
+ extern struct class *drm_class;
+ extern struct proc_dir_entry *drm_proc_root;
+
++extern struct idr drm_minors_idr;
++
+ extern drm_local_map_t *drm_getsarea(struct drm_device *dev);
+
+ /* Proc support (drm_proc.h) */
+-extern int drm_proc_init(struct drm_device *dev,
+- int minor,
+- struct proc_dir_entry *root,
+- struct proc_dir_entry **dev_root);
+-extern int drm_proc_cleanup(int minor,
+- struct proc_dir_entry *root,
+- struct proc_dir_entry *dev_root);
++extern int drm_proc_init(struct drm_minor *minor, int minor_id,
++ struct proc_dir_entry *root);
++extern int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root);
+
+ /* Scatter Gather Support (drm_scatter.h) */
+ extern void drm_sg_cleanup(struct drm_sg_mem * entry);
+@@ -1072,8 +1126,8 @@ extern void drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah);
+ struct drm_sysfs_class;
+ extern struct class *drm_sysfs_create(struct module *owner, char *name);
+ extern void drm_sysfs_destroy(void);
+-extern int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head);
+-extern void drm_sysfs_device_remove(struct drm_device *dev);
++extern int drm_sysfs_device_add(struct drm_minor *minor);
++extern void drm_sysfs_device_remove(struct drm_minor *minor);
+
+ /*
+ * Basic memory manager support (drm_mm.c)
+diff --git a/drivers/char/drm/drm_agpsupport.c b/drivers/char/drm/drm_agpsupport.c
+index 9468c78..aefa5ac 100644
+--- a/drivers/char/drm/drm_agpsupport.c
++++ b/drivers/char/drm/drm_agpsupport.c
+@@ -122,7 +122,7 @@ EXPORT_SYMBOL(drm_agp_acquire);
+ int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+ {
+- return drm_agp_acquire((struct drm_device *) file_priv->head->dev);
++ return drm_agp_acquire((struct drm_device *) file_priv->minor->dev);
+ }
+
+ /**
+diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
+index 0e7af53..fc54140 100644
+--- a/drivers/char/drm/drm_drv.c
++++ b/drivers/char/drm/drm_drv.c
+@@ -313,35 +313,36 @@ static void drm_cleanup(struct drm_device * dev)
+ drm_ht_remove(&dev->map_hash);
+ drm_ctxbitmap_cleanup(dev);
+
+- drm_put_head(&dev->primary);
++ drm_put_minor(&dev->primary);
+ if (drm_put_dev(dev))
+ DRM_ERROR("Cannot unload module\n");
+ }
+
+-void drm_exit(struct drm_driver *driver)
++int drm_minors_cleanup(int id, void *ptr, void *data)
+ {
+- int i;
+- struct drm_device *dev = NULL;
+- struct drm_head *head;
++ struct drm_minor *minor = ptr;
++ struct drm_device *dev;
++ struct drm_driver *driver = data;
++
++ dev = minor->dev;
++ if (minor->dev->driver != driver)
++ return 0;
++
++ if (minor->type != DRM_MINOR_LEGACY)
++ return 0;
+
++ if (dev)
++ pci_dev_put(dev->pdev);
++ drm_cleanup(dev);
++ return 1;
++}
++
++void drm_exit(struct drm_driver *driver)
++{
+ DRM_DEBUG("\n");
+
+- for (i = 0; i < drm_cards_limit; i++) {
+- head = drm_heads[i];
+- if (!head)
+- continue;
+- if (!head->dev)
+- continue;
+- if (head->dev->driver != driver)
+- continue;
+- dev = head->dev;
+- if (dev) {
+- /* release the pci driver */
+- if (dev->pdev)
+- pci_dev_put(dev->pdev);
+- drm_cleanup(dev);
+- }
+- }
++ idr_for_each(&drm_minors_idr, &drm_minors_cleanup, driver);
++
+ DRM_INFO("Module unloaded\n");
+ }
+
+@@ -357,13 +358,7 @@ static int __init drm_core_init(void)
+ {
+ int ret = -ENOMEM;
+
+- drm_cards_limit =
+- (drm_cards_limit <
+- DRM_MAX_MINOR + 1 ? drm_cards_limit : DRM_MAX_MINOR + 1);
+- drm_heads =
+- drm_calloc(drm_cards_limit, sizeof(*drm_heads), DRM_MEM_STUB);
+- if (!drm_heads)
+- goto err_p1;
++ idr_init(&drm_minors_idr);
+
+ if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
+ goto err_p1;
+@@ -391,7 +386,8 @@ err_p3:
+ drm_sysfs_destroy();
+ err_p2:
+ unregister_chrdev(DRM_MAJOR, "drm");
+- drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB);
++
++ idr_destroy(&drm_minors_idr);
+ err_p1:
+ return ret;
+ }
+@@ -403,7 +399,7 @@ static void __exit drm_core_exit(void)
+
+ unregister_chrdev(DRM_MAJOR, "drm");
+
+- drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB);
++ idr_destroy(&drm_minors_idr);
+ }
+
+ module_init(drm_core_init);
+@@ -452,7 +448,7 @@ int drm_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+ {
+ struct drm_file *file_priv = filp->private_data;
+- struct drm_device *dev = file_priv->head->dev;
++ struct drm_device *dev = file_priv->minor->dev;
+ struct drm_ioctl_desc *ioctl;
+ drm_ioctl_t *func;
+ unsigned int nr = DRM_IOCTL_NR(cmd);
+@@ -465,7 +461,7 @@ int drm_ioctl(struct inode *inode, struct file *filp,
+
+ DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
+ task_pid_nr(current), cmd, nr,
+- (long)old_encode_dev(file_priv->head->device),
++ (long)old_encode_dev(file_priv->minor->device),
+ file_priv->authenticated);
+
+ if ((nr >= DRM_CORE_IOCTL_COUNT) &&
+diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
+index f09d4b5..68f0da8 100644
+--- a/drivers/char/drm/drm_fops.c
++++ b/drivers/char/drm/drm_fops.c
+@@ -129,16 +129,15 @@ static int drm_setup(struct drm_device * dev)
+ int drm_open(struct inode *inode, struct file *filp)
+ {
+ struct drm_device *dev = NULL;
+- int minor = iminor(inode);
++ int minor_id = iminor(inode);
++ struct drm_minor *minor;
+ int retcode = 0;
+
+- if (!((minor >= 0) && (minor < drm_cards_limit)))
++ minor = idr_find(&drm_minors_idr, minor_id);
++ if (!minor)
+ return -ENODEV;
+
+- if (!drm_heads[minor])
+- return -ENODEV;
+-
+- if (!(dev = drm_heads[minor]->dev))
++ if (!(dev = minor->dev))
+ return -ENODEV;
+
+ retcode = drm_open_helper(inode, filp, dev);
+@@ -168,19 +167,18 @@ EXPORT_SYMBOL(drm_open);
+ int drm_stub_open(struct inode *inode, struct file *filp)
+ {
+ struct drm_device *dev = NULL;
+- int minor = iminor(inode);
++ struct drm_minor *minor;
++ int minor_id = iminor(inode);
+ int err = -ENODEV;
+ const struct file_operations *old_fops;
+
+ DRM_DEBUG("\n");
+
+- if (!((minor >= 0) && (minor < drm_cards_limit)))
+- return -ENODEV;
+-
+- if (!drm_heads[minor])
++ minor = idr_find(&drm_minors_idr, minor_id);
++ if (!minor)
+ return -ENODEV;
+
+- if (!(dev = drm_heads[minor]->dev))
++ if (!(dev = minor->dev))
+ return -ENODEV;
+
+ old_fops = filp->f_op;
+@@ -225,7 +223,7 @@ static int drm_cpu_valid(void)
+ static int drm_open_helper(struct inode *inode, struct file *filp,
+ struct drm_device * dev)
+ {
+- int minor = iminor(inode);
++ int minor_id = iminor(inode);
+ struct drm_file *priv;
+ int ret;
+
+@@ -234,7 +232,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
+ if (!drm_cpu_valid())
+ return -EINVAL;
+
+- DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor);
++ DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor_id);
+
+ priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
+ if (!priv)
+@@ -245,8 +243,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
+ priv->filp = filp;
+ priv->uid = current->euid;
+ priv->pid = task_pid_nr(current);
+- priv->minor = minor;
+- priv->head = drm_heads[minor];
++ priv->minor = idr_find(&drm_minors_idr, minor_id);
+ priv->ioctl_count = 0;
+ /* for compatibility root is always authenticated */
+ priv->authenticated = capable(CAP_SYS_ADMIN);
+@@ -297,11 +294,11 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
+ int drm_fasync(int fd, struct file *filp, int on)
+ {
+ struct drm_file *priv = filp->private_data;
+- struct drm_device *dev = priv->head->dev;
++ struct drm_device *dev = priv->minor->dev;
+ int retcode;
+
+ DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,
+- (long)old_encode_dev(priv->head->device));
++ (long)old_encode_dev(priv->minor->device));
+ retcode = fasync_helper(fd, filp, on, &dev->buf_async);
+ if (retcode < 0)
+ return retcode;
+@@ -324,7 +321,7 @@ EXPORT_SYMBOL(drm_fasync);
+ int drm_release(struct inode *inode, struct file *filp)
+ {
+ struct drm_file *file_priv = filp->private_data;
+- struct drm_device *dev = file_priv->head->dev;
++ struct drm_device *dev = file_priv->minor->dev;
+ int retcode = 0;
+ unsigned long irqflags;
+
+@@ -341,14 +338,14 @@ int drm_release(struct inode *inode, struct file *filp)
+
+ DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
+ task_pid_nr(current),
+- (long)old_encode_dev(file_priv->head->device),
++ (long)old_encode_dev(file_priv->minor->device),
+ dev->open_count);
+
+ if (dev->driver->reclaim_buffers_locked && dev->lock.hw_lock) {
+ if (drm_i_have_hw_lock(dev, file_priv)) {
+ dev->driver->reclaim_buffers_locked(dev, file_priv);
+ } else {
+- unsigned long _end=jiffies + 3*DRM_HZ;
++ unsigned long endtime = jiffies + 3 * DRM_HZ;
+ int locked = 0;
+
+ drm_idlelock_take(&dev->lock);
+@@ -366,7 +363,7 @@ int drm_release(struct inode *inode, struct file *filp)
+ if (locked)
+ break;
+ schedule();
+- } while (!time_after_eq(jiffies, _end));
++ } while (!time_after_eq(jiffies, endtime));
+
+ if (!locked) {
+ DRM_ERROR("reclaim_buffers_locked() deadlock. Please rework this\n"
+diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c
+index 089c015..286f9d6 100644
+--- a/drivers/char/drm/drm_irq.c
++++ b/drivers/char/drm/drm_irq.c
+@@ -71,6 +71,117 @@ int drm_irq_by_busid(struct drm_device *dev, void *data,
+ return 0;
+ }
+
++static void vblank_disable_fn(unsigned long arg)
++{
++ struct drm_device *dev = (struct drm_device *)arg;
++ unsigned long irqflags;
++ int i;
++
++ for (i = 0; i < dev->num_crtcs; i++) {
++ spin_lock_irqsave(&dev->vbl_lock, irqflags);
++ if (atomic_read(&dev->vblank_refcount[i]) == 0 &&
++ dev->vblank_enabled[i]) {
++ dev->driver->disable_vblank(dev, i);
++ dev->vblank_enabled[i] = 0;
++ }
++ spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
++ }
++}
++
++static void drm_vblank_cleanup(struct drm_device *dev)
++{
++ /* Bail if the driver didn't call drm_vblank_init() */
++ if (dev->num_crtcs == 0)
++ return;
++
++ del_timer(&dev->vblank_disable_timer);
++
++ vblank_disable_fn((unsigned long)dev);
++
++ drm_free(dev->vbl_queue, sizeof(*dev->vbl_queue) * dev->num_crtcs,
++ DRM_MEM_DRIVER);
++ drm_free(dev->vbl_sigs, sizeof(*dev->vbl_sigs) * dev->num_crtcs,
++ DRM_MEM_DRIVER);
++ drm_free(dev->_vblank_count, sizeof(*dev->_vblank_count) *
++ dev->num_crtcs, DRM_MEM_DRIVER);
++ drm_free(dev->vblank_refcount, sizeof(*dev->vblank_refcount) *
++ dev->num_crtcs, DRM_MEM_DRIVER);
++ drm_free(dev->vblank_enabled, sizeof(*dev->vblank_enabled) *
++ dev->num_crtcs, DRM_MEM_DRIVER);
++ drm_free(dev->last_vblank, sizeof(*dev->last_vblank) * dev->num_crtcs,
++ DRM_MEM_DRIVER);
++ drm_free(dev->vblank_premodeset, sizeof(*dev->vblank_premodeset) *
++ dev->num_crtcs, DRM_MEM_DRIVER);
++ drm_free(dev->vblank_offset, sizeof(*dev->vblank_offset) * dev->num_crtcs,
++ DRM_MEM_DRIVER);
++
++ dev->num_crtcs = 0;
++}
++
++int drm_vblank_init(struct drm_device *dev, int num_crtcs)
++{
++ int i, ret = -ENOMEM;
++
++ setup_timer(&dev->vblank_disable_timer, vblank_disable_fn,
++ (unsigned long)dev);
++ spin_lock_init(&dev->vbl_lock);
++ atomic_set(&dev->vbl_signal_pending, 0);
++ dev->num_crtcs = num_crtcs;
++
++ dev->vbl_queue = drm_alloc(sizeof(wait_queue_head_t) * num_crtcs,
++ DRM_MEM_DRIVER);
++ if (!dev->vbl_queue)
++ goto err;
++
++ dev->vbl_sigs = drm_alloc(sizeof(struct list_head) * num_crtcs,
++ DRM_MEM_DRIVER);
++ if (!dev->vbl_sigs)
++ goto err;
++
++ dev->_vblank_count = drm_alloc(sizeof(atomic_t) * num_crtcs,
++ DRM_MEM_DRIVER);
++ if (!dev->_vblank_count)
++ goto err;
++
++ dev->vblank_refcount = drm_alloc(sizeof(atomic_t) * num_crtcs,
++ DRM_MEM_DRIVER);
++ if (!dev->vblank_refcount)
++ goto err;
++
++ dev->vblank_enabled = drm_calloc(num_crtcs, sizeof(int),
++ DRM_MEM_DRIVER);
++ if (!dev->vblank_enabled)
++ goto err;
++
++ dev->last_vblank = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER);
++ if (!dev->last_vblank)
++ goto err;
++
++ dev->vblank_premodeset = drm_calloc(num_crtcs, sizeof(u32),
++ DRM_MEM_DRIVER);
++ if (!dev->vblank_premodeset)
++ goto err;
++
++ dev->vblank_offset = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER);
++ if (!dev->vblank_offset)
++ goto err;
++
++ /* Zero per-crtc vblank stuff */
++ for (i = 0; i < num_crtcs; i++) {
++ init_waitqueue_head(&dev->vbl_queue[i]);
++ INIT_LIST_HEAD(&dev->vbl_sigs[i]);
++ atomic_set(&dev->_vblank_count[i], 0);
++ atomic_set(&dev->vblank_refcount[i], 0);
++ }
++
++ return 0;
++
++err:
++ drm_vblank_cleanup(dev);
++ return ret;
++}
++EXPORT_SYMBOL(drm_vblank_init);
++
+ /**
+ * Install IRQ handler.
+ *
+@@ -109,17 +220,6 @@ static int drm_irq_install(struct drm_device * dev)
+
+ DRM_DEBUG("irq=%d\n", dev->irq);
+
+- if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) {
+- init_waitqueue_head(&dev->vbl_queue);
+-
+- spin_lock_init(&dev->vbl_lock);
+-
+- INIT_LIST_HEAD(&dev->vbl_sigs);
+- INIT_LIST_HEAD(&dev->vbl_sigs2);
+-
+- dev->vbl_pending = 0;
+- }
+-
+ /* Before installing handler */
+ dev->driver->irq_preinstall(dev);
+
+@@ -137,9 +237,14 @@ static int drm_irq_install(struct drm_device * dev)
+ }
+
+ /* After installing handler */
+- dev->driver->irq_postinstall(dev);
++ ret = dev->driver->irq_postinstall(dev);
++ if (ret < 0) {
++ mutex_lock(&dev->struct_mutex);
++ dev->irq_enabled = 0;
++ mutex_unlock(&dev->struct_mutex);
++ }
+
+- return 0;
++ return ret;
+ }
+
+ /**
+@@ -170,6 +275,8 @@ int drm_irq_uninstall(struct drm_device * dev)
+
+ free_irq(dev->irq, dev);
+
++ drm_vblank_cleanup(dev);
++
+ dev->locked_tasklet_func = NULL;
+
+ return 0;
+@@ -214,6 +321,148 @@ int drm_control(struct drm_device *dev, void *data,
+ }
+
+ /**
++ * drm_vblank_count - retrieve "cooked" vblank counter value
++ * @dev: DRM device
++ * @crtc: which counter to retrieve
++ *
++ * Fetches the "cooked" vblank count value that represents the number of
++ * vblank events since the system was booted, including lost events due to
++ * modesetting activity.
++ */
++u32 drm_vblank_count(struct drm_device *dev, int crtc)
++{
++ return atomic_read(&dev->_vblank_count[crtc]) +
++ dev->vblank_offset[crtc];
++}
++EXPORT_SYMBOL(drm_vblank_count);
++
++/**
++ * drm_update_vblank_count - update the master vblank counter
++ * @dev: DRM device
++ * @crtc: counter to update
++ *
++ * Call back into the driver to update the appropriate vblank counter
++ * (specified by @crtc). Deal with wraparound, if it occurred, and
++ * update the last read value so we can deal with wraparound on the next
++ * call if necessary.
++ */
++void drm_update_vblank_count(struct drm_device *dev, int crtc)
++{
++ unsigned long irqflags;
++ u32 cur_vblank, diff;
++
++ /*
++ * Interrupts were disabled prior to this call, so deal with counter
++ * wrap if needed.
++ * NOTE! It's possible we lost a full dev->max_vblank_count events
++ * here if the register is small or we had vblank interrupts off for
++ * a long time.
++ */
++ cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
++ spin_lock_irqsave(&dev->vbl_lock, irqflags);
++ if (cur_vblank < dev->last_vblank[crtc]) {
++ diff = dev->max_vblank_count -
++ dev->last_vblank[crtc];
++ diff += cur_vblank;
++ } else {
++ diff = cur_vblank - dev->last_vblank[crtc];
++ }
++ dev->last_vblank[crtc] = cur_vblank;
++ spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
++
++ atomic_add(diff, &dev->_vblank_count[crtc]);
++}
++EXPORT_SYMBOL(drm_update_vblank_count);
++
++/**
++ * drm_vblank_get - get a reference count on vblank events
++ * @dev: DRM device
++ * @crtc: which CRTC to own
++ *
++ * Acquire a reference count on vblank events to avoid having them disabled
++ * while in use. Note callers will probably want to update the master counter
++ * using drm_update_vblank_count() above before calling this routine so that
++ * wakeups occur on the right vblank event.
++ *
++ * RETURNS
++ * Zero on success, nonzero on failure.
++ */
++int drm_vblank_get(struct drm_device *dev, int crtc)
++{
++ unsigned long irqflags;
++ int ret = 0;
++
++ spin_lock_irqsave(&dev->vbl_lock, irqflags);
++ /* Going from 0->1 means we have to enable interrupts again */
++ if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1 &&
++ !dev->vblank_enabled[crtc]) {
++ ret = dev->driver->enable_vblank(dev, crtc);
++ if (ret)
++ atomic_dec(&dev->vblank_refcount[crtc]);
++ else
++ dev->vblank_enabled[crtc] = 1;
++ }
++ spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
++
++ return ret;
++}
++EXPORT_SYMBOL(drm_vblank_get);
++
++/**
++ * drm_vblank_put - give up ownership of vblank events
++ * @dev: DRM device
++ * @crtc: which counter to give up
++ *
++ * Release ownership of a given vblank counter, turning off interrupts
++ * if possible.
++ */
++void drm_vblank_put(struct drm_device *dev, int crtc)
++{
++ /* Last user schedules interrupt disable */
++ if (atomic_dec_and_test(&dev->vblank_refcount[crtc]))
++ mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ);
++}
++EXPORT_SYMBOL(drm_vblank_put);
++
++/**
++ * drm_modeset_ctl - handle vblank event counter changes across mode switch
++ * @DRM_IOCTL_ARGS: standard ioctl arguments
++ *
++ * Applications should call the %_DRM_PRE_MODESET and %_DRM_POST_MODESET
++ * ioctls around modesetting so that any lost vblank events are accounted for.
++ */
++int drm_modeset_ctl(struct drm_device *dev, void *data,
++ struct drm_file *file_priv)
++{
++ struct drm_modeset_ctl *modeset = data;
++ int crtc, ret = 0;
++ u32 new;
++
++ crtc = modeset->arg;
++ if (crtc >= dev->num_crtcs) {
++ ret = -EINVAL;
++ goto out;
++ }
++
++ switch (modeset->cmd) {
++ case _DRM_PRE_MODESET:
++ dev->vblank_premodeset[crtc] =
++ dev->driver->get_vblank_counter(dev, crtc);
++ break;
++ case _DRM_POST_MODESET:
++ new = dev->driver->get_vblank_counter(dev, crtc);
++ dev->vblank_offset[crtc] = dev->vblank_premodeset[crtc] - new;
++ break;
++ default:
++ ret = -EINVAL;
++ break;
++ }
++
++out:
++ return ret;
++}
++
++/**
+ * Wait for VBLANK.
+ *
+ * \param inode device inode.
+@@ -232,12 +481,13 @@ int drm_control(struct drm_device *dev, void *data,
+ *
+ * If a signal is not requested, then calls vblank_wait().
+ */
+-int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv)
++int drm_wait_vblank(struct drm_device *dev, void *data,
++ struct drm_file *file_priv)
+ {
+ union drm_wait_vblank *vblwait = data;
+ struct timeval now;
+ int ret = 0;
+- unsigned int flags, seq;
++ unsigned int flags, seq, crtc;
+
+ if ((!dev->irq) || (!dev->irq_enabled))
+ return -EINVAL;
+@@ -251,13 +501,13 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
+ }
+
+ flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
++ crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
+
+- if (!drm_core_check_feature(dev, (flags & _DRM_VBLANK_SECONDARY) ?
+- DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL))
++ if (crtc >= dev->num_crtcs)
+ return -EINVAL;
+
+- seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2
+- : &dev->vbl_received);
++ drm_update_vblank_count(dev, crtc);
++ seq = drm_vblank_count(dev, crtc);
+
+ switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
+ case _DRM_VBLANK_RELATIVE:
+@@ -276,8 +526,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
+
+ if (flags & _DRM_VBLANK_SIGNAL) {
+ unsigned long irqflags;
+- struct list_head *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
+- ? &dev->vbl_sigs2 : &dev->vbl_sigs;
++ struct list_head *vbl_sigs = &dev->vbl_sigs[crtc];
+ struct drm_vbl_sig *vbl_sig;
+
+ spin_lock_irqsave(&dev->vbl_lock, irqflags);
+@@ -298,22 +547,26 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
+ }
+ }
+
+- if (dev->vbl_pending >= 100) {
++ if (atomic_read(&dev->vbl_signal_pending) >= 100) {
+ spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+ return -EBUSY;
+ }
+
+- dev->vbl_pending++;
+-
+ spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+
+- if (!
+- (vbl_sig =
+- drm_alloc(sizeof(struct drm_vbl_sig), DRM_MEM_DRIVER))) {
++ vbl_sig = drm_calloc(1, sizeof(struct drm_vbl_sig),
++ DRM_MEM_DRIVER);
++ if (!vbl_sig)
+ return -ENOMEM;
++
++ ret = drm_vblank_get(dev, crtc);
++ if (ret) {
++ drm_free(vbl_sig, sizeof(struct drm_vbl_sig),
++ DRM_MEM_DRIVER);
++ return ret;
+ }
+
+- memset((void *)vbl_sig, 0, sizeof(*vbl_sig));
++ atomic_inc(&dev->vbl_signal_pending);
+
+ vbl_sig->sequence = vblwait->request.sequence;
+ vbl_sig->info.si_signo = vblwait->request.signal;
+@@ -327,17 +580,20 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
+
+ vblwait->reply.sequence = seq;
+ } else {
+- if (flags & _DRM_VBLANK_SECONDARY) {
+- if (dev->driver->vblank_wait2)
+- ret = dev->driver->vblank_wait2(dev, &vblwait->request.sequence);
+- } else if (dev->driver->vblank_wait)
+- ret =
+- dev->driver->vblank_wait(dev,
+- &vblwait->request.sequence);
+-
++ unsigned long cur_vblank;
++
++ ret = drm_vblank_get(dev, crtc);
++ if (ret)
++ return ret;
++ DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ,
++ (((cur_vblank = drm_vblank_count(dev, crtc))
++ - vblwait->request.sequence) <= (1 << 23)));
++ drm_vblank_put(dev, crtc);
+ do_gettimeofday(&now);
++
+ vblwait->reply.tval_sec = now.tv_sec;
+ vblwait->reply.tval_usec = now.tv_usec;
++ vblwait->reply.sequence = cur_vblank;
+ }
+
+ done:
+@@ -348,44 +604,57 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
+ * Send the VBLANK signals.
+ *
+ * \param dev DRM device.
++ * \param crtc CRTC where the vblank event occurred
+ *
+ * Sends a signal for each task in drm_device::vbl_sigs and empties the list.
+ *
+ * If a signal is not requested, then calls vblank_wait().
+ */
+-void drm_vbl_send_signals(struct drm_device * dev)
++static void drm_vbl_send_signals(struct drm_device * dev, int crtc)
+ {
++ struct drm_vbl_sig *vbl_sig, *tmp;
++ struct list_head *vbl_sigs;
++ unsigned int vbl_seq;
+ unsigned long flags;
+- int i;
+
+ spin_lock_irqsave(&dev->vbl_lock, flags);
+
+- for (i = 0; i < 2; i++) {
+- struct drm_vbl_sig *vbl_sig, *tmp;
+- struct list_head *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
+- unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 :
+- &dev->vbl_received);
++ vbl_sigs = &dev->vbl_sigs[crtc];
++ vbl_seq = drm_vblank_count(dev, crtc);
+
+- list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
+- if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
+- vbl_sig->info.si_code = vbl_seq;
+- send_sig_info(vbl_sig->info.si_signo,
+- &vbl_sig->info, vbl_sig->task);
++ list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
++ if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
++ vbl_sig->info.si_code = vbl_seq;
++ send_sig_info(vbl_sig->info.si_signo,
++ &vbl_sig->info, vbl_sig->task);
+
+- list_del(&vbl_sig->head);
++ list_del(&vbl_sig->head);
+
+- drm_free(vbl_sig, sizeof(*vbl_sig),
+- DRM_MEM_DRIVER);
+-
+- dev->vbl_pending--;
+- }
+- }
++ drm_free(vbl_sig, sizeof(*vbl_sig),
++ DRM_MEM_DRIVER);
++ atomic_dec(&dev->vbl_signal_pending);
++ drm_vblank_put(dev, crtc);
++ }
+ }
+
+ spin_unlock_irqrestore(&dev->vbl_lock, flags);
+ }
+
+-EXPORT_SYMBOL(drm_vbl_send_signals);
++/**
++ * drm_handle_vblank - handle a vblank event
++ * @dev: DRM device
++ * @crtc: where this event occurred
++ *
++ * Drivers should call this routine in their vblank interrupt handlers to
++ * update the vblank counter and send any signals that may be pending.
++ */
++void drm_handle_vblank(struct drm_device *dev, int crtc)
++{
++ drm_update_vblank_count(dev, crtc);
++ DRM_WAKEUP(&dev->vbl_queue[crtc]);
++ drm_vbl_send_signals(dev, crtc);
++}
++EXPORT_SYMBOL(drm_handle_vblank);
+
+ /**
+ * Tasklet wrapper function.
+diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c
+index d9b560f..93b1e04 100644
+--- a/drivers/char/drm/drm_proc.c
++++ b/drivers/char/drm/drm_proc.c
+@@ -87,34 +87,35 @@ static struct drm_proc_list {
+ * "/proc/dri/%minor%/", and each entry in proc_list as
+ * "/proc/dri/%minor%/%name%".
+ */
+-int drm_proc_init(struct drm_device * dev, int minor,
+- struct proc_dir_entry *root, struct proc_dir_entry **dev_root)
++int drm_proc_init(struct drm_minor *minor, int minor_id,
++ struct proc_dir_entry *root)
+ {
+ struct proc_dir_entry *ent;
+ int i, j;
+ char name[64];
+
+- sprintf(name, "%d", minor);
+- *dev_root = proc_mkdir(name, root);
+- if (!*dev_root) {
++ sprintf(name, "%d", minor_id);
++ minor->dev_root = proc_mkdir(name, root);
++ if (!minor->dev_root) {
+ DRM_ERROR("Cannot create /proc/dri/%s\n", name);
+ return -1;
+ }
+
+ for (i = 0; i < DRM_PROC_ENTRIES; i++) {
+ ent = create_proc_entry(drm_proc_list[i].name,
+- S_IFREG | S_IRUGO, *dev_root);
++ S_IFREG | S_IRUGO, minor->dev_root);
+ if (!ent) {
+ DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
+ name, drm_proc_list[i].name);
+ for (j = 0; j < i; j++)
+ remove_proc_entry(drm_proc_list[i].name,
+- *dev_root);
++ minor->dev_root);
+ remove_proc_entry(name, root);
++ minor->dev_root = NULL;
+ return -1;
+ }
+ ent->read_proc = drm_proc_list[i].f;
+- ent->data = dev;
++ ent->data = minor;
+ }
+
+ return 0;
+@@ -130,18 +131,17 @@ int drm_proc_init(struct drm_device * dev, int minor,
+ *
+ * Remove all proc entries created by proc_init().
+ */
+-int drm_proc_cleanup(int minor, struct proc_dir_entry *root,
+- struct proc_dir_entry *dev_root)
++int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root)
+ {
+ int i;
+ char name[64];
+
+- if (!root || !dev_root)
++ if (!root || !minor->dev_root)
+ return 0;
+
+ for (i = 0; i < DRM_PROC_ENTRIES; i++)
+- remove_proc_entry(drm_proc_list[i].name, dev_root);
+- sprintf(name, "%d", minor);
++ remove_proc_entry(drm_proc_list[i].name, minor->dev_root);
++ sprintf(name, "%d", minor->index);
+ remove_proc_entry(name, root);
+
+ return 0;
+@@ -163,7 +163,8 @@ int drm_proc_cleanup(int minor, struct proc_dir_entry *root,
+ static int drm_name_info(char *buf, char **start, off_t offset, int request,
+ int *eof, void *data)
+ {
+- struct drm_device *dev = (struct drm_device *) data;
++ struct drm_minor *minor = (struct drm_minor *) data;
++ struct drm_device *dev = minor->dev;
+ int len = 0;
+
+ if (offset > DRM_PROC_LIMIT) {
+@@ -205,7 +206,8 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request,
+ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
+ int *eof, void *data)
+ {
+- struct drm_device *dev = (struct drm_device *) data;
++ struct drm_minor *minor = (struct drm_minor *) data;
++ struct drm_device *dev = minor->dev;
+ int len = 0;
+ struct drm_map *map;
+ struct drm_map_list *r_list;
+@@ -261,7 +263,8 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
+ static int drm_vm_info(char *buf, char **start, off_t offset, int request,
+ int *eof, void *data)
+ {
+- struct drm_device *dev = (struct drm_device *) data;
++ struct drm_minor *minor = (struct drm_minor *) data;
++ struct drm_device *dev = minor->dev;
+ int ret;
+
+ mutex_lock(&dev->struct_mutex);
+@@ -284,7 +287,8 @@ static int drm_vm_info(char *buf, char **start, off_t offset, int request,
+ static int drm__queues_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data)
+ {
+- struct drm_device *dev = (struct drm_device *) data;
++ struct drm_minor *minor = (struct drm_minor *) data;
++ struct drm_device *dev = minor->dev;
+ int len = 0;
+ int i;
+ struct drm_queue *q;
+@@ -334,7 +338,8 @@ static int drm__queues_info(char *buf, char **start, off_t offset,
+ static int drm_queues_info(char *buf, char **start, off_t offset, int request,
+ int *eof, void *data)
+ {
+- struct drm_device *dev = (struct drm_device *) data;
++ struct drm_minor *minor = (struct drm_minor *) data;
++ struct drm_device *dev = minor->dev;
+ int ret;
+
+ mutex_lock(&dev->struct_mutex);
+@@ -357,7 +362,8 @@ static int drm_queues_info(char *buf, char **start, off_t offset, int request,
+ static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
+ int *eof, void *data)
+ {
+- struct drm_device *dev = (struct drm_device *) data;
++ struct drm_minor *minor = (struct drm_minor *) data;
++ struct drm_device *dev = minor->dev;
+ int len = 0;
+ struct drm_device_dma *dma = dev->dma;
+ int i;
+@@ -406,7 +412,8 @@ static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
+ static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
+ int *eof, void *data)
+ {
+- struct drm_device *dev = (struct drm_device *) data;
++ struct drm_minor *minor = (struct drm_minor *) data;
++ struct drm_device *dev = minor->dev;
+ int ret;
+
+ mutex_lock(&dev->struct_mutex);
+@@ -429,7 +436,8 @@ static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
+ static int drm__clients_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data)
+ {
+- struct drm_device *dev = (struct drm_device *) data;
++ struct drm_minor *minor = (struct drm_minor *) data;
++ struct drm_device *dev = minor->dev;
+ int len = 0;
+ struct drm_file *priv;
+
+@@ -445,7 +453,7 @@ static int drm__clients_info(char *buf, char **start, off_t offset,
+ list_for_each_entry(priv, &dev->filelist, lhead) {
+ DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n",
+ priv->authenticated ? 'y' : 'n',
+- priv->minor,
++ priv->minor->index,
+ priv->pid,
+ priv->uid, priv->magic, priv->ioctl_count);
+ }
+@@ -462,7 +470,8 @@ static int drm__clients_info(char *buf, char **start, off_t offset,
+ static int drm_clients_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data)
+ {
+- struct drm_device *dev = (struct drm_device *) data;
++ struct drm_minor *minor = (struct drm_minor *) data;
++ struct drm_device *dev = minor->dev;
+ int ret;
+
+ mutex_lock(&dev->struct_mutex);
+@@ -476,7 +485,8 @@ static int drm_clients_info(char *buf, char **start, off_t offset,
+ static int drm__vma_info(char *buf, char **start, off_t offset, int request,
+ int *eof, void *data)
+ {
+- struct drm_device *dev = (struct drm_device *) data;
++ struct drm_minor *minor = (struct drm_minor *) data;
++ struct drm_device *dev = minor->dev;
+ int len = 0;
+ struct drm_vma_entry *pt;
+ struct vm_area_struct *vma;
+@@ -535,7 +545,8 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request,
+ static int drm_vma_info(char *buf, char **start, off_t offset, int request,
+ int *eof, void *data)
+ {
+- struct drm_device *dev = (struct drm_device *) data;
++ struct drm_minor *minor = (struct drm_minor *) data;
++ struct drm_device *dev = minor->dev;
+ int ret;
+
+ mutex_lock(&dev->struct_mutex);
+diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
+index d93a217..c2f584f 100644
+--- a/drivers/char/drm/drm_stub.c
++++ b/drivers/char/drm/drm_stub.c
+@@ -36,23 +36,49 @@
+ #include "drmP.h"
+ #include "drm_core.h"
+
+-unsigned int drm_cards_limit = 16; /* Enough for one machine */
+ unsigned int drm_debug = 0; /* 1 to enable debug output */
+ EXPORT_SYMBOL(drm_debug);
+
+ MODULE_AUTHOR(CORE_AUTHOR);
+ MODULE_DESCRIPTION(CORE_DESC);
+ MODULE_LICENSE("GPL and additional rights");
+-MODULE_PARM_DESC(cards_limit, "Maximum number of graphics cards");
+ MODULE_PARM_DESC(debug, "Enable debug output");
+
+-module_param_named(cards_limit, drm_cards_limit, int, 0444);
+ module_param_named(debug, drm_debug, int, 0600);
+
+-struct drm_head **drm_heads;
++struct idr drm_minors_idr;
++
+ struct class *drm_class;
+ struct proc_dir_entry *drm_proc_root;
+
++static int drm_minor_get_id(struct drm_device *dev, int type)
++{
++ int new_id;
++ int ret;
++ int base = 0, limit = 63;
++
++again:
++ if (idr_pre_get(&drm_minors_idr, GFP_KERNEL) == 0) {
++ DRM_ERROR("Out of memory expanding drawable idr\n");
++ return -ENOMEM;
++ }
++ mutex_lock(&dev->struct_mutex);
++ ret = idr_get_new_above(&drm_minors_idr, NULL,
++ base, &new_id);
++ mutex_unlock(&dev->struct_mutex);
++ if (ret == -EAGAIN) {
++ goto again;
++ } else if (ret) {
++ return ret;
++ }
++
++ if (new_id >= limit) {
++ idr_remove(&drm_minors_idr, new_id);
++ return -EINVAL;
++ }
++ return new_id;
++}
++
+ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
+ const struct pci_device_id *ent,
+ struct drm_driver *driver)
+@@ -145,48 +171,60 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
+ * create the proc init entry via proc_init(). This routines assigns
+ * minor numbers to secondary heads of multi-headed cards
+ */
+-static int drm_get_head(struct drm_device * dev, struct drm_head * head)
++static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type)
+ {
+- struct drm_head **heads = drm_heads;
++ struct drm_minor *new_minor;
+ int ret;
+- int minor;
++ int minor_id;
+
+ DRM_DEBUG("\n");
+
+- for (minor = 0; minor < drm_cards_limit; minor++, heads++) {
+- if (!*heads) {
+-
+- *head = (struct drm_head) {
+- .dev = dev,.device =
+- MKDEV(DRM_MAJOR, minor),.minor = minor,};
+-
+- if ((ret =
+- drm_proc_init(dev, minor, drm_proc_root,
+- &head->dev_root))) {
+- printk(KERN_ERR
+- "DRM: Failed to initialize /proc/dri.\n");
+- goto err_g1;
+- }
+-
+- ret = drm_sysfs_device_add(dev, head);
+- if (ret) {
+- printk(KERN_ERR
+- "DRM: Error sysfs_device_add.\n");
+- goto err_g2;
+- }
+- *heads = head;
+-
+- DRM_DEBUG("new minor assigned %d\n", minor);
+- return 0;
++ minor_id = drm_minor_get_id(dev, type);
++ if (minor_id < 0)
++ return minor_id;
++
++ new_minor = kzalloc(sizeof(struct drm_minor), GFP_KERNEL);
++ if (!new_minor) {
++ ret = -ENOMEM;
++ goto err_idr;
++ }
++
++ new_minor->type = type;
++ new_minor->device = MKDEV(DRM_MAJOR, minor_id);
++ new_minor->dev = dev;
++ new_minor->index = minor_id;
++
++ idr_replace(&drm_minors_idr, new_minor, minor_id);
++
++ if (type == DRM_MINOR_LEGACY) {
++ ret = drm_proc_init(new_minor, minor_id, drm_proc_root);
++ if (ret) {
++ DRM_ERROR("DRM: Failed to initialize /proc/dri.\n");
++ goto err_mem;
+ }
++ } else
++ new_minor->dev_root = NULL;
++
++ ret = drm_sysfs_device_add(new_minor);
++ if (ret) {
++ printk(KERN_ERR
++ "DRM: Error sysfs_device_add.\n");
++ goto err_g2;
+ }
+- DRM_ERROR("out of minors\n");
+- return -ENOMEM;
+- err_g2:
+- drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
+- err_g1:
+- *head = (struct drm_head) {
+- .dev = NULL};
++ *minor = new_minor;
++
++ DRM_DEBUG("new minor assigned %d\n", minor_id);
++ return 0;
++
++
++err_g2:
++ if (new_minor->type == DRM_MINOR_LEGACY)
++ drm_proc_cleanup(new_minor, drm_proc_root);
++err_mem:
++ kfree(new_minor);
++err_idr:
++ idr_remove(&drm_minors_idr, minor_id);
++ *minor = NULL;
+ return ret;
+ }
+
+@@ -222,12 +260,12 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
+ printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
+ goto err_g2;
+ }
+- if ((ret = drm_get_head(dev, &dev->primary)))
++ if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
+ goto err_g2;
+
+ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
+ driver->name, driver->major, driver->minor, driver->patchlevel,
+- driver->date, dev->primary.minor);
++ driver->date, dev->primary->index);
+
+ return 0;
+
+@@ -276,18 +314,18 @@ int drm_put_dev(struct drm_device * dev)
+ * last minor released.
+ *
+ */
+-int drm_put_head(struct drm_head * head)
++int drm_put_minor(struct drm_minor **minor_p)
+ {
+- int minor = head->minor;
+-
+- DRM_DEBUG("release secondary minor %d\n", minor);
+-
+- drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
+- drm_sysfs_device_remove(head->dev);
++ struct drm_minor *minor = *minor_p;
++ DRM_DEBUG("release secondary minor %d\n", minor->index);
+
+- *head = (struct drm_head) {.dev = NULL};
++ if (minor->type == DRM_MINOR_LEGACY)
++ drm_proc_cleanup(minor, drm_proc_root);
++ drm_sysfs_device_remove(minor);
+
+- drm_heads[minor] = NULL;
++ idr_remove(&drm_minors_idr, minor->index);
+
++ kfree(minor);
++ *minor_p = NULL;
+ return 0;
+ }
+diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c
+index 05ed504..7a1d9a7 100644
+--- a/drivers/char/drm/drm_sysfs.c
++++ b/drivers/char/drm/drm_sysfs.c
+@@ -19,7 +19,7 @@
+ #include "drm_core.h"
+ #include "drmP.h"
+
+-#define to_drm_device(d) container_of(d, struct drm_device, dev)
++#define to_drm_minor(d) container_of(d, struct drm_minor, kdev)
+
+ /**
+ * drm_sysfs_suspend - DRM class suspend hook
+@@ -31,7 +31,8 @@
+ */
+ static int drm_sysfs_suspend(struct device *dev, pm_message_t state)
+ {
+- struct drm_device *drm_dev = to_drm_device(dev);
++ struct drm_minor *drm_minor = to_drm_minor(dev);
++ struct drm_device *drm_dev = drm_minor->dev;
+
+ printk(KERN_ERR "%s\n", __FUNCTION__);
+
+@@ -50,7 +51,8 @@ static int drm_sysfs_suspend(struct device *dev, pm_message_t state)
+ */
+ static int drm_sysfs_resume(struct device *dev)
+ {
+- struct drm_device *drm_dev = to_drm_device(dev);
++ struct drm_minor *drm_minor = to_drm_minor(dev);
++ struct drm_device *drm_dev = drm_minor->dev;
+
+ if (drm_dev->driver->resume)
+ return drm_dev->driver->resume(drm_dev);
+@@ -120,10 +122,11 @@ void drm_sysfs_destroy(void)
+ static ssize_t show_dri(struct device *device, struct device_attribute *attr,
+ char *buf)
+ {
+- struct drm_device *dev = to_drm_device(device);
+- if (dev->driver->dri_library_name)
+- return dev->driver->dri_library_name(dev, buf);
+- return snprintf(buf, PAGE_SIZE, "%s\n", dev->driver->pci_driver.name);
++ struct drm_minor *drm_minor = to_drm_minor(device);
++ struct drm_device *drm_dev = drm_minor->dev;
++ if (drm_dev->driver->dri_library_name)
++ return drm_dev->driver->dri_library_name(drm_dev, buf);
++ return snprintf(buf, PAGE_SIZE, "%s\n", drm_dev->driver->pci_driver.name);
+ }
+
+ static struct device_attribute device_attrs[] = {
+@@ -152,25 +155,28 @@ static void drm_sysfs_device_release(struct device *dev)
+ * as the parent for the Linux device, and make sure it has a file containing
+ * the driver we're using (for userspace compatibility).
+ */
+-int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head)
++int drm_sysfs_device_add(struct drm_minor *minor)
+ {
+ int err;
+ int i, j;
++ char *minor_str;
+
+- dev->dev.parent = &dev->pdev->dev;
+- dev->dev.class = drm_class;
+- dev->dev.release = drm_sysfs_device_release;
+- dev->dev.devt = head->device;
+- snprintf(dev->dev.bus_id, BUS_ID_SIZE, "card%d", head->minor);
++ minor->kdev.parent = &minor->dev->pdev->dev;
++ minor->kdev.class = drm_class;
++ minor->kdev.release = drm_sysfs_device_release;
++ minor->kdev.devt = minor->device;
++ minor_str = "card%d";
+
+- err = device_register(&dev->dev);
++ snprintf(minor->kdev.bus_id, BUS_ID_SIZE, minor_str, minor->index);
++
++ err = device_register(&minor->kdev);
+ if (err) {
+ DRM_ERROR("device add failed: %d\n", err);
+ goto err_out;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
+- err = device_create_file(&dev->dev, &device_attrs[i]);
++ err = device_create_file(&minor->kdev, &device_attrs[i]);
+ if (err)
+ goto err_out_files;
+ }
+@@ -180,8 +186,8 @@ int drm_sysfs_device_add(struct drm_device *dev, struct drm_head *head)
+ err_out_files:
+ if (i > 0)
+ for (j = 0; j < i; j++)
+- device_remove_file(&dev->dev, &device_attrs[i]);
+- device_unregister(&dev->dev);
++ device_remove_file(&minor->kdev, &device_attrs[i]);
++ device_unregister(&minor->kdev);
+ err_out:
+
+ return err;
+@@ -194,11 +200,11 @@ err_out:
+ * This call unregisters and cleans up a class device that was created with a
+ * call to drm_sysfs_device_add()
+ */
+-void drm_sysfs_device_remove(struct drm_device *dev)
++void drm_sysfs_device_remove(struct drm_minor *minor)
+ {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
+- device_remove_file(&dev->dev, &device_attrs[i]);
+- device_unregister(&dev->dev);
++ device_remove_file(&minor->kdev, &device_attrs[i]);
++ device_unregister(&minor->kdev);
+ }
+diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
+index 945df72..c234c6f 100644
+--- a/drivers/char/drm/drm_vm.c
++++ b/drivers/char/drm/drm_vm.c
+@@ -90,7 +90,7 @@ static pgprot_t drm_dma_prot(uint32_t map_type, struct vm_area_struct *vma)
+ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+ {
+ struct drm_file *priv = vma->vm_file->private_data;
+- struct drm_device *dev = priv->head->dev;
++ struct drm_device *dev = priv->minor->dev;
+ struct drm_map *map = NULL;
+ struct drm_map_list *r_list;
+ struct drm_hash_item *hash;
+@@ -207,7 +207,7 @@ static int drm_do_vm_shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+ static void drm_vm_shm_close(struct vm_area_struct *vma)
+ {
+ struct drm_file *priv = vma->vm_file->private_data;
+- struct drm_device *dev = priv->head->dev;
++ struct drm_device *dev = priv->minor->dev;
+ struct drm_vma_entry *pt, *temp;
+ struct drm_map *map;
+ struct drm_map_list *r_list;
+@@ -286,7 +286,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
+ static int drm_do_vm_dma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+ {
+ struct drm_file *priv = vma->vm_file->private_data;
+- struct drm_device *dev = priv->head->dev;
++ struct drm_device *dev = priv->minor->dev;
+ struct drm_device_dma *dma = dev->dma;
+ unsigned long offset;
+ unsigned long page_nr;
+@@ -321,7 +321,7 @@ static int drm_do_vm_sg_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+ {
+ struct drm_map *map = (struct drm_map *) vma->vm_private_data;
+ struct drm_file *priv = vma->vm_file->private_data;
+- struct drm_device *dev = priv->head->dev;
++ struct drm_device *dev = priv->minor->dev;
+ struct drm_sg_mem *entry = dev->sg;
+ unsigned long offset;
+ unsigned long map_offset;
+@@ -402,7 +402,7 @@ static struct vm_operations_struct drm_vm_sg_ops = {
+ static void drm_vm_open_locked(struct vm_area_struct *vma)
+ {
+ struct drm_file *priv = vma->vm_file->private_data;
+- struct drm_device *dev = priv->head->dev;
++ struct drm_device *dev = priv->minor->dev;
+ struct drm_vma_entry *vma_entry;
+
+ DRM_DEBUG("0x%08lx,0x%08lx\n",
+@@ -420,7 +420,7 @@ static void drm_vm_open_locked(struct vm_area_struct *vma)
+ static void drm_vm_open(struct vm_area_struct *vma)
+ {
+ struct drm_file *priv = vma->vm_file->private_data;
+- struct drm_device *dev = priv->head->dev;
++ struct drm_device *dev = priv->minor->dev;
+
+ mutex_lock(&dev->struct_mutex);
+ drm_vm_open_locked(vma);
+@@ -438,7 +438,7 @@ static void drm_vm_open(struct vm_area_struct *vma)
+ static void drm_vm_close(struct vm_area_struct *vma)
+ {
+ struct drm_file *priv = vma->vm_file->private_data;
+- struct drm_device *dev = priv->head->dev;
++ struct drm_device *dev = priv->minor->dev;
+ struct drm_vma_entry *pt, *temp;
+
+ DRM_DEBUG("0x%08lx,0x%08lx\n",
+@@ -473,7 +473,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
+ struct drm_device_dma *dma;
+ unsigned long length = vma->vm_end - vma->vm_start;
+
+- dev = priv->head->dev;
++ dev = priv->minor->dev;
+ dma = dev->dma;
+ DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n",
+ vma->vm_start, vma->vm_end, vma->vm_pgoff);
+@@ -543,7 +543,7 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs);
+ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
+ {
+ struct drm_file *priv = filp->private_data;
+- struct drm_device *dev = priv->head->dev;
++ struct drm_device *dev = priv->minor->dev;
+ struct drm_map *map = NULL;
+ unsigned long offset = 0;
+ struct drm_hash_item *hash;
+@@ -640,12 +640,12 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
+ /* Don't let this area swap. Change when
+ DRM_KERNEL advisory is supported. */
+ vma->vm_flags |= VM_RESERVED;
+- vma->vm_page_prot = drm_dma_prot(map->type, vma);
+ break;
+ case _DRM_SCATTER_GATHER:
+ vma->vm_ops = &drm_vm_sg_ops;
+ vma->vm_private_data = (void *)map;
+ vma->vm_flags |= VM_RESERVED;
++ vma->vm_page_prot = drm_dma_prot(map->type, vma);
+ break;
+ default:
+ return -EINVAL; /* This should never happen. */
+@@ -661,7 +661,7 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
+ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
+ {
+ struct drm_file *priv = filp->private_data;
+- struct drm_device *dev = priv->head->dev;
++ struct drm_device *dev = priv->minor->dev;
+ int ret;
+
+ mutex_lock(&dev->struct_mutex);
+diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
+index 8d7ea81..e5de8ea 100644
+--- a/drivers/char/drm/i810_dma.c
++++ b/drivers/char/drm/i810_dma.c
+@@ -94,7 +94,7 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
+ drm_i810_buf_priv_t *buf_priv;
+
+ lock_kernel();
+- dev = priv->head->dev;
++ dev = priv->minor->dev;
+ dev_priv = dev->dev_private;
+ buf = dev_priv->mmap_buffer;
+ buf_priv = buf->dev_private;
+@@ -122,7 +122,7 @@ static const struct file_operations i810_buffer_fops = {
+
+ static int i810_map_buffer(struct drm_buf * buf, struct drm_file *file_priv)
+ {
+- struct drm_device *dev = file_priv->head->dev;
++ struct drm_device *dev = file_priv->minor->dev;
+ drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ const struct file_operations *old_fops;
+diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
+index 9df0810..60c9376 100644
+--- a/drivers/char/drm/i830_dma.c
++++ b/drivers/char/drm/i830_dma.c
+@@ -96,7 +96,7 @@ static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
+ drm_i830_buf_priv_t *buf_priv;
+
+ lock_kernel();
+- dev = priv->head->dev;
++ dev = priv->minor->dev;
+ dev_priv = dev->dev_private;
+ buf = dev_priv->mmap_buffer;
+ buf_priv = buf->dev_private;
+@@ -124,7 +124,7 @@ static const struct file_operations i830_buffer_fops = {
+
+ static int i830_map_buffer(struct drm_buf * buf, struct drm_file *file_priv)
+ {
+- struct drm_device *dev = file_priv->head->dev;
++ struct drm_device *dev = file_priv->minor->dev;
+ drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+ drm_i830_private_t *dev_priv = dev->dev_private;
+ const struct file_operations *old_fops;
+diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
+index a043bb1..ef7bf14 100644
+--- a/drivers/char/drm/i915_dma.c
++++ b/drivers/char/drm/i915_dma.c
+@@ -415,10 +415,13 @@ static void i915_emit_breadcrumb(struct drm_device *dev)
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ RING_LOCALS;
+
+- dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
++ if (++dev_priv->counter > BREADCRUMB_MASK) {
++ dev_priv->counter = 1;
++ DRM_DEBUG("Breadcrumb counter wrapped around\n");
++ }
+
+- if (dev_priv->counter > 0x7FFFFFFFUL)
+- dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
++ if (dev_priv->sarea_priv)
++ dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
+
+ BEGIN_LP_RING(4);
+ OUT_RING(CMD_STORE_DWORD_IDX);
+@@ -428,6 +431,26 @@ static void i915_emit_breadcrumb(struct drm_device *dev)
+ ADVANCE_LP_RING();
+ }
+
++int i915_emit_mi_flush(struct drm_device *dev, uint32_t flush)
++{
++ drm_i915_private_t *dev_priv = dev->dev_private;
++ uint32_t flush_cmd = CMD_MI_FLUSH;
++ RING_LOCALS;
++
++ flush_cmd |= flush;
++
++ i915_kernel_lost_context(dev);
++
++ BEGIN_LP_RING(4);
++ OUT_RING(flush_cmd);
++ OUT_RING(0);
++ OUT_RING(0);
++ OUT_RING(0);
++ ADVANCE_LP_RING();
++
++ return 0;
++}
++
+ static int i915_dispatch_cmdbuffer(struct drm_device * dev,
+ drm_i915_cmdbuffer_t * cmd)
+ {
+@@ -511,52 +534,74 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev,
+ return 0;
+ }
+
+-static int i915_dispatch_flip(struct drm_device * dev)
++static void i915_do_dispatch_flip(struct drm_device * dev, int plane, int sync)
+ {
+ drm_i915_private_t *dev_priv = dev->dev_private;
++ u32 num_pages, current_page, next_page, dspbase;
++ int shift = 2 * plane, x, y;
+ RING_LOCALS;
+
+- DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
+- __FUNCTION__,
+- dev_priv->current_page,
+- dev_priv->sarea_priv->pf_current_page);
++ /* Calculate display base offset */
++ num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2;
++ current_page = (dev_priv->sarea_priv->pf_current_page >> shift) & 0x3;
++ next_page = (current_page + 1) % num_pages;
+
+- i915_kernel_lost_context(dev);
+-
+- BEGIN_LP_RING(2);
+- OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
+- OUT_RING(0);
+- ADVANCE_LP_RING();
++ switch (next_page) {
++ default:
++ case 0:
++ dspbase = dev_priv->sarea_priv->front_offset;
++ break;
++ case 1:
++ dspbase = dev_priv->sarea_priv->back_offset;
++ break;
++ case 2:
++ dspbase = dev_priv->sarea_priv->third_offset;
++ break;
++ }
+
+- BEGIN_LP_RING(6);
+- OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
+- OUT_RING(0);
+- if (dev_priv->current_page == 0) {
+- OUT_RING(dev_priv->back_offset);
+- dev_priv->current_page = 1;
++ if (plane == 0) {
++ x = dev_priv->sarea_priv->planeA_x;
++ y = dev_priv->sarea_priv->planeA_y;
+ } else {
+- OUT_RING(dev_priv->front_offset);
+- dev_priv->current_page = 0;
++ x = dev_priv->sarea_priv->planeB_x;
++ y = dev_priv->sarea_priv->planeB_y;
+ }
+- OUT_RING(0);
+- ADVANCE_LP_RING();
+
+- BEGIN_LP_RING(2);
+- OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
+- OUT_RING(0);
+- ADVANCE_LP_RING();
++ dspbase += (y * dev_priv->sarea_priv->pitch + x) * dev_priv->cpp;
+
+- dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
++ DRM_DEBUG("plane=%d current_page=%d dspbase=0x%x\n", plane, current_page,
++ dspbase);
+
+ BEGIN_LP_RING(4);
+- OUT_RING(CMD_STORE_DWORD_IDX);
+- OUT_RING(20);
+- OUT_RING(dev_priv->counter);
+- OUT_RING(0);
++ OUT_RING(sync ? 0 :
++ (MI_WAIT_FOR_EVENT | (plane ? MI_WAIT_FOR_PLANE_B_FLIP :
++ MI_WAIT_FOR_PLANE_A_FLIP)));
++ OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | (sync ? 0 : ASYNC_FLIP) |
++ (plane ? DISPLAY_PLANE_B : DISPLAY_PLANE_A));
++ OUT_RING(dev_priv->sarea_priv->pitch * dev_priv->cpp);
++ OUT_RING(dspbase);
+ ADVANCE_LP_RING();
+
+- dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+- return 0;
++ dev_priv->sarea_priv->pf_current_page &= ~(0x3 << shift);
++ dev_priv->sarea_priv->pf_current_page |= next_page << shift;
++}
++
++void i915_dispatch_flip(struct drm_device * dev, int planes, int sync)
++{
++ drm_i915_private_t *dev_priv = dev->dev_private;
++ int i;
++
++ DRM_DEBUG("planes=0x%x pfCurrentPage=%d\n",
++ planes, dev_priv->sarea_priv->pf_current_page);
++
++ i915_emit_mi_flush(dev, MI_READ_FLUSH | MI_EXE_FLUSH);
++
++ for (i = 0; i < 2; i++)
++ if (planes & (1 << i))
++ i915_do_dispatch_flip(dev, i, sync);
++
++ i915_emit_breadcrumb(dev);
++
+ }
+
+ static int i915_quiescent(struct drm_device * dev)
+@@ -579,7 +624,6 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+ {
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+- u32 *hw_status = dev_priv->hw_status_page;
+ drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
+ dev_priv->sarea_priv;
+ drm_i915_batchbuffer_t *batch = data;
+@@ -602,7 +646,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
+
+ ret = i915_dispatch_batchbuffer(dev, batch);
+
+- sarea_priv->last_dispatch = (int)hw_status[5];
++ sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+ return ret;
+ }
+
+@@ -610,7 +654,6 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+ {
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+- u32 *hw_status = dev_priv->hw_status_page;
+ drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
+ dev_priv->sarea_priv;
+ drm_i915_cmdbuffer_t *cmdbuf = data;
+@@ -635,18 +678,51 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
+ return ret;
+ }
+
+- sarea_priv->last_dispatch = (int)hw_status[5];
++ sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
++ return 0;
++}
++
++static int i915_do_cleanup_pageflip(struct drm_device * dev)
++{
++ drm_i915_private_t *dev_priv = dev->dev_private;
++ int i, planes, num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2;
++
++ DRM_DEBUG("\n");
++
++ for (i = 0, planes = 0; i < 2; i++)
++ if (dev_priv->sarea_priv->pf_current_page & (0x3 << (2 * i))) {
++ dev_priv->sarea_priv->pf_current_page =
++ (dev_priv->sarea_priv->pf_current_page &
++ ~(0x3 << (2 * i))) | ((num_pages - 1) << (2 * i));
++
++ planes |= 1 << i;
++ }
++
++ if (planes)
++ i915_dispatch_flip(dev, planes, 0);
++
+ return 0;
+ }
+
+ static int i915_flip_bufs(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+ {
+- DRM_DEBUG("%s\n", __FUNCTION__);
++ drm_i915_flip_t *param = data;
++
++ DRM_DEBUG("\n");
+
+ LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+- return i915_dispatch_flip(dev);
++ /* This is really planes */
++ if (param->pipes & ~0x3) {
++ DRM_ERROR("Invalid planes 0x%x, only <= 0x3 is valid\n",
++ param->pipes);
++ return -EINVAL;
++ }
++
++ i915_dispatch_flip(dev, param->pipes, 0);
++
++ return 0;
+ }
+
+ static int i915_getparam(struct drm_device *dev, void *data,
+@@ -807,6 +883,8 @@ void i915_driver_lastclose(struct drm_device * dev)
+ if (!dev_priv)
+ return;
+
++ if (drm_getsarea(dev) && dev_priv->sarea_priv)
++ i915_do_cleanup_pageflip(dev);
+ if (dev_priv->agp_heap)
+ i915_mem_takedown(&(dev_priv->agp_heap));
+
+diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h
+index 05c66cf..0431c00 100644
+--- a/drivers/char/drm/i915_drm.h
++++ b/drivers/char/drm/i915_drm.h
+@@ -105,14 +105,29 @@ typedef struct _drm_i915_sarea {
+ unsigned int rotated_tiled;
+ unsigned int rotated2_tiled;
+
+- int pipeA_x;
+- int pipeA_y;
+- int pipeA_w;
+- int pipeA_h;
+- int pipeB_x;
+- int pipeB_y;
+- int pipeB_w;
+- int pipeB_h;
++ int planeA_x;
++ int planeA_y;
++ int planeA_w;
++ int planeA_h;
++ int planeB_x;
++ int planeB_y;
++ int planeB_w;
++ int planeB_h;
++
++ /* Triple buffering */
++ drm_handle_t third_handle;
++ int third_offset;
++ int third_size;
++ unsigned int third_tiled;
++
++ /* buffer object handles for the static buffers. May change
++ * over the lifetime of the client, though it doesn't in our current
++ * implementation.
++ */
++ unsigned int front_bo_handle;
++ unsigned int back_bo_handle;
++ unsigned int third_bo_handle;
++ unsigned int depth_bo_handle;
+ } drm_i915_sarea_t;
+
+ /* Flags for perf_boxes
+@@ -146,7 +161,7 @@ typedef struct _drm_i915_sarea {
+
+ #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
+ #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
+-#define DRM_IOCTL_I915_FLIP DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLIP)
++#define DRM_IOCTL_I915_FLIP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FLIP, drm_i915_flip_t)
+ #define DRM_IOCTL_I915_BATCHBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_BATCHBUFFER, drm_i915_batchbuffer_t)
+ #define DRM_IOCTL_I915_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_IRQ_EMIT, drm_i915_irq_emit_t)
+ #define DRM_IOCTL_I915_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_IRQ_WAIT, drm_i915_irq_wait_t)
+@@ -161,6 +176,18 @@ typedef struct _drm_i915_sarea {
+ #define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
+ #define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
+
++/* Asynchronous page flipping:
++ */
++typedef struct drm_i915_flip {
++ /*
++ * This is really talking about planes, and we could rename it
++ * except for the fact that some of the duplicated i915_drm.h files
++ * out there check for HAVE_I915_FLIP and so might pick up this
++ * version.
++ */
++ int pipes;
++} drm_i915_flip_t;
++
+ /* Allow drivers to submit batchbuffers directly to hardware, relying
+ * on the security mechanisms provided by hardware.
+ */
+diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c
+index b2b451d..bb8f1b2 100644
+--- a/drivers/char/drm/i915_drv.c
++++ b/drivers/char/drm/i915_drv.c
+@@ -533,8 +533,7 @@ static struct drm_driver driver = {
+ */
+ .driver_features =
+ DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
+- DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL |
+- DRIVER_IRQ_VBL2,
++ DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
+ .load = i915_driver_load,
+ .unload = i915_driver_unload,
+ .lastclose = i915_driver_lastclose,
+@@ -542,8 +541,9 @@ static struct drm_driver driver = {
+ .suspend = i915_suspend,
+ .resume = i915_resume,
+ .device_is_agp = i915_driver_device_is_agp,
+- .vblank_wait = i915_driver_vblank_wait,
+- .vblank_wait2 = i915_driver_vblank_wait2,
++ .get_vblank_counter = i915_get_vblank_counter,
++ .enable_vblank = i915_enable_vblank,
++ .disable_vblank = i915_disable_vblank,
+ .irq_preinstall = i915_driver_irq_preinstall,
+ .irq_postinstall = i915_driver_irq_postinstall,
+ .irq_uninstall = i915_driver_irq_uninstall,
+diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
+index 675d88b..c614d78 100644
+--- a/drivers/char/drm/i915_drv.h
++++ b/drivers/char/drm/i915_drv.h
+@@ -76,8 +76,9 @@ struct mem_block {
+ typedef struct _drm_i915_vbl_swap {
+ struct list_head head;
+ drm_drawable_t drw_id;
+- unsigned int pipe;
++ unsigned int plane;
+ unsigned int sequence;
++ int flip;
+ } drm_i915_vbl_swap_t;
+
+ typedef struct drm_i915_private {
+@@ -90,7 +91,7 @@ typedef struct drm_i915_private {
+ drm_dma_handle_t *status_page_dmah;
+ void *hw_status_page;
+ dma_addr_t dma_status_page;
+- unsigned long counter;
++ uint32_t counter;
+ unsigned int status_gfx_addr;
+ drm_local_map_t hws_map;
+
+@@ -103,13 +104,18 @@ typedef struct drm_i915_private {
+
+ wait_queue_head_t irq_queue;
+ atomic_t irq_received;
+- atomic_t irq_emitted;
++ atomic_t irq_emited;
+
+ int tex_lru_log_granularity;
+ int allow_batchbuffer;
+ struct mem_block *agp_heap;
+ unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
+ int vblank_pipe;
++ spinlock_t user_irq_lock;
++ int user_irq_refcount;
++ int fence_irq_on;
++ uint32_t irq_enable_reg;
++ int irq_enabled;
+
+ spinlock_t swaps_lock;
+ drm_i915_vbl_swap_t vbl_swaps;
+@@ -216,7 +222,7 @@ extern void i915_driver_preclose(struct drm_device *dev,
+ extern int i915_driver_device_is_agp(struct drm_device * dev);
+ extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg);
+-
++extern void i915_dispatch_flip(struct drm_device * dev, int pipes, int sync);
+ /* i915_irq.c */
+ extern int i915_irq_emit(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+@@ -227,7 +233,7 @@ extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequenc
+ extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
+ extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
+ extern void i915_driver_irq_preinstall(struct drm_device * dev);
+-extern void i915_driver_irq_postinstall(struct drm_device * dev);
++extern int i915_driver_irq_postinstall(struct drm_device * dev);
+ extern void i915_driver_irq_uninstall(struct drm_device * dev);
+ extern int i915_vblank_pipe_set(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+@@ -235,6 +241,9 @@ extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+ extern int i915_vblank_swap(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
++extern int i915_enable_vblank(struct drm_device *dev, int crtc);
++extern void i915_disable_vblank(struct drm_device *dev, int crtc);
++extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc);
+
+ /* i915_mem.c */
+ extern int i915_mem_alloc(struct drm_device *dev, void *data,
+@@ -379,21 +388,91 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
+
+ /* Interrupt bits:
+ */
+-#define USER_INT_FLAG (1<<1)
+-#define VSYNC_PIPEB_FLAG (1<<5)
+-#define VSYNC_PIPEA_FLAG (1<<7)
+-#define HWB_OOM_FLAG (1<<13) /* binner out of memory */
++#define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18)
++#define I915_DISPLAY_PORT_INTERRUPT (1<<17)
++#define I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT (1<<15)
++#define I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT (1<<14)
++#define I915_HWB_OOM_INTERRUPT (1<<13) /* binner out of memory */
++#define I915_SYNC_STATUS_INTERRUPT (1<<12)
++#define I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT (1<<11)
++#define I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT (1<<10)
++#define I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT (1<<9)
++#define I915_DISPLAY_PLANE_C_FLIP_PENDING_INTERRUPT (1<<8)
++#define I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT (1<<7)
++#define I915_DISPLAY_PIPE_A_EVENT_INTERRUPT (1<<6)
++#define I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT (1<<5)
++#define I915_DISPLAY_PIPE_B_EVENT_INTERRUPT (1<<4)
++#define I915_DEBUG_INTERRUPT (1<<2)
++#define I915_USER_INTERRUPT (1<<1)
++
+
+ #define I915REG_HWSTAM 0x02098
+ #define I915REG_INT_IDENTITY_R 0x020a4
+ #define I915REG_INT_MASK_R 0x020a8
+ #define I915REG_INT_ENABLE_R 0x020a0
++#define I915REG_INSTPM 0x020c0
++
++#define PIPEADSL 0x70000
++#define PIPEBDSL 0x71000
+
+ #define I915REG_PIPEASTAT 0x70024
+ #define I915REG_PIPEBSTAT 0x71024
++/*
++ * The two pipe frame counter registers are not synchronized, so
++ * reading a stable value is somewhat tricky. The following code
++ * should work:
++ *
++ * do {
++ * high1 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
++ * PIPE_FRAME_HIGH_SHIFT;
++ * low1 = ((INREG(PIPEAFRAMEPIXEL) & PIPE_FRAME_LOW_MASK) >>
++ * PIPE_FRAME_LOW_SHIFT);
++ * high2 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
++ * PIPE_FRAME_HIGH_SHIFT);
++ * } while (high1 != high2);
++ * frame = (high1 << 8) | low1;
++ */
++#define PIPEAFRAMEHIGH 0x70040
++#define PIPEBFRAMEHIGH 0x71040
++#define PIPE_FRAME_HIGH_MASK 0x0000ffff
++#define PIPE_FRAME_HIGH_SHIFT 0
++#define PIPEAFRAMEPIXEL 0x70044
++#define PIPEBFRAMEPIXEL 0x71044
+
+-#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17)
+-#define I915_VBLANK_CLEAR (1UL<<1)
++#define PIPE_FRAME_LOW_MASK 0xff000000
++#define PIPE_FRAME_LOW_SHIFT 24
++/*
++ * Pixel within the current frame is counted in the PIPEAFRAMEPIXEL register
++ * and is 24 bits wide.
++ */
++#define PIPE_PIXEL_MASK 0x00ffffff
++#define PIPE_PIXEL_SHIFT 0
++
++#define I915_FIFO_UNDERRUN_STATUS (1UL<<31)
++#define I915_CRC_ERROR_ENABLE (1UL<<29)
++#define I915_CRC_DONE_ENABLE (1UL<<28)
++#define I915_GMBUS_EVENT_ENABLE (1UL<<27)
++#define I915_VSYNC_INTERRUPT_ENABLE (1UL<<25)
++#define I915_DISPLAY_LINE_COMPARE_ENABLE (1UL<<24)
++#define I915_DPST_EVENT_ENABLE (1UL<<23)
++#define I915_LEGACY_BLC_EVENT_ENABLE (1UL<<22)
++#define I915_ODD_FIELD_INTERRUPT_ENABLE (1UL<<21)
++#define I915_EVEN_FIELD_INTERRUPT_ENABLE (1UL<<20)
++#define I915_START_VBLANK_INTERRUPT_ENABLE (1UL<<18) /* 965 or later */
++#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17)
++#define I915_OVERLAY_UPDATED_ENABLE (1UL<<16)
++#define I915_CRC_ERROR_INTERRUPT_STATUS (1UL<<13)
++#define I915_CRC_DONE_INTERRUPT_STATUS (1UL<<12)
++#define I915_GMBUS_INTERRUPT_STATUS (1UL<<11)
++#define I915_VSYNC_INTERRUPT_STATUS (1UL<<9)
++#define I915_DISPLAY_LINE_COMPARE_STATUS (1UL<<8)
++#define I915_DPST_EVENT_STATUS (1UL<<7)
++#define I915_LEGACY_BLC_EVENT_STATUS (1UL<<6)
++#define I915_ODD_FIELD_INTERRUPT_STATUS (1UL<<5)
++#define I915_EVEN_FIELD_INTERRUPT_STATUS (1UL<<4)
++#define I915_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */
++#define I915_VBLANK_INTERRUPT_STATUS (1UL<<1)
++#define I915_OVERLAY_UPDATED_STATUS (1UL<<0)
+
+ #define SRX_INDEX 0x3c4
+ #define SRX_DATA 0x3c5
+@@ -566,6 +645,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
+ #define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6)
+ #define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21)
+ #define XY_SRC_COPY_BLT_WRITE_RGB (1<<20)
++#define XY_SRC_COPY_BLT_SRC_TILED (1<<15)
++#define XY_SRC_COPY_BLT_DST_TILED (1<<11)
+
+ #define MI_BATCH_BUFFER ((0x30<<23)|1)
+ #define MI_BATCH_BUFFER_START (0x31<<23)
+diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
+index 92653b3..023ce66 100644
+--- a/drivers/char/drm/i915_irq.c
++++ b/drivers/char/drm/i915_irq.c
+@@ -38,6 +38,109 @@
+ #define MAX_NOPID ((u32)~0)
+
+ /**
++ * i915_get_pipe - return the the pipe associated with a given plane
++ * @dev: DRM device
++ * @plane: plane to look for
++ *
++ * The Intel Mesa & 2D drivers call the vblank routines with a plane number
++ * rather than a pipe number, since they may not always be equal. This routine
++ * maps the given @plane back to a pipe number.
++ */
++static int
++i915_get_pipe(struct drm_device *dev, int plane)
++{
++ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
++ u32 dspcntr;
++
++ dspcntr = plane ? I915_READ(DSPBCNTR) : I915_READ(DSPACNTR);
++
++ return dspcntr & DISPPLANE_SEL_PIPE_MASK ? 1 : 0;
++}
++
++/**
++ * i915_get_plane - return the the plane associated with a given pipe
++ * @dev: DRM device
++ * @pipe: pipe to look for
++ *
++ * The Intel Mesa & 2D drivers call the vblank routines with a plane number
++ * rather than a plane number, since they may not always be equal. This routine
++ * maps the given @pipe back to a plane number.
++ */
++static int
++i915_get_plane(struct drm_device *dev, int pipe)
++{
++ if (i915_get_pipe(dev, 0) == pipe)
++ return 0;
++ return 1;
++}
++
++/**
++ * i915_pipe_enabled - check if a pipe is enabled
++ * @dev: DRM device
++ * @pipe: pipe to check
++ *
++ * Reading certain registers when the pipe is disabled can hang the chip.
++ * Use this routine to make sure the PLL is running and the pipe is active
++ * before reading such registers if unsure.
++ */
++static int
++i915_pipe_enabled(struct drm_device *dev, int pipe)
++{
++ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
++ unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF;
++
++ if (I915_READ(pipeconf) & PIPEACONF_ENABLE)
++ return 1;
++
++ return 0;
++}
++
++/**
++ * Emit a synchronous flip.
++ *
++ * This function must be called with the drawable spinlock held.
++ */
++static void
++i915_dispatch_vsync_flip(struct drm_device *dev, struct drm_drawable_info *drw,
++ int plane)
++{
++ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
++ drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
++ u16 x1, y1, x2, y2;
++ int pf_planes = 1 << plane;
++
++ /* If the window is visible on the other plane, we have to flip on that
++ * plane as well.
++ */
++ if (plane == 1) {
++ x1 = sarea_priv->planeA_x;
++ y1 = sarea_priv->planeA_y;
++ x2 = x1 + sarea_priv->planeA_w;
++ y2 = y1 + sarea_priv->planeA_h;
++ } else {
++ x1 = sarea_priv->planeB_x;
++ y1 = sarea_priv->planeB_y;
++ x2 = x1 + sarea_priv->planeB_w;
++ y2 = y1 + sarea_priv->planeB_h;
++ }
++
++ if (x2 > 0 && y2 > 0) {
++ int i, num_rects = drw->num_rects;
++ struct drm_clip_rect *rect = drw->rects;
++
++ for (i = 0; i < num_rects; i++)
++ if (!(rect[i].x1 >= x2 || rect[i].y1 >= y2 ||
++ rect[i].x2 <= x1 || rect[i].y2 <= y1)) {
++ pf_planes = 0x3;
++
++ break;
++ }
++ }
++
++ i915_dispatch_flip(dev, pf_planes, 1);
++}
++
++/**
+ * Emit blits for scheduled buffer swaps.
+ *
+ * This function will be called with the HW lock held.
+@@ -45,40 +148,59 @@
+ static void i915_vblank_tasklet(struct drm_device *dev)
+ {
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+- unsigned long irqflags;
+ struct list_head *list, *tmp, hits, *hit;
+- int nhits, nrects, slice[2], upper[2], lower[2], i;
+- unsigned counter[2] = { atomic_read(&dev->vbl_received),
+- atomic_read(&dev->vbl_received2) };
++ int nhits, nrects, slice[2], upper[2], lower[2], i, num_pages;
++ unsigned counter[2];
+ struct drm_drawable_info *drw;
+ drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
+- u32 cpp = dev_priv->cpp;
++ u32 cpp = dev_priv->cpp, offsets[3];
+ u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB)
+ : XY_SRC_COPY_BLT_CMD;
+- u32 pitchropcpp = (sarea_priv->pitch * cpp) | (0xcc << 16) |
+- (cpp << 23) | (1 << 24);
++ u32 src_pitch = sarea_priv->pitch * cpp;
++ u32 dst_pitch = sarea_priv->pitch * cpp;
++ /* COPY rop (0xcc), map cpp to magic color depth constants */
++ u32 ropcpp = (0xcc << 16) | ((cpp - 1) << 24);
+ RING_LOCALS;
+
++ if (sarea_priv->front_tiled) {
++ cmd |= XY_SRC_COPY_BLT_DST_TILED;
++ dst_pitch >>= 2;
++ }
++ if (sarea_priv->back_tiled) {
++ cmd |= XY_SRC_COPY_BLT_SRC_TILED;
++ src_pitch >>= 2;
++ }
++
++ counter[0] = drm_vblank_count(dev, 0);
++ counter[1] = drm_vblank_count(dev, 1);
++
+ DRM_DEBUG("\n");
+
+ INIT_LIST_HEAD(&hits);
+
+ nhits = nrects = 0;
+
+- spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
++ /* No irqsave/restore necessary. This tasklet may be run in an
++ * interrupt context or normal context, but we don't have to worry
++ * about getting interrupted by something acquiring the lock, because
++ * we are the interrupt context thing that acquires the lock.
++ */
++ spin_lock(&dev_priv->swaps_lock);
+
+ /* Find buffer swaps scheduled for this vertical blank */
+ list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) {
+ drm_i915_vbl_swap_t *vbl_swap =
+ list_entry(list, drm_i915_vbl_swap_t, head);
++ int pipe = i915_get_pipe(dev, vbl_swap->plane);
+
+- if ((counter[vbl_swap->pipe] - vbl_swap->sequence) > (1<<23))
++ if ((counter[pipe] - vbl_swap->sequence) > (1<<23))
+ continue;
+
+ list_del(list);
+ dev_priv->swaps_pending--;
++ drm_vblank_put(dev, pipe);
+
+ spin_unlock(&dev_priv->swaps_lock);
+ spin_lock(&dev->drw_lock);
+@@ -116,33 +238,23 @@ static void i915_vblank_tasklet(struct drm_device *dev)
+ spin_lock(&dev_priv->swaps_lock);
+ }
+
+- if (nhits == 0) {
+- spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+- return;
+- }
+-
+ spin_unlock(&dev_priv->swaps_lock);
+
+- i915_kernel_lost_context(dev);
+-
+- BEGIN_LP_RING(6);
+-
+- OUT_RING(GFX_OP_DRAWRECT_INFO);
+- OUT_RING(0);
+- OUT_RING(0);
+- OUT_RING(sarea_priv->width | sarea_priv->height << 16);
+- OUT_RING(sarea_priv->width | sarea_priv->height << 16);
+- OUT_RING(0);
+-
+- ADVANCE_LP_RING();
++ if (nhits == 0)
++ return;
+
+- sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT;
++ i915_kernel_lost_context(dev);
+
+ upper[0] = upper[1] = 0;
+- slice[0] = max(sarea_priv->pipeA_h / nhits, 1);
+- slice[1] = max(sarea_priv->pipeB_h / nhits, 1);
+- lower[0] = sarea_priv->pipeA_y + slice[0];
+- lower[1] = sarea_priv->pipeB_y + slice[0];
++ slice[0] = max(sarea_priv->planeA_h / nhits, 1);
++ slice[1] = max(sarea_priv->planeB_h / nhits, 1);
++ lower[0] = sarea_priv->planeA_y + slice[0];
++ lower[1] = sarea_priv->planeB_y + slice[0];
++
++ offsets[0] = sarea_priv->front_offset;
++ offsets[1] = sarea_priv->back_offset;
++ offsets[2] = sarea_priv->third_offset;
++ num_pages = sarea_priv->third_handle ? 3 : 2;
+
+ spin_lock(&dev->drw_lock);
+
+@@ -154,6 +266,8 @@ static void i915_vblank_tasklet(struct drm_device *dev)
+ for (i = 0; i++ < nhits;
+ upper[0] = lower[0], lower[0] += slice[0],
+ upper[1] = lower[1], lower[1] += slice[1]) {
++ int init_drawrect = 1;
++
+ if (i == nhits)
+ lower[0] = lower[1] = sarea_priv->height;
+
+@@ -161,7 +275,7 @@ static void i915_vblank_tasklet(struct drm_device *dev)
+ drm_i915_vbl_swap_t *swap_hit =
+ list_entry(hit, drm_i915_vbl_swap_t, head);
+ struct drm_clip_rect *rect;
+- int num_rects, pipe;
++ int num_rects, plane, front, back;
+ unsigned short top, bottom;
+
+ drw = drm_get_drawable_info(dev, swap_hit->drw_id);
+@@ -169,10 +283,50 @@ static void i915_vblank_tasklet(struct drm_device *dev)
+ if (!drw)
+ continue;
+
++ plane = swap_hit->plane;
++
++ if (swap_hit->flip) {
++ i915_dispatch_vsync_flip(dev, drw, plane);
++ continue;
++ }
++
++ if (init_drawrect) {
++ int width = sarea_priv->width;
++ int height = sarea_priv->height;
++ if (IS_I965G(dev)) {
++ BEGIN_LP_RING(4);
++
++ OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
++ OUT_RING(0);
++ OUT_RING(((width - 1) & 0xffff) | ((height - 1) << 16));
++ OUT_RING(0);
++
++ ADVANCE_LP_RING();
++ } else {
++ BEGIN_LP_RING(6);
++
++ OUT_RING(GFX_OP_DRAWRECT_INFO);
++ OUT_RING(0);
++ OUT_RING(0);
++ OUT_RING(((width - 1) & 0xffff) | ((height - 1) << 16));
++ OUT_RING(0);
++ OUT_RING(0);
++
++ ADVANCE_LP_RING();
++ }
++
++ sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT;
++
++ init_drawrect = 0;
++ }
++
+ rect = drw->rects;
+- pipe = swap_hit->pipe;
+- top = upper[pipe];
+- bottom = lower[pipe];
++ top = upper[plane];
++ bottom = lower[plane];
++
++ front = (dev_priv->sarea_priv->pf_current_page >>
++ (2 * plane)) & 0x3;
++ back = (front + 1) % num_pages;
+
+ for (num_rects = drw->num_rects; num_rects--; rect++) {
+ int y1 = max(rect->y1, top);
+@@ -184,20 +338,20 @@ static void i915_vblank_tasklet(struct drm_device *dev)
+ BEGIN_LP_RING(8);
+
+ OUT_RING(cmd);
+- OUT_RING(pitchropcpp);
++ OUT_RING(ropcpp | dst_pitch);
+ OUT_RING((y1 << 16) | rect->x1);
+ OUT_RING((y2 << 16) | rect->x2);
+- OUT_RING(sarea_priv->front_offset);
++ OUT_RING(offsets[front]);
+ OUT_RING((y1 << 16) | rect->x1);
+- OUT_RING(pitchropcpp & 0xffff);
+- OUT_RING(sarea_priv->back_offset);
++ OUT_RING(src_pitch);
++ OUT_RING(offsets[back]);
+
+ ADVANCE_LP_RING();
+ }
+ }
+ }
+
+- spin_unlock_irqrestore(&dev->drw_lock, irqflags);
++ spin_unlock(&dev->drw_lock);
+
+ list_for_each_safe(hit, tmp, &hits) {
+ drm_i915_vbl_swap_t *swap_hit =
+@@ -209,67 +363,112 @@ static void i915_vblank_tasklet(struct drm_device *dev)
+ }
+ }
+
++u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
++{
++ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
++ unsigned long high_frame;
++ unsigned long low_frame;
++ u32 high1, high2, low, count;
++ int pipe;
++
++ pipe = i915_get_pipe(dev, plane);
++ high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
++ low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
++
++ if (!i915_pipe_enabled(dev, pipe)) {
++ printk(KERN_ERR "trying to get vblank count for disabled "
++ "pipe %d\n", pipe);
++ return 0;
++ }
++
++ /*
++ * High & low register fields aren't synchronized, so make sure
++ * we get a low value that's stable across two reads of the high
++ * register.
++ */
++ do {
++ high1 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
++ PIPE_FRAME_HIGH_SHIFT);
++ low = ((I915_READ(low_frame) & PIPE_FRAME_LOW_MASK) >>
++ PIPE_FRAME_LOW_SHIFT);
++ high2 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
++ PIPE_FRAME_HIGH_SHIFT);
++ } while (high1 != high2);
++
++ count = (high1 << 8) | low;
++
++ /* count may be reset by other driver(e.g. 2D driver),
++ we have no way to know if it is wrapped or resetted
++ when count is zero. do a rough guess.
++ */
++ if (count == 0 && dev->last_vblank[pipe] < dev->max_vblank_count/2)
++ dev->last_vblank[pipe] = 0;
++
++ return count;
++}
++
+ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
+ {
+ struct drm_device *dev = (struct drm_device *) arg;
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+- u16 temp;
++ u32 iir;
+ u32 pipea_stats, pipeb_stats;
+-
+- pipea_stats = I915_READ(I915REG_PIPEASTAT);
+- pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
+-
+- temp = I915_READ16(I915REG_INT_IDENTITY_R);
+-
+- temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG);
+-
+- DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
+-
+- if (temp == 0)
++ int vblank = 0;
++
++ iir = I915_READ(I915REG_INT_IDENTITY_R);
++ if (iir == 0) {
++ DRM_DEBUG ("iir 0x%08x im 0x%08x ie 0x%08x pipea 0x%08x pipeb 0x%08x\n",
++ iir,
++ I915_READ(I915REG_INT_MASK_R),
++ I915_READ(I915REG_INT_ENABLE_R),
++ I915_READ(I915REG_PIPEASTAT),
++ I915_READ(I915REG_PIPEBSTAT));
+ return IRQ_NONE;
++ }
+
+- I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
+- (void) I915_READ16(I915REG_INT_IDENTITY_R);
+- DRM_READMEMORYBARRIER();
+-
+- dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
++ /*
++ * Clear the PIPE(A|B)STAT regs before the IIR otherwise
++ * we may get extra interrupts.
++ */
++ if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {
++ pipea_stats = I915_READ(I915REG_PIPEASTAT);
++ if (pipea_stats & (I915_START_VBLANK_INTERRUPT_STATUS|
++ I915_VBLANK_INTERRUPT_STATUS))
++ {
++ vblank++;
++ drm_handle_vblank(dev, i915_get_plane(dev, 0));
++ }
++ I915_WRITE(I915REG_PIPEASTAT, pipea_stats);
++ }
++ if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
++ pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
++ if (pipeb_stats & (I915_START_VBLANK_INTERRUPT_STATUS|
++ I915_VBLANK_INTERRUPT_STATUS))
++ {
++ vblank++;
++ drm_handle_vblank(dev, i915_get_plane(dev, 1));
++ }
++ I915_WRITE(I915REG_PIPEBSTAT, pipeb_stats);
++ }
+
+- if (temp & USER_INT_FLAG)
+- DRM_WAKEUP(&dev_priv->irq_queue);
++ if (dev_priv->sarea_priv)
++ dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+
+- if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
+- int vblank_pipe = dev_priv->vblank_pipe;
+-
+- if ((vblank_pipe &
+- (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B))
+- == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) {
+- if (temp & VSYNC_PIPEA_FLAG)
+- atomic_inc(&dev->vbl_received);
+- if (temp & VSYNC_PIPEB_FLAG)
+- atomic_inc(&dev->vbl_received2);
+- } else if (((temp & VSYNC_PIPEA_FLAG) &&
+- (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) ||
+- ((temp & VSYNC_PIPEB_FLAG) &&
+- (vblank_pipe & DRM_I915_VBLANK_PIPE_B)))
+- atomic_inc(&dev->vbl_received);
+-
+- DRM_WAKEUP(&dev->vbl_queue);
+- drm_vbl_send_signals(dev);
++ I915_WRITE(I915REG_INT_IDENTITY_R, iir);
++ (void) I915_READ(I915REG_INT_IDENTITY_R); /* Flush posted write */
+
++ if (iir & I915_USER_INTERRUPT) {
++ DRM_WAKEUP(&dev_priv->irq_queue);
++ }
++ if (vblank) {
+ if (dev_priv->swaps_pending > 0)
+ drm_locked_tasklet(dev, i915_vblank_tasklet);
+- I915_WRITE(I915REG_PIPEASTAT,
+- pipea_stats|I915_VBLANK_INTERRUPT_ENABLE|
+- I915_VBLANK_CLEAR);
+- I915_WRITE(I915REG_PIPEBSTAT,
+- pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE|
+- I915_VBLANK_CLEAR);
+ }
+
+ return IRQ_HANDLED;
+ }
+
+-static int i915_emit_irq(struct drm_device * dev)
++static int i915_emit_irq(struct drm_device *dev)
+ {
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ RING_LOCALS;
+@@ -316,42 +515,12 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
+ READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
+ }
+
+- dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+- return ret;
+-}
+-
+-static int i915_driver_vblank_do_wait(struct drm_device *dev, unsigned int *sequence,
+- atomic_t *counter)
+-{
+- drm_i915_private_t *dev_priv = dev->dev_private;
+- unsigned int cur_vblank;
+- int ret = 0;
+-
+- if (!dev_priv) {
+- DRM_ERROR("called with no initialization\n");
+- return -EINVAL;
+- }
+-
+- DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+- (((cur_vblank = atomic_read(counter))
+- - *sequence) <= (1<<23)));
+-
+- *sequence = cur_vblank;
+-
++ if (dev_priv->sarea_priv)
++ dev_priv->sarea_priv->last_dispatch =
++ READ_BREADCRUMB(dev_priv);
+ return ret;
+ }
+
+-
+-int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
+-{
+- return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received);
+-}
+-
+-int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
+-{
+- return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2);
+-}
+-
+ /* Needs the lock as it touches the ring.
+ */
+ int i915_irq_emit(struct drm_device *dev, void *data,
+@@ -394,18 +563,96 @@ int i915_irq_wait(struct drm_device *dev, void *data,
+ return i915_wait_irq(dev, irqwait->irq_seq);
+ }
+
++int i915_enable_vblank(struct drm_device *dev, int plane)
++{
++ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
++ int pipe = i915_get_pipe(dev, plane);
++ u32 pipestat_reg = 0;
++ u32 pipestat;
++
++ switch (pipe) {
++ case 0:
++ pipestat_reg = I915REG_PIPEASTAT;
++ dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
++ break;
++ case 1:
++ pipestat_reg = I915REG_PIPEBSTAT;
++ dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
++ break;
++ default:
++ DRM_ERROR("tried to enable vblank on non-existent pipe %d\n",
++ pipe);
++ break;
++ }
++
++ if (pipestat_reg)
++ {
++ pipestat = I915_READ (pipestat_reg);
++ /*
++ * Older chips didn't have the start vblank interrupt,
++ * but
++ */
++ if (IS_I965G (dev))
++ pipestat |= I915_START_VBLANK_INTERRUPT_ENABLE;
++ else
++ pipestat |= I915_VBLANK_INTERRUPT_ENABLE;
++ /*
++ * Clear any pending status
++ */
++ pipestat |= (I915_START_VBLANK_INTERRUPT_STATUS |
++ I915_VBLANK_INTERRUPT_STATUS);
++ I915_WRITE(pipestat_reg, pipestat);
++ }
++ I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
++
++ return 0;
++}
++
++void i915_disable_vblank(struct drm_device *dev, int plane)
++{
++ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
++ int pipe = i915_get_pipe(dev, plane);
++ u32 pipestat_reg = 0;
++ u32 pipestat;
++
++ switch (pipe) {
++ case 0:
++ pipestat_reg = I915REG_PIPEASTAT;
++ dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
++ break;
++ case 1:
++ pipestat_reg = I915REG_PIPEBSTAT;
++ dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
++ break;
++ default:
++ DRM_ERROR("tried to disable vblank on non-existent pipe %d\n",
++ pipe);
++ break;
++ }
++
++ I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
++ if (pipestat_reg)
++ {
++ pipestat = I915_READ (pipestat_reg);
++ pipestat &= ~(I915_START_VBLANK_INTERRUPT_ENABLE |
++ I915_VBLANK_INTERRUPT_ENABLE);
++ /*
++ * Clear any pending status
++ */
++ pipestat |= (I915_START_VBLANK_INTERRUPT_STATUS |
++ I915_VBLANK_INTERRUPT_STATUS);
++ I915_WRITE(pipestat_reg, pipestat);
++ }
++}
++
+ static void i915_enable_interrupt (struct drm_device *dev)
+ {
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+- u16 flag;
+
+- flag = 0;
+- if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
+- flag |= VSYNC_PIPEA_FLAG;
+- if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
+- flag |= VSYNC_PIPEB_FLAG;
++ dev_priv->irq_enable_reg |= I915_USER_INTERRUPT;
+
+- I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag);
++ I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
++ dev_priv->irq_enabled = 1;
+ }
+
+ /* Set the vblank monitor pipe
+@@ -428,8 +675,6 @@ int i915_vblank_pipe_set(struct drm_device *dev, void *data,
+
+ dev_priv->vblank_pipe = pipe->pipe;
+
+- i915_enable_interrupt (dev);
+-
+ return 0;
+ }
+
+@@ -447,9 +692,9 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data,
+
+ flag = I915_READ(I915REG_INT_ENABLE_R);
+ pipe->pipe = 0;
+- if (flag & VSYNC_PIPEA_FLAG)
++ if (flag & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT)
+ pipe->pipe |= DRM_I915_VBLANK_PIPE_A;
+- if (flag & VSYNC_PIPEB_FLAG)
++ if (flag & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
+ pipe->pipe |= DRM_I915_VBLANK_PIPE_B;
+
+ return 0;
+@@ -464,27 +709,30 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ drm_i915_vblank_swap_t *swap = data;
+ drm_i915_vbl_swap_t *vbl_swap;
+- unsigned int pipe, seqtype, curseq;
++ unsigned int pipe, seqtype, curseq, plane;
+ unsigned long irqflags;
+ struct list_head *list;
++ int ret;
+
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __func__);
+ return -EINVAL;
+ }
+
+- if (dev_priv->sarea_priv->rotation) {
++ if (!dev_priv->sarea_priv || dev_priv->sarea_priv->rotation) {
+ DRM_DEBUG("Rotation not supported\n");
+ return -EINVAL;
+ }
+
+ if (swap->seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE |
+- _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS)) {
++ _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS |
++ _DRM_VBLANK_FLIP)) {
+ DRM_ERROR("Invalid sequence type 0x%x\n", swap->seqtype);
+ return -EINVAL;
+ }
+
+- pipe = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
++ plane = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
++ pipe = i915_get_pipe(dev, plane);
+
+ seqtype = swap->seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE);
+
+@@ -495,6 +743,11 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
+
+ spin_lock_irqsave(&dev->drw_lock, irqflags);
+
++ /* It makes no sense to schedule a swap for a drawable that doesn't have
++ * valid information at this point. E.g. this could mean that the X
++ * server is too old to push drawable information to the DRM, in which
++ * case all such swaps would become ineffective.
++ */
+ if (!drm_get_drawable_info(dev, swap->drawable)) {
+ spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+ DRM_DEBUG("Invalid drawable ID %d\n", swap->drawable);
+@@ -503,7 +756,8 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
+
+ spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+
+- curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received);
++ drm_update_vblank_count(dev, pipe);
++ curseq = drm_vblank_count(dev, pipe);
+
+ if (seqtype == _DRM_VBLANK_RELATIVE)
+ swap->sequence += curseq;
+@@ -517,14 +771,43 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
+ }
+ }
+
++ if (swap->seqtype & _DRM_VBLANK_FLIP) {
++ swap->sequence--;
++
++ if ((curseq - swap->sequence) <= (1<<23)) {
++ struct drm_drawable_info *drw;
++
++ LOCK_TEST_WITH_RETURN(dev, file_priv);
++
++ spin_lock_irqsave(&dev->drw_lock, irqflags);
++
++ drw = drm_get_drawable_info(dev, swap->drawable);
++
++ if (!drw) {
++ spin_unlock_irqrestore(&dev->drw_lock,
++ irqflags);
++ DRM_DEBUG("Invalid drawable ID %d\n",
++ swap->drawable);
++ return -EINVAL;
++ }
++
++ i915_dispatch_vsync_flip(dev, drw, plane);
++
++ spin_unlock_irqrestore(&dev->drw_lock, irqflags);
++
++ return 0;
++ }
++ }
++
+ spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
+
+ list_for_each(list, &dev_priv->vbl_swaps.head) {
+ vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);
+
+ if (vbl_swap->drw_id == swap->drawable &&
+- vbl_swap->pipe == pipe &&
++ vbl_swap->plane == plane &&
+ vbl_swap->sequence == swap->sequence) {
++ vbl_swap->flip = (swap->seqtype & _DRM_VBLANK_FLIP);
+ spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+ DRM_DEBUG("Already scheduled\n");
+ return 0;
+@@ -547,9 +830,19 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
+
+ DRM_DEBUG("\n");
+
++ ret = drm_vblank_get(dev, pipe);
++ if (ret) {
++ drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER);
++ return ret;
++ }
++
+ vbl_swap->drw_id = swap->drawable;
+- vbl_swap->pipe = pipe;
++ vbl_swap->plane = plane;
+ vbl_swap->sequence = swap->sequence;
++ vbl_swap->flip = (swap->seqtype & _DRM_VBLANK_FLIP);
++
++ if (vbl_swap->flip)
++ swap->sequence++;
+
+ spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
+
+@@ -567,37 +860,57 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
+ {
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+- I915_WRITE16(I915REG_HWSTAM, 0xfffe);
++ I915_WRITE16(I915REG_HWSTAM, 0xeffe);
+ I915_WRITE16(I915REG_INT_MASK_R, 0x0);
+ I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
+ }
+
+-void i915_driver_irq_postinstall(struct drm_device * dev)
++int i915_driver_irq_postinstall(struct drm_device * dev)
+ {
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
++ int ret, num_pipes = 2;
+
+ spin_lock_init(&dev_priv->swaps_lock);
+ INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
+ dev_priv->swaps_pending = 0;
+
+- if (!dev_priv->vblank_pipe)
+- dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A;
++ dev_priv->user_irq_refcount = 0;
++ dev_priv->irq_enable_reg = 0;
++
++ ret = drm_vblank_init(dev, num_pipes);
++ if (ret)
++ return ret;
++
++ dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
++
+ i915_enable_interrupt(dev);
+ DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
++
++ /*
++ * Initialize the hardware status page IRQ location.
++ */
++
++ I915_WRITE(I915REG_INSTPM, (1 << 5) | (1 << 21));
++ return 0;
+ }
+
+ void i915_driver_irq_uninstall(struct drm_device * dev)
+ {
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+- u16 temp;
++ u32 temp;
+
+ if (!dev_priv)
+ return;
+
+- I915_WRITE16(I915REG_HWSTAM, 0xffff);
+- I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
+- I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
+-
+- temp = I915_READ16(I915REG_INT_IDENTITY_R);
+- I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
++ dev_priv->irq_enabled = 0;
++ I915_WRITE(I915REG_HWSTAM, 0xffffffff);
++ I915_WRITE(I915REG_INT_MASK_R, 0xffffffff);
++ I915_WRITE(I915REG_INT_ENABLE_R, 0x0);
++
++ temp = I915_READ(I915REG_PIPEASTAT);
++ I915_WRITE(I915REG_PIPEASTAT, temp);
++ temp = I915_READ(I915REG_PIPEBSTAT);
++ I915_WRITE(I915REG_PIPEBSTAT, temp);
++ temp = I915_READ(I915REG_INT_IDENTITY_R);
++ I915_WRITE(I915REG_INT_IDENTITY_R, temp);
+ }
+diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c
+index 5572939..6b37909 100644
+--- a/drivers/char/drm/mga_drv.c
++++ b/drivers/char/drm/mga_drv.c
+@@ -45,15 +45,16 @@ static struct pci_device_id pciidlist[] = {
+ static struct drm_driver driver = {
+ .driver_features =
+ DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA |
+- DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
+- DRIVER_IRQ_VBL,
++ DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
+ .dev_priv_size = sizeof(drm_mga_buf_priv_t),
+ .load = mga_driver_load,
+ .unload = mga_driver_unload,
+ .lastclose = mga_driver_lastclose,
+ .dma_quiescent = mga_driver_dma_quiescent,
+ .device_is_agp = mga_driver_device_is_agp,
+- .vblank_wait = mga_driver_vblank_wait,
++ .get_vblank_counter = mga_get_vblank_counter,
++ .enable_vblank = mga_enable_vblank,
++ .disable_vblank = mga_disable_vblank,
+ .irq_preinstall = mga_driver_irq_preinstall,
+ .irq_postinstall = mga_driver_irq_postinstall,
+ .irq_uninstall = mga_driver_irq_uninstall,
+diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h
+index f6ebd24..8f7291f 100644
+--- a/drivers/char/drm/mga_drv.h
++++ b/drivers/char/drm/mga_drv.h
+@@ -120,6 +120,7 @@ typedef struct drm_mga_private {
+ u32 clear_cmd;
+ u32 maccess;
+
++ atomic_t vbl_received; /**< Number of vblanks received. */
+ wait_queue_head_t fence_queue;
+ atomic_t last_fence_retired;
+ u32 next_fence_to_post;
+@@ -181,11 +182,14 @@ extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv);
+ extern int mga_warp_init(drm_mga_private_t * dev_priv);
+
+ /* mga_irq.c */
++extern int mga_enable_vblank(struct drm_device *dev, int crtc);
++extern void mga_disable_vblank(struct drm_device *dev, int crtc);
++extern u32 mga_get_vblank_counter(struct drm_device *dev, int crtc);
+ extern int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence);
+ extern int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
+ extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
+ extern void mga_driver_irq_preinstall(struct drm_device * dev);
+-extern void mga_driver_irq_postinstall(struct drm_device * dev);
++extern int mga_driver_irq_postinstall(struct drm_device * dev);
+ extern void mga_driver_irq_uninstall(struct drm_device * dev);
+ extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg);
+diff --git a/drivers/char/drm/mga_irq.c b/drivers/char/drm/mga_irq.c
+index 9302cb8..06852fb 100644
+--- a/drivers/char/drm/mga_irq.c
++++ b/drivers/char/drm/mga_irq.c
+@@ -35,6 +35,20 @@
+ #include "mga_drm.h"
+ #include "mga_drv.h"
+
++u32 mga_get_vblank_counter(struct drm_device *dev, int crtc)
++{
++ const drm_mga_private_t *const dev_priv =
++ (drm_mga_private_t *) dev->dev_private;
++
++ if (crtc != 0) {
++ return 0;
++ }
++
++
++ return atomic_read(&dev_priv->vbl_received);
++}
++
++
+ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
+ {
+ struct drm_device *dev = (struct drm_device *) arg;
+@@ -47,9 +61,8 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
+ /* VBLANK interrupt */
+ if (status & MGA_VLINEPEN) {
+ MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR);
+- atomic_inc(&dev->vbl_received);
+- DRM_WAKEUP(&dev->vbl_queue);
+- drm_vbl_send_signals(dev);
++ atomic_inc(&dev_priv->vbl_received);
++ drm_handle_vblank(dev, 0);
+ handled = 1;
+ }
+
+@@ -78,22 +91,34 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
+ return IRQ_NONE;
+ }
+
+-int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
++int mga_enable_vblank(struct drm_device *dev, int crtc)
+ {
+- unsigned int cur_vblank;
+- int ret = 0;
++ drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+
+- /* Assume that the user has missed the current sequence number
+- * by about a day rather than she wants to wait for years
+- * using vertical blanks...
+- */
+- DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+- (((cur_vblank = atomic_read(&dev->vbl_received))
+- - *sequence) <= (1 << 23)));
++ if (crtc != 0) {
++ DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
++ crtc);
++ return 0;
++ }
+
+- *sequence = cur_vblank;
++ MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
++ return 0;
++}
+
+- return ret;
++
++void mga_disable_vblank(struct drm_device *dev, int crtc)
++{
++ if (crtc != 0) {
++ DRM_ERROR("tried to disable vblank on non-existent crtc %d\n",
++ crtc);
++ }
++
++ /* Do *NOT* disable the vertical refresh interrupt. MGA doesn't have
++ * a nice hardware counter that tracks the number of refreshes when
++ * the interrupt is disabled, and the kernel doesn't know the refresh
++ * rate to calculate an estimate.
++ */
++ /* MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); */
+ }
+
+ int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
+@@ -125,14 +150,22 @@ void mga_driver_irq_preinstall(struct drm_device * dev)
+ MGA_WRITE(MGA_ICLEAR, ~0);
+ }
+
+-void mga_driver_irq_postinstall(struct drm_device * dev)
++int mga_driver_irq_postinstall(struct drm_device * dev)
+ {
+ drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
++ int ret;
++
++ ret = drm_vblank_init(dev, 1);
++ if (ret)
++ return ret;
+
+ DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
+
+- /* Turn on vertical blank interrupt and soft trap interrupt. */
+- MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
++ /* Turn on soft trap interrupt. Vertical blank interrupts are enabled
++ * in mga_enable_vblank.
++ */
++ MGA_WRITE(MGA_IEN, MGA_SOFTRAPEN);
++ return 0;
+ }
+
+ void mga_driver_irq_uninstall(struct drm_device * dev)
+diff --git a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c
+index 6108e75..2888aa0 100644
+--- a/drivers/char/drm/r128_drv.c
++++ b/drivers/char/drm/r128_drv.c
+@@ -43,12 +43,13 @@ static struct pci_device_id pciidlist[] = {
+ static struct drm_driver driver = {
+ .driver_features =
+ DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
+- DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
+- DRIVER_IRQ_VBL,
++ DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
+ .dev_priv_size = sizeof(drm_r128_buf_priv_t),
+ .preclose = r128_driver_preclose,
+ .lastclose = r128_driver_lastclose,
+- .vblank_wait = r128_driver_vblank_wait,
++ .get_vblank_counter = r128_get_vblank_counter,
++ .enable_vblank = r128_enable_vblank,
++ .disable_vblank = r128_disable_vblank,
+ .irq_preinstall = r128_driver_irq_preinstall,
+ .irq_postinstall = r128_driver_irq_postinstall,
+ .irq_uninstall = r128_driver_irq_uninstall,
+diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
+index 011105e..80af9e0 100644
+--- a/drivers/char/drm/r128_drv.h
++++ b/drivers/char/drm/r128_drv.h
+@@ -97,6 +97,8 @@ typedef struct drm_r128_private {
+ u32 crtc_offset;
+ u32 crtc_offset_cntl;
+
++ atomic_t vbl_received;
++
+ u32 color_fmt;
+ unsigned int front_offset;
+ unsigned int front_pitch;
+@@ -149,11 +151,12 @@ extern int r128_wait_ring(drm_r128_private_t * dev_priv, int n);
+ extern int r128_do_cce_idle(drm_r128_private_t * dev_priv);
+ extern int r128_do_cleanup_cce(struct drm_device * dev);
+
+-extern int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
+-
++extern int r128_enable_vblank(struct drm_device *dev, int crtc);
++extern void r128_disable_vblank(struct drm_device *dev, int crtc);
++extern u32 r128_get_vblank_counter(struct drm_device *dev, int crtc);
+ extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS);
+ extern void r128_driver_irq_preinstall(struct drm_device * dev);
+-extern void r128_driver_irq_postinstall(struct drm_device * dev);
++extern int r128_driver_irq_postinstall(struct drm_device * dev);
+ extern void r128_driver_irq_uninstall(struct drm_device * dev);
+ extern void r128_driver_lastclose(struct drm_device * dev);
+ extern void r128_driver_preclose(struct drm_device * dev,
+diff --git a/drivers/char/drm/r128_irq.c b/drivers/char/drm/r128_irq.c
+index c76fdca..5b95bd8 100644
+--- a/drivers/char/drm/r128_irq.c
++++ b/drivers/char/drm/r128_irq.c
+@@ -35,6 +35,16 @@
+ #include "r128_drm.h"
+ #include "r128_drv.h"
+
++u32 r128_get_vblank_counter(struct drm_device *dev, int crtc)
++{
++ const drm_r128_private_t *dev_priv = dev->dev_private;
++
++ if (crtc != 0)
++ return 0;
++
++ return atomic_read(&dev_priv->vbl_received);
++}
++
+ irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
+ {
+ struct drm_device *dev = (struct drm_device *) arg;
+@@ -46,30 +56,38 @@ irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
+ /* VBLANK interrupt */
+ if (status & R128_CRTC_VBLANK_INT) {
+ R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
+- atomic_inc(&dev->vbl_received);
+- DRM_WAKEUP(&dev->vbl_queue);
+- drm_vbl_send_signals(dev);
++ atomic_inc(&dev_priv->vbl_received);
++ drm_handle_vblank(dev, 0);
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+ }
+
+-int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
++int r128_enable_vblank(struct drm_device *dev, int crtc)
+ {
+- unsigned int cur_vblank;
+- int ret = 0;
++ drm_r128_private_t *dev_priv = dev->dev_private;
+
+- /* Assume that the user has missed the current sequence number
+- * by about a day rather than she wants to wait for years
+- * using vertical blanks...
+- */
+- DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+- (((cur_vblank = atomic_read(&dev->vbl_received))
+- - *sequence) <= (1 << 23)));
++ if (crtc != 0) {
++ DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc);
++ return -EINVAL;
++ }
+
+- *sequence = cur_vblank;
++ R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
++ return 0;
++}
++
++void r128_disable_vblank(struct drm_device *dev, int crtc)
++{
++ if (crtc != 0)
++ DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc);
+
+- return ret;
++ /*
++ * FIXME: implement proper interrupt disable by using the vblank
++ * counter register (if available)
++ *
++ * R128_WRITE(R128_GEN_INT_CNTL,
++ * R128_READ(R128_GEN_INT_CNTL) & ~R128_CRTC_VBLANK_INT_EN);
++ */
+ }
+
+ void r128_driver_irq_preinstall(struct drm_device * dev)
+@@ -82,12 +100,9 @@ void r128_driver_irq_preinstall(struct drm_device * dev)
+ R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
+ }
+
+-void r128_driver_irq_postinstall(struct drm_device * dev)
++int r128_driver_irq_postinstall(struct drm_device * dev)
+ {
+- drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
+-
+- /* Turn on VBL interrupt */
+- R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
++ return drm_vblank_init(dev, 1);
+ }
+
+ void r128_driver_irq_uninstall(struct drm_device * dev)
+diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
+index 349ac3d..a261031 100644
+--- a/drivers/char/drm/radeon_drv.c
++++ b/drivers/char/drm/radeon_drv.c
+@@ -59,8 +59,7 @@ static struct pci_device_id pciidlist[] = {
+ static struct drm_driver driver = {
+ .driver_features =
+ DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
+- DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED |
+- DRIVER_IRQ_VBL | DRIVER_IRQ_VBL2,
++ DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED,
+ .dev_priv_size = sizeof(drm_radeon_buf_priv_t),
+ .load = radeon_driver_load,
+ .firstopen = radeon_driver_firstopen,
+@@ -69,8 +68,9 @@ static struct drm_driver driver = {
+ .postclose = radeon_driver_postclose,
+ .lastclose = radeon_driver_lastclose,
+ .unload = radeon_driver_unload,
+- .vblank_wait = radeon_driver_vblank_wait,
+- .vblank_wait2 = radeon_driver_vblank_wait2,
++ .get_vblank_counter = radeon_get_vblank_counter,
++ .enable_vblank = radeon_enable_vblank,
++ .disable_vblank = radeon_disable_vblank,
+ .dri_library_name = dri_library_name,
+ .irq_preinstall = radeon_driver_irq_preinstall,
+ .irq_postinstall = radeon_driver_irq_postinstall,
+diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
+index 173ae62..b791420 100644
+--- a/drivers/char/drm/radeon_drv.h
++++ b/drivers/char/drm/radeon_drv.h
+@@ -304,6 +304,9 @@ typedef struct drm_radeon_private {
+
+ u32 scratch_ages[5];
+
++ unsigned int crtc_last_cnt;
++ unsigned int crtc2_last_cnt;
++
+ /* starting from here on, data is preserved accross an open */
+ uint32_t flags; /* see radeon_chip_flags */
+ unsigned long fb_aper_offset;
+@@ -374,13 +377,13 @@ extern int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *
+ extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv);
+
+ extern void radeon_do_release(struct drm_device * dev);
+-extern int radeon_driver_vblank_wait(struct drm_device * dev,
+- unsigned int *sequence);
+-extern int radeon_driver_vblank_wait2(struct drm_device * dev,
+- unsigned int *sequence);
++extern u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc);
++extern int radeon_enable_vblank(struct drm_device *dev, int crtc);
++extern void radeon_disable_vblank(struct drm_device *dev, int crtc);
++extern void radeon_do_release(struct drm_device * dev);
+ extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
+ extern void radeon_driver_irq_preinstall(struct drm_device * dev);
+-extern void radeon_driver_irq_postinstall(struct drm_device * dev);
++extern int radeon_driver_irq_postinstall(struct drm_device * dev);
+ extern void radeon_driver_irq_uninstall(struct drm_device * dev);
+ extern int radeon_vblank_crtc_get(struct drm_device *dev);
+ extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value);
+@@ -558,6 +561,12 @@ extern int r300_do_cp_cmdbuf(struct drm_device * dev,
+ ? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \
+ : RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) )
+
++#define RADEON_CRTC_CRNT_FRAME 0x0214
++#define RADEON_CRTC2_CRNT_FRAME 0x0314
++
++#define RADEON_CRTC_STATUS 0x005c
++#define RADEON_CRTC2_STATUS 0x03fc
++
+ #define RADEON_GEN_INT_CNTL 0x0040
+ # define RADEON_CRTC_VBLANK_MASK (1 << 0)
+ # define RADEON_CRTC2_VBLANK_MASK (1 << 9)
+diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c
+index 009af38..507d6b7 100644
+--- a/drivers/char/drm/radeon_irq.c
++++ b/drivers/char/drm/radeon_irq.c
+@@ -35,12 +35,61 @@
+ #include "radeon_drm.h"
+ #include "radeon_drv.h"
+
+-static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,
+- u32 mask)
++static void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state)
+ {
+- u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
++ drm_radeon_private_t *dev_priv = dev->dev_private;
++
++ if (state)
++ dev_priv->irq_enable_reg |= mask;
++ else
++ dev_priv->irq_enable_reg &= ~mask;
++
++ RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
++}
++
++int radeon_enable_vblank(struct drm_device *dev, int crtc)
++{
++ switch (crtc) {
++ case 0:
++ radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1);
++ break;
++ case 1:
++ radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 1);
++ break;
++ default:
++ DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
++ crtc);
++ return EINVAL;
++ }
++
++ return 0;
++}
++
++void radeon_disable_vblank(struct drm_device *dev, int crtc)
++{
++ switch (crtc) {
++ case 0:
++ radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0);
++ break;
++ case 1:
++ radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 0);
++ break;
++ default:
++ DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
++ crtc);
++ break;
++ }
++}
++
++static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv)
++{
++ u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) &
++ (RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT |
++ RADEON_CRTC2_VBLANK_STAT);
++
+ if (irqs)
+ RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
++
+ return irqs;
+ }
+
+@@ -72,39 +121,21 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
+ /* Only consider the bits we're interested in - others could be used
+ * outside the DRM
+ */
+- stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
+- RADEON_CRTC_VBLANK_STAT |
+- RADEON_CRTC2_VBLANK_STAT));
++ stat = radeon_acknowledge_irqs(dev_priv);
+ if (!stat)
+ return IRQ_NONE;
+
+ stat &= dev_priv->irq_enable_reg;
+
+ /* SW interrupt */
+- if (stat & RADEON_SW_INT_TEST) {
++ if (stat & RADEON_SW_INT_TEST)
+ DRM_WAKEUP(&dev_priv->swi_queue);
+- }
+
+ /* VBLANK interrupt */
+- if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) {
+- int vblank_crtc = dev_priv->vblank_crtc;
+-
+- if ((vblank_crtc &
+- (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) ==
+- (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
+- if (stat & RADEON_CRTC_VBLANK_STAT)
+- atomic_inc(&dev->vbl_received);
+- if (stat & RADEON_CRTC2_VBLANK_STAT)
+- atomic_inc(&dev->vbl_received2);
+- } else if (((stat & RADEON_CRTC_VBLANK_STAT) &&
+- (vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) ||
+- ((stat & RADEON_CRTC2_VBLANK_STAT) &&
+- (vblank_crtc & DRM_RADEON_VBLANK_CRTC2)))
+- atomic_inc(&dev->vbl_received);
+-
+- DRM_WAKEUP(&dev->vbl_queue);
+- drm_vbl_send_signals(dev);
+- }
++ if (stat & RADEON_CRTC_VBLANK_STAT)
++ drm_handle_vblank(dev, 0);
++ if (stat & RADEON_CRTC2_VBLANK_STAT)
++ drm_handle_vblank(dev, 1);
+
+ return IRQ_HANDLED;
+ }
+@@ -144,54 +175,27 @@ static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
+ return ret;
+ }
+
+-static int radeon_driver_vblank_do_wait(struct drm_device * dev,
+- unsigned int *sequence, int crtc)
++u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc)
+ {
+- drm_radeon_private_t *dev_priv =
+- (drm_radeon_private_t *) dev->dev_private;
+- unsigned int cur_vblank;
+- int ret = 0;
+- int ack = 0;
+- atomic_t *counter;
++ drm_radeon_private_t *dev_priv = dev->dev_private;
++ u32 crtc_cnt_reg, crtc_status_reg;
++
+ if (!dev_priv) {
+ DRM_ERROR("called with no initialization\n");
+ return -EINVAL;
+ }
+
+- if (crtc == DRM_RADEON_VBLANK_CRTC1) {
+- counter = &dev->vbl_received;
+- ack |= RADEON_CRTC_VBLANK_STAT;
+- } else if (crtc == DRM_RADEON_VBLANK_CRTC2) {
+- counter = &dev->vbl_received2;
+- ack |= RADEON_CRTC2_VBLANK_STAT;
+- } else
++ if (crtc == 0) {
++ crtc_cnt_reg = RADEON_CRTC_CRNT_FRAME;
++ crtc_status_reg = RADEON_CRTC_STATUS;
++ } else if (crtc == 1) {
++ crtc_cnt_reg = RADEON_CRTC2_CRNT_FRAME;
++ crtc_status_reg = RADEON_CRTC2_STATUS;
++ } else {
+ return -EINVAL;
++ }
+
+- radeon_acknowledge_irqs(dev_priv, ack);
+-
+- dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+-
+- /* Assume that the user has missed the current sequence number
+- * by about a day rather than she wants to wait for years
+- * using vertical blanks...
+- */
+- DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+- (((cur_vblank = atomic_read(counter))
+- - *sequence) <= (1 << 23)));
+-
+- *sequence = cur_vblank;
+-
+- return ret;
+-}
+-
+-int radeon_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
+-{
+- return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1);
+-}
+-
+-int radeon_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
+-{
+- return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2);
++ return RADEON_READ(crtc_cnt_reg) + (RADEON_READ(crtc_status_reg) & 1);
+ }
+
+ /* Needs the lock as it touches the ring.
+@@ -234,21 +238,6 @@ int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_pr
+ return radeon_wait_irq(dev, irqwait->irq_seq);
+ }
+
+-static void radeon_enable_interrupt(struct drm_device *dev)
+-{
+- drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
+-
+- dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE;
+- if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1)
+- dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK;
+-
+- if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2)
+- dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK;
+-
+- RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
+- dev_priv->irq_enabled = 1;
+-}
+-
+ /* drm_dma.h hooks
+ */
+ void radeon_driver_irq_preinstall(struct drm_device * dev)
+@@ -260,20 +249,27 @@ void radeon_driver_irq_preinstall(struct drm_device * dev)
+ RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
+
+ /* Clear bits if they're already high */
+- radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
+- RADEON_CRTC_VBLANK_STAT |
+- RADEON_CRTC2_VBLANK_STAT));
++ radeon_acknowledge_irqs(dev_priv);
+ }
+
+-void radeon_driver_irq_postinstall(struct drm_device * dev)
++int radeon_driver_irq_postinstall(struct drm_device * dev)
+ {
+ drm_radeon_private_t *dev_priv =
+ (drm_radeon_private_t *) dev->dev_private;
++ int ret;
+
+ atomic_set(&dev_priv->swi_emitted, 0);
+ DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
+
+- radeon_enable_interrupt(dev);
++ ret = drm_vblank_init(dev, 2);
++ if (ret)
++ return ret;
++
++ dev->max_vblank_count = 0x001fffff;
++
++ radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
++
++ return 0;
+ }
+
+ void radeon_driver_irq_uninstall(struct drm_device * dev)
+@@ -315,6 +311,5 @@ int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value)
+ return -EINVAL;
+ }
+ dev_priv->vblank_crtc = (unsigned int)value;
+- radeon_enable_interrupt(dev);
+ return 0;
+ }
+diff --git a/drivers/char/drm/via_drv.c b/drivers/char/drm/via_drv.c
+index 80c01cd..37870a4 100644
+--- a/drivers/char/drm/via_drv.c
++++ b/drivers/char/drm/via_drv.c
+@@ -40,11 +40,13 @@ static struct pci_device_id pciidlist[] = {
+ static struct drm_driver driver = {
+ .driver_features =
+ DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ |
+- DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
++ DRIVER_IRQ_SHARED,
+ .load = via_driver_load,
+ .unload = via_driver_unload,
+ .context_dtor = via_final_context,
+- .vblank_wait = via_driver_vblank_wait,
++ .get_vblank_counter = via_get_vblank_counter,
++ .enable_vblank = via_enable_vblank,
++ .disable_vblank = via_disable_vblank,
+ .irq_preinstall = via_driver_irq_preinstall,
+ .irq_postinstall = via_driver_irq_postinstall,
+ .irq_uninstall = via_driver_irq_uninstall,
+diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h
+index 2daae81..fe67030 100644
+--- a/drivers/char/drm/via_drv.h
++++ b/drivers/char/drm/via_drv.h
+@@ -75,6 +75,7 @@ typedef struct drm_via_private {
+ struct timeval last_vblank;
+ int last_vblank_valid;
+ unsigned usec_per_vblank;
++ atomic_t vbl_received;
+ drm_via_state_t hc_state;
+ char pci_buf[VIA_PCI_BUF_SIZE];
+ const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE];
+@@ -130,11 +131,13 @@ extern int via_init_context(struct drm_device * dev, int context);
+ extern int via_final_context(struct drm_device * dev, int context);
+
+ extern int via_do_cleanup_map(struct drm_device * dev);
+-extern int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
++extern u32 via_get_vblank_counter(struct drm_device *dev, int crtc);
++extern int via_enable_vblank(struct drm_device *dev, int crtc);
++extern void via_disable_vblank(struct drm_device *dev, int crtc);
+
+ extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);
+ extern void via_driver_irq_preinstall(struct drm_device * dev);
+-extern void via_driver_irq_postinstall(struct drm_device * dev);
++extern int via_driver_irq_postinstall(struct drm_device * dev);
+ extern void via_driver_irq_uninstall(struct drm_device * dev);
+
+ extern int via_dma_cleanup(struct drm_device * dev);
+diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c
+index c6bb978..f1ab6fc 100644
+--- a/drivers/char/drm/via_irq.c
++++ b/drivers/char/drm/via_irq.c
+@@ -92,8 +92,17 @@ static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};
+ static unsigned time_diff(struct timeval *now, struct timeval *then)
+ {
+ return (now->tv_usec >= then->tv_usec) ?
+- now->tv_usec - then->tv_usec :
+- 1000000 - (then->tv_usec - now->tv_usec);
++ now->tv_usec - then->tv_usec :
++ 1000000 - (then->tv_usec - now->tv_usec);
++}
++
++u32 via_get_vblank_counter(struct drm_device *dev, int crtc)
++{
++ drm_via_private_t *dev_priv = dev->dev_private;
++ if (crtc != 0)
++ return 0;
++
++ return atomic_read(&dev_priv->vbl_received);
+ }
+
+ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
+@@ -108,8 +117,8 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
+
+ status = VIA_READ(VIA_REG_INTERRUPT);
+ if (status & VIA_IRQ_VBLANK_PENDING) {
+- atomic_inc(&dev->vbl_received);
+- if (!(atomic_read(&dev->vbl_received) & 0x0F)) {
++ atomic_inc(&dev_priv->vbl_received);
++ if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) {
+ do_gettimeofday(&cur_vblank);
+ if (dev_priv->last_vblank_valid) {
+ dev_priv->usec_per_vblank =
+@@ -119,12 +128,11 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
+ dev_priv->last_vblank = cur_vblank;
+ dev_priv->last_vblank_valid = 1;
+ }
+- if (!(atomic_read(&dev->vbl_received) & 0xFF)) {
++ if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) {
+ DRM_DEBUG("US per vblank is: %u\n",
+ dev_priv->usec_per_vblank);
+ }
+- DRM_WAKEUP(&dev->vbl_queue);
+- drm_vbl_send_signals(dev);
++ drm_handle_vblank(dev, 0);
+ handled = 1;
+ }
+
+@@ -163,31 +171,34 @@ static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv)
+ }
+ }
+
+-int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
++int via_enable_vblank(struct drm_device *dev, int crtc)
+ {
+- drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+- unsigned int cur_vblank;
+- int ret = 0;
++ drm_via_private_t *dev_priv = dev->dev_private;
++ u32 status;
+
+- DRM_DEBUG("\n");
+- if (!dev_priv) {
+- DRM_ERROR("called with no initialization\n");
++ if (crtc != 0) {
++ DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc);
+ return -EINVAL;
+ }
+
+- viadrv_acknowledge_irqs(dev_priv);
++ status = VIA_READ(VIA_REG_INTERRUPT);
++ VIA_WRITE(VIA_REG_INTERRUPT, status & VIA_IRQ_VBLANK_ENABLE);
+
+- /* Assume that the user has missed the current sequence number
+- * by about a day rather than she wants to wait for years
+- * using vertical blanks...
+- */
++ VIA_WRITE8(0x83d4, 0x11);
++ VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
+
+- DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+- (((cur_vblank = atomic_read(&dev->vbl_received)) -
+- *sequence) <= (1 << 23)));
++ return 0;
++}
+
+- *sequence = cur_vblank;
+- return ret;
++void via_disable_vblank(struct drm_device *dev, int crtc)
++{
++ drm_via_private_t *dev_priv = dev->dev_private;
++
++ VIA_WRITE8(0x83d4, 0x11);
++ VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
++
++ if (crtc != 0)
++ DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc);
+ }
+
+ static int
+@@ -292,23 +303,25 @@ void via_driver_irq_preinstall(struct drm_device * dev)
+ }
+ }
+
+-void via_driver_irq_postinstall(struct drm_device * dev)
++int via_driver_irq_postinstall(struct drm_device * dev)
+ {
+ drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+ u32 status;
+
+- DRM_DEBUG("\n");
+- if (dev_priv) {
+- status = VIA_READ(VIA_REG_INTERRUPT);
+- VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
+- | dev_priv->irq_enable_mask);
++ DRM_DEBUG("via_driver_irq_postinstall\n");
++ if (!dev_priv)
++ return -EINVAL;
+
+- /* Some magic, oh for some data sheets ! */
++ drm_vblank_init(dev, 1);
++ status = VIA_READ(VIA_REG_INTERRUPT);
++ VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
++ | dev_priv->irq_enable_mask);
+
+- VIA_WRITE8(0x83d4, 0x11);
+- VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
++ /* Some magic, oh for some data sheets ! */
++ VIA_WRITE8(0x83d4, 0x11);
++ VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
+
+- }
++ return 0;
+ }
+
+ void via_driver_irq_uninstall(struct drm_device * dev)
+diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c
+index 8facf3e..7ed7da1 100644
+--- a/drivers/char/generic_serial.c
++++ b/drivers/char/generic_serial.c
+@@ -28,7 +28,6 @@
+ #include <linux/interrupt.h>
+ #include <linux/tty_flip.h>
+ #include <linux/delay.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+
+ #define DEBUG
+diff --git a/drivers/char/hvc_beat.c b/drivers/char/hvc_beat.c
+index e74bb94..91cdb35 100644
+--- a/drivers/char/hvc_beat.c
++++ b/drivers/char/hvc_beat.c
+@@ -78,8 +78,8 @@ static int hvc_beat_put_chars(uint32_t vtermno, const char *buf, int cnt)
+ for (rest = cnt; rest > 0; rest -= nlen) {
+ nlen = (rest > 16) ? 16 : rest;
+ memcpy(kb, buf, nlen);
+- beat_put_term_char(vtermno, rest, kb[0], kb[1]);
+- rest -= nlen;
++ beat_put_term_char(vtermno, nlen, kb[0], kb[1]);
++ buf += nlen;
+ }
+ return cnt;
+ }
+diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
+index 84cdf90..662d60e 100644
+--- a/drivers/char/hw_random/core.c
++++ b/drivers/char/hw_random/core.c
+@@ -116,6 +116,10 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf,
+ err = -EAGAIN;
+ if (!bytes_read && (filp->f_flags & O_NONBLOCK))
+ goto out;
++ if (bytes_read < 0) {
++ err = bytes_read;
++ goto out;
++ }
+
+ err = -EFAULT;
+ while (bytes_read && size) {
+@@ -234,11 +238,11 @@ static DEVICE_ATTR(rng_available, S_IRUGO,
+ NULL);
+
+
+-static void unregister_miscdev(bool suspended)
++static void unregister_miscdev(void)
+ {
+ device_remove_file(rng_miscdev.this_device, &dev_attr_rng_available);
+ device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current);
+- __misc_deregister(&rng_miscdev, suspended);
++ misc_deregister(&rng_miscdev);
+ }
+
+ static int register_miscdev(void)
+@@ -313,7 +317,7 @@ out:
+ }
+ EXPORT_SYMBOL_GPL(hwrng_register);
+
+-void __hwrng_unregister(struct hwrng *rng, bool suspended)
++void hwrng_unregister(struct hwrng *rng)
+ {
+ int err;
+
+@@ -332,11 +336,11 @@ void __hwrng_unregister(struct hwrng *rng, bool suspended)
+ }
+ }
+ if (list_empty(&rng_list))
+- unregister_miscdev(suspended);
++ unregister_miscdev();
+
+ mutex_unlock(&rng_mutex);
+ }
+-EXPORT_SYMBOL_GPL(__hwrng_unregister);
++EXPORT_SYMBOL_GPL(hwrng_unregister);
+
+
+ MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver");
+diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
+index 7e31995..51738bd 100644
+--- a/drivers/char/hw_random/omap-rng.c
++++ b/drivers/char/hw_random/omap-rng.c
+@@ -1,7 +1,5 @@
+ /*
+- * drivers/char/hw_random/omap-rng.c
+- *
+- * RNG driver for TI OMAP CPU family
++ * omap-rng.c - RNG driver for TI OMAP CPU family
+ *
+ * Author: Deepak Saxena <dsaxena at plexity.net>
+ *
+@@ -15,11 +13,6 @@
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+- *
+- * TODO:
+- *
+- * - Make status updated be interrupt driven so we don't poll
+- *
+ */
+
+ #include <linux/module.h>
+@@ -55,17 +48,16 @@ static void __iomem *rng_base;
+ static struct clk *rng_ick;
+ static struct platform_device *rng_dev;
+
+-static u32 omap_rng_read_reg(int reg)
++static inline u32 omap_rng_read_reg(int reg)
+ {
+ return __raw_readl(rng_base + reg);
+ }
+
+-static void omap_rng_write_reg(int reg, u32 val)
++static inline void omap_rng_write_reg(int reg, u32 val)
+ {
+ __raw_writel(val, rng_base + reg);
+ }
+
+-/* REVISIT: Does the status bit really work on 16xx? */
+ static int omap_rng_data_present(struct hwrng *rng, int wait)
+ {
+ int data, i;
+@@ -74,6 +66,11 @@ static int omap_rng_data_present(struct hwrng *rng, int wait)
+ data = omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1;
+ if (data || !wait)
+ break;
++ /* RNG produces data fast enough (2+ MBit/sec, even
++ * during "rngtest" loads, that these delays don't
++ * seem to trigger. We *could* use the RNG IRQ, but
++ * that'd be higher overhead ... so why bother?
++ */
+ udelay(10);
+ }
+ return data;
+@@ -101,7 +98,8 @@ static int __init omap_rng_probe(struct platform_device *pdev)
+ * A bit ugly, and it will never actually happen but there can
+ * be only one RNG and this catches any bork
+ */
+- BUG_ON(rng_dev);
++ if (rng_dev)
++ return -EBUSY;
+
+ if (cpu_is_omap24xx()) {
+ rng_ick = clk_get(NULL, "rng_ick");
+@@ -124,7 +122,7 @@ static int __init omap_rng_probe(struct platform_device *pdev)
+ return -EBUSY;
+
+ dev_set_drvdata(&pdev->dev, mem);
+- rng_base = (u32 __iomem *)io_p2v(res->start);
++ rng_base = (u32 __force __iomem *)io_p2v(res->start);
+
+ ret = hwrng_register(&omap_rng_ops);
+ if (ret) {
+@@ -182,6 +180,8 @@ static int omap_rng_resume(struct platform_device *pdev)
+
+ #endif
+
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:omap_rng");
+
+ static struct platform_driver omap_rng_driver = {
+ .driver = {
+diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
+index 4dbd342..60b934a 100644
+--- a/drivers/char/keyboard.c
++++ b/drivers/char/keyboard.c
+@@ -42,6 +42,7 @@
+ #include <linux/input.h>
+ #include <linux/reboot.h>
+ #include <linux/notifier.h>
++#include <linux/jiffies.h>
+
+ extern void ctrl_alt_del(void);
+
+@@ -928,7 +929,8 @@ static void k_brl(struct vc_data *vc, unsigned char value, char up_flag)
+ if (up_flag) {
+ if (brl_timeout) {
+ if (!committing ||
+- jiffies - releasestart > (brl_timeout * HZ) / 1000) {
++ time_after(jiffies,
++ releasestart + msecs_to_jiffies(brl_timeout))) {
+ committing = pressed;
+ releasestart = jiffies;
+ }
+@@ -1033,7 +1035,8 @@ DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
+ #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
+ defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\
+ defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\
+- (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC))
++ (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC)) ||\
++ defined(CONFIG_AVR32)
+
+ #define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\
+ ((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001))
+@@ -1237,6 +1240,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
+ }
+
+ param.shift = shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
++ param.ledstate = kbd->ledflagstate;
+ key_map = key_maps[shift_final];
+
+ if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_KEYCODE, ¶m) == NOTIFY_STOP || !key_map) {
+@@ -1285,6 +1289,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
+
+ (*k_handler[type])(vc, keysym & 0xff, !down);
+
++ param.ledstate = kbd->ledflagstate;
+ atomic_notifier_call_chain(&keyboard_notifier_list, KBD_POST_KEYSYM, ¶m);
+
+ if (type != KT_SLOCK)
+diff --git a/drivers/char/mem.c b/drivers/char/mem.c
+index 20070b7..e83623e 100644
+--- a/drivers/char/mem.c
++++ b/drivers/char/mem.c
+@@ -41,36 +41,7 @@
+ */
+ static inline int uncached_access(struct file *file, unsigned long addr)
+ {
+-#if defined(__i386__) && !defined(__arch_um__)
+- /*
+- * On the PPro and successors, the MTRRs are used to set
+- * memory types for physical addresses outside main memory,
+- * so blindly setting PCD or PWT on those pages is wrong.
+- * For Pentiums and earlier, the surround logic should disable
+- * caching for the high addresses through the KEN pin, but
+- * we maintain the tradition of paranoia in this code.
+- */
+- if (file->f_flags & O_SYNC)
+- return 1;
+- return !( test_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability) ||
+- test_bit(X86_FEATURE_K6_MTRR, boot_cpu_data.x86_capability) ||
+- test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) ||
+- test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability) )
+- && addr >= __pa(high_memory);
+-#elif defined(__x86_64__) && !defined(__arch_um__)
+- /*
+- * This is broken because it can generate memory type aliases,
+- * which can cause cache corruptions
+- * But it is only available for root and we have to be bug-to-bug
+- * compatible with i386.
+- */
+- if (file->f_flags & O_SYNC)
+- return 1;
+- /* same behaviour as i386. PAT always set to cached and MTRRs control the
+- caching behaviour.
+- Hopefully a full PAT implementation will fix that soon. */
+- return 0;
+-#elif defined(CONFIG_IA64)
++#if defined(CONFIG_IA64)
+ /*
+ * On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases.
+ */
+@@ -108,6 +79,36 @@ static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
+ }
+ #endif
+
++#ifdef CONFIG_NONPROMISC_DEVMEM
++static inline int range_is_allowed(unsigned long pfn, unsigned long size)
++{
++ u64 from = ((u64)pfn) << PAGE_SHIFT;
++ u64 to = from + size;
++ u64 cursor = from;
++
++ while (cursor < to) {
++ if (!devmem_is_allowed(pfn)) {
++ printk(KERN_INFO
++ "Program %s tried to access /dev/mem between %Lx->%Lx.\n",
++ current->comm, from, to);
++ return 0;
++ }
++ cursor += PAGE_SIZE;
++ pfn++;
++ }
++ return 1;
++}
++#else
++static inline int range_is_allowed(unsigned long pfn, unsigned long size)
++{
++ return 1;
++}
++#endif
++
++void __attribute__((weak)) unxlate_dev_mem_ptr(unsigned long phys, void *addr)
++{
++}
++
+ /*
+ * This funcion reads the *physical* memory. The f_pos points directly to the
+ * memory location.
+@@ -150,15 +151,25 @@ static ssize_t read_mem(struct file * file, char __user * buf,
+
+ sz = min_t(unsigned long, sz, count);
+
++ if (!range_is_allowed(p >> PAGE_SHIFT, count))
++ return -EPERM;
++
+ /*
+ * On ia64 if a page has been mapped somewhere as
+ * uncached, then it must also be accessed uncached
+ * by the kernel or data corruption may occur
+ */
+ ptr = xlate_dev_mem_ptr(p);
++ if (!ptr)
++ return -EFAULT;
+
+- if (copy_to_user(buf, ptr, sz))
++ if (copy_to_user(buf, ptr, sz)) {
++ unxlate_dev_mem_ptr(p, ptr);
+ return -EFAULT;
++ }
++
++ unxlate_dev_mem_ptr(p, ptr);
++
+ buf += sz;
+ p += sz;
+ count -= sz;
+@@ -207,20 +218,32 @@ static ssize_t write_mem(struct file * file, const char __user * buf,
+
+ sz = min_t(unsigned long, sz, count);
+
++ if (!range_is_allowed(p >> PAGE_SHIFT, sz))
++ return -EPERM;
++
+ /*
+ * On ia64 if a page has been mapped somewhere as
+ * uncached, then it must also be accessed uncached
+ * by the kernel or data corruption may occur
+ */
+ ptr = xlate_dev_mem_ptr(p);
++ if (!ptr) {
++ if (written)
++ break;
++ return -EFAULT;
++ }
+
+ copied = copy_from_user(ptr, buf, sz);
+ if (copied) {
+ written += sz - copied;
++ unxlate_dev_mem_ptr(p, ptr);
+ if (written)
+ break;
+ return -EFAULT;
+ }
++
++ unxlate_dev_mem_ptr(p, ptr);
++
+ buf += sz;
+ p += sz;
+ count -= sz;
+@@ -231,6 +254,12 @@ static ssize_t write_mem(struct file * file, const char __user * buf,
+ return written;
+ }
+
++int __attribute__((weak)) phys_mem_access_prot_allowed(struct file *file,
++ unsigned long pfn, unsigned long size, pgprot_t *vma_prot)
++{
++ return 1;
++}
++
+ #ifndef __HAVE_PHYS_MEM_ACCESS_PROT
+ static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+ unsigned long size, pgprot_t vma_prot)
+@@ -271,6 +300,35 @@ static inline int private_mapping_ok(struct vm_area_struct *vma)
+ }
+ #endif
+
++void __attribute__((weak))
++map_devmem(unsigned long pfn, unsigned long len, pgprot_t prot)
++{
++ /* nothing. architectures can override. */
++}
++
++void __attribute__((weak))
++unmap_devmem(unsigned long pfn, unsigned long len, pgprot_t prot)
++{
++ /* nothing. architectures can override. */
++}
++
++static void mmap_mem_open(struct vm_area_struct *vma)
++{
++ map_devmem(vma->vm_pgoff, vma->vm_end - vma->vm_start,
++ vma->vm_page_prot);
++}
++
++static void mmap_mem_close(struct vm_area_struct *vma)
++{
++ unmap_devmem(vma->vm_pgoff, vma->vm_end - vma->vm_start,
++ vma->vm_page_prot);
++}
++
++static struct vm_operations_struct mmap_mem_ops = {
++ .open = mmap_mem_open,
++ .close = mmap_mem_close
++};
++
+ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
+ {
+ size_t size = vma->vm_end - vma->vm_start;
+@@ -281,17 +339,28 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
+ if (!private_mapping_ok(vma))
+ return -ENOSYS;
+
++ if (!range_is_allowed(vma->vm_pgoff, size))
++ return -EPERM;
++
++ if (!phys_mem_access_prot_allowed(file, vma->vm_pgoff, size,
++ &vma->vm_page_prot))
++ return -EINVAL;
++
+ vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
+ size,
+ vma->vm_page_prot);
+
++ vma->vm_ops = &mmap_mem_ops;
++
+ /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */
+ if (remap_pfn_range(vma,
+ vma->vm_start,
+ vma->vm_pgoff,
+ size,
+- vma->vm_page_prot))
++ vma->vm_page_prot)) {
++ unmap_devmem(vma->vm_pgoff, size, vma->vm_page_prot);
+ return -EAGAIN;
++ }
+ return 0;
+ }
+
+diff --git a/drivers/char/misc.c b/drivers/char/misc.c
+index a39101f..4d058da 100644
+--- a/drivers/char/misc.c
++++ b/drivers/char/misc.c
+@@ -232,9 +232,8 @@ int misc_register(struct miscdevice * misc)
+ }
+
+ /**
+- * __misc_deregister - unregister a miscellaneous device
++ * misc_deregister - unregister a miscellaneous device
+ * @misc: device to unregister
+- * @suspended: to be set if the function is used during suspend/resume
+ *
+ * Unregister a miscellaneous device that was previously
+ * successfully registered with misc_register(). Success
+@@ -242,7 +241,7 @@ int misc_register(struct miscdevice * misc)
+ * indicates an error.
+ */
+
+-int __misc_deregister(struct miscdevice *misc, bool suspended)
++int misc_deregister(struct miscdevice *misc)
+ {
+ int i = misc->minor;
+
+@@ -251,11 +250,7 @@ int __misc_deregister(struct miscdevice *misc, bool suspended)
+
+ mutex_lock(&misc_mtx);
+ list_del(&misc->list);
+- if (suspended)
+- destroy_suspended_device(misc_class,
+- MKDEV(MISC_MAJOR, misc->minor));
+- else
+- device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
++ device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
+ if (i < DYNAMIC_MINORS && i>0) {
+ misc_minors[i>>3] &= ~(1 << (misc->minor & 7));
+ }
+@@ -264,7 +259,7 @@ int __misc_deregister(struct miscdevice *misc, bool suspended)
+ }
+
+ EXPORT_SYMBOL(misc_register);
+-EXPORT_SYMBOL(__misc_deregister);
++EXPORT_SYMBOL(misc_deregister);
+
+ static int __init misc_init(void)
+ {
+diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
+index 279ff50..4e84d23 100644
+--- a/drivers/char/pcmcia/synclink_cs.c
++++ b/drivers/char/pcmcia/synclink_cs.c
+@@ -1225,17 +1225,15 @@ static void ri_change(MGSLPC_INFO *info)
+ * irq interrupt number that caused interrupt
+ * dev_id device ID supplied during interrupt registration
+ */
+-static irqreturn_t mgslpc_isr(int irq, void *dev_id)
++static irqreturn_t mgslpc_isr(int dummy, void *dev_id)
+ {
+- MGSLPC_INFO * info = (MGSLPC_INFO *)dev_id;
++ MGSLPC_INFO *info = dev_id;
+ unsigned short isr;
+ unsigned char gis, pis;
+ int count=0;
+
+ if (debug_level >= DEBUG_LEVEL_ISR)
+- printk("mgslpc_isr(%d) entry.\n", irq);
+- if (!info)
+- return IRQ_NONE;
++ printk("mgslpc_isr(%d) entry.\n", info->irq_level);
+
+ if (!(info->p_dev->_locked))
+ return IRQ_HANDLED;
+@@ -1327,7 +1325,7 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id)
+
+ if (debug_level >= DEBUG_LEVEL_ISR)
+ printk("%s(%d):mgslpc_isr(%d)exit.\n",
+- __FILE__,__LINE__,irq);
++ __FILE__, __LINE__, info->irq_level);
+
+ return IRQ_HANDLED;
+ }
+diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c
+index eca2b95..d956dd3 100644
+--- a/drivers/char/rio/rioboot.c
++++ b/drivers/char/rio/rioboot.c
+@@ -35,7 +35,6 @@
+ #include <linux/termios.h>
+ #include <linux/serial.h>
+ #include <linux/vmalloc.h>
+-#include <asm/semaphore.h>
+ #include <linux/generic_serial.h>
+ #include <linux/errno.h>
+ #include <linux/interrupt.h>
+diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c
+index 7321d00..bf36959 100644
+--- a/drivers/char/rio/riocmd.c
++++ b/drivers/char/rio/riocmd.c
+@@ -41,7 +41,6 @@ static char *_riocmd_c_sccs_ = "@(#)riocmd.c 1.2";
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/string.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+
+ #include <linux/termios.h>
+diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c
+index 7ce7761..d8eb2bc 100644
+--- a/drivers/char/rio/rioctrl.c
++++ b/drivers/char/rio/rioctrl.c
+@@ -40,7 +40,6 @@ static char *_rioctrl_c_sccs_ = "@(#)rioctrl.c 1.3";
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/string.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+
+ #include <linux/termios.h>
+diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c
+index 0794844..add1718 100644
+--- a/drivers/char/rio/rioinit.c
++++ b/drivers/char/rio/rioinit.c
+@@ -40,7 +40,6 @@ static char *_rioinit_c_sccs_ = "@(#)rioinit.c 1.3";
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/string.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+
+ #include <linux/termios.h>
+diff --git a/drivers/char/rio/riointr.c b/drivers/char/rio/riointr.c
+index ebc7634..4734e26 100644
+--- a/drivers/char/rio/riointr.c
++++ b/drivers/char/rio/riointr.c
+@@ -42,7 +42,6 @@ static char *_riointr_c_sccs_ = "@(#)riointr.c 1.2";
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/string.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+
+ #include <linux/termios.h>
+diff --git a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c
+index bb498d2..da276ed 100644
+--- a/drivers/char/rio/rioparam.c
++++ b/drivers/char/rio/rioparam.c
+@@ -41,7 +41,6 @@ static char *_rioparam_c_sccs_ = "@(#)rioparam.c 1.3";
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/string.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+
+ #include <linux/termios.h>
+diff --git a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c
+index a99f3d9..85091ff 100644
+--- a/drivers/char/rio/rioroute.c
++++ b/drivers/char/rio/rioroute.c
+@@ -39,7 +39,6 @@ static char *_rioroute_c_sccs_ = "@(#)rioroute.c 1.3";
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/string.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+
+ #include <linux/termios.h>
+diff --git a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c
+index 9b52892..2b24488 100644
+--- a/drivers/char/rio/riotable.c
++++ b/drivers/char/rio/riotable.c
+@@ -42,7 +42,6 @@ static char *_riotable_c_sccs_ = "@(#)riotable.c 1.2";
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/string.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+
+ #include <linux/termios.h>
+diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c
+index cfa5436..1cb8580 100644
+--- a/drivers/char/rio/riotty.c
++++ b/drivers/char/rio/riotty.c
+@@ -44,7 +44,6 @@ static char *_riotty_c_sccs_ = "@(#)riotty.c 1.3";
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/string.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+
+ #include <linux/termios.h>
+diff --git a/drivers/char/snsc.h b/drivers/char/snsc.h
+index 8a98169..4be62ed 100644
+--- a/drivers/char/snsc.h
++++ b/drivers/char/snsc.h
+@@ -22,8 +22,8 @@
+ #include <linux/kobject.h>
+ #include <linux/fs.h>
+ #include <linux/cdev.h>
++#include <linux/semaphore.h>
+ #include <asm/sn/types.h>
+-#include <asm/semaphore.h>
+
+ #define CHUNKSIZE 127
+
+diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
+index 921c6d2..c03ad16 100644
+--- a/drivers/char/sonypi.c
++++ b/drivers/char/sonypi.c
+@@ -1147,7 +1147,7 @@ static int sonypi_acpi_remove(struct acpi_device *device, int type)
+ return 0;
+ }
+
+-const static struct acpi_device_id sonypi_device_ids[] = {
++static const struct acpi_device_id sonypi_device_ids[] = {
+ {"SNY6001", 0},
+ {"", 0},
+ };
+diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
+index 5ff83df..4b5b5b7 100644
+--- a/drivers/char/specialix.c
++++ b/drivers/char/specialix.c
+@@ -443,8 +443,7 @@ void missed_irq (unsigned long data)
+ spin_unlock_irqrestore(&bp->lock, flags);
+ if (irq) {
+ printk (KERN_INFO "Missed interrupt... Calling int from timer. \n");
+- sx_interrupt (((struct specialix_board *)data)->irq,
+- (void*)data);
++ sx_interrupt (-1, bp);
+ }
+ mod_timer(&missed_irq_timer, jiffies + sx_poll);
+ }
+@@ -862,23 +861,22 @@ static inline void sx_check_modem(struct specialix_board * bp)
+
+
+ /* The main interrupt processing routine */
+-static irqreturn_t sx_interrupt(int irq, void *dev_id)
++static irqreturn_t sx_interrupt(int dummy, void *dev_id)
+ {
+ unsigned char status;
+ unsigned char ack;
+- struct specialix_board *bp;
++ struct specialix_board *bp = dev_id;
+ unsigned long loop = 0;
+ int saved_reg;
+ unsigned long flags;
+
+ func_enter();
+
+- bp = dev_id;
+ spin_lock_irqsave(&bp->lock, flags);
+
+ dprintk (SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __FUNCTION__, port_No(sx_get_port(bp, "INT")), SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1);
+ if (!(bp->flags & SX_BOARD_ACTIVE)) {
+- dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", irq);
++ dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", bp->irq);
+ spin_unlock_irqrestore(&bp->lock, flags);
+ func_exit();
+ return IRQ_NONE;
+diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
+index feac54e..874aaa0 100644
+--- a/drivers/char/stallion.c
++++ b/drivers/char/stallion.c
+@@ -1645,7 +1645,7 @@ static irqreturn_t stl_intr(int irq, void *dev_id)
+ {
+ struct stlbrd *brdp = dev_id;
+
+- pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, irq);
++ pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq);
+
+ return IRQ_RETVAL((* brdp->isr)(brdp));
+ }
+diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
+index ddc74d1..a3237d4 100644
+--- a/drivers/char/synclink.c
++++ b/drivers/char/synclink.c
+@@ -1695,20 +1695,16 @@ static void mgsl_isr_transmit_dma( struct mgsl_struct *info )
+ *
+ * Return Value: None
+ */
+-static irqreturn_t mgsl_interrupt(int irq, void *dev_id)
++static irqreturn_t mgsl_interrupt(int dummy, void *dev_id)
+ {
+- struct mgsl_struct * info;
++ struct mgsl_struct *info = dev_id;
+ u16 UscVector;
+ u16 DmaVector;
+
+ if ( debug_level >= DEBUG_LEVEL_ISR )
+- printk("%s(%d):mgsl_interrupt(%d)entry.\n",
+- __FILE__,__LINE__,irq);
++ printk(KERN_DEBUG "%s(%d):mgsl_interrupt(%d)entry.\n",
++ __FILE__, __LINE__, info->irq_level);
+
+- info = (struct mgsl_struct *)dev_id;
+- if (!info)
+- return IRQ_NONE;
+-
+ spin_lock(&info->irq_spinlock);
+
+ for(;;) {
+@@ -1732,8 +1728,8 @@ static irqreturn_t mgsl_interrupt(int irq, void *dev_id)
+ mgsl_isr_receive_dma(info);
+
+ if ( info->isr_overflow ) {
+- printk(KERN_ERR"%s(%d):%s isr overflow irq=%d\n",
+- __FILE__,__LINE__,info->device_name, irq);
++ printk(KERN_ERR "%s(%d):%s isr overflow irq=%d\n",
++ __FILE__, __LINE__, info->device_name, info->irq_level);
+ usc_DisableMasterIrqBit(info);
+ usc_DisableDmaInterrupts(info,DICR_MASTER);
+ break;
+@@ -1755,8 +1751,9 @@ static irqreturn_t mgsl_interrupt(int irq, void *dev_id)
+ spin_unlock(&info->irq_spinlock);
+
+ if ( debug_level >= DEBUG_LEVEL_ISR )
+- printk("%s(%d):mgsl_interrupt(%d)exit.\n",
+- __FILE__,__LINE__,irq);
++ printk(KERN_DEBUG "%s(%d):mgsl_interrupt(%d)exit.\n",
++ __FILE__, __LINE__, info->irq_level);
++
+ return IRQ_HANDLED;
+ } /* end of mgsl_interrupt() */
+
+diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
+index 1f954ac..3c89266 100644
+--- a/drivers/char/synclink_gt.c
++++ b/drivers/char/synclink_gt.c
+@@ -491,7 +491,6 @@ static void isr_serial(struct slgt_info *info);
+ static void isr_rdma(struct slgt_info *info);
+ static void isr_txeom(struct slgt_info *info, unsigned short status);
+ static void isr_tdma(struct slgt_info *info);
+-static irqreturn_t slgt_interrupt(int irq, void *dev_id);
+
+ static int alloc_dma_bufs(struct slgt_info *info);
+ static void free_dma_bufs(struct slgt_info *info);
+@@ -2326,17 +2325,13 @@ static void isr_gpio(struct slgt_info *info, unsigned int changed, unsigned int
+ * irq interrupt number
+ * dev_id device ID supplied during interrupt registration
+ */
+-static irqreturn_t slgt_interrupt(int irq, void *dev_id)
++static irqreturn_t slgt_interrupt(int dummy, void *dev_id)
+ {
+- struct slgt_info *info;
++ struct slgt_info *info = dev_id;
+ unsigned int gsr;
+ unsigned int i;
+
+- DBGISR(("slgt_interrupt irq=%d entry\n", irq));
+-
+- info = dev_id;
+- if (!info)
+- return IRQ_NONE;
++ DBGISR(("slgt_interrupt irq=%d entry\n", info->irq_level));
+
+ spin_lock(&info->lock);
+
+@@ -2385,7 +2380,7 @@ static irqreturn_t slgt_interrupt(int irq, void *dev_id)
+
+ spin_unlock(&info->lock);
+
+- DBGISR(("slgt_interrupt irq=%d exit\n", irq));
++ DBGISR(("slgt_interrupt irq=%d exit\n", info->irq_level));
+ return IRQ_HANDLED;
+ }
+
+diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
+index f3e7807..c96062e 100644
+--- a/drivers/char/synclinkmp.c
++++ b/drivers/char/synclinkmp.c
+@@ -2586,9 +2586,9 @@ void isr_io_pin( SLMP_INFO *info, u16 status )
+ * dev_id device ID supplied during interrupt registration
+ * regs interrupted processor context
+ */
+-static irqreturn_t synclinkmp_interrupt(int irq, void *dev_id)
++static irqreturn_t synclinkmp_interrupt(int dummy, void *dev_id)
+ {
+- SLMP_INFO * info;
++ SLMP_INFO *info = dev_id;
+ unsigned char status, status0, status1=0;
+ unsigned char dmastatus, dmastatus0, dmastatus1=0;
+ unsigned char timerstatus0, timerstatus1=0;
+@@ -2597,12 +2597,8 @@ static irqreturn_t synclinkmp_interrupt(int irq, void *dev_id)
+ unsigned short tmp;
+
+ if ( debug_level >= DEBUG_LEVEL_ISR )
+- printk("%s(%d): synclinkmp_interrupt(%d)entry.\n",
+- __FILE__,__LINE__,irq);
+-
+- info = (SLMP_INFO *)dev_id;
+- if (!info)
+- return IRQ_NONE;
++ printk(KERN_DEBUG "%s(%d): synclinkmp_interrupt(%d)entry.\n",
++ __FILE__, __LINE__, info->irq_level);
+
+ spin_lock(&info->lock);
+
+@@ -2615,9 +2611,9 @@ static irqreturn_t synclinkmp_interrupt(int irq, void *dev_id)
+ timerstatus0 = read_reg(info, ISR2);
+
+ if ( debug_level >= DEBUG_LEVEL_ISR )
+- printk("%s(%d):%s status0=%02x, dmastatus0=%02x, timerstatus0=%02x\n",
+- __FILE__,__LINE__,info->device_name,
+- status0,dmastatus0,timerstatus0);
++ printk(KERN_DEBUG "%s(%d):%s status0=%02x, dmastatus0=%02x, timerstatus0=%02x\n",
++ __FILE__, __LINE__, info->device_name,
++ status0, dmastatus0, timerstatus0);
+
+ if (info->port_count == 4) {
+ /* get status for SCA1 (ports 2-3) */
+@@ -2702,8 +2698,8 @@ static irqreturn_t synclinkmp_interrupt(int irq, void *dev_id)
+ spin_unlock(&info->lock);
+
+ if ( debug_level >= DEBUG_LEVEL_ISR )
+- printk("%s(%d):synclinkmp_interrupt(%d)exit.\n",
+- __FILE__,__LINE__,irq);
++ printk(KERN_DEBUG "%s(%d):synclinkmp_interrupt(%d)exit.\n",
++ __FILE__, __LINE__, info->irq_level);
+ return IRQ_HANDLED;
+ }
+
+diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
+index 81503d9..13a4bdd 100644
+--- a/drivers/char/tpm/tpm_tis.c
++++ b/drivers/char/tpm/tpm_tis.c
+@@ -399,7 +399,7 @@ static irqreturn_t tis_int_probe(int irq, void *dev_id)
+ return IRQ_HANDLED;
+ }
+
+-static irqreturn_t tis_int_handler(int irq, void *dev_id)
++static irqreturn_t tis_int_handler(int dummy, void *dev_id)
+ {
+ struct tpm_chip *chip = dev_id;
+ u32 interrupt;
+diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
+index 613ec81..4d3c701 100644
+--- a/drivers/char/tty_io.c
++++ b/drivers/char/tty_io.c
+@@ -1155,6 +1155,48 @@ static struct tty_driver *get_tty_driver(dev_t device, int *index)
+ return NULL;
+ }
+
++#ifdef CONFIG_CONSOLE_POLL
++
++/**
++ * tty_find_polling_driver - find device of a polled tty
++ * @name: name string to match
++ * @line: pointer to resulting tty line nr
++ *
++ * This routine returns a tty driver structure, given a name
++ * and the condition that the tty driver is capable of polled
++ * operation.
++ */
++struct tty_driver *tty_find_polling_driver(char *name, int *line)
++{
++ struct tty_driver *p, *res = NULL;
++ int tty_line = 0;
++ char *str;
++
++ mutex_lock(&tty_mutex);
++ /* Search through the tty devices to look for a match */
++ list_for_each_entry(p, &tty_drivers, tty_drivers) {
++ str = name + strlen(p->name);
++ tty_line = simple_strtoul(str, &str, 10);
++ if (*str == ',')
++ str++;
++ if (*str == '\0')
++ str = 0;
++
++ if (tty_line >= 0 && tty_line <= p->num && p->poll_init &&
++ !p->poll_init(p, tty_line, str)) {
++
++ res = p;
++ *line = tty_line;
++ break;
++ }
++ }
++ mutex_unlock(&tty_mutex);
++
++ return res;
++}
++EXPORT_SYMBOL_GPL(tty_find_polling_driver);
++#endif
++
+ /**
+ * tty_check_change - check for POSIX terminal changes
+ * @tty: tty to check
+@@ -3850,6 +3892,11 @@ void tty_set_operations(struct tty_driver *driver,
+ driver->write_proc = op->write_proc;
+ driver->tiocmget = op->tiocmget;
+ driver->tiocmset = op->tiocmset;
++#ifdef CONFIG_CONSOLE_POLL
++ driver->poll_init = op->poll_init;
++ driver->poll_get_char = op->poll_get_char;
++ driver->poll_put_char = op->poll_put_char;
++#endif
+ }
+
+
+diff --git a/drivers/char/xilinx_hwicap/buffer_icap.c b/drivers/char/xilinx_hwicap/buffer_icap.c
+index f577dae..aa7f796 100644
+--- a/drivers/char/xilinx_hwicap/buffer_icap.c
++++ b/drivers/char/xilinx_hwicap/buffer_icap.c
+@@ -74,7 +74,7 @@
+
+ /**
+ * buffer_icap_get_status - Get the contents of the status register.
+- * @base_address: is the base address of the device
++ * @drvdata: a pointer to the drvdata.
+ *
+ * The status register contains the ICAP status and the done bit.
+ *
+@@ -88,9 +88,9 @@
+ * D1 - Always 1
+ * D0 - Done bit
+ **/
+-static inline u32 buffer_icap_get_status(void __iomem *base_address)
++u32 buffer_icap_get_status(struct hwicap_drvdata *drvdata)
+ {
+- return in_be32(base_address + XHI_STATUS_REG_OFFSET);
++ return in_be32(drvdata->base_address + XHI_STATUS_REG_OFFSET);
+ }
+
+ /**
+@@ -117,20 +117,8 @@ static inline u32 buffer_icap_get_bram(void __iomem *base_address,
+ **/
+ static inline bool buffer_icap_busy(void __iomem *base_address)
+ {
+- return (buffer_icap_get_status(base_address) & 1) == XHI_NOT_FINISHED;
+-}
+-
+-/**
+- * buffer_icap_busy - Return true if the icap device is not busy
+- * @base_address: is the base address of the device
+- *
+- * The queries the low order bit of the status register, which
+- * indicates whether the current configuration or readback operation
+- * has completed.
+- **/
+-static inline bool buffer_icap_done(void __iomem *base_address)
+-{
+- return (buffer_icap_get_status(base_address) & 1) == XHI_FINISHED;
++ u32 status = in_be32(base_address + XHI_STATUS_REG_OFFSET);
++ return (status & 1) == XHI_NOT_FINISHED;
+ }
+
+ /**
+diff --git a/drivers/char/xilinx_hwicap/buffer_icap.h b/drivers/char/xilinx_hwicap/buffer_icap.h
+index 0318495..c5b1840 100644
+--- a/drivers/char/xilinx_hwicap/buffer_icap.h
++++ b/drivers/char/xilinx_hwicap/buffer_icap.h
+@@ -44,8 +44,6 @@
+ #include <asm/io.h>
+ #include "xilinx_hwicap.h"
+
+-void buffer_icap_reset(struct hwicap_drvdata *drvdata);
+-
+ /* Loads a partial bitstream from system memory. */
+ int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data,
+ u32 Size);
+@@ -54,4 +52,7 @@ int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data,
+ int buffer_icap_get_configuration(struct hwicap_drvdata *drvdata, u32 *data,
+ u32 Size);
+
++u32 buffer_icap_get_status(struct hwicap_drvdata *drvdata);
++void buffer_icap_reset(struct hwicap_drvdata *drvdata);
++
+ #endif
+diff --git a/drivers/char/xilinx_hwicap/fifo_icap.c b/drivers/char/xilinx_hwicap/fifo_icap.c
+index 6f45dbd..776b505 100644
+--- a/drivers/char/xilinx_hwicap/fifo_icap.c
++++ b/drivers/char/xilinx_hwicap/fifo_icap.c
+@@ -78,13 +78,6 @@
+ #define XHI_CR_READ_MASK 0x00000002 /* Read from ICAP to FIFO */
+ #define XHI_CR_WRITE_MASK 0x00000001 /* Write from FIFO to ICAP */
+
+-/* Status Register (SR) */
+-#define XHI_SR_CFGERR_N_MASK 0x00000100 /* Config Error Mask */
+-#define XHI_SR_DALIGN_MASK 0x00000080 /* Data Alignment Mask */
+-#define XHI_SR_RIP_MASK 0x00000040 /* Read back Mask */
+-#define XHI_SR_IN_ABORT_N_MASK 0x00000020 /* Select Map Abort Mask */
+-#define XHI_SR_DONE_MASK 0x00000001 /* Done bit Mask */
+-
+
+ #define XHI_WFO_MAX_VACANCY 1024 /* Max Write FIFO Vacancy, in words */
+ #define XHI_RFO_MAX_OCCUPANCY 256 /* Max Read FIFO Occupancy, in words */
+@@ -152,13 +145,35 @@ static inline void fifo_icap_start_readback(struct hwicap_drvdata *drvdata)
+ }
+
+ /**
++ * fifo_icap_get_status - Get the contents of the status register.
++ * @drvdata: a pointer to the drvdata.
++ *
++ * The status register contains the ICAP status and the done bit.
++ *
++ * D8 - cfgerr
++ * D7 - dalign
++ * D6 - rip
++ * D5 - in_abort_l
++ * D4 - Always 1
++ * D3 - Always 1
++ * D2 - Always 1
++ * D1 - Always 1
++ * D0 - Done bit
++ **/
++u32 fifo_icap_get_status(struct hwicap_drvdata *drvdata)
++{
++ u32 status = in_be32(drvdata->base_address + XHI_SR_OFFSET);
++ dev_dbg(drvdata->dev, "Getting status = %x\n", status);
++ return status;
++}
++
++/**
+ * fifo_icap_busy - Return true if the ICAP is still processing a transaction.
+ * @drvdata: a pointer to the drvdata.
+ **/
+ static inline u32 fifo_icap_busy(struct hwicap_drvdata *drvdata)
+ {
+ u32 status = in_be32(drvdata->base_address + XHI_SR_OFFSET);
+- dev_dbg(drvdata->dev, "Getting status = %x\n", status);
+ return (status & XHI_SR_DONE_MASK) ? 0 : 1;
+ }
+
+diff --git a/drivers/char/xilinx_hwicap/fifo_icap.h b/drivers/char/xilinx_hwicap/fifo_icap.h
+index 4d3068d..ffabd3b 100644
+--- a/drivers/char/xilinx_hwicap/fifo_icap.h
++++ b/drivers/char/xilinx_hwicap/fifo_icap.h
+@@ -56,6 +56,7 @@ int fifo_icap_set_configuration(
+ u32 *FrameBuffer,
+ u32 NumWords);
+
++u32 fifo_icap_get_status(struct hwicap_drvdata *drvdata);
+ void fifo_icap_reset(struct hwicap_drvdata *drvdata);
+ void fifo_icap_flush_fifo(struct hwicap_drvdata *drvdata);
+
+diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+index 2284fa2..dfe6907 100644
+--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
++++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+@@ -36,7 +36,7 @@
+ *****************************************************************************/
+
+ /*
+- * This is the code behind /dev/xilinx_icap -- it allows a user-space
++ * This is the code behind /dev/icap* -- it allows a user-space
+ * application to use the Xilinx ICAP subsystem.
+ *
+ * The following operations are possible:
+@@ -67,7 +67,7 @@
+ * user-space application code that uses this device. The simplest
+ * way to use this interface is simply:
+ *
+- * cp foo.bit /dev/xilinx_icap
++ * cp foo.bit /dev/icap0
+ *
+ * Note that unless foo.bit is an appropriately constructed partial
+ * bitstream, this has a high likelyhood of overwriting the design
+@@ -105,18 +105,14 @@
+ #include "buffer_icap.h"
+ #include "fifo_icap.h"
+
+-#define DRIVER_NAME "xilinx_icap"
++#define DRIVER_NAME "icap"
+
+ #define HWICAP_REGS (0x10000)
+
+-/* dynamically allocate device number */
+-static int xhwicap_major;
+-static int xhwicap_minor;
++#define XHWICAP_MAJOR 259
++#define XHWICAP_MINOR 0
+ #define HWICAP_DEVICES 1
+
+-module_param(xhwicap_major, int, S_IRUGO);
+-module_param(xhwicap_minor, int, S_IRUGO);
+-
+ /* An array, which is set to true when the device is registered. */
+ static bool probed_devices[HWICAP_DEVICES];
+ static struct mutex icap_sem;
+@@ -250,8 +246,26 @@ static int hwicap_get_configuration_register(struct hwicap_drvdata *drvdata,
+ * Create the data to be written to the ICAP.
+ */
+ buffer[index++] = XHI_DUMMY_PACKET;
++ buffer[index++] = XHI_NOOP_PACKET;
+ buffer[index++] = XHI_SYNC_PACKET;
+ buffer[index++] = XHI_NOOP_PACKET;
++ buffer[index++] = XHI_NOOP_PACKET;
++
++ /*
++ * Write the data to the FIFO and initiate the transfer of data present
++ * in the FIFO to the ICAP device.
++ */
++ status = drvdata->config->set_configuration(drvdata,
++ &buffer[0], index);
++ if (status)
++ return status;
++
++ /* If the syncword was not found, then we need to start over. */
++ status = drvdata->config->get_status(drvdata);
++ if ((status & XHI_SR_DALIGN_MASK) != XHI_SR_DALIGN_MASK)
++ return -EIO;
++
++ index = 0;
+ buffer[index++] = hwicap_type_1_read(reg) | 1;
+ buffer[index++] = XHI_NOOP_PACKET;
+ buffer[index++] = XHI_NOOP_PACKET;
+@@ -587,7 +601,7 @@ static int __devinit hwicap_setup(struct device *dev, int id,
+ probed_devices[id] = 1;
+ mutex_unlock(&icap_sem);
+
+- devt = MKDEV(xhwicap_major, xhwicap_minor + id);
++ devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR + id);
+
+ drvdata = kzalloc(sizeof(struct hwicap_drvdata), GFP_KERNEL);
+ if (!drvdata) {
+@@ -664,12 +678,14 @@ static int __devinit hwicap_setup(struct device *dev, int id,
+ static struct hwicap_driver_config buffer_icap_config = {
+ .get_configuration = buffer_icap_get_configuration,
+ .set_configuration = buffer_icap_set_configuration,
++ .get_status = buffer_icap_get_status,
+ .reset = buffer_icap_reset,
+ };
+
+ static struct hwicap_driver_config fifo_icap_config = {
+ .get_configuration = fifo_icap_get_configuration,
+ .set_configuration = fifo_icap_set_configuration,
++ .get_status = fifo_icap_get_status,
+ .reset = fifo_icap_reset,
+ };
+
+@@ -690,7 +706,7 @@ static int __devexit hwicap_remove(struct device *dev)
+ dev_set_drvdata(dev, NULL);
+
+ mutex_lock(&icap_sem);
+- probed_devices[MINOR(dev->devt)-xhwicap_minor] = 0;
++ probed_devices[MINOR(dev->devt)-XHWICAP_MINOR] = 0;
+ mutex_unlock(&icap_sem);
+ return 0; /* success */
+ }
+@@ -787,7 +803,7 @@ static int __devexit hwicap_of_remove(struct of_device *op)
+ }
+
+ /* Match table for of_platform binding */
+-static const struct of_device_id __devinit hwicap_of_match[] = {
++static const struct of_device_id __devinitconst hwicap_of_match[] = {
+ { .compatible = "xlnx,opb-hwicap-1.00.b", .data = &buffer_icap_config},
+ { .compatible = "xlnx,xps-hwicap-1.00.a", .data = &fifo_icap_config},
+ {},
+@@ -830,23 +846,12 @@ static int __init hwicap_module_init(void)
+ icap_class = class_create(THIS_MODULE, "xilinx_config");
+ mutex_init(&icap_sem);
+
+- if (xhwicap_major) {
+- devt = MKDEV(xhwicap_major, xhwicap_minor);
+- retval = register_chrdev_region(
+- devt,
+- HWICAP_DEVICES,
+- DRIVER_NAME);
+- if (retval < 0)
+- return retval;
+- } else {
+- retval = alloc_chrdev_region(&devt,
+- xhwicap_minor,
+- HWICAP_DEVICES,
+- DRIVER_NAME);
+- if (retval < 0)
+- return retval;
+- xhwicap_major = MAJOR(devt);
+- }
++ devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR);
++ retval = register_chrdev_region(devt,
++ HWICAP_DEVICES,
++ DRIVER_NAME);
++ if (retval < 0)
++ return retval;
+
+ retval = platform_driver_register(&hwicap_platform_driver);
+
+@@ -871,7 +876,7 @@ static int __init hwicap_module_init(void)
+
+ static void __exit hwicap_module_cleanup(void)
+ {
+- dev_t devt = MKDEV(xhwicap_major, xhwicap_minor);
++ dev_t devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR);
+
+ class_destroy(icap_class);
+
+diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.h b/drivers/char/xilinx_hwicap/xilinx_hwicap.h
+index 405fee7..1f9c8b0 100644
+--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.h
++++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.h
+@@ -65,10 +65,27 @@ struct hwicap_drvdata {
+ };
+
+ struct hwicap_driver_config {
++ /* Read configuration data given by size into the data buffer.
++ Return 0 if successful. */
+ int (*get_configuration)(struct hwicap_drvdata *drvdata, u32 *data,
+ u32 size);
++ /* Write configuration data given by size from the data buffer.
++ Return 0 if successful. */
+ int (*set_configuration)(struct hwicap_drvdata *drvdata, u32 *data,
+ u32 size);
++ /* Get the status register, bit pattern given by:
++ * D8 - 0 = configuration error
++ * D7 - 1 = alignment found
++ * D6 - 1 = readback in progress
++ * D5 - 0 = abort in progress
++ * D4 - Always 1
++ * D3 - Always 1
++ * D2 - Always 1
++ * D1 - Always 1
++ * D0 - 1 = operation completed
++ */
++ u32 (*get_status)(struct hwicap_drvdata *drvdata);
++ /* Reset the hw */
+ void (*reset)(struct hwicap_drvdata *drvdata);
+ };
+
+@@ -163,6 +180,13 @@ struct config_registers {
+ /* Constant to use for CRC check when CRC has been disabled */
+ #define XHI_DISABLED_AUTO_CRC 0x0000DEFCUL
+
++/* Meanings of the bits returned by get_status */
++#define XHI_SR_CFGERR_N_MASK 0x00000100 /* Config Error Mask */
++#define XHI_SR_DALIGN_MASK 0x00000080 /* Data Alignment Mask */
++#define XHI_SR_RIP_MASK 0x00000040 /* Read back Mask */
++#define XHI_SR_IN_ABORT_N_MASK 0x00000020 /* Select Map Abort Mask */
++#define XHI_SR_DONE_MASK 0x00000001 /* Done bit Mask */
++
+ /**
+ * hwicap_type_1_read - Generates a Type 1 read packet header.
+ * @reg: is the address of the register to be read back.
+diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
+index a522254..1525882 100644
+--- a/drivers/clocksource/Makefile
++++ b/drivers/clocksource/Makefile
+@@ -1,3 +1,4 @@
++obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o
+ obj-$(CONFIG_X86_CYCLONE_TIMER) += cyclone.o
+ obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o
+ obj-$(CONFIG_SCx200HR_TIMER) += scx200_hrt.o
+diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c
+new file mode 100644
+index 0000000..f450588
+--- /dev/null
++++ b/drivers/clocksource/tcb_clksrc.c
+@@ -0,0 +1,302 @@
++#include <linux/init.h>
++#include <linux/clocksource.h>
++#include <linux/clockchips.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++
++#include <linux/clk.h>
++#include <linux/err.h>
++#include <linux/ioport.h>
++#include <linux/io.h>
++#include <linux/platform_device.h>
++#include <linux/atmel_tc.h>
++
++
++/*
++ * We're configured to use a specific TC block, one that's not hooked
++ * up to external hardware, to provide a time solution:
++ *
++ * - Two channels combine to create a free-running 32 bit counter
++ * with a base rate of 5+ MHz, packaged as a clocksource (with
++ * resolution better than 200 nsec).
++ *
++ * - The third channel may be used to provide a 16-bit clockevent
++ * source, used in either periodic or oneshot mode. This runs
++ * at 32 KiHZ, and can handle delays of up to two seconds.
++ *
++ * A boot clocksource and clockevent source are also currently needed,
++ * unless the relevant platforms (ARM/AT91, AVR32/AT32) are changed so
++ * this code can be used when init_timers() is called, well before most
++ * devices are set up. (Some low end AT91 parts, which can run uClinux,
++ * have only the timers in one TC block... they currently don't support
++ * the tclib code, because of that initialization issue.)
++ *
++ * REVISIT behavior during system suspend states... we should disable
++ * all clocks and save the power. Easily done for clockevent devices,
++ * but clocksources won't necessarily get the needed notifications.
++ * For deeper system sleep states, this will be mandatory...
++ */
++
++static void __iomem *tcaddr;
++
++static cycle_t tc_get_cycles(void)
++{
++ unsigned long flags;
++ u32 lower, upper;
++
++ raw_local_irq_save(flags);
++ do {
++ upper = __raw_readl(tcaddr + ATMEL_TC_REG(1, CV));
++ lower = __raw_readl(tcaddr + ATMEL_TC_REG(0, CV));
++ } while (upper != __raw_readl(tcaddr + ATMEL_TC_REG(1, CV)));
++
++ raw_local_irq_restore(flags);
++ return (upper << 16) | lower;
++}
++
++static struct clocksource clksrc = {
++ .name = "tcb_clksrc",
++ .rating = 200,
++ .read = tc_get_cycles,
++ .mask = CLOCKSOURCE_MASK(32),
++ .shift = 18,
++ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
++};
++
++#ifdef CONFIG_GENERIC_CLOCKEVENTS
++
++struct tc_clkevt_device {
++ struct clock_event_device clkevt;
++ struct clk *clk;
++ void __iomem *regs;
++};
++
++static struct tc_clkevt_device *to_tc_clkevt(struct clock_event_device *clkevt)
++{
++ return container_of(clkevt, struct tc_clkevt_device, clkevt);
++}
++
++/* For now, we always use the 32K clock ... this optimizes for NO_HZ,
++ * because using one of the divided clocks would usually mean the
++ * tick rate can never be less than several dozen Hz (vs 0.5 Hz).
++ *
++ * A divided clock could be good for high resolution timers, since
++ * 30.5 usec resolution can seem "low".
++ */
++static u32 timer_clock;
++
++static void tc_mode(enum clock_event_mode m, struct clock_event_device *d)
++{
++ struct tc_clkevt_device *tcd = to_tc_clkevt(d);
++ void __iomem *regs = tcd->regs;
++
++ if (tcd->clkevt.mode == CLOCK_EVT_MODE_PERIODIC
++ || tcd->clkevt.mode == CLOCK_EVT_MODE_ONESHOT) {
++ __raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR));
++ __raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR));
++ clk_disable(tcd->clk);
++ }
++
++ switch (m) {
++
++ /* By not making the gentime core emulate periodic mode on top
++ * of oneshot, we get lower overhead and improved accuracy.
++ */
++ case CLOCK_EVT_MODE_PERIODIC:
++ clk_enable(tcd->clk);
++
++ /* slow clock, count up to RC, then irq and restart */
++ __raw_writel(timer_clock
++ | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO,
++ regs + ATMEL_TC_REG(2, CMR));
++ __raw_writel((32768 + HZ/2) / HZ, tcaddr + ATMEL_TC_REG(2, RC));
++
++ /* Enable clock and interrupts on RC compare */
++ __raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
++
++ /* go go gadget! */
++ __raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG,
++ regs + ATMEL_TC_REG(2, CCR));
++ break;
++
++ case CLOCK_EVT_MODE_ONESHOT:
++ clk_enable(tcd->clk);
++
++ /* slow clock, count up to RC, then irq and stop */
++ __raw_writel(timer_clock | ATMEL_TC_CPCSTOP
++ | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO,
++ regs + ATMEL_TC_REG(2, CMR));
++ __raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
++
++ /* set_next_event() configures and starts the timer */
++ break;
++
++ default:
++ break;
++ }
++}
++
++static int tc_next_event(unsigned long delta, struct clock_event_device *d)
++{
++ __raw_writel(delta, tcaddr + ATMEL_TC_REG(2, RC));
++
++ /* go go gadget! */
++ __raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG,
++ tcaddr + ATMEL_TC_REG(2, CCR));
++ return 0;
++}
++
++static struct tc_clkevt_device clkevt = {
++ .clkevt = {
++ .name = "tc_clkevt",
++ .features = CLOCK_EVT_FEAT_PERIODIC
++ | CLOCK_EVT_FEAT_ONESHOT,
++ .shift = 32,
++ /* Should be lower than at91rm9200's system timer */
++ .rating = 125,
++ .cpumask = CPU_MASK_CPU0,
++ .set_next_event = tc_next_event,
++ .set_mode = tc_mode,
++ },
++};
++
++static irqreturn_t ch2_irq(int irq, void *handle)
++{
++ struct tc_clkevt_device *dev = handle;
++ unsigned int sr;
++
++ sr = __raw_readl(dev->regs + ATMEL_TC_REG(2, SR));
++ if (sr & ATMEL_TC_CPCS) {
++ dev->clkevt.event_handler(&dev->clkevt);
++ return IRQ_HANDLED;
++ }
++
++ return IRQ_NONE;
++}
++
++static struct irqaction tc_irqaction = {
++ .name = "tc_clkevt",
++ .flags = IRQF_TIMER | IRQF_DISABLED,
++ .handler = ch2_irq,
++};
++
++static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
++{
++ struct clk *t2_clk = tc->clk[2];
++ int irq = tc->irq[2];
++
++ clkevt.regs = tc->regs;
++ clkevt.clk = t2_clk;
++ tc_irqaction.dev_id = &clkevt;
++
++ timer_clock = clk32k_divisor_idx;
++
++ clkevt.clkevt.mult = div_sc(32768, NSEC_PER_SEC, clkevt.clkevt.shift);
++ clkevt.clkevt.max_delta_ns
++ = clockevent_delta2ns(0xffff, &clkevt.clkevt);
++ clkevt.clkevt.min_delta_ns = clockevent_delta2ns(1, &clkevt.clkevt) + 1;
++
++ setup_irq(irq, &tc_irqaction);
++
++ clockevents_register_device(&clkevt.clkevt);
++}
++
++#else /* !CONFIG_GENERIC_CLOCKEVENTS */
++
++static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
++{
++ /* NOTHING */
++}
++
++#endif
++
++static int __init tcb_clksrc_init(void)
++{
++ static char bootinfo[] __initdata
++ = KERN_DEBUG "%s: tc%d at %d.%03d MHz\n";
++
++ struct platform_device *pdev;
++ struct atmel_tc *tc;
++ struct clk *t0_clk;
++ u32 rate, divided_rate = 0;
++ int best_divisor_idx = -1;
++ int clk32k_divisor_idx = -1;
++ int i;
++
++ tc = atmel_tc_alloc(CONFIG_ATMEL_TCB_CLKSRC_BLOCK, clksrc.name);
++ if (!tc) {
++ pr_debug("can't alloc TC for clocksource\n");
++ return -ENODEV;
++ }
++ tcaddr = tc->regs;
++ pdev = tc->pdev;
++
++ t0_clk = tc->clk[0];
++ clk_enable(t0_clk);
++
++ /* How fast will we be counting? Pick something over 5 MHz. */
++ rate = (u32) clk_get_rate(t0_clk);
++ for (i = 0; i < 5; i++) {
++ unsigned divisor = atmel_tc_divisors[i];
++ unsigned tmp;
++
++ /* remember 32 KiHz clock for later */
++ if (!divisor) {
++ clk32k_divisor_idx = i;
++ continue;
++ }
++
++ tmp = rate / divisor;
++ pr_debug("TC: %u / %-3u [%d] --> %u\n", rate, divisor, i, tmp);
++ if (best_divisor_idx > 0) {
++ if (tmp < 5 * 1000 * 1000)
++ continue;
++ }
++ divided_rate = tmp;
++ best_divisor_idx = i;
++ }
++
++ clksrc.mult = clocksource_hz2mult(divided_rate, clksrc.shift);
++
++ printk(bootinfo, clksrc.name, CONFIG_ATMEL_TCB_CLKSRC_BLOCK,
++ divided_rate / 1000000,
++ ((divided_rate + 500000) % 1000000) / 1000);
++
++ /* tclib will give us three clocks no matter what the
++ * underlying platform supports.
++ */
++ clk_enable(tc->clk[1]);
++
++ /* channel 0: waveform mode, input mclk/8, clock TIOA0 on overflow */
++ __raw_writel(best_divisor_idx /* likely divide-by-8 */
++ | ATMEL_TC_WAVE
++ | ATMEL_TC_WAVESEL_UP /* free-run */
++ | ATMEL_TC_ACPA_SET /* TIOA0 rises at 0 */
++ | ATMEL_TC_ACPC_CLEAR, /* (duty cycle 50%) */
++ tcaddr + ATMEL_TC_REG(0, CMR));
++ __raw_writel(0x0000, tcaddr + ATMEL_TC_REG(0, RA));
++ __raw_writel(0x8000, tcaddr + ATMEL_TC_REG(0, RC));
++ __raw_writel(0xff, tcaddr + ATMEL_TC_REG(0, IDR)); /* no irqs */
++ __raw_writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(0, CCR));
++
++ /* channel 1: waveform mode, input TIOA0 */
++ __raw_writel(ATMEL_TC_XC1 /* input: TIOA0 */
++ | ATMEL_TC_WAVE
++ | ATMEL_TC_WAVESEL_UP, /* free-run */
++ tcaddr + ATMEL_TC_REG(1, CMR));
++ __raw_writel(0xff, tcaddr + ATMEL_TC_REG(1, IDR)); /* no irqs */
++ __raw_writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(1, CCR));
++
++ /* chain channel 0 to channel 1, then reset all the timers */
++ __raw_writel(ATMEL_TC_TC1XC1S_TIOA0, tcaddr + ATMEL_TC_BMR);
++ __raw_writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR);
++
++ /* and away we go! */
++ clocksource_register(&clksrc);
++
++ /* channel 2: periodic and oneshot timer support */
++ setup_clkevents(tc, clk32k_divisor_idx);
++
++ return 0;
++}
++arch_initcall(tcb_clksrc_init);
+diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
+index 6b658d8..43b71b6 100644
+--- a/drivers/crypto/Kconfig
++++ b/drivers/crypto/Kconfig
+@@ -27,6 +27,7 @@ config CRYPTO_DEV_PADLOCK_AES
+ tristate "PadLock driver for AES algorithm"
+ depends on CRYPTO_DEV_PADLOCK
+ select CRYPTO_BLKCIPHER
++ select CRYPTO_AES
+ help
+ Use VIA PadLock for AES algorithm.
+
+@@ -64,6 +65,7 @@ config ZCRYPT
+ tristate "Support for PCI-attached cryptographic adapters"
+ depends on S390
+ select ZCRYPT_MONOLITHIC if ZCRYPT="y"
++ select HW_RANDOM
+ help
+ Select this option if you want to use a PCI-attached cryptographic
+ adapter like:
+@@ -100,6 +102,19 @@ config CRYPTO_SHA256_S390
+ This version of SHA implements a 256 bit hash with 128 bits of
+ security against collision attacks.
+
++config CRYPTO_SHA512_S390
++ tristate "SHA384 and SHA512 digest algorithm"
++ depends on S390
++ select CRYPTO_ALGAPI
++ help
++ This is the s390 hardware accelerated implementation of the
++ SHA512 secure hash standard.
++
++ This version of SHA implements a 512 bit hash with 256 bits of
++ security against collision attacks. The code also includes SHA-384,
++ a 384 bit hash with 192 bits of security against collision attacks.
++
++
+ config CRYPTO_DES_S390
+ tristate "DES and Triple DES cipher algorithms"
+ depends on S390
+diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
+index 2f3ad3f..bb30eb9 100644
+--- a/drivers/crypto/padlock-aes.c
++++ b/drivers/crypto/padlock-aes.c
+@@ -5,42 +5,6 @@
+ *
+ * Copyright (c) 2004 Michal Ludvig <michal at logix.cz>
+ *
+- * Key expansion routine taken from crypto/aes_generic.c
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * ---------------------------------------------------------------------------
+- * Copyright (c) 2002, Dr Brian Gladman <brg at gladman.me.uk>, Worcester, UK.
+- * All rights reserved.
+- *
+- * LICENSE TERMS
+- *
+- * The free distribution and use of this software in both source and binary
+- * form is allowed (with or without changes) provided that:
+- *
+- * 1. distributions of this source code include the above copyright
+- * notice, this list of conditions and the following disclaimer;
+- *
+- * 2. distributions in binary form include the above copyright
+- * notice, this list of conditions and the following disclaimer
+- * in the documentation and/or other associated materials;
+- *
+- * 3. the copyright holder's name is not used to endorse products
+- * built using this software without specific written permission.
+- *
+- * ALTERNATIVELY, provided that this notice is retained in full, this product
+- * may be distributed under the terms of the GNU General Public License (GPL),
+- * in which case the provisions of the GPL apply INSTEAD OF those given above.
+- *
+- * DISCLAIMER
+- *
+- * This software is provided 'as is' with no explicit or implied warranties
+- * in respect of its properties, including, but not limited to, correctness
+- * and/or fitness for purpose.
+- * ---------------------------------------------------------------------------
+ */
+
+ #include <crypto/algapi.h>
+@@ -54,9 +18,6 @@
+ #include <asm/byteorder.h>
+ #include "padlock.h"
+
+-#define AES_EXTENDED_KEY_SIZE 64 /* in uint32_t units */
+-#define AES_EXTENDED_KEY_SIZE_B (AES_EXTENDED_KEY_SIZE * sizeof(uint32_t))
+-
+ /* Control word. */
+ struct cword {
+ unsigned int __attribute__ ((__packed__))
+@@ -70,218 +31,23 @@ struct cword {
+
+ /* Whenever making any changes to the following
+ * structure *make sure* you keep E, d_data
+- * and cword aligned on 16 Bytes boundaries!!! */
++ * and cword aligned on 16 Bytes boundaries and
++ * the Hardware can access 16 * 16 bytes of E and d_data
++ * (only the first 15 * 16 bytes matter but the HW reads
++ * more).
++ */
+ struct aes_ctx {
++ u32 E[AES_MAX_KEYLENGTH_U32]
++ __attribute__ ((__aligned__(PADLOCK_ALIGNMENT)));
++ u32 d_data[AES_MAX_KEYLENGTH_U32]
++ __attribute__ ((__aligned__(PADLOCK_ALIGNMENT)));
+ struct {
+ struct cword encrypt;
+ struct cword decrypt;
+ } cword;
+ u32 *D;
+- int key_length;
+- u32 E[AES_EXTENDED_KEY_SIZE]
+- __attribute__ ((__aligned__(PADLOCK_ALIGNMENT)));
+- u32 d_data[AES_EXTENDED_KEY_SIZE]
+- __attribute__ ((__aligned__(PADLOCK_ALIGNMENT)));
+ };
+
+-/* ====== Key management routines ====== */
+-
+-static inline uint32_t
+-generic_rotr32 (const uint32_t x, const unsigned bits)
+-{
+- const unsigned n = bits % 32;
+- return (x >> n) | (x << (32 - n));
+-}
+-
+-static inline uint32_t
+-generic_rotl32 (const uint32_t x, const unsigned bits)
+-{
+- const unsigned n = bits % 32;
+- return (x << n) | (x >> (32 - n));
+-}
+-
+-#define rotl generic_rotl32
+-#define rotr generic_rotr32
+-
+-/*
+- * #define byte(x, nr) ((unsigned char)((x) >> (nr*8)))
+- */
+-static inline uint8_t
+-byte(const uint32_t x, const unsigned n)
+-{
+- return x >> (n << 3);
+-}
+-
+-#define E_KEY ctx->E
+-#define D_KEY ctx->D
+-
+-static uint8_t pow_tab[256];
+-static uint8_t log_tab[256];
+-static uint8_t sbx_tab[256];
+-static uint8_t isb_tab[256];
+-static uint32_t rco_tab[10];
+-static uint32_t ft_tab[4][256];
+-static uint32_t it_tab[4][256];
+-
+-static uint32_t fl_tab[4][256];
+-static uint32_t il_tab[4][256];
+-
+-static inline uint8_t
+-f_mult (uint8_t a, uint8_t b)
+-{
+- uint8_t aa = log_tab[a], cc = aa + log_tab[b];
+-
+- return pow_tab[cc + (cc < aa ? 1 : 0)];
+-}
+-
+-#define ff_mult(a,b) (a && b ? f_mult(a, b) : 0)
+-
+-#define f_rn(bo, bi, n, k) \
+- bo[n] = ft_tab[0][byte(bi[n],0)] ^ \
+- ft_tab[1][byte(bi[(n + 1) & 3],1)] ^ \
+- ft_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
+- ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
+-
+-#define i_rn(bo, bi, n, k) \
+- bo[n] = it_tab[0][byte(bi[n],0)] ^ \
+- it_tab[1][byte(bi[(n + 3) & 3],1)] ^ \
+- it_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
+- it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
+-
+-#define ls_box(x) \
+- ( fl_tab[0][byte(x, 0)] ^ \
+- fl_tab[1][byte(x, 1)] ^ \
+- fl_tab[2][byte(x, 2)] ^ \
+- fl_tab[3][byte(x, 3)] )
+-
+-#define f_rl(bo, bi, n, k) \
+- bo[n] = fl_tab[0][byte(bi[n],0)] ^ \
+- fl_tab[1][byte(bi[(n + 1) & 3],1)] ^ \
+- fl_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
+- fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
+-
+-#define i_rl(bo, bi, n, k) \
+- bo[n] = il_tab[0][byte(bi[n],0)] ^ \
+- il_tab[1][byte(bi[(n + 3) & 3],1)] ^ \
+- il_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
+- il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
+-
+-static void
+-gen_tabs (void)
+-{
+- uint32_t i, t;
+- uint8_t p, q;
+-
+- /* log and power tables for GF(2**8) finite field with
+- 0x011b as modular polynomial - the simplest prmitive
+- root is 0x03, used here to generate the tables */
+-
+- for (i = 0, p = 1; i < 256; ++i) {
+- pow_tab[i] = (uint8_t) p;
+- log_tab[p] = (uint8_t) i;
+-
+- p ^= (p << 1) ^ (p & 0x80 ? 0x01b : 0);
+- }
+-
+- log_tab[1] = 0;
+-
+- for (i = 0, p = 1; i < 10; ++i) {
+- rco_tab[i] = p;
+-
+- p = (p << 1) ^ (p & 0x80 ? 0x01b : 0);
+- }
+-
+- for (i = 0; i < 256; ++i) {
+- p = (i ? pow_tab[255 - log_tab[i]] : 0);
+- q = ((p >> 7) | (p << 1)) ^ ((p >> 6) | (p << 2));
+- p ^= 0x63 ^ q ^ ((q >> 6) | (q << 2));
+- sbx_tab[i] = p;
+- isb_tab[p] = (uint8_t) i;
+- }
+-
+- for (i = 0; i < 256; ++i) {
+- p = sbx_tab[i];
+-
+- t = p;
+- fl_tab[0][i] = t;
+- fl_tab[1][i] = rotl (t, 8);
+- fl_tab[2][i] = rotl (t, 16);
+- fl_tab[3][i] = rotl (t, 24);
+-
+- t = ((uint32_t) ff_mult (2, p)) |
+- ((uint32_t) p << 8) |
+- ((uint32_t) p << 16) | ((uint32_t) ff_mult (3, p) << 24);
+-
+- ft_tab[0][i] = t;
+- ft_tab[1][i] = rotl (t, 8);
+- ft_tab[2][i] = rotl (t, 16);
+- ft_tab[3][i] = rotl (t, 24);
+-
+- p = isb_tab[i];
+-
+- t = p;
+- il_tab[0][i] = t;
+- il_tab[1][i] = rotl (t, 8);
+- il_tab[2][i] = rotl (t, 16);
+- il_tab[3][i] = rotl (t, 24);
+-
+- t = ((uint32_t) ff_mult (14, p)) |
+- ((uint32_t) ff_mult (9, p) << 8) |
+- ((uint32_t) ff_mult (13, p) << 16) |
+- ((uint32_t) ff_mult (11, p) << 24);
+-
+- it_tab[0][i] = t;
+- it_tab[1][i] = rotl (t, 8);
+- it_tab[2][i] = rotl (t, 16);
+- it_tab[3][i] = rotl (t, 24);
+- }
+-}
+-
+-#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)
+-
+-#define imix_col(y,x) \
+- u = star_x(x); \
+- v = star_x(u); \
+- w = star_x(v); \
+- t = w ^ (x); \
+- (y) = u ^ v ^ w; \
+- (y) ^= rotr(u ^ t, 8) ^ \
+- rotr(v ^ t, 16) ^ \
+- rotr(t,24)
+-
+-/* initialise the key schedule from the user supplied key */
+-
+-#define loop4(i) \
+-{ t = rotr(t, 8); t = ls_box(t) ^ rco_tab[i]; \
+- t ^= E_KEY[4 * i]; E_KEY[4 * i + 4] = t; \
+- t ^= E_KEY[4 * i + 1]; E_KEY[4 * i + 5] = t; \
+- t ^= E_KEY[4 * i + 2]; E_KEY[4 * i + 6] = t; \
+- t ^= E_KEY[4 * i + 3]; E_KEY[4 * i + 7] = t; \
+-}
+-
+-#define loop6(i) \
+-{ t = rotr(t, 8); t = ls_box(t) ^ rco_tab[i]; \
+- t ^= E_KEY[6 * i]; E_KEY[6 * i + 6] = t; \
+- t ^= E_KEY[6 * i + 1]; E_KEY[6 * i + 7] = t; \
+- t ^= E_KEY[6 * i + 2]; E_KEY[6 * i + 8] = t; \
+- t ^= E_KEY[6 * i + 3]; E_KEY[6 * i + 9] = t; \
+- t ^= E_KEY[6 * i + 4]; E_KEY[6 * i + 10] = t; \
+- t ^= E_KEY[6 * i + 5]; E_KEY[6 * i + 11] = t; \
+-}
+-
+-#define loop8(i) \
+-{ t = rotr(t, 8); ; t = ls_box(t) ^ rco_tab[i]; \
+- t ^= E_KEY[8 * i]; E_KEY[8 * i + 8] = t; \
+- t ^= E_KEY[8 * i + 1]; E_KEY[8 * i + 9] = t; \
+- t ^= E_KEY[8 * i + 2]; E_KEY[8 * i + 10] = t; \
+- t ^= E_KEY[8 * i + 3]; E_KEY[8 * i + 11] = t; \
+- t = E_KEY[8 * i + 4] ^ ls_box(t); \
+- E_KEY[8 * i + 12] = t; \
+- t ^= E_KEY[8 * i + 5]; E_KEY[8 * i + 13] = t; \
+- t ^= E_KEY[8 * i + 6]; E_KEY[8 * i + 14] = t; \
+- t ^= E_KEY[8 * i + 7]; E_KEY[8 * i + 15] = t; \
+-}
+-
+ /* Tells whether the ACE is capable to generate
+ the extended key for a given key_len. */
+ static inline int
+@@ -321,17 +87,13 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ struct aes_ctx *ctx = aes_ctx(tfm);
+ const __le32 *key = (const __le32 *)in_key;
+ u32 *flags = &tfm->crt_flags;
+- uint32_t i, t, u, v, w;
+- uint32_t P[AES_EXTENDED_KEY_SIZE];
+- uint32_t rounds;
++ struct crypto_aes_ctx gen_aes;
+
+ if (key_len % 8) {
+ *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -EINVAL;
+ }
+
+- ctx->key_length = key_len;
+-
+ /*
+ * If the hardware is capable of generating the extended key
+ * itself we must supply the plain key for both encryption
+@@ -339,10 +101,10 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ */
+ ctx->D = ctx->E;
+
+- E_KEY[0] = le32_to_cpu(key[0]);
+- E_KEY[1] = le32_to_cpu(key[1]);
+- E_KEY[2] = le32_to_cpu(key[2]);
+- E_KEY[3] = le32_to_cpu(key[3]);
++ ctx->E[0] = le32_to_cpu(key[0]);
++ ctx->E[1] = le32_to_cpu(key[1]);
++ ctx->E[2] = le32_to_cpu(key[2]);
++ ctx->E[3] = le32_to_cpu(key[3]);
+
+ /* Prepare control words. */
+ memset(&ctx->cword, 0, sizeof(ctx->cword));
+@@ -361,56 +123,13 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ ctx->cword.encrypt.keygen = 1;
+ ctx->cword.decrypt.keygen = 1;
+
+- switch (key_len) {
+- case 16:
+- t = E_KEY[3];
+- for (i = 0; i < 10; ++i)
+- loop4 (i);
+- break;
+-
+- case 24:
+- E_KEY[4] = le32_to_cpu(key[4]);
+- t = E_KEY[5] = le32_to_cpu(key[5]);
+- for (i = 0; i < 8; ++i)
+- loop6 (i);
+- break;
+-
+- case 32:
+- E_KEY[4] = le32_to_cpu(key[4]);
+- E_KEY[5] = le32_to_cpu(key[5]);
+- E_KEY[6] = le32_to_cpu(key[6]);
+- t = E_KEY[7] = le32_to_cpu(key[7]);
+- for (i = 0; i < 7; ++i)
+- loop8 (i);
+- break;
+- }
+-
+- D_KEY[0] = E_KEY[0];
+- D_KEY[1] = E_KEY[1];
+- D_KEY[2] = E_KEY[2];
+- D_KEY[3] = E_KEY[3];
+-
+- for (i = 4; i < key_len + 24; ++i) {
+- imix_col (D_KEY[i], E_KEY[i]);
+- }
+-
+- /* PadLock needs a different format of the decryption key. */
+- rounds = 10 + (key_len - 16) / 4;
+-
+- for (i = 0; i < rounds; i++) {
+- P[((i + 1) * 4) + 0] = D_KEY[((rounds - i - 1) * 4) + 0];
+- P[((i + 1) * 4) + 1] = D_KEY[((rounds - i - 1) * 4) + 1];
+- P[((i + 1) * 4) + 2] = D_KEY[((rounds - i - 1) * 4) + 2];
+- P[((i + 1) * 4) + 3] = D_KEY[((rounds - i - 1) * 4) + 3];
++ if (crypto_aes_expand_key(&gen_aes, in_key, key_len)) {
++ *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
++ return -EINVAL;
+ }
+
+- P[0] = E_KEY[(rounds * 4) + 0];
+- P[1] = E_KEY[(rounds * 4) + 1];
+- P[2] = E_KEY[(rounds * 4) + 2];
+- P[3] = E_KEY[(rounds * 4) + 3];
+-
+- memcpy(D_KEY, P, AES_EXTENDED_KEY_SIZE_B);
+-
++ memcpy(ctx->E, gen_aes.key_enc, AES_MAX_KEYLENGTH);
++ memcpy(ctx->D, gen_aes.key_dec, AES_MAX_KEYLENGTH);
+ return 0;
+ }
+
+@@ -675,7 +394,6 @@ static int __init padlock_init(void)
+ return -ENODEV;
+ }
+
+- gen_tabs();
+ if ((ret = crypto_register_alg(&aes_alg)))
+ goto aes_err;
+
+diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
+index 27340a7..6239c3d 100644
+--- a/drivers/dma/Kconfig
++++ b/drivers/dma/Kconfig
+@@ -46,14 +46,6 @@ config FSL_DMA
+ MPC8560/40, MPC8555, MPC8548 and MPC8641 processors.
+ The MPC8349, MPC8360 is also supported.
+
+-config FSL_DMA_SELFTEST
+- bool "Enable the self test for each DMA channel"
+- depends on FSL_DMA
+- default y
+- ---help---
+- Enable the self test for each DMA channel. A self test will be
+- performed after the channel probed to ensure the DMA works well.
+-
+ config DMA_ENGINE
+ bool
+
+diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
+index 8db0e7f..97b329e 100644
+--- a/drivers/dma/dmaengine.c
++++ b/drivers/dma/dmaengine.c
+@@ -42,9 +42,9 @@
+ *
+ * Each device has a kref, which is initialized to 1 when the device is
+ * registered. A kref_get is done for each device registered. When the
+- * device is released, the coresponding kref_put is done in the release
++ * device is released, the corresponding kref_put is done in the release
+ * method. Every time one of the device's channels is allocated to a client,
+- * a kref_get occurs. When the channel is freed, the coresponding kref_put
++ * a kref_get occurs. When the channel is freed, the corresponding kref_put
+ * happens. The device's release function does a completion, so
+ * unregister_device does a remove event, device_unregister, a kref_put
+ * for the first reference, then waits on the completion for all other
+@@ -53,7 +53,7 @@
+ * Each channel has an open-coded implementation of Rusty Russell's "bigref,"
+ * with a kref and a per_cpu local_t. A dma_chan_get is called when a client
+ * signals that it wants to use a channel, and dma_chan_put is called when
+- * a channel is removed or a client using it is unregesitered. A client can
++ * a channel is removed or a client using it is unregistered. A client can
+ * take extra references per outstanding transaction, as is the case with
+ * the NET DMA client. The release function does a kref_put on the device.
+ * -ChrisL, DanW
+@@ -362,7 +362,6 @@ int dma_async_device_register(struct dma_device *device)
+
+ BUG_ON(!device->device_alloc_chan_resources);
+ BUG_ON(!device->device_free_chan_resources);
+- BUG_ON(!device->device_dependency_added);
+ BUG_ON(!device->device_is_tx_complete);
+ BUG_ON(!device->device_issue_pending);
+ BUG_ON(!device->dev);
+@@ -479,7 +478,8 @@ dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest,
+
+ dma_src = dma_map_single(dev->dev, src, len, DMA_TO_DEVICE);
+ dma_dest = dma_map_single(dev->dev, dest, len, DMA_FROM_DEVICE);
+- tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, 0);
++ tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len,
++ DMA_CTRL_ACK);
+
+ if (!tx) {
+ dma_unmap_single(dev->dev, dma_src, len, DMA_TO_DEVICE);
+@@ -487,7 +487,6 @@ dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest,
+ return -ENOMEM;
+ }
+
+- tx->ack = 1;
+ tx->callback = NULL;
+ cookie = tx->tx_submit(tx);
+
+@@ -525,7 +524,8 @@ dma_async_memcpy_buf_to_pg(struct dma_chan *chan, struct page *page,
+
+ dma_src = dma_map_single(dev->dev, kdata, len, DMA_TO_DEVICE);
+ dma_dest = dma_map_page(dev->dev, page, offset, len, DMA_FROM_DEVICE);
+- tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, 0);
++ tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len,
++ DMA_CTRL_ACK);
+
+ if (!tx) {
+ dma_unmap_single(dev->dev, dma_src, len, DMA_TO_DEVICE);
+@@ -533,7 +533,6 @@ dma_async_memcpy_buf_to_pg(struct dma_chan *chan, struct page *page,
+ return -ENOMEM;
+ }
+
+- tx->ack = 1;
+ tx->callback = NULL;
+ cookie = tx->tx_submit(tx);
+
+@@ -574,7 +573,8 @@ dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg,
+ dma_src = dma_map_page(dev->dev, src_pg, src_off, len, DMA_TO_DEVICE);
+ dma_dest = dma_map_page(dev->dev, dest_pg, dest_off, len,
+ DMA_FROM_DEVICE);
+- tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, 0);
++ tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len,
++ DMA_CTRL_ACK);
+
+ if (!tx) {
+ dma_unmap_page(dev->dev, dma_src, len, DMA_TO_DEVICE);
+@@ -582,7 +582,6 @@ dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg,
+ return -ENOMEM;
+ }
+
+- tx->ack = 1;
+ tx->callback = NULL;
+ cookie = tx->tx_submit(tx);
+
+@@ -600,8 +599,6 @@ void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx,
+ {
+ tx->chan = chan;
+ spin_lock_init(&tx->lock);
+- INIT_LIST_HEAD(&tx->depend_node);
+- INIT_LIST_HEAD(&tx->depend_list);
+ }
+ EXPORT_SYMBOL(dma_async_tx_descriptor_init);
+
+diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
+index df16368..054eabf 100644
+--- a/drivers/dma/fsldma.c
++++ b/drivers/dma/fsldma.c
+@@ -412,7 +412,7 @@ static void fsl_dma_free_chan_resources(struct dma_chan *chan)
+ }
+
+ static struct dma_async_tx_descriptor *
+-fsl_dma_prep_interrupt(struct dma_chan *chan)
++fsl_dma_prep_interrupt(struct dma_chan *chan, unsigned long flags)
+ {
+ struct fsl_dma_chan *fsl_chan;
+ struct fsl_desc_sw *new;
+@@ -429,7 +429,7 @@ fsl_dma_prep_interrupt(struct dma_chan *chan)
+ }
+
+ new->async_tx.cookie = -EBUSY;
+- new->async_tx.ack = 0;
++ new->async_tx.flags = flags;
+
+ /* Insert the link descriptor to the LD ring */
+ list_add_tail(&new->node, &new->async_tx.tx_list);
+@@ -482,7 +482,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+ set_desc_next(fsl_chan, &prev->hw, new->async_tx.phys);
+
+ new->async_tx.cookie = 0;
+- new->async_tx.ack = 1;
++ async_tx_ack(&new->async_tx);
+
+ prev = new;
+ len -= copy;
+@@ -493,7 +493,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
+ list_add_tail(&new->node, &first->async_tx.tx_list);
+ } while (len);
+
+- new->async_tx.ack = 0; /* client is in control of this ack */
++ new->async_tx.flags = flags; /* client is in control of this ack */
+ new->async_tx.cookie = -EBUSY;
+
+ /* Set End-of-link to the last link descriptor of new list*/
+@@ -658,13 +658,6 @@ static void fsl_dma_memcpy_issue_pending(struct dma_chan *chan)
+ fsl_chan_xfer_ld_queue(fsl_chan);
+ }
+
+-static void fsl_dma_dependency_added(struct dma_chan *chan)
+-{
+- struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
+-
+- fsl_chan_ld_cleanup(fsl_chan);
+-}
+-
+ /**
+ * fsl_dma_is_complete - Determine the DMA status
+ * @fsl_chan : Freescale DMA channel
+@@ -696,6 +689,8 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
+ {
+ struct fsl_dma_chan *fsl_chan = (struct fsl_dma_chan *)data;
+ u32 stat;
++ int update_cookie = 0;
++ int xfer_ld_q = 0;
+
+ stat = get_sr(fsl_chan);
+ dev_dbg(fsl_chan->dev, "event: channel %d, stat = 0x%x\n",
+@@ -720,8 +715,8 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
+ * Now, update the completed cookie, and continue the
+ * next uncompleted transfer.
+ */
+- fsl_dma_update_completed_cookie(fsl_chan);
+- fsl_chan_xfer_ld_queue(fsl_chan);
++ update_cookie = 1;
++ xfer_ld_q = 1;
+ }
+ stat &= ~FSL_DMA_SR_PE;
+ }
+@@ -734,19 +729,33 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
+ dev_dbg(fsl_chan->dev, "event: clndar %p, nlndar %p\n",
+ (void *)get_cdar(fsl_chan), (void *)get_ndar(fsl_chan));
+ stat &= ~FSL_DMA_SR_EOSI;
+- fsl_dma_update_completed_cookie(fsl_chan);
++ update_cookie = 1;
++ }
++
++ /* For MPC8349, EOCDI event need to update cookie
++ * and start the next transfer if it exist.
++ */
++ if (stat & FSL_DMA_SR_EOCDI) {
++ dev_dbg(fsl_chan->dev, "event: End-of-Chain link INT\n");
++ stat &= ~FSL_DMA_SR_EOCDI;
++ update_cookie = 1;
++ xfer_ld_q = 1;
+ }
+
+ /* If it current transfer is the end-of-transfer,
+ * we should clear the Channel Start bit for
+ * prepare next transfer.
+ */
+- if (stat & (FSL_DMA_SR_EOLNI | FSL_DMA_SR_EOCDI)) {
++ if (stat & FSL_DMA_SR_EOLNI) {
+ dev_dbg(fsl_chan->dev, "event: End-of-link INT\n");
+ stat &= ~FSL_DMA_SR_EOLNI;
+- fsl_chan_xfer_ld_queue(fsl_chan);
++ xfer_ld_q = 1;
+ }
+
++ if (update_cookie)
++ fsl_dma_update_completed_cookie(fsl_chan);
++ if (xfer_ld_q)
++ fsl_chan_xfer_ld_queue(fsl_chan);
+ if (stat)
+ dev_dbg(fsl_chan->dev, "event: unhandled sr 0x%02x\n",
+ stat);
+@@ -776,15 +785,13 @@ static void dma_do_tasklet(unsigned long data)
+ fsl_chan_ld_cleanup(fsl_chan);
+ }
+
+-#ifdef FSL_DMA_CALLBACKTEST
+-static void fsl_dma_callback_test(struct fsl_dma_chan *fsl_chan)
++static void fsl_dma_callback_test(void *param)
+ {
++ struct fsl_dma_chan *fsl_chan = param;
+ if (fsl_chan)
+- dev_info(fsl_chan->dev, "selftest: callback is ok!\n");
++ dev_dbg(fsl_chan->dev, "selftest: callback is ok!\n");
+ }
+-#endif
+
+-#ifdef CONFIG_FSL_DMA_SELFTEST
+ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
+ {
+ struct dma_chan *chan;
+@@ -867,7 +874,7 @@ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
+ async_tx_ack(tx3);
+
+ /* Interrupt tx test */
+- tx1 = fsl_dma_prep_interrupt(chan);
++ tx1 = fsl_dma_prep_interrupt(chan, 0);
+ async_tx_ack(tx1);
+ cookie = fsl_dma_tx_submit(tx1);
+
+@@ -875,13 +882,11 @@ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
+ cookie = fsl_dma_tx_submit(tx3);
+ cookie = fsl_dma_tx_submit(tx2);
+
+-#ifdef FSL_DMA_CALLBACKTEST
+ if (dma_has_cap(DMA_INTERRUPT, ((struct fsl_dma_device *)
+ dev_get_drvdata(fsl_chan->dev->parent))->common.cap_mask)) {
+ tx3->callback = fsl_dma_callback_test;
+ tx3->callback_param = fsl_chan;
+ }
+-#endif
+ fsl_dma_memcpy_issue_pending(chan);
+ msleep(2);
+
+@@ -906,7 +911,6 @@ out:
+ kfree(src);
+ return err;
+ }
+-#endif
+
+ static int __devinit of_fsl_dma_chan_probe(struct of_device *dev,
+ const struct of_device_id *match)
+@@ -997,11 +1001,9 @@ static int __devinit of_fsl_dma_chan_probe(struct of_device *dev,
+ }
+ }
+
+-#ifdef CONFIG_FSL_DMA_SELFTEST
+ err = fsl_dma_self_test(new_fsl_chan);
+ if (err)
+ goto err;
+-#endif
+
+ dev_info(&dev->dev, "#%d (%s), irq %d\n", new_fsl_chan->id,
+ match->compatible, new_fsl_chan->irq);
+@@ -1080,7 +1082,6 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
+ fdev->common.device_prep_dma_memcpy = fsl_dma_prep_memcpy;
+ fdev->common.device_is_tx_complete = fsl_dma_is_complete;
+ fdev->common.device_issue_pending = fsl_dma_memcpy_issue_pending;
+- fdev->common.device_dependency_added = fsl_dma_dependency_added;
+ fdev->common.dev = &dev->dev;
+
+ irq = irq_of_parse_and_map(dev->node, 0);
+diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c
+index 4017d9e..318e8a2 100644
+--- a/drivers/dma/ioat_dma.c
++++ b/drivers/dma/ioat_dma.c
+@@ -212,14 +212,14 @@ static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx)
+ u32 copy;
+ size_t len;
+ dma_addr_t src, dst;
+- int orig_ack;
++ unsigned long orig_flags;
+ unsigned int desc_count = 0;
+
+ /* src and dest and len are stored in the initial descriptor */
+ len = first->len;
+ src = first->src;
+ dst = first->dst;
+- orig_ack = first->async_tx.ack;
++ orig_flags = first->async_tx.flags;
+ new = first;
+
+ spin_lock_bh(&ioat_chan->desc_lock);
+@@ -228,7 +228,7 @@ static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx)
+ do {
+ copy = min_t(size_t, len, ioat_chan->xfercap);
+
+- new->async_tx.ack = 1;
++ async_tx_ack(&new->async_tx);
+
+ hw = new->hw;
+ hw->size = copy;
+@@ -264,7 +264,7 @@ static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx)
+ }
+
+ new->tx_cnt = desc_count;
+- new->async_tx.ack = orig_ack; /* client is in control of this ack */
++ new->async_tx.flags = orig_flags; /* client is in control of this ack */
+
+ /* store the original values for use in later cleanup */
+ if (new != first) {
+@@ -304,14 +304,14 @@ static dma_cookie_t ioat2_tx_submit(struct dma_async_tx_descriptor *tx)
+ u32 copy;
+ size_t len;
+ dma_addr_t src, dst;
+- int orig_ack;
++ unsigned long orig_flags;
+ unsigned int desc_count = 0;
+
+ /* src and dest and len are stored in the initial descriptor */
+ len = first->len;
+ src = first->src;
+ dst = first->dst;
+- orig_ack = first->async_tx.ack;
++ orig_flags = first->async_tx.flags;
+ new = first;
+
+ /*
+@@ -321,7 +321,7 @@ static dma_cookie_t ioat2_tx_submit(struct dma_async_tx_descriptor *tx)
+ do {
+ copy = min_t(size_t, len, ioat_chan->xfercap);
+
+- new->async_tx.ack = 1;
++ async_tx_ack(&new->async_tx);
+
+ hw = new->hw;
+ hw->size = copy;
+@@ -349,7 +349,7 @@ static dma_cookie_t ioat2_tx_submit(struct dma_async_tx_descriptor *tx)
+ }
+
+ new->tx_cnt = desc_count;
+- new->async_tx.ack = orig_ack; /* client is in control of this ack */
++ new->async_tx.flags = orig_flags; /* client is in control of this ack */
+
+ /* store the original values for use in later cleanup */
+ if (new != first) {
+@@ -714,7 +714,7 @@ static struct dma_async_tx_descriptor *ioat1_dma_prep_memcpy(
+ new->len = len;
+ new->dst = dma_dest;
+ new->src = dma_src;
+- new->async_tx.ack = 0;
++ new->async_tx.flags = flags;
+ return &new->async_tx;
+ } else
+ return NULL;
+@@ -742,7 +742,7 @@ static struct dma_async_tx_descriptor *ioat2_dma_prep_memcpy(
+ new->len = len;
+ new->dst = dma_dest;
+ new->src = dma_src;
+- new->async_tx.ack = 0;
++ new->async_tx.flags = flags;
+ return &new->async_tx;
+ } else
+ return NULL;
+@@ -842,7 +842,7 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)
+ * a completed entry, but not the last, so clean
+ * up if the client is done with the descriptor
+ */
+- if (desc->async_tx.ack) {
++ if (async_tx_test_ack(&desc->async_tx)) {
+ list_del(&desc->node);
+ list_add_tail(&desc->node,
+ &ioat_chan->free_desc);
+@@ -924,17 +924,6 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)
+ spin_unlock_bh(&ioat_chan->cleanup_lock);
+ }
+
+-static void ioat_dma_dependency_added(struct dma_chan *chan)
+-{
+- struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+- spin_lock_bh(&ioat_chan->desc_lock);
+- if (ioat_chan->pending == 0) {
+- spin_unlock_bh(&ioat_chan->desc_lock);
+- ioat_dma_memcpy_cleanup(ioat_chan);
+- } else
+- spin_unlock_bh(&ioat_chan->desc_lock);
+-}
+-
+ /**
+ * ioat_dma_is_complete - poll the status of a IOAT DMA transaction
+ * @chan: IOAT DMA channel handle
+@@ -990,7 +979,7 @@ static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan)
+ desc->hw->size = 0;
+ desc->hw->src_addr = 0;
+ desc->hw->dst_addr = 0;
+- desc->async_tx.ack = 1;
++ async_tx_ack(&desc->async_tx);
+ switch (ioat_chan->device->version) {
+ case IOAT_VER_1_2:
+ desc->hw->next = 0;
+@@ -1316,7 +1305,6 @@ struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev,
+
+ dma_cap_set(DMA_MEMCPY, device->common.cap_mask);
+ device->common.device_is_tx_complete = ioat_dma_is_complete;
+- device->common.device_dependency_added = ioat_dma_dependency_added;
+ switch (device->version) {
+ case IOAT_VER_1_2:
+ device->common.device_prep_dma_memcpy = ioat1_dma_prep_memcpy;
+diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
+index f82b090..762b729 100644
+--- a/drivers/dma/iop-adma.c
++++ b/drivers/dma/iop-adma.c
+@@ -63,7 +63,6 @@ iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
+ struct iop_adma_chan *iop_chan, dma_cookie_t cookie)
+ {
+ BUG_ON(desc->async_tx.cookie < 0);
+- spin_lock_bh(&desc->async_tx.lock);
+ if (desc->async_tx.cookie > 0) {
+ cookie = desc->async_tx.cookie;
+ desc->async_tx.cookie = 0;
+@@ -101,7 +100,6 @@ iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
+
+ /* run dependent operations */
+ async_tx_run_dependencies(&desc->async_tx);
+- spin_unlock_bh(&desc->async_tx.lock);
+
+ return cookie;
+ }
+@@ -113,7 +111,7 @@ iop_adma_clean_slot(struct iop_adma_desc_slot *desc,
+ /* the client is allowed to attach dependent operations
+ * until 'ack' is set
+ */
+- if (!desc->async_tx.ack)
++ if (!async_tx_test_ack(&desc->async_tx))
+ return 0;
+
+ /* leave the last descriptor in the chain
+@@ -150,7 +148,7 @@ static void __iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
+ "this_desc: %#x next_desc: %#x ack: %d\n",
+ iter->async_tx.cookie, iter->idx, busy,
+ iter->async_tx.phys, iop_desc_get_next_desc(iter),
+- iter->async_tx.ack);
++ async_tx_test_ack(&iter->async_tx));
+ prefetch(_iter);
+ prefetch(&_iter->async_tx);
+
+@@ -257,8 +255,6 @@ static void __iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
+
+ BUG_ON(!seen_current);
+
+- iop_chan_idle(busy, iop_chan);
+-
+ if (cookie > 0) {
+ iop_chan->completed_cookie = cookie;
+ pr_debug("\tcompleted cookie %d\n", cookie);
+@@ -275,8 +271,11 @@ iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
+
+ static void iop_adma_tasklet(unsigned long data)
+ {
+- struct iop_adma_chan *chan = (struct iop_adma_chan *) data;
+- __iop_adma_slot_cleanup(chan);
++ struct iop_adma_chan *iop_chan = (struct iop_adma_chan *) data;
++
++ spin_lock(&iop_chan->lock);
++ __iop_adma_slot_cleanup(iop_chan);
++ spin_unlock(&iop_chan->lock);
+ }
+
+ static struct iop_adma_desc_slot *
+@@ -339,9 +338,7 @@ retry:
+
+ /* pre-ack all but the last descriptor */
+ if (num_slots != slots_per_op)
+- iter->async_tx.ack = 1;
+- else
+- iter->async_tx.ack = 0;
++ async_tx_ack(&iter->async_tx);
+
+ list_add_tail(&iter->chain_node, &chain);
+ alloc_tail = iter;
+@@ -514,7 +511,7 @@ static int iop_adma_alloc_chan_resources(struct dma_chan *chan)
+ }
+
+ static struct dma_async_tx_descriptor *
+-iop_adma_prep_dma_interrupt(struct dma_chan *chan)
++iop_adma_prep_dma_interrupt(struct dma_chan *chan, unsigned long flags)
+ {
+ struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+ struct iop_adma_desc_slot *sw_desc, *grp_start;
+@@ -529,6 +526,7 @@ iop_adma_prep_dma_interrupt(struct dma_chan *chan)
+ grp_start = sw_desc->group_head;
+ iop_desc_init_interrupt(grp_start, iop_chan);
+ grp_start->unmap_len = 0;
++ sw_desc->async_tx.flags = flags;
+ }
+ spin_unlock_bh(&iop_chan->lock);
+
+@@ -561,6 +559,7 @@ iop_adma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dma_dest,
+ iop_desc_set_memcpy_src_addr(grp_start, dma_src);
+ sw_desc->unmap_src_cnt = 1;
+ sw_desc->unmap_len = len;
++ sw_desc->async_tx.flags = flags;
+ }
+ spin_unlock_bh(&iop_chan->lock);
+
+@@ -593,6 +592,7 @@ iop_adma_prep_dma_memset(struct dma_chan *chan, dma_addr_t dma_dest,
+ iop_desc_set_dest_addr(grp_start, iop_chan, dma_dest);
+ sw_desc->unmap_src_cnt = 1;
+ sw_desc->unmap_len = len;
++ sw_desc->async_tx.flags = flags;
+ }
+ spin_unlock_bh(&iop_chan->lock);
+
+@@ -626,6 +626,7 @@ iop_adma_prep_dma_xor(struct dma_chan *chan, dma_addr_t dma_dest,
+ iop_desc_set_dest_addr(grp_start, iop_chan, dma_dest);
+ sw_desc->unmap_src_cnt = src_cnt;
+ sw_desc->unmap_len = len;
++ sw_desc->async_tx.flags = flags;
+ while (src_cnt--)
+ iop_desc_set_xor_src_addr(grp_start, src_cnt,
+ dma_src[src_cnt]);
+@@ -662,6 +663,7 @@ iop_adma_prep_dma_zero_sum(struct dma_chan *chan, dma_addr_t *dma_src,
+ __func__, grp_start->xor_check_result);
+ sw_desc->unmap_src_cnt = src_cnt;
+ sw_desc->unmap_len = len;
++ sw_desc->async_tx.flags = flags;
+ while (src_cnt--)
+ iop_desc_set_zero_sum_src_addr(grp_start, src_cnt,
+ dma_src[src_cnt]);
+@@ -671,12 +673,6 @@ iop_adma_prep_dma_zero_sum(struct dma_chan *chan, dma_addr_t *dma_src,
+ return sw_desc ? &sw_desc->async_tx : NULL;
+ }
+
+-static void iop_adma_dependency_added(struct dma_chan *chan)
+-{
+- struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+- tasklet_schedule(&iop_chan->irq_tasklet);
+-}
+-
+ static void iop_adma_free_chan_resources(struct dma_chan *chan)
+ {
+ struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+@@ -854,11 +850,11 @@ static int __devinit iop_adma_memcpy_self_test(struct iop_adma_device *device)
+ src_dma = dma_map_single(dma_chan->device->dev, src,
+ IOP_ADMA_TEST_SIZE, DMA_TO_DEVICE);
+ tx = iop_adma_prep_dma_memcpy(dma_chan, dest_dma, src_dma,
+- IOP_ADMA_TEST_SIZE, 1);
++ IOP_ADMA_TEST_SIZE,
++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+
+ cookie = iop_adma_tx_submit(tx);
+ iop_adma_issue_pending(dma_chan);
+- async_tx_ack(tx);
+ msleep(1);
+
+ if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) !=
+@@ -954,11 +950,11 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device)
+ dma_srcs[i] = dma_map_page(dma_chan->device->dev, xor_srcs[i],
+ 0, PAGE_SIZE, DMA_TO_DEVICE);
+ tx = iop_adma_prep_dma_xor(dma_chan, dest_dma, dma_srcs,
+- IOP_ADMA_NUM_SRC_TEST, PAGE_SIZE, 1);
++ IOP_ADMA_NUM_SRC_TEST, PAGE_SIZE,
++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+
+ cookie = iop_adma_tx_submit(tx);
+ iop_adma_issue_pending(dma_chan);
+- async_tx_ack(tx);
+ msleep(8);
+
+ if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) !=
+@@ -1001,11 +997,11 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device)
+ DMA_TO_DEVICE);
+ tx = iop_adma_prep_dma_zero_sum(dma_chan, dma_srcs,
+ IOP_ADMA_NUM_SRC_TEST + 1, PAGE_SIZE,
+- &zero_sum_result, 1);
++ &zero_sum_result,
++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+
+ cookie = iop_adma_tx_submit(tx);
+ iop_adma_issue_pending(dma_chan);
+- async_tx_ack(tx);
+ msleep(8);
+
+ if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+@@ -1025,11 +1021,11 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device)
+ /* test memset */
+ dma_addr = dma_map_page(dma_chan->device->dev, dest, 0,
+ PAGE_SIZE, DMA_FROM_DEVICE);
+- tx = iop_adma_prep_dma_memset(dma_chan, dma_addr, 0, PAGE_SIZE, 1);
++ tx = iop_adma_prep_dma_memset(dma_chan, dma_addr, 0, PAGE_SIZE,
++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+
+ cookie = iop_adma_tx_submit(tx);
+ iop_adma_issue_pending(dma_chan);
+- async_tx_ack(tx);
+ msleep(8);
+
+ if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+@@ -1057,11 +1053,11 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device)
+ DMA_TO_DEVICE);
+ tx = iop_adma_prep_dma_zero_sum(dma_chan, dma_srcs,
+ IOP_ADMA_NUM_SRC_TEST + 1, PAGE_SIZE,
+- &zero_sum_result, 1);
++ &zero_sum_result,
++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+
+ cookie = iop_adma_tx_submit(tx);
+ iop_adma_issue_pending(dma_chan);
+- async_tx_ack(tx);
+ msleep(8);
+
+ if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+@@ -1177,7 +1173,6 @@ static int __devinit iop_adma_probe(struct platform_device *pdev)
+ dma_dev->device_free_chan_resources = iop_adma_free_chan_resources;
+ dma_dev->device_is_tx_complete = iop_adma_is_complete;
+ dma_dev->device_issue_pending = iop_adma_issue_pending;
+- dma_dev->device_dependency_added = iop_adma_dependency_added;
+ dma_dev->dev = &pdev->dev;
+
+ /* set prep routines based on capability */
+@@ -1232,9 +1227,6 @@ static int __devinit iop_adma_probe(struct platform_device *pdev)
+ }
+
+ spin_lock_init(&iop_chan->lock);
+- init_timer(&iop_chan->cleanup_watchdog);
+- iop_chan->cleanup_watchdog.data = (unsigned long) iop_chan;
+- iop_chan->cleanup_watchdog.function = iop_adma_tasklet;
+ INIT_LIST_HEAD(&iop_chan->chain);
+ INIT_LIST_HEAD(&iop_chan->all_slots);
+ INIT_RCU_HEAD(&iop_chan->common.rcu);
+@@ -1298,7 +1290,7 @@ static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan)
+ grp_start = sw_desc->group_head;
+
+ list_splice_init(&sw_desc->async_tx.tx_list, &iop_chan->chain);
+- sw_desc->async_tx.ack = 1;
++ async_tx_ack(&sw_desc->async_tx);
+ iop_desc_init_memcpy(grp_start, 0);
+ iop_desc_set_byte_count(grp_start, iop_chan, 0);
+ iop_desc_set_dest_addr(grp_start, iop_chan, 0);
+@@ -1354,7 +1346,7 @@ static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan)
+ if (sw_desc) {
+ grp_start = sw_desc->group_head;
+ list_splice_init(&sw_desc->async_tx.tx_list, &iop_chan->chain);
+- sw_desc->async_tx.ack = 1;
++ async_tx_ack(&sw_desc->async_tx);
+ iop_desc_init_null_xor(grp_start, 2, 0);
+ iop_desc_set_byte_count(grp_start, iop_chan, 0);
+ iop_desc_set_dest_addr(grp_start, iop_chan, 0);
+diff --git a/drivers/firewire/Kconfig b/drivers/firewire/Kconfig
+index 25bdc2d..fb4d391 100644
+--- a/drivers/firewire/Kconfig
++++ b/drivers/firewire/Kconfig
+@@ -54,6 +54,11 @@ config FIREWIRE_OHCI
+ directive, use "install modulename /bin/true" for the modules to be
+ blacklisted.
+
++config FIREWIRE_OHCI_DEBUG
++ bool
++ depends on FIREWIRE_OHCI
++ default y
++
+ config FIREWIRE_SBP2
+ tristate "Support for storage devices (SBP-2 protocol driver)"
+ depends on FIREWIRE && SCSI
+diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c
+index a034627..5b4c0d9 100644
+--- a/drivers/firewire/fw-card.c
++++ b/drivers/firewire/fw-card.c
+@@ -167,7 +167,6 @@ fw_core_add_descriptor(struct fw_descriptor *desc)
+
+ return 0;
+ }
+-EXPORT_SYMBOL(fw_core_add_descriptor);
+
+ void
+ fw_core_remove_descriptor(struct fw_descriptor *desc)
+@@ -182,7 +181,6 @@ fw_core_remove_descriptor(struct fw_descriptor *desc)
+
+ mutex_unlock(&card_mutex);
+ }
+-EXPORT_SYMBOL(fw_core_remove_descriptor);
+
+ static const char gap_count_table[] = {
+ 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40
+@@ -220,7 +218,7 @@ fw_card_bm_work(struct work_struct *work)
+ struct bm_data bmd;
+ unsigned long flags;
+ int root_id, new_root_id, irm_id, gap_count, generation, grace;
+- int do_reset = 0;
++ bool do_reset = false;
+
+ spin_lock_irqsave(&card->lock, flags);
+ local_node = card->local_node;
+@@ -331,7 +329,7 @@ fw_card_bm_work(struct work_struct *work)
+ */
+ spin_unlock_irqrestore(&card->lock, flags);
+ goto out;
+- } else if (root_device->config_rom[2] & BIB_CMC) {
++ } else if (root_device->cmc) {
+ /*
+ * FIXME: I suppose we should set the cmstr bit in the
+ * STATE_CLEAR register of this node, as described in
+@@ -360,14 +358,14 @@ fw_card_bm_work(struct work_struct *work)
+ gap_count = 63;
+
+ /*
+- * Finally, figure out if we should do a reset or not. If we've
+- * done less that 5 resets with the same physical topology and we
++ * Finally, figure out if we should do a reset or not. If we have
++ * done less than 5 resets with the same physical topology and we
+ * have either a new root or a new gap count setting, let's do it.
+ */
+
+ if (card->bm_retries++ < 5 &&
+ (card->gap_count != gap_count || new_root_id != root_id))
+- do_reset = 1;
++ do_reset = true;
+
+ spin_unlock_irqrestore(&card->lock, flags);
+
+@@ -398,7 +396,6 @@ fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver,
+ {
+ static atomic_t index = ATOMIC_INIT(-1);
+
+- kref_init(&card->kref);
+ atomic_set(&card->device_count, 0);
+ card->index = atomic_inc_return(&index);
+ card->driver = driver;
+@@ -429,12 +426,6 @@ fw_card_add(struct fw_card *card,
+ card->link_speed = link_speed;
+ card->guid = guid;
+
+- /*
+- * The subsystem grabs a reference when the card is added and
+- * drops it when the driver calls fw_core_remove_card.
+- */
+- fw_card_get(card);
+-
+ mutex_lock(&card_mutex);
+ config_rom = generate_config_rom(card, &length);
+ list_add_tail(&card->link, &card_list);
+@@ -540,40 +531,9 @@ fw_core_remove_card(struct fw_card *card)
+ cancel_delayed_work_sync(&card->work);
+ fw_flush_transactions(card);
+ del_timer_sync(&card->flush_timer);
+-
+- fw_card_put(card);
+ }
+ EXPORT_SYMBOL(fw_core_remove_card);
+
+-struct fw_card *
+-fw_card_get(struct fw_card *card)
+-{
+- kref_get(&card->kref);
+-
+- return card;
+-}
+-EXPORT_SYMBOL(fw_card_get);
+-
+-static void
+-release_card(struct kref *kref)
+-{
+- struct fw_card *card = container_of(kref, struct fw_card, kref);
+-
+- kfree(card);
+-}
+-
+-/*
+- * An assumption for fw_card_put() is that the card driver allocates
+- * the fw_card struct with kalloc and that it has been shut down
+- * before the last ref is dropped.
+- */
+-void
+-fw_card_put(struct fw_card *card)
+-{
+- kref_put(&card->kref, release_card);
+-}
+-EXPORT_SYMBOL(fw_card_put);
+-
+ int
+ fw_core_initiate_bus_reset(struct fw_card *card, int short_reset)
+ {
+diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c
+index 46bc197..4a54192 100644
+--- a/drivers/firewire/fw-cdev.c
++++ b/drivers/firewire/fw-cdev.c
+@@ -269,21 +269,28 @@ static int ioctl_get_info(struct client *client, void *buffer)
+ {
+ struct fw_cdev_get_info *get_info = buffer;
+ struct fw_cdev_event_bus_reset bus_reset;
++ unsigned long ret = 0;
+
+ client->version = get_info->version;
+ get_info->version = FW_CDEV_VERSION;
+
++ down_read(&fw_device_rwsem);
++
+ if (get_info->rom != 0) {
+ void __user *uptr = u64_to_uptr(get_info->rom);
+ size_t want = get_info->rom_length;
+ size_t have = client->device->config_rom_length * 4;
+
+- if (copy_to_user(uptr, client->device->config_rom,
+- min(want, have)))
+- return -EFAULT;
++ ret = copy_to_user(uptr, client->device->config_rom,
++ min(want, have));
+ }
+ get_info->rom_length = client->device->config_rom_length * 4;
+
++ up_read(&fw_device_rwsem);
++
++ if (ret != 0)
++ return -EFAULT;
++
+ client->bus_reset_closure = get_info->bus_reset_closure;
+ if (get_info->bus_reset != 0) {
+ void __user *uptr = u64_to_uptr(get_info->bus_reset);
+diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c
+index 870125a..d9c8daf 100644
+--- a/drivers/firewire/fw-device.c
++++ b/drivers/firewire/fw-device.c
+@@ -25,8 +25,9 @@
+ #include <linux/device.h>
+ #include <linux/delay.h>
+ #include <linux/idr.h>
++#include <linux/string.h>
+ #include <linux/rwsem.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+ #include <asm/system.h>
+ #include <linux/ctype.h>
+ #include "fw-transaction.h"
+@@ -160,9 +161,9 @@ static void fw_device_release(struct device *dev)
+ * Take the card lock so we don't set this to NULL while a
+ * FW_NODE_UPDATED callback is being handled.
+ */
+- spin_lock_irqsave(&device->card->lock, flags);
++ spin_lock_irqsave(&card->lock, flags);
+ device->node->data = NULL;
+- spin_unlock_irqrestore(&device->card->lock, flags);
++ spin_unlock_irqrestore(&card->lock, flags);
+
+ fw_node_put(device->node);
+ kfree(device->config_rom);
+@@ -195,7 +196,9 @@ show_immediate(struct device *dev, struct device_attribute *dattr, char *buf)
+ container_of(dattr, struct config_rom_attribute, attr);
+ struct fw_csr_iterator ci;
+ u32 *dir;
+- int key, value;
++ int key, value, ret = -ENOENT;
++
++ down_read(&fw_device_rwsem);
+
+ if (is_fw_unit(dev))
+ dir = fw_unit(dev)->directory;
+@@ -204,11 +207,15 @@ show_immediate(struct device *dev, struct device_attribute *dattr, char *buf)
+
+ fw_csr_iterator_init(&ci, dir);
+ while (fw_csr_iterator_next(&ci, &key, &value))
+- if (attr->key == key)
+- return snprintf(buf, buf ? PAGE_SIZE : 0,
+- "0x%06x\n", value);
++ if (attr->key == key) {
++ ret = snprintf(buf, buf ? PAGE_SIZE : 0,
++ "0x%06x\n", value);
++ break;
++ }
++
++ up_read(&fw_device_rwsem);
+
+- return -ENOENT;
++ return ret;
+ }
+
+ #define IMMEDIATE_ATTR(name, key) \
+@@ -221,9 +228,11 @@ show_text_leaf(struct device *dev, struct device_attribute *dattr, char *buf)
+ container_of(dattr, struct config_rom_attribute, attr);
+ struct fw_csr_iterator ci;
+ u32 *dir, *block = NULL, *p, *end;
+- int length, key, value, last_key = 0;
++ int length, key, value, last_key = 0, ret = -ENOENT;
+ char *b;
+
++ down_read(&fw_device_rwsem);
++
+ if (is_fw_unit(dev))
+ dir = fw_unit(dev)->directory;
+ else
+@@ -238,18 +247,20 @@ show_text_leaf(struct device *dev, struct device_attribute *dattr, char *buf)
+ }
+
+ if (block == NULL)
+- return -ENOENT;
++ goto out;
+
+ length = min(block[0] >> 16, 256U);
+ if (length < 3)
+- return -ENOENT;
++ goto out;
+
+ if (block[1] != 0 || block[2] != 0)
+ /* Unknown encoding. */
+- return -ENOENT;
++ goto out;
+
+- if (buf == NULL)
+- return length * 4;
++ if (buf == NULL) {
++ ret = length * 4;
++ goto out;
++ }
+
+ b = buf;
+ end = &block[length + 1];
+@@ -259,8 +270,11 @@ show_text_leaf(struct device *dev, struct device_attribute *dattr, char *buf)
+ /* Strip trailing whitespace and add newline. */
+ while (b--, (isspace(*b) || *b == '\0') && b > buf);
+ strcpy(b + 1, "\n");
++ ret = b + 2 - buf;
++ out:
++ up_read(&fw_device_rwsem);
+
+- return b + 2 - buf;
++ return ret;
+ }
+
+ #define TEXT_LEAF_ATTR(name, key) \
+@@ -337,19 +351,28 @@ static ssize_t
+ config_rom_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+ struct fw_device *device = fw_device(dev);
++ size_t length;
+
+- memcpy(buf, device->config_rom, device->config_rom_length * 4);
++ down_read(&fw_device_rwsem);
++ length = device->config_rom_length * 4;
++ memcpy(buf, device->config_rom, length);
++ up_read(&fw_device_rwsem);
+
+- return device->config_rom_length * 4;
++ return length;
+ }
+
+ static ssize_t
+ guid_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+ struct fw_device *device = fw_device(dev);
++ int ret;
++
++ down_read(&fw_device_rwsem);
++ ret = snprintf(buf, PAGE_SIZE, "0x%08x%08x\n",
++ device->config_rom[3], device->config_rom[4]);
++ up_read(&fw_device_rwsem);
+
+- return snprintf(buf, PAGE_SIZE, "0x%08x%08x\n",
+- device->config_rom[3], device->config_rom[4]);
++ return ret;
+ }
+
+ static struct device_attribute fw_device_attributes[] = {
+@@ -388,7 +411,7 @@ read_rom(struct fw_device *device, int generation, int index, u32 *data)
+
+ init_completion(&callback_data.done);
+
+- offset = 0xfffff0000400ULL + index * 4;
++ offset = (CSR_REGISTER_BASE | CSR_CONFIG_ROM) + index * 4;
+ fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST,
+ device->node_id, generation, device->max_speed,
+ offset, NULL, 4, complete_transaction, &callback_data);
+@@ -400,6 +423,9 @@ read_rom(struct fw_device *device, int generation, int index, u32 *data)
+ return callback_data.rcode;
+ }
+
++#define READ_BIB_ROM_SIZE 256
++#define READ_BIB_STACK_SIZE 16
++
+ /*
+ * Read the bus info block, perform a speed probe, and read all of the rest of
+ * the config ROM. We do all this with a cached bus generation. If the bus
+@@ -409,16 +435,23 @@ read_rom(struct fw_device *device, int generation, int index, u32 *data)
+ */
+ static int read_bus_info_block(struct fw_device *device, int generation)
+ {
+- static u32 rom[256];
+- u32 stack[16], sp, key;
+- int i, end, length;
++ u32 *rom, *stack, *old_rom, *new_rom;
++ u32 sp, key;
++ int i, end, length, ret = -1;
++
++ rom = kmalloc(sizeof(*rom) * READ_BIB_ROM_SIZE +
++ sizeof(*stack) * READ_BIB_STACK_SIZE, GFP_KERNEL);
++ if (rom == NULL)
++ return -ENOMEM;
++
++ stack = &rom[READ_BIB_ROM_SIZE];
+
+ device->max_speed = SCODE_100;
+
+ /* First read the bus info block. */
+ for (i = 0; i < 5; i++) {
+ if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
+- return -1;
++ goto out;
+ /*
+ * As per IEEE1212 7.2, during power-up, devices can
+ * reply with a 0 for the first quadlet of the config
+@@ -428,7 +461,7 @@ static int read_bus_info_block(struct fw_device *device, int generation)
+ * retry mechanism will try again later.
+ */
+ if (i == 0 && rom[i] == 0)
+- return -1;
++ goto out;
+ }
+
+ device->max_speed = device->node->max_speed;
+@@ -478,26 +511,26 @@ static int read_bus_info_block(struct fw_device *device, int generation)
+ */
+ key = stack[--sp];
+ i = key & 0xffffff;
+- if (i >= ARRAY_SIZE(rom))
++ if (i >= READ_BIB_ROM_SIZE)
+ /*
+ * The reference points outside the standard
+ * config rom area, something's fishy.
+ */
+- return -1;
++ goto out;
+
+ /* Read header quadlet for the block to get the length. */
+ if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
+- return -1;
++ goto out;
+ end = i + (rom[i] >> 16) + 1;
+ i++;
+- if (end > ARRAY_SIZE(rom))
++ if (end > READ_BIB_ROM_SIZE)
+ /*
+ * This block extends outside standard config
+ * area (and the array we're reading it
+ * into). That's broken, so ignore this
+ * device.
+ */
+- return -1;
++ goto out;
+
+ /*
+ * Now read in the block. If this is a directory
+@@ -507,9 +540,9 @@ static int read_bus_info_block(struct fw_device *device, int generation)
+ while (i < end) {
+ if (read_rom(device, generation, i, &rom[i]) !=
+ RCODE_COMPLETE)
+- return -1;
++ goto out;
+ if ((key >> 30) == 3 && (rom[i] >> 30) > 1 &&
+- sp < ARRAY_SIZE(stack))
++ sp < READ_BIB_STACK_SIZE)
+ stack[sp++] = i + rom[i];
+ i++;
+ }
+@@ -517,13 +550,23 @@ static int read_bus_info_block(struct fw_device *device, int generation)
+ length = i;
+ }
+
+- device->config_rom = kmalloc(length * 4, GFP_KERNEL);
+- if (device->config_rom == NULL)
+- return -1;
+- memcpy(device->config_rom, rom, length * 4);
++ old_rom = device->config_rom;
++ new_rom = kmemdup(rom, length * 4, GFP_KERNEL);
++ if (new_rom == NULL)
++ goto out;
++
++ down_write(&fw_device_rwsem);
++ device->config_rom = new_rom;
+ device->config_rom_length = length;
++ up_write(&fw_device_rwsem);
+
+- return 0;
++ kfree(old_rom);
++ ret = 0;
++ device->cmc = rom[2] & 1 << 30;
++ out:
++ kfree(rom);
++
++ return ret;
+ }
+
+ static void fw_unit_release(struct device *dev)
+@@ -592,7 +635,14 @@ static int shutdown_unit(struct device *device, void *data)
+ return 0;
+ }
+
+-static DECLARE_RWSEM(idr_rwsem);
++/*
++ * fw_device_rwsem acts as dual purpose mutex:
++ * - serializes accesses to fw_device_idr,
++ * - serializes accesses to fw_device.config_rom/.config_rom_length and
++ * fw_unit.directory, unless those accesses happen at safe occasions
++ */
++DECLARE_RWSEM(fw_device_rwsem);
++
+ static DEFINE_IDR(fw_device_idr);
+ int fw_cdev_major;
+
+@@ -600,11 +650,11 @@ struct fw_device *fw_device_get_by_devt(dev_t devt)
+ {
+ struct fw_device *device;
+
+- down_read(&idr_rwsem);
++ down_read(&fw_device_rwsem);
+ device = idr_find(&fw_device_idr, MINOR(devt));
+ if (device)
+ fw_device_get(device);
+- up_read(&idr_rwsem);
++ up_read(&fw_device_rwsem);
+
+ return device;
+ }
+@@ -619,9 +669,9 @@ static void fw_device_shutdown(struct work_struct *work)
+ device_for_each_child(&device->device, NULL, shutdown_unit);
+ device_unregister(&device->device);
+
+- down_write(&idr_rwsem);
++ down_write(&fw_device_rwsem);
+ idr_remove(&fw_device_idr, minor);
+- up_write(&idr_rwsem);
++ up_write(&fw_device_rwsem);
+ fw_device_put(device);
+ }
+
+@@ -674,10 +724,10 @@ static void fw_device_init(struct work_struct *work)
+ err = -ENOMEM;
+
+ fw_device_get(device);
+- down_write(&idr_rwsem);
++ down_write(&fw_device_rwsem);
+ if (idr_pre_get(&fw_device_idr, GFP_KERNEL))
+ err = idr_get_new(&fw_device_idr, device, &minor);
+- up_write(&idr_rwsem);
++ up_write(&fw_device_rwsem);
+
+ if (err < 0)
+ goto error;
+@@ -711,7 +761,7 @@ static void fw_device_init(struct work_struct *work)
+ if (atomic_cmpxchg(&device->state,
+ FW_DEVICE_INITIALIZING,
+ FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN) {
+- fw_device_shutdown(&device->work.work);
++ fw_device_shutdown(work);
+ } else {
+ if (device->config_rom_retries)
+ fw_notify("created device %s: GUID %08x%08x, S%d00, "
+@@ -725,6 +775,7 @@ static void fw_device_init(struct work_struct *work)
+ device->device.bus_id,
+ device->config_rom[3], device->config_rom[4],
+ 1 << device->max_speed);
++ device->config_rom_retries = 0;
+ }
+
+ /*
+@@ -739,9 +790,9 @@ static void fw_device_init(struct work_struct *work)
+ return;
+
+ error_with_cdev:
+- down_write(&idr_rwsem);
++ down_write(&fw_device_rwsem);
+ idr_remove(&fw_device_idr, minor);
+- up_write(&idr_rwsem);
++ up_write(&fw_device_rwsem);
+ error:
+ fw_device_put(device); /* fw_device_idr's reference */
+
+@@ -771,6 +822,106 @@ static void fw_device_update(struct work_struct *work)
+ device_for_each_child(&device->device, NULL, update_unit);
+ }
+
++enum {
++ REREAD_BIB_ERROR,
++ REREAD_BIB_GONE,
++ REREAD_BIB_UNCHANGED,
++ REREAD_BIB_CHANGED,
++};
++
++/* Reread and compare bus info block and header of root directory */
++static int reread_bus_info_block(struct fw_device *device, int generation)
++{
++ u32 q;
++ int i;
++
++ for (i = 0; i < 6; i++) {
++ if (read_rom(device, generation, i, &q) != RCODE_COMPLETE)
++ return REREAD_BIB_ERROR;
++
++ if (i == 0 && q == 0)
++ return REREAD_BIB_GONE;
++
++ if (i > device->config_rom_length || q != device->config_rom[i])
++ return REREAD_BIB_CHANGED;
++ }
++
++ return REREAD_BIB_UNCHANGED;
++}
++
++static void fw_device_refresh(struct work_struct *work)
++{
++ struct fw_device *device =
++ container_of(work, struct fw_device, work.work);
++ struct fw_card *card = device->card;
++ int node_id = device->node_id;
++
++ switch (reread_bus_info_block(device, device->generation)) {
++ case REREAD_BIB_ERROR:
++ if (device->config_rom_retries < MAX_RETRIES / 2 &&
++ atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
++ device->config_rom_retries++;
++ schedule_delayed_work(&device->work, RETRY_DELAY / 2);
++
++ return;
++ }
++ goto give_up;
++
++ case REREAD_BIB_GONE:
++ goto gone;
++
++ case REREAD_BIB_UNCHANGED:
++ if (atomic_cmpxchg(&device->state,
++ FW_DEVICE_INITIALIZING,
++ FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
++ goto gone;
++
++ fw_device_update(work);
++ device->config_rom_retries = 0;
++ goto out;
++
++ case REREAD_BIB_CHANGED:
++ break;
++ }
++
++ /*
++ * Something changed. We keep things simple and don't investigate
++ * further. We just destroy all previous units and create new ones.
++ */
++ device_for_each_child(&device->device, NULL, shutdown_unit);
++
++ if (read_bus_info_block(device, device->generation) < 0) {
++ if (device->config_rom_retries < MAX_RETRIES &&
++ atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
++ device->config_rom_retries++;
++ schedule_delayed_work(&device->work, RETRY_DELAY);
++
++ return;
++ }
++ goto give_up;
++ }
++
++ create_units(device);
++
++ if (atomic_cmpxchg(&device->state,
++ FW_DEVICE_INITIALIZING,
++ FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
++ goto gone;
++
++ fw_notify("refreshed device %s\n", device->device.bus_id);
++ device->config_rom_retries = 0;
++ goto out;
++
++ give_up:
++ fw_notify("giving up on refresh of device %s\n", device->device.bus_id);
++ gone:
++ atomic_set(&device->state, FW_DEVICE_SHUTDOWN);
++ fw_device_shutdown(work);
++ out:
++ if (node_id == card->root_node->node_id)
++ schedule_delayed_work(&card->work, 0);
++}
++
+ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
+ {
+ struct fw_device *device;
+@@ -780,7 +931,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
+ case FW_NODE_LINK_ON:
+ if (!node->link_on)
+ break;
+-
++ create:
+ device = kzalloc(sizeof(*device), GFP_ATOMIC);
+ if (device == NULL)
+ break;
+@@ -819,6 +970,23 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
+ schedule_delayed_work(&device->work, INITIAL_DELAY);
+ break;
+
++ case FW_NODE_INITIATED_RESET:
++ device = node->data;
++ if (device == NULL)
++ goto create;
++
++ device->node_id = node->node_id;
++ smp_wmb(); /* update node_id before generation */
++ device->generation = card->generation;
++ if (atomic_cmpxchg(&device->state,
++ FW_DEVICE_RUNNING,
++ FW_DEVICE_INITIALIZING) == FW_DEVICE_RUNNING) {
++ PREPARE_DELAYED_WORK(&device->work, fw_device_refresh);
++ schedule_delayed_work(&device->work,
++ node == card->local_node ? 0 : INITIAL_DELAY);
++ }
++ break;
++
+ case FW_NODE_UPDATED:
+ if (!node->link_on || node->data == NULL)
+ break;
+diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h
+index 78ecd39..5f131f5 100644
+--- a/drivers/firewire/fw-device.h
++++ b/drivers/firewire/fw-device.h
+@@ -21,6 +21,7 @@
+
+ #include <linux/fs.h>
+ #include <linux/cdev.h>
++#include <linux/rwsem.h>
+ #include <asm/atomic.h>
+
+ enum fw_device_state {
+@@ -46,6 +47,11 @@ struct fw_attribute_group {
+ * fw_device.node_id is guaranteed to be current too.
+ *
+ * The same applies to fw_device.card->node_id vs. fw_device.generation.
++ *
++ * fw_device.config_rom and fw_device.config_rom_length may be accessed during
++ * the lifetime of any fw_unit belonging to the fw_device, before device_del()
++ * was called on the last fw_unit. Alternatively, they may be accessed while
++ * holding fw_device_rwsem.
+ */
+ struct fw_device {
+ atomic_t state;
+@@ -53,6 +59,7 @@ struct fw_device {
+ int node_id;
+ int generation;
+ unsigned max_speed;
++ bool cmc;
+ struct fw_card *card;
+ struct device device;
+ struct list_head link;
+@@ -64,28 +71,24 @@ struct fw_device {
+ struct fw_attribute_group attribute_group;
+ };
+
+-static inline struct fw_device *
+-fw_device(struct device *dev)
++static inline struct fw_device *fw_device(struct device *dev)
+ {
+ return container_of(dev, struct fw_device, device);
+ }
+
+-static inline int
+-fw_device_is_shutdown(struct fw_device *device)
++static inline int fw_device_is_shutdown(struct fw_device *device)
+ {
+ return atomic_read(&device->state) == FW_DEVICE_SHUTDOWN;
+ }
+
+-static inline struct fw_device *
+-fw_device_get(struct fw_device *device)
++static inline struct fw_device *fw_device_get(struct fw_device *device)
+ {
+ get_device(&device->device);
+
+ return device;
+ }
+
+-static inline void
+-fw_device_put(struct fw_device *device)
++static inline void fw_device_put(struct fw_device *device)
+ {
+ put_device(&device->device);
+ }
+@@ -96,20 +99,35 @@ int fw_device_enable_phys_dma(struct fw_device *device);
+ void fw_device_cdev_update(struct fw_device *device);
+ void fw_device_cdev_remove(struct fw_device *device);
+
++extern struct rw_semaphore fw_device_rwsem;
+ extern int fw_cdev_major;
+
++/*
++ * fw_unit.directory must not be accessed after device_del(&fw_unit.device).
++ */
+ struct fw_unit {
+ struct device device;
+ u32 *directory;
+ struct fw_attribute_group attribute_group;
+ };
+
+-static inline struct fw_unit *
+-fw_unit(struct device *dev)
++static inline struct fw_unit *fw_unit(struct device *dev)
+ {
+ return container_of(dev, struct fw_unit, device);
+ }
+
++static inline struct fw_unit *fw_unit_get(struct fw_unit *unit)
++{
++ get_device(&unit->device);
++
++ return unit;
++}
++
++static inline void fw_unit_put(struct fw_unit *unit)
++{
++ put_device(&unit->device);
++}
++
+ #define CSR_OFFSET 0x40
+ #define CSR_LEAF 0x80
+ #define CSR_DIRECTORY 0xc0
+diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c
+index 2b640e9..bcbe794 100644
+--- a/drivers/firewire/fw-iso.c
++++ b/drivers/firewire/fw-iso.c
+@@ -126,7 +126,6 @@ fw_iso_context_create(struct fw_card *card, int type,
+
+ return ctx;
+ }
+-EXPORT_SYMBOL(fw_iso_context_create);
+
+ void fw_iso_context_destroy(struct fw_iso_context *ctx)
+ {
+@@ -134,14 +133,12 @@ void fw_iso_context_destroy(struct fw_iso_context *ctx)
+
+ card->driver->free_iso_context(ctx);
+ }
+-EXPORT_SYMBOL(fw_iso_context_destroy);
+
+ int
+ fw_iso_context_start(struct fw_iso_context *ctx, int cycle, int sync, int tags)
+ {
+ return ctx->card->driver->start_iso(ctx, cycle, sync, tags);
+ }
+-EXPORT_SYMBOL(fw_iso_context_start);
+
+ int
+ fw_iso_context_queue(struct fw_iso_context *ctx,
+@@ -153,11 +150,9 @@ fw_iso_context_queue(struct fw_iso_context *ctx,
+
+ return card->driver->queue_iso(ctx, packet, buffer, payload);
+ }
+-EXPORT_SYMBOL(fw_iso_context_queue);
+
+ int
+ fw_iso_context_stop(struct fw_iso_context *ctx)
+ {
+ return ctx->card->driver->stop_iso(ctx);
+ }
+-EXPORT_SYMBOL(fw_iso_context_stop);
+diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
+index ca6d51e..4f02c55 100644
+--- a/drivers/firewire/fw-ohci.c
++++ b/drivers/firewire/fw-ohci.c
+@@ -27,6 +27,7 @@
+ #include <linux/kernel.h>
+ #include <linux/mm.h>
+ #include <linux/module.h>
++#include <linux/moduleparam.h>
+ #include <linux/pci.h>
+ #include <linux/spinlock.h>
+
+@@ -177,9 +178,10 @@ struct fw_ohci {
+ struct tasklet_struct bus_reset_tasklet;
+ int node_id;
+ int generation;
+- int request_generation;
++ int request_generation; /* for timestamping incoming requests */
+ u32 bus_seconds;
+ bool old_uninorth;
++ bool bus_reset_packet_quirk;
+
+ /*
+ * Spinlock for accessing fw_ohci data. Never call out of
+@@ -237,6 +239,196 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card)
+
+ static char ohci_driver_name[] = KBUILD_MODNAME;
+
++#ifdef CONFIG_FIREWIRE_OHCI_DEBUG
++
++#define OHCI_PARAM_DEBUG_AT_AR 1
++#define OHCI_PARAM_DEBUG_SELFIDS 2
++#define OHCI_PARAM_DEBUG_IRQS 4
++#define OHCI_PARAM_DEBUG_BUSRESETS 8 /* only effective before chip init */
++
++static int param_debug;
++module_param_named(debug, param_debug, int, 0644);
++MODULE_PARM_DESC(debug, "Verbose logging (default = 0"
++ ", AT/AR events = " __stringify(OHCI_PARAM_DEBUG_AT_AR)
++ ", self-IDs = " __stringify(OHCI_PARAM_DEBUG_SELFIDS)
++ ", IRQs = " __stringify(OHCI_PARAM_DEBUG_IRQS)
++ ", busReset events = " __stringify(OHCI_PARAM_DEBUG_BUSRESETS)
++ ", or a combination, or all = -1)");
++
++static void log_irqs(u32 evt)
++{
++ if (likely(!(param_debug &
++ (OHCI_PARAM_DEBUG_IRQS | OHCI_PARAM_DEBUG_BUSRESETS))))
++ return;
++
++ if (!(param_debug & OHCI_PARAM_DEBUG_IRQS) &&
++ !(evt & OHCI1394_busReset))
++ return;
++
++ printk(KERN_DEBUG KBUILD_MODNAME ": IRQ "
++ "%08x%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
++ evt,
++ evt & OHCI1394_selfIDComplete ? " selfID" : "",
++ evt & OHCI1394_RQPkt ? " AR_req" : "",
++ evt & OHCI1394_RSPkt ? " AR_resp" : "",
++ evt & OHCI1394_reqTxComplete ? " AT_req" : "",
++ evt & OHCI1394_respTxComplete ? " AT_resp" : "",
++ evt & OHCI1394_isochRx ? " IR" : "",
++ evt & OHCI1394_isochTx ? " IT" : "",
++ evt & OHCI1394_postedWriteErr ? " postedWriteErr" : "",
++ evt & OHCI1394_cycleTooLong ? " cycleTooLong" : "",
++ evt & OHCI1394_cycle64Seconds ? " cycle64Seconds" : "",
++ evt & OHCI1394_regAccessFail ? " regAccessFail" : "",
++ evt & OHCI1394_busReset ? " busReset" : "",
++ evt & ~(OHCI1394_selfIDComplete | OHCI1394_RQPkt |
++ OHCI1394_RSPkt | OHCI1394_reqTxComplete |
++ OHCI1394_respTxComplete | OHCI1394_isochRx |
++ OHCI1394_isochTx | OHCI1394_postedWriteErr |
++ OHCI1394_cycleTooLong | OHCI1394_cycle64Seconds |
++ OHCI1394_regAccessFail | OHCI1394_busReset)
++ ? " ?" : "");
++}
++
++static const char *speed[] = {
++ [0] = "S100", [1] = "S200", [2] = "S400", [3] = "beta",
++};
++static const char *power[] = {
++ [0] = "+0W", [1] = "+15W", [2] = "+30W", [3] = "+45W",
++ [4] = "-3W", [5] = " ?W", [6] = "-3..-6W", [7] = "-3..-10W",
++};
++static const char port[] = { '.', '-', 'p', 'c', };
++
++static char _p(u32 *s, int shift)
++{
++ return port[*s >> shift & 3];
++}
++
++static void log_selfids(int node_id, int generation, int self_id_count, u32 *s)
++{
++ if (likely(!(param_debug & OHCI_PARAM_DEBUG_SELFIDS)))
++ return;
++
++ printk(KERN_DEBUG KBUILD_MODNAME ": %d selfIDs, generation %d, "
++ "local node ID %04x\n", self_id_count, generation, node_id);
++
++ for (; self_id_count--; ++s)
++ if ((*s & 1 << 23) == 0)
++ printk(KERN_DEBUG "selfID 0: %08x, phy %d [%c%c%c] "
++ "%s gc=%d %s %s%s%s\n",
++ *s, *s >> 24 & 63, _p(s, 6), _p(s, 4), _p(s, 2),
++ speed[*s >> 14 & 3], *s >> 16 & 63,
++ power[*s >> 8 & 7], *s >> 22 & 1 ? "L" : "",
++ *s >> 11 & 1 ? "c" : "", *s & 2 ? "i" : "");
++ else
++ printk(KERN_DEBUG "selfID n: %08x, phy %d "
++ "[%c%c%c%c%c%c%c%c]\n",
++ *s, *s >> 24 & 63,
++ _p(s, 16), _p(s, 14), _p(s, 12), _p(s, 10),
++ _p(s, 8), _p(s, 6), _p(s, 4), _p(s, 2));
++}
++
++static const char *evts[] = {
++ [0x00] = "evt_no_status", [0x01] = "-reserved-",
++ [0x02] = "evt_long_packet", [0x03] = "evt_missing_ack",
++ [0x04] = "evt_underrun", [0x05] = "evt_overrun",
++ [0x06] = "evt_descriptor_read", [0x07] = "evt_data_read",
++ [0x08] = "evt_data_write", [0x09] = "evt_bus_reset",
++ [0x0a] = "evt_timeout", [0x0b] = "evt_tcode_err",
++ [0x0c] = "-reserved-", [0x0d] = "-reserved-",
++ [0x0e] = "evt_unknown", [0x0f] = "evt_flushed",
++ [0x10] = "-reserved-", [0x11] = "ack_complete",
++ [0x12] = "ack_pending ", [0x13] = "-reserved-",
++ [0x14] = "ack_busy_X", [0x15] = "ack_busy_A",
++ [0x16] = "ack_busy_B", [0x17] = "-reserved-",
++ [0x18] = "-reserved-", [0x19] = "-reserved-",
++ [0x1a] = "-reserved-", [0x1b] = "ack_tardy",
++ [0x1c] = "-reserved-", [0x1d] = "ack_data_error",
++ [0x1e] = "ack_type_error", [0x1f] = "-reserved-",
++ [0x20] = "pending/cancelled",
++};
++static const char *tcodes[] = {
++ [0x0] = "QW req", [0x1] = "BW req",
++ [0x2] = "W resp", [0x3] = "-reserved-",
++ [0x4] = "QR req", [0x5] = "BR req",
++ [0x6] = "QR resp", [0x7] = "BR resp",
++ [0x8] = "cycle start", [0x9] = "Lk req",
++ [0xa] = "async stream packet", [0xb] = "Lk resp",
++ [0xc] = "-reserved-", [0xd] = "-reserved-",
++ [0xe] = "link internal", [0xf] = "-reserved-",
++};
++static const char *phys[] = {
++ [0x0] = "phy config packet", [0x1] = "link-on packet",
++ [0x2] = "self-id packet", [0x3] = "-reserved-",
++};
++
++static void log_ar_at_event(char dir, int speed, u32 *header, int evt)
++{
++ int tcode = header[0] >> 4 & 0xf;
++ char specific[12];
++
++ if (likely(!(param_debug & OHCI_PARAM_DEBUG_AT_AR)))
++ return;
++
++ if (unlikely(evt >= ARRAY_SIZE(evts)))
++ evt = 0x1f;
++
++ if (evt == OHCI1394_evt_bus_reset) {
++ printk(KERN_DEBUG "A%c evt_bus_reset, generation %d\n",
++ dir, (header[2] >> 16) & 0xff);
++ return;
++ }
++
++ if (header[0] == ~header[1]) {
++ printk(KERN_DEBUG "A%c %s, %s, %08x\n",
++ dir, evts[evt], phys[header[0] >> 30 & 0x3],
++ header[0]);
++ return;
++ }
++
++ switch (tcode) {
++ case 0x0: case 0x6: case 0x8:
++ snprintf(specific, sizeof(specific), " = %08x",
++ be32_to_cpu((__force __be32)header[3]));
++ break;
++ case 0x1: case 0x5: case 0x7: case 0x9: case 0xb:
++ snprintf(specific, sizeof(specific), " %x,%x",
++ header[3] >> 16, header[3] & 0xffff);
++ break;
++ default:
++ specific[0] = '\0';
++ }
++
++ switch (tcode) {
++ case 0xe: case 0xa:
++ printk(KERN_DEBUG "A%c %s, %s\n",
++ dir, evts[evt], tcodes[tcode]);
++ break;
++ case 0x0: case 0x1: case 0x4: case 0x5: case 0x9:
++ printk(KERN_DEBUG "A%c spd %x tl %02x, "
++ "%04x -> %04x, %s, "
++ "%s, %04x%08x%s\n",
++ dir, speed, header[0] >> 10 & 0x3f,
++ header[1] >> 16, header[0] >> 16, evts[evt],
++ tcodes[tcode], header[1] & 0xffff, header[2], specific);
++ break;
++ default:
++ printk(KERN_DEBUG "A%c spd %x tl %02x, "
++ "%04x -> %04x, %s, "
++ "%s%s\n",
++ dir, speed, header[0] >> 10 & 0x3f,
++ header[1] >> 16, header[0] >> 16, evts[evt],
++ tcodes[tcode], specific);
++ }
++}
++
++#else
++
++#define log_irqs(evt)
++#define log_selfids(node_id, generation, self_id_count, sid)
++#define log_ar_at_event(dir, speed, header, evt)
++
++#endif /* CONFIG_FIREWIRE_OHCI_DEBUG */
++
+ static inline void reg_write(const struct fw_ohci *ohci, int offset, u32 data)
+ {
+ writel(data, ohci->registers + offset);
+@@ -320,6 +512,7 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
+ struct fw_ohci *ohci = ctx->ohci;
+ struct fw_packet p;
+ u32 status, length, tcode;
++ int evt;
+
+ p.header[0] = cond_le32_to_cpu(buffer[0]);
+ p.header[1] = cond_le32_to_cpu(buffer[1]);
+@@ -362,12 +555,15 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
+ /* FIXME: What to do about evt_* errors? */
+ length = (p.header_length + p.payload_length + 3) / 4;
+ status = cond_le32_to_cpu(buffer[length]);
++ evt = (status >> 16) & 0x1f;
+
+- p.ack = ((status >> 16) & 0x1f) - 16;
++ p.ack = evt - 16;
+ p.speed = (status >> 21) & 0x7;
+ p.timestamp = status & 0xffff;
+ p.generation = ohci->request_generation;
+
++ log_ar_at_event('R', p.speed, p.header, evt);
++
+ /*
+ * The OHCI bus reset handler synthesizes a phy packet with
+ * the new generation number when a bus reset happens (see
+@@ -376,14 +572,19 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
+ * generation. We only need this for requests; for responses
+ * we use the unique tlabel for finding the matching
+ * request.
++ *
++ * Alas some chips sometimes emit bus reset packets with a
++ * wrong generation. We set the correct generation for these
++ * at a slightly incorrect time (in bus_reset_tasklet).
+ */
+-
+- if (p.ack + 16 == 0x09)
+- ohci->request_generation = (p.header[2] >> 16) & 0xff;
+- else if (ctx == &ohci->ar_request_ctx)
++ if (evt == OHCI1394_evt_bus_reset) {
++ if (!ohci->bus_reset_packet_quirk)
++ ohci->request_generation = (p.header[2] >> 16) & 0xff;
++ } else if (ctx == &ohci->ar_request_ctx) {
+ fw_core_handle_request(&ohci->card, &p);
+- else
++ } else {
+ fw_core_handle_response(&ohci->card, &p);
++ }
+
+ return buffer + length + 1;
+ }
+@@ -770,8 +971,19 @@ at_context_queue_packet(struct context *ctx, struct fw_packet *packet)
+ DESCRIPTOR_IRQ_ALWAYS |
+ DESCRIPTOR_BRANCH_ALWAYS);
+
+- /* FIXME: Document how the locking works. */
+- if (ohci->generation != packet->generation) {
++ /*
++ * If the controller and packet generations don't match, we need to
++ * bail out and try again. If IntEvent.busReset is set, the AT context
++ * is halted, so appending to the context and trying to run it is
++ * futile. Most controllers do the right thing and just flush the AT
++ * queue (per section 7.2.3.2 of the OHCI 1.1 specification), but
++ * some controllers (like a JMicron JMB381 PCI-e) misbehave and wind
++ * up stalling out. So we just bail out in software and try again
++ * later, and everyone is happy.
++ * FIXME: Document how the locking works.
++ */
++ if (ohci->generation != packet->generation ||
++ reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) {
+ if (packet->payload_length > 0)
+ dma_unmap_single(ohci->card.device, payload_bus,
+ packet->payload_length, DMA_TO_DEVICE);
+@@ -817,6 +1029,8 @@ static int handle_at_packet(struct context *context,
+ evt = le16_to_cpu(last->transfer_status) & 0x1f;
+ packet->timestamp = le16_to_cpu(last->res_count);
+
++ log_ar_at_event('T', packet->speed, packet->header, evt);
++
+ switch (evt) {
+ case OHCI1394_evt_timeout:
+ /* Async response transmit timed out. */
+@@ -1019,20 +1233,30 @@ static void bus_reset_tasklet(unsigned long data)
+ ohci->node_id = reg & (OHCI1394_NodeID_busNumber |
+ OHCI1394_NodeID_nodeNumber);
+
++ reg = reg_read(ohci, OHCI1394_SelfIDCount);
++ if (reg & OHCI1394_SelfIDCount_selfIDError) {
++ fw_notify("inconsistent self IDs\n");
++ return;
++ }
+ /*
+ * The count in the SelfIDCount register is the number of
+ * bytes in the self ID receive buffer. Since we also receive
+ * the inverted quadlets and a header quadlet, we shift one
+ * bit extra to get the actual number of self IDs.
+ */
+-
+- self_id_count = (reg_read(ohci, OHCI1394_SelfIDCount) >> 3) & 0x3ff;
++ self_id_count = (reg >> 3) & 0x3ff;
++ if (self_id_count == 0) {
++ fw_notify("inconsistent self IDs\n");
++ return;
++ }
+ generation = (cond_le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff;
+ rmb();
+
+ for (i = 1, j = 0; j < self_id_count; i += 2, j++) {
+- if (ohci->self_id_cpu[i] != ~ohci->self_id_cpu[i + 1])
+- fw_error("inconsistent self IDs\n");
++ if (ohci->self_id_cpu[i] != ~ohci->self_id_cpu[i + 1]) {
++ fw_notify("inconsistent self IDs\n");
++ return;
++ }
+ ohci->self_id_buffer[j] =
+ cond_le32_to_cpu(ohci->self_id_cpu[i]);
+ }
+@@ -1067,6 +1291,9 @@ static void bus_reset_tasklet(unsigned long data)
+ context_stop(&ohci->at_response_ctx);
+ reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
+
++ if (ohci->bus_reset_packet_quirk)
++ ohci->request_generation = generation;
++
+ /*
+ * This next bit is unrelated to the AT context stuff but we
+ * have to do it under the spinlock also. If a new config rom
+@@ -1097,12 +1324,20 @@ static void bus_reset_tasklet(unsigned long data)
+ reg_write(ohci, OHCI1394_ConfigROMhdr, ohci->next_header);
+ }
+
++#ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA
++ reg_write(ohci, OHCI1394_PhyReqFilterHiSet, ~0);
++ reg_write(ohci, OHCI1394_PhyReqFilterLoSet, ~0);
++#endif
++
+ spin_unlock_irqrestore(&ohci->lock, flags);
+
+ if (free_rom)
+ dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+ free_rom, free_rom_bus);
+
++ log_selfids(ohci->node_id, generation,
++ self_id_count, ohci->self_id_buffer);
++
+ fw_core_handle_bus_reset(&ohci->card, ohci->node_id, generation,
+ self_id_count, ohci->self_id_buffer);
+ }
+@@ -1118,7 +1353,9 @@ static irqreturn_t irq_handler(int irq, void *data)
+ if (!event || !~event)
+ return IRQ_NONE;
+
+- reg_write(ohci, OHCI1394_IntEventClear, event);
++ /* busReset must not be cleared yet, see OHCI 1.1 clause 7.2.3.2 */
++ reg_write(ohci, OHCI1394_IntEventClear, event & ~OHCI1394_busReset);
++ log_irqs(event);
+
+ if (event & OHCI1394_selfIDComplete)
+ tasklet_schedule(&ohci->bus_reset_tasklet);
+@@ -1153,6 +1390,10 @@ static irqreturn_t irq_handler(int irq, void *data)
+ iso_event &= ~(1 << i);
+ }
+
++ if (unlikely(event & OHCI1394_regAccessFail))
++ fw_error("Register access failure - "
++ "please notify linux1394-devel at lists.sf.net\n");
++
+ if (unlikely(event & OHCI1394_postedWriteErr))
+ fw_error("PCI posted write error\n");
+
+@@ -1192,6 +1433,8 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
+ {
+ struct fw_ohci *ohci = fw_ohci(card);
+ struct pci_dev *dev = to_pci_dev(card->device);
++ u32 lps;
++ int i;
+
+ if (software_reset(ohci)) {
+ fw_error("Failed to reset ohci card.\n");
+@@ -1203,13 +1446,24 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
+ * most of the registers. In fact, on some cards (ALI M5251),
+ * accessing registers in the SClk domain without LPS enabled
+ * will lock up the machine. Wait 50msec to make sure we have
+- * full link enabled.
++ * full link enabled. However, with some cards (well, at least
++ * a JMicron PCIe card), we have to try again sometimes.
+ */
+ reg_write(ohci, OHCI1394_HCControlSet,
+ OHCI1394_HCControl_LPS |
+ OHCI1394_HCControl_postedWriteEnable);
+ flush_writes(ohci);
+- msleep(50);
++
++ for (lps = 0, i = 0; !lps && i < 3; i++) {
++ msleep(50);
++ lps = reg_read(ohci, OHCI1394_HCControlSet) &
++ OHCI1394_HCControl_LPS;
++ }
++
++ if (!lps) {
++ fw_error("Failed to set Link Power Status\n");
++ return -EIO;
++ }
+
+ reg_write(ohci, OHCI1394_HCControlClear,
+ OHCI1394_HCControl_noByteSwapData);
+@@ -1237,7 +1491,10 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
+ OHCI1394_reqTxComplete | OHCI1394_respTxComplete |
+ OHCI1394_isochRx | OHCI1394_isochTx |
+ OHCI1394_postedWriteErr | OHCI1394_cycleTooLong |
+- OHCI1394_cycle64Seconds | OHCI1394_masterIntEnable);
++ OHCI1394_cycle64Seconds | OHCI1394_regAccessFail |
++ OHCI1394_masterIntEnable);
++ if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS)
++ reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset);
+
+ /* Activate link_on bit and contender bit in our self ID packets.*/
+ if (ohci_update_phy_reg(card, 4, 0,
+@@ -1421,6 +1678,7 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet)
+ if (packet->ack != 0)
+ goto out;
+
++ log_ar_at_event('T', packet->speed, packet->header, 0x20);
+ driver_data->packet = NULL;
+ packet->ack = RCODE_CANCELLED;
+ packet->callback(packet, &ohci->card, packet->ack);
+@@ -1435,6 +1693,9 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet)
+ static int
+ ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation)
+ {
++#ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA
++ return 0;
++#else
+ struct fw_ohci *ohci = fw_ohci(card);
+ unsigned long flags;
+ int n, retval = 0;
+@@ -1466,6 +1727,7 @@ ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation)
+ out:
+ spin_unlock_irqrestore(&ohci->lock, flags);
+ return retval;
++#endif /* CONFIG_FIREWIRE_OHCI_REMOTE_DMA */
+ }
+
+ static u64
+@@ -2045,17 +2307,9 @@ static const struct fw_card_driver ohci_driver = {
+ .stop_iso = ohci_stop_iso,
+ };
+
+-static int __devinit
+-pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+-{
+- struct fw_ohci *ohci;
+- u32 bus_options, max_receive, link_speed;
+- u64 guid;
+- int err;
+- size_t size;
+-
+ #ifdef CONFIG_PPC_PMAC
+- /* Necessary on some machines if fw-ohci was loaded/ unloaded before */
++static void ohci_pmac_on(struct pci_dev *dev)
++{
+ if (machine_is(powermac)) {
+ struct device_node *ofn = pci_device_to_OF_node(dev);
+
+@@ -2064,8 +2318,33 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+ pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
+ }
+ }
++}
++
++static void ohci_pmac_off(struct pci_dev *dev)
++{
++ if (machine_is(powermac)) {
++ struct device_node *ofn = pci_device_to_OF_node(dev);
++
++ if (ofn) {
++ pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
++ pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0);
++ }
++ }
++}
++#else
++#define ohci_pmac_on(dev)
++#define ohci_pmac_off(dev)
+ #endif /* CONFIG_PPC_PMAC */
+
++static int __devinit
++pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
++{
++ struct fw_ohci *ohci;
++ u32 bus_options, max_receive, link_speed;
++ u64 guid;
++ int err;
++ size_t size;
++
+ ohci = kzalloc(sizeof(*ohci), GFP_KERNEL);
+ if (ohci == NULL) {
+ fw_error("Could not malloc fw_ohci data.\n");
+@@ -2074,10 +2353,12 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+
+ fw_card_initialize(&ohci->card, &ohci_driver, &dev->dev);
+
++ ohci_pmac_on(dev);
++
+ err = pci_enable_device(dev);
+ if (err) {
+ fw_error("Failed to enable OHCI hardware.\n");
+- goto fail_put_card;
++ goto fail_free;
+ }
+
+ pci_set_master(dev);
+@@ -2088,6 +2369,8 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+ ohci->old_uninorth = dev->vendor == PCI_VENDOR_ID_APPLE &&
+ dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW;
+ #endif
++ ohci->bus_reset_packet_quirk = dev->vendor == PCI_VENDOR_ID_TI;
++
+ spin_lock_init(&ohci->lock);
+
+ tasklet_init(&ohci->bus_reset_tasklet,
+@@ -2173,8 +2456,9 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+ pci_release_region(dev, 0);
+ fail_disable:
+ pci_disable_device(dev);
+- fail_put_card:
+- fw_card_put(&ohci->card);
++ fail_free:
++ kfree(&ohci->card);
++ ohci_pmac_off(dev);
+
+ return err;
+ }
+@@ -2202,72 +2486,42 @@ static void pci_remove(struct pci_dev *dev)
+ pci_iounmap(dev, ohci->registers);
+ pci_release_region(dev, 0);
+ pci_disable_device(dev);
+- fw_card_put(&ohci->card);
+-
+-#ifdef CONFIG_PPC_PMAC
+- /* On UniNorth, power down the cable and turn off the chip clock
+- * to save power on laptops */
+- if (machine_is(powermac)) {
+- struct device_node *ofn = pci_device_to_OF_node(dev);
+-
+- if (ofn) {
+- pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
+- pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0);
+- }
+- }
+-#endif /* CONFIG_PPC_PMAC */
++ kfree(&ohci->card);
++ ohci_pmac_off(dev);
+
+ fw_notify("Removed fw-ohci device.\n");
+ }
+
+ #ifdef CONFIG_PM
+-static int pci_suspend(struct pci_dev *pdev, pm_message_t state)
++static int pci_suspend(struct pci_dev *dev, pm_message_t state)
+ {
+- struct fw_ohci *ohci = pci_get_drvdata(pdev);
++ struct fw_ohci *ohci = pci_get_drvdata(dev);
+ int err;
+
+ software_reset(ohci);
+- free_irq(pdev->irq, ohci);
+- err = pci_save_state(pdev);
++ free_irq(dev->irq, ohci);
++ err = pci_save_state(dev);
+ if (err) {
+ fw_error("pci_save_state failed\n");
+ return err;
+ }
+- err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
++ err = pci_set_power_state(dev, pci_choose_state(dev, state));
+ if (err)
+ fw_error("pci_set_power_state failed with %d\n", err);
+-
+-/* PowerMac suspend code comes last */
+-#ifdef CONFIG_PPC_PMAC
+- if (machine_is(powermac)) {
+- struct device_node *ofn = pci_device_to_OF_node(pdev);
+-
+- if (ofn)
+- pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
+- }
+-#endif /* CONFIG_PPC_PMAC */
++ ohci_pmac_off(dev);
+
+ return 0;
+ }
+
+-static int pci_resume(struct pci_dev *pdev)
++static int pci_resume(struct pci_dev *dev)
+ {
+- struct fw_ohci *ohci = pci_get_drvdata(pdev);
++ struct fw_ohci *ohci = pci_get_drvdata(dev);
+ int err;
+
+-/* PowerMac resume code comes first */
+-#ifdef CONFIG_PPC_PMAC
+- if (machine_is(powermac)) {
+- struct device_node *ofn = pci_device_to_OF_node(pdev);
+-
+- if (ofn)
+- pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
+- }
+-#endif /* CONFIG_PPC_PMAC */
+-
+- pci_set_power_state(pdev, PCI_D0);
+- pci_restore_state(pdev);
+- err = pci_enable_device(pdev);
++ ohci_pmac_on(dev);
++ pci_set_power_state(dev, PCI_D0);
++ pci_restore_state(dev);
++ err = pci_enable_device(dev);
+ if (err) {
+ fw_error("pci_enable_device failed\n");
+ return err;
+diff --git a/drivers/firewire/fw-ohci.h b/drivers/firewire/fw-ohci.h
+index dec4f04..a2fbb62 100644
+--- a/drivers/firewire/fw-ohci.h
++++ b/drivers/firewire/fw-ohci.h
+@@ -30,6 +30,7 @@
+ #define OHCI1394_HCControl_softReset 0x00010000
+ #define OHCI1394_SelfIDBuffer 0x064
+ #define OHCI1394_SelfIDCount 0x068
++#define OHCI1394_SelfIDCount_selfIDError 0x80000000
+ #define OHCI1394_IRMultiChanMaskHiSet 0x070
+ #define OHCI1394_IRMultiChanMaskHiClear 0x074
+ #define OHCI1394_IRMultiChanMaskLoSet 0x078
+@@ -124,6 +125,7 @@
+ #define OHCI1394_lockRespErr 0x00000200
+ #define OHCI1394_selfIDComplete 0x00010000
+ #define OHCI1394_busReset 0x00020000
++#define OHCI1394_regAccessFail 0x00040000
+ #define OHCI1394_phy 0x00080000
+ #define OHCI1394_cycleSynch 0x00100000
+ #define OHCI1394_cycle64Seconds 0x00200000
+diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
+index 62b4e47..2a99937 100644
+--- a/drivers/firewire/fw-sbp2.c
++++ b/drivers/firewire/fw-sbp2.c
+@@ -153,6 +153,7 @@ struct sbp2_target {
+ struct list_head lu_list;
+
+ u64 management_agent_address;
++ u64 guid;
+ int directory_id;
+ int node_id;
+ int address_high;
+@@ -173,10 +174,8 @@ struct sbp2_target {
+ #define SBP2_ORB_TIMEOUT 2000U /* Timeout in ms */
+ #define SBP2_ORB_NULL 0x80000000
+ #define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000
+-#define SBP2_RETRY_LIMIT 0xf /* 15 retries */
+-
+-#define SBP2_DIRECTION_TO_MEDIA 0x0
+-#define SBP2_DIRECTION_FROM_MEDIA 0x1
++#define SBP2_RETRY_LIMIT 0xf /* 15 retries */
++#define SBP2_CYCLE_LIMIT (0xc8 << 12) /* 200 125us cycles */
+
+ /* Unit directory keys */
+ #define SBP2_CSR_UNIT_CHARACTERISTICS 0x3a
+@@ -224,8 +223,8 @@ struct sbp2_status {
+ };
+
+ struct sbp2_pointer {
+- u32 high;
+- u32 low;
++ __be32 high;
++ __be32 low;
+ };
+
+ struct sbp2_orb {
+@@ -253,8 +252,8 @@ struct sbp2_management_orb {
+ struct {
+ struct sbp2_pointer password;
+ struct sbp2_pointer response;
+- u32 misc;
+- u32 length;
++ __be32 misc;
++ __be32 length;
+ struct sbp2_pointer status_fifo;
+ } request;
+ __be32 response[4];
+@@ -263,20 +262,17 @@ struct sbp2_management_orb {
+ struct sbp2_status status;
+ };
+
+-#define LOGIN_RESPONSE_GET_LOGIN_ID(v) ((v).misc & 0xffff)
+-#define LOGIN_RESPONSE_GET_LENGTH(v) (((v).misc >> 16) & 0xffff)
+-
+ struct sbp2_login_response {
+- u32 misc;
++ __be32 misc;
+ struct sbp2_pointer command_block_agent;
+- u32 reconnect_hold;
++ __be32 reconnect_hold;
+ };
+ #define COMMAND_ORB_DATA_SIZE(v) ((v))
+ #define COMMAND_ORB_PAGE_SIZE(v) ((v) << 16)
+ #define COMMAND_ORB_PAGE_TABLE_PRESENT ((1) << 19)
+ #define COMMAND_ORB_MAX_PAYLOAD(v) ((v) << 20)
+ #define COMMAND_ORB_SPEED(v) ((v) << 24)
+-#define COMMAND_ORB_DIRECTION(v) ((v) << 27)
++#define COMMAND_ORB_DIRECTION ((1) << 27)
+ #define COMMAND_ORB_REQUEST_FORMAT(v) ((v) << 29)
+ #define COMMAND_ORB_NOTIFY ((1) << 31)
+
+@@ -285,7 +281,7 @@ struct sbp2_command_orb {
+ struct {
+ struct sbp2_pointer next;
+ struct sbp2_pointer data_descriptor;
+- u32 misc;
++ __be32 misc;
+ u8 command_block[12];
+ } request;
+ struct scsi_cmnd *cmd;
+@@ -459,8 +455,7 @@ sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu,
+ unsigned long flags;
+
+ orb->pointer.high = 0;
+- orb->pointer.low = orb->request_bus;
+- fw_memcpy_to_be32(&orb->pointer, &orb->pointer, sizeof(orb->pointer));
++ orb->pointer.low = cpu_to_be32(orb->request_bus);
+
+ spin_lock_irqsave(&device->card->lock, flags);
+ list_add_tail(&orb->link, &lu->orb_list);
+@@ -536,31 +531,31 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
+ if (dma_mapping_error(orb->response_bus))
+ goto fail_mapping_response;
+
+- orb->request.response.high = 0;
+- orb->request.response.low = orb->response_bus;
++ orb->request.response.high = 0;
++ orb->request.response.low = cpu_to_be32(orb->response_bus);
+
+- orb->request.misc =
++ orb->request.misc = cpu_to_be32(
+ MANAGEMENT_ORB_NOTIFY |
+ MANAGEMENT_ORB_FUNCTION(function) |
+- MANAGEMENT_ORB_LUN(lun_or_login_id);
+- orb->request.length =
+- MANAGEMENT_ORB_RESPONSE_LENGTH(sizeof(orb->response));
++ MANAGEMENT_ORB_LUN(lun_or_login_id));
++ orb->request.length = cpu_to_be32(
++ MANAGEMENT_ORB_RESPONSE_LENGTH(sizeof(orb->response)));
+
+- orb->request.status_fifo.high = lu->address_handler.offset >> 32;
+- orb->request.status_fifo.low = lu->address_handler.offset;
++ orb->request.status_fifo.high =
++ cpu_to_be32(lu->address_handler.offset >> 32);
++ orb->request.status_fifo.low =
++ cpu_to_be32(lu->address_handler.offset);
+
+ if (function == SBP2_LOGIN_REQUEST) {
+ /* Ask for 2^2 == 4 seconds reconnect grace period */
+- orb->request.misc |=
++ orb->request.misc |= cpu_to_be32(
+ MANAGEMENT_ORB_RECONNECT(2) |
+- MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login);
++ MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login));
+ timeout = lu->tgt->mgt_orb_timeout;
+ } else {
+ timeout = SBP2_ORB_TIMEOUT;
+ }
+
+- fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request));
+-
+ init_completion(&orb->done);
+ orb->base.callback = complete_management_orb;
+
+@@ -605,8 +600,7 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
+ sizeof(orb->response), DMA_FROM_DEVICE);
+ fail_mapping_response:
+ if (response)
+- fw_memcpy_from_be32(response,
+- orb->response, sizeof(orb->response));
++ memcpy(response, orb->response, sizeof(orb->response));
+ kref_put(&orb->base.kref, free_orb);
+
+ return retval;
+@@ -701,10 +695,8 @@ static void sbp2_conditionally_block(struct sbp2_logical_unit *lu)
+ if (!tgt->dont_block && !lu->blocked &&
+ lu->generation != card->generation) {
+ lu->blocked = true;
+- if (++tgt->blocked == 1) {
++ if (++tgt->blocked == 1)
+ scsi_block_requests(shost);
+- fw_notify("blocked %s\n", lu->tgt->bus_id);
+- }
+ }
+ spin_unlock_irqrestore(&card->lock, flags);
+ }
+@@ -731,10 +723,8 @@ static void sbp2_conditionally_unblock(struct sbp2_logical_unit *lu)
+ }
+ spin_unlock_irqrestore(&card->lock, flags);
+
+- if (unblock) {
++ if (unblock)
+ scsi_unblock_requests(shost);
+- fw_notify("unblocked %s\n", lu->tgt->bus_id);
+- }
+ }
+
+ /*
+@@ -796,7 +786,7 @@ static void sbp2_release_target(struct kref *kref)
+ scsi_remove_host(shost);
+ fw_notify("released %s\n", tgt->bus_id);
+
+- put_device(&tgt->unit->device);
++ fw_unit_put(tgt->unit);
+ scsi_host_put(shost);
+ fw_device_put(device);
+ }
+@@ -825,6 +815,22 @@ complete_set_busy_timeout(struct fw_card *card, int rcode,
+ complete(done);
+ }
+
++/*
++ * Write retransmit retry values into the BUSY_TIMEOUT register.
++ * - The single-phase retry protocol is supported by all SBP-2 devices, but the
++ * default retry_limit value is 0 (i.e. never retry transmission). We write a
++ * saner value after logging into the device.
++ * - The dual-phase retry protocol is optional to implement, and if not
++ * supported, writes to the dual-phase portion of the register will be
++ * ignored. We try to write the original 1394-1995 default here.
++ * - In the case of devices that are also SBP-3-compliant, all writes are
++ * ignored, as the register is read-only, but contains single-phase retry of
++ * 15, which is what we're trying to set for all SBP-2 device anyway, so this
++ * write attempt is safe and yields more consistent behavior for all devices.
++ *
++ * See section 8.3.2.3.5 of the 1394-1995 spec, section 6.2 of the SBP-2 spec,
++ * and section 6.4 of the SBP-3 spec for further details.
++ */
+ static void sbp2_set_busy_timeout(struct sbp2_logical_unit *lu)
+ {
+ struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
+@@ -832,8 +838,7 @@ static void sbp2_set_busy_timeout(struct sbp2_logical_unit *lu)
+ struct fw_transaction t;
+ static __be32 busy_timeout;
+
+- /* FIXME: we should try to set dual-phase cycle_limit too */
+- busy_timeout = cpu_to_be32(SBP2_RETRY_LIMIT);
++ busy_timeout = cpu_to_be32(SBP2_CYCLE_LIMIT | SBP2_RETRY_LIMIT);
+
+ fw_send_request(device->card, &t, TCODE_WRITE_QUADLET_REQUEST,
+ lu->tgt->node_id, lu->generation, device->max_speed,
+@@ -885,11 +890,10 @@ static void sbp2_login(struct work_struct *work)
+ tgt->address_high = local_node_id << 16;
+ sbp2_set_generation(lu, generation);
+
+- /* Get command block agent offset and login id. */
+ lu->command_block_agent_address =
+- ((u64) (response.command_block_agent.high & 0xffff) << 32) |
+- response.command_block_agent.low;
+- lu->login_id = LOGIN_RESPONSE_GET_LOGIN_ID(response);
++ ((u64)(be32_to_cpu(response.command_block_agent.high) & 0xffff)
++ << 32) | be32_to_cpu(response.command_block_agent.low);
++ lu->login_id = be32_to_cpu(response.misc) & 0xffff;
+
+ fw_notify("%s: logged in to LUN %04x (%d retries)\n",
+ tgt->bus_id, lu->lun, lu->retries);
+@@ -1111,6 +1115,7 @@ static int sbp2_probe(struct device *dev)
+ kref_init(&tgt->kref);
+ INIT_LIST_HEAD(&tgt->lu_list);
+ tgt->bus_id = unit->device.bus_id;
++ tgt->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4];
+
+ if (fw_device_enable_phys_dma(device) < 0)
+ goto fail_shost_put;
+@@ -1119,6 +1124,7 @@ static int sbp2_probe(struct device *dev)
+ goto fail_shost_put;
+
+ fw_device_get(device);
++ fw_unit_get(unit);
+
+ /* Initialize to values that won't match anything in our table. */
+ firmware_revision = 0xff000000;
+@@ -1134,8 +1140,6 @@ static int sbp2_probe(struct device *dev)
+
+ sbp2_init_workarounds(tgt, model, firmware_revision);
+
+- get_device(&unit->device);
+-
+ /* Do the login in a workqueue so we can easily reschedule retries. */
+ list_for_each_entry(lu, &tgt->lu_list, link)
+ sbp2_queue_work(lu, 0);
+@@ -1367,9 +1371,12 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
+ * tables.
+ */
+ if (count == 1 && sg_dma_len(sg) < SBP2_MAX_SG_ELEMENT_LENGTH) {
+- orb->request.data_descriptor.high = lu->tgt->address_high;
+- orb->request.data_descriptor.low = sg_dma_address(sg);
+- orb->request.misc |= COMMAND_ORB_DATA_SIZE(sg_dma_len(sg));
++ orb->request.data_descriptor.high =
++ cpu_to_be32(lu->tgt->address_high);
++ orb->request.data_descriptor.low =
++ cpu_to_be32(sg_dma_address(sg));
++ orb->request.misc |=
++ cpu_to_be32(COMMAND_ORB_DATA_SIZE(sg_dma_len(sg)));
+ return 0;
+ }
+
+@@ -1390,16 +1397,14 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
+ goto fail_page_table;
+ }
+ l = min(sg_len, SBP2_MAX_SG_ELEMENT_LENGTH);
+- orb->page_table[j].low = sg_addr;
+- orb->page_table[j].high = (l << 16);
++ orb->page_table[j].low = cpu_to_be32(sg_addr);
++ orb->page_table[j].high = cpu_to_be32(l << 16);
+ sg_addr += l;
+ sg_len -= l;
+ j++;
+ }
+ }
+
+- fw_memcpy_to_be32(orb->page_table, orb->page_table,
+- sizeof(orb->page_table[0]) * j);
+ orb->page_table_bus =
+ dma_map_single(device->card->device, orb->page_table,
+ sizeof(orb->page_table), DMA_TO_DEVICE);
+@@ -1413,11 +1418,10 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
+ * initiator (i.e. us), but data_descriptor can refer to data
+ * on other nodes so we need to put our ID in descriptor.high.
+ */
+- orb->request.data_descriptor.high = lu->tgt->address_high;
+- orb->request.data_descriptor.low = orb->page_table_bus;
+- orb->request.misc |=
+- COMMAND_ORB_PAGE_TABLE_PRESENT |
+- COMMAND_ORB_DATA_SIZE(j);
++ orb->request.data_descriptor.high = cpu_to_be32(lu->tgt->address_high);
++ orb->request.data_descriptor.low = cpu_to_be32(orb->page_table_bus);
++ orb->request.misc |= cpu_to_be32(COMMAND_ORB_PAGE_TABLE_PRESENT |
++ COMMAND_ORB_DATA_SIZE(j));
+
+ return 0;
+
+@@ -1463,8 +1467,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
+ orb->done = done;
+ orb->cmd = cmd;
+
+- orb->request.next.high = SBP2_ORB_NULL;
+- orb->request.next.low = 0x0;
++ orb->request.next.high = cpu_to_be32(SBP2_ORB_NULL);
+ /*
+ * At speed 100 we can do 512 bytes per packet, at speed 200,
+ * 1024 bytes per packet etc. The SBP-2 max_payload field
+@@ -1473,25 +1476,17 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
+ */
+ max_payload = min(device->max_speed + 7,
+ device->card->max_receive - 1);
+- orb->request.misc =
++ orb->request.misc = cpu_to_be32(
+ COMMAND_ORB_MAX_PAYLOAD(max_payload) |
+ COMMAND_ORB_SPEED(device->max_speed) |
+- COMMAND_ORB_NOTIFY;
++ COMMAND_ORB_NOTIFY);
+
+ if (cmd->sc_data_direction == DMA_FROM_DEVICE)
+- orb->request.misc |=
+- COMMAND_ORB_DIRECTION(SBP2_DIRECTION_FROM_MEDIA);
+- else if (cmd->sc_data_direction == DMA_TO_DEVICE)
+- orb->request.misc |=
+- COMMAND_ORB_DIRECTION(SBP2_DIRECTION_TO_MEDIA);
++ orb->request.misc |= cpu_to_be32(COMMAND_ORB_DIRECTION);
+
+ if (scsi_sg_count(cmd) && sbp2_map_scatterlist(orb, device, lu) < 0)
+ goto out;
+
+- fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request));
+-
+- memset(orb->request.command_block,
+- 0, sizeof(orb->request.command_block));
+ memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
+
+ orb->base.callback = complete_command_orb;
+@@ -1519,11 +1514,8 @@ static int sbp2_scsi_slave_alloc(struct scsi_device *sdev)
+
+ sdev->allow_restart = 1;
+
+- /*
+- * Update the dma alignment (minimum alignment requirements for
+- * start and end of DMA transfers) to be a sector
+- */
+- blk_queue_update_dma_alignment(sdev->request_queue, 511);
++ /* SBP-2 requires quadlet alignment of the data buffers. */
++ blk_queue_update_dma_alignment(sdev->request_queue, 4 - 1);
+
+ if (lu->tgt->workarounds & SBP2_WORKAROUND_INQUIRY_36)
+ sdev->inquiry_len = 36;
+@@ -1581,16 +1573,14 @@ sbp2_sysfs_ieee1394_id_show(struct device *dev, struct device_attribute *attr,
+ {
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct sbp2_logical_unit *lu;
+- struct fw_device *device;
+
+ if (!sdev)
+ return 0;
+
+ lu = sdev->hostdata;
+- device = fw_device(lu->tgt->unit->device.parent);
+
+- return sprintf(buf, "%08x%08x:%06x:%04x\n",
+- device->config_rom[3], device->config_rom[4],
++ return sprintf(buf, "%016llx:%06x:%04x\n",
++ (unsigned long long)lu->tgt->guid,
+ lu->tgt->directory_id, lu->lun);
+ }
+
+diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c
+index d2c7a3d..213b0ff 100644
+--- a/drivers/firewire/fw-topology.c
++++ b/drivers/firewire/fw-topology.c
+@@ -108,6 +108,7 @@ static struct fw_node *fw_node_create(u32 sid, int port_count, int color)
+ node->node_id = LOCAL_BUS | SELF_ID_PHY_ID(sid);
+ node->link_on = SELF_ID_LINK_ON(sid);
+ node->phy_speed = SELF_ID_PHY_SPEED(sid);
++ node->initiated_reset = SELF_ID_PHY_INITIATOR(sid);
+ node->port_count = port_count;
+
+ atomic_set(&node->ref_count, 1);
+@@ -289,12 +290,11 @@ static struct fw_node *build_tree(struct fw_card *card,
+ beta_repeaters_present = true;
+
+ /*
+- * If all PHYs does not report the same gap count
+- * setting, we fall back to 63 which will force a gap
+- * count reconfiguration and a reset.
++ * If PHYs report different gap counts, set an invalid count
++ * which will force a gap count reconfiguration and a reset.
+ */
+ if (SELF_ID_GAP_COUNT(q) != gap_count)
+- gap_count = 63;
++ gap_count = 0;
+
+ update_hop_count(node);
+
+@@ -431,6 +431,8 @@ update_tree(struct fw_card *card, struct fw_node *root)
+ event = FW_NODE_LINK_OFF;
+ else if (!node0->link_on && node1->link_on)
+ event = FW_NODE_LINK_ON;
++ else if (node1->initiated_reset && node1->link_on)
++ event = FW_NODE_INITIATED_RESET;
+ else
+ event = FW_NODE_UPDATED;
+
+diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h
+index cedc1ec..addb9f8 100644
+--- a/drivers/firewire/fw-topology.h
++++ b/drivers/firewire/fw-topology.h
+@@ -20,11 +20,12 @@
+ #define __fw_topology_h
+
+ enum {
+- FW_NODE_CREATED = 0x00,
+- FW_NODE_UPDATED = 0x01,
+- FW_NODE_DESTROYED = 0x02,
+- FW_NODE_LINK_ON = 0x03,
+- FW_NODE_LINK_OFF = 0x04,
++ FW_NODE_CREATED,
++ FW_NODE_UPDATED,
++ FW_NODE_DESTROYED,
++ FW_NODE_LINK_ON,
++ FW_NODE_LINK_OFF,
++ FW_NODE_INITIATED_RESET,
+ };
+
+ struct fw_node {
+diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c
+index e6f1bda..ccf0e4c 100644
+--- a/drivers/firewire/fw-transaction.c
++++ b/drivers/firewire/fw-transaction.c
+@@ -18,6 +18,7 @@
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
++#include <linux/completion.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+@@ -28,7 +29,6 @@
+ #include <linux/list.h>
+ #include <linux/kthread.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+
+ #include "fw-transaction.h"
+ #include "fw-topology.h"
+@@ -294,42 +294,40 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t,
+ }
+ EXPORT_SYMBOL(fw_send_request);
+
++struct fw_phy_packet {
++ struct fw_packet packet;
++ struct completion done;
++};
++
+ static void
+ transmit_phy_packet_callback(struct fw_packet *packet,
+ struct fw_card *card, int status)
+ {
+- kfree(packet);
+-}
+-
+-static void send_phy_packet(struct fw_card *card, u32 data, int generation)
+-{
+- struct fw_packet *packet;
+-
+- packet = kzalloc(sizeof(*packet), GFP_ATOMIC);
+- if (packet == NULL)
+- return;
+-
+- packet->header[0] = data;
+- packet->header[1] = ~data;
+- packet->header_length = 8;
+- packet->payload_length = 0;
+- packet->speed = SCODE_100;
+- packet->generation = generation;
+- packet->callback = transmit_phy_packet_callback;
++ struct fw_phy_packet *p =
++ container_of(packet, struct fw_phy_packet, packet);
+
+- card->driver->send_request(card, packet);
++ complete(&p->done);
+ }
+
+ void fw_send_phy_config(struct fw_card *card,
+ int node_id, int generation, int gap_count)
+ {
+- u32 q;
+-
+- q = PHY_IDENTIFIER(PHY_PACKET_CONFIG) |
+- PHY_CONFIG_ROOT_ID(node_id) |
+- PHY_CONFIG_GAP_COUNT(gap_count);
+-
+- send_phy_packet(card, q, generation);
++ struct fw_phy_packet p;
++ u32 data = PHY_IDENTIFIER(PHY_PACKET_CONFIG) |
++ PHY_CONFIG_ROOT_ID(node_id) |
++ PHY_CONFIG_GAP_COUNT(gap_count);
++
++ p.packet.header[0] = data;
++ p.packet.header[1] = ~data;
++ p.packet.header_length = 8;
++ p.packet.payload_length = 0;
++ p.packet.speed = SCODE_100;
++ p.packet.generation = generation;
++ p.packet.callback = transmit_phy_packet_callback;
++ init_completion(&p.done);
++
++ card->driver->send_request(card, &p.packet);
++ wait_for_completion(&p.done);
+ }
+
+ void fw_flush_transactions(struct fw_card *card)
+@@ -389,21 +387,21 @@ lookup_enclosing_address_handler(struct list_head *list,
+ static DEFINE_SPINLOCK(address_handler_lock);
+ static LIST_HEAD(address_handler_list);
+
+-const struct fw_address_region fw_low_memory_region =
+- { .start = 0x000000000000ULL, .end = 0x000100000000ULL, };
+ const struct fw_address_region fw_high_memory_region =
+ { .start = 0x000100000000ULL, .end = 0xffffe0000000ULL, };
++EXPORT_SYMBOL(fw_high_memory_region);
++
++#if 0
++const struct fw_address_region fw_low_memory_region =
++ { .start = 0x000000000000ULL, .end = 0x000100000000ULL, };
+ const struct fw_address_region fw_private_region =
+ { .start = 0xffffe0000000ULL, .end = 0xfffff0000000ULL, };
+ const struct fw_address_region fw_csr_region =
+- { .start = 0xfffff0000000ULL, .end = 0xfffff0000800ULL, };
++ { .start = CSR_REGISTER_BASE,
++ .end = CSR_REGISTER_BASE | CSR_CONFIG_ROM_END, };
+ const struct fw_address_region fw_unit_space_region =
+ { .start = 0xfffff0000900ULL, .end = 0x1000000000000ULL, };
+-EXPORT_SYMBOL(fw_low_memory_region);
+-EXPORT_SYMBOL(fw_high_memory_region);
+-EXPORT_SYMBOL(fw_private_region);
+-EXPORT_SYMBOL(fw_csr_region);
+-EXPORT_SYMBOL(fw_unit_space_region);
++#endif /* 0 */
+
+ /**
+ * Allocate a range of addresses in the node space of the OHCI
+@@ -747,7 +745,8 @@ fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
+ EXPORT_SYMBOL(fw_core_handle_response);
+
+ static const struct fw_address_region topology_map_region =
+- { .start = 0xfffff0001000ull, .end = 0xfffff0001400ull, };
++ { .start = CSR_REGISTER_BASE | CSR_TOPOLOGY_MAP,
++ .end = CSR_REGISTER_BASE | CSR_TOPOLOGY_MAP_END, };
+
+ static void
+ handle_topology_map(struct fw_card *card, struct fw_request *request,
+@@ -785,7 +784,8 @@ static struct fw_address_handler topology_map = {
+ };
+
+ static const struct fw_address_region registers_region =
+- { .start = 0xfffff0000000ull, .end = 0xfffff0000400ull, };
++ { .start = CSR_REGISTER_BASE,
++ .end = CSR_REGISTER_BASE | CSR_CONFIG_ROM, };
+
+ static void
+ handle_registers(struct fw_card *card, struct fw_request *request,
+@@ -794,7 +794,7 @@ handle_registers(struct fw_card *card, struct fw_request *request,
+ unsigned long long offset,
+ void *payload, size_t length, void *callback_data)
+ {
+- int reg = offset - CSR_REGISTER_BASE;
++ int reg = offset & ~CSR_REGISTER_BASE;
+ unsigned long long bus_time;
+ __be32 *data = payload;
+
+diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
+index a43bb22..04d3854 100644
+--- a/drivers/firewire/fw-transaction.h
++++ b/drivers/firewire/fw-transaction.h
+@@ -201,11 +201,7 @@ struct fw_address_region {
+ u64 end;
+ };
+
+-extern const struct fw_address_region fw_low_memory_region;
+ extern const struct fw_address_region fw_high_memory_region;
+-extern const struct fw_address_region fw_private_region;
+-extern const struct fw_address_region fw_csr_region;
+-extern const struct fw_address_region fw_unit_space_region;
+
+ int fw_core_add_address_handler(struct fw_address_handler *handler,
+ const struct fw_address_region *region);
+@@ -221,12 +217,9 @@ struct fw_card {
+ const struct fw_card_driver *driver;
+ struct device *device;
+ atomic_t device_count;
+- struct kref kref;
+
+ int node_id;
+ int generation;
+- /* This is the generation used for timestamping incoming requests. */
+- int request_generation;
+ int current_tlabel, tlabel_mask;
+ struct list_head transaction_list;
+ struct timer_list flush_timer;
+@@ -263,9 +256,6 @@ struct fw_card {
+ int bm_generation;
+ };
+
+-struct fw_card *fw_card_get(struct fw_card *card);
+-void fw_card_put(struct fw_card *card);
+-
+ /*
+ * The iso packet format allows for an immediate header/payload part
+ * stored in 'header' immediately after the packet info plus an
+diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
+index 05f02a3..40ffd76 100644
+--- a/drivers/firmware/Kconfig
++++ b/drivers/firmware/Kconfig
+@@ -93,4 +93,24 @@ config DMIID
+ information from userspace through /sys/class/dmi/id/ or if you want
+ DMI-based module auto-loading.
+
++config ISCSI_IBFT_FIND
++ bool "iSCSI Boot Firmware Table Attributes"
++ depends on X86
++ default n
++ help
++ This option enables the kernel to find the region of memory
++ in which the ISCSI Boot Firmware Table (iBFT) resides. This
++ is necessary for iSCSI Boot Firmware Table Attributes module to work
++ properly.
++
++config ISCSI_IBFT
++ tristate "iSCSI Boot Firmware Table Attributes module"
++ depends on ISCSI_IBFT_FIND
++ default n
++ help
++ This option enables support for detection and exposing of iSCSI
++ Boot Firmware Table (iBFT) via sysfs to userspace. If you wish to
++ detect iSCSI boot parameters dynamically during system boot, say Y.
++ Otherwise, say N.
++
+ endmenu
+diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
+index 8d4ebc8..4c91471 100644
+--- a/drivers/firmware/Makefile
++++ b/drivers/firmware/Makefile
+@@ -8,3 +8,5 @@ obj-$(CONFIG_EFI_PCDP) += pcdp.o
+ obj-$(CONFIG_DELL_RBU) += dell_rbu.o
+ obj-$(CONFIG_DCDBAS) += dcdbas.o
+ obj-$(CONFIG_DMIID) += dmi-id.o
++obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o
++obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o
+diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
+index 1636806..f235940 100644
+--- a/drivers/firmware/dcdbas.c
++++ b/drivers/firmware/dcdbas.c
+@@ -35,7 +35,6 @@
+ #include <linux/types.h>
+ #include <linux/mutex.h>
+ #include <asm/io.h>
+-#include <asm/semaphore.h>
+
+ #include "dcdbas.h"
+
+@@ -265,7 +264,7 @@ static int smi_request(struct smi_cmd *smi_cmd)
+
+ /* SMI requires CPU 0 */
+ old_mask = current->cpus_allowed;
+- set_cpus_allowed(current, cpumask_of_cpu(0));
++ set_cpus_allowed_ptr(current, &cpumask_of_cpu(0));
+ if (smp_processor_id() != 0) {
+ dev_dbg(&dcdbas_pdev->dev, "%s: failed to get CPU 0\n",
+ __FUNCTION__);
+@@ -285,7 +284,7 @@ static int smi_request(struct smi_cmd *smi_cmd)
+ );
+
+ out:
+- set_cpus_allowed(current, old_mask);
++ set_cpus_allowed_ptr(current, &old_mask);
+ return ret;
+ }
+
+diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c
+new file mode 100644
+index 0000000..8024e3b
+--- /dev/null
++++ b/drivers/firmware/iscsi_ibft.c
+@@ -0,0 +1,982 @@
++/*
++ * Copyright 2007 Red Hat, Inc.
++ * by Peter Jones <pjones at redhat.com>
++ * Copyright 2008 IBM, Inc.
++ * by Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Copyright 2008
++ * by Konrad Rzeszutek <ketuzsezr at darnok.org>
++ *
++ * This code exposes the iSCSI Boot Format Table to userland via sysfs.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License v2.0 as published by
++ * the Free Software Foundation
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * Changelog:
++ *
++ * 14 Mar 2008 - Konrad Rzeszutek <ketuzsezr at darnok.org>
++ * Updated comments and copyrights. (v0.4.9)
++ *
++ * 11 Feb 2008 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Converted to using ibft_addr. (v0.4.8)
++ *
++ * 8 Feb 2008 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Combined two functions in one: reserve_ibft_region. (v0.4.7)
++ *
++ * 30 Jan 2008 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Added logic to handle IPv6 addresses. (v0.4.6)
++ *
++ * 25 Jan 2008 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Added logic to handle badly not-to-spec iBFT. (v0.4.5)
++ *
++ * 4 Jan 2008 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Added __init to function declarations. (v0.4.4)
++ *
++ * 21 Dec 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Updated kobject registration, combined unregister functions in one
++ * and code and style cleanup. (v0.4.3)
++ *
++ * 5 Dec 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Added end-markers to enums and re-organized kobject registration. (v0.4.2)
++ *
++ * 4 Dec 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Created 'device' sysfs link to the NIC and style cleanup. (v0.4.1)
++ *
++ * 28 Nov 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Added sysfs-ibft documentation, moved 'find_ibft' function to
++ * in its own file and added text attributes for every struct field. (v0.4)
++ *
++ * 21 Nov 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Added text attributes emulating OpenFirmware /proc/device-tree naming.
++ * Removed binary /sysfs interface (v0.3)
++ *
++ * 29 Aug 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Added functionality in setup.c to reserve iBFT region. (v0.2)
++ *
++ * 27 Aug 2007 - Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * First version exposing iBFT data via a binary /sysfs. (v0.1)
++ *
++ */
++
++
++#include <linux/blkdev.h>
++#include <linux/capability.h>
++#include <linux/ctype.h>
++#include <linux/device.h>
++#include <linux/err.h>
++#include <linux/init.h>
++#include <linux/iscsi_ibft.h>
++#include <linux/limits.h>
++#include <linux/module.h>
++#include <linux/pci.h>
++#include <linux/slab.h>
++#include <linux/stat.h>
++#include <linux/string.h>
++#include <linux/types.h>
++
++#define IBFT_ISCSI_VERSION "0.4.9"
++#define IBFT_ISCSI_DATE "2008-Mar-14"
++
++MODULE_AUTHOR("Peter Jones <pjones at redhat.com> and \
++Konrad Rzeszutek <ketuzsezr at darnok.org>");
++MODULE_DESCRIPTION("sysfs interface to BIOS iBFT information");
++MODULE_LICENSE("GPL");
++MODULE_VERSION(IBFT_ISCSI_VERSION);
++
++struct ibft_hdr {
++ u8 id;
++ u8 version;
++ u16 length;
++ u8 index;
++ u8 flags;
++} __attribute__((__packed__));
++
++struct ibft_control {
++ struct ibft_hdr hdr;
++ u16 extensions;
++ u16 initiator_off;
++ u16 nic0_off;
++ u16 tgt0_off;
++ u16 nic1_off;
++ u16 tgt1_off;
++} __attribute__((__packed__));
++
++struct ibft_initiator {
++ struct ibft_hdr hdr;
++ char isns_server[16];
++ char slp_server[16];
++ char pri_radius_server[16];
++ char sec_radius_server[16];
++ u16 initiator_name_len;
++ u16 initiator_name_off;
++} __attribute__((__packed__));
++
++struct ibft_nic {
++ struct ibft_hdr hdr;
++ char ip_addr[16];
++ u8 subnet_mask_prefix;
++ u8 origin;
++ char gateway[16];
++ char primary_dns[16];
++ char secondary_dns[16];
++ char dhcp[16];
++ u16 vlan;
++ char mac[6];
++ u16 pci_bdf;
++ u16 hostname_len;
++ u16 hostname_off;
++} __attribute__((__packed__));
++
++struct ibft_tgt {
++ struct ibft_hdr hdr;
++ char ip_addr[16];
++ u16 port;
++ char lun[8];
++ u8 chap_type;
++ u8 nic_assoc;
++ u16 tgt_name_len;
++ u16 tgt_name_off;
++ u16 chap_name_len;
++ u16 chap_name_off;
++ u16 chap_secret_len;
++ u16 chap_secret_off;
++ u16 rev_chap_name_len;
++ u16 rev_chap_name_off;
++ u16 rev_chap_secret_len;
++ u16 rev_chap_secret_off;
++} __attribute__((__packed__));
++
++/*
++ * The kobject different types and its names.
++ *
++*/
++enum ibft_id {
++ id_reserved = 0, /* We don't support. */
++ id_control = 1, /* Should show up only once and is not exported. */
++ id_initiator = 2,
++ id_nic = 3,
++ id_target = 4,
++ id_extensions = 5, /* We don't support. */
++ id_end_marker,
++};
++
++/*
++ * We do not support the other types, hence the usage of NULL.
++ * This maps to the enum ibft_id.
++ */
++static const char *ibft_id_names[] =
++ {NULL, NULL, "initiator", "ethernet%d", "target%d", NULL, NULL};
++
++/*
++ * The text attributes names for each of the kobjects.
++*/
++enum ibft_eth_properties_enum {
++ ibft_eth_index,
++ ibft_eth_flags,
++ ibft_eth_ip_addr,
++ ibft_eth_subnet_mask,
++ ibft_eth_origin,
++ ibft_eth_gateway,
++ ibft_eth_primary_dns,
++ ibft_eth_secondary_dns,
++ ibft_eth_dhcp,
++ ibft_eth_vlan,
++ ibft_eth_mac,
++ /* ibft_eth_pci_bdf - this is replaced by link to the device itself. */
++ ibft_eth_hostname,
++ ibft_eth_end_marker,
++};
++
++static const char *ibft_eth_properties[] =
++ {"index", "flags", "ip-addr", "subnet-mask", "origin", "gateway",
++ "primary-dns", "secondary-dns", "dhcp", "vlan", "mac", "hostname",
++ NULL};
++
++enum ibft_tgt_properties_enum {
++ ibft_tgt_index,
++ ibft_tgt_flags,
++ ibft_tgt_ip_addr,
++ ibft_tgt_port,
++ ibft_tgt_lun,
++ ibft_tgt_chap_type,
++ ibft_tgt_nic_assoc,
++ ibft_tgt_name,
++ ibft_tgt_chap_name,
++ ibft_tgt_chap_secret,
++ ibft_tgt_rev_chap_name,
++ ibft_tgt_rev_chap_secret,
++ ibft_tgt_end_marker,
++};
++
++static const char *ibft_tgt_properties[] =
++ {"index", "flags", "ip-addr", "port", "lun", "chap-type", "nic-assoc",
++ "target-name", "chap-name", "chap-secret", "rev-chap-name",
++ "rev-chap-name-secret", NULL};
++
++enum ibft_initiator_properties_enum {
++ ibft_init_index,
++ ibft_init_flags,
++ ibft_init_isns_server,
++ ibft_init_slp_server,
++ ibft_init_pri_radius_server,
++ ibft_init_sec_radius_server,
++ ibft_init_initiator_name,
++ ibft_init_end_marker,
++};
++
++static const char *ibft_initiator_properties[] =
++ {"index", "flags", "isns-server", "slp-server", "pri-radius-server",
++ "sec-radius-server", "initiator-name", NULL};
++
++/*
++ * The kobject and attribute structures.
++ */
++
++struct ibft_kobject {
++ struct ibft_table_header *header;
++ union {
++ struct ibft_initiator *initiator;
++ struct ibft_nic *nic;
++ struct ibft_tgt *tgt;
++ struct ibft_hdr *hdr;
++ };
++ struct kobject kobj;
++ struct list_head node;
++};
++
++struct ibft_attribute {
++ struct attribute attr;
++ ssize_t (*show) (struct ibft_kobject *entry,
++ struct ibft_attribute *attr, char *buf);
++ union {
++ struct ibft_initiator *initiator;
++ struct ibft_nic *nic;
++ struct ibft_tgt *tgt;
++ struct ibft_hdr *hdr;
++ };
++ struct kobject *kobj;
++ int type; /* The enum of the type. This can be any value of:
++ ibft_eth_properties_enum, ibft_tgt_properties_enum,
++ or ibft_initiator_properties_enum. */
++ struct list_head node;
++};
++
++static LIST_HEAD(ibft_attr_list);
++static LIST_HEAD(ibft_kobject_list);
++
++static const char nulls[16];
++
++/*
++ * Helper functions to parse data properly.
++ */
++static ssize_t sprintf_ipaddr(char *buf, u8 *ip)
++{
++ char *str = buf;
++
++ if (ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0 &&
++ ip[4] == 0 && ip[5] == 0 && ip[6] == 0 && ip[7] == 0 &&
++ ip[8] == 0 && ip[9] == 0 && ip[10] == 0xff && ip[11] == 0xff) {
++ /*
++ * IPV4
++ */
++ str += sprintf(buf, NIPQUAD_FMT, ip[12],
++ ip[13], ip[14], ip[15]);
++ } else {
++ /*
++ * IPv6
++ */
++ str += sprintf(str, NIP6_FMT, ntohs(ip[0]), ntohs(ip[1]),
++ ntohs(ip[2]), ntohs(ip[3]), ntohs(ip[4]),
++ ntohs(ip[5]), ntohs(ip[6]), ntohs(ip[7]));
++ }
++ str += sprintf(str, "\n");
++ return str - buf;
++}
++
++static ssize_t sprintf_string(char *str, int len, char *buf)
++{
++ return sprintf(str, "%.*s\n", len, buf);
++}
++
++/*
++ * Helper function to verify the IBFT header.
++ */
++static int ibft_verify_hdr(char *t, struct ibft_hdr *hdr, int id, int length)
++{
++ if (hdr->id != id) {
++ printk(KERN_ERR "iBFT error: We expected the " \
++ "field header.id to have %d but " \
++ "found %d instead!\n", id, hdr->id);
++ return -ENODEV;
++ }
++ if (hdr->length != length) {
++ printk(KERN_ERR "iBFT error: We expected the " \
++ "field header.length to have %d but " \
++ "found %d instead!\n", length, hdr->length);
++ return -ENODEV;
++ }
++
++ return 0;
++}
++
++static void ibft_release(struct kobject *kobj)
++{
++ struct ibft_kobject *ibft =
++ container_of(kobj, struct ibft_kobject, kobj);
++ kfree(ibft);
++}
++
++/*
++ * Routines for parsing the iBFT data to be human readable.
++ */
++ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry,
++ struct ibft_attribute *attr,
++ char *buf)
++{
++ struct ibft_initiator *initiator = entry->initiator;
++ void *ibft_loc = entry->header;
++ char *str = buf;
++
++ if (!initiator)
++ return 0;
++
++ switch (attr->type) {
++ case ibft_init_index:
++ str += sprintf(str, "%d\n", initiator->hdr.index);
++ break;
++ case ibft_init_flags:
++ str += sprintf(str, "%d\n", initiator->hdr.flags);
++ break;
++ case ibft_init_isns_server:
++ str += sprintf_ipaddr(str, initiator->isns_server);
++ break;
++ case ibft_init_slp_server:
++ str += sprintf_ipaddr(str, initiator->slp_server);
++ break;
++ case ibft_init_pri_radius_server:
++ str += sprintf_ipaddr(str, initiator->pri_radius_server);
++ break;
++ case ibft_init_sec_radius_server:
++ str += sprintf_ipaddr(str, initiator->sec_radius_server);
++ break;
++ case ibft_init_initiator_name:
++ str += sprintf_string(str, initiator->initiator_name_len,
++ (char *)ibft_loc +
++ initiator->initiator_name_off);
++ break;
++ default:
++ break;
++ }
++
++ return str - buf;
++}
++
++ssize_t ibft_attr_show_nic(struct ibft_kobject *entry,
++ struct ibft_attribute *attr,
++ char *buf)
++{
++ struct ibft_nic *nic = entry->nic;
++ void *ibft_loc = entry->header;
++ char *str = buf;
++ char *mac;
++ int val;
++
++ if (!nic)
++ return 0;
++
++ switch (attr->type) {
++ case ibft_eth_index:
++ str += sprintf(str, "%d\n", nic->hdr.index);
++ break;
++ case ibft_eth_flags:
++ str += sprintf(str, "%d\n", nic->hdr.flags);
++ break;
++ case ibft_eth_ip_addr:
++ str += sprintf_ipaddr(str, nic->ip_addr);
++ break;
++ case ibft_eth_subnet_mask:
++ val = ~((1 << (32-nic->subnet_mask_prefix))-1);
++ str += sprintf(str, NIPQUAD_FMT,
++ (u8)(val >> 24), (u8)(val >> 16),
++ (u8)(val >> 8), (u8)(val));
++ break;
++ case ibft_eth_origin:
++ str += sprintf(str, "%d\n", nic->origin);
++ break;
++ case ibft_eth_gateway:
++ str += sprintf_ipaddr(str, nic->gateway);
++ break;
++ case ibft_eth_primary_dns:
++ str += sprintf_ipaddr(str, nic->primary_dns);
++ break;
++ case ibft_eth_secondary_dns:
++ str += sprintf_ipaddr(str, nic->secondary_dns);
++ break;
++ case ibft_eth_dhcp:
++ str += sprintf_ipaddr(str, nic->dhcp);
++ break;
++ case ibft_eth_vlan:
++ str += sprintf(str, "%d\n", nic->vlan);
++ break;
++ case ibft_eth_mac:
++ mac = nic->mac;
++ str += sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x\n",
++ (u8)mac[0], (u8)mac[1], (u8)mac[2],
++ (u8)mac[3], (u8)mac[4], (u8)mac[5]);
++ break;
++ case ibft_eth_hostname:
++ str += sprintf_string(str, nic->hostname_len,
++ (char *)ibft_loc + nic->hostname_off);
++ break;
++ default:
++ break;
++ }
++
++ return str - buf;
++};
++
++ssize_t ibft_attr_show_target(struct ibft_kobject *entry,
++ struct ibft_attribute *attr,
++ char *buf)
++{
++ struct ibft_tgt *tgt = entry->tgt;
++ void *ibft_loc = entry->header;
++ char *str = buf;
++ int i;
++
++ if (!tgt)
++ return 0;
++
++ switch (attr->type) {
++ case ibft_tgt_index:
++ str += sprintf(str, "%d\n", tgt->hdr.index);
++ break;
++ case ibft_tgt_flags:
++ str += sprintf(str, "%d\n", tgt->hdr.flags);
++ break;
++ case ibft_tgt_ip_addr:
++ str += sprintf_ipaddr(str, tgt->ip_addr);
++ break;
++ case ibft_tgt_port:
++ str += sprintf(str, "%d\n", tgt->port);
++ break;
++ case ibft_tgt_lun:
++ for (i = 0; i < 8; i++)
++ str += sprintf(str, "%x", (u8)tgt->lun[i]);
++ str += sprintf(str, "\n");
++ break;
++ case ibft_tgt_nic_assoc:
++ str += sprintf(str, "%d\n", tgt->nic_assoc);
++ break;
++ case ibft_tgt_chap_type:
++ str += sprintf(str, "%d\n", tgt->chap_type);
++ break;
++ case ibft_tgt_name:
++ str += sprintf_string(str, tgt->tgt_name_len,
++ (char *)ibft_loc + tgt->tgt_name_off);
++ break;
++ case ibft_tgt_chap_name:
++ str += sprintf_string(str, tgt->chap_name_len,
++ (char *)ibft_loc + tgt->chap_name_off);
++ break;
++ case ibft_tgt_chap_secret:
++ str += sprintf_string(str, tgt->chap_secret_len,
++ (char *)ibft_loc + tgt->chap_secret_off);
++ break;
++ case ibft_tgt_rev_chap_name:
++ str += sprintf_string(str, tgt->rev_chap_name_len,
++ (char *)ibft_loc +
++ tgt->rev_chap_name_off);
++ break;
++ case ibft_tgt_rev_chap_secret:
++ str += sprintf_string(str, tgt->rev_chap_secret_len,
++ (char *)ibft_loc +
++ tgt->rev_chap_secret_off);
++ break;
++ default:
++ break;
++ }
++
++ return str - buf;
++}
++
++/*
++ * The routine called for all sysfs attributes.
++ */
++static ssize_t ibft_show_attribute(struct kobject *kobj,
++ struct attribute *attr,
++ char *buf)
++{
++ struct ibft_kobject *dev =
++ container_of(kobj, struct ibft_kobject, kobj);
++ struct ibft_attribute *ibft_attr =
++ container_of(attr, struct ibft_attribute, attr);
++ ssize_t ret = -EIO;
++ char *str = buf;
++
++ if (!capable(CAP_SYS_ADMIN))
++ return -EACCES;
++
++ if (ibft_attr->show)
++ ret = ibft_attr->show(dev, ibft_attr, str);
++
++ return ret;
++}
++
++static struct sysfs_ops ibft_attr_ops = {
++ .show = ibft_show_attribute,
++};
++
++static struct kobj_type ibft_ktype = {
++ .release = ibft_release,
++ .sysfs_ops = &ibft_attr_ops,
++};
++
++static struct kset *ibft_kset;
++
++static int __init ibft_check_device(void)
++{
++ int len;
++ u8 *pos;
++ u8 csum = 0;
++
++ len = ibft_addr->length;
++
++ /* Sanity checking of iBFT. */
++ if (ibft_addr->revision != 1) {
++ printk(KERN_ERR "iBFT module supports only revision 1, " \
++ "while this is %d.\n", ibft_addr->revision);
++ return -ENOENT;
++ }
++ for (pos = (u8 *)ibft_addr; pos < (u8 *)ibft_addr + len; pos++)
++ csum += *pos;
++
++ if (csum) {
++ printk(KERN_ERR "iBFT has incorrect checksum (0x%x)!\n", csum);
++ return -ENOENT;
++ }
++
++ return 0;
++}
++
++/*
++ * Helper function for ibft_register_kobjects.
++ */
++static int __init ibft_create_kobject(struct ibft_table_header *header,
++ struct ibft_hdr *hdr,
++ struct list_head *list)
++{
++ struct ibft_kobject *ibft_kobj = NULL;
++ struct ibft_nic *nic = (struct ibft_nic *)hdr;
++ struct pci_dev *pci_dev;
++ int rc = 0;
++
++ ibft_kobj = kzalloc(sizeof(*ibft_kobj), GFP_KERNEL);
++ if (!ibft_kobj)
++ return -ENOMEM;
++
++ ibft_kobj->header = header;
++ ibft_kobj->hdr = hdr;
++
++ switch (hdr->id) {
++ case id_initiator:
++ rc = ibft_verify_hdr("initiator", hdr, id_initiator,
++ sizeof(*ibft_kobj->initiator));
++ break;
++ case id_nic:
++ rc = ibft_verify_hdr("ethernet", hdr, id_nic,
++ sizeof(*ibft_kobj->nic));
++ break;
++ case id_target:
++ rc = ibft_verify_hdr("target", hdr, id_target,
++ sizeof(*ibft_kobj->tgt));
++ break;
++ case id_reserved:
++ case id_control:
++ case id_extensions:
++ /* Fields which we don't support. Ignore them */
++ rc = 1;
++ break;
++ default:
++ printk(KERN_ERR "iBFT has unknown structure type (%d). " \
++ "Report this bug to %.6s!\n", hdr->id,
++ header->oem_id);
++ rc = 1;
++ break;
++ }
++
++ if (rc) {
++ /* Skip adding this kobject, but exit with non-fatal error. */
++ kfree(ibft_kobj);
++ goto out_invalid_struct;
++ }
++
++ ibft_kobj->kobj.kset = ibft_kset;
++
++ rc = kobject_init_and_add(&ibft_kobj->kobj, &ibft_ktype,
++ NULL, ibft_id_names[hdr->id], hdr->index);
++
++ if (rc) {
++ kfree(ibft_kobj);
++ goto out;
++ }
++
++ kobject_uevent(&ibft_kobj->kobj, KOBJ_ADD);
++
++ if (hdr->id == id_nic) {
++ /*
++ * We don't search for the device in other domains than
++ * zero. This is because on x86 platforms the BIOS
++ * executes only devices which are in domain 0. Furthermore, the
++ * iBFT spec doesn't have a domain id field :-(
++ */
++ pci_dev = pci_get_bus_and_slot((nic->pci_bdf & 0xff00) >> 8,
++ (nic->pci_bdf & 0xff));
++ if (pci_dev) {
++ rc = sysfs_create_link(&ibft_kobj->kobj,
++ &pci_dev->dev.kobj, "device");
++ pci_dev_put(pci_dev);
++ }
++ }
++
++ /* Nothing broke so lets add it to the list. */
++ list_add_tail(&ibft_kobj->node, list);
++out:
++ return rc;
++out_invalid_struct:
++ /* Unsupported structs are skipped. */
++ return 0;
++}
++
++/*
++ * Scan the IBFT table structure for the NIC and Target fields. When
++ * found add them on the passed-in list. We do not support the other
++ * fields at this point, so they are skipped.
++ */
++static int __init ibft_register_kobjects(struct ibft_table_header *header,
++ struct list_head *list)
++{
++ struct ibft_control *control = NULL;
++ void *ptr, *end;
++ int rc = 0;
++ u16 offset;
++ u16 eot_offset;
++
++ control = (void *)header + sizeof(*header);
++ end = (void *)control + control->hdr.length;
++ eot_offset = (void *)header + header->length -
++ (void *)control - sizeof(*header);
++ rc = ibft_verify_hdr("control", (struct ibft_hdr *)control, id_control,
++ sizeof(*control));
++
++ /* iBFT table safety checking */
++ rc |= ((control->hdr.index) ? -ENODEV : 0);
++ if (rc) {
++ printk(KERN_ERR "iBFT error: Control header is invalid!\n");
++ return rc;
++ }
++ for (ptr = &control->initiator_off; ptr < end; ptr += sizeof(u16)) {
++ offset = *(u16 *)ptr;
++ if (offset && offset < header->length && offset < eot_offset) {
++ rc = ibft_create_kobject(header,
++ (void *)header + offset,
++ list);
++ if (rc)
++ break;
++ }
++ }
++
++ return rc;
++}
++
++static void ibft_unregister(struct list_head *attr_list,
++ struct list_head *kobj_list)
++{
++ struct ibft_kobject *data = NULL, *n;
++ struct ibft_attribute *attr = NULL, *m;
++
++ list_for_each_entry_safe(attr, m, attr_list, node) {
++ sysfs_remove_file(attr->kobj, &attr->attr);
++ list_del(&attr->node);
++ kfree(attr);
++ };
++ list_del_init(attr_list);
++
++ list_for_each_entry_safe(data, n, kobj_list, node) {
++ list_del(&data->node);
++ if (data->hdr->id == id_nic)
++ sysfs_remove_link(&data->kobj, "device");
++ kobject_put(&data->kobj);
++ };
++ list_del_init(kobj_list);
++}
++
++static int __init ibft_create_attribute(struct ibft_kobject *kobj_data,
++ int type,
++ const char *name,
++ ssize_t (*show)(struct ibft_kobject *,
++ struct ibft_attribute*,
++ char *buf),
++ struct list_head *list)
++{
++ struct ibft_attribute *attr = NULL;
++ struct ibft_hdr *hdr = kobj_data->hdr;
++
++ attr = kmalloc(sizeof(*attr), GFP_KERNEL);
++ if (!attr)
++ return -ENOMEM;
++
++ attr->attr.name = name;
++ attr->attr.mode = S_IRUSR;
++ attr->attr.owner = THIS_MODULE;
++
++ attr->hdr = hdr;
++ attr->show = show;
++ attr->kobj = &kobj_data->kobj;
++ attr->type = type;
++
++ list_add_tail(&attr->node, list);
++
++ return 0;
++}
++
++/*
++ * Helper routiners to check to determine if the entry is valid
++ * in the proper iBFT structure.
++ */
++static int __init ibft_check_nic_for(struct ibft_nic *nic, int entry)
++{
++ int rc = 0;
++
++ switch (entry) {
++ case ibft_eth_index:
++ case ibft_eth_flags:
++ rc = 1;
++ break;
++ case ibft_eth_ip_addr:
++ if (!memcmp(nic->dhcp, nulls, sizeof(nic->dhcp)))
++ rc = 1;
++ break;
++ case ibft_eth_subnet_mask:
++ if (!memcmp(nic->dhcp, nulls, sizeof(nic->dhcp)))
++ rc = 1;
++ break;
++ case ibft_eth_origin:
++ rc = 1;
++ break;
++ case ibft_eth_gateway:
++ if (memcmp(nic->gateway, nulls, sizeof(nic->gateway)))
++ rc = 1;
++ break;
++ case ibft_eth_primary_dns:
++ if (memcmp(nic->primary_dns, nulls,
++ sizeof(nic->primary_dns)))
++ rc = 1;
++ break;
++ case ibft_eth_secondary_dns:
++ if (memcmp(nic->secondary_dns, nulls,
++ sizeof(nic->secondary_dns)))
++ rc = 1;
++ break;
++ case ibft_eth_dhcp:
++ if (memcmp(nic->dhcp, nulls, sizeof(nic->dhcp)))
++ rc = 1;
++ break;
++ case ibft_eth_vlan:
++ case ibft_eth_mac:
++ rc = 1;
++ break;
++ case ibft_eth_hostname:
++ if (nic->hostname_off)
++ rc = 1;
++ break;
++ default:
++ break;
++ }
++
++ return rc;
++}
++
++static int __init ibft_check_tgt_for(struct ibft_tgt *tgt, int entry)
++{
++ int rc = 0;
++
++ switch (entry) {
++ case ibft_tgt_index:
++ case ibft_tgt_flags:
++ case ibft_tgt_ip_addr:
++ case ibft_tgt_port:
++ case ibft_tgt_lun:
++ case ibft_tgt_nic_assoc:
++ case ibft_tgt_chap_type:
++ rc = 1;
++ case ibft_tgt_name:
++ if (tgt->tgt_name_len)
++ rc = 1;
++ break;
++ case ibft_tgt_chap_name:
++ case ibft_tgt_chap_secret:
++ if (tgt->chap_name_len)
++ rc = 1;
++ break;
++ case ibft_tgt_rev_chap_name:
++ case ibft_tgt_rev_chap_secret:
++ if (tgt->rev_chap_name_len)
++ rc = 1;
++ break;
++ default:
++ break;
++ }
++
++ return rc;
++}
++
++static int __init ibft_check_initiator_for(struct ibft_initiator *init,
++ int entry)
++{
++ int rc = 0;
++
++ switch (entry) {
++ case ibft_init_index:
++ case ibft_init_flags:
++ rc = 1;
++ break;
++ case ibft_init_isns_server:
++ if (memcmp(init->isns_server, nulls,
++ sizeof(init->isns_server)))
++ rc = 1;
++ break;
++ case ibft_init_slp_server:
++ if (memcmp(init->slp_server, nulls,
++ sizeof(init->slp_server)))
++ rc = 1;
++ break;
++ case ibft_init_pri_radius_server:
++ if (memcmp(init->pri_radius_server, nulls,
++ sizeof(init->pri_radius_server)))
++ rc = 1;
++ break;
++ case ibft_init_sec_radius_server:
++ if (memcmp(init->sec_radius_server, nulls,
++ sizeof(init->sec_radius_server)))
++ rc = 1;
++ break;
++ case ibft_init_initiator_name:
++ if (init->initiator_name_len)
++ rc = 1;
++ break;
++ default:
++ break;
++ }
++
++ return rc;
++}
++
++/*
++ * Register the attributes for all of the kobjects.
++ */
++static int __init ibft_register_attributes(struct list_head *kobject_list,
++ struct list_head *attr_list)
++{
++ int rc = 0, i = 0;
++ struct ibft_kobject *data = NULL;
++ struct ibft_attribute *attr = NULL, *m;
++
++ list_for_each_entry(data, kobject_list, node) {
++ switch (data->hdr->id) {
++ case id_nic:
++ for (i = 0; i < ibft_eth_end_marker && !rc; i++)
++ if (ibft_check_nic_for(data->nic, i))
++ rc = ibft_create_attribute(data, i,
++ ibft_eth_properties[i],
++ ibft_attr_show_nic, attr_list);
++ break;
++ case id_target:
++ for (i = 0; i < ibft_tgt_end_marker && !rc; i++)
++ if (ibft_check_tgt_for(data->tgt, i))
++ rc = ibft_create_attribute(data, i,
++ ibft_tgt_properties[i],
++ ibft_attr_show_target,
++ attr_list);
++ break;
++ case id_initiator:
++ for (i = 0; i < ibft_init_end_marker && !rc; i++)
++ if (ibft_check_initiator_for(
++ data->initiator, i))
++ rc = ibft_create_attribute(data, i,
++ ibft_initiator_properties[i],
++ ibft_attr_show_initiator,
++ attr_list);
++ break;
++ default:
++ break;
++ }
++ if (rc)
++ break;
++ }
++ list_for_each_entry_safe(attr, m, attr_list, node) {
++ rc = sysfs_create_file(attr->kobj, &attr->attr);
++ if (rc) {
++ list_del(&attr->node);
++ kfree(attr);
++ break;
++ }
++ }
++
++ return rc;
++}
++
++/*
++ * ibft_init() - creates sysfs tree entries for the iBFT data.
++ */
++static int __init ibft_init(void)
++{
++ int rc = 0;
++
++ ibft_kset = kset_create_and_add("ibft", NULL, firmware_kobj);
++ if (!ibft_kset)
++ return -ENOMEM;
++
++ if (ibft_addr) {
++ printk(KERN_INFO "iBFT detected at 0x%lx.\n",
++ virt_to_phys((void *)ibft_addr));
++
++ rc = ibft_check_device();
++ if (rc)
++ goto out_firmware_unregister;
++
++ /* Scan the IBFT for data and register the kobjects. */
++ rc = ibft_register_kobjects(ibft_addr, &ibft_kobject_list);
++ if (rc)
++ goto out_free;
++
++ /* Register the attributes */
++ rc = ibft_register_attributes(&ibft_kobject_list,
++ &ibft_attr_list);
++ if (rc)
++ goto out_free;
++ } else
++ printk(KERN_INFO "No iBFT detected.\n");
++
++ return 0;
++
++out_free:
++ ibft_unregister(&ibft_attr_list, &ibft_kobject_list);
++out_firmware_unregister:
++ kset_unregister(ibft_kset);
++ return rc;
++}
++
++static void __exit ibft_exit(void)
++{
++ ibft_unregister(&ibft_attr_list, &ibft_kobject_list);
++ kset_unregister(ibft_kset);
++}
++
++module_init(ibft_init);
++module_exit(ibft_exit);
+diff --git a/drivers/firmware/iscsi_ibft_find.c b/drivers/firmware/iscsi_ibft_find.c
+new file mode 100644
+index 0000000..d0e5fa4
+--- /dev/null
++++ b/drivers/firmware/iscsi_ibft_find.c
+@@ -0,0 +1,84 @@
++/*
++ * Copyright 2007 Red Hat, Inc.
++ * by Peter Jones <pjones at redhat.com>
++ * Copyright 2007 IBM, Inc.
++ * by Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Copyright 2008
++ * by Konrad Rzeszutek <ketuzsezr at darnok.org>
++ *
++ * This code finds the iSCSI Boot Format Table.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License v2.0 as published by
++ * the Free Software Foundation
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/bootmem.h>
++#include <linux/blkdev.h>
++#include <linux/ctype.h>
++#include <linux/device.h>
++#include <linux/err.h>
++#include <linux/init.h>
++#include <linux/limits.h>
++#include <linux/module.h>
++#include <linux/pci.h>
++#include <linux/slab.h>
++#include <linux/stat.h>
++#include <linux/string.h>
++#include <linux/types.h>
++
++#include <asm/mmzone.h>
++
++/*
++ * Physical location of iSCSI Boot Format Table.
++ */
++struct ibft_table_header *ibft_addr;
++EXPORT_SYMBOL_GPL(ibft_addr);
++
++#define IBFT_SIGN "iBFT"
++#define IBFT_SIGN_LEN 4
++#define IBFT_START 0x80000 /* 512kB */
++#define IBFT_END 0x100000 /* 1MB */
++#define VGA_MEM 0xA0000 /* VGA buffer */
++#define VGA_SIZE 0x20000 /* 128kB */
++
++
++/*
++ * Routine used to find the iSCSI Boot Format Table. The logical
++ * kernel address is set in the ibft_addr global variable.
++ */
++void __init reserve_ibft_region(void)
++{
++ unsigned long pos;
++ unsigned int len = 0;
++ void *virt;
++
++ ibft_addr = 0;
++
++ for (pos = IBFT_START; pos < IBFT_END; pos += 16) {
++ /* The table can't be inside the VGA BIOS reserved space,
++ * so skip that area */
++ if (pos == VGA_MEM)
++ pos += VGA_SIZE;
++ virt = phys_to_virt(pos);
++ if (memcmp(virt, IBFT_SIGN, IBFT_SIGN_LEN) == 0) {
++ unsigned long *addr =
++ (unsigned long *)phys_to_virt(pos + 4);
++ len = *addr;
++ /* if the length of the table extends past 1M,
++ * the table cannot be valid. */
++ if (pos + len <= (IBFT_END-1)) {
++ ibft_addr = (struct ibft_table_header *)virt;
++ break;
++ }
++ }
++ }
++ if (ibft_addr)
++ reserve_bootmem(pos, PAGE_ALIGN(len), BOOTMEM_DEFAULT);
++}
++EXPORT_SYMBOL_GPL(reserve_ibft_region);
+diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
+index f0b00ec..e03c67d 100644
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -44,8 +44,8 @@
+
+ #ifdef CONFIG_HID_DEBUG
+ int hid_debug = 0;
+-module_param_named(debug, hid_debug, bool, 0600);
+-MODULE_PARM_DESC(debug, "Turn HID debugging mode on and off");
++module_param_named(debug, hid_debug, int, 0600);
++MODULE_PARM_DESC(debug, "HID debugging (0=off, 1=probing info, 2=continuous data dumping)");
+ EXPORT_SYMBOL_GPL(hid_debug);
+ #endif
+
+@@ -97,7 +97,7 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
+ field->index = report->maxfield++;
+ report->field[field->index] = field;
+ field->usage = (struct hid_usage *)(field + 1);
+- field->value = (unsigned *)(field->usage + usages);
++ field->value = (s32 *)(field->usage + usages);
+ field->report = report;
+
+ return field;
+@@ -830,7 +830,8 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field, s
+ * reporting to the layer).
+ */
+
+-void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt)
++static void hid_input_field(struct hid_device *hid, struct hid_field *field,
++ __u8 *data, int interrupt)
+ {
+ unsigned n;
+ unsigned count = field->report_count;
+@@ -876,7 +877,6 @@ void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data
+ exit:
+ kfree(value);
+ }
+-EXPORT_SYMBOL_GPL(hid_input_field);
+
+ /*
+ * Output the field into the report.
+@@ -988,8 +988,13 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
+
+ if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)
+ hid->hiddev_report_event(hid, report);
+- if (hid->claimed & HID_CLAIMED_HIDRAW)
+- hidraw_report_event(hid, data, size);
++ if (hid->claimed & HID_CLAIMED_HIDRAW) {
++ /* numbered reports need to be passed with the report num */
++ if (report_enum->numbered)
++ hidraw_report_event(hid, data - 1, size + 1);
++ else
++ hidraw_report_event(hid, data, size);
++ }
+
+ for (n = 0; n < report->maxfield; n++)
+ hid_input_field(hid, report->field[n], data, interrupt);
+diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
+index 5c24fe4..f88714b 100644
+--- a/drivers/hid/hid-debug.c
++++ b/drivers/hid/hid-debug.c
+@@ -498,7 +498,7 @@ void hid_dump_device(struct hid_device *device) {
+ EXPORT_SYMBOL_GPL(hid_dump_device);
+
+ void hid_dump_input(struct hid_usage *usage, __s32 value) {
+- if (!hid_debug)
++ if (hid_debug < 2)
+ return;
+
+ printk(KERN_DEBUG "hid-debug: input ");
+diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c
+index dceadd0..4c2052c 100644
+--- a/drivers/hid/hid-input-quirks.c
++++ b/drivers/hid/hid-input-quirks.c
+@@ -276,6 +276,21 @@ static int quirk_btc_8193(struct hid_usage *usage, struct input_dev *input,
+ return 1;
+ }
+
++static int quirk_sunplus_wdesktop(struct hid_usage *usage, struct input_dev *input,
++ unsigned long **bit, int *max)
++{
++ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
++ return 0;
++
++ switch (usage->hid & HID_USAGE) {
++ case 0x2003: map_key_clear(KEY_ZOOMIN); break;
++ case 0x2103: map_key_clear(KEY_ZOOMOUT); break;
++ default:
++ return 0;
++ }
++ return 1;
++}
++
+ #define VENDOR_ID_BELKIN 0x1020
+ #define DEVICE_ID_BELKIN_WIRELESS_KEYBOARD 0x0006
+
+@@ -306,6 +321,9 @@ static int quirk_btc_8193(struct hid_usage *usage, struct input_dev *input,
+ #define VENDOR_ID_PETALYNX 0x18b1
+ #define DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037
+
++#define VENDOR_ID_SUNPLUS 0x04fc
++#define DEVICE_ID_SUNPLUS_WDESKTOP 0x05d8
++
+ static const struct hid_input_blacklist {
+ __u16 idVendor;
+ __u16 idProduct;
+@@ -332,8 +350,10 @@ static const struct hid_input_blacklist {
+ { VENDOR_ID_MONTEREY, DEVICE_ID_GENIUS_KB29E, quirk_cherry_genius_29e },
+
+ { VENDOR_ID_PETALYNX, DEVICE_ID_PETALYNX_MAXTER_REMOTE, quirk_petalynx_remote },
+-
+- { 0, 0, 0 }
++
++ { VENDOR_ID_SUNPLUS, DEVICE_ID_SUNPLUS_WDESKTOP, quirk_sunplus_wdesktop },
++
++ { 0, 0, NULL }
+ };
+
+ int hidinput_mapping_quirks(struct hid_usage *usage,
+diff --git a/drivers/hid/usbhid/Kconfig b/drivers/hid/usbhid/Kconfig
+index 7160fa6..18f0910 100644
+--- a/drivers/hid/usbhid/Kconfig
++++ b/drivers/hid/usbhid/Kconfig
+@@ -71,6 +71,14 @@ config LOGITECH_FF
+ Note: if you say N here, this device will still be supported, but without
+ force feedback.
+
++config LOGIRUMBLEPAD2_FF
++ bool "Logitech Rumblepad 2 support"
++ depends on HID_FF
++ select INPUT_FF_MEMLESS if USB_HID
++ help
++ Say Y here if you want to enable force feedback support for Logitech
++ Rumblepad 2 devices.
++
+ config PANTHERLORD_FF
+ bool "PantherLord/GreenAsia based device support"
+ depends on HID_FF
+@@ -80,8 +88,8 @@ config PANTHERLORD_FF
+ or adapter and want to enable force feedback support for it.
+
+ config THRUSTMASTER_FF
+- bool "ThrustMaster devices support (EXPERIMENTAL)"
+- depends on HID_FF && EXPERIMENTAL
++ bool "ThrustMaster devices support"
++ depends on HID_FF
+ select INPUT_FF_MEMLESS if USB_HID
+ help
+ Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or
+diff --git a/drivers/hid/usbhid/Makefile b/drivers/hid/usbhid/Makefile
+index 8e6ab5b..00a7b70 100644
+--- a/drivers/hid/usbhid/Makefile
++++ b/drivers/hid/usbhid/Makefile
+@@ -16,6 +16,9 @@ endif
+ ifeq ($(CONFIG_LOGITECH_FF),y)
+ usbhid-objs += hid-lgff.o
+ endif
++ifeq ($(CONFIG_LOGIRUMBLEPAD2_FF),y)
++ usbhid-objs += hid-lg2ff.o
++endif
+ ifeq ($(CONFIG_PANTHERLORD_FF),y)
+ usbhid-objs += hid-plff.o
+ endif
+diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
+index d95979f..e0d805f 100644
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -82,6 +82,7 @@ static int hid_start_in(struct hid_device *hid)
+
+ spin_lock_irqsave(&usbhid->inlock, flags);
+ if (hid->open > 0 && !test_bit(HID_SUSPENDED, &usbhid->iofl) &&
++ !test_bit(HID_DISCONNECTED, &usbhid->iofl) &&
+ !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) {
+ rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC);
+ if (rc != 0)
+@@ -155,7 +156,7 @@ static void hid_io_error(struct hid_device *hid)
+ spin_lock_irqsave(&usbhid->inlock, flags);
+
+ /* Stop when disconnected */
+- if (usb_get_intfdata(usbhid->intf) == NULL)
++ if (test_bit(HID_DISCONNECTED, &usbhid->iofl))
+ goto done;
+
+ /* If it has been a while since the last error, we'll assume
+@@ -341,7 +342,7 @@ static void hid_irq_out(struct urb *urb)
+ if (usbhid->outhead != usbhid->outtail) {
+ if (hid_submit_out(hid)) {
+ clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
+- wake_up(&hid->wait);
++ wake_up(&usbhid->wait);
+ }
+ spin_unlock_irqrestore(&usbhid->outlock, flags);
+ return;
+@@ -349,7 +350,7 @@ static void hid_irq_out(struct urb *urb)
+
+ clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
+ spin_unlock_irqrestore(&usbhid->outlock, flags);
+- wake_up(&hid->wait);
++ wake_up(&usbhid->wait);
+ }
+
+ /*
+@@ -391,7 +392,7 @@ static void hid_ctrl(struct urb *urb)
+ if (usbhid->ctrlhead != usbhid->ctrltail) {
+ if (hid_submit_ctrl(hid)) {
+ clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
+- wake_up(&hid->wait);
++ wake_up(&usbhid->wait);
+ }
+ spin_unlock_irqrestore(&usbhid->ctrllock, flags);
+ return;
+@@ -399,7 +400,7 @@ static void hid_ctrl(struct urb *urb)
+
+ clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
+ spin_unlock_irqrestore(&usbhid->ctrllock, flags);
+- wake_up(&hid->wait);
++ wake_up(&usbhid->wait);
+ }
+
+ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
+@@ -478,8 +479,9 @@ int usbhid_wait_io(struct hid_device *hid)
+ {
+ struct usbhid_device *usbhid = hid->driver_data;
+
+- if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl) &&
+- !test_bit(HID_OUT_RUNNING, &usbhid->iofl)),
++ if (!wait_event_timeout(usbhid->wait,
++ (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl) &&
++ !test_bit(HID_OUT_RUNNING, &usbhid->iofl)),
+ 10*HZ)) {
+ dbg_hid("timeout waiting for ctrl or out queue to clear\n");
+ return -1;
+@@ -610,10 +612,11 @@ static void usbhid_set_leds(struct hid_device *hid)
+ /*
+ * Traverse the supplied list of reports and find the longest
+ */
+-static void hid_find_max_report(struct hid_device *hid, unsigned int type, int *max)
++static void hid_find_max_report(struct hid_device *hid, unsigned int type,
++ unsigned int *max)
+ {
+ struct hid_report *report;
+- int size;
++ unsigned int size;
+
+ list_for_each_entry(report, &hid->report_enum[type].report_list, list) {
+ size = ((report->size - 1) >> 3) + 1;
+@@ -705,9 +708,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
+ struct hid_descriptor *hdesc;
+ struct hid_device *hid;
+ u32 quirks = 0;
+- unsigned rsize = 0;
++ unsigned int insize = 0, rsize = 0;
+ char *rdesc;
+- int n, len, insize = 0;
++ int n, len;
+ struct usbhid_device *usbhid;
+
+ quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
+@@ -800,6 +803,22 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
+ goto fail;
+ }
+
++ hid->name[0] = 0;
++
++ if (dev->manufacturer)
++ strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));
++
++ if (dev->product) {
++ if (dev->manufacturer)
++ strlcat(hid->name, " ", sizeof(hid->name));
++ strlcat(hid->name, dev->product, sizeof(hid->name));
++ }
++
++ if (!strlen(hid->name))
++ snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x",
++ le16_to_cpu(dev->descriptor.idVendor),
++ le16_to_cpu(dev->descriptor.idProduct));
++
+ for (n = 0; n < interface->desc.bNumEndpoints; n++) {
+
+ struct usb_endpoint_descriptor *endpoint;
+@@ -812,6 +831,14 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
+
+ interval = endpoint->bInterval;
+
++ /* Some vendors give fullspeed interval on highspeed devides */
++ if (quirks & HID_QUIRK_FULLSPEED_INTERVAL &&
++ dev->speed == USB_SPEED_HIGH) {
++ interval = fls(endpoint->bInterval*8);
++ printk(KERN_INFO "%s: Fixing fullspeed to highspeed interval: %d -> %d\n",
++ hid->name, endpoint->bInterval, interval);
++ }
++
+ /* Change the polling interval of mice. */
+ if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0)
+ interval = hid_mousepoll_interval;
+@@ -844,8 +871,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
+ goto fail;
+ }
+
+- init_waitqueue_head(&hid->wait);
+-
++ init_waitqueue_head(&usbhid->wait);
+ INIT_WORK(&usbhid->reset_work, hid_reset);
+ setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
+
+@@ -859,22 +885,6 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
+ usbhid->intf = intf;
+ usbhid->ifnum = interface->desc.bInterfaceNumber;
+
+- hid->name[0] = 0;
+-
+- if (dev->manufacturer)
+- strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));
+-
+- if (dev->product) {
+- if (dev->manufacturer)
+- strlcat(hid->name, " ", sizeof(hid->name));
+- strlcat(hid->name, dev->product, sizeof(hid->name));
+- }
+-
+- if (!strlen(hid->name))
+- snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x",
+- le16_to_cpu(dev->descriptor.idVendor),
+- le16_to_cpu(dev->descriptor.idProduct));
+-
+ hid->bus = BUS_USB;
+ hid->vendor = le16_to_cpu(dev->descriptor.idVendor);
+ hid->product = le16_to_cpu(dev->descriptor.idProduct);
+@@ -932,6 +942,7 @@ static void hid_disconnect(struct usb_interface *intf)
+
+ spin_lock_irq(&usbhid->inlock); /* Sync with error handler */
+ usb_set_intfdata(intf, NULL);
++ set_bit(HID_DISCONNECTED, &usbhid->iofl);
+ spin_unlock_irq(&usbhid->inlock);
+ usb_kill_urb(usbhid->urbin);
+ usb_kill_urb(usbhid->urbout);
+diff --git a/drivers/hid/usbhid/hid-ff.c b/drivers/hid/usbhid/hid-ff.c
+index 4c210e1..1d0dac5 100644
+--- a/drivers/hid/usbhid/hid-ff.c
++++ b/drivers/hid/usbhid/hid-ff.c
+@@ -59,6 +59,9 @@ static struct hid_ff_initializer inits[] = {
+ { 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */
+ { 0x46d, 0xca03, hid_lgff_init }, /* Logitech MOMO force wheel */
+ #endif
++#ifdef CONFIG_LOGIRUMBLEPAD2_FF
++ { 0x46d, 0xc218, hid_lg2ff_init }, /* Logitech Rumblepad 2 */
++#endif
+ #ifdef CONFIG_PANTHERLORD_FF
+ { 0x810, 0x0001, hid_plff_init }, /* "Twin USB Joystick" */
+ { 0xe8f, 0x0003, hid_plff_init }, /* "GreenAsia Inc. USB Joystick " */
+diff --git a/drivers/hid/usbhid/hid-lg2ff.c b/drivers/hid/usbhid/hid-lg2ff.c
+new file mode 100644
+index 0000000..d469bd0
+--- /dev/null
++++ b/drivers/hid/usbhid/hid-lg2ff.c
+@@ -0,0 +1,114 @@
++/*
++ * Force feedback support for Logitech Rumblepad 2
++ *
++ * Copyright (c) 2008 Anssi Hannula <anssi.hannula at gmail.com>
++ */
++
++/*
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++
++#include <linux/input.h>
++#include <linux/usb.h>
++#include <linux/hid.h>
++#include "usbhid.h"
++
++struct lg2ff_device {
++ struct hid_report *report;
++};
++
++static int play_effect(struct input_dev *dev, void *data,
++ struct ff_effect *effect)
++{
++ struct hid_device *hid = input_get_drvdata(dev);
++ struct lg2ff_device *lg2ff = data;
++ int weak, strong;
++
++ strong = effect->u.rumble.strong_magnitude;
++ weak = effect->u.rumble.weak_magnitude;
++
++ if (weak || strong) {
++ weak = weak * 0xff / 0xffff;
++ strong = strong * 0xff / 0xffff;
++
++ lg2ff->report->field[0]->value[0] = 0x51;
++ lg2ff->report->field[0]->value[2] = weak;
++ lg2ff->report->field[0]->value[4] = strong;
++ } else {
++ lg2ff->report->field[0]->value[0] = 0xf3;
++ lg2ff->report->field[0]->value[2] = 0x00;
++ lg2ff->report->field[0]->value[4] = 0x00;
++ }
++
++ usbhid_submit_report(hid, lg2ff->report, USB_DIR_OUT);
++ return 0;
++}
++
++int hid_lg2ff_init(struct hid_device *hid)
++{
++ struct lg2ff_device *lg2ff;
++ struct hid_report *report;
++ struct hid_input *hidinput = list_entry(hid->inputs.next,
++ struct hid_input, list);
++ struct list_head *report_list =
++ &hid->report_enum[HID_OUTPUT_REPORT].report_list;
++ struct input_dev *dev = hidinput->input;
++ int error;
++
++ if (list_empty(report_list)) {
++ printk(KERN_ERR "hid-lg2ff: no output report found\n");
++ return -ENODEV;
++ }
++
++ report = list_entry(report_list->next, struct hid_report, list);
++
++ if (report->maxfield < 1) {
++ printk(KERN_ERR "hid-lg2ff: output report is empty\n");
++ return -ENODEV;
++ }
++ if (report->field[0]->report_count < 7) {
++ printk(KERN_ERR "hid-lg2ff: not enough values in the field\n");
++ return -ENODEV;
++ }
++
++ lg2ff = kmalloc(sizeof(struct lg2ff_device), GFP_KERNEL);
++ if (!lg2ff)
++ return -ENOMEM;
++
++ set_bit(FF_RUMBLE, dev->ffbit);
++
++ error = input_ff_create_memless(dev, lg2ff, play_effect);
++ if (error) {
++ kfree(lg2ff);
++ return error;
++ }
++
++ lg2ff->report = report;
++ report->field[0]->value[0] = 0xf3;
++ report->field[0]->value[1] = 0x00;
++ report->field[0]->value[2] = 0x00;
++ report->field[0]->value[3] = 0x00;
++ report->field[0]->value[4] = 0x00;
++ report->field[0]->value[5] = 0x00;
++ report->field[0]->value[6] = 0x00;
++
++ usbhid_submit_report(hid, report, USB_DIR_OUT);
++
++ printk(KERN_INFO "Force feedback for Logitech Rumblepad 2 by "
++ "Anssi Hannula <anssi.hannula at gmail.com>\n");
++
++ return 0;
++}
+diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
+index e29a057..d3f8d91 100644
+--- a/drivers/hid/usbhid/hid-quirks.c
++++ b/drivers/hid/usbhid/hid-quirks.c
+@@ -32,6 +32,9 @@
+ #define USB_VENDOR_ID_ADS_TECH 0x06e1
+ #define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X 0xa155
+
++#define USB_VENDOR_ID_AFATECH 0x15a4
++#define USB_DEVICE_ID_AFATECH_AF9016 0x9016
++
+ #define USB_VENDOR_ID_AIPTEK 0x08ca
+ #define USB_DEVICE_ID_AIPTEK_01 0x0001
+ #define USB_DEVICE_ID_AIPTEK_10 0x0010
+@@ -124,6 +127,9 @@
+ #define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
+ #define USB_DEVICE_ID_DELORME_EM_LT20 0x0200
+
++#define USB_VENDOR_ID_DMI 0x0c0b
++#define USB_DEVICE_ID_DMI_ENC 0x5fab
++
+ #define USB_VENDOR_ID_ELO 0x04E7
+ #define USB_DEVICE_ID_ELO_TS2700 0x0020
+
+@@ -199,17 +205,6 @@
+ #define USB_DEVICE_ID_GTCO_502 0x0502
+ #define USB_DEVICE_ID_GTCO_503 0x0503
+ #define USB_DEVICE_ID_GTCO_504 0x0504
+-#define USB_DEVICE_ID_GTCO_600 0x0600
+-#define USB_DEVICE_ID_GTCO_601 0x0601
+-#define USB_DEVICE_ID_GTCO_602 0x0602
+-#define USB_DEVICE_ID_GTCO_603 0x0603
+-#define USB_DEVICE_ID_GTCO_604 0x0604
+-#define USB_DEVICE_ID_GTCO_605 0x0605
+-#define USB_DEVICE_ID_GTCO_606 0x0606
+-#define USB_DEVICE_ID_GTCO_607 0x0607
+-#define USB_DEVICE_ID_GTCO_608 0x0608
+-#define USB_DEVICE_ID_GTCO_609 0x0609
+-#define USB_DEVICE_ID_GTCO_609 0x0609
+ #define USB_DEVICE_ID_GTCO_1000 0x1000
+ #define USB_DEVICE_ID_GTCO_1001 0x1001
+ #define USB_DEVICE_ID_GTCO_1002 0x1002
+@@ -320,6 +315,7 @@
+ #define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512
+ #define USB_DEVICE_ID_MX3000_RECEIVER 0xc513
+ #define USB_DEVICE_ID_DINOVO_EDGE 0xc714
++#define USB_DEVICE_ID_DINOVO_MINI 0xc71f
+
+ #define USB_VENDOR_ID_MCC 0x09db
+ #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076
+@@ -332,6 +328,7 @@
+ #define USB_VENDOR_ID_MICROSOFT 0x045e
+ #define USB_DEVICE_ID_SIDEWINDER_GV 0x003b
+ #define USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0 0x009d
++#define USB_DEVICE_ID_DESKTOP_RECV_1028 0x00f9
+ #define USB_DEVICE_ID_MS_NE4K 0x00db
+ #define USB_DEVICE_ID_MS_LK6K 0x00f9
+
+@@ -377,6 +374,9 @@
+ #define USB_VENDOR_ID_SUN 0x0430
+ #define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab
+
++#define USB_VENDOR_ID_SUNPLUS 0x04fc
++#define USB_DEVICE_ID_SUNPLUS_WDESKTOP 0x05d8
++
+ #define USB_VENDOR_ID_TOPMAX 0x0663
+ #define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103
+
+@@ -405,6 +405,9 @@
+ #define USB_VENDOR_ID_YEALINK 0x6993
+ #define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001
+
++#define USB_VENDOR_ID_KYE 0x0458
++#define USB_DEVICE_ID_KYE_GPEN_560 0x5003
++
+ /*
+ * Alphabetically sorted blacklist by quirk type.
+ */
+@@ -435,9 +438,13 @@ static const struct hid_blacklist {
+ { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
+
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES },
++ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI, HID_QUIRK_DUPLICATE_USAGES },
++
++ { USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016, HID_QUIRK_FULLSPEED_INTERVAL },
+
+ { USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM, HID_QUIRK_HIDDEV },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4, HID_QUIRK_HIDDEV | HID_QUIRK_IGNORE_HIDINPUT },
++ { USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE, HID_QUIRK_HIDDEV | HID_QUIRK_IGNORE_HIDINPUT },
+ { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV, HID_QUIRK_HIDINPUT },
+
+ { USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193, HID_QUIRK_HWHEEL_WHEEL_INVERT },
+@@ -518,16 +525,6 @@ static const struct hid_blacklist {
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_502, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_503, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_504, HID_QUIRK_IGNORE },
+- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_600, HID_QUIRK_IGNORE },
+- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_601, HID_QUIRK_IGNORE },
+- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_602, HID_QUIRK_IGNORE },
+- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_603, HID_QUIRK_IGNORE },
+- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_604, HID_QUIRK_IGNORE },
+- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_605, HID_QUIRK_IGNORE },
+- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_606, HID_QUIRK_IGNORE },
+- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_607, HID_QUIRK_IGNORE },
+- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_608, HID_QUIRK_IGNORE },
+- { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_609, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1000, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1001, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1002, HID_QUIRK_IGNORE },
+@@ -601,6 +598,7 @@ static const struct hid_blacklist {
+ { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
++ { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET },
+@@ -608,7 +606,7 @@ static const struct hid_blacklist {
+ { USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
+- { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
++ { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
+ { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
+
+ { USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
+@@ -703,6 +701,7 @@ static const struct hid_blacklist {
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_63, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_64, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR, USB_DEVICE_ID_N_S_HARMONY, HID_QUIRK_IGNORE },
++ { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560, HID_QUIRK_IGNORE },
+
+ { 0, 0 }
+ };
+@@ -719,6 +718,7 @@ static const struct hid_rdesc_blacklist {
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_RDESC_LOGITECH },
++ { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_DESKTOP_RECV_1028, HID_QUIRK_RDESC_MICROSOFT_RECV_1028 },
+
+ { USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E, HID_QUIRK_RDESC_BUTTON_CONSUMER },
+
+@@ -728,6 +728,8 @@ static const struct hid_rdesc_blacklist {
+
+ { USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE, HID_QUIRK_RDESC_SAMSUNG_REMOTE },
+
++ { USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP, HID_QUIRK_RDESC_SUNPLUS_WDESKTOP },
++
+ { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
+ { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
+
+@@ -793,8 +795,8 @@ static struct hid_blacklist *usbhid_exists_dquirk(const u16 idVendor,
+ *
+ * Returns: 0 OK, -error on failure.
+ */
+-int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct,
+- const u32 quirks)
++static int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct,
++ const u32 quirks)
+ {
+ struct quirks_list_struct *q_new, *q;
+ int list_edited = 0;
+@@ -1002,6 +1004,17 @@ static void usbhid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
+ }
+ }
+
++static void usbhid_fixup_sunplus_wdesktop(unsigned char *rdesc, int rsize)
++{
++ if (rsize >= 107 && rdesc[104] == 0x26
++ && rdesc[105] == 0x80
++ && rdesc[106] == 0x03) {
++ printk(KERN_INFO "Fixing up Sunplus Wireless Desktop report descriptor\n");
++ rdesc[105] = rdesc[110] = 0x03;
++ rdesc[106] = rdesc[111] = 0x21;
++ }
++}
++
+ /*
+ * Samsung IrDA remote controller (reports as Cypress USB Mouse).
+ *
+@@ -1089,6 +1102,28 @@ static void usbhid_fixup_button_consumer_descriptor(unsigned char *rdesc, int rs
+ }
+ }
+
++/*
++ * Microsoft Wireless Desktop Receiver (Model 1028) has several
++ * 'Usage Min/Max' where it ought to have 'Physical Min/Max'
++ */
++static void usbhid_fixup_microsoft_descriptor(unsigned char *rdesc, int rsize)
++{
++ if (rsize == 571 && rdesc[284] == 0x19
++ && rdesc[286] == 0x2a
++ && rdesc[304] == 0x19
++ && rdesc[306] == 0x29
++ && rdesc[352] == 0x1a
++ && rdesc[355] == 0x2a
++ && rdesc[557] == 0x19
++ && rdesc[559] == 0x29) {
++ printk(KERN_INFO "Fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n");
++ rdesc[284] = rdesc[304] = rdesc[558] = 0x35;
++ rdesc[352] = 0x36;
++ rdesc[286] = rdesc[355] = 0x46;
++ rdesc[306] = rdesc[559] = 0x45;
++ }
++}
++
+ static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned rsize)
+ {
+ if ((quirks & HID_QUIRK_RDESC_CYMOTION))
+@@ -1112,6 +1147,11 @@ static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned
+ if (quirks & HID_QUIRK_RDESC_SAMSUNG_REMOTE)
+ usbhid_fixup_samsung_irda_descriptor(rdesc, rsize);
+
++ if (quirks & HID_QUIRK_RDESC_MICROSOFT_RECV_1028)
++ usbhid_fixup_microsoft_descriptor(rdesc, rsize);
++
++ if (quirks & HID_QUIRK_RDESC_SUNPLUS_WDESKTOP)
++ usbhid_fixup_sunplus_wdesktop(rdesc, rsize);
+ }
+
+ /**
+@@ -1150,5 +1190,4 @@ void usbhid_fixup_report_descriptor(const u16 idVendor, const u16 idProduct,
+ else if (paramVendor == idVendor && paramProduct == idProduct)
+ __usbhid_fixup_report_descriptor(quirks, rdesc, rsize);
+ }
+-
+ }
+diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
+index 5fc4019..95cc192 100644
+--- a/drivers/hid/usbhid/hiddev.c
++++ b/drivers/hid/usbhid/hiddev.c
+@@ -393,6 +393,153 @@ static unsigned int hiddev_poll(struct file *file, poll_table *wait)
+ /*
+ * "ioctl" file op
+ */
++static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd, void __user *user_arg)
++{
++ struct hid_device *hid = hiddev->hid;
++ struct hiddev_report_info rinfo;
++ struct hiddev_usage_ref_multi *uref_multi = NULL;
++ struct hiddev_usage_ref *uref;
++ struct hid_report *report;
++ struct hid_field *field;
++ int i;
++
++ uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL);
++ if (!uref_multi)
++ return -ENOMEM;
++ uref = &uref_multi->uref;
++ if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) {
++ if (copy_from_user(uref_multi, user_arg,
++ sizeof(*uref_multi)))
++ goto fault;
++ } else {
++ if (copy_from_user(uref, user_arg, sizeof(*uref)))
++ goto fault;
++ }
++
++ switch (cmd) {
++ case HIDIOCGUCODE:
++ rinfo.report_type = uref->report_type;
++ rinfo.report_id = uref->report_id;
++ if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
++ goto inval;
++
++ if (uref->field_index >= report->maxfield)
++ goto inval;
++
++ field = report->field[uref->field_index];
++ if (uref->usage_index >= field->maxusage)
++ goto inval;
++
++ uref->usage_code = field->usage[uref->usage_index].hid;
++
++ if (copy_to_user(user_arg, uref, sizeof(*uref)))
++ goto fault;
++
++ kfree(uref_multi);
++ return 0;
++
++ default:
++ if (cmd != HIDIOCGUSAGE &&
++ cmd != HIDIOCGUSAGES &&
++ uref->report_type == HID_REPORT_TYPE_INPUT)
++ goto inval;
++
++ if (uref->report_id == HID_REPORT_ID_UNKNOWN) {
++ field = hiddev_lookup_usage(hid, uref);
++ if (field == NULL)
++ goto inval;
++ } else {
++ rinfo.report_type = uref->report_type;
++ rinfo.report_id = uref->report_id;
++ if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
++ goto inval;
++
++ if (uref->field_index >= report->maxfield)
++ goto inval;
++
++ field = report->field[uref->field_index];
++
++ if (cmd == HIDIOCGCOLLECTIONINDEX) {
++ if (uref->usage_index >= field->maxusage)
++ goto inval;
++ } else if (uref->usage_index >= field->report_count)
++ goto inval;
++
++ else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
++ (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
++ uref->usage_index + uref_multi->num_values > field->report_count))
++ goto inval;
++ }
++
++ switch (cmd) {
++ case HIDIOCGUSAGE:
++ uref->value = field->value[uref->usage_index];
++ if (copy_to_user(user_arg, uref, sizeof(*uref)))
++ goto fault;
++ goto goodreturn;
++
++ case HIDIOCSUSAGE:
++ field->value[uref->usage_index] = uref->value;
++ goto goodreturn;
++
++ case HIDIOCGCOLLECTIONINDEX:
++ kfree(uref_multi);
++ return field->usage[uref->usage_index].collection_index;
++ case HIDIOCGUSAGES:
++ for (i = 0; i < uref_multi->num_values; i++)
++ uref_multi->values[i] =
++ field->value[uref->usage_index + i];
++ if (copy_to_user(user_arg, uref_multi,
++ sizeof(*uref_multi)))
++ goto fault;
++ goto goodreturn;
++ case HIDIOCSUSAGES:
++ for (i = 0; i < uref_multi->num_values; i++)
++ field->value[uref->usage_index + i] =
++ uref_multi->values[i];
++ goto goodreturn;
++ }
++
++goodreturn:
++ kfree(uref_multi);
++ return 0;
++fault:
++ kfree(uref_multi);
++ return -EFAULT;
++inval:
++ kfree(uref_multi);
++ return -EINVAL;
++ }
++}
++
++static noinline int hiddev_ioctl_string(struct hiddev *hiddev, unsigned int cmd, void __user *user_arg)
++{
++ struct hid_device *hid = hiddev->hid;
++ struct usb_device *dev = hid_to_usb_dev(hid);
++ int idx, len;
++ char *buf;
++
++ if (get_user(idx, (int __user *)user_arg))
++ return -EFAULT;
++
++ if ((buf = kmalloc(HID_STRING_SIZE, GFP_KERNEL)) == NULL)
++ return -ENOMEM;
++
++ if ((len = usb_string(dev, idx, buf, HID_STRING_SIZE-1)) < 0) {
++ kfree(buf);
++ return -EINVAL;
++ }
++
++ if (copy_to_user(user_arg+sizeof(int), buf, len+1)) {
++ kfree(buf);
++ return -EFAULT;
++ }
++
++ kfree(buf);
++
++ return len;
++}
++
+ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+ {
+ struct hiddev_list *list = file->private_data;
+@@ -402,8 +549,6 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
+ struct hiddev_collection_info cinfo;
+ struct hiddev_report_info rinfo;
+ struct hiddev_field_info finfo;
+- struct hiddev_usage_ref_multi *uref_multi = NULL;
+- struct hiddev_usage_ref *uref;
+ struct hiddev_devinfo dinfo;
+ struct hid_report *report;
+ struct hid_field *field;
+@@ -470,30 +615,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
+ }
+
+ case HIDIOCGSTRING:
+- {
+- int idx, len;
+- char *buf;
+-
+- if (get_user(idx, (int __user *)arg))
+- return -EFAULT;
+-
+- if ((buf = kmalloc(HID_STRING_SIZE, GFP_KERNEL)) == NULL)
+- return -ENOMEM;
+-
+- if ((len = usb_string(dev, idx, buf, HID_STRING_SIZE-1)) < 0) {
+- kfree(buf);
+- return -EINVAL;
+- }
+-
+- if (copy_to_user(user_arg+sizeof(int), buf, len+1)) {
+- kfree(buf);
+- return -EFAULT;
+- }
+-
+- kfree(buf);
+-
+- return len;
+- }
++ return hiddev_ioctl_string(hiddev, cmd, user_arg);
+
+ case HIDIOCINITREPORT:
+ usbhid_init_reports(hid);
+@@ -578,121 +700,13 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
+ return 0;
+
+ case HIDIOCGUCODE:
+- uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL);
+- if (!uref_multi)
+- return -ENOMEM;
+- uref = &uref_multi->uref;
+- if (copy_from_user(uref, user_arg, sizeof(*uref)))
+- goto fault;
+-
+- rinfo.report_type = uref->report_type;
+- rinfo.report_id = uref->report_id;
+- if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
+- goto inval;
+-
+- if (uref->field_index >= report->maxfield)
+- goto inval;
+-
+- field = report->field[uref->field_index];
+- if (uref->usage_index >= field->maxusage)
+- goto inval;
+-
+- uref->usage_code = field->usage[uref->usage_index].hid;
+-
+- if (copy_to_user(user_arg, uref, sizeof(*uref)))
+- goto fault;
+-
+- kfree(uref_multi);
+- return 0;
+-
++ /* fall through */
+ case HIDIOCGUSAGE:
+ case HIDIOCSUSAGE:
+ case HIDIOCGUSAGES:
+ case HIDIOCSUSAGES:
+ case HIDIOCGCOLLECTIONINDEX:
+- uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL);
+- if (!uref_multi)
+- return -ENOMEM;
+- uref = &uref_multi->uref;
+- if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) {
+- if (copy_from_user(uref_multi, user_arg,
+- sizeof(*uref_multi)))
+- goto fault;
+- } else {
+- if (copy_from_user(uref, user_arg, sizeof(*uref)))
+- goto fault;
+- }
+-
+- if (cmd != HIDIOCGUSAGE &&
+- cmd != HIDIOCGUSAGES &&
+- uref->report_type == HID_REPORT_TYPE_INPUT)
+- goto inval;
+-
+- if (uref->report_id == HID_REPORT_ID_UNKNOWN) {
+- field = hiddev_lookup_usage(hid, uref);
+- if (field == NULL)
+- goto inval;
+- } else {
+- rinfo.report_type = uref->report_type;
+- rinfo.report_id = uref->report_id;
+- if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
+- goto inval;
+-
+- if (uref->field_index >= report->maxfield)
+- goto inval;
+-
+- field = report->field[uref->field_index];
+-
+- if (cmd == HIDIOCGCOLLECTIONINDEX) {
+- if (uref->usage_index >= field->maxusage)
+- goto inval;
+- } else if (uref->usage_index >= field->report_count)
+- goto inval;
+-
+- else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
+- (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
+- uref->usage_index + uref_multi->num_values > field->report_count))
+- goto inval;
+- }
+-
+- switch (cmd) {
+- case HIDIOCGUSAGE:
+- uref->value = field->value[uref->usage_index];
+- if (copy_to_user(user_arg, uref, sizeof(*uref)))
+- goto fault;
+- goto goodreturn;
+-
+- case HIDIOCSUSAGE:
+- field->value[uref->usage_index] = uref->value;
+- goto goodreturn;
+-
+- case HIDIOCGCOLLECTIONINDEX:
+- kfree(uref_multi);
+- return field->usage[uref->usage_index].collection_index;
+- case HIDIOCGUSAGES:
+- for (i = 0; i < uref_multi->num_values; i++)
+- uref_multi->values[i] =
+- field->value[uref->usage_index + i];
+- if (copy_to_user(user_arg, uref_multi,
+- sizeof(*uref_multi)))
+- goto fault;
+- goto goodreturn;
+- case HIDIOCSUSAGES:
+- for (i = 0; i < uref_multi->num_values; i++)
+- field->value[uref->usage_index + i] =
+- uref_multi->values[i];
+- goto goodreturn;
+- }
+-
+-goodreturn:
+- kfree(uref_multi);
+- return 0;
+-fault:
+- kfree(uref_multi);
+- return -EFAULT;
+-inval:
+- kfree(uref_multi);
+- return -EINVAL;
++ return hiddev_ioctl_usage(hiddev, cmd, user_arg);
+
+ case HIDIOCGCOLLECTIONINFO:
+ if (copy_from_user(&cinfo, user_arg, sizeof(cinfo)))
+diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h
+index 0023f96..62d2d7c 100644
+--- a/drivers/hid/usbhid/usbhid.h
++++ b/drivers/hid/usbhid/usbhid.h
+@@ -28,6 +28,7 @@
+ #include <linux/slab.h>
+ #include <linux/list.h>
+ #include <linux/timer.h>
++#include <linux/wait.h>
+ #include <linux/workqueue.h>
+ #include <linux/input.h>
+
+@@ -77,7 +78,7 @@ struct usbhid_device {
+ unsigned long stop_retry; /* Time to give up, in jiffies */
+ unsigned int retry_delay; /* Delay length in ms */
+ struct work_struct reset_work; /* Task context for resets */
+-
++ wait_queue_head_t wait; /* For sleeping */
+ };
+
+ #define hid_to_usb_dev(hid_dev) \
+diff --git a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig
+index 014dfa5..7137a17 100644
+--- a/drivers/i2c/algos/Kconfig
++++ b/drivers/i2c/algos/Kconfig
+@@ -1,45 +1,16 @@
+ #
+-# Character device configuration
++# I2C algorithm drivers configuration
+ #
+
+-menu "I2C Algorithms"
+-
+ config I2C_ALGOBIT
+- tristate "I2C bit-banging interfaces"
+- help
+- This allows you to use a range of I2C adapters called bit-banging
+- adapters. Say Y if you own an I2C adapter belonging to this class
+- and then say Y to the specific driver for you adapter below.
+-
+- This support is also available as a module. If so, the module
+- will be called i2c-algo-bit.
++ tristate
+
+ config I2C_ALGOPCF
+- tristate "I2C PCF 8584 interfaces"
+- help
+- This allows you to use a range of I2C adapters called PCF adapters.
+- Say Y if you own an I2C adapter belonging to this class and then say
+- Y to the specific driver for you adapter below.
+-
+- This support is also available as a module. If so, the module
+- will be called i2c-algo-pcf.
++ tristate
+
+ config I2C_ALGOPCA
+- tristate "I2C PCA 9564 interfaces"
+- help
+- This allows you to use a range of I2C adapters called PCA adapters.
+- Say Y if you own an I2C adapter belonging to this class and then say
+- Y to the specific driver for you adapter below.
+-
+- This support is also available as a module. If so, the module
+- will be called i2c-algo-pca.
++ tristate
+
+ config I2C_ALGO_SGI
+- tristate "I2C SGI interfaces"
++ tristate
+ depends on SGI_IP22 || SGI_IP32 || X86_VISWS
+- help
+- Supports the SGI interfaces like the ones found on SGI Indy VINO
+- or SGI O2 MACE.
+-
+-endmenu
+-
+diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
+index 2a16211..e954a20 100644
+--- a/drivers/i2c/algos/i2c-algo-pca.c
++++ b/drivers/i2c/algos/i2c-algo-pca.c
+@@ -1,6 +1,7 @@
+ /*
+- * i2c-algo-pca.c i2c driver algorithms for PCA9564 adapters
++ * i2c-algo-pca.c i2c driver algorithms for PCA9564 adapters
+ * Copyright (C) 2004 Arcom Control Systems
++ * Copyright (C) 2008 Pengutronix
+ *
+ * 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
+@@ -21,14 +22,10 @@
+ #include <linux/module.h>
+ #include <linux/moduleparam.h>
+ #include <linux/delay.h>
+-#include <linux/slab.h>
+ #include <linux/init.h>
+ #include <linux/errno.h>
+ #include <linux/i2c.h>
+ #include <linux/i2c-algo-pca.h>
+-#include "i2c-algo-pca.h"
+-
+-#define DRIVER "i2c-algo-pca"
+
+ #define DEB1(fmt, args...) do { if (i2c_debug>=1) printk(fmt, ## args); } while(0)
+ #define DEB2(fmt, args...) do { if (i2c_debug>=2) printk(fmt, ## args); } while(0)
+@@ -36,15 +33,15 @@
+
+ static int i2c_debug;
+
+-#define pca_outw(adap, reg, val) adap->write_byte(adap, reg, val)
+-#define pca_inw(adap, reg) adap->read_byte(adap, reg)
++#define pca_outw(adap, reg, val) adap->write_byte(adap->data, reg, val)
++#define pca_inw(adap, reg) adap->read_byte(adap->data, reg)
+
+ #define pca_status(adap) pca_inw(adap, I2C_PCA_STA)
+-#define pca_clock(adap) adap->get_clock(adap)
+-#define pca_own(adap) adap->get_own(adap)
++#define pca_clock(adap) adap->i2c_clock
+ #define pca_set_con(adap, val) pca_outw(adap, I2C_PCA_CON, val)
+ #define pca_get_con(adap) pca_inw(adap, I2C_PCA_CON)
+-#define pca_wait(adap) adap->wait_for_interrupt(adap)
++#define pca_wait(adap) adap->wait_for_completion(adap->data)
++#define pca_reset(adap) adap->reset_chip(adap->data)
+
+ /*
+ * Generate a start condition on the i2c bus.
+@@ -99,7 +96,7 @@ static void pca_stop(struct i2c_algo_pca_data *adap)
+ *
+ * returns after the address has been sent
+ */
+-static void pca_address(struct i2c_algo_pca_data *adap,
++static void pca_address(struct i2c_algo_pca_data *adap,
+ struct i2c_msg *msg)
+ {
+ int sta = pca_get_con(adap);
+@@ -108,9 +105,9 @@ static void pca_address(struct i2c_algo_pca_data *adap,
+ addr = ( (0x7f & msg->addr) << 1 );
+ if (msg->flags & I2C_M_RD )
+ addr |= 1;
+- DEB2("=== SLAVE ADDRESS %#04x+%c=%#04x\n",
++ DEB2("=== SLAVE ADDRESS %#04x+%c=%#04x\n",
+ msg->addr, msg->flags & I2C_M_RD ? 'R' : 'W', addr);
+-
++
+ pca_outw(adap, I2C_PCA_DAT, addr);
+
+ sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI);
+@@ -124,7 +121,7 @@ static void pca_address(struct i2c_algo_pca_data *adap,
+ *
+ * Returns after the byte has been transmitted
+ */
+-static void pca_tx_byte(struct i2c_algo_pca_data *adap,
++static void pca_tx_byte(struct i2c_algo_pca_data *adap,
+ __u8 b)
+ {
+ int sta = pca_get_con(adap);
+@@ -142,19 +139,19 @@ static void pca_tx_byte(struct i2c_algo_pca_data *adap,
+ *
+ * returns immediately.
+ */
+-static void pca_rx_byte(struct i2c_algo_pca_data *adap,
++static void pca_rx_byte(struct i2c_algo_pca_data *adap,
+ __u8 *b, int ack)
+ {
+ *b = pca_inw(adap, I2C_PCA_DAT);
+ DEB2("=== READ %#04x %s\n", *b, ack ? "ACK" : "NACK");
+ }
+
+-/*
++/*
+ * Setup ACK or NACK for next received byte and wait for it to arrive.
+ *
+ * Returns after next byte has arrived.
+ */
+-static void pca_rx_ack(struct i2c_algo_pca_data *adap,
++static void pca_rx_ack(struct i2c_algo_pca_data *adap,
+ int ack)
+ {
+ int sta = pca_get_con(adap);
+@@ -168,15 +165,6 @@ static void pca_rx_ack(struct i2c_algo_pca_data *adap,
+ pca_wait(adap);
+ }
+
+-/*
+- * Reset the i2c bus / SIO
+- */
+-static void pca_reset(struct i2c_algo_pca_data *adap)
+-{
+- /* apparently only an external reset will do it. not a lot can be done */
+- printk(KERN_ERR DRIVER ": Haven't figured out how to do a reset yet\n");
+-}
+-
+ static int pca_xfer(struct i2c_adapter *i2c_adap,
+ struct i2c_msg *msgs,
+ int num)
+@@ -187,7 +175,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
+ int numbytes = 0;
+ int state;
+ int ret;
+- int timeout = 100;
++ int timeout = i2c_adap->timeout;
+
+ while ((state = pca_status(adap)) != 0xf8 && timeout--) {
+ msleep(10);
+@@ -203,14 +191,14 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
+ for (curmsg = 0; curmsg < num; curmsg++) {
+ int addr, i;
+ msg = &msgs[curmsg];
+-
++
+ addr = (0x7f & msg->addr) ;
+-
++
+ if (msg->flags & I2C_M_RD )
+- printk(KERN_INFO " [%02d] RD %d bytes from %#02x [%#02x, ...]\n",
++ printk(KERN_INFO " [%02d] RD %d bytes from %#02x [%#02x, ...]\n",
+ curmsg, msg->len, addr, (addr<<1) | 1);
+ else {
+- printk(KERN_INFO " [%02d] WR %d bytes to %#02x [%#02x%s",
++ printk(KERN_INFO " [%02d] WR %d bytes to %#02x [%#02x%s",
+ curmsg, msg->len, addr, addr<<1,
+ msg->len == 0 ? "" : ", ");
+ for(i=0; i < msg->len; i++)
+@@ -237,7 +225,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
+ case 0x10: /* A repeated start condition has been transmitted */
+ pca_address(adap, msg);
+ break;
+-
++
+ case 0x18: /* SLA+W has been transmitted; ACK has been received */
+ case 0x28: /* Data byte in I2CDAT has been transmitted; ACK has been received */
+ if (numbytes < msg->len) {
+@@ -287,7 +275,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
+ case 0x38: /* Arbitration lost during SLA+W, SLA+R or data bytes */
+ DEB2("Arbitration lost\n");
+ goto out;
+-
++
+ case 0x58: /* Data byte has been received; NOT ACK has been returned */
+ if ( numbytes == msg->len - 1 ) {
+ pca_rx_byte(adap, &msg->buf[numbytes], 0);
+@@ -317,16 +305,16 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
+ pca_reset(adap);
+ goto out;
+ default:
+- printk(KERN_ERR DRIVER ": unhandled SIO state 0x%02x\n", state);
++ dev_err(&i2c_adap->dev, "unhandled SIO state 0x%02x\n", state);
+ break;
+ }
+-
++
+ }
+
+ ret = curmsg;
+ out:
+ DEB1(KERN_CRIT "}}} transfered %d/%d messages. "
+- "status is %#04x. control is %#04x\n",
++ "status is %#04x. control is %#04x\n",
+ curmsg, num, pca_status(adap),
+ pca_get_con(adap));
+ return ret;
+@@ -337,53 +325,65 @@ static u32 pca_func(struct i2c_adapter *adap)
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+ }
+
+-static int pca_init(struct i2c_algo_pca_data *adap)
++static const struct i2c_algorithm pca_algo = {
++ .master_xfer = pca_xfer,
++ .functionality = pca_func,
++};
++
++static int pca_init(struct i2c_adapter *adap)
+ {
+ static int freqs[] = {330,288,217,146,88,59,44,36};
+- int own, clock;
++ int clock;
++ struct i2c_algo_pca_data *pca_data = adap->algo_data;
++
++ if (pca_data->i2c_clock > 7) {
++ printk(KERN_WARNING "%s: Invalid I2C clock speed selected. Trying default.\n",
++ adap->name);
++ pca_data->i2c_clock = I2C_PCA_CON_59kHz;
++ }
++
++ adap->algo = &pca_algo;
+
+- own = pca_own(adap);
+- clock = pca_clock(adap);
+- DEB1(KERN_INFO DRIVER ": own address is %#04x\n", own);
+- DEB1(KERN_INFO DRIVER ": clock freqeuncy is %dkHz\n", freqs[clock]);
++ pca_reset(pca_data);
+
+- pca_outw(adap, I2C_PCA_ADR, own << 1);
++ clock = pca_clock(pca_data);
++ DEB1(KERN_INFO "%s: Clock frequency is %dkHz\n", adap->name, freqs[clock]);
+
+- pca_set_con(adap, I2C_PCA_CON_ENSIO | clock);
+- udelay(500); /* 500 µs for oscilator to stabilise */
++ pca_set_con(pca_data, I2C_PCA_CON_ENSIO | clock);
++ udelay(500); /* 500 us for oscilator to stabilise */
+
+ return 0;
+ }
+
+-static const struct i2c_algorithm pca_algo = {
+- .master_xfer = pca_xfer,
+- .functionality = pca_func,
+-};
+-
+-/*
+- * registering functions to load algorithms at runtime
++/*
++ * registering functions to load algorithms at runtime
+ */
+ int i2c_pca_add_bus(struct i2c_adapter *adap)
+ {
+- struct i2c_algo_pca_data *pca_adap = adap->algo_data;
+ int rval;
+
+- /* register new adapter to i2c module... */
+- adap->algo = &pca_algo;
++ rval = pca_init(adap);
++ if (rval)
++ return rval;
+
+- adap->timeout = 100; /* default values, should */
+- adap->retries = 3; /* be replaced by defines */
++ return i2c_add_adapter(adap);
++}
++EXPORT_SYMBOL(i2c_pca_add_bus);
+
+- if ((rval = pca_init(pca_adap)))
+- return rval;
++int i2c_pca_add_numbered_bus(struct i2c_adapter *adap)
++{
++ int rval;
+
+- rval = i2c_add_adapter(adap);
++ rval = pca_init(adap);
++ if (rval)
++ return rval;
+
+- return rval;
++ return i2c_add_numbered_adapter(adap);
+ }
+-EXPORT_SYMBOL(i2c_pca_add_bus);
++EXPORT_SYMBOL(i2c_pca_add_numbered_bus);
+
+-MODULE_AUTHOR("Ian Campbell <icampbell at arcom.com>");
++MODULE_AUTHOR("Ian Campbell <icampbell at arcom.com>, "
++ "Wolfram Sang <w.sang at pengutronix.de>");
+ MODULE_DESCRIPTION("I2C-Bus PCA9564 algorithm");
+ MODULE_LICENSE("GPL");
+
+diff --git a/drivers/i2c/algos/i2c-algo-pca.h b/drivers/i2c/algos/i2c-algo-pca.h
+deleted file mode 100644
+index 2fee07e..0000000
+--- a/drivers/i2c/algos/i2c-algo-pca.h
++++ /dev/null
+@@ -1,26 +0,0 @@
+-#ifndef I2C_PCA9564_H
+-#define I2C_PCA9564_H 1
+-
+-#define I2C_PCA_STA 0x00 /* STATUS Read Only */
+-#define I2C_PCA_TO 0x00 /* TIMEOUT Write Only */
+-#define I2C_PCA_DAT 0x01 /* DATA Read/Write */
+-#define I2C_PCA_ADR 0x02 /* OWN ADR Read/Write */
+-#define I2C_PCA_CON 0x03 /* CONTROL Read/Write */
+-
+-#define I2C_PCA_CON_AA 0x80 /* Assert Acknowledge */
+-#define I2C_PCA_CON_ENSIO 0x40 /* Enable */
+-#define I2C_PCA_CON_STA 0x20 /* Start */
+-#define I2C_PCA_CON_STO 0x10 /* Stop */
+-#define I2C_PCA_CON_SI 0x08 /* Serial Interrupt */
+-#define I2C_PCA_CON_CR 0x07 /* Clock Rate (MASK) */
+-
+-#define I2C_PCA_CON_330kHz 0x00
+-#define I2C_PCA_CON_288kHz 0x01
+-#define I2C_PCA_CON_217kHz 0x02
+-#define I2C_PCA_CON_146kHz 0x03
+-#define I2C_PCA_CON_88kHz 0x04
+-#define I2C_PCA_CON_59kHz 0x05
+-#define I2C_PCA_CON_44kHz 0x06
+-#define I2C_PCA_CON_36kHz 0x07
+-
+-#endif /* I2C_PCA9564_H */
+diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
+index 5fa9c3c..48438cc 100644
+--- a/drivers/i2c/busses/Kconfig
++++ b/drivers/i2c/busses/Kconfig
+@@ -100,9 +100,12 @@ config I2C_AU1550
+
+ config I2C_BLACKFIN_TWI
+ tristate "Blackfin TWI I2C support"
+- depends on BF534 || BF536 || BF537
++ depends on BLACKFIN
+ help
+- This is the TWI I2C device driver for Blackfin 534/536/537/54x.
++ This is the TWI I2C device driver for Blackfin BF522, BF525,
++ BF527, BF534, BF536, BF537 and BF54x. For other Blackfin processors,
++ please don't use this driver.
++
+ This driver can also be built as a module. If so, the module
+ will be called i2c-bfin-twi.
+
+@@ -135,7 +138,7 @@ config I2C_ELEKTOR
+ This supports the PCF8584 ISA bus I2C adapter. Say Y if you own
+ such an adapter.
+
+- This support is also available as a module. If so, the module
++ This support is also available as a module. If so, the module
+ will be called i2c-elektor.
+
+ config I2C_GPIO
+@@ -190,7 +193,7 @@ config I2C_I810
+ select I2C_ALGOBIT
+ help
+ If you say yes to this option, support will be included for the Intel
+- 810/815 family of mainboard I2C interfaces. Specifically, the
++ 810/815 family of mainboard I2C interfaces. Specifically, the
+ following versions of the chipset are supported:
+ i810AA
+ i810AB
+@@ -246,10 +249,10 @@ config I2C_PIIX4
+
+ config I2C_IBM_IIC
+ tristate "IBM PPC 4xx on-chip I2C interface"
+- depends on IBM_OCP
++ depends on 4xx
+ help
+- Say Y here if you want to use IIC peripheral found on
+- embedded IBM PPC 4xx based systems.
++ Say Y here if you want to use IIC peripheral found on
++ embedded IBM PPC 4xx based systems.
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c-ibm_iic.
+@@ -269,7 +272,7 @@ config I2C_IXP2000
+ depends on ARCH_IXP2000
+ select I2C_ALGOBIT
+ help
+- Say Y here if you have an Intel IXP2000 (2400, 2800, 2850) based
++ Say Y here if you have an Intel IXP2000 (2400, 2800, 2850) based
+ system and are using GPIO lines for an I2C bus.
+
+ This support is also available as a module. If so, the module
+@@ -354,7 +357,7 @@ config I2C_PARPORT
+ on the parport driver. This is meant for embedded systems. Don't say
+ Y here if you intend to say Y or M there.
+
+- This support is also available as a module. If so, the module
++ This support is also available as a module. If so, the module
+ will be called i2c-parport.
+
+ config I2C_PARPORT_LIGHT
+@@ -372,12 +375,12 @@ config I2C_PARPORT_LIGHT
+ the clean but heavy parport handling is not an option. The
+ drawback is a reduced portability and the impossibility to
+ daisy-chain other parallel port devices.
+-
++
+ Don't say Y here if you said Y or M to i2c-parport. Saying M to
+ both is possible but both modules should not be loaded at the same
+ time.
+
+- This support is also available as a module. If so, the module
++ This support is also available as a module. If so, the module
+ will be called i2c-parport-light.
+
+ config I2C_PASEMI
+@@ -401,7 +404,7 @@ config I2C_PROSAVAGE
+
+ This driver is deprecated in favor of the savagefb driver.
+
+- This support is also available as a module. If so, the module
++ This support is also available as a module. If so, the module
+ will be called i2c-prosavage.
+
+ config I2C_S3C2410
+@@ -417,7 +420,7 @@ config I2C_SAVAGE4
+ depends on PCI
+ select I2C_ALGOBIT
+ help
+- If you say yes to this option, support will be included for the
++ If you say yes to this option, support will be included for the
+ S3 Savage 4 I2C interface.
+
+ This driver is deprecated in favor of the savagefb driver.
+@@ -452,7 +455,7 @@ config SCx200_I2C
+
+ If you don't know what to do here, say N.
+
+- This support is also available as a module. If so, the module
++ This support is also available as a module. If so, the module
+ will be called scx200_i2c.
+
+ This driver is deprecated and will be dropped soon. Use i2c-gpio
+@@ -483,14 +486,14 @@ config SCx200_ACB
+
+ If you don't know what to do here, say N.
+
+- This support is also available as a module. If so, the module
++ This support is also available as a module. If so, the module
+ will be called scx200_acb.
+
+ config I2C_SIS5595
+ tristate "SiS 5595"
+ depends on PCI
+ help
+- If you say yes to this option, support will be included for the
++ If you say yes to this option, support will be included for the
+ SiS5595 SMBus (a subset of I2C) interface.
+
+ This driver can also be built as a module. If so, the module
+@@ -500,7 +503,7 @@ config I2C_SIS630
+ tristate "SiS 630/730"
+ depends on PCI
+ help
+- If you say yes to this option, support will be included for the
++ If you say yes to this option, support will be included for the
+ SiS630 and SiS730 SMBus (a subset of I2C) interface.
+
+ This driver can also be built as a module. If so, the module
+@@ -632,9 +635,9 @@ config I2C_PCA_ISA
+ select I2C_ALGOPCA
+ default n
+ help
+- This driver supports ISA boards using the Philips PCA 9564
+- Parallel bus to I2C bus controller
+-
++ This driver supports ISA boards using the Philips PCA9564
++ parallel bus to I2C bus controller.
++
+ This driver can also be built as a module. If so, the module
+ will be called i2c-pca-isa.
+
+@@ -643,9 +646,20 @@ config I2C_PCA_ISA
+ delays when I2C/SMBus chip drivers are loaded (e.g. at boot
+ time). If unsure, say N.
+
++config I2C_PCA_PLATFORM
++ tristate "PCA9564 as platform device"
++ select I2C_ALGOPCA
++ default n
++ help
++ This driver supports a memory mapped Philips PCA9564
++ parallel bus to I2C bus controller.
++
++ This driver can also be built as a module. If so, the module
++ will be called i2c-pca-platform.
++
+ config I2C_MV64XXX
+ tristate "Marvell mv64xxx I2C Controller"
+- depends on (MV64X60 || ARCH_ORION) && EXPERIMENTAL
++ depends on (MV64X60 || PLAT_ORION) && EXPERIMENTAL
+ help
+ If you say yes to this option, support will be included for the
+ built-in I2C interface on the Marvell 64xxx line of host bridges.
+@@ -672,4 +686,23 @@ config I2C_PMCMSP
+ This driver can also be built as module. If so, the module
+ will be called i2c-pmcmsp.
+
++config I2C_SH7760
++ tristate "Renesas SH7760 I2C Controller"
++ depends on CPU_SUBTYPE_SH7760
++ help
++ This driver supports the 2 I2C interfaces on the Renesas SH7760.
++
++ This driver can also be built as a module. If so, the module
++ will be called i2c-sh7760.
++
++config I2C_SH_MOBILE
++ tristate "SuperH Mobile I2C Controller"
++ depends on SUPERH
++ help
++ If you say yes to this option, support will be included for the
++ built-in I2C interface on the Renesas SH-Mobile processor.
++
++ This driver can also be built as a module. If so, the module
++ will be called i2c-sh_mobile.
++
+ endmenu
+diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
+index ea7068f..e8c882a 100644
+--- a/drivers/i2c/busses/Makefile
++++ b/drivers/i2c/busses/Makefile
+@@ -30,6 +30,7 @@ obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o
+ obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o
+ obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o
+ obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
++obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
+ obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o
+ obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o
+ obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
+@@ -37,6 +38,8 @@ obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o
+ obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
+ obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
+ obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o
++obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o
++obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o
+ obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
+ obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o
+ obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o
+diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
+index c09b036..73d6194 100644
+--- a/drivers/i2c/busses/i2c-at91.c
++++ b/drivers/i2c/busses/i2c-at91.c
+@@ -298,7 +298,7 @@ static int at91_i2c_resume(struct platform_device *pdev)
+ #endif
+
+ /* work with "modprobe at91_i2c" from hotplugging or coldplugging */
+-MODULE_ALIAS("at91_i2c");
++MODULE_ALIAS("platform:at91_i2c");
+
+ static struct platform_driver at91_i2c_driver = {
+ .probe = at91_i2c_probe,
+diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c
+index 1953b26..491718f 100644
+--- a/drivers/i2c/busses/i2c-au1550.c
++++ b/drivers/i2c/busses/i2c-au1550.c
+@@ -472,6 +472,7 @@ i2c_au1550_exit(void)
+ MODULE_AUTHOR("Dan Malek, Embedded Edge, LLC.");
+ MODULE_DESCRIPTION("SMBus adapter Alchemy pb1550");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:au1xpsc_smbus");
+
+ module_init (i2c_au1550_init);
+ module_exit (i2c_au1550_exit);
+diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c
+index 7dbdaeb..48d084b 100644
+--- a/drivers/i2c/busses/i2c-bfin-twi.c
++++ b/drivers/i2c/busses/i2c-bfin-twi.c
+@@ -1,25 +1,11 @@
+ /*
+- * drivers/i2c/busses/i2c-bfin-twi.c
++ * Blackfin On-Chip Two Wire Interface Driver
+ *
+- * Description: Driver for Blackfin Two Wire Interface
++ * Copyright 2005-2007 Analog Devices Inc.
+ *
+- * Author: sonicz <sonic.zhang at analog.com>
++ * Enter bugs at http://blackfin.uclinux.org/
+ *
+- * Copyright (c) 2005-2007 Analog Devices, Inc.
+- *
+- * 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
++ * Licensed under the GPL-2 or later.
+ */
+
+ #include <linux/module.h>
+@@ -34,14 +20,16 @@
+ #include <linux/platform_device.h>
+
+ #include <asm/blackfin.h>
++#include <asm/portmux.h>
+ #include <asm/irq.h>
+
+ #define POLL_TIMEOUT (2 * HZ)
+
+ /* SMBus mode*/
+-#define TWI_I2C_MODE_STANDARD 0x01
+-#define TWI_I2C_MODE_STANDARDSUB 0x02
+-#define TWI_I2C_MODE_COMBINED 0x04
++#define TWI_I2C_MODE_STANDARD 1
++#define TWI_I2C_MODE_STANDARDSUB 2
++#define TWI_I2C_MODE_COMBINED 3
++#define TWI_I2C_MODE_REPEAT 4
+
+ struct bfin_twi_iface {
+ int irq;
+@@ -58,39 +46,74 @@ struct bfin_twi_iface {
+ struct timer_list timeout_timer;
+ struct i2c_adapter adap;
+ struct completion complete;
++ struct i2c_msg *pmsg;
++ int msg_num;
++ int cur_msg;
++ void __iomem *regs_base;
+ };
+
+-static struct bfin_twi_iface twi_iface;
++
++#define DEFINE_TWI_REG(reg, off) \
++static inline u16 read_##reg(struct bfin_twi_iface *iface) \
++ { return bfin_read16(iface->regs_base + (off)); } \
++static inline void write_##reg(struct bfin_twi_iface *iface, u16 v) \
++ { bfin_write16(iface->regs_base + (off), v); }
++
++DEFINE_TWI_REG(CLKDIV, 0x00)
++DEFINE_TWI_REG(CONTROL, 0x04)
++DEFINE_TWI_REG(SLAVE_CTL, 0x08)
++DEFINE_TWI_REG(SLAVE_STAT, 0x0C)
++DEFINE_TWI_REG(SLAVE_ADDR, 0x10)
++DEFINE_TWI_REG(MASTER_CTL, 0x14)
++DEFINE_TWI_REG(MASTER_STAT, 0x18)
++DEFINE_TWI_REG(MASTER_ADDR, 0x1C)
++DEFINE_TWI_REG(INT_STAT, 0x20)
++DEFINE_TWI_REG(INT_MASK, 0x24)
++DEFINE_TWI_REG(FIFO_CTL, 0x28)
++DEFINE_TWI_REG(FIFO_STAT, 0x2C)
++DEFINE_TWI_REG(XMT_DATA8, 0x80)
++DEFINE_TWI_REG(XMT_DATA16, 0x84)
++DEFINE_TWI_REG(RCV_DATA8, 0x88)
++DEFINE_TWI_REG(RCV_DATA16, 0x8C)
++
++static const u16 pin_req[2][3] = {
++ {P_TWI0_SCL, P_TWI0_SDA, 0},
++ {P_TWI1_SCL, P_TWI1_SDA, 0},
++};
+
+ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
+ {
+- unsigned short twi_int_status = bfin_read_TWI_INT_STAT();
+- unsigned short mast_stat = bfin_read_TWI_MASTER_STAT();
++ unsigned short twi_int_status = read_INT_STAT(iface);
++ unsigned short mast_stat = read_MASTER_STAT(iface);
+
+ if (twi_int_status & XMTSERV) {
+ /* Transmit next data */
+ if (iface->writeNum > 0) {
+- bfin_write_TWI_XMT_DATA8(*(iface->transPtr++));
++ write_XMT_DATA8(iface, *(iface->transPtr++));
+ iface->writeNum--;
+ }
+ /* start receive immediately after complete sending in
+ * combine mode.
+ */
+- else if (iface->cur_mode == TWI_I2C_MODE_COMBINED) {
+- bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
+- | MDIR | RSTART);
+- } else if (iface->manual_stop)
+- bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
+- | STOP);
++ else if (iface->cur_mode == TWI_I2C_MODE_COMBINED)
++ write_MASTER_CTL(iface,
++ read_MASTER_CTL(iface) | MDIR | RSTART);
++ else if (iface->manual_stop)
++ write_MASTER_CTL(iface,
++ read_MASTER_CTL(iface) | STOP);
++ else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
++ iface->cur_msg+1 < iface->msg_num)
++ write_MASTER_CTL(iface,
++ read_MASTER_CTL(iface) | RSTART);
+ SSYNC();
+ /* Clear status */
+- bfin_write_TWI_INT_STAT(XMTSERV);
++ write_INT_STAT(iface, XMTSERV);
+ SSYNC();
+ }
+ if (twi_int_status & RCVSERV) {
+ if (iface->readNum > 0) {
+ /* Receive next data */
+- *(iface->transPtr) = bfin_read_TWI_RCV_DATA8();
++ *(iface->transPtr) = read_RCV_DATA8(iface);
+ if (iface->cur_mode == TWI_I2C_MODE_COMBINED) {
+ /* Change combine mode into sub mode after
+ * read first data.
+@@ -105,28 +128,33 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
+ iface->transPtr++;
+ iface->readNum--;
+ } else if (iface->manual_stop) {
+- bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
+- | STOP);
++ write_MASTER_CTL(iface,
++ read_MASTER_CTL(iface) | STOP);
++ SSYNC();
++ } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
++ iface->cur_msg+1 < iface->msg_num) {
++ write_MASTER_CTL(iface,
++ read_MASTER_CTL(iface) | RSTART);
+ SSYNC();
+ }
+ /* Clear interrupt source */
+- bfin_write_TWI_INT_STAT(RCVSERV);
++ write_INT_STAT(iface, RCVSERV);
+ SSYNC();
+ }
+ if (twi_int_status & MERR) {
+- bfin_write_TWI_INT_STAT(MERR);
+- bfin_write_TWI_INT_MASK(0);
+- bfin_write_TWI_MASTER_STAT(0x3e);
+- bfin_write_TWI_MASTER_CTL(0);
++ write_INT_STAT(iface, MERR);
++ write_INT_MASK(iface, 0);
++ write_MASTER_STAT(iface, 0x3e);
++ write_MASTER_CTL(iface, 0);
+ SSYNC();
+- iface->result = -1;
++ iface->result = -EIO;
+ /* if both err and complete int stats are set, return proper
+ * results.
+ */
+ if (twi_int_status & MCOMP) {
+- bfin_write_TWI_INT_STAT(MCOMP);
+- bfin_write_TWI_INT_MASK(0);
+- bfin_write_TWI_MASTER_CTL(0);
++ write_INT_STAT(iface, MCOMP);
++ write_INT_MASK(iface, 0);
++ write_MASTER_CTL(iface, 0);
+ SSYNC();
+ /* If it is a quick transfer, only address bug no data,
+ * not an err, return 1.
+@@ -143,7 +171,7 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
+ return;
+ }
+ if (twi_int_status & MCOMP) {
+- bfin_write_TWI_INT_STAT(MCOMP);
++ write_INT_STAT(iface, MCOMP);
+ SSYNC();
+ if (iface->cur_mode == TWI_I2C_MODE_COMBINED) {
+ if (iface->readNum == 0) {
+@@ -152,28 +180,63 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
+ */
+ iface->readNum = 1;
+ iface->manual_stop = 1;
+- bfin_write_TWI_MASTER_CTL(
+- bfin_read_TWI_MASTER_CTL()
+- | (0xff << 6));
++ write_MASTER_CTL(iface,
++ read_MASTER_CTL(iface) | (0xff << 6));
+ } else {
+ /* set the readd number in other
+ * combine mode.
+ */
+- bfin_write_TWI_MASTER_CTL(
+- (bfin_read_TWI_MASTER_CTL() &
++ write_MASTER_CTL(iface,
++ (read_MASTER_CTL(iface) &
+ (~(0xff << 6))) |
+- ( iface->readNum << 6));
++ (iface->readNum << 6));
++ }
++ /* remove restart bit and enable master receive */
++ write_MASTER_CTL(iface,
++ read_MASTER_CTL(iface) & ~RSTART);
++ write_MASTER_CTL(iface,
++ read_MASTER_CTL(iface) | MEN | MDIR);
++ SSYNC();
++ } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
++ iface->cur_msg+1 < iface->msg_num) {
++ iface->cur_msg++;
++ iface->transPtr = iface->pmsg[iface->cur_msg].buf;
++ iface->writeNum = iface->readNum =
++ iface->pmsg[iface->cur_msg].len;
++ /* Set Transmit device address */
++ write_MASTER_ADDR(iface,
++ iface->pmsg[iface->cur_msg].addr);
++ if (iface->pmsg[iface->cur_msg].flags & I2C_M_RD)
++ iface->read_write = I2C_SMBUS_READ;
++ else {
++ iface->read_write = I2C_SMBUS_WRITE;
++ /* Transmit first data */
++ if (iface->writeNum > 0) {
++ write_XMT_DATA8(iface,
++ *(iface->transPtr++));
++ iface->writeNum--;
++ SSYNC();
++ }
++ }
++
++ if (iface->pmsg[iface->cur_msg].len <= 255)
++ write_MASTER_CTL(iface,
++ iface->pmsg[iface->cur_msg].len << 6);
++ else {
++ write_MASTER_CTL(iface, 0xff << 6);
++ iface->manual_stop = 1;
+ }
+ /* remove restart bit and enable master receive */
+- bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() &
+- ~RSTART);
+- bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() |
+- MEN | MDIR);
++ write_MASTER_CTL(iface,
++ read_MASTER_CTL(iface) & ~RSTART);
++ write_MASTER_CTL(iface, read_MASTER_CTL(iface) |
++ MEN | ((iface->read_write == I2C_SMBUS_READ) ?
++ MDIR : 0));
+ SSYNC();
+ } else {
+ iface->result = 1;
+- bfin_write_TWI_INT_MASK(0);
+- bfin_write_TWI_MASTER_CTL(0);
++ write_INT_MASK(iface, 0);
++ write_MASTER_CTL(iface, 0);
+ SSYNC();
+ complete(&iface->complete);
+ }
+@@ -221,91 +284,85 @@ static int bfin_twi_master_xfer(struct i2c_adapter *adap,
+ {
+ struct bfin_twi_iface *iface = adap->algo_data;
+ struct i2c_msg *pmsg;
+- int i, ret;
+ int rc = 0;
+
+- if (!(bfin_read_TWI_CONTROL() & TWI_ENA))
++ if (!(read_CONTROL(iface) & TWI_ENA))
+ return -ENXIO;
+
+- while (bfin_read_TWI_MASTER_STAT() & BUSBUSY) {
++ while (read_MASTER_STAT(iface) & BUSBUSY)
+ yield();
++
++ iface->pmsg = msgs;
++ iface->msg_num = num;
++ iface->cur_msg = 0;
++
++ pmsg = &msgs[0];
++ if (pmsg->flags & I2C_M_TEN) {
++ dev_err(&adap->dev, "10 bits addr not supported!\n");
++ return -EINVAL;
+ }
+
+- ret = 0;
+- for (i = 0; rc >= 0 && i < num; i++) {
+- pmsg = &msgs[i];
+- if (pmsg->flags & I2C_M_TEN) {
+- dev_err(&(adap->dev), "i2c-bfin-twi: 10 bits addr "
+- "not supported !\n");
+- rc = -EINVAL;
+- break;
+- }
++ iface->cur_mode = TWI_I2C_MODE_REPEAT;
++ iface->manual_stop = 0;
++ iface->transPtr = pmsg->buf;
++ iface->writeNum = iface->readNum = pmsg->len;
++ iface->result = 0;
++ iface->timeout_count = 10;
++ init_completion(&(iface->complete));
++ /* Set Transmit device address */
++ write_MASTER_ADDR(iface, pmsg->addr);
+
+- iface->cur_mode = TWI_I2C_MODE_STANDARD;
+- iface->manual_stop = 0;
+- iface->transPtr = pmsg->buf;
+- iface->writeNum = iface->readNum = pmsg->len;
+- iface->result = 0;
+- iface->timeout_count = 10;
+- /* Set Transmit device address */
+- bfin_write_TWI_MASTER_ADDR(pmsg->addr);
+-
+- /* FIFO Initiation. Data in FIFO should be
+- * discarded before start a new operation.
+- */
+- bfin_write_TWI_FIFO_CTL(0x3);
+- SSYNC();
+- bfin_write_TWI_FIFO_CTL(0);
+- SSYNC();
++ /* FIFO Initiation. Data in FIFO should be
++ * discarded before start a new operation.
++ */
++ write_FIFO_CTL(iface, 0x3);
++ SSYNC();
++ write_FIFO_CTL(iface, 0);
++ SSYNC();
+
+- if (pmsg->flags & I2C_M_RD)
+- iface->read_write = I2C_SMBUS_READ;
+- else {
+- iface->read_write = I2C_SMBUS_WRITE;
+- /* Transmit first data */
+- if (iface->writeNum > 0) {
+- bfin_write_TWI_XMT_DATA8(*(iface->transPtr++));
+- iface->writeNum--;
+- SSYNC();
+- }
++ if (pmsg->flags & I2C_M_RD)
++ iface->read_write = I2C_SMBUS_READ;
++ else {
++ iface->read_write = I2C_SMBUS_WRITE;
++ /* Transmit first data */
++ if (iface->writeNum > 0) {
++ write_XMT_DATA8(iface, *(iface->transPtr++));
++ iface->writeNum--;
++ SSYNC();
+ }
++ }
+
+- /* clear int stat */
+- bfin_write_TWI_INT_STAT(MERR|MCOMP|XMTSERV|RCVSERV);
++ /* clear int stat */
++ write_INT_STAT(iface, MERR | MCOMP | XMTSERV | RCVSERV);
+
+- /* Interrupt mask . Enable XMT, RCV interrupt */
+- bfin_write_TWI_INT_MASK(MCOMP | MERR |
+- ((iface->read_write == I2C_SMBUS_READ)?
+- RCVSERV : XMTSERV));
+- SSYNC();
++ /* Interrupt mask . Enable XMT, RCV interrupt */
++ write_INT_MASK(iface, MCOMP | MERR | RCVSERV | XMTSERV);
++ SSYNC();
+
+- if (pmsg->len > 0 && pmsg->len <= 255)
+- bfin_write_TWI_MASTER_CTL(pmsg->len << 6);
+- else if (pmsg->len > 255) {
+- bfin_write_TWI_MASTER_CTL(0xff << 6);
+- iface->manual_stop = 1;
+- } else
+- break;
++ if (pmsg->len <= 255)
++ write_MASTER_CTL(iface, pmsg->len << 6);
++ else {
++ write_MASTER_CTL(iface, 0xff << 6);
++ iface->manual_stop = 1;
++ }
+
+- iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
+- add_timer(&iface->timeout_timer);
++ iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
++ add_timer(&iface->timeout_timer);
+
+- /* Master enable */
+- bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
+- ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) |
+- ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0));
+- SSYNC();
++ /* Master enable */
++ write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN |
++ ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) |
++ ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0));
++ SSYNC();
+
+- wait_for_completion(&iface->complete);
++ wait_for_completion(&iface->complete);
+
+- rc = iface->result;
+- if (rc == 1)
+- ret++;
+- else if (rc == -1)
+- break;
+- }
++ rc = iface->result;
+
+- return ret;
++ if (rc == 1)
++ return num;
++ else
++ return rc;
+ }
+
+ /*
+@@ -319,12 +376,11 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
+ struct bfin_twi_iface *iface = adap->algo_data;
+ int rc = 0;
+
+- if (!(bfin_read_TWI_CONTROL() & TWI_ENA))
++ if (!(read_CONTROL(iface) & TWI_ENA))
+ return -ENXIO;
+
+- while (bfin_read_TWI_MASTER_STAT() & BUSBUSY) {
++ while (read_MASTER_STAT(iface) & BUSBUSY)
+ yield();
+- }
+
+ iface->writeNum = 0;
+ iface->readNum = 0;
+@@ -392,19 +448,20 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
+ iface->read_write = read_write;
+ iface->command = command;
+ iface->timeout_count = 10;
++ init_completion(&(iface->complete));
+
+ /* FIFO Initiation. Data in FIFO should be discarded before
+ * start a new operation.
+ */
+- bfin_write_TWI_FIFO_CTL(0x3);
++ write_FIFO_CTL(iface, 0x3);
+ SSYNC();
+- bfin_write_TWI_FIFO_CTL(0);
++ write_FIFO_CTL(iface, 0);
+
+ /* clear int stat */
+- bfin_write_TWI_INT_STAT(MERR|MCOMP|XMTSERV|RCVSERV);
++ write_INT_STAT(iface, MERR | MCOMP | XMTSERV | RCVSERV);
+
+ /* Set Transmit device address */
+- bfin_write_TWI_MASTER_ADDR(addr);
++ write_MASTER_ADDR(iface, addr);
+ SSYNC();
+
+ iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
+@@ -412,60 +469,64 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
+
+ switch (iface->cur_mode) {
+ case TWI_I2C_MODE_STANDARDSUB:
+- bfin_write_TWI_XMT_DATA8(iface->command);
+- bfin_write_TWI_INT_MASK(MCOMP | MERR |
++ write_XMT_DATA8(iface, iface->command);
++ write_INT_MASK(iface, MCOMP | MERR |
+ ((iface->read_write == I2C_SMBUS_READ) ?
+ RCVSERV : XMTSERV));
+ SSYNC();
+
+ if (iface->writeNum + 1 <= 255)
+- bfin_write_TWI_MASTER_CTL((iface->writeNum + 1) << 6);
++ write_MASTER_CTL(iface, (iface->writeNum + 1) << 6);
+ else {
+- bfin_write_TWI_MASTER_CTL(0xff << 6);
++ write_MASTER_CTL(iface, 0xff << 6);
+ iface->manual_stop = 1;
+ }
+ /* Master enable */
+- bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
++ write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN |
+ ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0));
+ break;
+ case TWI_I2C_MODE_COMBINED:
+- bfin_write_TWI_XMT_DATA8(iface->command);
+- bfin_write_TWI_INT_MASK(MCOMP | MERR | RCVSERV | XMTSERV);
++ write_XMT_DATA8(iface, iface->command);
++ write_INT_MASK(iface, MCOMP | MERR | RCVSERV | XMTSERV);
+ SSYNC();
+
+ if (iface->writeNum > 0)
+- bfin_write_TWI_MASTER_CTL((iface->writeNum + 1) << 6);
++ write_MASTER_CTL(iface, (iface->writeNum + 1) << 6);
+ else
+- bfin_write_TWI_MASTER_CTL(0x1 << 6);
++ write_MASTER_CTL(iface, 0x1 << 6);
+ /* Master enable */
+- bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
++ write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN |
+ ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0));
+ break;
+ default:
+- bfin_write_TWI_MASTER_CTL(0);
++ write_MASTER_CTL(iface, 0);
+ if (size != I2C_SMBUS_QUICK) {
+ /* Don't access xmit data register when this is a
+ * read operation.
+ */
+ if (iface->read_write != I2C_SMBUS_READ) {
+ if (iface->writeNum > 0) {
+- bfin_write_TWI_XMT_DATA8(*(iface->transPtr++));
++ write_XMT_DATA8(iface,
++ *(iface->transPtr++));
+ if (iface->writeNum <= 255)
+- bfin_write_TWI_MASTER_CTL(iface->writeNum << 6);
++ write_MASTER_CTL(iface,
++ iface->writeNum << 6);
+ else {
+- bfin_write_TWI_MASTER_CTL(0xff << 6);
++ write_MASTER_CTL(iface,
++ 0xff << 6);
+ iface->manual_stop = 1;
+ }
+ iface->writeNum--;
+ } else {
+- bfin_write_TWI_XMT_DATA8(iface->command);
+- bfin_write_TWI_MASTER_CTL(1 << 6);
++ write_XMT_DATA8(iface, iface->command);
++ write_MASTER_CTL(iface, 1 << 6);
+ }
+ } else {
+ if (iface->readNum > 0 && iface->readNum <= 255)
+- bfin_write_TWI_MASTER_CTL(iface->readNum << 6);
++ write_MASTER_CTL(iface,
++ iface->readNum << 6);
+ else if (iface->readNum > 255) {
+- bfin_write_TWI_MASTER_CTL(0xff << 6);
++ write_MASTER_CTL(iface, 0xff << 6);
+ iface->manual_stop = 1;
+ } else {
+ del_timer(&iface->timeout_timer);
+@@ -473,13 +534,13 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
+ }
+ }
+ }
+- bfin_write_TWI_INT_MASK(MCOMP | MERR |
++ write_INT_MASK(iface, MCOMP | MERR |
+ ((iface->read_write == I2C_SMBUS_READ) ?
+ RCVSERV : XMTSERV));
+ SSYNC();
+
+ /* Master enable */
+- bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
++ write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN |
+ ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) |
+ ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0));
+ break;
+@@ -514,10 +575,10 @@ static struct i2c_algorithm bfin_twi_algorithm = {
+
+ static int i2c_bfin_twi_suspend(struct platform_device *dev, pm_message_t state)
+ {
+-/* struct bfin_twi_iface *iface = platform_get_drvdata(dev);*/
++ struct bfin_twi_iface *iface = platform_get_drvdata(dev);
+
+ /* Disable TWI */
+- bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() & ~TWI_ENA);
++ write_CONTROL(iface, read_CONTROL(iface) & ~TWI_ENA);
+ SSYNC();
+
+ return 0;
+@@ -525,24 +586,52 @@ static int i2c_bfin_twi_suspend(struct platform_device *dev, pm_message_t state)
+
+ static int i2c_bfin_twi_resume(struct platform_device *dev)
+ {
+-/* struct bfin_twi_iface *iface = platform_get_drvdata(dev);*/
++ struct bfin_twi_iface *iface = platform_get_drvdata(dev);
+
+ /* Enable TWI */
+- bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() | TWI_ENA);
++ write_CONTROL(iface, read_CONTROL(iface) | TWI_ENA);
+ SSYNC();
+
+ return 0;
+ }
+
+-static int i2c_bfin_twi_probe(struct platform_device *dev)
++static int i2c_bfin_twi_probe(struct platform_device *pdev)
+ {
+- struct bfin_twi_iface *iface = &twi_iface;
++ struct bfin_twi_iface *iface;
+ struct i2c_adapter *p_adap;
++ struct resource *res;
+ int rc;
+
++ iface = kzalloc(sizeof(struct bfin_twi_iface), GFP_KERNEL);
++ if (!iface) {
++ dev_err(&pdev->dev, "Cannot allocate memory\n");
++ rc = -ENOMEM;
++ goto out_error_nomem;
++ }
++
+ spin_lock_init(&(iface->lock));
+- init_completion(&(iface->complete));
+- iface->irq = IRQ_TWI;
++
++ /* Find and map our resources */
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (res == NULL) {
++ dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
++ rc = -ENOENT;
++ goto out_error_get_res;
++ }
++
++ iface->regs_base = ioremap(res->start, res->end - res->start + 1);
++ if (iface->regs_base == NULL) {
++ dev_err(&pdev->dev, "Cannot map IO\n");
++ rc = -ENXIO;
++ goto out_error_ioremap;
++ }
++
++ iface->irq = platform_get_irq(pdev, 0);
++ if (iface->irq < 0) {
++ dev_err(&pdev->dev, "No IRQ specified\n");
++ rc = -ENOENT;
++ goto out_error_no_irq;
++ }
+
+ init_timer(&(iface->timeout_timer));
+ iface->timeout_timer.function = bfin_twi_timeout;
+@@ -550,39 +639,63 @@ static int i2c_bfin_twi_probe(struct platform_device *dev)
+
+ p_adap = &iface->adap;
+ p_adap->id = I2C_HW_BLACKFIN;
+- p_adap->nr = dev->id;
+- strlcpy(p_adap->name, dev->name, sizeof(p_adap->name));
++ p_adap->nr = pdev->id;
++ strlcpy(p_adap->name, pdev->name, sizeof(p_adap->name));
+ p_adap->algo = &bfin_twi_algorithm;
+ p_adap->algo_data = iface;
+ p_adap->class = I2C_CLASS_ALL;
+- p_adap->dev.parent = &dev->dev;
++ p_adap->dev.parent = &pdev->dev;
++
++ rc = peripheral_request_list(pin_req[pdev->id], "i2c-bfin-twi");
++ if (rc) {
++ dev_err(&pdev->dev, "Can't setup pin mux!\n");
++ goto out_error_pin_mux;
++ }
+
+ rc = request_irq(iface->irq, bfin_twi_interrupt_entry,
+- IRQF_DISABLED, dev->name, iface);
++ IRQF_DISABLED, pdev->name, iface);
+ if (rc) {
+- dev_err(&(p_adap->dev), "i2c-bfin-twi: can't get IRQ %d !\n",
+- iface->irq);
+- return -ENODEV;
++ dev_err(&pdev->dev, "Can't get IRQ %d !\n", iface->irq);
++ rc = -ENODEV;
++ goto out_error_req_irq;
+ }
+
+ /* Set TWI internal clock as 10MHz */
+- bfin_write_TWI_CONTROL(((get_sclk() / 1024 / 1024 + 5) / 10) & 0x7F);
++ write_CONTROL(iface, ((get_sclk() / 1024 / 1024 + 5) / 10) & 0x7F);
+
+ /* Set Twi interface clock as specified */
+- bfin_write_TWI_CLKDIV((( 5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ )
+- << 8) | (( 5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ )
++ write_CLKDIV(iface, ((5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ)
++ << 8) | ((5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ)
+ & 0xFF));
+
+ /* Enable TWI */
+- bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() | TWI_ENA);
++ write_CONTROL(iface, read_CONTROL(iface) | TWI_ENA);
+ SSYNC();
+
+ rc = i2c_add_numbered_adapter(p_adap);
+- if (rc < 0)
+- free_irq(iface->irq, iface);
+- else
+- platform_set_drvdata(dev, iface);
++ if (rc < 0) {
++ dev_err(&pdev->dev, "Can't add i2c adapter!\n");
++ goto out_error_add_adapter;
++ }
++
++ platform_set_drvdata(pdev, iface);
+
++ dev_info(&pdev->dev, "Blackfin BF5xx on-chip I2C TWI Contoller, "
++ "regs_base@%p\n", iface->regs_base);
++
++ return 0;
++
++out_error_add_adapter:
++ free_irq(iface->irq, iface);
++out_error_req_irq:
++out_error_no_irq:
++ peripheral_free_list(pin_req[pdev->id]);
++out_error_pin_mux:
++ iounmap(iface->regs_base);
++out_error_ioremap:
++out_error_get_res:
++ kfree(iface);
++out_error_nomem:
+ return rc;
+ }
+
+@@ -594,6 +707,9 @@ static int i2c_bfin_twi_remove(struct platform_device *pdev)
+
+ i2c_del_adapter(&(iface->adap));
+ free_irq(iface->irq, iface);
++ peripheral_free_list(pin_req[pdev->id]);
++ iounmap(iface->regs_base);
++ kfree(iface);
+
+ return 0;
+ }
+@@ -611,8 +727,6 @@ static struct platform_driver i2c_bfin_twi_driver = {
+
+ static int __init i2c_bfin_twi_init(void)
+ {
+- pr_info("I2C: Blackfin I2C TWI driver\n");
+-
+ return platform_driver_register(&i2c_bfin_twi_driver);
+ }
+
+@@ -621,9 +735,10 @@ static void __exit i2c_bfin_twi_exit(void)
+ platform_driver_unregister(&i2c_bfin_twi_driver);
+ }
+
+-MODULE_AUTHOR("Sonic Zhang <sonic.zhang at analog.com>");
+-MODULE_DESCRIPTION("I2C-Bus adapter routines for Blackfin TWI");
+-MODULE_LICENSE("GPL");
+-
+ module_init(i2c_bfin_twi_init);
+ module_exit(i2c_bfin_twi_exit);
++
++MODULE_AUTHOR("Bryan Wu, Sonic Zhang");
++MODULE_DESCRIPTION("Blackfin BF5xx on-chip I2C TWI Contoller Driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:i2c-bfin-twi");
+diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
+index fde2634..7ecbfc4 100644
+--- a/drivers/i2c/busses/i2c-davinci.c
++++ b/drivers/i2c/busses/i2c-davinci.c
+@@ -328,7 +328,7 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+ int i;
+ int ret;
+
+- dev_dbg(dev->dev, "%s: msgs: %d\n", __FUNCTION__, num);
++ dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);
+
+ ret = i2c_davinci_wait_bus_not_busy(dev, 1);
+ if (ret < 0) {
+@@ -342,7 +342,7 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+ return ret;
+ }
+
+- dev_dbg(dev->dev, "%s:%d ret: %d\n", __FUNCTION__, __LINE__, ret);
++ dev_dbg(dev->dev, "%s:%d ret: %d\n", __func__, __LINE__, ret);
+
+ return num;
+ }
+@@ -364,7 +364,7 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
+ u16 w;
+
+ while ((stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG))) {
+- dev_dbg(dev->dev, "%s: stat=0x%x\n", __FUNCTION__, stat);
++ dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat);
+ if (count++ == 100) {
+ dev_warn(dev->dev, "Too much work in one IRQ\n");
+ break;
+@@ -553,6 +553,9 @@ static int davinci_i2c_remove(struct platform_device *pdev)
+ return 0;
+ }
+
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:i2c_davinci");
++
+ static struct platform_driver davinci_i2c_driver = {
+ .probe = davinci_i2c_probe,
+ .remove = davinci_i2c_remove,
+diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
+index 3ca19fc..7c1b762 100644
+--- a/drivers/i2c/busses/i2c-gpio.c
++++ b/drivers/i2c/busses/i2c-gpio.c
+@@ -220,3 +220,4 @@ module_exit(i2c_gpio_exit);
+ MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen at atmel.com>");
+ MODULE_DESCRIPTION("Platform-independent bitbanging I2C driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:i2c-gpio");
+diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
+index 22bb247..85dbf34 100644
+--- a/drivers/i2c/busses/i2c-ibm_iic.c
++++ b/drivers/i2c/busses/i2c-ibm_iic.c
+@@ -6,6 +6,9 @@
+ * Copyright (c) 2003, 2004 Zultys Technologies.
+ * Eugene Surovegin <eugene.surovegin at zultys.com> or <ebs at ebshome.net>
+ *
++ * Copyright (c) 2008 PIKA Technologies
++ * Sean MacLennan <smaclennan at pikatech.com>
++ *
+ * Based on original work by
+ * Ian DaSilva <idasilva at mvista.com>
+ * Armin Kuster <akuster at mvista.com>
+@@ -39,12 +42,17 @@
+ #include <asm/io.h>
+ #include <linux/i2c.h>
+ #include <linux/i2c-id.h>
++
++#ifdef CONFIG_IBM_OCP
+ #include <asm/ocp.h>
+ #include <asm/ibm4xx.h>
++#else
++#include <linux/of_platform.h>
++#endif
+
+ #include "i2c-ibm_iic.h"
+
+-#define DRIVER_VERSION "2.1"
++#define DRIVER_VERSION "2.2"
+
+ MODULE_DESCRIPTION("IBM IIC driver v" DRIVER_VERSION);
+ MODULE_LICENSE("GPL");
+@@ -650,13 +658,14 @@ static inline u8 iic_clckdiv(unsigned int opb)
+ opb /= 1000000;
+
+ if (opb < 20 || opb > 150){
+- printk(KERN_CRIT "ibm-iic: invalid OPB clock frequency %u MHz\n",
++ printk(KERN_WARNING "ibm-iic: invalid OPB clock frequency %u MHz\n",
+ opb);
+ opb = opb < 20 ? 20 : 150;
+ }
+ return (u8)((opb + 9) / 10 - 1);
+ }
+
++#ifdef CONFIG_IBM_OCP
+ /*
+ * Register single IIC interface
+ */
+@@ -672,7 +681,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
+ ocp->def->index);
+
+ if (!(dev = kzalloc(sizeof(*dev), GFP_KERNEL))) {
+- printk(KERN_CRIT "ibm-iic%d: failed to allocate device data\n",
++ printk(KERN_ERR "ibm-iic%d: failed to allocate device data\n",
+ ocp->def->index);
+ return -ENOMEM;
+ }
+@@ -687,7 +696,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
+ }
+
+ if (!(dev->vaddr = ioremap(ocp->def->paddr, sizeof(struct iic_regs)))){
+- printk(KERN_CRIT "ibm-iic%d: failed to ioremap device registers\n",
++ printk(KERN_ERR "ibm-iic%d: failed to ioremap device registers\n",
+ dev->idx);
+ ret = -ENXIO;
+ goto fail2;
+@@ -745,7 +754,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
+ adap->nr = dev->idx >= 0 ? dev->idx : 0;
+
+ if ((ret = i2c_add_numbered_adapter(adap)) < 0) {
+- printk(KERN_CRIT "ibm-iic%d: failed to register i2c adapter\n",
++ printk(KERN_ERR "ibm-iic%d: failed to register i2c adapter\n",
+ dev->idx);
+ goto fail;
+ }
+@@ -778,7 +787,7 @@ static void __devexit iic_remove(struct ocp_device *ocp)
+ struct ibm_iic_private* dev = (struct ibm_iic_private*)ocp_get_drvdata(ocp);
+ BUG_ON(dev == NULL);
+ if (i2c_del_adapter(&dev->adap)){
+- printk(KERN_CRIT "ibm-iic%d: failed to delete i2c adapter :(\n",
++ printk(KERN_ERR "ibm-iic%d: failed to delete i2c adapter :(\n",
+ dev->idx);
+ /* That's *very* bad, just shutdown IRQ ... */
+ if (dev->irq >= 0){
+@@ -828,5 +837,181 @@ static void __exit iic_exit(void)
+ ocp_unregister_driver(&ibm_iic_driver);
+ }
+
++#else /* !CONFIG_IBM_OCP */
++
++static int __devinit iic_request_irq(struct of_device *ofdev,
++ struct ibm_iic_private *dev)
++{
++ struct device_node *np = ofdev->node;
++ int irq;
++
++ if (iic_force_poll)
++ return NO_IRQ;
++
++ irq = irq_of_parse_and_map(np, 0);
++ if (irq == NO_IRQ) {
++ dev_err(&ofdev->dev, "irq_of_parse_and_map failed\n");
++ return NO_IRQ;
++ }
++
++ /* Disable interrupts until we finish initialization, assumes
++ * level-sensitive IRQ setup...
++ */
++ iic_interrupt_mode(dev, 0);
++ if (request_irq(irq, iic_handler, 0, "IBM IIC", dev)) {
++ dev_err(&ofdev->dev, "request_irq %d failed\n", irq);
++ /* Fallback to the polling mode */
++ return NO_IRQ;
++ }
++
++ return irq;
++}
++
++/*
++ * Register single IIC interface
++ */
++static int __devinit iic_probe(struct of_device *ofdev,
++ const struct of_device_id *match)
++{
++ struct device_node *np = ofdev->node;
++ struct ibm_iic_private *dev;
++ struct i2c_adapter *adap;
++ const u32 *indexp, *freq;
++ int ret;
++
++ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
++ if (!dev) {
++ dev_err(&ofdev->dev, "failed to allocate device data\n");
++ return -ENOMEM;
++ }
++
++ dev_set_drvdata(&ofdev->dev, dev);
++
++ indexp = of_get_property(np, "index", NULL);
++ if (!indexp) {
++ dev_err(&ofdev->dev, "no index specified\n");
++ ret = -EINVAL;
++ goto error_cleanup;
++ }
++ dev->idx = *indexp;
++
++ dev->vaddr = of_iomap(np, 0);
++ if (dev->vaddr == NULL) {
++ dev_err(&ofdev->dev, "failed to iomap device\n");
++ ret = -ENXIO;
++ goto error_cleanup;
++ }
++
++ init_waitqueue_head(&dev->wq);
++
++ dev->irq = iic_request_irq(ofdev, dev);
++ if (dev->irq == NO_IRQ)
++ dev_warn(&ofdev->dev, "using polling mode\n");
++
++ /* Board specific settings */
++ if (iic_force_fast || of_get_property(np, "fast-mode", NULL))
++ dev->fast_mode = 1;
++
++ freq = of_get_property(np, "clock-frequency", NULL);
++ if (freq == NULL) {
++ freq = of_get_property(np->parent, "clock-frequency", NULL);
++ if (freq == NULL) {
++ dev_err(&ofdev->dev, "Unable to get bus frequency\n");
++ ret = -EINVAL;
++ goto error_cleanup;
++ }
++ }
++
++ dev->clckdiv = iic_clckdiv(*freq);
++ dev_dbg(&ofdev->dev, "clckdiv = %d\n", dev->clckdiv);
++
++ /* Initialize IIC interface */
++ iic_dev_init(dev);
++
++ /* Register it with i2c layer */
++ adap = &dev->adap;
++ adap->dev.parent = &ofdev->dev;
++ strlcpy(adap->name, "IBM IIC", sizeof(adap->name));
++ i2c_set_adapdata(adap, dev);
++ adap->id = I2C_HW_OCP;
++ adap->class = I2C_CLASS_HWMON;
++ adap->algo = &iic_algo;
++ adap->timeout = 1;
++ adap->nr = dev->idx;
++
++ ret = i2c_add_numbered_adapter(adap);
++ if (ret < 0) {
++ dev_err(&ofdev->dev, "failed to register i2c adapter\n");
++ goto error_cleanup;
++ }
++
++ dev_info(&ofdev->dev, "using %s mode\n",
++ dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
++
++ return 0;
++
++error_cleanup:
++ if (dev->irq != NO_IRQ) {
++ iic_interrupt_mode(dev, 0);
++ free_irq(dev->irq, dev);
++ }
++
++ if (dev->vaddr)
++ iounmap(dev->vaddr);
++
++ dev_set_drvdata(&ofdev->dev, NULL);
++ kfree(dev);
++ return ret;
++}
++
++/*
++ * Cleanup initialized IIC interface
++ */
++static int __devexit iic_remove(struct of_device *ofdev)
++{
++ struct ibm_iic_private *dev = dev_get_drvdata(&ofdev->dev);
++
++ dev_set_drvdata(&ofdev->dev, NULL);
++
++ i2c_del_adapter(&dev->adap);
++
++ if (dev->irq != NO_IRQ) {
++ iic_interrupt_mode(dev, 0);
++ free_irq(dev->irq, dev);
++ }
++
++ iounmap(dev->vaddr);
++ kfree(dev);
++
++ return 0;
++}
++
++static const struct of_device_id ibm_iic_match[] = {
++ { .compatible = "ibm,iic-405ex", },
++ { .compatible = "ibm,iic-405gp", },
++ { .compatible = "ibm,iic-440gp", },
++ { .compatible = "ibm,iic-440gpx", },
++ { .compatible = "ibm,iic-440grx", },
++ {}
++};
++
++static struct of_platform_driver ibm_iic_driver = {
++ .name = "ibm-iic",
++ .match_table = ibm_iic_match,
++ .probe = iic_probe,
++ .remove = __devexit_p(iic_remove),
++};
++
++static int __init iic_init(void)
++{
++ return of_register_platform_driver(&ibm_iic_driver);
++}
++
++static void __exit iic_exit(void)
++{
++ of_unregister_platform_driver(&ibm_iic_driver);
++}
++#endif /* CONFIG_IBM_OCP */
++
+ module_init(iic_init);
+ module_exit(iic_exit);
+diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
+index ab41400..39884e7 100644
+--- a/drivers/i2c/busses/i2c-iop3xx.c
++++ b/drivers/i2c/busses/i2c-iop3xx.c
+@@ -550,3 +550,4 @@ module_exit (i2c_iop3xx_exit);
+ MODULE_AUTHOR("D-TACQ Solutions Ltd <www.d-tacq.com>");
+ MODULE_DESCRIPTION("IOP3xx iic algorithm and driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:IOP3xx-I2C");
+diff --git a/drivers/i2c/busses/i2c-ixp2000.c b/drivers/i2c/busses/i2c-ixp2000.c
+index 6352121..5af9e65 100644
+--- a/drivers/i2c/busses/i2c-ixp2000.c
++++ b/drivers/i2c/busses/i2c-ixp2000.c
+@@ -164,4 +164,5 @@ module_exit(ixp2000_i2c_exit);
+ MODULE_AUTHOR ("Deepak Saxena <dsaxena at plexity.net>");
+ MODULE_DESCRIPTION("IXP2000 GPIO-based I2C bus driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:IXP2000-I2C");
+
+diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
+index bbe787b..18beb0a 100644
+--- a/drivers/i2c/busses/i2c-mpc.c
++++ b/drivers/i2c/busses/i2c-mpc.c
+@@ -392,6 +392,9 @@ static int fsl_i2c_remove(struct platform_device *pdev)
+ return 0;
+ };
+
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:fsl-i2c");
++
+ /* Structure for a device driver */
+ static struct platform_driver fsl_i2c_driver = {
+ .probe = fsl_i2c_probe,
+diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
+index e417c2c..f145692 100644
+--- a/drivers/i2c/busses/i2c-ocores.c
++++ b/drivers/i2c/busses/i2c-ocores.c
+@@ -312,6 +312,9 @@ static int __devexit ocores_i2c_remove(struct platform_device* pdev)
+ return 0;
+ }
+
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:ocores-i2c");
++
+ static struct platform_driver ocores_i2c_driver = {
+ .probe = ocores_i2c_probe,
+ .remove = __devexit_p(ocores_i2c_remove),
+diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
+index 7ba3177..e7eb7bf 100644
+--- a/drivers/i2c/busses/i2c-omap.c
++++ b/drivers/i2c/busses/i2c-omap.c
+@@ -693,3 +693,4 @@ module_exit(omap_i2c_exit_driver);
+ MODULE_AUTHOR("MontaVista Software, Inc. (and others)");
+ MODULE_DESCRIPTION("TI OMAP I2C bus adapter");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:i2c_omap");
+diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c
+index 496ee87..a119784 100644
+--- a/drivers/i2c/busses/i2c-pca-isa.c
++++ b/drivers/i2c/busses/i2c-pca-isa.c
+@@ -1,6 +1,7 @@
+ /*
+ * i2c-pca-isa.c driver for PCA9564 on ISA boards
+ * Copyright (C) 2004 Arcom Control Systems
++ * Copyright (C) 2008 Pengutronix
+ *
+ * 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
+@@ -22,11 +23,9 @@
+ #include <linux/module.h>
+ #include <linux/moduleparam.h>
+ #include <linux/delay.h>
+-#include <linux/slab.h>
+ #include <linux/init.h>
+ #include <linux/interrupt.h>
+ #include <linux/wait.h>
+-
+ #include <linux/isa.h>
+ #include <linux/i2c.h>
+ #include <linux/i2c-algo-pca.h>
+@@ -34,13 +33,9 @@
+ #include <asm/io.h>
+ #include <asm/irq.h>
+
+-#include "../algos/i2c-algo-pca.h"
+-
++#define DRIVER "i2c-pca-isa"
+ #define IO_SIZE 4
+
+-#undef DEBUG_IO
+-//#define DEBUG_IO
+-
+ static unsigned long base = 0x330;
+ static int irq = 10;
+
+@@ -48,22 +43,9 @@ static int irq = 10;
+ * in the actual clock rate */
+ static int clock = I2C_PCA_CON_59kHz;
+
+-static int own = 0x55;
+-
+ static wait_queue_head_t pca_wait;
+
+-static int pca_isa_getown(struct i2c_algo_pca_data *adap)
+-{
+- return (own);
+-}
+-
+-static int pca_isa_getclock(struct i2c_algo_pca_data *adap)
+-{
+- return (clock);
+-}
+-
+-static void
+-pca_isa_writebyte(struct i2c_algo_pca_data *adap, int reg, int val)
++static void pca_isa_writebyte(void *pd, int reg, int val)
+ {
+ #ifdef DEBUG_IO
+ static char *names[] = { "T/O", "DAT", "ADR", "CON" };
+@@ -72,44 +54,49 @@ pca_isa_writebyte(struct i2c_algo_pca_data *adap, int reg, int val)
+ outb(val, base+reg);
+ }
+
+-static int
+-pca_isa_readbyte(struct i2c_algo_pca_data *adap, int reg)
++static int pca_isa_readbyte(void *pd, int reg)
+ {
+ int res = inb(base+reg);
+ #ifdef DEBUG_IO
+ {
+- static char *names[] = { "STA", "DAT", "ADR", "CON" };
++ static char *names[] = { "STA", "DAT", "ADR", "CON" };
+ printk("*** read %s => %#04x\n", names[reg], res);
+ }
+ #endif
+ return res;
+ }
+
+-static int pca_isa_waitforinterrupt(struct i2c_algo_pca_data *adap)
++static int pca_isa_waitforcompletion(void *pd)
+ {
+ int ret = 0;
+
+ if (irq > -1) {
+ ret = wait_event_interruptible(pca_wait,
+- pca_isa_readbyte(adap, I2C_PCA_CON) & I2C_PCA_CON_SI);
++ pca_isa_readbyte(pd, I2C_PCA_CON) & I2C_PCA_CON_SI);
+ } else {
+- while ((pca_isa_readbyte(adap, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0)
++ while ((pca_isa_readbyte(pd, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0)
+ udelay(100);
+ }
+ return ret;
+ }
+
++static void pca_isa_resetchip(void *pd)
++{
++ /* apparently only an external reset will do it. not a lot can be done */
++ printk(KERN_WARNING DRIVER ": Haven't figured out how to do a reset yet\n");
++}
++
+ static irqreturn_t pca_handler(int this_irq, void *dev_id) {
+ wake_up_interruptible(&pca_wait);
+ return IRQ_HANDLED;
+ }
+
+ static struct i2c_algo_pca_data pca_isa_data = {
+- .get_own = pca_isa_getown,
+- .get_clock = pca_isa_getclock,
++ /* .data intentionally left NULL, not needed with ISA */
+ .write_byte = pca_isa_writebyte,
+ .read_byte = pca_isa_readbyte,
+- .wait_for_interrupt = pca_isa_waitforinterrupt,
++ .wait_for_completion = pca_isa_waitforcompletion,
++ .reset_chip = pca_isa_resetchip,
+ };
+
+ static struct i2c_adapter pca_isa_ops = {
+@@ -117,6 +104,7 @@ static struct i2c_adapter pca_isa_ops = {
+ .id = I2C_HW_A_ISA,
+ .algo_data = &pca_isa_data,
+ .name = "PCA9564 ISA Adapter",
++ .timeout = 100,
+ };
+
+ static int __devinit pca_isa_probe(struct device *dev, unsigned int id)
+@@ -144,6 +132,7 @@ static int __devinit pca_isa_probe(struct device *dev, unsigned int id)
+ }
+ }
+
++ pca_isa_data.i2c_clock = clock;
+ if (i2c_pca_add_bus(&pca_isa_ops) < 0) {
+ dev_err(dev, "Failed to add i2c bus\n");
+ goto out_irq;
+@@ -178,7 +167,7 @@ static struct isa_driver pca_isa_driver = {
+ .remove = __devexit_p(pca_isa_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+- .name = "i2c-pca-isa",
++ .name = DRIVER,
+ }
+ };
+
+@@ -204,7 +193,5 @@ MODULE_PARM_DESC(irq, "IRQ");
+ module_param(clock, int, 0);
+ MODULE_PARM_DESC(clock, "Clock rate as described in table 1 of PCA9564 datasheet");
+
+-module_param(own, int, 0); /* the driver can't do slave mode, so there's no real point in this */
+-
+ module_init(pca_isa_init);
+ module_exit(pca_isa_exit);
+diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c
+new file mode 100644
+index 0000000..9d75f51
+--- /dev/null
++++ b/drivers/i2c/busses/i2c-pca-platform.c
+@@ -0,0 +1,298 @@
++/*
++ * i2c_pca_platform.c
++ *
++ * Platform driver for the PCA9564 I2C controller.
++ *
++ * Copyright (C) 2008 Pengutronix
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++
++ */
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/errno.h>
++#include <linux/i2c.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/i2c-algo-pca.h>
++#include <linux/i2c-pca-platform.h>
++#include <linux/gpio.h>
++
++#include <asm/irq.h>
++#include <asm/io.h>
++
++#define res_len(r) ((r)->end - (r)->start + 1)
++
++struct i2c_pca_pf_data {
++ void __iomem *reg_base;
++ int irq; /* if 0, use polling */
++ int gpio;
++ wait_queue_head_t wait;
++ struct i2c_adapter adap;
++ struct i2c_algo_pca_data algo_data;
++ unsigned long io_base;
++ unsigned long io_size;
++};
++
++/* Read/Write functions for different register alignments */
++
++static int i2c_pca_pf_readbyte8(void *pd, int reg)
++{
++ struct i2c_pca_pf_data *i2c = pd;
++ return ioread8(i2c->reg_base + reg);
++}
++
++static int i2c_pca_pf_readbyte16(void *pd, int reg)
++{
++ struct i2c_pca_pf_data *i2c = pd;
++ return ioread8(i2c->reg_base + reg * 2);
++}
++
++static int i2c_pca_pf_readbyte32(void *pd, int reg)
++{
++ struct i2c_pca_pf_data *i2c = pd;
++ return ioread8(i2c->reg_base + reg * 4);
++}
++
++static void i2c_pca_pf_writebyte8(void *pd, int reg, int val)
++{
++ struct i2c_pca_pf_data *i2c = pd;
++ iowrite8(val, i2c->reg_base + reg);
++}
++
++static void i2c_pca_pf_writebyte16(void *pd, int reg, int val)
++{
++ struct i2c_pca_pf_data *i2c = pd;
++ iowrite8(val, i2c->reg_base + reg * 2);
++}
++
++static void i2c_pca_pf_writebyte32(void *pd, int reg, int val)
++{
++ struct i2c_pca_pf_data *i2c = pd;
++ iowrite8(val, i2c->reg_base + reg * 4);
++}
++
++
++static int i2c_pca_pf_waitforcompletion(void *pd)
++{
++ struct i2c_pca_pf_data *i2c = pd;
++ int ret = 0;
++
++ if (i2c->irq) {
++ ret = wait_event_interruptible(i2c->wait,
++ i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
++ & I2C_PCA_CON_SI);
++ } else {
++ /*
++ * Do polling...
++ * XXX: Could get stuck in extreme cases!
++ * Maybe add timeout, but using irqs is preferred anyhow.
++ */
++ while ((i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
++ & I2C_PCA_CON_SI) == 0)
++ udelay(100);
++ }
++
++ return ret;
++}
++
++static void i2c_pca_pf_dummyreset(void *pd)
++{
++ struct i2c_pca_pf_data *i2c = pd;
++ printk(KERN_WARNING "%s: No reset-pin found. Chip may get stuck!\n",
++ i2c->adap.name);
++}
++
++static void i2c_pca_pf_resetchip(void *pd)
++{
++ struct i2c_pca_pf_data *i2c = pd;
++
++ gpio_set_value(i2c->gpio, 0);
++ ndelay(100);
++ gpio_set_value(i2c->gpio, 1);
++}
++
++static irqreturn_t i2c_pca_pf_handler(int this_irq, void *dev_id)
++{
++ struct i2c_pca_pf_data *i2c = dev_id;
++
++ if ((i2c->algo_data.read_byte(i2c, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0)
++ return IRQ_NONE;
++
++ wake_up_interruptible(&i2c->wait);
++
++ return IRQ_HANDLED;
++}
++
++
++static int __devinit i2c_pca_pf_probe(struct platform_device *pdev)
++{
++ struct i2c_pca_pf_data *i2c;
++ struct resource *res;
++ struct i2c_pca9564_pf_platform_data *platform_data =
++ pdev->dev.platform_data;
++ int ret = 0;
++ int irq;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ irq = platform_get_irq(pdev, 0);
++ /* If irq is 0, we do polling. */
++
++ if (res == NULL) {
++ ret = -ENODEV;
++ goto e_print;
++ }
++
++ if (!request_mem_region(res->start, res_len(res), res->name)) {
++ ret = -ENOMEM;
++ goto e_print;
++ }
++
++ i2c = kzalloc(sizeof(struct i2c_pca_pf_data), GFP_KERNEL);
++ if (!i2c) {
++ ret = -ENOMEM;
++ goto e_alloc;
++ }
++
++ init_waitqueue_head(&i2c->wait);
++
++ i2c->reg_base = ioremap(res->start, res_len(res));
++ if (!i2c->reg_base) {
++ ret = -EIO;
++ goto e_remap;
++ }
++ i2c->io_base = res->start;
++ i2c->io_size = res_len(res);
++ i2c->irq = irq;
++
++ i2c->adap.nr = pdev->id >= 0 ? pdev->id : 0;
++ i2c->adap.owner = THIS_MODULE;
++ snprintf(i2c->adap.name, sizeof(i2c->adap.name), "PCA9564 at 0x%08lx",
++ (unsigned long) res->start);
++ i2c->adap.algo_data = &i2c->algo_data;
++ i2c->adap.dev.parent = &pdev->dev;
++ i2c->adap.timeout = platform_data->timeout;
++
++ i2c->algo_data.i2c_clock = platform_data->i2c_clock_speed;
++ i2c->algo_data.data = i2c;
++
++ switch (res->flags & IORESOURCE_MEM_TYPE_MASK) {
++ case IORESOURCE_MEM_32BIT:
++ i2c->algo_data.write_byte = i2c_pca_pf_writebyte32;
++ i2c->algo_data.read_byte = i2c_pca_pf_readbyte32;
++ break;
++ case IORESOURCE_MEM_16BIT:
++ i2c->algo_data.write_byte = i2c_pca_pf_writebyte16;
++ i2c->algo_data.read_byte = i2c_pca_pf_readbyte16;
++ break;
++ case IORESOURCE_MEM_8BIT:
++ default:
++ i2c->algo_data.write_byte = i2c_pca_pf_writebyte8;
++ i2c->algo_data.read_byte = i2c_pca_pf_readbyte8;
++ break;
++ }
++
++ i2c->algo_data.wait_for_completion = i2c_pca_pf_waitforcompletion;
++
++ i2c->gpio = platform_data->gpio;
++ i2c->algo_data.reset_chip = i2c_pca_pf_dummyreset;
++
++ /* Use gpio_is_valid() when in mainline */
++ if (i2c->gpio > -1) {
++ ret = gpio_request(i2c->gpio, i2c->adap.name);
++ if (ret == 0) {
++ gpio_direction_output(i2c->gpio, 1);
++ i2c->algo_data.reset_chip = i2c_pca_pf_resetchip;
++ } else {
++ printk(KERN_WARNING "%s: Registering gpio failed!\n",
++ i2c->adap.name);
++ i2c->gpio = ret;
++ }
++ }
++
++ if (irq) {
++ ret = request_irq(irq, i2c_pca_pf_handler,
++ IRQF_TRIGGER_FALLING, i2c->adap.name, i2c);
++ if (ret)
++ goto e_reqirq;
++ }
++
++ if (i2c_pca_add_numbered_bus(&i2c->adap) < 0) {
++ ret = -ENODEV;
++ goto e_adapt;
++ }
++
++ platform_set_drvdata(pdev, i2c);
++
++ printk(KERN_INFO "%s registered.\n", i2c->adap.name);
++
++ return 0;
++
++e_adapt:
++ if (irq)
++ free_irq(irq, i2c);
++e_reqirq:
++ if (i2c->gpio > -1)
++ gpio_free(i2c->gpio);
++
++ iounmap(i2c->reg_base);
++e_remap:
++ kfree(i2c);
++e_alloc:
++ release_mem_region(res->start, res_len(res));
++e_print:
++ printk(KERN_ERR "Registering PCA9564 FAILED! (%d)\n", ret);
++ return ret;
++}
++
++static int __devexit i2c_pca_pf_remove(struct platform_device *pdev)
++{
++ struct i2c_pca_pf_data *i2c = platform_get_drvdata(pdev);
++ platform_set_drvdata(pdev, NULL);
++
++ i2c_del_adapter(&i2c->adap);
++
++ if (i2c->irq)
++ free_irq(i2c->irq, i2c);
++
++ if (i2c->gpio > -1)
++ gpio_free(i2c->gpio);
++
++ iounmap(i2c->reg_base);
++ release_mem_region(i2c->io_base, i2c->io_size);
++ kfree(i2c);
++
++ return 0;
++}
++
++static struct platform_driver i2c_pca_pf_driver = {
++ .probe = i2c_pca_pf_probe,
++ .remove = __devexit_p(i2c_pca_pf_remove),
++ .driver = {
++ .name = "i2c-pca-platform",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init i2c_pca_pf_init(void)
++{
++ return platform_driver_register(&i2c_pca_pf_driver);
++}
++
++static void __exit i2c_pca_pf_exit(void)
++{
++ platform_driver_unregister(&i2c_pca_pf_driver);
++}
++
++MODULE_AUTHOR("Wolfram Sang <w.sang at pengutronix.de>");
++MODULE_DESCRIPTION("I2C-PCA9564 platform driver");
++MODULE_LICENSE("GPL");
++
++module_init(i2c_pca_pf_init);
++module_exit(i2c_pca_pf_exit);
++
+diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c
+index b03af56..63b3e2c 100644
+--- a/drivers/i2c/busses/i2c-pmcmsp.c
++++ b/drivers/i2c/busses/i2c-pmcmsp.c
+@@ -467,7 +467,7 @@ static enum pmcmsptwi_xfer_result pmcmsptwi_xfer_cmd(
+ (cmd->read_len == 0 || cmd->write_len == 0))) {
+ dev_err(&pmcmsptwi_adapter.dev,
+ "%s: Cannot transfer less than 1 byte\n",
+- __FUNCTION__);
++ __func__);
+ return -EINVAL;
+ }
+
+@@ -475,7 +475,7 @@ static enum pmcmsptwi_xfer_result pmcmsptwi_xfer_cmd(
+ cmd->write_len > MSP_MAX_BYTES_PER_RW) {
+ dev_err(&pmcmsptwi_adapter.dev,
+ "%s: Cannot transfer more than %d bytes\n",
+- __FUNCTION__, MSP_MAX_BYTES_PER_RW);
++ __func__, MSP_MAX_BYTES_PER_RW);
+ return -EINVAL;
+ }
+
+@@ -627,6 +627,9 @@ static struct i2c_adapter pmcmsptwi_adapter = {
+ .name = DRV_NAME,
+ };
+
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:" DRV_NAME);
++
+ static struct platform_driver pmcmsptwi_driver = {
+ .probe = pmcmsptwi_probe,
+ .remove = __devexit_p(pmcmsptwi_remove),
+diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c
+index f8d0dff..1ca2108 100644
+--- a/drivers/i2c/busses/i2c-pnx.c
++++ b/drivers/i2c/busses/i2c-pnx.c
+@@ -76,7 +76,7 @@ static int i2c_pnx_start(unsigned char slave_addr, struct i2c_adapter *adap)
+ {
+ struct i2c_pnx_algo_data *alg_data = adap->algo_data;
+
+- dev_dbg(&adap->dev, "%s(): addr 0x%x mode %d\n", __FUNCTION__,
++ dev_dbg(&adap->dev, "%s(): addr 0x%x mode %d\n", __func__,
+ slave_addr, alg_data->mif.mode);
+
+ /* Check for 7 bit slave addresses only */
+@@ -110,14 +110,14 @@ static int i2c_pnx_start(unsigned char slave_addr, struct i2c_adapter *adap)
+ iowrite32(ioread32(I2C_REG_STS(alg_data)) | mstatus_tdi | mstatus_afi,
+ I2C_REG_STS(alg_data));
+
+- dev_dbg(&adap->dev, "%s(): sending %#x\n", __FUNCTION__,
++ dev_dbg(&adap->dev, "%s(): sending %#x\n", __func__,
+ (slave_addr << 1) | start_bit | alg_data->mif.mode);
+
+ /* Write the slave address, START bit and R/W bit */
+ iowrite32((slave_addr << 1) | start_bit | alg_data->mif.mode,
+ I2C_REG_TX(alg_data));
+
+- dev_dbg(&adap->dev, "%s(): exit\n", __FUNCTION__);
++ dev_dbg(&adap->dev, "%s(): exit\n", __func__);
+
+ return 0;
+ }
+@@ -135,7 +135,7 @@ static void i2c_pnx_stop(struct i2c_adapter *adap)
+ long timeout = 1000;
+
+ dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
+- __FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
++ __func__, ioread32(I2C_REG_STS(alg_data)));
+
+ /* Write a STOP bit to TX FIFO */
+ iowrite32(0xff | stop_bit, I2C_REG_TX(alg_data));
+@@ -149,7 +149,7 @@ static void i2c_pnx_stop(struct i2c_adapter *adap)
+ }
+
+ dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
+- __FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
++ __func__, ioread32(I2C_REG_STS(alg_data)));
+ }
+
+ /**
+@@ -164,7 +164,7 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap)
+ u32 val;
+
+ dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
+- __FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
++ __func__, ioread32(I2C_REG_STS(alg_data)));
+
+ if (alg_data->mif.len > 0) {
+ /* We still have something to talk about... */
+@@ -179,7 +179,7 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap)
+ alg_data->mif.len--;
+ iowrite32(val, I2C_REG_TX(alg_data));
+
+- dev_dbg(&adap->dev, "%s(): xmit %#x [%d]\n", __FUNCTION__,
++ dev_dbg(&adap->dev, "%s(): xmit %#x [%d]\n", __func__,
+ val, alg_data->mif.len + 1);
+
+ if (alg_data->mif.len == 0) {
+@@ -197,7 +197,7 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap)
+ del_timer_sync(&alg_data->mif.timer);
+
+ dev_dbg(&adap->dev, "%s(): Waking up xfer routine.\n",
+- __FUNCTION__);
++ __func__);
+
+ complete(&alg_data->mif.complete);
+ }
+@@ -213,13 +213,13 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap)
+ /* Stop timer. */
+ del_timer_sync(&alg_data->mif.timer);
+ dev_dbg(&adap->dev, "%s(): Waking up xfer routine after "
+- "zero-xfer.\n", __FUNCTION__);
++ "zero-xfer.\n", __func__);
+
+ complete(&alg_data->mif.complete);
+ }
+
+ dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
+- __FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
++ __func__, ioread32(I2C_REG_STS(alg_data)));
+
+ return 0;
+ }
+@@ -237,14 +237,14 @@ static int i2c_pnx_master_rcv(struct i2c_adapter *adap)
+ u32 ctl = 0;
+
+ dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
+- __FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
++ __func__, ioread32(I2C_REG_STS(alg_data)));
+
+ /* Check, whether there is already data,
+ * or we didn't 'ask' for it yet.
+ */
+ if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) {
+ dev_dbg(&adap->dev, "%s(): Write dummy data to fill "
+- "Rx-fifo...\n", __FUNCTION__);
++ "Rx-fifo...\n", __func__);
+
+ if (alg_data->mif.len == 1) {
+ /* Last byte, do not acknowledge next rcv. */
+@@ -276,7 +276,7 @@ static int i2c_pnx_master_rcv(struct i2c_adapter *adap)
+ if (alg_data->mif.len > 0) {
+ val = ioread32(I2C_REG_RX(alg_data));
+ *alg_data->mif.buf++ = (u8) (val & 0xff);
+- dev_dbg(&adap->dev, "%s(): rcv 0x%x [%d]\n", __FUNCTION__, val,
++ dev_dbg(&adap->dev, "%s(): rcv 0x%x [%d]\n", __func__, val,
+ alg_data->mif.len);
+
+ alg_data->mif.len--;
+@@ -300,7 +300,7 @@ static int i2c_pnx_master_rcv(struct i2c_adapter *adap)
+ }
+
+ dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
+- __FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
++ __func__, ioread32(I2C_REG_STS(alg_data)));
+
+ return 0;
+ }
+@@ -312,7 +312,7 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
+ struct i2c_pnx_algo_data *alg_data = adap->algo_data;
+
+ dev_dbg(&adap->dev, "%s(): mstat = %x mctrl = %x, mode = %d\n",
+- __FUNCTION__,
++ __func__,
+ ioread32(I2C_REG_STS(alg_data)),
+ ioread32(I2C_REG_CTL(alg_data)),
+ alg_data->mif.mode);
+@@ -336,7 +336,7 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
+ /* Slave did not acknowledge, generate a STOP */
+ dev_dbg(&adap->dev, "%s(): "
+ "Slave did not acknowledge, generating a STOP.\n",
+- __FUNCTION__);
++ __func__);
+ i2c_pnx_stop(adap);
+
+ /* Disable master interrupts. */
+@@ -375,7 +375,7 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
+ iowrite32(stat | mstatus_tdi | mstatus_afi, I2C_REG_STS(alg_data));
+
+ dev_dbg(&adap->dev, "%s(): exiting, stat = %x ctrl = %x.\n",
+- __FUNCTION__, ioread32(I2C_REG_STS(alg_data)),
++ __func__, ioread32(I2C_REG_STS(alg_data)),
+ ioread32(I2C_REG_CTL(alg_data)));
+
+ return IRQ_HANDLED;
+@@ -447,7 +447,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+ u32 stat = ioread32(I2C_REG_STS(alg_data));
+
+ dev_dbg(&adap->dev, "%s(): entering: %d messages, stat = %04x.\n",
+- __FUNCTION__, num, ioread32(I2C_REG_STS(alg_data)));
++ __func__, num, ioread32(I2C_REG_STS(alg_data)));
+
+ bus_reset_if_active(adap);
+
+@@ -473,7 +473,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+ alg_data->mif.ret = 0;
+ alg_data->last = (i == num - 1);
+
+- dev_dbg(&adap->dev, "%s(): mode %d, %d bytes\n", __FUNCTION__,
++ dev_dbg(&adap->dev, "%s(): mode %d, %d bytes\n", __func__,
+ alg_data->mif.mode,
+ alg_data->mif.len);
+
+@@ -498,7 +498,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+ if (!(rc = alg_data->mif.ret))
+ completed++;
+ dev_dbg(&adap->dev, "%s(): Complete, return code = %d.\n",
+- __FUNCTION__, rc);
++ __func__, rc);
+
+ /* Clear TDI and AFI bits in case they are set. */
+ if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_tdi) {
+@@ -522,7 +522,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+ alg_data->mif.len = 0;
+
+ dev_dbg(&adap->dev, "%s(): exiting, stat = %x\n",
+- __FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
++ __func__, ioread32(I2C_REG_STS(alg_data)));
+
+ if (completed != num)
+ return ((rc < 0) ? rc : -EREMOTEIO);
+@@ -563,7 +563,7 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev)
+
+ if (!i2c_pnx || !i2c_pnx->adapter) {
+ dev_err(&pdev->dev, "%s: no platform data supplied\n",
+- __FUNCTION__);
++ __func__);
+ ret = -EINVAL;
+ goto out;
+ }
+@@ -697,6 +697,7 @@ static void __exit i2c_adap_pnx_exit(void)
+ MODULE_AUTHOR("Vitaly Wool, Dennis Kovalev <source at mvista.com>");
+ MODULE_DESCRIPTION("I2C driver for Philips IP3204-based I2C busses");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:pnx-i2c");
+
+ /* We need to make sure I2C is initialized before USB */
+ subsys_initcall(i2c_adap_pnx_init);
+diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
+index 7813127..22f6d5c 100644
+--- a/drivers/i2c/busses/i2c-powermac.c
++++ b/drivers/i2c/busses/i2c-powermac.c
+@@ -263,6 +263,9 @@ static int __devexit i2c_powermac_probe(struct platform_device *dev)
+ }
+
+
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:i2c-powermac");
++
+ static struct platform_driver i2c_powermac_driver = {
+ .probe = i2c_powermac_probe,
+ .remove = __devexit_p(i2c_powermac_remove),
+diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
+index 2d2087a..eb69fba 100644
+--- a/drivers/i2c/busses/i2c-pxa.c
++++ b/drivers/i2c/busses/i2c-pxa.c
+@@ -39,6 +39,7 @@
+ #include <asm/io.h>
+ #include <asm/arch/i2c.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+
+ struct pxa_i2c {
+ spinlock_t lock;
+@@ -154,7 +155,7 @@ static void i2c_pxa_show_state(struct pxa_i2c *i2c, int lno, const char *fname)
+ readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c)));
+ }
+
+-#define show_state(i2c) i2c_pxa_show_state(i2c, __LINE__, __FUNCTION__)
++#define show_state(i2c) i2c_pxa_show_state(i2c, __LINE__, __func__)
+ #else
+ #define i2c_debug 0
+
+@@ -1131,6 +1132,7 @@ static void __exit i2c_adap_pxa_exit(void)
+ }
+
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:pxa2xx-i2c");
+
+ module_init(i2c_adap_pxa_init);
+ module_exit(i2c_adap_pxa_exit);
+diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
+index c44ada5..1305ef1 100644
+--- a/drivers/i2c/busses/i2c-s3c2410.c
++++ b/drivers/i2c/busses/i2c-s3c2410.c
+@@ -276,12 +276,12 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
+ switch (i2c->state) {
+
+ case STATE_IDLE:
+- dev_err(i2c->dev, "%s: called in STATE_IDLE\n", __FUNCTION__);
++ dev_err(i2c->dev, "%s: called in STATE_IDLE\n", __func__);
+ goto out;
+ break;
+
+ case STATE_STOP:
+- dev_err(i2c->dev, "%s: called in STATE_STOP\n", __FUNCTION__);
++ dev_err(i2c->dev, "%s: called in STATE_STOP\n", __func__);
+ s3c24xx_i2c_disable_irq(i2c);
+ goto out_ack;
+
+@@ -948,3 +948,4 @@ module_exit(i2c_adap_s3c_exit);
+ MODULE_DESCRIPTION("S3C24XX I2C Bus driver");
+ MODULE_AUTHOR("Ben Dooks, <ben at simtec.co.uk>");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:s3c2410-i2c");
+diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c
+new file mode 100644
+index 0000000..5e0e254
+--- /dev/null
++++ b/drivers/i2c/busses/i2c-sh7760.c
+@@ -0,0 +1,577 @@
++/*
++ * I2C bus driver for the SH7760 I2C Interfaces.
++ *
++ * (c) 2005-2008 MSC Vertriebsges.m.b.H, Manuel Lauss <mlau at msc-ge.com>
++ *
++ * licensed under the terms outlined in the file COPYING.
++ *
++ */
++
++#include <linux/completion.h>
++#include <linux/delay.h>
++#include <linux/err.h>
++#include <linux/i2c.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++
++#include <asm/clock.h>
++#include <asm/i2c-sh7760.h>
++#include <asm/io.h>
++
++/* register offsets */
++#define I2CSCR 0x0 /* slave ctrl */
++#define I2CMCR 0x4 /* master ctrl */
++#define I2CSSR 0x8 /* slave status */
++#define I2CMSR 0xC /* master status */
++#define I2CSIER 0x10 /* slave irq enable */
++#define I2CMIER 0x14 /* master irq enable */
++#define I2CCCR 0x18 /* clock dividers */
++#define I2CSAR 0x1c /* slave address */
++#define I2CMAR 0x20 /* master address */
++#define I2CRXTX 0x24 /* data port */
++#define I2CFCR 0x28 /* fifo control */
++#define I2CFSR 0x2C /* fifo status */
++#define I2CFIER 0x30 /* fifo irq enable */
++#define I2CRFDR 0x34 /* rx fifo count */
++#define I2CTFDR 0x38 /* tx fifo count */
++
++#define REGSIZE 0x3C
++
++#define MCR_MDBS 0x80 /* non-fifo mode switch */
++#define MCR_FSCL 0x40 /* override SCL pin */
++#define MCR_FSDA 0x20 /* override SDA pin */
++#define MCR_OBPC 0x10 /* override pins */
++#define MCR_MIE 0x08 /* master if enable */
++#define MCR_TSBE 0x04
++#define MCR_FSB 0x02 /* force stop bit */
++#define MCR_ESG 0x01 /* en startbit gen. */
++
++#define MSR_MNR 0x40 /* nack received */
++#define MSR_MAL 0x20 /* arbitration lost */
++#define MSR_MST 0x10 /* sent a stop */
++#define MSR_MDE 0x08
++#define MSR_MDT 0x04
++#define MSR_MDR 0x02
++#define MSR_MAT 0x01 /* slave addr xfer done */
++
++#define MIE_MNRE 0x40 /* nack irq en */
++#define MIE_MALE 0x20 /* arblos irq en */
++#define MIE_MSTE 0x10 /* stop irq en */
++#define MIE_MDEE 0x08
++#define MIE_MDTE 0x04
++#define MIE_MDRE 0x02
++#define MIE_MATE 0x01 /* address sent irq en */
++
++#define FCR_RFRST 0x02 /* reset rx fifo */
++#define FCR_TFRST 0x01 /* reset tx fifo */
++
++#define FSR_TEND 0x04 /* last byte sent */
++#define FSR_RDF 0x02 /* rx fifo trigger */
++#define FSR_TDFE 0x01 /* tx fifo empty */
++
++#define FIER_TEIE 0x04 /* tx fifo empty irq en */
++#define FIER_RXIE 0x02 /* rx fifo trig irq en */
++#define FIER_TXIE 0x01 /* tx fifo trig irq en */
++
++#define FIFO_SIZE 16
++
++struct cami2c {
++ void __iomem *iobase;
++ struct i2c_adapter adap;
++
++ /* message processing */
++ struct i2c_msg *msg;
++#define IDF_SEND 1
++#define IDF_RECV 2
++#define IDF_STOP 4
++ int flags;
++
++#define IDS_DONE 1
++#define IDS_ARBLOST 2
++#define IDS_NACK 4
++ int status;
++ struct completion xfer_done;
++
++ int irq;
++ struct resource *ioarea;
++};
++
++static inline void OUT32(struct cami2c *cam, int reg, unsigned long val)
++{
++ ctrl_outl(val, (unsigned long)cam->iobase + reg);
++}
++
++static inline unsigned long IN32(struct cami2c *cam, int reg)
++{
++ return ctrl_inl((unsigned long)cam->iobase + reg);
++}
++
++static irqreturn_t sh7760_i2c_irq(int irq, void *ptr)
++{
++ struct cami2c *id = ptr;
++ struct i2c_msg *msg = id->msg;
++ char *data = msg->buf;
++ unsigned long msr, fsr, fier, len;
++
++ msr = IN32(id, I2CMSR);
++ fsr = IN32(id, I2CFSR);
++
++ /* arbitration lost */
++ if (msr & MSR_MAL) {
++ OUT32(id, I2CMCR, 0);
++ OUT32(id, I2CSCR, 0);
++ OUT32(id, I2CSAR, 0);
++ id->status |= IDS_DONE | IDS_ARBLOST;
++ goto out;
++ }
++
++ if (msr & MSR_MNR) {
++ /* NACK handling is very screwed up. After receiving a
++ * NAK IRQ one has to wait a bit before writing to any
++ * registers, or the ctl will lock up. After that delay
++ * do a normal i2c stop. Then wait at least 1 ms before
++ * attempting another transfer or ctl will stop working
++ */
++ udelay(100); /* wait or risk ctl hang */
++ OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST);
++ OUT32(id, I2CMCR, MCR_MIE | MCR_FSB);
++ OUT32(id, I2CFIER, 0);
++ OUT32(id, I2CMIER, MIE_MSTE);
++ OUT32(id, I2CSCR, 0);
++ OUT32(id, I2CSAR, 0);
++ id->status |= IDS_NACK;
++ msr &= ~MSR_MAT;
++ fsr = 0;
++ /* In some cases the MST bit is also set. */
++ }
++
++ /* i2c-stop was sent */
++ if (msr & MSR_MST) {
++ id->status |= IDS_DONE;
++ goto out;
++ }
++
++ /* i2c slave addr was sent; set to "normal" operation */
++ if (msr & MSR_MAT)
++ OUT32(id, I2CMCR, MCR_MIE);
++
++ fier = IN32(id, I2CFIER);
++
++ if (fsr & FSR_RDF) {
++ len = IN32(id, I2CRFDR);
++ if (msg->len <= len) {
++ if (id->flags & IDF_STOP) {
++ OUT32(id, I2CMCR, MCR_MIE | MCR_FSB);
++ OUT32(id, I2CFIER, 0);
++ /* manual says: wait >= 0.5 SCL times */
++ udelay(5);
++ /* next int should be MST */
++ } else {
++ id->status |= IDS_DONE;
++ /* keep the RDF bit: ctrl holds SCL low
++ * until the setup for the next i2c_msg
++ * clears this bit.
++ */
++ fsr &= ~FSR_RDF;
++ }
++ }
++ while (msg->len && len) {
++ *data++ = IN32(id, I2CRXTX);
++ msg->len--;
++ len--;
++ }
++
++ if (msg->len) {
++ len = (msg->len >= FIFO_SIZE) ? FIFO_SIZE - 1
++ : msg->len - 1;
++
++ OUT32(id, I2CFCR, FCR_TFRST | ((len & 0xf) << 4));
++ }
++
++ } else if (id->flags & IDF_SEND) {
++ if ((fsr & FSR_TEND) && (msg->len < 1)) {
++ if (id->flags & IDF_STOP) {
++ OUT32(id, I2CMCR, MCR_MIE | MCR_FSB);
++ } else {
++ id->status |= IDS_DONE;
++ /* keep the TEND bit: ctl holds SCL low
++ * until the setup for the next i2c_msg
++ * clears this bit.
++ */
++ fsr &= ~FSR_TEND;
++ }
++ }
++ if (fsr & FSR_TDFE) {
++ while (msg->len && (IN32(id, I2CTFDR) < FIFO_SIZE)) {
++ OUT32(id, I2CRXTX, *data++);
++ msg->len--;
++ }
++
++ if (msg->len < 1) {
++ fier &= ~FIER_TXIE;
++ OUT32(id, I2CFIER, fier);
++ } else {
++ len = (msg->len >= FIFO_SIZE) ? 2 : 0;
++ OUT32(id, I2CFCR,
++ FCR_RFRST | ((len & 3) << 2));
++ }
++ }
++ }
++out:
++ if (id->status & IDS_DONE) {
++ OUT32(id, I2CMIER, 0);
++ OUT32(id, I2CFIER, 0);
++ id->msg = NULL;
++ complete(&id->xfer_done);
++ }
++ /* clear status flags and ctrl resumes work */
++ OUT32(id, I2CMSR, ~msr);
++ OUT32(id, I2CFSR, ~fsr);
++ OUT32(id, I2CSSR, 0);
++
++ return IRQ_HANDLED;
++}
++
++
++/* prepare and start a master receive operation */
++static void sh7760_i2c_mrecv(struct cami2c *id)
++{
++ int len;
++
++ id->flags |= IDF_RECV;
++
++ /* set the slave addr reg; otherwise rcv wont work! */
++ OUT32(id, I2CSAR, 0xfe);
++ OUT32(id, I2CMAR, (id->msg->addr << 1) | 1);
++
++ /* adjust rx fifo trigger */
++ if (id->msg->len >= FIFO_SIZE)
++ len = FIFO_SIZE - 1; /* trigger at fifo full */
++ else
++ len = id->msg->len - 1; /* trigger before all received */
++
++ OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST);
++ OUT32(id, I2CFCR, FCR_TFRST | ((len & 0xF) << 4));
++
++ OUT32(id, I2CMSR, 0);
++ OUT32(id, I2CMCR, MCR_MIE | MCR_ESG);
++ OUT32(id, I2CMIER, MIE_MNRE | MIE_MALE | MIE_MSTE | MIE_MATE);
++ OUT32(id, I2CFIER, FIER_RXIE);
++}
++
++/* prepare and start a master send operation */
++static void sh7760_i2c_msend(struct cami2c *id)
++{
++ int len;
++
++ id->flags |= IDF_SEND;
++
++ /* set the slave addr reg; otherwise xmit wont work! */
++ OUT32(id, I2CSAR, 0xfe);
++ OUT32(id, I2CMAR, (id->msg->addr << 1) | 0);
++
++ /* adjust tx fifo trigger */
++ if (id->msg->len >= FIFO_SIZE)
++ len = 2; /* trig: 2 bytes left in TX fifo */
++ else
++ len = 0; /* trig: 8 bytes left in TX fifo */
++
++ OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST);
++ OUT32(id, I2CFCR, FCR_RFRST | ((len & 3) << 2));
++
++ while (id->msg->len && IN32(id, I2CTFDR) < FIFO_SIZE) {
++ OUT32(id, I2CRXTX, *(id->msg->buf));
++ (id->msg->len)--;
++ (id->msg->buf)++;
++ }
++
++ OUT32(id, I2CMSR, 0);
++ OUT32(id, I2CMCR, MCR_MIE | MCR_ESG);
++ OUT32(id, I2CFSR, 0);
++ OUT32(id, I2CMIER, MIE_MNRE | MIE_MALE | MIE_MSTE | MIE_MATE);
++ OUT32(id, I2CFIER, FIER_TEIE | (id->msg->len ? FIER_TXIE : 0));
++}
++
++static inline int sh7760_i2c_busy_check(struct cami2c *id)
++{
++ return (IN32(id, I2CMCR) & MCR_FSDA);
++}
++
++static int sh7760_i2c_master_xfer(struct i2c_adapter *adap,
++ struct i2c_msg *msgs,
++ int num)
++{
++ struct cami2c *id = adap->algo_data;
++ int i, retr;
++
++ if (sh7760_i2c_busy_check(id)) {
++ dev_err(&adap->dev, "sh7760-i2c%d: bus busy!\n", adap->nr);
++ return -EBUSY;
++ }
++
++ i = 0;
++ while (i < num) {
++ retr = adap->retries;
++retry:
++ id->flags = ((i == (num-1)) ? IDF_STOP : 0);
++ id->status = 0;
++ id->msg = msgs;
++ init_completion(&id->xfer_done);
++
++ if (msgs->flags & I2C_M_RD)
++ sh7760_i2c_mrecv(id);
++ else
++ sh7760_i2c_msend(id);
++
++ wait_for_completion(&id->xfer_done);
++
++ if (id->status == 0) {
++ num = -EIO;
++ break;
++ }
++
++ if (id->status & IDS_NACK) {
++ /* wait a bit or i2c module stops working */
++ mdelay(1);
++ num = -EREMOTEIO;
++ break;
++ }
++
++ if (id->status & IDS_ARBLOST) {
++ if (retr--) {
++ mdelay(2);
++ goto retry;
++ }
++ num = -EREMOTEIO;
++ break;
++ }
++
++ msgs++;
++ i++;
++ }
++
++ id->msg = NULL;
++ id->flags = 0;
++ id->status = 0;
++
++ OUT32(id, I2CMCR, 0);
++ OUT32(id, I2CMSR, 0);
++ OUT32(id, I2CMIER, 0);
++ OUT32(id, I2CFIER, 0);
++
++ /* reset slave module registers too: master mode enables slave
++ * module for receive ops (ack, data). Without this reset,
++ * eternal bus activity might be reported after NACK / ARBLOST.
++ */
++ OUT32(id, I2CSCR, 0);
++ OUT32(id, I2CSAR, 0);
++ OUT32(id, I2CSSR, 0);
++
++ return num;
++}
++
++static u32 sh7760_i2c_func(struct i2c_adapter *adap)
++{
++ return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
++}
++
++static const struct i2c_algorithm sh7760_i2c_algo = {
++ .master_xfer = sh7760_i2c_master_xfer,
++ .functionality = sh7760_i2c_func,
++};
++
++/* calculate CCR register setting for a desired scl clock. SCL clock is
++ * derived from I2C module clock (iclk) which in turn is derived from
++ * peripheral module clock (mclk, usually around 33MHz):
++ * iclk = mclk/(CDF + 1). iclk must be < 20MHz.
++ * scl = iclk/(SCGD*8 + 20).
++ */
++static int __devinit calc_CCR(unsigned long scl_hz)
++{
++ struct clk *mclk;
++ unsigned long mck, m1, dff, odff, iclk;
++ signed char cdf, cdfm;
++ int scgd, scgdm, scgds;
++
++ mclk = clk_get(NULL, "module_clk");
++ if (IS_ERR(mclk)) {
++ return PTR_ERR(mclk);
++ } else {
++ mck = mclk->rate;
++ clk_put(mclk);
++ }
++
++ odff = scl_hz;
++ scgdm = cdfm = m1 = 0;
++ for (cdf = 3; cdf >= 0; cdf--) {
++ iclk = mck / (1 + cdf);
++ if (iclk >= 20000000)
++ continue;
++ scgds = ((iclk / scl_hz) - 20) >> 3;
++ for (scgd = scgds; (scgd < 63) && scgd <= scgds + 1; scgd++) {
++ m1 = iclk / (20 + (scgd << 3));
++ dff = abs(scl_hz - m1);
++ if (dff < odff) {
++ odff = dff;
++ cdfm = cdf;
++ scgdm = scgd;
++ }
++ }
++ }
++ /* fail if more than 25% off of requested SCL */
++ if (odff > (scl_hz >> 2))
++ return -EINVAL;
++
++ /* create a CCR register value */
++ return ((scgdm << 2) | cdfm);
++}
++
++static int __devinit sh7760_i2c_probe(struct platform_device *pdev)
++{
++ struct sh7760_i2c_platdata *pd;
++ struct resource *res;
++ struct cami2c *id;
++ int ret;
++
++ pd = pdev->dev.platform_data;
++ if (!pd) {
++ dev_err(&pdev->dev, "no platform_data!\n");
++ ret = -ENODEV;
++ goto out0;
++ }
++
++ id = kzalloc(sizeof(struct cami2c), GFP_KERNEL);
++ if (!id) {
++ dev_err(&pdev->dev, "no mem for private data\n");
++ ret = -ENOMEM;
++ goto out0;
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ dev_err(&pdev->dev, "no mmio resources\n");
++ ret = -ENODEV;
++ goto out1;
++ }
++
++ id->ioarea = request_mem_region(res->start, REGSIZE, pdev->name);
++ if (!id->ioarea) {
++ dev_err(&pdev->dev, "mmio already reserved\n");
++ ret = -EBUSY;
++ goto out1;
++ }
++
++ id->iobase = ioremap(res->start, REGSIZE);
++ if (!id->iobase) {
++ dev_err(&pdev->dev, "cannot ioremap\n");
++ ret = -ENODEV;
++ goto out2;
++ }
++
++ id->irq = platform_get_irq(pdev, 0);
++
++ id->adap.nr = pdev->id;
++ id->adap.algo = &sh7760_i2c_algo;
++ id->adap.class = I2C_CLASS_ALL;
++ id->adap.retries = 3;
++ id->adap.algo_data = id;
++ id->adap.dev.parent = &pdev->dev;
++ snprintf(id->adap.name, sizeof(id->adap.name),
++ "SH7760 I2C at %08lx", (unsigned long)res->start);
++
++ OUT32(id, I2CMCR, 0);
++ OUT32(id, I2CMSR, 0);
++ OUT32(id, I2CMIER, 0);
++ OUT32(id, I2CMAR, 0);
++ OUT32(id, I2CSIER, 0);
++ OUT32(id, I2CSAR, 0);
++ OUT32(id, I2CSCR, 0);
++ OUT32(id, I2CSSR, 0);
++ OUT32(id, I2CFIER, 0);
++ OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST);
++ OUT32(id, I2CFSR, 0);
++
++ ret = calc_CCR(pd->speed_khz * 1000);
++ if (ret < 0) {
++ dev_err(&pdev->dev, "invalid SCL clock: %dkHz\n",
++ pd->speed_khz);
++ goto out3;
++ }
++ OUT32(id, I2CCCR, ret);
++
++ if (request_irq(id->irq, sh7760_i2c_irq, IRQF_DISABLED,
++ SH7760_I2C_DEVNAME, id)) {
++ dev_err(&pdev->dev, "cannot get irq %d\n", id->irq);
++ ret = -EBUSY;
++ goto out3;
++ }
++
++ ret = i2c_add_numbered_adapter(&id->adap);
++ if (ret < 0) {
++ dev_err(&pdev->dev, "reg adap failed: %d\n", ret);
++ goto out4;
++ }
++
++ platform_set_drvdata(pdev, id);
++
++ dev_info(&pdev->dev, "%d kHz mmio %08x irq %d\n",
++ pd->speed_khz, res->start, id->irq);
++
++ return 0;
++
++out4:
++ free_irq(id->irq, id);
++out3:
++ iounmap(id->iobase);
++out2:
++ release_resource(id->ioarea);
++ kfree(id->ioarea);
++out1:
++ kfree(id);
++out0:
++ return ret;
++}
++
++static int __devexit sh7760_i2c_remove(struct platform_device *pdev)
++{
++ struct cami2c *id = platform_get_drvdata(pdev);
++
++ i2c_del_adapter(&id->adap);
++ free_irq(id->irq, id);
++ iounmap(id->iobase);
++ release_resource(id->ioarea);
++ kfree(id->ioarea);
++ kfree(id);
++ platform_set_drvdata(pdev, NULL);
++
++ return 0;
++}
++
++static struct platform_driver sh7760_i2c_drv = {
++ .driver = {
++ .name = SH7760_I2C_DEVNAME,
++ .owner = THIS_MODULE,
++ },
++ .probe = sh7760_i2c_probe,
++ .remove = __devexit_p(sh7760_i2c_remove),
++};
++
++static int __init sh7760_i2c_init(void)
++{
++ return platform_driver_register(&sh7760_i2c_drv);
++}
++
++static void __exit sh7760_i2c_exit(void)
++{
++ platform_driver_unregister(&sh7760_i2c_drv);
++}
++
++module_init(sh7760_i2c_init);
++module_exit(sh7760_i2c_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("SH7760 I2C bus driver");
++MODULE_AUTHOR("Manuel Lauss <mano at roarinelk.homelinux.net>");
+diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
+new file mode 100644
+index 0000000..840e634
+--- /dev/null
++++ b/drivers/i2c/busses/i2c-sh_mobile.c
+@@ -0,0 +1,500 @@
++/*
++ * SuperH Mobile I2C Controller
++ *
++ * Copyright (C) 2008 Magnus Damm
++ *
++ * Portions of the code based on out-of-tree driver i2c-sh7343.c
++ * Copyright (c) 2006 Carlos Munoz <carlos at kenati.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
++ *
++ * 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/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <linux/interrupt.h>
++#include <linux/i2c.h>
++#include <linux/err.h>
++#include <linux/clk.h>
++#include <linux/io.h>
++
++enum sh_mobile_i2c_op {
++ OP_START = 0,
++ OP_TX_ONLY,
++ OP_TX_STOP,
++ OP_TX_TO_RX,
++ OP_RX_ONLY,
++ OP_RX_STOP,
++};
++
++struct sh_mobile_i2c_data {
++ struct device *dev;
++ void __iomem *reg;
++ struct i2c_adapter adap;
++
++ struct clk *clk;
++ u_int8_t iccl;
++ u_int8_t icch;
++
++ spinlock_t lock;
++ wait_queue_head_t wait;
++ struct i2c_msg *msg;
++ int pos;
++ int sr;
++};
++
++#define NORMAL_SPEED 100000 /* FAST_SPEED 400000 */
++
++/* Register offsets */
++#define ICDR(pd) (pd->reg + 0x00)
++#define ICCR(pd) (pd->reg + 0x04)
++#define ICSR(pd) (pd->reg + 0x08)
++#define ICIC(pd) (pd->reg + 0x0c)
++#define ICCL(pd) (pd->reg + 0x10)
++#define ICCH(pd) (pd->reg + 0x14)
++
++/* Register bits */
++#define ICCR_ICE 0x80
++#define ICCR_RACK 0x40
++#define ICCR_TRS 0x10
++#define ICCR_BBSY 0x04
++#define ICCR_SCP 0x01
++
++#define ICSR_SCLM 0x80
++#define ICSR_SDAM 0x40
++#define SW_DONE 0x20
++#define ICSR_BUSY 0x10
++#define ICSR_AL 0x08
++#define ICSR_TACK 0x04
++#define ICSR_WAIT 0x02
++#define ICSR_DTE 0x01
++
++#define ICIC_ALE 0x08
++#define ICIC_TACKE 0x04
++#define ICIC_WAITE 0x02
++#define ICIC_DTEE 0x01
++
++static void activate_ch(struct sh_mobile_i2c_data *pd)
++{
++ /* Make sure the clock is enabled */
++ clk_enable(pd->clk);
++
++ /* Enable channel and configure rx ack */
++ iowrite8(ioread8(ICCR(pd)) | ICCR_ICE, ICCR(pd));
++
++ /* Mask all interrupts */
++ iowrite8(0, ICIC(pd));
++
++ /* Set the clock */
++ iowrite8(pd->iccl, ICCL(pd));
++ iowrite8(pd->icch, ICCH(pd));
++}
++
++static void deactivate_ch(struct sh_mobile_i2c_data *pd)
++{
++ /* Clear/disable interrupts */
++ iowrite8(0, ICSR(pd));
++ iowrite8(0, ICIC(pd));
++
++ /* Disable channel */
++ iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd));
++
++ /* Disable clock */
++ clk_disable(pd->clk);
++}
++
++static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,
++ enum sh_mobile_i2c_op op, unsigned char data)
++{
++ unsigned char ret = 0;
++ unsigned long flags;
++
++ dev_dbg(pd->dev, "op %d, data in 0x%02x\n", op, data);
++
++ spin_lock_irqsave(&pd->lock, flags);
++
++ switch (op) {
++ case OP_START:
++ iowrite8(0x94, ICCR(pd));
++ break;
++ case OP_TX_ONLY:
++ iowrite8(data, ICDR(pd));
++ break;
++ case OP_TX_STOP:
++ iowrite8(data, ICDR(pd));
++ iowrite8(0x90, ICCR(pd));
++ iowrite8(ICIC_ALE | ICIC_TACKE, ICIC(pd));
++ break;
++ case OP_TX_TO_RX:
++ iowrite8(data, ICDR(pd));
++ iowrite8(0x81, ICCR(pd));
++ break;
++ case OP_RX_ONLY:
++ ret = ioread8(ICDR(pd));
++ break;
++ case OP_RX_STOP:
++ ret = ioread8(ICDR(pd));
++ iowrite8(0xc0, ICCR(pd));
++ break;
++ }
++
++ spin_unlock_irqrestore(&pd->lock, flags);
++
++ dev_dbg(pd->dev, "op %d, data out 0x%02x\n", op, ret);
++ return ret;
++}
++
++static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)
++{
++ struct platform_device *dev = dev_id;
++ struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev);
++ struct i2c_msg *msg = pd->msg;
++ unsigned char data, sr;
++ int wakeup = 0;
++
++ sr = ioread8(ICSR(pd));
++ pd->sr |= sr;
++
++ dev_dbg(pd->dev, "i2c_isr 0x%02x 0x%02x %s %d %d!\n", sr, pd->sr,
++ (msg->flags & I2C_M_RD) ? "read" : "write",
++ pd->pos, msg->len);
++
++ if (sr & (ICSR_AL | ICSR_TACK)) {
++ iowrite8(0, ICIC(pd)); /* disable interrupts */
++ wakeup = 1;
++ goto do_wakeup;
++ }
++
++ if (pd->pos == msg->len) {
++ i2c_op(pd, OP_RX_ONLY, 0);
++ wakeup = 1;
++ goto do_wakeup;
++ }
++
++ if (pd->pos == -1) {
++ data = (msg->addr & 0x7f) << 1;
++ data |= (msg->flags & I2C_M_RD) ? 1 : 0;
++ } else
++ data = msg->buf[pd->pos];
++
++ if ((pd->pos == -1) || !(msg->flags & I2C_M_RD)) {
++ if (msg->flags & I2C_M_RD)
++ i2c_op(pd, OP_TX_TO_RX, data);
++ else if (pd->pos == (msg->len - 1)) {
++ i2c_op(pd, OP_TX_STOP, data);
++ wakeup = 1;
++ } else
++ i2c_op(pd, OP_TX_ONLY, data);
++ } else {
++ if (pd->pos == (msg->len - 1))
++ data = i2c_op(pd, OP_RX_STOP, 0);
++ else
++ data = i2c_op(pd, OP_RX_ONLY, 0);
++
++ msg->buf[pd->pos] = data;
++ }
++ pd->pos++;
++
++ do_wakeup:
++ if (wakeup) {
++ pd->sr |= SW_DONE;
++ wake_up(&pd->wait);
++ }
++
++ return IRQ_HANDLED;
++}
++
++static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg)
++{
++ /* Initialize channel registers */
++ iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd));
++
++ /* Enable channel and configure rx ack */
++ iowrite8(ioread8(ICCR(pd)) | ICCR_ICE, ICCR(pd));
++
++ /* Set the clock */
++ iowrite8(pd->iccl, ICCL(pd));
++ iowrite8(pd->icch, ICCH(pd));
++
++ pd->msg = usr_msg;
++ pd->pos = -1;
++ pd->sr = 0;
++
++ /* Enable all interrupts except wait */
++ iowrite8(ioread8(ICIC(pd)) | ICIC_ALE | ICIC_TACKE | ICIC_DTEE,
++ ICIC(pd));
++ return 0;
++}
++
++static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
++ struct i2c_msg *msgs,
++ int num)
++{
++ struct sh_mobile_i2c_data *pd = i2c_get_adapdata(adapter);
++ struct i2c_msg *msg;
++ int err = 0;
++ u_int8_t val;
++ int i, k, retry_count;
++
++ activate_ch(pd);
++
++ /* Process all messages */
++ for (i = 0; i < num; i++) {
++ msg = &msgs[i];
++
++ err = start_ch(pd, msg);
++ if (err)
++ break;
++
++ i2c_op(pd, OP_START, 0);
++
++ /* The interrupt handler takes care of the rest... */
++ k = wait_event_timeout(pd->wait,
++ pd->sr & (ICSR_TACK | SW_DONE),
++ 5 * HZ);
++ if (!k)
++ dev_err(pd->dev, "Transfer request timed out\n");
++
++ retry_count = 10;
++again:
++ val = ioread8(ICSR(pd));
++
++ dev_dbg(pd->dev, "val 0x%02x pd->sr 0x%02x\n", val, pd->sr);
++
++ if ((val | pd->sr) & (ICSR_TACK | ICSR_AL)) {
++ err = -EIO;
++ break;
++ }
++
++ /* the interrupt handler may wake us up before the
++ * transfer is finished, so poll the hardware
++ * until we're done.
++ */
++
++ if (!(!(val & ICSR_BUSY) && (val & ICSR_SCLM) &&
++ (val & ICSR_SDAM))) {
++ msleep(1);
++ if (retry_count--)
++ goto again;
++
++ err = -EIO;
++ dev_err(pd->dev, "Polling timed out\n");
++ break;
++ }
++ }
++
++ deactivate_ch(pd);
++
++ if (!err)
++ err = num;
++ return err;
++}
++
++static u32 sh_mobile_i2c_func(struct i2c_adapter *adapter)
++{
++ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
++}
++
++static struct i2c_algorithm sh_mobile_i2c_algorithm = {
++ .functionality = sh_mobile_i2c_func,
++ .master_xfer = sh_mobile_i2c_xfer,
++};
++
++static void sh_mobile_i2c_setup_channel(struct platform_device *dev)
++{
++ struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev);
++ unsigned long peripheral_clk = clk_get_rate(pd->clk);
++ u_int32_t num;
++ u_int32_t denom;
++ u_int32_t tmp;
++
++ spin_lock_init(&pd->lock);
++ init_waitqueue_head(&pd->wait);
++
++ /* Calculate the value for iccl. From the data sheet:
++ * iccl = (p clock / transfer rate) * (L / (L + H))
++ * where L and H are the SCL low/high ratio (5/4 in this case).
++ * We also round off the result.
++ */
++ num = peripheral_clk * 5;
++ denom = NORMAL_SPEED * 9;
++ tmp = num * 10 / denom;
++ if (tmp % 10 >= 5)
++ pd->iccl = (u_int8_t)((num/denom) + 1);
++ else
++ pd->iccl = (u_int8_t)(num/denom);
++
++ /* Calculate the value for icch. From the data sheet:
++ icch = (p clock / transfer rate) * (H / (L + H)) */
++ num = peripheral_clk * 4;
++ tmp = num * 10 / denom;
++ if (tmp % 10 >= 5)
++ pd->icch = (u_int8_t)((num/denom) + 1);
++ else
++ pd->icch = (u_int8_t)(num/denom);
++}
++
++static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook)
++{
++ struct resource *res;
++ int ret = -ENXIO;
++ int q, m;
++ int k = 0;
++ int n = 0;
++
++ while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) {
++ for (n = res->start; hook && n <= res->end; n++) {
++ if (request_irq(n, sh_mobile_i2c_isr, IRQF_DISABLED,
++ dev->dev.bus_id, dev))
++ goto rollback;
++ }
++ k++;
++ }
++
++ if (hook)
++ return k > 0 ? 0 : -ENOENT;
++
++ k--;
++ ret = 0;
++
++ rollback:
++ for (q = k; k >= 0; k--) {
++ for (m = n; m >= res->start; m--)
++ free_irq(m, dev);
++
++ res = platform_get_resource(dev, IORESOURCE_IRQ, k - 1);
++ m = res->end;
++ }
++
++ return ret;
++}
++
++static int sh_mobile_i2c_probe(struct platform_device *dev)
++{
++ struct sh_mobile_i2c_data *pd;
++ struct i2c_adapter *adap;
++ struct resource *res;
++ int size;
++ int ret;
++
++ pd = kzalloc(sizeof(struct sh_mobile_i2c_data), GFP_KERNEL);
++ if (pd == NULL) {
++ dev_err(&dev->dev, "cannot allocate private data\n");
++ return -ENOMEM;
++ }
++
++ pd->clk = clk_get(&dev->dev, "peripheral_clk");
++ if (IS_ERR(pd->clk)) {
++ dev_err(&dev->dev, "cannot get peripheral clock\n");
++ ret = PTR_ERR(pd->clk);
++ goto err;
++ }
++
++ ret = sh_mobile_i2c_hook_irqs(dev, 1);
++ if (ret) {
++ dev_err(&dev->dev, "cannot request IRQ\n");
++ goto err_clk;
++ }
++
++ pd->dev = &dev->dev;
++ platform_set_drvdata(dev, pd);
++
++ res = platform_get_resource(dev, IORESOURCE_MEM, 0);
++ if (res == NULL) {
++ dev_err(&dev->dev, "cannot find IO resource\n");
++ ret = -ENOENT;
++ goto err_irq;
++ }
++
++ size = (res->end - res->start) + 1;
++
++ pd->reg = ioremap(res->start, size);
++ if (pd->reg == NULL) {
++ dev_err(&dev->dev, "cannot map IO\n");
++ ret = -ENXIO;
++ goto err_irq;
++ }
++
++ /* setup the private data */
++ adap = &pd->adap;
++ i2c_set_adapdata(adap, pd);
++
++ adap->owner = THIS_MODULE;
++ adap->algo = &sh_mobile_i2c_algorithm;
++ adap->dev.parent = &dev->dev;
++ adap->retries = 5;
++ adap->nr = dev->id;
++
++ strlcpy(adap->name, dev->name, sizeof(adap->name));
++
++ sh_mobile_i2c_setup_channel(dev);
++
++ ret = i2c_add_numbered_adapter(adap);
++ if (ret < 0) {
++ dev_err(&dev->dev, "cannot add numbered adapter\n");
++ goto err_all;
++ }
++
++ return 0;
++
++ err_all:
++ iounmap(pd->reg);
++ err_irq:
++ sh_mobile_i2c_hook_irqs(dev, 0);
++ err_clk:
++ clk_put(pd->clk);
++ err:
++ kfree(pd);
++ return ret;
++}
++
++static int sh_mobile_i2c_remove(struct platform_device *dev)
++{
++ struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev);
++
++ i2c_del_adapter(&pd->adap);
++ iounmap(pd->reg);
++ sh_mobile_i2c_hook_irqs(dev, 0);
++ clk_put(pd->clk);
++ kfree(pd);
++ return 0;
++}
++
++static struct platform_driver sh_mobile_i2c_driver = {
++ .driver = {
++ .name = "i2c-sh_mobile",
++ .owner = THIS_MODULE,
++ },
++ .probe = sh_mobile_i2c_probe,
++ .remove = sh_mobile_i2c_remove,
++};
++
++static int __init sh_mobile_i2c_adap_init(void)
++{
++ return platform_driver_register(&sh_mobile_i2c_driver);
++}
++
++static void __exit sh_mobile_i2c_adap_exit(void)
++{
++ platform_driver_unregister(&sh_mobile_i2c_driver);
++}
++
++module_init(sh_mobile_i2c_adap_init);
++module_exit(sh_mobile_i2c_adap_exit);
++
++MODULE_DESCRIPTION("SuperH Mobile I2C Bus Controller driver");
++MODULE_AUTHOR("Magnus Damm");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/i2c/busses/i2c-simtec.c b/drivers/i2c/busses/i2c-simtec.c
+index 10af8d3..042fda2 100644
+--- a/drivers/i2c/busses/i2c-simtec.c
++++ b/drivers/i2c/busses/i2c-simtec.c
+@@ -159,6 +159,9 @@ static int simtec_i2c_remove(struct platform_device *dev)
+
+ /* device driver */
+
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:simtec-i2c");
++
+ static struct platform_driver simtec_i2c_driver = {
+ .driver = {
+ .name = "simtec-i2c",
+diff --git a/drivers/i2c/busses/i2c-versatile.c b/drivers/i2c/busses/i2c-versatile.c
+index 081d957..4678bab 100644
+--- a/drivers/i2c/busses/i2c-versatile.c
++++ b/drivers/i2c/busses/i2c-versatile.c
+@@ -151,3 +151,4 @@ module_exit(i2c_versatile_exit);
+
+ MODULE_DESCRIPTION("ARM Versatile I2C bus driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:versatile-i2c");
+diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
+index f5e7a70..61abe0f 100644
+--- a/drivers/i2c/busses/scx200_acb.c
++++ b/drivers/i2c/busses/scx200_acb.c
+@@ -527,7 +527,7 @@ static int __init scx200_create_isa(const char *text, unsigned long base,
+ if (iface == NULL)
+ return -ENOMEM;
+
+- if (request_region(base, 8, iface->adapter.name) == 0) {
++ if (!request_region(base, 8, iface->adapter.name)) {
+ printk(KERN_ERR NAME ": can't allocate io 0x%lx-0x%lx\n",
+ base, base + 8 - 1);
+ rc = -EBUSY;
+diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
+index b21593f..2da2edf 100644
+--- a/drivers/i2c/chips/Kconfig
++++ b/drivers/i2c/chips/Kconfig
+@@ -93,6 +93,7 @@ config ISP1301_OMAP
+
+ config TPS65010
+ tristate "TPS6501x Power Management chips"
++ depends on HAVE_GPIO_LIB
+ default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK
+ help
+ If you say yes here you get support for the TPS6501x series of
+diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
+index 2a31601..b1b45dd 100644
+--- a/drivers/i2c/chips/isp1301_omap.c
++++ b/drivers/i2c/chips/isp1301_omap.c
+@@ -658,7 +658,7 @@ pulldown:
+ OTG_CTRL_REG |= OTG_PULLUP;
+ }
+
+- check_state(isp, __FUNCTION__);
++ check_state(isp, __func__);
+ dump_regs(isp, "otg->isp1301");
+ }
+
+@@ -782,7 +782,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp)
+ if (otg_ctrl & OTG_DRIVER_SEL) {
+ switch (isp->otg.state) {
+ case OTG_STATE_A_IDLE:
+- b_idle(isp, __FUNCTION__);
++ b_idle(isp, __func__);
+ break;
+ default:
+ break;
+@@ -826,7 +826,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp)
+ isp->otg.host->otg_port);
+ }
+
+- check_state(isp, __FUNCTION__);
++ check_state(isp, __func__);
+ return ret;
+ }
+
+@@ -837,7 +837,7 @@ static int otg_init(struct isp1301 *isp)
+ if (!otg_dev)
+ return -ENODEV;
+
+- dump_regs(isp, __FUNCTION__);
++ dump_regs(isp, __func__);
+ /* some of these values are board-specific... */
+ OTG_SYSCON_2_REG |= OTG_EN
+ /* for B-device: */
+@@ -853,9 +853,9 @@ static int otg_init(struct isp1301 *isp)
+ update_otg1(isp, isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE));
+ update_otg2(isp, isp1301_get_u8(isp, ISP1301_OTG_STATUS));
+
+- check_state(isp, __FUNCTION__);
++ check_state(isp, __func__);
+ pr_debug("otg: %s, %s %06x\n",
+- state_name(isp), __FUNCTION__, OTG_CTRL_REG);
++ state_name(isp), __func__, OTG_CTRL_REG);
+
+ OTG_IRQ_EN_REG = DRIVER_SWITCH | OPRT_CHG
+ | B_SRP_TMROUT | B_HNP_FAIL
+@@ -1041,11 +1041,11 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat)
+ OTG1_DP_PULLDOWN);
+ isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1,
+ OTG1_DP_PULLUP);
+- dump_regs(isp, __FUNCTION__);
++ dump_regs(isp, __func__);
+ #endif
+ /* FALLTHROUGH */
+ case OTG_STATE_B_SRP_INIT:
+- b_idle(isp, __FUNCTION__);
++ b_idle(isp, __func__);
+ OTG_CTRL_REG &= OTG_CTRL_REG & OTG_XCEIV_OUTPUTS;
+ /* FALLTHROUGH */
+ case OTG_STATE_B_IDLE:
+@@ -1077,7 +1077,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat)
+ */
+ update_otg1(isp, isp_stat);
+ update_otg2(isp, isp_bstat);
+- check_state(isp, __FUNCTION__);
++ check_state(isp, __func__);
+ #endif
+
+ dump_regs(isp, "isp1301->otg");
+@@ -1310,7 +1310,7 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host)
+ */
+ isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_VBUS_DRV);
+
+- dump_regs(isp, __FUNCTION__);
++ dump_regs(isp, __func__);
+
+ return 0;
+
+@@ -1365,7 +1365,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget)
+ isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
+ INTR_VBUS_VLD);
+ dev_info(&isp->client.dev, "B-Peripheral sessions ok\n");
+- dump_regs(isp, __FUNCTION__);
++ dump_regs(isp, __func__);
+
+ /* If this has a Mini-AB connector, this mode is highly
+ * nonstandard ... but can be handy for testing, so long
+@@ -1416,7 +1416,7 @@ isp1301_start_srp(struct otg_transceiver *dev)
+
+ pr_debug("otg: SRP, %s ... %06x\n", state_name(isp), OTG_CTRL_REG);
+ #ifdef CONFIG_USB_OTG
+- check_state(isp, __FUNCTION__);
++ check_state(isp, __func__);
+ #endif
+ return 0;
+ }
+@@ -1463,7 +1463,7 @@ isp1301_start_hnp(struct otg_transceiver *dev)
+ }
+ pr_debug("otg: HNP %s, %06x ...\n",
+ state_name(isp), OTG_CTRL_REG);
+- check_state(isp, __FUNCTION__);
++ check_state(isp, __func__);
+ return 0;
+ #else
+ /* srp-only */
+@@ -1601,7 +1601,7 @@ fail2:
+ update_otg2(isp, isp1301_get_u8(isp, ISP1301_OTG_STATUS));
+ #endif
+
+- dump_regs(isp, __FUNCTION__);
++ dump_regs(isp, __func__);
+
+ #ifdef VERBOSE
+ mod_timer(&isp->timer, jiffies + TIMER_JIFFIES);
+diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
+index 4154a91..b67f69c 100644
+--- a/drivers/i2c/chips/tps65010.c
++++ b/drivers/i2c/chips/tps65010.c
+@@ -30,9 +30,13 @@
+ #include <linux/debugfs.h>
+ #include <linux/seq_file.h>
+ #include <linux/mutex.h>
++#include <linux/platform_device.h>
+
+ #include <linux/i2c/tps65010.h>
+
++#include <asm/gpio.h>
++
++
+ /*-------------------------------------------------------------------------*/
+
+ #define DRIVER_VERSION "2 May 2005"
+@@ -84,7 +88,9 @@ struct tps65010 {
+ u8 chgstatus, regstatus, chgconf;
+ u8 nmask1, nmask2;
+
+- /* not currently tracking GPIO state */
++ u8 outmask;
++ struct gpio_chip chip;
++ struct platform_device *leds;
+ };
+
+ #define POWER_POLL_DELAY msecs_to_jiffies(5000)
+@@ -449,12 +455,72 @@ static irqreturn_t tps65010_irq(int irq, void *_tps)
+
+ /*-------------------------------------------------------------------------*/
+
++/* offsets 0..3 == GPIO1..GPIO4
++ * offsets 4..5 == LED1/nPG, LED2 (we set one of the non-BLINK modes)
++ */
++static void
++tps65010_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
++{
++ if (offset < 4)
++ tps65010_set_gpio_out_value(offset + 1, value);
++ else
++ tps65010_set_led(offset - 3, value ? ON : OFF);
++}
++
++static int
++tps65010_output(struct gpio_chip *chip, unsigned offset, int value)
++{
++ /* GPIOs may be input-only */
++ if (offset < 4) {
++ struct tps65010 *tps;
++
++ tps = container_of(chip, struct tps65010, chip);
++ if (!(tps->outmask & (1 << offset)))
++ return -EINVAL;
++ tps65010_set_gpio_out_value(offset + 1, value);
++ } else
++ tps65010_set_led(offset - 3, value ? ON : OFF);
++
++ return 0;
++}
++
++static int tps65010_gpio_get(struct gpio_chip *chip, unsigned offset)
++{
++ int value;
++ struct tps65010 *tps;
++
++ tps = container_of(chip, struct tps65010, chip);
++
++ if (offset < 4) {
++ value = i2c_smbus_read_byte_data(tps->client, TPS_DEFGPIO);
++ if (value < 0)
++ return 0;
++ if (value & (1 << (offset + 4))) /* output */
++ return !(value & (1 << offset));
++ else /* input */
++ return (value & (1 << offset));
++ }
++
++ /* REVISIT we *could* report LED1/nPG and LED2 state ... */
++ return 0;
++}
++
++
++/*-------------------------------------------------------------------------*/
++
+ static struct tps65010 *the_tps;
+
+ static int __exit tps65010_remove(struct i2c_client *client)
+ {
+ struct tps65010 *tps = i2c_get_clientdata(client);
++ struct tps65010_board *board = client->dev.platform_data;
+
++ if (board && board->teardown) {
++ int status = board->teardown(client, board->context);
++ if (status < 0)
++ dev_dbg(&client->dev, "board %s %s err %d\n",
++ "teardown", client->name, status);
++ }
+ if (client->irq > 0)
+ free_irq(client->irq, tps);
+ cancel_delayed_work(&tps->work);
+@@ -469,6 +535,7 @@ static int tps65010_probe(struct i2c_client *client)
+ {
+ struct tps65010 *tps;
+ int status;
++ struct tps65010_board *board = client->dev.platform_data;
+
+ if (the_tps) {
+ dev_dbg(&client->dev, "only one tps6501x chip allowed\n");
+@@ -577,6 +644,38 @@ static int tps65010_probe(struct i2c_client *client)
+
+ tps->file = debugfs_create_file(DRIVER_NAME, S_IRUGO, NULL,
+ tps, DEBUG_FOPS);
++
++ /* optionally register GPIOs */
++ if (board && board->base > 0) {
++ tps->outmask = board->outmask;
++
++ tps->chip.label = client->name;
++
++ tps->chip.set = tps65010_gpio_set;
++ tps->chip.direction_output = tps65010_output;
++
++ /* NOTE: only partial support for inputs; nyet IRQs */
++ tps->chip.get = tps65010_gpio_get;
++
++ tps->chip.base = board->base;
++ tps->chip.ngpio = 6;
++ tps->chip.can_sleep = 1;
++
++ status = gpiochip_add(&tps->chip);
++ if (status < 0)
++ dev_err(&client->dev, "can't add gpiochip, err %d\n",
++ status);
++ else if (board->setup) {
++ status = board->setup(client, board->context);
++ if (status < 0) {
++ dev_dbg(&client->dev,
++ "board %s %s err %d\n",
++ "setup", client->name, status);
++ status = 0;
++ }
++ }
++ }
++
+ return 0;
+ fail1:
+ kfree(tps);
+diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
+index 8b645c6..6c7fa8d 100644
+--- a/drivers/i2c/i2c-core.c
++++ b/drivers/i2c/i2c-core.c
+@@ -35,8 +35,8 @@
+ #include <linux/completion.h>
+ #include <linux/hardirq.h>
+ #include <linux/irqflags.h>
++#include <linux/semaphore.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+
+ #include "i2c-core.h"
+
+@@ -1506,7 +1506,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
+ read_write = I2C_SMBUS_READ;
+ if (data->block[0] > I2C_SMBUS_BLOCK_MAX) {
+ dev_err(&adapter->dev, "%s called with invalid "
+- "block proc call size (%d)\n", __FUNCTION__,
++ "block proc call size (%d)\n", __func__,
+ data->block[0]);
+ return -1;
+ }
+diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
+index 393e679..d34c14c 100644
+--- a/drivers/i2c/i2c-dev.c
++++ b/drivers/i2c/i2c-dev.c
+@@ -200,16 +200,176 @@ static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr)
+ return device_for_each_child(&adapter->dev, &addr, i2cdev_check);
+ }
+
+-static int i2cdev_ioctl(struct inode *inode, struct file *file,
+- unsigned int cmd, unsigned long arg)
++static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client,
++ unsigned long arg)
+ {
+- struct i2c_client *client = (struct i2c_client *)file->private_data;
+ struct i2c_rdwr_ioctl_data rdwr_arg;
+- struct i2c_smbus_ioctl_data data_arg;
+- union i2c_smbus_data temp;
+ struct i2c_msg *rdwr_pa;
+ u8 __user **data_ptrs;
+- int i,datasize,res;
++ int i, res;
++
++ if (copy_from_user(&rdwr_arg,
++ (struct i2c_rdwr_ioctl_data __user *)arg,
++ sizeof(rdwr_arg)))
++ return -EFAULT;
++
++ /* Put an arbitrary limit on the number of messages that can
++ * be sent at once */
++ if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
++ return -EINVAL;
++
++ rdwr_pa = (struct i2c_msg *)
++ kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg),
++ GFP_KERNEL);
++ if (!rdwr_pa)
++ return -ENOMEM;
++
++ if (copy_from_user(rdwr_pa, rdwr_arg.msgs,
++ rdwr_arg.nmsgs * sizeof(struct i2c_msg))) {
++ kfree(rdwr_pa);
++ return -EFAULT;
++ }
++
++ data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL);
++ if (data_ptrs == NULL) {
++ kfree(rdwr_pa);
++ return -ENOMEM;
++ }
++
++ res = 0;
++ for (i = 0; i < rdwr_arg.nmsgs; i++) {
++ /* Limit the size of the message to a sane amount;
++ * and don't let length change either. */
++ if ((rdwr_pa[i].len > 8192) ||
++ (rdwr_pa[i].flags & I2C_M_RECV_LEN)) {
++ res = -EINVAL;
++ break;
++ }
++ data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf;
++ rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL);
++ if (rdwr_pa[i].buf == NULL) {
++ res = -ENOMEM;
++ break;
++ }
++ if (copy_from_user(rdwr_pa[i].buf, data_ptrs[i],
++ rdwr_pa[i].len)) {
++ ++i; /* Needs to be kfreed too */
++ res = -EFAULT;
++ break;
++ }
++ }
++ if (res < 0) {
++ int j;
++ for (j = 0; j < i; ++j)
++ kfree(rdwr_pa[j].buf);
++ kfree(data_ptrs);
++ kfree(rdwr_pa);
++ return res;
++ }
++
++ res = i2c_transfer(client->adapter, rdwr_pa, rdwr_arg.nmsgs);
++ while (i-- > 0) {
++ if (res >= 0 && (rdwr_pa[i].flags & I2C_M_RD)) {
++ if (copy_to_user(data_ptrs[i], rdwr_pa[i].buf,
++ rdwr_pa[i].len))
++ res = -EFAULT;
++ }
++ kfree(rdwr_pa[i].buf);
++ }
++ kfree(data_ptrs);
++ kfree(rdwr_pa);
++ return res;
++}
++
++static noinline int i2cdev_ioctl_smbus(struct i2c_client *client,
++ unsigned long arg)
++{
++ struct i2c_smbus_ioctl_data data_arg;
++ union i2c_smbus_data temp;
++ int datasize, res;
++
++ if (copy_from_user(&data_arg,
++ (struct i2c_smbus_ioctl_data __user *) arg,
++ sizeof(struct i2c_smbus_ioctl_data)))
++ return -EFAULT;
++ if ((data_arg.size != I2C_SMBUS_BYTE) &&
++ (data_arg.size != I2C_SMBUS_QUICK) &&
++ (data_arg.size != I2C_SMBUS_BYTE_DATA) &&
++ (data_arg.size != I2C_SMBUS_WORD_DATA) &&
++ (data_arg.size != I2C_SMBUS_PROC_CALL) &&
++ (data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
++ (data_arg.size != I2C_SMBUS_I2C_BLOCK_BROKEN) &&
++ (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) &&
++ (data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) {
++ dev_dbg(&client->adapter->dev,
++ "size out of range (%x) in ioctl I2C_SMBUS.\n",
++ data_arg.size);
++ return -EINVAL;
++ }
++ /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
++ so the check is valid if size==I2C_SMBUS_QUICK too. */
++ if ((data_arg.read_write != I2C_SMBUS_READ) &&
++ (data_arg.read_write != I2C_SMBUS_WRITE)) {
++ dev_dbg(&client->adapter->dev,
++ "read_write out of range (%x) in ioctl I2C_SMBUS.\n",
++ data_arg.read_write);
++ return -EINVAL;
++ }
++
++ /* Note that command values are always valid! */
++
++ if ((data_arg.size == I2C_SMBUS_QUICK) ||
++ ((data_arg.size == I2C_SMBUS_BYTE) &&
++ (data_arg.read_write == I2C_SMBUS_WRITE)))
++ /* These are special: we do not use data */
++ return i2c_smbus_xfer(client->adapter, client->addr,
++ client->flags, data_arg.read_write,
++ data_arg.command, data_arg.size, NULL);
++
++ if (data_arg.data == NULL) {
++ dev_dbg(&client->adapter->dev,
++ "data is NULL pointer in ioctl I2C_SMBUS.\n");
++ return -EINVAL;
++ }
++
++ if ((data_arg.size == I2C_SMBUS_BYTE_DATA) ||
++ (data_arg.size == I2C_SMBUS_BYTE))
++ datasize = sizeof(data_arg.data->byte);
++ else if ((data_arg.size == I2C_SMBUS_WORD_DATA) ||
++ (data_arg.size == I2C_SMBUS_PROC_CALL))
++ datasize = sizeof(data_arg.data->word);
++ else /* size == smbus block, i2c block, or block proc. call */
++ datasize = sizeof(data_arg.data->block);
++
++ if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
++ (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
++ (data_arg.size == I2C_SMBUS_I2C_BLOCK_DATA) ||
++ (data_arg.read_write == I2C_SMBUS_WRITE)) {
++ if (copy_from_user(&temp, data_arg.data, datasize))
++ return -EFAULT;
++ }
++ if (data_arg.size == I2C_SMBUS_I2C_BLOCK_BROKEN) {
++ /* Convert old I2C block commands to the new
++ convention. This preserves binary compatibility. */
++ data_arg.size = I2C_SMBUS_I2C_BLOCK_DATA;
++ if (data_arg.read_write == I2C_SMBUS_READ)
++ temp.block[0] = I2C_SMBUS_BLOCK_MAX;
++ }
++ res = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
++ data_arg.read_write, data_arg.command, data_arg.size, &temp);
++ if (!res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
++ (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
++ (data_arg.read_write == I2C_SMBUS_READ))) {
++ if (copy_to_user(data_arg.data, &temp, datasize))
++ return -EFAULT;
++ }
++ return res;
++}
++
++static int i2cdev_ioctl(struct inode *inode, struct file *file,
++ unsigned int cmd, unsigned long arg)
++{
++ struct i2c_client *client = (struct i2c_client *)file->private_data;
+ unsigned long funcs;
+
+ dev_dbg(&client->adapter->dev, "ioctl, cmd=0x%02x, arg=0x%02lx\n",
+@@ -253,164 +413,11 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
+ return put_user(funcs, (unsigned long __user *)arg);
+
+ case I2C_RDWR:
+- if (copy_from_user(&rdwr_arg,
+- (struct i2c_rdwr_ioctl_data __user *)arg,
+- sizeof(rdwr_arg)))
+- return -EFAULT;
+-
+- /* Put an arbitrary limit on the number of messages that can
+- * be sent at once */
+- if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
+- return -EINVAL;
+-
+- rdwr_pa = (struct i2c_msg *)
+- kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg),
+- GFP_KERNEL);
+-
+- if (rdwr_pa == NULL) return -ENOMEM;
+-
+- if (copy_from_user(rdwr_pa, rdwr_arg.msgs,
+- rdwr_arg.nmsgs * sizeof(struct i2c_msg))) {
+- kfree(rdwr_pa);
+- return -EFAULT;
+- }
+-
+- data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL);
+- if (data_ptrs == NULL) {
+- kfree(rdwr_pa);
+- return -ENOMEM;
+- }
+-
+- res = 0;
+- for( i=0; i<rdwr_arg.nmsgs; i++ ) {
+- /* Limit the size of the message to a sane amount;
+- * and don't let length change either. */
+- if ((rdwr_pa[i].len > 8192) ||
+- (rdwr_pa[i].flags & I2C_M_RECV_LEN)) {
+- res = -EINVAL;
+- break;
+- }
+- data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf;
+- rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL);
+- if(rdwr_pa[i].buf == NULL) {
+- res = -ENOMEM;
+- break;
+- }
+- if(copy_from_user(rdwr_pa[i].buf,
+- data_ptrs[i],
+- rdwr_pa[i].len)) {
+- ++i; /* Needs to be kfreed too */
+- res = -EFAULT;
+- break;
+- }
+- }
+- if (res < 0) {
+- int j;
+- for (j = 0; j < i; ++j)
+- kfree(rdwr_pa[j].buf);
+- kfree(data_ptrs);
+- kfree(rdwr_pa);
+- return res;
+- }
+-
+- res = i2c_transfer(client->adapter,
+- rdwr_pa,
+- rdwr_arg.nmsgs);
+- while(i-- > 0) {
+- if( res>=0 && (rdwr_pa[i].flags & I2C_M_RD)) {
+- if(copy_to_user(
+- data_ptrs[i],
+- rdwr_pa[i].buf,
+- rdwr_pa[i].len)) {
+- res = -EFAULT;
+- }
+- }
+- kfree(rdwr_pa[i].buf);
+- }
+- kfree(data_ptrs);
+- kfree(rdwr_pa);
+- return res;
++ return i2cdev_ioctl_rdrw(client, arg);
+
+ case I2C_SMBUS:
+- if (copy_from_user(&data_arg,
+- (struct i2c_smbus_ioctl_data __user *) arg,
+- sizeof(struct i2c_smbus_ioctl_data)))
+- return -EFAULT;
+- if ((data_arg.size != I2C_SMBUS_BYTE) &&
+- (data_arg.size != I2C_SMBUS_QUICK) &&
+- (data_arg.size != I2C_SMBUS_BYTE_DATA) &&
+- (data_arg.size != I2C_SMBUS_WORD_DATA) &&
+- (data_arg.size != I2C_SMBUS_PROC_CALL) &&
+- (data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
+- (data_arg.size != I2C_SMBUS_I2C_BLOCK_BROKEN) &&
+- (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) &&
+- (data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) {
+- dev_dbg(&client->adapter->dev,
+- "size out of range (%x) in ioctl I2C_SMBUS.\n",
+- data_arg.size);
+- return -EINVAL;
+- }
+- /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
+- so the check is valid if size==I2C_SMBUS_QUICK too. */
+- if ((data_arg.read_write != I2C_SMBUS_READ) &&
+- (data_arg.read_write != I2C_SMBUS_WRITE)) {
+- dev_dbg(&client->adapter->dev,
+- "read_write out of range (%x) in ioctl I2C_SMBUS.\n",
+- data_arg.read_write);
+- return -EINVAL;
+- }
+-
+- /* Note that command values are always valid! */
+-
+- if ((data_arg.size == I2C_SMBUS_QUICK) ||
+- ((data_arg.size == I2C_SMBUS_BYTE) &&
+- (data_arg.read_write == I2C_SMBUS_WRITE)))
+- /* These are special: we do not use data */
+- return i2c_smbus_xfer(client->adapter, client->addr,
+- client->flags,
+- data_arg.read_write,
+- data_arg.command,
+- data_arg.size, NULL);
+-
+- if (data_arg.data == NULL) {
+- dev_dbg(&client->adapter->dev,
+- "data is NULL pointer in ioctl I2C_SMBUS.\n");
+- return -EINVAL;
+- }
++ return i2cdev_ioctl_smbus(client, arg);
+
+- if ((data_arg.size == I2C_SMBUS_BYTE_DATA) ||
+- (data_arg.size == I2C_SMBUS_BYTE))
+- datasize = sizeof(data_arg.data->byte);
+- else if ((data_arg.size == I2C_SMBUS_WORD_DATA) ||
+- (data_arg.size == I2C_SMBUS_PROC_CALL))
+- datasize = sizeof(data_arg.data->word);
+- else /* size == smbus block, i2c block, or block proc. call */
+- datasize = sizeof(data_arg.data->block);
+-
+- if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
+- (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
+- (data_arg.size == I2C_SMBUS_I2C_BLOCK_DATA) ||
+- (data_arg.read_write == I2C_SMBUS_WRITE)) {
+- if (copy_from_user(&temp, data_arg.data, datasize))
+- return -EFAULT;
+- }
+- if (data_arg.size == I2C_SMBUS_I2C_BLOCK_BROKEN) {
+- /* Convert old I2C block commands to the new
+- convention. This preserves binary compatibility. */
+- data_arg.size = I2C_SMBUS_I2C_BLOCK_DATA;
+- if (data_arg.read_write == I2C_SMBUS_READ)
+- temp.block[0] = I2C_SMBUS_BLOCK_MAX;
+- }
+- res = i2c_smbus_xfer(client->adapter,client->addr,client->flags,
+- data_arg.read_write,
+- data_arg.command,data_arg.size,&temp);
+- if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
+- (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
+- (data_arg.read_write == I2C_SMBUS_READ))) {
+- if (copy_to_user(data_arg.data, &temp, datasize))
+- return -EFAULT;
+- }
+- return res;
+ case I2C_RETRIES:
+ client->adapter->retries = arg;
+ break;
+diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
+index eed6d8e..3f9e100 100644
+--- a/drivers/ide/Kconfig
++++ b/drivers/ide/Kconfig
+@@ -122,24 +122,6 @@ config BLK_DEV_IDE_SATA
+
+ If unsure, say N.
+
+-config BLK_DEV_HD_IDE
+- bool "Use old disk-only driver on primary interface"
+- depends on (X86 || SH_MPC1211)
+- ---help---
+- There are two drivers for MFM/RLL/IDE disks. Most people use just
+- the new enhanced driver by itself. This option however installs the
+- old hard disk driver to control the primary IDE/disk interface in
+- the system, leaving the new enhanced IDE driver to take care of only
+- the 2nd/3rd/4th IDE interfaces. Doing this will prevent you from
+- having an IDE/ATAPI CD-ROM or tape drive connected to the primary
+- IDE interface. Choosing this option may be useful for older systems
+- which have MFM/RLL/ESDI controller+drives at the primary port
+- address (0x1f0), along with IDE drives at the secondary/3rd/4th port
+- addresses.
+-
+- Normally, just say N here; you will then use the new driver for all
+- 4 interfaces.
+-
+ config BLK_DEV_IDEDISK
+ tristate "Include IDE/ATA-2 DISK support"
+ ---help---
+@@ -325,6 +307,7 @@ comment "IDE chipset support/bugfixes"
+
+ config IDE_GENERIC
+ tristate "generic/default IDE chipset support"
++ depends on ALPHA || X86 || IA64 || M32R || MIPS || PPC32
+ help
+ If unsure, say N.
+
+@@ -416,12 +399,6 @@ config BLK_DEV_OFFBOARD
+ This can improve the usability of some boot managers such as lilo
+ when booting from a drive on an off-board controller.
+
+- If you say Y here, and you actually want to reverse the device scan
+- order as explained above, you also need to issue the kernel command
+- line option "ide=reverse". (Try "man bootparam" or see the
+- documentation of your boot loader (lilo or loadlin) about how to
+- pass options to the kernel at boot time.)
+-
+ Note that, if you do this, the order of the hd* devices will be
+ rearranged which may require modification of fstab and other files.
+
+@@ -615,8 +592,7 @@ config BLK_DEV_HPT366
+ reference to device 0x80. The other solution is to say Y to "Boot
+ off-board chipsets first support" (CONFIG_BLK_DEV_OFFBOARD) unless
+ your mother board has the chipset natively mounted. Regardless one
+- should use the fore mentioned option and call at LILO or include
+- "ide=reverse" in LILO's append-line.
++ should use the fore mentioned option and call at LILO.
+
+ This driver requires dynamic tuning of the chipset during the
+ ide-probe at boot. It is reported to support DVD II drives, by the
+@@ -1049,19 +1025,19 @@ config IDE_EXT_DIRECT
+ endchoice
+
+ # no isa -> no vlb
+-if ISA
++if ISA && (ALPHA || X86 || MIPS)
+
+ comment "Other IDE chipsets support"
+ comment "Note: most of these also require special kernel boot parameters"
+
+ config BLK_DEV_4DRIVES
+- bool "Generic 4 drives/port support"
++ tristate "Generic 4 drives/port support"
+ help
+ Certain older chipsets, including the Tekram 690CD, use a single set
+ of I/O ports at 0x1f0 to control up to four drives, instead of the
+ customary two drives per port. Support for this can be enabled at
+- runtime using the "ide0=four" kernel boot parameter if you say Y
+- here.
++ runtime using the "ide-4drives.probe" kernel boot parameter if you
++ say Y here.
+
+ config BLK_DEV_ALI14XX
+ tristate "ALI M14xx support"
+@@ -1114,14 +1090,10 @@ config BLK_DEV_IDEDMA
+ def_bool BLK_DEV_IDEDMA_SFF || BLK_DEV_IDEDMA_PMAC || \
+ BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+
+-config IDE_ARCH_OBSOLETE_INIT
+- def_bool ALPHA || (ARM && !ARCH_L7200) || BLACKFIN || X86 || IA64 || M32R || MIPS || PARISC || PPC || (SUPERH64 && BLK_DEV_IDEPCI) || SPARC
+-
+ endif
+
+ config BLK_DEV_HD_ONLY
+ bool "Old hard disk (MFM/RLL/IDE) driver"
+- depends on BLK_DEV_IDE=n
+ help
+ There are two drivers for MFM/RLL/IDE hard disks. Most people use
+ the newer enhanced driver, but this old one is still around for two
+@@ -1133,12 +1105,16 @@ config BLK_DEV_HD_ONLY
+ for systems with only older MFM/RLL/ESDI drives. Choosing the old
+ driver can save 13 KB or so of kernel memory.
+
++ If you want to use this driver together with the new one you have
++ to use "hda=noprobe hdb=noprobe" kernel parameters to prevent the new
++ driver from probing the primary interface.
++
+ If you are unsure, then just choose the Enhanced IDE/MFM/RLL driver
+ instead of this one. For more detailed information, read the
+ Disk-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ config BLK_DEV_HD
+- def_bool BLK_DEV_HD_IDE || BLK_DEV_HD_ONLY
++ def_bool BLK_DEV_HD_ONLY
+
+ endif # IDE
+diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
+index a4a4323..571544c 100644
+--- a/drivers/ide/Makefile
++++ b/drivers/ide/Makefile
+@@ -36,9 +36,9 @@ ifeq ($(CONFIG_BLK_DEV_CMD640), y)
+ endif
+
+ obj-$(CONFIG_BLK_DEV_IDE) += cris/ ppc/
+-obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o
+ obj-$(CONFIG_IDE_H8300) += h8300/
+ obj-$(CONFIG_IDE_GENERIC) += ide-generic.o
++obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o
+
+ ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o
+
+diff --git a/drivers/ide/arm/bast-ide.c b/drivers/ide/arm/bast-ide.c
+index 161d30c..a80b957 100644
+--- a/drivers/ide/arm/bast-ide.c
++++ b/drivers/ide/arm/bast-ide.c
+@@ -21,6 +21,8 @@
+ #include <asm/arch/bast-map.h>
+ #include <asm/arch/bast-irq.h>
+
++#define DRV_NAME "bast-ide"
++
+ static int __init bastide_register(unsigned int base, unsigned int aux, int irq)
+ {
+ ide_hwif_t *hwif;
+@@ -41,18 +43,19 @@ static int __init bastide_register(unsigned int base, unsigned int aux, int irq)
+ hw.io_ports[IDE_CONTROL_OFFSET] = aux + (6 * 0x20);
+ hw.irq = irq;
+
+- hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++ hwif = ide_find_port();
+ if (hwif == NULL)
+ goto out;
+
+ i = hwif->index;
+
+ if (hwif->present)
+- ide_unregister(i, 0, 0);
+- else if (!hwif->hold)
++ ide_unregister(i);
++ else
+ ide_init_port_data(hwif, i);
+
+ ide_init_port_hw(hwif, &hw);
++ hwif->mmio = 1;
+ hwif->quirkproc = NULL;
+
+ idx[0] = i;
+@@ -64,6 +67,8 @@ out:
+
+ static int __init bastide_init(void)
+ {
++ unsigned long base = BAST_VA_IDEPRI + BAST_IDE_CS;
++
+ /* we can treat the VR1000 and the BAST the same */
+
+ if (!(machine_is_bast() || machine_is_vr1000()))
+@@ -71,6 +76,11 @@ static int __init bastide_init(void)
+
+ printk("BAST: IDE driver, (c) 2003-2004 Simtec Electronics\n");
+
++ if (!request_mem_region(base, 0x400000, DRV_NAME)) {
++ printk(KERN_ERR "%s: resources busy\n", DRV_NAME);
++ return -EBUSY;
++ }
++
+ bastide_register(BAST_VA_IDEPRI, BAST_VA_IDEPRIAUX, IRQ_IDE0);
+ bastide_register(BAST_VA_IDESEC, BAST_VA_IDESECAUX, IRQ_IDE1);
+
+diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
+index e816b0f..fd12bbe 100644
+--- a/drivers/ide/arm/icside.c
++++ b/drivers/ide/arm/icside.c
+@@ -400,7 +400,7 @@ icside_setup(void __iomem *base, struct cardinfo *info, struct expansion_card *e
+ unsigned long port = (unsigned long)base + info->dataoffset;
+ ide_hwif_t *hwif;
+
+- hwif = ide_find_port(port);
++ hwif = ide_find_port();
+ if (hwif) {
+ int i;
+
+diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c
+index be9ff73..82643df 100644
+--- a/drivers/ide/arm/ide_arm.c
++++ b/drivers/ide/arm/ide_arm.c
+@@ -34,7 +34,7 @@ static int __init ide_arm_init(void)
+ ide_std_init_ports(&hw, IDE_ARM_IO, IDE_ARM_IO + 0x206);
+ hw.irq = IDE_ARM_IRQ;
+
+- hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++ hwif = ide_find_port();
+ if (hwif) {
+ ide_init_port_hw(hwif, &hw);
+ idx[0] = hwif->index;
+diff --git a/drivers/ide/arm/palm_bk3710.c b/drivers/ide/arm/palm_bk3710.c
+index 8e1f6bd..666df77 100644
+--- a/drivers/ide/arm/palm_bk3710.c
++++ b/drivers/ide/arm/palm_bk3710.c
+@@ -96,11 +96,11 @@ static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev,
+ u16 val16;
+
+ /* DMA Data Setup */
+- t0 = (palm_bk3710_udmatimings[mode].cycletime + ide_palm_clk - 1)
+- / ide_palm_clk - 1;
+- tenv = (20 + ide_palm_clk - 1) / ide_palm_clk - 1;
+- trp = (palm_bk3710_udmatimings[mode].rptime + ide_palm_clk - 1)
+- / ide_palm_clk - 1;
++ t0 = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].cycletime,
++ ide_palm_clk) - 1;
++ tenv = DIV_ROUND_UP(20, ide_palm_clk) - 1;
++ trp = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].rptime,
++ ide_palm_clk) - 1;
+
+ /* udmatim Register */
+ val16 = readw(base + BK3710_UDMATIM) & (dev ? 0xFF0F : 0xFFF0);
+@@ -141,8 +141,8 @@ static void palm_bk3710_setdmamode(void __iomem *base, unsigned int dev,
+ cycletime = max_t(int, t->cycle, min_cycle);
+
+ /* DMA Data Setup */
+- t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
+- td = (t->active + ide_palm_clk - 1) / ide_palm_clk;
++ t0 = DIV_ROUND_UP(cycletime, ide_palm_clk);
++ td = DIV_ROUND_UP(t->active, ide_palm_clk);
+ tkw = t0 - td - 1;
+ td -= 1;
+
+@@ -168,9 +168,9 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
+ struct ide_timing *t;
+
+ /* PIO Data Setup */
+- t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
+- t2 = (ide_timing_find_mode(XFER_PIO_0 + mode)->active +
+- ide_palm_clk - 1) / ide_palm_clk;
++ t0 = DIV_ROUND_UP(cycletime, ide_palm_clk);
++ t2 = DIV_ROUND_UP(ide_timing_find_mode(XFER_PIO_0 + mode)->active,
++ ide_palm_clk);
+
+ t2i = t0 - t2 - 1;
+ t2 -= 1;
+@@ -192,8 +192,8 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
+
+ /* TASKFILE Setup */
+ t = ide_timing_find_mode(XFER_PIO_0 + mode);
+- t0 = (t->cyc8b + ide_palm_clk - 1) / ide_palm_clk;
+- t2 = (t->act8b + ide_palm_clk - 1) / ide_palm_clk;
++ t0 = DIV_ROUND_UP(t->cyc8b, ide_palm_clk);
++ t2 = DIV_ROUND_UP(t->act8b, ide_palm_clk);
+
+ t2i = t0 - t2 - 1;
+ t2 -= 1;
+@@ -378,15 +378,15 @@ static int __devinit palm_bk3710_probe(struct platform_device *pdev)
+ hw.irq = irq->start;
+ hw.chipset = ide_palm3710;
+
+- hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++ hwif = ide_find_port();
+ if (hwif == NULL)
+ goto out;
+
+ i = hwif->index;
+
+ if (hwif->present)
+- ide_unregister(i, 0, 0);
+- else if (!hwif->hold)
++ ide_unregister(i);
++ else
+ ide_init_port_data(hwif, i);
+
+ ide_init_port_hw(hwif, &hw);
+@@ -409,9 +409,13 @@ out:
+ return -ENODEV;
+ }
+
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:palm_bk3710");
++
+ static struct platform_driver platform_bk_driver = {
+ .driver = {
+ .name = "palm_bk3710",
++ .owner = THIS_MODULE,
+ },
+ .probe = palm_bk3710_probe,
+ .remove = NULL,
+diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c
+index efba00d..2c3d0ec 100644
+--- a/drivers/ide/arm/rapide.c
++++ b/drivers/ide/arm/rapide.c
+@@ -44,7 +44,7 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
+ goto release;
+ }
+
+- hwif = ide_find_port((unsigned long)base);
++ hwif = ide_find_port();
+ if (hwif) {
+ memset(&hw, 0, sizeof(hw));
+ rapide_setup_ports(&hw, base, base + 0x818, 1 << 6, ec->irq);
+@@ -76,7 +76,7 @@ static void __devexit rapide_remove(struct expansion_card *ec)
+
+ ecard_set_drvdata(ec, NULL);
+
+- ide_unregister(hwif->index, 0, 0);
++ ide_unregister(hwif->index);
+
+ ecard_release_resources(ec);
+ }
+diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c
+index c8ffbaf..790a775 100644
+--- a/drivers/ide/cris/ide-cris.c
++++ b/drivers/ide/cris/ide-cris.c
+@@ -228,7 +228,10 @@ cris_ide_fill_descriptor(cris_dma_descr_type *d, void* buf, unsigned int len, in
+ static void
+ cris_ide_start_dma(ide_drive_t *drive, cris_dma_descr_type *d, int dir,int type,int len)
+ {
+- reg_ata_rw_ctrl2 ctrl2 = REG_TYPE_CONV(reg_ata_rw_ctrl2, int, IDE_DATA_REG);
++ ide_hwif_t *hwif = drive->hwif;
++
++ reg_ata_rw_ctrl2 ctrl2 = REG_TYPE_CONV(reg_ata_rw_ctrl2, int,
++ hwif->io_ports[IDE_DATA_OFFSET]);
+ reg_ata_rw_trf_cnt trf_cnt = {0};
+
+ mycontext.saved_data = (dma_descr_data*)virt_to_phys(d);
+@@ -264,8 +267,12 @@ cris_ide_wait_dma(int dir)
+
+ static int cris_dma_test_irq(ide_drive_t *drive)
+ {
++ ide_hwif_t *hwif = drive->hwif;
+ int intr = REG_RD_INT(ata, regi_ata, r_intr);
+- reg_ata_rw_ctrl2 ctrl2 = REG_TYPE_CONV(reg_ata_rw_ctrl2, int, IDE_DATA_REG);
++
++ reg_ata_rw_ctrl2 ctrl2 = REG_TYPE_CONV(reg_ata_rw_ctrl2, int,
++ hwif->io_ports[IDE_DATA_OFFSET]);
++
+ return intr & (1 << ctrl2.sel) ? 1 : 0;
+ }
+
+@@ -523,7 +530,8 @@ static void cris_ide_start_dma(ide_drive_t *drive, cris_dma_descr_type *d, int d
+ IO_STATE(R_ATA_CTRL_DATA, handsh, dma);
+ *R_ATA_CTRL_DATA =
+ cmd |
+- IO_FIELD(R_ATA_CTRL_DATA, data, IDE_DATA_REG) |
++ IO_FIELD(R_ATA_CTRL_DATA, data,
++ drive->hwif->io_ports[IDE_DATA_OFFSET]) |
+ IO_STATE(R_ATA_CTRL_DATA, src_dst, dma) |
+ IO_STATE(R_ATA_CTRL_DATA, multi, on) |
+ IO_STATE(R_ATA_CTRL_DATA, dma_size, word);
+@@ -541,7 +549,9 @@ cris_ide_wait_dma(int dir)
+ static int cris_dma_test_irq(ide_drive_t *drive)
+ {
+ int intr = *R_IRQ_MASK0_RD;
+- int bus = IO_EXTRACT(R_ATA_CTRL_DATA, sel, IDE_DATA_REG);
++ int bus = IO_EXTRACT(R_ATA_CTRL_DATA, sel,
++ drive->hwif->io_ports[IDE_DATA_OFFSET]);
++
+ return intr & (1 << (bus + IO_BITNR(R_IRQ_MASK0_RD, ata_irq0))) ? 1 : 0;
+ }
+
+@@ -794,7 +804,7 @@ static int __init init_e100_ide(void)
+
+ cris_setup_ports(&hw, cris_ide_base_address(h));
+
+- hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++ hwif = ide_find_port();
+ if (hwif == NULL)
+ continue;
+ ide_init_port_data(hwif, hwif->index);
+diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c
+index 4108ec4..92b02b9 100644
+--- a/drivers/ide/h8300/ide-h8300.c
++++ b/drivers/ide/h8300/ide-h8300.c
+@@ -99,8 +99,7 @@ static int __init h8300_ide_init(void)
+
+ hw_setup(&hw);
+
+- /* register if */
+- hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++ hwif = ide_find_port();
+ if (hwif == NULL) {
+ printk(KERN_ERR "ide-h8300: IDE I/F register failed\n");
+ return -ENOENT;
+diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c
+index e07b189..0f6fb6b 100644
+--- a/drivers/ide/ide-acpi.c
++++ b/drivers/ide/ide-acpi.c
+@@ -710,6 +710,8 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif)
+ for (i = 0; i < MAX_DRIVES; i++) {
+ drive = &hwif->drives[i];
+
++ memset(drive->acpidata, 0, sizeof(*drive->acpidata));
++
+ if (!drive->present)
+ continue;
+
+diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
+index c8d0e87..1afd95a 100644
+--- a/drivers/ide/ide-cd.c
++++ b/drivers/ide/ide-cd.c
+@@ -13,8 +13,8 @@
+ *
+ * Suggestions are welcome. Patches that work are more welcome though. ;-)
+ * For those wishing to work on this driver, please be sure you download
+- * and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI
+- * (SFF-8020i rev 2.6) standards. These documents can be obtained by
++ * and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI
++ * (SFF-8020i rev 2.6) standards. These documents can be obtained by
+ * anonymous ftp from:
+ * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps
+ * ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r10.pdf
+@@ -51,7 +51,7 @@
+
+ static DEFINE_MUTEX(idecd_ref_mutex);
+
+-#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref)
++#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref)
+
+ #define ide_cd_g(disk) \
+ container_of((disk)->private_data, struct cdrom_info, driver)
+@@ -83,13 +83,12 @@ static void ide_cd_put(struct cdrom_info *cd)
+
+ /* Mark that we've seen a media change, and invalidate our internal
+ buffers. */
+-static void cdrom_saw_media_change (ide_drive_t *drive)
++static void cdrom_saw_media_change(ide_drive_t *drive)
+ {
+ struct cdrom_info *cd = drive->driver_data;
+
+ cd->cd_flags |= IDE_CD_FLAG_MEDIA_CHANGED;
+ cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
+- cd->nsectors_buffered = 0;
+ }
+
+ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
+@@ -101,38 +100,39 @@ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
+ return 0;
+
+ switch (sense->sense_key) {
+- case NO_SENSE: case RECOVERED_ERROR:
+- break;
+- case NOT_READY:
+- /*
+- * don't care about tray state messages for
+- * e.g. capacity commands or in-progress or
+- * becoming ready
+- */
+- if (sense->asc == 0x3a || sense->asc == 0x04)
+- break;
+- log = 1;
+- break;
+- case ILLEGAL_REQUEST:
+- /*
+- * don't log START_STOP unit with LoEj set, since
+- * we cannot reliably check if drive can auto-close
+- */
+- if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24)
+- break;
+- log = 1;
+- break;
+- case UNIT_ATTENTION:
+- /*
+- * Make good and sure we've seen this potential media
+- * change. Some drives (i.e. Creative) fail to present
+- * the correct sense key in the error register.
+- */
+- cdrom_saw_media_change(drive);
++ case NO_SENSE:
++ case RECOVERED_ERROR:
++ break;
++ case NOT_READY:
++ /*
++ * don't care about tray state messages for
++ * e.g. capacity commands or in-progress or
++ * becoming ready
++ */
++ if (sense->asc == 0x3a || sense->asc == 0x04)
+ break;
+- default:
+- log = 1;
++ log = 1;
++ break;
++ case ILLEGAL_REQUEST:
++ /*
++ * don't log START_STOP unit with LoEj set, since
++ * we cannot reliably check if drive can auto-close
++ */
++ if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24)
+ break;
++ log = 1;
++ break;
++ case UNIT_ATTENTION:
++ /*
++ * Make good and sure we've seen this potential media
++ * change. Some drives (i.e. Creative) fail to present
++ * the correct sense key in the error register.
++ */
++ cdrom_saw_media_change(drive);
++ break;
++ default:
++ log = 1;
++ break;
+ }
+ return log;
+ }
+@@ -159,8 +159,8 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
+ if (sense->sense_key == 0x05 && sense->asc == 0x24)
+ return;
+
+- if (sense->error_code == 0x70) { /* Current Error */
+- switch(sense->sense_key) {
++ if (sense->error_code == 0x70) { /* Current Error */
++ switch (sense->sense_key) {
+ case MEDIUM_ERROR:
+ case VOLUME_OVERFLOW:
+ case ILLEGAL_REQUEST:
+@@ -179,7 +179,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
+ bio_sectors = 4;
+ if (drive->queue->hardsect_size == 2048)
+ sector <<= 2; /* Device sector size is 2K */
+- sector &= ~(bio_sectors -1);
++ sector &= ~(bio_sectors - 1);
+ valid = (sector - failed_command->sector) << 9;
+
+ if (valid < 0)
+@@ -188,8 +188,8 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
+ drive->probed_capacity - sector < 4 * 75) {
+ set_capacity(info->disk, sector);
+ }
+- }
+- }
++ }
++ }
+
+ ide_cd_log_error(drive->name, failed_command, sense);
+ }
+@@ -230,7 +230,7 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
+ (void) ide_do_drive_cmd(drive, rq, ide_preempt);
+ }
+
+-static void cdrom_end_request (ide_drive_t *drive, int uptodate)
++static void cdrom_end_request(ide_drive_t *drive, int uptodate)
+ {
+ struct request *rq = HWGROUP(drive)->rq;
+ int nsectors = rq->hard_cur_sectors;
+@@ -293,7 +293,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
+ {
+ struct request *rq = HWGROUP(drive)->rq;
+ int stat, err, sense_key;
+-
++
+ /* Check for errors. */
+ stat = ide_read_status(drive);
+
+@@ -334,26 +334,26 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
+
+ /* Check for tray open. */
+ if (sense_key == NOT_READY) {
+- cdrom_saw_media_change (drive);
++ cdrom_saw_media_change(drive);
+ } else if (sense_key == UNIT_ATTENTION) {
+ /* Check for media change. */
+- cdrom_saw_media_change (drive);
++ cdrom_saw_media_change(drive);
+ /*printk("%s: media changed\n",drive->name);*/
+ return 0;
+- } else if ((sense_key == ILLEGAL_REQUEST) &&
+- (rq->cmd[0] == GPCMD_START_STOP_UNIT)) {
+- /*
+- * Don't print error message for this condition--
+- * SFF8090i indicates that 5/24/00 is the correct
+- * response to a request to close the tray if the
+- * drive doesn't have that capability.
+- * cdrom_log_sense() knows this!
+- */
++ } else if (sense_key == ILLEGAL_REQUEST &&
++ rq->cmd[0] == GPCMD_START_STOP_UNIT) {
++ /*
++ * Don't print error message for this condition--
++ * SFF8090i indicates that 5/24/00 is the correct
++ * response to a request to close the tray if the
++ * drive doesn't have that capability.
++ * cdrom_log_sense() knows this!
++ */
+ } else if (!(rq->cmd_flags & REQ_QUIET)) {
+ /* Otherwise, print an error. */
+ ide_dump_status(drive, "packet command error", stat);
+ }
+-
++
+ rq->cmd_flags |= REQ_FAILED;
+
+ /*
+@@ -374,10 +374,10 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
+ if (sense_key == NOT_READY) {
+ /* Tray open. */
+ if (rq_data_dir(rq) == READ) {
+- cdrom_saw_media_change (drive);
++ cdrom_saw_media_change(drive);
+
+ /* Fail the request. */
+- printk ("%s: tray open\n", drive->name);
++ printk("%s: tray open\n", drive->name);
+ do_end_request = 1;
+ } else {
+ struct cdrom_info *info = drive->driver_data;
+@@ -399,7 +399,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
+ */
+ spin_lock_irqsave(&ide_lock, flags);
+ blk_plug_device(drive->queue);
+- spin_unlock_irqrestore(&ide_lock,flags);
++ spin_unlock_irqrestore(&ide_lock, flags);
+ return 1;
+ }
+ }
+@@ -407,25 +407,31 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
+ /* Media change. */
+ cdrom_saw_media_change (drive);
+
+- /* Arrange to retry the request.
+- But be sure to give up if we've retried
+- too many times. */
++ /*
++ * Arrange to retry the request.
++ * But be sure to give up if we've retried
++ * too many times.
++ */
+ if (++rq->errors > ERROR_MAX)
+ do_end_request = 1;
+ } else if (sense_key == ILLEGAL_REQUEST ||
+ sense_key == DATA_PROTECT) {
+- /* No point in retrying after an illegal
+- request or data protect error.*/
+- ide_dump_status_no_sense (drive, "command error", stat);
++ /*
++ * No point in retrying after an illegal
++ * request or data protect error.
++ */
++ ide_dump_status_no_sense(drive, "command error", stat);
+ do_end_request = 1;
+ } else if (sense_key == MEDIUM_ERROR) {
+- /* No point in re-trying a zillion times on a bad
+- * sector... If we got here the error is not correctable */
+- ide_dump_status_no_sense (drive, "media error (bad sector)", stat);
++ /*
++ * No point in re-trying a zillion times on a bad
++ * sector... If we got here the error is not correctable
++ */
++ ide_dump_status_no_sense(drive, "media error (bad sector)", stat);
+ do_end_request = 1;
+ } else if (sense_key == BLANK_CHECK) {
+ /* Disk appears blank ?? */
+- ide_dump_status_no_sense (drive, "media error (blank)", stat);
++ ide_dump_status_no_sense(drive, "media error (blank)", stat);
+ do_end_request = 1;
+ } else if ((err & ~ABRT_ERR) != 0) {
+ /* Go to the default handler
+@@ -486,18 +492,18 @@ static int cdrom_timer_expiry(ide_drive_t *drive)
+ * ide_timer_expiry keep polling us for these.
+ */
+ switch (rq->cmd[0]) {
+- case GPCMD_BLANK:
+- case GPCMD_FORMAT_UNIT:
+- case GPCMD_RESERVE_RZONE_TRACK:
+- case GPCMD_CLOSE_TRACK:
+- case GPCMD_FLUSH_CACHE:
+- wait = ATAPI_WAIT_PC;
+- break;
+- default:
+- if (!(rq->cmd_flags & REQ_QUIET))
+- printk(KERN_INFO "ide-cd: cmd 0x%x timed out\n", rq->cmd[0]);
+- wait = 0;
+- break;
++ case GPCMD_BLANK:
++ case GPCMD_FORMAT_UNIT:
++ case GPCMD_RESERVE_RZONE_TRACK:
++ case GPCMD_CLOSE_TRACK:
++ case GPCMD_FLUSH_CACHE:
++ wait = ATAPI_WAIT_PC;
++ break;
++ default:
++ if (!(rq->cmd_flags & REQ_QUIET))
++ printk(KERN_INFO "ide-cd: cmd 0x%x timed out\n", rq->cmd[0]);
++ wait = 0;
++ break;
+ }
+ return wait;
+ }
+@@ -542,7 +548,8 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
+
+ /* packet command */
+ spin_lock_irqsave(&ide_lock, flags);
+- hwif->OUTBSYNC(drive, WIN_PACKETCMD, IDE_COMMAND_REG);
++ hwif->OUTBSYNC(drive, WIN_PACKETCMD,
++ hwif->io_ports[IDE_COMMAND_OFFSET]);
+ ndelay(400);
+ spin_unlock_irqrestore(&ide_lock, flags);
+
+@@ -556,7 +563,7 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
+ HANDLER is the interrupt handler to call when the command completes
+ or there's data ready. */
+ #define ATAPI_MIN_CDB_BYTES 12
+-static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
++static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
+ struct request *rq,
+ ide_handler_t *handler)
+ {
+@@ -625,47 +632,6 @@ static void ide_cd_drain_data(ide_drive_t *drive, int nsects)
+ }
+
+ /*
+- * Buffer up to SECTORS_TO_TRANSFER sectors from the drive in our sector
+- * buffer. Once the first sector is added, any subsequent sectors are
+- * assumed to be continuous (until the buffer is cleared). For the first
+- * sector added, SECTOR is its sector number. (SECTOR is then ignored until
+- * the buffer is cleared.)
+- */
+-static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector,
+- int sectors_to_transfer)
+-{
+- struct cdrom_info *info = drive->driver_data;
+-
+- /* Number of sectors to read into the buffer. */
+- int sectors_to_buffer = min_t(int, sectors_to_transfer,
+- (SECTOR_BUFFER_SIZE >> SECTOR_BITS) -
+- info->nsectors_buffered);
+-
+- char *dest;
+-
+- /* If we couldn't get a buffer, don't try to buffer anything... */
+- if (info->buffer == NULL)
+- sectors_to_buffer = 0;
+-
+- /* If this is the first sector in the buffer, remember its number. */
+- if (info->nsectors_buffered == 0)
+- info->sector_buffered = sector;
+-
+- /* Read the data into the buffer. */
+- dest = info->buffer + info->nsectors_buffered * SECTOR_SIZE;
+- while (sectors_to_buffer > 0) {
+- HWIF(drive)->atapi_input_bytes(drive, dest, SECTOR_SIZE);
+- --sectors_to_buffer;
+- --sectors_to_transfer;
+- ++info->nsectors_buffered;
+- dest += SECTOR_SIZE;
+- }
+-
+- /* Throw away any remaining data. */
+- ide_cd_drain_data(drive, sectors_to_transfer);
+-}
+-
+-/*
+ * Check the contents of the interrupt reason register from the cdrom
+ * and attempt to recover if there are problems. Returns 0 if everything's
+ * ok; nonzero if the request has been terminated.
+@@ -685,7 +651,7 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
+
+ /* Whoops... */
+ printk(KERN_ERR "%s: %s: wrong transfer direction!\n",
+- drive->name, __FUNCTION__);
++ drive->name, __func__);
+
+ xf = rw ? hwif->atapi_output_bytes : hwif->atapi_input_bytes;
+ ide_cd_pad_transfer(drive, xf, len);
+@@ -698,7 +664,7 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
+ } else {
+ /* Drive wants a command packet, or invalid ireason... */
+ printk(KERN_ERR "%s: %s: bad interrupt reason 0x%02x\n",
+- drive->name, __FUNCTION__, ireason);
++ drive->name, __func__, ireason);
+ }
+
+ if (rq->cmd_type == REQ_TYPE_ATA_PC)
+@@ -720,7 +686,7 @@ static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
+ return 0;
+
+ printk(KERN_ERR "%s: %s: Bad transfer size %d\n",
+- drive->name, __FUNCTION__, len);
++ drive->name, __func__, len);
+
+ if (cd->cd_flags & IDE_CD_FLAG_LIMIT_NFRAMES)
+ printk(KERN_ERR " This drive is not supported by "
+@@ -733,65 +699,6 @@ static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
+ return 1;
+ }
+
+-/*
+- * Try to satisfy some of the current read request from our cached data.
+- * Returns nonzero if the request has been completed, zero otherwise.
+- */
+-static int cdrom_read_from_buffer (ide_drive_t *drive)
+-{
+- struct cdrom_info *info = drive->driver_data;
+- struct request *rq = HWGROUP(drive)->rq;
+- unsigned short sectors_per_frame;
+-
+- sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS;
+-
+- /* Can't do anything if there's no buffer. */
+- if (info->buffer == NULL) return 0;
+-
+- /* Loop while this request needs data and the next block is present
+- in our cache. */
+- while (rq->nr_sectors > 0 &&
+- rq->sector >= info->sector_buffered &&
+- rq->sector < info->sector_buffered + info->nsectors_buffered) {
+- if (rq->current_nr_sectors == 0)
+- cdrom_end_request(drive, 1);
+-
+- memcpy (rq->buffer,
+- info->buffer +
+- (rq->sector - info->sector_buffered) * SECTOR_SIZE,
+- SECTOR_SIZE);
+- rq->buffer += SECTOR_SIZE;
+- --rq->current_nr_sectors;
+- --rq->nr_sectors;
+- ++rq->sector;
+- }
+-
+- /* If we've satisfied the current request,
+- terminate it successfully. */
+- if (rq->nr_sectors == 0) {
+- cdrom_end_request(drive, 1);
+- return -1;
+- }
+-
+- /* Move on to the next buffer if needed. */
+- if (rq->current_nr_sectors == 0)
+- cdrom_end_request(drive, 1);
+-
+- /* If this condition does not hold, then the kluge i use to
+- represent the number of sectors to skip at the start of a transfer
+- will fail. I think that this will never happen, but let's be
+- paranoid and check. */
+- if (rq->current_nr_sectors < bio_cur_sectors(rq->bio) &&
+- (rq->sector & (sectors_per_frame - 1))) {
+- printk(KERN_ERR "%s: cdrom_read_from_buffer: buffer botch (%ld)\n",
+- drive->name, (long)rq->sector);
+- cdrom_end_request(drive, 0);
+- return -1;
+- }
+-
+- return 0;
+-}
+-
+ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *);
+
+ /*
+@@ -824,7 +731,7 @@ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
+ if (rq->current_nr_sectors !=
+ bio_cur_sectors(rq->bio)) {
+ printk(KERN_ERR "%s: %s: buffer botch (%u)\n",
+- drive->name, __FUNCTION__,
++ drive->name, __func__,
+ rq->current_nr_sectors);
+ cdrom_end_request(drive, 0);
+ return ide_stopped;
+@@ -848,7 +755,7 @@ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
+ #define IDECD_SEEK_TIMER (5 * WAIT_MIN_SLEEP) /* 100 ms */
+ #define IDECD_SEEK_TIMEOUT (2 * WAIT_CMD) /* 20 sec */
+
+-static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive)
++static ide_startstop_t cdrom_seek_intr(ide_drive_t *drive)
+ {
+ struct cdrom_info *info = drive->driver_data;
+ int stat;
+@@ -865,14 +772,14 @@ static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive)
+ * this condition is far too common, to bother
+ * users about it
+ */
+- /* printk("%s: disabled DSC seek overlap\n", drive->name);*/
++ /* printk("%s: disabled DSC seek overlap\n", drive->name);*/
+ drive->dsc_overlap = 0;
+ }
+ }
+ return ide_stopped;
+ }
+
+-static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive)
++static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive)
+ {
+ struct request *rq = HWGROUP(drive)->rq;
+ sector_t frame = rq->sector;
+@@ -887,7 +794,7 @@ static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive)
+ return cdrom_transfer_packet_command(drive, rq, &cdrom_seek_intr);
+ }
+
+-static ide_startstop_t cdrom_start_seek (ide_drive_t *drive, unsigned int block)
++static ide_startstop_t cdrom_start_seek(ide_drive_t *drive, unsigned int block)
+ {
+ struct cdrom_info *info = drive->driver_data;
+
+@@ -896,9 +803,11 @@ static ide_startstop_t cdrom_start_seek (ide_drive_t *drive, unsigned int block)
+ return cdrom_start_packet_command(drive, 0, cdrom_start_seek_continuation);
+ }
+
+-/* Fix up a possibly partially-processed request so that we can
+- start it over entirely, or even put it back on the request queue. */
+-static void restore_request (struct request *rq)
++/*
++ * Fix up a possibly partially-processed request so that we can
++ * start it over entirely, or even put it back on the request queue.
++ */
++static void restore_request(struct request *rq)
+ {
+ if (rq->buffer != bio_data(rq->bio)) {
+ sector_t n = (rq->buffer - (char *) bio_data(rq->bio)) / SECTOR_SIZE;
+@@ -949,7 +858,7 @@ int ide_cd_queue_pc(ide_drive_t *drive, struct request *rq)
+ error = ide_do_drive_cmd(drive, rq, ide_wait);
+ time = jiffies - time;
+
+- /* FIXME: we should probably abort/retry or something
++ /* FIXME: we should probably abort/retry or something
+ * in case of failure */
+ if (rq->cmd_flags & REQ_FAILED) {
+ /* The request failed. Retry if it was due to a unit
+@@ -992,6 +901,7 @@ static int cdrom_newpc_intr_dummy_cb(struct request *rq)
+
+ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
+ {
++ ide_hwif_t *hwif = drive->hwif;
+ struct cdrom_info *info = drive->driver_data;
+ struct request *rq = HWGROUP(drive)->rq;
+ xfer_func_t *xferfunc;
+@@ -1032,9 +942,9 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
+ /*
+ * ok we fall to pio :/
+ */
+- ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3;
+- lowcyl = HWIF(drive)->INB(IDE_BCOUNTL_REG);
+- highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
++ ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]) & 0x3;
++ lowcyl = hwif->INB(hwif->io_ports[IDE_BCOUNTL_OFFSET]);
++ highcyl = hwif->INB(hwif->io_ports[IDE_BCOUNTH_OFFSET]);
+
+ len = lowcyl + (256 * highcyl);
+
+@@ -1055,7 +965,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
+ if (rq->current_nr_sectors > 0) {
+ printk(KERN_ERR "%s: %s: data underrun "
+ "(%d blocks)\n",
+- drive->name, __FUNCTION__,
++ drive->name, __func__,
+ rq->current_nr_sectors);
+ if (!write)
+ rq->cmd_flags |= REQ_FAILED;
+@@ -1132,11 +1042,9 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
+ if (!ptr) {
+ if (blk_fs_request(rq) && !write)
+ /*
+- * If the buffers are full, cache the rest
+- * of the data in our internal buffer.
+- */
+- cdrom_buffer_sectors(drive, rq->sector,
+- thislen >> 9);
++ * If the buffers are full, pipe the rest into
++ * oblivion. */
++ ide_cd_drain_data(drive, thislen >> 9);
+ else {
+ printk(KERN_ERR "%s: confused, missing data\n",
+ drive->name);
+@@ -1241,10 +1149,6 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
+ * weirdness which might be present in the request packet.
+ */
+ restore_request(rq);
+-
+- /* Satisfy whatever we can of this request from our cache. */
+- if (cdrom_read_from_buffer(drive))
+- return ide_stopped;
+ }
+
+ /*
+@@ -1260,9 +1164,6 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
+ } else
+ cd->dma = drive->using_dma;
+
+- /* Clear the local sector buffer. */
+- cd->nsectors_buffered = 0;
+-
+ if (write)
+ cd->devinfo.media_written = 1;
+
+@@ -1318,7 +1219,7 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
+ * cdrom driver request routine.
+ */
+ static ide_startstop_t
+-ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
++ide_do_rw_cdrom(ide_drive_t *drive, struct request *rq, sector_t block)
+ {
+ ide_startstop_t action;
+ struct cdrom_info *info = drive->driver_data;
+@@ -1333,13 +1234,13 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
+ ide_stall_queue(drive, IDECD_SEEK_TIMER);
+ return ide_stopped;
+ }
+- printk (KERN_ERR "%s: DSC timeout\n", drive->name);
++ printk(KERN_ERR "%s: DSC timeout\n", drive->name);
+ }
+ info->cd_flags &= ~IDE_CD_FLAG_SEEKING;
+ }
+- if ((rq_data_dir(rq) == READ) && IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) {
++ if ((rq_data_dir(rq) == READ) && IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap)
+ action = cdrom_start_seek(drive, block);
+- } else
++ else
+ action = cdrom_start_rw(drive, rq);
+ info->last_block = block;
+ return action;
+@@ -1372,7 +1273,7 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
+ */
+
+ static
+-void msf_from_bcd (struct atapi_msf *msf)
++void msf_from_bcd(struct atapi_msf *msf)
+ {
+ msf->minute = BCD2BIN(msf->minute);
+ msf->second = BCD2BIN(msf->second);
+@@ -1472,7 +1373,7 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
+ /* Try to allocate space. */
+ toc = kmalloc(sizeof(struct atapi_toc), GFP_KERNEL);
+ if (toc == NULL) {
+- printk (KERN_ERR "%s: No cdrom TOC buffer!\n", drive->name);
++ printk(KERN_ERR "%s: No cdrom TOC buffer!\n", drive->name);
+ return -ENOMEM;
+ }
+ info->toc = toc;
+@@ -1567,9 +1468,9 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
+ toc->ent[i].track = BCD2BIN(toc->ent[i].track);
+ msf_from_bcd(&toc->ent[i].addr.msf);
+ }
+- toc->ent[i].addr.lba = msf_to_lba (toc->ent[i].addr.msf.minute,
+- toc->ent[i].addr.msf.second,
+- toc->ent[i].addr.msf.frame);
++ toc->ent[i].addr.lba = msf_to_lba(toc->ent[i].addr.msf.minute,
++ toc->ent[i].addr.msf.second,
++ toc->ent[i].addr.msf.frame);
+ }
+
+ /* Read the multisession information. */
+@@ -1593,9 +1494,9 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
+ if (stat)
+ return stat;
+
+- msf_from_bcd (&ms_tmp.ent.addr.msf);
++ msf_from_bcd(&ms_tmp.ent.addr.msf);
+ toc->last_session_lba = msf_to_lba(ms_tmp.ent.addr.msf.minute,
+- ms_tmp.ent.addr.msf.second,
++ ms_tmp.ent.addr.msf.second,
+ ms_tmp.ent.addr.msf.frame);
+ }
+
+@@ -1677,7 +1578,7 @@ static struct cdrom_device_ops ide_cdrom_dops = {
+ .generic_packet = ide_cdrom_packet,
+ };
+
+-static int ide_cdrom_register (ide_drive_t *drive, int nslots)
++static int ide_cdrom_register(ide_drive_t *drive, int nslots)
+ {
+ struct cdrom_info *info = drive->driver_data;
+ struct cdrom_device_info *devinfo = &info->devinfo;
+@@ -1696,7 +1597,7 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
+ }
+
+ static
+-int ide_cdrom_probe_capabilities (ide_drive_t *drive)
++int ide_cdrom_probe_capabilities(ide_drive_t *drive)
+ {
+ struct cdrom_info *cd = drive->driver_data;
+ struct cdrom_device_info *cdi = &cd->devinfo;
+@@ -1868,7 +1769,7 @@ static int ide_cdrom_prep_pc(struct request *rq)
+ rq->errors = ILLEGAL_REQUEST;
+ return BLKPREP_KILL;
+ }
+-
++
+ return BLKPREP_OK;
+ }
+
+@@ -1946,7 +1847,7 @@ static unsigned int ide_cd_flags(struct hd_driveid *id)
+ }
+
+ static
+-int ide_cdrom_setup (ide_drive_t *drive)
++int ide_cdrom_setup(ide_drive_t *drive)
+ {
+ struct cdrom_info *cd = drive->driver_data;
+ struct cdrom_device_info *cdi = &cd->devinfo;
+@@ -1977,7 +1878,7 @@ int ide_cdrom_setup (ide_drive_t *drive)
+ else if (cd->cd_flags & IDE_CD_FLAG_SANYO_3CD)
+ cdi->sanyo_slot = 3; /* 3 => use CD in slot 0 */
+
+- nslots = ide_cdrom_probe_capabilities (drive);
++ nslots = ide_cdrom_probe_capabilities(drive);
+
+ /*
+ * set correct block size
+@@ -1989,7 +1890,7 @@ int ide_cdrom_setup (ide_drive_t *drive)
+ drive->dsc_overlap = (drive->next != drive);
+
+ if (ide_cdrom_register(drive, nslots)) {
+- printk (KERN_ERR "%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
++ printk(KERN_ERR "%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
+ cd->devinfo.handle = NULL;
+ return 1;
+ }
+@@ -1997,19 +1898,6 @@ int ide_cdrom_setup (ide_drive_t *drive)
+ return 0;
+ }
+
+-#ifdef CONFIG_IDE_PROC_FS
+-static
+-sector_t ide_cdrom_capacity (ide_drive_t *drive)
+-{
+- unsigned long capacity, sectors_per_frame;
+-
+- if (cdrom_read_capacity(drive, &capacity, §ors_per_frame, NULL))
+- return 0;
+-
+- return capacity * sectors_per_frame;
+-}
+-#endif
+-
+ static void ide_cd_remove(ide_drive_t *drive)
+ {
+ struct cdrom_info *info = drive->driver_data;
+@@ -2028,11 +1916,9 @@ static void ide_cd_release(struct kref *kref)
+ ide_drive_t *drive = info->drive;
+ struct gendisk *g = info->disk;
+
+- kfree(info->buffer);
+ kfree(info->toc);
+- if (devinfo->handle == drive && unregister_cdrom(devinfo))
+- printk(KERN_ERR "%s: %s failed to unregister device from the cdrom "
+- "driver.\n", __FUNCTION__, drive->name);
++ if (devinfo->handle == drive)
++ unregister_cdrom(devinfo);
+ drive->dsc_overlap = 0;
+ drive->driver_data = NULL;
+ blk_queue_prep_rq(drive->queue, NULL);
+@@ -2044,14 +1930,24 @@ static void ide_cd_release(struct kref *kref)
+ static int ide_cd_probe(ide_drive_t *);
+
+ #ifdef CONFIG_IDE_PROC_FS
++static sector_t ide_cdrom_capacity(ide_drive_t *drive)
++{
++ unsigned long capacity, sectors_per_frame;
++
++ if (cdrom_read_capacity(drive, &capacity, §ors_per_frame, NULL))
++ return 0;
++
++ return capacity * sectors_per_frame;
++}
++
+ static int proc_idecd_read_capacity
+ (char *page, char **start, off_t off, int count, int *eof, void *data)
+ {
+ ide_drive_t *drive = data;
+ int len;
+
+- len = sprintf(page,"%llu\n", (long long)ide_cdrom_capacity(drive));
+- PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++ len = sprintf(page, "%llu\n", (long long)ide_cdrom_capacity(drive));
++ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+
+ static ide_proc_entry_t idecd_proc[] = {
+@@ -2080,20 +1976,17 @@ static ide_driver_t ide_cdrom_driver = {
+ #endif
+ };
+
+-static int idecd_open(struct inode * inode, struct file * file)
++static int idecd_open(struct inode *inode, struct file *file)
+ {
+ struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct cdrom_info *info;
+ int rc = -ENOMEM;
+
+- if (!(info = ide_cd_get(disk)))
++ info = ide_cd_get(disk);
++ if (!info)
+ return -ENXIO;
+
+- if (!info->buffer)
+- info->buffer = kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL|__GFP_REPEAT);
+-
+- if (info->buffer)
+- rc = cdrom_open(&info->devinfo, inode, file);
++ rc = cdrom_open(&info->devinfo, inode, file);
+
+ if (rc < 0)
+ ide_cd_put(info);
+@@ -2101,12 +1994,12 @@ static int idecd_open(struct inode * inode, struct file * file)
+ return rc;
+ }
+
+-static int idecd_release(struct inode * inode, struct file * file)
++static int idecd_release(struct inode *inode, struct file *file)
+ {
+ struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct cdrom_info *info = ide_cd_g(disk);
+
+- cdrom_release (&info->devinfo, file);
++ cdrom_release(&info->devinfo, file);
+
+ ide_cd_put(info);
+
+@@ -2138,7 +2031,7 @@ static int idecd_get_spindown(struct cdrom_device_info *cdi, unsigned long arg)
+ struct packet_command cgc;
+ char buffer[16];
+ int stat;
+- char spindown;
++ char spindown;
+
+ init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN);
+
+@@ -2147,12 +2040,12 @@ static int idecd_get_spindown(struct cdrom_device_info *cdi, unsigned long arg)
+ return stat;
+
+ spindown = buffer[11] & 0x0f;
+- if (copy_to_user((void __user *)arg, &spindown, sizeof (char)))
++ if (copy_to_user((void __user *)arg, &spindown, sizeof(char)))
+ return -EFAULT;
+ return 0;
+ }
+
+-static int idecd_ioctl (struct inode *inode, struct file *file,
++static int idecd_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+ {
+ struct block_device *bdev = inode->i_bdev;
+@@ -2160,13 +2053,13 @@ static int idecd_ioctl (struct inode *inode, struct file *file,
+ int err;
+
+ switch (cmd) {
+- case CDROMSETSPINDOWN:
++ case CDROMSETSPINDOWN:
+ return idecd_set_spindown(&info->devinfo, arg);
+- case CDROMGETSPINDOWN:
++ case CDROMGETSPINDOWN:
+ return idecd_get_spindown(&info->devinfo, arg);
+ default:
+ break;
+- }
++ }
+
+ err = generic_ide_ioctl(info->drive, file, bdev, cmd, arg);
+ if (err == -EINVAL)
+@@ -2192,16 +2085,16 @@ static int idecd_revalidate_disk(struct gendisk *disk)
+ }
+
+ static struct block_device_operations idecd_ops = {
+- .owner = THIS_MODULE,
+- .open = idecd_open,
+- .release = idecd_release,
+- .ioctl = idecd_ioctl,
+- .media_changed = idecd_media_changed,
+- .revalidate_disk= idecd_revalidate_disk
++ .owner = THIS_MODULE,
++ .open = idecd_open,
++ .release = idecd_release,
++ .ioctl = idecd_ioctl,
++ .media_changed = idecd_media_changed,
++ .revalidate_disk = idecd_revalidate_disk
+ };
+
+ /* options */
+-static char *ignore = NULL;
++static char *ignore;
+
+ module_param(ignore, charp, 0400);
+ MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
+diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
+index 22e3751..a58801c 100644
+--- a/drivers/ide/ide-cd.h
++++ b/drivers/ide/ide-cd.h
+@@ -119,10 +119,6 @@ struct cdrom_info {
+
+ struct atapi_toc *toc;
+
+- unsigned long sector_buffered;
+- unsigned long nsectors_buffered;
+- unsigned char *buffer;
+-
+ /* The result of the last successful request sense command
+ on this device. */
+ struct request_sense sense_data;
+diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
+index 39501d1..8e08d08 100644
+--- a/drivers/ide/ide-disk.c
++++ b/drivers/ide/ide-disk.c
+@@ -16,8 +16,6 @@
+
+ #define IDEDISK_VERSION "1.18"
+
+-//#define DEBUG
+-
+ #include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/string.h>
+@@ -88,7 +86,7 @@ static void ide_disk_put(struct ide_disk_obj *idkp)
+ *
+ * It is called only once for each drive.
+ */
+-static int lba_capacity_is_ok (struct hd_driveid *id)
++static int lba_capacity_is_ok(struct hd_driveid *id)
+ {
+ unsigned long lba_sects, chs_sects, head, tail;
+
+@@ -176,7 +174,8 @@ static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma)
+ * __ide_do_rw_disk() issues READ and WRITE commands to a disk,
+ * using LBA if supported, or CHS otherwise, to address sectors.
+ */
+-static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, sector_t block)
++static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
++ sector_t block)
+ {
+ ide_hwif_t *hwif = HWIF(drive);
+ unsigned int dma = drive->using_dma;
+@@ -228,7 +227,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
+ tf->device = (block >> 8) & 0xf;
+ }
+ } else {
+- unsigned int sect,head,cyl,track;
++ unsigned int sect, head, cyl, track;
++
+ track = (int)block / drive->sect;
+ sect = (int)block % drive->sect + 1;
+ head = track % drive->head;
+@@ -271,7 +271,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
+ * 1073741822 == 549756 MB or 48bit addressing fake drive
+ */
+
+-static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block)
++static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
++ sector_t block)
+ {
+ ide_hwif_t *hwif = HWIF(drive);
+
+@@ -452,7 +453,7 @@ static void idedisk_check_hpa(ide_drive_t *drive)
+ * in above order (i.e., if value of higher priority is available,
+ * reset will be ignored).
+ */
+-static void init_idedisk_capacity (ide_drive_t *drive)
++static void init_idedisk_capacity(ide_drive_t *drive)
+ {
+ struct hd_driveid *id = drive->id;
+ /*
+@@ -479,7 +480,7 @@ static void init_idedisk_capacity (ide_drive_t *drive)
+ }
+ }
+
+-static sector_t idedisk_capacity (ide_drive_t *drive)
++static sector_t idedisk_capacity(ide_drive_t *drive)
+ {
+ return drive->capacity64 - drive->sect0;
+ }
+@@ -524,10 +525,11 @@ static int proc_idedisk_read_cache
+ int len;
+
+ if (drive->id_read)
+- len = sprintf(out,"%i\n", drive->id->buf_size / 2);
++ len = sprintf(out, "%i\n", drive->id->buf_size / 2);
+ else
+- len = sprintf(out,"(none)\n");
+- PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++ len = sprintf(out, "(none)\n");
++
++ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+
+ static int proc_idedisk_read_capacity
+@@ -536,54 +538,52 @@ static int proc_idedisk_read_capacity
+ ide_drive_t*drive = (ide_drive_t *)data;
+ int len;
+
+- len = sprintf(page,"%llu\n", (long long)idedisk_capacity(drive));
+- PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++ len = sprintf(page, "%llu\n", (long long)idedisk_capacity(drive));
++
++ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+
+-static int proc_idedisk_read_smart_thresholds
+- (char *page, char **start, off_t off, int count, int *eof, void *data)
++static int proc_idedisk_read_smart(char *page, char **start, off_t off,
++ int count, int *eof, void *data, u8 sub_cmd)
+ {
+ ide_drive_t *drive = (ide_drive_t *)data;
+ int len = 0, i = 0;
+
+- if (get_smart_data(drive, page, SMART_READ_THRESHOLDS) == 0) {
++ if (get_smart_data(drive, page, sub_cmd) == 0) {
+ unsigned short *val = (unsigned short *) page;
+ char *out = ((char *)val) + (SECTOR_WORDS * 4);
+ page = out;
+ do {
+- out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');
++ out += sprintf(out, "%04x%c", le16_to_cpu(*val),
++ (++i & 7) ? ' ' : '\n');
+ val += 1;
+ } while (i < (SECTOR_WORDS * 2));
+ len = out - page;
+ }
+- PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++
++ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+
+-static int proc_idedisk_read_smart_values
++static int proc_idedisk_read_sv
+ (char *page, char **start, off_t off, int count, int *eof, void *data)
+ {
+- ide_drive_t *drive = (ide_drive_t *)data;
+- int len = 0, i = 0;
++ return proc_idedisk_read_smart(page, start, off, count, eof, data,
++ SMART_READ_VALUES);
++}
+
+- if (get_smart_data(drive, page, SMART_READ_VALUES) == 0) {
+- unsigned short *val = (unsigned short *) page;
+- char *out = ((char *)val) + (SECTOR_WORDS * 4);
+- page = out;
+- do {
+- out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');
+- val += 1;
+- } while (i < (SECTOR_WORDS * 2));
+- len = out - page;
+- }
+- PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++static int proc_idedisk_read_st
++ (char *page, char **start, off_t off, int count, int *eof, void *data)
++{
++ return proc_idedisk_read_smart(page, start, off, count, eof, data,
++ SMART_READ_THRESHOLDS);
+ }
+
+ static ide_proc_entry_t idedisk_proc[] = {
+- { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL },
+- { "capacity", S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL },
+- { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL },
+- { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_smart_values, NULL },
+- { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_smart_thresholds, NULL },
++ { "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL },
++ { "capacity", S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL },
++ { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL },
++ { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_sv, NULL },
++ { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_st, NULL },
+ { NULL, 0, NULL, NULL }
+ };
+ #endif /* CONFIG_IDE_PROC_FS */
+@@ -625,12 +625,13 @@ static int set_multcount(ide_drive_t *drive, int arg)
+ if (drive->special.b.set_multmode)
+ return -EBUSY;
+
+- ide_init_drive_cmd (&rq);
++ ide_init_drive_cmd(&rq);
+ rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
+
+ drive->mult_req = arg;
+ drive->special.b.set_multmode = 1;
+- (void) ide_do_drive_cmd (drive, &rq, ide_wait);
++ (void)ide_do_drive_cmd(drive, &rq, ide_wait);
++
+ return (drive->mult_count == arg) ? 0 : -EIO;
+ }
+
+@@ -706,7 +707,7 @@ static int write_cache(ide_drive_t *drive, int arg)
+ return err;
+ }
+
+-static int do_idedisk_flushcache (ide_drive_t *drive)
++static int do_idedisk_flushcache(ide_drive_t *drive)
+ {
+ ide_task_t args;
+
+@@ -719,7 +720,7 @@ static int do_idedisk_flushcache (ide_drive_t *drive)
+ return ide_no_data_taskfile(drive, &args);
+ }
+
+-static int set_acoustic (ide_drive_t *drive, int arg)
++static int set_acoustic(ide_drive_t *drive, int arg)
+ {
+ ide_task_t args;
+
+@@ -753,7 +754,7 @@ static int set_lba_addressing(ide_drive_t *drive, int arg)
+ return 0;
+
+ if (!idedisk_supports_lba48(drive->id))
+- return -EIO;
++ return -EIO;
+ drive->addressing = arg;
+ return 0;
+ }
+@@ -763,23 +764,35 @@ static void idedisk_add_settings(ide_drive_t *drive)
+ {
+ struct hd_driveid *id = drive->id;
+
+- ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->bios_cyl, NULL);
+- ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL);
+- ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL);
+- ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1, &drive->addressing, set_lba_addressing);
+- ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0, id->max_multsect, 1, 1, &drive->mult_count, set_multcount);
+- ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr);
+- ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1, &drive->lun, NULL);
+- ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->wcache, write_cache);
+- ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1, &drive->acoustic, set_acoustic);
+- ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->failures, NULL);
+- ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL);
++ ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
++ &drive->bios_cyl, NULL);
++ ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1,
++ &drive->bios_head, NULL);
++ ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1,
++ &drive->bios_sect, NULL);
++ ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1,
++ &drive->addressing, set_lba_addressing);
++ ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0,
++ id->max_multsect, 1, 1, &drive->mult_count,
++ set_multcount);
++ ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
++ &drive->nowerr, set_nowerr);
++ ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1,
++ &drive->lun, NULL);
++ ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1,
++ &drive->wcache, write_cache);
++ ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1,
++ &drive->acoustic, set_acoustic);
++ ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1,
++ &drive->failures, NULL);
++ ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535,
++ 1, 1, &drive->max_failures, NULL);
+ }
+ #else
+ static inline void idedisk_add_settings(ide_drive_t *drive) { ; }
+ #endif
+
+-static void idedisk_setup (ide_drive_t *drive)
++static void idedisk_setup(ide_drive_t *drive)
+ {
+ ide_hwif_t *hwif = drive->hwif;
+ struct hd_driveid *id = drive->id;
+@@ -792,11 +805,10 @@ static void idedisk_setup (ide_drive_t *drive)
+
+ if (drive->removable) {
+ /*
+- * Removable disks (eg. SYQUEST); ignore 'WD' drives
++ * Removable disks (eg. SYQUEST); ignore 'WD' drives
+ */
+- if (id->model[0] != 'W' || id->model[1] != 'D') {
++ if (id->model[0] != 'W' || id->model[1] != 'D')
+ drive->doorlocking = 1;
+- }
+ }
+
+ (void)set_lba_addressing(drive, 1);
+@@ -810,10 +822,11 @@ static void idedisk_setup (ide_drive_t *drive)
+ blk_queue_max_sectors(drive->queue, max_s);
+ }
+
+- printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name, drive->queue->max_sectors / 2);
++ printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name,
++ drive->queue->max_sectors / 2);
+
+ /* calculate drive capacity, and select LBA if possible */
+- init_idedisk_capacity (drive);
++ init_idedisk_capacity(drive);
+
+ /* limit drive capacity to 137GB if LBA48 cannot be used */
+ if (drive->addressing == 0 && drive->capacity64 > 1ULL << 28) {
+@@ -826,9 +839,9 @@ static void idedisk_setup (ide_drive_t *drive)
+
+ if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && drive->addressing) {
+ if (drive->capacity64 > 1ULL << 28) {
+- printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode will"
+- " be used for accessing sectors > %u\n",
+- drive->name, 1 << 28);
++ printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode"
++ " will be used for accessing sectors "
++ "> %u\n", drive->name, 1 << 28);
+ } else
+ drive->addressing = 0;
+ }
+@@ -837,7 +850,8 @@ static void idedisk_setup (ide_drive_t *drive)
+ * if possible, give fdisk access to more of the drive,
+ * by correcting bios_cyls:
+ */
+- capacity = idedisk_capacity (drive);
++ capacity = idedisk_capacity(drive);
++
+ if (!drive->forced_geom) {
+
+ if (idedisk_supports_lba48(drive->id)) {
+@@ -993,7 +1007,8 @@ static int idedisk_open(struct inode *inode, struct file *filp)
+ struct ide_disk_obj *idkp;
+ ide_drive_t *drive;
+
+- if (!(idkp = ide_disk_get(disk)))
++ idkp = ide_disk_get(disk);
++ if (idkp == NULL)
+ return -ENXIO;
+
+ drive = idkp->drive;
+@@ -1115,13 +1130,13 @@ static int idedisk_revalidate_disk(struct gendisk *disk)
+ }
+
+ static struct block_device_operations idedisk_ops = {
+- .owner = THIS_MODULE,
+- .open = idedisk_open,
+- .release = idedisk_release,
+- .ioctl = idedisk_ioctl,
+- .getgeo = idedisk_getgeo,
+- .media_changed = idedisk_media_changed,
+- .revalidate_disk= idedisk_revalidate_disk
++ .owner = THIS_MODULE,
++ .open = idedisk_open,
++ .release = idedisk_release,
++ .ioctl = idedisk_ioctl,
++ .getgeo = idedisk_getgeo,
++ .media_changed = idedisk_media_changed,
++ .revalidate_disk = idedisk_revalidate_disk
+ };
+
+ MODULE_DESCRIPTION("ATA DISK Driver");
+@@ -1184,7 +1199,7 @@ failed:
+ return -ENODEV;
+ }
+
+-static void __exit idedisk_exit (void)
++static void __exit idedisk_exit(void)
+ {
+ driver_unregister(&idedisk_driver.gen_driver);
+ }
+diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
+index d61e578..8757e5e 100644
+--- a/drivers/ide/ide-dma.c
++++ b/drivers/ide/ide-dma.c
+@@ -703,17 +703,8 @@ static int ide_tune_dma(ide_drive_t *drive)
+
+ speed = ide_max_dma_mode(drive);
+
+- if (!speed) {
+- /* is this really correct/needed? */
+- if ((hwif->host_flags & IDE_HFLAG_CY82C693) &&
+- ide_dma_good_drive(drive))
+- return 1;
+- else
+- return 0;
+- }
+-
+- if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
+- return 1;
++ if (!speed)
++ return 0;
+
+ if (ide_set_dma_mode(drive, speed))
+ return 0;
+diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
+index faf22d7..ed19a8b 100644
+--- a/drivers/ide/ide-floppy.c
++++ b/drivers/ide/ide-floppy.c
+@@ -78,40 +78,6 @@
+ */
+ #define IDEFLOPPY_PC_STACK (10 + IDEFLOPPY_MAX_PC_RETRIES)
+
+-typedef struct idefloppy_packet_command_s {
+- u8 c[12]; /* Actual packet bytes */
+- int retries; /* On each retry, we increment
+- retries */
+- int error; /* Error code */
+- int request_transfer; /* Bytes to transfer */
+- int actually_transferred; /* Bytes actually transferred */
+- int buffer_size; /* Size of our data buffer */
+- int b_count; /* Missing/Available data on
+- the current buffer */
+- struct request *rq; /* The corresponding request */
+- u8 *buffer; /* Data buffer */
+- u8 *current_position; /* Pointer into above buffer */
+- void (*callback) (ide_drive_t *); /* Called when this packet
+- command is completed */
+- u8 pc_buffer[IDEFLOPPY_PC_BUFFER_SIZE]; /* Temporary buffer */
+- unsigned long flags; /* Status/Action bit flags: long
+- for set_bit */
+-} idefloppy_pc_t;
+-
+-/* Packet command flag bits. */
+-enum {
+- /* 1 when we prefer to use DMA if possible */
+- PC_FLAG_DMA_RECOMMENDED = (1 << 0),
+- /* 1 while DMA in progress */
+- PC_FLAG_DMA_IN_PROGRESS = (1 << 1),
+- /* 1 when encountered problem during DMA */
+- PC_FLAG_DMA_ERROR = (1 << 2),
+- /* Data direction */
+- PC_FLAG_WRITING = (1 << 3),
+- /* Suppress error reporting */
+- PC_FLAG_SUPPRESS_ERROR = (1 << 4),
+-};
+-
+ /* format capacities descriptor codes */
+ #define CAPACITY_INVALID 0x00
+ #define CAPACITY_UNFORMATTED 0x01
+@@ -131,11 +97,11 @@ typedef struct ide_floppy_obj {
+ unsigned int openers; /* protected by BKL for now */
+
+ /* Current packet command */
+- idefloppy_pc_t *pc;
++ struct ide_atapi_pc *pc;
+ /* Last failed packet command */
+- idefloppy_pc_t *failed_pc;
++ struct ide_atapi_pc *failed_pc;
+ /* Packet command stack */
+- idefloppy_pc_t pc_stack[IDEFLOPPY_PC_STACK];
++ struct ide_atapi_pc pc_stack[IDEFLOPPY_PC_STACK];
+ /* Next free packet command storage space */
+ int pc_stack_index;
+ struct request rq_stack[IDEFLOPPY_PC_STACK];
+@@ -195,32 +161,6 @@ enum {
+ #define IDEFLOPPY_ERROR_GENERAL 101
+
+ /*
+- * The following is used to format the general configuration word of the
+- * ATAPI IDENTIFY DEVICE command.
+- */
+-struct idefloppy_id_gcw {
+-#if defined(__LITTLE_ENDIAN_BITFIELD)
+- unsigned packet_size :2; /* Packet Size */
+- unsigned reserved234 :3; /* Reserved */
+- unsigned drq_type :2; /* Command packet DRQ type */
+- unsigned removable :1; /* Removable media */
+- unsigned device_type :5; /* Device type */
+- unsigned reserved13 :1; /* Reserved */
+- unsigned protocol :2; /* Protocol type */
+-#elif defined(__BIG_ENDIAN_BITFIELD)
+- unsigned protocol :2; /* Protocol type */
+- unsigned reserved13 :1; /* Reserved */
+- unsigned device_type :5; /* Device type */
+- unsigned removable :1; /* Removable media */
+- unsigned drq_type :2; /* Command packet DRQ type */
+- unsigned reserved234 :3; /* Reserved */
+- unsigned packet_size :2; /* Packet Size */
+-#else
+-#error "Bitfield endianness not defined! Check your byteorder.h"
+-#endif
+-};
+-
+-/*
+ * Pages of the SELECT SENSE / MODE SENSE packet commands.
+ * See SFF-8070i spec.
+ */
+@@ -256,27 +196,10 @@ static void ide_floppy_put(struct ide_floppy_obj *floppy)
+ }
+
+ /*
+- * Too bad. The drive wants to send us data which we are not ready to accept.
+- * Just throw it away.
+- */
+-static void idefloppy_discard_data(ide_drive_t *drive, unsigned int bcount)
+-{
+- while (bcount--)
+- (void) HWIF(drive)->INB(IDE_DATA_REG);
+-}
+-
+-static void idefloppy_write_zeros(ide_drive_t *drive, unsigned int bcount)
+-{
+- while (bcount--)
+- HWIF(drive)->OUTB(0, IDE_DATA_REG);
+-}
+-
+-
+-/*
+ * Used to finish servicing a request. For read/write requests, we will call
+ * ide_end_request to pass to the next buffer.
+ */
+-static int idefloppy_do_end_request(ide_drive_t *drive, int uptodate, int nsecs)
++static int idefloppy_end_request(ide_drive_t *drive, int uptodate, int nsecs)
+ {
+ idefloppy_floppy_t *floppy = drive->driver_data;
+ struct request *rq = HWGROUP(drive)->rq;
+@@ -305,7 +228,7 @@ static int idefloppy_do_end_request(ide_drive_t *drive, int uptodate, int nsecs)
+ return 0;
+ }
+
+-static void ide_floppy_io_buffers(ide_drive_t *drive, idefloppy_pc_t *pc,
++static void ide_floppy_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
+ unsigned int bcount, int direction)
+ {
+ struct request *rq = pc->rq;
+@@ -333,26 +256,26 @@ static void ide_floppy_io_buffers(ide_drive_t *drive, idefloppy_pc_t *pc,
+ done += count;
+ }
+
+- idefloppy_do_end_request(drive, 1, done >> 9);
++ idefloppy_end_request(drive, 1, done >> 9);
+
+ if (bcount) {
+ printk(KERN_ERR "%s: leftover data in %s, bcount == %d\n",
+ drive->name, __func__, bcount);
+ if (direction)
+- idefloppy_write_zeros(drive, bcount);
++ ide_atapi_write_zeros(drive, bcount);
+ else
+- idefloppy_discard_data(drive, bcount);
+-
++ ide_atapi_discard_data(drive, bcount);
+ }
+ }
+
+-static void idefloppy_update_buffers(ide_drive_t *drive, idefloppy_pc_t *pc)
++static void idefloppy_update_buffers(ide_drive_t *drive,
++ struct ide_atapi_pc *pc)
+ {
+ struct request *rq = pc->rq;
+ struct bio *bio = rq->bio;
+
+ while ((bio = rq->bio) != NULL)
+- idefloppy_do_end_request(drive, 1, 0);
++ idefloppy_end_request(drive, 1, 0);
+ }
+
+ /*
+@@ -360,7 +283,7 @@ static void idefloppy_update_buffers(ide_drive_t *drive, idefloppy_pc_t *pc)
+ * the current request so that it will be processed immediately, on the next
+ * pass through the driver.
+ */
+-static void idefloppy_queue_pc_head(ide_drive_t *drive, idefloppy_pc_t *pc,
++static void idefloppy_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc,
+ struct request *rq)
+ {
+ struct ide_floppy_obj *floppy = drive->driver_data;
+@@ -372,7 +295,7 @@ static void idefloppy_queue_pc_head(ide_drive_t *drive, idefloppy_pc_t *pc,
+ (void) ide_do_drive_cmd(drive, rq, ide_preempt);
+ }
+
+-static idefloppy_pc_t *idefloppy_next_pc_storage(ide_drive_t *drive)
++static struct ide_atapi_pc *idefloppy_next_pc_storage(ide_drive_t *drive)
+ {
+ idefloppy_floppy_t *floppy = drive->driver_data;
+
+@@ -393,7 +316,7 @@ static struct request *idefloppy_next_rq_storage(ide_drive_t *drive)
+ static void idefloppy_request_sense_callback(ide_drive_t *drive)
+ {
+ idefloppy_floppy_t *floppy = drive->driver_data;
+- u8 *buf = floppy->pc->buffer;
++ u8 *buf = floppy->pc->buf;
+
+ debug_log("Reached %s\n", __func__);
+
+@@ -418,11 +341,11 @@ static void idefloppy_request_sense_callback(ide_drive_t *drive)
+ floppy->ascq);
+
+
+- idefloppy_do_end_request(drive, 1, 0);
++ idefloppy_end_request(drive, 1, 0);
+ } else {
+ printk(KERN_ERR "Error in REQUEST SENSE itself - Aborting"
+ " request!\n");
+- idefloppy_do_end_request(drive, 0, 0);
++ idefloppy_end_request(drive, 0, 0);
+ }
+ }
+
+@@ -433,27 +356,27 @@ static void idefloppy_pc_callback(ide_drive_t *drive)
+
+ debug_log("Reached %s\n", __func__);
+
+- idefloppy_do_end_request(drive, floppy->pc->error ? 0 : 1, 0);
++ idefloppy_end_request(drive, floppy->pc->error ? 0 : 1, 0);
+ }
+
+-static void idefloppy_init_pc(idefloppy_pc_t *pc)
++static void idefloppy_init_pc(struct ide_atapi_pc *pc)
+ {
+ memset(pc->c, 0, 12);
+ pc->retries = 0;
+ pc->flags = 0;
+- pc->request_transfer = 0;
+- pc->buffer = pc->pc_buffer;
+- pc->buffer_size = IDEFLOPPY_PC_BUFFER_SIZE;
+- pc->callback = &idefloppy_pc_callback;
++ pc->req_xfer = 0;
++ pc->buf = pc->pc_buf;
++ pc->buf_size = IDEFLOPPY_PC_BUFFER_SIZE;
++ pc->idefloppy_callback = &idefloppy_pc_callback;
+ }
+
+-static void idefloppy_create_request_sense_cmd(idefloppy_pc_t *pc)
++static void idefloppy_create_request_sense_cmd(struct ide_atapi_pc *pc)
+ {
+ idefloppy_init_pc(pc);
+ pc->c[0] = GPCMD_REQUEST_SENSE;
+ pc->c[4] = 255;
+- pc->request_transfer = 18;
+- pc->callback = &idefloppy_request_sense_callback;
++ pc->req_xfer = 18;
++ pc->idefloppy_callback = &idefloppy_request_sense_callback;
+ }
+
+ /*
+@@ -462,7 +385,7 @@ static void idefloppy_create_request_sense_cmd(idefloppy_pc_t *pc)
+ */
+ static void idefloppy_retry_pc(ide_drive_t *drive)
+ {
+- idefloppy_pc_t *pc;
++ struct ide_atapi_pc *pc;
+ struct request *rq;
+
+ (void)ide_read_error(drive);
+@@ -473,11 +396,11 @@ static void idefloppy_retry_pc(ide_drive_t *drive)
+ }
+
+ /* The usual interrupt handler called during a packet command. */
+-static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
++static ide_startstop_t idefloppy_pc_intr(ide_drive_t *drive)
+ {
+ idefloppy_floppy_t *floppy = drive->driver_data;
+ ide_hwif_t *hwif = drive->hwif;
+- idefloppy_pc_t *pc = floppy->pc;
++ struct ide_atapi_pc *pc = floppy->pc;
+ struct request *rq = pc->rq;
+ xfer_func_t *xferfunc;
+ unsigned int temp;
+@@ -494,7 +417,7 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
+ rq_data_dir(rq) ? "write" : "read");
+ pc->flags |= PC_FLAG_DMA_ERROR;
+ } else {
+- pc->actually_transferred = pc->request_transfer;
++ pc->xferred = pc->req_xfer;
+ idefloppy_update_buffers(drive, pc);
+ }
+ debug_log("DMA finished\n");
+@@ -506,7 +429,7 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
+ /* No more interrupts */
+ if ((stat & DRQ_STAT) == 0) {
+ debug_log("Packet command completed, %d bytes transferred\n",
+- pc->actually_transferred);
++ pc->xferred);
+ pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
+
+ local_irq_enable_in_hardirq();
+@@ -529,7 +452,7 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
+ if (floppy->failed_pc == pc)
+ floppy->failed_pc = NULL;
+ /* Command finished - Call the callback function */
+- pc->callback(drive);
++ pc->idefloppy_callback(drive);
+ return ide_stopped;
+ }
+
+@@ -542,10 +465,10 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
+ }
+
+ /* Get the number of bytes to transfer */
+- bcount = (hwif->INB(IDE_BCOUNTH_REG) << 8) |
+- hwif->INB(IDE_BCOUNTL_REG);
++ bcount = (hwif->INB(hwif->io_ports[IDE_BCOUNTH_OFFSET]) << 8) |
++ hwif->INB(hwif->io_ports[IDE_BCOUNTL_OFFSET]);
+ /* on this interrupt */
+- ireason = hwif->INB(IDE_IREASON_REG);
++ ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+
+ if (ireason & CD) {
+ printk(KERN_ERR "ide-floppy: CoD != 0 in %s\n", __func__);
+@@ -561,13 +484,13 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
+ }
+ if (!(pc->flags & PC_FLAG_WRITING)) {
+ /* Reading - Check that we have enough space */
+- temp = pc->actually_transferred + bcount;
+- if (temp > pc->request_transfer) {
+- if (temp > pc->buffer_size) {
++ temp = pc->xferred + bcount;
++ if (temp > pc->req_xfer) {
++ if (temp > pc->buf_size) {
+ printk(KERN_ERR "ide-floppy: The floppy wants "
+ "to send us more data than expected "
+ "- discarding data\n");
+- idefloppy_discard_data(drive, bcount);
++ ide_atapi_discard_data(drive, bcount);
+
+ ide_set_handler(drive,
+ &idefloppy_pc_intr,
+@@ -584,15 +507,15 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
+ else
+ xferfunc = hwif->atapi_input_bytes;
+
+- if (pc->buffer)
+- xferfunc(drive, pc->current_position, bcount);
++ if (pc->buf)
++ xferfunc(drive, pc->cur_pos, bcount);
+ else
+ ide_floppy_io_buffers(drive, pc, bcount,
+ !!(pc->flags & PC_FLAG_WRITING));
+
+ /* Update the current position */
+- pc->actually_transferred += bcount;
+- pc->current_position += bcount;
++ pc->xferred += bcount;
++ pc->cur_pos += bcount;
+
+ /* And set the interrupt handler again */
+ ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);
+@@ -606,6 +529,7 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
+ */
+ static ide_startstop_t idefloppy_transfer_pc(ide_drive_t *drive)
+ {
++ ide_hwif_t *hwif = drive->hwif;
+ ide_startstop_t startstop;
+ idefloppy_floppy_t *floppy = drive->driver_data;
+ u8 ireason;
+@@ -615,7 +539,7 @@ static ide_startstop_t idefloppy_transfer_pc(ide_drive_t *drive)
+ "initiated yet DRQ isn't asserted\n");
+ return startstop;
+ }
+- ireason = drive->hwif->INB(IDE_IREASON_REG);
++ ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+ if ((ireason & CD) == 0 || (ireason & IO)) {
+ printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while "
+ "issuing a packet command\n");
+@@ -652,6 +576,7 @@ static int idefloppy_transfer_pc2(ide_drive_t *drive)
+
+ static ide_startstop_t idefloppy_transfer_pc1(ide_drive_t *drive)
+ {
++ ide_hwif_t *hwif = drive->hwif;
+ idefloppy_floppy_t *floppy = drive->driver_data;
+ ide_startstop_t startstop;
+ u8 ireason;
+@@ -661,7 +586,7 @@ static ide_startstop_t idefloppy_transfer_pc1(ide_drive_t *drive)
+ "initiated yet DRQ isn't asserted\n");
+ return startstop;
+ }
+- ireason = drive->hwif->INB(IDE_IREASON_REG);
++ ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+ if ((ireason & CD) == 0 || (ireason & IO)) {
+ printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) "
+ "while issuing a packet command\n");
+@@ -682,7 +607,7 @@ static ide_startstop_t idefloppy_transfer_pc1(ide_drive_t *drive)
+ }
+
+ static void ide_floppy_report_error(idefloppy_floppy_t *floppy,
+- idefloppy_pc_t *pc)
++ struct ide_atapi_pc *pc)
+ {
+ /* supress error messages resulting from Medium not present */
+ if (floppy->sense_key == 0x02 &&
+@@ -698,7 +623,7 @@ static void ide_floppy_report_error(idefloppy_floppy_t *floppy,
+ }
+
+ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
+- idefloppy_pc_t *pc)
++ struct ide_atapi_pc *pc)
+ {
+ idefloppy_floppy_t *floppy = drive->driver_data;
+ ide_hwif_t *hwif = drive->hwif;
+@@ -719,7 +644,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
+ pc->error = IDEFLOPPY_ERROR_GENERAL;
+
+ floppy->failed_pc = NULL;
+- pc->callback(drive);
++ pc->idefloppy_callback(drive);
+ return ide_stopped;
+ }
+
+@@ -727,9 +652,9 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
+
+ pc->retries++;
+ /* We haven't transferred any data yet */
+- pc->actually_transferred = 0;
+- pc->current_position = pc->buffer;
+- bcount = min(pc->request_transfer, 63 * 1024);
++ pc->xferred = 0;
++ pc->cur_pos = pc->buf;
++ bcount = min(pc->req_xfer, 63 * 1024);
+
+ if (pc->flags & PC_FLAG_DMA_ERROR) {
+ pc->flags &= ~PC_FLAG_DMA_ERROR;
+@@ -757,7 +682,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
+ /* immediate */
+ pkt_xfer_routine = &idefloppy_transfer_pc;
+ }
+-
++
+ if (floppy->flags & IDEFLOPPY_FLAG_DRQ_INTERRUPT) {
+ /* Issue the packet command */
+ ide_execute_command(drive, WIN_PACKETCMD,
+@@ -767,7 +692,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
+ return ide_started;
+ } else {
+ /* Issue the packet command */
+- HWIF(drive)->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG);
++ hwif->OUTB(WIN_PACKETCMD, hwif->io_ports[IDE_COMMAND_OFFSET]);
+ return (*pkt_xfer_routine) (drive);
+ }
+ }
+@@ -776,11 +701,11 @@ static void idefloppy_rw_callback(ide_drive_t *drive)
+ {
+ debug_log("Reached %s\n", __func__);
+
+- idefloppy_do_end_request(drive, 1, 0);
++ idefloppy_end_request(drive, 1, 0);
+ return;
+ }
+
+-static void idefloppy_create_prevent_cmd(idefloppy_pc_t *pc, int prevent)
++static void idefloppy_create_prevent_cmd(struct ide_atapi_pc *pc, int prevent)
+ {
+ debug_log("creating prevent removal command, prevent = %d\n", prevent);
+
+@@ -789,39 +714,39 @@ static void idefloppy_create_prevent_cmd(idefloppy_pc_t *pc, int prevent)
+ pc->c[4] = prevent;
+ }
+
+-static void idefloppy_create_read_capacity_cmd(idefloppy_pc_t *pc)
++static void idefloppy_create_read_capacity_cmd(struct ide_atapi_pc *pc)
+ {
+ idefloppy_init_pc(pc);
+ pc->c[0] = GPCMD_READ_FORMAT_CAPACITIES;
+ pc->c[7] = 255;
+ pc->c[8] = 255;
+- pc->request_transfer = 255;
++ pc->req_xfer = 255;
+ }
+
+-static void idefloppy_create_format_unit_cmd(idefloppy_pc_t *pc, int b, int l,
+- int flags)
++static void idefloppy_create_format_unit_cmd(struct ide_atapi_pc *pc, int b,
++ int l, int flags)
+ {
+ idefloppy_init_pc(pc);
+ pc->c[0] = GPCMD_FORMAT_UNIT;
+ pc->c[1] = 0x17;
+
+- memset(pc->buffer, 0, 12);
+- pc->buffer[1] = 0xA2;
++ memset(pc->buf, 0, 12);
++ pc->buf[1] = 0xA2;
+ /* Default format list header, u8 1: FOV/DCRT/IMM bits set */
+
+ if (flags & 1) /* Verify bit on... */
+- pc->buffer[1] ^= 0x20; /* ... turn off DCRT bit */
+- pc->buffer[3] = 8;
++ pc->buf[1] ^= 0x20; /* ... turn off DCRT bit */
++ pc->buf[3] = 8;
+
+- put_unaligned(cpu_to_be32(b), (unsigned int *)(&pc->buffer[4]));
+- put_unaligned(cpu_to_be32(l), (unsigned int *)(&pc->buffer[8]));
+- pc->buffer_size = 12;
++ put_unaligned(cpu_to_be32(b), (unsigned int *)(&pc->buf[4]));
++ put_unaligned(cpu_to_be32(l), (unsigned int *)(&pc->buf[8]));
++ pc->buf_size = 12;
+ pc->flags |= PC_FLAG_WRITING;
+ }
+
+ /* A mode sense command is used to "sense" floppy parameters. */
+-static void idefloppy_create_mode_sense_cmd(idefloppy_pc_t *pc, u8 page_code,
+- u8 type)
++static void idefloppy_create_mode_sense_cmd(struct ide_atapi_pc *pc,
++ u8 page_code, u8 type)
+ {
+ u16 length = 8; /* sizeof(Mode Parameter Header) = 8 Bytes */
+
+@@ -842,24 +767,24 @@ static void idefloppy_create_mode_sense_cmd(idefloppy_pc_t *pc, u8 page_code,
+ "in create_mode_sense_cmd\n");
+ }
+ put_unaligned(cpu_to_be16(length), (u16 *) &pc->c[7]);
+- pc->request_transfer = length;
++ pc->req_xfer = length;
+ }
+
+-static void idefloppy_create_start_stop_cmd(idefloppy_pc_t *pc, int start)
++static void idefloppy_create_start_stop_cmd(struct ide_atapi_pc *pc, int start)
+ {
+ idefloppy_init_pc(pc);
+ pc->c[0] = GPCMD_START_STOP_UNIT;
+ pc->c[4] = start;
+ }
+
+-static void idefloppy_create_test_unit_ready_cmd(idefloppy_pc_t *pc)
++static void idefloppy_create_test_unit_ready_cmd(struct ide_atapi_pc *pc)
+ {
+ idefloppy_init_pc(pc);
+ pc->c[0] = GPCMD_TEST_UNIT_READY;
+ }
+
+ static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy,
+- idefloppy_pc_t *pc, struct request *rq,
++ struct ide_atapi_pc *pc, struct request *rq,
+ unsigned long sector)
+ {
+ int block = sector / floppy->bs_factor;
+@@ -874,41 +799,41 @@ static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy,
+ put_unaligned(cpu_to_be16(blocks), (unsigned short *)&pc->c[7]);
+ put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[2]);
+
+- pc->callback = &idefloppy_rw_callback;
++ pc->idefloppy_callback = &idefloppy_rw_callback;
+ pc->rq = rq;
+ pc->b_count = cmd == READ ? 0 : rq->bio->bi_size;
+ if (rq->cmd_flags & REQ_RW)
+ pc->flags |= PC_FLAG_WRITING;
+- pc->buffer = NULL;
+- pc->request_transfer = pc->buffer_size = blocks * floppy->block_size;
++ pc->buf = NULL;
++ pc->req_xfer = pc->buf_size = blocks * floppy->block_size;
+ pc->flags |= PC_FLAG_DMA_RECOMMENDED;
+ }
+
+ static void idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy,
+- idefloppy_pc_t *pc, struct request *rq)
++ struct ide_atapi_pc *pc, struct request *rq)
+ {
+ idefloppy_init_pc(pc);
+- pc->callback = &idefloppy_rw_callback;
++ pc->idefloppy_callback = &idefloppy_rw_callback;
+ memcpy(pc->c, rq->cmd, sizeof(pc->c));
+ pc->rq = rq;
+ pc->b_count = rq->data_len;
+ if (rq->data_len && rq_data_dir(rq) == WRITE)
+ pc->flags |= PC_FLAG_WRITING;
+- pc->buffer = rq->data;
++ pc->buf = rq->data;
+ if (rq->bio)
+ pc->flags |= PC_FLAG_DMA_RECOMMENDED;
+ /*
+ * possibly problematic, doesn't look like ide-floppy correctly
+ * handled scattered requests if dma fails...
+ */
+- pc->request_transfer = pc->buffer_size = rq->data_len;
++ pc->req_xfer = pc->buf_size = rq->data_len;
+ }
+
+ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive,
+ struct request *rq, sector_t block_s)
+ {
+ idefloppy_floppy_t *floppy = drive->driver_data;
+- idefloppy_pc_t *pc;
++ struct ide_atapi_pc *pc;
+ unsigned long block = (unsigned long)block_s;
+
+ debug_log("dev: %s, cmd_type: %x, errors: %d\n",
+@@ -924,7 +849,7 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive,
+ else
+ printk(KERN_ERR "ide-floppy: %s: I/O error\n",
+ drive->name);
+- idefloppy_do_end_request(drive, 0, 0);
++ idefloppy_end_request(drive, 0, 0);
+ return ide_stopped;
+ }
+ if (blk_fs_request(rq)) {
+@@ -932,20 +857,20 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive,
+ (rq->nr_sectors % floppy->bs_factor)) {
+ printk(KERN_ERR "%s: unsupported r/w request size\n",
+ drive->name);
+- idefloppy_do_end_request(drive, 0, 0);
++ idefloppy_end_request(drive, 0, 0);
+ return ide_stopped;
+ }
+ pc = idefloppy_next_pc_storage(drive);
+ idefloppy_create_rw_cmd(floppy, pc, rq, block);
+ } else if (blk_special_request(rq)) {
+- pc = (idefloppy_pc_t *) rq->buffer;
++ pc = (struct ide_atapi_pc *) rq->buffer;
+ } else if (blk_pc_request(rq)) {
+ pc = idefloppy_next_pc_storage(drive);
+ idefloppy_blockpc_cmd(floppy, pc, rq);
+ } else {
+ blk_dump_rq_flags(rq,
+ "ide-floppy: unsupported command in queue");
+- idefloppy_do_end_request(drive, 0, 0);
++ idefloppy_end_request(drive, 0, 0);
+ return ide_stopped;
+ }
+
+@@ -957,7 +882,7 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive,
+ * Add a special packet command request to the tail of the request queue,
+ * and wait for it to be serviced.
+ */
+-static int idefloppy_queue_pc_tail(ide_drive_t *drive, idefloppy_pc_t *pc)
++static int idefloppy_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc)
+ {
+ struct ide_floppy_obj *floppy = drive->driver_data;
+ struct request rq;
+@@ -977,7 +902,7 @@ static int idefloppy_queue_pc_tail(ide_drive_t *drive, idefloppy_pc_t *pc)
+ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
+ {
+ idefloppy_floppy_t *floppy = drive->driver_data;
+- idefloppy_pc_t pc;
++ struct ide_atapi_pc pc;
+ u8 *page;
+ int capacity, lba_capacity;
+ u16 transfer_rate, sector_size, cyls, rpm;
+@@ -991,16 +916,16 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
+ " parameters\n");
+ return 1;
+ }
+- floppy->wp = !!(pc.buffer[3] & 0x80);
++ floppy->wp = !!(pc.buf[3] & 0x80);
+ set_disk_ro(floppy->disk, floppy->wp);
+- page = &pc.buffer[8];
++ page = &pc.buf[8];
+
+- transfer_rate = be16_to_cpu(*(u16 *)&pc.buffer[8 + 2]);
+- sector_size = be16_to_cpu(*(u16 *)&pc.buffer[8 + 6]);
+- cyls = be16_to_cpu(*(u16 *)&pc.buffer[8 + 8]);
+- rpm = be16_to_cpu(*(u16 *)&pc.buffer[8 + 28]);
+- heads = pc.buffer[8 + 4];
+- sectors = pc.buffer[8 + 5];
++ transfer_rate = be16_to_cpu(*(u16 *)&pc.buf[8 + 2]);
++ sector_size = be16_to_cpu(*(u16 *)&pc.buf[8 + 6]);
++ cyls = be16_to_cpu(*(u16 *)&pc.buf[8 + 8]);
++ rpm = be16_to_cpu(*(u16 *)&pc.buf[8 + 28]);
++ heads = pc.buf[8 + 4];
++ sectors = pc.buf[8 + 5];
+
+ capacity = cyls * heads * sectors * sector_size;
+
+@@ -1029,7 +954,7 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
+ static int idefloppy_get_sfrp_bit(ide_drive_t *drive)
+ {
+ idefloppy_floppy_t *floppy = drive->driver_data;
+- idefloppy_pc_t pc;
++ struct ide_atapi_pc pc;
+
+ floppy->srfp = 0;
+ idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE,
+@@ -1039,7 +964,7 @@ static int idefloppy_get_sfrp_bit(ide_drive_t *drive)
+ if (idefloppy_queue_pc_tail(drive, &pc))
+ return 1;
+
+- floppy->srfp = pc.buffer[8 + 2] & 0x40;
++ floppy->srfp = pc.buf[8 + 2] & 0x40;
+ return (0);
+ }
+
+@@ -1050,7 +975,7 @@ static int idefloppy_get_sfrp_bit(ide_drive_t *drive)
+ static int ide_floppy_get_capacity(ide_drive_t *drive)
+ {
+ idefloppy_floppy_t *floppy = drive->driver_data;
+- idefloppy_pc_t pc;
++ struct ide_atapi_pc pc;
+ u8 *cap_desc;
+ u8 header_len, desc_cnt;
+ int i, rc = 1, blocks, length;
+@@ -1066,15 +991,15 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
+ printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n");
+ return 1;
+ }
+- header_len = pc.buffer[3];
+- cap_desc = &pc.buffer[4];
++ header_len = pc.buf[3];
++ cap_desc = &pc.buf[4];
+ desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */
+
+ for (i = 0; i < desc_cnt; i++) {
+ unsigned int desc_start = 4 + i*8;
+
+- blocks = be32_to_cpu(*(u32 *)&pc.buffer[desc_start]);
+- length = be16_to_cpu(*(u16 *)&pc.buffer[desc_start + 6]);
++ blocks = be32_to_cpu(*(u32 *)&pc.buf[desc_start]);
++ length = be16_to_cpu(*(u16 *)&pc.buf[desc_start + 6]);
+
+ debug_log("Descriptor %d: %dkB, %d blocks, %d sector size\n",
+ i, blocks * length / 1024, blocks, length);
+@@ -1085,7 +1010,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
+ * the code below is valid only for the 1st descriptor, ie i=0
+ */
+
+- switch (pc.buffer[desc_start + 4] & 0x03) {
++ switch (pc.buf[desc_start + 4] & 0x03) {
+ /* Clik! drive returns this instead of CAPACITY_CURRENT */
+ case CAPACITY_UNFORMATTED:
+ if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE))
+@@ -1130,7 +1055,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
+ break;
+ }
+ debug_log("Descriptor 0 Code: %d\n",
+- pc.buffer[desc_start + 4] & 0x03);
++ pc.buf[desc_start + 4] & 0x03);
+ }
+
+ /* Clik! disk does not support get_flexible_disk_page */
+@@ -1162,7 +1087,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
+
+ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
+ {
+- idefloppy_pc_t pc;
++ struct ide_atapi_pc pc;
+ u8 header_len, desc_cnt;
+ int i, blocks, length, u_array_size, u_index;
+ int __user *argp;
+@@ -1178,7 +1103,7 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
+ printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n");
+ return (-EIO);
+ }
+- header_len = pc.buffer[3];
++ header_len = pc.buf[3];
+ desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */
+
+ u_index = 0;
+@@ -1195,8 +1120,8 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
+ if (u_index >= u_array_size)
+ break; /* User-supplied buffer too small */
+
+- blocks = be32_to_cpu(*(u32 *)&pc.buffer[desc_start]);
+- length = be16_to_cpu(*(u16 *)&pc.buffer[desc_start + 6]);
++ blocks = be32_to_cpu(*(u32 *)&pc.buf[desc_start]);
++ length = be16_to_cpu(*(u16 *)&pc.buf[desc_start + 6]);
+
+ if (put_user(blocks, argp))
+ return(-EFAULT);
+@@ -1227,7 +1152,7 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
+ static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg)
+ {
+ idefloppy_floppy_t *floppy = drive->driver_data;
+- idefloppy_pc_t pc;
++ struct ide_atapi_pc pc;
+ int progress_indication = 0x10000;
+
+ if (floppy->srfp) {
+@@ -1271,33 +1196,39 @@ static sector_t idefloppy_capacity(ide_drive_t *drive)
+ */
+ static int idefloppy_identify_device(ide_drive_t *drive, struct hd_driveid *id)
+ {
+- struct idefloppy_id_gcw gcw;
++ u8 gcw[2];
++ u8 device_type, protocol, removable, drq_type, packet_size;
+
+ *((u16 *) &gcw) = id->config;
+
++ device_type = gcw[1] & 0x1F;
++ removable = (gcw[0] & 0x80) >> 7;
++ protocol = (gcw[1] & 0xC0) >> 6;
++ drq_type = (gcw[0] & 0x60) >> 5;
++ packet_size = gcw[0] & 0x03;
++
+ #ifdef CONFIG_PPC
+ /* kludge for Apple PowerBook internal zip */
+- if ((gcw.device_type == 5) &&
+- !strstr(id->model, "CD-ROM") &&
+- strstr(id->model, "ZIP"))
+- gcw.device_type = 0;
++ if (device_type == 5 &&
++ !strstr(id->model, "CD-ROM") && strstr(id->model, "ZIP"))
++ device_type = 0;
+ #endif
+
+- if (gcw.protocol != 2)
++ if (protocol != 2)
+ printk(KERN_ERR "ide-floppy: Protocol (0x%02x) is not ATAPI\n",
+- gcw.protocol);
+- else if (gcw.device_type != 0)
++ protocol);
++ else if (device_type != 0)
+ printk(KERN_ERR "ide-floppy: Device type (0x%02x) is not set "
+- "to floppy\n", gcw.device_type);
+- else if (!gcw.removable)
++ "to floppy\n", device_type);
++ else if (!removable)
+ printk(KERN_ERR "ide-floppy: The removable flag is not set\n");
+- else if (gcw.drq_type == 3) {
++ else if (drq_type == 3)
+ printk(KERN_ERR "ide-floppy: Sorry, DRQ type (0x%02x) not "
+- "supported\n", gcw.drq_type);
+- } else if (gcw.packet_size != 0) {
++ "supported\n", drq_type);
++ else if (packet_size != 0)
+ printk(KERN_ERR "ide-floppy: Packet size (0x%02x) is not 12 "
+- "bytes long\n", gcw.packet_size);
+- } else
++ "bytes\n", packet_size);
++ else
+ return 1;
+ return 0;
+ }
+@@ -1322,11 +1253,12 @@ static inline void idefloppy_add_settings(ide_drive_t *drive) { ; }
+
+ static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
+ {
+- struct idefloppy_id_gcw gcw;
++ u8 gcw[2];
+
+ *((u16 *) &gcw) = drive->id->config;
+ floppy->pc = floppy->pc_stack;
+- if (gcw.drq_type == 1)
++
++ if (((gcw[0] & 0x60) >> 5) == 1)
+ floppy->flags |= IDEFLOPPY_FLAG_DRQ_INTERRUPT;
+ /*
+ * We used to check revisions here. At this point however I'm giving up.
+@@ -1413,7 +1345,7 @@ static ide_driver_t idefloppy_driver = {
+ .media = ide_floppy,
+ .supports_dsc_overlap = 0,
+ .do_request = idefloppy_do_request,
+- .end_request = idefloppy_do_end_request,
++ .end_request = idefloppy_end_request,
+ .error = __ide_error,
+ .abort = __ide_abort,
+ #ifdef CONFIG_IDE_PROC_FS
+@@ -1426,7 +1358,7 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
+ struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct ide_floppy_obj *floppy;
+ ide_drive_t *drive;
+- idefloppy_pc_t pc;
++ struct ide_atapi_pc pc;
+ int ret = 0;
+
+ debug_log("Reached %s\n", __func__);
+@@ -1489,7 +1421,7 @@ static int idefloppy_release(struct inode *inode, struct file *filp)
+ struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct ide_floppy_obj *floppy = ide_floppy_g(disk);
+ ide_drive_t *drive = floppy->drive;
+- idefloppy_pc_t pc;
++ struct ide_atapi_pc pc;
+
+ debug_log("Reached %s\n", __func__);
+
+@@ -1521,8 +1453,8 @@ static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+ return 0;
+ }
+
+-static int ide_floppy_lockdoor(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc,
+- unsigned long arg, unsigned int cmd)
++static int ide_floppy_lockdoor(idefloppy_floppy_t *floppy,
++ struct ide_atapi_pc *pc, unsigned long arg, unsigned int cmd)
+ {
+ if (floppy->openers > 1)
+ return -EBUSY;
+@@ -1551,7 +1483,7 @@ static int ide_floppy_format_unit(idefloppy_floppy_t *floppy,
+ int __user *arg)
+ {
+ int blocks, length, flags, err = 0;
+- idefloppy_pc_t pc;
++ struct ide_atapi_pc pc;
+
+ if (floppy->openers > 1) {
+ /* Don't format if someone is using the disk */
+@@ -1602,7 +1534,7 @@ static int idefloppy_ioctl(struct inode *inode, struct file *file,
+ struct block_device *bdev = inode->i_bdev;
+ struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk);
+ ide_drive_t *drive = floppy->drive;
+- idefloppy_pc_t pc;
++ struct ide_atapi_pc pc;
+ void __user *argp = (void __user *)arg;
+ int err;
+
+@@ -1664,13 +1596,13 @@ static int idefloppy_revalidate_disk(struct gendisk *disk)
+ }
+
+ static struct block_device_operations idefloppy_ops = {
+- .owner = THIS_MODULE,
+- .open = idefloppy_open,
+- .release = idefloppy_release,
+- .ioctl = idefloppy_ioctl,
+- .getgeo = idefloppy_getgeo,
+- .media_changed = idefloppy_media_changed,
+- .revalidate_disk= idefloppy_revalidate_disk
++ .owner = THIS_MODULE,
++ .open = idefloppy_open,
++ .release = idefloppy_release,
++ .ioctl = idefloppy_ioctl,
++ .getgeo = idefloppy_getgeo,
++ .media_changed = idefloppy_media_changed,
++ .revalidate_disk = idefloppy_revalidate_disk
+ };
+
+ static int ide_floppy_probe(ide_drive_t *drive)
+diff --git a/drivers/ide/ide-generic.c b/drivers/ide/ide-generic.c
+index 9ebec08..19f63e3 100644
+--- a/drivers/ide/ide-generic.c
++++ b/drivers/ide/ide-generic.c
+@@ -1,33 +1,126 @@
+ /*
+ * generic/default IDE host driver
+ *
+- * Copyright (C) 2004 Bartlomiej Zolnierkiewicz
++ * Copyright (C) 2004, 2008 Bartlomiej Zolnierkiewicz
+ * This code was split off from ide.c. See it for original copyrights.
+ *
+ * May be copied or modified under the terms of the GNU General Public License.
+ */
+
++/*
++ * For special cases new interfaces may be added using sysfs, i.e.
++ *
++ * echo -n "0x168:0x36e:10" > /sys/class/ide_generic/add
++ *
++ * will add an interface using I/O ports 0x168-0x16f/0x36e and IRQ 10.
++ */
++
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/module.h>
+ #include <linux/ide.h>
+
++#define DRV_NAME "ide_generic"
++
++static ssize_t store_add(struct class *cls, const char *buf, size_t n)
++{
++ ide_hwif_t *hwif;
++ unsigned int base, ctl;
++ int irq;
++ hw_regs_t hw;
++ u8 idx[] = { 0xff, 0xff, 0xff, 0xff };
++
++ if (sscanf(buf, "%x:%x:%d", &base, &ctl, &irq) != 3)
++ return -EINVAL;
++
++ hwif = ide_find_port();
++ if (hwif == NULL)
++ return -ENOENT;
++
++ memset(&hw, 0, sizeof(hw));
++ ide_std_init_ports(&hw, base, ctl);
++ hw.irq = irq;
++ hw.chipset = ide_generic;
++
++ ide_init_port_hw(hwif, &hw);
++
++ idx[0] = hwif->index;
++
++ ide_device_add(idx, NULL);
++
++ return n;
++};
++
++static struct class_attribute ide_generic_class_attrs[] = {
++ __ATTR(add, S_IWUSR, NULL, store_add),
++ __ATTR_NULL
++};
++
++static void ide_generic_class_release(struct class *cls)
++{
++ kfree(cls);
++}
++
++static int __init ide_generic_sysfs_init(void)
++{
++ struct class *cls;
++ int rc;
++
++ cls = kzalloc(sizeof(*cls), GFP_KERNEL);
++ if (!cls)
++ return -ENOMEM;
++
++ cls->name = DRV_NAME;
++ cls->owner = THIS_MODULE;
++ cls->class_release = ide_generic_class_release;
++ cls->class_attrs = ide_generic_class_attrs;
++
++ rc = class_register(cls);
++ if (rc) {
++ kfree(cls);
++ return rc;
++ }
++
++ return 0;
++}
++
+ static int __init ide_generic_init(void)
+ {
+ u8 idx[MAX_HWIFS];
+ int i;
+
+ for (i = 0; i < MAX_HWIFS; i++) {
+- ide_hwif_t *hwif = &ide_hwifs[i];
++ ide_hwif_t *hwif;
++ unsigned long io_addr = ide_default_io_base(i);
++ hw_regs_t hw;
++
++ if (io_addr) {
++ /*
++ * Skip probing if the corresponding
++ * slot is already occupied.
++ */
++ hwif = ide_find_port();
++ if (hwif == NULL || hwif->index != i) {
++ idx[i] = 0xff;
++ continue;
++ }
++
++ memset(&hw, 0, sizeof(hw));
++ ide_std_init_ports(&hw, io_addr, io_addr + 0x206);
++ hw.irq = ide_default_irq(io_addr);
++ ide_init_port_hw(hwif, &hw);
+
+- if (hwif->io_ports[IDE_DATA_OFFSET] && !hwif->present)
+ idx[i] = i;
+- else
++ } else
+ idx[i] = 0xff;
+ }
+
+ ide_device_add_all(idx, NULL);
+
++ if (ide_generic_sysfs_init())
++ printk(KERN_ERR DRV_NAME ": failed to create ide_generic "
++ "class\n");
++
+ return 0;
+ }
+
+diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
+index 7153796..51d181e 100644
+--- a/drivers/ide/ide-io.c
++++ b/drivers/ide/ide-io.c
+@@ -301,39 +301,45 @@ void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
+ struct ide_taskfile *tf = &task->tf;
+
+ if (task->tf_flags & IDE_TFLAG_IN_DATA) {
+- u16 data = hwif->INW(IDE_DATA_REG);
++ u16 data = hwif->INW(hwif->io_ports[IDE_DATA_OFFSET]);
+
+ tf->data = data & 0xff;
+ tf->hob_data = (data >> 8) & 0xff;
+ }
+
+ /* be sure we're looking at the low order bits */
+- hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG);
++ hwif->OUTB(drive->ctl & ~0x80, hwif->io_ports[IDE_CONTROL_OFFSET]);
+
+ if (task->tf_flags & IDE_TFLAG_IN_NSECT)
+- tf->nsect = hwif->INB(IDE_NSECTOR_REG);
++ tf->nsect = hwif->INB(hwif->io_ports[IDE_NSECTOR_OFFSET]);
+ if (task->tf_flags & IDE_TFLAG_IN_LBAL)
+- tf->lbal = hwif->INB(IDE_SECTOR_REG);
++ tf->lbal = hwif->INB(hwif->io_ports[IDE_SECTOR_OFFSET]);
+ if (task->tf_flags & IDE_TFLAG_IN_LBAM)
+- tf->lbam = hwif->INB(IDE_LCYL_REG);
++ tf->lbam = hwif->INB(hwif->io_ports[IDE_LCYL_OFFSET]);
+ if (task->tf_flags & IDE_TFLAG_IN_LBAH)
+- tf->lbah = hwif->INB(IDE_HCYL_REG);
++ tf->lbah = hwif->INB(hwif->io_ports[IDE_HCYL_OFFSET]);
+ if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
+- tf->device = hwif->INB(IDE_SELECT_REG);
++ tf->device = hwif->INB(hwif->io_ports[IDE_SELECT_OFFSET]);
+
+ if (task->tf_flags & IDE_TFLAG_LBA48) {
+- hwif->OUTB(drive->ctl | 0x80, IDE_CONTROL_REG);
++ hwif->OUTB(drive->ctl | 0x80,
++ hwif->io_ports[IDE_CONTROL_OFFSET]);
+
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
+- tf->hob_feature = hwif->INB(IDE_FEATURE_REG);
++ tf->hob_feature =
++ hwif->INB(hwif->io_ports[IDE_FEATURE_OFFSET]);
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
+- tf->hob_nsect = hwif->INB(IDE_NSECTOR_REG);
++ tf->hob_nsect =
++ hwif->INB(hwif->io_ports[IDE_NSECTOR_OFFSET]);
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
+- tf->hob_lbal = hwif->INB(IDE_SECTOR_REG);
++ tf->hob_lbal =
++ hwif->INB(hwif->io_ports[IDE_SECTOR_OFFSET]);
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
+- tf->hob_lbam = hwif->INB(IDE_LCYL_REG);
++ tf->hob_lbam =
++ hwif->INB(hwif->io_ports[IDE_LCYL_OFFSET]);
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
+- tf->hob_lbah = hwif->INB(IDE_HCYL_REG);
++ tf->hob_lbah =
++ hwif->INB(hwif->io_ports[IDE_HCYL_OFFSET]);
+ }
+ }
+
+@@ -448,7 +454,8 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8
+ if (err == ABRT_ERR) {
+ if (drive->select.b.lba &&
+ /* some newer drives don't support WIN_SPECIFY */
+- hwif->INB(IDE_COMMAND_REG) == WIN_SPECIFY)
++ hwif->INB(hwif->io_ports[IDE_COMMAND_OFFSET]) ==
++ WIN_SPECIFY)
+ return ide_stopped;
+ } else if ((err & BAD_CRC) == BAD_CRC) {
+ /* UDMA crc error, just retry the operation */
+@@ -500,7 +507,8 @@ static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u
+
+ if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
+ /* force an abort */
+- hwif->OUTB(WIN_IDLEIMMEDIATE, IDE_COMMAND_REG);
++ hwif->OUTB(WIN_IDLEIMMEDIATE,
++ hwif->io_ports[IDE_COMMAND_OFFSET]);
+
+ if (rq->errors >= ERROR_MAX) {
+ ide_kill_rq(drive, rq);
+@@ -718,10 +726,6 @@ static ide_startstop_t do_special (ide_drive_t *drive)
+ s->b.set_tune = 0;
+
+ if (set_pio_mode_abuse(drive->hwif, req_pio)) {
+-
+- if (hwif->set_pio_mode == NULL)
+- return ide_stopped;
+-
+ /*
+ * take ide_lock for drive->[no_]unmask/[no_]io_32bit
+ */
+diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
+index e77cee0..4594421 100644
+--- a/drivers/ide/ide-iops.c
++++ b/drivers/ide/ide-iops.c
+@@ -158,9 +158,12 @@ EXPORT_SYMBOL(default_hwif_mmiops);
+
+ void SELECT_DRIVE (ide_drive_t *drive)
+ {
+- if (HWIF(drive)->selectproc)
+- HWIF(drive)->selectproc(drive);
+- HWIF(drive)->OUTB(drive->select.all, IDE_SELECT_REG);
++ ide_hwif_t *hwif = drive->hwif;
++
++ if (hwif->selectproc)
++ hwif->selectproc(drive);
++
++ hwif->OUTB(drive->select.all, hwif->io_ports[IDE_SELECT_OFFSET]);
+ }
+
+ void SELECT_MASK (ide_drive_t *drive, int mask)
+@@ -194,15 +197,18 @@ static void ata_input_data(ide_drive_t *drive, void *buffer, u32 wcount)
+ if (io_32bit) {
+ if (io_32bit & 2) {
+ unsigned long flags;
++
+ local_irq_save(flags);
+- ata_vlb_sync(drive, IDE_NSECTOR_REG);
+- hwif->INSL(IDE_DATA_REG, buffer, wcount);
++ ata_vlb_sync(drive, hwif->io_ports[IDE_NSECTOR_OFFSET]);
++ hwif->INSL(hwif->io_ports[IDE_DATA_OFFSET], buffer,
++ wcount);
+ local_irq_restore(flags);
+ } else
+- hwif->INSL(IDE_DATA_REG, buffer, wcount);
+- } else {
+- hwif->INSW(IDE_DATA_REG, buffer, wcount<<1);
+- }
++ hwif->INSL(hwif->io_ports[IDE_DATA_OFFSET], buffer,
++ wcount);
++ } else
++ hwif->INSW(hwif->io_ports[IDE_DATA_OFFSET], buffer,
++ wcount << 1);
+ }
+
+ /*
+@@ -216,15 +222,18 @@ static void ata_output_data(ide_drive_t *drive, void *buffer, u32 wcount)
+ if (io_32bit) {
+ if (io_32bit & 2) {
+ unsigned long flags;
++
+ local_irq_save(flags);
+- ata_vlb_sync(drive, IDE_NSECTOR_REG);
+- hwif->OUTSL(IDE_DATA_REG, buffer, wcount);
++ ata_vlb_sync(drive, hwif->io_ports[IDE_NSECTOR_OFFSET]);
++ hwif->OUTSL(hwif->io_ports[IDE_DATA_OFFSET], buffer,
++ wcount);
+ local_irq_restore(flags);
+ } else
+- hwif->OUTSL(IDE_DATA_REG, buffer, wcount);
+- } else {
+- hwif->OUTSW(IDE_DATA_REG, buffer, wcount<<1);
+- }
++ hwif->OUTSL(hwif->io_ports[IDE_DATA_OFFSET], buffer,
++ wcount);
++ } else
++ hwif->OUTSW(hwif->io_ports[IDE_DATA_OFFSET], buffer,
++ wcount << 1);
+ }
+
+ /*
+@@ -243,13 +252,15 @@ static void atapi_input_bytes(ide_drive_t *drive, void *buffer, u32 bytecount)
+ #if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
+ if (MACH_IS_ATARI || MACH_IS_Q40) {
+ /* Atari has a byte-swapped IDE interface */
+- insw_swapw(IDE_DATA_REG, buffer, bytecount / 2);
++ insw_swapw(hwif->io_ports[IDE_DATA_OFFSET], buffer,
++ bytecount / 2);
+ return;
+ }
+ #endif /* CONFIG_ATARI || CONFIG_Q40 */
+ hwif->ata_input_data(drive, buffer, bytecount / 4);
+ if ((bytecount & 0x03) >= 2)
+- hwif->INSW(IDE_DATA_REG, ((u8 *)buffer)+(bytecount & ~0x03), 1);
++ hwif->INSW(hwif->io_ports[IDE_DATA_OFFSET],
++ (u8 *)buffer + (bytecount & ~0x03), 1);
+ }
+
+ static void atapi_output_bytes(ide_drive_t *drive, void *buffer, u32 bytecount)
+@@ -260,13 +271,15 @@ static void atapi_output_bytes(ide_drive_t *drive, void *buffer, u32 bytecount)
+ #if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
+ if (MACH_IS_ATARI || MACH_IS_Q40) {
+ /* Atari has a byte-swapped IDE interface */
+- outsw_swapw(IDE_DATA_REG, buffer, bytecount / 2);
++ outsw_swapw(hwif->io_ports[IDE_DATA_OFFSET], buffer,
++ bytecount / 2);
+ return;
+ }
+ #endif /* CONFIG_ATARI || CONFIG_Q40 */
+ hwif->ata_output_data(drive, buffer, bytecount / 4);
+ if ((bytecount & 0x03) >= 2)
+- hwif->OUTSW(IDE_DATA_REG, ((u8*)buffer)+(bytecount & ~0x03), 1);
++ hwif->OUTSW(hwif->io_ports[IDE_DATA_OFFSET],
++ (u8 *)buffer + (bytecount & ~0x03), 1);
+ }
+
+ void default_hwif_transport(ide_hwif_t *hwif)
+@@ -429,7 +442,7 @@ int drive_is_ready (ide_drive_t *drive)
+ * an interrupt with another pci card/device. We make no assumptions
+ * about possible isa-pnp and pci-pnp issues yet.
+ */
+- if (IDE_CONTROL_REG)
++ if (hwif->io_ports[IDE_CONTROL_OFFSET])
+ stat = ide_read_altstatus(drive);
+ else
+ /* Note: this may clear a pending IRQ!! */
+@@ -631,7 +644,7 @@ int ide_driveid_update(ide_drive_t *drive)
+ SELECT_MASK(drive, 1);
+ ide_set_irq(drive, 1);
+ msleep(50);
+- hwif->OUTB(WIN_IDENTIFY, IDE_COMMAND_REG);
++ hwif->OUTB(WIN_IDENTIFY, hwif->io_ports[IDE_COMMAND_OFFSET]);
+ timeout = jiffies + WAIT_WORSTCASE;
+ do {
+ if (time_after(jiffies, timeout)) {
+@@ -718,9 +731,10 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
+ SELECT_MASK(drive, 0);
+ udelay(1);
+ ide_set_irq(drive, 0);
+- hwif->OUTB(speed, IDE_NSECTOR_REG);
+- hwif->OUTB(SETFEATURES_XFER, IDE_FEATURE_REG);
+- hwif->OUTBSYNC(drive, WIN_SETFEATURES, IDE_COMMAND_REG);
++ hwif->OUTB(speed, hwif->io_ports[IDE_NSECTOR_OFFSET]);
++ hwif->OUTB(SETFEATURES_XFER, hwif->io_ports[IDE_FEATURE_OFFSET]);
++ hwif->OUTBSYNC(drive, WIN_SETFEATURES,
++ hwif->io_ports[IDE_COMMAND_OFFSET]);
+ if (drive->quirk_list == 2)
+ ide_set_irq(drive, 1);
+
+@@ -828,7 +842,7 @@ void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler,
+
+ spin_lock_irqsave(&ide_lock, flags);
+ __ide_set_handler(drive, handler, timeout, expiry);
+- hwif->OUTBSYNC(drive, cmd, IDE_COMMAND_REG);
++ hwif->OUTBSYNC(drive, cmd, hwif->io_ports[IDE_COMMAND_OFFSET]);
+ /*
+ * Drive takes 400nS to respond, we must avoid the IRQ being
+ * serviced before that.
+@@ -1009,7 +1023,8 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
+ unsigned long flags;
+ ide_hwif_t *hwif;
+ ide_hwgroup_t *hwgroup;
+-
++ u8 ctl;
++
+ spin_lock_irqsave(&ide_lock, flags);
+ hwif = HWIF(drive);
+ hwgroup = HWGROUP(drive);
+@@ -1023,7 +1038,8 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
+ pre_reset(drive);
+ SELECT_DRIVE(drive);
+ udelay (20);
+- hwif->OUTBSYNC(drive, WIN_SRST, IDE_COMMAND_REG);
++ hwif->OUTBSYNC(drive, WIN_SRST,
++ hwif->io_ports[IDE_COMMAND_OFFSET]);
+ ndelay(400);
+ hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
+ hwgroup->polling = 1;
+@@ -1039,7 +1055,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
+ for (unit = 0; unit < MAX_DRIVES; ++unit)
+ pre_reset(&hwif->drives[unit]);
+
+- if (!IDE_CONTROL_REG) {
++ if (hwif->io_ports[IDE_CONTROL_OFFSET] == 0) {
+ spin_unlock_irqrestore(&ide_lock, flags);
+ return ide_stopped;
+ }
+@@ -1054,16 +1070,14 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
+ * recover from reset very quickly, saving us the first 50ms wait time.
+ */
+ /* set SRST and nIEN */
+- hwif->OUTBSYNC(drive, drive->ctl|6,IDE_CONTROL_REG);
++ hwif->OUTBSYNC(drive, drive->ctl|6, hwif->io_ports[IDE_CONTROL_OFFSET]);
+ /* more than enough time */
+ udelay(10);
+- if (drive->quirk_list == 2) {
+- /* clear SRST and nIEN */
+- hwif->OUTBSYNC(drive, drive->ctl, IDE_CONTROL_REG);
+- } else {
+- /* clear SRST, leave nIEN */
+- hwif->OUTBSYNC(drive, drive->ctl|2, IDE_CONTROL_REG);
+- }
++ if (drive->quirk_list == 2)
++ ctl = drive->ctl; /* clear SRST and nIEN */
++ else
++ ctl = drive->ctl | 2; /* clear SRST, leave nIEN */
++ hwif->OUTBSYNC(drive, ctl, hwif->io_ports[IDE_CONTROL_OFFSET]);
+ /* more than enough time */
+ udelay(10);
+ hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
+diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
+index 7031a8d..c859de7 100644
+--- a/drivers/ide/ide-lib.c
++++ b/drivers/ide/ide-lib.c
+@@ -274,16 +274,6 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode)
+ if (overridden)
+ printk(KERN_INFO "%s: tPIO > 2, assuming tPIO = 2\n",
+ drive->name);
+-
+- /*
+- * Conservative "downgrade" for all pre-ATA2 drives
+- */
+- if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_DOWNGRADE) == 0 &&
+- pio_mode && pio_mode < 4) {
+- pio_mode--;
+- printk(KERN_INFO "%s: applying conservative "
+- "PIO \"downgrade\"\n", drive->name);
+- }
+ }
+
+ if (pio_mode > max_mode)
+@@ -300,7 +290,8 @@ void ide_set_pio(ide_drive_t *drive, u8 req_pio)
+ ide_hwif_t *hwif = drive->hwif;
+ u8 host_pio, pio;
+
+- if (hwif->set_pio_mode == NULL)
++ if (hwif->set_pio_mode == NULL ||
++ (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
+ return;
+
+ BUG_ON(hwif->pio_mask == 0x00);
+@@ -353,6 +344,9 @@ int ide_set_pio_mode(ide_drive_t *drive, const u8 mode)
+ {
+ ide_hwif_t *hwif = drive->hwif;
+
++ if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
++ return 0;
++
+ if (hwif->set_pio_mode == NULL)
+ return -1;
+
+@@ -380,6 +374,9 @@ int ide_set_dma_mode(ide_drive_t *drive, const u8 mode)
+ {
+ ide_hwif_t *hwif = drive->hwif;
+
++ if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
++ return 0;
++
+ if (hwif->set_dma_mode == NULL)
+ return -1;
+
+@@ -410,7 +407,8 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
+ {
+ ide_hwif_t *hwif = drive->hwif;
+
+- if (hwif->set_dma_mode == NULL)
++ if (hwif->set_dma_mode == NULL ||
++ (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
+ return -1;
+
+ rate = ide_rate_filter(drive, rate);
+diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c
+index c14bb53..8a178a5 100644
+--- a/drivers/ide/ide-pnp.c
++++ b/drivers/ide/ide-pnp.c
+@@ -11,7 +11,7 @@
+ *
+ * You should have received a copy of the GNU General Public License
+ * (for example /usr/src/linux/COPYING); if not, write to the Free
+- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+ #include <linux/init.h>
+@@ -20,12 +20,12 @@
+
+ /* Add your devices here :)) */
+ static struct pnp_device_id idepnp_devices[] = {
+- /* Generic ESDI/IDE/ATA compatible hard disk controller */
++ /* Generic ESDI/IDE/ATA compatible hard disk controller */
+ {.id = "PNP0600", .driver_data = 0},
+ {.id = ""}
+ };
+
+-static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id)
++static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
+ {
+ hw_regs_t hw;
+ ide_hwif_t *hwif;
+@@ -38,7 +38,7 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id
+ pnp_port_start(dev, 1));
+ hw.irq = pnp_irq(dev, 0);
+
+- hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++ hwif = ide_find_port();
+ if (hwif) {
+ u8 index = hwif->index;
+ u8 idx[4] = { index, 0xff, 0xff, 0xff };
+@@ -47,7 +47,7 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id
+ ide_init_port_hw(hwif, &hw);
+
+ printk(KERN_INFO "ide%d: generic PnP IDE interface\n", index);
+- pnp_set_drvdata(dev,hwif);
++ pnp_set_drvdata(dev, hwif);
+
+ ide_device_add(idx, NULL);
+
+@@ -57,12 +57,12 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id
+ return -1;
+ }
+
+-static void idepnp_remove(struct pnp_dev * dev)
++static void idepnp_remove(struct pnp_dev *dev)
+ {
+ ide_hwif_t *hwif = pnp_get_drvdata(dev);
+
+ if (hwif)
+- ide_unregister(hwif->index, 0, 0);
++ ide_unregister(hwif->index);
+ else
+ printk(KERN_ERR "idepnp: Unable to remove device, please report.\n");
+ }
+diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
+index 47a1149..8754297 100644
+--- a/drivers/ide/ide-probe.c
++++ b/drivers/ide/ide-probe.c
+@@ -271,7 +271,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
+ /* take a deep breath */
+ msleep(50);
+
+- if (IDE_CONTROL_REG) {
++ if (hwif->io_ports[IDE_CONTROL_OFFSET]) {
+ a = ide_read_altstatus(drive);
+ s = ide_read_status(drive);
+ if ((a ^ s) & ~INDEX_STAT)
+@@ -289,10 +289,10 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
+ */
+ if ((cmd == WIN_PIDENTIFY))
+ /* disable dma & overlap */
+- hwif->OUTB(0, IDE_FEATURE_REG);
++ hwif->OUTB(0, hwif->io_ports[IDE_FEATURE_OFFSET]);
+
+ /* ask drive for ID */
+- hwif->OUTB(cmd, IDE_COMMAND_REG);
++ hwif->OUTB(cmd, hwif->io_ports[IDE_COMMAND_OFFSET]);
+
+ timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
+ timeout += jiffies;
+@@ -353,7 +353,7 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
+ * interrupts during the identify-phase that
+ * the irq handler isn't expecting.
+ */
+- if (IDE_CONTROL_REG) {
++ if (hwif->io_ports[IDE_CONTROL_OFFSET]) {
+ if (!hwif->irq) {
+ autoprobe = 1;
+ cookie = probe_irq_on();
+@@ -445,7 +445,8 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
+ msleep(50);
+ SELECT_DRIVE(drive);
+ msleep(50);
+- if (hwif->INB(IDE_SELECT_REG) != drive->select.all && !drive->present) {
++ if (hwif->INB(hwif->io_ports[IDE_SELECT_OFFSET]) != drive->select.all &&
++ !drive->present) {
+ if (drive->select.b.unit != 0) {
+ /* exit with drive0 selected */
+ SELECT_DRIVE(&hwif->drives[0]);
+@@ -477,9 +478,11 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
+ printk(KERN_ERR "%s: no response (status = 0x%02x), "
+ "resetting drive\n", drive->name, stat);
+ msleep(50);
+- hwif->OUTB(drive->select.all, IDE_SELECT_REG);
++ hwif->OUTB(drive->select.all,
++ hwif->io_ports[IDE_SELECT_OFFSET]);
+ msleep(50);
+- hwif->OUTB(WIN_SRST, IDE_COMMAND_REG);
++ hwif->OUTB(WIN_SRST,
++ hwif->io_ports[IDE_COMMAND_OFFSET]);
+ (void)ide_busy_sleep(hwif);
+ rc = try_to_identify(drive, cmd);
+ }
+@@ -515,7 +518,7 @@ static void enable_nest (ide_drive_t *drive)
+ printk("%s: enabling %s -- ", hwif->name, drive->id->model);
+ SELECT_DRIVE(drive);
+ msleep(50);
+- hwif->OUTB(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG);
++ hwif->OUTB(EXABYTE_ENABLE_NEST, hwif->io_ports[IDE_COMMAND_OFFSET]);
+
+ if (ide_busy_sleep(hwif)) {
+ printk(KERN_CONT "failed (timeout)\n");
+@@ -623,7 +626,7 @@ static void hwif_release_dev (struct device *dev)
+ complete(&hwif->gendev_rel_comp);
+ }
+
+-static void ide_register_port(ide_hwif_t *hwif)
++static int ide_register_port(ide_hwif_t *hwif)
+ {
+ int ret;
+
+@@ -639,9 +642,23 @@ static void ide_register_port(ide_hwif_t *hwif)
+ }
+ hwif->gendev.release = hwif_release_dev;
+ ret = device_register(&hwif->gendev);
+- if (ret < 0)
++ if (ret < 0) {
+ printk(KERN_WARNING "IDE: %s: device_register error: %d\n",
+ __FUNCTION__, ret);
++ goto out;
++ }
++
++ get_device(&hwif->gendev);
++
++ hwif->portdev = device_create(ide_port_class, &hwif->gendev,
++ MKDEV(0, 0), hwif->name);
++ if (IS_ERR(hwif->portdev)) {
++ ret = PTR_ERR(hwif->portdev);
++ device_unregister(&hwif->gendev);
++ }
++ dev_set_drvdata(hwif->portdev, hwif);
++out:
++ return ret;
+ }
+
+ /**
+@@ -949,6 +966,7 @@ static void ide_port_setup_devices(ide_hwif_t *hwif)
+ {
+ int i;
+
++ mutex_lock(&ide_cfg_mtx);
+ for (i = 0; i < MAX_DRIVES; i++) {
+ ide_drive_t *drive = &hwif->drives[i];
+
+@@ -963,6 +981,7 @@ static void ide_port_setup_devices(ide_hwif_t *hwif)
+
+ ide_add_drive_to_hwgroup(drive);
+ }
++ mutex_unlock(&ide_cfg_mtx);
+ }
+
+ /*
+@@ -1088,8 +1107,6 @@ static int init_irq (ide_hwif_t *hwif)
+ hwif->sharing_irq ? "shar" : "serializ", match->name);
+ printk("\n");
+
+- ide_port_setup_devices(hwif);
+-
+ mutex_unlock(&ide_cfg_mtx);
+ return 0;
+ out_unlink:
+@@ -1199,6 +1216,8 @@ static void drive_release_dev (struct device *dev)
+ {
+ ide_drive_t *drive = container_of(dev, ide_drive_t, gendev);
+
++ ide_proc_unregister_device(drive);
++
+ spin_lock_irq(&ide_lock);
+ ide_remove_drive_from_hwgroup(drive);
+ kfree(drive->id);
+@@ -1214,6 +1233,10 @@ static void drive_release_dev (struct device *dev)
+ complete(&drive->gendev_rel_comp);
+ }
+
++#ifndef ide_default_irq
++#define ide_default_irq(irq) 0
++#endif
++
+ static int hwif_init(ide_hwif_t *hwif)
+ {
+ int old_irq;
+@@ -1225,13 +1248,6 @@ static int hwif_init(ide_hwif_t *hwif)
+ return 0;
+ }
+ }
+-#ifdef CONFIG_BLK_DEV_HD
+- if (hwif->irq == HD_IRQ && hwif->io_ports[IDE_DATA_OFFSET] != HD_DATA) {
+- printk("%s: CANNOT SHARE IRQ WITH OLD "
+- "HARDDISK DRIVER (hd.c)\n", hwif->name);
+- return 0;
+- }
+-#endif /* CONFIG_BLK_DEV_HD */
+
+ if (register_blkdev(hwif->major, hwif->name))
+ return 0;
+@@ -1366,13 +1382,116 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
+ /* call chipset specific routine for each enabled port */
+ if (d->init_hwif)
+ d->init_hwif(hwif);
++}
+
++static void ide_port_cable_detect(ide_hwif_t *hwif)
++{
+ if (hwif->cable_detect && (hwif->ultra_mask & 0x78)) {
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = hwif->cable_detect(hwif);
+ }
+ }
+
++static ssize_t store_delete_devices(struct device *portdev,
++ struct device_attribute *attr,
++ const char *buf, size_t n)
++{
++ ide_hwif_t *hwif = dev_get_drvdata(portdev);
++
++ if (strncmp(buf, "1", n))
++ return -EINVAL;
++
++ ide_port_unregister_devices(hwif);
++
++ return n;
++};
++
++static DEVICE_ATTR(delete_devices, S_IWUSR, NULL, store_delete_devices);
++
++static ssize_t store_scan(struct device *portdev,
++ struct device_attribute *attr,
++ const char *buf, size_t n)
++{
++ ide_hwif_t *hwif = dev_get_drvdata(portdev);
++
++ if (strncmp(buf, "1", n))
++ return -EINVAL;
++
++ ide_port_unregister_devices(hwif);
++ ide_port_scan(hwif);
++
++ return n;
++};
++
++static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
++
++static struct device_attribute *ide_port_attrs[] = {
++ &dev_attr_delete_devices,
++ &dev_attr_scan,
++ NULL
++};
++
++static int ide_sysfs_register_port(ide_hwif_t *hwif)
++{
++ int i, rc;
++
++ for (i = 0; ide_port_attrs[i]; i++) {
++ rc = device_create_file(hwif->portdev, ide_port_attrs[i]);
++ if (rc)
++ break;
++ }
++
++ return rc;
++}
++
++/**
++ * ide_find_port_slot - find free ide_hwifs[] slot
++ * @d: IDE port info
++ *
++ * Return the new hwif. If we are out of free slots return NULL.
++ */
++
++ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d)
++{
++ ide_hwif_t *hwif;
++ int i;
++ u8 bootable = (d && (d->host_flags & IDE_HFLAG_NON_BOOTABLE)) ? 0 : 1;
++
++ /*
++ * Claim an unassigned slot.
++ *
++ * Give preference to claiming other slots before claiming ide0/ide1,
++ * just in case there's another interface yet-to-be-scanned
++ * which uses ports 0x1f0/0x170 (the ide0/ide1 defaults).
++ *
++ * Unless there is a bootable card that does not use the standard
++ * ports 0x1f0/0x170 (the ide0/ide1 defaults).
++ */
++ if (bootable) {
++ i = (d && (d->host_flags & IDE_HFLAG_QD_2ND_PORT)) ? 1 : 0;
++
++ for (; i < MAX_HWIFS; i++) {
++ hwif = &ide_hwifs[i];
++ if (hwif->chipset == ide_unknown)
++ return hwif;
++ }
++ } else {
++ for (i = 2; i < MAX_HWIFS; i++) {
++ hwif = &ide_hwifs[i];
++ if (hwif->chipset == ide_unknown)
++ return hwif;
++ }
++ for (i = 0; i < 2 && i < MAX_HWIFS; i++) {
++ hwif = &ide_hwifs[i];
++ if (hwif->chipset == ide_unknown)
++ return hwif;
++ }
++ }
++
++ return NULL;
++}
++EXPORT_SYMBOL_GPL(ide_find_port_slot);
++
+ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
+ {
+ ide_hwif_t *hwif, *mate = NULL;
+@@ -1394,6 +1513,7 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
+ mate = (i & 1) ? NULL : hwif;
+
+ ide_init_port(hwif, i & 1, d);
++ ide_port_cable_detect(hwif);
+ ide_port_init_devices(hwif);
+ }
+
+@@ -1441,6 +1561,8 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
+ continue;
+ }
+
++ ide_port_setup_devices(hwif);
++
+ ide_acpi_init(hwif);
+ ide_acpi_port_init_devices(hwif);
+ }
+@@ -1452,8 +1574,7 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
+ hwif = &ide_hwifs[idx[i]];
+
+ if (hwif->present) {
+- if (hwif->chipset == ide_unknown ||
+- hwif->chipset == ide_forced)
++ if (hwif->chipset == ide_unknown)
+ hwif->chipset = ide_generic;
+ hwif_register_devices(hwif);
+ }
+@@ -1466,6 +1587,7 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
+ hwif = &ide_hwifs[idx[i]];
+
+ if (hwif->present) {
++ ide_sysfs_register_port(hwif);
+ ide_proc_register_port(hwif);
+ ide_proc_port_register_devices(hwif);
+ }
+@@ -1486,3 +1608,21 @@ int ide_device_add(u8 idx[4], const struct ide_port_info *d)
+ return ide_device_add_all(idx_all, d);
+ }
+ EXPORT_SYMBOL_GPL(ide_device_add);
++
++void ide_port_scan(ide_hwif_t *hwif)
++{
++ ide_port_cable_detect(hwif);
++ ide_port_init_devices(hwif);
++
++ if (ide_probe_port(hwif) < 0)
++ return;
++
++ hwif->present = 1;
++
++ ide_port_tune_devices(hwif);
++ ide_acpi_port_init_devices(hwif);
++ ide_port_setup_devices(hwif);
++ hwif_register_devices(hwif);
++ ide_proc_port_register_devices(hwif);
++}
++EXPORT_SYMBOL_GPL(ide_port_scan);
+diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
+index bab88ca..5d3562b 100644
+--- a/drivers/ide/ide-proc.c
++++ b/drivers/ide/ide-proc.c
+@@ -46,32 +46,29 @@ static int proc_ide_read_imodel
+ int len;
+ const char *name;
+
+- /*
+- * Neither ide_unknown nor ide_forced should be set at this point.
+- */
+ switch (hwif->chipset) {
+- case ide_generic: name = "generic"; break;
+- case ide_pci: name = "pci"; break;
+- case ide_cmd640: name = "cmd640"; break;
+- case ide_dtc2278: name = "dtc2278"; break;
+- case ide_ali14xx: name = "ali14xx"; break;
+- case ide_qd65xx: name = "qd65xx"; break;
+- case ide_umc8672: name = "umc8672"; break;
+- case ide_ht6560b: name = "ht6560b"; break;
+- case ide_rz1000: name = "rz1000"; break;
+- case ide_trm290: name = "trm290"; break;
+- case ide_cmd646: name = "cmd646"; break;
+- case ide_cy82c693: name = "cy82c693"; break;
+- case ide_4drives: name = "4drives"; break;
+- case ide_pmac: name = "mac-io"; break;
+- case ide_au1xxx: name = "au1xxx"; break;
+- case ide_palm3710: name = "palm3710"; break;
+- case ide_etrax100: name = "etrax100"; break;
+- case ide_acorn: name = "acorn"; break;
+- default: name = "(unknown)"; break;
++ case ide_generic: name = "generic"; break;
++ case ide_pci: name = "pci"; break;
++ case ide_cmd640: name = "cmd640"; break;
++ case ide_dtc2278: name = "dtc2278"; break;
++ case ide_ali14xx: name = "ali14xx"; break;
++ case ide_qd65xx: name = "qd65xx"; break;
++ case ide_umc8672: name = "umc8672"; break;
++ case ide_ht6560b: name = "ht6560b"; break;
++ case ide_rz1000: name = "rz1000"; break;
++ case ide_trm290: name = "trm290"; break;
++ case ide_cmd646: name = "cmd646"; break;
++ case ide_cy82c693: name = "cy82c693"; break;
++ case ide_4drives: name = "4drives"; break;
++ case ide_pmac: name = "mac-io"; break;
++ case ide_au1xxx: name = "au1xxx"; break;
++ case ide_palm3710: name = "palm3710"; break;
++ case ide_etrax100: name = "etrax100"; break;
++ case ide_acorn: name = "acorn"; break;
++ default: name = "(unknown)"; break;
+ }
+ len = sprintf(page, "%s\n", name);
+- PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+
+ static int proc_ide_read_mate
+@@ -84,7 +81,7 @@ static int proc_ide_read_mate
+ len = sprintf(page, "%s\n", hwif->mate->name);
+ else
+ len = sprintf(page, "(none)\n");
+- PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+
+ static int proc_ide_read_channel
+@@ -96,7 +93,7 @@ static int proc_ide_read_channel
+ page[0] = hwif->channel ? '1' : '0';
+ page[1] = '\n';
+ len = 2;
+- PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+
+ static int proc_ide_read_identify
+@@ -123,7 +120,7 @@ static int proc_ide_read_identify
+ len = out - page;
+ }
+ }
+- PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+
+ /**
+@@ -200,7 +197,7 @@ EXPORT_SYMBOL(ide_add_setting);
+ * The caller must hold the setting semaphore.
+ */
+
+-static void __ide_remove_setting (ide_drive_t *drive, char *name)
++static void __ide_remove_setting(ide_drive_t *drive, char *name)
+ {
+ ide_settings_t **p, *setting;
+
+@@ -208,7 +205,8 @@ static void __ide_remove_setting (ide_drive_t *drive, char *name)
+
+ while ((*p) && strcmp((*p)->name, name))
+ p = &((*p)->next);
+- if ((setting = (*p)) == NULL)
++ setting = (*p);
++ if (setting == NULL)
+ return;
+
+ (*p) = setting->next;
+@@ -226,7 +224,7 @@ static void __ide_remove_setting (ide_drive_t *drive, char *name)
+ * caller must hold ide_setting_mtx.
+ */
+
+-static void auto_remove_settings (ide_drive_t *drive)
++static void auto_remove_settings(ide_drive_t *drive)
+ {
+ ide_settings_t *setting;
+ repeat:
+@@ -282,16 +280,16 @@ static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
+
+ if ((setting->rw & SETTING_READ)) {
+ spin_lock_irqsave(&ide_lock, flags);
+- switch(setting->data_type) {
+- case TYPE_BYTE:
+- val = *((u8 *) setting->data);
+- break;
+- case TYPE_SHORT:
+- val = *((u16 *) setting->data);
+- break;
+- case TYPE_INT:
+- val = *((u32 *) setting->data);
+- break;
++ switch (setting->data_type) {
++ case TYPE_BYTE:
++ val = *((u8 *) setting->data);
++ break;
++ case TYPE_SHORT:
++ val = *((u16 *) setting->data);
++ break;
++ case TYPE_INT:
++ val = *((u32 *) setting->data);
++ break;
+ }
+ spin_unlock_irqrestore(&ide_lock, flags);
+ }
+@@ -329,15 +327,15 @@ static int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int va
+ if (ide_spin_wait_hwgroup(drive))
+ return -EBUSY;
+ switch (setting->data_type) {
+- case TYPE_BYTE:
+- *((u8 *) setting->data) = val;
+- break;
+- case TYPE_SHORT:
+- *((u16 *) setting->data) = val;
+- break;
+- case TYPE_INT:
+- *((u32 *) setting->data) = val;
+- break;
++ case TYPE_BYTE:
++ *((u8 *) setting->data) = val;
++ break;
++ case TYPE_SHORT:
++ *((u16 *) setting->data) = val;
++ break;
++ case TYPE_INT:
++ *((u32 *) setting->data) = val;
++ break;
+ }
+ spin_unlock_irq(&ide_lock);
+ return 0;
+@@ -393,7 +391,7 @@ void ide_add_generic_settings (ide_drive_t *drive)
+
+ static void proc_ide_settings_warn(void)
+ {
+- static int warned = 0;
++ static int warned;
+
+ if (warned)
+ return;
+@@ -416,11 +414,12 @@ static int proc_ide_read_settings
+ mutex_lock(&ide_setting_mtx);
+ out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n");
+ out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n");
+- while(setting) {
++ while (setting) {
+ mul_factor = setting->mul_factor;
+ div_factor = setting->div_factor;
+ out += sprintf(out, "%-24s", setting->name);
+- if ((rc = ide_read_setting(drive, setting)) >= 0)
++ rc = ide_read_setting(drive, setting);
++ if (rc >= 0)
+ out += sprintf(out, "%-16d", rc * mul_factor / div_factor);
+ else
+ out += sprintf(out, "%-16s", "write-only");
+@@ -434,7 +433,7 @@ static int proc_ide_read_settings
+ }
+ len = out - page;
+ mutex_unlock(&ide_setting_mtx);
+- PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+
+ #define MAX_LEN 30
+@@ -515,8 +514,7 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer,
+
+ mutex_lock(&ide_setting_mtx);
+ setting = ide_find_setting_by_name(drive, name);
+- if (!setting)
+- {
++ if (!setting) {
+ mutex_unlock(&ide_setting_mtx);
+ goto parse_error;
+ }
+@@ -536,8 +534,8 @@ parse_error:
+ int proc_ide_read_capacity
+ (char *page, char **start, off_t off, int count, int *eof, void *data)
+ {
+- int len = sprintf(page,"%llu\n", (long long)0x7fffffff);
+- PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++ int len = sprintf(page, "%llu\n", (long long)0x7fffffff);
++ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+
+ EXPORT_SYMBOL_GPL(proc_ide_read_capacity);
+@@ -549,13 +547,13 @@ int proc_ide_read_geometry
+ char *out = page;
+ int len;
+
+- out += sprintf(out,"physical %d/%d/%d\n",
++ out += sprintf(out, "physical %d/%d/%d\n",
+ drive->cyl, drive->head, drive->sect);
+- out += sprintf(out,"logical %d/%d/%d\n",
++ out += sprintf(out, "logical %d/%d/%d\n",
+ drive->bios_cyl, drive->bios_head, drive->bios_sect);
+
+ len = out - page;
+- PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+
+ EXPORT_SYMBOL(proc_ide_read_geometry);
+@@ -569,7 +567,7 @@ static int proc_ide_read_dmodel
+
+ len = sprintf(page, "%.40s\n",
+ (id && id->model[0]) ? (char *)id->model : "(none)");
+- PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+
+ static int proc_ide_read_driver
+@@ -586,7 +584,7 @@ static int proc_ide_read_driver
+ dev->driver->name, ide_drv->version);
+ } else
+ len = sprintf(page, "ide-default version 0.9.newide\n");
+- PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+
+ static int ide_replace_subdriver(ide_drive_t *drive, const char *driver)
+@@ -642,30 +640,26 @@ static int proc_ide_read_media
+ int len;
+
+ switch (drive->media) {
+- case ide_disk: media = "disk\n";
+- break;
+- case ide_cdrom: media = "cdrom\n";
+- break;
+- case ide_tape: media = "tape\n";
+- break;
+- case ide_floppy:media = "floppy\n";
+- break;
+- case ide_optical:media = "optical\n";
+- break;
+- default: media = "UNKNOWN\n";
+- break;
++ case ide_disk: media = "disk\n"; break;
++ case ide_cdrom: media = "cdrom\n"; break;
++ case ide_tape: media = "tape\n"; break;
++ case ide_floppy: media = "floppy\n"; break;
++ case ide_optical: media = "optical\n"; break;
++ default: media = "UNKNOWN\n"; break;
+ }
+- strcpy(page,media);
++ strcpy(page, media);
+ len = strlen(media);
+- PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++ PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
+
+ static ide_proc_entry_t generic_drive_entries[] = {
+- { "driver", S_IFREG|S_IRUGO, proc_ide_read_driver, proc_ide_write_driver },
+- { "identify", S_IFREG|S_IRUSR, proc_ide_read_identify, NULL },
+- { "media", S_IFREG|S_IRUGO, proc_ide_read_media, NULL },
+- { "model", S_IFREG|S_IRUGO, proc_ide_read_dmodel, NULL },
+- { "settings", S_IFREG|S_IRUSR|S_IWUSR,proc_ide_read_settings, proc_ide_write_settings },
++ { "driver", S_IFREG|S_IRUGO, proc_ide_read_driver,
++ proc_ide_write_driver },
++ { "identify", S_IFREG|S_IRUSR, proc_ide_read_identify, NULL },
++ { "media", S_IFREG|S_IRUGO, proc_ide_read_media, NULL },
++ { "model", S_IFREG|S_IRUGO, proc_ide_read_dmodel, NULL },
++ { "settings", S_IFREG|S_IRUSR|S_IWUSR, proc_ide_read_settings,
++ proc_ide_write_settings },
+ { NULL, 0, NULL, NULL }
+ };
+
+@@ -737,7 +731,6 @@ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
+ spin_unlock_irqrestore(&ide_lock, flags);
+ mutex_unlock(&ide_setting_mtx);
+ }
+-
+ EXPORT_SYMBOL(ide_proc_unregister_driver);
+
+ void ide_proc_port_register_devices(ide_hwif_t *hwif)
+@@ -758,33 +751,22 @@ void ide_proc_port_register_devices(ide_hwif_t *hwif)
+ drive->proc = proc_mkdir(drive->name, parent);
+ if (drive->proc)
+ ide_add_proc_entries(drive->proc, generic_drive_entries, drive);
+- sprintf(name,"ide%d/%s", (drive->name[2]-'a')/2, drive->name);
++ sprintf(name, "ide%d/%s", (drive->name[2]-'a')/2, drive->name);
+ ent = proc_symlink(drive->name, proc_ide_root, name);
+ if (!ent) return;
+ }
+ }
+
+-static void destroy_proc_ide_device(ide_hwif_t *hwif, ide_drive_t *drive)
++void ide_proc_unregister_device(ide_drive_t *drive)
+ {
+ if (drive->proc) {
+ ide_remove_proc_entries(drive->proc, generic_drive_entries);
+ remove_proc_entry(drive->name, proc_ide_root);
+- remove_proc_entry(drive->name, hwif->proc);
++ remove_proc_entry(drive->name, drive->hwif->proc);
+ drive->proc = NULL;
+ }
+ }
+
+-static void destroy_proc_ide_drives(ide_hwif_t *hwif)
+-{
+- int d;
+-
+- for (d = 0; d < MAX_DRIVES; d++) {
+- ide_drive_t *drive = &hwif->drives[d];
+- if (drive->proc)
+- destroy_proc_ide_device(hwif, drive);
+- }
+-}
+-
+ static ide_proc_entry_t hwif_entries[] = {
+ { "channel", S_IFREG|S_IRUGO, proc_ide_read_channel, NULL },
+ { "mate", S_IFREG|S_IRUGO, proc_ide_read_mate, NULL },
+@@ -809,14 +791,12 @@ void ide_pci_create_host_proc(const char *name, get_info_t *get_info)
+ {
+ create_proc_info_entry(name, 0, proc_ide_root, get_info);
+ }
+-
+ EXPORT_SYMBOL_GPL(ide_pci_create_host_proc);
+ #endif
+
+ void ide_proc_unregister_port(ide_hwif_t *hwif)
+ {
+ if (hwif->proc) {
+- destroy_proc_ide_drives(hwif);
+ ide_remove_proc_entries(hwif->proc, hwif_entries);
+ remove_proc_entry(hwif->name, proc_ide_root);
+ hwif->proc = NULL;
+diff --git a/drivers/ide/ide-scan-pci.c b/drivers/ide/ide-scan-pci.c
+index 93d2e41..98888da 100644
+--- a/drivers/ide/ide-scan-pci.c
++++ b/drivers/ide/ide-scan-pci.c
+@@ -88,13 +88,8 @@ static int __init ide_scan_pcibus(void)
+ struct list_head *l, *n;
+
+ pre_init = 0;
+- if (!ide_scan_direction)
+- while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)))
+- ide_scan_pcidev(dev);
+- else
+- while ((dev = pci_get_device_reverse(PCI_ANY_ID, PCI_ANY_ID,
+- dev)))
+- ide_scan_pcidev(dev);
++ while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)))
++ ide_scan_pcidev(dev);
+
+ /*
+ * Hand the drivers over to the PCI layer now we
+diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
+index 0598ecf..f43fd07 100644
+--- a/drivers/ide/ide-tape.c
++++ b/drivers/ide/ide-tape.c
+@@ -181,49 +181,63 @@ struct idetape_bh {
+ char *b_data;
+ };
+
+-typedef struct idetape_packet_command_s {
+- /* Actual packet bytes */
+- u8 c[12];
+- /* On each retry, we increment retries */
+- int retries;
+- /* Error code */
+- int error;
+- /* Bytes to transfer */
+- int request_transfer;
+- /* Bytes actually transferred */
+- int actually_transferred;
+- /* Size of our data buffer */
+- int buffer_size;
+- struct idetape_bh *bh;
+- char *b_data;
+- int b_count;
+- /* Data buffer */
+- u8 *buffer;
+- /* Pointer into the above buffer */
+- u8 *current_position;
+- /* Called when this packet command is completed */
+- ide_startstop_t (*callback) (ide_drive_t *);
+- /* Temporary buffer */
+- u8 pc_buffer[IDETAPE_PC_BUFFER_SIZE];
+- /* Status/Action bit flags: long for set_bit */
+- unsigned long flags;
+-} idetape_pc_t;
++/* Tape door status */
++#define DOOR_UNLOCKED 0
++#define DOOR_LOCKED 1
++#define DOOR_EXPLICITLY_LOCKED 2
++
++/* Some defines for the SPACE command */
++#define IDETAPE_SPACE_OVER_FILEMARK 1
++#define IDETAPE_SPACE_TO_EOD 3
++
++/* Some defines for the LOAD UNLOAD command */
++#define IDETAPE_LU_LOAD_MASK 1
++#define IDETAPE_LU_RETENSION_MASK 2
++#define IDETAPE_LU_EOT_MASK 4
+
+ /*
+- * Packet command flag bits.
++ * Special requests for our block device strategy routine.
++ *
++ * In order to service a character device command, we add special requests to
++ * the tail of our block device request queue and wait for their completion.
+ */
+-/* Set when an error is considered normal - We won't retry */
+-#define PC_ABORT 0
+-/* 1 When polling for DSC on a media access command */
+-#define PC_WAIT_FOR_DSC 1
+-/* 1 when we prefer to use DMA if possible */
+-#define PC_DMA_RECOMMENDED 2
+-/* 1 while DMA in progress */
+-#define PC_DMA_IN_PROGRESS 3
+-/* 1 when encountered problem during DMA */
+-#define PC_DMA_ERROR 4
+-/* Data direction */
+-#define PC_WRITING 5
++
++enum {
++ REQ_IDETAPE_PC1 = (1 << 0), /* packet command (first stage) */
++ REQ_IDETAPE_PC2 = (1 << 1), /* packet command (second stage) */
++ REQ_IDETAPE_READ = (1 << 2),
++ REQ_IDETAPE_WRITE = (1 << 3),
++};
++
++/* Error codes returned in rq->errors to the higher part of the driver. */
++#define IDETAPE_ERROR_GENERAL 101
++#define IDETAPE_ERROR_FILEMARK 102
++#define IDETAPE_ERROR_EOD 103
++
++/* Structures related to the SELECT SENSE / MODE SENSE packet commands. */
++#define IDETAPE_BLOCK_DESCRIPTOR 0
++#define IDETAPE_CAPABILITIES_PAGE 0x2a
++
++/* Tape flag bits values. */
++enum {
++ IDETAPE_FLAG_IGNORE_DSC = (1 << 0),
++ /* 0 When the tape position is unknown */
++ IDETAPE_FLAG_ADDRESS_VALID = (1 << 1),
++ /* Device already opened */
++ IDETAPE_FLAG_BUSY = (1 << 2),
++ /* Error detected in a pipeline stage */
++ IDETAPE_FLAG_PIPELINE_ERR = (1 << 3),
++ /* Attempt to auto-detect the current user block size */
++ IDETAPE_FLAG_DETECT_BS = (1 << 4),
++ /* Currently on a filemark */
++ IDETAPE_FLAG_FILEMARK = (1 << 5),
++ /* DRQ interrupt device */
++ IDETAPE_FLAG_DRQ_INTERRUPT = (1 << 6),
++ /* pipeline active */
++ IDETAPE_FLAG_PIPELINE_ACTIVE = (1 << 7),
++ /* 0 = no tape is loaded, so we don't rewind after ejecting */
++ IDETAPE_FLAG_MEDIUM_PRESENT = (1 << 8),
++};
+
+ /* A pipeline stage. */
+ typedef struct idetape_stage_s {
+@@ -258,11 +272,11 @@ typedef struct ide_tape_obj {
+ * retry, to get detailed information on what went wrong.
+ */
+ /* Current packet command */
+- idetape_pc_t *pc;
++ struct ide_atapi_pc *pc;
+ /* Last failed packet command */
+- idetape_pc_t *failed_pc;
++ struct ide_atapi_pc *failed_pc;
+ /* Packet command stack */
+- idetape_pc_t pc_stack[IDETAPE_PC_STACK];
++ struct ide_atapi_pc pc_stack[IDETAPE_PC_STACK];
+ /* Next free packet command storage space */
+ int pc_stack_index;
+ struct request rq_stack[IDETAPE_PC_STACK];
+@@ -446,58 +460,6 @@ static void ide_tape_put(struct ide_tape_obj *tape)
+ mutex_unlock(&idetape_ref_mutex);
+ }
+
+-/* Tape door status */
+-#define DOOR_UNLOCKED 0
+-#define DOOR_LOCKED 1
+-#define DOOR_EXPLICITLY_LOCKED 2
+-
+-/*
+- * Tape flag bits values.
+- */
+-#define IDETAPE_IGNORE_DSC 0
+-#define IDETAPE_ADDRESS_VALID 1 /* 0 When the tape position is unknown */
+-#define IDETAPE_BUSY 2 /* Device already opened */
+-#define IDETAPE_PIPELINE_ERROR 3 /* Error detected in a pipeline stage */
+-#define IDETAPE_DETECT_BS 4 /* Attempt to auto-detect the current user block size */
+-#define IDETAPE_FILEMARK 5 /* Currently on a filemark */
+-#define IDETAPE_DRQ_INTERRUPT 6 /* DRQ interrupt device */
+-#define IDETAPE_READ_ERROR 7
+-#define IDETAPE_PIPELINE_ACTIVE 8 /* pipeline active */
+-/* 0 = no tape is loaded, so we don't rewind after ejecting */
+-#define IDETAPE_MEDIUM_PRESENT 9
+-
+-/* Some defines for the SPACE command */
+-#define IDETAPE_SPACE_OVER_FILEMARK 1
+-#define IDETAPE_SPACE_TO_EOD 3
+-
+-/* Some defines for the LOAD UNLOAD command */
+-#define IDETAPE_LU_LOAD_MASK 1
+-#define IDETAPE_LU_RETENSION_MASK 2
+-#define IDETAPE_LU_EOT_MASK 4
+-
+-/*
+- * Special requests for our block device strategy routine.
+- *
+- * In order to service a character device command, we add special requests to
+- * the tail of our block device request queue and wait for their completion.
+- */
+-
+-enum {
+- REQ_IDETAPE_PC1 = (1 << 0), /* packet command (first stage) */
+- REQ_IDETAPE_PC2 = (1 << 1), /* packet command (second stage) */
+- REQ_IDETAPE_READ = (1 << 2),
+- REQ_IDETAPE_WRITE = (1 << 3),
+-};
+-
+-/* Error codes returned in rq->errors to the higher part of the driver. */
+-#define IDETAPE_ERROR_GENERAL 101
+-#define IDETAPE_ERROR_FILEMARK 102
+-#define IDETAPE_ERROR_EOD 103
+-
+-/* Structures related to the SELECT SENSE / MODE SENSE packet commands. */
+-#define IDETAPE_BLOCK_DESCRIPTOR 0
+-#define IDETAPE_CAPABILITIES_PAGE 0x2a
+-
+ /*
+ * The variables below are used for the character device interface. Additional
+ * state variables are defined in our ide_drive_t structure.
+@@ -518,17 +480,7 @@ static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i)
+ return tape;
+ }
+
+-/*
+- * Too bad. The drive wants to send us data which we are not ready to accept.
+- * Just throw it away.
+- */
+-static void idetape_discard_data(ide_drive_t *drive, unsigned int bcount)
+-{
+- while (bcount--)
+- (void) HWIF(drive)->INB(IDE_DATA_REG);
+-}
+-
+-static void idetape_input_buffers(ide_drive_t *drive, idetape_pc_t *pc,
++static void idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
+ unsigned int bcount)
+ {
+ struct idetape_bh *bh = pc->bh;
+@@ -538,7 +490,7 @@ static void idetape_input_buffers(ide_drive_t *drive, idetape_pc_t *pc,
+ if (bh == NULL) {
+ printk(KERN_ERR "ide-tape: bh == NULL in "
+ "idetape_input_buffers\n");
+- idetape_discard_data(drive, bcount);
++ ide_atapi_discard_data(drive, bcount);
+ return;
+ }
+ count = min(
+@@ -557,7 +509,7 @@ static void idetape_input_buffers(ide_drive_t *drive, idetape_pc_t *pc,
+ pc->bh = bh;
+ }
+
+-static void idetape_output_buffers(ide_drive_t *drive, idetape_pc_t *pc,
++static void idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
+ unsigned int bcount)
+ {
+ struct idetape_bh *bh = pc->bh;
+@@ -585,13 +537,13 @@ static void idetape_output_buffers(ide_drive_t *drive, idetape_pc_t *pc,
+ }
+ }
+
+-static void idetape_update_buffers(idetape_pc_t *pc)
++static void idetape_update_buffers(struct ide_atapi_pc *pc)
+ {
+ struct idetape_bh *bh = pc->bh;
+ int count;
+- unsigned int bcount = pc->actually_transferred;
++ unsigned int bcount = pc->xferred;
+
+- if (test_bit(PC_WRITING, &pc->flags))
++ if (pc->flags & PC_FLAG_WRITING)
+ return;
+ while (bcount) {
+ if (bh == NULL) {
+@@ -614,7 +566,7 @@ static void idetape_update_buffers(idetape_pc_t *pc)
+ * driver. A storage space for a maximum of IDETAPE_PC_STACK packet
+ * commands is allocated at initialization time.
+ */
+-static idetape_pc_t *idetape_next_pc_storage(ide_drive_t *drive)
++static struct ide_atapi_pc *idetape_next_pc_storage(ide_drive_t *drive)
+ {
+ idetape_tape_t *tape = drive->driver_data;
+
+@@ -649,14 +601,14 @@ static struct request *idetape_next_rq_storage(ide_drive_t *drive)
+ return (&tape->rq_stack[tape->rq_stack_index++]);
+ }
+
+-static void idetape_init_pc(idetape_pc_t *pc)
++static void idetape_init_pc(struct ide_atapi_pc *pc)
+ {
+ memset(pc->c, 0, 12);
+ pc->retries = 0;
+ pc->flags = 0;
+- pc->request_transfer = 0;
+- pc->buffer = pc->pc_buffer;
+- pc->buffer_size = IDETAPE_PC_BUFFER_SIZE;
++ pc->req_xfer = 0;
++ pc->buf = pc->pc_buf;
++ pc->buf_size = IDETAPE_PC_BUFFER_SIZE;
+ pc->bh = NULL;
+ pc->b_data = NULL;
+ }
+@@ -668,7 +620,7 @@ static void idetape_init_pc(idetape_pc_t *pc)
+ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
+ {
+ idetape_tape_t *tape = drive->driver_data;
+- idetape_pc_t *pc = tape->failed_pc;
++ struct ide_atapi_pc *pc = tape->failed_pc;
+
+ tape->sense_key = sense[2] & 0xF;
+ tape->asc = sense[12];
+@@ -677,9 +629,9 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
+ debug_log(DBG_ERR, "pc = %x, sense key = %x, asc = %x, ascq = %x\n",
+ pc->c[0], tape->sense_key, tape->asc, tape->ascq);
+
+- /* Correct pc->actually_transferred by asking the tape. */
+- if (test_bit(PC_DMA_ERROR, &pc->flags)) {
+- pc->actually_transferred = pc->request_transfer -
++ /* Correct pc->xferred by asking the tape. */
++ if (pc->flags & PC_FLAG_DMA_ERROR) {
++ pc->xferred = pc->req_xfer -
+ tape->blk_size *
+ be32_to_cpu(get_unaligned((u32 *)&sense[3]));
+ idetape_update_buffers(pc);
+@@ -697,27 +649,27 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
+ /* don't report an error, everything's ok */
+ pc->error = 0;
+ /* don't retry read/write */
+- set_bit(PC_ABORT, &pc->flags);
++ pc->flags |= PC_FLAG_ABORT;
+ }
+ }
+ if (pc->c[0] == READ_6 && (sense[2] & 0x80)) {
+ pc->error = IDETAPE_ERROR_FILEMARK;
+- set_bit(PC_ABORT, &pc->flags);
++ pc->flags |= PC_FLAG_ABORT;
+ }
+ if (pc->c[0] == WRITE_6) {
+ if ((sense[2] & 0x40) || (tape->sense_key == 0xd
+ && tape->asc == 0x0 && tape->ascq == 0x2)) {
+ pc->error = IDETAPE_ERROR_EOD;
+- set_bit(PC_ABORT, &pc->flags);
++ pc->flags |= PC_FLAG_ABORT;
+ }
+ }
+ if (pc->c[0] == READ_6 || pc->c[0] == WRITE_6) {
+ if (tape->sense_key == 8) {
+ pc->error = IDETAPE_ERROR_EOD;
+- set_bit(PC_ABORT, &pc->flags);
++ pc->flags |= PC_FLAG_ABORT;
+ }
+- if (!test_bit(PC_ABORT, &pc->flags) &&
+- pc->actually_transferred)
++ if (!(pc->flags & PC_FLAG_ABORT) &&
++ pc->xferred)
+ pc->retries = IDETAPE_MAX_PC_RETRIES + 1;
+ }
+ }
+@@ -872,14 +824,16 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
+ if (rq->cmd[0] & REQ_IDETAPE_WRITE) {
+ remove_stage = 1;
+ if (error) {
+- set_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
++ set_bit(IDETAPE_FLAG_PIPELINE_ERR,
++ &tape->flags);
+ if (error == IDETAPE_ERROR_EOD)
+ idetape_abort_pipeline(drive,
+ active_stage);
+ }
+ } else if (rq->cmd[0] & REQ_IDETAPE_READ) {
+ if (error == IDETAPE_ERROR_EOD) {
+- set_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
++ set_bit(IDETAPE_FLAG_PIPELINE_ERR,
++ &tape->flags);
+ idetape_abort_pipeline(drive, active_stage);
+ }
+ }
+@@ -912,7 +866,7 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
+ if (remove_stage)
+ idetape_remove_stage_head(drive);
+ if (tape->active_data_rq == NULL)
+- clear_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags);
++ clear_bit(IDETAPE_FLAG_PIPELINE_ACTIVE, &tape->flags);
+ spin_unlock_irqrestore(&tape->lock, flags);
+ return 0;
+ }
+@@ -924,7 +878,7 @@ static ide_startstop_t idetape_request_sense_callback(ide_drive_t *drive)
+ debug_log(DBG_PROCS, "Enter %s\n", __func__);
+
+ if (!tape->pc->error) {
+- idetape_analyze_error(drive, tape->pc->buffer);
++ idetape_analyze_error(drive, tape->pc->buf);
+ idetape_end_request(drive, 1, 0);
+ } else {
+ printk(KERN_ERR "ide-tape: Error in REQUEST SENSE itself - "
+@@ -934,13 +888,13 @@ static ide_startstop_t idetape_request_sense_callback(ide_drive_t *drive)
+ return ide_stopped;
+ }
+
+-static void idetape_create_request_sense_cmd(idetape_pc_t *pc)
++static void idetape_create_request_sense_cmd(struct ide_atapi_pc *pc)
+ {
+ idetape_init_pc(pc);
+ pc->c[0] = REQUEST_SENSE;
+ pc->c[4] = 20;
+- pc->request_transfer = 20;
+- pc->callback = &idetape_request_sense_callback;
++ pc->req_xfer = 20;
++ pc->idetape_callback = &idetape_request_sense_callback;
+ }
+
+ static void idetape_init_rq(struct request *rq, u8 cmd)
+@@ -965,7 +919,7 @@ static void idetape_init_rq(struct request *rq, u8 cmd)
+ * handling functions should queue request to the lower level part and wait for
+ * their completion using idetape_queue_pc_tail or idetape_queue_rw_tail.
+ */
+-static void idetape_queue_pc_head(ide_drive_t *drive, idetape_pc_t *pc,
++static void idetape_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc,
+ struct request *rq)
+ {
+ struct ide_tape_obj *tape = drive->driver_data;
+@@ -984,14 +938,14 @@ static void idetape_queue_pc_head(ide_drive_t *drive, idetape_pc_t *pc,
+ static ide_startstop_t idetape_retry_pc (ide_drive_t *drive)
+ {
+ idetape_tape_t *tape = drive->driver_data;
+- idetape_pc_t *pc;
++ struct ide_atapi_pc *pc;
+ struct request *rq;
+
+ (void)ide_read_error(drive);
+ pc = idetape_next_pc_storage(drive);
+ rq = idetape_next_rq_storage(drive);
+ idetape_create_request_sense_cmd(pc);
+- set_bit(IDETAPE_IGNORE_DSC, &tape->flags);
++ set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags);
+ idetape_queue_pc_head(drive, pc, rq);
+ return ide_stopped;
+ }
+@@ -1010,7 +964,7 @@ static void idetape_postpone_request(ide_drive_t *drive)
+ ide_stall_queue(drive, tape->dsc_poll_freq);
+ }
+
+-typedef void idetape_io_buf(ide_drive_t *, idetape_pc_t *, unsigned int);
++typedef void idetape_io_buf(ide_drive_t *, struct ide_atapi_pc *, unsigned int);
+
+ /*
+ * This is the usual interrupt handler which will be called during a packet
+@@ -1023,7 +977,7 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
+ {
+ ide_hwif_t *hwif = drive->hwif;
+ idetape_tape_t *tape = drive->driver_data;
+- idetape_pc_t *pc = tape->pc;
++ struct ide_atapi_pc *pc = tape->pc;
+ xfer_func_t *xferfunc;
+ idetape_io_buf *iobuf;
+ unsigned int temp;
+@@ -1038,7 +992,7 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
+ /* Clear the interrupt */
+ stat = ide_read_status(drive);
+
+- if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
++ if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
+ if (hwif->ide_dma_end(drive) || (stat & ERR_STAT)) {
+ /*
+ * A DMA error is sometimes expected. For example,
+@@ -1061,9 +1015,9 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
+ * data transfer will occur, but no DMA error.
+ * (AS, 19 Apr 2001)
+ */
+- set_bit(PC_DMA_ERROR, &pc->flags);
++ pc->flags |= PC_FLAG_DMA_ERROR;
+ } else {
+- pc->actually_transferred = pc->request_transfer;
++ pc->xferred = pc->req_xfer;
+ idetape_update_buffers(pc);
+ }
+ debug_log(DBG_PROCS, "DMA finished\n");
+@@ -1073,9 +1027,9 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
+ /* No more interrupts */
+ if ((stat & DRQ_STAT) == 0) {
+ debug_log(DBG_SENSE, "Packet command completed, %d bytes"
+- " transferred\n", pc->actually_transferred);
++ " transferred\n", pc->xferred);
+
+- clear_bit(PC_DMA_IN_PROGRESS, &pc->flags);
++ pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
+ local_irq_enable();
+
+ #if SIMULATE_ERRORS
+@@ -1088,7 +1042,7 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
+ #endif
+ if ((stat & ERR_STAT) && pc->c[0] == REQUEST_SENSE)
+ stat &= ~ERR_STAT;
+- if ((stat & ERR_STAT) || test_bit(PC_DMA_ERROR, &pc->flags)) {
++ if ((stat & ERR_STAT) || (pc->flags & PC_FLAG_DMA_ERROR)) {
+ /* Error detected */
+ debug_log(DBG_ERR, "%s: I/O error\n", tape->name);
+
+@@ -1104,7 +1058,7 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
+ return idetape_retry_pc(drive);
+ }
+ pc->error = 0;
+- if (test_bit(PC_WAIT_FOR_DSC, &pc->flags) &&
++ if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) &&
+ (stat & SEEK_STAT) == 0) {
+ /* Media access command */
+ tape->dsc_polling_start = jiffies;
+@@ -1117,9 +1071,11 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
+ if (tape->failed_pc == pc)
+ tape->failed_pc = NULL;
+ /* Command finished - Call the callback function */
+- return pc->callback(drive);
++ return pc->idetape_callback(drive);
+ }
+- if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
++
++ if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
++ pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
+ printk(KERN_ERR "ide-tape: The tape wants to issue more "
+ "interrupts in DMA mode\n");
+ printk(KERN_ERR "ide-tape: DMA disabled, reverting to PIO\n");
+@@ -1127,16 +1083,16 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
+ return ide_do_reset(drive);
+ }
+ /* Get the number of bytes to transfer on this interrupt. */
+- bcount = (hwif->INB(IDE_BCOUNTH_REG) << 8) |
+- hwif->INB(IDE_BCOUNTL_REG);
++ bcount = (hwif->INB(hwif->io_ports[IDE_BCOUNTH_OFFSET]) << 8) |
++ hwif->INB(hwif->io_ports[IDE_BCOUNTL_OFFSET]);
+
+- ireason = hwif->INB(IDE_IREASON_REG);
++ ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+
+ if (ireason & CD) {
+ printk(KERN_ERR "ide-tape: CoD != 0 in %s\n", __func__);
+ return ide_do_reset(drive);
+ }
+- if (((ireason & IO) == IO) == test_bit(PC_WRITING, &pc->flags)) {
++ if (((ireason & IO) == IO) == !!(pc->flags & PC_FLAG_WRITING)) {
+ /* Hopefully, we will never get here */
+ printk(KERN_ERR "ide-tape: We wanted to %s, ",
+ (ireason & IO) ? "Write" : "Read");
+@@ -1144,15 +1100,15 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
+ (ireason & IO) ? "Read" : "Write");
+ return ide_do_reset(drive);
+ }
+- if (!test_bit(PC_WRITING, &pc->flags)) {
++ if (!(pc->flags & PC_FLAG_WRITING)) {
+ /* Reading - Check that we have enough space */
+- temp = pc->actually_transferred + bcount;
+- if (temp > pc->request_transfer) {
+- if (temp > pc->buffer_size) {
++ temp = pc->xferred + bcount;
++ if (temp > pc->req_xfer) {
++ if (temp > pc->buf_size) {
+ printk(KERN_ERR "ide-tape: The tape wants to "
+ "send us more data than expected "
+ "- discarding data\n");
+- idetape_discard_data(drive, bcount);
++ ide_atapi_discard_data(drive, bcount);
+ ide_set_handler(drive, &idetape_pc_intr,
+ IDETAPE_WAIT_CMD, NULL);
+ return ide_started;
+@@ -1170,11 +1126,11 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
+ if (pc->bh)
+ iobuf(drive, pc, bcount);
+ else
+- xferfunc(drive, pc->current_position, bcount);
++ xferfunc(drive, pc->cur_pos, bcount);
+
+ /* Update the current position */
+- pc->actually_transferred += bcount;
+- pc->current_position += bcount;
++ pc->xferred += bcount;
++ pc->cur_pos += bcount;
+
+ debug_log(DBG_SENSE, "[cmd %x] transferred %d bytes on that intr.\n",
+ pc->c[0], bcount);
+@@ -1224,7 +1180,7 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
+ {
+ ide_hwif_t *hwif = drive->hwif;
+ idetape_tape_t *tape = drive->driver_data;
+- idetape_pc_t *pc = tape->pc;
++ struct ide_atapi_pc *pc = tape->pc;
+ int retries = 100;
+ ide_startstop_t startstop;
+ u8 ireason;
+@@ -1234,12 +1190,12 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
+ "yet DRQ isn't asserted\n");
+ return startstop;
+ }
+- ireason = hwif->INB(IDE_IREASON_REG);
++ ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+ while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) {
+ printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing "
+ "a packet command, retrying\n");
+ udelay(100);
+- ireason = hwif->INB(IDE_IREASON_REG);
++ ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+ if (retries == 0) {
+ printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while "
+ "issuing a packet command, ignoring\n");
+@@ -1256,7 +1212,7 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
+ ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
+ #ifdef CONFIG_BLK_DEV_IDEDMA
+ /* Begin DMA, if necessary */
+- if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags))
++ if (pc->flags & PC_FLAG_DMA_IN_PROGRESS)
+ hwif->dma_start(drive);
+ #endif
+ /* Send the actual packet */
+@@ -1264,7 +1220,8 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
+ return ide_started;
+ }
+
+-static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, idetape_pc_t *pc)
++static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
++ struct ide_atapi_pc *pc)
+ {
+ ide_hwif_t *hwif = drive->hwif;
+ idetape_tape_t *tape = drive->driver_data;
+@@ -1283,13 +1240,13 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, idetape_pc_t *pc)
+ tape->pc = pc;
+
+ if (pc->retries > IDETAPE_MAX_PC_RETRIES ||
+- test_bit(PC_ABORT, &pc->flags)) {
++ (pc->flags & PC_FLAG_ABORT)) {
+ /*
+ * We will "abort" retrying a packet command in case legitimate
+ * error code was received (crossing a filemark, or end of the
+ * media, for example).
+ */
+- if (!test_bit(PC_ABORT, &pc->flags)) {
++ if (!(pc->flags & PC_FLAG_ABORT)) {
+ if (!(pc->c[0] == TEST_UNIT_READY &&
+ tape->sense_key == 2 && tape->asc == 4 &&
+ (tape->ascq == 1 || tape->ascq == 8))) {
+@@ -1304,36 +1261,38 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, idetape_pc_t *pc)
+ pc->error = IDETAPE_ERROR_GENERAL;
+ }
+ tape->failed_pc = NULL;
+- return pc->callback(drive);
++ return pc->idetape_callback(drive);
+ }
+ debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]);
+
+ pc->retries++;
+ /* We haven't transferred any data yet */
+- pc->actually_transferred = 0;
+- pc->current_position = pc->buffer;
++ pc->xferred = 0;
++ pc->cur_pos = pc->buf;
+ /* Request to transfer the entire buffer at once */
+- bcount = pc->request_transfer;
++ bcount = pc->req_xfer;
+
+- if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) {
++ if (pc->flags & PC_FLAG_DMA_ERROR) {
++ pc->flags &= ~PC_FLAG_DMA_ERROR;
+ printk(KERN_WARNING "ide-tape: DMA disabled, "
+ "reverting to PIO\n");
+ ide_dma_off(drive);
+ }
+- if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
++ if ((pc->flags & PC_FLAG_DMA_RECOMMENDED) && drive->using_dma)
+ dma_ok = !hwif->dma_setup(drive);
+
+ ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK |
+ IDE_TFLAG_OUT_DEVICE, bcount, dma_ok);
+
+- if (dma_ok) /* Will begin DMA later */
+- set_bit(PC_DMA_IN_PROGRESS, &pc->flags);
+- if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) {
++ if (dma_ok)
++ /* Will begin DMA later */
++ pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
++ if (test_bit(IDETAPE_FLAG_DRQ_INTERRUPT, &tape->flags)) {
+ ide_execute_command(drive, WIN_PACKETCMD, &idetape_transfer_pc,
+ IDETAPE_WAIT_CMD, NULL);
+ return ide_started;
+ } else {
+- hwif->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG);
++ hwif->OUTB(WIN_PACKETCMD, hwif->io_ports[IDE_COMMAND_OFFSET]);
+ return idetape_transfer_pc(drive);
+ }
+ }
+@@ -1349,7 +1308,7 @@ static ide_startstop_t idetape_pc_callback(ide_drive_t *drive)
+ }
+
+ /* A mode sense command is used to "sense" tape parameters. */
+-static void idetape_create_mode_sense_cmd(idetape_pc_t *pc, u8 page_code)
++static void idetape_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code)
+ {
+ idetape_init_pc(pc);
+ pc->c[0] = MODE_SENSE;
+@@ -1368,12 +1327,12 @@ static void idetape_create_mode_sense_cmd(idetape_pc_t *pc, u8 page_code)
+ /* We will just discard data in that case */
+ pc->c[4] = 255;
+ if (page_code == IDETAPE_BLOCK_DESCRIPTOR)
+- pc->request_transfer = 12;
++ pc->req_xfer = 12;
+ else if (page_code == IDETAPE_CAPABILITIES_PAGE)
+- pc->request_transfer = 24;
++ pc->req_xfer = 24;
+ else
+- pc->request_transfer = 50;
+- pc->callback = &idetape_pc_callback;
++ pc->req_xfer = 50;
++ pc->idetape_callback = &idetape_pc_callback;
+ }
+
+ static void idetape_calculate_speeds(ide_drive_t *drive)
+@@ -1442,7 +1401,7 @@ static void idetape_calculate_speeds(ide_drive_t *drive)
+ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
+ {
+ idetape_tape_t *tape = drive->driver_data;
+- idetape_pc_t *pc = tape->pc;
++ struct ide_atapi_pc *pc = tape->pc;
+ u8 stat;
+
+ stat = ide_read_status(drive);
+@@ -1463,14 +1422,14 @@ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
+ pc->error = IDETAPE_ERROR_GENERAL;
+ tape->failed_pc = NULL;
+ }
+- return pc->callback(drive);
++ return pc->idetape_callback(drive);
+ }
+
+ static ide_startstop_t idetape_rw_callback(ide_drive_t *drive)
+ {
+ idetape_tape_t *tape = drive->driver_data;
+ struct request *rq = HWGROUP(drive)->rq;
+- int blocks = tape->pc->actually_transferred / tape->blk_size;
++ int blocks = tape->pc->xferred / tape->blk_size;
+
+ tape->avg_size += blocks * tape->blk_size;
+ tape->insert_size += blocks * tape->blk_size;
+@@ -1502,47 +1461,49 @@ static ide_startstop_t idetape_rw_callback(ide_drive_t *drive)
+ return ide_stopped;
+ }
+
+-static void idetape_create_read_cmd(idetape_tape_t *tape, idetape_pc_t *pc,
++static void idetape_create_read_cmd(idetape_tape_t *tape,
++ struct ide_atapi_pc *pc,
+ unsigned int length, struct idetape_bh *bh)
+ {
+ idetape_init_pc(pc);
+ pc->c[0] = READ_6;
+ put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
+ pc->c[1] = 1;
+- pc->callback = &idetape_rw_callback;
++ pc->idetape_callback = &idetape_rw_callback;
+ pc->bh = bh;
+ atomic_set(&bh->b_count, 0);
+- pc->buffer = NULL;
+- pc->buffer_size = length * tape->blk_size;
+- pc->request_transfer = pc->buffer_size;
+- if (pc->request_transfer == tape->stage_size)
+- set_bit(PC_DMA_RECOMMENDED, &pc->flags);
++ pc->buf = NULL;
++ pc->buf_size = length * tape->blk_size;
++ pc->req_xfer = pc->buf_size;
++ if (pc->req_xfer == tape->stage_size)
++ pc->flags |= PC_FLAG_DMA_RECOMMENDED;
+ }
+
+-static void idetape_create_write_cmd(idetape_tape_t *tape, idetape_pc_t *pc,
++static void idetape_create_write_cmd(idetape_tape_t *tape,
++ struct ide_atapi_pc *pc,
+ unsigned int length, struct idetape_bh *bh)
+ {
+ idetape_init_pc(pc);
+ pc->c[0] = WRITE_6;
+ put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
+ pc->c[1] = 1;
+- pc->callback = &idetape_rw_callback;
+- set_bit(PC_WRITING, &pc->flags);
++ pc->idetape_callback = &idetape_rw_callback;
++ pc->flags |= PC_FLAG_WRITING;
+ pc->bh = bh;
+ pc->b_data = bh->b_data;
+ pc->b_count = atomic_read(&bh->b_count);
+- pc->buffer = NULL;
+- pc->buffer_size = length * tape->blk_size;
+- pc->request_transfer = pc->buffer_size;
+- if (pc->request_transfer == tape->stage_size)
+- set_bit(PC_DMA_RECOMMENDED, &pc->flags);
++ pc->buf = NULL;
++ pc->buf_size = length * tape->blk_size;
++ pc->req_xfer = pc->buf_size;
++ if (pc->req_xfer == tape->stage_size)
++ pc->flags |= PC_FLAG_DMA_RECOMMENDED;
+ }
+
+ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
+ struct request *rq, sector_t block)
+ {
+ idetape_tape_t *tape = drive->driver_data;
+- idetape_pc_t *pc = NULL;
++ struct ide_atapi_pc *pc = NULL;
+ struct request *postponed_rq = tape->postponed_rq;
+ u8 stat;
+
+@@ -1579,10 +1540,10 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
+ stat = ide_read_status(drive);
+
+ if (!drive->dsc_overlap && !(rq->cmd[0] & REQ_IDETAPE_PC2))
+- set_bit(IDETAPE_IGNORE_DSC, &tape->flags);
++ set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags);
+
+ if (drive->post_reset == 1) {
+- set_bit(IDETAPE_IGNORE_DSC, &tape->flags);
++ set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags);
+ drive->post_reset = 0;
+ }
+
+@@ -1590,7 +1551,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
+ tape->insert_speed = tape->insert_size / 1024 * HZ /
+ (jiffies - tape->insert_time);
+ idetape_calculate_speeds(drive);
+- if (!test_and_clear_bit(IDETAPE_IGNORE_DSC, &tape->flags) &&
++ if (!test_and_clear_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags) &&
+ (stat & SEEK_STAT) == 0) {
+ if (postponed_rq == NULL) {
+ tape->dsc_polling_start = jiffies;
+@@ -1629,7 +1590,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
+ goto out;
+ }
+ if (rq->cmd[0] & REQ_IDETAPE_PC1) {
+- pc = (idetape_pc_t *) rq->buffer;
++ pc = (struct ide_atapi_pc *) rq->buffer;
+ rq->cmd[0] &= ~(REQ_IDETAPE_PC1);
+ rq->cmd[0] |= REQ_IDETAPE_PC2;
+ goto out;
+@@ -1648,7 +1609,7 @@ static inline int idetape_pipeline_active(idetape_tape_t *tape)
+ {
+ int rc1, rc2;
+
+- rc1 = test_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags);
++ rc1 = test_bit(IDETAPE_FLAG_PIPELINE_ACTIVE, &tape->flags);
+ rc2 = (tape->active_data_rq != NULL);
+ return rc1;
+ }
+@@ -1881,7 +1842,7 @@ static void idetape_wait_for_request(ide_drive_t *drive, struct request *rq)
+ static ide_startstop_t idetape_read_position_callback(ide_drive_t *drive)
+ {
+ idetape_tape_t *tape = drive->driver_data;
+- u8 *readpos = tape->pc->buffer;
++ u8 *readpos = tape->pc->buf;
+
+ debug_log(DBG_PROCS, "Enter %s\n", __func__);
+
+@@ -1894,7 +1855,7 @@ static ide_startstop_t idetape_read_position_callback(ide_drive_t *drive)
+ if (readpos[0] & 0x4) {
+ printk(KERN_INFO "ide-tape: Block location is unknown"
+ "to the tape\n");
+- clear_bit(IDETAPE_ADDRESS_VALID, &tape->flags);
++ clear_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags);
+ idetape_end_request(drive, 0, 0);
+ } else {
+ debug_log(DBG_SENSE, "Block Location - %u\n",
+@@ -1903,7 +1864,7 @@ static ide_startstop_t idetape_read_position_callback(ide_drive_t *drive)
+ tape->partition = readpos[1];
+ tape->first_frame =
+ be32_to_cpu(*(u32 *)&readpos[4]);
+- set_bit(IDETAPE_ADDRESS_VALID, &tape->flags);
++ set_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags);
+ idetape_end_request(drive, 1, 0);
+ }
+ } else {
+@@ -1917,20 +1878,20 @@ static ide_startstop_t idetape_read_position_callback(ide_drive_t *drive)
+ * writing a filemark otherwise.
+ */
+ static void idetape_create_write_filemark_cmd(ide_drive_t *drive,
+- idetape_pc_t *pc, int write_filemark)
++ struct ide_atapi_pc *pc, int write_filemark)
+ {
+ idetape_init_pc(pc);
+ pc->c[0] = WRITE_FILEMARKS;
+ pc->c[4] = write_filemark;
+- set_bit(PC_WAIT_FOR_DSC, &pc->flags);
+- pc->callback = &idetape_pc_callback;
++ pc->flags |= PC_FLAG_WAIT_FOR_DSC;
++ pc->idetape_callback = &idetape_pc_callback;
+ }
+
+-static void idetape_create_test_unit_ready_cmd(idetape_pc_t *pc)
++static void idetape_create_test_unit_ready_cmd(struct ide_atapi_pc *pc)
+ {
+ idetape_init_pc(pc);
+ pc->c[0] = TEST_UNIT_READY;
+- pc->callback = &idetape_pc_callback;
++ pc->idetape_callback = &idetape_pc_callback;
+ }
+
+ /*
+@@ -1946,7 +1907,7 @@ static void idetape_create_test_unit_ready_cmd(idetape_pc_t *pc)
+ * to the request list without waiting for it to be serviced! In that case, we
+ * usually use idetape_queue_pc_head().
+ */
+-static int __idetape_queue_pc_tail(ide_drive_t *drive, idetape_pc_t *pc)
++static int __idetape_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc)
+ {
+ struct ide_tape_obj *tape = drive->driver_data;
+ struct request rq;
+@@ -1957,24 +1918,24 @@ static int __idetape_queue_pc_tail(ide_drive_t *drive, idetape_pc_t *pc)
+ return ide_do_drive_cmd(drive, &rq, ide_wait);
+ }
+
+-static void idetape_create_load_unload_cmd(ide_drive_t *drive, idetape_pc_t *pc,
+- int cmd)
++static void idetape_create_load_unload_cmd(ide_drive_t *drive,
++ struct ide_atapi_pc *pc, int cmd)
+ {
+ idetape_init_pc(pc);
+ pc->c[0] = START_STOP;
+ pc->c[4] = cmd;
+- set_bit(PC_WAIT_FOR_DSC, &pc->flags);
+- pc->callback = &idetape_pc_callback;
++ pc->flags |= PC_FLAG_WAIT_FOR_DSC;
++ pc->idetape_callback = &idetape_pc_callback;
+ }
+
+ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
+ {
+ idetape_tape_t *tape = drive->driver_data;
+- idetape_pc_t pc;
++ struct ide_atapi_pc pc;
+ int load_attempted = 0;
+
+ /* Wait for the tape to become ready */
+- set_bit(IDETAPE_MEDIUM_PRESENT, &tape->flags);
++ set_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags);
+ timeout += jiffies;
+ while (time_before(jiffies, timeout)) {
+ idetape_create_test_unit_ready_cmd(&pc);
+@@ -1998,14 +1959,14 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
+ return -EIO;
+ }
+
+-static int idetape_queue_pc_tail(ide_drive_t *drive, idetape_pc_t *pc)
++static int idetape_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc)
+ {
+ return __idetape_queue_pc_tail(drive, pc);
+ }
+
+ static int idetape_flush_tape_buffers(ide_drive_t *drive)
+ {
+- idetape_pc_t pc;
++ struct ide_atapi_pc pc;
+ int rc;
+
+ idetape_create_write_filemark_cmd(drive, &pc, 0);
+@@ -2016,18 +1977,18 @@ static int idetape_flush_tape_buffers(ide_drive_t *drive)
+ return 0;
+ }
+
+-static void idetape_create_read_position_cmd(idetape_pc_t *pc)
++static void idetape_create_read_position_cmd(struct ide_atapi_pc *pc)
+ {
+ idetape_init_pc(pc);
+ pc->c[0] = READ_POSITION;
+- pc->request_transfer = 20;
+- pc->callback = &idetape_read_position_callback;
++ pc->req_xfer = 20;
++ pc->idetape_callback = &idetape_read_position_callback;
+ }
+
+ static int idetape_read_position(ide_drive_t *drive)
+ {
+ idetape_tape_t *tape = drive->driver_data;
+- idetape_pc_t pc;
++ struct ide_atapi_pc pc;
+ int position;
+
+ debug_log(DBG_PROCS, "Enter %s\n", __func__);
+@@ -2039,7 +2000,8 @@ static int idetape_read_position(ide_drive_t *drive)
+ return position;
+ }
+
+-static void idetape_create_locate_cmd(ide_drive_t *drive, idetape_pc_t *pc,
++static void idetape_create_locate_cmd(ide_drive_t *drive,
++ struct ide_atapi_pc *pc,
+ unsigned int block, u8 partition, int skip)
+ {
+ idetape_init_pc(pc);
+@@ -2047,12 +2009,12 @@ static void idetape_create_locate_cmd(ide_drive_t *drive, idetape_pc_t *pc,
+ pc->c[1] = 2;
+ put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[3]);
+ pc->c[8] = partition;
+- set_bit(PC_WAIT_FOR_DSC, &pc->flags);
+- pc->callback = &idetape_pc_callback;
++ pc->flags |= PC_FLAG_WAIT_FOR_DSC;
++ pc->idetape_callback = &idetape_pc_callback;
+ }
+
+-static int idetape_create_prevent_cmd(ide_drive_t *drive, idetape_pc_t *pc,
+- int prevent)
++static int idetape_create_prevent_cmd(ide_drive_t *drive,
++ struct ide_atapi_pc *pc, int prevent)
+ {
+ idetape_tape_t *tape = drive->driver_data;
+
+@@ -2063,7 +2025,7 @@ static int idetape_create_prevent_cmd(ide_drive_t *drive, idetape_pc_t *pc,
+ idetape_init_pc(pc);
+ pc->c[0] = ALLOW_MEDIUM_REMOVAL;
+ pc->c[4] = prevent;
+- pc->callback = &idetape_pc_callback;
++ pc->idetape_callback = &idetape_pc_callback;
+ return 1;
+ }
+
+@@ -2078,7 +2040,7 @@ static int __idetape_discard_read_pipeline(ide_drive_t *drive)
+
+ /* Remove merge stage. */
+ cnt = tape->merge_stage_size / tape->blk_size;
+- if (test_and_clear_bit(IDETAPE_FILEMARK, &tape->flags))
++ if (test_and_clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags))
+ ++cnt; /* Filemarks count as 1 sector */
+ tape->merge_stage_size = 0;
+ if (tape->merge_stage != NULL) {
+@@ -2087,7 +2049,7 @@ static int __idetape_discard_read_pipeline(ide_drive_t *drive)
+ }
+
+ /* Clear pipeline flags. */
+- clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
++ clear_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags);
+ tape->chrdev_dir = IDETAPE_DIR_NONE;
+
+ /* Remove pipeline stages. */
+@@ -2124,7 +2086,7 @@ static int idetape_position_tape(ide_drive_t *drive, unsigned int block,
+ {
+ idetape_tape_t *tape = drive->driver_data;
+ int retval;
+- idetape_pc_t pc;
++ struct ide_atapi_pc pc;
+
+ if (tape->chrdev_dir == IDETAPE_DIR_READ)
+ __idetape_discard_read_pipeline(drive);
+@@ -2201,46 +2163,47 @@ static void idetape_plug_pipeline(ide_drive_t *drive)
+ if (tape->next_stage == NULL)
+ return;
+ if (!idetape_pipeline_active(tape)) {
+- set_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags);
++ set_bit(IDETAPE_FLAG_PIPELINE_ACTIVE, &tape->flags);
+ idetape_activate_next_stage(drive);
+ (void) ide_do_drive_cmd(drive, tape->active_data_rq, ide_end);
+ }
+ }
+
+-static void idetape_create_inquiry_cmd(idetape_pc_t *pc)
++static void idetape_create_inquiry_cmd(struct ide_atapi_pc *pc)
+ {
+ idetape_init_pc(pc);
+ pc->c[0] = INQUIRY;
+ pc->c[4] = 254;
+- pc->request_transfer = 254;
+- pc->callback = &idetape_pc_callback;
++ pc->req_xfer = 254;
++ pc->idetape_callback = &idetape_pc_callback;
+ }
+
+-static void idetape_create_rewind_cmd(ide_drive_t *drive, idetape_pc_t *pc)
++static void idetape_create_rewind_cmd(ide_drive_t *drive,
++ struct ide_atapi_pc *pc)
+ {
+ idetape_init_pc(pc);
+ pc->c[0] = REZERO_UNIT;
+- set_bit(PC_WAIT_FOR_DSC, &pc->flags);
+- pc->callback = &idetape_pc_callback;
++ pc->flags |= PC_FLAG_WAIT_FOR_DSC;
++ pc->idetape_callback = &idetape_pc_callback;
+ }
+
+-static void idetape_create_erase_cmd(idetape_pc_t *pc)
++static void idetape_create_erase_cmd(struct ide_atapi_pc *pc)
+ {
+ idetape_init_pc(pc);
+ pc->c[0] = ERASE;
+ pc->c[1] = 1;
+- set_bit(PC_WAIT_FOR_DSC, &pc->flags);
+- pc->callback = &idetape_pc_callback;
++ pc->flags |= PC_FLAG_WAIT_FOR_DSC;
++ pc->idetape_callback = &idetape_pc_callback;
+ }
+
+-static void idetape_create_space_cmd(idetape_pc_t *pc, int count, u8 cmd)
++static void idetape_create_space_cmd(struct ide_atapi_pc *pc, int count, u8 cmd)
+ {
+ idetape_init_pc(pc);
+ pc->c[0] = SPACE;
+ put_unaligned(cpu_to_be32(count), (unsigned int *) &pc->c[1]);
+ pc->c[1] = cmd;
+- set_bit(PC_WAIT_FOR_DSC, &pc->flags);
+- pc->callback = &idetape_pc_callback;
++ pc->flags |= PC_FLAG_WAIT_FOR_DSC;
++ pc->idetape_callback = &idetape_pc_callback;
+ }
+
+ static void idetape_wait_first_stage(ide_drive_t *drive)
+@@ -2326,7 +2289,7 @@ static int idetape_add_chrdev_write_request(ide_drive_t *drive, int blocks)
+ idetape_plug_pipeline(drive);
+ }
+ }
+- if (test_and_clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags))
++ if (test_and_clear_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags))
+ /* Return a deferred error */
+ return -EIO;
+ return blocks;
+@@ -2402,7 +2365,7 @@ static void idetape_empty_write_pipeline(ide_drive_t *drive)
+ __idetape_kfree_stage(tape->merge_stage);
+ tape->merge_stage = NULL;
+ }
+- clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
++ clear_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags);
+ tape->chrdev_dir = IDETAPE_DIR_NONE;
+
+ /*
+@@ -2490,7 +2453,7 @@ static int idetape_init_read(ide_drive_t *drive, int max_stages)
+ rq.sector = tape->first_frame;
+ rq.nr_sectors = blocks;
+ rq.current_nr_sectors = blocks;
+- if (!test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags) &&
++ if (!test_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags) &&
+ tape->nr_stages < max_stages) {
+ new_stage = idetape_kmalloc_stage(tape);
+ while (new_stage != NULL) {
+@@ -2527,13 +2490,13 @@ static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks)
+ debug_log(DBG_PROCS, "Enter %s, %d blocks\n", __func__, blocks);
+
+ /* If we are at a filemark, return a read length of 0 */
+- if (test_bit(IDETAPE_FILEMARK, &tape->flags))
++ if (test_bit(IDETAPE_FLAG_FILEMARK, &tape->flags))
+ return 0;
+
+ /* Wait for the next block to reach the head of the pipeline. */
+ idetape_init_read(drive, tape->max_stages);
+ if (tape->first_stage == NULL) {
+- if (test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags))
++ if (test_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags))
+ return 0;
+ return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks,
+ tape->merge_stage->bh);
+@@ -2550,7 +2513,7 @@ static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks)
+ else {
+ idetape_switch_buffers(tape, tape->first_stage);
+ if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK)
+- set_bit(IDETAPE_FILEMARK, &tape->flags);
++ set_bit(IDETAPE_FLAG_FILEMARK, &tape->flags);
+ spin_lock_irqsave(&tape->lock, flags);
+ idetape_remove_stage_head(drive);
+ spin_unlock_irqrestore(&tape->lock, flags);
+@@ -2618,7 +2581,7 @@ static int idetape_pipeline_size(ide_drive_t *drive)
+ static int idetape_rewind_tape(ide_drive_t *drive)
+ {
+ int retval;
+- idetape_pc_t pc;
++ struct ide_atapi_pc pc;
+ idetape_tape_t *tape;
+ tape = drive->driver_data;
+
+@@ -2681,7 +2644,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
+ int mt_count)
+ {
+ idetape_tape_t *tape = drive->driver_data;
+- idetape_pc_t pc;
++ struct ide_atapi_pc pc;
+ unsigned long flags;
+ int retval, count = 0;
+ int sprev = !!(tape->caps[4] & 0x20);
+@@ -2697,12 +2660,13 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
+ if (tape->chrdev_dir == IDETAPE_DIR_READ) {
+ /* its a read-ahead buffer, scan it for crossed filemarks. */
+ tape->merge_stage_size = 0;
+- if (test_and_clear_bit(IDETAPE_FILEMARK, &tape->flags))
++ if (test_and_clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags))
+ ++count;
+ while (tape->first_stage != NULL) {
+ if (count == mt_count) {
+ if (mt_op == MTFSFM)
+- set_bit(IDETAPE_FILEMARK, &tape->flags);
++ set_bit(IDETAPE_FLAG_FILEMARK,
++ &tape->flags);
+ return 0;
+ }
+ spin_lock_irqsave(&tape->lock, flags);
+@@ -2786,7 +2750,7 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
+ debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count);
+
+ if (tape->chrdev_dir != IDETAPE_DIR_READ) {
+- if (test_bit(IDETAPE_DETECT_BS, &tape->flags))
++ if (test_bit(IDETAPE_FLAG_DETECT_BS, &tape->flags))
+ if (count > tape->blk_size &&
+ (count % tape->blk_size) == 0)
+ tape->user_bs_factor = count / tape->blk_size;
+@@ -2829,7 +2793,7 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
+ tape->merge_stage_size = bytes_read-temp;
+ }
+ finish:
+- if (!actually_read && test_bit(IDETAPE_FILEMARK, &tape->flags)) {
++ if (!actually_read && test_bit(IDETAPE_FLAG_FILEMARK, &tape->flags)) {
+ debug_log(DBG_SENSE, "%s: spacing over filemark\n", tape->name);
+
+ idetape_space_over_filemarks(drive, MTFSF, 1);
+@@ -2938,7 +2902,7 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
+
+ static int idetape_write_filemark(ide_drive_t *drive)
+ {
+- idetape_pc_t pc;
++ struct ide_atapi_pc pc;
+
+ /* Write a filemark */
+ idetape_create_write_filemark_cmd(drive, &pc, 1);
+@@ -2966,7 +2930,7 @@ static int idetape_write_filemark(ide_drive_t *drive)
+ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
+ {
+ idetape_tape_t *tape = drive->driver_data;
+- idetape_pc_t pc;
++ struct ide_atapi_pc pc;
+ int i, retval;
+
+ debug_log(DBG_ERR, "Handling MTIOCTOP ioctl: mt_op=%d, mt_count=%d\n",
+@@ -3022,7 +2986,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
+ !IDETAPE_LU_LOAD_MASK);
+ retval = idetape_queue_pc_tail(drive, &pc);
+ if (!retval)
+- clear_bit(IDETAPE_MEDIUM_PRESENT, &tape->flags);
++ clear_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags);
+ return retval;
+ case MTNOP:
+ idetape_discard_read_pipeline(drive, 0);
+@@ -3045,9 +3009,9 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
+ mt_count % tape->blk_size)
+ return -EIO;
+ tape->user_bs_factor = mt_count / tape->blk_size;
+- clear_bit(IDETAPE_DETECT_BS, &tape->flags);
++ clear_bit(IDETAPE_FLAG_DETECT_BS, &tape->flags);
+ } else
+- set_bit(IDETAPE_DETECT_BS, &tape->flags);
++ set_bit(IDETAPE_FLAG_DETECT_BS, &tape->flags);
+ return 0;
+ case MTSEEK:
+ idetape_discard_read_pipeline(drive, 0);
+@@ -3149,7 +3113,7 @@ static int idetape_chrdev_ioctl(struct inode *inode, struct file *file,
+ static void ide_tape_get_bsize_from_bdesc(ide_drive_t *drive)
+ {
+ idetape_tape_t *tape = drive->driver_data;
+- idetape_pc_t pc;
++ struct ide_atapi_pc pc;
+
+ idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_DESCRIPTOR);
+ if (idetape_queue_pc_tail(drive, &pc)) {
+@@ -3161,10 +3125,10 @@ static void ide_tape_get_bsize_from_bdesc(ide_drive_t *drive)
+ }
+ return;
+ }
+- tape->blk_size = (pc.buffer[4 + 5] << 16) +
+- (pc.buffer[4 + 6] << 8) +
+- pc.buffer[4 + 7];
+- tape->drv_write_prot = (pc.buffer[2] & 0x80) >> 7;
++ tape->blk_size = (pc.buf[4 + 5] << 16) +
++ (pc.buf[4 + 6] << 8) +
++ pc.buf[4 + 7];
++ tape->drv_write_prot = (pc.buf[2] & 0x80) >> 7;
+ }
+
+ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
+@@ -3172,7 +3136,7 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
+ unsigned int minor = iminor(inode), i = minor & ~0xc0;
+ ide_drive_t *drive;
+ idetape_tape_t *tape;
+- idetape_pc_t pc;
++ struct ide_atapi_pc pc;
+ int retval;
+
+ if (i >= MAX_HWIFS * MAX_DRIVES)
+@@ -3195,24 +3159,24 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
+
+ filp->private_data = tape;
+
+- if (test_and_set_bit(IDETAPE_BUSY, &tape->flags)) {
++ if (test_and_set_bit(IDETAPE_FLAG_BUSY, &tape->flags)) {
+ retval = -EBUSY;
+ goto out_put_tape;
+ }
+
+ retval = idetape_wait_ready(drive, 60 * HZ);
+ if (retval) {
+- clear_bit(IDETAPE_BUSY, &tape->flags);
++ clear_bit(IDETAPE_FLAG_BUSY, &tape->flags);
+ printk(KERN_ERR "ide-tape: %s: drive not ready\n", tape->name);
+ goto out_put_tape;
+ }
+
+ idetape_read_position(drive);
+- if (!test_bit(IDETAPE_ADDRESS_VALID, &tape->flags))
++ if (!test_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags))
+ (void)idetape_rewind_tape(drive);
+
+ if (tape->chrdev_dir != IDETAPE_DIR_READ)
+- clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
++ clear_bit(IDETAPE_FLAG_PIPELINE_ERR, &tape->flags);
+
+ /* Read block size and write protect status from drive. */
+ ide_tape_get_bsize_from_bdesc(drive);
+@@ -3227,7 +3191,7 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
+ if (tape->write_prot) {
+ if ((filp->f_flags & O_ACCMODE) == O_WRONLY ||
+ (filp->f_flags & O_ACCMODE) == O_RDWR) {
+- clear_bit(IDETAPE_BUSY, &tape->flags);
++ clear_bit(IDETAPE_FLAG_BUSY, &tape->flags);
+ retval = -EROFS;
+ goto out_put_tape;
+ }
+@@ -3272,7 +3236,7 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp)
+ {
+ struct ide_tape_obj *tape = ide_tape_f(filp);
+ ide_drive_t *drive = tape->drive;
+- idetape_pc_t pc;
++ struct ide_atapi_pc pc;
+ unsigned int minor = iminor(inode);
+
+ lock_kernel();
+@@ -3292,7 +3256,7 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp)
+ __idetape_kfree_stage(tape->cache_stage);
+ tape->cache_stage = NULL;
+ }
+- if (minor < 128 && test_bit(IDETAPE_MEDIUM_PRESENT, &tape->flags))
++ if (minor < 128 && test_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags))
+ (void) idetape_rewind_tape(drive);
+ if (tape->chrdev_dir == IDETAPE_DIR_NONE) {
+ if (tape->door_locked == DOOR_LOCKED) {
+@@ -3302,7 +3266,7 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp)
+ }
+ }
+ }
+- clear_bit(IDETAPE_BUSY, &tape->flags);
++ clear_bit(IDETAPE_FLAG_BUSY, &tape->flags);
+ ide_tape_put(tape);
+ unlock_kernel();
+ return 0;
+@@ -3350,7 +3314,7 @@ static int idetape_identify_device(ide_drive_t *drive)
+ static void idetape_get_inquiry_results(ide_drive_t *drive)
+ {
+ idetape_tape_t *tape = drive->driver_data;
+- idetape_pc_t pc;
++ struct ide_atapi_pc pc;
+ char fw_rev[6], vendor_id[10], product_id[18];
+
+ idetape_create_inquiry_cmd(&pc);
+@@ -3359,9 +3323,9 @@ static void idetape_get_inquiry_results(ide_drive_t *drive)
+ tape->name);
+ return;
+ }
+- memcpy(vendor_id, &pc.buffer[8], 8);
+- memcpy(product_id, &pc.buffer[16], 16);
+- memcpy(fw_rev, &pc.buffer[32], 4);
++ memcpy(vendor_id, &pc.buf[8], 8);
++ memcpy(product_id, &pc.buf[16], 16);
++ memcpy(fw_rev, &pc.buf[32], 4);
+
+ ide_fixstring(vendor_id, 10, 0);
+ ide_fixstring(product_id, 18, 0);
+@@ -3378,7 +3342,7 @@ static void idetape_get_inquiry_results(ide_drive_t *drive)
+ static void idetape_get_mode_sense_results(ide_drive_t *drive)
+ {
+ idetape_tape_t *tape = drive->driver_data;
+- idetape_pc_t pc;
++ struct ide_atapi_pc pc;
+ u8 *caps;
+ u8 speed, max_speed;
+
+@@ -3392,7 +3356,7 @@ static void idetape_get_mode_sense_results(ide_drive_t *drive)
+ put_unaligned(6*52, (u16 *)&tape->caps[16]);
+ return;
+ }
+- caps = pc.buffer + 4 + pc.buffer[3];
++ caps = pc.buf + 4 + pc.buf[3];
+
+ /* convert to host order and save for later use */
+ speed = be16_to_cpu(*(u16 *)&caps[14]);
+@@ -3506,7 +3470,7 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
+
+ /* Command packet DRQ type */
+ if (((gcw[0] & 0x60) >> 5) == 1)
+- set_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags);
++ set_bit(IDETAPE_FLAG_DRQ_INTERRUPT, &tape->flags);
+
+ tape->min_pipeline = 10;
+ tape->max_pipeline = 10;
+diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
+index 4c86a8d..155cc90 100644
+--- a/drivers/ide/ide-taskfile.c
++++ b/drivers/ide/ide-taskfile.c
+@@ -59,32 +59,34 @@ void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
+ SELECT_MASK(drive, 0);
+
+ if (task->tf_flags & IDE_TFLAG_OUT_DATA)
+- hwif->OUTW((tf->hob_data << 8) | tf->data, IDE_DATA_REG);
++ hwif->OUTW((tf->hob_data << 8) | tf->data,
++ hwif->io_ports[IDE_DATA_OFFSET]);
+
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
+- hwif->OUTB(tf->hob_feature, IDE_FEATURE_REG);
++ hwif->OUTB(tf->hob_feature, hwif->io_ports[IDE_FEATURE_OFFSET]);
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
+- hwif->OUTB(tf->hob_nsect, IDE_NSECTOR_REG);
++ hwif->OUTB(tf->hob_nsect, hwif->io_ports[IDE_NSECTOR_OFFSET]);
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
+- hwif->OUTB(tf->hob_lbal, IDE_SECTOR_REG);
++ hwif->OUTB(tf->hob_lbal, hwif->io_ports[IDE_SECTOR_OFFSET]);
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
+- hwif->OUTB(tf->hob_lbam, IDE_LCYL_REG);
++ hwif->OUTB(tf->hob_lbam, hwif->io_ports[IDE_LCYL_OFFSET]);
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
+- hwif->OUTB(tf->hob_lbah, IDE_HCYL_REG);
++ hwif->OUTB(tf->hob_lbah, hwif->io_ports[IDE_HCYL_OFFSET]);
+
+ if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
+- hwif->OUTB(tf->feature, IDE_FEATURE_REG);
++ hwif->OUTB(tf->feature, hwif->io_ports[IDE_FEATURE_OFFSET]);
+ if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
+- hwif->OUTB(tf->nsect, IDE_NSECTOR_REG);
++ hwif->OUTB(tf->nsect, hwif->io_ports[IDE_NSECTOR_OFFSET]);
+ if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
+- hwif->OUTB(tf->lbal, IDE_SECTOR_REG);
++ hwif->OUTB(tf->lbal, hwif->io_ports[IDE_SECTOR_OFFSET]);
+ if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
+- hwif->OUTB(tf->lbam, IDE_LCYL_REG);
++ hwif->OUTB(tf->lbam, hwif->io_ports[IDE_LCYL_OFFSET]);
+ if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
+- hwif->OUTB(tf->lbah, IDE_HCYL_REG);
++ hwif->OUTB(tf->lbah, hwif->io_ports[IDE_HCYL_OFFSET]);
+
+ if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
+- hwif->OUTB((tf->device & HIHI) | drive->select.all, IDE_SELECT_REG);
++ hwif->OUTB((tf->device & HIHI) | drive->select.all,
++ hwif->io_ports[IDE_SELECT_OFFSET]);
+ }
+
+ int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
+@@ -152,7 +154,8 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
+ switch (task->data_phase) {
+ case TASKFILE_MULTI_OUT:
+ case TASKFILE_OUT:
+- hwif->OUTBSYNC(drive, tf->command, IDE_COMMAND_REG);
++ hwif->OUTBSYNC(drive, tf->command,
++ hwif->io_ports[IDE_COMMAND_OFFSET]);
+ ndelay(400); /* FIXME */
+ return pre_task_out_intr(drive, task->rq);
+ case TASKFILE_MULTI_IN:
+diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
+index fc69fe2..d868ca4 100644
+--- a/drivers/ide/ide.c
++++ b/drivers/ide/ide.c
+@@ -78,6 +78,8 @@
+ /* default maximum number of failures */
+ #define IDE_DEFAULT_MAX_FAILURES 1
+
++struct class *ide_port_class;
++
+ static const u8 ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR,
+ IDE2_MAJOR, IDE3_MAJOR,
+ IDE4_MAJOR, IDE5_MAJOR,
+@@ -90,10 +92,6 @@ static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */
+ DEFINE_MUTEX(ide_cfg_mtx);
+ __cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock);
+
+-#ifdef CONFIG_IDEPCI_PCIBUS_ORDER
+-int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
+-#endif
+-
+ int noautodma = 0;
+
+ #ifdef CONFIG_BLK_DEV_IDEACPI
+@@ -102,20 +100,15 @@ int ide_noacpitfs = 1;
+ int ide_noacpionboot = 1;
+ #endif
+
+-/*
+- * This is declared extern in ide.h, for access by other IDE modules:
+- */
+ ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */
+
+-EXPORT_SYMBOL(ide_hwifs);
++static void ide_port_init_devices_data(ide_hwif_t *);
+
+ /*
+ * Do not even *think* about calling this!
+ */
+ void ide_init_port_data(ide_hwif_t *hwif, unsigned int index)
+ {
+- unsigned int unit;
+-
+ /* bulk initialize hwif & drive info with zeros */
+ memset(hwif, 0, sizeof(ide_hwif_t));
+
+@@ -134,8 +127,20 @@ void ide_init_port_data(ide_hwif_t *hwif, unsigned int index)
+
+ default_hwif_iops(hwif);
+ default_hwif_transport(hwif);
++
++ ide_port_init_devices_data(hwif);
++}
++EXPORT_SYMBOL_GPL(ide_init_port_data);
++
++static void ide_port_init_devices_data(ide_hwif_t *hwif)
++{
++ int unit;
++
+ for (unit = 0; unit < MAX_DRIVES; ++unit) {
+ ide_drive_t *drive = &hwif->drives[unit];
++ u8 j = (hwif->index * MAX_DRIVES) + unit;
++
++ memset(drive, 0, sizeof(*drive));
+
+ drive->media = ide_disk;
+ drive->select.all = (unit<<4)|0xa0;
+@@ -147,32 +152,13 @@ void ide_init_port_data(ide_hwif_t *hwif, unsigned int index)
+ drive->special.b.set_geometry = 1;
+ drive->name[0] = 'h';
+ drive->name[1] = 'd';
+- drive->name[2] = 'a' + (index * MAX_DRIVES) + unit;
++ drive->name[2] = 'a' + j;
+ drive->max_failures = IDE_DEFAULT_MAX_FAILURES;
+- drive->using_dma = 0;
+- drive->vdma = 0;
++
+ INIT_LIST_HEAD(&drive->list);
+ init_completion(&drive->gendev_rel_comp);
+ }
+ }
+-EXPORT_SYMBOL_GPL(ide_init_port_data);
+-
+-static void init_hwif_default(ide_hwif_t *hwif, unsigned int index)
+-{
+- hw_regs_t hw;
+-
+- memset(&hw, 0, sizeof(hw_regs_t));
+-
+- ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &hwif->irq);
+-
+- memcpy(hwif->io_ports, hw.io_ports, sizeof(hw.io_ports));
+-
+- hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
+-#ifdef CONFIG_BLK_DEV_HD
+- if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA)
+- hwif->noprobe = 1; /* may be overridden by ide_setup() */
+-#endif
+-}
+
+ /*
+ * init_ide_data() sets reasonable default values into all fields
+@@ -194,7 +180,6 @@ static void init_hwif_default(ide_hwif_t *hwif, unsigned int index)
+ #define MAGIC_COOKIE 0x12345678
+ static void __init init_ide_data (void)
+ {
+- ide_hwif_t *hwif;
+ unsigned int index;
+ static unsigned long magic_cookie = MAGIC_COOKIE;
+
+@@ -204,13 +189,9 @@ static void __init init_ide_data (void)
+
+ /* Initialise all interface structures */
+ for (index = 0; index < MAX_HWIFS; ++index) {
+- hwif = &ide_hwifs[index];
++ ide_hwif_t *hwif = &ide_hwifs[index];
++
+ ide_init_port_data(hwif, index);
+- init_hwif_default(hwif, index);
+-#if !defined(CONFIG_PPC32) || !defined(CONFIG_PCI)
+- hwif->irq =
+- ide_init_default_irq(hwif->io_ports[IDE_DATA_OFFSET]);
+-#endif
+ }
+ }
+
+@@ -246,30 +227,6 @@ static int ide_system_bus_speed(void)
+ return pci_dev_present(pci_default) ? 33 : 50;
+ }
+
+-ide_hwif_t * ide_find_port(unsigned long base)
+-{
+- ide_hwif_t *hwif;
+- int i;
+-
+- for (i = 0; i < MAX_HWIFS; i++) {
+- hwif = &ide_hwifs[i];
+- if (hwif->io_ports[IDE_DATA_OFFSET] == base)
+- goto found;
+- }
+-
+- for (i = 0; i < MAX_HWIFS; i++) {
+- hwif = &ide_hwifs[i];
+- if (hwif->io_ports[IDE_DATA_OFFSET] == 0)
+- goto found;
+- }
+-
+- hwif = NULL;
+-found:
+- return hwif;
+-}
+-
+-EXPORT_SYMBOL_GPL(ide_find_port);
+-
+ static struct resource* hwif_request_region(ide_hwif_t *hwif,
+ unsigned long addr, int num)
+ {
+@@ -294,29 +251,21 @@ static struct resource* hwif_request_region(ide_hwif_t *hwif,
+ int ide_hwif_request_regions(ide_hwif_t *hwif)
+ {
+ unsigned long addr;
+- unsigned int i;
+
+ if (hwif->mmio)
+ return 0;
++
+ addr = hwif->io_ports[IDE_CONTROL_OFFSET];
++
+ if (addr && !hwif_request_region(hwif, addr, 1))
+ goto control_region_busy;
+- hwif->straight8 = 0;
++
+ addr = hwif->io_ports[IDE_DATA_OFFSET];
+- if ((addr | 7) == hwif->io_ports[IDE_STATUS_OFFSET]) {
+- if (!hwif_request_region(hwif, addr, 8))
+- goto data_region_busy;
+- hwif->straight8 = 1;
+- return 0;
+- }
+- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+- addr = hwif->io_ports[i];
+- if (!hwif_request_region(hwif, addr, 1)) {
+- while (--i)
+- release_region(addr, 1);
+- goto data_region_busy;
+- }
+- }
++ BUG_ON((addr | 7) != hwif->io_ports[IDE_STATUS_OFFSET]);
++
++ if (!hwif_request_region(hwif, addr, 8))
++ goto data_region_busy;
++
+ return 0;
+
+ data_region_busy:
+@@ -342,121 +291,13 @@ control_region_busy:
+
+ void ide_hwif_release_regions(ide_hwif_t *hwif)
+ {
+- u32 i = 0;
+-
+ if (hwif->mmio)
+ return;
++
+ if (hwif->io_ports[IDE_CONTROL_OFFSET])
+ release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
+- if (hwif->straight8) {
+- release_region(hwif->io_ports[IDE_DATA_OFFSET], 8);
+- return;
+- }
+- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
+- if (hwif->io_ports[i])
+- release_region(hwif->io_ports[i], 1);
+-}
+-
+-/**
+- * ide_hwif_restore - restore hwif to template
+- * @hwif: hwif to update
+- * @tmp_hwif: template
+- *
+- * Restore hwif to a previous state by copying most settings
+- * from the template.
+- */
+-
+-static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
+-{
+- hwif->hwgroup = tmp_hwif->hwgroup;
+-
+- hwif->gendev.parent = tmp_hwif->gendev.parent;
+-
+- hwif->proc = tmp_hwif->proc;
+-
+- hwif->major = tmp_hwif->major;
+- hwif->straight8 = tmp_hwif->straight8;
+- hwif->bus_state = tmp_hwif->bus_state;
+
+- hwif->host_flags = tmp_hwif->host_flags;
+-
+- hwif->pio_mask = tmp_hwif->pio_mask;
+-
+- hwif->ultra_mask = tmp_hwif->ultra_mask;
+- hwif->mwdma_mask = tmp_hwif->mwdma_mask;
+- hwif->swdma_mask = tmp_hwif->swdma_mask;
+-
+- hwif->cbl = tmp_hwif->cbl;
+-
+- hwif->chipset = tmp_hwif->chipset;
+- hwif->hold = tmp_hwif->hold;
+-
+- hwif->dev = tmp_hwif->dev;
+-
+-#ifdef CONFIG_BLK_DEV_IDEPCI
+- hwif->cds = tmp_hwif->cds;
+-#endif
+-
+- hwif->set_pio_mode = tmp_hwif->set_pio_mode;
+- hwif->set_dma_mode = tmp_hwif->set_dma_mode;
+- hwif->mdma_filter = tmp_hwif->mdma_filter;
+- hwif->udma_filter = tmp_hwif->udma_filter;
+- hwif->selectproc = tmp_hwif->selectproc;
+- hwif->reset_poll = tmp_hwif->reset_poll;
+- hwif->pre_reset = tmp_hwif->pre_reset;
+- hwif->resetproc = tmp_hwif->resetproc;
+- hwif->maskproc = tmp_hwif->maskproc;
+- hwif->quirkproc = tmp_hwif->quirkproc;
+- hwif->busproc = tmp_hwif->busproc;
+-
+- hwif->ata_input_data = tmp_hwif->ata_input_data;
+- hwif->ata_output_data = tmp_hwif->ata_output_data;
+- hwif->atapi_input_bytes = tmp_hwif->atapi_input_bytes;
+- hwif->atapi_output_bytes = tmp_hwif->atapi_output_bytes;
+-
+- hwif->dma_host_set = tmp_hwif->dma_host_set;
+- hwif->dma_setup = tmp_hwif->dma_setup;
+- hwif->dma_exec_cmd = tmp_hwif->dma_exec_cmd;
+- hwif->dma_start = tmp_hwif->dma_start;
+- hwif->ide_dma_end = tmp_hwif->ide_dma_end;
+- hwif->ide_dma_test_irq = tmp_hwif->ide_dma_test_irq;
+- hwif->ide_dma_clear_irq = tmp_hwif->ide_dma_clear_irq;
+- hwif->dma_lost_irq = tmp_hwif->dma_lost_irq;
+- hwif->dma_timeout = tmp_hwif->dma_timeout;
+-
+- hwif->OUTB = tmp_hwif->OUTB;
+- hwif->OUTBSYNC = tmp_hwif->OUTBSYNC;
+- hwif->OUTW = tmp_hwif->OUTW;
+- hwif->OUTSW = tmp_hwif->OUTSW;
+- hwif->OUTSL = tmp_hwif->OUTSL;
+-
+- hwif->INB = tmp_hwif->INB;
+- hwif->INW = tmp_hwif->INW;
+- hwif->INSW = tmp_hwif->INSW;
+- hwif->INSL = tmp_hwif->INSL;
+-
+- hwif->sg_max_nents = tmp_hwif->sg_max_nents;
+-
+- hwif->mmio = tmp_hwif->mmio;
+- hwif->rqsize = tmp_hwif->rqsize;
+-
+-#ifndef CONFIG_BLK_DEV_IDECS
+- hwif->irq = tmp_hwif->irq;
+-#endif
+-
+- hwif->dma_base = tmp_hwif->dma_base;
+- hwif->dma_command = tmp_hwif->dma_command;
+- hwif->dma_vendor1 = tmp_hwif->dma_vendor1;
+- hwif->dma_status = tmp_hwif->dma_status;
+- hwif->dma_vendor3 = tmp_hwif->dma_vendor3;
+- hwif->dma_prdtable = tmp_hwif->dma_prdtable;
+-
+- hwif->config_data = tmp_hwif->config_data;
+- hwif->select_data = tmp_hwif->select_data;
+- hwif->extra_base = tmp_hwif->extra_base;
+- hwif->extra_ports = tmp_hwif->extra_ports;
+-
+- hwif->hwif_data = tmp_hwif->hwif_data;
++ release_region(hwif->io_ports[IDE_DATA_OFFSET], 8);
+ }
+
+ void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
+@@ -494,11 +335,38 @@ void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
+ spin_unlock_irq(&ide_lock);
+ }
+
++/* Called with ide_lock held. */
++static void __ide_port_unregister_devices(ide_hwif_t *hwif)
++{
++ int i;
++
++ for (i = 0; i < MAX_DRIVES; i++) {
++ ide_drive_t *drive = &hwif->drives[i];
++
++ if (drive->present) {
++ spin_unlock_irq(&ide_lock);
++ device_unregister(&drive->gendev);
++ wait_for_completion(&drive->gendev_rel_comp);
++ spin_lock_irq(&ide_lock);
++ }
++ }
++}
++
++void ide_port_unregister_devices(ide_hwif_t *hwif)
++{
++ mutex_lock(&ide_cfg_mtx);
++ spin_lock_irq(&ide_lock);
++ __ide_port_unregister_devices(hwif);
++ hwif->present = 0;
++ ide_port_init_devices_data(hwif);
++ spin_unlock_irq(&ide_lock);
++ mutex_unlock(&ide_cfg_mtx);
++}
++EXPORT_SYMBOL_GPL(ide_port_unregister_devices);
++
+ /**
+ * ide_unregister - free an IDE interface
+ * @index: index of interface (will change soon to a pointer)
+- * @init_default: init default hwif flag
+- * @restore: restore hwif flag
+ *
+ * Perform the final unregister of an IDE interface. At the moment
+ * we don't refcount interfaces so this will also get split up.
+@@ -518,13 +386,11 @@ void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
+ * This is raving bonkers.
+ */
+
+-void ide_unregister(unsigned int index, int init_default, int restore)
++void ide_unregister(unsigned int index)
+ {
+- ide_drive_t *drive;
+ ide_hwif_t *hwif, *g;
+- static ide_hwif_t tmp_hwif; /* protected by ide_cfg_mtx */
+ ide_hwgroup_t *hwgroup;
+- int irq_count = 0, unit;
++ int irq_count = 0;
+
+ BUG_ON(index >= MAX_HWIFS);
+
+@@ -535,15 +401,7 @@ void ide_unregister(unsigned int index, int init_default, int restore)
+ hwif = &ide_hwifs[index];
+ if (!hwif->present)
+ goto abort;
+- for (unit = 0; unit < MAX_DRIVES; ++unit) {
+- drive = &hwif->drives[unit];
+- if (!drive->present)
+- continue;
+- spin_unlock_irq(&ide_lock);
+- device_unregister(&drive->gendev);
+- wait_for_completion(&drive->gendev_rel_comp);
+- spin_lock_irq(&ide_lock);
+- }
++ __ide_port_unregister_devices(hwif);
+ hwif->present = 0;
+
+ spin_unlock_irq(&ide_lock);
+@@ -565,6 +423,7 @@ void ide_unregister(unsigned int index, int init_default, int restore)
+
+ ide_remove_port_from_hwgroup(hwif);
+
++ device_unregister(hwif->portdev);
+ device_unregister(&hwif->gendev);
+ wait_for_completion(&hwif->gendev_rel_comp);
+
+@@ -576,34 +435,14 @@ void ide_unregister(unsigned int index, int init_default, int restore)
+ unregister_blkdev(hwif->major, hwif->name);
+ spin_lock_irq(&ide_lock);
+
+- if (hwif->dma_base) {
+- (void) ide_release_dma(hwif);
+-
+- hwif->dma_base = 0;
+- hwif->dma_command = 0;
+- hwif->dma_vendor1 = 0;
+- hwif->dma_status = 0;
+- hwif->dma_vendor3 = 0;
+- hwif->dma_prdtable = 0;
+-
+- hwif->extra_base = 0;
+- hwif->extra_ports = 0;
+- }
++ if (hwif->dma_base)
++ (void)ide_release_dma(hwif);
+
+ ide_hwif_release_regions(hwif);
+
+- /* copy original settings */
+- tmp_hwif = *hwif;
+-
+ /* restore hwif data to pristine status */
+ ide_init_port_data(hwif, index);
+
+- if (init_default)
+- init_hwif_default(hwif, index);
+-
+- if (restore)
+- ide_hwif_restore(hwif, &tmp_hwif);
+-
+ abort:
+ spin_unlock_irq(&ide_lock);
+ mutex_unlock(&ide_cfg_mtx);
+@@ -622,79 +461,6 @@ void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw)
+ }
+ EXPORT_SYMBOL_GPL(ide_init_port_hw);
+
+-ide_hwif_t *ide_deprecated_find_port(unsigned long base)
+-{
+- ide_hwif_t *hwif;
+- int i;
+-
+- for (i = 0; i < MAX_HWIFS; i++) {
+- hwif = &ide_hwifs[i];
+- if (hwif->io_ports[IDE_DATA_OFFSET] == base)
+- goto found;
+- }
+-
+- for (i = 0; i < MAX_HWIFS; i++) {
+- hwif = &ide_hwifs[i];
+- if (hwif->hold)
+- continue;
+- if (!hwif->present && hwif->mate == NULL)
+- goto found;
+- }
+-
+- hwif = NULL;
+-found:
+- return hwif;
+-}
+-EXPORT_SYMBOL_GPL(ide_deprecated_find_port);
+-
+-/**
+- * ide_register_hw - register IDE interface
+- * @hw: hardware registers
+- * @quirkproc: quirkproc function
+- * @hwifp: pointer to returned hwif
+- *
+- * Register an IDE interface, specifying exactly the registers etc.
+- *
+- * Returns -1 on error.
+- */
+-
+-int ide_register_hw(hw_regs_t *hw, void (*quirkproc)(ide_drive_t *),
+- ide_hwif_t **hwifp)
+-{
+- int index, retry = 1;
+- ide_hwif_t *hwif;
+- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+-
+- do {
+- hwif = ide_deprecated_find_port(hw->io_ports[IDE_DATA_OFFSET]);
+- if (hwif)
+- goto found;
+- for (index = 0; index < MAX_HWIFS; index++)
+- ide_unregister(index, 1, 1);
+- } while (retry--);
+- return -1;
+-found:
+- index = hwif->index;
+- if (hwif->present)
+- ide_unregister(index, 0, 1);
+- else if (!hwif->hold)
+- ide_init_port_data(hwif, index);
+-
+- ide_init_port_hw(hwif, hw);
+- hwif->quirkproc = quirkproc;
+-
+- idx[0] = index;
+-
+- ide_device_add(idx, NULL);
+-
+- if (hwifp)
+- *hwifp = hwif;
+-
+- return hwif->present ? index : -1;
+-}
+-
+-EXPORT_SYMBOL(ide_register_hw);
+-
+ /*
+ * Locks for IDE setting functionality
+ */
+@@ -818,11 +584,13 @@ out:
+ int set_pio_mode(ide_drive_t *drive, int arg)
+ {
+ struct request rq;
++ ide_hwif_t *hwif = drive->hwif;
+
+ if (arg < 0 || arg > 255)
+ return -EINVAL;
+
+- if (drive->hwif->set_pio_mode == NULL)
++ if (hwif->set_pio_mode == NULL ||
++ (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
+ return -ENOSYS;
+
+ if (drive->special.b.set_tune)
+@@ -997,27 +765,6 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
+ if (!capable(CAP_SYS_RAWIO))
+ return -EACCES;
+ return ide_task_ioctl(drive, cmd, arg);
+-
+- case HDIO_SCAN_HWIF:
+- {
+- hw_regs_t hw;
+- int args[3];
+- if (!capable(CAP_SYS_RAWIO)) return -EACCES;
+- if (copy_from_user(args, p, 3 * sizeof(int)))
+- return -EFAULT;
+- memset(&hw, 0, sizeof(hw));
+- ide_init_hwif_ports(&hw, (unsigned long) args[0],
+- (unsigned long) args[1], NULL);
+- hw.irq = args[2];
+- if (ide_register_hw(&hw, NULL, NULL) == -1)
+- return -EIO;
+- return 0;
+- }
+- case HDIO_UNREGISTER_HWIF:
+- if (!capable(CAP_SYS_RAWIO)) return -EACCES;
+- /* (arg > MAX_HWIFS) checked in function */
+- ide_unregister(arg, 1, 1);
+- return 0;
+ case HDIO_SET_NICE:
+ if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+ if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1))))
+@@ -1071,8 +818,6 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
+ case HDIO_SET_BUSSTATE:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+- if (HWIF(drive)->busproc)
+- return HWIF(drive)->busproc(drive, (int)arg);
+ return -EOPNOTSUPP;
+ default:
+ return -EINVAL;
+@@ -1173,8 +918,9 @@ extern int probe_dtc2278;
+ extern int probe_ht6560b;
+ extern int probe_qd65xx;
+ extern int cmd640_vlb;
++extern int probe_4drives;
+
+-static int __initdata is_chipset_set[MAX_HWIFS];
++static int __initdata is_chipset_set;
+
+ /*
+ * ide_setup() gets called VERY EARLY during initialization,
+@@ -1217,14 +963,6 @@ static int __init ide_setup(char *s)
+ goto obsolete_option;
+ }
+
+-#ifdef CONFIG_IDEPCI_PCIBUS_ORDER
+- if (!strcmp(s, "ide=reverse")) {
+- ide_scan_direction = 1;
+- printk(" : Enabled support for IDE inverse scan order.\n");
+- goto obsolete_option;
+- }
+-#endif
+-
+ #ifdef CONFIG_BLK_DEV_IDEACPI
+ if (!strcmp(s, "ide=noacpi")) {
+ //printk(" : Disable IDE ACPI support.\n");
+@@ -1335,13 +1073,11 @@ static int __init ide_setup(char *s)
+ * (-8, -9, -10) are reserved to ease the hardcoding.
+ */
+ static const char *ide_words[] = {
+- "noprobe", "serialize", "minus3", "minus4",
++ "minus1", "serialize", "minus3", "minus4",
+ "reset", "minus6", "ata66", "minus8", "minus9",
+ "minus10", "four", "qd65xx", "ht6560b", "cmd640_vlb",
+ "dtc2278", "umc8672", "ali14xx", NULL };
+
+- hw_regs_t hwregs;
+-
+ hw = s[3] - '0';
+ hwif = &ide_hwifs[hw];
+ i = match_parm(&s[4], ide_words, vals, 3);
+@@ -1350,19 +1086,14 @@ static int __init ide_setup(char *s)
+ * Cryptic check to ensure chipset not already set for hwif.
+ * Note: we can't depend on hwif->chipset here.
+ */
+- if ((i >= -18 && i <= -11) || (i > 0 && i <= 3)) {
++ if (i >= -18 && i <= -11) {
+ /* chipset already specified */
+- if (is_chipset_set[hw])
++ if (is_chipset_set)
+ goto bad_option;
+- if (i > -18 && i <= -11) {
+- /* these drivers are for "ide0=" only */
+- if (hw != 0)
+- goto bad_hwif;
+- /* chipset already specified for 2nd port */
+- if (is_chipset_set[hw+1])
+- goto bad_option;
+- }
+- is_chipset_set[hw] = 1;
++ /* these drivers are for "ide0=" only */
++ if (hw != 0)
++ goto bad_hwif;
++ is_chipset_set = 1;
+ printk("\n");
+ }
+
+@@ -1399,19 +1130,9 @@ static int __init ide_setup(char *s)
+ #endif
+ #ifdef CONFIG_BLK_DEV_4DRIVES
+ case -11: /* "four" drives on one set of ports */
+- {
+- ide_hwif_t *mate = &ide_hwifs[hw^1];
+- mate->drives[0].select.all ^= 0x20;
+- mate->drives[1].select.all ^= 0x20;
+- hwif->chipset = mate->chipset = ide_4drives;
+- mate->irq = hwif->irq;
+- memcpy(mate->io_ports, hwif->io_ports, sizeof(hwif->io_ports));
+- hwif->mate = mate;
+- mate->mate = hwif;
+- hwif->serialized = mate->serialized = 1;
++ probe_4drives = 1;
+ goto obsolete_option;
+- }
+-#endif /* CONFIG_BLK_DEV_4DRIVES */
++#endif
+ case -10: /* minus10 */
+ case -9: /* minus9 */
+ case -8: /* minus8 */
+@@ -1439,24 +1160,12 @@ static int __init ide_setup(char *s)
+ hwif->serialized = hwif->mate->serialized = 1;
+ goto obsolete_option;
+
+- case -1: /* "noprobe" */
+- hwif->noprobe = 1;
+- goto obsolete_option;
+-
+- case 1: /* base */
+- vals[1] = vals[0] + 0x206; /* default ctl */
+- case 2: /* base,ctl */
+- vals[2] = 0; /* default irq = probe for it */
+- case 3: /* base,ctl,irq */
+- memset(&hwregs, 0, sizeof(hwregs));
+- ide_init_hwif_ports(&hwregs, vals[0], vals[1], &hwif->irq);
+- memcpy(hwif->io_ports, hwregs.io_ports, sizeof(hwif->io_ports));
+- hwif->irq = vals[2];
+- hwif->noprobe = 0;
+- hwif->chipset = ide_forced;
+- goto obsolete_option;
+-
+- case 0: goto bad_option;
++ case -1:
++ case 0:
++ case 1:
++ case 2:
++ case 3:
++ goto bad_option;
+ default:
+ printk(" -- SUPPORT NOT CONFIGURED IN THIS KERNEL\n");
+ return 1;
+@@ -1601,6 +1310,13 @@ struct bus_type ide_bus_type = {
+
+ EXPORT_SYMBOL_GPL(ide_bus_type);
+
++static void ide_port_class_release(struct device *portdev)
++{
++ ide_hwif_t *hwif = dev_get_drvdata(portdev);
++
++ put_device(&hwif->gendev);
++}
++
+ /*
+ * This is gets invoked once during initialization, to set *everything* up
+ */
+@@ -1621,11 +1337,23 @@ static int __init ide_init(void)
+ return ret;
+ }
+
++ ide_port_class = class_create(THIS_MODULE, "ide_port");
++ if (IS_ERR(ide_port_class)) {
++ ret = PTR_ERR(ide_port_class);
++ goto out_port_class;
++ }
++ ide_port_class->dev_release = ide_port_class_release;
++
+ init_ide_data();
+
+ proc_ide_create();
+
+ return 0;
++
++out_port_class:
++ bus_unregister(&ide_bus_type);
++
++ return ret;
+ }
+
+ #ifdef MODULE
+@@ -1658,10 +1386,12 @@ void __exit cleanup_module (void)
+ int index;
+
+ for (index = 0; index < MAX_HWIFS; ++index)
+- ide_unregister(index, 0, 0);
++ ide_unregister(index);
+
+ proc_ide_destroy();
+
++ class_destroy(ide_port_class);
++
+ bus_unregister(&ide_bus_type);
+ }
+
+diff --git a/drivers/ide/legacy/Makefile b/drivers/ide/legacy/Makefile
+index 7043ec7..6939329 100644
+--- a/drivers/ide/legacy/Makefile
++++ b/drivers/ide/legacy/Makefile
+@@ -6,6 +6,7 @@ obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o
+ obj-$(CONFIG_BLK_DEV_DTC2278) += dtc2278.o
+ obj-$(CONFIG_BLK_DEV_HT6560B) += ht6560b.o
+ obj-$(CONFIG_BLK_DEV_QD65XX) += qd65xx.o
++obj-$(CONFIG_BLK_DEV_4DRIVES) += ide-4drives.o
+
+ obj-$(CONFIG_BLK_DEV_GAYLE) += gayle.o
+ obj-$(CONFIG_BLK_DEV_FALCON_IDE) += falconide.o
+diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c
+index d4d1a6b..33bb7b8 100644
+--- a/drivers/ide/legacy/ali14xx.c
++++ b/drivers/ide/legacy/ali14xx.c
+@@ -86,7 +86,7 @@ static u8 regOff; /* output to base port to close registers */
+ /*
+ * Read a controller register.
+ */
+-static inline u8 inReg (u8 reg)
++static inline u8 inReg(u8 reg)
+ {
+ outb_p(reg, regPort);
+ return inb(dataPort);
+@@ -95,7 +95,7 @@ static inline u8 inReg (u8 reg)
+ /*
+ * Write a controller register.
+ */
+-static void outReg (u8 data, u8 reg)
++static void outReg(u8 data, u8 reg)
+ {
+ outb_p(reg, regPort);
+ outb_p(data, dataPort);
+@@ -143,7 +143,7 @@ static void ali14xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ /*
+ * Auto-detect the IDE controller port.
+ */
+-static int __init findPort (void)
++static int __init findPort(void)
+ {
+ int i;
+ u8 t;
+@@ -175,7 +175,8 @@ static int __init findPort (void)
+ /*
+ * Initialize controller registers with default values.
+ */
+-static int __init initRegisters (void) {
++static int __init initRegisters(void)
++{
+ const RegInitializer *p;
+ u8 t;
+ unsigned long flags;
+@@ -199,7 +200,9 @@ static const struct ide_port_info ali14xx_port_info = {
+
+ static int __init ali14xx_probe(void)
+ {
+- static u8 idx[4] = { 0, 1, 0xff, 0xff };
++ ide_hwif_t *hwif, *mate;
++ static u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
++ hw_regs_t hw[2];
+
+ printk(KERN_DEBUG "ali14xx: base=0x%03x, regOn=0x%02x.\n",
+ basePort, regOn);
+@@ -210,15 +213,34 @@ static int __init ali14xx_probe(void)
+ return 1;
+ }
+
+- ide_hwifs[0].set_pio_mode = &ali14xx_set_pio_mode;
+- ide_hwifs[1].set_pio_mode = &ali14xx_set_pio_mode;
++ memset(&hw, 0, sizeof(hw));
++
++ ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
++ hw[0].irq = 14;
++
++ ide_std_init_ports(&hw[1], 0x170, 0x376);
++ hw[1].irq = 15;
++
++ hwif = ide_find_port();
++ if (hwif) {
++ ide_init_port_hw(hwif, &hw[0]);
++ hwif->set_pio_mode = &ali14xx_set_pio_mode;
++ idx[0] = hwif->index;
++ }
++
++ mate = ide_find_port();
++ if (mate) {
++ ide_init_port_hw(mate, &hw[1]);
++ mate->set_pio_mode = &ali14xx_set_pio_mode;
++ idx[1] = mate->index;
++ }
+
+ ide_device_add(idx, &ali14xx_port_info);
+
+ return 0;
+ }
+
+-int probe_ali14xx = 0;
++int probe_ali14xx;
+
+ module_param_named(probe, probe_ali14xx, bool, 0);
+ MODULE_PARM_DESC(probe, "probe for ALI M14xx chipsets");
+diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c
+index fdd3791..6956eb8 100644
+--- a/drivers/ide/legacy/buddha.c
++++ b/drivers/ide/legacy/buddha.c
+@@ -221,7 +221,7 @@ fail_base2:
+
+ buddha_setup_ports(&hw, base, ctl, irq_port, ack_intr);
+
+- hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++ hwif = ide_find_port();
+ if (hwif) {
+ u8 index = hwif->index;
+
+diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/legacy/dtc2278.c
+index 73396f7..9c6b324 100644
+--- a/drivers/ide/legacy/dtc2278.c
++++ b/drivers/ide/legacy/dtc2278.c
+@@ -102,13 +102,8 @@ static int __init dtc2278_probe(void)
+ {
+ unsigned long flags;
+ ide_hwif_t *hwif, *mate;
+- static u8 idx[4] = { 0, 1, 0xff, 0xff };
+-
+- hwif = &ide_hwifs[0];
+- mate = &ide_hwifs[1];
+-
+- if (hwif->chipset != ide_unknown || mate->chipset != ide_unknown)
+- return 1;
++ static u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
++ hw_regs_t hw[2];
+
+ local_irq_save(flags);
+ /*
+@@ -128,7 +123,26 @@ static int __init dtc2278_probe(void)
+ #endif
+ local_irq_restore(flags);
+
+- hwif->set_pio_mode = &dtc2278_set_pio_mode;
++ memset(&hw, 0, sizeof(hw));
++
++ ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
++ hw[0].irq = 14;
++
++ ide_std_init_ports(&hw[1], 0x170, 0x376);
++ hw[1].irq = 15;
++
++ hwif = ide_find_port();
++ if (hwif) {
++ ide_init_port_hw(hwif, &hw[0]);
++ hwif->set_pio_mode = dtc2278_set_pio_mode;
++ idx[0] = hwif->index;
++ }
++
++ mate = ide_find_port();
++ if (mate) {
++ ide_init_port_hw(mate, &hw[1]);
++ idx[1] = mate->index;
++ }
+
+ ide_device_add(idx, &dtc2278_port_info);
+
+diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c
+index e950afa..8c9c9f7 100644
+--- a/drivers/ide/legacy/falconide.c
++++ b/drivers/ide/legacy/falconide.c
+@@ -22,6 +22,7 @@
+ #include <asm/atariints.h>
+ #include <asm/atari_stdma.h>
+
++#define DRV_NAME "falconide"
+
+ /*
+ * Base of the IDE interface
+@@ -74,15 +75,21 @@ static int __init falconide_init(void)
+
+ printk(KERN_INFO "ide: Falcon IDE controller\n");
+
++ if (!request_mem_region(ATA_HD_BASE, 0x40, DRV_NAME)) {
++ printk(KERN_ERR "%s: resources busy\n", DRV_NAME);
++ return -EBUSY;
++ }
++
+ falconide_setup_ports(&hw);
+
+- hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++ hwif = ide_find_port();
+ if (hwif) {
+ u8 index = hwif->index;
+ u8 idx[4] = { index, 0xff, 0xff, 0xff };
+
+ ide_init_port_data(hwif, index);
+ ide_init_port_hw(hwif, &hw);
++ hwif->mmio = 1;
+
+ ide_get_lock(NULL, NULL);
+ ide_device_add(idx, NULL);
+diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c
+index e3b4638..fcc8d52 100644
+--- a/drivers/ide/legacy/gayle.c
++++ b/drivers/ide/legacy/gayle.c
+@@ -175,7 +175,7 @@ found:
+
+ gayle_setup_ports(&hw, base, ctrlport, irqport, ack_intr);
+
+- hwif = ide_find_port(base);
++ hwif = ide_find_port();
+ if (hwif) {
+ u8 index = hwif->index;
+
+diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c
+index 0b0d867..abdedf5 100644
+--- a/drivers/ide/legacy/hd.c
++++ b/drivers/ide/legacy/hd.c
+@@ -122,12 +122,12 @@ static int hd_error;
+ * This struct defines the HD's and their types.
+ */
+ struct hd_i_struct {
+- unsigned int head,sect,cyl,wpcom,lzone,ctl;
++ unsigned int head, sect, cyl, wpcom, lzone, ctl;
+ int unit;
+ int recalibrate;
+ int special_op;
+ };
+-
++
+ #ifdef HD_TYPE
+ static struct hd_i_struct hd_info[] = { HD_TYPE };
+ static int NR_HD = ARRAY_SIZE(hd_info);
+@@ -168,7 +168,7 @@ unsigned long read_timer(void)
+
+ spin_lock_irqsave(&i8253_lock, flags);
+ t = jiffies * 11932;
+- outb_p(0, 0x43);
++ outb_p(0, 0x43);
+ i = inb_p(0x40);
+ i |= inb(0x40) << 8;
+ spin_unlock_irqrestore(&i8253_lock, flags);
+@@ -183,7 +183,7 @@ static void __init hd_setup(char *str, int *ints)
+ if (ints[0] != 3)
+ return;
+ if (hd_info[0].head != 0)
+- hdind=1;
++ hdind = 1;
+ hd_info[hdind].head = ints[2];
+ hd_info[hdind].sect = ints[3];
+ hd_info[hdind].cyl = ints[1];
+@@ -193,7 +193,7 @@ static void __init hd_setup(char *str, int *ints)
+ NR_HD = hdind+1;
+ }
+
+-static void dump_status (const char *msg, unsigned int stat)
++static void dump_status(const char *msg, unsigned int stat)
+ {
+ char *name = "hd?";
+ if (CURRENT)
+@@ -291,7 +291,6 @@ static int controller_ready(unsigned int drive, unsigned int head)
+ return 0;
+ }
+
+-
+ static void hd_out(struct hd_i_struct *disk,
+ unsigned int nsect,
+ unsigned int sect,
+@@ -313,15 +312,15 @@ static void hd_out(struct hd_i_struct *disk,
+ return;
+ }
+ SET_HANDLER(intr_addr);
+- outb_p(disk->ctl,HD_CMD);
+- port=HD_DATA;
+- outb_p(disk->wpcom>>2,++port);
+- outb_p(nsect,++port);
+- outb_p(sect,++port);
+- outb_p(cyl,++port);
+- outb_p(cyl>>8,++port);
+- outb_p(0xA0|(disk->unit<<4)|head,++port);
+- outb_p(cmd,++port);
++ outb_p(disk->ctl, HD_CMD);
++ port = HD_DATA;
++ outb_p(disk->wpcom >> 2, ++port);
++ outb_p(nsect, ++port);
++ outb_p(sect, ++port);
++ outb_p(cyl, ++port);
++ outb_p(cyl >> 8, ++port);
++ outb_p(0xA0 | (disk->unit << 4) | head, ++port);
++ outb_p(cmd, ++port);
+ }
+
+ static void hd_request (void);
+@@ -344,14 +343,14 @@ static void reset_controller(void)
+ {
+ int i;
+
+- outb_p(4,HD_CMD);
+- for(i = 0; i < 1000; i++) barrier();
+- outb_p(hd_info[0].ctl & 0x0f,HD_CMD);
+- for(i = 0; i < 1000; i++) barrier();
++ outb_p(4, HD_CMD);
++ for (i = 0; i < 1000; i++) barrier();
++ outb_p(hd_info[0].ctl & 0x0f, HD_CMD);
++ for (i = 0; i < 1000; i++) barrier();
+ if (drive_busy())
+ printk("hd: controller still busy\n");
+ else if ((hd_error = inb(HD_ERROR)) != 1)
+- printk("hd: controller reset failed: %02x\n",hd_error);
++ printk("hd: controller reset failed: %02x\n", hd_error);
+ }
+
+ static void reset_hd(void)
+@@ -371,8 +370,8 @@ repeat:
+ if (++i < NR_HD) {
+ struct hd_i_struct *disk = &hd_info[i];
+ disk->special_op = disk->recalibrate = 1;
+- hd_out(disk,disk->sect,disk->sect,disk->head-1,
+- disk->cyl,WIN_SPECIFY,&reset_hd);
++ hd_out(disk, disk->sect, disk->sect, disk->head-1,
++ disk->cyl, WIN_SPECIFY, &reset_hd);
+ if (reset)
+ goto repeat;
+ } else
+@@ -393,7 +392,7 @@ static void unexpected_hd_interrupt(void)
+ unsigned int stat = inb_p(HD_STATUS);
+
+ if (stat & (BUSY_STAT|DRQ_STAT|ECC_STAT|ERR_STAT)) {
+- dump_status ("unexpected interrupt", stat);
++ dump_status("unexpected interrupt", stat);
+ SET_TIMER;
+ }
+ }
+@@ -453,7 +452,7 @@ static void read_intr(void)
+ return;
+ ok_to_read:
+ req = CURRENT;
+- insw(HD_DATA,req->buffer,256);
++ insw(HD_DATA, req->buffer, 256);
+ req->sector++;
+ req->buffer += 512;
+ req->errors = 0;
+@@ -507,7 +506,7 @@ ok_to_write:
+ end_request(req, 1);
+ if (i > 0) {
+ SET_HANDLER(&write_intr);
+- outsw(HD_DATA,req->buffer,256);
++ outsw(HD_DATA, req->buffer, 256);
+ local_irq_enable();
+ } else {
+ #if (HD_DELAY > 0)
+@@ -560,11 +559,11 @@ static int do_special_op(struct hd_i_struct *disk, struct request *req)
+ {
+ if (disk->recalibrate) {
+ disk->recalibrate = 0;
+- hd_out(disk,disk->sect,0,0,0,WIN_RESTORE,&recal_intr);
++ hd_out(disk, disk->sect, 0, 0, 0, WIN_RESTORE, &recal_intr);
+ return reset;
+ }
+ if (disk->head > 16) {
+- printk ("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name);
++ printk("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name);
+ end_request(req, 0);
+ }
+ disk->special_op = 0;
+@@ -633,19 +632,21 @@ repeat:
+ if (blk_fs_request(req)) {
+ switch (rq_data_dir(req)) {
+ case READ:
+- hd_out(disk,nsect,sec,head,cyl,WIN_READ,&read_intr);
++ hd_out(disk, nsect, sec, head, cyl, WIN_READ,
++ &read_intr);
+ if (reset)
+ goto repeat;
+ break;
+ case WRITE:
+- hd_out(disk,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
++ hd_out(disk, nsect, sec, head, cyl, WIN_WRITE,
++ &write_intr);
+ if (reset)
+ goto repeat;
+ if (wait_DRQ()) {
+ bad_rw_intr();
+ goto repeat;
+ }
+- outsw(HD_DATA,req->buffer,256);
++ outsw(HD_DATA, req->buffer, 256);
+ break;
+ default:
+ printk("unknown hd-command\n");
+@@ -655,7 +656,7 @@ repeat:
+ }
+ }
+
+-static void do_hd_request (struct request_queue * q)
++static void do_hd_request(struct request_queue *q)
+ {
+ disable_irq(HD_IRQ);
+ hd_request();
+@@ -708,12 +709,12 @@ static int __init hd_init(void)
+ {
+ int drive;
+
+- if (register_blkdev(MAJOR_NR,"hd"))
++ if (register_blkdev(MAJOR_NR, "hd"))
+ return -1;
+
+ hd_queue = blk_init_queue(do_hd_request, &hd_lock);
+ if (!hd_queue) {
+- unregister_blkdev(MAJOR_NR,"hd");
++ unregister_blkdev(MAJOR_NR, "hd");
+ return -ENOMEM;
+ }
+
+@@ -742,7 +743,7 @@ static int __init hd_init(void)
+ goto out;
+ }
+
+- for (drive=0 ; drive < NR_HD ; drive++) {
++ for (drive = 0 ; drive < NR_HD ; drive++) {
+ struct gendisk *disk = alloc_disk(64);
+ struct hd_i_struct *p = &hd_info[drive];
+ if (!disk)
+@@ -756,7 +757,7 @@ static int __init hd_init(void)
+ disk->queue = hd_queue;
+ p->unit = drive;
+ hd_gendisk[drive] = disk;
+- printk ("%s: %luMB, CHS=%d/%d/%d\n",
++ printk("%s: %luMB, CHS=%d/%d/%d\n",
+ disk->disk_name, (unsigned long)get_capacity(disk)/2048,
+ p->cyl, p->head, p->sect);
+ }
+@@ -776,7 +777,7 @@ static int __init hd_init(void)
+ }
+
+ /* Let them fly */
+- for(drive=0; drive < NR_HD; drive++)
++ for (drive = 0; drive < NR_HD; drive++)
+ add_disk(hd_gendisk[drive]);
+
+ return 0;
+@@ -791,7 +792,7 @@ out1:
+ NR_HD = 0;
+ out:
+ del_timer(&device_timer);
+- unregister_blkdev(MAJOR_NR,"hd");
++ unregister_blkdev(MAJOR_NR, "hd");
+ blk_cleanup_queue(hd_queue);
+ return -1;
+ Enomem:
+@@ -800,7 +801,8 @@ Enomem:
+ goto out;
+ }
+
+-static int __init parse_hd_setup (char *line) {
++static int __init parse_hd_setup(char *line)
++{
+ int ints[6];
+
+ (void) get_options(line, ARRAY_SIZE(ints), ints);
+diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c
+index 78ca68e..60f52f5 100644
+--- a/drivers/ide/legacy/ht6560b.c
++++ b/drivers/ide/legacy/ht6560b.c
+@@ -35,6 +35,7 @@
+ * Try: http://www.maf.iki.fi/~maf/ht6560b/
+ */
+
++#define DRV_NAME "ht6560b"
+ #define HT6560B_VERSION "v0.08"
+
+ #include <linux/module.h>
+@@ -82,7 +83,7 @@
+ * out how they setup those cycle time interfacing values, as they at Holtek
+ * call them. IDESETUP.COM that is supplied with the drivers figures out
+ * optimal values and fetches those values to drivers. I found out that
+- * they use IDE_SELECT_REG to fetch timings to the ide board right after
++ * they use Select register to fetch timings to the ide board right after
+ * interface switching. After that it was quite easy to add code to
+ * ht6560b.c.
+ *
+@@ -127,6 +128,7 @@
+ */
+ static void ht6560b_selectproc (ide_drive_t *drive)
+ {
++ ide_hwif_t *hwif = drive->hwif;
+ unsigned long flags;
+ static u8 current_select = 0;
+ static u8 current_timing = 0;
+@@ -155,8 +157,8 @@ static void ht6560b_selectproc (ide_drive_t *drive)
+ /*
+ * Set timing for this drive:
+ */
+- outb(timing, IDE_SELECT_REG);
+- (void)inb(IDE_STATUS_REG);
++ outb(timing, hwif->io_ports[IDE_SELECT_OFFSET]);
++ (void)inb(hwif->io_ports[IDE_STATUS_OFFSET]);
+ #ifdef DEBUG
+ printk("ht6560b: %s: select=%#x timing=%#x\n",
+ drive->name, select, timing);
+@@ -193,9 +195,9 @@ static int __init try_to_init_ht6560b(void)
+ * Ht6560b autodetected
+ */
+ outb(HT_CONFIG_DEFAULT, HT_CONFIG_PORT);
+- outb(HT_TIMING_DEFAULT, 0x1f6); /* IDE_SELECT_REG */
+- (void) inb(0x1f7); /* IDE_STATUS_REG */
+-
++ outb(HT_TIMING_DEFAULT, 0x1f6); /* Select register */
++ (void)inb(0x1f7); /* Status register */
++
+ printk("ht6560b " HT6560B_VERSION
+ ": chipset detected and initialized"
+ #ifdef DEBUG
+@@ -338,15 +340,13 @@ static const struct ide_port_info ht6560b_port_info __initdata = {
+ static int __init ht6560b_init(void)
+ {
+ ide_hwif_t *hwif, *mate;
+- static u8 idx[4] = { 0, 1, 0xff, 0xff };
++ static u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
++ hw_regs_t hw[2];
+
+ if (probe_ht6560b == 0)
+ return -ENODEV;
+
+- hwif = &ide_hwifs[0];
+- mate = &ide_hwifs[1];
+-
+- if (!request_region(HT_CONFIG_PORT, 1, hwif->name)) {
++ if (!request_region(HT_CONFIG_PORT, 1, DRV_NAME)) {
+ printk(KERN_NOTICE "%s: HT_CONFIG_PORT not found\n",
+ __FUNCTION__);
+ return -ENODEV;
+@@ -357,14 +357,31 @@ static int __init ht6560b_init(void)
+ goto release_region;
+ }
+
+- hwif->selectproc = &ht6560b_selectproc;
+- hwif->set_pio_mode = &ht6560b_set_pio_mode;
++ memset(&hw, 0, sizeof(hw));
++
++ ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
++ hw[0].irq = 14;
+
+- mate->selectproc = &ht6560b_selectproc;
+- mate->set_pio_mode = &ht6560b_set_pio_mode;
++ ide_std_init_ports(&hw[1], 0x170, 0x376);
++ hw[1].irq = 15;
+
+- hwif->port_init_devs = ht6560b_port_init_devs;
+- mate->port_init_devs = ht6560b_port_init_devs;
++ hwif = ide_find_port();
++ if (hwif) {
++ ide_init_port_hw(hwif, &hw[0]);
++ hwif->selectproc = ht6560b_selectproc;
++ hwif->set_pio_mode = ht6560b_set_pio_mode;
++ hwif->port_init_devs = ht6560b_port_init_devs;
++ idx[0] = hwif->index;
++ }
++
++ mate = ide_find_port();
++ if (mate) {
++ ide_init_port_hw(mate, &hw[1]);
++ mate->selectproc = ht6560b_selectproc;
++ mate->set_pio_mode = ht6560b_set_pio_mode;
++ mate->port_init_devs = ht6560b_port_init_devs;
++ idx[1] = mate->index;
++ }
+
+ ide_device_add(idx, &ht6560b_port_info);
+
+diff --git a/drivers/ide/legacy/ide-4drives.c b/drivers/ide/legacy/ide-4drives.c
+new file mode 100644
+index 0000000..c352f12
+--- /dev/null
++++ b/drivers/ide/legacy/ide-4drives.c
+@@ -0,0 +1,56 @@
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/ide.h>
++
++int probe_4drives;
++
++module_param_named(probe, probe_4drives, bool, 0);
++MODULE_PARM_DESC(probe, "probe for generic IDE chipset with 4 drives/port");
++
++static int __init ide_4drives_init(void)
++{
++ ide_hwif_t *hwif, *mate;
++ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
++ hw_regs_t hw;
++
++ if (probe_4drives == 0)
++ return -ENODEV;
++
++ memset(&hw, 0, sizeof(hw));
++
++ ide_std_init_ports(&hw, 0x1f0, 0x3f6);
++ hw.irq = 14;
++ hw.chipset = ide_4drives;
++
++ hwif = ide_find_port();
++ if (hwif) {
++ ide_init_port_hw(hwif, &hw);
++ idx[0] = hwif->index;
++ }
++
++ mate = ide_find_port();
++ if (mate) {
++ ide_init_port_hw(mate, &hw);
++ mate->drives[0].select.all ^= 0x20;
++ mate->drives[1].select.all ^= 0x20;
++ idx[1] = mate->index;
++
++ if (hwif) {
++ hwif->mate = mate;
++ mate->mate = hwif;
++ hwif->serialized = mate->serialized = 1;
++ }
++ }
++
++ ide_device_add(idx, NULL);
++
++ return 0;
++}
++
++module_init(ide_4drives_init);
++
++MODULE_AUTHOR("Bartlomiej Zolnierkiewicz");
++MODULE_DESCRIPTION("generic IDE chipset with 4 drives/port support");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
+index 15ccf69..b97b8d5 100644
+--- a/drivers/ide/legacy/ide-cs.c
++++ b/drivers/ide/legacy/ide-cs.c
+@@ -156,15 +156,15 @@ static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq
+ hw.chipset = ide_pci;
+ hw.dev = &handle->dev;
+
+- hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++ hwif = ide_find_port();
+ if (hwif == NULL)
+ return -1;
+
+ i = hwif->index;
+
+ if (hwif->present)
+- ide_unregister(i, 0, 0);
+- else if (!hwif->hold)
++ ide_unregister(i);
++ else
+ ide_init_port_data(hwif, i);
+
+ ide_init_port_hw(hwif, &hw);
+@@ -360,7 +360,7 @@ void ide_release(struct pcmcia_device *link)
+ if (info->ndev) {
+ /* FIXME: if this fails we need to queue the cleanup somehow
+ -- need to investigate the required PCMCIA magic */
+- ide_unregister(info->hd, 0, 0);
++ ide_unregister(info->hd);
+ }
+ info->ndev = 0;
+
+diff --git a/drivers/ide/legacy/ide_platform.c b/drivers/ide/legacy/ide_platform.c
+index 688fcae..bf24077 100644
+--- a/drivers/ide/legacy/ide_platform.c
++++ b/drivers/ide/legacy/ide_platform.c
+@@ -89,7 +89,7 @@ static int __devinit plat_ide_probe(struct platform_device *pdev)
+ res_alt->start, res_alt->end - res_alt->start + 1);
+ }
+
+- hwif = ide_find_port((unsigned long)base);
++ hwif = ide_find_port();
+ if (!hwif) {
+ ret = -ENODEV;
+ goto out;
+@@ -100,11 +100,10 @@ static int __devinit plat_ide_probe(struct platform_device *pdev)
+ hw.dev = &pdev->dev;
+
+ ide_init_port_hw(hwif, &hw);
++ hwif->mmio = 1;
+
+- if (mmio) {
+- hwif->mmio = 1;
++ if (mmio)
+ default_hwif_mmiops(hwif);
+- }
+
+ idx[0] = hwif->index;
+
+@@ -122,7 +121,7 @@ static int __devexit plat_ide_remove(struct platform_device *pdev)
+ {
+ ide_hwif_t *hwif = pdev->dev.driver_data;
+
+- ide_unregister(hwif->index, 0, 0);
++ ide_unregister(hwif->index);
+
+ return 0;
+ }
+@@ -130,6 +129,7 @@ static int __devexit plat_ide_remove(struct platform_device *pdev)
+ static struct platform_driver platform_ide_driver = {
+ .driver = {
+ .name = "pata_platform",
++ .owner = THIS_MODULE,
+ },
+ .probe = plat_ide_probe,
+ .remove = __devexit_p(plat_ide_remove),
+@@ -147,6 +147,7 @@ static void __exit platform_ide_exit(void)
+
+ MODULE_DESCRIPTION("Platform IDE driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:pata_platform");
+
+ module_init(platform_ide_init);
+ module_exit(platform_ide_exit);
+diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c
+index eaf5dbe..7429b80 100644
+--- a/drivers/ide/legacy/macide.c
++++ b/drivers/ide/legacy/macide.c
+@@ -120,7 +120,7 @@ static int __init macide_init(void)
+
+ macide_setup_ports(&hw, base, irq, ack_intr);
+
+- hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++ hwif = ide_find_port();
+ if (hwif) {
+ u8 index = hwif->index;
+ u8 idx[4] = { index, 0xff, 0xff, 0xff };
+diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c
+index 2da2875..fcbff0e 100644
+--- a/drivers/ide/legacy/q40ide.c
++++ b/drivers/ide/legacy/q40ide.c
+@@ -137,7 +137,7 @@ static int __init q40ide_init(void)
+ // m68kide_iops,
+ q40ide_default_irq(pcide_bases[i]));
+
+- hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++ hwif = ide_find_port();
+ if (hwif) {
+ ide_init_port_data(hwif, hwif->index);
+ ide_init_port_hw(hwif, &hw);
+diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c
+index 2f4f47a..6e820c7 100644
+--- a/drivers/ide/legacy/qd65xx.c
++++ b/drivers/ide/legacy/qd65xx.c
+@@ -88,12 +88,12 @@
+ static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */
+
+ /*
+- * qd_select:
++ * qd65xx_select:
+ *
+- * This routine is invoked from ide.c to prepare for access to a given drive.
++ * This routine is invoked to prepare for access to a given drive.
+ */
+
+-static void qd_select (ide_drive_t *drive)
++static void qd65xx_select(ide_drive_t *drive)
+ {
+ u8 index = (( (QD_TIMREG(drive)) & 0x80 ) >> 7) |
+ (QD_TIMREG(drive) & 0x02);
+@@ -168,36 +168,15 @@ static int qd_find_disk_type (ide_drive_t *drive,
+ }
+
+ /*
+- * qd_timing_ok:
+- *
+- * check whether timings don't conflict
+- */
+-
+-static int qd_timing_ok (ide_drive_t drives[])
+-{
+- return (IDE_IMPLY(drives[0].present && drives[1].present,
+- IDE_IMPLY(QD_TIMREG(drives) == QD_TIMREG(drives+1),
+- QD_TIMING(drives) == QD_TIMING(drives+1))));
+- /* if same timing register, must be same timing */
+-}
+-
+-/*
+ * qd_set_timing:
+ *
+- * records the timing, and enables selectproc as needed
++ * records the timing
+ */
+
+ static void qd_set_timing (ide_drive_t *drive, u8 timing)
+ {
+- ide_hwif_t *hwif = HWIF(drive);
+-
+ drive->drive_data &= 0xff00;
+ drive->drive_data |= timing;
+- if (qd_timing_ok(hwif->drives)) {
+- qd_select(drive); /* selects once */
+- hwif->selectproc = NULL;
+- } else
+- hwif->selectproc = &qd_select;
+
+ printk(KERN_DEBUG "%s: %#x\n", drive->name, timing);
+ }
+@@ -225,10 +204,11 @@ static void qd6500_set_pio_mode(ide_drive_t *drive, const u8 pio)
+
+ static void qd6580_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ {
+- int base = HWIF(drive)->select_data;
++ ide_hwif_t *hwif = drive->hwif;
+ unsigned int cycle_time;
+ int active_time = 175;
+ int recovery_time = 415; /* worst case values from the dos driver */
++ u8 base = (hwif->config_data & 0xff00) >> 8;
+
+ if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)) {
+ cycle_time = ide_pio_cycle_time(drive, pio);
+@@ -299,21 +279,10 @@ static int __init qd_testreg(int port)
+ return (readreg != QD_TESTVAL);
+ }
+
+-/*
+- * qd_setup:
+- *
+- * called to setup an ata channel : adjusts attributes & links for tuning
+- */
+-
+-static void __init qd_setup(ide_hwif_t *hwif, int base, int config)
+-{
+- hwif->select_data = base;
+- hwif->config_data = config;
+-}
+-
+ static void __init qd6500_port_init_devs(ide_hwif_t *hwif)
+ {
+- u8 base = hwif->select_data, config = QD_CONFIG(hwif);
++ u8 base = (hwif->config_data & 0xff00) >> 8;
++ u8 config = QD_CONFIG(hwif);
+
+ hwif->drives[0].drive_data = QD6500_DEF_DATA;
+ hwif->drives[1].drive_data = QD6500_DEF_DATA;
+@@ -322,9 +291,10 @@ static void __init qd6500_port_init_devs(ide_hwif_t *hwif)
+ static void __init qd6580_port_init_devs(ide_hwif_t *hwif)
+ {
+ u16 t1, t2;
+- u8 base = hwif->select_data, config = QD_CONFIG(hwif);
++ u8 base = (hwif->config_data & 0xff00) >> 8;
++ u8 config = QD_CONFIG(hwif);
+
+- if (QD_CONTROL(hwif) & QD_CONTR_SEC_DISABLED) {
++ if (hwif->host_flags & IDE_HFLAG_SINGLE) {
+ t1 = QD6580_DEF_DATA;
+ t2 = QD6580_DEF_DATA2;
+ } else
+@@ -352,41 +322,62 @@ static const struct ide_port_info qd65xx_port_info __initdata = {
+ static int __init qd_probe(int base)
+ {
+ ide_hwif_t *hwif;
++ u8 config, unit;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+- u8 config;
+- u8 unit;
++ hw_regs_t hw[2];
++ struct ide_port_info d = qd65xx_port_info;
+
+ config = inb(QD_CONFIG_PORT);
+
+ if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) )
+- return 1;
++ return -ENODEV;
+
+ unit = ! (config & QD_CONFIG_IDE_BASEPORT);
+
++ if (unit)
++ d.host_flags |= IDE_HFLAG_QD_2ND_PORT;
++
++ memset(&hw, 0, sizeof(hw));
++
++ ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
++ hw[0].irq = 14;
++
++ ide_std_init_ports(&hw[1], 0x170, 0x376);
++ hw[1].irq = 15;
++
+ if ((config & 0xf0) == QD_CONFIG_QD6500) {
+
+- if (qd_testreg(base)) return 1; /* bad register */
++ if (qd_testreg(base))
++ return -ENODEV; /* bad register */
+
+ /* qd6500 found */
+
+- hwif = &ide_hwifs[unit];
+- printk(KERN_NOTICE "%s: qd6500 at %#x\n", hwif->name, base);
+- printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n",
+- config, QD_ID3);
+-
+ if (config & QD_CONFIG_DISABLED) {
+ printk(KERN_WARNING "qd6500 is disabled !\n");
+- return 1;
++ return -ENODEV;
+ }
+
+- qd_setup(hwif, base, config);
++ printk(KERN_NOTICE "qd6500 at %#x\n", base);
++ printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n",
++ config, QD_ID3);
++
++ d.host_flags |= IDE_HFLAG_SINGLE;
++
++ hwif = ide_find_port_slot(&d);
++ if (hwif == NULL)
++ return -ENOENT;
++
++ ide_init_port_hw(hwif, &hw[unit]);
++
++ hwif->config_data = (base << 8) | config;
+
+ hwif->port_init_devs = qd6500_port_init_devs;
+- hwif->set_pio_mode = &qd6500_set_pio_mode;
++ hwif->set_pio_mode = qd6500_set_pio_mode;
++ hwif->selectproc = qd65xx_select;
+
+- idx[unit] = unit;
++ idx[unit] = hwif->index;
+
+- ide_device_add(idx, &qd65xx_port_info);
++ ide_device_add(idx, &d);
+
+ return 1;
+ }
+@@ -396,8 +387,8 @@ static int __init qd_probe(int base)
+
+ u8 control;
+
+- if (qd_testreg(base) || qd_testreg(base+0x02)) return 1;
+- /* bad registers */
++ if (qd_testreg(base) || qd_testreg(base + 0x02))
++ return -ENODEV; /* bad registers */
+
+ /* qd6580 found */
+
+@@ -412,41 +403,52 @@ static int __init qd_probe(int base)
+ if (control & QD_CONTR_SEC_DISABLED) {
+ /* secondary disabled */
+
+- hwif = &ide_hwifs[unit];
+- printk(KERN_INFO "%s: qd6580: single IDE board\n",
+- hwif->name);
++ printk(KERN_INFO "qd6580: single IDE board\n");
++
++ d.host_flags |= IDE_HFLAG_SINGLE;
++
++ hwif = ide_find_port_slot(&d);
++ if (hwif == NULL)
++ return -ENOENT;
+
+- qd_setup(hwif, base, config | (control << 8));
++ ide_init_port_hw(hwif, &hw[unit]);
++
++ hwif->config_data = (base << 8) | config;
+
+ hwif->port_init_devs = qd6580_port_init_devs;
+- hwif->set_pio_mode = &qd6580_set_pio_mode;
++ hwif->set_pio_mode = qd6580_set_pio_mode;
++ hwif->selectproc = qd65xx_select;
+
+- idx[unit] = unit;
++ idx[unit] = hwif->index;
+
+- ide_device_add(idx, &qd65xx_port_info);
++ ide_device_add(idx, &d);
+
+ return 1;
+ } else {
+ ide_hwif_t *mate;
+
+- hwif = &ide_hwifs[0];
+- mate = &ide_hwifs[1];
+ /* secondary enabled */
+- printk(KERN_INFO "%s&%s: qd6580: dual IDE board\n",
+- hwif->name, mate->name);
+-
+- qd_setup(hwif, base, config | (control << 8));
+-
+- hwif->port_init_devs = qd6580_port_init_devs;
+- hwif->set_pio_mode = &qd6580_set_pio_mode;
+-
+- qd_setup(mate, base, config | (control << 8));
+-
+- mate->port_init_devs = qd6580_port_init_devs;
+- mate->set_pio_mode = &qd6580_set_pio_mode;
+-
+- idx[0] = 0;
+- idx[1] = 1;
++ printk(KERN_INFO "qd6580: dual IDE board\n");
++
++ hwif = ide_find_port();
++ if (hwif) {
++ ide_init_port_hw(hwif, &hw[0]);
++ hwif->config_data = (base << 8) | config;
++ hwif->port_init_devs = qd6580_port_init_devs;
++ hwif->set_pio_mode = qd6580_set_pio_mode;
++ hwif->selectproc = qd65xx_select;
++ idx[0] = hwif->index;
++ }
++
++ mate = ide_find_port();
++ if (mate) {
++ ide_init_port_hw(mate, &hw[1]);
++ mate->config_data = (base << 8) | config;
++ mate->port_init_devs = qd6580_port_init_devs;
++ mate->set_pio_mode = qd6580_set_pio_mode;
++ mate->selectproc = qd65xx_select;
++ idx[1] = mate->index;
++ }
+
+ ide_device_add(idx, &qd65xx_port_info);
+
+@@ -454,7 +456,7 @@ static int __init qd_probe(int base)
+ }
+ }
+ /* no qd65xx found */
+- return 1;
++ return -ENODEV;
+ }
+
+ int probe_qd65xx = 0;
+@@ -464,14 +466,18 @@ MODULE_PARM_DESC(probe, "probe for QD65xx chipsets");
+
+ static int __init qd65xx_init(void)
+ {
++ int rc1, rc2 = -ENODEV;
++
+ if (probe_qd65xx == 0)
+ return -ENODEV;
+
+- if (qd_probe(0x30))
+- qd_probe(0xb0);
+- if (ide_hwifs[0].chipset != ide_qd65xx &&
+- ide_hwifs[1].chipset != ide_qd65xx)
++ rc1 = qd_probe(0x30);
++ if (rc1)
++ rc2 = qd_probe(0xb0);
++
++ if (rc1 < 0 && rc2 < 0)
+ return -ENODEV;
++
+ return 0;
+ }
+
+diff --git a/drivers/ide/legacy/qd65xx.h b/drivers/ide/legacy/qd65xx.h
+index 28dd50a..c83dea8 100644
+--- a/drivers/ide/legacy/qd65xx.h
++++ b/drivers/ide/legacy/qd65xx.h
+@@ -30,7 +30,6 @@
+ #define QD_ID3 ((config & QD_CONFIG_ID3)!=0)
+
+ #define QD_CONFIG(hwif) ((hwif)->config_data & 0x00ff)
+-#define QD_CONTROL(hwif) (((hwif)->config_data & 0xff00) >> 8)
+
+ #define QD_TIMING(drive) (byte)(((drive)->drive_data) & 0x00ff)
+ #define QD_TIMREG(drive) (byte)((((drive)->drive_data) & 0xff00) >> 8)
+diff --git a/drivers/ide/legacy/umc8672.c b/drivers/ide/legacy/umc8672.c
+index 5696ba0..4d90bad 100644
+--- a/drivers/ide/legacy/umc8672.c
++++ b/drivers/ide/legacy/umc8672.c
+@@ -19,7 +19,7 @@
+ */
+
+ /*
+- * VLB Controller Support from
++ * VLB Controller Support from
+ * Wolfram Podien
+ * Rohoefe 3
+ * D28832 Achim
+@@ -32,7 +32,7 @@
+ * #define UMC_DRIVE0 11
+ * in the beginning of the driver, which sets the speed of drive 0 to 11 (there
+ * are some lines present). 0 - 11 are allowed speed values. These values are
+- * the results from the DOS speed test program supplied from UMC. 11 is the
++ * the results from the DOS speed test program supplied from UMC. 11 is the
+ * highest speed (about PIO mode 3)
+ */
+ #define REALLY_SLOW_IO /* some systems can safely undef this */
+@@ -60,62 +60,62 @@
+ #define UMC_DRIVE3 1 /* In case of crash reduce speed */
+
+ static u8 current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3};
+-static const u8 pio_to_umc [5] = {0,3,7,10,11}; /* rough guesses */
++static const u8 pio_to_umc [5] = {0, 3, 7, 10, 11}; /* rough guesses */
+
+ /* 0 1 2 3 4 5 6 7 8 9 10 11 */
+ static const u8 speedtab [3][12] = {
+- {0xf, 0xb, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 },
+- {0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 },
+- {0xff,0xcb,0xc0,0x58,0x36,0x33,0x23,0x22,0x21,0x11,0x10,0x0}};
++ {0x0f, 0x0b, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1},
++ {0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1},
++ {0xff, 0xcb, 0xc0, 0x58, 0x36, 0x33, 0x23, 0x22, 0x21, 0x11, 0x10, 0x0}
++};
+
+-static void out_umc (char port,char wert)
++static void out_umc(char port, char wert)
+ {
+- outb_p(port,0x108);
+- outb_p(wert,0x109);
++ outb_p(port, 0x108);
++ outb_p(wert, 0x109);
+ }
+
+-static inline u8 in_umc (char port)
++static inline u8 in_umc(char port)
+ {
+- outb_p(port,0x108);
++ outb_p(port, 0x108);
+ return inb_p(0x109);
+ }
+
+-static void umc_set_speeds (u8 speeds[])
++static void umc_set_speeds(u8 speeds[])
+ {
+ int i, tmp;
+
+- outb_p(0x5A,0x108); /* enable umc */
++ outb_p(0x5A, 0x108); /* enable umc */
+
+- out_umc (0xd7,(speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4)));
+- out_umc (0xd6,(speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4)));
++ out_umc(0xd7, (speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4)));
++ out_umc(0xd6, (speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4)));
+ tmp = 0;
+- for (i = 3; i >= 0; i--) {
++ for (i = 3; i >= 0; i--)
+ tmp = (tmp << 2) | speedtab[1][speeds[i]];
++ out_umc(0xdc, tmp);
++ for (i = 0; i < 4; i++) {
++ out_umc(0xd0 + i, speedtab[2][speeds[i]]);
++ out_umc(0xd8 + i, speedtab[2][speeds[i]]);
+ }
+- out_umc (0xdc,tmp);
+- for (i = 0;i < 4; i++) {
+- out_umc (0xd0+i,speedtab[2][speeds[i]]);
+- out_umc (0xd8+i,speedtab[2][speeds[i]]);
+- }
+- outb_p(0xa5,0x108); /* disable umc */
++ outb_p(0xa5, 0x108); /* disable umc */
+
+- printk ("umc8672: drive speeds [0 to 11]: %d %d %d %d\n",
++ printk("umc8672: drive speeds [0 to 11]: %d %d %d %d\n",
+ speeds[0], speeds[1], speeds[2], speeds[3]);
+ }
+
+ static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ {
++ ide_hwif_t *hwif = drive->hwif;
+ unsigned long flags;
+- ide_hwgroup_t *hwgroup = ide_hwifs[HWIF(drive)->index^1].hwgroup;
+
+ printk("%s: setting umc8672 to PIO mode%d (speed %d)\n",
+ drive->name, pio, pio_to_umc[pio]);
+ spin_lock_irqsave(&ide_lock, flags);
+- if (hwgroup && hwgroup->handler != NULL) {
++ if (hwif->mate && hwif->mate->hwgroup->handler) {
+ printk(KERN_ERR "umc8672: other interface is busy: exiting tune_umc()\n");
+ } else {
+ current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio];
+- umc_set_speeds (current_speeds);
++ umc_set_speeds(current_speeds);
+ }
+ spin_unlock_irqrestore(&ide_lock, flags);
+ }
+@@ -128,35 +128,56 @@ static const struct ide_port_info umc8672_port_info __initdata = {
+
+ static int __init umc8672_probe(void)
+ {
++ ide_hwif_t *hwif, *mate;
+ unsigned long flags;
+- static u8 idx[4] = { 0, 1, 0xff, 0xff };
++ static u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
++ hw_regs_t hw[2];
+
+ if (!request_region(0x108, 2, "umc8672")) {
+ printk(KERN_ERR "umc8672: ports 0x108-0x109 already in use.\n");
+ return 1;
+ }
+ local_irq_save(flags);
+- outb_p(0x5A,0x108); /* enable umc */
++ outb_p(0x5A, 0x108); /* enable umc */
+ if (in_umc (0xd5) != 0xa0) {
+ local_irq_restore(flags);
+ printk(KERN_ERR "umc8672: not found\n");
+ release_region(0x108, 2);
+- return 1;
++ return 1;
+ }
+- outb_p(0xa5,0x108); /* disable umc */
++ outb_p(0xa5, 0x108); /* disable umc */
+
+- umc_set_speeds (current_speeds);
++ umc_set_speeds(current_speeds);
+ local_irq_restore(flags);
+
+- ide_hwifs[0].set_pio_mode = &umc_set_pio_mode;
+- ide_hwifs[1].set_pio_mode = &umc_set_pio_mode;
++ memset(&hw, 0, sizeof(hw));
++
++ ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
++ hw[0].irq = 14;
++
++ ide_std_init_ports(&hw[1], 0x170, 0x376);
++ hw[1].irq = 15;
++
++ hwif = ide_find_port();
++ if (hwif) {
++ ide_init_port_hw(hwif, &hw[0]);
++ hwif->set_pio_mode = umc_set_pio_mode;
++ idx[0] = hwif->index;
++ }
++
++ mate = ide_find_port();
++ if (mate) {
++ ide_init_port_hw(mate, &hw[1]);
++ mate->set_pio_mode = umc_set_pio_mode;
++ idx[1] = mate->index;
++ }
+
+ ide_device_add(idx, &umc8672_port_info);
+
+ return 0;
+ }
+
+-int probe_umc8672 = 0;
++int probe_umc8672;
+
+ module_param_named(probe, probe_umc8672, bool, 0);
+ MODULE_PARM_DESC(probe, "probe for UMC8672 chipset");
+diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
+index 85c016b..a8cd003 100644
+--- a/drivers/ide/mips/au1xxx-ide.c
++++ b/drivers/ide/mips/au1xxx-ide.c
+@@ -599,9 +599,11 @@ static int au_ide_probe(struct device *dev)
+ goto out;
+ }
+
+- /* FIXME: This might possibly break PCMCIA IDE devices */
+-
+- hwif = &ide_hwifs[pdev->id];
++ hwif = ide_find_port();
++ if (hwif == NULL) {
++ ret = -ENOENT;
++ goto out;
++ }
+
+ memset(&hw, 0, sizeof(hw));
+ auide_setup_ports(&hw, ahwif);
+@@ -613,9 +615,6 @@ static int au_ide_probe(struct device *dev)
+
+ hwif->dev = dev;
+
+- /* hold should be on in all cases */
+- hwif->hold = 1;
+-
+ hwif->mmio = 1;
+
+ /* If the user has selected DDMA assisted copies,
+@@ -673,7 +672,7 @@ static int au_ide_remove(struct device *dev)
+ ide_hwif_t *hwif = dev_get_drvdata(dev);
+ _auide_hwif *ahwif = &auide_hwif;
+
+- ide_unregister(hwif->index, 0, 0);
++ ide_unregister(hwif->index);
+
+ iounmap((void *)ahwif->regbase);
+
+diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c
+index 956259f..bbe8d58 100644
+--- a/drivers/ide/mips/swarm.c
++++ b/drivers/ide/mips/swarm.c
+@@ -76,17 +76,12 @@ static int __devinit swarm_ide_probe(struct device *dev)
+ if (!SIBYTE_HAVE_IDE)
+ return -ENODEV;
+
+- /* Find an empty slot. */
+- for (i = 0; i < MAX_HWIFS; i++)
+- if (!ide_hwifs[i].io_ports[IDE_DATA_OFFSET])
+- break;
+- if (i >= MAX_HWIFS) {
++ hwif = ide_find_port();
++ if (hwif == NULL) {
+ printk(KERN_ERR DRV_NAME ": no free slot for interface\n");
+ return -ENOMEM;
+ }
+
+- hwif = ide_hwifs + i;
+-
+ base = ioremap(A_IO_EXT_BASE, 0x800);
+ offset = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_START_ADDR, IDE_CS));
+ size = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_MULT_SIZE, IDE_CS));
+diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
+index cfb3265..c9ba15a 100644
+--- a/drivers/ide/pci/aec62xx.c
++++ b/drivers/ide/pci/aec62xx.c
+@@ -220,7 +220,8 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
+ .init_hwif = init_hwif_aec62xx,
+ .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
+ .host_flags = IDE_HFLAG_NO_ATAPI_DMA |
+- IDE_HFLAG_ABUSE_SET_DMA_MODE,
++ IDE_HFLAG_ABUSE_SET_DMA_MODE |
++ IDE_HFLAG_NON_BOOTABLE,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA4,
+diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
+index b3b6f51..3fa2d9f 100644
+--- a/drivers/ide/pci/alim15x3.c
++++ b/drivers/ide/pci/alim15x3.c
+@@ -750,7 +750,6 @@ static const struct ide_port_info ali15x3_chipset __devinitdata = {
+ .init_chipset = init_chipset_ali15x3,
+ .init_hwif = init_hwif_ali15x3,
+ .init_dma = init_dma_ali15x3,
+- .host_flags = IDE_HFLAG_BOOTABLE,
+ .pio_mask = ATA_PIO5,
+ .swdma_mask = ATA_SWDMA2,
+ .mwdma_mask = ATA_MWDMA2,
+diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
+index 2ef890c..ff684d3 100644
+--- a/drivers/ide/pci/amd74xx.c
++++ b/drivers/ide/pci/amd74xx.c
+@@ -219,12 +219,10 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
+
+ #define IDE_HFLAGS_AMD \
+ (IDE_HFLAG_PIO_NO_BLACKLIST | \
+- IDE_HFLAG_PIO_NO_DOWNGRADE | \
+ IDE_HFLAG_ABUSE_SET_DMA_MODE | \
+ IDE_HFLAG_POST_SET_MODE | \
+ IDE_HFLAG_IO_32BIT | \
+- IDE_HFLAG_UNMASK_IRQS | \
+- IDE_HFLAG_BOOTABLE)
++ IDE_HFLAG_UNMASK_IRQS)
+
+ #define DECLARE_AMD_DEV(name_str, swdma, udma) \
+ { \
+diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
+index 7e037c8..91722f8 100644
+--- a/drivers/ide/pci/atiixp.c
++++ b/drivers/ide/pci/atiixp.c
+@@ -151,7 +151,7 @@ static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
+ .name = "ATIIXP",
+ .init_hwif = init_hwif_atiixp,
+ .enablebits = {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
+- .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
++ .host_flags = IDE_HFLAG_LEGACY_IRQS,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
+@@ -159,8 +159,7 @@ static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
+ .name = "SB600_PATA",
+ .init_hwif = init_hwif_atiixp,
+ .enablebits = {{0x48,0x01,0x00}, {0x00,0x00,0x00}},
+- .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_LEGACY_IRQS |
+- IDE_HFLAG_BOOTABLE,
++ .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_LEGACY_IRQS,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
+diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c
+index 29fbc5e..b076dbf 100644
+--- a/drivers/ide/pci/cmd640.c
++++ b/drivers/ide/pci/cmd640.c
+@@ -4,7 +4,7 @@
+
+ /*
+ * Original authors: abramov at cecmow.enet.dec.com (Igor Abramov)
+- * mlord at pobox.com (Mark Lord)
++ * mlord at pobox.com (Mark Lord)
+ *
+ * See linux/MAINTAINERS for address of current maintainer.
+ *
+@@ -98,7 +98,7 @@
+
+ #define CMD640_PREFETCH_MASKS 1
+
+-//#define CMD640_DUMP_REGS
++/*#define CMD640_DUMP_REGS */
+
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+@@ -112,7 +112,7 @@
+ /*
+ * This flag is set in ide.c by the parameter: ide0=cmd640_vlb
+ */
+-int cmd640_vlb = 0;
++int cmd640_vlb;
+
+ /*
+ * CMD640 specific registers definition.
+@@ -185,7 +185,6 @@ static DEFINE_SPINLOCK(cmd640_lock);
+ * These are initialized to point at the devices we control
+ */
+ static ide_hwif_t *cmd_hwif0, *cmd_hwif1;
+-static ide_drive_t *cmd_drives[4];
+
+ /*
+ * Interface to access cmd640x registers
+@@ -207,13 +206,13 @@ static unsigned int cmd640_chip_version;
+
+ /* PCI method 1 access */
+
+-static void put_cmd640_reg_pci1 (u16 reg, u8 val)
++static void put_cmd640_reg_pci1(u16 reg, u8 val)
+ {
+ outl_p((reg & 0xfc) | cmd640_key, 0xcf8);
+ outb_p(val, (reg & 3) | 0xcfc);
+ }
+
+-static u8 get_cmd640_reg_pci1 (u16 reg)
++static u8 get_cmd640_reg_pci1(u16 reg)
+ {
+ outl_p((reg & 0xfc) | cmd640_key, 0xcf8);
+ return inb_p((reg & 3) | 0xcfc);
+@@ -221,14 +220,14 @@ static u8 get_cmd640_reg_pci1 (u16 reg)
+
+ /* PCI method 2 access (from CMD datasheet) */
+
+-static void put_cmd640_reg_pci2 (u16 reg, u8 val)
++static void put_cmd640_reg_pci2(u16 reg, u8 val)
+ {
+ outb_p(0x10, 0xcf8);
+ outb_p(val, cmd640_key + reg);
+ outb_p(0, 0xcf8);
+ }
+
+-static u8 get_cmd640_reg_pci2 (u16 reg)
++static u8 get_cmd640_reg_pci2(u16 reg)
+ {
+ u8 b;
+
+@@ -240,13 +239,13 @@ static u8 get_cmd640_reg_pci2 (u16 reg)
+
+ /* VLB access */
+
+-static void put_cmd640_reg_vlb (u16 reg, u8 val)
++static void put_cmd640_reg_vlb(u16 reg, u8 val)
+ {
+ outb_p(reg, cmd640_key);
+ outb_p(val, cmd640_key + 4);
+ }
+
+-static u8 get_cmd640_reg_vlb (u16 reg)
++static u8 get_cmd640_reg_vlb(u16 reg)
+ {
+ outb_p(reg, cmd640_key);
+ return inb_p(cmd640_key + 4);
+@@ -268,11 +267,11 @@ static void put_cmd640_reg(u16 reg, u8 val)
+ unsigned long flags;
+
+ spin_lock_irqsave(&cmd640_lock, flags);
+- __put_cmd640_reg(reg,val);
++ __put_cmd640_reg(reg, val);
+ spin_unlock_irqrestore(&cmd640_lock, flags);
+ }
+
+-static int __init match_pci_cmd640_device (void)
++static int __init match_pci_cmd640_device(void)
+ {
+ const u8 ven_dev[4] = {0x95, 0x10, 0x40, 0x06};
+ unsigned int i;
+@@ -292,7 +291,7 @@ static int __init match_pci_cmd640_device (void)
+ /*
+ * Probe for CMD640x -- pci method 1
+ */
+-static int __init probe_for_cmd640_pci1 (void)
++static int __init probe_for_cmd640_pci1(void)
+ {
+ __get_cmd640_reg = get_cmd640_reg_pci1;
+ __put_cmd640_reg = put_cmd640_reg_pci1;
+@@ -308,7 +307,7 @@ static int __init probe_for_cmd640_pci1 (void)
+ /*
+ * Probe for CMD640x -- pci method 2
+ */
+-static int __init probe_for_cmd640_pci2 (void)
++static int __init probe_for_cmd640_pci2(void)
+ {
+ __get_cmd640_reg = get_cmd640_reg_pci2;
+ __put_cmd640_reg = put_cmd640_reg_pci2;
+@@ -322,7 +321,7 @@ static int __init probe_for_cmd640_pci2 (void)
+ /*
+ * Probe for CMD640x -- vlb
+ */
+-static int __init probe_for_cmd640_vlb (void)
++static int __init probe_for_cmd640_vlb(void)
+ {
+ u8 b;
+
+@@ -343,7 +342,7 @@ static int __init probe_for_cmd640_vlb (void)
+ * Returns 1 if an IDE interface/drive exists at 0x170,
+ * Returns 0 otherwise.
+ */
+-static int __init secondary_port_responding (void)
++static int __init secondary_port_responding(void)
+ {
+ unsigned long flags;
+
+@@ -367,7 +366,7 @@ static int __init secondary_port_responding (void)
+ /*
+ * Dump out all cmd640 registers. May be called from ide.c
+ */
+-static void cmd640_dump_regs (void)
++static void cmd640_dump_regs(void)
+ {
+ unsigned int reg = cmd640_vlb ? 0x50 : 0x00;
+
+@@ -386,9 +385,8 @@ static void cmd640_dump_regs (void)
+ * Check whether prefetch is on for a drive,
+ * and initialize the unmask flags for safe operation.
+ */
+-static void __init check_prefetch (unsigned int index)
++static void __init check_prefetch(ide_drive_t *drive, unsigned int index)
+ {
+- ide_drive_t *drive = cmd_drives[index];
+ u8 b = get_cmd640_reg(prefetch_regs[index]);
+
+ if (b & prefetch_masks[index]) { /* is prefetch off? */
+@@ -404,38 +402,13 @@ static void __init check_prefetch (unsigned int index)
+ }
+ }
+
+-/*
+- * Figure out which devices we control
+- */
+-static void __init setup_device_ptrs (void)
+-{
+- unsigned int i;
+-
+- cmd_hwif0 = &ide_hwifs[0]; /* default, if not found below */
+- cmd_hwif1 = &ide_hwifs[1]; /* default, if not found below */
+- for (i = 0; i < MAX_HWIFS; i++) {
+- ide_hwif_t *hwif = &ide_hwifs[i];
+- if (hwif->chipset == ide_unknown || hwif->chipset == ide_forced) {
+- if (hwif->io_ports[IDE_DATA_OFFSET] == 0x1f0)
+- cmd_hwif0 = hwif;
+- else if (hwif->io_ports[IDE_DATA_OFFSET] == 0x170)
+- cmd_hwif1 = hwif;
+- }
+- }
+- cmd_drives[0] = &cmd_hwif0->drives[0];
+- cmd_drives[1] = &cmd_hwif0->drives[1];
+- cmd_drives[2] = &cmd_hwif1->drives[0];
+- cmd_drives[3] = &cmd_hwif1->drives[1];
+-}
+-
+ #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
+
+ /*
+ * Sets prefetch mode for a drive.
+ */
+-static void set_prefetch_mode (unsigned int index, int mode)
++static void set_prefetch_mode(ide_drive_t *drive, unsigned int index, int mode)
+ {
+- ide_drive_t *drive = cmd_drives[index];
+ unsigned long flags;
+ int reg = prefetch_regs[index];
+ u8 b;
+@@ -462,7 +435,7 @@ static void set_prefetch_mode (unsigned int index, int mode)
+ /*
+ * Dump out current drive clocks settings
+ */
+-static void display_clocks (unsigned int index)
++static void display_clocks(unsigned int index)
+ {
+ u8 active_count, recovery_count;
+
+@@ -481,7 +454,7 @@ static void display_clocks (unsigned int index)
+ * Pack active and recovery counts into single byte representation
+ * used by controller
+ */
+-static inline u8 pack_nibbles (u8 upper, u8 lower)
++static inline u8 pack_nibbles(u8 upper, u8 lower)
+ {
+ return ((upper & 0x0f) << 4) | (lower & 0x0f);
+ }
+@@ -489,7 +462,7 @@ static inline u8 pack_nibbles (u8 upper, u8 lower)
+ /*
+ * This routine retrieves the initial drive timings from the chipset.
+ */
+-static void __init retrieve_drive_counts (unsigned int index)
++static void __init retrieve_drive_counts(unsigned int index)
+ {
+ u8 b;
+
+@@ -498,10 +471,10 @@ static void __init retrieve_drive_counts (unsigned int index)
+ */
+ b = get_cmd640_reg(arttim_regs[index]) & ~0x3f;
+ switch (b) {
+- case 0x00: b = 4; break;
+- case 0x80: b = 3; break;
+- case 0x40: b = 2; break;
+- default: b = 5; break;
++ case 0x00: b = 4; break;
++ case 0x80: b = 3; break;
++ case 0x40: b = 2; break;
++ default: b = 5; break;
+ }
+ setup_counts[index] = b;
+
+@@ -518,7 +491,7 @@ static void __init retrieve_drive_counts (unsigned int index)
+ * This routine writes the prepared setup/active/recovery counts
+ * for a drive into the cmd640 chipset registers to active them.
+ */
+-static void program_drive_counts (unsigned int index)
++static void program_drive_counts(ide_drive_t *drive, unsigned int index)
+ {
+ unsigned long flags;
+ u8 setup_count = setup_counts[index];
+@@ -532,8 +505,11 @@ static void program_drive_counts (unsigned int index)
+ * so we merge the timings, using the slowest value for each timing.
+ */
+ if (index > 1) {
+- unsigned int mate;
+- if (cmd_drives[mate = index ^ 1]->present) {
++ ide_hwif_t *hwif = drive->hwif;
++ ide_drive_t *peer = &hwif->drives[!drive->select.b.unit];
++ unsigned int mate = index ^ 1;
++
++ if (peer->present) {
+ if (setup_count < setup_counts[mate])
+ setup_count = setup_counts[mate];
+ if (active_count < active_counts[mate])
+@@ -547,11 +523,11 @@ static void program_drive_counts (unsigned int index)
+ * Convert setup_count to internal chipset representation
+ */
+ switch (setup_count) {
+- case 4: setup_count = 0x00; break;
+- case 3: setup_count = 0x80; break;
+- case 1:
+- case 2: setup_count = 0x40; break;
+- default: setup_count = 0xc0; /* case 5 */
++ case 4: setup_count = 0x00; break;
++ case 3: setup_count = 0x80; break;
++ case 1:
++ case 2: setup_count = 0x40; break;
++ default: setup_count = 0xc0; /* case 5 */
+ }
+
+ /*
+@@ -572,7 +548,8 @@ static void program_drive_counts (unsigned int index)
+ /*
+ * Set a specific pio_mode for a drive
+ */
+-static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle_time)
++static void cmd640_set_mode(ide_drive_t *drive, unsigned int index,
++ u8 pio_mode, unsigned int cycle_time)
+ {
+ int setup_time, active_time, recovery_time, clock_time;
+ u8 setup_count, active_count, recovery_count, recovery_count2, cycle_count;
+@@ -584,15 +561,15 @@ static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle
+ active_time = ide_pio_timings[pio_mode].active_time;
+ recovery_time = cycle_time - (setup_time + active_time);
+ clock_time = 1000 / bus_speed;
+- cycle_count = (cycle_time + clock_time - 1) / clock_time;
++ cycle_count = DIV_ROUND_UP(cycle_time, clock_time);
+
+- setup_count = (setup_time + clock_time - 1) / clock_time;
++ setup_count = DIV_ROUND_UP(setup_time, clock_time);
+
+- active_count = (active_time + clock_time - 1) / clock_time;
++ active_count = DIV_ROUND_UP(active_time, clock_time);
+ if (active_count < 2)
+ active_count = 2; /* minimum allowed by cmd640 */
+
+- recovery_count = (recovery_time + clock_time - 1) / clock_time;
++ recovery_count = DIV_ROUND_UP(recovery_time, clock_time);
+ recovery_count2 = cycle_count - (setup_count + active_count);
+ if (recovery_count2 > recovery_count)
+ recovery_count = recovery_count2;
+@@ -621,7 +598,7 @@ static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle
+ * 1) this is the wrong place to do it (proper is do_special() in ide.c)
+ * 2) in practice this is rarely, if ever, necessary
+ */
+- program_drive_counts (index);
++ program_drive_counts(drive, index);
+ }
+
+ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
+@@ -629,32 +606,26 @@ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ unsigned int index = 0, cycle_time;
+ u8 b;
+
+- while (drive != cmd_drives[index]) {
+- if (++index > 3) {
+- printk(KERN_ERR "%s: bad news in %s\n",
+- drive->name, __FUNCTION__);
+- return;
+- }
+- }
+ switch (pio) {
+- case 6: /* set fast-devsel off */
+- case 7: /* set fast-devsel on */
+- b = get_cmd640_reg(CNTRL) & ~0x27;
+- if (pio & 1)
+- b |= 0x27;
+- put_cmd640_reg(CNTRL, b);
+- printk("%s: %sabled cmd640 fast host timing (devsel)\n", drive->name, (pio & 1) ? "en" : "dis");
+- return;
+-
+- case 8: /* set prefetch off */
+- case 9: /* set prefetch on */
+- set_prefetch_mode(index, pio & 1);
+- printk("%s: %sabled cmd640 prefetch\n", drive->name, (pio & 1) ? "en" : "dis");
+- return;
++ case 6: /* set fast-devsel off */
++ case 7: /* set fast-devsel on */
++ b = get_cmd640_reg(CNTRL) & ~0x27;
++ if (pio & 1)
++ b |= 0x27;
++ put_cmd640_reg(CNTRL, b);
++ printk("%s: %sabled cmd640 fast host timing (devsel)\n",
++ drive->name, (pio & 1) ? "en" : "dis");
++ return;
++ case 8: /* set prefetch off */
++ case 9: /* set prefetch on */
++ set_prefetch_mode(drive, index, pio & 1);
++ printk("%s: %sabled cmd640 prefetch\n",
++ drive->name, (pio & 1) ? "en" : "dis");
++ return;
+ }
+
+ cycle_time = ide_pio_cycle_time(drive, pio);
+- cmd640_set_mode(index, pio, cycle_time);
++ cmd640_set_mode(drive, index, pio, cycle_time);
+
+ printk("%s: selected cmd640 PIO mode%d (%dns)",
+ drive->name, pio, cycle_time);
+@@ -724,6 +695,7 @@ static int __init cmd640x_init(void)
+ unsigned int index;
+ u8 b, cfr;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
++ hw_regs_t hw[2];
+
+ if (cmd640_vlb && probe_for_cmd640_vlb()) {
+ bus_type = "VLB";
+@@ -758,21 +730,34 @@ static int __init cmd640x_init(void)
+ cfr = get_cmd640_reg(CFR);
+ cmd640_chip_version = cfr & CFR_DEVREV;
+ if (cmd640_chip_version == 0) {
+- printk ("ide: bad cmd640 revision: %d\n", cmd640_chip_version);
++ printk("ide: bad cmd640 revision: %d\n", cmd640_chip_version);
+ return 0;
+ }
+
++ memset(&hw, 0, sizeof(hw));
++
++ ide_std_init_ports(&hw[0], 0x1f0, 0x3f6);
++ hw[0].irq = 14;
++
++ ide_std_init_ports(&hw[1], 0x170, 0x376);
++ hw[1].irq = 15;
++
++ printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x"
++ "\n", 'a' + cmd640_chip_version - 1, bus_type, cfr);
++
++ cmd_hwif0 = ide_find_port();
++
+ /*
+ * Initialize data for primary port
+ */
+- setup_device_ptrs ();
+- printk("%s: buggy cmd640%c interface on %s, config=0x%02x\n",
+- cmd_hwif0->name, 'a' + cmd640_chip_version - 1, bus_type, cfr);
++ if (cmd_hwif0) {
++ ide_init_port_hw(cmd_hwif0, &hw[0]);
+ #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
+- cmd_hwif0->set_pio_mode = &cmd640_set_pio_mode;
++ cmd_hwif0->set_pio_mode = &cmd640_set_pio_mode;
+ #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
+
+- idx[0] = cmd_hwif0->index;
++ idx[0] = cmd_hwif0->index;
++ }
+
+ /*
+ * Ensure compatibility by always using the slowest timings
+@@ -784,11 +769,13 @@ static int __init cmd640x_init(void)
+ put_cmd640_reg(CMDTIM, 0);
+ put_cmd640_reg(BRST, 0x40);
+
++ cmd_hwif1 = ide_find_port();
++
+ /*
+ * Try to enable the secondary interface, if not already enabled
+ */
+- if (cmd_hwif1->noprobe ||
+- (cmd_hwif1->drives[0].noprobe && cmd_hwif1->drives[1].noprobe)) {
++ if (cmd_hwif1 &&
++ cmd_hwif1->drives[0].noprobe && cmd_hwif1->drives[1].noprobe) {
+ port2 = "not probed";
+ } else {
+ b = get_cmd640_reg(CNTRL);
+@@ -819,14 +806,15 @@ static int __init cmd640x_init(void)
+ /*
+ * Initialize data for secondary cmd640 port, if enabled
+ */
+- if (second_port_cmd640) {
++ if (second_port_cmd640 && cmd_hwif1) {
++ ide_init_port_hw(cmd_hwif1, &hw[1]);
+ #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
+ cmd_hwif1->set_pio_mode = &cmd640_set_pio_mode;
+ #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
+
+ idx[1] = cmd_hwif1->index;
+ }
+- printk(KERN_INFO "%s: %sserialized, secondary interface %s\n", cmd_hwif1->name,
++ printk(KERN_INFO "cmd640: %sserialized, secondary interface %s\n",
+ second_port_cmd640 ? "" : "not ", port2);
+
+ /*
+@@ -834,18 +822,30 @@ static int __init cmd640x_init(void)
+ * Do not unnecessarily disturb any prior BIOS setup of these.
+ */
+ for (index = 0; index < (2 + (second_port_cmd640 << 1)); index++) {
+- ide_drive_t *drive = cmd_drives[index];
++ ide_drive_t *drive;
++
++ if (index > 1) {
++ if (cmd_hwif1 == NULL)
++ continue;
++ drive = &cmd_hwif1->drives[index & 1];
++ } else {
++ if (cmd_hwif0 == NULL)
++ continue;
++ drive = &cmd_hwif0->drives[index & 1];
++ }
++
+ #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
+ if (drive->autotune || ((index > 1) && second_port_toggled)) {
+- /*
+- * Reset timing to the slowest speed and turn off prefetch.
+- * This way, the drive identify code has a better chance.
++ /*
++ * Reset timing to the slowest speed and turn off
++ * prefetch. This way, the drive identify code has
++ * a better chance.
+ */
+ setup_counts [index] = 4; /* max possible */
+ active_counts [index] = 16; /* max possible */
+ recovery_counts [index] = 16; /* max possible */
+- program_drive_counts (index);
+- set_prefetch_mode (index, 0);
++ program_drive_counts(drive, index);
++ set_prefetch_mode(drive, index, 0);
+ printk("cmd640: drive%d timings/prefetch cleared\n", index);
+ } else {
+ /*
+@@ -853,7 +853,7 @@ static int __init cmd640x_init(void)
+ * This preserves any prior BIOS setup.
+ */
+ retrieve_drive_counts (index);
+- check_prefetch (index);
++ check_prefetch(drive, index);
+ printk("cmd640: drive%d timings/prefetch(%s) preserved",
+ index, drive->no_io_32bit ? "off" : "on");
+ display_clocks(index);
+@@ -862,7 +862,7 @@ static int __init cmd640x_init(void)
+ /*
+ * Set the drive unmask flags to match the prefetch setting
+ */
+- check_prefetch (index);
++ check_prefetch(drive, index);
+ printk("cmd640: drive%d timings/prefetch(%s) preserved\n",
+ index, drive->no_io_32bit ? "off" : "on");
+ #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
+diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
+index edabe62..8baccfe 100644
+--- a/drivers/ide/pci/cmd64x.c
++++ b/drivers/ide/pci/cmd64x.c
+@@ -440,8 +440,7 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
+ .init_hwif = init_hwif_cmd64x,
+ .enablebits = {{0x00,0x00,0x00}, {0x51,0x08,0x08}},
+ .host_flags = IDE_HFLAG_CLEAR_SIMPLEX |
+- IDE_HFLAG_ABUSE_PREFETCH |
+- IDE_HFLAG_BOOTABLE,
++ IDE_HFLAG_ABUSE_PREFETCH,
+ .pio_mask = ATA_PIO5,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = 0x00, /* no udma */
+@@ -451,7 +450,7 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
+ .init_hwif = init_hwif_cmd64x,
+ .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
+ .chipset = ide_cmd646,
+- .host_flags = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE,
++ .host_flags = IDE_HFLAG_ABUSE_PREFETCH,
+ .pio_mask = ATA_PIO5,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA2,
+@@ -460,7 +459,7 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
+ .init_chipset = init_chipset_cmd64x,
+ .init_hwif = init_hwif_cmd64x,
+ .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
+- .host_flags = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE,
++ .host_flags = IDE_HFLAG_ABUSE_PREFETCH,
+ .pio_mask = ATA_PIO5,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA4,
+@@ -469,7 +468,7 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
+ .init_chipset = init_chipset_cmd64x,
+ .init_hwif = init_hwif_cmd64x,
+ .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
+- .host_flags = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE,
++ .host_flags = IDE_HFLAG_ABUSE_PREFETCH,
+ .pio_mask = ATA_PIO5,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
+diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
+index 1c163e4..01b37ec 100644
+--- a/drivers/ide/pci/cs5520.c
++++ b/drivers/ide/pci/cs5520.c
+@@ -122,8 +122,7 @@ static void __devinit init_hwif_cs5520(ide_hwif_t *hwif)
+ IDE_HFLAG_CS5520 | \
+ IDE_HFLAG_VDMA | \
+ IDE_HFLAG_NO_ATAPI_DMA | \
+- IDE_HFLAG_ABUSE_SET_DMA_MODE |\
+- IDE_HFLAG_BOOTABLE, \
++ IDE_HFLAG_ABUSE_SET_DMA_MODE, \
+ .pio_mask = ATA_PIO4, \
+ }
+
+diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
+index 941a134..56a369c 100644
+--- a/drivers/ide/pci/cs5530.c
++++ b/drivers/ide/pci/cs5530.c
+@@ -249,8 +249,7 @@ static const struct ide_port_info cs5530_chipset __devinitdata = {
+ .init_chipset = init_chipset_cs5530,
+ .init_hwif = init_hwif_cs5530,
+ .host_flags = IDE_HFLAG_SERIALIZE |
+- IDE_HFLAG_POST_SET_MODE |
+- IDE_HFLAG_BOOTABLE,
++ IDE_HFLAG_POST_SET_MODE,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA2,
+diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c
+index d7b5ea9..c9685f2 100644
+--- a/drivers/ide/pci/cs5535.c
++++ b/drivers/ide/pci/cs5535.c
+@@ -186,7 +186,7 @@ static const struct ide_port_info cs5535_chipset __devinitdata = {
+ .name = "CS5535",
+ .init_hwif = init_hwif_cs5535,
+ .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE |
+- IDE_HFLAG_ABUSE_SET_DMA_MODE | IDE_HFLAG_BOOTABLE,
++ IDE_HFLAG_ABUSE_SET_DMA_MODE,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA4,
+diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c
+index 724cbac..08eab7e 100644
+--- a/drivers/ide/pci/cy82c693.c
++++ b/drivers/ide/pci/cy82c693.c
+@@ -6,7 +6,7 @@
+ *
+ * The CY82C693 chipset is used on Digital's PC-Alpha 164SX boards.
+ * Writing the driver was quite simple, since most of the job is
+- * done by the generic pci-ide support.
++ * done by the generic pci-ide support.
+ * The hard part was finding the CY82C693's datasheet on Cypress's
+ * web page :-(. But Altavista solved this problem :-).
+ *
+@@ -15,12 +15,12 @@
+ * - I recently got a 16.8G IBM DTTA, so I was able to test it with
+ * a large and fast disk - the results look great, so I'd say the
+ * driver is working fine :-)
+- * hdparm -t reports 8.17 MB/sec at about 6% CPU usage for the DTTA
+- * - this is my first linux driver, so there's probably a lot of room
++ * hdparm -t reports 8.17 MB/sec at about 6% CPU usage for the DTTA
++ * - this is my first linux driver, so there's probably a lot of room
+ * for optimizations and bug fixing, so feel free to do it.
+ * - use idebus=xx parameter to set PCI bus speed - needed to calc
+ * timings for PIO modes (default will be 40)
+- * - if using PIO mode it's a good idea to set the PIO mode and
++ * - if using PIO mode it's a good idea to set the PIO mode and
+ * 32-bit I/O support (if possible), e.g. hdparm -p2 -c1 /dev/hda
+ * - I had some problems with my IBM DHEA with PIO modes < 2
+ * (lost interrupts) ?????
+@@ -110,11 +110,11 @@ typedef struct pio_clocks_s {
+ * calc clocks using bus_speed
+ * returns (rounded up) time in bus clocks for time in ns
+ */
+-static int calc_clk (int time, int bus_speed)
++static int calc_clk(int time, int bus_speed)
+ {
+ int clocks;
+
+- clocks = (time*bus_speed+999)/1000 -1;
++ clocks = (time*bus_speed+999)/1000 - 1;
+
+ if (clocks < 0)
+ clocks = 0;
+@@ -132,8 +132,8 @@ static int calc_clk (int time, int bus_speed)
+ * NOTE: for mode 0,1 and 2 drives 8-bit IDE command control registers are used
+ * for mode 3 and 4 drives 8 and 16-bit timings are the same
+ *
+- */
+-static void compute_clocks (u8 pio, pio_clocks_t *p_pclk)
++ */
++static void compute_clocks(u8 pio, pio_clocks_t *p_pclk)
+ {
+ int clk1, clk2;
+ int bus_speed = system_bus_clock(); /* get speed of PCI bus */
+@@ -158,7 +158,7 @@ static void compute_clocks (u8 pio, pio_clocks_t *p_pclk)
+ clk1 = (clk1<<4)|clk2; /* combine active and recovery clocks */
+
+ /* note: we use the same values for 16bit IOR and IOW
+- * those are all the same, since I don't have other
++ * those are all the same, since I don't have other
+ * timings than those from ide-lib.c
+ */
+
+@@ -186,7 +186,7 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
+ outb(index, CY82_INDEX_PORT);
+ data = inb(CY82_DATA_PORT);
+
+- printk (KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n",
++ printk(KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n",
+ drive->name, HWIF(drive)->channel, drive->select.b.unit,
+ (data&0x3), ((data>>2)&1));
+ #endif /* CY82C693_DEBUG_LOGS */
+@@ -202,7 +202,7 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
+ mode & 3, single);
+ #endif /* CY82C693_DEBUG_INFO */
+
+- /*
++ /*
+ * note: below we set the value for Bus Master IDE TimeOut Register
+ * I'm not absolutly sure what this does, but it solved my problem
+ * with IDE DMA and sound, so I now can play sound and work with
+@@ -216,8 +216,8 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
+ outb(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT);
+ outb(data, CY82_DATA_PORT);
+
+-#if CY82C693_DEBUG_INFO
+- printk (KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n",
++#if CY82C693_DEBUG_INFO
++ printk(KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n",
+ drive->name, data);
+ #endif /* CY82C693_DEBUG_INFO */
+ }
+@@ -242,14 +242,14 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
+
+ #if CY82C693_DEBUG_LOGS
+ /* for debug let's show the register values */
+-
+- if (drive->select.b.unit == 0) {
++
++ if (drive->select.b.unit == 0) {
+ /*
+- * get master drive registers
++ * get master drive registers
+ * address setup control register
+ * is 32 bit !!!
+- */
+- pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
++ */
++ pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
+ addrCtrl &= 0x0F;
+
+ /* now let's get the remaining registers */
+@@ -261,7 +261,7 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ * set slave drive registers
+ * address setup control register
+ * is 32 bit !!!
+- */
++ */
+ pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
+
+ addrCtrl &= 0xF0;
+@@ -288,9 +288,9 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ * set master drive
+ * address setup control register
+ * is 32 bit !!!
+- */
++ */
+ pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
+-
++
+ addrCtrl &= (~0xF);
+ addrCtrl |= (unsigned int)pclk.address_time;
+ pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl);
+@@ -299,14 +299,14 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ pci_write_config_byte(dev, CY82_IDE_MASTER_IOR, pclk.time_16r);
+ pci_write_config_byte(dev, CY82_IDE_MASTER_IOW, pclk.time_16w);
+ pci_write_config_byte(dev, CY82_IDE_MASTER_8BIT, pclk.time_8);
+-
++
+ addrCtrl &= 0xF;
+ } else {
+ /*
+ * set slave drive
+ * address setup control register
+ * is 32 bit !!!
+- */
++ */
+ pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
+
+ addrCtrl &= (~0xF0);
+@@ -320,7 +320,7 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
+
+ addrCtrl >>= 4;
+ addrCtrl &= 0xF;
+- }
++ }
+
+ #if CY82C693_DEBUG_INFO
+ printk(KERN_INFO "%s (ch=%d, dev=%d): set PIO timing to "
+@@ -340,41 +340,41 @@ static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev, const c
+
+ #ifdef CY82C693_SETDMA_CLOCK
+ u8 data = 0;
+-#endif /* CY82C693_SETDMA_CLOCK */
++#endif /* CY82C693_SETDMA_CLOCK */
+
+ /* write info about this verion of the driver */
+ printk(KERN_INFO CY82_VERSION "\n");
+
+ #ifdef CY82C693_SETDMA_CLOCK
+ /* okay let's set the DMA clock speed */
+-
+- outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
+- data = inb(CY82_DATA_PORT);
++
++ outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
++ data = inb(CY82_DATA_PORT);
+
+ #if CY82C693_DEBUG_INFO
+ printk(KERN_INFO "%s: Peripheral Configuration Register: 0x%X\n",
+ name, data);
+ #endif /* CY82C693_DEBUG_INFO */
+
+- /*
++ /*
+ * for some reason sometimes the DMA controller
+ * speed is set to ATCLK/2 ???? - we fix this here
+- *
++ *
+ * note: i don't know what causes this strange behaviour,
+ * but even changing the dma speed doesn't solve it :-(
+- * the ide performance is still only half the normal speed
+- *
++ * the ide performance is still only half the normal speed
++ *
+ * if anybody knows what goes wrong with my machine, please
+ * let me know - ASK
+- */
++ */
+
+ data |= 0x03;
+
+- outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
+- outb(data, CY82_DATA_PORT);
++ outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
++ outb(data, CY82_DATA_PORT);
+
+ #if CY82C693_DEBUG_INFO
+- printk (KERN_INFO "%s: New Peripheral Configuration Register: 0x%X\n",
++ printk(KERN_INFO "%s: New Peripheral Configuration Register: 0x%X\n",
+ name, data);
+ #endif /* CY82C693_DEBUG_INFO */
+
+@@ -410,8 +410,7 @@ static const struct ide_port_info cy82c693_chipset __devinitdata = {
+ .init_iops = init_iops_cy82c693,
+ .init_hwif = init_hwif_cy82c693,
+ .chipset = ide_cy82c693,
+- .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_CY82C693 |
+- IDE_HFLAG_BOOTABLE,
++ .host_flags = IDE_HFLAG_SINGLE,
+ .pio_mask = ATA_PIO4,
+ .swdma_mask = ATA_SWDMA2,
+ .mwdma_mask = ATA_MWDMA2,
+@@ -424,7 +423,7 @@ static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_dev
+
+ /* CY82C693 is more than only a IDE controller.
+ Function 1 is primary IDE channel, function 2 - secondary. */
+- if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
++ if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
+ PCI_FUNC(dev->devfn) == 1) {
+ dev2 = pci_get_slot(dev->bus, dev->devfn + 1);
+ ret = ide_setup_pci_devices(dev, dev2, &cy82c693_chipset);
+diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/pci/delkin_cb.c
+index 3f9cd64..753b86f 100644
+--- a/drivers/ide/pci/delkin_cb.c
++++ b/drivers/ide/pci/delkin_cb.c
+@@ -71,25 +71,25 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
+ if (setup[i])
+ outb(setup[i], base + i);
+ }
+- pci_release_regions(dev); /* IDE layer handles regions itself */
+
+ memset(&hw, 0, sizeof(hw));
+ ide_std_init_ports(&hw, base + 0x10, base + 0x1e);
+ hw.irq = dev->irq;
+ hw.chipset = ide_pci; /* this enables IRQ sharing */
+
+- hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++ hwif = ide_find_port();
+ if (hwif == NULL)
+ goto out_disable;
+
+ i = hwif->index;
+
+ if (hwif->present)
+- ide_unregister(i, 0, 0);
+- else if (!hwif->hold)
++ ide_unregister(i);
++ else
+ ide_init_port_data(hwif, i);
+
+ ide_init_port_hw(hwif, &hw);
++ hwif->mmio = 1;
+ hwif->quirkproc = &ide_undecoded_slave;
+
+ idx[0] = i;
+@@ -110,6 +110,7 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
+
+ out_disable:
+ printk(KERN_ERR "delkin_cb: no IDE devices found\n");
++ pci_release_regions(dev);
+ pci_disable_device(dev);
+ return -ENODEV;
+ }
+@@ -120,8 +121,9 @@ delkin_cb_remove (struct pci_dev *dev)
+ ide_hwif_t *hwif = pci_get_drvdata(dev);
+
+ if (hwif)
+- ide_unregister(hwif->index, 0, 0);
++ ide_unregister(hwif->index);
+
++ pci_release_regions(dev);
+ pci_disable_device(dev);
+ }
+
+diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
+index 7fd83a9..041720e 100644
+--- a/drivers/ide/pci/generic.c
++++ b/drivers/ide/pci/generic.c
+@@ -38,8 +38,7 @@ MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE st
+ { \
+ .name = name_str, \
+ .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | \
+- extra_flags | \
+- IDE_HFLAG_BOOTABLE, \
++ extra_flags, \
+ .swdma_mask = ATA_SWDMA2, \
+ .mwdma_mask = ATA_MWDMA2, \
+ .udma_mask = ATA_UDMA6, \
+@@ -50,9 +49,8 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = {
+
+ { /* 1 */
+ .name = "NS87410",
+- .enablebits = {{0x43,0x08,0x08}, {0x47,0x08,0x08}},
+- .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+- IDE_HFLAG_BOOTABLE,
++ .enablebits = { {0x43, 0x08, 0x08}, {0x47, 0x08, 0x08} },
++ .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA,
+ .swdma_mask = ATA_SWDMA2,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA6,
+@@ -99,7 +97,7 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = {
+ * Called when the PCI registration layer (or the IDE initialization)
+ * finds a device matching our IDE device tables.
+ */
+-
++
+ static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ const struct ide_port_info *d = &generic_chipsets[id->driver_data];
+diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
+index 9f01da4..9f2fc30 100644
+--- a/drivers/ide/pci/hpt34x.c
++++ b/drivers/ide/pci/hpt34x.c
+@@ -133,7 +133,7 @@ static const struct ide_port_info hpt34x_chipsets[] __devinitdata = {
+ .init_chipset = init_chipset_hpt34x,
+ .init_hwif = init_hwif_hpt34x,
+ .extra = 16,
+- .host_flags = IDE_HFLAGS_HPT34X,
++ .host_flags = IDE_HFLAGS_HPT34X | IDE_HFLAG_NON_BOOTABLE,
+ .pio_mask = ATA_PIO5,
+ },
+ { /* 1 */
+diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
+index 6357bb6..a490906 100644
+--- a/drivers/ide/pci/hpt366.c
++++ b/drivers/ide/pci/hpt366.c
+@@ -760,7 +760,7 @@ static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
+ }
+ } else
+ outb(mask ? (drive->ctl | 2) : (drive->ctl & ~2),
+- IDE_CONTROL_REG);
++ hwif->io_ports[IDE_CONTROL_OFFSET]);
+ }
+
+ /*
+@@ -929,64 +929,6 @@ static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq)
+ hpt3xxn_set_clock(HWIF(drive), rq_data_dir(rq) ? 0x23 : 0x21);
+ }
+
+-/*
+- * Set/get power state for a drive.
+- * NOTE: affects both drives on each channel.
+- *
+- * When we turn the power back on, we need to re-initialize things.
+- */
+-#define TRISTATE_BIT 0x8000
+-
+-static int hpt3xx_busproc(ide_drive_t *drive, int state)
+-{
+- ide_hwif_t *hwif = HWIF(drive);
+- struct pci_dev *dev = to_pci_dev(hwif->dev);
+- u8 mcr_addr = hwif->select_data + 2;
+- u8 resetmask = hwif->channel ? 0x80 : 0x40;
+- u8 bsr2 = 0;
+- u16 mcr = 0;
+-
+- hwif->bus_state = state;
+-
+- /* Grab the status. */
+- pci_read_config_word(dev, mcr_addr, &mcr);
+- pci_read_config_byte(dev, 0x59, &bsr2);
+-
+- /*
+- * Set the state. We don't set it if we don't need to do so.
+- * Make sure that the drive knows that it has failed if it's off.
+- */
+- switch (state) {
+- case BUSSTATE_ON:
+- if (!(bsr2 & resetmask))
+- return 0;
+- hwif->drives[0].failures = hwif->drives[1].failures = 0;
+-
+- pci_write_config_byte(dev, 0x59, bsr2 & ~resetmask);
+- pci_write_config_word(dev, mcr_addr, mcr & ~TRISTATE_BIT);
+- return 0;
+- case BUSSTATE_OFF:
+- if ((bsr2 & resetmask) && !(mcr & TRISTATE_BIT))
+- return 0;
+- mcr &= ~TRISTATE_BIT;
+- break;
+- case BUSSTATE_TRISTATE:
+- if ((bsr2 & resetmask) && (mcr & TRISTATE_BIT))
+- return 0;
+- mcr |= TRISTATE_BIT;
+- break;
+- default:
+- return -EINVAL;
+- }
+-
+- hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
+- hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
+-
+- pci_write_config_word(dev, mcr_addr, mcr);
+- pci_write_config_byte(dev, 0x59, bsr2 | resetmask);
+- return 0;
+-}
+-
+ /**
+ * hpt37x_calibrate_dpll - calibrate the DPLL
+ * @dev: PCI device
+@@ -1334,7 +1276,6 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
+
+ hwif->quirkproc = &hpt3xx_quirkproc;
+ hwif->maskproc = &hpt3xx_maskproc;
+- hwif->busproc = &hpt3xx_busproc;
+
+ hwif->udma_filter = &hpt3xx_udma_filter;
+ hwif->mdma_filter = &hpt3xx_mdma_filter;
+@@ -1616,7 +1557,7 @@ static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_devic
+ hpt374_init(dev, dev2);
+ else {
+ if (hpt36x_init(dev, dev2))
+- d.host_flags |= IDE_HFLAG_BOOTABLE;
++ d.host_flags &= ~IDE_HFLAG_NON_BOOTABLE;
+ }
+
+ ret = ide_setup_pci_devices(dev, dev2, &d);
+diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c
+index e3427ea..5b5b0cc 100644
+--- a/drivers/ide/pci/it8213.c
++++ b/drivers/ide/pci/it8213.c
+@@ -35,7 +35,7 @@ static void it8213_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ static DEFINE_SPINLOCK(tune_lock);
+ int control = 0;
+
+- static const u8 timings[][2]= {
++ static const u8 timings[][2] = {
+ { 0, 0 },
+ { 0, 0 },
+ { 1, 0 },
+@@ -105,11 +105,10 @@ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
+
+ if (!(reg48 & u_flag))
+ pci_write_config_byte(dev, 0x48, reg48 | u_flag);
+- if (speed >= XFER_UDMA_5) {
++ if (speed >= XFER_UDMA_5)
+ pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag);
+- } else {
++ else
+ pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
+- }
+
+ if ((reg4a & a_speed) != u_speed)
+ pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed);
+@@ -170,9 +169,8 @@ static void __devinit init_hwif_it8213(ide_hwif_t *hwif)
+ { \
+ .name = name_str, \
+ .init_hwif = init_hwif_it8213, \
+- .enablebits = {{0x41,0x80,0x80}}, \
+- .host_flags = IDE_HFLAG_SINGLE | \
+- IDE_HFLAG_BOOTABLE, \
++ .enablebits = { {0x41, 0x80, 0x80} }, \
++ .host_flags = IDE_HFLAG_SINGLE, \
+ .pio_mask = ATA_PIO4, \
+ .swdma_mask = ATA_SWDMA2_ONLY, \
+ .mwdma_mask = ATA_MWDMA12_ONLY, \
+diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
+index d8a1674..a38ec47 100644
+--- a/drivers/ide/pci/it821x.c
++++ b/drivers/ide/pci/it821x.c
+@@ -523,16 +523,12 @@ static void __devinit it821x_quirkproc(ide_drive_t *drive)
+ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
+ {
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+- struct it821x_dev *idev = kzalloc(sizeof(struct it821x_dev), GFP_KERNEL);
++ struct it821x_dev **itdevs = (struct it821x_dev **)pci_get_drvdata(dev);
++ struct it821x_dev *idev = itdevs[hwif->channel];
+ u8 conf;
+
+ hwif->quirkproc = &it821x_quirkproc;
+
+- if (idev == NULL) {
+- printk(KERN_ERR "it821x: out of memory, falling back to legacy behaviour.\n");
+- return;
+- }
+-
+ ide_set_hwifdata(hwif, idev);
+
+ pci_read_config_byte(dev, 0x50, &conf);
+@@ -623,7 +619,6 @@ static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const cha
+ .name = name_str, \
+ .init_chipset = init_chipset_it821x, \
+ .init_hwif = init_hwif_it821x, \
+- .host_flags = IDE_HFLAG_BOOTABLE, \
+ .pio_mask = ATA_PIO4, \
+ }
+
+@@ -642,6 +637,22 @@ static const struct ide_port_info it821x_chipsets[] __devinitdata = {
+
+ static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
++ struct it821x_dev *itdevs[2] = { NULL, NULL} , *itdev;
++ unsigned int i;
++
++ for (i = 0; i < 2; i++) {
++ itdev = kzalloc(sizeof(*itdev), GFP_KERNEL);
++ if (itdev == NULL) {
++ kfree(itdevs[0]);
++ printk(KERN_ERR "it821x: out of memory\n");
++ return -ENOMEM;
++ }
++
++ itdevs[i] = itdev;
++ }
++
++ pci_set_drvdata(dev, itdevs);
++
+ return ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]);
+ }
+
+diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c
+index a56bcb4..673f7dc 100644
+--- a/drivers/ide/pci/jmicron.c
++++ b/drivers/ide/pci/jmicron.c
+@@ -63,8 +63,7 @@ static u8 __devinit ata66_jmicron(ide_hwif_t *hwif)
+ * actually do our cable checking etc. Thankfully we don't need
+ * to do the plumbing for other cases.
+ */
+- switch (port_map[port])
+- {
++ switch (port_map[port]) {
+ case PORT_PATA0:
+ if (control & (1 << 3)) /* 40/80 pin primary */
+ return ATA_CBL_PATA40;
+@@ -114,7 +113,6 @@ static void __devinit init_hwif_jmicron(ide_hwif_t *hwif)
+ static const struct ide_port_info jmicron_chipset __devinitdata = {
+ .name = "JMB",
+ .init_hwif = init_hwif_jmicron,
+- .host_flags = IDE_HFLAG_BOOTABLE,
+ .enablebits = { { 0x40, 0x01, 0x01 }, { 0x40, 0x10, 0x10 } },
+ .pio_mask = ATA_PIO5,
+ .mwdma_mask = ATA_MWDMA2,
+diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c
+index bf0d3b2..3015d69 100644
+--- a/drivers/ide/pci/ns87415.c
++++ b/drivers/ide/pci/ns87415.c
+@@ -181,6 +181,10 @@ static int ns87415_ide_dma_setup(ide_drive_t *drive)
+ return 1;
+ }
+
++#ifndef ide_default_irq
++#define ide_default_irq(irq) 0
++#endif
++
+ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
+ {
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+@@ -261,8 +265,7 @@ static const struct ide_port_info ns87415_chipset __devinitdata = {
+ #endif
+ .init_hwif = init_hwif_ns87415,
+ .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+- IDE_HFLAG_NO_ATAPI_DMA |
+- IDE_HFLAG_BOOTABLE,
++ IDE_HFLAG_NO_ATAPI_DMA,
+ };
+
+ static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c
+index 46e8748..88a4dd9 100644
+--- a/drivers/ide/pci/opti621.c
++++ b/drivers/ide/pci/opti621.c
+@@ -57,9 +57,9 @@
+ * (use idebus=xx to select PCI bus speed).
+ *
+ * Version 0.1, Nov 8, 1996
+- * by Jaromir Koutek, for 2.1.8.
++ * by Jaromir Koutek, for 2.1.8.
+ * Initial version of driver.
+- *
++ *
+ * Version 0.2
+ * Number 0.2 skipped.
+ *
+@@ -75,7 +75,7 @@
+ * by Jaromir Koutek
+ * Updates for use with (again) new IDE block driver.
+ * Update of documentation.
+- *
++ *
+ * Version 0.6, Jan 2, 1999
+ * by Jaromir Koutek
+ * Reversed to version 0.3 of the driver, because
+@@ -208,29 +208,34 @@ typedef struct pio_clocks_s {
+
+ static void compute_clocks(int pio, pio_clocks_t *clks)
+ {
+- if (pio != PIO_NOT_EXIST) {
+- int adr_setup, data_pls;
++ if (pio != PIO_NOT_EXIST) {
++ int adr_setup, data_pls;
+ int bus_speed = system_bus_clock();
+
+- adr_setup = ide_pio_timings[pio].setup_time;
+- data_pls = ide_pio_timings[pio].active_time;
+- clks->address_time = cmpt_clk(adr_setup, bus_speed);
+- clks->data_time = cmpt_clk(data_pls, bus_speed);
+- clks->recovery_time = cmpt_clk(ide_pio_timings[pio].cycle_time
+- - adr_setup-data_pls, bus_speed);
+- if (clks->address_time<1) clks->address_time = 1;
+- if (clks->address_time>4) clks->address_time = 4;
+- if (clks->data_time<1) clks->data_time = 1;
+- if (clks->data_time>16) clks->data_time = 16;
+- if (clks->recovery_time<2) clks->recovery_time = 2;
+- if (clks->recovery_time>17) clks->recovery_time = 17;
++ adr_setup = ide_pio_timings[pio].setup_time;
++ data_pls = ide_pio_timings[pio].active_time;
++ clks->address_time = cmpt_clk(adr_setup, bus_speed);
++ clks->data_time = cmpt_clk(data_pls, bus_speed);
++ clks->recovery_time = cmpt_clk(ide_pio_timings[pio].cycle_time
++ - adr_setup-data_pls, bus_speed);
++ if (clks->address_time < 1)
++ clks->address_time = 1;
++ if (clks->address_time > 4)
++ clks->address_time = 4;
++ if (clks->data_time < 1)
++ clks->data_time = 1;
++ if (clks->data_time > 16)
++ clks->data_time = 16;
++ if (clks->recovery_time < 2)
++ clks->recovery_time = 2;
++ if (clks->recovery_time > 17)
++ clks->recovery_time = 17;
+ } else {
+ clks->address_time = 1;
+ clks->data_time = 1;
+ clks->recovery_time = 2;
+ /* minimal values */
+ }
+-
+ }
+
+ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
+@@ -247,8 +252,8 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
+
+ /* sets drive->drive_data for both drives */
+ compute_pios(drive, pio);
+- pio1 = hwif->drives[0].drive_data;
+- pio2 = hwif->drives[1].drive_data;
++ pio1 = hwif->drives[0].drive_data;
++ pio2 = hwif->drives[1].drive_data;
+
+ compute_clocks(pio1, &first);
+ compute_clocks(pio2, &second);
+@@ -275,7 +280,7 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
+
+ spin_lock_irqsave(&opti621_lock, flags);
+
+- reg_base = hwif->io_ports[IDE_DATA_OFFSET];
++ reg_base = hwif->io_ports[IDE_DATA_OFFSET];
+
+ /* allow Register-B */
+ outb(0xc0, reg_base + CNTRL_REG);
+@@ -324,7 +329,7 @@ static void __devinit opti621_port_init_devs(ide_hwif_t *hwif)
+ /*
+ * init_hwif_opti621() is called once for each hwif found at boot.
+ */
+-static void __devinit init_hwif_opti621 (ide_hwif_t *hwif)
++static void __devinit init_hwif_opti621(ide_hwif_t *hwif)
+ {
+ hwif->port_init_devs = opti621_port_init_devs;
+ hwif->set_pio_mode = &opti621_set_pio_mode;
+@@ -334,18 +339,16 @@ static const struct ide_port_info opti621_chipsets[] __devinitdata = {
+ { /* 0 */
+ .name = "OPTI621",
+ .init_hwif = init_hwif_opti621,
+- .enablebits = {{0x45,0x80,0x00}, {0x40,0x08,0x00}},
+- .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+- IDE_HFLAG_BOOTABLE,
++ .enablebits = { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} },
++ .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA,
+ .pio_mask = ATA_PIO3,
+ .swdma_mask = ATA_SWDMA2,
+ .mwdma_mask = ATA_MWDMA2,
+- },{ /* 1 */
++ }, { /* 1 */
+ .name = "OPTI621X",
+ .init_hwif = init_hwif_opti621,
+- .enablebits = {{0x45,0x80,0x00}, {0x40,0x08,0x00}},
+- .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+- IDE_HFLAG_BOOTABLE,
++ .enablebits = { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} },
++ .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA,
+ .pio_mask = ATA_PIO3,
+ .swdma_mask = ATA_SWDMA2,
+ .mwdma_mask = ATA_MWDMA2,
+diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
+index decef0f..89d74ff 100644
+--- a/drivers/ide/pci/piix.c
++++ b/drivers/ide/pci/piix.c
+@@ -307,9 +307,9 @@ static void __devinit init_hwif_ich(ide_hwif_t *hwif)
+ }
+
+ #ifndef CONFIG_IA64
+- #define IDE_HFLAGS_PIIX (IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE)
++ #define IDE_HFLAGS_PIIX IDE_HFLAG_LEGACY_IRQS
+ #else
+- #define IDE_HFLAGS_PIIX IDE_HFLAG_BOOTABLE
++ #define IDE_HFLAGS_PIIX 0
+ #endif
+
+ #define DECLARE_PIIX_DEV(name_str, udma) \
+diff --git a/drivers/ide/pci/rz1000.c b/drivers/ide/pci/rz1000.c
+index 5167661..532154a 100644
+--- a/drivers/ide/pci/rz1000.c
++++ b/drivers/ide/pci/rz1000.c
+@@ -43,7 +43,7 @@ static const struct ide_port_info rz1000_chipset __devinitdata = {
+ .name = "RZ100x",
+ .init_hwif = init_hwif_rz1000,
+ .chipset = ide_rz1000,
+- .host_flags = IDE_HFLAG_NO_DMA | IDE_HFLAG_BOOTABLE,
++ .host_flags = IDE_HFLAG_NO_DMA,
+ };
+
+ static int __devinit rz1000_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
+index 561aa47..44985c8 100644
+--- a/drivers/ide/pci/sc1200.c
++++ b/drivers/ide/pci/sc1200.c
+@@ -307,8 +307,7 @@ static const struct ide_port_info sc1200_chipset __devinitdata = {
+ .init_hwif = init_hwif_sc1200,
+ .host_flags = IDE_HFLAG_SERIALIZE |
+ IDE_HFLAG_POST_SET_MODE |
+- IDE_HFLAG_ABUSE_DMA_MODES |
+- IDE_HFLAG_BOOTABLE,
++ IDE_HFLAG_ABUSE_DMA_MODES,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA2,
+diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c
+index 238e3e1..5214579 100644
+--- a/drivers/ide/pci/scc_pata.c
++++ b/drivers/ide/pci/scc_pata.c
+@@ -65,7 +65,7 @@
+
+ static struct scc_ports {
+ unsigned long ctl, dma;
+- unsigned char hwif_id; /* for removing hwif from system */
++ ide_hwif_t *hwif; /* for removing port from system */
+ } scc_ports[MAX_HWIFS];
+
+ /* PIO transfer mode table */
+@@ -334,7 +334,8 @@ static int scc_ide_dma_end(ide_drive_t * drive)
+
+ /* errata A308 workaround: Step5 (check data loss) */
+ /* We don't check non ide_disk because it is limited to UDMA4 */
+- if (!(in_be32((void __iomem *)IDE_ALTSTATUS_REG) & ERR_STAT) &&
++ if (!(in_be32((void __iomem *)hwif->io_ports[IDE_ALTSTATUS_OFFSET])
++ & ERR_STAT) &&
+ drive->media == ide_disk && drive->current_speed > XFER_UDMA_4) {
+ reg = in_be32((void __iomem *)intsts_port);
+ if (!(reg & INTSTS_ACTEINT)) {
+@@ -437,7 +438,8 @@ static int scc_dma_test_irq(ide_drive_t *drive)
+ u32 int_stat = in_be32((void __iomem *)hwif->dma_base + 0x014);
+
+ /* SCC errata A252,A308 workaround: Step4 */
+- if ((in_be32((void __iomem *)IDE_ALTSTATUS_REG) & ERR_STAT) &&
++ if ((in_be32((void __iomem *)hwif->io_ports[IDE_ALTSTATUS_OFFSET])
++ & ERR_STAT) &&
+ (int_stat & INTSTS_INTRQ))
+ return 1;
+
+@@ -523,6 +525,39 @@ static int setup_mmio_scc (struct pci_dev *dev, const char *name)
+ return -ENOMEM;
+ }
+
++static int scc_ide_setup_pci_device(struct pci_dev *dev,
++ const struct ide_port_info *d)
++{
++ struct scc_ports *ports = pci_get_drvdata(dev);
++ ide_hwif_t *hwif = NULL;
++ hw_regs_t hw;
++ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
++ int i;
++
++ hwif = ide_find_port();
++ if (hwif == NULL) {
++ printk(KERN_ERR "%s: too many IDE interfaces, "
++ "no room in table\n", SCC_PATA_NAME);
++ return -ENOMEM;
++ }
++
++ memset(&hw, 0, sizeof(hw));
++ for (i = IDE_DATA_OFFSET; i <= IDE_CONTROL_OFFSET; i++)
++ hw.io_ports[i] = ports->dma + 0x20 + i * 4;
++ hw.irq = dev->irq;
++ hw.dev = &dev->dev;
++ hw.chipset = ide_pci;
++ ide_init_port_hw(hwif, &hw);
++ hwif->dev = &dev->dev;
++ hwif->cds = d;
++
++ idx[0] = hwif->index;
++
++ ide_device_add(idx, d);
++
++ return 0;
++}
++
+ /**
+ * init_setup_scc - set up an SCC PATA Controller
+ * @dev: PCI device
+@@ -545,10 +580,13 @@ static int __devinit init_setup_scc(struct pci_dev *dev,
+ struct scc_ports *ports;
+ int rc;
+
++ rc = pci_enable_device(dev);
++ if (rc)
++ goto end;
++
+ rc = setup_mmio_scc(dev, d->name);
+- if (rc < 0) {
+- return rc;
+- }
++ if (rc < 0)
++ goto end;
+
+ ports = pci_get_drvdata(dev);
+ ctl_base = ports->ctl;
+@@ -583,7 +621,10 @@ static int __devinit init_setup_scc(struct pci_dev *dev,
+ out_be32((void*)mode_port, MODE_JCUSFEN);
+ out_be32((void*)intmask_port, INTMASK_MSK);
+
+- return ide_setup_pci_device(dev, d);
++ rc = scc_ide_setup_pci_device(dev, d);
++
++ end:
++ return rc;
+ }
+
+ /**
+@@ -610,17 +651,6 @@ static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
+ hwif->OUTSW = scc_ide_outsw;
+ hwif->OUTSL = scc_ide_outsl;
+
+- hwif->io_ports[IDE_DATA_OFFSET] = dma_base + 0x20;
+- hwif->io_ports[IDE_ERROR_OFFSET] = dma_base + 0x24;
+- hwif->io_ports[IDE_NSECTOR_OFFSET] = dma_base + 0x28;
+- hwif->io_ports[IDE_SECTOR_OFFSET] = dma_base + 0x2c;
+- hwif->io_ports[IDE_LCYL_OFFSET] = dma_base + 0x30;
+- hwif->io_ports[IDE_HCYL_OFFSET] = dma_base + 0x34;
+- hwif->io_ports[IDE_SELECT_OFFSET] = dma_base + 0x38;
+- hwif->io_ports[IDE_STATUS_OFFSET] = dma_base + 0x3c;
+- hwif->io_ports[IDE_CONTROL_OFFSET] = dma_base + 0x40;
+-
+- hwif->irq = dev->irq;
+ hwif->dma_base = dma_base;
+ hwif->config_data = ports->ctl;
+ hwif->mmio = 1;
+@@ -662,7 +692,7 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
+ {
+ struct scc_ports *ports = ide_get_hwifdata(hwif);
+
+- ports->hwif_id = hwif->index;
++ ports->hwif = hwif;
+
+ hwif->dma_command = hwif->dma_base;
+ hwif->dma_status = hwif->dma_base + 0x04;
+@@ -691,8 +721,7 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
+ .name = name_str, \
+ .init_iops = init_iops_scc, \
+ .init_hwif = init_hwif_scc, \
+- .host_flags = IDE_HFLAG_SINGLE | \
+- IDE_HFLAG_BOOTABLE, \
++ .host_flags = IDE_HFLAG_SINGLE, \
+ .pio_mask = ATA_PIO4, \
+ }
+
+@@ -724,7 +753,7 @@ static int __devinit scc_init_one(struct pci_dev *dev, const struct pci_device_i
+ static void __devexit scc_remove(struct pci_dev *dev)
+ {
+ struct scc_ports *ports = pci_get_drvdata(dev);
+- ide_hwif_t *hwif = &ide_hwifs[ports->hwif_id];
++ ide_hwif_t *hwif = ports->hwif;
+ unsigned long ctl_base = pci_resource_start(dev, 0);
+ unsigned long dma_base = pci_resource_start(dev, 1);
+ unsigned long ctl_size = pci_resource_len(dev, 0);
+@@ -736,7 +765,7 @@ static void __devexit scc_remove(struct pci_dev *dev)
+ hwif->dmatable_cpu = NULL;
+ }
+
+- ide_unregister(hwif->index, 0, 0);
++ ide_unregister(hwif->index);
+
+ hwif->chipset = ide_unknown;
+ iounmap((void*)ports->dma);
+diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
+index c11880b..cfe9274 100644
+--- a/drivers/ide/pci/serverworks.c
++++ b/drivers/ide/pci/serverworks.c
+@@ -350,8 +350,7 @@ static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
+
+ #define IDE_HFLAGS_SVWKS \
+ (IDE_HFLAG_LEGACY_IRQS | \
+- IDE_HFLAG_ABUSE_SET_DMA_MODE | \
+- IDE_HFLAG_BOOTABLE)
++ IDE_HFLAG_ABUSE_SET_DMA_MODE)
+
+ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
+ { /* 0 */
+@@ -418,7 +417,7 @@ static int __devinit svwks_init_one(struct pci_dev *dev, const struct pci_device
+ else if (idx == 2 || idx == 3) {
+ if ((PCI_FUNC(dev->devfn) & 1) == 0) {
+ if (pci_resource_start(dev, 0) != 0x01f1)
+- d.host_flags &= ~IDE_HFLAG_BOOTABLE;
++ d.host_flags |= IDE_HFLAG_NON_BOOTABLE;
+ d.host_flags |= IDE_HFLAG_SINGLE;
+ } else
+ d.host_flags &= ~IDE_HFLAG_SINGLE;
+diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
+index 0546264..6bd9523 100644
+--- a/drivers/ide/pci/sgiioc4.c
++++ b/drivers/ide/pci/sgiioc4.c
+@@ -112,10 +112,9 @@ static void
+ sgiioc4_maskproc(ide_drive_t * drive, int mask)
+ {
+ writeb(mask ? (drive->ctl | 2) : (drive->ctl & ~2),
+- (void __iomem *)IDE_CONTROL_REG);
++ (void __iomem *)drive->hwif->io_ports[IDE_CONTROL_OFFSET]);
+ }
+
+-
+ static int
+ sgiioc4_checkirq(ide_hwif_t * hwif)
+ {
+@@ -142,18 +141,18 @@ sgiioc4_clearirq(ide_drive_t * drive)
+ intr_reg = readl((void __iomem *)other_ir);
+ if (intr_reg & 0x03) { /* Valid IOC4-IDE interrupt */
+ /*
+- * Using sgiioc4_INB to read the IDE_STATUS_REG has a side effect
+- * of clearing the interrupt. The first read should clear it
+- * if it is set. The second read should return a "clear" status
+- * if it got cleared. If not, then spin for a bit trying to
+- * clear it.
++ * Using sgiioc4_INB to read the Status register has a side
++ * effect of clearing the interrupt. The first read should
++ * clear it if it is set. The second read should return
++ * a "clear" status if it got cleared. If not, then spin
++ * for a bit trying to clear it.
+ */
+- u8 stat = sgiioc4_INB(IDE_STATUS_REG);
++ u8 stat = sgiioc4_INB(hwif->io_ports[IDE_STATUS_OFFSET]);
+ int count = 0;
+- stat = sgiioc4_INB(IDE_STATUS_REG);
++ stat = sgiioc4_INB(hwif->io_ports[IDE_STATUS_OFFSET]);
+ while ((stat & 0x80) && (count++ < 100)) {
+ udelay(1);
+- stat = sgiioc4_INB(IDE_STATUS_REG);
++ stat = sgiioc4_INB(hwif->io_ports[IDE_STATUS_OFFSET]);
+ }
+
+ if (intr_reg & 0x02) {
+@@ -562,7 +561,6 @@ ide_init_sgiioc4(ide_hwif_t * hwif)
+ clear interrupts */
+ hwif->maskproc = &sgiioc4_maskproc; /* Mask on/off NIEN register */
+ hwif->quirkproc = NULL;
+- hwif->busproc = NULL;
+
+ hwif->INB = &sgiioc4_INB;
+
+@@ -592,20 +590,12 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
+ unsigned long bar0, cmd_phys_base, ctl;
+ void __iomem *virt_base;
+ ide_hwif_t *hwif;
+- int h;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw;
+ struct ide_port_info d = sgiioc4_port_info;
+
+- /*
+- * Find an empty HWIF; if none available, return -ENOMEM.
+- */
+- for (h = 0; h < MAX_HWIFS; ++h) {
+- hwif = &ide_hwifs[h];
+- if (hwif->chipset == ide_unknown)
+- break;
+- }
+- if (h == MAX_HWIFS) {
++ hwif = ide_find_port();
++ if (hwif == NULL) {
+ printk(KERN_ERR "%s: too many IDE interfaces, no room in table\n",
+ DRV_NAME);
+ return -ENOMEM;
+diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
+index 8d624af..c9ecab8 100644
+--- a/drivers/ide/pci/siimage.c
++++ b/drivers/ide/pci/siimage.c
+@@ -370,48 +370,6 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive)
+ }
+
+ /**
+- * sil_sata_busproc - bus isolation IOCTL
+- * @drive: drive to isolate/restore
+- * @state: bus state to set
+- *
+- * Used by the SII3112 to handle bus isolation. As this is a
+- * SATA controller the work required is quite limited, we
+- * just have to clean up the statistics
+- */
+-
+-static int sil_sata_busproc(ide_drive_t * drive, int state)
+-{
+- ide_hwif_t *hwif = HWIF(drive);
+- struct pci_dev *dev = to_pci_dev(hwif->dev);
+- u32 stat_config = 0;
+- unsigned long addr = siimage_selreg(hwif, 0);
+-
+- if (hwif->mmio)
+- stat_config = readl((void __iomem *)addr);
+- else
+- pci_read_config_dword(dev, addr, &stat_config);
+-
+- switch (state) {
+- case BUSSTATE_ON:
+- hwif->drives[0].failures = 0;
+- hwif->drives[1].failures = 0;
+- break;
+- case BUSSTATE_OFF:
+- hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
+- hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
+- break;
+- case BUSSTATE_TRISTATE:
+- hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
+- hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
+- break;
+- default:
+- return -EINVAL;
+- }
+- hwif->bus_state = state;
+- return 0;
+-}
+-
+-/**
+ * sil_sata_reset_poll - wait for SATA reset
+ * @drive: drive we are resetting
+ *
+@@ -818,7 +776,6 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
+ if (sata) {
+ static int first = 1;
+
+- hwif->busproc = &sil_sata_busproc;
+ hwif->reset_poll = &sil_sata_reset_poll;
+ hwif->pre_reset = &sil_sata_pre_reset;
+ hwif->udma_filter = &sil_sata_udma_filter;
+@@ -851,7 +808,6 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
+ .init_chipset = init_chipset_siimage, \
+ .init_iops = init_iops_siimage, \
+ .init_hwif = init_hwif_siimage, \
+- .host_flags = IDE_HFLAG_BOOTABLE, \
+ .pio_mask = ATA_PIO4, \
+ .mwdma_mask = ATA_MWDMA2, \
+ .udma_mask = ATA_UDMA6, \
+diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
+index 512bb4c..181b647 100644
+--- a/drivers/ide/pci/sis5513.c
++++ b/drivers/ide/pci/sis5513.c
+@@ -59,10 +59,10 @@
+ #define ATA_16 0x01
+ #define ATA_33 0x02
+ #define ATA_66 0x03
+-#define ATA_100a 0x04 // SiS730/SiS550 is ATA100 with ATA66 layout
++#define ATA_100a 0x04 /* SiS730/SiS550 is ATA100 with ATA66 layout */
+ #define ATA_100 0x05
+-#define ATA_133a 0x06 // SiS961b with 133 support
+-#define ATA_133 0x07 // SiS962/963
++#define ATA_133a 0x06 /* SiS961b with 133 support */
++#define ATA_133 0x07 /* SiS962/963 */
+
+ static u8 chipset_family;
+
+@@ -111,69 +111,70 @@ static const struct {
+ Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */
+
+ /* {0, ATA_16, ATA_33, ATA_66, ATA_100a, ATA_100, ATA_133} */
+-static u8 cycle_time_offset[] = {0,0,5,4,4,0,0};
+-static u8 cycle_time_range[] = {0,0,2,3,3,4,4};
++static u8 cycle_time_offset[] = { 0, 0, 5, 4, 4, 0, 0 };
++static u8 cycle_time_range[] = { 0, 0, 2, 3, 3, 4, 4 };
+ static u8 cycle_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = {
+- {0,0,0,0,0,0,0}, /* no udma */
+- {0,0,0,0,0,0,0}, /* no udma */
+- {3,2,1,0,0,0,0}, /* ATA_33 */
+- {7,5,3,2,1,0,0}, /* ATA_66 */
+- {7,5,3,2,1,0,0}, /* ATA_100a (730 specific), differences are on cycle_time range and offset */
+- {11,7,5,4,2,1,0}, /* ATA_100 */
+- {15,10,7,5,3,2,1}, /* ATA_133a (earliest 691 southbridges) */
+- {15,10,7,5,3,2,1}, /* ATA_133 */
++ { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */
++ { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */
++ { 3, 2, 1, 0, 0, 0, 0 }, /* ATA_33 */
++ { 7, 5, 3, 2, 1, 0, 0 }, /* ATA_66 */
++ { 7, 5, 3, 2, 1, 0, 0 }, /* ATA_100a (730 specific),
++ different cycle_time range and offset */
++ { 11, 7, 5, 4, 2, 1, 0 }, /* ATA_100 */
++ { 15, 10, 7, 5, 3, 2, 1 }, /* ATA_133a (earliest 691 southbridges) */
++ { 15, 10, 7, 5, 3, 2, 1 }, /* ATA_133 */
+ };
+ /* CRC Valid Setup Time vary across IDE clock setting 33/66/100/133
+ See SiS962 data sheet for more detail */
+ static u8 cvs_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = {
+- {0,0,0,0,0,0,0}, /* no udma */
+- {0,0,0,0,0,0,0}, /* no udma */
+- {2,1,1,0,0,0,0},
+- {4,3,2,1,0,0,0},
+- {4,3,2,1,0,0,0},
+- {6,4,3,1,1,1,0},
+- {9,6,4,2,2,2,2},
+- {9,6,4,2,2,2,2},
++ { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */
++ { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */
++ { 2, 1, 1, 0, 0, 0, 0 },
++ { 4, 3, 2, 1, 0, 0, 0 },
++ { 4, 3, 2, 1, 0, 0, 0 },
++ { 6, 4, 3, 1, 1, 1, 0 },
++ { 9, 6, 4, 2, 2, 2, 2 },
++ { 9, 6, 4, 2, 2, 2, 2 },
+ };
+ /* Initialize time, Active time, Recovery time vary across
+ IDE clock settings. These 3 arrays hold the register value
+ for PIO0/1/2/3/4 and DMA0/1/2 mode in order */
+ static u8 ini_time_value[][8] = {
+- {0,0,0,0,0,0,0,0},
+- {0,0,0,0,0,0,0,0},
+- {2,1,0,0,0,1,0,0},
+- {4,3,1,1,1,3,1,1},
+- {4,3,1,1,1,3,1,1},
+- {6,4,2,2,2,4,2,2},
+- {9,6,3,3,3,6,3,3},
+- {9,6,3,3,3,6,3,3},
++ { 0, 0, 0, 0, 0, 0, 0, 0 },
++ { 0, 0, 0, 0, 0, 0, 0, 0 },
++ { 2, 1, 0, 0, 0, 1, 0, 0 },
++ { 4, 3, 1, 1, 1, 3, 1, 1 },
++ { 4, 3, 1, 1, 1, 3, 1, 1 },
++ { 6, 4, 2, 2, 2, 4, 2, 2 },
++ { 9, 6, 3, 3, 3, 6, 3, 3 },
++ { 9, 6, 3, 3, 3, 6, 3, 3 },
+ };
+ static u8 act_time_value[][8] = {
+- {0,0,0,0,0,0,0,0},
+- {0,0,0,0,0,0,0,0},
+- {9,9,9,2,2,7,2,2},
+- {19,19,19,5,4,14,5,4},
+- {19,19,19,5,4,14,5,4},
+- {28,28,28,7,6,21,7,6},
+- {38,38,38,10,9,28,10,9},
+- {38,38,38,10,9,28,10,9},
++ { 0, 0, 0, 0, 0, 0, 0, 0 },
++ { 0, 0, 0, 0, 0, 0, 0, 0 },
++ { 9, 9, 9, 2, 2, 7, 2, 2 },
++ { 19, 19, 19, 5, 4, 14, 5, 4 },
++ { 19, 19, 19, 5, 4, 14, 5, 4 },
++ { 28, 28, 28, 7, 6, 21, 7, 6 },
++ { 38, 38, 38, 10, 9, 28, 10, 9 },
++ { 38, 38, 38, 10, 9, 28, 10, 9 },
+ };
+ static u8 rco_time_value[][8] = {
+- {0,0,0,0,0,0,0,0},
+- {0,0,0,0,0,0,0,0},
+- {9,2,0,2,0,7,1,1},
+- {19,5,1,5,2,16,3,2},
+- {19,5,1,5,2,16,3,2},
+- {30,9,3,9,4,25,6,4},
+- {40,12,4,12,5,34,12,5},
+- {40,12,4,12,5,34,12,5},
++ { 0, 0, 0, 0, 0, 0, 0, 0 },
++ { 0, 0, 0, 0, 0, 0, 0, 0 },
++ { 9, 2, 0, 2, 0, 7, 1, 1 },
++ { 19, 5, 1, 5, 2, 16, 3, 2 },
++ { 19, 5, 1, 5, 2, 16, 3, 2 },
++ { 30, 9, 3, 9, 4, 25, 6, 4 },
++ { 40, 12, 4, 12, 5, 34, 12, 5 },
++ { 40, 12, 4, 12, 5, 34, 12, 5 },
+ };
+
+ /*
+ * Printing configuration
+ */
+ /* Used for chipset type printing at boot time */
+-static char* chipset_capability[] = {
++static char *chipset_capability[] = {
+ "ATA", "ATA 16",
+ "ATA 33", "ATA 66",
+ "ATA 100 (1st gen)", "ATA 100 (2nd gen)",
+@@ -272,7 +273,7 @@ static void sis_program_timings(ide_drive_t *drive, const u8 mode)
+ sis_ata133_program_timings(drive, mode);
+ }
+
+-static void config_drive_art_rwp (ide_drive_t *drive)
++static void config_drive_art_rwp(ide_drive_t *drive)
+ {
+ ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+@@ -358,8 +359,7 @@ static u8 sis5513_ata133_udma_filter(ide_drive_t *drive)
+ return (regdw & 0x08) ? ATA_UDMA6 : ATA_UDMA5;
+ }
+
+-/* Chip detection and general config */
+-static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const char *name)
++static int __devinit sis_find_family(struct pci_dev *dev)
+ {
+ struct pci_dev *host;
+ int i = 0;
+@@ -381,7 +381,7 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c
+ chipset_family = ATA_100a;
+ }
+ pci_dev_put(host);
+-
++
+ printk(KERN_INFO "SIS5513: %s %s controller\n",
+ SiSHostChipInfo[i].name, chipset_capability[chipset_family]);
+ }
+@@ -440,63 +440,60 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c
+ }
+ }
+
+- if (!chipset_family)
+- return -1;
++ return chipset_family;
++}
+
++static unsigned int __devinit init_chipset_sis5513(struct pci_dev *dev,
++ const char *name)
++{
+ /* Make general config ops here
+ 1/ tell IDE channels to operate in Compatibility mode only
+ 2/ tell old chips to allow per drive IDE timings */
+
+- {
+- u8 reg;
+- u16 regw;
+-
+- switch(chipset_family) {
+- case ATA_133:
+- /* SiS962 operation mode */
+- pci_read_config_word(dev, 0x50, ®w);
+- if (regw & 0x08)
+- pci_write_config_word(dev, 0x50, regw&0xfff7);
+- pci_read_config_word(dev, 0x52, ®w);
+- if (regw & 0x08)
+- pci_write_config_word(dev, 0x52, regw&0xfff7);
+- break;
+- case ATA_133a:
+- case ATA_100:
+- /* Fixup latency */
+- pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);
+- /* Set compatibility bit */
+- pci_read_config_byte(dev, 0x49, ®);
+- if (!(reg & 0x01)) {
+- pci_write_config_byte(dev, 0x49, reg|0x01);
+- }
+- break;
+- case ATA_100a:
+- case ATA_66:
+- /* Fixup latency */
+- pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10);
+-
+- /* On ATA_66 chips the bit was elsewhere */
+- pci_read_config_byte(dev, 0x52, ®);
+- if (!(reg & 0x04)) {
+- pci_write_config_byte(dev, 0x52, reg|0x04);
+- }
+- break;
+- case ATA_33:
+- /* On ATA_33 we didn't have a single bit to set */
+- pci_read_config_byte(dev, 0x09, ®);
+- if ((reg & 0x0f) != 0x00) {
+- pci_write_config_byte(dev, 0x09, reg&0xf0);
+- }
+- case ATA_16:
+- /* force per drive recovery and active timings
+- needed on ATA_33 and below chips */
+- pci_read_config_byte(dev, 0x52, ®);
+- if (!(reg & 0x08)) {
+- pci_write_config_byte(dev, 0x52, reg|0x08);
+- }
+- break;
+- }
++ u8 reg;
++ u16 regw;
++
++ switch (chipset_family) {
++ case ATA_133:
++ /* SiS962 operation mode */
++ pci_read_config_word(dev, 0x50, ®w);
++ if (regw & 0x08)
++ pci_write_config_word(dev, 0x50, regw&0xfff7);
++ pci_read_config_word(dev, 0x52, ®w);
++ if (regw & 0x08)
++ pci_write_config_word(dev, 0x52, regw&0xfff7);
++ break;
++ case ATA_133a:
++ case ATA_100:
++ /* Fixup latency */
++ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);
++ /* Set compatibility bit */
++ pci_read_config_byte(dev, 0x49, ®);
++ if (!(reg & 0x01))
++ pci_write_config_byte(dev, 0x49, reg|0x01);
++ break;
++ case ATA_100a:
++ case ATA_66:
++ /* Fixup latency */
++ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10);
++
++ /* On ATA_66 chips the bit was elsewhere */
++ pci_read_config_byte(dev, 0x52, ®);
++ if (!(reg & 0x04))
++ pci_write_config_byte(dev, 0x52, reg|0x04);
++ break;
++ case ATA_33:
++ /* On ATA_33 we didn't have a single bit to set */
++ pci_read_config_byte(dev, 0x09, ®);
++ if ((reg & 0x0f) != 0x00)
++ pci_write_config_byte(dev, 0x09, reg&0xf0);
++ case ATA_16:
++ /* force per drive recovery and active timings
++ needed on ATA_33 and below chips */
++ pci_read_config_byte(dev, 0x52, ®);
++ if (!(reg & 0x08))
++ pci_write_config_byte(dev, 0x52, reg|0x08);
++ break;
+ }
+
+ return 0;
+@@ -546,10 +543,8 @@ static u8 __devinit ata66_sis5513(ide_hwif_t *hwif)
+ return ata66 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+ }
+
+-static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
++static void __devinit init_hwif_sis5513(ide_hwif_t *hwif)
+ {
+- u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f };
+-
+ hwif->set_pio_mode = &sis_set_pio_mode;
+ hwif->set_dma_mode = &sis_set_dma_mode;
+
+@@ -557,27 +552,29 @@ static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
+ hwif->udma_filter = sis5513_ata133_udma_filter;
+
+ hwif->cable_detect = ata66_sis5513;
+-
+- if (hwif->dma_base == 0)
+- return;
+-
+- hwif->ultra_mask = udma_rates[chipset_family];
+ }
+
+ static const struct ide_port_info sis5513_chipset __devinitdata = {
+ .name = "SIS5513",
+ .init_chipset = init_chipset_sis5513,
+ .init_hwif = init_hwif_sis5513,
+- .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
+- .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_NO_AUTODMA |
+- IDE_HFLAG_BOOTABLE,
++ .enablebits = { {0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04} },
++ .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_NO_AUTODMA,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ };
+
+ static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+- return ide_setup_pci_device(dev, &sis5513_chipset);
++ struct ide_port_info d = sis5513_chipset;
++ u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f };
++
++ if (sis_find_family(dev) == 0)
++ return -ENOTSUPP;
++
++ d.udma_mask = udma_rates[chipset_family];
++
++ return ide_setup_pci_device(dev, &d);
+ }
+
+ static const struct pci_device_id sis5513_pci_tbl[] = {
+diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
+index ee261ae..40b3eeb 100644
+--- a/drivers/ide/pci/sl82c105.c
++++ b/drivers/ide/pci/sl82c105.c
+@@ -328,8 +328,11 @@ static const struct ide_port_info sl82c105_chipset __devinitdata = {
+ .enablebits = {{0x40,0x01,0x01}, {0x40,0x10,0x10}},
+ .host_flags = IDE_HFLAG_IO_32BIT |
+ IDE_HFLAG_UNMASK_IRQS |
+- IDE_HFLAG_NO_AUTODMA |
+- IDE_HFLAG_BOOTABLE,
++/* FIXME: check for Compatibility mode in generic IDE PCI code */
++#if defined(CONFIG_LOPEC) || defined(CONFIG_SANDPOINT)
++ IDE_HFLAG_FORCE_LEGACY_IRQS |
++#endif
++ IDE_HFLAG_NO_AUTODMA,
+ .pio_mask = ATA_PIO5,
+ };
+
+diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
+index 65f4c2f..eab557c 100644
+--- a/drivers/ide/pci/slc90e66.c
++++ b/drivers/ide/pci/slc90e66.c
+@@ -27,9 +27,9 @@ static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ unsigned long flags;
+ u16 master_data;
+ u8 slave_data;
+- int control = 0;
++ int control = 0;
+ /* ISP RTC */
+- static const u8 timings[][2]= {
++ static const u8 timings[][2] = {
+ { 0, 0 },
+ { 0, 0 },
+ { 1, 0 },
+@@ -136,8 +136,8 @@ static void __devinit init_hwif_slc90e66(ide_hwif_t *hwif)
+ static const struct ide_port_info slc90e66_chipset __devinitdata = {
+ .name = "SLC90E66",
+ .init_hwif = init_hwif_slc90e66,
+- .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+- .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
++ .enablebits = { {0x41, 0x80, 0x80}, {0x43, 0x80, 0x80} },
++ .host_flags = IDE_HFLAG_LEGACY_IRQS,
+ .pio_mask = ATA_PIO4,
+ .swdma_mask = ATA_SWDMA2_ONLY,
+ .mwdma_mask = ATA_MWDMA12_ONLY,
+diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c
+index 2ef2ed2..c154351 100644
+--- a/drivers/ide/pci/tc86c001.c
++++ b/drivers/ide/pci/tc86c001.c
+@@ -18,20 +18,20 @@ static void tc86c001_set_mode(ide_drive_t *drive, const u8 speed)
+ u16 mode, scr = inw(scr_port);
+
+ switch (speed) {
+- case XFER_UDMA_4: mode = 0x00c0; break;
+- case XFER_UDMA_3: mode = 0x00b0; break;
+- case XFER_UDMA_2: mode = 0x00a0; break;
+- case XFER_UDMA_1: mode = 0x0090; break;
+- case XFER_UDMA_0: mode = 0x0080; break;
+- case XFER_MW_DMA_2: mode = 0x0070; break;
+- case XFER_MW_DMA_1: mode = 0x0060; break;
+- case XFER_MW_DMA_0: mode = 0x0050; break;
+- case XFER_PIO_4: mode = 0x0400; break;
+- case XFER_PIO_3: mode = 0x0300; break;
+- case XFER_PIO_2: mode = 0x0200; break;
+- case XFER_PIO_1: mode = 0x0100; break;
+- case XFER_PIO_0:
+- default: mode = 0x0000; break;
++ case XFER_UDMA_4: mode = 0x00c0; break;
++ case XFER_UDMA_3: mode = 0x00b0; break;
++ case XFER_UDMA_2: mode = 0x00a0; break;
++ case XFER_UDMA_1: mode = 0x0090; break;
++ case XFER_UDMA_0: mode = 0x0080; break;
++ case XFER_MW_DMA_2: mode = 0x0070; break;
++ case XFER_MW_DMA_1: mode = 0x0060; break;
++ case XFER_MW_DMA_0: mode = 0x0050; break;
++ case XFER_PIO_4: mode = 0x0400; break;
++ case XFER_PIO_3: mode = 0x0300; break;
++ case XFER_PIO_2: mode = 0x0200; break;
++ case XFER_PIO_1: mode = 0x0100; break;
++ case XFER_PIO_0:
++ default: mode = 0x0000; break;
+ }
+
+ scr &= (speed < XFER_MW_DMA_0) ? 0xf8ff : 0xff0f;
+@@ -126,40 +126,6 @@ static void tc86c001_dma_start(ide_drive_t *drive)
+ ide_dma_start(drive);
+ }
+
+-static int tc86c001_busproc(ide_drive_t *drive, int state)
+-{
+- ide_hwif_t *hwif = HWIF(drive);
+- unsigned long sc_base = hwif->config_data;
+- u16 scr1;
+-
+- /* System Control 1 Register bit 11 (ATA Hard Reset) read */
+- scr1 = inw(sc_base + 0x00);
+-
+- switch (state) {
+- case BUSSTATE_ON:
+- if (!(scr1 & 0x0800))
+- return 0;
+- scr1 &= ~0x0800;
+-
+- hwif->drives[0].failures = hwif->drives[1].failures = 0;
+- break;
+- case BUSSTATE_OFF:
+- if (scr1 & 0x0800)
+- return 0;
+- scr1 |= 0x0800;
+-
+- hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
+- hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
+- break;
+- default:
+- return -EINVAL;
+- }
+-
+- /* System Control 1 Register bit 11 (ATA Hard Reset) write */
+- outw(scr1, sc_base + 0x00);
+- return 0;
+-}
+-
+ static u8 __devinit tc86c001_cable_detect(ide_hwif_t *hwif)
+ {
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+@@ -194,8 +160,6 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
+ hwif->set_pio_mode = &tc86c001_set_pio_mode;
+ hwif->set_dma_mode = &tc86c001_set_mode;
+
+- hwif->busproc = &tc86c001_busproc;
+-
+ hwif->cable_detect = tc86c001_cable_detect;
+
+ if (!hwif->dma_base)
+diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c
+index a67d02a..3316b19 100644
+--- a/drivers/ide/pci/triflex.c
++++ b/drivers/ide/pci/triflex.c
+@@ -97,7 +97,6 @@ static const struct ide_port_info triflex_device __devinitdata = {
+ .name = "TRIFLEX",
+ .init_hwif = init_hwif_triflex,
+ .enablebits = {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}},
+- .host_flags = IDE_HFLAG_BOOTABLE,
+ .pio_mask = ATA_PIO4,
+ .swdma_mask = ATA_SWDMA2,
+ .mwdma_mask = ATA_MWDMA2,
+diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c
+index de750f7..2b8f3a2 100644
+--- a/drivers/ide/pci/trm290.c
++++ b/drivers/ide/pci/trm290.c
+@@ -337,7 +337,6 @@ static const struct ide_port_info trm290_chipset __devinitdata = {
+ IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+ #endif
+ IDE_HFLAG_NO_AUTODMA |
+- IDE_HFLAG_BOOTABLE |
+ IDE_HFLAG_NO_LBA48,
+ };
+
+diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
+index 9004e75..cff3caf 100644
+--- a/drivers/ide/pci/via82cxxx.c
++++ b/drivers/ide/pci/via82cxxx.c
+@@ -429,11 +429,9 @@ static const struct ide_port_info via82cxxx_chipset __devinitdata = {
+ .init_hwif = init_hwif_via82cxxx,
+ .enablebits = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } },
+ .host_flags = IDE_HFLAG_PIO_NO_BLACKLIST |
+- IDE_HFLAG_PIO_NO_DOWNGRADE |
+ IDE_HFLAG_ABUSE_SET_DMA_MODE |
+ IDE_HFLAG_POST_SET_MODE |
+- IDE_HFLAG_IO_32BIT |
+- IDE_HFLAG_BOOTABLE,
++ IDE_HFLAG_IO_32BIT,
+ .pio_mask = ATA_PIO5,
+ .swdma_mask = ATA_SWDMA2,
+ .mwdma_mask = ATA_MWDMA2,
+diff --git a/drivers/ide/ppc/mpc8xx.c b/drivers/ide/ppc/mpc8xx.c
+index ebaba01..467656f 100644
+--- a/drivers/ide/ppc/mpc8xx.c
++++ b/drivers/ide/ppc/mpc8xx.c
+@@ -36,6 +36,8 @@
+ #include <asm/machdep.h>
+ #include <asm/irq.h>
+
++#define DRV_NAME "ide-mpc8xx"
++
+ static int identify (volatile u8 *p);
+ static void print_fixed (volatile u8 *p);
+ static void print_funcid (int func);
+@@ -99,32 +101,6 @@ static int _slot_ = -1; /* will be read from PCMCIA registers */
+ /* Make clock cycles and always round up */
+ #define PCMCIA_MK_CLKS( t, T ) (( (t) * ((T)/1000000) + 999U ) / 1000U )
+
+-
+-
+-/*
+- * IDE stuff.
+- */
+-static int
+-m8xx_ide_default_irq(unsigned long base)
+-{
+-#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
+- if (base >= MAX_HWIFS)
+- return 0;
+-
+- printk("[%d] m8xx_ide_default_irq %d\n",__LINE__,ioport_dsc[base].irq);
+-
+- return (ioport_dsc[base].irq);
+-#else
+- return 9;
+-#endif
+-}
+-
+-static unsigned long
+-m8xx_ide_default_io_base(int index)
+-{
+- return index;
+-}
+-
+ #define M8XX_PCMCIA_CD2(slot) (0x10000000 >> (slot << 4))
+ #define M8XX_PCMCIA_CD1(slot) (0x08000000 >> (slot << 4))
+
+@@ -149,12 +125,11 @@ static int pcmcia_schlvl = PCMCIA_SCHLVL;
+ */
+
+ /*
+- * m8xx_ide_init_hwif_ports for a direct IDE interface _using_
++ * m8xx_ide_init_ports() for a direct IDE interface _using_
++ * MPC8xx's internal PCMCIA interface
+ */
+ #if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT)
+-static void
+-m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+- unsigned long ctrl_port, int *irq)
++static int __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
+ {
+ unsigned long *p = hw->io_ports;
+ int i;
+@@ -173,8 +148,6 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+ unsigned long base;
+
+ *p = 0;
+- if (irq)
+- *irq = 0;
+
+ pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia));
+
+@@ -211,6 +184,13 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+ pcmcia_phy_base, pcmcia_phy_end,
+ pcmcia_phy_end - pcmcia_phy_base);
+
++ if (!request_mem_region(pcmcia_phy_base,
++ pcmcia_phy_end - pcmcia_phy_base,
++ DRV_NAME)) {
++ printk(KERN_ERR "%s: resources busy\n", DRV_NAME);
++ return -EBUSY;
++ }
++
+ pcmcia_base=(unsigned long)ioremap(pcmcia_phy_base,
+ pcmcia_phy_end-pcmcia_phy_base);
+
+@@ -248,9 +228,6 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+ }
+ }
+
+- if (data_port >= MAX_HWIFS)
+- return;
+-
+ if (_slot_ == -1) {
+ printk ("PCMCIA slot has not been defined! Using A as default\n");
+ _slot_ = 0;
+@@ -268,7 +245,7 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+ if (pcmp->pcmc_pipr & (M8XX_PCMCIA_CD1(_slot_)|M8XX_PCMCIA_CD2(_slot_))) {
+ printk ("No card in slot %c: PIPR=%08x\n",
+ 'A' + _slot_, (u32) pcmp->pcmc_pipr);
+- return; /* No card in slot */
++ return -ENODEV; /* No card in slot */
+ }
+
+ check_ide_device (pcmcia_base);
+@@ -292,11 +269,13 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+ *p++ = base + ioport_dsc[data_port].reg_off[i];
+ }
+
+- if (irq) {
++ hw->irq = ioport_dsc[data_port].irq;
++ hw->ack_intr = (ide_ack_intr_t *)ide_interrupt_ack;
++
+ #ifdef CONFIG_IDE_8xx_PCCARD
++ {
+ unsigned int reg;
+
+- *irq = ioport_dsc[data_port].irq;
+ if (_slot_)
+ pgcrx = &((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pgcrb;
+ else
+@@ -306,14 +285,8 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+ reg |= mk_int_int_mask (pcmcia_schlvl) << 24;
+ reg |= mk_int_int_mask (pcmcia_schlvl) << 16;
+ *pgcrx = reg;
+-#else /* direct connected IDE drive, i.e. external IRQ, not the PCMCIA irq */
+- *irq = ioport_dsc[data_port].irq;
+-#endif /* CONFIG_IDE_8xx_PCCARD */
+ }
+-
+- ide_hwifs[data_port].pio_mask = ATA_PIO4;
+- ide_hwifs[data_port].set_pio_mode = m8xx_ide_set_pio_mode;
+- ide_hwifs[data_port].ack_intr = (ide_ack_intr_t *)ide_interrupt_ack;
++#endif /* CONFIG_IDE_8xx_PCCARD */
+
+ /* Enable Harddisk Interrupt,
+ * and make it edge sensitive
+@@ -329,16 +302,17 @@ m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+ /* Enable falling edge irq */
+ pcmp->pcmc_per = 0x100000 >> (16 * _slot_);
+ #endif /* CONFIG_IDE_8xx_PCCARD */
+-} /* m8xx_ide_init_hwif_ports() using 8xx internal PCMCIA interface */
++
++ return 0;
++}
+ #endif /* CONFIG_IDE_8xx_PCCARD || CONFIG_IDE_8xx_DIRECT */
+
+ /*
+- * m8xx_ide_init_hwif_ports for a direct IDE interface _not_ using
++ * m8xx_ide_init_ports() for a direct IDE interface _not_ using
+ * MPC8xx's internal PCMCIA interface
+ */
+ #if defined(CONFIG_IDE_EXT_DIRECT)
+-void m8xx_ide_init_hwif_ports (hw_regs_t *hw,
+- unsigned long data_port, unsigned long ctrl_port, int *irq)
++static int __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
+ {
+ unsigned long *p = hw->io_ports;
+ int i;
+@@ -349,8 +323,6 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw,
+ unsigned long base;
+
+ *p = 0;
+- if (irq)
+- *irq = 0;
+
+ if (!ide_base) {
+
+@@ -363,7 +335,12 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw,
+ printk ("IDE phys mem : %08x...%08x (size %08x)\n",
+ ide_phy_base, ide_phy_end,
+ ide_phy_end - ide_phy_base);
+-
++
++ if (!request_mem_region(ide_phy_base, 0x200, DRV_NAME)) {
++ printk(KERN_ERR "%s: resources busy\n", DRV_NAME);
++ return -EBUSY;
++ }
++
+ ide_base=(unsigned long)ioremap(ide_phy_base,
+ ide_phy_end-ide_phy_base);
+
+@@ -372,9 +349,6 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw,
+ #endif
+ }
+
+- if (data_port >= MAX_HWIFS)
+- return;
+-
+ base = ide_base + ioport_dsc[data_port].base_off;
+ #ifdef DEBUG
+ printk ("base: %08x + %08x = %08x\n",
+@@ -392,14 +366,9 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw,
+ *p++ = base + ioport_dsc[data_port].reg_off[i];
+ }
+
+- if (irq) {
+- /* direct connected IDE drive, i.e. external IRQ */
+- *irq = ioport_dsc[data_port].irq;
+- }
+-
+- ide_hwifs[data_port].pio_mask = ATA_PIO4;
+- ide_hwifs[data_port].set_pio_mode = m8xx_ide_set_pio_mode;
+- ide_hwifs[data_port].ack_intr = (ide_ack_intr_t *)ide_interrupt_ack;
++ /* direct connected IDE drive, i.e. external IRQ */
++ hw->irq = ioport_dsc[data_port].irq;
++ hw->ack_intr = (ide_ack_intr_t *)ide_interrupt_ack;
+
+ /* Enable Harddisk Interrupt,
+ * and make it edge sensitive
+@@ -407,8 +376,9 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw,
+ /* (11-18) Set edge detect for irq, no wakeup from low power mode */
+ ((immap_t *) IMAP_ADDR)->im_siu_conf.sc_siel |=
+ (0x80000000 >> ioport_dsc[data_port].irq);
+-} /* m8xx_ide_init_hwif_ports() for CONFIG_IDE_8xx_DIRECT */
+
++ return 0;
++}
+ #endif /* CONFIG_IDE_8xx_DIRECT */
+
+
+@@ -829,21 +799,35 @@ static int identify (volatile u8 *p)
+ return (0); /* don't know */
+ }
+
+-void m8xx_ide_init(void)
+-{
+- ppc_ide_md.default_irq = m8xx_ide_default_irq;
+- ppc_ide_md.default_io_base = m8xx_ide_default_io_base;
+- ppc_ide_md.ide_init_hwif = m8xx_ide_init_hwif_ports;
+-}
+-
+ static int __init mpc8xx_ide_probe(void)
+ {
++ hw_regs_t hw;
+ u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+
+ #ifdef IDE0_BASE_OFFSET
+- idx[0] = 0;
++ memset(&hw, 0, sizeof(hw));
++ if (!m8xx_ide_init_ports(&hw, 0)) {
++ ide_hwif_t *hwif = &ide_hwifs[0];
++
++ ide_init_port_hw(hwif, &hw);
++ hwif->mmio = 1;
++ hwif->pio_mask = ATA_PIO4;
++ hwif->set_pio_mode = m8xx_ide_set_pio_mode;
++
++ idx[0] = 0;
++ }
+ #ifdef IDE1_BASE_OFFSET
+- idx[1] = 1;
++ memset(&hw, 0, sizeof(hw));
++ if (!m8xx_ide_init_ports(&hw, 1)) {
++ ide_hwif_t *mate = &ide_hwifs[1];
++
++ ide_init_port_hw(mate, &hw);
++ mate->mmio = 1;
++ mate->pio_mask = ATA_PIO4;
++ mate->set_pio_mode = m8xx_ide_set_pio_mode;
++
++ idx[1] = 1;
++ }
+ #endif
+ #endif
+
+diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
+index d9ca52e..177961e 100644
+--- a/drivers/ide/ppc/pmac.c
++++ b/drivers/ide/ppc/pmac.c
+@@ -79,9 +79,6 @@ typedef struct pmac_ide_hwif {
+
+ } pmac_ide_hwif_t;
+
+-static pmac_ide_hwif_t pmac_ide[MAX_HWIFS];
+-static int pmac_ide_count;
+-
+ enum {
+ controller_ohare, /* OHare based */
+ controller_heathrow, /* Heathrow/Paddington */
+@@ -419,38 +416,8 @@ static void pmac_ide_kauai_selectproc(ide_drive_t *drive);
+
+ #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
+
+-/*
+- * N.B. this can't be an initfunc, because the media-bay task can
+- * call ide_[un]register at any time.
+- */
+-void
+-pmac_ide_init_hwif_ports(hw_regs_t *hw,
+- unsigned long data_port, unsigned long ctrl_port,
+- int *irq)
+-{
+- int i, ix;
+-
+- if (data_port == 0)
+- return;
+-
+- for (ix = 0; ix < MAX_HWIFS; ++ix)
+- if (data_port == pmac_ide[ix].regbase)
+- break;
+-
+- if (ix >= MAX_HWIFS)
+- return; /* not an IDE PMAC interface */
+-
+- for (i = 0; i < 8; ++i)
+- hw->io_ports[i] = data_port + i * 0x10;
+- hw->io_ports[8] = data_port + 0x160;
+-
+- if (irq != NULL)
+- *irq = pmac_ide[ix].irq;
+-
+- hw->dev = &pmac_ide[ix].mdev->ofdev.dev;
+-}
+-
+-#define PMAC_IDE_REG(x) ((void __iomem *)(IDE_DATA_REG+(x)))
++#define PMAC_IDE_REG(x) \
++ ((void __iomem *)((drive)->hwif->io_ports[IDE_DATA_OFFSET] + (x)))
+
+ /*
+ * Apply the timings of the proper unit (master/slave) to the shared
+@@ -886,58 +853,6 @@ sanitize_timings(pmac_ide_hwif_t *pmif)
+ pmif->timings[2] = pmif->timings[3] = value2;
+ }
+
+-unsigned long
+-pmac_ide_get_base(int index)
+-{
+- return pmac_ide[index].regbase;
+-}
+-
+-int
+-pmac_ide_check_base(unsigned long base)
+-{
+- int ix;
+-
+- for (ix = 0; ix < MAX_HWIFS; ++ix)
+- if (base == pmac_ide[ix].regbase)
+- return ix;
+- return -1;
+-}
+-
+-int
+-pmac_ide_get_irq(unsigned long base)
+-{
+- int ix;
+-
+- for (ix = 0; ix < MAX_HWIFS; ++ix)
+- if (base == pmac_ide[ix].regbase)
+- return pmac_ide[ix].irq;
+- return 0;
+-}
+-
+-static int ide_majors[] = { 3, 22, 33, 34, 56, 57 };
+-
+-dev_t __init
+-pmac_find_ide_boot(char *bootdevice, int n)
+-{
+- int i;
+-
+- /*
+- * Look through the list of IDE interfaces for this one.
+- */
+- for (i = 0; i < pmac_ide_count; ++i) {
+- char *name;
+- if (!pmac_ide[i].node || !pmac_ide[i].node->full_name)
+- continue;
+- name = pmac_ide[i].node->full_name;
+- if (memcmp(name, bootdevice, n) == 0 && name[n] == 0) {
+- /* XXX should cope with the 2nd drive as well... */
+- return MKDEV(ide_majors[i], 0);
+- }
+- }
+-
+- return 0;
+-}
+-
+ /* Suspend call back, should be called after the child devices
+ * have actually been suspended
+ */
+@@ -1006,7 +921,6 @@ pmac_ide_do_resume(ide_hwif_t *hwif)
+ static const struct ide_port_info pmac_port_info = {
+ .chipset = ide_pmac,
+ .host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA |
+- IDE_HFLAG_PIO_NO_DOWNGRADE |
+ IDE_HFLAG_POST_SET_MODE |
+ IDE_HFLAG_NO_DMA | /* no SFF-style DMA */
+ IDE_HFLAG_UNMASK_IRQS,
+@@ -1088,7 +1002,8 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw)
+ if (np->parent && np->parent->name
+ && strcasecmp(np->parent->name, "media-bay") == 0) {
+ #ifdef CONFIG_PMAC_MEDIABAY
+- media_bay_set_ide_infos(np->parent, pmif->regbase, pmif->irq, hwif->index);
++ media_bay_set_ide_infos(np->parent, pmif->regbase, pmif->irq,
++ hwif);
+ #endif /* CONFIG_PMAC_MEDIABAY */
+ pmif->mediabay = 1;
+ if (!bidp)
+@@ -1119,7 +1034,6 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw)
+ hwif->hwif_data = pmif;
+ ide_init_port_hw(hwif, hw);
+ hwif->noprobe = pmif->mediabay;
+- hwif->hold = pmif->mediabay;
+ hwif->cbl = pmif->cable_80 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+ hwif->set_pio_mode = pmac_ide_set_pio_mode;
+ if (pmif->kind == controller_un_ata6
+@@ -1154,6 +1068,15 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw)
+ return 0;
+ }
+
++static void __devinit pmac_ide_init_ports(hw_regs_t *hw, unsigned long base)
++{
++ int i;
++
++ for (i = 0; i < 8; ++i)
++ hw->io_ports[i] = base + i * 0x10;
++ hw->io_ports[8] = base + 0x160;
++}
++
+ /*
+ * Attach to a macio probed interface
+ */
+@@ -1162,35 +1085,36 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
+ {
+ void __iomem *base;
+ unsigned long regbase;
+- int irq;
+ ide_hwif_t *hwif;
+ pmac_ide_hwif_t *pmif;
+- int i, rc;
++ int irq, rc;
+ hw_regs_t hw;
+
+- i = 0;
+- while (i < MAX_HWIFS && (ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0
+- || pmac_ide[i].node != NULL))
+- ++i;
+- if (i >= MAX_HWIFS) {
++ pmif = kzalloc(sizeof(*pmif), GFP_KERNEL);
++ if (pmif == NULL)
++ return -ENOMEM;
++
++ hwif = ide_find_port();
++ if (hwif == NULL) {
+ printk(KERN_ERR "ide-pmac: MacIO interface attach with no slot\n");
+ printk(KERN_ERR " %s\n", mdev->ofdev.node->full_name);
+- return -ENODEV;
++ rc = -ENODEV;
++ goto out_free_pmif;
+ }
+
+- pmif = &pmac_ide[i];
+- hwif = &ide_hwifs[i];
+-
+ if (macio_resource_count(mdev) == 0) {
+- printk(KERN_WARNING "ide%d: no address for %s\n",
+- i, mdev->ofdev.node->full_name);
+- return -ENXIO;
++ printk(KERN_WARNING "ide-pmac: no address for %s\n",
++ mdev->ofdev.node->full_name);
++ rc = -ENXIO;
++ goto out_free_pmif;
+ }
+
+ /* Request memory resource for IO ports */
+ if (macio_request_resource(mdev, 0, "ide-pmac (ports)")) {
+- printk(KERN_ERR "ide%d: can't request mmio resource !\n", i);
+- return -EBUSY;
++ printk(KERN_ERR "ide-pmac: can't request MMIO resource for "
++ "%s!\n", mdev->ofdev.node->full_name);
++ rc = -EBUSY;
++ goto out_free_pmif;
+ }
+
+ /* XXX This is bogus. Should be fixed in the registry by checking
+@@ -1199,8 +1123,8 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
+ * where that happens though...
+ */
+ if (macio_irq_count(mdev) == 0) {
+- printk(KERN_WARNING "ide%d: no intrs for device %s, using 13\n",
+- i, mdev->ofdev.node->full_name);
++ printk(KERN_WARNING "ide-pmac: no intrs for device %s, using "
++ "13\n", mdev->ofdev.node->full_name);
+ irq = irq_create_mapping(NULL, 13);
+ } else
+ irq = macio_irq(mdev, 0);
+@@ -1218,7 +1142,9 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
+ #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+ if (macio_resource_count(mdev) >= 2) {
+ if (macio_request_resource(mdev, 1, "ide-pmac (dma)"))
+- printk(KERN_WARNING "ide%d: can't request DMA resource !\n", i);
++ printk(KERN_WARNING "ide-pmac: can't request DMA "
++ "resource for %s!\n",
++ mdev->ofdev.node->full_name);
+ else
+ pmif->dma_regs = ioremap(macio_resource_start(mdev, 1), 0x1000);
+ } else
+@@ -1227,7 +1153,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
+ dev_set_drvdata(&mdev->ofdev.dev, hwif);
+
+ memset(&hw, 0, sizeof(hw));
+- pmac_ide_init_hwif_ports(&hw, pmif->regbase, 0, NULL);
++ pmac_ide_init_ports(&hw, pmif->regbase);
+ hw.irq = irq;
+ hw.dev = &mdev->ofdev.dev;
+
+@@ -1240,11 +1166,15 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
+ iounmap(pmif->dma_regs);
+ macio_release_resource(mdev, 1);
+ }
+- memset(pmif, 0, sizeof(*pmif));
+ macio_release_resource(mdev, 0);
++ kfree(pmif);
+ }
+
+ return rc;
++
++out_free_pmif:
++ kfree(pmif);
++ return rc;
+ }
+
+ static int
+@@ -1289,7 +1219,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
+ pmac_ide_hwif_t *pmif;
+ void __iomem *base;
+ unsigned long rbase, rlen;
+- int i, rc;
++ int rc;
+ hw_regs_t hw;
+
+ np = pci_device_to_OF_node(pdev);
+@@ -1297,30 +1227,32 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
+ printk(KERN_ERR "ide-pmac: cannot find MacIO node for Kauai ATA interface\n");
+ return -ENODEV;
+ }
+- i = 0;
+- while (i < MAX_HWIFS && (ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0
+- || pmac_ide[i].node != NULL))
+- ++i;
+- if (i >= MAX_HWIFS) {
++
++ pmif = kzalloc(sizeof(*pmif), GFP_KERNEL);
++ if (pmif == NULL)
++ return -ENOMEM;
++
++ hwif = ide_find_port();
++ if (hwif == NULL) {
+ printk(KERN_ERR "ide-pmac: PCI interface attach with no slot\n");
+ printk(KERN_ERR " %s\n", np->full_name);
+- return -ENODEV;
++ rc = -ENODEV;
++ goto out_free_pmif;
+ }
+
+- pmif = &pmac_ide[i];
+- hwif = &ide_hwifs[i];
+-
+ if (pci_enable_device(pdev)) {
+- printk(KERN_WARNING "ide%i: Can't enable PCI device for %s\n",
+- i, np->full_name);
+- return -ENXIO;
++ printk(KERN_WARNING "ide-pmac: Can't enable PCI device for "
++ "%s\n", np->full_name);
++ rc = -ENXIO;
++ goto out_free_pmif;
+ }
+ pci_set_master(pdev);
+
+ if (pci_request_regions(pdev, "Kauai ATA")) {
+- printk(KERN_ERR "ide%d: Cannot obtain PCI resources for %s\n",
+- i, np->full_name);
+- return -ENXIO;
++ printk(KERN_ERR "ide-pmac: Cannot obtain PCI resources for "
++ "%s\n", np->full_name);
++ rc = -ENXIO;
++ goto out_free_pmif;
+ }
+
+ hwif->dev = &pdev->dev;
+@@ -1341,7 +1273,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
+ pci_set_drvdata(pdev, hwif);
+
+ memset(&hw, 0, sizeof(hw));
+- pmac_ide_init_hwif_ports(&hw, pmif->regbase, 0, NULL);
++ pmac_ide_init_ports(&hw, pmif->regbase);
+ hw.irq = pdev->irq;
+ hw.dev = &pdev->dev;
+
+@@ -1350,11 +1282,15 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
+ /* The inteface is released to the common IDE layer */
+ pci_set_drvdata(pdev, NULL);
+ iounmap(base);
+- memset(pmif, 0, sizeof(*pmif));
+ pci_release_regions(pdev);
++ kfree(pmif);
+ }
+
+ return rc;
++
++out_free_pmif:
++ kfree(pmif);
++ return rc;
+ }
+
+ static int
+diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
+index 634e3f6..6302010 100644
+--- a/drivers/ide/setup-pci.c
++++ b/drivers/ide/setup-pci.c
+@@ -20,84 +20,6 @@
+ #include <asm/io.h>
+ #include <asm/irq.h>
+
+-
+-/**
+- * ide_match_hwif - match a PCI IDE against an ide_hwif
+- * @io_base: I/O base of device
+- * @bootable: set if its bootable
+- * @name: name of device
+- *
+- * Match a PCI IDE port against an entry in ide_hwifs[],
+- * based on io_base port if possible. Return the matching hwif,
+- * or a new hwif. If we find an error (clashing, out of devices, etc)
+- * return NULL
+- *
+- * FIXME: we need to handle mmio matches here too
+- */
+-
+-static ide_hwif_t *ide_match_hwif(unsigned long io_base, u8 bootable, const char *name)
+-{
+- int h;
+- ide_hwif_t *hwif;
+-
+- /*
+- * Look for a hwif with matching io_base specified using
+- * parameters to ide_setup().
+- */
+- for (h = 0; h < MAX_HWIFS; ++h) {
+- hwif = &ide_hwifs[h];
+- if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) {
+- if (hwif->chipset == ide_forced)
+- return hwif; /* a perfect match */
+- }
+- }
+- /*
+- * Look for a hwif with matching io_base default value.
+- * If chipset is "ide_unknown", then claim that hwif slot.
+- * Otherwise, some other chipset has already claimed it.. :(
+- */
+- for (h = 0; h < MAX_HWIFS; ++h) {
+- hwif = &ide_hwifs[h];
+- if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) {
+- if (hwif->chipset == ide_unknown)
+- return hwif; /* match */
+- printk(KERN_ERR "%s: port 0x%04lx already claimed by %s\n",
+- name, io_base, hwif->name);
+- return NULL; /* already claimed */
+- }
+- }
+- /*
+- * Okay, there is no hwif matching our io_base,
+- * so we'll just claim an unassigned slot.
+- * Give preference to claiming other slots before claiming ide0/ide1,
+- * just in case there's another interface yet-to-be-scanned
+- * which uses ports 1f0/170 (the ide0/ide1 defaults).
+- *
+- * Unless there is a bootable card that does not use the standard
+- * ports 1f0/170 (the ide0/ide1 defaults). The (bootable) flag.
+- */
+- if (bootable) {
+- for (h = 0; h < MAX_HWIFS; ++h) {
+- hwif = &ide_hwifs[h];
+- if (hwif->chipset == ide_unknown)
+- return hwif; /* pick an unused entry */
+- }
+- } else {
+- for (h = 2; h < MAX_HWIFS; ++h) {
+- hwif = ide_hwifs + h;
+- if (hwif->chipset == ide_unknown)
+- return hwif; /* pick an unused entry */
+- }
+- }
+- for (h = 0; h < 2 && h < MAX_HWIFS; ++h) {
+- hwif = ide_hwifs + h;
+- if (hwif->chipset == ide_unknown)
+- return hwif; /* pick an unused entry */
+- }
+- printk(KERN_ERR "%s: too many IDE interfaces, no room in table\n", name);
+- return NULL;
+-}
+-
+ /**
+ * ide_setup_pci_baseregs - place a PCI IDE controller native
+ * @dev: PCI device of interface to switch native
+@@ -105,13 +27,13 @@ static ide_hwif_t *ide_match_hwif(unsigned long io_base, u8 bootable, const char
+ *
+ * We attempt to place the PCI interface into PCI native mode. If
+ * we succeed the BARs are ok and the controller is in PCI mode.
+- * Returns 0 on success or an errno code.
++ * Returns 0 on success or an errno code.
+ *
+ * FIXME: if we program the interface and then fail to set the BARS
+ * we don't switch it back to legacy mode. Do we actually care ??
+ */
+-
+-static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name)
++
++static int ide_setup_pci_baseregs(struct pci_dev *dev, const char *name)
+ {
+ u8 progif = 0;
+
+@@ -218,7 +140,6 @@ void ide_setup_pci_noise(struct pci_dev *dev, const struct ide_port_info *d)
+ " PCI slot %s\n", d->name, dev->vendor, dev->device,
+ dev->revision, pci_name(dev));
+ }
+-
+ EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
+
+
+@@ -231,7 +152,7 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
+ * but if that fails then we only need IO space. The PCI code should
+ * have setup the proper resources for us already for controllers in
+ * legacy mode.
+- *
++ *
+ * Returns zero on success or an error code
+ */
+
+@@ -290,8 +211,8 @@ static int ide_pci_configure(struct pci_dev *dev, const struct ide_port_info *d)
+ * Maybe the user deliberately *disabled* the device,
+ * but we'll eventually ignore it again if no drives respond.
+ */
+- if (ide_setup_pci_baseregs(dev, d->name) || pci_write_config_word(dev, PCI_COMMAND, pcicmd|PCI_COMMAND_IO))
+- {
++ if (ide_setup_pci_baseregs(dev, d->name) ||
++ pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_IO)) {
+ printk(KERN_INFO "%s: device disabled (BIOS)\n", d->name);
+ return -ENODEV;
+ }
+@@ -312,26 +233,24 @@ static int ide_pci_configure(struct pci_dev *dev, const struct ide_port_info *d)
+ * @d: IDE port info
+ * @bar: BAR number
+ *
+- * Checks if a BAR is configured and points to MMIO space. If so
+- * print an error and return an error code. Otherwise return 0
++ * Checks if a BAR is configured and points to MMIO space. If so,
++ * return an error code. Otherwise return 0
+ */
+
+-static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *d, int bar)
++static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *d,
++ int bar)
+ {
+ ulong flags = pci_resource_flags(dev, bar);
+-
++
+ /* Unconfigured ? */
+ if (!flags || pci_resource_len(dev, bar) == 0)
+ return 0;
+
+- /* I/O space */
+- if(flags & PCI_BASE_ADDRESS_IO_MASK)
++ /* I/O space */
++ if (flags & IORESOURCE_IO)
+ return 0;
+-
++
+ /* Bad */
+- printk(KERN_ERR "%s: IO baseregs (BIOS) are reported "
+- "as MEM, report to "
+- "<andre at linux-ide.org>.\n", d->name);
+ return -EINVAL;
+ }
+
+@@ -355,15 +274,16 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev,
+ {
+ unsigned long ctl = 0, base = 0;
+ ide_hwif_t *hwif;
+- u8 bootable = (d->host_flags & IDE_HFLAG_BOOTABLE) ? 1 : 0;
+- u8 oldnoprobe = 0;
+ struct hw_regs_s hw;
+
+ if ((d->host_flags & IDE_HFLAG_ISA_PORTS) == 0) {
+- /* Possibly we should fail if these checks report true */
+- ide_pci_check_iomem(dev, d, 2*port);
+- ide_pci_check_iomem(dev, d, 2*port+1);
+-
++ if (ide_pci_check_iomem(dev, d, 2 * port) ||
++ ide_pci_check_iomem(dev, d, 2 * port + 1)) {
++ printk(KERN_ERR "%s: I/O baseregs (BIOS) are reported "
++ "as MEM for port %d!\n", d->name, port);
++ return NULL;
++ }
++
+ ctl = pci_resource_start(dev, 2*port+1);
+ base = pci_resource_start(dev, 2*port);
+ if ((ctl && !base) || (base && !ctl)) {
+@@ -372,29 +292,27 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev,
+ return NULL;
+ }
+ }
+- if (!ctl)
+- {
++ if (!ctl) {
+ /* Use default values */
+ ctl = port ? 0x374 : 0x3f4;
+ base = port ? 0x170 : 0x1f0;
+ }
+- if ((hwif = ide_match_hwif(base, bootable, d->name)) == NULL)
+- return NULL; /* no room in ide_hwifs[] */
++
++ hwif = ide_find_port_slot(d);
++ if (hwif == NULL) {
++ printk(KERN_ERR "%s: too many IDE interfaces, no room in "
++ "table\n", d->name);
++ return NULL;
++ }
+
+ memset(&hw, 0, sizeof(hw));
+- hw.irq = hwif->irq ? hwif->irq : irq;
++ hw.irq = irq;
+ hw.dev = &dev->dev;
+ hw.chipset = d->chipset ? d->chipset : ide_pci;
+ ide_std_init_ports(&hw, base, ctl | 2);
+
+- if (hwif->io_ports[IDE_DATA_OFFSET] == base &&
+- hwif->io_ports[IDE_CONTROL_OFFSET] == (ctl | 2))
+- oldnoprobe = hwif->noprobe;
+-
+ ide_init_port_hw(hwif, &hw);
+
+- hwif->noprobe = oldnoprobe;
+-
+ hwif->dev = &dev->dev;
+ hwif->cds = d;
+
+@@ -425,9 +343,9 @@ void ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
+ unsigned long dma_base = ide_get_or_set_dma_base(d, hwif);
+ if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) {
+ /*
+- * Set up BM-DMA capability
++ * Set up BM-DMA capability
+ * (PnP BIOS should have done this)
+- */
++ */
+ pci_set_master(dev);
+ if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || !(pcicmd & PCI_COMMAND_MASTER)) {
+ printk(KERN_ERR "%s: %s error updating PCICMD\n",
+@@ -532,7 +450,6 @@ void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int
+ *(idx + port) = hwif->index;
+ }
+ }
+-
+ EXPORT_SYMBOL_GPL(ide_pci_setup_ports);
+
+ /*
+@@ -615,7 +532,6 @@ int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d)
+
+ return ret;
+ }
+-
+ EXPORT_SYMBOL_GPL(ide_setup_pci_device);
+
+ int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2,
+@@ -639,5 +555,4 @@ int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2,
+ out:
+ return ret;
+ }
+-
+ EXPORT_SYMBOL_GPL(ide_setup_pci_devices);
+diff --git a/drivers/ieee1394/csr.c b/drivers/ieee1394/csr.c
+index 52ac83e..c90be40 100644
+--- a/drivers/ieee1394/csr.c
++++ b/drivers/ieee1394/csr.c
+@@ -133,8 +133,7 @@ static void host_reset(struct hpsb_host *host)
+ host->csr.state &= ~0x100;
+ }
+
+- host->csr.topology_map[1] =
+- cpu_to_be32(be32_to_cpu(host->csr.topology_map[1]) + 1);
++ be32_add_cpu(&host->csr.topology_map[1], 1);
+ host->csr.topology_map[2] = cpu_to_be32(host->node_count << 16
+ | host->selfid_count);
+ host->csr.topology_map[0] =
+@@ -142,8 +141,7 @@ static void host_reset(struct hpsb_host *host)
+ | csr_crc16(host->csr.topology_map + 1,
+ host->selfid_count + 2));
+
+- host->csr.speed_map[1] =
+- cpu_to_be32(be32_to_cpu(host->csr.speed_map[1]) + 1);
++ be32_add_cpu(&host->csr.speed_map[1], 1);
+ host->csr.speed_map[0] = cpu_to_be32(0x3f1 << 16
+ | csr_crc16(host->csr.speed_map+1,
+ 0x3f1));
+diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
+index 6572211..9d19aec 100644
+--- a/drivers/ieee1394/dv1394.c
++++ b/drivers/ieee1394/dv1394.c
+@@ -2167,6 +2167,7 @@ static const struct file_operations dv1394_fops=
+ /*
+ * Export information about protocols/devices supported by this driver.
+ */
++#ifdef MODULE
+ static struct ieee1394_device_id dv1394_id_table[] = {
+ {
+ .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+@@ -2177,10 +2178,10 @@ static struct ieee1394_device_id dv1394_id_table[] = {
+ };
+
+ MODULE_DEVICE_TABLE(ieee1394, dv1394_id_table);
++#endif /* MODULE */
+
+ static struct hpsb_protocol_driver dv1394_driver = {
+- .name = "dv1394",
+- .id_table = dv1394_id_table,
++ .name = "dv1394",
+ };
+
+
+@@ -2568,7 +2569,6 @@ static int __init dv1394_init_module(void)
+
+ cdev_init(&dv1394_cdev, &dv1394_fops);
+ dv1394_cdev.owner = THIS_MODULE;
+- kobject_set_name(&dv1394_cdev.kobj, "dv1394");
+ ret = cdev_add(&dv1394_cdev, IEEE1394_DV1394_DEV, 16);
+ if (ret) {
+ printk(KERN_ERR "dv1394: unable to register character device\n");
+diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c
+index b642546..fa2bfec 100644
+--- a/drivers/ieee1394/highlevel.c
++++ b/drivers/ieee1394/highlevel.c
+@@ -339,7 +339,7 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
+ if ((alignment & 3) || (alignment > 0x800000000000ULL) ||
+ (hweight64(alignment) != 1)) {
+ HPSB_ERR("%s called with invalid alignment: 0x%048llx",
+- __FUNCTION__, (unsigned long long)alignment);
++ __func__, (unsigned long long)alignment);
+ return retval;
+ }
+
+@@ -354,7 +354,7 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
+ if (((start|end) & ~align_mask) || (start >= end) ||
+ (end > CSR1212_ALL_SPACE_END)) {
+ HPSB_ERR("%s called with invalid addresses "
+- "(start = %012Lx end = %012Lx)", __FUNCTION__,
++ "(start = %012Lx end = %012Lx)", __func__,
+ (unsigned long long)start,(unsigned long long)end);
+ return retval;
+ }
+@@ -422,7 +422,7 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
+
+ if (((start|end) & 3) || (start >= end) ||
+ (end > CSR1212_ALL_SPACE_END)) {
+- HPSB_ERR("%s called with invalid addresses", __FUNCTION__);
++ HPSB_ERR("%s called with invalid addresses", __func__);
+ return 0;
+ }
+
+diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
+index 36c747b..dcdb71a 100644
+--- a/drivers/ieee1394/ieee1394_core.c
++++ b/drivers/ieee1394/ieee1394_core.c
+@@ -242,7 +242,7 @@ int hpsb_bus_reset(struct hpsb_host *host)
+ {
+ if (host->in_bus_reset) {
+ HPSB_NOTICE("%s called while bus reset already in progress",
+- __FUNCTION__);
++ __func__);
+ return 1;
+ }
+
+@@ -373,6 +373,8 @@ static void build_speed_map(struct hpsb_host *host, int nodecount)
+ if (sid->port2 == SELFID_PORT_CHILD) cldcnt[n]++;
+
+ speedcap[n] = sid->speed;
++ if (speedcap[n] > host->csr.lnk_spd)
++ speedcap[n] = host->csr.lnk_spd;
+ n--;
+ }
+ }
+diff --git a/drivers/ieee1394/iso.h b/drivers/ieee1394/iso.h
+index b94e55e..b5de5f2 100644
+--- a/drivers/ieee1394/iso.h
++++ b/drivers/ieee1394/iso.h
+@@ -123,6 +123,8 @@ struct hpsb_iso {
+
+ /* how many times the buffer has overflowed or underflowed */
+ atomic_t overflows;
++ /* how many cycles were skipped for a given context */
++ atomic_t skips;
+
+ /* Current number of bytes lost in discarded packets */
+ int bytes_discarded;
+diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
+index 511e432..29d833e 100644
+--- a/drivers/ieee1394/nodemgr.c
++++ b/drivers/ieee1394/nodemgr.c
+@@ -18,8 +18,8 @@
+ #include <linux/moduleparam.h>
+ #include <linux/mutex.h>
+ #include <linux/freezer.h>
++#include <linux/semaphore.h>
+ #include <asm/atomic.h>
+-#include <asm/semaphore.h>
+
+ #include "csr.h"
+ #include "highlevel.h"
+@@ -701,7 +701,11 @@ static int nodemgr_bus_match(struct device * dev, struct device_driver * drv)
+ return 0;
+
+ driver = container_of(drv, struct hpsb_protocol_driver, driver);
+- for (id = driver->id_table; id->match_flags != 0; id++) {
++ id = driver->id_table;
++ if (!id)
++ return 0;
++
++ for (; id->match_flags != 0; id++) {
+ if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) &&
+ id->vendor_id != ud->vendor_id)
+ continue;
+diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
+index 969de2a..e509e13 100644
+--- a/drivers/ieee1394/ohci1394.c
++++ b/drivers/ieee1394/ohci1394.c
+@@ -149,7 +149,7 @@ printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id ,
+ /* Module Parameters */
+ static int phys_dma = 1;
+ module_param(phys_dma, int, 0444);
+-MODULE_PARM_DESC(phys_dma, "Enable physical dma (default = 1).");
++MODULE_PARM_DESC(phys_dma, "Enable physical DMA (default = 1).");
+
+ static void dma_trm_tasklet(unsigned long data);
+ static void dma_trm_reset(struct dma_trm_ctx *d);
+@@ -708,7 +708,7 @@ static void insert_packet(struct ti_ohci *ohci,
+ /* FIXME: do something about it */
+ PRINT(KERN_ERR,
+ "%s: packet data addr: %p size %Zd bytes "
+- "cross page boundary", __FUNCTION__,
++ "cross page boundary", __func__,
+ packet->data, packet->data_size);
+ }
+ #endif
+@@ -1723,6 +1723,8 @@ struct ohci_iso_xmit {
+ struct dma_prog_region prog;
+ struct ohci1394_iso_tasklet task;
+ int task_active;
++ int last_cycle;
++ atomic_t skips;
+
+ u32 ContextControlSet;
+ u32 ContextControlClear;
+@@ -1759,6 +1761,8 @@ static int ohci_iso_xmit_init(struct hpsb_iso *iso)
+ iso->hostdata = xmit;
+ xmit->ohci = iso->host->hostdata;
+ xmit->task_active = 0;
++ xmit->last_cycle = -1;
++ atomic_set(&iso->skips, 0);
+
+ dma_prog_region_init(&xmit->prog);
+
+@@ -1856,6 +1860,26 @@ static void ohci_iso_xmit_task(unsigned long data)
+ /* parse cycle */
+ cycle = le32_to_cpu(cmd->output_last.status) & 0x1FFF;
+
++ if (xmit->last_cycle > -1) {
++ int cycle_diff = cycle - xmit->last_cycle;
++ int skip;
++
++ /* unwrap */
++ if (cycle_diff < 0) {
++ cycle_diff += 8000;
++ if (cycle_diff < 0)
++ PRINT(KERN_ERR, "bogus cycle diff %d\n",
++ cycle_diff);
++ }
++
++ skip = cycle_diff - 1;
++ if (skip > 0) {
++ DBGMSG("skipped %d cycles without packet loss", skip);
++ atomic_add(skip, &iso->skips);
++ }
++ }
++ xmit->last_cycle = cycle;
++
+ /* tell the subsystem the packet has gone out */
+ hpsb_iso_packet_sent(iso, cycle, event != 0x11);
+
+@@ -1943,6 +1967,16 @@ static int ohci_iso_xmit_queue(struct hpsb_iso *iso, struct hpsb_iso_packet_info
+ prev->output_last.branchAddress = cpu_to_le32(
+ dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3);
+
++ /*
++ * Link the skip address to this descriptor itself. This causes a
++ * context to skip a cycle whenever lost cycles or FIFO overruns occur,
++ * without dropping the data at that point the application should then
++ * decide whether this is an error condition or not. Some protocols
++ * can deal with this by dropping some rate-matching padding packets.
++ */
++ next->output_more_immediate.branchAddress =
++ prev->output_last.branchAddress;
++
+ /* disable interrupt, unless required by the IRQ interval */
+ if (prev_i % iso->irq_interval) {
+ prev->output_last.control &= cpu_to_le32(~(3 << 20)); /* no interrupt */
+@@ -2089,10 +2123,8 @@ static void dma_trm_reset(struct dma_trm_ctx *d)
+
+ spin_lock_irqsave(&d->lock, flags);
+
+- list_splice(&d->fifo_list, &packet_list);
+- list_splice(&d->pending_list, &packet_list);
+- INIT_LIST_HEAD(&d->fifo_list);
+- INIT_LIST_HEAD(&d->pending_list);
++ list_splice_init(&d->fifo_list, &packet_list);
++ list_splice_init(&d->pending_list, &packet_list);
+
+ d->branchAddrPtr = NULL;
+ d->sent_ind = d->prg_ind;
+@@ -2787,7 +2819,7 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
+ d->buf_bus = kzalloc(d->num_desc * sizeof(*d->buf_bus), GFP_ATOMIC);
+
+ if (d->buf_cpu == NULL || d->buf_bus == NULL) {
+- PRINT(KERN_ERR, "Failed to allocate dma buffer");
++ PRINT(KERN_ERR, "Failed to allocate %s", "DMA buffer");
+ free_dma_rcv_ctx(d);
+ return -ENOMEM;
+ }
+@@ -2796,7 +2828,7 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
+ d->prg_bus = kzalloc(d->num_desc * sizeof(*d->prg_bus), GFP_ATOMIC);
+
+ if (d->prg_cpu == NULL || d->prg_bus == NULL) {
+- PRINT(KERN_ERR, "Failed to allocate dma prg");
++ PRINT(KERN_ERR, "Failed to allocate %s", "DMA prg");
+ free_dma_rcv_ctx(d);
+ return -ENOMEM;
+ }
+@@ -2804,7 +2836,7 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
+ d->spb = kmalloc(d->split_buf_size, GFP_ATOMIC);
+
+ if (d->spb == NULL) {
+- PRINT(KERN_ERR, "Failed to allocate split buffer");
++ PRINT(KERN_ERR, "Failed to allocate %s", "split buffer");
+ free_dma_rcv_ctx(d);
+ return -ENOMEM;
+ }
+@@ -2830,7 +2862,7 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
+ memset(d->buf_cpu[i], 0, d->buf_size);
+ } else {
+ PRINT(KERN_ERR,
+- "Failed to allocate dma buffer");
++ "Failed to allocate %s", "DMA buffer");
+ free_dma_rcv_ctx(d);
+ return -ENOMEM;
+ }
+@@ -2841,7 +2873,7 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
+ memset(d->prg_cpu[i], 0, sizeof(struct dma_cmd));
+ } else {
+ PRINT(KERN_ERR,
+- "Failed to allocate dma prg");
++ "Failed to allocate %s", "DMA prg");
+ free_dma_rcv_ctx(d);
+ return -ENOMEM;
+ }
+@@ -2902,7 +2934,7 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
+ d->prg_bus = kzalloc(d->num_desc * sizeof(*d->prg_bus), GFP_KERNEL);
+
+ if (d->prg_cpu == NULL || d->prg_bus == NULL) {
+- PRINT(KERN_ERR, "Failed to allocate at dma prg");
++ PRINT(KERN_ERR, "Failed to allocate %s", "AT DMA prg");
+ free_dma_trm_ctx(d);
+ return -ENOMEM;
+ }
+@@ -2925,7 +2957,7 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
+ memset(d->prg_cpu[i], 0, sizeof(struct at_dma_prg));
+ } else {
+ PRINT(KERN_ERR,
+- "Failed to allocate at dma prg");
++ "Failed to allocate %s", "AT DMA prg");
+ free_dma_trm_ctx(d);
+ return -ENOMEM;
+ }
+@@ -2986,22 +3018,9 @@ static struct hpsb_host_driver ohci1394_driver = {
+ * PCI Driver Interface functions *
+ ***********************************/
+
+-#define FAIL(err, fmt, args...) \
+-do { \
+- PRINT_G(KERN_ERR, fmt , ## args); \
+- ohci1394_pci_remove(dev); \
+- return err; \
+-} while (0)
+-
+-static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
+- const struct pci_device_id *ent)
+-{
+- struct hpsb_host *host;
+- struct ti_ohci *ohci; /* shortcut to currently handled device */
+- resource_size_t ohci_base;
+-
+ #ifdef CONFIG_PPC_PMAC
+- /* Necessary on some machines if ohci1394 was loaded/ unloaded before */
++static void ohci1394_pmac_on(struct pci_dev *dev)
++{
+ if (machine_is(powermac)) {
+ struct device_node *ofn = pci_device_to_OF_node(dev);
+
+@@ -3010,15 +3029,45 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
+ pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
+ }
+ }
++}
++
++static void ohci1394_pmac_off(struct pci_dev *dev)
++{
++ if (machine_is(powermac)) {
++ struct device_node *ofn = pci_device_to_OF_node(dev);
++
++ if (ofn) {
++ pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
++ pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0);
++ }
++ }
++}
++#else
++#define ohci1394_pmac_on(dev)
++#define ohci1394_pmac_off(dev)
+ #endif /* CONFIG_PPC_PMAC */
+
+- if (pci_enable_device(dev))
+- FAIL(-ENXIO, "Failed to enable OHCI hardware");
++static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
++ const struct pci_device_id *ent)
++{
++ struct hpsb_host *host;
++ struct ti_ohci *ohci; /* shortcut to currently handled device */
++ resource_size_t ohci_base;
++ int err = -ENOMEM;
++
++ ohci1394_pmac_on(dev);
++ if (pci_enable_device(dev)) {
++ PRINT_G(KERN_ERR, "Failed to enable OHCI hardware");
++ err = -ENXIO;
++ goto err;
++ }
+ pci_set_master(dev);
+
+ host = hpsb_alloc_host(&ohci1394_driver, sizeof(struct ti_ohci), &dev->dev);
+- if (!host) FAIL(-ENOMEM, "Failed to allocate host structure");
+-
++ if (!host) {
++ PRINT_G(KERN_ERR, "Failed to allocate %s", "host structure");
++ goto err;
++ }
+ ohci = host->hostdata;
+ ohci->dev = dev;
+ ohci->host = host;
+@@ -3067,15 +3116,20 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
+ (unsigned long long)pci_resource_len(dev, 0));
+
+ if (!request_mem_region(ohci_base, OHCI1394_REGISTER_SIZE,
+- OHCI1394_DRIVER_NAME))
+- FAIL(-ENOMEM, "MMIO resource (0x%llx - 0x%llx) unavailable",
++ OHCI1394_DRIVER_NAME)) {
++ PRINT_G(KERN_ERR, "MMIO resource (0x%llx - 0x%llx) unavailable",
+ (unsigned long long)ohci_base,
+ (unsigned long long)ohci_base + OHCI1394_REGISTER_SIZE);
++ goto err;
++ }
+ ohci->init_state = OHCI_INIT_HAVE_MEM_REGION;
+
+ ohci->registers = ioremap(ohci_base, OHCI1394_REGISTER_SIZE);
+- if (ohci->registers == NULL)
+- FAIL(-ENXIO, "Failed to remap registers - card not accessible");
++ if (ohci->registers == NULL) {
++ PRINT_G(KERN_ERR, "Failed to remap registers");
++ err = -ENXIO;
++ goto err;
++ }
+ ohci->init_state = OHCI_INIT_HAVE_IOMAPPING;
+ DBGMSG("Remapped memory spaces reg 0x%p", ohci->registers);
+
+@@ -3083,16 +3137,20 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
+ ohci->csr_config_rom_cpu =
+ pci_alloc_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN,
+ &ohci->csr_config_rom_bus);
+- if (ohci->csr_config_rom_cpu == NULL)
+- FAIL(-ENOMEM, "Failed to allocate buffer config rom");
++ if (ohci->csr_config_rom_cpu == NULL) {
++ PRINT_G(KERN_ERR, "Failed to allocate %s", "buffer config rom");
++ goto err;
++ }
+ ohci->init_state = OHCI_INIT_HAVE_CONFIG_ROM_BUFFER;
+
+ /* self-id dma buffer allocation */
+ ohci->selfid_buf_cpu =
+ pci_alloc_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
+ &ohci->selfid_buf_bus);
+- if (ohci->selfid_buf_cpu == NULL)
+- FAIL(-ENOMEM, "Failed to allocate DMA buffer for self-id packets");
++ if (ohci->selfid_buf_cpu == NULL) {
++ PRINT_G(KERN_ERR, "Failed to allocate %s", "self-ID buffer");
++ goto err;
++ }
+ ohci->init_state = OHCI_INIT_HAVE_SELFID_BUFFER;
+
+ if ((unsigned long)ohci->selfid_buf_cpu & 0x1fff)
+@@ -3108,28 +3166,32 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
+ if (alloc_dma_rcv_ctx(ohci, &ohci->ar_req_context,
+ DMA_CTX_ASYNC_REQ, 0, AR_REQ_NUM_DESC,
+ AR_REQ_BUF_SIZE, AR_REQ_SPLIT_BUF_SIZE,
+- OHCI1394_AsReqRcvContextBase) < 0)
+- FAIL(-ENOMEM, "Failed to allocate AR Req context");
+-
++ OHCI1394_AsReqRcvContextBase) < 0) {
++ PRINT_G(KERN_ERR, "Failed to allocate %s", "AR Req context");
++ goto err;
++ }
+ /* AR DMA response context allocation */
+ if (alloc_dma_rcv_ctx(ohci, &ohci->ar_resp_context,
+ DMA_CTX_ASYNC_RESP, 0, AR_RESP_NUM_DESC,
+ AR_RESP_BUF_SIZE, AR_RESP_SPLIT_BUF_SIZE,
+- OHCI1394_AsRspRcvContextBase) < 0)
+- FAIL(-ENOMEM, "Failed to allocate AR Resp context");
+-
++ OHCI1394_AsRspRcvContextBase) < 0) {
++ PRINT_G(KERN_ERR, "Failed to allocate %s", "AR Resp context");
++ goto err;
++ }
+ /* AT DMA request context */
+ if (alloc_dma_trm_ctx(ohci, &ohci->at_req_context,
+ DMA_CTX_ASYNC_REQ, 0, AT_REQ_NUM_DESC,
+- OHCI1394_AsReqTrContextBase) < 0)
+- FAIL(-ENOMEM, "Failed to allocate AT Req context");
+-
++ OHCI1394_AsReqTrContextBase) < 0) {
++ PRINT_G(KERN_ERR, "Failed to allocate %s", "AT Req context");
++ goto err;
++ }
+ /* AT DMA response context */
+ if (alloc_dma_trm_ctx(ohci, &ohci->at_resp_context,
+ DMA_CTX_ASYNC_RESP, 1, AT_RESP_NUM_DESC,
+- OHCI1394_AsRspTrContextBase) < 0)
+- FAIL(-ENOMEM, "Failed to allocate AT Resp context");
+-
++ OHCI1394_AsRspTrContextBase) < 0) {
++ PRINT_G(KERN_ERR, "Failed to allocate %s", "AT Resp context");
++ goto err;
++ }
+ /* Start off with a soft reset, to clear everything to a sane
+ * state. */
+ ohci_soft_reset(ohci);
+@@ -3172,9 +3234,10 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
+ * by that point.
+ */
+ if (request_irq(dev->irq, ohci_irq_handler, IRQF_SHARED,
+- OHCI1394_DRIVER_NAME, ohci))
+- FAIL(-ENOMEM, "Failed to allocate shared interrupt %d", dev->irq);
+-
++ OHCI1394_DRIVER_NAME, ohci)) {
++ PRINT_G(KERN_ERR, "Failed to allocate interrupt %d", dev->irq);
++ goto err;
++ }
+ ohci->init_state = OHCI_INIT_HAVE_IRQ;
+ ohci_initialize(ohci);
+
+@@ -3194,25 +3257,28 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
+ host->middle_addr_space = OHCI1394_MIDDLE_ADDRESS_SPACE;
+
+ /* Tell the highlevel this host is ready */
+- if (hpsb_add_host(host))
+- FAIL(-ENOMEM, "Failed to register host with highlevel");
+-
++ if (hpsb_add_host(host)) {
++ PRINT_G(KERN_ERR, "Failed to register host with highlevel");
++ goto err;
++ }
+ ohci->init_state = OHCI_INIT_DONE;
+
+ return 0;
+-#undef FAIL
++err:
++ ohci1394_pci_remove(dev);
++ return err;
+ }
+
+-static void ohci1394_pci_remove(struct pci_dev *pdev)
++static void ohci1394_pci_remove(struct pci_dev *dev)
+ {
+ struct ti_ohci *ohci;
+- struct device *dev;
++ struct device *device;
+
+- ohci = pci_get_drvdata(pdev);
++ ohci = pci_get_drvdata(dev);
+ if (!ohci)
+- return;
++ goto out;
+
+- dev = get_device(&ohci->host->device);
++ device = get_device(&ohci->host->device);
+
+ switch (ohci->init_state) {
+ case OHCI_INIT_DONE:
+@@ -3246,7 +3312,7 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
+ /* Soft reset before we start - this disables
+ * interrupts and clears linkEnable and LPS. */
+ ohci_soft_reset(ohci);
+- free_irq(ohci->dev->irq, ohci);
++ free_irq(dev->irq, ohci);
+
+ case OHCI_INIT_HAVE_TXRX_BUFFERS__MAYBE:
+ /* The ohci_soft_reset() stops all DMA contexts, so we
+@@ -3257,12 +3323,12 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
+ free_dma_trm_ctx(&ohci->at_resp_context);
+
+ case OHCI_INIT_HAVE_SELFID_BUFFER:
+- pci_free_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
++ pci_free_consistent(dev, OHCI1394_SI_DMA_BUF_SIZE,
+ ohci->selfid_buf_cpu,
+ ohci->selfid_buf_bus);
+
+ case OHCI_INIT_HAVE_CONFIG_ROM_BUFFER:
+- pci_free_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN,
++ pci_free_consistent(dev, OHCI_CONFIG_ROM_LEN,
+ ohci->csr_config_rom_cpu,
+ ohci->csr_config_rom_bus);
+
+@@ -3270,35 +3336,24 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
+ iounmap(ohci->registers);
+
+ case OHCI_INIT_HAVE_MEM_REGION:
+- release_mem_region(pci_resource_start(ohci->dev, 0),
++ release_mem_region(pci_resource_start(dev, 0),
+ OHCI1394_REGISTER_SIZE);
+
+-#ifdef CONFIG_PPC_PMAC
+- /* On UniNorth, power down the cable and turn off the chip clock
+- * to save power on laptops */
+- if (machine_is(powermac)) {
+- struct device_node* ofn = pci_device_to_OF_node(ohci->dev);
+-
+- if (ofn) {
+- pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
+- pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0);
+- }
+- }
+-#endif /* CONFIG_PPC_PMAC */
+-
+ case OHCI_INIT_ALLOC_HOST:
+- pci_set_drvdata(ohci->dev, NULL);
++ pci_set_drvdata(dev, NULL);
+ }
+
+- if (dev)
+- put_device(dev);
++ if (device)
++ put_device(device);
++out:
++ ohci1394_pmac_off(dev);
+ }
+
+ #ifdef CONFIG_PM
+-static int ohci1394_pci_suspend(struct pci_dev *pdev, pm_message_t state)
++static int ohci1394_pci_suspend(struct pci_dev *dev, pm_message_t state)
+ {
+ int err;
+- struct ti_ohci *ohci = pci_get_drvdata(pdev);
++ struct ti_ohci *ohci = pci_get_drvdata(dev);
+
+ if (!ohci) {
+ printk(KERN_ERR "%s: tried to suspend nonexisting host\n",
+@@ -3326,32 +3381,23 @@ static int ohci1394_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+ ohci_devctl(ohci->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT);
+ ohci_soft_reset(ohci);
+
+- err = pci_save_state(pdev);
++ err = pci_save_state(dev);
+ if (err) {
+ PRINT(KERN_ERR, "pci_save_state failed with %d", err);
+ return err;
+ }
+- err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
++ err = pci_set_power_state(dev, pci_choose_state(dev, state));
+ if (err)
+ DBGMSG("pci_set_power_state failed with %d", err);
+-
+-/* PowerMac suspend code comes last */
+-#ifdef CONFIG_PPC_PMAC
+- if (machine_is(powermac)) {
+- struct device_node *ofn = pci_device_to_OF_node(pdev);
+-
+- if (ofn)
+- pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
+- }
+-#endif /* CONFIG_PPC_PMAC */
++ ohci1394_pmac_off(dev);
+
+ return 0;
+ }
+
+-static int ohci1394_pci_resume(struct pci_dev *pdev)
++static int ohci1394_pci_resume(struct pci_dev *dev)
+ {
+ int err;
+- struct ti_ohci *ohci = pci_get_drvdata(pdev);
++ struct ti_ohci *ohci = pci_get_drvdata(dev);
+
+ if (!ohci) {
+ printk(KERN_ERR "%s: tried to resume nonexisting host\n",
+@@ -3360,19 +3406,10 @@ static int ohci1394_pci_resume(struct pci_dev *pdev)
+ }
+ DBGMSG("resume called");
+
+-/* PowerMac resume code comes first */
+-#ifdef CONFIG_PPC_PMAC
+- if (machine_is(powermac)) {
+- struct device_node *ofn = pci_device_to_OF_node(pdev);
+-
+- if (ofn)
+- pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
+- }
+-#endif /* CONFIG_PPC_PMAC */
+-
+- pci_set_power_state(pdev, PCI_D0);
+- pci_restore_state(pdev);
+- err = pci_enable_device(pdev);
++ ohci1394_pmac_on(dev);
++ pci_set_power_state(dev, PCI_D0);
++ pci_restore_state(dev);
++ err = pci_enable_device(dev);
+ if (err) {
+ PRINT(KERN_ERR, "pci_enable_device failed with %d", err);
+ return err;
+diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
+index 8af01ab..7aee1ac 100644
+--- a/drivers/ieee1394/pcilynx.c
++++ b/drivers/ieee1394/pcilynx.c
+@@ -226,7 +226,7 @@ static int get_phy_reg(struct ti_lynx *lynx, int addr)
+ if (addr > 15) {
+ PRINT(KERN_ERR, lynx->id,
+ "%s: PHY register address %d out of range",
+- __FUNCTION__, addr);
++ __func__, addr);
+ return -1;
+ }
+
+@@ -238,7 +238,7 @@ static int get_phy_reg(struct ti_lynx *lynx, int addr)
+
+ if (i > 10000) {
+ PRINT(KERN_ERR, lynx->id, "%s: runaway loop, aborting",
+- __FUNCTION__);
++ __func__);
+ retval = -1;
+ break;
+ }
+@@ -261,13 +261,13 @@ static int set_phy_reg(struct ti_lynx *lynx, int addr, int val)
+
+ if (addr > 15) {
+ PRINT(KERN_ERR, lynx->id,
+- "%s: PHY register address %d out of range", __FUNCTION__, addr);
++ "%s: PHY register address %d out of range", __func__, addr);
+ return -1;
+ }
+
+ if (val > 0xff) {
+ PRINT(KERN_ERR, lynx->id,
+- "%s: PHY register value %d out of range", __FUNCTION__, val);
++ "%s: PHY register value %d out of range", __func__, val);
+ return -1;
+ }
+
+@@ -287,7 +287,7 @@ static int sel_phy_reg_page(struct ti_lynx *lynx, int page)
+
+ if (page > 7) {
+ PRINT(KERN_ERR, lynx->id,
+- "%s: PHY page %d out of range", __FUNCTION__, page);
++ "%s: PHY page %d out of range", __func__, page);
+ return -1;
+ }
+
+@@ -309,7 +309,7 @@ static int sel_phy_reg_port(struct ti_lynx *lynx, int port)
+
+ if (port > 15) {
+ PRINT(KERN_ERR, lynx->id,
+- "%s: PHY port %d out of range", __FUNCTION__, port);
++ "%s: PHY port %d out of range", __func__, port);
+ return -1;
+ }
+
+@@ -738,8 +738,7 @@ static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
+ spin_lock_irqsave(&lynx->async.queue_lock, flags);
+
+ reg_write(lynx, DMA_CHAN_CTRL(CHANNEL_ASYNC_SEND), 0);
+- list_splice(&lynx->async.queue, &packet_list);
+- INIT_LIST_HEAD(&lynx->async.queue);
++ list_splice_init(&lynx->async.queue, &packet_list);
+
+ if (list_empty(&lynx->async.pcl_queue)) {
+ spin_unlock_irqrestore(&lynx->async.queue_lock, flags);
+diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
+index 37e7e10..ec2a0ad 100644
+--- a/drivers/ieee1394/raw1394.c
++++ b/drivers/ieee1394/raw1394.c
+@@ -2356,13 +2356,16 @@ static void rawiso_activity_cb(struct hpsb_iso *iso)
+ static void raw1394_iso_fill_status(struct hpsb_iso *iso,
+ struct raw1394_iso_status *stat)
+ {
++ int overflows = atomic_read(&iso->overflows);
++ int skips = atomic_read(&iso->skips);
++
+ stat->config.data_buf_size = iso->buf_size;
+ stat->config.buf_packets = iso->buf_packets;
+ stat->config.channel = iso->channel;
+ stat->config.speed = iso->speed;
+ stat->config.irq_interval = iso->irq_interval;
+ stat->n_packets = hpsb_iso_n_ready(iso);
+- stat->overflows = atomic_read(&iso->overflows);
++ stat->overflows = ((skips & 0xFFFF) << 16) | ((overflows & 0xFFFF));
+ stat->xmit_cycle = iso->xmit_cycle;
+ }
+
+@@ -2437,6 +2440,8 @@ static int raw1394_iso_get_status(struct file_info *fi, void __user * uaddr)
+
+ /* reset overflow counter */
+ atomic_set(&iso->overflows, 0);
++ /* reset skip counter */
++ atomic_set(&iso->skips, 0);
+
+ return 0;
+ }
+@@ -2935,6 +2940,7 @@ static int raw1394_release(struct inode *inode, struct file *file)
+ /*
+ * Export information about protocols/devices supported by this driver.
+ */
++#ifdef MODULE
+ static struct ieee1394_device_id raw1394_id_table[] = {
+ {
+ .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+@@ -2956,10 +2962,10 @@ static struct ieee1394_device_id raw1394_id_table[] = {
+ };
+
+ MODULE_DEVICE_TABLE(ieee1394, raw1394_id_table);
++#endif /* MODULE */
+
+ static struct hpsb_protocol_driver raw1394_driver = {
+ .name = "raw1394",
+- .id_table = raw1394_id_table,
+ };
+
+ /******************************************************************************/
+@@ -3004,7 +3010,6 @@ static int __init init_raw1394(void)
+
+ cdev_init(&raw1394_cdev, &raw1394_fops);
+ raw1394_cdev.owner = THIS_MODULE;
+- kobject_set_name(&raw1394_cdev.kobj, RAW1394_DEVICE_NAME);
+ ret = cdev_add(&raw1394_cdev, IEEE1394_RAW1394_DEV, 1);
+ if (ret) {
+ HPSB_ERR("raw1394 failed to register minor device block");
+diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
+index f53f72d..16b9d0a 100644
+--- a/drivers/ieee1394/sbp2.c
++++ b/drivers/ieee1394/sbp2.c
+@@ -615,7 +615,7 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb(
+ cmd->Current_SCpnt = Current_SCpnt;
+ list_add_tail(&cmd->list, &lu->cmd_orb_inuse);
+ } else
+- SBP2_ERR("%s: no orbs available", __FUNCTION__);
++ SBP2_ERR("%s: no orbs available", __func__);
+ spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
+ return cmd;
+ }
+@@ -1294,7 +1294,7 @@ static int sbp2_set_busy_timeout(struct sbp2_lu *lu)
+
+ data = cpu_to_be32(SBP2_BUSY_TIMEOUT_VALUE);
+ if (hpsb_node_write(lu->ne, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4))
+- SBP2_ERR("%s error", __FUNCTION__);
++ SBP2_ERR("%s error", __func__);
+ return 0;
+ }
+
+@@ -1985,11 +1985,8 @@ static int sbp2scsi_slave_alloc(struct scsi_device *sdev)
+ lu->sdev = sdev;
+ sdev->allow_restart = 1;
+
+- /*
+- * Update the dma alignment (minimum alignment requirements for
+- * start and end of DMA transfers) to be a sector
+- */
+- blk_queue_update_dma_alignment(sdev->request_queue, 511);
++ /* SBP-2 requires quadlet alignment of the data buffers. */
++ blk_queue_update_dma_alignment(sdev->request_queue, 4 - 1);
+
+ if (lu->workarounds & SBP2_WORKAROUND_INQUIRY_36)
+ sdev->inquiry_len = 36;
+diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
+index bd28adf..e24772d 100644
+--- a/drivers/ieee1394/video1394.c
++++ b/drivers/ieee1394/video1394.c
+@@ -1293,6 +1293,7 @@ static const struct file_operations video1394_fops=
+ /*
+ * Export information about protocols/devices supported by this driver.
+ */
++#ifdef MODULE
+ static struct ieee1394_device_id video1394_id_table[] = {
+ {
+ .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+@@ -1313,10 +1314,10 @@ static struct ieee1394_device_id video1394_id_table[] = {
+ };
+
+ MODULE_DEVICE_TABLE(ieee1394, video1394_id_table);
++#endif /* MODULE */
+
+ static struct hpsb_protocol_driver video1394_driver = {
+- .name = VIDEO1394_DRIVER_NAME,
+- .id_table = video1394_id_table,
++ .name = VIDEO1394_DRIVER_NAME,
+ };
+
+
+@@ -1504,7 +1505,6 @@ static int __init video1394_init_module (void)
+
+ cdev_init(&video1394_cdev, &video1394_fops);
+ video1394_cdev.owner = THIS_MODULE;
+- kobject_set_name(&video1394_cdev.kobj, VIDEO1394_DRIVER_NAME);
+ ret = cdev_add(&video1394_cdev, IEEE1394_VIDEO1394_DEV, 16);
+ if (ret) {
+ PRINT_G(KERN_ERR, "video1394: unable to get minor device block");
+diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
+index faa7ce3..a47fe64 100644
+--- a/drivers/infiniband/core/cm.c
++++ b/drivers/infiniband/core/cm.c
+@@ -467,6 +467,31 @@ static int cm_compare_private_data(u8 *private_data,
+ return memcmp(src, dst_data->data, IB_CM_COMPARE_SIZE);
+ }
+
++/*
++ * Trivial helpers to strip endian annotation and compare; the
++ * endianness doesn't actually matter since we just need a stable
++ * order for the RB tree.
++ */
++static int be32_lt(__be32 a, __be32 b)
++{
++ return (__force u32) a < (__force u32) b;
++}
++
++static int be32_gt(__be32 a, __be32 b)
++{
++ return (__force u32) a > (__force u32) b;
++}
++
++static int be64_lt(__be64 a, __be64 b)
++{
++ return (__force u64) a < (__force u64) b;
++}
++
++static int be64_gt(__be64 a, __be64 b)
++{
++ return (__force u64) a > (__force u64) b;
++}
++
+ static struct cm_id_private * cm_insert_listen(struct cm_id_private *cm_id_priv)
+ {
+ struct rb_node **link = &cm.listen_service_table.rb_node;
+@@ -492,9 +517,9 @@ static struct cm_id_private * cm_insert_listen(struct cm_id_private *cm_id_priv)
+ link = &(*link)->rb_left;
+ else if (cm_id_priv->id.device > cur_cm_id_priv->id.device)
+ link = &(*link)->rb_right;
+- else if (service_id < cur_cm_id_priv->id.service_id)
++ else if (be64_lt(service_id, cur_cm_id_priv->id.service_id))
+ link = &(*link)->rb_left;
+- else if (service_id > cur_cm_id_priv->id.service_id)
++ else if (be64_gt(service_id, cur_cm_id_priv->id.service_id))
+ link = &(*link)->rb_right;
+ else if (data_cmp < 0)
+ link = &(*link)->rb_left;
+@@ -527,9 +552,9 @@ static struct cm_id_private * cm_find_listen(struct ib_device *device,
+ node = node->rb_left;
+ else if (device > cm_id_priv->id.device)
+ node = node->rb_right;
+- else if (service_id < cm_id_priv->id.service_id)
++ else if (be64_lt(service_id, cm_id_priv->id.service_id))
+ node = node->rb_left;
+- else if (service_id > cm_id_priv->id.service_id)
++ else if (be64_gt(service_id, cm_id_priv->id.service_id))
+ node = node->rb_right;
+ else if (data_cmp < 0)
+ node = node->rb_left;
+@@ -552,13 +577,13 @@ static struct cm_timewait_info * cm_insert_remote_id(struct cm_timewait_info
+ parent = *link;
+ cur_timewait_info = rb_entry(parent, struct cm_timewait_info,
+ remote_id_node);
+- if (remote_id < cur_timewait_info->work.remote_id)
++ if (be32_lt(remote_id, cur_timewait_info->work.remote_id))
+ link = &(*link)->rb_left;
+- else if (remote_id > cur_timewait_info->work.remote_id)
++ else if (be32_gt(remote_id, cur_timewait_info->work.remote_id))
+ link = &(*link)->rb_right;
+- else if (remote_ca_guid < cur_timewait_info->remote_ca_guid)
++ else if (be64_lt(remote_ca_guid, cur_timewait_info->remote_ca_guid))
+ link = &(*link)->rb_left;
+- else if (remote_ca_guid > cur_timewait_info->remote_ca_guid)
++ else if (be64_gt(remote_ca_guid, cur_timewait_info->remote_ca_guid))
+ link = &(*link)->rb_right;
+ else
+ return cur_timewait_info;
+@@ -578,13 +603,13 @@ static struct cm_timewait_info * cm_find_remote_id(__be64 remote_ca_guid,
+ while (node) {
+ timewait_info = rb_entry(node, struct cm_timewait_info,
+ remote_id_node);
+- if (remote_id < timewait_info->work.remote_id)
++ if (be32_lt(remote_id, timewait_info->work.remote_id))
+ node = node->rb_left;
+- else if (remote_id > timewait_info->work.remote_id)
++ else if (be32_gt(remote_id, timewait_info->work.remote_id))
+ node = node->rb_right;
+- else if (remote_ca_guid < timewait_info->remote_ca_guid)
++ else if (be64_lt(remote_ca_guid, timewait_info->remote_ca_guid))
+ node = node->rb_left;
+- else if (remote_ca_guid > timewait_info->remote_ca_guid)
++ else if (be64_gt(remote_ca_guid, timewait_info->remote_ca_guid))
+ node = node->rb_right;
+ else
+ return timewait_info;
+@@ -605,13 +630,13 @@ static struct cm_timewait_info * cm_insert_remote_qpn(struct cm_timewait_info
+ parent = *link;
+ cur_timewait_info = rb_entry(parent, struct cm_timewait_info,
+ remote_qp_node);
+- if (remote_qpn < cur_timewait_info->remote_qpn)
++ if (be32_lt(remote_qpn, cur_timewait_info->remote_qpn))
+ link = &(*link)->rb_left;
+- else if (remote_qpn > cur_timewait_info->remote_qpn)
++ else if (be32_gt(remote_qpn, cur_timewait_info->remote_qpn))
+ link = &(*link)->rb_right;
+- else if (remote_ca_guid < cur_timewait_info->remote_ca_guid)
++ else if (be64_lt(remote_ca_guid, cur_timewait_info->remote_ca_guid))
+ link = &(*link)->rb_left;
+- else if (remote_ca_guid > cur_timewait_info->remote_ca_guid)
++ else if (be64_gt(remote_ca_guid, cur_timewait_info->remote_ca_guid))
+ link = &(*link)->rb_right;
+ else
+ return cur_timewait_info;
+@@ -635,9 +660,9 @@ static struct cm_id_private * cm_insert_remote_sidr(struct cm_id_private
+ parent = *link;
+ cur_cm_id_priv = rb_entry(parent, struct cm_id_private,
+ sidr_id_node);
+- if (remote_id < cur_cm_id_priv->id.remote_id)
++ if (be32_lt(remote_id, cur_cm_id_priv->id.remote_id))
+ link = &(*link)->rb_left;
+- else if (remote_id > cur_cm_id_priv->id.remote_id)
++ else if (be32_gt(remote_id, cur_cm_id_priv->id.remote_id))
+ link = &(*link)->rb_right;
+ else {
+ int cmp;
+@@ -2848,7 +2873,7 @@ static void cm_format_sidr_req(struct cm_sidr_req_msg *sidr_req_msg,
+ cm_format_mad_hdr(&sidr_req_msg->hdr, CM_SIDR_REQ_ATTR_ID,
+ cm_form_tid(cm_id_priv, CM_MSG_SEQUENCE_SIDR));
+ sidr_req_msg->request_id = cm_id_priv->id.local_id;
+- sidr_req_msg->pkey = cpu_to_be16(param->path->pkey);
++ sidr_req_msg->pkey = param->path->pkey;
+ sidr_req_msg->service_id = param->service_id;
+
+ if (param->private_data && param->private_data_len)
+diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
+index d81c156..671f137 100644
+--- a/drivers/infiniband/core/cma.c
++++ b/drivers/infiniband/core/cma.c
+@@ -1289,7 +1289,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
+ new_cm_id = rdma_create_id(listen_id->id.event_handler,
+ listen_id->id.context,
+ RDMA_PS_TCP);
+- if (!new_cm_id) {
++ if (IS_ERR(new_cm_id)) {
+ ret = -ENOMEM;
+ goto out;
+ }
+diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c
+index 06d502c..1286dc1 100644
+--- a/drivers/infiniband/core/fmr_pool.c
++++ b/drivers/infiniband/core/fmr_pool.c
+@@ -158,8 +158,7 @@ static void ib_fmr_batch_release(struct ib_fmr_pool *pool)
+ #endif
+ }
+
+- list_splice(&pool->dirty_list, &unmap_list);
+- INIT_LIST_HEAD(&pool->dirty_list);
++ list_splice_init(&pool->dirty_list, &unmap_list);
+ pool->dirty_len = 0;
+
+ spin_unlock_irq(&pool->pool_lock);
+diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
+index 5a4b2e6..9575655 100644
+--- a/drivers/infiniband/core/sysfs.c
++++ b/drivers/infiniband/core/sysfs.c
+@@ -427,17 +427,17 @@ static struct kobj_type port_type = {
+ .default_attrs = port_default_attrs
+ };
+
+-static void ib_device_release(struct class_device *cdev)
++static void ib_device_release(struct device *device)
+ {
+- struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
++ struct ib_device *dev = container_of(device, struct ib_device, dev);
+
+ kfree(dev);
+ }
+
+-static int ib_device_uevent(struct class_device *cdev,
++static int ib_device_uevent(struct device *device,
+ struct kobj_uevent_env *env)
+ {
+- struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
++ struct ib_device *dev = container_of(device, struct ib_device, dev);
+
+ if (add_uevent_var(env, "NAME=%s", dev->name))
+ return -ENOMEM;
+@@ -567,9 +567,10 @@ err_put:
+ return ret;
+ }
+
+-static ssize_t show_node_type(struct class_device *cdev, char *buf)
++static ssize_t show_node_type(struct device *device,
++ struct device_attribute *attr, char *buf)
+ {
+- struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
++ struct ib_device *dev = container_of(device, struct ib_device, dev);
+
+ if (!ibdev_is_alive(dev))
+ return -ENODEV;
+@@ -583,9 +584,10 @@ static ssize_t show_node_type(struct class_device *cdev, char *buf)
+ }
+ }
+
+-static ssize_t show_sys_image_guid(struct class_device *cdev, char *buf)
++static ssize_t show_sys_image_guid(struct device *device,
++ struct device_attribute *dev_attr, char *buf)
+ {
+- struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
++ struct ib_device *dev = container_of(device, struct ib_device, dev);
+ struct ib_device_attr attr;
+ ssize_t ret;
+
+@@ -603,9 +605,10 @@ static ssize_t show_sys_image_guid(struct class_device *cdev, char *buf)
+ be16_to_cpu(((__be16 *) &attr.sys_image_guid)[3]));
+ }
+
+-static ssize_t show_node_guid(struct class_device *cdev, char *buf)
++static ssize_t show_node_guid(struct device *device,
++ struct device_attribute *attr, char *buf)
+ {
+- struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
++ struct ib_device *dev = container_of(device, struct ib_device, dev);
+
+ if (!ibdev_is_alive(dev))
+ return -ENODEV;
+@@ -617,17 +620,19 @@ static ssize_t show_node_guid(struct class_device *cdev, char *buf)
+ be16_to_cpu(((__be16 *) &dev->node_guid)[3]));
+ }
+
+-static ssize_t show_node_desc(struct class_device *cdev, char *buf)
++static ssize_t show_node_desc(struct device *device,
++ struct device_attribute *attr, char *buf)
+ {
+- struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
++ struct ib_device *dev = container_of(device, struct ib_device, dev);
+
+ return sprintf(buf, "%.64s\n", dev->node_desc);
+ }
+
+-static ssize_t set_node_desc(struct class_device *cdev, const char *buf,
+- size_t count)
++static ssize_t set_node_desc(struct device *device,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+- struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
++ struct ib_device *dev = container_of(device, struct ib_device, dev);
+ struct ib_device_modify desc = {};
+ int ret;
+
+@@ -642,44 +647,43 @@ static ssize_t set_node_desc(struct class_device *cdev, const char *buf,
+ return count;
+ }
+
+-static CLASS_DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL);
+-static CLASS_DEVICE_ATTR(sys_image_guid, S_IRUGO, show_sys_image_guid, NULL);
+-static CLASS_DEVICE_ATTR(node_guid, S_IRUGO, show_node_guid, NULL);
+-static CLASS_DEVICE_ATTR(node_desc, S_IRUGO | S_IWUSR, show_node_desc,
+- set_node_desc);
+-
+-static struct class_device_attribute *ib_class_attributes[] = {
+- &class_device_attr_node_type,
+- &class_device_attr_sys_image_guid,
+- &class_device_attr_node_guid,
+- &class_device_attr_node_desc
++static DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL);
++static DEVICE_ATTR(sys_image_guid, S_IRUGO, show_sys_image_guid, NULL);
++static DEVICE_ATTR(node_guid, S_IRUGO, show_node_guid, NULL);
++static DEVICE_ATTR(node_desc, S_IRUGO | S_IWUSR, show_node_desc, set_node_desc);
++
++static struct device_attribute *ib_class_attributes[] = {
++ &dev_attr_node_type,
++ &dev_attr_sys_image_guid,
++ &dev_attr_node_guid,
++ &dev_attr_node_desc
+ };
+
+ static struct class ib_class = {
+ .name = "infiniband",
+- .release = ib_device_release,
+- .uevent = ib_device_uevent,
++ .dev_release = ib_device_release,
++ .dev_uevent = ib_device_uevent,
+ };
+
+ int ib_device_register_sysfs(struct ib_device *device)
+ {
+- struct class_device *class_dev = &device->class_dev;
++ struct device *class_dev = &device->dev;
+ int ret;
+ int i;
+
+ class_dev->class = &ib_class;
+- class_dev->class_data = device;
+- class_dev->dev = device->dma_device;
+- strlcpy(class_dev->class_id, device->name, BUS_ID_SIZE);
++ class_dev->driver_data = device;
++ class_dev->parent = device->dma_device;
++ strlcpy(class_dev->bus_id, device->name, BUS_ID_SIZE);
+
+ INIT_LIST_HEAD(&device->port_list);
+
+- ret = class_device_register(class_dev);
++ ret = device_register(class_dev);
+ if (ret)
+ goto err;
+
+ for (i = 0; i < ARRAY_SIZE(ib_class_attributes); ++i) {
+- ret = class_device_create_file(class_dev, ib_class_attributes[i]);
++ ret = device_create_file(class_dev, ib_class_attributes[i]);
+ if (ret)
+ goto err_unregister;
+ }
+@@ -723,7 +727,7 @@ err_put:
+ kobject_put(&class_dev->kobj);
+
+ err_unregister:
+- class_device_unregister(class_dev);
++ device_unregister(class_dev);
+
+ err:
+ return ret;
+@@ -744,7 +748,7 @@ void ib_device_unregister_sysfs(struct ib_device *device)
+ }
+
+ kobject_put(device->ports_parent);
+- class_device_unregister(&device->class_dev);
++ device_unregister(&device->dev);
+ }
+
+ int ib_sysfs_setup(void)
+diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
+index 4291ab4..d7a6881 100644
+--- a/drivers/infiniband/core/ucm.c
++++ b/drivers/infiniband/core/ucm.c
+@@ -58,8 +58,8 @@ MODULE_LICENSE("Dual BSD/GPL");
+
+ struct ib_ucm_device {
+ int devnum;
+- struct cdev dev;
+- struct class_device class_dev;
++ struct cdev cdev;
++ struct device dev;
+ struct ib_device *ib_dev;
+ };
+
+@@ -1171,7 +1171,7 @@ static int ib_ucm_open(struct inode *inode, struct file *filp)
+
+ filp->private_data = file;
+ file->filp = filp;
+- file->device = container_of(inode->i_cdev, struct ib_ucm_device, dev);
++ file->device = container_of(inode->i_cdev, struct ib_ucm_device, cdev);
+
+ return 0;
+ }
+@@ -1202,14 +1202,14 @@ static int ib_ucm_close(struct inode *inode, struct file *filp)
+ return 0;
+ }
+
+-static void ucm_release_class_dev(struct class_device *class_dev)
++static void ib_ucm_release_dev(struct device *dev)
+ {
+- struct ib_ucm_device *dev;
++ struct ib_ucm_device *ucm_dev;
+
+- dev = container_of(class_dev, struct ib_ucm_device, class_dev);
+- cdev_del(&dev->dev);
+- clear_bit(dev->devnum, dev_map);
+- kfree(dev);
++ ucm_dev = container_of(dev, struct ib_ucm_device, dev);
++ cdev_del(&ucm_dev->cdev);
++ clear_bit(ucm_dev->devnum, dev_map);
++ kfree(ucm_dev);
+ }
+
+ static const struct file_operations ucm_fops = {
+@@ -1220,14 +1220,15 @@ static const struct file_operations ucm_fops = {
+ .poll = ib_ucm_poll,
+ };
+
+-static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
++static ssize_t show_ibdev(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct ib_ucm_device *dev;
++ struct ib_ucm_device *ucm_dev;
+
+- dev = container_of(class_dev, struct ib_ucm_device, class_dev);
+- return sprintf(buf, "%s\n", dev->ib_dev->name);
++ ucm_dev = container_of(dev, struct ib_ucm_device, dev);
++ return sprintf(buf, "%s\n", ucm_dev->ib_dev->name);
+ }
+-static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
++static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
+
+ static void ib_ucm_add_one(struct ib_device *device)
+ {
+@@ -1249,32 +1250,31 @@ static void ib_ucm_add_one(struct ib_device *device)
+
+ set_bit(ucm_dev->devnum, dev_map);
+
+- cdev_init(&ucm_dev->dev, &ucm_fops);
+- ucm_dev->dev.owner = THIS_MODULE;
+- kobject_set_name(&ucm_dev->dev.kobj, "ucm%d", ucm_dev->devnum);
+- if (cdev_add(&ucm_dev->dev, IB_UCM_BASE_DEV + ucm_dev->devnum, 1))
++ cdev_init(&ucm_dev->cdev, &ucm_fops);
++ ucm_dev->cdev.owner = THIS_MODULE;
++ kobject_set_name(&ucm_dev->cdev.kobj, "ucm%d", ucm_dev->devnum);
++ if (cdev_add(&ucm_dev->cdev, IB_UCM_BASE_DEV + ucm_dev->devnum, 1))
+ goto err;
+
+- ucm_dev->class_dev.class = &cm_class;
+- ucm_dev->class_dev.dev = device->dma_device;
+- ucm_dev->class_dev.devt = ucm_dev->dev.dev;
+- ucm_dev->class_dev.release = ucm_release_class_dev;
+- snprintf(ucm_dev->class_dev.class_id, BUS_ID_SIZE, "ucm%d",
++ ucm_dev->dev.class = &cm_class;
++ ucm_dev->dev.parent = device->dma_device;
++ ucm_dev->dev.devt = ucm_dev->cdev.dev;
++ ucm_dev->dev.release = ib_ucm_release_dev;
++ snprintf(ucm_dev->dev.bus_id, BUS_ID_SIZE, "ucm%d",
+ ucm_dev->devnum);
+- if (class_device_register(&ucm_dev->class_dev))
++ if (device_register(&ucm_dev->dev))
+ goto err_cdev;
+
+- if (class_device_create_file(&ucm_dev->class_dev,
+- &class_device_attr_ibdev))
+- goto err_class;
++ if (device_create_file(&ucm_dev->dev, &dev_attr_ibdev))
++ goto err_dev;
+
+ ib_set_client_data(device, &ucm_client, ucm_dev);
+ return;
+
+-err_class:
+- class_device_unregister(&ucm_dev->class_dev);
++err_dev:
++ device_unregister(&ucm_dev->dev);
+ err_cdev:
+- cdev_del(&ucm_dev->dev);
++ cdev_del(&ucm_dev->cdev);
+ clear_bit(ucm_dev->devnum, dev_map);
+ err:
+ kfree(ucm_dev);
+@@ -1288,7 +1288,7 @@ static void ib_ucm_remove_one(struct ib_device *device)
+ if (!ucm_dev)
+ return;
+
+- class_device_unregister(&ucm_dev->class_dev);
++ device_unregister(&ucm_dev->dev);
+ }
+
+ static ssize_t show_abi_version(struct class *class, char *buf)
+diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
+index 15937eb..ca4cf3a 100644
+--- a/drivers/infiniband/core/ucma.c
++++ b/drivers/infiniband/core/ucma.c
+@@ -614,7 +614,7 @@ static ssize_t ucma_query_route(struct ucma_file *file,
+ if (!ctx->cm_id->device)
+ goto out;
+
+- resp.node_guid = ctx->cm_id->device->node_guid;
++ resp.node_guid = (__force __u64) ctx->cm_id->device->node_guid;
+ resp.port_num = ctx->cm_id->port_num;
+ switch (rdma_node_get_transport(ctx->cm_id->device->node_type)) {
+ case RDMA_TRANSPORT_IB:
+diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
+index 4e91510..3aa2db5 100644
+--- a/drivers/infiniband/core/user_mad.c
++++ b/drivers/infiniband/core/user_mad.c
+@@ -46,9 +46,9 @@
+ #include <linux/mutex.h>
+ #include <linux/kref.h>
+ #include <linux/compat.h>
++#include <linux/semaphore.h>
+
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+
+ #include <rdma/ib_mad.h>
+ #include <rdma/ib_user_mad.h>
+@@ -88,11 +88,11 @@ enum {
+ */
+
+ struct ib_umad_port {
+- struct cdev *dev;
+- struct class_device *class_dev;
++ struct cdev *cdev;
++ struct device *dev;
+
+- struct cdev *sm_dev;
+- struct class_device *sm_class_dev;
++ struct cdev *sm_cdev;
++ struct device *sm_dev;
+ struct semaphore sm_sem;
+
+ struct mutex file_mutex;
+@@ -948,27 +948,29 @@ static struct ib_client umad_client = {
+ .remove = ib_umad_remove_one
+ };
+
+-static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
++static ssize_t show_ibdev(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct ib_umad_port *port = class_get_devdata(class_dev);
++ struct ib_umad_port *port = dev_get_drvdata(dev);
+
+ if (!port)
+ return -ENODEV;
+
+ return sprintf(buf, "%s\n", port->ib_dev->name);
+ }
+-static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
++static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
+
+-static ssize_t show_port(struct class_device *class_dev, char *buf)
++static ssize_t show_port(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct ib_umad_port *port = class_get_devdata(class_dev);
++ struct ib_umad_port *port = dev_get_drvdata(dev);
+
+ if (!port)
+ return -ENODEV;
+
+ return sprintf(buf, "%d\n", port->port_num);
+ }
+-static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
++static DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
+
+ static ssize_t show_abi_version(struct class *class, char *buf)
+ {
+@@ -994,48 +996,47 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
+ mutex_init(&port->file_mutex);
+ INIT_LIST_HEAD(&port->file_list);
+
+- port->dev = cdev_alloc();
+- if (!port->dev)
++ port->cdev = cdev_alloc();
++ if (!port->cdev)
+ return -1;
+- port->dev->owner = THIS_MODULE;
+- port->dev->ops = &umad_fops;
+- kobject_set_name(&port->dev->kobj, "umad%d", port->dev_num);
+- if (cdev_add(port->dev, base_dev + port->dev_num, 1))
++ port->cdev->owner = THIS_MODULE;
++ port->cdev->ops = &umad_fops;
++ kobject_set_name(&port->cdev->kobj, "umad%d", port->dev_num);
++ if (cdev_add(port->cdev, base_dev + port->dev_num, 1))
+ goto err_cdev;
+
+- port->class_dev = class_device_create(umad_class, NULL, port->dev->dev,
+- device->dma_device,
+- "umad%d", port->dev_num);
+- if (IS_ERR(port->class_dev))
++ port->dev = device_create(umad_class, device->dma_device,
++ port->cdev->dev, "umad%d", port->dev_num);
++ if (IS_ERR(port->dev))
+ goto err_cdev;
+
+- if (class_device_create_file(port->class_dev, &class_device_attr_ibdev))
+- goto err_class;
+- if (class_device_create_file(port->class_dev, &class_device_attr_port))
+- goto err_class;
+-
+- port->sm_dev = cdev_alloc();
+- if (!port->sm_dev)
+- goto err_class;
+- port->sm_dev->owner = THIS_MODULE;
+- port->sm_dev->ops = &umad_sm_fops;
+- kobject_set_name(&port->sm_dev->kobj, "issm%d", port->dev_num);
+- if (cdev_add(port->sm_dev, base_dev + port->dev_num + IB_UMAD_MAX_PORTS, 1))
++ if (device_create_file(port->dev, &dev_attr_ibdev))
++ goto err_dev;
++ if (device_create_file(port->dev, &dev_attr_port))
++ goto err_dev;
++
++ port->sm_cdev = cdev_alloc();
++ if (!port->sm_cdev)
++ goto err_dev;
++ port->sm_cdev->owner = THIS_MODULE;
++ port->sm_cdev->ops = &umad_sm_fops;
++ kobject_set_name(&port->sm_cdev->kobj, "issm%d", port->dev_num);
++ if (cdev_add(port->sm_cdev, base_dev + port->dev_num + IB_UMAD_MAX_PORTS, 1))
+ goto err_sm_cdev;
+
+- port->sm_class_dev = class_device_create(umad_class, NULL, port->sm_dev->dev,
+- device->dma_device,
+- "issm%d", port->dev_num);
+- if (IS_ERR(port->sm_class_dev))
++ port->sm_dev = device_create(umad_class, device->dma_device,
++ port->sm_cdev->dev,
++ "issm%d", port->dev_num);
++ if (IS_ERR(port->sm_dev))
+ goto err_sm_cdev;
+
+- class_set_devdata(port->class_dev, port);
+- class_set_devdata(port->sm_class_dev, port);
++ dev_set_drvdata(port->dev, port);
++ dev_set_drvdata(port->sm_dev, port);
+
+- if (class_device_create_file(port->sm_class_dev, &class_device_attr_ibdev))
+- goto err_sm_class;
+- if (class_device_create_file(port->sm_class_dev, &class_device_attr_port))
+- goto err_sm_class;
++ if (device_create_file(port->sm_dev, &dev_attr_ibdev))
++ goto err_sm_dev;
++ if (device_create_file(port->sm_dev, &dev_attr_port))
++ goto err_sm_dev;
+
+ spin_lock(&port_lock);
+ umad_port[port->dev_num] = port;
+@@ -1043,17 +1044,17 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
+
+ return 0;
+
+-err_sm_class:
+- class_device_destroy(umad_class, port->sm_dev->dev);
++err_sm_dev:
++ device_destroy(umad_class, port->sm_cdev->dev);
+
+ err_sm_cdev:
+- cdev_del(port->sm_dev);
++ cdev_del(port->sm_cdev);
+
+-err_class:
+- class_device_destroy(umad_class, port->dev->dev);
++err_dev:
++ device_destroy(umad_class, port->cdev->dev);
+
+ err_cdev:
+- cdev_del(port->dev);
++ cdev_del(port->cdev);
+ clear_bit(port->dev_num, dev_map);
+
+ return -1;
+@@ -1065,14 +1066,14 @@ static void ib_umad_kill_port(struct ib_umad_port *port)
+ int already_dead;
+ int id;
+
+- class_set_devdata(port->class_dev, NULL);
+- class_set_devdata(port->sm_class_dev, NULL);
++ dev_set_drvdata(port->dev, NULL);
++ dev_set_drvdata(port->sm_dev, NULL);
+
+- class_device_destroy(umad_class, port->dev->dev);
+- class_device_destroy(umad_class, port->sm_dev->dev);
++ device_destroy(umad_class, port->cdev->dev);
++ device_destroy(umad_class, port->sm_cdev->dev);
+
+- cdev_del(port->dev);
+- cdev_del(port->sm_dev);
++ cdev_del(port->cdev);
++ cdev_del(port->sm_cdev);
+
+ spin_lock(&port_lock);
+ umad_port[port->dev_num] = NULL;
+diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
+index c75eb6c..376a57c 100644
+--- a/drivers/infiniband/core/uverbs.h
++++ b/drivers/infiniband/core/uverbs.h
+@@ -73,21 +73,21 @@ struct ib_uverbs_device {
+ struct kref ref;
+ struct completion comp;
+ int devnum;
+- struct cdev *dev;
+- struct class_device *class_dev;
++ struct cdev *cdev;
++ struct device *dev;
+ struct ib_device *ib_dev;
+ int num_comp_vectors;
+ };
+
+ struct ib_uverbs_event_file {
+ struct kref ref;
+- struct file *file;
+ struct ib_uverbs_file *uverbs_file;
+ spinlock_t lock;
+- int is_async;
+ wait_queue_head_t poll_wait;
+ struct fasync_struct *async_queue;
+ struct list_head event_list;
++ int is_async;
++ int is_closed;
+ };
+
+ struct ib_uverbs_file {
+diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
+index 495c803..2c3bff5 100644
+--- a/drivers/infiniband/core/uverbs_cmd.c
++++ b/drivers/infiniband/core/uverbs_cmd.c
+@@ -1065,6 +1065,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
+ attr.srq = srq;
+ attr.sq_sig_type = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
+ attr.qp_type = cmd.qp_type;
++ attr.create_flags = 0;
+
+ attr.cap.max_send_wr = cmd.max_send_wr;
+ attr.cap.max_recv_wr = cmd.max_recv_wr;
+@@ -1462,7 +1463,6 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
+ next->num_sge = user_wr->num_sge;
+ next->opcode = user_wr->opcode;
+ next->send_flags = user_wr->send_flags;
+- next->imm_data = (__be32 __force) user_wr->imm_data;
+
+ if (is_ud) {
+ next->wr.ud.ah = idr_read_ah(user_wr->wr.ud.ah,
+@@ -1475,14 +1475,24 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
+ next->wr.ud.remote_qkey = user_wr->wr.ud.remote_qkey;
+ } else {
+ switch (next->opcode) {
+- case IB_WR_RDMA_WRITE:
+ case IB_WR_RDMA_WRITE_WITH_IMM:
++ next->ex.imm_data =
++ (__be32 __force) user_wr->ex.imm_data;
++ case IB_WR_RDMA_WRITE:
+ case IB_WR_RDMA_READ:
+ next->wr.rdma.remote_addr =
+ user_wr->wr.rdma.remote_addr;
+ next->wr.rdma.rkey =
+ user_wr->wr.rdma.rkey;
+ break;
++ case IB_WR_SEND_WITH_IMM:
++ next->ex.imm_data =
++ (__be32 __force) user_wr->ex.imm_data;
++ break;
++ case IB_WR_SEND_WITH_INV:
++ next->ex.invalidate_rkey =
++ user_wr->ex.invalidate_rkey;
++ break;
+ case IB_WR_ATOMIC_CMP_AND_SWP:
+ case IB_WR_ATOMIC_FETCH_AND_ADD:
+ next->wr.atomic.remote_addr =
+diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
+index 7c2ac39..cc1afa2 100644
+--- a/drivers/infiniband/core/uverbs_main.c
++++ b/drivers/infiniband/core/uverbs_main.c
+@@ -352,7 +352,7 @@ static int ib_uverbs_event_close(struct inode *inode, struct file *filp)
+ struct ib_uverbs_event *entry, *tmp;
+
+ spin_lock_irq(&file->lock);
+- file->file = NULL;
++ file->is_closed = 1;
+ list_for_each_entry_safe(entry, tmp, &file->event_list, list) {
+ if (entry->counter)
+ list_del(&entry->obj_list);
+@@ -390,7 +390,7 @@ void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)
+ return;
+
+ spin_lock_irqsave(&file->lock, flags);
+- if (!file->file) {
++ if (file->is_closed) {
+ spin_unlock_irqrestore(&file->lock, flags);
+ return;
+ }
+@@ -423,7 +423,7 @@ static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
+ unsigned long flags;
+
+ spin_lock_irqsave(&file->async_file->lock, flags);
+- if (!file->async_file->file) {
++ if (!file->async_file->is_closed) {
+ spin_unlock_irqrestore(&file->async_file->lock, flags);
+ return;
+ }
+@@ -509,6 +509,7 @@ struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
+ ev_file->uverbs_file = uverbs_file;
+ ev_file->async_queue = NULL;
+ ev_file->is_async = is_async;
++ ev_file->is_closed = 0;
+
+ *fd = get_unused_fd();
+ if (*fd < 0) {
+@@ -516,25 +517,18 @@ struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
+ goto err;
+ }
+
+- filp = get_empty_filp();
+- if (!filp) {
+- ret = -ENFILE;
+- goto err_fd;
+- }
+-
+- ev_file->file = filp;
+-
+ /*
+ * fops_get() can't fail here, because we're coming from a
+ * system call on a uverbs file, which will already have a
+ * module reference.
+ */
+- filp->f_op = fops_get(&uverbs_event_fops);
+- filp->f_path.mnt = mntget(uverbs_event_mnt);
+- filp->f_path.dentry = dget(uverbs_event_mnt->mnt_root);
+- filp->f_mapping = filp->f_path.dentry->d_inode->i_mapping;
+- filp->f_flags = O_RDONLY;
+- filp->f_mode = FMODE_READ;
++ filp = alloc_file(uverbs_event_mnt, dget(uverbs_event_mnt->mnt_root),
++ FMODE_READ, fops_get(&uverbs_event_fops));
++ if (!filp) {
++ ret = -ENFILE;
++ goto err_fd;
++ }
++
+ filp->private_data = ev_file;
+
+ return filp;
+@@ -696,27 +690,29 @@ static struct ib_client uverbs_client = {
+ .remove = ib_uverbs_remove_one
+ };
+
+-static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
++static ssize_t show_ibdev(struct device *device, struct device_attribute *attr,
++ char *buf)
+ {
+- struct ib_uverbs_device *dev = class_get_devdata(class_dev);
++ struct ib_uverbs_device *dev = dev_get_drvdata(device);
+
+ if (!dev)
+ return -ENODEV;
+
+ return sprintf(buf, "%s\n", dev->ib_dev->name);
+ }
+-static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
++static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
+
+-static ssize_t show_dev_abi_version(struct class_device *class_dev, char *buf)
++static ssize_t show_dev_abi_version(struct device *device,
++ struct device_attribute *attr, char *buf)
+ {
+- struct ib_uverbs_device *dev = class_get_devdata(class_dev);
++ struct ib_uverbs_device *dev = dev_get_drvdata(device);
+
+ if (!dev)
+ return -ENODEV;
+
+ return sprintf(buf, "%d\n", dev->ib_dev->uverbs_abi_ver);
+ }
+-static CLASS_DEVICE_ATTR(abi_version, S_IRUGO, show_dev_abi_version, NULL);
++static DEVICE_ATTR(abi_version, S_IRUGO, show_dev_abi_version, NULL);
+
+ static ssize_t show_abi_version(struct class *class, char *buf)
+ {
+@@ -750,27 +746,26 @@ static void ib_uverbs_add_one(struct ib_device *device)
+ uverbs_dev->ib_dev = device;
+ uverbs_dev->num_comp_vectors = device->num_comp_vectors;
+
+- uverbs_dev->dev = cdev_alloc();
+- if (!uverbs_dev->dev)
++ uverbs_dev->cdev = cdev_alloc();
++ if (!uverbs_dev->cdev)
+ goto err;
+- uverbs_dev->dev->owner = THIS_MODULE;
+- uverbs_dev->dev->ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops;
+- kobject_set_name(&uverbs_dev->dev->kobj, "uverbs%d", uverbs_dev->devnum);
+- if (cdev_add(uverbs_dev->dev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1))
++ uverbs_dev->cdev->owner = THIS_MODULE;
++ uverbs_dev->cdev->ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops;
++ kobject_set_name(&uverbs_dev->cdev->kobj, "uverbs%d", uverbs_dev->devnum);
++ if (cdev_add(uverbs_dev->cdev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1))
+ goto err_cdev;
+
+- uverbs_dev->class_dev = class_device_create(uverbs_class, NULL,
+- uverbs_dev->dev->dev,
+- device->dma_device,
+- "uverbs%d", uverbs_dev->devnum);
+- if (IS_ERR(uverbs_dev->class_dev))
++ uverbs_dev->dev = device_create(uverbs_class, device->dma_device,
++ uverbs_dev->cdev->dev,
++ "uverbs%d", uverbs_dev->devnum);
++ if (IS_ERR(uverbs_dev->dev))
+ goto err_cdev;
+
+- class_set_devdata(uverbs_dev->class_dev, uverbs_dev);
++ dev_set_drvdata(uverbs_dev->dev, uverbs_dev);
+
+- if (class_device_create_file(uverbs_dev->class_dev, &class_device_attr_ibdev))
++ if (device_create_file(uverbs_dev->dev, &dev_attr_ibdev))
+ goto err_class;
+- if (class_device_create_file(uverbs_dev->class_dev, &class_device_attr_abi_version))
++ if (device_create_file(uverbs_dev->dev, &dev_attr_abi_version))
+ goto err_class;
+
+ spin_lock(&map_lock);
+@@ -782,10 +777,10 @@ static void ib_uverbs_add_one(struct ib_device *device)
+ return;
+
+ err_class:
+- class_device_destroy(uverbs_class, uverbs_dev->dev->dev);
++ device_destroy(uverbs_class, uverbs_dev->cdev->dev);
+
+ err_cdev:
+- cdev_del(uverbs_dev->dev);
++ cdev_del(uverbs_dev->cdev);
+ clear_bit(uverbs_dev->devnum, dev_map);
+
+ err:
+@@ -802,9 +797,9 @@ static void ib_uverbs_remove_one(struct ib_device *device)
+ if (!uverbs_dev)
+ return;
+
+- class_set_devdata(uverbs_dev->class_dev, NULL);
+- class_device_destroy(uverbs_class, uverbs_dev->dev->dev);
+- cdev_del(uverbs_dev->dev);
++ dev_set_drvdata(uverbs_dev->dev, NULL);
++ device_destroy(uverbs_class, uverbs_dev->cdev->dev);
++ cdev_del(uverbs_dev->cdev);
+
+ spin_lock(&map_lock);
+ dev_table[uverbs_dev->devnum] = NULL;
+diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
+index 86ed8af..0504208 100644
+--- a/drivers/infiniband/core/verbs.c
++++ b/drivers/infiniband/core/verbs.c
+@@ -248,7 +248,9 @@ int ib_modify_srq(struct ib_srq *srq,
+ struct ib_srq_attr *srq_attr,
+ enum ib_srq_attr_mask srq_attr_mask)
+ {
+- return srq->device->modify_srq(srq, srq_attr, srq_attr_mask, NULL);
++ return srq->device->modify_srq ?
++ srq->device->modify_srq(srq, srq_attr, srq_attr_mask, NULL) :
++ -ENOSYS;
+ }
+ EXPORT_SYMBOL(ib_modify_srq);
+
+@@ -628,6 +630,13 @@ struct ib_cq *ib_create_cq(struct ib_device *device,
+ }
+ EXPORT_SYMBOL(ib_create_cq);
+
++int ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period)
++{
++ return cq->device->modify_cq ?
++ cq->device->modify_cq(cq, cq_count, cq_period) : -ENOSYS;
++}
++EXPORT_SYMBOL(ib_modify_cq);
++
+ int ib_destroy_cq(struct ib_cq *cq)
+ {
+ if (atomic_read(&cq->usecnt))
+@@ -672,6 +681,9 @@ struct ib_mr *ib_reg_phys_mr(struct ib_pd *pd,
+ {
+ struct ib_mr *mr;
+
++ if (!pd->device->reg_phys_mr)
++ return ERR_PTR(-ENOSYS);
++
+ mr = pd->device->reg_phys_mr(pd, phys_buf_array, num_phys_buf,
+ mr_access_flags, iova_start);
+
+diff --git a/drivers/infiniband/hw/amso1100/c2.c b/drivers/infiniband/hw/amso1100/c2.c
+index f283a9f..113f3c0 100644
+--- a/drivers/infiniband/hw/amso1100/c2.c
++++ b/drivers/infiniband/hw/amso1100/c2.c
+@@ -130,10 +130,10 @@ static int c2_tx_ring_alloc(struct c2_ring *tx_ring, void *vaddr,
+ tx_desc->status = 0;
+
+ /* Set TXP_HTXD_UNINIT */
+- __raw_writeq(cpu_to_be64(0x1122334455667788ULL),
++ __raw_writeq((__force u64) cpu_to_be64(0x1122334455667788ULL),
+ (void __iomem *) txp_desc + C2_TXP_ADDR);
+ __raw_writew(0, (void __iomem *) txp_desc + C2_TXP_LEN);
+- __raw_writew(cpu_to_be16(TXP_HTXD_UNINIT),
++ __raw_writew((__force u16) cpu_to_be16(TXP_HTXD_UNINIT),
+ (void __iomem *) txp_desc + C2_TXP_FLAGS);
+
+ elem->skb = NULL;
+@@ -179,13 +179,13 @@ static int c2_rx_ring_alloc(struct c2_ring *rx_ring, void *vaddr,
+ rx_desc->status = 0;
+
+ /* Set RXP_HRXD_UNINIT */
+- __raw_writew(cpu_to_be16(RXP_HRXD_OK),
++ __raw_writew((__force u16) cpu_to_be16(RXP_HRXD_OK),
+ (void __iomem *) rxp_desc + C2_RXP_STATUS);
+ __raw_writew(0, (void __iomem *) rxp_desc + C2_RXP_COUNT);
+ __raw_writew(0, (void __iomem *) rxp_desc + C2_RXP_LEN);
+- __raw_writeq(cpu_to_be64(0x99aabbccddeeffULL),
++ __raw_writeq((__force u64) cpu_to_be64(0x99aabbccddeeffULL),
+ (void __iomem *) rxp_desc + C2_RXP_ADDR);
+- __raw_writew(cpu_to_be16(RXP_HRXD_UNINIT),
++ __raw_writew((__force u16) cpu_to_be16(RXP_HRXD_UNINIT),
+ (void __iomem *) rxp_desc + C2_RXP_FLAGS);
+
+ elem->skb = NULL;
+@@ -239,10 +239,11 @@ static inline int c2_rx_alloc(struct c2_port *c2_port, struct c2_element *elem)
+ rxp_hdr->flags = RXP_HRXD_READY;
+
+ __raw_writew(0, elem->hw_desc + C2_RXP_STATUS);
+- __raw_writew(cpu_to_be16((u16) maplen - sizeof(*rxp_hdr)),
++ __raw_writew((__force u16) cpu_to_be16((u16) maplen - sizeof(*rxp_hdr)),
+ elem->hw_desc + C2_RXP_LEN);
+- __raw_writeq(cpu_to_be64(mapaddr), elem->hw_desc + C2_RXP_ADDR);
+- __raw_writew(cpu_to_be16(RXP_HRXD_READY), elem->hw_desc + C2_RXP_FLAGS);
++ __raw_writeq((__force u64) cpu_to_be64(mapaddr), elem->hw_desc + C2_RXP_ADDR);
++ __raw_writew((__force u16) cpu_to_be16(RXP_HRXD_READY),
++ elem->hw_desc + C2_RXP_FLAGS);
+
+ elem->skb = skb;
+ elem->mapaddr = mapaddr;
+@@ -290,9 +291,9 @@ static void c2_rx_clean(struct c2_port *c2_port)
+ __raw_writew(0, elem->hw_desc + C2_RXP_STATUS);
+ __raw_writew(0, elem->hw_desc + C2_RXP_COUNT);
+ __raw_writew(0, elem->hw_desc + C2_RXP_LEN);
+- __raw_writeq(cpu_to_be64(0x99aabbccddeeffULL),
++ __raw_writeq((__force u64) cpu_to_be64(0x99aabbccddeeffULL),
+ elem->hw_desc + C2_RXP_ADDR);
+- __raw_writew(cpu_to_be16(RXP_HRXD_UNINIT),
++ __raw_writew((__force u16) cpu_to_be16(RXP_HRXD_UNINIT),
+ elem->hw_desc + C2_RXP_FLAGS);
+
+ if (elem->skb) {
+@@ -346,16 +347,16 @@ static void c2_tx_clean(struct c2_port *c2_port)
+ elem->hw_desc + C2_TXP_LEN);
+ __raw_writeq(0,
+ elem->hw_desc + C2_TXP_ADDR);
+- __raw_writew(cpu_to_be16(TXP_HTXD_DONE),
++ __raw_writew((__force u16) cpu_to_be16(TXP_HTXD_DONE),
+ elem->hw_desc + C2_TXP_FLAGS);
+ c2_port->netstats.tx_dropped++;
+ break;
+ } else {
+ __raw_writew(0,
+ elem->hw_desc + C2_TXP_LEN);
+- __raw_writeq(cpu_to_be64(0x1122334455667788ULL),
++ __raw_writeq((__force u64) cpu_to_be64(0x1122334455667788ULL),
+ elem->hw_desc + C2_TXP_ADDR);
+- __raw_writew(cpu_to_be16(TXP_HTXD_UNINIT),
++ __raw_writew((__force u16) cpu_to_be16(TXP_HTXD_UNINIT),
+ elem->hw_desc + C2_TXP_FLAGS);
+ }
+
+@@ -390,7 +391,7 @@ static void c2_tx_interrupt(struct net_device *netdev)
+ for (elem = tx_ring->to_clean; elem != tx_ring->to_use;
+ elem = elem->next) {
+ txp_htxd.flags =
+- be16_to_cpu(readw(elem->hw_desc + C2_TXP_FLAGS));
++ be16_to_cpu((__force __be16) readw(elem->hw_desc + C2_TXP_FLAGS));
+
+ if (txp_htxd.flags != TXP_HTXD_DONE)
+ break;
+@@ -398,7 +399,7 @@ static void c2_tx_interrupt(struct net_device *netdev)
+ if (netif_msg_tx_done(c2_port)) {
+ /* PCI reads are expensive in fast path */
+ txp_htxd.len =
+- be16_to_cpu(readw(elem->hw_desc + C2_TXP_LEN));
++ be16_to_cpu((__force __be16) readw(elem->hw_desc + C2_TXP_LEN));
+ pr_debug("%s: tx done slot %3Zu status 0x%x len "
+ "%5u bytes\n",
+ netdev->name, elem - tx_ring->start,
+@@ -448,10 +449,12 @@ static void c2_rx_error(struct c2_port *c2_port, struct c2_element *elem)
+ /* Write the descriptor to the adapter's rx ring */
+ __raw_writew(0, elem->hw_desc + C2_RXP_STATUS);
+ __raw_writew(0, elem->hw_desc + C2_RXP_COUNT);
+- __raw_writew(cpu_to_be16((u16) elem->maplen - sizeof(*rxp_hdr)),
++ __raw_writew((__force u16) cpu_to_be16((u16) elem->maplen - sizeof(*rxp_hdr)),
+ elem->hw_desc + C2_RXP_LEN);
+- __raw_writeq(cpu_to_be64(elem->mapaddr), elem->hw_desc + C2_RXP_ADDR);
+- __raw_writew(cpu_to_be16(RXP_HRXD_READY), elem->hw_desc + C2_RXP_FLAGS);
++ __raw_writeq((__force u64) cpu_to_be64(elem->mapaddr),
++ elem->hw_desc + C2_RXP_ADDR);
++ __raw_writew((__force u16) cpu_to_be16(RXP_HRXD_READY),
++ elem->hw_desc + C2_RXP_FLAGS);
+
+ pr_debug("packet dropped\n");
+ c2_port->netstats.rx_dropped++;
+@@ -653,7 +656,7 @@ static int c2_up(struct net_device *netdev)
+ i++, elem++) {
+ rxp_hdr = (struct c2_rxp_hdr *) elem->skb->data;
+ rxp_hdr->flags = 0;
+- __raw_writew(cpu_to_be16(RXP_HRXD_READY),
++ __raw_writew((__force u16) cpu_to_be16(RXP_HRXD_READY),
+ elem->hw_desc + C2_RXP_FLAGS);
+ }
+
+@@ -787,9 +790,12 @@ static int c2_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ elem->maplen = maplen;
+
+ /* Tell HW to xmit */
+- __raw_writeq(cpu_to_be64(mapaddr), elem->hw_desc + C2_TXP_ADDR);
+- __raw_writew(cpu_to_be16(maplen), elem->hw_desc + C2_TXP_LEN);
+- __raw_writew(cpu_to_be16(TXP_HTXD_READY), elem->hw_desc + C2_TXP_FLAGS);
++ __raw_writeq((__force u64) cpu_to_be64(mapaddr),
++ elem->hw_desc + C2_TXP_ADDR);
++ __raw_writew((__force u16) cpu_to_be16(maplen),
++ elem->hw_desc + C2_TXP_LEN);
++ __raw_writew((__force u16) cpu_to_be16(TXP_HTXD_READY),
++ elem->hw_desc + C2_TXP_FLAGS);
+
+ c2_port->netstats.tx_packets++;
+ c2_port->netstats.tx_bytes += maplen;
+@@ -810,11 +816,11 @@ static int c2_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ elem->maplen = maplen;
+
+ /* Tell HW to xmit */
+- __raw_writeq(cpu_to_be64(mapaddr),
++ __raw_writeq((__force u64) cpu_to_be64(mapaddr),
+ elem->hw_desc + C2_TXP_ADDR);
+- __raw_writew(cpu_to_be16(maplen),
++ __raw_writew((__force u16) cpu_to_be16(maplen),
+ elem->hw_desc + C2_TXP_LEN);
+- __raw_writew(cpu_to_be16(TXP_HTXD_READY),
++ __raw_writew((__force u16) cpu_to_be16(TXP_HTXD_READY),
+ elem->hw_desc + C2_TXP_FLAGS);
+
+ c2_port->netstats.tx_packets++;
+@@ -1005,7 +1011,7 @@ static int __devinit c2_probe(struct pci_dev *pcidev,
+ /* Remap the adapter PCI registers in BAR4 */
+ mmio_regs = ioremap_nocache(reg4_start + C2_PCI_REGS_OFFSET,
+ sizeof(struct c2_adapter_pci_regs));
+- if (mmio_regs == 0UL) {
++ if (!mmio_regs) {
+ printk(KERN_ERR PFX
+ "Unable to remap adapter PCI registers in BAR4\n");
+ ret = -EIO;
+@@ -1029,10 +1035,10 @@ static int __devinit c2_probe(struct pci_dev *pcidev,
+ }
+
+ /* Validate the adapter version */
+- if (be32_to_cpu(readl(mmio_regs + C2_REGS_VERS)) != C2_VERSION) {
++ if (be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_VERS)) != C2_VERSION) {
+ printk(KERN_ERR PFX "Version mismatch "
+ "[fw=%u, c2=%u], Adapter not claimed\n",
+- be32_to_cpu(readl(mmio_regs + C2_REGS_VERS)),
++ be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_VERS)),
+ C2_VERSION);
+ ret = -EINVAL;
+ iounmap(mmio_regs);
+@@ -1040,12 +1046,12 @@ static int __devinit c2_probe(struct pci_dev *pcidev,
+ }
+
+ /* Validate the adapter IVN */
+- if (be32_to_cpu(readl(mmio_regs + C2_REGS_IVN)) != C2_IVN) {
++ if (be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_IVN)) != C2_IVN) {
+ printk(KERN_ERR PFX "Downlevel FIrmware level. You should be using "
+ "the OpenIB device support kit. "
+ "[fw=0x%x, c2=0x%x], Adapter not claimed\n",
+- be32_to_cpu(readl(mmio_regs + C2_REGS_IVN)),
+- C2_IVN);
++ be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_IVN)),
++ C2_IVN);
+ ret = -EINVAL;
+ iounmap(mmio_regs);
+ goto bail2;
+@@ -1068,7 +1074,7 @@ static int __devinit c2_probe(struct pci_dev *pcidev,
+
+ /* Get the last RX index */
+ c2dev->cur_rx =
+- (be32_to_cpu(readl(mmio_regs + C2_REGS_HRX_CUR)) -
++ (be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_HRX_CUR)) -
+ 0xffffc000) / sizeof(struct c2_rxp_desc);
+
+ /* Request an interrupt line for the driver */
+@@ -1090,7 +1096,7 @@ static int __devinit c2_probe(struct pci_dev *pcidev,
+ }
+
+ /* Save off the actual size prior to unmapping mmio_regs */
+- kva_map_size = be32_to_cpu(readl(mmio_regs + C2_REGS_PCI_WINSIZE));
++ kva_map_size = be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_PCI_WINSIZE));
+
+ /* Unmap the adapter PCI registers in BAR4 */
+ iounmap(mmio_regs);
+@@ -1109,7 +1115,7 @@ static int __devinit c2_probe(struct pci_dev *pcidev,
+ /* Remap the adapter HRXDQ PA space to kernel VA space */
+ c2dev->mmio_rxp_ring = ioremap_nocache(reg4_start + C2_RXP_HRXDQ_OFFSET,
+ C2_RXP_HRXDQ_SIZE);
+- if (c2dev->mmio_rxp_ring == 0UL) {
++ if (!c2dev->mmio_rxp_ring) {
+ printk(KERN_ERR PFX "Unable to remap MMIO HRXDQ region\n");
+ ret = -EIO;
+ goto bail6;
+@@ -1118,7 +1124,7 @@ static int __devinit c2_probe(struct pci_dev *pcidev,
+ /* Remap the adapter HTXDQ PA space to kernel VA space */
+ c2dev->mmio_txp_ring = ioremap_nocache(reg4_start + C2_TXP_HTXDQ_OFFSET,
+ C2_TXP_HTXDQ_SIZE);
+- if (c2dev->mmio_txp_ring == 0UL) {
++ if (!c2dev->mmio_txp_ring) {
+ printk(KERN_ERR PFX "Unable to remap MMIO HTXDQ region\n");
+ ret = -EIO;
+ goto bail7;
+@@ -1129,7 +1135,7 @@ static int __devinit c2_probe(struct pci_dev *pcidev,
+
+ /* Remap the PCI registers in adapter BAR0 to kernel VA space */
+ c2dev->regs = ioremap_nocache(reg0_start, reg0_len);
+- if (c2dev->regs == 0UL) {
++ if (!c2dev->regs) {
+ printk(KERN_ERR PFX "Unable to remap BAR0\n");
+ ret = -EIO;
+ goto bail8;
+@@ -1139,7 +1145,7 @@ static int __devinit c2_probe(struct pci_dev *pcidev,
+ c2dev->pa = reg4_start + C2_PCI_REGS_OFFSET;
+ c2dev->kva = ioremap_nocache(reg4_start + C2_PCI_REGS_OFFSET,
+ kva_map_size);
+- if (c2dev->kva == 0UL) {
++ if (!c2dev->kva) {
+ printk(KERN_ERR PFX "Unable to remap BAR4\n");
+ ret = -EIO;
+ goto bail9;
+diff --git a/drivers/infiniband/hw/amso1100/c2.h b/drivers/infiniband/hw/amso1100/c2.h
+index fa58200..d12a24a 100644
+--- a/drivers/infiniband/hw/amso1100/c2.h
++++ b/drivers/infiniband/hw/amso1100/c2.h
+@@ -40,7 +40,6 @@
+ #include <linux/pci.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/idr.h>
+-#include <asm/semaphore.h>
+
+ #include "c2_provider.h"
+ #include "c2_mq.h"
+@@ -346,7 +345,7 @@ struct c2_dev {
+ // spinlock_t aeq_lock;
+ // spinlock_t rnic_lock;
+
+- u16 *hint_count;
++ __be16 *hint_count;
+ dma_addr_t hint_count_dma;
+ u16 hints_read;
+
+@@ -425,10 +424,10 @@ static inline void __raw_writeq(u64 val, void __iomem * addr)
+ #endif
+
+ #define C2_SET_CUR_RX(c2dev, cur_rx) \
+- __raw_writel(cpu_to_be32(cur_rx), c2dev->mmio_txp_ring + 4092)
++ __raw_writel((__force u32) cpu_to_be32(cur_rx), c2dev->mmio_txp_ring + 4092)
+
+ #define C2_GET_CUR_RX(c2dev) \
+- be32_to_cpu(readl(c2dev->mmio_txp_ring + 4092))
++ be32_to_cpu((__force __be32) readl(c2dev->mmio_txp_ring + 4092))
+
+ static inline struct c2_dev *to_c2dev(struct ib_device *ibdev)
+ {
+@@ -485,8 +484,8 @@ extern void c2_unregister_device(struct c2_dev *c2dev);
+ extern int c2_rnic_init(struct c2_dev *c2dev);
+ extern void c2_rnic_term(struct c2_dev *c2dev);
+ extern void c2_rnic_interrupt(struct c2_dev *c2dev);
+-extern int c2_del_addr(struct c2_dev *c2dev, u32 inaddr, u32 inmask);
+-extern int c2_add_addr(struct c2_dev *c2dev, u32 inaddr, u32 inmask);
++extern int c2_del_addr(struct c2_dev *c2dev, __be32 inaddr, __be32 inmask);
++extern int c2_add_addr(struct c2_dev *c2dev, __be32 inaddr, __be32 inmask);
+
+ /* QPs */
+ extern int c2_alloc_qp(struct c2_dev *c2dev, struct c2_pd *pd,
+@@ -545,7 +544,7 @@ extern void c2_ae_event(struct c2_dev *c2dev, u32 mq_index);
+ extern int c2_init_mqsp_pool(struct c2_dev *c2dev, gfp_t gfp_mask,
+ struct sp_chunk **root);
+ extern void c2_free_mqsp_pool(struct c2_dev *c2dev, struct sp_chunk *root);
+-extern u16 *c2_alloc_mqsp(struct c2_dev *c2dev, struct sp_chunk *head,
+- dma_addr_t *dma_addr, gfp_t gfp_mask);
+-extern void c2_free_mqsp(u16 * mqsp);
++extern __be16 *c2_alloc_mqsp(struct c2_dev *c2dev, struct sp_chunk *head,
++ dma_addr_t *dma_addr, gfp_t gfp_mask);
++extern void c2_free_mqsp(__be16* mqsp);
+ #endif
+diff --git a/drivers/infiniband/hw/amso1100/c2_ae.c b/drivers/infiniband/hw/amso1100/c2_ae.c
+index a31439b..62af742 100644
+--- a/drivers/infiniband/hw/amso1100/c2_ae.c
++++ b/drivers/infiniband/hw/amso1100/c2_ae.c
+@@ -61,7 +61,7 @@ static int c2_convert_cm_status(u32 c2_status)
+ default:
+ printk(KERN_ERR PFX
+ "%s - Unable to convert CM status: %d\n",
+- __FUNCTION__, c2_status);
++ __func__, c2_status);
+ return -EIO;
+ }
+ }
+@@ -193,9 +193,9 @@ void c2_ae_event(struct c2_dev *c2dev, u32 mq_index)
+ pr_debug("%s: event = %s, user_context=%llx, "
+ "resource_type=%x, "
+ "resource=%x, qp_state=%s\n",
+- __FUNCTION__,
++ __func__,
+ to_event_str(event_id),
+- (unsigned long long) be64_to_cpu(wr->ae.ae_generic.user_context),
++ (unsigned long long) wr->ae.ae_generic.user_context,
+ be32_to_cpu(wr->ae.ae_generic.resource_type),
+ be32_to_cpu(wr->ae.ae_generic.resource),
+ to_qp_state_str(be32_to_cpu(wr->ae.ae_generic.qp_state)));
+@@ -259,7 +259,7 @@ void c2_ae_event(struct c2_dev *c2dev, u32 mq_index)
+ BUG_ON(1);
+ pr_debug("%s:%d Unexpected event_id=%d on QP=%p, "
+ "CM_ID=%p\n",
+- __FUNCTION__, __LINE__,
++ __func__, __LINE__,
+ event_id, qp, cm_id);
+ break;
+ }
+@@ -276,7 +276,7 @@ void c2_ae_event(struct c2_dev *c2dev, u32 mq_index)
+ pr_debug("C2_RES_IND_EP event_id=%d\n", event_id);
+ if (event_id != CCAE_CONNECTION_REQUEST) {
+ pr_debug("%s: Invalid event_id: %d\n",
+- __FUNCTION__, event_id);
++ __func__, event_id);
+ break;
+ }
+ cm_event.event = IW_CM_EVENT_CONNECT_REQUEST;
+diff --git a/drivers/infiniband/hw/amso1100/c2_alloc.c b/drivers/infiniband/hw/amso1100/c2_alloc.c
+index 0315f99..e911016 100644
+--- a/drivers/infiniband/hw/amso1100/c2_alloc.c
++++ b/drivers/infiniband/hw/amso1100/c2_alloc.c
+@@ -87,8 +87,8 @@ void c2_free_mqsp_pool(struct c2_dev *c2dev, struct sp_chunk *root)
+ }
+ }
+
+-u16 *c2_alloc_mqsp(struct c2_dev *c2dev, struct sp_chunk *head,
+- dma_addr_t *dma_addr, gfp_t gfp_mask)
++__be16 *c2_alloc_mqsp(struct c2_dev *c2dev, struct sp_chunk *head,
++ dma_addr_t *dma_addr, gfp_t gfp_mask)
+ {
+ u16 mqsp;
+
+@@ -113,14 +113,14 @@ u16 *c2_alloc_mqsp(struct c2_dev *c2dev, struct sp_chunk *head,
+ *dma_addr = head->dma_addr +
+ ((unsigned long) &(head->shared_ptr[mqsp]) -
+ (unsigned long) head);
+- pr_debug("%s addr %p dma_addr %llx\n", __FUNCTION__,
++ pr_debug("%s addr %p dma_addr %llx\n", __func__,
+ &(head->shared_ptr[mqsp]), (unsigned long long) *dma_addr);
+- return &(head->shared_ptr[mqsp]);
++ return (__force __be16 *) &(head->shared_ptr[mqsp]);
+ }
+ return NULL;
+ }
+
+-void c2_free_mqsp(u16 * mqsp)
++void c2_free_mqsp(__be16 *mqsp)
+ {
+ struct sp_chunk *head;
+ u16 idx;
+@@ -129,7 +129,7 @@ void c2_free_mqsp(u16 * mqsp)
+ head = (struct sp_chunk *) ((unsigned long) mqsp & PAGE_MASK);
+
+ /* Link head to new mqsp */
+- *mqsp = head->head;
++ *mqsp = (__force __be16) head->head;
+
+ /* Compute the shared_ptr index */
+ idx = ((unsigned long) mqsp & ~PAGE_MASK) >> 1;
+diff --git a/drivers/infiniband/hw/amso1100/c2_cq.c b/drivers/infiniband/hw/amso1100/c2_cq.c
+index d2b3366..bb17cce 100644
+--- a/drivers/infiniband/hw/amso1100/c2_cq.c
++++ b/drivers/infiniband/hw/amso1100/c2_cq.c
+@@ -422,8 +422,8 @@ void c2_free_cq(struct c2_dev *c2dev, struct c2_cq *cq)
+ goto bail1;
+
+ reply = (struct c2wr_cq_destroy_rep *) (unsigned long) (vq_req->reply_msg);
+-
+- vq_repbuf_free(c2dev, reply);
++ if (reply)
++ vq_repbuf_free(c2dev, reply);
+ bail1:
+ vq_req_free(c2dev, vq_req);
+ bail0:
+diff --git a/drivers/infiniband/hw/amso1100/c2_intr.c b/drivers/infiniband/hw/amso1100/c2_intr.c
+index 0d0bc33..3b50954 100644
+--- a/drivers/infiniband/hw/amso1100/c2_intr.c
++++ b/drivers/infiniband/hw/amso1100/c2_intr.c
+@@ -174,7 +174,11 @@ static void handle_vq(struct c2_dev *c2dev, u32 mq_index)
+ return;
+ }
+
+- err = c2_errno(reply_msg);
++ if (reply_msg)
++ err = c2_errno(reply_msg);
++ else
++ err = -ENOMEM;
++
+ if (!err) switch (req->event) {
+ case IW_CM_EVENT_ESTABLISHED:
+ c2_set_qp_state(req->qp,
+diff --git a/drivers/infiniband/hw/amso1100/c2_mm.c b/drivers/infiniband/hw/amso1100/c2_mm.c
+index 1e4f464..b506fe2 100644
+--- a/drivers/infiniband/hw/amso1100/c2_mm.c
++++ b/drivers/infiniband/hw/amso1100/c2_mm.c
+@@ -45,7 +45,7 @@
+ * Reply buffer _is_ freed by this function.
+ */
+ static int
+-send_pbl_messages(struct c2_dev *c2dev, u32 stag_index,
++send_pbl_messages(struct c2_dev *c2dev, __be32 stag_index,
+ unsigned long va, u32 pbl_depth,
+ struct c2_vq_req *vq_req, int pbl_type)
+ {
+diff --git a/drivers/infiniband/hw/amso1100/c2_mq.c b/drivers/infiniband/hw/amso1100/c2_mq.c
+index b88a755..0cddc49 100644
+--- a/drivers/infiniband/hw/amso1100/c2_mq.c
++++ b/drivers/infiniband/hw/amso1100/c2_mq.c
+@@ -64,7 +64,7 @@ void c2_mq_produce(struct c2_mq *q)
+ q->priv = (q->priv + 1) % q->q_size;
+ q->hint_count++;
+ /* Update peer's offset. */
+- __raw_writew(cpu_to_be16(q->priv), &q->peer->shared);
++ __raw_writew((__force u16) cpu_to_be16(q->priv), &q->peer->shared);
+ }
+ }
+
+@@ -105,7 +105,7 @@ void c2_mq_free(struct c2_mq *q)
+ #endif
+ q->priv = (q->priv + 1) % q->q_size;
+ /* Update peer's offset. */
+- __raw_writew(cpu_to_be16(q->priv), &q->peer->shared);
++ __raw_writew((__force u16) cpu_to_be16(q->priv), &q->peer->shared);
+ }
+ }
+
+diff --git a/drivers/infiniband/hw/amso1100/c2_mq.h b/drivers/infiniband/hw/amso1100/c2_mq.h
+index 9185bbb..acede00 100644
+--- a/drivers/infiniband/hw/amso1100/c2_mq.h
++++ b/drivers/infiniband/hw/amso1100/c2_mq.h
+@@ -75,7 +75,7 @@ struct c2_mq {
+ u16 hint_count;
+ u16 priv;
+ struct c2_mq_shared __iomem *peer;
+- u16 *shared;
++ __be16 *shared;
+ dma_addr_t shared_dma;
+ u32 q_size;
+ u32 msg_size;
+diff --git a/drivers/infiniband/hw/amso1100/c2_provider.c b/drivers/infiniband/hw/amso1100/c2_provider.c
+index 7a6cece..6af2c0f 100644
+--- a/drivers/infiniband/hw/amso1100/c2_provider.c
++++ b/drivers/infiniband/hw/amso1100/c2_provider.c
+@@ -67,7 +67,7 @@ static int c2_query_device(struct ib_device *ibdev,
+ {
+ struct c2_dev *c2dev = to_c2dev(ibdev);
+
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+
+ *props = c2dev->props;
+ return 0;
+@@ -76,7 +76,7 @@ static int c2_query_device(struct ib_device *ibdev,
+ static int c2_query_port(struct ib_device *ibdev,
+ u8 port, struct ib_port_attr *props)
+ {
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+
+ props->max_mtu = IB_MTU_4096;
+ props->lid = 0;
+@@ -102,14 +102,14 @@ static int c2_modify_port(struct ib_device *ibdev,
+ u8 port, int port_modify_mask,
+ struct ib_port_modify *props)
+ {
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+ return 0;
+ }
+
+ static int c2_query_pkey(struct ib_device *ibdev,
+ u8 port, u16 index, u16 * pkey)
+ {
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+ *pkey = 0;
+ return 0;
+ }
+@@ -119,7 +119,7 @@ static int c2_query_gid(struct ib_device *ibdev, u8 port,
+ {
+ struct c2_dev *c2dev = to_c2dev(ibdev);
+
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+ memset(&(gid->raw[0]), 0, sizeof(gid->raw));
+ memcpy(&(gid->raw[0]), c2dev->pseudo_netdev->dev_addr, 6);
+
+@@ -134,7 +134,7 @@ static struct ib_ucontext *c2_alloc_ucontext(struct ib_device *ibdev,
+ {
+ struct c2_ucontext *context;
+
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+ context = kmalloc(sizeof(*context), GFP_KERNEL);
+ if (!context)
+ return ERR_PTR(-ENOMEM);
+@@ -144,14 +144,14 @@ static struct ib_ucontext *c2_alloc_ucontext(struct ib_device *ibdev,
+
+ static int c2_dealloc_ucontext(struct ib_ucontext *context)
+ {
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+ kfree(context);
+ return 0;
+ }
+
+ static int c2_mmap_uar(struct ib_ucontext *context, struct vm_area_struct *vma)
+ {
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+ return -ENOSYS;
+ }
+
+@@ -162,7 +162,7 @@ static struct ib_pd *c2_alloc_pd(struct ib_device *ibdev,
+ struct c2_pd *pd;
+ int err;
+
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+
+ pd = kmalloc(sizeof(*pd), GFP_KERNEL);
+ if (!pd)
+@@ -187,7 +187,7 @@ static struct ib_pd *c2_alloc_pd(struct ib_device *ibdev,
+
+ static int c2_dealloc_pd(struct ib_pd *pd)
+ {
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+ c2_pd_free(to_c2dev(pd->device), to_c2pd(pd));
+ kfree(pd);
+
+@@ -196,13 +196,13 @@ static int c2_dealloc_pd(struct ib_pd *pd)
+
+ static struct ib_ah *c2_ah_create(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
+ {
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+ return ERR_PTR(-ENOSYS);
+ }
+
+ static int c2_ah_destroy(struct ib_ah *ah)
+ {
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+ return -ENOSYS;
+ }
+
+@@ -230,7 +230,7 @@ struct ib_qp *c2_get_qp(struct ib_device *device, int qpn)
+
+ qp = c2_find_qpn(c2dev, qpn);
+ pr_debug("%s Returning QP=%p for QPN=%d, device=%p, refcount=%d\n",
+- __FUNCTION__, qp, qpn, device,
++ __func__, qp, qpn, device,
+ (qp?atomic_read(&qp->refcount):0));
+
+ return (qp?&qp->ibqp:NULL);
+@@ -243,13 +243,16 @@ static struct ib_qp *c2_create_qp(struct ib_pd *pd,
+ struct c2_qp *qp;
+ int err;
+
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
++
++ if (init_attr->create_flags)
++ return ERR_PTR(-EINVAL);
+
+ switch (init_attr->qp_type) {
+ case IB_QPT_RC:
+ qp = kzalloc(sizeof(*qp), GFP_KERNEL);
+ if (!qp) {
+- pr_debug("%s: Unable to allocate QP\n", __FUNCTION__);
++ pr_debug("%s: Unable to allocate QP\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+ spin_lock_init(&qp->lock);
+@@ -266,7 +269,7 @@ static struct ib_qp *c2_create_qp(struct ib_pd *pd,
+
+ break;
+ default:
+- pr_debug("%s: Invalid QP type: %d\n", __FUNCTION__,
++ pr_debug("%s: Invalid QP type: %d\n", __func__,
+ init_attr->qp_type);
+ return ERR_PTR(-EINVAL);
+ break;
+@@ -285,7 +288,7 @@ static int c2_destroy_qp(struct ib_qp *ib_qp)
+ struct c2_qp *qp = to_c2qp(ib_qp);
+
+ pr_debug("%s:%u qp=%p,qp->state=%d\n",
+- __FUNCTION__, __LINE__,ib_qp,qp->state);
++ __func__, __LINE__, ib_qp, qp->state);
+ c2_free_qp(to_c2dev(ib_qp->device), qp);
+ kfree(qp);
+ return 0;
+@@ -300,13 +303,13 @@ static struct ib_cq *c2_create_cq(struct ib_device *ibdev, int entries, int vect
+
+ cq = kmalloc(sizeof(*cq), GFP_KERNEL);
+ if (!cq) {
+- pr_debug("%s: Unable to allocate CQ\n", __FUNCTION__);
++ pr_debug("%s: Unable to allocate CQ\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ err = c2_init_cq(to_c2dev(ibdev), entries, NULL, cq);
+ if (err) {
+- pr_debug("%s: error initializing CQ\n", __FUNCTION__);
++ pr_debug("%s: error initializing CQ\n", __func__);
+ kfree(cq);
+ return ERR_PTR(err);
+ }
+@@ -318,7 +321,7 @@ static int c2_destroy_cq(struct ib_cq *ib_cq)
+ {
+ struct c2_cq *cq = to_c2cq(ib_cq);
+
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+
+ c2_free_cq(to_c2dev(ib_cq->device), cq);
+ kfree(cq);
+@@ -400,7 +403,7 @@ static struct ib_mr *c2_reg_phys_mr(struct ib_pd *ib_pd,
+ mr->umem = NULL;
+ pr_debug("%s - page shift %d, pbl_depth %d, total_len %u, "
+ "*iova_start %llx, first pa %llx, last pa %llx\n",
+- __FUNCTION__, page_shift, pbl_depth, total_len,
++ __func__, page_shift, pbl_depth, total_len,
+ (unsigned long long) *iova_start,
+ (unsigned long long) page_list[0],
+ (unsigned long long) page_list[pbl_depth-1]);
+@@ -422,7 +425,7 @@ static struct ib_mr *c2_get_dma_mr(struct ib_pd *pd, int acc)
+ struct ib_phys_buf bl;
+ u64 kva = 0;
+
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+
+ /* AMSO1100 limit */
+ bl.size = 0xffffffff;
+@@ -442,7 +445,7 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+ struct c2_pd *c2pd = to_c2pd(pd);
+ struct c2_mr *c2mr;
+
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+
+ c2mr = kmalloc(sizeof(*c2mr), GFP_KERNEL);
+ if (!c2mr)
+@@ -506,7 +509,7 @@ static int c2_dereg_mr(struct ib_mr *ib_mr)
+ struct c2_mr *mr = to_c2mr(ib_mr);
+ int err;
+
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+
+ err = c2_stag_dealloc(to_c2dev(ib_mr->device), ib_mr->lkey);
+ if (err)
+@@ -520,45 +523,49 @@ static int c2_dereg_mr(struct ib_mr *ib_mr)
+ return err;
+ }
+
+-static ssize_t show_rev(struct class_device *cdev, char *buf)
++static ssize_t show_rev(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct c2_dev *dev = container_of(cdev, struct c2_dev, ibdev.class_dev);
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
+- return sprintf(buf, "%x\n", dev->props.hw_ver);
++ struct c2_dev *c2dev = container_of(dev, struct c2_dev, ibdev.dev);
++ pr_debug("%s:%u\n", __func__, __LINE__);
++ return sprintf(buf, "%x\n", c2dev->props.hw_ver);
+ }
+
+-static ssize_t show_fw_ver(struct class_device *cdev, char *buf)
++static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct c2_dev *dev = container_of(cdev, struct c2_dev, ibdev.class_dev);
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ struct c2_dev *c2dev = container_of(dev, struct c2_dev, ibdev.dev);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+ return sprintf(buf, "%x.%x.%x\n",
+- (int) (dev->props.fw_ver >> 32),
+- (int) (dev->props.fw_ver >> 16) & 0xffff,
+- (int) (dev->props.fw_ver & 0xffff));
++ (int) (c2dev->props.fw_ver >> 32),
++ (int) (c2dev->props.fw_ver >> 16) & 0xffff,
++ (int) (c2dev->props.fw_ver & 0xffff));
+ }
+
+-static ssize_t show_hca(struct class_device *cdev, char *buf)
++static ssize_t show_hca(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+ return sprintf(buf, "AMSO1100\n");
+ }
+
+-static ssize_t show_board(struct class_device *cdev, char *buf)
++static ssize_t show_board(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+ return sprintf(buf, "%.*s\n", 32, "AMSO1100 Board ID");
+ }
+
+-static CLASS_DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
+-static CLASS_DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
+-static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
+-static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
++static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
++static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
++static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
++static DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
+
+-static struct class_device_attribute *c2_class_attributes[] = {
+- &class_device_attr_hw_rev,
+- &class_device_attr_fw_ver,
+- &class_device_attr_hca_type,
+- &class_device_attr_board_id
++static struct device_attribute *c2_dev_attributes[] = {
++ &dev_attr_hw_rev,
++ &dev_attr_fw_ver,
++ &dev_attr_hca_type,
++ &dev_attr_board_id
+ };
+
+ static int c2_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+@@ -575,13 +582,13 @@ static int c2_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+
+ static int c2_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
+ {
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+ return -ENOSYS;
+ }
+
+ static int c2_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
+ {
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+ return -ENOSYS;
+ }
+
+@@ -592,13 +599,13 @@ static int c2_process_mad(struct ib_device *ibdev,
+ struct ib_grh *in_grh,
+ struct ib_mad *in_mad, struct ib_mad *out_mad)
+ {
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+ return -ENOSYS;
+ }
+
+ static int c2_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
+ {
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+
+ /* Request a connection */
+ return c2_llp_connect(cm_id, iw_param);
+@@ -606,7 +613,7 @@ static int c2_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
+
+ static int c2_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
+ {
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+
+ /* Accept the new connection */
+ return c2_llp_accept(cm_id, iw_param);
+@@ -616,7 +623,7 @@ static int c2_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
+ {
+ int err;
+
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+
+ err = c2_llp_reject(cm_id, pdata, pdata_len);
+ return err;
+@@ -626,10 +633,10 @@ static int c2_service_create(struct iw_cm_id *cm_id, int backlog)
+ {
+ int err;
+
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+ err = c2_llp_service_create(cm_id, backlog);
+ pr_debug("%s:%u err=%d\n",
+- __FUNCTION__, __LINE__,
++ __func__, __LINE__,
+ err);
+ return err;
+ }
+@@ -637,7 +644,7 @@ static int c2_service_create(struct iw_cm_id *cm_id, int backlog)
+ static int c2_service_destroy(struct iw_cm_id *cm_id)
+ {
+ int err;
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+
+ err = c2_llp_service_destroy(cm_id);
+
+@@ -743,7 +750,7 @@ static struct net_device *c2_pseudo_netdev_init(struct c2_dev *c2dev)
+ netdev = alloc_netdev(sizeof(*netdev), name, setup);
+ if (!netdev) {
+ printk(KERN_ERR PFX "%s - etherdev alloc failed",
+- __FUNCTION__);
++ __func__);
+ return NULL;
+ }
+
+@@ -780,7 +787,7 @@ int c2_register_device(struct c2_dev *dev)
+ if (ret)
+ goto out2;
+
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+ strlcpy(dev->ibdev.name, "amso%d", IB_DEVICE_NAME_MAX);
+ dev->ibdev.owner = THIS_MODULE;
+ dev->ibdev.uverbs_cmd_mask =
+@@ -858,9 +865,9 @@ int c2_register_device(struct c2_dev *dev)
+ if (ret)
+ goto out1;
+
+- for (i = 0; i < ARRAY_SIZE(c2_class_attributes); ++i) {
+- ret = class_device_create_file(&dev->ibdev.class_dev,
+- c2_class_attributes[i]);
++ for (i = 0; i < ARRAY_SIZE(c2_dev_attributes); ++i) {
++ ret = device_create_file(&dev->ibdev.dev,
++ c2_dev_attributes[i]);
+ if (ret)
+ goto out0;
+ }
+@@ -873,13 +880,13 @@ out1:
+ out2:
+ free_netdev(dev->pseudo_netdev);
+ out3:
+- pr_debug("%s:%u ret=%d\n", __FUNCTION__, __LINE__, ret);
++ pr_debug("%s:%u ret=%d\n", __func__, __LINE__, ret);
+ return ret;
+ }
+
+ void c2_unregister_device(struct c2_dev *dev)
+ {
+- pr_debug("%s:%u\n", __FUNCTION__, __LINE__);
++ pr_debug("%s:%u\n", __func__, __LINE__);
+ unregister_netdev(dev->pseudo_netdev);
+ free_netdev(dev->pseudo_netdev);
+ ib_unregister_device(&dev->ibdev);
+diff --git a/drivers/infiniband/hw/amso1100/c2_qp.c b/drivers/infiniband/hw/amso1100/c2_qp.c
+index 01d0786..a6d8944 100644
+--- a/drivers/infiniband/hw/amso1100/c2_qp.c
++++ b/drivers/infiniband/hw/amso1100/c2_qp.c
+@@ -121,7 +121,7 @@ void c2_set_qp_state(struct c2_qp *qp, int c2_state)
+ int new_state = to_ib_state(c2_state);
+
+ pr_debug("%s: qp[%p] state modify %s --> %s\n",
+- __FUNCTION__,
++ __func__,
+ qp,
+ to_ib_state_str(qp->state),
+ to_ib_state_str(new_state));
+@@ -141,7 +141,7 @@ int c2_qp_modify(struct c2_dev *c2dev, struct c2_qp *qp,
+ int err;
+
+ pr_debug("%s:%d qp=%p, %s --> %s\n",
+- __FUNCTION__, __LINE__,
++ __func__, __LINE__,
+ qp,
+ to_ib_state_str(qp->state),
+ to_ib_state_str(attr->qp_state));
+@@ -224,7 +224,7 @@ int c2_qp_modify(struct c2_dev *c2dev, struct c2_qp *qp,
+ qp->state = next_state;
+ #ifdef DEBUG
+ else
+- pr_debug("%s: c2_errno=%d\n", __FUNCTION__, err);
++ pr_debug("%s: c2_errno=%d\n", __func__, err);
+ #endif
+ /*
+ * If we're going to error and generating the event here, then
+@@ -243,7 +243,7 @@ int c2_qp_modify(struct c2_dev *c2dev, struct c2_qp *qp,
+ vq_req_free(c2dev, vq_req);
+
+ pr_debug("%s:%d qp=%p, cur_state=%s\n",
+- __FUNCTION__, __LINE__,
++ __func__, __LINE__,
+ qp,
+ to_ib_state_str(qp->state));
+ return err;
+@@ -811,16 +811,24 @@ int c2_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
+
+ switch (ib_wr->opcode) {
+ case IB_WR_SEND:
+- if (ib_wr->send_flags & IB_SEND_SOLICITED) {
+- c2_wr_set_id(&wr, C2_WR_TYPE_SEND_SE);
+- msg_size = sizeof(struct c2wr_send_req);
++ case IB_WR_SEND_WITH_INV:
++ if (ib_wr->opcode == IB_WR_SEND) {
++ if (ib_wr->send_flags & IB_SEND_SOLICITED)
++ c2_wr_set_id(&wr, C2_WR_TYPE_SEND_SE);
++ else
++ c2_wr_set_id(&wr, C2_WR_TYPE_SEND);
++ wr.sqwr.send.remote_stag = 0;
+ } else {
+- c2_wr_set_id(&wr, C2_WR_TYPE_SEND);
+- msg_size = sizeof(struct c2wr_send_req);
++ if (ib_wr->send_flags & IB_SEND_SOLICITED)
++ c2_wr_set_id(&wr, C2_WR_TYPE_SEND_SE_INV);
++ else
++ c2_wr_set_id(&wr, C2_WR_TYPE_SEND_INV);
++ wr.sqwr.send.remote_stag =
++ cpu_to_be32(ib_wr->ex.invalidate_rkey);
+ }
+
+- wr.sqwr.send.remote_stag = 0;
+- msg_size += sizeof(struct c2_data_addr) * ib_wr->num_sge;
++ msg_size = sizeof(struct c2wr_send_req) +
++ sizeof(struct c2_data_addr) * ib_wr->num_sge;
+ if (ib_wr->num_sge > qp->send_sgl_depth) {
+ err = -EINVAL;
+ break;
+diff --git a/drivers/infiniband/hw/amso1100/c2_rnic.c b/drivers/infiniband/hw/amso1100/c2_rnic.c
+index 1687c51..9a054c6 100644
+--- a/drivers/infiniband/hw/amso1100/c2_rnic.c
++++ b/drivers/infiniband/hw/amso1100/c2_rnic.c
+@@ -208,7 +208,7 @@ static int c2_rnic_query(struct c2_dev *c2dev, struct ib_device_attr *props)
+ /*
+ * Add an IP address to the RNIC interface
+ */
+-int c2_add_addr(struct c2_dev *c2dev, u32 inaddr, u32 inmask)
++int c2_add_addr(struct c2_dev *c2dev, __be32 inaddr, __be32 inmask)
+ {
+ struct c2_vq_req *vq_req;
+ struct c2wr_rnic_setconfig_req *wr;
+@@ -270,7 +270,7 @@ int c2_add_addr(struct c2_dev *c2dev, u32 inaddr, u32 inmask)
+ /*
+ * Delete an IP address from the RNIC interface
+ */
+-int c2_del_addr(struct c2_dev *c2dev, u32 inaddr, u32 inmask)
++int c2_del_addr(struct c2_dev *c2dev, __be32 inaddr, __be32 inmask)
+ {
+ struct c2_vq_req *vq_req;
+ struct c2wr_rnic_setconfig_req *wr;
+@@ -455,7 +455,8 @@ int __devinit c2_rnic_init(struct c2_dev *c2dev)
+ IB_DEVICE_CURR_QP_STATE_MOD |
+ IB_DEVICE_SYS_IMAGE_GUID |
+ IB_DEVICE_ZERO_STAG |
+- IB_DEVICE_SEND_W_INV | IB_DEVICE_MEM_WINDOW);
++ IB_DEVICE_MEM_WINDOW |
++ IB_DEVICE_SEND_W_INV);
+
+ /* Allocate the qptr_array */
+ c2dev->qptr_array = vmalloc(C2_MAX_CQS * sizeof(void *));
+@@ -506,17 +507,17 @@ int __devinit c2_rnic_init(struct c2_dev *c2dev)
+ mmio_regs = c2dev->kva;
+ /* Initialize the Verbs Request Queue */
+ c2_mq_req_init(&c2dev->req_vq, 0,
+- be32_to_cpu(readl(mmio_regs + C2_REGS_Q0_QSIZE)),
+- be32_to_cpu(readl(mmio_regs + C2_REGS_Q0_MSGSIZE)),
++ be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q0_QSIZE)),
++ be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q0_MSGSIZE)),
+ mmio_regs +
+- be32_to_cpu(readl(mmio_regs + C2_REGS_Q0_POOLSTART)),
++ be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q0_POOLSTART)),
+ mmio_regs +
+- be32_to_cpu(readl(mmio_regs + C2_REGS_Q0_SHARED)),
++ be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q0_SHARED)),
+ C2_MQ_ADAPTER_TARGET);
+
+ /* Initialize the Verbs Reply Queue */
+- qsize = be32_to_cpu(readl(mmio_regs + C2_REGS_Q1_QSIZE));
+- msgsize = be32_to_cpu(readl(mmio_regs + C2_REGS_Q1_MSGSIZE));
++ qsize = be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q1_QSIZE));
++ msgsize = be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q1_MSGSIZE));
+ q1_pages = dma_alloc_coherent(&c2dev->pcidev->dev, qsize * msgsize,
+ &c2dev->rep_vq.host_dma, GFP_KERNEL);
+ if (!q1_pages) {
+@@ -524,7 +525,7 @@ int __devinit c2_rnic_init(struct c2_dev *c2dev)
+ goto bail1;
+ }
+ pci_unmap_addr_set(&c2dev->rep_vq, mapping, c2dev->rep_vq.host_dma);
+- pr_debug("%s rep_vq va %p dma %llx\n", __FUNCTION__, q1_pages,
++ pr_debug("%s rep_vq va %p dma %llx\n", __func__, q1_pages,
+ (unsigned long long) c2dev->rep_vq.host_dma);
+ c2_mq_rep_init(&c2dev->rep_vq,
+ 1,
+@@ -532,12 +533,12 @@ int __devinit c2_rnic_init(struct c2_dev *c2dev)
+ msgsize,
+ q1_pages,
+ mmio_regs +
+- be32_to_cpu(readl(mmio_regs + C2_REGS_Q1_SHARED)),
++ be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q1_SHARED)),
+ C2_MQ_HOST_TARGET);
+
+ /* Initialize the Asynchronus Event Queue */
+- qsize = be32_to_cpu(readl(mmio_regs + C2_REGS_Q2_QSIZE));
+- msgsize = be32_to_cpu(readl(mmio_regs + C2_REGS_Q2_MSGSIZE));
++ qsize = be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q2_QSIZE));
++ msgsize = be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q2_MSGSIZE));
+ q2_pages = dma_alloc_coherent(&c2dev->pcidev->dev, qsize * msgsize,
+ &c2dev->aeq.host_dma, GFP_KERNEL);
+ if (!q2_pages) {
+@@ -545,7 +546,7 @@ int __devinit c2_rnic_init(struct c2_dev *c2dev)
+ goto bail2;
+ }
+ pci_unmap_addr_set(&c2dev->aeq, mapping, c2dev->aeq.host_dma);
+- pr_debug("%s aeq va %p dma %llx\n", __FUNCTION__, q2_pages,
++ pr_debug("%s aeq va %p dma %llx\n", __func__, q2_pages,
+ (unsigned long long) c2dev->aeq.host_dma);
+ c2_mq_rep_init(&c2dev->aeq,
+ 2,
+@@ -553,7 +554,7 @@ int __devinit c2_rnic_init(struct c2_dev *c2dev)
+ msgsize,
+ q2_pages,
+ mmio_regs +
+- be32_to_cpu(readl(mmio_regs + C2_REGS_Q2_SHARED)),
++ be32_to_cpu((__force __be32) readl(mmio_regs + C2_REGS_Q2_SHARED)),
+ C2_MQ_HOST_TARGET);
+
+ /* Initialize the verbs request allocator */
+diff --git a/drivers/infiniband/hw/amso1100/c2_vq.c b/drivers/infiniband/hw/amso1100/c2_vq.c
+index cfdacb1..9ce7819 100644
+--- a/drivers/infiniband/hw/amso1100/c2_vq.c
++++ b/drivers/infiniband/hw/amso1100/c2_vq.c
+@@ -197,7 +197,7 @@ int vq_send_wr(struct c2_dev *c2dev, union c2wr *wr)
+ */
+ while (msg == NULL) {
+ pr_debug("%s:%d no available msg in VQ, waiting...\n",
+- __FUNCTION__, __LINE__);
++ __func__, __LINE__);
+ init_waitqueue_entry(&__wait, current);
+ add_wait_queue(&c2dev->req_vq_wo, &__wait);
+ spin_unlock(&c2dev->vqlock);
+diff --git a/drivers/infiniband/hw/amso1100/c2_wr.h b/drivers/infiniband/hw/amso1100/c2_wr.h
+index 3ec6c43..c65fbdd 100644
+--- a/drivers/infiniband/hw/amso1100/c2_wr.h
++++ b/drivers/infiniband/hw/amso1100/c2_wr.h
+@@ -180,8 +180,8 @@ enum c2_wr_type {
+ };
+
+ struct c2_netaddr {
+- u32 ip_addr;
+- u32 netmask;
++ __be32 ip_addr;
++ __be32 netmask;
+ u32 mtu;
+ };
+
+@@ -199,9 +199,9 @@ struct c2_route {
+ * A Scatter Gather Entry.
+ */
+ struct c2_data_addr {
+- u32 stag;
+- u32 length;
+- u64 to;
++ __be32 stag;
++ __be32 length;
++ __be64 to;
+ };
+
+ /*
+@@ -274,7 +274,7 @@ struct c2wr_hdr {
+ * from the host to adapter by libccil, but we copy it anyway
+ * to make the memcpy to the adapter better aligned.
+ */
+- u32 wqe_count;
++ __be32 wqe_count;
+
+ /* Put these fields next so that later 32- and 64-bit
+ * quantities are naturally aligned.
+@@ -316,8 +316,8 @@ enum c2_rnic_flags {
+ struct c2wr_rnic_open_req {
+ struct c2wr_hdr hdr;
+ u64 user_context;
+- u16 flags; /* See enum c2_rnic_flags */
+- u16 port_num;
++ __be16 flags; /* See enum c2_rnic_flags */
++ __be16 port_num;
+ } __attribute__((packed));
+
+ struct c2wr_rnic_open_rep {
+@@ -341,30 +341,30 @@ struct c2wr_rnic_query_req {
+ struct c2wr_rnic_query_rep {
+ struct c2wr_hdr hdr;
+ u64 user_context;
+- u32 vendor_id;
+- u32 part_number;
+- u32 hw_version;
+- u32 fw_ver_major;
+- u32 fw_ver_minor;
+- u32 fw_ver_patch;
++ __be32 vendor_id;
++ __be32 part_number;
++ __be32 hw_version;
++ __be32 fw_ver_major;
++ __be32 fw_ver_minor;
++ __be32 fw_ver_patch;
+ char fw_ver_build_str[WR_BUILD_STR_LEN];
+- u32 max_qps;
+- u32 max_qp_depth;
++ __be32 max_qps;
++ __be32 max_qp_depth;
+ u32 max_srq_depth;
+ u32 max_send_sgl_depth;
+ u32 max_rdma_sgl_depth;
+- u32 max_cqs;
+- u32 max_cq_depth;
++ __be32 max_cqs;
++ __be32 max_cq_depth;
+ u32 max_cq_event_handlers;
+- u32 max_mrs;
++ __be32 max_mrs;
+ u32 max_pbl_depth;
+- u32 max_pds;
+- u32 max_global_ird;
++ __be32 max_pds;
++ __be32 max_global_ird;
+ u32 max_global_ord;
+- u32 max_qp_ird;
+- u32 max_qp_ord;
++ __be32 max_qp_ird;
++ __be32 max_qp_ord;
+ u32 flags;
+- u32 max_mws;
++ __be32 max_mws;
+ u32 pbe_range_low;
+ u32 pbe_range_high;
+ u32 max_srqs;
+@@ -405,7 +405,7 @@ union c2wr_rnic_getconfig {
+ struct c2wr_rnic_setconfig_req {
+ struct c2wr_hdr hdr;
+ u32 rnic_handle;
+- u32 option; /* See c2_setconfig_cmd_t */
++ __be32 option; /* See c2_setconfig_cmd_t */
+ /* variable data and pad. See c2_netaddr and c2_route */
+ u8 data[0];
+ } __attribute__((packed)) ;
+@@ -441,18 +441,18 @@ union c2wr_rnic_close {
+ */
+ struct c2wr_cq_create_req {
+ struct c2wr_hdr hdr;
+- u64 shared_ht;
++ __be64 shared_ht;
+ u64 user_context;
+- u64 msg_pool;
++ __be64 msg_pool;
+ u32 rnic_handle;
+- u32 msg_size;
+- u32 depth;
++ __be32 msg_size;
++ __be32 depth;
+ } __attribute__((packed)) ;
+
+ struct c2wr_cq_create_rep {
+ struct c2wr_hdr hdr;
+- u32 mq_index;
+- u32 adapter_shared;
++ __be32 mq_index;
++ __be32 adapter_shared;
+ u32 cq_handle;
+ } __attribute__((packed)) ;
+
+@@ -585,40 +585,40 @@ enum c2wr_qp_flags {
+
+ struct c2wr_qp_create_req {
+ struct c2wr_hdr hdr;
+- u64 shared_sq_ht;
+- u64 shared_rq_ht;
++ __be64 shared_sq_ht;
++ __be64 shared_rq_ht;
+ u64 user_context;
+ u32 rnic_handle;
+ u32 sq_cq_handle;
+ u32 rq_cq_handle;
+- u32 sq_depth;
+- u32 rq_depth;
++ __be32 sq_depth;
++ __be32 rq_depth;
+ u32 srq_handle;
+ u32 srq_limit;
+- u32 flags; /* see enum c2wr_qp_flags */
+- u32 send_sgl_depth;
+- u32 recv_sgl_depth;
+- u32 rdma_write_sgl_depth;
+- u32 ord;
+- u32 ird;
++ __be32 flags; /* see enum c2wr_qp_flags */
++ __be32 send_sgl_depth;
++ __be32 recv_sgl_depth;
++ __be32 rdma_write_sgl_depth;
++ __be32 ord;
++ __be32 ird;
+ u32 pd_id;
+ } __attribute__((packed)) ;
+
+ struct c2wr_qp_create_rep {
+ struct c2wr_hdr hdr;
+- u32 sq_depth;
+- u32 rq_depth;
++ __be32 sq_depth;
++ __be32 rq_depth;
+ u32 send_sgl_depth;
+ u32 recv_sgl_depth;
+ u32 rdma_write_sgl_depth;
+ u32 ord;
+ u32 ird;
+- u32 sq_msg_size;
+- u32 sq_mq_index;
+- u32 sq_mq_start;
+- u32 rq_msg_size;
+- u32 rq_mq_index;
+- u32 rq_mq_start;
++ __be32 sq_msg_size;
++ __be32 sq_mq_index;
++ __be32 sq_mq_start;
++ __be32 rq_msg_size;
++ __be32 rq_mq_index;
++ __be32 rq_mq_start;
+ u32 qp_handle;
+ } __attribute__((packed)) ;
+
+@@ -667,11 +667,11 @@ struct c2wr_qp_modify_req {
+ u32 stream_msg_length;
+ u32 rnic_handle;
+ u32 qp_handle;
+- u32 next_qp_state;
+- u32 ord;
+- u32 ird;
+- u32 sq_depth;
+- u32 rq_depth;
++ __be32 next_qp_state;
++ __be32 ord;
++ __be32 ird;
++ __be32 sq_depth;
++ __be32 rq_depth;
+ u32 llp_ep_handle;
+ } __attribute__((packed)) ;
+
+@@ -721,10 +721,10 @@ struct c2wr_qp_connect_req {
+ struct c2wr_hdr hdr;
+ u32 rnic_handle;
+ u32 qp_handle;
+- u32 remote_addr;
+- u16 remote_port;
++ __be32 remote_addr;
++ __be16 remote_port;
+ u16 pad;
+- u32 private_data_length;
++ __be32 private_data_length;
+ u8 private_data[0]; /* Private data in-line. */
+ } __attribute__((packed)) ;
+
+@@ -759,25 +759,25 @@ union c2wr_nsmr_stag_alloc {
+
+ struct c2wr_nsmr_register_req {
+ struct c2wr_hdr hdr;
+- u64 va;
++ __be64 va;
+ u32 rnic_handle;
+- u16 flags;
++ __be16 flags;
+ u8 stag_key;
+ u8 pad;
+ u32 pd_id;
+- u32 pbl_depth;
+- u32 pbe_size;
+- u32 fbo;
+- u32 length;
+- u32 addrs_length;
++ __be32 pbl_depth;
++ __be32 pbe_size;
++ __be32 fbo;
++ __be32 length;
++ __be32 addrs_length;
+ /* array of paddrs (must be aligned on a 64bit boundary) */
+- u64 paddrs[0];
++ __be64 paddrs[0];
+ } __attribute__((packed)) ;
+
+ struct c2wr_nsmr_register_rep {
+ struct c2wr_hdr hdr;
+ u32 pbl_depth;
+- u32 stag_index;
++ __be32 stag_index;
+ } __attribute__((packed)) ;
+
+ union c2wr_nsmr_register {
+@@ -788,11 +788,11 @@ union c2wr_nsmr_register {
+ struct c2wr_nsmr_pbl_req {
+ struct c2wr_hdr hdr;
+ u32 rnic_handle;
+- u32 flags;
+- u32 stag_index;
+- u32 addrs_length;
++ __be32 flags;
++ __be32 stag_index;
++ __be32 addrs_length;
+ /* array of paddrs (must be aligned on a 64bit boundary) */
+- u64 paddrs[0];
++ __be64 paddrs[0];
+ } __attribute__((packed)) ;
+
+ struct c2wr_nsmr_pbl_rep {
+@@ -847,7 +847,7 @@ union c2wr_mw_query {
+ struct c2wr_stag_dealloc_req {
+ struct c2wr_hdr hdr;
+ u32 rnic_handle;
+- u32 stag_index;
++ __be32 stag_index;
+ } __attribute__((packed)) ;
+
+ struct c2wr_stag_dealloc_rep {
+@@ -949,7 +949,7 @@ struct c2wr_ce {
+ u64 qp_user_context; /* c2_user_qp_t * */
+ u32 qp_state; /* Current QP State */
+ u32 handle; /* QPID or EP Handle */
+- u32 bytes_rcvd; /* valid for RECV WCs */
++ __be32 bytes_rcvd; /* valid for RECV WCs */
+ u32 stag;
+ } __attribute__((packed)) ;
+
+@@ -984,8 +984,8 @@ struct c2_rq_hdr {
+ */
+ struct c2wr_send_req {
+ struct c2_sq_hdr sq_hdr;
+- u32 sge_len;
+- u32 remote_stag;
++ __be32 sge_len;
++ __be32 remote_stag;
+ u8 data[0]; /* SGE array */
+ } __attribute__((packed));
+
+@@ -996,9 +996,9 @@ union c2wr_send {
+
+ struct c2wr_rdma_write_req {
+ struct c2_sq_hdr sq_hdr;
+- u64 remote_to;
+- u32 remote_stag;
+- u32 sge_len;
++ __be64 remote_to;
++ __be32 remote_stag;
++ __be32 sge_len;
+ u8 data[0]; /* SGE array */
+ } __attribute__((packed));
+
+@@ -1009,11 +1009,11 @@ union c2wr_rdma_write {
+
+ struct c2wr_rdma_read_req {
+ struct c2_sq_hdr sq_hdr;
+- u64 local_to;
+- u64 remote_to;
+- u32 local_stag;
+- u32 remote_stag;
+- u32 length;
++ __be64 local_to;
++ __be64 remote_to;
++ __be32 local_stag;
++ __be32 remote_stag;
++ __be32 length;
+ } __attribute__((packed));
+
+ union c2wr_rdma_read {
+@@ -1113,9 +1113,9 @@ union c2wr_recv {
+ struct c2wr_ae_hdr {
+ struct c2wr_hdr hdr;
+ u64 user_context; /* user context for this res. */
+- u32 resource_type; /* see enum c2_resource_indicator */
+- u32 resource; /* handle for resource */
+- u32 qp_state; /* current QP State */
++ __be32 resource_type; /* see enum c2_resource_indicator */
++ __be32 resource; /* handle for resource */
++ __be32 qp_state; /* current QP State */
+ } __attribute__((packed));
+
+ /*
+@@ -1124,11 +1124,11 @@ struct c2wr_ae_hdr {
+ */
+ struct c2wr_ae_active_connect_results {
+ struct c2wr_ae_hdr ae_hdr;
+- u32 laddr;
+- u32 raddr;
+- u16 lport;
+- u16 rport;
+- u32 private_data_length;
++ __be32 laddr;
++ __be32 raddr;
++ __be16 lport;
++ __be16 rport;
++ __be32 private_data_length;
+ u8 private_data[0]; /* data is in-line in the msg. */
+ } __attribute__((packed));
+
+@@ -1142,11 +1142,11 @@ struct c2wr_ae_active_connect_results {
+ struct c2wr_ae_connection_request {
+ struct c2wr_ae_hdr ae_hdr;
+ u32 cr_handle; /* connreq handle (sock ptr) */
+- u32 laddr;
+- u32 raddr;
+- u16 lport;
+- u16 rport;
+- u32 private_data_length;
++ __be32 laddr;
++ __be32 raddr;
++ __be16 lport;
++ __be16 rport;
++ __be32 private_data_length;
+ u8 private_data[0]; /* data is in-line in the msg. */
+ } __attribute__((packed));
+
+@@ -1158,12 +1158,12 @@ union c2wr_ae {
+
+ struct c2wr_init_req {
+ struct c2wr_hdr hdr;
+- u64 hint_count;
+- u64 q0_host_shared;
+- u64 q1_host_shared;
+- u64 q1_host_msg_pool;
+- u64 q2_host_shared;
+- u64 q2_host_msg_pool;
++ __be64 hint_count;
++ __be64 q0_host_shared;
++ __be64 q1_host_shared;
++ __be64 q1_host_msg_pool;
++ __be64 q2_host_shared;
++ __be64 q2_host_msg_pool;
+ } __attribute__((packed));
+
+ struct c2wr_init_rep {
+@@ -1276,10 +1276,10 @@ struct c2wr_ep_listen_create_req {
+ struct c2wr_hdr hdr;
+ u64 user_context; /* returned in AEs. */
+ u32 rnic_handle;
+- u32 local_addr; /* local addr, or 0 */
+- u16 local_port; /* 0 means "pick one" */
++ __be32 local_addr; /* local addr, or 0 */
++ __be16 local_port; /* 0 means "pick one" */
+ u16 pad;
+- u32 backlog; /* tradional tcp listen bl */
++ __be32 backlog; /* tradional tcp listen bl */
+ } __attribute__((packed));
+
+ struct c2wr_ep_listen_create_rep {
+@@ -1340,7 +1340,7 @@ struct c2wr_cr_accept_req {
+ u32 rnic_handle;
+ u32 qp_handle; /* QP to bind to this LLP conn */
+ u32 ep_handle; /* LLP handle to accept */
+- u32 private_data_length;
++ __be32 private_data_length;
+ u8 private_data[0]; /* data in-line in msg. */
+ } __attribute__((packed));
+
+@@ -1508,7 +1508,7 @@ static __inline__ void c2_wr_set_sge_count(void *wr, u8 sge_count)
+ {
+ ((struct c2wr_hdr *) wr)->sge_count = sge_count;
+ }
+-static __inline__ u32 c2_wr_get_wqe_count(void *wr)
++static __inline__ __be32 c2_wr_get_wqe_count(void *wr)
+ {
+ return ((struct c2wr_hdr *) wr)->wqe_count;
+ }
+diff --git a/drivers/infiniband/hw/cxgb3/cxio_dbg.c b/drivers/infiniband/hw/cxgb3/cxio_dbg.c
+index 75f7b16..a8d24d5 100644
+--- a/drivers/infiniband/hw/cxgb3/cxio_dbg.c
++++ b/drivers/infiniband/hw/cxgb3/cxio_dbg.c
+@@ -45,16 +45,16 @@ void cxio_dump_tpt(struct cxio_rdev *rdev, u32 stag)
+
+ m = kmalloc(sizeof(*m) + size, GFP_ATOMIC);
+ if (!m) {
+- PDBG("%s couldn't allocate memory.\n", __FUNCTION__);
++ PDBG("%s couldn't allocate memory.\n", __func__);
+ return;
+ }
+ m->mem_id = MEM_PMRX;
+ m->addr = (stag>>8) * 32 + rdev->rnic_info.tpt_base;
+ m->len = size;
+- PDBG("%s TPT addr 0x%x len %d\n", __FUNCTION__, m->addr, m->len);
++ PDBG("%s TPT addr 0x%x len %d\n", __func__, m->addr, m->len);
+ rc = rdev->t3cdev_p->ctl(rdev->t3cdev_p, RDMA_GET_MEM, m);
+ if (rc) {
+- PDBG("%s toectl returned error %d\n", __FUNCTION__, rc);
++ PDBG("%s toectl returned error %d\n", __func__, rc);
+ kfree(m);
+ return;
+ }
+@@ -82,17 +82,17 @@ void cxio_dump_pbl(struct cxio_rdev *rdev, u32 pbl_addr, uint len, u8 shift)
+
+ m = kmalloc(sizeof(*m) + size, GFP_ATOMIC);
+ if (!m) {
+- PDBG("%s couldn't allocate memory.\n", __FUNCTION__);
++ PDBG("%s couldn't allocate memory.\n", __func__);
+ return;
+ }
+ m->mem_id = MEM_PMRX;
+ m->addr = pbl_addr;
+ m->len = size;
+ PDBG("%s PBL addr 0x%x len %d depth %d\n",
+- __FUNCTION__, m->addr, m->len, npages);
++ __func__, m->addr, m->len, npages);
+ rc = rdev->t3cdev_p->ctl(rdev->t3cdev_p, RDMA_GET_MEM, m);
+ if (rc) {
+- PDBG("%s toectl returned error %d\n", __FUNCTION__, rc);
++ PDBG("%s toectl returned error %d\n", __func__, rc);
+ kfree(m);
+ return;
+ }
+@@ -144,16 +144,16 @@ void cxio_dump_rqt(struct cxio_rdev *rdev, u32 hwtid, int nents)
+
+ m = kmalloc(sizeof(*m) + size, GFP_ATOMIC);
+ if (!m) {
+- PDBG("%s couldn't allocate memory.\n", __FUNCTION__);
++ PDBG("%s couldn't allocate memory.\n", __func__);
+ return;
+ }
+ m->mem_id = MEM_PMRX;
+ m->addr = ((hwtid)<<10) + rdev->rnic_info.rqt_base;
+ m->len = size;
+- PDBG("%s RQT addr 0x%x len %d\n", __FUNCTION__, m->addr, m->len);
++ PDBG("%s RQT addr 0x%x len %d\n", __func__, m->addr, m->len);
+ rc = rdev->t3cdev_p->ctl(rdev->t3cdev_p, RDMA_GET_MEM, m);
+ if (rc) {
+- PDBG("%s toectl returned error %d\n", __FUNCTION__, rc);
++ PDBG("%s toectl returned error %d\n", __func__, rc);
+ kfree(m);
+ return;
+ }
+@@ -177,16 +177,16 @@ void cxio_dump_tcb(struct cxio_rdev *rdev, u32 hwtid)
+
+ m = kmalloc(sizeof(*m) + size, GFP_ATOMIC);
+ if (!m) {
+- PDBG("%s couldn't allocate memory.\n", __FUNCTION__);
++ PDBG("%s couldn't allocate memory.\n", __func__);
+ return;
+ }
+ m->mem_id = MEM_CM;
+ m->addr = hwtid * size;
+ m->len = size;
+- PDBG("%s TCB %d len %d\n", __FUNCTION__, m->addr, m->len);
++ PDBG("%s TCB %d len %d\n", __func__, m->addr, m->len);
+ rc = rdev->t3cdev_p->ctl(rdev->t3cdev_p, RDMA_GET_MEM, m);
+ if (rc) {
+- PDBG("%s toectl returned error %d\n", __FUNCTION__, rc);
++ PDBG("%s toectl returned error %d\n", __func__, rc);
+ kfree(m);
+ return;
+ }
+diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.c b/drivers/infiniband/hw/cxgb3/cxio_hal.c
+index 03c5ff6..66eb703 100644
+--- a/drivers/infiniband/hw/cxgb3/cxio_hal.c
++++ b/drivers/infiniband/hw/cxgb3/cxio_hal.c
+@@ -140,7 +140,7 @@ static int cxio_hal_clear_qp_ctx(struct cxio_rdev *rdev_p, u32 qpid)
+ struct t3_modify_qp_wr *wqe;
+ struct sk_buff *skb = alloc_skb(sizeof(*wqe), GFP_KERNEL);
+ if (!skb) {
+- PDBG("%s alloc_skb failed\n", __FUNCTION__);
++ PDBG("%s alloc_skb failed\n", __func__);
+ return -ENOMEM;
+ }
+ wqe = (struct t3_modify_qp_wr *) skb_put(skb, sizeof(*wqe));
+@@ -225,7 +225,7 @@ static u32 get_qpid(struct cxio_rdev *rdev_p, struct cxio_ucontext *uctx)
+ }
+ out:
+ mutex_unlock(&uctx->lock);
+- PDBG("%s qpid 0x%x\n", __FUNCTION__, qpid);
++ PDBG("%s qpid 0x%x\n", __func__, qpid);
+ return qpid;
+ }
+
+@@ -237,7 +237,7 @@ static void put_qpid(struct cxio_rdev *rdev_p, u32 qpid,
+ entry = kmalloc(sizeof *entry, GFP_KERNEL);
+ if (!entry)
+ return;
+- PDBG("%s qpid 0x%x\n", __FUNCTION__, qpid);
++ PDBG("%s qpid 0x%x\n", __func__, qpid);
+ entry->qpid = qpid;
+ mutex_lock(&uctx->lock);
+ list_add_tail(&entry->entry, &uctx->qpids);
+@@ -300,7 +300,7 @@ int cxio_create_qp(struct cxio_rdev *rdev_p, u32 kernel_domain,
+ if (!kernel_domain)
+ wq->udb = (u64)rdev_p->rnic_info.udbell_physbase +
+ (wq->qpid << rdev_p->qpshift);
+- PDBG("%s qpid 0x%x doorbell 0x%p udb 0x%llx\n", __FUNCTION__,
++ PDBG("%s qpid 0x%x doorbell 0x%p udb 0x%llx\n", __func__,
+ wq->qpid, wq->doorbell, (unsigned long long) wq->udb);
+ return 0;
+ err4:
+@@ -345,7 +345,7 @@ static void insert_recv_cqe(struct t3_wq *wq, struct t3_cq *cq)
+ {
+ struct t3_cqe cqe;
+
+- PDBG("%s wq %p cq %p sw_rptr 0x%x sw_wptr 0x%x\n", __FUNCTION__,
++ PDBG("%s wq %p cq %p sw_rptr 0x%x sw_wptr 0x%x\n", __func__,
+ wq, cq, cq->sw_rptr, cq->sw_wptr);
+ memset(&cqe, 0, sizeof(cqe));
+ cqe.header = cpu_to_be32(V_CQE_STATUS(TPT_ERR_SWFLUSH) |
+@@ -363,10 +363,10 @@ void cxio_flush_rq(struct t3_wq *wq, struct t3_cq *cq, int count)
+ {
+ u32 ptr;
+
+- PDBG("%s wq %p cq %p\n", __FUNCTION__, wq, cq);
++ PDBG("%s wq %p cq %p\n", __func__, wq, cq);
+
+ /* flush RQ */
+- PDBG("%s rq_rptr %u rq_wptr %u skip count %u\n", __FUNCTION__,
++ PDBG("%s rq_rptr %u rq_wptr %u skip count %u\n", __func__,
+ wq->rq_rptr, wq->rq_wptr, count);
+ ptr = wq->rq_rptr + count;
+ while (ptr++ != wq->rq_wptr)
+@@ -378,7 +378,7 @@ static void insert_sq_cqe(struct t3_wq *wq, struct t3_cq *cq,
+ {
+ struct t3_cqe cqe;
+
+- PDBG("%s wq %p cq %p sw_rptr 0x%x sw_wptr 0x%x\n", __FUNCTION__,
++ PDBG("%s wq %p cq %p sw_rptr 0x%x sw_wptr 0x%x\n", __func__,
+ wq, cq, cq->sw_rptr, cq->sw_wptr);
+ memset(&cqe, 0, sizeof(cqe));
+ cqe.header = cpu_to_be32(V_CQE_STATUS(TPT_ERR_SWFLUSH) |
+@@ -415,11 +415,11 @@ void cxio_flush_hw_cq(struct t3_cq *cq)
+ {
+ struct t3_cqe *cqe, *swcqe;
+
+- PDBG("%s cq %p cqid 0x%x\n", __FUNCTION__, cq, cq->cqid);
++ PDBG("%s cq %p cqid 0x%x\n", __func__, cq, cq->cqid);
+ cqe = cxio_next_hw_cqe(cq);
+ while (cqe) {
+ PDBG("%s flushing hwcq rptr 0x%x to swcq wptr 0x%x\n",
+- __FUNCTION__, cq->rptr, cq->sw_wptr);
++ __func__, cq->rptr, cq->sw_wptr);
+ swcqe = cq->sw_queue + Q_PTR2IDX(cq->sw_wptr, cq->size_log2);
+ *swcqe = *cqe;
+ swcqe->header |= cpu_to_be32(V_CQE_SWCQE(1));
+@@ -461,7 +461,7 @@ void cxio_count_scqes(struct t3_cq *cq, struct t3_wq *wq, int *count)
+ (*count)++;
+ ptr++;
+ }
+- PDBG("%s cq %p count %d\n", __FUNCTION__, cq, *count);
++ PDBG("%s cq %p count %d\n", __func__, cq, *count);
+ }
+
+ void cxio_count_rcqes(struct t3_cq *cq, struct t3_wq *wq, int *count)
+@@ -470,7 +470,7 @@ void cxio_count_rcqes(struct t3_cq *cq, struct t3_wq *wq, int *count)
+ u32 ptr;
+
+ *count = 0;
+- PDBG("%s count zero %d\n", __FUNCTION__, *count);
++ PDBG("%s count zero %d\n", __func__, *count);
+ ptr = cq->sw_rptr;
+ while (!Q_EMPTY(ptr, cq->sw_wptr)) {
+ cqe = cq->sw_queue + (Q_PTR2IDX(ptr, cq->size_log2));
+@@ -479,7 +479,7 @@ void cxio_count_rcqes(struct t3_cq *cq, struct t3_wq *wq, int *count)
+ (*count)++;
+ ptr++;
+ }
+- PDBG("%s cq %p count %d\n", __FUNCTION__, cq, *count);
++ PDBG("%s cq %p count %d\n", __func__, cq, *count);
+ }
+
+ static int cxio_hal_init_ctrl_cq(struct cxio_rdev *rdev_p)
+@@ -506,12 +506,12 @@ static int cxio_hal_init_ctrl_qp(struct cxio_rdev *rdev_p)
+
+ skb = alloc_skb(sizeof(*wqe), GFP_KERNEL);
+ if (!skb) {
+- PDBG("%s alloc_skb failed\n", __FUNCTION__);
++ PDBG("%s alloc_skb failed\n", __func__);
+ return -ENOMEM;
+ }
+ err = cxio_hal_init_ctrl_cq(rdev_p);
+ if (err) {
+- PDBG("%s err %d initializing ctrl_cq\n", __FUNCTION__, err);
++ PDBG("%s err %d initializing ctrl_cq\n", __func__, err);
+ goto err;
+ }
+ rdev_p->ctrl_qp.workq = dma_alloc_coherent(
+@@ -521,7 +521,7 @@ static int cxio_hal_init_ctrl_qp(struct cxio_rdev *rdev_p)
+ &(rdev_p->ctrl_qp.dma_addr),
+ GFP_KERNEL);
+ if (!rdev_p->ctrl_qp.workq) {
+- PDBG("%s dma_alloc_coherent failed\n", __FUNCTION__);
++ PDBG("%s dma_alloc_coherent failed\n", __func__);
+ err = -ENOMEM;
+ goto err;
+ }
+@@ -591,25 +591,25 @@ static int cxio_hal_ctrl_qp_write_mem(struct cxio_rdev *rdev_p, u32 addr,
+ addr &= 0x7FFFFFF;
+ nr_wqe = len % 96 ? len / 96 + 1 : len / 96; /* 96B max per WQE */
+ PDBG("%s wptr 0x%x rptr 0x%x len %d, nr_wqe %d data %p addr 0x%0x\n",
+- __FUNCTION__, rdev_p->ctrl_qp.wptr, rdev_p->ctrl_qp.rptr, len,
++ __func__, rdev_p->ctrl_qp.wptr, rdev_p->ctrl_qp.rptr, len,
+ nr_wqe, data, addr);
+ utx_len = 3; /* in 32B unit */
+ for (i = 0; i < nr_wqe; i++) {
+ if (Q_FULL(rdev_p->ctrl_qp.rptr, rdev_p->ctrl_qp.wptr,
+ T3_CTRL_QP_SIZE_LOG2)) {
+ PDBG("%s ctrl_qp full wtpr 0x%0x rptr 0x%0x, "
+- "wait for more space i %d\n", __FUNCTION__,
++ "wait for more space i %d\n", __func__,
+ rdev_p->ctrl_qp.wptr, rdev_p->ctrl_qp.rptr, i);
+ if (wait_event_interruptible(rdev_p->ctrl_qp.waitq,
+ !Q_FULL(rdev_p->ctrl_qp.rptr,
+ rdev_p->ctrl_qp.wptr,
+ T3_CTRL_QP_SIZE_LOG2))) {
+ PDBG("%s ctrl_qp workq interrupted\n",
+- __FUNCTION__);
++ __func__);
+ return -ERESTARTSYS;
+ }
+ PDBG("%s ctrl_qp wakeup, continue posting work request "
+- "i %d\n", __FUNCTION__, i);
++ "i %d\n", __func__, i);
+ }
+ wqe = (__be64 *)(rdev_p->ctrl_qp.workq + (rdev_p->ctrl_qp.wptr %
+ (1 << T3_CTRL_QP_SIZE_LOG2)));
+@@ -630,7 +630,7 @@ static int cxio_hal_ctrl_qp_write_mem(struct cxio_rdev *rdev_p, u32 addr,
+ if ((i != 0) &&
+ (i % (((1 << T3_CTRL_QP_SIZE_LOG2)) >> 1) == 0)) {
+ flag = T3_COMPLETION_FLAG;
+- PDBG("%s force completion at i %d\n", __FUNCTION__, i);
++ PDBG("%s force completion at i %d\n", __func__, i);
+ }
+
+ /* build the utx mem command */
+@@ -701,7 +701,7 @@ static int __cxio_tpt_op(struct cxio_rdev *rdev_p, u32 reset_tpt_entry,
+ *stag = (stag_idx << 8) | ((*stag) & 0xFF);
+ }
+ PDBG("%s stag_state 0x%0x type 0x%0x pdid 0x%0x, stag_idx 0x%x\n",
+- __FUNCTION__, stag_state, type, pdid, stag_idx);
++ __func__, stag_state, type, pdid, stag_idx);
+
+ if (reset_tpt_entry)
+ cxio_hal_pblpool_free(rdev_p, *pbl_addr, *pbl_size << 3);
+@@ -718,7 +718,7 @@ static int __cxio_tpt_op(struct cxio_rdev *rdev_p, u32 reset_tpt_entry,
+ if (pbl) {
+
+ PDBG("%s *pdb_addr 0x%x, pbl_base 0x%x, pbl_size %d\n",
+- __FUNCTION__, *pbl_addr, rdev_p->rnic_info.pbl_base,
++ __func__, *pbl_addr, rdev_p->rnic_info.pbl_base,
+ *pbl_size);
+ err = cxio_hal_ctrl_qp_write_mem(rdev_p,
+ (*pbl_addr >> 5),
+@@ -814,7 +814,7 @@ int cxio_rdma_init(struct cxio_rdev *rdev_p, struct t3_rdma_init_attr *attr)
+ struct sk_buff *skb = alloc_skb(sizeof(*wqe), GFP_ATOMIC);
+ if (!skb)
+ return -ENOMEM;
+- PDBG("%s rdev_p %p\n", __FUNCTION__, rdev_p);
++ PDBG("%s rdev_p %p\n", __func__, rdev_p);
+ wqe = (struct t3_rdma_init_wr *) __skb_put(skb, sizeof(*wqe));
+ wqe->wrh.op_seop_flags = cpu_to_be32(V_FW_RIWR_OP(T3_WR_INIT));
+ wqe->wrh.gen_tid_len = cpu_to_be32(V_FW_RIWR_TID(attr->tid) |
+@@ -856,7 +856,7 @@ static int cxio_hal_ev_handler(struct t3cdev *t3cdev_p, struct sk_buff *skb)
+ struct respQ_msg_t *rsp_msg = (struct respQ_msg_t *) skb->data;
+ PDBG("%d: %s cq_id 0x%x cq_ptr 0x%x genbit %0x overflow %0x an %0x"
+ " se %0x notify %0x cqbranch %0x creditth %0x\n",
+- cnt, __FUNCTION__, RSPQ_CQID(rsp_msg), RSPQ_CQPTR(rsp_msg),
++ cnt, __func__, RSPQ_CQID(rsp_msg), RSPQ_CQPTR(rsp_msg),
+ RSPQ_GENBIT(rsp_msg), RSPQ_OVERFLOW(rsp_msg), RSPQ_AN(rsp_msg),
+ RSPQ_SE(rsp_msg), RSPQ_NOTIFY(rsp_msg), RSPQ_CQBRANCH(rsp_msg),
+ RSPQ_CREDIT_THRESH(rsp_msg));
+@@ -868,7 +868,7 @@ static int cxio_hal_ev_handler(struct t3cdev *t3cdev_p, struct sk_buff *skb)
+ CQE_WRID_HI(rsp_msg->cqe), CQE_WRID_LOW(rsp_msg->cqe));
+ rdev_p = (struct cxio_rdev *)t3cdev_p->ulp;
+ if (!rdev_p) {
+- PDBG("%s called by t3cdev %p with null ulp\n", __FUNCTION__,
++ PDBG("%s called by t3cdev %p with null ulp\n", __func__,
+ t3cdev_p);
+ return 0;
+ }
+@@ -908,13 +908,13 @@ int cxio_rdev_open(struct cxio_rdev *rdev_p)
+ strncpy(rdev_p->dev_name, rdev_p->t3cdev_p->name,
+ T3_MAX_DEV_NAME_LEN);
+ } else {
+- PDBG("%s t3cdev_p or dev_name must be set\n", __FUNCTION__);
++ PDBG("%s t3cdev_p or dev_name must be set\n", __func__);
+ return -EINVAL;
+ }
+
+ list_add_tail(&rdev_p->entry, &rdev_list);
+
+- PDBG("%s opening rnic dev %s\n", __FUNCTION__, rdev_p->dev_name);
++ PDBG("%s opening rnic dev %s\n", __func__, rdev_p->dev_name);
+ memset(&rdev_p->ctrl_qp, 0, sizeof(rdev_p->ctrl_qp));
+ if (!rdev_p->t3cdev_p)
+ rdev_p->t3cdev_p = dev2t3cdev(netdev_p);
+@@ -923,14 +923,14 @@ int cxio_rdev_open(struct cxio_rdev *rdev_p)
+ &(rdev_p->rnic_info));
+ if (err) {
+ printk(KERN_ERR "%s t3cdev_p(%p)->ctl returned error %d.\n",
+- __FUNCTION__, rdev_p->t3cdev_p, err);
++ __func__, rdev_p->t3cdev_p, err);
+ goto err1;
+ }
+ err = rdev_p->t3cdev_p->ctl(rdev_p->t3cdev_p, GET_PORTS,
+ &(rdev_p->port_info));
+ if (err) {
+ printk(KERN_ERR "%s t3cdev_p(%p)->ctl returned error %d.\n",
+- __FUNCTION__, rdev_p->t3cdev_p, err);
++ __func__, rdev_p->t3cdev_p, err);
+ goto err1;
+ }
+
+@@ -947,7 +947,7 @@ int cxio_rdev_open(struct cxio_rdev *rdev_p)
+ rdev_p->qpmask = (65536 >> ilog2(rdev_p->qpnr)) - 1;
+ PDBG("%s rnic %s info: tpt_base 0x%0x tpt_top 0x%0x num stags %d "
+ "pbl_base 0x%0x pbl_top 0x%0x rqt_base 0x%0x, rqt_top 0x%0x\n",
+- __FUNCTION__, rdev_p->dev_name, rdev_p->rnic_info.tpt_base,
++ __func__, rdev_p->dev_name, rdev_p->rnic_info.tpt_base,
+ rdev_p->rnic_info.tpt_top, cxio_num_stags(rdev_p),
+ rdev_p->rnic_info.pbl_base,
+ rdev_p->rnic_info.pbl_top, rdev_p->rnic_info.rqt_base,
+@@ -961,7 +961,7 @@ int cxio_rdev_open(struct cxio_rdev *rdev_p)
+ err = cxio_hal_init_ctrl_qp(rdev_p);
+ if (err) {
+ printk(KERN_ERR "%s error %d initializing ctrl_qp.\n",
+- __FUNCTION__, err);
++ __func__, err);
+ goto err1;
+ }
+ err = cxio_hal_init_resource(rdev_p, cxio_num_stags(rdev_p), 0,
+@@ -969,19 +969,19 @@ int cxio_rdev_open(struct cxio_rdev *rdev_p)
+ T3_MAX_NUM_PD);
+ if (err) {
+ printk(KERN_ERR "%s error %d initializing hal resources.\n",
+- __FUNCTION__, err);
++ __func__, err);
+ goto err2;
+ }
+ err = cxio_hal_pblpool_create(rdev_p);
+ if (err) {
+ printk(KERN_ERR "%s error %d initializing pbl mem pool.\n",
+- __FUNCTION__, err);
++ __func__, err);
+ goto err3;
+ }
+ err = cxio_hal_rqtpool_create(rdev_p);
+ if (err) {
+ printk(KERN_ERR "%s error %d initializing rqt mem pool.\n",
+- __FUNCTION__, err);
++ __func__, err);
+ goto err4;
+ }
+ return 0;
+@@ -1043,7 +1043,7 @@ static void flush_completed_wrs(struct t3_wq *wq, struct t3_cq *cq)
+ * Insert this completed cqe into the swcq.
+ */
+ PDBG("%s moving cqe into swcq sq idx %ld cq idx %ld\n",
+- __FUNCTION__, Q_PTR2IDX(ptr, wq->sq_size_log2),
++ __func__, Q_PTR2IDX(ptr, wq->sq_size_log2),
+ Q_PTR2IDX(cq->sw_wptr, cq->size_log2));
+ sqp->cqe.header |= htonl(V_CQE_SWCQE(1));
+ *(cq->sw_queue + Q_PTR2IDX(cq->sw_wptr, cq->size_log2))
+@@ -1112,7 +1112,7 @@ int cxio_poll_cq(struct t3_wq *wq, struct t3_cq *cq, struct t3_cqe *cqe,
+
+ PDBG("%s CQE OOO %d qpid 0x%0x genbit %d type %d status 0x%0x"
+ " opcode 0x%0x len 0x%0x wrid_hi_stag 0x%x wrid_low_msn 0x%x\n",
+- __FUNCTION__, CQE_OOO(*hw_cqe), CQE_QPID(*hw_cqe),
++ __func__, CQE_OOO(*hw_cqe), CQE_QPID(*hw_cqe),
+ CQE_GENBIT(*hw_cqe), CQE_TYPE(*hw_cqe), CQE_STATUS(*hw_cqe),
+ CQE_OPCODE(*hw_cqe), CQE_LEN(*hw_cqe), CQE_WRID_HI(*hw_cqe),
+ CQE_WRID_LOW(*hw_cqe));
+@@ -1215,7 +1215,7 @@ int cxio_poll_cq(struct t3_wq *wq, struct t3_cq *cq, struct t3_cqe *cqe,
+ struct t3_swsq *sqp;
+
+ PDBG("%s out of order completion going in swsq at idx %ld\n",
+- __FUNCTION__,
++ __func__,
+ Q_PTR2IDX(CQE_WRID_SQ_WPTR(*hw_cqe), wq->sq_size_log2));
+ sqp = wq->sq +
+ Q_PTR2IDX(CQE_WRID_SQ_WPTR(*hw_cqe), wq->sq_size_log2);
+@@ -1234,13 +1234,13 @@ proc_cqe:
+ */
+ if (SQ_TYPE(*hw_cqe)) {
+ wq->sq_rptr = CQE_WRID_SQ_WPTR(*hw_cqe);
+- PDBG("%s completing sq idx %ld\n", __FUNCTION__,
++ PDBG("%s completing sq idx %ld\n", __func__,
+ Q_PTR2IDX(wq->sq_rptr, wq->sq_size_log2));
+ *cookie = (wq->sq +
+ Q_PTR2IDX(wq->sq_rptr, wq->sq_size_log2))->wr_id;
+ wq->sq_rptr++;
+ } else {
+- PDBG("%s completing rq idx %ld\n", __FUNCTION__,
++ PDBG("%s completing rq idx %ld\n", __func__,
+ Q_PTR2IDX(wq->rq_rptr, wq->rq_size_log2));
+ *cookie = *(wq->rq + Q_PTR2IDX(wq->rq_rptr, wq->rq_size_log2));
+ wq->rq_rptr++;
+@@ -1255,11 +1255,11 @@ flush_wq:
+ skip_cqe:
+ if (SW_CQE(*hw_cqe)) {
+ PDBG("%s cq %p cqid 0x%x skip sw cqe sw_rptr 0x%x\n",
+- __FUNCTION__, cq, cq->cqid, cq->sw_rptr);
++ __func__, cq, cq->cqid, cq->sw_rptr);
+ ++cq->sw_rptr;
+ } else {
+ PDBG("%s cq %p cqid 0x%x skip hw cqe rptr 0x%x\n",
+- __FUNCTION__, cq, cq->cqid, cq->rptr);
++ __func__, cq, cq->cqid, cq->rptr);
+ ++cq->rptr;
+
+ /*
+diff --git a/drivers/infiniband/hw/cxgb3/cxio_resource.c b/drivers/infiniband/hw/cxgb3/cxio_resource.c
+index d3095ae..45ed4f2 100644
+--- a/drivers/infiniband/hw/cxgb3/cxio_resource.c
++++ b/drivers/infiniband/hw/cxgb3/cxio_resource.c
+@@ -206,13 +206,13 @@ void cxio_hal_put_stag(struct cxio_hal_resource *rscp, u32 stag)
+ u32 cxio_hal_get_qpid(struct cxio_hal_resource *rscp)
+ {
+ u32 qpid = cxio_hal_get_resource(rscp->qpid_fifo);
+- PDBG("%s qpid 0x%x\n", __FUNCTION__, qpid);
++ PDBG("%s qpid 0x%x\n", __func__, qpid);
+ return qpid;
+ }
+
+ void cxio_hal_put_qpid(struct cxio_hal_resource *rscp, u32 qpid)
+ {
+- PDBG("%s qpid 0x%x\n", __FUNCTION__, qpid);
++ PDBG("%s qpid 0x%x\n", __func__, qpid);
+ cxio_hal_put_resource(rscp->qpid_fifo, qpid);
+ }
+
+@@ -255,13 +255,13 @@ void cxio_hal_destroy_resource(struct cxio_hal_resource *rscp)
+ u32 cxio_hal_pblpool_alloc(struct cxio_rdev *rdev_p, int size)
+ {
+ unsigned long addr = gen_pool_alloc(rdev_p->pbl_pool, size);
+- PDBG("%s addr 0x%x size %d\n", __FUNCTION__, (u32)addr, size);
++ PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size);
+ return (u32)addr;
+ }
+
+ void cxio_hal_pblpool_free(struct cxio_rdev *rdev_p, u32 addr, int size)
+ {
+- PDBG("%s addr 0x%x size %d\n", __FUNCTION__, addr, size);
++ PDBG("%s addr 0x%x size %d\n", __func__, addr, size);
+ gen_pool_free(rdev_p->pbl_pool, (unsigned long)addr, size);
+ }
+
+@@ -292,13 +292,13 @@ void cxio_hal_pblpool_destroy(struct cxio_rdev *rdev_p)
+ u32 cxio_hal_rqtpool_alloc(struct cxio_rdev *rdev_p, int size)
+ {
+ unsigned long addr = gen_pool_alloc(rdev_p->rqt_pool, size << 6);
+- PDBG("%s addr 0x%x size %d\n", __FUNCTION__, (u32)addr, size << 6);
++ PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size << 6);
+ return (u32)addr;
+ }
+
+ void cxio_hal_rqtpool_free(struct cxio_rdev *rdev_p, u32 addr, int size)
+ {
+- PDBG("%s addr 0x%x size %d\n", __FUNCTION__, addr, size << 6);
++ PDBG("%s addr 0x%x size %d\n", __func__, addr, size << 6);
+ gen_pool_free(rdev_p->rqt_pool, (unsigned long)addr, size << 6);
+ }
+
+diff --git a/drivers/infiniband/hw/cxgb3/iwch.c b/drivers/infiniband/hw/cxgb3/iwch.c
+index 0315c9d..6ba4138 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch.c
++++ b/drivers/infiniband/hw/cxgb3/iwch.c
+@@ -65,7 +65,7 @@ static DEFINE_MUTEX(dev_mutex);
+
+ static void rnic_init(struct iwch_dev *rnicp)
+ {
+- PDBG("%s iwch_dev %p\n", __FUNCTION__, rnicp);
++ PDBG("%s iwch_dev %p\n", __func__, rnicp);
+ idr_init(&rnicp->cqidr);
+ idr_init(&rnicp->qpidr);
+ idr_init(&rnicp->mmidr);
+@@ -106,7 +106,7 @@ static void open_rnic_dev(struct t3cdev *tdev)
+ struct iwch_dev *rnicp;
+ static int vers_printed;
+
+- PDBG("%s t3cdev %p\n", __FUNCTION__, tdev);
++ PDBG("%s t3cdev %p\n", __func__, tdev);
+ if (!vers_printed++)
+ printk(KERN_INFO MOD "Chelsio T3 RDMA Driver - version %s\n",
+ DRV_VERSION);
+@@ -144,7 +144,7 @@ static void open_rnic_dev(struct t3cdev *tdev)
+ static void close_rnic_dev(struct t3cdev *tdev)
+ {
+ struct iwch_dev *dev, *tmp;
+- PDBG("%s t3cdev %p\n", __FUNCTION__, tdev);
++ PDBG("%s t3cdev %p\n", __func__, tdev);
+ mutex_lock(&dev_mutex);
+ list_for_each_entry_safe(dev, tmp, &dev_list, entry) {
+ if (dev->rdev.t3cdev_p == tdev) {
+diff --git a/drivers/infiniband/hw/cxgb3/iwch.h b/drivers/infiniband/hw/cxgb3/iwch.h
+index caf4e60..9ad9b1e 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch.h
++++ b/drivers/infiniband/hw/cxgb3/iwch.h
+@@ -147,7 +147,7 @@ static inline int insert_handle(struct iwch_dev *rhp, struct idr *idr,
+ void *handle, u32 id)
+ {
+ int ret;
+- u32 newid;
++ int newid;
+
+ do {
+ if (!idr_pre_get(idr, GFP_KERNEL)) {
+diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
+index 99f2f2a..72ca360 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
++++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
+@@ -110,9 +110,9 @@ static void connect_reply_upcall(struct iwch_ep *ep, int status);
+
+ static void start_ep_timer(struct iwch_ep *ep)
+ {
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
+ if (timer_pending(&ep->timer)) {
+- PDBG("%s stopped / restarted timer ep %p\n", __FUNCTION__, ep);
++ PDBG("%s stopped / restarted timer ep %p\n", __func__, ep);
+ del_timer_sync(&ep->timer);
+ } else
+ get_ep(&ep->com);
+@@ -124,7 +124,7 @@ static void start_ep_timer(struct iwch_ep *ep)
+
+ static void stop_ep_timer(struct iwch_ep *ep)
+ {
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
+ del_timer_sync(&ep->timer);
+ put_ep(&ep->com);
+ }
+@@ -190,7 +190,7 @@ int iwch_resume_tid(struct iwch_ep *ep)
+
+ static void set_emss(struct iwch_ep *ep, u16 opt)
+ {
+- PDBG("%s ep %p opt %u\n", __FUNCTION__, ep, opt);
++ PDBG("%s ep %p opt %u\n", __func__, ep, opt);
+ ep->emss = T3C_DATA(ep->com.tdev)->mtus[G_TCPOPT_MSS(opt)] - 40;
+ if (G_TCPOPT_TSTAMP(opt))
+ ep->emss -= 12;
+@@ -220,7 +220,7 @@ static void state_set(struct iwch_ep_common *epc, enum iwch_ep_state new)
+ unsigned long flags;
+
+ spin_lock_irqsave(&epc->lock, flags);
+- PDBG("%s - %s -> %s\n", __FUNCTION__, states[epc->state], states[new]);
++ PDBG("%s - %s -> %s\n", __func__, states[epc->state], states[new]);
+ __state_set(epc, new);
+ spin_unlock_irqrestore(&epc->lock, flags);
+ return;
+@@ -236,7 +236,7 @@ static void *alloc_ep(int size, gfp_t gfp)
+ spin_lock_init(&epc->lock);
+ init_waitqueue_head(&epc->waitq);
+ }
+- PDBG("%s alloc ep %p\n", __FUNCTION__, epc);
++ PDBG("%s alloc ep %p\n", __func__, epc);
+ return epc;
+ }
+
+@@ -244,13 +244,13 @@ void __free_ep(struct kref *kref)
+ {
+ struct iwch_ep_common *epc;
+ epc = container_of(kref, struct iwch_ep_common, kref);
+- PDBG("%s ep %p state %s\n", __FUNCTION__, epc, states[state_read(epc)]);
++ PDBG("%s ep %p state %s\n", __func__, epc, states[state_read(epc)]);
+ kfree(epc);
+ }
+
+ static void release_ep_resources(struct iwch_ep *ep)
+ {
+- PDBG("%s ep %p tid %d\n", __FUNCTION__, ep, ep->hwtid);
++ PDBG("%s ep %p tid %d\n", __func__, ep, ep->hwtid);
+ cxgb3_remove_tid(ep->com.tdev, (void *)ep, ep->hwtid);
+ dst_release(ep->dst);
+ l2t_release(L2DATA(ep->com.tdev), ep->l2t);
+@@ -349,7 +349,7 @@ static unsigned int find_best_mtu(const struct t3c_data *d, unsigned short mtu)
+
+ static void arp_failure_discard(struct t3cdev *dev, struct sk_buff *skb)
+ {
+- PDBG("%s t3cdev %p\n", __FUNCTION__, dev);
++ PDBG("%s t3cdev %p\n", __func__, dev);
+ kfree_skb(skb);
+ }
+
+@@ -370,7 +370,7 @@ static void abort_arp_failure(struct t3cdev *dev, struct sk_buff *skb)
+ {
+ struct cpl_abort_req *req = cplhdr(skb);
+
+- PDBG("%s t3cdev %p\n", __FUNCTION__, dev);
++ PDBG("%s t3cdev %p\n", __func__, dev);
+ req->cmd = CPL_ABORT_NO_RST;
+ cxgb3_ofld_send(dev, skb);
+ }
+@@ -380,10 +380,10 @@ static int send_halfclose(struct iwch_ep *ep, gfp_t gfp)
+ struct cpl_close_con_req *req;
+ struct sk_buff *skb;
+
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
+ skb = get_skb(NULL, sizeof(*req), gfp);
+ if (!skb) {
+- printk(KERN_ERR MOD "%s - failed to alloc skb\n", __FUNCTION__);
++ printk(KERN_ERR MOD "%s - failed to alloc skb\n", __func__);
+ return -ENOMEM;
+ }
+ skb->priority = CPL_PRIORITY_DATA;
+@@ -400,11 +400,11 @@ static int send_abort(struct iwch_ep *ep, struct sk_buff *skb, gfp_t gfp)
+ {
+ struct cpl_abort_req *req;
+
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
+ skb = get_skb(skb, sizeof(*req), gfp);
+ if (!skb) {
+ printk(KERN_ERR MOD "%s - failed to alloc skb.\n",
+- __FUNCTION__);
++ __func__);
+ return -ENOMEM;
+ }
+ skb->priority = CPL_PRIORITY_DATA;
+@@ -426,12 +426,12 @@ static int send_connect(struct iwch_ep *ep)
+ unsigned int mtu_idx;
+ int wscale;
+
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
+
+ skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
+ if (!skb) {
+ printk(KERN_ERR MOD "%s - failed to alloc skb.\n",
+- __FUNCTION__);
++ __func__);
+ return -ENOMEM;
+ }
+ mtu_idx = find_best_mtu(T3C_DATA(ep->com.tdev), dst_mtu(ep->dst));
+@@ -470,7 +470,7 @@ static void send_mpa_req(struct iwch_ep *ep, struct sk_buff *skb)
+ struct mpa_message *mpa;
+ int len;
+
+- PDBG("%s ep %p pd_len %d\n", __FUNCTION__, ep, ep->plen);
++ PDBG("%s ep %p pd_len %d\n", __func__, ep, ep->plen);
+
+ BUG_ON(skb_cloned(skb));
+
+@@ -530,13 +530,13 @@ static int send_mpa_reject(struct iwch_ep *ep, const void *pdata, u8 plen)
+ struct mpa_message *mpa;
+ struct sk_buff *skb;
+
+- PDBG("%s ep %p plen %d\n", __FUNCTION__, ep, plen);
++ PDBG("%s ep %p plen %d\n", __func__, ep, plen);
+
+ mpalen = sizeof(*mpa) + plen;
+
+ skb = get_skb(NULL, mpalen + sizeof(*req), GFP_KERNEL);
+ if (!skb) {
+- printk(KERN_ERR MOD "%s - cannot alloc skb!\n", __FUNCTION__);
++ printk(KERN_ERR MOD "%s - cannot alloc skb!\n", __func__);
+ return -ENOMEM;
+ }
+ skb_reserve(skb, sizeof(*req));
+@@ -580,13 +580,13 @@ static int send_mpa_reply(struct iwch_ep *ep, const void *pdata, u8 plen)
+ int len;
+ struct sk_buff *skb;
+
+- PDBG("%s ep %p plen %d\n", __FUNCTION__, ep, plen);
++ PDBG("%s ep %p plen %d\n", __func__, ep, plen);
+
+ mpalen = sizeof(*mpa) + plen;
+
+ skb = get_skb(NULL, mpalen + sizeof(*req), GFP_KERNEL);
+ if (!skb) {
+- printk(KERN_ERR MOD "%s - cannot alloc skb!\n", __FUNCTION__);
++ printk(KERN_ERR MOD "%s - cannot alloc skb!\n", __func__);
+ return -ENOMEM;
+ }
+ skb->priority = CPL_PRIORITY_DATA;
+@@ -630,7 +630,7 @@ static int act_establish(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ struct cpl_act_establish *req = cplhdr(skb);
+ unsigned int tid = GET_TID(req);
+
+- PDBG("%s ep %p tid %d\n", __FUNCTION__, ep, tid);
++ PDBG("%s ep %p tid %d\n", __func__, ep, tid);
+
+ dst_confirm(ep->dst);
+
+@@ -663,7 +663,7 @@ static void close_complete_upcall(struct iwch_ep *ep)
+ {
+ struct iw_cm_event event;
+
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
+ memset(&event, 0, sizeof(event));
+ event.event = IW_CM_EVENT_CLOSE;
+ if (ep->com.cm_id) {
+@@ -680,7 +680,7 @@ static void peer_close_upcall(struct iwch_ep *ep)
+ {
+ struct iw_cm_event event;
+
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
+ memset(&event, 0, sizeof(event));
+ event.event = IW_CM_EVENT_DISCONNECT;
+ if (ep->com.cm_id) {
+@@ -694,7 +694,7 @@ static void peer_abort_upcall(struct iwch_ep *ep)
+ {
+ struct iw_cm_event event;
+
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
+ memset(&event, 0, sizeof(event));
+ event.event = IW_CM_EVENT_CLOSE;
+ event.status = -ECONNRESET;
+@@ -712,7 +712,7 @@ static void connect_reply_upcall(struct iwch_ep *ep, int status)
+ {
+ struct iw_cm_event event;
+
+- PDBG("%s ep %p status %d\n", __FUNCTION__, ep, status);
++ PDBG("%s ep %p status %d\n", __func__, ep, status);
+ memset(&event, 0, sizeof(event));
+ event.event = IW_CM_EVENT_CONNECT_REPLY;
+ event.status = status;
+@@ -724,7 +724,7 @@ static void connect_reply_upcall(struct iwch_ep *ep, int status)
+ event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
+ }
+ if (ep->com.cm_id) {
+- PDBG("%s ep %p tid %d status %d\n", __FUNCTION__, ep,
++ PDBG("%s ep %p tid %d status %d\n", __func__, ep,
+ ep->hwtid, status);
+ ep->com.cm_id->event_handler(ep->com.cm_id, &event);
+ }
+@@ -739,7 +739,7 @@ static void connect_request_upcall(struct iwch_ep *ep)
+ {
+ struct iw_cm_event event;
+
+- PDBG("%s ep %p tid %d\n", __FUNCTION__, ep, ep->hwtid);
++ PDBG("%s ep %p tid %d\n", __func__, ep, ep->hwtid);
+ memset(&event, 0, sizeof(event));
+ event.event = IW_CM_EVENT_CONNECT_REQUEST;
+ event.local_addr = ep->com.local_addr;
+@@ -759,11 +759,11 @@ static void established_upcall(struct iwch_ep *ep)
+ {
+ struct iw_cm_event event;
+
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
+ memset(&event, 0, sizeof(event));
+ event.event = IW_CM_EVENT_ESTABLISHED;
+ if (ep->com.cm_id) {
+- PDBG("%s ep %p tid %d\n", __FUNCTION__, ep, ep->hwtid);
++ PDBG("%s ep %p tid %d\n", __func__, ep, ep->hwtid);
+ ep->com.cm_id->event_handler(ep->com.cm_id, &event);
+ }
+ }
+@@ -773,7 +773,7 @@ static int update_rx_credits(struct iwch_ep *ep, u32 credits)
+ struct cpl_rx_data_ack *req;
+ struct sk_buff *skb;
+
+- PDBG("%s ep %p credits %u\n", __FUNCTION__, ep, credits);
++ PDBG("%s ep %p credits %u\n", __func__, ep, credits);
+ skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
+ if (!skb) {
+ printk(KERN_ERR MOD "update_rx_credits - cannot alloc skb!\n");
+@@ -797,7 +797,7 @@ static void process_mpa_reply(struct iwch_ep *ep, struct sk_buff *skb)
+ enum iwch_qp_attr_mask mask;
+ int err;
+
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
+
+ /*
+ * Stop mpa timer. If it expired, then the state has
+@@ -884,7 +884,7 @@ static void process_mpa_reply(struct iwch_ep *ep, struct sk_buff *skb)
+ ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0;
+ ep->mpa_attr.version = mpa_rev;
+ PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, "
+- "xmit_marker_enabled=%d, version=%d\n", __FUNCTION__,
++ "xmit_marker_enabled=%d, version=%d\n", __func__,
+ ep->mpa_attr.crc_enabled, ep->mpa_attr.recv_marker_enabled,
+ ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version);
+
+@@ -915,7 +915,7 @@ static void process_mpa_request(struct iwch_ep *ep, struct sk_buff *skb)
+ struct mpa_message *mpa;
+ u16 plen;
+
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
+
+ /*
+ * Stop mpa timer. If it expired, then the state has
+@@ -935,7 +935,7 @@ static void process_mpa_request(struct iwch_ep *ep, struct sk_buff *skb)
+ return;
+ }
+
+- PDBG("%s enter (%s line %u)\n", __FUNCTION__, __FILE__, __LINE__);
++ PDBG("%s enter (%s line %u)\n", __func__, __FILE__, __LINE__);
+
+ /*
+ * Copy the new data into our accumulation buffer.
+@@ -950,7 +950,7 @@ static void process_mpa_request(struct iwch_ep *ep, struct sk_buff *skb)
+ */
+ if (ep->mpa_pkt_len < sizeof(*mpa))
+ return;
+- PDBG("%s enter (%s line %u)\n", __FUNCTION__, __FILE__, __LINE__);
++ PDBG("%s enter (%s line %u)\n", __func__, __FILE__, __LINE__);
+ mpa = (struct mpa_message *) ep->mpa_pkt;
+
+ /*
+@@ -1000,7 +1000,7 @@ static void process_mpa_request(struct iwch_ep *ep, struct sk_buff *skb)
+ ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0;
+ ep->mpa_attr.version = mpa_rev;
+ PDBG("%s - crc_enabled=%d, recv_marker_enabled=%d, "
+- "xmit_marker_enabled=%d, version=%d\n", __FUNCTION__,
++ "xmit_marker_enabled=%d, version=%d\n", __func__,
+ ep->mpa_attr.crc_enabled, ep->mpa_attr.recv_marker_enabled,
+ ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version);
+
+@@ -1017,7 +1017,7 @@ static int rx_data(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ struct cpl_rx_data *hdr = cplhdr(skb);
+ unsigned int dlen = ntohs(hdr->len);
+
+- PDBG("%s ep %p dlen %u\n", __FUNCTION__, ep, dlen);
++ PDBG("%s ep %p dlen %u\n", __func__, ep, dlen);
+
+ skb_pull(skb, sizeof(*hdr));
+ skb_trim(skb, dlen);
+@@ -1037,7 +1037,7 @@ static int rx_data(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ default:
+ printk(KERN_ERR MOD "%s Unexpected streaming data."
+ " ep %p state %d tid %d\n",
+- __FUNCTION__, ep, state_read(&ep->com), ep->hwtid);
++ __func__, ep, state_read(&ep->com), ep->hwtid);
+
+ /*
+ * The ep will timeout and inform the ULP of the failure.
+@@ -1063,7 +1063,7 @@ static int tx_ack(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ struct cpl_wr_ack *hdr = cplhdr(skb);
+ unsigned int credits = ntohs(hdr->credits);
+
+- PDBG("%s ep %p credits %u\n", __FUNCTION__, ep, credits);
++ PDBG("%s ep %p credits %u\n", __func__, ep, credits);
+
+ if (credits == 0)
+ return CPL_RET_BUF_DONE;
+@@ -1084,7 +1084,7 @@ static int abort_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ {
+ struct iwch_ep *ep = ctx;
+
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
+
+ /*
+ * We get 2 abort replies from the HW. The first one must
+@@ -1115,7 +1115,7 @@ static int act_open_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ struct iwch_ep *ep = ctx;
+ struct cpl_act_open_rpl *rpl = cplhdr(skb);
+
+- PDBG("%s ep %p status %u errno %d\n", __FUNCTION__, ep, rpl->status,
++ PDBG("%s ep %p status %u errno %d\n", __func__, ep, rpl->status,
+ status2errno(rpl->status));
+ connect_reply_upcall(ep, status2errno(rpl->status));
+ state_set(&ep->com, DEAD);
+@@ -1133,7 +1133,7 @@ static int listen_start(struct iwch_listen_ep *ep)
+ struct sk_buff *skb;
+ struct cpl_pass_open_req *req;
+
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
+ skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
+ if (!skb) {
+ printk(KERN_ERR MOD "t3c_listen_start failed to alloc skb!\n");
+@@ -1162,7 +1162,7 @@ static int pass_open_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ struct iwch_listen_ep *ep = ctx;
+ struct cpl_pass_open_rpl *rpl = cplhdr(skb);
+
+- PDBG("%s ep %p status %d error %d\n", __FUNCTION__, ep,
++ PDBG("%s ep %p status %d error %d\n", __func__, ep,
+ rpl->status, status2errno(rpl->status));
+ ep->com.rpl_err = status2errno(rpl->status);
+ ep->com.rpl_done = 1;
+@@ -1176,10 +1176,10 @@ static int listen_stop(struct iwch_listen_ep *ep)
+ struct sk_buff *skb;
+ struct cpl_close_listserv_req *req;
+
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
+ skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
+ if (!skb) {
+- printk(KERN_ERR MOD "%s - failed to alloc skb\n", __FUNCTION__);
++ printk(KERN_ERR MOD "%s - failed to alloc skb\n", __func__);
+ return -ENOMEM;
+ }
+ req = (struct cpl_close_listserv_req *) skb_put(skb, sizeof(*req));
+@@ -1197,7 +1197,7 @@ static int close_listsrv_rpl(struct t3cdev *tdev, struct sk_buff *skb,
+ struct iwch_listen_ep *ep = ctx;
+ struct cpl_close_listserv_rpl *rpl = cplhdr(skb);
+
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
+ ep->com.rpl_err = status2errno(rpl->status);
+ ep->com.rpl_done = 1;
+ wake_up(&ep->com.waitq);
+@@ -1211,7 +1211,7 @@ static void accept_cr(struct iwch_ep *ep, __be32 peer_ip, struct sk_buff *skb)
+ u32 opt0h, opt0l, opt2;
+ int wscale;
+
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
+ BUG_ON(skb_cloned(skb));
+ skb_trim(skb, sizeof(*rpl));
+ skb_get(skb);
+@@ -1244,7 +1244,7 @@ static void accept_cr(struct iwch_ep *ep, __be32 peer_ip, struct sk_buff *skb)
+ static void reject_cr(struct t3cdev *tdev, u32 hwtid, __be32 peer_ip,
+ struct sk_buff *skb)
+ {
+- PDBG("%s t3cdev %p tid %u peer_ip %x\n", __FUNCTION__, tdev, hwtid,
++ PDBG("%s t3cdev %p tid %u peer_ip %x\n", __func__, tdev, hwtid,
+ peer_ip);
+ BUG_ON(skb_cloned(skb));
+ skb_trim(skb, sizeof(struct cpl_tid_release));
+@@ -1279,11 +1279,11 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ struct rtable *rt;
+ struct iff_mac tim;
+
+- PDBG("%s parent ep %p tid %u\n", __FUNCTION__, parent_ep, hwtid);
++ PDBG("%s parent ep %p tid %u\n", __func__, parent_ep, hwtid);
+
+ if (state_read(&parent_ep->com) != LISTEN) {
+ printk(KERN_ERR "%s - listening ep not in LISTEN\n",
+- __FUNCTION__);
++ __func__);
+ goto reject;
+ }
+
+@@ -1295,7 +1295,7 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ if (tdev->ctl(tdev, GET_IFF_FROM_MAC, &tim) < 0 || !tim.dev) {
+ printk(KERN_ERR
+ "%s bad dst mac %02x %02x %02x %02x %02x %02x\n",
+- __FUNCTION__,
++ __func__,
+ req->dst_mac[0],
+ req->dst_mac[1],
+ req->dst_mac[2],
+@@ -1313,21 +1313,21 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ req->peer_port, G_PASS_OPEN_TOS(ntohl(req->tos_tid)));
+ if (!rt) {
+ printk(KERN_ERR MOD "%s - failed to find dst entry!\n",
+- __FUNCTION__);
++ __func__);
+ goto reject;
+ }
+ dst = &rt->u.dst;
+ l2t = t3_l2t_get(tdev, dst->neighbour, dst->neighbour->dev);
+ if (!l2t) {
+ printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
+- __FUNCTION__);
++ __func__);
+ dst_release(dst);
+ goto reject;
+ }
+ child_ep = alloc_ep(sizeof(*child_ep), GFP_KERNEL);
+ if (!child_ep) {
+ printk(KERN_ERR MOD "%s - failed to allocate ep entry!\n",
+- __FUNCTION__);
++ __func__);
+ l2t_release(L2DATA(tdev), l2t);
+ dst_release(dst);
+ goto reject;
+@@ -1362,7 +1362,7 @@ static int pass_establish(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ struct iwch_ep *ep = ctx;
+ struct cpl_pass_establish *req = cplhdr(skb);
+
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
+ ep->snd_seq = ntohl(req->snd_isn);
+ ep->rcv_seq = ntohl(req->rcv_isn);
+
+@@ -1383,7 +1383,7 @@ static int peer_close(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ int disconnect = 1;
+ int release = 0;
+
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
+ dst_confirm(ep->dst);
+
+ spin_lock_irqsave(&ep->com.lock, flags);
+@@ -1473,7 +1473,7 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ int state;
+
+ if (is_neg_adv_abort(req->status)) {
+- PDBG("%s neg_adv_abort ep %p tid %d\n", __FUNCTION__, ep,
++ PDBG("%s neg_adv_abort ep %p tid %d\n", __func__, ep,
+ ep->hwtid);
+ t3_l2t_send_event(ep->com.tdev, ep->l2t);
+ return CPL_RET_BUF_DONE;
+@@ -1489,7 +1489,7 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ }
+
+ state = state_read(&ep->com);
+- PDBG("%s ep %p state %u\n", __FUNCTION__, ep, state);
++ PDBG("%s ep %p state %u\n", __func__, ep, state);
+ switch (state) {
+ case CONNECTING:
+ break;
+@@ -1528,14 +1528,14 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ if (ret)
+ printk(KERN_ERR MOD
+ "%s - qp <- error failed!\n",
+- __FUNCTION__);
++ __func__);
+ }
+ peer_abort_upcall(ep);
+ break;
+ case ABORTING:
+ break;
+ case DEAD:
+- PDBG("%s PEER_ABORT IN DEAD STATE!!!!\n", __FUNCTION__);
++ PDBG("%s PEER_ABORT IN DEAD STATE!!!!\n", __func__);
+ return CPL_RET_BUF_DONE;
+ default:
+ BUG_ON(1);
+@@ -1546,7 +1546,7 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ rpl_skb = get_skb(skb, sizeof(*rpl), GFP_KERNEL);
+ if (!rpl_skb) {
+ printk(KERN_ERR MOD "%s - cannot allocate skb!\n",
+- __FUNCTION__);
++ __func__);
+ dst_release(ep->dst);
+ l2t_release(L2DATA(ep->com.tdev), ep->l2t);
+ put_ep(&ep->com);
+@@ -1573,7 +1573,7 @@ static int close_con_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ unsigned long flags;
+ int release = 0;
+
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
+ BUG_ON(!ep);
+
+ /* The cm_id may be null if we failed to connect */
+@@ -1624,9 +1624,9 @@ static int terminate(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ {
+ struct iwch_ep *ep = ctx;
+
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
+ skb_pull(skb, sizeof(struct cpl_rdma_terminate));
+- PDBG("%s saving %d bytes of term msg\n", __FUNCTION__, skb->len);
++ PDBG("%s saving %d bytes of term msg\n", __func__, skb->len);
+ skb_copy_from_linear_data(skb, ep->com.qp->attr.terminate_buffer,
+ skb->len);
+ ep->com.qp->attr.terminate_msg_len = skb->len;
+@@ -1639,13 +1639,13 @@ static int ec_status(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ struct cpl_rdma_ec_status *rep = cplhdr(skb);
+ struct iwch_ep *ep = ctx;
+
+- PDBG("%s ep %p tid %u status %d\n", __FUNCTION__, ep, ep->hwtid,
++ PDBG("%s ep %p tid %u status %d\n", __func__, ep, ep->hwtid,
+ rep->status);
+ if (rep->status) {
+ struct iwch_qp_attributes attrs;
+
+ printk(KERN_ERR MOD "%s BAD CLOSE - Aborting tid %u\n",
+- __FUNCTION__, ep->hwtid);
++ __func__, ep->hwtid);
+ stop_ep_timer(ep);
+ attrs.next_state = IWCH_QP_STATE_ERROR;
+ iwch_modify_qp(ep->com.qp->rhp,
+@@ -1663,7 +1663,7 @@ static void ep_timeout(unsigned long arg)
+ unsigned long flags;
+
+ spin_lock_irqsave(&ep->com.lock, flags);
+- PDBG("%s ep %p tid %u state %d\n", __FUNCTION__, ep, ep->hwtid,
++ PDBG("%s ep %p tid %u state %d\n", __func__, ep, ep->hwtid,
+ ep->com.state);
+ switch (ep->com.state) {
+ case MPA_REQ_SENT:
+@@ -1693,7 +1693,7 @@ int iwch_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
+ {
+ int err;
+ struct iwch_ep *ep = to_ep(cm_id);
+- PDBG("%s ep %p tid %u\n", __FUNCTION__, ep, ep->hwtid);
++ PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
+
+ if (state_read(&ep->com) == DEAD) {
+ put_ep(&ep->com);
+@@ -1718,7 +1718,7 @@ int iwch_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+ struct iwch_dev *h = to_iwch_dev(cm_id->device);
+ struct iwch_qp *qp = get_qhp(h, conn_param->qpn);
+
+- PDBG("%s ep %p tid %u\n", __FUNCTION__, ep, ep->hwtid);
++ PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
+ if (state_read(&ep->com) == DEAD)
+ return -ECONNRESET;
+
+@@ -1739,7 +1739,7 @@ int iwch_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+ ep->com.rpl_err = 0;
+ ep->ird = conn_param->ird;
+ ep->ord = conn_param->ord;
+- PDBG("%s %d ird %d ord %d\n", __FUNCTION__, __LINE__, ep->ird, ep->ord);
++ PDBG("%s %d ird %d ord %d\n", __func__, __LINE__, ep->ird, ep->ord);
+
+ get_ep(&ep->com);
+
+@@ -1810,7 +1810,7 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+
+ ep = alloc_ep(sizeof(*ep), GFP_KERNEL);
+ if (!ep) {
+- printk(KERN_ERR MOD "%s - cannot alloc ep.\n", __FUNCTION__);
++ printk(KERN_ERR MOD "%s - cannot alloc ep.\n", __func__);
+ err = -ENOMEM;
+ goto out;
+ }
+@@ -1827,7 +1827,7 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+ ep->com.cm_id = cm_id;
+ ep->com.qp = get_qhp(h, conn_param->qpn);
+ BUG_ON(!ep->com.qp);
+- PDBG("%s qpn 0x%x qp %p cm_id %p\n", __FUNCTION__, conn_param->qpn,
++ PDBG("%s qpn 0x%x qp %p cm_id %p\n", __func__, conn_param->qpn,
+ ep->com.qp, cm_id);
+
+ /*
+@@ -1835,7 +1835,7 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+ */
+ ep->atid = cxgb3_alloc_atid(h->rdev.t3cdev_p, &t3c_client, ep);
+ if (ep->atid == -1) {
+- printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __FUNCTION__);
++ printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __func__);
+ err = -ENOMEM;
+ goto fail2;
+ }
+@@ -1847,7 +1847,7 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+ cm_id->local_addr.sin_port,
+ cm_id->remote_addr.sin_port, IPTOS_LOWDELAY);
+ if (!rt) {
+- printk(KERN_ERR MOD "%s - cannot find route.\n", __FUNCTION__);
++ printk(KERN_ERR MOD "%s - cannot find route.\n", __func__);
+ err = -EHOSTUNREACH;
+ goto fail3;
+ }
+@@ -1857,7 +1857,7 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+ ep->l2t = t3_l2t_get(ep->com.tdev, ep->dst->neighbour,
+ ep->dst->neighbour->dev);
+ if (!ep->l2t) {
+- printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __FUNCTION__);
++ printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
+ err = -ENOMEM;
+ goto fail4;
+ }
+@@ -1894,11 +1894,11 @@ int iwch_create_listen(struct iw_cm_id *cm_id, int backlog)
+
+ ep = alloc_ep(sizeof(*ep), GFP_KERNEL);
+ if (!ep) {
+- printk(KERN_ERR MOD "%s - cannot alloc ep.\n", __FUNCTION__);
++ printk(KERN_ERR MOD "%s - cannot alloc ep.\n", __func__);
+ err = -ENOMEM;
+ goto fail1;
+ }
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
+ ep->com.tdev = h->rdev.t3cdev_p;
+ cm_id->add_ref(cm_id);
+ ep->com.cm_id = cm_id;
+@@ -1910,7 +1910,7 @@ int iwch_create_listen(struct iw_cm_id *cm_id, int backlog)
+ */
+ ep->stid = cxgb3_alloc_stid(h->rdev.t3cdev_p, &t3c_client, ep);
+ if (ep->stid == -1) {
+- printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __FUNCTION__);
++ printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __func__);
+ err = -ENOMEM;
+ goto fail2;
+ }
+@@ -1942,7 +1942,7 @@ int iwch_destroy_listen(struct iw_cm_id *cm_id)
+ int err;
+ struct iwch_listen_ep *ep = to_listen_ep(cm_id);
+
+- PDBG("%s ep %p\n", __FUNCTION__, ep);
++ PDBG("%s ep %p\n", __func__, ep);
+
+ might_sleep();
+ state_set(&ep->com, DEAD);
+@@ -1965,11 +1965,11 @@ int iwch_ep_disconnect(struct iwch_ep *ep, int abrupt, gfp_t gfp)
+
+ spin_lock_irqsave(&ep->com.lock, flags);
+
+- PDBG("%s ep %p state %s, abrupt %d\n", __FUNCTION__, ep,
++ PDBG("%s ep %p state %s, abrupt %d\n", __func__, ep,
+ states[ep->com.state], abrupt);
+
+ if (ep->com.state == DEAD) {
+- PDBG("%s already dead ep %p\n", __FUNCTION__, ep);
++ PDBG("%s already dead ep %p\n", __func__, ep);
+ goto out;
+ }
+
+@@ -2020,7 +2020,7 @@ int iwch_ep_redirect(void *ctx, struct dst_entry *old, struct dst_entry *new,
+ if (ep->dst != old)
+ return 0;
+
+- PDBG("%s ep %p redirect to dst %p l2t %p\n", __FUNCTION__, ep, new,
++ PDBG("%s ep %p redirect to dst %p l2t %p\n", __func__, ep, new,
+ l2t);
+ dst_hold(new);
+ l2t_release(L2DATA(ep->com.tdev), ep->l2t);
+diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.h b/drivers/infiniband/hw/cxgb3/iwch_cm.h
+index 6107e7c..2bb7fbd 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch_cm.h
++++ b/drivers/infiniband/hw/cxgb3/iwch_cm.h
+@@ -54,13 +54,13 @@
+ #define MPA_FLAGS_MASK 0xE0
+
+ #define put_ep(ep) { \
+- PDBG("put_ep (via %s:%u) ep %p refcnt %d\n", __FUNCTION__, __LINE__, \
++ PDBG("put_ep (via %s:%u) ep %p refcnt %d\n", __func__, __LINE__, \
+ ep, atomic_read(&((ep)->kref.refcount))); \
+ kref_put(&((ep)->kref), __free_ep); \
+ }
+
+ #define get_ep(ep) { \
+- PDBG("get_ep (via %s:%u) ep %p, refcnt %d\n", __FUNCTION__, __LINE__, \
++ PDBG("get_ep (via %s:%u) ep %p, refcnt %d\n", __func__, __LINE__, \
+ ep, atomic_read(&((ep)->kref.refcount))); \
+ kref_get(&((ep)->kref)); \
+ }
+diff --git a/drivers/infiniband/hw/cxgb3/iwch_cq.c b/drivers/infiniband/hw/cxgb3/iwch_cq.c
+index d7624c1..4ee8ccd 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch_cq.c
++++ b/drivers/infiniband/hw/cxgb3/iwch_cq.c
+@@ -67,7 +67,7 @@ static int iwch_poll_cq_one(struct iwch_dev *rhp, struct iwch_cq *chp,
+ ret = cxio_poll_cq(wq, &(chp->cq), &cqe, &cqe_flushed, &cookie,
+ &credit);
+ if (t3a_device(chp->rhp) && credit) {
+- PDBG("%s updating %d cq credits on id %d\n", __FUNCTION__,
++ PDBG("%s updating %d cq credits on id %d\n", __func__,
+ credit, chp->cq.cqid);
+ cxio_hal_cq_op(&rhp->rdev, &chp->cq, CQ_CREDIT_UPDATE, credit);
+ }
+@@ -83,7 +83,7 @@ static int iwch_poll_cq_one(struct iwch_dev *rhp, struct iwch_cq *chp,
+ wc->vendor_err = CQE_STATUS(cqe);
+
+ PDBG("%s qpid 0x%x type %d opcode %d status 0x%x wrid hi 0x%x "
+- "lo 0x%x cookie 0x%llx\n", __FUNCTION__,
++ "lo 0x%x cookie 0x%llx\n", __func__,
+ CQE_QPID(cqe), CQE_TYPE(cqe),
+ CQE_OPCODE(cqe), CQE_STATUS(cqe), CQE_WRID_HI(cqe),
+ CQE_WRID_LOW(cqe), (unsigned long long) cookie);
+diff --git a/drivers/infiniband/hw/cxgb3/iwch_ev.c b/drivers/infiniband/hw/cxgb3/iwch_ev.c
+index b406766..7b67a67 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch_ev.c
++++ b/drivers/infiniband/hw/cxgb3/iwch_ev.c
+@@ -52,7 +52,7 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp,
+
+ if (!qhp) {
+ printk(KERN_ERR "%s unaffiliated error 0x%x qpid 0x%x\n",
+- __FUNCTION__, CQE_STATUS(rsp_msg->cqe),
++ __func__, CQE_STATUS(rsp_msg->cqe),
+ CQE_QPID(rsp_msg->cqe));
+ spin_unlock(&rnicp->lock);
+ return;
+@@ -61,14 +61,14 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp,
+ if ((qhp->attr.state == IWCH_QP_STATE_ERROR) ||
+ (qhp->attr.state == IWCH_QP_STATE_TERMINATE)) {
+ PDBG("%s AE received after RTS - "
+- "qp state %d qpid 0x%x status 0x%x\n", __FUNCTION__,
++ "qp state %d qpid 0x%x status 0x%x\n", __func__,
+ qhp->attr.state, qhp->wq.qpid, CQE_STATUS(rsp_msg->cqe));
+ spin_unlock(&rnicp->lock);
+ return;
+ }
+
+ printk(KERN_ERR "%s - AE qpid 0x%x opcode %d status 0x%x "
+- "type %d wrid.hi 0x%x wrid.lo 0x%x \n", __FUNCTION__,
++ "type %d wrid.hi 0x%x wrid.lo 0x%x \n", __func__,
+ CQE_QPID(rsp_msg->cqe), CQE_OPCODE(rsp_msg->cqe),
+ CQE_STATUS(rsp_msg->cqe), CQE_TYPE(rsp_msg->cqe),
+ CQE_WRID_HI(rsp_msg->cqe), CQE_WRID_LOW(rsp_msg->cqe));
+@@ -132,10 +132,10 @@ void iwch_ev_dispatch(struct cxio_rdev *rdev_p, struct sk_buff *skb)
+ (CQE_STATUS(rsp_msg->cqe) == 0)) {
+ if (SQ_TYPE(rsp_msg->cqe)) {
+ PDBG("%s QPID 0x%x ep %p disconnecting\n",
+- __FUNCTION__, qhp->wq.qpid, qhp->ep);
++ __func__, qhp->wq.qpid, qhp->ep);
+ iwch_ep_disconnect(qhp->ep, 0, GFP_ATOMIC);
+ } else {
+- PDBG("%s post REQ_ERR AE QPID 0x%x\n", __FUNCTION__,
++ PDBG("%s post REQ_ERR AE QPID 0x%x\n", __func__,
+ qhp->wq.qpid);
+ post_qp_event(rnicp, chp, rsp_msg,
+ IB_EVENT_QP_REQ_ERR, 0);
+@@ -180,7 +180,7 @@ void iwch_ev_dispatch(struct cxio_rdev *rdev_p, struct sk_buff *skb)
+ case TPT_ERR_INVALIDATE_SHARED_MR:
+ case TPT_ERR_INVALIDATE_MR_WITH_MW_BOUND:
+ printk(KERN_ERR "%s - CQE Err qpid 0x%x opcode %d status 0x%x "
+- "type %d wrid.hi 0x%x wrid.lo 0x%x \n", __FUNCTION__,
++ "type %d wrid.hi 0x%x wrid.lo 0x%x \n", __func__,
+ CQE_QPID(rsp_msg->cqe), CQE_OPCODE(rsp_msg->cqe),
+ CQE_STATUS(rsp_msg->cqe), CQE_TYPE(rsp_msg->cqe),
+ CQE_WRID_HI(rsp_msg->cqe), CQE_WRID_LOW(rsp_msg->cqe));
+diff --git a/drivers/infiniband/hw/cxgb3/iwch_mem.c b/drivers/infiniband/hw/cxgb3/iwch_mem.c
+index b8797c6..58c3d61 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch_mem.c
++++ b/drivers/infiniband/hw/cxgb3/iwch_mem.c
+@@ -62,7 +62,7 @@ int iwch_register_mem(struct iwch_dev *rhp, struct iwch_pd *php,
+ mmid = stag >> 8;
+ mhp->ibmr.rkey = mhp->ibmr.lkey = stag;
+ insert_handle(rhp, &rhp->mmidr, mhp, mmid);
+- PDBG("%s mmid 0x%x mhp %p\n", __FUNCTION__, mmid, mhp);
++ PDBG("%s mmid 0x%x mhp %p\n", __func__, mmid, mhp);
+ return 0;
+ }
+
+@@ -96,7 +96,7 @@ int iwch_reregister_mem(struct iwch_dev *rhp, struct iwch_pd *php,
+ mmid = stag >> 8;
+ mhp->ibmr.rkey = mhp->ibmr.lkey = stag;
+ insert_handle(rhp, &rhp->mmidr, mhp, mmid);
+- PDBG("%s mmid 0x%x mhp %p\n", __FUNCTION__, mmid, mhp);
++ PDBG("%s mmid 0x%x mhp %p\n", __func__, mmid, mhp);
+ return 0;
+ }
+
+@@ -163,7 +163,7 @@ int build_phys_page_list(struct ib_phys_buf *buffer_list,
+ ((u64) j << *shift));
+
+ PDBG("%s va 0x%llx mask 0x%llx shift %d len %lld pbl_size %d\n",
+- __FUNCTION__, (unsigned long long) *iova_start,
++ __func__, (unsigned long long) *iova_start,
+ (unsigned long long) mask, *shift, (unsigned long long) *total_size,
+ *npages);
+
+diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
+index b2ea921..ab4695c 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
++++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
+@@ -101,7 +101,7 @@ static int iwch_dealloc_ucontext(struct ib_ucontext *context)
+ struct iwch_ucontext *ucontext = to_iwch_ucontext(context);
+ struct iwch_mm_entry *mm, *tmp;
+
+- PDBG("%s context %p\n", __FUNCTION__, context);
++ PDBG("%s context %p\n", __func__, context);
+ list_for_each_entry_safe(mm, tmp, &ucontext->mmaps, entry)
+ kfree(mm);
+ cxio_release_ucontext(&rhp->rdev, &ucontext->uctx);
+@@ -115,7 +115,7 @@ static struct ib_ucontext *iwch_alloc_ucontext(struct ib_device *ibdev,
+ struct iwch_ucontext *context;
+ struct iwch_dev *rhp = to_iwch_dev(ibdev);
+
+- PDBG("%s ibdev %p\n", __FUNCTION__, ibdev);
++ PDBG("%s ibdev %p\n", __func__, ibdev);
+ context = kzalloc(sizeof(*context), GFP_KERNEL);
+ if (!context)
+ return ERR_PTR(-ENOMEM);
+@@ -129,7 +129,7 @@ static int iwch_destroy_cq(struct ib_cq *ib_cq)
+ {
+ struct iwch_cq *chp;
+
+- PDBG("%s ib_cq %p\n", __FUNCTION__, ib_cq);
++ PDBG("%s ib_cq %p\n", __func__, ib_cq);
+ chp = to_iwch_cq(ib_cq);
+
+ remove_handle(chp->rhp, &chp->rhp->cqidr, chp->cq.cqid);
+@@ -151,7 +151,7 @@ static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries, int ve
+ struct iwch_create_cq_req ureq;
+ struct iwch_ucontext *ucontext = NULL;
+
+- PDBG("%s ib_dev %p entries %d\n", __FUNCTION__, ibdev, entries);
++ PDBG("%s ib_dev %p entries %d\n", __func__, ibdev, entries);
+ rhp = to_iwch_dev(ibdev);
+ chp = kzalloc(sizeof(*chp), GFP_KERNEL);
+ if (!chp)
+@@ -233,7 +233,7 @@ static int iwch_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata)
+ struct t3_cq oldcq, newcq;
+ int ret;
+
+- PDBG("%s ib_cq %p cqe %d\n", __FUNCTION__, cq, cqe);
++ PDBG("%s ib_cq %p cqe %d\n", __func__, cq, cqe);
+
+ /* We don't downsize... */
+ if (cqe <= cq->cqe)
+@@ -281,7 +281,7 @@ static int iwch_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata)
+ ret = cxio_destroy_cq(&chp->rhp->rdev, &oldcq);
+ if (ret) {
+ printk(KERN_ERR MOD "%s - cxio_destroy_cq failed %d\n",
+- __FUNCTION__, ret);
++ __func__, ret);
+ }
+
+ /* add user hooks here */
+@@ -316,7 +316,7 @@ static int iwch_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags)
+ chp->cq.rptr = rptr;
+ } else
+ spin_lock_irqsave(&chp->lock, flag);
+- PDBG("%s rptr 0x%x\n", __FUNCTION__, chp->cq.rptr);
++ PDBG("%s rptr 0x%x\n", __func__, chp->cq.rptr);
+ err = cxio_hal_cq_op(&rhp->rdev, &chp->cq, cq_op, 0);
+ spin_unlock_irqrestore(&chp->lock, flag);
+ if (err < 0)
+@@ -337,7 +337,7 @@ static int iwch_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
+ struct iwch_ucontext *ucontext;
+ u64 addr;
+
+- PDBG("%s pgoff 0x%lx key 0x%x len %d\n", __FUNCTION__, vma->vm_pgoff,
++ PDBG("%s pgoff 0x%lx key 0x%x len %d\n", __func__, vma->vm_pgoff,
+ key, len);
+
+ if (vma->vm_start & (PAGE_SIZE-1)) {
+@@ -390,7 +390,7 @@ static int iwch_deallocate_pd(struct ib_pd *pd)
+
+ php = to_iwch_pd(pd);
+ rhp = php->rhp;
+- PDBG("%s ibpd %p pdid 0x%x\n", __FUNCTION__, pd, php->pdid);
++ PDBG("%s ibpd %p pdid 0x%x\n", __func__, pd, php->pdid);
+ cxio_hal_put_pdid(rhp->rdev.rscp, php->pdid);
+ kfree(php);
+ return 0;
+@@ -404,7 +404,7 @@ static struct ib_pd *iwch_allocate_pd(struct ib_device *ibdev,
+ u32 pdid;
+ struct iwch_dev *rhp;
+
+- PDBG("%s ibdev %p\n", __FUNCTION__, ibdev);
++ PDBG("%s ibdev %p\n", __func__, ibdev);
+ rhp = (struct iwch_dev *) ibdev;
+ pdid = cxio_hal_get_pdid(rhp->rdev.rscp);
+ if (!pdid)
+@@ -422,7 +422,7 @@ static struct ib_pd *iwch_allocate_pd(struct ib_device *ibdev,
+ return ERR_PTR(-EFAULT);
+ }
+ }
+- PDBG("%s pdid 0x%0x ptr 0x%p\n", __FUNCTION__, pdid, php);
++ PDBG("%s pdid 0x%0x ptr 0x%p\n", __func__, pdid, php);
+ return &php->ibpd;
+ }
+
+@@ -432,7 +432,7 @@ static int iwch_dereg_mr(struct ib_mr *ib_mr)
+ struct iwch_mr *mhp;
+ u32 mmid;
+
+- PDBG("%s ib_mr %p\n", __FUNCTION__, ib_mr);
++ PDBG("%s ib_mr %p\n", __func__, ib_mr);
+ /* There can be no memory windows */
+ if (atomic_read(&ib_mr->usecnt))
+ return -EINVAL;
+@@ -447,7 +447,7 @@ static int iwch_dereg_mr(struct ib_mr *ib_mr)
+ kfree((void *) (unsigned long) mhp->kva);
+ if (mhp->umem)
+ ib_umem_release(mhp->umem);
+- PDBG("%s mmid 0x%x ptr %p\n", __FUNCTION__, mmid, mhp);
++ PDBG("%s mmid 0x%x ptr %p\n", __func__, mmid, mhp);
+ kfree(mhp);
+ return 0;
+ }
+@@ -467,7 +467,7 @@ static struct ib_mr *iwch_register_phys_mem(struct ib_pd *pd,
+ struct iwch_mr *mhp;
+ int ret;
+
+- PDBG("%s ib_pd %p\n", __FUNCTION__, pd);
++ PDBG("%s ib_pd %p\n", __func__, pd);
+ php = to_iwch_pd(pd);
+ rhp = php->rhp;
+
+@@ -531,7 +531,7 @@ static int iwch_reregister_phys_mem(struct ib_mr *mr,
+ int npages;
+ int ret;
+
+- PDBG("%s ib_mr %p ib_pd %p\n", __FUNCTION__, mr, pd);
++ PDBG("%s ib_mr %p ib_pd %p\n", __func__, mr, pd);
+
+ /* There can be no memory windows */
+ if (atomic_read(&mr->usecnt))
+@@ -594,7 +594,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+ struct iwch_mr *mhp;
+ struct iwch_reg_user_mr_resp uresp;
+
+- PDBG("%s ib_pd %p\n", __FUNCTION__, pd);
++ PDBG("%s ib_pd %p\n", __func__, pd);
+
+ php = to_iwch_pd(pd);
+ rhp = php->rhp;
+@@ -649,7 +649,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+ if (udata && !t3a_device(rhp)) {
+ uresp.pbl_addr = (mhp->attr.pbl_addr -
+ rhp->rdev.rnic_info.pbl_base) >> 3;
+- PDBG("%s user resp pbl_addr 0x%x\n", __FUNCTION__,
++ PDBG("%s user resp pbl_addr 0x%x\n", __func__,
+ uresp.pbl_addr);
+
+ if (ib_copy_to_udata(udata, &uresp, sizeof (uresp))) {
+@@ -673,7 +673,7 @@ static struct ib_mr *iwch_get_dma_mr(struct ib_pd *pd, int acc)
+ u64 kva;
+ struct ib_mr *ibmr;
+
+- PDBG("%s ib_pd %p\n", __FUNCTION__, pd);
++ PDBG("%s ib_pd %p\n", __func__, pd);
+
+ /*
+ * T3 only supports 32 bits of size.
+@@ -710,7 +710,7 @@ static struct ib_mw *iwch_alloc_mw(struct ib_pd *pd)
+ mhp->attr.stag = stag;
+ mmid = (stag) >> 8;
+ insert_handle(rhp, &rhp->mmidr, mhp, mmid);
+- PDBG("%s mmid 0x%x mhp %p stag 0x%x\n", __FUNCTION__, mmid, mhp, stag);
++ PDBG("%s mmid 0x%x mhp %p stag 0x%x\n", __func__, mmid, mhp, stag);
+ return &(mhp->ibmw);
+ }
+
+@@ -726,7 +726,7 @@ static int iwch_dealloc_mw(struct ib_mw *mw)
+ cxio_deallocate_window(&rhp->rdev, mhp->attr.stag);
+ remove_handle(rhp, &rhp->mmidr, mmid);
+ kfree(mhp);
+- PDBG("%s ib_mw %p mmid 0x%x ptr %p\n", __FUNCTION__, mw, mmid, mhp);
++ PDBG("%s ib_mw %p mmid 0x%x ptr %p\n", __func__, mw, mmid, mhp);
+ return 0;
+ }
+
+@@ -754,7 +754,7 @@ static int iwch_destroy_qp(struct ib_qp *ib_qp)
+ cxio_destroy_qp(&rhp->rdev, &qhp->wq,
+ ucontext ? &ucontext->uctx : &rhp->rdev.uctx);
+
+- PDBG("%s ib_qp %p qpid 0x%0x qhp %p\n", __FUNCTION__,
++ PDBG("%s ib_qp %p qpid 0x%0x qhp %p\n", __func__,
+ ib_qp, qhp->wq.qpid, qhp);
+ kfree(qhp);
+ return 0;
+@@ -773,7 +773,7 @@ static struct ib_qp *iwch_create_qp(struct ib_pd *pd,
+ int wqsize, sqsize, rqsize;
+ struct iwch_ucontext *ucontext;
+
+- PDBG("%s ib_pd %p\n", __FUNCTION__, pd);
++ PDBG("%s ib_pd %p\n", __func__, pd);
+ if (attrs->qp_type != IB_QPT_RC)
+ return ERR_PTR(-EINVAL);
+ php = to_iwch_pd(pd);
+@@ -805,7 +805,7 @@ static struct ib_qp *iwch_create_qp(struct ib_pd *pd,
+ */
+ sqsize = roundup_pow_of_two(attrs->cap.max_send_wr);
+ wqsize = roundup_pow_of_two(rqsize + sqsize);
+- PDBG("%s wqsize %d sqsize %d rqsize %d\n", __FUNCTION__,
++ PDBG("%s wqsize %d sqsize %d rqsize %d\n", __func__,
+ wqsize, sqsize, rqsize);
+ qhp = kzalloc(sizeof(*qhp), GFP_KERNEL);
+ if (!qhp)
+@@ -898,7 +898,7 @@ static struct ib_qp *iwch_create_qp(struct ib_pd *pd,
+ init_timer(&(qhp->timer));
+ PDBG("%s sq_num_entries %d, rq_num_entries %d "
+ "qpid 0x%0x qhp %p dma_addr 0x%llx size %d\n",
+- __FUNCTION__, qhp->attr.sq_num_entries, qhp->attr.rq_num_entries,
++ __func__, qhp->attr.sq_num_entries, qhp->attr.rq_num_entries,
+ qhp->wq.qpid, qhp, (unsigned long long) qhp->wq.dma_addr,
+ 1 << qhp->wq.size_log2);
+ return &qhp->ibqp;
+@@ -912,7 +912,7 @@ static int iwch_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ enum iwch_qp_attr_mask mask = 0;
+ struct iwch_qp_attributes attrs;
+
+- PDBG("%s ib_qp %p\n", __FUNCTION__, ibqp);
++ PDBG("%s ib_qp %p\n", __func__, ibqp);
+
+ /* iwarp does not support the RTR state */
+ if ((attr_mask & IB_QP_STATE) && (attr->qp_state == IB_QPS_RTR))
+@@ -945,20 +945,20 @@ static int iwch_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+
+ void iwch_qp_add_ref(struct ib_qp *qp)
+ {
+- PDBG("%s ib_qp %p\n", __FUNCTION__, qp);
++ PDBG("%s ib_qp %p\n", __func__, qp);
+ atomic_inc(&(to_iwch_qp(qp)->refcnt));
+ }
+
+ void iwch_qp_rem_ref(struct ib_qp *qp)
+ {
+- PDBG("%s ib_qp %p\n", __FUNCTION__, qp);
++ PDBG("%s ib_qp %p\n", __func__, qp);
+ if (atomic_dec_and_test(&(to_iwch_qp(qp)->refcnt)))
+ wake_up(&(to_iwch_qp(qp)->wait));
+ }
+
+ static struct ib_qp *iwch_get_qp(struct ib_device *dev, int qpn)
+ {
+- PDBG("%s ib_dev %p qpn 0x%x\n", __FUNCTION__, dev, qpn);
++ PDBG("%s ib_dev %p qpn 0x%x\n", __func__, dev, qpn);
+ return (struct ib_qp *)get_qhp(to_iwch_dev(dev), qpn);
+ }
+
+@@ -966,7 +966,7 @@ static struct ib_qp *iwch_get_qp(struct ib_device *dev, int qpn)
+ static int iwch_query_pkey(struct ib_device *ibdev,
+ u8 port, u16 index, u16 * pkey)
+ {
+- PDBG("%s ibdev %p\n", __FUNCTION__, ibdev);
++ PDBG("%s ibdev %p\n", __func__, ibdev);
+ *pkey = 0;
+ return 0;
+ }
+@@ -977,7 +977,7 @@ static int iwch_query_gid(struct ib_device *ibdev, u8 port,
+ struct iwch_dev *dev;
+
+ PDBG("%s ibdev %p, port %d, index %d, gid %p\n",
+- __FUNCTION__, ibdev, port, index, gid);
++ __func__, ibdev, port, index, gid);
+ dev = to_iwch_dev(ibdev);
+ BUG_ON(port == 0 || port > 2);
+ memset(&(gid->raw[0]), 0, sizeof(gid->raw));
+@@ -990,7 +990,7 @@ static int iwch_query_device(struct ib_device *ibdev,
+ {
+
+ struct iwch_dev *dev;
+- PDBG("%s ibdev %p\n", __FUNCTION__, ibdev);
++ PDBG("%s ibdev %p\n", __func__, ibdev);
+
+ dev = to_iwch_dev(ibdev);
+ memset(props, 0, sizeof *props);
+@@ -1017,7 +1017,7 @@ static int iwch_query_device(struct ib_device *ibdev,
+ static int iwch_query_port(struct ib_device *ibdev,
+ u8 port, struct ib_port_attr *props)
+ {
+- PDBG("%s ibdev %p\n", __FUNCTION__, ibdev);
++ PDBG("%s ibdev %p\n", __func__, ibdev);
+ props->max_mtu = IB_MTU_4096;
+ props->lid = 0;
+ props->lmc = 0;
+@@ -1041,61 +1041,60 @@ static int iwch_query_port(struct ib_device *ibdev,
+ return 0;
+ }
+
+-static ssize_t show_rev(struct class_device *cdev, char *buf)
++static ssize_t show_rev(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct iwch_dev *dev = container_of(cdev, struct iwch_dev,
+- ibdev.class_dev);
+- PDBG("%s class dev 0x%p\n", __FUNCTION__, cdev);
+- return sprintf(buf, "%d\n", dev->rdev.t3cdev_p->type);
++ struct iwch_dev *iwch_dev = container_of(dev, struct iwch_dev,
++ ibdev.dev);
++ PDBG("%s dev 0x%p\n", __func__, dev);
++ return sprintf(buf, "%d\n", iwch_dev->rdev.t3cdev_p->type);
+ }
+
+-static ssize_t show_fw_ver(struct class_device *cdev, char *buf)
++static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+- struct iwch_dev *dev = container_of(cdev, struct iwch_dev,
+- ibdev.class_dev);
++ struct iwch_dev *iwch_dev = container_of(dev, struct iwch_dev,
++ ibdev.dev);
+ struct ethtool_drvinfo info;
+- struct net_device *lldev = dev->rdev.t3cdev_p->lldev;
++ struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev;
+
+- PDBG("%s class dev 0x%p\n", __FUNCTION__, cdev);
+- rtnl_lock();
++ PDBG("%s dev 0x%p\n", __func__, dev);
+ lldev->ethtool_ops->get_drvinfo(lldev, &info);
+- rtnl_unlock();
+ return sprintf(buf, "%s\n", info.fw_version);
+ }
+
+-static ssize_t show_hca(struct class_device *cdev, char *buf)
++static ssize_t show_hca(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct iwch_dev *dev = container_of(cdev, struct iwch_dev,
+- ibdev.class_dev);
++ struct iwch_dev *iwch_dev = container_of(dev, struct iwch_dev,
++ ibdev.dev);
+ struct ethtool_drvinfo info;
+- struct net_device *lldev = dev->rdev.t3cdev_p->lldev;
++ struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev;
+
+- PDBG("%s class dev 0x%p\n", __FUNCTION__, cdev);
+- rtnl_lock();
++ PDBG("%s dev 0x%p\n", __func__, dev);
+ lldev->ethtool_ops->get_drvinfo(lldev, &info);
+- rtnl_unlock();
+ return sprintf(buf, "%s\n", info.driver);
+ }
+
+-static ssize_t show_board(struct class_device *cdev, char *buf)
++static ssize_t show_board(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct iwch_dev *dev = container_of(cdev, struct iwch_dev,
+- ibdev.class_dev);
+- PDBG("%s class dev 0x%p\n", __FUNCTION__, dev);
+- return sprintf(buf, "%x.%x\n", dev->rdev.rnic_info.pdev->vendor,
+- dev->rdev.rnic_info.pdev->device);
++ struct iwch_dev *iwch_dev = container_of(dev, struct iwch_dev,
++ ibdev.dev);
++ PDBG("%s dev 0x%p\n", __func__, dev);
++ return sprintf(buf, "%x.%x\n", iwch_dev->rdev.rnic_info.pdev->vendor,
++ iwch_dev->rdev.rnic_info.pdev->device);
+ }
+
+-static CLASS_DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
+-static CLASS_DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
+-static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
+-static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
++static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
++static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
++static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
++static DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
+
+-static struct class_device_attribute *iwch_class_attributes[] = {
+- &class_device_attr_hw_rev,
+- &class_device_attr_fw_ver,
+- &class_device_attr_hca_type,
+- &class_device_attr_board_id
++static struct device_attribute *iwch_class_attributes[] = {
++ &dev_attr_hw_rev,
++ &dev_attr_fw_ver,
++ &dev_attr_hca_type,
++ &dev_attr_board_id
+ };
+
+ int iwch_register_device(struct iwch_dev *dev)
+@@ -1103,14 +1102,13 @@ int iwch_register_device(struct iwch_dev *dev)
+ int ret;
+ int i;
+
+- PDBG("%s iwch_dev %p\n", __FUNCTION__, dev);
++ PDBG("%s iwch_dev %p\n", __func__, dev);
+ strlcpy(dev->ibdev.name, "cxgb3_%d", IB_DEVICE_NAME_MAX);
+ memset(&dev->ibdev.node_guid, 0, sizeof(dev->ibdev.node_guid));
+ memcpy(&dev->ibdev.node_guid, dev->rdev.t3cdev_p->lldev->dev_addr, 6);
+ dev->ibdev.owner = THIS_MODULE;
+ dev->device_cap_flags =
+- (IB_DEVICE_ZERO_STAG |
+- IB_DEVICE_SEND_W_INV | IB_DEVICE_MEM_WINDOW);
++ (IB_DEVICE_ZERO_STAG | IB_DEVICE_MEM_WINDOW);
+
+ dev->ibdev.uverbs_cmd_mask =
+ (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) |
+@@ -1190,8 +1188,8 @@ int iwch_register_device(struct iwch_dev *dev)
+ goto bail1;
+
+ for (i = 0; i < ARRAY_SIZE(iwch_class_attributes); ++i) {
+- ret = class_device_create_file(&dev->ibdev.class_dev,
+- iwch_class_attributes[i]);
++ ret = device_create_file(&dev->ibdev.dev,
++ iwch_class_attributes[i]);
+ if (ret) {
+ goto bail2;
+ }
+@@ -1207,10 +1205,10 @@ void iwch_unregister_device(struct iwch_dev *dev)
+ {
+ int i;
+
+- PDBG("%s iwch_dev %p\n", __FUNCTION__, dev);
++ PDBG("%s iwch_dev %p\n", __func__, dev);
+ for (i = 0; i < ARRAY_SIZE(iwch_class_attributes); ++i)
+- class_device_remove_file(&dev->ibdev.class_dev,
+- iwch_class_attributes[i]);
++ device_remove_file(&dev->ibdev.dev,
++ iwch_class_attributes[i]);
+ ib_unregister_device(&dev->ibdev);
+ return;
+ }
+diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.h b/drivers/infiniband/hw/cxgb3/iwch_provider.h
+index 48833f3..61356f9 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch_provider.h
++++ b/drivers/infiniband/hw/cxgb3/iwch_provider.h
+@@ -213,7 +213,7 @@ static inline struct iwch_mm_entry *remove_mmap(struct iwch_ucontext *ucontext,
+ if (mm->key == key && mm->len == len) {
+ list_del_init(&mm->entry);
+ spin_unlock(&ucontext->mmap_lock);
+- PDBG("%s key 0x%x addr 0x%llx len %d\n", __FUNCTION__,
++ PDBG("%s key 0x%x addr 0x%llx len %d\n", __func__,
+ key, (unsigned long long) mm->addr, mm->len);
+ return mm;
+ }
+@@ -226,7 +226,7 @@ static inline void insert_mmap(struct iwch_ucontext *ucontext,
+ struct iwch_mm_entry *mm)
+ {
+ spin_lock(&ucontext->mmap_lock);
+- PDBG("%s key 0x%x addr 0x%llx len %d\n", __FUNCTION__,
++ PDBG("%s key 0x%x addr 0x%llx len %d\n", __func__,
+ mm->key, (unsigned long long) mm->addr, mm->len);
+ list_add_tail(&mm->entry, &ucontext->mmaps);
+ spin_unlock(&ucontext->mmap_lock);
+diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c
+index ea2cdd7..8891c3b 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch_qp.c
++++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c
+@@ -72,7 +72,7 @@ static int iwch_build_rdma_send(union t3_wr *wqe, struct ib_send_wr *wr,
+ wqe->send.reserved[2] = 0;
+ if (wr->opcode == IB_WR_SEND_WITH_IMM) {
+ plen = 4;
+- wqe->send.sgl[0].stag = wr->imm_data;
++ wqe->send.sgl[0].stag = wr->ex.imm_data;
+ wqe->send.sgl[0].len = __constant_cpu_to_be32(0);
+ wqe->send.num_sgle = __constant_cpu_to_be32(0);
+ *flit_cnt = 5;
+@@ -112,7 +112,7 @@ static int iwch_build_rdma_write(union t3_wr *wqe, struct ib_send_wr *wr,
+
+ if (wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) {
+ plen = 4;
+- wqe->write.sgl[0].stag = wr->imm_data;
++ wqe->write.sgl[0].stag = wr->ex.imm_data;
+ wqe->write.sgl[0].len = __constant_cpu_to_be32(0);
+ wqe->write.num_sgle = __constant_cpu_to_be32(0);
+ *flit_cnt = 6;
+@@ -168,30 +168,30 @@ static int iwch_sgl2pbl_map(struct iwch_dev *rhp, struct ib_sge *sg_list,
+
+ mhp = get_mhp(rhp, (sg_list[i].lkey) >> 8);
+ if (!mhp) {
+- PDBG("%s %d\n", __FUNCTION__, __LINE__);
++ PDBG("%s %d\n", __func__, __LINE__);
+ return -EIO;
+ }
+ if (!mhp->attr.state) {
+- PDBG("%s %d\n", __FUNCTION__, __LINE__);
++ PDBG("%s %d\n", __func__, __LINE__);
+ return -EIO;
+ }
+ if (mhp->attr.zbva) {
+- PDBG("%s %d\n", __FUNCTION__, __LINE__);
++ PDBG("%s %d\n", __func__, __LINE__);
+ return -EIO;
+ }
+
+ if (sg_list[i].addr < mhp->attr.va_fbo) {
+- PDBG("%s %d\n", __FUNCTION__, __LINE__);
++ PDBG("%s %d\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+ if (sg_list[i].addr + ((u64) sg_list[i].length) <
+ sg_list[i].addr) {
+- PDBG("%s %d\n", __FUNCTION__, __LINE__);
++ PDBG("%s %d\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+ if (sg_list[i].addr + ((u64) sg_list[i].length) >
+ mhp->attr.va_fbo + ((u64) mhp->attr.len)) {
+- PDBG("%s %d\n", __FUNCTION__, __LINE__);
++ PDBG("%s %d\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+ offset = sg_list[i].addr - mhp->attr.va_fbo;
+@@ -290,7 +290,7 @@ int iwch_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ qhp->wq.oldest_read = sqp;
+ break;
+ default:
+- PDBG("%s post of type=%d TBD!\n", __FUNCTION__,
++ PDBG("%s post of type=%d TBD!\n", __func__,
+ wr->opcode);
+ err = -EINVAL;
+ }
+@@ -309,7 +309,7 @@ int iwch_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ Q_GENBIT(qhp->wq.wptr, qhp->wq.size_log2),
+ 0, t3_wr_flit_cnt);
+ PDBG("%s cookie 0x%llx wq idx 0x%x swsq idx %ld opcode %d\n",
+- __FUNCTION__, (unsigned long long) wr->wr_id, idx,
++ __func__, (unsigned long long) wr->wr_id, idx,
+ Q_PTR2IDX(qhp->wq.sq_wptr, qhp->wq.sq_size_log2),
+ sqp->opcode);
+ wr = wr->next;
+@@ -361,7 +361,7 @@ int iwch_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+ Q_GENBIT(qhp->wq.wptr, qhp->wq.size_log2),
+ 0, sizeof(struct t3_receive_wr) >> 3);
+ PDBG("%s cookie 0x%llx idx 0x%x rq_wptr 0x%x rw_rptr 0x%x "
+- "wqe %p \n", __FUNCTION__, (unsigned long long) wr->wr_id,
++ "wqe %p \n", __func__, (unsigned long long) wr->wr_id,
+ idx, qhp->wq.rq_wptr, qhp->wq.rq_rptr, wqe);
+ ++(qhp->wq.rq_wptr);
+ ++(qhp->wq.wptr);
+@@ -407,7 +407,7 @@ int iwch_bind_mw(struct ib_qp *qp,
+ return -ENOMEM;
+ }
+ idx = Q_PTR2IDX(qhp->wq.wptr, qhp->wq.size_log2);
+- PDBG("%s: idx 0x%0x, mw 0x%p, mw_bind 0x%p\n", __FUNCTION__, idx,
++ PDBG("%s: idx 0x%0x, mw 0x%p, mw_bind 0x%p\n", __func__, idx,
+ mw, mw_bind);
+ wqe = (union t3_wr *) (qhp->wq.queue + idx);
+
+@@ -595,10 +595,10 @@ int iwch_post_terminate(struct iwch_qp *qhp, struct respQ_msg_t *rsp_msg)
+ struct terminate_message *term;
+ struct sk_buff *skb;
+
+- PDBG("%s %d\n", __FUNCTION__, __LINE__);
++ PDBG("%s %d\n", __func__, __LINE__);
+ skb = alloc_skb(40, GFP_ATOMIC);
+ if (!skb) {
+- printk(KERN_ERR "%s cannot send TERMINATE!\n", __FUNCTION__);
++ printk(KERN_ERR "%s cannot send TERMINATE!\n", __func__);
+ return -ENOMEM;
+ }
+ wqe = (union t3_wr *)skb_put(skb, 40);
+@@ -629,7 +629,7 @@ static void __flush_qp(struct iwch_qp *qhp, unsigned long *flag)
+ rchp = get_chp(qhp->rhp, qhp->attr.rcq);
+ schp = get_chp(qhp->rhp, qhp->attr.scq);
+
+- PDBG("%s qhp %p rchp %p schp %p\n", __FUNCTION__, qhp, rchp, schp);
++ PDBG("%s qhp %p rchp %p schp %p\n", __func__, qhp, rchp, schp);
+ /* take a ref on the qhp since we must release the lock */
+ atomic_inc(&qhp->refcnt);
+ spin_unlock_irqrestore(&qhp->lock, *flag);
+@@ -720,11 +720,11 @@ static int rdma_init(struct iwch_dev *rhp, struct iwch_qp *qhp,
+ init_attr.flags |= capable(CAP_NET_BIND_SERVICE) ? PRIV_QP : 0;
+ init_attr.irs = qhp->ep->rcv_seq;
+ PDBG("%s init_attr.rq_addr 0x%x init_attr.rq_size = %d "
+- "flags 0x%x qpcaps 0x%x\n", __FUNCTION__,
++ "flags 0x%x qpcaps 0x%x\n", __func__,
+ init_attr.rq_addr, init_attr.rq_size,
+ init_attr.flags, init_attr.qpcaps);
+ ret = cxio_rdma_init(&rhp->rdev, &init_attr);
+- PDBG("%s ret %d\n", __FUNCTION__, ret);
++ PDBG("%s ret %d\n", __func__, ret);
+ return ret;
+ }
+
+@@ -742,7 +742,7 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp,
+ int free = 0;
+ struct iwch_ep *ep = NULL;
+
+- PDBG("%s qhp %p qpid 0x%x ep %p state %d -> %d\n", __FUNCTION__,
++ PDBG("%s qhp %p qpid 0x%x ep %p state %d -> %d\n", __func__,
+ qhp, qhp->wq.qpid, qhp->ep, qhp->attr.state,
+ (mask & IWCH_QP_ATTR_NEXT_STATE) ? attrs->next_state : -1);
+
+@@ -899,14 +899,14 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp,
+ break;
+ default:
+ printk(KERN_ERR "%s in a bad state %d\n",
+- __FUNCTION__, qhp->attr.state);
++ __func__, qhp->attr.state);
+ ret = -EINVAL;
+ goto err;
+ break;
+ }
+ goto out;
+ err:
+- PDBG("%s disassociating ep %p qpid 0x%x\n", __FUNCTION__, qhp->ep,
++ PDBG("%s disassociating ep %p qpid 0x%x\n", __func__, qhp->ep,
+ qhp->wq.qpid);
+
+ /* disassociate the LLP connection */
+@@ -939,7 +939,7 @@ out:
+ if (free)
+ put_ep(&ep->com);
+
+- PDBG("%s exit state %d\n", __FUNCTION__, qhp->attr.state);
++ PDBG("%s exit state %d\n", __func__, qhp->attr.state);
+ return ret;
+ }
+
+diff --git a/drivers/infiniband/hw/ehca/ehca_av.c b/drivers/infiniband/hw/ehca/ehca_av.c
+index 194c1c3..56735ea 100644
+--- a/drivers/infiniband/hw/ehca/ehca_av.c
++++ b/drivers/infiniband/hw/ehca/ehca_av.c
+@@ -41,9 +41,6 @@
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+-
+-#include <asm/current.h>
+-
+ #include "ehca_tools.h"
+ #include "ehca_iverbs.h"
+ #include "hcp_if.h"
+@@ -170,17 +167,8 @@ int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
+ {
+ struct ehca_av *av;
+ struct ehca_ud_av new_ehca_av;
+- struct ehca_pd *my_pd = container_of(ah->pd, struct ehca_pd, ib_pd);
+ struct ehca_shca *shca = container_of(ah->pd->device, struct ehca_shca,
+ ib_device);
+- u32 cur_pid = current->tgid;
+-
+- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+- my_pd->ownpid != cur_pid) {
+- ehca_err(ah->device, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_pd->ownpid);
+- return -EINVAL;
+- }
+
+ memset(&new_ehca_av, 0, sizeof(new_ehca_av));
+ new_ehca_av.sl = ah_attr->sl;
+@@ -242,15 +230,6 @@ int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
+ int ehca_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
+ {
+ struct ehca_av *av = container_of(ah, struct ehca_av, ib_ah);
+- struct ehca_pd *my_pd = container_of(ah->pd, struct ehca_pd, ib_pd);
+- u32 cur_pid = current->tgid;
+-
+- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+- my_pd->ownpid != cur_pid) {
+- ehca_err(ah->device, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_pd->ownpid);
+- return -EINVAL;
+- }
+
+ memcpy(&ah_attr->grh.dgid, &av->av.grh.word_3,
+ sizeof(ah_attr->grh.dgid));
+@@ -273,16 +252,6 @@ int ehca_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
+
+ int ehca_destroy_ah(struct ib_ah *ah)
+ {
+- struct ehca_pd *my_pd = container_of(ah->pd, struct ehca_pd, ib_pd);
+- u32 cur_pid = current->tgid;
+-
+- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+- my_pd->ownpid != cur_pid) {
+- ehca_err(ah->device, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_pd->ownpid);
+- return -EINVAL;
+- }
+-
+ kmem_cache_free(av_cache, container_of(ah, struct ehca_av, ib_ah));
+
+ return 0;
+diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
+index 92cce8a..0d13fe0 100644
+--- a/drivers/infiniband/hw/ehca/ehca_classes.h
++++ b/drivers/infiniband/hw/ehca/ehca_classes.h
+@@ -132,7 +132,6 @@ struct ehca_shca {
+ struct ehca_pd {
+ struct ib_pd ib_pd;
+ struct ipz_pd fw_pd;
+- u32 ownpid;
+ /* small queue mgmt */
+ struct mutex lock;
+ struct list_head free[2];
+@@ -215,7 +214,6 @@ struct ehca_cq {
+ atomic_t nr_events; /* #events seen */
+ wait_queue_head_t wait_completion;
+ spinlock_t task_lock;
+- u32 ownpid;
+ /* mmap counter for resources mapped into user space */
+ u32 mm_count_queue;
+ u32 mm_count_galpa;
+diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
+index 0467c15..ec0cfcf 100644
+--- a/drivers/infiniband/hw/ehca/ehca_cq.c
++++ b/drivers/infiniband/hw/ehca/ehca_cq.c
+@@ -43,8 +43,6 @@
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+-#include <asm/current.h>
+-
+ #include "ehca_iverbs.h"
+ #include "ehca_classes.h"
+ #include "ehca_irq.h"
+@@ -148,7 +146,6 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
+ spin_lock_init(&my_cq->task_lock);
+ atomic_set(&my_cq->nr_events, 0);
+ init_waitqueue_head(&my_cq->wait_completion);
+- my_cq->ownpid = current->tgid;
+
+ cq = &my_cq->ib_cq;
+
+@@ -320,7 +317,6 @@ int ehca_destroy_cq(struct ib_cq *cq)
+ struct ehca_shca *shca = container_of(device, struct ehca_shca,
+ ib_device);
+ struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle;
+- u32 cur_pid = current->tgid;
+ unsigned long flags;
+
+ if (cq->uobject) {
+@@ -329,12 +325,6 @@ int ehca_destroy_cq(struct ib_cq *cq)
+ "user space cq_num=%x", my_cq->cq_number);
+ return -EINVAL;
+ }
+- if (my_cq->ownpid != cur_pid) {
+- ehca_err(device, "Invalid caller pid=%x ownpid=%x "
+- "cq_num=%x",
+- cur_pid, my_cq->ownpid, my_cq->cq_number);
+- return -EINVAL;
+- }
+ }
+
+ /*
+@@ -374,15 +364,6 @@ int ehca_destroy_cq(struct ib_cq *cq)
+
+ int ehca_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata)
+ {
+- struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
+- u32 cur_pid = current->tgid;
+-
+- if (cq->uobject && my_cq->ownpid != cur_pid) {
+- ehca_err(cq->device, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_cq->ownpid);
+- return -EINVAL;
+- }
+-
+ /* TODO: proper resize needs to be done */
+ ehca_err(cq->device, "not implemented yet");
+
+diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c
+index 5bd7b59..2515cbd 100644
+--- a/drivers/infiniband/hw/ehca/ehca_hca.c
++++ b/drivers/infiniband/hw/ehca/ehca_hca.c
+@@ -43,6 +43,11 @@
+ #include "ehca_iverbs.h"
+ #include "hcp_if.h"
+
++static unsigned int limit_uint(unsigned int value)
++{
++ return min_t(unsigned int, value, INT_MAX);
++}
++
+ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
+ {
+ int i, ret = 0;
+@@ -83,37 +88,40 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
+ props->vendor_id = rblock->vendor_id >> 8;
+ props->vendor_part_id = rblock->vendor_part_id >> 16;
+ props->hw_ver = rblock->hw_ver;
+- props->max_qp = min_t(unsigned, rblock->max_qp, INT_MAX);
+- props->max_qp_wr = min_t(unsigned, rblock->max_wqes_wq, INT_MAX);
+- props->max_sge = min_t(unsigned, rblock->max_sge, INT_MAX);
+- props->max_sge_rd = min_t(unsigned, rblock->max_sge_rd, INT_MAX);
+- props->max_cq = min_t(unsigned, rblock->max_cq, INT_MAX);
+- props->max_cqe = min_t(unsigned, rblock->max_cqe, INT_MAX);
+- props->max_mr = min_t(unsigned, rblock->max_mr, INT_MAX);
+- props->max_mw = min_t(unsigned, rblock->max_mw, INT_MAX);
+- props->max_pd = min_t(unsigned, rblock->max_pd, INT_MAX);
+- props->max_ah = min_t(unsigned, rblock->max_ah, INT_MAX);
+- props->max_fmr = min_t(unsigned, rblock->max_mr, INT_MAX);
++ props->max_qp = limit_uint(rblock->max_qp);
++ props->max_qp_wr = limit_uint(rblock->max_wqes_wq);
++ props->max_sge = limit_uint(rblock->max_sge);
++ props->max_sge_rd = limit_uint(rblock->max_sge_rd);
++ props->max_cq = limit_uint(rblock->max_cq);
++ props->max_cqe = limit_uint(rblock->max_cqe);
++ props->max_mr = limit_uint(rblock->max_mr);
++ props->max_mw = limit_uint(rblock->max_mw);
++ props->max_pd = limit_uint(rblock->max_pd);
++ props->max_ah = limit_uint(rblock->max_ah);
++ props->max_ee = limit_uint(rblock->max_rd_ee_context);
++ props->max_rdd = limit_uint(rblock->max_rd_domain);
++ props->max_fmr = limit_uint(rblock->max_mr);
++ props->local_ca_ack_delay = limit_uint(rblock->local_ca_ack_delay);
++ props->max_qp_rd_atom = limit_uint(rblock->max_rr_qp);
++ props->max_ee_rd_atom = limit_uint(rblock->max_rr_ee_context);
++ props->max_res_rd_atom = limit_uint(rblock->max_rr_hca);
++ props->max_qp_init_rd_atom = limit_uint(rblock->max_act_wqs_qp);
++ props->max_ee_init_rd_atom = limit_uint(rblock->max_act_wqs_ee_context);
+
+ if (EHCA_BMASK_GET(HCA_CAP_SRQ, shca->hca_cap)) {
+- props->max_srq = props->max_qp;
+- props->max_srq_wr = props->max_qp_wr;
++ props->max_srq = limit_uint(props->max_qp);
++ props->max_srq_wr = limit_uint(props->max_qp_wr);
+ props->max_srq_sge = 3;
+ }
+
+- props->max_pkeys = 16;
+- props->local_ca_ack_delay
+- = rblock->local_ca_ack_delay;
+- props->max_raw_ipv6_qp
+- = min_t(unsigned, rblock->max_raw_ipv6_qp, INT_MAX);
+- props->max_raw_ethy_qp
+- = min_t(unsigned, rblock->max_raw_ethy_qp, INT_MAX);
+- props->max_mcast_grp
+- = min_t(unsigned, rblock->max_mcast_grp, INT_MAX);
+- props->max_mcast_qp_attach
+- = min_t(unsigned, rblock->max_mcast_qp_attach, INT_MAX);
++ props->max_pkeys = 16;
++ props->local_ca_ack_delay = limit_uint(rblock->local_ca_ack_delay);
++ props->max_raw_ipv6_qp = limit_uint(rblock->max_raw_ipv6_qp);
++ props->max_raw_ethy_qp = limit_uint(rblock->max_raw_ethy_qp);
++ props->max_mcast_grp = limit_uint(rblock->max_mcast_grp);
++ props->max_mcast_qp_attach = limit_uint(rblock->max_mcast_qp_attach);
+ props->max_total_mcast_qp_attach
+- = min_t(unsigned, rblock->max_total_mcast_qp_attach, INT_MAX);
++ = limit_uint(rblock->max_total_mcast_qp_attach);
+
+ /* translate device capabilities */
+ props->device_cap_flags = IB_DEVICE_SYS_IMAGE_GUID |
+@@ -128,6 +136,46 @@ query_device1:
+ return ret;
+ }
+
++static int map_mtu(struct ehca_shca *shca, u32 fw_mtu)
++{
++ switch (fw_mtu) {
++ case 0x1:
++ return IB_MTU_256;
++ case 0x2:
++ return IB_MTU_512;
++ case 0x3:
++ return IB_MTU_1024;
++ case 0x4:
++ return IB_MTU_2048;
++ case 0x5:
++ return IB_MTU_4096;
++ default:
++ ehca_err(&shca->ib_device, "Unknown MTU size: %x.",
++ fw_mtu);
++ return 0;
++ }
++}
++
++static int map_number_of_vls(struct ehca_shca *shca, u32 vl_cap)
++{
++ switch (vl_cap) {
++ case 0x1:
++ return 1;
++ case 0x2:
++ return 2;
++ case 0x3:
++ return 4;
++ case 0x4:
++ return 8;
++ case 0x5:
++ return 15;
++ default:
++ ehca_err(&shca->ib_device, "invalid Vl Capability: %x.",
++ vl_cap);
++ return 0;
++ }
++}
++
+ int ehca_query_port(struct ib_device *ibdev,
+ u8 port, struct ib_port_attr *props)
+ {
+@@ -152,31 +200,13 @@ int ehca_query_port(struct ib_device *ibdev,
+
+ memset(props, 0, sizeof(struct ib_port_attr));
+
+- switch (rblock->max_mtu) {
+- case 0x1:
+- props->active_mtu = props->max_mtu = IB_MTU_256;
+- break;
+- case 0x2:
+- props->active_mtu = props->max_mtu = IB_MTU_512;
+- break;
+- case 0x3:
+- props->active_mtu = props->max_mtu = IB_MTU_1024;
+- break;
+- case 0x4:
+- props->active_mtu = props->max_mtu = IB_MTU_2048;
+- break;
+- case 0x5:
+- props->active_mtu = props->max_mtu = IB_MTU_4096;
+- break;
+- default:
+- ehca_err(&shca->ib_device, "Unknown MTU size: %x.",
+- rblock->max_mtu);
+- break;
+- }
+-
++ props->active_mtu = props->max_mtu = map_mtu(shca, rblock->max_mtu);
+ props->port_cap_flags = rblock->capability_mask;
+ props->gid_tbl_len = rblock->gid_tbl_len;
+- props->max_msg_sz = rblock->max_msg_sz;
++ if (rblock->max_msg_sz)
++ props->max_msg_sz = rblock->max_msg_sz;
++ else
++ props->max_msg_sz = 0x1 << 31;
+ props->bad_pkey_cntr = rblock->bad_pkey_cntr;
+ props->qkey_viol_cntr = rblock->qkey_viol_cntr;
+ props->pkey_tbl_len = rblock->pkey_tbl_len;
+@@ -186,6 +216,7 @@ int ehca_query_port(struct ib_device *ibdev,
+ props->sm_sl = rblock->sm_sl;
+ props->subnet_timeout = rblock->subnet_timeout;
+ props->init_type_reply = rblock->init_type_reply;
++ props->max_vl_num = map_number_of_vls(shca, rblock->vl_cap);
+
+ if (rblock->state && rblock->phys_width) {
+ props->phys_state = rblock->phys_pstate;
+@@ -314,7 +345,7 @@ query_gid1:
+ return ret;
+ }
+
+-const u32 allowed_port_caps = (
++static const u32 allowed_port_caps = (
+ IB_PORT_SM | IB_PORT_LED_INFO_SUP | IB_PORT_CM_SUP |
+ IB_PORT_SNMP_TUNNEL_SUP | IB_PORT_DEVICE_MGMT_SUP |
+ IB_PORT_VENDOR_CLASS_SUP);
+diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
+index a86ebcc..65b3362 100644
+--- a/drivers/infiniband/hw/ehca/ehca_main.c
++++ b/drivers/infiniband/hw/ehca/ehca_main.c
+@@ -57,16 +57,17 @@ MODULE_AUTHOR("Christoph Raisch <raisch at de.ibm.com>");
+ MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver");
+ MODULE_VERSION(HCAD_VERSION);
+
+-int ehca_open_aqp1 = 0;
++static int ehca_open_aqp1 = 0;
++static int ehca_hw_level = 0;
++static int ehca_poll_all_eqs = 1;
++static int ehca_mr_largepage = 1;
++
+ int ehca_debug_level = 0;
+-int ehca_hw_level = 0;
+ int ehca_nr_ports = 2;
+ int ehca_use_hp_mr = 0;
+ int ehca_port_act_time = 30;
+-int ehca_poll_all_eqs = 1;
+ int ehca_static_rate = -1;
+ int ehca_scaling_code = 0;
+-int ehca_mr_largepage = 1;
+ int ehca_lock_hcalls = -1;
+
+ module_param_named(open_aqp1, ehca_open_aqp1, int, S_IRUGO);
+@@ -396,7 +397,7 @@ init_node_guid1:
+ return ret;
+ }
+
+-int ehca_init_device(struct ehca_shca *shca)
++static int ehca_init_device(struct ehca_shca *shca)
+ {
+ int ret;
+
+@@ -579,8 +580,8 @@ static ssize_t ehca_store_debug_level(struct device_driver *ddp,
+ return 1;
+ }
+
+-DRIVER_ATTR(debug_level, S_IRUSR | S_IWUSR,
+- ehca_show_debug_level, ehca_store_debug_level);
++static DRIVER_ATTR(debug_level, S_IRUSR | S_IWUSR,
++ ehca_show_debug_level, ehca_store_debug_level);
+
+ static struct attribute *ehca_drv_attrs[] = {
+ &driver_attr_debug_level.attr,
+@@ -941,7 +942,7 @@ void ehca_poll_eqs(unsigned long data)
+ spin_unlock(&shca_list_lock);
+ }
+
+-int __init ehca_module_init(void)
++static int __init ehca_module_init(void)
+ {
+ int ret;
+
+@@ -988,7 +989,7 @@ module_init1:
+ return ret;
+ };
+
+-void __exit ehca_module_exit(void)
++static void __exit ehca_module_exit(void)
+ {
+ if (ehca_poll_all_eqs == 1)
+ del_timer_sync(&poll_eqs_timer);
+diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c
+index e239bbf..f26997f 100644
+--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
++++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
+@@ -40,8 +40,6 @@
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+-#include <asm/current.h>
+-
+ #include <rdma/ib_umem.h>
+
+ #include "ehca_iverbs.h"
+@@ -419,7 +417,6 @@ int ehca_rereg_phys_mr(struct ib_mr *mr,
+ struct ehca_shca *shca =
+ container_of(mr->device, struct ehca_shca, ib_device);
+ struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr);
+- struct ehca_pd *my_pd = container_of(mr->pd, struct ehca_pd, ib_pd);
+ u64 new_size;
+ u64 *new_start;
+ u32 new_acl;
+@@ -429,15 +426,6 @@ int ehca_rereg_phys_mr(struct ib_mr *mr,
+ u32 num_kpages = 0;
+ u32 num_hwpages = 0;
+ struct ehca_mr_pginfo pginfo;
+- u32 cur_pid = current->tgid;
+-
+- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+- (my_pd->ownpid != cur_pid)) {
+- ehca_err(mr->device, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_pd->ownpid);
+- ret = -EINVAL;
+- goto rereg_phys_mr_exit0;
+- }
+
+ if (!(mr_rereg_mask & IB_MR_REREG_TRANS)) {
+ /* TODO not supported, because PHYP rereg hCall needs pages */
+@@ -577,19 +565,9 @@ int ehca_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr)
+ struct ehca_shca *shca =
+ container_of(mr->device, struct ehca_shca, ib_device);
+ struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr);
+- struct ehca_pd *my_pd = container_of(mr->pd, struct ehca_pd, ib_pd);
+- u32 cur_pid = current->tgid;
+ unsigned long sl_flags;
+ struct ehca_mr_hipzout_parms hipzout;
+
+- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+- (my_pd->ownpid != cur_pid)) {
+- ehca_err(mr->device, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_pd->ownpid);
+- ret = -EINVAL;
+- goto query_mr_exit0;
+- }
+-
+ if ((e_mr->flags & EHCA_MR_FLAG_FMR)) {
+ ehca_err(mr->device, "not supported for FMR, mr=%p e_mr=%p "
+ "e_mr->flags=%x", mr, e_mr, e_mr->flags);
+@@ -634,16 +612,6 @@ int ehca_dereg_mr(struct ib_mr *mr)
+ struct ehca_shca *shca =
+ container_of(mr->device, struct ehca_shca, ib_device);
+ struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr);
+- struct ehca_pd *my_pd = container_of(mr->pd, struct ehca_pd, ib_pd);
+- u32 cur_pid = current->tgid;
+-
+- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+- (my_pd->ownpid != cur_pid)) {
+- ehca_err(mr->device, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_pd->ownpid);
+- ret = -EINVAL;
+- goto dereg_mr_exit0;
+- }
+
+ if ((e_mr->flags & EHCA_MR_FLAG_FMR)) {
+ ehca_err(mr->device, "not supported for FMR, mr=%p e_mr=%p "
+@@ -1952,9 +1920,8 @@ next_kpage:
+ return ret;
+ }
+
+-int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo,
+- u32 number,
+- u64 *kpage)
++static int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo,
++ u32 number, u64 *kpage)
+ {
+ int ret = 0;
+ struct ib_phys_buf *pbuf;
+@@ -2012,9 +1979,8 @@ int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo,
+ return ret;
+ }
+
+-int ehca_set_pagebuf_fmr(struct ehca_mr_pginfo *pginfo,
+- u32 number,
+- u64 *kpage)
++static int ehca_set_pagebuf_fmr(struct ehca_mr_pginfo *pginfo,
++ u32 number, u64 *kpage)
+ {
+ int ret = 0;
+ u64 *fmrlist;
+diff --git a/drivers/infiniband/hw/ehca/ehca_pd.c b/drivers/infiniband/hw/ehca/ehca_pd.c
+index 43bcf08..2fe5548 100644
+--- a/drivers/infiniband/hw/ehca/ehca_pd.c
++++ b/drivers/infiniband/hw/ehca/ehca_pd.c
+@@ -38,8 +38,6 @@
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+-#include <asm/current.h>
+-
+ #include "ehca_tools.h"
+ #include "ehca_iverbs.h"
+
+@@ -58,7 +56,6 @@ struct ib_pd *ehca_alloc_pd(struct ib_device *device,
+ return ERR_PTR(-ENOMEM);
+ }
+
+- pd->ownpid = current->tgid;
+ for (i = 0; i < 2; i++) {
+ INIT_LIST_HEAD(&pd->free[i]);
+ INIT_LIST_HEAD(&pd->full[i]);
+@@ -85,18 +82,10 @@ struct ib_pd *ehca_alloc_pd(struct ib_device *device,
+
+ int ehca_dealloc_pd(struct ib_pd *pd)
+ {
+- u32 cur_pid = current->tgid;
+ struct ehca_pd *my_pd = container_of(pd, struct ehca_pd, ib_pd);
+ int i, leftovers = 0;
+ struct ipz_small_queue_page *page, *tmp;
+
+- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+- my_pd->ownpid != cur_pid) {
+- ehca_err(pd->device, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_pd->ownpid);
+- return -EINVAL;
+- }
+-
+ for (i = 0; i < 2; i++) {
+ list_splice(&my_pd->full[i], &my_pd->free[i]);
+ list_for_each_entry_safe(page, tmp, &my_pd->free[i], list) {
+diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
+index 1012f15..3eb14a5 100644
+--- a/drivers/infiniband/hw/ehca/ehca_qp.c
++++ b/drivers/infiniband/hw/ehca/ehca_qp.c
+@@ -43,9 +43,6 @@
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+-
+-#include <asm/current.h>
+-
+ #include "ehca_classes.h"
+ #include "ehca_tools.h"
+ #include "ehca_qes.h"
+@@ -424,6 +421,9 @@ static struct ehca_qp *internal_create_qp(
+ u32 swqe_size = 0, rwqe_size = 0, ib_qp_num;
+ unsigned long flags;
+
++ if (init_attr->create_flags)
++ return ERR_PTR(-EINVAL);
++
+ memset(&parms, 0, sizeof(parms));
+ qp_type = init_attr->qp_type;
+
+@@ -1526,16 +1526,6 @@ int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
+ struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca,
+ ib_device);
+ struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);
+- struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd,
+- ib_pd);
+- u32 cur_pid = current->tgid;
+-
+- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+- my_pd->ownpid != cur_pid) {
+- ehca_err(ibqp->pd->device, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_pd->ownpid);
+- return -EINVAL;
+- }
+
+ /* The if-block below caches qp_attr to be modified for GSI and SMI
+ * qps during the initialization by ib_mad. When the respective port
+@@ -1636,23 +1626,13 @@ int ehca_query_qp(struct ib_qp *qp,
+ int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr)
+ {
+ struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp);
+- struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd,
+- ib_pd);
+ struct ehca_shca *shca = container_of(qp->device, struct ehca_shca,
+ ib_device);
+ struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle;
+ struct hcp_modify_qp_control_block *qpcb;
+- u32 cur_pid = current->tgid;
+ int cnt, ret = 0;
+ u64 h_ret;
+
+- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+- my_pd->ownpid != cur_pid) {
+- ehca_err(qp->device, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_pd->ownpid);
+- return -EINVAL;
+- }
+-
+ if (qp_attr_mask & QP_ATTR_QUERY_NOT_SUPPORTED) {
+ ehca_err(qp->device, "Invalid attribute mask "
+ "ehca_qp=%p qp_num=%x qp_attr_mask=%x ",
+@@ -1797,8 +1777,6 @@ int ehca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+ {
+ struct ehca_qp *my_qp =
+ container_of(ibsrq, struct ehca_qp, ib_srq);
+- struct ehca_pd *my_pd =
+- container_of(ibsrq->pd, struct ehca_pd, ib_pd);
+ struct ehca_shca *shca =
+ container_of(ibsrq->pd->device, struct ehca_shca, ib_device);
+ struct hcp_modify_qp_control_block *mqpcb;
+@@ -1806,14 +1784,6 @@ int ehca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+ u64 h_ret;
+ int ret = 0;
+
+- u32 cur_pid = current->tgid;
+- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+- my_pd->ownpid != cur_pid) {
+- ehca_err(ibsrq->pd->device, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_pd->ownpid);
+- return -EINVAL;
+- }
+-
+ mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+ if (!mqpcb) {
+ ehca_err(ibsrq->device, "Could not get zeroed page for mqpcb "
+@@ -1864,22 +1834,13 @@ modify_srq_exit0:
+ int ehca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr)
+ {
+ struct ehca_qp *my_qp = container_of(srq, struct ehca_qp, ib_srq);
+- struct ehca_pd *my_pd = container_of(srq->pd, struct ehca_pd, ib_pd);
+ struct ehca_shca *shca = container_of(srq->device, struct ehca_shca,
+ ib_device);
+ struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle;
+ struct hcp_modify_qp_control_block *qpcb;
+- u32 cur_pid = current->tgid;
+ int ret = 0;
+ u64 h_ret;
+
+- if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+- my_pd->ownpid != cur_pid) {
+- ehca_err(srq->device, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_pd->ownpid);
+- return -EINVAL;
+- }
+-
+ qpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+ if (!qpcb) {
+ ehca_err(srq->device, "Out of memory for qpcb "
+@@ -1919,7 +1880,6 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
+ struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd,
+ ib_pd);
+ struct ehca_sport *sport = &shca->sport[my_qp->init_attr.port_num - 1];
+- u32 cur_pid = current->tgid;
+ u32 qp_num = my_qp->real_qp_num;
+ int ret;
+ u64 h_ret;
+@@ -1934,11 +1894,6 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
+ "user space qp_num=%x", qp_num);
+ return -EINVAL;
+ }
+- if (my_pd->ownpid != cur_pid) {
+- ehca_err(dev, "Invalid caller pid=%x ownpid=%x",
+- cur_pid, my_pd->ownpid);
+- return -EINVAL;
+- }
+ }
+
+ if (my_qp->send_cq) {
+diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c
+index 2ce8cff..a20bbf4 100644
+--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
++++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
+@@ -188,7 +188,7 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
+ if (send_wr->opcode == IB_WR_SEND_WITH_IMM ||
+ send_wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) {
+ /* this might not work as long as HW does not support it */
+- wqe_p->immediate_data = be32_to_cpu(send_wr->imm_data);
++ wqe_p->immediate_data = be32_to_cpu(send_wr->ex.imm_data);
+ wqe_p->wr_flag |= WQE_WRFLAG_IMM_DATA_PRESENT;
+ }
+
+diff --git a/drivers/infiniband/hw/ehca/ehca_tools.h b/drivers/infiniband/hw/ehca/ehca_tools.h
+index 4a8346a..ec950bf 100644
+--- a/drivers/infiniband/hw/ehca/ehca_tools.h
++++ b/drivers/infiniband/hw/ehca/ehca_tools.h
+@@ -73,37 +73,37 @@ extern int ehca_debug_level;
+ if (unlikely(ehca_debug_level)) \
+ dev_printk(KERN_DEBUG, (ib_dev)->dma_device, \
+ "PU%04x EHCA_DBG:%s " format "\n", \
+- raw_smp_processor_id(), __FUNCTION__, \
++ raw_smp_processor_id(), __func__, \
+ ## arg); \
+ } while (0)
+
+ #define ehca_info(ib_dev, format, arg...) \
+ dev_info((ib_dev)->dma_device, "PU%04x EHCA_INFO:%s " format "\n", \
+- raw_smp_processor_id(), __FUNCTION__, ## arg)
++ raw_smp_processor_id(), __func__, ## arg)
+
+ #define ehca_warn(ib_dev, format, arg...) \
+ dev_warn((ib_dev)->dma_device, "PU%04x EHCA_WARN:%s " format "\n", \
+- raw_smp_processor_id(), __FUNCTION__, ## arg)
++ raw_smp_processor_id(), __func__, ## arg)
+
+ #define ehca_err(ib_dev, format, arg...) \
+ dev_err((ib_dev)->dma_device, "PU%04x EHCA_ERR:%s " format "\n", \
+- raw_smp_processor_id(), __FUNCTION__, ## arg)
++ raw_smp_processor_id(), __func__, ## arg)
+
+ /* use this one only if no ib_dev available */
+ #define ehca_gen_dbg(format, arg...) \
+ do { \
+ if (unlikely(ehca_debug_level)) \
+ printk(KERN_DEBUG "PU%04x EHCA_DBG:%s " format "\n", \
+- raw_smp_processor_id(), __FUNCTION__, ## arg); \
++ raw_smp_processor_id(), __func__, ## arg); \
+ } while (0)
+
+ #define ehca_gen_warn(format, arg...) \
+ printk(KERN_INFO "PU%04x EHCA_WARN:%s " format "\n", \
+- raw_smp_processor_id(), __FUNCTION__, ## arg)
++ raw_smp_processor_id(), __func__, ## arg)
+
+ #define ehca_gen_err(format, arg...) \
+ printk(KERN_ERR "PU%04x EHCA_ERR:%s " format "\n", \
+- raw_smp_processor_id(), __FUNCTION__, ## arg)
++ raw_smp_processor_id(), __func__, ## arg)
+
+ /**
+ * ehca_dmp - printk a memory block, whose length is n*8 bytes.
+@@ -118,7 +118,7 @@ extern int ehca_debug_level;
+ for (x = 0; x < l; x += 16) { \
+ printk(KERN_INFO "EHCA_DMP:%s " format \
+ " adr=%p ofs=%04x %016lx %016lx\n", \
+- __FUNCTION__, ##args, deb, x, \
++ __func__, ##args, deb, x, \
+ *((u64 *)&deb[0]), *((u64 *)&deb[8])); \
+ deb += 16; \
+ } \
+diff --git a/drivers/infiniband/hw/ehca/ehca_uverbs.c b/drivers/infiniband/hw/ehca/ehca_uverbs.c
+index 5234d6c..1b07f2b 100644
+--- a/drivers/infiniband/hw/ehca/ehca_uverbs.c
++++ b/drivers/infiniband/hw/ehca/ehca_uverbs.c
+@@ -40,8 +40,6 @@
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+-#include <asm/current.h>
+-
+ #include "ehca_classes.h"
+ #include "ehca_iverbs.h"
+ #include "ehca_mrmw.h"
+@@ -253,11 +251,9 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
+ u32 idr_handle = fileoffset & 0x1FFFFFF;
+ u32 q_type = (fileoffset >> 27) & 0x1; /* CQ, QP,... */
+ u32 rsrc_type = (fileoffset >> 25) & 0x3; /* sq,rq,cmnd_window */
+- u32 cur_pid = current->tgid;
+ u32 ret;
+ struct ehca_cq *cq;
+ struct ehca_qp *qp;
+- struct ehca_pd *pd;
+ struct ib_uobject *uobject;
+
+ switch (q_type) {
+@@ -270,13 +266,6 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
+ if (!cq)
+ return -EINVAL;
+
+- if (cq->ownpid != cur_pid) {
+- ehca_err(cq->ib_cq.device,
+- "Invalid caller pid=%x ownpid=%x",
+- cur_pid, cq->ownpid);
+- return -ENOMEM;
+- }
+-
+ if (!cq->ib_cq.uobject || cq->ib_cq.uobject->context != context)
+ return -EINVAL;
+
+@@ -298,14 +287,6 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
+ if (!qp)
+ return -EINVAL;
+
+- pd = container_of(qp->ib_qp.pd, struct ehca_pd, ib_pd);
+- if (pd->ownpid != cur_pid) {
+- ehca_err(qp->ib_qp.device,
+- "Invalid caller pid=%x ownpid=%x",
+- cur_pid, pd->ownpid);
+- return -ENOMEM;
+- }
+-
+ uobject = IS_SRQ(qp) ? qp->ib_srq.uobject : qp->ib_qp.uobject;
+ if (!uobject || uobject->context != context)
+ return -EINVAL;
+diff --git a/drivers/infiniband/hw/ipath/Kconfig b/drivers/infiniband/hw/ipath/Kconfig
+index 044da58..3c7968f 100644
+--- a/drivers/infiniband/hw/ipath/Kconfig
++++ b/drivers/infiniband/hw/ipath/Kconfig
+@@ -1,6 +1,6 @@
+ config INFINIBAND_IPATH
+ tristate "QLogic InfiniPath Driver"
+- depends on (PCI_MSI || HT_IRQ) && 64BIT && NET
++ depends on 64BIT && NET
+ ---help---
+ This is a driver for QLogic InfiniPath host channel adapters,
+ including InfiniBand verbs support. This driver allows these
+diff --git a/drivers/infiniband/hw/ipath/Makefile b/drivers/infiniband/hw/ipath/Makefile
+index fe67388..bf94500 100644
+--- a/drivers/infiniband/hw/ipath/Makefile
++++ b/drivers/infiniband/hw/ipath/Makefile
+@@ -20,14 +20,19 @@ ib_ipath-y := \
+ ipath_qp.o \
+ ipath_rc.o \
+ ipath_ruc.o \
++ ipath_sdma.o \
+ ipath_srq.o \
+ ipath_stats.o \
+ ipath_sysfs.o \
+ ipath_uc.o \
+ ipath_ud.o \
+ ipath_user_pages.o \
++ ipath_user_sdma.o \
+ ipath_verbs_mcast.o \
+- ipath_verbs.o
++ ipath_verbs.o \
++ ipath_iba7220.o \
++ ipath_sd7220.o \
++ ipath_sd7220_img.o
+
+ ib_ipath-$(CONFIG_HT_IRQ) += ipath_iba6110.o
+ ib_ipath-$(CONFIG_PCI_MSI) += ipath_iba6120.o
+diff --git a/drivers/infiniband/hw/ipath/ipath_7220.h b/drivers/infiniband/hw/ipath/ipath_7220.h
+new file mode 100644
+index 0000000..74fa5cc
+--- /dev/null
++++ b/drivers/infiniband/hw/ipath/ipath_7220.h
+@@ -0,0 +1,57 @@
++#ifndef _IPATH_7220_H
++#define _IPATH_7220_H
++/*
++ * Copyright (c) 2007 QLogic Corporation. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses. You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ * Redistribution and use in source and binary forms, with or
++ * without modification, are permitted provided that the following
++ * conditions are met:
++ *
++ * - Redistributions of source code must retain the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer.
++ *
++ * - Redistributions in binary form must reproduce the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer in the documentation and/or other materials
++ * provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++/*
++ * This header file provides the declarations and common definitions
++ * for (mostly) manipulation of the SerDes blocks within the IBA7220.
++ * the functions declared should only be called from within other
++ * 7220-related files such as ipath_iba7220.c or ipath_sd7220.c.
++ */
++int ipath_sd7220_presets(struct ipath_devdata *dd);
++int ipath_sd7220_init(struct ipath_devdata *dd, int was_reset);
++int ipath_sd7220_prog_ld(struct ipath_devdata *dd, int sdnum, u8 *img,
++ int len, int offset);
++int ipath_sd7220_prog_vfy(struct ipath_devdata *dd, int sdnum, const u8 *img,
++ int len, int offset);
++/*
++ * Below used for sdnum parameter, selecting one of the two sections
++ * used for PCIe, or the single SerDes used for IB, which is the
++ * only one currently used
++ */
++#define IB_7220_SERDES 2
++
++int ipath_sd7220_ib_load(struct ipath_devdata *dd);
++int ipath_sd7220_ib_vfy(struct ipath_devdata *dd);
++
++#endif /* _IPATH_7220_H */
+diff --git a/drivers/infiniband/hw/ipath/ipath_common.h b/drivers/infiniband/hw/ipath/ipath_common.h
+index 591901a..28cfe97 100644
+--- a/drivers/infiniband/hw/ipath/ipath_common.h
++++ b/drivers/infiniband/hw/ipath/ipath_common.h
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+@@ -80,6 +80,8 @@
+ #define IPATH_IB_LINKDOWN_DISABLE 5
+ #define IPATH_IB_LINK_LOOPBACK 6 /* enable local loopback */
+ #define IPATH_IB_LINK_EXTERNAL 7 /* normal, disable local loopback */
++#define IPATH_IB_LINK_NO_HRTBT 8 /* disable Heartbeat, e.g. for loopback */
++#define IPATH_IB_LINK_HRTBT 9 /* enable heartbeat, normal, non-loopback */
+
+ /*
+ * These 3 values (SDR and DDR may be ORed for auto-speed
+@@ -198,7 +200,8 @@ typedef enum _ipath_ureg {
+ #define IPATH_RUNTIME_FORCE_WC_ORDER 0x4
+ #define IPATH_RUNTIME_RCVHDR_COPY 0x8
+ #define IPATH_RUNTIME_MASTER 0x10
+-/* 0x20 and 0x40 are no longer used, but are reserved for ABI compatibility */
++#define IPATH_RUNTIME_NODMA_RTAIL 0x80
++#define IPATH_RUNTIME_SDMA 0x200
+ #define IPATH_RUNTIME_FORCE_PIOAVAIL 0x400
+ #define IPATH_RUNTIME_PIO_REGSWAPPED 0x800
+
+@@ -444,8 +447,9 @@ struct ipath_user_info {
+ #define IPATH_CMD_PIOAVAILUPD 27 /* force an update of PIOAvail reg */
+ #define IPATH_CMD_POLL_TYPE 28 /* set the kind of polling we want */
+ #define IPATH_CMD_ARMLAUNCH_CTRL 29 /* armlaunch detection control */
+-
+-#define IPATH_CMD_MAX 29
++/* 30 is unused */
++#define IPATH_CMD_SDMA_INFLIGHT 31 /* sdma inflight counter request */
++#define IPATH_CMD_SDMA_COMPLETE 32 /* sdma completion counter request */
+
+ /*
+ * Poll types
+@@ -483,6 +487,17 @@ struct ipath_cmd {
+ union {
+ struct ipath_tid_info tid_info;
+ struct ipath_user_info user_info;
++
++ /*
++ * address in userspace where we should put the sdma
++ * inflight counter
++ */
++ __u64 sdma_inflight;
++ /*
++ * address in userspace where we should put the sdma
++ * completion counter
++ */
++ __u64 sdma_complete;
+ /* address in userspace of struct ipath_port_info to
+ write result to */
+ __u64 port_info;
+@@ -537,7 +552,7 @@ struct ipath_diag_pkt {
+
+ /* The second diag_pkt struct is the expanded version that allows
+ * more control over the packet, specifically, by allowing a custom
+- * pbc (+ extra) qword, so that special modes and deliberate
++ * pbc (+ static rate) qword, so that special modes and deliberate
+ * changes to CRCs can be used. The elements were also re-ordered
+ * for better alignment and to avoid padding issues.
+ */
+@@ -662,8 +677,12 @@ struct infinipath_counters {
+ #define INFINIPATH_RHF_LENGTH_SHIFT 0
+ #define INFINIPATH_RHF_RCVTYPE_MASK 0x7
+ #define INFINIPATH_RHF_RCVTYPE_SHIFT 11
+-#define INFINIPATH_RHF_EGRINDEX_MASK 0x7FF
++#define INFINIPATH_RHF_EGRINDEX_MASK 0xFFF
+ #define INFINIPATH_RHF_EGRINDEX_SHIFT 16
++#define INFINIPATH_RHF_SEQ_MASK 0xF
++#define INFINIPATH_RHF_SEQ_SHIFT 0
++#define INFINIPATH_RHF_HDRQ_OFFSET_MASK 0x7FF
++#define INFINIPATH_RHF_HDRQ_OFFSET_SHIFT 4
+ #define INFINIPATH_RHF_H_ICRCERR 0x80000000
+ #define INFINIPATH_RHF_H_VCRCERR 0x40000000
+ #define INFINIPATH_RHF_H_PARITYERR 0x20000000
+@@ -673,6 +692,8 @@ struct infinipath_counters {
+ #define INFINIPATH_RHF_H_TIDERR 0x02000000
+ #define INFINIPATH_RHF_H_MKERR 0x01000000
+ #define INFINIPATH_RHF_H_IBERR 0x00800000
++#define INFINIPATH_RHF_H_ERR_MASK 0xFF800000
++#define INFINIPATH_RHF_L_USE_EGR 0x80000000
+ #define INFINIPATH_RHF_L_SWA 0x00008000
+ #define INFINIPATH_RHF_L_SWB 0x00004000
+
+@@ -696,6 +717,7 @@ struct infinipath_counters {
+ /* SendPIO per-buffer control */
+ #define INFINIPATH_SP_TEST 0x40
+ #define INFINIPATH_SP_TESTEBP 0x20
++#define INFINIPATH_SP_TRIGGER_SHIFT 15
+
+ /* SendPIOAvail bits */
+ #define INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT 1
+@@ -762,6 +784,7 @@ struct ether_header {
+ #define IPATH_MSN_MASK 0xFFFFFF
+ #define IPATH_QPN_MASK 0xFFFFFF
+ #define IPATH_MULTICAST_LID_BASE 0xC000
++#define IPATH_EAGER_TID_ID INFINIPATH_I_TID_MASK
+ #define IPATH_MULTICAST_QPN 0xFFFFFF
+
+ /* Receive Header Queue: receive type (from infinipath) */
+@@ -781,7 +804,7 @@ struct ether_header {
+ */
+ static inline __u32 ipath_hdrget_err_flags(const __le32 * rbuf)
+ {
+- return __le32_to_cpu(rbuf[1]);
++ return __le32_to_cpu(rbuf[1]) & INFINIPATH_RHF_H_ERR_MASK;
+ }
+
+ static inline __u32 ipath_hdrget_rcv_type(const __le32 * rbuf)
+@@ -802,6 +825,23 @@ static inline __u32 ipath_hdrget_index(const __le32 * rbuf)
+ & INFINIPATH_RHF_EGRINDEX_MASK;
+ }
+
++static inline __u32 ipath_hdrget_seq(const __le32 *rbuf)
++{
++ return (__le32_to_cpu(rbuf[1]) >> INFINIPATH_RHF_SEQ_SHIFT)
++ & INFINIPATH_RHF_SEQ_MASK;
++}
++
++static inline __u32 ipath_hdrget_offset(const __le32 *rbuf)
++{
++ return (__le32_to_cpu(rbuf[1]) >> INFINIPATH_RHF_HDRQ_OFFSET_SHIFT)
++ & INFINIPATH_RHF_HDRQ_OFFSET_MASK;
++}
++
++static inline __u32 ipath_hdrget_use_egr_buf(const __le32 *rbuf)
++{
++ return __le32_to_cpu(rbuf[0]) & INFINIPATH_RHF_L_USE_EGR;
++}
++
+ static inline __u32 ipath_hdrget_ipath_ver(__le32 hdrword)
+ {
+ return (__le32_to_cpu(hdrword) >> INFINIPATH_I_VERS_SHIFT)
+diff --git a/drivers/infiniband/hw/ipath/ipath_debug.h b/drivers/infiniband/hw/ipath/ipath_debug.h
+index d6f6953..65926cd 100644
+--- a/drivers/infiniband/hw/ipath/ipath_debug.h
++++ b/drivers/infiniband/hw/ipath/ipath_debug.h
+@@ -66,6 +66,7 @@
+ #define __IPATH_IPATHERR 0x40000 /* Ethernet (IPATH) errors */
+ #define __IPATH_IPATHPD 0x80000 /* Ethernet (IPATH) packet dump */
+ #define __IPATH_IPATHTABLE 0x100000 /* Ethernet (IPATH) table dump */
++#define __IPATH_LINKVERBDBG 0x200000 /* very verbose linkchange debug */
+
+ #else /* _IPATH_DEBUGGING */
+
+@@ -89,6 +90,7 @@
+ #define __IPATH_IPATHERR 0x0 /* Ethernet (IPATH) errors on */
+ #define __IPATH_IPATHPD 0x0 /* Ethernet (IPATH) packet dump on */
+ #define __IPATH_IPATHTABLE 0x0 /* Ethernet (IPATH) packet dump on */
++#define __IPATH_LINKVERBDBG 0x0 /* very verbose linkchange debug */
+
+ #endif /* _IPATH_DEBUGGING */
+
+diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c
+index 4137c77..d4ce8b6 100644
+--- a/drivers/infiniband/hw/ipath/ipath_diag.c
++++ b/drivers/infiniband/hw/ipath/ipath_diag.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+@@ -79,7 +79,7 @@ static const struct file_operations diagpkt_file_ops = {
+
+ static atomic_t diagpkt_count = ATOMIC_INIT(0);
+ static struct cdev *diagpkt_cdev;
+-static struct class_device *diagpkt_class_dev;
++static struct device *diagpkt_dev;
+
+ int ipath_diag_add(struct ipath_devdata *dd)
+ {
+@@ -89,7 +89,7 @@ int ipath_diag_add(struct ipath_devdata *dd)
+ if (atomic_inc_return(&diagpkt_count) == 1) {
+ ret = ipath_cdev_init(IPATH_DIAGPKT_MINOR,
+ "ipath_diagpkt", &diagpkt_file_ops,
+- &diagpkt_cdev, &diagpkt_class_dev);
++ &diagpkt_cdev, &diagpkt_dev);
+
+ if (ret) {
+ ipath_dev_err(dd, "Couldn't create ipath_diagpkt "
+@@ -102,7 +102,7 @@ int ipath_diag_add(struct ipath_devdata *dd)
+
+ ret = ipath_cdev_init(IPATH_DIAG_MINOR_BASE + dd->ipath_unit, name,
+ &diag_file_ops, &dd->diag_cdev,
+- &dd->diag_class_dev);
++ &dd->diag_dev);
+ if (ret)
+ ipath_dev_err(dd, "Couldn't create %s device: %d",
+ name, ret);
+@@ -114,9 +114,9 @@ done:
+ void ipath_diag_remove(struct ipath_devdata *dd)
+ {
+ if (atomic_dec_and_test(&diagpkt_count))
+- ipath_cdev_cleanup(&diagpkt_cdev, &diagpkt_class_dev);
++ ipath_cdev_cleanup(&diagpkt_cdev, &diagpkt_dev);
+
+- ipath_cdev_cleanup(&dd->diag_cdev, &dd->diag_class_dev);
++ ipath_cdev_cleanup(&dd->diag_cdev, &dd->diag_dev);
+ }
+
+ /**
+@@ -330,13 +330,19 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
+ struct ipath_devdata *dd;
+ ssize_t ret = 0;
+ u64 val;
++ u32 l_state, lt_state; /* LinkState, LinkTrainingState */
+
+- if (count != sizeof(dp)) {
++ if (count < sizeof(odp)) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+- if (copy_from_user(&dp, data, sizeof(dp))) {
++ if (count == sizeof(dp)) {
++ if (copy_from_user(&dp, data, sizeof(dp))) {
++ ret = -EFAULT;
++ goto bail;
++ }
++ } else if (copy_from_user(&odp, data, sizeof(odp))) {
+ ret = -EFAULT;
+ goto bail;
+ }
+@@ -396,10 +402,17 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
+ ret = -ENODEV;
+ goto bail;
+ }
+- /* Check link state, but not if we have custom PBC */
+- val = dd->ipath_lastibcstat & IPATH_IBSTATE_MASK;
+- if (!dp.pbc_wd && val != IPATH_IBSTATE_INIT &&
+- val != IPATH_IBSTATE_ARM && val != IPATH_IBSTATE_ACTIVE) {
++ /*
++ * Want to skip check for l_state if using custom PBC,
++ * because we might be trying to force an SM packet out.
++ * first-cut, skip _all_ state checking in that case.
++ */
++ val = ipath_ib_state(dd, dd->ipath_lastibcstat);
++ lt_state = ipath_ib_linktrstate(dd, dd->ipath_lastibcstat);
++ l_state = ipath_ib_linkstate(dd, dd->ipath_lastibcstat);
++ if (!dp.pbc_wd && (lt_state != INFINIPATH_IBCS_LT_STATE_LINKUP ||
++ (val != dd->ib_init && val != dd->ib_arm &&
++ val != dd->ib_active))) {
+ ipath_cdbg(VERBOSE, "unit %u not ready (state %llx)\n",
+ dd->ipath_unit, (unsigned long long) val);
+ ret = -EINVAL;
+@@ -431,15 +444,17 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
+ goto bail;
+ }
+
+- piobuf = ipath_getpiobuf(dd, &pbufn);
++ plen >>= 2; /* in dwords */
++
++ piobuf = ipath_getpiobuf(dd, plen, &pbufn);
+ if (!piobuf) {
+ ipath_cdbg(VERBOSE, "No PIO buffers avail unit for %u\n",
+ dd->ipath_unit);
+ ret = -EBUSY;
+ goto bail;
+ }
+-
+- plen >>= 2; /* in dwords */
++ /* disarm it just to be extra sure */
++ ipath_disarm_piobufs(dd, pbufn, 1);
+
+ if (ipath_debug & __IPATH_PKTDBG)
+ ipath_cdbg(VERBOSE, "unit %u 0x%x+1w pio%d\n",
+diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
+index ca4d0ac..acf30c0 100644
+--- a/drivers/infiniband/hw/ipath/ipath_driver.c
++++ b/drivers/infiniband/hw/ipath/ipath_driver.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+@@ -41,7 +41,6 @@
+
+ #include "ipath_kernel.h"
+ #include "ipath_verbs.h"
+-#include "ipath_common.h"
+
+ static void ipath_update_pio_bufs(struct ipath_devdata *);
+
+@@ -73,10 +72,27 @@ module_param_named(debug, ipath_debug, uint, S_IWUSR | S_IRUGO);
+ MODULE_PARM_DESC(debug, "mask for debug prints");
+ EXPORT_SYMBOL_GPL(ipath_debug);
+
++unsigned ipath_mtu4096 = 1; /* max 4KB IB mtu by default, if supported */
++module_param_named(mtu4096, ipath_mtu4096, uint, S_IRUGO);
++MODULE_PARM_DESC(mtu4096, "enable MTU of 4096 bytes, if supported");
++
++static unsigned ipath_hol_timeout_ms = 13000;
++module_param_named(hol_timeout_ms, ipath_hol_timeout_ms, uint, S_IRUGO);
++MODULE_PARM_DESC(hol_timeout_ms,
++ "duration of user app suspension after link failure");
++
++unsigned ipath_linkrecovery = 1;
++module_param_named(linkrecovery, ipath_linkrecovery, uint, S_IWUSR | S_IRUGO);
++MODULE_PARM_DESC(linkrecovery, "enable workaround for link recovery issue");
++
+ MODULE_LICENSE("GPL");
+-MODULE_AUTHOR("QLogic <support at pathscale.com>");
++MODULE_AUTHOR("QLogic <support at qlogic.com>");
+ MODULE_DESCRIPTION("QLogic InfiniPath driver");
+
++/*
++ * Table to translate the LINKTRAININGSTATE portion of
++ * IBCStatus to a human-readable form.
++ */
+ const char *ipath_ibcstatus_str[] = {
+ "Disabled",
+ "LinkUp",
+@@ -91,9 +107,20 @@ const char *ipath_ibcstatus_str[] = {
+ "CfgWaitRmt",
+ "CfgIdle",
+ "RecovRetrain",
+- "LState0xD", /* unused */
++ "CfgTxRevLane", /* unused before IBA7220 */
+ "RecovWaitRmt",
+ "RecovIdle",
++ /* below were added for IBA7220 */
++ "CfgEnhanced",
++ "CfgTest",
++ "CfgWaitRmtTest",
++ "CfgWaitCfgEnhanced",
++ "SendTS_T",
++ "SendTstIdles",
++ "RcvTS_T",
++ "SendTst_TS1s",
++ "LTState18", "LTState19", "LTState1A", "LTState1B",
++ "LTState1C", "LTState1D", "LTState1E", "LTState1F"
+ };
+
+ static void __devexit ipath_remove_one(struct pci_dev *);
+@@ -102,8 +129,10 @@ static int __devinit ipath_init_one(struct pci_dev *,
+
+ /* Only needed for registration, nothing else needs this info */
+ #define PCI_VENDOR_ID_PATHSCALE 0x1fc1
++#define PCI_VENDOR_ID_QLOGIC 0x1077
+ #define PCI_DEVICE_ID_INFINIPATH_HT 0xd
+ #define PCI_DEVICE_ID_INFINIPATH_PE800 0x10
++#define PCI_DEVICE_ID_INFINIPATH_7220 0x7220
+
+ /* Number of seconds before our card status check... */
+ #define STATUS_TIMEOUT 60
+@@ -111,6 +140,7 @@ static int __devinit ipath_init_one(struct pci_dev *,
+ static const struct pci_device_id ipath_pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_INFINIPATH_HT) },
+ { PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_INFINIPATH_PE800) },
++ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_INFINIPATH_7220) },
+ { 0, }
+ };
+
+@@ -126,19 +156,6 @@ static struct pci_driver ipath_driver = {
+ },
+ };
+
+-static void ipath_check_status(struct work_struct *work)
+-{
+- struct ipath_devdata *dd = container_of(work, struct ipath_devdata,
+- status_work.work);
+-
+- /*
+- * If we don't have any interrupts, let the user know and
+- * don't bother checking again.
+- */
+- if (dd->ipath_int_counter == 0)
+- dev_err(&dd->pcidev->dev, "No interrupts detected.\n");
+-}
+-
+ static inline void read_bars(struct ipath_devdata *dd, struct pci_dev *dev,
+ u32 *bar0, u32 *bar1)
+ {
+@@ -206,8 +223,6 @@ static struct ipath_devdata *ipath_alloc_devdata(struct pci_dev *pdev)
+ dd->pcidev = pdev;
+ pci_set_drvdata(pdev, dd);
+
+- INIT_DELAYED_WORK(&dd->status_work, ipath_check_status);
+-
+ list_add(&dd->ipath_list, &ipath_dev_list);
+
+ bail_unlock:
+@@ -234,12 +249,12 @@ struct ipath_devdata *ipath_lookup(int unit)
+ return dd;
+ }
+
+-int ipath_count_units(int *npresentp, int *nupp, u32 *maxportsp)
++int ipath_count_units(int *npresentp, int *nupp, int *maxportsp)
+ {
+ int nunits, npresent, nup;
+ struct ipath_devdata *dd;
+ unsigned long flags;
+- u32 maxports;
++ int maxports;
+
+ nunits = npresent = nup = maxports = 0;
+
+@@ -304,7 +319,7 @@ static void ipath_verify_pioperf(struct ipath_devdata *dd)
+ u32 *addr;
+ u64 msecs, emsecs;
+
+- piobuf = ipath_getpiobuf(dd, &pbnum);
++ piobuf = ipath_getpiobuf(dd, 0, &pbnum);
+ if (!piobuf) {
+ dev_info(&dd->pcidev->dev,
+ "No PIObufs for checking perf, skipping\n");
+@@ -336,7 +351,14 @@ static void ipath_verify_pioperf(struct ipath_devdata *dd)
+
+ ipath_disable_armlaunch(dd);
+
+- writeq(0, piobuf); /* length 0, no dwords actually sent */
++ /*
++ * length 0, no dwords actually sent, and mark as VL15
++ * on chips where that may matter (due to IB flowcontrol)
++ */
++ if ((dd->ipath_flags & IPATH_HAS_PBC_CNT))
++ writeq(1UL << 63, piobuf);
++ else
++ writeq(0, piobuf);
+ ipath_flush_wc();
+
+ /*
+@@ -377,6 +399,7 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
+ struct ipath_devdata *dd;
+ unsigned long long addr;
+ u32 bar0 = 0, bar1 = 0;
++ u8 rev;
+
+ dd = ipath_alloc_devdata(pdev);
+ if (IS_ERR(dd)) {
+@@ -408,7 +431,7 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
+ }
+ addr = pci_resource_start(pdev, 0);
+ len = pci_resource_len(pdev, 0);
+- ipath_cdbg(VERBOSE, "regbase (0) %llx len %d pdev->irq %d, vend %x/%x "
++ ipath_cdbg(VERBOSE, "regbase (0) %llx len %d irq %d, vend %x/%x "
+ "driver_data %lx\n", addr, len, pdev->irq, ent->vendor,
+ ent->device, ent->driver_data);
+
+@@ -512,6 +535,13 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
+ "CONFIG_PCI_MSI is not enabled\n", ent->device);
+ return -ENODEV;
+ #endif
++ case PCI_DEVICE_ID_INFINIPATH_7220:
++#ifndef CONFIG_PCI_MSI
++ ipath_dbg("CONFIG_PCI_MSI is not enabled, "
++ "using INTx for unit %u\n", dd->ipath_unit);
++#endif
++ ipath_init_iba7220_funcs(dd);
++ break;
+ default:
+ ipath_dev_err(dd, "Found unknown QLogic deviceid 0x%x, "
+ "failing\n", ent->device);
+@@ -533,7 +563,13 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
+ goto bail_regions;
+ }
+
+- dd->ipath_pcirev = pdev->revision;
++ ret = pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
++ if (ret) {
++ ipath_dev_err(dd, "Failed to read PCI revision ID unit "
++ "%u: err %d\n", dd->ipath_unit, -ret);
++ goto bail_regions; /* shouldn't ever happen */
++ }
++ dd->ipath_pcirev = rev;
+
+ #if defined(__powerpc__)
+ /* There isn't a generic way to specify writethrough mappings */
+@@ -556,14 +592,6 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
+ ipath_cdbg(VERBOSE, "mapped io addr %llx to kregbase %p\n",
+ addr, dd->ipath_kregbase);
+
+- /*
+- * clear ipath_flags here instead of in ipath_init_chip as it is set
+- * by ipath_setup_htconfig.
+- */
+- dd->ipath_flags = 0;
+- dd->ipath_lli_counter = 0;
+- dd->ipath_lli_errors = 0;
+-
+ if (dd->ipath_f_bus(dd, pdev))
+ ipath_dev_err(dd, "Failed to setup config space; "
+ "continuing anyway\n");
+@@ -608,13 +636,11 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
+ ipath_diag_add(dd);
+ ipath_register_ib_device(dd);
+
+- /* Check that card status in STATUS_TIMEOUT seconds. */
+- schedule_delayed_work(&dd->status_work, HZ * STATUS_TIMEOUT);
+-
+ goto bail;
+
+ bail_irqsetup:
+- if (pdev->irq) free_irq(pdev->irq, dd);
++ if (pdev->irq)
++ free_irq(pdev->irq, dd);
+
+ bail_iounmap:
+ iounmap((volatile void __iomem *) dd->ipath_kregbase);
+@@ -654,6 +680,10 @@ static void __devexit cleanup_device(struct ipath_devdata *dd)
+ ipath_disable_wc(dd);
+ }
+
++ if (dd->ipath_spectriggerhit)
++ dev_info(&dd->pcidev->dev, "%lu special trigger hits\n",
++ dd->ipath_spectriggerhit);
++
+ if (dd->ipath_pioavailregs_dma) {
+ dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE,
+ (void *) dd->ipath_pioavailregs_dma,
+@@ -706,6 +736,8 @@ static void __devexit cleanup_device(struct ipath_devdata *dd)
+ tmpp = dd->ipath_pageshadow;
+ dd->ipath_pageshadow = NULL;
+ vfree(tmpp);
++
++ dd->ipath_egrtidbase = NULL;
+ }
+
+ /*
+@@ -738,7 +770,6 @@ static void __devexit ipath_remove_one(struct pci_dev *pdev)
+ */
+ ipath_shutdown_device(dd);
+
+- cancel_delayed_work(&dd->status_work);
+ flush_scheduled_work();
+
+ if (dd->verbs_dev)
+@@ -823,20 +854,8 @@ void ipath_disarm_piobufs(struct ipath_devdata *dd, unsigned first,
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
+ }
+-
+- /*
+- * Disable PIOAVAILUPD, then re-enable, reading scratch in
+- * between. This seems to avoid a chip timing race that causes
+- * pioavail updates to memory to stop. We xor as we don't
+- * know the state of the bit when we're called.
+- */
+- spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
+- ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+- dd->ipath_sendctrl ^ INFINIPATH_S_PIOBUFAVAILUPD);
+- ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+- ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+- dd->ipath_sendctrl);
+- spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++ /* on some older chips, update may not happen after cancel */
++ ipath_force_pio_avail_update(dd);
+ }
+
+ /**
+@@ -873,18 +892,52 @@ int ipath_wait_linkstate(struct ipath_devdata *dd, u32 state, int msecs)
+ (unsigned long long) ipath_read_kreg64(
+ dd, dd->ipath_kregs->kr_ibcctrl),
+ (unsigned long long) val,
+- ipath_ibcstatus_str[val & 0xf]);
++ ipath_ibcstatus_str[val & dd->ibcs_lts_mask]);
+ }
+ return (dd->ipath_flags & state) ? 0 : -ETIMEDOUT;
+ }
+
++static void decode_sdma_errs(struct ipath_devdata *dd, ipath_err_t err,
++ char *buf, size_t blen)
++{
++ static const struct {
++ ipath_err_t err;
++ const char *msg;
++ } errs[] = {
++ { INFINIPATH_E_SDMAGENMISMATCH, "SDmaGenMismatch" },
++ { INFINIPATH_E_SDMAOUTOFBOUND, "SDmaOutOfBound" },
++ { INFINIPATH_E_SDMATAILOUTOFBOUND, "SDmaTailOutOfBound" },
++ { INFINIPATH_E_SDMABASE, "SDmaBase" },
++ { INFINIPATH_E_SDMA1STDESC, "SDma1stDesc" },
++ { INFINIPATH_E_SDMARPYTAG, "SDmaRpyTag" },
++ { INFINIPATH_E_SDMADWEN, "SDmaDwEn" },
++ { INFINIPATH_E_SDMAMISSINGDW, "SDmaMissingDw" },
++ { INFINIPATH_E_SDMAUNEXPDATA, "SDmaUnexpData" },
++ { INFINIPATH_E_SDMADESCADDRMISALIGN, "SDmaDescAddrMisalign" },
++ { INFINIPATH_E_SENDBUFMISUSE, "SendBufMisuse" },
++ { INFINIPATH_E_SDMADISABLED, "SDmaDisabled" },
++ };
++ int i;
++ int expected;
++ size_t bidx = 0;
++
++ for (i = 0; i < ARRAY_SIZE(errs); i++) {
++ expected = (errs[i].err != INFINIPATH_E_SDMADISABLED) ? 0 :
++ test_bit(IPATH_SDMA_ABORTING, &dd->ipath_sdma_status);
++ if ((err & errs[i].err) && !expected)
++ bidx += snprintf(buf + bidx, blen - bidx,
++ "%s ", errs[i].msg);
++ }
++}
++
+ /*
+ * Decode the error status into strings, deciding whether to always
+ * print * it or not depending on "normal packet errors" vs everything
+ * else. Return 1 if "real" errors, otherwise 0 if only packet
+ * errors, so caller can decide what to print with the string.
+ */
+-int ipath_decode_err(char *buf, size_t blen, ipath_err_t err)
++int ipath_decode_err(struct ipath_devdata *dd, char *buf, size_t blen,
++ ipath_err_t err)
+ {
+ int iserr = 1;
+ *buf = '\0';
+@@ -922,6 +975,8 @@ int ipath_decode_err(char *buf, size_t blen, ipath_err_t err)
+ strlcat(buf, "rbadversion ", blen);
+ if (err & INFINIPATH_E_RHDR)
+ strlcat(buf, "rhdr ", blen);
++ if (err & INFINIPATH_E_SENDSPECIALTRIGGER)
++ strlcat(buf, "sendspecialtrigger ", blen);
+ if (err & INFINIPATH_E_RLONGPKTLEN)
+ strlcat(buf, "rlongpktlen ", blen);
+ if (err & INFINIPATH_E_RMAXPKTLEN)
+@@ -964,6 +1019,10 @@ int ipath_decode_err(char *buf, size_t blen, ipath_err_t err)
+ strlcat(buf, "hardware ", blen);
+ if (err & INFINIPATH_E_RESET)
+ strlcat(buf, "reset ", blen);
++ if (err & INFINIPATH_E_SDMAERRS)
++ decode_sdma_errs(dd, err, buf, blen);
++ if (err & INFINIPATH_E_INVALIDEEPCMD)
++ strlcat(buf, "invalideepromcmd ", blen);
+ done:
+ return iserr;
+ }
+@@ -1076,18 +1135,17 @@ static void ipath_rcv_hdrerr(struct ipath_devdata *dd,
+ u32 eflags,
+ u32 l,
+ u32 etail,
+- u64 *rc)
++ __le32 *rhf_addr,
++ struct ipath_message_header *hdr)
+ {
+ char emsg[128];
+- struct ipath_message_header *hdr;
+
+ get_rhf_errstring(eflags, emsg, sizeof emsg);
+- hdr = (struct ipath_message_header *)&rc[1];
+ ipath_cdbg(PKT, "RHFerrs %x hdrqtail=%x typ=%u "
+ "tlen=%x opcode=%x egridx=%x: %s\n",
+ eflags, l,
+- ipath_hdrget_rcv_type((__le32 *) rc),
+- ipath_hdrget_length_in_bytes((__le32 *) rc),
++ ipath_hdrget_rcv_type(rhf_addr),
++ ipath_hdrget_length_in_bytes(rhf_addr),
+ be32_to_cpu(hdr->bth[0]) >> 24,
+ etail, emsg);
+
+@@ -1112,55 +1170,52 @@ static void ipath_rcv_hdrerr(struct ipath_devdata *dd,
+ */
+ void ipath_kreceive(struct ipath_portdata *pd)
+ {
+- u64 *rc;
+ struct ipath_devdata *dd = pd->port_dd;
++ __le32 *rhf_addr;
+ void *ebuf;
+ const u32 rsize = dd->ipath_rcvhdrentsize; /* words */
+ const u32 maxcnt = dd->ipath_rcvhdrcnt * rsize; /* words */
+ u32 etail = -1, l, hdrqtail;
+ struct ipath_message_header *hdr;
+- u32 eflags, i, etype, tlen, pkttot = 0, updegr=0, reloop=0;
++ u32 eflags, i, etype, tlen, pkttot = 0, updegr = 0, reloop = 0;
+ static u64 totcalls; /* stats, may eventually remove */
+-
+- if (!dd->ipath_hdrqtailptr) {
+- ipath_dev_err(dd,
+- "hdrqtailptr not set, can't do receives\n");
+- goto bail;
+- }
++ int last;
+
+ l = pd->port_head;
+- hdrqtail = ipath_get_rcvhdrtail(pd);
+- if (l == hdrqtail)
+- goto bail;
+-
+-reloop:
+- for (i = 0; l != hdrqtail; i++) {
+- u32 qp;
+- u8 *bthbytes;
++ rhf_addr = (__le32 *) pd->port_rcvhdrq + l + dd->ipath_rhf_offset;
++ if (dd->ipath_flags & IPATH_NODMA_RTAIL) {
++ u32 seq = ipath_hdrget_seq(rhf_addr);
+
+- rc = (u64 *) (pd->port_rcvhdrq + (l << 2));
+- hdr = (struct ipath_message_header *)&rc[1];
+- /*
+- * could make a network order version of IPATH_KD_QP, and
+- * do the obvious shift before masking to speed this up.
+- */
+- qp = ntohl(hdr->bth[1]) & 0xffffff;
+- bthbytes = (u8 *) hdr->bth;
++ if (seq != pd->port_seq_cnt)
++ goto bail;
++ hdrqtail = 0;
++ } else {
++ hdrqtail = ipath_get_rcvhdrtail(pd);
++ if (l == hdrqtail)
++ goto bail;
++ smp_rmb();
++ }
+
+- eflags = ipath_hdrget_err_flags((__le32 *) rc);
+- etype = ipath_hdrget_rcv_type((__le32 *) rc);
++reloop:
++ for (last = 0, i = 1; !last; i++) {
++ hdr = dd->ipath_f_get_msgheader(dd, rhf_addr);
++ eflags = ipath_hdrget_err_flags(rhf_addr);
++ etype = ipath_hdrget_rcv_type(rhf_addr);
+ /* total length */
+- tlen = ipath_hdrget_length_in_bytes((__le32 *) rc);
++ tlen = ipath_hdrget_length_in_bytes(rhf_addr);
+ ebuf = NULL;
+- if (etype != RCVHQ_RCV_TYPE_EXPECTED) {
++ if ((dd->ipath_flags & IPATH_NODMA_RTAIL) ?
++ ipath_hdrget_use_egr_buf(rhf_addr) :
++ (etype != RCVHQ_RCV_TYPE_EXPECTED)) {
+ /*
+- * it turns out that the chips uses an eager buffer
++ * It turns out that the chip uses an eager buffer
+ * for all non-expected packets, whether it "needs"
+ * one or not. So always get the index, but don't
+ * set ebuf (so we try to copy data) unless the
+ * length requires it.
+ */
+- etail = ipath_hdrget_index((__le32 *) rc);
++ etail = ipath_hdrget_index(rhf_addr);
++ updegr = 1;
+ if (tlen > sizeof(*hdr) ||
+ etype == RCVHQ_RCV_TYPE_NON_KD)
+ ebuf = ipath_get_egrbuf(dd, etail);
+@@ -1171,75 +1226,91 @@ reloop:
+ * packets; only ipathhdrerr should be set.
+ */
+
+- if (etype != RCVHQ_RCV_TYPE_NON_KD && etype !=
+- RCVHQ_RCV_TYPE_ERROR && ipath_hdrget_ipath_ver(
+- hdr->iph.ver_port_tid_offset) !=
+- IPS_PROTO_VERSION) {
++ if (etype != RCVHQ_RCV_TYPE_NON_KD &&
++ etype != RCVHQ_RCV_TYPE_ERROR &&
++ ipath_hdrget_ipath_ver(hdr->iph.ver_port_tid_offset) !=
++ IPS_PROTO_VERSION)
+ ipath_cdbg(PKT, "Bad InfiniPath protocol version "
+ "%x\n", etype);
+- }
+
+ if (unlikely(eflags))
+- ipath_rcv_hdrerr(dd, eflags, l, etail, rc);
++ ipath_rcv_hdrerr(dd, eflags, l, etail, rhf_addr, hdr);
+ else if (etype == RCVHQ_RCV_TYPE_NON_KD) {
+- ipath_ib_rcv(dd->verbs_dev, rc + 1, ebuf, tlen);
++ ipath_ib_rcv(dd->verbs_dev, (u32 *)hdr, ebuf, tlen);
+ if (dd->ipath_lli_counter)
+ dd->ipath_lli_counter--;
++ } else if (etype == RCVHQ_RCV_TYPE_EAGER) {
++ u8 opcode = be32_to_cpu(hdr->bth[0]) >> 24;
++ u32 qp = be32_to_cpu(hdr->bth[1]) & 0xffffff;
+ ipath_cdbg(PKT, "typ %x, opcode %x (eager, "
+ "qp=%x), len %x; ignored\n",
+- etype, bthbytes[0], qp, tlen);
++ etype, opcode, qp, tlen);
+ }
+- else if (etype == RCVHQ_RCV_TYPE_EAGER)
+- ipath_cdbg(PKT, "typ %x, opcode %x (eager, "
+- "qp=%x), len %x; ignored\n",
+- etype, bthbytes[0], qp, tlen);
+ else if (etype == RCVHQ_RCV_TYPE_EXPECTED)
+ ipath_dbg("Bug: Expected TID, opcode %x; ignored\n",
+- be32_to_cpu(hdr->bth[0]) & 0xff);
++ be32_to_cpu(hdr->bth[0]) >> 24);
+ else {
+ /*
+ * error packet, type of error unknown.
+ * Probably type 3, but we don't know, so don't
+ * even try to print the opcode, etc.
++ * Usually caused by a "bad packet", that has no
++ * BTH, when the LRH says it should.
+ */
+- ipath_dbg("Error Pkt, but no eflags! egrbuf %x, "
+- "len %x\nhdrq@%lx;hdrq+%x rhf: %llx; "
+- "hdr %llx %llx %llx %llx %llx\n",
+- etail, tlen, (unsigned long) rc, l,
+- (unsigned long long) rc[0],
+- (unsigned long long) rc[1],
+- (unsigned long long) rc[2],
+- (unsigned long long) rc[3],
+- (unsigned long long) rc[4],
+- (unsigned long long) rc[5]);
++ ipath_cdbg(ERRPKT, "Error Pkt, but no eflags! egrbuf"
++ " %x, len %x hdrq+%x rhf: %Lx\n",
++ etail, tlen, l,
++ le64_to_cpu(*(__le64 *) rhf_addr));
++ if (ipath_debug & __IPATH_ERRPKTDBG) {
++ u32 j, *d, dw = rsize-2;
++ if (rsize > (tlen>>2))
++ dw = tlen>>2;
++ d = (u32 *)hdr;
++ printk(KERN_DEBUG "EPkt rcvhdr(%x dw):\n",
++ dw);
++ for (j = 0; j < dw; j++)
++ printk(KERN_DEBUG "%8x%s", d[j],
++ (j%8) == 7 ? "\n" : " ");
++ printk(KERN_DEBUG ".\n");
++ }
+ }
+ l += rsize;
+ if (l >= maxcnt)
+ l = 0;
+- if (etype != RCVHQ_RCV_TYPE_EXPECTED)
+- updegr = 1;
++ rhf_addr = (__le32 *) pd->port_rcvhdrq +
++ l + dd->ipath_rhf_offset;
++ if (dd->ipath_flags & IPATH_NODMA_RTAIL) {
++ u32 seq = ipath_hdrget_seq(rhf_addr);
++
++ if (++pd->port_seq_cnt > 13)
++ pd->port_seq_cnt = 1;
++ if (seq != pd->port_seq_cnt)
++ last = 1;
++ } else if (l == hdrqtail)
++ last = 1;
+ /*
+ * update head regs on last packet, and every 16 packets.
+ * Reduce bus traffic, while still trying to prevent
+ * rcvhdrq overflows, for when the queue is nearly full
+ */
+- if (l == hdrqtail || (i && !(i&0xf))) {
+- u64 lval;
+- if (l == hdrqtail)
+- /* request IBA6120 interrupt only on last */
+- lval = dd->ipath_rhdrhead_intr_off | l;
+- else
+- lval = l;
+- (void)ipath_write_ureg(dd, ur_rcvhdrhead, lval, 0);
++ if (last || !(i & 0xf)) {
++ u64 lval = l;
++
++ /* request IBA6120 and 7220 interrupt only on last */
++ if (last)
++ lval |= dd->ipath_rhdrhead_intr_off;
++ ipath_write_ureg(dd, ur_rcvhdrhead, lval,
++ pd->port_port);
+ if (updegr) {
+- (void)ipath_write_ureg(dd, ur_rcvegrindexhead,
+- etail, 0);
++ ipath_write_ureg(dd, ur_rcvegrindexhead,
++ etail, pd->port_port);
+ updegr = 0;
+ }
+ }
+ }
+
+- if (!dd->ipath_rhdrhead_intr_off && !reloop) {
++ if (!dd->ipath_rhdrhead_intr_off && !reloop &&
++ !(dd->ipath_flags & IPATH_NODMA_RTAIL)) {
+ /* IBA6110 workaround; we can have a race clearing chip
+ * interrupt with another interrupt about to be delivered,
+ * and can clear it before it is delivered on the GPIO
+@@ -1301,7 +1372,6 @@ static void ipath_update_pio_bufs(struct ipath_devdata *dd)
+ * happens when all buffers are in use, so only cpu overhead, not
+ * latency or bandwidth is affected.
+ */
+-#define _IPATH_ALL_CHECKBITS 0x5555555555555555ULL
+ if (!dd->ipath_pioavailregs_dma) {
+ ipath_dbg("Update shadow pioavail, but regs_dma NULL!\n");
+ return;
+@@ -1346,7 +1416,7 @@ static void ipath_update_pio_bufs(struct ipath_devdata *dd)
+ piov = le64_to_cpu(dd->ipath_pioavailregs_dma[i ^ 1]);
+ else
+ piov = le64_to_cpu(dd->ipath_pioavailregs_dma[i]);
+- pchg = _IPATH_ALL_CHECKBITS &
++ pchg = dd->ipath_pioavailkernel[i] &
+ ~(dd->ipath_pioavailshadow[i] ^ piov);
+ pchbusy = pchg << INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT;
+ if (pchg && (pchbusy & dd->ipath_pioavailshadow[i])) {
+@@ -1397,27 +1467,63 @@ int ipath_setrcvhdrsize(struct ipath_devdata *dd, unsigned rhdrsize)
+ return ret;
+ }
+
+-/**
+- * ipath_getpiobuf - find an available pio buffer
+- * @dd: the infinipath device
+- * @pbufnum: the buffer number is placed here
++/*
++ * debugging code and stats updates if no pio buffers available.
++ */
++static noinline void no_pio_bufs(struct ipath_devdata *dd)
++{
++ unsigned long *shadow = dd->ipath_pioavailshadow;
++ __le64 *dma = (__le64 *)dd->ipath_pioavailregs_dma;
++
++ dd->ipath_upd_pio_shadow = 1;
++
++ /*
++ * not atomic, but if we lose a stat count in a while, that's OK
++ */
++ ipath_stats.sps_nopiobufs++;
++ if (!(++dd->ipath_consec_nopiobuf % 100000)) {
++ ipath_dbg("%u pio sends with no bufavail; dmacopy: "
++ "%llx %llx %llx %llx; shadow: %lx %lx %lx %lx\n",
++ dd->ipath_consec_nopiobuf,
++ (unsigned long long) le64_to_cpu(dma[0]),
++ (unsigned long long) le64_to_cpu(dma[1]),
++ (unsigned long long) le64_to_cpu(dma[2]),
++ (unsigned long long) le64_to_cpu(dma[3]),
++ shadow[0], shadow[1], shadow[2], shadow[3]);
++ /*
++ * 4 buffers per byte, 4 registers above, cover rest
++ * below
++ */
++ if ((dd->ipath_piobcnt2k + dd->ipath_piobcnt4k) >
++ (sizeof(shadow[0]) * 4 * 4))
++ ipath_dbg("2nd group: dmacopy: %llx %llx "
++ "%llx %llx; shadow: %lx %lx %lx %lx\n",
++ (unsigned long long)le64_to_cpu(dma[4]),
++ (unsigned long long)le64_to_cpu(dma[5]),
++ (unsigned long long)le64_to_cpu(dma[6]),
++ (unsigned long long)le64_to_cpu(dma[7]),
++ shadow[4], shadow[5], shadow[6],
++ shadow[7]);
++ }
++}
++
++/*
++ * common code for normal driver pio buffer allocation, and reserved
++ * allocation.
+ *
+ * do appropriate marking as busy, etc.
+ * returns buffer number if one found (>=0), negative number is error.
+- * Used by ipath_layer_send
+ */
+-u32 __iomem *ipath_getpiobuf(struct ipath_devdata *dd, u32 * pbufnum)
++static u32 __iomem *ipath_getpiobuf_range(struct ipath_devdata *dd,
++ u32 *pbufnum, u32 first, u32 last, u32 firsti)
+ {
+- int i, j, starti, updated = 0;
+- unsigned piobcnt, iter;
++ int i, j, updated = 0;
++ unsigned piobcnt;
+ unsigned long flags;
+ unsigned long *shadow = dd->ipath_pioavailshadow;
+ u32 __iomem *buf;
+
+- piobcnt = (unsigned)(dd->ipath_piobcnt2k
+- + dd->ipath_piobcnt4k);
+- starti = dd->ipath_lastport_piobuf;
+- iter = piobcnt - starti;
++ piobcnt = last - first;
+ if (dd->ipath_upd_pio_shadow) {
+ /*
+ * Minor optimization. If we had no buffers on last call,
+@@ -1425,12 +1531,10 @@ u32 __iomem *ipath_getpiobuf(struct ipath_devdata *dd, u32 * pbufnum)
+ * if no buffers were updated, to be paranoid
+ */
+ ipath_update_pio_bufs(dd);
+- /* we scanned here, don't do it at end of scan */
+- updated = 1;
+- i = starti;
++ updated++;
++ i = first;
+ } else
+- i = dd->ipath_lastpioindex;
+-
++ i = firsti;
+ rescan:
+ /*
+ * while test_and_set_bit() is atomic, we do that and then the
+@@ -1438,104 +1542,141 @@ rescan:
+ * of the remaining armlaunch errors.
+ */
+ spin_lock_irqsave(&ipath_pioavail_lock, flags);
+- for (j = 0; j < iter; j++, i++) {
+- if (i >= piobcnt)
+- i = starti;
+- /*
+- * To avoid bus lock overhead, we first find a candidate
+- * buffer, then do the test and set, and continue if that
+- * fails.
+- */
+- if (test_bit((2 * i) + 1, shadow) ||
+- test_and_set_bit((2 * i) + 1, shadow))
++ for (j = 0; j < piobcnt; j++, i++) {
++ if (i >= last)
++ i = first;
++ if (__test_and_set_bit((2 * i) + 1, shadow))
+ continue;
+ /* flip generation bit */
+- change_bit(2 * i, shadow);
++ __change_bit(2 * i, shadow);
+ break;
+ }
+ spin_unlock_irqrestore(&ipath_pioavail_lock, flags);
+
+- if (j == iter) {
+- volatile __le64 *dma = dd->ipath_pioavailregs_dma;
+-
+- /*
+- * first time through; shadow exhausted, but may be real
+- * buffers available, so go see; if any updated, rescan
+- * (once)
+- */
++ if (j == piobcnt) {
+ if (!updated) {
++ /*
++ * first time through; shadow exhausted, but may be
++ * buffers available, try an update and then rescan.
++ */
+ ipath_update_pio_bufs(dd);
+- updated = 1;
+- i = starti;
++ updated++;
++ i = first;
+ goto rescan;
+- }
+- dd->ipath_upd_pio_shadow = 1;
+- /*
+- * not atomic, but if we lose one once in a while, that's OK
+- */
+- ipath_stats.sps_nopiobufs++;
+- if (!(++dd->ipath_consec_nopiobuf % 100000)) {
+- ipath_dbg(
+- "%u pio sends with no bufavail; dmacopy: "
+- "%llx %llx %llx %llx; shadow: "
+- "%lx %lx %lx %lx\n",
+- dd->ipath_consec_nopiobuf,
+- (unsigned long long) le64_to_cpu(dma[0]),
+- (unsigned long long) le64_to_cpu(dma[1]),
+- (unsigned long long) le64_to_cpu(dma[2]),
+- (unsigned long long) le64_to_cpu(dma[3]),
+- shadow[0], shadow[1], shadow[2],
+- shadow[3]);
++ } else if (updated == 1 && piobcnt <=
++ ((dd->ipath_sendctrl
++ >> INFINIPATH_S_UPDTHRESH_SHIFT) &
++ INFINIPATH_S_UPDTHRESH_MASK)) {
+ /*
+- * 4 buffers per byte, 4 registers above, cover rest
+- * below
++ * for chips supporting and using the update
++ * threshold we need to force an update of the
++ * in-memory copy if the count is less than the
++ * thershold, then check one more time.
+ */
+- if ((dd->ipath_piobcnt2k + dd->ipath_piobcnt4k) >
+- (sizeof(shadow[0]) * 4 * 4))
+- ipath_dbg("2nd group: dmacopy: %llx %llx "
+- "%llx %llx; shadow: %lx %lx "
+- "%lx %lx\n",
+- (unsigned long long)
+- le64_to_cpu(dma[4]),
+- (unsigned long long)
+- le64_to_cpu(dma[5]),
+- (unsigned long long)
+- le64_to_cpu(dma[6]),
+- (unsigned long long)
+- le64_to_cpu(dma[7]),
+- shadow[4], shadow[5],
+- shadow[6], shadow[7]);
++ ipath_force_pio_avail_update(dd);
++ ipath_update_pio_bufs(dd);
++ updated++;
++ i = first;
++ goto rescan;
+ }
++
++ no_pio_bufs(dd);
+ buf = NULL;
+- goto bail;
++ } else {
++ if (i < dd->ipath_piobcnt2k)
++ buf = (u32 __iomem *) (dd->ipath_pio2kbase +
++ i * dd->ipath_palign);
++ else
++ buf = (u32 __iomem *)
++ (dd->ipath_pio4kbase +
++ (i - dd->ipath_piobcnt2k) * dd->ipath_4kalign);
++ if (pbufnum)
++ *pbufnum = i;
+ }
+
+- /*
+- * set next starting place. Since it's just an optimization,
+- * it doesn't matter who wins on this, so no locking
+- */
+- dd->ipath_lastpioindex = i + 1;
+- if (dd->ipath_upd_pio_shadow)
+- dd->ipath_upd_pio_shadow = 0;
+- if (dd->ipath_consec_nopiobuf)
+- dd->ipath_consec_nopiobuf = 0;
+- if (i < dd->ipath_piobcnt2k)
+- buf = (u32 __iomem *) (dd->ipath_pio2kbase +
+- i * dd->ipath_palign);
+- else
+- buf = (u32 __iomem *)
+- (dd->ipath_pio4kbase +
+- (i - dd->ipath_piobcnt2k) * dd->ipath_4kalign);
+- ipath_cdbg(VERBOSE, "Return piobuf%u %uk @ %p\n",
+- i, (i < dd->ipath_piobcnt2k) ? 2 : 4, buf);
+- if (pbufnum)
+- *pbufnum = i;
++ return buf;
++}
+
+-bail:
++/**
++ * ipath_getpiobuf - find an available pio buffer
++ * @dd: the infinipath device
++ * @plen: the size of the PIO buffer needed in 32-bit words
++ * @pbufnum: the buffer number is placed here
++ */
++u32 __iomem *ipath_getpiobuf(struct ipath_devdata *dd, u32 plen, u32 *pbufnum)
++{
++ u32 __iomem *buf;
++ u32 pnum, nbufs;
++ u32 first, lasti;
++
++ if (plen + 1 >= IPATH_SMALLBUF_DWORDS) {
++ first = dd->ipath_piobcnt2k;
++ lasti = dd->ipath_lastpioindexl;
++ } else {
++ first = 0;
++ lasti = dd->ipath_lastpioindex;
++ }
++ nbufs = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k;
++ buf = ipath_getpiobuf_range(dd, &pnum, first, nbufs, lasti);
++
++ if (buf) {
++ /*
++ * Set next starting place. It's just an optimization,
++ * it doesn't matter who wins on this, so no locking
++ */
++ if (plen + 1 >= IPATH_SMALLBUF_DWORDS)
++ dd->ipath_lastpioindexl = pnum + 1;
++ else
++ dd->ipath_lastpioindex = pnum + 1;
++ if (dd->ipath_upd_pio_shadow)
++ dd->ipath_upd_pio_shadow = 0;
++ if (dd->ipath_consec_nopiobuf)
++ dd->ipath_consec_nopiobuf = 0;
++ ipath_cdbg(VERBOSE, "Return piobuf%u %uk @ %p\n",
++ pnum, (pnum < dd->ipath_piobcnt2k) ? 2 : 4, buf);
++ if (pbufnum)
++ *pbufnum = pnum;
++
++ }
+ return buf;
+ }
+
+ /**
++ * ipath_chg_pioavailkernel - change which send buffers are available for kernel
++ * @dd: the infinipath device
++ * @start: the starting send buffer number
++ * @len: the number of send buffers
++ * @avail: true if the buffers are available for kernel use, false otherwise
++ */
++void ipath_chg_pioavailkernel(struct ipath_devdata *dd, unsigned start,
++ unsigned len, int avail)
++{
++ unsigned long flags;
++ unsigned end;
++
++ /* There are two bits per send buffer (busy and generation) */
++ start *= 2;
++ len *= 2;
++ end = start + len;
++
++ /* Set or clear the generation bits. */
++ spin_lock_irqsave(&ipath_pioavail_lock, flags);
++ while (start < end) {
++ if (avail) {
++ __clear_bit(start + INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT,
++ dd->ipath_pioavailshadow);
++ __set_bit(start, dd->ipath_pioavailkernel);
++ } else {
++ __set_bit(start + INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT,
++ dd->ipath_pioavailshadow);
++ __clear_bit(start, dd->ipath_pioavailkernel);
++ }
++ start += 2;
++ }
++ spin_unlock_irqrestore(&ipath_pioavail_lock, flags);
++}
++
++/**
+ * ipath_create_rcvhdrq - create a receive header queue
+ * @dd: the infinipath device
+ * @pd: the port data
+@@ -1566,19 +1707,27 @@ int ipath_create_rcvhdrq(struct ipath_devdata *dd,
+ ret = -ENOMEM;
+ goto bail;
+ }
+- pd->port_rcvhdrtail_kvaddr = dma_alloc_coherent(
+- &dd->pcidev->dev, PAGE_SIZE, &phys_hdrqtail, GFP_KERNEL);
+- if (!pd->port_rcvhdrtail_kvaddr) {
+- ipath_dev_err(dd, "attempt to allocate 1 page "
+- "for port %u rcvhdrqtailaddr failed\n",
+- pd->port_port);
+- ret = -ENOMEM;
+- dma_free_coherent(&dd->pcidev->dev, amt,
+- pd->port_rcvhdrq, pd->port_rcvhdrq_phys);
+- pd->port_rcvhdrq = NULL;
+- goto bail;
++
++ if (!(dd->ipath_flags & IPATH_NODMA_RTAIL)) {
++ pd->port_rcvhdrtail_kvaddr = dma_alloc_coherent(
++ &dd->pcidev->dev, PAGE_SIZE, &phys_hdrqtail,
++ GFP_KERNEL);
++ if (!pd->port_rcvhdrtail_kvaddr) {
++ ipath_dev_err(dd, "attempt to allocate 1 page "
++ "for port %u rcvhdrqtailaddr "
++ "failed\n", pd->port_port);
++ ret = -ENOMEM;
++ dma_free_coherent(&dd->pcidev->dev, amt,
++ pd->port_rcvhdrq,
++ pd->port_rcvhdrq_phys);
++ pd->port_rcvhdrq = NULL;
++ goto bail;
++ }
++ pd->port_rcvhdrqtailaddr_phys = phys_hdrqtail;
++ ipath_cdbg(VERBOSE, "port %d hdrtailaddr, %llx "
++ "physical\n", pd->port_port,
++ (unsigned long long) phys_hdrqtail);
+ }
+- pd->port_rcvhdrqtailaddr_phys = phys_hdrqtail;
+
+ pd->port_rcvhdrq_size = amt;
+
+@@ -1588,10 +1737,6 @@ int ipath_create_rcvhdrq(struct ipath_devdata *dd,
+ (unsigned long) pd->port_rcvhdrq_phys,
+ (unsigned long) pd->port_rcvhdrq_size,
+ pd->port_port);
+-
+- ipath_cdbg(VERBOSE, "port %d hdrtailaddr, %llx physical\n",
+- pd->port_port,
+- (unsigned long long) phys_hdrqtail);
+ }
+ else
+ ipath_cdbg(VERBOSE, "reuse port %d rcvhdrq @%p %llx phys; "
+@@ -1615,7 +1760,6 @@ int ipath_create_rcvhdrq(struct ipath_devdata *dd,
+ ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdraddr,
+ pd->port_port, pd->port_rcvhdrq_phys);
+
+- ret = 0;
+ bail:
+ return ret;
+ }
+@@ -1632,52 +1776,149 @@ bail:
+ */
+ void ipath_cancel_sends(struct ipath_devdata *dd, int restore_sendctrl)
+ {
++ unsigned long flags;
++
++ if (dd->ipath_flags & IPATH_IB_AUTONEG_INPROG) {
++ ipath_cdbg(VERBOSE, "Ignore while in autonegotiation\n");
++ goto bail;
++ }
++ /*
++ * If we have SDMA, and it's not disabled, we have to kick off the
++ * abort state machine, provided we aren't already aborting.
++ * If we are in the process of aborting SDMA (!DISABLED, but ABORTING),
++ * we skip the rest of this routine. It is already "in progress"
++ */
++ if (dd->ipath_flags & IPATH_HAS_SEND_DMA) {
++ int skip_cancel;
++ u64 *statp = &dd->ipath_sdma_status;
++
++ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++ skip_cancel =
++ !test_bit(IPATH_SDMA_DISABLED, statp) &&
++ test_and_set_bit(IPATH_SDMA_ABORTING, statp);
++ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++ if (skip_cancel)
++ goto bail;
++ }
++
+ ipath_dbg("Cancelling all in-progress send buffers\n");
+- dd->ipath_lastcancel = jiffies+HZ/2; /* skip armlaunch errs a bit */
++
++ /* skip armlaunch errs for a while */
++ dd->ipath_lastcancel = jiffies + HZ / 2;
++
+ /*
+- * the abort bit is auto-clearing. We read scratch to be sure
+- * that cancels and the abort have taken effect in the chip.
++ * The abort bit is auto-clearing. We also don't want pioavail
++ * update happening during this, and we don't want any other
++ * sends going out, so turn those off for the duration. We read
++ * the scratch register to be sure that cancels and the abort
++ * have taken effect in the chip. Otherwise two parts are same
++ * as ipath_force_pio_avail_update()
+ */
++ spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++ dd->ipath_sendctrl &= ~(INFINIPATH_S_PIOBUFAVAILUPD
++ | INFINIPATH_S_PIOENABLE);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+- INFINIPATH_S_ABORT);
++ dd->ipath_sendctrl | INFINIPATH_S_ABORT);
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++ spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++
++ /* disarm all send buffers */
+ ipath_disarm_piobufs(dd, 0,
+- (unsigned)(dd->ipath_piobcnt2k + dd->ipath_piobcnt4k));
+- if (restore_sendctrl) /* else done by caller later */
++ dd->ipath_piobcnt2k + dd->ipath_piobcnt4k);
++
++ if (restore_sendctrl) {
++ /* else done by caller later if needed */
++ spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++ dd->ipath_sendctrl |= INFINIPATH_S_PIOBUFAVAILUPD |
++ INFINIPATH_S_PIOENABLE;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+- dd->ipath_sendctrl);
++ dd->ipath_sendctrl);
++ /* and again, be sure all have hit the chip */
++ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++ spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++ }
+
+- /* and again, be sure all have hit the chip */
+- ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++ if ((dd->ipath_flags & IPATH_HAS_SEND_DMA) &&
++ !test_bit(IPATH_SDMA_DISABLED, &dd->ipath_sdma_status) &&
++ test_bit(IPATH_SDMA_RUNNING, &dd->ipath_sdma_status)) {
++ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++ /* only wait so long for intr */
++ dd->ipath_sdma_abort_intr_timeout = jiffies + HZ;
++ dd->ipath_sdma_reset_wait = 200;
++ __set_bit(IPATH_SDMA_DISARMED, &dd->ipath_sdma_status);
++ if (!test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status))
++ tasklet_hi_schedule(&dd->ipath_sdma_abort_task);
++ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++ }
++bail:;
+ }
+
++/*
++ * Force an update of in-memory copy of the pioavail registers, when
++ * needed for any of a variety of reasons. We read the scratch register
++ * to make it highly likely that the update will have happened by the
++ * time we return. If already off (as in cancel_sends above), this
++ * routine is a nop, on the assumption that the caller will "do the
++ * right thing".
++ */
++void ipath_force_pio_avail_update(struct ipath_devdata *dd)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++ if (dd->ipath_sendctrl & INFINIPATH_S_PIOBUFAVAILUPD) {
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
++ dd->ipath_sendctrl & ~INFINIPATH_S_PIOBUFAVAILUPD);
++ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
++ dd->ipath_sendctrl);
++ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++ }
++ spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++}
+
+-static void ipath_set_ib_lstate(struct ipath_devdata *dd, int which)
++static void ipath_set_ib_lstate(struct ipath_devdata *dd, int linkcmd,
++ int linitcmd)
+ {
++ u64 mod_wd;
+ static const char *what[4] = {
+ [0] = "NOP",
+ [INFINIPATH_IBCC_LINKCMD_DOWN] = "DOWN",
+ [INFINIPATH_IBCC_LINKCMD_ARMED] = "ARMED",
+ [INFINIPATH_IBCC_LINKCMD_ACTIVE] = "ACTIVE"
+ };
+- int linkcmd = (which >> INFINIPATH_IBCC_LINKCMD_SHIFT) &
+- INFINIPATH_IBCC_LINKCMD_MASK;
+-
+- ipath_cdbg(VERBOSE, "Trying to move unit %u to %s, current ltstate "
+- "is %s\n", dd->ipath_unit,
+- what[linkcmd],
+- ipath_ibcstatus_str[
+- (ipath_read_kreg64
+- (dd, dd->ipath_kregs->kr_ibcstatus) >>
+- INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) &
+- INFINIPATH_IBCS_LINKTRAININGSTATE_MASK]);
+- /* flush all queued sends when going to DOWN to be sure that
+- * they don't block MAD packets */
+- if (linkcmd == INFINIPATH_IBCC_LINKCMD_DOWN)
+- ipath_cancel_sends(dd, 1);
++
++ if (linitcmd == INFINIPATH_IBCC_LINKINITCMD_DISABLE) {
++ /*
++ * If we are told to disable, note that so link-recovery
++ * code does not attempt to bring us back up.
++ */
++ preempt_disable();
++ dd->ipath_flags |= IPATH_IB_LINK_DISABLED;
++ preempt_enable();
++ } else if (linitcmd) {
++ /*
++ * Any other linkinitcmd will lead to LINKDOWN and then
++ * to INIT (if all is well), so clear flag to let
++ * link-recovery code attempt to bring us back up.
++ */
++ preempt_disable();
++ dd->ipath_flags &= ~IPATH_IB_LINK_DISABLED;
++ preempt_enable();
++ }
++
++ mod_wd = (linkcmd << dd->ibcc_lc_shift) |
++ (linitcmd << INFINIPATH_IBCC_LINKINITCMD_SHIFT);
++ ipath_cdbg(VERBOSE,
++ "Moving unit %u to %s (initcmd=0x%x), current ltstate is %s\n",
++ dd->ipath_unit, what[linkcmd], linitcmd,
++ ipath_ibcstatus_str[ipath_ib_linktrstate(dd,
++ ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus))]);
+
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
+- dd->ipath_ibcctrl | which);
++ dd->ipath_ibcctrl | mod_wd);
++ /* read from chip so write is flushed */
++ (void) ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
+ }
+
+ int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate)
+@@ -1687,30 +1928,28 @@ int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate)
+
+ switch (newstate) {
+ case IPATH_IB_LINKDOWN_ONLY:
+- ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_DOWN <<
+- INFINIPATH_IBCC_LINKCMD_SHIFT);
++ ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_DOWN, 0);
+ /* don't wait */
+ ret = 0;
+ goto bail;
+
+ case IPATH_IB_LINKDOWN:
+- ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_POLL <<
+- INFINIPATH_IBCC_LINKINITCMD_SHIFT);
++ ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_DOWN,
++ INFINIPATH_IBCC_LINKINITCMD_POLL);
+ /* don't wait */
+ ret = 0;
+ goto bail;
+
+ case IPATH_IB_LINKDOWN_SLEEP:
+- ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_SLEEP <<
+- INFINIPATH_IBCC_LINKINITCMD_SHIFT);
++ ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_DOWN,
++ INFINIPATH_IBCC_LINKINITCMD_SLEEP);
+ /* don't wait */
+ ret = 0;
+ goto bail;
+
+ case IPATH_IB_LINKDOWN_DISABLE:
+- ipath_set_ib_lstate(dd,
+- INFINIPATH_IBCC_LINKINITCMD_DISABLE <<
+- INFINIPATH_IBCC_LINKINITCMD_SHIFT);
++ ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_DOWN,
++ INFINIPATH_IBCC_LINKINITCMD_DISABLE);
+ /* don't wait */
+ ret = 0;
+ goto bail;
+@@ -1725,8 +1964,8 @@ int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate)
+ ret = -EINVAL;
+ goto bail;
+ }
+- ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ARMED <<
+- INFINIPATH_IBCC_LINKCMD_SHIFT);
++ ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ARMED, 0);
++
+ /*
+ * Since the port can transition to ACTIVE by receiving
+ * a non VL 15 packet, wait for either state.
+@@ -1743,8 +1982,7 @@ int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate)
+ ret = -EINVAL;
+ goto bail;
+ }
+- ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ACTIVE <<
+- INFINIPATH_IBCC_LINKCMD_SHIFT);
++ ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ACTIVE, 0);
+ lstate = IPATH_LINKACTIVE;
+ break;
+
+@@ -1753,16 +1991,41 @@ int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate)
+ dd->ipath_ibcctrl |= INFINIPATH_IBCC_LOOPBACK;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
+ dd->ipath_ibcctrl);
++
++ /* turn heartbeat off, as it causes loopback to fail */
++ dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_HRTBT,
++ IPATH_IB_HRTBT_OFF);
++ /* don't wait */
+ ret = 0;
+- goto bail; // no state change to wait for
++ goto bail;
+
+ case IPATH_IB_LINK_EXTERNAL:
+- dev_info(&dd->pcidev->dev, "Disabling IB local loopback (normal)\n");
++ dev_info(&dd->pcidev->dev,
++ "Disabling IB local loopback (normal)\n");
++ dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_HRTBT,
++ IPATH_IB_HRTBT_ON);
+ dd->ipath_ibcctrl &= ~INFINIPATH_IBCC_LOOPBACK;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
+ dd->ipath_ibcctrl);
++ /* don't wait */
+ ret = 0;
+- goto bail; // no state change to wait for
++ goto bail;
++
++ /*
++ * Heartbeat can be explicitly enabled by the user via
++ * "hrtbt_enable" "file", and if disabled, trying to enable here
++ * will have no effect. Implicit changes (heartbeat off when
++ * loopback on, and vice versa) are included to ease testing.
++ */
++ case IPATH_IB_LINK_HRTBT:
++ ret = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_HRTBT,
++ IPATH_IB_HRTBT_ON);
++ goto bail;
++
++ case IPATH_IB_LINK_NO_HRTBT:
++ ret = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_HRTBT,
++ IPATH_IB_HRTBT_OFF);
++ goto bail;
+
+ default:
+ ipath_dbg("Invalid linkstate 0x%x requested\n", newstate);
+@@ -1785,7 +2048,7 @@ bail:
+ * sanity checking on this, and we don't deal with what happens to
+ * programs that are already running when the size changes.
+ * NOTE: changing the MTU will usually cause the IBC to go back to
+- * link initialize (IPATH_IBSTATE_INIT) state...
++ * link INIT state...
+ */
+ int ipath_set_mtu(struct ipath_devdata *dd, u16 arg)
+ {
+@@ -1800,7 +2063,7 @@ int ipath_set_mtu(struct ipath_devdata *dd, u16 arg)
+ * piosize). We check that it's one of the valid IB sizes.
+ */
+ if (arg != 256 && arg != 512 && arg != 1024 && arg != 2048 &&
+- arg != 4096) {
++ (arg != 4096 || !ipath_mtu4096)) {
+ ipath_dbg("Trying to set invalid mtu %u, failing\n", arg);
+ ret = -EINVAL;
+ goto bail;
+@@ -1816,6 +2079,8 @@ int ipath_set_mtu(struct ipath_devdata *dd, u16 arg)
+ if (arg >= (piosize - IPATH_PIO_MAXIBHDR)) {
+ /* Only if it's not the initial value (or reset to it) */
+ if (piosize != dd->ipath_init_ibmaxlen) {
++ if (arg > piosize && arg <= dd->ipath_init_ibmaxlen)
++ piosize = dd->ipath_init_ibmaxlen;
+ dd->ipath_ibmaxlen = piosize;
+ changed = 1;
+ }
+@@ -1829,24 +2094,17 @@ int ipath_set_mtu(struct ipath_devdata *dd, u16 arg)
+ }
+
+ if (changed) {
++ u64 ibc = dd->ipath_ibcctrl, ibdw;
+ /*
+- * set the IBC maxpktlength to the size of our pio
+- * buffers in words
++ * update our housekeeping variables, and set IBC max
++ * size, same as init code; max IBC is max we allow in
++ * buffer, less the qword pbc, plus 1 for ICRC, in dwords
+ */
+- u64 ibc = dd->ipath_ibcctrl;
++ dd->ipath_ibmaxlen = piosize - 2 * sizeof(u32);
++ ibdw = (dd->ipath_ibmaxlen >> 2) + 1;
+ ibc &= ~(INFINIPATH_IBCC_MAXPKTLEN_MASK <<
+- INFINIPATH_IBCC_MAXPKTLEN_SHIFT);
+-
+- piosize = piosize - 2 * sizeof(u32); /* ignore pbc */
+- dd->ipath_ibmaxlen = piosize;
+- piosize /= sizeof(u32); /* in words */
+- /*
+- * for ICRC, which we only send in diag test pkt mode, and
+- * we don't need to worry about that for mtu
+- */
+- piosize += 1;
+-
+- ibc |= piosize << INFINIPATH_IBCC_MAXPKTLEN_SHIFT;
++ dd->ibcc_mpl_shift);
++ ibc |= ibdw << dd->ibcc_mpl_shift;
+ dd->ipath_ibcctrl = ibc;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
+ dd->ipath_ibcctrl);
+@@ -1859,11 +2117,16 @@ bail:
+ return ret;
+ }
+
+-int ipath_set_lid(struct ipath_devdata *dd, u32 arg, u8 lmc)
++int ipath_set_lid(struct ipath_devdata *dd, u32 lid, u8 lmc)
+ {
+- dd->ipath_lid = arg;
++ dd->ipath_lid = lid;
+ dd->ipath_lmc = lmc;
+
++ dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_LIDLMC, lid |
++ (~((1U << lmc) - 1)) << 16);
++
++ dev_info(&dd->pcidev->dev, "We got a lid: 0x%x\n", lid);
++
+ return 0;
+ }
+
+@@ -1925,10 +2188,8 @@ static void ipath_run_led_override(unsigned long opaque)
+ * but leave that to per-chip functions.
+ */
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
+- ltstate = (val >> INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) &
+- INFINIPATH_IBCS_LINKTRAININGSTATE_MASK;
+- lstate = (val >> INFINIPATH_IBCS_LINKSTATE_SHIFT) &
+- INFINIPATH_IBCS_LINKSTATE_MASK;
++ ltstate = ipath_ib_linktrstate(dd, val);
++ lstate = ipath_ib_linkstate(dd, val);
+
+ dd->ipath_f_setextled(dd, lstate, ltstate);
+ mod_timer(&dd->ipath_led_override_timer, jiffies + timeoff);
+@@ -1969,9 +2230,8 @@ void ipath_set_led_override(struct ipath_devdata *dd, unsigned int val)
+ dd->ipath_led_override_timer.data = (unsigned long) dd;
+ dd->ipath_led_override_timer.expires = jiffies + 1;
+ add_timer(&dd->ipath_led_override_timer);
+- } else {
++ } else
+ atomic_dec(&dd->ipath_led_override_timer_active);
+- }
+ }
+
+ /**
+@@ -1989,6 +2249,8 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
+
+ ipath_dbg("Shutting down the device\n");
+
++ ipath_hol_up(dd); /* make sure user processes aren't suspended */
++
+ dd->ipath_flags |= IPATH_LINKUNK;
+ dd->ipath_flags &= ~(IPATH_INITTED | IPATH_LINKDOWN |
+ IPATH_LINKINIT | IPATH_LINKARMED |
+@@ -2003,6 +2265,9 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl);
+
++ if (dd->ipath_flags & IPATH_HAS_SEND_DMA)
++ teardown_sdma(dd);
++
+ /*
+ * gracefully stop all sends allowing any in progress to trickle out
+ * first.
+@@ -2020,10 +2285,16 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
+ */
+ udelay(5);
+
+- ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_DISABLE <<
+- INFINIPATH_IBCC_LINKINITCMD_SHIFT);
++ dd->ipath_f_setextled(dd, 0, 0); /* make sure LEDs are off */
++
++ ipath_set_ib_lstate(dd, 0, INFINIPATH_IBCC_LINKINITCMD_DISABLE);
+ ipath_cancel_sends(dd, 0);
+
++ /*
++ * we are shutting down, so tell components that care. We don't do
++ * this on just a link state change, much like ethernet, a cable
++ * unplug, etc. doesn't change driver state
++ */
+ signal_ib_event(dd, IB_EVENT_PORT_ERR);
+
+ /* disable IBC */
+@@ -2038,10 +2309,20 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
+ */
+ dd->ipath_f_quiet_serdes(dd);
+
++ /* stop all the timers that might still be running */
++ del_timer_sync(&dd->ipath_hol_timer);
+ if (dd->ipath_stats_timer_active) {
+ del_timer_sync(&dd->ipath_stats_timer);
+ dd->ipath_stats_timer_active = 0;
+ }
++ if (dd->ipath_intrchk_timer.data) {
++ del_timer_sync(&dd->ipath_intrchk_timer);
++ dd->ipath_intrchk_timer.data = 0;
++ }
++ if (atomic_read(&dd->ipath_led_override_timer_active)) {
++ del_timer_sync(&dd->ipath_led_override_timer);
++ atomic_set(&dd->ipath_led_override_timer_active, 0);
++ }
+
+ /*
+ * clear all interrupts and errors, so that the next time the driver
+@@ -2115,13 +2396,13 @@ void ipath_free_pddata(struct ipath_devdata *dd, struct ipath_portdata *pd)
+ ipath_cdbg(VERBOSE, "free closed port %d "
+ "ipath_port0_skbinfo @ %p\n", pd->port_port,
+ skbinfo);
+- for (e = 0; e < dd->ipath_rcvegrcnt; e++)
+- if (skbinfo[e].skb) {
+- pci_unmap_single(dd->pcidev, skbinfo[e].phys,
+- dd->ipath_ibmaxlen,
+- PCI_DMA_FROMDEVICE);
+- dev_kfree_skb(skbinfo[e].skb);
+- }
++ for (e = 0; e < dd->ipath_p0_rcvegrcnt; e++)
++ if (skbinfo[e].skb) {
++ pci_unmap_single(dd->pcidev, skbinfo[e].phys,
++ dd->ipath_ibmaxlen,
++ PCI_DMA_FROMDEVICE);
++ dev_kfree_skb(skbinfo[e].skb);
++ }
+ vfree(skbinfo);
+ }
+ kfree(pd->port_tid_pg_list);
+@@ -2144,6 +2425,7 @@ static int __init infinipath_init(void)
+ */
+ idr_init(&unit_table);
+ if (!idr_pre_get(&unit_table, GFP_KERNEL)) {
++ printk(KERN_ERR IPATH_DRV_NAME ": idr_pre_get() failed\n");
+ ret = -ENOMEM;
+ goto bail;
+ }
+@@ -2235,13 +2517,18 @@ int ipath_reset_device(int unit)
+ }
+ }
+
++ if (dd->ipath_flags & IPATH_HAS_SEND_DMA)
++ teardown_sdma(dd);
++
+ dd->ipath_flags &= ~IPATH_INITTED;
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask, 0ULL);
+ ret = dd->ipath_f_reset(dd);
+- if (ret != 1)
+- ipath_dbg("reset was not successful\n");
+- ipath_dbg("Trying to reinitialize unit %u after reset attempt\n",
+- unit);
+- ret = ipath_init_chip(dd, 1);
++ if (ret == 1) {
++ ipath_dbg("Reinitializing unit %u after reset attempt\n",
++ unit);
++ ret = ipath_init_chip(dd, 1);
++ } else
++ ret = -EAGAIN;
+ if (ret)
+ ipath_dev_err(dd, "Reinitialize unit %u after "
+ "reset failed with %d\n", unit, ret);
+@@ -2253,13 +2540,121 @@ bail:
+ return ret;
+ }
+
++/*
++ * send a signal to all the processes that have the driver open
++ * through the normal interfaces (i.e., everything other than diags
++ * interface). Returns number of signalled processes.
++ */
++static int ipath_signal_procs(struct ipath_devdata *dd, int sig)
++{
++ int i, sub, any = 0;
++ pid_t pid;
++
++ if (!dd->ipath_pd)
++ return 0;
++ for (i = 1; i < dd->ipath_cfgports; i++) {
++ if (!dd->ipath_pd[i] || !dd->ipath_pd[i]->port_cnt ||
++ !dd->ipath_pd[i]->port_pid)
++ continue;
++ pid = dd->ipath_pd[i]->port_pid;
++ dev_info(&dd->pcidev->dev, "context %d in use "
++ "(PID %u), sending signal %d\n",
++ i, pid, sig);
++ kill_proc(pid, sig, 1);
++ any++;
++ for (sub = 0; sub < INFINIPATH_MAX_SUBPORT; sub++) {
++ pid = dd->ipath_pd[i]->port_subpid[sub];
++ if (!pid)
++ continue;
++ dev_info(&dd->pcidev->dev, "sub-context "
++ "%d:%d in use (PID %u), sending "
++ "signal %d\n", i, sub, pid, sig);
++ kill_proc(pid, sig, 1);
++ any++;
++ }
++ }
++ return any;
++}
++
++static void ipath_hol_signal_down(struct ipath_devdata *dd)
++{
++ if (ipath_signal_procs(dd, SIGSTOP))
++ ipath_dbg("Stopped some processes\n");
++ ipath_cancel_sends(dd, 1);
++}
++
++
++static void ipath_hol_signal_up(struct ipath_devdata *dd)
++{
++ if (ipath_signal_procs(dd, SIGCONT))
++ ipath_dbg("Continued some processes\n");
++}
++
++/*
++ * link is down, stop any users processes, and flush pending sends
++ * to prevent HoL blocking, then start the HoL timer that
++ * periodically continues, then stop procs, so they can detect
++ * link down if they want, and do something about it.
++ * Timer may already be running, so use __mod_timer, not add_timer.
++ */
++void ipath_hol_down(struct ipath_devdata *dd)
++{
++ dd->ipath_hol_state = IPATH_HOL_DOWN;
++ ipath_hol_signal_down(dd);
++ dd->ipath_hol_next = IPATH_HOL_DOWNCONT;
++ dd->ipath_hol_timer.expires = jiffies +
++ msecs_to_jiffies(ipath_hol_timeout_ms);
++ __mod_timer(&dd->ipath_hol_timer, dd->ipath_hol_timer.expires);
++}
++
++/*
++ * link is up, continue any user processes, and ensure timer
++ * is a nop, if running. Let timer keep running, if set; it
++ * will nop when it sees the link is up
++ */
++void ipath_hol_up(struct ipath_devdata *dd)
++{
++ ipath_hol_signal_up(dd);
++ dd->ipath_hol_state = IPATH_HOL_UP;
++}
++
++/*
++ * toggle the running/not running state of user proceses
++ * to prevent HoL blocking on chip resources, but still allow
++ * user processes to do link down special case handling.
++ * Should only be called via the timer
++ */
++void ipath_hol_event(unsigned long opaque)
++{
++ struct ipath_devdata *dd = (struct ipath_devdata *)opaque;
++
++ if (dd->ipath_hol_next == IPATH_HOL_DOWNSTOP
++ && dd->ipath_hol_state != IPATH_HOL_UP) {
++ dd->ipath_hol_next = IPATH_HOL_DOWNCONT;
++ ipath_dbg("Stopping processes\n");
++ ipath_hol_signal_down(dd);
++ } else { /* may do "extra" if also in ipath_hol_up() */
++ dd->ipath_hol_next = IPATH_HOL_DOWNSTOP;
++ ipath_dbg("Continuing processes\n");
++ ipath_hol_signal_up(dd);
++ }
++ if (dd->ipath_hol_state == IPATH_HOL_UP)
++ ipath_dbg("link's up, don't resched timer\n");
++ else {
++ dd->ipath_hol_timer.expires = jiffies +
++ msecs_to_jiffies(ipath_hol_timeout_ms);
++ __mod_timer(&dd->ipath_hol_timer,
++ dd->ipath_hol_timer.expires);
++ }
++}
++
+ int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv)
+ {
+ u64 val;
+- if ( new_pol_inv > INFINIPATH_XGXS_RX_POL_MASK ) {
++
++ if (new_pol_inv > INFINIPATH_XGXS_RX_POL_MASK)
+ return -1;
+- }
+- if ( dd->ipath_rx_pol_inv != new_pol_inv ) {
++ if (dd->ipath_rx_pol_inv != new_pol_inv) {
+ dd->ipath_rx_pol_inv = new_pol_inv;
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
+ val &= ~(INFINIPATH_XGXS_RX_POL_MASK <<
+diff --git a/drivers/infiniband/hw/ipath/ipath_eeprom.c b/drivers/infiniband/hw/ipath/ipath_eeprom.c
+index e28a42f..dc37277 100644
+--- a/drivers/infiniband/hw/ipath/ipath_eeprom.c
++++ b/drivers/infiniband/hw/ipath/ipath_eeprom.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+@@ -62,6 +62,33 @@
+ * accessing eeprom contents from within the kernel, only via sysfs.
+ */
+
++/* Added functionality for IBA7220-based cards */
++#define IPATH_EEPROM_DEV_V1 0xA0
++#define IPATH_EEPROM_DEV_V2 0xA2
++#define IPATH_TEMP_DEV 0x98
++#define IPATH_BAD_DEV (IPATH_EEPROM_DEV_V2+2)
++#define IPATH_NO_DEV (0xFF)
++
++/*
++ * The number of I2C chains is proliferating. Table below brings
++ * some order to the madness. The basic principle is that the
++ * table is scanned from the top, and a "probe" is made to the
++ * device probe_dev. If that succeeds, the chain is considered
++ * to be of that type, and dd->i2c_chain_type is set to the index+1
++ * of the entry.
++ * The +1 is so static initialization can mean "unknown, do probe."
++ */
++static struct i2c_chain_desc {
++ u8 probe_dev; /* If seen at probe, chain is this type */
++ u8 eeprom_dev; /* Dev addr (if any) for EEPROM */
++ u8 temp_dev; /* Dev Addr (if any) for Temp-sense */
++} i2c_chains[] = {
++ { IPATH_BAD_DEV, IPATH_NO_DEV, IPATH_NO_DEV }, /* pre-iba7220 bds */
++ { IPATH_EEPROM_DEV_V1, IPATH_EEPROM_DEV_V1, IPATH_TEMP_DEV}, /* V1 */
++ { IPATH_EEPROM_DEV_V2, IPATH_EEPROM_DEV_V2, IPATH_TEMP_DEV}, /* V2 */
++ { IPATH_NO_DEV }
++};
++
+ enum i2c_type {
+ i2c_line_scl = 0,
+ i2c_line_sda
+@@ -75,13 +102,6 @@ enum i2c_state {
+ #define READ_CMD 1
+ #define WRITE_CMD 0
+
+-static int eeprom_init;
+-
+-/*
+- * The gpioval manipulation really should be protected by spinlocks
+- * or be converted to use atomic operations.
+- */
+-
+ /**
+ * i2c_gpio_set - set a GPIO line
+ * @dd: the infinipath device
+@@ -241,6 +261,27 @@ static int i2c_ackrcv(struct ipath_devdata *dd)
+ }
+
+ /**
++ * rd_byte - read a byte, leaving ACK, STOP, etc up to caller
++ * @dd: the infinipath device
++ *
++ * Returns byte shifted out of device
++ */
++static int rd_byte(struct ipath_devdata *dd)
++{
++ int bit_cntr, data;
++
++ data = 0;
++
++ for (bit_cntr = 7; bit_cntr >= 0; --bit_cntr) {
++ data <<= 1;
++ scl_out(dd, i2c_line_high);
++ data |= sda_in(dd, 0);
++ scl_out(dd, i2c_line_low);
++ }
++ return data;
++}
++
++/**
+ * wr_byte - write a byte, one bit at a time
+ * @dd: the infinipath device
+ * @data: the byte to write
+@@ -331,7 +372,6 @@ static int eeprom_reset(struct ipath_devdata *dd)
+ ipath_cdbg(VERBOSE, "Resetting i2c eeprom; initial gpioout reg "
+ "is %llx\n", (unsigned long long) *gpioval);
+
+- eeprom_init = 1;
+ /*
+ * This is to get the i2c into a known state, by first going low,
+ * then tristate sda (and then tristate scl as first thing
+@@ -340,12 +380,17 @@ static int eeprom_reset(struct ipath_devdata *dd)
+ scl_out(dd, i2c_line_low);
+ sda_out(dd, i2c_line_high);
+
++ /* Clock up to 9 cycles looking for SDA hi, then issue START and STOP */
+ while (clock_cycles_left--) {
+ scl_out(dd, i2c_line_high);
+
++ /* SDA seen high, issue START by dropping it while SCL high */
+ if (sda_in(dd, 0)) {
+ sda_out(dd, i2c_line_low);
+ scl_out(dd, i2c_line_low);
++ /* ATMEL spec says must be followed by STOP. */
++ scl_out(dd, i2c_line_high);
++ sda_out(dd, i2c_line_high);
+ ret = 0;
+ goto bail;
+ }
+@@ -359,29 +404,121 @@ bail:
+ return ret;
+ }
+
+-/**
+- * ipath_eeprom_read - receives bytes from the eeprom via I2C
+- * @dd: the infinipath device
+- * @eeprom_offset: address to read from
+- * @buffer: where to store result
+- * @len: number of bytes to receive
++/*
++ * Probe for I2C device at specified address. Returns 0 for "success"
++ * to match rest of this file.
++ * Leave bus in "reasonable" state for further commands.
+ */
++static int i2c_probe(struct ipath_devdata *dd, int devaddr)
++{
++ int ret = 0;
++
++ ret = eeprom_reset(dd);
++ if (ret) {
++ ipath_dev_err(dd, "Failed reset probing device 0x%02X\n",
++ devaddr);
++ return ret;
++ }
++ /*
++ * Reset no longer leaves bus in start condition, so normal
++ * i2c_startcmd() will do.
++ */
++ ret = i2c_startcmd(dd, devaddr | READ_CMD);
++ if (ret)
++ ipath_cdbg(VERBOSE, "Failed startcmd for device 0x%02X\n",
++ devaddr);
++ else {
++ /*
++ * Device did respond. Complete a single-byte read, because some
++ * devices apparently cannot handle STOP immediately after they
++ * ACK the start-cmd.
++ */
++ int data;
++ data = rd_byte(dd);
++ stop_cmd(dd);
++ ipath_cdbg(VERBOSE, "Response from device 0x%02X\n", devaddr);
++ }
++ return ret;
++}
++
++/*
++ * Returns the "i2c type". This is a pointer to a struct that describes
++ * the I2C chain on this board. To minimize impact on struct ipath_devdata,
++ * the (small integer) index into the table is actually memoized, rather
++ * then the pointer.
++ * Memoization is because the type is determined on the first call per chip.
++ * An alternative would be to move type determination to early
++ * init code.
++ */
++static struct i2c_chain_desc *ipath_i2c_type(struct ipath_devdata *dd)
++{
++ int idx;
++
++ /* Get memoized index, from previous successful probes */
++ idx = dd->ipath_i2c_chain_type - 1;
++ if (idx >= 0 && idx < (ARRAY_SIZE(i2c_chains) - 1))
++ goto done;
++
++ idx = 0;
++ while (i2c_chains[idx].probe_dev != IPATH_NO_DEV) {
++ /* if probe succeeds, this is type */
++ if (!i2c_probe(dd, i2c_chains[idx].probe_dev))
++ break;
++ ++idx;
++ }
++
++ /*
++ * Old EEPROM (first entry) may require a reset after probe,
++ * rather than being able to "start" after "stop"
++ */
++ if (idx == 0)
++ eeprom_reset(dd);
++
++ if (i2c_chains[idx].probe_dev == IPATH_NO_DEV)
++ idx = -1;
++ else
++ dd->ipath_i2c_chain_type = idx + 1;
++done:
++ return (idx >= 0) ? i2c_chains + idx : NULL;
++}
+
+ static int ipath_eeprom_internal_read(struct ipath_devdata *dd,
+ u8 eeprom_offset, void *buffer, int len)
+ {
+- /* compiler complains unless initialized */
+- u8 single_byte = 0;
+- int bit_cntr;
+ int ret;
++ struct i2c_chain_desc *icd;
++ u8 *bp = buffer;
+
+- if (!eeprom_init)
+- eeprom_reset(dd);
+-
+- eeprom_offset = (eeprom_offset << 1) | READ_CMD;
++ ret = 1;
++ icd = ipath_i2c_type(dd);
++ if (!icd)
++ goto bail;
+
+- if (i2c_startcmd(dd, eeprom_offset)) {
+- ipath_dbg("Failed startcmd\n");
++ if (icd->eeprom_dev == IPATH_NO_DEV) {
++ /* legacy not-really-I2C */
++ ipath_cdbg(VERBOSE, "Start command only address\n");
++ eeprom_offset = (eeprom_offset << 1) | READ_CMD;
++ ret = i2c_startcmd(dd, eeprom_offset);
++ } else {
++ /* Actual I2C */
++ ipath_cdbg(VERBOSE, "Start command uses devaddr\n");
++ if (i2c_startcmd(dd, icd->eeprom_dev | WRITE_CMD)) {
++ ipath_dbg("Failed EEPROM startcmd\n");
++ stop_cmd(dd);
++ ret = 1;
++ goto bail;
++ }
++ ret = wr_byte(dd, eeprom_offset);
++ stop_cmd(dd);
++ if (ret) {
++ ipath_dev_err(dd, "Failed to write EEPROM address\n");
++ ret = 1;
++ goto bail;
++ }
++ ret = i2c_startcmd(dd, icd->eeprom_dev | READ_CMD);
++ }
++ if (ret) {
++ ipath_dbg("Failed startcmd for dev %02X\n", icd->eeprom_dev);
+ stop_cmd(dd);
+ ret = 1;
+ goto bail;
+@@ -392,22 +529,11 @@ static int ipath_eeprom_internal_read(struct ipath_devdata *dd,
+ * incrementing the address.
+ */
+ while (len-- > 0) {
+- /* get data */
+- single_byte = 0;
+- for (bit_cntr = 8; bit_cntr; bit_cntr--) {
+- u8 bit;
+- scl_out(dd, i2c_line_high);
+- bit = sda_in(dd, 0);
+- single_byte |= bit << (bit_cntr - 1);
+- scl_out(dd, i2c_line_low);
+- }
+-
++ /* get and store data */
++ *bp++ = rd_byte(dd);
+ /* send ack if not the last byte */
+ if (len)
+ send_ack(dd);
+-
+- *((u8 *) buffer) = single_byte;
+- buffer++;
+ }
+
+ stop_cmd(dd);
+@@ -418,31 +544,40 @@ bail:
+ return ret;
+ }
+
+-
+-/**
+- * ipath_eeprom_write - writes data to the eeprom via I2C
+- * @dd: the infinipath device
+- * @eeprom_offset: where to place data
+- * @buffer: data to write
+- * @len: number of bytes to write
+- */
+ static int ipath_eeprom_internal_write(struct ipath_devdata *dd, u8 eeprom_offset,
+ const void *buffer, int len)
+ {
+- u8 single_byte;
+ int sub_len;
+ const u8 *bp = buffer;
+ int max_wait_time, i;
+ int ret;
++ struct i2c_chain_desc *icd;
+
+- if (!eeprom_init)
+- eeprom_reset(dd);
++ ret = 1;
++ icd = ipath_i2c_type(dd);
++ if (!icd)
++ goto bail;
+
+ while (len > 0) {
+- if (i2c_startcmd(dd, (eeprom_offset << 1) | WRITE_CMD)) {
+- ipath_dbg("Failed to start cmd offset %u\n",
+- eeprom_offset);
+- goto failed_write;
++ if (icd->eeprom_dev == IPATH_NO_DEV) {
++ if (i2c_startcmd(dd,
++ (eeprom_offset << 1) | WRITE_CMD)) {
++ ipath_dbg("Failed to start cmd offset %u\n",
++ eeprom_offset);
++ goto failed_write;
++ }
++ } else {
++ /* Real I2C */
++ if (i2c_startcmd(dd, icd->eeprom_dev | WRITE_CMD)) {
++ ipath_dbg("Failed EEPROM startcmd\n");
++ goto failed_write;
++ }
++ ret = wr_byte(dd, eeprom_offset);
++ if (ret) {
++ ipath_dev_err(dd, "Failed to write EEPROM "
++ "address\n");
++ goto failed_write;
++ }
+ }
+
+ sub_len = min(len, 4);
+@@ -468,9 +603,11 @@ static int ipath_eeprom_internal_write(struct ipath_devdata *dd, u8 eeprom_offse
+ * the writes have completed. We do this inline to avoid
+ * the debug prints that are in the real read routine
+ * if the startcmd fails.
++ * We also use the proper device address, so it doesn't matter
++ * whether we have real eeprom_dev. legacy likes any address.
+ */
+ max_wait_time = 100;
+- while (i2c_startcmd(dd, READ_CMD)) {
++ while (i2c_startcmd(dd, icd->eeprom_dev | READ_CMD)) {
+ stop_cmd(dd);
+ if (!--max_wait_time) {
+ ipath_dbg("Did not get successful read to "
+@@ -478,15 +615,8 @@ static int ipath_eeprom_internal_write(struct ipath_devdata *dd, u8 eeprom_offse
+ goto failed_write;
+ }
+ }
+- /* now read the zero byte */
+- for (i = single_byte = 0; i < 8; i++) {
+- u8 bit;
+- scl_out(dd, i2c_line_high);
+- bit = sda_in(dd, 0);
+- scl_out(dd, i2c_line_low);
+- single_byte <<= 1;
+- single_byte |= bit;
+- }
++ /* now read (and ignore) the resulting byte */
++ rd_byte(dd);
+ stop_cmd(dd);
+ }
+
+@@ -501,9 +631,12 @@ bail:
+ return ret;
+ }
+
+-/*
+- * The public entry-points ipath_eeprom_read() and ipath_eeprom_write()
+- * are now just wrappers around the internal functions.
++/**
++ * ipath_eeprom_read - receives bytes from the eeprom via I2C
++ * @dd: the infinipath device
++ * @eeprom_offset: address to read from
++ * @buffer: where to store result
++ * @len: number of bytes to receive
+ */
+ int ipath_eeprom_read(struct ipath_devdata *dd, u8 eeprom_offset,
+ void *buff, int len)
+@@ -519,6 +652,13 @@ int ipath_eeprom_read(struct ipath_devdata *dd, u8 eeprom_offset,
+ return ret;
+ }
+
++/**
++ * ipath_eeprom_write - writes data to the eeprom via I2C
++ * @dd: the infinipath device
++ * @eeprom_offset: where to place data
++ * @buffer: data to write
++ * @len: number of bytes to write
++ */
+ int ipath_eeprom_write(struct ipath_devdata *dd, u8 eeprom_offset,
+ const void *buff, int len)
+ {
+@@ -820,7 +960,7 @@ int ipath_update_eeprom_log(struct ipath_devdata *dd)
+ * if we log an hour at 31 minutes, then we would need to set
+ * active_time to -29 to accurately count the _next_ hour.
+ */
+- if (new_time > 3600) {
++ if (new_time >= 3600) {
+ new_hrs = new_time / 3600;
+ atomic_sub((new_hrs * 3600), &dd->ipath_active_time);
+ new_hrs += dd->ipath_eep_hrs;
+@@ -885,3 +1025,159 @@ void ipath_inc_eeprom_err(struct ipath_devdata *dd, u32 eidx, u32 incr)
+ spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
+ return;
+ }
++
++static int ipath_tempsense_internal_read(struct ipath_devdata *dd, u8 regnum)
++{
++ int ret;
++ struct i2c_chain_desc *icd;
++
++ ret = -ENOENT;
++
++ icd = ipath_i2c_type(dd);
++ if (!icd)
++ goto bail;
++
++ if (icd->temp_dev == IPATH_NO_DEV) {
++ /* tempsense only exists on new, real-I2C boards */
++ ret = -ENXIO;
++ goto bail;
++ }
++
++ if (i2c_startcmd(dd, icd->temp_dev | WRITE_CMD)) {
++ ipath_dbg("Failed tempsense startcmd\n");
++ stop_cmd(dd);
++ ret = -ENXIO;
++ goto bail;
++ }
++ ret = wr_byte(dd, regnum);
++ stop_cmd(dd);
++ if (ret) {
++ ipath_dev_err(dd, "Failed tempsense WR command %02X\n",
++ regnum);
++ ret = -ENXIO;
++ goto bail;
++ }
++ if (i2c_startcmd(dd, icd->temp_dev | READ_CMD)) {
++ ipath_dbg("Failed tempsense RD startcmd\n");
++ stop_cmd(dd);
++ ret = -ENXIO;
++ goto bail;
++ }
++ /*
++ * We can only clock out one byte per command, sensibly
++ */
++ ret = rd_byte(dd);
++ stop_cmd(dd);
++
++bail:
++ return ret;
++}
++
++#define VALID_TS_RD_REG_MASK 0xBF
++
++/**
++ * ipath_tempsense_read - read register of temp sensor via I2C
++ * @dd: the infinipath device
++ * @regnum: register to read from
++ *
++ * returns reg contents (0..255) or < 0 for error
++ */
++int ipath_tempsense_read(struct ipath_devdata *dd, u8 regnum)
++{
++ int ret;
++
++ if (regnum > 7)
++ return -EINVAL;
++
++ /* return a bogus value for (the one) register we do not have */
++ if (!((1 << regnum) & VALID_TS_RD_REG_MASK))
++ return 0;
++
++ ret = mutex_lock_interruptible(&dd->ipath_eep_lock);
++ if (!ret) {
++ ret = ipath_tempsense_internal_read(dd, regnum);
++ mutex_unlock(&dd->ipath_eep_lock);
++ }
++
++ /*
++ * There are three possibilities here:
++ * ret is actual value (0..255)
++ * ret is -ENXIO or -EINVAL from code in this file
++ * ret is -EINTR from mutex_lock_interruptible.
++ */
++ return ret;
++}
++
++static int ipath_tempsense_internal_write(struct ipath_devdata *dd,
++ u8 regnum, u8 data)
++{
++ int ret = -ENOENT;
++ struct i2c_chain_desc *icd;
++
++ icd = ipath_i2c_type(dd);
++ if (!icd)
++ goto bail;
++
++ if (icd->temp_dev == IPATH_NO_DEV) {
++ /* tempsense only exists on new, real-I2C boards */
++ ret = -ENXIO;
++ goto bail;
++ }
++ if (i2c_startcmd(dd, icd->temp_dev | WRITE_CMD)) {
++ ipath_dbg("Failed tempsense startcmd\n");
++ stop_cmd(dd);
++ ret = -ENXIO;
++ goto bail;
++ }
++ ret = wr_byte(dd, regnum);
++ if (ret) {
++ stop_cmd(dd);
++ ipath_dev_err(dd, "Failed to write tempsense command %02X\n",
++ regnum);
++ ret = -ENXIO;
++ goto bail;
++ }
++ ret = wr_byte(dd, data);
++ stop_cmd(dd);
++ ret = i2c_startcmd(dd, icd->temp_dev | READ_CMD);
++ if (ret) {
++ ipath_dev_err(dd, "Failed tempsense data wrt to %02X\n",
++ regnum);
++ ret = -ENXIO;
++ }
++
++bail:
++ return ret;
++}
++
++#define VALID_TS_WR_REG_MASK ((1 << 9) | (1 << 0xB) | (1 << 0xD))
++
++/**
++ * ipath_tempsense_write - write register of temp sensor via I2C
++ * @dd: the infinipath device
++ * @regnum: register to write
++ * @data: data to write
++ *
++ * returns 0 for success or < 0 for error
++ */
++int ipath_tempsense_write(struct ipath_devdata *dd, u8 regnum, u8 data)
++{
++ int ret;
++
++ if (regnum > 15 || !((1 << regnum) & VALID_TS_WR_REG_MASK))
++ return -EINVAL;
++
++ ret = mutex_lock_interruptible(&dd->ipath_eep_lock);
++ if (!ret) {
++ ret = ipath_tempsense_internal_write(dd, regnum, data);
++ mutex_unlock(&dd->ipath_eep_lock);
++ }
++
++ /*
++ * There are three possibilities here:
++ * ret is 0 for success
++ * ret is -ENXIO or -EINVAL from code in this file
++ * ret is -EINTR from mutex_lock_interruptible.
++ */
++ return ret;
++}
+diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
+index 7e025c8..8b17522 100644
+--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
++++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+@@ -36,21 +36,28 @@
+ #include <linux/cdev.h>
+ #include <linux/swap.h>
+ #include <linux/vmalloc.h>
++#include <linux/highmem.h>
++#include <linux/io.h>
++#include <linux/jiffies.h>
+ #include <asm/pgtable.h>
+
+ #include "ipath_kernel.h"
+ #include "ipath_common.h"
++#include "ipath_user_sdma.h"
+
+ static int ipath_open(struct inode *, struct file *);
+ static int ipath_close(struct inode *, struct file *);
+ static ssize_t ipath_write(struct file *, const char __user *, size_t,
+ loff_t *);
++static ssize_t ipath_writev(struct kiocb *, const struct iovec *,
++ unsigned long , loff_t);
+ static unsigned int ipath_poll(struct file *, struct poll_table_struct *);
+ static int ipath_mmap(struct file *, struct vm_area_struct *);
+
+ static const struct file_operations ipath_file_ops = {
+ .owner = THIS_MODULE,
+ .write = ipath_write,
++ .aio_write = ipath_writev,
+ .open = ipath_open,
+ .release = ipath_close,
+ .poll = ipath_poll,
+@@ -184,6 +191,29 @@ static int ipath_get_base_info(struct file *fp,
+ kinfo->spi_piobufbase = (u64) pd->port_piobufs +
+ dd->ipath_palign * kinfo->spi_piocnt * slave;
+ }
++
++ /*
++ * Set the PIO avail update threshold to no larger
++ * than the number of buffers per process. Note that
++ * we decrease it here, but won't ever increase it.
++ */
++ if (dd->ipath_pioupd_thresh &&
++ kinfo->spi_piocnt < dd->ipath_pioupd_thresh) {
++ unsigned long flags;
++
++ dd->ipath_pioupd_thresh = kinfo->spi_piocnt;
++ ipath_dbg("Decreased pio update threshold to %u\n",
++ dd->ipath_pioupd_thresh);
++ spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++ dd->ipath_sendctrl &= ~(INFINIPATH_S_UPDTHRESH_MASK
++ << INFINIPATH_S_UPDTHRESH_SHIFT);
++ dd->ipath_sendctrl |= dd->ipath_pioupd_thresh
++ << INFINIPATH_S_UPDTHRESH_SHIFT;
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
++ dd->ipath_sendctrl);
++ spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++ }
++
+ if (shared) {
+ kinfo->spi_port_uregbase = (u64) dd->ipath_uregbase +
+ dd->ipath_ureg_align * pd->port_port;
+@@ -219,7 +249,12 @@ static int ipath_get_base_info(struct file *fp,
+ kinfo->spi_pioalign = dd->ipath_palign;
+
+ kinfo->spi_qpair = IPATH_KD_QP;
+- kinfo->spi_piosize = dd->ipath_ibmaxlen;
++ /*
++ * user mode PIO buffers are always 2KB, even when 4KB can
++ * be received, and sent via the kernel; this is ibmaxlen
++ * for 2K MTU.
++ */
++ kinfo->spi_piosize = dd->ipath_piosize2k - 2 * sizeof(u32);
+ kinfo->spi_mtu = dd->ipath_ibmaxlen; /* maxlen, not ibmtu */
+ kinfo->spi_port = pd->port_port;
+ kinfo->spi_subport = subport_fp(fp);
+@@ -1598,6 +1633,9 @@ static int try_alloc_port(struct ipath_devdata *dd, int port,
+ port_fp(fp) = pd;
+ pd->port_pid = current->pid;
+ strncpy(pd->port_comm, current->comm, sizeof(pd->port_comm));
++ ipath_chg_pioavailkernel(dd,
++ dd->ipath_pbufsport * (pd->port_port - 1),
++ dd->ipath_pbufsport, 0);
+ ipath_stats.sps_ports++;
+ ret = 0;
+ } else
+@@ -1760,7 +1798,7 @@ static int find_shared_port(struct file *fp,
+ for (ndev = 0; ndev < devmax; ndev++) {
+ struct ipath_devdata *dd = ipath_lookup(ndev);
+
+- if (!dd)
++ if (!usable(dd))
+ continue;
+ for (i = 1; i < dd->ipath_cfgports; i++) {
+ struct ipath_portdata *pd = dd->ipath_pd[i];
+@@ -1839,10 +1877,9 @@ static int ipath_assign_port(struct file *fp,
+ if (ipath_compatible_subports(swmajor, swminor) &&
+ uinfo->spu_subport_cnt &&
+ (ret = find_shared_port(fp, uinfo))) {
+- mutex_unlock(&ipath_mutex);
+ if (ret > 0)
+ ret = 0;
+- goto done;
++ goto done_chk_sdma;
+ }
+
+ i_minor = iminor(fp->f_path.dentry->d_inode) - IPATH_USER_MINOR_BASE;
+@@ -1854,6 +1891,21 @@ static int ipath_assign_port(struct file *fp,
+ else
+ ret = find_best_unit(fp, uinfo);
+
++done_chk_sdma:
++ if (!ret) {
++ struct ipath_filedata *fd = fp->private_data;
++ const struct ipath_portdata *pd = fd->pd;
++ const struct ipath_devdata *dd = pd->port_dd;
++
++ fd->pq = ipath_user_sdma_queue_create(&dd->pcidev->dev,
++ dd->ipath_unit,
++ pd->port_port,
++ fd->subport);
++
++ if (!fd->pq)
++ ret = -ENOMEM;
++ }
++
+ mutex_unlock(&ipath_mutex);
+
+ done:
+@@ -1922,22 +1974,25 @@ static int ipath_do_user_init(struct file *fp,
+ pd->port_hdrqfull_poll = pd->port_hdrqfull;
+
+ /*
+- * now enable the port; the tail registers will be written to memory
+- * by the chip as soon as it sees the write to
+- * dd->ipath_kregs->kr_rcvctrl. The update only happens on
+- * transition from 0 to 1, so clear it first, then set it as part of
+- * enabling the port. This will (very briefly) affect any other
+- * open ports, but it shouldn't be long enough to be an issue.
+- * We explictly set the in-memory copy to 0 beforehand, so we don't
+- * have to wait to be sure the DMA update has happened.
++ * Now enable the port for receive.
++ * For chips that are set to DMA the tail register to memory
++ * when they change (and when the update bit transitions from
++ * 0 to 1. So for those chips, we turn it off and then back on.
++ * This will (very briefly) affect any other open ports, but the
++ * duration is very short, and therefore isn't an issue. We
++ * explictly set the in-memory tail copy to 0 beforehand, so we
++ * don't have to wait to be sure the DMA update has happened
++ * (chip resets head/tail to 0 on transition to enable).
+ */
+- if (pd->port_rcvhdrtail_kvaddr)
+- ipath_clear_rcvhdrtail(pd);
+ set_bit(dd->ipath_r_portenable_shift + pd->port_port,
+ &dd->ipath_rcvctrl);
+- ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
++ if (!(dd->ipath_flags & IPATH_NODMA_RTAIL)) {
++ if (pd->port_rcvhdrtail_kvaddr)
++ ipath_clear_rcvhdrtail(pd);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl &
+ ~(1ULL << dd->ipath_r_tailupd_shift));
++ }
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl);
+ /* Notify any waiting slaves */
+@@ -1965,14 +2020,15 @@ static void unlock_expected_tids(struct ipath_portdata *pd)
+ ipath_cdbg(VERBOSE, "Port %u unlocking any locked expTID pages\n",
+ pd->port_port);
+ for (i = port_tidbase; i < maxtid; i++) {
+- if (!dd->ipath_pageshadow[i])
++ struct page *ps = dd->ipath_pageshadow[i];
++
++ if (!ps)
+ continue;
+
++ dd->ipath_pageshadow[i] = NULL;
+ pci_unmap_page(dd->pcidev, dd->ipath_physshadow[i],
+ PAGE_SIZE, PCI_DMA_FROMDEVICE);
+- ipath_release_user_pages_on_close(&dd->ipath_pageshadow[i],
+- 1);
+- dd->ipath_pageshadow[i] = NULL;
++ ipath_release_user_pages_on_close(&ps, 1);
+ cnt++;
+ ipath_stats.sps_pageunlocks++;
+ }
+@@ -2007,6 +2063,13 @@ static int ipath_close(struct inode *in, struct file *fp)
+ mutex_unlock(&ipath_mutex);
+ goto bail;
+ }
++
++ dd = pd->port_dd;
++
++ /* drain user sdma queue */
++ ipath_user_sdma_queue_drain(dd, fd->pq);
++ ipath_user_sdma_queue_destroy(fd->pq);
++
+ if (--pd->port_cnt) {
+ /*
+ * XXX If the master closes the port before the slave(s),
+@@ -2019,7 +2082,6 @@ static int ipath_close(struct inode *in, struct file *fp)
+ goto bail;
+ }
+ port = pd->port_port;
+- dd = pd->port_dd;
+
+ if (pd->port_hdrqfull) {
+ ipath_cdbg(PROC, "%s[%u] had %u rcvhdrqfull errors "
+@@ -2039,7 +2101,7 @@ static int ipath_close(struct inode *in, struct file *fp)
+ pd->port_rcvnowait = pd->port_pionowait = 0;
+ }
+ if (pd->port_flag) {
+- ipath_dbg("port %u port_flag still set to 0x%lx\n",
++ ipath_cdbg(PROC, "port %u port_flag set: 0x%lx\n",
+ pd->port_port, pd->port_flag);
+ pd->port_flag = 0;
+ }
+@@ -2076,6 +2138,7 @@ static int ipath_close(struct inode *in, struct file *fp)
+
+ i = dd->ipath_pbufsport * (port - 1);
+ ipath_disarm_piobufs(dd, i, dd->ipath_pbufsport);
++ ipath_chg_pioavailkernel(dd, i, dd->ipath_pbufsport, 1);
+
+ dd->ipath_f_clear_tids(dd, pd->port_port);
+
+@@ -2140,17 +2203,31 @@ static int ipath_get_slave_info(struct ipath_portdata *pd,
+ return ret;
+ }
+
+-static int ipath_force_pio_avail_update(struct ipath_devdata *dd)
++static int ipath_sdma_get_inflight(struct ipath_user_sdma_queue *pq,
++ u32 __user *inflightp)
+ {
+- unsigned long flags;
++ const u32 val = ipath_user_sdma_inflight_counter(pq);
+
+- spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
+- ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+- dd->ipath_sendctrl & ~INFINIPATH_S_PIOBUFAVAILUPD);
+- ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+- ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
+- ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+- spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++ if (put_user(val, inflightp))
++ return -EFAULT;
++
++ return 0;
++}
++
++static int ipath_sdma_get_complete(struct ipath_devdata *dd,
++ struct ipath_user_sdma_queue *pq,
++ u32 __user *completep)
++{
++ u32 val;
++ int err;
++
++ err = ipath_user_sdma_make_progress(dd, pq);
++ if (err < 0)
++ return err;
++
++ val = ipath_user_sdma_complete_counter(pq);
++ if (put_user(val, completep))
++ return -EFAULT;
+
+ return 0;
+ }
+@@ -2229,6 +2306,16 @@ static ssize_t ipath_write(struct file *fp, const char __user *data,
+ dest = &cmd.cmd.armlaunch_ctrl;
+ src = &ucmd->cmd.armlaunch_ctrl;
+ break;
++ case IPATH_CMD_SDMA_INFLIGHT:
++ copy = sizeof(cmd.cmd.sdma_inflight);
++ dest = &cmd.cmd.sdma_inflight;
++ src = &ucmd->cmd.sdma_inflight;
++ break;
++ case IPATH_CMD_SDMA_COMPLETE:
++ copy = sizeof(cmd.cmd.sdma_complete);
++ dest = &cmd.cmd.sdma_complete;
++ src = &ucmd->cmd.sdma_complete;
++ break;
+ default:
+ ret = -EINVAL;
+ goto bail;
+@@ -2299,7 +2386,7 @@ static ssize_t ipath_write(struct file *fp, const char __user *data,
+ cmd.cmd.slave_mask_addr);
+ break;
+ case IPATH_CMD_PIOAVAILUPD:
+- ret = ipath_force_pio_avail_update(pd->port_dd);
++ ipath_force_pio_avail_update(pd->port_dd);
+ break;
+ case IPATH_CMD_POLL_TYPE:
+ pd->poll_type = cmd.cmd.poll_type;
+@@ -2310,6 +2397,17 @@ static ssize_t ipath_write(struct file *fp, const char __user *data,
+ else
+ ipath_disable_armlaunch(pd->port_dd);
+ break;
++ case IPATH_CMD_SDMA_INFLIGHT:
++ ret = ipath_sdma_get_inflight(user_sdma_queue_fp(fp),
++ (u32 __user *) (unsigned long)
++ cmd.cmd.sdma_inflight);
++ break;
++ case IPATH_CMD_SDMA_COMPLETE:
++ ret = ipath_sdma_get_complete(pd->port_dd,
++ user_sdma_queue_fp(fp),
++ (u32 __user *) (unsigned long)
++ cmd.cmd.sdma_complete);
++ break;
+ }
+
+ if (ret >= 0)
+@@ -2319,14 +2417,28 @@ bail:
+ return ret;
+ }
+
++static ssize_t ipath_writev(struct kiocb *iocb, const struct iovec *iov,
++ unsigned long dim, loff_t off)
++{
++ struct file *filp = iocb->ki_filp;
++ struct ipath_filedata *fp = filp->private_data;
++ struct ipath_portdata *pd = port_fp(filp);
++ struct ipath_user_sdma_queue *pq = fp->pq;
++
++ if (!dim)
++ return -EINVAL;
++
++ return ipath_user_sdma_writev(pd->port_dd, pq, iov, dim);
++}
++
+ static struct class *ipath_class;
+
+ static int init_cdev(int minor, char *name, const struct file_operations *fops,
+- struct cdev **cdevp, struct class_device **class_devp)
++ struct cdev **cdevp, struct device **devp)
+ {
+ const dev_t dev = MKDEV(IPATH_MAJOR, minor);
+ struct cdev *cdev = NULL;
+- struct class_device *class_dev = NULL;
++ struct device *device = NULL;
+ int ret;
+
+ cdev = cdev_alloc();
+@@ -2350,12 +2462,12 @@ static int init_cdev(int minor, char *name, const struct file_operations *fops,
+ goto err_cdev;
+ }
+
+- class_dev = class_device_create(ipath_class, NULL, dev, NULL, name);
++ device = device_create(ipath_class, NULL, dev, name);
+
+- if (IS_ERR(class_dev)) {
+- ret = PTR_ERR(class_dev);
++ if (IS_ERR(device)) {
++ ret = PTR_ERR(device);
+ printk(KERN_ERR IPATH_DRV_NAME ": Could not create "
+- "class_dev for minor %d, %s (err %d)\n",
++ "device for minor %d, %s (err %d)\n",
+ minor, name, -ret);
+ goto err_cdev;
+ }
+@@ -2369,29 +2481,29 @@ err_cdev:
+ done:
+ if (ret >= 0) {
+ *cdevp = cdev;
+- *class_devp = class_dev;
++ *devp = device;
+ } else {
+ *cdevp = NULL;
+- *class_devp = NULL;
++ *devp = NULL;
+ }
+
+ return ret;
+ }
+
+ int ipath_cdev_init(int minor, char *name, const struct file_operations *fops,
+- struct cdev **cdevp, struct class_device **class_devp)
++ struct cdev **cdevp, struct device **devp)
+ {
+- return init_cdev(minor, name, fops, cdevp, class_devp);
++ return init_cdev(minor, name, fops, cdevp, devp);
+ }
+
+ static void cleanup_cdev(struct cdev **cdevp,
+- struct class_device **class_devp)
++ struct device **devp)
+ {
+- struct class_device *class_dev = *class_devp;
++ struct device *dev = *devp;
+
+- if (class_dev) {
+- class_device_unregister(class_dev);
+- *class_devp = NULL;
++ if (dev) {
++ device_unregister(dev);
++ *devp = NULL;
+ }
+
+ if (*cdevp) {
+@@ -2401,13 +2513,13 @@ static void cleanup_cdev(struct cdev **cdevp,
+ }
+
+ void ipath_cdev_cleanup(struct cdev **cdevp,
+- struct class_device **class_devp)
++ struct device **devp)
+ {
+- cleanup_cdev(cdevp, class_devp);
++ cleanup_cdev(cdevp, devp);
+ }
+
+ static struct cdev *wildcard_cdev;
+-static struct class_device *wildcard_class_dev;
++static struct device *wildcard_dev;
+
+ static const dev_t dev = MKDEV(IPATH_MAJOR, 0);
+
+@@ -2464,7 +2576,7 @@ int ipath_user_add(struct ipath_devdata *dd)
+ goto bail;
+ }
+ ret = init_cdev(0, "ipath", &ipath_file_ops, &wildcard_cdev,
+- &wildcard_class_dev);
++ &wildcard_dev);
+ if (ret < 0) {
+ ipath_dev_err(dd, "Could not create wildcard "
+ "minor: error %d\n", -ret);
+@@ -2477,7 +2589,7 @@ int ipath_user_add(struct ipath_devdata *dd)
+ snprintf(name, sizeof(name), "ipath%d", dd->ipath_unit);
+
+ ret = init_cdev(dd->ipath_unit + 1, name, &ipath_file_ops,
+- &dd->user_cdev, &dd->user_class_dev);
++ &dd->user_cdev, &dd->user_dev);
+ if (ret < 0)
+ ipath_dev_err(dd, "Could not create user minor %d, %s\n",
+ dd->ipath_unit + 1, name);
+@@ -2492,13 +2604,13 @@ bail:
+
+ void ipath_user_remove(struct ipath_devdata *dd)
+ {
+- cleanup_cdev(&dd->user_cdev, &dd->user_class_dev);
++ cleanup_cdev(&dd->user_cdev, &dd->user_dev);
+
+ if (atomic_dec_return(&user_count) == 0) {
+ if (atomic_read(&user_setup) == 0)
+ goto bail;
+
+- cleanup_cdev(&wildcard_cdev, &wildcard_class_dev);
++ cleanup_cdev(&wildcard_cdev, &wildcard_dev);
+ user_cleanup();
+
+ atomic_set(&user_setup, 0);
+diff --git a/drivers/infiniband/hw/ipath/ipath_iba6110.c b/drivers/infiniband/hw/ipath/ipath_iba6110.c
+index 9e2ced3..02831ad 100644
+--- a/drivers/infiniband/hw/ipath/ipath_iba6110.c
++++ b/drivers/infiniband/hw/ipath/ipath_iba6110.c
+@@ -40,6 +40,7 @@
+ #include <linux/pci.h>
+ #include <linux/delay.h>
+ #include <linux/htirq.h>
++#include <rdma/ib_verbs.h>
+
+ #include "ipath_kernel.h"
+ #include "ipath_registers.h"
+@@ -305,7 +306,9 @@ static const struct ipath_cregs ipath_ht_cregs = {
+
+ /* kr_intstatus, kr_intclear, kr_intmask bits */
+ #define INFINIPATH_I_RCVURG_MASK ((1U<<9)-1)
++#define INFINIPATH_I_RCVURG_SHIFT 0
+ #define INFINIPATH_I_RCVAVAIL_MASK ((1U<<9)-1)
++#define INFINIPATH_I_RCVAVAIL_SHIFT 12
+
+ /* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */
+ #define INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT 0
+@@ -476,7 +479,13 @@ static const struct ipath_hwerror_msgs ipath_6110_hwerror_msgs[] = {
+ #define RXE_EAGER_PARITY (INFINIPATH_HWE_RXEMEMPARITYERR_EAGERTID \
+ << INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT)
+
+-static int ipath_ht_txe_recover(struct ipath_devdata *);
++static void ipath_ht_txe_recover(struct ipath_devdata *dd)
++{
++ ++ipath_stats.sps_txeparity;
++ dev_info(&dd->pcidev->dev,
++ "Recovering from TXE PIO parity error\n");
++}
++
+
+ /**
+ * ipath_ht_handle_hwerrors - display hardware errors.
+@@ -557,11 +566,11 @@ static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg,
+ * occur if a processor speculative read is done to the PIO
+ * buffer while we are sending a packet, for example.
+ */
+- if ((hwerrs & TXE_PIO_PARITY) && ipath_ht_txe_recover(dd))
++ if (hwerrs & TXE_PIO_PARITY) {
++ ipath_ht_txe_recover(dd);
+ hwerrs &= ~TXE_PIO_PARITY;
+- if (hwerrs & RXE_EAGER_PARITY)
+- ipath_dev_err(dd, "RXE parity, Eager TID error is not "
+- "recoverable\n");
++ }
++
+ if (!hwerrs) {
+ ipath_dbg("Clearing freezemode on ignored or "
+ "recovered hardware error\n");
+@@ -735,11 +744,10 @@ static int ipath_ht_boardname(struct ipath_devdata *dd, char *name,
+ */
+ dd->ipath_flags |= IPATH_32BITCOUNTERS;
+ dd->ipath_flags |= IPATH_GPIO_INTR;
+- if (dd->ipath_htspeed != 800)
++ if (dd->ipath_lbus_speed != 800)
+ ipath_dev_err(dd,
+ "Incorrectly configured for HT @ %uMHz\n",
+- dd->ipath_htspeed);
+- ret = 0;
++ dd->ipath_lbus_speed);
+
+ /*
+ * set here, not in ipath_init_*_funcs because we have to do
+@@ -839,7 +847,7 @@ static void slave_or_pri_blk(struct ipath_devdata *dd, struct pci_dev *pdev,
+ /*
+ * now write them back to clear the error.
+ */
+- pci_write_config_byte(pdev, link_off,
++ pci_write_config_word(pdev, link_off,
+ linkctrl & (0xf << 8));
+ }
+ }
+@@ -904,7 +912,7 @@ static void slave_or_pri_blk(struct ipath_devdata *dd, struct pci_dev *pdev,
+ break;
+ }
+
+- dd->ipath_htwidth = width;
++ dd->ipath_lbus_width = width;
+
+ if (linkwidth != 0x11) {
+ ipath_dev_err(dd, "Not configured for 16 bit HT "
+@@ -952,8 +960,13 @@ static void slave_or_pri_blk(struct ipath_devdata *dd, struct pci_dev *pdev,
+ speed = 200;
+ break;
+ }
+- dd->ipath_htspeed = speed;
++ dd->ipath_lbus_speed = speed;
+ }
++
++ snprintf(dd->ipath_lbus_info, sizeof(dd->ipath_lbus_info),
++ "HyperTransport,%uMHz,x%u\n",
++ dd->ipath_lbus_speed,
++ dd->ipath_lbus_width);
+ }
+
+ static int ipath_ht_intconfig(struct ipath_devdata *dd)
+@@ -1653,22 +1666,6 @@ static int ipath_ht_early_init(struct ipath_devdata *dd)
+ }
+
+
+-static int ipath_ht_txe_recover(struct ipath_devdata *dd)
+-{
+- int cnt = ++ipath_stats.sps_txeparity;
+- if (cnt >= IPATH_MAX_PARITY_ATTEMPTS) {
+- if (cnt == IPATH_MAX_PARITY_ATTEMPTS)
+- ipath_dev_err(dd,
+- "Too many attempts to recover from "
+- "TXE parity, giving up\n");
+- return 0;
+- }
+- dev_info(&dd->pcidev->dev,
+- "Recovering from TXE PIO parity error\n");
+- return 1;
+-}
+-
+-
+ /**
+ * ipath_init_ht_get_base_info - set chip-specific flags for user code
+ * @dd: the infinipath device
+diff --git a/drivers/infiniband/hw/ipath/ipath_iba6120.c b/drivers/infiniband/hw/ipath/ipath_iba6120.c
+index c7a2f50..421cc2a 100644
+--- a/drivers/infiniband/hw/ipath/ipath_iba6120.c
++++ b/drivers/infiniband/hw/ipath/ipath_iba6120.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+@@ -38,7 +38,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/pci.h>
+ #include <linux/delay.h>
+-
++#include <rdma/ib_verbs.h>
+
+ #include "ipath_kernel.h"
+ #include "ipath_registers.h"
+@@ -311,9 +311,14 @@ static const struct ipath_cregs ipath_pe_cregs = {
+ .cr_ibsymbolerrcnt = IPATH_CREG_OFFSET(IBSymbolErrCnt)
+ };
+
++/* kr_control bits */
++#define INFINIPATH_C_RESET 1U
++
+ /* kr_intstatus, kr_intclear, kr_intmask bits */
+ #define INFINIPATH_I_RCVURG_MASK ((1U<<5)-1)
++#define INFINIPATH_I_RCVURG_SHIFT 0
+ #define INFINIPATH_I_RCVAVAIL_MASK ((1U<<5)-1)
++#define INFINIPATH_I_RCVAVAIL_SHIFT 12
+
+ /* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */
+ #define INFINIPATH_HWE_PCIEMEMPARITYERR_MASK 0x000000000000003fULL
+@@ -338,6 +343,9 @@ static const struct ipath_cregs ipath_pe_cregs = {
+ #define INFINIPATH_EXTS_MEMBIST_ENDTEST 0x0000000000004000
+ #define INFINIPATH_EXTS_MEMBIST_FOUND 0x0000000000008000
+
++/* kr_xgxsconfig bits */
++#define INFINIPATH_XGXS_RESET 0x5ULL
++
+ #define _IPATH_GPIO_SDA_NUM 1
+ #define _IPATH_GPIO_SCL_NUM 0
+
+@@ -346,6 +354,16 @@ static const struct ipath_cregs ipath_pe_cregs = {
+ #define IPATH_GPIO_SCL (1ULL << \
+ (_IPATH_GPIO_SCL_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
+
++#define INFINIPATH_RT_BUFSIZE_MASK 0xe0000000ULL
++#define INFINIPATH_RT_BUFSIZE_SHIFTVAL(tid) \
++ ((((tid) & INFINIPATH_RT_BUFSIZE_MASK) >> 29) + 11 - 1)
++#define INFINIPATH_RT_BUFSIZE(tid) (1 << INFINIPATH_RT_BUFSIZE_SHIFTVAL(tid))
++#define INFINIPATH_RT_IS_VALID(tid) \
++ (((tid) & INFINIPATH_RT_BUFSIZE_MASK) && \
++ ((((tid) & INFINIPATH_RT_BUFSIZE_MASK) != INFINIPATH_RT_BUFSIZE_MASK)))
++#define INFINIPATH_RT_ADDR_MASK 0x1FFFFFFFULL /* 29 bits valid */
++#define INFINIPATH_RT_ADDR_SHIFT 10
++
+ #define INFINIPATH_R_INTRAVAIL_SHIFT 16
+ #define INFINIPATH_R_TAILUPD_SHIFT 31
+
+@@ -372,6 +390,8 @@ static const struct ipath_hwerror_msgs ipath_6120_hwerror_msgs[] = {
+ #define TXE_PIO_PARITY ((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF | \
+ INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC) \
+ << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT)
++#define RXE_EAGER_PARITY (INFINIPATH_HWE_RXEMEMPARITYERR_EAGERTID \
++ << INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT)
+
+ static void ipath_pe_put_tid_2(struct ipath_devdata *, u64 __iomem *,
+ u32, unsigned long);
+@@ -450,10 +470,8 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
+ * make sure we get this much out, unless told to be quiet,
+ * or it's occurred within the last 5 seconds
+ */
+- if ((hwerrs & ~(dd->ipath_lasthwerror |
+- ((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF |
+- INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC)
+- << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT))) ||
++ if ((hwerrs & ~(dd->ipath_lasthwerror | TXE_PIO_PARITY |
++ RXE_EAGER_PARITY)) ||
+ (ipath_debug & __IPATH_VERBDBG))
+ dev_info(&dd->pcidev->dev, "Hardware error: hwerr=0x%llx "
+ "(cleared)\n", (unsigned long long) hwerrs);
+@@ -465,7 +483,7 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
+ (hwerrs & ~dd->ipath_hwe_bitsextant));
+
+ ctrl = ipath_read_kreg32(dd, dd->ipath_kregs->kr_control);
+- if (ctrl & INFINIPATH_C_FREEZEMODE) {
++ if ((ctrl & INFINIPATH_C_FREEZEMODE) && !ipath_diag_inuse) {
+ /*
+ * parity errors in send memory are recoverable,
+ * just cancel the send (if indicated in * sendbuffererror),
+@@ -540,12 +558,40 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
+ dd->ipath_hwerrmask);
+ }
+
+- if (*msg)
++ if (hwerrs) {
++ /*
++ * if any set that we aren't ignoring; only
++ * make the complaint once, in case it's stuck
++ * or recurring, and we get here multiple
++ * times.
++ */
+ ipath_dev_err(dd, "%s hardware error\n", msg);
+- if (isfatal && !ipath_diag_inuse && dd->ipath_freezemsg) {
++ if (dd->ipath_flags & IPATH_INITTED) {
++ ipath_set_linkstate(dd, IPATH_IB_LINKDOWN);
++ ipath_setup_pe_setextled(dd,
++ INFINIPATH_IBCS_L_STATE_DOWN,
++ INFINIPATH_IBCS_LT_STATE_DISABLED);
++ ipath_dev_err(dd, "Fatal Hardware Error (freeze "
++ "mode), no longer usable, SN %.16s\n",
++ dd->ipath_serial);
++ isfatal = 1;
++ }
++ *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
++ /* mark as having had error */
++ *dd->ipath_statusp |= IPATH_STATUS_HWERROR;
+ /*
+- * for /sys status file ; if no trailing } is copied, we'll
+- * know it was truncated.
++ * mark as not usable, at a minimum until driver
++ * is reloaded, probably until reboot, since no
++ * other reset is possible.
++ */
++ dd->ipath_flags &= ~IPATH_INITTED;
++ } else
++ *msg = 0; /* recovered from all of them */
++
++ if (isfatal && !ipath_diag_inuse && dd->ipath_freezemsg && msg) {
++ /*
++ * for /sys status file ; if no trailing brace is copied,
++ * we'll know it was truncated.
+ */
+ snprintf(dd->ipath_freezemsg, dd->ipath_freezelen,
+ "{%s}", msg);
+@@ -610,7 +656,6 @@ static int ipath_pe_boardname(struct ipath_devdata *dd, char *name,
+ dd->ipath_f_put_tid = ipath_pe_put_tid_2;
+ }
+
+-
+ /*
+ * set here, not in ipath_init_*_funcs because we have to do
+ * it after we can read chip registers.
+@@ -838,7 +883,7 @@ static void ipath_setup_pe_setextled(struct ipath_devdata *dd, u64 lst,
+ extctl = dd->ipath_extctrl & ~(INFINIPATH_EXTC_LED1PRIPORT_ON |
+ INFINIPATH_EXTC_LED2PRIPORT_ON);
+
+- if (ltst & INFINIPATH_IBCS_LT_STATE_LINKUP)
++ if (ltst == INFINIPATH_IBCS_LT_STATE_LINKUP)
+ extctl |= INFINIPATH_EXTC_LED2PRIPORT_ON;
+ if (lst == INFINIPATH_IBCS_L_STATE_ACTIVE)
+ extctl |= INFINIPATH_EXTC_LED1PRIPORT_ON;
+@@ -863,6 +908,62 @@ static void ipath_setup_pe_cleanup(struct ipath_devdata *dd)
+ pci_disable_msi(dd->pcidev);
+ }
+
++static void ipath_6120_pcie_params(struct ipath_devdata *dd)
++{
++ u16 linkstat, speed;
++ int pos;
++
++ pos = pci_find_capability(dd->pcidev, PCI_CAP_ID_EXP);
++ if (!pos) {
++ ipath_dev_err(dd, "Can't find PCI Express capability!\n");
++ goto bail;
++ }
++
++ pci_read_config_word(dd->pcidev, pos + PCI_EXP_LNKSTA,
++ &linkstat);
++ /*
++ * speed is bits 0-4, linkwidth is bits 4-8
++ * no defines for them in headers
++ */
++ speed = linkstat & 0xf;
++ linkstat >>= 4;
++ linkstat &= 0x1f;
++ dd->ipath_lbus_width = linkstat;
++
++ switch (speed) {
++ case 1:
++ dd->ipath_lbus_speed = 2500; /* Gen1, 2.5GHz */
++ break;
++ case 2:
++ dd->ipath_lbus_speed = 5000; /* Gen1, 5GHz */
++ break;
++ default: /* not defined, assume gen1 */
++ dd->ipath_lbus_speed = 2500;
++ break;
++ }
++
++ if (linkstat < 8)
++ ipath_dev_err(dd,
++ "PCIe width %u (x8 HCA), performance reduced\n",
++ linkstat);
++ else
++ ipath_cdbg(VERBOSE, "PCIe speed %u width %u (x8 HCA)\n",
++ dd->ipath_lbus_speed, linkstat);
++
++ if (speed != 1)
++ ipath_dev_err(dd,
++ "PCIe linkspeed %u is incorrect; "
++ "should be 1 (2500)!\n", speed);
++bail:
++ /* fill in string, even on errors */
++ snprintf(dd->ipath_lbus_info, sizeof(dd->ipath_lbus_info),
++ "PCIe,%uMHz,x%u\n",
++ dd->ipath_lbus_speed,
++ dd->ipath_lbus_width);
++
++ return;
++}
++
+ /**
+ * ipath_setup_pe_config - setup PCIe config related stuff
+ * @dd: the infinipath device
+@@ -920,19 +1021,8 @@ static int ipath_setup_pe_config(struct ipath_devdata *dd,
+ } else
+ ipath_dev_err(dd, "Can't find MSI capability, "
+ "can't save MSI settings for reset\n");
+- if ((pos = pci_find_capability(dd->pcidev, PCI_CAP_ID_EXP))) {
+- u16 linkstat;
+- pci_read_config_word(dd->pcidev, pos + PCI_EXP_LNKSTA,
+- &linkstat);
+- linkstat >>= 4;
+- linkstat &= 0x1f;
+- if (linkstat != 8)
+- ipath_dev_err(dd, "PCIe width %u, "
+- "performance reduced\n", linkstat);
+- }
+- else
+- ipath_dev_err(dd, "Can't find PCI Express "
+- "capability!\n");
++
++ ipath_6120_pcie_params(dd);
+
+ dd->ipath_link_width_supported = IB_WIDTH_1X | IB_WIDTH_4X;
+ dd->ipath_link_speed_supported = IPATH_IB_SDR;
+@@ -1065,10 +1155,7 @@ static void ipath_init_pe_variables(struct ipath_devdata *dd)
+ INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
+ INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT;
+
+- dd->ipath_eep_st_masks[2].errs_to_log =
+- INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET;
+-
+-
++ dd->ipath_eep_st_masks[2].errs_to_log = INFINIPATH_E_RESET;
+ dd->delay_mult = 2; /* SDR, 4X, can't change */
+ }
+
+@@ -1142,6 +1229,9 @@ static int ipath_setup_pe_reset(struct ipath_devdata *dd)
+ u64 val;
+ int i;
+ int ret;
++ u16 cmdval;
++
++ pci_read_config_word(dd->pcidev, PCI_COMMAND, &cmdval);
+
+ /* Use ERROR so it shows up in logs, etc. */
+ ipath_dev_err(dd, "Resetting InfiniPath unit %u\n", dd->ipath_unit);
+@@ -1169,10 +1259,14 @@ static int ipath_setup_pe_reset(struct ipath_devdata *dd)
+ ipath_dev_err(dd, "rewrite of BAR1 failed: %d\n",
+ r);
+ /* now re-enable memory access */
++ pci_write_config_word(dd->pcidev, PCI_COMMAND, cmdval);
+ if ((r = pci_enable_device(dd->pcidev)))
+ ipath_dev_err(dd, "pci_enable_device failed after "
+ "reset: %d\n", r);
+- /* whether it worked or not, mark as present, again */
++ /*
++ * whether it fully enabled or not, mark as present,
++ * again (but not INITTED)
++ */
+ dd->ipath_flags |= IPATH_PRESENT;
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_revision);
+ if (val == dd->ipath_revision) {
+@@ -1190,6 +1284,8 @@ static int ipath_setup_pe_reset(struct ipath_devdata *dd)
+ ret = 0; /* failed */
+
+ bail:
++ if (ret)
++ ipath_6120_pcie_params(dd);
+ return ret;
+ }
+
+@@ -1209,16 +1305,21 @@ static void ipath_pe_put_tid(struct ipath_devdata *dd, u64 __iomem *tidptr,
+ {
+ u32 __iomem *tidp32 = (u32 __iomem *)tidptr;
+ unsigned long flags = 0; /* keep gcc quiet */
++ int tidx;
++ spinlock_t *tidlockp;
++
++ if (!dd->ipath_kregbase)
++ return;
+
+ if (pa != dd->ipath_tidinvalid) {
+ if (pa & ((1U << 11) - 1)) {
+ dev_info(&dd->pcidev->dev, "BUG: physaddr %lx "
+- "not 4KB aligned!\n", pa);
++ "not 2KB aligned!\n", pa);
+ return;
+ }
+ pa >>= 11;
+ /* paranoia check */
+- if (pa & (7<<29))
++ if (pa & ~INFINIPATH_RT_ADDR_MASK)
+ ipath_dev_err(dd,
+ "BUG: Physical page address 0x%lx "
+ "has bits set in 31-29\n", pa);
+@@ -1238,14 +1339,22 @@ static void ipath_pe_put_tid(struct ipath_devdata *dd, u64 __iomem *tidptr,
+ * call can be done from interrupt level for the port 0 eager TIDs,
+ * so we have to use irqsave locks.
+ */
+- spin_lock_irqsave(&dd->ipath_tid_lock, flags);
++ /*
++ * Assumes tidptr always > ipath_egrtidbase
++ * if type == RCVHQ_RCV_TYPE_EAGER.
++ */
++ tidx = tidptr - dd->ipath_egrtidbase;
++
++ tidlockp = (type == RCVHQ_RCV_TYPE_EAGER && tidx < dd->ipath_rcvegrcnt)
++ ? &dd->ipath_kernel_tid_lock : &dd->ipath_user_tid_lock;
++ spin_lock_irqsave(tidlockp, flags);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_scratch, 0xfeeddeaf);
+- if (dd->ipath_kregbase)
+- writel(pa, tidp32);
++ writel(pa, tidp32);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_scratch, 0xdeadbeef);
+ mmiowb();
+- spin_unlock_irqrestore(&dd->ipath_tid_lock, flags);
++ spin_unlock_irqrestore(tidlockp, flags);
+ }
++
+ /**
+ * ipath_pe_put_tid_2 - write a TID in chip, Revision 2 or higher
+ * @dd: the infinipath device
+@@ -1261,6 +1370,10 @@ static void ipath_pe_put_tid_2(struct ipath_devdata *dd, u64 __iomem *tidptr,
+ u32 type, unsigned long pa)
+ {
+ u32 __iomem *tidp32 = (u32 __iomem *)tidptr;
++ u32 tidx;
++
++ if (!dd->ipath_kregbase)
++ return;
+
+ if (pa != dd->ipath_tidinvalid) {
+ if (pa & ((1U << 11) - 1)) {
+@@ -1270,7 +1383,7 @@ static void ipath_pe_put_tid_2(struct ipath_devdata *dd, u64 __iomem *tidptr,
+ }
+ pa >>= 11;
+ /* paranoia check */
+- if (pa & (7<<29))
++ if (pa & ~INFINIPATH_RT_ADDR_MASK)
+ ipath_dev_err(dd,
+ "BUG: Physical page address 0x%lx "
+ "has bits set in 31-29\n", pa);
+@@ -1280,8 +1393,8 @@ static void ipath_pe_put_tid_2(struct ipath_devdata *dd, u64 __iomem *tidptr,
+ else /* for now, always full 4KB page */
+ pa |= 2 << 29;
+ }
+- if (dd->ipath_kregbase)
+- writel(pa, tidp32);
++ tidx = tidptr - dd->ipath_egrtidbase;
++ writel(pa, tidp32);
+ mmiowb();
+ }
+
+@@ -1379,17 +1492,13 @@ static int ipath_pe_early_init(struct ipath_devdata *dd)
+ dd->ipath_egrtidbase = (u64 __iomem *)
+ ((char __iomem *) dd->ipath_kregbase + dd->ipath_rcvegrbase);
+
+- /*
+- * To truly support a 4KB MTU (for usermode), we need to
+- * bump this to a larger value. For now, we use them for
+- * the kernel only.
+- */
+- dd->ipath_rcvegrbufsize = 2048;
++ dd->ipath_rcvegrbufsize = ipath_mtu4096 ? 4096 : 2048;
+ /*
+ * the min() check here is currently a nop, but it may not always
+ * be, depending on just how we do ipath_rcvegrbufsize
+ */
+- dd->ipath_ibmaxlen = min(dd->ipath_piosize2k,
++ dd->ipath_ibmaxlen = min(ipath_mtu4096 ? dd->ipath_piosize4k :
++ dd->ipath_piosize2k,
+ dd->ipath_rcvegrbufsize +
+ (dd->ipath_rcvhdrentsize << 2));
+ dd->ipath_init_ibmaxlen = dd->ipath_ibmaxlen;
+diff --git a/drivers/infiniband/hw/ipath/ipath_iba7220.c b/drivers/infiniband/hw/ipath/ipath_iba7220.c
+new file mode 100644
+index 0000000..e3ec0d1
+--- /dev/null
++++ b/drivers/infiniband/hw/ipath/ipath_iba7220.c
+@@ -0,0 +1,2566 @@
++/*
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses. You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ * Redistribution and use in source and binary forms, with or
++ * without modification, are permitted provided that the following
++ * conditions are met:
++ *
++ * - Redistributions of source code must retain the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer.
++ *
++ * - Redistributions in binary form must reproduce the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer in the documentation and/or other materials
++ * provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++/*
++ * This file contains all of the code that is specific to the
++ * InfiniPath 7220 chip (except that specific to the SerDes)
++ */
++
++#include <linux/interrupt.h>
++#include <linux/pci.h>
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <rdma/ib_verbs.h>
++
++#include "ipath_kernel.h"
++#include "ipath_registers.h"
++#include "ipath_7220.h"
++
++static void ipath_setup_7220_setextled(struct ipath_devdata *, u64, u64);
++
++static unsigned ipath_compat_ddr_negotiate = 1;
++
++module_param_named(compat_ddr_negotiate, ipath_compat_ddr_negotiate, uint,
++ S_IWUSR | S_IRUGO);
++MODULE_PARM_DESC(compat_ddr_negotiate,
++ "Attempt pre-IBTA 1.2 DDR speed negotiation");
++
++static unsigned ipath_sdma_fetch_arb = 1;
++module_param_named(fetch_arb, ipath_sdma_fetch_arb, uint, S_IRUGO);
++MODULE_PARM_DESC(fetch_arb, "IBA7220: change SDMA descriptor arbitration");
++
++/*
++ * This file contains almost all the chip-specific register information and
++ * access functions for the QLogic InfiniPath 7220 PCI-Express chip, with the
++ * exception of SerDes support, which in in ipath_sd7220.c.
++ *
++ * This lists the InfiniPath registers, in the actual chip layout.
++ * This structure should never be directly accessed.
++ */
++struct _infinipath_do_not_use_kernel_regs {
++ unsigned long long Revision;
++ unsigned long long Control;
++ unsigned long long PageAlign;
++ unsigned long long PortCnt;
++ unsigned long long DebugPortSelect;
++ unsigned long long DebugSigsIntSel; /* was Reserved0;*/
++ unsigned long long SendRegBase;
++ unsigned long long UserRegBase;
++ unsigned long long CounterRegBase;
++ unsigned long long Scratch;
++ unsigned long long EEPROMAddrCmd; /* was Reserved1; */
++ unsigned long long EEPROMData; /* was Reserved2; */
++ unsigned long long IntBlocked;
++ unsigned long long IntMask;
++ unsigned long long IntStatus;
++ unsigned long long IntClear;
++ unsigned long long ErrorMask;
++ unsigned long long ErrorStatus;
++ unsigned long long ErrorClear;
++ unsigned long long HwErrMask;
++ unsigned long long HwErrStatus;
++ unsigned long long HwErrClear;
++ unsigned long long HwDiagCtrl;
++ unsigned long long MDIO;
++ unsigned long long IBCStatus;
++ unsigned long long IBCCtrl;
++ unsigned long long ExtStatus;
++ unsigned long long ExtCtrl;
++ unsigned long long GPIOOut;
++ unsigned long long GPIOMask;
++ unsigned long long GPIOStatus;
++ unsigned long long GPIOClear;
++ unsigned long long RcvCtrl;
++ unsigned long long RcvBTHQP;
++ unsigned long long RcvHdrSize;
++ unsigned long long RcvHdrCnt;
++ unsigned long long RcvHdrEntSize;
++ unsigned long long RcvTIDBase;
++ unsigned long long RcvTIDCnt;
++ unsigned long long RcvEgrBase;
++ unsigned long long RcvEgrCnt;
++ unsigned long long RcvBufBase;
++ unsigned long long RcvBufSize;
++ unsigned long long RxIntMemBase;
++ unsigned long long RxIntMemSize;
++ unsigned long long RcvPartitionKey;
++ unsigned long long RcvQPMulticastPort;
++ unsigned long long RcvPktLEDCnt;
++ unsigned long long IBCDDRCtrl;
++ unsigned long long HRTBT_GUID;
++ unsigned long long IB_SDTEST_IF_TX;
++ unsigned long long IB_SDTEST_IF_RX;
++ unsigned long long IBCDDRCtrl2;
++ unsigned long long IBCDDRStatus;
++ unsigned long long JIntReload;
++ unsigned long long IBNCModeCtrl;
++ unsigned long long SendCtrl;
++ unsigned long long SendBufBase;
++ unsigned long long SendBufSize;
++ unsigned long long SendBufCnt;
++ unsigned long long SendAvailAddr;
++ unsigned long long TxIntMemBase;
++ unsigned long long TxIntMemSize;
++ unsigned long long SendDmaBase;
++ unsigned long long SendDmaLenGen;
++ unsigned long long SendDmaTail;
++ unsigned long long SendDmaHead;
++ unsigned long long SendDmaHeadAddr;
++ unsigned long long SendDmaBufMask0;
++ unsigned long long SendDmaBufMask1;
++ unsigned long long SendDmaBufMask2;
++ unsigned long long SendDmaStatus;
++ unsigned long long SendBufferError;
++ unsigned long long SendBufferErrorCONT1;
++ unsigned long long SendBufErr2; /* was Reserved6SBE[0/6] */
++ unsigned long long Reserved6L[2];
++ unsigned long long AvailUpdCount;
++ unsigned long long RcvHdrAddr0;
++ unsigned long long RcvHdrAddrs[16]; /* Why enumerate? */
++ unsigned long long Reserved7hdtl; /* Align next to 300 */
++ unsigned long long RcvHdrTailAddr0; /* 300, like others */
++ unsigned long long RcvHdrTailAddrs[16];
++ unsigned long long Reserved9SW[7]; /* was [8]; we have 17 ports */
++ unsigned long long IbsdEpbAccCtl; /* IB Serdes EPB access control */
++ unsigned long long IbsdEpbTransReg; /* IB Serdes EPB Transaction */
++ unsigned long long Reserved10sds; /* was SerdesStatus on */
++ unsigned long long XGXSConfig;
++ unsigned long long IBSerDesCtrl; /* Was IBPLLCfg on Monty */
++ unsigned long long EEPCtlStat; /* for "boot" EEPROM/FLASH */
++ unsigned long long EEPAddrCmd;
++ unsigned long long EEPData;
++ unsigned long long PcieEpbAccCtl;
++ unsigned long long PcieEpbTransCtl;
++ unsigned long long EfuseCtl; /* E-Fuse control */
++ unsigned long long EfuseData[4];
++ unsigned long long ProcMon;
++ /* this chip moves following two from previous 200, 208 */
++ unsigned long long PCIeRBufTestReg0;
++ unsigned long long PCIeRBufTestReg1;
++ /* added for this chip */
++ unsigned long long PCIeRBufTestReg2;
++ unsigned long long PCIeRBufTestReg3;
++ /* added for this chip, debug only */
++ unsigned long long SPC_JTAG_ACCESS_REG;
++ unsigned long long LAControlReg;
++ unsigned long long GPIODebugSelReg;
++ unsigned long long DebugPortValueReg;
++ /* added for this chip, DMA */
++ unsigned long long SendDmaBufUsed[3];
++ unsigned long long SendDmaReqTagUsed;
++ /*
++ * added for this chip, EFUSE: note that these program 64-bit
++ * words 2 and 3 */
++ unsigned long long efuse_pgm_data[2];
++ unsigned long long Reserved11LAalign[10]; /* Skip 4B0..4F8 */
++ /* we have 30 regs for DDS and RXEQ in IB SERDES */
++ unsigned long long SerDesDDSRXEQ[30];
++ unsigned long long Reserved12LAalign[2]; /* Skip 5F0, 5F8 */
++ /* added for LA debug support */
++ unsigned long long LAMemory[32];
++};
++
++struct _infinipath_do_not_use_counters {
++ __u64 LBIntCnt;
++ __u64 LBFlowStallCnt;
++ __u64 TxSDmaDescCnt; /* was Reserved1 */
++ __u64 TxUnsupVLErrCnt;
++ __u64 TxDataPktCnt;
++ __u64 TxFlowPktCnt;
++ __u64 TxDwordCnt;
++ __u64 TxLenErrCnt;
++ __u64 TxMaxMinLenErrCnt;
++ __u64 TxUnderrunCnt;
++ __u64 TxFlowStallCnt;
++ __u64 TxDroppedPktCnt;
++ __u64 RxDroppedPktCnt;
++ __u64 RxDataPktCnt;
++ __u64 RxFlowPktCnt;
++ __u64 RxDwordCnt;
++ __u64 RxLenErrCnt;
++ __u64 RxMaxMinLenErrCnt;
++ __u64 RxICRCErrCnt;
++ __u64 RxVCRCErrCnt;
++ __u64 RxFlowCtrlErrCnt;
++ __u64 RxBadFormatCnt;
++ __u64 RxLinkProblemCnt;
++ __u64 RxEBPCnt;
++ __u64 RxLPCRCErrCnt;
++ __u64 RxBufOvflCnt;
++ __u64 RxTIDFullErrCnt;
++ __u64 RxTIDValidErrCnt;
++ __u64 RxPKeyMismatchCnt;
++ __u64 RxP0HdrEgrOvflCnt;
++ __u64 RxP1HdrEgrOvflCnt;
++ __u64 RxP2HdrEgrOvflCnt;
++ __u64 RxP3HdrEgrOvflCnt;
++ __u64 RxP4HdrEgrOvflCnt;
++ __u64 RxP5HdrEgrOvflCnt;
++ __u64 RxP6HdrEgrOvflCnt;
++ __u64 RxP7HdrEgrOvflCnt;
++ __u64 RxP8HdrEgrOvflCnt;
++ __u64 RxP9HdrEgrOvflCnt; /* was Reserved6 */
++ __u64 RxP10HdrEgrOvflCnt; /* was Reserved7 */
++ __u64 RxP11HdrEgrOvflCnt; /* new for IBA7220 */
++ __u64 RxP12HdrEgrOvflCnt; /* new for IBA7220 */
++ __u64 RxP13HdrEgrOvflCnt; /* new for IBA7220 */
++ __u64 RxP14HdrEgrOvflCnt; /* new for IBA7220 */
++ __u64 RxP15HdrEgrOvflCnt; /* new for IBA7220 */
++ __u64 RxP16HdrEgrOvflCnt; /* new for IBA7220 */
++ __u64 IBStatusChangeCnt;
++ __u64 IBLinkErrRecoveryCnt;
++ __u64 IBLinkDownedCnt;
++ __u64 IBSymbolErrCnt;
++ /* The following are new for IBA7220 */
++ __u64 RxVL15DroppedPktCnt;
++ __u64 RxOtherLocalPhyErrCnt;
++ __u64 PcieRetryBufDiagQwordCnt;
++ __u64 ExcessBufferOvflCnt;
++ __u64 LocalLinkIntegrityErrCnt;
++ __u64 RxVlErrCnt;
++ __u64 RxDlidFltrCnt;
++ __u64 Reserved8[7];
++ __u64 PSStat;
++ __u64 PSStart;
++ __u64 PSInterval;
++ __u64 PSRcvDataCount;
++ __u64 PSRcvPktsCount;
++ __u64 PSXmitDataCount;
++ __u64 PSXmitPktsCount;
++ __u64 PSXmitWaitCount;
++};
++
++#define IPATH_KREG_OFFSET(field) (offsetof( \
++ struct _infinipath_do_not_use_kernel_regs, field) / sizeof(u64))
++#define IPATH_CREG_OFFSET(field) (offsetof( \
++ struct _infinipath_do_not_use_counters, field) / sizeof(u64))
++
++static const struct ipath_kregs ipath_7220_kregs = {
++ .kr_control = IPATH_KREG_OFFSET(Control),
++ .kr_counterregbase = IPATH_KREG_OFFSET(CounterRegBase),
++ .kr_debugportselect = IPATH_KREG_OFFSET(DebugPortSelect),
++ .kr_errorclear = IPATH_KREG_OFFSET(ErrorClear),
++ .kr_errormask = IPATH_KREG_OFFSET(ErrorMask),
++ .kr_errorstatus = IPATH_KREG_OFFSET(ErrorStatus),
++ .kr_extctrl = IPATH_KREG_OFFSET(ExtCtrl),
++ .kr_extstatus = IPATH_KREG_OFFSET(ExtStatus),
++ .kr_gpio_clear = IPATH_KREG_OFFSET(GPIOClear),
++ .kr_gpio_mask = IPATH_KREG_OFFSET(GPIOMask),
++ .kr_gpio_out = IPATH_KREG_OFFSET(GPIOOut),
++ .kr_gpio_status = IPATH_KREG_OFFSET(GPIOStatus),
++ .kr_hwdiagctrl = IPATH_KREG_OFFSET(HwDiagCtrl),
++ .kr_hwerrclear = IPATH_KREG_OFFSET(HwErrClear),
++ .kr_hwerrmask = IPATH_KREG_OFFSET(HwErrMask),
++ .kr_hwerrstatus = IPATH_KREG_OFFSET(HwErrStatus),
++ .kr_ibcctrl = IPATH_KREG_OFFSET(IBCCtrl),
++ .kr_ibcstatus = IPATH_KREG_OFFSET(IBCStatus),
++ .kr_intblocked = IPATH_KREG_OFFSET(IntBlocked),
++ .kr_intclear = IPATH_KREG_OFFSET(IntClear),
++ .kr_intmask = IPATH_KREG_OFFSET(IntMask),
++ .kr_intstatus = IPATH_KREG_OFFSET(IntStatus),
++ .kr_mdio = IPATH_KREG_OFFSET(MDIO),
++ .kr_pagealign = IPATH_KREG_OFFSET(PageAlign),
++ .kr_partitionkey = IPATH_KREG_OFFSET(RcvPartitionKey),
++ .kr_portcnt = IPATH_KREG_OFFSET(PortCnt),
++ .kr_rcvbthqp = IPATH_KREG_OFFSET(RcvBTHQP),
++ .kr_rcvbufbase = IPATH_KREG_OFFSET(RcvBufBase),
++ .kr_rcvbufsize = IPATH_KREG_OFFSET(RcvBufSize),
++ .kr_rcvctrl = IPATH_KREG_OFFSET(RcvCtrl),
++ .kr_rcvegrbase = IPATH_KREG_OFFSET(RcvEgrBase),
++ .kr_rcvegrcnt = IPATH_KREG_OFFSET(RcvEgrCnt),
++ .kr_rcvhdrcnt = IPATH_KREG_OFFSET(RcvHdrCnt),
++ .kr_rcvhdrentsize = IPATH_KREG_OFFSET(RcvHdrEntSize),
++ .kr_rcvhdrsize = IPATH_KREG_OFFSET(RcvHdrSize),
++ .kr_rcvintmembase = IPATH_KREG_OFFSET(RxIntMemBase),
++ .kr_rcvintmemsize = IPATH_KREG_OFFSET(RxIntMemSize),
++ .kr_rcvtidbase = IPATH_KREG_OFFSET(RcvTIDBase),
++ .kr_rcvtidcnt = IPATH_KREG_OFFSET(RcvTIDCnt),
++ .kr_revision = IPATH_KREG_OFFSET(Revision),
++ .kr_scratch = IPATH_KREG_OFFSET(Scratch),
++ .kr_sendbuffererror = IPATH_KREG_OFFSET(SendBufferError),
++ .kr_sendctrl = IPATH_KREG_OFFSET(SendCtrl),
++ .kr_sendpioavailaddr = IPATH_KREG_OFFSET(SendAvailAddr),
++ .kr_sendpiobufbase = IPATH_KREG_OFFSET(SendBufBase),
++ .kr_sendpiobufcnt = IPATH_KREG_OFFSET(SendBufCnt),
++ .kr_sendpiosize = IPATH_KREG_OFFSET(SendBufSize),
++ .kr_sendregbase = IPATH_KREG_OFFSET(SendRegBase),
++ .kr_txintmembase = IPATH_KREG_OFFSET(TxIntMemBase),
++ .kr_txintmemsize = IPATH_KREG_OFFSET(TxIntMemSize),
++ .kr_userregbase = IPATH_KREG_OFFSET(UserRegBase),
++
++ .kr_xgxsconfig = IPATH_KREG_OFFSET(XGXSConfig),
++
++ /* send dma related regs */
++ .kr_senddmabase = IPATH_KREG_OFFSET(SendDmaBase),
++ .kr_senddmalengen = IPATH_KREG_OFFSET(SendDmaLenGen),
++ .kr_senddmatail = IPATH_KREG_OFFSET(SendDmaTail),
++ .kr_senddmahead = IPATH_KREG_OFFSET(SendDmaHead),
++ .kr_senddmaheadaddr = IPATH_KREG_OFFSET(SendDmaHeadAddr),
++ .kr_senddmabufmask0 = IPATH_KREG_OFFSET(SendDmaBufMask0),
++ .kr_senddmabufmask1 = IPATH_KREG_OFFSET(SendDmaBufMask1),
++ .kr_senddmabufmask2 = IPATH_KREG_OFFSET(SendDmaBufMask2),
++ .kr_senddmastatus = IPATH_KREG_OFFSET(SendDmaStatus),
++
++ /* SerDes related regs */
++ .kr_ibserdesctrl = IPATH_KREG_OFFSET(IBSerDesCtrl),
++ .kr_ib_epbacc = IPATH_KREG_OFFSET(IbsdEpbAccCtl),
++ .kr_ib_epbtrans = IPATH_KREG_OFFSET(IbsdEpbTransReg),
++ .kr_pcie_epbacc = IPATH_KREG_OFFSET(PcieEpbAccCtl),
++ .kr_pcie_epbtrans = IPATH_KREG_OFFSET(PcieEpbTransCtl),
++ .kr_ib_ddsrxeq = IPATH_KREG_OFFSET(SerDesDDSRXEQ),
++
++ /*
++ * These should not be used directly via ipath_read_kreg64(),
++ * use them with ipath_read_kreg64_port()
++ */
++ .kr_rcvhdraddr = IPATH_KREG_OFFSET(RcvHdrAddr0),
++ .kr_rcvhdrtailaddr = IPATH_KREG_OFFSET(RcvHdrTailAddr0),
++
++ /*
++ * The rcvpktled register controls one of the debug port signals, so
++ * a packet activity LED can be connected to it.
++ */
++ .kr_rcvpktledcnt = IPATH_KREG_OFFSET(RcvPktLEDCnt),
++ .kr_pcierbuftestreg0 = IPATH_KREG_OFFSET(PCIeRBufTestReg0),
++ .kr_pcierbuftestreg1 = IPATH_KREG_OFFSET(PCIeRBufTestReg1),
++
++ .kr_hrtbt_guid = IPATH_KREG_OFFSET(HRTBT_GUID),
++ .kr_ibcddrctrl = IPATH_KREG_OFFSET(IBCDDRCtrl),
++ .kr_ibcddrstatus = IPATH_KREG_OFFSET(IBCDDRStatus),
++ .kr_jintreload = IPATH_KREG_OFFSET(JIntReload)
++};
++
++static const struct ipath_cregs ipath_7220_cregs = {
++ .cr_badformatcnt = IPATH_CREG_OFFSET(RxBadFormatCnt),
++ .cr_erricrccnt = IPATH_CREG_OFFSET(RxICRCErrCnt),
++ .cr_errlinkcnt = IPATH_CREG_OFFSET(RxLinkProblemCnt),
++ .cr_errlpcrccnt = IPATH_CREG_OFFSET(RxLPCRCErrCnt),
++ .cr_errpkey = IPATH_CREG_OFFSET(RxPKeyMismatchCnt),
++ .cr_errrcvflowctrlcnt = IPATH_CREG_OFFSET(RxFlowCtrlErrCnt),
++ .cr_err_rlencnt = IPATH_CREG_OFFSET(RxLenErrCnt),
++ .cr_errslencnt = IPATH_CREG_OFFSET(TxLenErrCnt),
++ .cr_errtidfull = IPATH_CREG_OFFSET(RxTIDFullErrCnt),
++ .cr_errtidvalid = IPATH_CREG_OFFSET(RxTIDValidErrCnt),
++ .cr_errvcrccnt = IPATH_CREG_OFFSET(RxVCRCErrCnt),
++ .cr_ibstatuschange = IPATH_CREG_OFFSET(IBStatusChangeCnt),
++ .cr_intcnt = IPATH_CREG_OFFSET(LBIntCnt),
++ .cr_invalidrlencnt = IPATH_CREG_OFFSET(RxMaxMinLenErrCnt),
++ .cr_invalidslencnt = IPATH_CREG_OFFSET(TxMaxMinLenErrCnt),
++ .cr_lbflowstallcnt = IPATH_CREG_OFFSET(LBFlowStallCnt),
++ .cr_pktrcvcnt = IPATH_CREG_OFFSET(RxDataPktCnt),
++ .cr_pktrcvflowctrlcnt = IPATH_CREG_OFFSET(RxFlowPktCnt),
++ .cr_pktsendcnt = IPATH_CREG_OFFSET(TxDataPktCnt),
++ .cr_pktsendflowcnt = IPATH_CREG_OFFSET(TxFlowPktCnt),
++ .cr_portovflcnt = IPATH_CREG_OFFSET(RxP0HdrEgrOvflCnt),
++ .cr_rcvebpcnt = IPATH_CREG_OFFSET(RxEBPCnt),
++ .cr_rcvovflcnt = IPATH_CREG_OFFSET(RxBufOvflCnt),
++ .cr_senddropped = IPATH_CREG_OFFSET(TxDroppedPktCnt),
++ .cr_sendstallcnt = IPATH_CREG_OFFSET(TxFlowStallCnt),
++ .cr_sendunderruncnt = IPATH_CREG_OFFSET(TxUnderrunCnt),
++ .cr_wordrcvcnt = IPATH_CREG_OFFSET(RxDwordCnt),
++ .cr_wordsendcnt = IPATH_CREG_OFFSET(TxDwordCnt),
++ .cr_unsupvlcnt = IPATH_CREG_OFFSET(TxUnsupVLErrCnt),
++ .cr_rxdroppktcnt = IPATH_CREG_OFFSET(RxDroppedPktCnt),
++ .cr_iblinkerrrecovcnt = IPATH_CREG_OFFSET(IBLinkErrRecoveryCnt),
++ .cr_iblinkdowncnt = IPATH_CREG_OFFSET(IBLinkDownedCnt),
++ .cr_ibsymbolerrcnt = IPATH_CREG_OFFSET(IBSymbolErrCnt),
++ .cr_vl15droppedpktcnt = IPATH_CREG_OFFSET(RxVL15DroppedPktCnt),
++ .cr_rxotherlocalphyerrcnt =
++ IPATH_CREG_OFFSET(RxOtherLocalPhyErrCnt),
++ .cr_excessbufferovflcnt = IPATH_CREG_OFFSET(ExcessBufferOvflCnt),
++ .cr_locallinkintegrityerrcnt =
++ IPATH_CREG_OFFSET(LocalLinkIntegrityErrCnt),
++ .cr_rxvlerrcnt = IPATH_CREG_OFFSET(RxVlErrCnt),
++ .cr_rxdlidfltrcnt = IPATH_CREG_OFFSET(RxDlidFltrCnt),
++ .cr_psstat = IPATH_CREG_OFFSET(PSStat),
++ .cr_psstart = IPATH_CREG_OFFSET(PSStart),
++ .cr_psinterval = IPATH_CREG_OFFSET(PSInterval),
++ .cr_psrcvdatacount = IPATH_CREG_OFFSET(PSRcvDataCount),
++ .cr_psrcvpktscount = IPATH_CREG_OFFSET(PSRcvPktsCount),
++ .cr_psxmitdatacount = IPATH_CREG_OFFSET(PSXmitDataCount),
++ .cr_psxmitpktscount = IPATH_CREG_OFFSET(PSXmitPktsCount),
++ .cr_psxmitwaitcount = IPATH_CREG_OFFSET(PSXmitWaitCount),
++};
++
++/* kr_control bits */
++#define INFINIPATH_C_RESET (1U<<7)
++
++/* kr_intstatus, kr_intclear, kr_intmask bits */
++#define INFINIPATH_I_RCVURG_MASK ((1ULL<<17)-1)
++#define INFINIPATH_I_RCVURG_SHIFT 32
++#define INFINIPATH_I_RCVAVAIL_MASK ((1ULL<<17)-1)
++#define INFINIPATH_I_RCVAVAIL_SHIFT 0
++#define INFINIPATH_I_SERDESTRIMDONE (1ULL<<27)
++
++/* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */
++#define INFINIPATH_HWE_PCIEMEMPARITYERR_MASK 0x00000000000000ffULL
++#define INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT 0
++#define INFINIPATH_HWE_PCIEPOISONEDTLP 0x0000000010000000ULL
++#define INFINIPATH_HWE_PCIECPLTIMEOUT 0x0000000020000000ULL
++#define INFINIPATH_HWE_PCIEBUSPARITYXTLH 0x0000000040000000ULL
++#define INFINIPATH_HWE_PCIEBUSPARITYXADM 0x0000000080000000ULL
++#define INFINIPATH_HWE_PCIEBUSPARITYRADM 0x0000000100000000ULL
++#define INFINIPATH_HWE_COREPLL_FBSLIP 0x0080000000000000ULL
++#define INFINIPATH_HWE_COREPLL_RFSLIP 0x0100000000000000ULL
++#define INFINIPATH_HWE_PCIE1PLLFAILED 0x0400000000000000ULL
++#define INFINIPATH_HWE_PCIE0PLLFAILED 0x0800000000000000ULL
++#define INFINIPATH_HWE_SERDESPLLFAILED 0x1000000000000000ULL
++/* specific to this chip */
++#define INFINIPATH_HWE_PCIECPLDATAQUEUEERR 0x0000000000000040ULL
++#define INFINIPATH_HWE_PCIECPLHDRQUEUEERR 0x0000000000000080ULL
++#define INFINIPATH_HWE_SDMAMEMREADERR 0x0000000010000000ULL
++#define INFINIPATH_HWE_CLK_UC_PLLNOTLOCKED 0x2000000000000000ULL
++#define INFINIPATH_HWE_PCIESERDESQ0PCLKNOTDETECT 0x0100000000000000ULL
++#define INFINIPATH_HWE_PCIESERDESQ1PCLKNOTDETECT 0x0200000000000000ULL
++#define INFINIPATH_HWE_PCIESERDESQ2PCLKNOTDETECT 0x0400000000000000ULL
++#define INFINIPATH_HWE_PCIESERDESQ3PCLKNOTDETECT 0x0800000000000000ULL
++#define INFINIPATH_HWE_DDSRXEQMEMORYPARITYERR 0x0000008000000000ULL
++#define INFINIPATH_HWE_IB_UC_MEMORYPARITYERR 0x0000004000000000ULL
++#define INFINIPATH_HWE_PCIE_UC_OCT0MEMORYPARITYERR 0x0000001000000000ULL
++#define INFINIPATH_HWE_PCIE_UC_OCT1MEMORYPARITYERR 0x0000002000000000ULL
++
++#define IBA7220_IBCS_LINKTRAININGSTATE_MASK 0x1F
++#define IBA7220_IBCS_LINKSTATE_SHIFT 5
++#define IBA7220_IBCS_LINKSPEED_SHIFT 8
++#define IBA7220_IBCS_LINKWIDTH_SHIFT 9
++
++#define IBA7220_IBCC_LINKINITCMD_MASK 0x7ULL
++#define IBA7220_IBCC_LINKCMD_SHIFT 19
++#define IBA7220_IBCC_MAXPKTLEN_SHIFT 21
++
++/* kr_ibcddrctrl bits */
++#define IBA7220_IBC_DLIDLMC_MASK 0xFFFFFFFFUL
++#define IBA7220_IBC_DLIDLMC_SHIFT 32
++#define IBA7220_IBC_HRTBT_MASK 3
++#define IBA7220_IBC_HRTBT_SHIFT 16
++#define IBA7220_IBC_HRTBT_ENB 0x10000UL
++#define IBA7220_IBC_LANE_REV_SUPPORTED (1<<8)
++#define IBA7220_IBC_LREV_MASK 1
++#define IBA7220_IBC_LREV_SHIFT 8
++#define IBA7220_IBC_RXPOL_MASK 1
++#define IBA7220_IBC_RXPOL_SHIFT 7
++#define IBA7220_IBC_WIDTH_SHIFT 5
++#define IBA7220_IBC_WIDTH_MASK 0x3
++#define IBA7220_IBC_WIDTH_1X_ONLY (0<<IBA7220_IBC_WIDTH_SHIFT)
++#define IBA7220_IBC_WIDTH_4X_ONLY (1<<IBA7220_IBC_WIDTH_SHIFT)
++#define IBA7220_IBC_WIDTH_AUTONEG (2<<IBA7220_IBC_WIDTH_SHIFT)
++#define IBA7220_IBC_SPEED_AUTONEG (1<<1)
++#define IBA7220_IBC_SPEED_SDR (1<<2)
++#define IBA7220_IBC_SPEED_DDR (1<<3)
++#define IBA7220_IBC_SPEED_AUTONEG_MASK (0x7<<1)
++#define IBA7220_IBC_IBTA_1_2_MASK (1)
++
++/* kr_ibcddrstatus */
++/* link latency shift is 0, don't bother defining */
++#define IBA7220_DDRSTAT_LINKLAT_MASK 0x3ffffff
++
++/* kr_extstatus bits */
++#define INFINIPATH_EXTS_FREQSEL 0x2
++#define INFINIPATH_EXTS_SERDESSEL 0x4
++#define INFINIPATH_EXTS_MEMBIST_ENDTEST 0x0000000000004000
++#define INFINIPATH_EXTS_MEMBIST_DISABLED 0x0000000000008000
++
++/* kr_xgxsconfig bits */
++#define INFINIPATH_XGXS_RESET 0x5ULL
++#define INFINIPATH_XGXS_FC_SAFE (1ULL<<63)
++
++/* kr_rcvpktledcnt */
++#define IBA7220_LEDBLINK_ON_SHIFT 32 /* 4ns period on after packet */
++#define IBA7220_LEDBLINK_OFF_SHIFT 0 /* 4ns period off before next on */
++
++#define _IPATH_GPIO_SDA_NUM 1
++#define _IPATH_GPIO_SCL_NUM 0
++
++#define IPATH_GPIO_SDA (1ULL << \
++ (_IPATH_GPIO_SDA_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
++#define IPATH_GPIO_SCL (1ULL << \
++ (_IPATH_GPIO_SCL_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
++
++#define IBA7220_R_INTRAVAIL_SHIFT 17
++#define IBA7220_R_TAILUPD_SHIFT 35
++#define IBA7220_R_PORTCFG_SHIFT 36
++
++#define INFINIPATH_JINT_PACKETSHIFT 16
++#define INFINIPATH_JINT_DEFAULT_IDLE_TICKS 0
++#define INFINIPATH_JINT_DEFAULT_MAX_PACKETS 0
++
++#define IBA7220_HDRHEAD_PKTINT_SHIFT 32 /* interrupt cnt in upper 32 bits */
++
++/*
++ * the size bits give us 2^N, in KB units. 0 marks as invalid,
++ * and 7 is reserved. We currently use only 2KB and 4KB
++ */
++#define IBA7220_TID_SZ_SHIFT 37 /* shift to 3bit size selector */
++#define IBA7220_TID_SZ_2K (1UL<<IBA7220_TID_SZ_SHIFT) /* 2KB */
++#define IBA7220_TID_SZ_4K (2UL<<IBA7220_TID_SZ_SHIFT) /* 4KB */
++#define IBA7220_TID_PA_SHIFT 11U /* TID addr in chip stored w/o low bits */
++
++#define IPATH_AUTONEG_TRIES 5 /* sequential retries to negotiate DDR */
++
++static char int_type[16] = "auto";
++module_param_string(interrupt_type, int_type, sizeof(int_type), 0444);
++MODULE_PARM_DESC(int_type, " interrupt_type=auto|force_msi|force_intx\n");
++
++/* packet rate matching delay; chip has support */
++static u8 rate_to_delay[2][2] = {
++ /* 1x, 4x */
++ { 8, 2 }, /* SDR */
++ { 4, 1 } /* DDR */
++};
++
++/* 7220 specific hardware errors... */
++static const struct ipath_hwerror_msgs ipath_7220_hwerror_msgs[] = {
++ INFINIPATH_HWE_MSG(PCIEPOISONEDTLP, "PCIe Poisoned TLP"),
++ INFINIPATH_HWE_MSG(PCIECPLTIMEOUT, "PCIe completion timeout"),
++ /*
++ * In practice, it's unlikely wthat we'll see PCIe PLL, or bus
++ * parity or memory parity error failures, because most likely we
++ * won't be able to talk to the core of the chip. Nonetheless, we
++ * might see them, if they are in parts of the PCIe core that aren't
++ * essential.
++ */
++ INFINIPATH_HWE_MSG(PCIE1PLLFAILED, "PCIePLL1"),
++ INFINIPATH_HWE_MSG(PCIE0PLLFAILED, "PCIePLL0"),
++ INFINIPATH_HWE_MSG(PCIEBUSPARITYXTLH, "PCIe XTLH core parity"),
++ INFINIPATH_HWE_MSG(PCIEBUSPARITYXADM, "PCIe ADM TX core parity"),
++ INFINIPATH_HWE_MSG(PCIEBUSPARITYRADM, "PCIe ADM RX core parity"),
++ INFINIPATH_HWE_MSG(RXDSYNCMEMPARITYERR, "Rx Dsync"),
++ INFINIPATH_HWE_MSG(SERDESPLLFAILED, "SerDes PLL"),
++ INFINIPATH_HWE_MSG(PCIECPLDATAQUEUEERR, "PCIe cpl header queue"),
++ INFINIPATH_HWE_MSG(PCIECPLHDRQUEUEERR, "PCIe cpl data queue"),
++ INFINIPATH_HWE_MSG(SDMAMEMREADERR, "Send DMA memory read"),
++ INFINIPATH_HWE_MSG(CLK_UC_PLLNOTLOCKED, "uC PLL clock not locked"),
++ INFINIPATH_HWE_MSG(PCIESERDESQ0PCLKNOTDETECT,
++ "PCIe serdes Q0 no clock"),
++ INFINIPATH_HWE_MSG(PCIESERDESQ1PCLKNOTDETECT,
++ "PCIe serdes Q1 no clock"),
++ INFINIPATH_HWE_MSG(PCIESERDESQ2PCLKNOTDETECT,
++ "PCIe serdes Q2 no clock"),
++ INFINIPATH_HWE_MSG(PCIESERDESQ3PCLKNOTDETECT,
++ "PCIe serdes Q3 no clock"),
++ INFINIPATH_HWE_MSG(DDSRXEQMEMORYPARITYERR,
++ "DDS RXEQ memory parity"),
++ INFINIPATH_HWE_MSG(IB_UC_MEMORYPARITYERR, "IB uC memory parity"),
++ INFINIPATH_HWE_MSG(PCIE_UC_OCT0MEMORYPARITYERR,
++ "PCIe uC oct0 memory parity"),
++ INFINIPATH_HWE_MSG(PCIE_UC_OCT1MEMORYPARITYERR,
++ "PCIe uC oct1 memory parity"),
++};
++
++static void autoneg_work(struct work_struct *);
++
++/*
++ * the offset is different for different configured port numbers, since
++ * port0 is fixed in size, but others can vary. Make it a function to
++ * make the issue more obvious.
++*/
++static inline u32 port_egrtid_idx(struct ipath_devdata *dd, unsigned port)
++{
++ return port ? dd->ipath_p0_rcvegrcnt +
++ (port-1) * dd->ipath_rcvegrcnt : 0;
++}
++
++static void ipath_7220_txe_recover(struct ipath_devdata *dd)
++{
++ ++ipath_stats.sps_txeparity;
++
++ dev_info(&dd->pcidev->dev,
++ "Recovering from TXE PIO parity error\n");
++ ipath_disarm_senderrbufs(dd, 1);
++}
++
++
++/**
++ * ipath_7220_handle_hwerrors - display hardware errors.
++ * @dd: the infinipath device
++ * @msg: the output buffer
++ * @msgl: the size of the output buffer
++ *
++ * Use same msg buffer as regular errors to avoid excessive stack
++ * use. Most hardware errors are catastrophic, but for right now,
++ * we'll print them and continue. We reuse the same message buffer as
++ * ipath_handle_errors() to avoid excessive stack usage.
++ */
++static void ipath_7220_handle_hwerrors(struct ipath_devdata *dd, char *msg,
++ size_t msgl)
++{
++ ipath_err_t hwerrs;
++ u32 bits, ctrl;
++ int isfatal = 0;
++ char bitsmsg[64];
++ int log_idx;
++
++ hwerrs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus);
++ if (!hwerrs) {
++ /*
++ * better than printing cofusing messages
++ * This seems to be related to clearing the crc error, or
++ * the pll error during init.
++ */
++ ipath_cdbg(VERBOSE, "Called but no hardware errors set\n");
++ goto bail;
++ } else if (hwerrs == ~0ULL) {
++ ipath_dev_err(dd, "Read of hardware error status failed "
++ "(all bits set); ignoring\n");
++ goto bail;
++ }
++ ipath_stats.sps_hwerrs++;
++
++ /*
++ * Always clear the error status register, except MEMBISTFAIL,
++ * regardless of whether we continue or stop using the chip.
++ * We want that set so we know it failed, even across driver reload.
++ * We'll still ignore it in the hwerrmask. We do this partly for
++ * diagnostics, but also for support.
++ */
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
++ hwerrs&~INFINIPATH_HWE_MEMBISTFAILED);
++
++ hwerrs &= dd->ipath_hwerrmask;
++
++ /* We log some errors to EEPROM, check if we have any of those. */
++ for (log_idx = 0; log_idx < IPATH_EEP_LOG_CNT; ++log_idx)
++ if (hwerrs & dd->ipath_eep_st_masks[log_idx].hwerrs_to_log)
++ ipath_inc_eeprom_err(dd, log_idx, 1);
++ /*
++ * Make sure we get this much out, unless told to be quiet,
++ * or it's occurred within the last 5 seconds.
++ */
++ if ((hwerrs & ~(dd->ipath_lasthwerror |
++ ((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF |
++ INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC)
++ << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT))) ||
++ (ipath_debug & __IPATH_VERBDBG))
++ dev_info(&dd->pcidev->dev, "Hardware error: hwerr=0x%llx "
++ "(cleared)\n", (unsigned long long) hwerrs);
++ dd->ipath_lasthwerror |= hwerrs;
++
++ if (hwerrs & ~dd->ipath_hwe_bitsextant)
++ ipath_dev_err(dd, "hwerror interrupt with unknown errors "
++ "%llx set\n", (unsigned long long)
++ (hwerrs & ~dd->ipath_hwe_bitsextant));
++
++ if (hwerrs & INFINIPATH_HWE_IB_UC_MEMORYPARITYERR)
++ ipath_sd7220_clr_ibpar(dd);
++
++ ctrl = ipath_read_kreg32(dd, dd->ipath_kregs->kr_control);
++ if ((ctrl & INFINIPATH_C_FREEZEMODE) && !ipath_diag_inuse) {
++ /*
++ * Parity errors in send memory are recoverable,
++ * just cancel the send (if indicated in * sendbuffererror),
++ * count the occurrence, unfreeze (if no other handled
++ * hardware error bits are set), and continue.
++ */
++ if (hwerrs & ((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF |
++ INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC)
++ << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT)) {
++ ipath_7220_txe_recover(dd);
++ hwerrs &= ~((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF |
++ INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC)
++ << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT);
++ if (!hwerrs) {
++ /* else leave in freeze mode */
++ ipath_write_kreg(dd,
++ dd->ipath_kregs->kr_control,
++ dd->ipath_control);
++ goto bail;
++ }
++ }
++ if (hwerrs) {
++ /*
++ * If any set that we aren't ignoring only make the
++ * complaint once, in case it's stuck or recurring,
++ * and we get here multiple times
++ * Force link down, so switch knows, and
++ * LEDs are turned off.
++ */
++ if (dd->ipath_flags & IPATH_INITTED) {
++ ipath_set_linkstate(dd, IPATH_IB_LINKDOWN);
++ ipath_setup_7220_setextled(dd,
++ INFINIPATH_IBCS_L_STATE_DOWN,
++ INFINIPATH_IBCS_LT_STATE_DISABLED);
++ ipath_dev_err(dd, "Fatal Hardware Error "
++ "(freeze mode), no longer"
++ " usable, SN %.16s\n",
++ dd->ipath_serial);
++ isfatal = 1;
++ }
++ /*
++ * Mark as having had an error for driver, and also
++ * for /sys and status word mapped to user programs.
++ * This marks unit as not usable, until reset.
++ */
++ *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
++ *dd->ipath_statusp |= IPATH_STATUS_HWERROR;
++ dd->ipath_flags &= ~IPATH_INITTED;
++ } else {
++ ipath_dbg("Clearing freezemode on ignored hardware "
++ "error\n");
++ ipath_clear_freeze(dd);
++ }
++ }
++
++ *msg = '\0';
++
++ if (hwerrs & INFINIPATH_HWE_MEMBISTFAILED) {
++ strlcat(msg, "[Memory BIST test failed, "
++ "InfiniPath hardware unusable]", msgl);
++ /* ignore from now on, so disable until driver reloaded */
++ *dd->ipath_statusp |= IPATH_STATUS_HWERROR;
++ dd->ipath_hwerrmask &= ~INFINIPATH_HWE_MEMBISTFAILED;
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
++ dd->ipath_hwerrmask);
++ }
++
++ ipath_format_hwerrors(hwerrs,
++ ipath_7220_hwerror_msgs,
++ ARRAY_SIZE(ipath_7220_hwerror_msgs),
++ msg, msgl);
++
++ if (hwerrs & (INFINIPATH_HWE_PCIEMEMPARITYERR_MASK
++ << INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT)) {
++ bits = (u32) ((hwerrs >>
++ INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT) &
++ INFINIPATH_HWE_PCIEMEMPARITYERR_MASK);
++ snprintf(bitsmsg, sizeof bitsmsg,
++ "[PCIe Mem Parity Errs %x] ", bits);
++ strlcat(msg, bitsmsg, msgl);
++ }
++
++#define _IPATH_PLL_FAIL (INFINIPATH_HWE_COREPLL_FBSLIP | \
++ INFINIPATH_HWE_COREPLL_RFSLIP)
++
++ if (hwerrs & _IPATH_PLL_FAIL) {
++ snprintf(bitsmsg, sizeof bitsmsg,
++ "[PLL failed (%llx), InfiniPath hardware unusable]",
++ (unsigned long long) hwerrs & _IPATH_PLL_FAIL);
++ strlcat(msg, bitsmsg, msgl);
++ /* ignore from now on, so disable until driver reloaded */
++ dd->ipath_hwerrmask &= ~(hwerrs & _IPATH_PLL_FAIL);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
++ dd->ipath_hwerrmask);
++ }
++
++ if (hwerrs & INFINIPATH_HWE_SERDESPLLFAILED) {
++ /*
++ * If it occurs, it is left masked since the eternal
++ * interface is unused.
++ */
++ dd->ipath_hwerrmask &= ~INFINIPATH_HWE_SERDESPLLFAILED;
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
++ dd->ipath_hwerrmask);
++ }
++
++ ipath_dev_err(dd, "%s hardware error\n", msg);
++ /*
++ * For /sys status file. if no trailing } is copied, we'll
++ * know it was truncated.
++ */
++ if (isfatal && !ipath_diag_inuse && dd->ipath_freezemsg)
++ snprintf(dd->ipath_freezemsg, dd->ipath_freezelen,
++ "{%s}", msg);
++bail:;
++}
++
++/**
++ * ipath_7220_boardname - fill in the board name
++ * @dd: the infinipath device
++ * @name: the output buffer
++ * @namelen: the size of the output buffer
++ *
++ * info is based on the board revision register
++ */
++static int ipath_7220_boardname(struct ipath_devdata *dd, char *name,
++ size_t namelen)
++{
++ char *n = NULL;
++ u8 boardrev = dd->ipath_boardrev;
++ int ret;
++
++ if (boardrev == 15) {
++ /*
++ * Emulator sometimes comes up all-ones, rather than zero.
++ */
++ boardrev = 0;
++ dd->ipath_boardrev = boardrev;
++ }
++ switch (boardrev) {
++ case 0:
++ n = "InfiniPath_7220_Emulation";
++ break;
++ case 1:
++ n = "InfiniPath_QLE7240";
++ break;
++ case 2:
++ n = "InfiniPath_QLE7280";
++ break;
++ case 3:
++ n = "InfiniPath_QLE7242";
++ break;
++ case 4:
++ n = "InfiniPath_QEM7240";
++ break;
++ case 5:
++ n = "InfiniPath_QMI7240";
++ break;
++ case 6:
++ n = "InfiniPath_QMI7264";
++ break;
++ case 7:
++ n = "InfiniPath_QMH7240";
++ break;
++ case 8:
++ n = "InfiniPath_QME7240";
++ break;
++ case 9:
++ n = "InfiniPath_QLE7250";
++ break;
++ case 10:
++ n = "InfiniPath_QLE7290";
++ break;
++ case 11:
++ n = "InfiniPath_QEM7250";
++ break;
++ case 12:
++ n = "InfiniPath_QLE-Bringup";
++ break;
++ default:
++ ipath_dev_err(dd,
++ "Don't yet know about board with ID %u\n",
++ boardrev);
++ snprintf(name, namelen, "Unknown_InfiniPath_PCIe_%u",
++ boardrev);
++ break;
++ }
++ if (n)
++ snprintf(name, namelen, "%s", n);
++
++ if (dd->ipath_majrev != 5 || !dd->ipath_minrev ||
++ dd->ipath_minrev > 2) {
++ ipath_dev_err(dd, "Unsupported InfiniPath hardware "
++ "revision %u.%u!\n",
++ dd->ipath_majrev, dd->ipath_minrev);
++ ret = 1;
++ } else if (dd->ipath_minrev == 1) {
++ /* Rev1 chips are prototype. Complain, but allow use */
++ ipath_dev_err(dd, "Unsupported hardware "
++ "revision %u.%u, Contact support at qlogic.com\n",
++ dd->ipath_majrev, dd->ipath_minrev);
++ ret = 0;
++ } else
++ ret = 0;
++
++ /*
++ * Set here not in ipath_init_*_funcs because we have to do
++ * it after we can read chip registers.
++ */
++ dd->ipath_ureg_align = 0x10000; /* 64KB alignment */
++
++ return ret;
++}
++
++/**
++ * ipath_7220_init_hwerrors - enable hardware errors
++ * @dd: the infinipath device
++ *
++ * now that we have finished initializing everything that might reasonably
++ * cause a hardware error, and cleared those errors bits as they occur,
++ * we can enable hardware errors in the mask (potentially enabling
++ * freeze mode), and enable hardware errors as errors (along with
++ * everything else) in errormask
++ */
++static void ipath_7220_init_hwerrors(struct ipath_devdata *dd)
++{
++ ipath_err_t val;
++ u64 extsval;
++
++ extsval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus);
++
++ if (!(extsval & (INFINIPATH_EXTS_MEMBIST_ENDTEST |
++ INFINIPATH_EXTS_MEMBIST_DISABLED)))
++ ipath_dev_err(dd, "MemBIST did not complete!\n");
++ if (extsval & INFINIPATH_EXTS_MEMBIST_DISABLED)
++ dev_info(&dd->pcidev->dev, "MemBIST is disabled.\n");
++
++ val = ~0ULL; /* barring bugs, all hwerrors become interrupts, */
++
++ if (!dd->ipath_boardrev) /* no PLL for Emulator */
++ val &= ~INFINIPATH_HWE_SERDESPLLFAILED;
++
++ if (dd->ipath_minrev == 1)
++ val &= ~(1ULL << 42); /* TXE LaunchFIFO Parity rev1 issue */
++
++ val &= ~INFINIPATH_HWE_IB_UC_MEMORYPARITYERR;
++ dd->ipath_hwerrmask = val;
++
++ /*
++ * special trigger "error" is for debugging purposes. It
++ * works around a processor/chipset problem. The error
++ * interrupt allows us to count occurrences, but we don't
++ * want to pay the overhead for normal use. Emulation only
++ */
++ if (!dd->ipath_boardrev)
++ dd->ipath_maskederrs = INFINIPATH_E_SENDSPECIALTRIGGER;
++}
++
++/*
++ * All detailed interaction with the SerDes has been moved to ipath_sd7220.c
++ *
++ * The portion of IBA7220-specific bringup_serdes() that actually deals with
++ * registers and memory within the SerDes itself is ipath_sd7220_init().
++ */
++
++/**
++ * ipath_7220_bringup_serdes - bring up the serdes
++ * @dd: the infinipath device
++ */
++static int ipath_7220_bringup_serdes(struct ipath_devdata *dd)
++{
++ int ret = 0;
++ u64 val, prev_val, guid;
++ int was_reset; /* Note whether uC was reset */
++
++ ipath_dbg("Trying to bringup serdes\n");
++
++ if (ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus) &
++ INFINIPATH_HWE_SERDESPLLFAILED) {
++ ipath_dbg("At start, serdes PLL failed bit set "
++ "in hwerrstatus, clearing and continuing\n");
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
++ INFINIPATH_HWE_SERDESPLLFAILED);
++ }
++
++ if (!dd->ipath_ibcddrctrl) {
++ /* not on re-init after reset */
++ dd->ipath_ibcddrctrl =
++ ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcddrctrl);
++
++ if (dd->ipath_link_speed_enabled ==
++ (IPATH_IB_SDR | IPATH_IB_DDR))
++ dd->ipath_ibcddrctrl |=
++ IBA7220_IBC_SPEED_AUTONEG_MASK |
++ IBA7220_IBC_IBTA_1_2_MASK;
++ else
++ dd->ipath_ibcddrctrl |=
++ dd->ipath_link_speed_enabled == IPATH_IB_DDR
++ ? IBA7220_IBC_SPEED_DDR :
++ IBA7220_IBC_SPEED_SDR;
++ if ((dd->ipath_link_width_enabled & (IB_WIDTH_1X |
++ IB_WIDTH_4X)) == (IB_WIDTH_1X | IB_WIDTH_4X))
++ dd->ipath_ibcddrctrl |= IBA7220_IBC_WIDTH_AUTONEG;
++ else
++ dd->ipath_ibcddrctrl |=
++ dd->ipath_link_width_enabled == IB_WIDTH_4X
++ ? IBA7220_IBC_WIDTH_4X_ONLY :
++ IBA7220_IBC_WIDTH_1X_ONLY;
++
++ /* always enable these on driver reload, not sticky */
++ dd->ipath_ibcddrctrl |=
++ IBA7220_IBC_RXPOL_MASK << IBA7220_IBC_RXPOL_SHIFT;
++ dd->ipath_ibcddrctrl |=
++ IBA7220_IBC_HRTBT_MASK << IBA7220_IBC_HRTBT_SHIFT;
++ /*
++ * automatic lane reversal detection for receive
++ * doesn't work correctly in rev 1, so disable it
++ * on that rev, otherwise enable (disabling not
++ * sticky across reload for >rev1)
++ */
++ if (dd->ipath_minrev == 1)
++ dd->ipath_ibcddrctrl &=
++ ~IBA7220_IBC_LANE_REV_SUPPORTED;
++ else
++ dd->ipath_ibcddrctrl |=
++ IBA7220_IBC_LANE_REV_SUPPORTED;
++ }
++
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcddrctrl,
++ dd->ipath_ibcddrctrl);
++
++ ipath_write_kreg(dd, IPATH_KREG_OFFSET(IBNCModeCtrl), 0Ull);
++
++ /* IBA7220 has SERDES MPU reset in D0 of what _was_ IBPLLCfg */
++ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibserdesctrl);
++ /* remember if uC was in Reset or not, for dactrim */
++ was_reset = (val & 1);
++ ipath_cdbg(VERBOSE, "IBReset %s xgxsconfig %llx\n",
++ was_reset ? "Asserted" : "Negated", (unsigned long long)
++ ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig));
++
++ if (dd->ipath_boardrev) {
++ /*
++ * Hardware is not emulator, and may have been reset. Init it.
++ * Below will release reset, but needs to know if chip was
++ * originally in reset, to only trim DACs on first time
++ * after chip reset or powercycle (not driver reload)
++ */
++ ret = ipath_sd7220_init(dd, was_reset);
++ }
++
++ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
++ prev_val = val;
++ val |= INFINIPATH_XGXS_FC_SAFE;
++ if (val != prev_val) {
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
++ ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++ }
++ if (val & INFINIPATH_XGXS_RESET)
++ val &= ~INFINIPATH_XGXS_RESET;
++ if (val != prev_val)
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
++
++ ipath_cdbg(VERBOSE, "done: xgxs=%llx from %llx\n",
++ (unsigned long long)
++ ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig),
++ prev_val);
++
++ guid = be64_to_cpu(dd->ipath_guid);
++
++ if (!guid) {
++ /* have to have something, so use likely unique tsc */
++ guid = get_cycles();
++ ipath_dbg("No GUID for heartbeat, faking %llx\n",
++ (unsigned long long)guid);
++ } else
++ ipath_cdbg(VERBOSE, "Wrote %llX to HRTBT_GUID\n", guid);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_hrtbt_guid, guid);
++ return ret;
++}
++
++static void ipath_7220_config_jint(struct ipath_devdata *dd,
++ u16 idle_ticks, u16 max_packets)
++{
++
++ /*
++ * We can request a receive interrupt for 1 or more packets
++ * from current offset.
++ */
++ if (idle_ticks == 0 || max_packets == 0)
++ /* interrupt after one packet if no mitigation */
++ dd->ipath_rhdrhead_intr_off =
++ 1ULL << IBA7220_HDRHEAD_PKTINT_SHIFT;
++ else
++ /* Turn off RcvHdrHead interrupts if using mitigation */
++ dd->ipath_rhdrhead_intr_off = 0ULL;
++
++ /* refresh kernel RcvHdrHead registers... */
++ ipath_write_ureg(dd, ur_rcvhdrhead,
++ dd->ipath_rhdrhead_intr_off |
++ dd->ipath_pd[0]->port_head, 0);
++
++ dd->ipath_jint_max_packets = max_packets;
++ dd->ipath_jint_idle_ticks = idle_ticks;
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_jintreload,
++ ((u64) max_packets << INFINIPATH_JINT_PACKETSHIFT) |
++ idle_ticks);
++}
++
++/**
++ * ipath_7220_quiet_serdes - set serdes to txidle
++ * @dd: the infinipath device
++ * Called when driver is being unloaded
++ */
++static void ipath_7220_quiet_serdes(struct ipath_devdata *dd)
++{
++ u64 val;
++ dd->ipath_flags &= ~IPATH_IB_AUTONEG_INPROG;
++ wake_up(&dd->ipath_autoneg_wait);
++ cancel_delayed_work(&dd->ipath_autoneg_work);
++ flush_scheduled_work();
++ ipath_shutdown_relock_poll(dd);
++ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
++ val |= INFINIPATH_XGXS_RESET;
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
++}
++
++static int ipath_7220_intconfig(struct ipath_devdata *dd)
++{
++ ipath_7220_config_jint(dd, dd->ipath_jint_idle_ticks,
++ dd->ipath_jint_max_packets);
++ return 0;
++}
++
++/**
++ * ipath_setup_7220_setextled - set the state of the two external LEDs
++ * @dd: the infinipath device
++ * @lst: the L state
++ * @ltst: the LT state
++ *
++ * These LEDs indicate the physical and logical state of IB link.
++ * For this chip (at least with recommended board pinouts), LED1
++ * is Yellow (logical state) and LED2 is Green (physical state),
++ *
++ * Note: We try to match the Mellanox HCA LED behavior as best
++ * we can. Green indicates physical link state is OK (something is
++ * plugged in, and we can train).
++ * Amber indicates the link is logically up (ACTIVE).
++ * Mellanox further blinks the amber LED to indicate data packet
++ * activity, but we have no hardware support for that, so it would
++ * require waking up every 10-20 msecs and checking the counters
++ * on the chip, and then turning the LED off if appropriate. That's
++ * visible overhead, so not something we will do.
++ *
++ */
++static void ipath_setup_7220_setextled(struct ipath_devdata *dd, u64 lst,
++ u64 ltst)
++{
++ u64 extctl, ledblink = 0;
++ unsigned long flags = 0;
++
++ /* the diags use the LED to indicate diag info, so we leave
++ * the external LED alone when the diags are running */
++ if (ipath_diag_inuse)
++ return;
++
++ /* Allow override of LED display for, e.g. Locating system in rack */
++ if (dd->ipath_led_override) {
++ ltst = (dd->ipath_led_override & IPATH_LED_PHYS)
++ ? INFINIPATH_IBCS_LT_STATE_LINKUP
++ : INFINIPATH_IBCS_LT_STATE_DISABLED;
++ lst = (dd->ipath_led_override & IPATH_LED_LOG)
++ ? INFINIPATH_IBCS_L_STATE_ACTIVE
++ : INFINIPATH_IBCS_L_STATE_DOWN;
++ }
++
++ spin_lock_irqsave(&dd->ipath_gpio_lock, flags);
++ extctl = dd->ipath_extctrl & ~(INFINIPATH_EXTC_LED1PRIPORT_ON |
++ INFINIPATH_EXTC_LED2PRIPORT_ON);
++ if (ltst == INFINIPATH_IBCS_LT_STATE_LINKUP) {
++ extctl |= INFINIPATH_EXTC_LED1PRIPORT_ON;
++ /*
++ * counts are in chip clock (4ns) periods.
++ * This is 1/16 sec (66.6ms) on,
++ * 3/16 sec (187.5 ms) off, with packets rcvd
++ */
++ ledblink = ((66600*1000UL/4) << IBA7220_LEDBLINK_ON_SHIFT)
++ | ((187500*1000UL/4) << IBA7220_LEDBLINK_OFF_SHIFT);
++ }
++ if (lst == INFINIPATH_IBCS_L_STATE_ACTIVE)
++ extctl |= INFINIPATH_EXTC_LED2PRIPORT_ON;
++ dd->ipath_extctrl = extctl;
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, extctl);
++ spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags);
++
++ if (ledblink) /* blink the LED on packet receive */
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvpktledcnt,
++ ledblink);
++}
++
++/*
++ * Similar to pci_intx(pdev, 1), except that we make sure
++ * msi is off...
++ */
++static void ipath_enable_intx(struct pci_dev *pdev)
++{
++ u16 cw, new;
++ int pos;
++
++ /* first, turn on INTx */
++ pci_read_config_word(pdev, PCI_COMMAND, &cw);
++ new = cw & ~PCI_COMMAND_INTX_DISABLE;
++ if (new != cw)
++ pci_write_config_word(pdev, PCI_COMMAND, new);
++
++ /* then turn off MSI */
++ pos = pci_find_capability(pdev, PCI_CAP_ID_MSI);
++ if (pos) {
++ pci_read_config_word(pdev, pos + PCI_MSI_FLAGS, &cw);
++ new = cw & ~PCI_MSI_FLAGS_ENABLE;
++ if (new != cw)
++ pci_write_config_word(pdev, pos + PCI_MSI_FLAGS, new);
++ }
++}
++
++static int ipath_msi_enabled(struct pci_dev *pdev)
++{
++ int pos, ret = 0;
++
++ pos = pci_find_capability(pdev, PCI_CAP_ID_MSI);
++ if (pos) {
++ u16 cw;
++
++ pci_read_config_word(pdev, pos + PCI_MSI_FLAGS, &cw);
++ ret = !!(cw & PCI_MSI_FLAGS_ENABLE);
++ }
++ return ret;
++}
++
++/*
++ * disable msi interrupt if enabled, and clear the flag.
++ * flag is used primarily for the fallback to INTx, but
++ * is also used in reinit after reset as a flag.
++ */
++static void ipath_7220_nomsi(struct ipath_devdata *dd)
++{
++ dd->ipath_msi_lo = 0;
++
++ if (ipath_msi_enabled(dd->pcidev)) {
++ /*
++ * free, but don't zero; later kernels require
++ * it be freed before disable_msi, so the intx
++ * setup has to request it again.
++ */
++ if (dd->ipath_irq)
++ free_irq(dd->ipath_irq, dd);
++ pci_disable_msi(dd->pcidev);
++ }
++}
++
++/*
++ * ipath_setup_7220_cleanup - clean up any per-chip chip-specific stuff
++ * @dd: the infinipath device
++ *
++ * Nothing but msi interrupt cleanup for now.
++ *
++ * This is called during driver unload.
++ */
++static void ipath_setup_7220_cleanup(struct ipath_devdata *dd)
++{
++ ipath_7220_nomsi(dd);
++}
++
++
++static void ipath_7220_pcie_params(struct ipath_devdata *dd, u32 boardrev)
++{
++ u16 linkstat, minwidth, speed;
++ int pos;
++
++ pos = pci_find_capability(dd->pcidev, PCI_CAP_ID_EXP);
++ if (!pos) {
++ ipath_dev_err(dd, "Can't find PCI Express capability!\n");
++ goto bail;
++ }
++
++ pci_read_config_word(dd->pcidev, pos + PCI_EXP_LNKSTA,
++ &linkstat);
++ /*
++ * speed is bits 0-4, linkwidth is bits 4-8
++ * no defines for them in headers
++ */
++ speed = linkstat & 0xf;
++ linkstat >>= 4;
++ linkstat &= 0x1f;
++ dd->ipath_lbus_width = linkstat;
++ switch (boardrev) {
++ case 0:
++ case 2:
++ case 10:
++ case 12:
++ minwidth = 16; /* x16 capable boards */
++ break;
++ default:
++ minwidth = 8; /* x8 capable boards */
++ break;
++ }
++
++ switch (speed) {
++ case 1:
++ dd->ipath_lbus_speed = 2500; /* Gen1, 2.5GHz */
++ break;
++ case 2:
++ dd->ipath_lbus_speed = 5000; /* Gen1, 5GHz */
++ break;
++ default: /* not defined, assume gen1 */
++ dd->ipath_lbus_speed = 2500;
++ break;
++ }
++
++ if (linkstat < minwidth)
++ ipath_dev_err(dd,
++ "PCIe width %u (x%u HCA), performance "
++ "reduced\n", linkstat, minwidth);
++ else
++ ipath_cdbg(VERBOSE, "PCIe speed %u width %u (x%u HCA)\n",
++ dd->ipath_lbus_speed, linkstat, minwidth);
++
++ if (speed != 1)
++ ipath_dev_err(dd,
++ "PCIe linkspeed %u is incorrect; "
++ "should be 1 (2500)!\n", speed);
++
++bail:
++ /* fill in string, even on errors */
++ snprintf(dd->ipath_lbus_info, sizeof(dd->ipath_lbus_info),
++ "PCIe,%uMHz,x%u\n",
++ dd->ipath_lbus_speed,
++ dd->ipath_lbus_width);
++ return;
++}
++
++
++/**
++ * ipath_setup_7220_config - setup PCIe config related stuff
++ * @dd: the infinipath device
++ * @pdev: the PCI device
++ *
++ * The pci_enable_msi() call will fail on systems with MSI quirks
++ * such as those with AMD8131, even if the device of interest is not
++ * attached to that device, (in the 2.6.13 - 2.6.15 kernels, at least, fixed
++ * late in 2.6.16).
++ * All that can be done is to edit the kernel source to remove the quirk
++ * check until that is fixed.
++ * We do not need to call enable_msi() for our HyperTransport chip,
++ * even though it uses MSI, and we want to avoid the quirk warning, so
++ * So we call enable_msi only for PCIe. If we do end up needing
++ * pci_enable_msi at some point in the future for HT, we'll move the
++ * call back into the main init_one code.
++ * We save the msi lo and hi values, so we can restore them after
++ * chip reset (the kernel PCI infrastructure doesn't yet handle that
++ * correctly).
++ */
++static int ipath_setup_7220_config(struct ipath_devdata *dd,
++ struct pci_dev *pdev)
++{
++ int pos, ret = -1;
++ u32 boardrev;
++
++ dd->ipath_msi_lo = 0; /* used as a flag during reset processing */
++
++ pos = pci_find_capability(pdev, PCI_CAP_ID_MSI);
++ if (!strcmp(int_type, "force_msi") || !strcmp(int_type, "auto"))
++ ret = pci_enable_msi(pdev);
++ if (ret) {
++ if (!strcmp(int_type, "force_msi")) {
++ ipath_dev_err(dd, "pci_enable_msi failed: %d, "
++ "force_msi is on, so not continuing.\n",
++ ret);
++ return ret;
++ }
++
++ ipath_enable_intx(pdev);
++ if (!strcmp(int_type, "auto"))
++ ipath_dev_err(dd, "pci_enable_msi failed: %d, "
++ "falling back to INTx\n", ret);
++ } else if (pos) {
++ u16 control;
++ pci_read_config_dword(pdev, pos + PCI_MSI_ADDRESS_LO,
++ &dd->ipath_msi_lo);
++ pci_read_config_dword(pdev, pos + PCI_MSI_ADDRESS_HI,
++ &dd->ipath_msi_hi);
++ pci_read_config_word(pdev, pos + PCI_MSI_FLAGS,
++ &control);
++ /* now save the data (vector) info */
++ pci_read_config_word(pdev,
++ pos + ((control & PCI_MSI_FLAGS_64BIT)
++ ? PCI_MSI_DATA_64 :
++ PCI_MSI_DATA_32),
++ &dd->ipath_msi_data);
++ } else
++ ipath_dev_err(dd, "Can't find MSI capability, "
++ "can't save MSI settings for reset\n");
++
++ dd->ipath_irq = pdev->irq;
++
++ /*
++ * We save the cachelinesize also, although it doesn't
++ * really matter.
++ */
++ pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE,
++ &dd->ipath_pci_cacheline);
++
++ /*
++ * this function called early, ipath_boardrev not set yet. Can't
++ * use ipath_read_kreg64() yet, too early in init, so use readq()
++ */
++ boardrev = (readq(&dd->ipath_kregbase[dd->ipath_kregs->kr_revision])
++ >> INFINIPATH_R_BOARDID_SHIFT) & INFINIPATH_R_BOARDID_MASK;
++
++ ipath_7220_pcie_params(dd, boardrev);
++
++ dd->ipath_flags |= IPATH_NODMA_RTAIL | IPATH_HAS_SEND_DMA |
++ IPATH_HAS_PBC_CNT | IPATH_HAS_THRESH_UPDATE;
++ dd->ipath_pioupd_thresh = 4U; /* set default update threshold */
++ return 0;
++}
++
++static void ipath_init_7220_variables(struct ipath_devdata *dd)
++{
++ /*
++ * setup the register offsets, since they are different for each
++ * chip
++ */
++ dd->ipath_kregs = &ipath_7220_kregs;
++ dd->ipath_cregs = &ipath_7220_cregs;
++
++ /*
++ * bits for selecting i2c direction and values,
++ * used for I2C serial flash
++ */
++ dd->ipath_gpio_sda_num = _IPATH_GPIO_SDA_NUM;
++ dd->ipath_gpio_scl_num = _IPATH_GPIO_SCL_NUM;
++ dd->ipath_gpio_sda = IPATH_GPIO_SDA;
++ dd->ipath_gpio_scl = IPATH_GPIO_SCL;
++
++ /*
++ * Fill in data for field-values that change in IBA7220.
++ * We dynamically specify only the mask for LINKTRAININGSTATE
++ * and only the shift for LINKSTATE, as they are the only ones
++ * that change. Also precalculate the 3 link states of interest
++ * and the combined mask.
++ */
++ dd->ibcs_ls_shift = IBA7220_IBCS_LINKSTATE_SHIFT;
++ dd->ibcs_lts_mask = IBA7220_IBCS_LINKTRAININGSTATE_MASK;
++ dd->ibcs_mask = (INFINIPATH_IBCS_LINKSTATE_MASK <<
++ dd->ibcs_ls_shift) | dd->ibcs_lts_mask;
++ dd->ib_init = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
++ INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
++ (INFINIPATH_IBCS_L_STATE_INIT << dd->ibcs_ls_shift);
++ dd->ib_arm = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
++ INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
++ (INFINIPATH_IBCS_L_STATE_ARM << dd->ibcs_ls_shift);
++ dd->ib_active = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
++ INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
++ (INFINIPATH_IBCS_L_STATE_ACTIVE << dd->ibcs_ls_shift);
++
++ /*
++ * Fill in data for ibcc field-values that change in IBA7220.
++ * We dynamically specify only the mask for LINKINITCMD
++ * and only the shift for LINKCMD and MAXPKTLEN, as they are
++ * the only ones that change.
++ */
++ dd->ibcc_lic_mask = IBA7220_IBCC_LINKINITCMD_MASK;
++ dd->ibcc_lc_shift = IBA7220_IBCC_LINKCMD_SHIFT;
++ dd->ibcc_mpl_shift = IBA7220_IBCC_MAXPKTLEN_SHIFT;
++
++ /* Fill in shifts for RcvCtrl. */
++ dd->ipath_r_portenable_shift = INFINIPATH_R_PORTENABLE_SHIFT;
++ dd->ipath_r_intravail_shift = IBA7220_R_INTRAVAIL_SHIFT;
++ dd->ipath_r_tailupd_shift = IBA7220_R_TAILUPD_SHIFT;
++ dd->ipath_r_portcfg_shift = IBA7220_R_PORTCFG_SHIFT;
++
++ /* variables for sanity checking interrupt and errors */
++ dd->ipath_hwe_bitsextant =
++ (INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
++ INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) |
++ (INFINIPATH_HWE_TXEMEMPARITYERR_MASK <<
++ INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) |
++ (INFINIPATH_HWE_PCIEMEMPARITYERR_MASK <<
++ INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT) |
++ INFINIPATH_HWE_PCIE1PLLFAILED |
++ INFINIPATH_HWE_PCIE0PLLFAILED |
++ INFINIPATH_HWE_PCIEPOISONEDTLP |
++ INFINIPATH_HWE_PCIECPLTIMEOUT |
++ INFINIPATH_HWE_PCIEBUSPARITYXTLH |
++ INFINIPATH_HWE_PCIEBUSPARITYXADM |
++ INFINIPATH_HWE_PCIEBUSPARITYRADM |
++ INFINIPATH_HWE_MEMBISTFAILED |
++ INFINIPATH_HWE_COREPLL_FBSLIP |
++ INFINIPATH_HWE_COREPLL_RFSLIP |
++ INFINIPATH_HWE_SERDESPLLFAILED |
++ INFINIPATH_HWE_IBCBUSTOSPCPARITYERR |
++ INFINIPATH_HWE_IBCBUSFRSPCPARITYERR |
++ INFINIPATH_HWE_PCIECPLDATAQUEUEERR |
++ INFINIPATH_HWE_PCIECPLHDRQUEUEERR |
++ INFINIPATH_HWE_SDMAMEMREADERR |
++ INFINIPATH_HWE_CLK_UC_PLLNOTLOCKED |
++ INFINIPATH_HWE_PCIESERDESQ0PCLKNOTDETECT |
++ INFINIPATH_HWE_PCIESERDESQ1PCLKNOTDETECT |
++ INFINIPATH_HWE_PCIESERDESQ2PCLKNOTDETECT |
++ INFINIPATH_HWE_PCIESERDESQ3PCLKNOTDETECT |
++ INFINIPATH_HWE_DDSRXEQMEMORYPARITYERR |
++ INFINIPATH_HWE_IB_UC_MEMORYPARITYERR |
++ INFINIPATH_HWE_PCIE_UC_OCT0MEMORYPARITYERR |
++ INFINIPATH_HWE_PCIE_UC_OCT1MEMORYPARITYERR;
++ dd->ipath_i_bitsextant =
++ INFINIPATH_I_SDMAINT | INFINIPATH_I_SDMADISABLED |
++ (INFINIPATH_I_RCVURG_MASK << INFINIPATH_I_RCVURG_SHIFT) |
++ (INFINIPATH_I_RCVAVAIL_MASK <<
++ INFINIPATH_I_RCVAVAIL_SHIFT) |
++ INFINIPATH_I_ERROR | INFINIPATH_I_SPIOSENT |
++ INFINIPATH_I_SPIOBUFAVAIL | INFINIPATH_I_GPIO |
++ INFINIPATH_I_JINT | INFINIPATH_I_SERDESTRIMDONE;
++ dd->ipath_e_bitsextant =
++ INFINIPATH_E_RFORMATERR | INFINIPATH_E_RVCRC |
++ INFINIPATH_E_RICRC | INFINIPATH_E_RMINPKTLEN |
++ INFINIPATH_E_RMAXPKTLEN | INFINIPATH_E_RLONGPKTLEN |
++ INFINIPATH_E_RSHORTPKTLEN | INFINIPATH_E_RUNEXPCHAR |
++ INFINIPATH_E_RUNSUPVL | INFINIPATH_E_REBP |
++ INFINIPATH_E_RIBFLOW | INFINIPATH_E_RBADVERSION |
++ INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL |
++ INFINIPATH_E_RBADTID | INFINIPATH_E_RHDRLEN |
++ INFINIPATH_E_RHDR | INFINIPATH_E_RIBLOSTLINK |
++ INFINIPATH_E_SENDSPECIALTRIGGER |
++ INFINIPATH_E_SDMADISABLED | INFINIPATH_E_SMINPKTLEN |
++ INFINIPATH_E_SMAXPKTLEN | INFINIPATH_E_SUNDERRUN |
++ INFINIPATH_E_SPKTLEN | INFINIPATH_E_SDROPPEDSMPPKT |
++ INFINIPATH_E_SDROPPEDDATAPKT |
++ INFINIPATH_E_SPIOARMLAUNCH | INFINIPATH_E_SUNEXPERRPKTNUM |
++ INFINIPATH_E_SUNSUPVL | INFINIPATH_E_SENDBUFMISUSE |
++ INFINIPATH_E_SDMAGENMISMATCH | INFINIPATH_E_SDMAOUTOFBOUND |
++ INFINIPATH_E_SDMATAILOUTOFBOUND | INFINIPATH_E_SDMABASE |
++ INFINIPATH_E_SDMA1STDESC | INFINIPATH_E_SDMARPYTAG |
++ INFINIPATH_E_SDMADWEN | INFINIPATH_E_SDMAMISSINGDW |
++ INFINIPATH_E_SDMAUNEXPDATA |
++ INFINIPATH_E_IBSTATUSCHANGED | INFINIPATH_E_INVALIDADDR |
++ INFINIPATH_E_RESET | INFINIPATH_E_HARDWARE |
++ INFINIPATH_E_SDMADESCADDRMISALIGN |
++ INFINIPATH_E_INVALIDEEPCMD;
++
++ dd->ipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
++ dd->ipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
++ dd->ipath_i_rcvavail_shift = INFINIPATH_I_RCVAVAIL_SHIFT;
++ dd->ipath_i_rcvurg_shift = INFINIPATH_I_RCVURG_SHIFT;
++ dd->ipath_flags |= IPATH_INTREG_64 | IPATH_HAS_MULT_IB_SPEED
++ | IPATH_HAS_LINK_LATENCY;
++
++ /*
++ * EEPROM error log 0 is TXE Parity errors. 1 is RXE Parity.
++ * 2 is Some Misc, 3 is reserved for future.
++ */
++ dd->ipath_eep_st_masks[0].hwerrs_to_log =
++ INFINIPATH_HWE_TXEMEMPARITYERR_MASK <<
++ INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT;
++
++ dd->ipath_eep_st_masks[1].hwerrs_to_log =
++ INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
++ INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT;
++
++ dd->ipath_eep_st_masks[2].errs_to_log = INFINIPATH_E_RESET;
++
++ ipath_linkrecovery = 0;
++
++ init_waitqueue_head(&dd->ipath_autoneg_wait);
++ INIT_DELAYED_WORK(&dd->ipath_autoneg_work, autoneg_work);
++
++ dd->ipath_link_width_supported = IB_WIDTH_1X | IB_WIDTH_4X;
++ dd->ipath_link_speed_supported = IPATH_IB_SDR | IPATH_IB_DDR;
++
++ dd->ipath_link_width_enabled = dd->ipath_link_width_supported;
++ dd->ipath_link_speed_enabled = dd->ipath_link_speed_supported;
++ /*
++ * set the initial values to reasonable default, will be set
++ * for real when link is up.
++ */
++ dd->ipath_link_width_active = IB_WIDTH_4X;
++ dd->ipath_link_speed_active = IPATH_IB_SDR;
++ dd->delay_mult = rate_to_delay[0][1];
++}
++
++
++/*
++ * Setup the MSI stuff again after a reset. I'd like to just call
++ * pci_enable_msi() and request_irq() again, but when I do that,
++ * the MSI enable bit doesn't get set in the command word, and
++ * we switch to to a different interrupt vector, which is confusing,
++ * so I instead just do it all inline. Perhaps somehow can tie this
++ * into the PCIe hotplug support at some point
++ * Note, because I'm doing it all here, I don't call pci_disable_msi()
++ * or free_irq() at the start of ipath_setup_7220_reset().
++ */
++static int ipath_reinit_msi(struct ipath_devdata *dd)
++{
++ int ret = 0;
++
++ int pos;
++ u16 control;
++ if (!dd->ipath_msi_lo) /* Using intX, or init problem */
++ goto bail;
++
++ pos = pci_find_capability(dd->pcidev, PCI_CAP_ID_MSI);
++ if (!pos) {
++ ipath_dev_err(dd, "Can't find MSI capability, "
++ "can't restore MSI settings\n");
++ goto bail;
++ }
++ ipath_cdbg(VERBOSE, "Writing msi_lo 0x%x to config offset 0x%x\n",
++ dd->ipath_msi_lo, pos + PCI_MSI_ADDRESS_LO);
++ pci_write_config_dword(dd->pcidev, pos + PCI_MSI_ADDRESS_LO,
++ dd->ipath_msi_lo);
++ ipath_cdbg(VERBOSE, "Writing msi_lo 0x%x to config offset 0x%x\n",
++ dd->ipath_msi_hi, pos + PCI_MSI_ADDRESS_HI);
++ pci_write_config_dword(dd->pcidev, pos + PCI_MSI_ADDRESS_HI,
++ dd->ipath_msi_hi);
++ pci_read_config_word(dd->pcidev, pos + PCI_MSI_FLAGS, &control);
++ if (!(control & PCI_MSI_FLAGS_ENABLE)) {
++ ipath_cdbg(VERBOSE, "MSI control at off %x was %x, "
++ "setting MSI enable (%x)\n", pos + PCI_MSI_FLAGS,
++ control, control | PCI_MSI_FLAGS_ENABLE);
++ control |= PCI_MSI_FLAGS_ENABLE;
++ pci_write_config_word(dd->pcidev, pos + PCI_MSI_FLAGS,
++ control);
++ }
++ /* now rewrite the data (vector) info */
++ pci_write_config_word(dd->pcidev, pos +
++ ((control & PCI_MSI_FLAGS_64BIT) ? 12 : 8),
++ dd->ipath_msi_data);
++ ret = 1;
++
++bail:
++ if (!ret) {
++ ipath_dbg("Using INTx, MSI disabled or not configured\n");
++ ipath_enable_intx(dd->pcidev);
++ ret = 1;
++ }
++ /*
++ * We restore the cachelinesize also, although it doesn't really
++ * matter.
++ */
++ pci_write_config_byte(dd->pcidev, PCI_CACHE_LINE_SIZE,
++ dd->ipath_pci_cacheline);
++ /* and now set the pci master bit again */
++ pci_set_master(dd->pcidev);
++
++ return ret;
++}
++
++/*
++ * This routine sleeps, so it can only be called from user context, not
++ * from interrupt context. If we need interrupt context, we can split
++ * it into two routines.
++ */
++static int ipath_setup_7220_reset(struct ipath_devdata *dd)
++{
++ u64 val;
++ int i;
++ int ret;
++ u16 cmdval;
++
++ pci_read_config_word(dd->pcidev, PCI_COMMAND, &cmdval);
++
++ /* Use dev_err so it shows up in logs, etc. */
++ ipath_dev_err(dd, "Resetting InfiniPath unit %u\n", dd->ipath_unit);
++
++ /* keep chip from being accessed in a few places */
++ dd->ipath_flags &= ~(IPATH_INITTED | IPATH_PRESENT);
++ val = dd->ipath_control | INFINIPATH_C_RESET;
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_control, val);
++ mb();
++
++ for (i = 1; i <= 5; i++) {
++ int r;
++
++ /*
++ * Allow MBIST, etc. to complete; longer on each retry.
++ * We sometimes get machine checks from bus timeout if no
++ * response, so for now, make it *really* long.
++ */
++ msleep(1000 + (1 + i) * 2000);
++ r = pci_write_config_dword(dd->pcidev, PCI_BASE_ADDRESS_0,
++ dd->ipath_pcibar0);
++ if (r)
++ ipath_dev_err(dd, "rewrite of BAR0 failed: %d\n", r);
++ r = pci_write_config_dword(dd->pcidev, PCI_BASE_ADDRESS_1,
++ dd->ipath_pcibar1);
++ if (r)
++ ipath_dev_err(dd, "rewrite of BAR1 failed: %d\n", r);
++ /* now re-enable memory access */
++ pci_write_config_word(dd->pcidev, PCI_COMMAND, cmdval);
++ r = pci_enable_device(dd->pcidev);
++ if (r)
++ ipath_dev_err(dd, "pci_enable_device failed after "
++ "reset: %d\n", r);
++ /*
++ * whether it fully enabled or not, mark as present,
++ * again (but not INITTED)
++ */
++ dd->ipath_flags |= IPATH_PRESENT;
++ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_revision);
++ if (val == dd->ipath_revision) {
++ ipath_cdbg(VERBOSE, "Got matching revision "
++ "register %llx on try %d\n",
++ (unsigned long long) val, i);
++ ret = ipath_reinit_msi(dd);
++ goto bail;
++ }
++ /* Probably getting -1 back */
++ ipath_dbg("Didn't get expected revision register, "
++ "got %llx, try %d\n", (unsigned long long) val,
++ i + 1);
++ }
++ ret = 0; /* failed */
++
++bail:
++ if (ret)
++ ipath_7220_pcie_params(dd, dd->ipath_boardrev);
++
++ return ret;
++}
++
++/**
++ * ipath_7220_put_tid - write a TID to the chip
++ * @dd: the infinipath device
++ * @tidptr: pointer to the expected TID (in chip) to udpate
++ * @tidtype: 0 for eager, 1 for expected
++ * @pa: physical address of in memory buffer; ipath_tidinvalid if freeing
++ *
++ * This exists as a separate routine to allow for selection of the
++ * appropriate "flavor". The static calls in cleanup just use the
++ * revision-agnostic form, as they are not performance critical.
++ */
++static void ipath_7220_put_tid(struct ipath_devdata *dd, u64 __iomem *tidptr,
++ u32 type, unsigned long pa)
++{
++ if (pa != dd->ipath_tidinvalid) {
++ u64 chippa = pa >> IBA7220_TID_PA_SHIFT;
++
++ /* paranoia checks */
++ if (pa != (chippa << IBA7220_TID_PA_SHIFT)) {
++ dev_info(&dd->pcidev->dev, "BUG: physaddr %lx "
++ "not 2KB aligned!\n", pa);
++ return;
++ }
++ if (pa >= (1UL << IBA7220_TID_SZ_SHIFT)) {
++ ipath_dev_err(dd,
++ "BUG: Physical page address 0x%lx "
++ "larger than supported\n", pa);
++ return;
++ }
++
++ if (type == RCVHQ_RCV_TYPE_EAGER)
++ chippa |= dd->ipath_tidtemplate;
++ else /* for now, always full 4KB page */
++ chippa |= IBA7220_TID_SZ_4K;
++ writeq(chippa, tidptr);
++ } else
++ writeq(pa, tidptr);
++ mmiowb();
++}
++
++/**
++ * ipath_7220_clear_tid - clear all TID entries for a port, expected and eager
++ * @dd: the infinipath device
++ * @port: the port
++ *
++ * clear all TID entries for a port, expected and eager.
++ * Used from ipath_close(). On this chip, TIDs are only 32 bits,
++ * not 64, but they are still on 64 bit boundaries, so tidbase
++ * is declared as u64 * for the pointer math, even though we write 32 bits
++ */
++static void ipath_7220_clear_tids(struct ipath_devdata *dd, unsigned port)
++{
++ u64 __iomem *tidbase;
++ unsigned long tidinv;
++ int i;
++
++ if (!dd->ipath_kregbase)
++ return;
++
++ ipath_cdbg(VERBOSE, "Invalidate TIDs for port %u\n", port);
++
++ tidinv = dd->ipath_tidinvalid;
++ tidbase = (u64 __iomem *)
++ ((char __iomem *)(dd->ipath_kregbase) +
++ dd->ipath_rcvtidbase +
++ port * dd->ipath_rcvtidcnt * sizeof(*tidbase));
++
++ for (i = 0; i < dd->ipath_rcvtidcnt; i++)
++ ipath_7220_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EXPECTED,
++ tidinv);
++
++ tidbase = (u64 __iomem *)
++ ((char __iomem *)(dd->ipath_kregbase) +
++ dd->ipath_rcvegrbase + port_egrtid_idx(dd, port)
++ * sizeof(*tidbase));
++
++ for (i = port ? dd->ipath_rcvegrcnt : dd->ipath_p0_rcvegrcnt; i; i--)
++ ipath_7220_put_tid(dd, &tidbase[i-1], RCVHQ_RCV_TYPE_EAGER,
++ tidinv);
++}
++
++/**
++ * ipath_7220_tidtemplate - setup constants for TID updates
++ * @dd: the infinipath device
++ *
++ * We setup stuff that we use a lot, to avoid calculating each time
++ */
++static void ipath_7220_tidtemplate(struct ipath_devdata *dd)
++{
++ /* For now, we always allocate 4KB buffers (at init) so we can
++ * receive max size packets. We may want a module parameter to
++ * specify 2KB or 4KB and/or make be per port instead of per device
++ * for those who want to reduce memory footprint. Note that the
++ * ipath_rcvhdrentsize size must be large enough to hold the largest
++ * IB header (currently 96 bytes) that we expect to handle (plus of
++ * course the 2 dwords of RHF).
++ */
++ if (dd->ipath_rcvegrbufsize == 2048)
++ dd->ipath_tidtemplate = IBA7220_TID_SZ_2K;
++ else if (dd->ipath_rcvegrbufsize == 4096)
++ dd->ipath_tidtemplate = IBA7220_TID_SZ_4K;
++ else {
++ dev_info(&dd->pcidev->dev, "BUG: unsupported egrbufsize "
++ "%u, using %u\n", dd->ipath_rcvegrbufsize,
++ 4096);
++ dd->ipath_tidtemplate = IBA7220_TID_SZ_4K;
++ }
++ dd->ipath_tidinvalid = 0;
++}
++
++static int ipath_7220_early_init(struct ipath_devdata *dd)
++{
++ u32 i, s;
++
++ if (strcmp(int_type, "auto") &&
++ strcmp(int_type, "force_msi") &&
++ strcmp(int_type, "force_intx")) {
++ ipath_dev_err(dd, "Invalid interrupt_type: '%s', expecting "
++ "auto, force_msi or force_intx\n", int_type);
++ return -EINVAL;
++ }
++
++ /*
++ * Control[4] has been added to change the arbitration within
++ * the SDMA engine between favoring data fetches over descriptor
++ * fetches. ipath_sdma_fetch_arb==0 gives data fetches priority.
++ */
++ if (ipath_sdma_fetch_arb && (dd->ipath_minrev > 1))
++ dd->ipath_control |= 1<<4;
++
++ dd->ipath_flags |= IPATH_4BYTE_TID;
++
++ /*
++ * For openfabrics, we need to be able to handle an IB header of
++ * 24 dwords. HT chip has arbitrary sized receive buffers, so we
++ * made them the same size as the PIO buffers. This chip does not
++ * handle arbitrary size buffers, so we need the header large enough
++ * to handle largest IB header, but still have room for a 2KB MTU
++ * standard IB packet.
++ */
++ dd->ipath_rcvhdrentsize = 24;
++ dd->ipath_rcvhdrsize = IPATH_DFLT_RCVHDRSIZE;
++ dd->ipath_rhf_offset =
++ dd->ipath_rcvhdrentsize - sizeof(u64) / sizeof(u32);
++
++ dd->ipath_rcvegrbufsize = ipath_mtu4096 ? 4096 : 2048;
++ /*
++ * the min() check here is currently a nop, but it may not always
++ * be, depending on just how we do ipath_rcvegrbufsize
++ */
++ dd->ipath_ibmaxlen = min(ipath_mtu4096 ? dd->ipath_piosize4k :
++ dd->ipath_piosize2k,
++ dd->ipath_rcvegrbufsize +
++ (dd->ipath_rcvhdrentsize << 2));
++ dd->ipath_init_ibmaxlen = dd->ipath_ibmaxlen;
++
++ ipath_7220_config_jint(dd, INFINIPATH_JINT_DEFAULT_IDLE_TICKS,
++ INFINIPATH_JINT_DEFAULT_MAX_PACKETS);
++
++ if (dd->ipath_boardrev) /* no eeprom on emulator */
++ ipath_get_eeprom_info(dd);
++
++ /* start of code to check and print procmon */
++ s = ipath_read_kreg32(dd, IPATH_KREG_OFFSET(ProcMon));
++ s &= ~(1U<<31); /* clear done bit */
++ s |= 1U<<14; /* clear counter (write 1 to clear) */
++ ipath_write_kreg(dd, IPATH_KREG_OFFSET(ProcMon), s);
++ /* make sure clear_counter low long enough before start */
++ ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++ ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++
++ s &= ~(1U<<14); /* allow counter to count (before starting) */
++ ipath_write_kreg(dd, IPATH_KREG_OFFSET(ProcMon), s);
++ ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++ ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++ s = ipath_read_kreg32(dd, IPATH_KREG_OFFSET(ProcMon));
++
++ s |= 1U<<15; /* start the counter */
++ s &= ~(1U<<31); /* clear done bit */
++ s &= ~0x7ffU; /* clear frequency bits */
++ s |= 0xe29; /* set frequency bits, in case cleared */
++ ipath_write_kreg(dd, IPATH_KREG_OFFSET(ProcMon), s);
++
++ s = 0;
++ for (i = 500; i > 0 && !(s&(1ULL<<31)); i--) {
++ ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++ s = ipath_read_kreg32(dd, IPATH_KREG_OFFSET(ProcMon));
++ }
++ if (!(s&(1U<<31)))
++ ipath_dev_err(dd, "ProcMon register not valid: 0x%x\n", s);
++ else
++ ipath_dbg("ProcMon=0x%x, count=0x%x\n", s, (s>>16)&0x1ff);
++
++ return 0;
++}
++
++/**
++ * ipath_init_7220_get_base_info - set chip-specific flags for user code
++ * @pd: the infinipath port
++ * @kbase: ipath_base_info pointer
++ *
++ * We set the PCIE flag because the lower bandwidth on PCIe vs
++ * HyperTransport can affect some user packet algorithims.
++ */
++static int ipath_7220_get_base_info(struct ipath_portdata *pd, void *kbase)
++{
++ struct ipath_base_info *kinfo = kbase;
++
++ kinfo->spi_runtime_flags |=
++ IPATH_RUNTIME_PCIE | IPATH_RUNTIME_NODMA_RTAIL |
++ IPATH_RUNTIME_SDMA;
++
++ return 0;
++}
++
++static void ipath_7220_free_irq(struct ipath_devdata *dd)
++{
++ free_irq(dd->ipath_irq, dd);
++ dd->ipath_irq = 0;
++}
++
++static struct ipath_message_header *
++ipath_7220_get_msgheader(struct ipath_devdata *dd, __le32 *rhf_addr)
++{
++ u32 offset = ipath_hdrget_offset(rhf_addr);
++
++ return (struct ipath_message_header *)
++ (rhf_addr - dd->ipath_rhf_offset + offset);
++}
++
++static void ipath_7220_config_ports(struct ipath_devdata *dd, ushort cfgports)
++{
++ u32 nchipports;
++
++ nchipports = ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt);
++ if (!cfgports) {
++ int ncpus = num_online_cpus();
++
++ if (ncpus <= 4)
++ dd->ipath_portcnt = 5;
++ else if (ncpus <= 8)
++ dd->ipath_portcnt = 9;
++ if (dd->ipath_portcnt)
++ ipath_dbg("Auto-configured for %u ports, %d cpus "
++ "online\n", dd->ipath_portcnt, ncpus);
++ } else if (cfgports <= nchipports)
++ dd->ipath_portcnt = cfgports;
++ if (!dd->ipath_portcnt) /* none of the above, set to max */
++ dd->ipath_portcnt = nchipports;
++ /*
++ * chip can be configured for 5, 9, or 17 ports, and choice
++ * affects number of eager TIDs per port (1K, 2K, 4K).
++ */
++ if (dd->ipath_portcnt > 9)
++ dd->ipath_rcvctrl |= 2ULL << IBA7220_R_PORTCFG_SHIFT;
++ else if (dd->ipath_portcnt > 5)
++ dd->ipath_rcvctrl |= 1ULL << IBA7220_R_PORTCFG_SHIFT;
++ /* else configure for default 5 receive ports */
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
++ dd->ipath_rcvctrl);
++ dd->ipath_p0_rcvegrcnt = 2048; /* always */
++ if (dd->ipath_flags & IPATH_HAS_SEND_DMA)
++ dd->ipath_pioreserved = 1; /* reserve a buffer */
++}
++
++
++static int ipath_7220_get_ib_cfg(struct ipath_devdata *dd, int which)
++{
++ int lsb, ret = 0;
++ u64 maskr; /* right-justified mask */
++
++ switch (which) {
++ case IPATH_IB_CFG_HRTBT: /* Get Heartbeat off/enable/auto */
++ lsb = IBA7220_IBC_HRTBT_SHIFT;
++ maskr = IBA7220_IBC_HRTBT_MASK;
++ break;
++
++ case IPATH_IB_CFG_LWID_ENB: /* Get allowed Link-width */
++ ret = dd->ipath_link_width_enabled;
++ goto done;
++
++ case IPATH_IB_CFG_LWID: /* Get currently active Link-width */
++ ret = dd->ipath_link_width_active;
++ goto done;
++
++ case IPATH_IB_CFG_SPD_ENB: /* Get allowed Link speeds */
++ ret = dd->ipath_link_speed_enabled;
++ goto done;
++
++ case IPATH_IB_CFG_SPD: /* Get current Link spd */
++ ret = dd->ipath_link_speed_active;
++ goto done;
++
++ case IPATH_IB_CFG_RXPOL_ENB: /* Get Auto-RX-polarity enable */
++ lsb = IBA7220_IBC_RXPOL_SHIFT;
++ maskr = IBA7220_IBC_RXPOL_MASK;
++ break;
++
++ case IPATH_IB_CFG_LREV_ENB: /* Get Auto-Lane-reversal enable */
++ lsb = IBA7220_IBC_LREV_SHIFT;
++ maskr = IBA7220_IBC_LREV_MASK;
++ break;
++
++ case IPATH_IB_CFG_LINKLATENCY:
++ ret = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcddrstatus)
++ & IBA7220_DDRSTAT_LINKLAT_MASK;
++ goto done;
++
++ default:
++ ret = -ENOTSUPP;
++ goto done;
++ }
++ ret = (int)((dd->ipath_ibcddrctrl >> lsb) & maskr);
++done:
++ return ret;
++}
++
++static int ipath_7220_set_ib_cfg(struct ipath_devdata *dd, int which, u32 val)
++{
++ int lsb, ret = 0, setforce = 0;
++ u64 maskr; /* right-justified mask */
++
++ switch (which) {
++ case IPATH_IB_CFG_LIDLMC:
++ /*
++ * Set LID and LMC. Combined to avoid possible hazard
++ * caller puts LMC in 16MSbits, DLID in 16LSbits of val
++ */
++ lsb = IBA7220_IBC_DLIDLMC_SHIFT;
++ maskr = IBA7220_IBC_DLIDLMC_MASK;
++ break;
++
++ case IPATH_IB_CFG_HRTBT: /* set Heartbeat off/enable/auto */
++ if (val & IPATH_IB_HRTBT_ON &&
++ (dd->ipath_flags & IPATH_NO_HRTBT))
++ goto bail;
++ lsb = IBA7220_IBC_HRTBT_SHIFT;
++ maskr = IBA7220_IBC_HRTBT_MASK;
++ break;
++
++ case IPATH_IB_CFG_LWID_ENB: /* set allowed Link-width */
++ /*
++ * As with speed, only write the actual register if
++ * the link is currently down, otherwise takes effect
++ * on next link change.
++ */
++ dd->ipath_link_width_enabled = val;
++ if ((dd->ipath_flags & (IPATH_LINKDOWN|IPATH_LINKINIT)) !=
++ IPATH_LINKDOWN)
++ goto bail;
++ /*
++ * We set the IPATH_IB_FORCE_NOTIFY bit so updown
++ * will get called because we want update
++ * link_width_active, and the change may not take
++ * effect for some time (if we are in POLL), so this
++ * flag will force the updown routine to be called
++ * on the next ibstatuschange down interrupt, even
++ * if it's not an down->up transition.
++ */
++ val--; /* convert from IB to chip */
++ maskr = IBA7220_IBC_WIDTH_MASK;
++ lsb = IBA7220_IBC_WIDTH_SHIFT;
++ setforce = 1;
++ dd->ipath_flags |= IPATH_IB_FORCE_NOTIFY;
++ break;
++
++ case IPATH_IB_CFG_SPD_ENB: /* set allowed Link speeds */
++ /*
++ * If we turn off IB1.2, need to preset SerDes defaults,
++ * but not right now. Set a flag for the next time
++ * we command the link down. As with width, only write the
++ * actual register if the link is currently down, otherwise
++ * takes effect on next link change. Since setting is being
++ * explictly requested (via MAD or sysfs), clear autoneg
++ * failure status if speed autoneg is enabled.
++ */
++ dd->ipath_link_speed_enabled = val;
++ if (dd->ipath_ibcddrctrl & IBA7220_IBC_IBTA_1_2_MASK &&
++ !(val & (val - 1)))
++ dd->ipath_presets_needed = 1;
++ if ((dd->ipath_flags & (IPATH_LINKDOWN|IPATH_LINKINIT)) !=
++ IPATH_LINKDOWN)
++ goto bail;
++ /*
++ * We set the IPATH_IB_FORCE_NOTIFY bit so updown
++ * will get called because we want update
++ * link_speed_active, and the change may not take
++ * effect for some time (if we are in POLL), so this
++ * flag will force the updown routine to be called
++ * on the next ibstatuschange down interrupt, even
++ * if it's not an down->up transition. When setting
++ * speed autoneg, clear AUTONEG_FAILED.
++ */
++ if (val == (IPATH_IB_SDR | IPATH_IB_DDR)) {
++ val = IBA7220_IBC_SPEED_AUTONEG_MASK |
++ IBA7220_IBC_IBTA_1_2_MASK;
++ dd->ipath_flags &= ~IPATH_IB_AUTONEG_FAILED;
++ } else
++ val = val == IPATH_IB_DDR ? IBA7220_IBC_SPEED_DDR
++ : IBA7220_IBC_SPEED_SDR;
++ maskr = IBA7220_IBC_SPEED_AUTONEG_MASK |
++ IBA7220_IBC_IBTA_1_2_MASK;
++ lsb = 0; /* speed bits are low bits */
++ setforce = 1;
++ break;
++
++ case IPATH_IB_CFG_RXPOL_ENB: /* set Auto-RX-polarity enable */
++ lsb = IBA7220_IBC_RXPOL_SHIFT;
++ maskr = IBA7220_IBC_RXPOL_MASK;
++ break;
++
++ case IPATH_IB_CFG_LREV_ENB: /* set Auto-Lane-reversal enable */
++ lsb = IBA7220_IBC_LREV_SHIFT;
++ maskr = IBA7220_IBC_LREV_MASK;
++ break;
++
++ default:
++ ret = -ENOTSUPP;
++ goto bail;
++ }
++ dd->ipath_ibcddrctrl &= ~(maskr << lsb);
++ dd->ipath_ibcddrctrl |= (((u64) val & maskr) << lsb);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcddrctrl,
++ dd->ipath_ibcddrctrl);
++ if (setforce)
++ dd->ipath_flags |= IPATH_IB_FORCE_NOTIFY;
++bail:
++ return ret;
++}
++
++static void ipath_7220_read_counters(struct ipath_devdata *dd,
++ struct infinipath_counters *cntrs)
++{
++ u64 *counters = (u64 *) cntrs;
++ int i;
++
++ for (i = 0; i < sizeof(*cntrs) / sizeof(u64); i++)
++ counters[i] = ipath_snap_cntr(dd, i);
++}
++
++/* if we are using MSI, try to fallback to INTx */
++static int ipath_7220_intr_fallback(struct ipath_devdata *dd)
++{
++ if (dd->ipath_msi_lo) {
++ dev_info(&dd->pcidev->dev, "MSI interrupt not detected,"
++ " trying INTx interrupts\n");
++ ipath_7220_nomsi(dd);
++ ipath_enable_intx(dd->pcidev);
++ /*
++ * some newer kernels require free_irq before disable_msi,
++ * and irq can be changed during disable and intx enable
++ * and we need to therefore use the pcidev->irq value,
++ * not our saved MSI value.
++ */
++ dd->ipath_irq = dd->pcidev->irq;
++ if (request_irq(dd->ipath_irq, ipath_intr, IRQF_SHARED,
++ IPATH_DRV_NAME, dd))
++ ipath_dev_err(dd,
++ "Could not re-request_irq for INTx\n");
++ return 1;
++ }
++ return 0;
++}
++
++/*
++ * reset the XGXS (between serdes and IBC). Slightly less intrusive
++ * than resetting the IBC or external link state, and useful in some
++ * cases to cause some retraining. To do this right, we reset IBC
++ * as well.
++ */
++static void ipath_7220_xgxs_reset(struct ipath_devdata *dd)
++{
++ u64 val, prev_val;
++
++ prev_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
++ val = prev_val | INFINIPATH_XGXS_RESET;
++ prev_val &= ~INFINIPATH_XGXS_RESET; /* be sure */
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
++ dd->ipath_control & ~INFINIPATH_C_LINKENABLE);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
++ ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, prev_val);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
++ dd->ipath_control);
++}
++
++
++/* Still needs cleanup, too much hardwired stuff */
++static void autoneg_send(struct ipath_devdata *dd,
++ u32 *hdr, u32 dcnt, u32 *data)
++{
++ int i;
++ u64 cnt;
++ u32 __iomem *piobuf;
++ u32 pnum;
++
++ i = 0;
++ cnt = 7 + dcnt + 1; /* 7 dword header, dword data, icrc */
++ while (!(piobuf = ipath_getpiobuf(dd, cnt, &pnum))) {
++ if (i++ > 15) {
++ ipath_dbg("Couldn't get pio buffer for send\n");
++ return;
++ }
++ udelay(2);
++ }
++ if (dd->ipath_flags&IPATH_HAS_PBC_CNT)
++ cnt |= 0x80000000UL<<32; /* mark as VL15 */
++ writeq(cnt, piobuf);
++ ipath_flush_wc();
++ __iowrite32_copy(piobuf + 2, hdr, 7);
++ __iowrite32_copy(piobuf + 9, data, dcnt);
++ ipath_flush_wc();
++}
++
++/*
++ * _start packet gets sent twice at start, _done gets sent twice at end
++ */
++static void ipath_autoneg_send(struct ipath_devdata *dd, int which)
++{
++ static u32 swapped;
++ u32 dw, i, hcnt, dcnt, *data;
++ static u32 hdr[7] = { 0xf002ffff, 0x48ffff, 0x6400abba };
++ static u32 madpayload_start[0x40] = {
++ 0x1810103, 0x1, 0x0, 0x0, 0x2c90000, 0x2c9, 0x0, 0x0,
++ 0xffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
++ 0x1, 0x1388, 0x15e, 0x1, /* rest 0's */
++ };
++ static u32 madpayload_done[0x40] = {
++ 0x1810103, 0x1, 0x0, 0x0, 0x2c90000, 0x2c9, 0x0, 0x0,
++ 0xffffffff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
++ 0x40000001, 0x1388, 0x15e, /* rest 0's */
++ };
++ dcnt = sizeof(madpayload_start)/sizeof(madpayload_start[0]);
++ hcnt = sizeof(hdr)/sizeof(hdr[0]);
++ if (!swapped) {
++ /* for maintainability, do it at runtime */
++ for (i = 0; i < hcnt; i++) {
++ dw = (__force u32) cpu_to_be32(hdr[i]);
++ hdr[i] = dw;
++ }
++ for (i = 0; i < dcnt; i++) {
++ dw = (__force u32) cpu_to_be32(madpayload_start[i]);
++ madpayload_start[i] = dw;
++ dw = (__force u32) cpu_to_be32(madpayload_done[i]);
++ madpayload_done[i] = dw;
++ }
++ swapped = 1;
++ }
++
++ data = which ? madpayload_done : madpayload_start;
++ ipath_cdbg(PKT, "Sending %s special MADs\n", which?"done":"start");
++
++ autoneg_send(dd, hdr, dcnt, data);
++ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++ udelay(2);
++ autoneg_send(dd, hdr, dcnt, data);
++ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++ udelay(2);
++}
++
++
++
++/*
++ * Do the absolute minimum to cause an IB speed change, and make it
++ * ready, but don't actually trigger the change. The caller will
++ * do that when ready (if link is in Polling training state, it will
++ * happen immediately, otherwise when link next goes down)
++ *
++ * This routine should only be used as part of the DDR autonegotation
++ * code for devices that are not compliant with IB 1.2 (or code that
++ * fixes things up for same).
++ *
++ * When link has gone down, and autoneg enabled, or autoneg has
++ * failed and we give up until next time we set both speeds, and
++ * then we want IBTA enabled as well as "use max enabled speed.
++ */
++static void set_speed_fast(struct ipath_devdata *dd, u32 speed)
++{
++ dd->ipath_ibcddrctrl &= ~(IBA7220_IBC_SPEED_AUTONEG_MASK |
++ IBA7220_IBC_IBTA_1_2_MASK |
++ (IBA7220_IBC_WIDTH_MASK << IBA7220_IBC_WIDTH_SHIFT));
++
++ if (speed == (IPATH_IB_SDR | IPATH_IB_DDR))
++ dd->ipath_ibcddrctrl |= IBA7220_IBC_SPEED_AUTONEG_MASK |
++ IBA7220_IBC_IBTA_1_2_MASK;
++ else
++ dd->ipath_ibcddrctrl |= speed == IPATH_IB_DDR ?
++ IBA7220_IBC_SPEED_DDR : IBA7220_IBC_SPEED_SDR;
++
++ /*
++ * Convert from IB-style 1 = 1x, 2 = 4x, 3 = auto
++ * to chip-centric 0 = 1x, 1 = 4x, 2 = auto
++ */
++ dd->ipath_ibcddrctrl |= (u64)(dd->ipath_link_width_enabled - 1) <<
++ IBA7220_IBC_WIDTH_SHIFT;
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcddrctrl,
++ dd->ipath_ibcddrctrl);
++ ipath_cdbg(VERBOSE, "setup for IB speed (%x) done\n", speed);
++}
++
++
++/*
++ * this routine is only used when we are not talking to another
++ * IB 1.2-compliant device that we think can do DDR.
++ * (This includes all existing switch chips as of Oct 2007.)
++ * 1.2-compliant devices go directly to DDR prior to reaching INIT
++ */
++static void try_auto_neg(struct ipath_devdata *dd)
++{
++ /*
++ * required for older non-IB1.2 DDR switches. Newer
++ * non-IB-compliant switches don't need it, but so far,
++ * aren't bothered by it either. "Magic constant"
++ */
++ ipath_write_kreg(dd, IPATH_KREG_OFFSET(IBNCModeCtrl),
++ 0x3b9dc07);
++ dd->ipath_flags |= IPATH_IB_AUTONEG_INPROG;
++ ipath_autoneg_send(dd, 0);
++ set_speed_fast(dd, IPATH_IB_DDR);
++ ipath_toggle_rclkrls(dd);
++ /* 2 msec is minimum length of a poll cycle */
++ schedule_delayed_work(&dd->ipath_autoneg_work,
++ msecs_to_jiffies(2));
++}
++
++
++static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
++{
++ int ret = 0;
++ u32 ltstate = ipath_ib_linkstate(dd, ibcs);
++
++ dd->ipath_link_width_active =
++ ((ibcs >> IBA7220_IBCS_LINKWIDTH_SHIFT) & 1) ?
++ IB_WIDTH_4X : IB_WIDTH_1X;
++ dd->ipath_link_speed_active =
++ ((ibcs >> IBA7220_IBCS_LINKSPEED_SHIFT) & 1) ?
++ IPATH_IB_DDR : IPATH_IB_SDR;
++
++ if (!ibup) {
++ /*
++ * when link goes down we don't want aeq running, so it
++ * won't't interfere with IBC training, etc., and we need
++ * to go back to the static SerDes preset values
++ */
++ if (dd->ipath_x1_fix_tries &&
++ ltstate <= INFINIPATH_IBCS_LT_STATE_SLEEPQUIET &&
++ ltstate != INFINIPATH_IBCS_LT_STATE_LINKUP)
++ dd->ipath_x1_fix_tries = 0;
++ if (!(dd->ipath_flags & (IPATH_IB_AUTONEG_FAILED |
++ IPATH_IB_AUTONEG_INPROG)))
++ set_speed_fast(dd, dd->ipath_link_speed_enabled);
++ if (!(dd->ipath_flags & IPATH_IB_AUTONEG_INPROG)) {
++ ipath_cdbg(VERBOSE, "Setting RXEQ defaults\n");
++ ipath_sd7220_presets(dd);
++ }
++ /* this might better in ipath_sd7220_presets() */
++ ipath_set_relock_poll(dd, ibup);
++ } else {
++ if (ipath_compat_ddr_negotiate &&
++ !(dd->ipath_flags & (IPATH_IB_AUTONEG_FAILED |
++ IPATH_IB_AUTONEG_INPROG)) &&
++ dd->ipath_link_speed_active == IPATH_IB_SDR &&
++ (dd->ipath_link_speed_enabled &
++ (IPATH_IB_DDR | IPATH_IB_SDR)) ==
++ (IPATH_IB_DDR | IPATH_IB_SDR) &&
++ dd->ipath_autoneg_tries < IPATH_AUTONEG_TRIES) {
++ /* we are SDR, and DDR auto-negotiation enabled */
++ ++dd->ipath_autoneg_tries;
++ ipath_dbg("DDR negotiation try, %u/%u\n",
++ dd->ipath_autoneg_tries,
++ IPATH_AUTONEG_TRIES);
++ try_auto_neg(dd);
++ ret = 1; /* no other IB status change processing */
++ } else if ((dd->ipath_flags & IPATH_IB_AUTONEG_INPROG)
++ && dd->ipath_link_speed_active == IPATH_IB_SDR) {
++ ipath_autoneg_send(dd, 1);
++ set_speed_fast(dd, IPATH_IB_DDR);
++ udelay(2);
++ ipath_toggle_rclkrls(dd);
++ ret = 1; /* no other IB status change processing */
++ } else {
++ if ((dd->ipath_flags & IPATH_IB_AUTONEG_INPROG) &&
++ (dd->ipath_link_speed_active & IPATH_IB_DDR)) {
++ ipath_dbg("Got to INIT with DDR autoneg\n");
++ dd->ipath_flags &= ~(IPATH_IB_AUTONEG_INPROG
++ | IPATH_IB_AUTONEG_FAILED);
++ dd->ipath_autoneg_tries = 0;
++ /* re-enable SDR, for next link down */
++ set_speed_fast(dd,
++ dd->ipath_link_speed_enabled);
++ wake_up(&dd->ipath_autoneg_wait);
++ } else if (dd->ipath_flags & IPATH_IB_AUTONEG_FAILED) {
++ /*
++ * clear autoneg failure flag, and do setup
++ * so we'll try next time link goes down and
++ * back to INIT (possibly connected to different
++ * device).
++ */
++ ipath_dbg("INIT %sDR after autoneg failure\n",
++ (dd->ipath_link_speed_active &
++ IPATH_IB_DDR) ? "D" : "S");
++ dd->ipath_flags &= ~IPATH_IB_AUTONEG_FAILED;
++ dd->ipath_ibcddrctrl |=
++ IBA7220_IBC_IBTA_1_2_MASK;
++ ipath_write_kreg(dd,
++ IPATH_KREG_OFFSET(IBNCModeCtrl), 0);
++ }
++ }
++ /*
++ * if we are in 1X, and are in autoneg width, it
++ * could be due to an xgxs problem, so if we haven't
++ * already tried, try twice to get to 4X; if we
++ * tried, and couldn't, report it, since it will
++ * probably not be what is desired.
++ */
++ if ((dd->ipath_link_width_enabled & (IB_WIDTH_1X |
++ IB_WIDTH_4X)) == (IB_WIDTH_1X | IB_WIDTH_4X)
++ && dd->ipath_link_width_active == IB_WIDTH_1X
++ && dd->ipath_x1_fix_tries < 3) {
++ if (++dd->ipath_x1_fix_tries == 3)
++ dev_info(&dd->pcidev->dev,
++ "IB link is in 1X mode\n");
++ else {
++ ipath_cdbg(VERBOSE, "IB 1X in "
++ "auto-width, try %u to be "
++ "sure it's really 1X; "
++ "ltstate %u\n",
++ dd->ipath_x1_fix_tries,
++ ltstate);
++ dd->ipath_f_xgxs_reset(dd);
++ ret = 1; /* skip other processing */
++ }
++ }
++
++ if (!ret) {
++ dd->delay_mult = rate_to_delay
++ [(ibcs >> IBA7220_IBCS_LINKSPEED_SHIFT) & 1]
++ [(ibcs >> IBA7220_IBCS_LINKWIDTH_SHIFT) & 1];
++
++ ipath_set_relock_poll(dd, ibup);
++ }
++ }
++
++ if (!ret)
++ ipath_setup_7220_setextled(dd, ipath_ib_linkstate(dd, ibcs),
++ ltstate);
++ return ret;
++}
++
++
++/*
++ * Handle the empirically determined mechanism for auto-negotiation
++ * of DDR speed with switches.
++ */
++static void autoneg_work(struct work_struct *work)
++{
++ struct ipath_devdata *dd;
++ u64 startms;
++ u32 lastlts, i;
++
++ dd = container_of(work, struct ipath_devdata,
++ ipath_autoneg_work.work);
++
++ startms = jiffies_to_msecs(jiffies);
++
++ /*
++ * busy wait for this first part, it should be at most a
++ * few hundred usec, since we scheduled ourselves for 2msec.
++ */
++ for (i = 0; i < 25; i++) {
++ lastlts = ipath_ib_linktrstate(dd, dd->ipath_lastibcstat);
++ if (lastlts == INFINIPATH_IBCS_LT_STATE_POLLQUIET) {
++ ipath_set_linkstate(dd, IPATH_IB_LINKDOWN_DISABLE);
++ break;
++ }
++ udelay(100);
++ }
++
++ if (!(dd->ipath_flags & IPATH_IB_AUTONEG_INPROG))
++ goto done; /* we got there early or told to stop */
++
++ /* we expect this to timeout */
++ if (wait_event_timeout(dd->ipath_autoneg_wait,
++ !(dd->ipath_flags & IPATH_IB_AUTONEG_INPROG),
++ msecs_to_jiffies(90)))
++ goto done;
++
++ ipath_toggle_rclkrls(dd);
++
++ /* we expect this to timeout */
++ if (wait_event_timeout(dd->ipath_autoneg_wait,
++ !(dd->ipath_flags & IPATH_IB_AUTONEG_INPROG),
++ msecs_to_jiffies(1700)))
++ goto done;
++
++ set_speed_fast(dd, IPATH_IB_SDR);
++ ipath_toggle_rclkrls(dd);
++
++ /*
++ * wait up to 250 msec for link to train and get to INIT at DDR;
++ * this should terminate early
++ */
++ wait_event_timeout(dd->ipath_autoneg_wait,
++ !(dd->ipath_flags & IPATH_IB_AUTONEG_INPROG),
++ msecs_to_jiffies(250));
++done:
++ if (dd->ipath_flags & IPATH_IB_AUTONEG_INPROG) {
++ ipath_dbg("Did not get to DDR INIT (%x) after %Lu msecs\n",
++ ipath_ib_state(dd, dd->ipath_lastibcstat),
++ jiffies_to_msecs(jiffies)-startms);
++ dd->ipath_flags &= ~IPATH_IB_AUTONEG_INPROG;
++ if (dd->ipath_autoneg_tries == IPATH_AUTONEG_TRIES) {
++ dd->ipath_flags |= IPATH_IB_AUTONEG_FAILED;
++ ipath_dbg("Giving up on DDR until next IB "
++ "link Down\n");
++ dd->ipath_autoneg_tries = 0;
++ }
++ set_speed_fast(dd, dd->ipath_link_speed_enabled);
++ }
++}
++
++
++/**
++ * ipath_init_iba7220_funcs - set up the chip-specific function pointers
++ * @dd: the infinipath device
++ *
++ * This is global, and is called directly at init to set up the
++ * chip-specific function pointers for later use.
++ */
++void ipath_init_iba7220_funcs(struct ipath_devdata *dd)
++{
++ dd->ipath_f_intrsetup = ipath_7220_intconfig;
++ dd->ipath_f_bus = ipath_setup_7220_config;
++ dd->ipath_f_reset = ipath_setup_7220_reset;
++ dd->ipath_f_get_boardname = ipath_7220_boardname;
++ dd->ipath_f_init_hwerrors = ipath_7220_init_hwerrors;
++ dd->ipath_f_early_init = ipath_7220_early_init;
++ dd->ipath_f_handle_hwerrors = ipath_7220_handle_hwerrors;
++ dd->ipath_f_quiet_serdes = ipath_7220_quiet_serdes;
++ dd->ipath_f_bringup_serdes = ipath_7220_bringup_serdes;
++ dd->ipath_f_clear_tids = ipath_7220_clear_tids;
++ dd->ipath_f_put_tid = ipath_7220_put_tid;
++ dd->ipath_f_cleanup = ipath_setup_7220_cleanup;
++ dd->ipath_f_setextled = ipath_setup_7220_setextled;
++ dd->ipath_f_get_base_info = ipath_7220_get_base_info;
++ dd->ipath_f_free_irq = ipath_7220_free_irq;
++ dd->ipath_f_tidtemplate = ipath_7220_tidtemplate;
++ dd->ipath_f_intr_fallback = ipath_7220_intr_fallback;
++ dd->ipath_f_xgxs_reset = ipath_7220_xgxs_reset;
++ dd->ipath_f_get_ib_cfg = ipath_7220_get_ib_cfg;
++ dd->ipath_f_set_ib_cfg = ipath_7220_set_ib_cfg;
++ dd->ipath_f_config_jint = ipath_7220_config_jint;
++ dd->ipath_f_config_ports = ipath_7220_config_ports;
++ dd->ipath_f_read_counters = ipath_7220_read_counters;
++ dd->ipath_f_get_msgheader = ipath_7220_get_msgheader;
++ dd->ipath_f_ib_updown = ipath_7220_ib_updown;
++
++ /* initialize chip-specific variables */
++ ipath_init_7220_variables(dd);
++}
+diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c
+index 4471674..27dd894 100644
+--- a/drivers/infiniband/hw/ipath/ipath_init_chip.c
++++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+@@ -155,24 +155,13 @@ static int bringup_link(struct ipath_devdata *dd)
+ dd->ipath_control);
+
+ /*
+- * Note that prior to try 14 or 15 of IB, the credit scaling
+- * wasn't working, because it was swapped for writes with the
+- * 1 bit default linkstate field
++ * set initial max size pkt IBC will send, including ICRC; it's the
++ * PIO buffer size in dwords, less 1; also see ipath_set_mtu()
+ */
++ val = (dd->ipath_ibmaxlen >> 2) + 1;
++ ibc = val << dd->ibcc_mpl_shift;
+
+- /* ignore pbc and align word */
+- val = dd->ipath_piosize2k - 2 * sizeof(u32);
+- /*
+- * for ICRC, which we only send in diag test pkt mode, and we
+- * don't need to worry about that for mtu
+- */
+- val += 1;
+- /*
+- * Set the IBC maxpktlength to the size of our pio buffers the
+- * maxpktlength is in words. This is *not* the IB data MTU.
+- */
+- ibc = (val / sizeof(u32)) << INFINIPATH_IBCC_MAXPKTLEN_SHIFT;
+- /* in KB */
++ /* flowcontrolwatermark is in units of KBytes */
+ ibc |= 0x5ULL << INFINIPATH_IBCC_FLOWCTRLWATERMARK_SHIFT;
+ /*
+ * How often flowctrl sent. More or less in usecs; balance against
+@@ -191,10 +180,13 @@ static int bringup_link(struct ipath_devdata *dd)
+ /*
+ * Want to start out with both LINKCMD and LINKINITCMD in NOP
+ * (0 and 0). Don't put linkinitcmd in ipath_ibcctrl, want that
+- * to stay a NOP
++ * to stay a NOP. Flag that we are disabled, for the (unlikely)
++ * case that some recovery path is trying to bring the link up
++ * before we are ready.
+ */
+ ibc |= INFINIPATH_IBCC_LINKINITCMD_DISABLE <<
+ INFINIPATH_IBCC_LINKINITCMD_SHIFT;
++ dd->ipath_flags |= IPATH_IB_LINK_DISABLED;
+ ipath_cdbg(VERBOSE, "Writing 0x%llx to ibcctrl\n",
+ (unsigned long long) ibc);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, ibc);
+@@ -227,17 +219,26 @@ static struct ipath_portdata *create_portdata0(struct ipath_devdata *dd)
+ pd->port_cnt = 1;
+ /* The port 0 pkey table is used by the layer interface. */
+ pd->port_pkeys[0] = IPATH_DEFAULT_P_KEY;
++ pd->port_seq_cnt = 1;
+ }
+ return pd;
+ }
+
+-static int init_chip_first(struct ipath_devdata *dd,
+- struct ipath_portdata **pdp)
++static int init_chip_first(struct ipath_devdata *dd)
+ {
+- struct ipath_portdata *pd = NULL;
++ struct ipath_portdata *pd;
+ int ret = 0;
+ u64 val;
+
++ spin_lock_init(&dd->ipath_kernel_tid_lock);
++ spin_lock_init(&dd->ipath_user_tid_lock);
++ spin_lock_init(&dd->ipath_sendctrl_lock);
++ spin_lock_init(&dd->ipath_sdma_lock);
++ spin_lock_init(&dd->ipath_gpio_lock);
++ spin_lock_init(&dd->ipath_eep_st_lock);
++ spin_lock_init(&dd->ipath_sdepb_lock);
++ mutex_init(&dd->ipath_eep_lock);
++
+ /*
+ * skip cfgports stuff because we are not allocating memory,
+ * and we don't want problems if the portcnt changed due to
+@@ -250,12 +251,14 @@ static int init_chip_first(struct ipath_devdata *dd,
+ else if (ipath_cfgports <= dd->ipath_portcnt) {
+ dd->ipath_cfgports = ipath_cfgports;
+ ipath_dbg("Configured to use %u ports out of %u in chip\n",
+- dd->ipath_cfgports, dd->ipath_portcnt);
++ dd->ipath_cfgports, ipath_read_kreg32(dd,
++ dd->ipath_kregs->kr_portcnt));
+ } else {
+ dd->ipath_cfgports = dd->ipath_portcnt;
+ ipath_dbg("Tried to configured to use %u ports; chip "
+ "only supports %u\n", ipath_cfgports,
+- dd->ipath_portcnt);
++ ipath_read_kreg32(dd,
++ dd->ipath_kregs->kr_portcnt));
+ }
+ /*
+ * Allocate full portcnt array, rather than just cfgports, because
+@@ -295,12 +298,9 @@ static int init_chip_first(struct ipath_devdata *dd,
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiosize);
+ dd->ipath_piosize2k = val & ~0U;
+ dd->ipath_piosize4k = val >> 32;
+- /*
+- * Note: the chips support a maximum MTU of 4096, but the driver
+- * hasn't implemented this feature yet, so set the initial value
+- * to 2048.
+- */
+- dd->ipath_ibmtu = 2048;
++ if (dd->ipath_piosize4k == 0 && ipath_mtu4096)
++ ipath_mtu4096 = 0; /* 4KB not supported by this chip */
++ dd->ipath_ibmtu = ipath_mtu4096 ? 4096 : 2048;
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiobufcnt);
+ dd->ipath_piobcnt2k = val & ~0U;
+ dd->ipath_piobcnt4k = val >> 32;
+@@ -328,43 +328,46 @@ static int init_chip_first(struct ipath_devdata *dd,
+ else ipath_dbg("%u 2k piobufs @ %p\n",
+ dd->ipath_piobcnt2k, dd->ipath_pio2kbase);
+
+- spin_lock_init(&dd->ipath_tid_lock);
+- spin_lock_init(&dd->ipath_sendctrl_lock);
+- spin_lock_init(&dd->ipath_gpio_lock);
+- spin_lock_init(&dd->ipath_eep_st_lock);
+- mutex_init(&dd->ipath_eep_lock);
+-
+ done:
+- *pdp = pd;
+ return ret;
+ }
+
+ /**
+ * init_chip_reset - re-initialize after a reset, or enable
+ * @dd: the infinipath device
+- * @pdp: output for port data
+ *
+ * sanity check at least some of the values after reset, and
+ * ensure no receive or transmit (explictly, in case reset
+ * failed
+ */
+-static int init_chip_reset(struct ipath_devdata *dd,
+- struct ipath_portdata **pdp)
++static int init_chip_reset(struct ipath_devdata *dd)
+ {
+ u32 rtmp;
++ int i;
++ unsigned long flags;
++
++ /*
++ * ensure chip does no sends or receives, tail updates, or
++ * pioavail updates while we re-initialize
++ */
++ dd->ipath_rcvctrl &= ~(1ULL << dd->ipath_r_tailupd_shift);
++ for (i = 0; i < dd->ipath_portcnt; i++) {
++ clear_bit(dd->ipath_r_portenable_shift + i,
++ &dd->ipath_rcvctrl);
++ clear_bit(dd->ipath_r_intravail_shift + i,
++ &dd->ipath_rcvctrl);
++ }
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
++ dd->ipath_rcvctrl);
+
+- *pdp = dd->ipath_pd[0];
+- /* ensure chip does no sends or receives while we re-initialize */
+- dd->ipath_control = dd->ipath_sendctrl = dd->ipath_rcvctrl = 0U;
+- ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, dd->ipath_rcvctrl);
++ spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++ dd->ipath_sendctrl = 0U; /* no sdma, etc */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
+- ipath_write_kreg(dd, dd->ipath_kregs->kr_control, dd->ipath_control);
++ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++ spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_control, 0ULL);
+
+- rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt);
+- if (dd->ipath_portcnt != rtmp)
+- dev_info(&dd->pcidev->dev, "portcnt was %u before "
+- "reset, now %u, using original\n",
+- dd->ipath_portcnt, rtmp);
+ rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidcnt);
+ if (rtmp != dd->ipath_rcvtidcnt)
+ dev_info(&dd->pcidev->dev, "tidcnt was %u before "
+@@ -467,10 +470,10 @@ static void init_shadow_tids(struct ipath_devdata *dd)
+ dd->ipath_physshadow = addrs;
+ }
+
+-static void enable_chip(struct ipath_devdata *dd,
+- struct ipath_portdata *pd, int reinit)
++static void enable_chip(struct ipath_devdata *dd, int reinit)
+ {
+ u32 val;
++ u64 rcvmask;
+ unsigned long flags;
+ int i;
+
+@@ -484,17 +487,28 @@ static void enable_chip(struct ipath_devdata *dd,
+ /* Enable PIO send, and update of PIOavail regs to memory. */
+ dd->ipath_sendctrl = INFINIPATH_S_PIOENABLE |
+ INFINIPATH_S_PIOBUFAVAILUPD;
++
++ /*
++ * Set the PIO avail update threshold to host memory
++ * on chips that support it.
++ */
++ if (dd->ipath_pioupd_thresh)
++ dd->ipath_sendctrl |= dd->ipath_pioupd_thresh
++ << INFINIPATH_S_UPDTHRESH_SHIFT;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
+
+ /*
+- * enable port 0 receive, and receive interrupt. other ports
+- * done as user opens and inits them.
++ * Enable kernel ports' receive and receive interrupt.
++ * Other ports done as user opens and inits them.
+ */
+- dd->ipath_rcvctrl = (1ULL << dd->ipath_r_tailupd_shift) |
+- (1ULL << dd->ipath_r_portenable_shift) |
+- (1ULL << dd->ipath_r_intravail_shift);
++ rcvmask = 1ULL;
++ dd->ipath_rcvctrl |= (rcvmask << dd->ipath_r_portenable_shift) |
++ (rcvmask << dd->ipath_r_intravail_shift);
++ if (!(dd->ipath_flags & IPATH_NODMA_RTAIL))
++ dd->ipath_rcvctrl |= (1ULL << dd->ipath_r_tailupd_shift);
++
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl);
+
+@@ -505,16 +519,16 @@ static void enable_chip(struct ipath_devdata *dd,
+ dd->ipath_flags |= IPATH_INITTED;
+
+ /*
+- * init our shadow copies of head from tail values, and write
+- * head values to match.
++ * Init our shadow copies of head from tail values,
++ * and write head values to match.
+ */
+ val = ipath_read_ureg32(dd, ur_rcvegrindextail, 0);
+- (void)ipath_write_ureg(dd, ur_rcvegrindexhead, val, 0);
++ ipath_write_ureg(dd, ur_rcvegrindexhead, val, 0);
+
+ /* Initialize so we interrupt on next packet received */
+- (void)ipath_write_ureg(dd, ur_rcvhdrhead,
+- dd->ipath_rhdrhead_intr_off |
+- dd->ipath_pd[0]->port_head, 0);
++ ipath_write_ureg(dd, ur_rcvhdrhead,
++ dd->ipath_rhdrhead_intr_off |
++ dd->ipath_pd[0]->port_head, 0);
+
+ /*
+ * by now pioavail updates to memory should have occurred, so
+@@ -523,25 +537,26 @@ static void enable_chip(struct ipath_devdata *dd,
+ * initial values of the generation bit correct.
+ */
+ for (i = 0; i < dd->ipath_pioavregs; i++) {
+- __le64 val;
++ __le64 pioavail;
+
+ /*
+ * Chip Errata bug 6641; even and odd qwords>3 are swapped.
+ */
+ if (i > 3 && (dd->ipath_flags & IPATH_SWAP_PIOBUFS))
+- val = dd->ipath_pioavailregs_dma[i ^ 1];
++ pioavail = dd->ipath_pioavailregs_dma[i ^ 1];
+ else
+- val = dd->ipath_pioavailregs_dma[i];
+- dd->ipath_pioavailshadow[i] = le64_to_cpu(val);
++ pioavail = dd->ipath_pioavailregs_dma[i];
++ dd->ipath_pioavailshadow[i] = le64_to_cpu(pioavail) |
++ (~dd->ipath_pioavailkernel[i] <<
++ INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT);
+ }
+ /* can get counters, stats, etc. */
+ dd->ipath_flags |= IPATH_PRESENT;
+ }
+
+-static int init_housekeeping(struct ipath_devdata *dd,
+- struct ipath_portdata **pdp, int reinit)
++static int init_housekeeping(struct ipath_devdata *dd, int reinit)
+ {
+- char boardn[32];
++ char boardn[40];
+ int ret = 0;
+
+ /*
+@@ -600,18 +615,9 @@ static int init_housekeeping(struct ipath_devdata *dd,
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear,
+ INFINIPATH_E_RESET);
+
+- if (reinit)
+- ret = init_chip_reset(dd, pdp);
+- else
+- ret = init_chip_first(dd, pdp);
+-
+- if (ret)
+- goto done;
+-
+- ipath_cdbg(VERBOSE, "Revision %llx (PCI %x), %u ports, %u tids, "
+- "%u egrtids\n", (unsigned long long) dd->ipath_revision,
+- dd->ipath_pcirev, dd->ipath_portcnt, dd->ipath_rcvtidcnt,
+- dd->ipath_rcvegrcnt);
++ ipath_cdbg(VERBOSE, "Revision %llx (PCI %x)\n",
++ (unsigned long long) dd->ipath_revision,
++ dd->ipath_pcirev);
+
+ if (((dd->ipath_revision >> INFINIPATH_R_SOFTWARE_SHIFT) &
+ INFINIPATH_R_SOFTWARE_MASK) != IPATH_CHIP_SWVERSION) {
+@@ -650,10 +656,39 @@ static int init_housekeeping(struct ipath_devdata *dd,
+
+ ipath_dbg("%s", dd->ipath_boardversion);
+
++ if (ret)
++ goto done;
++
++ if (reinit)
++ ret = init_chip_reset(dd);
++ else
++ ret = init_chip_first(dd);
++
+ done:
+ return ret;
+ }
+
++static void verify_interrupt(unsigned long opaque)
++{
++ struct ipath_devdata *dd = (struct ipath_devdata *) opaque;
++
++ if (!dd)
++ return; /* being torn down */
++
++ /*
++ * If we don't have any interrupts, let the user know and
++ * don't bother checking again.
++ */
++ if (dd->ipath_int_counter == 0) {
++ if (!dd->ipath_f_intr_fallback(dd))
++ dev_err(&dd->pcidev->dev, "No interrupts detected, "
++ "not usable.\n");
++ else /* re-arm the timer to see if fallback works */
++ mod_timer(&dd->ipath_intrchk_timer, jiffies + HZ/2);
++ } else
++ ipath_cdbg(VERBOSE, "%u interrupts at timer check\n",
++ dd->ipath_int_counter);
++}
+
+ /**
+ * ipath_init_chip - do the actual initialization sequence on the chip
+@@ -676,11 +711,11 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
+ u32 val32, kpiobufs;
+ u32 piobufs, uports;
+ u64 val;
+- struct ipath_portdata *pd = NULL; /* keep gcc4 happy */
++ struct ipath_portdata *pd;
+ gfp_t gfp_flags = GFP_USER | __GFP_COMP;
+ unsigned long flags;
+
+- ret = init_housekeeping(dd, &pd, reinit);
++ ret = init_housekeeping(dd, reinit);
+ if (ret)
+ goto done;
+
+@@ -700,7 +735,7 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
+ * we now use routines that backend onto __get_free_pages, the
+ * rest would be wasted.
+ */
+- dd->ipath_rcvhdrcnt = dd->ipath_rcvegrcnt;
++ dd->ipath_rcvhdrcnt = max(dd->ipath_p0_rcvegrcnt, dd->ipath_rcvegrcnt);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvhdrcnt,
+ dd->ipath_rcvhdrcnt);
+
+@@ -731,8 +766,8 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
+ if (kpiobufs + (uports * IPATH_MIN_USER_PORT_BUFCNT) > piobufs) {
+ int i = (int) piobufs -
+ (int) (uports * IPATH_MIN_USER_PORT_BUFCNT);
+- if (i < 0)
+- i = 0;
++ if (i < 1)
++ i = 1;
+ dev_info(&dd->pcidev->dev, "Allocating %d PIO bufs of "
+ "%d for kernel leaves too few for %d user ports "
+ "(%d each); using %u\n", kpiobufs,
+@@ -751,24 +786,40 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
+ ipath_dbg("allocating %u pbufs/port leaves %u unused, "
+ "add to kernel\n", dd->ipath_pbufsport, val32);
+ dd->ipath_lastport_piobuf -= val32;
++ kpiobufs += val32;
+ ipath_dbg("%u pbufs/port leaves %u unused, add to kernel\n",
+ dd->ipath_pbufsport, val32);
+ }
+- dd->ipath_lastpioindex = dd->ipath_lastport_piobuf;
++ dd->ipath_lastpioindex = 0;
++ dd->ipath_lastpioindexl = dd->ipath_piobcnt2k;
++ ipath_chg_pioavailkernel(dd, 0, piobufs, 1);
+ ipath_cdbg(VERBOSE, "%d PIO bufs for kernel out of %d total %u "
+ "each for %u user ports\n", kpiobufs,
+ piobufs, dd->ipath_pbufsport, uports);
++ if (dd->ipath_pioupd_thresh) {
++ if (dd->ipath_pbufsport < dd->ipath_pioupd_thresh)
++ dd->ipath_pioupd_thresh = dd->ipath_pbufsport;
++ if (kpiobufs < dd->ipath_pioupd_thresh)
++ dd->ipath_pioupd_thresh = kpiobufs;
++ }
++
++ ret = dd->ipath_f_early_init(dd);
++ if (ret) {
++ ipath_dev_err(dd, "Early initialization failure\n");
++ goto done;
++ }
+
+- dd->ipath_f_early_init(dd);
+ /*
+- * cancel any possible active sends from early driver load.
++ * Cancel any possible active sends from early driver load.
+ * Follows early_init because some chips have to initialize
+ * PIO buffers in early_init to avoid false parity errors.
+ */
+ ipath_cancel_sends(dd, 0);
+
+- /* early_init sets rcvhdrentsize and rcvhdrsize, so this must be
+- * done after early_init */
++ /*
++ * Early_init sets rcvhdrentsize and rcvhdrsize, so this must be
++ * done after early_init.
++ */
+ dd->ipath_hdrqlast =
+ dd->ipath_rcvhdrentsize * (dd->ipath_rcvhdrcnt - 1);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvhdrentsize,
+@@ -783,8 +834,8 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
+ goto done;
+ }
+
+- (void)ipath_write_kreg(dd, dd->ipath_kregs->kr_sendpioavailaddr,
+- dd->ipath_pioavailregs_phys);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendpioavailaddr,
++ dd->ipath_pioavailregs_phys);
+ /*
+ * this is to detect s/w errors, which the h/w works around by
+ * ignoring the low 6 bits of address, if it wasn't aligned.
+@@ -843,58 +894,65 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
+ /* enable errors that are masked, at least this first time. */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
+ ~dd->ipath_maskederrs);
+- dd->ipath_errormask = ipath_read_kreg64(dd,
+- dd->ipath_kregs->kr_errormask);
++ dd->ipath_maskederrs = 0; /* don't re-enable ignored in timer */
++ dd->ipath_errormask =
++ ipath_read_kreg64(dd, dd->ipath_kregs->kr_errormask);
+ /* clear any interrupts up to this point (ints still not enabled) */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, -1LL);
+
++ dd->ipath_f_tidtemplate(dd);
++
+ /*
+ * Set up the port 0 (kernel) rcvhdr q and egr TIDs. If doing
+ * re-init, the simplest way to handle this is to free
+ * existing, and re-allocate.
+ * Need to re-create rest of port 0 portdata as well.
+ */
++ pd = dd->ipath_pd[0];
+ if (reinit) {
+- /* Alloc and init new ipath_portdata for port0,
++ struct ipath_portdata *npd;
++
++ /*
++ * Alloc and init new ipath_portdata for port0,
+ * Then free old pd. Could lead to fragmentation, but also
+ * makes later support for hot-swap easier.
+ */
+- struct ipath_portdata *npd;
+ npd = create_portdata0(dd);
+ if (npd) {
+ ipath_free_pddata(dd, pd);
+- dd->ipath_pd[0] = pd = npd;
++ dd->ipath_pd[0] = npd;
++ pd = npd;
+ } else {
+- ipath_dev_err(dd, "Unable to allocate portdata for"
+- " port 0, failing\n");
++ ipath_dev_err(dd, "Unable to allocate portdata"
++ " for port 0, failing\n");
+ ret = -ENOMEM;
+ goto done;
+ }
+ }
+- dd->ipath_f_tidtemplate(dd);
+ ret = ipath_create_rcvhdrq(dd, pd);
+- if (!ret) {
+- dd->ipath_hdrqtailptr =
+- (volatile __le64 *)pd->port_rcvhdrtail_kvaddr;
++ if (!ret)
+ ret = create_port0_egr(dd);
+- }
+- if (ret)
+- ipath_dev_err(dd, "failed to allocate port 0 (kernel) "
++ if (ret) {
++ ipath_dev_err(dd, "failed to allocate kernel port's "
+ "rcvhdrq and/or egr bufs\n");
++ goto done;
++ }
+ else
+- enable_chip(dd, pd, reinit);
+-
++ enable_chip(dd, reinit);
+
+- if (!ret && !reinit) {
+- /* used when we close a port, for DMA already in flight at close */
++ if (!reinit) {
++ /*
++ * Used when we close a port, for DMA already in flight
++ * at close.
++ */
+ dd->ipath_dummy_hdrq = dma_alloc_coherent(
+- &dd->pcidev->dev, pd->port_rcvhdrq_size,
++ &dd->pcidev->dev, dd->ipath_pd[0]->port_rcvhdrq_size,
+ &dd->ipath_dummy_hdrq_phys,
+ gfp_flags);
+- if (!dd->ipath_dummy_hdrq ) {
++ if (!dd->ipath_dummy_hdrq) {
+ dev_info(&dd->pcidev->dev,
+ "Couldn't allocate 0x%lx bytes for dummy hdrq\n",
+- pd->port_rcvhdrq_size);
++ dd->ipath_pd[0]->port_rcvhdrq_size);
+ /* fallback to just 0'ing */
+ dd->ipath_dummy_hdrq_phys = 0UL;
+ }
+@@ -906,7 +964,7 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, 0ULL);
+
+- if(!dd->ipath_stats_timer_active) {
++ if (!dd->ipath_stats_timer_active) {
+ /*
+ * first init, or after an admin disable/enable
+ * set up stats retrieval timer, even if we had errors
+@@ -922,6 +980,16 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
+ dd->ipath_stats_timer_active = 1;
+ }
+
++ /* Set up SendDMA if chip supports it */
++ if (dd->ipath_flags & IPATH_HAS_SEND_DMA)
++ ret = setup_sdma(dd);
++
++ /* Set up HoL state */
++ init_timer(&dd->ipath_hol_timer);
++ dd->ipath_hol_timer.function = ipath_hol_event;
++ dd->ipath_hol_timer.data = (unsigned long)dd;
++ dd->ipath_hol_state = IPATH_HOL_UP;
++
+ done:
+ if (!ret) {
+ *dd->ipath_statusp |= IPATH_STATUS_CHIP_PRESENT;
+@@ -934,6 +1002,20 @@ done:
+ 0ULL);
+ /* chip is usable; mark it as initialized */
+ *dd->ipath_statusp |= IPATH_STATUS_INITTED;
++
++ /*
++ * setup to verify we get an interrupt, and fallback
++ * to an alternate if necessary and possible
++ */
++ if (!reinit) {
++ init_timer(&dd->ipath_intrchk_timer);
++ dd->ipath_intrchk_timer.function =
++ verify_interrupt;
++ dd->ipath_intrchk_timer.data =
++ (unsigned long) dd;
++ }
++ dd->ipath_intrchk_timer.expires = jiffies + HZ/2;
++ add_timer(&dd->ipath_intrchk_timer);
+ } else
+ ipath_dev_err(dd, "No interrupts enabled, couldn't "
+ "setup interrupt address\n");
+diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c
+index 92e58c9..1b58f47 100644
+--- a/drivers/infiniband/hw/ipath/ipath_intr.c
++++ b/drivers/infiniband/hw/ipath/ipath_intr.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+@@ -32,6 +32,7 @@
+ */
+
+ #include <linux/pci.h>
++#include <linux/delay.h>
+
+ #include "ipath_kernel.h"
+ #include "ipath_verbs.h"
+@@ -59,9 +60,11 @@ static void ipath_clrpiobuf(struct ipath_devdata *dd, u32 pnum)
+ dev_info(&dd->pcidev->dev,
+ "Rewrite PIO buffer %u, to recover from parity error\n",
+ pnum);
+- *pbuf = dwcnt+1; /* no flush required, since already in freeze */
+- while(--dwcnt)
+- *pbuf++ = 0;
++
++ /* no flush required, since already in freeze */
++ writel(dwcnt + 1, pbuf);
++ while (--dwcnt)
++ writel(0, pbuf++);
+ }
+
+ /*
+@@ -70,7 +73,7 @@ static void ipath_clrpiobuf(struct ipath_devdata *dd, u32 pnum)
+ * If rewrite is true, and bits are set in the sendbufferror registers,
+ * we'll write to the buffer, for error recovery on parity errors.
+ */
+-static void ipath_disarm_senderrbufs(struct ipath_devdata *dd, int rewrite)
++void ipath_disarm_senderrbufs(struct ipath_devdata *dd, int rewrite)
+ {
+ u32 piobcnt;
+ unsigned long sbuf[4];
+@@ -84,12 +87,14 @@ static void ipath_disarm_senderrbufs(struct ipath_devdata *dd, int rewrite)
+ dd, dd->ipath_kregs->kr_sendbuffererror);
+ sbuf[1] = ipath_read_kreg64(
+ dd, dd->ipath_kregs->kr_sendbuffererror + 1);
+- if (piobcnt > 128) {
++ if (piobcnt > 128)
+ sbuf[2] = ipath_read_kreg64(
+ dd, dd->ipath_kregs->kr_sendbuffererror + 2);
++ if (piobcnt > 192)
+ sbuf[3] = ipath_read_kreg64(
+ dd, dd->ipath_kregs->kr_sendbuffererror + 3);
+- }
++ else
++ sbuf[3] = 0;
+
+ if (sbuf[0] || sbuf[1] || (piobcnt > 128 && (sbuf[2] || sbuf[3]))) {
+ int i;
+@@ -254,24 +259,20 @@ void ipath_format_hwerrors(u64 hwerrs,
+ }
+
+ /* return the strings for the most common link states */
+-static char *ib_linkstate(u32 linkstate)
++static char *ib_linkstate(struct ipath_devdata *dd, u64 ibcs)
+ {
+ char *ret;
++ u32 state;
+
+- switch (linkstate) {
+- case IPATH_IBSTATE_INIT:
++ state = ipath_ib_state(dd, ibcs);
++ if (state == dd->ib_init)
+ ret = "Init";
+- break;
+- case IPATH_IBSTATE_ARM:
++ else if (state == dd->ib_arm)
+ ret = "Arm";
+- break;
+- case IPATH_IBSTATE_ACTIVE:
++ else if (state == dd->ib_active)
+ ret = "Active";
+- break;
+- default:
++ else
+ ret = "Down";
+- }
+-
+ return ret;
+ }
+
+@@ -286,103 +287,172 @@ void signal_ib_event(struct ipath_devdata *dd, enum ib_event_type ev)
+ }
+
+ static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
+- ipath_err_t errs, int noprint)
++ ipath_err_t errs)
+ {
+- u64 val;
+- u32 ltstate, lstate;
++ u32 ltstate, lstate, ibstate, lastlstate;
++ u32 init = dd->ib_init;
++ u32 arm = dd->ib_arm;
++ u32 active = dd->ib_active;
++ const u64 ibcs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
++
++ lstate = ipath_ib_linkstate(dd, ibcs); /* linkstate */
++ ibstate = ipath_ib_state(dd, ibcs);
++ /* linkstate at last interrupt */
++ lastlstate = ipath_ib_linkstate(dd, dd->ipath_lastibcstat);
++ ltstate = ipath_ib_linktrstate(dd, ibcs); /* linktrainingtate */
+
+ /*
+- * even if diags are enabled, we want to notice LINKINIT, etc.
+- * We just don't want to change the LED state, or
+- * dd->ipath_kregs->kr_ibcctrl
++ * Since going into a recovery state causes the link state to go
++ * down and since recovery is transitory, it is better if we "miss"
++ * ever seeing the link training state go into recovery (i.e.,
++ * ignore this transition for link state special handling purposes)
++ * without even updating ipath_lastibcstat.
+ */
+- val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
+- lstate = val & IPATH_IBSTATE_MASK;
++ if ((ltstate == INFINIPATH_IBCS_LT_STATE_RECOVERRETRAIN) ||
++ (ltstate == INFINIPATH_IBCS_LT_STATE_RECOVERWAITRMT) ||
++ (ltstate == INFINIPATH_IBCS_LT_STATE_RECOVERIDLE))
++ goto done;
+
+ /*
+- * this is confusing enough when it happens that I want to always put it
+- * on the console and in the logs. If it was a requested state change,
+- * we'll have already cleared the flags, so we won't print this warning
++ * if linkstate transitions into INIT from any of the various down
++ * states, or if it transitions from any of the up (INIT or better)
++ * states into any of the down states (except link recovery), then
++ * call the chip-specific code to take appropriate actions.
+ */
+- if ((lstate != IPATH_IBSTATE_ARM && lstate != IPATH_IBSTATE_ACTIVE)
+- && (dd->ipath_flags & (IPATH_LINKARMED | IPATH_LINKACTIVE))) {
+- dev_info(&dd->pcidev->dev, "Link state changed from %s to %s\n",
+- (dd->ipath_flags & IPATH_LINKARMED) ? "ARM" : "ACTIVE",
+- ib_linkstate(lstate));
+- /*
+- * Flush all queued sends when link went to DOWN or INIT,
+- * to be sure that they don't block SMA and other MAD packets
+- */
+- ipath_cancel_sends(dd, 1);
+- }
+- else if (lstate == IPATH_IBSTATE_INIT || lstate == IPATH_IBSTATE_ARM ||
+- lstate == IPATH_IBSTATE_ACTIVE) {
+- /*
+- * only print at SMA if there is a change, debug if not
+- * (sometimes we want to know that, usually not).
+- */
+- if (lstate == ((unsigned) dd->ipath_lastibcstat
+- & IPATH_IBSTATE_MASK)) {
+- ipath_dbg("Status change intr but no change (%s)\n",
+- ib_linkstate(lstate));
++ if (lstate >= INFINIPATH_IBCS_L_STATE_INIT &&
++ lastlstate == INFINIPATH_IBCS_L_STATE_DOWN) {
++ /* transitioned to UP */
++ if (dd->ipath_f_ib_updown(dd, 1, ibcs)) {
++ /* link came up, so we must no longer be disabled */
++ dd->ipath_flags &= ~IPATH_IB_LINK_DISABLED;
++ ipath_cdbg(LINKVERB, "LinkUp handled, skipped\n");
++ goto skip_ibchange; /* chip-code handled */
++ }
++ } else if ((lastlstate >= INFINIPATH_IBCS_L_STATE_INIT ||
++ (dd->ipath_flags & IPATH_IB_FORCE_NOTIFY)) &&
++ ltstate <= INFINIPATH_IBCS_LT_STATE_CFGWAITRMT &&
++ ltstate != INFINIPATH_IBCS_LT_STATE_LINKUP) {
++ int handled;
++ handled = dd->ipath_f_ib_updown(dd, 0, ibcs);
++ dd->ipath_flags &= ~IPATH_IB_FORCE_NOTIFY;
++ if (handled) {
++ ipath_cdbg(LINKVERB, "LinkDown handled, skipped\n");
++ goto skip_ibchange; /* chip-code handled */
+ }
+- else
+- ipath_cdbg(VERBOSE, "Unit %u link state %s, last "
+- "was %s\n", dd->ipath_unit,
+- ib_linkstate(lstate),
+- ib_linkstate((unsigned)
+- dd->ipath_lastibcstat
+- & IPATH_IBSTATE_MASK));
+ }
+- else {
+- lstate = dd->ipath_lastibcstat & IPATH_IBSTATE_MASK;
+- if (lstate == IPATH_IBSTATE_INIT ||
+- lstate == IPATH_IBSTATE_ARM ||
+- lstate == IPATH_IBSTATE_ACTIVE)
+- ipath_cdbg(VERBOSE, "Unit %u link state down"
+- " (state 0x%x), from %s\n",
+- dd->ipath_unit,
+- (u32)val & IPATH_IBSTATE_MASK,
+- ib_linkstate(lstate));
+- else
+- ipath_cdbg(VERBOSE, "Unit %u link state changed "
+- "to 0x%x from down (%x)\n",
+- dd->ipath_unit, (u32) val, lstate);
++
++ /*
++ * Significant enough to always print and get into logs, if it was
++ * unexpected. If it was a requested state change, we'll have
++ * already cleared the flags, so we won't print this warning
++ */
++ if ((ibstate != arm && ibstate != active) &&
++ (dd->ipath_flags & (IPATH_LINKARMED | IPATH_LINKACTIVE))) {
++ dev_info(&dd->pcidev->dev, "Link state changed from %s "
++ "to %s\n", (dd->ipath_flags & IPATH_LINKARMED) ?
++ "ARM" : "ACTIVE", ib_linkstate(dd, ibcs));
+ }
+- ltstate = (val >> INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) &
+- INFINIPATH_IBCS_LINKTRAININGSTATE_MASK;
+- lstate = (val >> INFINIPATH_IBCS_LINKSTATE_SHIFT) &
+- INFINIPATH_IBCS_LINKSTATE_MASK;
+
+ if (ltstate == INFINIPATH_IBCS_LT_STATE_POLLACTIVE ||
+ ltstate == INFINIPATH_IBCS_LT_STATE_POLLQUIET) {
+- u32 last_ltstate;
+-
++ u32 lastlts;
++ lastlts = ipath_ib_linktrstate(dd, dd->ipath_lastibcstat);
+ /*
+- * Ignore cycling back and forth from Polling.Active
+- * to Polling.Quiet while waiting for the other end of
+- * the link to come up. We will cycle back and forth
+- * between them if no cable is plugged in,
+- * the other device is powered off or disabled, etc.
++ * Ignore cycling back and forth from Polling.Active to
++ * Polling.Quiet while waiting for the other end of the link
++ * to come up, except to try and decide if we are connected
++ * to a live IB device or not. We will cycle back and
++ * forth between them if no cable is plugged in, the other
++ * device is powered off or disabled, etc.
+ */
+- last_ltstate = (dd->ipath_lastibcstat >>
+- INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT)
+- & INFINIPATH_IBCS_LINKTRAININGSTATE_MASK;
+- if (last_ltstate == INFINIPATH_IBCS_LT_STATE_POLLACTIVE
+- || last_ltstate ==
+- INFINIPATH_IBCS_LT_STATE_POLLQUIET) {
+- if (dd->ipath_ibpollcnt > 40) {
++ if (lastlts == INFINIPATH_IBCS_LT_STATE_POLLACTIVE ||
++ lastlts == INFINIPATH_IBCS_LT_STATE_POLLQUIET) {
++ if (!(dd->ipath_flags & IPATH_IB_AUTONEG_INPROG) &&
++ (++dd->ipath_ibpollcnt == 40)) {
+ dd->ipath_flags |= IPATH_NOCABLE;
+ *dd->ipath_statusp |=
+ IPATH_STATUS_IB_NOCABLE;
+- } else
+- dd->ipath_ibpollcnt++;
++ ipath_cdbg(LINKVERB, "Set NOCABLE\n");
++ }
++ ipath_cdbg(LINKVERB, "POLL change to %s (%x)\n",
++ ipath_ibcstatus_str[ltstate], ibstate);
+ goto skip_ibchange;
+ }
+ }
+- dd->ipath_ibpollcnt = 0; /* some state other than 2 or 3 */
++
++ dd->ipath_ibpollcnt = 0; /* not poll*, now */
+ ipath_stats.sps_iblink++;
+- if (ltstate != INFINIPATH_IBCS_LT_STATE_LINKUP) {
++
++ if (ibstate != init && dd->ipath_lastlinkrecov && ipath_linkrecovery) {
++ u64 linkrecov;
++ linkrecov = ipath_snap_cntr(dd,
++ dd->ipath_cregs->cr_iblinkerrrecovcnt);
++ if (linkrecov != dd->ipath_lastlinkrecov) {
++ ipath_dbg("IB linkrecov up %Lx (%s %s) recov %Lu\n",
++ ibcs, ib_linkstate(dd, ibcs),
++ ipath_ibcstatus_str[ltstate],
++ linkrecov);
++ /* and no more until active again */
++ dd->ipath_lastlinkrecov = 0;
++ ipath_set_linkstate(dd, IPATH_IB_LINKDOWN);
++ goto skip_ibchange;
++ }
++ }
++
++ if (ibstate == init || ibstate == arm || ibstate == active) {
++ *dd->ipath_statusp &= ~IPATH_STATUS_IB_NOCABLE;
++ if (ibstate == init || ibstate == arm) {
++ *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
++ if (dd->ipath_flags & IPATH_LINKACTIVE)
++ signal_ib_event(dd, IB_EVENT_PORT_ERR);
++ }
++ if (ibstate == arm) {
++ dd->ipath_flags |= IPATH_LINKARMED;
++ dd->ipath_flags &= ~(IPATH_LINKUNK |
++ IPATH_LINKINIT | IPATH_LINKDOWN |
++ IPATH_LINKACTIVE | IPATH_NOCABLE);
++ ipath_hol_down(dd);
++ } else if (ibstate == init) {
++ /*
++ * set INIT and DOWN. Down is checked by
++ * most of the other code, but INIT is
++ * useful to know in a few places.
++ */
++ dd->ipath_flags |= IPATH_LINKINIT |
++ IPATH_LINKDOWN;
++ dd->ipath_flags &= ~(IPATH_LINKUNK |
++ IPATH_LINKARMED | IPATH_LINKACTIVE |
++ IPATH_NOCABLE);
++ ipath_hol_down(dd);
++ } else { /* active */
++ dd->ipath_lastlinkrecov = ipath_snap_cntr(dd,
++ dd->ipath_cregs->cr_iblinkerrrecovcnt);
++ *dd->ipath_statusp |=
++ IPATH_STATUS_IB_READY | IPATH_STATUS_IB_CONF;
++ dd->ipath_flags |= IPATH_LINKACTIVE;
++ dd->ipath_flags &= ~(IPATH_LINKUNK | IPATH_LINKINIT
++ | IPATH_LINKDOWN | IPATH_LINKARMED |
++ IPATH_NOCABLE);
++ if (dd->ipath_flags & IPATH_HAS_SEND_DMA)
++ ipath_restart_sdma(dd);
++ signal_ib_event(dd, IB_EVENT_PORT_ACTIVE);
++ /* LED active not handled in chip _f_updown */
++ dd->ipath_f_setextled(dd, lstate, ltstate);
++ ipath_hol_up(dd);
++ }
++
++ /*
++ * print after we've already done the work, so as not to
++ * delay the state changes and notifications, for debugging
++ */
++ if (lstate == lastlstate)
++ ipath_cdbg(LINKVERB, "Unchanged from last: %s "
++ "(%x)\n", ib_linkstate(dd, ibcs), ibstate);
++ else
++ ipath_cdbg(VERBOSE, "Unit %u: link up to %s %s (%x)\n",
++ dd->ipath_unit, ib_linkstate(dd, ibcs),
++ ipath_ibcstatus_str[ltstate], ibstate);
++ } else { /* down */
+ if (dd->ipath_flags & IPATH_LINKACTIVE)
+ signal_ib_event(dd, IB_EVENT_PORT_ERR);
+ dd->ipath_flags |= IPATH_LINKDOWN;
+@@ -391,69 +461,28 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
+ IPATH_LINKARMED);
+ *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
+ dd->ipath_lli_counter = 0;
+- if (!noprint) {
+- if (((dd->ipath_lastibcstat >>
+- INFINIPATH_IBCS_LINKSTATE_SHIFT) &
+- INFINIPATH_IBCS_LINKSTATE_MASK)
+- == INFINIPATH_IBCS_L_STATE_ACTIVE)
+- /* if from up to down be more vocal */
+- ipath_cdbg(VERBOSE,
+- "Unit %u link now down (%s)\n",
+- dd->ipath_unit,
+- ipath_ibcstatus_str[ltstate]);
+- else
+- ipath_cdbg(VERBOSE, "Unit %u link is "
+- "down (%s)\n", dd->ipath_unit,
+- ipath_ibcstatus_str[ltstate]);
+- }
+
+- dd->ipath_f_setextled(dd, lstate, ltstate);
+- } else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_ACTIVE) {
+- dd->ipath_flags |= IPATH_LINKACTIVE;
+- dd->ipath_flags &=
+- ~(IPATH_LINKUNK | IPATH_LINKINIT | IPATH_LINKDOWN |
+- IPATH_LINKARMED | IPATH_NOCABLE);
+- *dd->ipath_statusp &= ~IPATH_STATUS_IB_NOCABLE;
+- *dd->ipath_statusp |=
+- IPATH_STATUS_IB_READY | IPATH_STATUS_IB_CONF;
+- dd->ipath_f_setextled(dd, lstate, ltstate);
+- signal_ib_event(dd, IB_EVENT_PORT_ACTIVE);
+- } else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_INIT) {
+- if (dd->ipath_flags & IPATH_LINKACTIVE)
+- signal_ib_event(dd, IB_EVENT_PORT_ERR);
+- /*
+- * set INIT and DOWN. Down is checked by most of the other
+- * code, but INIT is useful to know in a few places.
+- */
+- dd->ipath_flags |= IPATH_LINKINIT | IPATH_LINKDOWN;
+- dd->ipath_flags &=
+- ~(IPATH_LINKUNK | IPATH_LINKACTIVE | IPATH_LINKARMED
+- | IPATH_NOCABLE);
+- *dd->ipath_statusp &= ~(IPATH_STATUS_IB_NOCABLE
+- | IPATH_STATUS_IB_READY);
+- dd->ipath_f_setextled(dd, lstate, ltstate);
+- } else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_ARM) {
+- if (dd->ipath_flags & IPATH_LINKACTIVE)
+- signal_ib_event(dd, IB_EVENT_PORT_ERR);
+- dd->ipath_flags |= IPATH_LINKARMED;
+- dd->ipath_flags &=
+- ~(IPATH_LINKUNK | IPATH_LINKDOWN | IPATH_LINKINIT |
+- IPATH_LINKACTIVE | IPATH_NOCABLE);
+- *dd->ipath_statusp &= ~(IPATH_STATUS_IB_NOCABLE
+- | IPATH_STATUS_IB_READY);
+- dd->ipath_f_setextled(dd, lstate, ltstate);
+- } else {
+- if (!noprint)
+- ipath_dbg("IBstatuschange unit %u: %s (%x)\n",
+- dd->ipath_unit,
+- ipath_ibcstatus_str[ltstate], ltstate);
++ if (lastlstate != INFINIPATH_IBCS_L_STATE_DOWN)
++ ipath_cdbg(VERBOSE, "Unit %u link state down "
++ "(state 0x%x), from %s\n",
++ dd->ipath_unit, lstate,
++ ib_linkstate(dd, dd->ipath_lastibcstat));
++ else
++ ipath_cdbg(LINKVERB, "Unit %u link state changed "
++ "to %s (0x%x) from down (%x)\n",
++ dd->ipath_unit,
++ ipath_ibcstatus_str[ltstate],
++ ibstate, lastlstate);
+ }
++
+ skip_ibchange:
+- dd->ipath_lastibcstat = val;
++ dd->ipath_lastibcstat = ibcs;
++done:
++ return;
+ }
+
+ static void handle_supp_msgs(struct ipath_devdata *dd,
+- unsigned supp_msgs, char *msg, int msgsz)
++ unsigned supp_msgs, char *msg, u32 msgsz)
+ {
+ /*
+ * Print the message unless it's ibc status change only, which
+@@ -461,12 +490,19 @@ static void handle_supp_msgs(struct ipath_devdata *dd,
+ */
+ if (dd->ipath_lasterror & ~INFINIPATH_E_IBSTATUSCHANGED) {
+ int iserr;
+- iserr = ipath_decode_err(msg, msgsz,
++ ipath_err_t mask;
++ iserr = ipath_decode_err(dd, msg, msgsz,
+ dd->ipath_lasterror &
+ ~INFINIPATH_E_IBSTATUSCHANGED);
+- if (dd->ipath_lasterror &
+- ~(INFINIPATH_E_RRCVEGRFULL |
+- INFINIPATH_E_RRCVHDRFULL | INFINIPATH_E_PKTERRS))
++
++ mask = INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL |
++ INFINIPATH_E_PKTERRS | INFINIPATH_E_SDMADISABLED;
++
++ /* if we're in debug, then don't mask SDMADISABLED msgs */
++ if (ipath_debug & __IPATH_DBG)
++ mask &= ~INFINIPATH_E_SDMADISABLED;
++
++ if (dd->ipath_lasterror & ~mask)
+ ipath_dev_err(dd, "Suppressed %u messages for "
+ "fast-repeating errors (%s) (%llx)\n",
+ supp_msgs, msg,
+@@ -493,7 +529,7 @@ static void handle_supp_msgs(struct ipath_devdata *dd,
+
+ static unsigned handle_frequent_errors(struct ipath_devdata *dd,
+ ipath_err_t errs, char *msg,
+- int msgsz, int *noprint)
++ u32 msgsz, int *noprint)
+ {
+ unsigned long nc;
+ static unsigned long nextmsg_time;
+@@ -523,19 +559,125 @@ static unsigned handle_frequent_errors(struct ipath_devdata *dd,
+ return supp_msgs;
+ }
+
++static void handle_sdma_errors(struct ipath_devdata *dd, ipath_err_t errs)
++{
++ unsigned long flags;
++ int expected;
++
++ if (ipath_debug & __IPATH_DBG) {
++ char msg[128];
++ ipath_decode_err(dd, msg, sizeof msg, errs &
++ INFINIPATH_E_SDMAERRS);
++ ipath_dbg("errors %lx (%s)\n", (unsigned long)errs, msg);
++ }
++ if (ipath_debug & __IPATH_VERBDBG) {
++ unsigned long tl, hd, status, lengen;
++ tl = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmatail);
++ hd = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmahead);
++ status = ipath_read_kreg64(dd
++ , dd->ipath_kregs->kr_senddmastatus);
++ lengen = ipath_read_kreg64(dd,
++ dd->ipath_kregs->kr_senddmalengen);
++ ipath_cdbg(VERBOSE, "sdma tl 0x%lx hd 0x%lx status 0x%lx "
++ "lengen 0x%lx\n", tl, hd, status, lengen);
++ }
++
++ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++ __set_bit(IPATH_SDMA_DISABLED, &dd->ipath_sdma_status);
++ expected = test_bit(IPATH_SDMA_ABORTING, &dd->ipath_sdma_status);
++ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++ if (!expected)
++ ipath_cancel_sends(dd, 1);
++}
++
++static void handle_sdma_intr(struct ipath_devdata *dd, u64 istat)
++{
++ unsigned long flags;
++ int expected;
++
++ if ((istat & INFINIPATH_I_SDMAINT) &&
++ !test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status))
++ ipath_sdma_intr(dd);
++
++ if (istat & INFINIPATH_I_SDMADISABLED) {
++ expected = test_bit(IPATH_SDMA_ABORTING,
++ &dd->ipath_sdma_status);
++ ipath_dbg("%s SDmaDisabled intr\n",
++ expected ? "expected" : "unexpected");
++ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++ __set_bit(IPATH_SDMA_DISABLED, &dd->ipath_sdma_status);
++ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++ if (!expected)
++ ipath_cancel_sends(dd, 1);
++ if (!test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status))
++ tasklet_hi_schedule(&dd->ipath_sdma_abort_task);
++ }
++}
++
++static int handle_hdrq_full(struct ipath_devdata *dd)
++{
++ int chkerrpkts = 0;
++ u32 hd, tl;
++ u32 i;
++
++ ipath_stats.sps_hdrqfull++;
++ for (i = 0; i < dd->ipath_cfgports; i++) {
++ struct ipath_portdata *pd = dd->ipath_pd[i];
++
++ if (i == 0) {
++ /*
++ * For kernel receive queues, we just want to know
++ * if there are packets in the queue that we can
++ * process.
++ */
++ if (pd->port_head != ipath_get_hdrqtail(pd))
++ chkerrpkts |= 1 << i;
++ continue;
++ }
++
++ /* Skip if user context is not open */
++ if (!pd || !pd->port_cnt)
++ continue;
++
++ /* Don't report the same point multiple times. */
++ if (dd->ipath_flags & IPATH_NODMA_RTAIL)
++ tl = ipath_read_ureg32(dd, ur_rcvhdrtail, i);
++ else
++ tl = ipath_get_rcvhdrtail(pd);
++ if (tl == pd->port_lastrcvhdrqtail)
++ continue;
++
++ hd = ipath_read_ureg32(dd, ur_rcvhdrhead, i);
++ if (hd == (tl + 1) || (!hd && tl == dd->ipath_hdrqlast)) {
++ pd->port_lastrcvhdrqtail = tl;
++ pd->port_hdrqfull++;
++ /* flush hdrqfull so that poll() sees it */
++ wmb();
++ wake_up_interruptible(&pd->port_wait);
++ }
++ }
++
++ return chkerrpkts;
++}
++
+ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ {
+ char msg[128];
+ u64 ignore_this_time = 0;
+- int i, iserr = 0;
++ u64 iserr = 0;
+ int chkerrpkts = 0, noprint = 0;
+ unsigned supp_msgs;
+ int log_idx;
+
+- supp_msgs = handle_frequent_errors(dd, errs, msg, sizeof msg, &noprint);
++ /*
++ * don't report errors that are masked, either at init
++ * (not set in ipath_errormask), or temporarily (set in
++ * ipath_maskederrs)
++ */
++ errs &= dd->ipath_errormask & ~dd->ipath_maskederrs;
+
+- /* don't report errors that are masked */
+- errs &= ~dd->ipath_maskederrs;
++ supp_msgs = handle_frequent_errors(dd, errs, msg, (u32)sizeof msg,
++ &noprint);
+
+ /* do these first, they are most important */
+ if (errs & INFINIPATH_E_HARDWARE) {
+@@ -550,6 +692,9 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ }
+ }
+
++ if (errs & INFINIPATH_E_SDMAERRS)
++ handle_sdma_errors(dd, errs);
++
+ if (!noprint && (errs & ~dd->ipath_e_bitsextant))
+ ipath_dev_err(dd, "error interrupt with unknown errors "
+ "%llx set\n", (unsigned long long)
+@@ -580,18 +725,19 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ * ones on this particular interrupt, which also isn't great
+ */
+ dd->ipath_maskederrs |= dd->ipath_lasterror | errs;
++
+ dd->ipath_errormask &= ~dd->ipath_maskederrs;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
+- dd->ipath_errormask);
+- s_iserr = ipath_decode_err(msg, sizeof msg,
+- dd->ipath_maskederrs);
++ dd->ipath_errormask);
++ s_iserr = ipath_decode_err(dd, msg, sizeof msg,
++ dd->ipath_maskederrs);
+
+ if (dd->ipath_maskederrs &
+- ~(INFINIPATH_E_RRCVEGRFULL |
+- INFINIPATH_E_RRCVHDRFULL | INFINIPATH_E_PKTERRS))
++ ~(INFINIPATH_E_RRCVEGRFULL |
++ INFINIPATH_E_RRCVHDRFULL | INFINIPATH_E_PKTERRS))
+ ipath_dev_err(dd, "Temporarily disabling "
+ "error(s) %llx reporting; too frequent (%s)\n",
+- (unsigned long long)dd->ipath_maskederrs,
++ (unsigned long long) dd->ipath_maskederrs,
+ msg);
+ else {
+ /*
+@@ -633,26 +779,43 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ INFINIPATH_E_IBSTATUSCHANGED);
+ }
+
+- /* likely due to cancel, so suppress */
++ if (errs & INFINIPATH_E_SENDSPECIALTRIGGER) {
++ dd->ipath_spectriggerhit++;
++ ipath_dbg("%lu special trigger hits\n",
++ dd->ipath_spectriggerhit);
++ }
++
++ /* likely due to cancel; so suppress message unless verbose */
+ if ((errs & (INFINIPATH_E_SPKTLEN | INFINIPATH_E_SPIOARMLAUNCH)) &&
+ dd->ipath_lastcancel > jiffies) {
+- ipath_dbg("Suppressed armlaunch/spktlen after error send cancel\n");
++ /* armlaunch takes precedence; it often causes both. */
++ ipath_cdbg(VERBOSE,
++ "Suppressed %s error (%llx) after sendbuf cancel\n",
++ (errs & INFINIPATH_E_SPIOARMLAUNCH) ?
++ "armlaunch" : "sendpktlen", (unsigned long long)errs);
+ errs &= ~(INFINIPATH_E_SPIOARMLAUNCH | INFINIPATH_E_SPKTLEN);
+ }
+
+ if (!errs)
+ return 0;
+
+- if (!noprint)
++ if (!noprint) {
++ ipath_err_t mask;
+ /*
+- * the ones we mask off are handled specially below or above
++ * The ones we mask off are handled specially below
++ * or above. Also mask SDMADISABLED by default as it
++ * is too chatty.
+ */
+- ipath_decode_err(msg, sizeof msg,
+- errs & ~(INFINIPATH_E_IBSTATUSCHANGED |
+- INFINIPATH_E_RRCVEGRFULL |
+- INFINIPATH_E_RRCVHDRFULL |
+- INFINIPATH_E_HARDWARE));
+- else
++ mask = INFINIPATH_E_IBSTATUSCHANGED |
++ INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL |
++ INFINIPATH_E_HARDWARE | INFINIPATH_E_SDMADISABLED;
++
++ /* if we're in debug, then don't mask SDMADISABLED msgs */
++ if (ipath_debug & __IPATH_DBG)
++ mask &= ~INFINIPATH_E_SDMADISABLED;
++
++ ipath_decode_err(dd, msg, sizeof msg, errs & ~mask);
++ } else
+ /* so we don't need if (!noprint) at strlcat's below */
+ *msg = 0;
+
+@@ -677,40 +840,8 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ * fast_stats, no more than every 5 seconds, user ports get printed
+ * on close
+ */
+- if (errs & INFINIPATH_E_RRCVHDRFULL) {
+- u32 hd, tl;
+- ipath_stats.sps_hdrqfull++;
+- for (i = 0; i < dd->ipath_cfgports; i++) {
+- struct ipath_portdata *pd = dd->ipath_pd[i];
+- if (i == 0) {
+- hd = pd->port_head;
+- tl = (u32) le64_to_cpu(
+- *dd->ipath_hdrqtailptr);
+- } else if (pd && pd->port_cnt &&
+- pd->port_rcvhdrtail_kvaddr) {
+- /*
+- * don't report same point multiple times,
+- * except kernel
+- */
+- tl = *(u64 *) pd->port_rcvhdrtail_kvaddr;
+- if (tl == pd->port_lastrcvhdrqtail)
+- continue;
+- hd = ipath_read_ureg32(dd, ur_rcvhdrhead,
+- i);
+- } else
+- continue;
+- if (hd == (tl + 1) ||
+- (!hd && tl == dd->ipath_hdrqlast)) {
+- if (i == 0)
+- chkerrpkts = 1;
+- pd->port_lastrcvhdrqtail = tl;
+- pd->port_hdrqfull++;
+- /* flush hdrqfull so that poll() sees it */
+- wmb();
+- wake_up_interruptible(&pd->port_wait);
+- }
+- }
+- }
++ if (errs & INFINIPATH_E_RRCVHDRFULL)
++ chkerrpkts |= handle_hdrq_full(dd);
+ if (errs & INFINIPATH_E_RRCVEGRFULL) {
+ struct ipath_portdata *pd = dd->ipath_pd[0];
+
+@@ -721,9 +852,8 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ * vs user)
+ */
+ ipath_stats.sps_etidfull++;
+- if (pd->port_head !=
+- (u32) le64_to_cpu(*dd->ipath_hdrqtailptr))
+- chkerrpkts = 1;
++ if (pd->port_head != ipath_get_hdrqtail(pd))
++ chkerrpkts |= 1;
+ }
+
+ /*
+@@ -741,16 +871,13 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ dd->ipath_flags &= ~(IPATH_LINKUNK | IPATH_LINKINIT
+ | IPATH_LINKARMED | IPATH_LINKACTIVE);
+ *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
+- if (!noprint) {
+- u64 st = ipath_read_kreg64(
+- dd, dd->ipath_kregs->kr_ibcstatus);
+
+- ipath_dbg("Lost link, link now down (%s)\n",
+- ipath_ibcstatus_str[st & 0xf]);
+- }
++ ipath_dbg("Lost link, link now down (%s)\n",
++ ipath_ibcstatus_str[ipath_read_kreg64(dd,
++ dd->ipath_kregs->kr_ibcstatus) & 0xf]);
+ }
+ if (errs & INFINIPATH_E_IBSTATUSCHANGED)
+- handle_e_ibstatuschanged(dd, errs, noprint);
++ handle_e_ibstatuschanged(dd, errs);
+
+ if (errs & INFINIPATH_E_RESET) {
+ if (!noprint)
+@@ -765,9 +892,6 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ if (!noprint && *msg) {
+ if (iserr)
+ ipath_dev_err(dd, "%s error\n", msg);
+- else
+- dev_info(&dd->pcidev->dev, "%s packet problems\n",
+- msg);
+ }
+ if (dd->ipath_state_wanted & dd->ipath_flags) {
+ ipath_cdbg(VERBOSE, "driver wanted state %x, iflags now %x, "
+@@ -779,7 +903,6 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ return chkerrpkts;
+ }
+
+-
+ /*
+ * try to cleanup as much as possible for anything that might have gone
+ * wrong while in freeze mode, such as pio buffers being written by user
+@@ -796,8 +919,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ void ipath_clear_freeze(struct ipath_devdata *dd)
+ {
+ int i, im;
+- __le64 val;
+- unsigned long flags;
++ u64 val;
+
+ /* disable error interrupts, to avoid confusion */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, 0ULL);
+@@ -816,14 +938,7 @@ void ipath_clear_freeze(struct ipath_devdata *dd)
+ dd->ipath_control);
+
+ /* ensure pio avail updates continue */
+- spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
+- ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+- dd->ipath_sendctrl & ~INFINIPATH_S_PIOBUFAVAILUPD);
+- ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+- ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+- dd->ipath_sendctrl);
+- ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+- spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++ ipath_force_pio_avail_update(dd);
+
+ /*
+ * We just enabled pioavailupdate, so dma copy is almost certainly
+@@ -831,10 +946,13 @@ void ipath_clear_freeze(struct ipath_devdata *dd)
+ */
+ for (i = 0; i < dd->ipath_pioavregs; i++) {
+ /* deal with 6110 chip bug */
+- im = i > 3 ? i ^ 1 : i;
++ im = (i > 3 && (dd->ipath_flags & IPATH_SWAP_PIOBUFS)) ?
++ i ^ 1 : i;
+ val = ipath_read_kreg64(dd, (0x1000 / sizeof(u64)) + im);
+- dd->ipath_pioavailregs_dma[i] = dd->ipath_pioavailshadow[i]
+- = le64_to_cpu(val);
++ dd->ipath_pioavailregs_dma[i] = cpu_to_le64(val);
++ dd->ipath_pioavailshadow[i] = val |
++ (~dd->ipath_pioavailkernel[i] <<
++ INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT);
+ }
+
+ /*
+@@ -950,7 +1068,7 @@ set:
+ * process was waiting for a packet to arrive, and didn't want
+ * to poll
+ */
+-static void handle_urcv(struct ipath_devdata *dd, u32 istat)
++static void handle_urcv(struct ipath_devdata *dd, u64 istat)
+ {
+ u64 portr;
+ int i;
+@@ -966,12 +1084,13 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat)
+ * and ipath_poll_next()...
+ */
+ rmb();
+- portr = ((istat >> INFINIPATH_I_RCVAVAIL_SHIFT) &
+- dd->ipath_i_rcvavail_mask)
+- | ((istat >> INFINIPATH_I_RCVURG_SHIFT) &
+- dd->ipath_i_rcvurg_mask);
++ portr = ((istat >> dd->ipath_i_rcvavail_shift) &
++ dd->ipath_i_rcvavail_mask) |
++ ((istat >> dd->ipath_i_rcvurg_shift) &
++ dd->ipath_i_rcvurg_mask);
+ for (i = 1; i < dd->ipath_cfgports; i++) {
+ struct ipath_portdata *pd = dd->ipath_pd[i];
++
+ if (portr & (1 << i) && pd && pd->port_cnt) {
+ if (test_and_clear_bit(IPATH_PORT_WAITING_RCV,
+ &pd->port_flag)) {
+@@ -988,7 +1107,7 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat)
+ }
+ if (rcvdint) {
+ /* only want to take one interrupt, so turn off the rcv
+- * interrupt for all the ports that we did the wakeup on
++ * interrupt for all the ports that we set the rcv_waiting
+ * (but never for kernel port)
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+@@ -999,12 +1118,11 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat)
+ irqreturn_t ipath_intr(int irq, void *data)
+ {
+ struct ipath_devdata *dd = data;
+- u32 istat, chk0rcv = 0;
++ u64 istat, chk0rcv = 0;
+ ipath_err_t estat = 0;
+ irqreturn_t ret;
+ static unsigned unexpected = 0;
+- static const u32 port0rbits = (1U<<INFINIPATH_I_RCVAVAIL_SHIFT) |
+- (1U<<INFINIPATH_I_RCVURG_SHIFT);
++ u64 kportrbits;
+
+ ipath_stats.sps_ints++;
+
+@@ -1053,17 +1171,17 @@ irqreturn_t ipath_intr(int irq, void *data)
+
+ if (unlikely(istat & ~dd->ipath_i_bitsextant))
+ ipath_dev_err(dd,
+- "interrupt with unknown interrupts %x set\n",
+- istat & (u32) ~ dd->ipath_i_bitsextant);
+- else
+- ipath_cdbg(VERBOSE, "intr stat=0x%x\n", istat);
++ "interrupt with unknown interrupts %Lx set\n",
++ istat & ~dd->ipath_i_bitsextant);
++ else if (istat & ~INFINIPATH_I_ERROR) /* errors do own printing */
++ ipath_cdbg(VERBOSE, "intr stat=0x%Lx\n", istat);
+
+- if (unlikely(istat & INFINIPATH_I_ERROR)) {
++ if (istat & INFINIPATH_I_ERROR) {
+ ipath_stats.sps_errints++;
+ estat = ipath_read_kreg64(dd,
+ dd->ipath_kregs->kr_errorstatus);
+ if (!estat)
+- dev_info(&dd->pcidev->dev, "error interrupt (%x), "
++ dev_info(&dd->pcidev->dev, "error interrupt (%Lx), "
+ "but no error bits set!\n", istat);
+ else if (estat == -1LL)
+ /*
+@@ -1073,9 +1191,7 @@ irqreturn_t ipath_intr(int irq, void *data)
+ ipath_dev_err(dd, "Read of error status failed "
+ "(all bits set); ignoring\n");
+ else
+- if (handle_errors(dd, estat))
+- /* force calling ipath_kreceive() */
+- chk0rcv = 1;
++ chk0rcv |= handle_errors(dd, estat);
+ }
+
+ if (istat & INFINIPATH_I_GPIO) {
+@@ -1093,8 +1209,7 @@ irqreturn_t ipath_intr(int irq, void *data)
+
+ gpiostatus = ipath_read_kreg32(
+ dd, dd->ipath_kregs->kr_gpio_status);
+- /* First the error-counter case.
+- */
++ /* First the error-counter case. */
+ if ((gpiostatus & IPATH_GPIO_ERRINTR_MASK) &&
+ (dd->ipath_flags & IPATH_GPIO_ERRINTRS)) {
+ /* want to clear the bits we see asserted. */
+@@ -1156,7 +1271,6 @@ irqreturn_t ipath_intr(int irq, void *data)
+ (u64) to_clear);
+ }
+ }
+- chk0rcv |= istat & port0rbits;
+
+ /*
+ * Clear the interrupt bits we found set, unless they are receive
+@@ -1169,22 +1283,25 @@ irqreturn_t ipath_intr(int irq, void *data)
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, istat);
+
+ /*
+- * handle port0 receive before checking for pio buffers available,
+- * since receives can overflow; piobuf waiters can afford a few
+- * extra cycles, since they were waiting anyway, and user's waiting
+- * for receive are at the bottom.
++ * Handle kernel receive queues before checking for pio buffers
++ * available since receives can overflow; piobuf waiters can afford
++ * a few extra cycles, since they were waiting anyway, and user's
++ * waiting for receive are at the bottom.
+ */
+- if (chk0rcv) {
++ kportrbits = (1ULL << dd->ipath_i_rcvavail_shift) |
++ (1ULL << dd->ipath_i_rcvurg_shift);
++ if (chk0rcv || (istat & kportrbits)) {
++ istat &= ~kportrbits;
+ ipath_kreceive(dd->ipath_pd[0]);
+- istat &= ~port0rbits;
+ }
+
+- if (istat & ((dd->ipath_i_rcvavail_mask <<
+- INFINIPATH_I_RCVAVAIL_SHIFT)
+- | (dd->ipath_i_rcvurg_mask <<
+- INFINIPATH_I_RCVURG_SHIFT)))
++ if (istat & ((dd->ipath_i_rcvavail_mask << dd->ipath_i_rcvavail_shift) |
++ (dd->ipath_i_rcvurg_mask << dd->ipath_i_rcvurg_shift)))
+ handle_urcv(dd, istat);
+
++ if (istat & (INFINIPATH_I_SDMAINT | INFINIPATH_I_SDMADISABLED))
++ handle_sdma_intr(dd, istat);
++
+ if (istat & INFINIPATH_I_SPIOBUFAVAIL) {
+ unsigned long flags;
+
+@@ -1195,7 +1312,10 @@ irqreturn_t ipath_intr(int irq, void *data)
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
+
+- handle_layer_pioavail(dd);
++ if (!(dd->ipath_flags & IPATH_HAS_SEND_DMA))
++ handle_layer_pioavail(dd);
++ else
++ ipath_dbg("unexpected BUFAVAIL intr\n");
+ }
+
+ ret = IRQ_HANDLED;
+diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
+index ecf3f7f..202337a 100644
+--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
++++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
+@@ -1,7 +1,7 @@
+ #ifndef _IPATH_KERNEL_H
+ #define _IPATH_KERNEL_H
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+@@ -42,6 +42,8 @@
+ #include <linux/pci.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/mutex.h>
++#include <linux/list.h>
++#include <linux/scatterlist.h>
+ #include <asm/io.h>
+ #include <rdma/ib_verbs.h>
+
+@@ -175,9 +177,13 @@ struct ipath_portdata {
+ u16 poll_type;
+ /* port rcvhdrq head offset */
+ u32 port_head;
++ /* receive packet sequence counter */
++ u32 port_seq_cnt;
+ };
+
+ struct sk_buff;
++struct ipath_sge_state;
++struct ipath_verbs_txreq;
+
+ /*
+ * control information for layered drivers
+@@ -191,6 +197,40 @@ struct ipath_skbinfo {
+ dma_addr_t phys;
+ };
+
++struct ipath_sdma_txreq {
++ int flags;
++ int sg_count;
++ union {
++ struct scatterlist *sg;
++ void *map_addr;
++ };
++ void (*callback)(void *, int);
++ void *callback_cookie;
++ int callback_status;
++ u16 start_idx; /* sdma private */
++ u16 next_descq_idx; /* sdma private */
++ struct list_head list; /* sdma private */
++};
++
++struct ipath_sdma_desc {
++ __le64 qw[2];
++};
++
++#define IPATH_SDMA_TXREQ_F_USELARGEBUF 0x1
++#define IPATH_SDMA_TXREQ_F_HEADTOHOST 0x2
++#define IPATH_SDMA_TXREQ_F_INTREQ 0x4
++#define IPATH_SDMA_TXREQ_F_FREEBUF 0x8
++#define IPATH_SDMA_TXREQ_F_FREEDESC 0x10
++#define IPATH_SDMA_TXREQ_F_VL15 0x20
++
++#define IPATH_SDMA_TXREQ_S_OK 0
++#define IPATH_SDMA_TXREQ_S_SENDERROR 1
++#define IPATH_SDMA_TXREQ_S_ABORTED 2
++#define IPATH_SDMA_TXREQ_S_SHUTDOWN 3
++
++/* max dwords in small buffer packet */
++#define IPATH_SMALLBUF_DWORDS (dd->ipath_piosize2k >> 2)
++
+ /*
+ * Possible IB config parameters for ipath_f_get/set_ib_cfg()
+ */
+@@ -221,11 +261,6 @@ struct ipath_devdata {
+ unsigned long ipath_physaddr;
+ /* base of memory alloced for ipath_kregbase, for free */
+ u64 *ipath_kregalloc;
+- /*
+- * virtual address where port0 rcvhdrqtail updated for this unit.
+- * only written to by the chip, not the driver.
+- */
+- volatile __le64 *ipath_hdrqtailptr;
+ /* ipath_cfgports pointers */
+ struct ipath_portdata **ipath_pd;
+ /* sk_buffs used by port 0 eager receive queue */
+@@ -283,6 +318,7 @@ struct ipath_devdata {
+ /* per chip actions needed for IB Link up/down changes */
+ int (*ipath_f_ib_updown)(struct ipath_devdata *, int, u64);
+
++ unsigned ipath_lastegr_idx;
+ struct ipath_ibdev *verbs_dev;
+ struct timer_list verbs_timer;
+ /* total dwords sent (summed from counter) */
+@@ -309,6 +345,7 @@ struct ipath_devdata {
+ ipath_err_t ipath_lasthwerror;
+ /* errors masked because they occur too fast */
+ ipath_err_t ipath_maskederrs;
++ u64 ipath_lastlinkrecov; /* link recoveries at last ACTIVE */
+ /* time in jiffies at which to re-enable maskederrs */
+ unsigned long ipath_unmasktime;
+ /* count of egrfull errors, combined for all ports */
+@@ -347,6 +384,7 @@ struct ipath_devdata {
+ u32 ipath_lastrpkts;
+ /* pio bufs allocated per port */
+ u32 ipath_pbufsport;
++ u32 ipath_pioupd_thresh; /* update threshold, some chips */
+ /*
+ * number of ports configured as max; zero is set to number chip
+ * supports, less gives more pio bufs/port, etc.
+@@ -365,6 +403,7 @@ struct ipath_devdata {
+ * get to multiple devices
+ */
+ u32 ipath_lastpioindex;
++ u32 ipath_lastpioindexl;
+ /* max length of freezemsg */
+ u32 ipath_freezelen;
+ /*
+@@ -381,6 +420,15 @@ struct ipath_devdata {
+ u32 ipath_pcibar0;
+ /* so we can rewrite it after a chip reset */
+ u32 ipath_pcibar1;
++ u32 ipath_x1_fix_tries;
++ u32 ipath_autoneg_tries;
++ u32 serdes_first_init_done;
++
++ struct ipath_relock {
++ atomic_t ipath_relock_timer_active;
++ struct timer_list ipath_relock_timer;
++ unsigned int ipath_relock_interval; /* in jiffies */
++ } ipath_relock_singleton;
+
+ /* interrupt number */
+ int ipath_irq;
+@@ -403,7 +451,7 @@ struct ipath_devdata {
+ u64 __iomem *ipath_egrtidbase;
+ /* lock to workaround chip bug 9437 and others */
+ spinlock_t ipath_kernel_tid_lock;
+- spinlock_t ipath_tid_lock;
++ spinlock_t ipath_user_tid_lock;
+ spinlock_t ipath_sendctrl_lock;
+
+ /*
+@@ -418,15 +466,52 @@ struct ipath_devdata {
+ struct pci_dev *pcidev;
+ struct cdev *user_cdev;
+ struct cdev *diag_cdev;
+- struct class_device *user_class_dev;
+- struct class_device *diag_class_dev;
++ struct device *user_dev;
++ struct device *diag_dev;
+ /* timer used to prevent stats overflow, error throttling, etc. */
+ struct timer_list ipath_stats_timer;
++ /* timer to verify interrupts work, and fallback if possible */
++ struct timer_list ipath_intrchk_timer;
+ void *ipath_dummy_hdrq; /* used after port close */
+ dma_addr_t ipath_dummy_hdrq_phys;
+
++ /* SendDMA related entries */
++ spinlock_t ipath_sdma_lock;
++ u64 ipath_sdma_status;
++ unsigned long ipath_sdma_abort_jiffies;
++ unsigned long ipath_sdma_abort_intr_timeout;
++ unsigned long ipath_sdma_buf_jiffies;
++ struct ipath_sdma_desc *ipath_sdma_descq;
++ u64 ipath_sdma_descq_added;
++ u64 ipath_sdma_descq_removed;
++ int ipath_sdma_desc_nreserved;
++ u16 ipath_sdma_descq_cnt;
++ u16 ipath_sdma_descq_tail;
++ u16 ipath_sdma_descq_head;
++ u16 ipath_sdma_next_intr;
++ u16 ipath_sdma_reset_wait;
++ u8 ipath_sdma_generation;
++ struct tasklet_struct ipath_sdma_abort_task;
++ struct tasklet_struct ipath_sdma_notify_task;
++ struct list_head ipath_sdma_activelist;
++ struct list_head ipath_sdma_notifylist;
++ atomic_t ipath_sdma_vl15_count;
++ struct timer_list ipath_sdma_vl15_timer;
++
++ dma_addr_t ipath_sdma_descq_phys;
++ volatile __le64 *ipath_sdma_head_dma;
++ dma_addr_t ipath_sdma_head_phys;
++
+ unsigned long ipath_ureg_align; /* user register alignment */
+
++ struct delayed_work ipath_autoneg_work;
++ wait_queue_head_t ipath_autoneg_wait;
++
++ /* HoL blocking / user app forward-progress state */
++ unsigned ipath_hol_state;
++ unsigned ipath_hol_next;
++ struct timer_list ipath_hol_timer;
++
+ /*
+ * Shadow copies of registers; size indicates read access size.
+ * Most of them are readonly, but some are write-only register,
+@@ -447,6 +532,8 @@ struct ipath_devdata {
+ * init time.
+ */
+ unsigned long ipath_pioavailshadow[8];
++ /* bitmap of send buffers available for the kernel to use with PIO. */
++ unsigned long ipath_pioavailkernel[8];
+ /* shadow of kr_gpio_out, for rmw ops */
+ u64 ipath_gpio_out;
+ /* shadow the gpio mask register */
+@@ -472,6 +559,8 @@ struct ipath_devdata {
+ u64 ipath_intconfig;
+ /* kr_sendpiobufbase value */
+ u64 ipath_piobufbase;
++ /* kr_ibcddrctrl shadow */
++ u64 ipath_ibcddrctrl;
+
+ /* these are the "32 bit" regs */
+
+@@ -488,7 +577,10 @@ struct ipath_devdata {
+ unsigned long ipath_rcvctrl;
+ /* shadow kr_sendctrl */
+ unsigned long ipath_sendctrl;
+- unsigned long ipath_lastcancel; /* to not count armlaunch after cancel */
++ /* to not count armlaunch after cancel */
++ unsigned long ipath_lastcancel;
++ /* count cases where special trigger was needed (double write) */
++ unsigned long ipath_spectriggerhit;
+
+ /* value we put in kr_rcvhdrcnt */
+ u32 ipath_rcvhdrcnt;
+@@ -510,6 +602,7 @@ struct ipath_devdata {
+ u32 ipath_piobcnt4k;
+ /* size in bytes of "4KB" PIO buffers */
+ u32 ipath_piosize4k;
++ u32 ipath_pioreserved; /* reserved special-inkernel; */
+ /* kr_rcvegrbase value */
+ u32 ipath_rcvegrbase;
+ /* kr_rcvegrcnt value */
+@@ -546,10 +639,10 @@ struct ipath_devdata {
+ u32 ipath_init_ibmaxlen;
+ /* size of each rcvegrbuffer */
+ u32 ipath_rcvegrbufsize;
+- /* width (2,4,8,16,32) from HT config reg */
+- u32 ipath_htwidth;
+- /* HT speed (200,400,800,1000) from HT config */
+- u32 ipath_htspeed;
++ /* localbus width (1, 2,4,8,16,32) from config space */
++ u32 ipath_lbus_width;
++ /* localbus speed (HT: 200,400,800,1000; PCIe 2500) */
++ u32 ipath_lbus_speed;
+ /*
+ * number of sequential ibcstatus change for polling active/quiet
+ * (i.e., link not coming up).
+@@ -573,21 +666,14 @@ struct ipath_devdata {
+ */
+ u8 ipath_serial[16];
+ /* human readable board version */
+- u8 ipath_boardversion[80];
++ u8 ipath_boardversion[96];
++ u8 ipath_lbus_info[32]; /* human readable localbus info */
+ /* chip major rev, from ipath_revision */
+ u8 ipath_majrev;
+ /* chip minor rev, from ipath_revision */
+ u8 ipath_minrev;
+ /* board rev, from ipath_revision */
+ u8 ipath_boardrev;
+-
+- u8 ipath_r_portenable_shift;
+- u8 ipath_r_intravail_shift;
+- u8 ipath_r_tailupd_shift;
+- u8 ipath_r_portcfg_shift;
+-
+- /* unit # of this chip, if present */
+- int ipath_unit;
+ /* saved for restore after reset */
+ u8 ipath_pci_cacheline;
+ /* LID mask control */
+@@ -603,6 +689,14 @@ struct ipath_devdata {
+ /* Rx Polarity inversion (compensate for ~tx on partner) */
+ u8 ipath_rx_pol_inv;
+
++ u8 ipath_r_portenable_shift;
++ u8 ipath_r_intravail_shift;
++ u8 ipath_r_tailupd_shift;
++ u8 ipath_r_portcfg_shift;
++
++ /* unit # of this chip, if present */
++ int ipath_unit;
++
+ /* local link integrity counter */
+ u32 ipath_lli_counter;
+ /* local link integrity errors */
+@@ -617,9 +711,6 @@ struct ipath_devdata {
+ u32 ipath_overrun_thresh_errs;
+ u32 ipath_lli_errs;
+
+- /* status check work */
+- struct delayed_work status_work;
+-
+ /*
+ * Not all devices managed by a driver instance are the same
+ * type, so these fields must be per-device.
+@@ -632,8 +723,8 @@ struct ipath_devdata {
+ * Below should be computable from number of ports,
+ * since they are never modified.
+ */
+- u32 ipath_i_rcvavail_mask;
+- u32 ipath_i_rcvurg_mask;
++ u64 ipath_i_rcvavail_mask;
++ u64 ipath_i_rcvurg_mask;
+ u16 ipath_i_rcvurg_shift;
+ u16 ipath_i_rcvavail_shift;
+
+@@ -641,8 +732,9 @@ struct ipath_devdata {
+ * Register bits for selecting i2c direction and values, used for
+ * I2C serial flash.
+ */
+- u16 ipath_gpio_sda_num;
+- u16 ipath_gpio_scl_num;
++ u8 ipath_gpio_sda_num;
++ u8 ipath_gpio_scl_num;
++ u8 ipath_i2c_chain_type;
+ u64 ipath_gpio_sda;
+ u64 ipath_gpio_scl;
+
+@@ -703,13 +795,51 @@ struct ipath_devdata {
+ /* interrupt mitigation reload register info */
+ u16 ipath_jint_idle_ticks; /* idle clock ticks */
+ u16 ipath_jint_max_packets; /* max packets across all ports */
++
++ /*
++ * lock for access to SerDes, and flags to sequence preset
++ * versus steady-state. 7220-only at the moment.
++ */
++ spinlock_t ipath_sdepb_lock;
++ u8 ipath_presets_needed; /* Set if presets to be restored next DOWN */
+ };
+
++/* ipath_hol_state values (stopping/starting user proc, send flushing) */
++#define IPATH_HOL_UP 0
++#define IPATH_HOL_DOWN 1
++/* ipath_hol_next toggle values, used when hol_state IPATH_HOL_DOWN */
++#define IPATH_HOL_DOWNSTOP 0
++#define IPATH_HOL_DOWNCONT 1
++
++/* bit positions for sdma_status */
++#define IPATH_SDMA_ABORTING 0
++#define IPATH_SDMA_DISARMED 1
++#define IPATH_SDMA_DISABLED 2
++#define IPATH_SDMA_LAYERBUF 3
++#define IPATH_SDMA_RUNNING 62
++#define IPATH_SDMA_SHUTDOWN 63
++
++/* bit combinations that correspond to abort states */
++#define IPATH_SDMA_ABORT_NONE 0
++#define IPATH_SDMA_ABORT_ABORTING (1UL << IPATH_SDMA_ABORTING)
++#define IPATH_SDMA_ABORT_DISARMED ((1UL << IPATH_SDMA_ABORTING) | \
++ (1UL << IPATH_SDMA_DISARMED))
++#define IPATH_SDMA_ABORT_DISABLED ((1UL << IPATH_SDMA_ABORTING) | \
++ (1UL << IPATH_SDMA_DISABLED))
++#define IPATH_SDMA_ABORT_ABORTED ((1UL << IPATH_SDMA_ABORTING) | \
++ (1UL << IPATH_SDMA_DISARMED) | (1UL << IPATH_SDMA_DISABLED))
++#define IPATH_SDMA_ABORT_MASK ((1UL<<IPATH_SDMA_ABORTING) | \
++ (1UL << IPATH_SDMA_DISARMED) | (1UL << IPATH_SDMA_DISABLED))
++
++#define IPATH_SDMA_BUF_NONE 0
++#define IPATH_SDMA_BUF_MASK (1UL<<IPATH_SDMA_LAYERBUF)
++
+ /* Private data for file operations */
+ struct ipath_filedata {
+ struct ipath_portdata *pd;
+ unsigned subport;
+ unsigned tidcursor;
++ struct ipath_user_sdma_queue *pq;
+ };
+ extern struct list_head ipath_dev_list;
+ extern spinlock_t ipath_devs_lock;
+@@ -718,15 +848,15 @@ extern struct ipath_devdata *ipath_lookup(int unit);
+ int ipath_init_chip(struct ipath_devdata *, int);
+ int ipath_enable_wc(struct ipath_devdata *dd);
+ void ipath_disable_wc(struct ipath_devdata *dd);
+-int ipath_count_units(int *npresentp, int *nupp, u32 *maxportsp);
++int ipath_count_units(int *npresentp, int *nupp, int *maxportsp);
+ void ipath_shutdown_device(struct ipath_devdata *);
+ void ipath_clear_freeze(struct ipath_devdata *);
+
+ struct file_operations;
+ int ipath_cdev_init(int minor, char *name, const struct file_operations *fops,
+- struct cdev **cdevp, struct class_device **class_devp);
++ struct cdev **cdevp, struct device **devp);
+ void ipath_cdev_cleanup(struct cdev **cdevp,
+- struct class_device **class_devp);
++ struct device **devp);
+
+ int ipath_diag_add(struct ipath_devdata *);
+ void ipath_diag_remove(struct ipath_devdata *);
+@@ -741,7 +871,8 @@ struct sk_buff *ipath_alloc_skb(struct ipath_devdata *dd, gfp_t);
+ extern int ipath_diag_inuse;
+
+ irqreturn_t ipath_intr(int irq, void *devid);
+-int ipath_decode_err(char *buf, size_t blen, ipath_err_t err);
++int ipath_decode_err(struct ipath_devdata *dd, char *buf, size_t blen,
++ ipath_err_t err);
+ #if __IPATH_INFO || __IPATH_DBG
+ extern const char *ipath_ibcstatus_str[];
+ #endif
+@@ -774,6 +905,13 @@ int ipath_set_lid(struct ipath_devdata *, u32, u8);
+ int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
+ void ipath_enable_armlaunch(struct ipath_devdata *);
+ void ipath_disable_armlaunch(struct ipath_devdata *);
++void ipath_hol_down(struct ipath_devdata *);
++void ipath_hol_up(struct ipath_devdata *);
++void ipath_hol_event(unsigned long);
++void ipath_toggle_rclkrls(struct ipath_devdata *);
++void ipath_sd7220_clr_ibpar(struct ipath_devdata *);
++void ipath_set_relock_poll(struct ipath_devdata *, int);
++void ipath_shutdown_relock_poll(struct ipath_devdata *);
+
+ /* for use in system calls, where we want to know device type, etc. */
+ #define port_fp(fp) ((struct ipath_filedata *)(fp)->private_data)->pd
+@@ -781,11 +919,15 @@ void ipath_disable_armlaunch(struct ipath_devdata *);
+ ((struct ipath_filedata *)(fp)->private_data)->subport
+ #define tidcursor_fp(fp) \
+ ((struct ipath_filedata *)(fp)->private_data)->tidcursor
++#define user_sdma_queue_fp(fp) \
++ ((struct ipath_filedata *)(fp)->private_data)->pq
+
+ /*
+ * values for ipath_flags
+ */
+-/* The chip is up and initted */
++ /* chip can report link latency (IB 1.2) */
++#define IPATH_HAS_LINK_LATENCY 0x1
++ /* The chip is up and initted */
+ #define IPATH_INITTED 0x2
+ /* set if any user code has set kr_rcvhdrsize */
+ #define IPATH_RCVHDRSZ_SET 0x4
+@@ -809,6 +951,8 @@ void ipath_disable_armlaunch(struct ipath_devdata *);
+ #define IPATH_LINKUNK 0x400
+ /* Write combining flush needed for PIO */
+ #define IPATH_PIO_FLUSH_WC 0x1000
++ /* DMA Receive tail pointer */
++#define IPATH_NODMA_RTAIL 0x2000
+ /* no IB cable, or no device on IB cable */
+ #define IPATH_NOCABLE 0x4000
+ /* Supports port zero per packet receive interrupts via
+@@ -819,16 +963,26 @@ void ipath_disable_armlaunch(struct ipath_devdata *);
+ /* packet/word counters are 32 bit, else those 4 counters
+ * are 64bit */
+ #define IPATH_32BITCOUNTERS 0x20000
+- /* can miss port0 rx interrupts */
+ /* Interrupt register is 64 bits */
+ #define IPATH_INTREG_64 0x40000
++ /* can miss port0 rx interrupts */
+ #define IPATH_DISABLED 0x80000 /* administratively disabled */
+ /* Use GPIO interrupts for new counters */
+ #define IPATH_GPIO_ERRINTRS 0x100000
+ #define IPATH_SWAP_PIOBUFS 0x200000
++ /* Supports Send DMA */
++#define IPATH_HAS_SEND_DMA 0x400000
++ /* Supports Send Count (not just word count) in PBC */
++#define IPATH_HAS_PBC_CNT 0x800000
+ /* Suppress heartbeat, even if turning off loopback */
+ #define IPATH_NO_HRTBT 0x1000000
++#define IPATH_HAS_THRESH_UPDATE 0x4000000
+ #define IPATH_HAS_MULT_IB_SPEED 0x8000000
++#define IPATH_IB_AUTONEG_INPROG 0x10000000
++#define IPATH_IB_AUTONEG_FAILED 0x20000000
++ /* Linkdown-disable intentionally, Do not attempt to bring up */
++#define IPATH_IB_LINK_DISABLED 0x40000000
++#define IPATH_IB_FORCE_NOTIFY 0x80000000 /* force notify on next ib change */
+
+ /* Bits in GPIO for the added interrupts */
+ #define IPATH_GPIO_PORT0_BIT 2
+@@ -847,13 +1001,18 @@ void ipath_disable_armlaunch(struct ipath_devdata *);
+
+ /* free up any allocated data at closes */
+ void ipath_free_data(struct ipath_portdata *dd);
+-u32 __iomem *ipath_getpiobuf(struct ipath_devdata *, u32 *);
++u32 __iomem *ipath_getpiobuf(struct ipath_devdata *, u32, u32 *);
++void ipath_chg_pioavailkernel(struct ipath_devdata *dd, unsigned start,
++ unsigned len, int avail);
++void ipath_init_iba7220_funcs(struct ipath_devdata *);
+ void ipath_init_iba6120_funcs(struct ipath_devdata *);
+ void ipath_init_iba6110_funcs(struct ipath_devdata *);
+ void ipath_get_eeprom_info(struct ipath_devdata *);
+ int ipath_update_eeprom_log(struct ipath_devdata *dd);
+ void ipath_inc_eeprom_err(struct ipath_devdata *dd, u32 eidx, u32 incr);
+ u64 ipath_snap_cntr(struct ipath_devdata *, ipath_creg);
++void ipath_disarm_senderrbufs(struct ipath_devdata *, int);
++void ipath_force_pio_avail_update(struct ipath_devdata *);
+ void signal_ib_event(struct ipath_devdata *dd, enum ib_event_type ev);
+
+ /*
+@@ -865,6 +1024,34 @@ void signal_ib_event(struct ipath_devdata *dd, enum ib_event_type ev);
+ #define IPATH_LED_LOG 2 /* Logical (link) YELLOW LED */
+ void ipath_set_led_override(struct ipath_devdata *dd, unsigned int val);
+
++/* send dma routines */
++int setup_sdma(struct ipath_devdata *);
++void teardown_sdma(struct ipath_devdata *);
++void ipath_restart_sdma(struct ipath_devdata *);
++void ipath_sdma_intr(struct ipath_devdata *);
++int ipath_sdma_verbs_send(struct ipath_devdata *, struct ipath_sge_state *,
++ u32, struct ipath_verbs_txreq *);
++/* ipath_sdma_lock should be locked before calling this. */
++int ipath_sdma_make_progress(struct ipath_devdata *dd);
++
++/* must be called under ipath_sdma_lock */
++static inline u16 ipath_sdma_descq_freecnt(const struct ipath_devdata *dd)
++{
++ return dd->ipath_sdma_descq_cnt -
++ (dd->ipath_sdma_descq_added - dd->ipath_sdma_descq_removed) -
++ 1 - dd->ipath_sdma_desc_nreserved;
++}
++
++static inline void ipath_sdma_desc_reserve(struct ipath_devdata *dd, u16 cnt)
++{
++ dd->ipath_sdma_desc_nreserved += cnt;
++}
++
++static inline void ipath_sdma_desc_unreserve(struct ipath_devdata *dd, u16 cnt)
++{
++ dd->ipath_sdma_desc_nreserved -= cnt;
++}
++
+ /*
+ * number of words used for protocol header if not set by ipath_userinit();
+ */
+@@ -875,6 +1062,8 @@ void ipath_release_user_pages(struct page **, size_t);
+ void ipath_release_user_pages_on_close(struct page **, size_t);
+ int ipath_eeprom_read(struct ipath_devdata *, u8, void *, int);
+ int ipath_eeprom_write(struct ipath_devdata *, u8, const void *, int);
++int ipath_tempsense_read(struct ipath_devdata *, u8 regnum);
++int ipath_tempsense_write(struct ipath_devdata *, u8 regnum, u8 data);
+
+ /* these are used for the registers that vary with port */
+ void ipath_write_kreg_port(const struct ipath_devdata *, ipath_kreg,
+@@ -891,8 +1080,7 @@ void ipath_write_kreg_port(const struct ipath_devdata *, ipath_kreg,
+
+ /*
+ * At the moment, none of the s-registers are writable, so no
+- * ipath_write_sreg(), and none of the c-registers are writable, so no
+- * ipath_write_creg().
++ * ipath_write_sreg().
+ */
+
+ /**
+@@ -1001,6 +1189,27 @@ static inline u32 ipath_get_rcvhdrtail(const struct ipath_portdata *pd)
+ pd->port_rcvhdrtail_kvaddr));
+ }
+
++static inline u32 ipath_get_hdrqtail(const struct ipath_portdata *pd)
++{
++ const struct ipath_devdata *dd = pd->port_dd;
++ u32 hdrqtail;
++
++ if (dd->ipath_flags & IPATH_NODMA_RTAIL) {
++ __le32 *rhf_addr;
++ u32 seq;
++
++ rhf_addr = (__le32 *) pd->port_rcvhdrq +
++ pd->port_head + dd->ipath_rhf_offset;
++ seq = ipath_hdrget_seq(rhf_addr);
++ hdrqtail = pd->port_head;
++ if (seq == pd->port_seq_cnt)
++ hdrqtail++;
++ } else
++ hdrqtail = ipath_get_rcvhdrtail(pd);
++
++ return hdrqtail;
++}
++
+ static inline u64 ipath_read_ireg(const struct ipath_devdata *dd, ipath_kreg r)
+ {
+ return (dd->ipath_flags & IPATH_INTREG_64) ?
+@@ -1029,6 +1238,21 @@ static inline u32 ipath_ib_linktrstate(struct ipath_devdata *dd, u64 ibcs)
+ }
+
+ /*
++ * from contents of IBCStatus (or a saved copy), return logical link state
++ * combination of link state and linktraining state (down, active, init,
++ * arm, etc.
++ */
++static inline u32 ipath_ib_state(struct ipath_devdata *dd, u64 ibcs)
++{
++ u32 ibs;
++ ibs = (u32)(ibcs >> INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) &
++ dd->ibcs_lts_mask;
++ ibs |= (u32)(ibcs &
++ (INFINIPATH_IBCS_LINKSTATE_MASK << dd->ibcs_ls_shift));
++ return ibs;
++}
++
++/*
+ * sysfs interface.
+ */
+
+@@ -1053,6 +1277,7 @@ int ipathfs_remove_device(struct ipath_devdata *);
+ dma_addr_t ipath_map_page(struct pci_dev *, struct page *, unsigned long,
+ size_t, int);
+ dma_addr_t ipath_map_single(struct pci_dev *, void *, size_t, int);
++const char *ipath_get_unit_name(int unit);
+
+ /*
+ * Flush write combining store buffers (if present) and perform a write
+@@ -1065,11 +1290,8 @@ dma_addr_t ipath_map_single(struct pci_dev *, void *, size_t, int);
+ #endif
+
+ extern unsigned ipath_debug; /* debugging bit mask */
+-
+-#define IPATH_MAX_PARITY_ATTEMPTS 10000 /* max times to try recovery */
+-
+-const char *ipath_get_unit_name(int unit);
+-
++extern unsigned ipath_linkrecovery;
++extern unsigned ipath_mtu4096;
+ extern struct mutex ipath_mutex;
+
+ #define IPATH_DRV_NAME "ib_ipath"
+@@ -1096,7 +1318,7 @@ extern struct mutex ipath_mutex;
+
+ # define __IPATH_DBG_WHICH(which,fmt,...) \
+ do { \
+- if(unlikely(ipath_debug&(which))) \
++ if (unlikely(ipath_debug & (which))) \
+ printk(KERN_DEBUG IPATH_DRV_NAME ": %s: " fmt, \
+ __func__,##__VA_ARGS__); \
+ } while(0)
+diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c
+index b34b91d..1ff46ae 100644
+--- a/drivers/infiniband/hw/ipath/ipath_mad.c
++++ b/drivers/infiniband/hw/ipath/ipath_mad.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+@@ -146,6 +146,15 @@ static int recv_subn_get_guidinfo(struct ib_smp *smp,
+ return reply(smp);
+ }
+
++static void set_link_width_enabled(struct ipath_devdata *dd, u32 w)
++{
++ (void) dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_LWID_ENB, w);
++}
++
++static void set_link_speed_enabled(struct ipath_devdata *dd, u32 s)
++{
++ (void) dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_SPD_ENB, s);
++}
+
+ static int get_overrunthreshold(struct ipath_devdata *dd)
+ {
+@@ -226,6 +235,7 @@ static int recv_subn_get_portinfo(struct ib_smp *smp,
+ struct ib_device *ibdev, u8 port)
+ {
+ struct ipath_ibdev *dev;
++ struct ipath_devdata *dd;
+ struct ib_port_info *pip = (struct ib_port_info *)smp->data;
+ u16 lid;
+ u8 ibcstat;
+@@ -239,6 +249,7 @@ static int recv_subn_get_portinfo(struct ib_smp *smp,
+ }
+
+ dev = to_idev(ibdev);
++ dd = dev->dd;
+
+ /* Clear all fields. Only set the non-zero fields. */
+ memset(smp->data, 0, sizeof(smp->data));
+@@ -248,25 +259,28 @@ static int recv_subn_get_portinfo(struct ib_smp *smp,
+ dev->mkeyprot == 0)
+ pip->mkey = dev->mkey;
+ pip->gid_prefix = dev->gid_prefix;
+- lid = dev->dd->ipath_lid;
++ lid = dd->ipath_lid;
+ pip->lid = lid ? cpu_to_be16(lid) : IB_LID_PERMISSIVE;
+ pip->sm_lid = cpu_to_be16(dev->sm_lid);
+ pip->cap_mask = cpu_to_be32(dev->port_cap_flags);
+ /* pip->diag_code; */
+ pip->mkey_lease_period = cpu_to_be16(dev->mkey_lease_period);
+ pip->local_port_num = port;
+- pip->link_width_enabled = dev->link_width_enabled;
+- pip->link_width_supported = 3; /* 1x or 4x */
+- pip->link_width_active = 2; /* 4x */
+- pip->linkspeed_portstate = 0x10; /* 2.5Gbps */
+- ibcstat = dev->dd->ipath_lastibcstat;
+- pip->linkspeed_portstate |= ((ibcstat >> 4) & 0x3) + 1;
++ pip->link_width_enabled = dd->ipath_link_width_enabled;
++ pip->link_width_supported = dd->ipath_link_width_supported;
++ pip->link_width_active = dd->ipath_link_width_active;
++ pip->linkspeed_portstate = dd->ipath_link_speed_supported << 4;
++ ibcstat = dd->ipath_lastibcstat;
++ /* map LinkState to IB portinfo values. */
++ pip->linkspeed_portstate |= ipath_ib_linkstate(dd, ibcstat) + 1;
++
+ pip->portphysstate_linkdown =
+- (ipath_cvt_physportstate[ibcstat & 0xf] << 4) |
+- (get_linkdowndefaultstate(dev->dd) ? 1 : 2);
+- pip->mkeyprot_resv_lmc = (dev->mkeyprot << 6) | dev->dd->ipath_lmc;
+- pip->linkspeedactive_enabled = 0x11; /* 2.5Gbps, 2.5Gbps */
+- switch (dev->dd->ipath_ibmtu) {
++ (ipath_cvt_physportstate[ibcstat & dd->ibcs_lts_mask] << 4) |
++ (get_linkdowndefaultstate(dd) ? 1 : 2);
++ pip->mkeyprot_resv_lmc = (dev->mkeyprot << 6) | dd->ipath_lmc;
++ pip->linkspeedactive_enabled = (dd->ipath_link_speed_active << 4) |
++ dd->ipath_link_speed_enabled;
++ switch (dd->ipath_ibmtu) {
+ case 4096:
+ mtu = IB_MTU_4096;
+ break;
+@@ -292,19 +306,15 @@ static int recv_subn_get_portinfo(struct ib_smp *smp,
+ /* pip->vl_arb_high_cap; // only one VL */
+ /* pip->vl_arb_low_cap; // only one VL */
+ /* InitTypeReply = 0 */
+- /*
+- * Note: the chips support a maximum MTU of 4096, but the driver
+- * hasn't implemented this feature yet, so set the maximum value
+- * to 2048.
+- */
+- pip->inittypereply_mtucap = IB_MTU_2048;
+- // HCAs ignore VLStallCount and HOQLife
++ /* our mtu cap depends on whether 4K MTU enabled or not */
++ pip->inittypereply_mtucap = ipath_mtu4096 ? IB_MTU_4096 : IB_MTU_2048;
++ /* HCAs ignore VLStallCount and HOQLife */
+ /* pip->vlstallcnt_hoqlife; */
+ pip->operationalvl_pei_peo_fpi_fpo = 0x10; /* OVLs = 1 */
+ pip->mkey_violations = cpu_to_be16(dev->mkey_violations);
+ /* P_KeyViolations are counted by hardware. */
+ pip->pkey_violations =
+- cpu_to_be16((ipath_get_cr_errpkey(dev->dd) -
++ cpu_to_be16((ipath_get_cr_errpkey(dd) -
+ dev->z_pkey_violations) & 0xFFFF);
+ pip->qkey_violations = cpu_to_be16(dev->qkey_violations);
+ /* Only the hardware GUID is supported for now */
+@@ -313,10 +323,17 @@ static int recv_subn_get_portinfo(struct ib_smp *smp,
+ /* 32.768 usec. response time (guessing) */
+ pip->resv_resptimevalue = 3;
+ pip->localphyerrors_overrunerrors =
+- (get_phyerrthreshold(dev->dd) << 4) |
+- get_overrunthreshold(dev->dd);
++ (get_phyerrthreshold(dd) << 4) |
++ get_overrunthreshold(dd);
+ /* pip->max_credit_hint; */
+- /* pip->link_roundtrip_latency[3]; */
++ if (dev->port_cap_flags & IB_PORT_LINK_LATENCY_SUP) {
++ u32 v;
++
++ v = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_LINKLATENCY);
++ pip->link_roundtrip_latency[0] = v >> 16;
++ pip->link_roundtrip_latency[1] = v >> 8;
++ pip->link_roundtrip_latency[2] = v;
++ }
+
+ ret = reply(smp);
+
+@@ -444,19 +461,25 @@ static int recv_subn_set_portinfo(struct ib_smp *smp,
+ ib_dispatch_event(&event);
+ }
+
+- /* Only 4x supported but allow 1x or 4x to be set (see 14.2.6.6). */
++ /* Allow 1x or 4x to be set (see 14.2.6.6). */
+ lwe = pip->link_width_enabled;
+- if ((lwe >= 4 && lwe <= 8) || (lwe >= 0xC && lwe <= 0xFE))
+- goto err;
+- if (lwe == 0xFF)
+- dev->link_width_enabled = 3; /* 1x or 4x */
+- else if (lwe)
+- dev->link_width_enabled = lwe;
++ if (lwe) {
++ if (lwe == 0xFF)
++ lwe = dd->ipath_link_width_supported;
++ else if (lwe >= 16 || (lwe & ~dd->ipath_link_width_supported))
++ goto err;
++ set_link_width_enabled(dd, lwe);
++ }
+
+- /* Only 2.5 Gbs supported. */
++ /* Allow 2.5 or 5.0 Gbs. */
+ lse = pip->linkspeedactive_enabled & 0xF;
+- if (lse >= 2 && lse <= 0xE)
+- goto err;
++ if (lse) {
++ if (lse == 15)
++ lse = dd->ipath_link_speed_supported;
++ else if (lse >= 8 || (lse & ~dd->ipath_link_speed_supported))
++ goto err;
++ set_link_speed_enabled(dd, lse);
++ }
+
+ /* Set link down default state. */
+ switch (pip->portphysstate_linkdown & 0xF) {
+@@ -491,6 +514,8 @@ static int recv_subn_set_portinfo(struct ib_smp *smp,
+ mtu = 2048;
+ break;
+ case IB_MTU_4096:
++ if (!ipath_mtu4096)
++ goto err;
+ mtu = 4096;
+ break;
+ default:
+@@ -565,6 +590,10 @@ static int recv_subn_set_portinfo(struct ib_smp *smp,
+ else
+ goto err;
+ ipath_set_linkstate(dd, lstate);
++ if (lstate == IPATH_IB_LINKDOWN_DISABLE) {
++ ret = IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;
++ goto done;
++ }
+ ipath_wait_linkstate(dd, IPATH_LINKINIT | IPATH_LINKARMED |
+ IPATH_LINKACTIVE, 1000);
+ break;
+@@ -948,10 +977,14 @@ static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
+ * nsec. 0 == 4 nsec., 1 == 8 nsec., ..., 255 == 1020 nsec. Sample
+ * intervals are counted in ticks. Since we use Linux timers, that
+ * count in jiffies, we can't sample for less than 1000 ticks if HZ
+- * == 1000 (4000 ticks if HZ is 250).
++ * == 1000 (4000 ticks if HZ is 250). link_speed_active returns 2 for
++ * DDR, 1 for SDR, set the tick to 1 for DDR, 0 for SDR on chips that
++ * have hardware support for delaying packets.
+ */
+- /* XXX This is WRONG. */
+- p->tick = 250; /* 1 usec. */
++ if (crp->cr_psstat)
++ p->tick = dev->dd->ipath_link_speed_active - 1;
++ else
++ p->tick = 250; /* 1 usec. */
+ p->counter_width = 4; /* 32 bit counters */
+ p->counter_mask0_9 = COUNTER_MASK0_9;
+ spin_lock_irqsave(&dev->pending_lock, flags);
+@@ -1364,7 +1397,8 @@ static int process_subn(struct ib_device *ibdev, int mad_flags,
+ }
+
+ /* Is the mkey in the process of expiring? */
+- if (dev->mkey_lease_timeout && jiffies >= dev->mkey_lease_timeout) {
++ if (dev->mkey_lease_timeout &&
++ time_after_eq(jiffies, dev->mkey_lease_timeout)) {
+ /* Clear timeout and mkey protection field. */
+ dev->mkey_lease_timeout = 0;
+ dev->mkeyprot = 0;
+diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c
+index 087ed31..dd5b6e9 100644
+--- a/drivers/infiniband/hw/ipath/ipath_qp.c
++++ b/drivers/infiniband/hw/ipath/ipath_qp.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+@@ -340,6 +340,7 @@ static void ipath_reset_qp(struct ipath_qp *qp, enum ib_qp_type type)
+ qp->s_flags &= IPATH_S_SIGNAL_REQ_WR;
+ qp->s_hdrwords = 0;
+ qp->s_wqe = NULL;
++ qp->s_pkt_delay = 0;
+ qp->s_psn = 0;
+ qp->r_psn = 0;
+ qp->r_msn = 0;
+@@ -392,7 +393,6 @@ int ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err)
+ qp->ibqp.qp_num, qp->remote_qpn, err);
+
+ spin_lock(&dev->pending_lock);
+- /* XXX What if its already removed by the timeout code? */
+ if (!list_empty(&qp->timerwait))
+ list_del_init(&qp->timerwait);
+ if (!list_empty(&qp->piowait))
+@@ -516,13 +516,13 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ goto inval;
+
+ /*
+- * Note: the chips support a maximum MTU of 4096, but the driver
+- * hasn't implemented this feature yet, so don't allow Path MTU
+- * values greater than 2048.
++ * don't allow invalid Path MTU values or greater than 2048
++ * unless we are configured for a 4KB MTU
+ */
+- if (attr_mask & IB_QP_PATH_MTU)
+- if (attr->path_mtu > IB_MTU_2048)
+- goto inval;
++ if ((attr_mask & IB_QP_PATH_MTU) &&
++ (ib_mtu_enum_to_int(attr->path_mtu) == -1 ||
++ (attr->path_mtu > IB_MTU_2048 && !ipath_mtu4096)))
++ goto inval;
+
+ if (attr_mask & IB_QP_PATH_MIG_STATE)
+ if (attr->path_mig_state != IB_MIG_MIGRATED &&
+@@ -564,8 +564,10 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ if (attr_mask & IB_QP_ACCESS_FLAGS)
+ qp->qp_access_flags = attr->qp_access_flags;
+
+- if (attr_mask & IB_QP_AV)
++ if (attr_mask & IB_QP_AV) {
+ qp->remote_ah_attr = attr->ah_attr;
++ qp->s_dmult = ipath_ib_rate_to_mult(attr->ah_attr.static_rate);
++ }
+
+ if (attr_mask & IB_QP_PATH_MTU)
+ qp->path_mtu = attr->path_mtu;
+@@ -748,22 +750,33 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
+ size_t sz;
+ struct ib_qp *ret;
+
+- if (init_attr->cap.max_send_sge > ib_ipath_max_sges ||
+- init_attr->cap.max_recv_sge > ib_ipath_max_sges ||
+- init_attr->cap.max_send_wr > ib_ipath_max_qp_wrs ||
+- init_attr->cap.max_recv_wr > ib_ipath_max_qp_wrs) {
+- ret = ERR_PTR(-ENOMEM);
++ if (init_attr->create_flags) {
++ ret = ERR_PTR(-EINVAL);
+ goto bail;
+ }
+
+- if (init_attr->cap.max_send_sge +
+- init_attr->cap.max_recv_sge +
+- init_attr->cap.max_send_wr +
+- init_attr->cap.max_recv_wr == 0) {
++ if (init_attr->cap.max_send_sge > ib_ipath_max_sges ||
++ init_attr->cap.max_send_wr > ib_ipath_max_qp_wrs) {
+ ret = ERR_PTR(-EINVAL);
+ goto bail;
+ }
+
++ /* Check receive queue parameters if no SRQ is specified. */
++ if (!init_attr->srq) {
++ if (init_attr->cap.max_recv_sge > ib_ipath_max_sges ||
++ init_attr->cap.max_recv_wr > ib_ipath_max_qp_wrs) {
++ ret = ERR_PTR(-EINVAL);
++ goto bail;
++ }
++ if (init_attr->cap.max_send_sge +
++ init_attr->cap.max_send_wr +
++ init_attr->cap.max_recv_sge +
++ init_attr->cap.max_recv_wr == 0) {
++ ret = ERR_PTR(-EINVAL);
++ goto bail;
++ }
++ }
++
+ switch (init_attr->qp_type) {
+ case IB_QPT_UC:
+ case IB_QPT_RC:
+@@ -840,6 +853,7 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
+ goto bail_qp;
+ }
+ qp->ip = NULL;
++ qp->s_tx = NULL;
+ ipath_reset_qp(qp, init_attr->qp_type);
+ break;
+
+@@ -945,12 +959,20 @@ int ipath_destroy_qp(struct ib_qp *ibqp)
+ /* Stop the sending tasklet. */
+ tasklet_kill(&qp->s_task);
+
++ if (qp->s_tx) {
++ atomic_dec(&qp->refcount);
++ if (qp->s_tx->txreq.flags & IPATH_SDMA_TXREQ_F_FREEBUF)
++ kfree(qp->s_tx->txreq.map_addr);
++ }
++
+ /* Make sure the QP isn't on the timeout list. */
+ spin_lock_irqsave(&dev->pending_lock, flags);
+ if (!list_empty(&qp->timerwait))
+ list_del_init(&qp->timerwait);
+ if (!list_empty(&qp->piowait))
+ list_del_init(&qp->piowait);
++ if (qp->s_tx)
++ list_add(&qp->s_tx->txreq.list, &dev->txreq_free);
+ spin_unlock_irqrestore(&dev->pending_lock, flags);
+
+ /*
+@@ -1021,7 +1043,6 @@ void ipath_sqerror_qp(struct ipath_qp *qp, struct ib_wc *wc)
+ qp->ibqp.qp_num, qp->remote_qpn, wc->status);
+
+ spin_lock(&dev->pending_lock);
+- /* XXX What if its already removed by the timeout code? */
+ if (!list_empty(&qp->timerwait))
+ list_del_init(&qp->timerwait);
+ if (!list_empty(&qp->piowait))
+diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c
+index 40f3e37..c405dfb 100644
+--- a/drivers/infiniband/hw/ipath/ipath_rc.c
++++ b/drivers/infiniband/hw/ipath/ipath_rc.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+@@ -31,6 +31,8 @@
+ * SOFTWARE.
+ */
+
++#include <linux/io.h>
++
+ #include "ipath_verbs.h"
+ #include "ipath_kernel.h"
+
+@@ -306,7 +308,7 @@ int ipath_make_rc_req(struct ipath_qp *qp)
+ else {
+ qp->s_state = OP(SEND_ONLY_WITH_IMMEDIATE);
+ /* Immediate data comes after the BTH */
+- ohdr->u.imm_data = wqe->wr.imm_data;
++ ohdr->u.imm_data = wqe->wr.ex.imm_data;
+ hwords += 1;
+ }
+ if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+@@ -344,7 +346,7 @@ int ipath_make_rc_req(struct ipath_qp *qp)
+ qp->s_state =
+ OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE);
+ /* Immediate data comes after RETH */
+- ohdr->u.rc.imm_data = wqe->wr.imm_data;
++ ohdr->u.rc.imm_data = wqe->wr.ex.imm_data;
+ hwords += 1;
+ if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ bth0 |= 1 << 23;
+@@ -488,7 +490,7 @@ int ipath_make_rc_req(struct ipath_qp *qp)
+ else {
+ qp->s_state = OP(SEND_LAST_WITH_IMMEDIATE);
+ /* Immediate data comes after the BTH */
+- ohdr->u.imm_data = wqe->wr.imm_data;
++ ohdr->u.imm_data = wqe->wr.ex.imm_data;
+ hwords += 1;
+ }
+ if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+@@ -524,7 +526,7 @@ int ipath_make_rc_req(struct ipath_qp *qp)
+ else {
+ qp->s_state = OP(RDMA_WRITE_LAST_WITH_IMMEDIATE);
+ /* Immediate data comes after the BTH */
+- ohdr->u.imm_data = wqe->wr.imm_data;
++ ohdr->u.imm_data = wqe->wr.ex.imm_data;
+ hwords += 1;
+ if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ bth0 |= 1 << 23;
+@@ -585,19 +587,39 @@ bail:
+ static void send_rc_ack(struct ipath_qp *qp)
+ {
+ struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
++ struct ipath_devdata *dd;
+ u16 lrh0;
+ u32 bth0;
+ u32 hwords;
++ u32 __iomem *piobuf;
+ struct ipath_ib_header hdr;
+ struct ipath_other_headers *ohdr;
+ unsigned long flags;
+
++ spin_lock_irqsave(&qp->s_lock, flags);
++
+ /* Don't send ACK or NAK if a RDMA read or atomic is pending. */
+ if (qp->r_head_ack_queue != qp->s_tail_ack_queue ||
+ (qp->s_flags & IPATH_S_ACK_PENDING) ||
+ qp->s_ack_state != OP(ACKNOWLEDGE))
+ goto queue_ack;
+
++ spin_unlock_irqrestore(&qp->s_lock, flags);
++
++ dd = dev->dd;
++ piobuf = ipath_getpiobuf(dd, 0, NULL);
++ if (!piobuf) {
++ /*
++ * We are out of PIO buffers at the moment.
++ * Pass responsibility for sending the ACK to the
++ * send tasklet so that when a PIO buffer becomes
++ * available, the ACK is sent ahead of other outgoing
++ * packets.
++ */
++ spin_lock_irqsave(&qp->s_lock, flags);
++ goto queue_ack;
++ }
++
+ /* Construct the header. */
+ ohdr = &hdr.u.oth;
+ lrh0 = IPATH_LRH_BTH;
+@@ -611,7 +633,7 @@ static void send_rc_ack(struct ipath_qp *qp)
+ lrh0 = IPATH_LRH_GRH;
+ }
+ /* read pkey_index w/o lock (its atomic) */
+- bth0 = ipath_get_pkey(dev->dd, qp->s_pkey_index) |
++ bth0 = ipath_get_pkey(dd, qp->s_pkey_index) |
+ (OP(ACKNOWLEDGE) << 24) | (1 << 22);
+ if (qp->r_nak_state)
+ ohdr->u.aeth = cpu_to_be32((qp->r_msn & IPATH_MSN_MASK) |
+@@ -623,30 +645,29 @@ static void send_rc_ack(struct ipath_qp *qp)
+ hdr.lrh[0] = cpu_to_be16(lrh0);
+ hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid);
+ hdr.lrh[2] = cpu_to_be16(hwords + SIZE_OF_CRC);
+- hdr.lrh[3] = cpu_to_be16(dev->dd->ipath_lid);
++ hdr.lrh[3] = cpu_to_be16(dd->ipath_lid);
+ ohdr->bth[0] = cpu_to_be32(bth0);
+ ohdr->bth[1] = cpu_to_be32(qp->remote_qpn);
+ ohdr->bth[2] = cpu_to_be32(qp->r_ack_psn & IPATH_PSN_MASK);
+
+- /*
+- * If we can send the ACK, clear the ACK state.
+- */
+- if (ipath_verbs_send(qp, &hdr, hwords, NULL, 0) == 0) {
+- dev->n_unicast_xmit++;
+- goto done;
+- }
++ writeq(hwords + 1, piobuf);
+
+- /*
+- * We are out of PIO buffers at the moment.
+- * Pass responsibility for sending the ACK to the
+- * send tasklet so that when a PIO buffer becomes
+- * available, the ACK is sent ahead of other outgoing
+- * packets.
+- */
+- dev->n_rc_qacks++;
++ if (dd->ipath_flags & IPATH_PIO_FLUSH_WC) {
++ u32 *hdrp = (u32 *) &hdr;
++
++ ipath_flush_wc();
++ __iowrite32_copy(piobuf + 2, hdrp, hwords - 1);
++ ipath_flush_wc();
++ __raw_writel(hdrp[hwords - 1], piobuf + hwords + 1);
++ } else
++ __iowrite32_copy(piobuf + 2, (u32 *) &hdr, hwords);
++
++ ipath_flush_wc();
++
++ dev->n_unicast_xmit++;
++ goto done;
+
+ queue_ack:
+- spin_lock_irqsave(&qp->s_lock, flags);
+ dev->n_rc_qacks++;
+ qp->s_flags |= IPATH_S_ACK_PENDING;
+ qp->s_nak_state = qp->r_nak_state;
+diff --git a/drivers/infiniband/hw/ipath/ipath_registers.h b/drivers/infiniband/hw/ipath/ipath_registers.h
+index 92ad73a..8f44d0c 100644
+--- a/drivers/infiniband/hw/ipath/ipath_registers.h
++++ b/drivers/infiniband/hw/ipath/ipath_registers.h
+@@ -63,67 +63,92 @@
+ /* kr_control bits */
+ #define INFINIPATH_C_FREEZEMODE 0x00000002
+ #define INFINIPATH_C_LINKENABLE 0x00000004
+-#define INFINIPATH_C_RESET 0x00000001
+
+ /* kr_sendctrl bits */
+ #define INFINIPATH_S_DISARMPIOBUF_SHIFT 16
++#define INFINIPATH_S_UPDTHRESH_SHIFT 24
++#define INFINIPATH_S_UPDTHRESH_MASK 0x1f
+
+ #define IPATH_S_ABORT 0
+ #define IPATH_S_PIOINTBUFAVAIL 1
+ #define IPATH_S_PIOBUFAVAILUPD 2
+ #define IPATH_S_PIOENABLE 3
++#define IPATH_S_SDMAINTENABLE 9
++#define IPATH_S_SDMASINGLEDESCRIPTOR 10
++#define IPATH_S_SDMAENABLE 11
++#define IPATH_S_SDMAHALT 12
+ #define IPATH_S_DISARM 31
+
+ #define INFINIPATH_S_ABORT (1U << IPATH_S_ABORT)
+ #define INFINIPATH_S_PIOINTBUFAVAIL (1U << IPATH_S_PIOINTBUFAVAIL)
+ #define INFINIPATH_S_PIOBUFAVAILUPD (1U << IPATH_S_PIOBUFAVAILUPD)
+ #define INFINIPATH_S_PIOENABLE (1U << IPATH_S_PIOENABLE)
++#define INFINIPATH_S_SDMAINTENABLE (1U << IPATH_S_SDMAINTENABLE)
++#define INFINIPATH_S_SDMASINGLEDESCRIPTOR \
++ (1U << IPATH_S_SDMASINGLEDESCRIPTOR)
++#define INFINIPATH_S_SDMAENABLE (1U << IPATH_S_SDMAENABLE)
++#define INFINIPATH_S_SDMAHALT (1U << IPATH_S_SDMAHALT)
+ #define INFINIPATH_S_DISARM (1U << IPATH_S_DISARM)
+
+-/* kr_rcvctrl bits */
++/* kr_rcvctrl bits that are the same on multiple chips */
+ #define INFINIPATH_R_PORTENABLE_SHIFT 0
+ #define INFINIPATH_R_QPMAP_ENABLE (1ULL << 38)
+
+ /* kr_intstatus, kr_intclear, kr_intmask bits */
+-#define INFINIPATH_I_RCVURG_SHIFT 0
+-#define INFINIPATH_I_RCVAVAIL_SHIFT 12
+-#define INFINIPATH_I_ERROR 0x80000000
+-#define INFINIPATH_I_SPIOSENT 0x40000000
+-#define INFINIPATH_I_SPIOBUFAVAIL 0x20000000
+-#define INFINIPATH_I_GPIO 0x10000000
++#define INFINIPATH_I_SDMAINT 0x8000000000000000ULL
++#define INFINIPATH_I_SDMADISABLED 0x4000000000000000ULL
++#define INFINIPATH_I_ERROR 0x0000000080000000ULL
++#define INFINIPATH_I_SPIOSENT 0x0000000040000000ULL
++#define INFINIPATH_I_SPIOBUFAVAIL 0x0000000020000000ULL
++#define INFINIPATH_I_GPIO 0x0000000010000000ULL
++#define INFINIPATH_I_JINT 0x0000000004000000ULL
+
+ /* kr_errorstatus, kr_errorclear, kr_errormask bits */
+-#define INFINIPATH_E_RFORMATERR 0x0000000000000001ULL
+-#define INFINIPATH_E_RVCRC 0x0000000000000002ULL
+-#define INFINIPATH_E_RICRC 0x0000000000000004ULL
+-#define INFINIPATH_E_RMINPKTLEN 0x0000000000000008ULL
+-#define INFINIPATH_E_RMAXPKTLEN 0x0000000000000010ULL
+-#define INFINIPATH_E_RLONGPKTLEN 0x0000000000000020ULL
+-#define INFINIPATH_E_RSHORTPKTLEN 0x0000000000000040ULL
+-#define INFINIPATH_E_RUNEXPCHAR 0x0000000000000080ULL
+-#define INFINIPATH_E_RUNSUPVL 0x0000000000000100ULL
+-#define INFINIPATH_E_REBP 0x0000000000000200ULL
+-#define INFINIPATH_E_RIBFLOW 0x0000000000000400ULL
+-#define INFINIPATH_E_RBADVERSION 0x0000000000000800ULL
+-#define INFINIPATH_E_RRCVEGRFULL 0x0000000000001000ULL
+-#define INFINIPATH_E_RRCVHDRFULL 0x0000000000002000ULL
+-#define INFINIPATH_E_RBADTID 0x0000000000004000ULL
+-#define INFINIPATH_E_RHDRLEN 0x0000000000008000ULL
+-#define INFINIPATH_E_RHDR 0x0000000000010000ULL
+-#define INFINIPATH_E_RIBLOSTLINK 0x0000000000020000ULL
+-#define INFINIPATH_E_SMINPKTLEN 0x0000000020000000ULL
+-#define INFINIPATH_E_SMAXPKTLEN 0x0000000040000000ULL
+-#define INFINIPATH_E_SUNDERRUN 0x0000000080000000ULL
+-#define INFINIPATH_E_SPKTLEN 0x0000000100000000ULL
+-#define INFINIPATH_E_SDROPPEDSMPPKT 0x0000000200000000ULL
+-#define INFINIPATH_E_SDROPPEDDATAPKT 0x0000000400000000ULL
+-#define INFINIPATH_E_SPIOARMLAUNCH 0x0000000800000000ULL
+-#define INFINIPATH_E_SUNEXPERRPKTNUM 0x0000001000000000ULL
+-#define INFINIPATH_E_SUNSUPVL 0x0000002000000000ULL
+-#define INFINIPATH_E_IBSTATUSCHANGED 0x0001000000000000ULL
+-#define INFINIPATH_E_INVALIDADDR 0x0002000000000000ULL
+-#define INFINIPATH_E_RESET 0x0004000000000000ULL
+-#define INFINIPATH_E_HARDWARE 0x0008000000000000ULL
++#define INFINIPATH_E_RFORMATERR 0x0000000000000001ULL
++#define INFINIPATH_E_RVCRC 0x0000000000000002ULL
++#define INFINIPATH_E_RICRC 0x0000000000000004ULL
++#define INFINIPATH_E_RMINPKTLEN 0x0000000000000008ULL
++#define INFINIPATH_E_RMAXPKTLEN 0x0000000000000010ULL
++#define INFINIPATH_E_RLONGPKTLEN 0x0000000000000020ULL
++#define INFINIPATH_E_RSHORTPKTLEN 0x0000000000000040ULL
++#define INFINIPATH_E_RUNEXPCHAR 0x0000000000000080ULL
++#define INFINIPATH_E_RUNSUPVL 0x0000000000000100ULL
++#define INFINIPATH_E_REBP 0x0000000000000200ULL
++#define INFINIPATH_E_RIBFLOW 0x0000000000000400ULL
++#define INFINIPATH_E_RBADVERSION 0x0000000000000800ULL
++#define INFINIPATH_E_RRCVEGRFULL 0x0000000000001000ULL
++#define INFINIPATH_E_RRCVHDRFULL 0x0000000000002000ULL
++#define INFINIPATH_E_RBADTID 0x0000000000004000ULL
++#define INFINIPATH_E_RHDRLEN 0x0000000000008000ULL
++#define INFINIPATH_E_RHDR 0x0000000000010000ULL
++#define INFINIPATH_E_RIBLOSTLINK 0x0000000000020000ULL
++#define INFINIPATH_E_SENDSPECIALTRIGGER 0x0000000008000000ULL
++#define INFINIPATH_E_SDMADISABLED 0x0000000010000000ULL
++#define INFINIPATH_E_SMINPKTLEN 0x0000000020000000ULL
++#define INFINIPATH_E_SMAXPKTLEN 0x0000000040000000ULL
++#define INFINIPATH_E_SUNDERRUN 0x0000000080000000ULL
++#define INFINIPATH_E_SPKTLEN 0x0000000100000000ULL
++#define INFINIPATH_E_SDROPPEDSMPPKT 0x0000000200000000ULL
++#define INFINIPATH_E_SDROPPEDDATAPKT 0x0000000400000000ULL
++#define INFINIPATH_E_SPIOARMLAUNCH 0x0000000800000000ULL
++#define INFINIPATH_E_SUNEXPERRPKTNUM 0x0000001000000000ULL
++#define INFINIPATH_E_SUNSUPVL 0x0000002000000000ULL
++#define INFINIPATH_E_SENDBUFMISUSE 0x0000004000000000ULL
++#define INFINIPATH_E_SDMAGENMISMATCH 0x0000008000000000ULL
++#define INFINIPATH_E_SDMAOUTOFBOUND 0x0000010000000000ULL
++#define INFINIPATH_E_SDMATAILOUTOFBOUND 0x0000020000000000ULL
++#define INFINIPATH_E_SDMABASE 0x0000040000000000ULL
++#define INFINIPATH_E_SDMA1STDESC 0x0000080000000000ULL
++#define INFINIPATH_E_SDMARPYTAG 0x0000100000000000ULL
++#define INFINIPATH_E_SDMADWEN 0x0000200000000000ULL
++#define INFINIPATH_E_SDMAMISSINGDW 0x0000400000000000ULL
++#define INFINIPATH_E_SDMAUNEXPDATA 0x0000800000000000ULL
++#define INFINIPATH_E_IBSTATUSCHANGED 0x0001000000000000ULL
++#define INFINIPATH_E_INVALIDADDR 0x0002000000000000ULL
++#define INFINIPATH_E_RESET 0x0004000000000000ULL
++#define INFINIPATH_E_HARDWARE 0x0008000000000000ULL
++#define INFINIPATH_E_SDMADESCADDRMISALIGN 0x0010000000000000ULL
++#define INFINIPATH_E_INVALIDEEPCMD 0x0020000000000000ULL
+
+ /*
+ * this is used to print "common" packet errors only when the
+@@ -134,6 +159,17 @@
+ | INFINIPATH_E_RICRC | INFINIPATH_E_RSHORTPKTLEN \
+ | INFINIPATH_E_REBP )
+
++/* Convenience for decoding Send DMA errors */
++#define INFINIPATH_E_SDMAERRS ( \
++ INFINIPATH_E_SDMAGENMISMATCH | INFINIPATH_E_SDMAOUTOFBOUND | \
++ INFINIPATH_E_SDMATAILOUTOFBOUND | INFINIPATH_E_SDMABASE | \
++ INFINIPATH_E_SDMA1STDESC | INFINIPATH_E_SDMARPYTAG | \
++ INFINIPATH_E_SDMADWEN | INFINIPATH_E_SDMAMISSINGDW | \
++ INFINIPATH_E_SDMAUNEXPDATA | \
++ INFINIPATH_E_SDMADESCADDRMISALIGN | \
++ INFINIPATH_E_SDMADISABLED | \
++ INFINIPATH_E_SENDBUFMISUSE)
++
+ /* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */
+ /* TXEMEMPARITYERR bit 0: PIObuf, 1: PIOpbc, 2: launchfifo
+ * RXEMEMPARITYERR bit 0: rcvbuf, 1: lookupq, 2: expTID, 3: eagerTID
+@@ -158,7 +194,7 @@
+ #define INFINIPATH_HWE_RXEMEMPARITYERR_HDRINFO 0x40ULL
+ /* waldo specific -- find the rest in ipath_6110.c */
+ #define INFINIPATH_HWE_RXDSYNCMEMPARITYERR 0x0000000400000000ULL
+-/* monty specific -- find the rest in ipath_6120.c */
++/* 6120/7220 specific -- find the rest in ipath_6120.c and ipath_7220.c */
+ #define INFINIPATH_HWE_MEMBISTFAILED 0x0040000000000000ULL
+
+ /* kr_hwdiagctrl bits */
+@@ -185,8 +221,8 @@
+ #define INFINIPATH_IBCC_LINKINITCMD_SLEEP 3
+ #define INFINIPATH_IBCC_LINKINITCMD_SHIFT 16
+ #define INFINIPATH_IBCC_LINKCMD_MASK 0x3ULL
+-#define INFINIPATH_IBCC_LINKCMD_DOWN 1 /* move to 0x11 */
+-#define INFINIPATH_IBCC_LINKCMD_ARMED 2 /* move to 0x21 */
++#define INFINIPATH_IBCC_LINKCMD_DOWN 1 /* move to 0x11 */
++#define INFINIPATH_IBCC_LINKCMD_ARMED 2 /* move to 0x21 */
+ #define INFINIPATH_IBCC_LINKCMD_ACTIVE 3 /* move to 0x31 */
+ #define INFINIPATH_IBCC_LINKCMD_SHIFT 18
+ #define INFINIPATH_IBCC_MAXPKTLEN_MASK 0x7FFULL
+@@ -201,10 +237,9 @@
+ #define INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE 0x4000000000000000ULL
+
+ /* kr_ibcstatus bits */
+-#define INFINIPATH_IBCS_LINKTRAININGSTATE_MASK 0xF
+ #define INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT 0
+ #define INFINIPATH_IBCS_LINKSTATE_MASK 0x7
+-#define INFINIPATH_IBCS_LINKSTATE_SHIFT 4
++
+ #define INFINIPATH_IBCS_TXREADY 0x40000000
+ #define INFINIPATH_IBCS_TXCREDITOK 0x80000000
+ /* link training states (shift by
+@@ -222,30 +257,13 @@
+ #define INFINIPATH_IBCS_LT_STATE_RECOVERRETRAIN 0x0c
+ #define INFINIPATH_IBCS_LT_STATE_RECOVERWAITRMT 0x0e
+ #define INFINIPATH_IBCS_LT_STATE_RECOVERIDLE 0x0f
+-/* link state machine states (shift by INFINIPATH_IBCS_LINKSTATE_SHIFT) */
++/* link state machine states (shift by ibcs_ls_shift) */
+ #define INFINIPATH_IBCS_L_STATE_DOWN 0x0
+ #define INFINIPATH_IBCS_L_STATE_INIT 0x1
+ #define INFINIPATH_IBCS_L_STATE_ARM 0x2
+ #define INFINIPATH_IBCS_L_STATE_ACTIVE 0x3
+ #define INFINIPATH_IBCS_L_STATE_ACT_DEFER 0x4
+
+-/* combination link status states that we use with some frequency */
+-#define IPATH_IBSTATE_MASK ((INFINIPATH_IBCS_LINKTRAININGSTATE_MASK \
+- << INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) | \
+- (INFINIPATH_IBCS_LINKSTATE_MASK \
+- <<INFINIPATH_IBCS_LINKSTATE_SHIFT))
+-#define IPATH_IBSTATE_INIT ((INFINIPATH_IBCS_L_STATE_INIT \
+- << INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
+- (INFINIPATH_IBCS_LT_STATE_LINKUP \
+- <<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
+-#define IPATH_IBSTATE_ARM ((INFINIPATH_IBCS_L_STATE_ARM \
+- << INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
+- (INFINIPATH_IBCS_LT_STATE_LINKUP \
+- <<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
+-#define IPATH_IBSTATE_ACTIVE ((INFINIPATH_IBCS_L_STATE_ACTIVE \
+- << INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
+- (INFINIPATH_IBCS_LT_STATE_LINKUP \
+- <<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
+
+ /* kr_extstatus bits */
+ #define INFINIPATH_EXTS_SERDESPLLLOCK 0x1
+@@ -286,8 +304,7 @@
+ /* L1 Power down; use with RXDETECT, Otherwise not used on IB side */
+ #define INFINIPATH_SERDC0_L1PWR_DN 0xF0ULL
+
+-/* kr_xgxsconfig bits */
+-#define INFINIPATH_XGXS_RESET 0x7ULL
++/* common kr_xgxsconfig bits (or safe in all, even if not implemented) */
+ #define INFINIPATH_XGXS_RX_POL_SHIFT 19
+ #define INFINIPATH_XGXS_RX_POL_MASK 0xfULL
+
+@@ -417,6 +434,29 @@ struct ipath_kregs {
+ ipath_kreg kr_pcieq1serdesconfig0;
+ ipath_kreg kr_pcieq1serdesconfig1;
+ ipath_kreg kr_pcieq1serdesstatus;
++ ipath_kreg kr_hrtbt_guid;
++ ipath_kreg kr_ibcddrctrl;
++ ipath_kreg kr_ibcddrstatus;
++ ipath_kreg kr_jintreload;
++
++ /* send dma related regs */
++ ipath_kreg kr_senddmabase;
++ ipath_kreg kr_senddmalengen;
++ ipath_kreg kr_senddmatail;
++ ipath_kreg kr_senddmahead;
++ ipath_kreg kr_senddmaheadaddr;
++ ipath_kreg kr_senddmabufmask0;
++ ipath_kreg kr_senddmabufmask1;
++ ipath_kreg kr_senddmabufmask2;
++ ipath_kreg kr_senddmastatus;
++
++ /* SerDes related regs (IBA7220-only) */
++ ipath_kreg kr_ibserdesctrl;
++ ipath_kreg kr_ib_epbacc;
++ ipath_kreg kr_ib_epbtrans;
++ ipath_kreg kr_pcie_epbacc;
++ ipath_kreg kr_pcie_epbtrans;
++ ipath_kreg kr_ib_ddsrxeq;
+ };
+
+ struct ipath_cregs {
+diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c
+index a59bdbd..8ac5c1d 100644
+--- a/drivers/infiniband/hw/ipath/ipath_ruc.c
++++ b/drivers/infiniband/hw/ipath/ipath_ruc.c
+@@ -310,7 +310,7 @@ again:
+ switch (wqe->wr.opcode) {
+ case IB_WR_SEND_WITH_IMM:
+ wc.wc_flags = IB_WC_WITH_IMM;
+- wc.imm_data = wqe->wr.imm_data;
++ wc.imm_data = wqe->wr.ex.imm_data;
+ /* FALLTHROUGH */
+ case IB_WR_SEND:
+ if (!ipath_get_rwqe(qp, 0)) {
+@@ -339,7 +339,7 @@ again:
+ goto err;
+ }
+ wc.wc_flags = IB_WC_WITH_IMM;
+- wc.imm_data = wqe->wr.imm_data;
++ wc.imm_data = wqe->wr.ex.imm_data;
+ if (!ipath_get_rwqe(qp, 1))
+ goto rnr_nak;
+ /* FALLTHROUGH */
+@@ -483,14 +483,16 @@ done:
+
+ static void want_buffer(struct ipath_devdata *dd)
+ {
+- unsigned long flags;
+-
+- spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
+- dd->ipath_sendctrl |= INFINIPATH_S_PIOINTBUFAVAIL;
+- ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+- dd->ipath_sendctrl);
+- ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+- spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++ if (!(dd->ipath_flags & IPATH_HAS_SEND_DMA)) {
++ unsigned long flags;
++
++ spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++ dd->ipath_sendctrl |= INFINIPATH_S_PIOINTBUFAVAIL;
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
++ dd->ipath_sendctrl);
++ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++ spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++ }
+ }
+
+ /**
+diff --git a/drivers/infiniband/hw/ipath/ipath_sd7220.c b/drivers/infiniband/hw/ipath/ipath_sd7220.c
+new file mode 100644
+index 0000000..aa47eb5
+--- /dev/null
++++ b/drivers/infiniband/hw/ipath/ipath_sd7220.c
+@@ -0,0 +1,1462 @@
++/*
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses. You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ * Redistribution and use in source and binary forms, with or
++ * without modification, are permitted provided that the following
++ * conditions are met:
++ *
++ * - Redistributions of source code must retain the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer.
++ *
++ * - Redistributions in binary form must reproduce the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer in the documentation and/or other materials
++ * provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++/*
++ * This file contains all of the code that is specific to the SerDes
++ * on the InfiniPath 7220 chip.
++ */
++
++#include <linux/pci.h>
++#include <linux/delay.h>
++
++#include "ipath_kernel.h"
++#include "ipath_registers.h"
++#include "ipath_7220.h"
++
++/*
++ * The IBSerDesMappTable is a memory that holds values to be stored in
++ * various SerDes registers by IBC. It is not part of the normal kregs
++ * map and is used in exactly one place, hence the #define below.
++ */
++#define KR_IBSerDesMappTable (0x94000 / (sizeof(uint64_t)))
++
++/*
++ * Below used for sdnum parameter, selecting one of the two sections
++ * used for PCIe, or the single SerDes used for IB.
++ */
++#define PCIE_SERDES0 0
++#define PCIE_SERDES1 1
++
++/*
++ * The EPB requires addressing in a particular form. EPB_LOC() is intended
++ * to make #definitions a little more readable.
++ */
++#define EPB_ADDR_SHF 8
++#define EPB_LOC(chn, elt, reg) \
++ (((elt & 0xf) | ((chn & 7) << 4) | ((reg & 0x3f) << 9)) << \
++ EPB_ADDR_SHF)
++#define EPB_IB_QUAD0_CS_SHF (25)
++#define EPB_IB_QUAD0_CS (1U << EPB_IB_QUAD0_CS_SHF)
++#define EPB_IB_UC_CS_SHF (26)
++#define EPB_PCIE_UC_CS_SHF (27)
++#define EPB_GLOBAL_WR (1U << (EPB_ADDR_SHF + 8))
++
++/* Forward declarations. */
++static int ipath_sd7220_reg_mod(struct ipath_devdata *dd, int sdnum, u32 loc,
++ u32 data, u32 mask);
++static int ibsd_mod_allchnls(struct ipath_devdata *dd, int loc, int val,
++ int mask);
++static int ipath_sd_trimdone_poll(struct ipath_devdata *dd);
++static void ipath_sd_trimdone_monitor(struct ipath_devdata *dd,
++ const char *where);
++static int ipath_sd_setvals(struct ipath_devdata *dd);
++static int ipath_sd_early(struct ipath_devdata *dd);
++static int ipath_sd_dactrim(struct ipath_devdata *dd);
++/* Set the registers that IBC may muck with to their default "preset" values */
++int ipath_sd7220_presets(struct ipath_devdata *dd);
++static int ipath_internal_presets(struct ipath_devdata *dd);
++/* Tweak the register (CMUCTRL5) that contains the TRIMSELF controls */
++static int ipath_sd_trimself(struct ipath_devdata *dd, int val);
++static int epb_access(struct ipath_devdata *dd, int sdnum, int claim);
++
++void ipath_set_relock_poll(struct ipath_devdata *dd, int ibup);
++
++/*
++ * Below keeps track of whether the "once per power-on" initialization has
++ * been done, because uC code Version 1.32.17 or higher allows the uC to
++ * be reset at will, and Automatic Equalization may require it. So the
++ * state of the reset "pin", as reflected in was_reset parameter to
++ * ipath_sd7220_init() is no longer valid. Instead, we check for the
++ * actual uC code having been loaded.
++ */
++static int ipath_ibsd_ucode_loaded(struct ipath_devdata *dd)
++{
++ if (!dd->serdes_first_init_done && (ipath_sd7220_ib_vfy(dd) > 0))
++ dd->serdes_first_init_done = 1;
++ return dd->serdes_first_init_done;
++}
++
++/* repeat #define for local use. "Real" #define is in ipath_iba7220.c */
++#define INFINIPATH_HWE_IB_UC_MEMORYPARITYERR 0x0000004000000000ULL
++#define IB_MPREG5 (EPB_LOC(6, 0, 0xE) | (1L << EPB_IB_UC_CS_SHF))
++#define IB_MPREG6 (EPB_LOC(6, 0, 0xF) | (1U << EPB_IB_UC_CS_SHF))
++#define UC_PAR_CLR_D 8
++#define UC_PAR_CLR_M 0xC
++#define IB_CTRL2(chn) (EPB_LOC(chn, 7, 3) | EPB_IB_QUAD0_CS)
++#define START_EQ1(chan) EPB_LOC(chan, 7, 0x27)
++
++void ipath_sd7220_clr_ibpar(struct ipath_devdata *dd)
++{
++ int ret;
++
++ /* clear, then re-enable parity errs */
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6,
++ UC_PAR_CLR_D, UC_PAR_CLR_M);
++ if (ret < 0) {
++ ipath_dev_err(dd, "Failed clearing IBSerDes Parity err\n");
++ goto bail;
++ }
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6, 0,
++ UC_PAR_CLR_M);
++
++ ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++ udelay(4);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
++ INFINIPATH_HWE_IB_UC_MEMORYPARITYERR);
++ ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++bail:
++ return;
++}
++
++/*
++ * After a reset or other unusual event, the epb interface may need
++ * to be re-synchronized, between the host and the uC.
++ * returns <0 for failure to resync within IBSD_RESYNC_TRIES (not expected)
++ */
++#define IBSD_RESYNC_TRIES 3
++#define IB_PGUDP(chn) (EPB_LOC((chn), 2, 1) | EPB_IB_QUAD0_CS)
++#define IB_CMUDONE(chn) (EPB_LOC((chn), 7, 0xF) | EPB_IB_QUAD0_CS)
++
++static int ipath_resync_ibepb(struct ipath_devdata *dd)
++{
++ int ret, pat, tries, chn;
++ u32 loc;
++
++ ret = -1;
++ chn = 0;
++ for (tries = 0; tries < (4 * IBSD_RESYNC_TRIES); ++tries) {
++ loc = IB_PGUDP(chn);
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, loc, 0, 0);
++ if (ret < 0) {
++ ipath_dev_err(dd, "Failed read in resync\n");
++ continue;
++ }
++ if (ret != 0xF0 && ret != 0x55 && tries == 0)
++ ipath_dev_err(dd, "unexpected pattern in resync\n");
++ pat = ret ^ 0xA5; /* alternate F0 and 55 */
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, loc, pat, 0xFF);
++ if (ret < 0) {
++ ipath_dev_err(dd, "Failed write in resync\n");
++ continue;
++ }
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, loc, 0, 0);
++ if (ret < 0) {
++ ipath_dev_err(dd, "Failed re-read in resync\n");
++ continue;
++ }
++ if (ret != pat) {
++ ipath_dev_err(dd, "Failed compare1 in resync\n");
++ continue;
++ }
++ loc = IB_CMUDONE(chn);
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, loc, 0, 0);
++ if (ret < 0) {
++ ipath_dev_err(dd, "Failed CMUDONE rd in resync\n");
++ continue;
++ }
++ if ((ret & 0x70) != ((chn << 4) | 0x40)) {
++ ipath_dev_err(dd, "Bad CMUDONE value %02X, chn %d\n",
++ ret, chn);
++ continue;
++ }
++ if (++chn == 4)
++ break; /* Success */
++ }
++ ipath_cdbg(VERBOSE, "Resync in %d tries\n", tries);
++ return (ret > 0) ? 0 : ret;
++}
++
++/*
++ * Localize the stuff that should be done to change IB uC reset
++ * returns <0 for errors.
++ */
++static int ipath_ibsd_reset(struct ipath_devdata *dd, int assert_rst)
++{
++ u64 rst_val;
++ int ret = 0;
++ unsigned long flags;
++
++ rst_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibserdesctrl);
++ if (assert_rst) {
++ /*
++ * Vendor recommends "interrupting" uC before reset, to
++ * minimize possible glitches.
++ */
++ spin_lock_irqsave(&dd->ipath_sdepb_lock, flags);
++ epb_access(dd, IB_7220_SERDES, 1);
++ rst_val |= 1ULL;
++ /* Squelch possible parity error from _asserting_ reset */
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
++ dd->ipath_hwerrmask &
++ ~INFINIPATH_HWE_IB_UC_MEMORYPARITYERR);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibserdesctrl, rst_val);
++ /* flush write, delay to ensure it took effect */
++ ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++ udelay(2);
++ /* once it's reset, can remove interrupt */
++ epb_access(dd, IB_7220_SERDES, -1);
++ spin_unlock_irqrestore(&dd->ipath_sdepb_lock, flags);
++ } else {
++ /*
++ * Before we de-assert reset, we need to deal with
++ * possible glitch on the Parity-error line.
++ * Suppress it around the reset, both in chip-level
++ * hwerrmask and in IB uC control reg. uC will allow
++ * it again during startup.
++ */
++ u64 val;
++ rst_val &= ~(1ULL);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
++ dd->ipath_hwerrmask &
++ ~INFINIPATH_HWE_IB_UC_MEMORYPARITYERR);
++
++ ret = ipath_resync_ibepb(dd);
++ if (ret < 0)
++ ipath_dev_err(dd, "unable to re-sync IB EPB\n");
++
++ /* set uC control regs to suppress parity errs */
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG5, 1, 1);
++ if (ret < 0)
++ goto bail;
++ /* IB uC code past Version 1.32.17 allow suppression of wdog */
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6, 0x80,
++ 0x80);
++ if (ret < 0) {
++ ipath_dev_err(dd, "Failed to set WDOG disable\n");
++ goto bail;
++ }
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibserdesctrl, rst_val);
++ /* flush write, delay for startup */
++ ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++ udelay(1);
++ /* clear, then re-enable parity errs */
++ ipath_sd7220_clr_ibpar(dd);
++ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus);
++ if (val & INFINIPATH_HWE_IB_UC_MEMORYPARITYERR) {
++ ipath_dev_err(dd, "IBUC Parity still set after RST\n");
++ dd->ipath_hwerrmask &=
++ ~INFINIPATH_HWE_IB_UC_MEMORYPARITYERR;
++ }
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
++ dd->ipath_hwerrmask);
++ }
++
++bail:
++ return ret;
++}
++
++static void ipath_sd_trimdone_monitor(struct ipath_devdata *dd,
++ const char *where)
++{
++ int ret, chn, baduns;
++ u64 val;
++
++ if (!where)
++ where = "?";
++
++ /* give time for reset to settle out in EPB */
++ udelay(2);
++
++ ret = ipath_resync_ibepb(dd);
++ if (ret < 0)
++ ipath_dev_err(dd, "not able to re-sync IB EPB (%s)\n", where);
++
++ /* Do "sacrificial read" to get EPB in sane state after reset */
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_CTRL2(0), 0, 0);
++ if (ret < 0)
++ ipath_dev_err(dd, "Failed TRIMDONE 1st read, (%s)\n", where);
++
++ /* Check/show "summary" Trim-done bit in IBCStatus */
++ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
++ if (val & (1ULL << 11))
++ ipath_cdbg(VERBOSE, "IBCS TRIMDONE set (%s)\n", where);
++ else
++ ipath_dev_err(dd, "IBCS TRIMDONE clear (%s)\n", where);
++
++ udelay(2);
++
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, IB_MPREG6, 0x80, 0x80);
++ if (ret < 0)
++ ipath_dev_err(dd, "Failed Dummy RMW, (%s)\n", where);
++ udelay(10);
++
++ baduns = 0;
++
++ for (chn = 3; chn >= 0; --chn) {
++ /* Read CTRL reg for each channel to check TRIMDONE */
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES,
++ IB_CTRL2(chn), 0, 0);
++ if (ret < 0)
++ ipath_dev_err(dd, "Failed checking TRIMDONE, chn %d"
++ " (%s)\n", chn, where);
++
++ if (!(ret & 0x10)) {
++ int probe;
++ baduns |= (1 << chn);
++ ipath_dev_err(dd, "TRIMDONE cleared on chn %d (%02X)."
++ " (%s)\n", chn, ret, where);
++ probe = ipath_sd7220_reg_mod(dd, IB_7220_SERDES,
++ IB_PGUDP(0), 0, 0);
++ ipath_dev_err(dd, "probe is %d (%02X)\n",
++ probe, probe);
++ probe = ipath_sd7220_reg_mod(dd, IB_7220_SERDES,
++ IB_CTRL2(chn), 0, 0);
++ ipath_dev_err(dd, "re-read: %d (%02X)\n",
++ probe, probe);
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES,
++ IB_CTRL2(chn), 0x10, 0x10);
++ if (ret < 0)
++ ipath_dev_err(dd,
++ "Err on TRIMDONE rewrite1\n");
++ }
++ }
++ for (chn = 3; chn >= 0; --chn) {
++ /* Read CTRL reg for each channel to check TRIMDONE */
++ if (baduns & (1 << chn)) {
++ ipath_dev_err(dd,
++ "Reseting TRIMDONE on chn %d (%s)\n",
++ chn, where);
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES,
++ IB_CTRL2(chn), 0x10, 0x10);
++ if (ret < 0)
++ ipath_dev_err(dd, "Failed re-setting "
++ "TRIMDONE, chn %d (%s)\n",
++ chn, where);
++ }
++ }
++}
++
++/*
++ * Below is portion of IBA7220-specific bringup_serdes() that actually
++ * deals with registers and memory within the SerDes itself.
++ * Post IB uC code version 1.32.17, was_reset being 1 is not really
++ * informative, so we double-check.
++ */
++int ipath_sd7220_init(struct ipath_devdata *dd, int was_reset)
++{
++ int ret = 1; /* default to failure */
++ int first_reset;
++ int val_stat;
++
++ if (!was_reset) {
++ /* entered with reset not asserted, we need to do it */
++ ipath_ibsd_reset(dd, 1);
++ ipath_sd_trimdone_monitor(dd, "Driver-reload");
++ }
++
++ /* Substitute our deduced value for was_reset */
++ ret = ipath_ibsd_ucode_loaded(dd);
++ if (ret < 0) {
++ ret = 1;
++ goto done;
++ }
++ first_reset = !ret; /* First reset if IBSD uCode not yet loaded */
++
++ /*
++ * Alter some regs per vendor latest doc, reset-defaults
++ * are not right for IB.
++ */
++ ret = ipath_sd_early(dd);
++ if (ret < 0) {
++ ipath_dev_err(dd, "Failed to set IB SERDES early defaults\n");
++ ret = 1;
++ goto done;
++ }
++
++ /*
++ * Set DAC manual trim IB.
++ * We only do this once after chip has been reset (usually
++ * same as once per system boot).
++ */
++ if (first_reset) {
++ ret = ipath_sd_dactrim(dd);
++ if (ret < 0) {
++ ipath_dev_err(dd, "Failed IB SERDES DAC trim\n");
++ ret = 1;
++ goto done;
++ }
++ }
++
++ /*
++ * Set various registers (DDS and RXEQ) that will be
++ * controlled by IBC (in 1.2 mode) to reasonable preset values
++ * Calling the "internal" version avoids the "check for needed"
++ * and "trimdone monitor" that might be counter-productive.
++ */
++ ret = ipath_internal_presets(dd);
++ if (ret < 0) {
++ ipath_dev_err(dd, "Failed to set IB SERDES presets\n");
++ ret = 1;
++ goto done;
++ }
++ ret = ipath_sd_trimself(dd, 0x80);
++ if (ret < 0) {
++ ipath_dev_err(dd, "Failed to set IB SERDES TRIMSELF\n");
++ ret = 1;
++ goto done;
++ }
++
++ /* Load image, then try to verify */
++ ret = 0; /* Assume success */
++ if (first_reset) {
++ int vfy;
++ int trim_done;
++ ipath_dbg("SerDes uC was reset, reloading PRAM\n");
++ ret = ipath_sd7220_ib_load(dd);
++ if (ret < 0) {
++ ipath_dev_err(dd, "Failed to load IB SERDES image\n");
++ ret = 1;
++ goto done;
++ }
++
++ /* Loaded image, try to verify */
++ vfy = ipath_sd7220_ib_vfy(dd);
++ if (vfy != ret) {
++ ipath_dev_err(dd, "SERDES PRAM VFY failed\n");
++ ret = 1;
++ goto done;
++ }
++ /*
++ * Loaded and verified. Almost good...
++ * hold "success" in ret
++ */
++ ret = 0;
++
++ /*
++ * Prev steps all worked, continue bringup
++ * De-assert RESET to uC, only in first reset, to allow
++ * trimming.
++ *
++ * Since our default setup sets START_EQ1 to
++ * PRESET, we need to clear that for this very first run.
++ */
++ ret = ibsd_mod_allchnls(dd, START_EQ1(0), 0, 0x38);
++ if (ret < 0) {
++ ipath_dev_err(dd, "Failed clearing START_EQ1\n");
++ ret = 1;
++ goto done;
++ }
++
++ ipath_ibsd_reset(dd, 0);
++ /*
++ * If this is not the first reset, trimdone should be set
++ * already.
++ */
++ trim_done = ipath_sd_trimdone_poll(dd);
++ /*
++ * Whether or not trimdone succeeded, we need to put the
++ * uC back into reset to avoid a possible fight with the
++ * IBC state-machine.
++ */
++ ipath_ibsd_reset(dd, 1);
++
++ if (!trim_done) {
++ ipath_dev_err(dd, "No TRIMDONE seen\n");
++ ret = 1;
++ goto done;
++ }
++
++ ipath_sd_trimdone_monitor(dd, "First-reset");
++ /* Remember so we do not re-do the load, dactrim, etc. */
++ dd->serdes_first_init_done = 1;
++ }
++ /*
++ * Setup for channel training and load values for
++ * RxEq and DDS in tables used by IBC in IB1.2 mode
++ */
++
++ val_stat = ipath_sd_setvals(dd);
++ if (val_stat < 0)
++ ret = 1;
++done:
++ /* start relock timer regardless, but start at 1 second */
++ ipath_set_relock_poll(dd, -1);
++ return ret;
++}
++
++#define EPB_ACC_REQ 1
++#define EPB_ACC_GNT 0x100
++#define EPB_DATA_MASK 0xFF
++#define EPB_RD (1ULL << 24)
++#define EPB_TRANS_RDY (1ULL << 31)
++#define EPB_TRANS_ERR (1ULL << 30)
++#define EPB_TRANS_TRIES 5
++
++/*
++ * query, claim, release ownership of the EPB (External Parallel Bus)
++ * for a specified SERDES.
++ * the "claim" parameter is >0 to claim, <0 to release, 0 to query.
++ * Returns <0 for errors, >0 if we had ownership, else 0.
++ */
++static int epb_access(struct ipath_devdata *dd, int sdnum, int claim)
++{
++ u16 acc;
++ u64 accval;
++ int owned = 0;
++ u64 oct_sel = 0;
++
++ switch (sdnum) {
++ case IB_7220_SERDES :
++ /*
++ * The IB SERDES "ownership" is fairly simple. A single each
++ * request/grant.
++ */
++ acc = dd->ipath_kregs->kr_ib_epbacc;
++ break;
++ case PCIE_SERDES0 :
++ case PCIE_SERDES1 :
++ /* PCIe SERDES has two "octants", need to select which */
++ acc = dd->ipath_kregs->kr_pcie_epbacc;
++ oct_sel = (2 << (sdnum - PCIE_SERDES0));
++ break;
++ default :
++ return 0;
++ }
++
++ /* Make sure any outstanding transaction was seen */
++ ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++ udelay(15);
++
++ accval = ipath_read_kreg32(dd, acc);
++
++ owned = !!(accval & EPB_ACC_GNT);
++ if (claim < 0) {
++ /* Need to release */
++ u64 pollval;
++ /*
++ * The only writeable bits are the request and CS.
++ * Both should be clear
++ */
++ u64 newval = 0;
++ ipath_write_kreg(dd, acc, newval);
++ /* First read after write is not trustworthy */
++ pollval = ipath_read_kreg32(dd, acc);
++ udelay(5);
++ pollval = ipath_read_kreg32(dd, acc);
++ if (pollval & EPB_ACC_GNT)
++ owned = -1;
++ } else if (claim > 0) {
++ /* Need to claim */
++ u64 pollval;
++ u64 newval = EPB_ACC_REQ | oct_sel;
++ ipath_write_kreg(dd, acc, newval);
++ /* First read after write is not trustworthy */
++ pollval = ipath_read_kreg32(dd, acc);
++ udelay(5);
++ pollval = ipath_read_kreg32(dd, acc);
++ if (!(pollval & EPB_ACC_GNT))
++ owned = -1;
++ }
++ return owned;
++}
++
++/*
++ * Lemma to deal with race condition of write..read to epb regs
++ */
++static int epb_trans(struct ipath_devdata *dd, u16 reg, u64 i_val, u64 *o_vp)
++{
++ int tries;
++ u64 transval;
++
++
++ ipath_write_kreg(dd, reg, i_val);
++ /* Throw away first read, as RDY bit may be stale */
++ transval = ipath_read_kreg64(dd, reg);
++
++ for (tries = EPB_TRANS_TRIES; tries; --tries) {
++ transval = ipath_read_kreg32(dd, reg);
++ if (transval & EPB_TRANS_RDY)
++ break;
++ udelay(5);
++ }
++ if (transval & EPB_TRANS_ERR)
++ return -1;
++ if (tries > 0 && o_vp)
++ *o_vp = transval;
++ return tries;
++}
++
++/**
++ *
++ * ipath_sd7220_reg_mod - modify SERDES register
++ * @dd: the infinipath device
++ * @sdnum: which SERDES to access
++ * @loc: location - channel, element, register, as packed by EPB_LOC() macro.
++ * @wd: Write Data - value to set in register
++ * @mask: ones where data should be spliced into reg.
++ *
++ * Basic register read/modify/write, with un-needed acesses elided. That is,
++ * a mask of zero will prevent write, while a mask of 0xFF will prevent read.
++ * returns current (presumed, if a write was done) contents of selected
++ * register, or <0 if errors.
++ */
++static int ipath_sd7220_reg_mod(struct ipath_devdata *dd, int sdnum, u32 loc,
++ u32 wd, u32 mask)
++{
++ u16 trans;
++ u64 transval;
++ int owned;
++ int tries, ret;
++ unsigned long flags;
++
++ switch (sdnum) {
++ case IB_7220_SERDES :
++ trans = dd->ipath_kregs->kr_ib_epbtrans;
++ break;
++ case PCIE_SERDES0 :
++ case PCIE_SERDES1 :
++ trans = dd->ipath_kregs->kr_pcie_epbtrans;
++ break;
++ default :
++ return -1;
++ }
++
++ /*
++ * All access is locked in software (vs other host threads) and
++ * hardware (vs uC access).
++ */
++ spin_lock_irqsave(&dd->ipath_sdepb_lock, flags);
++
++ owned = epb_access(dd, sdnum, 1);
++ if (owned < 0) {
++ spin_unlock_irqrestore(&dd->ipath_sdepb_lock, flags);
++ return -1;
++ }
++ ret = 0;
++ for (tries = EPB_TRANS_TRIES; tries; --tries) {
++ transval = ipath_read_kreg32(dd, trans);
++ if (transval & EPB_TRANS_RDY)
++ break;
++ udelay(5);
++ }
++
++ if (tries > 0) {
++ tries = 1; /* to make read-skip work */
++ if (mask != 0xFF) {
++ /*
++ * Not a pure write, so need to read.
++ * loc encodes chip-select as well as address
++ */
++ transval = loc | EPB_RD;
++ tries = epb_trans(dd, trans, transval, &transval);
++ }
++ if (tries > 0 && mask != 0) {
++ /*
++ * Not a pure read, so need to write.
++ */
++ wd = (wd & mask) | (transval & ~mask);
++ transval = loc | (wd & EPB_DATA_MASK);
++ tries = epb_trans(dd, trans, transval, &transval);
++ }
++ }
++ /* else, failed to see ready, what error-handling? */
++
++ /*
++ * Release bus. Failure is an error.
++ */
++ if (epb_access(dd, sdnum, -1) < 0)
++ ret = -1;
++ else
++ ret = transval & EPB_DATA_MASK;
++
++ spin_unlock_irqrestore(&dd->ipath_sdepb_lock, flags);
++ if (tries <= 0)
++ ret = -1;
++ return ret;
++}
++
++#define EPB_ROM_R (2)
++#define EPB_ROM_W (1)
++/*
++ * Below, all uC-related, use appropriate UC_CS, depending
++ * on which SerDes is used.
++ */
++#define EPB_UC_CTL EPB_LOC(6, 0, 0)
++#define EPB_MADDRL EPB_LOC(6, 0, 2)
++#define EPB_MADDRH EPB_LOC(6, 0, 3)
++#define EPB_ROMDATA EPB_LOC(6, 0, 4)
++#define EPB_RAMDATA EPB_LOC(6, 0, 5)
++
++/* Transfer date to/from uC Program RAM of IB or PCIe SerDes */
++static int ipath_sd7220_ram_xfer(struct ipath_devdata *dd, int sdnum, u32 loc,
++ u8 *buf, int cnt, int rd_notwr)
++{
++ u16 trans;
++ u64 transval;
++ u64 csbit;
++ int owned;
++ int tries;
++ int sofar;
++ int addr;
++ int ret;
++ unsigned long flags;
++ const char *op;
++
++ /* Pick appropriate transaction reg and "Chip select" for this serdes */
++ switch (sdnum) {
++ case IB_7220_SERDES :
++ csbit = 1ULL << EPB_IB_UC_CS_SHF;
++ trans = dd->ipath_kregs->kr_ib_epbtrans;
++ break;
++ case PCIE_SERDES0 :
++ case PCIE_SERDES1 :
++ /* PCIe SERDES has uC "chip select" in different bit, too */
++ csbit = 1ULL << EPB_PCIE_UC_CS_SHF;
++ trans = dd->ipath_kregs->kr_pcie_epbtrans;
++ break;
++ default :
++ return -1;
++ }
++
++ op = rd_notwr ? "Rd" : "Wr";
++ spin_lock_irqsave(&dd->ipath_sdepb_lock, flags);
++
++ owned = epb_access(dd, sdnum, 1);
++ if (owned < 0) {
++ spin_unlock_irqrestore(&dd->ipath_sdepb_lock, flags);
++ ipath_dbg("Could not get %s access to %s EPB: %X, loc %X\n",
++ op, (sdnum == IB_7220_SERDES) ? "IB" : "PCIe",
++ owned, loc);
++ return -1;
++ }
++
++ /*
++ * In future code, we may need to distinguish several address ranges,
++ * and select various memories based on this. For now, just trim
++ * "loc" (location including address and memory select) to
++ * "addr" (address within memory). we will only support PRAM
++ * The memory is 8KB.
++ */
++ addr = loc & 0x1FFF;
++ for (tries = EPB_TRANS_TRIES; tries; --tries) {
++ transval = ipath_read_kreg32(dd, trans);
++ if (transval & EPB_TRANS_RDY)
++ break;
++ udelay(5);
++ }
++
++ sofar = 0;
++ if (tries <= 0)
++ ipath_dbg("No initial RDY on EPB access request\n");
++ else {
++ /*
++ * Every "memory" access is doubly-indirect.
++ * We set two bytes of address, then read/write
++ * one or mores bytes of data.
++ */
++
++ /* First, we set control to "Read" or "Write" */
++ transval = csbit | EPB_UC_CTL |
++ (rd_notwr ? EPB_ROM_R : EPB_ROM_W);
++ tries = epb_trans(dd, trans, transval, &transval);
++ if (tries <= 0)
++ ipath_dbg("No EPB response to uC %s cmd\n", op);
++ while (tries > 0 && sofar < cnt) {
++ if (!sofar) {
++ /* Only set address at start of chunk */
++ int addrbyte = (addr + sofar) >> 8;
++ transval = csbit | EPB_MADDRH | addrbyte;
++ tries = epb_trans(dd, trans, transval,
++ &transval);
++ if (tries <= 0) {
++ ipath_dbg("No EPB response ADDRH\n");
++ break;
++ }
++ addrbyte = (addr + sofar) & 0xFF;
++ transval = csbit | EPB_MADDRL | addrbyte;
++ tries = epb_trans(dd, trans, transval,
++ &transval);
++ if (tries <= 0) {
++ ipath_dbg("No EPB response ADDRL\n");
++ break;
++ }
++ }
++
++ if (rd_notwr)
++ transval = csbit | EPB_ROMDATA | EPB_RD;
++ else
++ transval = csbit | EPB_ROMDATA | buf[sofar];
++ tries = epb_trans(dd, trans, transval, &transval);
++ if (tries <= 0) {
++ ipath_dbg("No EPB response DATA\n");
++ break;
++ }
++ if (rd_notwr)
++ buf[sofar] = transval & EPB_DATA_MASK;
++ ++sofar;
++ }
++ /* Finally, clear control-bit for Read or Write */
++ transval = csbit | EPB_UC_CTL;
++ tries = epb_trans(dd, trans, transval, &transval);
++ if (tries <= 0)
++ ipath_dbg("No EPB response to drop of uC %s cmd\n", op);
++ }
++
++ ret = sofar;
++ /* Release bus. Failure is an error */
++ if (epb_access(dd, sdnum, -1) < 0)
++ ret = -1;
++
++ spin_unlock_irqrestore(&dd->ipath_sdepb_lock, flags);
++ if (tries <= 0) {
++ ipath_dbg("SERDES PRAM %s failed after %d bytes\n", op, sofar);
++ ret = -1;
++ }
++ return ret;
++}
++
++#define PROG_CHUNK 64
++
++int ipath_sd7220_prog_ld(struct ipath_devdata *dd, int sdnum,
++ u8 *img, int len, int offset)
++{
++ int cnt, sofar, req;
++
++ sofar = 0;
++ while (sofar < len) {
++ req = len - sofar;
++ if (req > PROG_CHUNK)
++ req = PROG_CHUNK;
++ cnt = ipath_sd7220_ram_xfer(dd, sdnum, offset + sofar,
++ img + sofar, req, 0);
++ if (cnt < req) {
++ sofar = -1;
++ break;
++ }
++ sofar += req;
++ }
++ return sofar;
++}
++
++#define VFY_CHUNK 64
++#define SD_PRAM_ERROR_LIMIT 42
++
++int ipath_sd7220_prog_vfy(struct ipath_devdata *dd, int sdnum,
++ const u8 *img, int len, int offset)
++{
++ int cnt, sofar, req, idx, errors;
++ unsigned char readback[VFY_CHUNK];
++
++ errors = 0;
++ sofar = 0;
++ while (sofar < len) {
++ req = len - sofar;
++ if (req > VFY_CHUNK)
++ req = VFY_CHUNK;
++ cnt = ipath_sd7220_ram_xfer(dd, sdnum, sofar + offset,
++ readback, req, 1);
++ if (cnt < req) {
++ /* failed in read itself */
++ sofar = -1;
++ break;
++ }
++ for (idx = 0; idx < cnt; ++idx) {
++ if (readback[idx] != img[idx+sofar])
++ ++errors;
++ }
++ sofar += cnt;
++ }
++ return errors ? -errors : sofar;
++}
++
++/* IRQ not set up at this point in init, so we poll. */
++#define IB_SERDES_TRIM_DONE (1ULL << 11)
++#define TRIM_TMO (30)
++
++static int ipath_sd_trimdone_poll(struct ipath_devdata *dd)
++{
++ int trim_tmo, ret;
++ uint64_t val;
++
++ /*
++ * Default to failure, so IBC will not start
++ * without IB_SERDES_TRIM_DONE.
++ */
++ ret = 0;
++ for (trim_tmo = 0; trim_tmo < TRIM_TMO; ++trim_tmo) {
++ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
++ if (val & IB_SERDES_TRIM_DONE) {
++ ipath_cdbg(VERBOSE, "TRIMDONE after %d\n", trim_tmo);
++ ret = 1;
++ break;
++ }
++ msleep(10);
++ }
++ if (trim_tmo >= TRIM_TMO) {
++ ipath_dev_err(dd, "No TRIMDONE in %d tries\n", trim_tmo);
++ ret = 0;
++ }
++ return ret;
++}
++
++#define TX_FAST_ELT (9)
++
++/*
++ * Set the "negotiation" values for SERDES. These are used by the IB1.2
++ * link negotiation. Macros below are attempt to keep the values a
++ * little more human-editable.
++ * First, values related to Drive De-emphasis Settings.
++ */
++
++#define NUM_DDS_REGS 6
++#define DDS_REG_MAP 0x76A910 /* LSB-first list of regs (in elt 9) to mod */
++
++#define DDS_VAL(amp_d, main_d, ipst_d, ipre_d, amp_s, main_s, ipst_s, ipre_s) \
++ { { ((amp_d & 0x1F) << 1) | 1, ((amp_s & 0x1F) << 1) | 1, \
++ (main_d << 3) | 4 | (ipre_d >> 2), \
++ (main_s << 3) | 4 | (ipre_s >> 2), \
++ ((ipst_d & 0xF) << 1) | ((ipre_d & 3) << 6) | 0x21, \
++ ((ipst_s & 0xF) << 1) | ((ipre_s & 3) << 6) | 0x21 } }
++
++static struct dds_init {
++ uint8_t reg_vals[NUM_DDS_REGS];
++} dds_init_vals[] = {
++ /* DDR(FDR) SDR(HDR) */
++ /* Vendor recommends below for 3m cable */
++#define DDS_3M 0
++ DDS_VAL(31, 19, 12, 0, 29, 22, 9, 0),
++ DDS_VAL(31, 12, 15, 4, 31, 15, 15, 1),
++ DDS_VAL(31, 13, 15, 3, 31, 16, 15, 0),
++ DDS_VAL(31, 14, 15, 2, 31, 17, 14, 0),
++ DDS_VAL(31, 15, 15, 1, 31, 18, 13, 0),
++ DDS_VAL(31, 16, 15, 0, 31, 19, 12, 0),
++ DDS_VAL(31, 17, 14, 0, 31, 20, 11, 0),
++ DDS_VAL(31, 18, 13, 0, 30, 21, 10, 0),
++ DDS_VAL(31, 20, 11, 0, 28, 23, 8, 0),
++ DDS_VAL(31, 21, 10, 0, 27, 24, 7, 0),
++ DDS_VAL(31, 22, 9, 0, 26, 25, 6, 0),
++ DDS_VAL(30, 23, 8, 0, 25, 26, 5, 0),
++ DDS_VAL(29, 24, 7, 0, 23, 27, 4, 0),
++ /* Vendor recommends below for 1m cable */
++#define DDS_1M 13
++ DDS_VAL(28, 25, 6, 0, 21, 28, 3, 0),
++ DDS_VAL(27, 26, 5, 0, 19, 29, 2, 0),
++ DDS_VAL(25, 27, 4, 0, 17, 30, 1, 0)
++};
++
++/*
++ * Next, values related to Receive Equalization.
++ * In comments, FDR (Full) is IB DDR, HDR (Half) is IB SDR
++ */
++/* Hardware packs an element number and register address thus: */
++#define RXEQ_INIT_RDESC(elt, addr) (((elt) & 0xF) | ((addr) << 4))
++#define RXEQ_VAL(elt, adr, val0, val1, val2, val3) \
++ {RXEQ_INIT_RDESC((elt), (adr)), {(val0), (val1), (val2), (val3)} }
++
++#define RXEQ_VAL_ALL(elt, adr, val) \
++ {RXEQ_INIT_RDESC((elt), (adr)), {(val), (val), (val), (val)} }
++
++#define RXEQ_SDR_DFELTH 0
++#define RXEQ_SDR_TLTH 0
++#define RXEQ_SDR_G1CNT_Z1CNT 0x11
++#define RXEQ_SDR_ZCNT 23
++
++static struct rxeq_init {
++ u16 rdesc; /* in form used in SerDesDDSRXEQ */
++ u8 rdata[4];
++} rxeq_init_vals[] = {
++ /* Set Rcv Eq. to Preset node */
++ RXEQ_VAL_ALL(7, 0x27, 0x10),
++ /* Set DFELTHFDR/HDR thresholds */
++ RXEQ_VAL(7, 8, 0, 0, 0, 0), /* FDR */
++ RXEQ_VAL(7, 0x21, 0, 0, 0, 0), /* HDR */
++ /* Set TLTHFDR/HDR theshold */
++ RXEQ_VAL(7, 9, 2, 2, 2, 2), /* FDR */
++ RXEQ_VAL(7, 0x23, 2, 2, 2, 2), /* HDR */
++ /* Set Preamp setting 2 (ZFR/ZCNT) */
++ RXEQ_VAL(7, 0x1B, 12, 12, 12, 12), /* FDR */
++ RXEQ_VAL(7, 0x1C, 12, 12, 12, 12), /* HDR */
++ /* Set Preamp DC gain and Setting 1 (GFR/GHR) */
++ RXEQ_VAL(7, 0x1E, 0x10, 0x10, 0x10, 0x10), /* FDR */
++ RXEQ_VAL(7, 0x1F, 0x10, 0x10, 0x10, 0x10), /* HDR */
++ /* Toggle RELOCK (in VCDL_CTRL0) to lock to data */
++ RXEQ_VAL_ALL(6, 6, 0x20), /* Set D5 High */
++ RXEQ_VAL_ALL(6, 6, 0), /* Set D5 Low */
++};
++
++/* There are 17 values from vendor, but IBC only accesses the first 16 */
++#define DDS_ROWS (16)
++#define RXEQ_ROWS ARRAY_SIZE(rxeq_init_vals)
++
++static int ipath_sd_setvals(struct ipath_devdata *dd)
++{
++ int idx, midx;
++ int min_idx; /* Minimum index for this portion of table */
++ uint32_t dds_reg_map;
++ u64 __iomem *taddr, *iaddr;
++ uint64_t data;
++ uint64_t sdctl;
++
++ taddr = dd->ipath_kregbase + KR_IBSerDesMappTable;
++ iaddr = dd->ipath_kregbase + dd->ipath_kregs->kr_ib_ddsrxeq;
++
++ /*
++ * Init the DDS section of the table.
++ * Each "row" of the table provokes NUM_DDS_REG writes, to the
++ * registers indicated in DDS_REG_MAP.
++ */
++ sdctl = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibserdesctrl);
++ sdctl = (sdctl & ~(0x1f << 8)) | (NUM_DDS_REGS << 8);
++ sdctl = (sdctl & ~(0x1f << 13)) | (RXEQ_ROWS << 13);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_ibserdesctrl, sdctl);
++
++ /*
++ * Iterate down table within loop for each register to store.
++ */
++ dds_reg_map = DDS_REG_MAP;
++ for (idx = 0; idx < NUM_DDS_REGS; ++idx) {
++ data = ((dds_reg_map & 0xF) << 4) | TX_FAST_ELT;
++ writeq(data, iaddr + idx);
++ mmiowb();
++ ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++ dds_reg_map >>= 4;
++ for (midx = 0; midx < DDS_ROWS; ++midx) {
++ u64 __iomem *daddr = taddr + ((midx << 4) + idx);
++ data = dds_init_vals[midx].reg_vals[idx];
++ writeq(data, daddr);
++ mmiowb();
++ ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++ } /* End inner for (vals for this reg, each row) */
++ } /* end outer for (regs to be stored) */
++
++ /*
++ * Init the RXEQ section of the table. As explained above the table
++ * rxeq_init_vals[], this runs in a different order, as the pattern
++ * of register references is more complex, but there are only
++ * four "data" values per register.
++ */
++ min_idx = idx; /* RXEQ indices pick up where DDS left off */
++ taddr += 0x100; /* RXEQ data is in second half of table */
++ /* Iterate through RXEQ register addresses */
++ for (idx = 0; idx < RXEQ_ROWS; ++idx) {
++ int didx; /* "destination" */
++ int vidx;
++
++ /* didx is offset by min_idx to address RXEQ range of regs */
++ didx = idx + min_idx;
++ /* Store the next RXEQ register address */
++ writeq(rxeq_init_vals[idx].rdesc, iaddr + didx);
++ mmiowb();
++ ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++ /* Iterate through RXEQ values */
++ for (vidx = 0; vidx < 4; vidx++) {
++ data = rxeq_init_vals[idx].rdata[vidx];
++ writeq(data, taddr + (vidx << 6) + idx);
++ mmiowb();
++ ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++ }
++ } /* end outer for (Reg-writes for RXEQ) */
++ return 0;
++}
++
++#define CMUCTRL5 EPB_LOC(7, 0, 0x15)
++#define RXHSCTRL0(chan) EPB_LOC(chan, 6, 0)
++#define VCDL_DAC2(chan) EPB_LOC(chan, 6, 5)
++#define VCDL_CTRL0(chan) EPB_LOC(chan, 6, 6)
++#define VCDL_CTRL2(chan) EPB_LOC(chan, 6, 8)
++#define START_EQ2(chan) EPB_LOC(chan, 7, 0x28)
++
++static int ibsd_sto_noisy(struct ipath_devdata *dd, int loc, int val, int mask)
++{
++ int ret = -1;
++ int sloc; /* shifted loc, for messages */
++
++ loc |= (1U << EPB_IB_QUAD0_CS_SHF);
++ sloc = loc >> EPB_ADDR_SHF;
++
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, loc, val, mask);
++ if (ret < 0)
++ ipath_dev_err(dd, "Write failed: elt %d,"
++ " addr 0x%X, chnl %d, val 0x%02X, mask 0x%02X\n",
++ (sloc & 0xF), (sloc >> 9) & 0x3f, (sloc >> 4) & 7,
++ val & 0xFF, mask & 0xFF);
++ return ret;
++}
++
++/*
++ * Repeat a "store" across all channels of the IB SerDes.
++ * Although nominally it inherits the "read value" of the last
++ * channel it modified, the only really useful return is <0 for
++ * failure, >= 0 for success. The parameter 'loc' is assumed to
++ * be the location for the channel-0 copy of the register to
++ * be modified.
++ */
++static int ibsd_mod_allchnls(struct ipath_devdata *dd, int loc, int val,
++ int mask)
++{
++ int ret = -1;
++ int chnl;
++
++ if (loc & EPB_GLOBAL_WR) {
++ /*
++ * Our caller has assured us that we can set all four
++ * channels at once. Trust that. If mask is not 0xFF,
++ * we will read the _specified_ channel for our starting
++ * value.
++ */
++ loc |= (1U << EPB_IB_QUAD0_CS_SHF);
++ chnl = (loc >> (4 + EPB_ADDR_SHF)) & 7;
++ if (mask != 0xFF) {
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES,
++ loc & ~EPB_GLOBAL_WR, 0, 0);
++ if (ret < 0) {
++ int sloc = loc >> EPB_ADDR_SHF;
++ ipath_dev_err(dd, "pre-read failed: elt %d,"
++ " addr 0x%X, chnl %d\n", (sloc & 0xF),
++ (sloc >> 9) & 0x3f, chnl);
++ return ret;
++ }
++ val = (ret & ~mask) | (val & mask);
++ }
++ loc &= ~(7 << (4+EPB_ADDR_SHF));
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, loc, val, 0xFF);
++ if (ret < 0) {
++ int sloc = loc >> EPB_ADDR_SHF;
++ ipath_dev_err(dd, "Global WR failed: elt %d,"
++ " addr 0x%X, val %02X\n",
++ (sloc & 0xF), (sloc >> 9) & 0x3f, val);
++ }
++ return ret;
++ }
++ /* Clear "channel" and set CS so we can simply iterate */
++ loc &= ~(7 << (4+EPB_ADDR_SHF));
++ loc |= (1U << EPB_IB_QUAD0_CS_SHF);
++ for (chnl = 0; chnl < 4; ++chnl) {
++ int cloc;
++ cloc = loc | (chnl << (4+EPB_ADDR_SHF));
++ ret = ipath_sd7220_reg_mod(dd, IB_7220_SERDES, cloc, val, mask);
++ if (ret < 0) {
++ int sloc = loc >> EPB_ADDR_SHF;
++ ipath_dev_err(dd, "Write failed: elt %d,"
++ " addr 0x%X, chnl %d, val 0x%02X,"
++ " mask 0x%02X\n",
++ (sloc & 0xF), (sloc >> 9) & 0x3f, chnl,
++ val & 0xFF, mask & 0xFF);
++ break;
++ }
++ }
++ return ret;
++}
++
++/*
++ * Set the Tx values normally modified by IBC in IB1.2 mode to default
++ * values, as gotten from first row of init table.
++ */
++static int set_dds_vals(struct ipath_devdata *dd, struct dds_init *ddi)
++{
++ int ret;
++ int idx, reg, data;
++ uint32_t regmap;
++
++ regmap = DDS_REG_MAP;
++ for (idx = 0; idx < NUM_DDS_REGS; ++idx) {
++ reg = (regmap & 0xF);
++ regmap >>= 4;
++ data = ddi->reg_vals[idx];
++ /* Vendor says RMW not needed for these regs, use 0xFF mask */
++ ret = ibsd_mod_allchnls(dd, EPB_LOC(0, 9, reg), data, 0xFF);
++ if (ret < 0)
++ break;
++ }
++ return ret;
++}
++
++/*
++ * Set the Rx values normally modified by IBC in IB1.2 mode to default
++ * values, as gotten from selected column of init table.
++ */
++static int set_rxeq_vals(struct ipath_devdata *dd, int vsel)
++{
++ int ret;
++ int ridx;
++ int cnt = ARRAY_SIZE(rxeq_init_vals);
++
++ for (ridx = 0; ridx < cnt; ++ridx) {
++ int elt, reg, val, loc;
++ elt = rxeq_init_vals[ridx].rdesc & 0xF;
++ reg = rxeq_init_vals[ridx].rdesc >> 4;
++ loc = EPB_LOC(0, elt, reg);
++ val = rxeq_init_vals[ridx].rdata[vsel];
++ /* mask of 0xFF, because hardware does full-byte store. */
++ ret = ibsd_mod_allchnls(dd, loc, val, 0xFF);
++ if (ret < 0)
++ break;
++ }
++ return ret;
++}
++
++/*
++ * Set the default values (row 0) for DDR Driver Demphasis.
++ * we do this initially and whenever we turn off IB-1.2
++ * The "default" values for Rx equalization are also stored to
++ * SerDes registers. Formerly (and still default), we used set 2.
++ * For experimenting with cables and link-partners, we allow changing
++ * that via a module parameter.
++ */
++static unsigned ipath_rxeq_set = 2;
++module_param_named(rxeq_default_set, ipath_rxeq_set, uint,
++ S_IWUSR | S_IRUGO);
++MODULE_PARM_DESC(rxeq_default_set,
++ "Which set [0..3] of Rx Equalization values is default");
++
++static int ipath_internal_presets(struct ipath_devdata *dd)
++{
++ int ret = 0;
++
++ ret = set_dds_vals(dd, dds_init_vals + DDS_3M);
++
++ if (ret < 0)
++ ipath_dev_err(dd, "Failed to set default DDS values\n");
++ ret = set_rxeq_vals(dd, ipath_rxeq_set & 3);
++ if (ret < 0)
++ ipath_dev_err(dd, "Failed to set default RXEQ values\n");
++ return ret;
++}
++
++int ipath_sd7220_presets(struct ipath_devdata *dd)
++{
++ int ret = 0;
++
++ if (!dd->ipath_presets_needed)
++ return ret;
++ dd->ipath_presets_needed = 0;
++ /* Assert uC reset, so we don't clash with it. */
++ ipath_ibsd_reset(dd, 1);
++ udelay(2);
++ ipath_sd_trimdone_monitor(dd, "link-down");
++
++ ret = ipath_internal_presets(dd);
++return ret;
++}
++
++static int ipath_sd_trimself(struct ipath_devdata *dd, int val)
++{
++ return ibsd_sto_noisy(dd, CMUCTRL5, val, 0xFF);
++}
++
++static int ipath_sd_early(struct ipath_devdata *dd)
++{
++ int ret = -1; /* Default failed */
++ int chnl;
++
++ for (chnl = 0; chnl < 4; ++chnl) {
++ ret = ibsd_sto_noisy(dd, RXHSCTRL0(chnl), 0xD4, 0xFF);
++ if (ret < 0)
++ goto bail;
++ }
++ for (chnl = 0; chnl < 4; ++chnl) {
++ ret = ibsd_sto_noisy(dd, VCDL_DAC2(chnl), 0x2D, 0xFF);
++ if (ret < 0)
++ goto bail;
++ }
++ /* more fine-tuning of what will be default */
++ for (chnl = 0; chnl < 4; ++chnl) {
++ ret = ibsd_sto_noisy(dd, VCDL_CTRL2(chnl), 3, 0xF);
++ if (ret < 0)
++ goto bail;
++ }
++ for (chnl = 0; chnl < 4; ++chnl) {
++ ret = ibsd_sto_noisy(dd, START_EQ1(chnl), 0x10, 0xFF);
++ if (ret < 0)
++ goto bail;
++ }
++ for (chnl = 0; chnl < 4; ++chnl) {
++ ret = ibsd_sto_noisy(dd, START_EQ2(chnl), 0x30, 0xFF);
++ if (ret < 0)
++ goto bail;
++ }
++bail:
++ return ret;
++}
++
++#define BACTRL(chnl) EPB_LOC(chnl, 6, 0x0E)
++#define LDOUTCTRL1(chnl) EPB_LOC(chnl, 7, 6)
++#define RXHSSTATUS(chnl) EPB_LOC(chnl, 6, 0xF)
++
++static int ipath_sd_dactrim(struct ipath_devdata *dd)
++{
++ int ret = -1; /* Default failed */
++ int chnl;
++
++ for (chnl = 0; chnl < 4; ++chnl) {
++ ret = ibsd_sto_noisy(dd, BACTRL(chnl), 0x40, 0xFF);
++ if (ret < 0)
++ goto bail;
++ }
++ for (chnl = 0; chnl < 4; ++chnl) {
++ ret = ibsd_sto_noisy(dd, LDOUTCTRL1(chnl), 0x04, 0xFF);
++ if (ret < 0)
++ goto bail;
++ }
++ for (chnl = 0; chnl < 4; ++chnl) {
++ ret = ibsd_sto_noisy(dd, RXHSSTATUS(chnl), 0x04, 0xFF);
++ if (ret < 0)
++ goto bail;
++ }
++ /*
++ * delay for max possible number of steps, with slop.
++ * Each step is about 4usec.
++ */
++ udelay(415);
++ for (chnl = 0; chnl < 4; ++chnl) {
++ ret = ibsd_sto_noisy(dd, LDOUTCTRL1(chnl), 0x00, 0xFF);
++ if (ret < 0)
++ goto bail;
++ }
++bail:
++ return ret;
++}
++
++#define RELOCK_FIRST_MS 3
++#define RXLSPPM(chan) EPB_LOC(chan, 0, 2)
++void ipath_toggle_rclkrls(struct ipath_devdata *dd)
++{
++ int loc = RXLSPPM(0) | EPB_GLOBAL_WR;
++ int ret;
++
++ ret = ibsd_mod_allchnls(dd, loc, 0, 0x80);
++ if (ret < 0)
++ ipath_dev_err(dd, "RCLKRLS failed to clear D7\n");
++ else {
++ udelay(1);
++ ibsd_mod_allchnls(dd, loc, 0x80, 0x80);
++ }
++ /* And again for good measure */
++ udelay(1);
++ ret = ibsd_mod_allchnls(dd, loc, 0, 0x80);
++ if (ret < 0)
++ ipath_dev_err(dd, "RCLKRLS failed to clear D7\n");
++ else {
++ udelay(1);
++ ibsd_mod_allchnls(dd, loc, 0x80, 0x80);
++ }
++ /* Now reset xgxs and IBC to complete the recovery */
++ dd->ipath_f_xgxs_reset(dd);
++}
++
++/*
++ * Shut down the timer that polls for relock occasions, if needed
++ * this is "hooked" from ipath_7220_quiet_serdes(), which is called
++ * just before ipath_shutdown_device() in ipath_driver.c shuts down all
++ * the other timers
++ */
++void ipath_shutdown_relock_poll(struct ipath_devdata *dd)
++{
++ struct ipath_relock *irp = &dd->ipath_relock_singleton;
++ if (atomic_read(&irp->ipath_relock_timer_active)) {
++ del_timer_sync(&irp->ipath_relock_timer);
++ atomic_set(&irp->ipath_relock_timer_active, 0);
++ }
++}
++
++static unsigned ipath_relock_by_timer = 1;
++module_param_named(relock_by_timer, ipath_relock_by_timer, uint,
++ S_IWUSR | S_IRUGO);
++MODULE_PARM_DESC(relock_by_timer, "Allow relock attempt if link not up");
++
++static void ipath_run_relock(unsigned long opaque)
++{
++ struct ipath_devdata *dd = (struct ipath_devdata *)opaque;
++ struct ipath_relock *irp = &dd->ipath_relock_singleton;
++ u64 val, ltstate;
++
++ if (!(dd->ipath_flags & IPATH_INITTED)) {
++ /* Not yet up, just reenable the timer for later */
++ irp->ipath_relock_interval = HZ;
++ mod_timer(&irp->ipath_relock_timer, jiffies + HZ);
++ return;
++ }
++
++ /*
++ * Check link-training state for "stuck" state.
++ * if found, try relock and schedule another try at
++ * exponentially growing delay, maxed at one second.
++ * if not stuck, our work is done.
++ */
++ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
++ ltstate = ipath_ib_linktrstate(dd, val);
++
++ if (ltstate <= INFINIPATH_IBCS_LT_STATE_CFGWAITRMT
++ && ltstate != INFINIPATH_IBCS_LT_STATE_LINKUP) {
++ int timeoff;
++ /* Not up yet. Try again, if allowed by module-param */
++ if (ipath_relock_by_timer) {
++ if (dd->ipath_flags & IPATH_IB_AUTONEG_INPROG)
++ ipath_cdbg(VERBOSE, "Skip RELOCK in AUTONEG\n");
++ else if (!(dd->ipath_flags & IPATH_IB_LINK_DISABLED)) {
++ ipath_cdbg(VERBOSE, "RELOCK\n");
++ ipath_toggle_rclkrls(dd);
++ }
++ }
++ /* re-set timer for next check */
++ timeoff = irp->ipath_relock_interval << 1;
++ if (timeoff > HZ)
++ timeoff = HZ;
++ irp->ipath_relock_interval = timeoff;
++
++ mod_timer(&irp->ipath_relock_timer, jiffies + timeoff);
++ } else {
++ /* Up, so no more need to check so often */
++ mod_timer(&irp->ipath_relock_timer, jiffies + HZ);
++ }
++}
++
++void ipath_set_relock_poll(struct ipath_devdata *dd, int ibup)
++{
++ struct ipath_relock *irp = &dd->ipath_relock_singleton;
++
++ if (ibup > 0) {
++ /* we are now up, so relax timer to 1 second interval */
++ if (atomic_read(&irp->ipath_relock_timer_active))
++ mod_timer(&irp->ipath_relock_timer, jiffies + HZ);
++ } else {
++ /* Transition to down, (re-)set timer to short interval. */
++ int timeout;
++ timeout = (HZ * ((ibup == -1) ? 1000 : RELOCK_FIRST_MS))/1000;
++ if (timeout == 0)
++ timeout = 1;
++ /* If timer has not yet been started, do so. */
++ if (atomic_inc_return(&irp->ipath_relock_timer_active) == 1) {
++ init_timer(&irp->ipath_relock_timer);
++ irp->ipath_relock_timer.function = ipath_run_relock;
++ irp->ipath_relock_timer.data = (unsigned long) dd;
++ irp->ipath_relock_interval = timeout;
++ irp->ipath_relock_timer.expires = jiffies + timeout;
++ add_timer(&irp->ipath_relock_timer);
++ } else {
++ irp->ipath_relock_interval = timeout;
++ mod_timer(&irp->ipath_relock_timer, jiffies + timeout);
++ atomic_dec(&irp->ipath_relock_timer_active);
++ }
++ }
++}
++
+diff --git a/drivers/infiniband/hw/ipath/ipath_sd7220_img.c b/drivers/infiniband/hw/ipath/ipath_sd7220_img.c
+new file mode 100644
+index 0000000..5ef59da
+--- /dev/null
++++ b/drivers/infiniband/hw/ipath/ipath_sd7220_img.c
+@@ -0,0 +1,1082 @@
++/*
++ * Copyright (c) 2007, 2008 QLogic Corporation. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses. You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ * Redistribution and use in source and binary forms, with or
++ * without modification, are permitted provided that the following
++ * conditions are met:
++ *
++ * - Redistributions of source code must retain the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer.
++ *
++ * - Redistributions in binary form must reproduce the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer in the documentation and/or other materials
++ * provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++/*
++ * This file contains the memory image from the vendor, to be copied into
++ * the IB SERDES of the IBA7220 during initialization.
++ * The file also includes the two functions which use this image.
++ */
++#include <linux/pci.h>
++#include <linux/delay.h>
++
++#include "ipath_kernel.h"
++#include "ipath_registers.h"
++#include "ipath_7220.h"
++
++static unsigned char ipath_sd7220_ib_img[] = {
++/*0000*/0x02, 0x0A, 0x29, 0x02, 0x0A, 0x87, 0xE5, 0xE6,
++ 0x30, 0xE6, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F,
++/*0010*/0x00, 0xE5, 0xE2, 0x30, 0xE4, 0x04, 0x7E, 0x01,
++ 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x5F, 0x60, 0x08,
++/*0020*/0x53, 0xF9, 0xF7, 0xE4, 0xF5, 0xFE, 0x80, 0x08,
++ 0x7F, 0x0A, 0x12, 0x17, 0x31, 0x12, 0x0E, 0xA2,
++/*0030*/0x75, 0xFC, 0x08, 0xE4, 0xF5, 0xFD, 0xE5, 0xE7,
++ 0x20, 0xE7, 0x03, 0x43, 0xF9, 0x08, 0x22, 0x00,
++/*0040*/0x01, 0x20, 0x11, 0x00, 0x04, 0x20, 0x00, 0x75,
++ 0x51, 0x01, 0xE4, 0xF5, 0x52, 0xF5, 0x53, 0xF5,
++/*0050*/0x52, 0xF5, 0x7E, 0x7F, 0x04, 0x02, 0x04, 0x38,
++ 0xC2, 0x36, 0x05, 0x52, 0xE5, 0x52, 0xD3, 0x94,
++/*0060*/0x0C, 0x40, 0x05, 0x75, 0x52, 0x01, 0xD2, 0x36,
++ 0x90, 0x07, 0x0C, 0x74, 0x07, 0xF0, 0xA3, 0x74,
++/*0070*/0xFF, 0xF0, 0xE4, 0xF5, 0x0C, 0xA3, 0xF0, 0x90,
++ 0x07, 0x14, 0xF0, 0xA3, 0xF0, 0x75, 0x0B, 0x20,
++/*0080*/0xF5, 0x09, 0xE4, 0xF5, 0x08, 0xE5, 0x08, 0xD3,
++ 0x94, 0x30, 0x40, 0x03, 0x02, 0x04, 0x04, 0x12,
++/*0090*/0x00, 0x06, 0x15, 0x0B, 0xE5, 0x08, 0x70, 0x04,
++ 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x09,
++/*00A0*/0x70, 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00,
++ 0xEE, 0x5F, 0x60, 0x05, 0x12, 0x18, 0x71, 0xD2,
++/*00B0*/0x35, 0x53, 0xE1, 0xF7, 0xE5, 0x08, 0x45, 0x09,
++ 0xFF, 0xE5, 0x0B, 0x25, 0xE0, 0x25, 0xE0, 0x24,
++/*00C0*/0x83, 0xF5, 0x82, 0xE4, 0x34, 0x07, 0xF5, 0x83,
++ 0xEF, 0xF0, 0x85, 0xE2, 0x20, 0xE5, 0x52, 0xD3,
++/*00D0*/0x94, 0x01, 0x40, 0x0D, 0x12, 0x19, 0xF3, 0xE0,
++ 0x54, 0xA0, 0x64, 0x40, 0x70, 0x03, 0x02, 0x03,
++/*00E0*/0xFB, 0x53, 0xF9, 0xF8, 0x90, 0x94, 0x70, 0xE4,
++ 0xF0, 0xE0, 0xF5, 0x10, 0xAF, 0x09, 0x12, 0x1E,
++/*00F0*/0xB3, 0xAF, 0x08, 0xEF, 0x44, 0x08, 0xF5, 0x82,
++ 0x75, 0x83, 0x80, 0xE0, 0xF5, 0x29, 0xEF, 0x44,
++/*0100*/0x07, 0x12, 0x1A, 0x3C, 0xF5, 0x22, 0x54, 0x40,
++ 0xD3, 0x94, 0x00, 0x40, 0x1E, 0xE5, 0x29, 0x54,
++/*0110*/0xF0, 0x70, 0x21, 0x12, 0x19, 0xF3, 0xE0, 0x44,
++ 0x80, 0xF0, 0xE5, 0x22, 0x54, 0x30, 0x65, 0x08,
++/*0120*/0x70, 0x09, 0x12, 0x19, 0xF3, 0xE0, 0x54, 0xBF,
++ 0xF0, 0x80, 0x09, 0x12, 0x19, 0xF3, 0x74, 0x40,
++/*0130*/0xF0, 0x02, 0x03, 0xFB, 0x12, 0x1A, 0x12, 0x75,
++ 0x83, 0xAE, 0x74, 0xFF, 0xF0, 0xAF, 0x08, 0x7E,
++/*0140*/0x00, 0xEF, 0x44, 0x07, 0xF5, 0x82, 0xE0, 0xFD,
++ 0xE5, 0x0B, 0x25, 0xE0, 0x25, 0xE0, 0x24, 0x81,
++/*0150*/0xF5, 0x82, 0xE4, 0x34, 0x07, 0xF5, 0x83, 0xED,
++ 0xF0, 0x90, 0x07, 0x0E, 0xE0, 0x04, 0xF0, 0xEF,
++/*0160*/0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0x98, 0xE0,
++ 0xF5, 0x28, 0x12, 0x1A, 0x23, 0x40, 0x0C, 0x12,
++/*0170*/0x19, 0xF3, 0xE0, 0x44, 0x01, 0x12, 0x1A, 0x32,
++ 0x02, 0x03, 0xF6, 0xAF, 0x08, 0x7E, 0x00, 0x74,
++/*0180*/0x80, 0xCD, 0xEF, 0xCD, 0x8D, 0x82, 0xF5, 0x83,
++ 0xE0, 0x30, 0xE0, 0x0A, 0x12, 0x19, 0xF3, 0xE0,
++/*0190*/0x44, 0x20, 0xF0, 0x02, 0x03, 0xFB, 0x12, 0x19,
++ 0xF3, 0xE0, 0x54, 0xDF, 0xF0, 0xEE, 0x44, 0xAE,
++/*01A0*/0x12, 0x1A, 0x43, 0x30, 0xE4, 0x03, 0x02, 0x03,
++ 0xFB, 0x74, 0x9E, 0x12, 0x1A, 0x05, 0x20, 0xE0,
++/*01B0*/0x03, 0x02, 0x03, 0xFB, 0x8F, 0x82, 0x8E, 0x83,
++ 0xE0, 0x20, 0xE0, 0x03, 0x02, 0x03, 0xFB, 0x12,
++/*01C0*/0x19, 0xF3, 0xE0, 0x44, 0x10, 0xF0, 0xE5, 0xE3,
++ 0x20, 0xE7, 0x08, 0xE5, 0x08, 0x12, 0x1A, 0x3A,
++/*01D0*/0x44, 0x04, 0xF0, 0xAF, 0x08, 0x7E, 0x00, 0xEF,
++ 0x12, 0x1A, 0x3A, 0x20, 0xE2, 0x34, 0x12, 0x19,
++/*01E0*/0xF3, 0xE0, 0x44, 0x08, 0xF0, 0xE5, 0xE4, 0x30,
++ 0xE6, 0x04, 0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00,
++/*01F0*/0xE5, 0x7E, 0xC3, 0x94, 0x04, 0x50, 0x04, 0x7C,
++ 0x01, 0x80, 0x02, 0x7C, 0x00, 0xEC, 0x4D, 0x60,
++/*0200*/0x05, 0xC2, 0x35, 0x02, 0x03, 0xFB, 0xEE, 0x44,
++ 0xD2, 0x12, 0x1A, 0x43, 0x44, 0x40, 0xF0, 0x02,
++/*0210*/0x03, 0xFB, 0x12, 0x19, 0xF3, 0xE0, 0x54, 0xF7,
++ 0xF0, 0x12, 0x1A, 0x12, 0x75, 0x83, 0xD2, 0xE0,
++/*0220*/0x54, 0xBF, 0xF0, 0x90, 0x07, 0x14, 0xE0, 0x04,
++ 0xF0, 0xE5, 0x7E, 0x70, 0x03, 0x75, 0x7E, 0x01,
++/*0230*/0xAF, 0x08, 0x7E, 0x00, 0x12, 0x1A, 0x23, 0x40,
++ 0x12, 0x12, 0x19, 0xF3, 0xE0, 0x44, 0x01, 0x12,
++/*0240*/0x19, 0xF2, 0xE0, 0x54, 0x02, 0x12, 0x1A, 0x32,
++ 0x02, 0x03, 0xFB, 0x12, 0x19, 0xF3, 0xE0, 0x44,
++/*0250*/0x02, 0x12, 0x19, 0xF2, 0xE0, 0x54, 0xFE, 0xF0,
++ 0xC2, 0x35, 0xEE, 0x44, 0x8A, 0x8F, 0x82, 0xF5,
++/*0260*/0x83, 0xE0, 0xF5, 0x17, 0x54, 0x8F, 0x44, 0x40,
++ 0xF0, 0x74, 0x90, 0xFC, 0xE5, 0x08, 0x44, 0x07,
++/*0270*/0xFD, 0xF5, 0x82, 0x8C, 0x83, 0xE0, 0x54, 0x3F,
++ 0x90, 0x07, 0x02, 0xF0, 0xE0, 0x54, 0xC0, 0x8D,
++/*0280*/0x82, 0x8C, 0x83, 0xF0, 0x74, 0x92, 0x12, 0x1A,
++ 0x05, 0x90, 0x07, 0x03, 0x12, 0x1A, 0x19, 0x74,
++/*0290*/0x82, 0x12, 0x1A, 0x05, 0x90, 0x07, 0x04, 0x12,
++ 0x1A, 0x19, 0x74, 0xB4, 0x12, 0x1A, 0x05, 0x90,
++/*02A0*/0x07, 0x05, 0x12, 0x1A, 0x19, 0x74, 0x94, 0xFE,
++ 0xE5, 0x08, 0x44, 0x06, 0x12, 0x1A, 0x0A, 0xF5,
++/*02B0*/0x10, 0x30, 0xE0, 0x04, 0xD2, 0x37, 0x80, 0x02,
++ 0xC2, 0x37, 0xE5, 0x10, 0x54, 0x7F, 0x8F, 0x82,
++/*02C0*/0x8E, 0x83, 0xF0, 0x30, 0x44, 0x30, 0x12, 0x1A,
++ 0x03, 0x54, 0x80, 0xD3, 0x94, 0x00, 0x40, 0x04,
++/*02D0*/0xD2, 0x39, 0x80, 0x02, 0xC2, 0x39, 0x8F, 0x82,
++ 0x8E, 0x83, 0xE0, 0x44, 0x80, 0xF0, 0x12, 0x1A,
++/*02E0*/0x03, 0x54, 0x40, 0xD3, 0x94, 0x00, 0x40, 0x04,
++ 0xD2, 0x3A, 0x80, 0x02, 0xC2, 0x3A, 0x8F, 0x82,
++/*02F0*/0x8E, 0x83, 0xE0, 0x44, 0x40, 0xF0, 0x74, 0x92,
++ 0xFE, 0xE5, 0x08, 0x44, 0x06, 0x12, 0x1A, 0x0A,
++/*0300*/0x30, 0xE7, 0x04, 0xD2, 0x38, 0x80, 0x02, 0xC2,
++ 0x38, 0x8F, 0x82, 0x8E, 0x83, 0xE0, 0x54, 0x7F,
++/*0310*/0xF0, 0x12, 0x1E, 0x46, 0xE4, 0xF5, 0x0A, 0x20,
++ 0x03, 0x02, 0x80, 0x03, 0x30, 0x43, 0x03, 0x12,
++/*0320*/0x19, 0x95, 0x20, 0x02, 0x02, 0x80, 0x03, 0x30,
++ 0x42, 0x03, 0x12, 0x0C, 0x8F, 0x30, 0x30, 0x06,
++/*0330*/0x12, 0x19, 0x95, 0x12, 0x0C, 0x8F, 0x12, 0x0D,
++ 0x47, 0x12, 0x19, 0xF3, 0xE0, 0x54, 0xFB, 0xF0,
++/*0340*/0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x40, 0x46, 0x43,
++ 0xE1, 0x08, 0x12, 0x19, 0xF3, 0xE0, 0x44, 0x04,
++/*0350*/0xF0, 0xE5, 0xE4, 0x20, 0xE7, 0x2A, 0x12, 0x1A,
++ 0x12, 0x75, 0x83, 0xD2, 0xE0, 0x54, 0x08, 0xD3,
++/*0360*/0x94, 0x00, 0x40, 0x04, 0x7F, 0x01, 0x80, 0x02,
++ 0x7F, 0x00, 0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x40,
++/*0370*/0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEF,
++ 0x5E, 0x60, 0x05, 0x12, 0x1D, 0xD7, 0x80, 0x17,
++/*0380*/0x12, 0x1A, 0x12, 0x75, 0x83, 0xD2, 0xE0, 0x44,
++ 0x08, 0xF0, 0x02, 0x03, 0xFB, 0x12, 0x1A, 0x12,
++/*0390*/0x75, 0x83, 0xD2, 0xE0, 0x54, 0xF7, 0xF0, 0x12,
++ 0x1E, 0x46, 0x7F, 0x08, 0x12, 0x17, 0x31, 0x74,
++/*03A0*/0x8E, 0xFE, 0x12, 0x1A, 0x12, 0x8E, 0x83, 0xE0,
++ 0xF5, 0x10, 0x54, 0xFE, 0xF0, 0xE5, 0x10, 0x44,
++/*03B0*/0x01, 0xFF, 0xE5, 0x08, 0xFD, 0xED, 0x44, 0x07,
++ 0xF5, 0x82, 0xEF, 0xF0, 0xE5, 0x10, 0x54, 0xFE,
++/*03C0*/0xFF, 0xED, 0x44, 0x07, 0xF5, 0x82, 0xEF, 0x12,
++ 0x1A, 0x11, 0x75, 0x83, 0x86, 0xE0, 0x44, 0x10,
++/*03D0*/0x12, 0x1A, 0x11, 0xE0, 0x44, 0x10, 0xF0, 0x12,
++ 0x19, 0xF3, 0xE0, 0x54, 0xFD, 0x44, 0x01, 0xFF,
++/*03E0*/0x12, 0x19, 0xF3, 0xEF, 0x12, 0x1A, 0x32, 0x30,
++ 0x32, 0x0C, 0xE5, 0x08, 0x44, 0x08, 0xF5, 0x82,
++/*03F0*/0x75, 0x83, 0x82, 0x74, 0x05, 0xF0, 0xAF, 0x0B,
++ 0x12, 0x18, 0xD7, 0x74, 0x10, 0x25, 0x08, 0xF5,
++/*0400*/0x08, 0x02, 0x00, 0x85, 0x05, 0x09, 0xE5, 0x09,
++ 0xD3, 0x94, 0x07, 0x50, 0x03, 0x02, 0x00, 0x82,
++/*0410*/0xE5, 0x7E, 0xD3, 0x94, 0x00, 0x40, 0x04, 0x7F,
++ 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x7E, 0xC3,
++/*0420*/0x94, 0xFA, 0x50, 0x04, 0x7E, 0x01, 0x80, 0x02,
++ 0x7E, 0x00, 0xEE, 0x5F, 0x60, 0x02, 0x05, 0x7E,
++/*0430*/0x30, 0x35, 0x0B, 0x43, 0xE1, 0x01, 0x7F, 0x09,
++ 0x12, 0x17, 0x31, 0x02, 0x00, 0x58, 0x53, 0xE1,
++/*0440*/0xFE, 0x02, 0x00, 0x58, 0x8E, 0x6A, 0x8F, 0x6B,
++ 0x8C, 0x6C, 0x8D, 0x6D, 0x75, 0x6E, 0x01, 0x75,
++/*0450*/0x6F, 0x01, 0x75, 0x70, 0x01, 0xE4, 0xF5, 0x73,
++ 0xF5, 0x74, 0xF5, 0x75, 0x90, 0x07, 0x2F, 0xF0,
++/*0460*/0xF5, 0x3C, 0xF5, 0x3E, 0xF5, 0x46, 0xF5, 0x47,
++ 0xF5, 0x3D, 0xF5, 0x3F, 0xF5, 0x6F, 0xE5, 0x6F,
++/*0470*/0x70, 0x0F, 0xE5, 0x6B, 0x45, 0x6A, 0x12, 0x07,
++ 0x2A, 0x75, 0x83, 0x80, 0x74, 0x3A, 0xF0, 0x80,
++/*0480*/0x09, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x80, 0x74,
++ 0x1A, 0xF0, 0xE4, 0xF5, 0x6E, 0xC3, 0x74, 0x3F,
++/*0490*/0x95, 0x6E, 0xFF, 0x12, 0x08, 0x65, 0x75, 0x83,
++ 0x82, 0xEF, 0xF0, 0x12, 0x1A, 0x4D, 0x12, 0x08,
++/*04A0*/0xC6, 0xE5, 0x33, 0xF0, 0x12, 0x08, 0xFA, 0x12,
++ 0x08, 0xB1, 0x40, 0xE1, 0xE5, 0x6F, 0x70, 0x0B,
++/*04B0*/0x12, 0x07, 0x2A, 0x75, 0x83, 0x80, 0x74, 0x36,
++ 0xF0, 0x80, 0x09, 0x12, 0x07, 0x2A, 0x75, 0x83,
++/*04C0*/0x80, 0x74, 0x16, 0xF0, 0x75, 0x6E, 0x01, 0x12,
++ 0x07, 0x2A, 0x75, 0x83, 0xB4, 0xE5, 0x6E, 0xF0,
++/*04D0*/0x12, 0x1A, 0x4D, 0x74, 0x3F, 0x25, 0x6E, 0xF5,
++ 0x82, 0xE4, 0x34, 0x00, 0xF5, 0x83, 0xE5, 0x33,
++/*04E0*/0xF0, 0x74, 0xBF, 0x25, 0x6E, 0xF5, 0x82, 0xE4,
++ 0x34, 0x00, 0x12, 0x08, 0xB1, 0x40, 0xD8, 0xE4,
++/*04F0*/0xF5, 0x70, 0xF5, 0x46, 0xF5, 0x47, 0xF5, 0x6E,
++ 0x12, 0x08, 0xFA, 0xF5, 0x83, 0xE0, 0xFE, 0x12,
++/*0500*/0x08, 0xC6, 0xE0, 0x7C, 0x00, 0x24, 0x00, 0xFF,
++ 0xEC, 0x3E, 0xFE, 0xAD, 0x3B, 0xD3, 0xEF, 0x9D,
++/*0510*/0xEE, 0x9C, 0x50, 0x04, 0x7B, 0x01, 0x80, 0x02,
++ 0x7B, 0x00, 0xE5, 0x70, 0x70, 0x04, 0x7A, 0x01,
++/*0520*/0x80, 0x02, 0x7A, 0x00, 0xEB, 0x5A, 0x60, 0x06,
++ 0x85, 0x6E, 0x46, 0x75, 0x70, 0x01, 0xD3, 0xEF,
++/*0530*/0x9D, 0xEE, 0x9C, 0x50, 0x04, 0x7F, 0x01, 0x80,
++ 0x02, 0x7F, 0x00, 0xE5, 0x70, 0xB4, 0x01, 0x04,
++/*0540*/0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEF, 0x5E,
++ 0x60, 0x03, 0x85, 0x6E, 0x47, 0x05, 0x6E, 0xE5,
++/*0550*/0x6E, 0x64, 0x7F, 0x70, 0xA3, 0xE5, 0x46, 0x60,
++ 0x05, 0xE5, 0x47, 0xB4, 0x7E, 0x03, 0x85, 0x46,
++/*0560*/0x47, 0xE5, 0x6F, 0x70, 0x08, 0x85, 0x46, 0x76,
++ 0x85, 0x47, 0x77, 0x80, 0x0E, 0xC3, 0x74, 0x7F,
++/*0570*/0x95, 0x46, 0xF5, 0x78, 0xC3, 0x74, 0x7F, 0x95,
++ 0x47, 0xF5, 0x79, 0xE5, 0x6F, 0x70, 0x37, 0xE5,
++/*0580*/0x46, 0x65, 0x47, 0x70, 0x0C, 0x75, 0x73, 0x01,
++ 0x75, 0x74, 0x01, 0xF5, 0x3C, 0xF5, 0x3D, 0x80,
++/*0590*/0x35, 0xE4, 0xF5, 0x4E, 0xC3, 0xE5, 0x47, 0x95,
++ 0x46, 0xF5, 0x3C, 0xC3, 0x13, 0xF5, 0x71, 0x25,
++/*05A0*/0x46, 0xF5, 0x72, 0xC3, 0x94, 0x3F, 0x40, 0x05,
++ 0xE4, 0xF5, 0x3D, 0x80, 0x40, 0xC3, 0x74, 0x3F,
++/*05B0*/0x95, 0x72, 0xF5, 0x3D, 0x80, 0x37, 0xE5, 0x46,
++ 0x65, 0x47, 0x70, 0x0F, 0x75, 0x73, 0x01, 0x75,
++/*05C0*/0x75, 0x01, 0xF5, 0x3E, 0xF5, 0x3F, 0x75, 0x4E,
++ 0x01, 0x80, 0x22, 0xE4, 0xF5, 0x4E, 0xC3, 0xE5,
++/*05D0*/0x47, 0x95, 0x46, 0xF5, 0x3E, 0xC3, 0x13, 0xF5,
++ 0x71, 0x25, 0x46, 0xF5, 0x72, 0xD3, 0x94, 0x3F,
++/*05E0*/0x50, 0x05, 0xE4, 0xF5, 0x3F, 0x80, 0x06, 0xE5,
++ 0x72, 0x24, 0xC1, 0xF5, 0x3F, 0x05, 0x6F, 0xE5,
++/*05F0*/0x6F, 0xC3, 0x94, 0x02, 0x50, 0x03, 0x02, 0x04,
++ 0x6E, 0xE5, 0x6D, 0x45, 0x6C, 0x70, 0x02, 0x80,
++/*0600*/0x04, 0xE5, 0x74, 0x45, 0x75, 0x90, 0x07, 0x2F,
++ 0xF0, 0x7F, 0x01, 0xE5, 0x3E, 0x60, 0x04, 0xE5,
++/*0610*/0x3C, 0x70, 0x14, 0xE4, 0xF5, 0x3C, 0xF5, 0x3D,
++ 0xF5, 0x3E, 0xF5, 0x3F, 0x12, 0x08, 0xD2, 0x70,
++/*0620*/0x04, 0xF0, 0x02, 0x06, 0xA4, 0x80, 0x7A, 0xE5,
++ 0x3C, 0xC3, 0x95, 0x3E, 0x40, 0x07, 0xE5, 0x3C,
++/*0630*/0x95, 0x3E, 0xFF, 0x80, 0x06, 0xC3, 0xE5, 0x3E,
++ 0x95, 0x3C, 0xFF, 0xE5, 0x76, 0xD3, 0x95, 0x79,
++/*0640*/0x40, 0x05, 0x85, 0x76, 0x7A, 0x80, 0x03, 0x85,
++ 0x79, 0x7A, 0xE5, 0x77, 0xC3, 0x95, 0x78, 0x50,
++/*0650*/0x05, 0x85, 0x77, 0x7B, 0x80, 0x03, 0x85, 0x78,
++ 0x7B, 0xE5, 0x7B, 0xD3, 0x95, 0x7A, 0x40, 0x30,
++/*0660*/0xE5, 0x7B, 0x95, 0x7A, 0xF5, 0x3C, 0xF5, 0x3E,
++ 0xC3, 0xE5, 0x7B, 0x95, 0x7A, 0x90, 0x07, 0x19,
++/*0670*/0xF0, 0xE5, 0x3C, 0xC3, 0x13, 0xF5, 0x71, 0x25,
++ 0x7A, 0xF5, 0x72, 0xC3, 0x94, 0x3F, 0x40, 0x05,
++/*0680*/0xE4, 0xF5, 0x3D, 0x80, 0x1F, 0xC3, 0x74, 0x3F,
++ 0x95, 0x72, 0xF5, 0x3D, 0xF5, 0x3F, 0x80, 0x14,
++/*0690*/0xE4, 0xF5, 0x3C, 0xF5, 0x3E, 0x90, 0x07, 0x19,
++ 0xF0, 0x12, 0x08, 0xD2, 0x70, 0x03, 0xF0, 0x80,
++/*06A0*/0x03, 0x74, 0x01, 0xF0, 0x12, 0x08, 0x65, 0x75,
++ 0x83, 0xD0, 0xE0, 0x54, 0x0F, 0xFE, 0xAD, 0x3C,
++/*06B0*/0x70, 0x02, 0x7E, 0x07, 0xBE, 0x0F, 0x02, 0x7E,
++ 0x80, 0xEE, 0xFB, 0xEF, 0xD3, 0x9B, 0x74, 0x80,
++/*06C0*/0xF8, 0x98, 0x40, 0x1F, 0xE4, 0xF5, 0x3C, 0xF5,
++ 0x3E, 0x12, 0x08, 0xD2, 0x70, 0x03, 0xF0, 0x80,
++/*06D0*/0x12, 0x74, 0x01, 0xF0, 0xE5, 0x08, 0xFB, 0xEB,
++ 0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0xD2, 0xE0,
++/*06E0*/0x44, 0x10, 0xF0, 0xE5, 0x08, 0xFB, 0xEB, 0x44,
++ 0x09, 0xF5, 0x82, 0x75, 0x83, 0x9E, 0xED, 0xF0,
++/*06F0*/0xEB, 0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0xCA,
++ 0xED, 0xF0, 0x12, 0x08, 0x65, 0x75, 0x83, 0xCC,
++/*0700*/0xEF, 0xF0, 0x22, 0xE5, 0x08, 0x44, 0x07, 0xF5,
++ 0x82, 0x75, 0x83, 0xBC, 0xE0, 0x54, 0xF0, 0xF0,
++/*0710*/0xE5, 0x08, 0x44, 0x07, 0xF5, 0x82, 0x75, 0x83,
++ 0xBE, 0xE0, 0x54, 0xF0, 0xF0, 0xE5, 0x08, 0x44,
++/*0720*/0x07, 0xF5, 0x82, 0x75, 0x83, 0xC0, 0xE0, 0x54,
++ 0xF0, 0xF0, 0xE5, 0x08, 0x44, 0x07, 0xF5, 0x82,
++/*0730*/0x22, 0xF0, 0x90, 0x07, 0x28, 0xE0, 0xFE, 0xA3,
++ 0xE0, 0xF5, 0x82, 0x8E, 0x83, 0x22, 0x85, 0x42,
++/*0740*/0x42, 0x85, 0x41, 0x41, 0x85, 0x40, 0x40, 0x74,
++ 0xC0, 0x2F, 0xF5, 0x82, 0x74, 0x02, 0x3E, 0xF5,
++/*0750*/0x83, 0xE5, 0x42, 0xF0, 0x74, 0xE0, 0x2F, 0xF5,
++ 0x82, 0x74, 0x02, 0x3E, 0xF5, 0x83, 0x22, 0xE5,
++/*0760*/0x42, 0x29, 0xFD, 0xE4, 0x33, 0xFC, 0xE5, 0x3C,
++ 0xC3, 0x9D, 0xEC, 0x64, 0x80, 0xF8, 0x74, 0x80,
++/*0770*/0x98, 0x22, 0xF5, 0x83, 0xE0, 0x90, 0x07, 0x22,
++ 0x54, 0x1F, 0xFD, 0xE0, 0xFA, 0xA3, 0xE0, 0xF5,
++/*0780*/0x82, 0x8A, 0x83, 0xED, 0xF0, 0x22, 0x90, 0x07,
++ 0x22, 0xE0, 0xFC, 0xA3, 0xE0, 0xF5, 0x82, 0x8C,
++/*0790*/0x83, 0x22, 0x90, 0x07, 0x24, 0xFF, 0xED, 0x44,
++ 0x07, 0xCF, 0xF0, 0xA3, 0xEF, 0xF0, 0x22, 0x85,
++/*07A0*/0x38, 0x38, 0x85, 0x39, 0x39, 0x85, 0x3A, 0x3A,
++ 0x74, 0xC0, 0x2F, 0xF5, 0x82, 0x74, 0x02, 0x3E,
++/*07B0*/0xF5, 0x83, 0x22, 0x90, 0x07, 0x26, 0xFF, 0xED,
++ 0x44, 0x07, 0xCF, 0xF0, 0xA3, 0xEF, 0xF0, 0x22,
++/*07C0*/0xF0, 0x74, 0xA0, 0x2F, 0xF5, 0x82, 0x74, 0x02,
++ 0x3E, 0xF5, 0x83, 0x22, 0x74, 0xC0, 0x25, 0x11,
++/*07D0*/0xF5, 0x82, 0xE4, 0x34, 0x01, 0xF5, 0x83, 0x22,
++ 0x74, 0x00, 0x25, 0x11, 0xF5, 0x82, 0xE4, 0x34,
++/*07E0*/0x02, 0xF5, 0x83, 0x22, 0x74, 0x60, 0x25, 0x11,
++ 0xF5, 0x82, 0xE4, 0x34, 0x03, 0xF5, 0x83, 0x22,
++/*07F0*/0x74, 0x80, 0x25, 0x11, 0xF5, 0x82, 0xE4, 0x34,
++ 0x03, 0xF5, 0x83, 0x22, 0x74, 0xE0, 0x25, 0x11,
++/*0800*/0xF5, 0x82, 0xE4, 0x34, 0x03, 0xF5, 0x83, 0x22,
++ 0x74, 0x40, 0x25, 0x11, 0xF5, 0x82, 0xE4, 0x34,
++/*0810*/0x06, 0xF5, 0x83, 0x22, 0x74, 0x80, 0x2F, 0xF5,
++ 0x82, 0x74, 0x02, 0x3E, 0xF5, 0x83, 0x22, 0xAF,
++/*0820*/0x08, 0x7E, 0x00, 0xEF, 0x44, 0x07, 0xF5, 0x82,
++ 0x22, 0xF5, 0x83, 0xE5, 0x82, 0x44, 0x07, 0xF5,
++/*0830*/0x82, 0xE5, 0x40, 0xF0, 0x22, 0x74, 0x40, 0x25,
++ 0x11, 0xF5, 0x82, 0xE4, 0x34, 0x02, 0xF5, 0x83,
++/*0840*/0x22, 0x74, 0xC0, 0x25, 0x11, 0xF5, 0x82, 0xE4,
++ 0x34, 0x03, 0xF5, 0x83, 0x22, 0x74, 0x00, 0x25,
++/*0850*/0x11, 0xF5, 0x82, 0xE4, 0x34, 0x06, 0xF5, 0x83,
++ 0x22, 0x74, 0x20, 0x25, 0x11, 0xF5, 0x82, 0xE4,
++/*0860*/0x34, 0x06, 0xF5, 0x83, 0x22, 0xE5, 0x08, 0xFD,
++ 0xED, 0x44, 0x07, 0xF5, 0x82, 0x22, 0xE5, 0x41,
++/*0870*/0xF0, 0xE5, 0x65, 0x64, 0x01, 0x45, 0x64, 0x22,
++ 0x7E, 0x00, 0xFB, 0x7A, 0x00, 0xFD, 0x7C, 0x00,
++/*0880*/0x22, 0x74, 0x20, 0x25, 0x11, 0xF5, 0x82, 0xE4,
++ 0x34, 0x02, 0x22, 0x74, 0xA0, 0x25, 0x11, 0xF5,
++/*0890*/0x82, 0xE4, 0x34, 0x03, 0x22, 0x85, 0x3E, 0x42,
++ 0x85, 0x3F, 0x41, 0x8F, 0x40, 0x22, 0x85, 0x3C,
++/*08A0*/0x42, 0x85, 0x3D, 0x41, 0x8F, 0x40, 0x22, 0x75,
++ 0x45, 0x3F, 0x90, 0x07, 0x20, 0xE4, 0xF0, 0xA3,
++/*08B0*/0x22, 0xF5, 0x83, 0xE5, 0x32, 0xF0, 0x05, 0x6E,
++ 0xE5, 0x6E, 0xC3, 0x94, 0x40, 0x22, 0xF0, 0xE5,
++/*08C0*/0x08, 0x44, 0x06, 0xF5, 0x82, 0x22, 0x74, 0x00,
++ 0x25, 0x6E, 0xF5, 0x82, 0xE4, 0x34, 0x00, 0xF5,
++/*08D0*/0x83, 0x22, 0xE5, 0x6D, 0x45, 0x6C, 0x90, 0x07,
++ 0x2F, 0x22, 0xE4, 0xF9, 0xE5, 0x3C, 0xD3, 0x95,
++/*08E0*/0x3E, 0x22, 0x74, 0x80, 0x2E, 0xF5, 0x82, 0xE4,
++ 0x34, 0x02, 0xF5, 0x83, 0xE0, 0x22, 0x74, 0xA0,
++/*08F0*/0x2E, 0xF5, 0x82, 0xE4, 0x34, 0x02, 0xF5, 0x83,
++ 0xE0, 0x22, 0x74, 0x80, 0x25, 0x6E, 0xF5, 0x82,
++/*0900*/0xE4, 0x34, 0x00, 0x22, 0x25, 0x42, 0xFD, 0xE4,
++ 0x33, 0xFC, 0x22, 0x85, 0x42, 0x42, 0x85, 0x41,
++/*0910*/0x41, 0x85, 0x40, 0x40, 0x22, 0xED, 0x4C, 0x60,
++ 0x03, 0x02, 0x09, 0xE5, 0xEF, 0x4E, 0x70, 0x37,
++/*0920*/0x90, 0x07, 0x26, 0x12, 0x07, 0x89, 0xE0, 0xFD,
++ 0x12, 0x07, 0xCC, 0xED, 0xF0, 0x90, 0x07, 0x28,
++/*0930*/0x12, 0x07, 0x89, 0xE0, 0xFD, 0x12, 0x07, 0xD8,
++ 0xED, 0xF0, 0x12, 0x07, 0x86, 0xE0, 0x54, 0x1F,
++/*0940*/0xFD, 0x12, 0x08, 0x81, 0xF5, 0x83, 0xED, 0xF0,
++ 0x90, 0x07, 0x24, 0x12, 0x07, 0x89, 0xE0, 0x54,
++/*0950*/0x1F, 0xFD, 0x12, 0x08, 0x35, 0xED, 0xF0, 0xEF,
++ 0x64, 0x04, 0x4E, 0x70, 0x37, 0x90, 0x07, 0x26,
++/*0960*/0x12, 0x07, 0x89, 0xE0, 0xFD, 0x12, 0x07, 0xE4,
++ 0xED, 0xF0, 0x90, 0x07, 0x28, 0x12, 0x07, 0x89,
++/*0970*/0xE0, 0xFD, 0x12, 0x07, 0xF0, 0xED, 0xF0, 0x12,
++ 0x07, 0x86, 0xE0, 0x54, 0x1F, 0xFD, 0x12, 0x08,
++/*0980*/0x8B, 0xF5, 0x83, 0xED, 0xF0, 0x90, 0x07, 0x24,
++ 0x12, 0x07, 0x89, 0xE0, 0x54, 0x1F, 0xFD, 0x12,
++/*0990*/0x08, 0x41, 0xED, 0xF0, 0xEF, 0x64, 0x01, 0x4E,
++ 0x70, 0x04, 0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00,
++/*09A0*/0xEF, 0x64, 0x02, 0x4E, 0x70, 0x04, 0x7F, 0x01,
++ 0x80, 0x02, 0x7F, 0x00, 0xEF, 0x4D, 0x60, 0x78,
++/*09B0*/0x90, 0x07, 0x26, 0x12, 0x07, 0x35, 0xE0, 0xFF,
++ 0x12, 0x07, 0xFC, 0xEF, 0x12, 0x07, 0x31, 0xE0,
++/*09C0*/0xFF, 0x12, 0x08, 0x08, 0xEF, 0xF0, 0x90, 0x07,
++ 0x22, 0x12, 0x07, 0x35, 0xE0, 0x54, 0x1F, 0xFF,
++/*09D0*/0x12, 0x08, 0x4D, 0xEF, 0xF0, 0x90, 0x07, 0x24,
++ 0x12, 0x07, 0x35, 0xE0, 0x54, 0x1F, 0xFF, 0x12,
++/*09E0*/0x08, 0x59, 0xEF, 0xF0, 0x22, 0x12, 0x07, 0xCC,
++ 0xE4, 0xF0, 0x12, 0x07, 0xD8, 0xE4, 0xF0, 0x12,
++/*09F0*/0x08, 0x81, 0xF5, 0x83, 0xE4, 0xF0, 0x12, 0x08,
++ 0x35, 0x74, 0x14, 0xF0, 0x12, 0x07, 0xE4, 0xE4,
++/*0A00*/0xF0, 0x12, 0x07, 0xF0, 0xE4, 0xF0, 0x12, 0x08,
++ 0x8B, 0xF5, 0x83, 0xE4, 0xF0, 0x12, 0x08, 0x41,
++/*0A10*/0x74, 0x14, 0xF0, 0x12, 0x07, 0xFC, 0xE4, 0xF0,
++ 0x12, 0x08, 0x08, 0xE4, 0xF0, 0x12, 0x08, 0x4D,
++/*0A20*/0xE4, 0xF0, 0x12, 0x08, 0x59, 0x74, 0x14, 0xF0,
++ 0x22, 0x53, 0xF9, 0xF7, 0x75, 0xFC, 0x10, 0xE4,
++/*0A30*/0xF5, 0xFD, 0x75, 0xFE, 0x30, 0xF5, 0xFF, 0xE5,
++ 0xE7, 0x20, 0xE7, 0x03, 0x43, 0xF9, 0x08, 0xE5,
++/*0A40*/0xE6, 0x20, 0xE7, 0x0B, 0x78, 0xFF, 0xE4, 0xF6,
++ 0xD8, 0xFD, 0x53, 0xE6, 0xFE, 0x80, 0x09, 0x78,
++/*0A50*/0x08, 0xE4, 0xF6, 0xD8, 0xFD, 0x53, 0xE6, 0xFE,
++ 0x75, 0x81, 0x80, 0xE4, 0xF5, 0xA8, 0xD2, 0xA8,
++/*0A60*/0xC2, 0xA9, 0xD2, 0xAF, 0xE5, 0xE2, 0x20, 0xE5,
++ 0x05, 0x20, 0xE6, 0x02, 0x80, 0x03, 0x43, 0xE1,
++/*0A70*/0x02, 0xE5, 0xE2, 0x20, 0xE0, 0x0E, 0x90, 0x00,
++ 0x00, 0x7F, 0x00, 0x7E, 0x08, 0xE4, 0xF0, 0xA3,
++/*0A80*/0xDF, 0xFC, 0xDE, 0xFA, 0x02, 0x0A, 0xDB, 0x43,
++ 0xFA, 0x01, 0xC0, 0xE0, 0xC0, 0xF0, 0xC0, 0x83,
++/*0A90*/0xC0, 0x82, 0xC0, 0xD0, 0x12, 0x1C, 0xE7, 0xD0,
++ 0xD0, 0xD0, 0x82, 0xD0, 0x83, 0xD0, 0xF0, 0xD0,
++/*0AA0*/0xE0, 0x53, 0xFA, 0xFE, 0x32, 0x02, 0x1B, 0x55,
++ 0xE4, 0x93, 0xA3, 0xF8, 0xE4, 0x93, 0xA3, 0xF6,
++/*0AB0*/0x08, 0xDF, 0xF9, 0x80, 0x29, 0xE4, 0x93, 0xA3,
++ 0xF8, 0x54, 0x07, 0x24, 0x0C, 0xC8, 0xC3, 0x33,
++/*0AC0*/0xC4, 0x54, 0x0F, 0x44, 0x20, 0xC8, 0x83, 0x40,
++ 0x04, 0xF4, 0x56, 0x80, 0x01, 0x46, 0xF6, 0xDF,
++/*0AD0*/0xE4, 0x80, 0x0B, 0x01, 0x02, 0x04, 0x08, 0x10,
++ 0x20, 0x40, 0x80, 0x90, 0x00, 0x3F, 0xE4, 0x7E,
++/*0AE0*/0x01, 0x93, 0x60, 0xC1, 0xA3, 0xFF, 0x54, 0x3F,
++ 0x30, 0xE5, 0x09, 0x54, 0x1F, 0xFE, 0xE4, 0x93,
++/*0AF0*/0xA3, 0x60, 0x01, 0x0E, 0xCF, 0x54, 0xC0, 0x25,
++ 0xE0, 0x60, 0xAD, 0x40, 0xB8, 0x80, 0xFE, 0x8C,
++/*0B00*/0x64, 0x8D, 0x65, 0x8A, 0x66, 0x8B, 0x67, 0xE4,
++ 0xF5, 0x69, 0xEF, 0x4E, 0x70, 0x03, 0x02, 0x1D,
++/*0B10*/0x55, 0xE4, 0xF5, 0x68, 0xE5, 0x67, 0x45, 0x66,
++ 0x70, 0x32, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x90,
++/*0B20*/0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2, 0xE4,
++ 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0xE4, 0x12,
++/*0B30*/0x08, 0x70, 0x70, 0x29, 0x12, 0x07, 0x2A, 0x75,
++ 0x83, 0x92, 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83,
++/*0B40*/0xC6, 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC8,
++ 0xE4, 0xF0, 0x80, 0x11, 0x90, 0x07, 0x26, 0x12,
++/*0B50*/0x07, 0x35, 0xE4, 0x12, 0x08, 0x70, 0x70, 0x05,
++ 0x12, 0x07, 0x32, 0xE4, 0xF0, 0x12, 0x1D, 0x55,
++/*0B60*/0x12, 0x1E, 0xBF, 0xE5, 0x67, 0x45, 0x66, 0x70,
++ 0x33, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x90, 0xE5,
++/*0B70*/0x41, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2, 0xE5,
++ 0x41, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0x12,
++/*0B80*/0x08, 0x6E, 0x70, 0x29, 0x12, 0x07, 0x2A, 0x75,
++ 0x83, 0x92, 0xE5, 0x40, 0x12, 0x07, 0x29, 0x75,
++/*0B90*/0x83, 0xC6, 0xE5, 0x40, 0x12, 0x07, 0x29, 0x75,
++ 0x83, 0xC8, 0x80, 0x0E, 0x90, 0x07, 0x26, 0x12,
++/*0BA0*/0x07, 0x35, 0x12, 0x08, 0x6E, 0x70, 0x06, 0x12,
++ 0x07, 0x32, 0xE5, 0x40, 0xF0, 0xAF, 0x69, 0x7E,
++/*0BB0*/0x00, 0xAD, 0x67, 0xAC, 0x66, 0x12, 0x04, 0x44,
++ 0x12, 0x07, 0x2A, 0x75, 0x83, 0xCA, 0xE0, 0xD3,
++/*0BC0*/0x94, 0x00, 0x50, 0x0C, 0x05, 0x68, 0xE5, 0x68,
++ 0xC3, 0x94, 0x05, 0x50, 0x03, 0x02, 0x0B, 0x14,
++/*0BD0*/0x22, 0x8C, 0x60, 0x8D, 0x61, 0x12, 0x08, 0xDA,
++ 0x74, 0x20, 0x40, 0x0D, 0x2F, 0xF5, 0x82, 0x74,
++/*0BE0*/0x03, 0x3E, 0xF5, 0x83, 0xE5, 0x3E, 0xF0, 0x80,
++ 0x0B, 0x2F, 0xF5, 0x82, 0x74, 0x03, 0x3E, 0xF5,
++/*0BF0*/0x83, 0xE5, 0x3C, 0xF0, 0xE5, 0x3C, 0xD3, 0x95,
++ 0x3E, 0x40, 0x3C, 0xE5, 0x61, 0x45, 0x60, 0x70,
++/*0C00*/0x10, 0xE9, 0x12, 0x09, 0x04, 0xE5, 0x3E, 0x12,
++ 0x07, 0x68, 0x40, 0x3B, 0x12, 0x08, 0x95, 0x80,
++/*0C10*/0x18, 0xE5, 0x3E, 0xC3, 0x95, 0x38, 0x40, 0x1D,
++ 0x85, 0x3E, 0x38, 0xE5, 0x3E, 0x60, 0x05, 0x85,
++/*0C20*/0x3F, 0x39, 0x80, 0x03, 0x85, 0x39, 0x39, 0x8F,
++ 0x3A, 0x12, 0x08, 0x14, 0xE5, 0x3E, 0x12, 0x07,
++/*0C30*/0xC0, 0xE5, 0x3F, 0xF0, 0x22, 0x80, 0x43, 0xE5,
++ 0x61, 0x45, 0x60, 0x70, 0x19, 0x12, 0x07, 0x5F,
++/*0C40*/0x40, 0x05, 0x12, 0x08, 0x9E, 0x80, 0x27, 0x12,
++ 0x09, 0x0B, 0x12, 0x08, 0x14, 0xE5, 0x42, 0x12,
++/*0C50*/0x07, 0xC0, 0xE5, 0x41, 0xF0, 0x22, 0xE5, 0x3C,
++ 0xC3, 0x95, 0x38, 0x40, 0x1D, 0x85, 0x3C, 0x38,
++/*0C60*/0xE5, 0x3C, 0x60, 0x05, 0x85, 0x3D, 0x39, 0x80,
++ 0x03, 0x85, 0x39, 0x39, 0x8F, 0x3A, 0x12, 0x08,
++/*0C70*/0x14, 0xE5, 0x3C, 0x12, 0x07, 0xC0, 0xE5, 0x3D,
++ 0xF0, 0x22, 0x85, 0x38, 0x38, 0x85, 0x39, 0x39,
++/*0C80*/0x85, 0x3A, 0x3A, 0x12, 0x08, 0x14, 0xE5, 0x38,
++ 0x12, 0x07, 0xC0, 0xE5, 0x39, 0xF0, 0x22, 0x7F,
++/*0C90*/0x06, 0x12, 0x17, 0x31, 0x12, 0x1D, 0x23, 0x12,
++ 0x0E, 0x04, 0x12, 0x0E, 0x33, 0xE0, 0x44, 0x0A,
++/*0CA0*/0xF0, 0x74, 0x8E, 0xFE, 0x12, 0x0E, 0x04, 0x12,
++ 0x0E, 0x0B, 0xEF, 0xF0, 0xE5, 0x28, 0x30, 0xE5,
++/*0CB0*/0x03, 0xD3, 0x80, 0x01, 0xC3, 0x40, 0x05, 0x75,
++ 0x14, 0x20, 0x80, 0x03, 0x75, 0x14, 0x08, 0x12,
++/*0CC0*/0x0E, 0x04, 0x75, 0x83, 0x8A, 0xE5, 0x14, 0xF0,
++ 0xB4, 0xFF, 0x05, 0x75, 0x12, 0x80, 0x80, 0x06,
++/*0CD0*/0xE5, 0x14, 0xC3, 0x13, 0xF5, 0x12, 0xE4, 0xF5,
++ 0x16, 0xF5, 0x7F, 0x12, 0x19, 0x36, 0x12, 0x13,
++/*0CE0*/0xA3, 0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x50, 0x09,
++ 0x05, 0x16, 0xE5, 0x16, 0xC3, 0x94, 0x14, 0x40,
++/*0CF0*/0xEA, 0xE5, 0xE4, 0x20, 0xE7, 0x28, 0x12, 0x0E,
++ 0x04, 0x75, 0x83, 0xD2, 0xE0, 0x54, 0x08, 0xD3,
++/*0D00*/0x94, 0x00, 0x40, 0x04, 0x7F, 0x01, 0x80, 0x02,
++ 0x7F, 0x00, 0xE5, 0x0A, 0xC3, 0x94, 0x01, 0x40,
++/*0D10*/0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEF,
++ 0x5E, 0x60, 0x03, 0x12, 0x1D, 0xD7, 0xE5, 0x7F,
++/*0D20*/0xC3, 0x94, 0x11, 0x40, 0x14, 0x12, 0x0E, 0x04,
++ 0x75, 0x83, 0xD2, 0xE0, 0x44, 0x80, 0xF0, 0xE5,
++/*0D30*/0xE4, 0x20, 0xE7, 0x0F, 0x12, 0x1D, 0xD7, 0x80,
++ 0x0A, 0x12, 0x0E, 0x04, 0x75, 0x83, 0xD2, 0xE0,
++/*0D40*/0x54, 0x7F, 0xF0, 0x12, 0x1D, 0x23, 0x22, 0x74,
++ 0x8A, 0x85, 0x08, 0x82, 0xF5, 0x83, 0xE5, 0x17,
++/*0D50*/0xF0, 0x12, 0x0E, 0x3A, 0xE4, 0xF0, 0x90, 0x07,
++ 0x02, 0xE0, 0x12, 0x0E, 0x17, 0x75, 0x83, 0x90,
++/*0D60*/0xEF, 0xF0, 0x74, 0x92, 0xFE, 0xE5, 0x08, 0x44,
++ 0x07, 0xFF, 0xF5, 0x82, 0x8E, 0x83, 0xE0, 0x54,
++/*0D70*/0xC0, 0xFD, 0x90, 0x07, 0x03, 0xE0, 0x54, 0x3F,
++ 0x4D, 0x8F, 0x82, 0x8E, 0x83, 0xF0, 0x90, 0x07,
++/*0D80*/0x04, 0xE0, 0x12, 0x0E, 0x17, 0x75, 0x83, 0x82,
++ 0xEF, 0xF0, 0x90, 0x07, 0x05, 0xE0, 0xFF, 0xED,
++/*0D90*/0x44, 0x07, 0xF5, 0x82, 0x75, 0x83, 0xB4, 0xEF,
++ 0x12, 0x0E, 0x03, 0x75, 0x83, 0x80, 0xE0, 0x54,
++/*0DA0*/0xBF, 0xF0, 0x30, 0x37, 0x0A, 0x12, 0x0E, 0x91,
++ 0x75, 0x83, 0x94, 0xE0, 0x44, 0x80, 0xF0, 0x30,
++/*0DB0*/0x38, 0x0A, 0x12, 0x0E, 0x91, 0x75, 0x83, 0x92,
++ 0xE0, 0x44, 0x80, 0xF0, 0xE5, 0x28, 0x30, 0xE4,
++/*0DC0*/0x1A, 0x20, 0x39, 0x0A, 0x12, 0x0E, 0x04, 0x75,
++ 0x83, 0x88, 0xE0, 0x54, 0x7F, 0xF0, 0x20, 0x3A,
++/*0DD0*/0x0A, 0x12, 0x0E, 0x04, 0x75, 0x83, 0x88, 0xE0,
++ 0x54, 0xBF, 0xF0, 0x74, 0x8C, 0xFE, 0x12, 0x0E,
++/*0DE0*/0x04, 0x8E, 0x83, 0xE0, 0x54, 0x0F, 0x12, 0x0E,
++ 0x03, 0x75, 0x83, 0x86, 0xE0, 0x54, 0xBF, 0xF0,
++/*0DF0*/0xE5, 0x08, 0x44, 0x06, 0x12, 0x0D, 0xFD, 0x75,
++ 0x83, 0x8A, 0xE4, 0xF0, 0x22, 0xF5, 0x82, 0x75,
++/*0E00*/0x83, 0x82, 0xE4, 0xF0, 0xE5, 0x08, 0x44, 0x07,
++ 0xF5, 0x82, 0x22, 0x8E, 0x83, 0xE0, 0xF5, 0x10,
++/*0E10*/0x54, 0xFE, 0xF0, 0xE5, 0x10, 0x44, 0x01, 0xFF,
++ 0xE5, 0x08, 0xFD, 0xED, 0x44, 0x07, 0xF5, 0x82,
++/*0E20*/0x22, 0xE5, 0x15, 0xC4, 0x54, 0x07, 0xFF, 0xE5,
++ 0x08, 0xFD, 0xED, 0x44, 0x08, 0xF5, 0x82, 0x75,
++/*0E30*/0x83, 0x82, 0x22, 0x75, 0x83, 0x80, 0xE0, 0x44,
++ 0x40, 0xF0, 0xE5, 0x08, 0x44, 0x08, 0xF5, 0x82,
++/*0E40*/0x75, 0x83, 0x8A, 0x22, 0xE5, 0x16, 0x25, 0xE0,
++ 0x25, 0xE0, 0x24, 0xAF, 0xF5, 0x82, 0xE4, 0x34,
++/*0E50*/0x1A, 0xF5, 0x83, 0xE4, 0x93, 0xF5, 0x0D, 0x22,
++ 0x43, 0xE1, 0x10, 0x43, 0xE1, 0x80, 0x53, 0xE1,
++/*0E60*/0xFD, 0x85, 0xE1, 0x10, 0x22, 0xE5, 0x16, 0x25,
++ 0xE0, 0x25, 0xE0, 0x24, 0xB2, 0xF5, 0x82, 0xE4,
++/*0E70*/0x34, 0x1A, 0xF5, 0x83, 0xE4, 0x93, 0x22, 0x85,
++ 0x55, 0x82, 0x85, 0x54, 0x83, 0xE5, 0x15, 0xF0,
++/*0E80*/0x22, 0xE5, 0xE2, 0x54, 0x20, 0xD3, 0x94, 0x00,
++ 0x22, 0xE5, 0xE2, 0x54, 0x40, 0xD3, 0x94, 0x00,
++/*0E90*/0x22, 0xE5, 0x08, 0x44, 0x06, 0xF5, 0x82, 0x22,
++ 0xFD, 0xE5, 0x08, 0xFB, 0xEB, 0x44, 0x07, 0xF5,
++/*0EA0*/0x82, 0x22, 0x53, 0xF9, 0xF7, 0x75, 0xFE, 0x30,
++ 0x22, 0xEF, 0x4E, 0x70, 0x26, 0x12, 0x07, 0xCC,
++/*0EB0*/0xE0, 0xFD, 0x90, 0x07, 0x26, 0x12, 0x07, 0x7B,
++ 0x12, 0x07, 0xD8, 0xE0, 0xFD, 0x90, 0x07, 0x28,
++/*0EC0*/0x12, 0x07, 0x7B, 0x12, 0x08, 0x81, 0x12, 0x07,
++ 0x72, 0x12, 0x08, 0x35, 0xE0, 0x90, 0x07, 0x24,
++/*0ED0*/0x12, 0x07, 0x78, 0xEF, 0x64, 0x04, 0x4E, 0x70,
++ 0x29, 0x12, 0x07, 0xE4, 0xE0, 0xFD, 0x90, 0x07,
++/*0EE0*/0x26, 0x12, 0x07, 0x7B, 0x12, 0x07, 0xF0, 0xE0,
++ 0xFD, 0x90, 0x07, 0x28, 0x12, 0x07, 0x7B, 0x12,
++/*0EF0*/0x08, 0x8B, 0x12, 0x07, 0x72, 0x12, 0x08, 0x41,
++ 0xE0, 0x54, 0x1F, 0xFD, 0x90, 0x07, 0x24, 0x12,
++/*0F00*/0x07, 0x7B, 0xEF, 0x64, 0x01, 0x4E, 0x70, 0x04,
++ 0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00, 0xEF, 0x64,
++/*0F10*/0x02, 0x4E, 0x70, 0x04, 0x7F, 0x01, 0x80, 0x02,
++ 0x7F, 0x00, 0xEF, 0x4D, 0x60, 0x35, 0x12, 0x07,
++/*0F20*/0xFC, 0xE0, 0xFF, 0x90, 0x07, 0x26, 0x12, 0x07,
++ 0x89, 0xEF, 0xF0, 0x12, 0x08, 0x08, 0xE0, 0xFF,
++/*0F30*/0x90, 0x07, 0x28, 0x12, 0x07, 0x89, 0xEF, 0xF0,
++ 0x12, 0x08, 0x4D, 0xE0, 0x54, 0x1F, 0xFF, 0x12,
++/*0F40*/0x07, 0x86, 0xEF, 0xF0, 0x12, 0x08, 0x59, 0xE0,
++ 0x54, 0x1F, 0xFF, 0x90, 0x07, 0x24, 0x12, 0x07,
++/*0F50*/0x89, 0xEF, 0xF0, 0x22, 0xE4, 0xF5, 0x53, 0x12,
++ 0x0E, 0x81, 0x40, 0x04, 0x7F, 0x01, 0x80, 0x02,
++/*0F60*/0x7F, 0x00, 0x12, 0x0E, 0x89, 0x40, 0x04, 0x7E,
++ 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F, 0x70,
++/*0F70*/0x03, 0x02, 0x0F, 0xF6, 0x85, 0xE1, 0x10, 0x43,
++ 0xE1, 0x02, 0x53, 0xE1, 0x0F, 0x85, 0xE1, 0x10,
++/*0F80*/0xE4, 0xF5, 0x51, 0xE5, 0xE3, 0x54, 0x3F, 0xF5,
++ 0x52, 0x12, 0x0E, 0x89, 0x40, 0x1D, 0xAD, 0x52,
++/*0F90*/0xAF, 0x51, 0x12, 0x11, 0x18, 0xEF, 0x60, 0x08,
++ 0x85, 0xE1, 0x10, 0x43, 0xE1, 0x40, 0x80, 0x0B,
++/*0FA0*/0x53, 0xE1, 0xBF, 0x12, 0x0E, 0x58, 0x12, 0x00,
++ 0x06, 0x80, 0xFB, 0xE5, 0xE3, 0x54, 0x3F, 0xF5,
++/*0FB0*/0x51, 0xE5, 0xE4, 0x54, 0x3F, 0xF5, 0x52, 0x12,
++ 0x0E, 0x81, 0x40, 0x1D, 0xAD, 0x52, 0xAF, 0x51,
++/*0FC0*/0x12, 0x11, 0x18, 0xEF, 0x60, 0x08, 0x85, 0xE1,
++ 0x10, 0x43, 0xE1, 0x20, 0x80, 0x0B, 0x53, 0xE1,
++/*0FD0*/0xDF, 0x12, 0x0E, 0x58, 0x12, 0x00, 0x06, 0x80,
++ 0xFB, 0x12, 0x0E, 0x81, 0x40, 0x04, 0x7F, 0x01,
++/*0FE0*/0x80, 0x02, 0x7F, 0x00, 0x12, 0x0E, 0x89, 0x40,
++ 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE,
++/*0FF0*/0x4F, 0x60, 0x03, 0x12, 0x0E, 0x5B, 0x22, 0x12,
++ 0x0E, 0x21, 0xEF, 0xF0, 0x12, 0x10, 0x91, 0x22,
++/*1000*/0x02, 0x11, 0x00, 0x02, 0x10, 0x40, 0x02, 0x10,
++ 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1010*/0x01, 0x20, 0x01, 0x20, 0xE4, 0xF5, 0x57, 0x12,
++ 0x16, 0xBD, 0x12, 0x16, 0x44, 0xE4, 0x12, 0x10,
++/*1020*/0x56, 0x12, 0x14, 0xB7, 0x90, 0x07, 0x26, 0x12,
++ 0x07, 0x35, 0xE4, 0x12, 0x07, 0x31, 0xE4, 0xF0,
++/*1030*/0x12, 0x10, 0x56, 0x12, 0x14, 0xB7, 0x90, 0x07,
++ 0x26, 0x12, 0x07, 0x35, 0xE5, 0x41, 0x12, 0x07,
++/*1040*/0x31, 0xE5, 0x40, 0xF0, 0xAF, 0x57, 0x7E, 0x00,
++ 0xAD, 0x56, 0x7C, 0x00, 0x12, 0x04, 0x44, 0xAF,
++/*1050*/0x56, 0x7E, 0x00, 0x02, 0x11, 0xEE, 0xFF, 0x90,
++ 0x07, 0x20, 0xA3, 0xE0, 0xFD, 0xE4, 0xF5, 0x56,
++/*1060*/0xF5, 0x40, 0xFE, 0xFC, 0xAB, 0x56, 0xFA, 0x12,
++ 0x11, 0x51, 0x7F, 0x0F, 0x7D, 0x18, 0xE4, 0xF5,
++/*1070*/0x56, 0xF5, 0x40, 0xFE, 0xFC, 0xAB, 0x56, 0xFA,
++ 0x12, 0x15, 0x41, 0xAF, 0x56, 0x7E, 0x00, 0x12,
++/*1080*/0x1A, 0xFF, 0xE4, 0xFF, 0xF5, 0x56, 0x7D, 0x1F,
++ 0xF5, 0x40, 0xFE, 0xFC, 0xAB, 0x56, 0xFA, 0x22,
++/*1090*/0x22, 0xE4, 0xF5, 0x55, 0xE5, 0x08, 0xFD, 0x74,
++ 0xA0, 0xF5, 0x56, 0xED, 0x44, 0x07, 0xF5, 0x57,
++/*10A0*/0xE5, 0x28, 0x30, 0xE5, 0x03, 0xD3, 0x80, 0x01,
++ 0xC3, 0x40, 0x05, 0x7F, 0x28, 0xEF, 0x80, 0x04,
++/*10B0*/0x7F, 0x14, 0xEF, 0xC3, 0x13, 0xF5, 0x54, 0xE4,
++ 0xF9, 0x12, 0x0E, 0x18, 0x75, 0x83, 0x8E, 0xE0,
++/*10C0*/0xF5, 0x10, 0xCE, 0xEF, 0xCE, 0xEE, 0xD3, 0x94,
++ 0x00, 0x40, 0x26, 0xE5, 0x10, 0x54, 0xFE, 0x12,
++/*10D0*/0x0E, 0x98, 0x75, 0x83, 0x8E, 0xED, 0xF0, 0xE5,
++ 0x10, 0x44, 0x01, 0xFD, 0xEB, 0x44, 0x07, 0xF5,
++/*10E0*/0x82, 0xED, 0xF0, 0x85, 0x57, 0x82, 0x85, 0x56,
++ 0x83, 0xE0, 0x30, 0xE3, 0x01, 0x09, 0x1E, 0x80,
++/*10F0*/0xD4, 0xC2, 0x34, 0xE9, 0xC3, 0x95, 0x54, 0x40,
++ 0x02, 0xD2, 0x34, 0x22, 0x02, 0x00, 0x06, 0x22,
++/*1100*/0x30, 0x30, 0x11, 0x90, 0x10, 0x00, 0xE4, 0x93,
++ 0xF5, 0x10, 0x90, 0x10, 0x10, 0xE4, 0x93, 0xF5,
++/*1110*/0x10, 0x12, 0x10, 0x90, 0x12, 0x11, 0x50, 0x22,
++ 0xE4, 0xFC, 0xC3, 0xED, 0x9F, 0xFA, 0xEF, 0xF5,
++/*1120*/0x83, 0x75, 0x82, 0x00, 0x79, 0xFF, 0xE4, 0x93,
++ 0xCC, 0x6C, 0xCC, 0xA3, 0xD9, 0xF8, 0xDA, 0xF6,
++/*1130*/0xE5, 0xE2, 0x30, 0xE4, 0x02, 0x8C, 0xE5, 0xED,
++ 0x24, 0xFF, 0xFF, 0xEF, 0x75, 0x82, 0xFF, 0xF5,
++/*1140*/0x83, 0xE4, 0x93, 0x6C, 0x70, 0x03, 0x7F, 0x01,
++ 0x22, 0x7F, 0x00, 0x22, 0x22, 0x11, 0x00, 0x00,
++/*1150*/0x22, 0x8E, 0x58, 0x8F, 0x59, 0x8C, 0x5A, 0x8D,
++ 0x5B, 0x8A, 0x5C, 0x8B, 0x5D, 0x75, 0x5E, 0x01,
++/*1160*/0xE4, 0xF5, 0x5F, 0xF5, 0x60, 0xF5, 0x62, 0x12,
++ 0x07, 0x2A, 0x75, 0x83, 0xD0, 0xE0, 0xFF, 0xC4,
++/*1170*/0x54, 0x0F, 0xF5, 0x61, 0x12, 0x1E, 0xA5, 0x85,
++ 0x59, 0x5E, 0xD3, 0xE5, 0x5E, 0x95, 0x5B, 0xE5,
++/*1180*/0x5A, 0x12, 0x07, 0x6B, 0x50, 0x4B, 0x12, 0x07,
++ 0x03, 0x75, 0x83, 0xBC, 0xE0, 0x45, 0x5E, 0x12,
++/*1190*/0x07, 0x29, 0x75, 0x83, 0xBE, 0xE0, 0x45, 0x5E,
++ 0x12, 0x07, 0x29, 0x75, 0x83, 0xC0, 0xE0, 0x45,
++/*11A0*/0x5E, 0xF0, 0xAF, 0x5F, 0xE5, 0x60, 0x12, 0x08,
++ 0x78, 0x12, 0x0A, 0xFF, 0xAF, 0x62, 0x7E, 0x00,
++/*11B0*/0xAD, 0x5D, 0xAC, 0x5C, 0x12, 0x04, 0x44, 0xE5,
++ 0x61, 0xAF, 0x5E, 0x7E, 0x00, 0xB4, 0x03, 0x05,
++/*11C0*/0x12, 0x1E, 0x21, 0x80, 0x07, 0xAD, 0x5D, 0xAC,
++ 0x5C, 0x12, 0x13, 0x17, 0x05, 0x5E, 0x02, 0x11,
++/*11D0*/0x7A, 0x12, 0x07, 0x03, 0x75, 0x83, 0xBC, 0xE0,
++ 0x45, 0x40, 0x12, 0x07, 0x29, 0x75, 0x83, 0xBE,
++/*11E0*/0xE0, 0x45, 0x40, 0x12, 0x07, 0x29, 0x75, 0x83,
++ 0xC0, 0xE0, 0x45, 0x40, 0xF0, 0x22, 0x8E, 0x58,
++/*11F0*/0x8F, 0x59, 0x75, 0x5A, 0x01, 0x79, 0x01, 0x75,
++ 0x5B, 0x01, 0xE4, 0xFB, 0x12, 0x07, 0x2A, 0x75,
++/*1200*/0x83, 0xAE, 0xE0, 0x54, 0x1A, 0xFF, 0x12, 0x08,
++ 0x65, 0xE0, 0xC4, 0x13, 0x54, 0x07, 0xFE, 0xEF,
++/*1210*/0x70, 0x0C, 0xEE, 0x65, 0x35, 0x70, 0x07, 0x90,
++ 0x07, 0x2F, 0xE0, 0xB4, 0x01, 0x0D, 0xAF, 0x35,
++/*1220*/0x7E, 0x00, 0x12, 0x0E, 0xA9, 0xCF, 0xEB, 0xCF,
++ 0x02, 0x1E, 0x60, 0xE5, 0x59, 0x64, 0x02, 0x45,
++/*1230*/0x58, 0x70, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F,
++ 0x00, 0xE5, 0x59, 0x45, 0x58, 0x70, 0x04, 0x7E,
++/*1240*/0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F, 0x60,
++ 0x23, 0x85, 0x41, 0x49, 0x85, 0x40, 0x4B, 0xE5,
++/*1250*/0x59, 0x45, 0x58, 0x70, 0x2C, 0xAF, 0x5A, 0xFE,
++ 0xCD, 0xE9, 0xCD, 0xFC, 0xAB, 0x59, 0xAA, 0x58,
++/*1260*/0x12, 0x0A, 0xFF, 0xAF, 0x5B, 0x7E, 0x00, 0x12,
++ 0x1E, 0x60, 0x80, 0x15, 0xAF, 0x5B, 0x7E, 0x00,
++/*1270*/0x12, 0x1E, 0x60, 0x90, 0x07, 0x26, 0x12, 0x07,
++ 0x35, 0xE5, 0x49, 0x12, 0x07, 0x31, 0xE5, 0x4B,
++/*1280*/0xF0, 0xE4, 0xFD, 0xAF, 0x35, 0xFE, 0xFC, 0x12,
++ 0x09, 0x15, 0x22, 0x8C, 0x64, 0x8D, 0x65, 0x12,
++/*1290*/0x08, 0xDA, 0x40, 0x3C, 0xE5, 0x65, 0x45, 0x64,
++ 0x70, 0x10, 0x12, 0x09, 0x04, 0xC3, 0xE5, 0x3E,
++/*12A0*/0x12, 0x07, 0x69, 0x40, 0x3B, 0x12, 0x08, 0x95,
++ 0x80, 0x18, 0xE5, 0x3E, 0xC3, 0x95, 0x38, 0x40,
++/*12B0*/0x1D, 0x85, 0x3E, 0x38, 0xE5, 0x3E, 0x60, 0x05,
++ 0x85, 0x3F, 0x39, 0x80, 0x03, 0x85, 0x39, 0x39,
++/*12C0*/0x8F, 0x3A, 0x12, 0x07, 0xA8, 0xE5, 0x3E, 0x12,
++ 0x07, 0x53, 0xE5, 0x3F, 0xF0, 0x22, 0x80, 0x3B,
++/*12D0*/0xE5, 0x65, 0x45, 0x64, 0x70, 0x11, 0x12, 0x07,
++ 0x5F, 0x40, 0x05, 0x12, 0x08, 0x9E, 0x80, 0x1F,
++/*12E0*/0x12, 0x07, 0x3E, 0xE5, 0x41, 0xF0, 0x22, 0xE5,
++ 0x3C, 0xC3, 0x95, 0x38, 0x40, 0x1D, 0x85, 0x3C,
++/*12F0*/0x38, 0xE5, 0x3C, 0x60, 0x05, 0x85, 0x3D, 0x39,
++ 0x80, 0x03, 0x85, 0x39, 0x39, 0x8F, 0x3A, 0x12,
++/*1300*/0x07, 0xA8, 0xE5, 0x3C, 0x12, 0x07, 0x53, 0xE5,
++ 0x3D, 0xF0, 0x22, 0x12, 0x07, 0x9F, 0xE5, 0x38,
++/*1310*/0x12, 0x07, 0x53, 0xE5, 0x39, 0xF0, 0x22, 0x8C,
++ 0x63, 0x8D, 0x64, 0x12, 0x08, 0xDA, 0x40, 0x3C,
++/*1320*/0xE5, 0x64, 0x45, 0x63, 0x70, 0x10, 0x12, 0x09,
++ 0x04, 0xC3, 0xE5, 0x3E, 0x12, 0x07, 0x69, 0x40,
++/*1330*/0x3B, 0x12, 0x08, 0x95, 0x80, 0x18, 0xE5, 0x3E,
++ 0xC3, 0x95, 0x38, 0x40, 0x1D, 0x85, 0x3E, 0x38,
++/*1340*/0xE5, 0x3E, 0x60, 0x05, 0x85, 0x3F, 0x39, 0x80,
++ 0x03, 0x85, 0x39, 0x39, 0x8F, 0x3A, 0x12, 0x07,
++/*1350*/0xA8, 0xE5, 0x3E, 0x12, 0x07, 0x53, 0xE5, 0x3F,
++ 0xF0, 0x22, 0x80, 0x3B, 0xE5, 0x64, 0x45, 0x63,
++/*1360*/0x70, 0x11, 0x12, 0x07, 0x5F, 0x40, 0x05, 0x12,
++ 0x08, 0x9E, 0x80, 0x1F, 0x12, 0x07, 0x3E, 0xE5,
++/*1370*/0x41, 0xF0, 0x22, 0xE5, 0x3C, 0xC3, 0x95, 0x38,
++ 0x40, 0x1D, 0x85, 0x3C, 0x38, 0xE5, 0x3C, 0x60,
++/*1380*/0x05, 0x85, 0x3D, 0x39, 0x80, 0x03, 0x85, 0x39,
++ 0x39, 0x8F, 0x3A, 0x12, 0x07, 0xA8, 0xE5, 0x3C,
++/*1390*/0x12, 0x07, 0x53, 0xE5, 0x3D, 0xF0, 0x22, 0x12,
++ 0x07, 0x9F, 0xE5, 0x38, 0x12, 0x07, 0x53, 0xE5,
++/*13A0*/0x39, 0xF0, 0x22, 0xE5, 0x0D, 0xFE, 0xE5, 0x08,
++ 0x8E, 0x54, 0x44, 0x05, 0xF5, 0x55, 0x75, 0x15,
++/*13B0*/0x0F, 0xF5, 0x82, 0x12, 0x0E, 0x7A, 0x12, 0x17,
++ 0xA3, 0x20, 0x31, 0x05, 0x75, 0x15, 0x03, 0x80,
++/*13C0*/0x03, 0x75, 0x15, 0x0B, 0xE5, 0x0A, 0xC3, 0x94,
++ 0x01, 0x50, 0x38, 0x12, 0x14, 0x20, 0x20, 0x31,
++/*13D0*/0x06, 0x05, 0x15, 0x05, 0x15, 0x80, 0x04, 0x15,
++ 0x15, 0x15, 0x15, 0xE5, 0x0A, 0xC3, 0x94, 0x01,
++/*13E0*/0x50, 0x21, 0x12, 0x14, 0x20, 0x20, 0x31, 0x04,
++ 0x05, 0x15, 0x80, 0x02, 0x15, 0x15, 0xE5, 0x0A,
++/*13F0*/0xC3, 0x94, 0x01, 0x50, 0x0E, 0x12, 0x0E, 0x77,
++ 0x12, 0x17, 0xA3, 0x20, 0x31, 0x05, 0x05, 0x15,
++/*1400*/0x12, 0x0E, 0x77, 0xE5, 0x15, 0xB4, 0x08, 0x04,
++ 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x15,
++/*1410*/0xB4, 0x07, 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E,
++ 0x00, 0xEE, 0x4F, 0x60, 0x02, 0x05, 0x7F, 0x22,
++/*1420*/0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xE5, 0x15,
++ 0xF0, 0x12, 0x17, 0xA3, 0x22, 0x12, 0x07, 0x2A,
++/*1430*/0x75, 0x83, 0xAE, 0x74, 0xFF, 0x12, 0x07, 0x29,
++ 0xE0, 0x54, 0x1A, 0xF5, 0x34, 0xE0, 0xC4, 0x13,
++/*1440*/0x54, 0x07, 0xF5, 0x35, 0x24, 0xFE, 0x60, 0x24,
++ 0x24, 0xFE, 0x60, 0x3C, 0x24, 0x04, 0x70, 0x63,
++/*1450*/0x75, 0x31, 0x2D, 0xE5, 0x08, 0xFD, 0x74, 0xB6,
++ 0x12, 0x07, 0x92, 0x74, 0xBC, 0x90, 0x07, 0x22,
++/*1460*/0x12, 0x07, 0x95, 0x74, 0x90, 0x12, 0x07, 0xB3,
++ 0x74, 0x92, 0x80, 0x3C, 0x75, 0x31, 0x3A, 0xE5,
++/*1470*/0x08, 0xFD, 0x74, 0xBA, 0x12, 0x07, 0x92, 0x74,
++ 0xC0, 0x90, 0x07, 0x22, 0x12, 0x07, 0xB6, 0x74,
++/*1480*/0xC4, 0x12, 0x07, 0xB3, 0x74, 0xC8, 0x80, 0x20,
++ 0x75, 0x31, 0x35, 0xE5, 0x08, 0xFD, 0x74, 0xB8,
++/*1490*/0x12, 0x07, 0x92, 0x74, 0xBE, 0xFF, 0xED, 0x44,
++ 0x07, 0x90, 0x07, 0x22, 0xCF, 0xF0, 0xA3, 0xEF,
++/*14A0*/0xF0, 0x74, 0xC2, 0x12, 0x07, 0xB3, 0x74, 0xC6,
++ 0xFF, 0xED, 0x44, 0x07, 0xA3, 0xCF, 0xF0, 0xA3,
++/*14B0*/0xEF, 0xF0, 0x22, 0x75, 0x34, 0x01, 0x22, 0x8E,
++ 0x58, 0x8F, 0x59, 0x8C, 0x5A, 0x8D, 0x5B, 0x8A,
++/*14C0*/0x5C, 0x8B, 0x5D, 0x75, 0x5E, 0x01, 0xE4, 0xF5,
++ 0x5F, 0x12, 0x1E, 0xA5, 0x85, 0x59, 0x5E, 0xD3,
++/*14D0*/0xE5, 0x5E, 0x95, 0x5B, 0xE5, 0x5A, 0x12, 0x07,
++ 0x6B, 0x50, 0x57, 0xE5, 0x5D, 0x45, 0x5C, 0x70,
++/*14E0*/0x30, 0x12, 0x07, 0x2A, 0x75, 0x83, 0x92, 0xE5,
++ 0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC6, 0xE5,
++/*14F0*/0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC8, 0xE5,
++ 0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0x90, 0xE5,
++/*1500*/0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2, 0xE5,
++ 0x5E, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0x80,
++/*1510*/0x03, 0x12, 0x07, 0x32, 0xE5, 0x5E, 0xF0, 0xAF,
++ 0x5F, 0x7E, 0x00, 0xAD, 0x5D, 0xAC, 0x5C, 0x12,
++/*1520*/0x04, 0x44, 0xAF, 0x5E, 0x7E, 0x00, 0xAD, 0x5D,
++ 0xAC, 0x5C, 0x12, 0x0B, 0xD1, 0x05, 0x5E, 0x02,
++/*1530*/0x14, 0xCF, 0xAB, 0x5D, 0xAA, 0x5C, 0xAD, 0x5B,
++ 0xAC, 0x5A, 0xAF, 0x59, 0xAE, 0x58, 0x02, 0x1B,
++/*1540*/0xFB, 0x8C, 0x5C, 0x8D, 0x5D, 0x8A, 0x5E, 0x8B,
++ 0x5F, 0x75, 0x60, 0x01, 0xE4, 0xF5, 0x61, 0xF5,
++/*1550*/0x62, 0xF5, 0x63, 0x12, 0x1E, 0xA5, 0x8F, 0x60,
++ 0xD3, 0xE5, 0x60, 0x95, 0x5D, 0xE5, 0x5C, 0x12,
++/*1560*/0x07, 0x6B, 0x50, 0x61, 0xE5, 0x5F, 0x45, 0x5E,
++ 0x70, 0x27, 0x12, 0x07, 0x2A, 0x75, 0x83, 0xB6,
++/*1570*/0xE5, 0x60, 0x12, 0x07, 0x29, 0x75, 0x83, 0xB8,
++ 0xE5, 0x60, 0x12, 0x07, 0x29, 0x75, 0x83, 0xBA,
++/*1580*/0xE5, 0x60, 0xF0, 0xAF, 0x61, 0x7E, 0x00, 0xE5,
++ 0x62, 0x12, 0x08, 0x7A, 0x12, 0x0A, 0xFF, 0x80,
++/*1590*/0x19, 0x90, 0x07, 0x24, 0x12, 0x07, 0x35, 0xE5,
++ 0x60, 0x12, 0x07, 0x29, 0x75, 0x83, 0x8E, 0xE4,
++/*15A0*/0x12, 0x07, 0x29, 0x74, 0x01, 0x12, 0x07, 0x29,
++ 0xE4, 0xF0, 0xAF, 0x63, 0x7E, 0x00, 0xAD, 0x5F,
++/*15B0*/0xAC, 0x5E, 0x12, 0x04, 0x44, 0xAF, 0x60, 0x7E,
++ 0x00, 0xAD, 0x5F, 0xAC, 0x5E, 0x12, 0x12, 0x8B,
++/*15C0*/0x05, 0x60, 0x02, 0x15, 0x58, 0x22, 0x90, 0x11,
++ 0x4D, 0xE4, 0x93, 0x90, 0x07, 0x2E, 0xF0, 0x12,
++/*15D0*/0x08, 0x1F, 0x75, 0x83, 0xAE, 0xE0, 0x54, 0x1A,
++ 0xF5, 0x34, 0x70, 0x67, 0xEF, 0x44, 0x07, 0xF5,
++/*15E0*/0x82, 0x75, 0x83, 0xCE, 0xE0, 0xFF, 0x13, 0x13,
++ 0x13, 0x54, 0x07, 0xF5, 0x36, 0x54, 0x0F, 0xD3,
++/*15F0*/0x94, 0x00, 0x40, 0x06, 0x12, 0x14, 0x2D, 0x12,
++ 0x1B, 0xA9, 0xE5, 0x36, 0x54, 0x0F, 0x24, 0xFE,
++/*1600*/0x60, 0x0C, 0x14, 0x60, 0x0C, 0x14, 0x60, 0x19,
++ 0x24, 0x03, 0x70, 0x37, 0x80, 0x10, 0x02, 0x1E,
++/*1610*/0x91, 0x12, 0x1E, 0x91, 0x12, 0x07, 0x2A, 0x75,
++ 0x83, 0xCE, 0xE0, 0x54, 0xEF, 0xF0, 0x02, 0x1D,
++/*1620*/0xAE, 0x12, 0x10, 0x14, 0xE4, 0xF5, 0x55, 0x12,
++ 0x1D, 0x85, 0x05, 0x55, 0xE5, 0x55, 0xC3, 0x94,
++/*1630*/0x05, 0x40, 0xF4, 0x12, 0x07, 0x2A, 0x75, 0x83,
++ 0xCE, 0xE0, 0x54, 0xC7, 0x12, 0x07, 0x29, 0xE0,
++/*1640*/0x44, 0x08, 0xF0, 0x22, 0xE4, 0xF5, 0x58, 0xF5,
++ 0x59, 0xAF, 0x08, 0xEF, 0x44, 0x07, 0xF5, 0x82,
++/*1650*/0x75, 0x83, 0xD0, 0xE0, 0xFD, 0xC4, 0x54, 0x0F,
++ 0xF5, 0x5A, 0xEF, 0x44, 0x07, 0xF5, 0x82, 0x75,
++/*1660*/0x83, 0x80, 0x74, 0x01, 0xF0, 0x12, 0x08, 0x21,
++ 0x75, 0x83, 0x82, 0xE5, 0x45, 0xF0, 0xEF, 0x44,
++/*1670*/0x07, 0xF5, 0x82, 0x75, 0x83, 0x8A, 0x74, 0xFF,
++ 0xF0, 0x12, 0x1A, 0x4D, 0x12, 0x07, 0x2A, 0x75,
++/*1680*/0x83, 0xBC, 0xE0, 0x54, 0xEF, 0x12, 0x07, 0x29,
++ 0x75, 0x83, 0xBE, 0xE0, 0x54, 0xEF, 0x12, 0x07,
++/*1690*/0x29, 0x75, 0x83, 0xC0, 0xE0, 0x54, 0xEF, 0x12,
++ 0x07, 0x29, 0x75, 0x83, 0xBC, 0xE0, 0x44, 0x10,
++/*16A0*/0x12, 0x07, 0x29, 0x75, 0x83, 0xBE, 0xE0, 0x44,
++ 0x10, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC0, 0xE0,
++/*16B0*/0x44, 0x10, 0xF0, 0xAF, 0x58, 0xE5, 0x59, 0x12,
++ 0x08, 0x78, 0x02, 0x0A, 0xFF, 0xE4, 0xF5, 0x58,
++/*16C0*/0x7D, 0x01, 0xF5, 0x59, 0xAF, 0x35, 0xFE, 0xFC,
++ 0x12, 0x09, 0x15, 0x12, 0x07, 0x2A, 0x75, 0x83,
++/*16D0*/0xB6, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
++ 0xB8, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
++/*16E0*/0xBA, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
++ 0xBC, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
++/*16F0*/0xBE, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
++ 0xC0, 0x74, 0x10, 0x12, 0x07, 0x29, 0x75, 0x83,
++/*1700*/0x90, 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC2,
++ 0xE4, 0x12, 0x07, 0x29, 0x75, 0x83, 0xC4, 0xE4,
++/*1710*/0x12, 0x07, 0x29, 0x75, 0x83, 0x92, 0xE4, 0x12,
++ 0x07, 0x29, 0x75, 0x83, 0xC6, 0xE4, 0x12, 0x07,
++/*1720*/0x29, 0x75, 0x83, 0xC8, 0xE4, 0xF0, 0xAF, 0x58,
++ 0xFE, 0xE5, 0x59, 0x12, 0x08, 0x7A, 0x02, 0x0A,
++/*1730*/0xFF, 0xE5, 0xE2, 0x30, 0xE4, 0x6C, 0xE5, 0xE7,
++ 0x54, 0xC0, 0x64, 0x40, 0x70, 0x64, 0xE5, 0x09,
++/*1740*/0xC4, 0x54, 0x30, 0xFE, 0xE5, 0x08, 0x25, 0xE0,
++ 0x25, 0xE0, 0x54, 0xC0, 0x4E, 0xFE, 0xEF, 0x54,
++/*1750*/0x3F, 0x4E, 0xFD, 0xE5, 0x2B, 0xAE, 0x2A, 0x78,
++ 0x02, 0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9,
++/*1760*/0xF5, 0x82, 0x8E, 0x83, 0xED, 0xF0, 0xE5, 0x2B,
++ 0xAE, 0x2A, 0x78, 0x02, 0xC3, 0x33, 0xCE, 0x33,
++/*1770*/0xCE, 0xD8, 0xF9, 0xFF, 0xF5, 0x82, 0x8E, 0x83,
++ 0xA3, 0xE5, 0xFE, 0xF0, 0x8F, 0x82, 0x8E, 0x83,
++/*1780*/0xA3, 0xA3, 0xE5, 0xFD, 0xF0, 0x8F, 0x82, 0x8E,
++ 0x83, 0xA3, 0xA3, 0xA3, 0xE5, 0xFC, 0xF0, 0xC3,
++/*1790*/0xE5, 0x2B, 0x94, 0xFA, 0xE5, 0x2A, 0x94, 0x00,
++ 0x50, 0x08, 0x05, 0x2B, 0xE5, 0x2B, 0x70, 0x02,
++/*17A0*/0x05, 0x2A, 0x22, 0xE4, 0xFF, 0xE4, 0xF5, 0x58,
++ 0xF5, 0x56, 0xF5, 0x57, 0x74, 0x82, 0xFC, 0x12,
++/*17B0*/0x0E, 0x04, 0x8C, 0x83, 0xE0, 0xF5, 0x10, 0x54,
++ 0x7F, 0xF0, 0xE5, 0x10, 0x44, 0x80, 0x12, 0x0E,
++/*17C0*/0x98, 0xED, 0xF0, 0x7E, 0x0A, 0x12, 0x0E, 0x04,
++ 0x75, 0x83, 0xA0, 0xE0, 0x20, 0xE0, 0x26, 0xDE,
++/*17D0*/0xF4, 0x05, 0x57, 0xE5, 0x57, 0x70, 0x02, 0x05,
++ 0x56, 0xE5, 0x14, 0x24, 0x01, 0xFD, 0xE4, 0x33,
++/*17E0*/0xFC, 0xD3, 0xE5, 0x57, 0x9D, 0xE5, 0x56, 0x9C,
++ 0x40, 0xD9, 0xE5, 0x0A, 0x94, 0x20, 0x50, 0x02,
++/*17F0*/0x05, 0x0A, 0x43, 0xE1, 0x08, 0xC2, 0x31, 0x12,
++ 0x0E, 0x04, 0x75, 0x83, 0xA6, 0xE0, 0x55, 0x12,
++/*1800*/0x65, 0x12, 0x70, 0x03, 0xD2, 0x31, 0x22, 0xC2,
++ 0x31, 0x22, 0x90, 0x07, 0x26, 0xE0, 0xFA, 0xA3,
++/*1810*/0xE0, 0xF5, 0x82, 0x8A, 0x83, 0xE0, 0xF5, 0x41,
++ 0xE5, 0x39, 0xC3, 0x95, 0x41, 0x40, 0x26, 0xE5,
++/*1820*/0x39, 0x95, 0x41, 0xC3, 0x9F, 0xEE, 0x12, 0x07,
++ 0x6B, 0x40, 0x04, 0x7C, 0x01, 0x80, 0x02, 0x7C,
++/*1830*/0x00, 0xE5, 0x41, 0x64, 0x3F, 0x60, 0x04, 0x7B,
++ 0x01, 0x80, 0x02, 0x7B, 0x00, 0xEC, 0x5B, 0x60,
++/*1840*/0x29, 0x05, 0x41, 0x80, 0x28, 0xC3, 0xE5, 0x41,
++ 0x95, 0x39, 0xC3, 0x9F, 0xEE, 0x12, 0x07, 0x6B,
++/*1850*/0x40, 0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00,
++ 0xE5, 0x41, 0x60, 0x04, 0x7E, 0x01, 0x80, 0x02,
++/*1860*/0x7E, 0x00, 0xEF, 0x5E, 0x60, 0x04, 0x15, 0x41,
++ 0x80, 0x03, 0x85, 0x39, 0x41, 0x85, 0x3A, 0x40,
++/*1870*/0x22, 0xE5, 0xE2, 0x30, 0xE4, 0x60, 0xE5, 0xE1,
++ 0x30, 0xE2, 0x5B, 0xE5, 0x09, 0x70, 0x04, 0x7F,
++/*1880*/0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5, 0x08, 0x70,
++ 0x04, 0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE,
++/*1890*/0x5F, 0x60, 0x43, 0x53, 0xF9, 0xF8, 0xE5, 0xE2,
++ 0x30, 0xE4, 0x3B, 0xE5, 0xE1, 0x30, 0xE2, 0x2E,
++/*18A0*/0x43, 0xFA, 0x02, 0x53, 0xFA, 0xFB, 0xE4, 0xF5,
++ 0x10, 0x90, 0x94, 0x70, 0xE5, 0x10, 0xF0, 0xE5,
++/*18B0*/0xE1, 0x30, 0xE2, 0xE7, 0x90, 0x94, 0x70, 0xE0,
++ 0x65, 0x10, 0x60, 0x03, 0x43, 0xFA, 0x04, 0x05,
++/*18C0*/0x10, 0x90, 0x94, 0x70, 0xE5, 0x10, 0xF0, 0x70,
++ 0xE6, 0x12, 0x00, 0x06, 0x80, 0xE1, 0x53, 0xFA,
++/*18D0*/0xFD, 0x53, 0xFA, 0xFB, 0x80, 0xC0, 0x22, 0x8F,
++ 0x54, 0x12, 0x00, 0x06, 0xE5, 0xE1, 0x30, 0xE0,
++/*18E0*/0x04, 0x7F, 0x01, 0x80, 0x02, 0x7F, 0x00, 0xE5,
++ 0x7E, 0xD3, 0x94, 0x05, 0x40, 0x04, 0x7E, 0x01,
++/*18F0*/0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F, 0x60, 0x3D,
++ 0x85, 0x54, 0x11, 0xE5, 0xE2, 0x20, 0xE1, 0x32,
++/*1900*/0x74, 0xCE, 0x12, 0x1A, 0x05, 0x30, 0xE7, 0x04,
++ 0x7D, 0x01, 0x80, 0x02, 0x7D, 0x00, 0x8F, 0x82,
++/*1910*/0x8E, 0x83, 0xE0, 0x30, 0xE6, 0x04, 0x7F, 0x01,
++ 0x80, 0x02, 0x7F, 0x00, 0xEF, 0x5D, 0x70, 0x15,
++/*1920*/0x12, 0x15, 0xC6, 0x74, 0xCE, 0x12, 0x1A, 0x05,
++ 0x30, 0xE6, 0x07, 0xE0, 0x44, 0x80, 0xF0, 0x43,
++/*1930*/0xF9, 0x80, 0x12, 0x18, 0x71, 0x22, 0x12, 0x0E,
++ 0x44, 0xE5, 0x16, 0x25, 0xE0, 0x25, 0xE0, 0x24,
++/*1940*/0xB0, 0xF5, 0x82, 0xE4, 0x34, 0x1A, 0xF5, 0x83,
++ 0xE4, 0x93, 0xF5, 0x0F, 0xE5, 0x16, 0x25, 0xE0,
++/*1950*/0x25, 0xE0, 0x24, 0xB1, 0xF5, 0x82, 0xE4, 0x34,
++ 0x1A, 0xF5, 0x83, 0xE4, 0x93, 0xF5, 0x0E, 0x12,
++/*1960*/0x0E, 0x65, 0xF5, 0x10, 0xE5, 0x0F, 0x54, 0xF0,
++ 0x12, 0x0E, 0x17, 0x75, 0x83, 0x8C, 0xEF, 0xF0,
++/*1970*/0xE5, 0x0F, 0x30, 0xE0, 0x0C, 0x12, 0x0E, 0x04,
++ 0x75, 0x83, 0x86, 0xE0, 0x44, 0x40, 0xF0, 0x80,
++/*1980*/0x0A, 0x12, 0x0E, 0x04, 0x75, 0x83, 0x86, 0xE0,
++ 0x54, 0xBF, 0xF0, 0x12, 0x0E, 0x91, 0x75, 0x83,
++/*1990*/0x82, 0xE5, 0x0E, 0xF0, 0x22, 0x7F, 0x05, 0x12,
++ 0x17, 0x31, 0x12, 0x0E, 0x04, 0x12, 0x0E, 0x33,
++/*19A0*/0x74, 0x02, 0xF0, 0x74, 0x8E, 0xFE, 0x12, 0x0E,
++ 0x04, 0x12, 0x0E, 0x0B, 0xEF, 0xF0, 0x75, 0x15,
++/*19B0*/0x70, 0x12, 0x0F, 0xF7, 0x20, 0x34, 0x05, 0x75,
++ 0x15, 0x10, 0x80, 0x03, 0x75, 0x15, 0x50, 0x12,
++/*19C0*/0x0F, 0xF7, 0x20, 0x34, 0x04, 0x74, 0x10, 0x80,
++ 0x02, 0x74, 0xF0, 0x25, 0x15, 0xF5, 0x15, 0x12,
++/*19D0*/0x0E, 0x21, 0xEF, 0xF0, 0x12, 0x10, 0x91, 0x20,
++ 0x34, 0x17, 0xE5, 0x15, 0x64, 0x30, 0x60, 0x0C,
++/*19E0*/0x74, 0x10, 0x25, 0x15, 0xF5, 0x15, 0xB4, 0x80,
++ 0x03, 0xE4, 0xF5, 0x15, 0x12, 0x0E, 0x21, 0xEF,
++/*19F0*/0xF0, 0x22, 0xF0, 0xE5, 0x0B, 0x25, 0xE0, 0x25,
++ 0xE0, 0x24, 0x82, 0xF5, 0x82, 0xE4, 0x34, 0x07,
++/*1A00*/0xF5, 0x83, 0x22, 0x74, 0x88, 0xFE, 0xE5, 0x08,
++ 0x44, 0x07, 0xFF, 0xF5, 0x82, 0x8E, 0x83, 0xE0,
++/*1A10*/0x22, 0xF0, 0xE5, 0x08, 0x44, 0x07, 0xF5, 0x82,
++ 0x22, 0xF0, 0xE0, 0x54, 0xC0, 0x8F, 0x82, 0x8E,
++/*1A20*/0x83, 0xF0, 0x22, 0xEF, 0x44, 0x07, 0xF5, 0x82,
++ 0x75, 0x83, 0x86, 0xE0, 0x54, 0x10, 0xD3, 0x94,
++/*1A30*/0x00, 0x22, 0xF0, 0x90, 0x07, 0x15, 0xE0, 0x04,
++ 0xF0, 0x22, 0x44, 0x06, 0xF5, 0x82, 0x75, 0x83,
++/*1A40*/0x9E, 0xE0, 0x22, 0xFE, 0xEF, 0x44, 0x07, 0xF5,
++ 0x82, 0x8E, 0x83, 0xE0, 0x22, 0xE4, 0x90, 0x07,
++/*1A50*/0x2A, 0xF0, 0xA3, 0xF0, 0x12, 0x07, 0x2A, 0x75,
++ 0x83, 0x82, 0xE0, 0x54, 0x7F, 0x12, 0x07, 0x29,
++/*1A60*/0xE0, 0x44, 0x80, 0xF0, 0x12, 0x10, 0xFC, 0x12,
++ 0x08, 0x1F, 0x75, 0x83, 0xA0, 0xE0, 0x20, 0xE0,
++/*1A70*/0x1A, 0x90, 0x07, 0x2B, 0xE0, 0x04, 0xF0, 0x70,
++ 0x06, 0x90, 0x07, 0x2A, 0xE0, 0x04, 0xF0, 0x90,
++/*1A80*/0x07, 0x2A, 0xE0, 0xB4, 0x10, 0xE1, 0xA3, 0xE0,
++ 0xB4, 0x00, 0xDC, 0xEE, 0x44, 0xA6, 0xFC, 0xEF,
++/*1A90*/0x44, 0x07, 0xF5, 0x82, 0x8C, 0x83, 0xE0, 0xF5,
++ 0x32, 0xEE, 0x44, 0xA8, 0xFE, 0xEF, 0x44, 0x07,
++/*1AA0*/0xF5, 0x82, 0x8E, 0x83, 0xE0, 0xF5, 0x33, 0x22,
++ 0x01, 0x20, 0x11, 0x00, 0x04, 0x20, 0x00, 0x90,
++/*1AB0*/0x00, 0x20, 0x0F, 0x92, 0x00, 0x21, 0x0F, 0x94,
++ 0x00, 0x22, 0x0F, 0x96, 0x00, 0x23, 0x0F, 0x98,
++/*1AC0*/0x00, 0x24, 0x0F, 0x9A, 0x00, 0x25, 0x0F, 0x9C,
++ 0x00, 0x26, 0x0F, 0x9E, 0x00, 0x27, 0x0F, 0xA0,
++/*1AD0*/0x01, 0x20, 0x01, 0xA2, 0x01, 0x21, 0x01, 0xA4,
++ 0x01, 0x22, 0x01, 0xA6, 0x01, 0x23, 0x01, 0xA8,
++/*1AE0*/0x01, 0x24, 0x01, 0xAA, 0x01, 0x25, 0x01, 0xAC,
++ 0x01, 0x26, 0x01, 0xAE, 0x01, 0x27, 0x01, 0xB0,
++/*1AF0*/0x01, 0x28, 0x01, 0xB4, 0x00, 0x28, 0x0F, 0xB6,
++ 0x40, 0x28, 0x0F, 0xB8, 0x61, 0x28, 0x01, 0xCB,
++/*1B00*/0xEF, 0xCB, 0xCA, 0xEE, 0xCA, 0x7F, 0x01, 0xE4,
++ 0xFD, 0xEB, 0x4A, 0x70, 0x24, 0xE5, 0x08, 0xF5,
++/*1B10*/0x82, 0x74, 0xB6, 0x12, 0x08, 0x29, 0xE5, 0x08,
++ 0xF5, 0x82, 0x74, 0xB8, 0x12, 0x08, 0x29, 0xE5,
++/*1B20*/0x08, 0xF5, 0x82, 0x74, 0xBA, 0x12, 0x08, 0x29,
++ 0x7E, 0x00, 0x7C, 0x00, 0x12, 0x0A, 0xFF, 0x80,
++/*1B30*/0x12, 0x90, 0x07, 0x26, 0x12, 0x07, 0x35, 0xE5,
++ 0x41, 0xF0, 0x90, 0x07, 0x24, 0x12, 0x07, 0x35,
++/*1B40*/0xE5, 0x40, 0xF0, 0x12, 0x07, 0x2A, 0x75, 0x83,
++ 0x8E, 0xE4, 0x12, 0x07, 0x29, 0x74, 0x01, 0x12,
++/*1B50*/0x07, 0x29, 0xE4, 0xF0, 0x22, 0xE4, 0xF5, 0x26,
++ 0xF5, 0x27, 0x53, 0xE1, 0xFE, 0xF5, 0x2A, 0x75,
++/*1B60*/0x2B, 0x01, 0xF5, 0x08, 0x7F, 0x01, 0x12, 0x17,
++ 0x31, 0x30, 0x30, 0x1C, 0x90, 0x1A, 0xA9, 0xE4,
++/*1B70*/0x93, 0xF5, 0x10, 0x90, 0x1F, 0xF9, 0xE4, 0x93,
++ 0xF5, 0x10, 0x90, 0x00, 0x41, 0xE4, 0x93, 0xF5,
++/*1B80*/0x10, 0x90, 0x1E, 0xCA, 0xE4, 0x93, 0xF5, 0x10,
++ 0x7F, 0x02, 0x12, 0x17, 0x31, 0x12, 0x0F, 0x54,
++/*1B90*/0x7F, 0x03, 0x12, 0x17, 0x31, 0x12, 0x00, 0x06,
++ 0xE5, 0xE2, 0x30, 0xE7, 0x09, 0x12, 0x10, 0x00,
++/*1BA0*/0x30, 0x30, 0x03, 0x12, 0x11, 0x00, 0x02, 0x00,
++ 0x47, 0x12, 0x08, 0x1F, 0x75, 0x83, 0xD0, 0xE0,
++/*1BB0*/0xC4, 0x54, 0x0F, 0xFD, 0x75, 0x43, 0x01, 0x75,
++ 0x44, 0xFF, 0x12, 0x08, 0xAA, 0x74, 0x04, 0xF0,
++/*1BC0*/0x75, 0x3B, 0x01, 0xED, 0x14, 0x60, 0x0C, 0x14,
++ 0x60, 0x0B, 0x14, 0x60, 0x0F, 0x24, 0x03, 0x70,
++/*1BD0*/0x0B, 0x80, 0x09, 0x80, 0x00, 0x12, 0x08, 0xA7,
++ 0x04, 0xF0, 0x80, 0x06, 0x12, 0x08, 0xA7, 0x74,
++/*1BE0*/0x04, 0xF0, 0xEE, 0x44, 0x82, 0xFE, 0xEF, 0x44,
++ 0x07, 0xF5, 0x82, 0x8E, 0x83, 0xE5, 0x45, 0x12,
++/*1BF0*/0x08, 0xBE, 0x75, 0x83, 0x82, 0xE5, 0x31, 0xF0,
++ 0x02, 0x11, 0x4C, 0x8E, 0x60, 0x8F, 0x61, 0x12,
++/*1C00*/0x1E, 0xA5, 0xE4, 0xFF, 0xCE, 0xED, 0xCE, 0xEE,
++ 0xD3, 0x95, 0x61, 0xE5, 0x60, 0x12, 0x07, 0x6B,
++/*1C10*/0x40, 0x39, 0x74, 0x20, 0x2E, 0xF5, 0x82, 0xE4,
++ 0x34, 0x03, 0xF5, 0x83, 0xE0, 0x70, 0x03, 0xFF,
++/*1C20*/0x80, 0x26, 0x12, 0x08, 0xE2, 0xFD, 0xC3, 0x9F,
++ 0x40, 0x1E, 0xCF, 0xED, 0xCF, 0xEB, 0x4A, 0x70,
++/*1C30*/0x0B, 0x8D, 0x42, 0x12, 0x08, 0xEE, 0xF5, 0x41,
++ 0x8E, 0x40, 0x80, 0x0C, 0x12, 0x08, 0xE2, 0xF5,
++/*1C40*/0x38, 0x12, 0x08, 0xEE, 0xF5, 0x39, 0x8E, 0x3A,
++ 0x1E, 0x80, 0xBC, 0x22, 0x75, 0x58, 0x01, 0xE5,
++/*1C50*/0x35, 0x70, 0x0C, 0x12, 0x07, 0xCC, 0xE0, 0xF5,
++ 0x4A, 0x12, 0x07, 0xD8, 0xE0, 0xF5, 0x4C, 0xE5,
++/*1C60*/0x35, 0xB4, 0x04, 0x0C, 0x12, 0x07, 0xE4, 0xE0,
++ 0xF5, 0x4A, 0x12, 0x07, 0xF0, 0xE0, 0xF5, 0x4C,
++/*1C70*/0xE5, 0x35, 0xB4, 0x01, 0x04, 0x7F, 0x01, 0x80,
++ 0x02, 0x7F, 0x00, 0xE5, 0x35, 0xB4, 0x02, 0x04,
++/*1C80*/0x7E, 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x4F,
++ 0x60, 0x0C, 0x12, 0x07, 0xFC, 0xE0, 0xF5, 0x4A,
++/*1C90*/0x12, 0x08, 0x08, 0xE0, 0xF5, 0x4C, 0x85, 0x41,
++ 0x49, 0x85, 0x40, 0x4B, 0x22, 0x75, 0x5B, 0x01,
++/*1CA0*/0x90, 0x07, 0x24, 0x12, 0x07, 0x35, 0xE0, 0x54,
++ 0x1F, 0xFF, 0xD3, 0x94, 0x02, 0x50, 0x04, 0x8F,
++/*1CB0*/0x58, 0x80, 0x05, 0xEF, 0x24, 0xFE, 0xF5, 0x58,
++ 0xEF, 0xC3, 0x94, 0x18, 0x40, 0x05, 0x75, 0x59,
++/*1CC0*/0x18, 0x80, 0x04, 0xEF, 0x04, 0xF5, 0x59, 0x85,
++ 0x43, 0x5A, 0xAF, 0x58, 0x7E, 0x00, 0xAD, 0x59,
++/*1CD0*/0x7C, 0x00, 0xAB, 0x5B, 0x7A, 0x00, 0x12, 0x15,
++ 0x41, 0xAF, 0x5A, 0x7E, 0x00, 0x12, 0x18, 0x0A,
++/*1CE0*/0xAF, 0x5B, 0x7E, 0x00, 0x02, 0x1A, 0xFF, 0xE5,
++ 0xE2, 0x30, 0xE7, 0x0E, 0x12, 0x10, 0x03, 0xC2,
++/*1CF0*/0x30, 0x30, 0x30, 0x03, 0x12, 0x10, 0xFF, 0x20,
++ 0x33, 0x28, 0xE5, 0xE7, 0x30, 0xE7, 0x05, 0x12,
++/*1D00*/0x0E, 0xA2, 0x80, 0x0D, 0xE5, 0xFE, 0xC3, 0x94,
++ 0x20, 0x50, 0x06, 0x12, 0x0E, 0xA2, 0x43, 0xF9,
++/*1D10*/0x08, 0xE5, 0xF2, 0x30, 0xE7, 0x03, 0x53, 0xF9,
++ 0x7F, 0xE5, 0xF1, 0x54, 0x70, 0xD3, 0x94, 0x00,
++/*1D20*/0x50, 0xD8, 0x22, 0x12, 0x0E, 0x04, 0x75, 0x83,
++ 0x80, 0xE4, 0xF0, 0xE5, 0x08, 0x44, 0x07, 0x12,
++/*1D30*/0x0D, 0xFD, 0x75, 0x83, 0x84, 0x12, 0x0E, 0x02,
++ 0x75, 0x83, 0x86, 0x12, 0x0E, 0x02, 0x75, 0x83,
++/*1D40*/0x8C, 0xE0, 0x54, 0xF3, 0x12, 0x0E, 0x03, 0x75,
++ 0x83, 0x8E, 0x12, 0x0E, 0x02, 0x75, 0x83, 0x94,
++/*1D50*/0xE0, 0x54, 0xFB, 0xF0, 0x22, 0x12, 0x07, 0x2A,
++ 0x75, 0x83, 0x8E, 0xE4, 0x12, 0x07, 0x29, 0x74,
++/*1D60*/0x01, 0x12, 0x07, 0x29, 0xE4, 0x12, 0x08, 0xBE,
++ 0x75, 0x83, 0x8C, 0xE0, 0x44, 0x20, 0x12, 0x08,
++/*1D70*/0xBE, 0xE0, 0x54, 0xDF, 0xF0, 0x74, 0x84, 0x85,
++ 0x08, 0x82, 0xF5, 0x83, 0xE0, 0x54, 0x7F, 0xF0,
++/*1D80*/0xE0, 0x44, 0x80, 0xF0, 0x22, 0x75, 0x56, 0x01,
++ 0xE4, 0xFD, 0xF5, 0x57, 0xAF, 0x35, 0xFE, 0xFC,
++/*1D90*/0x12, 0x09, 0x15, 0x12, 0x1C, 0x9D, 0x12, 0x1E,
++ 0x7A, 0x12, 0x1C, 0x4C, 0xAF, 0x57, 0x7E, 0x00,
++/*1DA0*/0xAD, 0x56, 0x7C, 0x00, 0x12, 0x04, 0x44, 0xAF,
++ 0x56, 0x7E, 0x00, 0x02, 0x11, 0xEE, 0x75, 0x56,
++/*1DB0*/0x01, 0xE4, 0xFD, 0xF5, 0x57, 0xAF, 0x35, 0xFE,
++ 0xFC, 0x12, 0x09, 0x15, 0x12, 0x1C, 0x9D, 0x12,
++/*1DC0*/0x1E, 0x7A, 0x12, 0x1C, 0x4C, 0xAF, 0x57, 0x7E,
++ 0x00, 0xAD, 0x56, 0x7C, 0x00, 0x12, 0x04, 0x44,
++/*1DD0*/0xAF, 0x56, 0x7E, 0x00, 0x02, 0x11, 0xEE, 0xE4,
++ 0xF5, 0x16, 0x12, 0x0E, 0x44, 0xFE, 0xE5, 0x08,
++/*1DE0*/0x44, 0x05, 0xFF, 0x12, 0x0E, 0x65, 0x8F, 0x82,
++ 0x8E, 0x83, 0xF0, 0x05, 0x16, 0xE5, 0x16, 0xC3,
++/*1DF0*/0x94, 0x14, 0x40, 0xE6, 0xE5, 0x08, 0x12, 0x0E,
++ 0x2B, 0xE4, 0xF0, 0x22, 0xE4, 0xF5, 0x58, 0xF5,
++/*1E00*/0x59, 0xF5, 0x5A, 0xFF, 0xFE, 0xAD, 0x58, 0xFC,
++ 0x12, 0x09, 0x15, 0x7F, 0x04, 0x7E, 0x00, 0xAD,
++/*1E10*/0x58, 0x7C, 0x00, 0x12, 0x09, 0x15, 0x7F, 0x02,
++ 0x7E, 0x00, 0xAD, 0x58, 0x7C, 0x00, 0x02, 0x09,
++/*1E20*/0x15, 0xE5, 0x3C, 0x25, 0x3E, 0xFC, 0xE5, 0x42,
++ 0x24, 0x00, 0xFB, 0xE4, 0x33, 0xFA, 0xEC, 0xC3,
++/*1E30*/0x9B, 0xEA, 0x12, 0x07, 0x6B, 0x40, 0x0B, 0x8C,
++ 0x42, 0xE5, 0x3D, 0x25, 0x3F, 0xF5, 0x41, 0x8F,
++/*1E40*/0x40, 0x22, 0x12, 0x09, 0x0B, 0x22, 0x74, 0x84,
++ 0xF5, 0x18, 0x85, 0x08, 0x19, 0x85, 0x19, 0x82,
++/*1E50*/0x85, 0x18, 0x83, 0xE0, 0x54, 0x7F, 0xF0, 0xE0,
++ 0x44, 0x80, 0xF0, 0xE0, 0x44, 0x80, 0xF0, 0x22,
++/*1E60*/0xEF, 0x4E, 0x70, 0x0B, 0x12, 0x07, 0x2A, 0x75,
++ 0x83, 0xD2, 0xE0, 0x54, 0xDF, 0xF0, 0x22, 0x12,
++/*1E70*/0x07, 0x2A, 0x75, 0x83, 0xD2, 0xE0, 0x44, 0x20,
++ 0xF0, 0x22, 0x75, 0x58, 0x01, 0x90, 0x07, 0x26,
++/*1E80*/0x12, 0x07, 0x35, 0xE0, 0x54, 0x3F, 0xF5, 0x41,
++ 0x12, 0x07, 0x32, 0xE0, 0x54, 0x3F, 0xF5, 0x40,
++/*1E90*/0x22, 0x75, 0x56, 0x02, 0xE4, 0xF5, 0x57, 0x12,
++ 0x1D, 0xFC, 0xAF, 0x57, 0x7E, 0x00, 0xAD, 0x56,
++/*1EA0*/0x7C, 0x00, 0x02, 0x04, 0x44, 0xE4, 0xF5, 0x42,
++ 0xF5, 0x41, 0xF5, 0x40, 0xF5, 0x38, 0xF5, 0x39,
++/*1EB0*/0xF5, 0x3A, 0x22, 0xEF, 0x54, 0x07, 0xFF, 0xE5,
++ 0xF9, 0x54, 0xF8, 0x4F, 0xF5, 0xF9, 0x22, 0x7F,
++/*1EC0*/0x01, 0xE4, 0xFE, 0x0F, 0x0E, 0xBE, 0xFF, 0xFB,
++ 0x22, 0x01, 0x20, 0x00, 0x01, 0x04, 0x20, 0x00,
++/*1ED0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1EE0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1EF0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F00*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F10*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F20*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F30*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F40*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F50*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F60*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F70*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F80*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1F90*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1FA0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1FB0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1FC0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1FD0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1FE0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++/*1FF0*/0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x01, 0x20, 0x11, 0x00, 0x04, 0x20, 0x00, 0x81
++};
++
++int ipath_sd7220_ib_load(struct ipath_devdata *dd)
++{
++ return ipath_sd7220_prog_ld(dd, IB_7220_SERDES, ipath_sd7220_ib_img,
++ sizeof(ipath_sd7220_ib_img), 0);
++}
++
++int ipath_sd7220_ib_vfy(struct ipath_devdata *dd)
++{
++ return ipath_sd7220_prog_vfy(dd, IB_7220_SERDES, ipath_sd7220_ib_img,
++ sizeof(ipath_sd7220_ib_img), 0);
++}
+diff --git a/drivers/infiniband/hw/ipath/ipath_sdma.c b/drivers/infiniband/hw/ipath/ipath_sdma.c
+new file mode 100644
+index 0000000..1974df7
+--- /dev/null
++++ b/drivers/infiniband/hw/ipath/ipath_sdma.c
+@@ -0,0 +1,790 @@
++/*
++ * Copyright (c) 2007, 2008 QLogic Corporation. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses. You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ * Redistribution and use in source and binary forms, with or
++ * without modification, are permitted provided that the following
++ * conditions are met:
++ *
++ * - Redistributions of source code must retain the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer.
++ *
++ * - Redistributions in binary form must reproduce the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer in the documentation and/or other materials
++ * provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <linux/spinlock.h>
++
++#include "ipath_kernel.h"
++#include "ipath_verbs.h"
++#include "ipath_common.h"
++
++#define SDMA_DESCQ_SZ PAGE_SIZE /* 256 entries per 4KB page */
++
++static void vl15_watchdog_enq(struct ipath_devdata *dd)
++{
++ /* ipath_sdma_lock must already be held */
++ if (atomic_inc_return(&dd->ipath_sdma_vl15_count) == 1) {
++ unsigned long interval = (HZ + 19) / 20;
++ dd->ipath_sdma_vl15_timer.expires = jiffies + interval;
++ add_timer(&dd->ipath_sdma_vl15_timer);
++ }
++}
++
++static void vl15_watchdog_deq(struct ipath_devdata *dd)
++{
++ /* ipath_sdma_lock must already be held */
++ if (atomic_dec_return(&dd->ipath_sdma_vl15_count) != 0) {
++ unsigned long interval = (HZ + 19) / 20;
++ mod_timer(&dd->ipath_sdma_vl15_timer, jiffies + interval);
++ } else {
++ del_timer(&dd->ipath_sdma_vl15_timer);
++ }
++}
++
++static void vl15_watchdog_timeout(unsigned long opaque)
++{
++ struct ipath_devdata *dd = (struct ipath_devdata *)opaque;
++
++ if (atomic_read(&dd->ipath_sdma_vl15_count) != 0) {
++ ipath_dbg("vl15 watchdog timeout - clearing\n");
++ ipath_cancel_sends(dd, 1);
++ ipath_hol_down(dd);
++ } else {
++ ipath_dbg("vl15 watchdog timeout - "
++ "condition already cleared\n");
++ }
++}
++
++static void unmap_desc(struct ipath_devdata *dd, unsigned head)
++{
++ __le64 *descqp = &dd->ipath_sdma_descq[head].qw[0];
++ u64 desc[2];
++ dma_addr_t addr;
++ size_t len;
++
++ desc[0] = le64_to_cpu(descqp[0]);
++ desc[1] = le64_to_cpu(descqp[1]);
++
++ addr = (desc[1] << 32) | (desc[0] >> 32);
++ len = (desc[0] >> 14) & (0x7ffULL << 2);
++ dma_unmap_single(&dd->pcidev->dev, addr, len, DMA_TO_DEVICE);
++}
++
++/*
++ * ipath_sdma_lock should be locked before calling this.
++ */
++int ipath_sdma_make_progress(struct ipath_devdata *dd)
++{
++ struct list_head *lp = NULL;
++ struct ipath_sdma_txreq *txp = NULL;
++ u16 dmahead;
++ u16 start_idx = 0;
++ int progress = 0;
++
++ if (!list_empty(&dd->ipath_sdma_activelist)) {
++ lp = dd->ipath_sdma_activelist.next;
++ txp = list_entry(lp, struct ipath_sdma_txreq, list);
++ start_idx = txp->start_idx;
++ }
++
++ /*
++ * Read the SDMA head register in order to know that the
++ * interrupt clear has been written to the chip.
++ * Otherwise, we may not get an interrupt for the last
++ * descriptor in the queue.
++ */
++ dmahead = (u16)ipath_read_kreg32(dd, dd->ipath_kregs->kr_senddmahead);
++ /* sanity check return value for error handling (chip reset, etc.) */
++ if (dmahead >= dd->ipath_sdma_descq_cnt)
++ goto done;
++
++ while (dd->ipath_sdma_descq_head != dmahead) {
++ if (txp && txp->flags & IPATH_SDMA_TXREQ_F_FREEDESC &&
++ dd->ipath_sdma_descq_head == start_idx) {
++ unmap_desc(dd, dd->ipath_sdma_descq_head);
++ start_idx++;
++ if (start_idx == dd->ipath_sdma_descq_cnt)
++ start_idx = 0;
++ }
++
++ /* increment free count and head */
++ dd->ipath_sdma_descq_removed++;
++ if (++dd->ipath_sdma_descq_head == dd->ipath_sdma_descq_cnt)
++ dd->ipath_sdma_descq_head = 0;
++
++ if (txp && txp->next_descq_idx == dd->ipath_sdma_descq_head) {
++ /* move to notify list */
++ if (txp->flags & IPATH_SDMA_TXREQ_F_VL15)
++ vl15_watchdog_deq(dd);
++ list_move_tail(lp, &dd->ipath_sdma_notifylist);
++ if (!list_empty(&dd->ipath_sdma_activelist)) {
++ lp = dd->ipath_sdma_activelist.next;
++ txp = list_entry(lp, struct ipath_sdma_txreq,
++ list);
++ start_idx = txp->start_idx;
++ } else {
++ lp = NULL;
++ txp = NULL;
++ }
++ }
++ progress = 1;
++ }
++
++ if (progress)
++ tasklet_hi_schedule(&dd->ipath_sdma_notify_task);
++
++done:
++ return progress;
++}
++
++static void ipath_sdma_notify(struct ipath_devdata *dd, struct list_head *list)
++{
++ struct ipath_sdma_txreq *txp, *txp_next;
++
++ list_for_each_entry_safe(txp, txp_next, list, list) {
++ list_del_init(&txp->list);
++
++ if (txp->callback)
++ (*txp->callback)(txp->callback_cookie,
++ txp->callback_status);
++ }
++}
++
++static void sdma_notify_taskbody(struct ipath_devdata *dd)
++{
++ unsigned long flags;
++ struct list_head list;
++
++ INIT_LIST_HEAD(&list);
++
++ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++
++ list_splice_init(&dd->ipath_sdma_notifylist, &list);
++
++ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++
++ ipath_sdma_notify(dd, &list);
++
++ /*
++ * The IB verbs layer needs to see the callback before getting
++ * the call to ipath_ib_piobufavail() because the callback
++ * handles releasing resources the next send will need.
++ * Otherwise, we could do these calls in
++ * ipath_sdma_make_progress().
++ */
++ ipath_ib_piobufavail(dd->verbs_dev);
++}
++
++static void sdma_notify_task(unsigned long opaque)
++{
++ struct ipath_devdata *dd = (struct ipath_devdata *)opaque;
++
++ if (!test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status))
++ sdma_notify_taskbody(dd);
++}
++
++static void dump_sdma_state(struct ipath_devdata *dd)
++{
++ unsigned long reg;
++
++ reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmastatus);
++ ipath_cdbg(VERBOSE, "kr_senddmastatus: 0x%016lx\n", reg);
++
++ reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendctrl);
++ ipath_cdbg(VERBOSE, "kr_sendctrl: 0x%016lx\n", reg);
++
++ reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmabufmask0);
++ ipath_cdbg(VERBOSE, "kr_senddmabufmask0: 0x%016lx\n", reg);
++
++ reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmabufmask1);
++ ipath_cdbg(VERBOSE, "kr_senddmabufmask1: 0x%016lx\n", reg);
++
++ reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmabufmask2);
++ ipath_cdbg(VERBOSE, "kr_senddmabufmask2: 0x%016lx\n", reg);
++
++ reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmatail);
++ ipath_cdbg(VERBOSE, "kr_senddmatail: 0x%016lx\n", reg);
++
++ reg = ipath_read_kreg64(dd, dd->ipath_kregs->kr_senddmahead);
++ ipath_cdbg(VERBOSE, "kr_senddmahead: 0x%016lx\n", reg);
++}
++
++static void sdma_abort_task(unsigned long opaque)
++{
++ struct ipath_devdata *dd = (struct ipath_devdata *) opaque;
++ u64 status;
++ unsigned long flags;
++
++ if (test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status))
++ return;
++
++ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++
++ status = dd->ipath_sdma_status & IPATH_SDMA_ABORT_MASK;
++
++ /* nothing to do */
++ if (status == IPATH_SDMA_ABORT_NONE)
++ goto unlock;
++
++ /* ipath_sdma_abort() is done, waiting for interrupt */
++ if (status == IPATH_SDMA_ABORT_DISARMED) {
++ if (jiffies < dd->ipath_sdma_abort_intr_timeout)
++ goto resched_noprint;
++ /* give up, intr got lost somewhere */
++ ipath_dbg("give up waiting for SDMADISABLED intr\n");
++ __set_bit(IPATH_SDMA_DISABLED, &dd->ipath_sdma_status);
++ status = IPATH_SDMA_ABORT_ABORTED;
++ }
++
++ /* everything is stopped, time to clean up and restart */
++ if (status == IPATH_SDMA_ABORT_ABORTED) {
++ struct ipath_sdma_txreq *txp, *txpnext;
++ u64 hwstatus;
++ int notify = 0;
++
++ hwstatus = ipath_read_kreg64(dd,
++ dd->ipath_kregs->kr_senddmastatus);
++
++ if (/* ScoreBoardDrainInProg */
++ test_bit(63, &hwstatus) ||
++ /* AbortInProg */
++ test_bit(62, &hwstatus) ||
++ /* InternalSDmaEnable */
++ test_bit(61, &hwstatus) ||
++ /* ScbEmpty */
++ !test_bit(30, &hwstatus)) {
++ if (dd->ipath_sdma_reset_wait > 0) {
++ /* not done shutting down sdma */
++ --dd->ipath_sdma_reset_wait;
++ goto resched;
++ }
++ ipath_cdbg(VERBOSE, "gave up waiting for quiescent "
++ "status after SDMA reset, continuing\n");
++ dump_sdma_state(dd);
++ }
++
++ /* dequeue all "sent" requests */
++ list_for_each_entry_safe(txp, txpnext,
++ &dd->ipath_sdma_activelist, list) {
++ txp->callback_status = IPATH_SDMA_TXREQ_S_ABORTED;
++ if (txp->flags & IPATH_SDMA_TXREQ_F_VL15)
++ vl15_watchdog_deq(dd);
++ list_move_tail(&txp->list, &dd->ipath_sdma_notifylist);
++ notify = 1;
++ }
++ if (notify)
++ tasklet_hi_schedule(&dd->ipath_sdma_notify_task);
++
++ /* reset our notion of head and tail */
++ dd->ipath_sdma_descq_tail = 0;
++ dd->ipath_sdma_descq_head = 0;
++ dd->ipath_sdma_head_dma[0] = 0;
++ dd->ipath_sdma_generation = 0;
++ dd->ipath_sdma_descq_removed = dd->ipath_sdma_descq_added;
++
++ /* Reset SendDmaLenGen */
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmalengen,
++ (u64) dd->ipath_sdma_descq_cnt | (1ULL << 18));
++
++ /* done with sdma state for a bit */
++ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++
++ /*
++ * Don't restart sdma here. Wait until link is up to ACTIVE.
++ * VL15 MADs used to bring the link up use PIO, and multiple
++ * link transitions otherwise cause the sdma engine to be
++ * stopped and started multiple times.
++ * The disable is done here, including the shadow, so the
++ * state is kept consistent.
++ * See ipath_restart_sdma() for the actual starting of sdma.
++ */
++ spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++ dd->ipath_sendctrl &= ~INFINIPATH_S_SDMAENABLE;
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
++ dd->ipath_sendctrl);
++ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++ spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++
++ /* make sure I see next message */
++ dd->ipath_sdma_abort_jiffies = 0;
++
++ goto done;
++ }
++
++resched:
++ /*
++ * for now, keep spinning
++ * JAG - this is bad to just have default be a loop without
++ * state change
++ */
++ if (jiffies > dd->ipath_sdma_abort_jiffies) {
++ ipath_dbg("looping with status 0x%016llx\n",
++ dd->ipath_sdma_status);
++ dd->ipath_sdma_abort_jiffies = jiffies + 5 * HZ;
++ }
++resched_noprint:
++ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++ if (!test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status))
++ tasklet_hi_schedule(&dd->ipath_sdma_abort_task);
++ return;
++
++unlock:
++ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++done:
++ return;
++}
++
++/*
++ * This is called from interrupt context.
++ */
++void ipath_sdma_intr(struct ipath_devdata *dd)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++
++ (void) ipath_sdma_make_progress(dd);
++
++ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++}
++
++static int alloc_sdma(struct ipath_devdata *dd)
++{
++ int ret = 0;
++
++ /* Allocate memory for SendDMA descriptor FIFO */
++ dd->ipath_sdma_descq = dma_alloc_coherent(&dd->pcidev->dev,
++ SDMA_DESCQ_SZ, &dd->ipath_sdma_descq_phys, GFP_KERNEL);
++
++ if (!dd->ipath_sdma_descq) {
++ ipath_dev_err(dd, "failed to allocate SendDMA descriptor "
++ "FIFO memory\n");
++ ret = -ENOMEM;
++ goto done;
++ }
++
++ dd->ipath_sdma_descq_cnt =
++ SDMA_DESCQ_SZ / sizeof(struct ipath_sdma_desc);
++
++ /* Allocate memory for DMA of head register to memory */
++ dd->ipath_sdma_head_dma = dma_alloc_coherent(&dd->pcidev->dev,
++ PAGE_SIZE, &dd->ipath_sdma_head_phys, GFP_KERNEL);
++ if (!dd->ipath_sdma_head_dma) {
++ ipath_dev_err(dd, "failed to allocate SendDMA head memory\n");
++ ret = -ENOMEM;
++ goto cleanup_descq;
++ }
++ dd->ipath_sdma_head_dma[0] = 0;
++
++ init_timer(&dd->ipath_sdma_vl15_timer);
++ dd->ipath_sdma_vl15_timer.function = vl15_watchdog_timeout;
++ dd->ipath_sdma_vl15_timer.data = (unsigned long)dd;
++ atomic_set(&dd->ipath_sdma_vl15_count, 0);
++
++ goto done;
++
++cleanup_descq:
++ dma_free_coherent(&dd->pcidev->dev, SDMA_DESCQ_SZ,
++ (void *)dd->ipath_sdma_descq, dd->ipath_sdma_descq_phys);
++ dd->ipath_sdma_descq = NULL;
++ dd->ipath_sdma_descq_phys = 0;
++done:
++ return ret;
++}
++
++int setup_sdma(struct ipath_devdata *dd)
++{
++ int ret = 0;
++ unsigned i, n;
++ u64 tmp64;
++ u64 senddmabufmask[3] = { 0 };
++ unsigned long flags;
++
++ ret = alloc_sdma(dd);
++ if (ret)
++ goto done;
++
++ if (!dd->ipath_sdma_descq) {
++ ipath_dev_err(dd, "SendDMA memory not allocated\n");
++ goto done;
++ }
++
++ dd->ipath_sdma_status = 0;
++ dd->ipath_sdma_abort_jiffies = 0;
++ dd->ipath_sdma_generation = 0;
++ dd->ipath_sdma_descq_tail = 0;
++ dd->ipath_sdma_descq_head = 0;
++ dd->ipath_sdma_descq_removed = 0;
++ dd->ipath_sdma_descq_added = 0;
++
++ /* Set SendDmaBase */
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabase,
++ dd->ipath_sdma_descq_phys);
++ /* Set SendDmaLenGen */
++ tmp64 = dd->ipath_sdma_descq_cnt;
++ tmp64 |= 1<<18; /* enable generation checking */
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmalengen, tmp64);
++ /* Set SendDmaTail */
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmatail,
++ dd->ipath_sdma_descq_tail);
++ /* Set SendDmaHeadAddr */
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmaheadaddr,
++ dd->ipath_sdma_head_phys);
++
++ /* Reserve all the former "kernel" piobufs */
++ n = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - dd->ipath_pioreserved;
++ for (i = dd->ipath_lastport_piobuf; i < n; ++i) {
++ unsigned word = i / 64;
++ unsigned bit = i & 63;
++ BUG_ON(word >= 3);
++ senddmabufmask[word] |= 1ULL << bit;
++ }
++ ipath_chg_pioavailkernel(dd, dd->ipath_lastport_piobuf,
++ n - dd->ipath_lastport_piobuf, 0);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabufmask0,
++ senddmabufmask[0]);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabufmask1,
++ senddmabufmask[1]);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabufmask2,
++ senddmabufmask[2]);
++
++ INIT_LIST_HEAD(&dd->ipath_sdma_activelist);
++ INIT_LIST_HEAD(&dd->ipath_sdma_notifylist);
++
++ tasklet_init(&dd->ipath_sdma_notify_task, sdma_notify_task,
++ (unsigned long) dd);
++ tasklet_init(&dd->ipath_sdma_abort_task, sdma_abort_task,
++ (unsigned long) dd);
++
++ /*
++ * No use to turn on SDMA here, as link is probably not ACTIVE
++ * Just mark it RUNNING and enable the interrupt, and let the
++ * ipath_restart_sdma() on link transition to ACTIVE actually
++ * enable it.
++ */
++ spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++ dd->ipath_sendctrl |= INFINIPATH_S_SDMAINTENABLE;
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
++ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++ __set_bit(IPATH_SDMA_RUNNING, &dd->ipath_sdma_status);
++ spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++
++done:
++ return ret;
++}
++
++void teardown_sdma(struct ipath_devdata *dd)
++{
++ struct ipath_sdma_txreq *txp, *txpnext;
++ unsigned long flags;
++ dma_addr_t sdma_head_phys = 0;
++ dma_addr_t sdma_descq_phys = 0;
++ void *sdma_descq = NULL;
++ void *sdma_head_dma = NULL;
++
++ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++ __clear_bit(IPATH_SDMA_RUNNING, &dd->ipath_sdma_status);
++ __set_bit(IPATH_SDMA_ABORTING, &dd->ipath_sdma_status);
++ __set_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status);
++ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++
++ tasklet_kill(&dd->ipath_sdma_abort_task);
++ tasklet_kill(&dd->ipath_sdma_notify_task);
++
++ /* turn off sdma */
++ spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++ dd->ipath_sendctrl &= ~INFINIPATH_S_SDMAENABLE;
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
++ dd->ipath_sendctrl);
++ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++ spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++
++ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++ /* dequeue all "sent" requests */
++ list_for_each_entry_safe(txp, txpnext, &dd->ipath_sdma_activelist,
++ list) {
++ txp->callback_status = IPATH_SDMA_TXREQ_S_SHUTDOWN;
++ if (txp->flags & IPATH_SDMA_TXREQ_F_VL15)
++ vl15_watchdog_deq(dd);
++ list_move_tail(&txp->list, &dd->ipath_sdma_notifylist);
++ }
++ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++
++ sdma_notify_taskbody(dd);
++
++ del_timer_sync(&dd->ipath_sdma_vl15_timer);
++
++ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++
++ dd->ipath_sdma_abort_jiffies = 0;
++
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabase, 0);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmalengen, 0);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmatail, 0);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmaheadaddr, 0);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabufmask0, 0);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabufmask1, 0);
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmabufmask2, 0);
++
++ if (dd->ipath_sdma_head_dma) {
++ sdma_head_dma = (void *) dd->ipath_sdma_head_dma;
++ sdma_head_phys = dd->ipath_sdma_head_phys;
++ dd->ipath_sdma_head_dma = NULL;
++ dd->ipath_sdma_head_phys = 0;
++ }
++
++ if (dd->ipath_sdma_descq) {
++ sdma_descq = dd->ipath_sdma_descq;
++ sdma_descq_phys = dd->ipath_sdma_descq_phys;
++ dd->ipath_sdma_descq = NULL;
++ dd->ipath_sdma_descq_phys = 0;
++ }
++
++ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++
++ if (sdma_head_dma)
++ dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE,
++ sdma_head_dma, sdma_head_phys);
++
++ if (sdma_descq)
++ dma_free_coherent(&dd->pcidev->dev, SDMA_DESCQ_SZ,
++ sdma_descq, sdma_descq_phys);
++}
++
++/*
++ * [Re]start SDMA, if we use it, and it's not already OK.
++ * This is called on transition to link ACTIVE, either the first or
++ * subsequent times.
++ */
++void ipath_restart_sdma(struct ipath_devdata *dd)
++{
++ unsigned long flags;
++ int needed = 1;
++
++ if (!(dd->ipath_flags & IPATH_HAS_SEND_DMA))
++ goto bail;
++
++ /*
++ * First, make sure we should, which is to say,
++ * check that we are "RUNNING" (not in teardown)
++ * and not "SHUTDOWN"
++ */
++ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++ if (!test_bit(IPATH_SDMA_RUNNING, &dd->ipath_sdma_status)
++ || test_bit(IPATH_SDMA_SHUTDOWN, &dd->ipath_sdma_status))
++ needed = 0;
++ else {
++ __clear_bit(IPATH_SDMA_DISABLED, &dd->ipath_sdma_status);
++ __clear_bit(IPATH_SDMA_DISARMED, &dd->ipath_sdma_status);
++ __clear_bit(IPATH_SDMA_ABORTING, &dd->ipath_sdma_status);
++ }
++ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++ if (!needed) {
++ ipath_dbg("invalid attempt to restart SDMA, status 0x%016llx\n",
++ dd->ipath_sdma_status);
++ goto bail;
++ }
++ spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++ /*
++ * First clear, just to be safe. Enable is only done
++ * in chip on 0->1 transition
++ */
++ dd->ipath_sendctrl &= ~INFINIPATH_S_SDMAENABLE;
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
++ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++ dd->ipath_sendctrl |= INFINIPATH_S_SDMAENABLE;
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
++ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++ spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++
++bail:
++ return;
++}
++
++static inline void make_sdma_desc(struct ipath_devdata *dd,
++ u64 *sdmadesc, u64 addr, u64 dwlen, u64 dwoffset)
++{
++ WARN_ON(addr & 3);
++ /* SDmaPhyAddr[47:32] */
++ sdmadesc[1] = addr >> 32;
++ /* SDmaPhyAddr[31:0] */
++ sdmadesc[0] = (addr & 0xfffffffcULL) << 32;
++ /* SDmaGeneration[1:0] */
++ sdmadesc[0] |= (dd->ipath_sdma_generation & 3ULL) << 30;
++ /* SDmaDwordCount[10:0] */
++ sdmadesc[0] |= (dwlen & 0x7ffULL) << 16;
++ /* SDmaBufOffset[12:2] */
++ sdmadesc[0] |= dwoffset & 0x7ffULL;
++}
++
++/*
++ * This function queues one IB packet onto the send DMA queue per call.
++ * The caller is responsible for checking:
++ * 1) The number of send DMA descriptor entries is less than the size of
++ * the descriptor queue.
++ * 2) The IB SGE addresses and lengths are 32-bit aligned
++ * (except possibly the last SGE's length)
++ * 3) The SGE addresses are suitable for passing to dma_map_single().
++ */
++int ipath_sdma_verbs_send(struct ipath_devdata *dd,
++ struct ipath_sge_state *ss, u32 dwords,
++ struct ipath_verbs_txreq *tx)
++{
++
++ unsigned long flags;
++ struct ipath_sge *sge;
++ int ret = 0;
++ u16 tail;
++ __le64 *descqp;
++ u64 sdmadesc[2];
++ u32 dwoffset;
++ dma_addr_t addr;
++
++ if ((tx->map_len + (dwords<<2)) > dd->ipath_ibmaxlen) {
++ ipath_dbg("packet size %X > ibmax %X, fail\n",
++ tx->map_len + (dwords<<2), dd->ipath_ibmaxlen);
++ ret = -EMSGSIZE;
++ goto fail;
++ }
++
++ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++
++retry:
++ if (unlikely(test_bit(IPATH_SDMA_ABORTING, &dd->ipath_sdma_status))) {
++ ret = -EBUSY;
++ goto unlock;
++ }
++
++ if (tx->txreq.sg_count > ipath_sdma_descq_freecnt(dd)) {
++ if (ipath_sdma_make_progress(dd))
++ goto retry;
++ ret = -ENOBUFS;
++ goto unlock;
++ }
++
++ addr = dma_map_single(&dd->pcidev->dev, tx->txreq.map_addr,
++ tx->map_len, DMA_TO_DEVICE);
++ if (dma_mapping_error(addr)) {
++ ret = -EIO;
++ goto unlock;
++ }
++
++ dwoffset = tx->map_len >> 2;
++ make_sdma_desc(dd, sdmadesc, (u64) addr, dwoffset, 0);
++
++ /* SDmaFirstDesc */
++ sdmadesc[0] |= 1ULL << 12;
++ if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_USELARGEBUF)
++ sdmadesc[0] |= 1ULL << 14; /* SDmaUseLargeBuf */
++
++ /* write to the descq */
++ tail = dd->ipath_sdma_descq_tail;
++ descqp = &dd->ipath_sdma_descq[tail].qw[0];
++ *descqp++ = cpu_to_le64(sdmadesc[0]);
++ *descqp++ = cpu_to_le64(sdmadesc[1]);
++
++ if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_FREEDESC)
++ tx->txreq.start_idx = tail;
++
++ /* increment the tail */
++ if (++tail == dd->ipath_sdma_descq_cnt) {
++ tail = 0;
++ descqp = &dd->ipath_sdma_descq[0].qw[0];
++ ++dd->ipath_sdma_generation;
++ }
++
++ sge = &ss->sge;
++ while (dwords) {
++ u32 dw;
++ u32 len;
++
++ len = dwords << 2;
++ if (len > sge->length)
++ len = sge->length;
++ if (len > sge->sge_length)
++ len = sge->sge_length;
++ BUG_ON(len == 0);
++ dw = (len + 3) >> 2;
++ addr = dma_map_single(&dd->pcidev->dev, sge->vaddr, dw << 2,
++ DMA_TO_DEVICE);
++ make_sdma_desc(dd, sdmadesc, (u64) addr, dw, dwoffset);
++ /* SDmaUseLargeBuf has to be set in every descriptor */
++ if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_USELARGEBUF)
++ sdmadesc[0] |= 1ULL << 14;
++ /* write to the descq */
++ *descqp++ = cpu_to_le64(sdmadesc[0]);
++ *descqp++ = cpu_to_le64(sdmadesc[1]);
++
++ /* increment the tail */
++ if (++tail == dd->ipath_sdma_descq_cnt) {
++ tail = 0;
++ descqp = &dd->ipath_sdma_descq[0].qw[0];
++ ++dd->ipath_sdma_generation;
++ }
++ sge->vaddr += len;
++ sge->length -= len;
++ sge->sge_length -= len;
++ if (sge->sge_length == 0) {
++ if (--ss->num_sge)
++ *sge = *ss->sg_list++;
++ } else if (sge->length == 0 && sge->mr != NULL) {
++ if (++sge->n >= IPATH_SEGSZ) {
++ if (++sge->m >= sge->mr->mapsz)
++ break;
++ sge->n = 0;
++ }
++ sge->vaddr =
++ sge->mr->map[sge->m]->segs[sge->n].vaddr;
++ sge->length =
++ sge->mr->map[sge->m]->segs[sge->n].length;
++ }
++
++ dwoffset += dw;
++ dwords -= dw;
++ }
++
++ if (!tail)
++ descqp = &dd->ipath_sdma_descq[dd->ipath_sdma_descq_cnt].qw[0];
++ descqp -= 2;
++ /* SDmaLastDesc */
++ descqp[0] |= __constant_cpu_to_le64(1ULL << 11);
++ if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_INTREQ) {
++ /* SDmaIntReq */
++ descqp[0] |= __constant_cpu_to_le64(1ULL << 15);
++ }
++
++ /* Commit writes to memory and advance the tail on the chip */
++ wmb();
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmatail, tail);
++
++ tx->txreq.next_descq_idx = tail;
++ tx->txreq.callback_status = IPATH_SDMA_TXREQ_S_OK;
++ dd->ipath_sdma_descq_tail = tail;
++ dd->ipath_sdma_descq_added += tx->txreq.sg_count;
++ list_add_tail(&tx->txreq.list, &dd->ipath_sdma_activelist);
++ if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_VL15)
++ vl15_watchdog_enq(dd);
++
++unlock:
++ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++fail:
++ return ret;
++}
+diff --git a/drivers/infiniband/hw/ipath/ipath_srq.c b/drivers/infiniband/hw/ipath/ipath_srq.c
+index f772102..e3d80ca 100644
+--- a/drivers/infiniband/hw/ipath/ipath_srq.c
++++ b/drivers/infiniband/hw/ipath/ipath_srq.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+@@ -245,7 +245,8 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+ sizeof(offset_addr));
+ if (ret)
+ goto bail_free;
+- udata->outbuf = (void __user *) offset_addr;
++ udata->outbuf =
++ (void __user *) (unsigned long) offset_addr;
+ ret = ib_copy_to_udata(udata, &offset,
+ sizeof(offset));
+ if (ret)
+diff --git a/drivers/infiniband/hw/ipath/ipath_stats.c b/drivers/infiniband/hw/ipath/ipath_stats.c
+index d2725cd..c8e3d65 100644
+--- a/drivers/infiniband/hw/ipath/ipath_stats.c
++++ b/drivers/infiniband/hw/ipath/ipath_stats.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+@@ -136,6 +136,7 @@ static void ipath_qcheck(struct ipath_devdata *dd)
+ struct ipath_portdata *pd = dd->ipath_pd[0];
+ size_t blen = 0;
+ char buf[128];
++ u32 hdrqtail;
+
+ *buf = 0;
+ if (pd->port_hdrqfull != dd->ipath_p0_hdrqfull) {
+@@ -174,17 +175,18 @@ static void ipath_qcheck(struct ipath_devdata *dd)
+ if (blen)
+ ipath_dbg("%s\n", buf);
+
+- if (pd->port_head != (u32)
+- le64_to_cpu(*dd->ipath_hdrqtailptr)) {
++ hdrqtail = ipath_get_hdrqtail(pd);
++ if (pd->port_head != hdrqtail) {
+ if (dd->ipath_lastport0rcv_cnt ==
+ ipath_stats.sps_port0pkts) {
+ ipath_cdbg(PKT, "missing rcv interrupts? "
+- "port0 hd=%llx tl=%x; port0pkts %llx\n",
+- (unsigned long long)
+- le64_to_cpu(*dd->ipath_hdrqtailptr),
+- pd->port_head,
++ "port0 hd=%x tl=%x; port0pkts %llx; write"
++ " hd (w/intr)\n",
++ pd->port_head, hdrqtail,
+ (unsigned long long)
+ ipath_stats.sps_port0pkts);
++ ipath_write_ureg(dd, ur_rcvhdrhead, hdrqtail |
++ dd->ipath_rhdrhead_intr_off, pd->port_port);
+ }
+ dd->ipath_lastport0rcv_cnt = ipath_stats.sps_port0pkts;
+ }
+@@ -290,11 +292,11 @@ void ipath_get_faststats(unsigned long opaque)
+ && time_after(jiffies, dd->ipath_unmasktime)) {
+ char ebuf[256];
+ int iserr;
+- iserr = ipath_decode_err(ebuf, sizeof ebuf,
+- dd->ipath_maskederrs);
++ iserr = ipath_decode_err(dd, ebuf, sizeof ebuf,
++ dd->ipath_maskederrs);
+ if (dd->ipath_maskederrs &
+- ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL |
+- INFINIPATH_E_PKTERRS ))
++ ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL |
++ INFINIPATH_E_PKTERRS))
+ ipath_dev_err(dd, "Re-enabling masked errors "
+ "(%s)\n", ebuf);
+ else {
+@@ -306,17 +308,18 @@ void ipath_get_faststats(unsigned long opaque)
+ * level.
+ */
+ if (iserr)
+- ipath_dbg("Re-enabling queue full errors (%s)\n",
+- ebuf);
++ ipath_dbg(
++ "Re-enabling queue full errors (%s)\n",
++ ebuf);
+ else
+ ipath_cdbg(ERRPKT, "Re-enabling packet"
+- " problem interrupt (%s)\n", ebuf);
++ " problem interrupt (%s)\n", ebuf);
+ }
+
+ /* re-enable masked errors */
+ dd->ipath_errormask |= dd->ipath_maskederrs;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
+- dd->ipath_errormask);
++ dd->ipath_errormask);
+ dd->ipath_maskederrs = 0;
+ }
+
+diff --git a/drivers/infiniband/hw/ipath/ipath_sysfs.c b/drivers/infiniband/hw/ipath/ipath_sysfs.c
+index 56dfc8a..a6c8efb 100644
+--- a/drivers/infiniband/hw/ipath/ipath_sysfs.c
++++ b/drivers/infiniband/hw/ipath/ipath_sysfs.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+@@ -34,6 +34,7 @@
+ #include <linux/ctype.h>
+
+ #include "ipath_kernel.h"
++#include "ipath_verbs.h"
+ #include "ipath_common.h"
+
+ /**
+@@ -163,6 +164,15 @@ static ssize_t show_boardversion(struct device *dev,
+ return scnprintf(buf, PAGE_SIZE, "%s", dd->ipath_boardversion);
+ }
+
++static ssize_t show_localbus_info(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct ipath_devdata *dd = dev_get_drvdata(dev);
++ /* The string printed here is already newline-terminated. */
++ return scnprintf(buf, PAGE_SIZE, "%s", dd->ipath_lbus_info);
++}
++
+ static ssize_t show_lmc(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+@@ -311,6 +321,8 @@ static ssize_t store_guid(struct device *dev,
+
+ dd->ipath_guid = new_guid;
+ dd->ipath_nguid = 1;
++ if (dd->verbs_dev)
++ dd->verbs_dev->ibdev.node_guid = new_guid;
+
+ ret = strlen(buf);
+ goto bail;
+@@ -919,21 +931,21 @@ static ssize_t store_rx_polinv_enb(struct device *dev,
+ u16 val;
+
+ ret = ipath_parse_ushort(buf, &val);
+- if (ret < 0 || val > 1)
+- goto invalid;
++ if (ret >= 0 && val > 1) {
++ ipath_dev_err(dd,
++ "attempt to set invalid Rx Polarity (enable)\n");
++ ret = -EINVAL;
++ goto bail;
++ }
+
+ r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_RXPOL_ENB, val);
+- if (r < 0) {
++ if (r < 0)
+ ret = r;
+- goto bail;
+- }
+
+- goto bail;
+-invalid:
+- ipath_dev_err(dd, "attempt to set invalid Rx Polarity (enable)\n");
+ bail:
+ return ret;
+ }
++
+ /*
+ * Get/Set RX lane-reversal enable. 0=no, 1=yes.
+ */
+@@ -988,6 +1000,75 @@ static struct attribute_group driver_attr_group = {
+ .attrs = driver_attributes
+ };
+
++static ssize_t store_tempsense(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf,
++ size_t count)
++{
++ struct ipath_devdata *dd = dev_get_drvdata(dev);
++ int ret, stat;
++ u16 val;
++
++ ret = ipath_parse_ushort(buf, &val);
++ if (ret <= 0) {
++ ipath_dev_err(dd, "attempt to set invalid tempsense config\n");
++ goto bail;
++ }
++ /* If anything but the highest limit, enable T_CRIT_A "interrupt" */
++ stat = ipath_tempsense_write(dd, 9, (val == 0x7f7f) ? 0x80 : 0);
++ if (stat) {
++ ipath_dev_err(dd, "Unable to set tempsense config\n");
++ ret = -1;
++ goto bail;
++ }
++ stat = ipath_tempsense_write(dd, 0xB, (u8) (val & 0xFF));
++ if (stat) {
++ ipath_dev_err(dd, "Unable to set local Tcrit\n");
++ ret = -1;
++ goto bail;
++ }
++ stat = ipath_tempsense_write(dd, 0xD, (u8) (val >> 8));
++ if (stat) {
++ ipath_dev_err(dd, "Unable to set remote Tcrit\n");
++ ret = -1;
++ goto bail;
++ }
++
++bail:
++ return ret;
++}
++
++/*
++ * dump tempsense regs. in decimal, to ease shell-scripts.
++ */
++static ssize_t show_tempsense(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct ipath_devdata *dd = dev_get_drvdata(dev);
++ int ret;
++ int idx;
++ u8 regvals[8];
++
++ ret = -ENXIO;
++ for (idx = 0; idx < 8; ++idx) {
++ if (idx == 6)
++ continue;
++ ret = ipath_tempsense_read(dd, idx);
++ if (ret < 0)
++ break;
++ regvals[idx] = ret;
++ }
++ if (idx == 8)
++ ret = scnprintf(buf, PAGE_SIZE, "%d %d %02X %02X %d %d\n",
++ *(signed char *)(regvals),
++ *(signed char *)(regvals + 1),
++ regvals[2], regvals[3],
++ *(signed char *)(regvals + 5),
++ *(signed char *)(regvals + 7));
++ return ret;
++}
++
+ struct attribute_group *ipath_driver_attr_groups[] = {
+ &driver_attr_group,
+ NULL,
+@@ -1011,10 +1092,13 @@ static DEVICE_ATTR(unit, S_IRUGO, show_unit, NULL);
+ static DEVICE_ATTR(rx_pol_inv, S_IWUSR, NULL, store_rx_pol_inv);
+ static DEVICE_ATTR(led_override, S_IWUSR, NULL, store_led_override);
+ static DEVICE_ATTR(logged_errors, S_IRUGO, show_logged_errs, NULL);
++static DEVICE_ATTR(localbus_info, S_IRUGO, show_localbus_info, NULL);
+ static DEVICE_ATTR(jint_max_packets, S_IWUSR | S_IRUGO,
+ show_jint_max_packets, store_jint_max_packets);
+ static DEVICE_ATTR(jint_idle_ticks, S_IWUSR | S_IRUGO,
+ show_jint_idle_ticks, store_jint_idle_ticks);
++static DEVICE_ATTR(tempsense, S_IWUSR | S_IRUGO,
++ show_tempsense, store_tempsense);
+
+ static struct attribute *dev_attributes[] = {
+ &dev_attr_guid.attr,
+@@ -1034,6 +1118,8 @@ static struct attribute *dev_attributes[] = {
+ &dev_attr_rx_pol_inv.attr,
+ &dev_attr_led_override.attr,
+ &dev_attr_logged_errors.attr,
++ &dev_attr_tempsense.attr,
++ &dev_attr_localbus_info.attr,
+ NULL
+ };
+
+diff --git a/drivers/infiniband/hw/ipath/ipath_uc.c b/drivers/infiniband/hw/ipath/ipath_uc.c
+index 2dd8de2..bfe8926 100644
+--- a/drivers/infiniband/hw/ipath/ipath_uc.c
++++ b/drivers/infiniband/hw/ipath/ipath_uc.c
+@@ -94,7 +94,7 @@ int ipath_make_uc_req(struct ipath_qp *qp)
+ qp->s_state =
+ OP(SEND_ONLY_WITH_IMMEDIATE);
+ /* Immediate data comes after the BTH */
+- ohdr->u.imm_data = wqe->wr.imm_data;
++ ohdr->u.imm_data = wqe->wr.ex.imm_data;
+ hwords += 1;
+ }
+ if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+@@ -123,7 +123,7 @@ int ipath_make_uc_req(struct ipath_qp *qp)
+ qp->s_state =
+ OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE);
+ /* Immediate data comes after the RETH */
+- ohdr->u.rc.imm_data = wqe->wr.imm_data;
++ ohdr->u.rc.imm_data = wqe->wr.ex.imm_data;
+ hwords += 1;
+ if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ bth0 |= 1 << 23;
+@@ -152,7 +152,7 @@ int ipath_make_uc_req(struct ipath_qp *qp)
+ else {
+ qp->s_state = OP(SEND_LAST_WITH_IMMEDIATE);
+ /* Immediate data comes after the BTH */
+- ohdr->u.imm_data = wqe->wr.imm_data;
++ ohdr->u.imm_data = wqe->wr.ex.imm_data;
+ hwords += 1;
+ }
+ if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+@@ -177,7 +177,7 @@ int ipath_make_uc_req(struct ipath_qp *qp)
+ qp->s_state =
+ OP(RDMA_WRITE_LAST_WITH_IMMEDIATE);
+ /* Immediate data comes after the BTH */
+- ohdr->u.imm_data = wqe->wr.imm_data;
++ ohdr->u.imm_data = wqe->wr.ex.imm_data;
+ hwords += 1;
+ if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+ bth0 |= 1 << 23;
+diff --git a/drivers/infiniband/hw/ipath/ipath_ud.c b/drivers/infiniband/hw/ipath/ipath_ud.c
+index de67eed..8b6a261 100644
+--- a/drivers/infiniband/hw/ipath/ipath_ud.c
++++ b/drivers/infiniband/hw/ipath/ipath_ud.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+@@ -95,7 +95,7 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_swqe *swqe)
+
+ if (swqe->wr.opcode == IB_WR_SEND_WITH_IMM) {
+ wc.wc_flags = IB_WC_WITH_IMM;
+- wc.imm_data = swqe->wr.imm_data;
++ wc.imm_data = swqe->wr.ex.imm_data;
+ } else {
+ wc.wc_flags = 0;
+ wc.imm_data = 0;
+@@ -303,6 +303,7 @@ int ipath_make_ud_req(struct ipath_qp *qp)
+ qp->s_hdrwords = 7;
+ qp->s_cur_size = wqe->length;
+ qp->s_cur_sge = &qp->s_sge;
++ qp->s_dmult = ah_attr->static_rate;
+ qp->s_wqe = wqe;
+ qp->s_sge.sge = wqe->sg_list[0];
+ qp->s_sge.sg_list = wqe->sg_list + 1;
+@@ -326,7 +327,7 @@ int ipath_make_ud_req(struct ipath_qp *qp)
+ }
+ if (wqe->wr.opcode == IB_WR_SEND_WITH_IMM) {
+ qp->s_hdrwords++;
+- ohdr->u.ud.imm_data = wqe->wr.imm_data;
++ ohdr->u.ud.imm_data = wqe->wr.ex.imm_data;
+ bth0 = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE << 24;
+ } else
+ bth0 = IB_OPCODE_UD_SEND_ONLY << 24;
+diff --git a/drivers/infiniband/hw/ipath/ipath_user_sdma.c b/drivers/infiniband/hw/ipath/ipath_user_sdma.c
+new file mode 100644
+index 0000000..86e0169
+--- /dev/null
++++ b/drivers/infiniband/hw/ipath/ipath_user_sdma.c
+@@ -0,0 +1,879 @@
++/*
++ * Copyright (c) 2007, 2008 QLogic Corporation. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses. You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ * Redistribution and use in source and binary forms, with or
++ * without modification, are permitted provided that the following
++ * conditions are met:
++ *
++ * - Redistributions of source code must retain the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer.
++ *
++ * - Redistributions in binary form must reproduce the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer in the documentation and/or other materials
++ * provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++#include <linux/mm.h>
++#include <linux/types.h>
++#include <linux/device.h>
++#include <linux/dmapool.h>
++#include <linux/slab.h>
++#include <linux/list.h>
++#include <linux/highmem.h>
++#include <linux/io.h>
++#include <linux/uio.h>
++#include <linux/rbtree.h>
++#include <linux/spinlock.h>
++#include <linux/delay.h>
++
++#include "ipath_kernel.h"
++#include "ipath_user_sdma.h"
++
++/* minimum size of header */
++#define IPATH_USER_SDMA_MIN_HEADER_LENGTH 64
++/* expected size of headers (for dma_pool) */
++#define IPATH_USER_SDMA_EXP_HEADER_LENGTH 64
++/* length mask in PBC (lower 11 bits) */
++#define IPATH_PBC_LENGTH_MASK ((1 << 11) - 1)
++
++struct ipath_user_sdma_pkt {
++ u8 naddr; /* dimension of addr (1..3) ... */
++ u32 counter; /* sdma pkts queued counter for this entry */
++ u64 added; /* global descq number of entries */
++
++ struct {
++ u32 offset; /* offset for kvaddr, addr */
++ u32 length; /* length in page */
++ u8 put_page; /* should we put_page? */
++ u8 dma_mapped; /* is page dma_mapped? */
++ struct page *page; /* may be NULL (coherent mem) */
++ void *kvaddr; /* FIXME: only for pio hack */
++ dma_addr_t addr;
++ } addr[4]; /* max pages, any more and we coalesce */
++ struct list_head list; /* list element */
++};
++
++struct ipath_user_sdma_queue {
++ /*
++ * pkts sent to dma engine are queued on this
++ * list head. the type of the elements of this
++ * list are struct ipath_user_sdma_pkt...
++ */
++ struct list_head sent;
++
++ /* headers with expected length are allocated from here... */
++ char header_cache_name[64];
++ struct dma_pool *header_cache;
++
++ /* packets are allocated from the slab cache... */
++ char pkt_slab_name[64];
++ struct kmem_cache *pkt_slab;
++
++ /* as packets go on the queued queue, they are counted... */
++ u32 counter;
++ u32 sent_counter;
++
++ /* dma page table */
++ struct rb_root dma_pages_root;
++
++ /* protect everything above... */
++ struct mutex lock;
++};
++
++struct ipath_user_sdma_queue *
++ipath_user_sdma_queue_create(struct device *dev, int unit, int port, int sport)
++{
++ struct ipath_user_sdma_queue *pq =
++ kmalloc(sizeof(struct ipath_user_sdma_queue), GFP_KERNEL);
++
++ if (!pq)
++ goto done;
++
++ pq->counter = 0;
++ pq->sent_counter = 0;
++ INIT_LIST_HEAD(&pq->sent);
++
++ mutex_init(&pq->lock);
++
++ snprintf(pq->pkt_slab_name, sizeof(pq->pkt_slab_name),
++ "ipath-user-sdma-pkts-%u-%02u.%02u", unit, port, sport);
++ pq->pkt_slab = kmem_cache_create(pq->pkt_slab_name,
++ sizeof(struct ipath_user_sdma_pkt),
++ 0, 0, NULL);
++
++ if (!pq->pkt_slab)
++ goto err_kfree;
++
++ snprintf(pq->header_cache_name, sizeof(pq->header_cache_name),
++ "ipath-user-sdma-headers-%u-%02u.%02u", unit, port, sport);
++ pq->header_cache = dma_pool_create(pq->header_cache_name,
++ dev,
++ IPATH_USER_SDMA_EXP_HEADER_LENGTH,
++ 4, 0);
++ if (!pq->header_cache)
++ goto err_slab;
++
++ pq->dma_pages_root = RB_ROOT;
++
++ goto done;
++
++err_slab:
++ kmem_cache_destroy(pq->pkt_slab);
++err_kfree:
++ kfree(pq);
++ pq = NULL;
++
++done:
++ return pq;
++}
++
++static void ipath_user_sdma_init_frag(struct ipath_user_sdma_pkt *pkt,
++ int i, size_t offset, size_t len,
++ int put_page, int dma_mapped,
++ struct page *page,
++ void *kvaddr, dma_addr_t dma_addr)
++{
++ pkt->addr[i].offset = offset;
++ pkt->addr[i].length = len;
++ pkt->addr[i].put_page = put_page;
++ pkt->addr[i].dma_mapped = dma_mapped;
++ pkt->addr[i].page = page;
++ pkt->addr[i].kvaddr = kvaddr;
++ pkt->addr[i].addr = dma_addr;
++}
++
++static void ipath_user_sdma_init_header(struct ipath_user_sdma_pkt *pkt,
++ u32 counter, size_t offset,
++ size_t len, int dma_mapped,
++ struct page *page,
++ void *kvaddr, dma_addr_t dma_addr)
++{
++ pkt->naddr = 1;
++ pkt->counter = counter;
++ ipath_user_sdma_init_frag(pkt, 0, offset, len, 0, dma_mapped, page,
++ kvaddr, dma_addr);
++}
++
++/* we've too many pages in the iovec, coalesce to a single page */
++static int ipath_user_sdma_coalesce(const struct ipath_devdata *dd,
++ struct ipath_user_sdma_pkt *pkt,
++ const struct iovec *iov,
++ unsigned long niov) {
++ int ret = 0;
++ struct page *page = alloc_page(GFP_KERNEL);
++ void *mpage_save;
++ char *mpage;
++ int i;
++ int len = 0;
++ dma_addr_t dma_addr;
++
++ if (!page) {
++ ret = -ENOMEM;
++ goto done;
++ }
++
++ mpage = kmap(page);
++ mpage_save = mpage;
++ for (i = 0; i < niov; i++) {
++ int cfur;
++
++ cfur = copy_from_user(mpage,
++ iov[i].iov_base, iov[i].iov_len);
++ if (cfur) {
++ ret = -EFAULT;
++ goto free_unmap;
++ }
++
++ mpage += iov[i].iov_len;
++ len += iov[i].iov_len;
++ }
++
++ dma_addr = dma_map_page(&dd->pcidev->dev, page, 0, len,
++ DMA_TO_DEVICE);
++ if (dma_mapping_error(dma_addr)) {
++ ret = -ENOMEM;
++ goto free_unmap;
++ }
++
++ ipath_user_sdma_init_frag(pkt, 1, 0, len, 0, 1, page, mpage_save,
++ dma_addr);
++ pkt->naddr = 2;
++
++ goto done;
++
++free_unmap:
++ kunmap(page);
++ __free_page(page);
++done:
++ return ret;
++}
++
++/* how many pages in this iovec element? */
++static int ipath_user_sdma_num_pages(const struct iovec *iov)
++{
++ const unsigned long addr = (unsigned long) iov->iov_base;
++ const unsigned long len = iov->iov_len;
++ const unsigned long spage = addr & PAGE_MASK;
++ const unsigned long epage = (addr + len - 1) & PAGE_MASK;
++
++ return 1 + ((epage - spage) >> PAGE_SHIFT);
++}
++
++/* truncate length to page boundry */
++static int ipath_user_sdma_page_length(unsigned long addr, unsigned long len)
++{
++ const unsigned long offset = addr & ~PAGE_MASK;
++
++ return ((offset + len) > PAGE_SIZE) ? (PAGE_SIZE - offset) : len;
++}
++
++static void ipath_user_sdma_free_pkt_frag(struct device *dev,
++ struct ipath_user_sdma_queue *pq,
++ struct ipath_user_sdma_pkt *pkt,
++ int frag)
++{
++ const int i = frag;
++
++ if (pkt->addr[i].page) {
++ if (pkt->addr[i].dma_mapped)
++ dma_unmap_page(dev,
++ pkt->addr[i].addr,
++ pkt->addr[i].length,
++ DMA_TO_DEVICE);
++
++ if (pkt->addr[i].kvaddr)
++ kunmap(pkt->addr[i].page);
++
++ if (pkt->addr[i].put_page)
++ put_page(pkt->addr[i].page);
++ else
++ __free_page(pkt->addr[i].page);
++ } else if (pkt->addr[i].kvaddr)
++ /* free coherent mem from cache... */
++ dma_pool_free(pq->header_cache,
++ pkt->addr[i].kvaddr, pkt->addr[i].addr);
++}
++
++/* return number of pages pinned... */
++static int ipath_user_sdma_pin_pages(const struct ipath_devdata *dd,
++ struct ipath_user_sdma_pkt *pkt,
++ unsigned long addr, int tlen, int npages)
++{
++ struct page *pages[2];
++ int j;
++ int ret;
++
++ ret = get_user_pages(current, current->mm, addr,
++ npages, 0, 1, pages, NULL);
++
++ if (ret != npages) {
++ int i;
++
++ for (i = 0; i < ret; i++)
++ put_page(pages[i]);
++
++ ret = -ENOMEM;
++ goto done;
++ }
++
++ for (j = 0; j < npages; j++) {
++ /* map the pages... */
++ const int flen =
++ ipath_user_sdma_page_length(addr, tlen);
++ dma_addr_t dma_addr =
++ dma_map_page(&dd->pcidev->dev,
++ pages[j], 0, flen, DMA_TO_DEVICE);
++ unsigned long fofs = addr & ~PAGE_MASK;
++
++ if (dma_mapping_error(dma_addr)) {
++ ret = -ENOMEM;
++ goto done;
++ }
++
++ ipath_user_sdma_init_frag(pkt, pkt->naddr, fofs, flen, 1, 1,
++ pages[j], kmap(pages[j]),
++ dma_addr);
++
++ pkt->naddr++;
++ addr += flen;
++ tlen -= flen;
++ }
++
++done:
++ return ret;
++}
++
++static int ipath_user_sdma_pin_pkt(const struct ipath_devdata *dd,
++ struct ipath_user_sdma_queue *pq,
++ struct ipath_user_sdma_pkt *pkt,
++ const struct iovec *iov,
++ unsigned long niov)
++{
++ int ret = 0;
++ unsigned long idx;
++
++ for (idx = 0; idx < niov; idx++) {
++ const int npages = ipath_user_sdma_num_pages(iov + idx);
++ const unsigned long addr = (unsigned long) iov[idx].iov_base;
++
++ ret = ipath_user_sdma_pin_pages(dd, pkt,
++ addr, iov[idx].iov_len,
++ npages);
++ if (ret < 0)
++ goto free_pkt;
++ }
++
++ goto done;
++
++free_pkt:
++ for (idx = 0; idx < pkt->naddr; idx++)
++ ipath_user_sdma_free_pkt_frag(&dd->pcidev->dev, pq, pkt, idx);
++
++done:
++ return ret;
++}
++
++static int ipath_user_sdma_init_payload(const struct ipath_devdata *dd,
++ struct ipath_user_sdma_queue *pq,
++ struct ipath_user_sdma_pkt *pkt,
++ const struct iovec *iov,
++ unsigned long niov, int npages)
++{
++ int ret = 0;
++
++ if (npages >= ARRAY_SIZE(pkt->addr))
++ ret = ipath_user_sdma_coalesce(dd, pkt, iov, niov);
++ else
++ ret = ipath_user_sdma_pin_pkt(dd, pq, pkt, iov, niov);
++
++ return ret;
++}
++
++/* free a packet list -- return counter value of last packet */
++static void ipath_user_sdma_free_pkt_list(struct device *dev,
++ struct ipath_user_sdma_queue *pq,
++ struct list_head *list)
++{
++ struct ipath_user_sdma_pkt *pkt, *pkt_next;
++
++ list_for_each_entry_safe(pkt, pkt_next, list, list) {
++ int i;
++
++ for (i = 0; i < pkt->naddr; i++)
++ ipath_user_sdma_free_pkt_frag(dev, pq, pkt, i);
++
++ kmem_cache_free(pq->pkt_slab, pkt);
++ }
++}
++
++/*
++ * copy headers, coalesce etc -- pq->lock must be held
++ *
++ * we queue all the packets to list, returning the
++ * number of bytes total. list must be empty initially,
++ * as, if there is an error we clean it...
++ */
++static int ipath_user_sdma_queue_pkts(const struct ipath_devdata *dd,
++ struct ipath_user_sdma_queue *pq,
++ struct list_head *list,
++ const struct iovec *iov,
++ unsigned long niov,
++ int maxpkts)
++{
++ unsigned long idx = 0;
++ int ret = 0;
++ int npkts = 0;
++ struct page *page = NULL;
++ __le32 *pbc;
++ dma_addr_t dma_addr;
++ struct ipath_user_sdma_pkt *pkt = NULL;
++ size_t len;
++ size_t nw;
++ u32 counter = pq->counter;
++ int dma_mapped = 0;
++
++ while (idx < niov && npkts < maxpkts) {
++ const unsigned long addr = (unsigned long) iov[idx].iov_base;
++ const unsigned long idx_save = idx;
++ unsigned pktnw;
++ unsigned pktnwc;
++ int nfrags = 0;
++ int npages = 0;
++ int cfur;
++
++ dma_mapped = 0;
++ len = iov[idx].iov_len;
++ nw = len >> 2;
++ page = NULL;
++
++ pkt = kmem_cache_alloc(pq->pkt_slab, GFP_KERNEL);
++ if (!pkt) {
++ ret = -ENOMEM;
++ goto free_list;
++ }
++
++ if (len < IPATH_USER_SDMA_MIN_HEADER_LENGTH ||
++ len > PAGE_SIZE || len & 3 || addr & 3) {
++ ret = -EINVAL;
++ goto free_pkt;
++ }
++
++ if (len == IPATH_USER_SDMA_EXP_HEADER_LENGTH)
++ pbc = dma_pool_alloc(pq->header_cache, GFP_KERNEL,
++ &dma_addr);
++ else
++ pbc = NULL;
++
++ if (!pbc) {
++ page = alloc_page(GFP_KERNEL);
++ if (!page) {
++ ret = -ENOMEM;
++ goto free_pkt;
++ }
++ pbc = kmap(page);
++ }
++
++ cfur = copy_from_user(pbc, iov[idx].iov_base, len);
++ if (cfur) {
++ ret = -EFAULT;
++ goto free_pbc;
++ }
++
++ /*
++ * this assignment is a bit strange. it's because the
++ * the pbc counts the number of 32 bit words in the full
++ * packet _except_ the first word of the pbc itself...
++ */
++ pktnwc = nw - 1;
++
++ /*
++ * pktnw computation yields the number of 32 bit words
++ * that the caller has indicated in the PBC. note that
++ * this is one less than the total number of words that
++ * goes to the send DMA engine as the first 32 bit word
++ * of the PBC itself is not counted. Armed with this count,
++ * we can verify that the packet is consistent with the
++ * iovec lengths.
++ */
++ pktnw = le32_to_cpu(*pbc) & IPATH_PBC_LENGTH_MASK;
++ if (pktnw < pktnwc || pktnw > pktnwc + (PAGE_SIZE >> 2)) {
++ ret = -EINVAL;
++ goto free_pbc;
++ }
++
++
++ idx++;
++ while (pktnwc < pktnw && idx < niov) {
++ const size_t slen = iov[idx].iov_len;
++ const unsigned long faddr =
++ (unsigned long) iov[idx].iov_base;
++
++ if (slen & 3 || faddr & 3 || !slen ||
++ slen > PAGE_SIZE) {
++ ret = -EINVAL;
++ goto free_pbc;
++ }
++
++ npages++;
++ if ((faddr & PAGE_MASK) !=
++ ((faddr + slen - 1) & PAGE_MASK))
++ npages++;
++
++ pktnwc += slen >> 2;
++ idx++;
++ nfrags++;
++ }
++
++ if (pktnwc != pktnw) {
++ ret = -EINVAL;
++ goto free_pbc;
++ }
++
++ if (page) {
++ dma_addr = dma_map_page(&dd->pcidev->dev,
++ page, 0, len, DMA_TO_DEVICE);
++ if (dma_mapping_error(dma_addr)) {
++ ret = -ENOMEM;
++ goto free_pbc;
++ }
++
++ dma_mapped = 1;
++ }
++
++ ipath_user_sdma_init_header(pkt, counter, 0, len, dma_mapped,
++ page, pbc, dma_addr);
++
++ if (nfrags) {
++ ret = ipath_user_sdma_init_payload(dd, pq, pkt,
++ iov + idx_save + 1,
++ nfrags, npages);
++ if (ret < 0)
++ goto free_pbc_dma;
++ }
++
++ counter++;
++ npkts++;
++
++ list_add_tail(&pkt->list, list);
++ }
++
++ ret = idx;
++ goto done;
++
++free_pbc_dma:
++ if (dma_mapped)
++ dma_unmap_page(&dd->pcidev->dev, dma_addr, len, DMA_TO_DEVICE);
++free_pbc:
++ if (page) {
++ kunmap(page);
++ __free_page(page);
++ } else
++ dma_pool_free(pq->header_cache, pbc, dma_addr);
++free_pkt:
++ kmem_cache_free(pq->pkt_slab, pkt);
++free_list:
++ ipath_user_sdma_free_pkt_list(&dd->pcidev->dev, pq, list);
++done:
++ return ret;
++}
++
++static void ipath_user_sdma_set_complete_counter(struct ipath_user_sdma_queue *pq,
++ u32 c)
++{
++ pq->sent_counter = c;
++}
++
++/* try to clean out queue -- needs pq->lock */
++static int ipath_user_sdma_queue_clean(const struct ipath_devdata *dd,
++ struct ipath_user_sdma_queue *pq)
++{
++ struct list_head free_list;
++ struct ipath_user_sdma_pkt *pkt;
++ struct ipath_user_sdma_pkt *pkt_prev;
++ int ret = 0;
++
++ INIT_LIST_HEAD(&free_list);
++
++ list_for_each_entry_safe(pkt, pkt_prev, &pq->sent, list) {
++ s64 descd = dd->ipath_sdma_descq_removed - pkt->added;
++
++ if (descd < 0)
++ break;
++
++ list_move_tail(&pkt->list, &free_list);
++
++ /* one more packet cleaned */
++ ret++;
++ }
++
++ if (!list_empty(&free_list)) {
++ u32 counter;
++
++ pkt = list_entry(free_list.prev,
++ struct ipath_user_sdma_pkt, list);
++ counter = pkt->counter;
++
++ ipath_user_sdma_free_pkt_list(&dd->pcidev->dev, pq, &free_list);
++ ipath_user_sdma_set_complete_counter(pq, counter);
++ }
++
++ return ret;
++}
++
++void ipath_user_sdma_queue_destroy(struct ipath_user_sdma_queue *pq)
++{
++ if (!pq)
++ return;
++
++ kmem_cache_destroy(pq->pkt_slab);
++ dma_pool_destroy(pq->header_cache);
++ kfree(pq);
++}
++
++/* clean descriptor queue, returns > 0 if some elements cleaned */
++static int ipath_user_sdma_hwqueue_clean(struct ipath_devdata *dd)
++{
++ int ret;
++ unsigned long flags;
++
++ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++ ret = ipath_sdma_make_progress(dd);
++ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++
++ return ret;
++}
++
++/* we're in close, drain packets so that we can cleanup successfully... */
++void ipath_user_sdma_queue_drain(struct ipath_devdata *dd,
++ struct ipath_user_sdma_queue *pq)
++{
++ int i;
++
++ if (!pq)
++ return;
++
++ for (i = 0; i < 100; i++) {
++ mutex_lock(&pq->lock);
++ if (list_empty(&pq->sent)) {
++ mutex_unlock(&pq->lock);
++ break;
++ }
++ ipath_user_sdma_hwqueue_clean(dd);
++ ipath_user_sdma_queue_clean(dd, pq);
++ mutex_unlock(&pq->lock);
++ msleep(10);
++ }
++
++ if (!list_empty(&pq->sent)) {
++ struct list_head free_list;
++
++ printk(KERN_INFO "drain: lists not empty: forcing!\n");
++ INIT_LIST_HEAD(&free_list);
++ mutex_lock(&pq->lock);
++ list_splice_init(&pq->sent, &free_list);
++ ipath_user_sdma_free_pkt_list(&dd->pcidev->dev, pq, &free_list);
++ mutex_unlock(&pq->lock);
++ }
++}
++
++static inline __le64 ipath_sdma_make_desc0(struct ipath_devdata *dd,
++ u64 addr, u64 dwlen, u64 dwoffset)
++{
++ return cpu_to_le64(/* SDmaPhyAddr[31:0] */
++ ((addr & 0xfffffffcULL) << 32) |
++ /* SDmaGeneration[1:0] */
++ ((dd->ipath_sdma_generation & 3ULL) << 30) |
++ /* SDmaDwordCount[10:0] */
++ ((dwlen & 0x7ffULL) << 16) |
++ /* SDmaBufOffset[12:2] */
++ (dwoffset & 0x7ffULL));
++}
++
++static inline __le64 ipath_sdma_make_first_desc0(__le64 descq)
++{
++ return descq | __constant_cpu_to_le64(1ULL << 12);
++}
++
++static inline __le64 ipath_sdma_make_last_desc0(__le64 descq)
++{
++ /* last */ /* dma head */
++ return descq | __constant_cpu_to_le64(1ULL << 11 | 1ULL << 13);
++}
++
++static inline __le64 ipath_sdma_make_desc1(u64 addr)
++{
++ /* SDmaPhyAddr[47:32] */
++ return cpu_to_le64(addr >> 32);
++}
++
++static void ipath_user_sdma_send_frag(struct ipath_devdata *dd,
++ struct ipath_user_sdma_pkt *pkt, int idx,
++ unsigned ofs, u16 tail)
++{
++ const u64 addr = (u64) pkt->addr[idx].addr +
++ (u64) pkt->addr[idx].offset;
++ const u64 dwlen = (u64) pkt->addr[idx].length / 4;
++ __le64 *descqp;
++ __le64 descq0;
++
++ descqp = &dd->ipath_sdma_descq[tail].qw[0];
++
++ descq0 = ipath_sdma_make_desc0(dd, addr, dwlen, ofs);
++ if (idx == 0)
++ descq0 = ipath_sdma_make_first_desc0(descq0);
++ if (idx == pkt->naddr - 1)
++ descq0 = ipath_sdma_make_last_desc0(descq0);
++
++ descqp[0] = descq0;
++ descqp[1] = ipath_sdma_make_desc1(addr);
++}
++
++/* pq->lock must be held, get packets on the wire... */
++static int ipath_user_sdma_push_pkts(struct ipath_devdata *dd,
++ struct ipath_user_sdma_queue *pq,
++ struct list_head *pktlist)
++{
++ int ret = 0;
++ unsigned long flags;
++ u16 tail;
++
++ if (list_empty(pktlist))
++ return 0;
++
++ if (unlikely(!(dd->ipath_flags & IPATH_LINKACTIVE)))
++ return -ECOMM;
++
++ spin_lock_irqsave(&dd->ipath_sdma_lock, flags);
++
++ if (unlikely(dd->ipath_sdma_status & IPATH_SDMA_ABORT_MASK)) {
++ ret = -ECOMM;
++ goto unlock;
++ }
++
++ tail = dd->ipath_sdma_descq_tail;
++ while (!list_empty(pktlist)) {
++ struct ipath_user_sdma_pkt *pkt =
++ list_entry(pktlist->next, struct ipath_user_sdma_pkt,
++ list);
++ int i;
++ unsigned ofs = 0;
++ u16 dtail = tail;
++
++ if (pkt->naddr > ipath_sdma_descq_freecnt(dd))
++ goto unlock_check_tail;
++
++ for (i = 0; i < pkt->naddr; i++) {
++ ipath_user_sdma_send_frag(dd, pkt, i, ofs, tail);
++ ofs += pkt->addr[i].length >> 2;
++
++ if (++tail == dd->ipath_sdma_descq_cnt) {
++ tail = 0;
++ ++dd->ipath_sdma_generation;
++ }
++ }
++
++ if ((ofs<<2) > dd->ipath_ibmaxlen) {
++ ipath_dbg("packet size %X > ibmax %X, fail\n",
++ ofs<<2, dd->ipath_ibmaxlen);
++ ret = -EMSGSIZE;
++ goto unlock;
++ }
++
++ /*
++ * if the packet is >= 2KB mtu equivalent, we have to use
++ * the large buffers, and have to mark each descriptor as
++ * part of a large buffer packet.
++ */
++ if (ofs >= IPATH_SMALLBUF_DWORDS) {
++ for (i = 0; i < pkt->naddr; i++) {
++ dd->ipath_sdma_descq[dtail].qw[0] |=
++ __constant_cpu_to_le64(1ULL << 14);
++ if (++dtail == dd->ipath_sdma_descq_cnt)
++ dtail = 0;
++ }
++ }
++
++ dd->ipath_sdma_descq_added += pkt->naddr;
++ pkt->added = dd->ipath_sdma_descq_added;
++ list_move_tail(&pkt->list, &pq->sent);
++ ret++;
++ }
++
++unlock_check_tail:
++ /* advance the tail on the chip if necessary */
++ if (dd->ipath_sdma_descq_tail != tail) {
++ wmb();
++ ipath_write_kreg(dd, dd->ipath_kregs->kr_senddmatail, tail);
++ dd->ipath_sdma_descq_tail = tail;
++ }
++
++unlock:
++ spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
++
++ return ret;
++}
++
++int ipath_user_sdma_writev(struct ipath_devdata *dd,
++ struct ipath_user_sdma_queue *pq,
++ const struct iovec *iov,
++ unsigned long dim)
++{
++ int ret = 0;
++ struct list_head list;
++ int npkts = 0;
++
++ INIT_LIST_HEAD(&list);
++
++ mutex_lock(&pq->lock);
++
++ if (dd->ipath_sdma_descq_added != dd->ipath_sdma_descq_removed) {
++ ipath_user_sdma_hwqueue_clean(dd);
++ ipath_user_sdma_queue_clean(dd, pq);
++ }
++
++ while (dim) {
++ const int mxp = 8;
++
++ down_write(¤t->mm->mmap_sem);
++ ret = ipath_user_sdma_queue_pkts(dd, pq, &list, iov, dim, mxp);
++ up_write(¤t->mm->mmap_sem);
++
++ if (ret <= 0)
++ goto done_unlock;
++ else {
++ dim -= ret;
++ iov += ret;
++ }
++
++ /* force packets onto the sdma hw queue... */
++ if (!list_empty(&list)) {
++ /*
++ * lazily clean hw queue. the 4 is a guess of about
++ * how many sdma descriptors a packet will take (it
++ * doesn't have to be perfect).
++ */
++ if (ipath_sdma_descq_freecnt(dd) < ret * 4) {
++ ipath_user_sdma_hwqueue_clean(dd);
++ ipath_user_sdma_queue_clean(dd, pq);
++ }
++
++ ret = ipath_user_sdma_push_pkts(dd, pq, &list);
++ if (ret < 0)
++ goto done_unlock;
++ else {
++ npkts += ret;
++ pq->counter += ret;
++
++ if (!list_empty(&list))
++ goto done_unlock;
++ }
++ }
++ }
++
++done_unlock:
++ if (!list_empty(&list))
++ ipath_user_sdma_free_pkt_list(&dd->pcidev->dev, pq, &list);
++ mutex_unlock(&pq->lock);
++
++ return (ret < 0) ? ret : npkts;
++}
++
++int ipath_user_sdma_make_progress(struct ipath_devdata *dd,
++ struct ipath_user_sdma_queue *pq)
++{
++ int ret = 0;
++
++ mutex_lock(&pq->lock);
++ ipath_user_sdma_hwqueue_clean(dd);
++ ret = ipath_user_sdma_queue_clean(dd, pq);
++ mutex_unlock(&pq->lock);
++
++ return ret;
++}
++
++u32 ipath_user_sdma_complete_counter(const struct ipath_user_sdma_queue *pq)
++{
++ return pq->sent_counter;
++}
++
++u32 ipath_user_sdma_inflight_counter(struct ipath_user_sdma_queue *pq)
++{
++ return pq->counter;
++}
++
+diff --git a/drivers/infiniband/hw/ipath/ipath_user_sdma.h b/drivers/infiniband/hw/ipath/ipath_user_sdma.h
+new file mode 100644
+index 0000000..e70946c
+--- /dev/null
++++ b/drivers/infiniband/hw/ipath/ipath_user_sdma.h
+@@ -0,0 +1,54 @@
++/*
++ * Copyright (c) 2007, 2008 QLogic Corporation. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses. You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ * Redistribution and use in source and binary forms, with or
++ * without modification, are permitted provided that the following
++ * conditions are met:
++ *
++ * - Redistributions of source code must retain the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer.
++ *
++ * - Redistributions in binary form must reproduce the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer in the documentation and/or other materials
++ * provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++#include <linux/device.h>
++
++struct ipath_user_sdma_queue;
++
++struct ipath_user_sdma_queue *
++ipath_user_sdma_queue_create(struct device *dev, int unit, int port, int sport);
++void ipath_user_sdma_queue_destroy(struct ipath_user_sdma_queue *pq);
++
++int ipath_user_sdma_writev(struct ipath_devdata *dd,
++ struct ipath_user_sdma_queue *pq,
++ const struct iovec *iov,
++ unsigned long dim);
++
++int ipath_user_sdma_make_progress(struct ipath_devdata *dd,
++ struct ipath_user_sdma_queue *pq);
++
++int ipath_user_sdma_pkt_sent(const struct ipath_user_sdma_queue *pq,
++ u32 counter);
++void ipath_user_sdma_queue_drain(struct ipath_devdata *dd,
++ struct ipath_user_sdma_queue *pq);
++
++u32 ipath_user_sdma_complete_counter(const struct ipath_user_sdma_queue *pq);
++u32 ipath_user_sdma_inflight_counter(struct ipath_user_sdma_queue *pq);
+diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c
+index 32d8f88..e63927c 100644
+--- a/drivers/infiniband/hw/ipath/ipath_verbs.c
++++ b/drivers/infiniband/hw/ipath/ipath_verbs.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+@@ -109,7 +109,7 @@ MODULE_PARM_DESC(max_srq_wrs, "Maximum number of SRQ WRs support");
+
+ static unsigned int ib_ipath_disable_sma;
+ module_param_named(disable_sma, ib_ipath_disable_sma, uint, S_IWUSR | S_IRUGO);
+-MODULE_PARM_DESC(ib_ipath_disable_sma, "Disable the SMA");
++MODULE_PARM_DESC(disable_sma, "Disable the SMA");
+
+ const int ib_ipath_state_ops[IB_QPS_ERR + 1] = {
+ [IB_QPS_RESET] = 0,
+@@ -242,6 +242,93 @@ static void ipath_flush_wqe(struct ipath_qp *qp, struct ib_send_wr *wr)
+ ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 1);
+ }
+
++/*
++ * Count the number of DMA descriptors needed to send length bytes of data.
++ * Don't modify the ipath_sge_state to get the count.
++ * Return zero if any of the segments is not aligned.
++ */
++static u32 ipath_count_sge(struct ipath_sge_state *ss, u32 length)
++{
++ struct ipath_sge *sg_list = ss->sg_list;
++ struct ipath_sge sge = ss->sge;
++ u8 num_sge = ss->num_sge;
++ u32 ndesc = 1; /* count the header */
++
++ while (length) {
++ u32 len = sge.length;
++
++ if (len > length)
++ len = length;
++ if (len > sge.sge_length)
++ len = sge.sge_length;
++ BUG_ON(len == 0);
++ if (((long) sge.vaddr & (sizeof(u32) - 1)) ||
++ (len != length && (len & (sizeof(u32) - 1)))) {
++ ndesc = 0;
++ break;
++ }
++ ndesc++;
++ sge.vaddr += len;
++ sge.length -= len;
++ sge.sge_length -= len;
++ if (sge.sge_length == 0) {
++ if (--num_sge)
++ sge = *sg_list++;
++ } else if (sge.length == 0 && sge.mr != NULL) {
++ if (++sge.n >= IPATH_SEGSZ) {
++ if (++sge.m >= sge.mr->mapsz)
++ break;
++ sge.n = 0;
++ }
++ sge.vaddr =
++ sge.mr->map[sge.m]->segs[sge.n].vaddr;
++ sge.length =
++ sge.mr->map[sge.m]->segs[sge.n].length;
++ }
++ length -= len;
++ }
++ return ndesc;
++}
++
++/*
++ * Copy from the SGEs to the data buffer.
++ */
++static void ipath_copy_from_sge(void *data, struct ipath_sge_state *ss,
++ u32 length)
++{
++ struct ipath_sge *sge = &ss->sge;
++
++ while (length) {
++ u32 len = sge->length;
++
++ if (len > length)
++ len = length;
++ if (len > sge->sge_length)
++ len = sge->sge_length;
++ BUG_ON(len == 0);
++ memcpy(data, sge->vaddr, len);
++ sge->vaddr += len;
++ sge->length -= len;
++ sge->sge_length -= len;
++ if (sge->sge_length == 0) {
++ if (--ss->num_sge)
++ *sge = *ss->sg_list++;
++ } else if (sge->length == 0 && sge->mr != NULL) {
++ if (++sge->n >= IPATH_SEGSZ) {
++ if (++sge->m >= sge->mr->mapsz)
++ break;
++ sge->n = 0;
++ }
++ sge->vaddr =
++ sge->mr->map[sge->m]->segs[sge->n].vaddr;
++ sge->length =
++ sge->mr->map[sge->m]->segs[sge->n].length;
++ }
++ data += len;
++ length -= len;
++ }
++}
++
+ /**
+ * ipath_post_one_send - post one RC, UC, or UD send work request
+ * @qp: the QP to post on
+@@ -866,27 +953,257 @@ static void copy_io(u32 __iomem *piobuf, struct ipath_sge_state *ss,
+ __raw_writel(last, piobuf);
+ }
+
+-static int ipath_verbs_send_pio(struct ipath_qp *qp, u32 *hdr, u32 hdrwords,
++/*
++ * Convert IB rate to delay multiplier.
++ */
++unsigned ipath_ib_rate_to_mult(enum ib_rate rate)
++{
++ switch (rate) {
++ case IB_RATE_2_5_GBPS: return 8;
++ case IB_RATE_5_GBPS: return 4;
++ case IB_RATE_10_GBPS: return 2;
++ case IB_RATE_20_GBPS: return 1;
++ default: return 0;
++ }
++}
++
++/*
++ * Convert delay multiplier to IB rate
++ */
++static enum ib_rate ipath_mult_to_ib_rate(unsigned mult)
++{
++ switch (mult) {
++ case 8: return IB_RATE_2_5_GBPS;
++ case 4: return IB_RATE_5_GBPS;
++ case 2: return IB_RATE_10_GBPS;
++ case 1: return IB_RATE_20_GBPS;
++ default: return IB_RATE_PORT_CURRENT;
++ }
++}
++
++static inline struct ipath_verbs_txreq *get_txreq(struct ipath_ibdev *dev)
++{
++ struct ipath_verbs_txreq *tx = NULL;
++ unsigned long flags;
++
++ spin_lock_irqsave(&dev->pending_lock, flags);
++ if (!list_empty(&dev->txreq_free)) {
++ struct list_head *l = dev->txreq_free.next;
++
++ list_del(l);
++ tx = list_entry(l, struct ipath_verbs_txreq, txreq.list);
++ }
++ spin_unlock_irqrestore(&dev->pending_lock, flags);
++ return tx;
++}
++
++static inline void put_txreq(struct ipath_ibdev *dev,
++ struct ipath_verbs_txreq *tx)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&dev->pending_lock, flags);
++ list_add(&tx->txreq.list, &dev->txreq_free);
++ spin_unlock_irqrestore(&dev->pending_lock, flags);
++}
++
++static void sdma_complete(void *cookie, int status)
++{
++ struct ipath_verbs_txreq *tx = cookie;
++ struct ipath_qp *qp = tx->qp;
++ struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
++
++ /* Generate a completion queue entry if needed */
++ if (qp->ibqp.qp_type != IB_QPT_RC && tx->wqe) {
++ enum ib_wc_status ibs = status == IPATH_SDMA_TXREQ_S_OK ?
++ IB_WC_SUCCESS : IB_WC_WR_FLUSH_ERR;
++
++ ipath_send_complete(qp, tx->wqe, ibs);
++ }
++
++ if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_FREEBUF)
++ kfree(tx->txreq.map_addr);
++ put_txreq(dev, tx);
++
++ if (atomic_dec_and_test(&qp->refcount))
++ wake_up(&qp->wait);
++}
++
++/*
++ * Compute the number of clock cycles of delay before sending the next packet.
++ * The multipliers reflect the number of clocks for the fastest rate so
++ * one tick at 4xDDR is 8 ticks at 1xSDR.
++ * If the destination port will take longer to receive a packet than
++ * the outgoing link can send it, we need to delay sending the next packet
++ * by the difference in time it takes the receiver to receive and the sender
++ * to send this packet.
++ * Note that this delay is always correct for UC and RC but not always
++ * optimal for UD. For UD, the destination HCA can be different for each
++ * packet, in which case, we could send packets to a different destination
++ * while "waiting" for the delay. The overhead for doing this without
++ * HW support is more than just paying the cost of delaying some packets
++ * unnecessarily.
++ */
++static inline unsigned ipath_pkt_delay(u32 plen, u8 snd_mult, u8 rcv_mult)
++{
++ return (rcv_mult > snd_mult) ?
++ (plen * (rcv_mult - snd_mult) + 1) >> 1 : 0;
++}
++
++static int ipath_verbs_send_dma(struct ipath_qp *qp,
++ struct ipath_ib_header *hdr, u32 hdrwords,
++ struct ipath_sge_state *ss, u32 len,
++ u32 plen, u32 dwords)
++{
++ struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
++ struct ipath_devdata *dd = dev->dd;
++ struct ipath_verbs_txreq *tx;
++ u32 *piobuf;
++ u32 control;
++ u32 ndesc;
++ int ret;
++
++ tx = qp->s_tx;
++ if (tx) {
++ qp->s_tx = NULL;
++ /* resend previously constructed packet */
++ ret = ipath_sdma_verbs_send(dd, tx->ss, tx->len, tx);
++ if (ret)
++ qp->s_tx = tx;
++ goto bail;
++ }
++
++ tx = get_txreq(dev);
++ if (!tx) {
++ ret = -EBUSY;
++ goto bail;
++ }
++
++ /*
++ * Get the saved delay count we computed for the previous packet
++ * and save the delay count for this packet to be used next time
++ * we get here.
++ */
++ control = qp->s_pkt_delay;
++ qp->s_pkt_delay = ipath_pkt_delay(plen, dd->delay_mult, qp->s_dmult);
++
++ tx->qp = qp;
++ atomic_inc(&qp->refcount);
++ tx->wqe = qp->s_wqe;
++ tx->txreq.callback = sdma_complete;
++ tx->txreq.callback_cookie = tx;
++ tx->txreq.flags = IPATH_SDMA_TXREQ_F_HEADTOHOST |
++ IPATH_SDMA_TXREQ_F_INTREQ | IPATH_SDMA_TXREQ_F_FREEDESC;
++ if (plen + 1 >= IPATH_SMALLBUF_DWORDS)
++ tx->txreq.flags |= IPATH_SDMA_TXREQ_F_USELARGEBUF;
++
++ /* VL15 packets bypass credit check */
++ if ((be16_to_cpu(hdr->lrh[0]) >> 12) == 15) {
++ control |= 1ULL << 31;
++ tx->txreq.flags |= IPATH_SDMA_TXREQ_F_VL15;
++ }
++
++ if (len) {
++ /*
++ * Don't try to DMA if it takes more descriptors than
++ * the queue holds.
++ */
++ ndesc = ipath_count_sge(ss, len);
++ if (ndesc >= dd->ipath_sdma_descq_cnt)
++ ndesc = 0;
++ } else
++ ndesc = 1;
++ if (ndesc) {
++ tx->hdr.pbc[0] = cpu_to_le32(plen);
++ tx->hdr.pbc[1] = cpu_to_le32(control);
++ memcpy(&tx->hdr.hdr, hdr, hdrwords << 2);
++ tx->txreq.sg_count = ndesc;
++ tx->map_len = (hdrwords + 2) << 2;
++ tx->txreq.map_addr = &tx->hdr;
++ ret = ipath_sdma_verbs_send(dd, ss, dwords, tx);
++ if (ret) {
++ /* save ss and length in dwords */
++ tx->ss = ss;
++ tx->len = dwords;
++ qp->s_tx = tx;
++ }
++ goto bail;
++ }
++
++ /* Allocate a buffer and copy the header and payload to it. */
++ tx->map_len = (plen + 1) << 2;
++ piobuf = kmalloc(tx->map_len, GFP_ATOMIC);
++ if (unlikely(piobuf == NULL)) {
++ ret = -EBUSY;
++ goto err_tx;
++ }
++ tx->txreq.map_addr = piobuf;
++ tx->txreq.flags |= IPATH_SDMA_TXREQ_F_FREEBUF;
++ tx->txreq.sg_count = 1;
++
++ *piobuf++ = (__force u32) cpu_to_le32(plen);
++ *piobuf++ = (__force u32) cpu_to_le32(control);
++ memcpy(piobuf, hdr, hdrwords << 2);
++ ipath_copy_from_sge(piobuf + hdrwords, ss, len);
++
++ ret = ipath_sdma_verbs_send(dd, NULL, 0, tx);
++ /*
++ * If we couldn't queue the DMA request, save the info
++ * and try again later rather than destroying the
++ * buffer and undoing the side effects of the copy.
++ */
++ if (ret) {
++ tx->ss = NULL;
++ tx->len = 0;
++ qp->s_tx = tx;
++ }
++ dev->n_unaligned++;
++ goto bail;
++
++err_tx:
++ if (atomic_dec_and_test(&qp->refcount))
++ wake_up(&qp->wait);
++ put_txreq(dev, tx);
++bail:
++ return ret;
++}
++
++static int ipath_verbs_send_pio(struct ipath_qp *qp,
++ struct ipath_ib_header *ibhdr, u32 hdrwords,
+ struct ipath_sge_state *ss, u32 len,
+ u32 plen, u32 dwords)
+ {
+ struct ipath_devdata *dd = to_idev(qp->ibqp.device)->dd;
++ u32 *hdr = (u32 *) ibhdr;
+ u32 __iomem *piobuf;
+ unsigned flush_wc;
++ u32 control;
+ int ret;
+
+- piobuf = ipath_getpiobuf(dd, NULL);
++ piobuf = ipath_getpiobuf(dd, plen, NULL);
+ if (unlikely(piobuf == NULL)) {
+ ret = -EBUSY;
+ goto bail;
+ }
+
+ /*
+- * Write len to control qword, no flags.
++ * Get the saved delay count we computed for the previous packet
++ * and save the delay count for this packet to be used next time
++ * we get here.
++ */
++ control = qp->s_pkt_delay;
++ qp->s_pkt_delay = ipath_pkt_delay(plen, dd->delay_mult, qp->s_dmult);
++
++ /* VL15 packets bypass credit check */
++ if ((be16_to_cpu(ibhdr->lrh[0]) >> 12) == 15)
++ control |= 1ULL << 31;
++
++ /*
++ * Write the length to the control qword plus any needed flags.
+ * We have to flush after the PBC for correctness on some cpus
+ * or WC buffer can be written out of order.
+ */
+- writeq(plen, piobuf);
++ writeq(((u64) control << 32) | plen, piobuf);
+ piobuf += 2;
+
+ flush_wc = dd->ipath_flags & IPATH_PIO_FLUSH_WC;
+@@ -961,15 +1278,25 @@ int ipath_verbs_send(struct ipath_qp *qp, struct ipath_ib_header *hdr,
+ */
+ plen = hdrwords + dwords + 1;
+
+- /* Drop non-VL15 packets if we are not in the active state */
+- if (!(dd->ipath_flags & IPATH_LINKACTIVE) &&
+- qp->ibqp.qp_type != IB_QPT_SMI) {
++ /*
++ * VL15 packets (IB_QPT_SMI) will always use PIO, so we
++ * can defer SDMA restart until link goes ACTIVE without
++ * worrying about just how we got there.
++ */
++ if (qp->ibqp.qp_type == IB_QPT_SMI)
++ ret = ipath_verbs_send_pio(qp, hdr, hdrwords, ss, len,
++ plen, dwords);
++ /* All non-VL15 packets are dropped if link is not ACTIVE */
++ else if (!(dd->ipath_flags & IPATH_LINKACTIVE)) {
+ if (qp->s_wqe)
+ ipath_send_complete(qp, qp->s_wqe, IB_WC_SUCCESS);
+ ret = 0;
+- } else
+- ret = ipath_verbs_send_pio(qp, (u32 *) hdr, hdrwords,
+- ss, len, plen, dwords);
++ } else if (dd->ipath_flags & IPATH_HAS_SEND_DMA)
++ ret = ipath_verbs_send_dma(qp, hdr, hdrwords, ss, len,
++ plen, dwords);
++ else
++ ret = ipath_verbs_send_pio(qp, hdr, hdrwords, ss, len,
++ plen, dwords);
+
+ return ret;
+ }
+@@ -1038,6 +1365,12 @@ int ipath_get_counters(struct ipath_devdata *dd,
+ ipath_snap_cntr(dd, crp->cr_errlpcrccnt) +
+ ipath_snap_cntr(dd, crp->cr_badformatcnt) +
+ dd->ipath_rxfc_unsupvl_errs;
++ if (crp->cr_rxotherlocalphyerrcnt)
++ cntrs->port_rcv_errors +=
++ ipath_snap_cntr(dd, crp->cr_rxotherlocalphyerrcnt);
++ if (crp->cr_rxvlerrcnt)
++ cntrs->port_rcv_errors +=
++ ipath_snap_cntr(dd, crp->cr_rxvlerrcnt);
+ cntrs->port_rcv_remphys_errors =
+ ipath_snap_cntr(dd, crp->cr_rcvebpcnt);
+ cntrs->port_xmit_discards = ipath_snap_cntr(dd, crp->cr_unsupvlcnt);
+@@ -1046,9 +1379,16 @@ int ipath_get_counters(struct ipath_devdata *dd,
+ cntrs->port_xmit_packets = ipath_snap_cntr(dd, crp->cr_pktsendcnt);
+ cntrs->port_rcv_packets = ipath_snap_cntr(dd, crp->cr_pktrcvcnt);
+ cntrs->local_link_integrity_errors =
+- (dd->ipath_flags & IPATH_GPIO_ERRINTRS) ?
+- dd->ipath_lli_errs : dd->ipath_lli_errors;
+- cntrs->excessive_buffer_overrun_errors = dd->ipath_overrun_thresh_errs;
++ crp->cr_locallinkintegrityerrcnt ?
++ ipath_snap_cntr(dd, crp->cr_locallinkintegrityerrcnt) :
++ ((dd->ipath_flags & IPATH_GPIO_ERRINTRS) ?
++ dd->ipath_lli_errs : dd->ipath_lli_errors);
++ cntrs->excessive_buffer_overrun_errors =
++ crp->cr_excessbufferovflcnt ?
++ ipath_snap_cntr(dd, crp->cr_excessbufferovflcnt) :
++ dd->ipath_overrun_thresh_errs;
++ cntrs->vl15_dropped = crp->cr_vl15droppedpktcnt ?
++ ipath_snap_cntr(dd, crp->cr_vl15droppedpktcnt) : 0;
+
+ ret = 0;
+
+@@ -1183,7 +1523,9 @@ static int ipath_query_port(struct ib_device *ibdev,
+ props->sm_lid = dev->sm_lid;
+ props->sm_sl = dev->sm_sl;
+ ibcstat = dd->ipath_lastibcstat;
+- props->state = ((ibcstat >> 4) & 0x3) + 1;
++ /* map LinkState to IB portinfo values. */
++ props->state = ipath_ib_linkstate(dd, ibcstat) + 1;
++
+ /* See phys_state_show() */
+ props->phys_state = /* MEA: assumes shift == 0 */
+ ipath_cvt_physportstate[dd->ipath_lastibcstat &
+@@ -1195,18 +1537,13 @@ static int ipath_query_port(struct ib_device *ibdev,
+ props->bad_pkey_cntr = ipath_get_cr_errpkey(dd) -
+ dev->z_pkey_violations;
+ props->qkey_viol_cntr = dev->qkey_violations;
+- props->active_width = IB_WIDTH_4X;
++ props->active_width = dd->ipath_link_width_active;
+ /* See rate_show() */
+- props->active_speed = 1; /* Regular 10Mbs speed. */
++ props->active_speed = dd->ipath_link_speed_active;
+ props->max_vl_num = 1; /* VLCap = VL0 */
+ props->init_type_reply = 0;
+
+- /*
+- * Note: the chip supports a maximum MTU of 4096, but the driver
+- * hasn't implemented this feature yet, so set the maximum value
+- * to 2048.
+- */
+- props->max_mtu = IB_MTU_2048;
++ props->max_mtu = ipath_mtu4096 ? IB_MTU_4096 : IB_MTU_2048;
+ switch (dd->ipath_ibmtu) {
+ case 4096:
+ mtu = IB_MTU_4096;
+@@ -1399,6 +1736,7 @@ static struct ib_ah *ipath_create_ah(struct ib_pd *pd,
+
+ /* ib_create_ah() will initialize ah->ibah. */
+ ah->attr = *ah_attr;
++ ah->attr.static_rate = ipath_ib_rate_to_mult(ah_attr->static_rate);
+
+ ret = &ah->ibah;
+
+@@ -1432,6 +1770,7 @@ static int ipath_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr)
+ struct ipath_ah *ah = to_iah(ibah);
+
+ *ah_attr = ah->attr;
++ ah_attr->static_rate = ipath_mult_to_ib_rate(ah->attr.static_rate);
+
+ return 0;
+ }
+@@ -1581,6 +1920,8 @@ int ipath_register_ib_device(struct ipath_devdata *dd)
+ struct ipath_verbs_counters cntrs;
+ struct ipath_ibdev *idev;
+ struct ib_device *dev;
++ struct ipath_verbs_txreq *tx;
++ unsigned i;
+ int ret;
+
+ idev = (struct ipath_ibdev *)ib_alloc_device(sizeof *idev);
+@@ -1591,6 +1932,17 @@ int ipath_register_ib_device(struct ipath_devdata *dd)
+
+ dev = &idev->ibdev;
+
++ if (dd->ipath_sdma_descq_cnt) {
++ tx = kmalloc(dd->ipath_sdma_descq_cnt * sizeof *tx,
++ GFP_KERNEL);
++ if (tx == NULL) {
++ ret = -ENOMEM;
++ goto err_tx;
++ }
++ } else
++ tx = NULL;
++ idev->txreq_bufs = tx;
++
+ /* Only need to initialize non-zero fields. */
+ spin_lock_init(&idev->n_pds_lock);
+ spin_lock_init(&idev->n_ahs_lock);
+@@ -1631,15 +1983,17 @@ int ipath_register_ib_device(struct ipath_devdata *dd)
+ INIT_LIST_HEAD(&idev->pending[2]);
+ INIT_LIST_HEAD(&idev->piowait);
+ INIT_LIST_HEAD(&idev->rnrwait);
++ INIT_LIST_HEAD(&idev->txreq_free);
+ idev->pending_index = 0;
+ idev->port_cap_flags =
+ IB_PORT_SYS_IMAGE_GUID_SUP | IB_PORT_CLIENT_REG_SUP;
++ if (dd->ipath_flags & IPATH_HAS_LINK_LATENCY)
++ idev->port_cap_flags |= IB_PORT_LINK_LATENCY_SUP;
+ idev->pma_counter_select[0] = IB_PMA_PORT_XMIT_DATA;
+ idev->pma_counter_select[1] = IB_PMA_PORT_RCV_DATA;
+ idev->pma_counter_select[2] = IB_PMA_PORT_XMIT_PKTS;
+ idev->pma_counter_select[3] = IB_PMA_PORT_RCV_PKTS;
+ idev->pma_counter_select[4] = IB_PMA_PORT_XMIT_WAIT;
+- idev->link_width_enabled = 3; /* 1x or 4x */
+
+ /* Snapshot current HW counters to "clear" them. */
+ ipath_get_counters(dd, &cntrs);
+@@ -1661,6 +2015,9 @@ int ipath_register_ib_device(struct ipath_devdata *dd)
+ cntrs.excessive_buffer_overrun_errors;
+ idev->z_vl15_dropped = cntrs.vl15_dropped;
+
++ for (i = 0; i < dd->ipath_sdma_descq_cnt; i++, tx++)
++ list_add(&tx->txreq.list, &idev->txreq_free);
++
+ /*
+ * The system image GUID is supposed to be the same for all
+ * IB HCAs in a single system but since there can be other
+@@ -1774,6 +2131,8 @@ err_reg:
+ err_lk:
+ kfree(idev->qp_table.table);
+ err_qp:
++ kfree(idev->txreq_bufs);
++err_tx:
+ ib_dealloc_device(dev);
+ ipath_dev_err(dd, "cannot register verbs: %d!\n", -ret);
+ idev = NULL;
+@@ -1808,21 +2167,24 @@ void ipath_unregister_ib_device(struct ipath_ibdev *dev)
+ ipath_free_all_qps(&dev->qp_table);
+ kfree(dev->qp_table.table);
+ kfree(dev->lk_table.table);
++ kfree(dev->txreq_bufs);
+ ib_dealloc_device(ibdev);
+ }
+
+-static ssize_t show_rev(struct class_device *cdev, char *buf)
++static ssize_t show_rev(struct device *device, struct device_attribute *attr,
++ char *buf)
+ {
+ struct ipath_ibdev *dev =
+- container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
++ container_of(device, struct ipath_ibdev, ibdev.dev);
+
+ return sprintf(buf, "%x\n", dev->dd->ipath_pcirev);
+ }
+
+-static ssize_t show_hca(struct class_device *cdev, char *buf)
++static ssize_t show_hca(struct device *device, struct device_attribute *attr,
++ char *buf)
+ {
+ struct ipath_ibdev *dev =
+- container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
++ container_of(device, struct ipath_ibdev, ibdev.dev);
+ int ret;
+
+ ret = dev->dd->ipath_f_get_boardname(dev->dd, buf, 128);
+@@ -1835,10 +2197,11 @@ bail:
+ return ret;
+ }
+
+-static ssize_t show_stats(struct class_device *cdev, char *buf)
++static ssize_t show_stats(struct device *device, struct device_attribute *attr,
++ char *buf)
+ {
+ struct ipath_ibdev *dev =
+- container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
++ container_of(device, struct ipath_ibdev, ibdev.dev);
+ int i;
+ int len;
+
+@@ -1855,13 +2218,15 @@ static ssize_t show_stats(struct class_device *cdev, char *buf)
+ "RC stalls %d\n"
+ "piobuf wait %d\n"
+ "no piobuf %d\n"
++ "unaligned %d\n"
+ "PKT drops %d\n"
+ "WQE errs %d\n",
+ dev->n_rc_resends, dev->n_rc_qacks, dev->n_rc_acks,
+ dev->n_seq_naks, dev->n_rdma_seq, dev->n_rnr_naks,
+ dev->n_other_naks, dev->n_timeouts,
+ dev->n_rdma_dup_busy, dev->n_rc_stalls, dev->n_piowait,
+- dev->n_no_piobuf, dev->n_pkt_drops, dev->n_wqe_errs);
++ dev->n_no_piobuf, dev->n_unaligned,
++ dev->n_pkt_drops, dev->n_wqe_errs);
+ for (i = 0; i < ARRAY_SIZE(dev->opstats); i++) {
+ const struct ipath_opcode_stats *si = &dev->opstats[i];
+
+@@ -1874,16 +2239,16 @@ static ssize_t show_stats(struct class_device *cdev, char *buf)
+ return len;
+ }
+
+-static CLASS_DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
+-static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
+-static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_hca, NULL);
+-static CLASS_DEVICE_ATTR(stats, S_IRUGO, show_stats, NULL);
++static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
++static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
++static DEVICE_ATTR(board_id, S_IRUGO, show_hca, NULL);
++static DEVICE_ATTR(stats, S_IRUGO, show_stats, NULL);
+
+-static struct class_device_attribute *ipath_class_attributes[] = {
+- &class_device_attr_hw_rev,
+- &class_device_attr_hca_type,
+- &class_device_attr_board_id,
+- &class_device_attr_stats
++static struct device_attribute *ipath_class_attributes[] = {
++ &dev_attr_hw_rev,
++ &dev_attr_hca_type,
++ &dev_attr_board_id,
++ &dev_attr_stats
+ };
+
+ static int ipath_verbs_register_sysfs(struct ib_device *dev)
+@@ -1892,8 +2257,8 @@ static int ipath_verbs_register_sysfs(struct ib_device *dev)
+ int ret;
+
+ for (i = 0; i < ARRAY_SIZE(ipath_class_attributes); ++i)
+- if (class_device_create_file(&dev->class_dev,
+- ipath_class_attributes[i])) {
++ if (device_create_file(&dev->dev,
++ ipath_class_attributes[i])) {
+ ret = 1;
+ goto bail;
+ }
+diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h
+index 3d59736..6514aa8 100644
+--- a/drivers/infiniband/hw/ipath/ipath_verbs.h
++++ b/drivers/infiniband/hw/ipath/ipath_verbs.h
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
++ * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+@@ -138,6 +138,11 @@ struct ipath_ib_header {
+ } u;
+ } __attribute__ ((packed));
+
++struct ipath_pio_header {
++ __le32 pbc[2];
++ struct ipath_ib_header hdr;
++} __attribute__ ((packed));
++
+ /*
+ * There is one struct ipath_mcast for each multicast GID.
+ * All attached QPs are then stored as a list of
+@@ -319,6 +324,7 @@ struct ipath_sge_state {
+ struct ipath_sge *sg_list; /* next SGE to be used if any */
+ struct ipath_sge sge; /* progress state for the current SGE */
+ u8 num_sge;
++ u8 static_rate;
+ };
+
+ /*
+@@ -356,6 +362,7 @@ struct ipath_qp {
+ struct tasklet_struct s_task;
+ struct ipath_mmap_info *ip;
+ struct ipath_sge_state *s_cur_sge;
++ struct ipath_verbs_txreq *s_tx;
+ struct ipath_sge_state s_sge; /* current send request data */
+ struct ipath_ack_entry s_ack_queue[IPATH_MAX_RDMA_ATOMIC + 1];
+ struct ipath_sge_state s_ack_rdma_sge;
+@@ -363,7 +370,8 @@ struct ipath_qp {
+ struct ipath_sge_state r_sge; /* current receive data */
+ spinlock_t s_lock;
+ unsigned long s_busy;
+- u32 s_hdrwords; /* size of s_hdr in 32 bit words */
++ u16 s_pkt_delay;
++ u16 s_hdrwords; /* size of s_hdr in 32 bit words */
+ u32 s_cur_size; /* size of send packet in bytes */
+ u32 s_len; /* total length of s_sge */
+ u32 s_rdma_read_len; /* total length of s_rdma_read_sge */
+@@ -387,7 +395,6 @@ struct ipath_qp {
+ u8 r_nak_state; /* non-zero if NAK is pending */
+ u8 r_min_rnr_timer; /* retry timeout value for RNR NAKs */
+ u8 r_reuse_sge; /* for UC receive errors */
+- u8 r_sge_inx; /* current index into sg_list */
+ u8 r_wrid_valid; /* r_wrid set but CQ entry not yet made */
+ u8 r_max_rd_atomic; /* max number of RDMA read/atomic to receive */
+ u8 r_head_ack_queue; /* index into s_ack_queue[] */
+@@ -403,6 +410,7 @@ struct ipath_qp {
+ u8 s_num_rd_atomic; /* number of RDMA read/atomic pending */
+ u8 s_tail_ack_queue; /* index into s_ack_queue[] */
+ u8 s_flags;
++ u8 s_dmult;
+ u8 timeout; /* Timeout for this QP */
+ enum ib_mtu path_mtu;
+ u32 remote_qpn;
+@@ -510,6 +518,8 @@ struct ipath_ibdev {
+ struct ipath_lkey_table lk_table;
+ struct list_head pending[3]; /* FIFO of QPs waiting for ACKs */
+ struct list_head piowait; /* list for wait PIO buf */
++ struct list_head txreq_free;
++ void *txreq_bufs;
+ /* list of QPs waiting for RNR timer */
+ struct list_head rnrwait;
+ spinlock_t pending_lock;
+@@ -570,6 +580,7 @@ struct ipath_ibdev {
+ u32 n_rdma_dup_busy;
+ u32 n_piowait;
+ u32 n_no_piobuf;
++ u32 n_unaligned;
+ u32 port_cap_flags;
+ u32 pma_sample_start;
+ u32 pma_sample_interval;
+@@ -581,7 +592,6 @@ struct ipath_ibdev {
+ u16 pending_index; /* which pending queue is active */
+ u8 pma_sample_status;
+ u8 subnet_timeout;
+- u8 link_width_enabled;
+ u8 vl_high_limit;
+ struct ipath_opcode_stats opstats[128];
+ };
+@@ -602,6 +612,16 @@ struct ipath_verbs_counters {
+ u32 vl15_dropped;
+ };
+
++struct ipath_verbs_txreq {
++ struct ipath_qp *qp;
++ struct ipath_swqe *wqe;
++ u32 map_len;
++ u32 len;
++ struct ipath_sge_state *ss;
++ struct ipath_pio_header hdr;
++ struct ipath_sdma_txreq txreq;
++};
++
+ static inline struct ipath_mr *to_imr(struct ib_mr *ibmr)
+ {
+ return container_of(ibmr, struct ipath_mr, ibmr);
+@@ -694,11 +714,11 @@ void ipath_sqerror_qp(struct ipath_qp *qp, struct ib_wc *wc);
+
+ void ipath_get_credit(struct ipath_qp *qp, u32 aeth);
+
++unsigned ipath_ib_rate_to_mult(enum ib_rate rate);
++
+ int ipath_verbs_send(struct ipath_qp *qp, struct ipath_ib_header *hdr,
+ u32 hdrwords, struct ipath_sge_state *ss, u32 len);
+
+-void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int sig);
+-
+ void ipath_copy_sge(struct ipath_sge_state *ss, void *data, u32 length);
+
+ void ipath_skip_sge(struct ipath_sge_state *ss, u32 length);
+diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c
+index 7360bba..3557e7e 100644
+--- a/drivers/infiniband/hw/mlx4/cq.c
++++ b/drivers/infiniband/hw/mlx4/cq.c
+@@ -85,6 +85,82 @@ static struct mlx4_cqe *next_cqe_sw(struct mlx4_ib_cq *cq)
+ return get_sw_cqe(cq, cq->mcq.cons_index);
+ }
+
++int mlx4_ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period)
++{
++ struct mlx4_ib_cq *mcq = to_mcq(cq);
++ struct mlx4_ib_dev *dev = to_mdev(cq->device);
++
++ return mlx4_cq_modify(dev->dev, &mcq->mcq, cq_count, cq_period);
++}
++
++static int mlx4_ib_alloc_cq_buf(struct mlx4_ib_dev *dev, struct mlx4_ib_cq_buf *buf, int nent)
++{
++ int err;
++
++ err = mlx4_buf_alloc(dev->dev, nent * sizeof(struct mlx4_cqe),
++ PAGE_SIZE * 2, &buf->buf);
++
++ if (err)
++ goto out;
++
++ err = mlx4_mtt_init(dev->dev, buf->buf.npages, buf->buf.page_shift,
++ &buf->mtt);
++ if (err)
++ goto err_buf;
++
++ err = mlx4_buf_write_mtt(dev->dev, &buf->mtt, &buf->buf);
++ if (err)
++ goto err_mtt;
++
++ return 0;
++
++err_mtt:
++ mlx4_mtt_cleanup(dev->dev, &buf->mtt);
++
++err_buf:
++ mlx4_buf_free(dev->dev, nent * sizeof(struct mlx4_cqe),
++ &buf->buf);
++
++out:
++ return err;
++}
++
++static void mlx4_ib_free_cq_buf(struct mlx4_ib_dev *dev, struct mlx4_ib_cq_buf *buf, int cqe)
++{
++ mlx4_buf_free(dev->dev, (cqe + 1) * sizeof(struct mlx4_cqe), &buf->buf);
++}
++
++static int mlx4_ib_get_cq_umem(struct mlx4_ib_dev *dev, struct ib_ucontext *context,
++ struct mlx4_ib_cq_buf *buf, struct ib_umem **umem,
++ u64 buf_addr, int cqe)
++{
++ int err;
++
++ *umem = ib_umem_get(context, buf_addr, cqe * sizeof (struct mlx4_cqe),
++ IB_ACCESS_LOCAL_WRITE);
++ if (IS_ERR(*umem))
++ return PTR_ERR(*umem);
++
++ err = mlx4_mtt_init(dev->dev, ib_umem_page_count(*umem),
++ ilog2((*umem)->page_size), &buf->mtt);
++ if (err)
++ goto err_buf;
++
++ err = mlx4_ib_umem_write_mtt(dev, &buf->mtt, *umem);
++ if (err)
++ goto err_mtt;
++
++ return 0;
++
++err_mtt:
++ mlx4_mtt_cleanup(dev->dev, &buf->mtt);
++
++err_buf:
++ ib_umem_release(*umem);
++
++ return err;
++}
++
+ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector,
+ struct ib_ucontext *context,
+ struct ib_udata *udata)
+@@ -92,7 +168,6 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector
+ struct mlx4_ib_dev *dev = to_mdev(ibdev);
+ struct mlx4_ib_cq *cq;
+ struct mlx4_uar *uar;
+- int buf_size;
+ int err;
+
+ if (entries < 1 || entries > dev->dev->caps.max_cqes)
+@@ -104,8 +179,10 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector
+
+ entries = roundup_pow_of_two(entries + 1);
+ cq->ibcq.cqe = entries - 1;
+- buf_size = entries * sizeof (struct mlx4_cqe);
++ mutex_init(&cq->resize_mutex);
+ spin_lock_init(&cq->lock);
++ cq->resize_buf = NULL;
++ cq->resize_umem = NULL;
+
+ if (context) {
+ struct mlx4_ib_create_cq ucmd;
+@@ -115,21 +192,10 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector
+ goto err_cq;
+ }
+
+- cq->umem = ib_umem_get(context, ucmd.buf_addr, buf_size,
+- IB_ACCESS_LOCAL_WRITE);
+- if (IS_ERR(cq->umem)) {
+- err = PTR_ERR(cq->umem);
+- goto err_cq;
+- }
+-
+- err = mlx4_mtt_init(dev->dev, ib_umem_page_count(cq->umem),
+- ilog2(cq->umem->page_size), &cq->buf.mtt);
+- if (err)
+- goto err_buf;
+-
+- err = mlx4_ib_umem_write_mtt(dev, &cq->buf.mtt, cq->umem);
++ err = mlx4_ib_get_cq_umem(dev, context, &cq->buf, &cq->umem,
++ ucmd.buf_addr, entries);
+ if (err)
+- goto err_mtt;
++ goto err_cq;
+
+ err = mlx4_ib_db_map_user(to_mucontext(context), ucmd.db_addr,
+ &cq->db);
+@@ -147,19 +213,9 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector
+ *cq->mcq.set_ci_db = 0;
+ *cq->mcq.arm_db = 0;
+
+- if (mlx4_buf_alloc(dev->dev, buf_size, PAGE_SIZE * 2, &cq->buf.buf)) {
+- err = -ENOMEM;
+- goto err_db;
+- }
+-
+- err = mlx4_mtt_init(dev->dev, cq->buf.buf.npages, cq->buf.buf.page_shift,
+- &cq->buf.mtt);
++ err = mlx4_ib_alloc_cq_buf(dev, &cq->buf, entries);
+ if (err)
+- goto err_buf;
+-
+- err = mlx4_buf_write_mtt(dev->dev, &cq->buf.mtt, &cq->buf.buf);
+- if (err)
+- goto err_mtt;
++ goto err_db;
+
+ uar = &dev->priv_uar;
+ }
+@@ -187,12 +243,10 @@ err_dbmap:
+ err_mtt:
+ mlx4_mtt_cleanup(dev->dev, &cq->buf.mtt);
+
+-err_buf:
+ if (context)
+ ib_umem_release(cq->umem);
+ else
+- mlx4_buf_free(dev->dev, entries * sizeof (struct mlx4_cqe),
+- &cq->buf.buf);
++ mlx4_ib_free_cq_buf(dev, &cq->buf, entries);
+
+ err_db:
+ if (!context)
+@@ -204,6 +258,170 @@ err_cq:
+ return ERR_PTR(err);
+ }
+
++static int mlx4_alloc_resize_buf(struct mlx4_ib_dev *dev, struct mlx4_ib_cq *cq,
++ int entries)
++{
++ int err;
++
++ if (cq->resize_buf)
++ return -EBUSY;
++
++ cq->resize_buf = kmalloc(sizeof *cq->resize_buf, GFP_ATOMIC);
++ if (!cq->resize_buf)
++ return -ENOMEM;
++
++ err = mlx4_ib_alloc_cq_buf(dev, &cq->resize_buf->buf, entries);
++ if (err) {
++ kfree(cq->resize_buf);
++ cq->resize_buf = NULL;
++ return err;
++ }
++
++ cq->resize_buf->cqe = entries - 1;
++
++ return 0;
++}
++
++static int mlx4_alloc_resize_umem(struct mlx4_ib_dev *dev, struct mlx4_ib_cq *cq,
++ int entries, struct ib_udata *udata)
++{
++ struct mlx4_ib_resize_cq ucmd;
++ int err;
++
++ if (cq->resize_umem)
++ return -EBUSY;
++
++ if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
++ return -EFAULT;
++
++ cq->resize_buf = kmalloc(sizeof *cq->resize_buf, GFP_ATOMIC);
++ if (!cq->resize_buf)
++ return -ENOMEM;
++
++ err = mlx4_ib_get_cq_umem(dev, cq->umem->context, &cq->resize_buf->buf,
++ &cq->resize_umem, ucmd.buf_addr, entries);
++ if (err) {
++ kfree(cq->resize_buf);
++ cq->resize_buf = NULL;
++ return err;
++ }
++
++ cq->resize_buf->cqe = entries - 1;
++
++ return 0;
++}
++
++static int mlx4_ib_get_outstanding_cqes(struct mlx4_ib_cq *cq)
++{
++ u32 i;
++
++ i = cq->mcq.cons_index;
++ while (get_sw_cqe(cq, i & cq->ibcq.cqe))
++ ++i;
++
++ return i - cq->mcq.cons_index;
++}
++
++static void mlx4_ib_cq_resize_copy_cqes(struct mlx4_ib_cq *cq)
++{
++ struct mlx4_cqe *cqe;
++ int i;
++
++ i = cq->mcq.cons_index;
++ cqe = get_cqe(cq, i & cq->ibcq.cqe);
++ while ((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) != MLX4_CQE_OPCODE_RESIZE) {
++ memcpy(get_cqe_from_buf(&cq->resize_buf->buf,
++ (i + 1) & cq->resize_buf->cqe),
++ get_cqe(cq, i & cq->ibcq.cqe), sizeof(struct mlx4_cqe));
++ cqe = get_cqe(cq, ++i & cq->ibcq.cqe);
++ }
++ ++cq->mcq.cons_index;
++}
++
++int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata)
++{
++ struct mlx4_ib_dev *dev = to_mdev(ibcq->device);
++ struct mlx4_ib_cq *cq = to_mcq(ibcq);
++ int outst_cqe;
++ int err;
++
++ mutex_lock(&cq->resize_mutex);
++
++ if (entries < 1 || entries > dev->dev->caps.max_cqes) {
++ err = -EINVAL;
++ goto out;
++ }
++
++ entries = roundup_pow_of_two(entries + 1);
++ if (entries == ibcq->cqe + 1) {
++ err = 0;
++ goto out;
++ }
++
++ if (ibcq->uobject) {
++ err = mlx4_alloc_resize_umem(dev, cq, entries, udata);
++ if (err)
++ goto out;
++ } else {
++ /* Can't be smaller then the number of outstanding CQEs */
++ outst_cqe = mlx4_ib_get_outstanding_cqes(cq);
++ if (entries < outst_cqe + 1) {
++ err = 0;
++ goto out;
++ }
++
++ err = mlx4_alloc_resize_buf(dev, cq, entries);
++ if (err)
++ goto out;
++ }
++
++ err = mlx4_cq_resize(dev->dev, &cq->mcq, entries, &cq->resize_buf->buf.mtt);
++ if (err)
++ goto err_buf;
++
++ if (ibcq->uobject) {
++ cq->buf = cq->resize_buf->buf;
++ cq->ibcq.cqe = cq->resize_buf->cqe;
++ ib_umem_release(cq->umem);
++ cq->umem = cq->resize_umem;
++
++ kfree(cq->resize_buf);
++ cq->resize_buf = NULL;
++ cq->resize_umem = NULL;
++ } else {
++ spin_lock_irq(&cq->lock);
++ if (cq->resize_buf) {
++ mlx4_ib_cq_resize_copy_cqes(cq);
++ mlx4_ib_free_cq_buf(dev, &cq->buf, cq->ibcq.cqe);
++ cq->buf = cq->resize_buf->buf;
++ cq->ibcq.cqe = cq->resize_buf->cqe;
++
++ kfree(cq->resize_buf);
++ cq->resize_buf = NULL;
++ }
++ spin_unlock_irq(&cq->lock);
++ }
++
++ goto out;
++
++err_buf:
++ if (!ibcq->uobject)
++ mlx4_ib_free_cq_buf(dev, &cq->resize_buf->buf,
++ cq->resize_buf->cqe);
++
++ kfree(cq->resize_buf);
++ cq->resize_buf = NULL;
++
++ if (cq->resize_umem) {
++ ib_umem_release(cq->resize_umem);
++ cq->resize_umem = NULL;
++ }
++
++out:
++ mutex_unlock(&cq->resize_mutex);
++ return err;
++}
++
+ int mlx4_ib_destroy_cq(struct ib_cq *cq)
+ {
+ struct mlx4_ib_dev *dev = to_mdev(cq->device);
+@@ -216,8 +434,7 @@ int mlx4_ib_destroy_cq(struct ib_cq *cq)
+ mlx4_ib_db_unmap_user(to_mucontext(cq->uobject->context), &mcq->db);
+ ib_umem_release(mcq->umem);
+ } else {
+- mlx4_buf_free(dev->dev, (cq->cqe + 1) * sizeof (struct mlx4_cqe),
+- &mcq->buf.buf);
++ mlx4_ib_free_cq_buf(dev, &mcq->buf, cq->cqe + 1);
+ mlx4_ib_db_free(dev, &mcq->db);
+ }
+
+@@ -297,6 +514,20 @@ static void mlx4_ib_handle_error_cqe(struct mlx4_err_cqe *cqe,
+ wc->vendor_err = cqe->vendor_err_syndrome;
+ }
+
++static int mlx4_ib_ipoib_csum_ok(__be32 status, __be16 checksum)
++{
++ return ((status & cpu_to_be32(MLX4_CQE_IPOIB_STATUS_IPV4 |
++ MLX4_CQE_IPOIB_STATUS_IPV4F |
++ MLX4_CQE_IPOIB_STATUS_IPV4OPT |
++ MLX4_CQE_IPOIB_STATUS_IPV6 |
++ MLX4_CQE_IPOIB_STATUS_IPOK)) ==
++ cpu_to_be32(MLX4_CQE_IPOIB_STATUS_IPV4 |
++ MLX4_CQE_IPOIB_STATUS_IPOK)) &&
++ (status & cpu_to_be32(MLX4_CQE_IPOIB_STATUS_UDP |
++ MLX4_CQE_IPOIB_STATUS_TCP)) &&
++ checksum == cpu_to_be16(0xffff);
++}
++
+ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
+ struct mlx4_ib_qp **cur_qp,
+ struct ib_wc *wc)
+@@ -310,6 +541,7 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
+ u32 g_mlpath_rqpn;
+ u16 wqe_ctr;
+
++repoll:
+ cqe = next_cqe_sw(cq);
+ if (!cqe)
+ return -EAGAIN;
+@@ -332,6 +564,22 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
+ return -EINVAL;
+ }
+
++ /* Resize CQ in progress */
++ if (unlikely((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) == MLX4_CQE_OPCODE_RESIZE)) {
++ if (cq->resize_buf) {
++ struct mlx4_ib_dev *dev = to_mdev(cq->ibcq.device);
++
++ mlx4_ib_free_cq_buf(dev, &cq->buf, cq->ibcq.cqe);
++ cq->buf = cq->resize_buf->buf;
++ cq->ibcq.cqe = cq->resize_buf->cqe;
++
++ kfree(cq->resize_buf);
++ cq->resize_buf = NULL;
++ }
++
++ goto repoll;
++ }
++
+ if (!*cur_qp ||
+ (be32_to_cpu(cqe->my_qpn) & 0xffffff) != (*cur_qp)->mqp.qpn) {
+ /*
+@@ -406,6 +654,9 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
+ case MLX4_OPCODE_BIND_MW:
+ wc->opcode = IB_WC_BIND_MW;
+ break;
++ case MLX4_OPCODE_LSO:
++ wc->opcode = IB_WC_LSO;
++ break;
+ }
+ } else {
+ wc->byte_len = be32_to_cpu(cqe->byte_cnt);
+@@ -434,6 +685,8 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
+ wc->dlid_path_bits = (g_mlpath_rqpn >> 24) & 0x7f;
+ wc->wc_flags |= g_mlpath_rqpn & 0x80000000 ? IB_WC_GRH : 0;
+ wc->pkey_index = be32_to_cpu(cqe->immed_rss_invalid) & 0x7f;
++ wc->csum_ok = mlx4_ib_ipoib_csum_ok(cqe->ipoib_status,
++ cqe->checksum);
+ }
+
+ return 0;
+diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
+index 0ed02b7..4c1e72f 100644
+--- a/drivers/infiniband/hw/mlx4/mad.c
++++ b/drivers/infiniband/hw/mlx4/mad.c
+@@ -165,7 +165,7 @@ static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad)
+ event.device = ibdev;
+ event.element.port_num = port_num;
+
+- if(pinfo->clientrereg_resv_subnetto & 0x80)
++ if (pinfo->clientrereg_resv_subnetto & 0x80)
+ event.event = IB_EVENT_CLIENT_REREGISTER;
+ else
+ event.event = IB_EVENT_LID_CHANGE;
+diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
+index 96a39b5..4d9b5ac 100644
+--- a/drivers/infiniband/hw/mlx4/main.c
++++ b/drivers/infiniband/hw/mlx4/main.c
+@@ -44,8 +44,8 @@
+ #include "user.h"
+
+ #define DRV_NAME "mlx4_ib"
+-#define DRV_VERSION "0.01"
+-#define DRV_RELDATE "May 1, 2006"
++#define DRV_VERSION "1.0"
++#define DRV_RELDATE "April 4, 2008"
+
+ MODULE_AUTHOR("Roland Dreier");
+ MODULE_DESCRIPTION("Mellanox ConnectX HCA InfiniBand driver");
+@@ -99,6 +99,10 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
+ props->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG;
+ if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_UD_AV_PORT)
+ props->device_cap_flags |= IB_DEVICE_UD_AV_PORT_ENFORCE;
++ if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_IPOIB_CSUM)
++ props->device_cap_flags |= IB_DEVICE_UD_IP_CSUM;
++ if (dev->dev->caps.max_gso_sz)
++ props->device_cap_flags |= IB_DEVICE_UD_TSO;
+
+ props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
+ 0xffffff;
+@@ -477,42 +481,51 @@ out:
+ return err;
+ }
+
+-static ssize_t show_hca(struct class_device *cdev, char *buf)
++static ssize_t show_hca(struct device *device, struct device_attribute *attr,
++ char *buf)
+ {
+- struct mlx4_ib_dev *dev = container_of(cdev, struct mlx4_ib_dev, ib_dev.class_dev);
++ struct mlx4_ib_dev *dev =
++ container_of(device, struct mlx4_ib_dev, ib_dev.dev);
+ return sprintf(buf, "MT%d\n", dev->dev->pdev->device);
+ }
+
+-static ssize_t show_fw_ver(struct class_device *cdev, char *buf)
++static ssize_t show_fw_ver(struct device *device, struct device_attribute *attr,
++ char *buf)
+ {
+- struct mlx4_ib_dev *dev = container_of(cdev, struct mlx4_ib_dev, ib_dev.class_dev);
++ struct mlx4_ib_dev *dev =
++ container_of(device, struct mlx4_ib_dev, ib_dev.dev);
+ return sprintf(buf, "%d.%d.%d\n", (int) (dev->dev->caps.fw_ver >> 32),
+ (int) (dev->dev->caps.fw_ver >> 16) & 0xffff,
+ (int) dev->dev->caps.fw_ver & 0xffff);
+ }
+
+-static ssize_t show_rev(struct class_device *cdev, char *buf)
++static ssize_t show_rev(struct device *device, struct device_attribute *attr,
++ char *buf)
+ {
+- struct mlx4_ib_dev *dev = container_of(cdev, struct mlx4_ib_dev, ib_dev.class_dev);
++ struct mlx4_ib_dev *dev =
++ container_of(device, struct mlx4_ib_dev, ib_dev.dev);
+ return sprintf(buf, "%x\n", dev->dev->rev_id);
+ }
+
+-static ssize_t show_board(struct class_device *cdev, char *buf)
++static ssize_t show_board(struct device *device, struct device_attribute *attr,
++ char *buf)
+ {
+- struct mlx4_ib_dev *dev = container_of(cdev, struct mlx4_ib_dev, ib_dev.class_dev);
+- return sprintf(buf, "%.*s\n", MLX4_BOARD_ID_LEN, dev->dev->board_id);
++ struct mlx4_ib_dev *dev =
++ container_of(device, struct mlx4_ib_dev, ib_dev.dev);
++ return sprintf(buf, "%.*s\n", MLX4_BOARD_ID_LEN,
++ dev->dev->board_id);
+ }
+
+-static CLASS_DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
+-static CLASS_DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
+-static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
+-static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
++static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
++static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
++static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
++static DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
+
+-static struct class_device_attribute *mlx4_class_attributes[] = {
+- &class_device_attr_hw_rev,
+- &class_device_attr_fw_ver,
+- &class_device_attr_hca_type,
+- &class_device_attr_board_id
++static struct device_attribute *mlx4_class_attributes[] = {
++ &dev_attr_hw_rev,
++ &dev_attr_fw_ver,
++ &dev_attr_hca_type,
++ &dev_attr_board_id
+ };
+
+ static void *mlx4_ib_add(struct mlx4_dev *dev)
+@@ -567,6 +580,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
+ (1ull << IB_USER_VERBS_CMD_DEREG_MR) |
+ (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) |
+ (1ull << IB_USER_VERBS_CMD_CREATE_CQ) |
++ (1ull << IB_USER_VERBS_CMD_RESIZE_CQ) |
+ (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) |
+ (1ull << IB_USER_VERBS_CMD_CREATE_QP) |
+ (1ull << IB_USER_VERBS_CMD_MODIFY_QP) |
+@@ -605,6 +619,8 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
+ ibdev->ib_dev.post_send = mlx4_ib_post_send;
+ ibdev->ib_dev.post_recv = mlx4_ib_post_recv;
+ ibdev->ib_dev.create_cq = mlx4_ib_create_cq;
++ ibdev->ib_dev.modify_cq = mlx4_ib_modify_cq;
++ ibdev->ib_dev.resize_cq = mlx4_ib_resize_cq;
+ ibdev->ib_dev.destroy_cq = mlx4_ib_destroy_cq;
+ ibdev->ib_dev.poll_cq = mlx4_ib_poll_cq;
+ ibdev->ib_dev.req_notify_cq = mlx4_ib_arm_cq;
+@@ -633,8 +649,8 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
+ goto err_reg;
+
+ for (i = 0; i < ARRAY_SIZE(mlx4_class_attributes); ++i) {
+- if (class_device_create_file(&ibdev->ib_dev.class_dev,
+- mlx4_class_attributes[i]))
++ if (device_create_file(&ibdev->ib_dev.dev,
++ mlx4_class_attributes[i]))
+ goto err_reg;
+ }
+
+@@ -675,18 +691,20 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
+ }
+
+ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr,
+- enum mlx4_dev_event event, int subtype,
+- int port)
++ enum mlx4_dev_event event, int port)
+ {
+ struct ib_event ibev;
+
+ switch (event) {
+- case MLX4_EVENT_TYPE_PORT_CHANGE:
+- ibev.event = subtype == MLX4_PORT_CHANGE_SUBTYPE_ACTIVE ?
+- IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR;
++ case MLX4_DEV_EVENT_PORT_UP:
++ ibev.event = IB_EVENT_PORT_ACTIVE;
+ break;
+
+- case MLX4_EVENT_TYPE_LOCAL_CATAS_ERROR:
++ case MLX4_DEV_EVENT_PORT_DOWN:
++ ibev.event = IB_EVENT_PORT_ERR;
++ break;
++
++ case MLX4_DEV_EVENT_CATASTROPHIC_ERROR:
+ ibev.event = IB_EVENT_DEVICE_FATAL;
+ break;
+
+diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
+index 3726e45..9e63732 100644
+--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
++++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
+@@ -78,13 +78,21 @@ struct mlx4_ib_cq_buf {
+ struct mlx4_mtt mtt;
+ };
+
++struct mlx4_ib_cq_resize {
++ struct mlx4_ib_cq_buf buf;
++ int cqe;
++};
++
+ struct mlx4_ib_cq {
+ struct ib_cq ibcq;
+ struct mlx4_cq mcq;
+ struct mlx4_ib_cq_buf buf;
++ struct mlx4_ib_cq_resize *resize_buf;
+ struct mlx4_ib_db db;
+ spinlock_t lock;
++ struct mutex resize_mutex;
+ struct ib_umem *umem;
++ struct ib_umem *resize_umem;
+ };
+
+ struct mlx4_ib_mr {
+@@ -110,6 +118,10 @@ struct mlx4_ib_wq {
+ unsigned tail;
+ };
+
++enum mlx4_ib_qp_flags {
++ MLX4_IB_QP_LSO = 1 << 0
++};
++
+ struct mlx4_ib_qp {
+ struct ib_qp ibqp;
+ struct mlx4_qp mqp;
+@@ -129,6 +141,7 @@ struct mlx4_ib_qp {
+ struct mlx4_mtt mtt;
+ int buf_size;
+ struct mutex mutex;
++ u32 flags;
+ u8 port;
+ u8 alt_port;
+ u8 atomic_rd_en;
+@@ -249,6 +262,8 @@ struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+ struct ib_udata *udata);
+ int mlx4_ib_dereg_mr(struct ib_mr *mr);
+
++int mlx4_ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period);
++int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata);
+ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector,
+ struct ib_ucontext *context,
+ struct ib_udata *udata);
+diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
+index 958e205..b75efae 100644
+--- a/drivers/infiniband/hw/mlx4/qp.c
++++ b/drivers/infiniband/hw/mlx4/qp.c
+@@ -71,6 +71,7 @@ enum {
+
+ static const __be32 mlx4_ib_opcode[] = {
+ [IB_WR_SEND] = __constant_cpu_to_be32(MLX4_OPCODE_SEND),
++ [IB_WR_LSO] = __constant_cpu_to_be32(MLX4_OPCODE_LSO),
+ [IB_WR_SEND_WITH_IMM] = __constant_cpu_to_be32(MLX4_OPCODE_SEND_IMM),
+ [IB_WR_RDMA_WRITE] = __constant_cpu_to_be32(MLX4_OPCODE_RDMA_WRITE),
+ [IB_WR_RDMA_WRITE_WITH_IMM] = __constant_cpu_to_be32(MLX4_OPCODE_RDMA_WRITE_IMM),
+@@ -122,7 +123,7 @@ static void *get_send_wqe(struct mlx4_ib_qp *qp, int n)
+ */
+ static void stamp_send_wqe(struct mlx4_ib_qp *qp, int n, int size)
+ {
+- u32 *wqe;
++ __be32 *wqe;
+ int i;
+ int s;
+ int ind;
+@@ -143,7 +144,7 @@ static void stamp_send_wqe(struct mlx4_ib_qp *qp, int n, int size)
+ buf = get_send_wqe(qp, n & (qp->sq.wqe_cnt - 1));
+ for (i = 64; i < s; i += 64) {
+ wqe = buf + i;
+- *wqe = 0xffffffff;
++ *wqe = cpu_to_be32(0xffffffff);
+ }
+ }
+ }
+@@ -242,7 +243,7 @@ static void mlx4_ib_qp_event(struct mlx4_qp *qp, enum mlx4_event type)
+ }
+ }
+
+-static int send_wqe_overhead(enum ib_qp_type type)
++static int send_wqe_overhead(enum ib_qp_type type, u32 flags)
+ {
+ /*
+ * UD WQEs must have a datagram segment.
+@@ -253,7 +254,8 @@ static int send_wqe_overhead(enum ib_qp_type type)
+ switch (type) {
+ case IB_QPT_UD:
+ return sizeof (struct mlx4_wqe_ctrl_seg) +
+- sizeof (struct mlx4_wqe_datagram_seg);
++ sizeof (struct mlx4_wqe_datagram_seg) +
++ ((flags & MLX4_IB_QP_LSO) ? 64 : 0);
+ case IB_QPT_UC:
+ return sizeof (struct mlx4_wqe_ctrl_seg) +
+ sizeof (struct mlx4_wqe_raddr_seg);
+@@ -315,7 +317,7 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
+ /* Sanity check SQ size before proceeding */
+ if (cap->max_send_wr > dev->dev->caps.max_wqes ||
+ cap->max_send_sge > dev->dev->caps.max_sq_sg ||
+- cap->max_inline_data + send_wqe_overhead(type) +
++ cap->max_inline_data + send_wqe_overhead(type, qp->flags) +
+ sizeof (struct mlx4_wqe_inline_seg) > dev->dev->caps.max_sq_desc_sz)
+ return -EINVAL;
+
+@@ -329,7 +331,7 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
+
+ s = max(cap->max_send_sge * sizeof (struct mlx4_wqe_data_seg),
+ cap->max_inline_data + sizeof (struct mlx4_wqe_inline_seg)) +
+- send_wqe_overhead(type);
++ send_wqe_overhead(type, qp->flags);
+
+ /*
+ * Hermon supports shrinking WQEs, such that a single work
+@@ -394,7 +396,8 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
+ }
+
+ qp->sq.max_gs = ((qp->sq_max_wqes_per_wr << qp->sq.wqe_shift) -
+- send_wqe_overhead(type)) / sizeof (struct mlx4_wqe_data_seg);
++ send_wqe_overhead(type, qp->flags)) /
++ sizeof (struct mlx4_wqe_data_seg);
+
+ qp->buf_size = (qp->rq.wqe_cnt << qp->rq.wqe_shift) +
+ (qp->sq.wqe_cnt << qp->sq.wqe_shift);
+@@ -503,6 +506,9 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
+ } else {
+ qp->sq_no_prefetch = 0;
+
++ if (init_attr->create_flags & IB_QP_CREATE_IPOIB_UD_LSO)
++ qp->flags |= MLX4_IB_QP_LSO;
++
+ err = set_kernel_sq_size(dev, &init_attr->cap, init_attr->qp_type, qp);
+ if (err)
+ goto err;
+@@ -673,6 +679,13 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
+ struct mlx4_ib_qp *qp;
+ int err;
+
++ /* We only support LSO, and only for kernel UD QPs. */
++ if (init_attr->create_flags & ~IB_QP_CREATE_IPOIB_UD_LSO)
++ return ERR_PTR(-EINVAL);
++ if (init_attr->create_flags & IB_QP_CREATE_IPOIB_UD_LSO &&
++ (pd->uobject || init_attr->qp_type != IB_QPT_UD))
++ return ERR_PTR(-EINVAL);
++
+ switch (init_attr->qp_type) {
+ case IB_QPT_RC:
+ case IB_QPT_UC:
+@@ -876,10 +889,15 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
+ }
+ }
+
+- if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI ||
+- ibqp->qp_type == IB_QPT_UD)
++ if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI)
+ context->mtu_msgmax = (IB_MTU_4096 << 5) | 11;
+- else if (attr_mask & IB_QP_PATH_MTU) {
++ else if (ibqp->qp_type == IB_QPT_UD) {
++ if (qp->flags & MLX4_IB_QP_LSO)
++ context->mtu_msgmax = (IB_MTU_4096 << 5) |
++ ilog2(dev->dev->caps.max_gso_sz);
++ else
++ context->mtu_msgmax = (IB_MTU_4096 << 5) | 11;
++ } else if (attr_mask & IB_QP_PATH_MTU) {
+ if (attr->path_mtu < IB_MTU_256 || attr->path_mtu > IB_MTU_4096) {
+ printk(KERN_ERR "path MTU (%u) is invalid\n",
+ attr->path_mtu);
+@@ -1182,7 +1200,7 @@ out:
+ }
+
+ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
+- void *wqe)
++ void *wqe, unsigned *mlx_seg_len)
+ {
+ struct ib_device *ib_dev = &to_mdev(sqp->qp.ibqp.device)->ib_dev;
+ struct mlx4_wqe_mlx_seg *mlx = wqe;
+@@ -1231,7 +1249,7 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
+ case IB_WR_SEND_WITH_IMM:
+ sqp->ud_header.bth.opcode = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
+ sqp->ud_header.immediate_present = 1;
+- sqp->ud_header.immediate_data = wr->imm_data;
++ sqp->ud_header.immediate_data = wr->ex.imm_data;
+ break;
+ default:
+ return -EINVAL;
+@@ -1303,7 +1321,9 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
+ i = 2;
+ }
+
+- return ALIGN(i * sizeof (struct mlx4_wqe_inline_seg) + header_size, 16);
++ *mlx_seg_len =
++ ALIGN(i * sizeof (struct mlx4_wqe_inline_seg) + header_size, 16);
++ return 0;
+ }
+
+ static int mlx4_wq_overflow(struct mlx4_ib_wq *wq, int nreq, struct ib_cq *ib_cq)
+@@ -1396,6 +1416,34 @@ static void __set_data_seg(struct mlx4_wqe_data_seg *dseg, struct ib_sge *sg)
+ dseg->addr = cpu_to_be64(sg->addr);
+ }
+
++static int build_lso_seg(struct mlx4_lso_seg *wqe, struct ib_send_wr *wr,
++ struct mlx4_ib_qp *qp, unsigned *lso_seg_len)
++{
++ unsigned halign = ALIGN(sizeof *wqe + wr->wr.ud.hlen, 16);
++
++ /*
++ * This is a temporary limitation and will be removed in
++ * a forthcoming FW release:
++ */
++ if (unlikely(halign > 64))
++ return -EINVAL;
++
++ if (unlikely(!(qp->flags & MLX4_IB_QP_LSO) &&
++ wr->num_sge > qp->sq.max_gs - (halign >> 4)))
++ return -EINVAL;
++
++ memcpy(wqe->header, wr->wr.ud.header, wr->wr.ud.hlen);
++
++ /* make sure LSO header is written before overwriting stamping */
++ wmb();
++
++ wqe->mss_hdr_size = cpu_to_be32((wr->wr.ud.mss - wr->wr.ud.hlen) << 16 |
++ wr->wr.ud.hlen);
++
++ *lso_seg_len = halign;
++ return 0;
++}
++
+ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ struct ib_send_wr **bad_wr)
+ {
+@@ -1409,6 +1457,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ unsigned ind;
+ int uninitialized_var(stamp);
+ int uninitialized_var(size);
++ unsigned seglen;
+ int i;
+
+ spin_lock_irqsave(&qp->sq.lock, flags);
+@@ -1436,11 +1485,14 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE) : 0) |
+ (wr->send_flags & IB_SEND_SOLICITED ?
+ cpu_to_be32(MLX4_WQE_CTRL_SOLICITED) : 0) |
++ ((wr->send_flags & IB_SEND_IP_CSUM) ?
++ cpu_to_be32(MLX4_WQE_CTRL_IP_CSUM |
++ MLX4_WQE_CTRL_TCP_UDP_CSUM) : 0) |
+ qp->sq_signal_bits;
+
+ if (wr->opcode == IB_WR_SEND_WITH_IMM ||
+ wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM)
+- ctrl->imm = wr->imm_data;
++ ctrl->imm = wr->ex.imm_data;
+ else
+ ctrl->imm = 0;
+
+@@ -1484,19 +1536,27 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ set_datagram_seg(wqe, wr);
+ wqe += sizeof (struct mlx4_wqe_datagram_seg);
+ size += sizeof (struct mlx4_wqe_datagram_seg) / 16;
++
++ if (wr->opcode == IB_WR_LSO) {
++ err = build_lso_seg(wqe, wr, qp, &seglen);
++ if (unlikely(err)) {
++ *bad_wr = wr;
++ goto out;
++ }
++ wqe += seglen;
++ size += seglen / 16;
++ }
+ break;
+
+ case IB_QPT_SMI:
+ case IB_QPT_GSI:
+- err = build_mlx_header(to_msqp(qp), wr, ctrl);
+- if (err < 0) {
++ err = build_mlx_header(to_msqp(qp), wr, ctrl, &seglen);
++ if (unlikely(err)) {
+ *bad_wr = wr;
+ goto out;
+ }
+- wqe += err;
+- size += err / 16;
+-
+- err = 0;
++ wqe += seglen;
++ size += seglen / 16;
+ break;
+
+ default:
+@@ -1725,7 +1785,9 @@ int mlx4_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr
+ struct mlx4_ib_qp *qp = to_mqp(ibqp);
+ struct mlx4_qp_context context;
+ int mlx4_state;
+- int err;
++ int err = 0;
++
++ mutex_lock(&qp->mutex);
+
+ if (qp->state == IB_QPS_RESET) {
+ qp_attr->qp_state = IB_QPS_RESET;
+@@ -1733,12 +1795,15 @@ int mlx4_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr
+ }
+
+ err = mlx4_qp_query(dev->dev, &qp->mqp, &context);
+- if (err)
+- return -EINVAL;
++ if (err) {
++ err = -EINVAL;
++ goto out;
++ }
+
+ mlx4_state = be32_to_cpu(context.flags) >> 28;
+
+- qp_attr->qp_state = to_ib_qp_state(mlx4_state);
++ qp->state = to_ib_qp_state(mlx4_state);
++ qp_attr->qp_state = qp->state;
+ qp_attr->path_mtu = context.mtu_msgmax >> 5;
+ qp_attr->path_mig_state =
+ to_ib_mig_state((be32_to_cpu(context.flags) >> 11) & 0x3);
+@@ -1797,6 +1862,8 @@ done:
+
+ qp_init_attr->cap = qp_attr->cap;
+
+- return 0;
++out:
++ mutex_unlock(&qp->mutex);
++ return err;
+ }
+
+diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
+index 09a30dd..54d230e 100644
+--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
++++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
+@@ -219,7 +219,7 @@ static void mthca_cmd_post_dbell(struct mthca_dev *dev,
+ __raw_writel((__force u32) cpu_to_be32((1 << HCR_GO_BIT) |
+ (1 << HCA_E_BIT) |
+ (op_modifier << HCR_OPMOD_SHIFT) |
+- op), ptr + offs[6]);
++ op), ptr + offs[6]);
+ wmb();
+ __raw_writel((__force u32) 0, ptr + offs[7]);
+ wmb();
+@@ -1339,6 +1339,10 @@ int mthca_INIT_HCA(struct mthca_dev *dev,
+ /* Check port for UD address vector: */
+ *(inbox + INIT_HCA_FLAGS2_OFFSET / 4) |= cpu_to_be32(1);
+
++ /* Enable IPoIB checksumming if we can: */
++ if (dev->device_cap_flags & IB_DEVICE_UD_IP_CSUM)
++ *(inbox + INIT_HCA_FLAGS2_OFFSET / 4) |= cpu_to_be32(7 << 3);
++
+ /* We leave wqe_quota, responder_exu, etc as 0 (default) */
+
+ /* QPC/EEC/CQC/EQC/RDB attributes */
+diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.h b/drivers/infiniband/hw/mthca/mthca_cmd.h
+index 2f976f2..8928ca4 100644
+--- a/drivers/infiniband/hw/mthca/mthca_cmd.h
++++ b/drivers/infiniband/hw/mthca/mthca_cmd.h
+@@ -103,6 +103,7 @@ enum {
+ DEV_LIM_FLAG_RAW_IPV6 = 1 << 4,
+ DEV_LIM_FLAG_RAW_ETHER = 1 << 5,
+ DEV_LIM_FLAG_SRQ = 1 << 6,
++ DEV_LIM_FLAG_IPOIB_CSUM = 1 << 7,
+ DEV_LIM_FLAG_BAD_PKEY_CNTR = 1 << 8,
+ DEV_LIM_FLAG_BAD_QKEY_CNTR = 1 << 9,
+ DEV_LIM_FLAG_MW = 1 << 16,
+diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
+index 1e1e336..20401d2 100644
+--- a/drivers/infiniband/hw/mthca/mthca_cq.c
++++ b/drivers/infiniband/hw/mthca/mthca_cq.c
+@@ -119,7 +119,8 @@ struct mthca_cqe {
+ __be32 my_qpn;
+ __be32 my_ee;
+ __be32 rqpn;
+- __be16 sl_g_mlpath;
++ u8 sl_ipok;
++ u8 g_mlpath;
+ __be16 rlid;
+ __be32 imm_etype_pkey_eec;
+ __be32 byte_cnt;
+@@ -493,6 +494,7 @@ static inline int mthca_poll_one(struct mthca_dev *dev,
+ int is_send;
+ int free_cqe = 1;
+ int err = 0;
++ u16 checksum;
+
+ cqe = next_cqe_sw(cq);
+ if (!cqe)
+@@ -635,12 +637,14 @@ static inline int mthca_poll_one(struct mthca_dev *dev,
+ break;
+ }
+ entry->slid = be16_to_cpu(cqe->rlid);
+- entry->sl = be16_to_cpu(cqe->sl_g_mlpath) >> 12;
++ entry->sl = cqe->sl_ipok >> 4;
+ entry->src_qp = be32_to_cpu(cqe->rqpn) & 0xffffff;
+- entry->dlid_path_bits = be16_to_cpu(cqe->sl_g_mlpath) & 0x7f;
++ entry->dlid_path_bits = cqe->g_mlpath & 0x7f;
+ entry->pkey_index = be32_to_cpu(cqe->imm_etype_pkey_eec) >> 16;
+- entry->wc_flags |= be16_to_cpu(cqe->sl_g_mlpath) & 0x80 ?
+- IB_WC_GRH : 0;
++ entry->wc_flags |= cqe->g_mlpath & 0x80 ? IB_WC_GRH : 0;
++ checksum = (be32_to_cpu(cqe->rqpn) >> 24) |
++ ((be32_to_cpu(cqe->my_ee) >> 16) & 0xff00);
++ entry->csum_ok = (cqe->sl_ipok & 1 && checksum == 0xffff);
+ }
+
+ entry->status = IB_WC_SUCCESS;
+diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
+index 7bbdd1f..7bc32f8 100644
+--- a/drivers/infiniband/hw/mthca/mthca_dev.h
++++ b/drivers/infiniband/hw/mthca/mthca_dev.h
+@@ -46,16 +46,15 @@
+ #include <linux/timer.h>
+ #include <linux/mutex.h>
+ #include <linux/list.h>
+-
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+
+ #include "mthca_provider.h"
+ #include "mthca_doorbell.h"
+
+ #define DRV_NAME "ib_mthca"
+ #define PFX DRV_NAME ": "
+-#define DRV_VERSION "0.08"
+-#define DRV_RELDATE "February 14, 2006"
++#define DRV_VERSION "1.0"
++#define DRV_RELDATE "April 4, 2008"
+
+ enum {
+ MTHCA_FLAG_DDR_HIDDEN = 1 << 1,
+@@ -390,11 +389,11 @@ extern void __buggy_use_of_MTHCA_PUT(void);
+ do { \
+ void *__p = (char *) (source) + (offset); \
+ switch (sizeof (dest)) { \
+- case 1: (dest) = *(u8 *) __p; break; \
+- case 2: (dest) = be16_to_cpup(__p); break; \
+- case 4: (dest) = be32_to_cpup(__p); break; \
+- case 8: (dest) = be64_to_cpup(__p); break; \
+- default: __buggy_use_of_MTHCA_GET(); \
++ case 1: (dest) = *(u8 *) __p; break; \
++ case 2: (dest) = be16_to_cpup(__p); break; \
++ case 4: (dest) = be32_to_cpup(__p); break; \
++ case 8: (dest) = be64_to_cpup(__p); break; \
++ default: __buggy_use_of_MTHCA_GET(); \
+ } \
+ } while (0)
+
+diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
+index b60eb5d..8bde7f9 100644
+--- a/drivers/infiniband/hw/mthca/mthca_eq.c
++++ b/drivers/infiniband/hw/mthca/mthca_eq.c
+@@ -232,9 +232,9 @@ static inline struct mthca_eqe *get_eqe(struct mthca_eq *eq, u32 entry)
+ return eq->page_list[off / PAGE_SIZE].buf + off % PAGE_SIZE;
+ }
+
+-static inline struct mthca_eqe* next_eqe_sw(struct mthca_eq *eq)
++static inline struct mthca_eqe *next_eqe_sw(struct mthca_eq *eq)
+ {
+- struct mthca_eqe* eqe;
++ struct mthca_eqe *eqe;
+ eqe = get_eqe(eq, eq->cons_index);
+ return (MTHCA_EQ_ENTRY_OWNER_HW & eqe->owner) ? NULL : eqe;
+ }
+diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c
+index acfa41d..8b7e83e 100644
+--- a/drivers/infiniband/hw/mthca/mthca_mad.c
++++ b/drivers/infiniband/hw/mthca/mthca_mad.c
+@@ -125,7 +125,7 @@ static void smp_snoop(struct ib_device *ibdev,
+ event.device = ibdev;
+ event.element.port_num = port_num;
+
+- if(pinfo->clientrereg_resv_subnetto & 0x80)
++ if (pinfo->clientrereg_resv_subnetto & 0x80)
+ event.event = IB_EVENT_CLIENT_REREGISTER;
+ else
+ event.event = IB_EVENT_LID_CHANGE;
+diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
+index cd3d8ad..9ebadd6 100644
+--- a/drivers/infiniband/hw/mthca/mthca_main.c
++++ b/drivers/infiniband/hw/mthca/mthca_main.c
+@@ -267,11 +267,16 @@ static int mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim *dev_lim)
+ if (dev_lim->flags & DEV_LIM_FLAG_SRQ)
+ mdev->mthca_flags |= MTHCA_FLAG_SRQ;
+
++ if (mthca_is_memfree(mdev))
++ if (dev_lim->flags & DEV_LIM_FLAG_IPOIB_CSUM)
++ mdev->device_cap_flags |= IB_DEVICE_UD_IP_CSUM;
++
+ return 0;
+ }
+
+ static int mthca_init_tavor(struct mthca_dev *mdev)
+ {
++ s64 size;
+ u8 status;
+ int err;
+ struct mthca_dev_lim dev_lim;
+@@ -324,9 +329,11 @@ static int mthca_init_tavor(struct mthca_dev *mdev)
+ if (mdev->mthca_flags & MTHCA_FLAG_SRQ)
+ profile.num_srq = dev_lim.max_srqs;
+
+- err = mthca_make_profile(mdev, &profile, &dev_lim, &init_hca);
+- if (err < 0)
++ size = mthca_make_profile(mdev, &profile, &dev_lim, &init_hca);
++ if (size < 0) {
++ err = size;
+ goto err_disable;
++ }
+
+ err = mthca_INIT_HCA(mdev, &init_hca, &status);
+ if (err) {
+@@ -605,7 +612,7 @@ static int mthca_init_arbel(struct mthca_dev *mdev)
+ struct mthca_dev_lim dev_lim;
+ struct mthca_profile profile;
+ struct mthca_init_hca_param init_hca;
+- u64 icm_size;
++ s64 icm_size;
+ u8 status;
+ int err;
+
+@@ -653,7 +660,7 @@ static int mthca_init_arbel(struct mthca_dev *mdev)
+ profile.num_srq = dev_lim.max_srqs;
+
+ icm_size = mthca_make_profile(mdev, &profile, &dev_lim, &init_hca);
+- if ((int) icm_size < 0) {
++ if (icm_size < 0) {
+ err = icm_size;
+ goto err_stop_fw;
+ }
+diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
+index 252db08..b224079 100644
+--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
++++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
+@@ -359,12 +359,14 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
+ int use_lowmem, int use_coherent)
+ {
+ struct mthca_icm_table *table;
++ int obj_per_chunk;
+ int num_icm;
+ unsigned chunk_size;
+ int i;
+ u8 status;
+
+- num_icm = (obj_size * nobj + MTHCA_TABLE_CHUNK_SIZE - 1) / MTHCA_TABLE_CHUNK_SIZE;
++ obj_per_chunk = MTHCA_TABLE_CHUNK_SIZE / obj_size;
++ num_icm = DIV_ROUND_UP(nobj, obj_per_chunk);
+
+ table = kmalloc(sizeof *table + num_icm * sizeof *table->icm, GFP_KERNEL);
+ if (!table)
+@@ -412,7 +414,7 @@ err:
+ if (table->icm[i]) {
+ mthca_UNMAP_ICM(dev, virt + i * MTHCA_TABLE_CHUNK_SIZE,
+ MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE,
+- &status);
++ &status);
+ mthca_free_icm(dev, table->icm[i], table->coherent);
+ }
+
+diff --git a/drivers/infiniband/hw/mthca/mthca_profile.c b/drivers/infiniband/hw/mthca/mthca_profile.c
+index 26bf86d..605a8d5 100644
+--- a/drivers/infiniband/hw/mthca/mthca_profile.c
++++ b/drivers/infiniband/hw/mthca/mthca_profile.c
+@@ -63,7 +63,7 @@ enum {
+ MTHCA_NUM_PDS = 1 << 15
+ };
+
+-u64 mthca_make_profile(struct mthca_dev *dev,
++s64 mthca_make_profile(struct mthca_dev *dev,
+ struct mthca_profile *request,
+ struct mthca_dev_lim *dev_lim,
+ struct mthca_init_hca_param *init_hca)
+@@ -77,7 +77,7 @@ u64 mthca_make_profile(struct mthca_dev *dev,
+ };
+
+ u64 mem_base, mem_avail;
+- u64 total_size = 0;
++ s64 total_size = 0;
+ struct mthca_resource *profile;
+ struct mthca_resource tmp;
+ int i, j;
+diff --git a/drivers/infiniband/hw/mthca/mthca_profile.h b/drivers/infiniband/hw/mthca/mthca_profile.h
+index 9464180..e76cb62 100644
+--- a/drivers/infiniband/hw/mthca/mthca_profile.h
++++ b/drivers/infiniband/hw/mthca/mthca_profile.h
+@@ -53,7 +53,7 @@ struct mthca_profile {
+ int fmr_reserved_mtts;
+ };
+
+-u64 mthca_make_profile(struct mthca_dev *mdev,
++s64 mthca_make_profile(struct mthca_dev *mdev,
+ struct mthca_profile *request,
+ struct mthca_dev_lim *dev_lim,
+ struct mthca_init_hca_param *init_hca);
+diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
+index 9e491df..696e1f3 100644
+--- a/drivers/infiniband/hw/mthca/mthca_provider.c
++++ b/drivers/infiniband/hw/mthca/mthca_provider.c
+@@ -60,7 +60,7 @@ static int mthca_query_device(struct ib_device *ibdev,
+ struct ib_smp *in_mad = NULL;
+ struct ib_smp *out_mad = NULL;
+ int err = -ENOMEM;
+- struct mthca_dev* mdev = to_mdev(ibdev);
++ struct mthca_dev *mdev = to_mdev(ibdev);
+
+ u8 status;
+
+@@ -540,6 +540,9 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
+ struct mthca_qp *qp;
+ int err;
+
++ if (init_attr->create_flags)
++ return ERR_PTR(-EINVAL);
++
+ switch (init_attr->qp_type) {
+ case IB_QPT_RC:
+ case IB_QPT_UC:
+@@ -1167,23 +1170,29 @@ static int mthca_unmap_fmr(struct list_head *fmr_list)
+ return 0;
+ }
+
+-static ssize_t show_rev(struct class_device *cdev, char *buf)
++static ssize_t show_rev(struct device *device, struct device_attribute *attr,
++ char *buf)
+ {
+- struct mthca_dev *dev = container_of(cdev, struct mthca_dev, ib_dev.class_dev);
++ struct mthca_dev *dev =
++ container_of(device, struct mthca_dev, ib_dev.dev);
+ return sprintf(buf, "%x\n", dev->rev_id);
+ }
+
+-static ssize_t show_fw_ver(struct class_device *cdev, char *buf)
++static ssize_t show_fw_ver(struct device *device, struct device_attribute *attr,
++ char *buf)
+ {
+- struct mthca_dev *dev = container_of(cdev, struct mthca_dev, ib_dev.class_dev);
++ struct mthca_dev *dev =
++ container_of(device, struct mthca_dev, ib_dev.dev);
+ return sprintf(buf, "%d.%d.%d\n", (int) (dev->fw_ver >> 32),
+ (int) (dev->fw_ver >> 16) & 0xffff,
+ (int) dev->fw_ver & 0xffff);
+ }
+
+-static ssize_t show_hca(struct class_device *cdev, char *buf)
++static ssize_t show_hca(struct device *device, struct device_attribute *attr,
++ char *buf)
+ {
+- struct mthca_dev *dev = container_of(cdev, struct mthca_dev, ib_dev.class_dev);
++ struct mthca_dev *dev =
++ container_of(device, struct mthca_dev, ib_dev.dev);
+ switch (dev->pdev->device) {
+ case PCI_DEVICE_ID_MELLANOX_TAVOR:
+ return sprintf(buf, "MT23108\n");
+@@ -1199,22 +1208,24 @@ static ssize_t show_hca(struct class_device *cdev, char *buf)
+ }
+ }
+
+-static ssize_t show_board(struct class_device *cdev, char *buf)
++static ssize_t show_board(struct device *device, struct device_attribute *attr,
++ char *buf)
+ {
+- struct mthca_dev *dev = container_of(cdev, struct mthca_dev, ib_dev.class_dev);
++ struct mthca_dev *dev =
++ container_of(device, struct mthca_dev, ib_dev.dev);
+ return sprintf(buf, "%.*s\n", MTHCA_BOARD_ID_LEN, dev->board_id);
+ }
+
+-static CLASS_DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
+-static CLASS_DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
+-static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
+-static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
++static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
++static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
++static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
++static DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
+
+-static struct class_device_attribute *mthca_class_attributes[] = {
+- &class_device_attr_hw_rev,
+- &class_device_attr_fw_ver,
+- &class_device_attr_hca_type,
+- &class_device_attr_board_id
++static struct device_attribute *mthca_dev_attributes[] = {
++ &dev_attr_hw_rev,
++ &dev_attr_fw_ver,
++ &dev_attr_hca_type,
++ &dev_attr_board_id
+ };
+
+ static int mthca_init_node_data(struct mthca_dev *dev)
+@@ -1376,9 +1387,9 @@ int mthca_register_device(struct mthca_dev *dev)
+ if (ret)
+ return ret;
+
+- for (i = 0; i < ARRAY_SIZE(mthca_class_attributes); ++i) {
+- ret = class_device_create_file(&dev->ib_dev.class_dev,
+- mthca_class_attributes[i]);
++ for (i = 0; i < ARRAY_SIZE(mthca_dev_attributes); ++i) {
++ ret = device_create_file(&dev->ib_dev.dev,
++ mthca_dev_attributes[i]);
+ if (ret) {
+ ib_unregister_device(&dev->ib_dev);
+ return ret;
+diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
+index db5595b..09dc361 100644
+--- a/drivers/infiniband/hw/mthca/mthca_qp.c
++++ b/drivers/infiniband/hw/mthca/mthca_qp.c
+@@ -437,29 +437,34 @@ int mthca_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_m
+ int mthca_state;
+ u8 status;
+
++ mutex_lock(&qp->mutex);
++
+ if (qp->state == IB_QPS_RESET) {
+ qp_attr->qp_state = IB_QPS_RESET;
+ goto done;
+ }
+
+ mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
+- if (IS_ERR(mailbox))
+- return PTR_ERR(mailbox);
++ if (IS_ERR(mailbox)) {
++ err = PTR_ERR(mailbox);
++ goto out;
++ }
+
+ err = mthca_QUERY_QP(dev, qp->qpn, 0, mailbox, &status);
+ if (err)
+- goto out;
++ goto out_mailbox;
+ if (status) {
+ mthca_warn(dev, "QUERY_QP returned status %02x\n", status);
+ err = -EINVAL;
+- goto out;
++ goto out_mailbox;
+ }
+
+ qp_param = mailbox->buf;
+ context = &qp_param->context;
+ mthca_state = be32_to_cpu(context->flags) >> 28;
+
+- qp_attr->qp_state = to_ib_qp_state(mthca_state);
++ qp->state = to_ib_qp_state(mthca_state);
++ qp_attr->qp_state = qp->state;
+ qp_attr->path_mtu = context->mtu_msgmax >> 5;
+ qp_attr->path_mig_state =
+ to_ib_mig_state((be32_to_cpu(context->flags) >> 11) & 0x3);
+@@ -506,8 +511,11 @@ done:
+
+ qp_init_attr->cap = qp_attr->cap;
+
+-out:
++out_mailbox:
+ mthca_free_mailbox(dev, mailbox);
++
++out:
++ mutex_unlock(&qp->mutex);
+ return err;
+ }
+
+@@ -1532,7 +1540,7 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
+ case IB_WR_SEND_WITH_IMM:
+ sqp->ud_header.bth.opcode = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
+ sqp->ud_header.immediate_present = 1;
+- sqp->ud_header.immediate_data = wr->imm_data;
++ sqp->ud_header.immediate_data = wr->ex.imm_data;
+ break;
+ default:
+ return -EINVAL;
+@@ -1679,7 +1687,7 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ cpu_to_be32(1);
+ if (wr->opcode == IB_WR_SEND_WITH_IMM ||
+ wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM)
+- ((struct mthca_next_seg *) wqe)->imm = wr->imm_data;
++ ((struct mthca_next_seg *) wqe)->imm = wr->ex.imm_data;
+
+ wqe += sizeof (struct mthca_next_seg);
+ size = sizeof (struct mthca_next_seg) / 16;
+@@ -2015,10 +2023,12 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ cpu_to_be32(MTHCA_NEXT_CQ_UPDATE) : 0) |
+ ((wr->send_flags & IB_SEND_SOLICITED) ?
+ cpu_to_be32(MTHCA_NEXT_SOLICIT) : 0) |
++ ((wr->send_flags & IB_SEND_IP_CSUM) ?
++ cpu_to_be32(MTHCA_NEXT_IP_CSUM | MTHCA_NEXT_TCP_UDP_CSUM) : 0) |
+ cpu_to_be32(1);
+ if (wr->opcode == IB_WR_SEND_WITH_IMM ||
+ wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM)
+- ((struct mthca_next_seg *) wqe)->imm = wr->imm_data;
++ ((struct mthca_next_seg *) wqe)->imm = wr->ex.imm_data;
+
+ wqe += sizeof (struct mthca_next_seg);
+ size = sizeof (struct mthca_next_seg) / 16;
+diff --git a/drivers/infiniband/hw/mthca/mthca_wqe.h b/drivers/infiniband/hw/mthca/mthca_wqe.h
+index f6a66fe..b3551a8 100644
+--- a/drivers/infiniband/hw/mthca/mthca_wqe.h
++++ b/drivers/infiniband/hw/mthca/mthca_wqe.h
+@@ -38,14 +38,16 @@
+ #include <linux/types.h>
+
+ enum {
+- MTHCA_NEXT_DBD = 1 << 7,
+- MTHCA_NEXT_FENCE = 1 << 6,
+- MTHCA_NEXT_CQ_UPDATE = 1 << 3,
+- MTHCA_NEXT_EVENT_GEN = 1 << 2,
+- MTHCA_NEXT_SOLICIT = 1 << 1,
+-
+- MTHCA_MLX_VL15 = 1 << 17,
+- MTHCA_MLX_SLR = 1 << 16
++ MTHCA_NEXT_DBD = 1 << 7,
++ MTHCA_NEXT_FENCE = 1 << 6,
++ MTHCA_NEXT_CQ_UPDATE = 1 << 3,
++ MTHCA_NEXT_EVENT_GEN = 1 << 2,
++ MTHCA_NEXT_SOLICIT = 1 << 1,
++ MTHCA_NEXT_IP_CSUM = 1 << 4,
++ MTHCA_NEXT_TCP_UDP_CSUM = 1 << 5,
++
++ MTHCA_MLX_VL15 = 1 << 17,
++ MTHCA_MLX_SLR = 1 << 16
+ };
+
+ enum {
+diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c
+index b2112f5..b046262 100644
+--- a/drivers/infiniband/hw/nes/nes.c
++++ b/drivers/infiniband/hw/nes/nes.c
+@@ -65,7 +65,6 @@ MODULE_LICENSE("Dual BSD/GPL");
+ MODULE_VERSION(DRV_VERSION);
+
+ int max_mtu = 9000;
+-int nics_per_function = 1;
+ int interrupt_mod_interval = 0;
+
+
+@@ -93,22 +92,10 @@ module_param_named(debug_level, nes_debug_level, uint, 0644);
+ MODULE_PARM_DESC(debug_level, "Enable debug output level");
+
+ LIST_HEAD(nes_adapter_list);
+-LIST_HEAD(nes_dev_list);
++static LIST_HEAD(nes_dev_list);
+
+ atomic_t qps_destroyed;
+-atomic_t cqp_reqs_allocated;
+-atomic_t cqp_reqs_freed;
+-atomic_t cqp_reqs_dynallocated;
+-atomic_t cqp_reqs_dynfreed;
+-atomic_t cqp_reqs_queued;
+-atomic_t cqp_reqs_redriven;
+-
+-static void nes_print_macaddr(struct net_device *netdev);
+-static irqreturn_t nes_interrupt(int, void *);
+-static int __devinit nes_probe(struct pci_dev *, const struct pci_device_id *);
+-static void __devexit nes_remove(struct pci_dev *);
+-static int __init nes_init_module(void);
+-static void __exit nes_exit_module(void);
++
+ static unsigned int ee_flsh_adapter;
+ static unsigned int sysfs_nonidx_addr;
+ static unsigned int sysfs_idx_addr;
+@@ -310,7 +297,7 @@ void nes_rem_ref(struct ib_qp *ibqp)
+
+ if (atomic_read(&nesqp->refcount) == 0) {
+ printk(KERN_INFO PFX "%s: Reference count already 0 for QP%d, last aeq = 0x%04X.\n",
+- __FUNCTION__, ibqp->qp_num, nesqp->last_aeq);
++ __func__, ibqp->qp_num, nesqp->last_aeq);
+ BUG();
+ }
+
+@@ -751,13 +738,13 @@ static void __devexit nes_remove(struct pci_dev *pcidev)
+
+ list_del(&nesdev->list);
+ nes_destroy_cqp(nesdev);
++
++ free_irq(pcidev->irq, nesdev);
+ tasklet_kill(&nesdev->dpc_tasklet);
+
+ /* Deallocate the Adapter Structure */
+ nes_destroy_adapter(nesdev->nesadapter);
+
+- free_irq(pcidev->irq, nesdev);
+-
+ if (nesdev->msi_enabled) {
+ pci_disable_msi(pcidev);
+ }
+diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h
+index a48b288..cdf2e9a 100644
+--- a/drivers/infiniband/hw/nes/nes.h
++++ b/drivers/infiniband/hw/nes/nes.h
+@@ -43,7 +43,6 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/workqueue.h>
+ #include <linux/slab.h>
+-#include <asm/semaphore.h>
+ #include <linux/version.h>
+ #include <asm/io.h>
+ #include <linux/crc32c.h>
+@@ -143,12 +142,12 @@
+ #ifdef CONFIG_INFINIBAND_NES_DEBUG
+ #define nes_debug(level, fmt, args...) \
+ if (level & nes_debug_level) \
+- printk(KERN_ERR PFX "%s[%u]: " fmt, __FUNCTION__, __LINE__, ##args)
++ printk(KERN_ERR PFX "%s[%u]: " fmt, __func__, __LINE__, ##args)
+
+ #define assert(expr) \
+ if (!(expr)) { \
+ printk(KERN_ERR PFX "Assertion failed! %s, %s, %s, line %d\n", \
+- #expr, __FILE__, __FUNCTION__, __LINE__); \
++ #expr, __FILE__, __func__, __LINE__); \
+ }
+
+ #define NES_EVENT_TIMEOUT 1200000
+@@ -166,7 +165,6 @@ if (!(expr)) { \
+ #include "nes_cm.h"
+
+ extern int max_mtu;
+-extern int nics_per_function;
+ #define max_frame_len (max_mtu+ETH_HLEN)
+ extern int interrupt_mod_interval;
+ extern int nes_if_count;
+@@ -177,9 +175,6 @@ extern unsigned int nes_drv_opt;
+ extern unsigned int nes_debug_level;
+
+ extern struct list_head nes_adapter_list;
+-extern struct list_head nes_dev_list;
+-
+-extern struct nes_cm_core *g_cm_core;
+
+ extern atomic_t cm_connects;
+ extern atomic_t cm_accepts;
+@@ -209,7 +204,6 @@ extern atomic_t cm_nodes_destroyed;
+ extern atomic_t cm_accel_dropped_pkts;
+ extern atomic_t cm_resets_recvd;
+
+-extern u32 crit_err_count;
+ extern u32 int_mod_timer_init;
+ extern u32 int_mod_cq_depth_256;
+ extern u32 int_mod_cq_depth_128;
+@@ -219,14 +213,6 @@ extern u32 int_mod_cq_depth_16;
+ extern u32 int_mod_cq_depth_4;
+ extern u32 int_mod_cq_depth_1;
+
+-extern atomic_t cqp_reqs_allocated;
+-extern atomic_t cqp_reqs_freed;
+-extern atomic_t cqp_reqs_dynallocated;
+-extern atomic_t cqp_reqs_dynfreed;
+-extern atomic_t cqp_reqs_queued;
+-extern atomic_t cqp_reqs_redriven;
+-
+-
+ struct nes_device {
+ struct nes_adapter *nesadapter;
+ void __iomem *regs;
+@@ -412,7 +398,7 @@ static inline int nes_alloc_resource(struct nes_adapter *nesadapter,
+ if (resource_num >= max_resources) {
+ resource_num = find_first_zero_bit(resource_array, max_resources);
+ if (resource_num >= max_resources) {
+- printk(KERN_ERR PFX "%s: No available resourcess.\n", __FUNCTION__);
++ printk(KERN_ERR PFX "%s: No available resourcess.\n", __func__);
+ spin_unlock_irqrestore(&nesadapter->resource_lock, flags);
+ return -EMFILE;
+ }
+@@ -510,9 +496,6 @@ struct ib_qp *nes_get_qp(struct ib_device *, int);
+ /* nes_hw.c */
+ struct nes_adapter *nes_init_adapter(struct nes_device *, u8);
+ void nes_nic_init_timer_defaults(struct nes_device *, u8);
+-unsigned int nes_reset_adapter_ne020(struct nes_device *, u8 *);
+-int nes_init_serdes(struct nes_device *, u8, u8, u8);
+-void nes_init_csr_ne020(struct nes_device *, u8, u8);
+ void nes_destroy_adapter(struct nes_adapter *);
+ int nes_init_cqp(struct nes_device *);
+ int nes_init_phy(struct nes_device *);
+@@ -520,20 +503,12 @@ int nes_init_nic_qp(struct nes_device *, struct net_device *);
+ void nes_destroy_nic_qp(struct nes_vnic *);
+ int nes_napi_isr(struct nes_device *);
+ void nes_dpc(unsigned long);
+-void nes_process_ceq(struct nes_device *, struct nes_hw_ceq *);
+-void nes_process_aeq(struct nes_device *, struct nes_hw_aeq *);
+-void nes_process_mac_intr(struct nes_device *, u32);
+-void nes_nic_napi_ce_handler(struct nes_device *, struct nes_hw_nic_cq *);
+ void nes_nic_ce_handler(struct nes_device *, struct nes_hw_nic_cq *);
+-void nes_cqp_ce_handler(struct nes_device *, struct nes_hw_cq *);
+-void nes_process_iwarp_aeqe(struct nes_device *, struct nes_hw_aeqe *);
+ void nes_iwarp_ce_handler(struct nes_device *, struct nes_hw_cq *);
+ int nes_destroy_cqp(struct nes_device *);
+ int nes_nic_cm_xmit(struct sk_buff *, struct net_device *);
+
+ /* nes_nic.c */
+-void nes_netdev_set_multicast_list(struct net_device *);
+-void nes_netdev_exit(struct nes_vnic *);
+ struct net_device *nes_netdev_init(struct nes_device *, void __iomem *);
+ void nes_netdev_destroy(struct net_device *);
+ int nes_nic_cm_xmit(struct sk_buff *, struct net_device *);
+@@ -544,7 +519,6 @@ int nes_cm_recv(struct sk_buff *, struct net_device *);
+ void nes_update_arp(unsigned char *, u32, u32, u16, u16);
+ void nes_manage_arp_cache(struct net_device *, unsigned char *, u32, u32);
+ void nes_sock_release(struct nes_qp *, unsigned long *);
+-struct nes_cm_core *nes_cm_alloc_core(void);
+ void flush_wqes(struct nes_device *nesdev, struct nes_qp *, u32, u32);
+ int nes_manage_apbvt(struct nes_vnic *, u32, u32, u32);
+ int nes_cm_disconn(struct nes_qp *);
+@@ -556,7 +530,6 @@ int nes_modify_qp(struct ib_qp *, struct ib_qp_attr *, int, struct ib_udata *);
+ struct nes_ib_device *nes_init_ofa_device(struct net_device *);
+ void nes_destroy_ofa_device(struct nes_ib_device *);
+ int nes_register_ofa_device(struct nes_ib_device *);
+-void nes_unregister_ofa_device(struct nes_ib_device *);
+
+ /* nes_util.c */
+ int nes_read_eeprom_values(struct nes_device *, struct nes_adapter *);
+diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
+index 0bef878..d073862 100644
+--- a/drivers/infiniband/hw/nes/nes_cm.c
++++ b/drivers/infiniband/hw/nes/nes_cm.c
+@@ -80,7 +80,30 @@ static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *,
+ static int add_ref_cm_node(struct nes_cm_node *);
+ static int rem_ref_cm_node(struct nes_cm_core *, struct nes_cm_node *);
+ static int mini_cm_del_listen(struct nes_cm_core *, struct nes_cm_listener *);
+-
++static struct sk_buff *form_cm_frame(struct sk_buff *, struct nes_cm_node *,
++ void *, u32, void *, u32, u8);
++static struct sk_buff *get_free_pkt(struct nes_cm_node *cm_node);
++
++static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *,
++ struct nes_vnic *,
++ struct ietf_mpa_frame *,
++ struct nes_cm_info *);
++static int mini_cm_accept(struct nes_cm_core *, struct ietf_mpa_frame *,
++ struct nes_cm_node *);
++static int mini_cm_reject(struct nes_cm_core *, struct ietf_mpa_frame *,
++ struct nes_cm_node *);
++static int mini_cm_close(struct nes_cm_core *, struct nes_cm_node *);
++static int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *,
++ struct sk_buff *);
++static int mini_cm_dealloc_core(struct nes_cm_core *);
++static int mini_cm_get(struct nes_cm_core *);
++static int mini_cm_set(struct nes_cm_core *, u32, u32);
++static int nes_cm_disconn_true(struct nes_qp *);
++static int nes_cm_post_event(struct nes_cm_event *event);
++static int nes_disconnect(struct nes_qp *nesqp, int abrupt);
++static void nes_disconnect_worker(struct work_struct *work);
++static int send_ack(struct nes_cm_node *cm_node);
++static int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb);
+
+ /* External CM API Interface */
+ /* instance of function pointers for client API */
+@@ -99,7 +122,7 @@ static struct nes_cm_ops nes_cm_api = {
+ mini_cm_set
+ };
+
+-struct nes_cm_core *g_cm_core;
++static struct nes_cm_core *g_cm_core;
+
+ atomic_t cm_connects;
+ atomic_t cm_accepts;
+@@ -149,7 +172,7 @@ static struct nes_cm_event *create_event(struct nes_cm_node *cm_node,
+ /**
+ * send_mpa_request
+ */
+-int send_mpa_request(struct nes_cm_node *cm_node)
++static int send_mpa_request(struct nes_cm_node *cm_node)
+ {
+ struct sk_buff *skb;
+ int ret;
+@@ -243,8 +266,9 @@ static int handle_exception_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb
+ * form_cm_frame - get a free packet and build empty frame Use
+ * node info to build.
+ */
+-struct sk_buff *form_cm_frame(struct sk_buff *skb, struct nes_cm_node *cm_node,
+- void *options, u32 optionsize, void *data, u32 datasize, u8 flags)
++static struct sk_buff *form_cm_frame(struct sk_buff *skb, struct nes_cm_node *cm_node,
++ void *options, u32 optionsize, void *data,
++ u32 datasize, u8 flags)
+ {
+ struct tcphdr *tcph;
+ struct iphdr *iph;
+@@ -342,7 +366,6 @@ static void print_core(struct nes_cm_core *core)
+ if (!core)
+ return;
+ nes_debug(NES_DBG_CM, "---------------------------------------------\n");
+- nes_debug(NES_DBG_CM, "Session ID : %u \n", atomic_read(&core->session_id));
+
+ nes_debug(NES_DBG_CM, "State : %u \n", core->state);
+
+@@ -395,7 +418,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
+ }
+
+ if (type == NES_TIMER_TYPE_SEND) {
+- new_send->seq_num = htonl(tcp_hdr(skb)->seq);
++ new_send->seq_num = ntohl(tcp_hdr(skb)->seq);
+ atomic_inc(&new_send->skb->users);
+
+ ret = nes_nic_cm_xmit(new_send->skb, cm_node->netdev);
+@@ -420,7 +443,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
+ spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
+ }
+ if (type == NES_TIMER_TYPE_RECV) {
+- new_send->seq_num = htonl(tcp_hdr(skb)->seq);
++ new_send->seq_num = ntohl(tcp_hdr(skb)->seq);
+ new_send->timetosend = jiffies;
+ spin_lock_irqsave(&cm_node->recv_list_lock, flags);
+ list_add_tail(&new_send->list, &cm_node->recv_list);
+@@ -442,7 +465,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
+ /**
+ * nes_cm_timer_tick
+ */
+-void nes_cm_timer_tick(unsigned long pass)
++static void nes_cm_timer_tick(unsigned long pass)
+ {
+ unsigned long flags, qplockflags;
+ unsigned long nexttimeout = jiffies + NES_LONG_TIME;
+@@ -644,7 +667,7 @@ void nes_cm_timer_tick(unsigned long pass)
+ /**
+ * send_syn
+ */
+-int send_syn(struct nes_cm_node *cm_node, u32 sendack)
++static int send_syn(struct nes_cm_node *cm_node, u32 sendack)
+ {
+ int ret;
+ int flags = SET_SYN;
+@@ -710,7 +733,7 @@ int send_syn(struct nes_cm_node *cm_node, u32 sendack)
+ /**
+ * send_reset
+ */
+-int send_reset(struct nes_cm_node *cm_node)
++static int send_reset(struct nes_cm_node *cm_node)
+ {
+ int ret;
+ struct sk_buff *skb = get_free_pkt(cm_node);
+@@ -732,7 +755,7 @@ int send_reset(struct nes_cm_node *cm_node)
+ /**
+ * send_ack
+ */
+-int send_ack(struct nes_cm_node *cm_node)
++static int send_ack(struct nes_cm_node *cm_node)
+ {
+ int ret;
+ struct sk_buff *skb = get_free_pkt(cm_node);
+@@ -752,7 +775,7 @@ int send_ack(struct nes_cm_node *cm_node)
+ /**
+ * send_fin
+ */
+-int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb)
++static int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb)
+ {
+ int ret;
+
+@@ -775,7 +798,7 @@ int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb)
+ /**
+ * get_free_pkt
+ */
+-struct sk_buff *get_free_pkt(struct nes_cm_node *cm_node)
++static struct sk_buff *get_free_pkt(struct nes_cm_node *cm_node)
+ {
+ struct sk_buff *skb, *new_skb;
+
+@@ -820,7 +843,6 @@ static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,
+ {
+ unsigned long flags;
+ u32 hashkey;
+- struct list_head *list_pos;
+ struct list_head *hte;
+ struct nes_cm_node *cm_node;
+
+@@ -835,8 +857,7 @@ static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,
+
+ /* walk list and find cm_node associated with this session ID */
+ spin_lock_irqsave(&cm_core->ht_lock, flags);
+- list_for_each(list_pos, hte) {
+- cm_node = container_of(list_pos, struct nes_cm_node, list);
++ list_for_each_entry(cm_node, hte, list) {
+ /* compare quad, return node handle if a match */
+ nes_debug(NES_DBG_CM, "finding node %x:%x =? %x:%x ^ %x:%x =? %x:%x\n",
+ cm_node->loc_addr, cm_node->loc_port,
+@@ -864,13 +885,11 @@ static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core,
+ nes_addr_t dst_addr, u16 dst_port, enum nes_cm_listener_state listener_state)
+ {
+ unsigned long flags;
+- struct list_head *listen_list;
+ struct nes_cm_listener *listen_node;
+
+ /* walk list and find cm_node associated with this session ID */
+ spin_lock_irqsave(&cm_core->listen_list_lock, flags);
+- list_for_each(listen_list, &cm_core->listen_list.list) {
+- listen_node = container_of(listen_list, struct nes_cm_listener, list);
++ list_for_each_entry(listen_node, &cm_core->listen_list.list, list) {
+ /* compare node pair, return node handle if a match */
+ if (((listen_node->loc_addr == dst_addr) ||
+ listen_node->loc_addr == 0x00000000) &&
+@@ -1014,7 +1033,7 @@ static void nes_addr_send_arp(u32 dst_ip)
+ fl.nl_u.ip4_u.daddr = htonl(dst_ip);
+ if (ip_route_output_key(&init_net, &rt, &fl)) {
+ printk("%s: ip_route_output_key failed for 0x%08X\n",
+- __FUNCTION__, dst_ip);
++ __func__, dst_ip);
+ return;
+ }
+
+@@ -1077,8 +1096,6 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
+ cm_node->tcp_cntxt.rcv_nxt = 0;
+ /* get a unique session ID , add thread_id to an upcounter to handle race */
+ atomic_inc(&cm_core->node_cnt);
+- atomic_inc(&cm_core->session_id);
+- cm_node->session_id = (u32)(atomic_read(&cm_core->session_id) + current->tgid);
+ cm_node->conn_type = cm_info->conn_type;
+ cm_node->apbvt_set = 0;
+ cm_node->accept_pend = 0;
+@@ -1239,7 +1256,7 @@ static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc, u32 opti
+ continue;
+ case OPTION_NUMBER_MSS:
+ nes_debug(NES_DBG_CM, "%s: MSS Length: %d Offset: %d Size: %d\n",
+- __FUNCTION__,
++ __func__,
+ all_options->as_mss.length, offset, optionsize);
+ got_mss_option = 1;
+ if (all_options->as_mss.length != 4) {
+@@ -1272,8 +1289,8 @@ static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc, u32 opti
+ /**
+ * process_packet
+ */
+-int process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
+- struct nes_cm_core *cm_core)
++static int process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
++ struct nes_cm_core *cm_core)
+ {
+ int optionsize;
+ int datasize;
+@@ -1360,7 +1377,7 @@ int process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
+ if (optionsize) {
+ u8 *optionsloc = (u8 *)&tcph[1];
+ if (process_options(cm_node, optionsloc, optionsize, (u32)tcph->syn)) {
+- nes_debug(NES_DBG_CM, "%s: Node %p, Sending RESET\n", __FUNCTION__, cm_node);
++ nes_debug(NES_DBG_CM, "%s: Node %p, Sending RESET\n", __func__, cm_node);
+ send_reset(cm_node);
+ if (cm_node->state != NES_CM_STATE_SYN_SENT)
+ rem_ref_cm_node(cm_core, cm_node);
+@@ -1605,9 +1622,7 @@ static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,
+ listener->cm_core = cm_core;
+ listener->nesvnic = nesvnic;
+ atomic_inc(&cm_core->node_cnt);
+- atomic_inc(&cm_core->session_id);
+
+- listener->session_id = (u32)(atomic_read(&cm_core->session_id) + current->tgid);
+ listener->conn_type = cm_info->conn_type;
+ listener->backlog = cm_info->backlog;
+ listener->listener_state = NES_CM_LISTENER_ACTIVE_STATE;
+@@ -1631,9 +1646,10 @@ static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,
+ /**
+ * mini_cm_connect - make a connection node with params
+ */
+-struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
+- struct nes_vnic *nesvnic, struct ietf_mpa_frame *mpa_frame,
+- struct nes_cm_info *cm_info)
++static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
++ struct nes_vnic *nesvnic,
++ struct ietf_mpa_frame *mpa_frame,
++ struct nes_cm_info *cm_info)
+ {
+ int ret = 0;
+ struct nes_cm_node *cm_node;
+@@ -1717,8 +1733,8 @@ struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
+ * mini_cm_accept - accept a connection
+ * This function is never called
+ */
+-int mini_cm_accept(struct nes_cm_core *cm_core, struct ietf_mpa_frame *mpa_frame,
+- struct nes_cm_node *cm_node)
++static int mini_cm_accept(struct nes_cm_core *cm_core, struct ietf_mpa_frame *mpa_frame,
++ struct nes_cm_node *cm_node)
+ {
+ return 0;
+ }
+@@ -1727,9 +1743,9 @@ int mini_cm_accept(struct nes_cm_core *cm_core, struct ietf_mpa_frame *mpa_frame
+ /**
+ * mini_cm_reject - reject and teardown a connection
+ */
+-int mini_cm_reject(struct nes_cm_core *cm_core,
+- struct ietf_mpa_frame *mpa_frame,
+- struct nes_cm_node *cm_node)
++static int mini_cm_reject(struct nes_cm_core *cm_core,
++ struct ietf_mpa_frame *mpa_frame,
++ struct nes_cm_node *cm_node)
+ {
+ int ret = 0;
+ struct sk_buff *skb;
+@@ -1761,7 +1777,7 @@ int mini_cm_reject(struct nes_cm_core *cm_core,
+ /**
+ * mini_cm_close
+ */
+-int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node)
++static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node)
+ {
+ int ret = 0;
+
+@@ -1808,8 +1824,8 @@ int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node)
+ * recv_pkt - recv an ETHERNET packet, and process it through CM
+ * node state machine
+ */
+-int mini_cm_recv_pkt(struct nes_cm_core *cm_core, struct nes_vnic *nesvnic,
+- struct sk_buff *skb)
++static int mini_cm_recv_pkt(struct nes_cm_core *cm_core, struct nes_vnic *nesvnic,
++ struct sk_buff *skb)
+ {
+ struct nes_cm_node *cm_node = NULL;
+ struct nes_cm_listener *listener = NULL;
+@@ -1898,7 +1914,7 @@ int mini_cm_recv_pkt(struct nes_cm_core *cm_core, struct nes_vnic *nesvnic,
+ /**
+ * nes_cm_alloc_core - allocate a top level instance of a cm core
+ */
+-struct nes_cm_core *nes_cm_alloc_core(void)
++static struct nes_cm_core *nes_cm_alloc_core(void)
+ {
+ int i;
+
+@@ -1919,7 +1935,6 @@ struct nes_cm_core *nes_cm_alloc_core(void)
+ cm_core->state = NES_CM_STATE_INITED;
+ cm_core->free_tx_pkt_max = NES_CM_DEFAULT_FREE_PKTS;
+
+- atomic_set(&cm_core->session_id, 0);
+ atomic_set(&cm_core->events_posted, 0);
+
+ /* init the packet lists */
+@@ -1958,7 +1973,7 @@ struct nes_cm_core *nes_cm_alloc_core(void)
+ /**
+ * mini_cm_dealloc_core - deallocate a top level instance of a cm core
+ */
+-int mini_cm_dealloc_core(struct nes_cm_core *cm_core)
++static int mini_cm_dealloc_core(struct nes_cm_core *cm_core)
+ {
+ nes_debug(NES_DBG_CM, "De-Alloc CM Core (%p)\n", cm_core);
+
+@@ -1983,7 +1998,7 @@ int mini_cm_dealloc_core(struct nes_cm_core *cm_core)
+ /**
+ * mini_cm_get
+ */
+-int mini_cm_get(struct nes_cm_core *cm_core)
++static int mini_cm_get(struct nes_cm_core *cm_core)
+ {
+ return cm_core->state;
+ }
+@@ -1992,7 +2007,7 @@ int mini_cm_get(struct nes_cm_core *cm_core)
+ /**
+ * mini_cm_set
+ */
+-int mini_cm_set(struct nes_cm_core *cm_core, u32 type, u32 value)
++static int mini_cm_set(struct nes_cm_core *cm_core, u32 type, u32 value)
+ {
+ int ret = 0;
+
+@@ -2109,7 +2124,7 @@ int nes_cm_disconn(struct nes_qp *nesqp)
+ /**
+ * nes_disconnect_worker
+ */
+-void nes_disconnect_worker(struct work_struct *work)
++static void nes_disconnect_worker(struct work_struct *work)
+ {
+ struct nes_qp *nesqp = container_of(work, struct nes_qp, disconn_work);
+
+@@ -2122,7 +2137,7 @@ void nes_disconnect_worker(struct work_struct *work)
+ /**
+ * nes_cm_disconn_true
+ */
+-int nes_cm_disconn_true(struct nes_qp *nesqp)
++static int nes_cm_disconn_true(struct nes_qp *nesqp)
+ {
+ unsigned long flags;
+ int ret = 0;
+@@ -2265,7 +2280,7 @@ int nes_cm_disconn_true(struct nes_qp *nesqp)
+ /**
+ * nes_disconnect
+ */
+-int nes_disconnect(struct nes_qp *nesqp, int abrupt)
++static int nes_disconnect(struct nes_qp *nesqp, int abrupt)
+ {
+ int ret = 0;
+ struct nes_vnic *nesvnic;
+@@ -2482,7 +2497,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+ }
+ if (ret)
+ printk("%s[%u] OFA CM event_handler returned, ret=%d\n",
+- __FUNCTION__, __LINE__, ret);
++ __func__, __LINE__, ret);
+
+ return 0;
+ }
+@@ -2650,7 +2665,7 @@ int nes_create_listen(struct iw_cm_id *cm_id, int backlog)
+ cm_node = g_cm_core->api->listen(g_cm_core, nesvnic, &cm_info);
+ if (!cm_node) {
+ printk("%s[%u] Error returned from listen API call\n",
+- __FUNCTION__, __LINE__);
++ __func__, __LINE__);
+ return -ENOMEM;
+ }
+
+@@ -2740,7 +2755,7 @@ int nes_cm_stop(void)
+ * cm_event_connected
+ * handle a connected event, setup QPs and HW
+ */
+-void cm_event_connected(struct nes_cm_event *event)
++static void cm_event_connected(struct nes_cm_event *event)
+ {
+ u64 u64temp;
+ struct nes_qp *nesqp;
+@@ -2864,7 +2879,7 @@ void cm_event_connected(struct nes_cm_event *event)
+
+ if (ret)
+ printk("%s[%u] OFA CM event_handler returned, ret=%d\n",
+- __FUNCTION__, __LINE__, ret);
++ __func__, __LINE__, ret);
+ nes_debug(NES_DBG_CM, "Exiting connect thread for QP%u. jiffies = %lu\n",
+ nesqp->hwqp.qp_id, jiffies );
+
+@@ -2877,7 +2892,7 @@ void cm_event_connected(struct nes_cm_event *event)
+ /**
+ * cm_event_connect_error
+ */
+-void cm_event_connect_error(struct nes_cm_event *event)
++static void cm_event_connect_error(struct nes_cm_event *event)
+ {
+ struct nes_qp *nesqp;
+ struct iw_cm_id *cm_id;
+@@ -2919,7 +2934,7 @@ void cm_event_connect_error(struct nes_cm_event *event)
+ nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret);
+ if (ret)
+ printk("%s[%u] OFA CM event_handler returned, ret=%d\n",
+- __FUNCTION__, __LINE__, ret);
++ __func__, __LINE__, ret);
+ nes_rem_ref(&nesqp->ibqp);
+ cm_id->rem_ref(cm_id);
+
+@@ -2930,7 +2945,7 @@ void cm_event_connect_error(struct nes_cm_event *event)
+ /**
+ * cm_event_reset
+ */
+-void cm_event_reset(struct nes_cm_event *event)
++static void cm_event_reset(struct nes_cm_event *event)
+ {
+ struct nes_qp *nesqp;
+ struct iw_cm_id *cm_id;
+@@ -2973,7 +2988,7 @@ void cm_event_reset(struct nes_cm_event *event)
+ /**
+ * cm_event_mpa_req
+ */
+-void cm_event_mpa_req(struct nes_cm_event *event)
++static void cm_event_mpa_req(struct nes_cm_event *event)
+ {
+ struct iw_cm_id *cm_id;
+ struct iw_cm_event cm_event;
+@@ -3007,7 +3022,7 @@ void cm_event_mpa_req(struct nes_cm_event *event)
+ ret = cm_id->event_handler(cm_id, &cm_event);
+ if (ret)
+ printk("%s[%u] OFA CM event_handler returned, ret=%d\n",
+- __FUNCTION__, __LINE__, ret);
++ __func__, __LINE__, ret);
+
+ return;
+ }
+@@ -3019,7 +3034,7 @@ static void nes_cm_event_handler(struct work_struct *);
+ * nes_cm_post_event
+ * post an event to the cm event handler
+ */
+-int nes_cm_post_event(struct nes_cm_event *event)
++static int nes_cm_post_event(struct nes_cm_event *event)
+ {
+ atomic_inc(&event->cm_node->cm_core->events_posted);
+ add_ref_cm_node(event->cm_node);
+diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h
+index a59f0a7..7717cb2 100644
+--- a/drivers/infiniband/hw/nes/nes_cm.h
++++ b/drivers/infiniband/hw/nes/nes_cm.h
+@@ -225,7 +225,6 @@ enum nes_cm_listener_state {
+
+ struct nes_cm_listener {
+ struct list_head list;
+- u64 session_id;
+ struct nes_cm_core *cm_core;
+ u8 loc_mac[ETH_ALEN];
+ nes_addr_t loc_addr;
+@@ -242,7 +241,6 @@ struct nes_cm_listener {
+
+ /* per connection node and node state information */
+ struct nes_cm_node {
+- u64 session_id;
+ u32 hashkey;
+
+ nes_addr_t loc_addr, rem_addr;
+@@ -327,7 +325,6 @@ struct nes_cm_event {
+
+ struct nes_cm_core {
+ enum nes_cm_node_state state;
+- atomic_t session_id;
+
+ atomic_t listen_node_cnt;
+ struct nes_cm_node listen_list;
+@@ -383,35 +380,10 @@ struct nes_cm_ops {
+ int (*set)(struct nes_cm_core *, u32, u32);
+ };
+
+-
+-int send_mpa_request(struct nes_cm_node *);
+-struct sk_buff *form_cm_frame(struct sk_buff *, struct nes_cm_node *,
+- void *, u32, void *, u32, u8);
+ int schedule_nes_timer(struct nes_cm_node *, struct sk_buff *,
+ enum nes_timer_type, int, int);
+-void nes_cm_timer_tick(unsigned long);
+-int send_syn(struct nes_cm_node *, u32);
+-int send_reset(struct nes_cm_node *);
+-int send_ack(struct nes_cm_node *);
+-int send_fin(struct nes_cm_node *, struct sk_buff *);
+-struct sk_buff *get_free_pkt(struct nes_cm_node *);
+-int process_packet(struct nes_cm_node *, struct sk_buff *, struct nes_cm_core *);
+-
+-struct nes_cm_node * mini_cm_connect(struct nes_cm_core *,
+- struct nes_vnic *, struct ietf_mpa_frame *, struct nes_cm_info *);
+-int mini_cm_accept(struct nes_cm_core *, struct ietf_mpa_frame *, struct nes_cm_node *);
+-int mini_cm_reject(struct nes_cm_core *, struct ietf_mpa_frame *, struct nes_cm_node *);
+-int mini_cm_close(struct nes_cm_core *, struct nes_cm_node *);
+-int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *, struct sk_buff *);
+-struct nes_cm_core *mini_cm_alloc_core(struct nes_cm_info *);
+-int mini_cm_dealloc_core(struct nes_cm_core *);
+-int mini_cm_get(struct nes_cm_core *);
+-int mini_cm_set(struct nes_cm_core *, u32, u32);
+
+ int nes_cm_disconn(struct nes_qp *);
+-void nes_disconnect_worker(struct work_struct *);
+-int nes_cm_disconn_true(struct nes_qp *);
+-int nes_disconnect(struct nes_qp *, int);
+
+ int nes_accept(struct iw_cm_id *, struct iw_cm_conn_param *);
+ int nes_reject(struct iw_cm_id *, const void *, u8);
+@@ -423,11 +395,4 @@ int nes_cm_recv(struct sk_buff *, struct net_device *);
+ int nes_cm_start(void);
+ int nes_cm_stop(void);
+
+-/* CM event handler functions */
+-void cm_event_connected(struct nes_cm_event *);
+-void cm_event_connect_error(struct nes_cm_event *);
+-void cm_event_reset(struct nes_cm_event *);
+-void cm_event_mpa_req(struct nes_cm_event *);
+-int nes_cm_post_event(struct nes_cm_event *);
+-
+ #endif /* NES_CM_H */
+diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c
+index 49e53e4..aa53aab 100644
+--- a/drivers/infiniband/hw/nes/nes_hw.c
++++ b/drivers/infiniband/hw/nes/nes_hw.c
+@@ -41,7 +41,7 @@
+
+ #include "nes.h"
+
+-u32 crit_err_count = 0;
++static u32 crit_err_count;
+ u32 int_mod_timer_init;
+ u32 int_mod_cq_depth_256;
+ u32 int_mod_cq_depth_128;
+@@ -53,6 +53,17 @@ u32 int_mod_cq_depth_1;
+
+ #include "nes_cm.h"
+
++static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq);
++static void nes_init_csr_ne020(struct nes_device *nesdev, u8 hw_rev, u8 port_count);
++static int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count,
++ u8 OneG_Mode);
++static void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq);
++static void nes_process_aeq(struct nes_device *nesdev, struct nes_hw_aeq *aeq);
++static void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq);
++static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
++ struct nes_hw_aeqe *aeqe);
++static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number);
++static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode);
+
+ #ifdef CONFIG_INFINIBAND_NES_DEBUG
+ static unsigned char *nes_iwarp_state_str[] = {
+@@ -370,7 +381,7 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) {
+ nesadapter->et_use_adaptive_rx_coalesce = 1;
+ nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT_DYNAMIC;
+ nesadapter->et_rx_coalesce_usecs_irq = 0;
+- printk(PFX "%s: Using Adaptive Interrupt Moderation\n", __FUNCTION__);
++ printk(PFX "%s: Using Adaptive Interrupt Moderation\n", __func__);
+ }
+ /* Setup and enable the periodic timer */
+ if (nesadapter->et_rx_coalesce_usecs_irq)
+@@ -382,7 +393,7 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) {
+ nesadapter->base_pd = 1;
+
+ nesadapter->device_cap_flags =
+- IB_DEVICE_ZERO_STAG | IB_DEVICE_SEND_W_INV | IB_DEVICE_MEM_WINDOW;
++ IB_DEVICE_ZERO_STAG | IB_DEVICE_MEM_WINDOW;
+
+ nesadapter->allocated_qps = (unsigned long *)&(((unsigned char *)nesadapter)
+ [(sizeof(struct nes_adapter)+(sizeof(unsigned long)-1))&(~(sizeof(unsigned long)-1))]);
+@@ -572,7 +583,7 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) {
+ if (vendor_id == 0xffff)
+ break;
+ }
+- nes_debug(NES_DBG_INIT, "%s %d functions found for %s.\n", __FUNCTION__,
++ nes_debug(NES_DBG_INIT, "%s %d functions found for %s.\n", __func__,
+ func_index, pci_name(nesdev->pcidev));
+ nesadapter->adapter_fcn_count = func_index;
+
+@@ -583,7 +594,7 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) {
+ /**
+ * nes_reset_adapter_ne020
+ */
+-unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode)
++static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode)
+ {
+ u32 port_count;
+ u32 u32temp;
+@@ -691,7 +702,8 @@ unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode)
+ /**
+ * nes_init_serdes
+ */
+-int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count, u8 OneG_Mode)
++static int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count,
++ u8 OneG_Mode)
+ {
+ int i;
+ u32 u32temp;
+@@ -739,7 +751,7 @@ int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count, u8 One
+ & 0x0000000f)) != 0x0000000f) && (i++ < 5000))
+ mdelay(1);
+ if (i >= 5000) {
+- printk("%s: Init: serdes 1 not ready, status=%x\n", __FUNCTION__, u32temp);
++ printk("%s: Init: serdes 1 not ready, status=%x\n", __func__, u32temp);
+ /* return 1; */
+ }
+ nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP1, 0x000bdef7);
+@@ -760,7 +772,7 @@ int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count, u8 One
+ * nes_init_csr_ne020
+ * Initialize registers for ne020 hardware
+ */
+-void nes_init_csr_ne020(struct nes_device *nesdev, u8 hw_rev, u8 port_count)
++static void nes_init_csr_ne020(struct nes_device *nesdev, u8 hw_rev, u8 port_count)
+ {
+ u32 u32temp;
+
+@@ -1204,7 +1216,7 @@ int nes_init_phy(struct nes_device *nesdev)
+ if (nesadapter->OneG_Mode) {
+ nes_debug(NES_DBG_PHY, "1G PHY, mac_index = %d.\n", mac_index);
+ if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_1G) {
+- printk(PFX "%s: Programming mdc config for 1G\n", __FUNCTION__);
++ printk(PFX "%s: Programming mdc config for 1G\n", __func__);
+ tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG);
+ tx_config |= 0x04;
+ nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config);
+@@ -1358,7 +1370,7 @@ static void nes_replenish_nic_rq(struct nes_vnic *nesvnic)
+ static void nes_rq_wqes_timeout(unsigned long parm)
+ {
+ struct nes_vnic *nesvnic = (struct nes_vnic *)parm;
+- printk("%s: Timer fired.\n", __FUNCTION__);
++ printk("%s: Timer fired.\n", __func__);
+ atomic_set(&nesvnic->rx_skb_timer_running, 0);
+ if (atomic_read(&nesvnic->rx_skbs_needed))
+ nes_replenish_nic_rq(nesvnic);
+@@ -1909,7 +1921,7 @@ void nes_dpc(unsigned long param)
+ /**
+ * nes_process_ceq
+ */
+-void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq)
++static void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq)
+ {
+ u64 u64temp;
+ struct nes_hw_cq *cq;
+@@ -1949,7 +1961,7 @@ void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq)
+ /**
+ * nes_process_aeq
+ */
+-void nes_process_aeq(struct nes_device *nesdev, struct nes_hw_aeq *aeq)
++static void nes_process_aeq(struct nes_device *nesdev, struct nes_hw_aeq *aeq)
+ {
+ // u64 u64temp;
+ u32 head;
+@@ -2060,7 +2072,7 @@ static void nes_reset_link(struct nes_device *nesdev, u32 mac_index)
+ /**
+ * nes_process_mac_intr
+ */
+-void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
++static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
+ {
+ unsigned long flags;
+ u32 pcs_control_status;
+@@ -2163,7 +2175,7 @@ void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
+ temp_phy_data = phy_data;
+ } while (1);
+ nes_debug(NES_DBG_PHY, "%s: Phy data = 0x%04X, link was %s.\n",
+- __FUNCTION__, phy_data, nesadapter->mac_link_down ? "DOWN" : "UP");
++ __func__, phy_data, nesadapter->mac_link_down ? "DOWN" : "UP");
+
+ } else {
+ phy_data = (0x0f0f0000 == (pcs_control_status & 0x0f1f0000)) ? 4 : 0;
+@@ -2205,7 +2217,7 @@ void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
+
+
+
+-void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
++static void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
+ {
+ struct nes_vnic *nesvnic = container_of(cq, struct nes_vnic, nic_cq);
+
+@@ -2428,7 +2440,7 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
+ /**
+ * nes_cqp_ce_handler
+ */
+-void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
++static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
+ {
+ u64 u64temp;
+ unsigned long flags;
+@@ -2567,7 +2579,8 @@ void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
+ /**
+ * nes_process_iwarp_aeqe
+ */
+-void nes_process_iwarp_aeqe(struct nes_device *nesdev, struct nes_hw_aeqe *aeqe)
++static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
++ struct nes_hw_aeqe *aeqe)
+ {
+ u64 context;
+ u64 aeqe_context = 0;
+@@ -2819,7 +2832,7 @@ void nes_process_iwarp_aeqe(struct nes_device *nesdev, struct nes_hw_aeqe *aeqe)
+ le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]));
+ if (resource_allocated) {
+ printk(KERN_ERR PFX "%s: Processing an NES_AEQE_AEID_CQ_OPERATION_ERROR event on CQ%u\n",
+- __FUNCTION__, le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]));
++ __func__, le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]));
+ }
+ break;
+ case NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG_FOR_AVAILABLE_BUFFER:
+diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
+index eee77da..01cd0ef 100644
+--- a/drivers/infiniband/hw/nes/nes_nic.c
++++ b/drivers/infiniband/hw/nes/nes_nic.c
+@@ -92,15 +92,6 @@ static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK
+ | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN;
+ static int debug = -1;
+
+-
+-static int nes_netdev_open(struct net_device *);
+-static int nes_netdev_stop(struct net_device *);
+-static int nes_netdev_start_xmit(struct sk_buff *, struct net_device *);
+-static struct net_device_stats *nes_netdev_get_stats(struct net_device *);
+-static void nes_netdev_tx_timeout(struct net_device *);
+-static int nes_netdev_set_mac_address(struct net_device *, void *);
+-static int nes_netdev_change_mtu(struct net_device *, int);
+-
+ /**
+ * nes_netdev_poll
+ */
+@@ -802,7 +793,7 @@ static int nes_netdev_set_mac_address(struct net_device *netdev, void *p)
+
+ memcpy(netdev->dev_addr, mac_addr->sa_data, netdev->addr_len);
+ printk(PFX "%s: Address length = %d, Address = %02X%02X%02X%02X%02X%02X..\n",
+- __FUNCTION__, netdev->addr_len,
++ __func__, netdev->addr_len,
+ mac_addr->sa_data[0], mac_addr->sa_data[1],
+ mac_addr->sa_data[2], mac_addr->sa_data[3],
+ mac_addr->sa_data[4], mac_addr->sa_data[5]);
+@@ -832,7 +823,7 @@ static int nes_netdev_set_mac_address(struct net_device *netdev, void *p)
+ /**
+ * nes_netdev_set_multicast_list
+ */
+-void nes_netdev_set_multicast_list(struct net_device *netdev)
++static void nes_netdev_set_multicast_list(struct net_device *netdev)
+ {
+ struct nes_vnic *nesvnic = netdev_priv(netdev);
+ struct nes_device *nesdev = nesvnic->nesdev;
+@@ -947,28 +938,6 @@ static int nes_netdev_change_mtu(struct net_device *netdev, int new_mtu)
+ return ret;
+ }
+
+-
+-/**
+- * nes_netdev_exit - destroy network device
+- */
+-void nes_netdev_exit(struct nes_vnic *nesvnic)
+-{
+- struct net_device *netdev = nesvnic->netdev;
+- struct nes_ib_device *nesibdev = nesvnic->nesibdev;
+-
+- nes_debug(NES_DBG_SHUTDOWN, "\n");
+-
+- // destroy the ibdevice if RDMA enabled
+- if ((nesvnic->rdma_enabled)&&(nesvnic->of_device_registered)) {
+- nes_destroy_ofa_device( nesibdev );
+- nesvnic->of_device_registered = 0;
+- nesvnic->nesibdev = NULL;
+- }
+- unregister_netdev(netdev);
+- nes_debug(NES_DBG_SHUTDOWN, "\n");
+-}
+-
+-
+ #define NES_ETHTOOL_STAT_COUNT 55
+ static const char nes_ethtool_stringset[NES_ETHTOOL_STAT_COUNT][ETH_GSTRING_LEN] = {
+ "Link Change Interrupts",
+diff --git a/drivers/infiniband/hw/nes/nes_utils.c b/drivers/infiniband/hw/nes/nes_utils.c
+index c4ec6ac..f9db07c 100644
+--- a/drivers/infiniband/hw/nes/nes_utils.c
++++ b/drivers/infiniband/hw/nes/nes_utils.c
+@@ -566,7 +566,7 @@ struct nes_cqp_request *nes_get_cqp_request(struct nes_device *nesdev)
+ cqp_request);
+ } else
+ printk(KERN_ERR PFX "%s: Could not allocated a CQP request.\n",
+- __FUNCTION__);
++ __func__);
+
+ return cqp_request;
+ }
+diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
+index a651e9d..f9a5d43 100644
+--- a/drivers/infiniband/hw/nes/nes_verbs.c
++++ b/drivers/infiniband/hw/nes/nes_verbs.c
+@@ -49,6 +49,7 @@ atomic_t mod_qp_timouts;
+ atomic_t qps_created;
+ atomic_t sw_qps_destroyed;
+
++static void nes_unregister_ofa_device(struct nes_ib_device *nesibdev);
+
+ /**
+ * nes_alloc_mw
+@@ -1043,10 +1044,10 @@ static int nes_setup_virt_qp(struct nes_qp *nesqp, struct nes_pbl *nespbl,
+ u8 sq_pbl_entries;
+
+ pbl_entries = nespbl->pbl_size >> 3;
+- nes_debug(NES_DBG_QP, "Userspace PBL, pbl_size=%u, pbl_entries = %d pbl_vbase=%p, pbl_pbase=%p\n",
++ nes_debug(NES_DBG_QP, "Userspace PBL, pbl_size=%u, pbl_entries = %d pbl_vbase=%p, pbl_pbase=%lx\n",
+ nespbl->pbl_size, pbl_entries,
+ (void *)nespbl->pbl_vbase,
+- (void *)nespbl->pbl_pbase);
++ (unsigned long) nespbl->pbl_pbase);
+ pbl = (__le64 *) nespbl->pbl_vbase; /* points to first pbl entry */
+ /* now lets set the sq_vbase as well as rq_vbase addrs we will assign */
+ /* the first pbl to be fro the rq_vbase... */
+@@ -1074,9 +1075,9 @@ static int nes_setup_virt_qp(struct nes_qp *nesqp, struct nes_pbl *nespbl,
+ /* nesqp->hwqp.rq_vbase = bus_to_virt(*pbl); */
+ /*nesqp->hwqp.rq_vbase = phys_to_virt(*pbl); */
+
+- nes_debug(NES_DBG_QP, "QP sq_vbase= %p sq_pbase=%p rq_vbase=%p rq_pbase=%p\n",
+- nesqp->hwqp.sq_vbase, (void *)nesqp->hwqp.sq_pbase,
+- nesqp->hwqp.rq_vbase, (void *)nesqp->hwqp.rq_pbase);
++ nes_debug(NES_DBG_QP, "QP sq_vbase= %p sq_pbase=%lx rq_vbase=%p rq_pbase=%lx\n",
++ nesqp->hwqp.sq_vbase, (unsigned long) nesqp->hwqp.sq_pbase,
++ nesqp->hwqp.rq_vbase, (unsigned long) nesqp->hwqp.rq_pbase);
+ spin_lock_irqsave(&nesadapter->pbl_lock, flags);
+ if (!nesadapter->free_256pbl) {
+ pci_free_consistent(nesdev->pcidev, nespbl->pbl_size, nespbl->pbl_vbase,
+@@ -1251,6 +1252,9 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd,
+ u8 rq_encoded_size;
+ /* int counter; */
+
++ if (init_attr->create_flags)
++ return ERR_PTR(-EINVAL);
++
+ atomic_inc(&qps_created);
+ switch (init_attr->qp_type) {
+ case IB_QPT_RC:
+@@ -1908,13 +1912,13 @@ static int nes_destroy_cq(struct ib_cq *ib_cq)
+ nesadapter->free_256pbl++;
+ if (nesadapter->free_256pbl > nesadapter->max_256pbl) {
+ printk(KERN_ERR PFX "%s: free 256B PBLs(%u) has exceeded the max(%u)\n",
+- __FUNCTION__, nesadapter->free_256pbl, nesadapter->max_256pbl);
++ __func__, nesadapter->free_256pbl, nesadapter->max_256pbl);
+ }
+ } else if (nescq->virtual_cq == 2) {
+ nesadapter->free_4kpbl++;
+ if (nesadapter->free_4kpbl > nesadapter->max_4kpbl) {
+ printk(KERN_ERR PFX "%s: free 4K PBLs(%u) has exceeded the max(%u)\n",
+- __FUNCTION__, nesadapter->free_4kpbl, nesadapter->max_4kpbl);
++ __func__, nesadapter->free_4kpbl, nesadapter->max_4kpbl);
+ }
+ opcode |= NES_CQP_CQ_4KB_CHUNK;
+ }
+@@ -2653,10 +2657,10 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+
+ nespbl->pbl_vbase = (u64 *)pbl;
+ nespbl->user_base = start;
+- nes_debug(NES_DBG_MR, "Allocated PBL memory, %u bytes, pbl_pbase=%p,"
++ nes_debug(NES_DBG_MR, "Allocated PBL memory, %u bytes, pbl_pbase=%lx,"
+ " pbl_vbase=%p user_base=0x%lx\n",
+- nespbl->pbl_size, (void *)nespbl->pbl_pbase,
+- (void*)nespbl->pbl_vbase, nespbl->user_base);
++ nespbl->pbl_size, (unsigned long) nespbl->pbl_pbase,
++ (void *) nespbl->pbl_vbase, nespbl->user_base);
+
+ list_for_each_entry(chunk, ®ion->chunk_list, list) {
+ for (nmap_index = 0; nmap_index < chunk->nmap; ++nmap_index) {
+@@ -2796,10 +2800,11 @@ static int nes_dereg_mr(struct ib_mr *ib_mr)
+ /**
+ * show_rev
+ */
+-static ssize_t show_rev(struct class_device *cdev, char *buf)
++static ssize_t show_rev(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+ struct nes_ib_device *nesibdev =
+- container_of(cdev, struct nes_ib_device, ibdev.class_dev);
++ container_of(dev, struct nes_ib_device, ibdev.dev);
+ struct nes_vnic *nesvnic = nesibdev->nesvnic;
+
+ nes_debug(NES_DBG_INIT, "\n");
+@@ -2810,10 +2815,11 @@ static ssize_t show_rev(struct class_device *cdev, char *buf)
+ /**
+ * show_fw_ver
+ */
+-static ssize_t show_fw_ver(struct class_device *cdev, char *buf)
++static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+ struct nes_ib_device *nesibdev =
+- container_of(cdev, struct nes_ib_device, ibdev.class_dev);
++ container_of(dev, struct nes_ib_device, ibdev.dev);
+ struct nes_vnic *nesvnic = nesibdev->nesvnic;
+
+ nes_debug(NES_DBG_INIT, "\n");
+@@ -2827,7 +2833,8 @@ static ssize_t show_fw_ver(struct class_device *cdev, char *buf)
+ /**
+ * show_hca
+ */
+-static ssize_t show_hca(struct class_device *cdev, char *buf)
++static ssize_t show_hca(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+ nes_debug(NES_DBG_INIT, "\n");
+ return sprintf(buf, "NES020\n");
+@@ -2837,23 +2844,24 @@ static ssize_t show_hca(struct class_device *cdev, char *buf)
+ /**
+ * show_board
+ */
+-static ssize_t show_board(struct class_device *cdev, char *buf)
++static ssize_t show_board(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+ nes_debug(NES_DBG_INIT, "\n");
+ return sprintf(buf, "%.*s\n", 32, "NES020 Board ID");
+ }
+
+
+-static CLASS_DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
+-static CLASS_DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
+-static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
+-static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
++static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
++static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
++static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
++static DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
+
+-static struct class_device_attribute *nes_class_attributes[] = {
+- &class_device_attr_hw_rev,
+- &class_device_attr_fw_ver,
+- &class_device_attr_hca_type,
+- &class_device_attr_board_id
++static struct device_attribute *nes_dev_attributes[] = {
++ &dev_attr_hw_rev,
++ &dev_attr_fw_ver,
++ &dev_attr_hca_type,
++ &dev_attr_board_id
+ };
+
+
+@@ -3778,7 +3786,7 @@ struct nes_ib_device *nes_init_ofa_device(struct net_device *netdev)
+ nesibdev->ibdev.phys_port_cnt = 1;
+ nesibdev->ibdev.num_comp_vectors = 1;
+ nesibdev->ibdev.dma_device = &nesdev->pcidev->dev;
+- nesibdev->ibdev.class_dev.dev = &nesdev->pcidev->dev;
++ nesibdev->ibdev.dev.parent = &nesdev->pcidev->dev;
+ nesibdev->ibdev.query_device = nes_query_device;
+ nesibdev->ibdev.query_port = nes_query_port;
+ nesibdev->ibdev.modify_port = nes_modify_port;
+@@ -3873,13 +3881,13 @@ int nes_register_ofa_device(struct nes_ib_device *nesibdev)
+ nesibdev->max_qp = (nesadapter->max_qp-NES_FIRST_QPN) / nesadapter->port_count;
+ nesibdev->max_pd = nesadapter->max_pd / nesadapter->port_count;
+
+- for (i = 0; i < ARRAY_SIZE(nes_class_attributes); ++i) {
+- ret = class_device_create_file(&nesibdev->ibdev.class_dev, nes_class_attributes[i]);
++ for (i = 0; i < ARRAY_SIZE(nes_dev_attributes); ++i) {
++ ret = device_create_file(&nesibdev->ibdev.dev, nes_dev_attributes[i]);
+ if (ret) {
+ while (i > 0) {
+ i--;
+- class_device_remove_file(&nesibdev->ibdev.class_dev,
+- nes_class_attributes[i]);
++ device_remove_file(&nesibdev->ibdev.dev,
++ nes_dev_attributes[i]);
+ }
+ ib_unregister_device(&nesibdev->ibdev);
+ return ret;
+@@ -3895,16 +3903,13 @@ int nes_register_ofa_device(struct nes_ib_device *nesibdev)
+ /**
+ * nes_unregister_ofa_device
+ */
+-void nes_unregister_ofa_device(struct nes_ib_device *nesibdev)
++static void nes_unregister_ofa_device(struct nes_ib_device *nesibdev)
+ {
+ struct nes_vnic *nesvnic = nesibdev->nesvnic;
+ int i;
+
+- if (nesibdev == NULL)
+- return;
+-
+- for (i = 0; i < ARRAY_SIZE(nes_class_attributes); ++i) {
+- class_device_remove_file(&nesibdev->ibdev.class_dev, nes_class_attributes[i]);
++ for (i = 0; i < ARRAY_SIZE(nes_dev_attributes); ++i) {
++ device_remove_file(&nesibdev->ibdev.dev, nes_dev_attributes[i]);
+ }
+
+ if (nesvnic->of_device_registered) {
+diff --git a/drivers/infiniband/ulp/ipoib/Makefile b/drivers/infiniband/ulp/ipoib/Makefile
+index 98ee38e..3090100 100644
+--- a/drivers/infiniband/ulp/ipoib/Makefile
++++ b/drivers/infiniband/ulp/ipoib/Makefile
+@@ -4,7 +4,8 @@ ib_ipoib-y := ipoib_main.o \
+ ipoib_ib.o \
+ ipoib_multicast.o \
+ ipoib_verbs.o \
+- ipoib_vlan.o
++ ipoib_vlan.o \
++ ipoib_ethtool.o
+ ib_ipoib-$(CONFIG_INFINIBAND_IPOIB_CM) += ipoib_cm.o
+ ib_ipoib-$(CONFIG_INFINIBAND_IPOIB_DEBUG) += ipoib_fs.o
+
+diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
+index 054fab8..73b2b17 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib.h
++++ b/drivers/infiniband/ulp/ipoib/ipoib.h
+@@ -87,6 +87,7 @@ enum {
+ IPOIB_MCAST_STARTED = 8,
+ IPOIB_FLAG_ADMIN_CM = 9,
+ IPOIB_FLAG_UMCAST = 10,
++ IPOIB_FLAG_CSUM = 11,
+
+ IPOIB_MAX_BACKOFF_SECONDS = 16,
+
+@@ -241,6 +242,11 @@ struct ipoib_cm_dev_priv {
+ int num_frags;
+ };
+
++struct ipoib_ethtool_st {
++ u16 coalesce_usecs;
++ u16 max_coalesced_frames;
++};
++
+ /*
+ * Device private locking: tx_lock protects members used in TX fast
+ * path (and we use LLTX so upper layers don't do extra locking).
+@@ -318,6 +324,8 @@ struct ipoib_dev_priv {
+ struct dentry *mcg_dentry;
+ struct dentry *path_dentry;
+ #endif
++ int hca_caps;
++ struct ipoib_ethtool_st ethtool;
+ };
+
+ struct ipoib_ah {
+@@ -458,6 +466,8 @@ void ipoib_pkey_poll(struct work_struct *work);
+ int ipoib_pkey_dev_delay_open(struct net_device *dev);
+ void ipoib_drain_cq(struct net_device *dev);
+
++void ipoib_set_ethtool_ops(struct net_device *dev);
++
+ #ifdef CONFIG_INFINIBAND_IPOIB_CM
+
+ #define IPOIB_FLAGS_RC 0x80
+diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+index 2490b2d..9db7b0b 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+@@ -1007,9 +1007,9 @@ static int ipoib_cm_modify_tx_init(struct net_device *dev,
+ struct ipoib_dev_priv *priv = netdev_priv(dev);
+ struct ib_qp_attr qp_attr;
+ int qp_attr_mask, ret;
+- ret = ib_find_cached_pkey(priv->ca, priv->port, priv->pkey, &qp_attr.pkey_index);
++ ret = ib_find_pkey(priv->ca, priv->port, priv->pkey, &qp_attr.pkey_index);
+ if (ret) {
+- ipoib_warn(priv, "pkey 0x%x not in cache: %d\n", priv->pkey, ret);
++ ipoib_warn(priv, "pkey 0x%x not found: %d\n", priv->pkey, ret);
+ return ret;
+ }
+
+@@ -1383,6 +1383,10 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr,
+ set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
+ ipoib_warn(priv, "enabling connected mode "
+ "will cause multicast packet drops\n");
++
++ dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO);
++ priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM;
++
+ ipoib_flush_paths(dev);
+ return count;
+ }
+@@ -1391,6 +1395,13 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr,
+ clear_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
+ dev->mtu = min(priv->mcast_mtu, dev->mtu);
+ ipoib_flush_paths(dev);
++
++ if (test_bit(IPOIB_FLAG_CSUM, &priv->flags)) {
++ dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
++ if (priv->hca_caps & IB_DEVICE_UD_TSO)
++ dev->features |= NETIF_F_TSO;
++ }
++
+ return count;
+ }
+
+diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
+new file mode 100644
+index 0000000..9a47428
+--- /dev/null
++++ b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
+@@ -0,0 +1,99 @@
++/*
++ * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses. You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ * Redistribution and use in source and binary forms, with or
++ * without modification, are permitted provided that the following
++ * conditions are met:
++ *
++ * - Redistributions of source code must retain the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer.
++ *
++ * - Redistributions in binary form must reproduce the above
++ * copyright notice, this list of conditions and the following
++ * disclaimer in the documentation and/or other materials
++ * provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <linux/kernel.h>
++#include <linux/ethtool.h>
++#include <linux/netdevice.h>
++
++#include "ipoib.h"
++
++static void ipoib_get_drvinfo(struct net_device *netdev,
++ struct ethtool_drvinfo *drvinfo)
++{
++ strncpy(drvinfo->driver, "ipoib", sizeof(drvinfo->driver) - 1);
++}
++
++static int ipoib_get_coalesce(struct net_device *dev,
++ struct ethtool_coalesce *coal)
++{
++ struct ipoib_dev_priv *priv = netdev_priv(dev);
++
++ coal->rx_coalesce_usecs = priv->ethtool.coalesce_usecs;
++ coal->tx_coalesce_usecs = priv->ethtool.coalesce_usecs;
++ coal->rx_max_coalesced_frames = priv->ethtool.max_coalesced_frames;
++ coal->tx_max_coalesced_frames = priv->ethtool.max_coalesced_frames;
++
++ return 0;
++}
++
++static int ipoib_set_coalesce(struct net_device *dev,
++ struct ethtool_coalesce *coal)
++{
++ struct ipoib_dev_priv *priv = netdev_priv(dev);
++ int ret;
++
++ /*
++ * Since IPoIB uses a single CQ for both rx and tx, we assume
++ * that rx params dictate the configuration. These values are
++ * saved in the private data and returned when ipoib_get_coalesce()
++ * is called.
++ */
++ if (coal->rx_coalesce_usecs > 0xffff ||
++ coal->rx_max_coalesced_frames > 0xffff)
++ return -EINVAL;
++
++ ret = ib_modify_cq(priv->cq, coal->rx_max_coalesced_frames,
++ coal->rx_coalesce_usecs);
++ if (ret && ret != -ENOSYS) {
++ ipoib_warn(priv, "failed modifying CQ (%d)\n", ret);
++ return ret;
++ }
++
++ coal->tx_coalesce_usecs = coal->rx_coalesce_usecs;
++ coal->tx_max_coalesced_frames = coal->rx_max_coalesced_frames;
++ priv->ethtool.coalesce_usecs = coal->rx_coalesce_usecs;
++ priv->ethtool.max_coalesced_frames = coal->rx_max_coalesced_frames;
++
++ return 0;
++}
++
++static const struct ethtool_ops ipoib_ethtool_ops = {
++ .get_drvinfo = ipoib_get_drvinfo,
++ .get_tso = ethtool_op_get_tso,
++ .get_coalesce = ipoib_get_coalesce,
++ .set_coalesce = ipoib_set_coalesce,
++};
++
++void ipoib_set_ethtool_ops(struct net_device *dev)
++{
++ SET_ETHTOOL_OPS(dev, &ipoib_ethtool_ops);
++}
+diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+index 08c4396..0205eb7 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+@@ -39,6 +39,8 @@
+ #include <linux/dma-mapping.h>
+
+ #include <rdma/ib_cache.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
+
+ #include "ipoib.h"
+
+@@ -231,6 +233,10 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
+ skb->dev = dev;
+ /* XXX get correct PACKET_ type here */
+ skb->pkt_type = PACKET_HOST;
++
++ if (test_bit(IPOIB_FLAG_CSUM, &priv->flags) && likely(wc->csum_ok))
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++
+ netif_receive_skb(skb);
+
+ repost:
+@@ -245,29 +251,37 @@ static int ipoib_dma_map_tx(struct ib_device *ca,
+ struct sk_buff *skb = tx_req->skb;
+ u64 *mapping = tx_req->mapping;
+ int i;
++ int off;
+
+- mapping[0] = ib_dma_map_single(ca, skb->data, skb_headlen(skb),
+- DMA_TO_DEVICE);
+- if (unlikely(ib_dma_mapping_error(ca, mapping[0])))
+- return -EIO;
++ if (skb_headlen(skb)) {
++ mapping[0] = ib_dma_map_single(ca, skb->data, skb_headlen(skb),
++ DMA_TO_DEVICE);
++ if (unlikely(ib_dma_mapping_error(ca, mapping[0])))
++ return -EIO;
++
++ off = 1;
++ } else
++ off = 0;
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+- mapping[i + 1] = ib_dma_map_page(ca, frag->page,
++ mapping[i + off] = ib_dma_map_page(ca, frag->page,
+ frag->page_offset, frag->size,
+ DMA_TO_DEVICE);
+- if (unlikely(ib_dma_mapping_error(ca, mapping[i + 1])))
++ if (unlikely(ib_dma_mapping_error(ca, mapping[i + off])))
+ goto partial_error;
+ }
+ return 0;
+
+ partial_error:
+- ib_dma_unmap_single(ca, mapping[0], skb_headlen(skb), DMA_TO_DEVICE);
+-
+ for (; i > 0; --i) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1];
+- ib_dma_unmap_page(ca, mapping[i], frag->size, DMA_TO_DEVICE);
++ ib_dma_unmap_page(ca, mapping[i - !off], frag->size, DMA_TO_DEVICE);
+ }
++
++ if (off)
++ ib_dma_unmap_single(ca, mapping[0], skb_headlen(skb), DMA_TO_DEVICE);
++
+ return -EIO;
+ }
+
+@@ -277,12 +291,17 @@ static void ipoib_dma_unmap_tx(struct ib_device *ca,
+ struct sk_buff *skb = tx_req->skb;
+ u64 *mapping = tx_req->mapping;
+ int i;
++ int off;
+
+- ib_dma_unmap_single(ca, mapping[0], skb_headlen(skb), DMA_TO_DEVICE);
++ if (skb_headlen(skb)) {
++ ib_dma_unmap_single(ca, mapping[0], skb_headlen(skb), DMA_TO_DEVICE);
++ off = 1;
++ } else
++ off = 0;
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+- ib_dma_unmap_page(ca, mapping[i + 1], frag->size,
++ ib_dma_unmap_page(ca, mapping[i + off], frag->size,
+ DMA_TO_DEVICE);
+ }
+ }
+@@ -388,24 +407,40 @@ void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr)
+ static inline int post_send(struct ipoib_dev_priv *priv,
+ unsigned int wr_id,
+ struct ib_ah *address, u32 qpn,
+- u64 *mapping, int headlen,
+- skb_frag_t *frags,
+- int nr_frags)
++ struct ipoib_tx_buf *tx_req,
++ void *head, int hlen)
+ {
+ struct ib_send_wr *bad_wr;
+- int i;
++ int i, off;
++ struct sk_buff *skb = tx_req->skb;
++ skb_frag_t *frags = skb_shinfo(skb)->frags;
++ int nr_frags = skb_shinfo(skb)->nr_frags;
++ u64 *mapping = tx_req->mapping;
++
++ if (skb_headlen(skb)) {
++ priv->tx_sge[0].addr = mapping[0];
++ priv->tx_sge[0].length = skb_headlen(skb);
++ off = 1;
++ } else
++ off = 0;
+
+- priv->tx_sge[0].addr = mapping[0];
+- priv->tx_sge[0].length = headlen;
+ for (i = 0; i < nr_frags; ++i) {
+- priv->tx_sge[i + 1].addr = mapping[i + 1];
+- priv->tx_sge[i + 1].length = frags[i].size;
++ priv->tx_sge[i + off].addr = mapping[i + off];
++ priv->tx_sge[i + off].length = frags[i].size;
+ }
+- priv->tx_wr.num_sge = nr_frags + 1;
++ priv->tx_wr.num_sge = nr_frags + off;
+ priv->tx_wr.wr_id = wr_id;
+ priv->tx_wr.wr.ud.remote_qpn = qpn;
+ priv->tx_wr.wr.ud.ah = address;
+
++ if (head) {
++ priv->tx_wr.wr.ud.mss = skb_shinfo(skb)->gso_size;
++ priv->tx_wr.wr.ud.header = head;
++ priv->tx_wr.wr.ud.hlen = hlen;
++ priv->tx_wr.opcode = IB_WR_LSO;
++ } else
++ priv->tx_wr.opcode = IB_WR_SEND;
++
+ return ib_post_send(priv->qp, &priv->tx_wr, &bad_wr);
+ }
+
+@@ -414,14 +449,30 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
+ {
+ struct ipoib_dev_priv *priv = netdev_priv(dev);
+ struct ipoib_tx_buf *tx_req;
+-
+- if (unlikely(skb->len > priv->mcast_mtu + IPOIB_ENCAP_LEN)) {
+- ipoib_warn(priv, "packet len %d (> %d) too long to send, dropping\n",
+- skb->len, priv->mcast_mtu + IPOIB_ENCAP_LEN);
+- ++dev->stats.tx_dropped;
+- ++dev->stats.tx_errors;
+- ipoib_cm_skb_too_long(dev, skb, priv->mcast_mtu);
+- return;
++ int hlen;
++ void *phead;
++
++ if (skb_is_gso(skb)) {
++ hlen = skb_transport_offset(skb) + tcp_hdrlen(skb);
++ phead = skb->data;
++ if (unlikely(!skb_pull(skb, hlen))) {
++ ipoib_warn(priv, "linear data too small\n");
++ ++dev->stats.tx_dropped;
++ ++dev->stats.tx_errors;
++ dev_kfree_skb_any(skb);
++ return;
++ }
++ } else {
++ if (unlikely(skb->len > priv->mcast_mtu + IPOIB_ENCAP_LEN)) {
++ ipoib_warn(priv, "packet len %d (> %d) too long to send, dropping\n",
++ skb->len, priv->mcast_mtu + IPOIB_ENCAP_LEN);
++ ++dev->stats.tx_dropped;
++ ++dev->stats.tx_errors;
++ ipoib_cm_skb_too_long(dev, skb, priv->mcast_mtu);
++ return;
++ }
++ phead = NULL;
++ hlen = 0;
+ }
+
+ ipoib_dbg_data(priv, "sending packet, length=%d address=%p qpn=0x%06x\n",
+@@ -442,10 +493,13 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
+ return;
+ }
+
++ if (skb->ip_summed == CHECKSUM_PARTIAL)
++ priv->tx_wr.send_flags |= IB_SEND_IP_CSUM;
++ else
++ priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM;
++
+ if (unlikely(post_send(priv, priv->tx_head & (ipoib_sendq_size - 1),
+- address->ah, qpn,
+- tx_req->mapping, skb_headlen(skb),
+- skb_shinfo(skb)->frags, skb_shinfo(skb)->nr_frags))) {
++ address->ah, qpn, tx_req, phead, hlen))) {
+ ipoib_warn(priv, "post_send failed\n");
+ ++dev->stats.tx_errors;
+ ipoib_dma_unmap_tx(priv->ca, tx_req);
+@@ -540,7 +594,7 @@ static void ipoib_pkey_dev_check_presence(struct net_device *dev)
+ struct ipoib_dev_priv *priv = netdev_priv(dev);
+ u16 pkey_index = 0;
+
+- if (ib_find_cached_pkey(priv->ca, priv->port, priv->pkey, &pkey_index))
++ if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &pkey_index))
+ clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
+ else
+ set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
+@@ -781,13 +835,13 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, int pkey_event)
+ clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
+ ipoib_ib_dev_down(dev, 0);
+ ipoib_ib_dev_stop(dev, 0);
+- ipoib_pkey_dev_delay_open(dev);
+- return;
++ if (ipoib_pkey_dev_delay_open(dev))
++ return;
+ }
+- set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
+
+ /* restart QP only if P_Key index is changed */
+- if (new_index == priv->pkey_index) {
++ if (test_and_set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags) &&
++ new_index == priv->pkey_index) {
+ ipoib_dbg(priv, "Not flushing - P_Key index not changed.\n");
+ return;
+ }
+diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
+index 5728204..bd07f02 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
+@@ -359,8 +359,7 @@ void ipoib_flush_paths(struct net_device *dev)
+ spin_lock_irq(&priv->tx_lock);
+ spin_lock(&priv->lock);
+
+- list_splice(&priv->path_list, &remove_list);
+- INIT_LIST_HEAD(&priv->path_list);
++ list_splice_init(&priv->path_list, &remove_list);
+
+ list_for_each_entry(path, &remove_list, list)
+ rb_erase(&path->rb_node, &priv->path_tree);
+@@ -952,6 +951,8 @@ static void ipoib_setup(struct net_device *dev)
+ dev->set_multicast_list = ipoib_set_mcast_list;
+ dev->neigh_setup = ipoib_neigh_setup_dev;
+
++ ipoib_set_ethtool_ops(dev);
++
+ netif_napi_add(dev, &priv->napi, ipoib_poll, 100);
+
+ dev->watchdog_timeo = HZ;
+@@ -1105,6 +1106,7 @@ static struct net_device *ipoib_add_port(const char *format,
+ struct ib_device *hca, u8 port)
+ {
+ struct ipoib_dev_priv *priv;
++ struct ib_device_attr *device_attr;
+ int result = -ENOMEM;
+
+ priv = ipoib_intf_alloc(format);
+@@ -1120,6 +1122,29 @@ static struct net_device *ipoib_add_port(const char *format,
+ goto device_init_failed;
+ }
+
++ device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL);
++ if (!device_attr) {
++ printk(KERN_WARNING "%s: allocation of %zu bytes failed\n",
++ hca->name, sizeof *device_attr);
++ goto device_init_failed;
++ }
++
++ result = ib_query_device(hca, device_attr);
++ if (result) {
++ printk(KERN_WARNING "%s: ib_query_device failed (ret = %d)\n",
++ hca->name, result);
++ kfree(device_attr);
++ goto device_init_failed;
++ }
++ priv->hca_caps = device_attr->device_cap_flags;
++
++ kfree(device_attr);
++
++ if (priv->hca_caps & IB_DEVICE_UD_IP_CSUM) {
++ set_bit(IPOIB_FLAG_CSUM, &priv->flags);
++ priv->dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
++ }
++
+ /*
+ * Set the full membership bit, so that we join the right
+ * broadcast group, etc.
+@@ -1137,7 +1162,6 @@ static struct net_device *ipoib_add_port(const char *format,
+ } else
+ memcpy(priv->dev->dev_addr + 4, priv->local_gid.raw, sizeof (union ib_gid));
+
+-
+ result = ipoib_dev_init(priv->dev, hca, port);
+ if (result < 0) {
+ printk(KERN_WARNING "%s: failed to initialize port %d (ret = %d)\n",
+@@ -1155,6 +1179,9 @@ static struct net_device *ipoib_add_port(const char *format,
+ goto event_failed;
+ }
+
++ if (priv->dev->features & NETIF_F_SG && priv->hca_caps & IB_DEVICE_UD_TSO)
++ priv->dev->features |= NETIF_F_TSO;
++
+ result = register_netdev(priv->dev);
+ if (result) {
+ printk(KERN_WARNING "%s: couldn't register ipoib port %d; error %d\n",
+diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+index a3aeb91..8a20e37 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+@@ -192,6 +192,9 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
+ init_attr.send_cq = priv->cq;
+ init_attr.recv_cq = priv->cq;
+
++ if (priv->hca_caps & IB_DEVICE_UD_TSO)
++ init_attr.create_flags = IB_QP_CREATE_IPOIB_UD_LSO;
++
+ if (dev->features & NETIF_F_SG)
+ init_attr.cap.max_send_sge = MAX_SKB_FRAGS + 1;
+
+diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
+index 83247f1..08dc81c 100644
+--- a/drivers/infiniband/ulp/iser/iser_initiator.c
++++ b/drivers/infiniband/ulp/iser/iser_initiator.c
+@@ -405,7 +405,7 @@ int iser_send_data_out(struct iscsi_conn *conn,
+ struct iser_dto *send_dto = NULL;
+ unsigned long buf_offset;
+ unsigned long data_seg_len;
+- unsigned int itt;
++ uint32_t itt;
+ int err = 0;
+
+ if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) {
+@@ -416,7 +416,7 @@ int iser_send_data_out(struct iscsi_conn *conn,
+ if (iser_check_xmit(conn, ctask))
+ return -ENOBUFS;
+
+- itt = ntohl(hdr->itt);
++ itt = (__force uint32_t)hdr->itt;
+ data_seg_len = ntoh24(hdr->dlength);
+ buf_offset = ntohl(hdr->offset);
+
+diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
+index 993f0a8..d19cfe6 100644
+--- a/drivers/infiniband/ulp/iser/iser_verbs.c
++++ b/drivers/infiniband/ulp/iser/iser_verbs.c
+@@ -473,11 +473,8 @@ static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *eve
+ iser_connect_error(cma_id);
+ break;
+ case RDMA_CM_EVENT_DISCONNECTED:
+- iser_disconnected_handler(cma_id);
+- break;
+ case RDMA_CM_EVENT_DEVICE_REMOVAL:
+- iser_err("Device removal is currently unsupported\n");
+- BUG();
++ iser_disconnected_handler(cma_id);
+ break;
+ default:
+ iser_err("Unexpected RDMA CM event (%d)\n", event->event);
+diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
+index fd4a49f..4351457 100644
+--- a/drivers/infiniband/ulp/srp/ib_srp.c
++++ b/drivers/infiniband/ulp/srp/ib_srp.c
+@@ -68,7 +68,7 @@ static int srp_max_iu_len;
+
+ module_param(srp_sg_tablesize, int, 0444);
+ MODULE_PARM_DESC(srp_sg_tablesize,
+- "Max number of gather/scatter entries per I/O (default is 12)");
++ "Max number of gather/scatter entries per I/O (default is 12, max 255)");
+
+ static int topspin_workarounds = 1;
+
+@@ -139,8 +139,9 @@ static struct srp_iu *srp_alloc_iu(struct srp_host *host, size_t size,
+ if (!iu->buf)
+ goto out_free_iu;
+
+- iu->dma = ib_dma_map_single(host->dev->dev, iu->buf, size, direction);
+- if (ib_dma_mapping_error(host->dev->dev, iu->dma))
++ iu->dma = ib_dma_map_single(host->srp_dev->dev, iu->buf, size,
++ direction);
++ if (ib_dma_mapping_error(host->srp_dev->dev, iu->dma))
+ goto out_free_buf;
+
+ iu->size = size;
+@@ -161,7 +162,8 @@ static void srp_free_iu(struct srp_host *host, struct srp_iu *iu)
+ if (!iu)
+ return;
+
+- ib_dma_unmap_single(host->dev->dev, iu->dma, iu->size, iu->direction);
++ ib_dma_unmap_single(host->srp_dev->dev, iu->dma, iu->size,
++ iu->direction);
+ kfree(iu->buf);
+ kfree(iu);
+ }
+@@ -181,7 +183,7 @@ static int srp_init_qp(struct srp_target_port *target,
+ if (!attr)
+ return -ENOMEM;
+
+- ret = ib_find_cached_pkey(target->srp_host->dev->dev,
++ ret = ib_find_cached_pkey(target->srp_host->srp_dev->dev,
+ target->srp_host->port,
+ be16_to_cpu(target->path.pkey),
+ &attr->pkey_index);
+@@ -208,7 +210,7 @@ static int srp_new_cm_id(struct srp_target_port *target)
+ {
+ struct ib_cm_id *new_cm_id;
+
+- new_cm_id = ib_create_cm_id(target->srp_host->dev->dev,
++ new_cm_id = ib_create_cm_id(target->srp_host->srp_dev->dev,
+ srp_cm_handler, target);
+ if (IS_ERR(new_cm_id))
+ return PTR_ERR(new_cm_id);
+@@ -229,8 +231,8 @@ static int srp_create_target_ib(struct srp_target_port *target)
+ if (!init_attr)
+ return -ENOMEM;
+
+- target->cq = ib_create_cq(target->srp_host->dev->dev, srp_completion,
+- NULL, target, SRP_CQ_SIZE, 0);
++ target->cq = ib_create_cq(target->srp_host->srp_dev->dev,
++ srp_completion, NULL, target, SRP_CQ_SIZE, 0);
+ if (IS_ERR(target->cq)) {
+ ret = PTR_ERR(target->cq);
+ goto out;
+@@ -248,7 +250,7 @@ static int srp_create_target_ib(struct srp_target_port *target)
+ init_attr->send_cq = target->cq;
+ init_attr->recv_cq = target->cq;
+
+- target->qp = ib_create_qp(target->srp_host->dev->pd, init_attr);
++ target->qp = ib_create_qp(target->srp_host->srp_dev->pd, init_attr);
+ if (IS_ERR(target->qp)) {
+ ret = PTR_ERR(target->qp);
+ ib_destroy_cq(target->cq);
+@@ -302,7 +304,7 @@ static int srp_lookup_path(struct srp_target_port *target)
+ init_completion(&target->done);
+
+ target->path_query_id = ib_sa_path_rec_get(&srp_sa_client,
+- target->srp_host->dev->dev,
++ target->srp_host->srp_dev->dev,
+ target->srp_host->port,
+ &target->path,
+ IB_SA_PATH_REC_SERVICE_ID |
+@@ -403,7 +405,7 @@ static int srp_send_req(struct srp_target_port *target)
+ (unsigned long long) be64_to_cpu(target->ioc_guid));
+ memset(req->priv.initiator_port_id, 0, 8);
+ memcpy(req->priv.initiator_port_id + 8,
+- &target->srp_host->dev->dev->node_guid, 8);
++ &target->srp_host->srp_dev->dev->node_guid, 8);
+ }
+
+ status = ib_send_cm_req(target->cm_id, &req->param);
+@@ -520,7 +522,7 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd,
+ req->fmr = NULL;
+ }
+
+- ib_dma_unmap_sg(target->srp_host->dev->dev, scsi_sglist(scmnd),
++ ib_dma_unmap_sg(target->srp_host->srp_dev->dev, scsi_sglist(scmnd),
+ scsi_sg_count(scmnd), scmnd->sc_data_direction);
+ }
+
+@@ -628,7 +630,7 @@ static int srp_map_fmr(struct srp_target_port *target, struct scatterlist *scat,
+ int page_cnt;
+ int i, j;
+ int ret;
+- struct srp_device *dev = target->srp_host->dev;
++ struct srp_device *dev = target->srp_host->srp_dev;
+ struct ib_device *ibdev = dev->dev;
+ struct scatterlist *sg;
+
+@@ -723,7 +725,7 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
+ nents = scsi_sg_count(scmnd);
+ scat = scsi_sglist(scmnd);
+
+- dev = target->srp_host->dev;
++ dev = target->srp_host->srp_dev;
+ ibdev = dev->dev;
+
+ count = ib_dma_map_sg(ibdev, scat, nents, scmnd->sc_data_direction);
+@@ -779,7 +781,7 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
+ buf->table_desc.va =
+ cpu_to_be64(req->cmd->dma + sizeof *cmd + sizeof *buf);
+ buf->table_desc.key =
+- cpu_to_be32(target->srp_host->dev->mr->rkey);
++ cpu_to_be32(target->srp_host->srp_dev->mr->rkey);
+ buf->table_desc.len =
+ cpu_to_be32(count * sizeof (struct srp_direct_buf));
+
+@@ -855,7 +857,7 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
+
+ iu = target->rx_ring[wc->wr_id & ~SRP_OP_RECV];
+
+- dev = target->srp_host->dev->dev;
++ dev = target->srp_host->srp_dev->dev;
+ ib_dma_sync_single_for_cpu(dev, iu->dma, target->max_ti_iu_len,
+ DMA_FROM_DEVICE);
+
+@@ -937,7 +939,7 @@ static int __srp_post_recv(struct srp_target_port *target)
+
+ list.addr = iu->dma;
+ list.length = iu->size;
+- list.lkey = target->srp_host->dev->mr->lkey;
++ list.lkey = target->srp_host->srp_dev->mr->lkey;
+
+ wr.next = NULL;
+ wr.sg_list = &list;
+@@ -996,7 +998,7 @@ static int __srp_post_send(struct srp_target_port *target,
+
+ list.addr = iu->dma;
+ list.length = len;
+- list.lkey = target->srp_host->dev->mr->lkey;
++ list.lkey = target->srp_host->srp_dev->mr->lkey;
+
+ wr.next = NULL;
+ wr.wr_id = target->tx_head & SRP_SQ_SIZE;
+@@ -1039,7 +1041,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
+ if (!iu)
+ goto err;
+
+- dev = target->srp_host->dev->dev;
++ dev = target->srp_host->srp_dev->dev;
+ ib_dma_sync_single_for_cpu(dev, iu->dma, srp_max_iu_len,
+ DMA_TO_DEVICE);
+
+@@ -1456,9 +1458,10 @@ static int srp_reset_host(struct scsi_cmnd *scmnd)
+ return ret;
+ }
+
+-static ssize_t show_id_ext(struct class_device *cdev, char *buf)
++static ssize_t show_id_ext(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct srp_target_port *target = host_to_target(class_to_shost(cdev));
++ struct srp_target_port *target = host_to_target(class_to_shost(dev));
+
+ if (target->state == SRP_TARGET_DEAD ||
+ target->state == SRP_TARGET_REMOVED)
+@@ -1468,9 +1471,10 @@ static ssize_t show_id_ext(struct class_device *cdev, char *buf)
+ (unsigned long long) be64_to_cpu(target->id_ext));
+ }
+
+-static ssize_t show_ioc_guid(struct class_device *cdev, char *buf)
++static ssize_t show_ioc_guid(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct srp_target_port *target = host_to_target(class_to_shost(cdev));
++ struct srp_target_port *target = host_to_target(class_to_shost(dev));
+
+ if (target->state == SRP_TARGET_DEAD ||
+ target->state == SRP_TARGET_REMOVED)
+@@ -1480,9 +1484,10 @@ static ssize_t show_ioc_guid(struct class_device *cdev, char *buf)
+ (unsigned long long) be64_to_cpu(target->ioc_guid));
+ }
+
+-static ssize_t show_service_id(struct class_device *cdev, char *buf)
++static ssize_t show_service_id(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct srp_target_port *target = host_to_target(class_to_shost(cdev));
++ struct srp_target_port *target = host_to_target(class_to_shost(dev));
+
+ if (target->state == SRP_TARGET_DEAD ||
+ target->state == SRP_TARGET_REMOVED)
+@@ -1492,9 +1497,10 @@ static ssize_t show_service_id(struct class_device *cdev, char *buf)
+ (unsigned long long) be64_to_cpu(target->service_id));
+ }
+
+-static ssize_t show_pkey(struct class_device *cdev, char *buf)
++static ssize_t show_pkey(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct srp_target_port *target = host_to_target(class_to_shost(cdev));
++ struct srp_target_port *target = host_to_target(class_to_shost(dev));
+
+ if (target->state == SRP_TARGET_DEAD ||
+ target->state == SRP_TARGET_REMOVED)
+@@ -1503,9 +1509,10 @@ static ssize_t show_pkey(struct class_device *cdev, char *buf)
+ return sprintf(buf, "0x%04x\n", be16_to_cpu(target->path.pkey));
+ }
+
+-static ssize_t show_dgid(struct class_device *cdev, char *buf)
++static ssize_t show_dgid(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct srp_target_port *target = host_to_target(class_to_shost(cdev));
++ struct srp_target_port *target = host_to_target(class_to_shost(dev));
+
+ if (target->state == SRP_TARGET_DEAD ||
+ target->state == SRP_TARGET_REMOVED)
+@@ -1522,9 +1529,10 @@ static ssize_t show_dgid(struct class_device *cdev, char *buf)
+ be16_to_cpu(((__be16 *) target->path.dgid.raw)[7]));
+ }
+
+-static ssize_t show_orig_dgid(struct class_device *cdev, char *buf)
++static ssize_t show_orig_dgid(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct srp_target_port *target = host_to_target(class_to_shost(cdev));
++ struct srp_target_port *target = host_to_target(class_to_shost(dev));
+
+ if (target->state == SRP_TARGET_DEAD ||
+ target->state == SRP_TARGET_REMOVED)
+@@ -1541,9 +1549,10 @@ static ssize_t show_orig_dgid(struct class_device *cdev, char *buf)
+ be16_to_cpu(target->orig_dgid[7]));
+ }
+
+-static ssize_t show_zero_req_lim(struct class_device *cdev, char *buf)
++static ssize_t show_zero_req_lim(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct srp_target_port *target = host_to_target(class_to_shost(cdev));
++ struct srp_target_port *target = host_to_target(class_to_shost(dev));
+
+ if (target->state == SRP_TARGET_DEAD ||
+ target->state == SRP_TARGET_REMOVED)
+@@ -1552,40 +1561,42 @@ static ssize_t show_zero_req_lim(struct class_device *cdev, char *buf)
+ return sprintf(buf, "%d\n", target->zero_req_lim);
+ }
+
+-static ssize_t show_local_ib_port(struct class_device *cdev, char *buf)
++static ssize_t show_local_ib_port(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct srp_target_port *target = host_to_target(class_to_shost(cdev));
++ struct srp_target_port *target = host_to_target(class_to_shost(dev));
+
+ return sprintf(buf, "%d\n", target->srp_host->port);
+ }
+
+-static ssize_t show_local_ib_device(struct class_device *cdev, char *buf)
++static ssize_t show_local_ib_device(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct srp_target_port *target = host_to_target(class_to_shost(cdev));
++ struct srp_target_port *target = host_to_target(class_to_shost(dev));
+
+- return sprintf(buf, "%s\n", target->srp_host->dev->dev->name);
++ return sprintf(buf, "%s\n", target->srp_host->srp_dev->dev->name);
+ }
+
+-static CLASS_DEVICE_ATTR(id_ext, S_IRUGO, show_id_ext, NULL);
+-static CLASS_DEVICE_ATTR(ioc_guid, S_IRUGO, show_ioc_guid, NULL);
+-static CLASS_DEVICE_ATTR(service_id, S_IRUGO, show_service_id, NULL);
+-static CLASS_DEVICE_ATTR(pkey, S_IRUGO, show_pkey, NULL);
+-static CLASS_DEVICE_ATTR(dgid, S_IRUGO, show_dgid, NULL);
+-static CLASS_DEVICE_ATTR(orig_dgid, S_IRUGO, show_orig_dgid, NULL);
+-static CLASS_DEVICE_ATTR(zero_req_lim, S_IRUGO, show_zero_req_lim, NULL);
+-static CLASS_DEVICE_ATTR(local_ib_port, S_IRUGO, show_local_ib_port, NULL);
+-static CLASS_DEVICE_ATTR(local_ib_device, S_IRUGO, show_local_ib_device, NULL);
+-
+-static struct class_device_attribute *srp_host_attrs[] = {
+- &class_device_attr_id_ext,
+- &class_device_attr_ioc_guid,
+- &class_device_attr_service_id,
+- &class_device_attr_pkey,
+- &class_device_attr_dgid,
+- &class_device_attr_orig_dgid,
+- &class_device_attr_zero_req_lim,
+- &class_device_attr_local_ib_port,
+- &class_device_attr_local_ib_device,
++static DEVICE_ATTR(id_ext, S_IRUGO, show_id_ext, NULL);
++static DEVICE_ATTR(ioc_guid, S_IRUGO, show_ioc_guid, NULL);
++static DEVICE_ATTR(service_id, S_IRUGO, show_service_id, NULL);
++static DEVICE_ATTR(pkey, S_IRUGO, show_pkey, NULL);
++static DEVICE_ATTR(dgid, S_IRUGO, show_dgid, NULL);
++static DEVICE_ATTR(orig_dgid, S_IRUGO, show_orig_dgid, NULL);
++static DEVICE_ATTR(zero_req_lim, S_IRUGO, show_zero_req_lim, NULL);
++static DEVICE_ATTR(local_ib_port, S_IRUGO, show_local_ib_port, NULL);
++static DEVICE_ATTR(local_ib_device, S_IRUGO, show_local_ib_device, NULL);
++
++static struct device_attribute *srp_host_attrs[] = {
++ &dev_attr_id_ext,
++ &dev_attr_ioc_guid,
++ &dev_attr_service_id,
++ &dev_attr_pkey,
++ &dev_attr_dgid,
++ &dev_attr_orig_dgid,
++ &dev_attr_zero_req_lim,
++ &dev_attr_local_ib_port,
++ &dev_attr_local_ib_device,
+ NULL
+ };
+
+@@ -1613,7 +1624,7 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
+ sprintf(target->target_name, "SRP.T10:%016llX",
+ (unsigned long long) be64_to_cpu(target->id_ext));
+
+- if (scsi_add_host(target->scsi_host, host->dev->dev->dma_device))
++ if (scsi_add_host(target->scsi_host, host->srp_dev->dev->dma_device))
+ return -ENODEV;
+
+ memcpy(ids.port_id, &target->id_ext, 8);
+@@ -1637,17 +1648,17 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
+ return 0;
+ }
+
+-static void srp_release_class_dev(struct class_device *class_dev)
++static void srp_release_dev(struct device *dev)
+ {
+ struct srp_host *host =
+- container_of(class_dev, struct srp_host, class_dev);
++ container_of(dev, struct srp_host, dev);
+
+ complete(&host->released);
+ }
+
+ static struct class srp_class = {
+ .name = "infiniband_srp",
+- .release = srp_release_class_dev
++ .dev_release = srp_release_dev
+ };
+
+ /*
+@@ -1835,11 +1846,12 @@ out:
+ return ret;
+ }
+
+-static ssize_t srp_create_target(struct class_device *class_dev,
++static ssize_t srp_create_target(struct device *dev,
++ struct device_attribute *attr,
+ const char *buf, size_t count)
+ {
+ struct srp_host *host =
+- container_of(class_dev, struct srp_host, class_dev);
++ container_of(dev, struct srp_host, dev);
+ struct Scsi_Host *target_host;
+ struct srp_target_port *target;
+ int ret;
+@@ -1871,7 +1883,8 @@ static ssize_t srp_create_target(struct class_device *class_dev,
+ if (ret)
+ goto err;
+
+- ib_get_cached_gid(host->dev->dev, host->port, 0, &target->path.sgid);
++ ib_get_cached_gid(host->srp_dev->dev, host->port, 0,
++ &target->path.sgid);
+
+ shost_printk(KERN_DEBUG, target->scsi_host, PFX
+ "new target: id_ext %016llx ioc_guid %016llx pkey %04x "
+@@ -1926,27 +1939,27 @@ err:
+ return ret;
+ }
+
+-static CLASS_DEVICE_ATTR(add_target, S_IWUSR, NULL, srp_create_target);
++static DEVICE_ATTR(add_target, S_IWUSR, NULL, srp_create_target);
+
+-static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
++static ssize_t show_ibdev(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct srp_host *host =
+- container_of(class_dev, struct srp_host, class_dev);
++ struct srp_host *host = container_of(dev, struct srp_host, dev);
+
+- return sprintf(buf, "%s\n", host->dev->dev->name);
++ return sprintf(buf, "%s\n", host->srp_dev->dev->name);
+ }
+
+-static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
++static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
+
+-static ssize_t show_port(struct class_device *class_dev, char *buf)
++static ssize_t show_port(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct srp_host *host =
+- container_of(class_dev, struct srp_host, class_dev);
++ struct srp_host *host = container_of(dev, struct srp_host, dev);
+
+ return sprintf(buf, "%d\n", host->port);
+ }
+
+-static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
++static DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
+
+ static struct srp_host *srp_add_port(struct srp_device *device, u8 port)
+ {
+@@ -1959,27 +1972,27 @@ static struct srp_host *srp_add_port(struct srp_device *device, u8 port)
+ INIT_LIST_HEAD(&host->target_list);
+ spin_lock_init(&host->target_lock);
+ init_completion(&host->released);
+- host->dev = device;
++ host->srp_dev = device;
+ host->port = port;
+
+- host->class_dev.class = &srp_class;
+- host->class_dev.dev = device->dev->dma_device;
+- snprintf(host->class_dev.class_id, BUS_ID_SIZE, "srp-%s-%d",
++ host->dev.class = &srp_class;
++ host->dev.parent = device->dev->dma_device;
++ snprintf(host->dev.bus_id, BUS_ID_SIZE, "srp-%s-%d",
+ device->dev->name, port);
+
+- if (class_device_register(&host->class_dev))
++ if (device_register(&host->dev))
+ goto free_host;
+- if (class_device_create_file(&host->class_dev, &class_device_attr_add_target))
++ if (device_create_file(&host->dev, &dev_attr_add_target))
+ goto err_class;
+- if (class_device_create_file(&host->class_dev, &class_device_attr_ibdev))
++ if (device_create_file(&host->dev, &dev_attr_ibdev))
+ goto err_class;
+- if (class_device_create_file(&host->class_dev, &class_device_attr_port))
++ if (device_create_file(&host->dev, &dev_attr_port))
+ goto err_class;
+
+ return host;
+
+ err_class:
+- class_device_unregister(&host->class_dev);
++ device_unregister(&host->dev);
+
+ free_host:
+ kfree(host);
+@@ -2084,7 +2097,7 @@ static void srp_remove_one(struct ib_device *device)
+ srp_dev = ib_get_client_data(device, &srp_client);
+
+ list_for_each_entry_safe(host, tmp_host, &srp_dev->dev_list, list) {
+- class_device_unregister(&host->class_dev);
++ device_unregister(&host->dev);
+ /*
+ * Wait for the sysfs entry to go away, so that no new
+ * target ports can be created.
+@@ -2138,6 +2151,11 @@ static int __init srp_init_module(void)
+ {
+ int ret;
+
++ if (srp_sg_tablesize > 255) {
++ printk(KERN_WARNING PFX "Clamping srp_sg_tablesize to 255\n");
++ srp_sg_tablesize = 255;
++ }
++
+ ib_srp_transport_template =
+ srp_attach_transport(&ib_srp_transport_functions);
+ if (!ib_srp_transport_template)
+diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
+index cb6eb81..63d2ae7 100644
+--- a/drivers/infiniband/ulp/srp/ib_srp.h
++++ b/drivers/infiniband/ulp/srp/ib_srp.h
+@@ -97,9 +97,9 @@ struct srp_device {
+ };
+
+ struct srp_host {
+- struct srp_device *dev;
++ struct srp_device *srp_dev;
+ u8 port;
+- struct class_device class_dev;
++ struct device dev;
+ struct list_head target_list;
+ spinlock_t target_lock;
+ struct completion released;
+diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
+index 9dea14d..5f9d860 100644
+--- a/drivers/input/Kconfig
++++ b/drivers/input/Kconfig
+@@ -149,6 +149,15 @@ config INPUT_APMPOWER
+ To compile this driver as a module, choose M here: the
+ module will be called apm-power.
+
++config XEN_KBDDEV_FRONTEND
++ tristate "Xen virtual keyboard and mouse support"
++ depends on XEN_FBDEV_FRONTEND
++ default y
++ help
++ This driver implements the front-end of the Xen virtual
++ keyboard and mouse device driver. It communicates with a back-end
++ in another domain.
++
+ comment "Input Device Drivers"
+
+ source "drivers/input/keyboard/Kconfig"
+diff --git a/drivers/input/Makefile b/drivers/input/Makefile
+index 2ae87b1..98c4f9a 100644
+--- a/drivers/input/Makefile
++++ b/drivers/input/Makefile
+@@ -23,3 +23,5 @@ obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/
+ obj-$(CONFIG_INPUT_MISC) += misc/
+
+ obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o
++
++obj-$(CONFIG_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o
+diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c
+index 490918a..0d3ce7a 100644
+--- a/drivers/input/input-polldev.c
++++ b/drivers/input/input-polldev.c
+@@ -73,7 +73,7 @@ static void input_polled_device_work(struct work_struct *work)
+
+ static int input_open_polled_device(struct input_dev *input)
+ {
+- struct input_polled_dev *dev = input->private;
++ struct input_polled_dev *dev = input_get_drvdata(input);
+ int error;
+
+ error = input_polldev_start_workqueue();
+@@ -91,7 +91,7 @@ static int input_open_polled_device(struct input_dev *input)
+
+ static void input_close_polled_device(struct input_dev *input)
+ {
+- struct input_polled_dev *dev = input->private;
++ struct input_polled_dev *dev = input_get_drvdata(input);
+
+ cancel_delayed_work_sync(&dev->work);
+ input_polldev_stop_workqueue();
+@@ -151,10 +151,10 @@ int input_register_polled_device(struct input_polled_dev *dev)
+ {
+ struct input_dev *input = dev->input;
+
++ input_set_drvdata(input, dev);
+ INIT_DELAYED_WORK(&dev->work, input_polled_device_work);
+ if (!dev->poll_interval)
+ dev->poll_interval = 500;
+- input->private = dev;
+ input->open = input_open_polled_device;
+ input->close = input_close_polled_device;
+
+diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
+index 7c662ee..be5c14a 100644
+--- a/drivers/input/joystick/Kconfig
++++ b/drivers/input/joystick/Kconfig
+@@ -193,6 +193,18 @@ config JOYSTICK_TWIDJOY
+ To compile this driver as a module, choose M here: the
+ module will be called twidjoy.
+
++config JOYSTICK_ZHENHUA
++ tristate "5-byte Zhenhua RC transmitter"
++ select SERIO
++ help
++ Say Y here if you have a Zhen Hua PPM-4CH transmitter which is
++ supplied with a ready to fly micro electric indoor helicopters
++ such as EasyCopter, Lama, MiniCopter, DragonFly or Jabo and want
++ to use it via serial cable as a joystick.
++
++ To compile this driver as a module, choose M here: the
++ module will be called zhenhua.
++
+ config JOYSTICK_DB9
+ tristate "Multisystem, Sega Genesis, Saturn joysticks and gamepads"
+ depends on PARPORT
+diff --git a/drivers/input/joystick/Makefile b/drivers/input/joystick/Makefile
+index e855abb..fdbf8c4 100644
+--- a/drivers/input/joystick/Makefile
++++ b/drivers/input/joystick/Makefile
+@@ -15,6 +15,7 @@ obj-$(CONFIG_JOYSTICK_GF2K) += gf2k.o
+ obj-$(CONFIG_JOYSTICK_GRIP) += grip.o
+ obj-$(CONFIG_JOYSTICK_GRIP_MP) += grip_mp.o
+ obj-$(CONFIG_JOYSTICK_GUILLEMOT) += guillemot.o
++obj-$(CONFIG_JOYSTICK_IFORCE) += iforce/
+ obj-$(CONFIG_JOYSTICK_INTERACT) += interact.o
+ obj-$(CONFIG_JOYSTICK_JOYDUMP) += joydump.o
+ obj-$(CONFIG_JOYSTICK_MAGELLAN) += magellan.o
+@@ -27,5 +28,5 @@ obj-$(CONFIG_JOYSTICK_TURBOGRAFX) += turbografx.o
+ obj-$(CONFIG_JOYSTICK_TWIDJOY) += twidjoy.o
+ obj-$(CONFIG_JOYSTICK_WARRIOR) += warrior.o
+ obj-$(CONFIG_JOYSTICK_XPAD) += xpad.o
++obj-$(CONFIG_JOYSTICK_ZHENHUA) += zhenhua.o
+
+-obj-$(CONFIG_JOYSTICK_IFORCE) += iforce/
+diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
+index 0380597..4b07bda 100644
+--- a/drivers/input/joystick/xpad.c
++++ b/drivers/input/joystick/xpad.c
+@@ -1,5 +1,5 @@
+ /*
+- * X-Box gamepad - v0.0.6
++ * X-Box gamepad driver
+ *
+ * Copyright (c) 2002 Marko Friedemann <mfr at bmx-chemnitz.de>
+ * 2004 Oliver Schwartz <Oliver.Schwartz at gmx.de>,
+@@ -68,6 +68,8 @@
+ * - dance pads will map D-PAD to buttons, not axes
+ * - pass the module paramater 'dpad_to_buttons' to force
+ * the D-PAD to map to buttons if your pad is not detected
++ *
++ * Later changes can be tracked in SCM.
+ */
+
+ #include <linux/kernel.h>
+@@ -77,7 +79,6 @@
+ #include <linux/module.h>
+ #include <linux/usb/input.h>
+
+-#define DRIVER_VERSION "v0.0.6"
+ #define DRIVER_AUTHOR "Marko Friedemann <mfr at bmx-chemnitz.de>"
+ #define DRIVER_DESC "X-Box pad driver"
+
+@@ -87,10 +88,12 @@
+ but we map them to axes when possible to simplify things */
+ #define MAP_DPAD_TO_BUTTONS 0
+ #define MAP_DPAD_TO_AXES 1
+-#define MAP_DPAD_UNKNOWN -1
++#define MAP_DPAD_UNKNOWN 2
+
+ #define XTYPE_XBOX 0
+ #define XTYPE_XBOX360 1
++#define XTYPE_XBOX360W 2
++#define XTYPE_UNKNOWN 3
+
+ static int dpad_to_buttons;
+ module_param(dpad_to_buttons, bool, S_IRUGO);
+@@ -107,8 +110,10 @@ static const struct xpad_device {
+ { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES, XTYPE_XBOX },
++ { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
+ { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+ { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
++ { 0x046d, 0xc242, "Logitech Chillstream Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
+ { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+@@ -135,18 +140,26 @@ static const struct xpad_device {
+ { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
++ { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
+ { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+ { 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
+ { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+- { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_XBOX }
++ { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_UNKNOWN }
+ };
+
+-static const signed short xpad_btn[] = {
+- BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, /* "analog" buttons */
++/* buttons shared with xbox and xbox360 */
++static const signed short xpad_common_btn[] = {
++ BTN_A, BTN_B, BTN_X, BTN_Y, /* "analog" buttons */
+ BTN_START, BTN_BACK, BTN_THUMBL, BTN_THUMBR, /* start/back/sticks */
+ -1 /* terminating entry */
+ };
+
++/* original xbox controllers only */
++static const signed short xpad_btn[] = {
++ BTN_C, BTN_Z, /* "analog" buttons */
++ -1 /* terminating entry */
++};
++
+ /* only used if MAP_DPAD_TO_BUTTONS */
+ static const signed short xpad_btn_pad[] = {
+ BTN_LEFT, BTN_RIGHT, /* d-pad left, right */
+@@ -173,12 +186,27 @@ static const signed short xpad_abs_pad[] = {
+ -1 /* terminating entry */
+ };
+
+-/* Xbox 360 has a vendor-specific (sub)class, so we cannot match it with only
+- * USB_INTERFACE_INFO, more to that this device has 4 InterfaceProtocols,
+- * but we need only one of them. */
++/* Xbox 360 has a vendor-specific class, so we cannot match it with only
++ * USB_INTERFACE_INFO (also specifically refused by USB subsystem), so we
++ * match against vendor id as well. Wired Xbox 360 devices have protocol 1,
++ * wireless controllers have protocol 129. */
++#define XPAD_XBOX360_VENDOR_PROTOCOL(vend,pr) \
++ .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \
++ .idVendor = (vend), \
++ .bInterfaceClass = USB_CLASS_VENDOR_SPEC, \
++ .bInterfaceSubClass = 93, \
++ .bInterfaceProtocol = (pr)
++#define XPAD_XBOX360_VENDOR(vend) \
++ { XPAD_XBOX360_VENDOR_PROTOCOL(vend,1) }, \
++ { XPAD_XBOX360_VENDOR_PROTOCOL(vend,129) }
++
+ static struct usb_device_id xpad_table [] = {
+ { USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */
+- { USB_DEVICE_INTERFACE_PROTOCOL(0x045e, 0x028e, 1) }, /* X-Box 360 controller */
++ XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */
++ XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */
++ XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */
++ XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */
++ XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */
+ { }
+ };
+
+@@ -188,10 +216,15 @@ struct usb_xpad {
+ struct input_dev *dev; /* input device interface */
+ struct usb_device *udev; /* usb device */
+
++ int pad_present;
++
+ struct urb *irq_in; /* urb for interrupt in report */
+ unsigned char *idata; /* input data */
+ dma_addr_t idata_dma;
+
++ struct urb *bulk_out;
++ unsigned char *bdata;
++
+ #if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS)
+ struct urb *irq_out; /* urb for interrupt out report */
+ unsigned char *odata; /* output data */
+@@ -227,13 +260,13 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
+ input_report_abs(dev, ABS_X,
+ (__s16) le16_to_cpup((__le16 *)(data + 12)));
+ input_report_abs(dev, ABS_Y,
+- (__s16) le16_to_cpup((__le16 *)(data + 14)));
++ ~(__s16) le16_to_cpup((__le16 *)(data + 14)));
+
+ /* right stick */
+ input_report_abs(dev, ABS_RX,
+ (__s16) le16_to_cpup((__le16 *)(data + 16)));
+ input_report_abs(dev, ABS_RY,
+- (__s16) le16_to_cpup((__le16 *)(data + 18)));
++ ~(__s16) le16_to_cpup((__le16 *)(data + 18)));
+
+ /* triggers left/right */
+ input_report_abs(dev, ABS_Z, data[10]);
+@@ -321,13 +354,13 @@ static void xpad360_process_packet(struct usb_xpad *xpad,
+ input_report_abs(dev, ABS_X,
+ (__s16) le16_to_cpup((__le16 *)(data + 6)));
+ input_report_abs(dev, ABS_Y,
+- (__s16) le16_to_cpup((__le16 *)(data + 8)));
++ ~(__s16) le16_to_cpup((__le16 *)(data + 8)));
+
+ /* right stick */
+ input_report_abs(dev, ABS_RX,
+ (__s16) le16_to_cpup((__le16 *)(data + 10)));
+ input_report_abs(dev, ABS_RY,
+- (__s16) le16_to_cpup((__le16 *)(data + 12)));
++ ~(__s16) le16_to_cpup((__le16 *)(data + 12)));
+
+ /* triggers left/right */
+ input_report_abs(dev, ABS_Z, data[4]);
+@@ -336,12 +369,47 @@ static void xpad360_process_packet(struct usb_xpad *xpad,
+ input_sync(dev);
+ }
+
++/*
++ * xpad360w_process_packet
++ *
++ * Completes a request by converting the data into events for the
++ * input subsystem. It is version for xbox 360 wireless controller.
++ *
++ * Byte.Bit
++ * 00.1 - Status change: The controller or headset has connected/disconnected
++ * Bits 01.7 and 01.6 are valid
++ * 01.7 - Controller present
++ * 01.6 - Headset present
++ * 01.1 - Pad state (Bytes 4+) valid
++ *
++ */
++
++static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data)
++{
++ /* Presence change */
++ if (data[0] & 0x08) {
++ if (data[1] & 0x80) {
++ xpad->pad_present = 1;
++ usb_submit_urb(xpad->bulk_out, GFP_ATOMIC);
++ } else
++ xpad->pad_present = 0;
++ }
++
++ /* Valid pad data */
++ if (!(data[1] & 0x1))
++ return;
++
++ xpad360_process_packet(xpad, cmd, &data[4]);
++}
++
+ static void xpad_irq_in(struct urb *urb)
+ {
+ struct usb_xpad *xpad = urb->context;
+- int retval;
++ int retval, status;
+
+- switch (urb->status) {
++ status = urb->status;
++
++ switch (status) {
+ case 0:
+ /* success */
+ break;
+@@ -350,18 +418,24 @@ static void xpad_irq_in(struct urb *urb)
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d",
+- __FUNCTION__, urb->status);
++ __FUNCTION__, status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d",
+- __FUNCTION__, urb->status);
++ __FUNCTION__, status);
+ goto exit;
+ }
+
+- if (xpad->xtype == XTYPE_XBOX360)
++ switch (xpad->xtype) {
++ case XTYPE_XBOX360:
+ xpad360_process_packet(xpad, 0, xpad->idata);
+- else
++ break;
++ case XTYPE_XBOX360W:
++ xpad360w_process_packet(xpad, 0, xpad->idata);
++ break;
++ default:
+ xpad_process_packet(xpad, 0, xpad->idata);
++ }
+
+ exit:
+ retval = usb_submit_urb (urb, GFP_ATOMIC);
+@@ -373,9 +447,11 @@ exit:
+ #if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS)
+ static void xpad_irq_out(struct urb *urb)
+ {
+- int retval;
++ int retval, status;
+
+- switch (urb->status) {
++ status = urb->status;
++
++ switch (status) {
+ case 0:
+ /* success */
+ break;
+@@ -384,11 +460,11 @@ static void xpad_irq_out(struct urb *urb)
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d",
+- __FUNCTION__, urb->status);
++ __FUNCTION__, status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d",
+- __FUNCTION__, urb->status);
++ __FUNCTION__, status);
+ goto exit;
+ }
+
+@@ -399,6 +475,23 @@ exit:
+ __FUNCTION__, retval);
+ }
+
++static void xpad_bulk_out(struct urb *urb)
++{
++ switch (urb->status) {
++ case 0:
++ /* success */
++ break;
++ case -ECONNRESET:
++ case -ENOENT:
++ case -ESHUTDOWN:
++ /* this urb is terminated, clean up */
++ dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
++ break;
++ default:
++ dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
++ }
++}
++
+ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
+ {
+ struct usb_endpoint_descriptor *ep_irq_out;
+@@ -408,7 +501,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
+ return 0;
+
+ xpad->odata = usb_buffer_alloc(xpad->udev, XPAD_PKT_LEN,
+- GFP_ATOMIC, &xpad->odata_dma );
++ GFP_KERNEL, &xpad->odata_dma);
+ if (!xpad->odata)
+ goto fail1;
+
+@@ -469,6 +562,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data,
+ xpad->odata[5] = 0x00;
+ xpad->odata[6] = 0x00;
+ xpad->odata[7] = 0x00;
++ xpad->irq_out->transfer_buffer_length = 8;
+ usb_submit_urb(xpad->irq_out, GFP_KERNEL);
+ }
+
+@@ -477,6 +571,9 @@ static int xpad_play_effect(struct input_dev *dev, void *data,
+
+ static int xpad_init_ff(struct usb_xpad *xpad)
+ {
++ if (xpad->xtype != XTYPE_XBOX360)
++ return 0;
++
+ input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
+
+ return input_ff_create_memless(xpad->dev, NULL, xpad_play_effect);
+@@ -502,6 +599,7 @@ static void xpad_send_led_command(struct usb_xpad *xpad, int command)
+ xpad->odata[0] = 0x01;
+ xpad->odata[1] = 0x03;
+ xpad->odata[2] = command;
++ xpad->irq_out->transfer_buffer_length = 3;
+ usb_submit_urb(xpad->irq_out, GFP_KERNEL);
+ mutex_unlock(&xpad->odata_mutex);
+ }
+@@ -574,6 +672,10 @@ static int xpad_open(struct input_dev *dev)
+ {
+ struct usb_xpad *xpad = input_get_drvdata(dev);
+
++ /* URB was submitted in probe */
++ if(xpad->xtype == XTYPE_XBOX360W)
++ return 0;
++
+ xpad->irq_in->dev = xpad->udev;
+ if (usb_submit_urb(xpad->irq_in, GFP_KERNEL))
+ return -EIO;
+@@ -585,7 +687,8 @@ static void xpad_close(struct input_dev *dev)
+ {
+ struct usb_xpad *xpad = input_get_drvdata(dev);
+
+- usb_kill_urb(xpad->irq_in);
++ if(xpad->xtype != XTYPE_XBOX360W)
++ usb_kill_urb(xpad->irq_in);
+ xpad_stop_output(xpad);
+ }
+
+@@ -632,7 +735,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
+ goto fail1;
+
+ xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN,
+- GFP_ATOMIC, &xpad->idata_dma);
++ GFP_KERNEL, &xpad->idata_dma);
+ if (!xpad->idata)
+ goto fail1;
+
+@@ -644,7 +747,16 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
+ xpad->dpad_mapping = xpad_device[i].dpad_mapping;
+ xpad->xtype = xpad_device[i].xtype;
+ if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN)
+- xpad->dpad_mapping = dpad_to_buttons;
++ xpad->dpad_mapping = !dpad_to_buttons;
++ if (xpad->xtype == XTYPE_UNKNOWN) {
++ if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) {
++ if (intf->cur_altsetting->desc.bInterfaceProtocol == 129)
++ xpad->xtype = XTYPE_XBOX360W;
++ else
++ xpad->xtype = XTYPE_XBOX360;
++ } else
++ xpad->xtype = XTYPE_XBOX;
++ }
+ xpad->dev = input_dev;
+ usb_make_path(udev, xpad->phys, sizeof(xpad->phys));
+ strlcat(xpad->phys, "/input0", sizeof(xpad->phys));
+@@ -662,11 +774,14 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+
+ /* set up buttons */
+- for (i = 0; xpad_btn[i] >= 0; i++)
+- set_bit(xpad_btn[i], input_dev->keybit);
+- if (xpad->xtype == XTYPE_XBOX360)
++ for (i = 0; xpad_common_btn[i] >= 0; i++)
++ set_bit(xpad_common_btn[i], input_dev->keybit);
++ if ((xpad->xtype == XTYPE_XBOX360) || (xpad->xtype == XTYPE_XBOX360W))
+ for (i = 0; xpad360_btn[i] >= 0; i++)
+ set_bit(xpad360_btn[i], input_dev->keybit);
++ else
++ for (i = 0; xpad_btn[i] >= 0; i++)
++ set_bit(xpad_btn[i], input_dev->keybit);
+ if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS)
+ for (i = 0; xpad_btn_pad[i] >= 0; i++)
+ set_bit(xpad_btn_pad[i], input_dev->keybit);
+@@ -703,8 +818,57 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
+ goto fail4;
+
+ usb_set_intfdata(intf, xpad);
++
++ /*
++ * Submit the int URB immediatly rather than waiting for open
++ * because we get status messages from the device whether
++ * or not any controllers are attached. In fact, it's
++ * exactly the message that a controller has arrived that
++ * we're waiting for.
++ */
++ if (xpad->xtype == XTYPE_XBOX360W) {
++ xpad->irq_in->dev = xpad->udev;
++ error = usb_submit_urb(xpad->irq_in, GFP_KERNEL);
++ if (error)
++ goto fail4;
++
++ /*
++ * Setup the message to set the LEDs on the
++ * controller when it shows up
++ */
++ xpad->bulk_out = usb_alloc_urb(0, GFP_KERNEL);
++ if(!xpad->bulk_out)
++ goto fail5;
++
++ xpad->bdata = kzalloc(XPAD_PKT_LEN, GFP_KERNEL);
++ if(!xpad->bdata)
++ goto fail6;
++
++ xpad->bdata[2] = 0x08;
++ switch (intf->cur_altsetting->desc.bInterfaceNumber) {
++ case 0:
++ xpad->bdata[3] = 0x42;
++ break;
++ case 2:
++ xpad->bdata[3] = 0x43;
++ break;
++ case 4:
++ xpad->bdata[3] = 0x44;
++ break;
++ case 6:
++ xpad->bdata[3] = 0x45;
++ }
++
++ ep_irq_in = &intf->cur_altsetting->endpoint[1].desc;
++ usb_fill_bulk_urb(xpad->bulk_out, udev,
++ usb_sndbulkpipe(udev, ep_irq_in->bEndpointAddress),
++ xpad->bdata, XPAD_PKT_LEN, xpad_bulk_out, xpad);
++ }
++
+ return 0;
+
++ fail6: usb_free_urb(xpad->bulk_out);
++ fail5: usb_kill_urb(xpad->irq_in);
+ fail4: usb_free_urb(xpad->irq_in);
+ fail3: xpad_deinit_output(xpad);
+ fail2: usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
+@@ -723,6 +887,11 @@ static void xpad_disconnect(struct usb_interface *intf)
+ xpad_led_disconnect(xpad);
+ input_unregister_device(xpad->dev);
+ xpad_deinit_output(xpad);
++ if (xpad->xtype == XTYPE_XBOX360W) {
++ usb_kill_urb(xpad->bulk_out);
++ usb_free_urb(xpad->bulk_out);
++ usb_kill_urb(xpad->irq_in);
++ }
+ usb_free_urb(xpad->irq_in);
+ usb_buffer_free(xpad->udev, XPAD_PKT_LEN,
+ xpad->idata, xpad->idata_dma);
+@@ -741,7 +910,7 @@ static int __init usb_xpad_init(void)
+ {
+ int result = usb_register(&xpad_driver);
+ if (result == 0)
+- info(DRIVER_DESC ":" DRIVER_VERSION);
++ info(DRIVER_DESC);
+ return result;
+ }
+
+diff --git a/drivers/input/joystick/zhenhua.c b/drivers/input/joystick/zhenhua.c
+new file mode 100644
+index 0000000..b585312
+--- /dev/null
++++ b/drivers/input/joystick/zhenhua.c
+@@ -0,0 +1,243 @@
++/*
++ * derived from "twidjoy.c"
++ *
++ * Copyright (c) 2008 Martin Kebert
++ * Copyright (c) 2001 Arndt Schoenewald
++ * Copyright (c) 2000-2001 Vojtech Pavlik
++ * Copyright (c) 2000 Mark Fletcher
++ *
++ */
++
++/*
++ * Driver to use 4CH RC transmitter using Zhen Hua 5-byte protocol (Walkera Lama,
++ * EasyCopter etc.) as a joystick under Linux.
++ *
++ * RC transmitters using Zhen Hua 5-byte protocol are cheap four channels
++ * transmitters for control a RC planes or RC helicopters with possibility to
++ * connect on a serial port.
++ * Data coming from transmitter is in this order:
++ * 1. byte = synchronisation byte
++ * 2. byte = X axis
++ * 3. byte = Y axis
++ * 4. byte = RZ axis
++ * 5. byte = Z axis
++ * (and this is repeated)
++ *
++ * For questions or feedback regarding this driver module please contact:
++ * Martin Kebert <gkmarty at gmail.com> - but I am not a C-programmer nor kernel
++ * coder :-(
++ */
++
++/*
++ * 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/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/input.h>
++#include <linux/serio.h>
++#include <linux/init.h>
++
++#define DRIVER_DESC "RC transmitter with 5-byte Zhen Hua protocol joystick driver"
++
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_LICENSE("GPL");
++
++/*
++ * Constants.
++ */
++
++#define ZHENHUA_MAX_LENGTH 5
++
++/*
++ * Zhen Hua data.
++ */
++
++struct zhenhua {
++ struct input_dev *dev;
++ int idx;
++ unsigned char data[ZHENHUA_MAX_LENGTH];
++ char phys[32];
++};
++
++
++/* bits in all incoming bytes needs to be "reversed" */
++static int zhenhua_bitreverse(int x)
++{
++ x = ((x & 0xaa) >> 1) | ((x & 0x55) << 1);
++ x = ((x & 0xcc) >> 2) | ((x & 0x33) << 2);
++ x = ((x & 0xf0) >> 4) | ((x & 0x0f) << 4);
++ return x;
++}
++
++/*
++ * zhenhua_process_packet() decodes packets the driver receives from the
++ * RC transmitter. It updates the data accordingly.
++ */
++
++static void zhenhua_process_packet(struct zhenhua *zhenhua)
++{
++ struct input_dev *dev = zhenhua->dev;
++ unsigned char *data = zhenhua->data;
++
++ input_report_abs(dev, ABS_Y, data[1]);
++ input_report_abs(dev, ABS_X, data[2]);
++ input_report_abs(dev, ABS_RZ, data[3]);
++ input_report_abs(dev, ABS_Z, data[4]);
++
++ input_sync(dev);
++}
++
++/*
++ * zhenhua_interrupt() is called by the low level driver when characters
++ * are ready for us. We then buffer them for further processing, or call the
++ * packet processing routine.
++ */
++
++static irqreturn_t zhenhua_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
++{
++ struct zhenhua *zhenhua = serio_get_drvdata(serio);
++
++ /* All Zhen Hua packets are 5 bytes. The fact that the first byte
++ * is allways 0xf7 and all others are in range 0x32 - 0xc8 (50-200)
++ * can be used to check and regain sync. */
++
++ if (data == 0xef)
++ zhenhua->idx = 0; /* this byte starts a new packet */
++ else if (zhenhua->idx == 0)
++ return IRQ_HANDLED; /* wrong MSB -- ignore this byte */
++
++ if (zhenhua->idx < ZHENHUA_MAX_LENGTH)
++ zhenhua->data[zhenhua->idx++] = zhenhua_bitreverse(data);
++
++ if (zhenhua->idx == ZHENHUA_MAX_LENGTH) {
++ zhenhua_process_packet(zhenhua);
++ zhenhua->idx = 0;
++ }
++
++ return IRQ_HANDLED;
++}
++
++/*
++ * zhenhua_disconnect() is the opposite of zhenhua_connect()
++ */
++
++static void zhenhua_disconnect(struct serio *serio)
++{
++ struct zhenhua *zhenhua = serio_get_drvdata(serio);
++
++ serio_close(serio);
++ serio_set_drvdata(serio, NULL);
++ input_unregister_device(zhenhua->dev);
++ kfree(zhenhua);
++}
++
++/*
++ * zhenhua_connect() is the routine that is called when someone adds a
++ * new serio device. It looks for the Twiddler, and if found, registers
++ * it as an input device.
++ */
++
++static int zhenhua_connect(struct serio *serio, struct serio_driver *drv)
++{
++ struct zhenhua *zhenhua;
++ struct input_dev *input_dev;
++ int err = -ENOMEM;
++
++ zhenhua = kzalloc(sizeof(struct zhenhua), GFP_KERNEL);
++ input_dev = input_allocate_device();
++ if (!zhenhua || !input_dev)
++ goto fail1;
++
++ zhenhua->dev = input_dev;
++ snprintf(zhenhua->phys, sizeof(zhenhua->phys), "%s/input0", serio->phys);
++
++ input_dev->name = "Zhen Hua 5-byte device";
++ input_dev->phys = zhenhua->phys;
++ input_dev->id.bustype = BUS_RS232;
++ input_dev->id.vendor = SERIO_ZHENHUA;
++ input_dev->id.product = 0x0001;
++ input_dev->id.version = 0x0100;
++ input_dev->dev.parent = &serio->dev;
++
++ input_dev->evbit[0] = BIT(EV_ABS);
++ input_set_abs_params(input_dev, ABS_X, 50, 200, 0, 0);
++ input_set_abs_params(input_dev, ABS_Y, 50, 200, 0, 0);
++ input_set_abs_params(input_dev, ABS_Z, 50, 200, 0, 0);
++ input_set_abs_params(input_dev, ABS_RZ, 50, 200, 0, 0);
++
++ serio_set_drvdata(serio, zhenhua);
++
++ err = serio_open(serio, drv);
++ if (err)
++ goto fail2;
++
++ err = input_register_device(zhenhua->dev);
++ if (err)
++ goto fail3;
++
++ return 0;
++
++ fail3: serio_close(serio);
++ fail2: serio_set_drvdata(serio, NULL);
++ fail1: input_free_device(input_dev);
++ kfree(zhenhua);
++ return err;
++}
++
++/*
++ * The serio driver structure.
++ */
++
++static struct serio_device_id zhenhua_serio_ids[] = {
++ {
++ .type = SERIO_RS232,
++ .proto = SERIO_ZHENHUA,
++ .id = SERIO_ANY,
++ .extra = SERIO_ANY,
++ },
++ { 0 }
++};
++
++MODULE_DEVICE_TABLE(serio, zhenhua_serio_ids);
++
++static struct serio_driver zhenhua_drv = {
++ .driver = {
++ .name = "zhenhua",
++ },
++ .description = DRIVER_DESC,
++ .id_table = zhenhua_serio_ids,
++ .interrupt = zhenhua_interrupt,
++ .connect = zhenhua_connect,
++ .disconnect = zhenhua_disconnect,
++};
++
++/*
++ * The functions for inserting/removing us as a module.
++ */
++
++static int __init zhenhua_init(void)
++{
++ return serio_register_driver(&zhenhua_drv);
++}
++
++static void __exit zhenhua_exit(void)
++{
++ serio_unregister_driver(&zhenhua_drv);
++}
++
++module_init(zhenhua_init);
++module_exit(zhenhua_exit);
+diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
+index 8ea709b..efd70a9 100644
+--- a/drivers/input/keyboard/Kconfig
++++ b/drivers/input/keyboard/Kconfig
+@@ -314,4 +314,13 @@ config KEYBOARD_BFIN
+ To compile this driver as a module, choose M here: the
+ module will be called bf54x-keys.
+
++config KEYBOARD_SH_KEYSC
++ tristate "SuperH KEYSC keypad support"
++ depends on SUPERH
++ help
++ Say Y here if you want to use a keypad attached to the KEYSC block
++ on SuperH processors such as sh7722 and sh7343.
++
++ To compile this driver as a module, choose M here: the
++ module will be called sh_keysc.
+ endif
+diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
+index e741f40..0edc8f2 100644
+--- a/drivers/input/keyboard/Makefile
++++ b/drivers/input/keyboard/Makefile
+@@ -26,3 +26,4 @@ obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o
+ obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o
+ obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o
+ obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o
++obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o
+diff --git a/drivers/input/keyboard/aaed2000_kbd.c b/drivers/input/keyboard/aaed2000_kbd.c
+index 72abc19..a293e8b 100644
+--- a/drivers/input/keyboard/aaed2000_kbd.c
++++ b/drivers/input/keyboard/aaed2000_kbd.c
+@@ -156,11 +156,15 @@ static int __devexit aaedkbd_remove(struct platform_device *pdev)
+ return 0;
+ }
+
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:aaed2000-keyboard");
++
+ static struct platform_driver aaedkbd_driver = {
+ .probe = aaedkbd_probe,
+ .remove = __devexit_p(aaedkbd_remove),
+ .driver = {
+ .name = "aaed2000-keyboard",
++ .owner = THIS_MODULE,
+ },
+ };
+
+diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c
+index 05e3494..54ed8e2 100644
+--- a/drivers/input/keyboard/bf54x-keys.c
++++ b/drivers/input/keyboard/bf54x-keys.c
+@@ -312,6 +312,8 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev)
+
+ bfin_write_KPAD_CTL(bfin_read_KPAD_CTL() | KPAD_EN);
+
++ device_init_wakeup(&pdev->dev, 1);
++
+ printk(KERN_ERR DRV_NAME
+ ": Blackfin BF54x Keypad registered IRQ %d\n", bf54x_kpad->irq);
+
+@@ -354,12 +356,40 @@ static int __devexit bfin_kpad_remove(struct platform_device *pdev)
+ return 0;
+ }
+
++#ifdef CONFIG_PM
++static int bfin_kpad_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
++
++ if (device_may_wakeup(&pdev->dev))
++ enable_irq_wake(bf54x_kpad->irq);
++
++ return 0;
++}
++
++static int bfin_kpad_resume(struct platform_device *pdev)
++{
++ struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
++
++ if (device_may_wakeup(&pdev->dev))
++ disable_irq_wake(bf54x_kpad->irq);
++
++ return 0;
++}
++#else
++# define bfin_kpad_suspend NULL
++# define bfin_kpad_resume NULL
++#endif
++
+ struct platform_driver bfin_kpad_device_driver = {
+- .probe = bfin_kpad_probe,
+- .remove = __devexit_p(bfin_kpad_remove),
+ .driver = {
+ .name = DRV_NAME,
+- }
++ .owner = THIS_MODULE,
++ },
++ .probe = bfin_kpad_probe,
++ .remove = __devexit_p(bfin_kpad_remove),
++ .suspend = bfin_kpad_suspend,
++ .resume = bfin_kpad_resume,
+ };
+
+ static int __init bfin_kpad_init(void)
+@@ -378,3 +408,4 @@ module_exit(bfin_kpad_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Michael Hennerich <hennerich at blackfin.uclinux.org>");
+ MODULE_DESCRIPTION("Keypad driver for BF54x Processors");
++MODULE_ALIAS("platform:bf54x-keys");
+diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
+index 790fed3..29fbec6 100644
+--- a/drivers/input/keyboard/corgikbd.c
++++ b/drivers/input/keyboard/corgikbd.c
+@@ -23,6 +23,7 @@
+ #include <asm/arch/corgi.h>
+ #include <asm/arch/hardware.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/hardware/scoop.h>
+
+ #define KB_ROWS 8
+@@ -392,6 +393,7 @@ static struct platform_driver corgikbd_driver = {
+ .resume = corgikbd_resume,
+ .driver = {
+ .name = "corgi-keyboard",
++ .owner = THIS_MODULE,
+ },
+ };
+
+@@ -411,3 +413,4 @@ module_exit(corgikbd_exit);
+ MODULE_AUTHOR("Richard Purdie <rpurdie at rpsys.net>");
+ MODULE_DESCRIPTION("Corgi Keyboard Driver");
+ MODULE_LICENSE("GPLv2");
++MODULE_ALIAS("platform:corgi-keyboard");
+diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
+index 6a9ca4b..bbd00c3 100644
+--- a/drivers/input/keyboard/gpio_keys.c
++++ b/drivers/input/keyboard/gpio_keys.c
+@@ -43,10 +43,11 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
+
+ input_event(input, type, button->code, !!state);
+ input_sync(input);
++ return IRQ_HANDLED;
+ }
+ }
+
+- return IRQ_HANDLED;
++ return IRQ_NONE;
+ }
+
+ static int __devinit gpio_keys_probe(struct platform_device *pdev)
+@@ -213,6 +214,7 @@ struct platform_driver gpio_keys_device_driver = {
+ .resume = gpio_keys_resume,
+ .driver = {
+ .name = "gpio-keys",
++ .owner = THIS_MODULE,
+ }
+ };
+
+@@ -232,3 +234,4 @@ module_exit(gpio_keys_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Phil Blundell <pb at handhelds.org>");
+ MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs");
++MODULE_ALIAS("platform:gpio-keys");
+diff --git a/drivers/input/keyboard/jornada680_kbd.c b/drivers/input/keyboard/jornada680_kbd.c
+index a23633a..9387da3 100644
+--- a/drivers/input/keyboard/jornada680_kbd.c
++++ b/drivers/input/keyboard/jornada680_kbd.c
+@@ -254,6 +254,7 @@ static int __devexit jornada680kbd_remove(struct platform_device *pdev)
+ static struct platform_driver jornada680kbd_driver = {
+ .driver = {
+ .name = "jornada680_kbd",
++ .owner = THIS_MODULE,
+ },
+ .probe = jornada680kbd_probe,
+ .remove = __devexit_p(jornada680kbd_remove),
+@@ -275,3 +276,4 @@ module_exit(jornada680kbd_exit);
+ MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson at gmail.com>");
+ MODULE_DESCRIPTION("HP Jornada 620/660/680/690 Keyboard Driver");
+ MODULE_LICENSE("GPLv2");
++MODULE_ALIAS("platform:jornada680_kbd");
+diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c
+index 986f93c..a1164a0 100644
+--- a/drivers/input/keyboard/jornada720_kbd.c
++++ b/drivers/input/keyboard/jornada720_kbd.c
+@@ -162,9 +162,13 @@ static int __devexit jornada720_kbd_remove(struct platform_device *pdev)
+ return 0;
+ }
+
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:jornada720_kbd");
++
+ static struct platform_driver jornada720_kbd_driver = {
+ .driver = {
+ .name = "jornada720_kbd",
++ .owner = THIS_MODULE,
+ },
+ .probe = jornada720_kbd_probe,
+ .remove = __devexit_p(jornada720_kbd_remove),
+diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c
+index 5a0ca18..9caed30 100644
+--- a/drivers/input/keyboard/locomokbd.c
++++ b/drivers/input/keyboard/locomokbd.c
+@@ -1,14 +1,12 @@
+ /*
+- * Copyright (c) 2005 John Lenz
++ * LoCoMo keyboard driver for Linux-based ARM PDAs:
++ * - SHARP Zaurus Collie (SL-5500)
++ * - SHARP Zaurus Poodle (SL-5600)
+ *
++ * Copyright (c) 2005 John Lenz
+ * Based on from xtkbd.c
+- */
+-
+-/*
+- * LoCoMo keyboard driver for Linux/ARM
+- */
+-
+-/*
++ *
++ *
+ * 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
+@@ -47,7 +45,8 @@ MODULE_LICENSE("GPL");
+ #define KEY_CONTACT KEY_F18
+ #define KEY_CENTER KEY_F15
+
+-static unsigned char locomokbd_keycode[LOCOMOKBD_NUMKEYS] = {
++static const unsigned char
++locomokbd_keycode[LOCOMOKBD_NUMKEYS] __devinitconst = {
+ 0, KEY_ESC, KEY_ACTIVITY, 0, 0, 0, 0, 0, 0, 0, /* 0 - 9 */
+ 0, 0, 0, 0, 0, 0, 0, KEY_MENU, KEY_HOME, KEY_CONTACT, /* 10 - 19 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 29 */
+@@ -67,22 +66,21 @@ static unsigned char locomokbd_keycode[LOCOMOKBD_NUMKEYS] = {
+ #define KB_COLS 8
+ #define KB_ROWMASK(r) (1 << (r))
+ #define SCANCODE(c,r) ( ((c)<<4) + (r) + 1 )
+-#define NR_SCANCODES 128
+
+ #define KB_DELAY 8
+ #define SCAN_INTERVAL (HZ/10)
+-#define LOCOMOKBD_PRESSED 1
+
+ struct locomokbd {
+ unsigned char keycode[LOCOMOKBD_NUMKEYS];
+ struct input_dev *input;
+ char phys[32];
+
+- struct locomo_dev *ldev;
+ unsigned long base;
+ spinlock_t lock;
+
+ struct timer_list timer;
++ unsigned long suspend_jiffies;
++ unsigned int count_cancel;
+ };
+
+ /* helper functions for reading the keyboard matrix */
+@@ -128,7 +126,7 @@ static inline void locomokbd_reset_col(unsigned long membase, int col)
+ /* Scan the hardware keyboard and push any changes up through the input layer */
+ static void locomokbd_scankeyboard(struct locomokbd *locomokbd)
+ {
+- unsigned int row, col, rowd, scancode;
++ unsigned int row, col, rowd;
+ unsigned long flags;
+ unsigned int num_pressed;
+ unsigned long membase = locomokbd->base;
+@@ -145,13 +143,33 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd)
+
+ rowd = ~locomo_readl(membase + LOCOMO_KIB);
+ for (row = 0; row < KB_ROWS; row++) {
++ unsigned int scancode, pressed, key;
++
+ scancode = SCANCODE(col, row);
+- if (rowd & KB_ROWMASK(row)) {
+- num_pressed += 1;
+- input_report_key(locomokbd->input, locomokbd->keycode[scancode], 1);
+- } else {
+- input_report_key(locomokbd->input, locomokbd->keycode[scancode], 0);
+- }
++ pressed = rowd & KB_ROWMASK(row);
++ key = locomokbd->keycode[scancode];
++
++ input_report_key(locomokbd->input, key, pressed);
++ if (likely(!pressed))
++ continue;
++
++ num_pressed++;
++
++ /* The "Cancel/ESC" key is labeled "On/Off" on
++ * Collie and Poodle and should suspend the device
++ * if it was pressed for more than a second. */
++ if (unlikely(key == KEY_ESC)) {
++ if (!time_after(jiffies,
++ locomokbd->suspend_jiffies + HZ))
++ continue;
++ if (locomokbd->count_cancel++
++ != (HZ/SCAN_INTERVAL + 1))
++ continue;
++ input_event(locomokbd->input, EV_PWR,
++ KEY_SUSPEND, 1);
++ locomokbd->suspend_jiffies = jiffies;
++ } else
++ locomokbd->count_cancel = 0;
+ }
+ locomokbd_reset_col(membase, col);
+ }
+@@ -162,6 +180,8 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd)
+ /* if any keys are pressed, enable the timer */
+ if (num_pressed)
+ mod_timer(&locomokbd->timer, jiffies + SCAN_INTERVAL);
++ else
++ locomokbd->count_cancel = 0;
+
+ spin_unlock_irqrestore(&locomokbd->lock, flags);
+ }
+@@ -186,10 +206,11 @@ static irqreturn_t locomokbd_interrupt(int irq, void *dev_id)
+ static void locomokbd_timer_callback(unsigned long data)
+ {
+ struct locomokbd *locomokbd = (struct locomokbd *) data;
++
+ locomokbd_scankeyboard(locomokbd);
+ }
+
+-static int locomokbd_probe(struct locomo_dev *dev)
++static int __devinit locomokbd_probe(struct locomo_dev *dev)
+ {
+ struct locomokbd *locomokbd;
+ struct input_dev *input_dev;
+@@ -211,7 +232,6 @@ static int locomokbd_probe(struct locomo_dev *dev)
+ goto err_free_mem;
+ }
+
+- locomokbd->ldev = dev;
+ locomo_set_drvdata(dev, locomokbd);
+
+ locomokbd->base = (unsigned long) dev->mapbase;
+@@ -222,6 +242,8 @@ static int locomokbd_probe(struct locomo_dev *dev)
+ locomokbd->timer.function = locomokbd_timer_callback;
+ locomokbd->timer.data = (unsigned long) locomokbd;
+
++ locomokbd->suspend_jiffies = jiffies;
++
+ locomokbd->input = input_dev;
+ strcpy(locomokbd->phys, "locomokbd/input0");
+
+@@ -233,9 +255,10 @@ static int locomokbd_probe(struct locomo_dev *dev)
+ input_dev->id.version = 0x0100;
+ input_dev->dev.parent = &dev->dev;
+
+- input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
++ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |
++ BIT_MASK(EV_PWR);
+ input_dev->keycode = locomokbd->keycode;
+- input_dev->keycodesize = sizeof(unsigned char);
++ input_dev->keycodesize = sizeof(locomokbd_keycode[0]);
+ input_dev->keycodemax = ARRAY_SIZE(locomokbd_keycode);
+
+ memcpy(locomokbd->keycode, locomokbd_keycode, sizeof(locomokbd->keycode));
+@@ -268,7 +291,7 @@ static int locomokbd_probe(struct locomo_dev *dev)
+ return err;
+ }
+
+-static int locomokbd_remove(struct locomo_dev *dev)
++static int __devexit locomokbd_remove(struct locomo_dev *dev)
+ {
+ struct locomokbd *locomokbd = locomo_get_drvdata(dev);
+
+@@ -292,7 +315,7 @@ static struct locomo_driver keyboard_driver = {
+ },
+ .devid = LOCOMO_DEVID_KEYBOARD,
+ .probe = locomokbd_probe,
+- .remove = locomokbd_remove,
++ .remove = __devexit_p(locomokbd_remove),
+ };
+
+ static int __init locomokbd_init(void)
+diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c
+index babc913..10afd20 100644
+--- a/drivers/input/keyboard/omap-keypad.c
++++ b/drivers/input/keyboard/omap-keypad.c
+@@ -352,6 +352,9 @@ static int __init omap_kp_probe(struct platform_device *pdev)
+ }
+ omap_set_gpio_direction(row_gpios[row_idx], 1);
+ }
++ } else {
++ col_idx = 0;
++ row_idx = 0;
+ }
+
+ setup_timer(&omap_kp->timer, omap_kp_timer, (unsigned long)omap_kp);
+@@ -415,10 +418,10 @@ err4:
+ err3:
+ device_remove_file(&pdev->dev, &dev_attr_enable);
+ err2:
+- for (i = row_idx-1; i >=0; i--)
++ for (i = row_idx - 1; i >=0; i--)
+ omap_free_gpio(row_gpios[i]);
+ err1:
+- for (i = col_idx-1; i >=0; i--)
++ for (i = col_idx - 1; i >=0; i--)
+ omap_free_gpio(col_gpios[i]);
+
+ kfree(omap_kp);
+@@ -464,6 +467,7 @@ static struct platform_driver omap_kp_driver = {
+ .resume = omap_kp_resume,
+ .driver = {
+ .name = "omap-keypad",
++ .owner = THIS_MODULE,
+ },
+ };
+
+@@ -484,3 +488,4 @@ module_exit(omap_kp_exit);
+ MODULE_AUTHOR("Timo Teräs");
+ MODULE_DESCRIPTION("OMAP Keypad Driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:omap-keypad");
+diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
+index 4e651c1..3dea0c5 100644
+--- a/drivers/input/keyboard/pxa27x_keypad.c
++++ b/drivers/input/keyboard/pxa27x_keypad.c
+@@ -545,6 +545,9 @@ static int __devexit pxa27x_keypad_remove(struct platform_device *pdev)
+ return 0;
+ }
+
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:pxa27x-keypad");
++
+ static struct platform_driver pxa27x_keypad_driver = {
+ .probe = pxa27x_keypad_probe,
+ .remove = __devexit_p(pxa27x_keypad_remove),
+@@ -552,6 +555,7 @@ static struct platform_driver pxa27x_keypad_driver = {
+ .resume = pxa27x_keypad_resume,
+ .driver = {
+ .name = "pxa27x-keypad",
++ .owner = THIS_MODULE,
+ },
+ };
+
+diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c
+new file mode 100644
+index 0000000..8486abc
+--- /dev/null
++++ b/drivers/input/keyboard/sh_keysc.c
+@@ -0,0 +1,280 @@
++/*
++ * SuperH KEYSC Keypad Driver
++ *
++ * Copyright (C) 2008 Magnus Damm
++ *
++ * Based on gpio_keys.c, Copyright 2005 Phil Blundell
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <linux/input.h>
++#include <linux/io.h>
++#include <asm/sh_keysc.h>
++
++#define KYCR1_OFFS 0x00
++#define KYCR2_OFFS 0x04
++#define KYINDR_OFFS 0x08
++#define KYOUTDR_OFFS 0x0c
++
++#define KYCR2_IRQ_LEVEL 0x10
++#define KYCR2_IRQ_DISABLED 0x00
++
++static const struct {
++ unsigned char kymd, keyout, keyin;
++} sh_keysc_mode[] = {
++ [SH_KEYSC_MODE_1] = { 0, 6, 5 },
++ [SH_KEYSC_MODE_2] = { 1, 5, 6 },
++ [SH_KEYSC_MODE_3] = { 2, 4, 7 },
++};
++
++struct sh_keysc_priv {
++ void __iomem *iomem_base;
++ unsigned long last_keys;
++ struct input_dev *input;
++ struct sh_keysc_info pdata;
++};
++
++static irqreturn_t sh_keysc_isr(int irq, void *dev_id)
++{
++ struct platform_device *pdev = dev_id;
++ struct sh_keysc_priv *priv = platform_get_drvdata(pdev);
++ struct sh_keysc_info *pdata = &priv->pdata;
++ unsigned long keys, keys1, keys0, mask;
++ unsigned char keyin_set, tmp;
++ int i, k;
++
++ dev_dbg(&pdev->dev, "isr!\n");
++
++ keys1 = ~0;
++ keys0 = 0;
++
++ do {
++ keys = 0;
++ keyin_set = 0;
++
++ iowrite16(KYCR2_IRQ_DISABLED, priv->iomem_base + KYCR2_OFFS);
++
++ for (i = 0; i < sh_keysc_mode[pdata->mode].keyout; i++) {
++ iowrite16(0xfff ^ (3 << (i * 2)),
++ priv->iomem_base + KYOUTDR_OFFS);
++ udelay(pdata->delay);
++ tmp = ioread16(priv->iomem_base + KYINDR_OFFS);
++ keys |= tmp << (sh_keysc_mode[pdata->mode].keyin * i);
++ tmp ^= (1 << sh_keysc_mode[pdata->mode].keyin) - 1;
++ keyin_set |= tmp;
++ }
++
++ iowrite16(0, priv->iomem_base + KYOUTDR_OFFS);
++ iowrite16(KYCR2_IRQ_LEVEL | (keyin_set << 8),
++ priv->iomem_base + KYCR2_OFFS);
++
++ keys ^= ~0;
++ keys &= (1 << (sh_keysc_mode[pdata->mode].keyin *
++ sh_keysc_mode[pdata->mode].keyout)) - 1;
++ keys1 &= keys;
++ keys0 |= keys;
++
++ dev_dbg(&pdev->dev, "keys 0x%08lx\n", keys);
++
++ } while (ioread16(priv->iomem_base + KYCR2_OFFS) & 0x01);
++
++ dev_dbg(&pdev->dev, "last_keys 0x%08lx keys0 0x%08lx keys1 0x%08lx\n",
++ priv->last_keys, keys0, keys1);
++
++ for (i = 0; i < SH_KEYSC_MAXKEYS; i++) {
++ k = pdata->keycodes[i];
++ if (!k)
++ continue;
++
++ mask = 1 << i;
++
++ if (!((priv->last_keys ^ keys0) & mask))
++ continue;
++
++ if ((keys1 | keys0) & mask) {
++ input_event(priv->input, EV_KEY, k, 1);
++ priv->last_keys |= mask;
++ }
++
++ if (!(keys1 & mask)) {
++ input_event(priv->input, EV_KEY, k, 0);
++ priv->last_keys &= ~mask;
++ }
++
++ }
++ input_sync(priv->input);
++
++ return IRQ_HANDLED;
++}
++
++#define res_size(res) ((res)->end - (res)->start + 1)
++
++static int __devinit sh_keysc_probe(struct platform_device *pdev)
++{
++ struct sh_keysc_priv *priv;
++ struct sh_keysc_info *pdata;
++ struct resource *res;
++ struct input_dev *input;
++ int i, k;
++ int irq, error;
++
++ if (!pdev->dev.platform_data) {
++ dev_err(&pdev->dev, "no platform data defined\n");
++ error = -EINVAL;
++ goto err0;
++ }
++
++ error = -ENXIO;
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (res == NULL) {
++ dev_err(&pdev->dev, "failed to get I/O memory\n");
++ goto err0;
++ }
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0) {
++ dev_err(&pdev->dev, "failed to get irq\n");
++ goto err0;
++ }
++
++ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
++ if (priv == NULL) {
++ dev_err(&pdev->dev, "failed to allocate driver data\n");
++ error = -ENOMEM;
++ goto err0;
++ }
++
++ platform_set_drvdata(pdev, priv);
++ memcpy(&priv->pdata, pdev->dev.platform_data, sizeof(priv->pdata));
++ pdata = &priv->pdata;
++
++ res = request_mem_region(res->start, res_size(res), pdev->name);
++ if (res == NULL) {
++ dev_err(&pdev->dev, "failed to request I/O memory\n");
++ error = -EBUSY;
++ goto err1;
++ }
++
++ priv->iomem_base = ioremap_nocache(res->start, res_size(res));
++ if (priv->iomem_base == NULL) {
++ dev_err(&pdev->dev, "failed to remap I/O memory\n");
++ error = -ENXIO;
++ goto err2;
++ }
++
++ priv->input = input_allocate_device();
++ if (!priv->input) {
++ dev_err(&pdev->dev, "failed to allocate input device\n");
++ error = -ENOMEM;
++ goto err3;
++ }
++
++ input = priv->input;
++ input->evbit[0] = BIT_MASK(EV_KEY);
++
++ input->name = pdev->name;
++ input->phys = "sh-keysc-keys/input0";
++ input->dev.parent = &pdev->dev;
++
++ input->id.bustype = BUS_HOST;
++ input->id.vendor = 0x0001;
++ input->id.product = 0x0001;
++ input->id.version = 0x0100;
++
++ error = request_irq(irq, sh_keysc_isr, 0, pdev->name, pdev);
++ if (error) {
++ dev_err(&pdev->dev, "failed to request IRQ\n");
++ goto err4;
++ }
++
++ for (i = 0; i < SH_KEYSC_MAXKEYS; i++) {
++ k = pdata->keycodes[i];
++ if (k)
++ input_set_capability(input, EV_KEY, k);
++ }
++
++ error = input_register_device(input);
++ if (error) {
++ dev_err(&pdev->dev, "failed to register input device\n");
++ goto err5;
++ }
++
++ iowrite16((sh_keysc_mode[pdata->mode].kymd << 8) |
++ pdata->scan_timing, priv->iomem_base + KYCR1_OFFS);
++ iowrite16(0, priv->iomem_base + KYOUTDR_OFFS);
++ iowrite16(KYCR2_IRQ_LEVEL, priv->iomem_base + KYCR2_OFFS);
++ return 0;
++ err5:
++ free_irq(irq, pdev);
++ err4:
++ input_free_device(input);
++ err3:
++ iounmap(priv->iomem_base);
++ err2:
++ release_mem_region(res->start, res_size(res));
++ err1:
++ platform_set_drvdata(pdev, NULL);
++ kfree(priv);
++ err0:
++ return error;
++}
++
++static int __devexit sh_keysc_remove(struct platform_device *pdev)
++{
++ struct sh_keysc_priv *priv = platform_get_drvdata(pdev);
++ struct resource *res;
++
++ iowrite16(KYCR2_IRQ_DISABLED, priv->iomem_base + KYCR2_OFFS);
++
++ input_unregister_device(priv->input);
++ free_irq(platform_get_irq(pdev, 0), pdev);
++ iounmap(priv->iomem_base);
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ release_mem_region(res->start, res_size(res));
++
++ platform_set_drvdata(pdev, NULL);
++ kfree(priv);
++ return 0;
++}
++
++
++#define sh_keysc_suspend NULL
++#define sh_keysc_resume NULL
++
++struct platform_driver sh_keysc_device_driver = {
++ .probe = sh_keysc_probe,
++ .remove = __devexit_p(sh_keysc_remove),
++ .suspend = sh_keysc_suspend,
++ .resume = sh_keysc_resume,
++ .driver = {
++ .name = "sh_keysc",
++ }
++};
++
++static int __init sh_keysc_init(void)
++{
++ return platform_driver_register(&sh_keysc_device_driver);
++}
++
++static void __exit sh_keysc_exit(void)
++{
++ platform_driver_unregister(&sh_keysc_device_driver);
++}
++
++module_init(sh_keysc_init);
++module_exit(sh_keysc_exit);
++
++MODULE_AUTHOR("Magnus Damm");
++MODULE_DESCRIPTION("SuperH KEYSC Keypad Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
+index 1d59a2d..61e401b 100644
+--- a/drivers/input/keyboard/spitzkbd.c
++++ b/drivers/input/keyboard/spitzkbd.c
+@@ -23,6 +23,7 @@
+ #include <asm/arch/spitz.h>
+ #include <asm/arch/hardware.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+
+ #define KB_ROWS 7
+ #define KB_COLS 11
+@@ -494,3 +495,4 @@ module_exit(spitzkbd_exit);
+ MODULE_AUTHOR("Richard Purdie <rpurdie at rpsys.net>");
+ MODULE_DESCRIPTION("Spitz Keyboard Driver");
+ MODULE_LICENSE("GPLv2");
++MODULE_ALIAS("platform:spitz-keyboard");
+diff --git a/drivers/input/keyboard/tosakbd.c b/drivers/input/keyboard/tosakbd.c
+index 3884d1e..94e444b 100644
+--- a/drivers/input/keyboard/tosakbd.c
++++ b/drivers/input/keyboard/tosakbd.c
+@@ -52,7 +52,7 @@ KEY_X, KEY_F, KEY_SPACE, KEY_APOSTROPHE, TOSA_KEY_MAIL, KEY_LEFT, KEY_DOWN, KEY_
+ struct tosakbd {
+ unsigned int keycode[ARRAY_SIZE(tosakbd_keycode)];
+ struct input_dev *input;
+-
++ int suspended;
+ spinlock_t lock; /* protect kbd scanning */
+ struct timer_list timer;
+ };
+@@ -133,6 +133,9 @@ static void tosakbd_scankeyboard(struct platform_device *dev)
+
+ spin_lock_irqsave(&tosakbd->lock, flags);
+
++ if (tosakbd->suspended)
++ goto out;
++
+ for (col = 0; col < TOSA_KEY_STROBE_NUM; col++) {
+ /*
+ * Discharge the output driver capacitatance
+@@ -174,6 +177,7 @@ static void tosakbd_scankeyboard(struct platform_device *dev)
+ if (num_pressed)
+ mod_timer(&tosakbd->timer, jiffies + SCAN_INTERVAL);
+
++ out:
+ spin_unlock_irqrestore(&tosakbd->lock, flags);
+ }
+
+@@ -200,6 +204,7 @@ static irqreturn_t tosakbd_interrupt(int irq, void *__dev)
+ static void tosakbd_timer_callback(unsigned long __dev)
+ {
+ struct platform_device *dev = (struct platform_device *)__dev;
++
+ tosakbd_scankeyboard(dev);
+ }
+
+@@ -207,6 +212,13 @@ static void tosakbd_timer_callback(unsigned long __dev)
+ static int tosakbd_suspend(struct platform_device *dev, pm_message_t state)
+ {
+ struct tosakbd *tosakbd = platform_get_drvdata(dev);
++ unsigned long flags;
++
++ spin_lock_irqsave(&tosakbd->lock, flags);
++ PGSR1 = (PGSR1 & ~TOSA_GPIO_LOW_STROBE_BIT);
++ PGSR2 = (PGSR2 & ~TOSA_GPIO_HIGH_STROBE_BIT);
++ tosakbd->suspended = 1;
++ spin_unlock_irqrestore(&tosakbd->lock, flags);
+
+ del_timer_sync(&tosakbd->timer);
+
+@@ -215,6 +227,9 @@ static int tosakbd_suspend(struct platform_device *dev, pm_message_t state)
+
+ static int tosakbd_resume(struct platform_device *dev)
+ {
++ struct tosakbd *tosakbd = platform_get_drvdata(dev);
++
++ tosakbd->suspended = 0;
+ tosakbd_scankeyboard(dev);
+
+ return 0;
+@@ -365,8 +380,8 @@ fail:
+ return error;
+ }
+
+-static int __devexit tosakbd_remove(struct platform_device *dev) {
+-
++static int __devexit tosakbd_remove(struct platform_device *dev)
++{
+ int i;
+ struct tosakbd *tosakbd = platform_get_drvdata(dev);
+
+@@ -394,6 +409,7 @@ static struct platform_driver tosakbd_driver = {
+ .resume = tosakbd_resume,
+ .driver = {
+ .name = "tosa-keyboard",
++ .owner = THIS_MODULE,
+ },
+ };
+
+@@ -413,3 +429,4 @@ module_exit(tosakbd_exit);
+ MODULE_AUTHOR("Dirk Opfer <Dirk at Opfer-Online.de>");
+ MODULE_DESCRIPTION("Tosa Keyboard Driver");
+ MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:tosa-keyboard");
+diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
+index c5263d6..92b6834 100644
+--- a/drivers/input/misc/Kconfig
++++ b/drivers/input/misc/Kconfig
+@@ -15,6 +15,7 @@ if INPUT_MISC
+ config INPUT_PCSPKR
+ tristate "PC Speaker support"
+ depends on ALPHA || X86 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES
++ depends on SND_PCSP=n
+ help
+ Say Y here if you want the standard PC Speaker to be used for
+ bells and whistles.
+diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c
+index 5511ef0..6a1f48b 100644
+--- a/drivers/input/misc/cobalt_btns.c
++++ b/drivers/input/misc/cobalt_btns.c
+@@ -148,6 +148,9 @@ static int __devexit cobalt_buttons_remove(struct platform_device *pdev)
+ return 0;
+ }
+
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:Cobalt buttons");
++
+ static struct platform_driver cobalt_buttons_driver = {
+ .probe = cobalt_buttons_probe,
+ .remove = __devexit_p(cobalt_buttons_remove),
+diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c
+index 0936d6b..3392901 100644
+--- a/drivers/input/mouse/gpio_mouse.c
++++ b/drivers/input/mouse/gpio_mouse.c
+@@ -171,10 +171,14 @@ static int __devexit gpio_mouse_remove(struct platform_device *pdev)
+ return 0;
+ }
+
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:gpio_mouse");
++
+ struct platform_driver gpio_mouse_device_driver = {
+ .remove = __devexit_p(gpio_mouse_remove),
+ .driver = {
+ .name = "gpio_mouse",
++ .owner = THIS_MODULE,
+ }
+ };
+
+diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
+index b88569e..ec4b661 100644
+--- a/drivers/input/serio/Kconfig
++++ b/drivers/input/serio/Kconfig
+@@ -88,6 +88,16 @@ config SERIO_RPCKBD
+ To compile this driver as a module, choose M here: the
+ module will be called rpckbd.
+
++config SERIO_AT32PSIF
++ tristate "AVR32 PSIF PS/2 keyboard and mouse controller"
++ depends on AVR32
++ help
++ Say Y here if you want to use the PSIF peripheral on AVR32 devices
++ and connect a PS/2 keyboard and/or mouse to it.
++
++ To compile this driver as a module, choose M here: the module will
++ be called at32psif.
++
+ config SERIO_AMBAKMI
+ tristate "AMBA KMI keyboard controller"
+ depends on ARM_AMBA
+diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
+index 4155197..38b8868 100644
+--- a/drivers/input/serio/Makefile
++++ b/drivers/input/serio/Makefile
+@@ -12,6 +12,7 @@ obj-$(CONFIG_SERIO_CT82C710) += ct82c710.o
+ obj-$(CONFIG_SERIO_RPCKBD) += rpckbd.o
+ obj-$(CONFIG_SERIO_SA1111) += sa1111ps2.o
+ obj-$(CONFIG_SERIO_AMBAKMI) += ambakmi.o
++obj-$(CONFIG_SERIO_AT32PSIF) += at32psif.o
+ obj-$(CONFIG_SERIO_Q40KBD) += q40kbd.o
+ obj-$(CONFIG_SERIO_GSCPS2) += gscps2.o
+ obj-$(CONFIG_HP_SDC) += hp_sdc.o
+diff --git a/drivers/input/serio/at32psif.c b/drivers/input/serio/at32psif.c
+new file mode 100644
+index 0000000..41fda8c
+--- /dev/null
++++ b/drivers/input/serio/at32psif.c
+@@ -0,0 +1,375 @@
++/*
++ * Copyright (C) 2007 Atmel Corporation
++ *
++ * Driver for the AT32AP700X PS/2 controller (PSIF).
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ */
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/device.h>
++#include <linux/init.h>
++#include <linux/serio.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/clk.h>
++#include <linux/platform_device.h>
++
++/* PSIF register offsets */
++#define PSIF_CR 0x00
++#define PSIF_RHR 0x04
++#define PSIF_THR 0x08
++#define PSIF_SR 0x10
++#define PSIF_IER 0x14
++#define PSIF_IDR 0x18
++#define PSIF_IMR 0x1c
++#define PSIF_PSR 0x24
++
++/* Bitfields in control register. */
++#define PSIF_CR_RXDIS_OFFSET 1
++#define PSIF_CR_RXDIS_SIZE 1
++#define PSIF_CR_RXEN_OFFSET 0
++#define PSIF_CR_RXEN_SIZE 1
++#define PSIF_CR_SWRST_OFFSET 15
++#define PSIF_CR_SWRST_SIZE 1
++#define PSIF_CR_TXDIS_OFFSET 9
++#define PSIF_CR_TXDIS_SIZE 1
++#define PSIF_CR_TXEN_OFFSET 8
++#define PSIF_CR_TXEN_SIZE 1
++
++/* Bitfields in interrupt disable, enable, mask and status register. */
++#define PSIF_NACK_OFFSET 8
++#define PSIF_NACK_SIZE 1
++#define PSIF_OVRUN_OFFSET 5
++#define PSIF_OVRUN_SIZE 1
++#define PSIF_PARITY_OFFSET 9
++#define PSIF_PARITY_SIZE 1
++#define PSIF_RXRDY_OFFSET 4
++#define PSIF_RXRDY_SIZE 1
++#define PSIF_TXEMPTY_OFFSET 1
++#define PSIF_TXEMPTY_SIZE 1
++#define PSIF_TXRDY_OFFSET 0
++#define PSIF_TXRDY_SIZE 1
++
++/* Bitfields in prescale register. */
++#define PSIF_PSR_PRSCV_OFFSET 0
++#define PSIF_PSR_PRSCV_SIZE 12
++
++/* Bitfields in receive hold register. */
++#define PSIF_RHR_RXDATA_OFFSET 0
++#define PSIF_RHR_RXDATA_SIZE 8
++
++/* Bitfields in transmit hold register. */
++#define PSIF_THR_TXDATA_OFFSET 0
++#define PSIF_THR_TXDATA_SIZE 8
++
++/* Bit manipulation macros */
++#define PSIF_BIT(name) \
++ (1 << PSIF_##name##_OFFSET)
++
++#define PSIF_BF(name, value) \
++ (((value) & ((1 << PSIF_##name##_SIZE) - 1)) \
++ << PSIF_##name##_OFFSET)
++
++#define PSIF_BFEXT(name, value) \
++ (((value) >> PSIF_##name##_OFFSET) \
++ & ((1 << PSIF_##name##_SIZE) - 1))
++
++#define PSIF_BFINS(name, value, old) \
++ (((old) & ~(((1 << PSIF_##name##_SIZE) - 1) \
++ << PSIF_##name##_OFFSET)) \
++ | PSIF_BF(name, value))
++
++/* Register access macros */
++#define psif_readl(port, reg) \
++ __raw_readl((port)->regs + PSIF_##reg)
++
++#define psif_writel(port, reg, value) \
++ __raw_writel((value), (port)->regs + PSIF_##reg)
++
++struct psif {
++ struct platform_device *pdev;
++ struct clk *pclk;
++ struct serio *io;
++ void __iomem *regs;
++ unsigned int irq;
++ unsigned int open;
++ /* Prevent concurrent writes to PSIF THR. */
++ spinlock_t lock;
++};
++
++static irqreturn_t psif_interrupt(int irq, void *_ptr)
++{
++ struct psif *psif = _ptr;
++ int retval = IRQ_NONE;
++ unsigned int io_flags = 0;
++ unsigned long status;
++
++ status = psif_readl(psif, SR);
++
++ if (status & PSIF_BIT(RXRDY)) {
++ unsigned char val = (unsigned char) psif_readl(psif, RHR);
++
++ if (status & PSIF_BIT(PARITY))
++ io_flags |= SERIO_PARITY;
++ if (status & PSIF_BIT(OVRUN))
++ dev_err(&psif->pdev->dev, "overrun read error\n");
++
++ serio_interrupt(psif->io, val, io_flags);
++
++ retval = IRQ_HANDLED;
++ }
++
++ return retval;
++}
++
++static int psif_write(struct serio *io, unsigned char val)
++{
++ struct psif *psif = io->port_data;
++ unsigned long flags;
++ int timeout = 10;
++ int retval = 0;
++
++ spin_lock_irqsave(&psif->lock, flags);
++
++ while (!(psif_readl(psif, SR) & PSIF_BIT(TXEMPTY)) && timeout--)
++ msleep(10);
++
++ if (timeout >= 0) {
++ psif_writel(psif, THR, val);
++ } else {
++ dev_dbg(&psif->pdev->dev, "timeout writing to THR\n");
++ retval = -EBUSY;
++ }
++
++ spin_unlock_irqrestore(&psif->lock, flags);
++
++ return retval;
++}
++
++static int psif_open(struct serio *io)
++{
++ struct psif *psif = io->port_data;
++ int retval;
++
++ retval = clk_enable(psif->pclk);
++ if (retval)
++ goto out;
++
++ psif_writel(psif, CR, PSIF_BIT(CR_TXEN) | PSIF_BIT(CR_RXEN));
++ psif_writel(psif, IER, PSIF_BIT(RXRDY));
++
++ psif->open = 1;
++out:
++ return retval;
++}
++
++static void psif_close(struct serio *io)
++{
++ struct psif *psif = io->port_data;
++
++ psif->open = 0;
++
++ psif_writel(psif, IDR, ~0UL);
++ psif_writel(psif, CR, PSIF_BIT(CR_TXDIS) | PSIF_BIT(CR_RXDIS));
++
++ clk_disable(psif->pclk);
++}
++
++static void psif_set_prescaler(struct psif *psif)
++{
++ unsigned long prscv;
++ unsigned long rate = clk_get_rate(psif->pclk);
++
++ /* PRSCV = Pulse length (100 us) * PSIF module frequency. */
++ prscv = 100 * (rate / 1000000UL);
++
++ if (prscv > ((1<<PSIF_PSR_PRSCV_SIZE) - 1)) {
++ prscv = (1<<PSIF_PSR_PRSCV_SIZE) - 1;
++ dev_dbg(&psif->pdev->dev, "pclk too fast, "
++ "prescaler set to max\n");
++ }
++
++ clk_enable(psif->pclk);
++ psif_writel(psif, PSR, prscv);
++ clk_disable(psif->pclk);
++}
++
++static int __init psif_probe(struct platform_device *pdev)
++{
++ struct resource *regs;
++ struct psif *psif;
++ struct serio *io;
++ struct clk *pclk;
++ int irq;
++ int ret;
++
++ psif = kzalloc(sizeof(struct psif), GFP_KERNEL);
++ if (!psif) {
++ dev_dbg(&pdev->dev, "out of memory\n");
++ ret = -ENOMEM;
++ goto out;
++ }
++ psif->pdev = pdev;
++
++ io = kzalloc(sizeof(struct serio), GFP_KERNEL);
++ if (!io) {
++ dev_dbg(&pdev->dev, "out of memory\n");
++ ret = -ENOMEM;
++ goto out_free_psif;
++ }
++ psif->io = io;
++
++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!regs) {
++ dev_dbg(&pdev->dev, "no mmio resources defined\n");
++ ret = -ENOMEM;
++ goto out_free_io;
++ }
++
++ psif->regs = ioremap(regs->start, regs->end - regs->start + 1);
++ if (!psif->regs) {
++ ret = -ENOMEM;
++ dev_dbg(&pdev->dev, "could not map I/O memory\n");
++ goto out_free_io;
++ }
++
++ pclk = clk_get(&pdev->dev, "pclk");
++ if (IS_ERR(pclk)) {
++ dev_dbg(&pdev->dev, "could not get peripheral clock\n");
++ ret = PTR_ERR(pclk);
++ goto out_iounmap;
++ }
++ psif->pclk = pclk;
++
++ /* Reset the PSIF to enter at a known state. */
++ ret = clk_enable(pclk);
++ if (ret) {
++ dev_dbg(&pdev->dev, "could not enable pclk\n");
++ goto out_put_clk;
++ }
++ psif_writel(psif, CR, PSIF_BIT(CR_SWRST));
++ clk_disable(pclk);
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0) {
++ dev_dbg(&pdev->dev, "could not get irq\n");
++ ret = -ENXIO;
++ goto out_put_clk;
++ }
++ ret = request_irq(irq, psif_interrupt, IRQF_SHARED, "at32psif", psif);
++ if (ret) {
++ dev_dbg(&pdev->dev, "could not request irq %d\n", irq);
++ goto out_put_clk;
++ }
++ psif->irq = irq;
++
++ io->id.type = SERIO_8042;
++ io->write = psif_write;
++ io->open = psif_open;
++ io->close = psif_close;
++ snprintf(io->name, sizeof(io->name), "AVR32 PS/2 port%d", pdev->id);
++ snprintf(io->phys, sizeof(io->phys), "at32psif/serio%d", pdev->id);
++ io->port_data = psif;
++ io->dev.parent = &pdev->dev;
++
++ psif_set_prescaler(psif);
++
++ spin_lock_init(&psif->lock);
++ serio_register_port(psif->io);
++ platform_set_drvdata(pdev, psif);
++
++ dev_info(&pdev->dev, "Atmel AVR32 PSIF PS/2 driver on 0x%08x irq %d\n",
++ (int)psif->regs, psif->irq);
++
++ return 0;
++
++out_put_clk:
++ clk_put(psif->pclk);
++out_iounmap:
++ iounmap(psif->regs);
++out_free_io:
++ kfree(io);
++out_free_psif:
++ kfree(psif);
++out:
++ return ret;
++}
++
++static int __exit psif_remove(struct platform_device *pdev)
++{
++ struct psif *psif = platform_get_drvdata(pdev);
++
++ psif_writel(psif, IDR, ~0UL);
++ psif_writel(psif, CR, PSIF_BIT(CR_TXDIS) | PSIF_BIT(CR_RXDIS));
++
++ serio_unregister_port(psif->io);
++ iounmap(psif->regs);
++ free_irq(psif->irq, psif);
++ clk_put(psif->pclk);
++ kfree(psif);
++
++ platform_set_drvdata(pdev, NULL);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int psif_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ struct psif *psif = platform_get_drvdata(pdev);
++
++ if (psif->open) {
++ psif_writel(psif, CR, PSIF_BIT(CR_RXDIS) | PSIF_BIT(CR_TXDIS));
++ clk_disable(psif->pclk);
++ }
++
++ return 0;
++}
++
++static int psif_resume(struct platform_device *pdev)
++{
++ struct psif *psif = platform_get_drvdata(pdev);
++
++ if (psif->open) {
++ clk_enable(psif->pclk);
++ psif_set_prescaler(psif);
++ psif_writel(psif, CR, PSIF_BIT(CR_RXEN) | PSIF_BIT(CR_TXEN));
++ }
++
++ return 0;
++}
++#else
++#define psif_suspend NULL
++#define psif_resume NULL
++#endif
++
++static struct platform_driver psif_driver = {
++ .remove = __exit_p(psif_remove),
++ .driver = {
++ .name = "atmel_psif",
++ },
++ .suspend = psif_suspend,
++ .resume = psif_resume,
++};
++
++static int __init psif_init(void)
++{
++ return platform_driver_probe(&psif_driver, psif_probe);
++}
++
++static void __exit psif_exit(void)
++{
++ platform_driver_unregister(&psif_driver);
++}
++
++module_init(psif_init);
++module_exit(psif_exit);
++
++MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt at atmel.com>");
++MODULE_DESCRIPTION("Atmel AVR32 PSIF PS/2 driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c
+index c45ea74..f1fd3b6 100644
+--- a/drivers/input/serio/hp_sdc_mlc.c
++++ b/drivers/input/serio/hp_sdc_mlc.c
+@@ -40,7 +40,7 @@
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/string.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+
+ #define PREFIX "HP SDC MLC: "
+
+diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
+index 60931ac..5ece9f5 100644
+--- a/drivers/input/serio/i8042-x86ia64io.h
++++ b/drivers/input/serio/i8042-x86ia64io.h
+@@ -370,10 +370,10 @@ static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id *
+ if (pnp_irq_valid(dev,0))
+ i8042_pnp_kbd_irq = pnp_irq(dev, 0);
+
+- strncpy(i8042_pnp_kbd_name, did->id, sizeof(i8042_pnp_kbd_name));
++ strlcpy(i8042_pnp_kbd_name, did->id, sizeof(i8042_pnp_kbd_name));
+ if (strlen(pnp_dev_name(dev))) {
+- strncat(i8042_pnp_kbd_name, ":", sizeof(i8042_pnp_kbd_name));
+- strncat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name));
++ strlcat(i8042_pnp_kbd_name, ":", sizeof(i8042_pnp_kbd_name));
++ strlcat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name));
+ }
+
+ i8042_pnp_kbd_devices++;
+@@ -391,10 +391,10 @@ static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id *
+ if (pnp_irq_valid(dev, 0))
+ i8042_pnp_aux_irq = pnp_irq(dev, 0);
+
+- strncpy(i8042_pnp_aux_name, did->id, sizeof(i8042_pnp_aux_name));
++ strlcpy(i8042_pnp_aux_name, did->id, sizeof(i8042_pnp_aux_name));
+ if (strlen(pnp_dev_name(dev))) {
+- strncat(i8042_pnp_aux_name, ":", sizeof(i8042_pnp_aux_name));
+- strncat(i8042_pnp_aux_name, pnp_dev_name(dev), sizeof(i8042_pnp_aux_name));
++ strlcat(i8042_pnp_aux_name, ":", sizeof(i8042_pnp_aux_name));
++ strlcat(i8042_pnp_aux_name, pnp_dev_name(dev), sizeof(i8042_pnp_aux_name));
+ }
+
+ i8042_pnp_aux_devices++;
+diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c
+index 49f8431..34c59d9 100644
+--- a/drivers/input/serio/rpckbd.c
++++ b/drivers/input/serio/rpckbd.c
+@@ -45,6 +45,7 @@
+ MODULE_AUTHOR("Vojtech Pavlik, Russell King");
+ MODULE_DESCRIPTION("Acorn RiscPC PS/2 keyboard controller driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:kart");
+
+ static int rpckbd_write(struct serio *port, unsigned char val)
+ {
+@@ -140,6 +141,7 @@ static struct platform_driver rpckbd_driver = {
+ .remove = __devexit_p(rpckbd_remove),
+ .driver = {
+ .name = "kart",
++ .owner = THIS_MODULE,
+ },
+ };
+
+diff --git a/drivers/input/tablet/Kconfig b/drivers/input/tablet/Kconfig
+index d371c0b..effb49e 100644
+--- a/drivers/input/tablet/Kconfig
++++ b/drivers/input/tablet/Kconfig
+@@ -25,14 +25,14 @@ config TABLET_USB_ACECAD
+ module will be called acecad.
+
+ config TABLET_USB_AIPTEK
+- tristate "Aiptek 6000U/8000U tablet support (USB)"
++ tristate "Aiptek 6000U/8000U and Genius G_PEN tablet support (USB)"
+ depends on USB_ARCH_HAS_HCD
+ select USB
+ help
+- Say Y here if you want to use the USB version of the Aiptek 6000U
+- or Aiptek 8000U tablet. Make sure to say Y to "Mouse support"
+- (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
+- (CONFIG_INPUT_EVDEV) as well.
++ Say Y here if you want to use the USB version of the Aiptek 6000U,
++ Aiptek 8000U or Genius G-PEN 560 tablet. Make sure to say Y to
++ "Mouse support" (CONFIG_INPUT_MOUSEDEV) and/or "Event interface
++ support" (CONFIG_INPUT_EVDEV) as well.
+
+ To compile this driver as a module, choose M here: the
+ module will be called aiptek.
+diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c
+index 94683f5..1d759f6 100644
+--- a/drivers/input/tablet/aiptek.c
++++ b/drivers/input/tablet/aiptek.c
+@@ -184,6 +184,7 @@
+ */
+
+ #define USB_VENDOR_ID_AIPTEK 0x08ca
++#define USB_VENDOR_ID_KYE 0x0458
+ #define USB_REQ_GET_REPORT 0x01
+ #define USB_REQ_SET_REPORT 0x09
+
+@@ -832,6 +833,7 @@ static const struct usb_device_id aiptek_ids[] = {
+ {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x22)},
+ {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x23)},
+ {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x24)},
++ {USB_DEVICE(USB_VENDOR_ID_KYE, 0x5003)},
+ {}
+ };
+
+diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
+index acf9830..706619d 100644
+--- a/drivers/input/tablet/wacom.h
++++ b/drivers/input/tablet/wacom.h
+@@ -101,8 +101,11 @@ struct wacom {
+ dma_addr_t data_dma;
+ struct input_dev *dev;
+ struct usb_device *usbdev;
++ struct usb_interface *intf;
+ struct urb *irq;
+ struct wacom_wac * wacom_wac;
++ struct mutex lock;
++ int open:1;
+ char phys[32];
+ };
+
+diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
+index 41caaef..71cc0c1 100644
+--- a/drivers/input/tablet/wacom_sys.c
++++ b/drivers/input/tablet/wacom_sys.c
+@@ -70,6 +70,7 @@ static void wacom_sys_irq(struct urb *urb)
+ input_sync(get_input_dev(&wcombo));
+
+ exit:
++ usb_mark_last_busy(wacom->usbdev);
+ retval = usb_submit_urb (urb, GFP_ATOMIC);
+ if (retval)
+ err ("%s - usb_submit_urb failed with result %d",
+@@ -124,10 +125,25 @@ static int wacom_open(struct input_dev *dev)
+ {
+ struct wacom *wacom = input_get_drvdata(dev);
+
++ mutex_lock(&wacom->lock);
++
+ wacom->irq->dev = wacom->usbdev;
+- if (usb_submit_urb(wacom->irq, GFP_KERNEL))
++
++ if (usb_autopm_get_interface(wacom->intf) < 0) {
++ mutex_unlock(&wacom->lock);
+ return -EIO;
++ }
++
++ if (usb_submit_urb(wacom->irq, GFP_KERNEL)) {
++ usb_autopm_put_interface(wacom->intf);
++ mutex_unlock(&wacom->lock);
++ return -EIO;
++ }
++
++ wacom->open = 1;
++ wacom->intf->needs_remote_wakeup = 1;
+
++ mutex_unlock(&wacom->lock);
+ return 0;
+ }
+
+@@ -135,7 +151,11 @@ static void wacom_close(struct input_dev *dev)
+ {
+ struct wacom *wacom = input_get_drvdata(dev);
+
++ mutex_lock(&wacom->lock);
+ usb_kill_urb(wacom->irq);
++ wacom->open = 0;
++ wacom->intf->needs_remote_wakeup = 0;
++ mutex_unlock(&wacom->lock);
+ }
+
+ void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+@@ -243,6 +263,8 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
+
+ wacom->usbdev = dev;
+ wacom->dev = input_dev;
++ wacom->intf = intf;
++ mutex_init(&wacom->lock);
+ usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
+ strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
+
+@@ -304,23 +326,57 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
+
+ static void wacom_disconnect(struct usb_interface *intf)
+ {
+- struct wacom *wacom = usb_get_intfdata (intf);
++ struct wacom *wacom = usb_get_intfdata(intf);
+
+ usb_set_intfdata(intf, NULL);
+- if (wacom) {
+- usb_kill_urb(wacom->irq);
+- input_unregister_device(wacom->dev);
+- usb_free_urb(wacom->irq);
+- usb_buffer_free(interface_to_usbdev(intf), 10, wacom->wacom_wac->data, wacom->data_dma);
+- kfree(wacom->wacom_wac);
+- kfree(wacom);
+- }
++
++ usb_kill_urb(wacom->irq);
++ input_unregister_device(wacom->dev);
++ usb_free_urb(wacom->irq);
++ usb_buffer_free(interface_to_usbdev(intf), 10, wacom->wacom_wac->data, wacom->data_dma);
++ kfree(wacom->wacom_wac);
++ kfree(wacom);
++}
++
++static int wacom_suspend(struct usb_interface *intf, pm_message_t message)
++{
++ struct wacom *wacom = usb_get_intfdata(intf);
++
++ mutex_lock(&wacom->lock);
++ usb_kill_urb(wacom->irq);
++ mutex_unlock(&wacom->lock);
++
++ return 0;
++}
++
++static int wacom_resume(struct usb_interface *intf)
++{
++ struct wacom *wacom = usb_get_intfdata(intf);
++ int rv;
++
++ mutex_lock(&wacom->lock);
++ if (wacom->open)
++ rv = usb_submit_urb(wacom->irq, GFP_NOIO);
++ else
++ rv = 0;
++ mutex_unlock(&wacom->lock);
++
++ return rv;
++}
++
++static int wacom_reset_resume(struct usb_interface *intf)
++{
++ return wacom_resume(intf);
+ }
+
+ static struct usb_driver wacom_driver = {
+ .name = "wacom",
+ .probe = wacom_probe,
+ .disconnect = wacom_disconnect,
++ .suspend = wacom_suspend,
++ .resume = wacom_resume,
++ .reset_resume = wacom_reset_resume,
++ .supports_autosuspend = 1,
+ };
+
+ static int __init wacom_init(void)
+diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
+index ffe3384..192513e 100644
+--- a/drivers/input/tablet/wacom_wac.c
++++ b/drivers/input/tablet/wacom_wac.c
+@@ -649,6 +649,7 @@ static struct wacom_features wacom_features[] = {
+ { "Wacom Intuos3 6x11", 10, 54204, 31750, 1023, 63, INTUOS3 },
+ { "Wacom Intuos3 4x6", 10, 31496, 19685, 1023, 63, INTUOS3S },
+ { "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 63, CINTIQ },
++ { "Wacom Cintiq 20WSX", 10, 86680, 54180, 1023, 63, WACOM_BEE },
+ { "Wacom Cintiq 12WX", 10, 53020, 33440, 1023, 63, WACOM_BEE },
+ { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS },
+ { }
+@@ -702,6 +703,7 @@ static struct usb_device_id wacom_ids[] = {
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB7) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) },
++ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC5) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC6) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
+ { }
+diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
+index 90e8e92..565ec71 100644
+--- a/drivers/input/touchscreen/Kconfig
++++ b/drivers/input/touchscreen/Kconfig
+@@ -185,6 +185,59 @@ config TOUCHSCREEN_UCB1400
+ To compile this driver as a module, choose M here: the
+ module will be called ucb1400_ts.
+
++config TOUCHSCREEN_WM97XX
++ tristate "Support for WM97xx AC97 touchscreen controllers"
++ depends on AC97_BUS
++ help
++ Say Y here if you have a Wolfson Microelectronics WM97xx
++ touchscreen connected to your system. Note that this option
++ only enables core driver, you will also need to select
++ support for appropriate chip below.
++
++ If unsure, say N.
++
++ To compile this driver as a module, choose M here: the
++ module will be called wm97xx-ts.
++
++config TOUCHSCREEN_WM9705
++ bool "WM9705 Touchscreen interface support"
++ depends on TOUCHSCREEN_WM97XX
++ help
++ Say Y here if you have a Wolfson Microelectronics WM9705
++ touchscreen controller connected to your system.
++
++ If unsure, say N.
++
++config TOUCHSCREEN_WM9712
++ bool "WM9712 Touchscreen interface support"
++ depends on TOUCHSCREEN_WM97XX
++ help
++ Say Y here if you have a Wolfson Microelectronics WM9712
++ touchscreen controller connected to your system.
++
++ If unsure, say N.
++
++config TOUCHSCREEN_WM9713
++ bool "WM9713 Touchscreen interface support"
++ depends on TOUCHSCREEN_WM97XX
++ help
++ Say Y here if you have a Wolfson Microelectronics WM9713 touchscreen
++ controller connected to your system.
++
++ If unsure, say N.
++
++config TOUCHSCREEN_WM97XX_MAINSTONE
++ tristate "WM97xx Mainstone accelerated touch"
++ depends on TOUCHSCREEN_WM97XX && ARCH_PXA
++ help
++ Say Y here for support for streaming mode with WM97xx touchscreens
++ on Mainstone systems.
++
++ If unsure, say N.
++
++ To compile this driver as a module, choose M here: the
++ module will be called mainstone-wm97xx.
++
+ config TOUCHSCREEN_USB_COMPOSITE
+ tristate "USB Touchscreen Driver"
+ depends on USB_ARCH_HAS_HCD
+diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
+index 35d4097..3c096d7 100644
+--- a/drivers/input/touchscreen/Makefile
++++ b/drivers/input/touchscreen/Makefile
+@@ -4,6 +4,8 @@
+
+ # Each configuration option enables a list of files.
+
++wm97xx-ts-y := wm97xx-core.o
++
+ obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o
+ obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o
+ obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o
+@@ -19,3 +21,8 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
+ obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
+ obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
+ obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o
++obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o
++wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
++wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o
++wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o
++obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
+diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
+index 57a1c28..907a45f 100644
+--- a/drivers/input/touchscreen/ads7846.c
++++ b/drivers/input/touchscreen/ads7846.c
+@@ -28,13 +28,6 @@
+ #include <linux/spi/ads7846.h>
+ #include <asm/irq.h>
+
+-#ifdef CONFIG_ARM
+-#include <asm/mach-types.h>
+-#ifdef CONFIG_ARCH_OMAP
+-#include <asm/arch/gpio.h>
+-#endif
+-#endif
+-
+
+ /*
+ * This code has been heavily tested on a Nokia 770, and lightly
+@@ -87,6 +80,7 @@ struct ads7846 {
+ #endif
+
+ u16 model;
++ u16 vref_mv;
+ u16 vref_delay_usecs;
+ u16 x_plate_ohms;
+ u16 pressure_max;
+@@ -184,9 +178,6 @@ struct ads7846 {
+ * The range is GND..vREF. The ads7843 and ads7835 must use external vREF;
+ * ads7846 lets that pin be unconnected, to use internal vREF.
+ */
+-static unsigned vREF_mV;
+-module_param(vREF_mV, uint, 0);
+-MODULE_PARM_DESC(vREF_mV, "external vREF voltage, in milliVolts");
+
+ struct ser_req {
+ u8 ref_on;
+@@ -213,7 +204,6 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
+ struct ads7846 *ts = dev_get_drvdata(dev);
+ struct ser_req *req = kzalloc(sizeof *req, GFP_KERNEL);
+ int status;
+- int uninitialized_var(sample);
+ int use_internal;
+
+ if (!req)
+@@ -270,13 +260,13 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
+
+ if (status == 0) {
+ /* on-wire is a must-ignore bit, a BE12 value, then padding */
+- sample = be16_to_cpu(req->sample);
+- sample = sample >> 3;
+- sample &= 0x0fff;
++ status = be16_to_cpu(req->sample);
++ status = status >> 3;
++ status &= 0x0fff;
+ }
+
+ kfree(req);
+- return status ? status : sample;
++ return status;
+ }
+
+ #if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE)
+@@ -317,7 +307,7 @@ static inline unsigned vaux_adjust(struct ads7846 *ts, ssize_t v)
+ unsigned retval = v;
+
+ /* external resistors may scale vAUX into 0..vREF */
+- retval *= vREF_mV;
++ retval *= ts->vref_mv;
+ retval = retval >> 12;
+ return retval;
+ }
+@@ -375,14 +365,14 @@ static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts)
+ /* hwmon sensors need a reference voltage */
+ switch (ts->model) {
+ case 7846:
+- if (!vREF_mV) {
++ if (!ts->vref_mv) {
+ dev_dbg(&spi->dev, "assuming 2.5V internal vREF\n");
+- vREF_mV = 2500;
++ ts->vref_mv = 2500;
+ }
+ break;
+ case 7845:
+ case 7843:
+- if (!vREF_mV) {
++ if (!ts->vref_mv) {
+ dev_warn(&spi->dev,
+ "external vREF for ADS%d not specified\n",
+ ts->model);
+@@ -875,6 +865,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
+
+ ts->spi = spi;
+ ts->input = input_dev;
++ ts->vref_mv = pdata->vref_mv;
+
+ hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ ts->timer.function = ads7846_timer;
+@@ -1174,31 +1165,6 @@ static struct spi_driver ads7846_driver = {
+
+ static int __init ads7846_init(void)
+ {
+- /* grr, board-specific init should stay out of drivers!! */
+-
+-#ifdef CONFIG_ARCH_OMAP
+- if (machine_is_omap_osk()) {
+- /* GPIO4 = PENIRQ; GPIO6 = BUSY */
+- omap_request_gpio(4);
+- omap_set_gpio_direction(4, 1);
+- omap_request_gpio(6);
+- omap_set_gpio_direction(6, 1);
+- }
+- // also TI 1510 Innovator, bitbanging through FPGA
+- // also Nokia 770
+- // also Palm Tungsten T2
+-#endif
+-
+- // PXA:
+- // also Dell Axim X50
+- // also HP iPaq H191x/H192x/H415x/H435x
+- // also Intel Lubbock (additional to UCB1400; as temperature sensor)
+- // also Sharp Zaurus C7xx, C8xx (corgi/sheperd/husky)
+-
+- // Atmel at91sam9261-EK uses ads7843
+-
+- // also various AMD Au1x00 devel boards
+-
+ return spi_register_driver(&ads7846_driver);
+ }
+ module_init(ads7846_init);
+@@ -1206,14 +1172,6 @@ module_init(ads7846_init);
+ static void __exit ads7846_exit(void)
+ {
+ spi_unregister_driver(&ads7846_driver);
+-
+-#ifdef CONFIG_ARCH_OMAP
+- if (machine_is_omap_osk()) {
+- omap_free_gpio(4);
+- omap_free_gpio(6);
+- }
+-#endif
+-
+ }
+ module_exit(ads7846_exit);
+
+diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
+index 99d92f5..4e9d8ee 100644
+--- a/drivers/input/touchscreen/corgi_ts.c
++++ b/drivers/input/touchscreen/corgi_ts.c
+@@ -22,6 +22,7 @@
+ #include <asm/arch/sharpsl.h>
+ #include <asm/arch/hardware.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+
+
+ #define PWR_MODE_ACTIVE 0
+@@ -361,6 +362,7 @@ static struct platform_driver corgits_driver = {
+ .resume = corgits_resume,
+ .driver = {
+ .name = "corgi-ts",
++ .owner = THIS_MODULE,
+ },
+ };
+
+@@ -380,3 +382,4 @@ module_exit(corgits_exit);
+ MODULE_AUTHOR("Richard Purdie <rpurdie at rpsys.net>");
+ MODULE_DESCRIPTION("Corgi TouchScreen Driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:corgi-ts");
+diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c
+index 42a1c9a..7422421 100644
+--- a/drivers/input/touchscreen/jornada720_ts.c
++++ b/drivers/input/touchscreen/jornada720_ts.c
+@@ -160,11 +160,15 @@ static int __devexit jornada720_ts_remove(struct platform_device *pdev)
+ return 0;
+ }
+
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:jornada_ts");
++
+ static struct platform_driver jornada720_ts_driver = {
+ .probe = jornada720_ts_probe,
+ .remove = __devexit_p(jornada720_ts_remove),
+ .driver = {
+ .name = "jornada_ts",
++ .owner = THIS_MODULE,
+ },
+ };
+
+diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c
+new file mode 100644
+index 0000000..a79f029
+--- /dev/null
++++ b/drivers/input/touchscreen/mainstone-wm97xx.c
+@@ -0,0 +1,302 @@
++/*
++ * mainstone-wm97xx.c -- Mainstone Continuous Touch screen driver for
++ * Wolfson WM97xx AC97 Codecs.
++ *
++ * Copyright 2004, 2007 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ * liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ * Parts Copyright : Ian Molton <spyro at f2s.com>
++ * Andrew Zabolotny <zap at homelink.ru>
++ *
++ * 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.
++ *
++ * Notes:
++ * This is a wm97xx extended touch driver to capture touch
++ * data in a continuous manner on the Intel XScale archictecture
++ *
++ * Features:
++ * - codecs supported:- WM9705, WM9712, WM9713
++ * - processors supported:- Intel XScale PXA25x, PXA26x, PXA27x
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/wm97xx.h>
++#include <linux/io.h>
++#include <asm/arch/pxa-regs.h>
++
++#define VERSION "0.13"
++
++struct continuous {
++ u16 id; /* codec id */
++ u8 code; /* continuous code */
++ u8 reads; /* number of coord reads per read cycle */
++ u32 speed; /* number of coords per second */
++};
++
++#define WM_READS(sp) ((sp / HZ) + 1)
++
++static const struct continuous cinfo[] = {
++ {WM9705_ID2, 0, WM_READS(94), 94},
++ {WM9705_ID2, 1, WM_READS(188), 188},
++ {WM9705_ID2, 2, WM_READS(375), 375},
++ {WM9705_ID2, 3, WM_READS(750), 750},
++ {WM9712_ID2, 0, WM_READS(94), 94},
++ {WM9712_ID2, 1, WM_READS(188), 188},
++ {WM9712_ID2, 2, WM_READS(375), 375},
++ {WM9712_ID2, 3, WM_READS(750), 750},
++ {WM9713_ID2, 0, WM_READS(94), 94},
++ {WM9713_ID2, 1, WM_READS(120), 120},
++ {WM9713_ID2, 2, WM_READS(154), 154},
++ {WM9713_ID2, 3, WM_READS(188), 188},
++};
++
++/* continuous speed index */
++static int sp_idx;
++static u16 last, tries;
++
++/*
++ * Pen sampling frequency (Hz) in continuous mode.
++ */
++static int cont_rate = 200;
++module_param(cont_rate, int, 0);
++MODULE_PARM_DESC(cont_rate, "Sampling rate in continuous mode (Hz)");
++
++/*
++ * Pen down detection.
++ *
++ * This driver can either poll or use an interrupt to indicate a pen down
++ * event. If the irq request fails then it will fall back to polling mode.
++ */
++static int pen_int;
++module_param(pen_int, int, 0);
++MODULE_PARM_DESC(pen_int, "Pen down detection (1 = interrupt, 0 = polling)");
++
++/*
++ * Pressure readback.
++ *
++ * Set to 1 to read back pen down pressure
++ */
++static int pressure;
++module_param(pressure, int, 0);
++MODULE_PARM_DESC(pressure, "Pressure readback (1 = pressure, 0 = no pressure)");
++
++/*
++ * AC97 touch data slot.
++ *
++ * Touch screen readback data ac97 slot
++ */
++static int ac97_touch_slot = 5;
++module_param(ac97_touch_slot, int, 0);
++MODULE_PARM_DESC(ac97_touch_slot, "Touch screen data slot AC97 number");
++
++
++/* flush AC97 slot 5 FIFO on pxa machines */
++#ifdef CONFIG_PXA27x
++static void wm97xx_acc_pen_up(struct wm97xx *wm)
++{
++ schedule_timeout_uninterruptible(1);
++
++ while (MISR & (1 << 2))
++ MODR;
++}
++#else
++static void wm97xx_acc_pen_up(struct wm97xx *wm)
++{
++ int count = 16;
++ schedule_timeout_uninterruptible(1);
++
++ while (count < 16) {
++ MODR;
++ count--;
++ }
++}
++#endif
++
++static int wm97xx_acc_pen_down(struct wm97xx *wm)
++{
++ u16 x, y, p = 0x100 | WM97XX_ADCSEL_PRES;
++ int reads = 0;
++
++ /* When the AC97 queue has been drained we need to allow time
++ * to buffer up samples otherwise we end up spinning polling
++ * for samples. The controller can't have a suitably low
++ * threashold set to use the notifications it gives.
++ */
++ schedule_timeout_uninterruptible(1);
++
++ if (tries > 5) {
++ tries = 0;
++ return RC_PENUP;
++ }
++
++ x = MODR;
++ if (x == last) {
++ tries++;
++ return RC_AGAIN;
++ }
++ last = x;
++ do {
++ if (reads)
++ x = MODR;
++ y = MODR;
++ if (pressure)
++ p = MODR;
++
++ /* are samples valid */
++ if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X ||
++ (y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y ||
++ (p & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_PRES)
++ goto up;
++
++ /* coordinate is good */
++ tries = 0;
++ input_report_abs(wm->input_dev, ABS_X, x & 0xfff);
++ input_report_abs(wm->input_dev, ABS_Y, y & 0xfff);
++ input_report_abs(wm->input_dev, ABS_PRESSURE, p & 0xfff);
++ input_sync(wm->input_dev);
++ reads++;
++ } while (reads < cinfo[sp_idx].reads);
++up:
++ return RC_PENDOWN | RC_AGAIN;
++}
++
++static int wm97xx_acc_startup(struct wm97xx *wm)
++{
++ int idx = 0;
++
++ /* check we have a codec */
++ if (wm->ac97 == NULL)
++ return -ENODEV;
++
++ /* Go you big red fire engine */
++ for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) {
++ if (wm->id != cinfo[idx].id)
++ continue;
++ sp_idx = idx;
++ if (cont_rate <= cinfo[idx].speed)
++ break;
++ }
++ wm->acc_rate = cinfo[sp_idx].code;
++ wm->acc_slot = ac97_touch_slot;
++ dev_info(wm->dev,
++ "mainstone accelerated touchscreen driver, %d samples/sec\n",
++ cinfo[sp_idx].speed);
++
++ /* codec specific irq config */
++ if (pen_int) {
++ switch (wm->id) {
++ case WM9705_ID2:
++ wm->pen_irq = IRQ_GPIO(4);
++ set_irq_type(IRQ_GPIO(4), IRQT_BOTHEDGE);
++ break;
++ case WM9712_ID2:
++ case WM9713_ID2:
++ /* enable pen down interrupt */
++ /* use PEN_DOWN GPIO 13 to assert IRQ on GPIO line 2 */
++ wm->pen_irq = MAINSTONE_AC97_IRQ;
++ wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN,
++ WM97XX_GPIO_POL_HIGH,
++ WM97XX_GPIO_STICKY,
++ WM97XX_GPIO_WAKE);
++ wm97xx_config_gpio(wm, WM97XX_GPIO_2, WM97XX_GPIO_OUT,
++ WM97XX_GPIO_POL_HIGH,
++ WM97XX_GPIO_NOTSTICKY,
++ WM97XX_GPIO_NOWAKE);
++ break;
++ default:
++ dev_err(wm->dev,
++ "pen down irq not supported on this device\n");
++ pen_int = 0;
++ break;
++ }
++ }
++
++ return 0;
++}
++
++static void wm97xx_acc_shutdown(struct wm97xx *wm)
++{
++ /* codec specific deconfig */
++ if (pen_int) {
++ switch (wm->id & 0xffff) {
++ case WM9705_ID2:
++ wm->pen_irq = 0;
++ break;
++ case WM9712_ID2:
++ case WM9713_ID2:
++ /* disable interrupt */
++ wm->pen_irq = 0;
++ break;
++ }
++ }
++}
++
++static void wm97xx_irq_enable(struct wm97xx *wm, int enable)
++{
++ if (enable)
++ enable_irq(wm->pen_irq);
++ else
++ disable_irq(wm->pen_irq);
++}
++
++static struct wm97xx_mach_ops mainstone_mach_ops = {
++ .acc_enabled = 1,
++ .acc_pen_up = wm97xx_acc_pen_up,
++ .acc_pen_down = wm97xx_acc_pen_down,
++ .acc_startup = wm97xx_acc_startup,
++ .acc_shutdown = wm97xx_acc_shutdown,
++ .irq_enable = wm97xx_irq_enable,
++ .irq_gpio = WM97XX_GPIO_2,
++};
++
++static int mainstone_wm97xx_probe(struct platform_device *pdev)
++{
++ struct wm97xx *wm = platform_get_drvdata(pdev);
++
++ return wm97xx_register_mach_ops(wm, &mainstone_mach_ops);
++}
++
++static int mainstone_wm97xx_remove(struct platform_device *pdev)
++{
++ struct wm97xx *wm = platform_get_drvdata(pdev);
++
++ wm97xx_unregister_mach_ops(wm);
++ return 0;
++}
++
++static struct platform_driver mainstone_wm97xx_driver = {
++ .probe = mainstone_wm97xx_probe,
++ .remove = mainstone_wm97xx_remove,
++ .driver = {
++ .name = "wm97xx-touch",
++ },
++};
++
++static int __init mainstone_wm97xx_init(void)
++{
++ return platform_driver_register(&mainstone_wm97xx_driver);
++}
++
++static void __exit mainstone_wm97xx_exit(void)
++{
++ platform_driver_unregister(&mainstone_wm97xx_driver);
++}
++
++module_init(mainstone_wm97xx_init);
++module_exit(mainstone_wm97xx_exit);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood <liam.girdwood at wolfsonmicro.com>");
++MODULE_DESCRIPTION("wm97xx continuous touch driver for mainstone");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
+index 607f993..bce018e 100644
+--- a/drivers/input/touchscreen/ucb1400_ts.c
++++ b/drivers/input/touchscreen/ucb1400_ts.c
+@@ -427,10 +427,6 @@ static int ucb1400_detect_irq(struct ucb1400 *ucb)
+ unsigned long mask, timeout;
+
+ mask = probe_irq_on();
+- if (!mask) {
+- probe_irq_off(mask);
+- return -EBUSY;
+- }
+
+ /* Enable the ADC interrupt. */
+ ucb1400_reg_write(ucb, UCB_IE_RIS, UCB_IE_ADC);
+diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
+index 63f9664..3a0a8ca 100644
+--- a/drivers/input/touchscreen/usbtouchscreen.c
++++ b/drivers/input/touchscreen/usbtouchscreen.c
+@@ -396,9 +396,12 @@ static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
+ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
+ {
+ struct usb_device *dev = usbtouch->udev;
+- int ret;
+- unsigned char buf[2];
++ int ret = -ENOMEM;
++ unsigned char *buf;
+
++ buf = kmalloc(2, GFP_KERNEL);
++ if (!buf)
++ goto err_nobuf;
+ /* reset */
+ buf[0] = buf[1] = 0xFF;
+ ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
+@@ -406,9 +409,11 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, 0, buf, 2, USB_CTRL_SET_TIMEOUT);
+ if (ret < 0)
+- return ret;
+- if (buf[0] != 0x06 || buf[1] != 0x00)
+- return -ENODEV;
++ goto err_out;
++ if (buf[0] != 0x06 || buf[1] != 0x00) {
++ ret = -ENODEV;
++ goto err_out;
++ }
+
+ /* set coordinate output rate */
+ buf[0] = buf[1] = 0xFF;
+@@ -417,20 +422,22 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT);
+ if (ret < 0)
+- return ret;
++ goto err_out;
+ if ((buf[0] != 0x06 || buf[1] != 0x00) &&
+- (buf[0] != 0x15 || buf[1] != 0x01))
+- return -ENODEV;
++ (buf[0] != 0x15 || buf[1] != 0x01)) {
++ ret = -ENODEV;
++ goto err_out;
++ }
+
+ /* start sending data */
+ ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
+ TSC10_CMD_DATA1,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
+- if (ret < 0)
+- return ret;
+-
+- return 0;
++err_out:
++ kfree(buf);
++err_nobuf:
++ return ret;
+ }
+
+
+diff --git a/drivers/input/touchscreen/wm9705.c b/drivers/input/touchscreen/wm9705.c
+new file mode 100644
+index 0000000..978e1a1
+--- /dev/null
++++ b/drivers/input/touchscreen/wm9705.c
+@@ -0,0 +1,353 @@
++/*
++ * wm9705.c -- Codec driver for Wolfson WM9705 AC97 Codec.
++ *
++ * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ * liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ * Parts Copyright : Ian Molton <spyro at f2s.com>
++ * Andrew Zabolotny <zap at homelink.ru>
++ * Russell King <rmk at arm.linux.org.uk>
++ *
++ * 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/module.h>
++#include <linux/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/input.h>
++#include <linux/delay.h>
++#include <linux/bitops.h>
++#include <linux/wm97xx.h>
++
++#define TS_NAME "wm97xx"
++#define WM9705_VERSION "1.00"
++#define DEFAULT_PRESSURE 0xb0c0
++
++/*
++ * Module parameters
++ */
++
++/*
++ * Set current used for pressure measurement.
++ *
++ * Set pil = 2 to use 400uA
++ * pil = 1 to use 200uA and
++ * pil = 0 to disable pressure measurement.
++ *
++ * This is used to increase the range of values returned by the adc
++ * when measureing touchpanel pressure.
++ */
++static int pil;
++module_param(pil, int, 0);
++MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
++
++/*
++ * Set threshold for pressure measurement.
++ *
++ * Pen down pressure below threshold is ignored.
++ */
++static int pressure = DEFAULT_PRESSURE & 0xfff;
++module_param(pressure, int, 0);
++MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
++
++/*
++ * Set adc sample delay.
++ *
++ * For accurate touchpanel measurements, some settling time may be
++ * required between the switch matrix applying a voltage across the
++ * touchpanel plate and the ADC sampling the signal.
++ *
++ * This delay can be set by setting delay = n, where n is the array
++ * position of the delay in the array delay_table below.
++ * Long delays > 1ms are supported for completeness, but are not
++ * recommended.
++ */
++static int delay = 4;
++module_param(delay, int, 0);
++MODULE_PARM_DESC(delay, "Set adc sample delay.");
++
++/*
++ * Pen detect comparator threshold.
++ *
++ * 0 to Vmid in 15 steps, 0 = use zero power comparator with Vmid threshold
++ * i.e. 1 = Vmid/15 threshold
++ * 15 = Vmid/1 threshold
++ *
++ * Adjust this value if you are having problems with pen detect not
++ * detecting any down events.
++ */
++static int pdd = 8;
++module_param(pdd, int, 0);
++MODULE_PARM_DESC(pdd, "Set pen detect comparator threshold");
++
++/*
++ * Set adc mask function.
++ *
++ * Sources of glitch noise, such as signals driving an LCD display, may feed
++ * through to the touch screen plates and affect measurement accuracy. In
++ * order to minimise this, a signal may be applied to the MASK pin to delay or
++ * synchronise the sampling.
++ *
++ * 0 = No delay or sync
++ * 1 = High on pin stops conversions
++ * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
++ * 3 = Edge triggered, edge on pin starts conversion after delay param
++ */
++static int mask;
++module_param(mask, int, 0);
++MODULE_PARM_DESC(mask, "Set adc mask function.");
++
++/*
++ * ADC sample delay times in uS
++ */
++static const int delay_table[] = {
++ 21, /* 1 AC97 Link frames */
++ 42, /* 2 */
++ 84, /* 4 */
++ 167, /* 8 */
++ 333, /* 16 */
++ 667, /* 32 */
++ 1000, /* 48 */
++ 1333, /* 64 */
++ 2000, /* 96 */
++ 2667, /* 128 */
++ 3333, /* 160 */
++ 4000, /* 192 */
++ 4667, /* 224 */
++ 5333, /* 256 */
++ 6000, /* 288 */
++ 0 /* No delay, switch matrix always on */
++};
++
++/*
++ * Delay after issuing a POLL command.
++ *
++ * The delay is 3 AC97 link frames + the touchpanel settling delay
++ */
++static inline void poll_delay(int d)
++{
++ udelay(3 * AC97_LINK_FRAME + delay_table[d]);
++}
++
++/*
++ * set up the physical settings of the WM9705
++ */
++static void wm9705_phy_init(struct wm97xx *wm)
++{
++ u16 dig1 = 0, dig2 = WM97XX_RPR;
++
++ /*
++ * mute VIDEO and AUX as they share X and Y touchscreen
++ * inputs on the WM9705
++ */
++ wm97xx_reg_write(wm, AC97_AUX, 0x8000);
++ wm97xx_reg_write(wm, AC97_VIDEO, 0x8000);
++
++ /* touchpanel pressure current*/
++ if (pil == 2) {
++ dig2 |= WM9705_PIL;
++ dev_dbg(wm->dev,
++ "setting pressure measurement current to 400uA.");
++ } else if (pil)
++ dev_dbg(wm->dev,
++ "setting pressure measurement current to 200uA.");
++ if (!pil)
++ pressure = 0;
++
++ /* polling mode sample settling delay */
++ if (delay != 4) {
++ if (delay < 0 || delay > 15) {
++ dev_dbg(wm->dev, "supplied delay out of range.");
++ delay = 4;
++ }
++ }
++ dig1 &= 0xff0f;
++ dig1 |= WM97XX_DELAY(delay);
++ dev_dbg(wm->dev, "setting adc sample delay to %d u Secs.",
++ delay_table[delay]);
++
++ /* WM9705 pdd */
++ dig2 |= (pdd & 0x000f);
++ dev_dbg(wm->dev, "setting pdd to Vmid/%d", 1 - (pdd & 0x000f));
++
++ /* mask */
++ dig2 |= ((mask & 0x3) << 4);
++
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
++}
++
++static void wm9705_dig_enable(struct wm97xx *wm, int enable)
++{
++ if (enable) {
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
++ wm->dig[2] | WM97XX_PRP_DET_DIG);
++ wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
++ } else
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
++ wm->dig[2] & ~WM97XX_PRP_DET_DIG);
++}
++
++static void wm9705_aux_prepare(struct wm97xx *wm)
++{
++ memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0);
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG);
++}
++
++static void wm9705_dig_restore(struct wm97xx *wm)
++{
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]);
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]);
++}
++
++static inline int is_pden(struct wm97xx *wm)
++{
++ return wm->dig[2] & WM9705_PDEN;
++}
++
++/*
++ * Read a sample from the WM9705 adc in polling mode.
++ */
++static int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
++{
++ int timeout = 5 * delay;
++
++ if (!wm->pen_probably_down) {
++ u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++ if (!(data & WM97XX_PEN_DOWN))
++ return RC_PENUP;
++ wm->pen_probably_down = 1;
++ }
++
++ /* set up digitiser */
++ if (adcsel & 0x8000)
++ adcsel = ((adcsel & 0x7fff) + 3) << 12;
++
++ if (wm->mach_ops && wm->mach_ops->pre_sample)
++ wm->mach_ops->pre_sample(adcsel);
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
++ adcsel | WM97XX_POLL | WM97XX_DELAY(delay));
++
++ /* wait 3 AC97 time slots + delay for conversion */
++ poll_delay(delay);
++
++ /* wait for POLL to go low */
++ while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL)
++ && timeout) {
++ udelay(AC97_LINK_FRAME);
++ timeout--;
++ }
++
++ if (timeout == 0) {
++ /* If PDEN is set, we can get a timeout when pen goes up */
++ if (is_pden(wm))
++ wm->pen_probably_down = 0;
++ else
++ dev_dbg(wm->dev, "adc sample timeout");
++ return RC_PENUP;
++ }
++
++ *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++ if (wm->mach_ops && wm->mach_ops->post_sample)
++ wm->mach_ops->post_sample(adcsel);
++
++ /* check we have correct sample */
++ if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) {
++ dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel,
++ *sample & WM97XX_ADCSEL_MASK);
++ return RC_PENUP;
++ }
++
++ if (!(*sample & WM97XX_PEN_DOWN)) {
++ wm->pen_probably_down = 0;
++ return RC_PENUP;
++ }
++
++ return RC_VALID;
++}
++
++/*
++ * Sample the WM9705 touchscreen in polling mode
++ */
++static int wm9705_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
++{
++ int rc;
++
++ rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_X, &data->x);
++ if (rc != RC_VALID)
++ return rc;
++ rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y);
++ if (rc != RC_VALID)
++ return rc;
++ if (pil) {
++ rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_PRES, &data->p);
++ if (rc != RC_VALID)
++ return rc;
++ } else
++ data->p = DEFAULT_PRESSURE;
++
++ return RC_VALID;
++}
++
++/*
++ * Enable WM9705 continuous mode, i.e. touch data is streamed across
++ * an AC97 slot
++ */
++static int wm9705_acc_enable(struct wm97xx *wm, int enable)
++{
++ u16 dig1, dig2;
++ int ret = 0;
++
++ dig1 = wm->dig[1];
++ dig2 = wm->dig[2];
++
++ if (enable) {
++ /* continous mode */
++ if (wm->mach_ops->acc_startup &&
++ (ret = wm->mach_ops->acc_startup(wm)) < 0)
++ return ret;
++ dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK |
++ WM97XX_DELAY_MASK | WM97XX_SLT_MASK);
++ dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN |
++ WM97XX_DELAY(delay) |
++ WM97XX_SLT(wm->acc_slot) |
++ WM97XX_RATE(wm->acc_rate);
++ if (pil)
++ dig1 |= WM97XX_ADCSEL_PRES;
++ dig2 |= WM9705_PDEN;
++ } else {
++ dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN);
++ dig2 &= ~WM9705_PDEN;
++ if (wm->mach_ops->acc_shutdown)
++ wm->mach_ops->acc_shutdown(wm);
++ }
++
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
++
++ return ret;
++}
++
++struct wm97xx_codec_drv wm9705_codec = {
++ .id = WM9705_ID2,
++ .name = "wm9705",
++ .poll_sample = wm9705_poll_sample,
++ .poll_touch = wm9705_poll_touch,
++ .acc_enable = wm9705_acc_enable,
++ .phy_init = wm9705_phy_init,
++ .dig_enable = wm9705_dig_enable,
++ .dig_restore = wm9705_dig_restore,
++ .aux_prepare = wm9705_aux_prepare,
++};
++EXPORT_SYMBOL_GPL(wm9705_codec);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood <liam.girdwood at wolfsonmicro.com>");
++MODULE_DESCRIPTION("WM9705 Touch Screen Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c
+new file mode 100644
+index 0000000..0b6e4cf
+--- /dev/null
++++ b/drivers/input/touchscreen/wm9712.c
+@@ -0,0 +1,462 @@
++/*
++ * wm9712.c -- Codec driver for Wolfson WM9712 AC97 Codecs.
++ *
++ * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ * liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ * Parts Copyright : Ian Molton <spyro at f2s.com>
++ * Andrew Zabolotny <zap at homelink.ru>
++ * Russell King <rmk at arm.linux.org.uk>
++ *
++ * 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/module.h>
++#include <linux/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/input.h>
++#include <linux/delay.h>
++#include <linux/bitops.h>
++#include <linux/wm97xx.h>
++
++#define TS_NAME "wm97xx"
++#define WM9712_VERSION "1.00"
++#define DEFAULT_PRESSURE 0xb0c0
++
++/*
++ * Module parameters
++ */
++
++/*
++ * Set internal pull up for pen detect.
++ *
++ * Pull up is in the range 1.02k (least sensitive) to 64k (most sensitive)
++ * i.e. pull up resistance = 64k Ohms / rpu.
++ *
++ * Adjust this value if you are having problems with pen detect not
++ * detecting any down event.
++ */
++static int rpu = 8;
++module_param(rpu, int, 0);
++MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect.");
++
++/*
++ * Set current used for pressure measurement.
++ *
++ * Set pil = 2 to use 400uA
++ * pil = 1 to use 200uA and
++ * pil = 0 to disable pressure measurement.
++ *
++ * This is used to increase the range of values returned by the adc
++ * when measureing touchpanel pressure.
++ */
++static int pil;
++module_param(pil, int, 0);
++MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
++
++/*
++ * Set threshold for pressure measurement.
++ *
++ * Pen down pressure below threshold is ignored.
++ */
++static int pressure = DEFAULT_PRESSURE & 0xfff;
++module_param(pressure, int, 0);
++MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
++
++/*
++ * Set adc sample delay.
++ *
++ * For accurate touchpanel measurements, some settling time may be
++ * required between the switch matrix applying a voltage across the
++ * touchpanel plate and the ADC sampling the signal.
++ *
++ * This delay can be set by setting delay = n, where n is the array
++ * position of the delay in the array delay_table below.
++ * Long delays > 1ms are supported for completeness, but are not
++ * recommended.
++ */
++static int delay = 3;
++module_param(delay, int, 0);
++MODULE_PARM_DESC(delay, "Set adc sample delay.");
++
++/*
++ * Set five_wire = 1 to use a 5 wire touchscreen.
++ *
++ * NOTE: Five wire mode does not allow for readback of pressure.
++ */
++static int five_wire;
++module_param(five_wire, int, 0);
++MODULE_PARM_DESC(five_wire, "Set to '1' to use 5-wire touchscreen.");
++
++/*
++ * Set adc mask function.
++ *
++ * Sources of glitch noise, such as signals driving an LCD display, may feed
++ * through to the touch screen plates and affect measurement accuracy. In
++ * order to minimise this, a signal may be applied to the MASK pin to delay or
++ * synchronise the sampling.
++ *
++ * 0 = No delay or sync
++ * 1 = High on pin stops conversions
++ * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
++ * 3 = Edge triggered, edge on pin starts conversion after delay param
++ */
++static int mask;
++module_param(mask, int, 0);
++MODULE_PARM_DESC(mask, "Set adc mask function.");
++
++/*
++ * Coordinate Polling Enable.
++ *
++ * Set to 1 to enable coordinate polling. e.g. x,y[,p] is sampled together
++ * for every poll.
++ */
++static int coord;
++module_param(coord, int, 0);
++MODULE_PARM_DESC(coord, "Polling coordinate mode");
++
++/*
++ * ADC sample delay times in uS
++ */
++static const int delay_table[] = {
++ 21, /* 1 AC97 Link frames */
++ 42, /* 2 */
++ 84, /* 4 */
++ 167, /* 8 */
++ 333, /* 16 */
++ 667, /* 32 */
++ 1000, /* 48 */
++ 1333, /* 64 */
++ 2000, /* 96 */
++ 2667, /* 128 */
++ 3333, /* 160 */
++ 4000, /* 192 */
++ 4667, /* 224 */
++ 5333, /* 256 */
++ 6000, /* 288 */
++ 0 /* No delay, switch matrix always on */
++};
++
++/*
++ * Delay after issuing a POLL command.
++ *
++ * The delay is 3 AC97 link frames + the touchpanel settling delay
++ */
++static inline void poll_delay(int d)
++{
++ udelay(3 * AC97_LINK_FRAME + delay_table[d]);
++}
++
++/*
++ * set up the physical settings of the WM9712
++ */
++static void wm9712_phy_init(struct wm97xx *wm)
++{
++ u16 dig1 = 0;
++ u16 dig2 = WM97XX_RPR | WM9712_RPU(1);
++
++ /* WM9712 rpu */
++ if (rpu) {
++ dig2 &= 0xffc0;
++ dig2 |= WM9712_RPU(rpu);
++ dev_dbg(wm->dev, "setting pen detect pull-up to %d Ohms",
++ 64000 / rpu);
++ }
++
++ /* touchpanel pressure current*/
++ if (pil == 2) {
++ dig2 |= WM9712_PIL;
++ dev_dbg(wm->dev,
++ "setting pressure measurement current to 400uA.");
++ } else if (pil)
++ dev_dbg(wm->dev,
++ "setting pressure measurement current to 200uA.");
++ if (!pil)
++ pressure = 0;
++
++ /* WM9712 five wire */
++ if (five_wire) {
++ dig2 |= WM9712_45W;
++ dev_dbg(wm->dev, "setting 5-wire touchscreen mode.");
++ }
++
++ /* polling mode sample settling delay */
++ if (delay < 0 || delay > 15) {
++ dev_dbg(wm->dev, "supplied delay out of range.");
++ delay = 4;
++ }
++ dig1 &= 0xff0f;
++ dig1 |= WM97XX_DELAY(delay);
++ dev_dbg(wm->dev, "setting adc sample delay to %d u Secs.",
++ delay_table[delay]);
++
++ /* mask */
++ dig2 |= ((mask & 0x3) << 6);
++ if (mask) {
++ u16 reg;
++ /* Set GPIO4 as Mask Pin*/
++ reg = wm97xx_reg_read(wm, AC97_MISC_AFE);
++ wm97xx_reg_write(wm, AC97_MISC_AFE, reg | WM97XX_GPIO_4);
++ reg = wm97xx_reg_read(wm, AC97_GPIO_CFG);
++ wm97xx_reg_write(wm, AC97_GPIO_CFG, reg | WM97XX_GPIO_4);
++ }
++
++ /* wait - coord mode */
++ if (coord)
++ dig2 |= WM9712_WAIT;
++
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
++}
++
++static void wm9712_dig_enable(struct wm97xx *wm, int enable)
++{
++ u16 dig2 = wm->dig[2];
++
++ if (enable) {
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
++ dig2 | WM97XX_PRP_DET_DIG);
++ wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
++ } else
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2,
++ dig2 & ~WM97XX_PRP_DET_DIG);
++}
++
++static void wm9712_aux_prepare(struct wm97xx *wm)
++{
++ memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, 0);
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, WM97XX_PRP_DET_DIG);
++}
++
++static void wm9712_dig_restore(struct wm97xx *wm)
++{
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, wm->dig_save[1]);
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, wm->dig_save[2]);
++}
++
++static inline int is_pden(struct wm97xx *wm)
++{
++ return wm->dig[2] & WM9712_PDEN;
++}
++
++/*
++ * Read a sample from the WM9712 adc in polling mode.
++ */
++static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
++{
++ int timeout = 5 * delay;
++
++ if (!wm->pen_probably_down) {
++ u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++ if (!(data & WM97XX_PEN_DOWN))
++ return RC_PENUP;
++ wm->pen_probably_down = 1;
++ }
++
++ /* set up digitiser */
++ if (adcsel & 0x8000)
++ adcsel = ((adcsel & 0x7fff) + 3) << 12;
++
++ if (wm->mach_ops && wm->mach_ops->pre_sample)
++ wm->mach_ops->pre_sample(adcsel);
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
++ adcsel | WM97XX_POLL | WM97XX_DELAY(delay));
++
++ /* wait 3 AC97 time slots + delay for conversion */
++ poll_delay(delay);
++
++ /* wait for POLL to go low */
++ while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL)
++ && timeout) {
++ udelay(AC97_LINK_FRAME);
++ timeout--;
++ }
++
++ if (timeout <= 0) {
++ /* If PDEN is set, we can get a timeout when pen goes up */
++ if (is_pden(wm))
++ wm->pen_probably_down = 0;
++ else
++ dev_dbg(wm->dev, "adc sample timeout");
++ return RC_PENUP;
++ }
++
++ *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++ if (wm->mach_ops && wm->mach_ops->post_sample)
++ wm->mach_ops->post_sample(adcsel);
++
++ /* check we have correct sample */
++ if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) {
++ dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel,
++ *sample & WM97XX_ADCSEL_MASK);
++ return RC_PENUP;
++ }
++
++ if (!(*sample & WM97XX_PEN_DOWN)) {
++ wm->pen_probably_down = 0;
++ return RC_PENUP;
++ }
++
++ return RC_VALID;
++}
++
++/*
++ * Read a coord from the WM9712 adc in polling mode.
++ */
++static int wm9712_poll_coord(struct wm97xx *wm, struct wm97xx_data *data)
++{
++ int timeout = 5 * delay;
++
++ if (!wm->pen_probably_down) {
++ u16 data_rd = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++ if (!(data_rd & WM97XX_PEN_DOWN))
++ return RC_PENUP;
++ wm->pen_probably_down = 1;
++ }
++
++ /* set up digitiser */
++ if (wm->mach_ops && wm->mach_ops->pre_sample)
++ wm->mach_ops->pre_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
++
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1,
++ WM97XX_COO | WM97XX_POLL | WM97XX_DELAY(delay));
++
++ /* wait 3 AC97 time slots + delay for conversion and read x */
++ poll_delay(delay);
++ data->x = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++ /* wait for POLL to go low */
++ while ((wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER1) & WM97XX_POLL)
++ && timeout) {
++ udelay(AC97_LINK_FRAME);
++ timeout--;
++ }
++
++ if (timeout <= 0) {
++ /* If PDEN is set, we can get a timeout when pen goes up */
++ if (is_pden(wm))
++ wm->pen_probably_down = 0;
++ else
++ dev_dbg(wm->dev, "adc sample timeout");
++ return RC_PENUP;
++ }
++
++ /* read back y data */
++ data->y = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++ if (pil)
++ data->p = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++ else
++ data->p = DEFAULT_PRESSURE;
++
++ if (wm->mach_ops && wm->mach_ops->post_sample)
++ wm->mach_ops->post_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
++
++ /* check we have correct sample */
++ if (!(data->x & WM97XX_ADCSEL_X) || !(data->y & WM97XX_ADCSEL_Y))
++ goto err;
++ if (pil && !(data->p & WM97XX_ADCSEL_PRES))
++ goto err;
++
++ if (!(data->x & WM97XX_PEN_DOWN) || !(data->y & WM97XX_PEN_DOWN)) {
++ wm->pen_probably_down = 0;
++ return RC_PENUP;
++ }
++ return RC_VALID;
++err:
++ return 0;
++}
++
++/*
++ * Sample the WM9712 touchscreen in polling mode
++ */
++static int wm9712_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
++{
++ int rc;
++
++ if (coord) {
++ rc = wm9712_poll_coord(wm, data);
++ if (rc != RC_VALID)
++ return rc;
++ } else {
++ rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_X, &data->x);
++ if (rc != RC_VALID)
++ return rc;
++
++ rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y);
++ if (rc != RC_VALID)
++ return rc;
++
++ if (pil && !five_wire) {
++ rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_PRES,
++ &data->p);
++ if (rc != RC_VALID)
++ return rc;
++ } else
++ data->p = DEFAULT_PRESSURE;
++ }
++ return RC_VALID;
++}
++
++/*
++ * Enable WM9712 continuous mode, i.e. touch data is streamed across
++ * an AC97 slot
++ */
++static int wm9712_acc_enable(struct wm97xx *wm, int enable)
++{
++ u16 dig1, dig2;
++ int ret = 0;
++
++ dig1 = wm->dig[1];
++ dig2 = wm->dig[2];
++
++ if (enable) {
++ /* continous mode */
++ if (wm->mach_ops->acc_startup) {
++ ret = wm->mach_ops->acc_startup(wm);
++ if (ret < 0)
++ return ret;
++ }
++ dig1 &= ~(WM97XX_CM_RATE_MASK | WM97XX_ADCSEL_MASK |
++ WM97XX_DELAY_MASK | WM97XX_SLT_MASK);
++ dig1 |= WM97XX_CTC | WM97XX_COO | WM97XX_SLEN |
++ WM97XX_DELAY(delay) |
++ WM97XX_SLT(wm->acc_slot) |
++ WM97XX_RATE(wm->acc_rate);
++ if (pil)
++ dig1 |= WM97XX_ADCSEL_PRES;
++ dig2 |= WM9712_PDEN;
++ } else {
++ dig1 &= ~(WM97XX_CTC | WM97XX_COO | WM97XX_SLEN);
++ dig2 &= ~WM9712_PDEN;
++ if (wm->mach_ops->acc_shutdown)
++ wm->mach_ops->acc_shutdown(wm);
++ }
++
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, dig1);
++ wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER2, dig2);
++
++ return 0;
++}
++
++struct wm97xx_codec_drv wm9712_codec = {
++ .id = WM9712_ID2,
++ .name = "wm9712",
++ .poll_sample = wm9712_poll_sample,
++ .poll_touch = wm9712_poll_touch,
++ .acc_enable = wm9712_acc_enable,
++ .phy_init = wm9712_phy_init,
++ .dig_enable = wm9712_dig_enable,
++ .dig_restore = wm9712_dig_restore,
++ .aux_prepare = wm9712_aux_prepare,
++};
++EXPORT_SYMBOL_GPL(wm9712_codec);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood <liam.girdwood at wolfsonmicro.com>");
++MODULE_DESCRIPTION("WM9712 Touch Screen Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c
+new file mode 100644
+index 0000000..01278bd
+--- /dev/null
++++ b/drivers/input/touchscreen/wm9713.c
+@@ -0,0 +1,460 @@
++/*
++ * wm9713.c -- Codec touch driver for Wolfson WM9713 AC97 Codec.
++ *
++ * Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ * liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ * Parts Copyright : Ian Molton <spyro at f2s.com>
++ * Andrew Zabolotny <zap at homelink.ru>
++ * Russell King <rmk at arm.linux.org.uk>
++ *
++ * 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/module.h>
++#include <linux/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/input.h>
++#include <linux/delay.h>
++#include <linux/bitops.h>
++#include <linux/wm97xx.h>
++
++#define TS_NAME "wm97xx"
++#define WM9713_VERSION "1.00"
++#define DEFAULT_PRESSURE 0xb0c0
++
++/*
++ * Module parameters
++ */
++
++/*
++ * Set internal pull up for pen detect.
++ *
++ * Pull up is in the range 1.02k (least sensitive) to 64k (most sensitive)
++ * i.e. pull up resistance = 64k Ohms / rpu.
++ *
++ * Adjust this value if you are having problems with pen detect not
++ * detecting any down event.
++ */
++static int rpu = 8;
++module_param(rpu, int, 0);
++MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect.");
++
++/*
++ * Set current used for pressure measurement.
++ *
++ * Set pil = 2 to use 400uA
++ * pil = 1 to use 200uA and
++ * pil = 0 to disable pressure measurement.
++ *
++ * This is used to increase the range of values returned by the adc
++ * when measureing touchpanel pressure.
++ */
++static int pil;
++module_param(pil, int, 0);
++MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");
++
++/*
++ * Set threshold for pressure measurement.
++ *
++ * Pen down pressure below threshold is ignored.
++ */
++static int pressure = DEFAULT_PRESSURE & 0xfff;
++module_param(pressure, int, 0);
++MODULE_PARM_DESC(pressure, "Set threshold for pressure measurement.");
++
++/*
++ * Set adc sample delay.
++ *
++ * For accurate touchpanel measurements, some settling time may be
++ * required between the switch matrix applying a voltage across the
++ * touchpanel plate and the ADC sampling the signal.
++ *
++ * This delay can be set by setting delay = n, where n is the array
++ * position of the delay in the array delay_table below.
++ * Long delays > 1ms are supported for completeness, but are not
++ * recommended.
++ */
++static int delay = 4;
++module_param(delay, int, 0);
++MODULE_PARM_DESC(delay, "Set adc sample delay.");
++
++/*
++ * Set adc mask function.
++ *
++ * Sources of glitch noise, such as signals driving an LCD display, may feed
++ * through to the touch screen plates and affect measurement accuracy. In
++ * order to minimise this, a signal may be applied to the MASK pin to delay or
++ * synchronise the sampling.
++ *
++ * 0 = No delay or sync
++ * 1 = High on pin stops conversions
++ * 2 = Edge triggered, edge on pin delays conversion by delay param (above)
++ * 3 = Edge triggered, edge on pin starts conversion after delay param
++ */
++static int mask;
++module_param(mask, int, 0);
++MODULE_PARM_DESC(mask, "Set adc mask function.");
++
++/*
++ * Coordinate Polling Enable.
++ *
++ * Set to 1 to enable coordinate polling. e.g. x,y[,p] is sampled together
++ * for every poll.
++ */
++static int coord;
++module_param(coord, int, 0);
++MODULE_PARM_DESC(coord, "Polling coordinate mode");
++
++/*
++ * ADC sample delay times in uS
++ */
++static const int delay_table[] = {
++ 21, /* 1 AC97 Link frames */
++ 42, /* 2 */
++ 84, /* 4 */
++ 167, /* 8 */
++ 333, /* 16 */
++ 667, /* 32 */
++ 1000, /* 48 */
++ 1333, /* 64 */
++ 2000, /* 96 */
++ 2667, /* 128 */
++ 3333, /* 160 */
++ 4000, /* 192 */
++ 4667, /* 224 */
++ 5333, /* 256 */
++ 6000, /* 288 */
++ 0 /* No delay, switch matrix always on */
++};
++
++/*
++ * Delay after issuing a POLL command.
++ *
++ * The delay is 3 AC97 link frames + the touchpanel settling delay
++ */
++static inline void poll_delay(int d)
++{
++ udelay(3 * AC97_LINK_FRAME + delay_table[d]);
++}
++
++/*
++ * set up the physical settings of the WM9713
++ */
++static void wm9713_phy_init(struct wm97xx *wm)
++{
++ u16 dig1 = 0, dig2, dig3;
++
++ /* default values */
++ dig2 = WM97XX_DELAY(4) | WM97XX_SLT(5);
++ dig3 = WM9712_RPU(1);
++
++ /* rpu */
++ if (rpu) {
++ dig3 &= 0xffc0;
++ dig3 |= WM9712_RPU(rpu);
++ dev_info(wm->dev, "setting pen detect pull-up to %d Ohms\n",
++ 64000 / rpu);
++ }
++
++ /* touchpanel pressure */
++ if (pil == 2) {
++ dig3 |= WM9712_PIL;
++ dev_info(wm->dev,
++ "setting pressure measurement current to 400uA.");
++ } else if (pil)
++ dev_info(wm->dev,
++ "setting pressure measurement current to 200uA.");
++ if (!pil)
++ pressure = 0;
++
++ /* sample settling delay */
++ if (delay < 0 || delay > 15) {
++ dev_info(wm->dev, "supplied delay out of range.");
++ delay = 4;
++ dev_info(wm->dev, "setting adc sample delay to %d u Secs.",
++ delay_table[delay]);
++ }
++ dig2 &= 0xff0f;
++ dig2 |= WM97XX_DELAY(delay);
++
++ /* mask */
++ dig3 |= ((mask & 0x3) << 4);
++ if (coord)
++ dig3 |= WM9713_WAIT;
++
++ wm->misc = wm97xx_reg_read(wm, 0x5a);
++
++ wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1);
++ wm97xx_reg_write(wm, AC97_WM9713_DIG2, dig2);
++ wm97xx_reg_write(wm, AC97_WM9713_DIG3, dig3);
++ wm97xx_reg_write(wm, AC97_GPIO_STICKY, 0x0);
++}
++
++static void wm9713_dig_enable(struct wm97xx *wm, int enable)
++{
++ u16 val;
++
++ if (enable) {
++ val = wm97xx_reg_read(wm, AC97_EXTENDED_MID);
++ wm97xx_reg_write(wm, AC97_EXTENDED_MID, val & 0x7fff);
++ wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2] |
++ WM97XX_PRP_DET_DIG);
++ wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); /* dummy read */
++ } else {
++ wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2] &
++ ~WM97XX_PRP_DET_DIG);
++ val = wm97xx_reg_read(wm, AC97_EXTENDED_MID);
++ wm97xx_reg_write(wm, AC97_EXTENDED_MID, val | 0x8000);
++ }
++}
++
++static void wm9713_dig_restore(struct wm97xx *wm)
++{
++ wm97xx_reg_write(wm, AC97_WM9713_DIG1, wm->dig_save[0]);
++ wm97xx_reg_write(wm, AC97_WM9713_DIG2, wm->dig_save[1]);
++ wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig_save[2]);
++}
++
++static void wm9713_aux_prepare(struct wm97xx *wm)
++{
++ memcpy(wm->dig_save, wm->dig, sizeof(wm->dig));
++ wm97xx_reg_write(wm, AC97_WM9713_DIG1, 0);
++ wm97xx_reg_write(wm, AC97_WM9713_DIG2, 0);
++ wm97xx_reg_write(wm, AC97_WM9713_DIG3, WM97XX_PRP_DET_DIG);
++}
++
++static inline int is_pden(struct wm97xx *wm)
++{
++ return wm->dig[2] & WM9713_PDEN;
++}
++
++/*
++ * Read a sample from the WM9713 adc in polling mode.
++ */
++static int wm9713_poll_sample(struct wm97xx *wm, int adcsel, int *sample)
++{
++ u16 dig1;
++ int timeout = 5 * delay;
++
++ if (!wm->pen_probably_down) {
++ u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++ if (!(data & WM97XX_PEN_DOWN))
++ return RC_PENUP;
++ wm->pen_probably_down = 1;
++ }
++
++ /* set up digitiser */
++ if (adcsel & 0x8000)
++ adcsel = 1 << ((adcsel & 0x7fff) + 3);
++
++ dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1);
++ dig1 &= ~WM9713_ADCSEL_MASK;
++
++ if (wm->mach_ops && wm->mach_ops->pre_sample)
++ wm->mach_ops->pre_sample(adcsel);
++ wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1 | adcsel | WM9713_POLL);
++
++ /* wait 3 AC97 time slots + delay for conversion */
++ poll_delay(delay);
++
++ /* wait for POLL to go low */
++ while ((wm97xx_reg_read(wm, AC97_WM9713_DIG1) & WM9713_POLL) &&
++ timeout) {
++ udelay(AC97_LINK_FRAME);
++ timeout--;
++ }
++
++ if (timeout <= 0) {
++ /* If PDEN is set, we can get a timeout when pen goes up */
++ if (is_pden(wm))
++ wm->pen_probably_down = 0;
++ else
++ dev_dbg(wm->dev, "adc sample timeout");
++ return RC_PENUP;
++ }
++
++ *sample = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++ if (wm->mach_ops && wm->mach_ops->post_sample)
++ wm->mach_ops->post_sample(adcsel);
++
++ /* check we have correct sample */
++ if ((*sample & WM97XX_ADCSRC_MASK) != ffs(adcsel >> 1) << 12) {
++ dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel,
++ *sample & WM97XX_ADCSRC_MASK);
++ return RC_PENUP;
++ }
++
++ if (!(*sample & WM97XX_PEN_DOWN)) {
++ wm->pen_probably_down = 0;
++ return RC_PENUP;
++ }
++
++ return RC_VALID;
++}
++
++/*
++ * Read a coordinate from the WM9713 adc in polling mode.
++ */
++static int wm9713_poll_coord(struct wm97xx *wm, struct wm97xx_data *data)
++{
++ u16 dig1;
++ int timeout = 5 * delay;
++
++ if (!wm->pen_probably_down) {
++ u16 val = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++ if (!(val & WM97XX_PEN_DOWN))
++ return RC_PENUP;
++ wm->pen_probably_down = 1;
++ }
++
++ /* set up digitiser */
++ dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1);
++ dig1 &= ~WM9713_ADCSEL_MASK;
++ if (pil)
++ dig1 |= WM9713_ADCSEL_PRES;
++
++ if (wm->mach_ops && wm->mach_ops->pre_sample)
++ wm->mach_ops->pre_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
++ wm97xx_reg_write(wm, AC97_WM9713_DIG1,
++ dig1 | WM9713_POLL | WM9713_COO);
++
++ /* wait 3 AC97 time slots + delay for conversion */
++ poll_delay(delay);
++ data->x = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++ /* wait for POLL to go low */
++ while ((wm97xx_reg_read(wm, AC97_WM9713_DIG1) & WM9713_POLL)
++ && timeout) {
++ udelay(AC97_LINK_FRAME);
++ timeout--;
++ }
++
++ if (timeout <= 0) {
++ /* If PDEN is set, we can get a timeout when pen goes up */
++ if (is_pden(wm))
++ wm->pen_probably_down = 0;
++ else
++ dev_dbg(wm->dev, "adc sample timeout");
++ return RC_PENUP;
++ }
++
++ /* read back data */
++ data->y = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++ if (pil)
++ data->p = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD);
++ else
++ data->p = DEFAULT_PRESSURE;
++
++ if (wm->mach_ops && wm->mach_ops->post_sample)
++ wm->mach_ops->post_sample(WM97XX_ADCSEL_X | WM97XX_ADCSEL_Y);
++
++ /* check we have correct sample */
++ if (!(data->x & WM97XX_ADCSEL_X) || !(data->y & WM97XX_ADCSEL_Y))
++ goto err;
++ if (pil && !(data->p & WM97XX_ADCSEL_PRES))
++ goto err;
++
++ if (!(data->x & WM97XX_PEN_DOWN) || !(data->y & WM97XX_PEN_DOWN)) {
++ wm->pen_probably_down = 0;
++ return RC_PENUP;
++ }
++ return RC_VALID;
++err:
++ return 0;
++}
++
++/*
++ * Sample the WM9713 touchscreen in polling mode
++ */
++static int wm9713_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
++{
++ int rc;
++
++ if (coord) {
++ rc = wm9713_poll_coord(wm, data);
++ if (rc != RC_VALID)
++ return rc;
++ } else {
++ rc = wm9713_poll_sample(wm, WM9713_ADCSEL_X, &data->x);
++ if (rc != RC_VALID)
++ return rc;
++ rc = wm9713_poll_sample(wm, WM9713_ADCSEL_Y, &data->y);
++ if (rc != RC_VALID)
++ return rc;
++ if (pil) {
++ rc = wm9713_poll_sample(wm, WM9713_ADCSEL_PRES,
++ &data->p);
++ if (rc != RC_VALID)
++ return rc;
++ } else
++ data->p = DEFAULT_PRESSURE;
++ }
++ return RC_VALID;
++}
++
++/*
++ * Enable WM9713 continuous mode, i.e. touch data is streamed across
++ * an AC97 slot
++ */
++static int wm9713_acc_enable(struct wm97xx *wm, int enable)
++{
++ u16 dig1, dig2, dig3;
++ int ret = 0;
++
++ dig1 = wm->dig[0];
++ dig2 = wm->dig[1];
++ dig3 = wm->dig[2];
++
++ if (enable) {
++ /* continous mode */
++ if (wm->mach_ops->acc_startup &&
++ (ret = wm->mach_ops->acc_startup(wm)) < 0)
++ return ret;
++
++ dig1 &= ~WM9713_ADCSEL_MASK;
++ dig1 |= WM9713_CTC | WM9713_COO | WM9713_ADCSEL_X |
++ WM9713_ADCSEL_Y;
++ if (pil)
++ dig1 |= WM9713_ADCSEL_PRES;
++ dig2 &= ~(WM97XX_DELAY_MASK | WM97XX_SLT_MASK |
++ WM97XX_CM_RATE_MASK);
++ dig2 |= WM97XX_SLEN | WM97XX_DELAY(delay) |
++ WM97XX_SLT(wm->acc_slot) | WM97XX_RATE(wm->acc_rate);
++ dig3 |= WM9713_PDEN;
++ } else {
++ dig1 &= ~(WM9713_CTC | WM9713_COO);
++ dig2 &= ~WM97XX_SLEN;
++ dig3 &= ~WM9713_PDEN;
++ if (wm->mach_ops->acc_shutdown)
++ wm->mach_ops->acc_shutdown(wm);
++ }
++
++ wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1);
++ wm97xx_reg_write(wm, AC97_WM9713_DIG2, dig2);
++ wm97xx_reg_write(wm, AC97_WM9713_DIG3, dig3);
++
++ return ret;
++}
++
++struct wm97xx_codec_drv wm9713_codec = {
++ .id = WM9713_ID2,
++ .name = "wm9713",
++ .poll_sample = wm9713_poll_sample,
++ .poll_touch = wm9713_poll_touch,
++ .acc_enable = wm9713_acc_enable,
++ .phy_init = wm9713_phy_init,
++ .dig_enable = wm9713_dig_enable,
++ .dig_restore = wm9713_dig_restore,
++ .aux_prepare = wm9713_aux_prepare,
++};
++EXPORT_SYMBOL_GPL(wm9713_codec);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood <liam.girdwood at wolfsonmicro.com>");
++MODULE_DESCRIPTION("WM9713 Touch Screen Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
+new file mode 100644
+index 0000000..e9c7ea4
+--- /dev/null
++++ b/drivers/input/touchscreen/wm97xx-core.c
+@@ -0,0 +1,829 @@
++/*
++ * wm97xx-core.c -- Touch screen driver core for Wolfson WM9705, WM9712
++ * and WM9713 AC97 Codecs.
++ *
++ * Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ * liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.com
++ * Parts Copyright : Ian Molton <spyro at f2s.com>
++ * Andrew Zabolotny <zap at homelink.ru>
++ * Russell King <rmk at arm.linux.org.uk>
++ *
++ * 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.
++ *
++ * Notes:
++ *
++ * Features:
++ * - supports WM9705, WM9712, WM9713
++ * - polling mode
++ * - continuous mode (arch-dependent)
++ * - adjustable rpu/dpp settings
++ * - adjustable pressure current
++ * - adjustable sample settle delay
++ * - 4 and 5 wire touchscreens (5 wire is WM9712 only)
++ * - pen down detection
++ * - battery monitor
++ * - sample AUX adcs
++ * - power management
++ * - codec GPIO
++ * - codec event notification
++ * Todo
++ * - Support for async sampling control for noisy LCDs.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/string.h>
++#include <linux/proc_fs.h>
++#include <linux/pm.h>
++#include <linux/interrupt.h>
++#include <linux/bitops.h>
++#include <linux/workqueue.h>
++#include <linux/wm97xx.h>
++#include <linux/uaccess.h>
++#include <linux/io.h>
++
++#define TS_NAME "wm97xx"
++#define WM_CORE_VERSION "1.00"
++#define DEFAULT_PRESSURE 0xb0c0
++
++
++/*
++ * Touchscreen absolute values
++ *
++ * These parameters are used to help the input layer discard out of
++ * range readings and reduce jitter etc.
++ *
++ * o min, max:- indicate the min and max values your touch screen returns
++ * o fuzz:- use a higher number to reduce jitter
++ *
++ * The default values correspond to Mainstone II in QVGA mode
++ *
++ * Please read
++ * Documentation/input/input-programming.txt for more details.
++ */
++
++static int abs_x[3] = {350, 3900, 5};
++module_param_array(abs_x, int, NULL, 0);
++MODULE_PARM_DESC(abs_x, "Touchscreen absolute X min, max, fuzz");
++
++static int abs_y[3] = {320, 3750, 40};
++module_param_array(abs_y, int, NULL, 0);
++MODULE_PARM_DESC(abs_y, "Touchscreen absolute Y min, max, fuzz");
++
++static int abs_p[3] = {0, 150, 4};
++module_param_array(abs_p, int, NULL, 0);
++MODULE_PARM_DESC(abs_p, "Touchscreen absolute Pressure min, max, fuzz");
++
++/*
++ * wm97xx IO access, all IO locking done by AC97 layer
++ */
++int wm97xx_reg_read(struct wm97xx *wm, u16 reg)
++{
++ if (wm->ac97)
++ return wm->ac97->bus->ops->read(wm->ac97, reg);
++ else
++ return -1;
++}
++EXPORT_SYMBOL_GPL(wm97xx_reg_read);
++
++void wm97xx_reg_write(struct wm97xx *wm, u16 reg, u16 val)
++{
++ /* cache digitiser registers */
++ if (reg >= AC97_WM9713_DIG1 && reg <= AC97_WM9713_DIG3)
++ wm->dig[(reg - AC97_WM9713_DIG1) >> 1] = val;
++
++ /* cache gpio regs */
++ if (reg >= AC97_GPIO_CFG && reg <= AC97_MISC_AFE)
++ wm->gpio[(reg - AC97_GPIO_CFG) >> 1] = val;
++
++ /* wm9713 irq reg */
++ if (reg == 0x5a)
++ wm->misc = val;
++
++ if (wm->ac97)
++ wm->ac97->bus->ops->write(wm->ac97, reg, val);
++}
++EXPORT_SYMBOL_GPL(wm97xx_reg_write);
++
++/**
++ * wm97xx_read_aux_adc - Read the aux adc.
++ * @wm: wm97xx device.
++ * @adcsel: codec ADC to be read
++ *
++ * Reads the selected AUX ADC.
++ */
++
++int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel)
++{
++ int power_adc = 0, auxval;
++ u16 power = 0;
++
++ /* get codec */
++ mutex_lock(&wm->codec_mutex);
++
++ /* When the touchscreen is not in use, we may have to power up
++ * the AUX ADC before we can use sample the AUX inputs->
++ */
++ if (wm->id == WM9713_ID2 &&
++ (power = wm97xx_reg_read(wm, AC97_EXTENDED_MID)) & 0x8000) {
++ power_adc = 1;
++ wm97xx_reg_write(wm, AC97_EXTENDED_MID, power & 0x7fff);
++ }
++
++ /* Prepare the codec for AUX reading */
++ wm->codec->aux_prepare(wm);
++
++ /* Turn polling mode on to read AUX ADC */
++ wm->pen_probably_down = 1;
++ wm->codec->poll_sample(wm, adcsel, &auxval);
++
++ if (power_adc)
++ wm97xx_reg_write(wm, AC97_EXTENDED_MID, power | 0x8000);
++
++ wm->codec->dig_restore(wm);
++
++ wm->pen_probably_down = 0;
++
++ mutex_unlock(&wm->codec_mutex);
++ return auxval & 0xfff;
++}
++EXPORT_SYMBOL_GPL(wm97xx_read_aux_adc);
++
++/**
++ * wm97xx_get_gpio - Get the status of a codec GPIO.
++ * @wm: wm97xx device.
++ * @gpio: gpio
++ *
++ * Get the status of a codec GPIO pin
++ */
++
++enum wm97xx_gpio_status wm97xx_get_gpio(struct wm97xx *wm, u32 gpio)
++{
++ u16 status;
++ enum wm97xx_gpio_status ret;
++
++ mutex_lock(&wm->codec_mutex);
++ status = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
++
++ if (status & gpio)
++ ret = WM97XX_GPIO_HIGH;
++ else
++ ret = WM97XX_GPIO_LOW;
++
++ mutex_unlock(&wm->codec_mutex);
++ return ret;
++}
++EXPORT_SYMBOL_GPL(wm97xx_get_gpio);
++
++/**
++ * wm97xx_set_gpio - Set the status of a codec GPIO.
++ * @wm: wm97xx device.
++ * @gpio: gpio
++ *
++ *
++ * Set the status of a codec GPIO pin
++ */
++
++void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio,
++ enum wm97xx_gpio_status status)
++{
++ u16 reg;
++
++ mutex_lock(&wm->codec_mutex);
++ reg = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
++
++ if (status & WM97XX_GPIO_HIGH)
++ reg |= gpio;
++ else
++ reg &= ~gpio;
++
++ if (wm->id == WM9712_ID2)
++ wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg << 1);
++ else
++ wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg);
++ mutex_unlock(&wm->codec_mutex);
++}
++EXPORT_SYMBOL_GPL(wm97xx_set_gpio);
++
++/*
++ * Codec GPIO pin configuration, this sets pin direction, polarity,
++ * stickyness and wake up.
++ */
++void wm97xx_config_gpio(struct wm97xx *wm, u32 gpio, enum wm97xx_gpio_dir dir,
++ enum wm97xx_gpio_pol pol, enum wm97xx_gpio_sticky sticky,
++ enum wm97xx_gpio_wake wake)
++{
++ u16 reg;
++
++ mutex_lock(&wm->codec_mutex);
++ reg = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
++
++ if (pol == WM97XX_GPIO_POL_HIGH)
++ reg |= gpio;
++ else
++ reg &= ~gpio;
++
++ wm97xx_reg_write(wm, AC97_GPIO_POLARITY, reg);
++ reg = wm97xx_reg_read(wm, AC97_GPIO_STICKY);
++
++ if (sticky == WM97XX_GPIO_STICKY)
++ reg |= gpio;
++ else
++ reg &= ~gpio;
++
++ wm97xx_reg_write(wm, AC97_GPIO_STICKY, reg);
++ reg = wm97xx_reg_read(wm, AC97_GPIO_WAKEUP);
++
++ if (wake == WM97XX_GPIO_WAKE)
++ reg |= gpio;
++ else
++ reg &= ~gpio;
++
++ wm97xx_reg_write(wm, AC97_GPIO_WAKEUP, reg);
++ reg = wm97xx_reg_read(wm, AC97_GPIO_CFG);
++
++ if (dir == WM97XX_GPIO_IN)
++ reg |= gpio;
++ else
++ reg &= ~gpio;
++
++ wm97xx_reg_write(wm, AC97_GPIO_CFG, reg);
++ mutex_unlock(&wm->codec_mutex);
++}
++EXPORT_SYMBOL_GPL(wm97xx_config_gpio);
++
++/*
++ * Configure the WM97XX_PRP value to use while system is suspended.
++ * If a value other than 0 is set then WM97xx pen detection will be
++ * left enabled in the configured mode while the system is in suspend,
++ * the device has users and suspend has not been disabled via the
++ * wakeup sysfs entries.
++ *
++ * @wm: WM97xx device to configure
++ * @mode: WM97XX_PRP value to configure while suspended
++ */
++void wm97xx_set_suspend_mode(struct wm97xx *wm, u16 mode)
++{
++ wm->suspend_mode = mode;
++ device_init_wakeup(&wm->input_dev->dev, mode != 0);
++}
++EXPORT_SYMBOL_GPL(wm97xx_set_suspend_mode);
++
++/*
++ * Handle a pen down interrupt.
++ */
++static void wm97xx_pen_irq_worker(struct work_struct *work)
++{
++ struct wm97xx *wm = container_of(work, struct wm97xx, pen_event_work);
++ int pen_was_down = wm->pen_is_down;
++
++ /* do we need to enable the touch panel reader */
++ if (wm->id == WM9705_ID2) {
++ if (wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD) &
++ WM97XX_PEN_DOWN)
++ wm->pen_is_down = 1;
++ else
++ wm->pen_is_down = 0;
++ } else {
++ u16 status, pol;
++ mutex_lock(&wm->codec_mutex);
++ status = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
++ pol = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
++
++ if (WM97XX_GPIO_13 & pol & status) {
++ wm->pen_is_down = 1;
++ wm97xx_reg_write(wm, AC97_GPIO_POLARITY, pol &
++ ~WM97XX_GPIO_13);
++ } else {
++ wm->pen_is_down = 0;
++ wm97xx_reg_write(wm, AC97_GPIO_POLARITY, pol |
++ WM97XX_GPIO_13);
++ }
++
++ if (wm->id == WM9712_ID2)
++ wm97xx_reg_write(wm, AC97_GPIO_STATUS, (status &
++ ~WM97XX_GPIO_13) << 1);
++ else
++ wm97xx_reg_write(wm, AC97_GPIO_STATUS, status &
++ ~WM97XX_GPIO_13);
++ mutex_unlock(&wm->codec_mutex);
++ }
++
++ /* If the system is not using continuous mode or it provides a
++ * pen down operation then we need to schedule polls while the
++ * pen is down. Otherwise the machine driver is responsible
++ * for scheduling reads.
++ */
++ if (!wm->mach_ops->acc_enabled || wm->mach_ops->acc_pen_down) {
++ if (wm->pen_is_down && !pen_was_down) {
++ /* Data is not availiable immediately on pen down */
++ queue_delayed_work(wm->ts_workq, &wm->ts_reader, 1);
++ }
++
++ /* Let ts_reader report the pen up for debounce. */
++ if (!wm->pen_is_down && pen_was_down)
++ wm->pen_is_down = 1;
++ }
++
++ if (!wm->pen_is_down && wm->mach_ops->acc_enabled)
++ wm->mach_ops->acc_pen_up(wm);
++
++ wm->mach_ops->irq_enable(wm, 1);
++}
++
++/*
++ * Codec PENDOWN irq handler
++ *
++ * We have to disable the codec interrupt in the handler because it
++ * can take upto 1ms to clear the interrupt source. We schedule a task
++ * in a work queue to do the actual interaction with the chip. The
++ * interrupt is then enabled again in the slow handler when the source
++ * has been cleared.
++ */
++static irqreturn_t wm97xx_pen_interrupt(int irq, void *dev_id)
++{
++ struct wm97xx *wm = dev_id;
++
++ if (!work_pending(&wm->pen_event_work)) {
++ wm->mach_ops->irq_enable(wm, 0);
++ queue_work(wm->ts_workq, &wm->pen_event_work);
++ }
++
++ return IRQ_HANDLED;
++}
++
++/*
++ * initialise pen IRQ handler and workqueue
++ */
++static int wm97xx_init_pen_irq(struct wm97xx *wm)
++{
++ u16 reg;
++
++ /* If an interrupt is supplied an IRQ enable operation must also be
++ * provided. */
++ BUG_ON(!wm->mach_ops->irq_enable);
++
++ if (request_irq(wm->pen_irq, wm97xx_pen_interrupt,
++ IRQF_SHARED | IRQF_SAMPLE_RANDOM,
++ "wm97xx-pen", wm)) {
++ dev_err(wm->dev,
++ "Failed to register pen down interrupt, polling");
++ wm->pen_irq = 0;
++ return -EINVAL;
++ }
++
++ /* Configure GPIO as interrupt source on WM971x */
++ if (wm->id != WM9705_ID2) {
++ BUG_ON(!wm->mach_ops->irq_gpio);
++ reg = wm97xx_reg_read(wm, AC97_MISC_AFE);
++ wm97xx_reg_write(wm, AC97_MISC_AFE,
++ reg & ~(wm->mach_ops->irq_gpio));
++ reg = wm97xx_reg_read(wm, 0x5a);
++ wm97xx_reg_write(wm, 0x5a, reg & ~0x0001);
++ }
++
++ return 0;
++}
++
++static int wm97xx_read_samples(struct wm97xx *wm)
++{
++ struct wm97xx_data data;
++ int rc;
++
++ mutex_lock(&wm->codec_mutex);
++
++ if (wm->mach_ops && wm->mach_ops->acc_enabled)
++ rc = wm->mach_ops->acc_pen_down(wm);
++ else
++ rc = wm->codec->poll_touch(wm, &data);
++
++ if (rc & RC_PENUP) {
++ if (wm->pen_is_down) {
++ wm->pen_is_down = 0;
++ dev_dbg(wm->dev, "pen up\n");
++ input_report_abs(wm->input_dev, ABS_PRESSURE, 0);
++ input_sync(wm->input_dev);
++ } else if (!(rc & RC_AGAIN)) {
++ /* We need high frequency updates only while
++ * pen is down, the user never will be able to
++ * touch screen faster than a few times per
++ * second... On the other hand, when the user
++ * is actively working with the touchscreen we
++ * don't want to lose the quick response. So we
++ * will slowly increase sleep time after the
++ * pen is up and quicky restore it to ~one task
++ * switch when pen is down again.
++ */
++ if (wm->ts_reader_interval < HZ / 10)
++ wm->ts_reader_interval++;
++ }
++
++ } else if (rc & RC_VALID) {
++ dev_dbg(wm->dev,
++ "pen down: x=%x:%d, y=%x:%d, pressure=%x:%d\n",
++ data.x >> 12, data.x & 0xfff, data.y >> 12,
++ data.y & 0xfff, data.p >> 12, data.p & 0xfff);
++ input_report_abs(wm->input_dev, ABS_X, data.x & 0xfff);
++ input_report_abs(wm->input_dev, ABS_Y, data.y & 0xfff);
++ input_report_abs(wm->input_dev, ABS_PRESSURE, data.p & 0xfff);
++ input_sync(wm->input_dev);
++ wm->pen_is_down = 1;
++ wm->ts_reader_interval = wm->ts_reader_min_interval;
++ } else if (rc & RC_PENDOWN) {
++ dev_dbg(wm->dev, "pen down\n");
++ wm->pen_is_down = 1;
++ wm->ts_reader_interval = wm->ts_reader_min_interval;
++ }
++
++ mutex_unlock(&wm->codec_mutex);
++ return rc;
++}
++
++/*
++* The touchscreen sample reader.
++*/
++static void wm97xx_ts_reader(struct work_struct *work)
++{
++ int rc;
++ struct wm97xx *wm = container_of(work, struct wm97xx, ts_reader.work);
++
++ BUG_ON(!wm->codec);
++
++ do {
++ rc = wm97xx_read_samples(wm);
++ } while (rc & RC_AGAIN);
++
++ if (wm->pen_is_down || !wm->pen_irq)
++ queue_delayed_work(wm->ts_workq, &wm->ts_reader,
++ wm->ts_reader_interval);
++}
++
++/**
++ * wm97xx_ts_input_open - Open the touch screen input device.
++ * @idev: Input device to be opened.
++ *
++ * Called by the input sub system to open a wm97xx touchscreen device.
++ * Starts the touchscreen thread and touch digitiser.
++ */
++static int wm97xx_ts_input_open(struct input_dev *idev)
++{
++ struct wm97xx *wm = input_get_drvdata(idev);
++
++ wm->ts_workq = create_singlethread_workqueue("kwm97xx");
++ if (wm->ts_workq == NULL) {
++ dev_err(wm->dev,
++ "Failed to create workqueue\n");
++ return -EINVAL;
++ }
++
++ /* start digitiser */
++ if (wm->mach_ops && wm->mach_ops->acc_enabled)
++ wm->codec->acc_enable(wm, 1);
++ wm->codec->dig_enable(wm, 1);
++
++ INIT_DELAYED_WORK(&wm->ts_reader, wm97xx_ts_reader);
++ INIT_WORK(&wm->pen_event_work, wm97xx_pen_irq_worker);
++
++ wm->ts_reader_min_interval = HZ >= 100 ? HZ / 100 : 1;
++ if (wm->ts_reader_min_interval < 1)
++ wm->ts_reader_min_interval = 1;
++ wm->ts_reader_interval = wm->ts_reader_min_interval;
++
++ wm->pen_is_down = 0;
++ if (wm->pen_irq)
++ wm97xx_init_pen_irq(wm);
++ else
++ dev_err(wm->dev, "No IRQ specified\n");
++
++ /* If we either don't have an interrupt for pen down events or
++ * failed to acquire it then we need to poll.
++ */
++ if (wm->pen_irq == 0)
++ queue_delayed_work(wm->ts_workq, &wm->ts_reader,
++ wm->ts_reader_interval);
++
++ return 0;
++}
++
++/**
++ * wm97xx_ts_input_close - Close the touch screen input device.
++ * @idev: Input device to be closed.
++ *
++ * Called by the input sub system to close a wm97xx touchscreen
++ * device. Kills the touchscreen thread and stops the touch
++ * digitiser.
++ */
++
++static void wm97xx_ts_input_close(struct input_dev *idev)
++{
++ struct wm97xx *wm = input_get_drvdata(idev);
++ u16 reg;
++
++ if (wm->pen_irq) {
++ /* Return the interrupt to GPIO usage (disabling it) */
++ if (wm->id != WM9705_ID2) {
++ BUG_ON(!wm->mach_ops->irq_gpio);
++ reg = wm97xx_reg_read(wm, AC97_MISC_AFE);
++ wm97xx_reg_write(wm, AC97_MISC_AFE,
++ reg | wm->mach_ops->irq_gpio);
++ }
++
++ free_irq(wm->pen_irq, wm);
++ }
++
++ wm->pen_is_down = 0;
++
++ /* Balance out interrupt disables/enables */
++ if (cancel_work_sync(&wm->pen_event_work))
++ wm->mach_ops->irq_enable(wm, 1);
++
++ /* ts_reader rearms itself so we need to explicitly stop it
++ * before we destroy the workqueue.
++ */
++ cancel_delayed_work_sync(&wm->ts_reader);
++
++ destroy_workqueue(wm->ts_workq);
++
++ /* stop digitiser */
++ wm->codec->dig_enable(wm, 0);
++ if (wm->mach_ops && wm->mach_ops->acc_enabled)
++ wm->codec->acc_enable(wm, 0);
++}
++
++static int wm97xx_probe(struct device *dev)
++{
++ struct wm97xx *wm;
++ int ret = 0, id = 0;
++
++ wm = kzalloc(sizeof(struct wm97xx), GFP_KERNEL);
++ if (!wm)
++ return -ENOMEM;
++ mutex_init(&wm->codec_mutex);
++
++ wm->dev = dev;
++ dev->driver_data = wm;
++ wm->ac97 = to_ac97_t(dev);
++
++ /* check that we have a supported codec */
++ id = wm97xx_reg_read(wm, AC97_VENDOR_ID1);
++ if (id != WM97XX_ID1) {
++ dev_err(dev, "Device with vendor %04x is not a wm97xx\n", id);
++ ret = -ENODEV;
++ goto alloc_err;
++ }
++
++ wm->id = wm97xx_reg_read(wm, AC97_VENDOR_ID2);
++
++ dev_info(wm->dev, "detected a wm97%02x codec\n", wm->id & 0xff);
++
++ switch (wm->id & 0xff) {
++#ifdef CONFIG_TOUCHSCREEN_WM9705
++ case 0x05:
++ wm->codec = &wm9705_codec;
++ break;
++#endif
++#ifdef CONFIG_TOUCHSCREEN_WM9712
++ case 0x12:
++ wm->codec = &wm9712_codec;
++ break;
++#endif
++#ifdef CONFIG_TOUCHSCREEN_WM9713
++ case 0x13:
++ wm->codec = &wm9713_codec;
++ break;
++#endif
++ default:
++ dev_err(wm->dev, "Support for wm97%02x not compiled in.\n",
++ wm->id & 0xff);
++ ret = -ENODEV;
++ goto alloc_err;
++ }
++
++ wm->input_dev = input_allocate_device();
++ if (wm->input_dev == NULL) {
++ ret = -ENOMEM;
++ goto alloc_err;
++ }
++
++ /* set up touch configuration */
++ wm->input_dev->name = "wm97xx touchscreen";
++ wm->input_dev->open = wm97xx_ts_input_open;
++ wm->input_dev->close = wm97xx_ts_input_close;
++ set_bit(EV_ABS, wm->input_dev->evbit);
++ set_bit(ABS_X, wm->input_dev->absbit);
++ set_bit(ABS_Y, wm->input_dev->absbit);
++ set_bit(ABS_PRESSURE, wm->input_dev->absbit);
++ input_set_abs_params(wm->input_dev, ABS_X, abs_x[0], abs_x[1],
++ abs_x[2], 0);
++ input_set_abs_params(wm->input_dev, ABS_Y, abs_y[0], abs_y[1],
++ abs_y[2], 0);
++ input_set_abs_params(wm->input_dev, ABS_PRESSURE, abs_p[0], abs_p[1],
++ abs_p[2], 0);
++ input_set_drvdata(wm->input_dev, wm);
++ wm->input_dev->dev.parent = dev;
++ ret = input_register_device(wm->input_dev);
++ if (ret < 0)
++ goto dev_alloc_err;
++
++ /* set up physical characteristics */
++ wm->codec->phy_init(wm);
++
++ /* load gpio cache */
++ wm->gpio[0] = wm97xx_reg_read(wm, AC97_GPIO_CFG);
++ wm->gpio[1] = wm97xx_reg_read(wm, AC97_GPIO_POLARITY);
++ wm->gpio[2] = wm97xx_reg_read(wm, AC97_GPIO_STICKY);
++ wm->gpio[3] = wm97xx_reg_read(wm, AC97_GPIO_WAKEUP);
++ wm->gpio[4] = wm97xx_reg_read(wm, AC97_GPIO_STATUS);
++ wm->gpio[5] = wm97xx_reg_read(wm, AC97_MISC_AFE);
++
++ /* register our battery device */
++ wm->battery_dev = platform_device_alloc("wm97xx-battery", -1);
++ if (!wm->battery_dev) {
++ ret = -ENOMEM;
++ goto batt_err;
++ }
++ platform_set_drvdata(wm->battery_dev, wm);
++ wm->battery_dev->dev.parent = dev;
++ ret = platform_device_add(wm->battery_dev);
++ if (ret < 0)
++ goto batt_reg_err;
++
++ /* register our extended touch device (for machine specific
++ * extensions) */
++ wm->touch_dev = platform_device_alloc("wm97xx-touch", -1);
++ if (!wm->touch_dev) {
++ ret = -ENOMEM;
++ goto touch_err;
++ }
++ platform_set_drvdata(wm->touch_dev, wm);
++ wm->touch_dev->dev.parent = dev;
++ ret = platform_device_add(wm->touch_dev);
++ if (ret < 0)
++ goto touch_reg_err;
++
++ return ret;
++
++ touch_reg_err:
++ platform_device_put(wm->touch_dev);
++ touch_err:
++ platform_device_unregister(wm->battery_dev);
++ wm->battery_dev = NULL;
++ batt_reg_err:
++ platform_device_put(wm->battery_dev);
++ batt_err:
++ input_unregister_device(wm->input_dev);
++ wm->input_dev = NULL;
++ dev_alloc_err:
++ input_free_device(wm->input_dev);
++ alloc_err:
++ kfree(wm);
++
++ return ret;
++}
++
++static int wm97xx_remove(struct device *dev)
++{
++ struct wm97xx *wm = dev_get_drvdata(dev);
++
++ platform_device_unregister(wm->battery_dev);
++ platform_device_unregister(wm->touch_dev);
++ input_unregister_device(wm->input_dev);
++ kfree(wm);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int wm97xx_suspend(struct device *dev, pm_message_t state)
++{
++ struct wm97xx *wm = dev_get_drvdata(dev);
++ u16 reg;
++ int suspend_mode;
++
++ if (device_may_wakeup(&wm->input_dev->dev))
++ suspend_mode = wm->suspend_mode;
++ else
++ suspend_mode = 0;
++
++ if (wm->input_dev->users)
++ cancel_delayed_work_sync(&wm->ts_reader);
++
++ /* Power down the digitiser (bypassing the cache for resume) */
++ reg = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER2);
++ reg &= ~WM97XX_PRP_DET_DIG;
++ if (wm->input_dev->users)
++ reg |= suspend_mode;
++ wm->ac97->bus->ops->write(wm->ac97, AC97_WM97XX_DIGITISER2, reg);
++
++ /* WM9713 has an additional power bit - turn it off if there
++ * are no users or if suspend mode is zero. */
++ if (wm->id == WM9713_ID2 &&
++ (!wm->input_dev->users || !suspend_mode)) {
++ reg = wm97xx_reg_read(wm, AC97_EXTENDED_MID) | 0x8000;
++ wm97xx_reg_write(wm, AC97_EXTENDED_MID, reg);
++ }
++
++ return 0;
++}
++
++static int wm97xx_resume(struct device *dev)
++{
++ struct wm97xx *wm = dev_get_drvdata(dev);
++
++ /* restore digitiser and gpios */
++ if (wm->id == WM9713_ID2) {
++ wm97xx_reg_write(wm, AC97_WM9713_DIG1, wm->dig[0]);
++ wm97xx_reg_write(wm, 0x5a, wm->misc);
++ if (wm->input_dev->users) {
++ u16 reg;
++ reg = wm97xx_reg_read(wm, AC97_EXTENDED_MID) & 0x7fff;
++ wm97xx_reg_write(wm, AC97_EXTENDED_MID, reg);
++ }
++ }
++
++ wm97xx_reg_write(wm, AC97_WM9713_DIG2, wm->dig[1]);
++ wm97xx_reg_write(wm, AC97_WM9713_DIG3, wm->dig[2]);
++
++ wm97xx_reg_write(wm, AC97_GPIO_CFG, wm->gpio[0]);
++ wm97xx_reg_write(wm, AC97_GPIO_POLARITY, wm->gpio[1]);
++ wm97xx_reg_write(wm, AC97_GPIO_STICKY, wm->gpio[2]);
++ wm97xx_reg_write(wm, AC97_GPIO_WAKEUP, wm->gpio[3]);
++ wm97xx_reg_write(wm, AC97_GPIO_STATUS, wm->gpio[4]);
++ wm97xx_reg_write(wm, AC97_MISC_AFE, wm->gpio[5]);
++
++ if (wm->input_dev->users && !wm->pen_irq) {
++ wm->ts_reader_interval = wm->ts_reader_min_interval;
++ queue_delayed_work(wm->ts_workq, &wm->ts_reader,
++ wm->ts_reader_interval);
++ }
++
++ return 0;
++}
++
++#else
++#define wm97xx_suspend NULL
++#define wm97xx_resume NULL
++#endif
++
++/*
++ * Machine specific operations
++ */
++int wm97xx_register_mach_ops(struct wm97xx *wm,
++ struct wm97xx_mach_ops *mach_ops)
++{
++ mutex_lock(&wm->codec_mutex);
++ if (wm->mach_ops) {
++ mutex_unlock(&wm->codec_mutex);
++ return -EINVAL;
++ }
++ wm->mach_ops = mach_ops;
++ mutex_unlock(&wm->codec_mutex);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(wm97xx_register_mach_ops);
++
++void wm97xx_unregister_mach_ops(struct wm97xx *wm)
++{
++ mutex_lock(&wm->codec_mutex);
++ wm->mach_ops = NULL;
++ mutex_unlock(&wm->codec_mutex);
++}
++EXPORT_SYMBOL_GPL(wm97xx_unregister_mach_ops);
++
++static struct device_driver wm97xx_driver = {
++ .name = "ac97",
++ .bus = &ac97_bus_type,
++ .owner = THIS_MODULE,
++ .probe = wm97xx_probe,
++ .remove = wm97xx_remove,
++ .suspend = wm97xx_suspend,
++ .resume = wm97xx_resume,
++};
++
++static int __init wm97xx_init(void)
++{
++ return driver_register(&wm97xx_driver);
++}
++
++static void __exit wm97xx_exit(void)
++{
++ driver_unregister(&wm97xx_driver);
++}
++
++module_init(wm97xx_init);
++module_exit(wm97xx_exit);
++
++/* Module information */
++MODULE_AUTHOR("Liam Girdwood <liam.girdwood at wolfsonmicro.com>");
++MODULE_DESCRIPTION("WM97xx Core - Touch Screen / AUX ADC / GPIO Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/xen-kbdfront.c
+new file mode 100644
+index 0000000..0f47f46
+--- /dev/null
++++ b/drivers/input/xen-kbdfront.c
+@@ -0,0 +1,340 @@
++/*
++ * Xen para-virtual input device
++ *
++ * Copyright (C) 2005 Anthony Liguori <aliguori at us.ibm.com>
++ * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster <armbru at redhat.com>
++ *
++ * Based on linux/drivers/input/mouse/sermouse.c
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file COPYING in the main directory of this archive for
++ * more details.
++ */
++
++/*
++ * TODO:
++ *
++ * Switch to grant tables together with xen-fbfront.c.
++ */
++
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/module.h>
++#include <linux/input.h>
++#include <asm/xen/hypervisor.h>
++#include <xen/events.h>
++#include <xen/page.h>
++#include <xen/interface/io/fbif.h>
++#include <xen/interface/io/kbdif.h>
++#include <xen/xenbus.h>
++
++struct xenkbd_info {
++ struct input_dev *kbd;
++ struct input_dev *ptr;
++ struct xenkbd_page *page;
++ int irq;
++ struct xenbus_device *xbdev;
++ char phys[32];
++};
++
++static int xenkbd_remove(struct xenbus_device *);
++static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info *);
++static void xenkbd_disconnect_backend(struct xenkbd_info *);
++
++/*
++ * Note: if you need to send out events, see xenfb_do_update() for how
++ * to do that.
++ */
++
++static irqreturn_t input_handler(int rq, void *dev_id)
++{
++ struct xenkbd_info *info = dev_id;
++ struct xenkbd_page *page = info->page;
++ __u32 cons, prod;
++
++ prod = page->in_prod;
++ if (prod == page->in_cons)
++ return IRQ_HANDLED;
++ rmb(); /* ensure we see ring contents up to prod */
++ for (cons = page->in_cons; cons != prod; cons++) {
++ union xenkbd_in_event *event;
++ struct input_dev *dev;
++ event = &XENKBD_IN_RING_REF(page, cons);
++
++ dev = info->ptr;
++ switch (event->type) {
++ case XENKBD_TYPE_MOTION:
++ input_report_rel(dev, REL_X, event->motion.rel_x);
++ input_report_rel(dev, REL_Y, event->motion.rel_y);
++ break;
++ case XENKBD_TYPE_KEY:
++ dev = NULL;
++ if (test_bit(event->key.keycode, info->kbd->keybit))
++ dev = info->kbd;
++ if (test_bit(event->key.keycode, info->ptr->keybit))
++ dev = info->ptr;
++ if (dev)
++ input_report_key(dev, event->key.keycode,
++ event->key.pressed);
++ else
++ printk(KERN_WARNING
++ "xenkbd: unhandled keycode 0x%x\n",
++ event->key.keycode);
++ break;
++ case XENKBD_TYPE_POS:
++ input_report_abs(dev, ABS_X, event->pos.abs_x);
++ input_report_abs(dev, ABS_Y, event->pos.abs_y);
++ break;
++ }
++ if (dev)
++ input_sync(dev);
++ }
++ mb(); /* ensure we got ring contents */
++ page->in_cons = cons;
++ notify_remote_via_irq(info->irq);
++
++ return IRQ_HANDLED;
++}
++
++static int __devinit xenkbd_probe(struct xenbus_device *dev,
++ const struct xenbus_device_id *id)
++{
++ int ret, i;
++ struct xenkbd_info *info;
++ struct input_dev *kbd, *ptr;
++
++ info = kzalloc(sizeof(*info), GFP_KERNEL);
++ if (!info) {
++ xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
++ return -ENOMEM;
++ }
++ dev->dev.driver_data = info;
++ info->xbdev = dev;
++ info->irq = -1;
++ snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename);
++
++ info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
++ if (!info->page)
++ goto error_nomem;
++
++ /* keyboard */
++ kbd = input_allocate_device();
++ if (!kbd)
++ goto error_nomem;
++ kbd->name = "Xen Virtual Keyboard";
++ kbd->phys = info->phys;
++ kbd->id.bustype = BUS_PCI;
++ kbd->id.vendor = 0x5853;
++ kbd->id.product = 0xffff;
++ kbd->evbit[0] = BIT(EV_KEY);
++ for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
++ set_bit(i, kbd->keybit);
++ for (i = KEY_OK; i < KEY_MAX; i++)
++ set_bit(i, kbd->keybit);
++
++ ret = input_register_device(kbd);
++ if (ret) {
++ input_free_device(kbd);
++ xenbus_dev_fatal(dev, ret, "input_register_device(kbd)");
++ goto error;
++ }
++ info->kbd = kbd;
++
++ /* pointing device */
++ ptr = input_allocate_device();
++ if (!ptr)
++ goto error_nomem;
++ ptr->name = "Xen Virtual Pointer";
++ ptr->phys = info->phys;
++ ptr->id.bustype = BUS_PCI;
++ ptr->id.vendor = 0x5853;
++ ptr->id.product = 0xfffe;
++ ptr->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
++ for (i = BTN_LEFT; i <= BTN_TASK; i++)
++ set_bit(i, ptr->keybit);
++ ptr->relbit[0] = BIT(REL_X) | BIT(REL_Y);
++ input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0);
++ input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0);
++
++ ret = input_register_device(ptr);
++ if (ret) {
++ input_free_device(ptr);
++ xenbus_dev_fatal(dev, ret, "input_register_device(ptr)");
++ goto error;
++ }
++ info->ptr = ptr;
++
++ ret = xenkbd_connect_backend(dev, info);
++ if (ret < 0)
++ goto error;
++
++ return 0;
++
++ error_nomem:
++ ret = -ENOMEM;
++ xenbus_dev_fatal(dev, ret, "allocating device memory");
++ error:
++ xenkbd_remove(dev);
++ return ret;
++}
++
++static int xenkbd_resume(struct xenbus_device *dev)
++{
++ struct xenkbd_info *info = dev->dev.driver_data;
++
++ xenkbd_disconnect_backend(info);
++ memset(info->page, 0, PAGE_SIZE);
++ return xenkbd_connect_backend(dev, info);
++}
++
++static int xenkbd_remove(struct xenbus_device *dev)
++{
++ struct xenkbd_info *info = dev->dev.driver_data;
++
++ xenkbd_disconnect_backend(info);
++ if (info->kbd)
++ input_unregister_device(info->kbd);
++ if (info->ptr)
++ input_unregister_device(info->ptr);
++ free_page((unsigned long)info->page);
++ kfree(info);
++ return 0;
++}
++
++static int xenkbd_connect_backend(struct xenbus_device *dev,
++ struct xenkbd_info *info)
++{
++ int ret, evtchn;
++ struct xenbus_transaction xbt;
++
++ ret = xenbus_alloc_evtchn(dev, &evtchn);
++ if (ret)
++ return ret;
++ ret = bind_evtchn_to_irqhandler(evtchn, input_handler,
++ 0, dev->devicetype, info);
++ if (ret < 0) {
++ xenbus_free_evtchn(dev, evtchn);
++ xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
++ return ret;
++ }
++ info->irq = ret;
++
++ again:
++ ret = xenbus_transaction_start(&xbt);
++ if (ret) {
++ xenbus_dev_fatal(dev, ret, "starting transaction");
++ return ret;
++ }
++ ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
++ virt_to_mfn(info->page));
++ if (ret)
++ goto error_xenbus;
++ ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
++ evtchn);
++ if (ret)
++ goto error_xenbus;
++ ret = xenbus_transaction_end(xbt, 0);
++ if (ret) {
++ if (ret == -EAGAIN)
++ goto again;
++ xenbus_dev_fatal(dev, ret, "completing transaction");
++ return ret;
++ }
++
++ xenbus_switch_state(dev, XenbusStateInitialised);
++ return 0;
++
++ error_xenbus:
++ xenbus_transaction_end(xbt, 1);
++ xenbus_dev_fatal(dev, ret, "writing xenstore");
++ return ret;
++}
++
++static void xenkbd_disconnect_backend(struct xenkbd_info *info)
++{
++ if (info->irq >= 0)
++ unbind_from_irqhandler(info->irq, info);
++ info->irq = -1;
++}
++
++static void xenkbd_backend_changed(struct xenbus_device *dev,
++ enum xenbus_state backend_state)
++{
++ struct xenkbd_info *info = dev->dev.driver_data;
++ int ret, val;
++
++ switch (backend_state) {
++ case XenbusStateInitialising:
++ case XenbusStateInitialised:
++ case XenbusStateUnknown:
++ case XenbusStateClosed:
++ break;
++
++ case XenbusStateInitWait:
++InitWait:
++ ret = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
++ "feature-abs-pointer", "%d", &val);
++ if (ret < 0)
++ val = 0;
++ if (val) {
++ ret = xenbus_printf(XBT_NIL, info->xbdev->nodename,
++ "request-abs-pointer", "1");
++ if (ret)
++ printk(KERN_WARNING
++ "xenkbd: can't request abs-pointer");
++ }
++ xenbus_switch_state(dev, XenbusStateConnected);
++ break;
++
++ case XenbusStateConnected:
++ /*
++ * Work around xenbus race condition: If backend goes
++ * through InitWait to Connected fast enough, we can
++ * get Connected twice here.
++ */
++ if (dev->state != XenbusStateConnected)
++ goto InitWait; /* no InitWait seen yet, fudge it */
++ break;
++
++ case XenbusStateClosing:
++ xenbus_frontend_closed(dev);
++ break;
++ }
++}
++
++static struct xenbus_device_id xenkbd_ids[] = {
++ { "vkbd" },
++ { "" }
++};
++
++static struct xenbus_driver xenkbd = {
++ .name = "vkbd",
++ .owner = THIS_MODULE,
++ .ids = xenkbd_ids,
++ .probe = xenkbd_probe,
++ .remove = xenkbd_remove,
++ .resume = xenkbd_resume,
++ .otherend_changed = xenkbd_backend_changed,
++};
++
++static int __init xenkbd_init(void)
++{
++ if (!is_running_on_xen())
++ return -ENODEV;
++
++ /* Nothing to do if running in dom0. */
++ if (is_initial_xendomain())
++ return -ENODEV;
++
++ return xenbus_register_frontend(&xenkbd);
++}
++
++static void __exit xenkbd_cleanup(void)
++{
++ xenbus_unregister_driver(&xenkbd);
++}
++
++module_init(xenkbd_init);
++module_exit(xenkbd_cleanup);
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c
+index 61e69e9..b96f318 100644
+--- a/drivers/isdn/hisax/asuscom.c
++++ b/drivers/isdn/hisax/asuscom.c
+@@ -20,8 +20,6 @@
+ #include "hscx.h"
+ #include "isdnl1.h"
+
+-extern const char *CardType[];
+-
+ static const char *Asuscom_revision = "$Revision: 1.14.2.4 $";
+
+ #define byteout(addr,val) outb(val,addr)
+@@ -376,8 +374,7 @@ setup_asuscom(struct IsdnCard *card)
+ cs->irq = card->para[0];
+ if (!request_region(cs->hw.asus.cfg_reg, bytecnt, "asuscom isdn")) {
+ printk(KERN_WARNING
+- "HiSax: %s config port %x-%x already in use\n",
+- CardType[card->typ],
++ "HiSax: ISDNLink config port %x-%x already in use\n",
+ cs->hw.asus.cfg_reg,
+ cs->hw.asus.cfg_reg + bytecnt);
+ return (0);
+diff --git a/drivers/isdn/hisax/avm_a1.c b/drivers/isdn/hisax/avm_a1.c
+index d9028e9..eb6b432 100644
+--- a/drivers/isdn/hisax/avm_a1.c
++++ b/drivers/isdn/hisax/avm_a1.c
+@@ -16,7 +16,6 @@
+ #include "hscx.h"
+ #include "isdnl1.h"
+
+-extern const char *CardType[];
+ static const char *avm_revision = "$Revision: 2.15.2.4 $";
+
+ #define AVM_A1_STAT_ISAC 0x01
+@@ -200,16 +199,14 @@ setup_avm_a1(struct IsdnCard *card)
+ cs->irq = card->para[0];
+ if (!request_region(cs->hw.avm.cfg_reg, 8, "avm cfg")) {
+ printk(KERN_WARNING
+- "HiSax: %s config port %x-%x already in use\n",
+- CardType[card->typ],
++ "HiSax: AVM A1 config port %x-%x already in use\n",
+ cs->hw.avm.cfg_reg,
+ cs->hw.avm.cfg_reg + 8);
+ return (0);
+ }
+ if (!request_region(cs->hw.avm.isac + 32, 32, "HiSax isac")) {
+ printk(KERN_WARNING
+- "HiSax: %s isac ports %x-%x already in use\n",
+- CardType[cs->typ],
++ "HiSax: AVM A1 isac ports %x-%x already in use\n",
+ cs->hw.avm.isac + 32,
+ cs->hw.avm.isac + 64);
+ release_ioregs(cs, 0);
+@@ -217,16 +214,14 @@ setup_avm_a1(struct IsdnCard *card)
+ }
+ if (!request_region(cs->hw.avm.isacfifo, 1, "HiSax isac fifo")) {
+ printk(KERN_WARNING
+- "HiSax: %s isac fifo port %x already in use\n",
+- CardType[cs->typ],
++ "HiSax: AVM A1 isac fifo port %x already in use\n",
+ cs->hw.avm.isacfifo);
+ release_ioregs(cs, 1);
+ return (0);
+ }
+ if (!request_region(cs->hw.avm.hscx[0] + 32, 32, "HiSax hscx A")) {
+ printk(KERN_WARNING
+- "HiSax: %s hscx A ports %x-%x already in use\n",
+- CardType[cs->typ],
++ "HiSax: AVM A1 hscx A ports %x-%x already in use\n",
+ cs->hw.avm.hscx[0] + 32,
+ cs->hw.avm.hscx[0] + 64);
+ release_ioregs(cs, 3);
+@@ -234,16 +229,14 @@ setup_avm_a1(struct IsdnCard *card)
+ }
+ if (!request_region(cs->hw.avm.hscxfifo[0], 1, "HiSax hscx A fifo")) {
+ printk(KERN_WARNING
+- "HiSax: %s hscx A fifo port %x already in use\n",
+- CardType[cs->typ],
++ "HiSax: AVM A1 hscx A fifo port %x already in use\n",
+ cs->hw.avm.hscxfifo[0]);
+ release_ioregs(cs, 7);
+ return (0);
+ }
+ if (!request_region(cs->hw.avm.hscx[1] + 32, 32, "HiSax hscx B")) {
+ printk(KERN_WARNING
+- "HiSax: %s hscx B ports %x-%x already in use\n",
+- CardType[cs->typ],
++ "HiSax: AVM A1 hscx B ports %x-%x already in use\n",
+ cs->hw.avm.hscx[1] + 32,
+ cs->hw.avm.hscx[1] + 64);
+ release_ioregs(cs, 0xf);
+@@ -251,8 +244,7 @@ setup_avm_a1(struct IsdnCard *card)
+ }
+ if (!request_region(cs->hw.avm.hscxfifo[1], 1, "HiSax hscx B fifo")) {
+ printk(KERN_WARNING
+- "HiSax: %s hscx B fifo port %x already in use\n",
+- CardType[cs->typ],
++ "HiSax: AVM A1 hscx B fifo port %x already in use\n",
+ cs->hw.avm.hscxfifo[1]);
+ release_ioregs(cs, 0x1f);
+ return (0);
+@@ -284,9 +276,8 @@ setup_avm_a1(struct IsdnCard *card)
+ printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
+ cs->hw.avm.cfg_reg, val);
+
+- printk(KERN_INFO
+- "HiSax: %s config irq:%d cfg:0x%X\n",
+- CardType[cs->typ], cs->irq,
++ printk(KERN_INFO "HiSax: AVM A1 config irq:%d cfg:0x%X\n",
++ cs->irq,
+ cs->hw.avm.cfg_reg);
+ printk(KERN_INFO
+ "HiSax: isac:0x%X/0x%X\n",
+diff --git a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c
+index 3d1bdc8..9ca2ee5 100644
+--- a/drivers/isdn/hisax/bkm_a4t.c
++++ b/drivers/isdn/hisax/bkm_a4t.c
+@@ -20,8 +20,6 @@
+ #include <linux/pci.h>
+ #include "bkm_ax.h"
+
+-extern const char *CardType[];
+-
+ static const char *bkm_a4t_revision = "$Revision: 1.22.2.4 $";
+
+
+@@ -284,15 +282,16 @@ static int __devinit a4t_cs_init(struct IsdnCard *card,
+ I20_REGISTER_FILE *pI20_Regs;
+
+ if (!cs->irq) { /* IRQ range check ?? */
+- printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]);
++ printk(KERN_WARNING "HiSax: Telekom A4T: No IRQ\n");
+ return (0);
+ }
+ cs->hw.ax.base = (long) ioremap(pci_memaddr, 4096);
+ /* Check suspecious address */
+ pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
+ if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) {
+- printk(KERN_WARNING "HiSax: %s address %lx-%lx suspecious\n",
+- CardType[card->typ], cs->hw.ax.base, cs->hw.ax.base + 4096);
++ printk(KERN_WARNING "HiSax: Telekom A4T address "
++ "%lx-%lx suspicious\n",
++ cs->hw.ax.base, cs->hw.ax.base + 4096);
+ iounmap((void *) cs->hw.ax.base);
+ cs->hw.ax.base = 0;
+ return (0);
+@@ -302,8 +301,9 @@ static int __devinit a4t_cs_init(struct IsdnCard *card,
+ cs->hw.ax.isac_ale = GCS_1;
+ cs->hw.ax.jade_ale = GCS_3;
+
+- printk(KERN_INFO "HiSax: %s: Card configured at 0x%lX IRQ %d\n",
+- CardType[card->typ], cs->hw.ax.base, cs->irq);
++ printk(KERN_INFO "HiSax: Telekom A4T: Card configured at "
++ "0x%lX IRQ %d\n",
++ cs->hw.ax.base, cs->irq);
+
+ setup_isac(cs);
+ cs->readisac = &ReadISAC;
+@@ -349,11 +349,12 @@ setup_bkm_a4t(struct IsdnCard *card)
+ break;
+ }
+ if (!found) {
+- printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]);
++ printk(KERN_WARNING "HiSax: Telekom A4T: Card not found\n");
+ return (0);
+ }
+ if (!pci_memaddr) {
+- printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]);
++ printk(KERN_WARNING "HiSax: Telekom A4T: "
++ "No Memory base address\n");
+ return (0);
+ }
+
+diff --git a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c
+index 99ef3b4..e1ff471 100644
+--- a/drivers/isdn/hisax/bkm_a8.c
++++ b/drivers/isdn/hisax/bkm_a8.c
+@@ -22,8 +22,6 @@
+
+ #define ATTEMPT_PCI_REMAPPING /* Required for PLX rev 1 */
+
+-extern const char *CardType[];
+-
+ static const char sct_quadro_revision[] = "$Revision: 1.22.2.4 $";
+
+ static const char *sct_quadro_subtypes[] =
+@@ -181,8 +179,7 @@ bkm_interrupt_ipac(int intno, void *dev_id)
+ goto Start_IPAC;
+ }
+ if (!icnt)
+- printk(KERN_WARNING "HiSax: %s (%s) IRQ LOOP\n",
+- CardType[cs->typ],
++ printk(KERN_WARNING "HiSax: Scitel Quadro (%s) IRQ LOOP\n",
+ sct_quadro_subtypes[cs->subtyp]);
+ writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, 0xFF);
+ writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, 0xC0);
+@@ -296,8 +293,8 @@ setup_sct_quadro(struct IsdnCard *card)
+ if (card->para[0] >= SCT_1 && card->para[0] <= SCT_4)
+ cs->subtyp = card->para[0];
+ else {
+- printk(KERN_WARNING "HiSax: %s: Invalid subcontroller in configuration, default to 1\n",
+- CardType[card->typ]);
++ printk(KERN_WARNING "HiSax: Scitel Quadro: Invalid "
++ "subcontroller in configuration, default to 1\n");
+ return (0);
+ }
+ if ((cs->subtyp != SCT_1) && ((sub_sys_id != PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO) ||
+@@ -322,16 +319,16 @@ setup_sct_quadro(struct IsdnCard *card)
+ }
+ }
+ if (!found) {
+- printk(KERN_WARNING "HiSax: %s (%s): Card not found\n",
+- CardType[card->typ],
++ printk(KERN_WARNING "HiSax: Scitel Quadro (%s): "
++ "Card not found\n",
+ sct_quadro_subtypes[cs->subtyp]);
+ return (0);
+ }
+ #ifdef ATTEMPT_PCI_REMAPPING
+ /* HACK: PLX revision 1 bug: PLX address bit 7 must not be set */
+ if ((pci_ioaddr1 & 0x80) && (dev_a8->revision == 1)) {
+- printk(KERN_WARNING "HiSax: %s (%s): PLX rev 1, remapping required!\n",
+- CardType[card->typ],
++ printk(KERN_WARNING "HiSax: Scitel Quadro (%s): "
++ "PLX rev 1, remapping required!\n",
+ sct_quadro_subtypes[cs->subtyp]);
+ /* Restart PCI negotiation */
+ pci_write_config_dword(dev_a8, PCI_BASE_ADDRESS_1, (u_int) - 1);
+@@ -344,8 +341,7 @@ setup_sct_quadro(struct IsdnCard *card)
+ #endif /* End HACK */
+ }
+ if (!pci_irq) { /* IRQ range check ?? */
+- printk(KERN_WARNING "HiSax: %s (%s): No IRQ\n",
+- CardType[card->typ],
++ printk(KERN_WARNING "HiSax: Scitel Quadro (%s): No IRQ\n",
+ sct_quadro_subtypes[cs->subtyp]);
+ return (0);
+ }
+@@ -355,8 +351,8 @@ setup_sct_quadro(struct IsdnCard *card)
+ pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_4, &pci_ioaddr4);
+ pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_5, &pci_ioaddr5);
+ if (!pci_ioaddr1 || !pci_ioaddr2 || !pci_ioaddr3 || !pci_ioaddr4 || !pci_ioaddr5) {
+- printk(KERN_WARNING "HiSax: %s (%s): No IO base address(es)\n",
+- CardType[card->typ],
++ printk(KERN_WARNING "HiSax: Scitel Quadro (%s): "
++ "No IO base address(es)\n",
+ sct_quadro_subtypes[cs->subtyp]);
+ return (0);
+ }
+@@ -411,8 +407,8 @@ setup_sct_quadro(struct IsdnCard *card)
+ /* For isac and hscx data path */
+ cs->hw.ax.data_adr = cs->hw.ax.base + 4;
+
+- printk(KERN_INFO "HiSax: %s (%s) configured at 0x%.4lX, 0x%.4lX, 0x%.4lX and IRQ %d\n",
+- CardType[card->typ],
++ printk(KERN_INFO "HiSax: Scitel Quadro (%s) configured at "
++ "0x%.4lX, 0x%.4lX, 0x%.4lX and IRQ %d\n",
+ sct_quadro_subtypes[cs->subtyp],
+ cs->hw.ax.plx_adr,
+ cs->hw.ax.base,
+@@ -432,8 +428,7 @@ setup_sct_quadro(struct IsdnCard *card)
+ cs->cardmsg = &BKM_card_msg;
+ cs->irq_func = &bkm_interrupt_ipac;
+
+- printk(KERN_INFO "HiSax: %s (%s): IPAC Version %d\n",
+- CardType[card->typ],
++ printk(KERN_INFO "HiSax: Scitel Quadro (%s): IPAC Version %d\n",
+ sct_quadro_subtypes[cs->subtyp],
+ readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ID));
+ return (1);
+diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
+index a0ee43c..84d75a3 100644
+--- a/drivers/isdn/hisax/config.c
++++ b/drivers/isdn/hisax/config.c
+@@ -1169,7 +1169,9 @@ outf_cs:
+ /* Used from an exported function but calls __devinit functions.
+ * Tell modpost not to warn (__ref)
+ */
+-static int __ref checkcard(int cardnr, char *id, int *busy_flag, struct module *lockowner)
++static int __ref checkcard(int cardnr, char *id, int *busy_flag,
++ struct module *lockowner,
++ hisax_setup_func_t card_setup)
+ {
+ int ret;
+ struct IsdnCard *card = cards + cardnr;
+@@ -1187,7 +1189,7 @@ static int __ref checkcard(int cardnr, char *id, int *busy_flag, struct module *
+ (card->protocol == ISDN_PTYPE_NI1) ? "NI1" :
+ "NONE", cs->iif.id, cs->myid);
+
+- ret = hisax_cs_setup_card(card);
++ ret = card_setup(card);
+ if (!ret) {
+ ll_unload(cs);
+ goto outf_cs;
+@@ -1241,7 +1243,8 @@ static int HiSax_inithardware(int *busy_flag)
+ else
+ sprintf(ids, "%s%d", id, i);
+ }
+- if (checkcard(i, ids, busy_flag, THIS_MODULE)) {
++ if (checkcard(i, ids, busy_flag, THIS_MODULE,
++ hisax_cs_setup_card)) {
+ foundcards++;
+ i++;
+ } else {
+@@ -1549,7 +1552,8 @@ int hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *card)
+ sprintf(ids, "HiSax%d", nrcards);
+ else
+ sprintf(ids, "HiSax");
+- if (!checkcard(nrcards, ids, busy_flag, THIS_MODULE))
++ if (!checkcard(nrcards, ids, busy_flag, THIS_MODULE,
++ hisax_cs_setup_card))
+ goto error;
+
+ ret = nrcards;
+@@ -1595,7 +1599,7 @@ int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[],
+ cards[i].protocol = protocol;
+ sprintf(id, "%s%d", name, i);
+ nrcards++;
+- retval = checkcard(i, id, NULL, hisax_d_if->owner);
++ retval = checkcard(i, id, NULL, hisax_d_if->owner, hisax_cs_setup_card);
+ if (retval == 0) { // yuck
+ cards[i].typ = 0;
+ nrcards--;
+diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
+index d272d8c..2c3691f 100644
+--- a/drivers/isdn/hisax/elsa.c
++++ b/drivers/isdn/hisax/elsa.c
+@@ -299,7 +299,7 @@ elsa_interrupt(int intno, void *dev_id)
+ val = serial_inp(cs, UART_IIR);
+ if (!(val & UART_IIR_NO_INT)) {
+ debugl1(cs,"IIR %02x", val);
+- rs_interrupt_elsa(intno, cs);
++ rs_interrupt_elsa(cs);
+ }
+ }
+ #endif
+@@ -379,7 +379,7 @@ elsa_interrupt_ipac(int intno, void *dev_id)
+ val = serial_inp(cs, UART_IIR);
+ if (!(val & UART_IIR_NO_INT)) {
+ debugl1(cs,"IIR %02x", val);
+- rs_interrupt_elsa(intno, cs);
++ rs_interrupt_elsa(cs);
+ }
+ }
+ #endif
+diff --git a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c
+index 1642dca..f181db4 100644
+--- a/drivers/isdn/hisax/elsa_ser.c
++++ b/drivers/isdn/hisax/elsa_ser.c
+@@ -384,13 +384,13 @@ static inline void transmit_chars(struct IsdnCardState *cs, int *intr_done)
+ }
+
+
+-static void rs_interrupt_elsa(int irq, struct IsdnCardState *cs)
++static void rs_interrupt_elsa(struct IsdnCardState *cs)
+ {
+ int status, iir, msr;
+ int pass_counter = 0;
+
+ #ifdef SERIAL_DEBUG_INTR
+- printk("rs_interrupt_single(%d)...", irq);
++ printk(KERN_DEBUG "rs_interrupt_single(%d)...", cs->irq);
+ #endif
+
+ do {
+diff --git a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c
+index f66620a..0ea3b46 100644
+--- a/drivers/isdn/hisax/gazel.c
++++ b/drivers/isdn/hisax/gazel.c
+@@ -19,7 +19,6 @@
+ #include "ipac.h"
+ #include <linux/pci.h>
+
+-extern const char *CardType[];
+ static const char *gazel_revision = "$Revision: 2.19.2.4 $";
+
+ #define R647 1
+@@ -479,8 +478,8 @@ reserve_regions(struct IsdnCard *card, struct IsdnCardState *cs)
+ return 0;
+
+ error:
+- printk(KERN_WARNING "Gazel: %s io ports 0x%x-0x%x already in use\n",
+- CardType[cs->typ], adr, adr + len);
++ printk(KERN_WARNING "Gazel: io ports 0x%x-0x%x already in use\n",
++ adr, adr + len);
+ return 1;
+ }
+
+diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
+index fba8b62..f126566 100644
+--- a/drivers/isdn/hisax/hfc_pci.c
++++ b/drivers/isdn/hisax/hfc_pci.c
+@@ -22,8 +22,6 @@
+ #include <linux/pci.h>
+ #include <linux/interrupt.h>
+
+-extern const char *CardType[];
+-
+ static const char *hfcpci_revision = "$Revision: 1.48.2.4 $";
+
+ /* table entry in the PCI devices list */
+diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c
+index 05482d2..f4a2138 100644
+--- a/drivers/isdn/hisax/hfc_sx.c
++++ b/drivers/isdn/hisax/hfc_sx.c
+@@ -18,8 +18,6 @@
+ #include <linux/interrupt.h>
+ #include <linux/isapnp.h>
+
+-extern const char *CardType[];
+-
+ static const char *hfcsx_revision = "$Revision: 1.12.2.5 $";
+
+ /***************************************/
+diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
+index 34733c9..e8d429f 100644
+--- a/drivers/isdn/hisax/hisax.h
++++ b/drivers/isdn/hisax/hisax.h
+@@ -925,7 +925,7 @@ struct IsdnCardState {
+ int (*cardmsg) (struct IsdnCardState *, int, void *);
+ void (*setstack_d) (struct PStack *, struct IsdnCardState *);
+ void (*DC_Close) (struct IsdnCardState *);
+- int (*irq_func) (int, void *);
++ irq_handler_t irq_func;
+ int (*auxcmd) (struct IsdnCardState *, isdn_ctrl *);
+ struct Channel channel[2+MAX_WAITING_CALLS];
+ struct BCState bcs[2+MAX_WAITING_CALLS];
+diff --git a/drivers/isdn/hisax/hisax_cfg.h b/drivers/isdn/hisax/hisax_cfg.h
+index ca3fe62..17a2fea 100644
+--- a/drivers/isdn/hisax/hisax_cfg.h
++++ b/drivers/isdn/hisax/hisax_cfg.h
+@@ -60,5 +60,7 @@ struct IsdnCard {
+ IsdnCardState_t *cs;
+ };
+
++typedef int (*hisax_setup_func_t)(struct IsdnCard *card);
++
+ extern void HiSax_closecard(int);
+ extern int hisax_init_pcmcia(void *, int *, IsdnCard_t *);
+diff --git a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c
+index 55de069..ca41617 100644
+--- a/drivers/isdn/hisax/isurf.c
++++ b/drivers/isdn/hisax/isurf.c
+@@ -17,8 +17,6 @@
+ #include "isdnl1.h"
+ #include <linux/isapnp.h>
+
+-extern const char *CardType[];
+-
+ static const char *ISurf_revision = "$Revision: 1.12.2.4 $";
+
+ #define byteout(addr,val) outb(val,addr)
+@@ -251,22 +249,19 @@ setup_isurf(struct IsdnCard *card)
+ return(0);
+ }
+ #else
+- printk(KERN_WARNING "HiSax: %s port/mem not set\n",
+- CardType[card->typ]);
++ printk(KERN_WARNING "HiSax: Siemens I-Surf port/mem not set\n");
+ return (0);
+ #endif
+ }
+ if (!request_region(cs->hw.isurf.reset, 1, "isurf isdn")) {
+ printk(KERN_WARNING
+- "HiSax: %s config port %x already in use\n",
+- CardType[card->typ],
++ "HiSax: Siemens I-Surf config port %x already in use\n",
+ cs->hw.isurf.reset);
+ return (0);
+ }
+ if (!request_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE, "isurf iomem")) {
+- printk(KERN_WARNING
+- "HiSax: %s memory region %lx-%lx already in use\n",
+- CardType[card->typ],
++ printk(KERN_WARNING "HiSax: Siemens I-Surf memory region "
++ "%lx-%lx already in use\n",
+ cs->hw.isurf.phymem,
+ cs->hw.isurf.phymem + ISURF_IOMEM_SIZE);
+ release_region(cs->hw.isurf.reset, 1);
+diff --git a/drivers/isdn/hisax/ix1_micro.c b/drivers/isdn/hisax/ix1_micro.c
+index 252d79d..2d18d4f 100644
+--- a/drivers/isdn/hisax/ix1_micro.c
++++ b/drivers/isdn/hisax/ix1_micro.c
+@@ -24,7 +24,6 @@
+ #include "hscx.h"
+ #include "isdnl1.h"
+
+-extern const char *CardType[];
+ static const char *ix1_revision = "$Revision: 2.12.2.4 $";
+
+ #define byteout(addr,val) outb(val,addr)
+@@ -288,15 +287,15 @@ setup_ix1micro(struct IsdnCard *card)
+ if (cs->hw.ix1.cfg_reg) {
+ if (!request_region(cs->hw.ix1.cfg_reg, 4, "ix1micro cfg")) {
+ printk(KERN_WARNING
+- "HiSax: %s config port %x-%x already in use\n",
+- CardType[card->typ],
++ "HiSax: ITK ix1-micro Rev.2 config port "
++ "%x-%x already in use\n",
+ cs->hw.ix1.cfg_reg,
+ cs->hw.ix1.cfg_reg + 4);
+ return (0);
+ }
+ }
+- printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n",
+- CardType[cs->typ], cs->irq, cs->hw.ix1.cfg_reg);
++ printk(KERN_INFO "HiSax: ITK ix1-micro Rev.2 config irq:%d io:0x%X\n",
++ cs->irq, cs->hw.ix1.cfg_reg);
+ setup_isac(cs);
+ cs->readisac = &ReadISAC;
+ cs->writeisac = &WriteISAC;
+diff --git a/drivers/isdn/hisax/mic.c b/drivers/isdn/hisax/mic.c
+index a81d175..2539430 100644
+--- a/drivers/isdn/hisax/mic.c
++++ b/drivers/isdn/hisax/mic.c
+@@ -16,8 +16,6 @@
+ #include "hscx.h"
+ #include "isdnl1.h"
+
+-extern const char *CardType[];
+-
+ static const char *mic_revision = "$Revision: 1.12.2.4 $";
+
+ #define byteout(addr,val) outb(val,addr)
+@@ -210,8 +208,7 @@ setup_mic(struct IsdnCard *card)
+
+ if (!request_region(cs->hw.mic.cfg_reg, bytecnt, "mic isdn")) {
+ printk(KERN_WARNING
+- "HiSax: %s config port %x-%x already in use\n",
+- CardType[card->typ],
++ "HiSax: ith mic config port %x-%x already in use\n",
+ cs->hw.mic.cfg_reg,
+ cs->hw.mic.cfg_reg + bytecnt);
+ return (0);
+diff --git a/drivers/isdn/hisax/netjet.h b/drivers/isdn/hisax/netjet.h
+index 4d89d3e..68e504d 100644
+--- a/drivers/isdn/hisax/netjet.h
++++ b/drivers/isdn/hisax/netjet.h
+@@ -12,8 +12,6 @@
+ *
+ */
+
+-extern const char *CardType[];
+-
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
+
+diff --git a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c
+index bd99211..421b8e6 100644
+--- a/drivers/isdn/hisax/niccy.c
++++ b/drivers/isdn/hisax/niccy.c
+@@ -21,7 +21,6 @@
+ #include <linux/pci.h>
+ #include <linux/isapnp.h>
+
+-extern const char *CardType[];
+ static const char *niccy_revision = "$Revision: 1.21.2.4 $";
+
+ #define byteout(addr,val) outb(val,addr)
+@@ -284,14 +283,14 @@ int __devinit setup_niccy(struct IsdnCard *card)
+ cs->subtyp = NICCY_PNP;
+ cs->irq = card->para[0];
+ if (!request_region(cs->hw.niccy.isac, 2, "niccy data")) {
+- printk(KERN_WARNING "HiSax: %s data port %x-%x "
+- "already in use\n", CardType[card->typ],
++ printk(KERN_WARNING "HiSax: NICCY data port %x-%x "
++ "already in use\n",
+ cs->hw.niccy.isac, cs->hw.niccy.isac + 1);
+ return 0;
+ }
+ if (!request_region(cs->hw.niccy.isac_ale, 2, "niccy addr")) {
+- printk(KERN_WARNING "HiSax: %s address port %x-%x "
+- "already in use\n", CardType[card->typ],
++ printk(KERN_WARNING "HiSax: NICCY address port %x-%x "
++ "already in use\n",
+ cs->hw.niccy.isac_ale,
+ cs->hw.niccy.isac_ale + 1);
+ release_region(cs->hw.niccy.isac, 2);
+@@ -339,15 +338,13 @@ int __devinit setup_niccy(struct IsdnCard *card)
+ cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR;
+ if (!request_region(cs->hw.niccy.isac, 4, "niccy")) {
+ printk(KERN_WARNING
+- "HiSax: %s data port %x-%x already in use\n",
+- CardType[card->typ],
++ "HiSax: NICCY data port %x-%x already in use\n",
+ cs->hw.niccy.isac, cs->hw.niccy.isac + 4);
+ return 0;
+ }
+ if (!request_region(cs->hw.niccy.cfg_reg, 0x40, "niccy pci")) {
+ printk(KERN_WARNING
+- "HiSax: %s pci port %x-%x already in use\n",
+- CardType[card->typ],
++ "HiSax: NICCY pci port %x-%x already in use\n",
+ cs->hw.niccy.cfg_reg,
+ cs->hw.niccy.cfg_reg + 0x40);
+ release_region(cs->hw.niccy.isac, 4);
+@@ -359,8 +356,8 @@ int __devinit setup_niccy(struct IsdnCard *card)
+ return 0;
+ #endif /* CONFIG_PCI_LEGACY */
+ }
+- printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n",
+- CardType[cs->typ], (cs->subtyp == 1) ? "PnP" : "PCI",
++ printk(KERN_INFO "HiSax: NICCY %s config irq:%d data:0x%X ale:0x%X\n",
++ (cs->subtyp == 1) ? "PnP" : "PCI",
+ cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale);
+ setup_isac(cs);
+ cs->readisac = &ReadISAC;
+diff --git a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c
+index a895dfe..8d36ccc 100644
+--- a/drivers/isdn/hisax/nj_s.c
++++ b/drivers/isdn/hisax/nj_s.c
+@@ -235,8 +235,7 @@ static int __devinit njs_cs_init_rest(struct IsdnCard *card,
+ cs->subtyp ? "TJ320" : "TJ300", cs->hw.njet.base, cs->irq);
+ if (!request_region(cs->hw.njet.base, bytecnt, "netjet-s isdn")) {
+ printk(KERN_WARNING
+- "HiSax: %s config port %#lx-%#lx already in use\n",
+- CardType[card->typ],
++ "HiSax: NETjet-S config port %#lx-%#lx already in use\n",
+ cs->hw.njet.base,
+ cs->hw.njet.base + bytecnt);
+ return (0);
+diff --git a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c
+index f017d38..d306c94 100644
+--- a/drivers/isdn/hisax/nj_u.c
++++ b/drivers/isdn/hisax/nj_u.c
+@@ -197,8 +197,8 @@ static int __devinit nju_cs_init_rest(struct IsdnCard *card,
+ cs->hw.njet.base, cs->irq);
+ if (!request_region(cs->hw.njet.base, bytecnt, "netspider-u isdn")) {
+ printk(KERN_WARNING
+- "HiSax: %s config port %#lx-%#lx already in use\n",
+- CardType[card->typ],
++ "HiSax: NETspider-U config port %#lx-%#lx "
++ "already in use\n",
+ cs->hw.njet.base,
+ cs->hw.njet.base + bytecnt);
+ return (0);
+diff --git a/drivers/isdn/hisax/s0box.c b/drivers/isdn/hisax/s0box.c
+index 150ef68..16d00b5 100644
+--- a/drivers/isdn/hisax/s0box.c
++++ b/drivers/isdn/hisax/s0box.c
+@@ -16,7 +16,6 @@
+ #include "hscx.h"
+ #include "isdnl1.h"
+
+-extern const char *CardType[];
+ static const char *s0box_revision = "$Revision: 2.6.2.4 $";
+
+ static inline void
+@@ -231,19 +230,15 @@ setup_s0box(struct IsdnCard *card)
+ cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
+ cs->irq = card->para[0];
+ if (!request_region(cs->hw.teles3.cfg_reg,8, "S0Box parallel I/O")) {
+- printk(KERN_WARNING
+- "HiSax: %s ports %x-%x already in use\n",
+- CardType[cs->typ],
++ printk(KERN_WARNING "HiSax: S0Box ports %x-%x already in use\n",
+ cs->hw.teles3.cfg_reg,
+ cs->hw.teles3.cfg_reg + 7);
+ return 0;
+ }
+- printk(KERN_INFO
+- "HiSax: %s config irq:%d isac:0x%x cfg:0x%x\n",
+- CardType[cs->typ], cs->irq,
++ printk(KERN_INFO "HiSax: S0Box config irq:%d isac:0x%x cfg:0x%x\n",
++ cs->irq,
+ cs->hw.teles3.isac, cs->hw.teles3.cfg_reg);
+- printk(KERN_INFO
+- "HiSax: hscx A:0x%x hscx B:0x%x\n",
++ printk(KERN_INFO "HiSax: hscx A:0x%x hscx B:0x%x\n",
+ cs->hw.teles3.hscx[0], cs->hw.teles3.hscx[1]);
+ setup_isac(cs);
+ cs->readisac = &ReadISAC;
+diff --git a/drivers/isdn/hisax/saphir.c b/drivers/isdn/hisax/saphir.c
+index c99b166..b34a81d 100644
+--- a/drivers/isdn/hisax/saphir.c
++++ b/drivers/isdn/hisax/saphir.c
+@@ -18,7 +18,6 @@
+ #include "hscx.h"
+ #include "isdnl1.h"
+
+-extern const char *CardType[];
+ static char *saphir_rev = "$Revision: 1.10.2.4 $";
+
+ #define byteout(addr,val) outb(val,addr)
+@@ -260,15 +259,14 @@ setup_saphir(struct IsdnCard *card)
+ cs->irq = card->para[0];
+ if (!request_region(cs->hw.saphir.cfg_reg, 6, "saphir")) {
+ printk(KERN_WARNING
+- "HiSax: %s config port %x-%x already in use\n",
+- CardType[card->typ],
++ "HiSax: HST Saphir config port %x-%x already in use\n",
+ cs->hw.saphir.cfg_reg,
+ cs->hw.saphir.cfg_reg + 5);
+ return (0);
+ }
+
+- printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n",
+- CardType[cs->typ], cs->irq, cs->hw.saphir.cfg_reg);
++ printk(KERN_INFO "HiSax: HST Saphir config irq:%d io:0x%X\n",
++ cs->irq, cs->hw.saphir.cfg_reg);
+
+ setup_isac(cs);
+ cs->hw.saphir.timer.function = (void *) SaphirWatchDog;
+diff --git a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c
+index 0220950..0a53759 100644
+--- a/drivers/isdn/hisax/sportster.c
++++ b/drivers/isdn/hisax/sportster.c
+@@ -18,7 +18,6 @@
+ #include "hscx.h"
+ #include "isdnl1.h"
+
+-extern const char *CardType[];
+ static const char *sportster_revision = "$Revision: 1.16.2.4 $";
+
+ #define byteout(addr,val) outb(val,addr)
+@@ -192,9 +191,9 @@ get_io_range(struct IsdnCardState *cs)
+ for (i=0;i<64;i++) {
+ adr = cs->hw.spt.cfg_reg + i *1024;
+ if (!request_region(adr, 8, "sportster")) {
+- printk(KERN_WARNING
+- "HiSax: %s config port %x-%x already in use\n",
+- CardType[cs->typ], adr, adr + 8);
++ printk(KERN_WARNING "HiSax: USR Sportster config port "
++ "%x-%x already in use\n",
++ adr, adr + 8);
+ break;
+ }
+ }
+@@ -247,8 +246,8 @@ setup_sportster(struct IsdnCard *card)
+ printk(KERN_WARNING "Sportster: wrong IRQ\n");
+ return(0);
+ }
+- printk(KERN_INFO "HiSax: %s config irq:%d cfg:0x%X\n",
+- CardType[cs->typ], cs->irq, cs->hw.spt.cfg_reg);
++ printk(KERN_INFO "HiSax: USR Sportster config irq:%d cfg:0x%X\n",
++ cs->irq, cs->hw.spt.cfg_reg);
+ setup_isac(cs);
+ cs->readisac = &ReadISAC;
+ cs->writeisac = &WriteISAC;
+diff --git a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c
+index 0909662..b0ce4ae 100644
+--- a/drivers/isdn/hisax/teleint.c
++++ b/drivers/isdn/hisax/teleint.c
+@@ -16,8 +16,6 @@
+ #include "hfc_2bs0.h"
+ #include "isdnl1.h"
+
+-extern const char *CardType[];
+-
+ static const char *TeleInt_revision = "$Revision: 1.16.2.5 $";
+
+ #define byteout(addr,val) outb(val,addr)
+@@ -286,8 +284,7 @@ setup_TeleInt(struct IsdnCard *card)
+ init_timer(&cs->hw.hfc.timer);
+ if (!request_region(cs->hw.hfc.addr, 2, "TeleInt isdn")) {
+ printk(KERN_WARNING
+- "HiSax: %s config port %x-%x already in use\n",
+- CardType[card->typ],
++ "HiSax: TeleInt config port %x-%x already in use\n",
+ cs->hw.hfc.addr,
+ cs->hw.hfc.addr + 2);
+ return (0);
+diff --git a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c
+index 4393003..28b08de 100644
+--- a/drivers/isdn/hisax/telespci.c
++++ b/drivers/isdn/hisax/telespci.c
+@@ -19,7 +19,6 @@
+ #include "isdnl1.h"
+ #include <linux/pci.h>
+
+-extern const char *CardType[];
+ static const char *telespci_revision = "$Revision: 2.23.2.3 $";
+
+ #define ZORAN_PO_RQ_PEN 0x02000000
+@@ -329,8 +328,8 @@ setup_telespci(struct IsdnCard *card)
+ /* writel(0x00800000, cs->hw.teles0.membase + 0x200); */
+
+ printk(KERN_INFO
+- "HiSax: %s config irq:%d mem:%p\n",
+- CardType[cs->typ], cs->irq,
++ "HiSax: Teles PCI config irq:%d mem:%p\n",
++ cs->irq,
+ cs->hw.teles0.membase);
+
+ setup_isac(cs);
+diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c
+index 39129b9..bb1c8dd 100644
+--- a/drivers/isdn/hisax/w6692.c
++++ b/drivers/isdn/hisax/w6692.c
+@@ -38,8 +38,6 @@ static const PCI_ENTRY id_list[] =
+ #define W6692_DYNALINK 1
+ #define W6692_USR 2
+
+-extern const char *CardType[];
+-
+ static const char *w6692_revision = "$Revision: 1.18.2.4 $";
+
+ #define DBUSY_TIMER_VALUE 80
+diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
+index 859814f..86a369b 100644
+--- a/drivers/leds/Kconfig
++++ b/drivers/leds/Kconfig
+@@ -1,6 +1,5 @@
+ menuconfig NEW_LEDS
+ bool "LED Support"
+- depends on HAS_IOMEM
+ help
+ Say Y to enable Linux LED support. This allows control of supported
+ LEDs from both userspace and optionally, by kernel events (triggers).
+@@ -46,13 +45,6 @@ config LEDS_SPITZ
+ This option enables support for the LEDs on Sharp Zaurus
+ SL-Cxx00 series (C1000, C3000, C3100).
+
+-config LEDS_TOSA
+- tristate "LED Support for the Sharp SL-6000 series"
+- depends on LEDS_CLASS && PXA_SHARPSL
+- help
+- This option enables support for the LEDs on Sharp Zaurus
+- SL-6000 series.
+-
+ config LEDS_S3C24XX
+ tristate "LED Support for Samsung S3C24XX GPIO LEDs"
+ depends on LEDS_CLASS && ARCH_S3C2410
+@@ -73,6 +65,12 @@ config LEDS_NET48XX
+ This option enables support for the Soekris net4801 and net4826 error
+ LED.
+
++config LEDS_FSG
++ tristate "LED Support for the Freecom FSG-3"
++ depends on LEDS_CLASS && MACH_FSG
++ help
++ This option enables support for the LEDs on the Freecom FSG-3.
++
+ config LEDS_WRAP
+ tristate "LED Support for the WRAP series LEDs"
+ depends on LEDS_CLASS && SCx200_GPIO
+@@ -135,6 +133,7 @@ config LEDS_CLEVO_MAIL
+
+ This module can drive the mail LED for the following notebooks:
+
++ Clevo D400P
+ Clevo D410J
+ Clevo D410V
+ Clevo D400V/D470V (not tested, but might work)
+@@ -142,6 +141,9 @@ config LEDS_CLEVO_MAIL
+ Clevo M5x0N (not tested, but might work)
+ Positivo Mobile (Clevo M5x0V)
+
++ If your model is not listed here you can try the "nodetect"
++ module paramter.
++
+ To compile this driver as a module, choose M here: the
+ module will be called leds-clevo-mail.
+
+@@ -181,4 +183,11 @@ config LEDS_TRIGGER_HEARTBEAT
+ load average.
+ If unsure, say Y.
+
++config LEDS_TRIGGER_DEFAULT_ON
++ tristate "LED Default ON Trigger"
++ depends on LEDS_TRIGGERS
++ help
++ This allows LEDs to be initialised in the ON state.
++ If unsure, say Y.
++
+ endif # NEW_LEDS
+diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
+index 84ced3b..973d626 100644
+--- a/drivers/leds/Makefile
++++ b/drivers/leds/Makefile
+@@ -9,7 +9,6 @@ obj-$(CONFIG_LEDS_ATMEL_PWM) += leds-atmel-pwm.o
+ obj-$(CONFIG_LEDS_CORGI) += leds-corgi.o
+ obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o
+ obj-$(CONFIG_LEDS_SPITZ) += leds-spitz.o
+-obj-$(CONFIG_LEDS_TOSA) += leds-tosa.o
+ obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o
+ obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o
+ obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o
+@@ -21,8 +20,10 @@ obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
+ obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.o
+ obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o
+ obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
++obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
+
+ # LED Triggers
+ obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
+ obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o
+ obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o
++obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
+diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
+index 4a93878..ac05a92 100644
+--- a/drivers/leds/led-class.c
++++ b/drivers/leds/led-class.c
+@@ -24,6 +24,12 @@
+
+ static struct class *leds_class;
+
++static void led_update_brightness(struct led_classdev *led_cdev)
++{
++ if (led_cdev->brightness_get)
++ led_cdev->brightness = led_cdev->brightness_get(led_cdev);
++}
++
+ static ssize_t led_brightness_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+ {
+@@ -31,6 +37,7 @@ static ssize_t led_brightness_show(struct device *dev,
+ ssize_t ret = 0;
+
+ /* no lock needed for this */
++ led_update_brightness(led_cdev);
+ sprintf(buf, "%u\n", led_cdev->brightness);
+ ret = strlen(buf) + 1;
+
+@@ -51,6 +58,9 @@ static ssize_t led_brightness_store(struct device *dev,
+
+ if (count == size) {
+ ret = count;
++
++ if (state == LED_OFF)
++ led_trigger_remove(led_cdev);
+ led_set_brightness(led_cdev, state);
+ }
+
+@@ -110,6 +120,8 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
+ list_add_tail(&led_cdev->node, &leds_list);
+ up_write(&leds_list_lock);
+
++ led_update_brightness(led_cdev);
++
+ #ifdef CONFIG_LEDS_TRIGGERS
+ init_rwsem(&led_cdev->trigger_lock);
+
+@@ -139,12 +151,10 @@ EXPORT_SYMBOL_GPL(led_classdev_register);
+ /**
+ * __led_classdev_unregister - unregisters a object of led_properties class.
+ * @led_cdev: the led device to unregister
+- * @suspended: indicates whether system-wide suspend or resume is in progress
+ *
+ * Unregisters a previously registered via led_classdev_register object.
+ */
+-void __led_classdev_unregister(struct led_classdev *led_cdev,
+- bool suspended)
++void led_classdev_unregister(struct led_classdev *led_cdev)
+ {
+ device_remove_file(led_cdev->dev, &dev_attr_brightness);
+ #ifdef CONFIG_LEDS_TRIGGERS
+@@ -155,16 +165,13 @@ void __led_classdev_unregister(struct led_classdev *led_cdev,
+ up_write(&led_cdev->trigger_lock);
+ #endif
+
+- if (suspended)
+- device_pm_schedule_removal(led_cdev->dev);
+- else
+- device_unregister(led_cdev->dev);
++ device_unregister(led_cdev->dev);
+
+ down_write(&leds_list_lock);
+ list_del(&led_cdev->node);
+ up_write(&leds_list_lock);
+ }
+-EXPORT_SYMBOL_GPL(__led_classdev_unregister);
++EXPORT_SYMBOL_GPL(led_classdev_unregister);
+
+ static int __init leds_init(void)
+ {
+diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
+index 5d1ca10..016d19f 100644
+--- a/drivers/leds/led-core.c
++++ b/drivers/leds/led-core.c
+@@ -19,7 +19,7 @@
+ #include "leds.h"
+
+ DECLARE_RWSEM(leds_list_lock);
+-LIST_HEAD(leds_list);
++EXPORT_SYMBOL_GPL(leds_list_lock);
+
++LIST_HEAD(leds_list);
+ EXPORT_SYMBOL_GPL(leds_list);
+-EXPORT_SYMBOL_GPL(leds_list_lock);
+diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
+index 13c9026..0f242b3 100644
+--- a/drivers/leds/led-triggers.c
++++ b/drivers/leds/led-triggers.c
+@@ -29,6 +29,8 @@
+ static DECLARE_RWSEM(triggers_list_lock);
+ static LIST_HEAD(trigger_list);
+
++ /* Used by LED Class */
++
+ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+ {
+@@ -45,9 +47,7 @@ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
+ trigger_name[len - 1] = '\0';
+
+ if (!strcmp(trigger_name, "none")) {
+- down_write(&led_cdev->trigger_lock);
+- led_trigger_set(led_cdev, NULL);
+- up_write(&led_cdev->trigger_lock);
++ led_trigger_remove(led_cdev);
+ return count;
+ }
+
+@@ -66,7 +66,7 @@ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
+
+ return -EINVAL;
+ }
+-
++EXPORT_SYMBOL_GPL(led_trigger_store);
+
+ ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+@@ -96,24 +96,7 @@ ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr,
+ len += sprintf(len+buf, "\n");
+ return len;
+ }
+-
+-void led_trigger_event(struct led_trigger *trigger,
+- enum led_brightness brightness)
+-{
+- struct list_head *entry;
+-
+- if (!trigger)
+- return;
+-
+- read_lock(&trigger->leddev_list_lock);
+- list_for_each(entry, &trigger->led_cdevs) {
+- struct led_classdev *led_cdev;
+-
+- led_cdev = list_entry(entry, struct led_classdev, trig_list);
+- led_set_brightness(led_cdev, brightness);
+- }
+- read_unlock(&trigger->leddev_list_lock);
+-}
++EXPORT_SYMBOL_GPL(led_trigger_show);
+
+ /* Caller must ensure led_cdev->trigger_lock held */
+ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger)
+@@ -124,7 +107,8 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger)
+ if (led_cdev->trigger) {
+ write_lock_irqsave(&led_cdev->trigger->leddev_list_lock, flags);
+ list_del(&led_cdev->trig_list);
+- write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock, flags);
++ write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock,
++ flags);
+ if (led_cdev->trigger->deactivate)
+ led_cdev->trigger->deactivate(led_cdev);
+ led_set_brightness(led_cdev, LED_OFF);
+@@ -138,6 +122,15 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger)
+ }
+ led_cdev->trigger = trigger;
+ }
++EXPORT_SYMBOL_GPL(led_trigger_set);
++
++void led_trigger_remove(struct led_classdev *led_cdev)
++{
++ down_write(&led_cdev->trigger_lock);
++ led_trigger_set(led_cdev, NULL);
++ up_write(&led_cdev->trigger_lock);
++}
++EXPORT_SYMBOL_GPL(led_trigger_remove);
+
+ void led_trigger_set_default(struct led_classdev *led_cdev)
+ {
+@@ -155,6 +148,9 @@ void led_trigger_set_default(struct led_classdev *led_cdev)
+ up_write(&led_cdev->trigger_lock);
+ up_read(&triggers_list_lock);
+ }
++EXPORT_SYMBOL_GPL(led_trigger_set_default);
++
++/* LED Trigger Interface */
+
+ int led_trigger_register(struct led_trigger *trigger)
+ {
+@@ -181,26 +177,7 @@ int led_trigger_register(struct led_trigger *trigger)
+
+ return 0;
+ }
+-
+-void led_trigger_register_simple(const char *name, struct led_trigger **tp)
+-{
+- struct led_trigger *trigger;
+- int err;
+-
+- trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
+-
+- if (trigger) {
+- trigger->name = name;
+- err = led_trigger_register(trigger);
+- if (err < 0)
+- printk(KERN_WARNING "LED trigger %s failed to register"
+- " (%d)\n", name, err);
+- } else
+- printk(KERN_WARNING "LED trigger %s failed to register"
+- " (no memory)\n", name);
+-
+- *tp = trigger;
+-}
++EXPORT_SYMBOL_GPL(led_trigger_register);
+
+ void led_trigger_unregister(struct led_trigger *trigger)
+ {
+@@ -221,6 +198,49 @@ void led_trigger_unregister(struct led_trigger *trigger)
+ }
+ up_read(&leds_list_lock);
+ }
++EXPORT_SYMBOL_GPL(led_trigger_unregister);
++
++/* Simple LED Tigger Interface */
++
++void led_trigger_event(struct led_trigger *trigger,
++ enum led_brightness brightness)
++{
++ struct list_head *entry;
++
++ if (!trigger)
++ return;
++
++ read_lock(&trigger->leddev_list_lock);
++ list_for_each(entry, &trigger->led_cdevs) {
++ struct led_classdev *led_cdev;
++
++ led_cdev = list_entry(entry, struct led_classdev, trig_list);
++ led_set_brightness(led_cdev, brightness);
++ }
++ read_unlock(&trigger->leddev_list_lock);
++}
++EXPORT_SYMBOL_GPL(led_trigger_event);
++
++void led_trigger_register_simple(const char *name, struct led_trigger **tp)
++{
++ struct led_trigger *trigger;
++ int err;
++
++ trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
++
++ if (trigger) {
++ trigger->name = name;
++ err = led_trigger_register(trigger);
++ if (err < 0)
++ printk(KERN_WARNING "LED trigger %s failed to register"
++ " (%d)\n", name, err);
++ } else
++ printk(KERN_WARNING "LED trigger %s failed to register"
++ " (no memory)\n", name);
++
++ *tp = trigger;
++}
++EXPORT_SYMBOL_GPL(led_trigger_register_simple);
+
+ void led_trigger_unregister_simple(struct led_trigger *trigger)
+ {
+@@ -228,21 +248,7 @@ void led_trigger_unregister_simple(struct led_trigger *trigger)
+ led_trigger_unregister(trigger);
+ kfree(trigger);
+ }
+-
+-/* Used by LED Class */
+-EXPORT_SYMBOL_GPL(led_trigger_set);
+-EXPORT_SYMBOL_GPL(led_trigger_set_default);
+-EXPORT_SYMBOL_GPL(led_trigger_show);
+-EXPORT_SYMBOL_GPL(led_trigger_store);
+-
+-/* LED Trigger Interface */
+-EXPORT_SYMBOL_GPL(led_trigger_register);
+-EXPORT_SYMBOL_GPL(led_trigger_unregister);
+-
+-/* Simple LED Tigger Interface */
+-EXPORT_SYMBOL_GPL(led_trigger_register_simple);
+ EXPORT_SYMBOL_GPL(led_trigger_unregister_simple);
+-EXPORT_SYMBOL_GPL(led_trigger_event);
+
+ MODULE_AUTHOR("Richard Purdie");
+ MODULE_LICENSE("GPL");
+diff --git a/drivers/leds/leds-clevo-mail.c b/drivers/leds/leds-clevo-mail.c
+index 5750b08..eb3415e 100644
+--- a/drivers/leds/leds-clevo-mail.c
++++ b/drivers/leds/leds-clevo-mail.c
+@@ -14,7 +14,7 @@
+ #define CLEVO_MAIL_LED_BLINK_1HZ 0x008A
+ #define CLEVO_MAIL_LED_BLINK_0_5HZ 0x0083
+
+-MODULE_AUTHOR("Márton Németh <nm127 at freemail.hu>");
++MODULE_AUTHOR("Márton Németh <nm127 at freemail.hu>");
+ MODULE_DESCRIPTION("Clevo mail LED driver");
+ MODULE_LICENSE("GPL");
+
+@@ -69,6 +69,16 @@ static struct dmi_system_id __initdata mail_led_whitelist[] = {
+ },
+ {
+ .callback = clevo_mail_led_dmi_callback,
++ .ident = "Clevo D400P",
++ .matches = {
++ DMI_MATCH(DMI_BOARD_VENDOR, "Clevo"),
++ DMI_MATCH(DMI_BOARD_NAME, "D400P"),
++ DMI_MATCH(DMI_BOARD_VERSION, "Rev.A"),
++ DMI_MATCH(DMI_PRODUCT_VERSION, "0106")
++ }
++ },
++ {
++ .callback = clevo_mail_led_dmi_callback,
+ .ident = "Clevo D410V",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Clevo, Co."),
+@@ -93,8 +103,8 @@ static void clevo_mail_led_set(struct led_classdev *led_cdev,
+ }
+
+ static int clevo_mail_led_blink(struct led_classdev *led_cdev,
+- unsigned long* delay_on,
+- unsigned long* delay_off)
++ unsigned long *delay_on,
++ unsigned long *delay_off)
+ {
+ int status = -EINVAL;
+
+diff --git a/drivers/leds/leds-cobalt-qube.c b/drivers/leds/leds-cobalt-qube.c
+index 096881a..059aa29 100644
+--- a/drivers/leds/leds-cobalt-qube.c
++++ b/drivers/leds/leds-cobalt-qube.c
+@@ -18,7 +18,7 @@ static void __iomem *led_port;
+ static u8 led_value;
+
+ static void qube_front_led_set(struct led_classdev *led_cdev,
+- enum led_brightness brightness)
++ enum led_brightness brightness)
+ {
+ if (brightness)
+ led_value = LED_FRONT_LEFT | LED_FRONT_RIGHT;
+diff --git a/drivers/leds/leds-cobalt-raq.c b/drivers/leds/leds-cobalt-raq.c
+index 6ebfff3..ff0e8c3 100644
+--- a/drivers/leds/leds-cobalt-raq.c
++++ b/drivers/leds/leds-cobalt-raq.c
+@@ -15,7 +15,7 @@
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+ #include <linux/init.h>
+ #include <linux/io.h>
+@@ -33,7 +33,7 @@ static u8 led_value;
+ static DEFINE_SPINLOCK(led_value_lock);
+
+ static void raq_web_led_set(struct led_classdev *led_cdev,
+- enum led_brightness brightness)
++ enum led_brightness brightness)
+ {
+ unsigned long flags;
+
+@@ -54,7 +54,7 @@ static struct led_classdev raq_web_led = {
+ };
+
+ static void raq_power_off_led_set(struct led_classdev *led_cdev,
+- enum led_brightness brightness)
++ enum led_brightness brightness)
+ {
+ unsigned long flags;
+
+diff --git a/drivers/leds/leds-corgi.c b/drivers/leds/leds-corgi.c
+index 29e931f..a709704 100644
+--- a/drivers/leds/leds-corgi.c
++++ b/drivers/leds/leds-corgi.c
+@@ -21,7 +21,8 @@
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/hardware/scoop.h>
+
+-static void corgiled_amber_set(struct led_classdev *led_cdev, enum led_brightness value)
++static void corgiled_amber_set(struct led_classdev *led_cdev,
++ enum led_brightness value)
+ {
+ if (value)
+ GPSR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE);
+@@ -29,7 +30,8 @@ static void corgiled_amber_set(struct led_classdev *led_cdev, enum led_brightnes
+ GPCR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE);
+ }
+
+-static void corgiled_green_set(struct led_classdev *led_cdev, enum led_brightness value)
++static void corgiled_green_set(struct led_classdev *led_cdev,
++ enum led_brightness value)
+ {
+ if (value)
+ set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN);
+@@ -53,7 +55,8 @@ static struct led_classdev corgi_green_led = {
+ static int corgiled_suspend(struct platform_device *dev, pm_message_t state)
+ {
+ #ifdef CONFIG_LEDS_TRIGGERS
+- if (corgi_amber_led.trigger && strcmp(corgi_amber_led.trigger->name, "sharpsl-charge"))
++ if (corgi_amber_led.trigger &&
++ strcmp(corgi_amber_led.trigger->name, "sharpsl-charge"))
+ #endif
+ led_classdev_suspend(&corgi_amber_led);
+ led_classdev_suspend(&corgi_green_led);
+@@ -110,7 +113,7 @@ static int __init corgiled_init(void)
+
+ static void __exit corgiled_exit(void)
+ {
+- platform_driver_unregister(&corgiled_driver);
++ platform_driver_unregister(&corgiled_driver);
+ }
+
+ module_init(corgiled_init);
+diff --git a/drivers/leds/leds-fsg.c b/drivers/leds/leds-fsg.c
+new file mode 100644
+index 0000000..a7421b8
+--- /dev/null
++++ b/drivers/leds/leds-fsg.c
+@@ -0,0 +1,261 @@
++/*
++ * LED Driver for the Freecom FSG-3
++ *
++ * Copyright (c) 2008 Rod Whitby <rod at whitby.id.au>
++ *
++ * Author: Rod Whitby <rod at whitby.id.au>
++ *
++ * Based on leds-spitz.c
++ * Copyright 2005-2006 Openedhand Ltd.
++ * Author: Richard Purdie <rpurdie at openedhand.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/leds.h>
++#include <asm/arch/hardware.h>
++#include <asm/io.h>
++
++static short __iomem *latch_address;
++static unsigned short latch_value;
++
++
++static void fsg_led_wlan_set(struct led_classdev *led_cdev,
++ enum led_brightness value)
++{
++ if (value) {
++ latch_value &= ~(1 << FSG_LED_WLAN_BIT);
++ *latch_address = latch_value;
++ } else {
++ latch_value |= (1 << FSG_LED_WLAN_BIT);
++ *latch_address = latch_value;
++ }
++}
++
++static void fsg_led_wan_set(struct led_classdev *led_cdev,
++ enum led_brightness value)
++{
++ if (value) {
++ latch_value &= ~(1 << FSG_LED_WAN_BIT);
++ *latch_address = latch_value;
++ } else {
++ latch_value |= (1 << FSG_LED_WAN_BIT);
++ *latch_address = latch_value;
++ }
++}
++
++static void fsg_led_sata_set(struct led_classdev *led_cdev,
++ enum led_brightness value)
++{
++ if (value) {
++ latch_value &= ~(1 << FSG_LED_SATA_BIT);
++ *latch_address = latch_value;
++ } else {
++ latch_value |= (1 << FSG_LED_SATA_BIT);
++ *latch_address = latch_value;
++ }
++}
++
++static void fsg_led_usb_set(struct led_classdev *led_cdev,
++ enum led_brightness value)
++{
++ if (value) {
++ latch_value &= ~(1 << FSG_LED_USB_BIT);
++ *latch_address = latch_value;
++ } else {
++ latch_value |= (1 << FSG_LED_USB_BIT);
++ *latch_address = latch_value;
++ }
++}
++
++static void fsg_led_sync_set(struct led_classdev *led_cdev,
++ enum led_brightness value)
++{
++ if (value) {
++ latch_value &= ~(1 << FSG_LED_SYNC_BIT);
++ *latch_address = latch_value;
++ } else {
++ latch_value |= (1 << FSG_LED_SYNC_BIT);
++ *latch_address = latch_value;
++ }
++}
++
++static void fsg_led_ring_set(struct led_classdev *led_cdev,
++ enum led_brightness value)
++{
++ if (value) {
++ latch_value &= ~(1 << FSG_LED_RING_BIT);
++ *latch_address = latch_value;
++ } else {
++ latch_value |= (1 << FSG_LED_RING_BIT);
++ *latch_address = latch_value;
++ }
++}
++
++
++
++static struct led_classdev fsg_wlan_led = {
++ .name = "fsg:blue:wlan",
++ .brightness_set = fsg_led_wlan_set,
++};
++
++static struct led_classdev fsg_wan_led = {
++ .name = "fsg:blue:wan",
++ .brightness_set = fsg_led_wan_set,
++};
++
++static struct led_classdev fsg_sata_led = {
++ .name = "fsg:blue:sata",
++ .brightness_set = fsg_led_sata_set,
++};
++
++static struct led_classdev fsg_usb_led = {
++ .name = "fsg:blue:usb",
++ .brightness_set = fsg_led_usb_set,
++};
++
++static struct led_classdev fsg_sync_led = {
++ .name = "fsg:blue:sync",
++ .brightness_set = fsg_led_sync_set,
++};
++
++static struct led_classdev fsg_ring_led = {
++ .name = "fsg:blue:ring",
++ .brightness_set = fsg_led_ring_set,
++};
++
++
++
++#ifdef CONFIG_PM
++static int fsg_led_suspend(struct platform_device *dev, pm_message_t state)
++{
++ led_classdev_suspend(&fsg_wlan_led);
++ led_classdev_suspend(&fsg_wan_led);
++ led_classdev_suspend(&fsg_sata_led);
++ led_classdev_suspend(&fsg_usb_led);
++ led_classdev_suspend(&fsg_sync_led);
++ led_classdev_suspend(&fsg_ring_led);
++ return 0;
++}
++
++static int fsg_led_resume(struct platform_device *dev)
++{
++ led_classdev_resume(&fsg_wlan_led);
++ led_classdev_resume(&fsg_wan_led);
++ led_classdev_resume(&fsg_sata_led);
++ led_classdev_resume(&fsg_usb_led);
++ led_classdev_resume(&fsg_sync_led);
++ led_classdev_resume(&fsg_ring_led);
++ return 0;
++}
++#endif
++
++
++static int fsg_led_probe(struct platform_device *pdev)
++{
++ int ret;
++
++ ret = led_classdev_register(&pdev->dev, &fsg_wlan_led);
++ if (ret < 0)
++ goto failwlan;
++
++ ret = led_classdev_register(&pdev->dev, &fsg_wan_led);
++ if (ret < 0)
++ goto failwan;
++
++ ret = led_classdev_register(&pdev->dev, &fsg_sata_led);
++ if (ret < 0)
++ goto failsata;
++
++ ret = led_classdev_register(&pdev->dev, &fsg_usb_led);
++ if (ret < 0)
++ goto failusb;
++
++ ret = led_classdev_register(&pdev->dev, &fsg_sync_led);
++ if (ret < 0)
++ goto failsync;
++
++ ret = led_classdev_register(&pdev->dev, &fsg_ring_led);
++ if (ret < 0)
++ goto failring;
++
++ /* Map the LED chip select address space */
++ latch_address = (unsigned short *) ioremap(IXP4XX_EXP_BUS_BASE(2), 512);
++ if (!latch_address) {
++ ret = -ENOMEM;
++ goto failremap;
++ }
++
++ latch_value = 0xffff;
++ *latch_address = latch_value;
++
++ return ret;
++
++ failremap:
++ led_classdev_unregister(&fsg_ring_led);
++ failring:
++ led_classdev_unregister(&fsg_sync_led);
++ failsync:
++ led_classdev_unregister(&fsg_usb_led);
++ failusb:
++ led_classdev_unregister(&fsg_sata_led);
++ failsata:
++ led_classdev_unregister(&fsg_wan_led);
++ failwan:
++ led_classdev_unregister(&fsg_wlan_led);
++ failwlan:
++
++ return ret;
++}
++
++static int fsg_led_remove(struct platform_device *pdev)
++{
++ iounmap(latch_address);
++
++ led_classdev_unregister(&fsg_wlan_led);
++ led_classdev_unregister(&fsg_wan_led);
++ led_classdev_unregister(&fsg_sata_led);
++ led_classdev_unregister(&fsg_usb_led);
++ led_classdev_unregister(&fsg_sync_led);
++ led_classdev_unregister(&fsg_ring_led);
++
++ return 0;
++}
++
++
++static struct platform_driver fsg_led_driver = {
++ .probe = fsg_led_probe,
++ .remove = fsg_led_remove,
++#ifdef CONFIG_PM
++ .suspend = fsg_led_suspend,
++ .resume = fsg_led_resume,
++#endif
++ .driver = {
++ .name = "fsg-led",
++ },
++};
++
++
++static int __init fsg_led_init(void)
++{
++ return platform_driver_register(&fsg_led_driver);
++}
++
++static void __exit fsg_led_exit(void)
++{
++ platform_driver_unregister(&fsg_led_driver);
++}
++
++
++module_init(fsg_led_init);
++module_exit(fsg_led_exit);
++
++MODULE_AUTHOR("Rod Whitby <rod at whitby.id.au>");
++MODULE_DESCRIPTION("Freecom FSG-3 LED driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
+index 1aae8b3..b13bd29 100644
+--- a/drivers/leds/leds-gpio.c
++++ b/drivers/leds/leds-gpio.c
+@@ -24,6 +24,8 @@ struct gpio_led_data {
+ u8 new_level;
+ u8 can_sleep;
+ u8 active_low;
++ int (*platform_gpio_blink_set)(unsigned gpio,
++ unsigned long *delay_on, unsigned long *delay_off);
+ };
+
+ static void gpio_led_work(struct work_struct *work)
+@@ -60,6 +62,15 @@ static void gpio_led_set(struct led_classdev *led_cdev,
+ gpio_set_value(led_dat->gpio, level);
+ }
+
++static int gpio_blink_set(struct led_classdev *led_cdev,
++ unsigned long *delay_on, unsigned long *delay_off)
++{
++ struct gpio_led_data *led_dat =
++ container_of(led_cdev, struct gpio_led_data, cdev);
++
++ return led_dat->platform_gpio_blink_set(led_dat->gpio, delay_on, delay_off);
++}
++
+ static int gpio_led_probe(struct platform_device *pdev)
+ {
+ struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
+@@ -88,6 +99,10 @@ static int gpio_led_probe(struct platform_device *pdev)
+ led_dat->gpio = cur_led->gpio;
+ led_dat->can_sleep = gpio_cansleep(cur_led->gpio);
+ led_dat->active_low = cur_led->active_low;
++ if (pdata->gpio_blink_set) {
++ led_dat->platform_gpio_blink_set = pdata->gpio_blink_set;
++ led_dat->cdev.blink_set = gpio_blink_set;
++ }
+ led_dat->cdev.brightness_set = gpio_led_set;
+ led_dat->cdev.brightness = LED_OFF;
+
+diff --git a/drivers/leds/leds-h1940.c b/drivers/leds/leds-h1940.c
+index 6e51c9b..bcec422 100644
+--- a/drivers/leds/leds-h1940.c
++++ b/drivers/leds/leds-h1940.c
+@@ -26,20 +26,20 @@
+ void h1940_greenled_set(struct led_classdev *led_dev, enum led_brightness value)
+ {
+ switch (value) {
+- case LED_HALF:
+- h1940_latch_control(0,H1940_LATCH_LED_FLASH);
+- s3c2410_gpio_setpin(S3C2410_GPA7,1);
+- break;
+- case LED_FULL:
+- h1940_latch_control(0,H1940_LATCH_LED_GREEN);
+- s3c2410_gpio_setpin(S3C2410_GPA7,1);
+- break;
+- default:
+- case LED_OFF:
+- h1940_latch_control(H1940_LATCH_LED_FLASH,0);
+- h1940_latch_control(H1940_LATCH_LED_GREEN,0);
+- s3c2410_gpio_setpin(S3C2410_GPA7,0);
+- break;
++ case LED_HALF:
++ h1940_latch_control(0, H1940_LATCH_LED_FLASH);
++ s3c2410_gpio_setpin(S3C2410_GPA7, 1);
++ break;
++ case LED_FULL:
++ h1940_latch_control(0, H1940_LATCH_LED_GREEN);
++ s3c2410_gpio_setpin(S3C2410_GPA7, 1);
++ break;
++ default:
++ case LED_OFF:
++ h1940_latch_control(H1940_LATCH_LED_FLASH, 0);
++ h1940_latch_control(H1940_LATCH_LED_GREEN, 0);
++ s3c2410_gpio_setpin(S3C2410_GPA7, 0);
++ break;
+ }
+ }
+
+@@ -55,20 +55,20 @@ static struct led_classdev h1940_greenled = {
+ void h1940_redled_set(struct led_classdev *led_dev, enum led_brightness value)
+ {
+ switch (value) {
+- case LED_HALF:
+- h1940_latch_control(0,H1940_LATCH_LED_FLASH);
+- s3c2410_gpio_setpin(S3C2410_GPA1,1);
+- break;
+- case LED_FULL:
+- h1940_latch_control(0,H1940_LATCH_LED_RED);
+- s3c2410_gpio_setpin(S3C2410_GPA1,1);
+- break;
+- default:
+- case LED_OFF:
+- h1940_latch_control(H1940_LATCH_LED_FLASH,0);
+- h1940_latch_control(H1940_LATCH_LED_RED,0);
+- s3c2410_gpio_setpin(S3C2410_GPA1,0);
+- break;
++ case LED_HALF:
++ h1940_latch_control(0, H1940_LATCH_LED_FLASH);
++ s3c2410_gpio_setpin(S3C2410_GPA1, 1);
++ break;
++ case LED_FULL:
++ h1940_latch_control(0, H1940_LATCH_LED_RED);
++ s3c2410_gpio_setpin(S3C2410_GPA1, 1);
++ break;
++ default:
++ case LED_OFF:
++ h1940_latch_control(H1940_LATCH_LED_FLASH, 0);
++ h1940_latch_control(H1940_LATCH_LED_RED, 0);
++ s3c2410_gpio_setpin(S3C2410_GPA1, 0);
++ break;
+ }
+ }
+
+@@ -86,11 +86,11 @@ void h1940_blueled_set(struct led_classdev *led_dev, enum led_brightness value)
+ {
+ if (value) {
+ /* flashing Blue */
+- h1940_latch_control(0,H1940_LATCH_LED_FLASH);
+- s3c2410_gpio_setpin(S3C2410_GPA3,1);
++ h1940_latch_control(0, H1940_LATCH_LED_FLASH);
++ s3c2410_gpio_setpin(S3C2410_GPA3, 1);
+ } else {
+- h1940_latch_control(H1940_LATCH_LED_FLASH,0);
+- s3c2410_gpio_setpin(S3C2410_GPA3,0);
++ h1940_latch_control(H1940_LATCH_LED_FLASH, 0);
++ s3c2410_gpio_setpin(S3C2410_GPA3, 0);
+ }
+
+ }
+diff --git a/drivers/leds/leds-hp6xx.c b/drivers/leds/leds-hp6xx.c
+index 870f5a3..844d597 100644
+--- a/drivers/leds/leds-hp6xx.c
++++ b/drivers/leds/leds-hp6xx.c
+@@ -17,7 +17,8 @@
+ #include <asm/hd64461.h>
+ #include <asm/hp6xx.h>
+
+-static void hp6xxled_green_set(struct led_classdev *led_cdev, enum led_brightness value)
++static void hp6xxled_green_set(struct led_classdev *led_cdev,
++ enum led_brightness value)
+ {
+ u8 v8;
+
+@@ -28,7 +29,8 @@ static void hp6xxled_green_set(struct led_classdev *led_cdev, enum led_brightnes
+ outb(v8 | PKDR_LED_GREEN, PKDR);
+ }
+
+-static void hp6xxled_red_set(struct led_classdev *led_cdev, enum led_brightness value)
++static void hp6xxled_red_set(struct led_classdev *led_cdev,
++ enum led_brightness value)
+ {
+ u16 v16;
+
+diff --git a/drivers/leds/leds-s3c24xx.c b/drivers/leds/leds-s3c24xx.c
+index 0d10e11..d4f5021 100644
+--- a/drivers/leds/leds-s3c24xx.c
++++ b/drivers/leds/leds-s3c24xx.c
+@@ -51,7 +51,7 @@ static void s3c24xx_led_set(struct led_classdev *led_cdev,
+
+ if (pd->flags & S3C24XX_LEDF_TRISTATE)
+ s3c2410_gpio_cfgpin(pd->gpio,
+- value ? S3C2410_GPIO_OUTPUT : S3C2410_GPIO_INPUT);
++ value ? S3C2410_GPIO_OUTPUT : S3C2410_GPIO_INPUT);
+
+ }
+
+@@ -151,7 +151,7 @@ static int __init s3c24xx_led_init(void)
+
+ static void __exit s3c24xx_led_exit(void)
+ {
+- platform_driver_unregister(&s3c24xx_led_driver);
++ platform_driver_unregister(&s3c24xx_led_driver);
+ }
+
+ module_init(s3c24xx_led_init);
+diff --git a/drivers/leds/leds-spitz.c b/drivers/leds/leds-spitz.c
+index 87007cc..e75e854 100644
+--- a/drivers/leds/leds-spitz.c
++++ b/drivers/leds/leds-spitz.c
+@@ -21,7 +21,8 @@
+ #include <asm/arch/pxa-regs.h>
+ #include <asm/arch/spitz.h>
+
+-static void spitzled_amber_set(struct led_classdev *led_cdev, enum led_brightness value)
++static void spitzled_amber_set(struct led_classdev *led_cdev,
++ enum led_brightness value)
+ {
+ if (value)
+ set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE);
+@@ -29,7 +30,8 @@ static void spitzled_amber_set(struct led_classdev *led_cdev, enum led_brightnes
+ reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE);
+ }
+
+-static void spitzled_green_set(struct led_classdev *led_cdev, enum led_brightness value)
++static void spitzled_green_set(struct led_classdev *led_cdev,
++ enum led_brightness value)
+ {
+ if (value)
+ set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN);
+@@ -53,7 +55,8 @@ static struct led_classdev spitz_green_led = {
+ static int spitzled_suspend(struct platform_device *dev, pm_message_t state)
+ {
+ #ifdef CONFIG_LEDS_TRIGGERS
+- if (spitz_amber_led.trigger && strcmp(spitz_amber_led.trigger->name, "sharpsl-charge"))
++ if (spitz_amber_led.trigger &&
++ strcmp(spitz_amber_led.trigger->name, "sharpsl-charge"))
+ #endif
+ led_classdev_suspend(&spitz_amber_led);
+ led_classdev_suspend(&spitz_green_led);
+@@ -116,7 +119,7 @@ static int __init spitzled_init(void)
+
+ static void __exit spitzled_exit(void)
+ {
+- platform_driver_unregister(&spitzled_driver);
++ platform_driver_unregister(&spitzled_driver);
+ }
+
+ module_init(spitzled_init);
+diff --git a/drivers/leds/leds-tosa.c b/drivers/leds/leds-tosa.c
+deleted file mode 100644
+index 7ebecc4..0000000
+--- a/drivers/leds/leds-tosa.c
++++ /dev/null
+@@ -1,132 +0,0 @@
+-/*
+- * LED Triggers Core
+- *
+- * Copyright 2005 Dirk Opfer
+- *
+- * Author: Dirk Opfer <Dirk at Opfer-Online.de>
+- * based on spitz.c
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- *
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/platform_device.h>
+-#include <linux/leds.h>
+-#include <asm/hardware/scoop.h>
+-#include <asm/mach-types.h>
+-#include <asm/arch/hardware.h>
+-#include <asm/arch/pxa-regs.h>
+-#include <asm/arch/tosa.h>
+-
+-static void tosaled_amber_set(struct led_classdev *led_cdev,
+- enum led_brightness value)
+-{
+- if (value)
+- set_scoop_gpio(&tosascoop_jc_device.dev,
+- TOSA_SCOOP_JC_CHRG_ERR_LED);
+- else
+- reset_scoop_gpio(&tosascoop_jc_device.dev,
+- TOSA_SCOOP_JC_CHRG_ERR_LED);
+-}
+-
+-static void tosaled_green_set(struct led_classdev *led_cdev,
+- enum led_brightness value)
+-{
+- if (value)
+- set_scoop_gpio(&tosascoop_jc_device.dev,
+- TOSA_SCOOP_JC_NOTE_LED);
+- else
+- reset_scoop_gpio(&tosascoop_jc_device.dev,
+- TOSA_SCOOP_JC_NOTE_LED);
+-}
+-
+-static struct led_classdev tosa_amber_led = {
+- .name = "tosa:amber:charge",
+- .default_trigger = "sharpsl-charge",
+- .brightness_set = tosaled_amber_set,
+-};
+-
+-static struct led_classdev tosa_green_led = {
+- .name = "tosa:green:mail",
+- .default_trigger = "nand-disk",
+- .brightness_set = tosaled_green_set,
+-};
+-
+-#ifdef CONFIG_PM
+-static int tosaled_suspend(struct platform_device *dev, pm_message_t state)
+-{
+-#ifdef CONFIG_LEDS_TRIGGERS
+- if (tosa_amber_led.trigger && strcmp(tosa_amber_led.trigger->name,
+- "sharpsl-charge"))
+-#endif
+- led_classdev_suspend(&tosa_amber_led);
+- led_classdev_suspend(&tosa_green_led);
+- return 0;
+-}
+-
+-static int tosaled_resume(struct platform_device *dev)
+-{
+- led_classdev_resume(&tosa_amber_led);
+- led_classdev_resume(&tosa_green_led);
+- return 0;
+-}
+-#else
+-#define tosaled_suspend NULL
+-#define tosaled_resume NULL
+-#endif
+-
+-static int tosaled_probe(struct platform_device *pdev)
+-{
+- int ret;
+-
+- ret = led_classdev_register(&pdev->dev, &tosa_amber_led);
+- if (ret < 0)
+- return ret;
+-
+- ret = led_classdev_register(&pdev->dev, &tosa_green_led);
+- if (ret < 0)
+- led_classdev_unregister(&tosa_amber_led);
+-
+- return ret;
+-}
+-
+-static int tosaled_remove(struct platform_device *pdev)
+-{
+- led_classdev_unregister(&tosa_amber_led);
+- led_classdev_unregister(&tosa_green_led);
+-
+- return 0;
+-}
+-
+-static struct platform_driver tosaled_driver = {
+- .probe = tosaled_probe,
+- .remove = tosaled_remove,
+- .suspend = tosaled_suspend,
+- .resume = tosaled_resume,
+- .driver = {
+- .name = "tosa-led",
+- .owner = THIS_MODULE,
+- },
+-};
+-
+-static int __init tosaled_init(void)
+-{
+- return platform_driver_register(&tosaled_driver);
+-}
+-
+-static void __exit tosaled_exit(void)
+-{
+- platform_driver_unregister(&tosaled_driver);
+-}
+-
+-module_init(tosaled_init);
+-module_exit(tosaled_exit);
+-
+-MODULE_AUTHOR("Dirk Opfer <Dirk at Opfer-Online.de>");
+-MODULE_DESCRIPTION("Tosa LED driver");
+-MODULE_LICENSE("GPL");
+-MODULE_ALIAS("platform:tosa-led");
+diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h
+index 12b6fe9..5edbf52 100644
+--- a/drivers/leds/leds.h
++++ b/drivers/leds/leds.h
+@@ -27,6 +27,11 @@ static inline void led_set_brightness(struct led_classdev *led_cdev,
+ led_cdev->brightness_set(led_cdev, value);
+ }
+
++static inline int led_get_brightness(struct led_classdev *led_cdev)
++{
++ return led_cdev->brightness;
++}
++
+ extern struct rw_semaphore leds_list_lock;
+ extern struct list_head leds_list;
+
+@@ -34,9 +39,11 @@ extern struct list_head leds_list;
+ void led_trigger_set_default(struct led_classdev *led_cdev);
+ void led_trigger_set(struct led_classdev *led_cdev,
+ struct led_trigger *trigger);
++void led_trigger_remove(struct led_classdev *led_cdev);
+ #else
+-#define led_trigger_set_default(x) do {} while(0)
+-#define led_trigger_set(x, y) do {} while(0)
++#define led_trigger_set_default(x) do {} while (0)
++#define led_trigger_set(x, y) do {} while (0)
++#define led_trigger_remove(x) do {} while (0)
+ #endif
+
+ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
+diff --git a/drivers/leds/ledtrig-default-on.c b/drivers/leds/ledtrig-default-on.c
+new file mode 100644
+index 0000000..92995e4
+--- /dev/null
++++ b/drivers/leds/ledtrig-default-on.c
+@@ -0,0 +1,45 @@
++/*
++ * LED Kernel Default ON Trigger
++ *
++ * Copyright 2008 Nick Forbes <nick.forbes at incepta.com>
++ *
++ * Based on Richard Purdie's ledtrig-timer.c.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/leds.h>
++#include "leds.h"
++
++static void defon_trig_activate(struct led_classdev *led_cdev)
++{
++ led_set_brightness(led_cdev, LED_FULL);
++}
++
++static struct led_trigger defon_led_trigger = {
++ .name = "default-on",
++ .activate = defon_trig_activate,
++};
++
++static int __init defon_trig_init(void)
++{
++ return led_trigger_register(&defon_led_trigger);
++}
++
++static void __exit defon_trig_exit(void)
++{
++ led_trigger_unregister(&defon_led_trigger);
++}
++
++module_init(defon_trig_init);
++module_exit(defon_trig_exit);
++
++MODULE_AUTHOR("Nick Forbes <nick.forbes at incepta.com>");
++MODULE_DESCRIPTION("Default-ON LED trigger");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/leds/ledtrig-ide-disk.c b/drivers/leds/ledtrig-ide-disk.c
+index 54b155c..883a577 100644
+--- a/drivers/leds/ledtrig-ide-disk.c
++++ b/drivers/leds/ledtrig-ide-disk.c
+@@ -38,7 +38,7 @@ static void ledtrig_ide_timerfunc(unsigned long data)
+ if (ide_lastactivity != ide_activity) {
+ ide_lastactivity = ide_activity;
+ led_trigger_event(ledtrig_ide, LED_FULL);
+- mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
++ mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
+ } else {
+ led_trigger_event(ledtrig_ide, LED_OFF);
+ }
+diff --git a/drivers/leds/ledtrig-timer.c b/drivers/leds/ledtrig-timer.c
+index 82c55d6..5c99f4f 100644
+--- a/drivers/leds/ledtrig-timer.c
++++ b/drivers/leds/ledtrig-timer.c
+@@ -25,6 +25,9 @@
+ #include "leds.h"
+
+ struct timer_trig_data {
++ int brightness_on; /* LED brightness during "on" period.
++ * (LED_OFF < brightness_on <= LED_FULL)
++ */
+ unsigned long delay_on; /* milliseconds on */
+ unsigned long delay_off; /* milliseconds off */
+ struct timer_list timer;
+@@ -34,17 +37,26 @@ static void led_timer_function(unsigned long data)
+ {
+ struct led_classdev *led_cdev = (struct led_classdev *) data;
+ struct timer_trig_data *timer_data = led_cdev->trigger_data;
+- unsigned long brightness = LED_OFF;
+- unsigned long delay = timer_data->delay_off;
++ unsigned long brightness;
++ unsigned long delay;
+
+ if (!timer_data->delay_on || !timer_data->delay_off) {
+ led_set_brightness(led_cdev, LED_OFF);
+ return;
+ }
+
+- if (!led_cdev->brightness) {
+- brightness = LED_FULL;
++ brightness = led_get_brightness(led_cdev);
++ if (!brightness) {
++ /* Time to switch the LED on. */
++ brightness = timer_data->brightness_on;
+ delay = timer_data->delay_on;
++ } else {
++ /* Store the current brightness value to be able
++ * to restore it when the delay_off period is over.
++ */
++ timer_data->brightness_on = brightness;
++ brightness = LED_OFF;
++ delay = timer_data->delay_off;
+ }
+
+ led_set_brightness(led_cdev, brightness);
+@@ -52,7 +64,7 @@ static void led_timer_function(unsigned long data)
+ mod_timer(&timer_data->timer, jiffies + msecs_to_jiffies(delay));
+ }
+
+-static ssize_t led_delay_on_show(struct device *dev,
++static ssize_t led_delay_on_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+ {
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+@@ -63,7 +75,7 @@ static ssize_t led_delay_on_show(struct device *dev,
+ return strlen(buf) + 1;
+ }
+
+-static ssize_t led_delay_on_store(struct device *dev,
++static ssize_t led_delay_on_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+ {
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+@@ -87,7 +99,7 @@ static ssize_t led_delay_on_store(struct device *dev,
+ /* try to activate hardware acceleration, if any */
+ if (!led_cdev->blink_set ||
+ led_cdev->blink_set(led_cdev,
+- &timer_data->delay_on, &timer_data->delay_off)) {
++ &timer_data->delay_on, &timer_data->delay_off)) {
+ /* no hardware acceleration, blink via timer */
+ mod_timer(&timer_data->timer, jiffies + 1);
+ }
+@@ -98,7 +110,7 @@ static ssize_t led_delay_on_store(struct device *dev,
+ return ret;
+ }
+
+-static ssize_t led_delay_off_show(struct device *dev,
++static ssize_t led_delay_off_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+ {
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+@@ -109,7 +121,7 @@ static ssize_t led_delay_off_show(struct device *dev,
+ return strlen(buf) + 1;
+ }
+
+-static ssize_t led_delay_off_store(struct device *dev,
++static ssize_t led_delay_off_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+ {
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+@@ -133,7 +145,7 @@ static ssize_t led_delay_off_store(struct device *dev,
+ /* try to activate hardware acceleration, if any */
+ if (!led_cdev->blink_set ||
+ led_cdev->blink_set(led_cdev,
+- &timer_data->delay_on, &timer_data->delay_off)) {
++ &timer_data->delay_on, &timer_data->delay_off)) {
+ /* no hardware acceleration, blink via timer */
+ mod_timer(&timer_data->timer, jiffies + 1);
+ }
+@@ -156,6 +168,9 @@ static void timer_trig_activate(struct led_classdev *led_cdev)
+ if (!timer_data)
+ return;
+
++ timer_data->brightness_on = led_get_brightness(led_cdev);
++ if (timer_data->brightness_on == LED_OFF)
++ timer_data->brightness_on = LED_FULL;
+ led_cdev->trigger_data = timer_data;
+
+ init_timer(&timer_data->timer);
+diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h
+index 2337e1a..005bd04 100644
+--- a/drivers/lguest/lg.h
++++ b/drivers/lguest/lg.h
+@@ -10,7 +10,6 @@
+ #include <linux/wait.h>
+ #include <linux/hrtimer.h>
+ #include <linux/err.h>
+-#include <asm/semaphore.h>
+
+ #include <asm/lguest.h>
+
+diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
+index 2895810..2097820 100644
+--- a/drivers/macintosh/adb.c
++++ b/drivers/macintosh/adb.c
+@@ -37,9 +37,9 @@
+ #include <linux/device.h>
+ #include <linux/kthread.h>
+ #include <linux/platform_device.h>
++#include <linux/semaphore.h>
+
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #ifdef CONFIG_PPC
+ #include <asm/prom.h>
+ #include <asm/machdep.h>
+diff --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c
+index 8930230..cc9f275 100644
+--- a/drivers/macintosh/mac_hid.c
++++ b/drivers/macintosh/mac_hid.c
+@@ -103,6 +103,9 @@ int mac_hid_mouse_emulate_buttons(int caller, unsigned int keycode, int down)
+ return 0;
+ }
+
++static struct lock_class_key emumousebtn_event_class;
++static struct lock_class_key emumousebtn_mutex_class;
++
+ static int emumousebtn_input_register(void)
+ {
+ int ret;
+@@ -111,6 +114,9 @@ static int emumousebtn_input_register(void)
+ if (!emumousebtn)
+ return -ENOMEM;
+
++ lockdep_set_class(&emumousebtn->event_lock, &emumousebtn_event_class);
++ lockdep_set_class(&emumousebtn->mutex, &emumousebtn_mutex_class);
++
+ emumousebtn->name = "Macintosh mouse button emulation";
+ emumousebtn->id.bustype = BUS_ADB;
+ emumousebtn->id.vendor = 0x0001;
+diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
+index bd8a1d1..82add26 100644
+--- a/drivers/macintosh/mediabay.c
++++ b/drivers/macintosh/mediabay.c
+@@ -79,6 +79,7 @@ struct media_bay_info {
+ int sleeping;
+ struct semaphore lock;
+ #ifdef CONFIG_BLK_DEV_IDE_PMAC
++ ide_hwif_t *cd_port;
+ void __iomem *cd_base;
+ int cd_irq;
+ int cd_retry;
+@@ -448,7 +449,7 @@ int check_media_bay_by_base(unsigned long base, int what)
+ }
+
+ int media_bay_set_ide_infos(struct device_node* which_bay, unsigned long base,
+- int irq, int index)
++ int irq, ide_hwif_t *hwif)
+ {
+ int i;
+
+@@ -456,10 +457,11 @@ int media_bay_set_ide_infos(struct device_node* which_bay, unsigned long base,
+ struct media_bay_info* bay = &media_bays[i];
+
+ if (bay->mdev && which_bay == bay->mdev->ofdev.node) {
+- int timeout = 5000;
++ int timeout = 5000, index = hwif->index;
+
+ down(&bay->lock);
+
++ bay->cd_port = hwif;
+ bay->cd_base = (void __iomem *) base;
+ bay->cd_irq = irq;
+
+@@ -551,15 +553,10 @@ static void media_bay_step(int i)
+ bay->timer = 0;
+ bay->state = mb_up;
+ if (bay->cd_index < 0) {
+- hw_regs_t hw;
+-
+ printk("mediabay %d, registering IDE...\n", i);
+ pmu_suspend();
+- ide_init_hwif_ports(&hw, (unsigned long) bay->cd_base, (unsigned long) 0, NULL);
+- hw.irq = bay->cd_irq;
+- hw.chipset = ide_pmac;
+- bay->cd_index =
+- ide_register_hw(&hw, NULL, NULL);
++ ide_port_scan(bay->cd_port);
++ bay->cd_index = bay->cd_port->index;
+ pmu_resume();
+ }
+ if (bay->cd_index == -1) {
+@@ -589,7 +586,7 @@ static void media_bay_step(int i)
+ if (bay->cd_index >= 0) {
+ printk(KERN_DEBUG "Unregistering mb %d ide, index:%d\n", i,
+ bay->cd_index);
+- ide_unregister(bay->cd_index, 1, 1);
++ ide_port_unregister_devices(bay->cd_port);
+ bay->cd_index = -1;
+ }
+ if (bay->cd_retry) {
+diff --git a/drivers/macintosh/windfarm_pm112.c b/drivers/macintosh/windfarm_pm112.c
+index b3fbb45..73d695d 100644
+--- a/drivers/macintosh/windfarm_pm112.c
++++ b/drivers/macintosh/windfarm_pm112.c
+@@ -668,7 +668,7 @@ static struct platform_driver wf_pm112_driver = {
+ .remove = __devexit_p(wf_pm112_remove),
+ .driver = {
+ .name = "windfarm",
+- .bus = &platform_bus_type,
++ .owner = THIS_MODULE,
+ },
+ };
+
+@@ -711,3 +711,4 @@ module_exit(wf_pm112_exit);
+ MODULE_AUTHOR("Paul Mackerras <paulus at samba.org>");
+ MODULE_DESCRIPTION("Thermal control for PowerMac11,2");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:windfarm");
+diff --git a/drivers/macintosh/windfarm_pm81.c b/drivers/macintosh/windfarm_pm81.c
+index f24fa73..abbe206 100644
+--- a/drivers/macintosh/windfarm_pm81.c
++++ b/drivers/macintosh/windfarm_pm81.c
+@@ -770,7 +770,7 @@ static struct platform_driver wf_smu_driver = {
+ .remove = __devexit_p(wf_smu_remove),
+ .driver = {
+ .name = "windfarm",
+- .bus = &platform_bus_type,
++ .owner = THIS_MODULE,
+ },
+ };
+
+@@ -810,4 +810,4 @@ module_exit(wf_smu_exit);
+ MODULE_AUTHOR("Benjamin Herrenschmidt <benh at kernel.crashing.org>");
+ MODULE_DESCRIPTION("Thermal control logic for iMac G5");
+ MODULE_LICENSE("GPL");
+-
++MODULE_ALIAS("platform:windfarm");
+diff --git a/drivers/macintosh/windfarm_pm91.c b/drivers/macintosh/windfarm_pm91.c
+index 26eee69..764c525 100644
+--- a/drivers/macintosh/windfarm_pm91.c
++++ b/drivers/macintosh/windfarm_pm91.c
+@@ -702,7 +702,7 @@ static struct platform_driver wf_smu_driver = {
+ .remove = __devexit_p(wf_smu_remove),
+ .driver = {
+ .name = "windfarm",
+- .bus = &platform_bus_type,
++ .owner = THIS_MODULE,
+ },
+ };
+
+@@ -742,3 +742,4 @@ MODULE_AUTHOR("Benjamin Herrenschmidt <benh at kernel.crashing.org>");
+ MODULE_DESCRIPTION("Thermal control logic for PowerMac9,1");
+ MODULE_LICENSE("GPL");
+
++MODULE_ALIAS("platform:windfarm");
+diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c
+index f449d77..797918d 100644
+--- a/drivers/macintosh/windfarm_smu_sat.c
++++ b/drivers/macintosh/windfarm_smu_sat.c
+@@ -13,7 +13,7 @@
+ #include <linux/init.h>
+ #include <linux/wait.h>
+ #include <linux/i2c.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+ #include <asm/prom.h>
+ #include <asm/smu.h>
+ #include <asm/pmac_low_i2c.h>
+diff --git a/drivers/md/Makefile b/drivers/md/Makefile
+index d9aa7ed..7be09ee 100644
+--- a/drivers/md/Makefile
++++ b/drivers/md/Makefile
+@@ -3,10 +3,10 @@
+ #
+
+ dm-mod-objs := dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \
+- dm-ioctl.o dm-io.o kcopyd.o
++ dm-ioctl.o dm-io.o dm-kcopyd.o
+ dm-multipath-objs := dm-hw-handler.o dm-path-selector.o dm-mpath.o
+ dm-snapshot-objs := dm-snap.o dm-exception-store.o
+-dm-mirror-objs := dm-log.o dm-raid1.o
++dm-mirror-objs := dm-raid1.o
+ dm-rdac-objs := dm-mpath-rdac.o
+ dm-hp-sw-objs := dm-mpath-hp-sw.o
+ md-mod-objs := md.o bitmap.o
+@@ -39,7 +39,7 @@ obj-$(CONFIG_DM_MULTIPATH_EMC) += dm-emc.o
+ obj-$(CONFIG_DM_MULTIPATH_HP) += dm-hp-sw.o
+ obj-$(CONFIG_DM_MULTIPATH_RDAC) += dm-rdac.o
+ obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o
+-obj-$(CONFIG_DM_MIRROR) += dm-mirror.o
++obj-$(CONFIG_DM_MIRROR) += dm-mirror.o dm-log.o
+ obj-$(CONFIG_DM_ZERO) += dm-zero.o
+
+ quiet_cmd_unroll = UNROLL $@
+diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c
+index 5bbce29..41f4080 100644
+--- a/drivers/md/dm-exception-store.c
++++ b/drivers/md/dm-exception-store.c
+@@ -9,13 +9,13 @@
+
+ #include "dm.h"
+ #include "dm-snap.h"
+-#include "dm-io.h"
+-#include "kcopyd.h"
+
+ #include <linux/mm.h>
+ #include <linux/pagemap.h>
+ #include <linux/vmalloc.h>
+ #include <linux/slab.h>
++#include <linux/dm-io.h>
++#include <linux/dm-kcopyd.h>
+
+ #define DM_MSG_PREFIX "snapshots"
+ #define DM_CHUNK_SIZE_DEFAULT_SECTORS 32 /* 16KB */
+@@ -131,7 +131,7 @@ struct pstore {
+
+ static unsigned sectors_to_pages(unsigned sectors)
+ {
+- return sectors / (PAGE_SIZE >> 9);
++ return DIV_ROUND_UP(sectors, PAGE_SIZE >> 9);
+ }
+
+ static int alloc_area(struct pstore *ps)
+@@ -159,7 +159,7 @@ static void free_area(struct pstore *ps)
+ }
+
+ struct mdata_req {
+- struct io_region *where;
++ struct dm_io_region *where;
+ struct dm_io_request *io_req;
+ struct work_struct work;
+ int result;
+@@ -177,7 +177,7 @@ static void do_metadata(struct work_struct *work)
+ */
+ static int chunk_io(struct pstore *ps, uint32_t chunk, int rw, int metadata)
+ {
+- struct io_region where = {
++ struct dm_io_region where = {
+ .bdev = ps->snap->cow->bdev,
+ .sector = ps->snap->chunk_size * chunk,
+ .count = ps->snap->chunk_size,
+diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
+index 8f25f62..4789c42 100644
+--- a/drivers/md/dm-io.c
++++ b/drivers/md/dm-io.c
+@@ -5,13 +5,14 @@
+ * This file is released under the GPL.
+ */
+
+-#include "dm-io.h"
++#include "dm.h"
+
+ #include <linux/bio.h>
+ #include <linux/mempool.h>
+ #include <linux/module.h>
+ #include <linux/sched.h>
+ #include <linux/slab.h>
++#include <linux/dm-io.h>
+
+ struct dm_io_client {
+ mempool_t *pool;
+@@ -20,7 +21,7 @@ struct dm_io_client {
+
+ /* FIXME: can we shrink this ? */
+ struct io {
+- unsigned long error;
++ unsigned long error_bits;
+ atomic_t count;
+ struct task_struct *sleeper;
+ struct dm_io_client *client;
+@@ -107,14 +108,14 @@ static inline unsigned bio_get_region(struct bio *bio)
+ static void dec_count(struct io *io, unsigned int region, int error)
+ {
+ if (error)
+- set_bit(region, &io->error);
++ set_bit(region, &io->error_bits);
+
+ if (atomic_dec_and_test(&io->count)) {
+ if (io->sleeper)
+ wake_up_process(io->sleeper);
+
+ else {
+- unsigned long r = io->error;
++ unsigned long r = io->error_bits;
+ io_notify_fn fn = io->callback;
+ void *context = io->context;
+
+@@ -271,7 +272,7 @@ static void km_dp_init(struct dpages *dp, void *data)
+ /*-----------------------------------------------------------------
+ * IO routines that accept a list of pages.
+ *---------------------------------------------------------------*/
+-static void do_region(int rw, unsigned int region, struct io_region *where,
++static void do_region(int rw, unsigned region, struct dm_io_region *where,
+ struct dpages *dp, struct io *io)
+ {
+ struct bio *bio;
+@@ -320,7 +321,7 @@ static void do_region(int rw, unsigned int region, struct io_region *where,
+ }
+
+ static void dispatch_io(int rw, unsigned int num_regions,
+- struct io_region *where, struct dpages *dp,
++ struct dm_io_region *where, struct dpages *dp,
+ struct io *io, int sync)
+ {
+ int i;
+@@ -347,17 +348,17 @@ static void dispatch_io(int rw, unsigned int num_regions,
+ }
+
+ static int sync_io(struct dm_io_client *client, unsigned int num_regions,
+- struct io_region *where, int rw, struct dpages *dp,
++ struct dm_io_region *where, int rw, struct dpages *dp,
+ unsigned long *error_bits)
+ {
+ struct io io;
+
+- if (num_regions > 1 && rw != WRITE) {
++ if (num_regions > 1 && (rw & RW_MASK) != WRITE) {
+ WARN_ON(1);
+ return -EIO;
+ }
+
+- io.error = 0;
++ io.error_bits = 0;
+ atomic_set(&io.count, 1); /* see dispatch_io() */
+ io.sleeper = current;
+ io.client = client;
+@@ -378,25 +379,25 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions,
+ return -EINTR;
+
+ if (error_bits)
+- *error_bits = io.error;
++ *error_bits = io.error_bits;
+
+- return io.error ? -EIO : 0;
++ return io.error_bits ? -EIO : 0;
+ }
+
+ static int async_io(struct dm_io_client *client, unsigned int num_regions,
+- struct io_region *where, int rw, struct dpages *dp,
++ struct dm_io_region *where, int rw, struct dpages *dp,
+ io_notify_fn fn, void *context)
+ {
+ struct io *io;
+
+- if (num_regions > 1 && rw != WRITE) {
++ if (num_regions > 1 && (rw & RW_MASK) != WRITE) {
+ WARN_ON(1);
+ fn(1, context);
+ return -EIO;
+ }
+
+ io = mempool_alloc(client->pool, GFP_NOIO);
+- io->error = 0;
++ io->error_bits = 0;
+ atomic_set(&io->count, 1); /* see dispatch_io() */
+ io->sleeper = NULL;
+ io->client = client;
+@@ -435,10 +436,15 @@ static int dp_init(struct dm_io_request *io_req, struct dpages *dp)
+ }
+
+ /*
+- * New collapsed (a)synchronous interface
++ * New collapsed (a)synchronous interface.
++ *
++ * If the IO is asynchronous (i.e. it has notify.fn), you must either unplug
++ * the queue with blk_unplug() some time later or set the BIO_RW_SYNC bit in
++ * io_req->bi_rw. If you fail to do one of these, the IO will be submitted to
++ * the disk after q->unplug_delay, which defaults to 3ms in blk-settings.c.
+ */
+ int dm_io(struct dm_io_request *io_req, unsigned num_regions,
+- struct io_region *where, unsigned long *sync_error_bits)
++ struct dm_io_region *where, unsigned long *sync_error_bits)
+ {
+ int r;
+ struct dpages dp;
+diff --git a/drivers/md/dm-io.h b/drivers/md/dm-io.h
+deleted file mode 100644
+index f647e2c..0000000
+--- a/drivers/md/dm-io.h
++++ /dev/null
+@@ -1,79 +0,0 @@
+-/*
+- * Copyright (C) 2003 Sistina Software
+- *
+- * This file is released under the GPL.
+- */
+-
+-#ifndef _DM_IO_H
+-#define _DM_IO_H
+-
+-#include "dm.h"
+-
+-struct io_region {
+- struct block_device *bdev;
+- sector_t sector;
+- sector_t count; /* If this is zero the region is ignored. */
+-};
+-
+-struct page_list {
+- struct page_list *next;
+- struct page *page;
+-};
+-
+-typedef void (*io_notify_fn)(unsigned long error, void *context);
+-
+-enum dm_io_mem_type {
+- DM_IO_PAGE_LIST,/* Page list */
+- DM_IO_BVEC, /* Bio vector */
+- DM_IO_VMA, /* Virtual memory area */
+- DM_IO_KMEM, /* Kernel memory */
+-};
+-
+-struct dm_io_memory {
+- enum dm_io_mem_type type;
+-
+- union {
+- struct page_list *pl;
+- struct bio_vec *bvec;
+- void *vma;
+- void *addr;
+- } ptr;
+-
+- unsigned offset;
+-};
+-
+-struct dm_io_notify {
+- io_notify_fn fn; /* Callback for asynchronous requests */
+- void *context; /* Passed to callback */
+-};
+-
+-/*
+- * IO request structure
+- */
+-struct dm_io_client;
+-struct dm_io_request {
+- int bi_rw; /* READ|WRITE - not READA */
+- struct dm_io_memory mem; /* Memory to use for io */
+- struct dm_io_notify notify; /* Synchronous if notify.fn is NULL */
+- struct dm_io_client *client; /* Client memory handler */
+-};
+-
+-/*
+- * For async io calls, users can alternatively use the dm_io() function below
+- * and dm_io_client_create() to create private mempools for the client.
+- *
+- * Create/destroy may block.
+- */
+-struct dm_io_client *dm_io_client_create(unsigned num_pages);
+-int dm_io_client_resize(unsigned num_pages, struct dm_io_client *client);
+-void dm_io_client_destroy(struct dm_io_client *client);
+-
+-/*
+- * IO interface using private per-client pools.
+- * Each bit in the optional 'sync_error_bits' bitset indicates whether an
+- * error occurred doing io to the corresponding region.
+- */
+-int dm_io(struct dm_io_request *io_req, unsigned num_regions,
+- struct io_region *region, unsigned long *sync_error_bits);
+-
+-#endif
+diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c
+new file mode 100644
+index 0000000..996802b
+--- /dev/null
++++ b/drivers/md/dm-kcopyd.c
+@@ -0,0 +1,654 @@
++/*
++ * Copyright (C) 2002 Sistina Software (UK) Limited.
++ * Copyright (C) 2006 Red Hat GmbH
++ *
++ * This file is released under the GPL.
++ *
++ * Kcopyd provides a simple interface for copying an area of one
++ * block-device to one or more other block-devices, with an asynchronous
++ * completion notification.
++ */
++
++#include <linux/types.h>
++#include <asm/atomic.h>
++#include <linux/blkdev.h>
++#include <linux/fs.h>
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/mempool.h>
++#include <linux/module.h>
++#include <linux/pagemap.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++#include <linux/workqueue.h>
++#include <linux/mutex.h>
++#include <linux/dm-kcopyd.h>
++
++#include "dm.h"
++
++/*-----------------------------------------------------------------
++ * Each kcopyd client has its own little pool of preallocated
++ * pages for kcopyd io.
++ *---------------------------------------------------------------*/
++struct dm_kcopyd_client {
++ spinlock_t lock;
++ struct page_list *pages;
++ unsigned int nr_pages;
++ unsigned int nr_free_pages;
++
++ struct dm_io_client *io_client;
++
++ wait_queue_head_t destroyq;
++ atomic_t nr_jobs;
++
++ mempool_t *job_pool;
++
++ struct workqueue_struct *kcopyd_wq;
++ struct work_struct kcopyd_work;
++
++/*
++ * We maintain three lists of jobs:
++ *
++ * i) jobs waiting for pages
++ * ii) jobs that have pages, and are waiting for the io to be issued.
++ * iii) jobs that have completed.
++ *
++ * All three of these are protected by job_lock.
++ */
++ spinlock_t job_lock;
++ struct list_head complete_jobs;
++ struct list_head io_jobs;
++ struct list_head pages_jobs;
++};
++
++static void wake(struct dm_kcopyd_client *kc)
++{
++ queue_work(kc->kcopyd_wq, &kc->kcopyd_work);
++}
++
++static struct page_list *alloc_pl(void)
++{
++ struct page_list *pl;
++
++ pl = kmalloc(sizeof(*pl), GFP_KERNEL);
++ if (!pl)
++ return NULL;
++
++ pl->page = alloc_page(GFP_KERNEL);
++ if (!pl->page) {
++ kfree(pl);
++ return NULL;
++ }
++
++ return pl;
++}
++
++static void free_pl(struct page_list *pl)
++{
++ __free_page(pl->page);
++ kfree(pl);
++}
++
++static int kcopyd_get_pages(struct dm_kcopyd_client *kc,
++ unsigned int nr, struct page_list **pages)
++{
++ struct page_list *pl;
++
++ spin_lock(&kc->lock);
++ if (kc->nr_free_pages < nr) {
++ spin_unlock(&kc->lock);
++ return -ENOMEM;
++ }
++
++ kc->nr_free_pages -= nr;
++ for (*pages = pl = kc->pages; --nr; pl = pl->next)
++ ;
++
++ kc->pages = pl->next;
++ pl->next = NULL;
++
++ spin_unlock(&kc->lock);
++
++ return 0;
++}
++
++static void kcopyd_put_pages(struct dm_kcopyd_client *kc, struct page_list *pl)
++{
++ struct page_list *cursor;
++
++ spin_lock(&kc->lock);
++ for (cursor = pl; cursor->next; cursor = cursor->next)
++ kc->nr_free_pages++;
++
++ kc->nr_free_pages++;
++ cursor->next = kc->pages;
++ kc->pages = pl;
++ spin_unlock(&kc->lock);
++}
++
++/*
++ * These three functions resize the page pool.
++ */
++static void drop_pages(struct page_list *pl)
++{
++ struct page_list *next;
++
++ while (pl) {
++ next = pl->next;
++ free_pl(pl);
++ pl = next;
++ }
++}
++
++static int client_alloc_pages(struct dm_kcopyd_client *kc, unsigned int nr)
++{
++ unsigned int i;
++ struct page_list *pl = NULL, *next;
++
++ for (i = 0; i < nr; i++) {
++ next = alloc_pl();
++ if (!next) {
++ if (pl)
++ drop_pages(pl);
++ return -ENOMEM;
++ }
++ next->next = pl;
++ pl = next;
++ }
++
++ kcopyd_put_pages(kc, pl);
++ kc->nr_pages += nr;
++ return 0;
++}
++
++static void client_free_pages(struct dm_kcopyd_client *kc)
++{
++ BUG_ON(kc->nr_free_pages != kc->nr_pages);
++ drop_pages(kc->pages);
++ kc->pages = NULL;
++ kc->nr_free_pages = kc->nr_pages = 0;
++}
++
++/*-----------------------------------------------------------------
++ * kcopyd_jobs need to be allocated by the *clients* of kcopyd,
++ * for this reason we use a mempool to prevent the client from
++ * ever having to do io (which could cause a deadlock).
++ *---------------------------------------------------------------*/
++struct kcopyd_job {
++ struct dm_kcopyd_client *kc;
++ struct list_head list;
++ unsigned long flags;
++
++ /*
++ * Error state of the job.
++ */
++ int read_err;
++ unsigned long write_err;
++
++ /*
++ * Either READ or WRITE
++ */
++ int rw;
++ struct dm_io_region source;
++
++ /*
++ * The destinations for the transfer.
++ */
++ unsigned int num_dests;
++ struct dm_io_region dests[DM_KCOPYD_MAX_REGIONS];
++
++ sector_t offset;
++ unsigned int nr_pages;
++ struct page_list *pages;
++
++ /*
++ * Set this to ensure you are notified when the job has
++ * completed. 'context' is for callback to use.
++ */
++ dm_kcopyd_notify_fn fn;
++ void *context;
++
++ /*
++ * These fields are only used if the job has been split
++ * into more manageable parts.
++ */
++ struct mutex lock;
++ atomic_t sub_jobs;
++ sector_t progress;
++};
++
++/* FIXME: this should scale with the number of pages */
++#define MIN_JOBS 512
++
++static struct kmem_cache *_job_cache;
++
++int __init dm_kcopyd_init(void)
++{
++ _job_cache = KMEM_CACHE(kcopyd_job, 0);
++ if (!_job_cache)
++ return -ENOMEM;
++
++ return 0;
++}
++
++void dm_kcopyd_exit(void)
++{
++ kmem_cache_destroy(_job_cache);
++ _job_cache = NULL;
++}
++
++/*
++ * Functions to push and pop a job onto the head of a given job
++ * list.
++ */
++static struct kcopyd_job *pop(struct list_head *jobs,
++ struct dm_kcopyd_client *kc)
++{
++ struct kcopyd_job *job = NULL;
++ unsigned long flags;
++
++ spin_lock_irqsave(&kc->job_lock, flags);
++
++ if (!list_empty(jobs)) {
++ job = list_entry(jobs->next, struct kcopyd_job, list);
++ list_del(&job->list);
++ }
++ spin_unlock_irqrestore(&kc->job_lock, flags);
++
++ return job;
++}
++
++static void push(struct list_head *jobs, struct kcopyd_job *job)
++{
++ unsigned long flags;
++ struct dm_kcopyd_client *kc = job->kc;
++
++ spin_lock_irqsave(&kc->job_lock, flags);
++ list_add_tail(&job->list, jobs);
++ spin_unlock_irqrestore(&kc->job_lock, flags);
++}
++
++/*
++ * These three functions process 1 item from the corresponding
++ * job list.
++ *
++ * They return:
++ * < 0: error
++ * 0: success
++ * > 0: can't process yet.
++ */
++static int run_complete_job(struct kcopyd_job *job)
++{
++ void *context = job->context;
++ int read_err = job->read_err;
++ unsigned long write_err = job->write_err;
++ dm_kcopyd_notify_fn fn = job->fn;
++ struct dm_kcopyd_client *kc = job->kc;
++
++ kcopyd_put_pages(kc, job->pages);
++ mempool_free(job, kc->job_pool);
++ fn(read_err, write_err, context);
++
++ if (atomic_dec_and_test(&kc->nr_jobs))
++ wake_up(&kc->destroyq);
++
++ return 0;
++}
++
++static void complete_io(unsigned long error, void *context)
++{
++ struct kcopyd_job *job = (struct kcopyd_job *) context;
++ struct dm_kcopyd_client *kc = job->kc;
++
++ if (error) {
++ if (job->rw == WRITE)
++ job->write_err |= error;
++ else
++ job->read_err = 1;
++
++ if (!test_bit(DM_KCOPYD_IGNORE_ERROR, &job->flags)) {
++ push(&kc->complete_jobs, job);
++ wake(kc);
++ return;
++ }
++ }
++
++ if (job->rw == WRITE)
++ push(&kc->complete_jobs, job);
++
++ else {
++ job->rw = WRITE;
++ push(&kc->io_jobs, job);
++ }
++
++ wake(kc);
++}
++
++/*
++ * Request io on as many buffer heads as we can currently get for
++ * a particular job.
++ */
++static int run_io_job(struct kcopyd_job *job)
++{
++ int r;
++ struct dm_io_request io_req = {
++ .bi_rw = job->rw | (1 << BIO_RW_SYNC),
++ .mem.type = DM_IO_PAGE_LIST,
++ .mem.ptr.pl = job->pages,
++ .mem.offset = job->offset,
++ .notify.fn = complete_io,
++ .notify.context = job,
++ .client = job->kc->io_client,
++ };
++
++ if (job->rw == READ)
++ r = dm_io(&io_req, 1, &job->source, NULL);
++ else
++ r = dm_io(&io_req, job->num_dests, job->dests, NULL);
++
++ return r;
++}
++
++static int run_pages_job(struct kcopyd_job *job)
++{
++ int r;
++
++ job->nr_pages = dm_div_up(job->dests[0].count + job->offset,
++ PAGE_SIZE >> 9);
++ r = kcopyd_get_pages(job->kc, job->nr_pages, &job->pages);
++ if (!r) {
++ /* this job is ready for io */
++ push(&job->kc->io_jobs, job);
++ return 0;
++ }
++
++ if (r == -ENOMEM)
++ /* can't complete now */
++ return 1;
++
++ return r;
++}
++
++/*
++ * Run through a list for as long as possible. Returns the count
++ * of successful jobs.
++ */
++static int process_jobs(struct list_head *jobs, struct dm_kcopyd_client *kc,
++ int (*fn) (struct kcopyd_job *))
++{
++ struct kcopyd_job *job;
++ int r, count = 0;
++
++ while ((job = pop(jobs, kc))) {
++
++ r = fn(job);
++
++ if (r < 0) {
++ /* error this rogue job */
++ if (job->rw == WRITE)
++ job->write_err = (unsigned long) -1L;
++ else
++ job->read_err = 1;
++ push(&kc->complete_jobs, job);
++ break;
++ }
++
++ if (r > 0) {
++ /*
++ * We couldn't service this job ATM, so
++ * push this job back onto the list.
++ */
++ push(jobs, job);
++ break;
++ }
++
++ count++;
++ }
++
++ return count;
++}
++
++/*
++ * kcopyd does this every time it's woken up.
++ */
++static void do_work(struct work_struct *work)
++{
++ struct dm_kcopyd_client *kc = container_of(work,
++ struct dm_kcopyd_client, kcopyd_work);
++
++ /*
++ * The order that these are called is *very* important.
++ * complete jobs can free some pages for pages jobs.
++ * Pages jobs when successful will jump onto the io jobs
++ * list. io jobs call wake when they complete and it all
++ * starts again.
++ */
++ process_jobs(&kc->complete_jobs, kc, run_complete_job);
++ process_jobs(&kc->pages_jobs, kc, run_pages_job);
++ process_jobs(&kc->io_jobs, kc, run_io_job);
++}
++
++/*
++ * If we are copying a small region we just dispatch a single job
++ * to do the copy, otherwise the io has to be split up into many
++ * jobs.
++ */
++static void dispatch_job(struct kcopyd_job *job)
++{
++ struct dm_kcopyd_client *kc = job->kc;
++ atomic_inc(&kc->nr_jobs);
++ push(&kc->pages_jobs, job);
++ wake(kc);
++}
++
++#define SUB_JOB_SIZE 128
++static void segment_complete(int read_err, unsigned long write_err,
++ void *context)
++{
++ /* FIXME: tidy this function */
++ sector_t progress = 0;
++ sector_t count = 0;
++ struct kcopyd_job *job = (struct kcopyd_job *) context;
++
++ mutex_lock(&job->lock);
++
++ /* update the error */
++ if (read_err)
++ job->read_err = 1;
++
++ if (write_err)
++ job->write_err |= write_err;
++
++ /*
++ * Only dispatch more work if there hasn't been an error.
++ */
++ if ((!job->read_err && !job->write_err) ||
++ test_bit(DM_KCOPYD_IGNORE_ERROR, &job->flags)) {
++ /* get the next chunk of work */
++ progress = job->progress;
++ count = job->source.count - progress;
++ if (count) {
++ if (count > SUB_JOB_SIZE)
++ count = SUB_JOB_SIZE;
++
++ job->progress += count;
++ }
++ }
++ mutex_unlock(&job->lock);
++
++ if (count) {
++ int i;
++ struct kcopyd_job *sub_job = mempool_alloc(job->kc->job_pool,
++ GFP_NOIO);
++
++ *sub_job = *job;
++ sub_job->source.sector += progress;
++ sub_job->source.count = count;
++
++ for (i = 0; i < job->num_dests; i++) {
++ sub_job->dests[i].sector += progress;
++ sub_job->dests[i].count = count;
++ }
++
++ sub_job->fn = segment_complete;
++ sub_job->context = job;
++ dispatch_job(sub_job);
++
++ } else if (atomic_dec_and_test(&job->sub_jobs)) {
++
++ /*
++ * To avoid a race we must keep the job around
++ * until after the notify function has completed.
++ * Otherwise the client may try and stop the job
++ * after we've completed.
++ */
++ job->fn(read_err, write_err, job->context);
++ mempool_free(job, job->kc->job_pool);
++ }
++}
++
++/*
++ * Create some little jobs that will do the move between
++ * them.
++ */
++#define SPLIT_COUNT 8
++static void split_job(struct kcopyd_job *job)
++{
++ int i;
++
++ atomic_set(&job->sub_jobs, SPLIT_COUNT);
++ for (i = 0; i < SPLIT_COUNT; i++)
++ segment_complete(0, 0u, job);
++}
++
++int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
++ unsigned int num_dests, struct dm_io_region *dests,
++ unsigned int flags, dm_kcopyd_notify_fn fn, void *context)
++{
++ struct kcopyd_job *job;
++
++ /*
++ * Allocate a new job.
++ */
++ job = mempool_alloc(kc->job_pool, GFP_NOIO);
++
++ /*
++ * set up for the read.
++ */
++ job->kc = kc;
++ job->flags = flags;
++ job->read_err = 0;
++ job->write_err = 0;
++ job->rw = READ;
++
++ job->source = *from;
++
++ job->num_dests = num_dests;
++ memcpy(&job->dests, dests, sizeof(*dests) * num_dests);
++
++ job->offset = 0;
++ job->nr_pages = 0;
++ job->pages = NULL;
++
++ job->fn = fn;
++ job->context = context;
++
++ if (job->source.count < SUB_JOB_SIZE)
++ dispatch_job(job);
++
++ else {
++ mutex_init(&job->lock);
++ job->progress = 0;
++ split_job(job);
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL(dm_kcopyd_copy);
++
++/*
++ * Cancels a kcopyd job, eg. someone might be deactivating a
++ * mirror.
++ */
++#if 0
++int kcopyd_cancel(struct kcopyd_job *job, int block)
++{
++ /* FIXME: finish */
++ return -1;
++}
++#endif /* 0 */
++
++/*-----------------------------------------------------------------
++ * Client setup
++ *---------------------------------------------------------------*/
++int dm_kcopyd_client_create(unsigned int nr_pages,
++ struct dm_kcopyd_client **result)
++{
++ int r = -ENOMEM;
++ struct dm_kcopyd_client *kc;
++
++ kc = kmalloc(sizeof(*kc), GFP_KERNEL);
++ if (!kc)
++ return -ENOMEM;
++
++ spin_lock_init(&kc->lock);
++ spin_lock_init(&kc->job_lock);
++ INIT_LIST_HEAD(&kc->complete_jobs);
++ INIT_LIST_HEAD(&kc->io_jobs);
++ INIT_LIST_HEAD(&kc->pages_jobs);
++
++ kc->job_pool = mempool_create_slab_pool(MIN_JOBS, _job_cache);
++ if (!kc->job_pool)
++ goto bad_slab;
++
++ INIT_WORK(&kc->kcopyd_work, do_work);
++ kc->kcopyd_wq = create_singlethread_workqueue("kcopyd");
++ if (!kc->kcopyd_wq)
++ goto bad_workqueue;
++
++ kc->pages = NULL;
++ kc->nr_pages = kc->nr_free_pages = 0;
++ r = client_alloc_pages(kc, nr_pages);
++ if (r)
++ goto bad_client_pages;
++
++ kc->io_client = dm_io_client_create(nr_pages);
++ if (IS_ERR(kc->io_client)) {
++ r = PTR_ERR(kc->io_client);
++ goto bad_io_client;
++ }
++
++ init_waitqueue_head(&kc->destroyq);
++ atomic_set(&kc->nr_jobs, 0);
++
++ *result = kc;
++ return 0;
++
++bad_io_client:
++ client_free_pages(kc);
++bad_client_pages:
++ destroy_workqueue(kc->kcopyd_wq);
++bad_workqueue:
++ mempool_destroy(kc->job_pool);
++bad_slab:
++ kfree(kc);
++
++ return r;
++}
++EXPORT_SYMBOL(dm_kcopyd_client_create);
++
++void dm_kcopyd_client_destroy(struct dm_kcopyd_client *kc)
++{
++ /* Wait for completion of all jobs submitted by this client. */
++ wait_event(kc->destroyq, !atomic_read(&kc->nr_jobs));
++
++ BUG_ON(!list_empty(&kc->complete_jobs));
++ BUG_ON(!list_empty(&kc->io_jobs));
++ BUG_ON(!list_empty(&kc->pages_jobs));
++ destroy_workqueue(kc->kcopyd_wq);
++ dm_io_client_destroy(kc->io_client);
++ client_free_pages(kc);
++ mempool_destroy(kc->job_pool);
++ kfree(kc);
++}
++EXPORT_SYMBOL(dm_kcopyd_client_destroy);
+diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
+index 2a74b21..67a6f31 100644
+--- a/drivers/md/dm-log.c
++++ b/drivers/md/dm-log.c
+@@ -1,5 +1,6 @@
+ /*
+ * Copyright (C) 2003 Sistina Software
++ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the LGPL.
+ */
+@@ -8,64 +9,58 @@
+ #include <linux/slab.h>
+ #include <linux/module.h>
+ #include <linux/vmalloc.h>
++#include <linux/dm-io.h>
++#include <linux/dm-dirty-log.h>
+
+-#include "dm-log.h"
+-#include "dm-io.h"
++#include "dm.h"
+
+-#define DM_MSG_PREFIX "mirror log"
++#define DM_MSG_PREFIX "dirty region log"
+
+-static LIST_HEAD(_log_types);
+-static DEFINE_SPINLOCK(_lock);
++struct dm_dirty_log_internal {
++ struct dm_dirty_log_type *type;
+
+-int dm_register_dirty_log_type(struct dirty_log_type *type)
+-{
+- spin_lock(&_lock);
+- type->use_count = 0;
+- list_add(&type->list, &_log_types);
+- spin_unlock(&_lock);
++ struct list_head list;
++ long use;
++};
+
+- return 0;
+-}
++static LIST_HEAD(_log_types);
++static DEFINE_SPINLOCK(_lock);
+
+-int dm_unregister_dirty_log_type(struct dirty_log_type *type)
++static struct dm_dirty_log_internal *__find_dirty_log_type(const char *name)
+ {
+- spin_lock(&_lock);
+-
+- if (type->use_count)
+- DMWARN("Attempt to unregister a log type that is still in use");
+- else
+- list_del(&type->list);
++ struct dm_dirty_log_internal *log_type;
+
+- spin_unlock(&_lock);
++ list_for_each_entry(log_type, &_log_types, list)
++ if (!strcmp(name, log_type->type->name))
++ return log_type;
+
+- return 0;
++ return NULL;
+ }
+
+-static struct dirty_log_type *_get_type(const char *type_name)
++static struct dm_dirty_log_internal *_get_dirty_log_type(const char *name)
+ {
+- struct dirty_log_type *type;
++ struct dm_dirty_log_internal *log_type;
+
+ spin_lock(&_lock);
+- list_for_each_entry (type, &_log_types, list)
+- if (!strcmp(type_name, type->name)) {
+- if (!type->use_count && !try_module_get(type->module)){
+- spin_unlock(&_lock);
+- return NULL;
+- }
+- type->use_count++;
+- spin_unlock(&_lock);
+- return type;
+- }
++
++ log_type = __find_dirty_log_type(name);
++ if (log_type) {
++ if (!log_type->use && !try_module_get(log_type->type->module))
++ log_type = NULL;
++ else
++ log_type->use++;
++ }
+
+ spin_unlock(&_lock);
+- return NULL;
++
++ return log_type;
+ }
+
+ /*
+ * get_type
+ * @type_name
+ *
+- * Attempt to retrieve the dirty_log_type by name. If not already
++ * Attempt to retrieve the dm_dirty_log_type by name. If not already
+ * available, attempt to load the appropriate module.
+ *
+ * Log modules are named "dm-log-" followed by the 'type_name'.
+@@ -78,14 +73,17 @@ static struct dirty_log_type *_get_type(const char *type_name)
+ *
+ * Returns: dirty_log_type* on success, NULL on failure
+ */
+-static struct dirty_log_type *get_type(const char *type_name)
++static struct dm_dirty_log_type *get_type(const char *type_name)
+ {
+ char *p, *type_name_dup;
+- struct dirty_log_type *type;
++ struct dm_dirty_log_internal *log_type;
++
++ if (!type_name)
++ return NULL;
+
+- type = _get_type(type_name);
+- if (type)
+- return type;
++ log_type = _get_dirty_log_type(type_name);
++ if (log_type)
++ return log_type->type;
+
+ type_name_dup = kstrdup(type_name, GFP_KERNEL);
+ if (!type_name_dup) {
+@@ -95,34 +93,106 @@ static struct dirty_log_type *get_type(const char *type_name)
+ }
+
+ while (request_module("dm-log-%s", type_name_dup) ||
+- !(type = _get_type(type_name))) {
++ !(log_type = _get_dirty_log_type(type_name))) {
+ p = strrchr(type_name_dup, '-');
+ if (!p)
+ break;
+ p[0] = '\0';
+ }
+
+- if (!type)
++ if (!log_type)
+ DMWARN("Module for logging type \"%s\" not found.", type_name);
+
+ kfree(type_name_dup);
+
+- return type;
++ return log_type ? log_type->type : NULL;
+ }
+
+-static void put_type(struct dirty_log_type *type)
++static void put_type(struct dm_dirty_log_type *type)
+ {
++ struct dm_dirty_log_internal *log_type;
++
++ if (!type)
++ return;
++
+ spin_lock(&_lock);
+- if (!--type->use_count)
++ log_type = __find_dirty_log_type(type->name);
++ if (!log_type)
++ goto out;
++
++ if (!--log_type->use)
+ module_put(type->module);
++
++ BUG_ON(log_type->use < 0);
++
++out:
+ spin_unlock(&_lock);
+ }
+
+-struct dirty_log *dm_create_dirty_log(const char *type_name, struct dm_target *ti,
+- unsigned int argc, char **argv)
++static struct dm_dirty_log_internal *_alloc_dirty_log_type(struct dm_dirty_log_type *type)
+ {
+- struct dirty_log_type *type;
+- struct dirty_log *log;
++ struct dm_dirty_log_internal *log_type = kzalloc(sizeof(*log_type),
++ GFP_KERNEL);
++
++ if (log_type)
++ log_type->type = type;
++
++ return log_type;
++}
++
++int dm_dirty_log_type_register(struct dm_dirty_log_type *type)
++{
++ struct dm_dirty_log_internal *log_type = _alloc_dirty_log_type(type);
++ int r = 0;
++
++ if (!log_type)
++ return -ENOMEM;
++
++ spin_lock(&_lock);
++ if (!__find_dirty_log_type(type->name))
++ list_add(&log_type->list, &_log_types);
++ else {
++ kfree(log_type);
++ r = -EEXIST;
++ }
++ spin_unlock(&_lock);
++
++ return r;
++}
++EXPORT_SYMBOL(dm_dirty_log_type_register);
++
++int dm_dirty_log_type_unregister(struct dm_dirty_log_type *type)
++{
++ struct dm_dirty_log_internal *log_type;
++
++ spin_lock(&_lock);
++
++ log_type = __find_dirty_log_type(type->name);
++ if (!log_type) {
++ spin_unlock(&_lock);
++ return -EINVAL;
++ }
++
++ if (log_type->use) {
++ spin_unlock(&_lock);
++ return -ETXTBSY;
++ }
++
++ list_del(&log_type->list);
++
++ spin_unlock(&_lock);
++ kfree(log_type);
++
++ return 0;
++}
++EXPORT_SYMBOL(dm_dirty_log_type_unregister);
++
++struct dm_dirty_log *dm_dirty_log_create(const char *type_name,
++ struct dm_target *ti,
++ unsigned int argc, char **argv)
++{
++ struct dm_dirty_log_type *type;
++ struct dm_dirty_log *log;
+
+ log = kmalloc(sizeof(*log), GFP_KERNEL);
+ if (!log)
+@@ -143,13 +213,15 @@ struct dirty_log *dm_create_dirty_log(const char *type_name, struct dm_target *t
+
+ return log;
+ }
++EXPORT_SYMBOL(dm_dirty_log_create);
+
+-void dm_destroy_dirty_log(struct dirty_log *log)
++void dm_dirty_log_destroy(struct dm_dirty_log *log)
+ {
+ log->type->dtr(log);
+ put_type(log->type);
+ kfree(log);
+ }
++EXPORT_SYMBOL(dm_dirty_log_destroy);
+
+ /*-----------------------------------------------------------------
+ * Persistent and core logs share a lot of their implementation.
+@@ -207,7 +279,7 @@ struct log_c {
+ struct dm_dev *log_dev;
+ struct log_header header;
+
+- struct io_region header_location;
++ struct dm_io_region header_location;
+ struct log_header *disk_header;
+ };
+
+@@ -215,7 +287,7 @@ struct log_c {
+ * The touched member needs to be updated every time we access
+ * one of the bitsets.
+ */
+-static inline int log_test_bit(uint32_t *bs, unsigned bit)
++static inline int log_test_bit(uint32_t *bs, unsigned bit)
+ {
+ return ext2_test_bit(bit, (unsigned long *) bs) ? 1 : 0;
+ }
+@@ -302,7 +374,7 @@ static inline int write_header(struct log_c *log)
+ * argv contains region_size followed optionally by [no]sync
+ *--------------------------------------------------------------*/
+ #define BYTE_SHIFT 3
+-static int create_log_context(struct dirty_log *log, struct dm_target *ti,
++static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
+ unsigned int argc, char **argv,
+ struct dm_dev *dev)
+ {
+@@ -315,7 +387,7 @@ static int create_log_context(struct dirty_log *log, struct dm_target *ti,
+ int r;
+
+ if (argc < 1 || argc > 2) {
+- DMWARN("wrong number of arguments to mirror log");
++ DMWARN("wrong number of arguments to dirty region log");
+ return -EINVAL;
+ }
+
+@@ -325,8 +397,8 @@ static int create_log_context(struct dirty_log *log, struct dm_target *ti,
+ else if (!strcmp(argv[1], "nosync"))
+ sync = NOSYNC;
+ else {
+- DMWARN("unrecognised sync argument to mirror log: %s",
+- argv[1]);
++ DMWARN("unrecognised sync argument to "
++ "dirty region log: %s", argv[1]);
+ return -EINVAL;
+ }
+ }
+@@ -434,7 +506,7 @@ static int create_log_context(struct dirty_log *log, struct dm_target *ti,
+ return 0;
+ }
+
+-static int core_ctr(struct dirty_log *log, struct dm_target *ti,
++static int core_ctr(struct dm_dirty_log *log, struct dm_target *ti,
+ unsigned int argc, char **argv)
+ {
+ return create_log_context(log, ti, argc, argv, NULL);
+@@ -447,7 +519,7 @@ static void destroy_log_context(struct log_c *lc)
+ kfree(lc);
+ }
+
+-static void core_dtr(struct dirty_log *log)
++static void core_dtr(struct dm_dirty_log *log)
+ {
+ struct log_c *lc = (struct log_c *) log->context;
+
+@@ -460,14 +532,14 @@ static void core_dtr(struct dirty_log *log)
+ *
+ * argv contains log_device region_size followed optionally by [no]sync
+ *--------------------------------------------------------------*/
+-static int disk_ctr(struct dirty_log *log, struct dm_target *ti,
++static int disk_ctr(struct dm_dirty_log *log, struct dm_target *ti,
+ unsigned int argc, char **argv)
+ {
+ int r;
+ struct dm_dev *dev;
+
+ if (argc < 2 || argc > 3) {
+- DMWARN("wrong number of arguments to disk mirror log");
++ DMWARN("wrong number of arguments to disk dirty region log");
+ return -EINVAL;
+ }
+
+@@ -485,7 +557,7 @@ static int disk_ctr(struct dirty_log *log, struct dm_target *ti,
+ return 0;
+ }
+
+-static void disk_dtr(struct dirty_log *log)
++static void disk_dtr(struct dm_dirty_log *log)
+ {
+ struct log_c *lc = (struct log_c *) log->context;
+
+@@ -514,7 +586,7 @@ static void fail_log_device(struct log_c *lc)
+ dm_table_event(lc->ti->table);
+ }
+
+-static int disk_resume(struct dirty_log *log)
++static int disk_resume(struct dm_dirty_log *log)
+ {
+ int r;
+ unsigned i;
+@@ -524,7 +596,7 @@ static int disk_resume(struct dirty_log *log)
+ /* read the disk header */
+ r = read_header(lc);
+ if (r) {
+- DMWARN("%s: Failed to read header on mirror log device",
++ DMWARN("%s: Failed to read header on dirty region log device",
+ lc->log_dev->name);
+ fail_log_device(lc);
+ /*
+@@ -562,7 +634,7 @@ static int disk_resume(struct dirty_log *log)
+ /* write the new header */
+ r = write_header(lc);
+ if (r) {
+- DMWARN("%s: Failed to write header on mirror log device",
++ DMWARN("%s: Failed to write header on dirty region log device",
+ lc->log_dev->name);
+ fail_log_device(lc);
+ }
+@@ -570,38 +642,38 @@ static int disk_resume(struct dirty_log *log)
+ return r;
+ }
+
+-static uint32_t core_get_region_size(struct dirty_log *log)
++static uint32_t core_get_region_size(struct dm_dirty_log *log)
+ {
+ struct log_c *lc = (struct log_c *) log->context;
+ return lc->region_size;
+ }
+
+-static int core_resume(struct dirty_log *log)
++static int core_resume(struct dm_dirty_log *log)
+ {
+ struct log_c *lc = (struct log_c *) log->context;
+ lc->sync_search = 0;
+ return 0;
+ }
+
+-static int core_is_clean(struct dirty_log *log, region_t region)
++static int core_is_clean(struct dm_dirty_log *log, region_t region)
+ {
+ struct log_c *lc = (struct log_c *) log->context;
+ return log_test_bit(lc->clean_bits, region);
+ }
+
+-static int core_in_sync(struct dirty_log *log, region_t region, int block)
++static int core_in_sync(struct dm_dirty_log *log, region_t region, int block)
+ {
+ struct log_c *lc = (struct log_c *) log->context;
+ return log_test_bit(lc->sync_bits, region);
+ }
+
+-static int core_flush(struct dirty_log *log)
++static int core_flush(struct dm_dirty_log *log)
+ {
+ /* no op */
+ return 0;
+ }
+
+-static int disk_flush(struct dirty_log *log)
++static int disk_flush(struct dm_dirty_log *log)
+ {
+ int r;
+ struct log_c *lc = (struct log_c *) log->context;
+@@ -619,19 +691,19 @@ static int disk_flush(struct dirty_log *log)
+ return r;
+ }
+
+-static void core_mark_region(struct dirty_log *log, region_t region)
++static void core_mark_region(struct dm_dirty_log *log, region_t region)
+ {
+ struct log_c *lc = (struct log_c *) log->context;
+ log_clear_bit(lc, lc->clean_bits, region);
+ }
+
+-static void core_clear_region(struct dirty_log *log, region_t region)
++static void core_clear_region(struct dm_dirty_log *log, region_t region)
+ {
+ struct log_c *lc = (struct log_c *) log->context;
+ log_set_bit(lc, lc->clean_bits, region);
+ }
+
+-static int core_get_resync_work(struct dirty_log *log, region_t *region)
++static int core_get_resync_work(struct dm_dirty_log *log, region_t *region)
+ {
+ struct log_c *lc = (struct log_c *) log->context;
+
+@@ -654,7 +726,7 @@ static int core_get_resync_work(struct dirty_log *log, region_t *region)
+ return 1;
+ }
+
+-static void core_set_region_sync(struct dirty_log *log, region_t region,
++static void core_set_region_sync(struct dm_dirty_log *log, region_t region,
+ int in_sync)
+ {
+ struct log_c *lc = (struct log_c *) log->context;
+@@ -669,7 +741,7 @@ static void core_set_region_sync(struct dirty_log *log, region_t region,
+ }
+ }
+
+-static region_t core_get_sync_count(struct dirty_log *log)
++static region_t core_get_sync_count(struct dm_dirty_log *log)
+ {
+ struct log_c *lc = (struct log_c *) log->context;
+
+@@ -680,7 +752,7 @@ static region_t core_get_sync_count(struct dirty_log *log)
+ if (lc->sync != DEFAULTSYNC) \
+ DMEMIT("%ssync ", lc->sync == NOSYNC ? "no" : "")
+
+-static int core_status(struct dirty_log *log, status_type_t status,
++static int core_status(struct dm_dirty_log *log, status_type_t status,
+ char *result, unsigned int maxlen)
+ {
+ int sz = 0;
+@@ -700,7 +772,7 @@ static int core_status(struct dirty_log *log, status_type_t status,
+ return sz;
+ }
+
+-static int disk_status(struct dirty_log *log, status_type_t status,
++static int disk_status(struct dm_dirty_log *log, status_type_t status,
+ char *result, unsigned int maxlen)
+ {
+ int sz = 0;
+@@ -722,7 +794,7 @@ static int disk_status(struct dirty_log *log, status_type_t status,
+ return sz;
+ }
+
+-static struct dirty_log_type _core_type = {
++static struct dm_dirty_log_type _core_type = {
+ .name = "core",
+ .module = THIS_MODULE,
+ .ctr = core_ctr,
+@@ -740,7 +812,7 @@ static struct dirty_log_type _core_type = {
+ .status = core_status,
+ };
+
+-static struct dirty_log_type _disk_type = {
++static struct dm_dirty_log_type _disk_type = {
+ .name = "disk",
+ .module = THIS_MODULE,
+ .ctr = disk_ctr,
+@@ -763,26 +835,28 @@ int __init dm_dirty_log_init(void)
+ {
+ int r;
+
+- r = dm_register_dirty_log_type(&_core_type);
++ r = dm_dirty_log_type_register(&_core_type);
+ if (r)
+ DMWARN("couldn't register core log");
+
+- r = dm_register_dirty_log_type(&_disk_type);
++ r = dm_dirty_log_type_register(&_disk_type);
+ if (r) {
+ DMWARN("couldn't register disk type");
+- dm_unregister_dirty_log_type(&_core_type);
++ dm_dirty_log_type_unregister(&_core_type);
+ }
+
+ return r;
+ }
+
+-void dm_dirty_log_exit(void)
++void __exit dm_dirty_log_exit(void)
+ {
+- dm_unregister_dirty_log_type(&_disk_type);
+- dm_unregister_dirty_log_type(&_core_type);
++ dm_dirty_log_type_unregister(&_disk_type);
++ dm_dirty_log_type_unregister(&_core_type);
+ }
+
+-EXPORT_SYMBOL(dm_register_dirty_log_type);
+-EXPORT_SYMBOL(dm_unregister_dirty_log_type);
+-EXPORT_SYMBOL(dm_create_dirty_log);
+-EXPORT_SYMBOL(dm_destroy_dirty_log);
++module_init(dm_dirty_log_init);
++module_exit(dm_dirty_log_exit);
++
++MODULE_DESCRIPTION(DM_NAME " dirty region log");
++MODULE_AUTHOR("Joe Thornber, Heinz Mauelshagen <dm-devel at redhat.com>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/md/dm-log.h b/drivers/md/dm-log.h
+deleted file mode 100644
+index 3fae87e..0000000
+--- a/drivers/md/dm-log.h
++++ /dev/null
+@@ -1,131 +0,0 @@
+-/*
+- * Copyright (C) 2003 Sistina Software
+- *
+- * This file is released under the LGPL.
+- */
+-
+-#ifndef DM_DIRTY_LOG
+-#define DM_DIRTY_LOG
+-
+-#include "dm.h"
+-
+-typedef sector_t region_t;
+-
+-struct dirty_log_type;
+-
+-struct dirty_log {
+- struct dirty_log_type *type;
+- void *context;
+-};
+-
+-struct dirty_log_type {
+- struct list_head list;
+- const char *name;
+- struct module *module;
+- unsigned int use_count;
+-
+- int (*ctr)(struct dirty_log *log, struct dm_target *ti,
+- unsigned int argc, char **argv);
+- void (*dtr)(struct dirty_log *log);
+-
+- /*
+- * There are times when we don't want the log to touch
+- * the disk.
+- */
+- int (*presuspend)(struct dirty_log *log);
+- int (*postsuspend)(struct dirty_log *log);
+- int (*resume)(struct dirty_log *log);
+-
+- /*
+- * Retrieves the smallest size of region that the log can
+- * deal with.
+- */
+- uint32_t (*get_region_size)(struct dirty_log *log);
+-
+- /*
+- * A predicate to say whether a region is clean or not.
+- * May block.
+- */
+- int (*is_clean)(struct dirty_log *log, region_t region);
+-
+- /*
+- * Returns: 0, 1, -EWOULDBLOCK, < 0
+- *
+- * A predicate function to check the area given by
+- * [sector, sector + len) is in sync.
+- *
+- * If -EWOULDBLOCK is returned the state of the region is
+- * unknown, typically this will result in a read being
+- * passed to a daemon to deal with, since a daemon is
+- * allowed to block.
+- */
+- int (*in_sync)(struct dirty_log *log, region_t region, int can_block);
+-
+- /*
+- * Flush the current log state (eg, to disk). This
+- * function may block.
+- */
+- int (*flush)(struct dirty_log *log);
+-
+- /*
+- * Mark an area as clean or dirty. These functions may
+- * block, though for performance reasons blocking should
+- * be extremely rare (eg, allocating another chunk of
+- * memory for some reason).
+- */
+- void (*mark_region)(struct dirty_log *log, region_t region);
+- void (*clear_region)(struct dirty_log *log, region_t region);
+-
+- /*
+- * Returns: <0 (error), 0 (no region), 1 (region)
+- *
+- * The mirrord will need perform recovery on regions of
+- * the mirror that are in the NOSYNC state. This
+- * function asks the log to tell the caller about the
+- * next region that this machine should recover.
+- *
+- * Do not confuse this function with 'in_sync()', one
+- * tells you if an area is synchronised, the other
+- * assigns recovery work.
+- */
+- int (*get_resync_work)(struct dirty_log *log, region_t *region);
+-
+- /*
+- * This notifies the log that the resync status of a region
+- * has changed. It also clears the region from the recovering
+- * list (if present).
+- */
+- void (*set_region_sync)(struct dirty_log *log,
+- region_t region, int in_sync);
+-
+- /*
+- * Returns the number of regions that are in sync.
+- */
+- region_t (*get_sync_count)(struct dirty_log *log);
+-
+- /*
+- * Support function for mirror status requests.
+- */
+- int (*status)(struct dirty_log *log, status_type_t status_type,
+- char *result, unsigned int maxlen);
+-};
+-
+-int dm_register_dirty_log_type(struct dirty_log_type *type);
+-int dm_unregister_dirty_log_type(struct dirty_log_type *type);
+-
+-
+-/*
+- * Make sure you use these two functions, rather than calling
+- * type->constructor/destructor() directly.
+- */
+-struct dirty_log *dm_create_dirty_log(const char *type_name, struct dm_target *ti,
+- unsigned int argc, char **argv);
+-void dm_destroy_dirty_log(struct dirty_log *log);
+-
+-/*
+- * init/exit functions.
+- */
+-int dm_dirty_log_init(void);
+-void dm_dirty_log_exit(void);
+-
+-#endif
+diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
+index 762cb08..ff05fe8 100644
+--- a/drivers/md/dm-raid1.c
++++ b/drivers/md/dm-raid1.c
+@@ -7,9 +7,6 @@
+ #include "dm.h"
+ #include "dm-bio-list.h"
+ #include "dm-bio-record.h"
+-#include "dm-io.h"
+-#include "dm-log.h"
+-#include "kcopyd.h"
+
+ #include <linux/ctype.h>
+ #include <linux/init.h>
+@@ -22,6 +19,9 @@
+ #include <linux/workqueue.h>
+ #include <linux/log2.h>
+ #include <linux/hardirq.h>
++#include <linux/dm-io.h>
++#include <linux/dm-dirty-log.h>
++#include <linux/dm-kcopyd.h>
+
+ #define DM_MSG_PREFIX "raid1"
+ #define DM_IO_PAGES 64
+@@ -74,7 +74,7 @@ struct region_hash {
+ unsigned region_shift;
+
+ /* holds persistent region state */
+- struct dirty_log *log;
++ struct dm_dirty_log *log;
+
+ /* hash table */
+ rwlock_t hash_lock;
+@@ -133,7 +133,7 @@ struct mirror_set {
+ struct dm_target *ti;
+ struct list_head list;
+ struct region_hash rh;
+- struct kcopyd_client *kcopyd_client;
++ struct dm_kcopyd_client *kcopyd_client;
+ uint64_t features;
+
+ spinlock_t lock; /* protects the lists */
+@@ -154,6 +154,9 @@ struct mirror_set {
+
+ struct workqueue_struct *kmirrord_wq;
+ struct work_struct kmirrord_work;
++ struct timer_list timer;
++ unsigned long timer_pending;
++
+ struct work_struct trigger_event;
+
+ unsigned int nr_mirrors;
+@@ -178,13 +181,32 @@ static void wake(struct mirror_set *ms)
+ queue_work(ms->kmirrord_wq, &ms->kmirrord_work);
+ }
+
++static void delayed_wake_fn(unsigned long data)
++{
++ struct mirror_set *ms = (struct mirror_set *) data;
++
++ clear_bit(0, &ms->timer_pending);
++ wake(ms);
++}
++
++static void delayed_wake(struct mirror_set *ms)
++{
++ if (test_and_set_bit(0, &ms->timer_pending))
++ return;
++
++ ms->timer.expires = jiffies + HZ / 5;
++ ms->timer.data = (unsigned long) ms;
++ ms->timer.function = delayed_wake_fn;
++ add_timer(&ms->timer);
++}
++
+ /* FIXME move this */
+ static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw);
+
+ #define MIN_REGIONS 64
+ #define MAX_RECOVERY 1
+ static int rh_init(struct region_hash *rh, struct mirror_set *ms,
+- struct dirty_log *log, uint32_t region_size,
++ struct dm_dirty_log *log, uint32_t region_size,
+ region_t nr_regions)
+ {
+ unsigned int nr_buckets, max_buckets;
+@@ -249,7 +271,7 @@ static void rh_exit(struct region_hash *rh)
+ }
+
+ if (rh->log)
+- dm_destroy_dirty_log(rh->log);
++ dm_dirty_log_destroy(rh->log);
+ if (rh->region_pool)
+ mempool_destroy(rh->region_pool);
+ vfree(rh->buckets);
+@@ -405,24 +427,22 @@ static void rh_update_states(struct region_hash *rh)
+ write_lock_irq(&rh->hash_lock);
+ spin_lock(&rh->region_lock);
+ if (!list_empty(&rh->clean_regions)) {
+- list_splice(&rh->clean_regions, &clean);
+- INIT_LIST_HEAD(&rh->clean_regions);
++ list_splice_init(&rh->clean_regions, &clean);
+
+ list_for_each_entry(reg, &clean, list)
+ list_del(®->hash_list);
+ }
+
+ if (!list_empty(&rh->recovered_regions)) {
+- list_splice(&rh->recovered_regions, &recovered);
+- INIT_LIST_HEAD(&rh->recovered_regions);
++ list_splice_init(&rh->recovered_regions, &recovered);
+
+ list_for_each_entry (reg, &recovered, list)
+ list_del(®->hash_list);
+ }
+
+ if (!list_empty(&rh->failed_recovered_regions)) {
+- list_splice(&rh->failed_recovered_regions, &failed_recovered);
+- INIT_LIST_HEAD(&rh->failed_recovered_regions);
++ list_splice_init(&rh->failed_recovered_regions,
++ &failed_recovered);
+
+ list_for_each_entry(reg, &failed_recovered, list)
+ list_del(®->hash_list);
+@@ -790,7 +810,7 @@ static int recover(struct mirror_set *ms, struct region *reg)
+ {
+ int r;
+ unsigned int i;
+- struct io_region from, to[KCOPYD_MAX_REGIONS], *dest;
++ struct dm_io_region from, to[DM_KCOPYD_MAX_REGIONS], *dest;
+ struct mirror *m;
+ unsigned long flags = 0;
+
+@@ -822,9 +842,9 @@ static int recover(struct mirror_set *ms, struct region *reg)
+ }
+
+ /* hand to kcopyd */
+- set_bit(KCOPYD_IGNORE_ERROR, &flags);
+- r = kcopyd_copy(ms->kcopyd_client, &from, ms->nr_mirrors - 1, to, flags,
+- recovery_complete, reg);
++ set_bit(DM_KCOPYD_IGNORE_ERROR, &flags);
++ r = dm_kcopyd_copy(ms->kcopyd_client, &from, ms->nr_mirrors - 1, to,
++ flags, recovery_complete, reg);
+
+ return r;
+ }
+@@ -833,7 +853,7 @@ static void do_recovery(struct mirror_set *ms)
+ {
+ int r;
+ struct region *reg;
+- struct dirty_log *log = ms->rh.log;
++ struct dm_dirty_log *log = ms->rh.log;
+
+ /*
+ * Start quiescing some regions.
+@@ -909,7 +929,7 @@ static void map_bio(struct mirror *m, struct bio *bio)
+ bio->bi_sector = map_sector(m, bio);
+ }
+
+-static void map_region(struct io_region *io, struct mirror *m,
++static void map_region(struct dm_io_region *io, struct mirror *m,
+ struct bio *bio)
+ {
+ io->bdev = m->dev->bdev;
+@@ -951,7 +971,7 @@ static void read_callback(unsigned long error, void *context)
+ /* Asynchronous read. */
+ static void read_async_bio(struct mirror *m, struct bio *bio)
+ {
+- struct io_region io;
++ struct dm_io_region io;
+ struct dm_io_request io_req = {
+ .bi_rw = READ,
+ .mem.type = DM_IO_BVEC,
+@@ -1019,7 +1039,7 @@ static void __bio_mark_nosync(struct mirror_set *ms,
+ {
+ unsigned long flags;
+ struct region_hash *rh = &ms->rh;
+- struct dirty_log *log = ms->rh.log;
++ struct dm_dirty_log *log = ms->rh.log;
+ struct region *reg;
+ region_t region = bio_to_region(rh, bio);
+ int recovering = 0;
+@@ -1107,7 +1127,7 @@ out:
+ static void do_write(struct mirror_set *ms, struct bio *bio)
+ {
+ unsigned int i;
+- struct io_region io[ms->nr_mirrors], *dest = io;
++ struct dm_io_region io[ms->nr_mirrors], *dest = io;
+ struct mirror *m;
+ struct dm_io_request io_req = {
+ .bi_rw = WRITE,
+@@ -1182,6 +1202,7 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes)
+ spin_lock_irq(&ms->lock);
+ bio_list_merge(&ms->failures, &sync);
+ spin_unlock_irq(&ms->lock);
++ wake(ms);
+ } else
+ while ((bio = bio_list_pop(&sync)))
+ do_write(ms, bio);
+@@ -1241,7 +1262,7 @@ static void do_failures(struct mirror_set *ms, struct bio_list *failures)
+ bio_list_merge(&ms->failures, failures);
+ spin_unlock_irq(&ms->lock);
+
+- wake(ms);
++ delayed_wake(ms);
+ }
+
+ static void trigger_event(struct work_struct *work)
+@@ -1255,7 +1276,7 @@ static void trigger_event(struct work_struct *work)
+ /*-----------------------------------------------------------------
+ * kmirrord
+ *---------------------------------------------------------------*/
+-static int _do_mirror(struct work_struct *work)
++static void do_mirror(struct work_struct *work)
+ {
+ struct mirror_set *ms =container_of(work, struct mirror_set,
+ kmirrord_work);
+@@ -1277,23 +1298,7 @@ static int _do_mirror(struct work_struct *work)
+ do_writes(ms, &writes);
+ do_failures(ms, &failures);
+
+- return (ms->failures.head) ? 1 : 0;
+-}
+-
+-static void do_mirror(struct work_struct *work)
+-{
+- /*
+- * If _do_mirror returns 1, we give it
+- * another shot. This helps for cases like
+- * 'suspend' where we call flush_workqueue
+- * and expect all work to be finished. If
+- * a failure happens during a suspend, we
+- * couldn't issue a 'wake' because it would
+- * not be honored. Therefore, we return '1'
+- * from _do_mirror, and retry here.
+- */
+- while (_do_mirror(work))
+- schedule();
++ dm_table_unplug_all(ms->ti->table);
+ }
+
+
+@@ -1303,7 +1308,7 @@ static void do_mirror(struct work_struct *work)
+ static struct mirror_set *alloc_context(unsigned int nr_mirrors,
+ uint32_t region_size,
+ struct dm_target *ti,
+- struct dirty_log *dl)
++ struct dm_dirty_log *dl)
+ {
+ size_t len;
+ struct mirror_set *ms = NULL;
+@@ -1403,12 +1408,12 @@ static int get_mirror(struct mirror_set *ms, struct dm_target *ti,
+ /*
+ * Create dirty log: log_type #log_params <log_params>
+ */
+-static struct dirty_log *create_dirty_log(struct dm_target *ti,
++static struct dm_dirty_log *create_dirty_log(struct dm_target *ti,
+ unsigned int argc, char **argv,
+ unsigned int *args_used)
+ {
+ unsigned int param_count;
+- struct dirty_log *dl;
++ struct dm_dirty_log *dl;
+
+ if (argc < 2) {
+ ti->error = "Insufficient mirror log arguments";
+@@ -1427,7 +1432,7 @@ static struct dirty_log *create_dirty_log(struct dm_target *ti,
+ return NULL;
+ }
+
+- dl = dm_create_dirty_log(argv[0], ti, param_count, argv + 2);
++ dl = dm_dirty_log_create(argv[0], ti, param_count, argv + 2);
+ if (!dl) {
+ ti->error = "Error creating mirror dirty log";
+ return NULL;
+@@ -1435,7 +1440,7 @@ static struct dirty_log *create_dirty_log(struct dm_target *ti,
+
+ if (!_check_region_size(ti, dl->type->get_region_size(dl))) {
+ ti->error = "Invalid region size";
+- dm_destroy_dirty_log(dl);
++ dm_dirty_log_destroy(dl);
+ return NULL;
+ }
+
+@@ -1496,7 +1501,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+ int r;
+ unsigned int nr_mirrors, m, args_used;
+ struct mirror_set *ms;
+- struct dirty_log *dl;
++ struct dm_dirty_log *dl;
+
+ dl = create_dirty_log(ti, argc, argv, &args_used);
+ if (!dl)
+@@ -1506,9 +1511,9 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+ argc -= args_used;
+
+ if (!argc || sscanf(argv[0], "%u", &nr_mirrors) != 1 ||
+- nr_mirrors < 2 || nr_mirrors > KCOPYD_MAX_REGIONS + 1) {
++ nr_mirrors < 2 || nr_mirrors > DM_KCOPYD_MAX_REGIONS + 1) {
+ ti->error = "Invalid number of mirrors";
+- dm_destroy_dirty_log(dl);
++ dm_dirty_log_destroy(dl);
+ return -EINVAL;
+ }
+
+@@ -1516,13 +1521,13 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+
+ if (argc < nr_mirrors * 2) {
+ ti->error = "Too few mirror arguments";
+- dm_destroy_dirty_log(dl);
++ dm_dirty_log_destroy(dl);
+ return -EINVAL;
+ }
+
+ ms = alloc_context(nr_mirrors, dl->type->get_region_size(dl), ti, dl);
+ if (!ms) {
+- dm_destroy_dirty_log(dl);
++ dm_dirty_log_destroy(dl);
+ return -ENOMEM;
+ }
+
+@@ -1547,6 +1552,8 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+ goto err_free_context;
+ }
+ INIT_WORK(&ms->kmirrord_work, do_mirror);
++ init_timer(&ms->timer);
++ ms->timer_pending = 0;
+ INIT_WORK(&ms->trigger_event, trigger_event);
+
+ r = parse_features(ms, argc, argv, &args_used);
+@@ -1571,7 +1578,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+ goto err_destroy_wq;
+ }
+
+- r = kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client);
++ r = dm_kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client);
+ if (r)
+ goto err_destroy_wq;
+
+@@ -1589,8 +1596,9 @@ static void mirror_dtr(struct dm_target *ti)
+ {
+ struct mirror_set *ms = (struct mirror_set *) ti->private;
+
++ del_timer_sync(&ms->timer);
+ flush_workqueue(ms->kmirrord_wq);
+- kcopyd_client_destroy(ms->kcopyd_client);
++ dm_kcopyd_client_destroy(ms->kcopyd_client);
+ destroy_workqueue(ms->kmirrord_wq);
+ free_context(ms, ti, ms->nr_mirrors);
+ }
+@@ -1734,7 +1742,7 @@ out:
+ static void mirror_presuspend(struct dm_target *ti)
+ {
+ struct mirror_set *ms = (struct mirror_set *) ti->private;
+- struct dirty_log *log = ms->rh.log;
++ struct dm_dirty_log *log = ms->rh.log;
+
+ atomic_set(&ms->suspend, 1);
+
+@@ -1763,7 +1771,7 @@ static void mirror_presuspend(struct dm_target *ti)
+ static void mirror_postsuspend(struct dm_target *ti)
+ {
+ struct mirror_set *ms = ti->private;
+- struct dirty_log *log = ms->rh.log;
++ struct dm_dirty_log *log = ms->rh.log;
+
+ if (log->type->postsuspend && log->type->postsuspend(log))
+ /* FIXME: need better error handling */
+@@ -1773,7 +1781,7 @@ static void mirror_postsuspend(struct dm_target *ti)
+ static void mirror_resume(struct dm_target *ti)
+ {
+ struct mirror_set *ms = ti->private;
+- struct dirty_log *log = ms->rh.log;
++ struct dm_dirty_log *log = ms->rh.log;
+
+ atomic_set(&ms->suspend, 0);
+ if (log->type->resume && log->type->resume(log))
+@@ -1811,7 +1819,7 @@ static int mirror_status(struct dm_target *ti, status_type_t type,
+ {
+ unsigned int m, sz = 0;
+ struct mirror_set *ms = (struct mirror_set *) ti->private;
+- struct dirty_log *log = ms->rh.log;
++ struct dm_dirty_log *log = ms->rh.log;
+ char buffer[ms->nr_mirrors + 1];
+
+ switch (type) {
+@@ -1864,15 +1872,9 @@ static int __init dm_mirror_init(void)
+ {
+ int r;
+
+- r = dm_dirty_log_init();
+- if (r)
+- return r;
+-
+ r = dm_register_target(&mirror_target);
+- if (r < 0) {
++ if (r < 0)
+ DMERR("Failed to register mirror target");
+- dm_dirty_log_exit();
+- }
+
+ return r;
+ }
+@@ -1884,8 +1886,6 @@ static void __exit dm_mirror_exit(void)
+ r = dm_unregister_target(&mirror_target);
+ if (r < 0)
+ DMERR("unregister failed %d", r);
+-
+- dm_dirty_log_exit();
+ }
+
+ /* Module hooks */
+diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
+index 4dc8a43..1ba8a47 100644
+--- a/drivers/md/dm-snap.c
++++ b/drivers/md/dm-snap.c
+@@ -18,10 +18,10 @@
+ #include <linux/slab.h>
+ #include <linux/vmalloc.h>
+ #include <linux/log2.h>
++#include <linux/dm-kcopyd.h>
+
+ #include "dm-snap.h"
+ #include "dm-bio-list.h"
+-#include "kcopyd.h"
+
+ #define DM_MSG_PREFIX "snapshots"
+
+@@ -36,9 +36,9 @@
+ #define SNAPSHOT_COPY_PRIORITY 2
+
+ /*
+- * Each snapshot reserves this many pages for io
++ * Reserve 1MB for each snapshot initially (with minimum of 1 page).
+ */
+-#define SNAPSHOT_PAGES 256
++#define SNAPSHOT_PAGES (((1UL << 20) >> PAGE_SHIFT) ? : 1)
+
+ static struct workqueue_struct *ksnapd;
+ static void flush_queued_bios(struct work_struct *work);
+@@ -536,7 +536,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+ s->last_percent = 0;
+ init_rwsem(&s->lock);
+ spin_lock_init(&s->pe_lock);
+- s->table = ti->table;
++ s->ti = ti;
+
+ /* Allocate hash table for COW data */
+ if (init_hash_tables(s)) {
+@@ -558,7 +558,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+ goto bad4;
+ }
+
+- r = kcopyd_client_create(SNAPSHOT_PAGES, &s->kcopyd_client);
++ r = dm_kcopyd_client_create(SNAPSHOT_PAGES, &s->kcopyd_client);
+ if (r) {
+ ti->error = "Could not create kcopyd client";
+ goto bad5;
+@@ -591,7 +591,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+ return 0;
+
+ bad6:
+- kcopyd_client_destroy(s->kcopyd_client);
++ dm_kcopyd_client_destroy(s->kcopyd_client);
+
+ bad5:
+ s->store.destroy(&s->store);
+@@ -613,7 +613,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+
+ static void __free_exceptions(struct dm_snapshot *s)
+ {
+- kcopyd_client_destroy(s->kcopyd_client);
++ dm_kcopyd_client_destroy(s->kcopyd_client);
+ s->kcopyd_client = NULL;
+
+ exit_exception_table(&s->pending, pending_cache);
+@@ -699,7 +699,7 @@ static void __invalidate_snapshot(struct dm_snapshot *s, int err)
+
+ s->valid = 0;
+
+- dm_table_event(s->table);
++ dm_table_event(s->ti->table);
+ }
+
+ static void get_pending_exception(struct dm_snap_pending_exception *pe)
+@@ -824,7 +824,7 @@ static void copy_callback(int read_err, unsigned long write_err, void *context)
+ static void start_copy(struct dm_snap_pending_exception *pe)
+ {
+ struct dm_snapshot *s = pe->snap;
+- struct io_region src, dest;
++ struct dm_io_region src, dest;
+ struct block_device *bdev = s->origin->bdev;
+ sector_t dev_size;
+
+@@ -839,7 +839,7 @@ static void start_copy(struct dm_snap_pending_exception *pe)
+ dest.count = src.count;
+
+ /* Hand over to kcopyd */
+- kcopyd_copy(s->kcopyd_client,
++ dm_kcopyd_copy(s->kcopyd_client,
+ &src, 1, &dest, 0, copy_callback, pe);
+ }
+
+@@ -1060,7 +1060,7 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio)
+ goto next_snapshot;
+
+ /* Nothing to do if writing beyond end of snapshot */
+- if (bio->bi_sector >= dm_table_get_size(snap->table))
++ if (bio->bi_sector >= dm_table_get_size(snap->ti->table))
+ goto next_snapshot;
+
+ /*
+diff --git a/drivers/md/dm-snap.h b/drivers/md/dm-snap.h
+index 93bce5d..24f9fb7 100644
+--- a/drivers/md/dm-snap.h
++++ b/drivers/md/dm-snap.h
+@@ -132,7 +132,7 @@ struct exception_store {
+
+ struct dm_snapshot {
+ struct rw_semaphore lock;
+- struct dm_table *table;
++ struct dm_target *ti;
+
+ struct dm_dev *origin;
+ struct dm_dev *cow;
+@@ -169,7 +169,7 @@ struct dm_snapshot {
+ /* The on disk metadata handler */
+ struct exception_store store;
+
+- struct kcopyd_client *kcopyd_client;
++ struct dm_kcopyd_client *kcopyd_client;
+
+ /* Queue of snapshot writes for ksnapd to flush */
+ struct bio_list queued_bios;
+diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
+index e75b143..51be533 100644
+--- a/drivers/md/dm-table.c
++++ b/drivers/md/dm-table.c
+@@ -245,44 +245,6 @@ int dm_table_create(struct dm_table **result, int mode,
+ return 0;
+ }
+
+-int dm_create_error_table(struct dm_table **result, struct mapped_device *md)
+-{
+- struct dm_table *t;
+- sector_t dev_size = 1;
+- int r;
+-
+- /*
+- * Find current size of device.
+- * Default to 1 sector if inactive.
+- */
+- t = dm_get_table(md);
+- if (t) {
+- dev_size = dm_table_get_size(t);
+- dm_table_put(t);
+- }
+-
+- r = dm_table_create(&t, FMODE_READ, 1, md);
+- if (r)
+- return r;
+-
+- r = dm_table_add_target(t, "error", 0, dev_size, NULL);
+- if (r)
+- goto out;
+-
+- r = dm_table_complete(t);
+- if (r)
+- goto out;
+-
+- *result = t;
+-
+-out:
+- if (r)
+- dm_table_put(t);
+-
+- return r;
+-}
+-EXPORT_SYMBOL_GPL(dm_create_error_table);
+-
+ static void free_devices(struct list_head *devices)
+ {
+ struct list_head *tmp, *next;
+@@ -954,7 +916,7 @@ void dm_table_presuspend_targets(struct dm_table *t)
+ if (!t)
+ return;
+
+- return suspend_targets(t, 0);
++ suspend_targets(t, 0);
+ }
+
+ void dm_table_postsuspend_targets(struct dm_table *t)
+@@ -962,7 +924,7 @@ void dm_table_postsuspend_targets(struct dm_table *t)
+ if (!t)
+ return;
+
+- return suspend_targets(t, 1);
++ suspend_targets(t, 1);
+ }
+
+ int dm_table_resume_targets(struct dm_table *t)
+diff --git a/drivers/md/dm.c b/drivers/md/dm.c
+index 6617ce4..372369b 100644
+--- a/drivers/md/dm.c
++++ b/drivers/md/dm.c
+@@ -204,6 +204,7 @@ static int (*_inits[])(void) __initdata = {
+ dm_target_init,
+ dm_linear_init,
+ dm_stripe_init,
++ dm_kcopyd_init,
+ dm_interface_init,
+ };
+
+@@ -212,6 +213,7 @@ static void (*_exits[])(void) = {
+ dm_target_exit,
+ dm_linear_exit,
+ dm_stripe_exit,
++ dm_kcopyd_exit,
+ dm_interface_exit,
+ };
+
+@@ -922,7 +924,7 @@ static void free_minor(int minor)
+ /*
+ * See if the device with a specific minor # is free.
+ */
+-static int specific_minor(struct mapped_device *md, int minor)
++static int specific_minor(int minor)
+ {
+ int r, m;
+
+@@ -955,7 +957,7 @@ out:
+ return r;
+ }
+
+-static int next_free_minor(struct mapped_device *md, int *minor)
++static int next_free_minor(int *minor)
+ {
+ int r, m;
+
+@@ -966,9 +968,8 @@ static int next_free_minor(struct mapped_device *md, int *minor)
+ spin_lock(&_minor_lock);
+
+ r = idr_get_new(&_minor_idr, MINOR_ALLOCED, &m);
+- if (r) {
++ if (r)
+ goto out;
+- }
+
+ if (m >= (1 << MINORBITS)) {
+ idr_remove(&_minor_idr, m);
+@@ -991,7 +992,7 @@ static struct block_device_operations dm_blk_dops;
+ static struct mapped_device *alloc_dev(int minor)
+ {
+ int r;
+- struct mapped_device *md = kmalloc(sizeof(*md), GFP_KERNEL);
++ struct mapped_device *md = kzalloc(sizeof(*md), GFP_KERNEL);
+ void *old_md;
+
+ if (!md) {
+@@ -1004,13 +1005,12 @@ static struct mapped_device *alloc_dev(int minor)
+
+ /* get a minor number for the dev */
+ if (minor == DM_ANY_MINOR)
+- r = next_free_minor(md, &minor);
++ r = next_free_minor(&minor);
+ else
+- r = specific_minor(md, minor);
++ r = specific_minor(minor);
+ if (r < 0)
+ goto bad_minor;
+
+- memset(md, 0, sizeof(*md));
+ init_rwsem(&md->io_lock);
+ mutex_init(&md->suspend_lock);
+ spin_lock_init(&md->pushback_lock);
+diff --git a/drivers/md/dm.h b/drivers/md/dm.h
+index b4584a3..8c03b63 100644
+--- a/drivers/md/dm.h
++++ b/drivers/md/dm.h
+@@ -16,67 +16,6 @@
+ #include <linux/blkdev.h>
+ #include <linux/hdreg.h>
+
+-#define DM_NAME "device-mapper"
+-
+-#define DMERR(f, arg...) \
+- printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
+-#define DMERR_LIMIT(f, arg...) \
+- do { \
+- if (printk_ratelimit()) \
+- printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " \
+- f "\n", ## arg); \
+- } while (0)
+-
+-#define DMWARN(f, arg...) \
+- printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
+-#define DMWARN_LIMIT(f, arg...) \
+- do { \
+- if (printk_ratelimit()) \
+- printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " \
+- f "\n", ## arg); \
+- } while (0)
+-
+-#define DMINFO(f, arg...) \
+- printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
+-#define DMINFO_LIMIT(f, arg...) \
+- do { \
+- if (printk_ratelimit()) \
+- printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f \
+- "\n", ## arg); \
+- } while (0)
+-
+-#ifdef CONFIG_DM_DEBUG
+-# define DMDEBUG(f, arg...) \
+- printk(KERN_DEBUG DM_NAME ": " DM_MSG_PREFIX " DEBUG: " f "\n", ## arg)
+-# define DMDEBUG_LIMIT(f, arg...) \
+- do { \
+- if (printk_ratelimit()) \
+- printk(KERN_DEBUG DM_NAME ": " DM_MSG_PREFIX ": " f \
+- "\n", ## arg); \
+- } while (0)
+-#else
+-# define DMDEBUG(f, arg...) do {} while (0)
+-# define DMDEBUG_LIMIT(f, arg...) do {} while (0)
+-#endif
+-
+-#define DMEMIT(x...) sz += ((sz >= maxlen) ? \
+- 0 : scnprintf(result + sz, maxlen - sz, x))
+-
+-#define SECTOR_SHIFT 9
+-
+-/*
+- * Definitions of return values from target end_io function.
+- */
+-#define DM_ENDIO_INCOMPLETE 1
+-#define DM_ENDIO_REQUEUE 2
+-
+-/*
+- * Definitions of return values from target map function.
+- */
+-#define DM_MAPIO_SUBMITTED 0
+-#define DM_MAPIO_REMAPPED 1
+-#define DM_MAPIO_REQUEUE DM_ENDIO_REQUEUE
+-
+ /*
+ * Suspend feature flags
+ */
+@@ -136,34 +75,6 @@ static inline int array_too_big(unsigned long fixed, unsigned long obj,
+ return (num > (ULONG_MAX - fixed) / obj);
+ }
+
+-/*
+- * Ceiling(n / sz)
+- */
+-#define dm_div_up(n, sz) (((n) + (sz) - 1) / (sz))
+-
+-#define dm_sector_div_up(n, sz) ( \
+-{ \
+- sector_t _r = ((n) + (sz) - 1); \
+- sector_div(_r, (sz)); \
+- _r; \
+-} \
+-)
+-
+-/*
+- * ceiling(n / size) * size
+- */
+-#define dm_round_up(n, sz) (dm_div_up((n), (sz)) * (sz))
+-
+-static inline sector_t to_sector(unsigned long n)
+-{
+- return (n >> 9);
+-}
+-
+-static inline unsigned long to_bytes(sector_t n)
+-{
+- return (n << 9);
+-}
+-
+ int dm_split_args(int *argc, char ***argvp, char *input);
+
+ /*
+@@ -189,4 +100,13 @@ int dm_lock_for_deletion(struct mapped_device *md);
+
+ void dm_kobject_uevent(struct mapped_device *md);
+
++/*
++ * Dirty log
++ */
++int dm_dirty_log_init(void);
++void dm_dirty_log_exit(void);
++
++int dm_kcopyd_init(void);
++void dm_kcopyd_exit(void);
++
+ #endif
+diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c
+deleted file mode 100644
+index e76b52a..0000000
+--- a/drivers/md/kcopyd.c
++++ /dev/null
+@@ -1,708 +0,0 @@
+-/*
+- * Copyright (C) 2002 Sistina Software (UK) Limited.
+- * Copyright (C) 2006 Red Hat GmbH
+- *
+- * This file is released under the GPL.
+- *
+- * Kcopyd provides a simple interface for copying an area of one
+- * block-device to one or more other block-devices, with an asynchronous
+- * completion notification.
+- */
+-
+-#include <asm/types.h>
+-#include <asm/atomic.h>
+-
+-#include <linux/blkdev.h>
+-#include <linux/fs.h>
+-#include <linux/init.h>
+-#include <linux/list.h>
+-#include <linux/mempool.h>
+-#include <linux/module.h>
+-#include <linux/pagemap.h>
+-#include <linux/slab.h>
+-#include <linux/vmalloc.h>
+-#include <linux/workqueue.h>
+-#include <linux/mutex.h>
+-
+-#include "kcopyd.h"
+-
+-static struct workqueue_struct *_kcopyd_wq;
+-static struct work_struct _kcopyd_work;
+-
+-static void wake(void)
+-{
+- queue_work(_kcopyd_wq, &_kcopyd_work);
+-}
+-
+-/*-----------------------------------------------------------------
+- * Each kcopyd client has its own little pool of preallocated
+- * pages for kcopyd io.
+- *---------------------------------------------------------------*/
+-struct kcopyd_client {
+- struct list_head list;
+-
+- spinlock_t lock;
+- struct page_list *pages;
+- unsigned int nr_pages;
+- unsigned int nr_free_pages;
+-
+- struct dm_io_client *io_client;
+-
+- wait_queue_head_t destroyq;
+- atomic_t nr_jobs;
+-};
+-
+-static struct page_list *alloc_pl(void)
+-{
+- struct page_list *pl;
+-
+- pl = kmalloc(sizeof(*pl), GFP_KERNEL);
+- if (!pl)
+- return NULL;
+-
+- pl->page = alloc_page(GFP_KERNEL);
+- if (!pl->page) {
+- kfree(pl);
+- return NULL;
+- }
+-
+- return pl;
+-}
+-
+-static void free_pl(struct page_list *pl)
+-{
+- __free_page(pl->page);
+- kfree(pl);
+-}
+-
+-static int kcopyd_get_pages(struct kcopyd_client *kc,
+- unsigned int nr, struct page_list **pages)
+-{
+- struct page_list *pl;
+-
+- spin_lock(&kc->lock);
+- if (kc->nr_free_pages < nr) {
+- spin_unlock(&kc->lock);
+- return -ENOMEM;
+- }
+-
+- kc->nr_free_pages -= nr;
+- for (*pages = pl = kc->pages; --nr; pl = pl->next)
+- ;
+-
+- kc->pages = pl->next;
+- pl->next = NULL;
+-
+- spin_unlock(&kc->lock);
+-
+- return 0;
+-}
+-
+-static void kcopyd_put_pages(struct kcopyd_client *kc, struct page_list *pl)
+-{
+- struct page_list *cursor;
+-
+- spin_lock(&kc->lock);
+- for (cursor = pl; cursor->next; cursor = cursor->next)
+- kc->nr_free_pages++;
+-
+- kc->nr_free_pages++;
+- cursor->next = kc->pages;
+- kc->pages = pl;
+- spin_unlock(&kc->lock);
+-}
+-
+-/*
+- * These three functions resize the page pool.
+- */
+-static void drop_pages(struct page_list *pl)
+-{
+- struct page_list *next;
+-
+- while (pl) {
+- next = pl->next;
+- free_pl(pl);
+- pl = next;
+- }
+-}
+-
+-static int client_alloc_pages(struct kcopyd_client *kc, unsigned int nr)
+-{
+- unsigned int i;
+- struct page_list *pl = NULL, *next;
+-
+- for (i = 0; i < nr; i++) {
+- next = alloc_pl();
+- if (!next) {
+- if (pl)
+- drop_pages(pl);
+- return -ENOMEM;
+- }
+- next->next = pl;
+- pl = next;
+- }
+-
+- kcopyd_put_pages(kc, pl);
+- kc->nr_pages += nr;
+- return 0;
+-}
+-
+-static void client_free_pages(struct kcopyd_client *kc)
+-{
+- BUG_ON(kc->nr_free_pages != kc->nr_pages);
+- drop_pages(kc->pages);
+- kc->pages = NULL;
+- kc->nr_free_pages = kc->nr_pages = 0;
+-}
+-
+-/*-----------------------------------------------------------------
+- * kcopyd_jobs need to be allocated by the *clients* of kcopyd,
+- * for this reason we use a mempool to prevent the client from
+- * ever having to do io (which could cause a deadlock).
+- *---------------------------------------------------------------*/
+-struct kcopyd_job {
+- struct kcopyd_client *kc;
+- struct list_head list;
+- unsigned long flags;
+-
+- /*
+- * Error state of the job.
+- */
+- int read_err;
+- unsigned long write_err;
+-
+- /*
+- * Either READ or WRITE
+- */
+- int rw;
+- struct io_region source;
+-
+- /*
+- * The destinations for the transfer.
+- */
+- unsigned int num_dests;
+- struct io_region dests[KCOPYD_MAX_REGIONS];
+-
+- sector_t offset;
+- unsigned int nr_pages;
+- struct page_list *pages;
+-
+- /*
+- * Set this to ensure you are notified when the job has
+- * completed. 'context' is for callback to use.
+- */
+- kcopyd_notify_fn fn;
+- void *context;
+-
+- /*
+- * These fields are only used if the job has been split
+- * into more manageable parts.
+- */
+- struct mutex lock;
+- atomic_t sub_jobs;
+- sector_t progress;
+-};
+-
+-/* FIXME: this should scale with the number of pages */
+-#define MIN_JOBS 512
+-
+-static struct kmem_cache *_job_cache;
+-static mempool_t *_job_pool;
+-
+-/*
+- * We maintain three lists of jobs:
+- *
+- * i) jobs waiting for pages
+- * ii) jobs that have pages, and are waiting for the io to be issued.
+- * iii) jobs that have completed.
+- *
+- * All three of these are protected by job_lock.
+- */
+-static DEFINE_SPINLOCK(_job_lock);
+-
+-static LIST_HEAD(_complete_jobs);
+-static LIST_HEAD(_io_jobs);
+-static LIST_HEAD(_pages_jobs);
+-
+-static int jobs_init(void)
+-{
+- _job_cache = KMEM_CACHE(kcopyd_job, 0);
+- if (!_job_cache)
+- return -ENOMEM;
+-
+- _job_pool = mempool_create_slab_pool(MIN_JOBS, _job_cache);
+- if (!_job_pool) {
+- kmem_cache_destroy(_job_cache);
+- return -ENOMEM;
+- }
+-
+- return 0;
+-}
+-
+-static void jobs_exit(void)
+-{
+- BUG_ON(!list_empty(&_complete_jobs));
+- BUG_ON(!list_empty(&_io_jobs));
+- BUG_ON(!list_empty(&_pages_jobs));
+-
+- mempool_destroy(_job_pool);
+- kmem_cache_destroy(_job_cache);
+- _job_pool = NULL;
+- _job_cache = NULL;
+-}
+-
+-/*
+- * Functions to push and pop a job onto the head of a given job
+- * list.
+- */
+-static struct kcopyd_job *pop(struct list_head *jobs)
+-{
+- struct kcopyd_job *job = NULL;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&_job_lock, flags);
+-
+- if (!list_empty(jobs)) {
+- job = list_entry(jobs->next, struct kcopyd_job, list);
+- list_del(&job->list);
+- }
+- spin_unlock_irqrestore(&_job_lock, flags);
+-
+- return job;
+-}
+-
+-static void push(struct list_head *jobs, struct kcopyd_job *job)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&_job_lock, flags);
+- list_add_tail(&job->list, jobs);
+- spin_unlock_irqrestore(&_job_lock, flags);
+-}
+-
+-/*
+- * These three functions process 1 item from the corresponding
+- * job list.
+- *
+- * They return:
+- * < 0: error
+- * 0: success
+- * > 0: can't process yet.
+- */
+-static int run_complete_job(struct kcopyd_job *job)
+-{
+- void *context = job->context;
+- int read_err = job->read_err;
+- unsigned long write_err = job->write_err;
+- kcopyd_notify_fn fn = job->fn;
+- struct kcopyd_client *kc = job->kc;
+-
+- kcopyd_put_pages(kc, job->pages);
+- mempool_free(job, _job_pool);
+- fn(read_err, write_err, context);
+-
+- if (atomic_dec_and_test(&kc->nr_jobs))
+- wake_up(&kc->destroyq);
+-
+- return 0;
+-}
+-
+-static void complete_io(unsigned long error, void *context)
+-{
+- struct kcopyd_job *job = (struct kcopyd_job *) context;
+-
+- if (error) {
+- if (job->rw == WRITE)
+- job->write_err |= error;
+- else
+- job->read_err = 1;
+-
+- if (!test_bit(KCOPYD_IGNORE_ERROR, &job->flags)) {
+- push(&_complete_jobs, job);
+- wake();
+- return;
+- }
+- }
+-
+- if (job->rw == WRITE)
+- push(&_complete_jobs, job);
+-
+- else {
+- job->rw = WRITE;
+- push(&_io_jobs, job);
+- }
+-
+- wake();
+-}
+-
+-/*
+- * Request io on as many buffer heads as we can currently get for
+- * a particular job.
+- */
+-static int run_io_job(struct kcopyd_job *job)
+-{
+- int r;
+- struct dm_io_request io_req = {
+- .bi_rw = job->rw,
+- .mem.type = DM_IO_PAGE_LIST,
+- .mem.ptr.pl = job->pages,
+- .mem.offset = job->offset,
+- .notify.fn = complete_io,
+- .notify.context = job,
+- .client = job->kc->io_client,
+- };
+-
+- if (job->rw == READ)
+- r = dm_io(&io_req, 1, &job->source, NULL);
+- else
+- r = dm_io(&io_req, job->num_dests, job->dests, NULL);
+-
+- return r;
+-}
+-
+-static int run_pages_job(struct kcopyd_job *job)
+-{
+- int r;
+-
+- job->nr_pages = dm_div_up(job->dests[0].count + job->offset,
+- PAGE_SIZE >> 9);
+- r = kcopyd_get_pages(job->kc, job->nr_pages, &job->pages);
+- if (!r) {
+- /* this job is ready for io */
+- push(&_io_jobs, job);
+- return 0;
+- }
+-
+- if (r == -ENOMEM)
+- /* can't complete now */
+- return 1;
+-
+- return r;
+-}
+-
+-/*
+- * Run through a list for as long as possible. Returns the count
+- * of successful jobs.
+- */
+-static int process_jobs(struct list_head *jobs, int (*fn) (struct kcopyd_job *))
+-{
+- struct kcopyd_job *job;
+- int r, count = 0;
+-
+- while ((job = pop(jobs))) {
+-
+- r = fn(job);
+-
+- if (r < 0) {
+- /* error this rogue job */
+- if (job->rw == WRITE)
+- job->write_err = (unsigned long) -1L;
+- else
+- job->read_err = 1;
+- push(&_complete_jobs, job);
+- break;
+- }
+-
+- if (r > 0) {
+- /*
+- * We couldn't service this job ATM, so
+- * push this job back onto the list.
+- */
+- push(jobs, job);
+- break;
+- }
+-
+- count++;
+- }
+-
+- return count;
+-}
+-
+-/*
+- * kcopyd does this every time it's woken up.
+- */
+-static void do_work(struct work_struct *ignored)
+-{
+- /*
+- * The order that these are called is *very* important.
+- * complete jobs can free some pages for pages jobs.
+- * Pages jobs when successful will jump onto the io jobs
+- * list. io jobs call wake when they complete and it all
+- * starts again.
+- */
+- process_jobs(&_complete_jobs, run_complete_job);
+- process_jobs(&_pages_jobs, run_pages_job);
+- process_jobs(&_io_jobs, run_io_job);
+-}
+-
+-/*
+- * If we are copying a small region we just dispatch a single job
+- * to do the copy, otherwise the io has to be split up into many
+- * jobs.
+- */
+-static void dispatch_job(struct kcopyd_job *job)
+-{
+- atomic_inc(&job->kc->nr_jobs);
+- push(&_pages_jobs, job);
+- wake();
+-}
+-
+-#define SUB_JOB_SIZE 128
+-static void segment_complete(int read_err, unsigned long write_err,
+- void *context)
+-{
+- /* FIXME: tidy this function */
+- sector_t progress = 0;
+- sector_t count = 0;
+- struct kcopyd_job *job = (struct kcopyd_job *) context;
+-
+- mutex_lock(&job->lock);
+-
+- /* update the error */
+- if (read_err)
+- job->read_err = 1;
+-
+- if (write_err)
+- job->write_err |= write_err;
+-
+- /*
+- * Only dispatch more work if there hasn't been an error.
+- */
+- if ((!job->read_err && !job->write_err) ||
+- test_bit(KCOPYD_IGNORE_ERROR, &job->flags)) {
+- /* get the next chunk of work */
+- progress = job->progress;
+- count = job->source.count - progress;
+- if (count) {
+- if (count > SUB_JOB_SIZE)
+- count = SUB_JOB_SIZE;
+-
+- job->progress += count;
+- }
+- }
+- mutex_unlock(&job->lock);
+-
+- if (count) {
+- int i;
+- struct kcopyd_job *sub_job = mempool_alloc(_job_pool, GFP_NOIO);
+-
+- *sub_job = *job;
+- sub_job->source.sector += progress;
+- sub_job->source.count = count;
+-
+- for (i = 0; i < job->num_dests; i++) {
+- sub_job->dests[i].sector += progress;
+- sub_job->dests[i].count = count;
+- }
+-
+- sub_job->fn = segment_complete;
+- sub_job->context = job;
+- dispatch_job(sub_job);
+-
+- } else if (atomic_dec_and_test(&job->sub_jobs)) {
+-
+- /*
+- * To avoid a race we must keep the job around
+- * until after the notify function has completed.
+- * Otherwise the client may try and stop the job
+- * after we've completed.
+- */
+- job->fn(read_err, write_err, job->context);
+- mempool_free(job, _job_pool);
+- }
+-}
+-
+-/*
+- * Create some little jobs that will do the move between
+- * them.
+- */
+-#define SPLIT_COUNT 8
+-static void split_job(struct kcopyd_job *job)
+-{
+- int i;
+-
+- atomic_set(&job->sub_jobs, SPLIT_COUNT);
+- for (i = 0; i < SPLIT_COUNT; i++)
+- segment_complete(0, 0u, job);
+-}
+-
+-int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from,
+- unsigned int num_dests, struct io_region *dests,
+- unsigned int flags, kcopyd_notify_fn fn, void *context)
+-{
+- struct kcopyd_job *job;
+-
+- /*
+- * Allocate a new job.
+- */
+- job = mempool_alloc(_job_pool, GFP_NOIO);
+-
+- /*
+- * set up for the read.
+- */
+- job->kc = kc;
+- job->flags = flags;
+- job->read_err = 0;
+- job->write_err = 0;
+- job->rw = READ;
+-
+- job->source = *from;
+-
+- job->num_dests = num_dests;
+- memcpy(&job->dests, dests, sizeof(*dests) * num_dests);
+-
+- job->offset = 0;
+- job->nr_pages = 0;
+- job->pages = NULL;
+-
+- job->fn = fn;
+- job->context = context;
+-
+- if (job->source.count < SUB_JOB_SIZE)
+- dispatch_job(job);
+-
+- else {
+- mutex_init(&job->lock);
+- job->progress = 0;
+- split_job(job);
+- }
+-
+- return 0;
+-}
+-
+-/*
+- * Cancels a kcopyd job, eg. someone might be deactivating a
+- * mirror.
+- */
+-#if 0
+-int kcopyd_cancel(struct kcopyd_job *job, int block)
+-{
+- /* FIXME: finish */
+- return -1;
+-}
+-#endif /* 0 */
+-
+-/*-----------------------------------------------------------------
+- * Unit setup
+- *---------------------------------------------------------------*/
+-static DEFINE_MUTEX(_client_lock);
+-static LIST_HEAD(_clients);
+-
+-static void client_add(struct kcopyd_client *kc)
+-{
+- mutex_lock(&_client_lock);
+- list_add(&kc->list, &_clients);
+- mutex_unlock(&_client_lock);
+-}
+-
+-static void client_del(struct kcopyd_client *kc)
+-{
+- mutex_lock(&_client_lock);
+- list_del(&kc->list);
+- mutex_unlock(&_client_lock);
+-}
+-
+-static DEFINE_MUTEX(kcopyd_init_lock);
+-static int kcopyd_clients = 0;
+-
+-static int kcopyd_init(void)
+-{
+- int r;
+-
+- mutex_lock(&kcopyd_init_lock);
+-
+- if (kcopyd_clients) {
+- /* Already initialized. */
+- kcopyd_clients++;
+- mutex_unlock(&kcopyd_init_lock);
+- return 0;
+- }
+-
+- r = jobs_init();
+- if (r) {
+- mutex_unlock(&kcopyd_init_lock);
+- return r;
+- }
+-
+- _kcopyd_wq = create_singlethread_workqueue("kcopyd");
+- if (!_kcopyd_wq) {
+- jobs_exit();
+- mutex_unlock(&kcopyd_init_lock);
+- return -ENOMEM;
+- }
+-
+- kcopyd_clients++;
+- INIT_WORK(&_kcopyd_work, do_work);
+- mutex_unlock(&kcopyd_init_lock);
+- return 0;
+-}
+-
+-static void kcopyd_exit(void)
+-{
+- mutex_lock(&kcopyd_init_lock);
+- kcopyd_clients--;
+- if (!kcopyd_clients) {
+- jobs_exit();
+- destroy_workqueue(_kcopyd_wq);
+- _kcopyd_wq = NULL;
+- }
+- mutex_unlock(&kcopyd_init_lock);
+-}
+-
+-int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result)
+-{
+- int r = 0;
+- struct kcopyd_client *kc;
+-
+- r = kcopyd_init();
+- if (r)
+- return r;
+-
+- kc = kmalloc(sizeof(*kc), GFP_KERNEL);
+- if (!kc) {
+- kcopyd_exit();
+- return -ENOMEM;
+- }
+-
+- spin_lock_init(&kc->lock);
+- kc->pages = NULL;
+- kc->nr_pages = kc->nr_free_pages = 0;
+- r = client_alloc_pages(kc, nr_pages);
+- if (r) {
+- kfree(kc);
+- kcopyd_exit();
+- return r;
+- }
+-
+- kc->io_client = dm_io_client_create(nr_pages);
+- if (IS_ERR(kc->io_client)) {
+- r = PTR_ERR(kc->io_client);
+- client_free_pages(kc);
+- kfree(kc);
+- kcopyd_exit();
+- return r;
+- }
+-
+- init_waitqueue_head(&kc->destroyq);
+- atomic_set(&kc->nr_jobs, 0);
+-
+- client_add(kc);
+- *result = kc;
+- return 0;
+-}
+-
+-void kcopyd_client_destroy(struct kcopyd_client *kc)
+-{
+- /* Wait for completion of all jobs submitted by this client. */
+- wait_event(kc->destroyq, !atomic_read(&kc->nr_jobs));
+-
+- dm_io_client_destroy(kc->io_client);
+- client_free_pages(kc);
+- client_del(kc);
+- kfree(kc);
+- kcopyd_exit();
+-}
+-
+-EXPORT_SYMBOL(kcopyd_client_create);
+-EXPORT_SYMBOL(kcopyd_client_destroy);
+-EXPORT_SYMBOL(kcopyd_copy);
+diff --git a/drivers/md/kcopyd.h b/drivers/md/kcopyd.h
+deleted file mode 100644
+index 4845f2a..0000000
+--- a/drivers/md/kcopyd.h
++++ /dev/null
+@@ -1,42 +0,0 @@
+-/*
+- * Copyright (C) 2001 Sistina Software
+- *
+- * This file is released under the GPL.
+- *
+- * Kcopyd provides a simple interface for copying an area of one
+- * block-device to one or more other block-devices, with an asynchronous
+- * completion notification.
+- */
+-
+-#ifndef DM_KCOPYD_H
+-#define DM_KCOPYD_H
+-
+-#include "dm-io.h"
+-
+-/* FIXME: make this configurable */
+-#define KCOPYD_MAX_REGIONS 8
+-
+-#define KCOPYD_IGNORE_ERROR 1
+-
+-/*
+- * To use kcopyd you must first create a kcopyd client object.
+- */
+-struct kcopyd_client;
+-int kcopyd_client_create(unsigned int num_pages, struct kcopyd_client **result);
+-void kcopyd_client_destroy(struct kcopyd_client *kc);
+-
+-/*
+- * Submit a copy job to kcopyd. This is built on top of the
+- * previous three fns.
+- *
+- * read_err is a boolean,
+- * write_err is a bitset, with 1 bit for each destination region
+- */
+-typedef void (*kcopyd_notify_fn)(int read_err, unsigned long write_err,
+- void *context);
+-
+-int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from,
+- unsigned int num_dests, struct io_region *dests,
+- unsigned int flags, kcopyd_notify_fn fn, void *context);
+-
+-#endif
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 61ccbd2..5ebfb4d 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -4152,7 +4152,7 @@ static int hot_remove_disk(mddev_t * mddev, dev_t dev)
+
+ return 0;
+ busy:
+- printk(KERN_WARNING "md: cannot remove active disk %s from %s ... \n",
++ printk(KERN_WARNING "md: cannot remove active disk %s from %s ...\n",
+ bdevname(rdev->bdev,b), mdname(mddev));
+ return -EBUSY;
+ }
+diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
+index 1195069..128bb9c 100644
+--- a/drivers/media/Kconfig
++++ b/drivers/media/Kconfig
+@@ -30,7 +30,7 @@ config VIDEO_V4L2_COMMON
+ depends on (I2C || I2C=n) && VIDEO_DEV
+ default (I2C || I2C=n) && VIDEO_DEV
+
+-config VIDEO_V4L1
++config VIDEO_ALLOW_V4L1
+ bool "Enable Video For Linux API 1 (DEPRECATED)"
+ depends on VIDEO_DEV && VIDEO_V4L2_COMMON
+ default VIDEO_DEV && VIDEO_V4L2_COMMON
+@@ -59,10 +59,15 @@ config VIDEO_V4L1_COMPAT
+ If you are unsure as to whether this is required, answer Y.
+
+ config VIDEO_V4L2
+- bool
++ tristate
+ depends on VIDEO_DEV && VIDEO_V4L2_COMMON
+ default VIDEO_DEV && VIDEO_V4L2_COMMON
+
++config VIDEO_V4L1
++ tristate
++ depends on VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1
++ default VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1
++
+ source "drivers/media/video/Kconfig"
+
+ source "drivers/media/radio/Kconfig"
+@@ -155,7 +160,7 @@ config VIDEOBUF_GEN
+ tristate
+
+ config VIDEOBUF_DMA_SG
+- depends on PCI
++ depends on HAS_DMA
+ select VIDEOBUF_GEN
+ tristate
+
+diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c
+index bb2a027..2665052 100644
+--- a/drivers/media/common/ir-functions.c
++++ b/drivers/media/common/ir-functions.c
+@@ -34,7 +34,7 @@ static int repeat = 1;
+ module_param(repeat, int, 0444);
+ MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)");
+
+-static int debug = 0; /* debug level (0,1,2) */
++static int debug; /* debug level (0,1,2) */
+ module_param(debug, int, 0644);
+
+ #define dprintk(level, fmt, arg...) if (debug >= level) \
+diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c
+index 2ab5a12..a348581 100644
+--- a/drivers/media/common/ir-keymaps.c
++++ b/drivers/media/common/ir-keymaps.c
+@@ -212,6 +212,51 @@ IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = {
+
+ EXPORT_SYMBOL_GPL(ir_codes_pixelview);
+
++/*
++ Mauro Carvalho Chehab <mchehab at infradead.org>
++ present on PV MPEG 8000GT
++ */
++IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE] = {
++ [0x3c] = KEY_PAUSE, /* Timeshift */
++ [0x12] = KEY_POWER,
++
++ [0x3d] = KEY_1,
++ [0x38] = KEY_2,
++ [0x18] = KEY_3,
++ [0x35] = KEY_4,
++ [0x39] = KEY_5,
++ [0x15] = KEY_6,
++ [0x36] = KEY_7,
++ [0x3a] = KEY_8,
++ [0x1e] = KEY_9,
++ [0x3e] = KEY_0,
++
++ [0x1c] = KEY_AGAIN, /* LOOP */
++ [0x3f] = KEY_MEDIA, /* Source */
++ [0x1f] = KEY_LAST, /* +100 */
++ [0x1b] = KEY_MUTE,
++
++ [0x17] = KEY_CHANNELDOWN,
++ [0x16] = KEY_CHANNELUP,
++ [0x10] = KEY_VOLUMEUP,
++ [0x14] = KEY_VOLUMEDOWN,
++ [0x13] = KEY_ZOOM,
++
++ [0x19] = KEY_SHUFFLE, /* SNAPSHOT */
++ [0x1a] = KEY_SEARCH, /* scan */
++
++ [0x37] = KEY_REWIND, /* << */
++ [0x32] = KEY_RECORD, /* o (red) */
++ [0x33] = KEY_FORWARD, /* >> */
++ [0x11] = KEY_STOP, /* square */
++ [0x3b] = KEY_PLAY, /* > */
++ [0x30] = KEY_PLAYPAUSE, /* || */
++
++ [0x31] = KEY_TV,
++ [0x34] = KEY_RADIO,
++};
++EXPORT_SYMBOL_GPL(ir_codes_pixelview_new);
++
+ IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = {
+ [ 0x00 ] = KEY_0,
+ [ 0x01 ] = KEY_1,
+@@ -726,7 +771,11 @@ IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = {
+ [ 0x12 ] = KEY_CHANNELUP, // Channel +
+ [ 0x13 ] = KEY_CHANNELDOWN, // Channel -
+ [ 0x06 ] = KEY_AGAIN, // Recall
+- [ 0x10 ] = KEY_ENTER, // Enter
++ [ 0x10 ] = KEY_ENTER, // Enter
++
++ [ 0x19 ] = KEY_BACK, // Rewind ( <<< )
++ [ 0x1f ] = KEY_FORWARD, // Forward ( >>> )
++ [ 0x0a ] = KEY_ANGLE, // (no label, may be used as the PAUSE button)
+ };
+
+ EXPORT_SYMBOL_GPL(ir_codes_flyvideo);
+@@ -1157,7 +1206,8 @@ EXPORT_SYMBOL_GPL(ir_codes_purpletv);
+
+ /* Mapping for the 28 key remote control as seen at
+ http://www.sednacomputer.com/photo/cardbus-tv.jpg
+- Pavel Mihaylov <bin at bash.info> */
++ Pavel Mihaylov <bin at bash.info>
++ Also for the remote bundled with Kozumi KTV-01C card */
+ IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = {
+ [ 0x00 ] = KEY_0,
+ [ 0x01 ] = KEY_1,
+@@ -1188,6 +1238,11 @@ IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = {
+ [ 0x1c ] = KEY_RADIO, /* FM Radio */
+ [ 0x1d ] = KEY_RECORD,
+ [ 0x1e ] = KEY_PAUSE,
++ /* additional codes for Kozumi's remote */
++ [0x14] = KEY_INFO, /* OSD */
++ [0x16] = KEY_OK, /* OK */
++ [0x17] = KEY_DIGITS, /* Plus */
++ [0x1f] = KEY_PLAY, /* Play */
+ };
+
+ EXPORT_SYMBOL_GPL(ir_codes_pctv_sedna);
+@@ -1988,6 +2043,76 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = {
+
+ EXPORT_SYMBOL_GPL(ir_codes_behold);
+
++/* Beholder Intl. Ltd. 2008
++ * Dmitry Belimov d.belimov at google.com
++ * Keytable is used by BeholdTV Columbus
++ * The "ascii-art picture" below (in comments, first row
++ * is the keycode in hex, and subsequent row(s) shows
++ * the button labels (several variants when appropriate)
++ * helps to descide which keycodes to assign to the buttons.
++ */
++IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE] = {
++
++ /* 0x13 0x11 0x1C 0x12 *
++ * Mute Source TV/FM Power *
++ * */
++
++ [0x13] = KEY_MUTE,
++ [0x11] = KEY_PROPS,
++ [0x1C] = KEY_TUNER, /* KEY_TV/KEY_RADIO */
++ [0x12] = KEY_POWER,
++
++ /* 0x01 0x02 0x03 0x0D *
++ * 1 2 3 Stereo *
++ * *
++ * 0x04 0x05 0x06 0x19 *
++ * 4 5 6 Snapshot *
++ * *
++ * 0x07 0x08 0x09 0x10 *
++ * 7 8 9 Zoom *
++ * */
++ [0x01] = KEY_1,
++ [0x02] = KEY_2,
++ [0x03] = KEY_3,
++ [0x0D] = KEY_SETUP, /* Setup key */
++ [0x04] = KEY_4,
++ [0x05] = KEY_5,
++ [0x06] = KEY_6,
++ [0x19] = KEY_BOOKMARKS, /* Snapshot key */
++ [0x07] = KEY_7,
++ [0x08] = KEY_8,
++ [0x09] = KEY_9,
++ [0x10] = KEY_ZOOM,
++
++ /* 0x0A 0x00 0x0B 0x0C *
++ * RECALL 0 ChannelUp VolumeUp *
++ * */
++ [0x0A] = KEY_AGAIN,
++ [0x00] = KEY_0,
++ [0x0B] = KEY_CHANNELUP,
++ [0x0C] = KEY_VOLUMEUP,
++
++ /* 0x1B 0x1D 0x15 0x18 *
++ * Timeshift Record ChannelDown VolumeDown *
++ * */
++
++ [0x1B] = KEY_REWIND,
++ [0x1D] = KEY_RECORD,
++ [0x15] = KEY_CHANNELDOWN,
++ [0x18] = KEY_VOLUMEDOWN,
++
++ /* 0x0E 0x1E 0x0F 0x1A *
++ * Stop Pause Previouse Next *
++ * */
++
++ [0x0E] = KEY_STOP,
++ [0x1E] = KEY_PAUSE,
++ [0x0F] = KEY_PREVIOUS,
++ [0x1A] = KEY_NEXT,
++
++};
++EXPORT_SYMBOL_GPL(ir_codes_behold_columbus);
++
+ /*
+ * Remote control for the Genius TVGO A11MCE
+ * Adrian Pardini <pardo.bsso at gmail.com>
+@@ -2033,3 +2158,46 @@ IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE] = {
+ [0x50] = KEY_BLUE,
+ };
+ EXPORT_SYMBOL_GPL(ir_codes_genius_tvgo_a11mce);
++
++/*
++ * Remote control for Powercolor Real Angel 330
++ * Daniel Fraga <fragabr at gmail.com>
++ */
++IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE] = {
++ [0x38] = KEY_SWITCHVIDEOMODE, /* switch inputs */
++ [0x0c] = KEY_MEDIA, /* Turn ON/OFF App */
++ [0x00] = KEY_0,
++ [0x01] = KEY_1,
++ [0x02] = KEY_2,
++ [0x03] = KEY_3,
++ [0x04] = KEY_4,
++ [0x05] = KEY_5,
++ [0x06] = KEY_6,
++ [0x07] = KEY_7,
++ [0x08] = KEY_8,
++ [0x09] = KEY_9,
++ [0x0a] = KEY_DIGITS, /* single, double, tripple digit */
++ [0x29] = KEY_PREVIOUS, /* previous channel */
++ [0x12] = KEY_BRIGHTNESSUP,
++ [0x13] = KEY_BRIGHTNESSDOWN,
++ [0x2b] = KEY_MODE, /* stereo/mono */
++ [0x2c] = KEY_TEXT, /* teletext */
++ [0x20] = KEY_UP, /* channel up */
++ [0x21] = KEY_DOWN, /* channel down */
++ [0x10] = KEY_RIGHT, /* volume up */
++ [0x11] = KEY_LEFT, /* volume down */
++ [0x0d] = KEY_MUTE,
++ [0x1f] = KEY_RECORD,
++ [0x17] = KEY_PLAY,
++ [0x16] = KEY_PAUSE,
++ [0x0b] = KEY_STOP,
++ [0x27] = KEY_FASTFORWARD,
++ [0x26] = KEY_REWIND,
++ [0x1e] = KEY_SEARCH, /* autoscan */
++ [0x0e] = KEY_SHUFFLE, /* snapshot */
++ [0x2d] = KEY_SETUP,
++ [0x0f] = KEY_SCREEN, /* full screen */
++ [0x14] = KEY_RADIO, /* FM radio */
++ [0x25] = KEY_POWER, /* power */
++};
++EXPORT_SYMBOL_GPL(ir_codes_powercolor_real_angel);
+diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
+index 7707b8c..89c7660 100644
+--- a/drivers/media/common/saa7146_core.c
++++ b/drivers/media/common/saa7146_core.c
+@@ -74,7 +74,7 @@ static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev,
+ if (err) {
+ printk(KERN_ERR "%s: %s timed out while waiting for "
+ "registers getting programmed\n",
+- dev->name, __FUNCTION__);
++ dev->name, __func__);
+ return -ETIMEDOUT;
+ }
+ msleep(1);
+@@ -89,7 +89,7 @@ static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev,
+ saa7146_read(dev, MC2);
+ if (err) {
+ DEB_S(("%s: %s timed out while waiting for transfer "
+- "completion\n", dev->name, __FUNCTION__));
++ "completion\n", dev->name, __func__));
+ return -ETIMEDOUT;
+ }
+ msleep(1);
+@@ -111,7 +111,7 @@ static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev,
+ if (!loops--) {
+ printk(KERN_ERR "%s: %s timed out while waiting for "
+ "registers getting programmed\n",
+- dev->name, __FUNCTION__);
++ dev->name, __func__);
+ return -ETIMEDOUT;
+ }
+ udelay(1);
+@@ -125,7 +125,7 @@ static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev,
+ saa7146_read(dev, MC2);
+ if (!loops--) {
+ DEB_S(("%s: %s timed out while waiting for transfer "
+- "completion\n", dev->name, __FUNCTION__));
++ "completion\n", dev->name, __func__));
+ return -ETIMEDOUT;
+ }
+ udelay(5);
+diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c
+index 7e7689a..35b01ec 100644
+--- a/drivers/media/common/saa7146_i2c.c
++++ b/drivers/media/common/saa7146_i2c.c
+@@ -203,7 +203,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
+ return -ERESTARTSYS;
+
+ printk(KERN_WARNING "%s %s [irq]: timed out waiting for end of xfer\n",
+- dev->name, __FUNCTION__);
++ dev->name, __func__);
+ return -EIO;
+ }
+ status = saa7146_read(dev, I2C_STATUS);
+@@ -221,7 +221,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
+ }
+ if (time_after(jiffies,timeout)) {
+ printk(KERN_WARNING "%s %s: timed out waiting for MC2\n",
+- dev->name, __FUNCTION__);
++ dev->name, __func__);
+ return -EIO;
+ }
+ }
+@@ -238,7 +238,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
+ * (no answer from nonexisistant device...)
+ */
+ printk(KERN_WARNING "%s %s [poll]: timed out waiting for end of xfer\n",
+- dev->name, __FUNCTION__);
++ dev->name, __func__);
+ return -EIO;
+ }
+ if (++trial < 50 && short_delay)
+diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c
+index bfbd5a8..74e2b56 100644
+--- a/drivers/media/common/saa7146_vbi.c
++++ b/drivers/media/common/saa7146_vbi.c
+@@ -407,8 +407,8 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
+ fh->vbi_fmt.start[1] = 312;
+ fh->vbi_fmt.count[1] = 16;
+
+- videobuf_queue_pci_init(&fh->vbi_q, &vbi_qops,
+- dev->pci, &dev->slock,
++ videobuf_queue_sg_init(&fh->vbi_q, &vbi_qops,
++ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VBI_CAPTURE,
+ V4L2_FIELD_SEQ_TB, // FIXME: does this really work?
+ sizeof(struct saa7146_buf),
+diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
+index 66fdbd0..3cbc6eb 100644
+--- a/drivers/media/common/saa7146_video.c
++++ b/drivers/media/common/saa7146_video.c
+@@ -1410,8 +1410,8 @@ static int video_open(struct saa7146_dev *dev, struct file *file)
+ sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
+ fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8;
+
+- videobuf_queue_pci_init(&fh->video_q, &video_qops,
+- dev->pci, &dev->slock,
++ videobuf_queue_sg_init(&fh->video_q, &video_qops,
++ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct saa7146_buf),
+diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig
+index 3197aeb..6ec5afb 100644
+--- a/drivers/media/dvb/b2c2/Kconfig
++++ b/drivers/media/dvb/b2c2/Kconfig
+@@ -9,6 +9,11 @@ config DVB_B2C2_FLEXCOP
+ select DVB_STV0297 if !DVB_FE_CUSTOMISE
+ select DVB_BCM3510 if !DVB_FE_CUSTOMISE
+ select DVB_LGDT330X if !DVB_FE_CUSTOMISE
++ select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
++ select DVB_S5H1420 if !DVB_FE_CUSTOMISE
++ select DVB_TUNER_ITD1000 if !DVB_FE_CUSTOMISE
++ select DVB_ISL6421 if !DVB_FE_CUSTOMISE
++ select DVB_CX24123 if !DVB_FE_CUSTOMISE
+ help
+ Support for the digital TV receiver chip made by B2C2 Inc. included in
+ Technisats PCI cards and USB boxes.
+diff --git a/drivers/media/dvb/b2c2/Makefile b/drivers/media/dvb/b2c2/Makefile
+index e97ff60..870e284 100644
+--- a/drivers/media/dvb/b2c2/Makefile
++++ b/drivers/media/dvb/b2c2/Makefile
+@@ -2,6 +2,7 @@ b2c2-flexcop-objs = flexcop.o flexcop-fe-tuner.o flexcop-i2c.o \
+ flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o
+ obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o
+
++
+ ifneq ($(CONFIG_DVB_B2C2_FLEXCOP_PCI),)
+ b2c2-flexcop-objs += flexcop-dma.o
+ endif
+@@ -13,3 +14,4 @@ b2c2-flexcop-usb-objs = flexcop-usb.o
+ obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o
+
+ EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
++EXTRA_CFLAGS += -Idrivers/media/video/
+diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h
+index 5a6c4fe..8ce0633 100644
+--- a/drivers/media/dvb/b2c2/flexcop-common.h
++++ b/drivers/media/dvb/b2c2/flexcop-common.h
+@@ -44,6 +44,14 @@ struct flexcop_dma {
+ u32 size; /* size of each address in bytes */
+ };
+
++struct flexcop_i2c_adapter {
++ struct flexcop_device *fc;
++ struct i2c_adapter i2c_adap;
++
++ u8 no_base_addr;
++ flexcop_i2c_port_t port;
++};
++
+ /* Control structure for data definitions that are common to
+ * the B2C2-based PCI and USB devices.
+ */
+@@ -72,7 +80,7 @@ struct flexcop_device {
+ struct dmx_frontend mem_frontend;
+ int (*fe_sleep) (struct dvb_frontend *);
+
+- struct i2c_adapter i2c_adap;
++ struct flexcop_i2c_adapter fc_i2c_adap[3];
+ struct mutex i2c_mutex;
+ struct module *owner;
+
+@@ -87,7 +95,8 @@ struct flexcop_device {
+ int (*write_ibi_reg) (struct flexcop_device *, flexcop_ibi_register, flexcop_ibi_value);
+
+
+- int (*i2c_request) (struct flexcop_device*, flexcop_access_op_t, flexcop_i2c_port_t, u8 chipaddr, u8 addr, u8 *buf, u16 len);
++ int (*i2c_request) (struct flexcop_i2c_adapter*,
++ flexcop_access_op_t, u8 chipaddr, u8 addr, u8 *buf, u16 len);
+ int (*stream_control) (struct flexcop_device*, int);
+
+ int (*get_mac_addr) (struct flexcop_device *fc, int extended);
+@@ -128,8 +137,8 @@ int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended);
+ * one. We have it in flexcop-i2c.c, because it is going via the actual
+ * I2C-channel of the flexcop.
+ */
+-int flexcop_i2c_request(struct flexcop_device*, flexcop_access_op_t,
+- flexcop_i2c_port_t, u8 chipaddr, u8 addr, u8 *buf, u16 len);
++int flexcop_i2c_request(struct flexcop_i2c_adapter*, flexcop_access_op_t,
++ u8 chipaddr, u8 addr, u8 *buf, u16 len);
+
+ /* from flexcop-sram.c */
+ int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, flexcop_sram_dest_target_t target);
+diff --git a/drivers/media/dvb/b2c2/flexcop-dma.c b/drivers/media/dvb/b2c2/flexcop-dma.c
+index 6f592bc..a91ed28 100644
+--- a/drivers/media/dvb/b2c2/flexcop-dma.c
++++ b/drivers/media/dvb/b2c2/flexcop-dma.c
+@@ -112,7 +112,7 @@ static int flexcop_dma_remap(struct flexcop_device *fc,
+ {
+ flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_00c : dma2_01c;
+ flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
+- deb_info("%s\n",__FUNCTION__);
++ deb_info("%s\n",__func__);
+ v.dma_0xc.remap_enable = onoff;
+ fc->write_ibi_reg(fc,r,v);
+ return 0;
+@@ -162,7 +162,7 @@ int flexcop_dma_config_timer(struct flexcop_device *fc,
+
+ flexcop_dma_remap(fc,dma_idx,0);
+
+- deb_info("%s\n",__FUNCTION__);
++ deb_info("%s\n",__func__);
+ v.dma_0x4_write.dmatimer = cycles;
+ fc->write_ibi_reg(fc,r,v);
+ return 0;
+diff --git a/drivers/media/dvb/b2c2/flexcop-eeprom.c b/drivers/media/dvb/b2c2/flexcop-eeprom.c
+index bbcf070..8a8ae8a 100644
+--- a/drivers/media/dvb/b2c2/flexcop-eeprom.c
++++ b/drivers/media/dvb/b2c2/flexcop-eeprom.c
+@@ -114,15 +114,18 @@ static int flexcop_eeprom_request(struct flexcop_device *fc, flexcop_access_op_t
+ {
+ int i,ret = 0;
+ u8 chipaddr = 0x50 | ((addr >> 8) & 3);
+- for (i = 0; i < retries; i++)
+- if ((ret = fc->i2c_request(fc,op,FC_I2C_PORT_EEPROM,chipaddr,addr & 0xff,buf,len)) == 0)
++ for (i = 0; i < retries; i++) {
++ ret = fc->i2c_request(&fc->fc_i2c_adap[1], op, chipaddr,
++ addr & 0xff, buf, len);
++ if (ret == 0)
+ break;
++ }
+ return ret;
+ }
+
+ static int flexcop_eeprom_lrc_read(struct flexcop_device *fc, u16 addr, u8 *buf, u16 len, int retries)
+ {
+- int ret = flexcop_eeprom_request(fc,FC_READ,addr,buf,len,retries);
++ int ret = flexcop_eeprom_request(fc, FC_READ, addr, buf, len, retries);
+ if (ret == 0)
+ if (calc_lrc(buf, len - 1) != buf[len - 1])
+ ret = -EINVAL;
+diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+index 0378fd6..7b0ea3b 100644
+--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
++++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+@@ -5,6 +5,8 @@
+ *
+ * see flexcop.c for copyright information.
+ */
++#include <media/tuner.h>
++
+ #include "flexcop.h"
+
+ #include "stv0299.h"
+@@ -15,6 +17,15 @@
+ #include "mt312.h"
+ #include "lgdt330x.h"
+ #include "dvb-pll.h"
++#include "tuner-simple.h"
++
++#include "s5h1420.h"
++#include "itd1000.h"
++
++#include "cx24123.h"
++#include "cx24113.h"
++
++#include "isl6421.h"
+
+ /* lnb control */
+
+@@ -180,13 +191,13 @@ static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend* fe, struct dv
+ buf[2] = 0x84; /* 0xC4 */
+ buf[3] = 0x08;
+
+- if (params->frequency < 1500000) buf[3] |= 0x10;
++ if (params->frequency < 1500000)
++ buf[3] |= 0x10;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+- if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1) {
++ if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1)
+ return -EIO;
+- }
+ return 0;
+ }
+
+@@ -241,7 +252,7 @@ static struct stv0299_config samsung_tbmu24112_config = {
+ .mclk = 88000000UL,
+ .invert = 0,
+ .skip_reinit = 0,
+- .lock_output = STV0229_LOCKOUTPUT_LK,
++ .lock_output = STV0299_LOCKOUTPUT_LK,
+ .volt13_op0_op1 = STV0299_VOLT13_OP1,
+ .min_delay_ms = 100,
+ .set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
+@@ -337,7 +348,7 @@ static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend* fe,
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+- if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1)
++ if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1)
+ return -EIO;
+ return 0;
+ }
+@@ -386,10 +397,11 @@ static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe,
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+ deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n",fep->frequency, buf[0],buf[1],buf[2],buf[3]);
+- ret = fc->i2c_request(fc, FC_WRITE, FC_I2C_PORT_TUNER, 0x61, buf[0], &buf[1], 3);
++ ret = fc->i2c_request(&fc->fc_i2c_adap[2],
++ FC_WRITE, 0x61, buf[0], &buf[1], 3);
+ deb_tuner("tuner write returned: %d\n",ret);
+
+- return 0;
++ return ret;
+ }
+
+ static u8 alps_tdee4_stv0297_inittab[] = {
+@@ -472,56 +484,159 @@ static struct stv0297_config alps_tdee4_stv0297_config = {
+ // .pll_set = alps_tdee4_stv0297_pll_set,
+ };
+
++
++/* SkyStar2 rev2.7 (a/u) */
++static struct s5h1420_config skystar2_rev2_7_s5h1420_config = {
++ .demod_address = 0x53,
++ .invert = 1,
++ .repeated_start_workaround = 1,
++};
++
++static struct itd1000_config skystar2_rev2_7_itd1000_config = {
++ .i2c_address = 0x61,
++};
++
++/* SkyStar2 rev2.8 */
++static struct cx24123_config skystar2_rev2_8_cx24123_config = {
++ .demod_address = 0x55,
++ .dont_use_pll = 1,
++ .agc_callback = cx24113_agc_callback,
++};
++
++static const struct cx24113_config skystar2_rev2_8_cx24113_config = {
++ .i2c_addr = 0x54,
++ .xtal_khz = 10111,
++};
++
+ /* try to figure out the frontend, each card/box can have on of the following list */
+ int flexcop_frontend_init(struct flexcop_device *fc)
+ {
+ struct dvb_frontend_ops *ops;
++ struct i2c_adapter *i2c = &fc->fc_i2c_adap[0].i2c_adap;
++ struct i2c_adapter *i2c_tuner;
++
++ /* enable no_base_addr - no repeated start when reading */
++ fc->fc_i2c_adap[0].no_base_addr = 1;
++ fc->fe = dvb_attach(s5h1420_attach, &skystar2_rev2_7_s5h1420_config, i2c);
++ if (fc->fe != NULL) {
++ flexcop_ibi_value r108;
++ i2c_tuner = s5h1420_get_tuner_i2c_adapter(fc->fe);
++ ops = &fc->fe->ops;
++
++ fc->fe_sleep = ops->sleep;
++ ops->sleep = flexcop_sleep;
++
++ fc->dev_type = FC_SKY_REV27;
++
++ /* enable no_base_addr - no repeated start when reading */
++ fc->fc_i2c_adap[2].no_base_addr = 1;
++ if (dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap, 0x08, 1, 1) == NULL)
++ err("ISL6421 could NOT be attached");
++ else
++ info("ISL6421 successfully attached");
++
++ /* the ITD1000 requires a lower i2c clock - it slows down the stuff for everyone - but is it a problem ? */
++ r108.raw = 0x00000506;
++ fc->write_ibi_reg(fc, tw_sm_c_108, r108);
++ if (i2c_tuner) {
++ if (dvb_attach(itd1000_attach, fc->fe, i2c_tuner, &skystar2_rev2_7_itd1000_config) == NULL)
++ err("ITD1000 could NOT be attached");
++ else
++ info("ITD1000 successfully attached");
++ }
++ goto fe_found;
++ }
++ fc->fc_i2c_adap[0].no_base_addr = 0; /* for the next devices we need it again */
++
++ /* try the sky v2.8 (cx24123, isl6421) */
++ fc->fe = dvb_attach(cx24123_attach,
++ &skystar2_rev2_8_cx24123_config, i2c);
++ if (fc->fe != NULL) {
++ i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe);
++ if (i2c_tuner != NULL) {
++ if (dvb_attach(cx24113_attach, fc->fe,
++ &skystar2_rev2_8_cx24113_config,
++ i2c_tuner) == NULL)
++ err("CX24113 could NOT be attached");
++ else
++ info("CX24113 successfully attached");
++ }
++
++ fc->dev_type = FC_SKY_REV28;
++
++ fc->fc_i2c_adap[2].no_base_addr = 1;
++ if (dvb_attach(isl6421_attach, fc->fe,
++ &fc->fc_i2c_adap[2].i2c_adap, 0x08, 0, 0) == NULL)
++ err("ISL6421 could NOT be attached");
++ else
++ info("ISL6421 successfully attached");
++
++ /* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an
++ * IR-receiver (PIC16F818) - but the card has no input for
++ * that ??? */
++
++ goto fe_found;
++ }
+
+ /* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
+- if ((fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
++ fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c);
++ if (fc->fe != NULL) {
+ ops = &fc->fe->ops;
+
+ ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
+
+ ops->set_voltage = flexcop_set_voltage;
+
+- fc->fe_sleep = ops->sleep;
+- ops->sleep = flexcop_sleep;
++ fc->fe_sleep = ops->sleep;
++ ops->sleep = flexcop_sleep;
++
++ fc->dev_type = FC_SKY;
++ goto fe_found;
++ }
+
+- fc->dev_type = FC_SKY;
+- info("found the stv0299 at i2c address: 0x%02x",samsung_tbmu24112_config.demod_address);
+- } else
+ /* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
+- if ((fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) {
+- fc->dev_type = FC_AIR_DVB;
++ fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c);
++ if (fc->fe != NULL) {
++ fc->dev_type = FC_AIR_DVB;
+ fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
+- info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
+- } else
++ goto fe_found;
++ }
++
+ /* try the air atsc 2nd generation (nxt2002) */
+- if ((fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
+- fc->dev_type = FC_AIR_ATSC2;
++ fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c);
++ if (fc->fe != NULL) {
++ fc->dev_type = FC_AIR_ATSC2;
+ dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, DVB_PLL_SAMSUNG_TBMV);
+- info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
+- } else
+- /* try the air atsc 3nd generation (lgdt3303) */
+- if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
+- fc->dev_type = FC_AIR_ATSC3;
+- dvb_attach(dvb_pll_attach, fc->fe, 0x61, &fc->i2c_adap, DVB_PLL_LG_TDVS_H06XF);
+- info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address);
+- } else
++ goto fe_found;
++ }
++
++ fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c);
++ if (fc->fe != NULL) {
++ fc->dev_type = FC_AIR_ATSC3;
++ dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61,
++ TUNER_LG_TDVS_H06XF);
++ goto fe_found;
++ }
++
+ /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
+- if ((fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) {
+- fc->dev_type = FC_AIR_ATSC1;
+- info("found the bcm3510 at i2c address: 0x%02x",air2pc_atsc_first_gen_config.demod_address);
+- } else
++ fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c);
++ if (fc->fe != NULL) {
++ fc->dev_type = FC_AIR_ATSC1;
++ goto fe_found;
++ }
++
+ /* try the cable dvb (stv0297) */
+- if ((fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
+- fc->dev_type = FC_CABLE;
++ fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c);
++ if (fc->fe != NULL) {
++ fc->dev_type = FC_CABLE;
+ fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
+- info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address);
+- } else
++ goto fe_found;
++ }
++
+ /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
+- if ((fc->fe = dvb_attach(vp310_mt312_attach, &skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
++ fc->fe = dvb_attach(vp310_mt312_attach,
++ &skystar23_samsung_tbdu18132_config, i2c);
++ if (fc->fe != NULL) {
+ ops = &fc->fe->ops;
+
+ ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params;
+@@ -535,19 +650,21 @@ int flexcop_frontend_init(struct flexcop_device *fc)
+ ops->sleep = flexcop_sleep;
+
+ fc->dev_type = FC_SKY_OLD;
+- info("found the vp310 (aka mt312) at i2c address: 0x%02x",skystar23_samsung_tbdu18132_config.demod_address);
++ goto fe_found;
+ }
+
+- if (fc->fe == NULL) {
+- err("no frontend driver found for this B2C2/FlexCop adapter");
+- return -ENODEV;
+- } else {
+- if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
+- err("frontend registration failed!");
+- dvb_frontend_detach(fc->fe);
+- fc->fe = NULL;
+- return -EINVAL;
+- }
++ err("no frontend driver found for this B2C2/FlexCop adapter");
++ return -ENODEV;
++
++fe_found:
++ info("found '%s' .", fc->fe->ops.info.name);
++ if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
++ err("frontend registration failed!");
++ ops = &fc->fe->ops;
++ if (ops->release != NULL)
++ ops->release(fc->fe);
++ fc->fe = NULL;
++ return -EINVAL;
+ }
+ fc->init_state |= FC_STATE_FE_INIT;
+ return 0;
+diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c
+index 6bf858a..55973ea 100644
+--- a/drivers/media/dvb/b2c2/flexcop-i2c.c
++++ b/drivers/media/dvb/b2c2/flexcop-i2c.c
+@@ -9,6 +9,8 @@
+
+ #define FC_MAX_I2C_RETRIES 100000
+
++/* #define DUMP_I2C_MESSAGES */
++
+ static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r100)
+ {
+ int i;
+@@ -38,30 +40,25 @@ static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r
+ return -EREMOTEIO;
+ }
+
+-static int flexcop_i2c_read4(struct flexcop_device *fc, flexcop_ibi_value r100, u8 *buf)
++static int flexcop_i2c_read4(struct flexcop_i2c_adapter *i2c,
++ flexcop_ibi_value r100, u8 *buf)
+ {
+ flexcop_ibi_value r104;
+ int len = r100.tw_sm_c_100.total_bytes, /* remember total_bytes is buflen-1 */
+ ret;
+
+- if ((ret = flexcop_i2c_operation(fc,&r100)) != 0) {
+- /* The Cablestar needs a different kind of i2c-transfer (does not
+- * support "Repeat Start"):
+- * wait for the ACK failure,
+- * and do a subsequent read with the Bit 30 enabled
+- */
+- r100.tw_sm_c_100.no_base_addr_ack_error = 1;
+- if ((ret = flexcop_i2c_operation(fc,&r100)) != 0) {
+- deb_i2c("no_base_addr read failed. %d\n",ret);
+- return ret;
+- }
++ r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr;
++ ret = flexcop_i2c_operation(i2c->fc, &r100);
++ if (ret != 0) {
++ deb_i2c("read failed. %d\n", ret);
++ return ret;
+ }
+
+ buf[0] = r100.tw_sm_c_100.data1_reg;
+
+ if (len > 0) {
+- r104 = fc->read_ibi_reg(fc,tw_sm_c_104);
+- deb_i2c("read: r100: %08x, r104: %08x\n",r100.raw,r104.raw);
++ r104 = i2c->fc->read_ibi_reg(i2c->fc, tw_sm_c_104);
++ deb_i2c("read: r100: %08x, r104: %08x\n", r100.raw, r104.raw);
+
+ /* there is at least one more byte, otherwise we wouldn't be here */
+ buf[1] = r104.tw_sm_c_104.data2_reg;
+@@ -85,17 +82,22 @@ static int flexcop_i2c_write4(struct flexcop_device *fc, flexcop_ibi_value r100,
+ r104.tw_sm_c_104.data3_reg = len > 1 ? buf[2] : 0;
+ r104.tw_sm_c_104.data4_reg = len > 2 ? buf[3] : 0;
+
+- deb_i2c("write: r100: %08x, r104: %08x\n",r100.raw,r104.raw);
++ deb_i2c("write: r100: %08x, r104: %08x\n", r100.raw, r104.raw);
+
+ /* write the additional i2c data before doing the actual i2c operation */
+- fc->write_ibi_reg(fc,tw_sm_c_104,r104);
+- return flexcop_i2c_operation(fc,&r100);
++ fc->write_ibi_reg(fc, tw_sm_c_104, r104);
++ return flexcop_i2c_operation(fc, &r100);
+ }
+
+-int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
+- flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u16 len)
++int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c,
++ flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len)
+ {
+ int ret;
++
++#ifdef DUMP_I2C_MESSAGES
++ int i;
++#endif
++
+ u16 bytes_to_transfer;
+ flexcop_ibi_value r100;
+
+@@ -103,7 +105,25 @@ int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
+ r100.raw = 0;
+ r100.tw_sm_c_100.chipaddr = chipaddr;
+ r100.tw_sm_c_100.twoWS_rw = op;
+- r100.tw_sm_c_100.twoWS_port_reg = port;
++ r100.tw_sm_c_100.twoWS_port_reg = i2c->port;
++
++#ifdef DUMP_I2C_MESSAGES
++ printk(KERN_DEBUG "%d ", i2c->port);
++ if (op == FC_READ)
++ printk("rd(");
++ else
++ printk("wr(");
++
++ printk("%02x): %02x ", chipaddr, addr);
++#endif
++
++ /* in that case addr is the only value ->
++ * we write it twice as baseaddr and val0
++ * BBTI is doing it like that for ISL6421 at least */
++ if (i2c->no_base_addr && len == 0 && op == FC_WRITE) {
++ buf = &addr;
++ len = 1;
++ }
+
+ while (len != 0) {
+ bytes_to_transfer = len > 4 ? 4 : len;
+@@ -112,9 +132,14 @@ int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
+ r100.tw_sm_c_100.baseaddr = addr;
+
+ if (op == FC_READ)
+- ret = flexcop_i2c_read4(fc, r100, buf);
++ ret = flexcop_i2c_read4(i2c, r100, buf);
+ else
+- ret = flexcop_i2c_write4(fc,r100, buf);
++ ret = flexcop_i2c_write4(i2c->fc, r100, buf);
++
++#ifdef DUMP_I2C_MESSAGES
++ for (i = 0; i < bytes_to_transfer; i++)
++ printk("%02x ", buf[i]);
++#endif
+
+ if (ret < 0)
+ return ret;
+@@ -122,7 +147,11 @@ int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
+ buf += bytes_to_transfer;
+ addr += bytes_to_transfer;
+ len -= bytes_to_transfer;
+- };
++ }
++
++#ifdef DUMP_I2C_MESSAGES
++ printk("\n");
++#endif
+
+ return 0;
+ }
+@@ -132,7 +161,7 @@ EXPORT_SYMBOL(flexcop_i2c_request);
+ /* master xfer callback for demodulator */
+ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
+ {
+- struct flexcop_device *fc = i2c_get_adapdata(i2c_adap);
++ struct flexcop_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap);
+ int i, ret = 0;
+
+ /* Some drivers use 1 byte or 0 byte reads as probes, which this
+@@ -142,34 +171,29 @@ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs
+ if (num == 1 && msgs[0].flags == I2C_M_RD && msgs[0].len <= 1)
+ return 1;
+
+- if (mutex_lock_interruptible(&fc->i2c_mutex))
++ if (mutex_lock_interruptible(&i2c->fc->i2c_mutex))
+ return -ERESTARTSYS;
+
+- /* reading */
+- if (num == 2 &&
+- msgs[0].flags == 0 &&
+- msgs[1].flags == I2C_M_RD &&
+- msgs[0].buf != NULL &&
+- msgs[1].buf != NULL) {
+-
+- ret = fc->i2c_request(fc, FC_READ, FC_I2C_PORT_DEMOD, msgs[0].addr, msgs[0].buf[0], msgs[1].buf, msgs[1].len);
+-
+- } else for (i = 0; i < num; i++) { /* writing command */
+- if (msgs[i].flags != 0 || msgs[i].buf == NULL || msgs[i].len < 2) {
+- ret = -EINVAL;
++ for (i = 0; i < num; i++) {
++ /* reading */
++ if (i+1 < num && (msgs[i+1].flags == I2C_M_RD)) {
++ ret = i2c->fc->i2c_request(i2c, FC_READ, msgs[i].addr,
++ msgs[i].buf[0], msgs[i+1].buf, msgs[i+1].len);
++ i++; /* skip the following message */
++ } else /* writing */
++ ret = i2c->fc->i2c_request(i2c, FC_WRITE, msgs[i].addr,
++ msgs[i].buf[0], &msgs[i].buf[1],
++ msgs[i].len - 1);
++ if (ret < 0) {
++ err("i2c master_xfer failed");
+ break;
+ }
+-
+- ret = fc->i2c_request(fc, FC_WRITE, FC_I2C_PORT_DEMOD, msgs[i].addr, msgs[i].buf[0], &msgs[i].buf[1], msgs[i].len - 1);
+ }
+
+- if (ret < 0)
+- err("i2c master_xfer failed");
+- else
+- ret = num;
+-
+- mutex_unlock(&fc->i2c_mutex);
++ mutex_unlock(&i2c->fc->i2c_mutex);
+
++ if (ret == 0)
++ ret = num;
+ return ret;
+ }
+
+@@ -189,28 +213,68 @@ int flexcop_i2c_init(struct flexcop_device *fc)
+
+ mutex_init(&fc->i2c_mutex);
+
+- memset(&fc->i2c_adap, 0, sizeof(struct i2c_adapter));
+- strncpy(fc->i2c_adap.name, "B2C2 FlexCop device",
+- sizeof(fc->i2c_adap.name));
+-
+- i2c_set_adapdata(&fc->i2c_adap,fc);
++ fc->fc_i2c_adap[0].fc = fc;
++ fc->fc_i2c_adap[1].fc = fc;
++ fc->fc_i2c_adap[2].fc = fc;
++
++ fc->fc_i2c_adap[0].port = FC_I2C_PORT_DEMOD;
++ fc->fc_i2c_adap[1].port = FC_I2C_PORT_EEPROM;
++ fc->fc_i2c_adap[2].port = FC_I2C_PORT_TUNER;
++
++ strncpy(fc->fc_i2c_adap[0].i2c_adap.name,
++ "B2C2 FlexCop I2C to demod", I2C_NAME_SIZE);
++ strncpy(fc->fc_i2c_adap[1].i2c_adap.name,
++ "B2C2 FlexCop I2C to eeprom", I2C_NAME_SIZE);
++ strncpy(fc->fc_i2c_adap[2].i2c_adap.name,
++ "B2C2 FlexCop I2C to tuner", I2C_NAME_SIZE);
++
++ i2c_set_adapdata(&fc->fc_i2c_adap[0].i2c_adap, &fc->fc_i2c_adap[0]);
++ i2c_set_adapdata(&fc->fc_i2c_adap[1].i2c_adap, &fc->fc_i2c_adap[1]);
++ i2c_set_adapdata(&fc->fc_i2c_adap[2].i2c_adap, &fc->fc_i2c_adap[2]);
++
++ fc->fc_i2c_adap[0].i2c_adap.class =
++ fc->fc_i2c_adap[1].i2c_adap.class =
++ fc->fc_i2c_adap[2].i2c_adap.class = I2C_CLASS_TV_DIGITAL;
++ fc->fc_i2c_adap[0].i2c_adap.algo =
++ fc->fc_i2c_adap[1].i2c_adap.algo =
++ fc->fc_i2c_adap[2].i2c_adap.algo = &flexcop_algo;
++ fc->fc_i2c_adap[0].i2c_adap.algo_data =
++ fc->fc_i2c_adap[1].i2c_adap.algo_data =
++ fc->fc_i2c_adap[2].i2c_adap.algo_data = NULL;
++ fc->fc_i2c_adap[0].i2c_adap.dev.parent =
++ fc->fc_i2c_adap[1].i2c_adap.dev.parent =
++ fc->fc_i2c_adap[2].i2c_adap.dev.parent = fc->dev;
++
++ ret = i2c_add_adapter(&fc->fc_i2c_adap[0].i2c_adap);
++ if (ret < 0)
++ return ret;
+
+- fc->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
+- fc->i2c_adap.algo = &flexcop_algo;
+- fc->i2c_adap.algo_data = NULL;
+- fc->i2c_adap.dev.parent = fc->dev;
++ ret = i2c_add_adapter(&fc->fc_i2c_adap[1].i2c_adap);
++ if (ret < 0)
++ goto adap_1_failed;
+
+- if ((ret = i2c_add_adapter(&fc->i2c_adap)) < 0)
+- return ret;
++ ret = i2c_add_adapter(&fc->fc_i2c_adap[2].i2c_adap);
++ if (ret < 0)
++ goto adap_2_failed;
+
+ fc->init_state |= FC_STATE_I2C_INIT;
+ return 0;
++
++adap_2_failed:
++ i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap);
++adap_1_failed:
++ i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap);
++
++ return ret;
+ }
+
+ void flexcop_i2c_exit(struct flexcop_device *fc)
+ {
+- if (fc->init_state & FC_STATE_I2C_INIT)
+- i2c_del_adapter(&fc->i2c_adap);
++ if (fc->init_state & FC_STATE_I2C_INIT) {
++ i2c_del_adapter(&fc->fc_i2c_adap[2].i2c_adap);
++ i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap);
++ i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap);
++ }
+
+ fc->init_state &= ~FC_STATE_I2C_INIT;
+ }
+diff --git a/drivers/media/dvb/b2c2/flexcop-misc.c b/drivers/media/dvb/b2c2/flexcop-misc.c
+index 167583b..93d20e5 100644
+--- a/drivers/media/dvb/b2c2/flexcop-misc.c
++++ b/drivers/media/dvb/b2c2/flexcop-misc.c
+@@ -52,6 +52,8 @@ static const char *flexcop_device_names[] = {
+ "Sky2PC/SkyStar 2 DVB-S (old version)",
+ "Cable2PC/CableStar 2 DVB-C",
+ "Air2PC/AirStar 2 ATSC 3rd generation (HD5000)",
++ "Sky2PC/SkyStar 2 DVB-S rev 2.7a/u",
++ "Sky2PC/SkyStar 2 DVB-S rev 2.8",
+ };
+
+ static const char *flexcop_bus_names[] = {
+diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c
+index 01af4d2..5b30dfc 100644
+--- a/drivers/media/dvb/b2c2/flexcop-pci.c
++++ b/drivers/media/dvb/b2c2/flexcop-pci.c
+@@ -32,7 +32,7 @@ MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ watchdog (currently jus
+ #define deb_irq(args...) dprintk(0x08,args)
+ #define deb_chk(args...) dprintk(0x10,args)
+
+-static int debug = 0;
++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);
+
+diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h
+index 491f9bd..7599fcc 100644
+--- a/drivers/media/dvb/b2c2/flexcop-reg.h
++++ b/drivers/media/dvb/b2c2/flexcop-reg.h
+@@ -25,6 +25,8 @@ typedef enum {
+ FC_SKY_OLD,
+ FC_CABLE,
+ FC_AIR_ATSC3,
++ FC_SKY_REV27,
++ FC_SKY_REV28,
+ } flexcop_device_type_t;
+
+ typedef enum {
+diff --git a/drivers/media/dvb/b2c2/flexcop-sram.c b/drivers/media/dvb/b2c2/flexcop-sram.c
+index 01570ec..cda6952 100644
+--- a/drivers/media/dvb/b2c2/flexcop-sram.c
++++ b/drivers/media/dvb/b2c2/flexcop-sram.c
+@@ -90,7 +90,7 @@ static void flexcop_sram_write(struct adapter *adapter, u32 bank, u32 addr, u8 *
+ };
+
+ if (retries == 0)
+- printk("%s: SRAM timeout\n", __FUNCTION__);
++ printk("%s: SRAM timeout\n", __func__);
+
+ write_reg_dw(adapter, 0x700, command);
+
+@@ -115,7 +115,7 @@ static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf,
+ };
+
+ if (retries == 0)
+- printk("%s: SRAM timeout\n", __FUNCTION__);
++ printk("%s: SRAM timeout\n", __func__);
+
+ write_reg_dw(adapter, 0x700, command);
+
+@@ -127,7 +127,7 @@ static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf,
+ };
+
+ if (retries == 0)
+- printk("%s: SRAM timeout\n", __FUNCTION__);
++ printk("%s: SRAM timeout\n", __func__);
+
+ value = read_reg_dw(adapter, 0x700) >> 0x10;
+
+@@ -240,13 +240,13 @@ static void sram_init(struct adapter *adapter)
+
+ adapter->dw_sram_type = tmp & 0x30000;
+
+- ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type);
++ ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type);
+
+ } else {
+
+ adapter->dw_sram_type = 0x10000;
+
+- ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type);
++ ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type);
+ }
+
+ /* return value is never used? */
+@@ -257,7 +257,7 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
+ {
+ u8 tmp1, tmp2;
+
+- dprintk("%s: mask = %x, addr = %x\n", __FUNCTION__, mask, addr);
++ dprintk("%s: mask = %x, addr = %x\n", __func__, mask, addr);
+
+ sram_set_size(adapter, mask);
+ sram_init(adapter);
+@@ -275,7 +275,7 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
+ sram_read(adapter, addr, &tmp2, 1);
+ sram_read(adapter, addr, &tmp2, 1);
+
+- dprintk("%s: wrote 0xa5, read 0x%2x\n", __FUNCTION__, tmp2);
++ dprintk("%s: wrote 0xa5, read 0x%2x\n", __func__, tmp2);
+
+ if (tmp2 != 0xa5)
+ return 0;
+@@ -293,7 +293,7 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
+ sram_read(adapter, addr, &tmp2, 1);
+ sram_read(adapter, addr, &tmp2, 1);
+
+- dprintk("%s: wrote 0x5a, read 0x%2x\n", __FUNCTION__, tmp2);
++ dprintk("%s: wrote 0x5a, read 0x%2x\n", __func__, tmp2);
+
+ if (tmp2 != 0x5a)
+ return 0;
+@@ -340,7 +340,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
+
+ tmp3 = read_reg_dw(adapter, 0x71c);
+
+- dprintk("%s: tmp3 = %x\n", __FUNCTION__, tmp3);
++ dprintk("%s: tmp3 = %x\n", __func__, tmp3);
+
+ write_reg_dw(adapter, 0x71c, tmp2);
+
+@@ -351,7 +351,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
+ sram_init(adapter);
+ write_reg_dw(adapter, 0x208, tmp);
+
+- dprintk("%s: sram size = 32K\n", __FUNCTION__);
++ dprintk("%s: sram size = 32K\n", __func__);
+
+ return 32;
+ }
+@@ -361,7 +361,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
+ sram_init(adapter);
+ write_reg_dw(adapter, 0x208, tmp);
+
+- dprintk("%s: sram size = 128K\n", __FUNCTION__);
++ dprintk("%s: sram size = 128K\n", __func__);
+
+ return 128;
+ }
+@@ -371,7 +371,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
+ sram_init(adapter);
+ write_reg_dw(adapter, 0x208, tmp);
+
+- dprintk("%s: sram size = 64K\n", __FUNCTION__);
++ dprintk("%s: sram size = 64K\n", __func__);
+
+ return 64;
+ }
+@@ -381,7 +381,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
+ sram_init(adapter);
+ write_reg_dw(adapter, 0x208, tmp);
+
+- dprintk("%s: sram size = 32K\n", __FUNCTION__);
++ dprintk("%s: sram size = 32K\n", __func__);
+
+ return 32;
+ }
+@@ -390,7 +390,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
+ sram_init(adapter);
+ write_reg_dw(adapter, 0x208, tmp);
+
+- dprintk("%s: SRAM detection failed. Set to 32K \n", __FUNCTION__);
++ dprintk("%s: SRAM detection failed. Set to 32K \n", __func__);
+
+ return 0;
+ }
+diff --git a/drivers/media/dvb/b2c2/flexcop-usb.c b/drivers/media/dvb/b2c2/flexcop-usb.c
+index 87fb75f..449fb5c 100644
+--- a/drivers/media/dvb/b2c2/flexcop-usb.c
++++ b/drivers/media/dvb/b2c2/flexcop-usb.c
+@@ -211,10 +211,11 @@ static int flexcop_usb_utility_req(struct flexcop_usb *fc_usb, int set,
+ #endif
+
+ /* usb i2c stuff */
+-static int flexcop_usb_i2c_req(struct flexcop_usb *fc_usb,
++static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
+ flexcop_usb_request_t req, flexcop_usb_i2c_function_t func,
+- flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u8 buflen)
++ u8 chipaddr, u8 addr, u8 *buf, u8 buflen)
+ {
++ struct flexcop_usb *fc_usb = i2c->fc->bus_specific;
+ u16 wValue, wIndex;
+ int nWaitTime,pipe,len;
+ // u8 dwRequestType;
+@@ -242,7 +243,7 @@ static int flexcop_usb_i2c_req(struct flexcop_usb *fc_usb,
+ deb_info("unsupported function for i2c_req %x\n",func);
+ return -EINVAL;
+ }
+- wValue = (func << 8 ) | (port << 4);
++ wValue = (func << 8) | (i2c->port << 4);
+ wIndex = (chipaddr << 8 ) | addr;
+
+ deb_i2c("i2c %2d: %02x %02x %02x %02x %02x %02x\n",func,request_type,req,
+@@ -274,13 +275,15 @@ static int flexcop_usb_write_ibi_reg(struct flexcop_device *fc, flexcop_ibi_regi
+ return flexcop_usb_readwrite_dw(fc,reg, &val.raw, 0);
+ }
+
+-static int flexcop_usb_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
+- flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u16 len)
++static int flexcop_usb_i2c_request(struct flexcop_i2c_adapter *i2c,
++ flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len)
+ {
+ if (op == FC_READ)
+- return flexcop_usb_i2c_req(fc->bus_specific,B2C2_USB_I2C_REQUEST,USB_FUNC_I2C_READ,port,chipaddr,addr,buf,len);
++ return flexcop_usb_i2c_req(i2c, B2C2_USB_I2C_REQUEST,
++ USB_FUNC_I2C_READ, chipaddr, addr, buf, len);
+ else
+- return flexcop_usb_i2c_req(fc->bus_specific,B2C2_USB_I2C_REQUEST,USB_FUNC_I2C_WRITE,port,chipaddr,addr,buf,len);
++ return flexcop_usb_i2c_req(i2c, B2C2_USB_I2C_REQUEST,
++ USB_FUNC_I2C_WRITE, chipaddr, addr, buf, len);
+ }
+
+ static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, u8 *buffer, int buffer_length)
+diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c
+index 2ddafd0..5f79c8d 100644
+--- a/drivers/media/dvb/b2c2/flexcop.c
++++ b/drivers/media/dvb/b2c2/flexcop.c
+@@ -49,6 +49,8 @@ module_param_named(debug, b2c2_flexcop_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debug level (1=info,2=tuner,4=i2c,8=ts,16=sram,32=reg (|-able))." DEBSTATUS);
+ #undef DEBSTATUS
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ /* global zero for ibi values */
+ flexcop_ibi_value ibi_zero;
+
+@@ -66,8 +68,10 @@ static int flexcop_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+
+ static int flexcop_dvb_init(struct flexcop_device *fc)
+ {
+- int ret;
+- if ((ret = dvb_register_adapter(&fc->dvb_adapter,"FlexCop Digital TV device",fc->owner,fc->dev)) < 0) {
++ int ret = dvb_register_adapter(&fc->dvb_adapter,
++ "FlexCop Digital TV device", fc->owner,
++ fc->dev, adapter_nr);
++ if (ret < 0) {
+ err("error registering DVB adapter");
+ return ret;
+ }
+@@ -257,6 +261,12 @@ int flexcop_device_initialize(struct flexcop_device *fc)
+ if ((ret = flexcop_dvb_init(fc)))
+ goto error;
+
++ /* i2c has to be done before doing EEProm stuff -
++ * because the EEProm is accessed via i2c */
++ ret = flexcop_i2c_init(fc);
++ if (ret)
++ goto error;
++
+ /* do the MAC address reading after initializing the dvb_adapter */
+ if (fc->get_mac_addr(fc, 0) == 0) {
+ u8 *b = fc->dvb_adapter.proposed_mac;
+@@ -266,10 +276,6 @@ int flexcop_device_initialize(struct flexcop_device *fc)
+ } else
+ warn("reading of MAC address failed.\n");
+
+-
+- if ((ret = flexcop_i2c_init(fc)))
+- goto error;
+-
+ if ((ret = flexcop_frontend_init(fc)))
+ goto error;
+
+diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig
+index ea66617..902c762 100644
+--- a/drivers/media/dvb/bt8xx/Kconfig
++++ b/drivers/media/dvb/bt8xx/Kconfig
+@@ -7,8 +7,8 @@ config DVB_BT8XX
+ select DVB_CX24110 if !DVB_FE_CUSTOMISE
+ select DVB_OR51211 if !DVB_FE_CUSTOMISE
+ select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+- select DVB_PLL if !DVB_FE_CUSTOMISE
+ select DVB_ZL10353 if !DVB_FE_CUSTOMISE
++ select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+ select FW_LOADER
+ help
+ Support for PCI cards based on the Bt8xx PCI bridge. Examples are
+diff --git a/drivers/media/dvb/bt8xx/Makefile b/drivers/media/dvb/bt8xx/Makefile
+index 84cf705..9d3e68b 100644
+--- a/drivers/media/dvb/bt8xx/Makefile
++++ b/drivers/media/dvb/bt8xx/Makefile
+@@ -1,3 +1,6 @@
+ obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
+
+-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video/bt8xx -Idrivers/media/dvb/frontends
++EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
++EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
++EXTRA_CFLAGS += -Idrivers/media/video/bt8xx
++EXTRA_CFLAGS += -Idrivers/media/video
+diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
+index 307ff35..75711bd 100644
+--- a/drivers/media/dvb/bt8xx/dst.c
++++ b/drivers/media/dvb/bt8xx/dst.c
+@@ -1290,7 +1290,7 @@ static int dst_get_signal(struct dst_state *state)
+ {
+ int retval;
+ u8 get_signal[] = { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb };
+- //dprintk("%s: Getting Signal strength and other parameters\n", __FUNCTION__);
++ //dprintk("%s: Getting Signal strength and other parameters\n", __func__);
+ if ((state->diseq_flags & ATTEMPT_TUNE) == 0) {
+ state->decode_lock = state->decode_strength = state->decode_snr = 0;
+ return 0;
+diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c
+index 50bc32a..0258451 100644
+--- a/drivers/media/dvb/bt8xx/dst_ca.c
++++ b/drivers/media/dvb/bt8xx/dst_ca.c
+@@ -36,13 +36,13 @@
+ #define dprintk(x, y, z, format, arg...) do { \
+ if (z) { \
+ if ((x > DST_CA_ERROR) && (x > y)) \
+- printk(KERN_ERR "%s: " format "\n", __FUNCTION__ , ##arg); \
++ printk(KERN_ERR "%s: " format "\n", __func__ , ##arg); \
+ else if ((x > DST_CA_NOTICE) && (x > y)) \
+- printk(KERN_NOTICE "%s: " format "\n", __FUNCTION__ , ##arg); \
++ printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg); \
+ else if ((x > DST_CA_INFO) && (x > y)) \
+- printk(KERN_INFO "%s: " format "\n", __FUNCTION__ , ##arg); \
++ printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \
+ else if ((x > DST_CA_DEBUG) && (x > y)) \
+- printk(KERN_DEBUG "%s: " format "\n", __FUNCTION__ , ##arg); \
++ printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg); \
+ } else { \
+ if (x > y) \
+ printk(format, ## arg); \
+@@ -162,7 +162,7 @@ static int ca_get_app_info(struct dst_state *state)
+ dprintk(verbose, DST_CA_INFO, 1, " ================================ CI Module Application Info ======================================");
+ dprintk(verbose, DST_CA_INFO, 1, " Application Type=[%d], Application Vendor=[%d], Vendor Code=[%d]\n%s: Application info=[%s]",
+ state->messages[7], (state->messages[8] << 8) | state->messages[9],
+- (state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12]));
++ (state->messages[10] << 8) | state->messages[11], __func__, (char *)(&state->messages[12]));
+ dprintk(verbose, DST_CA_INFO, 1, " ==================================================================================================");
+
+ // Transform dst message to correct application_info message
+diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+index dedd30a..6afbfbb 100644
+--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
++++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+@@ -40,10 +40,12 @@ static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define dprintk( args... ) \
+- do \
++ do { \
+ if (debug) printk(KERN_DEBUG args); \
+- while (0)
++ } while (0)
+
+ #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
+
+@@ -609,8 +611,9 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
+ lgdt330x_reset(card);
+ card->fe = dvb_attach(lgdt330x_attach, &tdvs_tua6034_config, card->i2c_adapter);
+ if (card->fe != NULL) {
+- dvb_attach(dvb_pll_attach, card->fe, 0x61,
+- card->i2c_adapter, DVB_PLL_LG_TDVS_H06XF);
++ dvb_attach(simple_tuner_attach, card->fe,
++ card->i2c_adapter, 0x61,
++ TUNER_LG_TDVS_H06XF);
+ dprintk ("dvb_bt8xx: lgdt330x detected\n");
+ }
+ break;
+@@ -670,7 +673,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
+ state->dst_ca = NULL;
+ /* DST is not a frontend, attaching the ASIC */
+ if (dvb_attach(dst_attach, state, &card->dvb_adapter) == NULL) {
+- printk("%s: Could not find a Twinhan DST.\n", __FUNCTION__);
++ printk("%s: Could not find a Twinhan DST.\n", __func__);
+ break;
+ }
+ /* Attach other DST peripherals if any */
+@@ -692,8 +695,9 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
+ case BTTV_BOARD_PC_HDTV:
+ card->fe = dvb_attach(or51211_attach, &or51211_config, card->i2c_adapter);
+ if (card->fe != NULL)
+- dvb_attach(dvb_pll_attach, card->fe, 0x61,
+- card->i2c_adapter, DVB_PLL_FCV1236D);
++ dvb_attach(simple_tuner_attach, card->fe,
++ card->i2c_adapter, 0x61,
++ TUNER_PHILIPS_FCV1236D);
+ break;
+ }
+
+@@ -715,7 +719,10 @@ static int __devinit dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
+ {
+ int result;
+
+- if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE, &card->bt->dev->dev)) < 0) {
++ result = dvb_register_adapter(&card->dvb_adapter, card->card_name,
++ THIS_MODULE, &card->bt->dev->dev,
++ adapter_nr);
++ if (result < 0) {
+ printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result);
+ return result;
+ }
+diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h
+index 436880e..4499ed2 100644
+--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h
++++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h
+@@ -38,7 +38,7 @@
+ #include "or51211.h"
+ #include "lgdt330x.h"
+ #include "zl10353.h"
+-#include "dvb-pll.h"
++#include "tuner-simple.h"
+
+ struct dvb_bt8xx_card {
+ struct mutex lock;
+diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
+index db08b0a..f5010e8 100644
+--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
++++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
+@@ -58,11 +58,13 @@ static int debug;
+ module_param_named(debug, debug, int, 0644);
+ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define dprintk(level, args...) \
+ do { \
+ if ((debug & level)) { \
+ printk("%s: %s(): ", KBUILD_MODNAME, \
+- __FUNCTION__); \
++ __func__); \
+ printk(args); } \
+ } while (0)
+
+@@ -938,7 +940,10 @@ static int cinergyt2_probe (struct usb_interface *intf,
+ return -ENOMEM;
+ }
+
+- if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE, &cinergyt2->udev->dev)) < 0) {
++ err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME,
++ THIS_MODULE, &cinergyt2->udev->dev,
++ adapter_nr);
++ if (err < 0) {
+ kfree(cinergyt2);
+ return err;
+ }
+diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
+index 0c1d87c..b0d347d 100644
+--- a/drivers/media/dvb/dvb-core/demux.h
++++ b/drivers/media/dvb/dvb-core/demux.h
+@@ -80,6 +80,8 @@ enum dmx_success {
+ #define TS_PAYLOAD_ONLY 2 /* in case TS_PACKET is set, only send the TS
+ payload (<=184 bytes per packet) to callback */
+ #define TS_DECODER 4 /* send stream to built-in decoder (if present) */
++#define TS_DEMUX 8 /* in case TS_PACKET is set, send the TS to
++ the demux device, not to the dvr device */
+
+ /* PES type for filters which write to built-in decoder */
+ /* these should be kept identical to the types in dmx.h */
+diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
+index f94bc31..df5bef6 100644
+--- a/drivers/media/dvb/dvb-core/dmxdev.c
++++ b/drivers/media/dvb/dvb-core/dmxdev.c
+@@ -126,7 +126,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
+ struct dmxdev *dmxdev = dvbdev->priv;
+ struct dmx_frontend *front;
+
+- dprintk("function : %s\n", __FUNCTION__);
++ dprintk("function : %s\n", __func__);
+
+ if (mutex_lock_interruptible(&dmxdev->mutex))
+ return -ERESTARTSYS;
+@@ -259,6 +259,39 @@ static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count,
+ return ret;
+ }
+
++static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev,
++ unsigned long size)
++{
++ struct dvb_ringbuffer *buf = &dmxdev->dvr_buffer;
++ void *newmem;
++ void *oldmem;
++
++ dprintk("function : %s\n", __func__);
++
++ if (buf->size == size)
++ return 0;
++ if (!size)
++ return -EINVAL;
++
++ newmem = vmalloc(size);
++ if (!newmem)
++ return -ENOMEM;
++
++ oldmem = buf->data;
++
++ spin_lock_irq(&dmxdev->lock);
++ buf->data = newmem;
++ buf->size = size;
++
++ /* reset and not flush in case the buffer shrinks */
++ dvb_ringbuffer_reset(buf);
++ spin_unlock_irq(&dmxdev->lock);
++
++ vfree(oldmem);
++
++ return 0;
++}
++
+ static inline void dvb_dmxdev_filter_state_set(struct dmxdev_filter
+ *dmxdevfilter, int state)
+ {
+@@ -271,28 +304,32 @@ static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter,
+ unsigned long size)
+ {
+ struct dvb_ringbuffer *buf = &dmxdevfilter->buffer;
+- void *mem;
++ void *newmem;
++ void *oldmem;
+
+ if (buf->size == size)
+ return 0;
++ if (!size)
++ return -EINVAL;
+ if (dmxdevfilter->state >= DMXDEV_STATE_GO)
+ return -EBUSY;
++
++ newmem = vmalloc(size);
++ if (!newmem)
++ return -ENOMEM;
++
++ oldmem = buf->data;
++
+ spin_lock_irq(&dmxdevfilter->dev->lock);
+- mem = buf->data;
+- buf->data = NULL;
++ buf->data = newmem;
+ buf->size = size;
+- dvb_ringbuffer_flush(buf);
++
++ /* reset and not flush in case the buffer shrinks */
++ dvb_ringbuffer_reset(buf);
+ spin_unlock_irq(&dmxdevfilter->dev->lock);
+- vfree(mem);
+
+- if (buf->size) {
+- mem = vmalloc(dmxdevfilter->buffer.size);
+- if (!mem)
+- return -ENOMEM;
+- spin_lock_irq(&dmxdevfilter->dev->lock);
+- buf->data = mem;
+- spin_unlock_irq(&dmxdevfilter->dev->lock);
+- }
++ vfree(oldmem);
++
+ return 0;
+ }
+
+@@ -374,7 +411,8 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
+ return 0;
+ }
+
+- if (dmxdevfilter->params.pes.output == DMX_OUT_TAP)
++ if (dmxdevfilter->params.pes.output == DMX_OUT_TAP
++ || dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP)
+ buffer = &dmxdevfilter->buffer;
+ else
+ buffer = &dmxdevfilter->dev->dvr_buffer;
+@@ -550,7 +588,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
+ dvb_dmxdev_section_callback);
+ if (ret < 0) {
+ printk("DVB (%s): could not alloc feed\n",
+- __FUNCTION__);
++ __func__);
+ return ret;
+ }
+
+@@ -558,7 +596,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
+ (para->flags & DMX_CHECK_CRC) ? 1 : 0);
+ if (ret < 0) {
+ printk("DVB (%s): could not set feed\n",
+- __FUNCTION__);
++ __func__);
+ dvb_dmxdev_feed_restart(filter);
+ return ret;
+ }
+@@ -620,9 +658,10 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
+
+ if (otype == DMX_OUT_TS_TAP)
+ ts_type |= TS_PACKET;
+-
+- if (otype == DMX_OUT_TAP)
+- ts_type |= TS_PAYLOAD_ONLY | TS_PACKET;
++ else if (otype == DMX_OUT_TSDEMUX_TAP)
++ ts_type |= TS_PACKET | TS_DEMUX;
++ else if (otype == DMX_OUT_TAP)
++ ts_type |= TS_PACKET | TS_DEMUX | TS_PAYLOAD_ONLY;
+
+ ret = dmxdev->demux->allocate_ts_feed(dmxdev->demux,
+ tsfeed,
+@@ -732,7 +771,7 @@ static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev,
+ struct dmxdev_filter *dmxdevfilter,
+ struct dmx_sct_filter_params *params)
+ {
+- dprintk("function : %s\n", __FUNCTION__);
++ dprintk("function : %s\n", __func__);
+
+ dvb_dmxdev_filter_stop(dmxdevfilter);
+
+@@ -1007,6 +1046,7 @@ static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file,
+ {
+ struct dvb_device *dvbdev = file->private_data;
+ struct dmxdev *dmxdev = dvbdev->priv;
++ unsigned long arg = (unsigned long)parg;
+ int ret;
+
+ if (mutex_lock_interruptible(&dmxdev->mutex))
+@@ -1014,8 +1054,7 @@ static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file,
+
+ switch (cmd) {
+ case DMX_SET_BUFFER_SIZE:
+- // FIXME: implement
+- ret = 0;
++ ret = dvb_dvr_set_buffer_size(dmxdev, arg);
+ break;
+
+ default:
+@@ -1038,7 +1077,7 @@ static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
+ struct dmxdev *dmxdev = dvbdev->priv;
+ unsigned int mask = 0;
+
+- dprintk("function : %s\n", __FUNCTION__);
++ dprintk("function : %s\n", __func__);
+
+ poll_wait(file, &dmxdev->dvr_buffer.queue, wait);
+
+diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+index 89437fd..8cbdb0e 100644
+--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
++++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+@@ -250,7 +250,7 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot,
+ unsigned long timeout;
+ unsigned long start;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ /* loop until timeout elapsed */
+ start = jiffies;
+@@ -263,7 +263,7 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot,
+
+ /* if we got the flags, it was successful! */
+ if (res & waitfor) {
+- dprintk("%s succeeded timeout:%lu\n", __FUNCTION__, jiffies - start);
++ dprintk("%s succeeded timeout:%lu\n", __func__, jiffies - start);
+ return 0;
+ }
+
+@@ -276,7 +276,7 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot,
+ msleep(1);
+ }
+
+- dprintk("%s failed timeout:%lu\n", __FUNCTION__, jiffies - start);
++ dprintk("%s failed timeout:%lu\n", __func__, jiffies - start);
+
+ /* if we get here, we've timed out */
+ return -ETIMEDOUT;
+@@ -297,7 +297,7 @@ static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot)
+ int buf_size;
+ u8 buf[2];
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ /* we'll be determining these during this function */
+ ca->slot_info[slot].da_irq_supported = 0;
+@@ -549,7 +549,7 @@ static int dvb_ca_en50221_set_configoption(struct dvb_ca_private *ca, int slot)
+ {
+ int configoption;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ /* set the config option */
+ ca->pub->write_attribute_mem(ca->pub, slot,
+@@ -587,7 +587,7 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 * eb
+ u8 buf[HOST_LINK_BUF_SIZE];
+ int i;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ /* check if we have space for a link buf in the rx_buffer */
+ if (ebuf == NULL) {
+@@ -708,7 +708,7 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * b
+ int status;
+ int i;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+
+ // sanity check
+@@ -785,7 +785,7 @@ EXPORT_SYMBOL(dvb_ca_en50221_camchange_irq);
+ */
+ static int dvb_ca_en50221_slot_shutdown(struct dvb_ca_private *ca, int slot)
+ {
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ ca->pub->slot_shutdown(ca->pub, slot);
+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
+@@ -892,7 +892,7 @@ void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221 *pubca, int slot)
+ static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca)
+ {
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ ca->wakeup = 1;
+ mb();
+@@ -964,7 +964,7 @@ static int dvb_ca_en50221_thread(void *data)
+ int pktcount;
+ void *rxbuf;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ /* choose the correct initial delay */
+ dvb_ca_en50221_thread_update_delay(ca);
+@@ -1172,7 +1172,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file,
+ int err = 0;
+ int slot;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ switch (cmd) {
+ case CA_RESET:
+@@ -1266,7 +1266,7 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
+ unsigned long timeout;
+ int written;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ /* Incoming packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */
+ if (count < 2)
+@@ -1401,7 +1401,7 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
+ int pktlen;
+ int dispose = 0;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ /* Outgoing packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */
+ if (count < 2)
+@@ -1490,7 +1490,7 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
+ int err;
+ int i;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ if (!try_module_get(ca->pub->owner))
+ return -EIO;
+@@ -1534,7 +1534,7 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
+ struct dvb_ca_private *ca = dvbdev->priv;
+ int err;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ /* mark the CA device as closed */
+ ca->open = 0;
+@@ -1564,7 +1564,7 @@ static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table * wait)
+ int slot;
+ int result = 0;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) {
+ mask |= POLLIN;
+@@ -1626,7 +1626,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
+ struct dvb_ca_private *ca = NULL;
+ int i;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ if (slot_count < 1)
+ return -EINVAL;
+@@ -1704,7 +1704,7 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
+ struct dvb_ca_private *ca = pubca->private;
+ int i;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ /* shutdown the thread if there was one */
+ kthread_stop(ca->thread);
+diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
+index 7959020..934e15f 100644
+--- a/drivers/media/dvb/dvb-core/dvb_demux.c
++++ b/drivers/media/dvb/dvb-core/dvb_demux.c
+@@ -368,7 +368,7 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
+ #define DVR_FEED(f) \
+ (((f)->type == DMX_TYPE_TS) && \
+ ((f)->feed.ts.is_filtering) && \
+- (((f)->ts_type & (TS_PACKET|TS_PAYLOAD_ONLY)) == TS_PACKET))
++ (((f)->ts_type & (TS_PACKET | TS_DEMUX)) == TS_PACKET))
+
+ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
+ {
+@@ -553,7 +553,7 @@ static void dvb_demux_feed_add(struct dvb_demux_feed *feed)
+ spin_lock_irq(&feed->demux->lock);
+ if (dvb_demux_feed_find(feed)) {
+ printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n",
+- __FUNCTION__, feed->type, feed->state, feed->pid);
++ __func__, feed->type, feed->state, feed->pid);
+ goto out;
+ }
+
+@@ -567,7 +567,7 @@ static void dvb_demux_feed_del(struct dvb_demux_feed *feed)
+ spin_lock_irq(&feed->demux->lock);
+ if (!(dvb_demux_feed_find(feed))) {
+ printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n",
+- __FUNCTION__, feed->type, feed->state, feed->pid);
++ __func__, feed->type, feed->state, feed->pid);
+ goto out;
+ }
+
+diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
+index 925cfa6..2dddd08 100644
+--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
++++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
+@@ -135,7 +135,7 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
+ struct dvb_frontend_event *e;
+ int wp;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ if (mutex_lock_interruptible (&events->mtx))
+ return;
+@@ -171,7 +171,7 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe,
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
+ struct dvb_fe_events *events = &fepriv->events;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ if (events->overflow) {
+ events->overflow = 0;
+@@ -237,7 +237,7 @@ static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepr
+ {
+ int q2;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ if (locked)
+ (fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256;
+@@ -329,7 +329,7 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
+
+ dprintk("%s: drift:%i inversion:%i auto_step:%i "
+ "auto_sub_step:%i started_auto_step:%i\n",
+- __FUNCTION__, fepriv->lnb_drift, fepriv->inversion,
++ __func__, fepriv->lnb_drift, fepriv->inversion,
+ fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step);
+
+ /* set the frontend itself */
+@@ -511,7 +511,7 @@ static int dvb_frontend_thread(void *data)
+ fe_status_t s;
+ struct dvb_frontend_parameters *params;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ fepriv->check_wrapped = 0;
+ fepriv->quality = 0;
+@@ -597,7 +597,7 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
+ {
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ fepriv->exit = 1;
+ mb();
+@@ -665,7 +665,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
+ struct task_struct *fe_thread;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ if (fepriv->thread) {
+ if (!fepriv->exit)
+@@ -763,7 +763,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
+ int err = -EOPNOTSUPP;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ if (fepriv->exit)
+ return -ENODEV;
+@@ -895,7 +895,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
+ int i;
+ u8 last = 1;
+ if (dvb_frontend_debug)
+- printk("%s switch command: 0x%04lx\n", __FUNCTION__, cmd);
++ printk("%s switch command: 0x%04lx\n", __func__, cmd);
+ do_gettimeofday(&nexttime);
+ if (dvb_frontend_debug)
+ memcpy(&tv[0], &nexttime, sizeof(struct timeval));
+@@ -919,7 +919,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
+ }
+ if (dvb_frontend_debug) {
+ printk("%s(%d): switch delay (should be 32k followed by all 8k\n",
+- __FUNCTION__, fe->dvb->num);
++ __func__, fe->dvb->num);
+ for (i = 1; i < 10; i++)
+ printk("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
+ }
+@@ -1037,7 +1037,7 @@ static unsigned int dvb_frontend_poll(struct file *file, struct poll_table_struc
+ struct dvb_frontend *fe = dvbdev->priv;
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ poll_wait (file, &fepriv->events.wait_queue, wait);
+
+@@ -1054,7 +1054,7 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
+ int ret;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) {
+ if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0)
+@@ -1095,7 +1095,7 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
+ int ret;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ if ((file->f_flags & O_ACCMODE) != O_RDONLY)
+ fepriv->release_jiffies = jiffies;
+@@ -1135,7 +1135,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
+ .kernel_ioctl = dvb_frontend_ioctl
+ };
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ if (mutex_lock_interruptible(&frontend_mutex))
+ return -ERESTARTSYS;
+@@ -1169,7 +1169,7 @@ EXPORT_SYMBOL(dvb_register_frontend);
+ int dvb_unregister_frontend(struct dvb_frontend* fe)
+ {
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ mutex_lock(&frontend_mutex);
+ dvb_frontend_stop (fe);
+diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
+index 4c8b62e..56d871c 100644
+--- a/drivers/media/dvb/dvb-core/dvb_net.c
++++ b/drivers/media/dvb/dvb-core/dvb_net.c
+@@ -354,7 +354,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
+ #ifdef ULE_DEBUG
+ /* The code inside ULE_DEBUG keeps a history of the last 100 TS cells processed. */
+ static unsigned char ule_hist[100*TS_SZ];
+- static unsigned char *ule_where = ule_hist, ule_dump = 0;
++ static unsigned char *ule_where = ule_hist, ule_dump;
+ #endif
+
+ /* For all TS cells in current buffer.
+@@ -965,17 +965,17 @@ static int dvb_net_feed_start(struct net_device *dev)
+ struct dmx_demux *demux = priv->demux;
+ unsigned char *mac = (unsigned char *) dev->dev_addr;
+
+- dprintk("%s: rx_mode %i\n", __FUNCTION__, priv->rx_mode);
++ dprintk("%s: rx_mode %i\n", __func__, priv->rx_mode);
+ mutex_lock(&priv->mutex);
+ if (priv->tsfeed || priv->secfeed || priv->secfilter || priv->multi_secfilter[0])
+- printk("%s: BUG %d\n", __FUNCTION__, __LINE__);
++ printk("%s: BUG %d\n", __func__, __LINE__);
+
+ priv->secfeed=NULL;
+ priv->secfilter=NULL;
+ priv->tsfeed = NULL;
+
+ if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
+- dprintk("%s: alloc secfeed\n", __FUNCTION__);
++ dprintk("%s: alloc secfeed\n", __func__);
+ ret=demux->allocate_section_feed(demux, &priv->secfeed,
+ dvb_net_sec_callback);
+ if (ret<0) {
+@@ -993,38 +993,38 @@ static int dvb_net_feed_start(struct net_device *dev)
+ }
+
+ if (priv->rx_mode != RX_MODE_PROMISC) {
+- dprintk("%s: set secfilter\n", __FUNCTION__);
++ dprintk("%s: set secfilter\n", __func__);
+ dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_normal);
+ }
+
+ switch (priv->rx_mode) {
+ case RX_MODE_MULTI:
+ for (i = 0; i < priv->multi_num; i++) {
+- dprintk("%s: set multi_secfilter[%d]\n", __FUNCTION__, i);
++ dprintk("%s: set multi_secfilter[%d]\n", __func__, i);
+ dvb_net_filter_sec_set(dev, &priv->multi_secfilter[i],
+ priv->multi_macs[i], mask_normal);
+ }
+ break;
+ case RX_MODE_ALL_MULTI:
+ priv->multi_num=1;
+- dprintk("%s: set multi_secfilter[0]\n", __FUNCTION__);
++ dprintk("%s: set multi_secfilter[0]\n", __func__);
+ dvb_net_filter_sec_set(dev, &priv->multi_secfilter[0],
+ mac_allmulti, mask_allmulti);
+ break;
+ case RX_MODE_PROMISC:
+ priv->multi_num=0;
+- dprintk("%s: set secfilter\n", __FUNCTION__);
++ dprintk("%s: set secfilter\n", __func__);
+ dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_promisc);
+ break;
+ }
+
+- dprintk("%s: start filtering\n", __FUNCTION__);
++ dprintk("%s: start filtering\n", __func__);
+ priv->secfeed->start_filtering(priv->secfeed);
+ } else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
+ struct timespec timeout = { 0, 10000000 }; // 10 msec
+
+ /* we have payloads encapsulated in TS */
+- dprintk("%s: alloc tsfeed\n", __FUNCTION__);
++ dprintk("%s: alloc tsfeed\n", __func__);
+ ret = demux->allocate_ts_feed(demux, &priv->tsfeed, dvb_net_ts_callback);
+ if (ret < 0) {
+ printk("%s: could not allocate ts feed\n", dev->name);
+@@ -1048,7 +1048,7 @@ static int dvb_net_feed_start(struct net_device *dev)
+ goto error;
+ }
+
+- dprintk("%s: start filtering\n", __FUNCTION__);
++ dprintk("%s: start filtering\n", __func__);
+ priv->tsfeed->start_filtering(priv->tsfeed);
+ } else
+ ret = -EINVAL;
+@@ -1063,17 +1063,17 @@ static int dvb_net_feed_stop(struct net_device *dev)
+ struct dvb_net_priv *priv = dev->priv;
+ int i, ret = 0;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+ mutex_lock(&priv->mutex);
+ if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
+ if (priv->secfeed) {
+ if (priv->secfeed->is_filtering) {
+- dprintk("%s: stop secfeed\n", __FUNCTION__);
++ dprintk("%s: stop secfeed\n", __func__);
+ priv->secfeed->stop_filtering(priv->secfeed);
+ }
+
+ if (priv->secfilter) {
+- dprintk("%s: release secfilter\n", __FUNCTION__);
++ dprintk("%s: release secfilter\n", __func__);
+ priv->secfeed->release_filter(priv->secfeed,
+ priv->secfilter);
+ priv->secfilter=NULL;
+@@ -1082,7 +1082,7 @@ static int dvb_net_feed_stop(struct net_device *dev)
+ for (i=0; i<priv->multi_num; i++) {
+ if (priv->multi_secfilter[i]) {
+ dprintk("%s: release multi_filter[%d]\n",
+- __FUNCTION__, i);
++ __func__, i);
+ priv->secfeed->release_filter(priv->secfeed,
+ priv->multi_secfilter[i]);
+ priv->multi_secfilter[i] = NULL;
+@@ -1096,7 +1096,7 @@ static int dvb_net_feed_stop(struct net_device *dev)
+ } else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
+ if (priv->tsfeed) {
+ if (priv->tsfeed->is_filtering) {
+- dprintk("%s: stop tsfeed\n", __FUNCTION__);
++ dprintk("%s: stop tsfeed\n", __func__);
+ priv->tsfeed->stop_filtering(priv->tsfeed);
+ }
+ priv->demux->release_ts_feed(priv->demux, priv->tsfeed);
+diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
+index ac9d93c..872985b 100644
+--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
++++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
+@@ -90,7 +90,11 @@ void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf)
+ rbuf->error = 0;
+ }
+
+-
++void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf)
++{
++ rbuf->pread = rbuf->pwrite = 0;
++ rbuf->error = 0;
++}
+
+ void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf)
+ {
+diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
+index d97714e..8908262 100644
+--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
++++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
+@@ -69,6 +69,7 @@ struct dvb_ringbuffer {
+ ** to lock read or write operations.
+ ** Two or more readers must be locked against each other.
+ ** Flushing the buffer counts as a read operation.
++** Resetting the buffer counts as a read and write operation.
+ ** Two or more writers must be locked against each other.
+ */
+
+@@ -85,6 +86,13 @@ extern ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf);
+ extern ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf);
+
+
++/*
++** Reset the read and write pointers to zero and flush the buffer
++** This counts as a read and write operation
++*/
++extern void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf);
++
++
+ /* read routines & macros */
+ /* ---------------------- */
+ /* flush buffer */
+diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
+index 18738fa..8b56d92 100644
+--- a/drivers/media/dvb/dvb-core/dvbdev.c
++++ b/drivers/media/dvb/dvb-core/dvbdev.c
+@@ -49,7 +49,6 @@ static const char * const dnames[] = {
+ "net", "osd"
+ };
+
+-#define DVB_MAX_ADAPTERS 8
+ #define DVB_MAX_IDS 4
+ #define nums2minor(num,type,id) ((num << 6) | (id << 4) | type)
+ #define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64)
+@@ -97,7 +96,7 @@ static int dvb_device_open(struct inode *inode, struct file *file)
+ }
+
+
+-static struct file_operations dvb_device_fops =
++static const struct file_operations dvb_device_fops =
+ {
+ .owner = THIS_MODULE,
+ .open = dvb_device_open,
+@@ -196,7 +195,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
+ if ((id = dvbdev_get_free_id (adap, type)) < 0){
+ mutex_unlock(&dvbdev_register_lock);
+ *pdvbdev = NULL;
+- printk(KERN_ERR "%s: couldn't find free device id\n", __FUNCTION__);
++ printk(KERN_ERR "%s: couldn't find free device id\n", __func__);
+ return -ENFILE;
+ }
+
+@@ -235,7 +234,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
+ "dvb%d.%s%d", adap->num, dnames[type], id);
+ if (IS_ERR(clsdev)) {
+ printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n",
+- __FUNCTION__, adap->num, dnames[type], id, PTR_ERR(clsdev));
++ __func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
+ return PTR_ERR(clsdev);
+ }
+
+@@ -262,18 +261,25 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
+ }
+ EXPORT_SYMBOL(dvb_unregister_device);
+
++static int dvbdev_check_free_adapter_num(int num)
++{
++ struct list_head *entry;
++ list_for_each(entry, &dvb_adapter_list) {
++ struct dvb_adapter *adap;
++ adap = list_entry(entry, struct dvb_adapter, list_head);
++ if (adap->num == num)
++ return 0;
++ }
++ return 1;
++}
+
+ static int dvbdev_get_free_adapter_num (void)
+ {
+ int num = 0;
+
+ while (num < DVB_MAX_ADAPTERS) {
+- struct dvb_adapter *adap;
+- list_for_each_entry(adap, &dvb_adapter_list, list_head)
+- if (adap->num == num)
+- goto skip;
+- return num;
+-skip:
++ if (dvbdev_check_free_adapter_num(num))
++ return num;
+ num++;
+ }
+
+@@ -281,13 +287,28 @@ skip:
+ }
+
+
+-int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct module *module, struct device *device)
++int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
++ struct module *module, struct device *device,
++ short *adapter_nums)
+ {
+- int num;
++ int i, num;
+
+ mutex_lock(&dvbdev_register_lock);
+
+- if ((num = dvbdev_get_free_adapter_num ()) < 0) {
++ for (i = 0; i < DVB_MAX_ADAPTERS; ++i) {
++ num = adapter_nums[i];
++ if (num >= 0 && num < DVB_MAX_ADAPTERS) {
++ /* use the one the driver asked for */
++ if (dvbdev_check_free_adapter_num(num))
++ break;
++ } else {
++ num = dvbdev_get_free_adapter_num();
++ break;
++ }
++ num = -1;
++ }
++
++ if (num < 0) {
+ mutex_unlock(&dvbdev_register_lock);
+ return -ENFILE;
+ }
+diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h
+index 6dff10e..5f9a737 100644
+--- a/drivers/media/dvb/dvb-core/dvbdev.h
++++ b/drivers/media/dvb/dvb-core/dvbdev.h
+@@ -31,6 +31,10 @@
+
+ #define DVB_MAJOR 212
+
++#define DVB_MAX_ADAPTERS 8
++
++#define DVB_UNSET (-1)
++
+ #define DVB_DEVICE_VIDEO 0
+ #define DVB_DEVICE_AUDIO 1
+ #define DVB_DEVICE_SEC 2
+@@ -41,6 +45,11 @@
+ #define DVB_DEVICE_NET 7
+ #define DVB_DEVICE_OSD 8
+
++#define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \
++ static short adapter_nr[] = \
++ {[0 ... (DVB_MAX_ADAPTERS - 1)] = DVB_UNSET }; \
++ module_param_array(adapter_nr, short, NULL, 0444); \
++ MODULE_PARM_DESC(adapter_nr, "DVB adapter numbers")
+
+ struct dvb_adapter {
+ int num;
+@@ -78,7 +87,9 @@ struct dvb_device {
+ };
+
+
+-extern int dvb_register_adapter (struct dvb_adapter *adap, const char *name, struct module *module, struct device *device);
++extern int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
++ struct module *module, struct device *device,
++ short *adapter_nums);
+ extern int dvb_unregister_adapter (struct dvb_adapter *adap);
+
+ extern int dvb_register_device (struct dvb_adapter *adap,
+diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
+index d73934d..3c8493d 100644
+--- a/drivers/media/dvb/dvb-usb/Kconfig
++++ b/drivers/media/dvb/dvb-usb/Kconfig
+@@ -105,6 +105,7 @@ config DVB_USB_CXUSB
+ select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+ select DVB_MT352 if !DVB_FE_CUSTOMISE
+ select DVB_ZL10353 if !DVB_FE_CUSTOMISE
++ select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+ help
+ Say Y here to support the Conexant USB2.0 hybrid reference design.
+ Currently, only DVB and ATSC modes are supported, analog mode
+diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c
+index a6c5f19..dc8c878 100644
+--- a/drivers/media/dvb/dvb-usb/a800.c
++++ b/drivers/media/dvb/dvb-usb/a800.c
+@@ -18,6 +18,9 @@
+ static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (rc=1 (or-able))." DVB_USB_DEBUG_STATUS);
++
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define deb_rc(args...) dprintk(debug,0x01,args)
+
+ static int a800_power_ctrl(struct dvb_usb_device *d, int onoff)
+@@ -94,7 +97,8 @@ static struct dvb_usb_device_properties a800_properties;
+ static int a800_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+ {
+- return dvb_usb_device_init(intf,&a800_properties,THIS_MODULE,NULL);
++ return dvb_usb_device_init(intf, &a800_properties,
++ THIS_MODULE, NULL, adapter_nr);
+ }
+
+ /* do not change the order of the ID table */
+diff --git a/drivers/media/dvb/dvb-usb/af9005.c b/drivers/media/dvb/dvb-usb/af9005.c
+index e7f76f5..cfe71fe 100644
+--- a/drivers/media/dvb/dvb-usb/af9005.c
++++ b/drivers/media/dvb/dvb-usb/af9005.c
+@@ -39,6 +39,8 @@ int dvb_usb_af9005_dump_eeprom = 0;
+ module_param_named(dump_eeprom, dvb_usb_af9005_dump_eeprom, int, 0);
+ MODULE_PARM_DESC(dump_eeprom, "dump contents of the eeprom.");
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ /* remote control decoder */
+ int (*rc_decode) (struct dvb_usb_device * d, u8 * data, int len, u32 * event,
+ int *state);
+@@ -1020,7 +1022,8 @@ static struct dvb_usb_device_properties af9005_properties;
+ static int af9005_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+ {
+- return dvb_usb_device_init(intf, &af9005_properties, THIS_MODULE, NULL);
++ return dvb_usb_device_init(intf, &af9005_properties,
++ THIS_MODULE, NULL, adapter_nr);
+ }
+
+ static struct usb_device_id af9005_usb_table[] = {
+diff --git a/drivers/media/dvb/dvb-usb/au6610.c b/drivers/media/dvb/dvb-usb/au6610.c
+index f3ff813..2ccb90f 100644
+--- a/drivers/media/dvb/dvb-usb/au6610.c
++++ b/drivers/media/dvb/dvb-usb/au6610.c
+@@ -19,6 +19,8 @@ static int dvb_usb_au6610_debug;
+ module_param_named(debug, dvb_usb_au6610_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
+ u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
+ {
+@@ -163,7 +165,9 @@ static int au6610_probe(struct usb_interface *intf,
+ if (intf->num_altsetting < AU6610_ALTSETTING_COUNT)
+ return -ENODEV;
+
+- if ((ret = dvb_usb_device_init(intf, &au6610_properties, THIS_MODULE, &d)) == 0) {
++ ret = dvb_usb_device_init(intf, &au6610_properties, THIS_MODULE, &d,
++ adapter_nr);
++ if (ret == 0) {
+ alt = usb_altnum_to_altsetting(intf, AU6610_ALTSETTING);
+
+ if (alt == NULL) {
+diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
+index c583650..720fcd1 100644
+--- a/drivers/media/dvb/dvb-usb/cxusb.c
++++ b/drivers/media/dvb/dvb-usb/cxusb.c
+@@ -23,6 +23,8 @@
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
++#include <media/tuner.h>
++
+ #include "cxusb.h"
+
+ #include "cx22702.h"
+@@ -31,12 +33,15 @@
+ #include "mt352_priv.h"
+ #include "zl10353.h"
+ #include "tuner-xc2028.h"
+-#include "tuner-xc2028-types.h"
++#include "tuner-simple.h"
+
+ /* debug */
+ static int dvb_usb_cxusb_debug;
+ module_param_named(debug, dvb_usb_cxusb_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
++
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define deb_info(args...) dprintk(dvb_usb_cxusb_debug,0x01,args)
+ #define deb_i2c(args...) if (d->udev->descriptor.idVendor == USB_VID_MEDION) \
+ dprintk(dvb_usb_cxusb_debug,0x01,args)
+@@ -450,8 +455,9 @@ static struct mt352_config cxusb_mt352_xc3028_config = {
+ /* Callbacks for DVB USB */
+ static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
+ {
+- dvb_attach(dvb_pll_attach, adap->fe, 0x61, &adap->dev->i2c_adap,
+- DVB_PLL_FMD1216ME);
++ dvb_attach(simple_tuner_attach, adap->fe,
++ &adap->dev->i2c_adap, 0x61,
++ TUNER_PHILIPS_FMD1216ME_MK3);
+ return 0;
+ }
+
+@@ -477,8 +483,8 @@ static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap)
+
+ static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap)
+ {
+- dvb_attach(dvb_pll_attach, adap->fe, 0x61, &adap->dev->i2c_adap,
+- DVB_PLL_LG_TDVS_H06XF);
++ dvb_attach(simple_tuner_attach, adap->fe,
++ &adap->dev->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF);
+ return 0;
+ }
+
+@@ -488,14 +494,14 @@ static int dvico_bluebird_xc2028_callback(void *ptr, int command, int arg)
+
+ switch (command) {
+ case XC2028_TUNER_RESET:
+- deb_info("%s: XC2028_TUNER_RESET %d\n", __FUNCTION__, arg);
++ deb_info("%s: XC2028_TUNER_RESET %d\n", __func__, arg);
+ cxusb_bluebird_gpio_pulse(d, 0x01, 1);
+ break;
+ case XC2028_RESET_CLK:
+- deb_info("%s: XC2028_RESET_CLK %d\n", __FUNCTION__, arg);
++ deb_info("%s: XC2028_RESET_CLK %d\n", __func__, arg);
+ break;
+ default:
+- deb_info("%s: unknown command %d, arg %d\n", __FUNCTION__,
++ deb_info("%s: unknown command %d, arg %d\n", __func__,
+ command, arg);
+ return -EINVAL;
+ }
+@@ -509,13 +515,12 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
+ struct xc2028_config cfg = {
+ .i2c_adap = &adap->dev->i2c_adap,
+ .i2c_addr = 0x61,
+- .video_dev = adap->dev,
+ .callback = dvico_bluebird_xc2028_callback,
+ };
+ static struct xc2028_ctrl ctl = {
+ .fname = "xc3028-dvico-au-01.fw",
+ .max_len = 64,
+- .scode_table = ZARLINK456,
++ .scode_table = XC3028_FE_ZARLINK456,
+ };
+
+ fe = dvb_attach(xc2028_attach, adap->fe, &cfg);
+@@ -720,16 +725,24 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope
+ static int cxusb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+ {
+- if (dvb_usb_device_init(intf,&cxusb_medion_properties,THIS_MODULE,NULL) == 0 ||
+- dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 ||
+- dvb_usb_device_init(intf,&cxusb_bluebird_dee1601_properties,THIS_MODULE,NULL) == 0 ||
+- dvb_usb_device_init(intf,&cxusb_bluebird_lgz201_properties,THIS_MODULE,NULL) == 0 ||
+- dvb_usb_device_init(intf,&cxusb_bluebird_dtt7579_properties,THIS_MODULE,NULL) == 0 ||
+- dvb_usb_device_init(intf,&cxusb_bluebird_dualdig4_properties,THIS_MODULE,NULL) == 0 ||
+- dvb_usb_device_init(intf,&cxusb_bluebird_nano2_properties,THIS_MODULE,NULL) == 0 ||
+- dvb_usb_device_init(intf,&cxusb_bluebird_nano2_needsfirmware_properties,THIS_MODULE,NULL) == 0) {
++ if (0 == dvb_usb_device_init(intf, &cxusb_medion_properties,
++ THIS_MODULE, NULL, adapter_nr) ||
++ 0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgh064f_properties,
++ THIS_MODULE, NULL, adapter_nr) ||
++ 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dee1601_properties,
++ THIS_MODULE, NULL, adapter_nr) ||
++ 0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgz201_properties,
++ THIS_MODULE, NULL, adapter_nr) ||
++ 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dtt7579_properties,
++ THIS_MODULE, NULL, adapter_nr) ||
++ 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dualdig4_properties,
++ THIS_MODULE, NULL, adapter_nr) ||
++ 0 == dvb_usb_device_init(intf, &cxusb_bluebird_nano2_properties,
++ THIS_MODULE, NULL, adapter_nr) ||
++ 0 == dvb_usb_device_init(intf,
++ &cxusb_bluebird_nano2_needsfirmware_properties,
++ THIS_MODULE, NULL, adapter_nr))
+ return 0;
+- }
+
+ return -EINVAL;
+ }
+diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h
+index 4a903ea..66d4dc6 100644
+--- a/drivers/media/dvb/dvb-usb/dib0700.h
++++ b/drivers/media/dvb/dvb-usb/dib0700.h
+@@ -37,6 +37,7 @@ struct dib0700_state {
+ u8 channel_state;
+ u16 mt2060_if1[2];
+ u8 rc_toggle;
++ u8 rc_counter;
+ u8 is_dib7000pc;
+ };
+
+@@ -44,12 +45,15 @@ extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8
+ extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3);
+ extern int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen);
+ extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw);
++extern int dib0700_rc_setup(struct dvb_usb_device *d);
+ extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff);
+ extern struct i2c_algorithm dib0700_i2c_algo;
+ extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
+ struct dvb_usb_device_description **desc, int *cold);
+
+ extern int dib0700_device_count;
++extern int dvb_usb_dib0700_ir_proto;
+ extern struct dvb_usb_device_properties dib0700_devices[];
+ extern struct usb_device_id dib0700_usb_id_table[];
++
+ #endif
+diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c
+index c9857d5..595a046 100644
+--- a/drivers/media/dvb/dvb-usb/dib0700_core.c
++++ b/drivers/media/dvb/dvb-usb/dib0700_core.c
+@@ -13,10 +13,12 @@ int dvb_usb_dib0700_debug;
+ module_param_named(debug,dvb_usb_dib0700_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=info,2=fw,4=fwdata,8=data (or-able))." DVB_USB_DEBUG_STATUS);
+
+-static int dvb_usb_dib0700_ir_proto = 1;
++int dvb_usb_dib0700_ir_proto = 1;
+ module_param(dvb_usb_dib0700_ir_proto, int, 0644);
+ MODULE_PARM_DESC(dvb_usb_dib0700_ir_proto, "set ir protocol (0=NEC, 1=RC5 (default), 2=RC6).");
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ /* expecting rx buffer: request data[0] data[1] ... data[2] */
+ static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen)
+ {
+@@ -261,7 +263,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+ return dib0700_ctrl_wr(adap->dev, b, 4);
+ }
+
+-static int dib0700_rc_setup(struct dvb_usb_device *d)
++int dib0700_rc_setup(struct dvb_usb_device *d)
+ {
+ u8 rc_setup[3] = {REQUEST_SET_RC, dvb_usb_dib0700_ir_proto, 0};
+ int i = dib0700_ctrl_wr(d, rc_setup, 3);
+@@ -279,7 +281,8 @@ static int dib0700_probe(struct usb_interface *intf,
+ struct dvb_usb_device *dev;
+
+ for (i = 0; i < dib0700_device_count; i++)
+- if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE, &dev) == 0)
++ if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE,
++ &dev, adapter_nr) == 0)
+ {
+ dib0700_rc_setup(dev);
+ return 0;
+diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
+index e709382..3462238 100644
+--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
++++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
+@@ -13,6 +13,7 @@
+ #include "dib7000p.h"
+ #include "mt2060.h"
+ #include "mt2266.h"
++#include "tuner-xc2028.h"
+ #include "dib0070.h"
+
+ static int force_lna_activation;
+@@ -297,10 +298,156 @@ static int stk7700d_tuner_attach(struct dvb_usb_adapter *adap)
+ &stk7700d_mt2266_config[adap->id]) == NULL ? -ENODEV : 0;;
+ }
+
++/* STK7700-PH: Digital/Analog Hybrid Tuner, e.h. Cinergy HT USB HE */
++static struct dibx000_agc_config xc3028_agc_config = {
++ BAND_VHF | BAND_UHF, /* band_caps */
++
++ /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=0,
++ * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
++ * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
++ (0 << 15) | (0 << 14) | (0 << 11) | (0 << 10) | (0 << 9) | (0 << 8) |
++ (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), /* setup */
++
++ 712, /* inv_gain */
++ 21, /* time_stabiliz */
++
++ 0, /* alpha_level */
++ 118, /* thlock */
++
++ 0, /* wbd_inv */
++ 2867, /* wbd_ref */
++ 0, /* wbd_sel */
++ 2, /* wbd_alpha */
++
++ 0, /* agc1_max */
++ 0, /* agc1_min */
++ 39718, /* agc2_max */
++ 9930, /* agc2_min */
++ 0, /* agc1_pt1 */
++ 0, /* agc1_pt2 */
++ 0, /* agc1_pt3 */
++ 0, /* agc1_slope1 */
++ 0, /* agc1_slope2 */
++ 0, /* agc2_pt1 */
++ 128, /* agc2_pt2 */
++ 29, /* agc2_slope1 */
++ 29, /* agc2_slope2 */
++
++ 17, /* alpha_mant */
++ 27, /* alpha_exp */
++ 23, /* beta_mant */
++ 51, /* beta_exp */
++
++ 1, /* perform_agc_softsplit */
++};
++
++/* PLL Configuration for COFDM BW_MHz = 8.00 with external clock = 30.00 */
++static struct dibx000_bandwidth_config xc3028_bw_config = {
++ 60000, 30000, /* internal, sampling */
++ 1, 8, 3, 1, 0, /* pll_cfg: prediv, ratio, range, reset, bypass */
++ 0, 0, 1, 1, 0, /* misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc,
++ modulo */
++ (3 << 14) | (1 << 12) | (524 << 0), /* sad_cfg: refsel, sel, freq_15k */
++ (1 << 25) | 5816102, /* ifreq = 5.200000 MHz */
++ 20452225, /* timf */
++ 30000000, /* xtal_hz */
++};
++
++static struct dib7000p_config stk7700ph_dib7700_xc3028_config = {
++ .output_mpeg2_in_188_bytes = 1,
++ .tuner_is_baseband = 1,
++
++ .agc_config_count = 1,
++ .agc = &xc3028_agc_config,
++ .bw = &xc3028_bw_config,
++
++ .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
++ .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
++ .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
++};
++
++static int stk7700ph_xc3028_callback(void *ptr, int command, int arg)
++{
++ struct dvb_usb_adapter *adap = ptr;
++
++ switch (command) {
++ case XC2028_TUNER_RESET:
++ /* Send the tuner in then out of reset */
++ dib7000p_set_gpio(adap->fe, 8, 0, 0); msleep(10);
++ dib7000p_set_gpio(adap->fe, 8, 0, 1);
++ break;
++ case XC2028_RESET_CLK:
++ break;
++ default:
++ err("%s: unknown command %d, arg %d\n", __func__,
++ command, arg);
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static struct xc2028_ctrl stk7700ph_xc3028_ctrl = {
++ .fname = XC2028_DEFAULT_FIRMWARE,
++ .max_len = 64,
++ .demod = XC3028_FE_DIBCOM52,
++};
++
++static struct xc2028_config stk7700ph_xc3028_config = {
++ .i2c_addr = 0x61,
++ .callback = stk7700ph_xc3028_callback,
++ .ctrl = &stk7700ph_xc3028_ctrl,
++};
++
++static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap)
++{
++ struct usb_device_descriptor *desc = &adap->dev->udev->descriptor;
++
++ if (desc->idVendor == USB_VID_PINNACLE &&
++ desc->idProduct == USB_PID_PINNACLE_EXPRESSCARD_320CX)
++ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
++ else
++ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
++ msleep(20);
++ dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
++ dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
++ dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
++ dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
++ msleep(10);
++ dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
++ msleep(20);
++ dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
++ msleep(10);
++
++ dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
++ &stk7700ph_dib7700_xc3028_config);
++
++ adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
++ &stk7700ph_dib7700_xc3028_config);
++
++ return adap->fe == NULL ? -ENODEV : 0;
++}
++
++static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap)
++{
++ struct i2c_adapter *tun_i2c;
++
++ tun_i2c = dib7000p_get_i2c_master(adap->fe,
++ DIBX000_I2C_INTERFACE_TUNER, 1);
++
++ stk7700ph_xc3028_config.i2c_adap = tun_i2c;
++ stk7700ph_xc3028_config.video_dev = adap;
++
++ return dvb_attach(xc2028_attach, adap->fe, &stk7700ph_xc3028_config)
++ == NULL ? -ENODEV : 0;
++}
++
+ #define DEFAULT_RC_INTERVAL 150
+
+ static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
+
++/* Number of keypresses to ignore before start repeating */
++#define RC_REPEAT_DELAY 2
++
+ static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+ {
+ u8 key[4];
+@@ -314,18 +461,67 @@ static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+ err("RC Query Failed");
+ return -1;
+ }
++
++ /* losing half of KEY_0 events from Philipps rc5 remotes.. */
+ if (key[0]==0 && key[1]==0 && key[2]==0 && key[3]==0) return 0;
+- if (key[3-1]!=st->rc_toggle) {
++
++ /* info("%d: %2X %2X %2X %2X",dvb_usb_dib0700_ir_proto,(int)key[3-2],(int)key[3-3],(int)key[3-1],(int)key[3]); */
++
++ dib0700_rc_setup(d); /* reset ir sensor data to prevent false events */
++
++ switch (dvb_usb_dib0700_ir_proto) {
++ case 0: {
++ /* NEC protocol sends repeat code as 0 0 0 FF */
++ if ((key[3-2] == 0x00) && (key[3-3] == 0x00) &&
++ (key[3] == 0xFF)) {
++ st->rc_counter++;
++ if (st->rc_counter > RC_REPEAT_DELAY) {
++ *event = d->last_event;
++ *state = REMOTE_KEY_PRESSED;
++ st->rc_counter = RC_REPEAT_DELAY;
++ }
++ return 0;
++ }
+ for (i=0;i<d->props.rc_key_map_size; i++) {
+ if (keymap[i].custom == key[3-2] && keymap[i].data == key[3-3]) {
++ st->rc_counter = 0;
++ *event = keymap[i].event;
++ *state = REMOTE_KEY_PRESSED;
++ d->last_event = keymap[i].event;
++ return 0;
++ }
++ }
++ break;
++ }
++ default: {
++ /* RC-5 protocol changes toggle bit on new keypress */
++ for (i = 0; i < d->props.rc_key_map_size; i++) {
++ if (keymap[i].custom == key[3-2] && keymap[i].data == key[3-3]) {
++ if (d->last_event == keymap[i].event &&
++ key[3-1] == st->rc_toggle) {
++ st->rc_counter++;
++ /* prevents unwanted double hits */
++ if (st->rc_counter > RC_REPEAT_DELAY) {
++ *event = d->last_event;
++ *state = REMOTE_KEY_PRESSED;
++ st->rc_counter = RC_REPEAT_DELAY;
++ }
++
++ return 0;
++ }
++ st->rc_counter = 0;
+ *event = keymap[i].event;
+ *state = REMOTE_KEY_PRESSED;
+- st->rc_toggle=key[3-1];
++ st->rc_toggle = key[3-1];
++ d->last_event = keymap[i].event;
+ return 0;
+ }
+ }
+- err("Unknown remote controller key : %2X %2X",(int)key[3-2],(int)key[3-3]);
++ break;
+ }
++ }
++ err("Unknown remote controller key: %2X %2X %2X %2X", (int) key[3-2], (int) key[3-3], (int) key[3-1], (int) key[3]);
++ d->last_event = 0;
+ return 0;
+ }
+
+@@ -794,6 +990,10 @@ static struct dib7000p_config dib7070p_dib7000p_config = {
+ /* STK7070P */
+ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
+ {
++ if (adap->dev->udev->descriptor.idVendor == USB_VID_PINNACLE &&
++ adap->dev->udev->descriptor.idProduct == USB_PID_PINNACLE_PCTV72E)
++ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
++ else
+ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+ msleep(10);
+ dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
+@@ -808,9 +1008,11 @@ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
+ msleep(10);
+ dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+
+- dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, &dib7070p_dib7000p_config);
++ dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
++ &dib7070p_dib7000p_config);
+
+- adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &dib7070p_dib7000p_config);
++ adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
++ &dib7070p_dib7000p_config);
+ return adap->fe == NULL ? -ENODEV : 0;
+ }
+
+@@ -878,34 +1080,43 @@ static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap)
+ /* DVB-USB and USB stuff follows */
+ struct usb_device_id dib0700_usb_id_table[] = {
+ /* 0 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) },
+- { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P_PC) },
+-
+- { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) },
+- { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) },
+- { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) },
++ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P_PC) },
++ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) },
++ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) },
++ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) },
+ /* 5 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) },
+- { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500) },
+- { USB_DEVICE(USB_VID_UNIWILL, USB_PID_UNIWILL_STK7700P) },
+- { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P) },
+- { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) },
++ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500) },
++ { USB_DEVICE(USB_VID_UNIWILL, USB_PID_UNIWILL_STK7700P) },
++ { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P) },
++ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) },
+ /* 10 */{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) },
+- { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV2000E) },
+- { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY) },
+- { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK) },
+- { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700D) },
++ { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV2000E) },
++ { USB_DEVICE(USB_VID_TERRATEC,
++ USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY) },
++ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK) },
++ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700D) },
+ /* 15 */{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7070P) },
+- { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV_DVB_T_FLASH) },
+- { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7070PD) },
+- { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T) },
+- { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500_PC) },
++ { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV_DVB_T_FLASH) },
++ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7070PD) },
++ { USB_DEVICE(USB_VID_PINNACLE,
++ USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T) },
++ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500_PC) },
+ /* 20 */{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_EXPRESS) },
+- { USB_DEVICE(USB_VID_GIGABYTE, USB_PID_GIGABYTE_U7000) },
+- { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14BR) },
+- { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3000) },
+- { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3100) },
+-/* 25 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_3) },
+- { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_MYTV_T) },
+- { 0 } /* Terminating entry */
++ { USB_DEVICE(USB_VID_GIGABYTE, USB_PID_GIGABYTE_U7000) },
++ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14BR) },
++ { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3000) },
++ { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3100) },
++/* 25 */{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_3) },
++ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_MYTV_T) },
++ { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_HT_USB_XE) },
++ { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_EXPRESSCARD_320CX) },
++ { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV72E) },
++/* 30 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73E) },
++ { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_EC372S) },
++ { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_HT_EXPRESS) },
++ { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_XXS) },
++ { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P_2) },
++ { 0 } /* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
+
+@@ -969,7 +1180,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
+ { NULL },
+ },
+ { "Leadtek Winfast DTV Dongle (STK7700P based)",
+- { &dib0700_usb_id_table[8], NULL },
++ { &dib0700_usb_id_table[8], &dib0700_usb_id_table[34] },
+ { NULL },
+ },
+ { "AVerMedia AVerTV DVB-T Express",
+@@ -1069,12 +1280,16 @@ struct dvb_usb_device_properties dib0700_devices[] = {
+ },
+ },
+
+- .num_device_descs = 1,
++ .num_device_descs = 2,
+ .devices = {
+ { "ASUS My Cinema U3000 Mini DVBT Tuner",
+ { &dib0700_usb_id_table[23], NULL },
+ { NULL },
+ },
++ { "Yuan EC372S",
++ { &dib0700_usb_id_table[31], NULL },
++ { NULL },
++ }
+ }
+ }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+
+@@ -1090,7 +1305,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
+ },
+ },
+
+- .num_device_descs = 6,
++ .num_device_descs = 9,
+ .devices = {
+ { "DiBcom STK7070P reference design",
+ { &dib0700_usb_id_table[15], NULL },
+@@ -1116,6 +1331,18 @@ struct dvb_usb_device_properties dib0700_devices[] = {
+ { &dib0700_usb_id_table[26], NULL },
+ { NULL },
+ },
++ { "Pinnacle PCTV 72e",
++ { &dib0700_usb_id_table[29], NULL },
++ { NULL },
++ },
++ { "Pinnacle PCTV 73e",
++ { &dib0700_usb_id_table[30], NULL },
++ { NULL },
++ },
++ { "Terratec Cinergy T USB XXS",
++ { &dib0700_usb_id_table[33], NULL },
++ { NULL },
++ },
+ },
+
+ .rc_interval = DEFAULT_RC_INTERVAL,
+@@ -1155,6 +1382,40 @@ struct dvb_usb_device_properties dib0700_devices[] = {
+ { NULL },
+ }
+ }
++ }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
++
++ .num_adapters = 1,
++ .adapter = {
++ {
++ .frontend_attach = stk7700ph_frontend_attach,
++ .tuner_attach = stk7700ph_tuner_attach,
++
++ DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
++
++ .size_of_priv = sizeof(struct
++ dib0700_adapter_state),
++ },
++ },
++
++ .num_device_descs = 3,
++ .devices = {
++ { "Terratec Cinergy HT USB XE",
++ { &dib0700_usb_id_table[27], NULL },
++ { NULL },
++ },
++ { "Pinnacle Expresscard 320cx",
++ { &dib0700_usb_id_table[28], NULL },
++ { NULL },
++ },
++ { "Terratec Cinergy HT Express",
++ { &dib0700_usb_id_table[32], NULL },
++ { NULL },
++ },
++ },
++ .rc_interval = DEFAULT_RC_INTERVAL,
++ .rc_key_map = dib0700_rc_keys,
++ .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys),
++ .rc_query = dib0700_rc_query
+ },
+ };
+
+diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c
+index 043cada..eeef50b 100644
+--- a/drivers/media/dvb/dvb-usb/dibusb-mb.c
++++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c
+@@ -14,6 +14,8 @@
+ */
+ #include "dibusb.h"
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ static int dib3000mb_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+ {
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+@@ -107,10 +109,14 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties;
+ static int dibusb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+ {
+- if (dvb_usb_device_init(intf,&dibusb1_1_properties,THIS_MODULE,NULL) == 0 ||
+- dvb_usb_device_init(intf,&dibusb1_1_an2235_properties,THIS_MODULE,NULL) == 0 ||
+- dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE,NULL) == 0 ||
+- dvb_usb_device_init(intf,&artec_t1_usb2_properties,THIS_MODULE,NULL) == 0)
++ if (0 == dvb_usb_device_init(intf, &dibusb1_1_properties,
++ THIS_MODULE, NULL, adapter_nr) ||
++ 0 == dvb_usb_device_init(intf, &dibusb1_1_an2235_properties,
++ THIS_MODULE, NULL, adapter_nr) ||
++ 0 == dvb_usb_device_init(intf, &dibusb2_0b_properties,
++ THIS_MODULE, NULL, adapter_nr) ||
++ 0 == dvb_usb_device_init(intf, &artec_t1_usb2_properties,
++ THIS_MODULE, NULL, adapter_nr))
+ return 0;
+
+ return -EINVAL;
+diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c
+index e7ea3e7..059cec9 100644
+--- a/drivers/media/dvb/dvb-usb/dibusb-mc.c
++++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c
+@@ -14,13 +14,16 @@
+ */
+ #include "dibusb.h"
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ /* USB Driver stuff */
+ static struct dvb_usb_device_properties dibusb_mc_properties;
+
+ static int dibusb_mc_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+ {
+- return dvb_usb_device_init(intf,&dibusb_mc_properties,THIS_MODULE,NULL);
++ return dvb_usb_device_init(intf, &dibusb_mc_properties, THIS_MODULE,
++ NULL, adapter_nr);
+ }
+
+ /* do not change the order of the ID table */
+diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
+index 3acbda4..b545cf3 100644
+--- a/drivers/media/dvb/dvb-usb/digitv.c
++++ b/drivers/media/dvb/dvb-usb/digitv.c
+@@ -20,6 +20,9 @@
+ static int dvb_usb_digitv_debug;
+ module_param_named(debug,dvb_usb_digitv_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
++
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define deb_rc(args...) dprintk(dvb_usb_digitv_debug,0x01,args)
+
+ static int digitv_ctrl_msg(struct dvb_usb_device *d,
+@@ -256,8 +259,9 @@ static int digitv_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+ {
+ struct dvb_usb_device *d;
+- int ret;
+- if ((ret = dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE,&d)) == 0) {
++ int ret = dvb_usb_device_init(intf, &digitv_properties, THIS_MODULE, &d,
++ adapter_nr);
++ if (ret == 0) {
+ u8 b[4] = { 0 };
+
+ if (d != NULL) { /* do that only when the firmware is loaded */
+diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
+index d86cf9b..81a6cbf 100644
+--- a/drivers/media/dvb/dvb-usb/dtt200u.c
++++ b/drivers/media/dvb/dvb-usb/dtt200u.c
+@@ -18,6 +18,8 @@ int dvb_usb_dtt200u_debug;
+ module_param_named(debug,dvb_usb_dtt200u_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB_DEBUG_STATUS);
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ static int dtt200u_power_ctrl(struct dvb_usb_device *d, int onoff)
+ {
+ u8 b = SET_INIT;
+@@ -101,11 +103,16 @@ static struct dvb_usb_device_properties wt220u_miglia_properties;
+ static int dtt200u_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+ {
+- if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE,NULL) == 0 ||
+- dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE,NULL) == 0 ||
+- dvb_usb_device_init(intf,&wt220u_fc_properties,THIS_MODULE,NULL) == 0 ||
+- dvb_usb_device_init(intf,&wt220u_zl0353_properties,THIS_MODULE,NULL) == 0 ||
+- dvb_usb_device_init(intf,&wt220u_miglia_properties,THIS_MODULE,NULL) == 0)
++ if (0 == dvb_usb_device_init(intf, &dtt200u_properties,
++ THIS_MODULE, NULL, adapter_nr) ||
++ 0 == dvb_usb_device_init(intf, &wt220u_properties,
++ THIS_MODULE, NULL, adapter_nr) ||
++ 0 == dvb_usb_device_init(intf, &wt220u_fc_properties,
++ THIS_MODULE, NULL, adapter_nr) ||
++ 0 == dvb_usb_device_init(intf, &wt220u_zl0353_properties,
++ THIS_MODULE, NULL, adapter_nr) ||
++ 0 == dvb_usb_device_init(intf, &wt220u_miglia_properties,
++ THIS_MODULE, NULL, adapter_nr))
+ return 0;
+
+ return -ENODEV;
+diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-common.h b/drivers/media/dvb/dvb-usb/dvb-usb-common.h
+index 35ab68f..6b7b2a8 100644
+--- a/drivers/media/dvb/dvb-usb/dvb-usb-common.h
++++ b/drivers/media/dvb/dvb-usb/dvb-usb-common.h
+@@ -40,7 +40,8 @@ extern int dvb_usb_adapter_stream_exit(struct dvb_usb_adapter *adap);
+ extern int dvb_usb_i2c_init(struct dvb_usb_device *);
+ extern int dvb_usb_i2c_exit(struct dvb_usb_device *);
+
+-extern int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap);
++extern int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap,
++ short *adapter_nums);
+ extern int dvb_usb_adapter_dvb_exit(struct dvb_usb_adapter *adap);
+ extern int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap);
+ extern int dvb_usb_adapter_frontend_exit(struct dvb_usb_adapter *adap);
+diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
+index 4561a67..ce8cd0c 100644
+--- a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
++++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
+@@ -77,12 +77,13 @@ static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+ return dvb_usb_ctrl_feed(dvbdmxfeed,0);
+ }
+
+-int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap)
++int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums)
+ {
+- int ret;
++ int ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name,
++ adap->dev->owner, &adap->dev->udev->dev,
++ adapter_nums);
+
+- if ((ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name,
+- adap->dev->owner, &adap->dev->udev->dev)) < 0) {
++ if (ret < 0) {
+ deb_info("dvb_register_adapter failed: error %d", ret);
+ goto err;
+ }
+diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+index aa4844e..34245d1 100644
+--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
++++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+@@ -40,14 +40,15 @@
+ #define USB_VID_MSI 0x0db0
+ #define USB_VID_OPERA1 0x695c
+ #define USB_VID_PINNACLE 0x2304
++#define USB_VID_TECHNOTREND 0x0b48
+ #define USB_VID_TERRATEC 0x0ccd
+ #define USB_VID_VISIONPLUS 0x13d3
+ #define USB_VID_TWINHAN 0x1822
+ #define USB_VID_ULTIMA_ELECTRONIC 0x05d8
+ #define USB_VID_UNIWILL 0x1584
+ #define USB_VID_WIDEVIEW 0x14aa
+-/* dom : pour gigabyte u7000 */
+ #define USB_VID_GIGABYTE 0x1044
++#define USB_VID_YUAN 0x1164
+
+
+ /* Product IDs */
+@@ -134,10 +135,17 @@
+ #define USB_PID_AVERMEDIA_EXPRESS 0xb568
+ #define USB_PID_AVERMEDIA_VOLAR 0xa807
+ #define USB_PID_AVERMEDIA_VOLAR_2 0xb808
++#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006
+ #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
++#define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058
++#define USB_PID_TERRATEC_CINERGY_HT_EXPRESS 0x0060
++#define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078
++#define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e
+ #define USB_PID_PINNACLE_PCTV2000E 0x022c
+ #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228
+ #define USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T 0x0229
++#define USB_PID_PINNACLE_PCTV72E 0x0236
++#define USB_PID_PINNACLE_PCTV73E 0x0237
+ #define USB_PID_PCTV_200E 0x020e
+ #define USB_PID_PCTV_400E 0x020f
+ #define USB_PID_PCTV_450E 0x0222
+@@ -172,6 +180,7 @@
+ #define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025
+ #define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026
+ #define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00
++#define USB_PID_WINFAST_DTV_DONGLE_STK7700P_2 0x6f01
+ #define USB_PID_GENPIX_8PSK_REV_1_COLD 0x0200
+ #define USB_PID_GENPIX_8PSK_REV_1_WARM 0x0201
+ #define USB_PID_GENPIX_8PSK_REV_2 0x0202
+@@ -183,9 +192,9 @@
+ #define USB_PID_OPERA1_WARM 0x3829
+ #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD 0x0514
+ #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM 0x0513
+-/* dom pour gigabyte u7000 */
+ #define USB_PID_GIGABYTE_U7000 0x7001
+ #define USB_PID_ASUS_U3000 0x171f
+ #define USB_PID_ASUS_U3100 0x173f
++#define USB_PID_YUAN_EC372S 0x1edc
+
+ #endif
+diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
+index cdd717c..e331db8 100644
+--- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c
++++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
+@@ -26,7 +26,7 @@ static int dvb_usb_force_pid_filter_usage;
+ module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage, int, 0444);
+ MODULE_PARM_DESC(force_pid_filter_usage, "force all dvb-usb-devices to use a PID filter, if any (default: 0).");
+
+-static int dvb_usb_adapter_init(struct dvb_usb_device *d)
++static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
+ {
+ struct dvb_usb_adapter *adap;
+ int ret,n;
+@@ -72,7 +72,7 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d)
+ }
+
+ if ((ret = dvb_usb_adapter_stream_init(adap)) ||
+- (ret = dvb_usb_adapter_dvb_init(adap)) ||
++ (ret = dvb_usb_adapter_dvb_init(adap, adapter_nrs)) ||
+ (ret = dvb_usb_adapter_frontend_init(adap))) {
+ return ret;
+ }
+@@ -122,7 +122,7 @@ static int dvb_usb_exit(struct dvb_usb_device *d)
+ return 0;
+ }
+
+-static int dvb_usb_init(struct dvb_usb_device *d)
++static int dvb_usb_init(struct dvb_usb_device *d, short *adapter_nums)
+ {
+ int ret = 0;
+
+@@ -143,7 +143,7 @@ static int dvb_usb_init(struct dvb_usb_device *d)
+ dvb_usb_device_power_ctrl(d, 1);
+
+ if ((ret = dvb_usb_i2c_init(d)) ||
+- (ret = dvb_usb_adapter_init(d))) {
++ (ret = dvb_usb_adapter_init(d, adapter_nums))) {
+ dvb_usb_exit(d);
+ return ret;
+ }
+@@ -213,8 +213,10 @@ int dvb_usb_device_power_ctrl(struct dvb_usb_device *d, int onoff)
+ /*
+ * USB
+ */
+-int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_device_properties
+- *props, struct module *owner,struct dvb_usb_device **du)
++int dvb_usb_device_init(struct usb_interface *intf,
++ struct dvb_usb_device_properties *props,
++ struct module *owner, struct dvb_usb_device **du,
++ short *adapter_nums)
+ {
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct dvb_usb_device *d = NULL;
+@@ -254,7 +256,7 @@ int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_device_proper
+ if (du != NULL)
+ *du = d;
+
+- ret = dvb_usb_init(d);
++ ret = dvb_usb_init(d, adapter_nums);
+
+ if (ret == 0)
+ info("%s successfully initialized and connected.",desc->name);
+diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
+index d1b3c7b..b1de0f7 100644
+--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
++++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
+@@ -372,7 +372,10 @@ struct dvb_usb_device {
+ void *priv;
+ };
+
+-extern int dvb_usb_device_init(struct usb_interface *, struct dvb_usb_device_properties *, struct module *, struct dvb_usb_device **);
++extern int dvb_usb_device_init(struct usb_interface *,
++ struct dvb_usb_device_properties *,
++ struct module *, struct dvb_usb_device **,
++ short *adapter_nums);
+ extern void dvb_usb_device_exit(struct usb_interface *);
+
+ /* the generic read/write method for device control */
+diff --git a/drivers/media/dvb/dvb-usb/gl861.c b/drivers/media/dvb/dvb-usb/gl861.c
+index 6b99d9f..0a8ac64 100644
+--- a/drivers/media/dvb/dvb-usb/gl861.c
++++ b/drivers/media/dvb/dvb-usb/gl861.c
+@@ -16,6 +16,8 @@ static int dvb_usb_gl861_debug;
+ module_param_named(debug,dvb_usb_gl861_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
+ u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
+ {
+@@ -140,7 +142,9 @@ static int gl861_probe(struct usb_interface *intf,
+ if (intf->num_altsetting < 2)
+ return -ENODEV;
+
+- if ((ret = dvb_usb_device_init(intf, &gl861_properties, THIS_MODULE, &d)) == 0) {
++ ret = dvb_usb_device_init(intf, &gl861_properties, THIS_MODULE, &d,
++ adapter_nr);
++ if (ret == 0) {
+ alt = usb_altnum_to_altsetting(intf, 0);
+
+ if (alt == NULL) {
+diff --git a/drivers/media/dvb/dvb-usb/gp8psk-fe.c b/drivers/media/dvb/dvb-usb/gp8psk-fe.c
+index e37142d..262a858 100644
+--- a/drivers/media/dvb/dvb-usb/gp8psk-fe.c
++++ b/drivers/media/dvb/dvb-usb/gp8psk-fe.c
+@@ -152,7 +152,7 @@ static int gp8psk_fe_send_diseqc_msg (struct dvb_frontend* fe,
+ {
+ struct gp8psk_fe_state *st = fe->demodulator_priv;
+
+- deb_fe("%s\n",__FUNCTION__);
++ deb_fe("%s\n",__func__);
+
+ if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, m->msg[0], 0,
+ m->msg, m->msg_len)) {
+@@ -167,7 +167,7 @@ static int gp8psk_fe_send_diseqc_burst (struct dvb_frontend* fe,
+ struct gp8psk_fe_state *st = fe->demodulator_priv;
+ u8 cmd;
+
+- deb_fe("%s\n",__FUNCTION__);
++ deb_fe("%s\n",__func__);
+
+ /* These commands are certainly wrong */
+ cmd = (burst == SEC_MINI_A) ? 0x00 : 0x01;
+diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c
+index 83e8535..9a942af 100644
+--- a/drivers/media/dvb/dvb-usb/gp8psk.c
++++ b/drivers/media/dvb/dvb-usb/gp8psk.c
+@@ -22,6 +22,8 @@ int dvb_usb_gp8psk_debug;
+ module_param_named(debug,dvb_usb_gp8psk_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
+ {
+ int ret = 0,try = 0;
+@@ -190,7 +192,8 @@ static int gp8psk_usb_probe(struct usb_interface *intf,
+ {
+ int ret;
+ struct usb_device *udev = interface_to_usbdev(intf);
+- ret = dvb_usb_device_init(intf,&gp8psk_properties,THIS_MODULE,NULL);
++ ret = dvb_usb_device_init(intf, &gp8psk_properties,
++ THIS_MODULE, NULL, adapter_nr);
+ if (ret == 0) {
+ info("found Genpix USB device pID = %x (hex)",
+ le16_to_cpu(udev->descriptor.idProduct));
+diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c
+index a956bc5..a12e6f7 100644
+--- a/drivers/media/dvb/dvb-usb/m920x.c
++++ b/drivers/media/dvb/dvb-usb/m920x.c
+@@ -22,6 +22,8 @@ static int dvb_usb_m920x_debug;
+ module_param_named(debug,dvb_usb_m920x_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ static int m920x_set_filter(struct dvb_usb_device *d, int type, int idx, int pid);
+
+ static inline int m920x_read(struct usb_device *udev, u8 request, u16 value,
+@@ -477,7 +479,7 @@ static struct qt1010_config m920x_qt1010_config = {
+ /* Callbacks for DVB USB */
+ static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap)
+ {
+- deb("%s\n",__FUNCTION__);
++ deb("%s\n",__func__);
+
+ if ((adap->fe = dvb_attach(mt352_attach,
+ &m920x_mt352_config,
+@@ -489,7 +491,7 @@ static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap)
+
+ static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap)
+ {
+- deb("%s\n",__FUNCTION__);
++ deb("%s\n",__func__);
+
+ if ((adap->fe = dvb_attach(tda10046_attach,
+ &m920x_tda10046_08_config,
+@@ -501,7 +503,7 @@ static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap)
+
+ static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap)
+ {
+- deb("%s\n",__FUNCTION__);
++ deb("%s\n",__func__);
+
+ if ((adap->fe = dvb_attach(tda10046_attach,
+ &m920x_tda10046_0b_config,
+@@ -513,7 +515,7 @@ static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap)
+
+ static int m920x_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
+ {
+- deb("%s\n",__FUNCTION__);
++ deb("%s\n",__func__);
+
+ if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, &m920x_qt1010_config) == NULL)
+ return -ENODEV;
+@@ -523,7 +525,7 @@ static int m920x_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
+
+ static int m920x_tda8275_60_tuner_attach(struct dvb_usb_adapter *adap)
+ {
+- deb("%s\n",__FUNCTION__);
++ deb("%s\n",__func__);
+
+ if (dvb_attach(tda827x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, NULL) == NULL)
+ return -ENODEV;
+@@ -533,7 +535,7 @@ static int m920x_tda8275_60_tuner_attach(struct dvb_usb_adapter *adap)
+
+ static int m920x_tda8275_61_tuner_attach(struct dvb_usb_adapter *adap)
+ {
+- deb("%s\n",__FUNCTION__);
++ deb("%s\n",__func__);
+
+ if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL)
+ return -ENODEV;
+@@ -618,27 +620,31 @@ static int m920x_probe(struct usb_interface *intf,
+ * multi-tuner device
+ */
+
+- if ((ret = dvb_usb_device_init(intf, &megasky_properties,
+- THIS_MODULE, &d)) == 0) {
++ ret = dvb_usb_device_init(intf, &megasky_properties,
++ THIS_MODULE, &d, adapter_nr);
++ if (ret == 0) {
+ rc_init_seq = megasky_rc_init;
+ goto found;
+ }
+
+- if ((ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties,
+- THIS_MODULE, &d)) == 0) {
++ ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties,
++ THIS_MODULE, &d, adapter_nr);
++ if (ret == 0) {
+ /* No remote control, so no rc_init_seq */
+ goto found;
+ }
+
+ /* This configures both tuners on the TV Walker Twin */
+- if ((ret = dvb_usb_device_init(intf, &tvwalkertwin_properties,
+- THIS_MODULE, &d)) == 0) {
++ ret = dvb_usb_device_init(intf, &tvwalkertwin_properties,
++ THIS_MODULE, &d, adapter_nr);
++ if (ret == 0) {
+ rc_init_seq = tvwalkertwin_rc_init;
+ goto found;
+ }
+
+- if ((ret = dvb_usb_device_init(intf, &dposh_properties,
+- THIS_MODULE, &d)) == 0) {
++ ret = dvb_usb_device_init(intf, &dposh_properties,
++ THIS_MODULE, &d, adapter_nr);
++ if (ret == 0) {
+ /* Remote controller not supported yet. */
+ goto found;
+ }
+diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
+index badc468..07fb843 100644
+--- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c
++++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
+@@ -15,6 +15,8 @@ static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=rc,2=eeprom (|-able))." DVB_USB_DEBUG_STATUS);
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define deb_rc(args...) dprintk(debug,0x01,args)
+ #define deb_ee(args...) dprintk(debug,0x02,args)
+
+@@ -142,7 +144,8 @@ static struct dvb_usb_device_properties nova_t_properties;
+ static int nova_t_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+ {
+- return dvb_usb_device_init(intf,&nova_t_properties,THIS_MODULE,NULL);
++ return dvb_usb_device_init(intf, &nova_t_properties,
++ THIS_MODULE, NULL, adapter_nr);
+ }
+
+ /* do not change the order of the ID table */
+diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c
+index 302cc67..7e32d11 100644
+--- a/drivers/media/dvb/dvb-usb/opera1.c
++++ b/drivers/media/dvb/dvb-usb/opera1.c
+@@ -46,6 +46,9 @@ MODULE_PARM_DESC(debug,
+ "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64 (or-able))."
+ DVB_USB_DEBUG_STATUS);
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
++
+ static int opera1_xilinx_rw(struct usb_device *dev, u8 request, u16 value,
+ u8 * data, u16 len, int flags)
+ {
+@@ -243,7 +246,7 @@ static struct stv0299_config opera1_stv0299_config = {
+ .mclk = 88000000UL,
+ .invert = 1,
+ .skip_reinit = 0,
+- .lock_output = STV0229_LOCKOUTPUT_0,
++ .lock_output = STV0299_LOCKOUTPUT_0,
+ .volt13_op0_op1 = STV0299_VOLT13_OP0,
+ .inittab = opera1_inittab,
+ .set_symbol_rate = opera1_stv0299_set_symbol_rate,
+@@ -548,7 +551,8 @@ static int opera1_probe(struct usb_interface *intf,
+ return -EINVAL;
+ }
+
+- if (dvb_usb_device_init(intf, &opera1_properties, THIS_MODULE, NULL) != 0)
++ if (0 != dvb_usb_device_init(intf, &opera1_properties,
++ THIS_MODULE, NULL, adapter_nr))
+ return -EINVAL;
+ return 0;
+ }
+diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c
+index 3b9da9c..20ca9d9 100644
+--- a/drivers/media/dvb/dvb-usb/ttusb2.c
++++ b/drivers/media/dvb/dvb-usb/ttusb2.c
+@@ -37,6 +37,8 @@ static int dvb_usb_ttusb2_debug;
+ module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS);
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ struct ttusb2_state {
+ u8 id;
+ };
+@@ -145,6 +147,7 @@ static struct tda10086_config tda10086_config = {
+ .demod_address = 0x0e,
+ .invert = 0,
+ .diseqc_tone = 1,
++ .xtal_freq = TDA10086_XTAL_16M,
+ };
+
+ static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap)
+@@ -176,17 +179,25 @@ static int ttusb2_tuner_attach(struct dvb_usb_adapter *adap)
+
+ /* DVB USB Driver stuff */
+ static struct dvb_usb_device_properties ttusb2_properties;
++static struct dvb_usb_device_properties ttusb2_properties_s2400;
+
+ static int ttusb2_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+ {
+- return dvb_usb_device_init(intf,&ttusb2_properties,THIS_MODULE,NULL);
++ if (0 == dvb_usb_device_init(intf, &ttusb2_properties,
++ THIS_MODULE, NULL, adapter_nr) ||
++ 0 == dvb_usb_device_init(intf, &ttusb2_properties_s2400,
++ THIS_MODULE, NULL, adapter_nr))
++ return 0;
++ return -ENODEV;
+ }
+
+ static struct usb_device_id ttusb2_table [] = {
+- { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_400E) },
+- { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_450E) },
+- {} /* Terminating entry */
++ { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_400E) },
++ { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_450E) },
++ { USB_DEVICE(USB_VID_TECHNOTREND,
++ USB_PID_TECHNOTREND_CONNECT_S2400) },
++ {} /* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE (usb, ttusb2_table);
+
+@@ -242,6 +253,54 @@ static struct dvb_usb_device_properties ttusb2_properties = {
+ }
+ };
+
++static struct dvb_usb_device_properties ttusb2_properties_s2400 = {
++ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
++
++ .usb_ctrl = CYPRESS_FX2,
++ .firmware = "dvb-usb-tt-s2400-01.fw",
++
++ .size_of_priv = sizeof(struct ttusb2_state),
++
++ .num_adapters = 1,
++ .adapter = {
++ {
++ .streaming_ctrl = NULL,
++
++ .frontend_attach = ttusb2_frontend_attach,
++ .tuner_attach = ttusb2_tuner_attach,
++
++ /* parameter for the MPEG2-data transfer */
++ .stream = {
++ .type = USB_ISOC,
++ .count = 5,
++ .endpoint = 0x02,
++ .u = {
++ .isoc = {
++ .framesperurb = 4,
++ .framesize = 940,
++ .interval = 1,
++ }
++ }
++ }
++ }
++ },
++
++ .power_ctrl = ttusb2_power_ctrl,
++ .identify_state = ttusb2_identify_state,
++
++ .i2c_algo = &ttusb2_i2c_algo,
++
++ .generic_bulk_ctrl_endpoint = 0x01,
++
++ .num_device_descs = 1,
++ .devices = {
++ { "Technotrend TT-connect S-2400",
++ { &ttusb2_table[2], NULL },
++ { NULL },
++ },
++ }
++};
++
+ static struct usb_driver ttusb2_driver = {
+ .name = "dvb_usb_ttusb2",
+ .probe = ttusb2_probe,
+diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c
+index 0dcab3d..9e7653b 100644
+--- a/drivers/media/dvb/dvb-usb/umt-010.c
++++ b/drivers/media/dvb/dvb-usb/umt-010.c
+@@ -13,6 +13,8 @@
+
+ #include "mt352.h"
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ static int umt_mt352_demod_init(struct dvb_frontend *fe)
+ {
+ static u8 mt352_clock_config[] = { 0x89, 0xb8, 0x2d };
+@@ -75,7 +77,8 @@ static struct dvb_usb_device_properties umt_properties;
+ static int umt_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+ {
+- if (dvb_usb_device_init(intf,&umt_properties,THIS_MODULE,NULL) == 0)
++ if (0 == dvb_usb_device_init(intf, &umt_properties,
++ THIS_MODULE, NULL, adapter_nr))
+ return 0;
+ return -EINVAL;
+ }
+diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/dvb/dvb-usb/vp702x-fe.c
+index c3fdc7c..ccc7e44 100644
+--- a/drivers/media/dvb/dvb-usb/vp702x-fe.c
++++ b/drivers/media/dvb/dvb-usb/vp702x-fe.c
+@@ -67,7 +67,7 @@ static int vp702x_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
+ {
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ vp702x_fe_refresh_state(st);
+- deb_fe("%s\n",__FUNCTION__);
++ deb_fe("%s\n",__func__);
+
+ if (st->lock == 0)
+ *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER;
+@@ -121,7 +121,7 @@ static int vp702x_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
+
+ static int vp702x_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+ {
+- deb_fe("%s\n",__FUNCTION__);
++ deb_fe("%s\n",__func__);
+ tune->min_delay_ms = 2000;
+ return 0;
+ }
+@@ -183,21 +183,21 @@ static int vp702x_fe_set_frontend(struct dvb_frontend* fe,
+ static int vp702x_fe_init(struct dvb_frontend *fe)
+ {
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+- deb_fe("%s\n",__FUNCTION__);
++ deb_fe("%s\n",__func__);
+ vp702x_usb_in_op(st->d, RESET_TUNER, 0, 0, NULL, 0);
+ return 0;
+ }
+
+ static int vp702x_fe_sleep(struct dvb_frontend *fe)
+ {
+- deb_fe("%s\n",__FUNCTION__);
++ deb_fe("%s\n",__func__);
+ return 0;
+ }
+
+ static int vp702x_fe_get_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *fep)
+ {
+- deb_fe("%s\n",__FUNCTION__);
++ deb_fe("%s\n",__func__);
+ return 0;
+ }
+
+@@ -208,7 +208,7 @@ static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
+ u8 cmd[8],ibuf[10];
+ memset(cmd,0,8);
+
+- deb_fe("%s\n",__FUNCTION__);
++ deb_fe("%s\n",__func__);
+
+ if (m->msg_len > 4)
+ return -EINVAL;
+@@ -230,7 +230,7 @@ static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
+
+ static int vp702x_fe_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
+ {
+- deb_fe("%s\n",__FUNCTION__);
++ deb_fe("%s\n",__func__);
+ return 0;
+ }
+
+@@ -238,7 +238,7 @@ static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+ {
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ u8 ibuf[10];
+- deb_fe("%s\n",__FUNCTION__);
++ deb_fe("%s\n",__func__);
+
+ st->tone_mode = tone;
+
+@@ -263,7 +263,7 @@ static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t
+ {
+ struct vp702x_fe_state *st = fe->demodulator_priv;
+ u8 ibuf[10];
+- deb_fe("%s\n",__FUNCTION__);
++ deb_fe("%s\n",__func__);
+
+ st->voltage = voltage;
+
+diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c
+index e553c13..986fff9 100644
+--- a/drivers/media/dvb/dvb-usb/vp702x.c
++++ b/drivers/media/dvb/dvb-usb/vp702x.c
+@@ -21,6 +21,8 @@ int dvb_usb_vp702x_debug;
+ module_param_named(debug,dvb_usb_vp702x_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ struct vp702x_state {
+ int pid_filter_count;
+ int pid_filter_can_bypass;
+@@ -238,7 +240,8 @@ static struct dvb_usb_device_properties vp702x_properties;
+ static int vp702x_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+ {
+- return dvb_usb_device_init(intf,&vp702x_properties,THIS_MODULE,NULL);
++ return dvb_usb_device_init(intf, &vp702x_properties,
++ THIS_MODULE, NULL, adapter_nr);
+ }
+
+ static struct usb_device_id vp702x_usb_table [] = {
+diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c
+index c172bab..acb3455 100644
+--- a/drivers/media/dvb/dvb-usb/vp7045.c
++++ b/drivers/media/dvb/dvb-usb/vp7045.c
+@@ -18,6 +18,9 @@
+ static int dvb_usb_vp7045_debug;
+ module_param_named(debug,dvb_usb_vp7045_debug, int, 0644);
+ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
++
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define deb_info(args...) dprintk(dvb_usb_vp7045_debug,0x01,args)
+ #define deb_xfer(args...) dprintk(dvb_usb_vp7045_debug,0x02,args)
+ #define deb_rc(args...) dprintk(dvb_usb_vp7045_debug,0x04,args)
+@@ -219,7 +222,8 @@ static struct dvb_usb_device_properties vp7045_properties;
+ static int vp7045_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+ {
+- return dvb_usb_device_init(intf,&vp7045_properties,THIS_MODULE,NULL);
++ return dvb_usb_device_init(intf, &vp7045_properties,
++ THIS_MODULE, NULL, adapter_nr);
+ }
+
+ static struct usb_device_id vp7045_usb_table [] = {
+diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
+index 9ad86ce..f5fceb3 100644
+--- a/drivers/media/dvb/frontends/Kconfig
++++ b/drivers/media/dvb/frontends/Kconfig
+@@ -188,6 +188,14 @@ config DVB_DIB7000P
+ A DVB-T tuner module. Designed for mobile usage. Say Y when you want
+ to support this frontend.
+
++config DVB_TDA10048
++ tristate "Philips TDA10048HN based"
++ depends on DVB_CORE && I2C
++ default m if DVB_FE_CUSTOMISE
++ select FW_LOADER
++ help
++ A DVB-T tuner module. Say Y when you want to support this frontend.
++
+ comment "DVB-C (cable) frontends"
+ depends on DVB_CORE
+
+@@ -291,6 +299,22 @@ config DVB_S5H1409
+ An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
+ to support this frontend.
+
++config DVB_AU8522
++ tristate "Auvitek AU8522 based"
++ depends on DVB_CORE && I2C
++ default m if DVB_FE_CUSTOMISE
++ help
++ An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
++ to support this frontend.
++
++config DVB_S5H1411
++ tristate "Samsung S5H1411 based"
++ depends on DVB_CORE && I2C
++ default m if DVB_FE_CUSTOMISE
++ help
++ An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
++ to support this frontend.
++
+ comment "Tuners/PLL support"
+ depends on DVB_CORE
+
+@@ -369,6 +393,11 @@ config DVB_TUNER_XC5000
+ This device is only used inside a SiP called togther with a
+ demodulator for now.
+
++config DVB_TUNER_ITD1000
++ tristate "Integrant ITD1000 Zero IF tuner for DVB-S/DSS"
++ depends on DVB_CORE && I2C
++ default m if DVB_FE_CUSTOMISE
++
+ comment "Miscellaneous devices"
+ depends on DVB_CORE
+
+@@ -379,6 +408,13 @@ config DVB_LNBP21
+ help
+ An SEC control chip.
+
++config DVB_ISL6405
++ tristate "ISL6405 SEC controller"
++ depends on DVB_CORE && I2C
++ default m if DVB_FE_CUSTOMISE
++ help
++ An SEC control chip.
++
+ config DVB_ISL6421
+ tristate "ISL6421 SEC controller"
+ depends on DVB_CORE && I2C
+diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
+index 16bd107..9747c73 100644
+--- a/drivers/media/dvb/frontends/Makefile
++++ b/drivers/media/dvb/frontends/Makefile
+@@ -38,6 +38,7 @@ obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
+ obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
+ obj-$(CONFIG_DVB_CX24123) += cx24123.o
+ obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
++obj-$(CONFIG_DVB_ISL6405) += isl6405.o
+ obj-$(CONFIG_DVB_ISL6421) += isl6421.o
+ obj-$(CONFIG_DVB_TDA10086) += tda10086.o
+ obj-$(CONFIG_DVB_TDA826X) += tda826x.o
+@@ -51,3 +52,7 @@ obj-$(CONFIG_DVB_TUA6100) += tua6100.o
+ obj-$(CONFIG_DVB_TUNER_MT2131) += mt2131.o
+ obj-$(CONFIG_DVB_S5H1409) += s5h1409.o
+ obj-$(CONFIG_DVB_TUNER_XC5000) += xc5000.o
++obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o
++obj-$(CONFIG_DVB_AU8522) += au8522.o
++obj-$(CONFIG_DVB_TDA10048) += tda10048.o
++obj-$(CONFIG_DVB_S5H1411) += s5h1411.o
+diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c
+new file mode 100644
+index 0000000..084a280
+--- /dev/null
++++ b/drivers/media/dvb/frontends/au8522.c
+@@ -0,0 +1,692 @@
++/*
++ Auvitek AU8522 QAM/8VSB demodulator driver
++
++ Copyright (C) 2008 Steven Toth <stoth at hauppauge.com>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++*/
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include "dvb_frontend.h"
++#include "dvb-pll.h"
++#include "au8522.h"
++
++struct au8522_state {
++
++ struct i2c_adapter *i2c;
++
++ /* configuration settings */
++ const struct au8522_config *config;
++
++ struct dvb_frontend frontend;
++
++ u32 current_frequency;
++ fe_modulation_t current_modulation;
++
++};
++
++static int debug;
++
++#define dprintk(arg...) do { \
++ if (debug) \
++ printk(arg); \
++ } while (0)
++
++/* 16 bit registers, 8 bit values */
++static int au8522_writereg(struct au8522_state *state, u16 reg, u8 data)
++{
++ int ret;
++ u8 buf [] = { reg >> 8, reg & 0xff, data };
++
++ struct i2c_msg msg = { .addr = state->config->demod_address,
++ .flags = 0, .buf = buf, .len = 3 };
++
++ ret = i2c_transfer(state->i2c, &msg, 1);
++
++ if (ret != 1)
++ printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
++ "ret == %i)\n", __func__, reg, data, ret);
++
++ return (ret != 1) ? -1 : 0;
++}
++
++static u8 au8522_readreg(struct au8522_state *state, u16 reg)
++{
++ int ret;
++ u8 b0 [] = { reg >> 8, reg & 0xff };
++ u8 b1 [] = { 0 };
++
++ struct i2c_msg msg [] = {
++ { .addr = state->config->demod_address, .flags = 0,
++ .buf = b0, .len = 2 },
++ { .addr = state->config->demod_address, .flags = I2C_M_RD,
++ .buf = b1, .len = 1 } };
++
++ ret = i2c_transfer(state->i2c, msg, 2);
++
++ if (ret != 2)
++ printk(KERN_ERR "%s: readreg error (ret == %i)\n",
++ __func__, ret);
++ return b1[0];
++}
++
++static int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
++{
++ struct au8522_state *state = fe->demodulator_priv;
++
++ dprintk("%s(%d)\n", __func__, enable);
++
++ if (enable)
++ return au8522_writereg(state, 0x106, 1);
++ else
++ return au8522_writereg(state, 0x106, 0);
++}
++
++struct mse2snr_tab {
++ u16 val;
++ u16 data;
++};
++
++/* VSB SNR lookup table */
++static struct mse2snr_tab vsb_mse2snr_tab[] = {
++ { 0, 270 },
++ { 2, 250 },
++ { 3, 240 },
++ { 5, 230 },
++ { 7, 220 },
++ { 9, 210 },
++ { 12, 200 },
++ { 13, 195 },
++ { 15, 190 },
++ { 17, 185 },
++ { 19, 180 },
++ { 21, 175 },
++ { 24, 170 },
++ { 27, 165 },
++ { 31, 160 },
++ { 32, 158 },
++ { 33, 156 },
++ { 36, 152 },
++ { 37, 150 },
++ { 39, 148 },
++ { 40, 146 },
++ { 41, 144 },
++ { 43, 142 },
++ { 44, 140 },
++ { 48, 135 },
++ { 50, 130 },
++ { 43, 142 },
++ { 53, 125 },
++ { 56, 120 },
++ { 256, 115 },
++};
++
++/* QAM64 SNR lookup table */
++static struct mse2snr_tab qam64_mse2snr_tab[] = {
++ { 15, 0 },
++ { 16, 290 },
++ { 17, 288 },
++ { 18, 286 },
++ { 19, 284 },
++ { 20, 282 },
++ { 21, 281 },
++ { 22, 279 },
++ { 23, 277 },
++ { 24, 275 },
++ { 25, 273 },
++ { 26, 271 },
++ { 27, 269 },
++ { 28, 268 },
++ { 29, 266 },
++ { 30, 264 },
++ { 31, 262 },
++ { 32, 260 },
++ { 33, 259 },
++ { 34, 258 },
++ { 35, 256 },
++ { 36, 255 },
++ { 37, 254 },
++ { 38, 252 },
++ { 39, 251 },
++ { 40, 250 },
++ { 41, 249 },
++ { 42, 248 },
++ { 43, 246 },
++ { 44, 245 },
++ { 45, 244 },
++ { 46, 242 },
++ { 47, 241 },
++ { 48, 240 },
++ { 50, 239 },
++ { 51, 238 },
++ { 53, 237 },
++ { 54, 236 },
++ { 56, 235 },
++ { 57, 234 },
++ { 59, 233 },
++ { 60, 232 },
++ { 62, 231 },
++ { 63, 230 },
++ { 65, 229 },
++ { 67, 228 },
++ { 68, 227 },
++ { 70, 226 },
++ { 71, 225 },
++ { 73, 224 },
++ { 74, 223 },
++ { 76, 222 },
++ { 78, 221 },
++ { 80, 220 },
++ { 82, 219 },
++ { 85, 218 },
++ { 88, 217 },
++ { 90, 216 },
++ { 92, 215 },
++ { 93, 214 },
++ { 94, 212 },
++ { 95, 211 },
++ { 97, 210 },
++ { 99, 209 },
++ { 101, 208 },
++ { 102, 207 },
++ { 104, 206 },
++ { 107, 205 },
++ { 111, 204 },
++ { 114, 203 },
++ { 118, 202 },
++ { 122, 201 },
++ { 125, 200 },
++ { 128, 199 },
++ { 130, 198 },
++ { 132, 197 },
++ { 256, 190 },
++};
++
++/* QAM256 SNR lookup table */
++static struct mse2snr_tab qam256_mse2snr_tab[] = {
++ { 16, 0 },
++ { 17, 400 },
++ { 18, 398 },
++ { 19, 396 },
++ { 20, 394 },
++ { 21, 392 },
++ { 22, 390 },
++ { 23, 388 },
++ { 24, 386 },
++ { 25, 384 },
++ { 26, 382 },
++ { 27, 380 },
++ { 28, 379 },
++ { 29, 378 },
++ { 30, 377 },
++ { 31, 376 },
++ { 32, 375 },
++ { 33, 374 },
++ { 34, 373 },
++ { 35, 372 },
++ { 36, 371 },
++ { 37, 370 },
++ { 38, 362 },
++ { 39, 354 },
++ { 40, 346 },
++ { 41, 338 },
++ { 42, 330 },
++ { 43, 328 },
++ { 44, 326 },
++ { 45, 324 },
++ { 46, 322 },
++ { 47, 320 },
++ { 48, 319 },
++ { 49, 318 },
++ { 50, 317 },
++ { 51, 316 },
++ { 52, 315 },
++ { 53, 314 },
++ { 54, 313 },
++ { 55, 312 },
++ { 56, 311 },
++ { 57, 310 },
++ { 58, 308 },
++ { 59, 306 },
++ { 60, 304 },
++ { 61, 302 },
++ { 62, 300 },
++ { 63, 298 },
++ { 65, 295 },
++ { 68, 294 },
++ { 70, 293 },
++ { 73, 292 },
++ { 76, 291 },
++ { 78, 290 },
++ { 79, 289 },
++ { 81, 288 },
++ { 82, 287 },
++ { 83, 286 },
++ { 84, 285 },
++ { 85, 284 },
++ { 86, 283 },
++ { 88, 282 },
++ { 89, 281 },
++ { 256, 280 },
++};
++
++static int au8522_mse2snr_lookup(struct mse2snr_tab *tab, int sz, int mse,
++ u16 *snr)
++{
++ int i, ret = -EINVAL;
++ dprintk("%s()\n", __func__);
++
++ for (i = 0; i < sz; i++) {
++ if (mse < tab[i].val) {
++ *snr = tab[i].data;
++ ret = 0;
++ break;
++ }
++ }
++ dprintk("%s() snr=%d\n", __func__, *snr);
++ return ret;
++}
++
++/* VSB Modulation table */
++static struct {
++ u16 reg;
++ u16 data;
++} VSB_mod_tab[] = {
++ { 0x8090, 0x84 },
++ { 0x4092, 0x11 },
++ { 0x2005, 0x00 },
++ { 0x8091, 0x80 },
++ { 0x80a3, 0x0c },
++ { 0x80a4, 0xe8 },
++ { 0x8081, 0xc4 },
++ { 0x80a5, 0x40 },
++ { 0x80a7, 0x40 },
++ { 0x80a6, 0x67 },
++ { 0x8262, 0x20 },
++ { 0x821c, 0x30 },
++ { 0x80d8, 0x1a },
++ { 0x8227, 0xa0 },
++ { 0x8121, 0xff },
++ { 0x80a8, 0xf0 },
++ { 0x80a9, 0x05 },
++ { 0x80aa, 0x77 },
++ { 0x80ab, 0xf0 },
++ { 0x80ac, 0x05 },
++ { 0x80ad, 0x77 },
++ { 0x80ae, 0x41 },
++ { 0x80af, 0x66 },
++ { 0x821b, 0xcc },
++ { 0x821d, 0x80 },
++ { 0x80b5, 0xfb },
++ { 0x80b6, 0x8e },
++ { 0x80b7, 0x39 },
++ { 0x80a4, 0xe8 },
++ { 0x8231, 0x13 },
++};
++
++/* QAM Modulation table */
++static struct {
++ u16 reg;
++ u16 data;
++} QAM_mod_tab[] = {
++ { 0x80a3, 0x09 },
++ { 0x80a4, 0x00 },
++ { 0x8081, 0xc4 },
++ { 0x80a5, 0x40 },
++ { 0x80b5, 0xfb },
++ { 0x80b6, 0x8e },
++ { 0x80b7, 0x39 },
++ { 0x80aa, 0x77 },
++ { 0x80ad, 0x77 },
++ { 0x80a6, 0x67 },
++ { 0x8262, 0x20 },
++ { 0x821c, 0x30 },
++ { 0x80b8, 0x3e },
++ { 0x80b9, 0xf0 },
++ { 0x80ba, 0x01 },
++ { 0x80bb, 0x18 },
++ { 0x80bc, 0x50 },
++ { 0x80bd, 0x00 },
++ { 0x80be, 0xea },
++ { 0x80bf, 0xef },
++ { 0x80c0, 0xfc },
++ { 0x80c1, 0xbd },
++ { 0x80c2, 0x1f },
++ { 0x80c3, 0xfc },
++ { 0x80c4, 0xdd },
++ { 0x80c5, 0xaf },
++ { 0x80c6, 0x00 },
++ { 0x80c7, 0x38 },
++ { 0x80c8, 0x30 },
++ { 0x80c9, 0x05 },
++ { 0x80ca, 0x4a },
++ { 0x80cb, 0xd0 },
++ { 0x80cc, 0x01 },
++ { 0x80cd, 0xd9 },
++ { 0x80ce, 0x6f },
++ { 0x80cf, 0xf9 },
++ { 0x80d0, 0x70 },
++ { 0x80d1, 0xdf },
++ { 0x80d2, 0xf7 },
++ { 0x80d3, 0xc2 },
++ { 0x80d4, 0xdf },
++ { 0x80d5, 0x02 },
++ { 0x80d6, 0x9a },
++ { 0x80d7, 0xd0 },
++ { 0x8250, 0x0d },
++ { 0x8251, 0xcd },
++ { 0x8252, 0xe0 },
++ { 0x8253, 0x05 },
++ { 0x8254, 0xa7 },
++ { 0x8255, 0xff },
++ { 0x8256, 0xed },
++ { 0x8257, 0x5b },
++ { 0x8258, 0xae },
++ { 0x8259, 0xe6 },
++ { 0x825a, 0x3d },
++ { 0x825b, 0x0f },
++ { 0x825c, 0x0d },
++ { 0x825d, 0xea },
++ { 0x825e, 0xf2 },
++ { 0x825f, 0x51 },
++ { 0x8260, 0xf5 },
++ { 0x8261, 0x06 },
++ { 0x821a, 0x00 },
++ { 0x8546, 0x40 },
++ { 0x8210, 0x26 },
++ { 0x8211, 0xf6 },
++ { 0x8212, 0x84 },
++ { 0x8213, 0x02 },
++ { 0x8502, 0x01 },
++ { 0x8121, 0x04 },
++ { 0x8122, 0x04 },
++ { 0x852e, 0x10 },
++ { 0x80a4, 0xca },
++ { 0x80a7, 0x40 },
++ { 0x8526, 0x01 },
++};
++
++static int au8522_enable_modulation(struct dvb_frontend *fe,
++ fe_modulation_t m)
++{
++ struct au8522_state *state = fe->demodulator_priv;
++ int i;
++
++ dprintk("%s(0x%08x)\n", __func__, m);
++
++ switch (m) {
++ case VSB_8:
++ dprintk("%s() VSB_8\n", __func__);
++ for (i = 0; i < ARRAY_SIZE(VSB_mod_tab); i++)
++ au8522_writereg(state,
++ VSB_mod_tab[i].reg,
++ VSB_mod_tab[i].data);
++ break;
++ case QAM_64:
++ case QAM_256:
++ dprintk("%s() QAM 64/256\n", __func__);
++ for (i = 0; i < ARRAY_SIZE(QAM_mod_tab); i++)
++ au8522_writereg(state,
++ QAM_mod_tab[i].reg,
++ QAM_mod_tab[i].data);
++ break;
++ default:
++ dprintk("%s() Invalid modulation\n", __func__);
++ return -EINVAL;
++ }
++
++ state->current_modulation = m;
++
++ return 0;
++}
++
++/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
++static int au8522_set_frontend(struct dvb_frontend *fe,
++ struct dvb_frontend_parameters *p)
++{
++ struct au8522_state *state = fe->demodulator_priv;
++
++ dprintk("%s(frequency=%d)\n", __func__, p->frequency);
++
++ state->current_frequency = p->frequency;
++
++ au8522_enable_modulation(fe, p->u.vsb.modulation);
++
++ /* Allow the demod to settle */
++ msleep(100);
++
++ if (fe->ops.tuner_ops.set_params) {
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
++ fe->ops.tuner_ops.set_params(fe, p);
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 0);
++ }
++
++ return 0;
++}
++
++/* Reset the demod hardware and reset all of the configuration registers
++ to a default state. */
++static int au8522_init(struct dvb_frontend *fe)
++{
++ struct au8522_state *state = fe->demodulator_priv;
++ dprintk("%s()\n", __func__);
++
++ au8522_writereg(state, 0xa4, 1 << 5);
++
++ au8522_i2c_gate_ctrl(fe, 1);
++
++ return 0;
++}
++
++static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status)
++{
++ struct au8522_state *state = fe->demodulator_priv;
++ u8 reg;
++ u32 tuner_status = 0;
++
++ *status = 0;
++
++ if (state->current_modulation == VSB_8) {
++ dprintk("%s() Checking VSB_8\n", __func__);
++ reg = au8522_readreg(state, 0x4088);
++ if (reg & 0x01)
++ *status |= FE_HAS_VITERBI;
++ if (reg & 0x02)
++ *status |= FE_HAS_LOCK | FE_HAS_SYNC;
++ } else {
++ dprintk("%s() Checking QAM\n", __func__);
++ reg = au8522_readreg(state, 0x4541);
++ if (reg & 0x80)
++ *status |= FE_HAS_VITERBI;
++ if (reg & 0x20)
++ *status |= FE_HAS_LOCK | FE_HAS_SYNC;
++ }
++
++ switch (state->config->status_mode) {
++ case AU8522_DEMODLOCKING:
++ dprintk("%s() DEMODLOCKING\n", __func__);
++ if (*status & FE_HAS_VITERBI)
++ *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
++ break;
++ case AU8522_TUNERLOCKING:
++ /* Get the tuner status */
++ dprintk("%s() TUNERLOCKING\n", __func__);
++ if (fe->ops.tuner_ops.get_status) {
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
++
++ fe->ops.tuner_ops.get_status(fe, &tuner_status);
++
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 0);
++ }
++ if (tuner_status)
++ *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
++ break;
++ }
++
++ dprintk("%s() status 0x%08x\n", __func__, *status);
++
++ return 0;
++}
++
++static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr)
++{
++ struct au8522_state *state = fe->demodulator_priv;
++ int ret = -EINVAL;
++
++ dprintk("%s()\n", __func__);
++
++ if (state->current_modulation == QAM_256)
++ ret = au8522_mse2snr_lookup(qam256_mse2snr_tab,
++ ARRAY_SIZE(qam256_mse2snr_tab),
++ au8522_readreg(state, 0x4522),
++ snr);
++ else if (state->current_modulation == QAM_64)
++ ret = au8522_mse2snr_lookup(qam64_mse2snr_tab,
++ ARRAY_SIZE(qam64_mse2snr_tab),
++ au8522_readreg(state, 0x4522),
++ snr);
++ else /* VSB_8 */
++ ret = au8522_mse2snr_lookup(vsb_mse2snr_tab,
++ ARRAY_SIZE(vsb_mse2snr_tab),
++ au8522_readreg(state, 0x4311),
++ snr);
++
++ return ret;
++}
++
++static int au8522_read_signal_strength(struct dvb_frontend *fe,
++ u16 *signal_strength)
++{
++ return au8522_read_snr(fe, signal_strength);
++}
++
++static int au8522_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
++{
++ struct au8522_state *state = fe->demodulator_priv;
++
++ if (state->current_modulation == VSB_8)
++ *ucblocks = au8522_readreg(state, 0x4087);
++ else
++ *ucblocks = au8522_readreg(state, 0x4543);
++
++ return 0;
++}
++
++static int au8522_read_ber(struct dvb_frontend *fe, u32 *ber)
++{
++ return au8522_read_ucblocks(fe, ber);
++}
++
++static int au8522_get_frontend(struct dvb_frontend *fe,
++ struct dvb_frontend_parameters *p)
++{
++ struct au8522_state *state = fe->demodulator_priv;
++
++ p->frequency = state->current_frequency;
++ p->u.vsb.modulation = state->current_modulation;
++
++ return 0;
++}
++
++static int au8522_get_tune_settings(struct dvb_frontend *fe,
++ struct dvb_frontend_tune_settings *tune)
++{
++ tune->min_delay_ms = 1000;
++ return 0;
++}
++
++static void au8522_release(struct dvb_frontend *fe)
++{
++ struct au8522_state *state = fe->demodulator_priv;
++ kfree(state);
++}
++
++static struct dvb_frontend_ops au8522_ops;
++
++struct dvb_frontend *au8522_attach(const struct au8522_config *config,
++ struct i2c_adapter *i2c)
++{
++ struct au8522_state *state = NULL;
++
++ /* allocate memory for the internal state */
++ state = kmalloc(sizeof(struct au8522_state), GFP_KERNEL);
++ if (state == NULL)
++ goto error;
++
++ /* setup the state */
++ state->config = config;
++ state->i2c = i2c;
++ /* create dvb_frontend */
++ memcpy(&state->frontend.ops, &au8522_ops,
++ sizeof(struct dvb_frontend_ops));
++ state->frontend.demodulator_priv = state;
++
++ if (au8522_init(&state->frontend) != 0) {
++ printk(KERN_ERR "%s: Failed to initialize correctly\n",
++ __func__);
++ goto error;
++ }
++
++ /* Note: Leaving the I2C gate open here. */
++ au8522_i2c_gate_ctrl(&state->frontend, 1);
++
++ return &state->frontend;
++
++error:
++ kfree(state);
++ return NULL;
++}
++EXPORT_SYMBOL(au8522_attach);
++
++static struct dvb_frontend_ops au8522_ops = {
++
++ .info = {
++ .name = "Auvitek AU8522 QAM/8VSB Frontend",
++ .type = FE_ATSC,
++ .frequency_min = 54000000,
++ .frequency_max = 858000000,
++ .frequency_stepsize = 62500,
++ .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
++ },
++
++ .init = au8522_init,
++ .i2c_gate_ctrl = au8522_i2c_gate_ctrl,
++ .set_frontend = au8522_set_frontend,
++ .get_frontend = au8522_get_frontend,
++ .get_tune_settings = au8522_get_tune_settings,
++ .read_status = au8522_read_status,
++ .read_ber = au8522_read_ber,
++ .read_signal_strength = au8522_read_signal_strength,
++ .read_snr = au8522_read_snr,
++ .read_ucblocks = au8522_read_ucblocks,
++ .release = au8522_release,
++};
++
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "Enable verbose debug messages");
++
++MODULE_DESCRIPTION("Auvitek AU8522 QAM-B/ATSC Demodulator driver");
++MODULE_AUTHOR("Steven Toth");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/dvb/frontends/au8522.h b/drivers/media/dvb/frontends/au8522.h
+new file mode 100644
+index 0000000..d7affa3
+--- /dev/null
++++ b/drivers/media/dvb/frontends/au8522.h
+@@ -0,0 +1,56 @@
++/*
++ Auvitek AU8522 QAM/8VSB demodulator driver
++
++ Copyright (C) 2008 Steven Toth <stoth at hauppauge.com>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++*/
++
++#ifndef __AU8522_H__
++#define __AU8522_H__
++
++#include <linux/dvb/frontend.h>
++
++struct au8522_config {
++ /* the demodulator's i2c address */
++ u8 demod_address;
++
++ /* Return lock status based on tuner lock, or demod lock */
++#define AU8522_TUNERLOCKING 0
++#define AU8522_DEMODLOCKING 1
++ u8 status_mode;
++};
++
++#if defined(CONFIG_DVB_AU8522) || \
++ (defined(CONFIG_DVB_AU8522_MODULE) && defined(MODULE))
++extern struct dvb_frontend *au8522_attach(const struct au8522_config *config,
++ struct i2c_adapter *i2c);
++#else
++static inline
++struct dvb_frontend *au8522_attach(const struct au8522_config *config,
++ struct i2c_adapter *i2c)
++{
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++ return NULL;
++}
++#endif /* CONFIG_DVB_AU8522 */
++
++#endif /* __AU8522_H__ */
++
++/*
++ * Local variables:
++ * c-basic-offset: 8
++ */
+diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c
+index a913f49..d268e65 100644
+--- a/drivers/media/dvb/frontends/bcm3510.c
++++ b/drivers/media/dvb/frontends/bcm3510.c
+@@ -91,7 +91,7 @@ static int bcm3510_writebytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8
+ if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+
+ deb_info("%s: i2c write error (addr %02x, reg %02x, err == %i)\n",
+- __FUNCTION__, state->config->demod_address, reg, err);
++ __func__, state->config->demod_address, reg, err);
+ return -EREMOTEIO;
+ }
+
+@@ -110,7 +110,7 @@ static int bcm3510_readbytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 l
+
+ if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
+ deb_info("%s: i2c read error (addr %02x, reg %02x, err == %i)\n",
+- __FUNCTION__, state->config->demod_address, reg, err);
++ __func__, state->config->demod_address, reg, err);
+ return -EREMOTEIO;
+ }
+ deb_i2c("i2c rd %02x: ",reg);
+diff --git a/drivers/media/dvb/frontends/bcm3510.h b/drivers/media/dvb/frontends/bcm3510.h
+index 7e4f95e..f4575c0 100644
+--- a/drivers/media/dvb/frontends/bcm3510.h
++++ b/drivers/media/dvb/frontends/bcm3510.h
+@@ -41,7 +41,7 @@ extern struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
+ static inline struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
+ struct i2c_adapter* i2c)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_BCM3510
+diff --git a/drivers/media/dvb/frontends/bsbe1.h b/drivers/media/dvb/frontends/bsbe1.h
+index d8f6573..5e431eb 100644
+--- a/drivers/media/dvb/frontends/bsbe1.h
++++ b/drivers/media/dvb/frontends/bsbe1.h
+@@ -1,5 +1,5 @@
+ /*
+- * bsbe1.h - ALPS BSBE1 tuner support (moved from av7110.c)
++ * bsbe1.h - ALPS BSBE1 tuner support
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+@@ -26,44 +26,24 @@
+ #define BSBE1_H
+
+ static u8 alps_bsbe1_inittab[] = {
+- 0x01, 0x15,
+- 0x02, 0x30,
+- 0x03, 0x00,
++ 0x01, 0x15, /* XTAL = 4MHz, VCO = 352 MHz */
++ 0x02, 0x30, /* MCLK = 88 MHz */
++ 0x03, 0x00, /* ACR output 0 */
+ 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
+- 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
+- 0x06, 0x40, /* DAC not used, set to high impendance mode */
+- 0x07, 0x00, /* DAC LSB */
++ 0x05, 0x05, /* I2CT = 0, SCLT = 1, SDAT = 1 */
++ 0x06, 0x00, /* DAC output 0 */
+ 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */
+ 0x09, 0x00, /* FIFO */
+- 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
+- 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
+- 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
+- 0x10, 0x3f, // AGC2 0x3d
+- 0x11, 0x84,
+- 0x12, 0xb9,
+- 0x15, 0xc9, // lock detector threshold
+- 0x16, 0x00,
+- 0x17, 0x00,
+- 0x18, 0x00,
+- 0x19, 0x00,
+- 0x1a, 0x00,
+- 0x1f, 0x50,
+- 0x20, 0x00,
+- 0x21, 0x00,
+- 0x22, 0x00,
+- 0x23, 0x00,
+- 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
+- 0x29, 0x1e, // 1/2 threshold
+- 0x2a, 0x14, // 2/3 threshold
+- 0x2b, 0x0f, // 3/4 threshold
+- 0x2c, 0x09, // 5/6 threshold
+- 0x2d, 0x05, // 7/8 threshold
+- 0x2e, 0x01,
+- 0x31, 0x1f, // test all FECs
+- 0x32, 0x19, // viterbi and synchro search
+- 0x33, 0xfc, // rs control
+- 0x34, 0x93, // error control
+- 0x0f, 0x92,
++ 0x0c, 0x51, /* OP1/OP0 normal, val = 1 (LNB power on) */
++ 0x0d, 0x82, /* DC offset compensation = on, beta_agc1 = 2 */
++ 0x0f, 0x92, /* AGC1R */
++ 0x10, 0x34, /* AGC2O */
++ 0x11, 0x84, /* TLSR */
++ 0x12, 0xb9, /* CFD */
++ 0x15, 0xc9, /* lock detector threshold */
++ 0x28, 0x00, /* out imp: normal, type: parallel, FEC mode: QPSK */
++ 0x33, 0xfc, /* RS control */
++ 0x34, 0x93, /* count viterbi bit errors per 2E18 bytes */
+ 0xff, 0xff
+ };
+
+@@ -100,11 +80,11 @@ static int alps_bsbe1_tuner_set_params(struct dvb_frontend* fe, struct dvb_front
+ if ((params->frequency < 950000) || (params->frequency > 2150000))
+ return -EINVAL;
+
+- div = (params->frequency + (125 - 1)) / 125; // round correctly
++ div = params->frequency / 1000;
+ data[0] = (div >> 8) & 0x7f;
+ data[1] = div & 0xff;
+- data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
+- data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4;
++ data[2] = 0x80 | ((div & 0x18000) >> 10) | 0x1;
++ data[3] = 0xe0;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+diff --git a/drivers/media/dvb/frontends/bsru6.h b/drivers/media/dvb/frontends/bsru6.h
+index e231cd8..45a6dfd 100644
+--- a/drivers/media/dvb/frontends/bsru6.h
++++ b/drivers/media/dvb/frontends/bsru6.h
+@@ -133,7 +133,7 @@ static struct stv0299_config alps_bsru6_config = {
+ .mclk = 88000000UL,
+ .invert = 1,
+ .skip_reinit = 0,
+- .lock_output = STV0229_LOCKOUTPUT_1,
++ .lock_output = STV0299_LOCKOUTPUT_1,
+ .volt13_op0_op1 = STV0299_VOLT13_OP1,
+ .min_delay_ms = 100,
+ .set_symbol_rate = alps_bsru6_set_symbol_rate,
+diff --git a/drivers/media/dvb/frontends/cx22700.c b/drivers/media/dvb/frontends/cx22700.c
+index 11a4968..ace5cb1 100644
+--- a/drivers/media/dvb/frontends/cx22700.c
++++ b/drivers/media/dvb/frontends/cx22700.c
+@@ -73,13 +73,13 @@ static int cx22700_writereg (struct cx22700_state* state, u8 reg, u8 data)
+ u8 buf [] = { reg, data };
+ struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ ret = i2c_transfer (state->i2c, &msg, 1);
+
+ if (ret != 1)
+ printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+- __FUNCTION__, reg, data, ret);
++ __func__, reg, data, ret);
+
+ return (ret != 1) ? -1 : 0;
+ }
+@@ -92,7 +92,7 @@ static int cx22700_readreg (struct cx22700_state* state, u8 reg)
+ struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
+ { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ ret = i2c_transfer (state->i2c, msg, 2);
+
+@@ -105,7 +105,7 @@ static int cx22700_set_inversion (struct cx22700_state* state, int inversion)
+ {
+ u8 val;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ switch (inversion) {
+ case INVERSION_AUTO:
+@@ -127,7 +127,7 @@ static int cx22700_set_tps (struct cx22700_state *state, struct dvb_ofdm_paramet
+ static const u8 fec_tab [6] = { 0, 1, 2, 0, 3, 4 };
+ u8 val;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ if (p->code_rate_HP < FEC_1_2 || p->code_rate_HP > FEC_7_8)
+ return -EINVAL;
+@@ -191,7 +191,7 @@ static int cx22700_get_tps (struct cx22700_state* state, struct dvb_ofdm_paramet
+ FEC_5_6, FEC_7_8 };
+ u8 val;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ if (!(cx22700_readreg(state, 0x07) & 0x20)) /* tps valid? */
+ return -EAGAIN;
+diff --git a/drivers/media/dvb/frontends/cx22700.h b/drivers/media/dvb/frontends/cx22700.h
+index 7ac3369..4757a93 100644
+--- a/drivers/media/dvb/frontends/cx22700.h
++++ b/drivers/media/dvb/frontends/cx22700.h
+@@ -38,7 +38,7 @@ extern struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
+ static inline struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
+ struct i2c_adapter* i2c)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_CX22700
+diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb/frontends/cx22702.c
+index 1dc164d..cc1db4e 100644
+--- a/drivers/media/dvb/frontends/cx22702.c
++++ b/drivers/media/dvb/frontends/cx22702.c
+@@ -48,7 +48,7 @@ struct cx22702_state {
+ u8 prevUCBlocks;
+ };
+
+-static int debug = 0;
++static int debug;
+ #define dprintk if (debug) printk
+
+ /* Register values to initialise the demod */
+@@ -90,7 +90,7 @@ static int cx22702_writereg (struct cx22702_state* state, u8 reg, u8 data)
+
+ if (ret != 1)
+ printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+- __FUNCTION__, reg, data, ret);
++ __func__, reg, data, ret);
+
+ return (ret != 1) ? -1 : 0;
+ }
+@@ -108,7 +108,7 @@ static u8 cx22702_readreg (struct cx22702_state* state, u8 reg)
+ ret = i2c_transfer(state->i2c, msg, 2);
+
+ if (ret != 2)
+- printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
++ printk("%s: readreg error (ret == %i)\n", __func__, ret);
+
+ return b1[0];
+ }
+@@ -195,7 +195,7 @@ static int cx22702_get_tps (struct cx22702_state *state, struct dvb_ofdm_paramet
+ static int cx22702_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+ {
+ struct cx22702_state* state = fe->demodulator_priv;
+- dprintk ("%s(%d)\n", __FUNCTION__, enable);
++ dprintk ("%s(%d)\n", __func__, enable);
+ if (enable)
+ return cx22702_writereg (state, 0x0D, cx22702_readreg(state, 0x0D) & 0xfe);
+ else
+@@ -228,7 +228,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
+ cx22702_writereg(state, 0x0C, cx22702_readreg(state, 0x0C) &0xcf );
+ break;
+ default:
+- dprintk ("%s: invalid bandwidth\n",__FUNCTION__);
++ dprintk ("%s: invalid bandwidth\n",__func__);
+ return -EINVAL;
+ }
+
+@@ -250,7 +250,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
+ cx22702_writereg(state, 0x0B, cx22702_readreg(state, 0x0B) & 0xfc );
+ cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40 );
+ cx22702_writereg(state, 0x00, 0x01); /* Begin aquisition */
+- dprintk("%s: Autodetecting\n",__FUNCTION__);
++ dprintk("%s: Autodetecting\n",__func__);
+ return 0;
+ }
+
+@@ -261,7 +261,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
+ case QAM_16: val = (val&0xe7)|0x08; break;
+ case QAM_64: val = (val&0xe7)|0x10; break;
+ default:
+- dprintk ("%s: invalid constellation\n",__FUNCTION__);
++ dprintk ("%s: invalid constellation\n",__func__);
+ return -EINVAL;
+ }
+ switch(p->u.ofdm.hierarchy_information) {
+@@ -270,7 +270,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
+ case HIERARCHY_2: val = (val&0xf8)|2; break;
+ case HIERARCHY_4: val = (val&0xf8)|3; break;
+ default:
+- dprintk ("%s: invalid hierarchy\n",__FUNCTION__);
++ dprintk ("%s: invalid hierarchy\n",__func__);
+ return -EINVAL;
+ }
+ cx22702_writereg (state, 0x06, val);
+@@ -284,7 +284,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
+ case FEC_5_6: val = (val&0xc7)|0x18; break;
+ case FEC_7_8: val = (val&0xc7)|0x20; break;
+ default:
+- dprintk ("%s: invalid code_rate_HP\n",__FUNCTION__);
++ dprintk ("%s: invalid code_rate_HP\n",__func__);
+ return -EINVAL;
+ }
+ switch(p->u.ofdm.code_rate_LP) {
+@@ -295,7 +295,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
+ case FEC_5_6: val = (val&0xf8)|3; break;
+ case FEC_7_8: val = (val&0xf8)|4; break;
+ default:
+- dprintk ("%s: invalid code_rate_LP\n",__FUNCTION__);
++ dprintk ("%s: invalid code_rate_LP\n",__func__);
+ return -EINVAL;
+ }
+ cx22702_writereg (state, 0x07, val);
+@@ -307,14 +307,14 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
+ case GUARD_INTERVAL_1_8: val = (val&0xf3)|0x08; break;
+ case GUARD_INTERVAL_1_4: val = (val&0xf3)|0x0c; break;
+ default:
+- dprintk ("%s: invalid guard_interval\n",__FUNCTION__);
++ dprintk ("%s: invalid guard_interval\n",__func__);
+ return -EINVAL;
+ }
+ switch(p->u.ofdm.transmission_mode) {
+ case TRANSMISSION_MODE_2K: val = (val&0xfc); break;
+ case TRANSMISSION_MODE_8K: val = (val&0xfc)|1; break;
+ default:
+- dprintk ("%s: invalid transmission_mode\n",__FUNCTION__);
++ dprintk ("%s: invalid transmission_mode\n",__func__);
+ return -EINVAL;
+ }
+ cx22702_writereg(state, 0x08, val);
+@@ -360,7 +360,7 @@ static int cx22702_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ reg23 = cx22702_readreg (state, 0x23);
+
+ dprintk ("%s: status demod=0x%02x agc=0x%02x\n"
+- ,__FUNCTION__,reg0A,reg23);
++ ,__func__,reg0A,reg23);
+
+ if(reg0A & 0x10) {
+ *status |= FE_HAS_LOCK;
+diff --git a/drivers/media/dvb/frontends/cx22702.h b/drivers/media/dvb/frontends/cx22702.h
+index 9cd64da..8af766a 100644
+--- a/drivers/media/dvb/frontends/cx22702.h
++++ b/drivers/media/dvb/frontends/cx22702.h
+@@ -48,7 +48,7 @@ extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
+ static inline struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
+ struct i2c_adapter* i2c)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_CX22702
+diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c
+index b03d828..87ae29d 100644
+--- a/drivers/media/dvb/frontends/cx24110.c
++++ b/drivers/media/dvb/frontends/cx24110.c
+@@ -121,7 +121,7 @@ static int cx24110_writereg (struct cx24110_state* state, int reg, int data)
+
+ if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+ dprintk ("%s: writereg error (err == %i, reg == 0x%02x,"
+- " data == 0x%02x)\n", __FUNCTION__, err, reg, data);
++ " data == 0x%02x)\n", __func__, err, reg, data);
+ return -EREMOTEIO;
+ }
+
+@@ -247,7 +247,7 @@ static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate)
+ static const u32 bands[]={5000000UL,15000000UL,90999000UL/2};
+ int i;
+
+- dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate);
++ dprintk("cx24110 debug: entering %s(%d)\n",__func__,srate);
+ if (srate>90999000UL/2)
+ srate=90999000UL/2;
+ if (srate<500000)
+@@ -358,7 +358,7 @@ static int cx24110_initfe(struct dvb_frontend* fe)
+ /* fixme (low): error handling */
+ int i;
+
+- dprintk("%s: init chip\n", __FUNCTION__);
++ dprintk("%s: init chip\n", __func__);
+
+ for(i = 0; i < ARRAY_SIZE(cx24110_regdata); i++) {
+ cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data);
+diff --git a/drivers/media/dvb/frontends/cx24110.h b/drivers/media/dvb/frontends/cx24110.h
+index 0ca3af4..1792adb 100644
+--- a/drivers/media/dvb/frontends/cx24110.h
++++ b/drivers/media/dvb/frontends/cx24110.h
+@@ -48,7 +48,7 @@ extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
+ static inline struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
+ struct i2c_adapter* i2c)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_CX24110
+diff --git a/drivers/media/dvb/frontends/cx24113.h b/drivers/media/dvb/frontends/cx24113.h
+new file mode 100644
+index 0000000..5ab3dd1
+--- /dev/null
++++ b/drivers/media/dvb/frontends/cx24113.h
+@@ -0,0 +1,48 @@
++/*
++ * Driver for Conexant CX24113/CX24128 Tuner (Satelite)
++ *
++ * Copyright (C) 2007-8 Patrick Boettcher <pb at linuxtv.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
++ */
++
++#ifndef CX24113_H
++#define CX24113_H
++
++struct dvb_frontend;
++
++struct cx24113_config {
++ u8 i2c_addr; /* 0x14 or 0x54 */
++
++ u32 xtal_khz;
++};
++
++/* TODO: #if defined(CONFIG_DVB_TUNER_CX24113) || \
++ * (defined(CONFIG_DVB_TUNER_CX24113_MODULE) && defined(MODULE)) */
++
++static inline struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe,
++ const struct cx24113_config *config, struct i2c_adapter *i2c)
++{
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++ return NULL;
++}
++
++static inline void cx24113_agc_callback(struct dvb_frontend *fe)
++{
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++}
++
++#endif /* CX24113_H */
+diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c
+index d74fdbd..7f68d78 100644
+--- a/drivers/media/dvb/frontends/cx24123.c
++++ b/drivers/media/dvb/frontends/cx24123.c
+@@ -1,24 +1,26 @@
+ /*
+- Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
+-
+- Copyright (C) 2005 Steven Toth <stoth at hauppauge.com>
+-
+- Support for KWorld DVB-S 100 by Vadim Catana <skystar at moldova.cc>
+-
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; either version 2 of the License, or
+- (at your option) any later version.
+-
+- This program is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- GNU General Public License for more details.
+-
+- You should have received a copy of the GNU General Public License
+- along with this program; if not, write to the Free Software
+- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-*/
++ * Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
++ *
++ * Copyright (C) 2005 Steven Toth <stoth at hauppauge.com>
++ *
++ * Support for KWorld DVB-S 100 by Vadim Catana <skystar at moldova.cc>
++ *
++ * Support for CX24123/CX24113-NIM by Patrick Boettcher <pb at linuxtv.org>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
+
+ #include <linux/slab.h>
+ #include <linux/kernel.h>
+@@ -32,9 +34,16 @@
+
+ static int force_band;
+ static int debug;
++
++#define info(args...) do { printk(KERN_INFO "CX24123: " args); } while (0)
++#define err(args...) do { printk(KERN_ERR "CX24123: " args); } while (0)
++
+ #define dprintk(args...) \
+ do { \
+- if (debug) printk (KERN_DEBUG "cx24123: " args); \
++ if (debug) { \
++ printk(KERN_DEBUG "CX24123: %s: ", __func__); \
++ printk(args); \
++ } \
+ } while (0)
+
+ struct cx24123_state
+@@ -51,6 +60,10 @@ struct cx24123_state
+ u32 pllarg;
+ u32 FILTune;
+
++ struct i2c_adapter tuner_i2c_adapter;
++
++ u8 demod_rev;
++
+ /* The Demod/Tuner can't easily provide these, we cache them */
+ u32 currentfreq;
+ u32 currentsymbolrate;
+@@ -225,48 +238,52 @@ static struct {
+ {0x67, 0x83}, /* Non-DCII symbol clock */
+ };
+
+-static int cx24123_writereg(struct cx24123_state* state, int reg, int data)
++static int cx24123_i2c_writereg(struct cx24123_state *state,
++ u8 i2c_addr, int reg, int data)
+ {
+ u8 buf[] = { reg, data };
+- struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
++ struct i2c_msg msg = {
++ .addr = i2c_addr, .flags = 0, .buf = buf, .len = 2
++ };
+ int err;
+
+- if (debug>1)
+- printk("cx24123: %s: write reg 0x%02x, value 0x%02x\n",
+- __FUNCTION__,reg, data);
++ /* printk(KERN_DEBUG "wr(%02x): %02x %02x\n", i2c_addr, reg, data); */
+
+ if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+ printk("%s: writereg error(err == %i, reg == 0x%02x,"
+- " data == 0x%02x)\n", __FUNCTION__, err, reg, data);
+- return -EREMOTEIO;
++ " data == 0x%02x)\n", __func__, err, reg, data);
++ return err;
+ }
+
+ return 0;
+ }
+
+-static int cx24123_readreg(struct cx24123_state* state, u8 reg)
++static int cx24123_i2c_readreg(struct cx24123_state *state, u8 i2c_addr, u8 reg)
+ {
+ int ret;
+- u8 b0[] = { reg };
+- u8 b1[] = { 0 };
++ u8 b = 0;
+ struct i2c_msg msg[] = {
+- { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
+- { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 }
++ { .addr = i2c_addr, .flags = 0, .buf = ®, .len = 1 },
++ { .addr = i2c_addr, .flags = I2C_M_RD, .buf = &b, .len = 1 }
+ };
+
+ ret = i2c_transfer(state->i2c, msg, 2);
+
+ if (ret != 2) {
+- printk("%s: reg=0x%x (error=%d)\n", __FUNCTION__, reg, ret);
++ err("%s: reg=0x%x (error=%d)\n", __func__, reg, ret);
+ return ret;
+ }
+
+- if (debug>1)
+- printk("cx24123: read reg 0x%02x, value 0x%02x\n",reg, ret);
++ /* printk(KERN_DEBUG "rd(%02x): %02x %02x\n", i2c_addr, reg, b); */
+
+- return b1[0];
++ return b;
+ }
+
++#define cx24123_readreg(state, reg) \
++ cx24123_i2c_readreg(state, state->config->demod_address, reg)
++#define cx24123_writereg(state, reg, val) \
++ cx24123_i2c_writereg(state, state->config->demod_address, reg, val)
++
+ static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion)
+ {
+ u8 nom_reg = cx24123_readreg(state, 0x0e);
+@@ -274,17 +291,17 @@ static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_invers
+
+ switch (inversion) {
+ case INVERSION_OFF:
+- dprintk("%s: inversion off\n",__FUNCTION__);
++ dprintk("inversion off\n");
+ cx24123_writereg(state, 0x0e, nom_reg & ~0x80);
+ cx24123_writereg(state, 0x10, auto_reg | 0x80);
+ break;
+ case INVERSION_ON:
+- dprintk("%s: inversion on\n",__FUNCTION__);
++ dprintk("inversion on\n");
+ cx24123_writereg(state, 0x0e, nom_reg | 0x80);
+ cx24123_writereg(state, 0x10, auto_reg | 0x80);
+ break;
+ case INVERSION_AUTO:
+- dprintk("%s: inversion auto\n",__FUNCTION__);
++ dprintk("inversion auto\n");
+ cx24123_writereg(state, 0x10, auto_reg & ~0x80);
+ break;
+ default:
+@@ -301,10 +318,10 @@ static int cx24123_get_inversion(struct cx24123_state* state, fe_spectral_invers
+ val = cx24123_readreg(state, 0x1b) >> 7;
+
+ if (val == 0) {
+- dprintk("%s: read inversion off\n",__FUNCTION__);
++ dprintk("read inversion off\n");
+ *inversion = INVERSION_OFF;
+ } else {
+- dprintk("%s: read inversion on\n",__FUNCTION__);
++ dprintk("read inversion on\n");
+ *inversion = INVERSION_ON;
+ }
+
+@@ -326,42 +343,42 @@ static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec)
+
+ switch (fec) {
+ case FEC_1_2:
+- dprintk("%s: set FEC to 1/2\n",__FUNCTION__);
++ dprintk("set FEC to 1/2\n");
+ cx24123_writereg(state, 0x0e, nom_reg | 0x01);
+ cx24123_writereg(state, 0x0f, 0x02);
+ break;
+ case FEC_2_3:
+- dprintk("%s: set FEC to 2/3\n",__FUNCTION__);
++ dprintk("set FEC to 2/3\n");
+ cx24123_writereg(state, 0x0e, nom_reg | 0x02);
+ cx24123_writereg(state, 0x0f, 0x04);
+ break;
+ case FEC_3_4:
+- dprintk("%s: set FEC to 3/4\n",__FUNCTION__);
++ dprintk("set FEC to 3/4\n");
+ cx24123_writereg(state, 0x0e, nom_reg | 0x03);
+ cx24123_writereg(state, 0x0f, 0x08);
+ break;
+ case FEC_4_5:
+- dprintk("%s: set FEC to 4/5\n",__FUNCTION__);
++ dprintk("set FEC to 4/5\n");
+ cx24123_writereg(state, 0x0e, nom_reg | 0x04);
+ cx24123_writereg(state, 0x0f, 0x10);
+ break;
+ case FEC_5_6:
+- dprintk("%s: set FEC to 5/6\n",__FUNCTION__);
++ dprintk("set FEC to 5/6\n");
+ cx24123_writereg(state, 0x0e, nom_reg | 0x05);
+ cx24123_writereg(state, 0x0f, 0x20);
+ break;
+ case FEC_6_7:
+- dprintk("%s: set FEC to 6/7\n",__FUNCTION__);
++ dprintk("set FEC to 6/7\n");
+ cx24123_writereg(state, 0x0e, nom_reg | 0x06);
+ cx24123_writereg(state, 0x0f, 0x40);
+ break;
+ case FEC_7_8:
+- dprintk("%s: set FEC to 7/8\n",__FUNCTION__);
++ dprintk("set FEC to 7/8\n");
+ cx24123_writereg(state, 0x0e, nom_reg | 0x07);
+ cx24123_writereg(state, 0x0f, 0x80);
+ break;
+ case FEC_AUTO:
+- dprintk("%s: set FEC to auto\n",__FUNCTION__);
++ dprintk("set FEC to auto\n");
+ cx24123_writereg(state, 0x0f, 0xfe);
+ break;
+ default:
+@@ -490,7 +507,8 @@ static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate)
+ tmp = cx24123_readreg(state, 0x0c) & ~0xe0;
+ cx24123_writereg(state, 0x0c, tmp | sample_gain << 5);
+
+- dprintk("%s: srate=%d, ratio=0x%08x, sample_rate=%i sample_gain=%d\n", __FUNCTION__, srate, ratio, sample_rate, sample_gain);
++ dprintk("srate=%d, ratio=0x%08x, sample_rate=%i sample_gain=%d\n",
++ srate, ratio, sample_rate, sample_gain);
+
+ return 0;
+ }
+@@ -570,7 +588,7 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
+ struct cx24123_state *state = fe->demodulator_priv;
+ unsigned long timeout;
+
+- dprintk("%s: pll writereg called, data=0x%08x\n",__FUNCTION__,data);
++ dprintk("pll writereg called, data=0x%08x\n", data);
+
+ /* align the 21 bytes into to bit23 boundary */
+ data = data << 3;
+@@ -583,7 +601,8 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
+ cx24123_writereg(state, 0x22, (data >> 16) & 0xff);
+ while ((cx24123_readreg(state, 0x20) & 0x40) == 0) {
+ if (time_after(jiffies, timeout)) {
+- printk("%s: demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__);
++ err("%s: demodulator is not responding, "\
++ "possibly hung, aborting.\n", __func__);
+ return -EREMOTEIO;
+ }
+ msleep(10);
+@@ -594,7 +613,8 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
+ cx24123_writereg(state, 0x22, (data>>8) & 0xff );
+ while ((cx24123_readreg(state, 0x20) & 0x40) == 0) {
+ if (time_after(jiffies, timeout)) {
+- printk("%s: demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__);
++ err("%s: demodulator is not responding, "\
++ "possibly hung, aborting.\n", __func__);
+ return -EREMOTEIO;
+ }
+ msleep(10);
+@@ -605,7 +625,8 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par
+ cx24123_writereg(state, 0x22, (data) & 0xff );
+ while ((cx24123_readreg(state, 0x20) & 0x80)) {
+ if (time_after(jiffies, timeout)) {
+- printk("%s: demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__);
++ err("%s: demodulator is not responding," \
++ "possibly hung, aborting.\n", __func__);
+ return -EREMOTEIO;
+ }
+ msleep(10);
+@@ -626,7 +647,7 @@ static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_paramet
+ dprintk("frequency=%i\n", p->frequency);
+
+ if (cx24123_pll_calculate(fe, p) != 0) {
+- printk("%s: cx24123_pll_calcutate failed\n",__FUNCTION__);
++ err("%s: cx24123_pll_calcutate failed\n", __func__);
+ return -EINVAL;
+ }
+
+@@ -643,18 +664,38 @@ static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_paramet
+ cx24123_writereg(state, 0x27, state->FILTune >> 2);
+ cx24123_writereg(state, 0x28, val | (state->FILTune & 0x3));
+
+- dprintk("%s: pll tune VCA=%d, band=%d, pll=%d\n",__FUNCTION__,state->VCAarg,
+- state->bandselectarg,state->pllarg);
++ dprintk("pll tune VCA=%d, band=%d, pll=%d\n", state->VCAarg,
++ state->bandselectarg, state->pllarg);
+
+ return 0;
+ }
+
++
++/*
++ * 0x23:
++ * [7:7] = BTI enabled
++ * [6:6] = I2C repeater enabled
++ * [5:5] = I2C repeater start
++ * [0:0] = BTI start
++ */
++
++/* mode == 1 -> i2c-repeater, 0 -> bti */
++static int cx24123_repeater_mode(struct cx24123_state *state, u8 mode, u8 start)
++{
++ u8 r = cx24123_readreg(state, 0x23) & 0x1e;
++ if (mode)
++ r |= (1 << 6) | (start << 5);
++ else
++ r |= (1 << 7) | (start);
++ return cx24123_writereg(state, 0x23, r);
++}
++
+ static int cx24123_initfe(struct dvb_frontend* fe)
+ {
+ struct cx24123_state *state = fe->demodulator_priv;
+ int i;
+
+- dprintk("%s: init frontend\n",__FUNCTION__);
++ dprintk("init frontend\n");
+
+ /* Configure the demod to a good set of defaults */
+ for (i = 0; i < ARRAY_SIZE(cx24123_regdata); i++)
+@@ -664,6 +705,9 @@ static int cx24123_initfe(struct dvb_frontend* fe)
+ if(state->config->lnb_polarity)
+ cx24123_writereg(state, 0x32, cx24123_readreg(state, 0x32) | 0x02);
+
++ if (state->config->dont_use_pll)
++ cx24123_repeater_mode(state, 1, 0);
++
+ return 0;
+ }
+
+@@ -676,10 +720,10 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage
+
+ switch (voltage) {
+ case SEC_VOLTAGE_13:
+- dprintk("%s: setting voltage 13V\n", __FUNCTION__);
++ dprintk("setting voltage 13V\n");
+ return cx24123_writereg(state, 0x29, val & 0x7f);
+ case SEC_VOLTAGE_18:
+- dprintk("%s: setting voltage 18V\n", __FUNCTION__);
++ dprintk("setting voltage 18V\n");
+ return cx24123_writereg(state, 0x29, val | 0x80);
+ case SEC_VOLTAGE_OFF:
+ /* already handled in cx88-dvb */
+@@ -697,7 +741,8 @@ static void cx24123_wait_for_diseqc(struct cx24123_state *state)
+ unsigned long timeout = jiffies + msecs_to_jiffies(200);
+ while (!(cx24123_readreg(state, 0x29) & 0x40)) {
+ if(time_after(jiffies, timeout)) {
+- printk("%s: diseqc queue not ready, command may be lost.\n", __FUNCTION__);
++ err("%s: diseqc queue not ready, " \
++ "command may be lost.\n", __func__);
+ break;
+ }
+ msleep(10);
+@@ -709,7 +754,7 @@ static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma
+ struct cx24123_state *state = fe->demodulator_priv;
+ int i, val, tone;
+
+- dprintk("%s:\n",__FUNCTION__);
++ dprintk("\n");
+
+ /* stop continuous tone if enabled */
+ tone = cx24123_readreg(state, 0x29);
+@@ -744,7 +789,7 @@ static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
+ struct cx24123_state *state = fe->demodulator_priv;
+ int val, tone;
+
+- dprintk("%s:\n", __FUNCTION__);
++ dprintk("\n");
+
+ /* stop continuous tone if enabled */
+ tone = cx24123_readreg(state, 0x29);
+@@ -778,13 +823,21 @@ static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
+ static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ {
+ struct cx24123_state *state = fe->demodulator_priv;
+-
+ int sync = cx24123_readreg(state, 0x14);
+- int lock = cx24123_readreg(state, 0x20);
+
+ *status = 0;
+- if (lock & 0x01)
+- *status |= FE_HAS_SIGNAL;
++ if (state->config->dont_use_pll) {
++ u32 tun_status = 0;
++ if (fe->ops.tuner_ops.get_status)
++ fe->ops.tuner_ops.get_status(fe, &tun_status);
++ if (tun_status & TUNER_STATUS_LOCKED)
++ *status |= FE_HAS_SIGNAL;
++ } else {
++ int lock = cx24123_readreg(state, 0x20);
++ if (lock & 0x01)
++ *status |= FE_HAS_SIGNAL;
++ }
++
+ if (sync & 0x02)
+ *status |= FE_HAS_CARRIER; /* Phase locked */
+ if (sync & 0x04)
+@@ -803,7 +856,7 @@ static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ * Configured to return the measurement of errors in blocks, because no UCBLOCKS value
+ * is available, so this value doubles up to satisfy both measurements
+ */
+-static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber)
++static int cx24123_read_ber(struct dvb_frontend *fe, u32 *ber)
+ {
+ struct cx24123_state *state = fe->demodulator_priv;
+
+@@ -813,23 +866,24 @@ static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber)
+ (cx24123_readreg(state, 0x1d) << 8 |
+ cx24123_readreg(state, 0x1e));
+
+- dprintk("%s: BER = %d\n",__FUNCTION__,*ber);
++ dprintk("BER = %d\n", *ber);
+
+ return 0;
+ }
+
+-static int cx24123_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
++static int cx24123_read_signal_strength(struct dvb_frontend *fe,
++ u16 *signal_strength)
+ {
+ struct cx24123_state *state = fe->demodulator_priv;
+
+ *signal_strength = cx24123_readreg(state, 0x3b) << 8; /* larger = better */
+
+- dprintk("%s: Signal strength = %d\n",__FUNCTION__,*signal_strength);
++ dprintk("Signal strength = %d\n", *signal_strength);
+
+ return 0;
+ }
+
+-static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr)
++static int cx24123_read_snr(struct dvb_frontend *fe, u16 *snr)
+ {
+ struct cx24123_state *state = fe->demodulator_priv;
+
+@@ -838,16 +892,17 @@ static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr)
+ *snr = 65535 - (((u16)cx24123_readreg(state, 0x18) << 8) |
+ (u16)cx24123_readreg(state, 0x19));
+
+- dprintk("%s: read S/N index = %d\n",__FUNCTION__,*snr);
++ dprintk("read S/N index = %d\n", *snr);
+
+ return 0;
+ }
+
+-static int cx24123_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
++static int cx24123_set_frontend(struct dvb_frontend *fe,
++ struct dvb_frontend_parameters *p)
+ {
+ struct cx24123_state *state = fe->demodulator_priv;
+
+- dprintk("%s: set_frontend\n",__FUNCTION__);
++ dprintk("\n");
+
+ if (state->config->set_ts_params)
+ state->config->set_ts_params(fe, 0);
+@@ -858,13 +913,22 @@ static int cx24123_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
+ cx24123_set_inversion(state, p->inversion);
+ cx24123_set_fec(state, p->u.qpsk.fec_inner);
+ cx24123_set_symbolrate(state, p->u.qpsk.symbol_rate);
+- cx24123_pll_tune(fe, p);
++
++ if (!state->config->dont_use_pll)
++ cx24123_pll_tune(fe, p);
++ else if (fe->ops.tuner_ops.set_params)
++ fe->ops.tuner_ops.set_params(fe, p);
++ else
++ err("it seems I don't have a tuner...");
+
+ /* Enable automatic aquisition and reset cycle */
+ cx24123_writereg(state, 0x03, (cx24123_readreg(state, 0x03) | 0x07));
+ cx24123_writereg(state, 0x00, 0x10);
+ cx24123_writereg(state, 0x00, 0);
+
++ if (state->config->agc_callback)
++ state->config->agc_callback(fe);
++
+ return 0;
+ }
+
+@@ -872,14 +936,14 @@ static int cx24123_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
+ {
+ struct cx24123_state *state = fe->demodulator_priv;
+
+- dprintk("%s: get_frontend\n",__FUNCTION__);
++ dprintk("\n");
+
+ if (cx24123_get_inversion(state, &p->inversion) != 0) {
+- printk("%s: Failed to get inversion status\n",__FUNCTION__);
++ err("%s: Failed to get inversion status\n", __func__);
+ return -EREMOTEIO;
+ }
+ if (cx24123_get_fec(state, &p->u.qpsk.fec_inner) != 0) {
+- printk("%s: Failed to get fec status\n",__FUNCTION__);
++ err("%s: Failed to get fec status\n", __func__);
+ return -EREMOTEIO;
+ }
+ p->frequency = state->currentfreq;
+@@ -900,13 +964,13 @@ static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+
+ switch (tone) {
+ case SEC_TONE_ON:
+- dprintk("%s: setting tone on\n", __FUNCTION__);
++ dprintk("setting tone on\n");
+ return cx24123_writereg(state, 0x29, val | 0x10);
+ case SEC_TONE_OFF:
+- dprintk("%s: setting tone off\n",__FUNCTION__);
++ dprintk("setting tone off\n");
+ return cx24123_writereg(state, 0x29, val & 0xef);
+ default:
+- printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
++ err("CASE reached default with tone=%d\n", tone);
+ return -EINVAL;
+ }
+
+@@ -939,47 +1003,86 @@ static int cx24123_get_algo(struct dvb_frontend *fe)
+ static void cx24123_release(struct dvb_frontend* fe)
+ {
+ struct cx24123_state* state = fe->demodulator_priv;
+- dprintk("%s\n",__FUNCTION__);
++ dprintk("\n");
++ i2c_del_adapter(&state->tuner_i2c_adapter);
+ kfree(state);
+ }
+
++static int cx24123_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap,
++ struct i2c_msg msg[], int num)
++{
++ struct cx24123_state *state = i2c_get_adapdata(i2c_adap);
++ /* this repeater closes after the first stop */
++ cx24123_repeater_mode(state, 1, 1);
++ return i2c_transfer(state->i2c, msg, num);
++}
++
++static u32 cx24123_tuner_i2c_func(struct i2c_adapter *adapter)
++{
++ return I2C_FUNC_I2C;
++}
++
++static struct i2c_algorithm cx24123_tuner_i2c_algo = {
++ .master_xfer = cx24123_tuner_i2c_tuner_xfer,
++ .functionality = cx24123_tuner_i2c_func,
++};
++
++struct i2c_adapter *
++ cx24123_get_tuner_i2c_adapter(struct dvb_frontend *fe)
++{
++ struct cx24123_state *state = fe->demodulator_priv;
++ return &state->tuner_i2c_adapter;
++}
++EXPORT_SYMBOL(cx24123_get_tuner_i2c_adapter);
++
+ static struct dvb_frontend_ops cx24123_ops;
+
+ struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
+ struct i2c_adapter* i2c)
+ {
+- struct cx24123_state* state = NULL;
+- int ret;
+-
+- dprintk("%s\n",__FUNCTION__);
++ struct cx24123_state *state =
++ kzalloc(sizeof(struct cx24123_state), GFP_KERNEL);
+
++ dprintk("\n");
+ /* allocate memory for the internal state */
+- state = kmalloc(sizeof(struct cx24123_state), GFP_KERNEL);
+ if (state == NULL) {
+- printk("Unable to kmalloc\n");
++ err("Unable to kmalloc\n");
+ goto error;
+ }
+
+ /* setup the state */
+ state->config = config;
+ state->i2c = i2c;
+- state->VCAarg = 0;
+- state->VGAarg = 0;
+- state->bandselectarg = 0;
+- state->pllarg = 0;
+- state->currentfreq = 0;
+- state->currentsymbolrate = 0;
+
+ /* check if the demod is there */
+- ret = cx24123_readreg(state, 0x00);
+- if ((ret != 0xd1) && (ret != 0xe1)) {
+- printk("Version != d1 or e1\n");
++ state->demod_rev = cx24123_readreg(state, 0x00);
++ switch (state->demod_rev) {
++ case 0xe1: info("detected CX24123C\n"); break;
++ case 0xd1: info("detected CX24123\n"); break;
++ default:
++ err("wrong demod revision: %x\n", state->demod_rev);
+ goto error;
+ }
+
+ /* create dvb_frontend */
+ memcpy(&state->frontend.ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
+ state->frontend.demodulator_priv = state;
++
++ /* create tuner i2c adapter */
++ if (config->dont_use_pll)
++ cx24123_repeater_mode(state, 1, 0);
++
++ strncpy(state->tuner_i2c_adapter.name,
++ "CX24123 tuner I2C bus", I2C_NAME_SIZE);
++ state->tuner_i2c_adapter.class = I2C_CLASS_TV_DIGITAL,
++ state->tuner_i2c_adapter.algo = &cx24123_tuner_i2c_algo;
++ state->tuner_i2c_adapter.algo_data = NULL;
++ i2c_set_adapdata(&state->tuner_i2c_adapter, state);
++ if (i2c_add_adapter(&state->tuner_i2c_adapter) < 0) {
++ err("tuner i2c bus could not be initialized\n");
++ goto error;
++ }
++
+ return &state->frontend;
+
+ error:
+@@ -1029,7 +1132,8 @@ MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
+ module_param(force_band, int, 0644);
+ MODULE_PARM_DESC(force_band, "Force a specific band select (1-9, default:off).");
+
+-MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24123/cx24109 hardware");
++MODULE_DESCRIPTION("DVB Frontend module for Conexant " \
++ "CX24123/CX24109/CX24113 hardware");
+ MODULE_AUTHOR("Steven Toth");
+ MODULE_LICENSE("GPL");
+
+diff --git a/drivers/media/dvb/frontends/cx24123.h b/drivers/media/dvb/frontends/cx24123.h
+index 84f9e4f..81ebc3d 100644
+--- a/drivers/media/dvb/frontends/cx24123.h
++++ b/drivers/media/dvb/frontends/cx24123.h
+@@ -33,16 +33,27 @@ struct cx24123_config
+
+ /* 0 = LNB voltage normal, 1 = LNB voltage inverted */
+ int lnb_polarity;
++
++ /* this device has another tuner */
++ u8 dont_use_pll;
++ void (*agc_callback) (struct dvb_frontend *);
+ };
+
+ #if defined(CONFIG_DVB_CX24123) || (defined(CONFIG_DVB_CX24123_MODULE) && defined(MODULE))
+-extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
+- struct i2c_adapter* i2c);
++extern struct dvb_frontend *cx24123_attach(const struct cx24123_config *config,
++ struct i2c_adapter *i2c);
++extern struct i2c_adapter *cx24123_get_tuner_i2c_adapter(struct dvb_frontend *);
+ #else
+-static inline struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
+- struct i2c_adapter* i2c)
++static inline struct dvb_frontend *cx24123_attach(
++ const struct cx24123_config *config, struct i2c_adapter *i2c)
++{
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++ return NULL;
++}
++static struct i2c_adapter *
++ cx24123_get_tuner_i2c_adapter(struct dvb_frontend *fe)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_CX24123
+diff --git a/drivers/media/dvb/frontends/dib3000.h b/drivers/media/dvb/frontends/dib3000.h
+index a6d3854..ba91735 100644
+--- a/drivers/media/dvb/frontends/dib3000.h
++++ b/drivers/media/dvb/frontends/dib3000.h
+@@ -48,7 +48,7 @@ extern struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config
+ static inline struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
+ struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_DIB3000MB
+diff --git a/drivers/media/dvb/frontends/dib3000mc.h b/drivers/media/dvb/frontends/dib3000mc.h
+index 72d4757..4142ed7 100644
+--- a/drivers/media/dvb/frontends/dib3000mc.h
++++ b/drivers/media/dvb/frontends/dib3000mc.h
+@@ -44,7 +44,7 @@ extern struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i
+ #else
+ static inline struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_DIB3000MC
+diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c
+index 47c23e2..1a0142e 100644
+--- a/drivers/media/dvb/frontends/dib7000p.c
++++ b/drivers/media/dvb/frontends/dib7000p.c
+@@ -1168,7 +1168,7 @@ static int dib7000p_set_frontend(struct dvb_frontend* fe,
+ ret = dib7000p_tune(fe, fep);
+
+ /* make this a config parameter */
+- dib7000p_set_output_mode(state, OUTMODE_MPEG2_FIFO);
++ dib7000p_set_output_mode(state, state->cfg.output_mode);
+ return ret;
+ }
+
+@@ -1330,6 +1330,12 @@ struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
+ st->gpio_val = cfg->gpio_val;
+ st->gpio_dir = cfg->gpio_dir;
+
++ /* Ensure the output mode remains at the previous default if it's
++ * not specifically set by the caller.
++ */
++ if (st->cfg.output_mode != OUTMODE_MPEG2_SERIAL)
++ st->cfg.output_mode = OUTMODE_MPEG2_FIFO;
++
+ demod = &st->demod;
+ demod->demodulator_priv = st;
+ memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops));
+diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h
+index eefcac8..081bd81 100644
+--- a/drivers/media/dvb/frontends/dib7000p.h
++++ b/drivers/media/dvb/frontends/dib7000p.h
+@@ -31,6 +31,8 @@ struct dib7000p_config {
+ u8 spur_protect;
+
+ int (*agc_control) (struct dvb_frontend *, u8 before);
++
++ u8 output_mode;
+ };
+
+ #define DEFAULT_DIB7000P_I2C_ADDRESS 18
+diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
+index 8c8d734..a054894 100644
+--- a/drivers/media/dvb/frontends/dvb-pll.c
++++ b/drivers/media/dvb/frontends/dvb-pll.c
+@@ -44,14 +44,10 @@ struct dvb_pll_priv {
+
+ static unsigned int dvb_pll_devcount;
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "enable verbose debug messages");
+
+-static unsigned int input[DVB_PLL_MAX] = { [ 0 ... (DVB_PLL_MAX-1) ] = 0 };
+-module_param_array(input, int, NULL, 0644);
+-MODULE_PARM_DESC(input,"specify rf input choice, 0 for autoselect (default)");
+-
+ static unsigned int id[DVB_PLL_MAX] =
+ { [ 0 ... (DVB_PLL_MAX-1) ] = DVB_PLL_UNDEFINED };
+ module_param_array(id, int, NULL, 0644);
+@@ -80,23 +76,6 @@ struct dvb_pll_desc {
+ /* ----------------------------------------------------------- */
+ /* descriptions */
+
+-/* Set AGC TOP value to 103 dBuV:
+- 0x80 = Control Byte
+- 0x40 = 250 uA charge pump (irrelevant)
+- 0x18 = Aux Byte to follow
+- 0x06 = 64.5 kHz divider (irrelevant)
+- 0x01 = Disable Vt (aka sleep)
+-
+- 0x00 = AGC Time constant 2s Iagc = 300 nA (vs 0x80 = 9 nA)
+- 0x50 = AGC Take over point = 103 dBuV */
+-static u8 tua603x_agc103[] = { 2, 0x80|0x40|0x18|0x06|0x01, 0x00|0x50 };
+-
+-/* 0x04 = 166.67 kHz divider
+-
+- 0x80 = AGC Time constant 50ms Iagc = 9 uA
+- 0x20 = AGC Take over point = 112 dBuV */
+-static u8 tua603x_agc112[] = { 2, 0x80|0x40|0x18|0x04|0x01, 0x80|0x20 };
+-
+ static struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {
+ .name = "Thomson dtt7579",
+ .min = 177000000,
+@@ -112,19 +91,6 @@ static struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {
+ },
+ };
+
+-static struct dvb_pll_desc dvb_pll_thomson_dtt7610 = {
+- .name = "Thomson dtt7610",
+- .min = 44000000,
+- .max = 958000000,
+- .iffreq= 44000000,
+- .count = 3,
+- .entries = {
+- { 157250000, 62500, 0x8e, 0x39 },
+- { 454000000, 62500, 0x8e, 0x3a },
+- { 999999999, 62500, 0x8e, 0x3c },
+- },
+-};
+-
+ static void thomson_dtt759x_bw(struct dvb_frontend *fe, u8 *buf,
+ const struct dvb_frontend_parameters *params)
+ {
+@@ -165,34 +131,6 @@ static struct dvb_pll_desc dvb_pll_lg_z201 = {
+ },
+ };
+
+-static struct dvb_pll_desc dvb_pll_microtune_4042 = {
+- .name = "Microtune 4042 FI5",
+- .min = 57000000,
+- .max = 858000000,
+- .iffreq= 44000000,
+- .count = 3,
+- .entries = {
+- { 162000000, 62500, 0x8e, 0xa1 },
+- { 457000000, 62500, 0x8e, 0x91 },
+- { 999999999, 62500, 0x8e, 0x31 },
+- },
+-};
+-
+-static struct dvb_pll_desc dvb_pll_thomson_dtt761x = {
+- /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
+- .name = "Thomson dtt761x",
+- .min = 57000000,
+- .max = 863000000,
+- .iffreq= 44000000,
+- .count = 3,
+- .initdata = tua603x_agc103,
+- .entries = {
+- { 147000000, 62500, 0x8e, 0x39 },
+- { 417000000, 62500, 0x8e, 0x3a },
+- { 999999999, 62500, 0x8e, 0x3c },
+- },
+-};
+-
+ static struct dvb_pll_desc dvb_pll_unknown_1 = {
+ .name = "unknown 1", /* used by dntv live dvb-t */
+ .min = 174000000,
+@@ -301,54 +239,6 @@ static struct dvb_pll_desc dvb_pll_tua6034 = {
+ },
+ };
+
+-/* Infineon TUA6034
+- * used in LG TDVS-H061F, LG TDVS-H062F and LG TDVS-H064F
+- */
+-static struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf = {
+- .name = "LG TDVS-H06xF",
+- .min = 54000000,
+- .max = 863000000,
+- .iffreq= 44000000,
+- .initdata = tua603x_agc103,
+- .count = 3,
+- .entries = {
+- { 165000000, 62500, 0xce, 0x01 },
+- { 450000000, 62500, 0xce, 0x02 },
+- { 999999999, 62500, 0xce, 0x04 },
+- },
+-};
+-
+-/* Philips FMD1216ME
+- * used in Medion Hybrid PCMCIA card and USB Box
+- */
+-static void fmd1216me_bw(struct dvb_frontend *fe, u8 *buf,
+- const struct dvb_frontend_parameters *params)
+-{
+- if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ &&
+- params->frequency >= 158870000)
+- buf[3] |= 0x08;
+-}
+-
+-static struct dvb_pll_desc dvb_pll_fmd1216me = {
+- .name = "Philips FMD1216ME",
+- .min = 50870000,
+- .max = 858000000,
+- .iffreq= 36125000,
+- .set = fmd1216me_bw,
+- .initdata = tua603x_agc112,
+- .sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 },
+- .count = 7,
+- .entries = {
+- { 143870000, 166667, 0xbc, 0x41 },
+- { 158870000, 166667, 0xf4, 0x41 },
+- { 329870000, 166667, 0xbc, 0x42 },
+- { 441870000, 166667, 0xf4, 0x42 },
+- { 625870000, 166667, 0xbc, 0x44 },
+- { 803870000, 166667, 0xf4, 0x44 },
+- { 999999999, 166667, 0xfc, 0x44 },
+- }
+-};
+-
+ /* ALPS TDED4
+ * used in Nebula-Cards and USB boxes
+ */
+@@ -391,55 +281,6 @@ static struct dvb_pll_desc dvb_pll_tdhu2 = {
+ }
+ };
+
+-/* Philips TUV1236D
+- * used in ATI HDTV Wonder
+- */
+-static void tuv1236d_rf(struct dvb_frontend *fe, u8 *buf,
+- const struct dvb_frontend_parameters *params)
+-{
+- struct dvb_pll_priv *priv = fe->tuner_priv;
+- unsigned int new_rf = input[priv->nr];
+-
+- if ((new_rf == 0) || (new_rf > 2)) {
+- switch (params->u.vsb.modulation) {
+- case QAM_64:
+- case QAM_256:
+- new_rf = 1;
+- break;
+- case VSB_8:
+- default:
+- new_rf = 2;
+- }
+- }
+-
+- switch (new_rf) {
+- case 1:
+- buf[3] |= 0x08;
+- break;
+- case 2:
+- buf[3] &= ~0x08;
+- break;
+- default:
+- printk(KERN_WARNING
+- "%s: unhandled rf input selection: %d",
+- __FUNCTION__, new_rf);
+- }
+-}
+-
+-static struct dvb_pll_desc dvb_pll_tuv1236d = {
+- .name = "Philips TUV1236D",
+- .min = 54000000,
+- .max = 864000000,
+- .iffreq= 44000000,
+- .set = tuv1236d_rf,
+- .count = 3,
+- .entries = {
+- { 157250000, 62500, 0xc6, 0x41 },
+- { 454000000, 62500, 0xc6, 0x42 },
+- { 999999999, 62500, 0xc6, 0x44 },
+- },
+-};
+-
+ /* Samsung TBMV30111IN / TBMV30712IN1
+ * used in Air2PC ATSC - 2nd generation (nxt2002)
+ */
+@@ -476,64 +317,6 @@ static struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {
+ },
+ };
+
+-/*
+- * Philips TD1316 Tuner.
+- */
+-static void td1316_bw(struct dvb_frontend *fe, u8 *buf,
+- const struct dvb_frontend_parameters *params)
+-{
+- u8 band;
+-
+- /* determine band */
+- if (params->frequency < 161000000)
+- band = 1;
+- else if (params->frequency < 444000000)
+- band = 2;
+- else
+- band = 4;
+-
+- buf[3] |= band;
+-
+- /* setup PLL filter */
+- if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
+- buf[3] |= 1 << 3;
+-}
+-
+-static struct dvb_pll_desc dvb_pll_philips_td1316 = {
+- .name = "Philips TD1316",
+- .min = 87000000,
+- .max = 895000000,
+- .iffreq= 36166667,
+- .set = td1316_bw,
+- .count = 9,
+- .entries = {
+- { 93834000, 166667, 0xca, 0x60},
+- { 123834000, 166667, 0xca, 0xa0},
+- { 163834000, 166667, 0xca, 0xc0},
+- { 253834000, 166667, 0xca, 0x60},
+- { 383834000, 166667, 0xca, 0xa0},
+- { 443834000, 166667, 0xca, 0xc0},
+- { 583834000, 166667, 0xca, 0x60},
+- { 793834000, 166667, 0xca, 0xa0},
+- { 858834000, 166667, 0xca, 0xe0},
+- },
+-};
+-
+-/* FE6600 used on DViCO Hybrid */
+-static struct dvb_pll_desc dvb_pll_thomson_fe6600 = {
+- .name = "Thomson FE6600",
+- .min = 44250000,
+- .max = 858000000,
+- .iffreq= 36125000,
+- .count = 4,
+- .entries = {
+- { 250000000, 166667, 0xb4, 0x12 },
+- { 455000000, 166667, 0xfe, 0x11 },
+- { 775500000, 166667, 0xbc, 0x18 },
+- { 999999999, 166667, 0xf4, 0x18 },
+- }
+-};
+-
+ static void opera1_bw(struct dvb_frontend *fe, u8 *buf,
+ const struct dvb_frontend_parameters *params)
+ {
+@@ -560,50 +343,23 @@ static struct dvb_pll_desc dvb_pll_opera1 = {
+ }
+ };
+
+-/* Philips FCV1236D
+- */
+-static struct dvb_pll_desc dvb_pll_fcv1236d = {
+-/* Bit_0: RF Input select
+- * Bit_1: 0=digital, 1=analog
+- */
+- .name = "Philips FCV1236D",
+- .min = 53000000,
+- .max = 803000000,
+- .iffreq= 44000000,
+- .count = 3,
+- .entries = {
+- { 159000000, 62500, 0x8e, 0xa0 },
+- { 453000000, 62500, 0x8e, 0x90 },
+- { 999999999, 62500, 0x8e, 0x30 },
+- },
+-};
+-
+ /* ----------------------------------------------------------- */
+
+ static struct dvb_pll_desc *pll_list[] = {
+ [DVB_PLL_UNDEFINED] = NULL,
+ [DVB_PLL_THOMSON_DTT7579] = &dvb_pll_thomson_dtt7579,
+ [DVB_PLL_THOMSON_DTT759X] = &dvb_pll_thomson_dtt759x,
+- [DVB_PLL_THOMSON_DTT7610] = &dvb_pll_thomson_dtt7610,
+ [DVB_PLL_LG_Z201] = &dvb_pll_lg_z201,
+- [DVB_PLL_MICROTUNE_4042] = &dvb_pll_microtune_4042,
+- [DVB_PLL_THOMSON_DTT761X] = &dvb_pll_thomson_dtt761x,
+ [DVB_PLL_UNKNOWN_1] = &dvb_pll_unknown_1,
+ [DVB_PLL_TUA6010XS] = &dvb_pll_tua6010xs,
+ [DVB_PLL_ENV57H1XD5] = &dvb_pll_env57h1xd5,
+ [DVB_PLL_TUA6034] = &dvb_pll_tua6034,
+- [DVB_PLL_LG_TDVS_H06XF] = &dvb_pll_lg_tdvs_h06xf,
+ [DVB_PLL_TDA665X] = &dvb_pll_tda665x,
+- [DVB_PLL_FMD1216ME] = &dvb_pll_fmd1216me,
+ [DVB_PLL_TDED4] = &dvb_pll_tded4,
+- [DVB_PLL_TUV1236D] = &dvb_pll_tuv1236d,
+ [DVB_PLL_TDHU2] = &dvb_pll_tdhu2,
+ [DVB_PLL_SAMSUNG_TBMV] = &dvb_pll_samsung_tbmv,
+ [DVB_PLL_PHILIPS_SD1878_TDA8261] = &dvb_pll_philips_sd1878_tda8261,
+- [DVB_PLL_PHILIPS_TD1316] = &dvb_pll_philips_td1316,
+- [DVB_PLL_THOMSON_FE6600] = &dvb_pll_thomson_fe6600,
+ [DVB_PLL_OPERA1] = &dvb_pll_opera1,
+- [DVB_PLL_FCV1236D] = &dvb_pll_fcv1236d,
+ };
+
+ /* ----------------------------------------------------------- */
+@@ -849,20 +605,6 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
+ id[priv->nr] == pll_desc_id ?
+ "insmod option" : "autodetected");
+ }
+- if ((debug) || (input[priv->nr] > 0)) {
+- printk("dvb-pll[%d]", priv->nr);
+- if (i2c != NULL)
+- printk(" %d-%04x", i2c_adapter_id(i2c), pll_addr);
+- printk(": tuner rf input will be ");
+- switch (input[priv->nr]) {
+- case 0:
+- printk("autoselected\n");
+- break;
+- default:
+- printk("set to input %d (insmod option)\n",
+- input[priv->nr]);
+- }
+- }
+
+ return fe;
+ }
+diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h
+index e93a810..872ca29 100644
+--- a/drivers/media/dvb/frontends/dvb-pll.h
++++ b/drivers/media/dvb/frontends/dvb-pll.h
+@@ -11,26 +11,17 @@
+ #define DVB_PLL_UNDEFINED 0
+ #define DVB_PLL_THOMSON_DTT7579 1
+ #define DVB_PLL_THOMSON_DTT759X 2
+-#define DVB_PLL_THOMSON_DTT7610 3
+-#define DVB_PLL_LG_Z201 4
+-#define DVB_PLL_MICROTUNE_4042 5
+-#define DVB_PLL_THOMSON_DTT761X 6
+-#define DVB_PLL_UNKNOWN_1 7
+-#define DVB_PLL_TUA6010XS 8
+-#define DVB_PLL_ENV57H1XD5 9
+-#define DVB_PLL_TUA6034 10
+-#define DVB_PLL_LG_TDVS_H06XF 11
+-#define DVB_PLL_TDA665X 12
+-#define DVB_PLL_FMD1216ME 13
+-#define DVB_PLL_TDED4 14
+-#define DVB_PLL_TUV1236D 15
+-#define DVB_PLL_TDHU2 16
+-#define DVB_PLL_SAMSUNG_TBMV 17
+-#define DVB_PLL_PHILIPS_SD1878_TDA8261 18
+-#define DVB_PLL_PHILIPS_TD1316 19
+-#define DVB_PLL_THOMSON_FE6600 20
+-#define DVB_PLL_OPERA1 21
+-#define DVB_PLL_FCV1236D 22
++#define DVB_PLL_LG_Z201 3
++#define DVB_PLL_UNKNOWN_1 4
++#define DVB_PLL_TUA6010XS 5
++#define DVB_PLL_ENV57H1XD5 6
++#define DVB_PLL_TUA6034 7
++#define DVB_PLL_TDA665X 8
++#define DVB_PLL_TDED4 9
++#define DVB_PLL_TDHU2 10
++#define DVB_PLL_SAMSUNG_TBMV 11
++#define DVB_PLL_PHILIPS_SD1878_TDA8261 12
++#define DVB_PLL_OPERA1 13
+
+ /**
+ * Attach a dvb-pll to the supplied frontend structure.
+@@ -52,7 +43,7 @@ static inline struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ unsigned int pll_desc_id)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif
+diff --git a/drivers/media/dvb/frontends/isl6405.c b/drivers/media/dvb/frontends/isl6405.c
+new file mode 100644
+index 0000000..33d33f4
+--- /dev/null
++++ b/drivers/media/dvb/frontends/isl6405.c
+@@ -0,0 +1,164 @@
++/*
++ * isl6405.c - driver for dual lnb supply and control ic ISL6405
++ *
++ * Copyright (C) 2008 Hartmut Hackmann
++ * Copyright (C) 2006 Oliver Endriss
++ *
++ * 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.
++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
++ *
++ *
++ * the project's page is at http://www.linuxtv.org
++ */
++#include <linux/delay.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++
++#include "dvb_frontend.h"
++#include "isl6405.h"
++
++struct isl6405 {
++ u8 config;
++ u8 override_or;
++ u8 override_and;
++ struct i2c_adapter *i2c;
++ u8 i2c_addr;
++};
++
++static int isl6405_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
++{
++ struct isl6405 *isl6405 = (struct isl6405 *) fe->sec_priv;
++ struct i2c_msg msg = { .addr = isl6405->i2c_addr, .flags = 0,
++ .buf = &isl6405->config,
++ .len = sizeof(isl6405->config) };
++
++ if (isl6405->override_or & 0x80) {
++ isl6405->config &= ~(ISL6405_VSEL2 | ISL6405_EN2);
++ switch (voltage) {
++ case SEC_VOLTAGE_OFF:
++ break;
++ case SEC_VOLTAGE_13:
++ isl6405->config |= ISL6405_EN2;
++ break;
++ case SEC_VOLTAGE_18:
++ isl6405->config |= (ISL6405_EN2 | ISL6405_VSEL2);
++ break;
++ default:
++ return -EINVAL;
++ }
++ } else {
++ isl6405->config &= ~(ISL6405_VSEL1 | ISL6405_EN1);
++ switch (voltage) {
++ case SEC_VOLTAGE_OFF:
++ break;
++ case SEC_VOLTAGE_13:
++ isl6405->config |= ISL6405_EN1;
++ break;
++ case SEC_VOLTAGE_18:
++ isl6405->config |= (ISL6405_EN1 | ISL6405_VSEL1);
++ break;
++ default:
++ return -EINVAL;
++ };
++ }
++ isl6405->config |= isl6405->override_or;
++ isl6405->config &= isl6405->override_and;
++
++ return (i2c_transfer(isl6405->i2c, &msg, 1) == 1) ? 0 : -EIO;
++}
++
++static int isl6405_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
++{
++ struct isl6405 *isl6405 = (struct isl6405 *) fe->sec_priv;
++ struct i2c_msg msg = { .addr = isl6405->i2c_addr, .flags = 0,
++ .buf = &isl6405->config,
++ .len = sizeof(isl6405->config) };
++
++ if (isl6405->override_or & 0x80) {
++ if (arg)
++ isl6405->config |= ISL6405_LLC2;
++ else
++ isl6405->config &= ~ISL6405_LLC2;
++ } else {
++ if (arg)
++ isl6405->config |= ISL6405_LLC1;
++ else
++ isl6405->config &= ~ISL6405_LLC1;
++ }
++ isl6405->config |= isl6405->override_or;
++ isl6405->config &= isl6405->override_and;
++
++ return (i2c_transfer(isl6405->i2c, &msg, 1) == 1) ? 0 : -EIO;
++}
++
++static void isl6405_release(struct dvb_frontend *fe)
++{
++ /* power off */
++ isl6405_set_voltage(fe, SEC_VOLTAGE_OFF);
++
++ /* free */
++ kfree(fe->sec_priv);
++ fe->sec_priv = NULL;
++}
++
++struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c,
++ u8 i2c_addr, u8 override_set, u8 override_clear)
++{
++ struct isl6405 *isl6405 = kmalloc(sizeof(struct isl6405), GFP_KERNEL);
++ if (!isl6405)
++ return NULL;
++
++ /* default configuration */
++ if (override_set & 0x80)
++ isl6405->config = ISL6405_ISEL2;
++ else
++ isl6405->config = ISL6405_ISEL1;
++ isl6405->i2c = i2c;
++ isl6405->i2c_addr = i2c_addr;
++ fe->sec_priv = isl6405;
++
++ /* bits which should be forced to '1' */
++ isl6405->override_or = override_set;
++
++ /* bits which should be forced to '0' */
++ isl6405->override_and = ~override_clear;
++
++ /* detect if it is present or not */
++ if (isl6405_set_voltage(fe, SEC_VOLTAGE_OFF)) {
++ kfree(isl6405);
++ fe->sec_priv = NULL;
++ return NULL;
++ }
++
++ /* install release callback */
++ fe->ops.release_sec = isl6405_release;
++
++ /* override frontend ops */
++ fe->ops.set_voltage = isl6405_set_voltage;
++ fe->ops.enable_high_lnb_voltage = isl6405_enable_high_lnb_voltage;
++
++ return fe;
++}
++EXPORT_SYMBOL(isl6405_attach);
++
++MODULE_DESCRIPTION("Driver for lnb supply and control ic isl6405");
++MODULE_AUTHOR("Hartmut Hackmann & Oliver Endriss");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/dvb/frontends/isl6405.h b/drivers/media/dvb/frontends/isl6405.h
+new file mode 100644
+index 0000000..1c793d3
+--- /dev/null
++++ b/drivers/media/dvb/frontends/isl6405.h
+@@ -0,0 +1,74 @@
++/*
++ * isl6405.h - driver for dual lnb supply and control ic ISL6405
++ *
++ * Copyright (C) 2008 Hartmut Hackmann
++ * Copyright (C) 2006 Oliver Endriss
++ *
++ * 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.
++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
++ *
++ *
++ * the project's page is at http://www.linuxtv.org
++ */
++
++#ifndef _ISL6405_H
++#define _ISL6405_H
++
++#include <linux/dvb/frontend.h>
++
++/* system register bits */
++
++/* this bit selects register (control) 1 or 2
++ note that the bit maps are different */
++
++#define ISL6405_SR 0x80
++
++/* SR = 0 */
++#define ISL6405_OLF1 0x01
++#define ISL6405_EN1 0x02
++#define ISL6405_VSEL1 0x04
++#define ISL6405_LLC1 0x08
++#define ISL6405_ENT1 0x10
++#define ISL6405_ISEL1 0x20
++#define ISL6405_DCL 0x40
++
++/* SR = 1 */
++#define ISL6405_OLF2 0x01
++#define ISL6405_OTF 0x02
++#define ISL6405_EN2 0x04
++#define ISL6405_VSEL2 0x08
++#define ISL6405_LLC2 0x10
++#define ISL6405_ENT2 0x20
++#define ISL6405_ISEL2 0x40
++
++#if defined(CONFIG_DVB_ISL6405) || (defined(CONFIG_DVB_ISL6405_MODULE) && defined(MODULE))
++/* override_set and override_clear control which system register bits (above)
++ * to always set & clear
++ */
++extern struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c,
++ u8 i2c_addr, u8 override_set, u8 override_clear);
++#else
++static inline struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe,
++ struct i2c_adapter *i2c, u8 i2c_addr,
++ u8 override_set, u8 override_clear)
++{
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++ return NULL;
++}
++#endif /* CONFIG_DVB_ISL6405 */
++
++#endif
+diff --git a/drivers/media/dvb/frontends/isl6421.h b/drivers/media/dvb/frontends/isl6421.h
+index ea7f78a..47e4518 100644
+--- a/drivers/media/dvb/frontends/isl6421.h
++++ b/drivers/media/dvb/frontends/isl6421.h
+@@ -47,7 +47,7 @@ extern struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_a
+ static inline struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
+ u8 override_set, u8 override_clear)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_ISL6421
+diff --git a/drivers/media/dvb/frontends/itd1000.c b/drivers/media/dvb/frontends/itd1000.c
+new file mode 100644
+index 0000000..04c562c
+--- /dev/null
++++ b/drivers/media/dvb/frontends/itd1000.c
+@@ -0,0 +1,400 @@
++/*
++ * Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
++ *
++ * Copyright (c) 2007-8 Patrick Boettcher <pb at linuxtv.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/delay.h>
++#include <linux/dvb/frontend.h>
++#include <linux/i2c.h>
++
++#include "dvb_frontend.h"
++
++#include "itd1000.h"
++#include "itd1000_priv.h"
++
++static int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
++
++#define deb(args...) do { \
++ if (debug) { \
++ printk(KERN_DEBUG "ITD1000: " args);\
++ printk("\n"); \
++ } \
++} while (0)
++
++#define warn(args...) do { \
++ printk(KERN_WARNING "ITD1000: " args); \
++ printk("\n"); \
++} while (0)
++
++#define info(args...) do { \
++ printk(KERN_INFO "ITD1000: " args); \
++ printk("\n"); \
++} while (0)
++
++/* don't write more than one byte with flexcop behind */
++static int itd1000_write_regs(struct itd1000_state *state, u8 reg, u8 v[], u8 len)
++{
++ u8 buf[1+len];
++ struct i2c_msg msg = {
++ .addr = state->cfg->i2c_address, .flags = 0, .buf = buf, .len = len+1
++ };
++ buf[0] = reg;
++ memcpy(&buf[1], v, len);
++
++ /* deb("wr %02x: %02x", reg, v[0]); */
++
++ if (i2c_transfer(state->i2c, &msg, 1) != 1) {
++ printk(KERN_WARNING "itd1000 I2C write failed\n");
++ return -EREMOTEIO;
++ }
++ return 0;
++}
++
++static int itd1000_read_reg(struct itd1000_state *state, u8 reg)
++{
++ u8 val;
++ struct i2c_msg msg[2] = {
++ { .addr = state->cfg->i2c_address, .flags = 0, .buf = ®, .len = 1 },
++ { .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = &val, .len = 1 },
++ };
++
++ /* ugly flexcop workaround */
++ itd1000_write_regs(state, (reg - 1) & 0xff, &state->shadow[(reg - 1) & 0xff], 1);
++
++ if (i2c_transfer(state->i2c, msg, 2) != 2) {
++ warn("itd1000 I2C read failed");
++ return -EREMOTEIO;
++ }
++ return val;
++}
++
++static inline int itd1000_write_reg(struct itd1000_state *state, u8 r, u8 v)
++{
++ int ret = itd1000_write_regs(state, r, &v, 1);
++ state->shadow[r] = v;
++ return ret;
++}
++
++
++static struct {
++ u32 symbol_rate;
++ u8 pgaext : 4; /* PLLFH */
++ u8 bbgvmin : 4; /* BBGVMIN */
++} itd1000_lpf_pga[] = {
++ { 0, 0x8, 0x3 },
++ { 5200000, 0x8, 0x3 },
++ { 12200000, 0x4, 0x3 },
++ { 15400000, 0x2, 0x3 },
++ { 19800000, 0x2, 0x3 },
++ { 21500000, 0x2, 0x3 },
++ { 24500000, 0x2, 0x3 },
++ { 28400000, 0x2, 0x3 },
++ { 33400000, 0x2, 0x3 },
++ { 34400000, 0x1, 0x4 },
++ { 34400000, 0x1, 0x4 },
++ { 38400000, 0x1, 0x4 },
++ { 38400000, 0x1, 0x4 },
++ { 40400000, 0x1, 0x4 },
++ { 45400000, 0x1, 0x4 },
++};
++
++static void itd1000_set_lpf_bw(struct itd1000_state *state, u32 symbol_rate)
++{
++ u8 i;
++ u8 con1 = itd1000_read_reg(state, CON1) & 0xfd;
++ u8 pllfh = itd1000_read_reg(state, PLLFH) & 0x0f;
++ u8 bbgvmin = itd1000_read_reg(state, BBGVMIN) & 0xf0;
++ u8 bw = itd1000_read_reg(state, BW) & 0xf0;
++
++ deb("symbol_rate = %d", symbol_rate);
++
++ /* not sure what is that ? - starting to download the table */
++ itd1000_write_reg(state, CON1, con1 | (1 << 1));
++
++ for (i = 0; i < ARRAY_SIZE(itd1000_lpf_pga); i++)
++ if (symbol_rate < itd1000_lpf_pga[i].symbol_rate) {
++ deb("symrate: index: %d pgaext: %x, bbgvmin: %x", i, itd1000_lpf_pga[i].pgaext, itd1000_lpf_pga[i].bbgvmin);
++ itd1000_write_reg(state, PLLFH, pllfh | (itd1000_lpf_pga[i].pgaext << 4));
++ itd1000_write_reg(state, BBGVMIN, bbgvmin | (itd1000_lpf_pga[i].bbgvmin));
++ itd1000_write_reg(state, BW, bw | (i & 0x0f));
++ break;
++ }
++
++ itd1000_write_reg(state, CON1, con1 | (0 << 1));
++}
++
++static struct {
++ u8 vcorg;
++ u32 fmax_rg;
++} itd1000_vcorg[] = {
++ { 1, 920000 },
++ { 2, 971000 },
++ { 3, 1031000 },
++ { 4, 1091000 },
++ { 5, 1171000 },
++ { 6, 1281000 },
++ { 7, 1381000 },
++ { 8, 500000 }, /* this is intentional. */
++ { 9, 1451000 },
++ { 10, 1531000 },
++ { 11, 1631000 },
++ { 12, 1741000 },
++ { 13, 1891000 },
++ { 14, 2071000 },
++ { 15, 2250000 },
++};
++
++static void itd1000_set_vco(struct itd1000_state *state, u32 freq_khz)
++{
++ u8 i;
++ u8 gvbb_i2c = itd1000_read_reg(state, GVBB_I2C) & 0xbf;
++ u8 vco_chp1_i2c = itd1000_read_reg(state, VCO_CHP1_I2C) & 0x0f;
++ u8 adcout;
++
++ /* reserved bit again (reset ?) */
++ itd1000_write_reg(state, GVBB_I2C, gvbb_i2c | (1 << 6));
++
++ for (i = 0; i < ARRAY_SIZE(itd1000_vcorg); i++) {
++ if (freq_khz < itd1000_vcorg[i].fmax_rg) {
++ itd1000_write_reg(state, VCO_CHP1_I2C, vco_chp1_i2c | (itd1000_vcorg[i].vcorg << 4));
++ msleep(1);
++
++ adcout = itd1000_read_reg(state, PLLLOCK) & 0x0f;
++
++ deb("VCO: %dkHz: %d -> ADCOUT: %d %02x", freq_khz, itd1000_vcorg[i].vcorg, adcout, vco_chp1_i2c);
++
++ if (adcout > 13) {
++ if (!(itd1000_vcorg[i].vcorg == 7 || itd1000_vcorg[i].vcorg == 15))
++ itd1000_write_reg(state, VCO_CHP1_I2C, vco_chp1_i2c | ((itd1000_vcorg[i].vcorg + 1) << 4));
++ } else if (adcout < 2) {
++ if (!(itd1000_vcorg[i].vcorg == 1 || itd1000_vcorg[i].vcorg == 9))
++ itd1000_write_reg(state, VCO_CHP1_I2C, vco_chp1_i2c | ((itd1000_vcorg[i].vcorg - 1) << 4));
++ }
++ break;
++ }
++ }
++}
++
++struct {
++ u32 freq;
++ u8 values[10]; /* RFTR, RFST1 - RFST9 */
++} itd1000_fre_values[] = {
++ { 1075000, { 0x59, 0x1d, 0x1c, 0x17, 0x16, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
++ { 1250000, { 0x89, 0x1e, 0x1d, 0x17, 0x15, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
++ { 1450000, { 0x89, 0x1e, 0x1d, 0x17, 0x15, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
++ { 1650000, { 0x69, 0x1e, 0x1d, 0x17, 0x15, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
++ { 1750000, { 0x69, 0x1e, 0x17, 0x15, 0x14, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
++ { 1850000, { 0x69, 0x1d, 0x17, 0x16, 0x14, 0x0f, 0x0e, 0x0d, 0x0b, 0x0a } },
++ { 1900000, { 0x69, 0x1d, 0x17, 0x15, 0x14, 0x0f, 0x0e, 0x0d, 0x0b, 0x0a } },
++ { 1950000, { 0x69, 0x1d, 0x17, 0x16, 0x14, 0x13, 0x0e, 0x0d, 0x0b, 0x0a } },
++ { 2050000, { 0x69, 0x1e, 0x1d, 0x17, 0x16, 0x14, 0x13, 0x0e, 0x0b, 0x0a } },
++ { 2150000, { 0x69, 0x1d, 0x1c, 0x17, 0x15, 0x14, 0x13, 0x0f, 0x0e, 0x0b } }
++};
++
++
++#define FREF 16
++
++static void itd1000_set_lo(struct itd1000_state *state, u32 freq_khz)
++{
++ int i, j;
++ u32 plln, pllf;
++ u64 tmp;
++
++ plln = (freq_khz * 1000) / 2 / FREF;
++
++ /* Compute the factional part times 1000 */
++ tmp = plln % 1000000;
++ plln /= 1000000;
++
++ tmp *= 1048576;
++ do_div(tmp, 1000000);
++ pllf = (u32) tmp;
++
++ state->frequency = ((plln * 1000) + (pllf * 1000)/1048576) * 2*FREF;
++ deb("frequency: %dkHz (wanted) %dkHz (set), PLLF = %d, PLLN = %d", freq_khz, state->frequency, pllf, plln);
++
++ itd1000_write_reg(state, PLLNH, 0x80); /* PLLNH */;
++ itd1000_write_reg(state, PLLNL, plln & 0xff);
++ itd1000_write_reg(state, PLLFH, (itd1000_read_reg(state, PLLFH) & 0xf0) | ((pllf >> 16) & 0x0f));
++ itd1000_write_reg(state, PLLFM, (pllf >> 8) & 0xff);
++ itd1000_write_reg(state, PLLFL, (pllf >> 0) & 0xff);
++
++ for (i = 0; i < ARRAY_SIZE(itd1000_fre_values); i++) {
++ if (freq_khz <= itd1000_fre_values[i].freq) {
++ deb("fre_values: %d", i);
++ itd1000_write_reg(state, RFTR, itd1000_fre_values[i].values[0]);
++ for (j = 0; j < 9; j++)
++ itd1000_write_reg(state, RFST1+j, itd1000_fre_values[i].values[j+1]);
++ break;
++ }
++ }
++
++ itd1000_set_vco(state, freq_khz);
++}
++
++static int itd1000_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
++{
++ struct itd1000_state *state = fe->tuner_priv;
++ u8 pllcon1;
++
++ itd1000_set_lo(state, p->frequency);
++ itd1000_set_lpf_bw(state, p->u.qpsk.symbol_rate);
++
++ pllcon1 = itd1000_read_reg(state, PLLCON1) & 0x7f;
++ itd1000_write_reg(state, PLLCON1, pllcon1 | (1 << 7));
++ itd1000_write_reg(state, PLLCON1, pllcon1);
++
++ return 0;
++}
++
++static int itd1000_get_frequency(struct dvb_frontend *fe, u32 *frequency)
++{
++ struct itd1000_state *state = fe->tuner_priv;
++ *frequency = state->frequency;
++ return 0;
++}
++
++static int itd1000_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
++{
++ return 0;
++}
++
++static u8 itd1000_init_tab[][2] = {
++ { PLLCON1, 0x65 }, /* Register does not change */
++ { PLLNH, 0x80 }, /* Bits [7:6] do not change */
++ { RESERVED_0X6D, 0x3b },
++ { VCO_CHP2_I2C, 0x12 },
++ { 0x72, 0xf9 }, /* No such regsister defined */
++ { RESERVED_0X73, 0xff },
++ { RESERVED_0X74, 0xb2 },
++ { RESERVED_0X75, 0xc7 },
++ { EXTGVBBRF, 0xf0 },
++ { DIVAGCCK, 0x80 },
++ { BBTR, 0xa0 },
++ { RESERVED_0X7E, 0x4f },
++ { 0x82, 0x88 }, /* No such regsister defined */
++ { 0x83, 0x80 }, /* No such regsister defined */
++ { 0x84, 0x80 }, /* No such regsister defined */
++ { RESERVED_0X85, 0x74 },
++ { RESERVED_0X86, 0xff },
++ { RESERVED_0X88, 0x02 },
++ { RESERVED_0X89, 0x16 },
++ { RFST0, 0x1f },
++ { RESERVED_0X94, 0x66 },
++ { RESERVED_0X95, 0x66 },
++ { RESERVED_0X96, 0x77 },
++ { RESERVED_0X97, 0x99 },
++ { RESERVED_0X98, 0xff },
++ { RESERVED_0X99, 0xfc },
++ { RESERVED_0X9A, 0xba },
++ { RESERVED_0X9B, 0xaa },
++};
++
++static u8 itd1000_reinit_tab[][2] = {
++ { VCO_CHP1_I2C, 0x8a },
++ { BW, 0x87 },
++ { GVBB_I2C, 0x03 },
++ { BBGVMIN, 0x03 },
++ { CON1, 0x2e },
++};
++
++
++static int itd1000_init(struct dvb_frontend *fe)
++{
++ struct itd1000_state *state = fe->tuner_priv;
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(itd1000_init_tab); i++)
++ itd1000_write_reg(state, itd1000_init_tab[i][0], itd1000_init_tab[i][1]);
++
++ for (i = 0; i < ARRAY_SIZE(itd1000_reinit_tab); i++)
++ itd1000_write_reg(state, itd1000_reinit_tab[i][0], itd1000_reinit_tab[i][1]);
++
++ return 0;
++}
++
++static int itd1000_sleep(struct dvb_frontend *fe)
++{
++ return 0;
++}
++
++static int itd1000_release(struct dvb_frontend *fe)
++{
++ kfree(fe->tuner_priv);
++ fe->tuner_priv = NULL;
++ return 0;
++}
++
++static const struct dvb_tuner_ops itd1000_tuner_ops = {
++ .info = {
++ .name = "Integrant ITD1000",
++ .frequency_min = 950000,
++ .frequency_max = 2150000,
++ .frequency_step = 125, /* kHz for QPSK frontends */
++ },
++
++ .release = itd1000_release,
++
++ .init = itd1000_init,
++ .sleep = itd1000_sleep,
++
++ .set_params = itd1000_set_parameters,
++ .get_frequency = itd1000_get_frequency,
++ .get_bandwidth = itd1000_get_bandwidth
++};
++
++
++struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg)
++{
++ struct itd1000_state *state = NULL;
++ u8 i = 0;
++
++ state = kzalloc(sizeof(struct itd1000_state), GFP_KERNEL);
++ if (state == NULL)
++ return NULL;
++
++ state->cfg = cfg;
++ state->i2c = i2c;
++
++ i = itd1000_read_reg(state, 0);
++ if (i != 0) {
++ kfree(state);
++ return NULL;
++ }
++ info("successfully identified (ID: %d)", i);
++
++ memset(state->shadow, 0xff, sizeof(state->shadow));
++ for (i = 0x65; i < 0x9c; i++)
++ state->shadow[i] = itd1000_read_reg(state, i);
++
++ memcpy(&fe->ops.tuner_ops, &itd1000_tuner_ops, sizeof(struct dvb_tuner_ops));
++
++ fe->tuner_priv = state;
++
++ return fe;
++}
++EXPORT_SYMBOL(itd1000_attach);
++
++MODULE_AUTHOR("Patrick Boettcher <pb at linuxtv.org>");
++MODULE_DESCRIPTION("Integrant ITD1000 driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/dvb/frontends/itd1000.h b/drivers/media/dvb/frontends/itd1000.h
+new file mode 100644
+index 0000000..5e18df0
+--- /dev/null
++++ b/drivers/media/dvb/frontends/itd1000.h
+@@ -0,0 +1,42 @@
++/*
++ * Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
++ *
++ * Copyright (c) 2007 Patrick Boettcher <pb at linuxtv.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
++ */
++
++#ifndef ITD1000_H
++#define ITD1000_H
++
++struct dvb_frontend;
++struct i2c_adapter;
++
++struct itd1000_config {
++ u8 i2c_address;
++};
++
++#if defined(CONFIG_DVB_TUNER_ITD1000) || (defined(CONFIG_DVB_TUNER_ITD1000_MODULE) && defined(MODULE))
++extern struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg);
++#else
++static inline struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg)
++{
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++ return NULL;
++}
++#endif
++
++#endif
+diff --git a/drivers/media/dvb/frontends/itd1000_priv.h b/drivers/media/dvb/frontends/itd1000_priv.h
+new file mode 100644
+index 0000000..8cdc54e
+--- /dev/null
++++ b/drivers/media/dvb/frontends/itd1000_priv.h
+@@ -0,0 +1,88 @@
++/*
++ * Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
++ *
++ * Copyright (c) 2007 Patrick Boettcher <pb at linuxtv.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
++ */
++
++#ifndef ITD1000_PRIV_H
++#define ITD1000_PRIV_H
++
++struct itd1000_state {
++ struct itd1000_config *cfg;
++ struct i2c_adapter *i2c;
++
++ u32 frequency; /* contains the value resulting from the LO-setting */
++
++ /* ugly workaround for flexcop's incapable i2c-controller
++ * FIXME, if possible
++ */
++ u8 shadow[255];
++};
++
++enum itd1000_register {
++ VCO_CHP1 = 0x65,
++ VCO_CHP2,
++ PLLCON1,
++ PLLNH,
++ PLLNL,
++ PLLFH,
++ PLLFM,
++ PLLFL,
++ RESERVED_0X6D,
++ PLLLOCK,
++ VCO_CHP2_I2C,
++ VCO_CHP1_I2C,
++ BW,
++ RESERVED_0X73 = 0x73,
++ RESERVED_0X74,
++ RESERVED_0X75,
++ GVBB,
++ GVRF,
++ GVBB_I2C,
++ EXTGVBBRF,
++ DIVAGCCK,
++ BBTR,
++ RFTR,
++ BBGVMIN,
++ RESERVED_0X7E,
++ RESERVED_0X85 = 0x85,
++ RESERVED_0X86,
++ CON1,
++ RESERVED_0X88,
++ RESERVED_0X89,
++ RFST0,
++ RFST1,
++ RFST2,
++ RFST3,
++ RFST4,
++ RFST5,
++ RFST6,
++ RFST7,
++ RFST8,
++ RFST9,
++ RESERVED_0X94,
++ RESERVED_0X95,
++ RESERVED_0X96,
++ RESERVED_0X97,
++ RESERVED_0X98,
++ RESERVED_0X99,
++ RESERVED_0X9A,
++ RESERVED_0X9B,
++};
++
++#endif
+diff --git a/drivers/media/dvb/frontends/l64781.c b/drivers/media/dvb/frontends/l64781.c
+index 443d904..e1e70e9 100644
+--- a/drivers/media/dvb/frontends/l64781.c
++++ b/drivers/media/dvb/frontends/l64781.c
+@@ -57,7 +57,7 @@ static int l64781_writereg (struct l64781_state* state, u8 reg, u8 data)
+
+ if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1)
+ dprintk ("%s: write_reg error (reg == %02x) = %02x!\n",
+- __FUNCTION__, reg, ret);
++ __func__, reg, ret);
+
+ return (ret != 1) ? -1 : 0;
+ }
+diff --git a/drivers/media/dvb/frontends/l64781.h b/drivers/media/dvb/frontends/l64781.h
+index cd15f76..1305a9e 100644
+--- a/drivers/media/dvb/frontends/l64781.h
++++ b/drivers/media/dvb/frontends/l64781.h
+@@ -38,7 +38,7 @@ extern struct dvb_frontend* l64781_attach(const struct l64781_config* config,
+ static inline struct dvb_frontend* l64781_attach(const struct l64781_config* config,
+ struct i2c_adapter* i2c)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_L64781
+diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c
+index bdc9fa8..f0195c8 100644
+--- a/drivers/media/dvb/frontends/lgdt330x.c
++++ b/drivers/media/dvb/frontends/lgdt330x.c
+@@ -49,7 +49,7 @@
+ /* Use Equalizer Mean Squared Error instead of Phaser Tracker MSE */
+ /* #define USE_EQMSE */
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off).");
+ #define dprintk(args...) \
+@@ -88,7 +88,7 @@ static int i2c_write_demod_bytes (struct lgdt330x_state* state,
+
+ for (i=0; i<len-1; i+=2){
+ if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+- printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __FUNCTION__, msg.buf[0], msg.buf[1], err);
++ printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __func__, msg.buf[0], msg.buf[1], err);
+ if (err < 0)
+ return err;
+ else
+@@ -117,7 +117,7 @@ static u8 i2c_read_demod_bytes (struct lgdt330x_state* state,
+ int ret;
+ ret = i2c_transfer(state->i2c, msg, 2);
+ if (ret != 2) {
+- printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __FUNCTION__, state->config->demod_address, reg, ret);
++ printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __func__, state->config->demod_address, reg, ret);
+ } else {
+ ret = 0;
+ }
+@@ -256,7 +256,7 @@ static int lgdt330x_init(struct dvb_frontend* fe)
+ printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n");
+ err = -ENODEV;
+ }
+- dprintk("%s entered as %s\n", __FUNCTION__, chip_name);
++ dprintk("%s entered as %s\n", __func__, chip_name);
+ if (err < 0)
+ return err;
+ return lgdt330x_SwReset(state);
+@@ -334,7 +334,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
+ if (state->current_modulation != param->u.vsb.modulation) {
+ switch(param->u.vsb.modulation) {
+ case VSB_8:
+- dprintk("%s: VSB_8 MODE\n", __FUNCTION__);
++ dprintk("%s: VSB_8 MODE\n", __func__);
+
+ /* Select VSB mode */
+ top_ctrl_cfg[1] = 0x03;
+@@ -350,7 +350,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
+ break;
+
+ case QAM_64:
+- dprintk("%s: QAM_64 MODE\n", __FUNCTION__);
++ dprintk("%s: QAM_64 MODE\n", __func__);
+
+ /* Select QAM_64 mode */
+ top_ctrl_cfg[1] = 0x00;
+@@ -366,7 +366,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
+ break;
+
+ case QAM_256:
+- dprintk("%s: QAM_256 MODE\n", __FUNCTION__);
++ dprintk("%s: QAM_256 MODE\n", __func__);
+
+ /* Select QAM_256 mode */
+ top_ctrl_cfg[1] = 0x01;
+@@ -381,7 +381,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
+ }
+ break;
+ default:
+- printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __FUNCTION__, param->u.vsb.modulation);
++ printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __func__, param->u.vsb.modulation);
+ return -1;
+ }
+ /*
+@@ -431,7 +431,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
+
+ /* AGC status register */
+ i2c_read_demod_bytes(state, AGC_STATUS, buf, 1);
+- dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
++ dprintk("%s: AGC_STATUS = 0x%02x\n", __func__, buf[0]);
+ if ((buf[0] & 0x0c) == 0x8){
+ /* Test signal does not exist flag */
+ /* as well as the AGC lock flag. */
+@@ -445,7 +445,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ */
+ /* signal status */
+ i2c_read_demod_bytes(state, TOP_CONTROL, buf, sizeof(buf));
+- dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __FUNCTION__, buf[0], buf[1], buf[2]);
++ dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __func__, buf[0], buf[1], buf[2]);
+
+
+ /* sync status */
+@@ -461,7 +461,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
+
+ /* Carrier Recovery Lock Status Register */
+ i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
+- dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
++ dprintk("%s: CARRIER_LOCK = 0x%02x\n", __func__, buf[0]);
+ switch (state->current_modulation) {
+ case QAM_256:
+ case QAM_64:
+@@ -474,7 +474,7 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ *status |= FE_HAS_CARRIER;
+ break;
+ default:
+- printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
++ printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __func__);
+ }
+
+ return 0;
+@@ -493,7 +493,7 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ if (err < 0)
+ return err;
+
+- dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
++ dprintk("%s: AGC_STATUS = 0x%02x\n", __func__, buf[0]);
+ if ((buf[0] & 0x21) == 0x01){
+ /* Test input signal does not exist flag */
+ /* as well as the AGC lock flag. */
+@@ -502,7 +502,7 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
+
+ /* Carrier Recovery Lock Status Register */
+ i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
+- dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
++ dprintk("%s: CARRIER_LOCK = 0x%02x\n", __func__, buf[0]);
+ switch (state->current_modulation) {
+ case QAM_256:
+ case QAM_64:
+@@ -533,7 +533,7 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ }
+ break;
+ default:
+- printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __FUNCTION__);
++ printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __func__);
+ }
+ return 0;
+ }
+@@ -607,14 +607,14 @@ static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr)
+ break;
+ default:
+ printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
+- __FUNCTION__);
++ __func__);
+ return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
+ }
+
+ state->snr = calculate_snr(noise, c);
+ *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
+
+- dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
++ dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise,
+ state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
+
+ return 0;
+@@ -651,14 +651,14 @@ static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
+ break;
+ default:
+ printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
+- __FUNCTION__);
++ __func__);
+ return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
+ }
+
+ state->snr = calculate_snr(noise, c);
+ *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
+
+- dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
++ dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise,
+ state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16);
+
+ return 0;
+@@ -743,7 +743,7 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
+
+ error:
+ kfree(state);
+- dprintk("%s: ERROR\n",__FUNCTION__);
++ dprintk("%s: ERROR\n",__func__);
+ return NULL;
+ }
+
+diff --git a/drivers/media/dvb/frontends/lgdt330x.h b/drivers/media/dvb/frontends/lgdt330x.h
+index 9950590..9012504 100644
+--- a/drivers/media/dvb/frontends/lgdt330x.h
++++ b/drivers/media/dvb/frontends/lgdt330x.h
+@@ -59,7 +59,7 @@ extern struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config
+ static inline struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
+ struct i2c_adapter* i2c)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_LGDT330X
+diff --git a/drivers/media/dvb/frontends/lnbp21.h b/drivers/media/dvb/frontends/lnbp21.h
+index 68906ac..8fe094b 100644
+--- a/drivers/media/dvb/frontends/lnbp21.h
++++ b/drivers/media/dvb/frontends/lnbp21.h
+@@ -45,7 +45,7 @@ extern struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_ad
+ #else
+ static inline struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_LNBP21
+diff --git a/drivers/media/dvb/frontends/mt2060.h b/drivers/media/dvb/frontends/mt2060.h
+index 0a86eab..acba005 100644
+--- a/drivers/media/dvb/frontends/mt2060.h
++++ b/drivers/media/dvb/frontends/mt2060.h
+@@ -35,7 +35,7 @@ extern struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_a
+ #else
+ static inline struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_TUNER_MT2060
+diff --git a/drivers/media/dvb/frontends/mt2131.c b/drivers/media/dvb/frontends/mt2131.c
+index 13cf166..e254bcf 100644
+--- a/drivers/media/dvb/frontends/mt2131.c
++++ b/drivers/media/dvb/frontends/mt2131.c
+@@ -110,7 +110,7 @@ static int mt2131_set_params(struct dvb_frontend *fe,
+ priv->bandwidth = 0;
+
+ freq = params->frequency / 1000; // Hz -> kHz
+- dprintk(1, "%s() freq=%d\n", __FUNCTION__, freq);
++ dprintk(1, "%s() freq=%d\n", __func__, freq);
+
+ f_lo1 = freq + MT2131_IF1 * 1000;
+ f_lo1 = (f_lo1 / 250) * 250;
+@@ -187,7 +187,7 @@ static int mt2131_set_params(struct dvb_frontend *fe,
+ static int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+ {
+ struct mt2131_priv *priv = fe->tuner_priv;
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+ *frequency = priv->frequency;
+ return 0;
+ }
+@@ -195,7 +195,7 @@ static int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+ static int mt2131_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+ {
+ struct mt2131_priv *priv = fe->tuner_priv;
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+ *bandwidth = priv->bandwidth;
+ return 0;
+ }
+@@ -214,7 +214,7 @@ static int mt2131_get_status(struct dvb_frontend *fe, u32 *status)
+
+ mt2131_readreg(priv, 0x09, &afc_status);
+ dprintk(1, "%s() - LO Status = 0x%x, AFC Status = 0x%x\n",
+- __FUNCTION__, lock_status, afc_status);
++ __func__, lock_status, afc_status);
+
+ return 0;
+ }
+@@ -223,7 +223,7 @@ static int mt2131_init(struct dvb_frontend *fe)
+ {
+ struct mt2131_priv *priv = fe->tuner_priv;
+ int ret;
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+
+ if ((ret = mt2131_writeregs(priv, mt2131_config1,
+ sizeof(mt2131_config1))) < 0)
+@@ -243,7 +243,7 @@ static int mt2131_init(struct dvb_frontend *fe)
+
+ static int mt2131_release(struct dvb_frontend *fe)
+ {
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+ kfree(fe->tuner_priv);
+ fe->tuner_priv = NULL;
+ return 0;
+@@ -273,7 +273,7 @@ struct dvb_frontend * mt2131_attach(struct dvb_frontend *fe,
+ struct mt2131_priv *priv = NULL;
+ u8 id = 0;
+
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+
+ priv = kzalloc(sizeof(struct mt2131_priv), GFP_KERNEL);
+ if (priv == NULL)
+diff --git a/drivers/media/dvb/frontends/mt2131.h b/drivers/media/dvb/frontends/mt2131.h
+index 1e4ffe7..606d857 100644
+--- a/drivers/media/dvb/frontends/mt2131.h
++++ b/drivers/media/dvb/frontends/mt2131.h
+@@ -41,7 +41,7 @@ static inline struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe,
+ struct mt2131_config *cfg,
+ u16 if1)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif /* CONFIG_DVB_TUNER_MT2131 */
+diff --git a/drivers/media/dvb/frontends/mt2266.h b/drivers/media/dvb/frontends/mt2266.h
+index f31dd61..c5113ef 100644
+--- a/drivers/media/dvb/frontends/mt2266.h
++++ b/drivers/media/dvb/frontends/mt2266.h
+@@ -29,7 +29,7 @@ extern struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_a
+ #else
+ static inline struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_TUNER_MT2266
+diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c
+index 1638301..081ca33 100644
+--- a/drivers/media/dvb/frontends/mt312.c
++++ b/drivers/media/dvb/frontends/mt312.c
+@@ -1,7 +1,8 @@
+ /*
+- Driver for Zarlink VP310/MT312 Satellite Channel Decoder
++ Driver for Zarlink VP310/MT312/ZL10313 Satellite Channel Decoder
+
+ Copyright (C) 2003 Andreas Oberritter <obi at linuxtv.org>
++ Copyright (C) 2008 Matthias Schwarzott <zzam at gentoo.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+@@ -43,7 +44,8 @@ struct mt312_state {
+ struct dvb_frontend frontend;
+
+ u8 id;
+- u8 frequency;
++ unsigned long xtal;
++ u8 freq_mult;
+ };
+
+ static int debug;
+@@ -53,12 +55,11 @@ static int debug;
+ printk(KERN_DEBUG "mt312: " args); \
+ } while (0)
+
+-#define MT312_SYS_CLK 90000000UL /* 90 MHz */
+-#define MT312_LPOWER_SYS_CLK 60000000UL /* 60 MHz */
+ #define MT312_PLL_CLK 10000000UL /* 10 MHz */
++#define MT312_PLL_CLK_10_111 10111000UL /* 10.111 MHz */
+
+ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
+- void *buf, const size_t count)
++ u8 *buf, const size_t count)
+ {
+ int ret;
+ struct i2c_msg msg[2];
+@@ -76,7 +77,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
+ ret = i2c_transfer(state->i2c, msg, 2);
+
+ if (ret != 2) {
+- printk(KERN_ERR "%s: ret == %d\n", __FUNCTION__, ret);
++ printk(KERN_ERR "%s: ret == %d\n", __func__, ret);
+ return -EREMOTEIO;
+ }
+
+@@ -84,7 +85,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
+ int i;
+ dprintk("R(%d):", reg & 0x7f);
+ for (i = 0; i < count; i++)
+- printk(" %02x", ((const u8 *) buf)[i]);
++ printk(" %02x", buf[i]);
+ printk("\n");
+ }
+
+@@ -92,7 +93,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
+ }
+
+ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
+- const void *src, const size_t count)
++ const u8 *src, const size_t count)
+ {
+ int ret;
+ u8 buf[count + 1];
+@@ -102,7 +103,7 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
+ int i;
+ dprintk("W(%d):", reg & 0x7f);
+ for (i = 0; i < count; i++)
+- printk(" %02x", ((const u8 *) src)[i]);
++ printk(" %02x", src[i]);
+ printk("\n");
+ }
+
+@@ -117,7 +118,7 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
+ ret = i2c_transfer(state->i2c, &msg, 1);
+
+ if (ret != 1) {
+- dprintk("%s: ret == %d\n", __FUNCTION__, ret);
++ dprintk("%s: ret == %d\n", __func__, ret);
+ return -EREMOTEIO;
+ }
+
+@@ -209,7 +210,7 @@ static int mt312_get_symbol_rate(struct mt312_state *state, u32 *sr)
+ dprintk("sym_rat_op=%d dec_ratio=%d\n",
+ sym_rat_op, dec_ratio);
+ dprintk("*sr(manual) = %lu\n",
+- (((MT312_PLL_CLK * 8192) / (sym_rat_op + 8192)) *
++ (((state->xtal * 8192) / (sym_rat_op + 8192)) *
+ 2) - dec_ratio);
+ }
+
+@@ -242,7 +243,7 @@ static int mt312_initfe(struct dvb_frontend *fe)
+
+ /* wake up */
+ ret = mt312_writereg(state, CONFIG,
+- (state->frequency == 60 ? 0x88 : 0x8c));
++ (state->freq_mult == 6 ? 0x88 : 0x8c));
+ if (ret < 0)
+ return ret;
+
+@@ -265,12 +266,37 @@ static int mt312_initfe(struct dvb_frontend *fe)
+ return ret;
+ }
+
++ switch (state->id) {
++ case ID_ZL10313:
++ /* enable ADC */
++ ret = mt312_writereg(state, GPP_CTRL, 0x80);
++ if (ret < 0)
++ return ret;
++
++ /* configure ZL10313 for optimal ADC performance */
++ buf[0] = 0x80;
++ buf[1] = 0xB0;
++ ret = mt312_write(state, HW_CTRL, buf, 2);
++ if (ret < 0)
++ return ret;
++
++ /* enable MPEG output and ADCs */
++ ret = mt312_writereg(state, HW_CTRL, 0x00);
++ if (ret < 0)
++ return ret;
++
++ ret = mt312_writereg(state, MPEG_CTRL, 0x00);
++ if (ret < 0)
++ return ret;
++
++ break;
++ }
++
+ /* SYS_CLK */
+- buf[0] = mt312_div((state->frequency == 60 ? MT312_LPOWER_SYS_CLK :
+- MT312_SYS_CLK) * 2, 1000000);
++ buf[0] = mt312_div(state->xtal * state->freq_mult * 2, 1000000);
+
+ /* DISEQC_RATIO */
+- buf[1] = mt312_div(MT312_PLL_CLK, 15000 * 4);
++ buf[1] = mt312_div(state->xtal, 22000 * 4);
+
+ ret = mt312_write(state, SYS_CLK, buf, sizeof(buf));
+ if (ret < 0)
+@@ -280,7 +306,17 @@ static int mt312_initfe(struct dvb_frontend *fe)
+ if (ret < 0)
+ return ret;
+
+- ret = mt312_writereg(state, OP_CTRL, 0x53);
++ /* different MOCLK polarity */
++ switch (state->id) {
++ case ID_ZL10313:
++ buf[0] = 0x33;
++ break;
++ default:
++ buf[0] = 0x53;
++ break;
++ }
++
++ ret = mt312_writereg(state, OP_CTRL, buf[0]);
+ if (ret < 0)
+ return ret;
+
+@@ -323,6 +359,9 @@ static int mt312_send_master_cmd(struct dvb_frontend *fe,
+ if (ret < 0)
+ return ret;
+
++ /* is there a better way to wait for message to be transmitted */
++ msleep(100);
++
+ /* set DISEQC_MODE[2:0] to zero if a return message is expected */
+ if (c->msg[0] & 0x02) {
+ ret = mt312_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40));
+@@ -383,11 +422,16 @@ static int mt312_set_voltage(struct dvb_frontend *fe, const fe_sec_voltage_t v)
+ {
+ struct mt312_state *state = fe->demodulator_priv;
+ const u8 volt_tab[3] = { 0x00, 0x40, 0x00 };
++ u8 val;
+
+ if (v > SEC_VOLTAGE_OFF)
+ return -EINVAL;
+
+- return mt312_writereg(state, DISEQC_MODE, volt_tab[v]);
++ val = volt_tab[v];
++ if (state->config->voltage_inverted)
++ val ^= 0x40;
++
++ return mt312_writereg(state, DISEQC_MODE, val);
+ }
+
+ static int mt312_read_status(struct dvb_frontend *fe, fe_status_t *s)
+@@ -463,7 +507,7 @@ static int mt312_read_snr(struct dvb_frontend *fe, u16 *snr)
+ int ret;
+ u8 buf[2];
+
+- ret = mt312_read(state, M_SNR_H, &buf, sizeof(buf));
++ ret = mt312_read(state, M_SNR_H, buf, sizeof(buf));
+ if (ret < 0)
+ return ret;
+
+@@ -478,7 +522,7 @@ static int mt312_read_ucblocks(struct dvb_frontend *fe, u32 *ubc)
+ int ret;
+ u8 buf[2];
+
+- ret = mt312_read(state, RS_UBC_H, &buf, sizeof(buf));
++ ret = mt312_read(state, RS_UBC_H, buf, sizeof(buf));
+ if (ret < 0)
+ return ret;
+
+@@ -499,7 +543,7 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
+ { 0x00, 0x01, 0x02, 0x04, 0x3f, 0x08, 0x10, 0x20, 0x3f, 0x3f };
+ const u8 inv_tab[3] = { 0x00, 0x40, 0x80 };
+
+- dprintk("%s: Freq %d\n", __FUNCTION__, p->frequency);
++ dprintk("%s: Freq %d\n", __func__, p->frequency);
+
+ if ((p->frequency < fe->ops.info.frequency_min)
+ || (p->frequency > fe->ops.info.frequency_max))
+@@ -532,17 +576,17 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
+ return ret;
+ if (p->u.qpsk.symbol_rate >= 30000000) {
+ /* Note that 30MS/s should use 90MHz */
+- if ((config_val & 0x0c) == 0x08) {
++ if (state->freq_mult == 6) {
+ /* We are running 60MHz */
+- state->frequency = 90;
++ state->freq_mult = 9;
+ ret = mt312_initfe(fe);
+ if (ret < 0)
+ return ret;
+ }
+ } else {
+- if ((config_val & 0x0c) == 0x0C) {
++ if (state->freq_mult == 9) {
+ /* We are running 90MHz */
+- state->frequency = 60;
++ state->freq_mult = 6;
+ ret = mt312_initfe(fe);
+ if (ret < 0)
+ return ret;
+@@ -551,6 +595,7 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
+ break;
+
+ case ID_MT312:
++ case ID_ZL10313:
+ break;
+
+ default:
+@@ -616,11 +661,29 @@ static int mt312_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+ {
+ struct mt312_state *state = fe->demodulator_priv;
+
+- if (enable) {
+- return mt312_writereg(state, GPP_CTRL, 0x40);
+- } else {
+- return mt312_writereg(state, GPP_CTRL, 0x00);
++ u8 val = 0x00;
++ int ret;
++
++ switch (state->id) {
++ case ID_ZL10313:
++ ret = mt312_readreg(state, GPP_CTRL, &val);
++ if (ret < 0)
++ goto error;
++
++ /* preserve this bit to not accidently shutdown ADC */
++ val &= 0x80;
++ break;
+ }
++
++ if (enable)
++ val |= 0x40;
++ else
++ val &= ~0x40;
++
++ ret = mt312_writereg(state, GPP_CTRL, val);
++
++error:
++ return ret;
+ }
+
+ static int mt312_sleep(struct dvb_frontend *fe)
+@@ -634,6 +697,18 @@ static int mt312_sleep(struct dvb_frontend *fe)
+ if (ret < 0)
+ return ret;
+
++ if (state->id == ID_ZL10313) {
++ /* reset ADC */
++ ret = mt312_writereg(state, GPP_CTRL, 0x00);
++ if (ret < 0)
++ return ret;
++
++ /* full shutdown of ADCs, mpeg bus tristated */
++ ret = mt312_writereg(state, HW_CTRL, 0x0d);
++ if (ret < 0)
++ return ret;
++ }
++
+ ret = mt312_readreg(state, CONFIG, &config);
+ if (ret < 0)
+ return ret;
+@@ -661,6 +736,7 @@ static void mt312_release(struct dvb_frontend *fe)
+ kfree(state);
+ }
+
++#define MT312_SYS_CLK 90000000UL /* 90 MHz */
+ static struct dvb_frontend_ops vp310_mt312_ops = {
+
+ .info = {
+@@ -668,8 +744,8 @@ static struct dvb_frontend_ops vp310_mt312_ops = {
+ .type = FE_QPSK,
+ .frequency_min = 950000,
+ .frequency_max = 2150000,
+- .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128,
+- .symbol_rate_min = MT312_SYS_CLK / 128,
++ .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128, /* FIXME: adjust freq to real used xtal */
++ .symbol_rate_min = MT312_SYS_CLK / 128, /* FIXME as above */
+ .symbol_rate_max = MT312_SYS_CLK / 2,
+ .caps =
+ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
+@@ -726,14 +802,21 @@ struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config,
+ switch (state->id) {
+ case ID_VP310:
+ strcpy(state->frontend.ops.info.name, "Zarlink VP310 DVB-S");
+- state->frequency = 90;
++ state->xtal = MT312_PLL_CLK;
++ state->freq_mult = 9;
+ break;
+ case ID_MT312:
+ strcpy(state->frontend.ops.info.name, "Zarlink MT312 DVB-S");
+- state->frequency = 60;
++ state->xtal = MT312_PLL_CLK;
++ state->freq_mult = 6;
++ break;
++ case ID_ZL10313:
++ strcpy(state->frontend.ops.info.name, "Zarlink ZL10313 DVB-S");
++ state->xtal = MT312_PLL_CLK_10_111;
++ state->freq_mult = 9;
+ break;
+ default:
+- printk(KERN_WARNING "Only Zarlink VP310/MT312"
++ printk(KERN_WARNING "Only Zarlink VP310/MT312/ZL10313"
+ " are supported chips.\n");
+ goto error;
+ }
+@@ -749,7 +832,7 @@ EXPORT_SYMBOL(vp310_mt312_attach);
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+-MODULE_DESCRIPTION("Zarlink VP310/MT312 DVB-S Demodulator driver");
++MODULE_DESCRIPTION("Zarlink VP310/MT312/ZL10313 DVB-S Demodulator driver");
+ MODULE_AUTHOR("Andreas Oberritter <obi at linuxtv.org>");
+ MODULE_LICENSE("GPL");
+
+diff --git a/drivers/media/dvb/frontends/mt312.h b/drivers/media/dvb/frontends/mt312.h
+index f17cb93..de796ea 100644
+--- a/drivers/media/dvb/frontends/mt312.h
++++ b/drivers/media/dvb/frontends/mt312.h
+@@ -31,6 +31,9 @@
+ struct mt312_config {
+ /* the demodulator's i2c address */
+ u8 demod_address;
++
++ /* inverted voltage setting */
++ unsigned int voltage_inverted:1;
+ };
+
+ #if defined(CONFIG_DVB_MT312) || (defined(CONFIG_DVB_MT312_MODULE) && defined(MODULE))
+@@ -40,7 +43,7 @@ struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config,
+ static inline struct dvb_frontend *vp310_mt312_attach(
+ const struct mt312_config *config, struct i2c_adapter *i2c)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif /* CONFIG_DVB_MT312 */
+diff --git a/drivers/media/dvb/frontends/mt312_priv.h b/drivers/media/dvb/frontends/mt312_priv.h
+index 5e0b95b..a3959f9 100644
+--- a/drivers/media/dvb/frontends/mt312_priv.h
++++ b/drivers/media/dvb/frontends/mt312_priv.h
+@@ -110,6 +110,8 @@ enum mt312_reg_addr {
+ VIT_ERRPER_H = 83,
+ VIT_ERRPER_M = 84,
+ VIT_ERRPER_L = 85,
++ HW_CTRL = 84, /* ZL10313 only */
++ MPEG_CTRL = 85, /* ZL10313 only */
+ VIT_SETUP = 86,
+ VIT_REF0 = 87,
+ VIT_REF1 = 88,
+@@ -156,7 +158,8 @@ enum mt312_reg_addr {
+
+ enum mt312_model_id {
+ ID_VP310 = 1,
+- ID_MT312 = 3
++ ID_MT312 = 3,
++ ID_ZL10313 = 5,
+ };
+
+ #endif /* DVB_FRONTENDS_MT312_PRIV */
+diff --git a/drivers/media/dvb/frontends/mt352.c b/drivers/media/dvb/frontends/mt352.c
+index 7cd190b..beba5aa 100644
+--- a/drivers/media/dvb/frontends/mt352.c
++++ b/drivers/media/dvb/frontends/mt352.c
+@@ -95,7 +95,7 @@ static int mt352_read_register(struct mt352_state* state, u8 reg)
+
+ if (ret != 2) {
+ printk("%s: readreg error (reg=%d, ret==%i)\n",
+- __FUNCTION__, reg, ret);
++ __func__, reg, ret);
+ return ret;
+ }
+
+@@ -135,7 +135,7 @@ static void mt352_calc_nominal_rate(struct mt352_state* state,
+ value = 64 * bw * (1<<16) / (7 * 8);
+ value = value * 1000 / adc_clock;
+ dprintk("%s: bw %d, adc_clock %d => 0x%x\n",
+- __FUNCTION__, bw, adc_clock, value);
++ __func__, bw, adc_clock, value);
+ buf[0] = msb(value);
+ buf[1] = lsb(value);
+ }
+@@ -161,7 +161,7 @@ static void mt352_calc_input_freq(struct mt352_state* state,
+ }
+ value = -16374 * ife / adc_clock;
+ dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n",
+- __FUNCTION__, if2, ife, adc_clock, value, value & 0x3fff);
++ __func__, if2, ife, adc_clock, value, value & 0x3fff);
+ buf[0] = msb(value);
+ buf[1] = lsb(value);
+ }
+@@ -521,7 +521,7 @@ static int mt352_init(struct dvb_frontend* fe)
+
+ static u8 mt352_reset_attach [] = { RESET, 0xC0 };
+
+- dprintk("%s: hello\n",__FUNCTION__);
++ dprintk("%s: hello\n",__func__);
+
+ if ((mt352_read_register(state, CLOCK_CTL) & 0x10) == 0 ||
+ (mt352_read_register(state, CONFIG) & 0x20) == 0) {
+diff --git a/drivers/media/dvb/frontends/mt352.h b/drivers/media/dvb/frontends/mt352.h
+index e996408..595092f 100644
+--- a/drivers/media/dvb/frontends/mt352.h
++++ b/drivers/media/dvb/frontends/mt352.h
+@@ -58,7 +58,7 @@ extern struct dvb_frontend* mt352_attach(const struct mt352_config* config,
+ static inline struct dvb_frontend* mt352_attach(const struct mt352_config* config,
+ struct i2c_adapter* i2c)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_MT352
+diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c
+index fcf964f..23d0228 100644
+--- a/drivers/media/dvb/frontends/nxt200x.c
++++ b/drivers/media/dvb/frontends/nxt200x.c
+@@ -74,7 +74,7 @@ static int i2c_writebytes (struct nxt200x_state* state, u8 addr, u8 *buf, u8 len
+
+ if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+ printk (KERN_WARNING "nxt200x: %s: i2c write error (addr 0x%02x, err == %i)\n",
+- __FUNCTION__, addr, err);
++ __func__, addr, err);
+ return -EREMOTEIO;
+ }
+ return 0;
+@@ -87,7 +87,7 @@ static u8 i2c_readbytes (struct nxt200x_state* state, u8 addr, u8* buf, u8 len)
+
+ if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+ printk (KERN_WARNING "nxt200x: %s: i2c read error (addr 0x%02x, err == %i)\n",
+- __FUNCTION__, addr, err);
++ __func__, addr, err);
+ return -EREMOTEIO;
+ }
+ return 0;
+@@ -104,7 +104,7 @@ static int nxt200x_writebytes (struct nxt200x_state* state, u8 reg, u8 *buf, u8
+
+ if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+ printk (KERN_WARNING "nxt200x: %s: i2c write error (addr 0x%02x, err == %i)\n",
+- __FUNCTION__, state->config->demod_address, err);
++ __func__, state->config->demod_address, err);
+ return -EREMOTEIO;
+ }
+ return 0;
+@@ -121,7 +121,7 @@ static u8 nxt200x_readbytes (struct nxt200x_state* state, u8 reg, u8* buf, u8 le
+
+ if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
+ printk (KERN_WARNING "nxt200x: %s: i2c read error (addr 0x%02x, err == %i)\n",
+- __FUNCTION__, state->config->demod_address, err);
++ __func__, state->config->demod_address, err);
+ return -EREMOTEIO;
+ }
+ return 0;
+@@ -146,7 +146,7 @@ static u16 nxt200x_crc(u16 crc, u8 c)
+ static int nxt200x_writereg_multibyte (struct nxt200x_state* state, u8 reg, u8* data, u8 len)
+ {
+ u8 attr, len2, buf;
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ /* set mutli register register */
+ nxt200x_writebytes(state, 0x35, ®, 1);
+@@ -207,7 +207,7 @@ static int nxt200x_readreg_multibyte (struct nxt200x_state* state, u8 reg, u8* d
+ {
+ int i;
+ u8 buf, len2, attr;
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ /* set mutli register register */
+ nxt200x_writebytes(state, 0x35, ®, 1);
+@@ -254,7 +254,7 @@ static int nxt200x_readreg_multibyte (struct nxt200x_state* state, u8 reg, u8* d
+ static void nxt200x_microcontroller_stop (struct nxt200x_state* state)
+ {
+ u8 buf, stopval, counter = 0;
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ /* set correct stop value */
+ switch (state->demod_chip) {
+@@ -287,7 +287,7 @@ static void nxt200x_microcontroller_stop (struct nxt200x_state* state)
+ static void nxt200x_microcontroller_start (struct nxt200x_state* state)
+ {
+ u8 buf;
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ buf = 0x00;
+ nxt200x_writebytes(state, 0x22, &buf, 1);
+@@ -297,7 +297,7 @@ static void nxt2004_microcontroller_init (struct nxt200x_state* state)
+ {
+ u8 buf[9];
+ u8 counter = 0;
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ buf[0] = 0x00;
+ nxt200x_writebytes(state, 0x2b, buf, 1);
+@@ -328,7 +328,7 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)
+ {
+ u8 buf, count = 0;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ dprintk("Tuner Bytes: %02X %02X %02X %02X\n", data[1], data[2], data[3], data[4]);
+
+@@ -387,7 +387,7 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)
+ static void nxt200x_agc_reset(struct nxt200x_state* state)
+ {
+ u8 buf;
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ switch (state->demod_chip) {
+ case NXT2002:
+@@ -416,7 +416,7 @@ static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware
+ u8 buf[3], written = 0, chunkpos = 0;
+ u16 rambase, position, crc = 0;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+ dprintk("Firmware is %zu bytes\n", fw->size);
+
+ /* Get the RAM base for this nxt2002 */
+@@ -483,7 +483,7 @@ static int nxt2004_load_firmware (struct dvb_frontend* fe, const struct firmware
+ u8 buf[3];
+ u16 rambase, position, crc=0;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+ dprintk("Firmware is %zu bytes\n", fw->size);
+
+ /* set rambase */
+diff --git a/drivers/media/dvb/frontends/nxt200x.h b/drivers/media/dvb/frontends/nxt200x.h
+index bb0ef58..f3c8458 100644
+--- a/drivers/media/dvb/frontends/nxt200x.h
++++ b/drivers/media/dvb/frontends/nxt200x.h
+@@ -49,7 +49,7 @@ extern struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
+ static inline struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
+ struct i2c_adapter* i2c)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_NXT200X
+diff --git a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c
+index d313d7d..0eef22d 100644
+--- a/drivers/media/dvb/frontends/nxt6000.c
++++ b/drivers/media/dvb/frontends/nxt6000.c
+@@ -38,7 +38,7 @@ struct nxt6000_state {
+ struct dvb_frontend frontend;
+ };
+
+-static int debug = 0;
++static int debug;
+ #define dprintk if (debug) printk
+
+ static int nxt6000_writereg(struct nxt6000_state* state, u8 reg, u8 data)
+diff --git a/drivers/media/dvb/frontends/nxt6000.h b/drivers/media/dvb/frontends/nxt6000.h
+index 13d2251..878eb38 100644
+--- a/drivers/media/dvb/frontends/nxt6000.h
++++ b/drivers/media/dvb/frontends/nxt6000.h
+@@ -40,7 +40,7 @@ extern struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
+ static inline struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
+ struct i2c_adapter* i2c)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_NXT6000
+diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c
+index 1d2d28c..c7b5785 100644
+--- a/drivers/media/dvb/frontends/or51132.c
++++ b/drivers/media/dvb/frontends/or51132.c
+@@ -91,7 +91,7 @@ static int or51132_writebuf(struct or51132_state *state, const u8 *buf, int len)
+ Less code and more efficient that loading a buffer on the stack with
+ the bytes to send and then calling or51132_writebuf() on that. */
+ #define or51132_writebytes(state, data...) \
+- ({ const static u8 _data[] = {data}; \
++ ({ static const u8 _data[] = {data}; \
+ or51132_writebuf(state, _data, sizeof(_data)); })
+
+ /* Read data from demod into buffer. Returns 0 on success. */
+@@ -132,7 +132,7 @@ static int or51132_readreg(struct or51132_state *state, u8 reg)
+ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
+ {
+ struct or51132_state* state = fe->demodulator_priv;
+- const static u8 run_buf[] = {0x7F,0x01};
++ static const u8 run_buf[] = {0x7F,0x01};
+ u8 rec_buf[8];
+ u32 firmwareAsize, firmwareBsize;
+ int i,ret;
+@@ -419,7 +419,7 @@ static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ *status = 0;
+ return -EREMOTEIO;
+ }
+- dprintk("%s: read_status %04x\n", __FUNCTION__, reg);
++ dprintk("%s: read_status %04x\n", __func__, reg);
+
+ if (reg & 0x0100) /* Receiver Lock */
+ *status = FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI|
+@@ -504,14 +504,14 @@ start:
+ if (retry--) goto start;
+ return -EREMOTEIO;
+ }
+- dprintk("%s: modulation %02x, NTSC rej O%s\n", __FUNCTION__,
++ dprintk("%s: modulation %02x, NTSC rej O%s\n", __func__,
+ reg&0xff, reg&0x1000?"n":"ff");
+
+ /* Calculate SNR using noise, c, and NTSC rejection correction */
+ state->snr = calculate_snr(noise, c) - usK;
+ *snr = (state->snr) >> 16;
+
+- dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
++ dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise,
+ state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
+
+ return 0;
+diff --git a/drivers/media/dvb/frontends/or51132.h b/drivers/media/dvb/frontends/or51132.h
+index add24f0..1b8e04d 100644
+--- a/drivers/media/dvb/frontends/or51132.h
++++ b/drivers/media/dvb/frontends/or51132.h
+@@ -41,7 +41,7 @@ extern struct dvb_frontend* or51132_attach(const struct or51132_config* config,
+ static inline struct dvb_frontend* or51132_attach(const struct or51132_config* config,
+ struct i2c_adapter* i2c)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_OR51132
+diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c
+index 6a6b0d7..7eaa476 100644
+--- a/drivers/media/dvb/frontends/or51211.c
++++ b/drivers/media/dvb/frontends/or51211.c
+@@ -307,19 +307,19 @@ static int or51211_read_snr(struct dvb_frontend* fe, u16* snr)
+
+ if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) {
+ printk(KERN_WARNING "%s: error writing snr reg\n",
+- __FUNCTION__);
++ __func__);
+ return -1;
+ }
+ if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
+ printk(KERN_WARNING "%s: read_status read error\n",
+- __FUNCTION__);
++ __func__);
+ return -1;
+ }
+
+ state->snr = calculate_snr(rec_buf[0], 89599047);
+ *snr = (state->snr) >> 16;
+
+- dprintk("%s: noise = 0x%02x, snr = %d.%02d dB\n", __FUNCTION__, rec_buf[0],
++ dprintk("%s: noise = 0x%02x, snr = %d.%02d dB\n", __func__, rec_buf[0],
+ state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
+
+ return 0;
+diff --git a/drivers/media/dvb/frontends/or51211.h b/drivers/media/dvb/frontends/or51211.h
+index 8aad840..3ce0508 100644
+--- a/drivers/media/dvb/frontends/or51211.h
++++ b/drivers/media/dvb/frontends/or51211.h
+@@ -44,7 +44,7 @@ extern struct dvb_frontend* or51211_attach(const struct or51211_config* config,
+ static inline struct dvb_frontend* or51211_attach(const struct or51211_config* config,
+ struct i2c_adapter* i2c)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_OR51211
+diff --git a/drivers/media/dvb/frontends/qt1010.h b/drivers/media/dvb/frontends/qt1010.h
+index 3ab4aa0..cff6a7c 100644
+--- a/drivers/media/dvb/frontends/qt1010.h
++++ b/drivers/media/dvb/frontends/qt1010.h
+@@ -45,7 +45,7 @@ static inline struct dvb_frontend *qt1010_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ struct qt1010_config *cfg)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_TUNER_QT1010
+diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c
+index 1a4d831..b999ec4 100644
+--- a/drivers/media/dvb/frontends/s5h1409.c
++++ b/drivers/media/dvb/frontends/s5h1409.c
+@@ -48,7 +48,7 @@ struct s5h1409_state {
+ u32 qam_state;
+ };
+
+-static int debug = 0;
++static int debug;
+ #define dprintk if (debug) printk
+
+ /* Register values to initialise the demod, this will set VSB by default */
+@@ -312,7 +312,7 @@ static int s5h1409_writereg(struct s5h1409_state* state, u8 reg, u16 data)
+
+ if (ret != 1)
+ printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
+- "ret == %i)\n", __FUNCTION__, reg, data, ret);
++ "ret == %i)\n", __func__, reg, data, ret);
+
+ return (ret != 1) ? -1 : 0;
+ }
+@@ -332,7 +332,7 @@ static u16 s5h1409_readreg(struct s5h1409_state* state, u8 reg)
+ ret = i2c_transfer(state->i2c, msg, 2);
+
+ if (ret != 2)
+- printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
++ printk("%s: readreg error (ret == %i)\n", __func__, ret);
+ return (b1[0] << 8) | b1[1];
+ }
+
+@@ -340,7 +340,7 @@ static int s5h1409_softreset(struct dvb_frontend* fe)
+ {
+ struct s5h1409_state* state = fe->demodulator_priv;
+
+- dprintk("%s()\n", __FUNCTION__);
++ dprintk("%s()\n", __func__);
+
+ s5h1409_writereg(state, 0xf5, 0);
+ s5h1409_writereg(state, 0xf5, 1);
+@@ -356,7 +356,7 @@ static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz)
+ {
+ struct s5h1409_state* state = fe->demodulator_priv;
+
+- dprintk("%s(%d KHz)\n", __FUNCTION__, KHz);
++ dprintk("%s(%d KHz)\n", __func__, KHz);
+
+ switch (KHz) {
+ case 4000:
+@@ -381,7 +381,7 @@ static int s5h1409_set_spectralinversion(struct dvb_frontend* fe, int inverted)
+ {
+ struct s5h1409_state* state = fe->demodulator_priv;
+
+- dprintk("%s(%d)\n", __FUNCTION__, inverted);
++ dprintk("%s(%d)\n", __func__, inverted);
+
+ if(inverted == 1)
+ return s5h1409_writereg(state, 0x1b, 0x1101); /* Inverted */
+@@ -394,25 +394,25 @@ static int s5h1409_enable_modulation(struct dvb_frontend* fe,
+ {
+ struct s5h1409_state* state = fe->demodulator_priv;
+
+- dprintk("%s(0x%08x)\n", __FUNCTION__, m);
++ dprintk("%s(0x%08x)\n", __func__, m);
+
+ switch(m) {
+ case VSB_8:
+- dprintk("%s() VSB_8\n", __FUNCTION__);
++ dprintk("%s() VSB_8\n", __func__);
+ if (state->if_freq != S5H1409_VSB_IF_FREQ)
+ s5h1409_set_if_freq(fe, S5H1409_VSB_IF_FREQ);
+ s5h1409_writereg(state, 0xf4, 0);
+ break;
+ case QAM_64:
+ case QAM_256:
+- dprintk("%s() QAM_AUTO (64/256)\n", __FUNCTION__);
++ dprintk("%s() QAM_AUTO (64/256)\n", __func__);
+ if (state->if_freq != S5H1409_QAM_IF_FREQ)
+ s5h1409_set_if_freq(fe, S5H1409_QAM_IF_FREQ);
+ s5h1409_writereg(state, 0xf4, 1);
+ s5h1409_writereg(state, 0x85, 0x110);
+ break;
+ default:
+- dprintk("%s() Invalid modulation\n", __FUNCTION__);
++ dprintk("%s() Invalid modulation\n", __func__);
+ return -EINVAL;
+ }
+
+@@ -426,7 +426,7 @@ static int s5h1409_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+ {
+ struct s5h1409_state* state = fe->demodulator_priv;
+
+- dprintk("%s(%d)\n", __FUNCTION__, enable);
++ dprintk("%s(%d)\n", __func__, enable);
+
+ if (enable)
+ return s5h1409_writereg(state, 0xf3, 1);
+@@ -438,7 +438,7 @@ static int s5h1409_set_gpio(struct dvb_frontend* fe, int enable)
+ {
+ struct s5h1409_state* state = fe->demodulator_priv;
+
+- dprintk("%s(%d)\n", __FUNCTION__, enable);
++ dprintk("%s(%d)\n", __func__, enable);
+
+ if (enable)
+ return s5h1409_writereg(state, 0xe3,
+@@ -452,7 +452,7 @@ static int s5h1409_sleep(struct dvb_frontend* fe, int enable)
+ {
+ struct s5h1409_state* state = fe->demodulator_priv;
+
+- dprintk("%s(%d)\n", __FUNCTION__, enable);
++ dprintk("%s(%d)\n", __func__, enable);
+
+ return s5h1409_writereg(state, 0xf2, enable);
+ }
+@@ -461,7 +461,7 @@ static int s5h1409_register_reset(struct dvb_frontend* fe)
+ {
+ struct s5h1409_state* state = fe->demodulator_priv;
+
+- dprintk("%s()\n", __FUNCTION__);
++ dprintk("%s()\n", __func__);
+
+ return s5h1409_writereg(state, 0xfa, 0);
+ }
+@@ -534,7 +534,7 @@ static int s5h1409_set_frontend (struct dvb_frontend* fe,
+ {
+ struct s5h1409_state* state = fe->demodulator_priv;
+
+- dprintk("%s(frequency=%d)\n", __FUNCTION__, p->frequency);
++ dprintk("%s(frequency=%d)\n", __func__, p->frequency);
+
+ s5h1409_softreset(fe);
+
+@@ -565,7 +565,7 @@ static int s5h1409_set_mpeg_timing(struct dvb_frontend *fe, int mode)
+ struct s5h1409_state *state = fe->demodulator_priv;
+ u16 val;
+
+- dprintk("%s(%d)\n", __FUNCTION__, mode);
++ dprintk("%s(%d)\n", __func__, mode);
+
+ val = s5h1409_readreg(state, 0xac) & 0xcfff;
+ switch (mode) {
+@@ -573,7 +573,7 @@ static int s5h1409_set_mpeg_timing(struct dvb_frontend *fe, int mode)
+ val |= 0x0000;
+ break;
+ case S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK:
+- dprintk("%s(%d) Mode1 or Defaulting\n", __FUNCTION__, mode);
++ dprintk("%s(%d) Mode1 or Defaulting\n", __func__, mode);
+ val |= 0x1000;
+ break;
+ case S5H1409_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK:
+@@ -597,7 +597,7 @@ static int s5h1409_init (struct dvb_frontend* fe)
+ int i;
+
+ struct s5h1409_state* state = fe->demodulator_priv;
+- dprintk("%s()\n", __FUNCTION__);
++ dprintk("%s()\n", __func__);
+
+ s5h1409_sleep(fe, 0);
+ s5h1409_register_reset(fe);
+@@ -663,7 +663,7 @@ static int s5h1409_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ break;
+ }
+
+- dprintk("%s() status 0x%08x\n", __FUNCTION__, *status);
++ dprintk("%s() status 0x%08x\n", __func__, *status);
+
+ return 0;
+ }
+@@ -671,7 +671,7 @@ static int s5h1409_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ static int s5h1409_qam256_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
+ {
+ int i, ret = -EINVAL;
+- dprintk("%s()\n", __FUNCTION__);
++ dprintk("%s()\n", __func__);
+
+ for (i=0; i < ARRAY_SIZE(qam256_snr_tab); i++) {
+ if (v < qam256_snr_tab[i].val) {
+@@ -686,7 +686,7 @@ static int s5h1409_qam256_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
+ static int s5h1409_qam64_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
+ {
+ int i, ret = -EINVAL;
+- dprintk("%s()\n", __FUNCTION__);
++ dprintk("%s()\n", __func__);
+
+ for (i=0; i < ARRAY_SIZE(qam64_snr_tab); i++) {
+ if (v < qam64_snr_tab[i].val) {
+@@ -701,7 +701,7 @@ static int s5h1409_qam64_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
+ static int s5h1409_vsb_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
+ {
+ int i, ret = -EINVAL;
+- dprintk("%s()\n", __FUNCTION__);
++ dprintk("%s()\n", __func__);
+
+ for (i=0; i < ARRAY_SIZE(vsb_snr_tab); i++) {
+ if (v > vsb_snr_tab[i].val) {
+@@ -710,7 +710,7 @@ static int s5h1409_vsb_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
+ break;
+ }
+ }
+- dprintk("%s() snr=%d\n", __FUNCTION__, *snr);
++ dprintk("%s() snr=%d\n", __func__, *snr);
+ return ret;
+ }
+
+@@ -718,7 +718,7 @@ static int s5h1409_read_snr(struct dvb_frontend* fe, u16* snr)
+ {
+ struct s5h1409_state* state = fe->demodulator_priv;
+ u16 reg;
+- dprintk("%s()\n", __FUNCTION__);
++ dprintk("%s()\n", __func__);
+
+ switch(state->current_modulation) {
+ case QAM_64:
+@@ -812,7 +812,7 @@ struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
+
+ if (s5h1409_init(&state->frontend) != 0) {
+ printk(KERN_ERR "%s: Failed to initialize correctly\n",
+- __FUNCTION__);
++ __func__);
+ goto error;
+ }
+
+diff --git a/drivers/media/dvb/frontends/s5h1409.h b/drivers/media/dvb/frontends/s5h1409.h
+index f0bb13f..59f4335 100644
+--- a/drivers/media/dvb/frontends/s5h1409.h
++++ b/drivers/media/dvb/frontends/s5h1409.h
+@@ -67,7 +67,7 @@ extern struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
+ static inline struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
+ struct i2c_adapter* i2c)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif /* CONFIG_DVB_S5H1409 */
+diff --git a/drivers/media/dvb/frontends/s5h1411.c b/drivers/media/dvb/frontends/s5h1411.c
+new file mode 100644
+index 0000000..eb5bfc9
+--- /dev/null
++++ b/drivers/media/dvb/frontends/s5h1411.c
+@@ -0,0 +1,888 @@
++/*
++ Samsung S5H1411 VSB/QAM demodulator driver
++
++ Copyright (C) 2008 Steven Toth <stoth at hauppauge.com>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++*/
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include "dvb_frontend.h"
++#include "dvb-pll.h"
++#include "s5h1411.h"
++
++struct s5h1411_state {
++
++ struct i2c_adapter *i2c;
++
++ /* configuration settings */
++ const struct s5h1411_config *config;
++
++ struct dvb_frontend frontend;
++
++ fe_modulation_t current_modulation;
++
++ u32 current_frequency;
++ int if_freq;
++
++ u8 inversion;
++};
++
++static int debug;
++
++#define dprintk(arg...) do { \
++ if (debug) \
++ printk(arg); \
++ } while (0)
++
++/* Register values to initialise the demod, defaults to VSB */
++static struct init_tab {
++ u8 addr;
++ u8 reg;
++ u16 data;
++} init_tab[] = {
++ { S5H1411_I2C_TOP_ADDR, 0x00, 0x0071, },
++ { S5H1411_I2C_TOP_ADDR, 0x08, 0x0047, },
++ { S5H1411_I2C_TOP_ADDR, 0x1c, 0x0400, },
++ { S5H1411_I2C_TOP_ADDR, 0x1e, 0x0370, },
++ { S5H1411_I2C_TOP_ADDR, 0x1f, 0x342a, },
++ { S5H1411_I2C_TOP_ADDR, 0x24, 0x0231, },
++ { S5H1411_I2C_TOP_ADDR, 0x25, 0x1011, },
++ { S5H1411_I2C_TOP_ADDR, 0x26, 0x0f07, },
++ { S5H1411_I2C_TOP_ADDR, 0x27, 0x0f04, },
++ { S5H1411_I2C_TOP_ADDR, 0x28, 0x070f, },
++ { S5H1411_I2C_TOP_ADDR, 0x29, 0x2820, },
++ { S5H1411_I2C_TOP_ADDR, 0x2a, 0x102e, },
++ { S5H1411_I2C_TOP_ADDR, 0x2b, 0x0220, },
++ { S5H1411_I2C_TOP_ADDR, 0x2e, 0x0d0e, },
++ { S5H1411_I2C_TOP_ADDR, 0x2f, 0x1013, },
++ { S5H1411_I2C_TOP_ADDR, 0x31, 0x171b, },
++ { S5H1411_I2C_TOP_ADDR, 0x32, 0x0e0f, },
++ { S5H1411_I2C_TOP_ADDR, 0x33, 0x0f10, },
++ { S5H1411_I2C_TOP_ADDR, 0x34, 0x170e, },
++ { S5H1411_I2C_TOP_ADDR, 0x35, 0x4b10, },
++ { S5H1411_I2C_TOP_ADDR, 0x36, 0x0f17, },
++ { S5H1411_I2C_TOP_ADDR, 0x3c, 0x1577, },
++ { S5H1411_I2C_TOP_ADDR, 0x3d, 0x081a, },
++ { S5H1411_I2C_TOP_ADDR, 0x3e, 0x77ee, },
++ { S5H1411_I2C_TOP_ADDR, 0x40, 0x1e09, },
++ { S5H1411_I2C_TOP_ADDR, 0x41, 0x0f0c, },
++ { S5H1411_I2C_TOP_ADDR, 0x42, 0x1f10, },
++ { S5H1411_I2C_TOP_ADDR, 0x4d, 0x0509, },
++ { S5H1411_I2C_TOP_ADDR, 0x4e, 0x0a00, },
++ { S5H1411_I2C_TOP_ADDR, 0x50, 0x0000, },
++ { S5H1411_I2C_TOP_ADDR, 0x5b, 0x0000, },
++ { S5H1411_I2C_TOP_ADDR, 0x5c, 0x0008, },
++ { S5H1411_I2C_TOP_ADDR, 0x57, 0x1101, },
++ { S5H1411_I2C_TOP_ADDR, 0x65, 0x007c, },
++ { S5H1411_I2C_TOP_ADDR, 0x68, 0x0512, },
++ { S5H1411_I2C_TOP_ADDR, 0x69, 0x0258, },
++ { S5H1411_I2C_TOP_ADDR, 0x70, 0x0004, },
++ { S5H1411_I2C_TOP_ADDR, 0x71, 0x0007, },
++ { S5H1411_I2C_TOP_ADDR, 0x76, 0x00a9, },
++ { S5H1411_I2C_TOP_ADDR, 0x78, 0x3141, },
++ { S5H1411_I2C_TOP_ADDR, 0x7a, 0x3141, },
++ { S5H1411_I2C_TOP_ADDR, 0xb3, 0x8003, },
++ { S5H1411_I2C_TOP_ADDR, 0xb5, 0xafbb, },
++ { S5H1411_I2C_TOP_ADDR, 0xb5, 0xa6bb, },
++ { S5H1411_I2C_TOP_ADDR, 0xb6, 0x0609, },
++ { S5H1411_I2C_TOP_ADDR, 0xb7, 0x2f06, },
++ { S5H1411_I2C_TOP_ADDR, 0xb8, 0x003f, },
++ { S5H1411_I2C_TOP_ADDR, 0xb9, 0x2700, },
++ { S5H1411_I2C_TOP_ADDR, 0xba, 0xfac8, },
++ { S5H1411_I2C_TOP_ADDR, 0xbe, 0x1003, },
++ { S5H1411_I2C_TOP_ADDR, 0xbf, 0x103f, },
++ { S5H1411_I2C_TOP_ADDR, 0xce, 0x2000, },
++ { S5H1411_I2C_TOP_ADDR, 0xcf, 0x0800, },
++ { S5H1411_I2C_TOP_ADDR, 0xd0, 0x0800, },
++ { S5H1411_I2C_TOP_ADDR, 0xd1, 0x0400, },
++ { S5H1411_I2C_TOP_ADDR, 0xd2, 0x0800, },
++ { S5H1411_I2C_TOP_ADDR, 0xd3, 0x2000, },
++ { S5H1411_I2C_TOP_ADDR, 0xd4, 0x3000, },
++ { S5H1411_I2C_TOP_ADDR, 0xdb, 0x4a9b, },
++ { S5H1411_I2C_TOP_ADDR, 0xdc, 0x1000, },
++ { S5H1411_I2C_TOP_ADDR, 0xde, 0x0001, },
++ { S5H1411_I2C_TOP_ADDR, 0xdf, 0x0000, },
++ { S5H1411_I2C_TOP_ADDR, 0xe3, 0x0301, },
++ { S5H1411_I2C_QAM_ADDR, 0xf3, 0x0000, },
++ { S5H1411_I2C_QAM_ADDR, 0xf3, 0x0001, },
++ { S5H1411_I2C_QAM_ADDR, 0x08, 0x0600, },
++ { S5H1411_I2C_QAM_ADDR, 0x18, 0x4201, },
++ { S5H1411_I2C_QAM_ADDR, 0x1e, 0x6476, },
++ { S5H1411_I2C_QAM_ADDR, 0x21, 0x0830, },
++ { S5H1411_I2C_QAM_ADDR, 0x0c, 0x5679, },
++ { S5H1411_I2C_QAM_ADDR, 0x0d, 0x579b, },
++ { S5H1411_I2C_QAM_ADDR, 0x24, 0x0102, },
++ { S5H1411_I2C_QAM_ADDR, 0x31, 0x7488, },
++ { S5H1411_I2C_QAM_ADDR, 0x32, 0x0a08, },
++ { S5H1411_I2C_QAM_ADDR, 0x3d, 0x8689, },
++ { S5H1411_I2C_QAM_ADDR, 0x49, 0x0048, },
++ { S5H1411_I2C_QAM_ADDR, 0x57, 0x2012, },
++ { S5H1411_I2C_QAM_ADDR, 0x5d, 0x7676, },
++ { S5H1411_I2C_QAM_ADDR, 0x04, 0x0400, },
++ { S5H1411_I2C_QAM_ADDR, 0x58, 0x00c0, },
++ { S5H1411_I2C_QAM_ADDR, 0x5b, 0x0100, },
++};
++
++/* VSB SNR lookup table */
++static struct vsb_snr_tab {
++ u16 val;
++ u16 data;
++} vsb_snr_tab[] = {
++ { 0x39f, 300, },
++ { 0x39b, 295, },
++ { 0x397, 290, },
++ { 0x394, 285, },
++ { 0x38f, 280, },
++ { 0x38b, 275, },
++ { 0x387, 270, },
++ { 0x382, 265, },
++ { 0x37d, 260, },
++ { 0x377, 255, },
++ { 0x370, 250, },
++ { 0x36a, 245, },
++ { 0x364, 240, },
++ { 0x35b, 235, },
++ { 0x353, 230, },
++ { 0x349, 225, },
++ { 0x340, 320, },
++ { 0x337, 215, },
++ { 0x327, 210, },
++ { 0x31b, 205, },
++ { 0x310, 200, },
++ { 0x302, 195, },
++ { 0x2f3, 190, },
++ { 0x2e4, 185, },
++ { 0x2d7, 180, },
++ { 0x2cd, 175, },
++ { 0x2bb, 170, },
++ { 0x2a9, 165, },
++ { 0x29e, 160, },
++ { 0x284, 155, },
++ { 0x27a, 150, },
++ { 0x260, 145, },
++ { 0x23a, 140, },
++ { 0x224, 135, },
++ { 0x213, 130, },
++ { 0x204, 125, },
++ { 0x1fe, 120, },
++ { 0, 0, },
++};
++
++/* QAM64 SNR lookup table */
++static struct qam64_snr_tab {
++ u16 val;
++ u16 data;
++} qam64_snr_tab[] = {
++ { 0x0001, 0, },
++ { 0x0af0, 300, },
++ { 0x0d80, 290, },
++ { 0x10a0, 280, },
++ { 0x14b5, 270, },
++ { 0x1590, 268, },
++ { 0x1680, 266, },
++ { 0x17b0, 264, },
++ { 0x18c0, 262, },
++ { 0x19b0, 260, },
++ { 0x1ad0, 258, },
++ { 0x1d00, 256, },
++ { 0x1da0, 254, },
++ { 0x1ef0, 252, },
++ { 0x2050, 250, },
++ { 0x20f0, 249, },
++ { 0x21d0, 248, },
++ { 0x22b0, 247, },
++ { 0x23a0, 246, },
++ { 0x2470, 245, },
++ { 0x24f0, 244, },
++ { 0x25a0, 243, },
++ { 0x26c0, 242, },
++ { 0x27b0, 241, },
++ { 0x28d0, 240, },
++ { 0x29b0, 239, },
++ { 0x2ad0, 238, },
++ { 0x2ba0, 237, },
++ { 0x2c80, 236, },
++ { 0x2d20, 235, },
++ { 0x2e00, 234, },
++ { 0x2f10, 233, },
++ { 0x3050, 232, },
++ { 0x3190, 231, },
++ { 0x3300, 230, },
++ { 0x3340, 229, },
++ { 0x3200, 228, },
++ { 0x3550, 227, },
++ { 0x3610, 226, },
++ { 0x3600, 225, },
++ { 0x3700, 224, },
++ { 0x3800, 223, },
++ { 0x3920, 222, },
++ { 0x3a20, 221, },
++ { 0x3b30, 220, },
++ { 0x3d00, 219, },
++ { 0x3e00, 218, },
++ { 0x4000, 217, },
++ { 0x4100, 216, },
++ { 0x4300, 215, },
++ { 0x4400, 214, },
++ { 0x4600, 213, },
++ { 0x4700, 212, },
++ { 0x4800, 211, },
++ { 0x4a00, 210, },
++ { 0x4b00, 209, },
++ { 0x4d00, 208, },
++ { 0x4f00, 207, },
++ { 0x5050, 206, },
++ { 0x5200, 205, },
++ { 0x53c0, 204, },
++ { 0x5450, 203, },
++ { 0x5650, 202, },
++ { 0x5820, 201, },
++ { 0x6000, 200, },
++ { 0xffff, 0, },
++};
++
++/* QAM256 SNR lookup table */
++static struct qam256_snr_tab {
++ u16 val;
++ u16 data;
++} qam256_snr_tab[] = {
++ { 0x0001, 0, },
++ { 0x0970, 400, },
++ { 0x0a90, 390, },
++ { 0x0b90, 380, },
++ { 0x0d90, 370, },
++ { 0x0ff0, 360, },
++ { 0x1240, 350, },
++ { 0x1345, 348, },
++ { 0x13c0, 346, },
++ { 0x14c0, 344, },
++ { 0x1500, 342, },
++ { 0x1610, 340, },
++ { 0x1700, 338, },
++ { 0x1800, 336, },
++ { 0x18b0, 334, },
++ { 0x1900, 332, },
++ { 0x1ab0, 330, },
++ { 0x1bc0, 328, },
++ { 0x1cb0, 326, },
++ { 0x1db0, 324, },
++ { 0x1eb0, 322, },
++ { 0x2030, 320, },
++ { 0x2200, 318, },
++ { 0x2280, 316, },
++ { 0x2410, 314, },
++ { 0x25b0, 312, },
++ { 0x27a0, 310, },
++ { 0x2840, 308, },
++ { 0x29d0, 306, },
++ { 0x2b10, 304, },
++ { 0x2d30, 302, },
++ { 0x2f20, 300, },
++ { 0x30c0, 298, },
++ { 0x3260, 297, },
++ { 0x32c0, 296, },
++ { 0x3300, 295, },
++ { 0x33b0, 294, },
++ { 0x34b0, 293, },
++ { 0x35a0, 292, },
++ { 0x3650, 291, },
++ { 0x3800, 290, },
++ { 0x3900, 289, },
++ { 0x3a50, 288, },
++ { 0x3b30, 287, },
++ { 0x3cb0, 286, },
++ { 0x3e20, 285, },
++ { 0x3fa0, 284, },
++ { 0x40a0, 283, },
++ { 0x41c0, 282, },
++ { 0x42f0, 281, },
++ { 0x44a0, 280, },
++ { 0x4600, 279, },
++ { 0x47b0, 278, },
++ { 0x4900, 277, },
++ { 0x4a00, 276, },
++ { 0x4ba0, 275, },
++ { 0x4d00, 274, },
++ { 0x4f00, 273, },
++ { 0x5000, 272, },
++ { 0x51f0, 272, },
++ { 0x53a0, 270, },
++ { 0x5520, 269, },
++ { 0x5700, 268, },
++ { 0x5800, 267, },
++ { 0x5a00, 266, },
++ { 0x5c00, 265, },
++ { 0x5d00, 264, },
++ { 0x5f00, 263, },
++ { 0x6000, 262, },
++ { 0x6200, 261, },
++ { 0x6400, 260, },
++ { 0xffff, 0, },
++};
++
++/* 8 bit registers, 16 bit values */
++static int s5h1411_writereg(struct s5h1411_state *state,
++ u8 addr, u8 reg, u16 data)
++{
++ int ret;
++ u8 buf [] = { reg, data >> 8, data & 0xff };
++
++ struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
++
++ ret = i2c_transfer(state->i2c, &msg, 1);
++
++ if (ret != 1)
++ printk(KERN_ERR "%s: writereg error 0x%02x 0x%02x 0x%04x, "
++ "ret == %i)\n", __func__, addr, reg, data, ret);
++
++ return (ret != 1) ? -1 : 0;
++}
++
++static u16 s5h1411_readreg(struct s5h1411_state *state, u8 addr, u8 reg)
++{
++ int ret;
++ u8 b0 [] = { reg };
++ u8 b1 [] = { 0, 0 };
++
++ struct i2c_msg msg [] = {
++ { .addr = addr, .flags = 0, .buf = b0, .len = 1 },
++ { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
++
++ ret = i2c_transfer(state->i2c, msg, 2);
++
++ if (ret != 2)
++ printk(KERN_ERR "%s: readreg error (ret == %i)\n",
++ __func__, ret);
++ return (b1[0] << 8) | b1[1];
++}
++
++static int s5h1411_softreset(struct dvb_frontend *fe)
++{
++ struct s5h1411_state *state = fe->demodulator_priv;
++
++ dprintk("%s()\n", __func__);
++
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf7, 0);
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf7, 1);
++ return 0;
++}
++
++static int s5h1411_set_if_freq(struct dvb_frontend *fe, int KHz)
++{
++ struct s5h1411_state *state = fe->demodulator_priv;
++
++ dprintk("%s(%d KHz)\n", __func__, KHz);
++
++ switch (KHz) {
++ case 3250:
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x10d9);
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x5342);
++ s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x10d9);
++ break;
++ case 3500:
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x1225);
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x1e96);
++ s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x1225);
++ break;
++ case 4000:
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x14bc);
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0xb53e);
++ s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x14bd);
++ break;
++ default:
++ dprintk("%s(%d KHz) Invalid, defaulting to 5380\n",
++ __func__, KHz);
++ /* no break, need to continue */
++ case 5380:
++ case 44000:
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x1be4);
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x3655);
++ s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x1be4);
++ break;
++ }
++
++ state->if_freq = KHz;
++
++ return 0;
++}
++
++static int s5h1411_set_mpeg_timing(struct dvb_frontend *fe, int mode)
++{
++ struct s5h1411_state *state = fe->demodulator_priv;
++ u16 val;
++
++ dprintk("%s(%d)\n", __func__, mode);
++
++ val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xbe) & 0xcfff;
++ switch (mode) {
++ case S5H1411_MPEGTIMING_CONTINOUS_INVERTING_CLOCK:
++ val |= 0x0000;
++ break;
++ case S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK:
++ dprintk("%s(%d) Mode1 or Defaulting\n", __func__, mode);
++ val |= 0x1000;
++ break;
++ case S5H1411_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK:
++ val |= 0x2000;
++ break;
++ case S5H1411_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK:
++ val |= 0x3000;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ /* Configure MPEG Signal Timing charactistics */
++ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbe, val);
++}
++
++static int s5h1411_set_spectralinversion(struct dvb_frontend *fe, int inversion)
++{
++ struct s5h1411_state *state = fe->demodulator_priv;
++ u16 val;
++
++ dprintk("%s(%d)\n", __func__, inversion);
++ val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x24) & ~0x1000;
++
++ if (inversion == 1)
++ val |= 0x1000; /* Inverted */
++ else
++ val |= 0x0000;
++
++ state->inversion = inversion;
++ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x24, val);
++}
++
++static int s5h1411_enable_modulation(struct dvb_frontend *fe,
++ fe_modulation_t m)
++{
++ struct s5h1411_state *state = fe->demodulator_priv;
++
++ dprintk("%s(0x%08x)\n", __func__, m);
++
++ switch (m) {
++ case VSB_8:
++ dprintk("%s() VSB_8\n", __func__);
++ s5h1411_set_if_freq(fe, state->config->vsb_if);
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x00, 0x71);
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf6, 0x00);
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xcd, 0xf1);
++ break;
++ case QAM_64:
++ case QAM_256:
++ dprintk("%s() QAM_AUTO (64/256)\n", __func__);
++ s5h1411_set_if_freq(fe, state->config->qam_if);
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x00, 0x0171);
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf6, 0x0001);
++ s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x16, 0x1101);
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xcd, 0x00f0);
++ break;
++ default:
++ dprintk("%s() Invalid modulation\n", __func__);
++ return -EINVAL;
++ }
++
++ state->current_modulation = m;
++ s5h1411_softreset(fe);
++
++ return 0;
++}
++
++static int s5h1411_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
++{
++ struct s5h1411_state *state = fe->demodulator_priv;
++
++ dprintk("%s(%d)\n", __func__, enable);
++
++ if (enable)
++ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 1);
++ else
++ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 0);
++}
++
++static int s5h1411_set_gpio(struct dvb_frontend *fe, int enable)
++{
++ struct s5h1411_state *state = fe->demodulator_priv;
++ u16 val;
++
++ dprintk("%s(%d)\n", __func__, enable);
++
++ val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xe0) & ~0x02;
++
++ if (enable)
++ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0,
++ val | 0x02);
++ else
++ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0, val);
++}
++
++static int s5h1411_sleep(struct dvb_frontend *fe, int enable)
++{
++ struct s5h1411_state *state = fe->demodulator_priv;
++
++ dprintk("%s(%d)\n", __func__, enable);
++
++ if (enable)
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf4, 1);
++ else {
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf4, 0);
++ s5h1411_softreset(fe);
++ }
++
++ return 0;
++}
++
++static int s5h1411_register_reset(struct dvb_frontend *fe)
++{
++ struct s5h1411_state *state = fe->demodulator_priv;
++
++ dprintk("%s()\n", __func__);
++
++ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf3, 0);
++}
++
++/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
++static int s5h1411_set_frontend(struct dvb_frontend *fe,
++ struct dvb_frontend_parameters *p)
++{
++ struct s5h1411_state *state = fe->demodulator_priv;
++
++ dprintk("%s(frequency=%d)\n", __func__, p->frequency);
++
++ s5h1411_softreset(fe);
++
++ state->current_frequency = p->frequency;
++
++ s5h1411_enable_modulation(fe, p->u.vsb.modulation);
++
++ /* Allow the demod to settle */
++ msleep(100);
++
++ if (fe->ops.tuner_ops.set_params) {
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
++
++ fe->ops.tuner_ops.set_params(fe, p);
++
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 0);
++ }
++
++ return 0;
++}
++
++/* Reset the demod hardware and reset all of the configuration registers
++ to a default state. */
++static int s5h1411_init(struct dvb_frontend *fe)
++{
++ struct s5h1411_state *state = fe->demodulator_priv;
++ int i;
++
++ dprintk("%s()\n", __func__);
++
++ s5h1411_sleep(fe, 0);
++ s5h1411_register_reset(fe);
++
++ for (i = 0; i < ARRAY_SIZE(init_tab); i++)
++ s5h1411_writereg(state, init_tab[i].addr,
++ init_tab[i].reg,
++ init_tab[i].data);
++
++ /* The datasheet says that after initialisation, VSB is default */
++ state->current_modulation = VSB_8;
++
++ if (state->config->output_mode == S5H1411_SERIAL_OUTPUT)
++ /* Serial */
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, 0x1101);
++ else
++ /* Parallel */
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, 0x1001);
++
++ s5h1411_set_spectralinversion(fe, state->config->inversion);
++ s5h1411_set_if_freq(fe, state->config->vsb_if);
++ s5h1411_set_gpio(fe, state->config->gpio);
++ s5h1411_set_mpeg_timing(fe, state->config->mpeg_timing);
++ s5h1411_softreset(fe);
++
++ /* Note: Leaving the I2C gate closed. */
++ s5h1411_i2c_gate_ctrl(fe, 0);
++
++ return 0;
++}
++
++static int s5h1411_read_status(struct dvb_frontend *fe, fe_status_t *status)
++{
++ struct s5h1411_state *state = fe->demodulator_priv;
++ u16 reg;
++ u32 tuner_status = 0;
++
++ *status = 0;
++
++ /* Get the demodulator status */
++ reg = (s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf2) >> 15)
++ & 0x0001;
++ if (reg)
++ *status |= FE_HAS_LOCK | FE_HAS_CARRIER | FE_HAS_SIGNAL;
++
++ switch (state->current_modulation) {
++ case QAM_64:
++ case QAM_256:
++ reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf0);
++ if (reg & 0x100)
++ *status |= FE_HAS_VITERBI;
++ if (reg & 0x10)
++ *status |= FE_HAS_SYNC;
++ break;
++ case VSB_8:
++ reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x5e);
++ if (reg & 0x0001)
++ *status |= FE_HAS_SYNC;
++ reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf2);
++ if (reg & 0x1000)
++ *status |= FE_HAS_VITERBI;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ switch (state->config->status_mode) {
++ case S5H1411_DEMODLOCKING:
++ if (*status & FE_HAS_VITERBI)
++ *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
++ break;
++ case S5H1411_TUNERLOCKING:
++ /* Get the tuner status */
++ if (fe->ops.tuner_ops.get_status) {
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
++
++ fe->ops.tuner_ops.get_status(fe, &tuner_status);
++
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 0);
++ }
++ if (tuner_status)
++ *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
++ break;
++ }
++
++ dprintk("%s() status 0x%08x\n", __func__, *status);
++
++ return 0;
++}
++
++static int s5h1411_qam256_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
++{
++ int i, ret = -EINVAL;
++ dprintk("%s()\n", __func__);
++
++ for (i = 0; i < ARRAY_SIZE(qam256_snr_tab); i++) {
++ if (v < qam256_snr_tab[i].val) {
++ *snr = qam256_snr_tab[i].data;
++ ret = 0;
++ break;
++ }
++ }
++ return ret;
++}
++
++static int s5h1411_qam64_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
++{
++ int i, ret = -EINVAL;
++ dprintk("%s()\n", __func__);
++
++ for (i = 0; i < ARRAY_SIZE(qam64_snr_tab); i++) {
++ if (v < qam64_snr_tab[i].val) {
++ *snr = qam64_snr_tab[i].data;
++ ret = 0;
++ break;
++ }
++ }
++ return ret;
++}
++
++static int s5h1411_vsb_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
++{
++ int i, ret = -EINVAL;
++ dprintk("%s()\n", __func__);
++
++ for (i = 0; i < ARRAY_SIZE(vsb_snr_tab); i++) {
++ if (v > vsb_snr_tab[i].val) {
++ *snr = vsb_snr_tab[i].data;
++ ret = 0;
++ break;
++ }
++ }
++ dprintk("%s() snr=%d\n", __func__, *snr);
++ return ret;
++}
++
++static int s5h1411_read_snr(struct dvb_frontend *fe, u16 *snr)
++{
++ struct s5h1411_state *state = fe->demodulator_priv;
++ u16 reg;
++ dprintk("%s()\n", __func__);
++
++ switch (state->current_modulation) {
++ case QAM_64:
++ reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf1);
++ return s5h1411_qam64_lookup_snr(fe, snr, reg);
++ case QAM_256:
++ reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf1);
++ return s5h1411_qam256_lookup_snr(fe, snr, reg);
++ case VSB_8:
++ reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR,
++ 0xf2) & 0x3ff;
++ return s5h1411_vsb_lookup_snr(fe, snr, reg);
++ default:
++ break;
++ }
++
++ return -EINVAL;
++}
++
++static int s5h1411_read_signal_strength(struct dvb_frontend *fe,
++ u16 *signal_strength)
++{
++ return s5h1411_read_snr(fe, signal_strength);
++}
++
++static int s5h1411_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
++{
++ struct s5h1411_state *state = fe->demodulator_priv;
++
++ *ucblocks = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xc9);
++
++ return 0;
++}
++
++static int s5h1411_read_ber(struct dvb_frontend *fe, u32 *ber)
++{
++ return s5h1411_read_ucblocks(fe, ber);
++}
++
++static int s5h1411_get_frontend(struct dvb_frontend *fe,
++ struct dvb_frontend_parameters *p)
++{
++ struct s5h1411_state *state = fe->demodulator_priv;
++
++ p->frequency = state->current_frequency;
++ p->u.vsb.modulation = state->current_modulation;
++
++ return 0;
++}
++
++static int s5h1411_get_tune_settings(struct dvb_frontend *fe,
++ struct dvb_frontend_tune_settings *tune)
++{
++ tune->min_delay_ms = 1000;
++ return 0;
++}
++
++static void s5h1411_release(struct dvb_frontend *fe)
++{
++ struct s5h1411_state *state = fe->demodulator_priv;
++ kfree(state);
++}
++
++static struct dvb_frontend_ops s5h1411_ops;
++
++struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
++ struct i2c_adapter *i2c)
++{
++ struct s5h1411_state *state = NULL;
++ u16 reg;
++
++ /* allocate memory for the internal state */
++ state = kmalloc(sizeof(struct s5h1411_state), GFP_KERNEL);
++ if (state == NULL)
++ goto error;
++
++ /* setup the state */
++ state->config = config;
++ state->i2c = i2c;
++ state->current_modulation = VSB_8;
++ state->inversion = state->config->inversion;
++
++ /* check if the demod exists */
++ reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x05);
++ if (reg != 0x0066)
++ goto error;
++
++ /* create dvb_frontend */
++ memcpy(&state->frontend.ops, &s5h1411_ops,
++ sizeof(struct dvb_frontend_ops));
++
++ state->frontend.demodulator_priv = state;
++
++ if (s5h1411_init(&state->frontend) != 0) {
++ printk(KERN_ERR "%s: Failed to initialize correctly\n",
++ __func__);
++ goto error;
++ }
++
++ /* Note: Leaving the I2C gate open here. */
++ s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 1);
++
++ return &state->frontend;
++
++error:
++ kfree(state);
++ return NULL;
++}
++EXPORT_SYMBOL(s5h1411_attach);
++
++static struct dvb_frontend_ops s5h1411_ops = {
++
++ .info = {
++ .name = "Samsung S5H1411 QAM/8VSB Frontend",
++ .type = FE_ATSC,
++ .frequency_min = 54000000,
++ .frequency_max = 858000000,
++ .frequency_stepsize = 62500,
++ .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
++ },
++
++ .init = s5h1411_init,
++ .i2c_gate_ctrl = s5h1411_i2c_gate_ctrl,
++ .set_frontend = s5h1411_set_frontend,
++ .get_frontend = s5h1411_get_frontend,
++ .get_tune_settings = s5h1411_get_tune_settings,
++ .read_status = s5h1411_read_status,
++ .read_ber = s5h1411_read_ber,
++ .read_signal_strength = s5h1411_read_signal_strength,
++ .read_snr = s5h1411_read_snr,
++ .read_ucblocks = s5h1411_read_ucblocks,
++ .release = s5h1411_release,
++};
++
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "Enable verbose debug messages");
++
++MODULE_DESCRIPTION("Samsung S5H1411 QAM-B/ATSC Demodulator driver");
++MODULE_AUTHOR("Steven Toth");
++MODULE_LICENSE("GPL");
++
++/*
++ * Local variables:
++ * c-basic-offset: 8
++ */
+diff --git a/drivers/media/dvb/frontends/s5h1411.h b/drivers/media/dvb/frontends/s5h1411.h
+new file mode 100644
+index 0000000..1855f64
+--- /dev/null
++++ b/drivers/media/dvb/frontends/s5h1411.h
+@@ -0,0 +1,90 @@
++/*
++ Samsung S5H1411 VSB/QAM demodulator driver
++
++ Copyright (C) 2008 Steven Toth <stoth at hauppauge.com>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++*/
++
++#ifndef __S5H1411_H__
++#define __S5H1411_H__
++
++#include <linux/dvb/frontend.h>
++
++#define S5H1411_I2C_TOP_ADDR (0x32 >> 1)
++#define S5H1411_I2C_QAM_ADDR (0x34 >> 1)
++
++struct s5h1411_config {
++
++ /* serial/parallel output */
++#define S5H1411_PARALLEL_OUTPUT 0
++#define S5H1411_SERIAL_OUTPUT 1
++ u8 output_mode;
++
++ /* GPIO Setting */
++#define S5H1411_GPIO_OFF 0
++#define S5H1411_GPIO_ON 1
++ u8 gpio;
++
++ /* MPEG signal timing */
++#define S5H1411_MPEGTIMING_CONTINOUS_INVERTING_CLOCK 0
++#define S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK 1
++#define S5H1411_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK 2
++#define S5H1411_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK 3
++ u16 mpeg_timing;
++
++ /* IF Freq for QAM and VSB in KHz */
++#define S5H1411_IF_2500 2500
++#define S5H1411_IF_3500 3500
++#define S5H1411_IF_4000 4000
++#define S5H1411_IF_5380 5380
++#define S5H1411_IF_44000 44000
++#define S5H1411_VSB_IF_DEFAULT S5H1411_IF_44000
++#define S5H1411_QAM_IF_DEFAULT S5H1411_IF_44000
++ u16 qam_if;
++ u16 vsb_if;
++
++ /* Spectral Inversion */
++#define S5H1411_INVERSION_OFF 0
++#define S5H1411_INVERSION_ON 1
++ u8 inversion;
++
++ /* Return lock status based on tuner lock, or demod lock */
++#define S5H1411_TUNERLOCKING 0
++#define S5H1411_DEMODLOCKING 1
++ u8 status_mode;
++};
++
++#if defined(CONFIG_DVB_S5H1411) || \
++ (defined(CONFIG_DVB_S5H1411_MODULE) && defined(MODULE))
++extern struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
++ struct i2c_adapter *i2c);
++#else
++static inline struct dvb_frontend *s5h1411_attach(
++ const struct s5h1411_config *config,
++ struct i2c_adapter *i2c)
++{
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++ return NULL;
++}
++#endif /* CONFIG_DVB_S5H1411 */
++
++#endif /* __S5H1411_H__ */
++
++/*
++ * Local variables:
++ * c-basic-offset: 8
++ */
+diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c
+index 2c2c344..281e1cb 100644
+--- a/drivers/media/dvb/frontends/s5h1420.c
++++ b/drivers/media/dvb/frontends/s5h1420.c
+@@ -1,24 +1,26 @@
+ /*
+-Driver for Samsung S5H1420 QPSK Demodulator
+-
+-Copyright (C) 2005 Andrew de Quincey <adq_dvb at lidskialf.net>
+-
+-This program is free software; you can redistribute it and/or modify
+-it under the terms of the GNU General Public License as published by
+-the Free Software Foundation; either version 2 of the License, or
+-(at your option) any later version.
+-
+-This program is distributed in the hope that it will be useful,
+-but WITHOUT ANY WARRANTY; without even the implied warranty of
+-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-
+-GNU General Public License for more details.
+-
+-You should have received a copy of the GNU General Public License
+-along with this program; if not, write to the Free Software
+-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-
+-*/
++ * Driver for
++ * Samsung S5H1420 and
++ * PnpNetwork PN1010 QPSK Demodulator
++ *
++ * Copyright (C) 2005 Andrew de Quincey <adq_dvb at lidskialf.net>
++ * Copyright (C) 2005-8 Patrick Boettcher <pb at linuxtv.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
+
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+@@ -29,23 +31,35 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ #include <linux/jiffies.h>
+ #include <asm/div64.h>
+
+-#include "dvb_frontend.h"
+-#include "s5h1420.h"
++#include <linux/i2c.h>
+
+
++#include "dvb_frontend.h"
++#include "s5h1420.h"
++#include "s5h1420_priv.h"
+
+ #define TONE_FREQ 22000
+
+ struct s5h1420_state {
+ struct i2c_adapter* i2c;
+ const struct s5h1420_config* config;
++
+ struct dvb_frontend frontend;
++ struct i2c_adapter tuner_i2c_adapter;
++
++ u8 CON_1_val;
+
+ u8 postlocked:1;
+ u32 fclk;
+ u32 tunedfreq;
+ fe_code_rate_t fec_inner;
+ u32 symbol_rate;
++
++ /* FIXME: ugly workaround for flexcop's incapable i2c-controller
++ * it does not support repeated-start, workaround: write addr-1
++ * and then read
++ */
++ u8 shadow[255];
+ };
+
+ static u32 s5h1420_getsymbolrate(struct s5h1420_state* state);
+@@ -53,44 +67,66 @@ static int s5h1420_get_tune_settings(struct dvb_frontend* fe,
+ struct dvb_frontend_tune_settings* fesettings);
+
+
+-static int debug = 0;
+-#define dprintk if (debug) printk
++static int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "enable debugging");
++
++#define dprintk(x...) do { \
++ if (debug) \
++ printk(KERN_DEBUG "S5H1420: " x); \
++} while (0)
++
++static u8 s5h1420_readreg(struct s5h1420_state *state, u8 reg)
++{
++ int ret;
++ u8 b[2];
++ struct i2c_msg msg[] = {
++ { .addr = state->config->demod_address, .flags = 0, .buf = b, .len = 2 },
++ { .addr = state->config->demod_address, .flags = 0, .buf = ®, .len = 1 },
++ { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = 1 },
++ };
++
++ b[0] = (reg - 1) & 0xff;
++ b[1] = state->shadow[(reg - 1) & 0xff];
++
++ if (state->config->repeated_start_workaround) {
++ ret = i2c_transfer(state->i2c, msg, 3);
++ if (ret != 3)
++ return ret;
++ } else {
++ ret = i2c_transfer(state->i2c, &msg[1], 2);
++ if (ret != 2)
++ return ret;
++ }
++
++ /* dprintk("rd(%02x): %02x %02x\n", state->config->demod_address, reg, b[0]); */
++
++ return b[0];
++}
+
+ static int s5h1420_writereg (struct s5h1420_state* state, u8 reg, u8 data)
+ {
+- u8 buf [] = { reg, data };
++ u8 buf[] = { reg, data };
+ struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
+ int err;
+
+- if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+- dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data);
++ /* dprintk("wr(%02x): %02x %02x\n", state->config->demod_address, reg, data); */
++ err = i2c_transfer(state->i2c, &msg, 1);
++ if (err != 1) {
++ dprintk("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
+ return -EREMOTEIO;
+ }
++ state->shadow[reg] = data;
+
+ return 0;
+ }
+
+-static u8 s5h1420_readreg (struct s5h1420_state* state, u8 reg)
+-{
+- int ret;
+- u8 b0 [] = { reg };
+- u8 b1 [] = { 0 };
+- struct i2c_msg msg1 = { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 };
+- struct i2c_msg msg2 = { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 };
+-
+- if ((ret = i2c_transfer (state->i2c, &msg1, 1)) != 1)
+- return ret;
+-
+- if ((ret = i2c_transfer (state->i2c, &msg2, 1)) != 1)
+- return ret;
+-
+- return b1[0];
+-}
+-
+ static int s5h1420_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+ {
+ struct s5h1420_state* state = fe->demodulator_priv;
+
++ dprintk("enter %s\n", __func__);
++
+ switch(voltage) {
+ case SEC_VOLTAGE_13:
+ s5h1420_writereg(state, 0x3c,
+@@ -106,6 +142,7 @@ static int s5h1420_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
+ break;
+ }
+
++ dprintk("leave %s\n", __func__);
+ return 0;
+ }
+
+@@ -113,6 +150,7 @@ static int s5h1420_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+ {
+ struct s5h1420_state* state = fe->demodulator_priv;
+
++ dprintk("enter %s\n", __func__);
+ switch(tone) {
+ case SEC_TONE_ON:
+ s5h1420_writereg(state, 0x3b,
+@@ -124,6 +162,7 @@ static int s5h1420_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+ (s5h1420_readreg(state, 0x3b) & 0x74) | 0x01);
+ break;
+ }
++ dprintk("leave %s\n", __func__);
+
+ return 0;
+ }
+@@ -137,6 +176,7 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe,
+ unsigned long timeout;
+ int result = 0;
+
++ dprintk("enter %s\n", __func__);
+ if (cmd->msg_len > 8)
+ return -EINVAL;
+
+@@ -168,6 +208,7 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe,
+ /* restore original settings */
+ s5h1420_writereg(state, 0x3b, val);
+ msleep(15);
++ dprintk("leave %s\n", __func__);
+ return result;
+ }
+
+@@ -289,6 +330,8 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ struct s5h1420_state* state = fe->demodulator_priv;
+ u8 val;
+
++ dprintk("enter %s\n", __func__);
++
+ if (status == NULL)
+ return -EINVAL;
+
+@@ -297,13 +340,13 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
+
+ /* fix for FEC 5/6 inversion issue - if it doesn't quite lock, invert
+ the inversion, wait a bit and check again */
+- if (*status == (FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI)) {
+- val = s5h1420_readreg(state, 0x32);
++ if (*status == (FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI)) {
++ val = s5h1420_readreg(state, Vit10);
+ if ((val & 0x07) == 0x03) {
+ if (val & 0x08)
+- s5h1420_writereg(state, 0x31, 0x13);
++ s5h1420_writereg(state, Vit09, 0x13);
+ else
+- s5h1420_writereg(state, 0x31, 0x1b);
++ s5h1420_writereg(state, Vit09, 0x1b);
+
+ /* wait a bit then update lock status */
+ mdelay(200);
+@@ -312,68 +355,73 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ }
+
+ /* perform post lock setup */
+- if ((*status & FE_HAS_LOCK) && (!state->postlocked)) {
++ if ((*status & FE_HAS_LOCK) && !state->postlocked) {
+
+ /* calculate the data rate */
+ u32 tmp = s5h1420_getsymbolrate(state);
+- switch(s5h1420_readreg(state, 0x32) & 0x07) {
+- case 0:
+- tmp = (tmp * 2 * 1) / 2;
+- break;
+-
+- case 1:
+- tmp = (tmp * 2 * 2) / 3;
+- break;
+-
+- case 2:
+- tmp = (tmp * 2 * 3) / 4;
+- break;
+-
+- case 3:
+- tmp = (tmp * 2 * 5) / 6;
+- break;
+-
+- case 4:
+- tmp = (tmp * 2 * 6) / 7;
+- break;
+-
+- case 5:
+- tmp = (tmp * 2 * 7) / 8;
+- break;
++ switch (s5h1420_readreg(state, Vit10) & 0x07) {
++ case 0: tmp = (tmp * 2 * 1) / 2; break;
++ case 1: tmp = (tmp * 2 * 2) / 3; break;
++ case 2: tmp = (tmp * 2 * 3) / 4; break;
++ case 3: tmp = (tmp * 2 * 5) / 6; break;
++ case 4: tmp = (tmp * 2 * 6) / 7; break;
++ case 5: tmp = (tmp * 2 * 7) / 8; break;
+ }
++
+ if (tmp == 0) {
+- printk("s5h1420: avoided division by 0\n");
++ printk(KERN_ERR "s5h1420: avoided division by 0\n");
+ tmp = 1;
+ }
+ tmp = state->fclk / tmp;
+
++
+ /* set the MPEG_CLK_INTL for the calculated data rate */
+- if (tmp < 4)
++ if (tmp < 2)
+ val = 0x00;
+- else if (tmp < 8)
++ else if (tmp < 5)
+ val = 0x01;
+- else if (tmp < 12)
++ else if (tmp < 9)
+ val = 0x02;
+- else if (tmp < 16)
++ else if (tmp < 13)
+ val = 0x03;
+- else if (tmp < 24)
++ else if (tmp < 17)
+ val = 0x04;
+- else if (tmp < 32)
++ else if (tmp < 25)
+ val = 0x05;
+- else
++ else if (tmp < 33)
+ val = 0x06;
+- s5h1420_writereg(state, 0x22, val);
++ else
++ val = 0x07;
++ dprintk("for MPEG_CLK_INTL %d %x\n", tmp, val);
++
++ s5h1420_writereg(state, FEC01, 0x18);
++ s5h1420_writereg(state, FEC01, 0x10);
++ s5h1420_writereg(state, FEC01, val);
++
++ /* Enable "MPEG_Out" */
++ val = s5h1420_readreg(state, Mpeg02);
++ s5h1420_writereg(state, Mpeg02, val | (1 << 6));
+
+- /* DC freeze */
+- s5h1420_writereg(state, 0x1f, s5h1420_readreg(state, 0x1f) | 0x01);
++ /* kicker disable */
++ val = s5h1420_readreg(state, QPSK01) & 0x7f;
++ s5h1420_writereg(state, QPSK01, val);
+
+- /* kicker disable + remove DC offset */
+- s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) & 0x6f);
++ /* DC freeze TODO it was never activated by default or it can stay activated */
++
++ if (s5h1420_getsymbolrate(state) >= 20000000) {
++ s5h1420_writereg(state, Loop04, 0x8a);
++ s5h1420_writereg(state, Loop05, 0x6a);
++ } else {
++ s5h1420_writereg(state, Loop04, 0x58);
++ s5h1420_writereg(state, Loop05, 0x27);
++ }
+
+ /* post-lock processing has been done! */
+ state->postlocked = 1;
+ }
+
++ dprintk("leave %s\n", __func__);
++
+ return 0;
+ }
+
+@@ -414,6 +462,7 @@ static int s5h1420_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+
+ static void s5h1420_reset(struct s5h1420_state* state)
+ {
++ dprintk("%s\n", __func__);
+ s5h1420_writereg (state, 0x01, 0x08);
+ s5h1420_writereg (state, 0x01, 0x00);
+ udelay(10);
+@@ -422,54 +471,52 @@ static void s5h1420_reset(struct s5h1420_state* state)
+ static void s5h1420_setsymbolrate(struct s5h1420_state* state,
+ struct dvb_frontend_parameters *p)
+ {
++ u8 v;
+ u64 val;
+
++ dprintk("enter %s\n", __func__);
++
+ val = ((u64) p->u.qpsk.symbol_rate / 1000ULL) * (1ULL<<24);
+- if (p->u.qpsk.symbol_rate <= 21000000) {
++ if (p->u.qpsk.symbol_rate < 29000000)
+ val *= 2;
+- }
+ do_div(val, (state->fclk / 1000));
+
+- s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) & 0x7f);
+- s5h1420_writereg(state, 0x11, val >> 16);
+- s5h1420_writereg(state, 0x12, val >> 8);
+- s5h1420_writereg(state, 0x13, val & 0xff);
+- s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) | 0x80);
++ dprintk("symbol rate register: %06llx\n", val);
++
++ v = s5h1420_readreg(state, Loop01);
++ s5h1420_writereg(state, Loop01, v & 0x7f);
++ s5h1420_writereg(state, Tnco01, val >> 16);
++ s5h1420_writereg(state, Tnco02, val >> 8);
++ s5h1420_writereg(state, Tnco03, val & 0xff);
++ s5h1420_writereg(state, Loop01, v | 0x80);
++ dprintk("leave %s\n", __func__);
+ }
+
+ static u32 s5h1420_getsymbolrate(struct s5h1420_state* state)
+ {
+- u64 val = 0;
+- int sampling = 2;
+-
+- if (s5h1420_readreg(state, 0x05) & 0x2)
+- sampling = 1;
+-
+- s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) | 0x08);
+- val = s5h1420_readreg(state, 0x11) << 16;
+- val |= s5h1420_readreg(state, 0x12) << 8;
+- val |= s5h1420_readreg(state, 0x13);
+- s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) & 0xf7);
+-
+- val *= (state->fclk / 1000ULL);
+- do_div(val, ((1<<24) * sampling));
+-
+- return (u32) (val * 1000ULL);
++ return state->symbol_rate;
+ }
+
+ static void s5h1420_setfreqoffset(struct s5h1420_state* state, int freqoffset)
+ {
+ int val;
++ u8 v;
++
++ dprintk("enter %s\n", __func__);
+
+ /* remember freqoffset is in kHz, but the chip wants the offset in Hz, so
+ * divide fclk by 1000000 to get the correct value. */
+ val = -(int) ((freqoffset * (1<<24)) / (state->fclk / 1000000));
+
+- s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) & 0xbf);
+- s5h1420_writereg(state, 0x0e, val >> 16);
+- s5h1420_writereg(state, 0x0f, val >> 8);
+- s5h1420_writereg(state, 0x10, val & 0xff);
+- s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) | 0x40);
++ dprintk("phase rotator/freqoffset: %d %06x\n", freqoffset, val);
++
++ v = s5h1420_readreg(state, Loop01);
++ s5h1420_writereg(state, Loop01, v & 0xbf);
++ s5h1420_writereg(state, Pnco01, val >> 16);
++ s5h1420_writereg(state, Pnco02, val >> 8);
++ s5h1420_writereg(state, Pnco03, val & 0xff);
++ s5h1420_writereg(state, Loop01, v | 0x40);
++ dprintk("leave %s\n", __func__);
+ }
+
+ static int s5h1420_getfreqoffset(struct s5h1420_state* state)
+@@ -496,52 +543,53 @@ static void s5h1420_setfec_inversion(struct s5h1420_state* state,
+ struct dvb_frontend_parameters *p)
+ {
+ u8 inversion = 0;
++ u8 vit08, vit09;
++
++ dprintk("enter %s\n", __func__);
+
+- if (p->inversion == INVERSION_OFF) {
++ if (p->inversion == INVERSION_OFF)
+ inversion = state->config->invert ? 0x08 : 0;
+- } else if (p->inversion == INVERSION_ON) {
++ else if (p->inversion == INVERSION_ON)
+ inversion = state->config->invert ? 0 : 0x08;
+- }
+
+ if ((p->u.qpsk.fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) {
+- s5h1420_writereg(state, 0x30, 0x3f);
+- s5h1420_writereg(state, 0x31, 0x00 | inversion);
++ vit08 = 0x3f;
++ vit09 = 0;
+ } else {
+ switch(p->u.qpsk.fec_inner) {
+ case FEC_1_2:
+- s5h1420_writereg(state, 0x30, 0x01);
+- s5h1420_writereg(state, 0x31, 0x10 | inversion);
++ vit08 = 0x01; vit09 = 0x10;
+ break;
+
+ case FEC_2_3:
+- s5h1420_writereg(state, 0x30, 0x02);
+- s5h1420_writereg(state, 0x31, 0x11 | inversion);
++ vit08 = 0x02; vit09 = 0x11;
+ break;
+
+ case FEC_3_4:
+- s5h1420_writereg(state, 0x30, 0x04);
+- s5h1420_writereg(state, 0x31, 0x12 | inversion);
++ vit08 = 0x04; vit09 = 0x12;
+ break;
+
+ case FEC_5_6:
+- s5h1420_writereg(state, 0x30, 0x08);
+- s5h1420_writereg(state, 0x31, 0x13 | inversion);
++ vit08 = 0x08; vit09 = 0x13;
+ break;
+
+ case FEC_6_7:
+- s5h1420_writereg(state, 0x30, 0x10);
+- s5h1420_writereg(state, 0x31, 0x14 | inversion);
++ vit08 = 0x10; vit09 = 0x14;
+ break;
+
+ case FEC_7_8:
+- s5h1420_writereg(state, 0x30, 0x20);
+- s5h1420_writereg(state, 0x31, 0x15 | inversion);
++ vit08 = 0x20; vit09 = 0x15;
+ break;
+
+ default:
+ return;
+ }
+ }
++ vit09 |= inversion;
++ dprintk("fec: %02x %02x\n", vit08, vit09);
++ s5h1420_writereg(state, Vit08, vit08);
++ s5h1420_writereg(state, Vit09, vit09);
++ dprintk("leave %s\n", __func__);
+ }
+
+ static fe_code_rate_t s5h1420_getfec(struct s5h1420_state* state)
+@@ -583,16 +631,19 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
+ struct s5h1420_state* state = fe->demodulator_priv;
+ int frequency_delta;
+ struct dvb_frontend_tune_settings fesettings;
++ uint8_t clock_settting;
++
++ dprintk("enter %s\n", __func__);
+
+ /* check if we should do a fast-tune */
+ memcpy(&fesettings.parameters, p, sizeof(struct dvb_frontend_parameters));
+ s5h1420_get_tune_settings(fe, &fesettings);
+ frequency_delta = p->frequency - state->tunedfreq;
+ if ((frequency_delta > -fesettings.max_drift) &&
+- (frequency_delta < fesettings.max_drift) &&
+- (frequency_delta != 0) &&
+- (state->fec_inner == p->u.qpsk.fec_inner) &&
+- (state->symbol_rate == p->u.qpsk.symbol_rate)) {
++ (frequency_delta < fesettings.max_drift) &&
++ (frequency_delta != 0) &&
++ (state->fec_inner == p->u.qpsk.fec_inner) &&
++ (state->symbol_rate == p->u.qpsk.symbol_rate)) {
+
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, p);
+@@ -606,54 +657,93 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
+ } else {
+ s5h1420_setfreqoffset(state, 0);
+ }
++ dprintk("simple tune\n");
+ return 0;
+ }
++ dprintk("tuning demod\n");
+
+ /* first of all, software reset */
+ s5h1420_reset(state);
+
+ /* set s5h1420 fclk PLL according to desired symbol rate */
+- if (p->u.qpsk.symbol_rate > 28000000) {
+- state->fclk = 88000000;
+- s5h1420_writereg(state, 0x03, 0x50);
+- s5h1420_writereg(state, 0x04, 0x40);
+- s5h1420_writereg(state, 0x05, 0xae);
+- } else if (p->u.qpsk.symbol_rate > 21000000) {
++ if (p->u.qpsk.symbol_rate > 33000000)
++ state->fclk = 80000000;
++ else if (p->u.qpsk.symbol_rate > 28500000)
+ state->fclk = 59000000;
+- s5h1420_writereg(state, 0x03, 0x33);
+- s5h1420_writereg(state, 0x04, 0x40);
+- s5h1420_writereg(state, 0x05, 0xae);
+- } else {
++ else if (p->u.qpsk.symbol_rate > 25000000)
++ state->fclk = 86000000;
++ else if (p->u.qpsk.symbol_rate > 1900000)
+ state->fclk = 88000000;
+- s5h1420_writereg(state, 0x03, 0x50);
+- s5h1420_writereg(state, 0x04, 0x40);
+- s5h1420_writereg(state, 0x05, 0xac);
++ else
++ state->fclk = 44000000;
++
++ /* Clock */
++ switch (state->fclk) {
++ default:
++ case 88000000:
++ clock_settting = 80;
++ break;
++ case 86000000:
++ clock_settting = 78;
++ break;
++ case 80000000:
++ clock_settting = 72;
++ break;
++ case 59000000:
++ clock_settting = 51;
++ break;
++ case 44000000:
++ clock_settting = 36;
++ break;
+ }
++ dprintk("pll01: %d, ToneFreq: %d\n", state->fclk/1000000 - 8, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
++ s5h1420_writereg(state, PLL01, state->fclk/1000000 - 8);
++ s5h1420_writereg(state, PLL02, 0x40);
++ s5h1420_writereg(state, DiS01, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
+
+- /* set misc registers */
+- s5h1420_writereg(state, 0x02, 0x00);
+- s5h1420_writereg(state, 0x06, 0x00);
+- s5h1420_writereg(state, 0x07, 0xb0);
+- s5h1420_writereg(state, 0x0a, 0xe7);
+- s5h1420_writereg(state, 0x0b, 0x78);
+- s5h1420_writereg(state, 0x0c, 0x48);
+- s5h1420_writereg(state, 0x0d, 0x6b);
+- s5h1420_writereg(state, 0x2e, 0x8e);
+- s5h1420_writereg(state, 0x35, 0x33);
+- s5h1420_writereg(state, 0x38, 0x01);
+- s5h1420_writereg(state, 0x39, 0x7d);
+- s5h1420_writereg(state, 0x3a, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
+- s5h1420_writereg(state, 0x3c, 0x00);
+- s5h1420_writereg(state, 0x45, 0x61);
+- s5h1420_writereg(state, 0x46, 0x1d);
++ /* TODO DC offset removal, config parameter ? */
++ if (p->u.qpsk.symbol_rate > 29000000)
++ s5h1420_writereg(state, QPSK01, 0xae | 0x10);
++ else
++ s5h1420_writereg(state, QPSK01, 0xac | 0x10);
+
+- /* start QPSK */
+- s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) | 1);
++ /* set misc registers */
++ s5h1420_writereg(state, CON_1, 0x00);
++ s5h1420_writereg(state, QPSK02, 0x00);
++ s5h1420_writereg(state, Pre01, 0xb0);
++
++ s5h1420_writereg(state, Loop01, 0xF0);
++ s5h1420_writereg(state, Loop02, 0x2a); /* e7 for s5h1420 */
++ s5h1420_writereg(state, Loop03, 0x79); /* 78 for s5h1420 */
++ if (p->u.qpsk.symbol_rate > 20000000)
++ s5h1420_writereg(state, Loop04, 0x79);
++ else
++ s5h1420_writereg(state, Loop04, 0x58);
++ s5h1420_writereg(state, Loop05, 0x6b);
++
++ if (p->u.qpsk.symbol_rate >= 8000000)
++ s5h1420_writereg(state, Post01, (0 << 6) | 0x10);
++ else if (p->u.qpsk.symbol_rate >= 4000000)
++ s5h1420_writereg(state, Post01, (1 << 6) | 0x10);
++ else
++ s5h1420_writereg(state, Post01, (3 << 6) | 0x10);
++
++ s5h1420_writereg(state, Monitor12, 0x00); /* unfreeze DC compensation */
++
++ s5h1420_writereg(state, Sync01, 0x33);
++ s5h1420_writereg(state, Mpeg01, state->config->cdclk_polarity);
++ s5h1420_writereg(state, Mpeg02, 0x3d); /* Parallel output more, disabled -> enabled later */
++ s5h1420_writereg(state, Err01, 0x03); /* 0x1d for s5h1420 */
++
++ s5h1420_writereg(state, Vit06, 0x6e); /* 0x8e for s5h1420 */
++ s5h1420_writereg(state, DiS03, 0x00);
++ s5h1420_writereg(state, Rf01, 0x61); /* Tuner i2c address - for the gate controller */
+
+ /* set tuner PLL */
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, p);
+- if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 0);
+ s5h1420_setfreqoffset(state, 0);
+ }
+
+@@ -661,10 +751,15 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
+ s5h1420_setsymbolrate(state, p);
+ s5h1420_setfec_inversion(state, p);
+
++ /* start QPSK */
++ s5h1420_writereg(state, QPSK01, s5h1420_readreg(state, QPSK01) | 1);
++
+ state->fec_inner = p->u.qpsk.fec_inner;
+ state->symbol_rate = p->u.qpsk.symbol_rate;
+ state->postlocked = 0;
+ state->tunedfreq = p->frequency;
++
++ dprintk("leave %s\n", __func__);
+ return 0;
+ }
+
+@@ -717,11 +812,10 @@ static int s5h1420_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+ {
+ struct s5h1420_state* state = fe->demodulator_priv;
+
+- if (enable) {
+- return s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
+- } else {
+- return s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) & 0xfe);
+- }
++ if (enable)
++ return s5h1420_writereg(state, 0x02, state->CON_1_val | 1);
++ else
++ return s5h1420_writereg(state, 0x02, state->CON_1_val & 0xfe);
+ }
+
+ static int s5h1420_init (struct dvb_frontend* fe)
+@@ -729,7 +823,8 @@ static int s5h1420_init (struct dvb_frontend* fe)
+ struct s5h1420_state* state = fe->demodulator_priv;
+
+ /* disable power down and do reset */
+- s5h1420_writereg(state, 0x02, 0x10);
++ state->CON_1_val = 0x10;
++ s5h1420_writereg(state, 0x02, state->CON_1_val);
+ msleep(10);
+ s5h1420_reset(state);
+
+@@ -739,26 +834,60 @@ static int s5h1420_init (struct dvb_frontend* fe)
+ static int s5h1420_sleep(struct dvb_frontend* fe)
+ {
+ struct s5h1420_state* state = fe->demodulator_priv;
+-
+- return s5h1420_writereg(state, 0x02, 0x12);
++ state->CON_1_val = 0x12;
++ return s5h1420_writereg(state, 0x02, state->CON_1_val);
+ }
+
+ static void s5h1420_release(struct dvb_frontend* fe)
+ {
+ struct s5h1420_state* state = fe->demodulator_priv;
++ i2c_del_adapter(&state->tuner_i2c_adapter);
+ kfree(state);
+ }
+
+-static struct dvb_frontend_ops s5h1420_ops;
++static u32 s5h1420_tuner_i2c_func(struct i2c_adapter *adapter)
++{
++ return I2C_FUNC_I2C;
++}
++
++static int s5h1420_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
++{
++ struct s5h1420_state *state = i2c_get_adapdata(i2c_adap);
++ struct i2c_msg m[1 + num];
++ u8 tx_open[2] = { CON_1, state->CON_1_val | 1 }; /* repeater stops once there was a stop condition */
++
++ memset(m, 0, sizeof(struct i2c_msg) * (1 + num));
++
++ m[0].addr = state->config->demod_address;
++ m[0].buf = tx_open;
++ m[0].len = 2;
+
+-struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
+- struct i2c_adapter* i2c)
++ memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
++
++ return i2c_transfer(state->i2c, m, 1+num) == 1 + num ? num : -EIO;
++}
++
++static struct i2c_algorithm s5h1420_tuner_i2c_algo = {
++ .master_xfer = s5h1420_tuner_i2c_tuner_xfer,
++ .functionality = s5h1420_tuner_i2c_func,
++};
++
++struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe)
+ {
+- struct s5h1420_state* state = NULL;
+- u8 identity;
++ struct s5h1420_state *state = fe->demodulator_priv;
++ return &state->tuner_i2c_adapter;
++}
++EXPORT_SYMBOL(s5h1420_get_tuner_i2c_adapter);
++
++static struct dvb_frontend_ops s5h1420_ops;
+
++struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
++ struct i2c_adapter *i2c)
++{
+ /* allocate memory for the internal state */
+- state = kmalloc(sizeof(struct s5h1420_state), GFP_KERNEL);
++ struct s5h1420_state *state = kzalloc(sizeof(struct s5h1420_state), GFP_KERNEL);
++ u8 i;
++
+ if (state == NULL)
+ goto error;
+
+@@ -772,24 +901,42 @@ struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
+ state->symbol_rate = 0;
+
+ /* check if the demod is there + identify it */
+- identity = s5h1420_readreg(state, 0x00);
+- if (identity != 0x03)
++ i = s5h1420_readreg(state, ID01);
++ if (i != 0x03)
+ goto error;
+
++ memset(state->shadow, 0xff, sizeof(state->shadow));
++
++ for (i = 0; i < 0x50; i++)
++ state->shadow[i] = s5h1420_readreg(state, i);
++
+ /* create dvb_frontend */
+ memcpy(&state->frontend.ops, &s5h1420_ops, sizeof(struct dvb_frontend_ops));
+ state->frontend.demodulator_priv = state;
++
++ /* create tuner i2c adapter */
++ strncpy(state->tuner_i2c_adapter.name, "S5H1420-PN1010 tuner I2C bus", I2C_NAME_SIZE);
++ state->tuner_i2c_adapter.class = I2C_CLASS_TV_DIGITAL,
++ state->tuner_i2c_adapter.algo = &s5h1420_tuner_i2c_algo;
++ state->tuner_i2c_adapter.algo_data = NULL;
++ i2c_set_adapdata(&state->tuner_i2c_adapter, state);
++ if (i2c_add_adapter(&state->tuner_i2c_adapter) < 0) {
++ printk(KERN_ERR "S5H1420/PN1010: tuner i2c bus could not be initialized\n");
++ goto error;
++ }
++
+ return &state->frontend;
+
+ error:
+ kfree(state);
+ return NULL;
+ }
++EXPORT_SYMBOL(s5h1420_attach);
+
+ static struct dvb_frontend_ops s5h1420_ops = {
+
+ .info = {
+- .name = "Samsung S5H1420 DVB-S",
++ .name = "Samsung S5H1420/PnpNetwork PN1010 DVB-S",
+ .type = FE_QPSK,
+ .frequency_min = 950000,
+ .frequency_max = 2150000,
+@@ -826,10 +973,6 @@ static struct dvb_frontend_ops s5h1420_ops = {
+ .set_voltage = s5h1420_set_voltage,
+ };
+
+-module_param(debug, int, 0644);
+-
+-MODULE_DESCRIPTION("Samsung S5H1420 DVB-S Demodulator driver");
+-MODULE_AUTHOR("Andrew de Quincey");
++MODULE_DESCRIPTION("Samsung S5H1420/PnpNetwork PN1010 DVB-S Demodulator driver");
++MODULE_AUTHOR("Andrew de Quincey, Patrick Boettcher");
+ MODULE_LICENSE("GPL");
+-
+-EXPORT_SYMBOL(s5h1420_attach);
+diff --git a/drivers/media/dvb/frontends/s5h1420.h b/drivers/media/dvb/frontends/s5h1420.h
+index 1555870..4c913f1 100644
+--- a/drivers/media/dvb/frontends/s5h1420.h
++++ b/drivers/media/dvb/frontends/s5h1420.h
+@@ -1,25 +1,26 @@
+ /*
+- Driver for S5H1420 QPSK Demodulators
+-
+- Copyright (C) 2005 Andrew de Quincey <adq_dvb at lidskialf.net>
+-
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; either version 2 of the License, or
+- (at your option) any later version.
+-
+- This program is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-
+- GNU General Public License for more details.
+-
+- You should have received a copy of the GNU General Public License
+- along with this program; if not, write to the Free Software
+- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-
+-*/
+-
++ * Driver for
++ * Samsung S5H1420 and
++ * PnpNetwork PN1010 QPSK Demodulator
++ *
++ * Copyright (C) 2005 Andrew de Quincey <adq_dvb at lidskialf.net>
++ * Copyright (C) 2005-8 Patrick Boettcher <pb at linuxtv.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
+ #ifndef S5H1420_H
+ #define S5H1420_H
+
+@@ -31,17 +32,26 @@ struct s5h1420_config
+ u8 demod_address;
+
+ /* does the inversion require inversion? */
+- u8 invert:1;
++ u8 invert : 1;
++
++ u8 repeated_start_workaround : 1;
++ u8 cdclk_polarity : 1; /* 1 == falling edge, 0 == raising edge */
+ };
+
+ #if defined(CONFIG_DVB_S5H1420) || (defined(CONFIG_DVB_S5H1420_MODULE) && defined(MODULE))
+-extern struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
+- struct i2c_adapter* i2c);
++extern struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
++ struct i2c_adapter *i2c);
++extern struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe);
+ #else
+-static inline struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
+- struct i2c_adapter* i2c)
++static inline struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
++ struct i2c_adapter *i2c)
++{
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++ return NULL;
++}
++
++static inline struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_S5H1420
+diff --git a/drivers/media/dvb/frontends/s5h1420_priv.h b/drivers/media/dvb/frontends/s5h1420_priv.h
+new file mode 100644
+index 0000000..d9c58d2
+--- /dev/null
++++ b/drivers/media/dvb/frontends/s5h1420_priv.h
+@@ -0,0 +1,102 @@
++/*
++ * Driver for
++ * Samsung S5H1420 and
++ * PnpNetwork PN1010 QPSK Demodulator
++ *
++ * Copyright (C) 2005 Andrew de Quincey <adq_dvb at lidskialf.net>
++ * Copyright (C) 2005 Patrick Boettcher <pb at linuxtv.org>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the Free
++ * Software Foundation; either version 2 of the License, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 675 Mass
++ * Ave, Cambridge, MA 02139, USA.
++ */
++#ifndef S5H1420_PRIV
++#define S5H1420_PRIV
++
++#include <asm/types.h>
++
++enum s5h1420_register {
++ ID01 = 0x00,
++ CON_0 = 0x01,
++ CON_1 = 0x02,
++ PLL01 = 0x03,
++ PLL02 = 0x04,
++ QPSK01 = 0x05,
++ QPSK02 = 0x06,
++ Pre01 = 0x07,
++ Post01 = 0x08,
++ Loop01 = 0x09,
++ Loop02 = 0x0a,
++ Loop03 = 0x0b,
++ Loop04 = 0x0c,
++ Loop05 = 0x0d,
++ Pnco01 = 0x0e,
++ Pnco02 = 0x0f,
++ Pnco03 = 0x10,
++ Tnco01 = 0x11,
++ Tnco02 = 0x12,
++ Tnco03 = 0x13,
++ Monitor01 = 0x14,
++ Monitor02 = 0x15,
++ Monitor03 = 0x16,
++ Monitor04 = 0x17,
++ Monitor05 = 0x18,
++ Monitor06 = 0x19,
++ Monitor07 = 0x1a,
++ Monitor12 = 0x1f,
++
++ FEC01 = 0x22,
++ Soft01 = 0x23,
++ Soft02 = 0x24,
++ Soft03 = 0x25,
++ Soft04 = 0x26,
++ Soft05 = 0x27,
++ Soft06 = 0x28,
++ Vit01 = 0x29,
++ Vit02 = 0x2a,
++ Vit03 = 0x2b,
++ Vit04 = 0x2c,
++ Vit05 = 0x2d,
++ Vit06 = 0x2e,
++ Vit07 = 0x2f,
++ Vit08 = 0x30,
++ Vit09 = 0x31,
++ Vit10 = 0x32,
++ Vit11 = 0x33,
++ Vit12 = 0x34,
++ Sync01 = 0x35,
++ Sync02 = 0x36,
++ Rs01 = 0x37,
++ Mpeg01 = 0x38,
++ Mpeg02 = 0x39,
++ DiS01 = 0x3a,
++ DiS02 = 0x3b,
++ DiS03 = 0x3c,
++ DiS04 = 0x3d,
++ DiS05 = 0x3e,
++ DiS06 = 0x3f,
++ DiS07 = 0x40,
++ DiS08 = 0x41,
++ DiS09 = 0x42,
++ DiS10 = 0x43,
++ DiS11 = 0x44,
++ Rf01 = 0x45,
++ Err01 = 0x46,
++ Err02 = 0x47,
++ Err03 = 0x48,
++ Err04 = 0x49,
++};
++
++
++#endif
+diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c
+index da876f7..aa78aa1 100644
+--- a/drivers/media/dvb/frontends/sp8870.c
++++ b/drivers/media/dvb/frontends/sp8870.c
+@@ -70,7 +70,7 @@ static int sp8870_writereg (struct sp8870_state* state, u16 reg, u16 data)
+ int err;
+
+ if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+- dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data);
++ dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
+ return -EREMOTEIO;
+ }
+
+@@ -88,7 +88,7 @@ static int sp8870_readreg (struct sp8870_state* state, u16 reg)
+ ret = i2c_transfer (state->i2c, msg, 2);
+
+ if (ret != 2) {
+- dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
++ dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
+ return -1;
+ }
+
+@@ -104,7 +104,7 @@ static int sp8870_firmware_upload (struct sp8870_state* state, const struct firm
+ int tx_len;
+ int err = 0;
+
+- dprintk ("%s: ...\n", __FUNCTION__);
++ dprintk ("%s: ...\n", __func__);
+
+ if (fw->size < SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET)
+ return -EINVAL;
+@@ -131,14 +131,14 @@ static int sp8870_firmware_upload (struct sp8870_state* state, const struct firm
+ msg.buf = tx_buf;
+ msg.len = tx_len + 2;
+ if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+- printk("%s: firmware upload failed!\n", __FUNCTION__);
+- printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err);
++ printk("%s: firmware upload failed!\n", __func__);
++ printk ("%s: i2c error (err == %i)\n", __func__, err);
+ return err;
+ }
+ fw_pos += tx_len;
+ }
+
+- dprintk ("%s: done!\n", __FUNCTION__);
++ dprintk ("%s: done!\n", __func__);
+ return 0;
+ };
+
+@@ -310,7 +310,7 @@ static int sp8870_init (struct dvb_frontend* fe)
+ if (state->initialised) return 0;
+ state->initialised = 1;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+
+ /* request the firmware, this will block until someone uploads it */
+@@ -449,15 +449,15 @@ static int sp8870_read_uncorrected_blocks (struct dvb_frontend* fe, u32* ublocks
+ return 0;
+ }
+
+-// number of trials to recover from lockup
++/* number of trials to recover from lockup */
+ #define MAXTRIALS 5
+-// maximum checks for data valid signal
++/* maximum checks for data valid signal */
+ #define MAXCHECKS 100
+
+-// only for debugging: counter for detected lockups
+-static int lockups = 0;
+-// only for debugging: counter for channel switches
+-static int switches = 0;
++/* only for debugging: counter for detected lockups */
++static int lockups;
++/* only for debugging: counter for channel switches */
++static int switches;
+
+ static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+ {
+@@ -475,7 +475,7 @@ static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_par
+ int trials = 0;
+ int check_count = 0;
+
+- dprintk("%s: frequency = %i\n", __FUNCTION__, p->frequency);
++ dprintk("%s: frequency = %i\n", __func__, p->frequency);
+
+ for (trials = 1; trials <= MAXTRIALS; trials++) {
+
+@@ -487,7 +487,7 @@ static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_par
+ valid = sp8870_read_data_valid_signal(state);
+ if (valid) {
+ dprintk("%s: delay = %i usec\n",
+- __FUNCTION__, check_count * 10);
++ __func__, check_count * 10);
+ break;
+ }
+ udelay(10);
+@@ -497,20 +497,20 @@ static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_par
+ }
+
+ if (!valid) {
+- printk("%s: firmware crash!!!!!!\n", __FUNCTION__);
++ printk("%s: firmware crash!!!!!!\n", __func__);
+ return -EIO;
+ }
+
+ if (debug) {
+ if (valid) {
+ if (trials > 1) {
+- printk("%s: firmware lockup!!!\n", __FUNCTION__);
+- printk("%s: recovered after %i trial(s))\n", __FUNCTION__, trials - 1);
++ printk("%s: firmware lockup!!!\n", __func__);
++ printk("%s: recovered after %i trial(s))\n", __func__, trials - 1);
+ lockups++;
+ }
+ }
+ switches++;
+- printk("%s: switches = %i lockups = %i\n", __FUNCTION__, switches, lockups);
++ printk("%s: switches = %i lockups = %i\n", __func__, switches, lockups);
+ }
+
+ return 0;
+diff --git a/drivers/media/dvb/frontends/sp8870.h b/drivers/media/dvb/frontends/sp8870.h
+index 909cefe..a764a79 100644
+--- a/drivers/media/dvb/frontends/sp8870.h
++++ b/drivers/media/dvb/frontends/sp8870.h
+@@ -42,7 +42,7 @@ extern struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
+ static inline struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
+ struct i2c_adapter* i2c)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_SP8870
+diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c
+index 1aa2539..49f5587 100644
+--- a/drivers/media/dvb/frontends/sp887x.c
++++ b/drivers/media/dvb/frontends/sp887x.c
+@@ -43,7 +43,7 @@ static int i2c_writebytes (struct sp887x_state* state, u8 *buf, u8 len)
+
+ if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+ printk ("%s: i2c write error (addr %02x, err == %i)\n",
+- __FUNCTION__, state->config->demod_address, err);
++ __func__, state->config->demod_address, err);
+ return -EREMOTEIO;
+ }
+
+@@ -65,7 +65,7 @@ static int sp887x_writereg (struct sp887x_state* state, u16 reg, u16 data)
+ {
+ printk("%s: writereg error "
+ "(reg %03x, data %03x, ret == %i)\n",
+- __FUNCTION__, reg & 0xffff, data & 0xffff, ret);
++ __func__, reg & 0xffff, data & 0xffff, ret);
+ return ret;
+ }
+ }
+@@ -82,7 +82,7 @@ static int sp887x_readreg (struct sp887x_state* state, u16 reg)
+ { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 2 }};
+
+ if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
+- printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
++ printk("%s: readreg error (ret == %i)\n", __func__, ret);
+ return -1;
+ }
+
+@@ -91,7 +91,7 @@ static int sp887x_readreg (struct sp887x_state* state, u16 reg)
+
+ static void sp887x_microcontroller_stop (struct sp887x_state* state)
+ {
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+ sp887x_writereg(state, 0xf08, 0x000);
+ sp887x_writereg(state, 0xf09, 0x000);
+
+@@ -101,7 +101,7 @@ static void sp887x_microcontroller_stop (struct sp887x_state* state)
+
+ static void sp887x_microcontroller_start (struct sp887x_state* state)
+ {
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+ sp887x_writereg(state, 0xf08, 0x000);
+ sp887x_writereg(state, 0xf09, 0x000);
+
+@@ -112,7 +112,7 @@ static void sp887x_microcontroller_start (struct sp887x_state* state)
+ static void sp887x_setup_agc (struct sp887x_state* state)
+ {
+ /* setup AGC parameters */
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+ sp887x_writereg(state, 0x33c, 0x054);
+ sp887x_writereg(state, 0x33b, 0x04c);
+ sp887x_writereg(state, 0x328, 0x000);
+@@ -142,7 +142,7 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware
+ int fw_size = fw->size;
+ unsigned char *mem = fw->data;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ /* ignore the first 10 bytes, then we expect 0x4000 bytes of firmware */
+ if (fw_size < FW_SIZE+10)
+@@ -155,7 +155,7 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware
+
+ sp887x_microcontroller_stop (state);
+
+- printk ("%s: firmware upload... ", __FUNCTION__);
++ printk ("%s: firmware upload... ", __func__);
+
+ /* setup write pointer to -1 (end of memory) */
+ /* bit 0x8000 in address is set to enable 13bit mode */
+@@ -181,7 +181,7 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware
+
+ if ((err = i2c_writebytes (state, buf, c+2)) < 0) {
+ printk ("failed.\n");
+- printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err);
++ printk ("%s: i2c error (err == %i)\n", __func__, err);
+ return err;
+ }
+ }
+diff --git a/drivers/media/dvb/frontends/sp887x.h b/drivers/media/dvb/frontends/sp887x.h
+index 7ee78d7..04eff6e 100644
+--- a/drivers/media/dvb/frontends/sp887x.h
++++ b/drivers/media/dvb/frontends/sp887x.h
+@@ -24,7 +24,7 @@ extern struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
+ static inline struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
+ struct i2c_adapter* i2c)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_SP887X
+diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c
+index 7c23775..62caf80 100644
+--- a/drivers/media/dvb/frontends/stv0297.c
++++ b/drivers/media/dvb/frontends/stv0297.c
+@@ -58,7 +58,7 @@ static int stv0297_writereg(struct stv0297_state *state, u8 reg, u8 data)
+
+ if (ret != 1)
+ dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
+- "ret == %i)\n", __FUNCTION__, reg, data, ret);
++ "ret == %i)\n", __func__, reg, data, ret);
+
+ return (ret != 1) ? -1 : 0;
+ }
+@@ -75,16 +75,16 @@ static int stv0297_readreg(struct stv0297_state *state, u8 reg)
+ // this device needs a STOP between the register and data
+ if (state->config->stop_during_read) {
+ if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
+- dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
++ dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret);
+ return -1;
+ }
+ if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
+- dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
++ dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret);
+ return -1;
+ }
+ } else {
+ if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
+- dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
++ dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret);
+ return -1;
+ }
+ }
+@@ -115,16 +115,16 @@ static int stv0297_readregs(struct stv0297_state *state, u8 reg1, u8 * b, u8 len
+ // this device needs a STOP between the register and data
+ if (state->config->stop_during_read) {
+ if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
+- dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
++ dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg1, ret);
+ return -1;
+ }
+ if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
+- dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
++ dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg1, ret);
+ return -1;
+ }
+ } else {
+ if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
+- dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
++ dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg1, ret);
+ return -1;
+ }
+ }
+diff --git a/drivers/media/dvb/frontends/stv0297.h b/drivers/media/dvb/frontends/stv0297.h
+index 69f4515..3f8f946 100644
+--- a/drivers/media/dvb/frontends/stv0297.h
++++ b/drivers/media/dvb/frontends/stv0297.h
+@@ -49,7 +49,7 @@ extern struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
+ static inline struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
+ struct i2c_adapter* i2c)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_STV0297
+diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c
+index 035dd7b..1755618 100644
+--- a/drivers/media/dvb/frontends/stv0299.c
++++ b/drivers/media/dvb/frontends/stv0299.c
+@@ -86,7 +86,7 @@ static int stv0299_writeregI (struct stv0299_state* state, u8 reg, u8 data)
+
+ if (ret != 1)
+ dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
+- "ret == %i)\n", __FUNCTION__, reg, data, ret);
++ "ret == %i)\n", __func__, reg, data, ret);
+
+ return (ret != 1) ? -EREMOTEIO : 0;
+ }
+@@ -113,7 +113,7 @@ static u8 stv0299_readreg (struct stv0299_state* state, u8 reg)
+
+ if (ret != 2)
+ dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
+- __FUNCTION__, reg, ret);
++ __func__, reg, ret);
+
+ return b1[0];
+ }
+@@ -127,14 +127,14 @@ static int stv0299_readregs (struct stv0299_state* state, u8 reg1, u8 *b, u8 len
+ ret = i2c_transfer (state->i2c, msg, 2);
+
+ if (ret != 2)
+- dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
++ dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
+
+ return ret == 2 ? 0 : ret;
+ }
+
+ static int stv0299_set_FEC (struct stv0299_state* state, fe_code_rate_t fec)
+ {
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ switch (fec) {
+ case FEC_AUTO:
+@@ -174,7 +174,7 @@ static fe_code_rate_t stv0299_get_fec (struct stv0299_state* state)
+ FEC_7_8, FEC_1_2 };
+ u8 index;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ index = stv0299_readreg (state, 0x1b);
+ index &= 0x7;
+@@ -189,11 +189,11 @@ static int stv0299_wait_diseqc_fifo (struct stv0299_state* state, int timeout)
+ {
+ unsigned long start = jiffies;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ while (stv0299_readreg(state, 0x0a) & 1) {
+ if (jiffies - start > timeout) {
+- dprintk ("%s: timeout!!\n", __FUNCTION__);
++ dprintk ("%s: timeout!!\n", __func__);
+ return -ETIMEDOUT;
+ }
+ msleep(10);
+@@ -206,11 +206,11 @@ static int stv0299_wait_diseqc_idle (struct stv0299_state* state, int timeout)
+ {
+ unsigned long start = jiffies;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ while ((stv0299_readreg(state, 0x0a) & 3) != 2 ) {
+ if (jiffies - start > timeout) {
+- dprintk ("%s: timeout!!\n", __FUNCTION__);
++ dprintk ("%s: timeout!!\n", __func__);
+ return -ETIMEDOUT;
+ }
+ msleep(10);
+@@ -245,7 +245,7 @@ static int stv0299_get_symbolrate (struct stv0299_state* state)
+ u8 sfr[3];
+ s8 rtf;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ stv0299_readregs (state, 0x1f, sfr, 3);
+ stv0299_readregs (state, 0x1a, (u8 *)&rtf, 1);
+@@ -257,8 +257,8 @@ static int stv0299_get_symbolrate (struct stv0299_state* state)
+ offset = (s32) rtf * (srate / 4096L);
+ offset /= 128;
+
+- dprintk ("%s : srate = %i\n", __FUNCTION__, srate);
+- dprintk ("%s : ofset = %i\n", __FUNCTION__, offset);
++ dprintk ("%s : srate = %i\n", __func__, srate);
++ dprintk ("%s : ofset = %i\n", __func__, offset);
+
+ srate += offset;
+
+@@ -276,7 +276,7 @@ static int stv0299_send_diseqc_msg (struct dvb_frontend* fe,
+ u8 val;
+ int i;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ if (stv0299_wait_diseqc_idle (state, 100) < 0)
+ return -ETIMEDOUT;
+@@ -305,7 +305,7 @@ static int stv0299_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t
+ struct stv0299_state* state = fe->demodulator_priv;
+ u8 val;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ if (stv0299_wait_diseqc_idle (state, 100) < 0)
+ return -ETIMEDOUT;
+@@ -355,7 +355,7 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
+ u8 reg0x08;
+ u8 reg0x0c;
+
+- dprintk("%s: %s\n", __FUNCTION__,
++ dprintk("%s: %s\n", __func__,
+ voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
+ voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
+
+@@ -366,26 +366,32 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
+ * H/V switching over OP0, OP1 and OP2 are LNB power enable bits
+ */
+ reg0x0c &= 0x0f;
+-
+- if (voltage == SEC_VOLTAGE_OFF) {
+- stv0299_writeregI (state, 0x0c, 0x00); /* LNB power off! */
+- return stv0299_writeregI (state, 0x08, 0x00); /* LNB power off! */
+- }
+-
+- stv0299_writeregI (state, 0x08, (reg0x08 & 0x3f) | (state->config->lock_output << 6));
++ reg0x08 = (reg0x08 & 0x3f) | (state->config->lock_output << 6);
+
+ switch (voltage) {
+ case SEC_VOLTAGE_13:
+- if (state->config->volt13_op0_op1 == STV0299_VOLT13_OP0) reg0x0c |= 0x10;
+- else reg0x0c |= 0x40;
+-
+- return stv0299_writeregI(state, 0x0c, reg0x0c);
+-
++ if (state->config->volt13_op0_op1 == STV0299_VOLT13_OP0)
++ reg0x0c |= 0x10; /* OP1 off, OP0 on */
++ else
++ reg0x0c |= 0x40; /* OP1 on, OP0 off */
++ break;
+ case SEC_VOLTAGE_18:
+- return stv0299_writeregI(state, 0x0c, reg0x0c | 0x50);
++ reg0x0c |= 0x50; /* OP1 on, OP0 on */
++ break;
++ case SEC_VOLTAGE_OFF:
++ /* LNB power off! */
++ reg0x08 = 0x00;
++ reg0x0c = 0x00;
++ break;
+ default:
+ return -EINVAL;
+ };
++
++ if (state->config->op0_off)
++ reg0x0c &= ~0x10;
++
++ stv0299_writeregI(state, 0x08, reg0x08);
++ return stv0299_writeregI(state, 0x0c, reg0x0c);
+ }
+
+ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long cmd)
+@@ -408,7 +414,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long
+
+ cmd = cmd << 1;
+ if (debug_legacy_dish_switch)
+- printk ("%s switch command: 0x%04lx\n",__FUNCTION__, cmd);
++ printk ("%s switch command: 0x%04lx\n",__func__, cmd);
+
+ do_gettimeofday (&nexttime);
+ if (debug_legacy_dish_switch)
+@@ -433,7 +439,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long
+ }
+ if (debug_legacy_dish_switch) {
+ printk ("%s(%d): switch delay (should be 32k followed by all 8k\n",
+- __FUNCTION__, fe->dvb->num);
++ __func__, fe->dvb->num);
+ for (i = 1; i < 10; i++)
+ printk ("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
+ }
+@@ -445,11 +451,20 @@ static int stv0299_init (struct dvb_frontend* fe)
+ {
+ struct stv0299_state* state = fe->demodulator_priv;
+ int i;
++ u8 reg;
++ u8 val;
+
+ dprintk("stv0299: init chip\n");
+
+- for (i=0; !(state->config->inittab[i] == 0xff && state->config->inittab[i+1] == 0xff); i+=2)
+- stv0299_writeregI(state, state->config->inittab[i], state->config->inittab[i+1]);
++ for (i = 0; ; i += 2) {
++ reg = state->config->inittab[i];
++ val = state->config->inittab[i+1];
++ if (reg == 0xff && val == 0xff)
++ break;
++ if (reg == 0x0c && state->config->op0_off)
++ val &= ~0x10;
++ stv0299_writeregI(state, reg, val);
++ }
+
+ return 0;
+ }
+@@ -461,7 +476,7 @@ static int stv0299_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ u8 signal = 0xff - stv0299_readreg (state, 0x18);
+ u8 sync = stv0299_readreg (state, 0x1b);
+
+- dprintk ("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __FUNCTION__, sync);
++ dprintk ("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, sync);
+ *status = 0;
+
+ if (signal > 10)
+@@ -499,7 +514,7 @@ static int stv0299_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+ s32 signal = 0xffff - ((stv0299_readreg (state, 0x18) << 8)
+ | stv0299_readreg (state, 0x19));
+
+- dprintk ("%s : FE_READ_SIGNAL_STRENGTH : AGC2I: 0x%02x%02x, signal=0x%04x\n", __FUNCTION__,
++ dprintk ("%s : FE_READ_SIGNAL_STRENGTH : AGC2I: 0x%02x%02x, signal=0x%04x\n", __func__,
+ stv0299_readreg (state, 0x18),
+ stv0299_readreg (state, 0x19), (int) signal);
+
+@@ -536,7 +551,7 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
+ struct stv0299_state* state = fe->demodulator_priv;
+ int invval = 0;
+
+- dprintk ("%s : FE_SET_FRONTEND\n", __FUNCTION__);
++ dprintk ("%s : FE_SET_FRONTEND\n", __func__);
+
+ // set the inversion
+ if (p->inversion == INVERSION_OFF) invval = 0;
+diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb/frontends/stv0299.h
+index 33df949..3282f43 100644
+--- a/drivers/media/dvb/frontends/stv0299.h
++++ b/drivers/media/dvb/frontends/stv0299.h
+@@ -48,10 +48,10 @@
+ #include <linux/dvb/frontend.h>
+ #include "dvb_frontend.h"
+
+-#define STV0229_LOCKOUTPUT_0 0
+-#define STV0229_LOCKOUTPUT_1 1
+-#define STV0229_LOCKOUTPUT_CF 2
+-#define STV0229_LOCKOUTPUT_LK 3
++#define STV0299_LOCKOUTPUT_0 0
++#define STV0299_LOCKOUTPUT_1 1
++#define STV0299_LOCKOUTPUT_CF 2
++#define STV0299_LOCKOUTPUT_LK 3
+
+ #define STV0299_VOLT13_OP0 0
+ #define STV0299_VOLT13_OP1 1
+@@ -82,6 +82,9 @@ struct stv0299_config
+ /* Is 13v controlled by OP0 or OP1? */
+ u8 volt13_op0_op1:1;
+
++ /* Turn-off OP0? */
++ u8 op0_off:1;
++
+ /* minimum delay before retuning */
+ int min_delay_ms;
+
+@@ -96,7 +99,7 @@ extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
+ static inline struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
+ struct i2c_adapter* i2c)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_STV0299
+diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c
+index 45137d2..f648fdb 100644
+--- a/drivers/media/dvb/frontends/tda10021.c
++++ b/drivers/media/dvb/frontends/tda10021.c
+@@ -79,7 +79,7 @@ static int _tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data)
+ if (ret != 1)
+ printk("DVB: TDA10021(%d): %s, writereg error "
+ "(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+- state->frontend.dvb->num, __FUNCTION__, reg, data, ret);
++ state->frontend.dvb->num, __func__, reg, data, ret);
+
+ msleep(10);
+ return (ret != 1) ? -EREMOTEIO : 0;
+@@ -97,7 +97,7 @@ static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
+ // Don't print an error message if the id is read.
+ if (ret != 2 && reg != 0x1a)
+ printk("DVB: TDA10021: %s: readreg error (ret == %i)\n",
+- __FUNCTION__, ret);
++ __func__, ret);
+ return b1[0];
+ }
+
+diff --git a/drivers/media/dvb/frontends/tda10023.c b/drivers/media/dvb/frontends/tda10023.c
+index 364bc01..0727b80 100644
+--- a/drivers/media/dvb/frontends/tda10023.c
++++ b/drivers/media/dvb/frontends/tda10023.c
+@@ -118,7 +118,7 @@ static u8 tda10023_readreg (struct tda10023_state* state, u8 reg)
+ ret = i2c_transfer (state->i2c, msg, 2);
+ if (ret != 2)
+ printk("DVB: TDA10023: %s: readreg error (ret == %i)\n",
+- __FUNCTION__, ret);
++ __func__, ret);
+ return b1[0];
+ }
+
+@@ -132,7 +132,7 @@ static int tda10023_writereg (struct tda10023_state* state, u8 reg, u8 data)
+ if (ret != 1)
+ printk("DVB: TDA10023(%d): %s, writereg error "
+ "(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+- state->frontend.dvb->num, __FUNCTION__, reg, data, ret);
++ state->frontend.dvb->num, __func__, reg, data, ret);
+
+ return (ret != 1) ? -EREMOTEIO : 0;
+ }
+diff --git a/drivers/media/dvb/frontends/tda1002x.h b/drivers/media/dvb/frontends/tda1002x.h
+index e9094d8..1bcc0d4 100644
+--- a/drivers/media/dvb/frontends/tda1002x.h
++++ b/drivers/media/dvb/frontends/tda1002x.h
+@@ -40,7 +40,7 @@ extern struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config
+ static inline struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config,
+ struct i2c_adapter* i2c, u8 pwm)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_TDA10021
+@@ -52,7 +52,7 @@ extern struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config
+ static inline struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config,
+ struct i2c_adapter* i2c, u8 pwm)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_TDA10023
+diff --git a/drivers/media/dvb/frontends/tda10048.c b/drivers/media/dvb/frontends/tda10048.c
+new file mode 100644
+index 0000000..090fb7d
+--- /dev/null
++++ b/drivers/media/dvb/frontends/tda10048.c
+@@ -0,0 +1,841 @@
++/*
++ NXP TDA10048HN DVB OFDM demodulator driver
++
++ Copyright (C) 2008 Steven Toth <stoth at hauppauge.com>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++*/
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include "dvb_frontend.h"
++#include "dvb_math.h"
++#include "tda10048.h"
++
++#define TDA10048_DEFAULT_FIRMWARE "dvb-fe-tda10048-1.0.fw"
++#define TDA10048_DEFAULT_FIRMWARE_SIZE 24878
++
++/* Register name definitions */
++#define TDA10048_IDENTITY 0x00
++#define TDA10048_VERSION 0x01
++#define TDA10048_DSP_CODE_CPT 0x0C
++#define TDA10048_DSP_CODE_IN 0x0E
++#define TDA10048_IN_CONF1 0x10
++#define TDA10048_IN_CONF2 0x11
++#define TDA10048_IN_CONF3 0x12
++#define TDA10048_OUT_CONF1 0x14
++#define TDA10048_OUT_CONF2 0x15
++#define TDA10048_OUT_CONF3 0x16
++#define TDA10048_AUTO 0x18
++#define TDA10048_SYNC_STATUS 0x1A
++#define TDA10048_CONF_C4_1 0x1E
++#define TDA10048_CONF_C4_2 0x1F
++#define TDA10048_CODE_IN_RAM 0x20
++#define TDA10048_CHANNEL_INFO_1_R 0x22
++#define TDA10048_CHANNEL_INFO_2_R 0x23
++#define TDA10048_CHANNEL_INFO1 0x24
++#define TDA10048_CHANNEL_INFO2 0x25
++#define TDA10048_TIME_ERROR_R 0x26
++#define TDA10048_TIME_ERROR 0x27
++#define TDA10048_FREQ_ERROR_LSB_R 0x28
++#define TDA10048_FREQ_ERROR_MSB_R 0x29
++#define TDA10048_FREQ_ERROR_LSB 0x2A
++#define TDA10048_FREQ_ERROR_MSB 0x2B
++#define TDA10048_IT_SEL 0x30
++#define TDA10048_IT_STAT 0x32
++#define TDA10048_DSP_AD_LSB 0x3C
++#define TDA10048_DSP_AD_MSB 0x3D
++#define TDA10048_DSP_REF_LSB 0x3E
++#define TDA10048_DSP_REF_MSB 0x3F
++#define TDA10048_CONF_TRISTATE1 0x44
++#define TDA10048_CONF_TRISTATE2 0x45
++#define TDA10048_CONF_POLARITY 0x46
++#define TDA10048_GPIO_SP_DS0 0x48
++#define TDA10048_GPIO_SP_DS1 0x49
++#define TDA10048_GPIO_SP_DS2 0x4A
++#define TDA10048_GPIO_SP_DS3 0x4B
++#define TDA10048_GPIO_OUT_SEL 0x4C
++#define TDA10048_GPIO_SELECT 0x4D
++#define TDA10048_IC_MODE 0x4E
++#define TDA10048_CONF_XO 0x50
++#define TDA10048_CONF_PLL1 0x51
++#define TDA10048_CONF_PLL2 0x52
++#define TDA10048_CONF_PLL3 0x53
++#define TDA10048_CONF_ADC 0x54
++#define TDA10048_CONF_ADC_2 0x55
++#define TDA10048_CONF_C1_1 0x60
++#define TDA10048_CONF_C1_3 0x62
++#define TDA10048_AGC_CONF 0x70
++#define TDA10048_AGC_THRESHOLD_LSB 0x72
++#define TDA10048_AGC_THRESHOLD_MSB 0x73
++#define TDA10048_AGC_RENORM 0x74
++#define TDA10048_AGC_GAINS 0x76
++#define TDA10048_AGC_TUN_MIN 0x78
++#define TDA10048_AGC_TUN_MAX 0x79
++#define TDA10048_AGC_IF_MIN 0x7A
++#define TDA10048_AGC_IF_MAX 0x7B
++#define TDA10048_AGC_TUN_LEVEL 0x7E
++#define TDA10048_AGC_IF_LEVEL 0x7F
++#define TDA10048_DIG_AGC_LEVEL 0x81
++#define TDA10048_FREQ_PHY2_LSB 0x86
++#define TDA10048_FREQ_PHY2_MSB 0x87
++#define TDA10048_TIME_INVWREF_LSB 0x88
++#define TDA10048_TIME_INVWREF_MSB 0x89
++#define TDA10048_TIME_WREF_LSB 0x8A
++#define TDA10048_TIME_WREF_MID1 0x8B
++#define TDA10048_TIME_WREF_MID2 0x8C
++#define TDA10048_TIME_WREF_MSB 0x8D
++#define TDA10048_NP_OUT 0xA2
++#define TDA10048_CELL_ID_LSB 0xA4
++#define TDA10048_CELL_ID_MSB 0xA5
++#define TDA10048_EXTTPS_ODD 0xAA
++#define TDA10048_EXTTPS_EVEN 0xAB
++#define TDA10048_TPS_LENGTH 0xAC
++#define TDA10048_FREE_REG_1 0xB2
++#define TDA10048_FREE_REG_2 0xB3
++#define TDA10048_CONF_C3_1 0xC0
++#define TDA10048_CYBER_CTRL 0xC2
++#define TDA10048_CBER_NMAX_LSB 0xC4
++#define TDA10048_CBER_NMAX_MSB 0xC5
++#define TDA10048_CBER_LSB 0xC6
++#define TDA10048_CBER_MSB 0xC7
++#define TDA10048_VBER_LSB 0xC8
++#define TDA10048_VBER_MID 0xC9
++#define TDA10048_VBER_MSB 0xCA
++#define TDA10048_CYBER_LUT 0xCC
++#define TDA10048_UNCOR_CTRL 0xCD
++#define TDA10048_UNCOR_CPT_LSB 0xCE
++#define TDA10048_UNCOR_CPT_MSB 0xCF
++#define TDA10048_SOFT_IT_C3 0xD6
++#define TDA10048_CONF_TS2 0xE0
++#define TDA10048_CONF_TS1 0xE1
++
++static unsigned int debug;
++
++#define dprintk(level, fmt, arg...)\
++ do { if (debug >= level)\
++ printk(KERN_DEBUG "tda10048: " fmt, ## arg);\
++ } while (0)
++
++struct tda10048_state {
++
++ struct i2c_adapter *i2c;
++
++ /* configuration settings */
++ const struct tda10048_config *config;
++ struct dvb_frontend frontend;
++
++ int fwloaded;
++};
++
++static struct init_tab {
++ u8 reg;
++ u16 data;
++} init_tab[] = {
++ { TDA10048_CONF_PLL1, 0x08 },
++ { TDA10048_CONF_ADC_2, 0x00 },
++ { TDA10048_CONF_C4_1, 0x00 },
++ { TDA10048_CONF_PLL1, 0x0f },
++ { TDA10048_CONF_PLL2, 0x0a },
++ { TDA10048_CONF_PLL3, 0x43 },
++ { TDA10048_FREQ_PHY2_LSB, 0x02 },
++ { TDA10048_FREQ_PHY2_MSB, 0x0a },
++ { TDA10048_TIME_WREF_LSB, 0xbd },
++ { TDA10048_TIME_WREF_MID1, 0xe4 },
++ { TDA10048_TIME_WREF_MID2, 0xa8 },
++ { TDA10048_TIME_WREF_MSB, 0x02 },
++ { TDA10048_TIME_INVWREF_LSB, 0x04 },
++ { TDA10048_TIME_INVWREF_MSB, 0x06 },
++ { TDA10048_CONF_C4_1, 0x00 },
++ { TDA10048_CONF_C1_1, 0xa8 },
++ { TDA10048_AGC_CONF, 0x16 },
++ { TDA10048_CONF_C1_3, 0x0b },
++ { TDA10048_AGC_TUN_MIN, 0x00 },
++ { TDA10048_AGC_TUN_MAX, 0xff },
++ { TDA10048_AGC_IF_MIN, 0x00 },
++ { TDA10048_AGC_IF_MAX, 0xff },
++ { TDA10048_AGC_THRESHOLD_MSB, 0x00 },
++ { TDA10048_AGC_THRESHOLD_LSB, 0x70 },
++ { TDA10048_CYBER_CTRL, 0x38 },
++ { TDA10048_AGC_GAINS, 0x12 },
++ { TDA10048_CONF_XO, 0x00 },
++ { TDA10048_CONF_TS1, 0x07 },
++ { TDA10048_IC_MODE, 0x00 },
++ { TDA10048_CONF_TS2, 0xc0 },
++ { TDA10048_CONF_TRISTATE1, 0x21 },
++ { TDA10048_CONF_TRISTATE2, 0x00 },
++ { TDA10048_CONF_POLARITY, 0x00 },
++ { TDA10048_CONF_C4_2, 0x04 },
++ { TDA10048_CONF_ADC, 0x60 },
++ { TDA10048_CONF_ADC_2, 0x10 },
++ { TDA10048_CONF_ADC, 0x60 },
++ { TDA10048_CONF_ADC_2, 0x00 },
++ { TDA10048_CONF_C1_1, 0xa8 },
++ { TDA10048_UNCOR_CTRL, 0x00 },
++ { TDA10048_CONF_C4_2, 0x04 },
++};
++
++static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data)
++{
++ int ret;
++ u8 buf [] = { reg, data };
++ struct i2c_msg msg = {
++ .addr = state->config->demod_address,
++ .flags = 0, .buf = buf, .len = 2 };
++
++ dprintk(2, "%s(reg = 0x%02x, data = 0x%02x)\n", __func__, reg, data);
++
++ ret = i2c_transfer(state->i2c, &msg, 1);
++
++ if (ret != 1)
++ printk("%s: writereg error (ret == %i)\n", __func__, ret);
++
++ return (ret != 1) ? -1 : 0;
++}
++
++static u8 tda10048_readreg(struct tda10048_state *state, u8 reg)
++{
++ int ret;
++ u8 b0 [] = { reg };
++ u8 b1 [] = { 0 };
++ struct i2c_msg msg [] = {
++ { .addr = state->config->demod_address,
++ .flags = 0, .buf = b0, .len = 1 },
++ { .addr = state->config->demod_address,
++ .flags = I2C_M_RD, .buf = b1, .len = 1 } };
++
++ dprintk(2, "%s(reg = 0x%02x)\n", __func__, reg);
++
++ ret = i2c_transfer(state->i2c, msg, 2);
++
++ if (ret != 2)
++ printk(KERN_ERR "%s: readreg error (ret == %i)\n",
++ __func__, ret);
++
++ return b1[0];
++}
++
++static int tda10048_writeregbulk(struct tda10048_state *state, u8 reg,
++ u8 *data, u16 len)
++{
++ int ret = -EREMOTEIO;
++ struct i2c_msg msg;
++ u8 *buf;
++
++ dprintk(2, "%s(%d, ?, len = %d)\n", __func__, reg, len);
++
++ buf = kmalloc(len + 1, GFP_KERNEL);
++ if (buf == NULL) {
++ ret = -ENOMEM;
++ goto error;
++ }
++
++ *buf = reg;
++ memcpy(buf + 1, data, len);
++
++ msg.addr = state->config->demod_address;
++ msg.flags = 0;
++ msg.buf = buf;
++ msg.len = len + 1;
++
++ dprintk(2, "%s(): write len = %d\n",
++ __func__, msg.len);
++
++ ret = i2c_transfer(state->i2c, &msg, 1);
++ if (ret != 1) {
++ printk(KERN_ERR "%s(): writereg error err %i\n",
++ __func__, ret);
++ ret = -EREMOTEIO;
++ }
++
++error:
++ kfree(buf);
++
++ return ret;
++}
++
++static int tda10048_firmware_upload(struct dvb_frontend *fe)
++{
++ struct tda10048_state *state = fe->demodulator_priv;
++ const struct firmware *fw;
++ int ret;
++ int pos = 0;
++ int cnt;
++ u8 wlen = state->config->fwbulkwritelen;
++
++ if ((wlen != TDA10048_BULKWRITE_200) && (wlen != TDA10048_BULKWRITE_50))
++ wlen = TDA10048_BULKWRITE_200;
++
++ /* request the firmware, this will block and timeout */
++ printk(KERN_INFO "%s: waiting for firmware upload (%s)...\n",
++ __func__,
++ TDA10048_DEFAULT_FIRMWARE);
++
++ ret = request_firmware(&fw, TDA10048_DEFAULT_FIRMWARE,
++ &state->i2c->dev);
++ if (ret) {
++ printk(KERN_ERR "%s: Upload failed. (file not found?)\n",
++ __func__);
++ return -EIO;
++ } else {
++ printk(KERN_INFO "%s: firmware read %Zu bytes.\n",
++ __func__,
++ fw->size);
++ ret = 0;
++ }
++
++ if (fw->size != TDA10048_DEFAULT_FIRMWARE_SIZE) {
++ printk(KERN_ERR "%s: firmware incorrect size\n", __func__);
++ return -EIO;
++ } else {
++ printk(KERN_INFO "%s: firmware uploading\n", __func__);
++
++ /* Soft reset */
++ tda10048_writereg(state, TDA10048_CONF_TRISTATE1,
++ tda10048_readreg(state, TDA10048_CONF_TRISTATE1)
++ & 0xfe);
++ tda10048_writereg(state, TDA10048_CONF_TRISTATE1,
++ tda10048_readreg(state, TDA10048_CONF_TRISTATE1)
++ | 0x01);
++
++ /* Put the demod into host download mode */
++ tda10048_writereg(state, TDA10048_CONF_C4_1,
++ tda10048_readreg(state, TDA10048_CONF_C4_1) & 0xf9);
++
++ /* Boot the DSP */
++ tda10048_writereg(state, TDA10048_CONF_C4_1,
++ tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x08);
++
++ /* Prepare for download */
++ tda10048_writereg(state, TDA10048_DSP_CODE_CPT, 0);
++
++ /* Download the firmware payload */
++ while (pos < fw->size) {
++
++ if ((fw->size - pos) > wlen)
++ cnt = wlen;
++ else
++ cnt = fw->size - pos;
++
++ tda10048_writeregbulk(state, TDA10048_DSP_CODE_IN,
++ &fw->data[pos], cnt);
++
++ pos += cnt;
++ }
++
++ ret = -EIO;
++ /* Wait up to 250ms for the DSP to boot */
++ for (cnt = 0; cnt < 250 ; cnt += 10) {
++
++ msleep(10);
++
++ if (tda10048_readreg(state, TDA10048_SYNC_STATUS)
++ & 0x40) {
++ ret = 0;
++ break;
++ }
++ }
++ }
++
++ release_firmware(fw);
++
++ if (ret == 0) {
++ printk(KERN_INFO "%s: firmware uploaded\n", __func__);
++ state->fwloaded = 1;
++ } else
++ printk(KERN_ERR "%s: firmware upload failed\n", __func__);
++
++ return ret;
++}
++
++static int tda10048_set_inversion(struct dvb_frontend *fe, int inversion)
++{
++ struct tda10048_state *state = fe->demodulator_priv;
++
++ dprintk(1, "%s(%d)\n", __func__, inversion);
++
++ if (inversion == TDA10048_INVERSION_ON)
++ tda10048_writereg(state, TDA10048_CONF_C1_1,
++ tda10048_readreg(state, TDA10048_CONF_C1_1) | 0x20);
++ else
++ tda10048_writereg(state, TDA10048_CONF_C1_1,
++ tda10048_readreg(state, TDA10048_CONF_C1_1) & 0xdf);
++
++ return 0;
++}
++
++/* Retrieve the demod settings */
++static int tda10048_get_tps(struct tda10048_state *state,
++ struct dvb_ofdm_parameters *p)
++{
++ u8 val;
++
++ /* Make sure the TPS regs are valid */
++ if (!(tda10048_readreg(state, TDA10048_AUTO) & 0x01))
++ return -EAGAIN;
++
++ val = tda10048_readreg(state, TDA10048_OUT_CONF2);
++ switch ((val & 0x60) >> 5) {
++ case 0: p->constellation = QPSK; break;
++ case 1: p->constellation = QAM_16; break;
++ case 2: p->constellation = QAM_64; break;
++ }
++ switch ((val & 0x18) >> 3) {
++ case 0: p->hierarchy_information = HIERARCHY_NONE; break;
++ case 1: p->hierarchy_information = HIERARCHY_1; break;
++ case 2: p->hierarchy_information = HIERARCHY_2; break;
++ case 3: p->hierarchy_information = HIERARCHY_4; break;
++ }
++ switch (val & 0x07) {
++ case 0: p->code_rate_HP = FEC_1_2; break;
++ case 1: p->code_rate_HP = FEC_2_3; break;
++ case 2: p->code_rate_HP = FEC_3_4; break;
++ case 3: p->code_rate_HP = FEC_5_6; break;
++ case 4: p->code_rate_HP = FEC_7_8; break;
++ }
++
++ val = tda10048_readreg(state, TDA10048_OUT_CONF3);
++ switch (val & 0x07) {
++ case 0: p->code_rate_LP = FEC_1_2; break;
++ case 1: p->code_rate_LP = FEC_2_3; break;
++ case 2: p->code_rate_LP = FEC_3_4; break;
++ case 3: p->code_rate_LP = FEC_5_6; break;
++ case 4: p->code_rate_LP = FEC_7_8; break;
++ }
++
++ val = tda10048_readreg(state, TDA10048_OUT_CONF1);
++ switch ((val & 0x0c) >> 2) {
++ case 0: p->guard_interval = GUARD_INTERVAL_1_32; break;
++ case 1: p->guard_interval = GUARD_INTERVAL_1_16; break;
++ case 2: p->guard_interval = GUARD_INTERVAL_1_8; break;
++ case 3: p->guard_interval = GUARD_INTERVAL_1_4; break;
++ }
++ switch (val & 0x02) {
++ case 0: p->transmission_mode = TRANSMISSION_MODE_2K; break;
++ case 1: p->transmission_mode = TRANSMISSION_MODE_8K; break;
++ }
++
++ return 0;
++}
++
++static int tda10048_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
++{
++ struct tda10048_state *state = fe->demodulator_priv;
++ dprintk(1, "%s(%d)\n", __func__, enable);
++
++ if (enable)
++ return tda10048_writereg(state, TDA10048_CONF_C4_1,
++ tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x02);
++ else
++ return tda10048_writereg(state, TDA10048_CONF_C4_1,
++ tda10048_readreg(state, TDA10048_CONF_C4_1) & 0xfd);
++}
++
++static int tda10048_output_mode(struct dvb_frontend *fe, int serial)
++{
++ struct tda10048_state *state = fe->demodulator_priv;
++ dprintk(1, "%s(%d)\n", __func__, serial);
++
++ /* Ensure pins are out of tri-state */
++ tda10048_writereg(state, TDA10048_CONF_TRISTATE1, 0x21);
++ tda10048_writereg(state, TDA10048_CONF_TRISTATE2, 0x00);
++
++ if (serial) {
++ tda10048_writereg(state, TDA10048_IC_MODE, 0x80 | 0x20);
++ tda10048_writereg(state, TDA10048_CONF_TS2, 0xc0);
++ } else {
++ tda10048_writereg(state, TDA10048_IC_MODE, 0x00);
++ tda10048_writereg(state, TDA10048_CONF_TS2, 0x01);
++ }
++
++ return 0;
++}
++
++/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
++/* TODO: Support manual tuning with specific params */
++static int tda10048_set_frontend(struct dvb_frontend *fe,
++ struct dvb_frontend_parameters *p)
++{
++ struct tda10048_state *state = fe->demodulator_priv;
++
++ dprintk(1, "%s(frequency=%d)\n", __func__, p->frequency);
++
++ if (fe->ops.tuner_ops.set_params) {
++
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
++
++ fe->ops.tuner_ops.set_params(fe, p);
++
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 0);
++ }
++
++ /* Enable demod TPS auto detection and begin acquisition */
++ tda10048_writereg(state, TDA10048_AUTO, 0x57);
++
++ return 0;
++}
++
++/* Establish sane defaults and load firmware. */
++static int tda10048_init(struct dvb_frontend *fe)
++{
++ struct tda10048_state *state = fe->demodulator_priv;
++ int ret = 0, i;
++
++ dprintk(1, "%s()\n", __func__);
++
++ /* Apply register defaults */
++ for (i = 0; i < ARRAY_SIZE(init_tab); i++)
++ tda10048_writereg(state, init_tab[i].reg, init_tab[i].data);
++
++ if (state->fwloaded == 0)
++ ret = tda10048_firmware_upload(fe);
++
++ /* Set either serial or parallel */
++ tda10048_output_mode(fe, state->config->output_mode);
++
++ /* set inversion */
++ tda10048_set_inversion(fe, state->config->inversion);
++
++ /* Ensure we leave the gate closed */
++ tda10048_i2c_gate_ctrl(fe, 0);
++
++ return ret;
++}
++
++static int tda10048_read_status(struct dvb_frontend *fe, fe_status_t *status)
++{
++ struct tda10048_state *state = fe->demodulator_priv;
++ u8 reg;
++
++ *status = 0;
++
++ reg = tda10048_readreg(state, TDA10048_SYNC_STATUS);
++
++ dprintk(1, "%s() status =0x%02x\n", __func__, reg);
++
++ if (reg & 0x02)
++ *status |= FE_HAS_CARRIER;
++
++ if (reg & 0x04)
++ *status |= FE_HAS_SIGNAL;
++
++ if (reg & 0x08) {
++ *status |= FE_HAS_LOCK;
++ *status |= FE_HAS_VITERBI;
++ *status |= FE_HAS_SYNC;
++ }
++
++ return 0;
++}
++
++static int tda10048_read_ber(struct dvb_frontend *fe, u32 *ber)
++{
++ struct tda10048_state *state = fe->demodulator_priv;
++
++ dprintk(1, "%s()\n", __func__);
++
++ /* TODO: A reset may be required here */
++ *ber = tda10048_readreg(state, TDA10048_CBER_MSB) << 8 |
++ tda10048_readreg(state, TDA10048_CBER_LSB);
++
++ return 0;
++}
++
++static int tda10048_read_signal_strength(struct dvb_frontend *fe,
++ u16 *signal_strength)
++{
++ struct tda10048_state *state = fe->demodulator_priv;
++ u8 v;
++
++ dprintk(1, "%s()\n", __func__);
++
++ *signal_strength = 65535;
++
++ v = tda10048_readreg(state, TDA10048_NP_OUT);
++ if (v > 0)
++ *signal_strength -= (v << 8) | v;
++
++ return 0;
++}
++
++/* SNR lookup table */
++static struct snr_tab {
++ u8 val;
++ u8 data;
++} snr_tab[] = {
++ { 0, 0 },
++ { 1, 246 },
++ { 2, 215 },
++ { 3, 198 },
++ { 4, 185 },
++ { 5, 176 },
++ { 6, 168 },
++ { 7, 161 },
++ { 8, 155 },
++ { 9, 150 },
++ { 10, 146 },
++ { 11, 141 },
++ { 12, 138 },
++ { 13, 134 },
++ { 14, 131 },
++ { 15, 128 },
++ { 16, 125 },
++ { 17, 122 },
++ { 18, 120 },
++ { 19, 118 },
++ { 20, 115 },
++ { 21, 113 },
++ { 22, 111 },
++ { 23, 109 },
++ { 24, 107 },
++ { 25, 106 },
++ { 26, 104 },
++ { 27, 102 },
++ { 28, 101 },
++ { 29, 99 },
++ { 30, 98 },
++ { 31, 96 },
++ { 32, 95 },
++ { 33, 94 },
++ { 34, 92 },
++ { 35, 91 },
++ { 36, 90 },
++ { 37, 89 },
++ { 38, 88 },
++ { 39, 86 },
++ { 40, 85 },
++ { 41, 84 },
++ { 42, 83 },
++ { 43, 82 },
++ { 44, 81 },
++ { 45, 80 },
++ { 46, 79 },
++ { 47, 78 },
++ { 48, 77 },
++ { 49, 76 },
++ { 50, 76 },
++ { 51, 75 },
++ { 52, 74 },
++ { 53, 73 },
++ { 54, 72 },
++ { 56, 71 },
++ { 57, 70 },
++ { 58, 69 },
++ { 60, 68 },
++ { 61, 67 },
++ { 63, 66 },
++ { 64, 65 },
++ { 66, 64 },
++ { 67, 63 },
++ { 68, 62 },
++ { 69, 62 },
++ { 70, 61 },
++ { 72, 60 },
++ { 74, 59 },
++ { 75, 58 },
++ { 77, 57 },
++ { 79, 56 },
++ { 81, 55 },
++ { 83, 54 },
++ { 85, 53 },
++ { 87, 52 },
++ { 89, 51 },
++ { 91, 50 },
++ { 93, 49 },
++ { 95, 48 },
++ { 97, 47 },
++ { 100, 46 },
++ { 102, 45 },
++ { 104, 44 },
++ { 107, 43 },
++ { 109, 42 },
++ { 112, 41 },
++ { 114, 40 },
++ { 117, 39 },
++ { 120, 38 },
++ { 123, 37 },
++ { 125, 36 },
++ { 128, 35 },
++ { 131, 34 },
++ { 134, 33 },
++ { 138, 32 },
++ { 141, 31 },
++ { 144, 30 },
++ { 147, 29 },
++ { 151, 28 },
++ { 154, 27 },
++ { 158, 26 },
++ { 162, 25 },
++ { 165, 24 },
++ { 169, 23 },
++ { 173, 22 },
++ { 177, 21 },
++ { 181, 20 },
++ { 186, 19 },
++ { 190, 18 },
++ { 194, 17 },
++ { 199, 16 },
++ { 204, 15 },
++ { 208, 14 },
++ { 213, 13 },
++ { 218, 12 },
++ { 223, 11 },
++ { 229, 10 },
++ { 234, 9 },
++ { 239, 8 },
++ { 245, 7 },
++ { 251, 6 },
++ { 255, 5 },
++};
++
++static int tda10048_read_snr(struct dvb_frontend *fe, u16 *snr)
++{
++ struct tda10048_state *state = fe->demodulator_priv;
++ u8 v;
++ int i, ret = -EINVAL;
++
++ dprintk(1, "%s()\n", __func__);
++
++ v = tda10048_readreg(state, TDA10048_NP_OUT);
++ for (i = 0; i < ARRAY_SIZE(snr_tab); i++) {
++ if (v <= snr_tab[i].val) {
++ *snr = snr_tab[i].data;
++ ret = 0;
++ break;
++ }
++ }
++
++ return ret;
++}
++
++static int tda10048_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
++{
++ struct tda10048_state *state = fe->demodulator_priv;
++
++ dprintk(1, "%s()\n", __func__);
++
++ *ucblocks = tda10048_readreg(state, TDA10048_UNCOR_CPT_MSB) << 8 |
++ tda10048_readreg(state, TDA10048_UNCOR_CPT_LSB);
++
++ return 0;
++}
++
++static int tda10048_get_frontend(struct dvb_frontend *fe,
++ struct dvb_frontend_parameters *p)
++{
++ struct tda10048_state *state = fe->demodulator_priv;
++
++ dprintk(1, "%s()\n", __func__);
++
++ p->inversion = tda10048_readreg(state, TDA10048_CONF_C1_1)
++ & 0x20 ? INVERSION_ON : INVERSION_OFF;
++
++ return tda10048_get_tps(state, &p->u.ofdm);
++}
++
++static int tda10048_get_tune_settings(struct dvb_frontend *fe,
++ struct dvb_frontend_tune_settings *tune)
++{
++ tune->min_delay_ms = 1000;
++ return 0;
++}
++
++static void tda10048_release(struct dvb_frontend *fe)
++{
++ struct tda10048_state *state = fe->demodulator_priv;
++ dprintk(1, "%s()\n", __func__);
++ kfree(state);
++}
++
++static struct dvb_frontend_ops tda10048_ops;
++
++struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
++ struct i2c_adapter *i2c)
++{
++ struct tda10048_state *state = NULL;
++
++ dprintk(1, "%s()\n", __func__);
++
++ /* allocate memory for the internal state */
++ state = kmalloc(sizeof(struct tda10048_state), GFP_KERNEL);
++ if (state == NULL)
++ goto error;
++
++ /* setup the state */
++ state->config = config;
++ state->i2c = i2c;
++ state->fwloaded = 0;
++
++ /* check if the demod is present */
++ if (tda10048_readreg(state, TDA10048_IDENTITY) != 0x048)
++ goto error;
++
++ /* create dvb_frontend */
++ memcpy(&state->frontend.ops, &tda10048_ops,
++ sizeof(struct dvb_frontend_ops));
++ state->frontend.demodulator_priv = state;
++
++ /* Leave the gate closed */
++ tda10048_i2c_gate_ctrl(&state->frontend, 0);
++
++ return &state->frontend;
++
++error:
++ kfree(state);
++ return NULL;
++}
++EXPORT_SYMBOL(tda10048_attach);
++
++static struct dvb_frontend_ops tda10048_ops = {
++
++ .info = {
++ .name = "NXP TDA10048HN DVB-T",
++ .type = FE_OFDM,
++ .frequency_min = 177000000,
++ .frequency_max = 858000000,
++ .frequency_stepsize = 166666,
++ .caps = 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 | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
++ FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
++ FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER
++ },
++
++ .release = tda10048_release,
++ .init = tda10048_init,
++ .i2c_gate_ctrl = tda10048_i2c_gate_ctrl,
++ .set_frontend = tda10048_set_frontend,
++ .get_frontend = tda10048_get_frontend,
++ .get_tune_settings = tda10048_get_tune_settings,
++ .read_status = tda10048_read_status,
++ .read_ber = tda10048_read_ber,
++ .read_signal_strength = tda10048_read_signal_strength,
++ .read_snr = tda10048_read_snr,
++ .read_ucblocks = tda10048_read_ucblocks,
++};
++
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "Enable verbose debug messages");
++
++MODULE_DESCRIPTION("NXP TDA10048HN DVB-T Demodulator driver");
++MODULE_AUTHOR("Steven Toth");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/dvb/frontends/tda10048.h b/drivers/media/dvb/frontends/tda10048.h
+new file mode 100644
+index 0000000..2b5c78e
+--- /dev/null
++++ b/drivers/media/dvb/frontends/tda10048.h
+@@ -0,0 +1,63 @@
++/*
++ NXP TDA10048HN DVB OFDM demodulator driver
++
++ Copyright (C) 2008 Steven Toth <stoth at hauppauge.com>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++*/
++
++#ifndef TDA10048_H
++#define TDA10048_H
++
++#include <linux/dvb/frontend.h>
++#include <linux/firmware.h>
++
++struct tda10048_config {
++
++ /* the demodulator's i2c address */
++ u8 demod_address;
++
++ /* serial/parallel output */
++#define TDA10048_PARALLEL_OUTPUT 0
++#define TDA10048_SERIAL_OUTPUT 1
++ u8 output_mode;
++
++#define TDA10048_BULKWRITE_200 200
++#define TDA10048_BULKWRITE_50 50
++ u8 fwbulkwritelen;
++
++ /* Spectral Inversion */
++#define TDA10048_INVERSION_OFF 0
++#define TDA10048_INVERSION_ON 1
++ u8 inversion;
++};
++
++#if defined(CONFIG_DVB_TDA10048) || \
++ (defined(CONFIG_DVB_TDA10048_MODULE) && defined(MODULE))
++extern struct dvb_frontend *tda10048_attach(
++ const struct tda10048_config *config,
++ struct i2c_adapter *i2c);
++#else
++static inline struct dvb_frontend *tda10048_attach(
++ const struct tda10048_config *config,
++ struct i2c_adapter *i2c)
++{
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
++ return NULL;
++}
++#endif /* CONFIG_DVB_TDA10048 */
++
++#endif /* TDA10048_H */
+diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
+index 8415a8a..4997384 100644
+--- a/drivers/media/dvb/frontends/tda1004x.c
++++ b/drivers/media/dvb/frontends/tda1004x.c
+@@ -131,16 +131,16 @@ static int tda1004x_write_byteI(struct tda1004x_state *state, int reg, int data)
+ u8 buf[] = { reg, data };
+ struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 };
+
+- dprintk("%s: reg=0x%x, data=0x%x\n", __FUNCTION__, reg, data);
++ dprintk("%s: reg=0x%x, data=0x%x\n", __func__, reg, data);
+
+ msg.addr = state->config->demod_address;
+ ret = i2c_transfer(state->i2c, &msg, 1);
+
+ if (ret != 1)
+ dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
+- __FUNCTION__, reg, data, ret);
++ __func__, reg, data, ret);
+
+- dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __FUNCTION__,
++ dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __func__,
+ reg, data, ret);
+ return (ret != 1) ? -1 : 0;
+ }
+@@ -153,19 +153,19 @@ static int tda1004x_read_byte(struct tda1004x_state *state, int reg)
+ struct i2c_msg msg[] = {{ .flags = 0, .buf = b0, .len = 1 },
+ { .flags = I2C_M_RD, .buf = b1, .len = 1 }};
+
+- dprintk("%s: reg=0x%x\n", __FUNCTION__, reg);
++ dprintk("%s: reg=0x%x\n", __func__, reg);
+
+ msg[0].addr = state->config->demod_address;
+ msg[1].addr = state->config->demod_address;
+ ret = i2c_transfer(state->i2c, msg, 2);
+
+ if (ret != 2) {
+- dprintk("%s: error reg=0x%x, ret=%i\n", __FUNCTION__, reg,
++ dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg,
+ ret);
+ return -1;
+ }
+
+- dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __FUNCTION__,
++ dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __func__,
+ reg, b1[0], ret);
+ return b1[0];
+ }
+@@ -173,7 +173,7 @@ static int tda1004x_read_byte(struct tda1004x_state *state, int reg)
+ static int tda1004x_write_mask(struct tda1004x_state *state, int reg, int mask, int data)
+ {
+ int val;
+- dprintk("%s: reg=0x%x, mask=0x%x, data=0x%x\n", __FUNCTION__, reg,
++ dprintk("%s: reg=0x%x, mask=0x%x, data=0x%x\n", __func__, reg,
+ mask, data);
+
+ // read a byte and check
+@@ -194,7 +194,7 @@ static int tda1004x_write_buf(struct tda1004x_state *state, int reg, unsigned ch
+ int i;
+ int result;
+
+- dprintk("%s: reg=0x%x, len=0x%x\n", __FUNCTION__, reg, len);
++ dprintk("%s: reg=0x%x, len=0x%x\n", __func__, reg, len);
+
+ result = 0;
+ for (i = 0; i < len; i++) {
+@@ -209,7 +209,7 @@ static int tda1004x_write_buf(struct tda1004x_state *state, int reg, unsigned ch
+ static int tda1004x_enable_tuner_i2c(struct tda1004x_state *state)
+ {
+ int result;
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ result = tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 2);
+ msleep(20);
+@@ -218,7 +218,7 @@ static int tda1004x_enable_tuner_i2c(struct tda1004x_state *state)
+
+ static int tda1004x_disable_tuner_i2c(struct tda1004x_state *state)
+ {
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ return tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 0);
+ }
+@@ -345,7 +345,7 @@ static int tda1004x_do_upload(struct tda1004x_state *state,
+ }
+ pos += tx_size;
+
+- dprintk("%s: fw_pos=0x%x\n", __FUNCTION__, pos);
++ dprintk("%s: fw_pos=0x%x\n", __func__, pos);
+ }
+ // give the DSP a chance to settle 03/10/05 Hac
+ msleep(100);
+@@ -444,10 +444,10 @@ static void tda10046_init_plls(struct dvb_frontend* fe)
+ tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x03); // PLL M = 3
+ }
+ if (state->config->xtal_freq == TDA10046_XTAL_4M ) {
+- dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __FUNCTION__);
++ dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __func__);
+ tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0
+ } else {
+- dprintk("%s: setting up PLLs for a 16 MHz Xtal\n", __FUNCTION__);
++ dprintk("%s: setting up PLLs for a 16 MHz Xtal\n", __func__);
+ tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 3); // PLL P = 0, N = 3
+ }
+ if(tda10046_clk53m)
+@@ -488,7 +488,7 @@ static int tda10046_fwupload(struct dvb_frontend* fe)
+ if (state->config->xtal_freq == TDA10046_XTAL_4M) {
+ tda1004x_write_byteI(state, TDA1004X_CONFC4, 0);
+ } else {
+- dprintk("%s: 16MHz Xtal, reducing I2C speed\n", __FUNCTION__);
++ dprintk("%s: 16MHz Xtal, reducing I2C speed\n", __func__);
+ tda1004x_write_byteI(state, TDA1004X_CONFC4, 0x80);
+ }
+ tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 1, 0);
+@@ -594,7 +594,7 @@ static int tda10045_init(struct dvb_frontend* fe)
+ {
+ struct tda1004x_state* state = fe->demodulator_priv;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ if (tda10045_fwupload(fe)) {
+ printk("tda1004x: firmware upload failed\n");
+@@ -624,7 +624,7 @@ static int tda10045_init(struct dvb_frontend* fe)
+ static int tda10046_init(struct dvb_frontend* fe)
+ {
+ struct tda1004x_state* state = fe->demodulator_priv;
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ if (tda10046_fwupload(fe)) {
+ printk("tda1004x: firmware upload failed\n");
+@@ -686,7 +686,7 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
+ int tmp;
+ int inversion;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ if (state->demod_type == TDA1004X_DEMOD_TDA10046) {
+ // setup auto offset
+@@ -881,7 +881,7 @@ static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_paramete
+ {
+ struct tda1004x_state* state = fe->demodulator_priv;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ // inversion status
+ fe_params->inversion = INVERSION_OFF;
+@@ -989,7 +989,7 @@ static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status
+ int cber;
+ int vber;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ // read status
+ status = tda1004x_read_byte(state, TDA1004X_STATUS_CD);
+@@ -1048,7 +1048,7 @@ static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status
+ }
+
+ // success
+- dprintk("%s: fe_status=0x%x\n", __FUNCTION__, *fe_status);
++ dprintk("%s: fe_status=0x%x\n", __func__, *fe_status);
+ return 0;
+ }
+
+@@ -1058,7 +1058,7 @@ static int tda1004x_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
+ int tmp;
+ int reg = 0;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ // determine the register to use
+ switch (state->demod_type) {
+@@ -1077,7 +1077,7 @@ static int tda1004x_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
+ return -EIO;
+
+ *signal = (tmp << 8) | tmp;
+- dprintk("%s: signal=0x%x\n", __FUNCTION__, *signal);
++ dprintk("%s: signal=0x%x\n", __func__, *signal);
+ return 0;
+ }
+
+@@ -1086,7 +1086,7 @@ static int tda1004x_read_snr(struct dvb_frontend* fe, u16 * snr)
+ struct tda1004x_state* state = fe->demodulator_priv;
+ int tmp;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ // read it
+ tmp = tda1004x_read_byte(state, TDA1004X_SNR);
+@@ -1095,7 +1095,7 @@ static int tda1004x_read_snr(struct dvb_frontend* fe, u16 * snr)
+ tmp = 255 - tmp;
+
+ *snr = ((tmp << 8) | tmp);
+- dprintk("%s: snr=0x%x\n", __FUNCTION__, *snr);
++ dprintk("%s: snr=0x%x\n", __func__, *snr);
+ return 0;
+ }
+
+@@ -1106,7 +1106,7 @@ static int tda1004x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+ int tmp2;
+ int counter;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ // read the UCBLOCKS and reset
+ counter = 0;
+@@ -1132,7 +1132,7 @@ static int tda1004x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+ else
+ *ucblocks = 0xffffffff;
+
+- dprintk("%s: ucblocks=0x%x\n", __FUNCTION__, *ucblocks);
++ dprintk("%s: ucblocks=0x%x\n", __func__, *ucblocks);
+ return 0;
+ }
+
+@@ -1141,7 +1141,7 @@ static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber)
+ struct tda1004x_state* state = fe->demodulator_priv;
+ int tmp;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ // read it in
+ tmp = tda1004x_read_byte(state, TDA1004X_CBER_LSB);
+@@ -1155,7 +1155,7 @@ static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber)
+ // The address 0x20 should be read to cope with a TDA10046 bug
+ tda1004x_read_byte(state, TDA1004X_CBER_RESET);
+
+- dprintk("%s: ber=0x%x\n", __FUNCTION__, *ber);
++ dprintk("%s: ber=0x%x\n", __func__, *ber);
+ return 0;
+ }
+
+diff --git a/drivers/media/dvb/frontends/tda1004x.h b/drivers/media/dvb/frontends/tda1004x.h
+index abae843..4e27ffb 100644
+--- a/drivers/media/dvb/frontends/tda1004x.h
++++ b/drivers/media/dvb/frontends/tda1004x.h
+@@ -94,7 +94,6 @@ struct tda1004x_config
+
+ /* slave address and configuration of the tuner */
+ u8 tuner_address;
+- u8 tuner_config;
+ u8 antenna_switch;
+
+ /* if the board uses another I2c Bridge (tda8290), its address */
+@@ -128,13 +127,13 @@ extern struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config
+ static inline struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
+ struct i2c_adapter* i2c)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ static inline struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
+ struct i2c_adapter* i2c)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_TDA1004X
+diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c
+index 0d2b69a..a17ce3c 100644
+--- a/drivers/media/dvb/frontends/tda10086.c
++++ b/drivers/media/dvb/frontends/tda10086.c
+@@ -43,7 +43,7 @@ struct tda10086_state {
+ bool has_lock;
+ };
+
+-static int debug = 0;
++static int debug;
+ #define dprintk(args...) \
+ do { \
+ if (debug) printk(KERN_DEBUG "tda10086: " args); \
+@@ -60,7 +60,7 @@ static int tda10086_write_byte(struct tda10086_state *state, int reg, int data)
+
+ if (ret != 1)
+ dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
+- __FUNCTION__, reg, data, ret);
++ __func__, reg, data, ret);
+
+ return (ret != 1) ? ret : 0;
+ }
+@@ -78,7 +78,7 @@ static int tda10086_read_byte(struct tda10086_state *state, int reg)
+ ret = i2c_transfer(state->i2c, msg, 2);
+
+ if (ret != 2) {
+- dprintk("%s: error reg=0x%x, ret=%i\n", __FUNCTION__, reg,
++ dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg,
+ ret);
+ return ret;
+ }
+@@ -90,16 +90,16 @@ static int tda10086_write_mask(struct tda10086_state *state, int reg, int mask,
+ {
+ int val;
+
+- // read a byte and check
++ /* read a byte and check */
+ val = tda10086_read_byte(state, reg);
+ if (val < 0)
+ return val;
+
+- // mask if off
++ /* mask if off */
+ val = val & ~mask;
+ val |= data & 0xff;
+
+- // write it out again
++ /* write it out again */
+ return tda10086_write_byte(state, reg, val);
+ }
+
+@@ -108,62 +108,67 @@ static int tda10086_init(struct dvb_frontend* fe)
+ struct tda10086_state* state = fe->demodulator_priv;
+ u8 t22k_off = 0x80;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ if (state->config->diseqc_tone)
+ t22k_off = 0;
+- // reset
++ /* reset */
+ tda10086_write_byte(state, 0x00, 0x00);
+ msleep(10);
+
+- // misc setup
++ /* misc setup */
+ tda10086_write_byte(state, 0x01, 0x94);
+- tda10086_write_byte(state, 0x02, 0x35); // NOTE: TT drivers appear to disable CSWP
++ tda10086_write_byte(state, 0x02, 0x35); /* NOTE: TT drivers appear to disable CSWP */
+ tda10086_write_byte(state, 0x03, 0xe4);
+ tda10086_write_byte(state, 0x04, 0x43);
+ tda10086_write_byte(state, 0x0c, 0x0c);
+- tda10086_write_byte(state, 0x1b, 0xb0); // noise threshold
+- tda10086_write_byte(state, 0x20, 0x89); // misc
+- tda10086_write_byte(state, 0x30, 0x04); // acquisition period length
+- tda10086_write_byte(state, 0x32, 0x00); // irq off
+- tda10086_write_byte(state, 0x31, 0x56); // setup AFC
+-
+- // setup PLL (assumes 16Mhz XIN)
+- tda10086_write_byte(state, 0x55, 0x2c); // misc PLL setup
+- tda10086_write_byte(state, 0x3a, 0x0b); // M=12
+- tda10086_write_byte(state, 0x3b, 0x01); // P=2
+- tda10086_write_mask(state, 0x55, 0x20, 0x00); // powerup PLL
+-
+- // setup TS interface
++ tda10086_write_byte(state, 0x1b, 0xb0); /* noise threshold */
++ tda10086_write_byte(state, 0x20, 0x89); /* misc */
++ tda10086_write_byte(state, 0x30, 0x04); /* acquisition period length */
++ tda10086_write_byte(state, 0x32, 0x00); /* irq off */
++ tda10086_write_byte(state, 0x31, 0x56); /* setup AFC */
++
++ /* setup PLL (this assumes SACLK = 96MHz) */
++ tda10086_write_byte(state, 0x55, 0x2c); /* misc PLL setup */
++ if (state->config->xtal_freq == TDA10086_XTAL_16M) {
++ tda10086_write_byte(state, 0x3a, 0x0b); /* M=12 */
++ tda10086_write_byte(state, 0x3b, 0x01); /* P=2 */
++ } else {
++ tda10086_write_byte(state, 0x3a, 0x17); /* M=24 */
++ tda10086_write_byte(state, 0x3b, 0x00); /* P=1 */
++ }
++ tda10086_write_mask(state, 0x55, 0x20, 0x00); /* powerup PLL */
++
++ /* setup TS interface */
+ tda10086_write_byte(state, 0x11, 0x81);
+ tda10086_write_byte(state, 0x12, 0x81);
+- tda10086_write_byte(state, 0x19, 0x40); // parallel mode A + MSBFIRST
+- tda10086_write_byte(state, 0x56, 0x80); // powerdown WPLL - unused in the mode we use
+- tda10086_write_byte(state, 0x57, 0x08); // bypass WPLL - unused in the mode we use
++ tda10086_write_byte(state, 0x19, 0x40); /* parallel mode A + MSBFIRST */
++ tda10086_write_byte(state, 0x56, 0x80); /* powerdown WPLL - unused in the mode we use */
++ tda10086_write_byte(state, 0x57, 0x08); /* bypass WPLL - unused in the mode we use */
+ tda10086_write_byte(state, 0x10, 0x2a);
+
+- // setup ADC
+- tda10086_write_byte(state, 0x58, 0x61); // ADC setup
+- tda10086_write_mask(state, 0x58, 0x01, 0x00); // powerup ADC
++ /* setup ADC */
++ tda10086_write_byte(state, 0x58, 0x61); /* ADC setup */
++ tda10086_write_mask(state, 0x58, 0x01, 0x00); /* powerup ADC */
+
+- // setup AGC
++ /* setup AGC */
+ tda10086_write_byte(state, 0x05, 0x0B);
+ tda10086_write_byte(state, 0x37, 0x63);
+- tda10086_write_byte(state, 0x3f, 0x0a); // NOTE: flydvb varies it
++ tda10086_write_byte(state, 0x3f, 0x0a); /* NOTE: flydvb varies it */
+ tda10086_write_byte(state, 0x40, 0x64);
+ tda10086_write_byte(state, 0x41, 0x4f);
+ tda10086_write_byte(state, 0x42, 0x43);
+
+- // setup viterbi
+- tda10086_write_byte(state, 0x1a, 0x11); // VBER 10^6, DVB, QPSK
++ /* setup viterbi */
++ tda10086_write_byte(state, 0x1a, 0x11); /* VBER 10^6, DVB, QPSK */
+
+- // setup carrier recovery
++ /* setup carrier recovery */
+ tda10086_write_byte(state, 0x3d, 0x80);
+
+- // setup SEC
+- tda10086_write_byte(state, 0x36, t22k_off); // all SEC off, 22k tone
+- tda10086_write_byte(state, 0x34, (((1<<19) * (22000/1000)) / (SACLK/1000))); // } tone frequency
+- tda10086_write_byte(state, 0x35, (((1<<19) * (22000/1000)) / (SACLK/1000)) >> 8); // }
++ /* setup SEC */
++ tda10086_write_byte(state, 0x36, t22k_off); /* all SEC off, 22k tone */
++ tda10086_write_byte(state, 0x34, (((1<<19) * (22000/1000)) / (SACLK/1000)));
++ tda10086_write_byte(state, 0x35, (((1<<19) * (22000/1000)) / (SACLK/1000)) >> 8);
+
+ return 0;
+ }
+@@ -173,7 +178,7 @@ static void tda10086_diseqc_wait(struct tda10086_state *state)
+ unsigned long timeout = jiffies + msecs_to_jiffies(200);
+ while (!(tda10086_read_byte(state, 0x50) & 0x01)) {
+ if(time_after(jiffies, timeout)) {
+- printk("%s: diseqc queue not ready, command may be lost.\n", __FUNCTION__);
++ printk("%s: diseqc queue not ready, command may be lost.\n", __func__);
+ break;
+ }
+ msleep(10);
+@@ -185,7 +190,7 @@ static int tda10086_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+ struct tda10086_state* state = fe->demodulator_priv;
+ u8 t22k_off = 0x80;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ if (state->config->diseqc_tone)
+ t22k_off = 0;
+@@ -211,7 +216,7 @@ static int tda10086_send_master_cmd (struct dvb_frontend* fe,
+ u8 oldval;
+ u8 t22k_off = 0x80;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ if (state->config->diseqc_tone)
+ t22k_off = 0;
+@@ -239,7 +244,7 @@ static int tda10086_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minic
+ u8 oldval = tda10086_read_byte(state, 0x36);
+ u8 t22k_off = 0x80;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ if (state->config->diseqc_tone)
+ t22k_off = 0;
+@@ -266,7 +271,7 @@ static int tda10086_set_inversion(struct tda10086_state *state,
+ {
+ u8 invval = 0x80;
+
+- dprintk ("%s %i %i\n", __FUNCTION__, fe_params->inversion, state->config->invert);
++ dprintk ("%s %i %i\n", __func__, fe_params->inversion, state->config->invert);
+
+ switch(fe_params->inversion) {
+ case INVERSION_OFF:
+@@ -300,9 +305,9 @@ static int tda10086_set_symbol_rate(struct tda10086_state *state,
+ u32 bdri;
+ u32 symbol_rate = fe_params->u.qpsk.symbol_rate;
+
+- dprintk ("%s %i\n", __FUNCTION__, symbol_rate);
++ dprintk ("%s %i\n", __func__, symbol_rate);
+
+- // setup the decimation and anti-aliasing filters..
++ /* setup the decimation and anti-aliasing filters.. */
+ if (symbol_rate < (u32) (SACLK * 0.0137)) {
+ dfn=4;
+ afs=1;
+@@ -339,13 +344,13 @@ static int tda10086_set_symbol_rate(struct tda10086_state *state,
+ byp=1;
+ }
+
+- // calculate BDR
++ /* calculate BDR */
+ big = (1ULL<<21) * ((u64) symbol_rate/1000ULL) * (1ULL<<dfn);
+ big += ((SACLK/1000ULL)-1ULL);
+ do_div(big, (SACLK/1000ULL));
+ bdr = big & 0xfffff;
+
+- // calculate BDRI
++ /* calculate BDRI */
+ tmp = (1<<dfn)*(symbol_rate/1000);
+ bdri = ((32 * (SACLK/1000)) + (tmp-1)) / tmp;
+
+@@ -366,7 +371,7 @@ static int tda10086_set_fec(struct tda10086_state *state,
+ {
+ u8 fecval;
+
+- dprintk ("%s %i\n", __FUNCTION__, fe_params->u.qpsk.fec_inner);
++ dprintk ("%s %i\n", __func__, fe_params->u.qpsk.fec_inner);
+
+ switch(fe_params->u.qpsk.fec_inner) {
+ case FEC_1_2:
+@@ -412,13 +417,13 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
+ u32 freq = 0;
+ int freqoff;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+- // modify parameters for tuning
++ /* modify parameters for tuning */
+ tda10086_write_byte(state, 0x02, 0x35);
+ state->has_lock = false;
+
+- // set params
++ /* set params */
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, fe_params);
+ if (fe->ops.i2c_gate_ctrl)
+@@ -430,7 +435,7 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
+ fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+
+- // calcluate the frequency offset (in *Hz* not kHz)
++ /* calcluate the frequency offset (in *Hz* not kHz) */
+ freqoff = fe_params->frequency - freq;
+ freqoff = ((1<<16) * freqoff) / (SACLK/1000);
+ tda10086_write_byte(state, 0x3d, 0x80 | ((freqoff >> 8) & 0x7f));
+@@ -443,7 +448,7 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
+ if ((ret = tda10086_set_fec(state, fe_params)) < 0)
+ return ret;
+
+- // soft reset + disable TS output until lock
++ /* soft reset + disable TS output until lock */
+ tda10086_write_mask(state, 0x10, 0x40, 0x40);
+ tda10086_write_mask(state, 0x00, 0x01, 0x00);
+
+@@ -459,13 +464,13 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
+ int tmp;
+ u64 tmp64;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+- // check for invalid symbol rate
++ /* check for invalid symbol rate */
+ if (fe_params->u.qpsk.symbol_rate < 500000)
+ return -EINVAL;
+
+- // calculate the updated frequency (note: we convert from Hz->kHz)
++ /* calculate the updated frequency (note: we convert from Hz->kHz) */
+ tmp64 = tda10086_read_byte(state, 0x52);
+ tmp64 |= (tda10086_read_byte(state, 0x51) << 8);
+ if (tmp64 & 0x8000)
+@@ -474,7 +479,7 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
+ do_div(tmp64, (1ULL<<15) * (1ULL<<1));
+ fe_params->frequency = (int) state->frequency + (int) tmp64;
+
+- // the inversion
++ /* the inversion */
+ val = tda10086_read_byte(state, 0x0c);
+ if (val & 0x80) {
+ switch(val & 0x40) {
+@@ -505,7 +510,7 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
+ }
+ }
+
+- // calculate the updated symbol rate
++ /* calculate the updated symbol rate */
+ tmp = tda10086_read_byte(state, 0x1d);
+ if (tmp & 0x80)
+ tmp |= 0xffffff00;
+@@ -513,7 +518,7 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
+ tmp = ((state->symbol_rate/1000) * tmp) / (1000000/1000);
+ fe_params->u.qpsk.symbol_rate = state->symbol_rate + tmp;
+
+- // the FEC
++ /* the FEC */
+ val = (tda10086_read_byte(state, 0x0d) & 0x70) >> 4;
+ switch(val) {
+ case 0x00:
+@@ -550,7 +555,7 @@ static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status)
+ struct tda10086_state* state = fe->demodulator_priv;
+ u8 val;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ val = tda10086_read_byte(state, 0x0e);
+ *fe_status = 0;
+@@ -566,7 +571,7 @@ static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status)
+ *fe_status |= FE_HAS_LOCK;
+ if (!state->has_lock) {
+ state->has_lock = true;
+- // modify parameters for stable reception
++ /* modify parameters for stable reception */
+ tda10086_write_byte(state, 0x02, 0x00);
+ }
+ }
+@@ -579,7 +584,7 @@ static int tda10086_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
+ struct tda10086_state* state = fe->demodulator_priv;
+ u8 _str;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ _str = 0xff - tda10086_read_byte(state, 0x43);
+ *signal = (_str << 8) | _str;
+@@ -592,7 +597,7 @@ static int tda10086_read_snr(struct dvb_frontend* fe, u16 * snr)
+ struct tda10086_state* state = fe->demodulator_priv;
+ u8 _snr;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ _snr = 0xff - tda10086_read_byte(state, 0x1c);
+ *snr = (_snr << 8) | _snr;
+@@ -604,12 +609,12 @@ static int tda10086_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+ {
+ struct tda10086_state* state = fe->demodulator_priv;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+- // read it
++ /* read it */
+ *ucblocks = tda10086_read_byte(state, 0x18) & 0x7f;
+
+- // reset counter
++ /* reset counter */
+ tda10086_write_byte(state, 0x18, 0x00);
+ tda10086_write_byte(state, 0x18, 0x80);
+
+@@ -620,9 +625,9 @@ static int tda10086_read_ber(struct dvb_frontend* fe, u32* ber)
+ {
+ struct tda10086_state* state = fe->demodulator_priv;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+- // read it
++ /* read it */
+ *ber = 0;
+ *ber |= tda10086_read_byte(state, 0x15);
+ *ber |= tda10086_read_byte(state, 0x16) << 8;
+@@ -635,7 +640,7 @@ static int tda10086_sleep(struct dvb_frontend* fe)
+ {
+ struct tda10086_state* state = fe->demodulator_priv;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ tda10086_write_mask(state, 0x00, 0x08, 0x08);
+
+@@ -646,7 +651,7 @@ static int tda10086_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+ {
+ struct tda10086_state* state = fe->demodulator_priv;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ if (enable) {
+ tda10086_write_mask(state, 0x00, 0x10, 0x10);
+@@ -737,7 +742,7 @@ struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
+ {
+ struct tda10086_state *state;
+
+- dprintk ("%s\n", __FUNCTION__);
++ dprintk ("%s\n", __func__);
+
+ /* allocate memory for the internal state */
+ state = kmalloc(sizeof(struct tda10086_state), GFP_KERNEL);
+diff --git a/drivers/media/dvb/frontends/tda10086.h b/drivers/media/dvb/frontends/tda10086.h
+index eeceaee..61148c5 100644
+--- a/drivers/media/dvb/frontends/tda10086.h
++++ b/drivers/media/dvb/frontends/tda10086.h
+@@ -26,6 +26,11 @@
+ #include <linux/dvb/frontend.h>
+ #include <linux/firmware.h>
+
++enum tda10086_xtal {
++ TDA10086_XTAL_16M,
++ TDA10086_XTAL_4M
++};
++
+ struct tda10086_config
+ {
+ /* the demodulator's i2c address */
+@@ -36,6 +41,9 @@ struct tda10086_config
+
+ /* do we need the diseqc signal with carrier? */
+ u8 diseqc_tone;
++
++ /* frequency of the reference xtal */
++ enum tda10086_xtal xtal_freq;
+ };
+
+ #if defined(CONFIG_DVB_TDA10086) || (defined(CONFIG_DVB_TDA10086_MODULE) && defined(MODULE))
+@@ -45,9 +53,9 @@ extern struct dvb_frontend* tda10086_attach(const struct tda10086_config* config
+ static inline struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
+ struct i2c_adapter* i2c)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+-#endif // CONFIG_DVB_TDA10086
++#endif /* CONFIG_DVB_TDA10086 */
+
+-#endif // TDA10086_H
++#endif /* TDA10086_H */
+diff --git a/drivers/media/dvb/frontends/tda18271-common.c b/drivers/media/dvb/frontends/tda18271-common.c
+index bca5709..e27a762 100644
+--- a/drivers/media/dvb/frontends/tda18271-common.c
++++ b/drivers/media/dvb/frontends/tda18271-common.c
+@@ -125,16 +125,16 @@ int tda18271_read_regs(struct dvb_frontend *fe)
+ unsigned char buf = 0x00;
+ int ret;
+ struct i2c_msg msg[] = {
+- { .addr = priv->i2c_addr, .flags = 0,
++ { .addr = priv->i2c_props.addr, .flags = 0,
+ .buf = &buf, .len = 1 },
+- { .addr = priv->i2c_addr, .flags = I2C_M_RD,
++ { .addr = priv->i2c_props.addr, .flags = I2C_M_RD,
+ .buf = regs, .len = 16 }
+ };
+
+ tda18271_i2c_gate_ctrl(fe, 1);
+
+ /* read all registers */
+- ret = i2c_transfer(priv->i2c_adap, msg, 2);
++ ret = i2c_transfer(priv->i2c_props.adap, msg, 2);
+
+ tda18271_i2c_gate_ctrl(fe, 0);
+
+@@ -155,16 +155,16 @@ int tda18271_read_extended(struct dvb_frontend *fe)
+ unsigned char buf = 0x00;
+ int ret, i;
+ struct i2c_msg msg[] = {
+- { .addr = priv->i2c_addr, .flags = 0,
++ { .addr = priv->i2c_props.addr, .flags = 0,
+ .buf = &buf, .len = 1 },
+- { .addr = priv->i2c_addr, .flags = I2C_M_RD,
++ { .addr = priv->i2c_props.addr, .flags = I2C_M_RD,
+ .buf = regdump, .len = TDA18271_NUM_REGS }
+ };
+
+ tda18271_i2c_gate_ctrl(fe, 1);
+
+ /* read all registers */
+- ret = i2c_transfer(priv->i2c_adap, msg, 2);
++ ret = i2c_transfer(priv->i2c_props.adap, msg, 2);
+
+ tda18271_i2c_gate_ctrl(fe, 0);
+
+@@ -192,7 +192,7 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
+ struct tda18271_priv *priv = fe->tuner_priv;
+ unsigned char *regs = priv->tda18271_regs;
+ unsigned char buf[TDA18271_NUM_REGS + 1];
+- struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
++ struct i2c_msg msg = { .addr = priv->i2c_props.addr, .flags = 0,
+ .buf = buf, .len = len + 1 };
+ int i, ret;
+
+@@ -205,7 +205,7 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
+ tda18271_i2c_gate_ctrl(fe, 1);
+
+ /* write registers */
+- ret = i2c_transfer(priv->i2c_adap, &msg, 1);
++ ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
+
+ tda18271_i2c_gate_ctrl(fe, 0);
+
+@@ -217,13 +217,29 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
+
+ /*---------------------------------------------------------------------*/
+
++int tda18271_charge_pump_source(struct dvb_frontend *fe,
++ enum tda18271_pll pll, int force)
++{
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned char *regs = priv->tda18271_regs;
++
++ int r_cp = (pll == TDA18271_CAL_PLL) ? R_EB7 : R_EB4;
++
++ regs[r_cp] &= ~0x20;
++ regs[r_cp] |= ((force & 1) << 5);
++ tda18271_write_regs(fe, r_cp, 1);
++
++ return 0;
++}
++
+ int tda18271_init_regs(struct dvb_frontend *fe)
+ {
+ struct tda18271_priv *priv = fe->tuner_priv;
+ unsigned char *regs = priv->tda18271_regs;
+
+ tda_dbg("initializing registers for device @ %d-%04x\n",
+- i2c_adapter_id(priv->i2c_adap), priv->i2c_addr);
++ i2c_adapter_id(priv->i2c_props.adap),
++ priv->i2c_props.addr);
+
+ /* initialize registers */
+ switch (priv->id) {
+@@ -310,7 +326,12 @@ int tda18271_init_regs(struct dvb_frontend *fe)
+ regs[R_EB22] = 0x48;
+ regs[R_EB23] = 0xb0;
+
+- tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS);
++ if (priv->small_i2c) {
++ tda18271_write_regs(fe, 0x00, 0x10);
++ tda18271_write_regs(fe, 0x10, 0x10);
++ tda18271_write_regs(fe, 0x20, 0x07);
++ } else
++ tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS);
+
+ /* setup agc1 gain */
+ regs[R_EB17] = 0x00;
+@@ -349,24 +370,15 @@ int tda18271_init_regs(struct dvb_frontend *fe)
+ regs[R_MD2] = 0x08;
+ regs[R_MD3] = 0x00;
+
+- switch (priv->id) {
+- case TDA18271HDC1:
+- tda18271_write_regs(fe, R_EP3, 11);
+- break;
+- case TDA18271HDC2:
+- tda18271_write_regs(fe, R_EP3, 12);
+- break;
+- };
++ tda18271_write_regs(fe, R_EP3, 11);
+
+ if ((priv->id) == TDA18271HDC2) {
+ /* main pll cp source on */
+- regs[R_EB4] = 0x61;
+- tda18271_write_regs(fe, R_EB4, 1);
++ tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1);
+ msleep(1);
+
+ /* main pll cp source off */
+- regs[R_EB4] = 0x41;
+- tda18271_write_regs(fe, R_EB4, 1);
++ tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0);
+ }
+
+ msleep(5); /* pll locking */
+@@ -398,6 +410,7 @@ int tda18271_init_regs(struct dvb_frontend *fe)
+ tda18271_write_regs(fe, R_EP3, 11);
+ msleep(5); /* pll locking */
+
++ /* launch detector */
+ tda18271_write_regs(fe, R_EP1, 1);
+ msleep(5); /* wanted mid measurement */
+
+diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c
+index dfe72aa..b262100 100644
+--- a/drivers/media/dvb/frontends/tda18271-fe.c
++++ b/drivers/media/dvb/frontends/tda18271-fe.c
+@@ -31,30 +31,23 @@ static int tda18271_cal_on_startup;
+ module_param_named(cal, tda18271_cal_on_startup, int, 0644);
+ MODULE_PARM_DESC(cal, "perform RF tracking filter calibration on startup");
+
+-static LIST_HEAD(tda18271_list);
+ static DEFINE_MUTEX(tda18271_list_mutex);
++static LIST_HEAD(hybrid_tuner_instance_list);
+
+ /*---------------------------------------------------------------------*/
+
+-static int tda18271_ir_cal_init(struct dvb_frontend *fe)
++static inline int charge_pump_source(struct dvb_frontend *fe, int force)
+ {
+ struct tda18271_priv *priv = fe->tuner_priv;
+- unsigned char *regs = priv->tda18271_regs;
+-
+- tda18271_read_regs(fe);
+-
+- /* test IR_CAL_OK to see if we need init */
+- if ((regs[R_EP1] & 0x08) == 0)
+- tda18271_init_regs(fe);
+-
+- return 0;
++ return tda18271_charge_pump_source(fe,
++ (priv->role == TDA18271_SLAVE) ?
++ TDA18271_CAL_PLL :
++ TDA18271_MAIN_PLL, force);
+ }
+
+-/* ------------------------------------------------------------------ */
+-
+ static int tda18271_channel_configuration(struct dvb_frontend *fe,
+- u32 ifc, u32 freq, u32 bw, u8 std,
+- int radio)
++ struct tda18271_std_map_item *map,
++ u32 freq, u32 bw)
+ {
+ struct tda18271_priv *priv = fe->tuner_priv;
+ unsigned char *regs = priv->tda18271_regs;
+@@ -64,38 +57,34 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
+
+ /* set standard */
+ regs[R_EP3] &= ~0x1f; /* clear std bits */
+- regs[R_EP3] |= std;
++ regs[R_EP3] |= (map->agc_mode << 3) | map->std;
++
++ /* set rfagc to high speed mode */
++ regs[R_EP3] &= ~0x04;
+
+ /* set cal mode to normal */
+ regs[R_EP4] &= ~0x03;
+
+ /* update IF output level & IF notch frequency */
+ regs[R_EP4] &= ~0x1c; /* clear if level bits */
++ regs[R_EP4] |= (map->if_lvl << 2);
+
+ switch (priv->mode) {
+ case TDA18271_ANALOG:
+ regs[R_MPD] &= ~0x80; /* IF notch = 0 */
+ break;
+ case TDA18271_DIGITAL:
+- regs[R_EP4] |= 0x04; /* IF level = 1 */
+ regs[R_MPD] |= 0x80; /* IF notch = 1 */
+ break;
+ }
+
+- if (radio)
+- regs[R_EP4] |= 0x80;
+- else
+- regs[R_EP4] &= ~0x80;
++ /* update FM_RFn */
++ regs[R_EP4] &= ~0x80;
++ regs[R_EP4] |= map->fm_rfn << 7;
+
+- /* update RF_TOP / IF_TOP */
+- switch (priv->mode) {
+- case TDA18271_ANALOG:
+- regs[R_EB22] = 0x2c;
+- break;
+- case TDA18271_DIGITAL:
+- regs[R_EB22] = 0x37;
+- break;
+- }
++ /* update rf top / if top */
++ regs[R_EB22] = 0x00;
++ regs[R_EB22] |= map->rfagc_top;
+ tda18271_write_regs(fe, R_EB22, 1);
+
+ /* --------------------------------------------------------------- */
+@@ -117,8 +106,14 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
+
+ /* dual tuner and agc1 extra configuration */
+
+- /* main vco when Master, cal vco when slave */
+- regs[R_EB1] |= 0x04; /* FIXME: assumes master */
++ switch (priv->role) {
++ case TDA18271_MASTER:
++ regs[R_EB1] |= 0x04; /* main vco */
++ break;
++ case TDA18271_SLAVE:
++ regs[R_EB1] &= ~0x04; /* cal vco */
++ break;
++ }
+
+ /* agc1 always active */
+ regs[R_EB1] &= ~0x02;
+@@ -130,25 +125,40 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
+
+ /* --------------------------------------------------------------- */
+
+- N = freq + ifc;
++ N = map->if_freq * 1000 + freq;
+
+- /* FIXME: assumes master */
+- tda18271_calc_main_pll(fe, N);
+- tda18271_write_regs(fe, R_MPD, 4);
++ switch (priv->role) {
++ case TDA18271_MASTER:
++ tda18271_calc_main_pll(fe, N);
++ tda18271_write_regs(fe, R_MPD, 4);
++ break;
++ case TDA18271_SLAVE:
++ tda18271_calc_cal_pll(fe, N);
++ tda18271_write_regs(fe, R_CPD, 4);
++
++ regs[R_MPD] = regs[R_CPD] & 0x7f;
++ tda18271_write_regs(fe, R_MPD, 1);
++ break;
++ }
+
+ tda18271_write_regs(fe, R_TM, 7);
+
+- /* main pll charge pump source */
+- regs[R_EB4] |= 0x20;
+- tda18271_write_regs(fe, R_EB4, 1);
++ /* force charge pump source */
++ charge_pump_source(fe, 1);
+
+ msleep(1);
+
+- /* normal operation for the main pll */
+- regs[R_EB4] &= ~0x20;
+- tda18271_write_regs(fe, R_EB4, 1);
++ /* return pll to normal operation */
++ charge_pump_source(fe, 0);
+
+- msleep(5);
++ msleep(20);
++
++ /* set rfagc to normal speed mode */
++ if (map->fm_rfn)
++ regs[R_EP3] &= ~0x04;
++ else
++ regs[R_EP3] |= 0x04;
++ tda18271_write_regs(fe, R_EP3, 1);
+
+ return 0;
+ }
+@@ -195,8 +205,10 @@ static int tda18271_read_thermometer(struct dvb_frontend *fe)
+ return tm;
+ }
+
+-static int tda18271_rf_tracking_filters_correction(struct dvb_frontend *fe,
+- u32 freq)
++/* ------------------------------------------------------------------ */
++
++static int tda18271c2_rf_tracking_filters_correction(struct dvb_frontend *fe,
++ u32 freq)
+ {
+ struct tda18271_priv *priv = fe->tuner_priv;
+ struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state;
+@@ -296,12 +308,10 @@ static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq)
+ tda18271_write_regs(fe, R_EB13, 1);
+
+ /* main pll charge pump source */
+- regs[R_EB4] |= 0x20;
+- tda18271_write_regs(fe, R_EB4, 1);
++ tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1);
+
+ /* cal pll charge pump source */
+- regs[R_EB7] |= 0x20;
+- tda18271_write_regs(fe, R_EB7, 1);
++ tda18271_charge_pump_source(fe, TDA18271_CAL_PLL, 1);
+
+ /* force dcdc converter to 0 V */
+ regs[R_EB14] = 0x00;
+@@ -320,8 +330,8 @@ static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq)
+ /* set the internal calibration signal */
+ N = freq;
+
+- tda18271_calc_main_pll(fe, N);
+- tda18271_write_regs(fe, R_MPD, 4);
++ tda18271_calc_cal_pll(fe, N);
++ tda18271_write_regs(fe, R_CPD, 4);
+
+ /* downconvert internal calibration */
+ N += 1000000;
+@@ -339,14 +349,12 @@ static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq)
+ /* --------------------------------------------------------------- */
+
+ /* normal operation for the main pll */
+- regs[R_EB4] &= ~0x20;
+- tda18271_write_regs(fe, R_EB4, 1);
++ tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0);
+
+ /* normal operation for the cal pll */
+- regs[R_EB7] &= ~0x20;
+- tda18271_write_regs(fe, R_EB7, 1);
++ tda18271_charge_pump_source(fe, TDA18271_CAL_PLL, 0);
+
+- msleep(5); /* plls locking */
++ msleep(10); /* plls locking */
+
+ /* launch the rf tracking filters calibration */
+ regs[R_EB20] |= 0x20;
+@@ -443,7 +451,7 @@ static int tda18271_powerscan(struct dvb_frontend *fe,
+
+ count += 200;
+
+- if (count < count_limit)
++ if (count <= count_limit)
+ continue;
+
+ if (sgn <= 0)
+@@ -587,7 +595,7 @@ static int tda18271_calc_rf_filter_curve(struct dvb_frontend *fe)
+
+ /* ------------------------------------------------------------------ */
+
+-static int tda18271_rf_cal_init(struct dvb_frontend *fe)
++static int tda18271c2_rf_cal_init(struct dvb_frontend *fe)
+ {
+ struct tda18271_priv *priv = fe->tuner_priv;
+ unsigned char *regs = priv->tda18271_regs;
+@@ -610,63 +618,13 @@ static int tda18271_rf_cal_init(struct dvb_frontend *fe)
+ return 0;
+ }
+
+-static int tda18271_init(struct dvb_frontend *fe)
+-{
+- struct tda18271_priv *priv = fe->tuner_priv;
+-
+- mutex_lock(&priv->lock);
+-
+- /* power up */
+- tda18271_set_standby_mode(fe, 0, 0, 0);
+-
+- /* initialization */
+- tda18271_ir_cal_init(fe);
+-
+- if (priv->id == TDA18271HDC2)
+- tda18271_rf_cal_init(fe);
+-
+- mutex_unlock(&priv->lock);
+-
+- return 0;
+-}
+-
+-static int tda18271c2_tune(struct dvb_frontend *fe,
+- u32 ifc, u32 freq, u32 bw, u8 std, int radio)
+-{
+- struct tda18271_priv *priv = fe->tuner_priv;
+-
+- tda_dbg("freq = %d, ifc = %d\n", freq, ifc);
+-
+- tda18271_init(fe);
+-
+- mutex_lock(&priv->lock);
+-
+- tda18271_rf_tracking_filters_correction(fe, freq);
+-
+- tda18271_channel_configuration(fe, ifc, freq, bw, std, radio);
+-
+- mutex_unlock(&priv->lock);
+-
+- return 0;
+-}
+-
+-/* ------------------------------------------------------------------ */
+-
+-static int tda18271c1_tune(struct dvb_frontend *fe,
+- u32 ifc, u32 freq, u32 bw, u8 std, int radio)
++static int tda18271c1_rf_tracking_filter_calibration(struct dvb_frontend *fe,
++ u32 freq, u32 bw)
+ {
+ struct tda18271_priv *priv = fe->tuner_priv;
+ unsigned char *regs = priv->tda18271_regs;
+ u32 N = 0;
+
+- tda18271_init(fe);
+-
+- mutex_lock(&priv->lock);
+-
+- tda_dbg("freq = %d, ifc = %d\n", freq, ifc);
+-
+- /* RF tracking filter calibration */
+-
+ /* calculate bp filter */
+ tda18271_calc_bp_filter(fe, &freq);
+ tda18271_write_regs(fe, R_EP1, 1);
+@@ -737,7 +695,7 @@ static int tda18271c1_tune(struct dvb_frontend *fe,
+
+ regs[R_EB7] = 0x40;
+ tda18271_write_regs(fe, R_EB7, 1);
+- msleep(10);
++ msleep(10); /* pll locking */
+
+ regs[R_EB20] = 0xec;
+ tda18271_write_regs(fe, R_EB20, 1);
+@@ -752,74 +710,70 @@ static int tda18271c1_tune(struct dvb_frontend *fe,
+ if (0 == tda18271_calc_rf_cal(fe, &freq))
+ tda18271_write_regs(fe, R_EB14, 1);
+
+- /* Channel Configuration */
++ return 0;
++}
+
+- switch (priv->mode) {
+- case TDA18271_ANALOG:
+- regs[R_EB22] = 0x2c;
+- break;
+- case TDA18271_DIGITAL:
+- regs[R_EB22] = 0x37;
+- break;
+- }
+- tda18271_write_regs(fe, R_EB22, 1);
++/* ------------------------------------------------------------------ */
+
+- regs[R_EP1] |= 0x40; /* set dis power level on */
++static int tda18271_ir_cal_init(struct dvb_frontend *fe)
++{
++ struct tda18271_priv *priv = fe->tuner_priv;
++ unsigned char *regs = priv->tda18271_regs;
+
+- /* set standard */
+- regs[R_EP3] &= ~0x1f; /* clear std bits */
++ tda18271_read_regs(fe);
+
+- /* see table 22 */
+- regs[R_EP3] |= std;
++ /* test IR_CAL_OK to see if we need init */
++ if ((regs[R_EP1] & 0x08) == 0)
++ tda18271_init_regs(fe);
+
+- regs[R_EP4] &= ~0x03; /* set cal mode to normal */
++ return 0;
++}
+
+- regs[R_EP4] &= ~0x1c; /* clear if level bits */
+- switch (priv->mode) {
+- case TDA18271_ANALOG:
+- regs[R_MPD] &= ~0x80; /* IF notch = 0 */
+- break;
+- case TDA18271_DIGITAL:
+- regs[R_EP4] |= 0x04;
+- regs[R_MPD] |= 0x80;
+- break;
+- }
++static int tda18271_init(struct dvb_frontend *fe)
++{
++ struct tda18271_priv *priv = fe->tuner_priv;
+
+- if (radio)
+- regs[R_EP4] |= 0x80;
+- else
+- regs[R_EP4] &= ~0x80;
++ mutex_lock(&priv->lock);
+
+- /* image rejection validity */
+- tda18271_calc_ir_measure(fe, &freq);
++ /* power up */
++ tda18271_set_standby_mode(fe, 0, 0, 0);
+
+- /* calculate MAIN PLL */
+- N = freq + ifc;
++ /* initialization */
++ tda18271_ir_cal_init(fe);
+
+- tda18271_calc_main_pll(fe, N);
++ if (priv->id == TDA18271HDC2)
++ tda18271c2_rf_cal_init(fe);
+
+- tda18271_write_regs(fe, R_TM, 15);
+- msleep(5);
+ mutex_unlock(&priv->lock);
+
+ return 0;
+ }
+
+-static inline int tda18271_tune(struct dvb_frontend *fe,
+- u32 ifc, u32 freq, u32 bw, u8 std, int radio)
++static int tda18271_tune(struct dvb_frontend *fe,
++ struct tda18271_std_map_item *map, u32 freq, u32 bw)
+ {
+ struct tda18271_priv *priv = fe->tuner_priv;
+- int ret = -EINVAL;
++
++ tda_dbg("freq = %d, ifc = %d, bw = %d, agc_mode = %d, std = %d\n",
++ freq, map->if_freq, bw, map->agc_mode, map->std);
++
++ tda18271_init(fe);
++
++ mutex_lock(&priv->lock);
+
+ switch (priv->id) {
+ case TDA18271HDC1:
+- ret = tda18271c1_tune(fe, ifc, freq, bw, std, radio);
++ tda18271c1_rf_tracking_filter_calibration(fe, freq, bw);
+ break;
+ case TDA18271HDC2:
+- ret = tda18271c2_tune(fe, ifc, freq, bw, std, radio);
++ tda18271c2_rf_tracking_filters_correction(fe, freq);
+ break;
+ }
+- return ret;
++ tda18271_channel_configuration(fe, map, freq, bw);
++
++ mutex_unlock(&priv->lock);
++
++ return 0;
+ }
+
+ /* ------------------------------------------------------------------ */
+@@ -829,9 +783,8 @@ static int tda18271_set_params(struct dvb_frontend *fe,
+ {
+ struct tda18271_priv *priv = fe->tuner_priv;
+ struct tda18271_std_map *std_map = &priv->std;
++ struct tda18271_std_map_item *map;
+ int ret;
+- u8 std;
+- u16 sgIF;
+ u32 bw, freq = params->frequency;
+
+ priv->mode = TDA18271_DIGITAL;
+@@ -840,13 +793,11 @@ static int tda18271_set_params(struct dvb_frontend *fe,
+ switch (params->u.vsb.modulation) {
+ case VSB_8:
+ case VSB_16:
+- std = std_map->atsc_6.std_bits;
+- sgIF = std_map->atsc_6.if_freq;
++ map = &std_map->atsc_6;
+ break;
+ case QAM_64:
+ case QAM_256:
+- std = std_map->qam_6.std_bits;
+- sgIF = std_map->qam_6.if_freq;
++ map = &std_map->qam_6;
+ break;
+ default:
+ tda_warn("modulation not set!\n");
+@@ -861,18 +812,15 @@ static int tda18271_set_params(struct dvb_frontend *fe,
+ switch (params->u.ofdm.bandwidth) {
+ case BANDWIDTH_6_MHZ:
+ bw = 6000000;
+- std = std_map->dvbt_6.std_bits;
+- sgIF = std_map->dvbt_6.if_freq;
++ map = &std_map->dvbt_6;
+ break;
+ case BANDWIDTH_7_MHZ:
+ bw = 7000000;
+- std = std_map->dvbt_7.std_bits;
+- sgIF = std_map->dvbt_7.if_freq;
++ map = &std_map->dvbt_7;
+ break;
+ case BANDWIDTH_8_MHZ:
+ bw = 8000000;
+- std = std_map->dvbt_8.std_bits;
+- sgIF = std_map->dvbt_8.if_freq;
++ map = &std_map->dvbt_8;
+ break;
+ default:
+ tda_warn("bandwidth not set!\n");
+@@ -887,7 +835,7 @@ static int tda18271_set_params(struct dvb_frontend *fe,
+ if (fe->ops.analog_ops.standby)
+ fe->ops.analog_ops.standby(fe);
+
+- ret = tda18271_tune(fe, sgIF * 1000, freq, bw, std, 0);
++ ret = tda18271_tune(fe, map, freq, bw);
+
+ if (ret < 0)
+ goto fail;
+@@ -904,57 +852,46 @@ static int tda18271_set_analog_params(struct dvb_frontend *fe,
+ {
+ struct tda18271_priv *priv = fe->tuner_priv;
+ struct tda18271_std_map *std_map = &priv->std;
++ struct tda18271_std_map_item *map;
+ char *mode;
+- int ret, radio = 0;
+- u8 std;
+- u16 sgIF;
++ int ret;
+ u32 freq = params->frequency * 62500;
+
+ priv->mode = TDA18271_ANALOG;
+
+ if (params->mode == V4L2_TUNER_RADIO) {
+- radio = 1;
+ freq = freq / 1000;
+- std = std_map->fm_radio.std_bits;
+- sgIF = std_map->fm_radio.if_freq;
++ map = &std_map->fm_radio;
+ mode = "fm";
+ } else if (params->std & V4L2_STD_MN) {
+- std = std_map->atv_mn.std_bits;
+- sgIF = std_map->atv_mn.if_freq;
++ map = &std_map->atv_mn;
+ mode = "MN";
+ } else if (params->std & V4L2_STD_B) {
+- std = std_map->atv_b.std_bits;
+- sgIF = std_map->atv_b.if_freq;
++ map = &std_map->atv_b;
+ mode = "B";
+ } else if (params->std & V4L2_STD_GH) {
+- std = std_map->atv_gh.std_bits;
+- sgIF = std_map->atv_gh.if_freq;
++ map = &std_map->atv_gh;
+ mode = "GH";
+ } else if (params->std & V4L2_STD_PAL_I) {
+- std = std_map->atv_i.std_bits;
+- sgIF = std_map->atv_i.if_freq;
++ map = &std_map->atv_i;
+ mode = "I";
+ } else if (params->std & V4L2_STD_DK) {
+- std = std_map->atv_dk.std_bits;
+- sgIF = std_map->atv_dk.if_freq;
++ map = &std_map->atv_dk;
+ mode = "DK";
+ } else if (params->std & V4L2_STD_SECAM_L) {
+- std = std_map->atv_l.std_bits;
+- sgIF = std_map->atv_l.if_freq;
++ map = &std_map->atv_l;
+ mode = "L";
+ } else if (params->std & V4L2_STD_SECAM_LC) {
+- std = std_map->atv_lc.std_bits;
+- sgIF = std_map->atv_lc.if_freq;
++ map = &std_map->atv_lc;
+ mode = "L'";
+ } else {
+- std = std_map->atv_i.std_bits;
+- sgIF = std_map->atv_i.if_freq;
++ map = &std_map->atv_i;
+ mode = "xx";
+ }
+
+ tda_dbg("setting tda18271 to system %s\n", mode);
+
+- ret = tda18271_tune(fe, sgIF * 1000, freq, 0, std, radio);
++ ret = tda18271_tune(fe, map, freq, 0);
+
+ if (ret < 0)
+ goto fail;
+@@ -986,16 +923,9 @@ static int tda18271_release(struct dvb_frontend *fe)
+
+ mutex_lock(&tda18271_list_mutex);
+
+- priv->count--;
++ if (priv)
++ hybrid_tuner_release_state(priv);
+
+- if (!priv->count) {
+- tda_dbg("destroying instance @ %d-%04x\n",
+- i2c_adapter_id(priv->i2c_adap),
+- priv->i2c_addr);
+- list_del(&priv->tda18271_list);
+-
+- kfree(priv);
+- }
+ mutex_unlock(&tda18271_list_mutex);
+
+ fe->tuner_priv = NULL;
+@@ -1020,15 +950,20 @@ static int tda18271_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+ /* ------------------------------------------------------------------ */
+
+ #define tda18271_update_std(std_cfg, name) do { \
+- if (map->std_cfg.if_freq + map->std_cfg.std_bits > 0) { \
++ if (map->std_cfg.if_freq + \
++ map->std_cfg.agc_mode + map->std_cfg.std + \
++ map->std_cfg.if_lvl + map->std_cfg.rfagc_top > 0) { \
+ tda_dbg("Using custom std config for %s\n", name); \
+ memcpy(&std->std_cfg, &map->std_cfg, \
+ sizeof(struct tda18271_std_map_item)); \
+ } } while (0)
+
+ #define tda18271_dump_std_item(std_cfg, name) do { \
+- tda_dbg("(%s) if freq = %d, std bits = 0x%02x\n", \
+- name, std->std_cfg.if_freq, std->std_cfg.std_bits); \
++ tda_dbg("(%s) if_freq = %d, agc_mode = %d, std = %d, " \
++ "if_lvl = %d, rfagc_top = 0x%02x\n", \
++ name, std->std_cfg.if_freq, \
++ std->std_cfg.agc_mode, std->std_cfg.std, \
++ std->std_cfg.if_lvl, std->std_cfg.rfagc_top); \
+ } while (0)
+
+ static int tda18271_dump_std_map(struct dvb_frontend *fe)
+@@ -1037,20 +972,20 @@ static int tda18271_dump_std_map(struct dvb_frontend *fe)
+ struct tda18271_std_map *std = &priv->std;
+
+ tda_dbg("========== STANDARD MAP SETTINGS ==========\n");
+- tda18271_dump_std_item(fm_radio, "fm");
+- tda18271_dump_std_item(atv_b, "pal b");
+- tda18271_dump_std_item(atv_dk, "pal dk");
+- tda18271_dump_std_item(atv_gh, "pal gh");
+- tda18271_dump_std_item(atv_i, "pal i");
+- tda18271_dump_std_item(atv_l, "pal l");
+- tda18271_dump_std_item(atv_lc, "pal l'");
++ tda18271_dump_std_item(fm_radio, " fm ");
++ tda18271_dump_std_item(atv_b, "atv b ");
++ tda18271_dump_std_item(atv_dk, "atv dk");
++ tda18271_dump_std_item(atv_gh, "atv gh");
++ tda18271_dump_std_item(atv_i, "atv i ");
++ tda18271_dump_std_item(atv_l, "atv l ");
++ tda18271_dump_std_item(atv_lc, "atv l'");
+ tda18271_dump_std_item(atv_mn, "atv mn");
+ tda18271_dump_std_item(atsc_6, "atsc 6");
+ tda18271_dump_std_item(dvbt_6, "dvbt 6");
+ tda18271_dump_std_item(dvbt_7, "dvbt 7");
+ tda18271_dump_std_item(dvbt_8, "dvbt 8");
+- tda18271_dump_std_item(qam_6, "qam 6");
+- tda18271_dump_std_item(qam_8, "qam 8");
++ tda18271_dump_std_item(qam_6, "qam 6 ");
++ tda18271_dump_std_item(qam_8, "qam 8 ");
+
+ return 0;
+ }
+@@ -1109,7 +1044,8 @@ static int tda18271_get_id(struct dvb_frontend *fe)
+ }
+
+ tda_info("%s detected @ %d-%04x%s\n", name,
+- i2c_adapter_id(priv->i2c_adap), priv->i2c_addr,
++ i2c_adapter_id(priv->i2c_props.adap),
++ priv->i2c_props.addr,
+ (0 == ret) ? "" : ", device not supported.");
+
+ return ret;
+@@ -1136,45 +1072,28 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
+ struct tda18271_config *cfg)
+ {
+ struct tda18271_priv *priv = NULL;
+- int state_found = 0;
++ int instance;
+
+ mutex_lock(&tda18271_list_mutex);
+
+- list_for_each_entry(priv, &tda18271_list, tda18271_list) {
+- if ((i2c_adapter_id(priv->i2c_adap) == i2c_adapter_id(i2c)) &&
+- (priv->i2c_addr == addr)) {
+- tda_dbg("attaching existing tuner @ %d-%04x\n",
+- i2c_adapter_id(priv->i2c_adap),
+- priv->i2c_addr);
+- priv->count++;
+- fe->tuner_priv = priv;
+- state_found = 1;
+- /* allow dvb driver to override i2c gate setting */
+- if ((cfg) && (cfg->gate != TDA18271_GATE_ANALOG))
+- priv->gate = cfg->gate;
+- break;
+- }
+- }
+- if (state_found == 0) {
+- tda_dbg("creating new tuner instance @ %d-%04x\n",
+- i2c_adapter_id(i2c), addr);
+-
+- priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL);
+- if (priv == NULL) {
+- mutex_unlock(&tda18271_list_mutex);
+- return NULL;
+- }
+-
+- priv->i2c_addr = addr;
+- priv->i2c_adap = i2c;
++ instance = hybrid_tuner_request_state(struct tda18271_priv, priv,
++ hybrid_tuner_instance_list,
++ i2c, addr, "tda18271");
++ switch (instance) {
++ case 0:
++ goto fail;
++ break;
++ case 1:
++ /* new tuner instance */
+ priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO;
++ priv->role = (cfg) ? cfg->role : TDA18271_MASTER;
+ priv->cal_initialized = false;
+ mutex_init(&priv->lock);
+- priv->count++;
+
+ fe->tuner_priv = priv;
+
+- list_add_tail(&priv->tda18271_list, &tda18271_list);
++ if (cfg)
++ priv->small_i2c = cfg->small_i2c;
+
+ if (tda18271_get_id(fe) < 0)
+ goto fail;
+@@ -1186,9 +1105,18 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
+ tda18271_init_regs(fe);
+
+ if ((tda18271_cal_on_startup) && (priv->id == TDA18271HDC2))
+- tda18271_rf_cal_init(fe);
++ tda18271c2_rf_cal_init(fe);
+
+ mutex_unlock(&priv->lock);
++ break;
++ default:
++ /* existing tuner instance */
++ fe->tuner_priv = priv;
++
++ /* allow dvb driver to override i2c gate setting */
++ if ((cfg) && (cfg->gate != TDA18271_GATE_ANALOG))
++ priv->gate = cfg->gate;
++ break;
+ }
+
+ /* override default std map with values in config struct */
+@@ -1200,7 +1128,7 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
+ memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops,
+ sizeof(struct dvb_tuner_ops));
+
+- if (tda18271_debug & DBG_MAP)
++ if (tda18271_debug & (DBG_MAP | DBG_ADV))
+ tda18271_dump_std_map(fe);
+
+ return fe;
+@@ -1214,7 +1142,7 @@ EXPORT_SYMBOL_GPL(tda18271_attach);
+ MODULE_DESCRIPTION("NXP TDA18271HD analog / digital tuner driver");
+ MODULE_AUTHOR("Michael Krufky <mkrufky at linuxtv.org>");
+ MODULE_LICENSE("GPL");
+-MODULE_VERSION("0.2");
++MODULE_VERSION("0.3");
+
+ /*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+diff --git a/drivers/media/dvb/frontends/tda18271-priv.h b/drivers/media/dvb/frontends/tda18271-priv.h
+index 7b939a5..2bc5eb3 100644
+--- a/drivers/media/dvb/frontends/tda18271-priv.h
++++ b/drivers/media/dvb/frontends/tda18271-priv.h
+@@ -24,6 +24,7 @@
+ #include <linux/kernel.h>
+ #include <linux/types.h>
+ #include <linux/mutex.h>
++#include "tuner-i2c.h"
+ #include "tda18271.h"
+
+ #define R_ID 0x00 /* ID byte */
+@@ -85,6 +86,11 @@ struct tda18271_rf_tracking_filter_cal {
+ int rf_b2;
+ };
+
++enum tda18271_pll {
++ TDA18271_MAIN_PLL,
++ TDA18271_CAL_PLL,
++};
++
+ enum tda18271_mode {
+ TDA18271_ANALOG,
+ TDA18271_DIGITAL,
+@@ -98,19 +104,19 @@ enum tda18271_ver {
+ };
+
+ struct tda18271_priv {
+- u8 i2c_addr;
+- struct i2c_adapter *i2c_adap;
+ unsigned char tda18271_regs[TDA18271_NUM_REGS];
+
+- struct list_head tda18271_list;
++ struct list_head hybrid_tuner_instance_list;
++ struct tuner_i2c_props i2c_props;
+
+ enum tda18271_mode mode;
++ enum tda18271_role role;
+ enum tda18271_i2c_gate gate;
+ enum tda18271_ver id;
+
+- unsigned int count;
+ unsigned int tm_rfcal;
+ unsigned int cal_initialized:1;
++ unsigned int small_i2c:1;
+
+ struct tda18271_map_layout *maps;
+ struct tda18271_std_map std;
+@@ -133,7 +139,7 @@ extern int tda18271_debug;
+ #define DBG_CAL 16
+
+ #define tda_printk(kern, fmt, arg...) \
+- printk(kern "%s: " fmt, __FUNCTION__, ##arg)
++ printk(kern "%s: " fmt, __func__, ##arg)
+
+ #define dprintk(kern, lvl, fmt, arg...) do {\
+ if (tda18271_debug & lvl) \
+@@ -188,6 +194,8 @@ extern int tda18271_read_extended(struct dvb_frontend *fe);
+ extern int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len);
+ extern int tda18271_init_regs(struct dvb_frontend *fe);
+
++extern int tda18271_charge_pump_source(struct dvb_frontend *fe,
++ enum tda18271_pll pll, int force);
+ extern int tda18271_set_standby_mode(struct dvb_frontend *fe,
+ int sm, int sm_lt, int sm_xt);
+
+diff --git a/drivers/media/dvb/frontends/tda18271-tables.c b/drivers/media/dvb/frontends/tda18271-tables.c
+index e94afcf..83e7561 100644
+--- a/drivers/media/dvb/frontends/tda18271-tables.c
++++ b/drivers/media/dvb/frontends/tda18271-tables.c
+@@ -1187,37 +1187,65 @@ fail:
+ /*---------------------------------------------------------------------*/
+
+ static struct tda18271_std_map tda18271c1_std_map = {
+- .fm_radio = { .if_freq = 1250, .std_bits = 0x18 },
+- .atv_b = { .if_freq = 6750, .std_bits = 0x0e },
+- .atv_dk = { .if_freq = 7750, .std_bits = 0x0f },
+- .atv_gh = { .if_freq = 7750, .std_bits = 0x0f },
+- .atv_i = { .if_freq = 7750, .std_bits = 0x0f },
+- .atv_l = { .if_freq = 7750, .std_bits = 0x0f },
+- .atv_lc = { .if_freq = 1250, .std_bits = 0x0f },
+- .atv_mn = { .if_freq = 5750, .std_bits = 0x0d },
+- .atsc_6 = { .if_freq = 3250, .std_bits = 0x1c },
+- .dvbt_6 = { .if_freq = 3300, .std_bits = 0x1c },
+- .dvbt_7 = { .if_freq = 3800, .std_bits = 0x1d },
+- .dvbt_8 = { .if_freq = 4300, .std_bits = 0x1e },
+- .qam_6 = { .if_freq = 4000, .std_bits = 0x1d },
+- .qam_8 = { .if_freq = 5000, .std_bits = 0x1f },
++ .fm_radio = { .if_freq = 1250, .fm_rfn = 1, .agc_mode = 3, .std = 0,
++ .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x18 */
++ .atv_b = { .if_freq = 6750, .fm_rfn = 0, .agc_mode = 1, .std = 6,
++ .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
++ .atv_dk = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7,
++ .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
++ .atv_gh = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7,
++ .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
++ .atv_i = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7,
++ .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
++ .atv_l = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7,
++ .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
++ .atv_lc = { .if_freq = 1250, .fm_rfn = 0, .agc_mode = 1, .std = 7,
++ .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
++ .atv_mn = { .if_freq = 5750, .fm_rfn = 0, .agc_mode = 1, .std = 5,
++ .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0d */
++ .atsc_6 = { .if_freq = 3250, .fm_rfn = 0, .agc_mode = 3, .std = 4,
++ .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
++ .dvbt_6 = { .if_freq = 3300, .fm_rfn = 0, .agc_mode = 3, .std = 4,
++ .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
++ .dvbt_7 = { .if_freq = 3800, .fm_rfn = 0, .agc_mode = 3, .std = 5,
++ .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */
++ .dvbt_8 = { .if_freq = 4300, .fm_rfn = 0, .agc_mode = 3, .std = 6,
++ .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1e */
++ .qam_6 = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5,
++ .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */
++ .qam_8 = { .if_freq = 5000, .fm_rfn = 0, .agc_mode = 3, .std = 7,
++ .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1f */
+ };
+
+ static struct tda18271_std_map tda18271c2_std_map = {
+- .fm_radio = { .if_freq = 1250, .std_bits = 0x18 },
+- .atv_b = { .if_freq = 6000, .std_bits = 0x0d },
+- .atv_dk = { .if_freq = 6900, .std_bits = 0x0e },
+- .atv_gh = { .if_freq = 7100, .std_bits = 0x0e },
+- .atv_i = { .if_freq = 7250, .std_bits = 0x0e },
+- .atv_l = { .if_freq = 6900, .std_bits = 0x0e },
+- .atv_lc = { .if_freq = 1250, .std_bits = 0x0e },
+- .atv_mn = { .if_freq = 5400, .std_bits = 0x0c },
+- .atsc_6 = { .if_freq = 3250, .std_bits = 0x1c },
+- .dvbt_6 = { .if_freq = 3300, .std_bits = 0x1c },
+- .dvbt_7 = { .if_freq = 3500, .std_bits = 0x1c },
+- .dvbt_8 = { .if_freq = 4000, .std_bits = 0x1d },
+- .qam_6 = { .if_freq = 4000, .std_bits = 0x1d },
+- .qam_8 = { .if_freq = 5000, .std_bits = 0x1f },
++ .fm_radio = { .if_freq = 1250, .fm_rfn = 1, .agc_mode = 3, .std = 0,
++ .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x18 */
++ .atv_b = { .if_freq = 6000, .fm_rfn = 0, .agc_mode = 1, .std = 5,
++ .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0d */
++ .atv_dk = { .if_freq = 6900, .fm_rfn = 0, .agc_mode = 1, .std = 6,
++ .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
++ .atv_gh = { .if_freq = 7100, .fm_rfn = 0, .agc_mode = 1, .std = 6,
++ .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
++ .atv_i = { .if_freq = 7250, .fm_rfn = 0, .agc_mode = 1, .std = 6,
++ .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
++ .atv_l = { .if_freq = 6900, .fm_rfn = 0, .agc_mode = 1, .std = 6,
++ .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
++ .atv_lc = { .if_freq = 1250, .fm_rfn = 0, .agc_mode = 1, .std = 6,
++ .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
++ .atv_mn = { .if_freq = 5400, .fm_rfn = 0, .agc_mode = 1, .std = 4,
++ .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0c */
++ .atsc_6 = { .if_freq = 3250, .fm_rfn = 0, .agc_mode = 3, .std = 4,
++ .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
++ .dvbt_6 = { .if_freq = 3300, .fm_rfn = 0, .agc_mode = 3, .std = 4,
++ .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
++ .dvbt_7 = { .if_freq = 3500, .fm_rfn = 0, .agc_mode = 3, .std = 4,
++ .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
++ .dvbt_8 = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5,
++ .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */
++ .qam_6 = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5,
++ .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */
++ .qam_8 = { .if_freq = 5000, .fm_rfn = 0, .agc_mode = 3, .std = 7,
++ .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1f */
+ };
+
+ /*---------------------------------------------------------------------*/
+diff --git a/drivers/media/dvb/frontends/tda18271.h b/drivers/media/dvb/frontends/tda18271.h
+index 24b0e35..0e7af8d 100644
+--- a/drivers/media/dvb/frontends/tda18271.h
++++ b/drivers/media/dvb/frontends/tda18271.h
+@@ -26,7 +26,17 @@
+
+ struct tda18271_std_map_item {
+ u16 if_freq;
+- u8 std_bits;
++
++ /* EP3[4:3] */
++ unsigned int agc_mode:2;
++ /* EP3[2:0] */
++ unsigned int std:3;
++ /* EP4[7] */
++ unsigned int fm_rfn:1;
++ /* EP4[4:2] */
++ unsigned int if_lvl:3;
++ /* EB22[6:0] */
++ unsigned int rfagc_top:7;
+ };
+
+ struct tda18271_std_map {
+@@ -46,6 +56,11 @@ struct tda18271_std_map {
+ struct tda18271_std_map_item qam_8;
+ };
+
++enum tda18271_role {
++ TDA18271_MASTER = 0,
++ TDA18271_SLAVE,
++};
++
+ enum tda18271_i2c_gate {
+ TDA18271_GATE_AUTO = 0,
+ TDA18271_GATE_ANALOG,
+@@ -56,8 +71,14 @@ struct tda18271_config {
+ /* override default if freq / std settings (optional) */
+ struct tda18271_std_map *std_map;
+
++ /* master / slave tuner: master uses main pll, slave uses cal pll */
++ enum tda18271_role role;
++
+ /* use i2c gate provided by analog or digital demod */
+ enum tda18271_i2c_gate gate;
++
++ /* some i2c providers cant write all 39 registers at once */
++ unsigned int small_i2c:1;
+ };
+
+ #if defined(CONFIG_DVB_TDA18271) || (defined(CONFIG_DVB_TDA18271_MODULE) && defined(MODULE))
+@@ -70,7 +91,7 @@ static inline struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ struct tda18271_config *cfg)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif
+diff --git a/drivers/media/dvb/frontends/tda8083.c b/drivers/media/dvb/frontends/tda8083.c
+index 011b74f..5b843b2 100644
+--- a/drivers/media/dvb/frontends/tda8083.c
++++ b/drivers/media/dvb/frontends/tda8083.c
+@@ -68,7 +68,7 @@ static int tda8083_writereg (struct tda8083_state* state, u8 reg, u8 data)
+
+ if (ret != 1)
+ dprintk ("%s: writereg error (reg %02x, ret == %i)\n",
+- __FUNCTION__, reg, ret);
++ __func__, reg, ret);
+
+ return (ret != 1) ? -1 : 0;
+ }
+@@ -83,7 +83,7 @@ static int tda8083_readregs (struct tda8083_state* state, u8 reg1, u8 *b, u8 len
+
+ if (ret != 2)
+ dprintk ("%s: readreg error (reg %02x, ret == %i)\n",
+- __FUNCTION__, reg1, ret);
++ __func__, reg1, ret);
+
+ return ret == 2 ? 0 : -1;
+ }
+diff --git a/drivers/media/dvb/frontends/tda8083.h b/drivers/media/dvb/frontends/tda8083.h
+index 2d33079..5a03c14 100644
+--- a/drivers/media/dvb/frontends/tda8083.h
++++ b/drivers/media/dvb/frontends/tda8083.h
+@@ -42,7 +42,7 @@ extern struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
+ static inline struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
+ struct i2c_adapter* i2c)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_TDA8083
+diff --git a/drivers/media/dvb/frontends/tda826x.c b/drivers/media/dvb/frontends/tda826x.c
+index bd3ebc2..a051554 100644
+--- a/drivers/media/dvb/frontends/tda826x.c
++++ b/drivers/media/dvb/frontends/tda826x.c
+@@ -26,7 +26,7 @@
+
+ #include "tda826x.h"
+
+-static int debug = 0;
++static int debug;
+ #define dprintk(args...) \
+ do { \
+ if (debug) printk(KERN_DEBUG "tda826x: " args); \
+@@ -54,7 +54,7 @@ static int tda826x_sleep(struct dvb_frontend *fe)
+ u8 buf [] = { 0x00, 0x8d };
+ struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = buf, .len = 2 };
+
+- dprintk("%s:\n", __FUNCTION__);
++ dprintk("%s:\n", __func__);
+
+ if (!priv->has_loopthrough)
+ buf[1] = 0xad;
+@@ -62,7 +62,7 @@ static int tda826x_sleep(struct dvb_frontend *fe)
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
+- dprintk("%s: i2c error\n", __FUNCTION__);
++ dprintk("%s: i2c error\n", __func__);
+ }
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+@@ -75,13 +75,24 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
+ struct tda826x_priv *priv = fe->tuner_priv;
+ int ret;
+ u32 div;
++ u32 ksyms;
++ u32 bandwidth;
+ u8 buf [11];
+ struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = buf, .len = 11 };
+
+- dprintk("%s:\n", __FUNCTION__);
++ dprintk("%s:\n", __func__);
+
+ div = (params->frequency + (1000-1)) / 1000;
+
++ /* BW = ((1 + RO) * SR/2 + 5) * 1.3 [SR in MSPS, BW in MHz] */
++ /* with R0 = 0.35 and some transformations: */
++ ksyms = params->u.qpsk.symbol_rate / 1000;
++ bandwidth = (878 * ksyms + 6500000) / 1000000 + 1;
++ if (bandwidth < 5)
++ bandwidth = 5;
++ else if (bandwidth > 36)
++ bandwidth = 36;
++
+ buf[0] = 0x00; // subaddress
+ buf[1] = 0x09; // powerdown RSSI + the magic value 1
+ if (!priv->has_loopthrough)
+@@ -89,7 +100,7 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
+ buf[2] = (1<<5) | 0x0b; // 1Mhz + 0.45 VCO
+ buf[3] = div >> 7;
+ buf[4] = div << 1;
+- buf[5] = 0x77; // baseband cut-off 19 MHz
++ buf[5] = ((bandwidth - 5) << 3) | 7; /* baseband cut-off */
+ buf[6] = 0xfe; // baseband gain 9 db + no RF attenuation
+ buf[7] = 0x83; // charge pumps at high, tests off
+ buf[8] = 0x80; // recommended value 4 for AMPVCO + disable ports.
+@@ -99,7 +110,7 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
+- dprintk("%s: i2c error\n", __FUNCTION__);
++ dprintk("%s: i2c error\n", __func__);
+ }
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+@@ -138,7 +149,7 @@ struct dvb_frontend *tda826x_attach(struct dvb_frontend *fe, int addr, struct i2
+ };
+ int ret;
+
+- dprintk("%s:\n", __FUNCTION__);
++ dprintk("%s:\n", __func__);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+diff --git a/drivers/media/dvb/frontends/tda826x.h b/drivers/media/dvb/frontends/tda826x.h
+index ad99811..89e9792 100644
+--- a/drivers/media/dvb/frontends/tda826x.h
++++ b/drivers/media/dvb/frontends/tda826x.h
+@@ -45,7 +45,7 @@ static inline struct dvb_frontend* tda826x_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ int has_loopthrough)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_TDA826X
+diff --git a/drivers/media/dvb/frontends/tda827x.c b/drivers/media/dvb/frontends/tda827x.c
+index 229b119..d30d2c9 100644
+--- a/drivers/media/dvb/frontends/tda827x.c
++++ b/drivers/media/dvb/frontends/tda827x.c
+@@ -25,7 +25,7 @@
+
+ #include "tda827x.h"
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+@@ -142,7 +142,7 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
+ int i, tuner_freq, if_freq;
+ u32 N;
+
+- dprintk("%s:\n", __FUNCTION__);
++ dprintk("%s:\n", __func__);
+ switch (params->u.ofdm.bandwidth) {
+ case BANDWIDTH_6_MHZ:
+ if_freq = 4000000;
+@@ -186,7 +186,7 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) {
+ printk("%s: could not write to tuner at addr: 0x%02x\n",
+- __FUNCTION__, priv->i2c_addr << 1);
++ __func__, priv->i2c_addr << 1);
+ return -EIO;
+ }
+ msleep(500);
+@@ -212,7 +212,7 @@ static int tda827xo_sleep(struct dvb_frontend *fe)
+ struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
+ .buf = buf, .len = sizeof(buf) };
+
+- dprintk("%s:\n", __FUNCTION__);
++ dprintk("%s:\n", __func__);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ i2c_transfer(priv->i2c_adap, &msg, 1);
+@@ -389,6 +389,79 @@ static struct tda827xa_data tda827xa_analog[] = {
+ { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
+ };
+
++static int tda827xa_sleep(struct dvb_frontend *fe)
++{
++ struct tda827x_priv *priv = fe->tuner_priv;
++ static u8 buf[] = { 0x30, 0x90 };
++ struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
++ .buf = buf, .len = sizeof(buf) };
++
++ dprintk("%s:\n", __func__);
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
++
++ i2c_transfer(priv->i2c_adap, &msg, 1);
++
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 0);
++
++ if (priv->cfg && priv->cfg->sleep)
++ priv->cfg->sleep(fe);
++
++ return 0;
++}
++
++static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
++ struct analog_parameters *params)
++{
++ struct tda827x_priv *priv = fe->tuner_priv;
++ unsigned char buf[] = {0x22, 0x01};
++ int arg;
++ int gp_func;
++ struct i2c_msg msg = { .addr = priv->cfg->switch_addr, .flags = 0,
++ .buf = buf, .len = sizeof(buf) };
++
++ if (NULL == priv->cfg) {
++ dprintk("tda827x_config not defined, cannot set LNA gain!\n");
++ return;
++ }
++ if (priv->cfg->config) {
++ if (high)
++ dprintk("setting LNA to high gain\n");
++ else
++ dprintk("setting LNA to low gain\n");
++ }
++ switch (priv->cfg->config) {
++ case 0: /* no LNA */
++ break;
++ case 1: /* switch is GPIO 0 of tda8290 */
++ case 2:
++ if (params == NULL) {
++ gp_func = 0;
++ arg = 0;
++ } else {
++ /* turn Vsync on */
++ gp_func = 1;
++ if (params->std & V4L2_STD_MN)
++ arg = 1;
++ else
++ arg = 0;
++ }
++ if (priv->cfg->tuner_callback)
++ priv->cfg->tuner_callback(priv->i2c_adap->algo_data,
++ gp_func, arg);
++ buf[1] = high ? 0 : 1;
++ if (priv->cfg->config == 2)
++ buf[1] = high ? 1 : 0;
++ i2c_transfer(priv->i2c_adap, &msg, 1);
++ break;
++ case 3: /* switch with GPIO of saa713x */
++ if (priv->cfg->tuner_callback)
++ priv->cfg->tuner_callback(priv->i2c_adap->algo_data, 0, high);
++ break;
++ }
++}
++
+ static int tda827xa_set_params(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *params)
+ {
+@@ -401,9 +474,9 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
+ int i, tuner_freq, if_freq;
+ u32 N;
+
+- dprintk("%s:\n", __FUNCTION__);
+- if (priv->cfg && priv->cfg->lna_gain)
+- priv->cfg->lna_gain(fe, 1);
++ dprintk("%s:\n", __func__);
++
++ tda827xa_lna_gain(fe, 1, NULL);
+ msleep(20);
+
+ switch (params->u.ofdm.bandwidth) {
+@@ -444,7 +517,7 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) {
+ printk("%s: could not write to tuner at addr: 0x%02x\n",
+- __FUNCTION__, priv->i2c_addr << 1);
++ __func__, priv->i2c_addr << 1);
+ return -EIO;
+ }
+ buf[0] = 0x90;
+@@ -474,8 +547,7 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
+ buf[1] >>= 4;
+ dprintk("tda8275a AGC2 gain is: %d\n", buf[1]);
+ if ((buf[1]) < 2) {
+- if (priv->cfg && priv->cfg->lna_gain)
+- priv->cfg->lna_gain(fe, 0);
++ tda827xa_lna_gain(fe, 0, NULL);
+ buf[0] = 0x60;
+ buf[1] = 0x0c;
+ if (fe->ops.i2c_gate_ctrl)
+@@ -523,75 +595,6 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
+ return 0;
+ }
+
+-static int tda827xa_sleep(struct dvb_frontend *fe)
+-{
+- struct tda827x_priv *priv = fe->tuner_priv;
+- static u8 buf[] = { 0x30, 0x90 };
+- struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
+- .buf = buf, .len = sizeof(buf) };
+-
+- dprintk("%s:\n", __FUNCTION__);
+- if (fe->ops.i2c_gate_ctrl)
+- fe->ops.i2c_gate_ctrl(fe, 1);
+-
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+-
+- if (fe->ops.i2c_gate_ctrl)
+- fe->ops.i2c_gate_ctrl(fe, 0);
+-
+- if (priv->cfg && priv->cfg->sleep)
+- priv->cfg->sleep(fe);
+-
+- return 0;
+-}
+-
+-/* ------------------------------------------------------------------ */
+-
+-static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
+- struct analog_parameters *params)
+-{
+- struct tda827x_priv *priv = fe->tuner_priv;
+- unsigned char buf[] = {0x22, 0x01};
+- int arg;
+- struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
+- .buf = buf, .len = sizeof(buf) };
+-
+- if (NULL == priv->cfg) {
+- dprintk("tda827x_config not defined, cannot set LNA gain!\n");
+- return;
+- }
+-
+- if (priv->cfg->config) {
+- if (high)
+- dprintk("setting LNA to high gain\n");
+- else
+- dprintk("setting LNA to low gain\n");
+- }
+- switch (*priv->cfg->config) {
+- case 0: /* no LNA */
+- break;
+- case 1: /* switch is GPIO 0 of tda8290 */
+- case 2:
+- /* turn Vsync on */
+- if (params->std & V4L2_STD_MN)
+- arg = 1;
+- else
+- arg = 0;
+- if (priv->cfg->tuner_callback)
+- priv->cfg->tuner_callback(priv->i2c_adap->algo_data,
+- 1, arg);
+- buf[1] = high ? 0 : 1;
+- if (*priv->cfg->config == 2)
+- buf[1] = high ? 1 : 0;
+- i2c_transfer(priv->i2c_adap, &msg, 1);
+- break;
+- case 3: /* switch with GPIO of saa713x */
+- if (priv->cfg->tuner_callback)
+- priv->cfg->tuner_callback(priv->i2c_adap->algo_data,
+- 0, high);
+- break;
+- }
+-}
+
+ static int tda827xa_set_analog_params(struct dvb_frontend *fe,
+ struct analog_parameters *params)
+@@ -726,7 +729,7 @@ static int tda827x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+ static int tda827x_init(struct dvb_frontend *fe)
+ {
+ struct tda827x_priv *priv = fe->tuner_priv;
+- dprintk("%s:\n", __FUNCTION__);
++ dprintk("%s:\n", __func__);
+ if (priv->cfg && priv->cfg->init)
+ priv->cfg->init(fe);
+
+@@ -794,7 +797,7 @@ static int tda827x_probe_version(struct dvb_frontend *fe)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) {
+ printk("%s: could not read from tuner at addr: 0x%02x\n",
+- __FUNCTION__, msg.addr << 1);
++ __func__, msg.addr << 1);
+ return -EIO;
+ }
+ if ((data & 0x3c) == 0) {
+@@ -818,7 +821,7 @@ struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr,
+ {
+ struct tda827x_priv *priv = NULL;
+
+- dprintk("%s:\n", __FUNCTION__);
++ dprintk("%s:\n", __func__);
+ priv = kzalloc(sizeof(struct tda827x_priv), GFP_KERNEL);
+ if (priv == NULL)
+ return NULL;
+diff --git a/drivers/media/dvb/frontends/tda827x.h b/drivers/media/dvb/frontends/tda827x.h
+index 92eb65b..b73c235 100644
+--- a/drivers/media/dvb/frontends/tda827x.h
++++ b/drivers/media/dvb/frontends/tda827x.h
+@@ -30,12 +30,12 @@
+ struct tda827x_config
+ {
+ /* saa7134 - provided callbacks */
+- void (*lna_gain) (struct dvb_frontend *fe, int high);
+ int (*init) (struct dvb_frontend *fe);
+ int (*sleep) (struct dvb_frontend *fe);
+
+ /* interface to tda829x driver */
+- unsigned int *config;
++ unsigned int config;
++ int switch_addr;
+ int (*tuner_callback) (void *dev, int command, int arg);
+
+ void (*agcf)(struct dvb_frontend *fe);
+@@ -61,7 +61,7 @@ static inline struct dvb_frontend* tda827x_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ struct tda827x_config *cfg)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_TDA827X
+diff --git a/drivers/media/dvb/frontends/tua6100.c b/drivers/media/dvb/frontends/tua6100.c
+index 6ba0029..1790bae 100644
+--- a/drivers/media/dvb/frontends/tua6100.c
++++ b/drivers/media/dvb/frontends/tua6100.c
+@@ -58,7 +58,7 @@ static int tua6100_sleep(struct dvb_frontend *fe)
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
+- printk("%s: i2c error\n", __FUNCTION__);
++ printk("%s: i2c error\n", __func__);
+ }
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+diff --git a/drivers/media/dvb/frontends/tua6100.h b/drivers/media/dvb/frontends/tua6100.h
+index 03a665e..f83dbd5 100644
+--- a/drivers/media/dvb/frontends/tua6100.h
++++ b/drivers/media/dvb/frontends/tua6100.h
+@@ -39,7 +39,7 @@ extern struct dvb_frontend *tua6100_attach(struct dvb_frontend *fe, int addr, st
+ #else
+ static inline struct dvb_frontend* tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_TUA6100
+diff --git a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb/frontends/ves1820.c
+index 8791701..a184597 100644
+--- a/drivers/media/dvb/frontends/ves1820.c
++++ b/drivers/media/dvb/frontends/ves1820.c
+@@ -66,7 +66,7 @@ static int ves1820_writereg(struct ves1820_state *state, u8 reg, u8 data)
+
+ if (ret != 1)
+ printk("ves1820: %s(): writereg error (reg == 0x%02x, "
+- "val == 0x%02x, ret == %i)\n", __FUNCTION__, reg, data, ret);
++ "val == 0x%02x, ret == %i)\n", __func__, reg, data, ret);
+
+ return (ret != 1) ? -EREMOTEIO : 0;
+ }
+@@ -85,7 +85,7 @@ static u8 ves1820_readreg(struct ves1820_state *state, u8 reg)
+
+ if (ret != 2)
+ printk("ves1820: %s(): readreg error (reg == 0x%02x, "
+- "ret == %i)\n", __FUNCTION__, reg, ret);
++ "ret == %i)\n", __func__, reg, ret);
+
+ return b1[0];
+ }
+diff --git a/drivers/media/dvb/frontends/ves1820.h b/drivers/media/dvb/frontends/ves1820.h
+index e4a2a32..e902ed6 100644
+--- a/drivers/media/dvb/frontends/ves1820.h
++++ b/drivers/media/dvb/frontends/ves1820.h
+@@ -48,7 +48,7 @@ extern struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
+ static inline struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
+ struct i2c_adapter* i2c, u8 pwm)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_VES1820
+diff --git a/drivers/media/dvb/frontends/ves1x93.c b/drivers/media/dvb/frontends/ves1x93.c
+index 23fd030..bd55896 100644
+--- a/drivers/media/dvb/frontends/ves1x93.c
++++ b/drivers/media/dvb/frontends/ves1x93.c
+@@ -48,7 +48,7 @@ struct ves1x93_state {
+ u8 demod_type;
+ };
+
+-static int debug = 0;
++static int debug;
+ #define dprintk if (debug) printk
+
+ #define DEMOD_VES1893 0
+@@ -98,7 +98,7 @@ static int ves1x93_writereg (struct ves1x93_state* state, u8 reg, u8 data)
+ int err;
+
+ if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+- dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data);
++ dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
+ return -EREMOTEIO;
+ }
+
+@@ -179,7 +179,7 @@ static int ves1x93_set_symbolrate (struct ves1x93_state* state, u32 srate)
+ u32 tmp;
+ u32 FIN;
+
+- dprintk("%s: srate == %d\n", __FUNCTION__, (unsigned int) srate);
++ dprintk("%s: srate == %d\n", __func__, (unsigned int) srate);
+
+ if (srate > state->config->xin/2)
+ srate = state->config->xin/2;
+@@ -266,7 +266,7 @@ static int ves1x93_init (struct dvb_frontend* fe)
+ int i;
+ int val;
+
+- dprintk("%s: init chip\n", __FUNCTION__);
++ dprintk("%s: init chip\n", __func__);
+
+ for (i = 0; i < state->tab_size; i++) {
+ if (state->init_1x93_wtab[i]) {
+diff --git a/drivers/media/dvb/frontends/ves1x93.h b/drivers/media/dvb/frontends/ves1x93.h
+index d507f89..8a5a49e 100644
+--- a/drivers/media/dvb/frontends/ves1x93.h
++++ b/drivers/media/dvb/frontends/ves1x93.h
+@@ -47,7 +47,7 @@ extern struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
+ static inline struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
+ struct i2c_adapter* i2c)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_VES1X93
+diff --git a/drivers/media/dvb/frontends/xc5000.c b/drivers/media/dvb/frontends/xc5000.c
+index f642ca2..43d35bd 100644
+--- a/drivers/media/dvb/frontends/xc5000.c
++++ b/drivers/media/dvb/frontends/xc5000.c
+@@ -151,7 +151,7 @@ typedef struct {
+ #define FM_Radio_INPUT2 21
+ #define FM_Radio_INPUT1 22
+
+-XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
++static XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
+ {"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020},
+ {"M/N-NTSC/PAL-A2", 0x0600, 0x8020},
+ {"M/N-NTSC/PAL-EIAJ", 0x0440, 0x8020},
+@@ -209,7 +209,7 @@ static void xc5000_TunerReset(struct dvb_frontend *fe)
+ struct xc5000_priv *priv = fe->tuner_priv;
+ int ret;
+
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+
+ if (priv->cfg->tuner_callback) {
+ ret = priv->cfg->tuner_callback(priv->cfg->priv,
+@@ -330,7 +330,7 @@ static int xc_load_i2c_sequence(struct dvb_frontend *fe, u8 i2c_sequence[])
+
+ static int xc_initialize(struct xc5000_priv *priv)
+ {
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+ return xc_write_reg(priv, XREG_INIT, 0);
+ }
+
+@@ -338,9 +338,9 @@ static int xc_SetTVStandard(struct xc5000_priv *priv,
+ u16 VideoMode, u16 AudioMode)
+ {
+ int ret;
+- dprintk(1, "%s(0x%04x,0x%04x)\n", __FUNCTION__, VideoMode, AudioMode);
++ dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, VideoMode, AudioMode);
+ dprintk(1, "%s() Standard = %s\n",
+- __FUNCTION__,
++ __func__,
+ XC5000_Standard[priv->video_standard].Name);
+
+ ret = xc_write_reg(priv, XREG_VIDEO_MODE, VideoMode);
+@@ -361,7 +361,7 @@ static int xc_shutdown(struct xc5000_priv *priv)
+
+ static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode)
+ {
+- dprintk(1, "%s(%d) Source = %s\n", __FUNCTION__, rf_mode,
++ dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode,
+ rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE");
+
+ if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE))
+@@ -369,7 +369,7 @@ static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode)
+ rf_mode = XC_RF_MODE_CABLE;
+ printk(KERN_ERR
+ "%s(), Invalid mode, defaulting to CABLE",
+- __FUNCTION__);
++ __func__);
+ }
+ return xc_write_reg(priv, XREG_SIGNALSOURCE, rf_mode);
+ }
+@@ -380,7 +380,7 @@ static int xc_set_RF_frequency(struct xc5000_priv *priv, u32 freq_hz)
+ {
+ u16 freq_code;
+
+- dprintk(1, "%s(%u)\n", __FUNCTION__, freq_hz);
++ dprintk(1, "%s(%u)\n", __func__, freq_hz);
+
+ if ((freq_hz > xc5000_tuner_ops.info.frequency_max) ||
+ (freq_hz < xc5000_tuner_ops.info.frequency_min))
+@@ -396,7 +396,7 @@ static int xc_set_IF_frequency(struct xc5000_priv *priv, u32 freq_khz)
+ {
+ u32 freq_code = (freq_khz * 1024)/1000;
+ dprintk(1, "%s(freq_khz = %d) freq_code = 0x%x\n",
+- __FUNCTION__, freq_khz, freq_code);
++ __func__, freq_khz, freq_code);
+
+ return xc_write_reg(priv, XREG_IF_OUT, freq_code);
+ }
+@@ -488,7 +488,7 @@ static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz)
+ {
+ int found = 0;
+
+- dprintk(1, "%s(%u)\n", __FUNCTION__, freq_hz);
++ dprintk(1, "%s(%u)\n", __func__, freq_hz);
+
+ if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS)
+ return 0;
+@@ -627,12 +627,12 @@ static int xc5000_set_params(struct dvb_frontend *fe,
+ struct xc5000_priv *priv = fe->tuner_priv;
+ int ret;
+
+- dprintk(1, "%s() frequency=%d (Hz)\n", __FUNCTION__, params->frequency);
++ dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency);
+
+ switch(params->u.vsb.modulation) {
+ case VSB_8:
+ case VSB_16:
+- dprintk(1, "%s() VSB modulation\n", __FUNCTION__);
++ dprintk(1, "%s() VSB modulation\n", __func__);
+ priv->rf_mode = XC_RF_MODE_AIR;
+ priv->freq_hz = params->frequency - 1750000;
+ priv->bandwidth = BANDWIDTH_6_MHZ;
+@@ -641,7 +641,7 @@ static int xc5000_set_params(struct dvb_frontend *fe,
+ case QAM_64:
+ case QAM_256:
+ case QAM_AUTO:
+- dprintk(1, "%s() QAM modulation\n", __FUNCTION__);
++ dprintk(1, "%s() QAM modulation\n", __func__);
+ priv->rf_mode = XC_RF_MODE_CABLE;
+ priv->freq_hz = params->frequency - 1750000;
+ priv->bandwidth = BANDWIDTH_6_MHZ;
+@@ -652,7 +652,7 @@ static int xc5000_set_params(struct dvb_frontend *fe,
+ }
+
+ dprintk(1, "%s() frequency=%d (compensated)\n",
+- __FUNCTION__, priv->freq_hz);
++ __func__, priv->freq_hz);
+
+ ret = xc_SetSignalSource(priv, priv->rf_mode);
+ if (ret != XC_RESULT_SUCCESS) {
+@@ -697,7 +697,7 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe,
+ xc_load_fw_and_init_tuner(fe);
+
+ dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
+- __FUNCTION__, params->frequency);
++ __func__, params->frequency);
+
+ priv->rf_mode = XC_RF_MODE_CABLE; /* Fix me: it could be air. */
+
+@@ -775,7 +775,7 @@ tune_channel:
+ static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq)
+ {
+ struct xc5000_priv *priv = fe->tuner_priv;
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+ *freq = priv->freq_hz;
+ return 0;
+ }
+@@ -783,7 +783,7 @@ static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq)
+ static int xc5000_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
+ {
+ struct xc5000_priv *priv = fe->tuner_priv;
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+
+ *bw = priv->bandwidth;
+ return 0;
+@@ -796,7 +796,7 @@ static int xc5000_get_status(struct dvb_frontend *fe, u32 *status)
+
+ xc_get_lock_status(priv, &lock_status);
+
+- dprintk(1, "%s() lock_status = 0x%08x\n", __FUNCTION__, lock_status);
++ dprintk(1, "%s() lock_status = 0x%08x\n", __func__, lock_status);
+
+ *status = lock_status;
+
+@@ -836,7 +836,7 @@ static int xc5000_sleep(struct dvb_frontend *fe)
+ struct xc5000_priv *priv = fe->tuner_priv;
+ int ret;
+
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+
+ /* On Pinnacle PCTV HD 800i, the tuner cannot be reinitialized
+ * once shutdown without reloading the driver. Maybe I am not
+@@ -848,7 +848,7 @@ static int xc5000_sleep(struct dvb_frontend *fe)
+ if(ret != XC_RESULT_SUCCESS) {
+ printk(KERN_ERR
+ "xc5000: %s() unable to shutdown tuner\n",
+- __FUNCTION__);
++ __func__);
+ return -EREMOTEIO;
+ }
+ else {
+@@ -860,7 +860,7 @@ static int xc5000_sleep(struct dvb_frontend *fe)
+ static int xc5000_init(struct dvb_frontend *fe)
+ {
+ struct xc5000_priv *priv = fe->tuner_priv;
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+
+ if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
+ printk(KERN_ERR "xc5000: Unable to initialise tuner\n");
+@@ -875,7 +875,7 @@ static int xc5000_init(struct dvb_frontend *fe)
+
+ static int xc5000_release(struct dvb_frontend *fe)
+ {
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+ kfree(fe->tuner_priv);
+ fe->tuner_priv = NULL;
+ return 0;
+@@ -907,7 +907,7 @@ struct dvb_frontend * xc5000_attach(struct dvb_frontend *fe,
+ struct xc5000_priv *priv = NULL;
+ u16 id = 0;
+
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+
+ priv = kzalloc(sizeof(struct xc5000_priv), GFP_KERNEL);
+ if (priv == NULL)
+diff --git a/drivers/media/dvb/frontends/xc5000.h b/drivers/media/dvb/frontends/xc5000.h
+index 32a5f1c..b890883 100644
+--- a/drivers/media/dvb/frontends/xc5000.h
++++ b/drivers/media/dvb/frontends/xc5000.h
+@@ -55,7 +55,7 @@ static inline struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ struct xc5000_config *cfg)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif // CONFIG_DVB_TUNER_XC5000
+diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c
+index 276e3b6..36a5a1c 100644
+--- a/drivers/media/dvb/frontends/zl10353.c
++++ b/drivers/media/dvb/frontends/zl10353.c
+@@ -46,7 +46,7 @@ static int debug;
+ if (debug) printk(KERN_DEBUG "zl10353: " args); \
+ } while (0)
+
+-static int debug_regs = 0;
++static int debug_regs;
+
+ static int zl10353_single_write(struct dvb_frontend *fe, u8 reg, u8 val)
+ {
+@@ -88,7 +88,7 @@ static int zl10353_read_register(struct zl10353_state *state, u8 reg)
+
+ if (ret != 2) {
+ printk("%s: readreg error (reg=%d, ret==%i)\n",
+- __FUNCTION__, reg, ret);
++ __func__, reg, ret);
+ return ret;
+ }
+
+@@ -152,7 +152,7 @@ static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
+ *nominal_rate = value;
+
+ dprintk("%s: bw %d, adc_clock %d => 0x%x\n",
+- __FUNCTION__, bw, adc_clock, *nominal_rate);
++ __func__, bw, adc_clock, *nominal_rate);
+ }
+
+ static void zl10353_calc_input_freq(struct dvb_frontend *fe,
+@@ -181,7 +181,7 @@ static void zl10353_calc_input_freq(struct dvb_frontend *fe,
+ *input_freq = -value;
+
+ dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n",
+- __FUNCTION__, if2, ife, adc_clock, -(int)value, *input_freq);
++ __func__, if2, ife, adc_clock, -(int)value, *input_freq);
+ }
+
+ static int zl10353_sleep(struct dvb_frontend *fe)
+diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h
+index fc734c2..fdbb88f 100644
+--- a/drivers/media/dvb/frontends/zl10353.h
++++ b/drivers/media/dvb/frontends/zl10353.h
+@@ -47,7 +47,7 @@ extern struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
+ static inline struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
+ struct i2c_adapter *i2c)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif /* CONFIG_DVB_ZL10353 */
+diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
+index 08a2599..960ed57 100644
+--- a/drivers/media/dvb/pluto2/pluto2.c
++++ b/drivers/media/dvb/pluto2/pluto2.c
+@@ -39,6 +39,8 @@
+ #include "dvbdev.h"
+ #include "tda1004x.h"
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define DRIVER_NAME "pluto2"
+
+ #define REG_PIDn(n) ((n) << 2) /* PID n pattern registers */
+@@ -662,7 +664,8 @@ static int __devinit pluto2_probe(struct pci_dev *pdev,
+ goto err_pluto_hw_exit;
+
+ /* dvb */
+- ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, THIS_MODULE, &pdev->dev);
++ ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME,
++ THIS_MODULE, &pdev->dev, adapter_nr);
+ if (ret < 0)
+ goto err_i2c_del_adapter;
+
+diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
+index 0e5701b..747e7f1 100644
+--- a/drivers/media/dvb/ttpci/av7110.c
++++ b/drivers/media/dvb/ttpci/av7110.c
+@@ -112,6 +112,8 @@ MODULE_PARM_DESC(wss_cfg_16_9, "WSS 16:9 - default 0x0007 - bit 15: disable, 14:
+ module_param(tv_standard, int, 0444);
+ MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC");
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ static void restart_feeds(struct av7110 *av7110);
+
+ static int av7110_num;
+@@ -359,7 +361,7 @@ static inline void start_debi_dma(struct av7110 *av7110, int dir,
+ {
+ dprintk(8, "%c %08lx %u\n", dir == DEBI_READ ? 'R' : 'W', addr, len);
+ if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
+- printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
++ printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __func__);
+ return;
+ }
+
+@@ -497,7 +499,7 @@ static void gpioirq(unsigned long data)
+ saa7146_read(av7110->dev, SSR));
+
+ if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
+- printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
++ printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __func__);
+ BUG(); /* maybe we should try resetting the debi? */
+ }
+
+@@ -827,7 +829,7 @@ static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
+ if (ret != 0 || handle >= 32) {
+ printk("dvb-ttpci: %s error buf %04x %04x %04x %04x "
+ "ret %d handle %04x\n",
+- __FUNCTION__, buf[0], buf[1], buf[2], buf[3],
++ __func__, buf[0], buf[1], buf[2], buf[3],
+ ret, handle);
+ dvbdmxfilter->hw_handle = 0xffff;
+ if (!ret)
+@@ -854,7 +856,7 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
+ handle = dvbdmxfilter->hw_handle;
+ if (handle >= 32) {
+ printk("%s tried to stop invalid filter %04x, filter type = %x\n",
+- __FUNCTION__, handle, dvbdmxfilter->type);
++ __func__, handle, dvbdmxfilter->type);
+ return -EINVAL;
+ }
+
+@@ -867,7 +869,7 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
+ if (ret != 0 || answ[1] != handle) {
+ printk("dvb-ttpci: %s error cmd %04x %04x %04x ret %x "
+ "resp %04x %04x pid %d\n",
+- __FUNCTION__, buf[0], buf[1], buf[2], ret,
++ __func__, buf[0], buf[1], buf[2], ret,
+ answ[0], answ[1], dvbdmxfilter->feed->pid);
+ if (!ret)
+ ret = -1;
+@@ -1122,7 +1124,7 @@ static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
+
+ ret = av7110_fw_request(av7110, &tag, 0, fwstc, 4);
+ if (ret) {
+- printk(KERN_ERR "%s: av7110_fw_request error\n", __FUNCTION__);
++ printk(KERN_ERR "%s: av7110_fw_request error\n", __func__);
+ return ret;
+ }
+ dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n",
+@@ -2461,7 +2463,7 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
+ goto err_kfree_0;
+
+ ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
+- THIS_MODULE, &dev->pci->dev);
++ THIS_MODULE, &dev->pci->dev, adapter_nr);
+ if (ret < 0)
+ goto err_put_firmware_1;
+
+diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h
+index 39fbf7d..e494e04 100644
+--- a/drivers/media/dvb/ttpci/av7110.h
++++ b/drivers/media/dvb/ttpci/av7110.h
+@@ -40,7 +40,7 @@
+ extern int av7110_debug;
+
+ #define dprintk(level,args...) \
+- do { if ((av7110_debug & level)) { printk("dvb-ttpci: %s(): ", __FUNCTION__); printk(args); } } while (0)
++ do { if ((av7110_debug & level)) { printk("dvb-ttpci: %s(): ", __func__); printk(args); } } while (0)
+
+ #define MAXFILT 32
+
+diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c
+index a468aa2..9d81074 100644
+--- a/drivers/media/dvb/ttpci/av7110_hw.c
++++ b/drivers/media/dvb/ttpci/av7110_hw.c
+@@ -53,11 +53,11 @@ int av7110_debiwrite(struct av7110 *av7110, u32 config,
+ struct saa7146_dev *dev = av7110->dev;
+
+ if (count <= 0 || count > 32764) {
+- printk("%s: invalid count %d\n", __FUNCTION__, count);
++ printk("%s: invalid count %d\n", __func__, count);
+ return -1;
+ }
+ if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
+- printk("%s: wait_for_debi_done failed\n", __FUNCTION__);
++ printk("%s: wait_for_debi_done failed\n", __func__);
+ return -1;
+ }
+ saa7146_write(dev, DEBI_CONFIG, config);
+@@ -76,11 +76,11 @@ u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count)
+ u32 result = 0;
+
+ if (count > 32764 || count <= 0) {
+- printk("%s: invalid count %d\n", __FUNCTION__, count);
++ printk("%s: invalid count %d\n", __func__, count);
+ return 0;
+ }
+ if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
+- printk("%s: wait_for_debi_done #1 failed\n", __FUNCTION__);
++ printk("%s: wait_for_debi_done #1 failed\n", __func__);
+ return 0;
+ }
+ saa7146_write(dev, DEBI_AD, av7110->debi_bus);
+@@ -91,7 +91,7 @@ u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count)
+ if (count > 4)
+ return count;
+ if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
+- printk("%s: wait_for_debi_done #2 failed\n", __FUNCTION__);
++ printk("%s: wait_for_debi_done #2 failed\n", __func__);
+ return 0;
+ }
+
+@@ -332,7 +332,7 @@ int av7110_wait_msgstate(struct av7110 *av7110, u16 flags)
+ break;
+ if (err) {
+ printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n",
+- __FUNCTION__, stat & flags);
++ __func__, stat & flags);
+ return -ETIMEDOUT;
+ }
+ msleep(1);
+@@ -362,7 +362,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
+ if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
+ break;
+ if (err) {
+- printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
++ printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __func__);
+ av7110->arm_errors++;
+ return -ETIMEDOUT;
+ }
+@@ -379,7 +379,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
+ if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
+ break;
+ if (err) {
+- printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
++ printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __func__);
+ return -ETIMEDOUT;
+ }
+ msleep(1);
+@@ -419,14 +419,14 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
+ stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
+ if (stat & flags[0]) {
+ printk(KERN_ERR "%s: %s QUEUE overflow\n",
+- __FUNCTION__, type);
++ __func__, type);
+ return -1;
+ }
+ if ((stat & flags[1]) == 0)
+ break;
+ if (err) {
+ printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
+- __FUNCTION__, type);
++ __func__, type);
+ return -ETIMEDOUT;
+ }
+ msleep(1);
+@@ -454,7 +454,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
+ break;
+ if (err) {
+ printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
+- __FUNCTION__, (buf[0] >> 8) & 0xff);
++ __func__, (buf[0] >> 8) & 0xff);
+ return -ETIMEDOUT;
+ }
+ msleep(1);
+@@ -462,11 +462,11 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
+
+ stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
+ if (stat & GPMQOver) {
+- printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __FUNCTION__);
++ printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __func__);
+ return -ENOSPC;
+ }
+ else if (stat & OSDQOver) {
+- printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __FUNCTION__);
++ printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __func__);
+ return -ENOSPC;
+ }
+ #endif
+@@ -491,7 +491,7 @@ static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
+ mutex_unlock(&av7110->dcomlock);
+ if (ret && ret!=-ERESTARTSYS)
+ printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
+- __FUNCTION__, ret);
++ __func__, ret);
+ return ret;
+ }
+
+@@ -575,7 +575,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
+ if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
+ break;
+ if (err) {
+- printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__);
++ printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __func__);
+ mutex_unlock(&av7110->dcomlock);
+ return -ETIMEDOUT;
+ }
+@@ -591,7 +591,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
+ if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
+ break;
+ if (err) {
+- printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
++ printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __func__);
+ mutex_unlock(&av7110->dcomlock);
+ return -ETIMEDOUT;
+ }
+@@ -602,12 +602,12 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
+ #ifdef COM_DEBUG
+ stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
+ if (stat & GPMQOver) {
+- printk(KERN_ERR "%s: GPMQOver\n", __FUNCTION__);
++ printk(KERN_ERR "%s: GPMQOver\n", __func__);
+ mutex_unlock(&av7110->dcomlock);
+ return -1;
+ }
+ else if (stat & OSDQOver) {
+- printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__);
++ printk(KERN_ERR "%s: OSDQOver\n", __func__);
+ mutex_unlock(&av7110->dcomlock);
+ return -1;
+ }
+@@ -741,7 +741,7 @@ static int FlushText(struct av7110 *av7110)
+ break;
+ if (err) {
+ printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
+- __FUNCTION__);
++ __func__);
+ mutex_unlock(&av7110->dcomlock);
+ return -ETIMEDOUT;
+ }
+@@ -768,7 +768,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, char *buf)
+ break;
+ if (ret) {
+ printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
+- __FUNCTION__);
++ __func__);
+ mutex_unlock(&av7110->dcomlock);
+ return -ETIMEDOUT;
+ }
+@@ -782,7 +782,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, char *buf)
+ break;
+ if (ret) {
+ printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
+- __FUNCTION__);
++ __func__);
+ mutex_unlock(&av7110->dcomlock);
+ return -ETIMEDOUT;
+ }
+diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
+index a283e1d..23a1c63 100644
+--- a/drivers/media/dvb/ttpci/av7110_ir.c
++++ b/drivers/media/dvb/ttpci/av7110_ir.c
+@@ -133,7 +133,7 @@ static void av7110_emit_key(unsigned long parm)
+ break;
+
+ default:
+- printk("%s invalid protocol %x\n", __FUNCTION__, ir->protocol);
++ printk("%s invalid protocol %x\n", __func__, ir->protocol);
+ return;
+ }
+
+@@ -143,7 +143,7 @@ static void av7110_emit_key(unsigned long parm)
+ keycode = ir->key_map[data];
+
+ dprintk(16, "%s: code %08x -> addr %i data 0x%02x -> keycode %i\n",
+- __FUNCTION__, ircom, addr, data, keycode);
++ __func__, ircom, addr, data, keycode);
+
+ /* check device address */
+ if (!(ir->device_mask & (1 << addr)))
+@@ -151,7 +151,7 @@ static void av7110_emit_key(unsigned long parm)
+
+ if (!keycode) {
+ printk ("%s: code %08x -> addr %i data 0x%02x -> unknown key!\n",
+- __FUNCTION__, ircom, addr, data);
++ __func__, ircom, addr, data);
+ return;
+ }
+
+diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
+index e2f066f..b4a0cc5 100644
+--- a/drivers/media/dvb/ttpci/av7110_v4l.c
++++ b/drivers/media/dvb/ttpci/av7110_v4l.c
+@@ -573,7 +573,7 @@ static int av7110_vbi_reset(struct inode *inode, struct file *file)
+ struct saa7146_dev *dev = fh->dev;
+ struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
+
+- dprintk(2, "%s\n", __FUNCTION__);
++ dprintk(2, "%s\n", __func__);
+ av7110->wssMode = 0;
+ av7110->wssData = 0;
+ if (FW_VERSION(av7110->arm_app) < 0x2623)
+@@ -590,7 +590,7 @@ static ssize_t av7110_vbi_write(struct file *file, const char __user *data, size
+ struct v4l2_sliced_vbi_data d;
+ int rc;
+
+- dprintk(2, "%s\n", __FUNCTION__);
++ dprintk(2, "%s\n", __func__);
+ if (FW_VERSION(av7110->arm_app) < 0x2623 || !av7110->wssMode || count != sizeof d)
+ return -EINVAL;
+ if (copy_from_user(&d, data, count))
+diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
+index 2d64d55..b30a528 100644
+--- a/drivers/media/dvb/ttpci/budget-av.c
++++ b/drivers/media/dvb/ttpci/budget-av.c
+@@ -178,7 +178,7 @@ static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 addre
+ udelay(1);
+
+ result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
+- if ((result == -ETIMEDOUT) || ((result == 0xff) && ((address & 3) < 2))) {
++ if (result == -ETIMEDOUT) {
+ ciintf_slot_shutdown(ca, slot);
+ printk(KERN_INFO "budget-av: cam ejected 3\n");
+ return -ETIMEDOUT;
+@@ -577,7 +577,7 @@ static struct stv0299_config typhoon_config = {
+ .mclk = 88000000UL,
+ .invert = 0,
+ .skip_reinit = 0,
+- .lock_output = STV0229_LOCKOUTPUT_1,
++ .lock_output = STV0299_LOCKOUTPUT_1,
+ .volt13_op0_op1 = STV0299_VOLT13_OP0,
+ .min_delay_ms = 100,
+ .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
+@@ -590,7 +590,7 @@ static struct stv0299_config cinergy_1200s_config = {
+ .mclk = 88000000UL,
+ .invert = 0,
+ .skip_reinit = 0,
+- .lock_output = STV0229_LOCKOUTPUT_0,
++ .lock_output = STV0299_LOCKOUTPUT_0,
+ .volt13_op0_op1 = STV0299_VOLT13_OP0,
+ .min_delay_ms = 100,
+ .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
+@@ -602,7 +602,7 @@ static struct stv0299_config cinergy_1200s_1894_0010_config = {
+ .mclk = 88000000UL,
+ .invert = 1,
+ .skip_reinit = 0,
+- .lock_output = STV0229_LOCKOUTPUT_1,
++ .lock_output = STV0299_LOCKOUTPUT_1,
+ .volt13_op0_op1 = STV0299_VOLT13_OP0,
+ .min_delay_ms = 100,
+ .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
+@@ -869,7 +869,7 @@ static struct stv0299_config philips_sd1878_config = {
+ .mclk = 88000000UL,
+ .invert = 0,
+ .skip_reinit = 0,
+- .lock_output = STV0229_LOCKOUTPUT_1,
++ .lock_output = STV0299_LOCKOUTPUT_1,
+ .volt13_op0_op1 = STV0299_VOLT13_OP0,
+ .min_delay_ms = 100,
+ .set_symbol_rate = philips_sd1878_ci_set_symbol_rate,
+@@ -941,6 +941,12 @@ static void frontend_init(struct budget_av *budget_av)
+ switch (saa->pci->subsystem_device) {
+
+ case SUBID_DVBS_KNC1:
++ /*
++ * maybe that setting is needed for other dvb-s cards as well,
++ * but so far it has been only confirmed for this type
++ */
++ budget_av->reinitialise_demod = 1;
++ /* fall through */
+ case SUBID_DVBS_KNC1_PLUS:
+ case SUBID_DVBS_EASYWATCH_1:
+ if (saa->pci->subsystem_vendor == 0x1894) {
+diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
+index 5093492..6530323 100644
+--- a/drivers/media/dvb/ttpci/budget-ci.c
++++ b/drivers/media/dvb/ttpci/budget-ci.c
+@@ -86,7 +86,7 @@ static int rc5_device = -1;
+ module_param(rc5_device, int, 0644);
+ MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)");
+
+-static int ir_debug = 0;
++static int ir_debug;
+ module_param(ir_debug, int, 0644);
+ MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
+
+@@ -728,7 +728,7 @@ static struct stv0299_config philips_su1278_tt_config = {
+ .mclk = 64000000UL,
+ .invert = 0,
+ .skip_reinit = 1,
+- .lock_output = STV0229_LOCKOUTPUT_1,
++ .lock_output = STV0299_LOCKOUTPUT_1,
+ .volt13_op0_op1 = STV0299_VOLT13_OP1,
+ .min_delay_ms = 50,
+ .set_symbol_rate = philips_su1278_tt_set_symbol_rate,
+@@ -1121,7 +1121,7 @@ static void frontend_init(struct budget_ci *budget_ci)
+
+ budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
+ if (dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0) == NULL) {
+- printk("%s: No LNBP21 found!\n", __FUNCTION__);
++ printk("%s: No LNBP21 found!\n", __func__);
+ dvb_frontend_detach(budget_ci->budget.dvb_frontend);
+ budget_ci->budget.dvb_frontend = NULL;
+ }
+diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
+index 0252081..18cac4b 100644
+--- a/drivers/media/dvb/ttpci/budget-core.c
++++ b/drivers/media/dvb/ttpci/budget-core.c
+@@ -57,6 +57,8 @@ module_param_named(bufsize, dma_buffer_size, int, 0444);
+ MODULE_PARM_DESC(debug, "Turn on/off budget debugging (default:off).");
+ MODULE_PARM_DESC(bufsize, "DMA buffer size in KB, default: 188, min: 188, max: 1410 (Activy: 564)");
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ /****************************************************************************
+ * TT budget / WinTV Nova
+ ****************************************************************************/
+@@ -223,7 +225,7 @@ static void vpeirq(unsigned long data)
+
+ if (budget->buffer_warnings && time_after(jiffies, budget->buffer_warning_time)) {
+ printk("%s %s: used %d times >80%% of buffer (%u bytes now)\n",
+- budget->dev->name, __FUNCTION__, budget->buffer_warnings, count);
++ budget->dev->name, __func__, budget->buffer_warnings, count);
+ budget->buffer_warning_time = jiffies + BUFFER_WARNING_WAIT;
+ budget->buffer_warnings = 0;
+ }
+@@ -471,9 +473,10 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
+ budget->buffer_width, budget->buffer_height);
+ printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size);
+
+- if ((ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner, &budget->dev->pci->dev)) < 0) {
++ ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name,
++ owner, &budget->dev->pci->dev, adapter_nr);
++ if (ret < 0)
+ return ret;
+- }
+
+ /* set dd1 stream a & b */
+ saa7146_write(dev, DD1_STREAM_B, 0x00000000);
+diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
+index 14b00f5..2293d80 100644
+--- a/drivers/media/dvb/ttpci/budget.c
++++ b/drivers/media/dvb/ttpci/budget.c
+@@ -45,6 +45,7 @@
+ #include "tda826x.h"
+ #include "lnbp21.h"
+ #include "bsru6.h"
++#include "bsbe1.h"
+
+ static int diseqc_method;
+ module_param(diseqc_method, int, 0444);
+@@ -257,11 +258,17 @@ static struct ves1820_config alps_tdbe2_config = {
+
+ static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+ {
+- struct budget* budget = (struct budget*) fe->dvb->priv;
++ struct budget *budget = fe->dvb->priv;
++ u8 *tuner_addr = fe->tuner_priv;
+ u32 div;
+ u8 cfg, cpump, band_select;
+ u8 data[4];
+- struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
++ struct i2c_msg msg = { .flags = 0, .buf = data, .len = sizeof(data) };
++
++ if (tuner_addr)
++ msg.addr = *tuner_addr;
++ else
++ msg.addr = 0x61;
+
+ div = (36125000 + params->frequency) / 166666;
+
+@@ -292,6 +299,12 @@ static struct l64781_config grundig_29504_401_config = {
+ .demod_address = 0x55,
+ };
+
++static struct l64781_config grundig_29504_401_config_activy = {
++ .demod_address = 0x54,
++};
++
++static u8 tuner_address_grundig_29504_401_activy = 0x60;
++
+ static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+ {
+ struct budget* budget = (struct budget*) fe->dvb->priv;
+@@ -346,14 +359,48 @@ static int s5h1420_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend
+ static struct s5h1420_config s5h1420_config = {
+ .demod_address = 0x53,
+ .invert = 1,
++ .cdclk_polarity = 1,
+ };
+
+ static struct tda10086_config tda10086_config = {
+ .demod_address = 0x0e,
+ .invert = 0,
+ .diseqc_tone = 1,
++ .xtal_freq = TDA10086_XTAL_16M,
+ };
+
++static struct stv0299_config alps_bsru6_config_activy = {
++ .demod_address = 0x68,
++ .inittab = alps_bsru6_inittab,
++ .mclk = 88000000UL,
++ .invert = 1,
++ .op0_off = 1,
++ .min_delay_ms = 100,
++ .set_symbol_rate = alps_bsru6_set_symbol_rate,
++};
++
++static struct stv0299_config alps_bsbe1_config_activy = {
++ .demod_address = 0x68,
++ .inittab = alps_bsbe1_inittab,
++ .mclk = 88000000UL,
++ .invert = 1,
++ .op0_off = 1,
++ .min_delay_ms = 100,
++ .set_symbol_rate = alps_bsbe1_set_symbol_rate,
++};
++
++
++static int i2c_readreg(struct i2c_adapter *i2c, u8 adr, u8 reg)
++{
++ u8 val;
++ struct i2c_msg msg[] = {
++ { .addr = adr, .flags = 0, .buf = ®, .len = 1 },
++ { .addr = adr, .flags = I2C_M_RD, .buf = &val, .len = 1 }
++ };
++
++ return (i2c_transfer(i2c, msg, 2) != 2) ? -EIO : val;
++}
++
+ static u8 read_pwm(struct budget* budget)
+ {
+ u8 b = 0xff;
+@@ -369,6 +416,8 @@ static u8 read_pwm(struct budget* budget)
+
+ static void frontend_init(struct budget *budget)
+ {
++ (void)alps_bsbe1_config; /* avoid warning */
++
+ switch(budget->dev->pci->subsystem_device) {
+ case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659))
+ case 0x1013:
+@@ -414,15 +463,43 @@ static void frontend_init(struct budget *budget)
+ }
+ break;
+
+- case 0x4f60: // Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/ALPS BSRU6(tsa5059))
+- budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap);
+- if (budget->dvb_frontend) {
+- budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
+- budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
+- budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
+- budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
++ case 0x4f60: /* Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/tsa5059) */
++ {
++ int subtype = i2c_readreg(&budget->i2c_adap, 0x50, 0x67);
++
++ if (subtype < 0)
++ break;
++ /* fixme: find a better way to identify the card */
++ if (subtype < 0x36) {
++ /* assume ALPS BSRU6 */
++ budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config_activy, &budget->i2c_adap);
++ if (budget->dvb_frontend) {
++ printk(KERN_INFO "budget: tuner ALPS BSRU6 detected\n");
++ budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
++ budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
++ budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
++ budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
++ break;
++ }
++ } else {
++ /* assume ALPS BSBE1 */
++ /* reset tuner */
++ saa7146_setgpio(budget->dev, 3, SAA7146_GPIO_OUTLO);
++ msleep(50);
++ saa7146_setgpio(budget->dev, 3, SAA7146_GPIO_OUTHI);
++ msleep(250);
++ budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config_activy, &budget->i2c_adap);
++ if (budget->dvb_frontend) {
++ printk(KERN_INFO "budget: tuner ALPS BSBE1 detected\n");
++ budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
++ budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
++ budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
++ budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
++ break;
++ }
+ }
+ break;
++ }
+
+ case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522))
+ budget->dvb_frontend = dvb_attach(tda8083_attach, &grundig_29504_451_config, &budget->i2c_adap);
+@@ -433,12 +510,20 @@ static void frontend_init(struct budget *budget)
+ }
+ break;
+
++ case 0x5f61: /* Fujitsu Siemens Activy Budget-T PCI rev GR (L64781/Grundig 29504-401(tsa5060)) */
++ budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config_activy, &budget->i2c_adap);
++ if (budget->dvb_frontend) {
++ budget->dvb_frontend->tuner_priv = &tuner_address_grundig_29504_401_activy;
++ budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
++ }
++ break;
++
+ case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260))
+ budget->dvb_frontend = dvb_attach(s5h1420_attach, &s5h1420_config, &budget->i2c_adap);
+ if (budget->dvb_frontend) {
+ budget->dvb_frontend->ops.tuner_ops.set_params = s5h1420_tuner_set_params;
+ if (dvb_attach(lnbp21_attach, budget->dvb_frontend, &budget->i2c_adap, 0, 0) == NULL) {
+- printk("%s: No LNBP21 found!\n", __FUNCTION__);
++ printk("%s: No LNBP21 found!\n", __func__);
+ goto error_out;
+ }
+ break;
+@@ -454,9 +539,9 @@ static void frontend_init(struct budget *budget)
+ budget->dvb_frontend = dvb_attach(tda10086_attach, &tda10086_config, &budget->i2c_adap);
+ if (budget->dvb_frontend) {
+ if (dvb_attach(tda826x_attach, budget->dvb_frontend, 0x60, &budget->i2c_adap, 0) == NULL)
+- printk("%s: No tda826x found!\n", __FUNCTION__);
++ printk("%s: No tda826x found!\n", __func__);
+ if (dvb_attach(lnbp21_attach, budget->dvb_frontend, &budget->i2c_adap, 0, 0) == NULL) {
+- printk("%s: No LNBP21 found!\n", __FUNCTION__);
++ printk("%s: No LNBP21 found!\n", __func__);
+ goto error_out;
+ }
+ break;
+@@ -537,6 +622,7 @@ MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC);
+ MAKE_BUDGET_INFO(ttbs1401, "TT-Budget-S-1401 PCI", BUDGET_TT);
+ MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY);
+ MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY);
++MAKE_BUDGET_INFO(fsact, "Fujitsu Siemens Activy Budget-T PCI (rev GR/Grundig frontend)", BUDGET_FS_ACTIVY);
+
+ static struct pci_device_id pci_tbl[] = {
+ MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003),
+@@ -547,6 +633,7 @@ static struct pci_device_id pci_tbl[] = {
+ MAKE_EXTENSION_PCI(ttbs1401, 0x13c2, 0x1018),
+ MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60),
+ MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61),
++ MAKE_EXTENSION_PCI(fsact, 0x1131, 0x5f61),
+ {
+ .vendor = 0,
+ }
+diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h
+index d764ffa..dd450b7 100644
+--- a/drivers/media/dvb/ttpci/budget.h
++++ b/drivers/media/dvb/ttpci/budget.h
+@@ -1,3 +1,4 @@
++
+ #ifndef __BUDGET_DVB__
+ #define __BUDGET_DVB__
+
+@@ -21,7 +22,7 @@ extern int budget_debug;
+ #endif
+
+ #define dprintk(level,args...) \
+- do { if ((budget_debug & level)) { printk("%s: %s(): ", KBUILD_MODNAME, __FUNCTION__); printk(args); } } while (0)
++ do { if ((budget_debug & level)) { printk("%s: %s(): ", KBUILD_MODNAME, __func__); printk(args); } } while (0)
+
+ struct budget_info {
+ char *name;
+diff --git a/drivers/media/dvb/ttpci/ttpci-eeprom.c b/drivers/media/dvb/ttpci/ttpci-eeprom.c
+index 1f31e91..7dd54b3 100644
+--- a/drivers/media/dvb/ttpci/ttpci-eeprom.c
++++ b/drivers/media/dvb/ttpci/ttpci-eeprom.c
+@@ -95,7 +95,7 @@ static int ttpci_eeprom_read_encodedMAC(struct i2c_adapter *adapter, u8 * encode
+ { .addr = 0x50, .flags = I2C_M_RD, .buf = encodedMAC, .len = 20 }
+ };
+
+- /* dprintk("%s\n", __FUNCTION__); */
++ /* dprintk("%s\n", __func__); */
+
+ ret = i2c_transfer(adapter, msg, 2);
+
+diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+index 7902ae1..732ce4d 100644
+--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
++++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+@@ -56,10 +56,11 @@
+ */
+
+ static int debug;
+-
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define dprintk(x...) do { if (debug) printk(KERN_DEBUG x); } while (0)
+
+ #define ISO_BUF_COUNT 4
+@@ -153,12 +154,12 @@ static int ttusb_cmd(struct ttusb *ttusb,
+ (u8 *) data, len, &actual_len, 1000);
+ if (err != 0) {
+ dprintk("%s: usb_bulk_msg(send) failed, err == %i!\n",
+- __FUNCTION__, err);
++ __func__, err);
+ mutex_unlock(&ttusb->semusb);
+ return err;
+ }
+ if (actual_len != len) {
+- dprintk("%s: only wrote %d of %d bytes\n", __FUNCTION__,
++ dprintk("%s: only wrote %d of %d bytes\n", __func__,
+ actual_len, len);
+ mutex_unlock(&ttusb->semusb);
+ return -1;
+@@ -168,7 +169,7 @@ static int ttusb_cmd(struct ttusb *ttusb,
+ ttusb->last_result, 32, &actual_len, 1000);
+
+ if (err != 0) {
+- printk("%s: failed, receive error %d\n", __FUNCTION__,
++ printk("%s: failed, receive error %d\n", __func__,
+ err);
+ mutex_unlock(&ttusb->semusb);
+ return err;
+@@ -229,7 +230,7 @@ static int ttusb_i2c_msg(struct ttusb *ttusb,
+ if (err || b[0] != 0x55 || b[1] != id) {
+ dprintk
+ ("%s: usb_bulk_msg(recv) failed, err == %i, id == %02x, b == ",
+- __FUNCTION__, err, id);
++ __func__, err, id);
+ return -EREMOTEIO;
+ }
+
+@@ -273,7 +274,7 @@ static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num
+ snd_buf, snd_len, rcv_buf, rcv_len);
+
+ if (err < rcv_len) {
+- dprintk("%s: i == %i\n", __FUNCTION__, i);
++ dprintk("%s: i == %i\n", __func__, i);
+ break;
+ }
+
+@@ -327,7 +328,7 @@ static int ttusb_boot_dsp(struct ttusb *ttusb)
+ done:
+ if (err) {
+ dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
+- __FUNCTION__, err);
++ __func__, err);
+ }
+
+ return err;
+@@ -427,7 +428,7 @@ static int ttusb_init_controller(struct ttusb *ttusb)
+ if ((err = ttusb_result(ttusb, get_version, sizeof(get_version))))
+ return err;
+
+- dprintk("%s: stc-version: %c%c%c%c%c\n", __FUNCTION__,
++ dprintk("%s: stc-version: %c%c%c%c%c\n", __func__,
+ get_version[4], get_version[5], get_version[6],
+ get_version[7], get_version[8]);
+
+@@ -437,7 +438,7 @@ static int ttusb_init_controller(struct ttusb *ttusb)
+ memcmp(get_version + 4, "V 2.2", 5)) {
+ printk
+ ("%s: unknown STC version %c%c%c%c%c, please report!\n",
+- __FUNCTION__, get_version[4], get_version[5],
++ __func__, get_version[4], get_version[5],
+ get_version[6], get_version[7], get_version[8]);
+ }
+
+@@ -453,7 +454,7 @@ static int ttusb_init_controller(struct ttusb *ttusb)
+ ttusb_result(ttusb, get_dsp_version, sizeof(get_dsp_version));
+ if (err)
+ return err;
+- printk("%s: dsp-version: %c%c%c\n", __FUNCTION__,
++ printk("%s: dsp-version: %c%c%c\n", __func__,
+ get_dsp_version[4], get_dsp_version[5], get_dsp_version[6]);
+ return 0;
+ }
+@@ -476,7 +477,7 @@ static int ttusb_send_diseqc(struct dvb_frontend* fe,
+ /* Diseqc */
+ if ((err = ttusb_cmd(ttusb, b, 4 + b[3], 0))) {
+ dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
+- __FUNCTION__, err);
++ __func__, err);
+ }
+
+ return err;
+@@ -494,7 +495,7 @@ static int ttusb_update_lnb(struct ttusb *ttusb)
+ /* SetLNB */
+ if ((err = ttusb_cmd(ttusb, b, sizeof(b), 0))) {
+ dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
+- __FUNCTION__, err);
++ __func__, err);
+ }
+
+ return err;
+@@ -528,7 +529,7 @@ static void ttusb_set_led_freq(struct ttusb *ttusb, u8 freq)
+ err = ttusb_cmd(ttusb, b, sizeof(b), 0);
+ if (err) {
+ dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
+- __FUNCTION__, err);
++ __func__, err);
+ }
+ }
+ #endif
+@@ -542,7 +543,7 @@ static void ttusb_handle_sec_data(struct ttusb_channel *channel,
+ const u8 * data, int len);
+ #endif
+
+-static int numpkt = 0, numts, numstuff, numsec, numinvalid;
++static int numpkt, numts, numstuff, numsec, numinvalid;
+ static unsigned long lastj;
+
+ static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack,
+@@ -554,7 +555,7 @@ static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack,
+ csum ^= le16_to_cpup((u16 *) (muxpack + i));
+ if (csum) {
+ printk("%s: muxpack with incorrect checksum, ignoring\n",
+- __FUNCTION__);
++ __func__);
+ numinvalid++;
+ return;
+ }
+@@ -563,7 +564,7 @@ static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack,
+ cc &= 0x7FFF;
+ if ((cc != ttusb->cc) && (ttusb->cc != -1))
+ printk("%s: cc discontinuity (%d frames missing)\n",
+- __FUNCTION__, (cc - ttusb->cc) & 0x7FFF);
++ __func__, (cc - ttusb->cc) & 0x7FFF);
+ ttusb->cc = (cc + 1) & 0x7FFF;
+ if (muxpack[0] & 0x80) {
+ #ifdef TTUSB_HWSECTIONS
+@@ -613,7 +614,7 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len)
+ int maxwork = 1024;
+ while (len) {
+ if (!(maxwork--)) {
+- printk("%s: too much work\n", __FUNCTION__);
++ printk("%s: too much work\n", __func__);
+ break;
+ }
+
+@@ -632,7 +633,7 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len)
+ #else
+ if (ttusb->insync) {
+ printk("%s: lost sync.\n",
+- __FUNCTION__);
++ __func__);
+ ttusb->insync = 0;
+ }
+ #endif
+@@ -691,7 +692,7 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len)
+ else {
+ dprintk
+ ("%s: invalid state: first byte is %x\n",
+- __FUNCTION__,
++ __func__,
+ ttusb->muxpack[0]);
+ ttusb->mux_state = 0;
+ }
+@@ -740,7 +741,7 @@ static void ttusb_iso_irq(struct urb *urb)
+
+ #if 0
+ printk("%s: status %d, errcount == %d, length == %i\n",
+- __FUNCTION__,
++ __func__,
+ urb->status, urb->error_count, urb->actual_length);
+ #endif
+
+@@ -833,7 +834,7 @@ static int ttusb_start_iso_xfer(struct ttusb *ttusb)
+ int i, j, err, buffer_offset = 0;
+
+ if (ttusb->iso_streaming) {
+- printk("%s: iso xfer already running!\n", __FUNCTION__);
++ printk("%s: iso xfer already running!\n", __func__);
+ return 0;
+ }
+
+@@ -869,7 +870,7 @@ static int ttusb_start_iso_xfer(struct ttusb *ttusb)
+ ttusb_stop_iso_xfer(ttusb);
+ printk
+ ("%s: failed urb submission (%i: err = %i)!\n",
+- __FUNCTION__, i, err);
++ __func__, i, err);
+ return err;
+ }
+ }
+@@ -1005,7 +1006,7 @@ static int stc_release(struct inode *inode, struct file *file)
+ return 0;
+ }
+
+-static struct file_operations stc_fops = {
++static const struct file_operations stc_fops = {
+ .owner = THIS_MODULE,
+ .read = stc_read,
+ .open = stc_open,
+@@ -1313,7 +1314,7 @@ static struct stv0299_config alps_stv0299_config = {
+ .mclk = 88000000UL,
+ .invert = 1,
+ .skip_reinit = 0,
+- .lock_output = STV0229_LOCKOUTPUT_1,
++ .lock_output = STV0299_LOCKOUTPUT_1,
+ .volt13_op0_op1 = STV0299_VOLT13_OP1,
+ .min_delay_ms = 100,
+ .set_symbol_rate = alps_stv0299_set_symbol_rate,
+@@ -1643,7 +1644,7 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
+ struct ttusb *ttusb;
+ int result;
+
+- dprintk("%s: TTUSB DVB connected\n", __FUNCTION__);
++ dprintk("%s: TTUSB DVB connected\n", __func__);
+
+ udev = interface_to_usbdev(intf);
+
+@@ -1669,7 +1670,10 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
+
+ mutex_unlock(&ttusb->semi2c);
+
+- if ((result = dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE, &udev->dev)) < 0) {
++ result = dvb_register_adapter(&ttusb->adapter,
++ "Technotrend/Hauppauge Nova-USB",
++ THIS_MODULE, &udev->dev, adapter_nr);
++ if (result < 0) {
+ ttusb_free_iso_urbs(ttusb);
+ kfree(ttusb);
+ return result;
+@@ -1773,7 +1777,7 @@ static void ttusb_disconnect(struct usb_interface *intf)
+
+ kfree(ttusb);
+
+- dprintk("%s: TTUSB DVB disconnected\n", __FUNCTION__);
++ dprintk("%s: TTUSB DVB disconnected\n", __func__);
+ }
+
+ static struct usb_device_id ttusb_table[] = {
+diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+index 1ec981d..42eee04 100644
+--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
++++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+@@ -52,6 +52,8 @@ MODULE_PARM_DESC(output_pva, "Output PVA from dvr device (default:off)");
+ module_param(enable_rc, int, 0644);
+ MODULE_PARM_DESC(enable_rc, "Turn on/off IR remote control(default: off)");
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define dprintk if (debug) printk
+
+ #define DRIVER_NAME "TechnoTrend/Hauppauge DEC USB"
+@@ -217,11 +219,11 @@ static void ttusb_dec_handle_irq( struct urb *urb)
+ case -ETIME:
+ /* this urb is dead, cleanup */
+ dprintk("%s:urb shutting down with status: %d\n",
+- __FUNCTION__, urb->status);
++ __func__, urb->status);
+ return;
+ default:
+ dprintk("%s:nonzero status received: %d\n",
+- __FUNCTION__,urb->status);
++ __func__,urb->status);
+ goto exit;
+ }
+
+@@ -235,7 +237,7 @@ static void ttusb_dec_handle_irq( struct urb *urb)
+ * keyrepeat signal is recieved for lets say 200ms.
+ * this should/could be added later ...
+ * for now lets report each signal as a key down and up*/
+- dprintk("%s:rc signal:%d\n", __FUNCTION__, buffer[4]);
++ dprintk("%s:rc signal:%d\n", __func__, buffer[4]);
+ input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 1);
+ input_sync(dec->rc_input_dev);
+ input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 0);
+@@ -245,7 +247,7 @@ static void ttusb_dec_handle_irq( struct urb *urb)
+ exit: retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if(retval)
+ printk("%s - usb_commit_urb failed with result: %d\n",
+- __FUNCTION__, retval);
++ __func__, retval);
+ }
+
+ static u16 crc16(u16 crc, const u8 *buf, size_t len)
+@@ -268,7 +270,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
+ int result, actual_len, i;
+ u8 *b;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ b = kmalloc(COMMAND_PACKET_SIZE + 4, GFP_KERNEL);
+ if (!b)
+@@ -276,7 +278,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
+
+ if ((result = mutex_lock_interruptible(&dec->usb_mutex))) {
+ kfree(b);
+- printk("%s: Failed to lock usb mutex.\n", __FUNCTION__);
++ printk("%s: Failed to lock usb mutex.\n", __func__);
+ return result;
+ }
+
+@@ -289,7 +291,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
+ memcpy(&b[4], params, param_length);
+
+ if (debug) {
+- printk("%s: command: ", __FUNCTION__);
++ printk("%s: command: ", __func__);
+ for (i = 0; i < param_length + 4; i++)
+ printk("0x%02X ", b[i]);
+ printk("\n");
+@@ -300,7 +302,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
+
+ if (result) {
+ printk("%s: command bulk message failed: error %d\n",
+- __FUNCTION__, result);
++ __func__, result);
+ mutex_unlock(&dec->usb_mutex);
+ kfree(b);
+ return result;
+@@ -311,13 +313,13 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
+
+ if (result) {
+ printk("%s: result bulk message failed: error %d\n",
+- __FUNCTION__, result);
++ __func__, result);
+ mutex_unlock(&dec->usb_mutex);
+ kfree(b);
+ return result;
+ } else {
+ if (debug) {
+- printk("%s: result: ", __FUNCTION__);
++ printk("%s: result: ", __func__);
+ for (i = 0; i < actual_len; i++)
+ printk("0x%02X ", b[i]);
+ printk("\n");
+@@ -343,7 +345,7 @@ static int ttusb_dec_get_stb_state (struct ttusb_dec *dec, unsigned int *mode,
+ int result;
+ unsigned int tmp;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ result = ttusb_dec_send_command(dec, 0x08, 0, NULL, &c_length, c);
+ if (result)
+@@ -400,7 +402,7 @@ static void ttusb_dec_set_pids(struct ttusb_dec *dec)
+ u16 audio = htons(dec->pid[DMX_PES_AUDIO]);
+ u16 video = htons(dec->pid[DMX_PES_VIDEO]);
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ memcpy(&b[0], &pcr, 2);
+ memcpy(&b[2], &audio, 2);
+@@ -419,12 +421,12 @@ static void ttusb_dec_set_pids(struct ttusb_dec *dec)
+ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
+ {
+ if (length < 8) {
+- printk("%s: packet too short - discarding\n", __FUNCTION__);
++ printk("%s: packet too short - discarding\n", __func__);
+ return;
+ }
+
+ if (length > 8 + MAX_PVA_LENGTH) {
+- printk("%s: packet too long - discarding\n", __FUNCTION__);
++ printk("%s: packet too long - discarding\n", __func__);
+ return;
+ }
+
+@@ -507,7 +509,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
+ break;
+
+ default:
+- printk("%s: unknown PVA type: %02x.\n", __FUNCTION__,
++ printk("%s: unknown PVA type: %02x.\n", __func__,
+ pva[2]);
+ break;
+ }
+@@ -546,7 +548,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec)
+ u16 packet_id;
+
+ if (dec->packet_length % 2) {
+- printk("%s: odd sized packet - discarding\n", __FUNCTION__);
++ printk("%s: odd sized packet - discarding\n", __func__);
+ return;
+ }
+
+@@ -554,7 +556,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec)
+ csum ^= ((dec->packet[i] << 8) + dec->packet[i + 1]);
+
+ if (csum) {
+- printk("%s: checksum failed - discarding\n", __FUNCTION__);
++ printk("%s: checksum failed - discarding\n", __func__);
+ return;
+ }
+
+@@ -563,7 +565,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec)
+
+ if ((packet_id != dec->next_packet_id) && dec->next_packet_id) {
+ printk("%s: warning: lost packets between %u and %u\n",
+- __FUNCTION__, dec->next_packet_id - 1, packet_id);
++ __func__, dec->next_packet_id - 1, packet_id);
+ }
+
+ if (packet_id == 0xffff)
+@@ -652,7 +654,7 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b,
+ dec->packet_state = 7;
+ } else {
+ printk("%s: unknown packet type: "
+- "%02x%02x\n", __FUNCTION__,
++ "%02x%02x\n", __func__,
+ dec->packet[0], dec->packet[1]);
+ dec->packet_state = 0;
+ }
+@@ -724,7 +726,7 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b,
+
+ default:
+ printk("%s: illegal packet state encountered.\n",
+- __FUNCTION__);
++ __func__);
+ dec->packet_state = 0;
+ }
+ }
+@@ -792,7 +794,7 @@ static void ttusb_dec_process_urb(struct urb *urb)
+ } else {
+ /* -ENOENT is expected when unlinking urbs */
+ if (urb->status != -ENOENT)
+- dprintk("%s: urb error: %d\n", __FUNCTION__,
++ dprintk("%s: urb error: %d\n", __func__,
+ urb->status);
+ }
+
+@@ -804,7 +806,7 @@ static void ttusb_dec_setup_urbs(struct ttusb_dec *dec)
+ {
+ int i, j, buffer_offset = 0;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ for (i = 0; i < ISO_BUF_COUNT; i++) {
+ int frame_offset = 0;
+@@ -834,7 +836,7 @@ static void ttusb_dec_stop_iso_xfer(struct ttusb_dec *dec)
+ {
+ int i;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ if (mutex_lock_interruptible(&dec->iso_mutex))
+ return;
+@@ -889,7 +891,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
+ {
+ int i, result;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ if (mutex_lock_interruptible(&dec->iso_mutex))
+ return -EAGAIN;
+@@ -905,7 +907,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
+ if ((result = usb_submit_urb(dec->iso_urb[i],
+ GFP_ATOMIC))) {
+ printk("%s: failed urb submission %d: "
+- "error %d\n", __FUNCTION__, i, result);
++ "error %d\n", __func__, i, result);
+
+ while (i) {
+ usb_kill_urb(dec->iso_urb[i - 1]);
+@@ -932,7 +934,7 @@ static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
+ u8 b0[] = { 0x05 };
+ int result = 0;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ dprintk(" ts_type:");
+
+@@ -1012,7 +1014,7 @@ static int ttusb_dec_start_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
+ unsigned long flags;
+ u8 x = 1;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ pid = htons(dvbdmxfeed->pid);
+ memcpy(&b0[0], &pid, 2);
+@@ -1052,7 +1054,7 @@ static int ttusb_dec_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+ {
+ struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ if (!dvbdmx->dmx.frontend)
+ return -EINVAL;
+@@ -1113,7 +1115,7 @@ static int ttusb_dec_stop_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
+
+ static int ttusb_dec_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+ {
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ switch (dvbdmxfeed->type) {
+ case DMX_TYPE_TS:
+@@ -1132,7 +1134,7 @@ static void ttusb_dec_free_iso_urbs(struct ttusb_dec *dec)
+ {
+ int i;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ for (i = 0; i < ISO_BUF_COUNT; i++)
+ usb_free_urb(dec->iso_urb[i]);
+@@ -1147,7 +1149,7 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec)
+ {
+ int i;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ dec->iso_buffer = pci_alloc_consistent(NULL,
+ ISO_FRAME_SIZE *
+@@ -1214,7 +1216,7 @@ static int ttusb_init_rc( struct ttusb_dec *dec)
+
+ dec->rc_input_dev = input_dev;
+ if (usb_submit_urb(dec->irq_urb, GFP_KERNEL))
+- printk("%s: usb_submit_urb failed\n",__FUNCTION__);
++ printk("%s: usb_submit_urb failed\n",__func__);
+ /* enable irq pipe */
+ ttusb_dec_send_command(dec,0xb0,sizeof(b),b,NULL,NULL);
+
+@@ -1223,7 +1225,7 @@ static int ttusb_init_rc( struct ttusb_dec *dec)
+
+ static void ttusb_dec_init_v_pes(struct ttusb_dec *dec)
+ {
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ dec->v_pes[0] = 0x00;
+ dec->v_pes[1] = 0x00;
+@@ -1233,7 +1235,7 @@ static void ttusb_dec_init_v_pes(struct ttusb_dec *dec)
+
+ static int ttusb_dec_init_usb(struct ttusb_dec *dec)
+ {
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ mutex_init(&dec->usb_mutex);
+ mutex_init(&dec->iso_mutex);
+@@ -1281,11 +1283,11 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
+ u32 crc32_csum, crc32_check, tmp;
+ const struct firmware *fw_entry = NULL;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ if (request_firmware(&fw_entry, dec->firmware_name, &dec->udev->dev)) {
+ printk(KERN_ERR "%s: Firmware (%s) unavailable.\n",
+- __FUNCTION__, dec->firmware_name);
++ __func__, dec->firmware_name);
+ return 1;
+ }
+
+@@ -1294,7 +1296,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
+
+ if (firmware_size < 60) {
+ printk("%s: firmware size too small for DSP code (%zu < 60).\n",
+- __FUNCTION__, firmware_size);
++ __func__, firmware_size);
+ release_firmware(fw_entry);
+ return -1;
+ }
+@@ -1308,7 +1310,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
+ if (crc32_csum != crc32_check) {
+ printk("%s: crc32 check of DSP code failed (calculated "
+ "0x%08x != 0x%08x in file), file invalid.\n",
+- __FUNCTION__, crc32_csum, crc32_check);
++ __func__, crc32_csum, crc32_check);
+ release_firmware(fw_entry);
+ return -1;
+ }
+@@ -1376,7 +1378,7 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec)
+ int result;
+ unsigned int mode, model, version;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ result = ttusb_dec_get_stb_state(dec, &mode, &model, &version);
+
+@@ -1415,7 +1417,7 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec)
+ default:
+ printk(KERN_ERR "%s: unknown model returned "
+ "by firmware (%08x) - please report\n",
+- __FUNCTION__, model);
++ __func__, model);
+ return -1;
+ break;
+ }
+@@ -1434,12 +1436,14 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
+ {
+ int result;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ if ((result = dvb_register_adapter(&dec->adapter,
+- dec->model_name, THIS_MODULE, &dec->udev->dev)) < 0) {
++ dec->model_name, THIS_MODULE,
++ &dec->udev->dev,
++ adapter_nr)) < 0) {
+ printk("%s: dvb_register_adapter failed: error %d\n",
+- __FUNCTION__, result);
++ __func__, result);
+
+ return result;
+ }
+@@ -1454,7 +1458,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
+ dec->demux.write_to_decoder = NULL;
+
+ if ((result = dvb_dmx_init(&dec->demux)) < 0) {
+- printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
++ printk("%s: dvb_dmx_init failed: error %d\n", __func__,
+ result);
+
+ dvb_unregister_adapter(&dec->adapter);
+@@ -1468,7 +1472,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
+
+ if ((result = dvb_dmxdev_init(&dec->dmxdev, &dec->adapter)) < 0) {
+ printk("%s: dvb_dmxdev_init failed: error %d\n",
+- __FUNCTION__, result);
++ __func__, result);
+
+ dvb_dmx_release(&dec->demux);
+ dvb_unregister_adapter(&dec->adapter);
+@@ -1480,7 +1484,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
+
+ if ((result = dec->demux.dmx.add_frontend(&dec->demux.dmx,
+ &dec->frontend)) < 0) {
+- printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
++ printk("%s: dvb_dmx_init failed: error %d\n", __func__,
+ result);
+
+ dvb_dmxdev_release(&dec->dmxdev);
+@@ -1492,7 +1496,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
+
+ if ((result = dec->demux.dmx.connect_frontend(&dec->demux.dmx,
+ &dec->frontend)) < 0) {
+- printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
++ printk("%s: dvb_dmx_init failed: error %d\n", __func__,
+ result);
+
+ dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend);
+@@ -1510,7 +1514,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
+
+ static void ttusb_dec_exit_dvb(struct ttusb_dec *dec)
+ {
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ dvb_net_release(&dec->dvb_net);
+ dec->demux.dmx.close(&dec->demux.dmx);
+@@ -1528,7 +1532,7 @@ static void ttusb_dec_exit_dvb(struct ttusb_dec *dec)
+ static void ttusb_dec_exit_rc(struct ttusb_dec *dec)
+ {
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+ /* we have to check whether the irq URB is already submitted.
+ * As the irq is submitted after the interface is changed,
+ * this is the best method i figured out.
+@@ -1552,7 +1556,7 @@ static void ttusb_dec_exit_usb(struct ttusb_dec *dec)
+ {
+ int i;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ dec->iso_stream_count = 0;
+
+@@ -1612,12 +1616,12 @@ static int ttusb_dec_probe(struct usb_interface *intf,
+ struct usb_device *udev;
+ struct ttusb_dec *dec;
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ udev = interface_to_usbdev(intf);
+
+ if (!(dec = kzalloc(sizeof(struct ttusb_dec), GFP_KERNEL))) {
+- printk("%s: couldn't allocate memory.\n", __FUNCTION__);
++ printk("%s: couldn't allocate memory.\n", __func__);
+ return -ENOMEM;
+ }
+
+@@ -1692,7 +1696,7 @@ static void ttusb_dec_disconnect(struct usb_interface *intf)
+
+ usb_set_intfdata(intf, NULL);
+
+- dprintk("%s\n", __FUNCTION__);
++ dprintk("%s\n", __func__);
+
+ if (dec->active) {
+ ttusb_dec_exit_tasklet(dec);
+@@ -1749,7 +1753,7 @@ static int __init ttusb_dec_init(void)
+ int result;
+
+ if ((result = usb_register(&ttusb_dec_driver)) < 0) {
+- printk("%s: initialisation failed: error %d.\n", __FUNCTION__,
++ printk("%s: initialisation failed: error %d.\n", __func__,
+ result);
+ return result;
+ }
+diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
+index a6fb1d6..eb5eaec 100644
+--- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
++++ b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
+@@ -53,7 +53,7 @@ static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ return ret;
+
+ if(len != 4) {
+- printk(KERN_ERR "%s: unexpected reply\n", __FUNCTION__);
++ printk(KERN_ERR "%s: unexpected reply\n", __func__);
+ return -EIO;
+ }
+
+@@ -70,7 +70,7 @@ static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status)
+ break;
+ default:
+ pr_info("%s: returned unknown value: %d\n",
+- __FUNCTION__, result[3]);
++ __func__, result[3]);
+ return -EIO;
+ }
+
+diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c
+index 36c0e36..4e3f83e 100644
+--- a/drivers/media/radio/dsbr100.c
++++ b/drivers/media/radio/dsbr100.c
+@@ -438,7 +438,9 @@ static const struct file_operations usb_dsbr100_fops = {
+ .open = usb_dsbr100_open,
+ .release = usb_dsbr100_close,
+ .ioctl = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+diff --git a/drivers/media/radio/miropcm20-radio.c b/drivers/media/radio/miropcm20-radio.c
+index 3ae56fe..09fe6f1 100644
+--- a/drivers/media/radio/miropcm20-radio.c
++++ b/drivers/media/radio/miropcm20-radio.c
+@@ -221,7 +221,9 @@ static const struct file_operations pcm20_fops = {
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = pcm20_ioctl,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+diff --git a/drivers/media/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c
+index aed1147..06dfed9 100644
+--- a/drivers/media/radio/miropcm20-rds.c
++++ b/drivers/media/radio/miropcm20-rds.c
+@@ -19,7 +19,7 @@
+ #include "miropcm20-rds-core.h"
+
+ static char * text_buffer;
+-static int rds_users = 0;
++static int rds_users;
+
+
+ static int rds_f_open(struct inode *in, struct file *fi)
+diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
+index f0a67e9..1ec18ed 100644
+--- a/drivers/media/radio/radio-aimslab.c
++++ b/drivers/media/radio/radio-aimslab.c
+@@ -36,7 +36,6 @@
+ #include <asm/uaccess.h> /* copy to/from user */
+ #include <linux/videodev2.h> /* kernel radio structs */
+ #include <media/v4l2-common.h>
+-#include <asm/semaphore.h> /* Lock for the I/O */
+
+ #include <linux/version.h> /* for KERNEL_VERSION MACRO */
+ #define RADIO_VERSION KERNEL_VERSION(0,0,2)
+@@ -383,7 +382,9 @@ static const struct file_operations rtrack_fops = {
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c
+index 9b1f7a9..46cdb54 100644
+--- a/drivers/media/radio/radio-aztech.c
++++ b/drivers/media/radio/radio-aztech.c
+@@ -346,7 +346,9 @@ static const struct file_operations aztech_fops = {
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
+index 57b9e3a..b14db53 100644
+--- a/drivers/media/radio/radio-cadet.c
++++ b/drivers/media/radio/radio-cadet.c
+@@ -69,13 +69,13 @@ static struct v4l2_queryctrl radio_qctrl[] = {
+
+ static int io=-1; /* default to isapnp activation */
+ static int radio_nr = -1;
+-static int users=0;
+-static int curtuner=0;
+-static int tunestat=0;
+-static int sigstrength=0;
++static int users;
++static int curtuner;
++static int tunestat;
++static int sigstrength;
+ static wait_queue_head_t read_queue;
+ static struct timer_list readtimer;
+-static __u8 rdsin=0,rdsout=0,rdsstat=0;
++static __u8 rdsin, rdsout, rdsstat;
+ static unsigned char rdsbuf[RDS_BUFFER];
+ static spinlock_t cadet_io_lock;
+
+@@ -563,7 +563,9 @@ static const struct file_operations cadet_fops = {
+ .read = cadet_read,
+ .ioctl = video_ioctl2,
+ .poll = cadet_poll,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c
+index 99a3231..de49be9 100644
+--- a/drivers/media/radio/radio-gemtek-pci.c
++++ b/drivers/media/radio/radio-gemtek-pci.c
+@@ -368,7 +368,9 @@ static const struct file_operations gemtek_pci_fops = {
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
+index 246422b..81f6aeb 100644
+--- a/drivers/media/radio/radio-gemtek.c
++++ b/drivers/media/radio/radio-gemtek.c
+@@ -397,7 +397,9 @@ static const struct file_operations gemtek_fops = {
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek
+ };
+
+diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c
+index bc51f4d..bddd3c4 100644
+--- a/drivers/media/radio/radio-maestro.c
++++ b/drivers/media/radio/radio-maestro.c
+@@ -100,7 +100,9 @@ static const struct file_operations maestro_fops = {
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c
+index 8e184cf..0133ecf 100644
+--- a/drivers/media/radio/radio-maxiradio.c
++++ b/drivers/media/radio/radio-maxiradio.c
+@@ -103,7 +103,9 @@ static const struct file_operations maxiradio_fops = {
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
+index 82aedfc..0708021 100644
+--- a/drivers/media/radio/radio-rtrack2.c
++++ b/drivers/media/radio/radio-rtrack2.c
+@@ -288,7 +288,9 @@ static const struct file_operations rtrack2_fops = {
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
+index 53e1148..66e052f 100644
+--- a/drivers/media/radio/radio-sf16fmi.c
++++ b/drivers/media/radio/radio-sf16fmi.c
+@@ -288,7 +288,9 @@ static const struct file_operations fmi_fops = {
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
+index ebc5fbb..b0ccf7c 100644
+--- a/drivers/media/radio/radio-sf16fmr2.c
++++ b/drivers/media/radio/radio-sf16fmr2.c
+@@ -29,6 +29,8 @@ static struct mutex lock;
+ #include <linux/version.h> /* for KERNEL_VERSION MACRO */
+ #define RADIO_VERSION KERNEL_VERSION(0,0,2)
+
++#define AUD_VOL_INDEX 1
++
+ static struct v4l2_queryctrl radio_qctrl[] = {
+ {
+ .id = V4L2_CID_AUDIO_MUTE,
+@@ -37,13 +39,14 @@ static struct v4l2_queryctrl radio_qctrl[] = {
+ .maximum = 1,
+ .default_value = 1,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+- },{
++ },
++ [AUD_VOL_INDEX] = {
+ .id = V4L2_CID_AUDIO_VOLUME,
+ .name = "Volume",
+ .minimum = 0,
+- .maximum = 65535,
+- .step = 1<<12,
+- .default_value = 0xff,
++ .maximum = 15,
++ .step = 1,
++ .default_value = 0,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ }
+ };
+@@ -61,7 +64,7 @@ static struct v4l2_queryctrl radio_qctrl[] = {
+ struct fmr2_device
+ {
+ int port;
+- int curvol; /* 0-65535, if not volume 0 or 65535 */
++ int curvol; /* 0-15 */
+ int mute;
+ int stereo; /* card is producing stereo audio */
+ unsigned long curfreq; /* freq in kHz */
+@@ -176,51 +179,35 @@ static int fmr2_setfreq(struct fmr2_device *dev)
+ /* !!! not tested, in my card this does't work !!! */
+ static int fmr2_setvolume(struct fmr2_device *dev)
+ {
+- int i,a,n, port = dev->port;
++ int vol[16] = { 0x021, 0x084, 0x090, 0x104,
++ 0x110, 0x204, 0x210, 0x402,
++ 0x404, 0x408, 0x410, 0x801,
++ 0x802, 0x804, 0x808, 0x810 };
++ int i, a, port = dev->port;
++ int n = vol[dev->curvol & 0x0f];
+
+- if (dev->card_type != 11) return 1;
++ if (dev->card_type != 11)
++ return 1;
+
+- switch( (dev->curvol+(1<<11)) >> 12 )
+- {
+- case 0: case 1: n = 0x21; break;
+- case 2: n = 0x84; break;
+- case 3: n = 0x90; break;
+- case 4: n = 0x104; break;
+- case 5: n = 0x110; break;
+- case 6: n = 0x204; break;
+- case 7: n = 0x210; break;
+- case 8: n = 0x402; break;
+- case 9: n = 0x404; break;
+- default:
+- case 10: n = 0x408; break;
+- case 11: n = 0x410; break;
+- case 12: n = 0x801; break;
+- case 13: n = 0x802; break;
+- case 14: n = 0x804; break;
+- case 15: n = 0x808; break;
+- case 16: n = 0x810; break;
+- }
+- for(i=12;--i>=0;)
+- {
++ for (i = 12; --i >= 0; ) {
+ a = ((n >> i) & 1) << 6; /* if (a=0) a= 0; else a= 0x40; */
+- outb(a|4, port);
+- wait(4,port);
+- outb(a|0x24, port);
+- wait(4,port);
+- outb(a|4, port);
+- wait(4,port);
++ outb(a | 4, port);
++ wait(4, port);
++ outb(a | 0x24, port);
++ wait(4, port);
++ outb(a | 4, port);
++ wait(4, port);
+ }
+- for(i=6;--i>=0;)
+- {
++ for (i = 6; --i >= 0; ) {
+ a = ((0x18 >> i) & 1) << 6;
+- outb(a|4, port);
++ outb(a | 4, port);
+ wait(4,port);
+- outb(a|0x24, port);
++ outb(a | 0x24, port);
+ wait(4,port);
+ outb(a|4, port);
+ wait(4,port);
+ }
+- wait(4,port);
++ wait(4, port);
+ outb(0x14, port);
+
+ return 0;
+@@ -312,16 +299,10 @@ static int vidioc_queryctrl(struct file *file, void *priv,
+ struct v4l2_queryctrl *qc)
+ {
+ int i;
+- struct video_device *dev = video_devdata(file);
+- struct fmr2_device *fmr2 = dev->priv;
+
+ for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+- if ((fmr2->card_type != 11)
+- && V4L2_CID_AUDIO_VOLUME)
+- radio_qctrl[i].step = 65535;
+ if (qc->id && qc->id == radio_qctrl[i].id) {
+- memcpy(qc, &(radio_qctrl[i]),
+- sizeof(*qc));
++ memcpy(qc, &radio_qctrl[i], sizeof(*qc));
+ return 0;
+ }
+ }
+@@ -354,24 +335,13 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ fmr2->mute = ctrl->value;
+- if (fmr2->card_type != 11) {
+- if (!fmr2->mute)
+- fmr2->curvol = 65535;
+- else
+- fmr2->curvol = 0;
+- }
+ break;
+ case V4L2_CID_AUDIO_VOLUME:
+- fmr2->curvol = ctrl->value;
+- if (fmr2->card_type != 11) {
+- if (fmr2->curvol) {
+- fmr2->curvol = 65535;
+- fmr2->mute = 0;
+- } else {
+- fmr2->curvol = 0;
+- fmr2->mute = 1;
+- }
+- }
++ if (ctrl->value > radio_qctrl[AUD_VOL_INDEX].maximum)
++ fmr2->curvol = radio_qctrl[AUD_VOL_INDEX].maximum;
++ else
++ fmr2->curvol = ctrl->value;
++
+ break;
+ default:
+ return -EINVAL;
+@@ -387,6 +357,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
+ mutex_lock(&lock);
+ if (fmr2->curvol && !fmr2->mute) {
+ fmr2_setvolume(fmr2);
++ /* Set frequency and unmute card */
+ fmr2_setfreq(fmr2);
+ } else
+ fmr2_mute(fmr2->port);
+@@ -433,7 +404,9 @@ static const struct file_operations fmr2_fops = {
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+@@ -487,6 +460,11 @@ static int __init fmr2_init(void)
+ fmr2_product_info(&fmr2_unit);
+ mutex_unlock(&lock);
+ debug_print((KERN_DEBUG "card_type %d\n", fmr2_unit.card_type));
++
++ /* Only card_type == 11 implements volume */
++ if (fmr2_unit.card_type != 11)
++ radio_qctrl[AUD_VOL_INDEX].maximum = 1;
++
+ return 0;
+ }
+
+diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c
+index 649f14d..77354ca 100644
+--- a/drivers/media/radio/radio-si470x.c
++++ b/drivers/media/radio/radio-si470x.c
+@@ -85,6 +85,7 @@
+ * Oliver Neukum <oliver at neukum.org>
+ * Version 1.0.7
+ * - usb autosuspend support
++ * - unplugging fixed
+ *
+ * ToDo:
+ * - add seeking support
+@@ -97,10 +98,10 @@
+ /* driver definitions */
+ #define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz at gmx.net>"
+ #define DRIVER_NAME "radio-si470x"
+-#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 6)
++#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 7)
+ #define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
+ #define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers"
+-#define DRIVER_VERSION "1.0.6"
++#define DRIVER_VERSION "1.0.7"
+
+
+ /* kernel includes */
+@@ -424,6 +425,7 @@ struct si470x_device {
+
+ /* driver management */
+ unsigned int users;
++ unsigned char disconnected;
+
+ /* Silabs internal registers (0..15) */
+ unsigned short registers[RADIO_REGISTER_NUM];
+@@ -440,6 +442,12 @@ struct si470x_device {
+
+
+ /*
++ * Lock to prevent kfree of data before all users have releases the device.
++ */
++static DEFINE_MUTEX(open_close_lock);
++
++
++/*
+ * The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW,
+ * 62.5 kHz otherwise.
+ * The tuner is able to have a channel spacing of 50, 100 or 200 kHz.
+@@ -577,7 +585,7 @@ static int si470x_get_rds_registers(struct si470x_device *radio)
+ usb_rcvintpipe(radio->usbdev, 1),
+ (void *) &buf, sizeof(buf), &size, usb_timeout);
+ if (size != sizeof(buf))
+- printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_register: "
++ printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: "
+ "return size differs: %d != %zu\n", size, sizeof(buf));
+ if (retval < 0)
+ printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: "
+@@ -875,6 +883,8 @@ static void si470x_work(struct work_struct *work)
+ struct si470x_device *radio = container_of(work, struct si470x_device,
+ work.work);
+
++ if (radio->disconnected)
++ return;
+ if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
+ return;
+
+@@ -1001,13 +1011,21 @@ static int si470x_fops_open(struct inode *inode, struct file *file)
+ static int si470x_fops_release(struct inode *inode, struct file *file)
+ {
+ struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+- int retval;
++ int retval = 0;
+
+ if (!radio)
+ return -ENODEV;
+
++ mutex_lock(&open_close_lock);
+ radio->users--;
+ if (radio->users == 0) {
++ if (radio->disconnected) {
++ video_unregister_device(radio->videodev);
++ kfree(radio->buffer);
++ kfree(radio);
++ goto done;
++ }
++
+ /* stop rds reception */
+ cancel_delayed_work_sync(&radio->work);
+
+@@ -1016,10 +1034,11 @@ static int si470x_fops_release(struct inode *inode, struct file *file)
+
+ retval = si470x_stop(radio);
+ usb_autopm_put_interface(radio->intf);
+- return retval;
+ }
+
+- return 0;
++done:
++ mutex_unlock(&open_close_lock);
++ return retval;
+ }
+
+
+@@ -1032,7 +1051,9 @@ static const struct file_operations si470x_fops = {
+ .read = si470x_fops_read,
+ .poll = si470x_fops_poll,
+ .ioctl = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .open = si470x_fops_open,
+ .release = si470x_fops_release,
+ };
+@@ -1157,6 +1178,9 @@ static int si470x_vidioc_g_ctrl(struct file *file, void *priv,
+ {
+ struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+
++ if (radio->disconnected)
++ return -EIO;
++
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_VOLUME:
+ ctrl->value = radio->registers[SYSCONFIG2] &
+@@ -1181,6 +1205,9 @@ static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
+ struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ int retval;
+
++ if (radio->disconnected)
++ return -EIO;
++
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_VOLUME:
+ radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME;
+@@ -1243,6 +1270,8 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
+ struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ int retval;
+
++ if (radio->disconnected)
++ return -EIO;
+ if (tuner->index > 0)
+ return -EINVAL;
+
+@@ -1299,6 +1328,8 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv,
+ struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ int retval;
+
++ if (radio->disconnected)
++ return -EIO;
+ if (tuner->index > 0)
+ return -EINVAL;
+
+@@ -1324,6 +1355,9 @@ static int si470x_vidioc_g_frequency(struct file *file, void *priv,
+ {
+ struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+
++ if (radio->disconnected)
++ return -EIO;
++
+ freq->type = V4L2_TUNER_RADIO;
+ freq->frequency = si470x_get_freq(radio);
+
+@@ -1340,6 +1374,8 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv,
+ struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ int retval;
+
++ if (radio->disconnected)
++ return -EIO;
+ if (freq->type != V4L2_TUNER_RADIO)
+ return -EINVAL;
+
+@@ -1510,11 +1546,16 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf)
+ {
+ struct si470x_device *radio = usb_get_intfdata(intf);
+
++ mutex_lock(&open_close_lock);
++ radio->disconnected = 1;
+ cancel_delayed_work_sync(&radio->work);
+ usb_set_intfdata(intf, NULL);
+- video_unregister_device(radio->videodev);
+- kfree(radio->buffer);
+- kfree(radio);
++ if (radio->users == 0) {
++ video_unregister_device(radio->videodev);
++ kfree(radio->buffer);
++ kfree(radio);
++ }
++ mutex_unlock(&open_close_lock);
+ }
+
+
+diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c
+index 535ffe8..acc3208 100644
+--- a/drivers/media/radio/radio-terratec.c
++++ b/drivers/media/radio/radio-terratec.c
+@@ -360,7 +360,9 @@ static const struct file_operations terratec_fops = {
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c
+index c11981f..4ebdfba 100644
+--- a/drivers/media/radio/radio-trust.c
++++ b/drivers/media/radio/radio-trust.c
+@@ -340,7 +340,9 @@ static const struct file_operations trust_fops = {
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c
+index 1366326..18f2abd 100644
+--- a/drivers/media/radio/radio-typhoon.c
++++ b/drivers/media/radio/radio-typhoon.c
+@@ -35,6 +35,7 @@
+ #include <linux/init.h> /* Initdata */
+ #include <linux/ioport.h> /* request_region */
+ #include <linux/proc_fs.h> /* radio card status report */
++#include <linux/seq_file.h>
+ #include <asm/io.h> /* outb, outb_p */
+ #include <asm/uaccess.h> /* copy to/from user */
+ #include <linux/videodev2.h> /* kernel radio structs */
+@@ -93,9 +94,6 @@ static int typhoon_setfreq(struct typhoon_device *dev, unsigned long frequency);
+ static void typhoon_mute(struct typhoon_device *dev);
+ static void typhoon_unmute(struct typhoon_device *dev);
+ static int typhoon_setvol(struct typhoon_device *dev, int vol);
+-#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
+-static int typhoon_get_info(char *buf, char **start, off_t offset, int len);
+-#endif
+
+ static void typhoon_setvol_generic(struct typhoon_device *dev, int vol)
+ {
+@@ -340,7 +338,9 @@ static const struct file_operations typhoon_fops = {
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+@@ -366,30 +366,39 @@ static struct video_device typhoon_radio =
+
+ #ifdef CONFIG_RADIO_TYPHOON_PROC_FS
+
+-static int typhoon_get_info(char *buf, char **start, off_t offset, int len)
++static int typhoon_proc_show(struct seq_file *m, void *v)
+ {
+- char *out = buf;
+-
+ #ifdef MODULE
+ #define MODULEPROCSTRING "Driver loaded as a module"
+ #else
+ #define MODULEPROCSTRING "Driver compiled into kernel"
+ #endif
+
+- /* output must be kept under PAGE_SIZE */
+- out += sprintf(out, BANNER);
+- out += sprintf(out, "Load type: " MODULEPROCSTRING "\n\n");
+- out += sprintf(out, "frequency = %lu kHz\n",
++ seq_puts(m, BANNER);
++ seq_puts(m, "Load type: " MODULEPROCSTRING "\n\n");
++ seq_printf(m, "frequency = %lu kHz\n",
+ typhoon_unit.curfreq >> 4);
+- out += sprintf(out, "volume = %d\n", typhoon_unit.curvol);
+- out += sprintf(out, "mute = %s\n", typhoon_unit.muted ?
++ seq_printf(m, "volume = %d\n", typhoon_unit.curvol);
++ seq_printf(m, "mute = %s\n", typhoon_unit.muted ?
+ "on" : "off");
+- out += sprintf(out, "iobase = 0x%x\n", typhoon_unit.iobase);
+- out += sprintf(out, "mute frequency = %lu kHz\n",
++ seq_printf(m, "iobase = 0x%x\n", typhoon_unit.iobase);
++ seq_printf(m, "mute frequency = %lu kHz\n",
+ typhoon_unit.mutefreq >> 4);
+- return out - buf;
++ return 0;
+ }
+
++static int typhoon_proc_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, typhoon_proc_show, NULL);
++}
++
++static const struct file_operations typhoon_proc_fops = {
++ .owner = THIS_MODULE,
++ .open = typhoon_proc_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
+ #endif /* CONFIG_RADIO_TYPHOON_PROC_FS */
+
+ MODULE_AUTHOR("Dr. Henrik Seidel");
+@@ -404,7 +413,7 @@ MODULE_PARM_DESC(io, "I/O address of the Typhoon card (0x316 or 0x336)");
+ module_param(radio_nr, int, 0);
+
+ #ifdef MODULE
+-static unsigned long mutefreq = 0;
++static unsigned long mutefreq;
+ module_param(mutefreq, ulong, 0);
+ MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)");
+ #endif
+@@ -450,8 +459,7 @@ static int __init typhoon_init(void)
+ typhoon_mute(&typhoon_unit);
+
+ #ifdef CONFIG_RADIO_TYPHOON_PROC_FS
+- if (!create_proc_info_entry("driver/radio-typhoon", 0, NULL,
+- typhoon_get_info))
++ if (!proc_create("driver/radio-typhoon", 0, NULL, &typhoon_proc_fops))
+ printk(KERN_ERR "radio-typhoon: registering /proc/driver/radio-typhoon failed\n");
+ #endif
+
+diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c
+index 203f437..43773c5 100644
+--- a/drivers/media/radio/radio-zoltrix.c
++++ b/drivers/media/radio/radio-zoltrix.c
+@@ -401,7 +401,9 @@ static const struct file_operations zoltrix_fops =
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
+index 1832966..fe9a4cc 100644
+--- a/drivers/media/video/Kconfig
++++ b/drivers/media/video/Kconfig
+@@ -270,6 +270,15 @@ config VIDEO_SAA711X
+ To compile this driver as a module, choose M here: the
+ module will be called saa7115.
+
++config VIDEO_SAA717X
++ tristate "Philips SAA7171/3/4 audio/video decoders"
++ depends on VIDEO_V4L2 && I2C
++ ---help---
++ Support for the Philips SAA7171/3/4 audio/video decoders.
++
++ To compile this driver as a module, choose M here: the
++ module will be called saa717x.
++
+ config VIDEO_SAA7191
+ tristate "Philips SAA7191 video decoder"
+ depends on VIDEO_V4L1 && I2C
+@@ -689,6 +698,8 @@ source "drivers/media/video/cx88/Kconfig"
+
+ source "drivers/media/video/cx23885/Kconfig"
+
++source "drivers/media/video/au0828/Kconfig"
++
+ source "drivers/media/video/ivtv/Kconfig"
+
+ config VIDEO_M32R_AR
+@@ -836,4 +847,49 @@ config USB_STKWEBCAM
+
+ endif # V4L_USB_DRIVERS
+
++config SOC_CAMERA
++ tristate "SoC camera support"
++ depends on VIDEO_V4L2
++ select VIDEOBUF_DMA_SG
++ help
++ SoC Camera is a common API to several cameras, not connecting
++ over a bus like PCI or USB. For example some i2c camera connected
++ directly to the data bus of an SoC.
++
++config SOC_CAMERA_MT9M001
++ tristate "mt9m001 support"
++ depends on SOC_CAMERA
++ select GPIO_PCA953X if MT9M001_PCA9536_SWITCH
++ help
++ This driver supports MT9M001 cameras from Micron, monochrome
++ and colour models.
++
++config MT9M001_PCA9536_SWITCH
++ bool "pca9536 datawidth switch for mt9m001"
++ depends on SOC_CAMERA_MT9M001 && GENERIC_GPIO
++ help
++ Select this if your MT9M001 camera uses a PCA9536 I2C GPIO
++ extender to switch between 8 and 10 bit datawidth modes
++
++config SOC_CAMERA_MT9V022
++ tristate "mt9v022 support"
++ depends on SOC_CAMERA
++ select GPIO_PCA953X if MT9V022_PCA9536_SWITCH
++ help
++ This driver supports MT9V022 cameras from Micron
++
++config MT9V022_PCA9536_SWITCH
++ bool "pca9536 datawidth switch for mt9v022"
++ depends on SOC_CAMERA_MT9V022 && GENERIC_GPIO
++ help
++ Select this if your MT9V022 camera uses a PCA9536 I2C GPIO
++ extender to switch between 8 and 10 bit datawidth modes
++
++config VIDEO_PXA27x
++ tristate "PXA27x Quick Capture Interface driver"
++ depends on VIDEO_DEV && PXA27x
++ select SOC_CAMERA
++ ---help---
++ This is a v4l2 driver for the PXA27x Quick Capture Interface
++
+ endif # VIDEO_CAPTURE_DRIVERS
+diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
+index 3f209b3..be14227 100644
+--- a/drivers/media/video/Makefile
++++ b/drivers/media/video/Makefile
+@@ -4,7 +4,7 @@
+
+ zr36067-objs := zoran_procfs.o zoran_device.o \
+ zoran_driver.o zoran_card.o
+-tuner-objs := tuner-core.o tuner-types.o
++tuner-objs := tuner-core.o
+
+ msp3400-objs := msp3400-driver.o msp3400-kthreads.o
+
+@@ -38,6 +38,7 @@ obj-$(CONFIG_VIDEO_SAA7110) += saa7110.o
+ obj-$(CONFIG_VIDEO_SAA7111) += saa7111.o
+ obj-$(CONFIG_VIDEO_SAA7114) += saa7114.o
+ obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o
++obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o
+ obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
+ obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
+ obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o
+@@ -87,6 +88,8 @@ obj-$(CONFIG_VIDEO_TUNER) += tuner.o
+
+ obj-$(CONFIG_TUNER_XC2028) += tuner-xc2028.o
+ obj-$(CONFIG_TUNER_SIMPLE) += tuner-simple.o
++# tuner-types will be merged into tuner-simple, in the future
++obj-$(CONFIG_TUNER_SIMPLE) += tuner-types.o
+ obj-$(CONFIG_TUNER_MT20XX) += mt20xx.o
+ obj-$(CONFIG_TUNER_TDA8290) += tda8290.o
+ obj-$(CONFIG_TUNER_TEA5767) += tea5767.o
+@@ -135,5 +138,12 @@ obj-$(CONFIG_VIDEO_IVTV) += ivtv/
+ obj-$(CONFIG_VIDEO_VIVI) += vivi.o
+ obj-$(CONFIG_VIDEO_CX23885) += cx23885/
+
++obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o
++obj-$(CONFIG_SOC_CAMERA) += soc_camera.o
++obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o
++obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o
++
++obj-$(CONFIG_VIDEO_AU0828) += au0828/
++
+ EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+ EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c
+index fea2e72..f794f2d 100644
+--- a/drivers/media/video/adv7170.c
++++ b/drivers/media/video/adv7170.c
+@@ -56,7 +56,7 @@ MODULE_LICENSE("GPL");
+ #define I2C_NAME(x) (x)->name
+
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
+index 10d4d89..8ee07a6 100644
+--- a/drivers/media/video/adv7175.c
++++ b/drivers/media/video/adv7175.c
+@@ -52,7 +52,7 @@ MODULE_LICENSE("GPL");
+ #define I2C_NAME(s) (s)->name
+
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c
+index c94a4d0..8c7d195 100644
+--- a/drivers/media/video/arv.c
++++ b/drivers/media/video/arv.c
+@@ -125,8 +125,8 @@ static unsigned char yuv[MAX_AR_FRAME_BYTES];
+ /* default frequency */
+ #define DEFAULT_FREQ 50 /* 50 or 75 (MHz) is available as BCLK */
+ static int freq = DEFAULT_FREQ; /* BCLK: available 50 or 70 (MHz) */
+-static int vga = 0; /* default mode(0:QVGA mode, other:VGA mode) */
+-static int vga_interlace = 0; /* 0 is normal mode for, else interlace mode */
++static int vga; /* default mode(0:QVGA mode, other:VGA mode) */
++static int vga_interlace; /* 0 is normal mode for, else interlace mode */
+ module_param(freq, int, 0);
+ module_param(vga, int, 0);
+ module_param(vga_interlace, int, 0);
+@@ -747,7 +747,9 @@ static const struct file_operations ar_fops = {
+ .release = video_exclusive_release,
+ .read = ar_read,
+ .ioctl = ar_ioctl,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig
+new file mode 100644
+index 0000000..4170826
+--- /dev/null
++++ b/drivers/media/video/au0828/Kconfig
+@@ -0,0 +1,12 @@
++
++config VIDEO_AU0828
++ tristate "Auvitek AU0828 support"
++ depends on VIDEO_DEV && I2C && INPUT && DVB_CORE
++ select I2C_ALGOBIT
++ select DVB_AU8522 if !DVB_FE_CUSTOMIZE
++ select DVB_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
++ ---help---
++ This is a video4linux driver for Auvitek's USB device.
++
++ To compile this driver as a module, choose M here: the
++ module will be called au0828
+diff --git a/drivers/media/video/au0828/Makefile b/drivers/media/video/au0828/Makefile
+new file mode 100644
+index 0000000..9f4f572
+--- /dev/null
++++ b/drivers/media/video/au0828/Makefile
+@@ -0,0 +1,9 @@
++au0828-objs := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o
++
++obj-$(CONFIG_VIDEO_AU0828) += au0828.o
++
++EXTRA_CFLAGS += -Idrivers/media/video
++EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
++EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
++
++EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c
+new file mode 100644
+index 0000000..a2a6983
+--- /dev/null
++++ b/drivers/media/video/au0828/au0828-cards.c
+@@ -0,0 +1,181 @@
++/*
++ * Driver for the Auvitek USB bridge
++ *
++ * Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include "au0828.h"
++#include "au0828-cards.h"
++
++struct au0828_board au0828_boards[] = {
++ [AU0828_BOARD_UNKNOWN] = {
++ .name = "Unknown board",
++ },
++ [AU0828_BOARD_HAUPPAUGE_HVR850] = {
++ .name = "Hauppauge HVR850",
++ },
++ [AU0828_BOARD_HAUPPAUGE_HVR950Q] = {
++ .name = "Hauppauge HVR950Q",
++ },
++ [AU0828_BOARD_DVICO_FUSIONHDTV7] = {
++ .name = "DViCO FusionHDTV USB",
++ },
++};
++
++/* Tuner callback function for au0828 boards. Currently only needed
++ * for HVR1500Q, which has an xc5000 tuner.
++ */
++int au0828_tuner_callback(void *priv, int command, int arg)
++{
++ struct au0828_dev *dev = priv;
++
++ dprintk(1, "%s()\n", __func__);
++
++ switch (dev->board) {
++ case AU0828_BOARD_HAUPPAUGE_HVR850:
++ case AU0828_BOARD_HAUPPAUGE_HVR950Q:
++ case AU0828_BOARD_DVICO_FUSIONHDTV7:
++ if (command == 0) {
++ /* Tuner Reset Command from xc5000 */
++ /* Drive the tuner into reset and out */
++ au0828_clear(dev, REG_001, 2);
++ mdelay(200);
++ au0828_set(dev, REG_001, 2);
++ mdelay(50);
++ return 0;
++ } else {
++ printk(KERN_ERR
++ "%s(): Unknown command.\n", __func__);
++ return -EINVAL;
++ }
++ break;
++ }
++
++ return 0; /* Should never be here */
++}
++
++static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data)
++{
++ struct tveeprom tv;
++
++ tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data);
++
++ /* Make sure we support the board model */
++ switch (tv.model) {
++ case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */
++ case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and basic analog video */
++ break;
++ default:
++ printk(KERN_WARNING "%s: warning: "
++ "unknown hauppauge model #%d\n", __func__, tv.model);
++ break;
++ }
++
++ printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n",
++ __func__, tv.model);
++}
++
++void au0828_card_setup(struct au0828_dev *dev)
++{
++ static u8 eeprom[256];
++
++ dprintk(1, "%s()\n", __func__);
++
++ if (dev->i2c_rc == 0) {
++ dev->i2c_client.addr = 0xa0 >> 1;
++ tveeprom_read(&dev->i2c_client, eeprom, sizeof(eeprom));
++ }
++
++ switch (dev->board) {
++ case AU0828_BOARD_HAUPPAUGE_HVR850:
++ case AU0828_BOARD_HAUPPAUGE_HVR950Q:
++ if (dev->i2c_rc == 0)
++ hauppauge_eeprom(dev, eeprom+0xa0);
++ break;
++ }
++}
++
++/*
++ * The bridge has between 8 and 12 gpios.
++ * Regs 1 and 0 deal with output enables.
++ * Regs 3 and 2 deal with direction.
++ */
++void au0828_gpio_setup(struct au0828_dev *dev)
++{
++ dprintk(1, "%s()\n", __func__);
++
++ switch (dev->board) {
++ case AU0828_BOARD_HAUPPAUGE_HVR850:
++ case AU0828_BOARD_HAUPPAUGE_HVR950Q:
++ /* GPIO's
++ * 4 - CS5340
++ * 5 - AU8522 Demodulator
++ * 6 - eeprom W/P
++ * 9 - XC5000 Tuner
++ */
++
++ /* Into reset */
++ au0828_write(dev, REG_003, 0x02);
++ au0828_write(dev, REG_002, 0x88 | 0x20);
++ au0828_write(dev, REG_001, 0x0);
++ au0828_write(dev, REG_000, 0x0);
++ msleep(100);
++
++ /* Out of reset */
++ au0828_write(dev, REG_003, 0x02);
++ au0828_write(dev, REG_001, 0x02);
++ au0828_write(dev, REG_002, 0x88 | 0x20);
++ au0828_write(dev, REG_000, 0x88 | 0x20 | 0x40);
++ msleep(250);
++ break;
++ case AU0828_BOARD_DVICO_FUSIONHDTV7:
++ /* GPIO's
++ * 6 - ?
++ * 8 - AU8522 Demodulator
++ * 9 - XC5000 Tuner
++ */
++
++ /* Into reset */
++ au0828_write(dev, REG_003, 0x02);
++ au0828_write(dev, REG_002, 0xa0);
++ au0828_write(dev, REG_001, 0x0);
++ au0828_write(dev, REG_000, 0x0);
++ msleep(100);
++
++ /* Out of reset */
++ au0828_write(dev, REG_003, 0x02);
++ au0828_write(dev, REG_002, 0xa0);
++ au0828_write(dev, REG_001, 0x02);
++ au0828_write(dev, REG_000, 0xa0);
++ msleep(250);
++ break;
++ }
++}
++
++/* table of devices that work with this driver */
++struct usb_device_id au0828_usb_id_table [] = {
++ { USB_DEVICE(0x2040, 0x7200),
++ .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
++ { USB_DEVICE(0x2040, 0x7240),
++ .driver_info = AU0828_BOARD_HAUPPAUGE_HVR850 },
++ { USB_DEVICE(0x0fe9, 0xd620),
++ .driver_info = AU0828_BOARD_DVICO_FUSIONHDTV7 },
++ { },
++};
++
++MODULE_DEVICE_TABLE(usb, au0828_usb_id_table);
+diff --git a/drivers/media/video/au0828/au0828-cards.h b/drivers/media/video/au0828/au0828-cards.h
+new file mode 100644
+index 0000000..e26f54a
+--- /dev/null
++++ b/drivers/media/video/au0828/au0828-cards.h
+@@ -0,0 +1,25 @@
++/*
++ * Driver for the Auvitek USB bridge
++ *
++ * Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#define AU0828_BOARD_UNKNOWN 0
++#define AU0828_BOARD_HAUPPAUGE_HVR950Q 1
++#define AU0828_BOARD_HAUPPAUGE_HVR850 2
++#define AU0828_BOARD_DVICO_FUSIONHDTV7 3
+diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c
+new file mode 100644
+index 0000000..54bfc0f
+--- /dev/null
++++ b/drivers/media/video/au0828/au0828-core.c
+@@ -0,0 +1,256 @@
++/*
++ * Driver for the Auvitek USB bridge
++ *
++ * Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/videodev2.h>
++#include <media/v4l2-common.h>
++#include <linux/mutex.h>
++
++#include "au0828.h"
++
++/*
++ * 1 = General debug messages
++ * 2 = USB handling
++ * 4 = I2C related
++ * 8 = Bridge related
++ */
++int au0828_debug;
++module_param_named(debug, au0828_debug, int, 0644);
++MODULE_PARM_DESC(debug, "enable debug messages");
++
++#define _AU0828_BULKPIPE 0x03
++#define _BULKPIPESIZE 0xffff
++
++static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
++ u16 index, unsigned char *cp, u16 size);
++static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
++ u16 index, unsigned char *cp, u16 size);
++
++/* USB Direction */
++#define CMD_REQUEST_IN 0x00
++#define CMD_REQUEST_OUT 0x01
++
++u32 au0828_readreg(struct au0828_dev *dev, u16 reg)
++{
++ recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, dev->ctrlmsg, 1);
++ dprintk(8, "%s(0x%x) = 0x%x\n", __func__, reg, dev->ctrlmsg[0]);
++ return dev->ctrlmsg[0];
++}
++
++u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val)
++{
++ dprintk(8, "%s(0x%x, 0x%x)\n", __func__, reg, val);
++ return send_control_msg(dev, CMD_REQUEST_OUT, val, reg,
++ dev->ctrlmsg, 0);
++}
++
++static void cmd_msg_dump(struct au0828_dev *dev)
++{
++ int i;
++
++ for (i = 0; i < sizeof(dev->ctrlmsg); i += 16)
++ dprintk(2, "%s() %02x %02x %02x %02x %02x %02x %02x %02x "
++ "%02x %02x %02x %02x %02x %02x %02x %02x\n",
++ __func__,
++ dev->ctrlmsg[i+0], dev->ctrlmsg[i+1],
++ dev->ctrlmsg[i+2], dev->ctrlmsg[i+3],
++ dev->ctrlmsg[i+4], dev->ctrlmsg[i+5],
++ dev->ctrlmsg[i+6], dev->ctrlmsg[i+7],
++ dev->ctrlmsg[i+8], dev->ctrlmsg[i+9],
++ dev->ctrlmsg[i+10], dev->ctrlmsg[i+11],
++ dev->ctrlmsg[i+12], dev->ctrlmsg[i+13],
++ dev->ctrlmsg[i+14], dev->ctrlmsg[i+15]);
++}
++
++static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
++ u16 index, unsigned char *cp, u16 size)
++{
++ int status = -ENODEV;
++ mutex_lock(&dev->mutex);
++ if (dev->usbdev) {
++
++ /* cp must be memory that has been allocated by kmalloc */
++ status = usb_control_msg(dev->usbdev,
++ usb_sndctrlpipe(dev->usbdev, 0),
++ request,
++ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
++ value, index,
++ cp, size, 1000);
++
++ status = min(status, 0);
++
++ if (status < 0) {
++ printk(KERN_ERR "%s() Failed sending control message, error %d.\n",
++ __func__, status);
++ }
++
++ }
++ mutex_unlock(&dev->mutex);
++ return status;
++}
++
++static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
++ u16 index, unsigned char *cp, u16 size)
++{
++ int status = -ENODEV;
++ mutex_lock(&dev->mutex);
++ if (dev->usbdev) {
++
++ memset(dev->ctrlmsg, 0, sizeof(dev->ctrlmsg));
++
++ /* cp must be memory that has been allocated by kmalloc */
++ status = usb_control_msg(dev->usbdev,
++ usb_rcvctrlpipe(dev->usbdev, 0),
++ request,
++ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
++ value, index,
++ cp, size, 1000);
++
++ status = min(status, 0);
++
++ if (status < 0) {
++ printk(KERN_ERR "%s() Failed receiving control message, error %d.\n",
++ __func__, status);
++ } else
++ cmd_msg_dump(dev);
++ }
++ mutex_unlock(&dev->mutex);
++ return status;
++}
++
++static void au0828_usb_disconnect(struct usb_interface *interface)
++{
++ struct au0828_dev *dev = usb_get_intfdata(interface);
++
++ dprintk(1, "%s()\n", __func__);
++
++ /* Digital TV */
++ au0828_dvb_unregister(dev);
++
++ /* I2C */
++ au0828_i2c_unregister(dev);
++
++ usb_set_intfdata(interface, NULL);
++
++ mutex_lock(&dev->mutex);
++ dev->usbdev = NULL;
++ mutex_unlock(&dev->mutex);
++
++ kfree(dev);
++
++}
++
++static int au0828_usb_probe(struct usb_interface *interface,
++ const struct usb_device_id *id)
++{
++ int ifnum;
++ struct au0828_dev *dev;
++ struct usb_device *usbdev = interface_to_usbdev(interface);
++
++ ifnum = interface->altsetting->desc.bInterfaceNumber;
++
++ if (ifnum != 0)
++ return -ENODEV;
++
++ dprintk(1, "%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __func__,
++ le16_to_cpu(usbdev->descriptor.idVendor),
++ le16_to_cpu(usbdev->descriptor.idProduct),
++ ifnum);
++
++ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
++ if (dev == NULL) {
++ printk(KERN_ERR "%s() Unable to allocate memory\n", __func__);
++ return -ENOMEM;
++ }
++
++ mutex_init(&dev->mutex);
++ mutex_init(&dev->dvb.lock);
++ dev->usbdev = usbdev;
++ dev->board = id->driver_info;
++
++ usb_set_intfdata(interface, dev);
++
++ /* Power Up the bridge */
++ au0828_write(dev, REG_600, 1 << 4);
++
++ /* Bring up the GPIO's and supporting devices */
++ au0828_gpio_setup(dev);
++
++ /* I2C */
++ au0828_i2c_register(dev);
++
++ /* Setup */
++ au0828_card_setup(dev);
++
++ /* Digital TV */
++ au0828_dvb_register(dev);
++
++ printk(KERN_INFO "Registered device AU0828 [%s]\n",
++ au0828_boards[dev->board].name == NULL ? "Unset" :
++ au0828_boards[dev->board].name);
++
++ return 0;
++}
++
++static struct usb_driver au0828_usb_driver = {
++ .name = DRIVER_NAME,
++ .probe = au0828_usb_probe,
++ .disconnect = au0828_usb_disconnect,
++ .id_table = au0828_usb_id_table,
++};
++
++static int __init au0828_init(void)
++{
++ int ret;
++
++ if (au0828_debug & 1)
++ printk(KERN_INFO "%s() Debugging is enabled\n", __func__);
++
++ if (au0828_debug & 2)
++ printk(KERN_INFO "%s() USB Debugging is enabled\n", __func__);
++
++ if (au0828_debug & 4)
++ printk(KERN_INFO "%s() I2C Debugging is enabled\n", __func__);
++
++ if (au0828_debug & 8)
++ printk(KERN_INFO "%s() Bridge Debugging is enabled\n",
++ __func__);
++
++ printk(KERN_INFO "au0828 driver loaded\n");
++
++ ret = usb_register(&au0828_usb_driver);
++ if (ret)
++ printk(KERN_ERR "usb_register failed, error = %d\n", ret);
++
++ return ret;
++}
++
++static void __exit au0828_exit(void)
++{
++ usb_deregister(&au0828_usb_driver);
++}
++
++module_init(au0828_init);
++module_exit(au0828_exit);
++
++MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products");
++MODULE_AUTHOR("Steven Toth <stoth at hauppauge.com>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c
+new file mode 100644
+index 0000000..5040d7f
+--- /dev/null
++++ b/drivers/media/video/au0828/au0828-dvb.c
+@@ -0,0 +1,373 @@
++/*
++ * Driver for the Auvitek USB bridge
++ *
++ * Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/device.h>
++#include <linux/suspend.h>
++#include <media/v4l2-common.h>
++
++#include "au0828.h"
++#include "au8522.h"
++#include "xc5000.h"
++
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
++#define _AU0828_BULKPIPE 0x83
++#define _BULKPIPESIZE 0xe522
++
++static struct au8522_config hauppauge_hvr950q_config = {
++ .demod_address = 0x8e >> 1,
++ .status_mode = AU8522_DEMODLOCKING,
++};
++
++static struct xc5000_config hauppauge_hvr950q_tunerconfig = {
++ .i2c_address = 0x61,
++ .if_khz = 6000,
++ .tuner_callback = au0828_tuner_callback
++};
++
++/*-------------------------------------------------------------------*/
++static void urb_completion(struct urb *purb)
++{
++ u8 *ptr;
++ struct au0828_dev *dev = purb->context;
++ int ptype = usb_pipetype(purb->pipe);
++
++ dprintk(2, "%s()\n", __func__);
++
++ if (!dev)
++ return;
++
++ if (dev->urb_streaming == 0)
++ return;
++
++ if (ptype != PIPE_BULK) {
++ printk(KERN_ERR "%s() Unsupported URB type %d\n",
++ __func__, ptype);
++ return;
++ }
++
++ ptr = (u8 *)purb->transfer_buffer;
++
++ /* Feed the transport payload into the kernel demux */
++ dvb_dmx_swfilter_packets(&dev->dvb.demux,
++ purb->transfer_buffer, purb->actual_length / 188);
++
++ /* Clean the buffer before we requeue */
++ memset(purb->transfer_buffer, 0, URB_BUFSIZE);
++
++ /* Requeue URB */
++ usb_submit_urb(purb, GFP_ATOMIC);
++}
++
++static int stop_urb_transfer(struct au0828_dev *dev)
++{
++ int i;
++
++ dprintk(2, "%s()\n", __func__);
++
++ for (i = 0; i < URB_COUNT; i++) {
++ usb_kill_urb(dev->urbs[i]);
++ kfree(dev->urbs[i]->transfer_buffer);
++ usb_free_urb(dev->urbs[i]);
++ }
++
++ dev->urb_streaming = 0;
++
++ return 0;
++}
++
++static int start_urb_transfer(struct au0828_dev *dev)
++{
++ struct urb *purb;
++ int i, ret = -ENOMEM;
++
++ dprintk(2, "%s()\n", __func__);
++
++ if (dev->urb_streaming) {
++ dprintk(2, "%s: iso xfer already running!\n", __func__);
++ return 0;
++ }
++
++ for (i = 0; i < URB_COUNT; i++) {
++
++ dev->urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
++ if (!dev->urbs[i])
++ goto err;
++
++ purb = dev->urbs[i];
++
++ purb->transfer_buffer = kzalloc(URB_BUFSIZE, GFP_KERNEL);
++ if (!purb->transfer_buffer) {
++ usb_free_urb(purb);
++ dev->urbs[i] = 0;
++ goto err;
++ }
++
++ purb->status = -EINPROGRESS;
++ usb_fill_bulk_urb(purb,
++ dev->usbdev,
++ usb_rcvbulkpipe(dev->usbdev, _AU0828_BULKPIPE),
++ purb->transfer_buffer,
++ URB_BUFSIZE,
++ urb_completion,
++ dev);
++
++ }
++
++ for (i = 0; i < URB_COUNT; i++) {
++ ret = usb_submit_urb(dev->urbs[i], GFP_ATOMIC);
++ if (ret != 0) {
++ stop_urb_transfer(dev);
++ printk(KERN_ERR "%s: failed urb submission, "
++ "err = %d\n", __func__, ret);
++ return ret;
++ }
++ }
++
++ dev->urb_streaming = 1;
++ ret = 0;
++
++err:
++ return ret;
++}
++
++static int au0828_dvb_start_feed(struct dvb_demux_feed *feed)
++{
++ struct dvb_demux *demux = feed->demux;
++ struct au0828_dev *dev = (struct au0828_dev *) demux->priv;
++ struct au0828_dvb *dvb = &dev->dvb;
++ int ret = 0;
++
++ dprintk(1, "%s()\n", __func__);
++
++ if (!demux->dmx.frontend)
++ return -EINVAL;
++
++ if (dvb) {
++ mutex_lock(&dvb->lock);
++ if (dvb->feeding++ == 0) {
++ /* Start transport */
++ au0828_write(dev, 0x608, 0x90);
++ au0828_write(dev, 0x609, 0x72);
++ au0828_write(dev, 0x60a, 0x71);
++ au0828_write(dev, 0x60b, 0x01);
++ ret = start_urb_transfer(dev);
++ }
++ mutex_unlock(&dvb->lock);
++ }
++
++ return ret;
++}
++
++static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed)
++{
++ struct dvb_demux *demux = feed->demux;
++ struct au0828_dev *dev = (struct au0828_dev *) demux->priv;
++ struct au0828_dvb *dvb = &dev->dvb;
++ int ret = 0;
++
++ dprintk(1, "%s()\n", __func__);
++
++ if (dvb) {
++ mutex_lock(&dvb->lock);
++ if (--dvb->feeding == 0) {
++ /* Stop transport */
++ au0828_write(dev, 0x608, 0x00);
++ au0828_write(dev, 0x609, 0x00);
++ au0828_write(dev, 0x60a, 0x00);
++ au0828_write(dev, 0x60b, 0x00);
++ ret = stop_urb_transfer(dev);
++ }
++ mutex_unlock(&dvb->lock);
++ }
++
++ return ret;
++}
++
++static int dvb_register(struct au0828_dev *dev)
++{
++ struct au0828_dvb *dvb = &dev->dvb;
++ int result;
++
++ dprintk(1, "%s()\n", __func__);
++
++ /* register adapter */
++ result = dvb_register_adapter(&dvb->adapter, DRIVER_NAME, THIS_MODULE,
++ &dev->usbdev->dev, adapter_nr);
++ if (result < 0) {
++ printk(KERN_ERR "%s: dvb_register_adapter failed "
++ "(errno = %d)\n", DRIVER_NAME, result);
++ goto fail_adapter;
++ }
++ dvb->adapter.priv = dev;
++
++ /* register frontend */
++ result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
++ if (result < 0) {
++ printk(KERN_ERR "%s: dvb_register_frontend failed "
++ "(errno = %d)\n", DRIVER_NAME, result);
++ goto fail_frontend;
++ }
++
++ /* register demux stuff */
++ dvb->demux.dmx.capabilities =
++ DMX_TS_FILTERING | DMX_SECTION_FILTERING |
++ DMX_MEMORY_BASED_FILTERING;
++ dvb->demux.priv = dev;
++ dvb->demux.filternum = 256;
++ dvb->demux.feednum = 256;
++ dvb->demux.start_feed = au0828_dvb_start_feed;
++ dvb->demux.stop_feed = au0828_dvb_stop_feed;
++ result = dvb_dmx_init(&dvb->demux);
++ if (result < 0) {
++ printk(KERN_ERR "%s: dvb_dmx_init failed (errno = %d)\n",
++ DRIVER_NAME, result);
++ goto fail_dmx;
++ }
++
++ dvb->dmxdev.filternum = 256;
++ dvb->dmxdev.demux = &dvb->demux.dmx;
++ dvb->dmxdev.capabilities = 0;
++ result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
++ if (result < 0) {
++ printk(KERN_ERR "%s: dvb_dmxdev_init failed (errno = %d)\n",
++ DRIVER_NAME, result);
++ goto fail_dmxdev;
++ }
++
++ dvb->fe_hw.source = DMX_FRONTEND_0;
++ result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
++ if (result < 0) {
++ printk(KERN_ERR "%s: add_frontend failed "
++ "(DMX_FRONTEND_0, errno = %d)\n", DRIVER_NAME, result);
++ goto fail_fe_hw;
++ }
++
++ dvb->fe_mem.source = DMX_MEMORY_FE;
++ result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
++ if (result < 0) {
++ printk(KERN_ERR "%s: add_frontend failed "
++ "(DMX_MEMORY_FE, errno = %d)\n", DRIVER_NAME, result);
++ goto fail_fe_mem;
++ }
++
++ result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
++ if (result < 0) {
++ printk(KERN_ERR "%s: connect_frontend failed (errno = %d)\n",
++ DRIVER_NAME, result);
++ goto fail_fe_conn;
++ }
++
++ /* register network adapter */
++ dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
++ return 0;
++
++fail_fe_conn:
++ dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
++fail_fe_mem:
++ dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
++fail_fe_hw:
++ dvb_dmxdev_release(&dvb->dmxdev);
++fail_dmxdev:
++ dvb_dmx_release(&dvb->demux);
++fail_dmx:
++ dvb_unregister_frontend(dvb->frontend);
++fail_frontend:
++ dvb_frontend_detach(dvb->frontend);
++ dvb_unregister_adapter(&dvb->adapter);
++fail_adapter:
++ return result;
++}
++
++void au0828_dvb_unregister(struct au0828_dev *dev)
++{
++ struct au0828_dvb *dvb = &dev->dvb;
++
++ dprintk(1, "%s()\n", __func__);
++
++ if (dvb->frontend == NULL)
++ return;
++
++ dvb_net_release(&dvb->net);
++ dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
++ dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
++ dvb_dmxdev_release(&dvb->dmxdev);
++ dvb_dmx_release(&dvb->demux);
++ dvb_unregister_frontend(dvb->frontend);
++ dvb_frontend_detach(dvb->frontend);
++ dvb_unregister_adapter(&dvb->adapter);
++}
++
++/* All the DVB attach calls go here, this function get's modified
++ * for each new card. No other function in this file needs
++ * to change.
++ */
++int au0828_dvb_register(struct au0828_dev *dev)
++{
++ struct au0828_dvb *dvb = &dev->dvb;
++ int ret;
++
++ dprintk(1, "%s()\n", __func__);
++
++ /* init frontend */
++ switch (dev->board) {
++ case AU0828_BOARD_HAUPPAUGE_HVR850:
++ case AU0828_BOARD_HAUPPAUGE_HVR950Q:
++ case AU0828_BOARD_DVICO_FUSIONHDTV7:
++ dvb->frontend = dvb_attach(au8522_attach,
++ &hauppauge_hvr950q_config,
++ &dev->i2c_adap);
++ if (dvb->frontend != NULL) {
++ hauppauge_hvr950q_tunerconfig.priv = dev;
++ dvb_attach(xc5000_attach, dvb->frontend,
++ &dev->i2c_adap,
++ &hauppauge_hvr950q_tunerconfig);
++ }
++ break;
++ default:
++ printk(KERN_WARNING "The frontend of your DVB/ATSC card "
++ "isn't supported yet\n");
++ break;
++ }
++ if (NULL == dvb->frontend) {
++ printk(KERN_ERR "%s() Frontend initialization failed\n",
++ __func__);
++ return -1;
++ }
++
++ /* Put the analog decoder in standby to keep it quiet */
++ au0828_call_i2c_clients(dev, TUNER_SET_STANDBY, NULL);
++
++ if (dvb->frontend->ops.analog_ops.standby)
++ dvb->frontend->ops.analog_ops.standby(dvb->frontend);
++
++ /* register everything */
++ ret = dvb_register(dev);
++ if (ret < 0) {
++ if (dvb->frontend->ops.release)
++ dvb->frontend->ops.release(dvb->frontend);
++ return ret;
++ }
++
++ return 0;
++}
+diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c
+new file mode 100644
+index 0000000..741a493
+--- /dev/null
++++ b/drivers/media/video/au0828/au0828-i2c.c
+@@ -0,0 +1,381 @@
++/*
++ * Driver for the Auvitek AU0828 USB bridge
++ *
++ * Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/io.h>
++
++#include "au0828.h"
++
++#include <media/v4l2-common.h>
++
++static int i2c_scan;
++module_param(i2c_scan, int, 0444);
++MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
++
++#define I2C_WAIT_DELAY 512
++#define I2C_WAIT_RETRY 64
++
++static inline int i2c_slave_did_write_ack(struct i2c_adapter *i2c_adap)
++{
++ struct au0828_dev *dev = i2c_adap->algo_data;
++ return au0828_read(dev, REG_201) & 0x08 ? 0 : 1;
++}
++
++static inline int i2c_slave_did_read_ack(struct i2c_adapter *i2c_adap)
++{
++ struct au0828_dev *dev = i2c_adap->algo_data;
++ return au0828_read(dev, REG_201) & 0x02 ? 0 : 1;
++}
++
++static int i2c_wait_read_ack(struct i2c_adapter *i2c_adap)
++{
++ int count;
++
++ for (count = 0; count < I2C_WAIT_RETRY; count++) {
++ if (!i2c_slave_did_read_ack(i2c_adap))
++ break;
++ udelay(I2C_WAIT_DELAY);
++ }
++
++ if (I2C_WAIT_RETRY == count)
++ return 0;
++
++ return 1;
++}
++
++static inline int i2c_is_read_busy(struct i2c_adapter *i2c_adap)
++{
++ struct au0828_dev *dev = i2c_adap->algo_data;
++ return au0828_read(dev, REG_201) & 0x01 ? 0 : 1;
++}
++
++static int i2c_wait_read_done(struct i2c_adapter *i2c_adap)
++{
++ int count;
++
++ for (count = 0; count < I2C_WAIT_RETRY; count++) {
++ if (!i2c_is_read_busy(i2c_adap))
++ break;
++ udelay(I2C_WAIT_DELAY);
++ }
++
++ if (I2C_WAIT_RETRY == count)
++ return 0;
++
++ return 1;
++}
++
++static inline int i2c_is_write_done(struct i2c_adapter *i2c_adap)
++{
++ struct au0828_dev *dev = i2c_adap->algo_data;
++ return au0828_read(dev, REG_201) & 0x04 ? 1 : 0;
++}
++
++static int i2c_wait_write_done(struct i2c_adapter *i2c_adap)
++{
++ int count;
++
++ for (count = 0; count < I2C_WAIT_RETRY; count++) {
++ if (i2c_is_write_done(i2c_adap))
++ break;
++ udelay(I2C_WAIT_DELAY);
++ }
++
++ if (I2C_WAIT_RETRY == count)
++ return 0;
++
++ return 1;
++}
++
++static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)
++{
++ struct au0828_dev *dev = i2c_adap->algo_data;
++ return au0828_read(dev, REG_201) & 0x10 ? 1 : 0;
++}
++
++static int i2c_wait_done(struct i2c_adapter *i2c_adap)
++{
++ int count;
++
++ for (count = 0; count < I2C_WAIT_RETRY; count++) {
++ if (!i2c_is_busy(i2c_adap))
++ break;
++ udelay(I2C_WAIT_DELAY);
++ }
++
++ if (I2C_WAIT_RETRY == count)
++ return 0;
++
++ return 1;
++}
++
++/* FIXME: Implement join handling correctly */
++static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
++ const struct i2c_msg *msg, int joined_rlen)
++{
++ int i, strobe = 0;
++ struct au0828_dev *dev = i2c_adap->algo_data;
++
++ dprintk(4, "%s()\n", __func__);
++
++ au0828_write(dev, REG_2FF, 0x01);
++ au0828_write(dev, REG_202, 0x07);
++
++ /* Hardware needs 8 bit addresses */
++ au0828_write(dev, REG_203, msg->addr << 1);
++
++ dprintk(4, "SEND: %02x\n", msg->addr);
++
++ for (i = 0; i < msg->len;) {
++
++ dprintk(4, " %02x\n", msg->buf[i]);
++
++ au0828_write(dev, REG_205, msg->buf[i]);
++
++ strobe++;
++ i++;
++
++ if ((strobe >= 4) || (i >= msg->len)) {
++
++ /* Strobe the byte into the bus */
++ if (i < msg->len)
++ au0828_write(dev, REG_200, 0x41);
++ else
++ au0828_write(dev, REG_200, 0x01);
++
++ /* Reset strobe trigger */
++ strobe = 0;
++
++ if (!i2c_wait_write_done(i2c_adap))
++ return -EIO;
++
++ }
++
++ }
++ if (!i2c_wait_done(i2c_adap))
++ return -EIO;
++
++ dprintk(4, "\n");
++
++ return msg->len;
++}
++
++/* FIXME: Implement join handling correctly */
++static int i2c_readbytes(struct i2c_adapter *i2c_adap,
++ const struct i2c_msg *msg, int joined)
++{
++ struct au0828_dev *dev = i2c_adap->algo_data;
++ int i;
++
++ dprintk(4, "%s()\n", __func__);
++
++ au0828_write(dev, REG_2FF, 0x01);
++ au0828_write(dev, REG_202, 0x07);
++
++ /* Hardware needs 8 bit addresses */
++ au0828_write(dev, REG_203, msg->addr << 1);
++
++ dprintk(4, " RECV:\n");
++
++ /* Deal with i2c_scan */
++ if (msg->len == 0) {
++ au0828_write(dev, REG_200, 0x20);
++ if (i2c_wait_read_ack(i2c_adap))
++ return -EIO;
++ return 0;
++ }
++
++ for (i = 0; i < msg->len;) {
++
++ i++;
++
++ if (i < msg->len)
++ au0828_write(dev, REG_200, 0x60);
++ else
++ au0828_write(dev, REG_200, 0x20);
++
++ if (!i2c_wait_read_done(i2c_adap))
++ return -EIO;
++
++ msg->buf[i-1] = au0828_read(dev, REG_209) & 0xff;
++
++ dprintk(4, " %02x\n", msg->buf[i-1]);
++ }
++ if (!i2c_wait_done(i2c_adap))
++ return -EIO;
++
++ dprintk(4, "\n");
++
++ return msg->len;
++}
++
++static int i2c_xfer(struct i2c_adapter *i2c_adap,
++ struct i2c_msg *msgs, int num)
++{
++ int i, retval = 0;
++
++ dprintk(4, "%s(num = %d)\n", __func__, num);
++
++ for (i = 0; i < num; i++) {
++ dprintk(4, "%s(num = %d) addr = 0x%02x len = 0x%x\n",
++ __func__, num, msgs[i].addr, msgs[i].len);
++ if (msgs[i].flags & I2C_M_RD) {
++ /* read */
++ retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
++ } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
++ msgs[i].addr == msgs[i + 1].addr) {
++ /* write then read from same address */
++ retval = i2c_sendbytes(i2c_adap, &msgs[i],
++ msgs[i + 1].len);
++ if (retval < 0)
++ goto err;
++ i++;
++ retval = i2c_readbytes(i2c_adap, &msgs[i], 1);
++ } else {
++ /* write */
++ retval = i2c_sendbytes(i2c_adap, &msgs[i], 0);
++ }
++ if (retval < 0)
++ goto err;
++ }
++ return num;
++
++err:
++ return retval;
++}
++
++static int attach_inform(struct i2c_client *client)
++{
++ dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
++ client->driver->driver.name, client->addr, client->name);
++
++ if (!client->driver->command)
++ return 0;
++
++ return 0;
++}
++
++static int detach_inform(struct i2c_client *client)
++{
++ dprintk(1, "i2c detach [client=%s]\n", client->name);
++
++ return 0;
++}
++
++void au0828_call_i2c_clients(struct au0828_dev *dev,
++ unsigned int cmd, void *arg)
++{
++ if (dev->i2c_rc != 0)
++ return;
++
++ i2c_clients_command(&dev->i2c_adap, cmd, arg);
++}
++
++static u32 au0828_functionality(struct i2c_adapter *adap)
++{
++ return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
++}
++
++static struct i2c_algorithm au0828_i2c_algo_template = {
++ .master_xfer = i2c_xfer,
++ .functionality = au0828_functionality,
++};
++
++/* ----------------------------------------------------------------------- */
++
++static struct i2c_adapter au0828_i2c_adap_template = {
++ .name = DRIVER_NAME,
++ .owner = THIS_MODULE,
++ .id = I2C_HW_B_AU0828,
++ .algo = &au0828_i2c_algo_template,
++ .class = I2C_CLASS_TV_ANALOG,
++ .client_register = attach_inform,
++ .client_unregister = detach_inform,
++};
++
++static struct i2c_client au0828_i2c_client_template = {
++ .name = "au0828 internal",
++};
++
++static char *i2c_devs[128] = {
++ [0x8e >> 1] = "au8522",
++ [0xa0 >> 1] = "eeprom",
++ [0xc2 >> 1] = "tuner/xc5000",
++};
++
++static void do_i2c_scan(char *name, struct i2c_client *c)
++{
++ unsigned char buf;
++ int i, rc;
++
++ for (i = 0; i < 128; i++) {
++ c->addr = i;
++ rc = i2c_master_recv(c, &buf, 0);
++ if (rc < 0)
++ continue;
++ printk(KERN_INFO "%s: i2c scan: found device @ 0x%x [%s]\n",
++ name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
++ }
++}
++
++/* init + register i2c algo-bit adapter */
++int au0828_i2c_register(struct au0828_dev *dev)
++{
++ dprintk(1, "%s()\n", __func__);
++
++ memcpy(&dev->i2c_adap, &au0828_i2c_adap_template,
++ sizeof(dev->i2c_adap));
++ memcpy(&dev->i2c_algo, &au0828_i2c_algo_template,
++ sizeof(dev->i2c_algo));
++ memcpy(&dev->i2c_client, &au0828_i2c_client_template,
++ sizeof(dev->i2c_client));
++
++ dev->i2c_adap.dev.parent = &dev->usbdev->dev;
++
++ strlcpy(dev->i2c_adap.name, DRIVER_NAME,
++ sizeof(dev->i2c_adap.name));
++
++ dev->i2c_algo.data = dev;
++ dev->i2c_adap.algo_data = dev;
++ i2c_set_adapdata(&dev->i2c_adap, dev);
++ i2c_add_adapter(&dev->i2c_adap);
++
++ dev->i2c_client.adapter = &dev->i2c_adap;
++
++ if (0 == dev->i2c_rc) {
++ printk(KERN_INFO "%s: i2c bus registered\n", DRIVER_NAME);
++ if (i2c_scan)
++ do_i2c_scan(DRIVER_NAME, &dev->i2c_client);
++ } else
++ printk(KERN_INFO "%s: i2c bus register FAILED\n", DRIVER_NAME);
++
++ return dev->i2c_rc;
++}
++
++int au0828_i2c_unregister(struct au0828_dev *dev)
++{
++ i2c_del_adapter(&dev->i2c_adap);
++ return 0;
++}
++
+diff --git a/drivers/media/video/au0828/au0828-reg.h b/drivers/media/video/au0828/au0828-reg.h
+new file mode 100644
+index 0000000..3982755
+--- /dev/null
++++ b/drivers/media/video/au0828/au0828-reg.h
+@@ -0,0 +1,38 @@
++/*
++ * Driver for the Auvitek USB bridge
++ *
++ * Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++/* We'll start to rename these registers once we have a better
++ * understanding of their meaning.
++ */
++#define REG_000 0x000
++#define REG_001 0x001
++#define REG_002 0x002
++#define REG_003 0x003
++
++#define REG_200 0x200
++#define REG_201 0x201
++#define REG_202 0x202
++#define REG_203 0x203
++#define REG_205 0x205
++#define REG_209 0x209
++#define REG_2FF 0x2ff
++
++#define REG_600 0x600
+diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h
+new file mode 100644
+index 0000000..7beb571
+--- /dev/null
++++ b/drivers/media/video/au0828/au0828.h
+@@ -0,0 +1,124 @@
++/*
++ * Driver for the Auvitek AU0828 USB bridge
++ *
++ * Copyright (c) 2008 Steven Toth <stoth at hauppauge.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ *
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/usb.h>
++#include <linux/i2c.h>
++#include <linux/i2c-algo-bit.h>
++#include <media/tveeprom.h>
++
++/* DVB */
++#include "demux.h"
++#include "dmxdev.h"
++#include "dvb_demux.h"
++#include "dvb_frontend.h"
++#include "dvb_net.h"
++#include "dvbdev.h"
++
++#include "au0828-reg.h"
++#include "au0828-cards.h"
++
++#define DRIVER_NAME "au0828"
++#define URB_COUNT 16
++#define URB_BUFSIZE (0xe522)
++
++struct au0828_board {
++ char *name;
++};
++
++struct au0828_dvb {
++ struct mutex lock;
++ struct dvb_adapter adapter;
++ struct dvb_frontend *frontend;
++ struct dvb_demux demux;
++ struct dmxdev dmxdev;
++ struct dmx_frontend fe_hw;
++ struct dmx_frontend fe_mem;
++ struct dvb_net net;
++ int feeding;
++};
++
++struct au0828_dev {
++ struct mutex mutex;
++ struct usb_device *usbdev;
++ int board;
++ u8 ctrlmsg[64];
++
++ /* I2C */
++ struct i2c_adapter i2c_adap;
++ struct i2c_algo_bit_data i2c_algo;
++ struct i2c_client i2c_client;
++ u32 i2c_rc;
++
++ /* Digital */
++ struct au0828_dvb dvb;
++
++ /* USB / URB Related */
++ int urb_streaming;
++ struct urb *urbs[URB_COUNT];
++
++};
++
++struct au0828_buff {
++ struct au0828_dev *dev;
++ struct urb *purb;
++ struct list_head buff_list;
++};
++
++/* ----------------------------------------------------------- */
++#define au0828_read(dev, reg) au0828_readreg(dev, reg)
++#define au0828_write(dev, reg, value) au0828_writereg(dev, reg, value)
++#define au0828_andor(dev, reg, mask, value) \
++ au0828_writereg(dev, reg, \
++ (au0828_readreg(dev, reg) & ~(mask)) | ((value) & (mask)))
++
++#define au0828_set(dev, reg, bit) au0828_andor(dev, (reg), (bit), (bit))
++#define au0828_clear(dev, reg, bit) au0828_andor(dev, (reg), (bit), 0)
++
++/* ----------------------------------------------------------- */
++/* au0828-core.c */
++extern u32 au0828_read(struct au0828_dev *dev, u16 reg);
++extern u32 au0828_write(struct au0828_dev *dev, u16 reg, u32 val);
++extern int au0828_debug;
++
++/* ----------------------------------------------------------- */
++/* au0828-cards.c */
++extern struct au0828_board au0828_boards[];
++extern struct usb_device_id au0828_usb_id_table[];
++extern void au0828_gpio_setup(struct au0828_dev *dev);
++extern int au0828_tuner_callback(void *priv, int command, int arg);
++extern void au0828_card_setup(struct au0828_dev *dev);
++
++/* ----------------------------------------------------------- */
++/* au0828-i2c.c */
++extern int au0828_i2c_register(struct au0828_dev *dev);
++extern int au0828_i2c_unregister(struct au0828_dev *dev);
++extern void au0828_call_i2c_clients(struct au0828_dev *dev,
++ unsigned int cmd, void *arg);
++
++/* ----------------------------------------------------------- */
++/* au0828-dvb.c */
++extern int au0828_dvb_register(struct au0828_dev *dev);
++extern void au0828_dvb_unregister(struct au0828_dev *dev);
++
++#define dprintk(level, fmt, arg...)\
++ do { if (au0828_debug & level)\
++ printk(KERN_DEBUG DRIVER_NAME "/0: " fmt, ## arg);\
++ } while (0)
+diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c
+index e663cc0..8bfd5c7 100644
+--- a/drivers/media/video/bt819.c
++++ b/drivers/media/video/bt819.c
+@@ -57,7 +57,7 @@ MODULE_LICENSE("GPL");
+ #define I2C_NAME(s) (s)->name
+
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c
+index 7dee2e3..98ee2d8 100644
+--- a/drivers/media/video/bt856.c
++++ b/drivers/media/video/bt856.c
+@@ -56,7 +56,7 @@ MODULE_LICENSE("GPL");
+ #define I2C_NAME(s) (s)->name
+
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c
+index 7374c02..f20a01c 100644
+--- a/drivers/media/video/bt8xx/bttv-cards.c
++++ b/drivers/media/video/bt8xx/bttv-cards.c
+@@ -71,6 +71,8 @@ static void kodicom4400r_init(struct bttv *btv);
+ static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input);
+ static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input);
+
++static void geovision_muxsel(struct bttv *btv, unsigned int input);
++
+ static int terratec_active_radio_upgrade(struct bttv *btv);
+ static int tea5757_read(struct bttv *btv);
+ static int tea5757_write(struct bttv *btv, int value);
+@@ -301,6 +303,7 @@ static struct CARD {
+ { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" },
+ { 0x00261822, BTTV_BOARD_TWINHAN_DST, "DNTV Live! Mini "},
+ { 0xd200dbc0, BTTV_BOARD_DVICO_FUSIONHDTV_2, "DViCO FusionHDTV 2" },
++ { 0x763c008a, BTTV_BOARD_GEOVISION_GV600, "GeoVision GV-600" },
+
+ { 0, -1, NULL }
+ };
+@@ -576,6 +579,8 @@ struct tvcard bttv_tvcards[] = {
+ .needs_tvaudio = 1,
+ .pll = PLL_28,
+ .tuner_type = UNSET,
++ .tuner_addr = ADDR_UNSET,
++ .radio_addr = ADDR_UNSET,
+ },
+ [BTTV_BOARD_WINVIEW_601] = {
+ .name = "Leadtek WinView 601",
+@@ -2322,7 +2327,7 @@ struct tvcard bttv_tvcards[] = {
+ .tuner = 0,
+ .svhs = 2,
+ .muxsel = { 2, 3, 1, 0 },
+- .tuner_type = TUNER_PHILIPS_ATSC,
++ .tuner_type = TUNER_PHILIPS_FCV1236D,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .has_dvb = 1,
+@@ -2961,7 +2966,7 @@ struct tvcard bttv_tvcards[] = {
+ [BTTV_BOARD_DVICO_FUSIONHDTV_2] = {
+ .name = "DViCO FusionHDTV 2",
+ .tuner = 0,
+- .tuner_type = TUNER_PHILIPS_ATSC, /* FCV1236D */
++ .tuner_type = TUNER_PHILIPS_FCV1236D,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .video_inputs = 3,
+@@ -2992,6 +2997,45 @@ struct tvcard bttv_tvcards[] = {
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ },
++ [BTTV_BOARD_GEOVISION_GV600] = {
++ /* emhn at usb.ve */
++ .name = "Geovision GV-600",
++ .video_inputs = 16,
++ .audio_inputs = 0,
++ .tuner = UNSET,
++ .svhs = UNSET,
++ .gpiomask = 0x0,
++ .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2 },
++ .muxsel_hook = geovision_muxsel,
++ .gpiomux = { 0 },
++ .no_msp34xx = 1,
++ .pll = PLL_28,
++ .tuner_type = UNSET,
++ .tuner_addr = ADDR_UNSET,
++ .radio_addr = ADDR_UNSET,
++ },
++ [BTTV_BOARD_KOZUMI_KTV_01C] = {
++ /* Mauro Lacy <mauro at lacy.com.ar>
++ * Based on MagicTV and Conceptronic CONTVFMi */
++
++ .name = "Kozumi KTV-01C",
++ .video_inputs = 3,
++ .audio_inputs = 1,
++ .tuner = 0,
++ .svhs = 2,
++ .gpiomask = 0x008007,
++ .muxsel = { 2, 3, 1, 1 },
++ .gpiomux = { 0, 1, 2, 2 }, /* CONTVFMi */
++ .gpiomute = 3, /* CONTVFMi */
++ .needs_tvaudio = 0,
++ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* TCL MK3 */
++ .tuner_addr = ADDR_UNSET,
++ .radio_addr = ADDR_UNSET,
++ .pll = PLL_28,
++ .has_radio = 1,
++ .has_remote = 1,
++ },
+ };
+
+ static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
+@@ -3331,6 +3375,13 @@ static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input)
+ gpio_bits( 3<<9, inmux<<9 );
+ }
+
++static void geovision_muxsel(struct bttv *btv, unsigned int input)
++{
++ unsigned int inmux = input % 16;
++ gpio_inout(0xf, 0xf);
++ gpio_bits(0xf, inmux);
++}
++
+ /* ----------------------------------------------------------------------- */
+
+ static void bttv_reset_audio(struct bttv *btv)
+diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
+index fcf8f2d..2ca3e9c 100644
+--- a/drivers/media/video/bt8xx/bttv-driver.c
++++ b/drivers/media/video/bt8xx/bttv-driver.c
+@@ -2372,7 +2372,7 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv,
+ if (check_btres(fh, RESOURCE_OVERLAY)) {
+ struct bttv_buffer *new;
+
+- new = videobuf_pci_alloc(sizeof(*new));
++ new = videobuf_sg_alloc(sizeof(*new));
+ new->crop = btv->crop[!!fh->do_crop].rect;
+ bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
+ retval = bttv_switch_overlay(btv,fh,new);
+@@ -2760,7 +2760,7 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)
+ mutex_lock(&fh->cap.vb_lock);
+ if (on) {
+ fh->ov.tvnorm = btv->tvnorm;
+- new = videobuf_pci_alloc(sizeof(*new));
++ new = videobuf_sg_alloc(sizeof(*new));
+ new->crop = btv->crop[!!fh->do_crop].rect;
+ bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
+ } else {
+@@ -2834,7 +2834,7 @@ static int bttv_s_fbuf(struct file *file, void *f,
+ if (check_btres(fh, RESOURCE_OVERLAY)) {
+ struct bttv_buffer *new;
+
+- new = videobuf_pci_alloc(sizeof(*new));
++ new = videobuf_sg_alloc(sizeof(*new));
+ new->crop = btv->crop[!!fh->do_crop].rect;
+ bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
+ retval = bttv_switch_overlay(btv, fh, new);
+@@ -3117,12 +3117,18 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
+
+ static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
+ {
++ if (unlikely(a->index))
++ return -EINVAL;
++
+ strcpy(a->name, "audio");
+ return 0;
+ }
+
+ static int bttv_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
+ {
++ if (unlikely(a->index))
++ return -EINVAL;
++
+ return 0;
+ }
+
+@@ -3184,7 +3190,7 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
+ /* need to capture a new frame */
+ if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM))
+ goto err;
+- fh->cap.read_buf = videobuf_pci_alloc(fh->cap.msize);
++ fh->cap.read_buf = videobuf_sg_alloc(fh->cap.msize);
+ if (NULL == fh->cap.read_buf)
+ goto err;
+ fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR;
+@@ -3251,14 +3257,14 @@ static int bttv_open(struct inode *inode, struct file *file)
+ fh->ov.setup_ok = 0;
+ v4l2_prio_open(&btv->prio,&fh->prio);
+
+- videobuf_queue_pci_init(&fh->cap, &bttv_video_qops,
+- btv->c.pci, &btv->s_lock,
++ videobuf_queue_sg_init(&fh->cap, &bttv_video_qops,
++ &btv->c.pci->dev, &btv->s_lock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct bttv_buffer),
+ fh);
+- videobuf_queue_pci_init(&fh->vbi, &bttv_vbi_qops,
+- btv->c.pci, &btv->s_lock,
++ videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops,
++ &btv->c.pci->dev, &btv->s_lock,
+ V4L2_BUF_TYPE_VBI_CAPTURE,
+ V4L2_FIELD_SEQ_TB,
+ sizeof(struct bttv_buffer),
+@@ -3457,6 +3463,9 @@ static int radio_release(struct inode *inode, struct file *file)
+ struct bttv *btv = fh->btv;
+ struct rds_command cmd;
+
++ file->private_data = NULL;
++ kfree(fh);
++
+ btv->radio_user--;
+
+ bttv_call_i2c_clients(btv, RDS_CMD_CLOSE, &cmd);
+@@ -3510,7 +3519,7 @@ static int radio_enum_input(struct file *file, void *priv,
+ return -EINVAL;
+
+ strcpy(i->name, "Radio");
+- i->type = V4L2_INPUT_TYPE_TUNER;
++ i->type = V4L2_INPUT_TYPE_TUNER;
+
+ return 0;
+ }
+@@ -3518,10 +3527,9 @@ static int radio_enum_input(struct file *file, void *priv,
+ static int radio_g_audio(struct file *file, void *priv,
+ struct v4l2_audio *a)
+ {
+- if (a->index != 0)
++ if (unlikely(a->index))
+ return -EINVAL;
+
+- memset(a, 0, sizeof(*a));
+ strcpy(a->name, "Radio");
+
+ return 0;
+@@ -3543,11 +3551,17 @@ static int radio_s_tuner(struct file *file, void *priv,
+ static int radio_s_audio(struct file *file, void *priv,
+ struct v4l2_audio *a)
+ {
++ if (unlikely(a->index))
++ return -EINVAL;
++
+ return 0;
+ }
+
+ static int radio_s_input(struct file *filp, void *priv, unsigned int i)
+ {
++ if (unlikely(i))
++ return -EINVAL;
++
+ return 0;
+ }
+
+diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c
+index fc9ecb2..a38af98 100644
+--- a/drivers/media/video/bt8xx/bttv-input.c
++++ b/drivers/media/video/bt8xx/bttv-input.c
+@@ -278,6 +278,12 @@ int bttv_input_init(struct bttv *btv)
+ ir->mask_keyup = 0x004000;
+ ir->polling = 50; /* ms */
+ break;
++ case BTTV_BOARD_KOZUMI_KTV_01C:
++ ir_codes = ir_codes_pctv_sedna;
++ ir->mask_keycode = 0x001f00;
++ ir->mask_keyup = 0x006000;
++ ir->polling = 50; /* ms */
++ break;
+ }
+ if (NULL == ir_codes) {
+ dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type);
+diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c
+index 75fa82c..bfdbc46 100644
+--- a/drivers/media/video/bt8xx/bttv-vbi.c
++++ b/drivers/media/video/bt8xx/bttv-vbi.c
+@@ -54,7 +54,7 @@
+ #define VBI_DEFLINES 16
+
+ static unsigned int vbibufs = 4;
+-static unsigned int vbi_debug = 0;
++static unsigned int vbi_debug;
+
+ module_param(vbibufs, int, 0444);
+ module_param(vbi_debug, int, 0644);
+diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h
+index bf4c339..f239320 100644
+--- a/drivers/media/video/bt8xx/bttv.h
++++ b/drivers/media/video/bt8xx/bttv.h
+@@ -19,6 +19,7 @@
+ #include <media/ir-common.h>
+ #include <media/ir-kbd-i2c.h>
+ #include <media/i2c-addr.h>
++#include <media/tuner.h>
+
+ /* ---------------------------------------------------------- */
+ /* exported by bttv-cards.c */
+@@ -173,6 +174,8 @@
+ #define BTTV_BOARD_VOODOOTV_200 0x93
+ #define BTTV_BOARD_DVICO_FUSIONHDTV_2 0x94
+ #define BTTV_BOARD_TYPHOON_TVTUNERPCI 0x95
++#define BTTV_BOARD_GEOVISION_GV600 0x96
++#define BTTV_BOARD_KOZUMI_KTV_01C 0x97
+
+
+ /* more card-specific defines */
+diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h
+index 1305d31..03816b7 100644
+--- a/drivers/media/video/bt8xx/bttvp.h
++++ b/drivers/media/video/bt8xx/bttvp.h
+@@ -42,7 +42,6 @@
+
+ #include <linux/device.h>
+ #include <media/videobuf-dma-sg.h>
+-#include <media/tuner.h>
+ #include <media/tveeprom.h>
+ #include <media/ir-common.h>
+
+diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c
+index 0322653..b364ada 100644
+--- a/drivers/media/video/bw-qcam.c
++++ b/drivers/media/video/bw-qcam.c
+@@ -523,7 +523,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[])
+ int ret=1;
+ unsigned int hi, lo;
+ unsigned int hi2, lo2;
+- static int state = 0;
++ static int state;
+
+ if (buffer == NULL)
+ {
+@@ -898,7 +898,9 @@ static const struct file_operations qcam_fops = {
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = qcam_ioctl,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .read = qcam_read,
+ .llseek = no_llseek,
+ };
+@@ -912,7 +914,7 @@ static struct video_device qcam_template=
+
+ #define MAX_CAMS 4
+ static struct qcam_device *qcams[MAX_CAMS];
+-static unsigned int num_cams = 0;
++static unsigned int num_cams;
+
+ static int init_bwqcam(struct parport *port)
+ {
+diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c
+index cf1546b..fe1e67b 100644
+--- a/drivers/media/video/c-qcam.c
++++ b/drivers/media/video/c-qcam.c
+@@ -36,6 +36,7 @@
+ #include <linux/videodev.h>
+ #include <media/v4l2-common.h>
+ #include <linux/mutex.h>
++#include <linux/jiffies.h>
+
+ #include <asm/uaccess.h>
+
+@@ -69,7 +70,7 @@ struct qcam_device {
+
+ static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 };
+ static int probe = 2;
+-static int force_rgb = 0;
++static int force_rgb;
+ static int video_nr = -1;
+
+ static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i)
+@@ -95,7 +96,8 @@ static unsigned int qcam_await_ready1(struct qcam_device *qcam,
+ unsigned long oldjiffies = jiffies;
+ unsigned int i;
+
+- for (oldjiffies = jiffies; (jiffies - oldjiffies) < msecs_to_jiffies(40); )
++ for (oldjiffies = jiffies;
++ time_before(jiffies, oldjiffies + msecs_to_jiffies(40)); )
+ if (qcam_ready1(qcam) == value)
+ return 0;
+
+@@ -120,7 +122,8 @@ static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value)
+ unsigned long oldjiffies = jiffies;
+ unsigned int i;
+
+- for (oldjiffies = jiffies; (jiffies - oldjiffies) < msecs_to_jiffies(40); )
++ for (oldjiffies = jiffies;
++ time_before(jiffies, oldjiffies + msecs_to_jiffies(40)); )
+ if (qcam_ready2(qcam) == value)
+ return 0;
+
+@@ -689,7 +692,9 @@ static const struct file_operations qcam_fops = {
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = qcam_ioctl,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .read = qcam_read,
+ .llseek = no_llseek,
+ };
+@@ -741,7 +746,7 @@ static struct qcam_device *qcam_init(struct parport *port)
+ }
+
+ static struct qcam_device *qcams[MAX_CAMS];
+-static unsigned int num_cams = 0;
++static unsigned int num_cams;
+
+ static int init_cqcam(struct parport *port)
+ {
+diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
+index 7ae499c..5195b1f 100644
+--- a/drivers/media/video/cafe_ccic.c
++++ b/drivers/media/video/cafe_ccic.c
+@@ -65,7 +65,7 @@ MODULE_SUPPORTED_DEVICE("Video");
+ */
+
+ #define MAX_DMA_BUFS 3
+-static int alloc_bufs_at_read = 0;
++static int alloc_bufs_at_read;
+ module_param(alloc_bufs_at_read, bool, 0444);
+ MODULE_PARM_DESC(alloc_bufs_at_read,
+ "Non-zero value causes DMA buffers to be allocated when the "
+@@ -99,7 +99,7 @@ MODULE_PARM_DESC(max_buffers,
+ "will be allowed to allocate. These buffers are big and live "
+ "in vmalloc space.");
+
+-static int flip = 0;
++static int flip;
+ module_param(flip, bool, 0444);
+ MODULE_PARM_DESC(flip,
+ "If set, the sensor will be instructed to flip the image "
+diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
+index 7c630f5..2a81376 100644
+--- a/drivers/media/video/cpia.c
++++ b/drivers/media/video/cpia.c
+@@ -3792,7 +3792,9 @@ static const struct file_operations cpia_fops = {
+ .read = cpia_read,
+ .mmap = cpia_mmap,
+ .ioctl = cpia_ioctl,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+diff --git a/drivers/media/video/cpia.h b/drivers/media/video/cpia.h
+index 78392fb..5096058 100644
+--- a/drivers/media/video/cpia.h
++++ b/drivers/media/video/cpia.h
+@@ -412,11 +412,11 @@ void cpia_unregister_camera(struct cam_data *cam);
+ /* ErrorCode */
+ #define ERROR_FLICKER_BELOW_MIN_EXP 0x01 /*flicker exposure got below minimum exposure */
+ #define ALOG(fmt,args...) printk(fmt, ##args)
+-#define LOG(fmt,args...) ALOG(KERN_INFO __FILE__ ":%s(%d):" fmt, __FUNCTION__ , __LINE__ , ##args)
++#define LOG(fmt,args...) ALOG(KERN_INFO __FILE__ ":%s(%d):" fmt, __func__ , __LINE__ , ##args)
+
+ #ifdef _CPIA_DEBUG_
+ #define ADBG(fmt,args...) printk(fmt, jiffies, ##args)
+-#define DBG(fmt,args...) ADBG(KERN_DEBUG __FILE__" (%ld):%s(%d):" fmt, __FUNCTION__, __LINE__ , ##args)
++#define DBG(fmt,args...) ADBG(KERN_DEBUG __FILE__" (%ld):%s(%d):" fmt, __func__, __LINE__ , ##args)
+ #else
+ #define DBG(fmn,args...) do {} while(0)
+ #endif
+diff --git a/drivers/media/video/cpia2/cpia2_core.c b/drivers/media/video/cpia2/cpia2_core.c
+index a76bd78..c8b9fdb 100644
+--- a/drivers/media/video/cpia2/cpia2_core.c
++++ b/drivers/media/video/cpia2/cpia2_core.c
+@@ -34,7 +34,7 @@
+ #include <linux/slab.h>
+ #include <linux/vmalloc.h>
+
+-//#define _CPIA2_DEBUG_
++/* #define _CPIA2_DEBUG_ */
+
+ #include "cpia2patch.h"
+
+@@ -48,7 +48,7 @@ static const char *block_name[] = {
+ };
+ #endif
+
+-static unsigned int debugs_on = 0;//DEBUG_REG;
++static unsigned int debugs_on; /* default 0 - DEBUG_REG */
+
+
+ /******************************************************************************
+@@ -570,7 +570,7 @@ int cpia2_send_command(struct camera_data *cam, struct cpia2_command *cmd)
+ block_name[block_index]);
+ break;
+ default:
+- LOG("%s: invalid request mode\n",__FUNCTION__);
++ LOG("%s: invalid request mode\n",__func__);
+ return -EINVAL;
+ }
+
+@@ -952,7 +952,7 @@ static int set_default_user_mode(struct camera_data *cam)
+ frame_rate = CPIA2_VP_FRAMERATE_30;
+ break;
+ default:
+- LOG("%s: Invalid sensor flag value 0x%0X\n",__FUNCTION__,
++ LOG("%s: Invalid sensor flag value 0x%0X\n",__func__,
+ cam->params.version.sensor_flags);
+ return -EINVAL;
+ }
+@@ -2356,12 +2356,12 @@ long cpia2_read(struct camera_data *cam,
+ }
+
+ if (!buf) {
+- ERR("%s: buffer NULL\n",__FUNCTION__);
++ ERR("%s: buffer NULL\n",__func__);
+ return -EINVAL;
+ }
+
+ if (!cam) {
+- ERR("%s: Internal error, camera_data NULL!\n",__FUNCTION__);
++ ERR("%s: Internal error, camera_data NULL!\n",__func__);
+ return -EINVAL;
+ }
+
+@@ -2370,7 +2370,7 @@ long cpia2_read(struct camera_data *cam,
+ return -ERESTARTSYS;
+
+ if (!cam->present) {
+- LOG("%s: camera removed\n",__FUNCTION__);
++ LOG("%s: camera removed\n",__func__);
+ mutex_unlock(&cam->busy_lock);
+ return 0; /* EOF */
+ }
+@@ -2434,7 +2434,7 @@ unsigned int cpia2_poll(struct camera_data *cam, struct file *filp,
+ unsigned int status=0;
+
+ if(!cam) {
+- ERR("%s: Internal error, camera_data not found!\n",__FUNCTION__);
++ ERR("%s: Internal error, camera_data not found!\n",__func__);
+ return POLLERR;
+ }
+
+diff --git a/drivers/media/video/cpia2/cpia2_usb.c b/drivers/media/video/cpia2/cpia2_usb.c
+index d8e9298..a457474 100644
+--- a/drivers/media/video/cpia2/cpia2_usb.c
++++ b/drivers/media/video/cpia2/cpia2_usb.c
+@@ -84,7 +84,7 @@ static struct usb_driver cpia2_driver = {
+ *****************************************************************************/
+ static void process_frame(struct camera_data *cam)
+ {
+- static int frame_count = 0;
++ static int frame_count;
+
+ unsigned char *inbuff = cam->workbuff->data;
+
+diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c
+index e378abe..7ce2789 100644
+--- a/drivers/media/video/cpia2/cpia2_v4l.c
++++ b/drivers/media/video/cpia2/cpia2_v4l.c
+@@ -1927,7 +1927,9 @@ static const struct file_operations fops_template = {
+ .poll = cpia2_v4l_poll,
+ .ioctl = cpia2_ioctl,
+ .llseek = no_llseek,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .mmap = cpia2_mmap,
+ };
+
+diff --git a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c
+index 9da4726..ef1f893 100644
+--- a/drivers/media/video/cpia_usb.c
++++ b/drivers/media/video/cpia_usb.c
+@@ -170,7 +170,7 @@ static void cpia_usb_complete(struct urb *urb)
+ /* resubmit */
+ urb->dev = ucpia->dev;
+ if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0)
+- printk(KERN_ERR "%s: usb_submit_urb ret %d\n", __FUNCTION__, i);
++ printk(KERN_ERR "%s: usb_submit_urb ret %d\n", __func__, i);
+ }
+
+ static int cpia_usb_open(void *privdata)
+diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig
+index 1fd326f..ca5fbce 100644
+--- a/drivers/media/video/cx23885/Kconfig
++++ b/drivers/media/video/cx23885/Kconfig
+@@ -8,6 +8,7 @@ config VIDEO_CX23885
+ select VIDEO_TVEEPROM
+ select VIDEO_IR
+ select VIDEOBUF_DVB
++ select VIDEO_CX25840
+ select DVB_TUNER_MT2131 if !DVB_FE_CUSTOMISE
+ select DVB_S5H1409 if !DVB_FE_CUSTOMISE
+ select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+@@ -16,6 +17,7 @@ config VIDEO_CX23885
+ select TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
+ select DVB_TDA18271 if !DVB_FE_CUSTOMIZE
+ select DVB_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
++ select DVB_TDA10048 if !DVB_FE_CUSTOMIZE
+ ---help---
+ This is a video4linux driver for Conexant 23885 based
+ TV cards.
+diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile
+index 32c90be..d7b0721 100644
+--- a/drivers/media/video/cx23885/Makefile
++++ b/drivers/media/video/cx23885/Makefile
+@@ -1,4 +1,4 @@
+-cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o cx23885-core.o cx23885-i2c.o cx23885-dvb.o
++cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o
+
+ obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
+
+diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c
+new file mode 100644
+index 0000000..acdd3b6
+--- /dev/null
++++ b/drivers/media/video/cx23885/cx23885-417.c
+@@ -0,0 +1,1764 @@
++/*
++ *
++ * Support for a cx23417 mpeg encoder via cx23885 host port.
++ *
++ * (c) 2004 Jelle Foks <jelle at foks.8m.com>
++ * (c) 2004 Gerd Knorr <kraxel at bytesex.org>
++ * (c) 2008 Steven Toth <stoth at hauppauge.com>
++ * - CX23885/7/8 support
++ *
++ * Includes parts from the ivtv driver( http://ivtv.sourceforge.net/),
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/init.h>
++#include <linux/fs.h>
++#include <linux/delay.h>
++#include <linux/device.h>
++#include <linux/firmware.h>
++#include <media/v4l2-common.h>
++#include <media/cx2341x.h>
++
++#include "cx23885.h"
++#include "media/cx2341x.h"
++
++#define CX23885_FIRM_IMAGE_SIZE 376836
++#define CX23885_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw"
++
++static unsigned int mpegbufs = 32;
++module_param(mpegbufs, int, 0644);
++MODULE_PARM_DESC(mpegbufs, "number of mpeg buffers, range 2-32");
++static unsigned int mpeglines = 32;
++module_param(mpeglines, int, 0644);
++MODULE_PARM_DESC(mpeglines, "number of lines in an MPEG buffer, range 2-32");
++static unsigned int mpeglinesize = 512;
++module_param(mpeglinesize, int, 0644);
++MODULE_PARM_DESC(mpeglinesize,
++ "number of bytes in each line of an MPEG buffer, range 512-1024");
++
++static unsigned int v4l_debug;
++module_param(v4l_debug, int, 0644);
++MODULE_PARM_DESC(v4l_debug, "enable V4L debug messages");
++
++#define dprintk(level, fmt, arg...)\
++ do { if (v4l_debug >= level) \
++ printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg);\
++ } while (0)
++
++static struct cx23885_tvnorm cx23885_tvnorms[] = {
++ {
++ .name = "NTSC-M",
++ .id = V4L2_STD_NTSC_M,
++ }, {
++ .name = "NTSC-JP",
++ .id = V4L2_STD_NTSC_M_JP,
++ }, {
++ .name = "PAL-BG",
++ .id = V4L2_STD_PAL_BG,
++ }, {
++ .name = "PAL-DK",
++ .id = V4L2_STD_PAL_DK,
++ }, {
++ .name = "PAL-I",
++ .id = V4L2_STD_PAL_I,
++ }, {
++ .name = "PAL-M",
++ .id = V4L2_STD_PAL_M,
++ }, {
++ .name = "PAL-N",
++ .id = V4L2_STD_PAL_N,
++ }, {
++ .name = "PAL-Nc",
++ .id = V4L2_STD_PAL_Nc,
++ }, {
++ .name = "PAL-60",
++ .id = V4L2_STD_PAL_60,
++ }, {
++ .name = "SECAM-L",
++ .id = V4L2_STD_SECAM_L,
++ }, {
++ .name = "SECAM-DK",
++ .id = V4L2_STD_SECAM_DK,
++ }
++};
++
++/* ------------------------------------------------------------------ */
++enum cx23885_capture_type {
++ CX23885_MPEG_CAPTURE,
++ CX23885_RAW_CAPTURE,
++ CX23885_RAW_PASSTHRU_CAPTURE
++};
++enum cx23885_capture_bits {
++ CX23885_RAW_BITS_NONE = 0x00,
++ CX23885_RAW_BITS_YUV_CAPTURE = 0x01,
++ CX23885_RAW_BITS_PCM_CAPTURE = 0x02,
++ CX23885_RAW_BITS_VBI_CAPTURE = 0x04,
++ CX23885_RAW_BITS_PASSTHRU_CAPTURE = 0x08,
++ CX23885_RAW_BITS_TO_HOST_CAPTURE = 0x10
++};
++enum cx23885_capture_end {
++ CX23885_END_AT_GOP, /* stop at the end of gop, generate irq */
++ CX23885_END_NOW, /* stop immediately, no irq */
++};
++enum cx23885_framerate {
++ CX23885_FRAMERATE_NTSC_30, /* NTSC: 30fps */
++ CX23885_FRAMERATE_PAL_25 /* PAL: 25fps */
++};
++enum cx23885_stream_port {
++ CX23885_OUTPUT_PORT_MEMORY,
++ CX23885_OUTPUT_PORT_STREAMING,
++ CX23885_OUTPUT_PORT_SERIAL
++};
++enum cx23885_data_xfer_status {
++ CX23885_MORE_BUFFERS_FOLLOW,
++ CX23885_LAST_BUFFER,
++};
++enum cx23885_picture_mask {
++ CX23885_PICTURE_MASK_NONE,
++ CX23885_PICTURE_MASK_I_FRAMES,
++ CX23885_PICTURE_MASK_I_P_FRAMES = 0x3,
++ CX23885_PICTURE_MASK_ALL_FRAMES = 0x7,
++};
++enum cx23885_vbi_mode_bits {
++ CX23885_VBI_BITS_SLICED,
++ CX23885_VBI_BITS_RAW,
++};
++enum cx23885_vbi_insertion_bits {
++ CX23885_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,
++ CX23885_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,
++ CX23885_VBI_BITS_SEPARATE_STREAM = 0x2 << 1,
++ CX23885_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,
++ CX23885_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,
++};
++enum cx23885_dma_unit {
++ CX23885_DMA_BYTES,
++ CX23885_DMA_FRAMES,
++};
++enum cx23885_dma_transfer_status_bits {
++ CX23885_DMA_TRANSFER_BITS_DONE = 0x01,
++ CX23885_DMA_TRANSFER_BITS_ERROR = 0x04,
++ CX23885_DMA_TRANSFER_BITS_LL_ERROR = 0x10,
++};
++enum cx23885_pause {
++ CX23885_PAUSE_ENCODING,
++ CX23885_RESUME_ENCODING,
++};
++enum cx23885_copyright {
++ CX23885_COPYRIGHT_OFF,
++ CX23885_COPYRIGHT_ON,
++};
++enum cx23885_notification_type {
++ CX23885_NOTIFICATION_REFRESH,
++};
++enum cx23885_notification_status {
++ CX23885_NOTIFICATION_OFF,
++ CX23885_NOTIFICATION_ON,
++};
++enum cx23885_notification_mailbox {
++ CX23885_NOTIFICATION_NO_MAILBOX = -1,
++};
++enum cx23885_field1_lines {
++ CX23885_FIELD1_SAA7114 = 0x00EF, /* 239 */
++ CX23885_FIELD1_SAA7115 = 0x00F0, /* 240 */
++ CX23885_FIELD1_MICRONAS = 0x0105, /* 261 */
++};
++enum cx23885_field2_lines {
++ CX23885_FIELD2_SAA7114 = 0x00EF, /* 239 */
++ CX23885_FIELD2_SAA7115 = 0x00F0, /* 240 */
++ CX23885_FIELD2_MICRONAS = 0x0106, /* 262 */
++};
++enum cx23885_custom_data_type {
++ CX23885_CUSTOM_EXTENSION_USR_DATA,
++ CX23885_CUSTOM_PRIVATE_PACKET,
++};
++enum cx23885_mute {
++ CX23885_UNMUTE,
++ CX23885_MUTE,
++};
++enum cx23885_mute_video_mask {
++ CX23885_MUTE_VIDEO_V_MASK = 0x0000FF00,
++ CX23885_MUTE_VIDEO_U_MASK = 0x00FF0000,
++ CX23885_MUTE_VIDEO_Y_MASK = 0xFF000000,
++};
++enum cx23885_mute_video_shift {
++ CX23885_MUTE_VIDEO_V_SHIFT = 8,
++ CX23885_MUTE_VIDEO_U_SHIFT = 16,
++ CX23885_MUTE_VIDEO_Y_SHIFT = 24,
++};
++
++/* defines below are from ivtv-driver.h */
++#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
++
++/* Firmware API commands */
++#define IVTV_API_STD_TIMEOUT 500
++
++/* Registers */
++/* IVTV_REG_OFFSET */
++#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8)
++#define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC)
++#define IVTV_REG_SPU (0x9050)
++#define IVTV_REG_HW_BLOCKS (0x9054)
++#define IVTV_REG_VPU (0x9058)
++#define IVTV_REG_APU (0xA064)
++
++/**** Bit definitions for MC417_RWD and MC417_OEN registers ***
++ bits 31-16
+++-----------+
++| Reserved |
+++-----------+
++ bit 15 bit 14 bit 13 bit 12 bit 11 bit 10 bit 9 bit 8
+++-------+-------+-------+-------+-------+-------+-------+-------+
++| MIWR# | MIRD# | MICS# |MIRDY# |MIADDR3|MIADDR2|MIADDR1|MIADDR0|
+++-------+-------+-------+-------+-------+-------+-------+-------+
++ bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0
+++-------+-------+-------+-------+-------+-------+-------+-------+
++|MIDATA7|MIDATA6|MIDATA5|MIDATA4|MIDATA3|MIDATA2|MIDATA1|MIDATA0|
+++-------+-------+-------+-------+-------+-------+-------+-------+
++***/
++#define MC417_MIWR 0x8000
++#define MC417_MIRD 0x4000
++#define MC417_MICS 0x2000
++#define MC417_MIRDY 0x1000
++#define MC417_MIADDR 0x0F00
++#define MC417_MIDATA 0x00FF
++
++/* MIADDR* nibble definitions */
++#define MCI_MEMORY_DATA_BYTE0 0x000
++#define MCI_MEMORY_DATA_BYTE1 0x100
++#define MCI_MEMORY_DATA_BYTE2 0x200
++#define MCI_MEMORY_DATA_BYTE3 0x300
++#define MCI_MEMORY_ADDRESS_BYTE2 0x400
++#define MCI_MEMORY_ADDRESS_BYTE1 0x500
++#define MCI_MEMORY_ADDRESS_BYTE0 0x600
++#define MCI_REGISTER_DATA_BYTE0 0x800
++#define MCI_REGISTER_DATA_BYTE1 0x900
++#define MCI_REGISTER_DATA_BYTE2 0xA00
++#define MCI_REGISTER_DATA_BYTE3 0xB00
++#define MCI_REGISTER_ADDRESS_BYTE0 0xC00
++#define MCI_REGISTER_ADDRESS_BYTE1 0xD00
++#define MCI_REGISTER_MODE 0xE00
++
++/* Read and write modes */
++#define MCI_MODE_REGISTER_READ 0
++#define MCI_MODE_REGISTER_WRITE 1
++#define MCI_MODE_MEMORY_READ 0
++#define MCI_MODE_MEMORY_WRITE 0x40
++
++/*** Bit definitions for MC417_CTL register ****
++ bits 31-6 bits 5-4 bit 3 bits 2-1 Bit 0
+++--------+-------------+--------+--------------+------------+
++|Reserved|MC417_SPD_CTL|Reserved|MC417_GPIO_SEL|UART_GPIO_EN|
+++--------+-------------+--------+--------------+------------+
++***/
++#define MC417_SPD_CTL(x) (((x) << 4) & 0x00000030)
++#define MC417_GPIO_SEL(x) (((x) << 1) & 0x00000006)
++#define MC417_UART_GPIO_EN 0x00000001
++
++/* Values for speed control */
++#define MC417_SPD_CTL_SLOW 0x1
++#define MC417_SPD_CTL_MEDIUM 0x0
++#define MC417_SPD_CTL_FAST 0x3 /* b'1x, but we use b'11 */
++
++/* Values for GPIO select */
++#define MC417_GPIO_SEL_GPIO3 0x3
++#define MC417_GPIO_SEL_GPIO2 0x2
++#define MC417_GPIO_SEL_GPIO1 0x1
++#define MC417_GPIO_SEL_GPIO0 0x0
++
++void cx23885_mc417_init(struct cx23885_dev *dev)
++{
++ u32 regval;
++
++ dprintk(2, "%s()\n", __func__);
++
++ /* Configure MC417_CTL register to defaults. */
++ regval = MC417_SPD_CTL(MC417_SPD_CTL_FAST) |
++ MC417_GPIO_SEL(MC417_GPIO_SEL_GPIO3) |
++ MC417_UART_GPIO_EN;
++ cx_write(MC417_CTL, regval);
++
++ /* Configure MC417_OEN to defaults. */
++ regval = MC417_MIRDY;
++ cx_write(MC417_OEN, regval);
++
++ /* Configure MC417_RWD to defaults. */
++ regval = MC417_MIWR | MC417_MIRD | MC417_MICS;
++ cx_write(MC417_RWD, regval);
++}
++
++static int mc417_wait_ready(struct cx23885_dev *dev)
++{
++ u32 mi_ready;
++ unsigned long timeout = jiffies + msecs_to_jiffies(1);
++
++ for (;;) {
++ mi_ready = cx_read(MC417_RWD) & MC417_MIRDY;
++ if (mi_ready != 0)
++ return 0;
++ if (time_after(jiffies, timeout))
++ return -1;
++ udelay(1);
++ }
++}
++
++static int mc417_register_write(struct cx23885_dev *dev, u16 address, u32 value)
++{
++ u32 regval;
++
++ /* Enable MC417 GPIO outputs except for MC417_MIRDY,
++ * which is an input.
++ */
++ cx_write(MC417_OEN, MC417_MIRDY);
++
++ /* Write data byte 0 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0 |
++ (value & 0x000000FF);
++ cx_write(MC417_RWD, regval);
++
++ /* Transition CS/WR to effect write transaction across bus. */
++ regval |= MC417_MICS | MC417_MIWR;
++ cx_write(MC417_RWD, regval);
++
++ /* Write data byte 1 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1 |
++ ((value >> 8) & 0x000000FF);
++ cx_write(MC417_RWD, regval);
++ regval |= MC417_MICS | MC417_MIWR;
++ cx_write(MC417_RWD, regval);
++
++ /* Write data byte 2 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2 |
++ ((value >> 16) & 0x000000FF);
++ cx_write(MC417_RWD, regval);
++ regval |= MC417_MICS | MC417_MIWR;
++ cx_write(MC417_RWD, regval);
++
++ /* Write data byte 3 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3 |
++ ((value >> 24) & 0x000000FF);
++ cx_write(MC417_RWD, regval);
++ regval |= MC417_MICS | MC417_MIWR;
++ cx_write(MC417_RWD, regval);
++
++ /* Write address byte 0 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE0 |
++ (address & 0xFF);
++ cx_write(MC417_RWD, regval);
++ regval |= MC417_MICS | MC417_MIWR;
++ cx_write(MC417_RWD, regval);
++
++ /* Write address byte 1 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE1 |
++ ((address >> 8) & 0xFF);
++ cx_write(MC417_RWD, regval);
++ regval |= MC417_MICS | MC417_MIWR;
++ cx_write(MC417_RWD, regval);
++
++ /* Indicate that this is a write. */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_MODE |
++ MCI_MODE_REGISTER_WRITE;
++ cx_write(MC417_RWD, regval);
++ regval |= MC417_MICS | MC417_MIWR;
++ cx_write(MC417_RWD, regval);
++
++ /* Wait for the trans to complete (MC417_MIRDY asserted). */
++ return mc417_wait_ready(dev);
++}
++
++static int mc417_register_read(struct cx23885_dev *dev, u16 address, u32 *value)
++{
++ int retval;
++ u32 regval;
++ u32 tempval;
++ u32 dataval;
++
++ /* Enable MC417 GPIO outputs except for MC417_MIRDY,
++ * which is an input.
++ */
++ cx_write(MC417_OEN, MC417_MIRDY);
++
++ /* Write address byte 0 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE0 |
++ ((address & 0x00FF));
++ cx_write(MC417_RWD, regval);
++ regval |= MC417_MICS | MC417_MIWR;
++ cx_write(MC417_RWD, regval);
++
++ /* Write address byte 1 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE1 |
++ ((address >> 8) & 0xFF);
++ cx_write(MC417_RWD, regval);
++ regval |= MC417_MICS | MC417_MIWR;
++ cx_write(MC417_RWD, regval);
++
++ /* Indicate that this is a register read. */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_MODE |
++ MCI_MODE_REGISTER_READ;
++ cx_write(MC417_RWD, regval);
++ regval |= MC417_MICS | MC417_MIWR;
++ cx_write(MC417_RWD, regval);
++
++ /* Wait for the trans to complete (MC417_MIRDY asserted). */
++ retval = mc417_wait_ready(dev);
++
++ /* switch the DAT0-7 GPIO[10:3] to input mode */
++ cx_write(MC417_OEN, MC417_MIRDY | MC417_MIDATA);
++
++ /* Read data byte 0 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0;
++ cx_write(MC417_RWD, regval);
++
++ /* Transition RD to effect read transaction across bus.
++ * Transtion 0x5000 -> 0x9000 correct (RD/RDY -> WR/RDY)?
++ * Should it be 0x9000 -> 0xF000 (also why is RDY being set, its
++ * input only...)
++ */
++ regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0;
++ cx_write(MC417_RWD, regval);
++
++ /* Collect byte */
++ tempval = cx_read(MC417_RWD);
++ dataval = tempval & 0x000000FF;
++
++ /* Bring CS and RD high. */
++ regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
++ cx_write(MC417_RWD, regval);
++
++ /* Read data byte 1 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1;
++ cx_write(MC417_RWD, regval);
++ regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1;
++ cx_write(MC417_RWD, regval);
++ tempval = cx_read(MC417_RWD);
++ dataval |= ((tempval & 0x000000FF) << 8);
++ regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
++ cx_write(MC417_RWD, regval);
++
++ /* Read data byte 2 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2;
++ cx_write(MC417_RWD, regval);
++ regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2;
++ cx_write(MC417_RWD, regval);
++ tempval = cx_read(MC417_RWD);
++ dataval |= ((tempval & 0x000000FF) << 16);
++ regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
++ cx_write(MC417_RWD, regval);
++
++ /* Read data byte 3 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3;
++ cx_write(MC417_RWD, regval);
++ regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3;
++ cx_write(MC417_RWD, regval);
++ tempval = cx_read(MC417_RWD);
++ dataval |= ((tempval & 0x000000FF) << 24);
++ regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
++ cx_write(MC417_RWD, regval);
++
++ *value = dataval;
++
++ return retval;
++}
++
++int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value)
++{
++ u32 regval;
++
++ /* Enable MC417 GPIO outputs except for MC417_MIRDY,
++ * which is an input.
++ */
++ cx_write(MC417_OEN, MC417_MIRDY);
++
++ /* Write data byte 0 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0 |
++ (value & 0x000000FF);
++ cx_write(MC417_RWD, regval);
++
++ /* Transition CS/WR to effect write transaction across bus. */
++ regval |= MC417_MICS | MC417_MIWR;
++ cx_write(MC417_RWD, regval);
++
++ /* Write data byte 1 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1 |
++ ((value >> 8) & 0x000000FF);
++ cx_write(MC417_RWD, regval);
++ regval |= MC417_MICS | MC417_MIWR;
++ cx_write(MC417_RWD, regval);
++
++ /* Write data byte 2 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2 |
++ ((value >> 16) & 0x000000FF);
++ cx_write(MC417_RWD, regval);
++ regval |= MC417_MICS | MC417_MIWR;
++ cx_write(MC417_RWD, regval);
++
++ /* Write data byte 3 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3 |
++ ((value >> 24) & 0x000000FF);
++ cx_write(MC417_RWD, regval);
++ regval |= MC417_MICS | MC417_MIWR;
++ cx_write(MC417_RWD, regval);
++
++ /* Write address byte 2 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE2 |
++ MCI_MODE_MEMORY_WRITE | ((address >> 16) & 0x3F);
++ cx_write(MC417_RWD, regval);
++ regval |= MC417_MICS | MC417_MIWR;
++ cx_write(MC417_RWD, regval);
++
++ /* Write address byte 1 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE1 |
++ ((address >> 8) & 0xFF);
++ cx_write(MC417_RWD, regval);
++ regval |= MC417_MICS | MC417_MIWR;
++ cx_write(MC417_RWD, regval);
++
++ /* Write address byte 0 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE0 |
++ (address & 0xFF);
++ cx_write(MC417_RWD, regval);
++ regval |= MC417_MICS | MC417_MIWR;
++ cx_write(MC417_RWD, regval);
++
++ /* Wait for the trans to complete (MC417_MIRDY asserted). */
++ return mc417_wait_ready(dev);
++}
++
++int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value)
++{
++ int retval;
++ u32 regval;
++ u32 tempval;
++ u32 dataval;
++
++ /* Enable MC417 GPIO outputs except for MC417_MIRDY,
++ * which is an input.
++ */
++ cx_write(MC417_OEN, MC417_MIRDY);
++
++ /* Write address byte 2 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE2 |
++ MCI_MODE_MEMORY_READ | ((address >> 16) & 0x3F);
++ cx_write(MC417_RWD, regval);
++ regval |= MC417_MICS | MC417_MIWR;
++ cx_write(MC417_RWD, regval);
++
++ /* Write address byte 1 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE1 |
++ ((address >> 8) & 0xFF);
++ cx_write(MC417_RWD, regval);
++ regval |= MC417_MICS | MC417_MIWR;
++ cx_write(MC417_RWD, regval);
++
++ /* Write address byte 0 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE0 |
++ (address & 0xFF);
++ cx_write(MC417_RWD, regval);
++ regval |= MC417_MICS | MC417_MIWR;
++ cx_write(MC417_RWD, regval);
++
++ /* Wait for the trans to complete (MC417_MIRDY asserted). */
++ retval = mc417_wait_ready(dev);
++
++ /* switch the DAT0-7 GPIO[10:3] to input mode */
++ cx_write(MC417_OEN, MC417_MIRDY | MC417_MIDATA);
++
++ /* Read data byte 3 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3;
++ cx_write(MC417_RWD, regval);
++
++ /* Transition RD to effect read transaction across bus. */
++ regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3;
++ cx_write(MC417_RWD, regval);
++
++ /* Collect byte */
++ tempval = cx_read(MC417_RWD);
++ dataval = ((tempval & 0x000000FF) << 24);
++
++ /* Bring CS and RD high. */
++ regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
++ cx_write(MC417_RWD, regval);
++
++ /* Read data byte 2 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2;
++ cx_write(MC417_RWD, regval);
++ regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2;
++ cx_write(MC417_RWD, regval);
++ tempval = cx_read(MC417_RWD);
++ dataval |= ((tempval & 0x000000FF) << 16);
++ regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
++ cx_write(MC417_RWD, regval);
++
++ /* Read data byte 1 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1;
++ cx_write(MC417_RWD, regval);
++ regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1;
++ cx_write(MC417_RWD, regval);
++ tempval = cx_read(MC417_RWD);
++ dataval |= ((tempval & 0x000000FF) << 8);
++ regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
++ cx_write(MC417_RWD, regval);
++
++ /* Read data byte 0 */
++ regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0;
++ cx_write(MC417_RWD, regval);
++ regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0;
++ cx_write(MC417_RWD, regval);
++ tempval = cx_read(MC417_RWD);
++ dataval |= (tempval & 0x000000FF);
++ regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
++ cx_write(MC417_RWD, regval);
++
++ *value = dataval;
++
++ return retval;
++}
++
++/* ------------------------------------------------------------------ */
++
++/* MPEG encoder API */
++char *cmd_to_str(int cmd)
++{
++ switch (cmd) {
++ case CX2341X_ENC_PING_FW:
++ return "PING_FW";
++ case CX2341X_ENC_START_CAPTURE:
++ return "START_CAPTURE";
++ case CX2341X_ENC_STOP_CAPTURE:
++ return "STOP_CAPTURE";
++ case CX2341X_ENC_SET_AUDIO_ID:
++ return "SET_AUDIO_ID";
++ case CX2341X_ENC_SET_VIDEO_ID:
++ return "SET_VIDEO_ID";
++ case CX2341X_ENC_SET_PCR_ID:
++ return "SET_PCR_PID";
++ case CX2341X_ENC_SET_FRAME_RATE:
++ return "SET_FRAME_RATE";
++ case CX2341X_ENC_SET_FRAME_SIZE:
++ return "SET_FRAME_SIZE";
++ case CX2341X_ENC_SET_BIT_RATE:
++ return "SET_BIT_RATE";
++ case CX2341X_ENC_SET_GOP_PROPERTIES:
++ return "SET_GOP_PROPERTIES";
++ case CX2341X_ENC_SET_ASPECT_RATIO:
++ return "SET_ASPECT_RATIO";
++ case CX2341X_ENC_SET_DNR_FILTER_MODE:
++ return "SET_DNR_FILTER_PROPS";
++ case CX2341X_ENC_SET_DNR_FILTER_PROPS:
++ return "SET_DNR_FILTER_PROPS";
++ case CX2341X_ENC_SET_CORING_LEVELS:
++ return "SET_CORING_LEVELS";
++ case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE:
++ return "SET_SPATIAL_FILTER_TYPE";
++ case CX2341X_ENC_SET_VBI_LINE:
++ return "SET_VBI_LINE";
++ case CX2341X_ENC_SET_STREAM_TYPE:
++ return "SET_STREAM_TYPE";
++ case CX2341X_ENC_SET_OUTPUT_PORT:
++ return "SET_OUTPUT_PORT";
++ case CX2341X_ENC_SET_AUDIO_PROPERTIES:
++ return "SET_AUDIO_PROPERTIES";
++ case CX2341X_ENC_HALT_FW:
++ return "HALT_FW";
++ case CX2341X_ENC_GET_VERSION:
++ return "GET_VERSION";
++ case CX2341X_ENC_SET_GOP_CLOSURE:
++ return "SET_GOP_CLOSURE";
++ case CX2341X_ENC_GET_SEQ_END:
++ return "GET_SEQ_END";
++ case CX2341X_ENC_SET_PGM_INDEX_INFO:
++ return "SET_PGM_INDEX_INFO";
++ case CX2341X_ENC_SET_VBI_CONFIG:
++ return "SET_VBI_CONFIG";
++ case CX2341X_ENC_SET_DMA_BLOCK_SIZE:
++ return "SET_DMA_BLOCK_SIZE";
++ case CX2341X_ENC_GET_PREV_DMA_INFO_MB_10:
++ return "GET_PREV_DMA_INFO_MB_10";
++ case CX2341X_ENC_GET_PREV_DMA_INFO_MB_9:
++ return "GET_PREV_DMA_INFO_MB_9";
++ case CX2341X_ENC_SCHED_DMA_TO_HOST:
++ return "SCHED_DMA_TO_HOST";
++ case CX2341X_ENC_INITIALIZE_INPUT:
++ return "INITIALIZE_INPUT";
++ case CX2341X_ENC_SET_FRAME_DROP_RATE:
++ return "SET_FRAME_DROP_RATE";
++ case CX2341X_ENC_PAUSE_ENCODER:
++ return "PAUSE_ENCODER";
++ case CX2341X_ENC_REFRESH_INPUT:
++ return "REFRESH_INPUT";
++ case CX2341X_ENC_SET_COPYRIGHT:
++ return "SET_COPYRIGHT";
++ case CX2341X_ENC_SET_EVENT_NOTIFICATION:
++ return "SET_EVENT_NOTIFICATION";
++ case CX2341X_ENC_SET_NUM_VSYNC_LINES:
++ return "SET_NUM_VSYNC_LINES";
++ case CX2341X_ENC_SET_PLACEHOLDER:
++ return "SET_PLACEHOLDER";
++ case CX2341X_ENC_MUTE_VIDEO:
++ return "MUTE_VIDEO";
++ case CX2341X_ENC_MUTE_AUDIO:
++ return "MUTE_AUDIO";
++ case CX2341X_ENC_MISC:
++ return "MISC";
++ default:
++ return "UNKNOWN";
++ }
++}
++
++static int cx23885_mbox_func(void *priv,
++ u32 command,
++ int in,
++ int out,
++ u32 data[CX2341X_MBOX_MAX_DATA])
++{
++ struct cx23885_dev *dev = priv;
++ unsigned long timeout;
++ u32 value, flag, retval = 0;
++ int i;
++
++ dprintk(3, "%s: command(0x%X) = %s\n", __func__, command,
++ cmd_to_str(command));
++
++ /* this may not be 100% safe if we can't read any memory location
++ without side effects */
++ mc417_memory_read(dev, dev->cx23417_mailbox - 4, &value);
++ if (value != 0x12345678) {
++ printk(KERN_ERR
++ "Firmware and/or mailbox pointer not initialized "
++ "or corrupted, signature = 0x%x, cmd = %s\n", value,
++ cmd_to_str(command));
++ return -1;
++ }
++
++ /* This read looks at 32 bits, but flag is only 8 bits.
++ * Seems we also bail if CMD or TIMEOUT bytes are set???
++ */
++ mc417_memory_read(dev, dev->cx23417_mailbox, &flag);
++ if (flag) {
++ printk(KERN_ERR "ERROR: Mailbox appears to be in use "
++ "(%x), cmd = %s\n", flag, cmd_to_str(command));
++ return -1;
++ }
++
++ flag |= 1; /* tell 'em we're working on it */
++ mc417_memory_write(dev, dev->cx23417_mailbox, flag);
++
++ /* write command + args + fill remaining with zeros */
++ /* command code */
++ mc417_memory_write(dev, dev->cx23417_mailbox + 1, command);
++ mc417_memory_write(dev, dev->cx23417_mailbox + 3,
++ IVTV_API_STD_TIMEOUT); /* timeout */
++ for (i = 0; i < in; i++) {
++ mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, data[i]);
++ dprintk(3, "API Input %d = %d\n", i, data[i]);
++ }
++ for (; i < CX2341X_MBOX_MAX_DATA; i++)
++ mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, 0);
++
++ flag |= 3; /* tell 'em we're done writing */
++ mc417_memory_write(dev, dev->cx23417_mailbox, flag);
++
++ /* wait for firmware to handle the API command */
++ timeout = jiffies + msecs_to_jiffies(10);
++ for (;;) {
++ mc417_memory_read(dev, dev->cx23417_mailbox, &flag);
++ if (0 != (flag & 4))
++ break;
++ if (time_after(jiffies, timeout)) {
++ printk(KERN_ERR "ERROR: API Mailbox timeout\n");
++ return -1;
++ }
++ udelay(10);
++ }
++
++ /* read output values */
++ for (i = 0; i < out; i++) {
++ mc417_memory_read(dev, dev->cx23417_mailbox + 4 + i, data + i);
++ dprintk(3, "API Output %d = %d\n", i, data[i]);
++ }
++
++ mc417_memory_read(dev, dev->cx23417_mailbox + 2, &retval);
++ dprintk(3, "API result = %d\n", retval);
++
++ flag = 0;
++ mc417_memory_write(dev, dev->cx23417_mailbox, flag);
++
++ return retval;
++}
++
++/* We don't need to call the API often, so using just one
++ * mailbox will probably suffice
++ */
++static int cx23885_api_cmd(struct cx23885_dev *dev,
++ u32 command,
++ u32 inputcnt,
++ u32 outputcnt,
++ ...)
++{
++ u32 data[CX2341X_MBOX_MAX_DATA];
++ va_list vargs;
++ int i, err;
++
++ dprintk(3, "%s() cmds = 0x%08x\n", __func__, command);
++
++ va_start(vargs, outputcnt);
++ for (i = 0; i < inputcnt; i++)
++ data[i] = va_arg(vargs, int);
++
++ err = cx23885_mbox_func(dev, command, inputcnt, outputcnt, data);
++ for (i = 0; i < outputcnt; i++) {
++ int *vptr = va_arg(vargs, int *);
++ *vptr = data[i];
++ }
++ va_end(vargs);
++
++ return err;
++}
++
++static int cx23885_find_mailbox(struct cx23885_dev *dev)
++{
++ u32 signature[4] = {
++ 0x12345678, 0x34567812, 0x56781234, 0x78123456
++ };
++ int signaturecnt = 0;
++ u32 value;
++ int i;
++
++ dprintk(2, "%s()\n", __func__);
++
++ for (i = 0; i < CX23885_FIRM_IMAGE_SIZE; i++) {
++ mc417_memory_read(dev, i, &value);
++ if (value == signature[signaturecnt])
++ signaturecnt++;
++ else
++ signaturecnt = 0;
++ if (4 == signaturecnt) {
++ dprintk(1, "Mailbox signature found at 0x%x\n", i+1);
++ return i+1;
++ }
++ }
++ printk(KERN_ERR "Mailbox signature values not found!\n");
++ return -1;
++}
++
++static int cx23885_load_firmware(struct cx23885_dev *dev)
++{
++ static const unsigned char magic[8] = {
++ 0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa
++ };
++ const struct firmware *firmware;
++ int i, retval = 0;
++ u32 value = 0;
++ u32 gpio_output = 0;
++ u32 checksum = 0;
++ u32 *dataptr;
++
++ dprintk(2, "%s()\n", __func__);
++
++ /* Save GPIO settings before reset of APU */
++ retval |= mc417_memory_read(dev, 0x9020, &gpio_output);
++ retval |= mc417_memory_read(dev, 0x900C, &value);
++
++ retval = mc417_register_write(dev,
++ IVTV_REG_VPU, 0xFFFFFFED);
++ retval |= mc417_register_write(dev,
++ IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
++ retval |= mc417_register_write(dev,
++ IVTV_REG_ENC_SDRAM_REFRESH, 0x80000800);
++ retval |= mc417_register_write(dev,
++ IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A);
++ retval |= mc417_register_write(dev,
++ IVTV_REG_APU, 0);
++
++ if (retval != 0) {
++ printk(KERN_ERR "%s: Error with mc417_register_write\n",
++ __func__);
++ return -1;
++ }
++
++ retval = request_firmware(&firmware, CX23885_FIRM_IMAGE_NAME,
++ &dev->pci->dev);
++
++ if (retval != 0) {
++ printk(KERN_ERR
++ "ERROR: Hotplug firmware request failed (%s).\n",
++ CX2341X_FIRM_ENC_FILENAME);
++ printk(KERN_ERR "Please fix your hotplug setup, the board will "
++ "not work without firmware loaded!\n");
++ return -1;
++ }
++
++ if (firmware->size != CX23885_FIRM_IMAGE_SIZE) {
++ printk(KERN_ERR "ERROR: Firmware size mismatch "
++ "(have %zd, expected %d)\n",
++ firmware->size, CX23885_FIRM_IMAGE_SIZE);
++ release_firmware(firmware);
++ return -1;
++ }
++
++ if (0 != memcmp(firmware->data, magic, 8)) {
++ printk(KERN_ERR
++ "ERROR: Firmware magic mismatch, wrong file?\n");
++ release_firmware(firmware);
++ return -1;
++ }
++
++ /* transfer to the chip */
++ dprintk(2, "Loading firmware ...\n");
++ dataptr = (u32 *)firmware->data;
++ for (i = 0; i < (firmware->size >> 2); i++) {
++ value = *dataptr;
++ checksum += ~value;
++ if (mc417_memory_write(dev, i, value) != 0) {
++ printk(KERN_ERR "ERROR: Loading firmware failed!\n");
++ release_firmware(firmware);
++ return -1;
++ }
++ dataptr++;
++ }
++
++ /* read back to verify with the checksum */
++ dprintk(1, "Verifying firmware ...\n");
++ for (i--; i >= 0; i--) {
++ if (mc417_memory_read(dev, i, &value) != 0) {
++ printk(KERN_ERR "ERROR: Reading firmware failed!\n");
++ release_firmware(firmware);
++ return -1;
++ }
++ checksum -= ~value;
++ }
++ if (checksum) {
++ printk(KERN_ERR
++ "ERROR: Firmware load failed (checksum mismatch).\n");
++ release_firmware(firmware);
++ return -1;
++ }
++ release_firmware(firmware);
++ dprintk(1, "Firmware upload successful.\n");
++
++ retval |= mc417_register_write(dev, IVTV_REG_HW_BLOCKS,
++ IVTV_CMD_HW_BLOCKS_RST);
++
++ /* Restore GPIO settings, make sure EIO14 is enabled as an output. */
++ dprintk(2, "%s: GPIO output EIO 0-15 was = 0x%x\n",
++ __func__, gpio_output);
++ /* Power-up seems to have GPIOs AFU. This was causing digital side
++ * to fail at power-up. Seems GPIOs should be set to 0x10ff0411 at
++ * power-up.
++ * gpio_output |= (1<<14);
++ */
++ /* Note: GPIO14 is specific to the HVR1800 here */
++ gpio_output = 0x10ff0411 | (1<<14);
++ retval |= mc417_register_write(dev, 0x9020, gpio_output | (1<<14));
++ dprintk(2, "%s: GPIO output EIO 0-15 now = 0x%x\n",
++ __func__, gpio_output);
++
++ dprintk(1, "%s: GPIO value EIO 0-15 was = 0x%x\n",
++ __func__, value);
++ value |= (1<<14);
++ dprintk(1, "%s: GPIO value EIO 0-15 now = 0x%x\n",
++ __func__, value);
++ retval |= mc417_register_write(dev, 0x900C, value);
++
++ retval |= mc417_register_read(dev, IVTV_REG_VPU, &value);
++ retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8);
++
++ if (retval < 0)
++ printk(KERN_ERR "%s: Error with mc417_register_write\n",
++ __func__);
++ return 0;
++}
++
++void cx23885_417_check_encoder(struct cx23885_dev *dev)
++{
++ u32 status, seq;
++
++ status = seq = 0;
++ cx23885_api_cmd(dev, CX2341X_ENC_GET_SEQ_END, 0, 2, &status, &seq);
++ dprintk(1, "%s() status = %d, seq = %d\n", __func__, status, seq);
++}
++
++static void cx23885_codec_settings(struct cx23885_dev *dev)
++{
++ dprintk(1, "%s()\n", __func__);
++
++ /* assign frame size */
++ cx23885_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
++ dev->ts1.height, dev->ts1.width);
++
++ dev->mpeg_params.width = dev->ts1.width;
++ dev->mpeg_params.height = dev->ts1.height;
++ dev->mpeg_params.is_50hz =
++ (dev->encodernorm.id & V4L2_STD_625_50) != 0;
++
++ cx2341x_update(dev, cx23885_mbox_func, NULL, &dev->mpeg_params);
++
++ cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 3, 1);
++ cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1);
++}
++
++static int cx23885_initialize_codec(struct cx23885_dev *dev)
++{
++ int version;
++ int retval;
++ u32 i, data[7];
++
++ dprintk(1, "%s()\n", __func__);
++
++ retval = cx23885_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
++ if (retval < 0) {
++ dprintk(2, "%s() PING OK\n", __func__);
++ retval = cx23885_load_firmware(dev);
++ if (retval < 0) {
++ printk(KERN_ERR "%s() f/w load failed\n", __func__);
++ return retval;
++ }
++ dev->cx23417_mailbox = cx23885_find_mailbox(dev);
++ if (dev->cx23417_mailbox < 0) {
++ printk(KERN_ERR "%s() mailbox < 0, error\n",
++ __func__);
++ return -1;
++ }
++ retval = cx23885_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0);
++ if (retval < 0) {
++ printk(KERN_ERR
++ "ERROR: cx23417 firmware ping failed!\n");
++ return -1;
++ }
++ retval = cx23885_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1,
++ &version);
++ if (retval < 0) {
++ printk(KERN_ERR "ERROR: cx23417 firmware get encoder :"
++ "version failed!\n");
++ return -1;
++ }
++ dprintk(1, "cx23417 firmware version is 0x%08x\n", version);
++ msleep(200);
++ }
++
++ cx23885_codec_settings(dev);
++ msleep(60);
++
++ cx23885_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0,
++ CX23885_FIELD1_SAA7115, CX23885_FIELD2_SAA7115);
++ cx23885_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0,
++ CX23885_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0);
++
++ /* Setup to capture VBI */
++ data[0] = 0x0001BD00;
++ data[1] = 1; /* frames per interrupt */
++ data[2] = 4; /* total bufs */
++ data[3] = 0x91559155; /* start codes */
++ data[4] = 0x206080C0; /* stop codes */
++ data[5] = 6; /* lines */
++ data[6] = 64; /* BPL */
++
++ cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_CONFIG, 7, 0, data[0], data[1],
++ data[2], data[3], data[4], data[5], data[6]);
++
++ for (i = 2; i <= 24; i++) {
++ int valid;
++
++ valid = ((i >= 19) && (i <= 21));
++ cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, i,
++ valid, 0 , 0, 0);
++ cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0,
++ i | 0x80000000, valid, 0, 0, 0);
++ }
++
++ cx23885_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, CX23885_UNMUTE);
++ msleep(60);
++
++ /* initialize the video input */
++ cx23885_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);
++ msleep(60);
++
++ /* Enable VIP style pixel invalidation so we work with scaled mode */
++ mc417_memory_write(dev, 2120, 0x00000080);
++
++ /* start capturing to the host interface */
++ cx23885_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
++ CX23885_MPEG_CAPTURE, CX23885_RAW_BITS_NONE);
++ msleep(10);
++
++ return 0;
++}
++
++/* ------------------------------------------------------------------ */
++
++static int bb_buf_setup(struct videobuf_queue *q,
++ unsigned int *count, unsigned int *size)
++{
++ struct cx23885_fh *fh = q->priv_data;
++
++ fh->dev->ts1.ts_packet_size = mpeglinesize;
++ fh->dev->ts1.ts_packet_count = mpeglines;
++
++ *size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count;
++ *count = mpegbufs;
++
++ return 0;
++}
++
++static int bb_buf_prepare(struct videobuf_queue *q,
++ struct videobuf_buffer *vb, enum v4l2_field field)
++{
++ struct cx23885_fh *fh = q->priv_data;
++ return cx23885_buf_prepare(q, &fh->dev->ts1,
++ (struct cx23885_buffer *)vb,
++ field);
++}
++
++static void bb_buf_queue(struct videobuf_queue *q,
++ struct videobuf_buffer *vb)
++{
++ struct cx23885_fh *fh = q->priv_data;
++ cx23885_buf_queue(&fh->dev->ts1, (struct cx23885_buffer *)vb);
++}
++
++static void bb_buf_release(struct videobuf_queue *q,
++ struct videobuf_buffer *vb)
++{
++ cx23885_free_buffer(q, (struct cx23885_buffer *)vb);
++}
++
++static struct videobuf_queue_ops cx23885_qops = {
++ .buf_setup = bb_buf_setup,
++ .buf_prepare = bb_buf_prepare,
++ .buf_queue = bb_buf_queue,
++ .buf_release = bb_buf_release,
++};
++
++/* ------------------------------------------------------------------ */
++
++static const u32 *ctrl_classes[] = {
++ cx2341x_mpeg_ctrls,
++ NULL
++};
++
++static int cx23885_queryctrl(struct cx23885_dev *dev,
++ struct v4l2_queryctrl *qctrl)
++{
++ qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
++ if (qctrl->id == 0)
++ return -EINVAL;
++
++ /* MPEG V4L2 controls */
++ if (cx2341x_ctrl_query(&dev->mpeg_params, qctrl))
++ qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
++
++ return 0;
++}
++
++static int cx23885_querymenu(struct cx23885_dev *dev,
++ struct v4l2_querymenu *qmenu)
++{
++ struct v4l2_queryctrl qctrl;
++
++ qctrl.id = qmenu->id;
++ cx23885_queryctrl(dev, &qctrl);
++ return v4l2_ctrl_query_menu(qmenu, &qctrl,
++ cx2341x_ctrl_get_menu(qmenu->id));
++}
++
++int cx23885_do_ioctl(struct inode *inode, struct file *file, int radio,
++ struct cx23885_dev *dev, unsigned int cmd, void *arg,
++ v4l2_kioctl driver_ioctl)
++{
++ int err;
++
++ switch (cmd) {
++ /* ---------- tv norms ---------- */
++ case VIDIOC_ENUMSTD:
++ {
++ struct v4l2_standard *e = arg;
++ unsigned int i;
++
++ i = e->index;
++ if (i >= ARRAY_SIZE(cx23885_tvnorms))
++ return -EINVAL;
++ err = v4l2_video_std_construct(e,
++ cx23885_tvnorms[e->index].id,
++ cx23885_tvnorms[e->index].name);
++ e->index = i;
++ if (err < 0)
++ return err;
++ return 0;
++ }
++ case VIDIOC_G_STD:
++ {
++ v4l2_std_id *id = arg;
++
++ *id = dev->encodernorm.id;
++ return 0;
++ }
++ case VIDIOC_S_STD:
++ {
++ v4l2_std_id *id = arg;
++ unsigned int i;
++
++ for (i = 0; i < ARRAY_SIZE(cx23885_tvnorms); i++)
++ if (*id & cx23885_tvnorms[i].id)
++ break;
++ if (i == ARRAY_SIZE(cx23885_tvnorms))
++ return -EINVAL;
++ dev->encodernorm = cx23885_tvnorms[i];
++
++ return 0;
++ }
++
++ /* ------ input switching ---------- */
++ case VIDIOC_ENUMINPUT:
++ {
++ struct cx23885_input *input;
++ struct v4l2_input *i = arg;
++ unsigned int n;
++
++ n = i->index;
++ if (n >= 4)
++ return -EINVAL;
++ input = &cx23885_boards[dev->board].input[n];
++ if (input->type == 0)
++ return -EINVAL;
++ memset(i, 0, sizeof(*i));
++ i->index = n;
++ /* FIXME
++ * strcpy(i->name, input->name); */
++ strcpy(i->name, "unset");
++ if (input->type == CX23885_VMUX_TELEVISION ||
++ input->type == CX23885_VMUX_CABLE)
++ i->type = V4L2_INPUT_TYPE_TUNER;
++ else
++ i->type = V4L2_INPUT_TYPE_CAMERA;
++
++ for (n = 0; n < ARRAY_SIZE(cx23885_tvnorms); n++)
++ i->std |= cx23885_tvnorms[n].id;
++ return 0;
++ }
++ case VIDIOC_G_INPUT:
++ {
++ unsigned int *i = arg;
++
++ *i = dev->input;
++ return 0;
++ }
++ case VIDIOC_S_INPUT:
++ {
++ unsigned int *i = arg;
++
++ if (*i >= 4)
++ return -EINVAL;
++
++ return 0;
++ }
++
++ /* --- tuner ioctls ------------------------------------------ */
++ case VIDIOC_G_TUNER:
++ {
++ struct v4l2_tuner *t = arg;
++
++ if (UNSET == dev->tuner_type)
++ return -EINVAL;
++ if (0 != t->index)
++ return -EINVAL;
++ memset(t, 0, sizeof(*t));
++ strcpy(t->name, "Television");
++ cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_TUNER, t);
++ cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t);
++
++ dprintk(1, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
++
++ return 0;
++ }
++ case VIDIOC_S_TUNER:
++ {
++ struct v4l2_tuner *t = arg;
++
++ if (UNSET == dev->tuner_type)
++ return -EINVAL;
++
++ /* Update the A/V core */
++ cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_TUNER, t);
++
++ return 0;
++ }
++ case VIDIOC_G_FREQUENCY:
++ {
++ struct v4l2_frequency *f = arg;
++
++ memset(f, 0, sizeof(*f));
++ if (UNSET == dev->tuner_type)
++ return -EINVAL;
++ f->type = V4L2_TUNER_ANALOG_TV;
++ f->frequency = dev->freq;
++
++ /* Assumption that tuner is always on bus 1 */
++ cx23885_call_i2c_clients(&dev->i2c_bus[1],
++ VIDIOC_G_FREQUENCY, f);
++
++ return 0;
++ }
++ case VIDIOC_S_FREQUENCY:
++ {
++ struct v4l2_frequency *f = arg;
++
++ dprintk(1, "VIDIOC_S_FREQUENCY: dev type %d, f\n",
++ dev->tuner_type);
++ dprintk(1, "VIDIOC_S_FREQUENCY: f tuner %d, f type %d\n",
++ f->tuner, f->type);
++ if (UNSET == dev->tuner_type)
++ return -EINVAL;
++ if (f->tuner != 0)
++ return -EINVAL;
++ if (f->type != V4L2_TUNER_ANALOG_TV)
++ return -EINVAL;
++ dev->freq = f->frequency;
++
++ /* Assumption that tuner is always on bus 1 */
++ cx23885_call_i2c_clients(&dev->i2c_bus[1],
++ VIDIOC_S_FREQUENCY, f);
++ return 0;
++ }
++ case VIDIOC_S_CTRL:
++ {
++ /* Update the A/V core */
++ cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_CTRL, arg);
++ return 0;
++ }
++ default:
++ /* Convert V4L ioctl to V4L2 and call mpeg_do_ioctl
++ * (driver_ioctl) */
++ return v4l_compat_translate_ioctl(inode, file, cmd, arg,
++ driver_ioctl);
++ }
++
++ return 0;
++}
++
++static int mpeg_do_ioctl(struct inode *inode, struct file *file,
++ unsigned int cmd, void *arg)
++{
++ struct cx23885_fh *fh = file->private_data;
++ struct cx23885_dev *dev = fh->dev;
++ struct cx23885_tsport *tsport = &dev->ts1;
++
++ if (v4l_debug > 1)
++ v4l_print_ioctl(dev->name, cmd);
++
++ switch (cmd) {
++
++ /* --- capabilities ------------------------------------------ */
++ case VIDIOC_QUERYCAP:
++ {
++ struct v4l2_capability *cap = arg;
++
++ memset(cap, 0, sizeof(*cap));
++ strcpy(cap->driver, dev->name);
++ strlcpy(cap->card, cx23885_boards[tsport->dev->board].name,
++ sizeof(cap->card));
++ sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
++ cap->version = CX23885_VERSION_CODE;
++ cap->capabilities =
++ V4L2_CAP_VIDEO_CAPTURE |
++ V4L2_CAP_READWRITE |
++ V4L2_CAP_STREAMING |
++ 0;
++ if (UNSET != dev->tuner_type)
++ cap->capabilities |= V4L2_CAP_TUNER;
++
++ return 0;
++ }
++
++ /* --- capture ioctls ---------------------------------------- */
++ case VIDIOC_ENUM_FMT:
++ {
++ struct v4l2_fmtdesc *f = arg;
++ int index;
++
++ index = f->index;
++ if (index != 0)
++ return -EINVAL;
++
++ memset(f, 0, sizeof(*f));
++ f->index = index;
++ strlcpy(f->description, "MPEG", sizeof(f->description));
++ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ f->pixelformat = V4L2_PIX_FMT_MPEG;
++ return 0;
++ }
++ case VIDIOC_G_FMT:
++ {
++ struct v4l2_format *f = arg;
++
++ memset(f, 0, sizeof(*f));
++ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
++ f->fmt.pix.bytesperline = 0;
++ f->fmt.pix.sizeimage =
++ dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
++ f->fmt.pix.colorspace = 0;
++ f->fmt.pix.width = dev->ts1.width;
++ f->fmt.pix.height = dev->ts1.height;
++ f->fmt.pix.field = fh->mpegq.field;
++ dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
++ dev->ts1.width, dev->ts1.height, fh->mpegq.field);
++ return 0;
++ }
++ case VIDIOC_TRY_FMT:
++ {
++ struct v4l2_format *f = arg;
++
++ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
++ f->fmt.pix.bytesperline = 0;
++ f->fmt.pix.sizeimage =
++ dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
++ f->fmt.pix.sizeimage =
++ f->fmt.pix.colorspace = 0;
++ dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
++ dev->ts1.width, dev->ts1.height, fh->mpegq.field);
++ return 0;
++ }
++ case VIDIOC_S_FMT:
++ {
++ struct v4l2_format *f = arg;
++
++ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
++ f->fmt.pix.bytesperline = 0;
++ f->fmt.pix.sizeimage =
++ dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
++ f->fmt.pix.colorspace = 0;
++ dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
++ f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
++ return 0;
++ }
++
++ /* --- streaming capture ------------------------------------- */
++ case VIDIOC_REQBUFS:
++ return videobuf_reqbufs(&fh->mpegq, arg);
++
++ case VIDIOC_QUERYBUF:
++ return videobuf_querybuf(&fh->mpegq, arg);
++
++ case VIDIOC_QBUF:
++ return videobuf_qbuf(&fh->mpegq, arg);
++
++ case VIDIOC_DQBUF:
++ return videobuf_dqbuf(&fh->mpegq, arg,
++ file->f_flags & O_NONBLOCK);
++
++ case VIDIOC_STREAMON:
++ return videobuf_streamon(&fh->mpegq);
++
++ case VIDIOC_STREAMOFF:
++ return videobuf_streamoff(&fh->mpegq);
++
++ case VIDIOC_G_EXT_CTRLS:
++ {
++ struct v4l2_ext_controls *f = arg;
++
++ if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
++ return -EINVAL;
++ return cx2341x_ext_ctrls(&dev->mpeg_params, 0, f, cmd);
++ }
++ case VIDIOC_S_EXT_CTRLS:
++ case VIDIOC_TRY_EXT_CTRLS:
++ {
++ struct v4l2_ext_controls *f = arg;
++ struct cx2341x_mpeg_params p;
++ int err;
++
++ if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
++ return -EINVAL;
++ p = dev->mpeg_params;
++ err = cx2341x_ext_ctrls(&p, 0, f, cmd);
++ if (err == 0 && cmd == VIDIOC_S_EXT_CTRLS) {
++ err = cx2341x_update(dev, cx23885_mbox_func,
++ &dev->mpeg_params, &p);
++ dev->mpeg_params = p;
++ }
++ return err;
++ }
++ case VIDIOC_S_FREQUENCY:
++ {
++ cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
++ CX23885_END_NOW, CX23885_MPEG_CAPTURE,
++ CX23885_RAW_BITS_NONE);
++ cx23885_do_ioctl(inode, file, 0, dev, cmd, arg,
++ mpeg_do_ioctl);
++ cx23885_initialize_codec(dev);
++
++ return 0;
++ }
++ case VIDIOC_LOG_STATUS:
++ {
++ char name[32 + 2];
++
++ snprintf(name, sizeof(name), "%s/2", dev->name);
++ printk(KERN_INFO
++ "%s/2: ============ START LOG STATUS ============\n",
++ dev->name);
++ cx23885_call_i2c_clients(&dev->i2c_bus[0], VIDIOC_LOG_STATUS,
++ NULL);
++ cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_LOG_STATUS,
++ NULL);
++ cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_LOG_STATUS,
++ NULL);
++ cx2341x_log_status(&dev->mpeg_params, name);
++ printk(KERN_INFO
++ "%s/2: ============= END LOG STATUS =============\n",
++ dev->name);
++ return 0;
++ }
++ case VIDIOC_QUERYMENU:
++ return cx23885_querymenu(dev, arg);
++ case VIDIOC_QUERYCTRL:
++ {
++ struct v4l2_queryctrl *c = arg;
++
++ return cx23885_queryctrl(dev, c);
++ }
++
++ default:
++ return cx23885_do_ioctl(inode, file, 0, dev, cmd, arg,
++ mpeg_do_ioctl);
++ }
++ return 0;
++}
++
++static int mpeg_ioctl(struct inode *inode, struct file *file,
++ unsigned int cmd, unsigned long arg)
++{
++ return video_usercopy(inode, file, cmd, arg, mpeg_do_ioctl);
++}
++
++static int mpeg_open(struct inode *inode, struct file *file)
++{
++ int minor = iminor(inode);
++ struct cx23885_dev *h, *dev = NULL;
++ struct list_head *list;
++ struct cx23885_fh *fh;
++
++ dprintk(2, "%s()\n", __func__);
++
++ list_for_each(list, &cx23885_devlist) {
++ h = list_entry(list, struct cx23885_dev, devlist);
++ if (h->v4l_device->minor == minor) {
++ dev = h;
++ break;
++ }
++ }
++
++ if (dev == NULL)
++ return -ENODEV;
++
++ /* allocate + initialize per filehandle data */
++ fh = kzalloc(sizeof(*fh), GFP_KERNEL);
++ if (NULL == fh)
++ return -ENOMEM;
++
++ file->private_data = fh;
++ fh->dev = dev;
++
++ videobuf_queue_sg_init(&fh->mpegq, &cx23885_qops,
++ &dev->pci->dev, &dev->ts1.slock,
++ V4L2_BUF_TYPE_VIDEO_CAPTURE,
++ V4L2_FIELD_INTERLACED,
++ sizeof(struct cx23885_buffer),
++ fh);
++
++ return 0;
++}
++
++static int mpeg_release(struct inode *inode, struct file *file)
++{
++ struct cx23885_fh *fh = file->private_data;
++ struct cx23885_dev *dev = fh->dev;
++
++ dprintk(2, "%s()\n", __func__);
++
++ /* FIXME: Review this crap */
++ /* Shut device down on last close */
++ if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {
++ if (atomic_dec_return(&dev->v4l_reader_count) == 0) {
++ /* stop mpeg capture */
++ cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
++ CX23885_END_NOW, CX23885_MPEG_CAPTURE,
++ CX23885_RAW_BITS_NONE);
++
++ msleep(500);
++ cx23885_417_check_encoder(dev);
++
++ cx23885_cancel_buffers(&fh->dev->ts1);
++ }
++ }
++
++ if (fh->mpegq.streaming)
++ videobuf_streamoff(&fh->mpegq);
++ if (fh->mpegq.reading)
++ videobuf_read_stop(&fh->mpegq);
++
++ videobuf_mmap_free(&fh->mpegq);
++ file->private_data = NULL;
++ kfree(fh);
++
++ return 0;
++}
++
++static ssize_t mpeg_read(struct file *file, char __user *data,
++ size_t count, loff_t *ppos)
++{
++ struct cx23885_fh *fh = file->private_data;
++ struct cx23885_dev *dev = fh->dev;
++
++ dprintk(2, "%s()\n", __func__);
++
++ /* Deal w/ A/V decoder * and mpeg encoder sync issues. */
++ /* Start mpeg encoder on first read. */
++ if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
++ if (atomic_inc_return(&dev->v4l_reader_count) == 1) {
++ if (cx23885_initialize_codec(dev) < 0)
++ return -EINVAL;
++ }
++ }
++
++ return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0,
++ file->f_flags & O_NONBLOCK);
++}
++
++static unsigned int mpeg_poll(struct file *file,
++ struct poll_table_struct *wait)
++{
++ struct cx23885_fh *fh = file->private_data;
++ struct cx23885_dev *dev = fh->dev;
++
++ dprintk(2, "%s\n", __func__);
++
++ return videobuf_poll_stream(file, &fh->mpegq, wait);
++}
++
++static int mpeg_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ struct cx23885_fh *fh = file->private_data;
++ struct cx23885_dev *dev = fh->dev;
++
++ dprintk(2, "%s()\n", __func__);
++
++ return videobuf_mmap_mapper(&fh->mpegq, vma);
++}
++
++static struct file_operations mpeg_fops = {
++ .owner = THIS_MODULE,
++ .open = mpeg_open,
++ .release = mpeg_release,
++ .read = mpeg_read,
++ .poll = mpeg_poll,
++ .mmap = mpeg_mmap,
++ .ioctl = mpeg_ioctl,
++ .llseek = no_llseek,
++};
++
++static struct video_device cx23885_mpeg_template = {
++ .name = "cx23885",
++ .type = VID_TYPE_CAPTURE |
++ VID_TYPE_TUNER |
++ VID_TYPE_SCALES |
++ VID_TYPE_MPEG_ENCODER,
++ .fops = &mpeg_fops,
++ .minor = -1,
++};
++
++void cx23885_417_unregister(struct cx23885_dev *dev)
++{
++ dprintk(1, "%s()\n", __func__);
++
++ if (dev->v4l_device) {
++ if (-1 != dev->v4l_device->minor)
++ video_unregister_device(dev->v4l_device);
++ else
++ video_device_release(dev->v4l_device);
++ dev->v4l_device = NULL;
++ }
++}
++
++static struct video_device *cx23885_video_dev_alloc(
++ struct cx23885_tsport *tsport,
++ struct pci_dev *pci,
++ struct video_device *template,
++ char *type)
++{
++ struct video_device *vfd;
++ struct cx23885_dev *dev = tsport->dev;
++
++ dprintk(1, "%s()\n", __func__);
++
++ vfd = video_device_alloc();
++ if (NULL == vfd)
++ return NULL;
++ *vfd = *template;
++ vfd->minor = -1;
++ snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
++ type, cx23885_boards[tsport->dev->board].name);
++ vfd->dev = &pci->dev;
++ vfd->release = video_device_release;
++ return vfd;
++}
++
++int cx23885_417_register(struct cx23885_dev *dev)
++{
++ /* FIXME: Port1 hardcoded here */
++ int err = -ENODEV;
++ struct cx23885_tsport *tsport = &dev->ts1;
++
++ dprintk(1, "%s()\n", __func__);
++
++ if (cx23885_boards[dev->board].portb != CX23885_MPEG_ENCODER)
++ return err;
++
++ /* Set default TV standard */
++ dev->encodernorm = cx23885_tvnorms[0];
++
++ if (dev->encodernorm.id & V4L2_STD_525_60)
++ tsport->height = 480;
++ else
++ tsport->height = 576;
++
++ tsport->width = 720;
++ cx2341x_fill_defaults(&dev->mpeg_params);
++
++ dev->mpeg_params.port = CX2341X_PORT_SERIAL;
++
++ /* Allocate and initialize V4L video device */
++ dev->v4l_device = cx23885_video_dev_alloc(tsport,
++ dev->pci, &cx23885_mpeg_template, "mpeg");
++ err = video_register_device(dev->v4l_device,
++ VFL_TYPE_GRABBER, -1);
++ if (err < 0) {
++ printk(KERN_INFO "%s: can't register mpeg device\n", dev->name);
++ return err;
++ }
++
++ /* Initialize MC417 registers */
++ cx23885_mc417_init(dev);
++
++ printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
++ dev->name, dev->v4l_device->minor & 0x1f);
++
++ return 0;
++}
+diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c
+index dfa2698..6ebf587 100644
+--- a/drivers/media/video/cx23885/cx23885-cards.c
++++ b/drivers/media/video/cx23885/cx23885-cards.c
+@@ -73,6 +73,7 @@ struct cx23885_board cx23885_boards[] = {
+ [CX23885_BOARD_HAUPPAUGE_HVR1800] = {
+ .name = "Hauppauge WinTV-HVR1800",
+ .porta = CX23885_ANALOG_VIDEO,
++ .portb = CX23885_MPEG_ENCODER,
+ .portc = CX23885_MPEG_DVB,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .tuner_addr = 0x42, /* 0x84 >> 1 */
+@@ -130,6 +131,18 @@ struct cx23885_board cx23885_boards[] = {
+ .name = "Hauppauge WinTV-HVR1500",
+ .portc = CX23885_MPEG_DVB,
+ },
++ [CX23885_BOARD_HAUPPAUGE_HVR1200] = {
++ .name = "Hauppauge WinTV-HVR1200",
++ .portc = CX23885_MPEG_DVB,
++ },
++ [CX23885_BOARD_HAUPPAUGE_HVR1700] = {
++ .name = "Hauppauge WinTV-HVR1700",
++ .portc = CX23885_MPEG_DVB,
++ },
++ [CX23885_BOARD_HAUPPAUGE_HVR1400] = {
++ .name = "Hauppauge WinTV-HVR1400",
++ .portc = CX23885_MPEG_DVB,
++ },
+ };
+ const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
+
+@@ -181,6 +194,18 @@ struct cx23885_subid cx23885_subids[] = {
+ .subvendor = 0x0070,
+ .subdevice = 0x7717,
+ .card = CX23885_BOARD_HAUPPAUGE_HVR1500,
++ }, {
++ .subvendor = 0x0070,
++ .subdevice = 0x71d1,
++ .card = CX23885_BOARD_HAUPPAUGE_HVR1200,
++ }, {
++ .subvendor = 0x0070,
++ .subdevice = 0x8101,
++ .card = CX23885_BOARD_HAUPPAUGE_HVR1700,
++ }, {
++ .subvendor = 0x0070,
++ .subdevice = 0x8010,
++ .card = CX23885_BOARD_HAUPPAUGE_HVR1400,
+ },
+ };
+ const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
+@@ -235,6 +260,12 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
+ case 79561: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */
+ case 79571: /* WinTV-HVR1250 (PCIe, OEM, No IR, full height, ATSC and Basic analog */
+ case 79671: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */
++ case 80019:
++ /* WinTV-HVR1400 (Express Card, Retail, IR,
++ * DVB-T and Basic analog */
++ case 81519:
++ /* WinTV-HVR1700 (PCIe, Retail, No IR, half height,
++ * DVB-T and MPEG2 HW Encoder */
+ break;
+ default:
+ printk("%s: warning: unknown hauppauge model #%d\n", dev->name, tv.model);
+@@ -264,7 +295,7 @@ int cx23885_tuner_callback(void *priv, int command, int arg)
+ }
+ else {
+ printk(KERN_ERR
+- "%s(): Unknow command.\n", __FUNCTION__);
++ "%s(): Unknow command.\n", __func__);
+ return -EINVAL;
+ }
+ break;
+@@ -306,6 +337,10 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
+ /* GPIO-15-18 cx23417 READY, CS, RD, WR */
+ /* GPIO-19 IR_RX */
+
++ /* CX23417 GPIO's */
++ /* EIO15 Zilog Reset */
++ /* EIO14 S5H1409/CX24227 Reset */
++
+ /* Force the TDA8295A into reset and back */
+ cx_set(GP0_IO, 0x00040004);
+ mdelay(20);
+@@ -314,6 +349,50 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
+ cx_set(GP0_IO, 0x00040004);
+ mdelay(20);
+ break;
++ case CX23885_BOARD_HAUPPAUGE_HVR1200:
++ /* GPIO-0 tda10048 demodulator reset */
++ /* GPIO-2 tda18271 tuner reset */
++
++ /* Put the parts into reset and back */
++ cx_set(GP0_IO, 0x00050000);
++ mdelay(20);
++ cx_clear(GP0_IO, 0x00000005);
++ mdelay(20);
++ cx_set(GP0_IO, 0x00050005);
++ break;
++ case CX23885_BOARD_HAUPPAUGE_HVR1700:
++ /* GPIO-0 TDA10048 demodulator reset */
++ /* GPIO-2 TDA8295A Reset */
++ /* GPIO-3-10 cx23417 data0-7 */
++ /* GPIO-11-14 cx23417 addr0-3 */
++ /* GPIO-15-18 cx23417 READY, CS, RD, WR */
++
++ /* The following GPIO's are on the interna AVCore (cx25840) */
++ /* GPIO-19 IR_RX */
++ /* GPIO-20 IR_TX 416/DVBT Select */
++ /* GPIO-21 IIS DAT */
++ /* GPIO-22 IIS WCLK */
++ /* GPIO-23 IIS BCLK */
++
++ /* Put the parts into reset and back */
++ cx_set(GP0_IO, 0x00050000);
++ mdelay(20);
++ cx_clear(GP0_IO, 0x00000005);
++ mdelay(20);
++ cx_set(GP0_IO, 0x00050005);
++ break;
++ case CX23885_BOARD_HAUPPAUGE_HVR1400:
++ /* GPIO-0 Dibcom7000p demodulator reset */
++ /* GPIO-2 xc3028L tuner reset */
++ /* GPIO-13 LED */
++
++ /* Put the parts into reset and back */
++ cx_set(GP0_IO, 0x00050000);
++ mdelay(20);
++ cx_clear(GP0_IO, 0x00000005);
++ mdelay(20);
++ cx_set(GP0_IO, 0x00050005);
++ break;
+ }
+ }
+
+@@ -324,6 +403,8 @@ int cx23885_ir_init(struct cx23885_dev *dev)
+ case CX23885_BOARD_HAUPPAUGE_HVR1500:
+ case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
+ case CX23885_BOARD_HAUPPAUGE_HVR1800:
++ case CX23885_BOARD_HAUPPAUGE_HVR1200:
++ case CX23885_BOARD_HAUPPAUGE_HVR1400:
+ /* FIXME: Implement me */
+ break;
+ }
+@@ -348,11 +429,14 @@ void cx23885_card_setup(struct cx23885_dev *dev)
+ case CX23885_BOARD_HAUPPAUGE_HVR1250:
+ case CX23885_BOARD_HAUPPAUGE_HVR1500:
+ case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
++ case CX23885_BOARD_HAUPPAUGE_HVR1400:
+ if (dev->i2c_bus[0].i2c_rc == 0)
+ hauppauge_eeprom(dev, eeprom+0x80);
+ break;
+ case CX23885_BOARD_HAUPPAUGE_HVR1800:
+ case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
++ case CX23885_BOARD_HAUPPAUGE_HVR1200:
++ case CX23885_BOARD_HAUPPAUGE_HVR1700:
+ if (dev->i2c_bus[0].i2c_rc == 0)
+ hauppauge_eeprom(dev, eeprom+0xc0);
+ break;
+@@ -364,17 +448,45 @@ void cx23885_card_setup(struct cx23885_dev *dev)
+ ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+ ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+ break;
++ case CX23885_BOARD_HAUPPAUGE_HVR1800:
++ /* Defaults for VID B - Analog encoder */
++ /* DREQ_POL, SMODE, PUNC_CLK, MCLK_POL Serial bus + punc clk */
++ ts1->gen_ctrl_val = 0x10e;
++ ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
++ ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
++
++ /* APB_TSVALERR_POL (active low)*/
++ ts1->vld_misc_val = 0x2000;
++ ts1->hw_sop_ctrl_val = (0x47 << 16 | 188 << 4 | 0xc);
++
++ /* Defaults for VID C */
++ ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
++ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
++ ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
++ break;
+ case CX23885_BOARD_HAUPPAUGE_HVR1250:
+ case CX23885_BOARD_HAUPPAUGE_HVR1500:
+ case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
+- case CX23885_BOARD_HAUPPAUGE_HVR1800:
+ case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
++ case CX23885_BOARD_HAUPPAUGE_HVR1200:
++ case CX23885_BOARD_HAUPPAUGE_HVR1700:
++ case CX23885_BOARD_HAUPPAUGE_HVR1400:
+ default:
+ ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
+ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+ ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+ }
+
++ /* Certain boards support analog, or require the avcore to be
++ * loaded, ensure this happens.
++ */
++ switch (dev->board) {
++ case CX23885_BOARD_HAUPPAUGE_HVR1800:
++ case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
++ case CX23885_BOARD_HAUPPAUGE_HVR1700:
++ request_module("cx25840");
++ break;
++ }
+ }
+
+ /* ------------------------------------------------------------------ */
+diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c
+index 7f10b27..f24abcd 100644
+--- a/drivers/media/video/cx23885/cx23885-core.c
++++ b/drivers/media/video/cx23885/cx23885-core.c
+@@ -190,25 +190,25 @@ static struct sram_channel cx23887_sram_channels[] = {
+ static int cx23885_risc_decode(u32 risc)
+ {
+ static char *instr[16] = {
+- [ RISC_SYNC >> 28 ] = "sync",
+- [ RISC_WRITE >> 28 ] = "write",
+- [ RISC_WRITEC >> 28 ] = "writec",
+- [ RISC_READ >> 28 ] = "read",
+- [ RISC_READC >> 28 ] = "readc",
+- [ RISC_JUMP >> 28 ] = "jump",
+- [ RISC_SKIP >> 28 ] = "skip",
+- [ RISC_WRITERM >> 28 ] = "writerm",
+- [ RISC_WRITECM >> 28 ] = "writecm",
+- [ RISC_WRITECR >> 28 ] = "writecr",
++ [RISC_SYNC >> 28] = "sync",
++ [RISC_WRITE >> 28] = "write",
++ [RISC_WRITEC >> 28] = "writec",
++ [RISC_READ >> 28] = "read",
++ [RISC_READC >> 28] = "readc",
++ [RISC_JUMP >> 28] = "jump",
++ [RISC_SKIP >> 28] = "skip",
++ [RISC_WRITERM >> 28] = "writerm",
++ [RISC_WRITECM >> 28] = "writecm",
++ [RISC_WRITECR >> 28] = "writecr",
+ };
+ static int incr[16] = {
+- [ RISC_WRITE >> 28 ] = 3,
+- [ RISC_JUMP >> 28 ] = 3,
+- [ RISC_SKIP >> 28 ] = 1,
+- [ RISC_SYNC >> 28 ] = 1,
+- [ RISC_WRITERM >> 28 ] = 3,
+- [ RISC_WRITECM >> 28 ] = 3,
+- [ RISC_WRITECR >> 28 ] = 4,
++ [RISC_WRITE >> 28] = 3,
++ [RISC_JUMP >> 28] = 3,
++ [RISC_SKIP >> 28] = 1,
++ [RISC_SYNC >> 28] = 1,
++ [RISC_WRITERM >> 28] = 3,
++ [RISC_WRITECM >> 28] = 3,
++ [RISC_WRITECR >> 28] = 4,
+ };
+ static char *bits[] = {
+ "12", "13", "14", "resync",
+@@ -260,7 +260,7 @@ void cx23885_wakeup(struct cx23885_tsport *port,
+ }
+ if (bc != 1)
+ printk("%s: %d buffers handled (should be 1)\n",
+- __FUNCTION__, bc);
++ __func__, bc);
+ }
+
+ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
+@@ -272,7 +272,7 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
+
+ if (ch->cmds_start == 0)
+ {
+- dprintk(1, "%s() Erasing channel [%s]\n", __FUNCTION__,
++ dprintk(1, "%s() Erasing channel [%s]\n", __func__,
+ ch->name);
+ cx_write(ch->ptr1_reg, 0);
+ cx_write(ch->ptr2_reg, 0);
+@@ -280,7 +280,7 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
+ cx_write(ch->cnt1_reg, 0);
+ return 0;
+ } else {
+- dprintk(1, "%s() Configuring channel [%s]\n", __FUNCTION__,
++ dprintk(1, "%s() Configuring channel [%s]\n", __func__,
+ ch->name);
+ }
+
+@@ -297,7 +297,7 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
+
+ /* write CDT */
+ for (i = 0; i < lines; i++) {
+- dprintk(2, "%s() 0x%08x <- 0x%08x\n", __FUNCTION__, cdt + 16*i,
++ dprintk(2, "%s() 0x%08x <- 0x%08x\n", __func__, cdt + 16*i,
+ ch->fifo_start + bpl*i);
+ cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
+ cx_write(cdt + 16*i + 4, 0);
+@@ -449,7 +449,7 @@ static void cx23885_shutdown(struct cx23885_dev *dev)
+
+ static void cx23885_reset(struct cx23885_dev *dev)
+ {
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+
+ cx23885_shutdown(dev);
+
+@@ -482,7 +482,7 @@ static void cx23885_reset(struct cx23885_dev *dev)
+
+ static int cx23885_pci_quirks(struct cx23885_dev *dev)
+ {
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+
+ /* The cx23885 bridge has a weird bug which causes NMI to be asserted
+ * when DMA begins if RDR_TLCTL0 bit4 is not cleared. It does not
+@@ -513,11 +513,13 @@ int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+
+ static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *port, int portno)
+ {
+- dprintk(1, "%s(portno=%d)\n", __FUNCTION__, portno);
++ dprintk(1, "%s(portno=%d)\n", __func__, portno);
+
+ /* Transport bus init dma queue - Common settings */
+ port->dma_ctl_val = 0x11; /* Enable RISC controller and Fifo */
+ port->ts_int_msk_val = 0x1111; /* TS port bits for RISC */
++ port->vld_misc_val = 0x0;
++ port->hw_sop_ctrl_val = (0x47 << 16 | 188 << 4);
+
+ spin_lock_init(&port->slock);
+ port->dev = dev;
+@@ -544,7 +546,7 @@ static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *p
+ port->reg_ts_clk_en = VID_B_TS_CLK_EN;
+ port->reg_src_sel = VID_B_SRC_SEL;
+ port->reg_ts_int_msk = VID_B_INT_MSK;
+- port->reg_ts_int_stat = VID_B_INT_STAT;
++ port->reg_ts_int_stat = VID_B_INT_STAT;
+ port->sram_chno = SRAM_CH03; /* VID_B */
+ port->pci_irqmask = 0x02; /* VID_B bit1 */
+ break;
+@@ -604,14 +606,14 @@ static void cx23885_dev_checkrevision(struct cx23885_dev *dev)
+ break;
+ default:
+ printk(KERN_ERR "%s() New hardware revision found 0x%x\n",
+- __FUNCTION__, dev->hwrevision);
++ __func__, dev->hwrevision);
+ }
+ if (dev->hwrevision)
+ printk(KERN_INFO "%s() Hardware revision = 0x%02x\n",
+- __FUNCTION__, dev->hwrevision);
++ __func__, dev->hwrevision);
+ else
+ printk(KERN_ERR "%s() Hardware revision unknown 0x%x\n",
+- __FUNCTION__, dev->hwrevision);
++ __func__, dev->hwrevision);
+ }
+
+ static int cx23885_dev_setup(struct cx23885_dev *dev)
+@@ -644,7 +646,7 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
+ BUG();
+
+ dprintk(1, "%s() Memory configured for PCIe bridge type %d\n",
+- __FUNCTION__, dev->bridge);
++ __func__, dev->bridge);
+
+ /* board config */
+ dev->board = UNSET;
+@@ -697,10 +699,12 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
+ dev->i2c_bus[2].reg_wdata = I2C3_WDATA;
+ dev->i2c_bus[2].i2c_period = (0x07 << 24); /* 1.95MHz */
+
+- if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
++ if ((cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) ||
++ (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER))
+ cx23885_init_tsport(dev, &dev->ts1, 1);
+
+- if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
++ if ((cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) ||
++ (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER))
+ cx23885_init_tsport(dev, &dev->ts2, 2);
+
+ if (get_resources(dev) < 0) {
+@@ -734,9 +738,9 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
+ dev->radio_addr = cx23885_boards[dev->board].radio_addr;
+
+ dprintk(1, "%s() tuner_type = 0x%x tuner_addr = 0x%x\n",
+- __FUNCTION__, dev->tuner_type, dev->tuner_addr);
++ __func__, dev->tuner_type, dev->tuner_addr);
+ dprintk(1, "%s() radio_type = 0x%x radio_addr = 0x%x\n",
+- __FUNCTION__, dev->radio_type, dev->radio_addr);
++ __func__, dev->radio_type, dev->radio_addr);
+
+ /* init hardware */
+ cx23885_reset(dev);
+@@ -744,28 +748,43 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
+ cx23885_i2c_register(&dev->i2c_bus[0]);
+ cx23885_i2c_register(&dev->i2c_bus[1]);
+ cx23885_i2c_register(&dev->i2c_bus[2]);
+- cx23885_call_i2c_clients (&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL);
+ cx23885_card_setup(dev);
++ cx23885_call_i2c_clients (&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL);
+ cx23885_ir_init(dev);
+
+ if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) {
+ if (cx23885_video_register(dev) < 0) {
+ printk(KERN_ERR "%s() Failed to register analog "
+- "video adapters on VID_A\n", __FUNCTION__);
++ "video adapters on VID_A\n", __func__);
+ }
+ }
+
+ if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) {
+ if (cx23885_dvb_register(&dev->ts1) < 0) {
+ printk(KERN_ERR "%s() Failed to register dvb adapters on VID_B\n",
+- __FUNCTION__);
++ __func__);
++ }
++ } else
++ if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) {
++ if (cx23885_417_register(dev) < 0) {
++ printk(KERN_ERR
++ "%s() Failed to register 417 on VID_B\n",
++ __func__);
+ }
+ }
+
+ if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) {
+ if (cx23885_dvb_register(&dev->ts2) < 0) {
+- printk(KERN_ERR "%s() Failed to register dvb adapters on VID_C\n",
+- __FUNCTION__);
++ printk(KERN_ERR
++ "%s() Failed to register dvb on VID_C\n",
++ __func__);
++ }
++ } else
++ if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER) {
++ if (cx23885_417_register(dev) < 0) {
++ printk(KERN_ERR
++ "%s() Failed to register 417 on VID_C\n",
++ __func__);
+ }
+ }
+
+@@ -785,12 +804,18 @@ static void cx23885_dev_unregister(struct cx23885_dev *dev)
+ if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO)
+ cx23885_video_unregister(dev);
+
+- if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
++ if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
+ cx23885_dvb_unregister(&dev->ts1);
+
+- if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
++ if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
++ cx23885_417_unregister(dev);
++
++ if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
+ cx23885_dvb_unregister(&dev->ts2);
+
++ if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER)
++ cx23885_417_unregister(dev);
++
+ cx23885_i2c_unregister(&dev->i2c_bus[2]);
+ cx23885_i2c_unregister(&dev->i2c_bus[1]);
+ cx23885_i2c_unregister(&dev->i2c_bus[0]);
+@@ -952,7 +977,7 @@ void cx23885_free_buffer(struct videobuf_queue *q, struct cx23885_buffer *buf)
+ videobuf_waiton(&buf->vb, 0, 0);
+ videobuf_dma_unmap(q, dma);
+ videobuf_dma_free(dma);
+- btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc);
++ btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
+ buf->vb.state = VIDEOBUF_NEEDS_INIT;
+ }
+
+@@ -960,50 +985,50 @@ static void cx23885_tsport_reg_dump(struct cx23885_tsport *port)
+ {
+ struct cx23885_dev *dev = port->dev;
+
+- dprintk(1, "%s() Register Dump\n", __FUNCTION__);
+- dprintk(1, "%s() DEV_CNTRL2 0x%08X\n", __FUNCTION__,
++ dprintk(1, "%s() Register Dump\n", __func__);
++ dprintk(1, "%s() DEV_CNTRL2 0x%08X\n", __func__,
+ cx_read(DEV_CNTRL2));
+- dprintk(1, "%s() PCI_INT_MSK 0x%08X\n", __FUNCTION__,
++ dprintk(1, "%s() PCI_INT_MSK 0x%08X\n", __func__,
+ cx_read(PCI_INT_MSK));
+- dprintk(1, "%s() AUD_INT_INT_MSK 0x%08X\n", __FUNCTION__,
++ dprintk(1, "%s() AUD_INT_INT_MSK 0x%08X\n", __func__,
+ cx_read(AUDIO_INT_INT_MSK));
+- dprintk(1, "%s() AUD_INT_DMA_CTL 0x%08X\n", __FUNCTION__,
++ dprintk(1, "%s() AUD_INT_DMA_CTL 0x%08X\n", __func__,
+ cx_read(AUD_INT_DMA_CTL));
+- dprintk(1, "%s() AUD_EXT_INT_MSK 0x%08X\n", __FUNCTION__,
++ dprintk(1, "%s() AUD_EXT_INT_MSK 0x%08X\n", __func__,
+ cx_read(AUDIO_EXT_INT_MSK));
+- dprintk(1, "%s() AUD_EXT_DMA_CTL 0x%08X\n", __FUNCTION__,
++ dprintk(1, "%s() AUD_EXT_DMA_CTL 0x%08X\n", __func__,
+ cx_read(AUD_EXT_DMA_CTL));
+- dprintk(1, "%s() PAD_CTRL 0x%08X\n", __FUNCTION__,
++ dprintk(1, "%s() PAD_CTRL 0x%08X\n", __func__,
+ cx_read(PAD_CTRL));
+- dprintk(1, "%s() ALT_PIN_OUT_SEL 0x%08X\n", __FUNCTION__,
++ dprintk(1, "%s() ALT_PIN_OUT_SEL 0x%08X\n", __func__,
+ cx_read(ALT_PIN_OUT_SEL));
+- dprintk(1, "%s() GPIO2 0x%08X\n", __FUNCTION__,
++ dprintk(1, "%s() GPIO2 0x%08X\n", __func__,
+ cx_read(GPIO2));
+- dprintk(1, "%s() gpcnt(0x%08X) 0x%08X\n", __FUNCTION__,
++ dprintk(1, "%s() gpcnt(0x%08X) 0x%08X\n", __func__,
+ port->reg_gpcnt, cx_read(port->reg_gpcnt));
+- dprintk(1, "%s() gpcnt_ctl(0x%08X) 0x%08x\n", __FUNCTION__,
++ dprintk(1, "%s() gpcnt_ctl(0x%08X) 0x%08x\n", __func__,
+ port->reg_gpcnt_ctl, cx_read(port->reg_gpcnt_ctl));
+- dprintk(1, "%s() dma_ctl(0x%08X) 0x%08x\n", __FUNCTION__,
++ dprintk(1, "%s() dma_ctl(0x%08X) 0x%08x\n", __func__,
+ port->reg_dma_ctl, cx_read(port->reg_dma_ctl));
+- dprintk(1, "%s() src_sel(0x%08X) 0x%08x\n", __FUNCTION__,
++ dprintk(1, "%s() src_sel(0x%08X) 0x%08x\n", __func__,
+ port->reg_src_sel, cx_read(port->reg_src_sel));
+- dprintk(1, "%s() lngth(0x%08X) 0x%08x\n", __FUNCTION__,
++ dprintk(1, "%s() lngth(0x%08X) 0x%08x\n", __func__,
+ port->reg_lngth, cx_read(port->reg_lngth));
+- dprintk(1, "%s() hw_sop_ctrl(0x%08X) 0x%08x\n", __FUNCTION__,
++ dprintk(1, "%s() hw_sop_ctrl(0x%08X) 0x%08x\n", __func__,
+ port->reg_hw_sop_ctrl, cx_read(port->reg_hw_sop_ctrl));
+- dprintk(1, "%s() gen_ctrl(0x%08X) 0x%08x\n", __FUNCTION__,
++ dprintk(1, "%s() gen_ctrl(0x%08X) 0x%08x\n", __func__,
+ port->reg_gen_ctrl, cx_read(port->reg_gen_ctrl));
+- dprintk(1, "%s() bd_pkt_status(0x%08X) 0x%08x\n", __FUNCTION__,
++ dprintk(1, "%s() bd_pkt_status(0x%08X) 0x%08x\n", __func__,
+ port->reg_bd_pkt_status, cx_read(port->reg_bd_pkt_status));
+- dprintk(1, "%s() sop_status(0x%08X) 0x%08x\n", __FUNCTION__,
++ dprintk(1, "%s() sop_status(0x%08X) 0x%08x\n", __func__,
+ port->reg_sop_status, cx_read(port->reg_sop_status));
+- dprintk(1, "%s() fifo_ovfl_stat(0x%08X) 0x%08x\n", __FUNCTION__,
++ dprintk(1, "%s() fifo_ovfl_stat(0x%08X) 0x%08x\n", __func__,
+ port->reg_fifo_ovfl_stat, cx_read(port->reg_fifo_ovfl_stat));
+- dprintk(1, "%s() vld_misc(0x%08X) 0x%08x\n", __FUNCTION__,
++ dprintk(1, "%s() vld_misc(0x%08X) 0x%08x\n", __func__,
+ port->reg_vld_misc, cx_read(port->reg_vld_misc));
+- dprintk(1, "%s() ts_clk_en(0x%08X) 0x%08x\n", __FUNCTION__,
++ dprintk(1, "%s() ts_clk_en(0x%08X) 0x%08x\n", __func__,
+ port->reg_ts_clk_en, cx_read(port->reg_ts_clk_en));
+- dprintk(1, "%s() ts_int_msk(0x%08X) 0x%08x\n", __FUNCTION__,
++ dprintk(1, "%s() ts_int_msk(0x%08X) 0x%08x\n", __func__,
+ port->reg_ts_int_msk, cx_read(port->reg_ts_int_msk));
+ }
+
+@@ -1012,8 +1037,9 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
+ struct cx23885_buffer *buf)
+ {
+ struct cx23885_dev *dev = port->dev;
++ u32 reg;
+
+- dprintk(1, "%s() w: %d, h: %d, f: %d\n", __FUNCTION__,
++ dprintk(1, "%s() w: %d, h: %d, f: %d\n", __func__,
+ buf->vb.width, buf->vb.height, buf->vb.field);
+
+ /* setup fifo + format */
+@@ -1031,21 +1057,24 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
+ if ( (!(cx23885_boards[dev->board].portb & CX23885_MPEG_DVB)) &&
+ (!(cx23885_boards[dev->board].portc & CX23885_MPEG_DVB)) ) {
+ printk( "%s() Failed. Unsupported value in .portb/c (0x%08x)/(0x%08x)\n",
+- __FUNCTION__,
++ __func__,
+ cx23885_boards[dev->board].portb,
+ cx23885_boards[dev->board].portc );
+ return -EINVAL;
+ }
+
++ if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
++ cx23885_av_clk(dev, 0);
++
+ udelay(100);
+
+ /* If the port supports SRC SELECT, configure it */
+ if(port->reg_src_sel)
+ cx_write(port->reg_src_sel, port->src_sel_val);
+
+- cx_write(port->reg_hw_sop_ctrl, 0x47 << 16 | 188 << 4);
++ cx_write(port->reg_hw_sop_ctrl, port->hw_sop_ctrl_val);
+ cx_write(port->reg_ts_clk_en, port->ts_clk_en_val);
+- cx_write(port->reg_vld_misc, 0x00);
++ cx_write(port->reg_vld_misc, port->vld_misc_val);
+ cx_write(port->reg_gen_ctrl, port->gen_ctrl_val);
+ udelay(100);
+
+@@ -1054,11 +1083,26 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
+ cx_write(port->reg_gpcnt_ctl, 3);
+ q->count = 1;
+
++ if (cx23885_boards[dev->board].portb & CX23885_MPEG_ENCODER) {
++
++ reg = cx_read(PAD_CTRL);
++ reg = reg & ~0x1; /* Clear TS1_OE */
++
++ /* FIXME, bit 2 writing here is questionable */
++ /* set TS1_SOP_OE and TS1_OE_HI */
++ reg = reg | 0xa;
++ cx_write(PAD_CTRL, reg);
++
++ /* FIXME and these two registers should be documented. */
++ cx_write(CLK_DELAY, cx_read(CLK_DELAY) | 0x80000011);
++ cx_write(ALT_PIN_OUT_SEL, 0x10100045);
++ }
++
+ switch(dev->bridge) {
+ case CX23885_BRIDGE_885:
+ case CX23885_BRIDGE_887:
+ /* enable irqs */
+- dprintk(1, "%s() enabling TS int's and DMA\n", __FUNCTION__ );
++ dprintk(1, "%s() enabling TS int's and DMA\n", __func__ );
+ cx_set(port->reg_ts_int_msk, port->ts_int_msk_val);
+ cx_set(port->reg_dma_ctl, port->dma_ctl_val);
+ cx_set(PCI_INT_MSK, dev->pci_irqmask | port->pci_irqmask);
+@@ -1069,6 +1113,9 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
+
+ cx_set(DEV_CNTRL2, (1<<5)); /* Enable RISC controller */
+
++ if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
++ cx23885_av_clk(dev, 1);
++
+ if (debug > 4)
+ cx23885_tsport_reg_dump(port);
+
+@@ -1078,12 +1125,32 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
+ static int cx23885_stop_dma(struct cx23885_tsport *port)
+ {
+ struct cx23885_dev *dev = port->dev;
+- dprintk(1, "%s()\n", __FUNCTION__);
++ u32 reg;
++
++ dprintk(1, "%s()\n", __func__);
+
+ /* Stop interrupts and DMA */
+ cx_clear(port->reg_ts_int_msk, port->ts_int_msk_val);
+ cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
+
++ if (cx23885_boards[dev->board].portb & CX23885_MPEG_ENCODER) {
++
++ reg = cx_read(PAD_CTRL);
++
++ /* Set TS1_OE */
++ reg = reg | 0x1;
++
++ /* clear TS1_SOP_OE and TS1_OE_HI */
++ reg = reg & ~0xa;
++ cx_write(PAD_CTRL, reg);
++ cx_write(port->reg_src_sel, 0);
++ cx_write(port->reg_gen_ctrl, 8);
++
++ }
++
++ if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
++ cx23885_av_clk(dev, 0);
++
+ return 0;
+ }
+
+@@ -1093,13 +1160,13 @@ int cx23885_restart_queue(struct cx23885_tsport *port,
+ struct cx23885_dev *dev = port->dev;
+ struct cx23885_buffer *buf;
+
+- dprintk(5, "%s()\n", __FUNCTION__);
++ dprintk(5, "%s()\n", __func__);
+ if (list_empty(&q->active))
+ {
+ struct cx23885_buffer *prev;
+ prev = NULL;
+
+- dprintk(5, "%s() queue is empty\n", __FUNCTION__);
++ dprintk(5, "%s() queue is empty\n", __func__);
+
+ for (;;) {
+ if (list_empty(&q->queued))
+@@ -1154,7 +1221,7 @@ int cx23885_buf_prepare(struct videobuf_queue *q, struct cx23885_tsport *port,
+ int size = port->ts_packet_size * port->ts_packet_count;
+ int rc;
+
+- dprintk(1, "%s: %p\n", __FUNCTION__, buf);
++ dprintk(1, "%s: %p\n", __func__, buf);
+ if (0 != buf->vb.baddr && buf->vb.bsize < size)
+ return -EINVAL;
+
+@@ -1197,7 +1264,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
+ buf->count = cx88q->count++;
+ mod_timer(&cx88q->timeout, jiffies + BUFFER_TIMEOUT);
+ dprintk(1, "[%p/%d] %s - first active\n",
+- buf, buf->vb.i, __FUNCTION__);
++ buf, buf->vb.i, __func__);
+ } else {
+ dprintk( 1, "queue is not empty - append to active\n" );
+ prev = list_entry(cx88q->active.prev, struct cx23885_buffer,
+@@ -1208,7 +1275,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
+ prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+ prev->risc.jmp[2] = cpu_to_le32(0); /* 64 bit bits 63-32 */
+ dprintk( 1, "[%p/%d] %s - append to active\n",
+- buf, buf->vb.i, __FUNCTION__);
++ buf, buf->vb.i, __func__);
+ }
+ }
+
+@@ -1239,13 +1306,23 @@ static void do_cancel_buffers(struct cx23885_tsport *port, char *reason,
+ spin_unlock_irqrestore(&port->slock, flags);
+ }
+
++void cx23885_cancel_buffers(struct cx23885_tsport *port)
++{
++ struct cx23885_dev *dev = port->dev;
++ struct cx23885_dmaqueue *q = &port->mpegq;
++
++ dprintk(1, "%s()\n", __FUNCTION__);
++ del_timer_sync(&q->timeout);
++ cx23885_stop_dma(port);
++ do_cancel_buffers(port, "cancel", 0);
++}
+
+ static void cx23885_timeout(unsigned long data)
+ {
+ struct cx23885_tsport *port = (struct cx23885_tsport *)data;
+ struct cx23885_dev *dev = port->dev;
+
+- dprintk(1, "%s()\n",__FUNCTION__);
++ dprintk(1, "%s()\n",__func__);
+
+ if (debug > 5)
+ cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ]);
+@@ -1254,16 +1331,77 @@ static void cx23885_timeout(unsigned long data)
+ do_cancel_buffers(port, "timeout", 1);
+ }
+
++int cx23885_irq_417(struct cx23885_dev *dev, u32 status)
++{
++ /* FIXME: port1 assumption here. */
++ struct cx23885_tsport *port = &dev->ts1;
++ int count = 0;
++ int handled = 0;
++
++ if (status == 0)
++ return handled;
++
++ count = cx_read(port->reg_gpcnt);
++ dprintk(7, "status: 0x%08x mask: 0x%08x count: 0x%x\n",
++ status, cx_read(port->reg_ts_int_msk), count);
++
++ if ((status & VID_B_MSK_BAD_PKT) ||
++ (status & VID_B_MSK_OPC_ERR) ||
++ (status & VID_B_MSK_VBI_OPC_ERR) ||
++ (status & VID_B_MSK_SYNC) ||
++ (status & VID_B_MSK_VBI_SYNC) ||
++ (status & VID_B_MSK_OF) ||
++ (status & VID_B_MSK_VBI_OF)) {
++ printk(KERN_ERR "%s: V4L mpeg risc op code error, status "
++ "= 0x%x\n", dev->name, status);
++ if (status & VID_B_MSK_BAD_PKT)
++ dprintk(1, " VID_B_MSK_BAD_PKT\n");
++ if (status & VID_B_MSK_OPC_ERR)
++ dprintk(1, " VID_B_MSK_OPC_ERR\n");
++ if (status & VID_B_MSK_VBI_OPC_ERR)
++ dprintk(1, " VID_B_MSK_VBI_OPC_ERR\n");
++ if (status & VID_B_MSK_SYNC)
++ dprintk(1, " VID_B_MSK_SYNC\n");
++ if (status & VID_B_MSK_VBI_SYNC)
++ dprintk(1, " VID_B_MSK_VBI_SYNC\n");
++ if (status & VID_B_MSK_OF)
++ dprintk(1, " VID_B_MSK_OF\n");
++ if (status & VID_B_MSK_VBI_OF)
++ dprintk(1, " VID_B_MSK_VBI_OF\n");
++
++ cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
++ cx23885_sram_channel_dump(dev,
++ &dev->sram_channels[port->sram_chno]);
++ cx23885_417_check_encoder(dev);
++ } else if (status & VID_B_MSK_RISCI1) {
++ dprintk(7, " VID_B_MSK_RISCI1\n");
++ spin_lock(&port->slock);
++ cx23885_wakeup(port, &port->mpegq, count);
++ spin_unlock(&port->slock);
++ } else if (status & VID_B_MSK_RISCI2) {
++ dprintk(7, " VID_B_MSK_RISCI2\n");
++ spin_lock(&port->slock);
++ cx23885_restart_queue(port, &port->mpegq);
++ spin_unlock(&port->slock);
++ }
++ if (status) {
++ cx_write(port->reg_ts_int_stat, status);
++ handled = 1;
++ }
++
++ return handled;
++}
++
+ static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status)
+ {
+ struct cx23885_dev *dev = port->dev;
+ int handled = 0;
+ u32 count;
+
+- if ( (status & VID_BC_MSK_OPC_ERR) ||
+- (status & VID_BC_MSK_BAD_PKT) ||
+- (status & VID_BC_MSK_SYNC) ||
+- (status & VID_BC_MSK_OF))
++ if ((status & VID_BC_MSK_OPC_ERR) ||
++ (status & VID_BC_MSK_BAD_PKT) ||
++ (status & VID_BC_MSK_SYNC) ||
++ (status & VID_BC_MSK_OF))
+ {
+ if (status & VID_BC_MSK_OPC_ERR)
+ dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n", VID_BC_MSK_OPC_ERR);
+@@ -1277,7 +1415,8 @@ static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status)
+ printk(KERN_ERR "%s: mpeg risc op code error\n", dev->name);
+
+ cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
+- cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ]);
++ cx23885_sram_channel_dump(dev,
++ &dev->sram_channels[port->sram_chno]);
+
+ } else if (status & VID_BC_MSK_RISCI1) {
+
+@@ -1378,11 +1517,17 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
+ if (ts1_status) {
+ if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
+ handled += cx23885_irq_ts(ts1, ts1_status);
++ else
++ if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
++ handled += cx23885_irq_417(dev, ts1_status);
+ }
+
+ if (ts2_status) {
+ if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
+ handled += cx23885_irq_ts(ts2, ts2_status);
++ else
++ if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER)
++ handled += cx23885_irq_417(dev, ts2_status);
+ }
+
+ if (vida_status)
+@@ -1422,7 +1567,8 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev,
+ printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, "
+ "latency: %d, mmio: 0x%llx\n", dev->name,
+ pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
+- dev->pci_lat, (unsigned long long)pci_resource_start(pci_dev,0));
++ dev->pci_lat,
++ (unsigned long long)pci_resource_start(pci_dev, 0));
+
+ pci_set_master(pci_dev);
+ if (!pci_dma_supported(pci_dev, 0xffffffff)) {
+diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c
+index ed465c0..f056497 100644
+--- a/drivers/media/video/cx23885/cx23885-dvb.c
++++ b/drivers/media/video/cx23885/cx23885-dvb.c
+@@ -36,9 +36,12 @@
+ #include "tda18271.h"
+ #include "lgdt330x.h"
+ #include "xc5000.h"
++#include "tda10048.h"
+ #include "dvb-pll.h"
+ #include "tuner-xc2028.h"
+-#include "tuner-xc2028-types.h"
++#include "tuner-simple.h"
++#include "dib7000p.h"
++#include "dibx000_common.h"
+
+ static unsigned int debug;
+
+@@ -53,6 +56,8 @@ static unsigned int alt_tuner;
+ module_param(alt_tuner, int, 0644);
+ MODULE_PARM_DESC(alt_tuner, "Enable alternate tuner configuration");
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ /* ------------------------------------------------------------------ */
+
+ static int dvb_buf_setup(struct videobuf_queue *q,
+@@ -104,6 +109,13 @@ static struct s5h1409_config hauppauge_generic_config = {
+ .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+ };
+
++static struct tda10048_config hauppauge_hvr1200_config = {
++ .demod_address = 0x10 >> 1,
++ .output_mode = TDA10048_SERIAL_OUTPUT,
++ .fwbulkwritelen = TDA10048_BULKWRITE_200,
++ .inversion = TDA10048_INVERSION_ON
++};
++
+ static struct s5h1409_config hauppauge_ezqam_config = {
+ .demod_address = 0x32 >> 1,
+ .output_mode = S5H1409_SERIAL_OUTPUT,
+@@ -164,8 +176,10 @@ static struct tda829x_config tda829x_no_probe = {
+ };
+
+ static struct tda18271_std_map hauppauge_tda18271_std_map = {
+- .atsc_6 = { .if_freq = 5380, .std_bits = 0x1b },
+- .qam_6 = { .if_freq = 4000, .std_bits = 0x18 },
++ .atsc_6 = { .if_freq = 5380, .agc_mode = 3, .std = 3,
++ .if_lvl = 6, .rfagc_top = 0x37 },
++ .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 0,
++ .if_lvl = 6, .rfagc_top = 0x37 },
+ };
+
+ static struct tda18271_config hauppauge_tda18271_config = {
+@@ -173,6 +187,96 @@ static struct tda18271_config hauppauge_tda18271_config = {
+ .gate = TDA18271_GATE_ANALOG,
+ };
+
++static struct tda18271_config hauppauge_hvr1200_tuner_config = {
++ .gate = TDA18271_GATE_ANALOG,
++};
++
++static struct dibx000_agc_config xc3028_agc_config = {
++ BAND_VHF | BAND_UHF, /* band_caps */
++
++ /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=0,
++ * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
++ * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0,
++ * P_agc_nb_est=2, P_agc_write=0
++ */
++ (0 << 15) | (0 << 14) | (0 << 11) | (0 << 10) | (0 << 9) | (0 << 8) |
++ (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), /* setup */
++
++ 712, /* inv_gain */
++ 21, /* time_stabiliz */
++
++ 0, /* alpha_level */
++ 118, /* thlock */
++
++ 0, /* wbd_inv */
++ 2867, /* wbd_ref */
++ 0, /* wbd_sel */
++ 2, /* wbd_alpha */
++
++ 0, /* agc1_max */
++ 0, /* agc1_min */
++ 39718, /* agc2_max */
++ 9930, /* agc2_min */
++ 0, /* agc1_pt1 */
++ 0, /* agc1_pt2 */
++ 0, /* agc1_pt3 */
++ 0, /* agc1_slope1 */
++ 0, /* agc1_slope2 */
++ 0, /* agc2_pt1 */
++ 128, /* agc2_pt2 */
++ 29, /* agc2_slope1 */
++ 29, /* agc2_slope2 */
++
++ 17, /* alpha_mant */
++ 27, /* alpha_exp */
++ 23, /* beta_mant */
++ 51, /* beta_exp */
++
++ 1, /* perform_agc_softsplit */
++};
++
++/* PLL Configuration for COFDM BW_MHz = 8.000000
++ * With external clock = 30.000000 */
++static struct dibx000_bandwidth_config xc3028_bw_config = {
++ 60000, /* internal */
++ 30000, /* sampling */
++ 1, /* pll_cfg: prediv */
++ 8, /* pll_cfg: ratio */
++ 3, /* pll_cfg: range */
++ 1, /* pll_cfg: reset */
++ 0, /* pll_cfg: bypass */
++ 0, /* misc: refdiv */
++ 0, /* misc: bypclk_div */
++ 1, /* misc: IO_CLK_en_core */
++ 1, /* misc: ADClkSrc */
++ 0, /* misc: modulo */
++ (3 << 14) | (1 << 12) | (524 << 0), /* sad_cfg: refsel, sel, freq_15k */
++ (1 << 25) | 5816102, /* ifreq = 5.200000 MHz */
++ 20452225, /* timf */
++ 30000000 /* xtal_hz */
++};
++
++static struct dib7000p_config hauppauge_hvr1400_dib7000_config = {
++ .output_mpeg2_in_188_bytes = 1,
++ .hostbus_diversity = 1,
++ .tuner_is_baseband = 0,
++ .update_lna = NULL,
++
++ .agc_config_count = 1,
++ .agc = &xc3028_agc_config,
++ .bw = &xc3028_bw_config,
++
++ .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
++ .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
++ .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
++
++ .pwm_freq_div = 0,
++ .agc_control = NULL,
++ .spur_protect = 0,
++
++ .output_mode = OUTMODE_MPEG2_SERIAL,
++};
++
+ static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg)
+ {
+ struct cx23885_tsport *port = ptr;
+@@ -182,7 +286,7 @@ static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg)
+ case XC2028_TUNER_RESET:
+ /* Send the tuner in then out of reset */
+ /* GPIO-2 xc3028 tuner */
+- dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __FUNCTION__, arg);
++ dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg);
+
+ cx_set(GP0_IO, 0x00040000);
+ cx_clear(GP0_IO, 0x00000004);
+@@ -192,10 +296,10 @@ static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg)
+ msleep(5);
+ break;
+ case XC2028_RESET_CLK:
+- dprintk(1, "%s: XC2028_RESET_CLK %d\n", __FUNCTION__, arg);
++ dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg);
+ break;
+ default:
+- dprintk(1, "%s: unknown command %d, arg %d\n", __FUNCTION__,
++ dprintk(1, "%s: unknown command %d, arg %d\n", __func__,
+ command, arg);
+ return -EINVAL;
+ }
+@@ -271,8 +375,9 @@ static int dvb_register(struct cx23885_tsport *port)
+ &fusionhdtv_5_express,
+ &i2c_bus->i2c_adap);
+ if (port->dvb.frontend != NULL) {
+- dvb_attach(dvb_pll_attach, port->dvb.frontend, 0x61,
+- &i2c_bus->i2c_adap, DVB_PLL_LG_TDVS_H06XF);
++ dvb_attach(simple_tuner_attach, port->dvb.frontend,
++ &i2c_bus->i2c_adap, 0x61,
++ TUNER_LG_TDVS_H06XF);
+ }
+ break;
+ case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
+@@ -297,13 +402,52 @@ static int dvb_register(struct cx23885_tsport *port)
+ struct xc2028_config cfg = {
+ .i2c_adap = &i2c_bus->i2c_adap,
+ .i2c_addr = 0x61,
+- .video_dev = port,
+ .callback = cx23885_hvr1500_xc3028_callback,
+ };
+ static struct xc2028_ctrl ctl = {
+ .fname = "xc3028-v27.fw",
+ .max_len = 64,
+- .scode_table = OREN538,
++ .scode_table = XC3028_FE_OREN538,
++ };
++
++ fe = dvb_attach(xc2028_attach,
++ port->dvb.frontend, &cfg);
++ if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
++ fe->ops.tuner_ops.set_config(fe, &ctl);
++ }
++ break;
++ case CX23885_BOARD_HAUPPAUGE_HVR1200:
++ case CX23885_BOARD_HAUPPAUGE_HVR1700:
++ i2c_bus = &dev->i2c_bus[0];
++ port->dvb.frontend = dvb_attach(tda10048_attach,
++ &hauppauge_hvr1200_config,
++ &i2c_bus->i2c_adap);
++ if (port->dvb.frontend != NULL) {
++ dvb_attach(tda829x_attach, port->dvb.frontend,
++ &dev->i2c_bus[1].i2c_adap, 0x42,
++ &tda829x_no_probe);
++ dvb_attach(tda18271_attach, port->dvb.frontend,
++ 0x60, &dev->i2c_bus[1].i2c_adap,
++ &hauppauge_hvr1200_tuner_config);
++ }
++ break;
++ case CX23885_BOARD_HAUPPAUGE_HVR1400:
++ i2c_bus = &dev->i2c_bus[0];
++ port->dvb.frontend = dvb_attach(dib7000p_attach,
++ &i2c_bus->i2c_adap,
++ 0x12, &hauppauge_hvr1400_dib7000_config);
++ if (port->dvb.frontend != NULL) {
++ struct dvb_frontend *fe;
++ struct xc2028_config cfg = {
++ .i2c_adap = &dev->i2c_bus[1].i2c_adap,
++ .i2c_addr = 0x64,
++ .callback = cx23885_hvr1500_xc3028_callback,
++ };
++ static struct xc2028_ctrl ctl = {
++ .fname = "xc3028L-v36.fw",
++ .max_len = 64,
++ .demod = 5000,
++ .d2633 = 1
+ };
+
+ fe = dvb_attach(xc2028_attach,
+@@ -330,7 +474,7 @@ static int dvb_register(struct cx23885_tsport *port)
+
+ /* register everything */
+ return videobuf_dvb_register(&port->dvb, THIS_MODULE, port,
+- &dev->pci->dev);
++ &dev->pci->dev, adapter_nr);
+ }
+
+ int cx23885_dvb_register(struct cx23885_tsport *port)
+@@ -338,7 +482,7 @@ int cx23885_dvb_register(struct cx23885_tsport *port)
+ struct cx23885_dev *dev = port->dev;
+ int err;
+
+- dprintk(1, "%s\n", __FUNCTION__);
++ dprintk(1, "%s\n", __func__);
+ dprintk(1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
+ dev->board,
+ dev->name,
+@@ -349,12 +493,12 @@ int cx23885_dvb_register(struct cx23885_tsport *port)
+
+ /* dvb stuff */
+ printk("%s: cx23885 based dvb card\n", dev->name);
+- videobuf_queue_pci_init(&port->dvb.dvbq, &dvb_qops, dev->pci, &port->slock,
++ videobuf_queue_sg_init(&port->dvb.dvbq, &dvb_qops, &dev->pci->dev, &port->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP,
+ sizeof(struct cx23885_buffer), port);
+ err = dvb_register(port);
+ if (err != 0)
+- printk("%s() dvb_register failed err = %d\n", __FUNCTION__, err);
++ printk("%s() dvb_register failed err = %d\n", __func__, err);
+
+ return err;
+ }
+diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c
+index 92fe0bd..c6bb0a0 100644
+--- a/drivers/media/video/cx23885/cx23885-i2c.c
++++ b/drivers/media/video/cx23885/cx23885-i2c.c
+@@ -33,7 +33,7 @@ static unsigned int i2c_debug;
+ module_param(i2c_debug, int, 0644);
+ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+
+-static unsigned int i2c_scan = 0;
++static unsigned int i2c_scan;
+ module_param(i2c_scan, int, 0444);
+ MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
+
+@@ -87,10 +87,10 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
+ int retval, cnt;
+
+ if (joined_rlen)
+- dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __FUNCTION__,
++ dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__,
+ msg->len, joined_rlen);
+ else
+- dprintk(1, "%s(msg->len=%d)\n", __FUNCTION__, msg->len);
++ dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
+
+ /* Deal with i2c probe functions with zero payload */
+ if (msg->len == 0) {
+@@ -101,7 +101,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
+ if (!i2c_slave_did_ack(i2c_adap))
+ return -EIO;
+
+- dprintk(1, "%s() returns 0\n", __FUNCTION__);
++ dprintk(1, "%s() returns 0\n", __func__);
+ return 0;
+ }
+
+@@ -176,7 +176,7 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
+
+
+ if (i2c_debug && !joined)
+- dprintk(1, "%s(msg->len=%d)\n", __FUNCTION__, msg->len);
++ dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
+
+ /* Deal with i2c probe functions with zero payload */
+ if (msg->len == 0) {
+@@ -188,7 +188,7 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
+ return -EIO;
+
+
+- dprintk(1, "%s() returns 0\n", __FUNCTION__);
++ dprintk(1, "%s() returns 0\n", __func__);
+ return 0;
+ }
+
+@@ -238,11 +238,11 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap,
+ struct cx23885_dev *dev = bus->dev;
+ int i, retval = 0;
+
+- dprintk(1, "%s(num = %d)\n", __FUNCTION__, num);
++ dprintk(1, "%s(num = %d)\n", __func__, num);
+
+ for (i = 0 ; i < num; i++) {
+ dprintk(1, "%s(num = %d) addr = 0x%02x len = 0x%x\n",
+- __FUNCTION__, num, msgs[i].addr, msgs[i].len);
++ __func__, num, msgs[i].addr, msgs[i].len);
+ if (msgs[i].flags & I2C_M_RD) {
+ /* read */
+ retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
+@@ -353,6 +353,8 @@ static struct i2c_client cx23885_i2c_client_template = {
+ };
+
+ static char *i2c_devs[128] = {
++ [0x10 >> 1] = "tda10048",
++ [0x12 >> 1] = "dib7000pc",
+ [ 0x1c >> 1 ] = "lgdt3303",
+ [ 0x86 >> 1 ] = "tda9887",
+ [ 0x32 >> 1 ] = "cx24227",
+@@ -360,7 +362,8 @@ static char *i2c_devs[128] = {
+ [ 0x84 >> 1 ] = "tda8295",
+ [ 0xa0 >> 1 ] = "eeprom",
+ [ 0xc0 >> 1 ] = "tuner/mt2131/tda8275",
+- [ 0xc2 >> 1 ] = "tuner/mt2131/tda8275/xc5000",
++ [0xc2 >> 1] = "tuner/mt2131/tda8275/xc5000/xc3028",
++ [0xc8 >> 1] = "tuner/xc3028L",
+ };
+
+ static void do_i2c_scan(char *name, struct i2c_client *c)
+@@ -383,7 +386,7 @@ int cx23885_i2c_register(struct cx23885_i2c *bus)
+ {
+ struct cx23885_dev *dev = bus->dev;
+
+- dprintk(1, "%s(bus = %d)\n", __FUNCTION__, bus->nr);
++ dprintk(1, "%s(bus = %d)\n", __func__, bus->nr);
+
+ memcpy(&bus->i2c_adap, &cx23885_i2c_adap_template,
+ sizeof(bus->i2c_adap));
+@@ -420,6 +423,29 @@ int cx23885_i2c_unregister(struct cx23885_i2c *bus)
+ return 0;
+ }
+
++void cx23885_av_clk(struct cx23885_dev *dev, int enable)
++{
++ /* write 0 to bus 2 addr 0x144 via i2x_xfer() */
++ char buffer[3];
++ struct i2c_msg msg;
++ dprintk(1, "%s(enabled = %d)\n", __func__, enable);
++
++ /* Register 0x144 */
++ buffer[0] = 0x01;
++ buffer[1] = 0x44;
++ if (enable == 1)
++ buffer[2] = 0x05;
++ else
++ buffer[2] = 0x00;
++
++ msg.addr = 0x44;
++ msg.flags = I2C_M_TEN;
++ msg.len = 3;
++ msg.buf = buffer;
++
++ i2c_xfer(&dev->i2c_bus[2].i2c_adap, &msg, 1);
++}
++
+ /* ----------------------------------------------------------------------- */
+
+ /*
+diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c
+index d3c4d2c..8465221 100644
+--- a/drivers/media/video/cx23885/cx23885-video.c
++++ b/drivers/media/video/cx23885/cx23885-video.c
+@@ -141,7 +141,7 @@ static struct cx23885_fmt *format_by_fourcc(unsigned int fourcc)
+ if (formats[i].fourcc == fourcc)
+ return formats+i;
+
+- printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __FUNCTION__, fourcc);
++ printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __func__, fourcc);
+ return NULL;
+ }
+
+@@ -292,13 +292,13 @@ void cx23885_video_wakeup(struct cx23885_dev *dev,
+ }
+ if (bc != 1)
+ printk(KERN_ERR "%s: %d buffers handled (should be 1)\n",
+- __FUNCTION__, bc);
++ __func__, bc);
+ }
+
+ int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
+ {
+ dprintk(1, "%s(norm = 0x%08x) name: [%s]\n",
+- __FUNCTION__,
++ __func__,
+ (unsigned int)norm,
+ v4l2_norm_to_name(norm));
+
+@@ -319,7 +319,7 @@ struct video_device *cx23885_vdev_init(struct cx23885_dev *dev,
+ char *type)
+ {
+ struct video_device *vfd;
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+
+ vfd = video_device_alloc();
+ if (NULL == vfd)
+@@ -358,7 +358,7 @@ EXPORT_SYMBOL(cx23885_ctrl_query);
+ static int res_get(struct cx23885_dev *dev, struct cx23885_fh *fh,
+ unsigned int bit)
+ {
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+ if (fh->resources & bit)
+ /* have it already allocated */
+ return 1;
+@@ -392,7 +392,7 @@ static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh,
+ unsigned int bits)
+ {
+ BUG_ON((fh->resources & bits) != bits);
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+
+ mutex_lock(&dev->lock);
+ fh->resources &= ~bits;
+@@ -407,7 +407,7 @@ int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
+ memset(&route, 0, sizeof(route));
+
+ dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n",
+- __FUNCTION__,
++ __func__,
+ input, INPUT(input)->vmux,
+ INPUT(input)->gpio0, INPUT(input)->gpio1,
+ INPUT(input)->gpio2, INPUT(input)->gpio3);
+@@ -427,7 +427,7 @@ EXPORT_SYMBOL(cx23885_video_mux);
+ int cx23885_set_scale(struct cx23885_dev *dev, unsigned int width,
+ unsigned int height, enum v4l2_field field)
+ {
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+ return 0;
+ }
+
+@@ -435,7 +435,7 @@ static int cx23885_start_video_dma(struct cx23885_dev *dev,
+ struct cx23885_dmaqueue *q,
+ struct cx23885_buffer *buf)
+ {
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+
+ /* setup fifo + format */
+ cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01],
+@@ -463,7 +463,7 @@ static int cx23885_restart_video_queue(struct cx23885_dev *dev,
+ {
+ struct cx23885_buffer *buf, *prev;
+ struct list_head *item;
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+
+ if (!list_empty(&q->active)) {
+ buf = list_entry(q->active.next, struct cx23885_buffer,
+@@ -579,13 +579,13 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+ if (dev->tvnorm & V4L2_STD_NTSC) {
+ /* cx25840 transmits NTSC bottom field first */
+ dprintk(1, "%s() Creating NTSC risc\n",
+- __FUNCTION__);
++ __func__);
+ line0_offset = buf->bpl;
+ line1_offset = 0;
+ } else {
+ /* All other formats are top field first */
+ dprintk(1, "%s() Creating PAL/SECAM risc\n",
+- __FUNCTION__);
++ __func__);
+ line0_offset = 0;
+ line1_offset = buf->bpl;
+ }
+@@ -765,8 +765,8 @@ static int video_open(struct inode *inode, struct file *file)
+ fh->height = 240;
+ fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
+
+- videobuf_queue_pci_init(&fh->vidq, &cx23885_video_qops,
+- dev->pci, &dev->slock,
++ videobuf_queue_sg_init(&fh->vidq, &cx23885_video_qops,
++ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct cx23885_buffer),
+@@ -885,7 +885,7 @@ static int video_mmap(struct file *file, struct vm_area_struct *vma)
+
+ int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl)
+ {
+- dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __FUNCTION__);
++ dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__);
+ cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_CTRL, ctl);
+ return 0;
+ }
+@@ -894,7 +894,7 @@ EXPORT_SYMBOL(cx23885_get_control);
+ int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl)
+ {
+ dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)"
+- " (disabled - no action)\n", __FUNCTION__);
++ " (disabled - no action)\n", __func__);
+ return 0;
+ }
+ EXPORT_SYMBOL(cx23885_set_control);
+@@ -990,7 +990,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
+ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+ int err;
+
+- dprintk(2, "%s()\n", __FUNCTION__);
++ dprintk(2, "%s()\n", __func__);
+ err = vidioc_try_fmt_cap(file, priv, f);
+
+ if (0 != err)
+@@ -999,7 +999,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
+ fh->width = f->fmt.pix.width;
+ fh->height = f->fmt.pix.height;
+ fh->vidq.field = f->fmt.pix.field;
+- dprintk(2, "%s() width=%d height=%d field=%d\n", __FUNCTION__,
++ dprintk(2, "%s() width=%d height=%d field=%d\n", __func__,
+ fh->width, fh->height, fh->vidq.field);
+ cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_FMT, f);
+ return 0;
+@@ -1101,7 +1101,7 @@ static int vidioc_streamon(struct file *file, void *priv,
+ {
+ struct cx23885_fh *fh = priv;
+ struct cx23885_dev *dev = fh->dev;
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+
+ if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+ return -EINVAL;
+@@ -1118,7 +1118,7 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+ struct cx23885_fh *fh = priv;
+ struct cx23885_dev *dev = fh->dev;
+ int err, res;
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+
+ if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+@@ -1136,7 +1136,7 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms)
+ {
+ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+
+ mutex_lock(&dev->lock);
+ cx23885_set_tvnorm(dev, *tvnorms);
+@@ -1159,7 +1159,7 @@ int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
+ [CX23885_VMUX_DEBUG] = "for debug only",
+ };
+ unsigned int n;
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+
+ n = i->index;
+ if (n >= 4)
+@@ -1184,7 +1184,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
+ struct v4l2_input *i)
+ {
+ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+ return cx23885_enum_input(dev, i);
+ }
+
+@@ -1193,7 +1193,7 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+
+ *i = dev->input;
+- dprintk(1, "%s() returns %d\n", __FUNCTION__, *i);
++ dprintk(1, "%s() returns %d\n", __func__, *i);
+ return 0;
+ }
+
+@@ -1201,10 +1201,10 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+ {
+ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+
+- dprintk(1, "%s(%d)\n", __FUNCTION__, i);
++ dprintk(1, "%s(%d)\n", __func__, i);
+
+ if (i >= 4) {
+- dprintk(1, "%s() -EINVAL\n", __FUNCTION__);
++ dprintk(1, "%s() -EINVAL\n", __func__);
+ return -EINVAL;
+ }
+
+@@ -1389,7 +1389,7 @@ int cx23885_video_irq(struct cx23885_dev *dev, u32 status)
+ return handled;
+ cx_write(VID_A_INT_STAT, status);
+
+- dprintk(2, "%s() status = 0x%08x\n", __FUNCTION__, status);
++ dprintk(2, "%s() status = 0x%08x\n", __func__, status);
+ /* risc op code error */
+ if (status & (1 << 16)) {
+ printk(KERN_WARNING "%s/0: video risc op code error\n",
+@@ -1487,7 +1487,7 @@ static const struct file_operations radio_fops = {
+
+ void cx23885_video_unregister(struct cx23885_dev *dev)
+ {
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+ cx_clear(PCI_INT_MSK, 1);
+
+ if (dev->video_dev) {
+@@ -1505,7 +1505,7 @@ int cx23885_video_register(struct cx23885_dev *dev)
+ {
+ int err;
+
+- dprintk(1, "%s()\n", __FUNCTION__);
++ dprintk(1, "%s()\n", __func__);
+ spin_lock_init(&dev->slock);
+
+ /* Initialize VBI template */
+diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h
+index 7cb2179..32af87f 100644
+--- a/drivers/media/video/cx23885/cx23885.h
++++ b/drivers/media/video/cx23885/cx23885.h
+@@ -32,6 +32,7 @@
+
+ #include "btcx-risc.h"
+ #include "cx23885-reg.h"
++#include "media/cx2341x.h"
+
+ #include <linux/version.h>
+ #include <linux/mutex.h>
+@@ -59,6 +60,9 @@
+ #define CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP 4
+ #define CX23885_BOARD_HAUPPAUGE_HVR1500Q 5
+ #define CX23885_BOARD_HAUPPAUGE_HVR1500 6
++#define CX23885_BOARD_HAUPPAUGE_HVR1200 7
++#define CX23885_BOARD_HAUPPAUGE_HVR1700 8
++#define CX23885_BOARD_HAUPPAUGE_HVR1400 9
+
+ /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */
+ #define CX23885_NORMS (\
+@@ -154,6 +158,7 @@ typedef enum {
+ CX23885_MPEG_UNDEFINED = 0,
+ CX23885_MPEG_DVB,
+ CX23885_ANALOG_VIDEO,
++ CX23885_MPEG_ENCODER,
+ } port_t;
+
+ struct cx23885_board {
+@@ -252,6 +257,8 @@ struct cx23885_tsport {
+ u32 gen_ctrl_val;
+ u32 ts_clk_en_val;
+ u32 src_sel_val;
++ u32 vld_misc_val;
++ u32 hw_sop_ctrl_val;
+ };
+
+ struct cx23885_dev {
+@@ -312,6 +319,14 @@ struct cx23885_dev {
+ struct cx23885_dmaqueue vidq;
+ struct cx23885_dmaqueue vbiq;
+ spinlock_t slock;
++
++ /* MPEG Encoder ONLY settings */
++ u32 cx23417_mailbox;
++ struct cx2341x_mpeg_params mpeg_params;
++ struct video_device *v4l_device;
++ atomic_t v4l_reader_count;
++ struct cx23885_tvnorm encodernorm;
++
+ };
+
+ extern struct list_head cx23885_devlist;
+@@ -431,6 +446,18 @@ extern int cx23885_i2c_register(struct cx23885_i2c *bus);
+ extern int cx23885_i2c_unregister(struct cx23885_i2c *bus);
+ extern void cx23885_call_i2c_clients(struct cx23885_i2c *bus, unsigned int cmd,
+ void *arg);
++extern void cx23885_av_clk(struct cx23885_dev *dev, int enable);
++
++/* ----------------------------------------------------------- */
++/* cx23885-417.c */
++extern int cx23885_417_register(struct cx23885_dev *dev);
++extern void cx23885_417_unregister(struct cx23885_dev *dev);
++extern int cx23885_irq_417(struct cx23885_dev *dev, u32 status);
++extern void cx23885_417_check_encoder(struct cx23885_dev *dev);
++extern void cx23885_mc417_init(struct cx23885_dev *dev);
++extern int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value);
++extern int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value);
++
+
+ /* ----------------------------------------------------------- */
+ /* tv norms */
+diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
+index 756a1ee..7fde678 100644
+--- a/drivers/media/video/cx25840/cx25840-core.c
++++ b/drivers/media/video/cx25840/cx25840-core.c
+@@ -352,7 +352,7 @@ static void cx23885_initialize(struct i2c_client *client)
+ static void input_change(struct i2c_client *client)
+ {
+ struct cx25840_state *state = i2c_get_clientdata(client);
+- v4l2_std_id std = cx25840_get_v4lstd(client);
++ v4l2_std_id std = state->std;
+
+ /* Follow step 8c and 8d of section 3.16 in the cx25840 datasheet */
+ if (std & V4L2_STD_SECAM) {
+@@ -523,32 +523,34 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
+
+ /* ----------------------------------------------------------------------- */
+
+-static int set_v4lstd(struct i2c_client *client, v4l2_std_id std)
++static int set_v4lstd(struct i2c_client *client)
+ {
+- u8 fmt=0; /* zero is autodetect */
++ struct cx25840_state *state = i2c_get_clientdata(client);
++ u8 fmt = 0; /* zero is autodetect */
++ u8 pal_m = 0;
+
+ /* First tests should be against specific std */
+- if (std == V4L2_STD_NTSC_M_JP) {
+- fmt=0x2;
+- } else if (std == V4L2_STD_NTSC_443) {
+- fmt=0x3;
+- } else if (std == V4L2_STD_PAL_M) {
+- fmt=0x5;
+- } else if (std == V4L2_STD_PAL_N) {
+- fmt=0x6;
+- } else if (std == V4L2_STD_PAL_Nc) {
+- fmt=0x7;
+- } else if (std == V4L2_STD_PAL_60) {
+- fmt=0x8;
++ if (state->std == V4L2_STD_NTSC_M_JP) {
++ fmt = 0x2;
++ } else if (state->std == V4L2_STD_NTSC_443) {
++ fmt = 0x3;
++ } else if (state->std == V4L2_STD_PAL_M) {
++ pal_m = 1;
++ fmt = 0x5;
++ } else if (state->std == V4L2_STD_PAL_N) {
++ fmt = 0x6;
++ } else if (state->std == V4L2_STD_PAL_Nc) {
++ fmt = 0x7;
++ } else if (state->std == V4L2_STD_PAL_60) {
++ fmt = 0x8;
+ } else {
+ /* Then, test against generic ones */
+- if (std & V4L2_STD_NTSC) {
+- fmt=0x1;
+- } else if (std & V4L2_STD_PAL) {
+- fmt=0x4;
+- } else if (std & V4L2_STD_SECAM) {
+- fmt=0xc;
+- }
++ if (state->std & V4L2_STD_NTSC)
++ fmt = 0x1;
++ else if (state->std & V4L2_STD_PAL)
++ fmt = 0x4;
++ else if (state->std & V4L2_STD_SECAM)
++ fmt = 0xc;
+ }
+
+ v4l_dbg(1, cx25840_debug, client, "changing video std to fmt %i\n",fmt);
+@@ -563,42 +565,13 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std)
+ cx25840_and_or(client, 0x47b, ~6, 0);
+ }
+ cx25840_and_or(client, 0x400, ~0xf, fmt);
++ cx25840_and_or(client, 0x403, ~0x3, pal_m);
+ cx25840_vbi_setup(client);
++ if (!state->is_cx25836)
++ input_change(client);
+ return 0;
+ }
+
+-v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client)
+-{
+- struct cx25840_state *state = i2c_get_clientdata(client);
+- /* check VID_FMT_SEL first */
+- u8 fmt = cx25840_read(client, 0x400) & 0xf;
+-
+- if (!fmt) {
+- /* check AFD_FMT_STAT if set to autodetect */
+- fmt = cx25840_read(client, 0x40d) & 0xf;
+- }
+-
+- switch (fmt) {
+- case 0x1:
+- {
+- /* if the audio std is A2-M, then this is the South Korean
+- NTSC standard */
+- if (!state->is_cx25836 && cx25840_read(client, 0x805) == 2)
+- return V4L2_STD_NTSC_M_KR;
+- return V4L2_STD_NTSC_M;
+- }
+- case 0x2: return V4L2_STD_NTSC_M_JP;
+- case 0x3: return V4L2_STD_NTSC_443;
+- case 0x4: return V4L2_STD_PAL;
+- case 0x5: return V4L2_STD_PAL_M;
+- case 0x6: return V4L2_STD_PAL_N;
+- case 0x7: return V4L2_STD_PAL_Nc;
+- case 0x8: return V4L2_STD_PAL_60;
+- case 0xc: return V4L2_STD_SECAM;
+- default: return V4L2_STD_UNKNOWN;
+- }
+-}
+-
+ /* ----------------------------------------------------------------------- */
+
+ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
+@@ -718,9 +691,10 @@ static int get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
+
+ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
+ {
++ struct cx25840_state *state = i2c_get_clientdata(client);
+ struct v4l2_pix_format *pix;
+ int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
+- int is_50Hz = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60);
++ int is_50Hz = !(state->std & V4L2_STD_525_60);
+
+ switch (fmt->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+@@ -1096,12 +1070,15 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
+ }
+
+ case VIDIOC_G_STD:
+- *(v4l2_std_id *)arg = cx25840_get_v4lstd(client);
++ *(v4l2_std_id *)arg = state->std;
+ break;
+
+ case VIDIOC_S_STD:
++ if (state->radio == 0 && state->std == *(v4l2_std_id *)arg)
++ return 0;
+ state->radio = 0;
+- return set_v4lstd(client, *(v4l2_std_id *)arg);
++ state->std = *(v4l2_std_id *)arg;
++ return set_v4lstd(client);
+
+ case AUDC_SET_RADIO:
+ state->radio = 1;
+@@ -1291,6 +1268,12 @@ static int cx25840_probe(struct i2c_client *client)
+ state->id = id;
+ state->rev = device_id;
+
++ if (state->is_cx23885) {
++ /* Drive GPIO2 direction and values */
++ cx25840_write(client, 0x160, 0x1d);
++ cx25840_write(client, 0x164, 0x00);
++ }
++
+ return 0;
+ }
+
+diff --git a/drivers/media/video/cx25840/cx25840-core.h b/drivers/media/video/cx25840/cx25840-core.h
+index 95093ed..8bf797f 100644
+--- a/drivers/media/video/cx25840/cx25840-core.h
++++ b/drivers/media/video/cx25840/cx25840-core.h
+@@ -38,6 +38,7 @@ struct cx25840_state {
+ struct i2c_client *c;
+ int pvr150_workaround;
+ int radio;
++ v4l2_std_id std;
+ enum cx25840_video_input vid_input;
+ enum cx25840_audio_input aud_input;
+ u32 audclk_freq;
+@@ -60,7 +61,6 @@ int cx25840_write4(struct i2c_client *client, u16 addr, u32 value);
+ u8 cx25840_read(struct i2c_client *client, u16 addr);
+ u32 cx25840_read4(struct i2c_client *client, u16 addr);
+ int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned mask, u8 value);
+-v4l2_std_id cx25840_get_v4lstd(struct i2c_client *client);
+
+ /* ----------------------------------------------------------------------- */
+ /* cx25850-firmware.c */
+diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c
+index 1ddf724..620d295 100644
+--- a/drivers/media/video/cx25840/cx25840-firmware.c
++++ b/drivers/media/video/cx25840/cx25840-firmware.c
+@@ -79,11 +79,9 @@ static int check_fw_load(struct i2c_client *client, int size)
+ return 0;
+ }
+
+-static int fw_write(struct i2c_client *client, u8 * data, int size)
++static int fw_write(struct i2c_client *client, u8 *data, int size)
+ {
+- int sent;
+-
+- if ((sent = i2c_master_send(client, data, size)) < size) {
++ if (i2c_master_send(client, data, size) < size) {
+ v4l_err(client, "firmware load i2c failure\n");
+ return -ENOSYS;
+ }
+@@ -96,7 +94,7 @@ int cx25840_loadfw(struct i2c_client *client)
+ struct cx25840_state *state = i2c_get_clientdata(client);
+ const struct firmware *fw = NULL;
+ u8 buffer[4], *ptr;
+- int size, send, retval;
++ int size, retval;
+
+ if (state->is_cx23885)
+ firmware = FWFILE_CX23885;
+@@ -124,8 +122,7 @@ int cx25840_loadfw(struct i2c_client *client)
+ while (size > 0) {
+ ptr[0] = 0x08;
+ ptr[1] = 0x02;
+- send = size > (FWSEND - 2) ? FWSEND : size + 2;
+- retval = fw_write(client, ptr, send);
++ retval = fw_write(client, ptr, min(FWSEND, size + 2));
+
+ if (retval < 0) {
+ release_firmware(fw);
+diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c
+index 6828f59..c754b9d 100644
+--- a/drivers/media/video/cx25840/cx25840-vbi.c
++++ b/drivers/media/video/cx25840/cx25840-vbi.c
+@@ -85,7 +85,7 @@ static int decode_vps(u8 * dst, u8 * p)
+ void cx25840_vbi_setup(struct i2c_client *client)
+ {
+ struct cx25840_state *state = i2c_get_clientdata(client);
+- v4l2_std_id std = cx25840_get_v4lstd(client);
++ v4l2_std_id std = state->std;
+ int hblank,hactive,burst,vblank,vactive,sc,vblank656,src_decimation;
+ int luma_lpf,uv_lpf, comb;
+ u32 pll_int,pll_frac,pll_post;
+@@ -242,7 +242,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
+ 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */
+ 0, 0, 0, 0
+ };
+- int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60);
++ int is_pal = !(state->std & V4L2_STD_525_60);
+ int i;
+
+ fmt = arg;
+@@ -279,7 +279,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
+
+ case VIDIOC_S_FMT:
+ {
+- int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60);
++ int is_pal = !(state->std & V4L2_STD_525_60);
+ int vbi_offset = is_pal ? 1 : 0;
+ int i, x;
+ u8 lcr[24];
+diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
+index 49d3813..27635cd 100644
+--- a/drivers/media/video/cx88/Kconfig
++++ b/drivers/media/video/cx88/Kconfig
+@@ -57,6 +57,8 @@ config VIDEO_CX88_DVB
+ select DVB_NXT200X if !DVB_FE_CUSTOMISE
+ select DVB_CX24123 if !DVB_FE_CUSTOMISE
+ select DVB_ISL6421 if !DVB_FE_CUSTOMISE
++ select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
++ select DVB_S5H1411 if !DVB_FE_CUSTOMISE
+ ---help---
+ This adds support for DVB/ATSC cards based on the
+ Conexant 2388x chip.
+diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
+index 316b106..e976fc6 100644
+--- a/drivers/media/video/cx88/cx88-alsa.c
++++ b/drivers/media/video/cx88/cx88-alsa.c
+@@ -283,7 +283,7 @@ static int dsp_buffer_free(snd_cx88_card_t *chip)
+ BUG_ON(!chip->dma_size);
+
+ dprintk(2,"Freeing buffer\n");
+- videobuf_pci_dma_unmap(chip->pci, chip->dma_risc);
++ videobuf_sg_dma_unmap(&chip->pci->dev, chip->dma_risc);
+ videobuf_dma_free(chip->dma_risc);
+ btcx_riscmem_free(chip->pci,&chip->buf->risc);
+ kfree(chip->buf);
+@@ -385,7 +385,7 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream,
+ BUG_ON(!chip->dma_size);
+ BUG_ON(chip->num_periods & (chip->num_periods-1));
+
+- buf = videobuf_pci_alloc(sizeof(*buf));
++ buf = videobuf_sg_alloc(sizeof(*buf));
+ if (NULL == buf)
+ return -ENOMEM;
+
+@@ -396,14 +396,14 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream,
+ buf->vb.height = chip->num_periods;
+ buf->vb.size = chip->dma_size;
+
+- dma=videobuf_to_dma(&buf->vb);
++ dma = videobuf_to_dma(&buf->vb);
+ videobuf_dma_init(dma);
+ ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
+ (PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT));
+ if (ret < 0)
+ goto error;
+
+- ret = videobuf_pci_dma_map(chip->pci,dma);
++ ret = videobuf_sg_dma_map(&chip->pci->dev, dma);
+ if (ret < 0)
+ goto error;
+
+@@ -494,7 +494,7 @@ static snd_pcm_uframes_t snd_cx88_pointer(struct snd_pcm_substream *substream)
+
+ count = atomic_read(&chip->count);
+
+-// dprintk(2, "%s - count %d (+%u), period %d, frame %lu\n", __FUNCTION__,
++// dprintk(2, "%s - count %d (+%u), period %d, frame %lu\n", __func__,
+ // count, new, count & (runtime->periods-1),
+ // runtime->period_size * (count & (runtime->periods-1)));
+ return runtime->period_size * (count & (runtime->periods-1));
+@@ -690,10 +690,8 @@ MODULE_DEVICE_TABLE(pci, cx88_audio_pci_tbl);
+ static int snd_cx88_free(snd_cx88_card_t *chip)
+ {
+
+- if (chip->irq >= 0){
+- synchronize_irq(chip->irq);
++ if (chip->irq >= 0)
+ free_irq(chip->irq, chip);
+- }
+
+ cx88_core_put(chip->core,chip->pci);
+
+diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
+index a99e9d5..6c0c94c 100644
+--- a/drivers/media/video/cx88/cx88-blackbird.c
++++ b/drivers/media/video/cx88/cx88-blackbird.c
+@@ -45,7 +45,7 @@ static unsigned int mpegbufs = 32;
+ module_param(mpegbufs,int,0644);
+ MODULE_PARM_DESC(mpegbufs,"number of mpeg buffers, range 2-32");
+
+-static unsigned int debug = 0;
++static unsigned int debug;
+ module_param(debug,int,0644);
+ MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
+
+@@ -314,7 +314,7 @@ static int blackbird_mbox_func(void *priv, u32 command, int in, int out, u32 dat
+ u32 value, flag, retval;
+ int i;
+
+- dprintk(1,"%s: 0x%X\n", __FUNCTION__, command);
++ dprintk(1,"%s: 0x%X\n", __func__, command);
+
+ /* this may not be 100% safe if we can't read any memory location
+ without side effects */
+@@ -546,10 +546,12 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
+ if (retval < 0)
+ return retval;
+
+- dev->mailbox = blackbird_find_mailbox(dev);
+- if (dev->mailbox < 0)
++ retval = blackbird_find_mailbox(dev);
++ if (retval < 0)
+ return -1;
+
++ dev->mailbox = retval;
++
+ retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
+ if (retval < 0) {
+ dprintk(0, "ERROR: Firmware ping failed!\n");
+@@ -693,7 +695,7 @@ static int blackbird_queryctrl(struct cx8802_dev *dev, struct v4l2_queryctrl *qc
+ return -EINVAL;
+
+ /* Standard V4L2 controls */
+- if (cx8800_ctrl_query(qctrl) == 0)
++ if (cx8800_ctrl_query(dev->core, qctrl) == 0)
+ return 0;
+
+ /* MPEG V4L2 controls */
+@@ -933,7 +935,7 @@ static int vidioc_queryctrl (struct file *file, void *priv,
+ qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
+ if (unlikely(qctrl->id == 0))
+ return -EINVAL;
+- return cx8800_ctrl_query(qctrl);
++ return cx8800_ctrl_query(dev->core, qctrl);
+ }
+
+ static int vidioc_enum_input (struct file *file, void *priv,
+@@ -1055,7 +1057,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
+
+ dev = cx8802_get_device(inode);
+
+- dprintk( 1, "%s\n", __FUNCTION__);
++ dprintk( 1, "%s\n", __func__);
+
+ if (dev == NULL)
+ return -ENODEV;
+@@ -1065,7 +1067,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
+ if (drv) {
+ err = drv->request_acquire(drv);
+ if(err != 0) {
+- dprintk(1,"%s: Unable to acquire hardware, %d\n", __FUNCTION__, err);
++ dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err);
+ return err;
+ }
+ }
+@@ -1087,8 +1089,8 @@ static int mpeg_open(struct inode *inode, struct file *file)
+ file->private_data = fh;
+ fh->dev = dev;
+
+- videobuf_queue_pci_init(&fh->mpegq, &blackbird_qops,
+- dev->pci, &dev->slock,
++ videobuf_queue_sg_init(&fh->mpegq, &blackbird_qops,
++ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct cx88_buffer),
+@@ -1284,7 +1286,7 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
+ struct cx8802_dev *dev = core->dvbdev;
+ int err;
+
+- dprintk( 1, "%s\n", __FUNCTION__);
++ dprintk( 1, "%s\n", __func__);
+ dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
+ core->boardnr,
+ core->name,
+diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
+index 8c9a8ad..2b6b283 100644
+--- a/drivers/media/video/cx88/cx88-cards.c
++++ b/drivers/media/video/cx88/cx88-cards.c
+@@ -44,6 +44,16 @@ static unsigned int latency = UNSET;
+ module_param(latency,int,0444);
+ MODULE_PARM_DESC(latency,"pci latency timer");
+
++#define info_printk(core, fmt, arg...) \
++ printk(KERN_INFO "%s: " fmt, core->name , ## arg)
++
++#define warn_printk(core, fmt, arg...) \
++ printk(KERN_WARNING "%s: " fmt, core->name , ## arg)
++
++#define err_printk(core, fmt, arg...) \
++ printk(KERN_ERR "%s: " fmt, core->name , ## arg)
++
++
+ /* ------------------------------------------------------------------ */
+ /* board config info */
+
+@@ -1354,6 +1364,10 @@ static const struct cx88_board cx88_boards[] = {
+ }},
+ /* fixme: Add radio support */
+ .mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD,
++ .radio = {
++ .type = CX88_RADIO,
++ .gpio0 = 0xe780,
++ },
+ },
+ [CX88_BOARD_ADSTECH_PTV_390] = {
+ .name = "ADS Tech Instant Video PCI",
+@@ -1401,6 +1415,246 @@ static const struct cx88_board cx88_boards[] = {
+ }},
+ .mpeg = CX88_MPEG_DVB,
+ },
++ [CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO] = {
++ .name = "DViCO FusionHDTV 5 PCI nano",
++ /* xc3008 tuner, digital only for now */
++ .tuner_type = TUNER_ABSENT,
++ .radio_type = UNSET,
++ .tuner_addr = ADDR_UNSET,
++ .radio_addr = ADDR_UNSET,
++ .input = {{
++ .type = CX88_VMUX_TELEVISION,
++ .vmux = 0,
++ .gpio0 = 0x000027df, /* Unconfirmed */
++ }, {
++ .type = CX88_VMUX_COMPOSITE1,
++ .vmux = 1,
++ .gpio0 = 0x000027df, /* Unconfirmed */
++ .audioroute = 1,
++ }, {
++ .type = CX88_VMUX_SVIDEO,
++ .vmux = 2,
++ .gpio0 = 0x000027df, /* Unconfirmed */
++ .audioroute = 1,
++ } },
++ .mpeg = CX88_MPEG_DVB,
++ },
++ [CX88_BOARD_PINNACLE_HYBRID_PCTV] = {
++ .name = "Pinnacle Hybrid PCTV",
++ .tuner_type = TUNER_XC2028,
++ .tuner_addr = 0x61,
++ .input = { {
++ .type = CX88_VMUX_TELEVISION,
++ .vmux = 0,
++ }, {
++ .type = CX88_VMUX_COMPOSITE1,
++ .vmux = 1,
++ }, {
++ .type = CX88_VMUX_SVIDEO,
++ .vmux = 2,
++ } },
++ .radio = {
++ .type = CX88_RADIO,
++ .gpio0 = 0x004ff,
++ .gpio1 = 0x010ff,
++ .gpio2 = 0x0ff,
++ },
++ },
++ [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = {
++ .name = "Winfast TV2000 XP Global",
++ .tuner_type = TUNER_XC2028,
++ .tuner_addr = 0x61,
++ .input = { {
++ .type = CX88_VMUX_TELEVISION,
++ .vmux = 0,
++ .gpio0 = 0x0400, /* pin 2:mute = 0 (off?) */
++ .gpio1 = 0x0000,
++ .gpio2 = 0x0800, /* pin 19:audio = 0 (tv) */
++
++ }, {
++ .type = CX88_VMUX_COMPOSITE1,
++ .vmux = 1,
++ .gpio0 = 0x0400, /* probably? or 0x0404 to turn mute on */
++ .gpio1 = 0x0000,
++ .gpio2 = 0x0808, /* pin 19:audio = 1 (line) */
++
++ }, {
++ .type = CX88_VMUX_SVIDEO,
++ .vmux = 2,
++ } },
++ .radio = {
++ .type = CX88_RADIO,
++ .gpio0 = 0x004ff,
++ .gpio1 = 0x010ff,
++ .gpio2 = 0x0ff,
++ },
++ },
++ [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = {
++ .name = "PowerColor Real Angel 330",
++ .tuner_type = TUNER_XC2028,
++ .tuner_addr = 0x61,
++ .input = { {
++ .type = CX88_VMUX_TELEVISION,
++ .vmux = 0,
++ .gpio0 = 0x00ff,
++ .gpio1 = 0xf35d,
++ .gpio3 = 0x0000,
++ }, {
++ .type = CX88_VMUX_COMPOSITE1,
++ .vmux = 1,
++ .gpio0 = 0x00ff,
++ .gpio1 = 0xf37d,
++ .gpio3 = 0x0000,
++ }, {
++ .type = CX88_VMUX_SVIDEO,
++ .vmux = 2,
++ .gpio0 = 0x000ff,
++ .gpio1 = 0x0f37d,
++ .gpio3 = 0x00000,
++ } },
++ .radio = {
++ .type = CX88_RADIO,
++ .gpio0 = 0x000ff,
++ .gpio1 = 0x0f35d,
++ .gpio3 = 0x00000,
++ },
++ },
++ [CX88_BOARD_GENIATECH_X8000_MT] = {
++ /* Also PowerColor Real Angel 330 and Geniatech X800 OEM */
++ .name = "Geniatech X8000-MT DVBT",
++ .tuner_type = TUNER_XC2028,
++ .tuner_addr = 0x61,
++ .input = { {
++ .type = CX88_VMUX_TELEVISION,
++ .vmux = 0,
++ .gpio0 = 0x00000000,
++ .gpio1 = 0x00e3e341,
++ .gpio2 = 0x00000000,
++ .gpio3 = 0x00000000,
++ }, {
++ .type = CX88_VMUX_COMPOSITE1,
++ .vmux = 1,
++ .gpio0 = 0x00000000,
++ .gpio1 = 0x00e3e361,
++ .gpio2 = 0x00000000,
++ .gpio3 = 0x00000000,
++ }, {
++ .type = CX88_VMUX_SVIDEO,
++ .vmux = 2,
++ .gpio0 = 0x00000000,
++ .gpio1 = 0x00e3e361,
++ .gpio2 = 0x00000000,
++ .gpio3 = 0x00000000,
++ } },
++ .radio = {
++ .type = CX88_RADIO,
++ .gpio0 = 0x00000000,
++ .gpio1 = 0x00e3e341,
++ .gpio2 = 0x00000000,
++ .gpio3 = 0x00000000,
++ },
++ .mpeg = CX88_MPEG_DVB,
++ },
++ [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO] = {
++ .name = "DViCO FusionHDTV DVB-T PRO",
++ .tuner_type = TUNER_ABSENT, /* XXX: Has XC3028 */
++ .radio_type = UNSET,
++ .tuner_addr = ADDR_UNSET,
++ .radio_addr = ADDR_UNSET,
++ .input = { {
++ .type = CX88_VMUX_COMPOSITE1,
++ .vmux = 1,
++ .gpio0 = 0x000067df,
++ }, {
++ .type = CX88_VMUX_SVIDEO,
++ .vmux = 2,
++ .gpio0 = 0x000067df,
++ } },
++ .mpeg = CX88_MPEG_DVB,
++ },
++ [CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD] = {
++ .name = "DViCO FusionHDTV 7 Gold",
++ .tuner_type = TUNER_XC5000,
++ .radio_type = UNSET,
++ .tuner_addr = ADDR_UNSET,
++ .radio_addr = ADDR_UNSET,
++ .input = {{
++ .type = CX88_VMUX_TELEVISION,
++ .vmux = 0,
++ .gpio0 = 0x10df,
++ },{
++ .type = CX88_VMUX_COMPOSITE1,
++ .vmux = 1,
++ .gpio0 = 0x16d9,
++ },{
++ .type = CX88_VMUX_SVIDEO,
++ .vmux = 2,
++ .gpio0 = 0x16d9,
++ }},
++ .mpeg = CX88_MPEG_DVB,
++ },
++ [CX88_BOARD_PROLINK_PV_8000GT] = {
++ .name = "Prolink Pixelview MPEG 8000GT",
++ .tuner_type = TUNER_XC2028,
++ .tuner_addr = 0x61,
++ .input = { {
++ .type = CX88_VMUX_TELEVISION,
++ .vmux = 0,
++ .gpio0 = 0x0ff,
++ .gpio2 = 0x0cfb,
++ }, {
++ .type = CX88_VMUX_COMPOSITE1,
++ .vmux = 1,
++ .gpio2 = 0x0cfb,
++ }, {
++ .type = CX88_VMUX_SVIDEO,
++ .vmux = 2,
++ .gpio2 = 0x0cfb,
++ } },
++ .radio = {
++ .type = CX88_RADIO,
++ .gpio2 = 0x0cfb,
++ },
++ },
++ /* Both radio, analog and ATSC work with this board.
++ However, for analog to work, s5h1409 gate should be open,
++ otherwise, tuner-xc3028 won't be detected.
++ A proper fix require using the newer i2c methods to add
++ tuner-xc3028 without doing an i2c probe.
++ */
++ [CX88_BOARD_KWORLD_ATSC_120] = {
++ .name = "Kworld PlusTV HD PCI 120 (ATSC 120)",
++ .tuner_type = TUNER_XC2028,
++ .radio_type = UNSET,
++ .tuner_addr = ADDR_UNSET,
++ .radio_addr = ADDR_UNSET,
++ .input = { {
++ .type = CX88_VMUX_TELEVISION,
++ .vmux = 0,
++ .gpio0 = 0x000000ff,
++ .gpio1 = 0x0000f35d,
++ .gpio2 = 0x00000000,
++ }, {
++ .type = CX88_VMUX_COMPOSITE1,
++ .vmux = 1,
++ .gpio0 = 0x000000ff,
++ .gpio1 = 0x0000f37e,
++ .gpio2 = 0x00000000,
++ }, {
++ .type = CX88_VMUX_SVIDEO,
++ .vmux = 2,
++ .gpio0 = 0x000000ff,
++ .gpio1 = 0x0000f37e,
++ .gpio2 = 0x00000000,
++ } },
++ .radio = {
++ .type = CX88_RADIO,
++ .gpio0 = 0x000000ff,
++ .gpio1 = 0x0000f35d,
++ .gpio2 = 0x00000000,
++ },
++ .mpeg = CX88_MPEG_DVB,
++ },
+ };
+
+ /* ------------------------------------------------------------------ */
+@@ -1605,7 +1859,11 @@ static const struct cx88_subid cx88_subids[] = {
+ .subdevice = 0xdb11,
+ .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS,
+ /* Re-branded DViCO: UltraView DVB-T Plus */
+- },{
++ }, {
++ .subvendor = 0x18ac,
++ .subdevice = 0xdb30,
++ .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO,
++ }, {
+ .subvendor = 0x17de,
+ .subdevice = 0x0840,
+ .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT,
+@@ -1714,6 +1972,38 @@ static const struct cx88_subid cx88_subids[] = {
+ .subvendor = 0x11bd,
+ .subdevice = 0x0051,
+ .card = CX88_BOARD_PINNACLE_PCTV_HD_800i,
++ }, {
++ .subvendor = 0x18ac,
++ .subdevice = 0xd530,
++ .card = CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO,
++ }, {
++ .subvendor = 0x12ab,
++ .subdevice = 0x1788,
++ .card = CX88_BOARD_PINNACLE_HYBRID_PCTV,
++ }, {
++ .subvendor = 0x14f1,
++ .subdevice = 0xea3d,
++ .card = CX88_BOARD_POWERCOLOR_REAL_ANGEL,
++ }, {
++ .subvendor = 0x107d,
++ .subdevice = 0x6f18,
++ .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL,
++ }, {
++ .subvendor = 0x14f1,
++ .subdevice = 0x8852,
++ .card = CX88_BOARD_GENIATECH_X8000_MT,
++ }, {
++ .subvendor = 0x18ac,
++ .subdevice = 0xd610,
++ .card = CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD,
++ }, {
++ .subvendor = 0x1554,
++ .subdevice = 0x4935,
++ .card = CX88_BOARD_PROLINK_PV_8000GT,
++ }, {
++ .subvendor = 0x17de,
++ .subdevice = 0x08c1,
++ .card = CX88_BOARD_KWORLD_ATSC_120,
+ },
+ };
+
+@@ -1731,17 +2021,16 @@ static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
+ if (eeprom_data[4] != 0x7d ||
+ eeprom_data[5] != 0x10 ||
+ eeprom_data[7] != 0x66) {
+- printk(KERN_WARNING "%s: Leadtek eeprom invalid.\n",
+- core->name);
++ warn_printk(core, "Leadtek eeprom invalid.\n");
+ return;
+ }
+
+ core->board.tuner_type = (eeprom_data[6] == 0x13) ?
+ TUNER_PHILIPS_FM1236_MK3 : TUNER_PHILIPS_FM1216ME_MK3;
+
+- printk(KERN_INFO "%s: Leadtek Winfast 2000XP Expert config: "
+- "tuner=%d, eeprom[0]=0x%02x\n",
+- core->name, core->board.tuner_type, eeprom_data[0]);
++ info_printk(core, "Leadtek Winfast 2000XP Expert config: "
++ "tuner=%d, eeprom[0]=0x%02x\n",
++ core->board.tuner_type, eeprom_data[0]);
+ }
+
+ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
+@@ -1785,13 +2074,12 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
+ /* known */
+ break;
+ default:
+- printk("%s: warning: unknown hauppauge model #%d\n",
+- core->name, tv.model);
++ warn_printk(core, "warning: unknown hauppauge model #%d\n",
++ tv.model);
+ break;
+ }
+
+- printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n",
+- core->name, tv.model);
++ info_printk(core, "hauppauge eeprom: model=%d\n", tv.model);
+ }
+
+ /* ----------------------------------------------------------------------- */
+@@ -1837,8 +2125,7 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data)
+ char *name = (eeprom_data[0x0d] < ARRAY_SIZE(gdi_tuner))
+ ? gdi_tuner[eeprom_data[0x0d]].name : NULL;
+
+- printk(KERN_INFO "%s: GDI: tuner=%s\n", core->name,
+- name ? name : "unknown");
++ info_printk(core, "GDI: tuner=%s\n", name ? name : "unknown");
+ if (NULL == name)
+ return;
+ core->board.tuner_type = gdi_tuner[eeprom_data[0x0d]].id;
+@@ -1846,6 +2133,75 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data)
+ CX88_RADIO : 0;
+ }
+
++/* ------------------------------------------------------------------- */
++/* some Divco specific stuff */
++static int cx88_dvico_xc2028_callback(struct cx88_core *core,
++ int command, int arg)
++{
++ switch (command) {
++ case XC2028_TUNER_RESET:
++ cx_write(MO_GP0_IO, 0x101000);
++ mdelay(5);
++ cx_set(MO_GP0_IO, 0x101010);
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++
++/* ----------------------------------------------------------------------- */
++/* some Geniatech specific stuff */
++
++static int cx88_xc3028_geniatech_tuner_callback(struct cx88_core *core,
++ int command, int mode)
++{
++ switch (command) {
++ case XC2028_TUNER_RESET:
++ switch (INPUT(core->input).type) {
++ case CX88_RADIO:
++ break;
++ case CX88_VMUX_DVB:
++ cx_write(MO_GP1_IO, 0x030302);
++ mdelay(50);
++ break;
++ default:
++ cx_write(MO_GP1_IO, 0x030301);
++ mdelay(50);
++ }
++ cx_write(MO_GP1_IO, 0x101010);
++ mdelay(50);
++ cx_write(MO_GP1_IO, 0x101000);
++ mdelay(50);
++ cx_write(MO_GP1_IO, 0x101010);
++ mdelay(50);
++ return 0;
++ }
++ return -EINVAL;
++}
++
++/* ------------------------------------------------------------------- */
++/* some Divco specific stuff */
++static int cx88_pv_8000gt_callback(struct cx88_core *core,
++ int command, int arg)
++{
++ switch (command) {
++ case XC2028_TUNER_RESET:
++ cx_write(MO_GP2_IO, 0xcf7);
++ mdelay(50);
++ cx_write(MO_GP2_IO, 0xef5);
++ mdelay(50);
++ cx_write(MO_GP2_IO, 0xcf7);
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
+ /* ----------------------------------------------------------------------- */
+ /* some DViCO specific stuff */
+
+@@ -1874,32 +2230,85 @@ static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core)
+ msg.len = (i != 12 ? 5 : 2);
+ err = i2c_transfer(&core->i2c_adap, &msg, 1);
+ if (err != 1) {
+- printk("dvico_fusionhdtv_hybrid_init buf %d failed (err = %d)!\n", i, err);
++ warn_printk(core, "dvico_fusionhdtv_hybrid_init buf %d "
++ "failed (err = %d)!\n", i, err);
+ return;
+ }
+ }
+ }
+
++static int cx88_xc2028_tuner_callback(struct cx88_core *core,
++ int command, int arg)
++{
++ /* Board-specific callbacks */
++ switch (core->boardnr) {
++ case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
++ case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
++ case CX88_BOARD_GENIATECH_X8000_MT:
++ case CX88_BOARD_KWORLD_ATSC_120:
++ return cx88_xc3028_geniatech_tuner_callback(core,
++ command, arg);
++ case CX88_BOARD_PROLINK_PV_8000GT:
++ return cx88_pv_8000gt_callback(core, command, arg);
++ case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
++ return cx88_dvico_xc2028_callback(core, command, arg);
++ }
++
++ switch (command) {
++ case XC2028_TUNER_RESET:
++ switch (INPUT(core->input).type) {
++ case CX88_RADIO:
++ info_printk(core, "setting GPIO to radio!\n");
++ cx_write(MO_GP0_IO, 0x4ff);
++ mdelay(250);
++ cx_write(MO_GP2_IO, 0xff);
++ mdelay(250);
++ break;
++ case CX88_VMUX_DVB: /* Digital TV*/
++ default: /* Analog TV */
++ info_printk(core, "setting GPIO to TV!\n");
++ break;
++ }
++ cx_write(MO_GP1_IO, 0x101010);
++ mdelay(250);
++ cx_write(MO_GP1_IO, 0x101000);
++ mdelay(250);
++ cx_write(MO_GP1_IO, 0x101010);
++ mdelay(250);
++ return 0;
++ }
++ return -EINVAL;
++}
++
+ /* ----------------------------------------------------------------------- */
+ /* Tuner callback function. Currently only needed for the Pinnacle *
+ * PCTV HD 800i with an xc5000 sillicon tuner. This is used for both *
+ * analog tuner attach (tuner-core.c) and dvb tuner attach (cx88-dvb.c) */
+
+-int cx88_tuner_callback(void *priv, int command, int arg)
++static int cx88_xc5000_tuner_callback(struct cx88_core *core,
++ int command, int arg)
+ {
+- struct i2c_algo_bit_data *i2c_algo = priv;
+- struct cx88_core *core = i2c_algo->data;
+-
+- switch(core->boardnr) {
++ switch (core->boardnr) {
+ case CX88_BOARD_PINNACLE_PCTV_HD_800i:
+- if(command == 0) { /* This is the reset command from xc5000 */
++ if (command == 0) { /* This is the reset command from xc5000 */
+ /* Reset XC5000 tuner via SYS_RSTO_pin */
+ cx_write(MO_SRST_IO, 0);
+ msleep(10);
+ cx_write(MO_SRST_IO, 1);
+ return 0;
++ } else {
++ err_printk(core, "xc5000: unknown tuner "
++ "callback command.\n");
++ return -EINVAL;
+ }
+- else {
++ break;
++ case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
++ if (command == 0) { /* This is the reset command from xc5000 */
++ cx_clear(MO_GP0_IO, 0x00000010);
++ msleep(10);
++ cx_set(MO_GP0_IO, 0x00000010);
++ return 0;
++ } else {
+ printk(KERN_ERR
+ "xc5000: unknown tuner callback command.\n");
+ return -EINVAL;
+@@ -1908,6 +2317,36 @@ int cx88_tuner_callback(void *priv, int command, int arg)
+ }
+ return 0; /* Should never be here */
+ }
++
++int cx88_tuner_callback(void *priv, int command, int arg)
++{
++ struct i2c_algo_bit_data *i2c_algo = priv;
++ struct cx88_core *core;
++
++ if (!i2c_algo) {
++ printk(KERN_ERR "cx88: Error - i2c private data undefined.\n");
++ return -EINVAL;
++ }
++
++ core = i2c_algo->data;
++
++ if (!core) {
++ printk(KERN_ERR "cx88: Error - device struct undefined.\n");
++ return -EINVAL;
++ }
++
++ switch (core->board.tuner_type) {
++ case TUNER_XC2028:
++ info_printk(core, "Calling XC2028/3028 callback\n");
++ return cx88_xc2028_tuner_callback(core, command, arg);
++ case TUNER_XC5000:
++ info_printk(core, "Calling XC5000 callback\n");
++ return cx88_xc5000_tuner_callback(core, command, arg);
++ }
++ err_printk(core, "Error: Calling callback for tuner %d\n",
++ core->board.tuner_type);
++ return -EINVAL;
++}
+ EXPORT_SYMBOL(cx88_tuner_callback);
+
+ /* ----------------------------------------------------------------------- */
+@@ -1918,23 +2357,25 @@ static void cx88_card_list(struct cx88_core *core, struct pci_dev *pci)
+
+ if (0 == pci->subsystem_vendor &&
+ 0 == pci->subsystem_device) {
+- printk("%s: Your board has no valid PCI Subsystem ID and thus can't\n"
++ printk(KERN_ERR
++ "%s: Your board has no valid PCI Subsystem ID and thus can't\n"
+ "%s: be autodetected. Please pass card=<n> insmod option to\n"
+ "%s: workaround that. Redirect complaints to the vendor of\n"
+ "%s: the TV card. Best regards,\n"
+ "%s: -- tux\n",
+ core->name,core->name,core->name,core->name,core->name);
+ } else {
+- printk("%s: Your board isn't known (yet) to the driver. You can\n"
++ printk(KERN_ERR
++ "%s: Your board isn't known (yet) to the driver. You can\n"
+ "%s: try to pick one of the existing card configs via\n"
+ "%s: card=<n> insmod option. Updating to the latest\n"
+ "%s: version might help as well.\n",
+ core->name,core->name,core->name,core->name);
+ }
+- printk("%s: Here is a list of valid choices for the card=<n> insmod option:\n",
+- core->name);
++ err_printk(core, "Here is a list of valid choices for the card=<n> "
++ "insmod option:\n");
+ for (i = 0; i < ARRAY_SIZE(cx88_boards); i++)
+- printk("%s: card=%d -> %s\n",
++ printk(KERN_ERR "%s: card=%d -> %s\n",
+ core->name, i, cx88_boards[i].name);
+ }
+
+@@ -1951,9 +2392,57 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core)
+ cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */
+ udelay(1000);
+ break;
++
++ case CX88_BOARD_PROLINK_PV_8000GT:
++ cx_write(MO_GP2_IO, 0xcf7);
++ mdelay(50);
++ cx_write(MO_GP2_IO, 0xef5);
++ mdelay(50);
++ cx_write(MO_GP2_IO, 0xcf7);
++ msleep(10);
++ break;
++
++ case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
++ /* Enable the xc5000 tuner */
++ cx_set(MO_GP0_IO, 0x00001010);
++ break;
+ }
+ }
+
++/*
++ * Sets board-dependent xc3028 configuration
++ */
++void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl)
++{
++ memset(ctl, 0, sizeof(*ctl));
++
++ ctl->fname = XC2028_DEFAULT_FIRMWARE;
++ ctl->max_len = 64;
++
++ switch (core->boardnr) {
++ case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
++ /* Doesn't work with firmware version 2.7 */
++ ctl->fname = "xc3028-v25.fw";
++ break;
++ case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
++ ctl->scode_table = XC3028_FE_ZARLINK456;
++ break;
++ case CX88_BOARD_KWORLD_ATSC_120:
++ case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
++ ctl->demod = XC3028_FE_OREN538;
++ break;
++ case CX88_BOARD_PROLINK_PV_8000GT:
++ /*
++ * This board uses non-MTS firmware
++ */
++ break;
++ default:
++ ctl->demod = XC3028_FE_OREN538;
++ ctl->mts = 1;
++ }
++}
++EXPORT_SYMBOL_GPL(cx88_setup_xc3028);
++
+ static void cx88_card_setup(struct cx88_core *core)
+ {
+ static u8 eeprom[256];
+@@ -1991,6 +2480,13 @@ static void cx88_card_setup(struct cx88_core *core)
+ cx_write(MO_GP0_IO, 0x000007f8);
+ cx_write(MO_GP1_IO, 0x00000001);
+ break;
++ case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
++ /* GPIO0:0 is hooked to demod reset */
++ /* GPIO0:4 is hooked to xc3028 reset */
++ cx_write(MO_GP0_IO, 0x00111100);
++ msleep(1);
++ cx_write(MO_GP0_IO, 0x00111111);
++ break;
+ case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
+ /* GPIO0:6 is hooked to FX2 reset pin */
+ cx_set(MO_GP0_IO, 0x00004040);
+@@ -2038,10 +2534,8 @@ static void cx88_card_setup(struct cx88_core *core)
+ for (i = 0; i < ARRAY_SIZE(buffer); i++)
+ if (2 != i2c_master_send(&core->i2c_client,
+ buffer[i],2))
+- printk(KERN_WARNING
+- "%s: Unable to enable "
+- "tuner(%i).\n",
+- core->name, i);
++ warn_printk(core, "Unable to enable "
++ "tuner(%i).\n", i);
+ }
+ break;
+ case CX88_BOARD_MSI_TVANYWHERE_MASTER:
+@@ -2062,6 +2556,22 @@ static void cx88_card_setup(struct cx88_core *core)
+ cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tea5767_cfg);
+ }
+ }
++
++ if (core->board.tuner_type == TUNER_XC2028) {
++ struct v4l2_priv_tun_config xc2028_cfg;
++ struct xc2028_ctrl ctl;
++
++ /* Fills device-dependent initialization parameters */
++ cx88_setup_xc3028(core, &ctl);
++
++ /* Sends parameters to xc2028/3028 tuner */
++ memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
++ xc2028_cfg.tuner = TUNER_XC2028;
++ xc2028_cfg.priv = &ctl;
++ info_printk(core, "Asking xc2028/3028 to load firmware %s\n",
++ ctl.fname);
++ cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &xc2028_cfg);
++ }
+ }
+
+ /* ------------------------------------------------------------------ */
+@@ -2178,9 +2688,8 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
+
+ memcpy(&core->board, &cx88_boards[core->boardnr], sizeof(core->board));
+
+- printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+- core->name,pci->subsystem_vendor,
+- pci->subsystem_device, core->board.name,
++ info_printk(core, "subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
++ pci->subsystem_vendor, pci->subsystem_device, core->board.name,
+ core->boardnr, card[core->nr] == core->boardnr ?
+ "insmod option" : "autodetected");
+
+@@ -2189,8 +2698,8 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
+ if (radio[core->nr] != UNSET)
+ core->board.radio_type = radio[core->nr];
+
+- printk(KERN_INFO "%s: TV tuner type %d, Radio tuner type %d\n",
+- core->name, core->board.tuner_type, core->board.radio_type);
++ info_printk(core, "TV tuner type %d, Radio tuner type %d\n",
++ core->board.tuner_type, core->board.radio_type);
+
+ /* init hardware */
+ cx88_reset(core);
+@@ -2207,12 +2716,3 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
+
+ return core;
+ }
+-
+-/* ------------------------------------------------------------------ */
+-
+-/*
+- * Local variables:
+- * c-basic-offset: 8
+- * End:
+- * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
+- */
+diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
+index 01e2ac9..c4d1aff 100644
+--- a/drivers/media/video/cx88/cx88-core.c
++++ b/drivers/media/video/cx88/cx88-core.c
+@@ -47,15 +47,15 @@ MODULE_LICENSE("GPL");
+
+ /* ------------------------------------------------------------------ */
+
+-static unsigned int core_debug = 0;
++static unsigned int core_debug;
+ module_param(core_debug,int,0644);
+ MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
+
+-static unsigned int nicam = 0;
++static unsigned int nicam;
+ module_param(nicam,int,0644);
+ MODULE_PARM_DESC(nicam,"tv audio is nicam");
+
+-static unsigned int nocomb = 0;
++static unsigned int nocomb;
+ module_param(nocomb,int,0644);
+ MODULE_PARM_DESC(nocomb,"disable comb filter");
+
+@@ -219,7 +219,7 @@ cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf)
+ videobuf_waiton(&buf->vb,0,0);
+ videobuf_dma_unmap(q, dma);
+ videobuf_dma_free(dma);
+- btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc);
++ btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
+ buf->vb.state = VIDEOBUF_NEEDS_INIT;
+ }
+
+@@ -548,7 +548,7 @@ void cx88_wakeup(struct cx88_core *core,
+ mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+ }
+ if (bc != 1)
+- printk("%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc);
++ printk("%s: %d buffers handled (should be 1)\n",__func__,bc);
+ }
+
+ void cx88_shutdown(struct cx88_core *core)
+@@ -577,7 +577,7 @@ void cx88_shutdown(struct cx88_core *core)
+
+ int cx88_reset(struct cx88_core *core)
+ {
+- dprintk(1,"%s\n",__FUNCTION__);
++ dprintk(1,"%s\n",__func__);
+ cx88_shutdown(core);
+
+ /* clear irq status */
+@@ -929,7 +929,10 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
+
+ dprintk(1,"set_tvnorm: MO_INPUT_FORMAT 0x%08x [old=0x%08x]\n",
+ cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
+- cx_andor(MO_INPUT_FORMAT, 0xf, cxiformat);
++ /* Chroma AGC must be disabled if SECAM is used, we enable it
++ by default on PAL and NTSC */
++ cx_andor(MO_INPUT_FORMAT, 0x40f,
++ norm & V4L2_STD_SECAM ? cxiformat : cxiformat | 0x400);
+
+ // FIXME: as-is from DScaler
+ dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
+diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
+index f7b41eb..1c7fe68 100644
+--- a/drivers/media/video/cx88/cx88-dvb.c
++++ b/drivers/media/video/cx88/cx88-dvb.c
+@@ -45,16 +45,21 @@
+ #include "nxt200x.h"
+ #include "cx24123.h"
+ #include "isl6421.h"
++#include "tuner-simple.h"
++#include "tda9887.h"
++#include "s5h1411.h"
+
+ MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
+ MODULE_AUTHOR("Chris Pascoe <c.pascoe at itee.uq.edu.au>");
+ MODULE_AUTHOR("Gerd Knorr <kraxel at bytesex.org> [SuSE Labs]");
+ MODULE_LICENSE("GPL");
+
+-static unsigned int debug = 0;
++static unsigned int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug,"enable debug messages [dvb]");
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define dprintk(level,fmt, arg...) if (debug >= level) \
+ printk(KERN_DEBUG "%s/2-dvb: " fmt, core->name, ## arg)
+
+@@ -235,6 +240,19 @@ static struct zl10353_config dvico_fusionhdtv_hybrid = {
+ .no_tuner = 1,
+ };
+
++static struct zl10353_config dvico_fusionhdtv_xc3028 = {
++ .demod_address = 0x0f,
++ .if2 = 45600,
++ .no_tuner = 1,
++};
++
++static struct mt352_config dvico_fusionhdtv_mt352_xc3028 = {
++ .demod_address = 0x0f,
++ .if2 = 4560,
++ .no_tuner = 1,
++ .demod_init = dvico_fusionhdtv_demod_init,
++};
++
+ static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = {
+ .demod_address = 0x0f,
+ };
+@@ -266,7 +284,7 @@ static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index)
+ struct cx8802_dev *dev= fe->dvb->priv;
+ struct cx88_core *core = dev->core;
+
+- dprintk(1, "%s: index = %d\n", __FUNCTION__, index);
++ dprintk(1, "%s: index = %d\n", __func__, index);
+ if (index == 0)
+ cx_clear(MO_GP0_IO, 8);
+ else
+@@ -357,6 +375,40 @@ static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe,
+ return 0;
+ }
+
++static int cx88_pci_nano_callback(void *ptr, int command, int arg)
++{
++ struct cx88_core *core = ptr;
++
++ switch (command) {
++ case XC2028_TUNER_RESET:
++ /* Send the tuner in then out of reset */
++ dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg);
++
++ switch (core->boardnr) {
++ case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
++ /* GPIO-4 xc3028 tuner */
++
++ cx_set(MO_GP0_IO, 0x00001000);
++ cx_clear(MO_GP0_IO, 0x00000010);
++ msleep(100);
++ cx_set(MO_GP0_IO, 0x00000010);
++ msleep(100);
++ break;
++ }
++
++ break;
++ case XC2028_RESET_CLK:
++ dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg);
++ break;
++ default:
++ dprintk(1, "%s: unknown command %d, arg %d\n", __func__,
++ command, arg);
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
+ static struct cx24123_config geniatech_dvbs_config = {
+ .demod_address = 0x55,
+ .set_ts_params = cx24123_set_ts_param,
+@@ -383,12 +435,92 @@ static struct s5h1409_config pinnacle_pctv_hd_800i_config = {
+ .mpeg_timing = S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK,
+ };
+
++static struct s5h1409_config dvico_hdtv5_pci_nano_config = {
++ .demod_address = 0x32 >> 1,
++ .output_mode = S5H1409_SERIAL_OUTPUT,
++ .gpio = S5H1409_GPIO_OFF,
++ .inversion = S5H1409_INVERSION_OFF,
++ .status_mode = S5H1409_DEMODLOCKING,
++ .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
++};
++
++static struct s5h1409_config kworld_atsc_120_config = {
++ .demod_address = 0x32 >> 1,
++ .output_mode = S5H1409_SERIAL_OUTPUT,
++ .gpio = S5H1409_GPIO_OFF,
++ .inversion = S5H1409_INVERSION_OFF,
++ .status_mode = S5H1409_DEMODLOCKING,
++ .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
++};
++
+ static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = {
+ .i2c_address = 0x64,
+ .if_khz = 5380,
+ .tuner_callback = cx88_tuner_callback,
+ };
+
++static struct zl10353_config cx88_geniatech_x8000_mt = {
++ .demod_address = (0x1e >> 1),
++ .no_tuner = 1,
++};
++
++static struct s5h1411_config dvico_fusionhdtv7_config = {
++ .output_mode = S5H1411_SERIAL_OUTPUT,
++ .gpio = S5H1411_GPIO_ON,
++ .mpeg_timing = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
++ .qam_if = S5H1411_IF_44000,
++ .vsb_if = S5H1411_IF_44000,
++ .inversion = S5H1411_INVERSION_OFF,
++ .status_mode = S5H1411_DEMODLOCKING
++};
++
++static struct xc5000_config dvico_fusionhdtv7_tuner_config = {
++ .i2c_address = 0xc2 >> 1,
++ .if_khz = 5380,
++ .tuner_callback = cx88_tuner_callback,
++};
++
++static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
++{
++ struct dvb_frontend *fe;
++ struct xc2028_ctrl ctl;
++ struct xc2028_config cfg = {
++ .i2c_adap = &dev->core->i2c_adap,
++ .i2c_addr = addr,
++ .ctrl = &ctl,
++ .callback = cx88_tuner_callback,
++ };
++
++ if (!dev->dvb.frontend) {
++ printk(KERN_ERR "%s/2: dvb frontend not attached. "
++ "Can't attach xc3028\n",
++ dev->core->name);
++ return -EINVAL;
++ }
++
++ /*
++ * Some xc3028 devices may be hidden by an I2C gate. This is known
++ * to happen with some s5h1409-based devices.
++ * Now that I2C gate is open, sets up xc3028 configuration
++ */
++ cx88_setup_xc3028(dev->core, &ctl);
++
++ fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg);
++ if (!fe) {
++ printk(KERN_ERR "%s/2: xc3028 attach failed\n",
++ dev->core->name);
++ dvb_frontend_detach(dev->dvb.frontend);
++ dvb_unregister_frontend(dev->dvb.frontend);
++ dev->dvb.frontend = NULL;
++ return -EINVAL;
++ }
++
++ printk(KERN_INFO "%s/2: xc3028 attached\n",
++ dev->core->name);
++
++ return 0;
++}
++
+ static int dvb_register(struct cx8802_dev *dev)
+ {
+ /* init struct videobuf_dvb */
+@@ -429,8 +561,9 @@ static int dvb_register(struct cx8802_dev *dev)
+ &hauppauge_hvr_config,
+ &dev->core->i2c_adap);
+ if (dev->dvb.frontend != NULL) {
+- dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+- &dev->core->i2c_adap, DVB_PLL_FMD1216ME);
++ dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++ &dev->core->i2c_adap, 0x61,
++ TUNER_PHILIPS_FMD1216ME_MK3);
+ }
+ break;
+ case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
+@@ -497,8 +630,9 @@ static int dvb_register(struct cx8802_dev *dev)
+ dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
+ &dev->vp3054->adap);
+ if (dev->dvb.frontend != NULL) {
+- dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+- &dev->core->i2c_adap, DVB_PLL_FMD1216ME);
++ dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++ &dev->core->i2c_adap, 0x61,
++ TUNER_PHILIPS_FMD1216ME_MK3);
+ }
+ #else
+ printk(KERN_ERR "%s/2: built without vp3054 support\n", dev->core->name);
+@@ -509,18 +643,36 @@ static int dvb_register(struct cx8802_dev *dev)
+ &dvico_fusionhdtv_hybrid,
+ &dev->core->i2c_adap);
+ if (dev->dvb.frontend != NULL) {
+- dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+- &dev->core->i2c_adap,
+- DVB_PLL_THOMSON_FE6600);
++ dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++ &dev->core->i2c_adap, 0x61,
++ TUNER_THOMSON_FE6600);
+ }
+ break;
++ case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
++ dev->dvb.frontend = dvb_attach(zl10353_attach,
++ &dvico_fusionhdtv_xc3028,
++ &dev->core->i2c_adap);
++ if (dev->dvb.frontend == NULL)
++ dev->dvb.frontend = dvb_attach(mt352_attach,
++ &dvico_fusionhdtv_mt352_xc3028,
++ &dev->core->i2c_adap);
++ /*
++ * On this board, the demod provides the I2C bus pullup.
++ * We must not permit gate_ctrl to be performed, or
++ * the xc3028 cannot communicate on the bus.
++ */
++ if (dev->dvb.frontend)
++ dev->dvb.frontend->ops.i2c_gate_ctrl = NULL;
++ if (attach_xc3028(0x61, dev) < 0)
++ return -EINVAL;
++ break;
+ case CX88_BOARD_PCHDTV_HD3000:
+ dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
+ &dev->core->i2c_adap);
+ if (dev->dvb.frontend != NULL) {
+- dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+- &dev->core->i2c_adap,
+- DVB_PLL_THOMSON_DTT761X);
++ dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++ &dev->core->i2c_adap, 0x61,
++ TUNER_THOMSON_DTT761X);
+ }
+ break;
+ case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
+@@ -540,9 +692,9 @@ static int dvb_register(struct cx8802_dev *dev)
+ &fusionhdtv_3_gold,
+ &dev->core->i2c_adap);
+ if (dev->dvb.frontend != NULL) {
+- dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+- &dev->core->i2c_adap,
+- DVB_PLL_MICROTUNE_4042);
++ dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++ &dev->core->i2c_adap, 0x61,
++ TUNER_MICROTUNE_4042FI5);
+ }
+ }
+ break;
+@@ -560,9 +712,9 @@ static int dvb_register(struct cx8802_dev *dev)
+ &fusionhdtv_3_gold,
+ &dev->core->i2c_adap);
+ if (dev->dvb.frontend != NULL) {
+- dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+- &dev->core->i2c_adap,
+- DVB_PLL_THOMSON_DTT761X);
++ dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++ &dev->core->i2c_adap, 0x61,
++ TUNER_THOMSON_DTT761X);
+ }
+ }
+ break;
+@@ -580,9 +732,11 @@ static int dvb_register(struct cx8802_dev *dev)
+ &fusionhdtv_5_gold,
+ &dev->core->i2c_adap);
+ if (dev->dvb.frontend != NULL) {
+- dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+- &dev->core->i2c_adap,
+- DVB_PLL_LG_TDVS_H06XF);
++ dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++ &dev->core->i2c_adap, 0x61,
++ TUNER_LG_TDVS_H06XF);
++ dvb_attach(tda9887_attach, dev->dvb.frontend,
++ &dev->core->i2c_adap, 0x43);
+ }
+ }
+ break;
+@@ -600,9 +754,11 @@ static int dvb_register(struct cx8802_dev *dev)
+ &pchdtv_hd5500,
+ &dev->core->i2c_adap);
+ if (dev->dvb.frontend != NULL) {
+- dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+- &dev->core->i2c_adap,
+- DVB_PLL_LG_TDVS_H06XF);
++ dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++ &dev->core->i2c_adap, 0x61,
++ TUNER_LG_TDVS_H06XF);
++ dvb_attach(tda9887_attach, dev->dvb.frontend,
++ &dev->core->i2c_adap, 0x43);
+ }
+ }
+ break;
+@@ -611,8 +767,9 @@ static int dvb_register(struct cx8802_dev *dev)
+ &ati_hdtvwonder,
+ &dev->core->i2c_adap);
+ if (dev->dvb.frontend != NULL) {
+- dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+- NULL, DVB_PLL_TUV1236D);
++ dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++ &dev->core->i2c_adap, 0x61,
++ TUNER_PHILIPS_TUV1236D);
+ }
+ break;
+ case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
+@@ -658,14 +815,77 @@ static int dvb_register(struct cx8802_dev *dev)
+ &pinnacle_pctv_hd_800i_tuner_config);
+ }
+ break;
++ case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
++ dev->dvb.frontend = dvb_attach(s5h1409_attach,
++ &dvico_hdtv5_pci_nano_config,
++ &dev->core->i2c_adap);
++ if (dev->dvb.frontend != NULL) {
++ struct dvb_frontend *fe;
++ struct xc2028_config cfg = {
++ .i2c_adap = &dev->core->i2c_adap,
++ .i2c_addr = 0x61,
++ .callback = cx88_pci_nano_callback,
++ };
++ static struct xc2028_ctrl ctl = {
++ .fname = "xc3028-v27.fw",
++ .max_len = 64,
++ .scode_table = XC3028_FE_OREN538,
++ };
++
++ fe = dvb_attach(xc2028_attach,
++ dev->dvb.frontend, &cfg);
++ if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
++ fe->ops.tuner_ops.set_config(fe, &ctl);
++ }
++ break;
++ case CX88_BOARD_PINNACLE_HYBRID_PCTV:
++ dev->dvb.frontend = dvb_attach(zl10353_attach,
++ &cx88_geniatech_x8000_mt,
++ &dev->core->i2c_adap);
++ if (attach_xc3028(0x61, dev) < 0)
++ return -EINVAL;
++ break;
++ case CX88_BOARD_GENIATECH_X8000_MT:
++ dev->ts_gen_cntrl = 0x00;
++
++ dev->dvb.frontend = dvb_attach(zl10353_attach,
++ &cx88_geniatech_x8000_mt,
++ &dev->core->i2c_adap);
++ if (attach_xc3028(0x61, dev) < 0)
++ return -EINVAL;
++ break;
++ case CX88_BOARD_KWORLD_ATSC_120:
++ dev->dvb.frontend = dvb_attach(s5h1409_attach,
++ &kworld_atsc_120_config,
++ &dev->core->i2c_adap);
++ if (attach_xc3028(0x61, dev) < 0)
++ return -EINVAL;
++ break;
++ case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
++ dev->dvb.frontend = dvb_attach(s5h1411_attach,
++ &dvico_fusionhdtv7_config,
++ &dev->core->i2c_adap);
++ if (dev->dvb.frontend != NULL) {
++ /* tuner_config.video_dev must point to
++ * i2c_adap.algo_data
++ */
++ dvico_fusionhdtv7_tuner_config.priv =
++ dev->core->i2c_adap.algo_data;
++ dvb_attach(xc5000_attach, dev->dvb.frontend,
++ &dev->core->i2c_adap,
++ &dvico_fusionhdtv7_tuner_config);
++ }
++ break;
+ default:
+ printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
+ dev->core->name);
+ break;
+ }
+ if (NULL == dev->dvb.frontend) {
+- printk(KERN_ERR "%s/2: frontend initialization failed\n", dev->core->name);
+- return -1;
++ printk(KERN_ERR
++ "%s/2: frontend initialization failed\n",
++ dev->core->name);
++ return -EINVAL;
+ }
+
+ /* Ensure all frontends negotiate bus access */
+@@ -675,7 +895,8 @@ static int dvb_register(struct cx8802_dev *dev)
+ cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
+
+ /* register everything */
+- return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev);
++ return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev,
++ &dev->pci->dev, adapter_nr);
+ }
+
+ /* ----------------------------------------------------------- */
+@@ -685,7 +906,7 @@ static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv)
+ {
+ struct cx88_core *core = drv->core;
+ int err = 0;
+- dprintk( 1, "%s\n", __FUNCTION__);
++ dprintk( 1, "%s\n", __func__);
+
+ switch (core->boardnr) {
+ case CX88_BOARD_HAUPPAUGE_HVR1300:
+@@ -708,7 +929,7 @@ static int cx8802_dvb_advise_release(struct cx8802_driver *drv)
+ {
+ struct cx88_core *core = drv->core;
+ int err = 0;
+- dprintk( 1, "%s\n", __FUNCTION__);
++ dprintk( 1, "%s\n", __func__);
+
+ switch (core->boardnr) {
+ case CX88_BOARD_HAUPPAUGE_HVR1300:
+@@ -726,7 +947,7 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
+ struct cx8802_dev *dev = drv->core->dvbdev;
+ int err;
+
+- dprintk( 1, "%s\n", __FUNCTION__);
++ dprintk( 1, "%s\n", __func__);
+ dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
+ core->boardnr,
+ core->name,
+@@ -744,8 +965,8 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
+
+ /* dvb stuff */
+ printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name);
+- videobuf_queue_pci_init(&dev->dvb.dvbq, &dvb_qops,
+- dev->pci, &dev->slock,
++ videobuf_queue_sg_init(&dev->dvb.dvbq, &dvb_qops,
++ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_TOP,
+ sizeof(struct cx88_buffer),
+@@ -764,7 +985,8 @@ static int cx8802_dvb_remove(struct cx8802_driver *drv)
+ struct cx8802_dev *dev = drv->core->dvbdev;
+
+ /* dvb */
+- videobuf_dvb_unregister(&dev->dvb);
++ if (dev->dvb.frontend)
++ videobuf_dvb_unregister(&dev->dvb);
+
+ vp3054_i2c_remove(dev);
+
+diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
+index 566b26a..c6b4473 100644
+--- a/drivers/media/video/cx88/cx88-i2c.c
++++ b/drivers/media/video/cx88/cx88-i2c.c
+@@ -35,11 +35,11 @@
+ #include "cx88.h"
+ #include <media/v4l2-common.h>
+
+-static unsigned int i2c_debug = 0;
++static unsigned int i2c_debug;
+ module_param(i2c_debug, int, 0644);
+ MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]");
+
+-static unsigned int i2c_scan = 0;
++static unsigned int i2c_scan;
+ module_param(i2c_scan, int, 0444);
+ MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
+
+diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
+index bb0911b..53526d9 100644
+--- a/drivers/media/video/cx88/cx88-input.c
++++ b/drivers/media/video/cx88/cx88-input.c
+@@ -57,7 +57,7 @@ struct cx88_IR {
+ u32 mask_keyup;
+ };
+
+-static int ir_debug = 0;
++static int ir_debug;
+ module_param(ir_debug, int, 0644); /* debug level [IR] */
+ MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
+
+@@ -258,6 +258,13 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
+ ir->mask_keyup = 0x80;
+ ir->polling = 1; /* ms */
+ break;
++ case CX88_BOARD_PROLINK_PV_8000GT:
++ ir_codes = ir_codes_pixelview_new;
++ ir->gpio_addr = MO_GP1_IO;
++ ir->mask_keycode = 0x3f;
++ ir->mask_keyup = 0x80;
++ ir->polling = 1; /* ms */
++ break;
+ case CX88_BOARD_KWORLD_LTV883:
+ ir_codes = ir_codes_pixelview;
+ ir->gpio_addr = MO_GP1_IO;
+@@ -310,6 +317,12 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
+ ir_type = IR_TYPE_RC5;
+ ir->sampling = 1;
+ break;
++ case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
++ ir_codes = ir_codes_powercolor_real_angel;
++ ir->gpio_addr = MO_GP2_IO;
++ ir->mask_keycode = 0x7e;
++ ir->polling = 100; /* ms */
++ break;
+ }
+
+ if (NULL == ir_codes) {
+diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
+index e357f41..a6b061c 100644
+--- a/drivers/media/video/cx88/cx88-mpeg.c
++++ b/drivers/media/video/cx88/cx88-mpeg.c
+@@ -39,7 +39,7 @@ MODULE_AUTHOR("Chris Pascoe <c.pascoe at itee.uq.edu.au>");
+ MODULE_AUTHOR("Gerd Knorr <kraxel at bytesex.org> [SuSE Labs]");
+ MODULE_LICENSE("GPL");
+
+-static unsigned int debug = 0;
++static unsigned int debug;
+ module_param(debug,int,0644);
+ MODULE_PARM_DESC(debug,"enable debug messages [mpeg]");
+
+@@ -146,7 +146,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
+ cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */
+ udelay(100);
+ } else {
+- printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __FUNCTION__,
++ printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __func__,
+ core->board.mpeg );
+ return -EINVAL;
+ }
+@@ -247,7 +247,7 @@ int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev,
+ struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+ int rc;
+
+- dprintk(1, "%s: %p\n", __FUNCTION__, buf);
++ dprintk(1, "%s: %p\n", __func__, buf);
+ if (0 != buf->vb.baddr && buf->vb.bsize < size)
+ return -EINVAL;
+
+@@ -289,7 +289,7 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
+ buf->count = cx88q->count++;
+ mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT);
+ dprintk(1,"[%p/%d] %s - first active\n",
+- buf, buf->vb.i, __FUNCTION__);
++ buf, buf->vb.i, __func__);
+
+ } else {
+ dprintk( 1, "queue is not empty - append to active\n" );
+@@ -299,7 +299,7 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
+ buf->count = cx88q->count++;
+ prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+ dprintk( 1, "[%p/%d] %s - append to active\n",
+- buf, buf->vb.i, __FUNCTION__);
++ buf, buf->vb.i, __func__);
+ }
+ }
+
+@@ -342,7 +342,7 @@ static void cx8802_timeout(unsigned long data)
+ {
+ struct cx8802_dev *dev = (struct cx8802_dev*)data;
+
+- dprintk(1, "%s\n",__FUNCTION__);
++ dprintk(1, "%s\n",__func__);
+
+ if (debug)
+ cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
+@@ -613,6 +613,8 @@ static int cx8802_request_acquire(struct cx8802_driver *drv)
+ core->active_type_id != drv->type_id)
+ return -EBUSY;
+
++ core->input = CX88_VMUX_DVB;
++
+ if (drv->advise_acquire)
+ {
+ mutex_lock(&drv->core->lock);
+@@ -623,7 +625,7 @@ static int cx8802_request_acquire(struct cx8802_driver *drv)
+ }
+ mutex_unlock(&drv->core->lock);
+
+- mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO));
++ mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
+ }
+
+ return 0;
+@@ -639,7 +641,7 @@ static int cx8802_request_release(struct cx8802_driver *drv)
+ {
+ drv->advise_release(drv);
+ core->active_type_id = CX88_BOARD_NONE;
+- mpeg_dbg(1,"%s() Post release GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO));
++ mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
+ }
+ mutex_unlock(&drv->core->lock);
+
+@@ -813,7 +815,7 @@ static void __devexit cx8802_remove(struct pci_dev *pci_dev)
+
+ dev = pci_get_drvdata(pci_dev);
+
+- dprintk( 1, "%s\n", __FUNCTION__);
++ dprintk( 1, "%s\n", __func__);
+
+ if (!list_empty(&dev->drvlist)) {
+ struct cx8802_driver *drv, *tmp;
+diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
+index 76e5c78..3a1977f 100644
+--- a/drivers/media/video/cx88/cx88-tvaudio.c
++++ b/drivers/media/video/cx88/cx88-tvaudio.c
+@@ -53,15 +53,15 @@
+
+ #include "cx88.h"
+
+-static unsigned int audio_debug = 0;
++static unsigned int audio_debug;
+ module_param(audio_debug, int, 0644);
+ MODULE_PARM_DESC(audio_debug, "enable debug messages [audio]");
+
+-static unsigned int always_analog = 0;
++static unsigned int always_analog;
+ module_param(always_analog,int,0644);
+ MODULE_PARM_DESC(always_analog,"force analog audio out");
+
+-static unsigned int radio_deemphasis = 0;
++static unsigned int radio_deemphasis;
+ module_param(radio_deemphasis,int,0644);
+ MODULE_PARM_DESC(radio_deemphasis, "Radio deemphasis time constant, "
+ "0=None, 1=50us (elsewhere), 2=75us (USA)");
+@@ -265,12 +265,12 @@ static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap,
+ mode |= EN_FMRADIO_EN_RDS;
+
+ if (sap) {
+- dprintk("%s SAP (status: unknown)\n", __FUNCTION__);
++ dprintk("%s SAP (status: unknown)\n", __func__);
+ set_audio_start(core, SEL_SAP);
+ set_audio_registers(core, btsc_sap);
+ set_audio_finish(core, mode);
+ } else {
+- dprintk("%s (status: known-good)\n", __FUNCTION__);
++ dprintk("%s (status: known-good)\n", __func__);
+ set_audio_start(core, SEL_BTSC);
+ set_audio_registers(core, btsc);
+ set_audio_finish(core, mode);
+@@ -351,16 +351,16 @@ static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode)
+ set_audio_start(core,SEL_NICAM);
+ switch (core->tvaudio) {
+ case WW_L:
+- dprintk("%s SECAM-L NICAM (status: devel)\n", __FUNCTION__);
++ dprintk("%s SECAM-L NICAM (status: devel)\n", __func__);
+ set_audio_registers(core, nicam_l);
+ break;
+ case WW_I:
+- dprintk("%s PAL-I NICAM (status: known-good)\n", __FUNCTION__);
++ dprintk("%s PAL-I NICAM (status: known-good)\n", __func__);
+ set_audio_registers(core, nicam_bgdki_common);
+ set_audio_registers(core, nicam_i);
+ break;
+ default:
+- dprintk("%s PAL-BGDK NICAM (status: known-good)\n", __FUNCTION__);
++ dprintk("%s PAL-BGDK NICAM (status: known-good)\n", __func__);
+ set_audio_registers(core, nicam_bgdki_common);
+ set_audio_registers(core, nicam_default);
+ break;
+@@ -600,28 +600,28 @@ static void set_audio_standard_A2(struct cx88_core *core, u32 mode)
+ set_audio_start(core, SEL_A2);
+ switch (core->tvaudio) {
+ case WW_BG:
+- dprintk("%s PAL-BG A1/2 (status: known-good)\n", __FUNCTION__);
++ dprintk("%s PAL-BG A1/2 (status: known-good)\n", __func__);
+ set_audio_registers(core, a2_bgdk_common);
+ set_audio_registers(core, a2_bg);
+ set_audio_registers(core, a2_deemph50);
+ break;
+ case WW_DK:
+- dprintk("%s PAL-DK A1/2 (status: known-good)\n", __FUNCTION__);
++ dprintk("%s PAL-DK A1/2 (status: known-good)\n", __func__);
+ set_audio_registers(core, a2_bgdk_common);
+ set_audio_registers(core, a2_dk);
+ set_audio_registers(core, a2_deemph50);
+ break;
+ case WW_I:
+- dprintk("%s PAL-I A1 (status: known-good)\n", __FUNCTION__);
++ dprintk("%s PAL-I A1 (status: known-good)\n", __func__);
+ set_audio_registers(core, a1_i);
+ set_audio_registers(core, a2_deemph50);
+ break;
+ case WW_L:
+- dprintk("%s AM-L (status: devel)\n", __FUNCTION__);
++ dprintk("%s AM-L (status: devel)\n", __func__);
+ set_audio_registers(core, am_l);
+ break;
+ default:
+- dprintk("%s Warning: wrong value\n", __FUNCTION__);
++ dprintk("%s Warning: wrong value\n", __func__);
+ return;
+ break;
+ };
+@@ -637,7 +637,7 @@ static void set_audio_standard_EIAJ(struct cx88_core *core)
+
+ { /* end of list */ },
+ };
+- dprintk("%s (status: unknown)\n", __FUNCTION__);
++ dprintk("%s (status: unknown)\n", __func__);
+
+ set_audio_start(core, SEL_EIAJ);
+ set_audio_registers(core, eiaj);
+@@ -691,7 +691,7 @@ static void set_audio_standard_FM(struct cx88_core *core,
+ { /* end of list */ },
+ };
+
+- dprintk("%s (status: unknown)\n", __FUNCTION__);
++ dprintk("%s (status: unknown)\n", __func__);
+ set_audio_start(core, SEL_FMRADIO);
+
+ switch (deemph) {
+diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c
+index d96ecfc..0943060 100644
+--- a/drivers/media/video/cx88/cx88-vbi.c
++++ b/drivers/media/video/cx88/cx88-vbi.c
+@@ -11,7 +11,7 @@ static unsigned int vbibufs = 4;
+ module_param(vbibufs,int,0644);
+ MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32");
+
+-static unsigned int vbi_debug = 0;
++static unsigned int vbi_debug;
+ module_param(vbi_debug,int,0644);
+ MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");
+
+diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
+index 2271796..eea23f9 100644
+--- a/drivers/media/video/cx88/cx88-video.c
++++ b/drivers/media/video/cx88/cx88-video.c
+@@ -63,11 +63,11 @@ MODULE_PARM_DESC(video_nr,"video device numbers");
+ MODULE_PARM_DESC(vbi_nr,"vbi device numbers");
+ MODULE_PARM_DESC(radio_nr,"radio device numbers");
+
+-static unsigned int video_debug = 0;
++static unsigned int video_debug;
+ module_param(video_debug,int,0644);
+ MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
+
+-static unsigned int irq_debug = 0;
++static unsigned int irq_debug;
+ module_param(irq_debug,int,0644);
+ MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]");
+
+@@ -228,6 +228,30 @@ static struct cx88_ctrl cx8800_ctls[] = {
+ .mask = 0x00ff,
+ .shift = 0,
+ },{
++ .v = {
++ .id = V4L2_CID_CHROMA_AGC,
++ .name = "Chroma AGC",
++ .minimum = 0,
++ .maximum = 1,
++ .default_value = 0x1,
++ .type = V4L2_CTRL_TYPE_BOOLEAN,
++ },
++ .reg = MO_INPUT_FORMAT,
++ .mask = 1 << 10,
++ .shift = 10,
++ }, {
++ .v = {
++ .id = V4L2_CID_COLOR_KILLER,
++ .name = "Color killer",
++ .minimum = 0,
++ .maximum = 1,
++ .default_value = 0x1,
++ .type = V4L2_CTRL_TYPE_BOOLEAN,
++ },
++ .reg = MO_INPUT_FORMAT,
++ .mask = 1 << 9,
++ .shift = 9,
++ }, {
+ /* --- audio --- */
+ .v = {
+ .id = V4L2_CID_AUDIO_MUTE,
+@@ -282,6 +306,8 @@ const u32 cx88_user_ctrls[] = {
+ V4L2_CID_AUDIO_VOLUME,
+ V4L2_CID_AUDIO_BALANCE,
+ V4L2_CID_AUDIO_MUTE,
++ V4L2_CID_CHROMA_AGC,
++ V4L2_CID_COLOR_KILLER,
+ 0
+ };
+ EXPORT_SYMBOL(cx88_user_ctrls);
+@@ -291,7 +317,7 @@ static const u32 *ctrl_classes[] = {
+ NULL
+ };
+
+-int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl)
++int cx8800_ctrl_query(struct cx88_core *core, struct v4l2_queryctrl *qctrl)
+ {
+ int i;
+
+@@ -306,6 +332,11 @@ int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl)
+ return 0;
+ }
+ *qctrl = cx8800_ctls[i].v;
++ /* Report chroma AGC as inactive when SECAM is selected */
++ if (cx8800_ctls[i].v.id == V4L2_CID_CHROMA_AGC &&
++ core->tvnorm & V4L2_STD_SECAM)
++ qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
++
+ return 0;
+ }
+ EXPORT_SYMBOL(cx8800_ctrl_query);
+@@ -776,14 +807,14 @@ static int video_open(struct inode *inode, struct file *file)
+ fh->height = 240;
+ fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
+
+- videobuf_queue_pci_init(&fh->vidq, &cx8800_video_qops,
+- dev->pci, &dev->slock,
++ videobuf_queue_sg_init(&fh->vidq, &cx8800_video_qops,
++ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct cx88_buffer),
+ fh);
+- videobuf_queue_pci_init(&fh->vbiq, &cx8800_vbi_qops,
+- dev->pci, &dev->slock,
++ videobuf_queue_sg_init(&fh->vbiq, &cx8800_vbi_qops,
++ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VBI_CAPTURE,
+ V4L2_FIELD_SEQ_TB,
+ sizeof(struct cx88_buffer),
+@@ -976,6 +1007,12 @@ int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl)
+ }
+ mask=0xffff;
+ break;
++ case V4L2_CID_CHROMA_AGC:
++ /* Do not allow chroma AGC to be enabled for SECAM */
++ value = ((ctl->value - c->off) << c->shift) & c->mask;
++ if (core->tvnorm & V4L2_STD_SECAM && value)
++ return -EINVAL;
++ break;
+ default:
+ value = ((ctl->value - c->off) << c->shift) & c->mask;
+ break;
+@@ -1268,10 +1305,12 @@ static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
+ static int vidioc_queryctrl (struct file *file, void *priv,
+ struct v4l2_queryctrl *qctrl)
+ {
++ struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
++
+ qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
+ if (unlikely(qctrl->id == 0))
+ return -EINVAL;
+- return cx8800_ctrl_query(qctrl);
++ return cx8800_ctrl_query(core, qctrl);
+ }
+
+ static int vidioc_g_ctrl (struct file *file, void *priv,
+@@ -1832,8 +1871,11 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
+
+ switch (core->boardnr) {
+ case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
+- request_module("ir-kbd-i2c");
++ case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
+ request_module("rtc-isl1208");
++ /* break intentionally omitted */
++ case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
++ request_module("ir-kbd-i2c");
+ }
+
+ /* register v4l devices */
+@@ -1917,6 +1959,9 @@ static void __devexit cx8800_finidev(struct pci_dev *pci_dev)
+ core->kthread = NULL;
+ }
+
++ if (core->ir)
++ cx88_ir_stop(core, core->ir);
++
+ cx88_shutdown(core); /* FIXME */
+ pci_disable_device(pci_dev);
+
+diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
+index 37e6d2e..14ac173 100644
+--- a/drivers/media/video/cx88/cx88.h
++++ b/drivers/media/video/cx88/cx88.h
+@@ -37,6 +37,7 @@
+
+ #include "btcx-risc.h"
+ #include "cx88-reg.h"
++#include "tuner-xc2028.h"
+
+ #include <linux/version.h>
+ #include <linux/mutex.h>
+@@ -211,6 +212,15 @@ extern struct sram_channel cx88_sram_channels[];
+ #define CX88_BOARD_HAUPPAUGE_HVR1300 56
+ #define CX88_BOARD_ADSTECH_PTV_390 57
+ #define CX88_BOARD_PINNACLE_PCTV_HD_800i 58
++#define CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO 59
++#define CX88_BOARD_PINNACLE_HYBRID_PCTV 60
++#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL 61
++#define CX88_BOARD_POWERCOLOR_REAL_ANGEL 62
++#define CX88_BOARD_GENIATECH_X8000_MT 63
++#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO 64
++#define CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD 65
++#define CX88_BOARD_PROLINK_PV_8000GT 66
++#define CX88_BOARD_KWORLD_ATSC_120 67
+
+ enum cx88_itype {
+ CX88_VMUX_COMPOSITE1 = 1,
+@@ -595,6 +605,7 @@ extern int cx88_tuner_callback(void *dev, int command, int arg);
+ extern int cx88_get_resources(const struct cx88_core *core,
+ struct pci_dev *pci);
+ extern struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr);
++extern void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl);
+
+ /* ----------------------------------------------------------- */
+ /* cx88-tvaudio.c */
+@@ -640,7 +651,8 @@ void cx8802_cancel_buffers(struct cx8802_dev *dev);
+ /* ----------------------------------------------------------- */
+ /* cx88-video.c*/
+ extern const u32 cx88_user_ctrls[];
+-extern int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl);
++extern int cx8800_ctrl_query(struct cx88_core *core,
++ struct v4l2_queryctrl *qctrl);
+ int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i);
+ int cx88_set_freq (struct cx88_core *core,struct v4l2_frequency *f);
+ int cx88_get_control(struct cx88_core *core, struct v4l2_control *ctl);
+diff --git a/drivers/media/video/dabfirmware.h b/drivers/media/video/dabfirmware.h
+index d14d803..cbd9263 100644
+--- a/drivers/media/video/dabfirmware.h
++++ b/drivers/media/video/dabfirmware.h
+@@ -1,5 +1,12 @@
+ /*
+ * dabdata.h - dab usb firmware and bitstream data
++ *
++ * Copyright (C) 1999 BayCom GmbH
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that redistributions of source
++ * code retain the above copyright notice and this comment without
++ * modification.
+ */
+
+ static INTEL_HEX_RECORD firmware[] = {
+diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c
+index a5731f9..8d1f8ee 100644
+--- a/drivers/media/video/dabusb.c
++++ b/drivers/media/video/dabusb.c
+@@ -205,7 +205,7 @@ static void dabusb_iso_complete (struct urb *purb)
+ /*-------------------------------------------------------------------*/
+ static int dabusb_alloc_buffers (pdabusb_t s)
+ {
+- int buffers = 0;
++ int transfer_len = 0;
+ pbuff_t b;
+ unsigned int pipe = usb_rcvisocpipe (s->usbdev, _DABUSB_ISOPIPE);
+ int pipesize = usb_maxpacket (s->usbdev, pipe, usb_pipeout (pipe));
+@@ -216,7 +216,7 @@ static int dabusb_alloc_buffers (pdabusb_t s)
+ dbg("dabusb_alloc_buffers pipesize:%d packets:%d transfer_buffer_len:%d",
+ pipesize, packets, transfer_buffer_length);
+
+- while (buffers < (s->total_buffer_size << 10)) {
++ while (transfer_len < (s->total_buffer_size << 10)) {
+ b = kzalloc(sizeof (buff_t), GFP_KERNEL);
+ if (!b) {
+ err("kzalloc(sizeof(buff_t))==NULL");
+@@ -251,10 +251,10 @@ static int dabusb_alloc_buffers (pdabusb_t s)
+ b->purb->iso_frame_desc[i].length = pipesize;
+ }
+
+- buffers += transfer_buffer_length;
++ transfer_len += transfer_buffer_length;
+ list_add_tail (&b->buff_list, &s->free_buff_list);
+ }
+- s->got_mem = buffers;
++ s->got_mem = transfer_len;
+
+ return 0;
+
+diff --git a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c
+index 9ceb6b2..88d6df7 100644
+--- a/drivers/media/video/dpc7146.c
++++ b/drivers/media/video/dpc7146.c
+@@ -54,11 +54,11 @@
+
+ #define DPC_BOARD_CAN_DO_VBI(dev) (dev->revision != 0)
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "debug verbosity");
+
+-static int dpc_num = 0;
++static int dpc_num;
+
+ #define DPC_INPUTS 2
+ static struct v4l2_input dpc_inputs[DPC_INPUTS] = {
+diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig
+index 0f7a0bd..9caffed 100644
+--- a/drivers/media/video/em28xx/Kconfig
++++ b/drivers/media/video/em28xx/Kconfig
+@@ -1,11 +1,13 @@
+ config VIDEO_EM28XX
+- tristate "Empia EM2800/2820/2840 USB video capture support"
++ tristate "Empia EM28xx USB video capture support"
+ depends on VIDEO_DEV && I2C && INPUT
+ select VIDEO_TUNER
+ select VIDEO_TVEEPROM
+ select VIDEO_IR
++ select VIDEOBUF_VMALLOC
+ select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
+ select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO
++ select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO
+ ---help---
+ This is a video4linux driver for Empia 28xx based TV cards.
+
+@@ -27,3 +29,13 @@ config VIDEO_EM28XX_ALSA
+ To compile this driver as a module, choose M here: the
+ module will be called em28xx-alsa
+
++config VIDEO_EM28XX_DVB
++ tristate "DVB/ATSC Support for em28xx based TV cards"
++ depends on VIDEO_EM28XX && DVB_CORE
++ select DVB_LGDT330X if !DVB_FE_CUSTOMISE
++ select DVB_ZL10353 if !DVB_FE_CUSTOMISE
++ select VIDEOBUF_DVB
++ select FW_LOADER
++ ---help---
++ This adds support for DVB cards based on the
++ Empiatech em28xx chips.
+diff --git a/drivers/media/video/em28xx/Makefile b/drivers/media/video/em28xx/Makefile
+index 0924550..3d1c3cc 100644
+--- a/drivers/media/video/em28xx/Makefile
++++ b/drivers/media/video/em28xx/Makefile
+@@ -5,6 +5,7 @@ em28xx-alsa-objs := em28xx-audio.o
+
+ obj-$(CONFIG_VIDEO_EM28XX) += em28xx.o
+ obj-$(CONFIG_VIDEO_EM28XX_ALSA) += em28xx-alsa.o
++obj-$(CONFIG_VIDEO_EM28XX_DVB) += em28xx-dvb.o
+
+ EXTRA_CFLAGS += -Idrivers/media/video
+ EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c
+index 8c67f67..92b2a6d 100644
+--- a/drivers/media/video/em28xx/em28xx-audio.c
++++ b/drivers/media/video/em28xx/em28xx-audio.c
+@@ -51,7 +51,7 @@ MODULE_PARM_DESC(debug, "activates debug info");
+ #define dprintk(fmt, arg...) do { \
+ if (debug) \
+ printk(KERN_INFO "em28xx-audio %s: " fmt, \
+- __FUNCTION__, ##arg); \
++ __func__, ##arg); \
+ } while (0)
+
+ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
+index aae7753..50ccf37 100644
+--- a/drivers/media/video/em28xx/em28xx-cards.c
++++ b/drivers/media/video/em28xx/em28xx-cards.c
+@@ -36,7 +36,6 @@
+ #include <media/v4l2-common.h>
+
+ #include "em28xx.h"
+-#include "tuner-xc2028.h"
+
+ static int tuner = -1;
+ module_param(tuner, int, 0444);
+@@ -52,26 +51,6 @@ struct em28xx_hash_table {
+ unsigned int tuner;
+ };
+
+-/* Boards supported by driver */
+-
+-#define EM2800_BOARD_UNKNOWN 0
+-#define EM2820_BOARD_UNKNOWN 1
+-#define EM2820_BOARD_TERRATEC_CINERGY_250 2
+-#define EM2820_BOARD_PINNACLE_USB_2 3
+-#define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 4
+-#define EM2820_BOARD_MSI_VOX_USB_2 5
+-#define EM2800_BOARD_TERRATEC_CINERGY_200 6
+-#define EM2800_BOARD_LEADTEK_WINFAST_USBII 7
+-#define EM2800_BOARD_KWORLD_USB2800 8
+-#define EM2820_BOARD_PINNACLE_DVC_90 9
+-#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 10
+-#define EM2880_BOARD_TERRATEC_HYBRID_XS 11
+-#define EM2820_BOARD_KWORLD_PVRTV2800RF 12
+-#define EM2880_BOARD_TERRATEC_PRODIGY_XS 13
+-#define EM2820_BOARD_PROLINK_PLAYTV_USB2 14
+-#define EM2800_BOARD_VGEAR_POCKETTV 15
+-#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 16
+-
+ struct em28xx_board em28xx_boards[] = {
+ [EM2800_BOARD_UNKNOWN] = {
+ .name = "Unknown EM2800 video grabber",
+@@ -200,6 +179,7 @@ struct em28xx_board em28xx_boards[] = {
+ .tuner_type = TUNER_XC2028,
+ .mts_firmware = 1,
+ .has_12mhz_i2s = 1,
++ .has_dvb = 1,
+ .decoder = EM28XX_TVP5150,
+ .input = { {
+ .type = EM28XX_VMUX_TELEVISION,
+@@ -214,9 +194,6 @@ struct em28xx_board em28xx_boards[] = {
+ .vmux = TVP5150_SVIDEO,
+ .amux = 1,
+ } },
+-
+- /* gpio's 4, 1, 0 */
+- .analog_gpio = 0x003d2d,
+ },
+ [EM2880_BOARD_TERRATEC_HYBRID_XS] = {
+ .name = "Terratec Hybrid XS",
+@@ -331,7 +308,7 @@ struct em28xx_board em28xx_boards[] = {
+ .name = "Kworld USB2800",
+ .is_em2800 = 1,
+ .vchannels = 3,
+- .tuner_type = TUNER_PHILIPS_ATSC,
++ .tuner_type = TUNER_PHILIPS_FCV1236D,
+ .tda9887_conf = TDA9887_PRESENT,
+ .decoder = EM28XX_SAA7113,
+ .input = { {
+@@ -453,7 +430,36 @@ struct usb_device_id em28xx_id_table [] = {
+ };
+ MODULE_DEVICE_TABLE(usb, em28xx_id_table);
+
+-/* EEPROM hash table for devices with generic USB IDs */
++/*
++ * Reset sequences for analog/digital modes
++ */
++
++/* Board Hauppauge WinTV HVR 900 analog */
++static struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = {
++ {EM28XX_R08_GPIO, 0x2d, ~EM_GPIO_4, 10},
++ {0x05, 0xff, 0x10, 10},
++ { -1, -1, -1, -1},
++};
++
++/* Board Hauppauge WinTV HVR 900 digital */
++static struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = {
++ {EM28XX_R08_GPIO, 0x2e, ~EM_GPIO_4, 10},
++ {EM2880_R04_GPO, 0x04, 0x0f, 10},
++ {EM2880_R04_GPO, 0x0c, 0x0f, 10},
++ { -1, -1, -1, -1},
++};
++
++/* Board Hauppauge WinTV HVR 900 tuner_callback */
++static struct em28xx_reg_seq hauppauge_wintv_hvr_900_tuner_callback[] = {
++ {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10},
++ {EM28XX_R08_GPIO, 0, EM_GPIO_4, 10},
++ {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10},
++ { -1, -1, -1, -1},
++};
++
++/*
++ * EEPROM hash table for devices with generic USB IDs
++ */
+ static struct em28xx_hash_table em28xx_eeprom_hash [] = {
+ /* P/N: SA 60002070465 Tuner: TVF7533-MF */
+ {0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF},
+@@ -465,79 +471,113 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = {
+ {0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC},
+ };
+
++int em28xx_tuner_callback(void *ptr, int command, int arg)
++{
++ int rc = 0;
++ struct em28xx *dev = ptr;
++
++ if (dev->tuner_type != TUNER_XC2028)
++ return 0;
++
++ if (command != XC2028_TUNER_RESET)
++ return 0;
++
++ if (dev->mode == EM28XX_ANALOG_MODE)
++ rc = em28xx_gpio_set(dev, dev->tun_analog_gpio);
++ else
++ rc = em28xx_gpio_set(dev, dev->tun_digital_gpio);
++
++ return rc;
++}
++EXPORT_SYMBOL_GPL(em28xx_tuner_callback);
++
++static void em28xx_set_model(struct em28xx *dev)
++{
++ dev->is_em2800 = em28xx_boards[dev->model].is_em2800;
++ dev->has_msp34xx = em28xx_boards[dev->model].has_msp34xx;
++ dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf;
++ dev->decoder = em28xx_boards[dev->model].decoder;
++ dev->video_inputs = em28xx_boards[dev->model].vchannels;
++ dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s;
++ dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480;
++ dev->has_dvb = em28xx_boards[dev->model].has_dvb;
++}
++
+ /* Since em28xx_pre_card_setup() requires a proper dev->model,
+ * this won't work for boards with generic PCI IDs
+ */
+ void em28xx_pre_card_setup(struct em28xx *dev)
+ {
++ int rc;
++
++ rc = em28xx_read_reg(dev, EM2880_R04_GPO);
++ if (rc >= 0)
++ dev->reg_gpo = rc;
++
++ dev->wait_after_write = 5;
++ rc = em28xx_read_reg(dev, EM28XX_R0A_CHIPID);
++ if (rc > 0) {
++ switch (rc) {
++ case CHIP_ID_EM2883:
++ em28xx_info("chip ID is em2882/em2883\n");
++ dev->wait_after_write = 0;
++ break;
++ default:
++ em28xx_info("em28xx chip ID = %d\n", rc);
++ }
++ }
++ em28xx_set_model(dev);
++
+ /* request some modules */
+ switch (dev->model) {
+ case EM2880_BOARD_TERRATEC_PRODIGY_XS:
+ case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
+- case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
+ case EM2880_BOARD_TERRATEC_HYBRID_XS:
+- em28xx_write_regs(dev, XCLK_REG, "\x27", 1);
+- em28xx_write_regs(dev, I2C_CLK_REG, "\x40", 1);
+- em28xx_write_regs(dev, 0x08, "\xff", 1);
+- em28xx_write_regs(dev, 0x04, "\x00", 1);
+- msleep(100);
+- em28xx_write_regs(dev, 0x04, "\x08", 1);
+- msleep(100);
+- em28xx_write_regs(dev, 0x08, "\xff", 1);
+- msleep(50);
+- em28xx_write_regs(dev, 0x08, "\x2d", 1);
++ case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
++ em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1);
++ em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1);
+ msleep(50);
+- em28xx_write_regs(dev, 0x08, "\x3d", 1);
++
++ /* Sets GPO/GPIO sequences for this device */
++ dev->analog_gpio = hauppauge_wintv_hvr_900_analog;
++ dev->digital_gpio = hauppauge_wintv_hvr_900_digital;
++ dev->tun_analog_gpio = hauppauge_wintv_hvr_900_tuner_callback;
++ dev->tun_digital_gpio = hauppauge_wintv_hvr_900_tuner_callback;
++
+ break;
+ }
++
++ em28xx_gpio_set(dev, dev->tun_analog_gpio);
++ em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
++
++ /* Unlock device */
++ em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+ }
+
+-static int em28xx_tuner_callback(void *ptr, int command, int arg)
++static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
+ {
+- int rc = 0;
+- struct em28xx *dev = ptr;
++ memset(ctl, 0, sizeof(*ctl));
+
+- if (dev->tuner_type != TUNER_XC2028)
+- return 0;
+-
+- switch (command) {
+- case XC2028_TUNER_RESET:
+- {
+- /* GPIO and initialization codes for analog TV and radio
+- This code should be complemented for DTV, since reset
+- codes are different.
+- */
+-
+- dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1);
+- dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x67", 1);
+-
+- if (dev->analog_gpio) {
+- char gpio0 = dev->analog_gpio & 0xff;
+- char gpio1 = (dev->analog_gpio >> 8) & 0xff;
+- char gpio4 = dev->analog_gpio >> 24;
+-
+- if (gpio4) {
+- dev->em28xx_write_regs(dev, 0x04, &gpio4, 1);
+- msleep(140);
+- }
+-
+- msleep(6);
+- dev->em28xx_write_regs(dev, 0x08, &gpio0, 1);
+- msleep(10);
+- dev->em28xx_write_regs(dev, 0x08, &gpio1, 1);
+- msleep(5);
+- }
++ ctl->fname = XC2028_DEFAULT_FIRMWARE;
++ ctl->max_len = 64;
++ ctl->mts = em28xx_boards[dev->model].mts_firmware;
+
++ switch (dev->model) {
++ case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
++ ctl->demod = XC3028_FE_ZARLINK456;
+ break;
++ case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
++ /* FIXME: Better to specify the needed IF */
++ ctl->demod = XC3028_FE_DEFAULT;
++ break;
++ default:
++ ctl->demod = XC3028_FE_OREN538;
+ }
+- }
+- return rc;
+ }
+
+ static void em28xx_config_tuner(struct em28xx *dev)
+ {
+ struct v4l2_priv_tun_config xc2028_cfg;
+- struct xc2028_ctrl ctl;
+ struct tuner_setup tun_setup;
+ struct v4l2_frequency f;
+
+@@ -552,11 +592,9 @@ static void em28xx_config_tuner(struct em28xx *dev)
+ em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
+
+ if (dev->tuner_type == TUNER_XC2028) {
+- memset(&ctl, 0, sizeof(ctl));
++ struct xc2028_ctrl ctl;
+
+- ctl.fname = XC2028_DEFAULT_FIRMWARE;
+- ctl.max_len = 64;
+- ctl.mts = em28xx_boards[dev->model].mts_firmware;
++ em28xx_setup_xc3028(dev, &ctl);
+
+ xc2028_cfg.tuner = TUNER_XC2028;
+ xc2028_cfg.priv = &ctl;
+@@ -654,19 +692,6 @@ static int em28xx_hint_board(struct em28xx *dev)
+ return -1;
+ }
+
+-
+-static void em28xx_set_model(struct em28xx *dev)
+-{
+- dev->is_em2800 = em28xx_boards[dev->model].is_em2800;
+- dev->has_msp34xx = em28xx_boards[dev->model].has_msp34xx;
+- dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf;
+- dev->decoder = em28xx_boards[dev->model].decoder;
+- dev->video_inputs = em28xx_boards[dev->model].vchannels;
+- dev->analog_gpio = em28xx_boards[dev->model].analog_gpio;
+- dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s;
+- dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480;
+-}
+-
+ /* ----------------------------------------------------------------------- */
+ void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir)
+ {
+diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
+index c1caaa8..5d837c1 100644
+--- a/drivers/media/video/em28xx/em28xx-core.c
++++ b/drivers/media/video/em28xx/em28xx-core.c
+@@ -31,104 +31,33 @@
+
+ /* #define ENABLE_DEBUG_ISOC_FRAMES */
+
+-static unsigned int core_debug = 0;
++static unsigned int core_debug;
+ module_param(core_debug,int,0644);
+ MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
+
+ #define em28xx_coredbg(fmt, arg...) do {\
+ if (core_debug) \
+ printk(KERN_INFO "%s %s :"fmt, \
+- dev->name, __FUNCTION__ , ##arg); } while (0)
++ dev->name, __func__ , ##arg); } while (0)
+
+-static unsigned int reg_debug = 0;
++static unsigned int reg_debug;
+ module_param(reg_debug,int,0644);
+ MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]");
+
+ #define em28xx_regdbg(fmt, arg...) do {\
+ if (reg_debug) \
+ printk(KERN_INFO "%s %s :"fmt, \
+- dev->name, __FUNCTION__ , ##arg); } while (0)
+-
+-static unsigned int isoc_debug = 0;
+-module_param(isoc_debug,int,0644);
+-MODULE_PARM_DESC(isoc_debug,"enable debug messages [isoc transfers]");
+-
+-#define em28xx_isocdbg(fmt, arg...) do {\
+- if (isoc_debug) \
+- printk(KERN_INFO "%s %s :"fmt, \
+- dev->name, __FUNCTION__ , ##arg); } while (0)
++ dev->name, __func__ , ##arg); } while (0)
+
+ static int alt = EM28XX_PINOUT;
+ module_param(alt, int, 0644);
+ MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
+
+-
+-/*
+- * em28xx_request_buffers()
+- * allocate a number of buffers
+- */
+-u32 em28xx_request_buffers(struct em28xx *dev, u32 count)
+-{
+- const size_t imagesize = PAGE_ALIGN(dev->frame_size); /*needs to be page aligned cause the buffers can be mapped individually! */
+- void *buff = NULL;
+- u32 i;
+- em28xx_coredbg("requested %i buffers with size %zi\n",
+- count, imagesize);
+- if (count > EM28XX_NUM_FRAMES)
+- count = EM28XX_NUM_FRAMES;
+-
+- dev->num_frames = count;
+- while (dev->num_frames > 0) {
+- if ((buff = vmalloc_32(dev->num_frames * imagesize))) {
+- memset(buff, 0, dev->num_frames * imagesize);
+- break;
+- }
+- dev->num_frames--;
+- }
+-
+- for (i = 0; i < dev->num_frames; i++) {
+- dev->frame[i].bufmem = buff + i * imagesize;
+- dev->frame[i].buf.index = i;
+- dev->frame[i].buf.m.offset = i * imagesize;
+- dev->frame[i].buf.length = dev->frame_size;
+- dev->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+- dev->frame[i].buf.sequence = 0;
+- dev->frame[i].buf.field = V4L2_FIELD_NONE;
+- dev->frame[i].buf.memory = V4L2_MEMORY_MMAP;
+- dev->frame[i].buf.flags = 0;
+- }
+- return dev->num_frames;
+-}
+-
+-/*
+- * em28xx_queue_unusedframes()
+- * add all frames that are not currently in use to the inbuffer queue
+- */
+-void em28xx_queue_unusedframes(struct em28xx *dev)
+-{
+- unsigned long lock_flags;
+- u32 i;
+-
+- for (i = 0; i < dev->num_frames; i++)
+- if (dev->frame[i].state == F_UNUSED) {
+- dev->frame[i].state = F_QUEUED;
+- spin_lock_irqsave(&dev->queue_lock, lock_flags);
+- list_add_tail(&dev->frame[i].frame, &dev->inqueue);
+- spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
+- }
+-}
+-
+-/*
+- * em28xx_release_buffers()
+- * free frame buffers
+- */
+-void em28xx_release_buffers(struct em28xx *dev)
+-{
+- if (dev->num_frames) {
+- vfree(dev->frame[0].bufmem);
+- dev->num_frames = 0;
+- }
+-}
++/* FIXME */
++#define em28xx_isocdbg(fmt, arg...) do {\
++ if (core_debug) \
++ printk(KERN_INFO "%s %s :"fmt, \
++ dev->name, __func__ , ##arg); } while (0)
+
+ /*
+ * em28xx_read_reg_req()
+@@ -148,11 +77,11 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0x0000, reg, buf, len, HZ);
+
+- if (reg_debug){
++ if (reg_debug) {
+ printk(ret < 0 ? " failed!\n" : "%02x values: ", ret);
+- for (byte = 0; byte < len; byte++) {
++ for (byte = 0; byte < len; byte++)
+ printk(" %02x", (unsigned char)buf[byte]);
+- }
++
+ printk("\n");
+ }
+
+@@ -205,7 +134,10 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
+ unsigned char *bufs;
+
+ if (dev->state & DEV_DISCONNECTED)
+- return(-ENODEV);
++ return -ENODEV;
++
++ if (len < 1)
++ return -EINVAL;
+
+ bufs = kmalloc(len, GFP_KERNEL);
+
+@@ -214,8 +146,8 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
+ if (reg_debug) {
+ int i;
+ for (i = 0; i < len; ++i)
+- printk (" %02x", (unsigned char)buf[i]);
+- printk ("\n");
++ printk(" %02x", (unsigned char)buf[i]);
++ printk("\n");
+ }
+
+ if (!bufs)
+@@ -224,14 +156,32 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
+ ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0x0000, reg, bufs, len, HZ);
+- msleep(5); /* FIXME: magic number */
++ if (dev->wait_after_write)
++ msleep(dev->wait_after_write);
++
+ kfree(bufs);
+ return ret;
+ }
+
+ int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len)
+ {
+- return em28xx_write_regs_req(dev, USB_REQ_GET_STATUS, reg, buf, len);
++ int rc;
++
++ rc = em28xx_write_regs_req(dev, USB_REQ_GET_STATUS, reg, buf, len);
++
++ /* Stores GPO/GPIO values at the cache, if changed
++ Only write values should be stored, since input on a GPIO
++ register will return the input bits.
++ Not sure what happens on reading GPO register.
++ */
++ if (rc >= 0) {
++ if (reg == EM2880_R04_GPO)
++ dev->reg_gpo = buf[0];
++ else if (reg == EM28XX_R08_GPIO)
++ dev->reg_gpio = buf[0];
++ }
++
++ return rc;
+ }
+
+ /*
+@@ -244,9 +194,20 @@ static int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
+ {
+ int oldval;
+ u8 newval;
+- if ((oldval = em28xx_read_reg(dev, reg)) < 0)
++
++ /* Uses cache for gpo/gpio registers */
++ if (reg == EM2880_R04_GPO)
++ oldval = dev->reg_gpo;
++ else if (reg == EM28XX_R08_GPIO)
++ oldval = dev->reg_gpio;
++ else
++ oldval = em28xx_read_reg(dev, reg);
++
++ if (oldval < 0)
+ return oldval;
++
+ newval = (((u8) oldval) & ~bitmask) | (val & bitmask);
++
+ return em28xx_write_regs(dev, reg, &newval, 1);
+ }
+
+@@ -258,20 +219,26 @@ static int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 *val)
+ {
+ int ret, i;
+ u8 addr = reg & 0x7f;
+- if ((ret = em28xx_write_regs(dev, AC97LSB_REG, val, 2)) < 0)
++
++ ret = em28xx_write_regs(dev, EM28XX_R40_AC97LSB, val, 2);
++ if (ret < 0)
+ return ret;
+- if ((ret = em28xx_write_regs(dev, AC97ADDR_REG, &addr, 1)) < 0)
++
++ ret = em28xx_write_regs(dev, EM28XX_R42_AC97ADDR, &addr, 1);
++ if (ret < 0)
+ return ret;
+
+ /* Wait up to 50 ms for AC97 command to complete */
+ for (i = 0; i < 10; i++) {
+- if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0)
++ ret = em28xx_read_reg(dev, EM28XX_R43_AC97BUSY);
++ if (ret < 0)
+ return ret;
++
+ if (!(ret & 0x01))
+ return 0;
+ msleep(5);
+ }
+- em28xx_warn ("AC97 command still being executed: not handled properly!\n");
++ em28xx_warn("AC97 command still being executed: not handled properly!\n");
+ return 0;
+ }
+
+@@ -289,7 +256,7 @@ static int em28xx_set_audio_source(struct em28xx *dev)
+ else
+ input = EM2800_AUDIO_SRC_TUNER;
+
+- ret = em28xx_write_regs(dev, EM2800_AUDIOSRC_REG, &input, 1);
++ ret = em28xx_write_regs(dev, EM2800_R08_AUDIOSRC, &input, 1);
+ if (ret < 0)
+ return ret;
+ }
+@@ -315,7 +282,7 @@ static int em28xx_set_audio_source(struct em28xx *dev)
+ }
+ }
+
+- ret = em28xx_write_reg_bits(dev, AUDIOSRC_REG, input, 0xc0);
++ ret = em28xx_write_reg_bits(dev, EM28XX_R0E_AUDIOSRC, input, 0xc0);
+ if (ret < 0)
+ return ret;
+ msleep(5);
+@@ -323,11 +290,11 @@ static int em28xx_set_audio_source(struct em28xx *dev)
+ /* Sets AC97 mixer registers
+ This is seems to be needed, even for non-ac97 configs
+ */
+- ret = em28xx_write_ac97(dev, VIDEO_AC97, video);
++ ret = em28xx_write_ac97(dev, EM28XX_R14_VIDEO_AC97, video);
+ if (ret < 0)
+ return ret;
+
+- ret = em28xx_write_ac97(dev, LINE_IN_AC97, line);
++ ret = em28xx_write_ac97(dev, EM28XX_R10_LINE_IN_AC97, line);
+
+ return ret;
+ }
+@@ -343,7 +310,7 @@ int em28xx_audio_analog_set(struct em28xx *dev)
+
+ /* Mute */
+ s[1] |= 0x80;
+- ret = em28xx_write_ac97(dev, MASTER_AC97, s);
++ ret = em28xx_write_ac97(dev, EM28XX_R02_MASTER_AC97, s);
+
+ if (ret < 0)
+ return ret;
+@@ -354,7 +321,7 @@ int em28xx_audio_analog_set(struct em28xx *dev)
+ if (!dev->mute)
+ xclk |= 0x80;
+
+- ret = em28xx_write_reg_bits(dev, XCLK_REG, xclk, 0xa7);
++ ret = em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, xclk, 0xa7);
+ if (ret < 0)
+ return ret;
+ msleep(10);
+@@ -365,7 +332,7 @@ int em28xx_audio_analog_set(struct em28xx *dev)
+ /* Unmute device */
+ if (!dev->mute)
+ s[1] &= ~0x80;
+- ret = em28xx_write_ac97(dev, MASTER_AC97, s);
++ ret = em28xx_write_ac97(dev, EM28XX_R02_MASTER_AC97, s);
+
+ return ret;
+ }
+@@ -373,50 +340,68 @@ EXPORT_SYMBOL_GPL(em28xx_audio_analog_set);
+
+ int em28xx_colorlevels_set_default(struct em28xx *dev)
+ {
+- em28xx_write_regs(dev, YGAIN_REG, "\x10", 1); /* contrast */
+- em28xx_write_regs(dev, YOFFSET_REG, "\x00", 1); /* brightness */
+- em28xx_write_regs(dev, UVGAIN_REG, "\x10", 1); /* saturation */
+- em28xx_write_regs(dev, UOFFSET_REG, "\x00", 1);
+- em28xx_write_regs(dev, VOFFSET_REG, "\x00", 1);
+- em28xx_write_regs(dev, SHARPNESS_REG, "\x00", 1);
+-
+- em28xx_write_regs(dev, GAMMA_REG, "\x20", 1);
+- em28xx_write_regs(dev, RGAIN_REG, "\x20", 1);
+- em28xx_write_regs(dev, GGAIN_REG, "\x20", 1);
+- em28xx_write_regs(dev, BGAIN_REG, "\x20", 1);
+- em28xx_write_regs(dev, ROFFSET_REG, "\x00", 1);
+- em28xx_write_regs(dev, GOFFSET_REG, "\x00", 1);
+- return em28xx_write_regs(dev, BOFFSET_REG, "\x00", 1);
++ em28xx_write_regs(dev, EM28XX_R20_YGAIN, "\x10", 1); /* contrast */
++ em28xx_write_regs(dev, EM28XX_R21_YOFFSET, "\x00", 1); /* brightness */
++ em28xx_write_regs(dev, EM28XX_R22_UVGAIN, "\x10", 1); /* saturation */
++ em28xx_write_regs(dev, EM28XX_R23_UOFFSET, "\x00", 1);
++ em28xx_write_regs(dev, EM28XX_R24_VOFFSET, "\x00", 1);
++ em28xx_write_regs(dev, EM28XX_R25_SHARPNESS, "\x00", 1);
++
++ em28xx_write_regs(dev, EM28XX_R14_GAMMA, "\x20", 1);
++ em28xx_write_regs(dev, EM28XX_R15_RGAIN, "\x20", 1);
++ em28xx_write_regs(dev, EM28XX_R16_GGAIN, "\x20", 1);
++ em28xx_write_regs(dev, EM28XX_R17_BGAIN, "\x20", 1);
++ em28xx_write_regs(dev, EM28XX_R18_ROFFSET, "\x00", 1);
++ em28xx_write_regs(dev, EM28XX_R19_GOFFSET, "\x00", 1);
++ return em28xx_write_regs(dev, EM28XX_R1A_BOFFSET, "\x00", 1);
+ }
+
+ int em28xx_capture_start(struct em28xx *dev, int start)
+ {
+- int ret;
++ int rc;
+ /* FIXME: which is the best order? */
+ /* video registers are sampled by VREF */
+- if ((ret = em28xx_write_reg_bits(dev, USBSUSP_REG, start ? 0x10 : 0x00,
+- 0x10)) < 0)
+- return ret;
++ rc = em28xx_write_reg_bits(dev, EM28XX_R0C_USBSUSP,
++ start ? 0x10 : 0x00, 0x10);
++ if (rc < 0)
++ return rc;
++
++ if (!start) {
++ /* disable video capture */
++ rc = em28xx_write_regs(dev, EM28XX_R12_VINENABLE, "\x27", 1);
++ return rc;
++ }
++
+ /* enable video capture */
+- return em28xx_write_regs(dev, VINENABLE_REG, start ? "\x67" : "\x27", 1);
++ rc = em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1);
++
++ if (dev->mode == EM28XX_ANALOG_MODE)
++ rc = em28xx_write_regs(dev, EM28XX_R12_VINENABLE, "\x67", 1);
++ else
++ rc = em28xx_write_regs(dev, EM28XX_R12_VINENABLE, "\x37", 1);
++
++ msleep(6);
++
++ return rc;
+ }
+
+ int em28xx_outfmt_set_yuv422(struct em28xx *dev)
+ {
+- em28xx_write_regs(dev, OUTFMT_REG, "\x34", 1);
+- em28xx_write_regs(dev, VINMODE_REG, "\x10", 1);
+- return em28xx_write_regs(dev, VINCTRL_REG, "\x11", 1);
++ em28xx_write_regs(dev, EM28XX_R27_OUTFMT, "\x34", 1);
++ em28xx_write_regs(dev, EM28XX_R10_VINMODE, "\x10", 1);
++ return em28xx_write_regs(dev, EM28XX_R11_VINCTRL, "\x11", 1);
+ }
+
+ static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
+ u8 ymin, u8 ymax)
+ {
+- em28xx_coredbg("em28xx Scale: (%d,%d)-(%d,%d)\n", xmin, ymin, xmax, ymax);
++ em28xx_coredbg("em28xx Scale: (%d,%d)-(%d,%d)\n",
++ xmin, ymin, xmax, ymax);
+
+- em28xx_write_regs(dev, XMIN_REG, &xmin, 1);
+- em28xx_write_regs(dev, XMAX_REG, &xmax, 1);
+- em28xx_write_regs(dev, YMIN_REG, &ymin, 1);
+- return em28xx_write_regs(dev, YMAX_REG, &ymax, 1);
++ em28xx_write_regs(dev, EM28XX_R28_XMIN, &xmin, 1);
++ em28xx_write_regs(dev, EM28XX_R29_XMAX, &xmax, 1);
++ em28xx_write_regs(dev, EM28XX_R2A_YMIN, &ymin, 1);
++ return em28xx_write_regs(dev, EM28XX_R2B_YMAX, &ymax, 1);
+ }
+
+ static int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
+@@ -426,34 +411,36 @@ static int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
+ u8 cheight = height;
+ u8 overflow = (height >> 7 & 0x02) | (width >> 8 & 0x01);
+
+- em28xx_coredbg("em28xx Area Set: (%d,%d)\n", (width | (overflow & 2) << 7),
++ em28xx_coredbg("em28xx Area Set: (%d,%d)\n",
++ (width | (overflow & 2) << 7),
+ (height | (overflow & 1) << 8));
+
+- em28xx_write_regs(dev, HSTART_REG, &hstart, 1);
+- em28xx_write_regs(dev, VSTART_REG, &vstart, 1);
+- em28xx_write_regs(dev, CWIDTH_REG, &cwidth, 1);
+- em28xx_write_regs(dev, CHEIGHT_REG, &cheight, 1);
+- return em28xx_write_regs(dev, OFLOW_REG, &overflow, 1);
++ em28xx_write_regs(dev, EM28XX_R1C_HSTART, &hstart, 1);
++ em28xx_write_regs(dev, EM28XX_R1D_VSTART, &vstart, 1);
++ em28xx_write_regs(dev, EM28XX_R1E_CWIDTH, &cwidth, 1);
++ em28xx_write_regs(dev, EM28XX_R1F_CHEIGHT, &cheight, 1);
++ return em28xx_write_regs(dev, EM28XX_R1B_OFLOW, &overflow, 1);
+ }
+
+ static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
+ {
+ u8 mode;
+ /* the em2800 scaler only supports scaling down to 50% */
+- if(dev->is_em2800)
++ if (dev->is_em2800)
+ mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
+ else {
+ u8 buf[2];
+ buf[0] = h;
+ buf[1] = h >> 8;
+- em28xx_write_regs(dev, HSCALELOW_REG, (char *)buf, 2);
++ em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2);
+ buf[0] = v;
+ buf[1] = v >> 8;
+- em28xx_write_regs(dev, VSCALELOW_REG, (char *)buf, 2);
+- /* it seems that both H and V scalers must be active to work correctly */
++ em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
++ /* it seems that both H and V scalers must be active
++ to work correctly */
+ mode = (h || v)? 0x30: 0x00;
+ }
+- return em28xx_write_reg_bits(dev, COMPR_REG, mode, 0x30);
++ return em28xx_write_reg_bits(dev, EM28XX_R26_COMPR, mode, 0x30);
+ }
+
+ /* FIXME: this only function read values from dev */
+@@ -469,376 +456,271 @@ int em28xx_resolution_set(struct em28xx *dev)
+ return em28xx_scaler_set(dev, dev->hscale, dev->vscale);
+ }
+
+-
+-/******************* isoc transfer handling ****************************/
+-
+-#ifdef ENABLE_DEBUG_ISOC_FRAMES
+-static void em28xx_isoc_dump(struct urb *urb)
++int em28xx_set_alternate(struct em28xx *dev)
+ {
+- int len = 0;
+- int ntrans = 0;
++ int errCode, prev_alt = dev->alt;
+ int i;
++ unsigned int min_pkt_size = dev->width * 2 + 4;
+
+- printk(KERN_DEBUG "isocIrq: sf=%d np=%d ec=%x\n",
+- urb->start_frame, urb->number_of_packets,
+- urb->error_count);
+- for (i = 0; i < urb->number_of_packets; i++) {
+- unsigned char *buf =
+- urb->transfer_buffer +
+- urb->iso_frame_desc[i].offset;
+- int alen = urb->iso_frame_desc[i].actual_length;
+- if (alen > 0) {
+- if (buf[0] == 0x88) {
+- ntrans++;
+- len += alen;
+- } else if (buf[0] == 0x22) {
+- printk(KERN_DEBUG
+- "= l=%d nt=%d bpp=%d\n",
+- len - 4 * ntrans, ntrans,
+- ntrans == 0 ? 0 : len / ntrans);
+- ntrans = 1;
+- len = alen;
+- } else
+- printk(KERN_DEBUG "!\n");
++ /* When image size is bigger than a certain value,
++ the frame size should be increased, otherwise, only
++ green screen will be received.
++ */
++ if (dev->width * 2 * dev->height > 720 * 240 * 2)
++ min_pkt_size *= 2;
++
++ for (i = 0; i < dev->num_alt; i++) {
++ /* stop when the selected alt setting offers enough bandwidth */
++ if (dev->alt_max_pkt_size[i] >= min_pkt_size) {
++ dev->alt = i;
++ break;
++ /* otherwise make sure that we end up with the maximum bandwidth
++ because the min_pkt_size equation might be wrong...
++ */
++ } else if (dev->alt_max_pkt_size[i] >
++ dev->alt_max_pkt_size[dev->alt])
++ dev->alt = i;
++ }
++
++ if (dev->alt != prev_alt) {
++ em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n",
++ min_pkt_size, dev->alt);
++ dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt];
++ em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n",
++ dev->alt, dev->max_pkt_size);
++ errCode = usb_set_interface(dev->udev, 0, dev->alt);
++ if (errCode < 0) {
++ em28xx_errdev("cannot change alternate number to %d (error=%i)\n",
++ dev->alt, errCode);
++ return errCode;
+ }
+- printk(KERN_DEBUG " n=%d s=%d al=%d %x\n", i,
+- urb->iso_frame_desc[i].status,
+- urb->iso_frame_desc[i].actual_length,
+- (unsigned int)
+- *((unsigned char *)(urb->transfer_buffer +
+- urb->iso_frame_desc[i].
+- offset)));
+ }
++ return 0;
+ }
+-#endif
+
+-static inline int em28xx_isoc_video(struct em28xx *dev,struct em28xx_frame_t **f,
+- unsigned long *lock_flags, unsigned char buf)
++int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio)
+ {
+- if (!(buf & 0x01)) {
+- if ((*f)->state == F_GRABBING) {
+- /*previous frame is incomplete */
+- if ((*f)->fieldbytesused < dev->field_size) {
+- (*f)->state = F_ERROR;
+- em28xx_isocdbg ("dropping incomplete bottom field (%i missing bytes)",
+- dev->field_size-(*f)->fieldbytesused);
+- } else {
+- (*f)->state = F_DONE;
+- (*f)->buf.bytesused = dev->frame_size;
+- }
+- }
+- if ((*f)->state == F_DONE || (*f)->state == F_ERROR) {
+- /* move current frame to outqueue and get next free buffer from inqueue */
+- spin_lock_irqsave(&dev-> queue_lock, *lock_flags);
+- list_move_tail(&(*f)->frame, &dev->outqueue);
+- if (!list_empty(&dev->inqueue))
+- (*f) = list_entry(dev-> inqueue.next,
+- struct em28xx_frame_t,frame);
+- else
+- (*f) = NULL;
+- spin_unlock_irqrestore(&dev->queue_lock,*lock_flags);
+- }
+- if (!(*f)) {
+- em28xx_isocdbg ("new frame but no buffer is free");
+- return -1;
+- }
+- do_gettimeofday(&(*f)->buf.timestamp);
+- (*f)->buf.sequence = ++dev->frame_count;
+- (*f)->buf.field = V4L2_FIELD_INTERLACED;
+- (*f)->state = F_GRABBING;
+- (*f)->buf.bytesused = 0;
+- (*f)->top_field = 1;
+- (*f)->fieldbytesused = 0;
+- } else {
+- /* acquiring bottom field */
+- if ((*f)->state == F_GRABBING) {
+- if (!(*f)->top_field) {
+- (*f)->state = F_ERROR;
+- em28xx_isocdbg ("unexpected begin of bottom field; discarding it");
+- } else if ((*f)-> fieldbytesused < dev->field_size - 172) {
+- (*f)->state = F_ERROR;
+- em28xx_isocdbg ("dropping incomplete top field (%i missing bytes)",
+- dev->field_size-(*f)->fieldbytesused);
+- } else {
+- (*f)->top_field = 0;
+- (*f)->fieldbytesused = 0;
+- }
++ int rc = 0;
++
++ if (!gpio)
++ return rc;
++
++ dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1);
++ if (dev->mode == EM28XX_ANALOG_MODE)
++ dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x67", 1);
++ else
++ dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x37", 1);
++ msleep(6);
++
++ /* Send GPIO reset sequences specified at board entry */
++ while (gpio->sleep >= 0) {
++ if (gpio->reg >= 0) {
++ rc = em28xx_write_reg_bits(dev,
++ gpio->reg,
++ gpio->val,
++ gpio->mask);
++ if (rc < 0)
++ return rc;
+ }
++ if (gpio->sleep > 0)
++ msleep(gpio->sleep);
++
++ gpio++;
+ }
+- return (0);
++ return rc;
+ }
+
+-static inline void em28xx_isoc_video_copy(struct em28xx *dev,
+- struct em28xx_frame_t **f, unsigned char *buf, int len)
++int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode)
+ {
+- void *fieldstart, *startwrite, *startread;
+- int linesdone, currlinedone, offset, lencopy,remain;
++ if (dev->mode == set_mode)
++ return 0;
+
+- if(dev->frame_size != (*f)->buf.length){
+- em28xx_err("frame_size %i and buf.length %i are different!!!\n",dev->frame_size,(*f)->buf.length);
+- return;
++ if (set_mode == EM28XX_MODE_UNDEFINED) {
++ dev->mode = set_mode;
++ return 0;
+ }
+
+- if ((*f)->fieldbytesused + len > dev->field_size)
+- len =dev->field_size - (*f)->fieldbytesused;
+-
+- if (buf[0] != 0x88 && buf[0] != 0x22) {
+- em28xx_isocdbg("frame is not complete\n");
+- startread = buf;
+- len+=4;
+- } else
+- startread = buf + 4;
+-
+- remain = len;
++ dev->mode = set_mode;
+
+- if ((*f)->top_field)
+- fieldstart = (*f)->bufmem;
++ if (dev->mode == EM28XX_DIGITAL_MODE)
++ return em28xx_gpio_set(dev, dev->digital_gpio);
+ else
+- fieldstart = (*f)->bufmem + dev->bytesperline;
+-
+- linesdone = (*f)->fieldbytesused / dev->bytesperline;
+- currlinedone = (*f)->fieldbytesused % dev->bytesperline;
+- offset = linesdone * dev->bytesperline * 2 + currlinedone;
+- startwrite = fieldstart + offset;
+- lencopy = dev->bytesperline - currlinedone;
+- lencopy = lencopy > remain ? remain : lencopy;
+-
+- memcpy(startwrite, startread, lencopy);
+- remain -= lencopy;
+-
+- while (remain > 0) {
+- startwrite += lencopy + dev->bytesperline;
+- startread += lencopy;
+- if (dev->bytesperline > remain)
+- lencopy = remain;
+- else
+- lencopy = dev->bytesperline;
+-
+- memcpy(startwrite, startread, lencopy);
+- remain -= lencopy;
+- }
+-
+- (*f)->fieldbytesused += len;
++ return em28xx_gpio_set(dev, dev->analog_gpio);
+ }
++EXPORT_SYMBOL_GPL(em28xx_set_mode);
++
++/* ------------------------------------------------------------------
++ URB control
++ ------------------------------------------------------------------*/
+
+ /*
+- * em28xx_isoIrq()
+- * handles the incoming isoc urbs and fills the frames from our inqueue
++ * IRQ callback, called by URB callback
+ */
+-static void em28xx_isocIrq(struct urb *urb)
++static void em28xx_irq_callback(struct urb *urb)
+ {
+- struct em28xx *dev = urb->context;
+- int i, status;
+- struct em28xx_frame_t **f;
+- unsigned long lock_flags;
+-
+- if (!dev)
+- return;
+-#ifdef ENABLE_DEBUG_ISOC_FRAMES
+- if (isoc_debug>1)
+- em28xx_isoc_dump(urb);
+-#endif
+-
+- if (urb->status == -ENOENT)
+- return;
+-
+- f = &dev->frame_current;
+-
+- if (dev->stream == STREAM_INTERRUPT) {
+- dev->stream = STREAM_OFF;
+- if ((*f))
+- (*f)->state = F_QUEUED;
+- em28xx_isocdbg("stream interrupted");
+- wake_up_interruptible(&dev->wait_stream);
+- }
+-
+- if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+- return;
+-
+- if (dev->stream == STREAM_ON && !list_empty(&dev->inqueue)) {
+- if (!(*f))
+- (*f) = list_entry(dev->inqueue.next,
+- struct em28xx_frame_t, frame);
+-
+- for (i = 0; i < urb->number_of_packets; i++) {
+- unsigned char *buf = urb->transfer_buffer +
+- urb->iso_frame_desc[i].offset;
+- int len = urb->iso_frame_desc[i].actual_length - 4;
+-
+- if (urb->iso_frame_desc[i].status) {
+- em28xx_isocdbg("data error: [%d] len=%d, status=%d", i,
+- urb->iso_frame_desc[i].actual_length,
+- urb->iso_frame_desc[i].status);
+- if (urb->iso_frame_desc[i].status != -EPROTO)
+- continue;
+- }
+- if (urb->iso_frame_desc[i].actual_length <= 0) {
+- em28xx_isocdbg("packet %d is empty",i);
+- continue;
+- }
+- if (urb->iso_frame_desc[i].actual_length >
+- urb->iso_frame_desc[i].length) {
+- em28xx_isocdbg("packet bigger than packet size");
+- continue;
+- }
+- /*new frame */
+- if (buf[0] == 0x22 && buf[1] == 0x5a) {
+- em28xx_isocdbg("Video frame, length=%i!",len);
+-
+- if (em28xx_isoc_video(dev,f,&lock_flags,buf[2]))
+- break;
+- } else if (buf[0]==0x33 && buf[1]==0x95 && buf[2]==0x00) {
+- em28xx_isocdbg("VBI HEADER!!!");
+- }
++ struct em28xx_dmaqueue *dma_q = urb->context;
++ struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
++ int rc, i;
+
+- /* actual copying */
+- if ((*f)->state == F_GRABBING) {
+- em28xx_isoc_video_copy(dev,f,buf, len);
+- }
+- }
+- }
++ /* Copy data from URB */
++ spin_lock(&dev->slock);
++ rc = dev->isoc_ctl.isoc_copy(dev, urb);
++ spin_unlock(&dev->slock);
+
++ /* Reset urb buffers */
+ for (i = 0; i < urb->number_of_packets; i++) {
+ urb->iso_frame_desc[i].status = 0;
+ urb->iso_frame_desc[i].actual_length = 0;
+ }
+-
+ urb->status = 0;
+- if ((status = usb_submit_urb(urb, GFP_ATOMIC))) {
+- em28xx_errdev("resubmit of urb failed (error=%i)\n", status);
+- dev->state |= DEV_MISCONFIGURED;
++
++ urb->status = usb_submit_urb(urb, GFP_ATOMIC);
++ if (urb->status) {
++ em28xx_isocdbg("urb resubmit failed (error=%i)\n",
++ urb->status);
+ }
+- wake_up_interruptible(&dev->wait_frame);
+- return;
+ }
+
+ /*
+- * em28xx_uninit_isoc()
+- * deallocates the buffers and urbs allocated during em28xx_init_iosc()
++ * Stop and Deallocate URBs
+ */
+ void em28xx_uninit_isoc(struct em28xx *dev)
+ {
++ struct urb *urb;
+ int i;
+
+- for (i = 0; i < EM28XX_NUM_BUFS; i++) {
+- if (dev->urb[i]) {
+- usb_kill_urb(dev->urb[i]);
+- if (dev->transfer_buffer[i]) {
++ em28xx_isocdbg("em28xx: called em28xx_uninit_isoc\n");
++
++ dev->isoc_ctl.nfields = -1;
++ for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
++ urb = dev->isoc_ctl.urb[i];
++ if (urb) {
++ usb_kill_urb(urb);
++ usb_unlink_urb(urb);
++ if (dev->isoc_ctl.transfer_buffer[i]) {
+ usb_buffer_free(dev->udev,
+- dev->urb[i]->transfer_buffer_length,
+- dev->transfer_buffer[i],
+- dev->urb[i]->transfer_dma);
++ urb->transfer_buffer_length,
++ dev->isoc_ctl.transfer_buffer[i],
++ urb->transfer_dma);
+ }
+- usb_free_urb(dev->urb[i]);
++ usb_free_urb(urb);
++ dev->isoc_ctl.urb[i] = NULL;
+ }
+- dev->urb[i] = NULL;
+- dev->transfer_buffer[i] = NULL;
++ dev->isoc_ctl.transfer_buffer[i] = NULL;
+ }
++
++ kfree(dev->isoc_ctl.urb);
++ kfree(dev->isoc_ctl.transfer_buffer);
++
++ dev->isoc_ctl.urb = NULL;
++ dev->isoc_ctl.transfer_buffer = NULL;
++ dev->isoc_ctl.num_bufs = 0;
++
+ em28xx_capture_start(dev, 0);
+ }
++EXPORT_SYMBOL_GPL(em28xx_uninit_isoc);
+
+ /*
+- * em28xx_init_isoc()
+- * allocates transfer buffers and submits the urbs for isoc transfer
++ * Allocate URBs and start IRQ
+ */
+-int em28xx_init_isoc(struct em28xx *dev)
++int em28xx_init_isoc(struct em28xx *dev, int max_packets,
++ int num_bufs, int max_pkt_size,
++ int (*isoc_copy) (struct em28xx *dev, struct urb *urb))
+ {
+- /* change interface to 3 which allows the biggest packet sizes */
+- int i, errCode;
+- int sb_size;
+-
+- em28xx_set_alternate(dev);
+- sb_size = EM28XX_NUM_PACKETS * dev->max_pkt_size;
+-
+- /* reset streaming vars */
+- dev->frame_current = NULL;
+- dev->frame_count = 0;
+-
+- /* allocate urbs */
+- for (i = 0; i < EM28XX_NUM_BUFS; i++) {
+- struct urb *urb;
+- int j;
+- /* allocate transfer buffer */
+- urb = usb_alloc_urb(EM28XX_NUM_PACKETS, GFP_KERNEL);
+- if (!urb){
+- em28xx_errdev("cannot alloc urb %i\n", i);
++ struct em28xx_dmaqueue *dma_q = &dev->vidq;
++ int i;
++ int sb_size, pipe;
++ struct urb *urb;
++ int j, k;
++ int rc;
++
++ em28xx_isocdbg("em28xx: called em28xx_prepare_isoc\n");
++
++ /* De-allocates all pending stuff */
++ em28xx_uninit_isoc(dev);
++
++ dev->isoc_ctl.isoc_copy = isoc_copy;
++ dev->isoc_ctl.num_bufs = num_bufs;
++
++ dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
++ if (!dev->isoc_ctl.urb) {
++ em28xx_errdev("cannot alloc memory for usb buffers\n");
++ return -ENOMEM;
++ }
++
++ dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
++ GFP_KERNEL);
++ if (!dev->isoc_ctl.transfer_buffer) {
++ em28xx_errdev("cannot allocate memory for usbtransfer\n");
++ kfree(dev->isoc_ctl.urb);
++ return -ENOMEM;
++ }
++
++ dev->isoc_ctl.max_pkt_size = max_pkt_size;
++ dev->isoc_ctl.buf = NULL;
++
++ sb_size = max_packets * dev->isoc_ctl.max_pkt_size;
++
++ /* allocate urbs and transfer buffers */
++ for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
++ urb = usb_alloc_urb(max_packets, GFP_KERNEL);
++ if (!urb) {
++ em28xx_err("cannot alloc isoc_ctl.urb %i\n", i);
+ em28xx_uninit_isoc(dev);
+ return -ENOMEM;
+ }
+- dev->transfer_buffer[i] = usb_buffer_alloc(dev->udev, sb_size,
+- GFP_KERNEL,
+- &urb->transfer_dma);
+- if (!dev->transfer_buffer[i]) {
+- em28xx_errdev
+- ("unable to allocate %i bytes for transfer buffer %i\n",
+- sb_size, i);
++ dev->isoc_ctl.urb[i] = urb;
++
++ dev->isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->udev,
++ sb_size, GFP_KERNEL, &urb->transfer_dma);
++ if (!dev->isoc_ctl.transfer_buffer[i]) {
++ em28xx_err("unable to allocate %i bytes for transfer"
++ " buffer %i%s\n",
++ sb_size, i,
++ in_interrupt()?" while in int":"");
+ em28xx_uninit_isoc(dev);
+- usb_free_urb(urb);
+ return -ENOMEM;
+ }
+- memset(dev->transfer_buffer[i], 0, sb_size);
+- urb->dev = dev->udev;
+- urb->context = dev;
+- urb->pipe = usb_rcvisocpipe(dev->udev, 0x82);
+- urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+- urb->interval = 1;
+- urb->transfer_buffer = dev->transfer_buffer[i];
+- urb->complete = em28xx_isocIrq;
+- urb->number_of_packets = EM28XX_NUM_PACKETS;
+- urb->transfer_buffer_length = sb_size;
+- for (j = 0; j < EM28XX_NUM_PACKETS; j++) {
+- urb->iso_frame_desc[j].offset = j * dev->max_pkt_size;
+- urb->iso_frame_desc[j].length = dev->max_pkt_size;
++ memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
++
++ /* FIXME: this is a hack - should be
++ 'desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK'
++ should also be using 'desc.bInterval'
++ */
++ pipe = usb_rcvisocpipe(dev->udev,
++ dev->mode == EM28XX_ANALOG_MODE ? 0x82 : 0x84);
++
++ usb_fill_int_urb(urb, dev->udev, pipe,
++ dev->isoc_ctl.transfer_buffer[i], sb_size,
++ em28xx_irq_callback, dma_q, 1);
++
++ urb->number_of_packets = max_packets;
++ urb->transfer_flags = URB_ISO_ASAP;
++
++ k = 0;
++ for (j = 0; j < max_packets; j++) {
++ urb->iso_frame_desc[j].offset = k;
++ urb->iso_frame_desc[j].length =
++ dev->isoc_ctl.max_pkt_size;
++ k += dev->isoc_ctl.max_pkt_size;
+ }
+- dev->urb[i] = urb;
+ }
+
+- /* submit urbs */
+- em28xx_coredbg("Submitting %d urbs of %d packets (%d each)\n",
+- EM28XX_NUM_BUFS, EM28XX_NUM_PACKETS, dev->max_pkt_size);
+- for (i = 0; i < EM28XX_NUM_BUFS; i++) {
+- errCode = usb_submit_urb(dev->urb[i], GFP_KERNEL);
+- if (errCode) {
+- em28xx_errdev("submit of urb %i failed (error=%i)\n", i,
+- errCode);
+- em28xx_uninit_isoc(dev);
+- return errCode;
+- }
+- }
+-
+- return 0;
+-}
+-
+-int em28xx_set_alternate(struct em28xx *dev)
+-{
+- int errCode, prev_alt = dev->alt;
+- int i;
+- unsigned int min_pkt_size = dev->bytesperline+4;
+-
+- /* When image size is bigger than a ceirtain value,
+- the frame size should be increased, otherwise, only
+- green screen will be received.
+- */
+- if (dev->frame_size > 720*240*2)
+- min_pkt_size *= 2;
++ init_waitqueue_head(&dma_q->wq);
+
+- for (i = 0; i < dev->num_alt; i++)
+- if (dev->alt_max_pkt_size[i] >= min_pkt_size)
+- break;
+- dev->alt = i;
++ em28xx_capture_start(dev, 1);
+
+- if (dev->alt != prev_alt) {
+- em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n",
+- min_pkt_size, dev->alt);
+- dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt];
+- em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n",
+- dev->alt, dev->max_pkt_size);
+- errCode = usb_set_interface(dev->udev, 0, dev->alt);
+- if (errCode < 0) {
+- em28xx_errdev ("cannot change alternate number to %d (error=%i)\n",
+- dev->alt, errCode);
+- return errCode;
++ /* submit urbs and enables IRQ */
++ for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
++ rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC);
++ if (rc) {
++ em28xx_err("submit of urb %i failed (error=%i)\n", i,
++ rc);
++ em28xx_uninit_isoc(dev);
++ return rc;
+ }
+ }
++
+ return 0;
+ }
++EXPORT_SYMBOL_GPL(em28xx_init_isoc);
+diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c
+new file mode 100644
+index 0000000..7df8157
+--- /dev/null
++++ b/drivers/media/video/em28xx/em28xx-dvb.c
+@@ -0,0 +1,474 @@
++/*
++ DVB device driver for em28xx
++
++ (c) 2008 Mauro Carvalho Chehab <mchehab at infradead.org>
++
++ (c) 2008 Devin Heitmueller <devin.heitmueller at gmail.com>
++ - Fixes for the driver to properly work with HVR-950
++
++ (c) 2008 Aidan Thornton <makosoft at googlemail.com>
++
++ Based on cx88-dvb, saa7134-dvb and videobuf-dvb originally written by:
++ (c) 2004, 2005 Chris Pascoe <c.pascoe at itee.uq.edu.au>
++ (c) 2004 Gerd Knorr <kraxel at bytesex.org> [SuSE Labs]
++
++ 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.
++ */
++
++#include <linux/kernel.h>
++#include <linux/usb.h>
++
++#include "em28xx.h"
++#include <media/v4l2-common.h>
++#include <media/videobuf-vmalloc.h>
++
++#include "lgdt330x.h"
++#include "zl10353.h"
++
++MODULE_DESCRIPTION("driver for em28xx based DVB cards");
++MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab at infradead.org>");
++MODULE_LICENSE("GPL");
++
++static unsigned int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "enable debug messages [dvb]");
++
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
++#define dprintk(level, fmt, arg...) do { \
++if (debug >= level) \
++ printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \
++} while (0)
++
++#define EM28XX_DVB_NUM_BUFS 5
++#define EM28XX_DVB_MAX_PACKETSIZE 564
++#define EM28XX_DVB_MAX_PACKETS 64
++
++struct em28xx_dvb {
++ struct dvb_frontend *frontend;
++
++ /* feed count management */
++ struct mutex lock;
++ int nfeeds;
++
++ /* general boilerplate stuff */
++ struct dvb_adapter adapter;
++ struct dvb_demux demux;
++ struct dmxdev dmxdev;
++ struct dmx_frontend fe_hw;
++ struct dmx_frontend fe_mem;
++ struct dvb_net net;
++};
++
++
++static inline void print_err_status(struct em28xx *dev,
++ int packet, int status)
++{
++ char *errmsg = "Unknown";
++
++ switch (status) {
++ case -ENOENT:
++ errmsg = "unlinked synchronuously";
++ break;
++ case -ECONNRESET:
++ errmsg = "unlinked asynchronuously";
++ break;
++ case -ENOSR:
++ errmsg = "Buffer error (overrun)";
++ break;
++ case -EPIPE:
++ errmsg = "Stalled (device not responding)";
++ break;
++ case -EOVERFLOW:
++ errmsg = "Babble (bad cable?)";
++ break;
++ case -EPROTO:
++ errmsg = "Bit-stuff error (bad cable?)";
++ break;
++ case -EILSEQ:
++ errmsg = "CRC/Timeout (could be anything)";
++ break;
++ case -ETIME:
++ errmsg = "Device does not respond";
++ break;
++ }
++ if (packet < 0) {
++ dprintk(1, "URB status %d [%s].\n", status, errmsg);
++ } else {
++ dprintk(1, "URB packet %d, status %d [%s].\n",
++ packet, status, errmsg);
++ }
++}
++
++static inline int dvb_isoc_copy(struct em28xx *dev, struct urb *urb)
++{
++ int i;
++
++ if (!dev)
++ return 0;
++
++ if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
++ return 0;
++
++ if (urb->status < 0) {
++ print_err_status(dev, -1, urb->status);
++ if (urb->status == -ENOENT)
++ return 0;
++ }
++
++ for (i = 0; i < urb->number_of_packets; i++) {
++ int status = urb->iso_frame_desc[i].status;
++
++ if (status < 0) {
++ print_err_status(dev, i, status);
++ if (urb->iso_frame_desc[i].status != -EPROTO)
++ continue;
++ }
++
++ dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer +
++ urb->iso_frame_desc[i].offset,
++ urb->iso_frame_desc[i].actual_length);
++ }
++
++ return 0;
++}
++
++static int start_streaming(struct em28xx_dvb *dvb)
++{
++ int rc;
++ struct em28xx *dev = dvb->adapter.priv;
++
++ usb_set_interface(dev->udev, 0, 1);
++ rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
++ if (rc < 0)
++ return rc;
++
++ return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS,
++ EM28XX_DVB_NUM_BUFS, EM28XX_DVB_MAX_PACKETSIZE,
++ dvb_isoc_copy);
++}
++
++static int stop_streaming(struct em28xx_dvb *dvb)
++{
++ struct em28xx *dev = dvb->adapter.priv;
++
++ em28xx_uninit_isoc(dev);
++
++ em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
++
++ return 0;
++}
++
++static int start_feed(struct dvb_demux_feed *feed)
++{
++ struct dvb_demux *demux = feed->demux;
++ struct em28xx_dvb *dvb = demux->priv;
++ int rc, ret;
++
++ if (!demux->dmx.frontend)
++ return -EINVAL;
++
++ mutex_lock(&dvb->lock);
++ dvb->nfeeds++;
++ rc = dvb->nfeeds;
++
++ if (dvb->nfeeds == 1) {
++ ret = start_streaming(dvb);
++ if (ret < 0)
++ rc = ret;
++ }
++
++ mutex_unlock(&dvb->lock);
++ return rc;
++}
++
++static int stop_feed(struct dvb_demux_feed *feed)
++{
++ struct dvb_demux *demux = feed->demux;
++ struct em28xx_dvb *dvb = demux->priv;
++ int err = 0;
++
++ mutex_lock(&dvb->lock);
++ dvb->nfeeds--;
++
++ if (0 == dvb->nfeeds)
++ err = stop_streaming(dvb);
++
++ mutex_unlock(&dvb->lock);
++ return err;
++}
++
++
++
++/* ------------------------------------------------------------------ */
++static int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
++{
++ struct em28xx *dev = fe->dvb->priv;
++
++ if (acquire)
++ return em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
++ else
++ return em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
++}
++
++/* ------------------------------------------------------------------ */
++
++static struct lgdt330x_config em2880_lgdt3303_dev = {
++ .demod_address = 0x0e,
++ .demod_chip = LGDT3303,
++};
++
++static struct zl10353_config em28xx_zl10353_with_xc3028 = {
++ .demod_address = (0x1e >> 1),
++ .no_tuner = 1,
++ .parallel_ts = 1,
++ .if2 = 45600,
++};
++
++/* ------------------------------------------------------------------ */
++
++static int attach_xc3028(u8 addr, struct em28xx *dev)
++{
++ struct dvb_frontend *fe;
++ struct xc2028_config cfg;
++
++ memset(&cfg, 0, sizeof(cfg));
++ cfg.i2c_adap = &dev->i2c_adap;
++ cfg.i2c_addr = addr;
++ cfg.callback = em28xx_tuner_callback;
++
++ if (!dev->dvb->frontend) {
++ printk(KERN_ERR "%s/2: dvb frontend not attached. "
++ "Can't attach xc3028\n",
++ dev->name);
++ return -EINVAL;
++ }
++
++ fe = dvb_attach(xc2028_attach, dev->dvb->frontend, &cfg);
++ if (!fe) {
++ printk(KERN_ERR "%s/2: xc3028 attach failed\n",
++ dev->name);
++ dvb_frontend_detach(dev->dvb->frontend);
++ dvb_unregister_frontend(dev->dvb->frontend);
++ dev->dvb->frontend = NULL;
++ return -EINVAL;
++ }
++
++ printk(KERN_INFO "%s/2: xc3028 attached\n", dev->name);
++
++ return 0;
++}
++
++/* ------------------------------------------------------------------ */
++
++int register_dvb(struct em28xx_dvb *dvb,
++ struct module *module,
++ struct em28xx *dev,
++ struct device *device)
++{
++ int result;
++
++ mutex_init(&dvb->lock);
++
++ /* register adapter */
++ result = dvb_register_adapter(&dvb->adapter, dev->name, module, device,
++ adapter_nr);
++ if (result < 0) {
++ printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n",
++ dev->name, result);
++ goto fail_adapter;
++ }
++
++ /* Ensure all frontends negotiate bus access */
++ dvb->frontend->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl;
++
++ dvb->adapter.priv = dev;
++
++ /* register frontend */
++ result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
++ if (result < 0) {
++ printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n",
++ dev->name, result);
++ goto fail_frontend;
++ }
++
++ /* register demux stuff */
++ dvb->demux.dmx.capabilities =
++ DMX_TS_FILTERING | DMX_SECTION_FILTERING |
++ DMX_MEMORY_BASED_FILTERING;
++ dvb->demux.priv = dvb;
++ dvb->demux.filternum = 256;
++ dvb->demux.feednum = 256;
++ dvb->demux.start_feed = start_feed;
++ dvb->demux.stop_feed = stop_feed;
++
++ result = dvb_dmx_init(&dvb->demux);
++ if (result < 0) {
++ printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n",
++ dev->name, result);
++ goto fail_dmx;
++ }
++
++ dvb->dmxdev.filternum = 256;
++ dvb->dmxdev.demux = &dvb->demux.dmx;
++ dvb->dmxdev.capabilities = 0;
++ result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
++ if (result < 0) {
++ printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n",
++ dev->name, result);
++ goto fail_dmxdev;
++ }
++
++ dvb->fe_hw.source = DMX_FRONTEND_0;
++ result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
++ if (result < 0) {
++ printk(KERN_WARNING "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
++ dev->name, result);
++ goto fail_fe_hw;
++ }
++
++ dvb->fe_mem.source = DMX_MEMORY_FE;
++ result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
++ if (result < 0) {
++ printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
++ dev->name, result);
++ goto fail_fe_mem;
++ }
++
++ result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
++ if (result < 0) {
++ printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n",
++ dev->name, result);
++ goto fail_fe_conn;
++ }
++
++ /* register network adapter */
++ dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
++ return 0;
++
++fail_fe_conn:
++ dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
++fail_fe_mem:
++ dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
++fail_fe_hw:
++ dvb_dmxdev_release(&dvb->dmxdev);
++fail_dmxdev:
++ dvb_dmx_release(&dvb->demux);
++fail_dmx:
++ dvb_unregister_frontend(dvb->frontend);
++fail_frontend:
++ dvb_frontend_detach(dvb->frontend);
++ dvb_unregister_adapter(&dvb->adapter);
++fail_adapter:
++ return result;
++}
++
++static void unregister_dvb(struct em28xx_dvb *dvb)
++{
++ dvb_net_release(&dvb->net);
++ dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
++ dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
++ dvb_dmxdev_release(&dvb->dmxdev);
++ dvb_dmx_release(&dvb->demux);
++ dvb_unregister_frontend(dvb->frontend);
++ dvb_frontend_detach(dvb->frontend);
++ dvb_unregister_adapter(&dvb->adapter);
++}
++
++
++static int dvb_init(struct em28xx *dev)
++{
++ int result = 0;
++ struct em28xx_dvb *dvb;
++
++ dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL);
++
++ if (dvb == NULL) {
++ printk(KERN_INFO "em28xx_dvb: memory allocation failed\n");
++ return -ENOMEM;
++ }
++ dev->dvb = dvb;
++
++ em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
++ /* init frontend */
++ switch (dev->model) {
++ case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
++ dvb->frontend = dvb_attach(lgdt330x_attach,
++ &em2880_lgdt3303_dev,
++ &dev->i2c_adap);
++ if (attach_xc3028(0x61, dev) < 0) {
++ result = -EINVAL;
++ goto out_free;
++ }
++ break;
++ case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
++ dvb->frontend = dvb_attach(zl10353_attach,
++ &em28xx_zl10353_with_xc3028,
++ &dev->i2c_adap);
++ if (attach_xc3028(0x61, dev) < 0) {
++ result = -EINVAL;
++ goto out_free;
++ }
++ break;
++ default:
++ printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"
++ " isn't supported yet\n",
++ dev->name);
++ break;
++ }
++ if (NULL == dvb->frontend) {
++ printk(KERN_ERR
++ "%s/2: frontend initialization failed\n",
++ dev->name);
++ result = -EINVAL;
++ goto out_free;
++ }
++
++ /* register everything */
++ result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
++
++ if (result < 0)
++ goto out_free;
++
++ em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
++ printk(KERN_INFO "Successfully loaded em28xx-dvb\n");
++ return 0;
++
++out_free:
++ em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
++ kfree(dvb);
++ dev->dvb = NULL;
++ return result;
++}
++
++static int dvb_fini(struct em28xx *dev)
++{
++ if (dev->dvb) {
++ unregister_dvb(dev->dvb);
++ dev->dvb = NULL;
++ }
++
++ return 0;
++}
++
++static struct em28xx_ops dvb_ops = {
++ .id = EM28XX_DVB,
++ .name = "Em28xx dvb Extension",
++ .init = dvb_init,
++ .fini = dvb_fini,
++};
++
++static int __init em28xx_dvb_register(void)
++{
++ return em28xx_register_extension(&dvb_ops);
++}
++
++static void __exit em28xx_dvb_unregister(void)
++{
++ em28xx_unregister_extension(&dvb_ops);
++}
++
++module_init(em28xx_dvb_register);
++module_exit(em28xx_dvb_unregister);
+diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c
+index cacd04d..6a78fd2 100644
+--- a/drivers/media/video/em28xx/em28xx-i2c.c
++++ b/drivers/media/video/em28xx/em28xx-i2c.c
+@@ -33,19 +33,29 @@
+
+ /* ----------------------------------------------------------- */
+
+-static unsigned int i2c_scan = 0;
++static unsigned int i2c_scan;
+ module_param(i2c_scan, int, 0444);
+ MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
+
+-static unsigned int i2c_debug = 0;
++static unsigned int i2c_debug;
+ module_param(i2c_debug, int, 0644);
+ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+
+-#define dprintk1(lvl,fmt, args...) if (i2c_debug>=lvl) do {\
+- printk(fmt, ##args); } while (0)
+-#define dprintk2(lvl,fmt, args...) if (i2c_debug>=lvl) do{ \
+- printk(KERN_DEBUG "%s at %s: " fmt, \
+- dev->name, __FUNCTION__ , ##args); } while (0)
++
++#define dprintk1(lvl, fmt, args...) \
++do { \
++ if (i2c_debug >= lvl) { \
++ printk(fmt, ##args); \
++ } \
++} while (0)
++
++#define dprintk2(lvl, fmt, args...) \
++do { \
++ if (i2c_debug >= lvl) { \
++ printk(KERN_DEBUG "%s at %s: " fmt, \
++ dev->name, __func__ , ##args); \
++ } \
++} while (0)
+
+ /*
+ * em2800_i2c_send_max4()
+@@ -235,16 +245,16 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
+ return 0;
+ for (i = 0; i < num; i++) {
+ addr = msgs[i].addr << 1;
+- dprintk2(2,"%s %s addr=%x len=%d:",
++ dprintk2(2, "%s %s addr=%x len=%d:",
+ (msgs[i].flags & I2C_M_RD) ? "read" : "write",
+ i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
+- if (!msgs[i].len) { /* no len: check only for device presence */
++ if (!msgs[i].len) { /* no len: check only for device presence */
+ if (dev->is_em2800)
+ rc = em2800_i2c_check_for_device(dev, addr);
+ else
+ rc = em28xx_i2c_check_for_device(dev, addr);
+ if (rc < 0) {
+- dprintk2(2," no device\n");
++ dprintk2(2, " no device\n");
+ return rc;
+ }
+
+@@ -258,14 +268,13 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
+ rc = em28xx_i2c_recv_bytes(dev, addr,
+ msgs[i].buf,
+ msgs[i].len);
+- if (i2c_debug>=2) {
+- for (byte = 0; byte < msgs[i].len; byte++) {
++ if (i2c_debug >= 2) {
++ for (byte = 0; byte < msgs[i].len; byte++)
+ printk(" %02x", msgs[i].buf[byte]);
+- }
+ }
+ } else {
+ /* write bytes */
+- if (i2c_debug>=2) {
++ if (i2c_debug >= 2) {
+ for (byte = 0; byte < msgs[i].len; byte++)
+ printk(" %02x", msgs[i].buf[byte]);
+ }
+@@ -281,13 +290,13 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
+ }
+ if (rc < 0)
+ goto err;
+- if (i2c_debug>=2)
++ if (i2c_debug >= 2)
+ printk("\n");
+ }
+
+ return num;
+- err:
+- dprintk2(2," ERROR: %i\n", rc);
++err:
++ dprintk2(2, " ERROR: %i\n", rc);
+ return rc;
+ }
+
+@@ -330,7 +339,9 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
+ return -1;
+
+ buf = 0;
+- if (1 != (err = i2c_master_send(&dev->i2c_client, &buf, 1))) {
++
++ err = i2c_master_send(&dev->i2c_client, &buf, 1);
++ if (err != 1) {
+ printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
+ dev->name, err);
+ return -1;
+@@ -403,8 +414,10 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
+ break;
+ }
+ printk(KERN_INFO "Table at 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n",
+- em_eeprom->string_idx_table,em_eeprom->string1,
+- em_eeprom->string2,em_eeprom->string3);
++ em_eeprom->string_idx_table,
++ em_eeprom->string1,
++ em_eeprom->string2,
++ em_eeprom->string3);
+
+ return 0;
+ }
+@@ -430,58 +443,61 @@ static int attach_inform(struct i2c_client *client)
+ struct em28xx *dev = client->adapter->algo_data;
+
+ switch (client->addr << 1) {
+- case 0x86:
+- case 0x84:
+- case 0x96:
+- case 0x94:
+- {
+- struct v4l2_priv_tun_config tda9887_cfg;
+-
+- struct tuner_setup tun_setup;
+-
+- tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
+- tun_setup.type = TUNER_TDA9887;
+- tun_setup.addr = client->addr;
+-
+- em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
+-
+- tda9887_cfg.tuner = TUNER_TDA9887;
+- tda9887_cfg.priv = &dev->tda9887_conf;
+- em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG,
+- &tda9887_cfg);
+- break;
+- }
+- case 0x42:
+- dprintk1(1,"attach_inform: saa7114 detected.\n");
+- break;
+- case 0x4a:
+- dprintk1(1,"attach_inform: saa7113 detected.\n");
+- break;
+- case 0xa0:
+- dprintk1(1,"attach_inform: eeprom detected.\n");
+- break;
+- case 0x60:
+- case 0x8e:
+- {
+- struct IR_i2c *ir = i2c_get_clientdata(client);
+- dprintk1(1,"attach_inform: IR detected (%s).\n",ir->phys);
+- em28xx_set_ir(dev,ir);
+- break;
+- }
+- case 0x80:
+- case 0x88:
+- dprintk1(1,"attach_inform: msp34xx detected.\n");
+- break;
+- case 0xb8:
+- case 0xba:
+- dprintk1(1,"attach_inform: tvp5150 detected.\n");
+- break;
+-
+- default:
+- if (!dev->tuner_addr)
+- dev->tuner_addr = client->addr;
+-
+- dprintk1(1,"attach inform: detected I2C address %x\n", client->addr << 1);
++ case 0x86:
++ case 0x84:
++ case 0x96:
++ case 0x94:
++ {
++ struct v4l2_priv_tun_config tda9887_cfg;
++
++ struct tuner_setup tun_setup;
++
++ tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
++ tun_setup.type = TUNER_TDA9887;
++ tun_setup.addr = client->addr;
++
++ em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR,
++ &tun_setup);
++
++ tda9887_cfg.tuner = TUNER_TDA9887;
++ tda9887_cfg.priv = &dev->tda9887_conf;
++ em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG,
++ &tda9887_cfg);
++ break;
++ }
++ case 0x42:
++ dprintk1(1, "attach_inform: saa7114 detected.\n");
++ break;
++ case 0x4a:
++ dprintk1(1, "attach_inform: saa7113 detected.\n");
++ break;
++ case 0xa0:
++ dprintk1(1, "attach_inform: eeprom detected.\n");
++ break;
++ case 0x60:
++ case 0x8e:
++ {
++ struct IR_i2c *ir = i2c_get_clientdata(client);
++ dprintk1(1, "attach_inform: IR detected (%s).\n",
++ ir->phys);
++ em28xx_set_ir(dev, ir);
++ break;
++ }
++ case 0x80:
++ case 0x88:
++ dprintk1(1, "attach_inform: msp34xx detected.\n");
++ break;
++ case 0xb8:
++ case 0xba:
++ dprintk1(1, "attach_inform: tvp5150 detected.\n");
++ break;
++
++ default:
++ if (!dev->tuner_addr)
++ dev->tuner_addr = client->addr;
++
++ dprintk1(1, "attach inform: detected I2C address %x\n",
++ client->addr << 1);
+
+ }
+
+diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c
+index 10da2fd..bb58071 100644
+--- a/drivers/media/video/em28xx/em28xx-input.c
++++ b/drivers/media/video/em28xx/em28xx-input.c
+@@ -32,10 +32,12 @@
+
+ static unsigned int ir_debug;
+ module_param(ir_debug, int, 0644);
+-MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]");
++MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
+
+-#define dprintk(fmt, arg...) if (ir_debug) \
+- printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg)
++#define dprintk(fmt, arg...) \
++ if (ir_debug) { \
++ printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg); \
++ }
+
+ /* ----------------------------------------------------------------------- */
+
+@@ -44,7 +46,7 @@ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+ unsigned char b;
+
+ /* poll IR chip */
+- if (1 != i2c_master_recv(&ir->c,&b,1)) {
++ if (1 != i2c_master_recv(&ir->c, &b, 1)) {
+ dprintk("read error\n");
+ return -EIO;
+ }
+@@ -74,24 +76,25 @@ int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+ unsigned char code;
+
+ /* poll IR chip */
+- if (2 != i2c_master_recv(&ir->c,buf,2))
++ if (2 != i2c_master_recv(&ir->c, buf, 2))
+ return -EIO;
+
+ /* Does eliminate repeated parity code */
+- if (buf[1]==0xff)
++ if (buf[1] == 0xff)
+ return 0;
+
+- ir->old=buf[1];
++ ir->old = buf[1];
+
+ /* Rearranges bits to the right order */
+- code= ((buf[0]&0x01)<<5) | /* 0010 0000 */
++ code = ((buf[0]&0x01)<<5) | /* 0010 0000 */
+ ((buf[0]&0x02)<<3) | /* 0001 0000 */
+ ((buf[0]&0x04)<<1) | /* 0000 1000 */
+ ((buf[0]&0x08)>>1) | /* 0000 0100 */
+ ((buf[0]&0x10)>>3) | /* 0000 0010 */
+ ((buf[0]&0x20)>>5); /* 0000 0001 */
+
+- dprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x)\n",code,buf[0]);
++ dprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x)\n",
++ code, buf[0]);
+
+ /* return key */
+ *ir_key = code;
+@@ -106,15 +109,14 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
+
+ /* poll IR chip */
+
+- if (3 != i2c_master_recv(&ir->c,buf,3)) {
++ if (3 != i2c_master_recv(&ir->c, buf, 3)) {
+ dprintk("read error\n");
+ return -EIO;
+ }
+
+ dprintk("key %02x\n", buf[2]&0x3f);
+- if (buf[0]!=0x00){
++ if (buf[0] != 0x00)
+ return 0;
+- }
+
+ *ir_key = buf[2]&0x3f;
+ *ir_raw = buf[2]&0x3f;
+diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h
+new file mode 100644
+index 0000000..9058bed
+--- /dev/null
++++ b/drivers/media/video/em28xx/em28xx-reg.h
+@@ -0,0 +1,88 @@
++#define EM_GPIO_0 (1 << 0)
++#define EM_GPIO_1 (1 << 1)
++#define EM_GPIO_2 (1 << 2)
++#define EM_GPIO_3 (1 << 3)
++#define EM_GPIO_4 (1 << 4)
++#define EM_GPIO_5 (1 << 5)
++#define EM_GPIO_6 (1 << 6)
++#define EM_GPIO_7 (1 << 7)
++
++#define EM_GPO_0 (1 << 0)
++#define EM_GPO_1 (1 << 1)
++#define EM_GPO_2 (1 << 2)
++#define EM_GPO_3 (1 << 3)
++
++/* em2800 registers */
++#define EM2800_R08_AUDIOSRC 0x08
++
++/* em28xx registers */
++
++ /* GPIO/GPO registers */
++#define EM2880_R04_GPO 0x04 /* em2880-em2883 only */
++#define EM28XX_R08_GPIO 0x08 /* em2820 or upper */
++
++#define EM28XX_R06_I2C_CLK 0x06
++#define EM28XX_R0A_CHIPID 0x0a
++#define EM28XX_R0C_USBSUSP 0x0c /* */
++
++#define EM28XX_R0E_AUDIOSRC 0x0e
++#define EM28XX_R0F_XCLK 0x0f
++
++#define EM28XX_R10_VINMODE 0x10
++#define EM28XX_R11_VINCTRL 0x11
++#define EM28XX_R12_VINENABLE 0x12 /* */
++
++#define EM28XX_R14_GAMMA 0x14
++#define EM28XX_R15_RGAIN 0x15
++#define EM28XX_R16_GGAIN 0x16
++#define EM28XX_R17_BGAIN 0x17
++#define EM28XX_R18_ROFFSET 0x18
++#define EM28XX_R19_GOFFSET 0x19
++#define EM28XX_R1A_BOFFSET 0x1a
++
++#define EM28XX_R1B_OFLOW 0x1b
++#define EM28XX_R1C_HSTART 0x1c
++#define EM28XX_R1D_VSTART 0x1d
++#define EM28XX_R1E_CWIDTH 0x1e
++#define EM28XX_R1F_CHEIGHT 0x1f
++
++#define EM28XX_R20_YGAIN 0x20
++#define EM28XX_R21_YOFFSET 0x21
++#define EM28XX_R22_UVGAIN 0x22
++#define EM28XX_R23_UOFFSET 0x23
++#define EM28XX_R24_VOFFSET 0x24
++#define EM28XX_R25_SHARPNESS 0x25
++
++#define EM28XX_R26_COMPR 0x26
++#define EM28XX_R27_OUTFMT 0x27
++
++#define EM28XX_R28_XMIN 0x28
++#define EM28XX_R29_XMAX 0x29
++#define EM28XX_R2A_YMIN 0x2a
++#define EM28XX_R2B_YMAX 0x2b
++
++#define EM28XX_R30_HSCALELOW 0x30
++#define EM28XX_R31_HSCALEHIGH 0x31
++#define EM28XX_R32_VSCALELOW 0x32
++#define EM28XX_R33_VSCALEHIGH 0x33
++
++#define EM28XX_R40_AC97LSB 0x40
++#define EM28XX_R41_AC97MSB 0x41
++#define EM28XX_R42_AC97ADDR 0x42
++#define EM28XX_R43_AC97BUSY 0x43
++
++/* em202 registers */
++#define EM28XX_R02_MASTER_AC97 0x02
++#define EM28XX_R10_LINE_IN_AC97 0x10
++#define EM28XX_R14_VIDEO_AC97 0x14
++
++/* register settings */
++#define EM2800_AUDIO_SRC_TUNER 0x0d
++#define EM2800_AUDIO_SRC_LINE 0x0c
++#define EM28XX_AUDIO_SRC_TUNER 0xc0
++#define EM28XX_AUDIO_SRC_LINE 0x80
++
++/* FIXME: Need to be populated with the other chip ID's */
++enum em28xx_chip_id {
++ CHIP_ID_EM2883 = 36,
++};
+diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
+index 4abe670..8996175 100644
+--- a/drivers/media/video/em28xx/em28xx-video.c
++++ b/drivers/media/video/em28xx/em28xx-video.c
+@@ -1,5 +1,6 @@
+ /*
+- em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
++ em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB
++ video capture devices
+
+ Copyright (C) 2005 Ludovico Cavedon <cavedon at sssup.it>
+ Markus Rechberger <mrechberger at gmail.com>
+@@ -52,7 +53,19 @@
+ #define em28xx_videodbg(fmt, arg...) do {\
+ if (video_debug) \
+ printk(KERN_INFO "%s %s :"fmt, \
+- dev->name, __FUNCTION__ , ##arg); } while (0)
++ dev->name, __func__ , ##arg); } while (0)
++
++static unsigned int isoc_debug;
++module_param(isoc_debug, int, 0644);
++MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
++
++#define em28xx_isocdbg(fmt, arg...) \
++do {\
++ if (isoc_debug) { \
++ printk(KERN_INFO "%s %s :"fmt, \
++ dev->name, __func__ , ##arg); \
++ } \
++ } while (0)
+
+ MODULE_AUTHOR(DRIVER_AUTHOR);
+ MODULE_DESCRIPTION(DRIVER_DESC);
+@@ -74,9 +87,9 @@ MODULE_PARM_DESC(video_nr, "video device numbers");
+ MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
+ MODULE_PARM_DESC(radio_nr, "radio device numbers");
+
+-static unsigned int video_debug = 0;
+-module_param(video_debug,int,0644);
+-MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
++static unsigned int video_debug;
++module_param(video_debug, int, 0644);
++MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
+
+ /* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */
+ static unsigned long em28xx_devused;
+@@ -93,7 +106,7 @@ static struct v4l2_queryctrl em28xx_qctrl[] = {
+ .step = 0x1,
+ .default_value = 0x1f,
+ .flags = 0,
+- },{
++ }, {
+ .id = V4L2_CID_AUDIO_MUTE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Mute",
+@@ -107,8 +120,391 @@ static struct v4l2_queryctrl em28xx_qctrl[] = {
+
+ static struct usb_driver em28xx_usb_driver;
+
++/* ------------------------------------------------------------------
++ DMA and thread functions
++ ------------------------------------------------------------------*/
++
++/*
++ * Announces that a buffer were filled and request the next
++ */
++static inline void buffer_filled(struct em28xx *dev,
++ struct em28xx_dmaqueue *dma_q,
++ struct em28xx_buffer *buf)
++{
++ /* Advice that buffer was filled */
++ em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
++ buf->vb.state = VIDEOBUF_DONE;
++ buf->vb.field_count++;
++ do_gettimeofday(&buf->vb.ts);
+
+-/********************* v4l2 interface ******************************************/
++ dev->isoc_ctl.buf = NULL;
++
++ list_del(&buf->vb.queue);
++ wake_up(&buf->vb.done);
++}
++
++/*
++ * Identify the buffer header type and properly handles
++ */
++static void em28xx_copy_video(struct em28xx *dev,
++ struct em28xx_dmaqueue *dma_q,
++ struct em28xx_buffer *buf,
++ unsigned char *p,
++ unsigned char *outp, unsigned long len)
++{
++ void *fieldstart, *startwrite, *startread;
++ int linesdone, currlinedone, offset, lencopy, remain;
++ int bytesperline = dev->width << 1;
++
++ if (dma_q->pos + len > buf->vb.size)
++ len = buf->vb.size - dma_q->pos;
++
++ if (p[0] != 0x88 && p[0] != 0x22) {
++ em28xx_isocdbg("frame is not complete\n");
++ len += 4;
++ } else
++ p += 4;
++
++ startread = p;
++ remain = len;
++
++ /* Interlaces frame */
++ if (buf->top_field)
++ fieldstart = outp;
++ else
++ fieldstart = outp + bytesperline;
++
++ linesdone = dma_q->pos / bytesperline;
++ currlinedone = dma_q->pos % bytesperline;
++ offset = linesdone * bytesperline * 2 + currlinedone;
++ startwrite = fieldstart + offset;
++ lencopy = bytesperline - currlinedone;
++ lencopy = lencopy > remain ? remain : lencopy;
++
++ if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
++ em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
++ ((char *)startwrite + lencopy) -
++ ((char *)outp + buf->vb.size));
++ lencopy = remain = (char *)outp + buf->vb.size - (char *)startwrite;
++ }
++ if (lencopy <= 0)
++ return;
++ memcpy(startwrite, startread, lencopy);
++
++ remain -= lencopy;
++
++ while (remain > 0) {
++ startwrite += lencopy + bytesperline;
++ startread += lencopy;
++ if (bytesperline > remain)
++ lencopy = remain;
++ else
++ lencopy = bytesperline;
++
++ if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
++ em28xx_isocdbg("Overflow of %zi bytes past buffer end (2)\n",
++ ((char *)startwrite + lencopy) -
++ ((char *)outp + buf->vb.size));
++ lencopy = remain = (char *)outp + buf->vb.size -
++ (char *)startwrite;
++ }
++ if (lencopy <= 0)
++ break;
++
++ memcpy(startwrite, startread, lencopy);
++
++ remain -= lencopy;
++ }
++
++ dma_q->pos += len;
++}
++
++static inline void print_err_status(struct em28xx *dev,
++ int packet, int status)
++{
++ char *errmsg = "Unknown";
++
++ switch (status) {
++ case -ENOENT:
++ errmsg = "unlinked synchronuously";
++ break;
++ case -ECONNRESET:
++ errmsg = "unlinked asynchronuously";
++ break;
++ case -ENOSR:
++ errmsg = "Buffer error (overrun)";
++ break;
++ case -EPIPE:
++ errmsg = "Stalled (device not responding)";
++ break;
++ case -EOVERFLOW:
++ errmsg = "Babble (bad cable?)";
++ break;
++ case -EPROTO:
++ errmsg = "Bit-stuff error (bad cable?)";
++ break;
++ case -EILSEQ:
++ errmsg = "CRC/Timeout (could be anything)";
++ break;
++ case -ETIME:
++ errmsg = "Device does not respond";
++ break;
++ }
++ if (packet < 0) {
++ em28xx_isocdbg("URB status %d [%s].\n", status, errmsg);
++ } else {
++ em28xx_isocdbg("URB packet %d, status %d [%s].\n",
++ packet, status, errmsg);
++ }
++}
++
++/*
++ * video-buf generic routine to get the next available buffer
++ */
++static inline void get_next_buf(struct em28xx_dmaqueue *dma_q,
++ struct em28xx_buffer **buf)
++{
++ struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
++ char *outp;
++
++ if (list_empty(&dma_q->active)) {
++ em28xx_isocdbg("No active queue to serve\n");
++ dev->isoc_ctl.buf = NULL;
++ *buf = NULL;
++ return;
++ }
++
++ /* Get the next buffer */
++ *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue);
++
++ /* Cleans up buffer - Usefull for testing for frame/URB loss */
++ outp = videobuf_to_vmalloc(&(*buf)->vb);
++ memset(outp, 0, (*buf)->vb.size);
++
++ dev->isoc_ctl.buf = *buf;
++
++ return;
++}
++
++/*
++ * Controls the isoc copy of each urb packet
++ */
++static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb)
++{
++ struct em28xx_buffer *buf;
++ struct em28xx_dmaqueue *dma_q = urb->context;
++ unsigned char *outp = NULL;
++ int i, len = 0, rc = 1;
++ unsigned char *p;
++
++ if (!dev)
++ return 0;
++
++ if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
++ return 0;
++
++ if (urb->status < 0) {
++ print_err_status(dev, -1, urb->status);
++ if (urb->status == -ENOENT)
++ return 0;
++ }
++
++ buf = dev->isoc_ctl.buf;
++ if (buf != NULL)
++ outp = videobuf_to_vmalloc(&buf->vb);
++
++ for (i = 0; i < urb->number_of_packets; i++) {
++ int status = urb->iso_frame_desc[i].status;
++
++ if (status < 0) {
++ print_err_status(dev, i, status);
++ if (urb->iso_frame_desc[i].status != -EPROTO)
++ continue;
++ }
++
++ len = urb->iso_frame_desc[i].actual_length - 4;
++
++ if (urb->iso_frame_desc[i].actual_length <= 0) {
++ /* em28xx_isocdbg("packet %d is empty",i); - spammy */
++ continue;
++ }
++ if (urb->iso_frame_desc[i].actual_length >
++ dev->max_pkt_size) {
++ em28xx_isocdbg("packet bigger than packet size");
++ continue;
++ }
++
++ p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
++
++ /* FIXME: incomplete buffer checks where removed to make
++ logic simpler. Impacts of those changes should be evaluated
++ */
++ if (p[0] == 0x33 && p[1] == 0x95 && p[2] == 0x00) {
++ em28xx_isocdbg("VBI HEADER!!!\n");
++ /* FIXME: Should add vbi copy */
++ continue;
++ }
++ if (p[0] == 0x22 && p[1] == 0x5a) {
++ em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2],
++ len, (p[2] & 1)? "odd" : "even");
++
++ if (!(p[2] & 1)) {
++ if (buf != NULL)
++ buffer_filled(dev, dma_q, buf);
++ get_next_buf(dma_q, &buf);
++ if (buf == NULL)
++ outp = NULL;
++ else
++ outp = videobuf_to_vmalloc(&buf->vb);
++ }
++
++ if (buf != NULL) {
++ if (p[2] & 1)
++ buf->top_field = 0;
++ else
++ buf->top_field = 1;
++ }
++
++ dma_q->pos = 0;
++ }
++ if (buf != NULL)
++ em28xx_copy_video(dev, dma_q, buf, p, outp, len);
++ }
++ return rc;
++}
++
++/* ------------------------------------------------------------------
++ Videobuf operations
++ ------------------------------------------------------------------*/
++
++static int
++buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
++{
++ struct em28xx_fh *fh = vq->priv_data;
++ struct em28xx *dev = fh->dev;
++ struct v4l2_frequency f;
++
++ *size = 16 * fh->dev->width * fh->dev->height >> 3;
++ if (0 == *count)
++ *count = EM28XX_DEF_BUF;
++
++ if (*count < EM28XX_MIN_BUF)
++ *count = EM28XX_MIN_BUF;
++
++ /* Ask tuner to go to analog mode */
++ memset(&f, 0, sizeof(f));
++ f.frequency = dev->ctl_freq;
++
++ em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, &f);
++
++ return 0;
++}
++
++/* This is called *without* dev->slock held; please keep it that way */
++static void free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf)
++{
++ struct em28xx_fh *fh = vq->priv_data;
++ struct em28xx *dev = fh->dev;
++ unsigned long flags = 0;
++ if (in_interrupt())
++ BUG();
++
++ /* We used to wait for the buffer to finish here, but this didn't work
++ because, as we were keeping the state as VIDEOBUF_QUEUED,
++ videobuf_queue_cancel marked it as finished for us.
++ (Also, it could wedge forever if the hardware was misconfigured.)
++
++ This should be safe; by the time we get here, the buffer isn't
++ queued anymore. If we ever start marking the buffers as
++ VIDEOBUF_ACTIVE, it won't be, though.
++ */
++ spin_lock_irqsave(&dev->slock, flags);
++ if (dev->isoc_ctl.buf == buf)
++ dev->isoc_ctl.buf = NULL;
++ spin_unlock_irqrestore(&dev->slock, flags);
++
++ videobuf_vmalloc_free(&buf->vb);
++ buf->vb.state = VIDEOBUF_NEEDS_INIT;
++}
++
++static int
++buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
++ enum v4l2_field field)
++{
++ struct em28xx_fh *fh = vq->priv_data;
++ struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
++ struct em28xx *dev = fh->dev;
++ int rc = 0, urb_init = 0;
++
++ /* FIXME: It assumes depth = 16 */
++ /* The only currently supported format is 16 bits/pixel */
++ buf->vb.size = 16 * dev->width * dev->height >> 3;
++
++ if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
++ return -EINVAL;
++
++ buf->vb.width = dev->width;
++ buf->vb.height = dev->height;
++ buf->vb.field = field;
++
++ if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
++ rc = videobuf_iolock(vq, &buf->vb, NULL);
++ if (rc < 0)
++ goto fail;
++ }
++
++ if (!dev->isoc_ctl.num_bufs)
++ urb_init = 1;
++
++ if (urb_init) {
++ rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS,
++ EM28XX_NUM_BUFS, dev->max_pkt_size,
++ em28xx_isoc_copy);
++ if (rc < 0)
++ goto fail;
++ }
++
++ buf->vb.state = VIDEOBUF_PREPARED;
++ return 0;
++
++fail:
++ free_buffer(vq, buf);
++ return rc;
++}
++
++static void
++buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
++{
++ struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
++ struct em28xx_fh *fh = vq->priv_data;
++ struct em28xx *dev = fh->dev;
++ struct em28xx_dmaqueue *vidq = &dev->vidq;
++
++ buf->vb.state = VIDEOBUF_QUEUED;
++ list_add_tail(&buf->vb.queue, &vidq->active);
++
++}
++
++static void buffer_release(struct videobuf_queue *vq,
++ struct videobuf_buffer *vb)
++{
++ struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
++ struct em28xx_fh *fh = vq->priv_data;
++ struct em28xx *dev = (struct em28xx *)fh->dev;
++
++ em28xx_isocdbg("em28xx: called buffer_release\n");
++
++ free_buffer(vq, buf);
++}
++
++static struct videobuf_queue_ops em28xx_video_qops = {
++ .buf_setup = buffer_setup,
++ .buf_prepare = buffer_prepare,
++ .buf_queue = buffer_queue,
++ .buf_release = buffer_release,
++};
++
++/********************* v4l2 interface **************************************/
+
+ /*
+ * em28xx_config()
+@@ -123,9 +519,9 @@ static int em28xx_config(struct em28xx *dev)
+
+ /* enable vbi capturing */
+
+-/* em28xx_write_regs_req(dev,0x00,0x0e,"\xC0",1); audio register */
+-/* em28xx_write_regs_req(dev,0x00,0x0f,"\x80",1); clk register */
+- em28xx_write_regs_req(dev,0x00,0x11,"\x51",1);
++/* em28xx_write_regs_req(dev, 0x00, 0x0e, "\xC0", 1); audio register */
++/* em28xx_write_regs_req(dev, 0x00, 0x0f, "\x80", 1); clk register */
++ em28xx_write_regs_req(dev, 0x00, 0x11, "\x51", 1);
+
+ dev->mute = 1; /* maybe not the right place... */
+ dev->volume = 0x1f;
+@@ -152,23 +548,6 @@ static void em28xx_config_i2c(struct em28xx *dev)
+ em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL);
+ }
+
+-/*
+- * em28xx_empty_framequeues()
+- * prepare queues for incoming and outgoing frames
+- */
+-static void em28xx_empty_framequeues(struct em28xx *dev)
+-{
+- u32 i;
+-
+- INIT_LIST_HEAD(&dev->inqueue);
+- INIT_LIST_HEAD(&dev->outqueue);
+-
+- for (i = 0; i < EM28XX_NUM_FRAMES; i++) {
+- dev->frame[i].state = F_UNUSED;
+- dev->frame[i].buf.bytesused = 0;
+- }
+-}
+-
+ static void video_mux(struct em28xx *dev, int index)
+ {
+ struct v4l2_routing route;
+@@ -181,12 +560,15 @@ static void video_mux(struct em28xx *dev, int index)
+ em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);
+
+ if (dev->has_msp34xx) {
+- if (dev->i2s_speed)
+- em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed);
++ if (dev->i2s_speed) {
++ em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ,
++ &dev->i2s_speed);
++ }
+ route.input = dev->ctl_ainput;
+ route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
+ /* Note: this is msp3400 specific */
+- em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route);
++ em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING,
++ &route);
+ }
+
+ em28xx_audio_analog_set(dev);
+@@ -202,15 +584,12 @@ static int res_get(struct em28xx_fh *fh)
+ if (fh->stream_on)
+ return rc;
+
+- mutex_lock(&dev->lock);
+-
+ if (dev->stream_on)
+- rc = -EINVAL;
+- else {
+- dev->stream_on = 1;
+- fh->stream_on = 1;
+- }
++ return -EINVAL;
+
++ mutex_lock(&dev->lock);
++ dev->stream_on = 1;
++ fh->stream_on = 1;
+ mutex_unlock(&dev->lock);
+ return rc;
+ }
+@@ -231,33 +610,6 @@ static void res_free(struct em28xx_fh *fh)
+ }
+
+ /*
+- * em28xx_vm_open()
+- */
+-static void em28xx_vm_open(struct vm_area_struct *vma)
+-{
+- struct em28xx_frame_t *f = vma->vm_private_data;
+- f->vma_use_count++;
+-}
+-
+-/*
+- * em28xx_vm_close()
+- */
+-static void em28xx_vm_close(struct vm_area_struct *vma)
+-{
+- /* NOTE: buffers are not freed here */
+- struct em28xx_frame_t *f = vma->vm_private_data;
+-
+- if (f->vma_use_count)
+- f->vma_use_count--;
+-}
+-
+-static struct vm_operations_struct em28xx_vm_ops = {
+- .open = em28xx_vm_open,
+- .close = em28xx_vm_close,
+-};
+-
+-
+-/*
+ * em28xx_get_ctrl()
+ * return the current saturation, brightness or contrast, mute state
+ */
+@@ -296,34 +648,6 @@ static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl)
+ }
+ }
+
+-/*
+- * em28xx_stream_interrupt()
+- * stops streaming
+- */
+-static int em28xx_stream_interrupt(struct em28xx *dev)
+-{
+- int rc = 0;
+-
+- /* stop reading from the device */
+-
+- dev->stream = STREAM_INTERRUPT;
+- rc = wait_event_timeout(dev->wait_stream,
+- (dev->stream == STREAM_OFF) ||
+- (dev->state & DEV_DISCONNECTED),
+- EM28XX_URB_TIMEOUT);
+-
+- if (rc) {
+- dev->state |= DEV_MISCONFIGURED;
+- em28xx_videodbg("device is misconfigured; close and "
+- "open /dev/video%d again\n",
+- dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN);
+- return rc;
+- }
+-
+- return 0;
+-}
+-
+-
+ static int check_dev(struct em28xx *dev)
+ {
+ if (dev->state & DEV_DISCONNECTED) {
+@@ -370,8 +694,8 @@ static int vidioc_g_fmt_cap(struct file *file, void *priv,
+ f->fmt.pix.width = dev->width;
+ f->fmt.pix.height = dev->height;
+ f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+- f->fmt.pix.bytesperline = dev->bytesperline;
+- f->fmt.pix.sizeimage = dev->frame_size;
++ f->fmt.pix.bytesperline = dev->width * 2;
++ f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height;
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+ /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
+@@ -447,7 +771,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
+ {
+ struct em28xx_fh *fh = priv;
+ struct em28xx *dev = fh->dev;
+- int rc, i;
++ int rc;
+
+ rc = check_dev(dev);
+ if (rc < 0)
+@@ -457,49 +781,34 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
+
+ mutex_lock(&dev->lock);
+
+- for (i = 0; i < dev->num_frames; i++)
+- if (dev->frame[i].vma_use_count) {
+- em28xx_videodbg("VIDIOC_S_FMT failed. "
+- "Unmap the buffers first.\n");
+- rc = -EINVAL;
+- goto err;
+- }
+-
+- /* stop io in case it is already in progress */
+- if (dev->stream == STREAM_ON) {
+- em28xx_videodbg("VIDIOC_SET_FMT: interrupting stream\n");
+- rc = em28xx_stream_interrupt(dev);
+- if (rc < 0)
+- goto err;
++ if (videobuf_queue_is_busy(&fh->vb_vidq)) {
++ em28xx_errdev("%s queue busy\n", __func__);
++ rc = -EBUSY;
++ goto out;
+ }
+
+- em28xx_release_buffers(dev);
+- dev->io = IO_NONE;
++ if (dev->stream_on && !fh->stream_on) {
++ em28xx_errdev("%s device in use by another fh\n", __func__);
++ rc = -EBUSY;
++ goto out;
++ }
+
+ /* set new image size */
+ dev->width = f->fmt.pix.width;
+ dev->height = f->fmt.pix.height;
+- dev->frame_size = dev->width * dev->height * 2;
+- dev->field_size = dev->frame_size >> 1;
+- dev->bytesperline = dev->width * 2;
+ get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
+
+- /* FIXME: This is really weird! Why capture is starting with
+- this ioctl ???
+- */
+- em28xx_uninit_isoc(dev);
+ em28xx_set_alternate(dev);
+- em28xx_capture_start(dev, 1);
+ em28xx_resolution_set(dev);
+- em28xx_init_isoc(dev);
++
+ rc = 0;
+
+-err:
++out:
+ mutex_unlock(&dev->lock);
+ return rc;
+ }
+
+-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
++static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm)
+ {
+ struct em28xx_fh *fh = priv;
+ struct em28xx *dev = fh->dev;
+@@ -524,9 +833,6 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
+ /* set new image size */
+ dev->width = f.fmt.pix.width;
+ dev->height = f.fmt.pix.height;
+- dev->frame_size = dev->width * dev->height * 2;
+- dev->field_size = dev->frame_size >> 1;
+- dev->bytesperline = dev->width * 2;
+ get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
+
+ em28xx_resolution_set(dev);
+@@ -619,11 +925,11 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
+
+ index = dev->ctl_ainput;
+
+- if (index == 0) {
++ if (index == 0)
+ strcpy(a->name, "Television");
+- } else {
++ else
+ strcpy(a->name, "Line In");
+- }
++
+ a->capability = V4L2_AUDCAP_STEREO;
+ a->index = index;
+
+@@ -834,9 +1140,9 @@ static int vidioc_s_frequency(struct file *file, void *priv,
+ static int em28xx_reg_len(int reg)
+ {
+ switch (reg) {
+- case AC97LSB_REG:
+- case HSCALELOW_REG:
+- case VSCALELOW_REG:
++ case EM28XX_R40_AC97LSB:
++ case EM28XX_R30_HSCALELOW:
++ case EM28XX_R32_VSCALELOW:
+ return 2;
+ default:
+ return 1;
+@@ -918,23 +1224,11 @@ static int vidioc_streamon(struct file *file, void *priv,
+ if (rc < 0)
+ return rc;
+
+- if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP)
+- return -EINVAL;
+-
+- if (list_empty(&dev->inqueue))
+- return -EINVAL;
+-
+- mutex_lock(&dev->lock);
+
+- if (unlikely(res_get(fh) < 0)) {
+- mutex_unlock(&dev->lock);
++ if (unlikely(res_get(fh) < 0))
+ return -EBUSY;
+- }
+
+- dev->stream = STREAM_ON; /* FIXME: Start video capture here? */
+-
+- mutex_unlock(&dev->lock);
+- return 0;
++ return (videobuf_streamon(&fh->vb_vidq));
+ }
+
+ static int vidioc_streamoff(struct file *file, void *priv,
+@@ -948,23 +1242,14 @@ static int vidioc_streamoff(struct file *file, void *priv,
+ if (rc < 0)
+ return rc;
+
+- if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP)
++ if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++ return -EINVAL;
++ if (type != fh->type)
+ return -EINVAL;
+
+- mutex_lock(&dev->lock);
+-
+- if (dev->stream == STREAM_ON) {
+- em28xx_videodbg("VIDIOC_STREAMOFF: interrupting stream\n");
+- rc = em28xx_stream_interrupt(dev);
+- if (rc < 0) {
+- mutex_unlock(&dev->lock);
+- return rc;
+- }
+- }
+-
+- em28xx_empty_framequeues(dev);
++ videobuf_streamoff(&fh->vb_vidq);
++ res_free(fh);
+
+- mutex_unlock(&dev->lock);
+ return 0;
+ }
+
+@@ -1058,53 +1343,13 @@ static int vidioc_reqbufs(struct file *file, void *priv,
+ {
+ struct em28xx_fh *fh = priv;
+ struct em28xx *dev = fh->dev;
+- u32 i;
+ int rc;
+
+ rc = check_dev(dev);
+ if (rc < 0)
+ return rc;
+
+- if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+- rb->memory != V4L2_MEMORY_MMAP)
+- return -EINVAL;
+-
+- if (dev->io == IO_READ) {
+- em28xx_videodbg("method is set to read;"
+- " close and open the device again to"
+- " choose the mmap I/O method\n");
+- return -EINVAL;
+- }
+-
+- for (i = 0; i < dev->num_frames; i++)
+- if (dev->frame[i].vma_use_count) {
+- em28xx_videodbg("VIDIOC_REQBUFS failed; "
+- "previous buffers are still mapped\n");
+- return -EINVAL;
+- }
+-
+- mutex_lock(&dev->lock);
+-
+- if (dev->stream == STREAM_ON) {
+- em28xx_videodbg("VIDIOC_REQBUFS: interrupting stream\n");
+- rc = em28xx_stream_interrupt(dev);
+- if (rc < 0) {
+- mutex_unlock(&dev->lock);
+- return rc;
+- }
+- }
+-
+- em28xx_empty_framequeues(dev);
+-
+- em28xx_release_buffers(dev);
+- if (rb->count)
+- rb->count = em28xx_request_buffers(dev, rb->count);
+-
+- dev->frame_current = NULL;
+- dev->io = rb->count ? IO_MMAP : IO_NONE;
+-
+- mutex_unlock(&dev->lock);
+- return 0;
++ return (videobuf_reqbufs(&fh->vb_vidq, rb));
+ }
+
+ static int vidioc_querybuf(struct file *file, void *priv,
+@@ -1118,52 +1363,20 @@ static int vidioc_querybuf(struct file *file, void *priv,
+ if (rc < 0)
+ return rc;
+
+- if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+- b->index >= dev->num_frames || dev->io != IO_MMAP)
+- return -EINVAL;
+-
+- mutex_lock(&dev->lock);
+-
+- memcpy(b, &dev->frame[b->index].buf, sizeof(*b));
+-
+- if (dev->frame[b->index].vma_use_count)
+- b->flags |= V4L2_BUF_FLAG_MAPPED;
+-
+- if (dev->frame[b->index].state == F_DONE)
+- b->flags |= V4L2_BUF_FLAG_DONE;
+- else if (dev->frame[b->index].state != F_UNUSED)
+- b->flags |= V4L2_BUF_FLAG_QUEUED;
+-
+- mutex_unlock(&dev->lock);
+- return 0;
++ return (videobuf_querybuf(&fh->vb_vidq, b));
+ }
+
+ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+ {
+ struct em28xx_fh *fh = priv;
+ struct em28xx *dev = fh->dev;
+- unsigned long lock_flags;
+ int rc;
+
+ rc = check_dev(dev);
+ if (rc < 0)
+ return rc;
+
+- if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP ||
+- b->index >= dev->num_frames)
+- return -EINVAL;
+-
+- if (dev->frame[b->index].state != F_UNUSED)
+- return -EAGAIN;
+-
+- dev->frame[b->index].state = F_QUEUED;
+-
+- /* add frame to fifo */
+- spin_lock_irqsave(&dev->queue_lock, lock_flags);
+- list_add_tail(&dev->frame[b->index].frame, &dev->inqueue);
+- spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
+-
+- return 0;
++ return (videobuf_qbuf(&fh->vb_vidq, b));
+ }
+
+ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+@@ -1171,46 +1384,24 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+ struct em28xx_fh *fh = priv;
+ struct em28xx *dev = fh->dev;
+ int rc;
+- struct em28xx_frame_t *f;
+- unsigned long lock_flags;
+
+ rc = check_dev(dev);
+ if (rc < 0)
+ return rc;
+
+- if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP)
+- return -EINVAL;
+-
+- if (list_empty(&dev->outqueue)) {
+- if (dev->stream == STREAM_OFF)
+- return -EINVAL;
+-
+- if (file->f_flags & O_NONBLOCK)
+- return -EAGAIN;
+-
+- rc = wait_event_interruptible(dev->wait_frame,
+- (!list_empty(&dev->outqueue)) ||
+- (dev->state & DEV_DISCONNECTED));
+- if (rc)
+- return rc;
+-
+- if (dev->state & DEV_DISCONNECTED)
+- return -ENODEV;
+- }
+-
+- spin_lock_irqsave(&dev->queue_lock, lock_flags);
+- f = list_entry(dev->outqueue.next, struct em28xx_frame_t, frame);
+- list_del(dev->outqueue.next);
+- spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
+-
+- f->state = F_UNUSED;
+- memcpy(b, &f->buf, sizeof(*b));
++ return (videobuf_dqbuf(&fh->vb_vidq, b,
++ file->f_flags & O_NONBLOCK));
++}
+
+- if (f->vma_use_count)
+- b->flags |= V4L2_BUF_FLAG_MAPPED;
++#ifdef CONFIG_VIDEO_V4L1_COMPAT
++static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
++{
++ struct em28xx_fh *fh = priv;
+
+- return 0;
++ return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
+ }
++#endif
++
+
+ /* ----------------------------------------------------------- */
+ /* RADIO ESPECIFIC IOCTLS */
+@@ -1316,17 +1507,18 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
+ {
+ int minor = iminor(inode);
+ int errCode = 0, radio = 0;
+- struct em28xx *h,*dev = NULL;
++ struct em28xx *h, *dev = NULL;
+ struct em28xx_fh *fh;
++ enum v4l2_buf_type fh_type = 0;
+
+ list_for_each_entry(h, &em28xx_devlist, devlist) {
+ if (h->vdev->minor == minor) {
+ dev = h;
+- dev->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ }
+ if (h->vbi_dev->minor == minor) {
+ dev = h;
+- dev->type = V4L2_BUF_TYPE_VBI_CAPTURE;
++ fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
+ }
+ if (h->radio_dev &&
+ h->radio_dev->minor == minor) {
+@@ -1338,10 +1530,10 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
+ return -ENODEV;
+
+ em28xx_videodbg("open minor=%d type=%s users=%d\n",
+- minor,v4l2_type_names[dev->type],dev->users);
++ minor, v4l2_type_names[fh_type], dev->users);
+
+- fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
+
++ fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
+ if (!fh) {
+ em28xx_errdev("em28xx-video.c: Out of memory?!\n");
+ return -ENOMEM;
+@@ -1349,28 +1541,24 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
+ mutex_lock(&dev->lock);
+ fh->dev = dev;
+ fh->radio = radio;
++ fh->type = fh_type;
+ filp->private_data = fh;
+
+- if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
++ if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
+ dev->width = norm_maxw(dev);
+ dev->height = norm_maxh(dev);
+- dev->frame_size = dev->width * dev->height * 2;
+- dev->field_size = dev->frame_size >> 1; /*both_fileds ? dev->frame_size>>1 : dev->frame_size; */
+- dev->bytesperline = dev->width * 2;
+ dev->hscale = 0;
+ dev->vscale = 0;
+
++ em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
+ em28xx_set_alternate(dev);
+- em28xx_capture_start(dev, 1);
+ em28xx_resolution_set(dev);
+
++ /* Needed, since GPIO might have disabled power of
++ some i2c device
++ */
++ em28xx_config_i2c(dev);
+
+- /* start the transfer */
+- errCode = em28xx_init_isoc(dev);
+- if (errCode)
+- goto err;
+-
+- em28xx_empty_framequeues(dev);
+ }
+ if (fh->radio) {
+ em28xx_videodbg("video_open: setting radio device\n");
+@@ -1379,8 +1567,12 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
+
+ dev->users++;
+
+-err:
++ videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops,
++ NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED,
++ sizeof(struct em28xx_buffer), fh);
++
+ mutex_unlock(&dev->lock);
++
+ return errCode;
+ }
+
+@@ -1423,12 +1615,13 @@ static void em28xx_release_resources(struct em28xx *dev)
+ usb_put_dev(dev->udev);
+
+ /* Mark device as unused */
+- em28xx_devused&=~(1<<dev->devno);
++ em28xx_devused &= ~(1<<dev->devno);
+ }
+
+ /*
+ * em28xx_v4l2_close()
+- * stops streaming and deallocates all resources allocated by the v4l2 calls and ioctls
++ * stops streaming and deallocates all resources allocated by the v4l2
++ * calls and ioctls
+ */
+ static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
+ {
+@@ -1445,9 +1638,8 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
+ mutex_lock(&dev->lock);
+
+ if (dev->users == 1) {
+- em28xx_uninit_isoc(dev);
+- em28xx_release_buffers(dev);
+- dev->io = IO_NONE;
++ videobuf_stop(&fh->vb_vidq);
++ videobuf_mmap_free(&fh->vb_vidq);
+
+ /* the device is already disconnect,
+ free the remaining resources */
+@@ -1458,6 +1650,10 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
+ return 0;
+ }
+
++ /* do this before setting alternate! */
++ em28xx_uninit_isoc(dev);
++ em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
++
+ /* set alternate 0 */
+ dev->alt = 0;
+ em28xx_videodbg("setting alternate 0\n");
+@@ -1479,135 +1675,29 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
+ * will allocate buffers when called for the first time
+ */
+ static ssize_t
+-em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
+- loff_t * f_pos)
++em28xx_v4l2_read(struct file *filp, char __user *buf, size_t count,
++ loff_t *pos)
+ {
+- struct em28xx_frame_t *f, *i;
+- unsigned long lock_flags;
+- int ret = 0;
+ struct em28xx_fh *fh = filp->private_data;
+ struct em28xx *dev = fh->dev;
++ int rc;
++
++ rc = check_dev(dev);
++ if (rc < 0)
++ return rc;
+
+ /* FIXME: read() is not prepared to allow changing the video
+ resolution while streaming. Seems a bug at em28xx_set_fmt
+ */
+
+- if (unlikely(res_get(fh) < 0))
+- return -EBUSY;
+-
+- mutex_lock(&dev->lock);
+-
+- if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+- em28xx_videodbg("V4l2_Buf_type_videocapture is set\n");
++ if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
++ if (unlikely(res_get(fh)))
++ return -EBUSY;
+
+- if (dev->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+- em28xx_videodbg("V4L2_BUF_TYPE_VBI_CAPTURE is set\n");
+- em28xx_videodbg("not supported yet! ...\n");
+- if (copy_to_user(buf, "", 1)) {
+- mutex_unlock(&dev->lock);
+- return -EFAULT;
+- }
+- mutex_unlock(&dev->lock);
+- return (1);
+- }
+- if (dev->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
+- em28xx_videodbg("V4L2_BUF_TYPE_SLICED_VBI_CAPTURE is set\n");
+- em28xx_videodbg("not supported yet! ...\n");
+- if (copy_to_user(buf, "", 1)) {
+- mutex_unlock(&dev->lock);
+- return -EFAULT;
+- }
+- mutex_unlock(&dev->lock);
+- return (1);
++ return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
++ filp->f_flags & O_NONBLOCK);
+ }
+-
+- if (dev->state & DEV_DISCONNECTED) {
+- em28xx_videodbg("device not present\n");
+- mutex_unlock(&dev->lock);
+- return -ENODEV;
+- }
+-
+- if (dev->state & DEV_MISCONFIGURED) {
+- em28xx_videodbg("device misconfigured; close and open it again\n");
+- mutex_unlock(&dev->lock);
+- return -EIO;
+- }
+-
+- if (dev->io == IO_MMAP) {
+- em28xx_videodbg ("IO method is set to mmap; close and open"
+- " the device again to choose the read method\n");
+- mutex_unlock(&dev->lock);
+- return -EINVAL;
+- }
+-
+- if (dev->io == IO_NONE) {
+- if (!em28xx_request_buffers(dev, EM28XX_NUM_READ_FRAMES)) {
+- em28xx_errdev("read failed, not enough memory\n");
+- mutex_unlock(&dev->lock);
+- return -ENOMEM;
+- }
+- dev->io = IO_READ;
+- dev->stream = STREAM_ON;
+- em28xx_queue_unusedframes(dev);
+- }
+-
+- if (!count) {
+- mutex_unlock(&dev->lock);
+- return 0;
+- }
+-
+- if (list_empty(&dev->outqueue)) {
+- if (filp->f_flags & O_NONBLOCK) {
+- mutex_unlock(&dev->lock);
+- return -EAGAIN;
+- }
+- ret = wait_event_interruptible
+- (dev->wait_frame,
+- (!list_empty(&dev->outqueue)) ||
+- (dev->state & DEV_DISCONNECTED));
+- if (ret) {
+- mutex_unlock(&dev->lock);
+- return ret;
+- }
+- if (dev->state & DEV_DISCONNECTED) {
+- mutex_unlock(&dev->lock);
+- return -ENODEV;
+- }
+- dev->video_bytesread = 0;
+- }
+-
+- f = list_entry(dev->outqueue.prev, struct em28xx_frame_t, frame);
+-
+- em28xx_queue_unusedframes(dev);
+-
+- if (count > f->buf.length)
+- count = f->buf.length;
+-
+- if ((dev->video_bytesread + count) > dev->frame_size)
+- count = dev->frame_size - dev->video_bytesread;
+-
+- if (copy_to_user(buf, f->bufmem+dev->video_bytesread, count)) {
+- em28xx_err("Error while copying to user\n");
+- return -EFAULT;
+- }
+- dev->video_bytesread += count;
+-
+- if (dev->video_bytesread == dev->frame_size) {
+- spin_lock_irqsave(&dev->queue_lock, lock_flags);
+- list_for_each_entry(i, &dev->outqueue, frame)
+- i->state = F_UNUSED;
+- INIT_LIST_HEAD(&dev->outqueue);
+- spin_unlock_irqrestore(&dev->queue_lock, lock_flags);
+-
+- em28xx_queue_unusedframes(dev);
+- dev->video_bytesread = 0;
+- }
+-
+- *f_pos += count;
+-
+- mutex_unlock(&dev->lock);
+-
+- return count;
++ return 0;
+ }
+
+ /*
+@@ -1616,46 +1706,21 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count,
+ */
+ static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait)
+ {
+- unsigned int mask = 0;
+ struct em28xx_fh *fh = filp->private_data;
+ struct em28xx *dev = fh->dev;
++ int rc;
++
++ rc = check_dev(dev);
++ if (rc < 0)
++ return rc;
+
+ if (unlikely(res_get(fh) < 0))
+ return POLLERR;
+
+- mutex_lock(&dev->lock);
+-
+- if (dev->state & DEV_DISCONNECTED) {
+- em28xx_videodbg("device not present\n");
+- } else if (dev->state & DEV_MISCONFIGURED) {
+- em28xx_videodbg("device is misconfigured; close and open it again\n");
+- } else {
+- if (dev->io == IO_NONE) {
+- if (!em28xx_request_buffers
+- (dev, EM28XX_NUM_READ_FRAMES)) {
+- em28xx_warn
+- ("poll() failed, not enough memory\n");
+- } else {
+- dev->io = IO_READ;
+- dev->stream = STREAM_ON;
+- }
+- }
+-
+- if (dev->io == IO_READ) {
+- em28xx_queue_unusedframes(dev);
+- poll_wait(filp, &dev->wait_frame, wait);
+-
+- if (!list_empty(&dev->outqueue))
+- mask |= POLLIN | POLLRDNORM;
+-
+- mutex_unlock(&dev->lock);
+-
+- return mask;
+- }
+- }
++ if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
++ return POLLERR;
+
+- mutex_unlock(&dev->lock);
+- return POLLERR;
++ return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
+ }
+
+ /*
+@@ -1665,69 +1730,23 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
+ {
+ struct em28xx_fh *fh = filp->private_data;
+ struct em28xx *dev = fh->dev;
+- unsigned long size = vma->vm_end - vma->vm_start;
+- unsigned long start = vma->vm_start;
+- void *pos;
+- u32 i;
++ int rc;
+
+ if (unlikely(res_get(fh) < 0))
+ return -EBUSY;
+
+- mutex_lock(&dev->lock);
+-
+- if (dev->state & DEV_DISCONNECTED) {
+- em28xx_videodbg("mmap: device not present\n");
+- mutex_unlock(&dev->lock);
+- return -ENODEV;
+- }
+-
+- if (dev->state & DEV_MISCONFIGURED) {
+- em28xx_videodbg ("mmap: Device is misconfigured; close and "
+- "open it again\n");
+- mutex_unlock(&dev->lock);
+- return -EIO;
+- }
+-
+- if (dev->io != IO_MMAP || !(vma->vm_flags & VM_WRITE)) {
+- mutex_unlock(&dev->lock);
+- return -EINVAL;
+- }
+-
+- if (size > PAGE_ALIGN(dev->frame[0].buf.length))
+- size = PAGE_ALIGN(dev->frame[0].buf.length);
+-
+- for (i = 0; i < dev->num_frames; i++) {
+- if ((dev->frame[i].buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
+- break;
+- }
+- if (i == dev->num_frames) {
+- em28xx_videodbg("mmap: user supplied mapping address is out of range\n");
+- mutex_unlock(&dev->lock);
+- return -EINVAL;
+- }
+-
+- /* VM_IO is eventually going to replace PageReserved altogether */
+- vma->vm_flags |= VM_IO;
+- vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */
++ rc = check_dev(dev);
++ if (rc < 0)
++ return rc;
+
+- pos = dev->frame[i].bufmem;
+- while (size > 0) { /* size is page-aligned */
+- if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
+- em28xx_videodbg("mmap: vm_insert_page failed\n");
+- mutex_unlock(&dev->lock);
+- return -EAGAIN;
+- }
+- start += PAGE_SIZE;
+- pos += PAGE_SIZE;
+- size -= PAGE_SIZE;
+- }
++ rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
+
+- vma->vm_ops = &em28xx_vm_ops;
+- vma->vm_private_data = &dev->frame[i];
++ em28xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n",
++ (unsigned long)vma->vm_start,
++ (unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
++ rc);
+
+- em28xx_vm_open(vma);
+- mutex_unlock(&dev->lock);
+- return 0;
++ return rc;
+ }
+
+ static const struct file_operations em28xx_v4l_fops = {
+@@ -1790,6 +1809,9 @@ static const struct video_device em28xx_video_template = {
+ .vidioc_g_register = vidioc_g_register,
+ .vidioc_s_register = vidioc_s_register,
+ #endif
++#ifdef CONFIG_VIDEO_V4L1_COMPAT
++ .vidiocgmbuf = vidiocgmbuf,
++#endif
+
+ .tvnorms = V4L2_STD_ALL,
+ .current_norm = V4L2_STD_PAL,
+@@ -1818,7 +1840,7 @@ static struct video_device em28xx_radio_template = {
+ #endif
+ };
+
+-/******************************** usb interface *****************************************/
++/******************************** usb interface ******************************/
+
+
+ static LIST_HEAD(em28xx_extension_devlist);
+@@ -1875,6 +1897,7 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev,
+ vfd->dev = &dev->udev->dev;
+ vfd->release = video_device_release;
+ vfd->type = type;
++ vfd->debug = video_debug;
+
+ snprintf(vfd->name, sizeof(vfd->name), "%s %s",
+ dev->name, type_name);
+@@ -1898,7 +1921,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
+
+ dev->udev = udev;
+ mutex_init(&dev->lock);
+- spin_lock_init(&dev->queue_lock);
++ spin_lock_init(&dev->slock);
+ init_waitqueue_head(&dev->open);
+ init_waitqueue_head(&dev->wait_frame);
+ init_waitqueue_head(&dev->wait_stream);
+@@ -1910,10 +1933,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
+ dev->em28xx_read_reg_req = em28xx_read_reg_req;
+ dev->is_em2800 = em28xx_boards[dev->model].is_em2800;
+
+- errCode = em28xx_read_reg(dev, CHIPID_REG);
+- if (errCode >= 0)
+- em28xx_info("em28xx chip ID = %d\n", errCode);
+-
+ em28xx_pre_card_setup(dev);
+
+ errCode = em28xx_config(dev);
+@@ -1946,10 +1965,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
+ dev->width = maxw;
+ dev->height = maxh;
+ dev->interlaced = EM28XX_INTERLACED_DEFAULT;
+- dev->field_size = dev->width * dev->height;
+- dev->frame_size =
+- dev->interlaced ? dev->field_size << 1 : dev->field_size;
+- dev->bytesperline = dev->width * 2;
+ dev->hscale = 0;
+ dev->vscale = 0;
+ dev->ctl_input = 2;
+@@ -2005,6 +2020,10 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
+ dev->radio_dev->minor & 0x1f);
+ }
+
++ /* init video dma queues */
++ INIT_LIST_HEAD(&dev->vidq.active);
++ INIT_LIST_HEAD(&dev->vidq.queued);
++
+
+ if (dev->has_msp34xx) {
+ /* Send a reset to other chips via gpio */
+@@ -2048,6 +2067,9 @@ static void request_module_async(struct work_struct *work)
+ request_module("snd-usb-audio");
+ else
+ request_module("em28xx-alsa");
++
++ if (dev->has_dvb)
++ request_module("em28xx-dvb");
+ }
+
+ static void request_modules(struct em28xx *dev)
+@@ -2077,22 +2099,24 @@ static int em28xx_usb_probe(struct usb_interface *interface,
+ ifnum = interface->altsetting[0].desc.bInterfaceNumber;
+
+ /* Check to see next free device and mark as used */
+- nr=find_first_zero_bit(&em28xx_devused,EM28XX_MAXBOARDS);
+- em28xx_devused|=1<<nr;
++ nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS);
++ em28xx_devused |= 1<<nr;
+
+ /* Don't register audio interfaces */
+ if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
+ em28xx_err(DRIVER_NAME " audio device (%04x:%04x): interface %i, class %i\n",
+- udev->descriptor.idVendor,udev->descriptor.idProduct,
++ udev->descriptor.idVendor,
++ udev->descriptor.idProduct,
+ ifnum,
+ interface->altsetting[0].desc.bInterfaceClass);
+
+- em28xx_devused&=~(1<<nr);
++ em28xx_devused &= ~(1<<nr);
+ return -ENODEV;
+ }
+
+ em28xx_err(DRIVER_NAME " new video device (%04x:%04x): interface %i, class %i\n",
+- udev->descriptor.idVendor,udev->descriptor.idProduct,
++ udev->descriptor.idVendor,
++ udev->descriptor.idProduct,
+ ifnum,
+ interface->altsetting[0].desc.bInterfaceClass);
+
+@@ -2102,18 +2126,19 @@ static int em28xx_usb_probe(struct usb_interface *interface,
+ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
+ USB_ENDPOINT_XFER_ISOC) {
+ em28xx_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n");
+- em28xx_devused&=~(1<<nr);
++ em28xx_devused &= ~(1<<nr);
+ return -ENODEV;
+ }
+ if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {
+ em28xx_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n");
+- em28xx_devused&=~(1<<nr);
++ em28xx_devused &= ~(1<<nr);
+ return -ENODEV;
+ }
+
+ if (nr >= EM28XX_MAXBOARDS) {
+- printk (DRIVER_NAME ": Supports only %i em28xx boards.\n",EM28XX_MAXBOARDS);
+- em28xx_devused&=~(1<<nr);
++ printk(DRIVER_NAME ": Supports only %i em28xx boards.\n",
++ EM28XX_MAXBOARDS);
++ em28xx_devused &= ~(1<<nr);
+ return -ENOMEM;
+ }
+
+@@ -2121,7 +2146,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (dev == NULL) {
+ em28xx_err(DRIVER_NAME ": out of memory!\n");
+- em28xx_devused&=~(1<<nr);
++ em28xx_devused &= ~(1<<nr);
+ return -ENOMEM;
+ }
+
+@@ -2145,14 +2170,14 @@ static int em28xx_usb_probe(struct usb_interface *interface,
+ /* compute alternate max packet sizes */
+ uif = udev->actconfig->interface[0];
+
+- dev->num_alt=uif->num_altsetting;
+- em28xx_info("Alternate settings: %i\n",dev->num_alt);
+-// dev->alt_max_pkt_size = kmalloc(sizeof(*dev->alt_max_pkt_size)*
+- dev->alt_max_pkt_size = kmalloc(32*
+- dev->num_alt,GFP_KERNEL);
++ dev->num_alt = uif->num_altsetting;
++ em28xx_info("Alternate settings: %i\n", dev->num_alt);
++/* dev->alt_max_pkt_size = kmalloc(sizeof(*dev->alt_max_pkt_size)* */
++ dev->alt_max_pkt_size = kmalloc(32 * dev->num_alt, GFP_KERNEL);
++
+ if (dev->alt_max_pkt_size == NULL) {
+ em28xx_errdev("out of memory!\n");
+- em28xx_devused&=~(1<<nr);
++ em28xx_devused &= ~(1<<nr);
+ kfree(dev);
+ return -ENOMEM;
+ }
+@@ -2162,11 +2187,11 @@ static int em28xx_usb_probe(struct usb_interface *interface,
+ wMaxPacketSize);
+ dev->alt_max_pkt_size[i] =
+ (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
+- em28xx_info("Alternate setting %i, max size= %i\n",i,
+- dev->alt_max_pkt_size[i]);
++ em28xx_info("Alternate setting %i, max size= %i\n", i,
++ dev->alt_max_pkt_size[i]);
+ }
+
+- if ((card[nr]>=0)&&(card[nr]<em28xx_bcount))
++ if ((card[nr] >= 0) && (card[nr] < em28xx_bcount))
+ dev->model = card[nr];
+
+ /* allocate device struct */
+@@ -2202,7 +2227,8 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
+
+ em28xx_info("disconnecting %s\n", dev->vdev->name);
+
+- /* wait until all current v4l2 io is finished then deallocate resources */
++ /* wait until all current v4l2 io is finished then deallocate
++ resources */
+ mutex_lock(&dev->lock);
+
+ wake_up_interruptible_all(&dev->open);
+diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
+index 04e0e48..002f170 100644
+--- a/drivers/media/video/em28xx/em28xx.h
++++ b/drivers/media/video/em28xx/em28xx.h
+@@ -26,11 +26,39 @@
+ #define _EM28XX_H
+
+ #include <linux/videodev2.h>
++#include <media/videobuf-vmalloc.h>
++
+ #include <linux/i2c.h>
+ #include <linux/mutex.h>
+ #include <media/ir-kbd-i2c.h>
+-
+-#define UNSET -1
++#if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE)
++#include <media/videobuf-dvb.h>
++#endif
++#include "tuner-xc2028.h"
++#include "em28xx-reg.h"
++
++/* Boards supported by driver */
++#define EM2800_BOARD_UNKNOWN 0
++#define EM2820_BOARD_UNKNOWN 1
++#define EM2820_BOARD_TERRATEC_CINERGY_250 2
++#define EM2820_BOARD_PINNACLE_USB_2 3
++#define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 4
++#define EM2820_BOARD_MSI_VOX_USB_2 5
++#define EM2800_BOARD_TERRATEC_CINERGY_200 6
++#define EM2800_BOARD_LEADTEK_WINFAST_USBII 7
++#define EM2800_BOARD_KWORLD_USB2800 8
++#define EM2820_BOARD_PINNACLE_DVC_90 9
++#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 10
++#define EM2880_BOARD_TERRATEC_HYBRID_XS 11
++#define EM2820_BOARD_KWORLD_PVRTV2800RF 12
++#define EM2880_BOARD_TERRATEC_PRODIGY_XS 13
++#define EM2820_BOARD_PROLINK_PLAYTV_USB2 14
++#define EM2800_BOARD_VGEAR_POCKETTV 15
++#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 16
++
++/* Limits minimum and default number of buffers */
++#define EM28XX_MIN_BUF 4
++#define EM28XX_DEF_BUF 8
+
+ /* maximum number of em28xx boards */
+ #define EM28XX_MAXBOARDS 4 /*FIXME: should be bigger */
+@@ -81,31 +109,78 @@
+ /* time in msecs to wait for i2c writes to finish */
+ #define EM2800_I2C_WRITE_TIMEOUT 20
+
+-/* the various frame states */
+-enum em28xx_frame_state {
+- F_UNUSED = 0,
+- F_QUEUED,
+- F_GRABBING,
+- F_DONE,
+- F_ERROR,
++enum em28xx_mode {
++ EM28XX_MODE_UNDEFINED,
++ EM28XX_ANALOG_MODE,
++ EM28XX_DIGITAL_MODE,
+ };
+
+-/* stream states */
+ enum em28xx_stream_state {
+ STREAM_OFF,
+ STREAM_INTERRUPT,
+ STREAM_ON,
+ };
+
+-/* frames */
+-struct em28xx_frame_t {
+- void *bufmem;
+- struct v4l2_buffer buf;
+- enum em28xx_frame_state state;
++struct em28xx;
++
++struct em28xx_usb_isoc_ctl {
++ /* max packet size of isoc transaction */
++ int max_pkt_size;
++
++ /* number of allocated urbs */
++ int num_bufs;
++
++ /* urb for isoc transfers */
++ struct urb **urb;
++
++ /* transfer buffers for isoc transfer */
++ char **transfer_buffer;
++
++ /* Last buffer command and region */
++ u8 cmd;
++ int pos, size, pktsize;
++
++ /* Last field: ODD or EVEN? */
++ int field;
++
++ /* Stores incomplete commands */
++ u32 tmp_buf;
++ int tmp_buf_len;
++
++ /* Stores already requested buffers */
++ struct em28xx_buffer *buf;
++
++ /* Stores the number of received fields */
++ int nfields;
++
++ /* isoc urb callback */
++ int (*isoc_copy) (struct em28xx *dev, struct urb *urb);
++
++};
++
++struct em28xx_fmt {
++ char *name;
++ u32 fourcc; /* v4l2 format id */
++};
++
++/* buffer for one video frame */
++struct em28xx_buffer {
++ /* common v4l buffer stuff -- must be first */
++ struct videobuf_buffer vb;
++
+ struct list_head frame;
+- unsigned long vma_use_count;
+ int top_field;
+- int fieldbytesused;
++ int receiving;
++};
++
++struct em28xx_dmaqueue {
++ struct list_head active;
++ struct list_head queued;
++
++ wait_queue_head_t wq;
++
++ /* Counters to control buffer fill */
++ int pos;
+ };
+
+ /* io methods */
+@@ -152,6 +227,12 @@ enum em28xx_decoder {
+ EM28XX_SAA7114
+ };
+
++struct em28xx_reg_seq {
++ int reg;
++ unsigned char val, mask;
++ int sleep;
++};
++
+ struct em28xx_board {
+ char *name;
+ int vchannels;
+@@ -165,8 +246,7 @@ struct em28xx_board {
+ unsigned int mts_firmware:1;
+ unsigned int has_12mhz_i2s:1;
+ unsigned int max_range_640_480:1;
+-
+- unsigned int analog_gpio;
++ unsigned int has_dvb:1;
+
+ enum em28xx_decoder decoder;
+
+@@ -199,7 +279,10 @@ enum em28xx_dev_state {
+ #define EM28XX_NUM_AUDIO_PACKETS 64
+ #define EM28XX_AUDIO_MAX_PACKET_SIZE 196 /* static value */
+ #define EM28XX_CAPTURE_STREAM_EN 1
++
++/* em28xx extensions */
+ #define EM28XX_AUDIO 0x10
++#define EM28XX_DVB 0x20
+
+ struct em28xx_audio {
+ char name[50];
+@@ -217,13 +300,24 @@ struct em28xx_audio {
+ spinlock_t slock;
+ };
+
++struct em28xx;
++
++struct em28xx_fh {
++ struct em28xx *dev;
++ unsigned int stream_on:1; /* Locks streams */
++ int radio;
++
++ struct videobuf_queue vb_vidq;
++
++ enum v4l2_buf_type type;
++};
++
+ /* main device struct */
+ struct em28xx {
+ /* generic device properties */
+ char name[30]; /* name (including minor) of the device */
+ int model; /* index in the device_data struct */
+ int devno; /* marks the number of this device */
+- unsigned int analog_gpio;
+ unsigned int is_em2800:1;
+ unsigned int has_msp34xx:1;
+ unsigned int has_tda9887:1;
+@@ -231,6 +325,16 @@ struct em28xx {
+ unsigned int has_audio_class:1;
+ unsigned int has_12mhz_i2s:1;
+ unsigned int max_range_640_480:1;
++ unsigned int has_dvb:1;
++
++ /* Some older em28xx chips needs a waiting time after writing */
++ unsigned int wait_after_write;
++
++ /* GPIO sequences for analog and digital mode */
++ struct em28xx_reg_seq *analog_gpio, *digital_gpio;
++
++ /* GPIO sequences for tuner callbacks */
++ struct em28xx_reg_seq *tun_analog_gpio, *tun_digital_gpio;
+
+ int video_inputs; /* number of video inputs */
+ struct list_head devlist;
+@@ -255,36 +359,28 @@ struct em28xx {
+ int mute;
+ int volume;
+ /* frame properties */
+- struct em28xx_frame_t frame[EM28XX_NUM_FRAMES]; /* list of frames */
+- int num_frames; /* number of frames currently in use */
+- unsigned int frame_count; /* total number of transfered frames */
+- struct em28xx_frame_t *frame_current; /* the frame that is being filled */
+ int width; /* current frame width */
+ int height; /* current frame height */
+- int frame_size; /* current frame size */
+- int field_size; /* current field size */
+- int bytesperline;
+ int hscale; /* horizontal scale factor (see datasheet) */
+ int vscale; /* vertical scale factor (see datasheet) */
+ int interlaced; /* 1=interlace fileds, 0=just top fileds */
+- int type;
+ unsigned int video_bytesread; /* Number of bytes read */
+
+ unsigned long hash; /* eeprom hash - for boards with generic ID */
+- unsigned long i2c_hash; /* i2c devicelist hash - for boards with generic ID */
++ unsigned long i2c_hash; /* i2c devicelist hash -
++ for boards with generic ID */
+
+ struct em28xx_audio *adev;
+
+ /* states */
+ enum em28xx_dev_state state;
+- enum em28xx_stream_state stream;
+ enum em28xx_io_method io;
+
+ struct work_struct request_module_wk;
+
+ /* locks */
+ struct mutex lock;
+- spinlock_t queue_lock;
++ /* spinlock_t queue_lock; */
+ struct list_head inqueue, outqueue;
+ wait_queue_head_t open, wait_frame, wait_stream;
+ struct video_device *vbi_dev;
+@@ -292,6 +388,11 @@ struct em28xx {
+
+ unsigned char eedata[256];
+
++ /* Isoc control struct */
++ struct em28xx_dmaqueue vidq;
++ struct em28xx_usb_isoc_ctl isoc_ctl;
++ spinlock_t slock;
++
+ /* usb transfer */
+ struct usb_device *udev; /* the usb device */
+ int alt; /* alternate */
+@@ -301,20 +402,21 @@ struct em28xx {
+ struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */
+ char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc transfer */
+ /* helper funcs that call usb_control_msg */
+- int (*em28xx_write_regs) (struct em28xx * dev, u16 reg, char *buf,
+- int len);
+- int (*em28xx_read_reg) (struct em28xx * dev, u16 reg);
+- int (*em28xx_read_reg_req_len) (struct em28xx * dev, u8 req, u16 reg,
++ int (*em28xx_write_regs) (struct em28xx *dev, u16 reg,
+ char *buf, int len);
+- int (*em28xx_write_regs_req) (struct em28xx * dev, u8 req, u16 reg,
++ int (*em28xx_read_reg) (struct em28xx *dev, u16 reg);
++ int (*em28xx_read_reg_req_len) (struct em28xx *dev, u8 req, u16 reg,
++ char *buf, int len);
++ int (*em28xx_write_regs_req) (struct em28xx *dev, u8 req, u16 reg,
+ char *buf, int len);
+- int (*em28xx_read_reg_req) (struct em28xx * dev, u8 req, u16 reg);
+-};
++ int (*em28xx_read_reg_req) (struct em28xx *dev, u8 req, u16 reg);
+
+-struct em28xx_fh {
+- struct em28xx *dev;
+- unsigned int stream_on:1; /* Locks streams */
+- int radio;
++ enum em28xx_mode mode;
++
++ /* Caches GPO and GPIO registers */
++ unsigned char reg_gpo, reg_gpio;
++
++ struct em28xx_dvb *dvb;
+ };
+
+ struct em28xx_ops {
+@@ -351,22 +453,27 @@ int em28xx_colorlevels_set_default(struct em28xx *dev);
+ int em28xx_capture_start(struct em28xx *dev, int start);
+ int em28xx_outfmt_set_yuv422(struct em28xx *dev);
+ int em28xx_resolution_set(struct em28xx *dev);
+-int em28xx_init_isoc(struct em28xx *dev);
+-void em28xx_uninit_isoc(struct em28xx *dev);
+ int em28xx_set_alternate(struct em28xx *dev);
++int em28xx_init_isoc(struct em28xx *dev, int max_packets,
++ int num_bufs, int max_pkt_size,
++ int (*isoc_copy) (struct em28xx *dev, struct urb *urb));
++void em28xx_uninit_isoc(struct em28xx *dev);
++int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode);
++int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio);
+
+ /* Provided by em28xx-video.c */
+ int em28xx_register_extension(struct em28xx_ops *dev);
+ void em28xx_unregister_extension(struct em28xx_ops *dev);
+
+ /* Provided by em28xx-cards.c */
+-extern int em2800_variant_detect(struct usb_device* udev,int model);
++extern int em2800_variant_detect(struct usb_device *udev, int model);
+ extern void em28xx_pre_card_setup(struct em28xx *dev);
+ extern void em28xx_card_setup(struct em28xx *dev);
+ extern struct em28xx_board em28xx_boards[];
+ extern struct usb_device_id em28xx_id_table[];
+ extern const unsigned int em28xx_bcount;
+ void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir);
++int em28xx_tuner_callback(void *ptr, int command, int arg);
+
+ /* Provided by em28xx-input.c */
+ /* TODO: Check if the standard get_key handlers on ir-common can be used */
+@@ -375,71 +482,6 @@ int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
+ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
+ u32 *ir_raw);
+
+-/* em2800 registers */
+-#define EM2800_AUDIOSRC_REG 0x08
+-
+-/* em28xx registers */
+-#define I2C_CLK_REG 0x06
+-#define CHIPID_REG 0x0a
+-#define USBSUSP_REG 0x0c /* */
+-
+-#define AUDIOSRC_REG 0x0e
+-#define XCLK_REG 0x0f
+-
+-#define VINMODE_REG 0x10
+-#define VINCTRL_REG 0x11
+-#define VINENABLE_REG 0x12 /* */
+-
+-#define GAMMA_REG 0x14
+-#define RGAIN_REG 0x15
+-#define GGAIN_REG 0x16
+-#define BGAIN_REG 0x17
+-#define ROFFSET_REG 0x18
+-#define GOFFSET_REG 0x19
+-#define BOFFSET_REG 0x1a
+-
+-#define OFLOW_REG 0x1b
+-#define HSTART_REG 0x1c
+-#define VSTART_REG 0x1d
+-#define CWIDTH_REG 0x1e
+-#define CHEIGHT_REG 0x1f
+-
+-#define YGAIN_REG 0x20
+-#define YOFFSET_REG 0x21
+-#define UVGAIN_REG 0x22
+-#define UOFFSET_REG 0x23
+-#define VOFFSET_REG 0x24
+-#define SHARPNESS_REG 0x25
+-
+-#define COMPR_REG 0x26
+-#define OUTFMT_REG 0x27
+-
+-#define XMIN_REG 0x28
+-#define XMAX_REG 0x29
+-#define YMIN_REG 0x2a
+-#define YMAX_REG 0x2b
+-
+-#define HSCALELOW_REG 0x30
+-#define HSCALEHIGH_REG 0x31
+-#define VSCALELOW_REG 0x32
+-#define VSCALEHIGH_REG 0x33
+-
+-#define AC97LSB_REG 0x40
+-#define AC97MSB_REG 0x41
+-#define AC97ADDR_REG 0x42
+-#define AC97BUSY_REG 0x43
+-
+-/* em202 registers */
+-#define MASTER_AC97 0x02
+-#define LINE_IN_AC97 0x10
+-#define VIDEO_AC97 0x14
+-
+-/* register settings */
+-#define EM2800_AUDIO_SRC_TUNER 0x0d
+-#define EM2800_AUDIO_SRC_LINE 0x0c
+-#define EM28XX_AUDIO_SRC_TUNER 0xc0
+-#define EM28XX_AUDIO_SRC_LINE 0x80
+-
+ /* printk macros */
+
+ #define em28xx_err(fmt, arg...) do {\
+@@ -456,80 +498,80 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
+ printk(KERN_WARNING "%s: "fmt,\
+ dev->name , ##arg); } while (0)
+
+-inline static int em28xx_compression_disable(struct em28xx *dev)
++static inline int em28xx_compression_disable(struct em28xx *dev)
+ {
+ /* side effect of disabling scaler and mixer */
+- return em28xx_write_regs(dev, COMPR_REG, "\x00", 1);
++ return em28xx_write_regs(dev, EM28XX_R26_COMPR, "\x00", 1);
+ }
+
+-inline static int em28xx_contrast_get(struct em28xx *dev)
++static inline int em28xx_contrast_get(struct em28xx *dev)
+ {
+- return em28xx_read_reg(dev, YGAIN_REG) & 0x1f;
++ return em28xx_read_reg(dev, EM28XX_R20_YGAIN) & 0x1f;
+ }
+
+-inline static int em28xx_brightness_get(struct em28xx *dev)
++static inline int em28xx_brightness_get(struct em28xx *dev)
+ {
+- return em28xx_read_reg(dev, YOFFSET_REG);
++ return em28xx_read_reg(dev, EM28XX_R21_YOFFSET);
+ }
+
+-inline static int em28xx_saturation_get(struct em28xx *dev)
++static inline int em28xx_saturation_get(struct em28xx *dev)
+ {
+- return em28xx_read_reg(dev, UVGAIN_REG) & 0x1f;
++ return em28xx_read_reg(dev, EM28XX_R22_UVGAIN) & 0x1f;
+ }
+
+-inline static int em28xx_u_balance_get(struct em28xx *dev)
++static inline int em28xx_u_balance_get(struct em28xx *dev)
+ {
+- return em28xx_read_reg(dev, UOFFSET_REG);
++ return em28xx_read_reg(dev, EM28XX_R23_UOFFSET);
+ }
+
+-inline static int em28xx_v_balance_get(struct em28xx *dev)
++static inline int em28xx_v_balance_get(struct em28xx *dev)
+ {
+- return em28xx_read_reg(dev, VOFFSET_REG);
++ return em28xx_read_reg(dev, EM28XX_R24_VOFFSET);
+ }
+
+-inline static int em28xx_gamma_get(struct em28xx *dev)
++static inline int em28xx_gamma_get(struct em28xx *dev)
+ {
+- return em28xx_read_reg(dev, GAMMA_REG) & 0x3f;
++ return em28xx_read_reg(dev, EM28XX_R14_GAMMA) & 0x3f;
+ }
+
+-inline static int em28xx_contrast_set(struct em28xx *dev, s32 val)
++static inline int em28xx_contrast_set(struct em28xx *dev, s32 val)
+ {
+ u8 tmp = (u8) val;
+- return em28xx_write_regs(dev, YGAIN_REG, &tmp, 1);
++ return em28xx_write_regs(dev, EM28XX_R20_YGAIN, &tmp, 1);
+ }
+
+-inline static int em28xx_brightness_set(struct em28xx *dev, s32 val)
++static inline int em28xx_brightness_set(struct em28xx *dev, s32 val)
+ {
+ u8 tmp = (u8) val;
+- return em28xx_write_regs(dev, YOFFSET_REG, &tmp, 1);
++ return em28xx_write_regs(dev, EM28XX_R21_YOFFSET, &tmp, 1);
+ }
+
+-inline static int em28xx_saturation_set(struct em28xx *dev, s32 val)
++static inline int em28xx_saturation_set(struct em28xx *dev, s32 val)
+ {
+ u8 tmp = (u8) val;
+- return em28xx_write_regs(dev, UVGAIN_REG, &tmp, 1);
++ return em28xx_write_regs(dev, EM28XX_R22_UVGAIN, &tmp, 1);
+ }
+
+-inline static int em28xx_u_balance_set(struct em28xx *dev, s32 val)
++static inline int em28xx_u_balance_set(struct em28xx *dev, s32 val)
+ {
+ u8 tmp = (u8) val;
+- return em28xx_write_regs(dev, UOFFSET_REG, &tmp, 1);
++ return em28xx_write_regs(dev, EM28XX_R23_UOFFSET, &tmp, 1);
+ }
+
+-inline static int em28xx_v_balance_set(struct em28xx *dev, s32 val)
++static inline int em28xx_v_balance_set(struct em28xx *dev, s32 val)
+ {
+ u8 tmp = (u8) val;
+- return em28xx_write_regs(dev, VOFFSET_REG, &tmp, 1);
++ return em28xx_write_regs(dev, EM28XX_R24_VOFFSET, &tmp, 1);
+ }
+
+-inline static int em28xx_gamma_set(struct em28xx *dev, s32 val)
++static inline int em28xx_gamma_set(struct em28xx *dev, s32 val)
+ {
+ u8 tmp = (u8) val;
+- return em28xx_write_regs(dev, GAMMA_REG, &tmp, 1);
++ return em28xx_write_regs(dev, EM28XX_R14_GAMMA, &tmp, 1);
+ }
+
+ /*FIXME: maxw should be dependent of alt mode */
+-inline static unsigned int norm_maxw(struct em28xx *dev)
++static inline unsigned int norm_maxw(struct em28xx *dev)
+ {
+ if (dev->max_range_640_480)
+ return 640;
+@@ -537,7 +579,7 @@ inline static unsigned int norm_maxw(struct em28xx *dev)
+ return 720;
+ }
+
+-inline static unsigned int norm_maxh(struct em28xx *dev)
++static inline unsigned int norm_maxh(struct em28xx *dev)
+ {
+ if (dev->max_range_640_480)
+ return 480;
+diff --git a/drivers/media/video/et61x251/et61x251.h b/drivers/media/video/et61x251/et61x251.h
+index 02c741d..cc77d14 100644
+--- a/drivers/media/video/et61x251/et61x251.h
++++ b/drivers/media/video/et61x251/et61x251.h
+@@ -199,7 +199,7 @@ do { \
+ dev_info(&cam->usbdev->dev, fmt "\n", ## args); \
+ else if ((level) >= 3) \
+ dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", \
+- __FILE__, __FUNCTION__, __LINE__ , ## args); \
++ __FILE__, __func__, __LINE__ , ## args); \
+ } \
+ } while (0)
+ # define KDBG(level, fmt, args...) \
+@@ -209,7 +209,7 @@ do { \
+ pr_info("et61x251: " fmt "\n", ## args); \
+ else if ((level) == 3) \
+ pr_debug("sn9c102: [%s:%s:%d] " fmt "\n", __FILE__, \
+- __FUNCTION__, __LINE__ , ## args); \
++ __func__, __LINE__ , ## args); \
+ } \
+ } while (0)
+ # define V4LDBG(level, name, cmd) \
+@@ -225,7 +225,7 @@ do { \
+
+ #undef PDBG
+ #define PDBG(fmt, args...) \
+-dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__, \
++dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__, \
+ __LINE__ , ## args)
+
+ #undef PDBGG
+diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c
+index 06b6a3a..5e749c5 100644
+--- a/drivers/media/video/et61x251/et61x251_core.c
++++ b/drivers/media/video/et61x251/et61x251_core.c
+@@ -2523,7 +2523,9 @@ static const struct file_operations et61x251_fops = {
+ .open = et61x251_open,
+ .release = et61x251_release,
+ .ioctl = et61x251_ioctl,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .read = et61x251_read,
+ .poll = et61x251_poll,
+ .mmap = et61x251_mmap,
+@@ -2538,7 +2540,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
+ {
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct et61x251_device* cam;
+- static unsigned int dev_nr = 0;
++ static unsigned int dev_nr;
+ unsigned int i;
+ int err = 0;
+
+diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c
+index c7fed34..352f84d 100644
+--- a/drivers/media/video/hexium_gemini.c
++++ b/drivers/media/video/hexium_gemini.c
+@@ -25,12 +25,12 @@
+
+ #include <media/saa7146_vv.h>
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "debug verbosity");
+
+ /* global variables */
+-static int hexium_num = 0;
++static int hexium_num;
+
+ #define HEXIUM_GEMINI 4
+ #define HEXIUM_GEMINI_DUAL 5
+diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c
+index 137c473..8d3c148 100644
+--- a/drivers/media/video/hexium_orion.c
++++ b/drivers/media/video/hexium_orion.c
+@@ -25,12 +25,12 @@
+
+ #include <media/saa7146_vv.h>
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "debug verbosity");
+
+ /* global variables */
+-static int hexium_num = 0;
++static int hexium_num;
+
+ #define HEXIUM_HV_PCI6_ORION 1
+ #define HEXIUM_ORION_1SVHS_3BNC 2
+diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
+index 9851987..7b65f5e 100644
+--- a/drivers/media/video/ir-kbd-i2c.c
++++ b/drivers/media/video/ir-kbd-i2c.c
+@@ -40,7 +40,6 @@
+ #include <linux/i2c.h>
+ #include <linux/i2c-id.h>
+ #include <linux/workqueue.h>
+-#include <asm/semaphore.h>
+
+ #include <media/ir-common.h>
+ #include <media/ir-kbd-i2c.h>
+@@ -51,7 +50,7 @@
+ static int debug;
+ module_param(debug, int, 0644); /* debug level (0,1,2) */
+
+-static int hauppauge = 0;
++static int hauppauge;
+ module_param(hauppauge, int, 0644); /* Choose Hauppauge remote */
+ MODULE_PARM_DESC(hauppauge, "Specify Hauppauge remote: 0=black, 1=grey (defaults to 0)");
+
+@@ -154,7 +153,7 @@ static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+ }
+
+ if(buf[0] !=0 || buf[1] !=0 || buf[2] !=0 || buf[3] != 0)
+- dprintk(2, "%s: 0x%2x 0x%2x 0x%2x 0x%2x\n", __FUNCTION__,
++ dprintk(2, "%s: 0x%2x 0x%2x 0x%2x 0x%2x\n", __func__,
+ buf[0], buf[1], buf[2], buf[3]);
+
+ /* no key pressed or signal from other ir remote */
+@@ -509,10 +508,13 @@ static int ir_probe(struct i2c_adapter *adap)
+ static const int probe_em28XX[] = { 0x30, 0x47, -1 };
+ static const int probe_cx88[] = { 0x18, 0x6b, 0x71, -1 };
+ static const int probe_cx23885[] = { 0x6b, -1 };
+- const int *probe = NULL;
+- struct i2c_client c;
+- unsigned char buf;
+- int i,rc;
++ const int *probe;
++ struct i2c_msg msg = {
++ .flags = I2C_M_RD,
++ .len = 0,
++ .buf = NULL,
++ };
++ int i, rc;
+
+ switch (adap->id) {
+ case I2C_HW_B_BT848:
+@@ -533,20 +535,18 @@ static int ir_probe(struct i2c_adapter *adap)
+ case I2C_HW_B_CX23885:
+ probe = probe_cx23885;
+ break;
+- }
+- if (NULL == probe)
++ default:
+ return 0;
++ }
+
+- memset(&c,0,sizeof(c));
+- c.adapter = adap;
+ for (i = 0; -1 != probe[i]; i++) {
+- c.addr = probe[i];
+- rc = i2c_master_recv(&c,&buf,0);
++ msg.addr = probe[i];
++ rc = i2c_transfer(adap, &msg, 1);
+ dprintk(1,"probe 0x%02x @ %s: %s\n",
+ probe[i], adap->name,
+- (0 == rc) ? "yes" : "no");
+- if (0 == rc) {
+- ir_attach(adap,probe[i],0,0);
++ (1 == rc) ? "yes" : "no");
++ if (1 == rc) {
++ ir_attach(adap, probe[i], 0, 0);
+ break;
+ }
+ }
+diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig
+index 270906f..b617170 100644
+--- a/drivers/media/video/ivtv/Kconfig
++++ b/drivers/media/video/ivtv/Kconfig
+@@ -10,6 +10,7 @@ config VIDEO_IVTV
+ select VIDEO_CX25840
+ select VIDEO_MSP3400
+ select VIDEO_SAA711X
++ select VIDEO_SAA717X
+ select VIDEO_SAA7127
+ select VIDEO_TVAUDIO
+ select VIDEO_CS53L32A
+diff --git a/drivers/media/video/ivtv/ivtv-cards.c b/drivers/media/video/ivtv/ivtv-cards.c
+index f23c6b8..e908649 100644
+--- a/drivers/media/video/ivtv/ivtv-cards.c
++++ b/drivers/media/video/ivtv/ivtv-cards.c
+@@ -416,11 +416,10 @@ static const struct ivtv_card ivtv_card_avc2410 = {
+ on the country/region setting of the user to decide which tuner
+ is available. */
+ .tuners = {
+- /* This tuner has been verified for the AVC2410 */
+ { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+- /* This is a good guess, but I'm not totally sure this is
+- the correct tuner for NTSC. */
+- { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
++ { .std = V4L2_STD_ALL - V4L2_STD_NTSC_M_JP,
++ .tuner = TUNER_PHILIPS_FM1236_MK3 },
++ { .std = V4L2_STD_NTSC_M_JP, .tuner = TUNER_PHILIPS_FQ1286 },
+ },
+ .pci_list = ivtv_pci_avc2410,
+ .i2c = &ivtv_i2c_std,
+diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h
+index 191aafd..9186fa2 100644
+--- a/drivers/media/video/ivtv/ivtv-cards.h
++++ b/drivers/media/video/ivtv/ivtv-cards.h
+@@ -119,7 +119,7 @@
+
+ #define IVTV_CARD_MAX_VIDEO_INPUTS 6
+ #define IVTV_CARD_MAX_AUDIO_INPUTS 3
+-#define IVTV_CARD_MAX_TUNERS 2
++#define IVTV_CARD_MAX_TUNERS 3
+
+ /* SAA71XX HW inputs */
+ #define IVTV_SAA71XX_COMPOSITE0 0
+diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
+index 948ca35..065df53 100644
+--- a/drivers/media/video/ivtv/ivtv-driver.c
++++ b/drivers/media/video/ivtv/ivtv-driver.c
+@@ -101,7 +101,7 @@ static int radio[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
+ static unsigned int cardtype_c = 1;
+ static unsigned int tuner_c = 1;
+ static unsigned int radio_c = 1;
+-static char pal[] = "--";
++static char pal[] = "---";
+ static char secam[] = "--";
+ static char ntsc[] = "-";
+
+@@ -126,12 +126,13 @@ static int dec_mpg_buffers = IVTV_DEFAULT_DEC_MPG_BUFFERS;
+ static int dec_yuv_buffers = IVTV_DEFAULT_DEC_YUV_BUFFERS;
+ static int dec_vbi_buffers = IVTV_DEFAULT_DEC_VBI_BUFFERS;
+
+-static int ivtv_yuv_mode = 0;
+-static int ivtv_yuv_threshold=-1;
++static int ivtv_yuv_mode;
++static int ivtv_yuv_threshold = -1;
+ static int ivtv_pci_latency = 1;
+
+-int ivtv_debug = 0;
++int ivtv_debug;
+
++static int tunertype = -1;
+ static int newi2c = -1;
+
+ module_param_array(tuner, int, &tuner_c, 0644);
+@@ -154,6 +155,7 @@ module_param(dec_mpg_buffers, int, 0644);
+ module_param(dec_yuv_buffers, int, 0644);
+ module_param(dec_vbi_buffers, int, 0644);
+
++module_param(tunertype, int, 0644);
+ module_param(newi2c, int, 0644);
+
+ MODULE_PARM_DESC(tuner, "Tuner type selection,\n"
+@@ -190,9 +192,14 @@ MODULE_PARM_DESC(cardtype,
+ "\t\t\t24 = AverMedia EZMaker PCI Deluxe\n"
+ "\t\t\t 0 = Autodetect (default)\n"
+ "\t\t\t-1 = Ignore this card\n\t\t");
+-MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60");
+-MODULE_PARM_DESC(secam, "Set SECAM standard: B, G, H, D, K, L, LC");
+-MODULE_PARM_DESC(ntsc, "Set NTSC standard: M, J, K");
++MODULE_PARM_DESC(pal, "Set PAL standard: BGH, DK, I, M, N, Nc, 60");
++MODULE_PARM_DESC(secam, "Set SECAM standard: BGH, DK, L, LC");
++MODULE_PARM_DESC(ntsc, "Set NTSC standard: M, J (Japan), K (South Korea)");
++MODULE_PARM_DESC(tunertype,
++ "Specify tuner type:\n"
++ "\t\t\t 0 = tuner for PAL-B/G/H/D/K/I, SECAM-B/G/H/D/K/L/Lc\n"
++ "\t\t\t 1 = tuner for NTSC-M/J/K, PAL-M/N/Nc\n"
++ "\t\t\t-1 = Autodetect (default)\n");
+ MODULE_PARM_DESC(debug,
+ "Debug level (bitmask). Default: 0\n"
+ "\t\t\t 1/0x0001: warning\n"
+@@ -490,30 +497,35 @@ static v4l2_std_id ivtv_parse_std(struct ivtv *itv)
+ {
+ switch (pal[0]) {
+ case '6':
++ tunertype = 0;
+ return V4L2_STD_PAL_60;
+ case 'b':
+ case 'B':
+ case 'g':
+ case 'G':
+- return V4L2_STD_PAL_BG;
+ case 'h':
+ case 'H':
+- return V4L2_STD_PAL_H;
++ tunertype = 0;
++ return V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
+ case 'n':
+ case 'N':
++ tunertype = 1;
+ if (pal[1] == 'c' || pal[1] == 'C')
+ return V4L2_STD_PAL_Nc;
+ return V4L2_STD_PAL_N;
+ case 'i':
+ case 'I':
++ tunertype = 0;
+ return V4L2_STD_PAL_I;
+ case 'd':
+ case 'D':
+ case 'k':
+ case 'K':
++ tunertype = 0;
+ return V4L2_STD_PAL_DK;
+ case 'M':
+ case 'm':
++ tunertype = 1;
+ return V4L2_STD_PAL_M;
+ case '-':
+ break;
+@@ -529,14 +541,17 @@ static v4l2_std_id ivtv_parse_std(struct ivtv *itv)
+ case 'G':
+ case 'h':
+ case 'H':
++ tunertype = 0;
+ return V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
+ case 'd':
+ case 'D':
+ case 'k':
+ case 'K':
++ tunertype = 0;
+ return V4L2_STD_SECAM_DK;
+ case 'l':
+ case 'L':
++ tunertype = 0;
+ if (secam[1] == 'C' || secam[1] == 'c')
+ return V4L2_STD_SECAM_LC;
+ return V4L2_STD_SECAM_L;
+@@ -550,12 +565,15 @@ static v4l2_std_id ivtv_parse_std(struct ivtv *itv)
+ switch (ntsc[0]) {
+ case 'm':
+ case 'M':
++ tunertype = 1;
+ return V4L2_STD_NTSC_M;
+ case 'j':
+ case 'J':
++ tunertype = 1;
+ return V4L2_STD_NTSC_M_JP;
+ case 'k':
+ case 'K':
++ tunertype = 1;
+ return V4L2_STD_NTSC_M_KR;
+ case '-':
+ break;
+@@ -584,8 +602,13 @@ static void ivtv_process_options(struct ivtv *itv)
+ itv->options.tuner = tuner[itv->num];
+ itv->options.radio = radio[itv->num];
+ itv->options.newi2c = newi2c;
+-
++ if (tunertype < -1 || tunertype > 1) {
++ IVTV_WARN("Invalid tunertype argument, will autodetect instead\n");
++ tunertype = -1;
++ }
+ itv->std = ivtv_parse_std(itv);
++ if (itv->std == 0 && tunertype >= 0)
++ itv->std = tunertype ? V4L2_STD_MN : (V4L2_STD_ALL & ~V4L2_STD_MN);
+ itv->has_cx23415 = (itv->dev->device == PCI_DEVICE_ID_IVTV15);
+ chipname = itv->has_cx23415 ? "cx23415" : "cx23416";
+ if (itv->options.cardtype == -1) {
+@@ -711,6 +734,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
+ itv->yuv_info.lace_mode = ivtv_yuv_mode;
+ itv->yuv_info.lace_threshold = ivtv_yuv_threshold;
+ itv->yuv_info.max_frames_buffered = 3;
++ itv->yuv_info.track_osd = 1;
+ return 0;
+ }
+
+@@ -859,7 +883,9 @@ static void ivtv_load_and_init_modules(struct ivtv *itv)
+ #ifndef CONFIG_VIDEO_SAA7127
+ hw = ivtv_request_module(itv, hw, "saa7127", IVTV_HW_SAA7127);
+ #endif
++#ifndef CONFIG_VIDEO_SAA717X
+ hw = ivtv_request_module(itv, hw, "saa717x", IVTV_HW_SAA717X);
++#endif
+ #ifndef CONFIG_VIDEO_UPD64031A
+ hw = ivtv_request_module(itv, hw, "upd64031a", IVTV_HW_UPD64031A);
+ #endif
+diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h
+index 536140f..ba06e81 100644
+--- a/drivers/media/video/ivtv/ivtv-driver.h
++++ b/drivers/media/video/ivtv/ivtv-driver.h
+@@ -456,6 +456,8 @@ struct yuv_playback_info
+ int v_filter_2;
+ int h_filter;
+
++ u8 track_osd; /* Should yuv output track the OSD size & position */
++
+ u32 osd_x_offset;
+ u32 osd_y_offset;
+
+diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
+index 6fb96f1..a7640c4 100644
+--- a/drivers/media/video/ivtv/ivtv-fileops.c
++++ b/drivers/media/video/ivtv/ivtv-fileops.c
+@@ -219,7 +219,9 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block,
+ /* Process pending program info updates and pending VBI data */
+ ivtv_update_pgm_info(itv);
+
+- if (jiffies - itv->dualwatch_jiffies > msecs_to_jiffies(1000)) {
++ if (time_after(jiffies,
++ itv->dualwatch_jiffies +
++ msecs_to_jiffies(1000))) {
+ itv->dualwatch_jiffies = jiffies;
+ ivtv_dualwatch(itv);
+ }
+@@ -753,7 +755,7 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait)
+ IVTV_DEBUG_HI_FILE("Encoder poll\n");
+ poll_wait(filp, &s->waitq, wait);
+
+- if (eof || s->q_full.length)
++ if (eof || s->q_full.length || s->q_io.length)
+ return POLLIN | POLLRDNORM;
+ return 0;
+ }
+diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c
+index fa5ab1e..9824eaf 100644
+--- a/drivers/media/video/ivtv/ivtv-i2c.c
++++ b/drivers/media/video/ivtv/ivtv-i2c.c
+@@ -177,10 +177,16 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx)
+ }
+
+ if (id != I2C_DRIVERID_TUNER) {
+- c = i2c_new_device(&itv->i2c_adap, &info);
+- if (c->driver == NULL)
++ if (id == I2C_DRIVERID_UPD64031A ||
++ id == I2C_DRIVERID_UPD64083) {
++ unsigned short addrs[2] = { info.addr, I2C_CLIENT_END };
++
++ c = i2c_new_probed_device(&itv->i2c_adap, &info, addrs);
++ } else
++ c = i2c_new_device(&itv->i2c_adap, &info);
++ if (c && c->driver == NULL)
+ i2c_unregister_device(c);
+- else
++ else if (c)
+ itv->i2c_clients[i] = c;
+ return itv->i2c_clients[i] ? 0 : -ENODEV;
+ }
+diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
+index edef2a5..15cac18 100644
+--- a/drivers/media/video/ivtv/ivtv-ioctl.c
++++ b/drivers/media/video/ivtv/ivtv-ioctl.c
+@@ -712,6 +712,7 @@ static int ivtv_debug_ioctls(struct file *filp, unsigned int cmd, void *arg)
+ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg)
+ {
+ struct ivtv_open_id *id = NULL;
++ struct yuv_playback_info *yi = &itv->yuv_info;
+ u32 data[CX2341X_MBOX_MAX_DATA];
+ int streamtype = 0;
+
+@@ -741,7 +742,8 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+
+ memset(vcap, 0, sizeof(*vcap));
+ strcpy(vcap->driver, IVTV_DRIVER_NAME); /* driver name */
+- strcpy(vcap->card, itv->card_name); /* card type */
++ strncpy(vcap->card, itv->card_name,
++ sizeof(vcap->card)-1); /* card type */
+ strcpy(vcap->bus_info, pci_name(itv->dev)); /* bus info... */
+ vcap->version = IVTV_DRIVER_VERSION; /* version */
+ vcap->capabilities = itv->v4l2_cap; /* capabilities */
+@@ -827,8 +829,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+ case VIDIOC_CROPCAP: {
+ struct v4l2_cropcap *cropcap = arg;
+
+- if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+- cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
++ if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ return -EINVAL;
+ cropcap->bounds.top = cropcap->bounds.left = 0;
+ cropcap->bounds.width = 720;
+@@ -837,8 +838,14 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+ cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
+ cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
+ } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
+- cropcap->bounds.width = itv->yuv_info.osd_full_w;
+- cropcap->bounds.height = itv->yuv_info.osd_full_h;
++ if (yi->track_osd) {
++ cropcap->bounds.width = yi->osd_full_w;
++ cropcap->bounds.height = yi->osd_full_h;
++ } else {
++ cropcap->bounds.width = 720;
++ cropcap->bounds.height =
++ itv->is_out_50hz ? 576 : 480;
++ }
+ cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
+ cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
+ } else {
+@@ -856,7 +863,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+ if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+ (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
+ if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
+- itv->yuv_info.main_rect = crop->c;
++ yi->main_rect = crop->c;
+ return 0;
+ } else {
+ if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
+@@ -867,9 +874,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+ }
+ return -EINVAL;
+ }
+- if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+- return -EINVAL;
+- return itv->video_dec_func(itv, VIDIOC_S_CROP, arg);
++ return -EINVAL;
+ }
+
+ case VIDIOC_G_CROP: {
+@@ -878,14 +883,12 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+ if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+ (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
+ if (streamtype == IVTV_DEC_STREAM_TYPE_YUV)
+- crop->c = itv->yuv_info.main_rect;
++ crop->c = yi->main_rect;
+ else
+ crop->c = itv->main_rect;
+ return 0;
+ }
+- if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+- return -EINVAL;
+- return itv->video_dec_func(itv, VIDIOC_G_CROP, arg);
++ return -EINVAL;
+ }
+
+ case VIDIOC_ENUM_FMT: {
+@@ -1070,11 +1073,10 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+ itv->main_rect.height = itv->params.height;
+ ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
+ 720, itv->main_rect.height, 0, 0);
+- itv->yuv_info.main_rect = itv->main_rect;
++ yi->main_rect = itv->main_rect;
+ if (!itv->osd_info) {
+- itv->yuv_info.osd_full_w = 720;
+- itv->yuv_info.osd_full_h =
+- itv->is_out_50hz ? 576 : 480;
++ yi->osd_full_w = 720;
++ yi->osd_full_h = itv->is_out_50hz ? 576 : 480;
+ }
+ }
+ break;
+@@ -1272,6 +1274,8 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+ else
+ fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
+ }
++ if (yi->track_osd)
++ fb->flags |= V4L2_FBUF_FLAG_OVERLAY;
+ break;
+ }
+
+@@ -1285,6 +1289,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
+ (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0;
+ itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
+ ivtv_set_osd_alpha(itv);
++ yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0;
+ break;
+ }
+
+@@ -1628,6 +1633,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
+ if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
+ printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
+ v4l_printk_ioctl(cmd);
++ printk("\n");
+ }
+ return ivtv_debug_ioctls(filp, cmd, arg);
+
+@@ -1671,6 +1677,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
+ if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
+ printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
+ v4l_printk_ioctl(cmd);
++ printk("\n");
+ }
+ return ivtv_v4l2_ioctls(itv, filp, cmd, arg);
+
+@@ -1684,6 +1691,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
+ if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
+ printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
+ v4l_printk_ioctl(cmd);
++ printk("\n");
+ }
+ return ivtv_control_ioctls(itv, cmd, arg);
+
+diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c
+index 65604dd..a329c46 100644
+--- a/drivers/media/video/ivtv/ivtv-irq.c
++++ b/drivers/media/video/ivtv/ivtv-irq.c
+@@ -384,6 +384,8 @@ static void ivtv_dma_enc_start_xfer(struct ivtv_stream *s)
+ ivtv_stream_sync_for_device(s);
+ write_reg(s->sg_handle, IVTV_REG_ENCDMAADDR);
+ write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER);
++ itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
++ add_timer(&itv->dma_timer);
+ }
+
+ static void ivtv_dma_dec_start_xfer(struct ivtv_stream *s)
+@@ -398,6 +400,8 @@ static void ivtv_dma_dec_start_xfer(struct ivtv_stream *s)
+ ivtv_stream_sync_for_device(s);
+ write_reg(s->sg_handle, IVTV_REG_DECDMAADDR);
+ write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER);
++ itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
++ add_timer(&itv->dma_timer);
+ }
+
+ /* start the encoder DMA */
+@@ -459,8 +463,6 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s)
+ ivtv_dma_enc_start_xfer(s);
+ set_bit(IVTV_F_I_DMA, &itv->i_flags);
+ itv->cur_dma_stream = s->type;
+- itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
+- add_timer(&itv->dma_timer);
+ }
+ }
+
+@@ -481,8 +483,6 @@ static void ivtv_dma_dec_start(struct ivtv_stream *s)
+ ivtv_dma_dec_start_xfer(s);
+ set_bit(IVTV_F_I_DMA, &itv->i_flags);
+ itv->cur_dma_stream = s->type;
+- itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
+- add_timer(&itv->dma_timer);
+ }
+
+ static void ivtv_irq_dma_read(struct ivtv *itv)
+@@ -492,10 +492,11 @@ static void ivtv_irq_dma_read(struct ivtv *itv)
+ int hw_stream_type = 0;
+
+ IVTV_DEBUG_HI_IRQ("DEC DMA READ\n");
+- if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && itv->cur_dma_stream < 0) {
+- del_timer(&itv->dma_timer);
++
++ del_timer(&itv->dma_timer);
++
++ if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && itv->cur_dma_stream < 0)
+ return;
+- }
+
+ if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
+ s = &itv->streams[itv->cur_dma_stream];
+@@ -543,7 +544,6 @@ static void ivtv_irq_dma_read(struct ivtv *itv)
+ }
+ wake_up(&s->waitq);
+ }
+- del_timer(&itv->dma_timer);
+ clear_bit(IVTV_F_I_UDMA, &itv->i_flags);
+ clear_bit(IVTV_F_I_DMA, &itv->i_flags);
+ itv->cur_dma_stream = -1;
+@@ -557,10 +557,12 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv)
+
+ ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, data);
+ IVTV_DEBUG_HI_IRQ("ENC DMA COMPLETE %x %d (%d)\n", data[0], data[1], itv->cur_dma_stream);
+- if (itv->cur_dma_stream < 0) {
+- del_timer(&itv->dma_timer);
++
++ del_timer(&itv->dma_timer);
++
++ if (itv->cur_dma_stream < 0)
+ return;
+- }
++
+ s = &itv->streams[itv->cur_dma_stream];
+ ivtv_stream_sync_for_cpu(s);
+
+@@ -585,7 +587,6 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv)
+ ivtv_dma_enc_start_xfer(s);
+ return;
+ }
+- del_timer(&itv->dma_timer);
+ clear_bit(IVTV_F_I_DMA, &itv->i_flags);
+ itv->cur_dma_stream = -1;
+ dma_post(s);
+diff --git a/drivers/media/video/ivtv/ivtv-mailbox.c b/drivers/media/video/ivtv/ivtv-mailbox.c
+index 13a6c37..1b5c0ac 100644
+--- a/drivers/media/video/ivtv/ivtv-mailbox.c
++++ b/drivers/media/video/ivtv/ivtv-mailbox.c
+@@ -177,7 +177,8 @@ static int get_mailbox(struct ivtv *itv, struct ivtv_mailbox_data *mbdata, int f
+
+ /* Sleep before a retry, if not atomic */
+ if (!(flags & API_NO_WAIT_MB)) {
+- if (jiffies - then > msecs_to_jiffies(10*retries))
++ if (time_after(jiffies,
++ then + msecs_to_jiffies(10*retries)))
+ break;
+ ivtv_msleep_timeout(10, 0);
+ }
+@@ -244,7 +245,9 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
+ data, then just return 0 as there is no need to issue this command again.
+ Just an optimization to prevent unnecessary use of mailboxes. */
+ if (itv->api_cache[cmd].last_jiffies &&
+- jiffies - itv->api_cache[cmd].last_jiffies < msecs_to_jiffies(1800000) &&
++ time_before(jiffies,
++ itv->api_cache[cmd].last_jiffies +
++ msecs_to_jiffies(1800000)) &&
+ !memcmp(data, itv->api_cache[cmd].data, sizeof(itv->api_cache[cmd].data))) {
+ itv->api_cache[cmd].last_jiffies = jiffies;
+ return 0;
+@@ -299,7 +302,7 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
+ }
+ }
+ while (!(readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE)) {
+- if (jiffies - then > api_timeout) {
++ if (time_after(jiffies, then + api_timeout)) {
+ IVTV_DEBUG_WARN("Could not get result (%s)\n", api_info[cmd].name);
+ /* reset the mailbox, but it is likely too late already */
+ write_sync(0, &mbox->flags);
+@@ -311,7 +314,7 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
+ else
+ ivtv_msleep_timeout(1, 0);
+ }
+- if (jiffies - then > msecs_to_jiffies(100))
++ if (time_after(jiffies, then + msecs_to_jiffies(100)))
+ IVTV_DEBUG_WARN("%s took %u jiffies\n",
+ api_info[cmd].name,
+ jiffies_to_msecs(jiffies - then));
+diff --git a/drivers/media/video/ivtv/ivtv-queue.c b/drivers/media/video/ivtv/ivtv-queue.c
+index 39a2167..3e1deec 100644
+--- a/drivers/media/video/ivtv/ivtv-queue.c
++++ b/drivers/media/video/ivtv/ivtv-queue.c
+@@ -51,7 +51,7 @@ void ivtv_queue_init(struct ivtv_queue *q)
+
+ void ivtv_enqueue(struct ivtv_stream *s, struct ivtv_buffer *buf, struct ivtv_queue *q)
+ {
+- unsigned long flags = 0;
++ unsigned long flags;
+
+ /* clear the buffer if it is going to be enqueued to the free queue */
+ if (q == &s->q_free) {
+@@ -71,7 +71,7 @@ void ivtv_enqueue(struct ivtv_stream *s, struct ivtv_buffer *buf, struct ivtv_qu
+ struct ivtv_buffer *ivtv_dequeue(struct ivtv_stream *s, struct ivtv_queue *q)
+ {
+ struct ivtv_buffer *buf = NULL;
+- unsigned long flags = 0;
++ unsigned long flags;
+
+ spin_lock_irqsave(&s->qlock, flags);
+ if (!list_empty(&q->list)) {
+diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
+index 24d98ec..4ab8d36 100644
+--- a/drivers/media/video/ivtv/ivtv-streams.c
++++ b/drivers/media/video/ivtv/ivtv-streams.c
+@@ -768,7 +768,8 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
+
+ /* wait 2s for EOS interrupt */
+ while (!test_bit(IVTV_F_I_EOS, &itv->i_flags) &&
+- jiffies < then + msecs_to_jiffies (2000)) {
++ time_before(jiffies,
++ then + msecs_to_jiffies(2000))) {
+ schedule_timeout(msecs_to_jiffies(10));
+ }
+
+diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c
+index 8518348..393d917 100644
+--- a/drivers/media/video/ivtv/ivtv-yuv.c
++++ b/drivers/media/video/ivtv/ivtv-yuv.c
+@@ -718,9 +718,11 @@ static u32 ivtv_yuv_window_setup(struct ivtv *itv, struct yuv_frame_info *f)
+ f->src_w -= (osd_scale * osd_crop) >> 16;
+ }
+
+- /* The OSD can be moved. Track to it */
+- f->dst_x += itv->yuv_info.osd_x_offset;
+- f->dst_y += itv->yuv_info.osd_y_offset;
++ if (itv->yuv_info.track_osd) {
++ /* The OSD can be moved. Track to it */
++ f->dst_x += itv->yuv_info.osd_x_offset;
++ f->dst_y += itv->yuv_info.osd_y_offset;
++ }
+
+ /* Width & height for both src & dst must be even.
+ Same for coordinates. */
+@@ -792,11 +794,19 @@ void ivtv_yuv_work_handler(struct ivtv *itv)
+ IVTV_DEBUG_YUV("Update yuv registers for frame %d\n", frame);
+ f = yi->new_frame_info[frame];
+
+- /* Update the osd pan info */
+- f.pan_x = yi->osd_x_pan;
+- f.pan_y = yi->osd_y_pan;
+- f.vis_w = yi->osd_vis_w;
+- f.vis_h = yi->osd_vis_h;
++ if (yi->track_osd) {
++ /* Snapshot the osd pan info */
++ f.pan_x = yi->osd_x_pan;
++ f.pan_y = yi->osd_y_pan;
++ f.vis_w = yi->osd_vis_w;
++ f.vis_h = yi->osd_vis_h;
++ } else {
++ /* Not tracking the osd, so assume full screen */
++ f.pan_x = 0;
++ f.pan_y = 0;
++ f.vis_w = 720;
++ f.vis_h = yi->decode_height;
++ }
+
+ /* Calculate the display window coordinates. Exit if nothing left */
+ if (!(yuv_update = ivtv_yuv_window_setup(itv, &f)))
+@@ -914,7 +924,7 @@ static void ivtv_yuv_init(struct ivtv *itv)
+ }
+
+ /* Get next available yuv buffer on PVR350 */
+-void ivtv_yuv_next_free(struct ivtv *itv)
++static void ivtv_yuv_next_free(struct ivtv *itv)
+ {
+ int draw, display;
+ struct yuv_playback_info *yi = &itv->yuv_info;
+@@ -937,7 +947,7 @@ void ivtv_yuv_next_free(struct ivtv *itv)
+ }
+
+ /* Set up frame according to ivtv_dma_frame parameters */
+-void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
++static void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
+ {
+ struct yuv_playback_info *yi = &itv->yuv_info;
+ u8 frame = yi->draw_frame;
+@@ -965,12 +975,6 @@ void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
+ /* Are we going to offset the Y plane */
+ nf->offset_y = (nf->tru_h + nf->src_x < 512 - 16) ? 1 : 0;
+
+- /* Snapshot the osd pan info */
+- nf->pan_x = yi->osd_x_pan;
+- nf->pan_y = yi->osd_y_pan;
+- nf->vis_w = yi->osd_vis_w;
+- nf->vis_h = yi->osd_vis_h;
+-
+ nf->update = 0;
+ nf->interlaced_y = 0;
+ nf->interlaced_uv = 0;
+@@ -1042,7 +1046,7 @@ void ivtv_yuv_frame_complete(struct ivtv *itv)
+ (itv->yuv_info.draw_frame + 1) % IVTV_YUV_BUFFERS);
+ }
+
+-int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
++static int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
+ {
+ DEFINE_WAIT(wait);
+ int rc = 0;
+diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
+index 3d51fa0..e7ccbc8 100644
+--- a/drivers/media/video/meye.c
++++ b/drivers/media/video/meye.c
+@@ -42,15 +42,10 @@
+ #include <linux/meye.h>
+
+ MODULE_AUTHOR("Stelian Pop <stelian at popies.net>");
+-MODULE_DESCRIPTION("v4l/v4l2 driver for the MotionEye camera");
++MODULE_DESCRIPTION("v4l2 driver for the MotionEye camera");
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION(MEYE_DRIVER_VERSION);
+
+-/* force usage of V4L1 API */
+-static int forcev4l1; /* = 0 */
+-module_param(forcev4l1, int, 0644);
+-MODULE_PARM_DESC(forcev4l1, "force use of V4L1 instead of V4L2");
+-
+ /* number of grab buffers */
+ static unsigned int gbuffers = 2;
+ module_param(gbuffers, int, 0444);
+@@ -789,7 +784,7 @@ static irqreturn_t meye_irq(int irq, void *dev_id)
+ {
+ u32 v;
+ int reqnr;
+- static int sequence = 0;
++ static int sequence;
+
+ v = mchip_read(MCHIP_MM_INTA);
+
+@@ -876,795 +871,735 @@ static int meye_release(struct inode *inode, struct file *file)
+ return 0;
+ }
+
+-static int meye_do_ioctl(struct inode *inode, struct file *file,
+- unsigned int cmd, void *arg)
++static int meyeioc_g_params(struct meye_params *p)
+ {
+- switch (cmd) {
++ *p = meye.params;
++ return 0;
++}
+
+- case VIDIOCGCAP: {
+- struct video_capability *b = arg;
+- strcpy(b->name,meye.video_dev->name);
+- b->type = VID_TYPE_CAPTURE;
+- b->channels = 1;
+- b->audios = 0;
+- b->maxwidth = 640;
+- b->maxheight = 480;
+- b->minwidth = 320;
+- b->minheight = 240;
+- break;
+- }
++static int meyeioc_s_params(struct meye_params *jp)
++{
++ if (jp->subsample > 1)
++ return -EINVAL;
+
+- case VIDIOCGCHAN: {
+- struct video_channel *v = arg;
+- v->flags = 0;
+- v->tuners = 0;
+- v->type = VIDEO_TYPE_CAMERA;
+- if (v->channel != 0)
+- return -EINVAL;
+- strcpy(v->name,"Camera");
+- break;
+- }
++ if (jp->quality > 10)
++ return -EINVAL;
+
+- case VIDIOCSCHAN: {
+- struct video_channel *v = arg;
+- if (v->channel != 0)
+- return -EINVAL;
+- break;
+- }
++ if (jp->sharpness > 63 || jp->agc > 63 || jp->picture > 63)
++ return -EINVAL;
+
+- case VIDIOCGPICT: {
+- struct video_picture *p = arg;
+- *p = meye.picture;
+- break;
+- }
++ if (jp->framerate > 31)
++ return -EINVAL;
+
+- case VIDIOCSPICT: {
+- struct video_picture *p = arg;
+- if (p->depth != 16)
+- return -EINVAL;
+- if (p->palette != VIDEO_PALETTE_YUV422 && p->palette != VIDEO_PALETTE_YUYV)
+- return -EINVAL;
+- mutex_lock(&meye.lock);
+- sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERABRIGHTNESS,
+- p->brightness >> 10);
+- sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAHUE,
+- p->hue >> 10);
+- sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACOLOR,
+- p->colour >> 10);
+- sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACONTRAST,
+- p->contrast >> 10);
+- meye.picture = *p;
+- mutex_unlock(&meye.lock);
+- break;
+- }
++ mutex_lock(&meye.lock);
+
+- case VIDIOCSYNC: {
+- int *i = arg;
+- int unused;
++ if (meye.params.subsample != jp->subsample ||
++ meye.params.quality != jp->quality)
++ mchip_hic_stop(); /* need restart */
++
++ meye.params = *jp;
++ sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS,
++ meye.params.sharpness);
++ sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC,
++ meye.params.agc);
++ sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE,
++ meye.params.picture);
++ mutex_unlock(&meye.lock);
+
+- if (*i < 0 || *i >= gbuffers)
+- return -EINVAL;
++ return 0;
++}
+
+- mutex_lock(&meye.lock);
++static int meyeioc_qbuf_capt(int *nb)
++{
++ if (!meye.grab_fbuffer)
++ return -EINVAL;
+
+- switch (meye.grab_buffer[*i].state) {
++ if (*nb >= gbuffers)
++ return -EINVAL;
+
+- case MEYE_BUF_UNUSED:
+- mutex_unlock(&meye.lock);
+- return -EINVAL;
+- case MEYE_BUF_USING:
+- if (file->f_flags & O_NONBLOCK) {
+- mutex_unlock(&meye.lock);
+- return -EAGAIN;
+- }
+- if (wait_event_interruptible(meye.proc_list,
+- (meye.grab_buffer[*i].state != MEYE_BUF_USING))) {
+- mutex_unlock(&meye.lock);
+- return -EINTR;
+- }
+- /* fall through */
+- case MEYE_BUF_DONE:
+- meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
+- kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int));
+- }
+- mutex_unlock(&meye.lock);
+- break;
++ if (*nb < 0) {
++ /* stop capture */
++ mchip_hic_stop();
++ return 0;
+ }
+
+- case VIDIOCMCAPTURE: {
+- struct video_mmap *vm = arg;
+- int restart = 0;
+-
+- if (vm->frame >= gbuffers || vm->frame < 0)
+- return -EINVAL;
+- if (vm->format != VIDEO_PALETTE_YUV422 && vm->format != VIDEO_PALETTE_YUYV)
+- return -EINVAL;
+- if (vm->height * vm->width * 2 > gbufsize)
+- return -EINVAL;
+- if (!meye.grab_fbuffer)
+- return -EINVAL;
+- if (meye.grab_buffer[vm->frame].state != MEYE_BUF_UNUSED)
+- return -EBUSY;
+-
+- mutex_lock(&meye.lock);
+- if (vm->width == 640 && vm->height == 480) {
+- if (meye.params.subsample) {
+- meye.params.subsample = 0;
+- restart = 1;
+- }
+- } else if (vm->width == 320 && vm->height == 240) {
+- if (!meye.params.subsample) {
+- meye.params.subsample = 1;
+- restart = 1;
+- }
+- } else {
+- mutex_unlock(&meye.lock);
+- return -EINVAL;
+- }
++ if (meye.grab_buffer[*nb].state != MEYE_BUF_UNUSED)
++ return -EBUSY;
+
+- if (restart || meye.mchip_mode != MCHIP_HIC_MODE_CONT_OUT)
+- mchip_continuous_start();
+- meye.grab_buffer[vm->frame].state = MEYE_BUF_USING;
+- kfifo_put(meye.grabq, (unsigned char *)&vm->frame, sizeof(int));
+- mutex_unlock(&meye.lock);
+- break;
+- }
++ mutex_lock(&meye.lock);
+
+- case VIDIOCGMBUF: {
+- struct video_mbuf *vm = arg;
+- int i;
++ if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP)
++ mchip_cont_compression_start();
+
+- memset(vm, 0 , sizeof(*vm));
+- vm->size = gbufsize * gbuffers;
+- vm->frames = gbuffers;
+- for (i = 0; i < gbuffers; i++)
+- vm->offsets[i] = i * gbufsize;
+- break;
+- }
++ meye.grab_buffer[*nb].state = MEYE_BUF_USING;
++ kfifo_put(meye.grabq, (unsigned char *)nb, sizeof(int));
++ mutex_unlock(&meye.lock);
+
+- case MEYEIOC_G_PARAMS: {
+- struct meye_params *p = arg;
+- *p = meye.params;
+- break;
+- }
++ return 0;
++}
+
+- case MEYEIOC_S_PARAMS: {
+- struct meye_params *jp = arg;
+- if (jp->subsample > 1)
+- return -EINVAL;
+- if (jp->quality > 10)
+- return -EINVAL;
+- if (jp->sharpness > 63 || jp->agc > 63 || jp->picture > 63)
+- return -EINVAL;
+- if (jp->framerate > 31)
+- return -EINVAL;
+- mutex_lock(&meye.lock);
+- if (meye.params.subsample != jp->subsample ||
+- meye.params.quality != jp->quality)
+- mchip_hic_stop(); /* need restart */
+- meye.params = *jp;
+- sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS,
+- meye.params.sharpness);
+- sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC,
+- meye.params.agc);
+- sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE,
+- meye.params.picture);
+- mutex_unlock(&meye.lock);
+- break;
+- }
++static int meyeioc_sync(struct file *file, void *fh, int *i)
++{
++ int unused;
+
+- case MEYEIOC_QBUF_CAPT: {
+- int *nb = arg;
+-
+- if (!meye.grab_fbuffer)
+- return -EINVAL;
+- if (*nb >= gbuffers)
+- return -EINVAL;
+- if (*nb < 0) {
+- /* stop capture */
+- mchip_hic_stop();
+- return 0;
+- }
+- if (meye.grab_buffer[*nb].state != MEYE_BUF_UNUSED)
+- return -EBUSY;
+- mutex_lock(&meye.lock);
+- if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP)
+- mchip_cont_compression_start();
+- meye.grab_buffer[*nb].state = MEYE_BUF_USING;
+- kfifo_put(meye.grabq, (unsigned char *)nb, sizeof(int));
++ if (*i < 0 || *i >= gbuffers)
++ return -EINVAL;
++
++ mutex_lock(&meye.lock);
++ switch (meye.grab_buffer[*i].state) {
++
++ case MEYE_BUF_UNUSED:
+ mutex_unlock(&meye.lock);
+- break;
++ return -EINVAL;
++ case MEYE_BUF_USING:
++ if (file->f_flags & O_NONBLOCK) {
++ mutex_unlock(&meye.lock);
++ return -EAGAIN;
++ }
++ if (wait_event_interruptible(meye.proc_list,
++ (meye.grab_buffer[*i].state != MEYE_BUF_USING))) {
++ mutex_unlock(&meye.lock);
++ return -EINTR;
++ }
++ /* fall through */
++ case MEYE_BUF_DONE:
++ meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
++ kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int));
+ }
++ *i = meye.grab_buffer[*i].size;
++ mutex_unlock(&meye.lock);
++ return 0;
++}
+
+- case MEYEIOC_SYNC: {
+- int *i = arg;
+- int unused;
++static int meyeioc_stillcapt(void)
++{
++ if (!meye.grab_fbuffer)
++ return -EINVAL;
+
+- if (*i < 0 || *i >= gbuffers)
+- return -EINVAL;
++ if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
++ return -EBUSY;
+
+- mutex_lock(&meye.lock);
+- switch (meye.grab_buffer[*i].state) {
++ mutex_lock(&meye.lock);
++ meye.grab_buffer[0].state = MEYE_BUF_USING;
++ mchip_take_picture();
+
+- case MEYE_BUF_UNUSED:
+- mutex_unlock(&meye.lock);
+- return -EINVAL;
+- case MEYE_BUF_USING:
+- if (file->f_flags & O_NONBLOCK) {
+- mutex_unlock(&meye.lock);
+- return -EAGAIN;
+- }
+- if (wait_event_interruptible(meye.proc_list,
+- (meye.grab_buffer[*i].state != MEYE_BUF_USING))) {
+- mutex_unlock(&meye.lock);
+- return -EINTR;
+- }
+- /* fall through */
+- case MEYE_BUF_DONE:
+- meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
+- kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int));
+- }
+- *i = meye.grab_buffer[*i].size;
+- mutex_unlock(&meye.lock);
+- break;
+- }
++ mchip_get_picture(meye.grab_fbuffer,
++ mchip_hsize() * mchip_vsize() * 2);
+
+- case MEYEIOC_STILLCAPT: {
++ meye.grab_buffer[0].state = MEYE_BUF_DONE;
++ mutex_unlock(&meye.lock);
+
+- if (!meye.grab_fbuffer)
+- return -EINVAL;
+- if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
+- return -EBUSY;
+- mutex_lock(&meye.lock);
+- meye.grab_buffer[0].state = MEYE_BUF_USING;
++ return 0;
++}
++
++static int meyeioc_stilljcapt(int *len)
++{
++ if (!meye.grab_fbuffer)
++ return -EINVAL;
++
++ if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
++ return -EBUSY;
++
++ mutex_lock(&meye.lock);
++ meye.grab_buffer[0].state = MEYE_BUF_USING;
++ *len = -1;
++
++ while (*len == -1) {
+ mchip_take_picture();
+- mchip_get_picture(
+- meye.grab_fbuffer,
+- mchip_hsize() * mchip_vsize() * 2);
+- meye.grab_buffer[0].state = MEYE_BUF_DONE;
+- mutex_unlock(&meye.lock);
+- break;
++ *len = mchip_compress_frame(meye.grab_fbuffer, gbufsize);
+ }
+
+- case MEYEIOC_STILLJCAPT: {
+- int *len = arg;
+-
+- if (!meye.grab_fbuffer)
+- return -EINVAL;
+- if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
+- return -EBUSY;
+- mutex_lock(&meye.lock);
+- meye.grab_buffer[0].state = MEYE_BUF_USING;
+- *len = -1;
+- while (*len == -1) {
+- mchip_take_picture();
+- *len = mchip_compress_frame(meye.grab_fbuffer, gbufsize);
+- }
+- meye.grab_buffer[0].state = MEYE_BUF_DONE;
+- mutex_unlock(&meye.lock);
+- break;
+- }
++ meye.grab_buffer[0].state = MEYE_BUF_DONE;
++ mutex_unlock(&meye.lock);
++ return 0;
++}
+
+- case VIDIOC_QUERYCAP: {
+- struct v4l2_capability *cap = arg;
++static int vidioc_querycap(struct file *file, void *fh,
++ struct v4l2_capability *cap)
++{
++ memset(cap, 0, sizeof(*cap));
++ strcpy(cap->driver, "meye");
++ strcpy(cap->card, "meye");
++ sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev));
+
+- if (forcev4l1)
+- return -EINVAL;
++ cap->version = (MEYE_DRIVER_MAJORVERSION << 8) +
++ MEYE_DRIVER_MINORVERSION;
+
+- memset(cap, 0, sizeof(*cap));
+- strcpy(cap->driver, "meye");
+- strcpy(cap->card, "meye");
+- sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev));
+- cap->version = (MEYE_DRIVER_MAJORVERSION << 8) +
+- MEYE_DRIVER_MINORVERSION;
+- cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
+- V4L2_CAP_STREAMING;
+- break;
+- }
++ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
++ V4L2_CAP_STREAMING;
++
++ return 0;
++}
++
++static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
++{
++ if (i->index != 0)
++ return -EINVAL;
+
+- case VIDIOC_ENUMINPUT: {
+- struct v4l2_input *i = arg;
++ memset(i, 0, sizeof(*i));
++ i->index = 0;
++ strcpy(i->name, "Camera");
++ i->type = V4L2_INPUT_TYPE_CAMERA;
+
+- if (i->index != 0)
+- return -EINVAL;
+- memset(i, 0, sizeof(*i));
+- i->index = 0;
+- strcpy(i->name, "Camera");
+- i->type = V4L2_INPUT_TYPE_CAMERA;
++ return 0;
++}
++
++static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
++{
++ *i = 0;
++ return 0;
++}
++
++static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
++{
++ if (i != 0)
++ return -EINVAL;
++
++ return 0;
++}
++
++static int vidioc_queryctrl(struct file *file, void *fh,
++ struct v4l2_queryctrl *c)
++{
++ switch (c->id) {
++
++ case V4L2_CID_BRIGHTNESS:
++ c->type = V4L2_CTRL_TYPE_INTEGER;
++ strcpy(c->name, "Brightness");
++ c->minimum = 0;
++ c->maximum = 63;
++ c->step = 1;
++ c->default_value = 32;
++ c->flags = 0;
++ break;
++ case V4L2_CID_HUE:
++ c->type = V4L2_CTRL_TYPE_INTEGER;
++ strcpy(c->name, "Hue");
++ c->minimum = 0;
++ c->maximum = 63;
++ c->step = 1;
++ c->default_value = 32;
++ c->flags = 0;
++ break;
++ case V4L2_CID_CONTRAST:
++ c->type = V4L2_CTRL_TYPE_INTEGER;
++ strcpy(c->name, "Contrast");
++ c->minimum = 0;
++ c->maximum = 63;
++ c->step = 1;
++ c->default_value = 32;
++ c->flags = 0;
++ break;
++ case V4L2_CID_SATURATION:
++ c->type = V4L2_CTRL_TYPE_INTEGER;
++ strcpy(c->name, "Saturation");
++ c->minimum = 0;
++ c->maximum = 63;
++ c->step = 1;
++ c->default_value = 32;
++ c->flags = 0;
++ break;
++ case V4L2_CID_AGC:
++ c->type = V4L2_CTRL_TYPE_INTEGER;
++ strcpy(c->name, "Agc");
++ c->minimum = 0;
++ c->maximum = 63;
++ c->step = 1;
++ c->default_value = 48;
++ c->flags = 0;
+ break;
++ case V4L2_CID_MEYE_SHARPNESS:
++ case V4L2_CID_SHARPNESS:
++ c->type = V4L2_CTRL_TYPE_INTEGER;
++ strcpy(c->name, "Sharpness");
++ c->minimum = 0;
++ c->maximum = 63;
++ c->step = 1;
++ c->default_value = 32;
++
++ /* Continue to report legacy private SHARPNESS ctrl but
++ * say it is disabled in preference to ctrl in the spec
++ */
++ c->flags = (c->id == V4L2_CID_SHARPNESS) ? 0 :
++ V4L2_CTRL_FLAG_DISABLED;
++ break;
++ case V4L2_CID_PICTURE:
++ c->type = V4L2_CTRL_TYPE_INTEGER;
++ strcpy(c->name, "Picture");
++ c->minimum = 0;
++ c->maximum = 63;
++ c->step = 1;
++ c->default_value = 0;
++ c->flags = 0;
++ break;
++ case V4L2_CID_JPEGQUAL:
++ c->type = V4L2_CTRL_TYPE_INTEGER;
++ strcpy(c->name, "JPEG quality");
++ c->minimum = 0;
++ c->maximum = 10;
++ c->step = 1;
++ c->default_value = 8;
++ c->flags = 0;
++ break;
++ case V4L2_CID_FRAMERATE:
++ c->type = V4L2_CTRL_TYPE_INTEGER;
++ strcpy(c->name, "Framerate");
++ c->minimum = 0;
++ c->maximum = 31;
++ c->step = 1;
++ c->default_value = 0;
++ c->flags = 0;
++ break;
++ default:
++ return -EINVAL;
+ }
+
+- case VIDIOC_G_INPUT: {
+- int *i = arg;
++ return 0;
++}
+
+- *i = 0;
++static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
++{
++ mutex_lock(&meye.lock);
++ switch (c->id) {
++ case V4L2_CID_BRIGHTNESS:
++ sony_pic_camera_command(
++ SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, c->value);
++ meye.picture.brightness = c->value << 10;
++ break;
++ case V4L2_CID_HUE:
++ sony_pic_camera_command(
++ SONY_PIC_COMMAND_SETCAMERAHUE, c->value);
++ meye.picture.hue = c->value << 10;
++ break;
++ case V4L2_CID_CONTRAST:
++ sony_pic_camera_command(
++ SONY_PIC_COMMAND_SETCAMERACONTRAST, c->value);
++ meye.picture.contrast = c->value << 10;
++ break;
++ case V4L2_CID_SATURATION:
++ sony_pic_camera_command(
++ SONY_PIC_COMMAND_SETCAMERACOLOR, c->value);
++ meye.picture.colour = c->value << 10;
++ break;
++ case V4L2_CID_AGC:
++ sony_pic_camera_command(
++ SONY_PIC_COMMAND_SETCAMERAAGC, c->value);
++ meye.params.agc = c->value;
++ break;
++ case V4L2_CID_SHARPNESS:
++ case V4L2_CID_MEYE_SHARPNESS:
++ sony_pic_camera_command(
++ SONY_PIC_COMMAND_SETCAMERASHARPNESS, c->value);
++ meye.params.sharpness = c->value;
++ break;
++ case V4L2_CID_PICTURE:
++ sony_pic_camera_command(
++ SONY_PIC_COMMAND_SETCAMERAPICTURE, c->value);
++ meye.params.picture = c->value;
++ break;
++ case V4L2_CID_JPEGQUAL:
++ meye.params.quality = c->value;
++ break;
++ case V4L2_CID_FRAMERATE:
++ meye.params.framerate = c->value;
+ break;
++ default:
++ mutex_unlock(&meye.lock);
++ return -EINVAL;
+ }
++ mutex_unlock(&meye.lock);
+
+- case VIDIOC_S_INPUT: {
+- int *i = arg;
++ return 0;
++}
+
+- if (*i != 0)
+- return -EINVAL;
++static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c)
++{
++ mutex_lock(&meye.lock);
++ switch (c->id) {
++ case V4L2_CID_BRIGHTNESS:
++ c->value = meye.picture.brightness >> 10;
++ break;
++ case V4L2_CID_HUE:
++ c->value = meye.picture.hue >> 10;
++ break;
++ case V4L2_CID_CONTRAST:
++ c->value = meye.picture.contrast >> 10;
++ break;
++ case V4L2_CID_SATURATION:
++ c->value = meye.picture.colour >> 10;
++ break;
++ case V4L2_CID_AGC:
++ c->value = meye.params.agc;
++ break;
++ case V4L2_CID_SHARPNESS:
++ case V4L2_CID_MEYE_SHARPNESS:
++ c->value = meye.params.sharpness;
+ break;
++ case V4L2_CID_PICTURE:
++ c->value = meye.params.picture;
++ break;
++ case V4L2_CID_JPEGQUAL:
++ c->value = meye.params.quality;
++ break;
++ case V4L2_CID_FRAMERATE:
++ c->value = meye.params.framerate;
++ break;
++ default:
++ mutex_unlock(&meye.lock);
++ return -EINVAL;
+ }
++ mutex_unlock(&meye.lock);
+
+- case VIDIOC_QUERYCTRL: {
+- struct v4l2_queryctrl *c = arg;
++ return 0;
++}
+
+- switch (c->id) {
++static int vidioc_enum_fmt_cap(struct file *file, void *fh,
++ struct v4l2_fmtdesc *f)
++{
++ if (f->index > 1)
++ return -EINVAL;
+
+- case V4L2_CID_BRIGHTNESS:
+- c->type = V4L2_CTRL_TYPE_INTEGER;
+- strcpy(c->name, "Brightness");
+- c->minimum = 0;
+- c->maximum = 63;
+- c->step = 1;
+- c->default_value = 32;
+- c->flags = 0;
+- break;
+- case V4L2_CID_HUE:
+- c->type = V4L2_CTRL_TYPE_INTEGER;
+- strcpy(c->name, "Hue");
+- c->minimum = 0;
+- c->maximum = 63;
+- c->step = 1;
+- c->default_value = 32;
+- c->flags = 0;
+- break;
+- case V4L2_CID_CONTRAST:
+- c->type = V4L2_CTRL_TYPE_INTEGER;
+- strcpy(c->name, "Contrast");
+- c->minimum = 0;
+- c->maximum = 63;
+- c->step = 1;
+- c->default_value = 32;
+- c->flags = 0;
+- break;
+- case V4L2_CID_SATURATION:
+- c->type = V4L2_CTRL_TYPE_INTEGER;
+- strcpy(c->name, "Saturation");
+- c->minimum = 0;
+- c->maximum = 63;
+- c->step = 1;
+- c->default_value = 32;
+- c->flags = 0;
+- break;
+- case V4L2_CID_AGC:
+- c->type = V4L2_CTRL_TYPE_INTEGER;
+- strcpy(c->name, "Agc");
+- c->minimum = 0;
+- c->maximum = 63;
+- c->step = 1;
+- c->default_value = 48;
+- c->flags = 0;
+- break;
+- case V4L2_CID_SHARPNESS:
+- c->type = V4L2_CTRL_TYPE_INTEGER;
+- strcpy(c->name, "Sharpness");
+- c->minimum = 0;
+- c->maximum = 63;
+- c->step = 1;
+- c->default_value = 32;
+- c->flags = 0;
+- break;
+- case V4L2_CID_PICTURE:
+- c->type = V4L2_CTRL_TYPE_INTEGER;
+- strcpy(c->name, "Picture");
+- c->minimum = 0;
+- c->maximum = 63;
+- c->step = 1;
+- c->default_value = 0;
+- c->flags = 0;
+- break;
+- case V4L2_CID_JPEGQUAL:
+- c->type = V4L2_CTRL_TYPE_INTEGER;
+- strcpy(c->name, "JPEG quality");
+- c->minimum = 0;
+- c->maximum = 10;
+- c->step = 1;
+- c->default_value = 8;
+- c->flags = 0;
+- break;
+- case V4L2_CID_FRAMERATE:
+- c->type = V4L2_CTRL_TYPE_INTEGER;
+- strcpy(c->name, "Framerate");
+- c->minimum = 0;
+- c->maximum = 31;
+- c->step = 1;
+- c->default_value = 0;
+- c->flags = 0;
+- break;
+- default:
+- return -EINVAL;
+- }
+- break;
++ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++ return -EINVAL;
++
++ if (f->index == 0) {
++ /* standard YUV 422 capture */
++ memset(f, 0, sizeof(*f));
++ f->index = 0;
++ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ f->flags = 0;
++ strcpy(f->description, "YUV422");
++ f->pixelformat = V4L2_PIX_FMT_YUYV;
++ } else {
++ /* compressed MJPEG capture */
++ memset(f, 0, sizeof(*f));
++ f->index = 1;
++ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ f->flags = V4L2_FMT_FLAG_COMPRESSED;
++ strcpy(f->description, "MJPEG");
++ f->pixelformat = V4L2_PIX_FMT_MJPEG;
+ }
+
+- case VIDIOC_S_CTRL: {
+- struct v4l2_control *c = arg;
++ return 0;
++}
+
+- mutex_lock(&meye.lock);
+- switch (c->id) {
+- case V4L2_CID_BRIGHTNESS:
+- sony_pic_camera_command(
+- SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, c->value);
+- meye.picture.brightness = c->value << 10;
+- break;
+- case V4L2_CID_HUE:
+- sony_pic_camera_command(
+- SONY_PIC_COMMAND_SETCAMERAHUE, c->value);
+- meye.picture.hue = c->value << 10;
+- break;
+- case V4L2_CID_CONTRAST:
+- sony_pic_camera_command(
+- SONY_PIC_COMMAND_SETCAMERACONTRAST, c->value);
+- meye.picture.contrast = c->value << 10;
+- break;
+- case V4L2_CID_SATURATION:
+- sony_pic_camera_command(
+- SONY_PIC_COMMAND_SETCAMERACOLOR, c->value);
+- meye.picture.colour = c->value << 10;
+- break;
+- case V4L2_CID_AGC:
+- sony_pic_camera_command(
+- SONY_PIC_COMMAND_SETCAMERAAGC, c->value);
+- meye.params.agc = c->value;
+- break;
+- case V4L2_CID_SHARPNESS:
+- sony_pic_camera_command(
+- SONY_PIC_COMMAND_SETCAMERASHARPNESS, c->value);
+- meye.params.sharpness = c->value;
+- break;
+- case V4L2_CID_PICTURE:
+- sony_pic_camera_command(
+- SONY_PIC_COMMAND_SETCAMERAPICTURE, c->value);
+- meye.params.picture = c->value;
+- break;
+- case V4L2_CID_JPEGQUAL:
+- meye.params.quality = c->value;
+- break;
+- case V4L2_CID_FRAMERATE:
+- meye.params.framerate = c->value;
+- break;
+- default:
+- mutex_unlock(&meye.lock);
+- return -EINVAL;
+- }
+- mutex_unlock(&meye.lock);
+- break;
++static int vidioc_try_fmt_cap(struct file *file, void *fh,
++ struct v4l2_format *f)
++{
++ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++ return -EINVAL;
++
++ if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
++ f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
++ return -EINVAL;
++
++ if (f->fmt.pix.field != V4L2_FIELD_ANY &&
++ f->fmt.pix.field != V4L2_FIELD_NONE)
++ return -EINVAL;
++
++ f->fmt.pix.field = V4L2_FIELD_NONE;
++
++ if (f->fmt.pix.width <= 320) {
++ f->fmt.pix.width = 320;
++ f->fmt.pix.height = 240;
++ } else {
++ f->fmt.pix.width = 640;
++ f->fmt.pix.height = 480;
+ }
+
+- case VIDIOC_G_CTRL: {
+- struct v4l2_control *c = arg;
++ f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
++ f->fmt.pix.sizeimage = f->fmt.pix.height *
++ f->fmt.pix.bytesperline;
++ f->fmt.pix.colorspace = 0;
++ f->fmt.pix.priv = 0;
+
+- mutex_lock(&meye.lock);
+- switch (c->id) {
+- case V4L2_CID_BRIGHTNESS:
+- c->value = meye.picture.brightness >> 10;
+- break;
+- case V4L2_CID_HUE:
+- c->value = meye.picture.hue >> 10;
+- break;
+- case V4L2_CID_CONTRAST:
+- c->value = meye.picture.contrast >> 10;
+- break;
+- case V4L2_CID_SATURATION:
+- c->value = meye.picture.colour >> 10;
+- break;
+- case V4L2_CID_AGC:
+- c->value = meye.params.agc;
+- break;
+- case V4L2_CID_SHARPNESS:
+- c->value = meye.params.sharpness;
+- break;
+- case V4L2_CID_PICTURE:
+- c->value = meye.params.picture;
+- break;
+- case V4L2_CID_JPEGQUAL:
+- c->value = meye.params.quality;
+- break;
+- case V4L2_CID_FRAMERATE:
+- c->value = meye.params.framerate;
+- break;
+- default:
+- mutex_unlock(&meye.lock);
+- return -EINVAL;
+- }
+- mutex_unlock(&meye.lock);
++ return 0;
++}
++
++static int vidioc_g_fmt_cap(struct file *file, void *fh, struct v4l2_format *f)
++{
++ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++ return -EINVAL;
++
++ memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
++ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++
++ switch (meye.mchip_mode) {
++ case MCHIP_HIC_MODE_CONT_OUT:
++ default:
++ f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
++ break;
++ case MCHIP_HIC_MODE_CONT_COMP:
++ f->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
+ break;
+ }
+
+- case VIDIOC_ENUM_FMT: {
+- struct v4l2_fmtdesc *f = arg;
+-
+- if (f->index > 1)
+- return -EINVAL;
+- if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+- return -EINVAL;
+- if (f->index == 0) {
+- /* standard YUV 422 capture */
+- memset(f, 0, sizeof(*f));
+- f->index = 0;
+- f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+- f->flags = 0;
+- strcpy(f->description, "YUV422");
+- f->pixelformat = V4L2_PIX_FMT_YUYV;
+- } else {
+- /* compressed MJPEG capture */
+- memset(f, 0, sizeof(*f));
+- f->index = 1;
+- f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+- f->flags = V4L2_FMT_FLAG_COMPRESSED;
+- strcpy(f->description, "MJPEG");
+- f->pixelformat = V4L2_PIX_FMT_MJPEG;
+- }
+- break;
++ f->fmt.pix.field = V4L2_FIELD_NONE;
++ f->fmt.pix.width = mchip_hsize();
++ f->fmt.pix.height = mchip_vsize();
++ f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
++ f->fmt.pix.sizeimage = f->fmt.pix.height *
++ f->fmt.pix.bytesperline;
++ f->fmt.pix.colorspace = 0;
++ f->fmt.pix.priv = 0;
++
++ return 0;
++}
++
++static int vidioc_s_fmt_cap(struct file *file, void *fh, struct v4l2_format *f)
++{
++ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++ return -EINVAL;
++
++ if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
++ f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
++ return -EINVAL;
++
++ if (f->fmt.pix.field != V4L2_FIELD_ANY &&
++ f->fmt.pix.field != V4L2_FIELD_NONE)
++ return -EINVAL;
++
++ f->fmt.pix.field = V4L2_FIELD_NONE;
++ mutex_lock(&meye.lock);
++
++ if (f->fmt.pix.width <= 320) {
++ f->fmt.pix.width = 320;
++ f->fmt.pix.height = 240;
++ meye.params.subsample = 1;
++ } else {
++ f->fmt.pix.width = 640;
++ f->fmt.pix.height = 480;
++ meye.params.subsample = 0;
+ }
+
+- case VIDIOC_TRY_FMT: {
+- struct v4l2_format *f = arg;
+-
+- if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+- return -EINVAL;
+- if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
+- f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
+- return -EINVAL;
+- if (f->fmt.pix.field != V4L2_FIELD_ANY &&
+- f->fmt.pix.field != V4L2_FIELD_NONE)
+- return -EINVAL;
+- f->fmt.pix.field = V4L2_FIELD_NONE;
+- if (f->fmt.pix.width <= 320) {
+- f->fmt.pix.width = 320;
+- f->fmt.pix.height = 240;
+- } else {
+- f->fmt.pix.width = 640;
+- f->fmt.pix.height = 480;
+- }
+- f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
+- f->fmt.pix.sizeimage = f->fmt.pix.height *
+- f->fmt.pix.bytesperline;
+- f->fmt.pix.colorspace = 0;
+- f->fmt.pix.priv = 0;
++ switch (f->fmt.pix.pixelformat) {
++ case V4L2_PIX_FMT_YUYV:
++ meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT;
++ break;
++ case V4L2_PIX_FMT_MJPEG:
++ meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP;
+ break;
+ }
+
+- case VIDIOC_G_FMT: {
+- struct v4l2_format *f = arg;
++ mutex_unlock(&meye.lock);
++ f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
++ f->fmt.pix.sizeimage = f->fmt.pix.height *
++ f->fmt.pix.bytesperline;
++ f->fmt.pix.colorspace = 0;
++ f->fmt.pix.priv = 0;
+
+- if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+- return -EINVAL;
+- memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
+- f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+- switch (meye.mchip_mode) {
+- case MCHIP_HIC_MODE_CONT_OUT:
+- default:
+- f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+- break;
+- case MCHIP_HIC_MODE_CONT_COMP:
+- f->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
+- break;
+- }
+- f->fmt.pix.field = V4L2_FIELD_NONE;
+- f->fmt.pix.width = mchip_hsize();
+- f->fmt.pix.height = mchip_vsize();
+- f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
+- f->fmt.pix.sizeimage = f->fmt.pix.height *
+- f->fmt.pix.bytesperline;
+- f->fmt.pix.colorspace = 0;
+- f->fmt.pix.priv = 0;
+- break;
+- }
++ return 0;
++}
+
+- case VIDIOC_S_FMT: {
+- struct v4l2_format *f = arg;
+-
+- if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+- return -EINVAL;
+- if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
+- f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
+- return -EINVAL;
+- if (f->fmt.pix.field != V4L2_FIELD_ANY &&
+- f->fmt.pix.field != V4L2_FIELD_NONE)
+- return -EINVAL;
+- f->fmt.pix.field = V4L2_FIELD_NONE;
+- mutex_lock(&meye.lock);
+- if (f->fmt.pix.width <= 320) {
+- f->fmt.pix.width = 320;
+- f->fmt.pix.height = 240;
+- meye.params.subsample = 1;
+- } else {
+- f->fmt.pix.width = 640;
+- f->fmt.pix.height = 480;
+- meye.params.subsample = 0;
+- }
+- switch (f->fmt.pix.pixelformat) {
+- case V4L2_PIX_FMT_YUYV:
+- meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT;
+- break;
+- case V4L2_PIX_FMT_MJPEG:
+- meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP;
+- break;
+- }
+- mutex_unlock(&meye.lock);
+- f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
+- f->fmt.pix.sizeimage = f->fmt.pix.height *
+- f->fmt.pix.bytesperline;
+- f->fmt.pix.colorspace = 0;
+- f->fmt.pix.priv = 0;
++static int vidioc_reqbufs(struct file *file, void *fh,
++ struct v4l2_requestbuffers *req)
++{
++ int i;
+
+- break;
+- }
++ if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++ return -EINVAL;
+
+- case VIDIOC_REQBUFS: {
+- struct v4l2_requestbuffers *req = arg;
+- int i;
++ if (req->memory != V4L2_MEMORY_MMAP)
++ return -EINVAL;
+
+- if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+- return -EINVAL;
+- if (req->memory != V4L2_MEMORY_MMAP)
+- return -EINVAL;
+- if (meye.grab_fbuffer && req->count == gbuffers) {
+- /* already allocated, no modifications */
+- break;
+- }
+- mutex_lock(&meye.lock);
+- if (meye.grab_fbuffer) {
+- for (i = 0; i < gbuffers; i++)
+- if (meye.vma_use_count[i]) {
+- mutex_unlock(&meye.lock);
+- return -EINVAL;
+- }
+- rvfree(meye.grab_fbuffer, gbuffers * gbufsize);
+- meye.grab_fbuffer = NULL;
+- }
+- gbuffers = max(2, min((int)req->count, MEYE_MAX_BUFNBRS));
+- req->count = gbuffers;
+- meye.grab_fbuffer = rvmalloc(gbuffers * gbufsize);
+- if (!meye.grab_fbuffer) {
+- printk(KERN_ERR "meye: v4l framebuffer allocation"
+- " failed\n");
+- mutex_unlock(&meye.lock);
+- return -ENOMEM;
+- }
+- for (i = 0; i < gbuffers; i++)
+- meye.vma_use_count[i] = 0;
+- mutex_unlock(&meye.lock);
+- break;
++ if (meye.grab_fbuffer && req->count == gbuffers) {
++ /* already allocated, no modifications */
++ return 0;
+ }
+
+- case VIDIOC_QUERYBUF: {
+- struct v4l2_buffer *buf = arg;
+- int index = buf->index;
+-
+- if (index < 0 || index >= gbuffers)
+- return -EINVAL;
+- memset(buf, 0, sizeof(*buf));
+- buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+- buf->index = index;
+- buf->bytesused = meye.grab_buffer[index].size;
+- buf->flags = V4L2_BUF_FLAG_MAPPED;
+- if (meye.grab_buffer[index].state == MEYE_BUF_USING)
+- buf->flags |= V4L2_BUF_FLAG_QUEUED;
+- if (meye.grab_buffer[index].state == MEYE_BUF_DONE)
+- buf->flags |= V4L2_BUF_FLAG_DONE;
+- buf->field = V4L2_FIELD_NONE;
+- buf->timestamp = meye.grab_buffer[index].timestamp;
+- buf->sequence = meye.grab_buffer[index].sequence;
+- buf->memory = V4L2_MEMORY_MMAP;
+- buf->m.offset = index * gbufsize;
+- buf->length = gbufsize;
+- break;
++ mutex_lock(&meye.lock);
++ if (meye.grab_fbuffer) {
++ for (i = 0; i < gbuffers; i++)
++ if (meye.vma_use_count[i]) {
++ mutex_unlock(&meye.lock);
++ return -EINVAL;
++ }
++ rvfree(meye.grab_fbuffer, gbuffers * gbufsize);
++ meye.grab_fbuffer = NULL;
+ }
+
+- case VIDIOC_QBUF: {
+- struct v4l2_buffer *buf = arg;
+-
+- if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+- return -EINVAL;
+- if (buf->memory != V4L2_MEMORY_MMAP)
+- return -EINVAL;
+- if (buf->index < 0 || buf->index >= gbuffers)
+- return -EINVAL;
+- if (meye.grab_buffer[buf->index].state != MEYE_BUF_UNUSED)
+- return -EINVAL;
+- mutex_lock(&meye.lock);
+- buf->flags |= V4L2_BUF_FLAG_QUEUED;
+- buf->flags &= ~V4L2_BUF_FLAG_DONE;
+- meye.grab_buffer[buf->index].state = MEYE_BUF_USING;
+- kfifo_put(meye.grabq, (unsigned char *)&buf->index, sizeof(int));
++ gbuffers = max(2, min((int)req->count, MEYE_MAX_BUFNBRS));
++ req->count = gbuffers;
++ meye.grab_fbuffer = rvmalloc(gbuffers * gbufsize);
++
++ if (!meye.grab_fbuffer) {
++ printk(KERN_ERR "meye: v4l framebuffer allocation"
++ " failed\n");
+ mutex_unlock(&meye.lock);
+- break;
++ return -ENOMEM;
+ }
+
+- case VIDIOC_DQBUF: {
+- struct v4l2_buffer *buf = arg;
+- int reqnr;
++ for (i = 0; i < gbuffers; i++)
++ meye.vma_use_count[i] = 0;
+
+- if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+- return -EINVAL;
+- if (buf->memory != V4L2_MEMORY_MMAP)
+- return -EINVAL;
++ mutex_unlock(&meye.lock);
+
+- mutex_lock(&meye.lock);
+- if (kfifo_len(meye.doneq) == 0 && file->f_flags & O_NONBLOCK) {
+- mutex_unlock(&meye.lock);
+- return -EAGAIN;
+- }
+- if (wait_event_interruptible(meye.proc_list,
+- kfifo_len(meye.doneq) != 0) < 0) {
+- mutex_unlock(&meye.lock);
+- return -EINTR;
+- }
+- if (!kfifo_get(meye.doneq, (unsigned char *)&reqnr,
+- sizeof(int))) {
+- mutex_unlock(&meye.lock);
+- return -EBUSY;
+- }
+- if (meye.grab_buffer[reqnr].state != MEYE_BUF_DONE) {
+- mutex_unlock(&meye.lock);
+- return -EINVAL;
+- }
+- buf->index = reqnr;
+- buf->bytesused = meye.grab_buffer[reqnr].size;
+- buf->flags = V4L2_BUF_FLAG_MAPPED;
+- buf->field = V4L2_FIELD_NONE;
+- buf->timestamp = meye.grab_buffer[reqnr].timestamp;
+- buf->sequence = meye.grab_buffer[reqnr].sequence;
+- buf->memory = V4L2_MEMORY_MMAP;
+- buf->m.offset = reqnr * gbufsize;
+- buf->length = gbufsize;
+- meye.grab_buffer[reqnr].state = MEYE_BUF_UNUSED;
++ return 0;
++}
++
++static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf)
++{
++ int index = buf->index;
++
++ if (index < 0 || index >= gbuffers)
++ return -EINVAL;
++
++ memset(buf, 0, sizeof(*buf));
++
++ buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ buf->index = index;
++ buf->bytesused = meye.grab_buffer[index].size;
++ buf->flags = V4L2_BUF_FLAG_MAPPED;
++
++ if (meye.grab_buffer[index].state == MEYE_BUF_USING)
++ buf->flags |= V4L2_BUF_FLAG_QUEUED;
++
++ if (meye.grab_buffer[index].state == MEYE_BUF_DONE)
++ buf->flags |= V4L2_BUF_FLAG_DONE;
++
++ buf->field = V4L2_FIELD_NONE;
++ buf->timestamp = meye.grab_buffer[index].timestamp;
++ buf->sequence = meye.grab_buffer[index].sequence;
++ buf->memory = V4L2_MEMORY_MMAP;
++ buf->m.offset = index * gbufsize;
++ buf->length = gbufsize;
++
++ return 0;
++}
++
++static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
++{
++ if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++ return -EINVAL;
++
++ if (buf->memory != V4L2_MEMORY_MMAP)
++ return -EINVAL;
++
++ if (buf->index < 0 || buf->index >= gbuffers)
++ return -EINVAL;
++
++ if (meye.grab_buffer[buf->index].state != MEYE_BUF_UNUSED)
++ return -EINVAL;
++
++ mutex_lock(&meye.lock);
++ buf->flags |= V4L2_BUF_FLAG_QUEUED;
++ buf->flags &= ~V4L2_BUF_FLAG_DONE;
++ meye.grab_buffer[buf->index].state = MEYE_BUF_USING;
++ kfifo_put(meye.grabq, (unsigned char *)&buf->index, sizeof(int));
++ mutex_unlock(&meye.lock);
++
++ return 0;
++}
++
++static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
++{
++ int reqnr;
++
++ if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++ return -EINVAL;
++
++ if (buf->memory != V4L2_MEMORY_MMAP)
++ return -EINVAL;
++
++ mutex_lock(&meye.lock);
++
++ if (kfifo_len(meye.doneq) == 0 && file->f_flags & O_NONBLOCK) {
+ mutex_unlock(&meye.lock);
+- break;
++ return -EAGAIN;
+ }
+
+- case VIDIOC_STREAMON: {
+- mutex_lock(&meye.lock);
+- switch (meye.mchip_mode) {
+- case MCHIP_HIC_MODE_CONT_OUT:
+- mchip_continuous_start();
+- break;
+- case MCHIP_HIC_MODE_CONT_COMP:
+- mchip_cont_compression_start();
+- break;
+- default:
+- mutex_unlock(&meye.lock);
+- return -EINVAL;
+- }
++ if (wait_event_interruptible(meye.proc_list,
++ kfifo_len(meye.doneq) != 0) < 0) {
+ mutex_unlock(&meye.lock);
+- break;
++ return -EINTR;
+ }
+
+- case VIDIOC_STREAMOFF: {
+- int i;
++ if (!kfifo_get(meye.doneq, (unsigned char *)&reqnr,
++ sizeof(int))) {
++ mutex_unlock(&meye.lock);
++ return -EBUSY;
++ }
+
+- mutex_lock(&meye.lock);
+- mchip_hic_stop();
+- kfifo_reset(meye.grabq);
+- kfifo_reset(meye.doneq);
+- for (i = 0; i < MEYE_MAX_BUFNBRS; i++)
+- meye.grab_buffer[i].state = MEYE_BUF_UNUSED;
++ if (meye.grab_buffer[reqnr].state != MEYE_BUF_DONE) {
+ mutex_unlock(&meye.lock);
+- break;
++ return -EINVAL;
+ }
+
+- /*
+- * XXX what about private snapshot ioctls ?
+- * Do they need to be converted to V4L2 ?
+- */
++ buf->index = reqnr;
++ buf->bytesused = meye.grab_buffer[reqnr].size;
++ buf->flags = V4L2_BUF_FLAG_MAPPED;
++ buf->field = V4L2_FIELD_NONE;
++ buf->timestamp = meye.grab_buffer[reqnr].timestamp;
++ buf->sequence = meye.grab_buffer[reqnr].sequence;
++ buf->memory = V4L2_MEMORY_MMAP;
++ buf->m.offset = reqnr * gbufsize;
++ buf->length = gbufsize;
++ meye.grab_buffer[reqnr].state = MEYE_BUF_UNUSED;
++ mutex_unlock(&meye.lock);
++
++ return 0;
++}
+
++static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
++{
++ mutex_lock(&meye.lock);
++
++ switch (meye.mchip_mode) {
++ case MCHIP_HIC_MODE_CONT_OUT:
++ mchip_continuous_start();
++ break;
++ case MCHIP_HIC_MODE_CONT_COMP:
++ mchip_cont_compression_start();
++ break;
+ default:
+- return -ENOIOCTLCMD;
++ mutex_unlock(&meye.lock);
++ return -EINVAL;
+ }
+
++ mutex_unlock(&meye.lock);
++
+ return 0;
+ }
+
+-static int meye_ioctl(struct inode *inode, struct file *file,
+- unsigned int cmd, unsigned long arg)
++static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
+ {
+- return video_usercopy(inode, file, cmd, arg, meye_do_ioctl);
++ mutex_lock(&meye.lock);
++ mchip_hic_stop();
++ kfifo_reset(meye.grabq);
++ kfifo_reset(meye.doneq);
++
++ for (i = 0; i < MEYE_MAX_BUFNBRS; i++)
++ meye.grab_buffer[i].state = MEYE_BUF_UNUSED;
++
++ mutex_unlock(&meye.lock);
++ return 0;
++}
++
++static int vidioc_default(struct file *file, void *fh, int cmd, void *arg)
++{
++ switch (cmd) {
++ case MEYEIOC_G_PARAMS:
++ return meyeioc_g_params((struct meye_params *) arg);
++
++ case MEYEIOC_S_PARAMS:
++ return meyeioc_s_params((struct meye_params *) arg);
++
++ case MEYEIOC_QBUF_CAPT:
++ return meyeioc_qbuf_capt((int *) arg);
++
++ case MEYEIOC_SYNC:
++ return meyeioc_sync(file, fh, (int *) arg);
++
++ case MEYEIOC_STILLCAPT:
++ return meyeioc_stillcapt();
++
++ case MEYEIOC_STILLJCAPT:
++ return meyeioc_stilljcapt((int *) arg);
++
++ default:
++ return -EINVAL;
++ }
++
+ }
+
+ static unsigned int meye_poll(struct file *file, poll_table *wait)
+@@ -1752,8 +1687,10 @@ static const struct file_operations meye_fops = {
+ .open = meye_open,
+ .release = meye_release,
+ .mmap = meye_mmap,
+- .ioctl = meye_ioctl,
++ .ioctl = video_ioctl2,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .poll = meye_poll,
+ .llseek = no_llseek,
+ };
+@@ -1765,6 +1702,24 @@ static struct video_device meye_template = {
+ .fops = &meye_fops,
+ .release = video_device_release,
+ .minor = -1,
++ .vidioc_querycap = vidioc_querycap,
++ .vidioc_enum_input = vidioc_enum_input,
++ .vidioc_g_input = vidioc_g_input,
++ .vidioc_s_input = vidioc_s_input,
++ .vidioc_queryctrl = vidioc_queryctrl,
++ .vidioc_s_ctrl = vidioc_s_ctrl,
++ .vidioc_g_ctrl = vidioc_g_ctrl,
++ .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap,
++ .vidioc_try_fmt_cap = vidioc_try_fmt_cap,
++ .vidioc_g_fmt_cap = vidioc_g_fmt_cap,
++ .vidioc_s_fmt_cap = vidioc_s_fmt_cap,
++ .vidioc_reqbufs = vidioc_reqbufs,
++ .vidioc_querybuf = vidioc_querybuf,
++ .vidioc_qbuf = vidioc_qbuf,
++ .vidioc_dqbuf = vidioc_dqbuf,
++ .vidioc_streamon = vidioc_streamon,
++ .vidioc_streamoff = vidioc_streamoff,
++ .vidioc_default = vidioc_default,
+ };
+
+ #ifdef CONFIG_PM
+diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
+index 7a11f31..b73c740 100644
+--- a/drivers/media/video/msp3400-driver.c
++++ b/drivers/media/video/msp3400-driver.c
+@@ -366,7 +366,7 @@ int msp_sleep(struct msp_state *state, int timeout)
+ }
+
+ /* ------------------------------------------------------------------------ */
+-#ifdef CONFIG_VIDEO_V4L1
++#ifdef CONFIG_VIDEO_ALLOW_V4L1
+ static int msp_mode_v4l2_to_v4l1(int rxsubchans, int audmode)
+ {
+ if (rxsubchans == V4L2_TUNER_SUB_MONO)
+@@ -514,7 +514,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
+ /* --- v4l ioctls --- */
+ /* take care: bttv does userspace copying, we'll get a
+ kernel pointer here... */
+-#ifdef CONFIG_VIDEO_V4L1
++#ifdef CONFIG_VIDEO_ALLOW_V4L1
+ case VIDIOCGAUDIO:
+ {
+ struct video_audio *va = arg;
+diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c
+index 61ec794..7f55685 100644
+--- a/drivers/media/video/msp3400-kthreads.c
++++ b/drivers/media/video/msp3400-kthreads.c
+@@ -833,11 +833,6 @@ static int msp34xxg_modus(struct i2c_client *client)
+ v4l_dbg(1, msp_debug, client, "selected radio modus\n");
+ return 0x0001;
+ }
+-
+- if (state->v4l2_std & V4L2_STD_PAL) {
+- v4l_dbg(1, msp_debug, client, "selected PAL modus\n");
+- return 0x7001;
+- }
+ if (state->v4l2_std == V4L2_STD_NTSC_M_JP) {
+ v4l_dbg(1, msp_debug, client, "selected M (EIA-J) modus\n");
+ return 0x4001;
+@@ -846,15 +841,15 @@ static int msp34xxg_modus(struct i2c_client *client)
+ v4l_dbg(1, msp_debug, client, "selected M (A2) modus\n");
+ return 0x0001;
+ }
++ if (state->v4l2_std == V4L2_STD_SECAM_L) {
++ v4l_dbg(1, msp_debug, client, "selected SECAM-L modus\n");
++ return 0x6001;
++ }
+ if (state->v4l2_std & V4L2_STD_MN) {
+ v4l_dbg(1, msp_debug, client, "selected M (BTSC) modus\n");
+ return 0x2001;
+ }
+- if (state->v4l2_std & V4L2_STD_SECAM) {
+- v4l_dbg(1, msp_debug, client, "selected SECAM modus\n");
+- return 0x6001;
+- }
+- return 0x0001;
++ return 0x7001;
+ }
+
+ static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in)
+diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c
+index 74fd6a0..fbcb282 100644
+--- a/drivers/media/video/mt20xx.c
++++ b/drivers/media/video/mt20xx.c
+@@ -10,12 +10,10 @@
+ #include "tuner-i2c.h"
+ #include "mt20xx.h"
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "enable verbose debug messages");
+
+-#define PREFIX "mt20xx"
+-
+ /* ---------------------------------------------------------------------- */
+
+ static unsigned int optimize_vco = 1;
+@@ -24,7 +22,7 @@ module_param(optimize_vco, int, 0644);
+ static unsigned int tv_antenna = 1;
+ module_param(tv_antenna, int, 0644);
+
+-static unsigned int radio_antenna = 0;
++static unsigned int radio_antenna;
+ module_param(radio_antenna, int, 0644);
+
+ /* ---------------------------------------------------------------------- */
+@@ -611,6 +609,7 @@ struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
+
+ priv->i2c_props.addr = i2c_addr;
+ priv->i2c_props.adap = i2c_adap;
++ priv->i2c_props.name = "mt20xx";
+
+ //priv->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */
+
+diff --git a/drivers/media/video/mt20xx.h b/drivers/media/video/mt20xx.h
+index 5e9c825..aa848e1 100644
+--- a/drivers/media/video/mt20xx.h
++++ b/drivers/media/video/mt20xx.h
+@@ -29,7 +29,7 @@ static inline struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
+ struct i2c_adapter* i2c_adap,
+ u8 i2c_addr)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif
+diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
+new file mode 100644
+index 0000000..3fb5f63
+--- /dev/null
++++ b/drivers/media/video/mt9m001.c
+@@ -0,0 +1,722 @@
++/*
++ * Driver for MT9M001 CMOS Image Sensor from Micron
++ *
++ * Copyright (C) 2008, Guennadi Liakhovetski <kernel at pengutronix.de>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/videodev2.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/log2.h>
++
++#include <media/v4l2-common.h>
++#include <media/v4l2-chip-ident.h>
++#include <media/soc_camera.h>
++
++#ifdef CONFIG_MT9M001_PCA9536_SWITCH
++#include <asm/gpio.h>
++#endif
++
++/* mt9m001 i2c address 0x5d
++ * The platform has to define i2c_board_info
++ * and call i2c_register_board_info() */
++
++/* mt9m001 selected register addresses */
++#define MT9M001_CHIP_VERSION 0x00
++#define MT9M001_ROW_START 0x01
++#define MT9M001_COLUMN_START 0x02
++#define MT9M001_WINDOW_HEIGHT 0x03
++#define MT9M001_WINDOW_WIDTH 0x04
++#define MT9M001_HORIZONTAL_BLANKING 0x05
++#define MT9M001_VERTICAL_BLANKING 0x06
++#define MT9M001_OUTPUT_CONTROL 0x07
++#define MT9M001_SHUTTER_WIDTH 0x09
++#define MT9M001_FRAME_RESTART 0x0b
++#define MT9M001_SHUTTER_DELAY 0x0c
++#define MT9M001_RESET 0x0d
++#define MT9M001_READ_OPTIONS1 0x1e
++#define MT9M001_READ_OPTIONS2 0x20
++#define MT9M001_GLOBAL_GAIN 0x35
++#define MT9M001_CHIP_ENABLE 0xF1
++
++static const struct soc_camera_data_format mt9m001_colour_formats[] = {
++ /* Order important: first natively supported,
++ * second supported with a GPIO extender */
++ {
++ .name = "Bayer (sRGB) 10 bit",
++ .depth = 10,
++ .fourcc = V4L2_PIX_FMT_SBGGR16,
++ .colorspace = V4L2_COLORSPACE_SRGB,
++ }, {
++ .name = "Bayer (sRGB) 8 bit",
++ .depth = 8,
++ .fourcc = V4L2_PIX_FMT_SBGGR8,
++ .colorspace = V4L2_COLORSPACE_SRGB,
++ }
++};
++
++static const struct soc_camera_data_format mt9m001_monochrome_formats[] = {
++ /* Order important - see above */
++ {
++ .name = "Monochrome 10 bit",
++ .depth = 10,
++ .fourcc = V4L2_PIX_FMT_Y16,
++ }, {
++ .name = "Monochrome 8 bit",
++ .depth = 8,
++ .fourcc = V4L2_PIX_FMT_GREY,
++ },
++};
++
++struct mt9m001 {
++ struct i2c_client *client;
++ struct soc_camera_device icd;
++ int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
++ int switch_gpio;
++ unsigned char autoexposure;
++ unsigned char datawidth;
++};
++
++static int reg_read(struct soc_camera_device *icd, const u8 reg)
++{
++ struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
++ struct i2c_client *client = mt9m001->client;
++ s32 data = i2c_smbus_read_word_data(client, reg);
++ return data < 0 ? data : swab16(data);
++}
++
++static int reg_write(struct soc_camera_device *icd, const u8 reg,
++ const u16 data)
++{
++ struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
++ return i2c_smbus_write_word_data(mt9m001->client, reg, swab16(data));
++}
++
++static int reg_set(struct soc_camera_device *icd, const u8 reg,
++ const u16 data)
++{
++ int ret;
++
++ ret = reg_read(icd, reg);
++ if (ret < 0)
++ return ret;
++ return reg_write(icd, reg, ret | data);
++}
++
++static int reg_clear(struct soc_camera_device *icd, const u8 reg,
++ const u16 data)
++{
++ int ret;
++
++ ret = reg_read(icd, reg);
++ if (ret < 0)
++ return ret;
++ return reg_write(icd, reg, ret & ~data);
++}
++
++static int mt9m001_init(struct soc_camera_device *icd)
++{
++ int ret;
++
++ /* Disable chip, synchronous option update */
++ dev_dbg(icd->vdev->dev, "%s\n", __func__);
++
++ ret = reg_write(icd, MT9M001_RESET, 1);
++ if (ret >= 0)
++ ret = reg_write(icd, MT9M001_RESET, 0);
++ if (ret >= 0)
++ ret = reg_write(icd, MT9M001_OUTPUT_CONTROL, 0);
++
++ return ret >= 0 ? 0 : -EIO;
++}
++
++static int mt9m001_release(struct soc_camera_device *icd)
++{
++ /* Disable the chip */
++ reg_write(icd, MT9M001_OUTPUT_CONTROL, 0);
++ return 0;
++}
++
++static int mt9m001_start_capture(struct soc_camera_device *icd)
++{
++ /* Switch to master "normal" mode */
++ if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 2) < 0)
++ return -EIO;
++ return 0;
++}
++
++static int mt9m001_stop_capture(struct soc_camera_device *icd)
++{
++ /* Stop sensor readout */
++ if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 0) < 0)
++ return -EIO;
++ return 0;
++}
++
++static int bus_switch_request(struct mt9m001 *mt9m001,
++ struct soc_camera_link *icl)
++{
++#ifdef CONFIG_MT9M001_PCA9536_SWITCH
++ int ret;
++ unsigned int gpio = icl->gpio;
++
++ if (gpio_is_valid(gpio)) {
++ /* We have a data bus switch. */
++ ret = gpio_request(gpio, "mt9m001");
++ if (ret < 0) {
++ dev_err(&mt9m001->client->dev, "Cannot get GPIO %u\n",
++ gpio);
++ return ret;
++ }
++
++ ret = gpio_direction_output(gpio, 0);
++ if (ret < 0) {
++ dev_err(&mt9m001->client->dev,
++ "Cannot set GPIO %u to output\n", gpio);
++ gpio_free(gpio);
++ return ret;
++ }
++ }
++
++ mt9m001->switch_gpio = gpio;
++#else
++ mt9m001->switch_gpio = -EINVAL;
++#endif
++ return 0;
++}
++
++static void bus_switch_release(struct mt9m001 *mt9m001)
++{
++#ifdef CONFIG_MT9M001_PCA9536_SWITCH
++ if (gpio_is_valid(mt9m001->switch_gpio))
++ gpio_free(mt9m001->switch_gpio);
++#endif
++}
++
++static int bus_switch_act(struct mt9m001 *mt9m001, int go8bit)
++{
++#ifdef CONFIG_MT9M001_PCA9536_SWITCH
++ if (!gpio_is_valid(mt9m001->switch_gpio))
++ return -ENODEV;
++
++ gpio_set_value_cansleep(mt9m001->switch_gpio, go8bit);
++ return 0;
++#else
++ return -ENODEV;
++#endif
++}
++
++static int bus_switch_possible(struct mt9m001 *mt9m001)
++{
++#ifdef CONFIG_MT9M001_PCA9536_SWITCH
++ return gpio_is_valid(mt9m001->switch_gpio);
++#else
++ return 0;
++#endif
++}
++
++static int mt9m001_set_bus_param(struct soc_camera_device *icd,
++ unsigned long flags)
++{
++ struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
++ unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
++ int ret;
++
++ /* Flags validity verified in test_bus_param */
++
++ if ((mt9m001->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) ||
++ (mt9m001->datawidth != 9 && (width_flag == SOCAM_DATAWIDTH_9)) ||
++ (mt9m001->datawidth != 8 && (width_flag == SOCAM_DATAWIDTH_8))) {
++ /* Well, we actually only can do 10 or 8 bits... */
++ if (width_flag == SOCAM_DATAWIDTH_9)
++ return -EINVAL;
++ ret = bus_switch_act(mt9m001,
++ width_flag == SOCAM_DATAWIDTH_8);
++ if (ret < 0)
++ return ret;
++
++ mt9m001->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10;
++ }
++
++ return 0;
++}
++
++static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
++{
++ struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
++ unsigned int width_flag = SOCAM_DATAWIDTH_10;
++
++ if (bus_switch_possible(mt9m001))
++ width_flag |= SOCAM_DATAWIDTH_8;
++
++ /* MT9M001 has all capture_format parameters fixed */
++ return SOCAM_PCLK_SAMPLE_RISING |
++ SOCAM_HSYNC_ACTIVE_HIGH |
++ SOCAM_VSYNC_ACTIVE_HIGH |
++ SOCAM_MASTER |
++ width_flag;
++}
++
++static int mt9m001_set_fmt_cap(struct soc_camera_device *icd,
++ __u32 pixfmt, struct v4l2_rect *rect)
++{
++ struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
++ int ret;
++ const u16 hblank = 9, vblank = 25;
++
++ /* Blanking and start values - default... */
++ ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank);
++ if (ret >= 0)
++ ret = reg_write(icd, MT9M001_VERTICAL_BLANKING, vblank);
++
++ /* The caller provides a supported format, as verified per
++ * call to icd->try_fmt_cap() */
++ if (ret >= 0)
++ ret = reg_write(icd, MT9M001_COLUMN_START, rect->left);
++ if (ret >= 0)
++ ret = reg_write(icd, MT9M001_ROW_START, rect->top);
++ if (ret >= 0)
++ ret = reg_write(icd, MT9M001_WINDOW_WIDTH, rect->width - 1);
++ if (ret >= 0)
++ ret = reg_write(icd, MT9M001_WINDOW_HEIGHT,
++ rect->height + icd->y_skip_top - 1);
++ if (ret >= 0 && mt9m001->autoexposure) {
++ ret = reg_write(icd, MT9M001_SHUTTER_WIDTH,
++ rect->height + icd->y_skip_top + vblank);
++ if (ret >= 0) {
++ const struct v4l2_queryctrl *qctrl =
++ soc_camera_find_qctrl(icd->ops,
++ V4L2_CID_EXPOSURE);
++ icd->exposure = (524 + (rect->height + icd->y_skip_top +
++ vblank - 1) *
++ (qctrl->maximum - qctrl->minimum)) /
++ 1048 + qctrl->minimum;
++ }
++ }
++
++ return ret < 0 ? ret : 0;
++}
++
++static int mt9m001_try_fmt_cap(struct soc_camera_device *icd,
++ struct v4l2_format *f)
++{
++ if (f->fmt.pix.height < 32 + icd->y_skip_top)
++ f->fmt.pix.height = 32 + icd->y_skip_top;
++ if (f->fmt.pix.height > 1024 + icd->y_skip_top)
++ f->fmt.pix.height = 1024 + icd->y_skip_top;
++ if (f->fmt.pix.width < 48)
++ f->fmt.pix.width = 48;
++ if (f->fmt.pix.width > 1280)
++ f->fmt.pix.width = 1280;
++ f->fmt.pix.width &= ~0x01; /* has to be even, unsure why was ~3 */
++
++ return 0;
++}
++
++static int mt9m001_get_chip_id(struct soc_camera_device *icd,
++ struct v4l2_chip_ident *id)
++{
++ struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
++
++ if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR)
++ return -EINVAL;
++
++ if (id->match_chip != mt9m001->client->addr)
++ return -ENODEV;
++
++ id->ident = mt9m001->model;
++ id->revision = 0;
++
++ return 0;
++}
++
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++static int mt9m001_get_register(struct soc_camera_device *icd,
++ struct v4l2_register *reg)
++{
++ struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
++
++ if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
++ return -EINVAL;
++
++ if (reg->match_chip != mt9m001->client->addr)
++ return -ENODEV;
++
++ reg->val = reg_read(icd, reg->reg);
++
++ if (reg->val > 0xffff)
++ return -EIO;
++
++ return 0;
++}
++
++static int mt9m001_set_register(struct soc_camera_device *icd,
++ struct v4l2_register *reg)
++{
++ struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
++
++ if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
++ return -EINVAL;
++
++ if (reg->match_chip != mt9m001->client->addr)
++ return -ENODEV;
++
++ if (reg_write(icd, reg->reg, reg->val) < 0)
++ return -EIO;
++
++ return 0;
++}
++#endif
++
++const struct v4l2_queryctrl mt9m001_controls[] = {
++ {
++ .id = V4L2_CID_VFLIP,
++ .type = V4L2_CTRL_TYPE_BOOLEAN,
++ .name = "Flip Vertically",
++ .minimum = 0,
++ .maximum = 1,
++ .step = 1,
++ .default_value = 0,
++ }, {
++ .id = V4L2_CID_GAIN,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "Gain",
++ .minimum = 0,
++ .maximum = 127,
++ .step = 1,
++ .default_value = 64,
++ .flags = V4L2_CTRL_FLAG_SLIDER,
++ }, {
++ .id = V4L2_CID_EXPOSURE,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "Exposure",
++ .minimum = 1,
++ .maximum = 255,
++ .step = 1,
++ .default_value = 255,
++ .flags = V4L2_CTRL_FLAG_SLIDER,
++ }, {
++ .id = V4L2_CID_EXPOSURE_AUTO,
++ .type = V4L2_CTRL_TYPE_BOOLEAN,
++ .name = "Automatic Exposure",
++ .minimum = 0,
++ .maximum = 1,
++ .step = 1,
++ .default_value = 1,
++ }
++};
++
++static int mt9m001_video_probe(struct soc_camera_device *);
++static void mt9m001_video_remove(struct soc_camera_device *);
++static int mt9m001_get_control(struct soc_camera_device *, struct v4l2_control *);
++static int mt9m001_set_control(struct soc_camera_device *, struct v4l2_control *);
++
++static struct soc_camera_ops mt9m001_ops = {
++ .owner = THIS_MODULE,
++ .probe = mt9m001_video_probe,
++ .remove = mt9m001_video_remove,
++ .init = mt9m001_init,
++ .release = mt9m001_release,
++ .start_capture = mt9m001_start_capture,
++ .stop_capture = mt9m001_stop_capture,
++ .set_fmt_cap = mt9m001_set_fmt_cap,
++ .try_fmt_cap = mt9m001_try_fmt_cap,
++ .set_bus_param = mt9m001_set_bus_param,
++ .query_bus_param = mt9m001_query_bus_param,
++ .controls = mt9m001_controls,
++ .num_controls = ARRAY_SIZE(mt9m001_controls),
++ .get_control = mt9m001_get_control,
++ .set_control = mt9m001_set_control,
++ .get_chip_id = mt9m001_get_chip_id,
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++ .get_register = mt9m001_get_register,
++ .set_register = mt9m001_set_register,
++#endif
++};
++
++static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
++{
++ struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
++ int data;
++
++ switch (ctrl->id) {
++ case V4L2_CID_VFLIP:
++ data = reg_read(icd, MT9M001_READ_OPTIONS2);
++ if (data < 0)
++ return -EIO;
++ ctrl->value = !!(data & 0x8000);
++ break;
++ case V4L2_CID_EXPOSURE_AUTO:
++ ctrl->value = mt9m001->autoexposure;
++ break;
++ }
++ return 0;
++}
++
++static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
++{
++ struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
++ const struct v4l2_queryctrl *qctrl;
++ int data;
++
++ qctrl = soc_camera_find_qctrl(&mt9m001_ops, ctrl->id);
++
++ if (!qctrl)
++ return -EINVAL;
++
++ switch (ctrl->id) {
++ case V4L2_CID_VFLIP:
++ if (ctrl->value)
++ data = reg_set(icd, MT9M001_READ_OPTIONS2, 0x8000);
++ else
++ data = reg_clear(icd, MT9M001_READ_OPTIONS2, 0x8000);
++ if (data < 0)
++ return -EIO;
++ break;
++ case V4L2_CID_GAIN:
++ if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
++ return -EINVAL;
++ /* See Datasheet Table 7, Gain settings. */
++ if (ctrl->value <= qctrl->default_value) {
++ /* Pack it into 0..1 step 0.125, register values 0..8 */
++ unsigned long range = qctrl->default_value - qctrl->minimum;
++ data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range;
++
++ dev_dbg(&icd->dev, "Setting gain %d\n", data);
++ data = reg_write(icd, MT9M001_GLOBAL_GAIN, data);
++ if (data < 0)
++ return -EIO;
++ } else {
++ /* Pack it into 1.125..15 variable step, register values 9..67 */
++ /* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */
++ unsigned long range = qctrl->maximum - qctrl->default_value - 1;
++ unsigned long gain = ((ctrl->value - qctrl->default_value - 1) *
++ 111 + range / 2) / range + 9;
++
++ if (gain <= 32)
++ data = gain;
++ else if (gain <= 64)
++ data = ((gain - 32) * 16 + 16) / 32 + 80;
++ else
++ data = ((gain - 64) * 7 + 28) / 56 + 96;
++
++ dev_dbg(&icd->dev, "Setting gain from %d to %d\n",
++ reg_read(icd, MT9M001_GLOBAL_GAIN), data);
++ data = reg_write(icd, MT9M001_GLOBAL_GAIN, data);
++ if (data < 0)
++ return -EIO;
++ }
++
++ /* Success */
++ icd->gain = ctrl->value;
++ break;
++ case V4L2_CID_EXPOSURE:
++ /* mt9m001 has maximum == default */
++ if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
++ return -EINVAL;
++ else {
++ unsigned long range = qctrl->maximum - qctrl->minimum;
++ unsigned long shutter = ((ctrl->value - qctrl->minimum) * 1048 +
++ range / 2) / range + 1;
++
++ dev_dbg(&icd->dev, "Setting shutter width from %d to %lu\n",
++ reg_read(icd, MT9M001_SHUTTER_WIDTH), shutter);
++ if (reg_write(icd, MT9M001_SHUTTER_WIDTH, shutter) < 0)
++ return -EIO;
++ icd->exposure = ctrl->value;
++ mt9m001->autoexposure = 0;
++ }
++ break;
++ case V4L2_CID_EXPOSURE_AUTO:
++ if (ctrl->value) {
++ const u16 vblank = 25;
++ if (reg_write(icd, MT9M001_SHUTTER_WIDTH, icd->height +
++ icd->y_skip_top + vblank) < 0)
++ return -EIO;
++ qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
++ icd->exposure = (524 + (icd->height + icd->y_skip_top + vblank - 1) *
++ (qctrl->maximum - qctrl->minimum)) /
++ 1048 + qctrl->minimum;
++ mt9m001->autoexposure = 1;
++ } else
++ mt9m001->autoexposure = 0;
++ break;
++ }
++ return 0;
++}
++
++/* Interface active, can use i2c. If it fails, it can indeed mean, that
++ * this wasn't our capture interface, so, we wait for the right one */
++static int mt9m001_video_probe(struct soc_camera_device *icd)
++{
++ struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
++ s32 data;
++ int ret;
++
++ /* We must have a parent by now. And it cannot be a wrong one.
++ * So this entire test is completely redundant. */
++ if (!icd->dev.parent ||
++ to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
++ return -ENODEV;
++
++ /* Enable the chip */
++ data = reg_write(&mt9m001->icd, MT9M001_CHIP_ENABLE, 1);
++ dev_dbg(&icd->dev, "write: %d\n", data);
++
++ /* Read out the chip version register */
++ data = reg_read(icd, MT9M001_CHIP_VERSION);
++
++ /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
++ switch (data) {
++ case 0x8411:
++ case 0x8421:
++ mt9m001->model = V4L2_IDENT_MT9M001C12ST;
++ icd->formats = mt9m001_colour_formats;
++ if (mt9m001->client->dev.platform_data)
++ icd->num_formats = ARRAY_SIZE(mt9m001_colour_formats);
++ else
++ icd->num_formats = 1;
++ break;
++ case 0x8431:
++ mt9m001->model = V4L2_IDENT_MT9M001C12STM;
++ icd->formats = mt9m001_monochrome_formats;
++ if (mt9m001->client->dev.platform_data)
++ icd->num_formats = ARRAY_SIZE(mt9m001_monochrome_formats);
++ else
++ icd->num_formats = 1;
++ break;
++ default:
++ ret = -ENODEV;
++ dev_err(&icd->dev,
++ "No MT9M001 chip detected, register read %x\n", data);
++ goto ei2c;
++ }
++
++ dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data,
++ data == 0x8431 ? "C12STM" : "C12ST");
++
++ /* Now that we know the model, we can start video */
++ ret = soc_camera_video_start(icd);
++ if (ret)
++ goto eisis;
++
++ return 0;
++
++eisis:
++ei2c:
++ return ret;
++}
++
++static void mt9m001_video_remove(struct soc_camera_device *icd)
++{
++ struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
++
++ dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr,
++ mt9m001->icd.dev.parent, mt9m001->icd.vdev);
++ soc_camera_video_stop(&mt9m001->icd);
++}
++
++static int mt9m001_probe(struct i2c_client *client)
++{
++ struct mt9m001 *mt9m001;
++ struct soc_camera_device *icd;
++ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
++ struct soc_camera_link *icl = client->dev.platform_data;
++ int ret;
++
++ if (!icl) {
++ dev_err(&client->dev, "MT9M001 driver needs platform data\n");
++ return -EINVAL;
++ }
++
++ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
++ dev_warn(&adapter->dev,
++ "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
++ return -EIO;
++ }
++
++ mt9m001 = kzalloc(sizeof(struct mt9m001), GFP_KERNEL);
++ if (!mt9m001)
++ return -ENOMEM;
++
++ mt9m001->client = client;
++ i2c_set_clientdata(client, mt9m001);
++
++ /* Second stage probe - when a capture adapter is there */
++ icd = &mt9m001->icd;
++ icd->ops = &mt9m001_ops;
++ icd->control = &client->dev;
++ icd->x_min = 20;
++ icd->y_min = 12;
++ icd->x_current = 20;
++ icd->y_current = 12;
++ icd->width_min = 48;
++ icd->width_max = 1280;
++ icd->height_min = 32;
++ icd->height_max = 1024;
++ icd->y_skip_top = 1;
++ icd->iface = icl->bus_id;
++ /* Default datawidth - this is the only width this camera (normally)
++ * supports. It is only with extra logic that it can support
++ * other widths. Therefore it seems to be a sensible default. */
++ mt9m001->datawidth = 10;
++ /* Simulated autoexposure. If enabled, we calculate shutter width
++ * ourselves in the driver based on vertical blanking and frame width */
++ mt9m001->autoexposure = 1;
++
++ ret = bus_switch_request(mt9m001, icl);
++ if (ret)
++ goto eswinit;
++
++ ret = soc_camera_device_register(icd);
++ if (ret)
++ goto eisdr;
++
++ return 0;
++
++eisdr:
++ bus_switch_release(mt9m001);
++eswinit:
++ kfree(mt9m001);
++ return ret;
++}
++
++static int mt9m001_remove(struct i2c_client *client)
++{
++ struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
++
++ soc_camera_device_unregister(&mt9m001->icd);
++ bus_switch_release(mt9m001);
++ kfree(mt9m001);
++
++ return 0;
++}
++
++static struct i2c_driver mt9m001_i2c_driver = {
++ .driver = {
++ .name = "mt9m001",
++ },
++ .probe = mt9m001_probe,
++ .remove = mt9m001_remove,
++};
++
++static int __init mt9m001_mod_init(void)
++{
++ return i2c_add_driver(&mt9m001_i2c_driver);
++}
++
++static void __exit mt9m001_mod_exit(void)
++{
++ i2c_del_driver(&mt9m001_i2c_driver);
++}
++
++module_init(mt9m001_mod_init);
++module_exit(mt9m001_mod_exit);
++
++MODULE_DESCRIPTION("Micron MT9M001 Camera driver");
++MODULE_AUTHOR("Guennadi Liakhovetski <kernel at pengutronix.de>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
+new file mode 100644
+index 0000000..d4b9e27
+--- /dev/null
++++ b/drivers/media/video/mt9v022.c
+@@ -0,0 +1,844 @@
++/*
++ * Driver for MT9V022 CMOS Image Sensor from Micron
++ *
++ * Copyright (C) 2008, Guennadi Liakhovetski <kernel at pengutronix.de>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/videodev2.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/delay.h>
++#include <linux/log2.h>
++
++#include <media/v4l2-common.h>
++#include <media/v4l2-chip-ident.h>
++#include <media/soc_camera.h>
++
++#ifdef CONFIG_MT9M001_PCA9536_SWITCH
++#include <asm/gpio.h>
++#endif
++
++/* mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c
++ * The platform has to define i2c_board_info
++ * and call i2c_register_board_info() */
++
++static char *sensor_type;
++module_param(sensor_type, charp, S_IRUGO);
++MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\"\n");
++
++/* mt9v022 selected register addresses */
++#define MT9V022_CHIP_VERSION 0x00
++#define MT9V022_COLUMN_START 0x01
++#define MT9V022_ROW_START 0x02
++#define MT9V022_WINDOW_HEIGHT 0x03
++#define MT9V022_WINDOW_WIDTH 0x04
++#define MT9V022_HORIZONTAL_BLANKING 0x05
++#define MT9V022_VERTICAL_BLANKING 0x06
++#define MT9V022_CHIP_CONTROL 0x07
++#define MT9V022_SHUTTER_WIDTH1 0x08
++#define MT9V022_SHUTTER_WIDTH2 0x09
++#define MT9V022_SHUTTER_WIDTH_CTRL 0x0a
++#define MT9V022_TOTAL_SHUTTER_WIDTH 0x0b
++#define MT9V022_RESET 0x0c
++#define MT9V022_READ_MODE 0x0d
++#define MT9V022_MONITOR_MODE 0x0e
++#define MT9V022_PIXEL_OPERATION_MODE 0x0f
++#define MT9V022_LED_OUT_CONTROL 0x1b
++#define MT9V022_ADC_MODE_CONTROL 0x1c
++#define MT9V022_ANALOG_GAIN 0x34
++#define MT9V022_BLACK_LEVEL_CALIB_CTRL 0x47
++#define MT9V022_PIXCLK_FV_LV 0x74
++#define MT9V022_DIGITAL_TEST_PATTERN 0x7f
++#define MT9V022_AEC_AGC_ENABLE 0xAF
++#define MT9V022_MAX_TOTAL_SHUTTER_WIDTH 0xBD
++
++/* Progressive scan, master, defaults */
++#define MT9V022_CHIP_CONTROL_DEFAULT 0x188
++
++static const struct soc_camera_data_format mt9v022_colour_formats[] = {
++ /* Order important: first natively supported,
++ * second supported with a GPIO extender */
++ {
++ .name = "Bayer (sRGB) 10 bit",
++ .depth = 10,
++ .fourcc = V4L2_PIX_FMT_SBGGR16,
++ .colorspace = V4L2_COLORSPACE_SRGB,
++ }, {
++ .name = "Bayer (sRGB) 8 bit",
++ .depth = 8,
++ .fourcc = V4L2_PIX_FMT_SBGGR8,
++ .colorspace = V4L2_COLORSPACE_SRGB,
++ }
++};
++
++static const struct soc_camera_data_format mt9v022_monochrome_formats[] = {
++ /* Order important - see above */
++ {
++ .name = "Monochrome 10 bit",
++ .depth = 10,
++ .fourcc = V4L2_PIX_FMT_Y16,
++ }, {
++ .name = "Monochrome 8 bit",
++ .depth = 8,
++ .fourcc = V4L2_PIX_FMT_GREY,
++ },
++};
++
++struct mt9v022 {
++ struct i2c_client *client;
++ struct soc_camera_device icd;
++ int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
++ int switch_gpio;
++ u16 chip_control;
++ unsigned char datawidth;
++};
++
++static int reg_read(struct soc_camera_device *icd, const u8 reg)
++{
++ struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++ struct i2c_client *client = mt9v022->client;
++ s32 data = i2c_smbus_read_word_data(client, reg);
++ return data < 0 ? data : swab16(data);
++}
++
++static int reg_write(struct soc_camera_device *icd, const u8 reg,
++ const u16 data)
++{
++ struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++ return i2c_smbus_write_word_data(mt9v022->client, reg, swab16(data));
++}
++
++static int reg_set(struct soc_camera_device *icd, const u8 reg,
++ const u16 data)
++{
++ int ret;
++
++ ret = reg_read(icd, reg);
++ if (ret < 0)
++ return ret;
++ return reg_write(icd, reg, ret | data);
++}
++
++static int reg_clear(struct soc_camera_device *icd, const u8 reg,
++ const u16 data)
++{
++ int ret;
++
++ ret = reg_read(icd, reg);
++ if (ret < 0)
++ return ret;
++ return reg_write(icd, reg, ret & ~data);
++}
++
++static int mt9v022_init(struct soc_camera_device *icd)
++{
++ struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++ int ret;
++
++ /* Almost the default mode: master, parallel, simultaneous, and an
++ * undocumented bit 0x200, which is present in table 7, but not in 8,
++ * plus snapshot mode to disable scan for now */
++ mt9v022->chip_control |= 0x10;
++ ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
++ if (ret >= 0)
++ reg_write(icd, MT9V022_READ_MODE, 0x300);
++
++ /* All defaults */
++ if (ret >= 0)
++ /* AEC, AGC on */
++ ret = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x3);
++ if (ret >= 0)
++ ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480);
++ if (ret >= 0)
++ /* default - auto */
++ ret = reg_clear(icd, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1);
++ if (ret >= 0)
++ ret = reg_write(icd, MT9V022_DIGITAL_TEST_PATTERN, 0);
++
++ return ret >= 0 ? 0 : -EIO;
++}
++
++static int mt9v022_release(struct soc_camera_device *icd)
++{
++ /* Nothing? */
++ return 0;
++}
++
++static int mt9v022_start_capture(struct soc_camera_device *icd)
++{
++ struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++ /* Switch to master "normal" mode */
++ mt9v022->chip_control &= ~0x10;
++ if (reg_write(icd, MT9V022_CHIP_CONTROL,
++ mt9v022->chip_control) < 0)
++ return -EIO;
++ return 0;
++}
++
++static int mt9v022_stop_capture(struct soc_camera_device *icd)
++{
++ struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++ /* Switch to snapshot mode */
++ mt9v022->chip_control |= 0x10;
++ if (reg_write(icd, MT9V022_CHIP_CONTROL,
++ mt9v022->chip_control) < 0)
++ return -EIO;
++ return 0;
++}
++
++static int bus_switch_request(struct mt9v022 *mt9v022, struct soc_camera_link *icl)
++{
++#ifdef CONFIG_MT9V022_PCA9536_SWITCH
++ int ret;
++ unsigned int gpio = icl->gpio;
++
++ if (gpio_is_valid(gpio)) {
++ /* We have a data bus switch. */
++ ret = gpio_request(gpio, "mt9v022");
++ if (ret < 0) {
++ dev_err(&mt9v022->client->dev, "Cannot get GPIO %u\n", gpio);
++ return ret;
++ }
++
++ ret = gpio_direction_output(gpio, 0);
++ if (ret < 0) {
++ dev_err(&mt9v022->client->dev,
++ "Cannot set GPIO %u to output\n", gpio);
++ gpio_free(gpio);
++ return ret;
++ }
++ }
++
++ mt9v022->switch_gpio = gpio;
++#else
++ mt9v022->switch_gpio = -EINVAL;
++#endif
++ return 0;
++}
++
++static void bus_switch_release(struct mt9v022 *mt9v022)
++{
++#ifdef CONFIG_MT9V022_PCA9536_SWITCH
++ if (gpio_is_valid(mt9v022->switch_gpio))
++ gpio_free(mt9v022->switch_gpio);
++#endif
++}
++
++static int bus_switch_act(struct mt9v022 *mt9v022, int go8bit)
++{
++#ifdef CONFIG_MT9V022_PCA9536_SWITCH
++ if (!gpio_is_valid(mt9v022->switch_gpio))
++ return -ENODEV;
++
++ gpio_set_value_cansleep(mt9v022->switch_gpio, go8bit);
++ return 0;
++#else
++ return -ENODEV;
++#endif
++}
++
++static int bus_switch_possible(struct mt9v022 *mt9v022)
++{
++#ifdef CONFIG_MT9V022_PCA9536_SWITCH
++ return gpio_is_valid(mt9v022->switch_gpio);
++#else
++ return 0;
++#endif
++}
++
++static int mt9v022_set_bus_param(struct soc_camera_device *icd,
++ unsigned long flags)
++{
++ struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++ unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
++ int ret;
++ u16 pixclk = 0;
++
++ /* Only one width bit may be set */
++ if (!is_power_of_2(width_flag))
++ return -EINVAL;
++
++ if ((mt9v022->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) ||
++ (mt9v022->datawidth != 9 && (width_flag == SOCAM_DATAWIDTH_9)) ||
++ (mt9v022->datawidth != 8 && (width_flag == SOCAM_DATAWIDTH_8))) {
++ /* Well, we actually only can do 10 or 8 bits... */
++ if (width_flag == SOCAM_DATAWIDTH_9)
++ return -EINVAL;
++
++ ret = bus_switch_act(mt9v022,
++ width_flag == SOCAM_DATAWIDTH_8);
++ if (ret < 0)
++ return ret;
++
++ mt9v022->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10;
++ }
++
++ if (flags & SOCAM_PCLK_SAMPLE_RISING)
++ pixclk |= 0x10;
++
++ if (!(flags & SOCAM_HSYNC_ACTIVE_HIGH))
++ pixclk |= 0x1;
++
++ if (!(flags & SOCAM_VSYNC_ACTIVE_HIGH))
++ pixclk |= 0x2;
++
++ ret = reg_write(icd, MT9V022_PIXCLK_FV_LV, pixclk);
++ if (ret < 0)
++ return ret;
++
++ if (!(flags & SOCAM_MASTER))
++ mt9v022->chip_control &= ~0x8;
++
++ ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
++ if (ret < 0)
++ return ret;
++
++ dev_dbg(&icd->dev, "Calculated pixclk 0x%x, chip control 0x%x\n",
++ pixclk, mt9v022->chip_control);
++
++ return 0;
++}
++
++static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
++{
++ struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++ unsigned int width_flag = SOCAM_DATAWIDTH_10;
++
++ if (bus_switch_possible(mt9v022))
++ width_flag |= SOCAM_DATAWIDTH_8;
++
++ return SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING |
++ SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW |
++ SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW |
++ SOCAM_MASTER | SOCAM_SLAVE |
++ width_flag;
++}
++
++static int mt9v022_set_fmt_cap(struct soc_camera_device *icd,
++ __u32 pixfmt, struct v4l2_rect *rect)
++{
++ struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++ int ret;
++
++ /* The caller provides a supported format, as verified per call to
++ * icd->try_fmt_cap(), datawidth is from our supported format list */
++ switch (pixfmt) {
++ case V4L2_PIX_FMT_GREY:
++ case V4L2_PIX_FMT_Y16:
++ if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM)
++ return -EINVAL;
++ break;
++ case V4L2_PIX_FMT_SBGGR8:
++ case V4L2_PIX_FMT_SBGGR16:
++ if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC)
++ return -EINVAL;
++ break;
++ case 0:
++ /* No format change, only geometry */
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ /* Like in example app. Contradicts the datasheet though */
++ ret = reg_read(icd, MT9V022_AEC_AGC_ENABLE);
++ if (ret >= 0) {
++ if (ret & 1) /* Autoexposure */
++ ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH,
++ rect->height + icd->y_skip_top + 43);
++ else
++ ret = reg_write(icd, MT9V022_TOTAL_SHUTTER_WIDTH,
++ rect->height + icd->y_skip_top + 43);
++ }
++ /* Setup frame format: defaults apart from width and height */
++ if (ret >= 0)
++ ret = reg_write(icd, MT9V022_COLUMN_START, rect->left);
++ if (ret >= 0)
++ ret = reg_write(icd, MT9V022_ROW_START, rect->top);
++ if (ret >= 0)
++ /* Default 94, Phytec driver says:
++ * "width + horizontal blank >= 660" */
++ ret = reg_write(icd, MT9V022_HORIZONTAL_BLANKING,
++ rect->width > 660 - 43 ? 43 :
++ 660 - rect->width);
++ if (ret >= 0)
++ ret = reg_write(icd, MT9V022_VERTICAL_BLANKING, 45);
++ if (ret >= 0)
++ ret = reg_write(icd, MT9V022_WINDOW_WIDTH, rect->width);
++ if (ret >= 0)
++ ret = reg_write(icd, MT9V022_WINDOW_HEIGHT,
++ rect->height + icd->y_skip_top);
++
++ if (ret < 0)
++ return ret;
++
++ dev_dbg(&icd->dev, "Frame %ux%u pixel\n", rect->width, rect->height);
++
++ return 0;
++}
++
++static int mt9v022_try_fmt_cap(struct soc_camera_device *icd,
++ struct v4l2_format *f)
++{
++ if (f->fmt.pix.height < 32 + icd->y_skip_top)
++ f->fmt.pix.height = 32 + icd->y_skip_top;
++ if (f->fmt.pix.height > 480 + icd->y_skip_top)
++ f->fmt.pix.height = 480 + icd->y_skip_top;
++ if (f->fmt.pix.width < 48)
++ f->fmt.pix.width = 48;
++ if (f->fmt.pix.width > 752)
++ f->fmt.pix.width = 752;
++ f->fmt.pix.width &= ~0x03; /* ? */
++
++ return 0;
++}
++
++static int mt9v022_get_chip_id(struct soc_camera_device *icd,
++ struct v4l2_chip_ident *id)
++{
++ struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++
++ if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR)
++ return -EINVAL;
++
++ if (id->match_chip != mt9v022->client->addr)
++ return -ENODEV;
++
++ id->ident = mt9v022->model;
++ id->revision = 0;
++
++ return 0;
++}
++
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++static int mt9v022_get_register(struct soc_camera_device *icd,
++ struct v4l2_register *reg)
++{
++ struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++
++ if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
++ return -EINVAL;
++
++ if (reg->match_chip != mt9v022->client->addr)
++ return -ENODEV;
++
++ reg->val = reg_read(icd, reg->reg);
++
++ if (reg->val > 0xffff)
++ return -EIO;
++
++ return 0;
++}
++
++static int mt9v022_set_register(struct soc_camera_device *icd,
++ struct v4l2_register *reg)
++{
++ struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++
++ if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
++ return -EINVAL;
++
++ if (reg->match_chip != mt9v022->client->addr)
++ return -ENODEV;
++
++ if (reg_write(icd, reg->reg, reg->val) < 0)
++ return -EIO;
++
++ return 0;
++}
++#endif
++
++const struct v4l2_queryctrl mt9v022_controls[] = {
++ {
++ .id = V4L2_CID_VFLIP,
++ .type = V4L2_CTRL_TYPE_BOOLEAN,
++ .name = "Flip Vertically",
++ .minimum = 0,
++ .maximum = 1,
++ .step = 1,
++ .default_value = 0,
++ }, {
++ .id = V4L2_CID_HFLIP,
++ .type = V4L2_CTRL_TYPE_BOOLEAN,
++ .name = "Flip Horizontally",
++ .minimum = 0,
++ .maximum = 1,
++ .step = 1,
++ .default_value = 0,
++ }, {
++ .id = V4L2_CID_GAIN,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "Analog Gain",
++ .minimum = 64,
++ .maximum = 127,
++ .step = 1,
++ .default_value = 64,
++ .flags = V4L2_CTRL_FLAG_SLIDER,
++ }, {
++ .id = V4L2_CID_EXPOSURE,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "Exposure",
++ .minimum = 1,
++ .maximum = 255,
++ .step = 1,
++ .default_value = 255,
++ .flags = V4L2_CTRL_FLAG_SLIDER,
++ }, {
++ .id = V4L2_CID_AUTOGAIN,
++ .type = V4L2_CTRL_TYPE_BOOLEAN,
++ .name = "Automatic Gain",
++ .minimum = 0,
++ .maximum = 1,
++ .step = 1,
++ .default_value = 1,
++ }, {
++ .id = V4L2_CID_EXPOSURE_AUTO,
++ .type = V4L2_CTRL_TYPE_BOOLEAN,
++ .name = "Automatic Exposure",
++ .minimum = 0,
++ .maximum = 1,
++ .step = 1,
++ .default_value = 1,
++ }
++};
++
++static int mt9v022_video_probe(struct soc_camera_device *);
++static void mt9v022_video_remove(struct soc_camera_device *);
++static int mt9v022_get_control(struct soc_camera_device *, struct v4l2_control *);
++static int mt9v022_set_control(struct soc_camera_device *, struct v4l2_control *);
++
++static struct soc_camera_ops mt9v022_ops = {
++ .owner = THIS_MODULE,
++ .probe = mt9v022_video_probe,
++ .remove = mt9v022_video_remove,
++ .init = mt9v022_init,
++ .release = mt9v022_release,
++ .start_capture = mt9v022_start_capture,
++ .stop_capture = mt9v022_stop_capture,
++ .set_fmt_cap = mt9v022_set_fmt_cap,
++ .try_fmt_cap = mt9v022_try_fmt_cap,
++ .set_bus_param = mt9v022_set_bus_param,
++ .query_bus_param = mt9v022_query_bus_param,
++ .controls = mt9v022_controls,
++ .num_controls = ARRAY_SIZE(mt9v022_controls),
++ .get_control = mt9v022_get_control,
++ .set_control = mt9v022_set_control,
++ .get_chip_id = mt9v022_get_chip_id,
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++ .get_register = mt9v022_get_register,
++ .set_register = mt9v022_set_register,
++#endif
++};
++
++static int mt9v022_get_control(struct soc_camera_device *icd,
++ struct v4l2_control *ctrl)
++{
++ int data;
++
++ switch (ctrl->id) {
++ case V4L2_CID_VFLIP:
++ data = reg_read(icd, MT9V022_READ_MODE);
++ if (data < 0)
++ return -EIO;
++ ctrl->value = !!(data & 0x10);
++ break;
++ case V4L2_CID_HFLIP:
++ data = reg_read(icd, MT9V022_READ_MODE);
++ if (data < 0)
++ return -EIO;
++ ctrl->value = !!(data & 0x20);
++ break;
++ case V4L2_CID_EXPOSURE_AUTO:
++ data = reg_read(icd, MT9V022_AEC_AGC_ENABLE);
++ if (data < 0)
++ return -EIO;
++ ctrl->value = !!(data & 0x1);
++ break;
++ case V4L2_CID_AUTOGAIN:
++ data = reg_read(icd, MT9V022_AEC_AGC_ENABLE);
++ if (data < 0)
++ return -EIO;
++ ctrl->value = !!(data & 0x2);
++ break;
++ }
++ return 0;
++}
++
++static int mt9v022_set_control(struct soc_camera_device *icd,
++ struct v4l2_control *ctrl)
++{
++ int data;
++ const struct v4l2_queryctrl *qctrl;
++
++ qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id);
++
++ if (!qctrl)
++ return -EINVAL;
++
++ switch (ctrl->id) {
++ case V4L2_CID_VFLIP:
++ if (ctrl->value)
++ data = reg_set(icd, MT9V022_READ_MODE, 0x10);
++ else
++ data = reg_clear(icd, MT9V022_READ_MODE, 0x10);
++ if (data < 0)
++ return -EIO;
++ break;
++ case V4L2_CID_HFLIP:
++ if (ctrl->value)
++ data = reg_set(icd, MT9V022_READ_MODE, 0x20);
++ else
++ data = reg_clear(icd, MT9V022_READ_MODE, 0x20);
++ if (data < 0)
++ return -EIO;
++ break;
++ case V4L2_CID_GAIN:
++ /* mt9v022 has minimum == default */
++ if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
++ return -EINVAL;
++ else {
++ unsigned long range = qctrl->maximum - qctrl->minimum;
++ /* Datasheet says 16 to 64. autogain only works properly
++ * after setting gain to maximum 14. Larger values
++ * produce "white fly" noise effect. On the whole,
++ * manually setting analog gain does no good. */
++ unsigned long gain = ((ctrl->value - qctrl->minimum) *
++ 10 + range / 2) / range + 4;
++ if (gain >= 32)
++ gain &= ~1;
++ /* The user wants to set gain manually, hope, she
++ * knows, what she's doing... Switch AGC off. */
++
++ if (reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x2) < 0)
++ return -EIO;
++
++ dev_info(&icd->dev, "Setting gain from %d to %lu\n",
++ reg_read(icd, MT9V022_ANALOG_GAIN), gain);
++ if (reg_write(icd, MT9V022_ANALOG_GAIN, gain) < 0)
++ return -EIO;
++ icd->gain = ctrl->value;
++ }
++ break;
++ case V4L2_CID_EXPOSURE:
++ /* mt9v022 has maximum == default */
++ if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
++ return -EINVAL;
++ else {
++ unsigned long range = qctrl->maximum - qctrl->minimum;
++ unsigned long shutter = ((ctrl->value - qctrl->minimum) *
++ 479 + range / 2) / range + 1;
++ /* The user wants to set shutter width manually, hope,
++ * she knows, what she's doing... Switch AEC off. */
++
++ if (reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x1) < 0)
++ return -EIO;
++
++ dev_dbg(&icd->dev, "Shutter width from %d to %lu\n",
++ reg_read(icd, MT9V022_TOTAL_SHUTTER_WIDTH),
++ shutter);
++ if (reg_write(icd, MT9V022_TOTAL_SHUTTER_WIDTH,
++ shutter) < 0)
++ return -EIO;
++ icd->exposure = ctrl->value;
++ }
++ break;
++ case V4L2_CID_AUTOGAIN:
++ if (ctrl->value)
++ data = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x2);
++ else
++ data = reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x2);
++ if (data < 0)
++ return -EIO;
++ break;
++ case V4L2_CID_EXPOSURE_AUTO:
++ if (ctrl->value)
++ data = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x1);
++ else
++ data = reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x1);
++ if (data < 0)
++ return -EIO;
++ break;
++ }
++ return 0;
++}
++
++/* Interface active, can use i2c. If it fails, it can indeed mean, that
++ * this wasn't our capture interface, so, we wait for the right one */
++static int mt9v022_video_probe(struct soc_camera_device *icd)
++{
++ struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++ s32 data;
++ int ret;
++
++ if (!icd->dev.parent ||
++ to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
++ return -ENODEV;
++
++ /* Read out the chip version register */
++ data = reg_read(icd, MT9V022_CHIP_VERSION);
++
++ /* must be 0x1311 or 0x1313 */
++ if (data != 0x1311 && data != 0x1313) {
++ ret = -ENODEV;
++ dev_info(&icd->dev, "No MT9V022 detected, ID register 0x%x\n",
++ data);
++ goto ei2c;
++ }
++
++ /* Soft reset */
++ ret = reg_write(icd, MT9V022_RESET, 1);
++ if (ret < 0)
++ goto ei2c;
++ /* 15 clock cycles */
++ udelay(200);
++ if (reg_read(icd, MT9V022_RESET)) {
++ dev_err(&icd->dev, "Resetting MT9V022 failed!\n");
++ goto ei2c;
++ }
++
++ /* Set monochrome or colour sensor type */
++ if (sensor_type && (!strcmp("colour", sensor_type) ||
++ !strcmp("color", sensor_type))) {
++ ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11);
++ mt9v022->model = V4L2_IDENT_MT9V022IX7ATC;
++ icd->formats = mt9v022_colour_formats;
++ if (mt9v022->client->dev.platform_data)
++ icd->num_formats = ARRAY_SIZE(mt9v022_colour_formats);
++ else
++ icd->num_formats = 1;
++ } else {
++ ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 0x11);
++ mt9v022->model = V4L2_IDENT_MT9V022IX7ATM;
++ icd->formats = mt9v022_monochrome_formats;
++ if (mt9v022->client->dev.platform_data)
++ icd->num_formats = ARRAY_SIZE(mt9v022_monochrome_formats);
++ else
++ icd->num_formats = 1;
++ }
++
++ if (ret >= 0)
++ ret = soc_camera_video_start(icd);
++ if (ret < 0)
++ goto eisis;
++
++ dev_info(&icd->dev, "Detected a MT9V022 chip ID %x, %s sensor\n",
++ data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ?
++ "monochrome" : "colour");
++
++ return 0;
++
++eisis:
++ei2c:
++ return ret;
++}
++
++static void mt9v022_video_remove(struct soc_camera_device *icd)
++{
++ struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
++
++ dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr,
++ mt9v022->icd.dev.parent, mt9v022->icd.vdev);
++ soc_camera_video_stop(&mt9v022->icd);
++}
++
++static int mt9v022_probe(struct i2c_client *client)
++{
++ struct mt9v022 *mt9v022;
++ struct soc_camera_device *icd;
++ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
++ struct soc_camera_link *icl = client->dev.platform_data;
++ int ret;
++
++ if (!icl) {
++ dev_err(&client->dev, "MT9V022 driver needs platform data\n");
++ return -EINVAL;
++ }
++
++ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
++ dev_warn(&adapter->dev,
++ "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
++ return -EIO;
++ }
++
++ mt9v022 = kzalloc(sizeof(struct mt9v022), GFP_KERNEL);
++ if (!mt9v022)
++ return -ENOMEM;
++
++ mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT;
++ mt9v022->client = client;
++ i2c_set_clientdata(client, mt9v022);
++
++ icd = &mt9v022->icd;
++ icd->ops = &mt9v022_ops;
++ icd->control = &client->dev;
++ icd->x_min = 1;
++ icd->y_min = 4;
++ icd->x_current = 1;
++ icd->y_current = 4;
++ icd->width_min = 48;
++ icd->width_max = 752;
++ icd->height_min = 32;
++ icd->height_max = 480;
++ icd->y_skip_top = 1;
++ icd->iface = icl->bus_id;
++ /* Default datawidth - this is the only width this camera (normally)
++ * supports. It is only with extra logic that it can support
++ * other widths. Therefore it seems to be a sensible default. */
++ mt9v022->datawidth = 10;
++
++ ret = bus_switch_request(mt9v022, icl);
++ if (ret)
++ goto eswinit;
++
++ ret = soc_camera_device_register(icd);
++ if (ret)
++ goto eisdr;
++
++ return 0;
++
++eisdr:
++ bus_switch_release(mt9v022);
++eswinit:
++ kfree(mt9v022);
++ return ret;
++}
++
++static int mt9v022_remove(struct i2c_client *client)
++{
++ struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
++
++ soc_camera_device_unregister(&mt9v022->icd);
++ bus_switch_release(mt9v022);
++ kfree(mt9v022);
++
++ return 0;
++}
++
++static struct i2c_driver mt9v022_i2c_driver = {
++ .driver = {
++ .name = "mt9v022",
++ },
++ .probe = mt9v022_probe,
++ .remove = mt9v022_remove,
++};
++
++static int __init mt9v022_mod_init(void)
++{
++ return i2c_add_driver(&mt9v022_i2c_driver);
++}
++
++static void __exit mt9v022_mod_exit(void)
++{
++ i2c_del_driver(&mt9v022_i2c_driver);
++}
++
++module_init(mt9v022_mod_init);
++module_exit(mt9v022_mod_exit);
++
++MODULE_DESCRIPTION("Micron MT9V022 Camera driver");
++MODULE_AUTHOR("Guennadi Liakhovetski <kernel at pengutronix.de>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c
+index cb5a510..f68e91f 100644
+--- a/drivers/media/video/mxb.c
++++ b/drivers/media/video/mxb.c
+@@ -38,7 +38,7 @@
+ #define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0)
+
+ /* global variable */
+-static int mxb_num = 0;
++static int mxb_num;
+
+ /* initial frequence the tuner will be tuned to.
+ in verden (lower saxony, germany) 4148 is a
+@@ -47,7 +47,7 @@ static int freq = 4148;
+ module_param(freq, int, 0644);
+ MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup");
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
+
+diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c
+index d55d580..eafb0c7 100644
+--- a/drivers/media/video/ov511.c
++++ b/drivers/media/video/ov511.c
+@@ -41,7 +41,6 @@
+ #include <linux/slab.h>
+ #include <linux/ctype.h>
+ #include <linux/pagemap.h>
+-#include <asm/semaphore.h>
+ #include <asm/processor.h>
+ #include <linux/mm.h>
+ #include <linux/device.h>
+@@ -4660,7 +4659,9 @@ static const struct file_operations ov511_fops = {
+ .read = ov51x_v4l1_read,
+ .mmap = ov51x_v4l1_mmap,
+ .ioctl = ov51x_v4l1_ioctl,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+@@ -5832,7 +5833,7 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id)
+ goto error;
+
+ memcpy(ov->vdev, &vdev_template, sizeof(*ov->vdev));
+- ov->vdev->dev = &dev->dev;
++ ov->vdev->dev = &intf->dev;
+ video_set_drvdata(ov->vdev, ov);
+
+ for (i = 0; i < OV511_MAX_UNIT_VIDEO; i++) {
+diff --git a/drivers/media/video/ov511.h b/drivers/media/video/ov511.h
+index 18c6422..1010e51 100644
+--- a/drivers/media/video/ov511.h
++++ b/drivers/media/video/ov511.h
+@@ -12,7 +12,7 @@
+ #ifdef OV511_DEBUG
+ #define PDEBUG(level, fmt, args...) \
+ if (debug >= (level)) info("[%s:%d] " fmt, \
+- __FUNCTION__, __LINE__ , ## args)
++ __func__, __LINE__ , ## args)
+ #else
+ #define PDEBUG(level, fmt, args...) do {} while(0)
+ #endif
+diff --git a/drivers/media/video/ovcamchip/ovcamchip_priv.h b/drivers/media/video/ovcamchip/ovcamchip_priv.h
+index 50c7763..9afa4fe 100644
+--- a/drivers/media/video/ovcamchip/ovcamchip_priv.h
++++ b/drivers/media/video/ovcamchip/ovcamchip_priv.h
+@@ -24,11 +24,11 @@ extern int ovcamchip_debug;
+
+ #define PDEBUG(level, fmt, args...) \
+ if (ovcamchip_debug >= (level)) pr_debug("[%s:%d] " fmt "\n", \
+- __FUNCTION__, __LINE__ , ## args)
++ __func__, __LINE__ , ## args)
+
+ #define DDEBUG(level, dev, fmt, args...) \
+ if (ovcamchip_debug >= (level)) dev_dbg(dev, "[%s:%d] " fmt "\n", \
+- __FUNCTION__, __LINE__ , ## args)
++ __func__, __LINE__ , ## args)
+
+ /* Number of times to retry chip detection. Increase this if you are getting
+ * "Failed to init camera chip" */
+diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c
+index 6820c2a..51b1461 100644
+--- a/drivers/media/video/pms.c
++++ b/drivers/media/video/pms.c
+@@ -57,11 +57,11 @@ struct i2c_info
+ u8 hits;
+ };
+
+-static int i2c_count = 0;
++static int i2c_count;
+ static struct i2c_info i2cinfo[64];
+
+ static int decoder = PHILIPS2;
+-static int standard = 0; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */
++static int standard; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */
+
+ /*
+ * I/O ports and Shared Memory
+@@ -885,7 +885,9 @@ static const struct file_operations pms_fops = {
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = pms_ioctl,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .read = pms_read,
+ .llseek = no_llseek,
+ };
+diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig
+index 6fc1b8b..158b3d0 100644
+--- a/drivers/media/video/pvrusb2/Kconfig
++++ b/drivers/media/video/pvrusb2/Kconfig
+@@ -58,6 +58,31 @@ config VIDEO_PVRUSB2_SYSFS
+
+ Note: This feature is experimental and subject to change.
+
++config VIDEO_PVRUSB2_DVB
++ bool "pvrusb2 DVB support (EXPERIMENTAL)"
++ default n
++ depends on VIDEO_PVRUSB2 && DVB_CORE && EXPERIMENTAL
++ select DVB_LGDT330X if !DVB_FE_CUSTOMISE
++ select DVB_S5H1409 if !DVB_FE_CUSTOMISE
++ select DVB_S5H1411 if !DVB_FE_CUSTOMISE
++ select DVB_TDA10048 if !DVB_FE_CUSTOMIZE
++ select DVB_TDA18271 if !DVB_FE_CUSTOMIZE
++ select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
++ select TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
++ ---help---
++
++ This option enables compilation of a DVB interface for the
++ pvrusb2 driver. Currently this is very very experimental.
++ It is also limiting - the DVB interface can only access the
++ digital side of hybrid devices, and there are going to be
++ issues if you attempt to mess with the V4L side at the same
++ time. Don't turn this on unless you know what you are
++ doing.
++
++ If you are in doubt, say N.
++
++ Note: This feature is very experimental and might break
++
+ config VIDEO_PVRUSB2_DEBUGIFC
+ bool "pvrusb2 debug interface"
+ depends on VIDEO_PVRUSB2_SYSFS
+diff --git a/drivers/media/video/pvrusb2/Makefile b/drivers/media/video/pvrusb2/Makefile
+index 47284e5..5b3083c 100644
+--- a/drivers/media/video/pvrusb2/Makefile
++++ b/drivers/media/video/pvrusb2/Makefile
+@@ -1,5 +1,6 @@
+ obj-pvrusb2-sysfs-$(CONFIG_VIDEO_PVRUSB2_SYSFS) := pvrusb2-sysfs.o
+ obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o
++obj-pvrusb2-dvb-$(CONFIG_VIDEO_PVRUSB2_DVB) := pvrusb2-dvb.o
+
+ pvrusb2-objs := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \
+ pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \
+@@ -9,6 +10,11 @@ pvrusb2-objs := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \
+ pvrusb2-ctrl.o pvrusb2-std.o pvrusb2-devattr.o \
+ pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \
+ pvrusb2-cx2584x-v4l.o pvrusb2-wm8775.o \
++ $(obj-pvrusb2-dvb-y) \
+ $(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y)
+
+ obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o
++
++EXTRA_CFLAGS += -Idrivers/media/video
++EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
++EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c
+index 9d94aed..b5db6a5 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-context.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-context.c
+@@ -23,40 +23,193 @@
+ #include "pvrusb2-ioread.h"
+ #include "pvrusb2-hdw.h"
+ #include "pvrusb2-debug.h"
++#include <linux/wait.h>
++#include <linux/kthread.h>
+ #include <linux/errno.h>
+ #include <linux/string.h>
+ #include <linux/slab.h>
+-#include <asm/semaphore.h>
++
++static struct pvr2_context *pvr2_context_exist_first;
++static struct pvr2_context *pvr2_context_exist_last;
++static struct pvr2_context *pvr2_context_notify_first;
++static struct pvr2_context *pvr2_context_notify_last;
++static DEFINE_MUTEX(pvr2_context_mutex);
++static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_sync_data);
++static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_cleanup_data);
++static int pvr2_context_cleanup_flag;
++static int pvr2_context_cleaned_flag;
++static struct task_struct *pvr2_context_thread_ptr;
++
++
++static void pvr2_context_set_notify(struct pvr2_context *mp, int fl)
++{
++ int signal_flag = 0;
++ mutex_lock(&pvr2_context_mutex);
++ if (fl) {
++ if (!mp->notify_flag) {
++ signal_flag = (pvr2_context_notify_first == NULL);
++ mp->notify_prev = pvr2_context_notify_last;
++ mp->notify_next = NULL;
++ pvr2_context_notify_last = mp;
++ if (mp->notify_prev) {
++ mp->notify_prev->notify_next = mp;
++ } else {
++ pvr2_context_notify_first = mp;
++ }
++ mp->notify_flag = !0;
++ }
++ } else {
++ if (mp->notify_flag) {
++ mp->notify_flag = 0;
++ if (mp->notify_next) {
++ mp->notify_next->notify_prev = mp->notify_prev;
++ } else {
++ pvr2_context_notify_last = mp->notify_prev;
++ }
++ if (mp->notify_prev) {
++ mp->notify_prev->notify_next = mp->notify_next;
++ } else {
++ pvr2_context_notify_first = mp->notify_next;
++ }
++ }
++ }
++ mutex_unlock(&pvr2_context_mutex);
++ if (signal_flag) wake_up(&pvr2_context_sync_data);
++}
+
+
+ static void pvr2_context_destroy(struct pvr2_context *mp)
+ {
+- pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr_main id=%p",mp);
++ pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (destroy)",mp);
+ if (mp->hdw) pvr2_hdw_destroy(mp->hdw);
++ pvr2_context_set_notify(mp, 0);
++ mutex_lock(&pvr2_context_mutex);
++ if (mp->exist_next) {
++ mp->exist_next->exist_prev = mp->exist_prev;
++ } else {
++ pvr2_context_exist_last = mp->exist_prev;
++ }
++ if (mp->exist_prev) {
++ mp->exist_prev->exist_next = mp->exist_next;
++ } else {
++ pvr2_context_exist_first = mp->exist_next;
++ }
++ if (!pvr2_context_exist_first) {
++ /* Trigger wakeup on control thread in case it is waiting
++ for an exit condition. */
++ wake_up(&pvr2_context_sync_data);
++ }
++ mutex_unlock(&pvr2_context_mutex);
+ kfree(mp);
+ }
+
+
+-static void pvr2_context_state_check(struct pvr2_context *mp)
++static void pvr2_context_notify(struct pvr2_context *mp)
+ {
+- if (mp->init_flag) return;
++ pvr2_context_set_notify(mp,!0);
++}
++
+
+- switch (pvr2_hdw_get_state(mp->hdw)) {
+- case PVR2_STATE_WARM: break;
+- case PVR2_STATE_ERROR: break;
+- case PVR2_STATE_READY: break;
+- case PVR2_STATE_RUN: break;
+- default: return;
++static void pvr2_context_check(struct pvr2_context *mp)
++{
++ struct pvr2_channel *ch1, *ch2;
++ pvr2_trace(PVR2_TRACE_CTXT,
++ "pvr2_context %p (notify)", mp);
++ if (!mp->initialized_flag && !mp->disconnect_flag) {
++ mp->initialized_flag = !0;
++ pvr2_trace(PVR2_TRACE_CTXT,
++ "pvr2_context %p (initialize)", mp);
++ /* Finish hardware initialization */
++ if (pvr2_hdw_initialize(mp->hdw,
++ (void (*)(void *))pvr2_context_notify,
++ mp)) {
++ mp->video_stream.stream =
++ pvr2_hdw_get_video_stream(mp->hdw);
++ /* Trigger interface initialization. By doing this
++ here initialization runs in our own safe and
++ cozy thread context. */
++ if (mp->setup_func) mp->setup_func(mp);
++ } else {
++ pvr2_trace(PVR2_TRACE_CTXT,
++ "pvr2_context %p (thread skipping setup)",
++ mp);
++ /* Even though initialization did not succeed,
++ we're still going to continue anyway. We need
++ to do this in order to await the expected
++ disconnect (which we will detect in the normal
++ course of operation). */
++ }
+ }
+
+- pvr2_context_enter(mp); do {
+- mp->init_flag = !0;
+- mp->video_stream.stream = pvr2_hdw_get_video_stream(mp->hdw);
+- if (mp->setup_func) {
+- mp->setup_func(mp);
++ for (ch1 = mp->mc_first; ch1; ch1 = ch2) {
++ ch2 = ch1->mc_next;
++ if (ch1->check_func) ch1->check_func(ch1);
++ }
++
++ if (mp->disconnect_flag && !mp->mc_first) {
++ /* Go away... */
++ pvr2_context_destroy(mp);
++ return;
++ }
++}
++
++
++static int pvr2_context_shutok(void)
++{
++ return pvr2_context_cleanup_flag && (pvr2_context_exist_first == NULL);
++}
++
++
++static int pvr2_context_thread_func(void *foo)
++{
++ struct pvr2_context *mp;
++
++ pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread start");
++
++ do {
++ while ((mp = pvr2_context_notify_first) != NULL) {
++ pvr2_context_set_notify(mp, 0);
++ pvr2_context_check(mp);
+ }
+- } while (0); pvr2_context_exit(mp);
+- }
++ wait_event_interruptible(
++ pvr2_context_sync_data,
++ ((pvr2_context_notify_first != NULL) ||
++ pvr2_context_shutok()));
++ } while (!pvr2_context_shutok());
++
++ pvr2_context_cleaned_flag = !0;
++ wake_up(&pvr2_context_cleanup_data);
++
++ pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread cleaned up");
++
++ wait_event_interruptible(
++ pvr2_context_sync_data,
++ kthread_should_stop());
++
++ pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread end");
++
++ return 0;
++}
++
++
++int pvr2_context_global_init(void)
++{
++ pvr2_context_thread_ptr = kthread_run(pvr2_context_thread_func,
++ 0,
++ "pvrusb2-context");
++ return (pvr2_context_thread_ptr ? 0 : -ENOMEM);
++}
++
++
++void pvr2_context_global_done(void)
++{
++ pvr2_context_cleanup_flag = !0;
++ wake_up(&pvr2_context_sync_data);
++ wait_event_interruptible(
++ pvr2_context_cleanup_data,
++ pvr2_context_cleaned_flag);
++ kthread_stop(pvr2_context_thread_ptr);
++}
+
+
+ struct pvr2_context *pvr2_context_create(
+@@ -67,67 +220,75 @@ struct pvr2_context *pvr2_context_create(
+ struct pvr2_context *mp = NULL;
+ mp = kzalloc(sizeof(*mp),GFP_KERNEL);
+ if (!mp) goto done;
+- pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_main id=%p",mp);
++ pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (create)",mp);
+ mp->setup_func = setup_func;
+ mutex_init(&mp->mutex);
++ mutex_lock(&pvr2_context_mutex);
++ mp->exist_prev = pvr2_context_exist_last;
++ mp->exist_next = NULL;
++ pvr2_context_exist_last = mp;
++ if (mp->exist_prev) {
++ mp->exist_prev->exist_next = mp;
++ } else {
++ pvr2_context_exist_first = mp;
++ }
++ mutex_unlock(&pvr2_context_mutex);
+ mp->hdw = pvr2_hdw_create(intf,devid);
+ if (!mp->hdw) {
+ pvr2_context_destroy(mp);
+ mp = NULL;
+ goto done;
+ }
+- pvr2_hdw_set_state_callback(mp->hdw,
+- (void (*)(void *))pvr2_context_state_check,
+- mp);
+- pvr2_context_state_check(mp);
++ pvr2_context_set_notify(mp, !0);
+ done:
+ return mp;
+ }
+
+
+-void pvr2_context_enter(struct pvr2_context *mp)
++static void pvr2_context_reset_input_limits(struct pvr2_context *mp)
++{
++ unsigned int tmsk,mmsk;
++ struct pvr2_channel *cp;
++ struct pvr2_hdw *hdw = mp->hdw;
++ mmsk = pvr2_hdw_get_input_available(hdw);
++ tmsk = mmsk;
++ for (cp = mp->mc_first; cp; cp = cp->mc_next) {
++ if (!cp->input_mask) continue;
++ tmsk &= cp->input_mask;
++ }
++ pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk);
++ pvr2_hdw_commit_ctl(hdw);
++}
++
++
++static void pvr2_context_enter(struct pvr2_context *mp)
+ {
+ mutex_lock(&mp->mutex);
+- pvr2_trace(PVR2_TRACE_CREG,"pvr2_context_enter(id=%p)",mp);
+ }
+
+
+-void pvr2_context_exit(struct pvr2_context *mp)
++static void pvr2_context_exit(struct pvr2_context *mp)
+ {
+ int destroy_flag = 0;
+ if (!(mp->mc_first || !mp->disconnect_flag)) {
+ destroy_flag = !0;
+ }
+- pvr2_trace(PVR2_TRACE_CREG,"pvr2_context_exit(id=%p) outside",mp);
+ mutex_unlock(&mp->mutex);
+- if (destroy_flag) pvr2_context_destroy(mp);
+-}
+-
+-
+-static void pvr2_context_run_checks(struct pvr2_context *mp)
+-{
+- struct pvr2_channel *ch1,*ch2;
+- for (ch1 = mp->mc_first; ch1; ch1 = ch2) {
+- ch2 = ch1->mc_next;
+- if (ch1->check_func) {
+- ch1->check_func(ch1);
+- }
+- }
++ if (destroy_flag) pvr2_context_notify(mp);
+ }
+
+
+ void pvr2_context_disconnect(struct pvr2_context *mp)
+ {
+- pvr2_context_enter(mp); do {
+- pvr2_hdw_disconnect(mp->hdw);
+- mp->disconnect_flag = !0;
+- pvr2_context_run_checks(mp);
+- } while (0); pvr2_context_exit(mp);
++ pvr2_hdw_disconnect(mp->hdw);
++ mp->disconnect_flag = !0;
++ pvr2_context_notify(mp);
+ }
+
+
+ void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp)
+ {
++ pvr2_context_enter(mp);
+ cp->hdw = mp->hdw;
+ cp->mc_head = mp;
+ cp->mc_next = NULL;
+@@ -138,6 +299,7 @@ void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp)
+ mp->mc_first = cp;
+ }
+ mp->mc_last = cp;
++ pvr2_context_exit(mp);
+ }
+
+
+@@ -153,7 +315,10 @@ static void pvr2_channel_disclaim_stream(struct pvr2_channel *cp)
+ void pvr2_channel_done(struct pvr2_channel *cp)
+ {
+ struct pvr2_context *mp = cp->mc_head;
++ pvr2_context_enter(mp);
++ cp->input_mask = 0;
+ pvr2_channel_disclaim_stream(cp);
++ pvr2_context_reset_input_limits(mp);
+ if (cp->mc_next) {
+ cp->mc_next->mc_prev = cp->mc_prev;
+ } else {
+@@ -165,6 +330,58 @@ void pvr2_channel_done(struct pvr2_channel *cp)
+ mp->mc_first = cp->mc_next;
+ }
+ cp->hdw = NULL;
++ pvr2_context_exit(mp);
++}
++
++
++int pvr2_channel_limit_inputs(struct pvr2_channel *cp,unsigned int cmsk)
++{
++ unsigned int tmsk,mmsk;
++ int ret = 0;
++ struct pvr2_channel *p2;
++ struct pvr2_hdw *hdw = cp->hdw;
++
++ mmsk = pvr2_hdw_get_input_available(hdw);
++ cmsk &= mmsk;
++ if (cmsk == cp->input_mask) {
++ /* No change; nothing to do */
++ return 0;
++ }
++
++ pvr2_context_enter(cp->mc_head);
++ do {
++ if (!cmsk) {
++ cp->input_mask = 0;
++ pvr2_context_reset_input_limits(cp->mc_head);
++ break;
++ }
++ tmsk = mmsk;
++ for (p2 = cp->mc_head->mc_first; p2; p2 = p2->mc_next) {
++ if (p2 == cp) continue;
++ if (!p2->input_mask) continue;
++ tmsk &= p2->input_mask;
++ }
++ if (!(tmsk & cmsk)) {
++ ret = -EPERM;
++ break;
++ }
++ tmsk &= cmsk;
++ if ((ret = pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk)) != 0) {
++ /* Internal failure changing allowed list; probably
++ should not happen, but react if it does. */
++ break;
++ }
++ cp->input_mask = cmsk;
++ pvr2_hdw_commit_ctl(hdw);
++ } while (0);
++ pvr2_context_exit(cp->mc_head);
++ return ret;
++}
++
++
++unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *cp)
++{
++ return cp->input_mask;
+ }
+
+
+@@ -174,7 +391,7 @@ int pvr2_channel_claim_stream(struct pvr2_channel *cp,
+ int code = 0;
+ pvr2_context_enter(cp->mc_head); do {
+ if (sp == cp->stream) break;
+- if (sp->user) {
++ if (sp && sp->user) {
+ code = -EBUSY;
+ break;
+ }
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.h b/drivers/media/video/pvrusb2/pvrusb2-context.h
+index a04187a..745e270 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-context.h
++++ b/drivers/media/video/pvrusb2/pvrusb2-context.h
+@@ -30,7 +30,6 @@ struct pvr2_stream; /* stream interface - defined elsewhere */
+ struct pvr2_context; /* All central state */
+ struct pvr2_channel; /* One I/O pathway to a user */
+ struct pvr2_context_stream; /* Wrapper for a stream */
+-struct pvr2_crit_reg; /* Critical region pointer */
+ struct pvr2_ioread; /* Low level stream structure */
+
+ struct pvr2_context_stream {
+@@ -41,11 +40,16 @@ struct pvr2_context_stream {
+ struct pvr2_context {
+ struct pvr2_channel *mc_first;
+ struct pvr2_channel *mc_last;
++ struct pvr2_context *exist_next;
++ struct pvr2_context *exist_prev;
++ struct pvr2_context *notify_next;
++ struct pvr2_context *notify_prev;
+ struct pvr2_hdw *hdw;
+ struct pvr2_context_stream video_stream;
+ struct mutex mutex;
++ int notify_flag;
++ int initialized_flag;
+ int disconnect_flag;
+- int init_flag;
+
+ /* Called after pvr2_context initialization is complete */
+ void (*setup_func)(struct pvr2_context *);
+@@ -58,12 +62,10 @@ struct pvr2_channel {
+ struct pvr2_channel *mc_prev;
+ struct pvr2_context_stream *stream;
+ struct pvr2_hdw *hdw;
++ unsigned int input_mask;
+ void (*check_func)(struct pvr2_channel *);
+ };
+
+-void pvr2_context_enter(struct pvr2_context *);
+-void pvr2_context_exit(struct pvr2_context *);
+-
+ struct pvr2_context *pvr2_context_create(struct usb_interface *intf,
+ const struct usb_device_id *devid,
+ void (*setup_func)(struct pvr2_context *));
+@@ -71,11 +73,15 @@ void pvr2_context_disconnect(struct pvr2_context *);
+
+ void pvr2_channel_init(struct pvr2_channel *,struct pvr2_context *);
+ void pvr2_channel_done(struct pvr2_channel *);
++int pvr2_channel_limit_inputs(struct pvr2_channel *,unsigned int);
++unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *);
+ int pvr2_channel_claim_stream(struct pvr2_channel *,
+ struct pvr2_context_stream *);
+ struct pvr2_ioread *pvr2_channel_create_mpeg_stream(
+ struct pvr2_context_stream *);
+
++int pvr2_context_global_init(void);
++void pvr2_context_global_done(void);
+
+ #endif /* __PVRUSB2_CONTEXT_H */
+ /*
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
+index 5a3e8d2..91a42f2 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
+@@ -30,6 +30,9 @@ static int pvr2_ctrl_range_check(struct pvr2_ctrl *cptr,int val)
+ {
+ if (cptr->info->check_value) {
+ if (!cptr->info->check_value(cptr,val)) return -ERANGE;
++ } else if (cptr->info->type == pvr2_ctl_enum) {
++ if (val < 0) return -ERANGE;
++ if (val >= cptr->info->def.type_enum.count) return -ERANGE;
+ } else {
+ int lim;
+ lim = cptr->info->def.type_int.min_value;
+@@ -63,13 +66,10 @@ int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
+ if (cptr->info->set_value) {
+ if (cptr->info->type == pvr2_ctl_bitmask) {
+ mask &= cptr->info->def.type_bitmask.valid_bits;
+- } else if (cptr->info->type == pvr2_ctl_int) {
++ } else if ((cptr->info->type == pvr2_ctl_int)||
++ (cptr->info->type == pvr2_ctl_enum)) {
+ ret = pvr2_ctrl_range_check(cptr,val);
+ if (ret < 0) break;
+- } else if (cptr->info->type == pvr2_ctl_enum) {
+- if (val >= cptr->info->def.type_enum.count) {
+- break;
+- }
+ } else if (cptr->info->type != pvr2_ctl_bool) {
+ break;
+ }
+@@ -204,8 +204,7 @@ int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val,
+ if (cptr->info->type == pvr2_ctl_enum) {
+ const char **names;
+ names = cptr->info->def.type_enum.value_names;
+- if ((val >= 0) &&
+- (val < cptr->info->def.type_enum.count)) {
++ if (pvr2_ctrl_range_check(cptr,val) == 0) {
+ if (names[val]) {
+ *blen = scnprintf(
+ bptr,bmax,"%s",
+@@ -528,10 +527,8 @@ int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
+ ptr,len,valptr,
+ cptr->info->def.type_enum.value_names,
+ cptr->info->def.type_enum.count);
+- if ((ret >= 0) &&
+- ((*valptr < 0) ||
+- (*valptr >= cptr->info->def.type_enum.count))) {
+- ret = -ERANGE;
++ if (ret >= 0) {
++ ret = pvr2_ctrl_range_check(cptr,*valptr);
+ }
+ if (maskptr) *maskptr = ~0;
+ } else if (cptr->info->type == pvr2_ctl_bitmask) {
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
+index ffdc45c..97350b0 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
+@@ -84,7 +84,9 @@ static const struct routing_scheme_item routing_schemegv[] = {
+ .vid = CX25840_COMPOSITE2,
+ .aud = CX25840_AUDIO5,
+ },
+- [PVR2_CVAL_INPUT_RADIO] = { /* Treat the same as composite */
++ [PVR2_CVAL_INPUT_RADIO] = {
++ /* line-in is used for radio and composite. A GPIO is
++ used to switch between the two choices. */
+ .vid = CX25840_COMPOSITE1,
+ .aud = CX25840_AUDIO_SERIAL,
+ },
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-debug.h b/drivers/media/video/pvrusb2/pvrusb2-debug.h
+index fca49d8..11537dd 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-debug.h
++++ b/drivers/media/video/pvrusb2/pvrusb2-debug.h
+@@ -39,7 +39,7 @@ extern int pvrusb2_debug;
+ #define PVR2_TRACE_EEPROM (1 << 10) /* eeprom parsing / report */
+ #define PVR2_TRACE_STRUCT (1 << 11) /* internal struct creation */
+ #define PVR2_TRACE_OPEN_CLOSE (1 << 12) /* application open / close */
+-#define PVR2_TRACE_CREG (1 << 13) /* Main critical region entry / exit */
++#define PVR2_TRACE_CTXT (1 << 13) /* Main context tracking */
+ #define PVR2_TRACE_SYSFS (1 << 14) /* Sysfs driven I/O */
+ #define PVR2_TRACE_FIRMWARE (1 << 15) /* firmware upload actions */
+ #define PVR2_TRACE_CHIPS (1 << 16) /* chip broadcast operation */
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
+index b068743..b53121c 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
+@@ -164,6 +164,8 @@ int pvr2_debugifc_print_status(struct pvr2_hdw *hdw,
+ int ccnt;
+ int ret;
+ u32 gpio_dir,gpio_in,gpio_out;
++ struct pvr2_stream_stats stats;
++ struct pvr2_stream *sp;
+
+ ret = pvr2_hdw_is_hsm(hdw);
+ ccnt = scnprintf(buf,acnt,"USB link speed: %s\n",
+@@ -182,6 +184,24 @@ int pvr2_debugifc_print_status(struct pvr2_hdw *hdw,
+ pvr2_hdw_get_streaming(hdw) ? "on" : "off");
+ bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+
++
++ sp = pvr2_hdw_get_video_stream(hdw);
++ if (sp) {
++ pvr2_stream_get_stats(sp, &stats, 0);
++ ccnt = scnprintf(
++ buf,acnt,
++ "Bytes streamed=%u"
++ " URBs: queued=%u idle=%u ready=%u"
++ " processed=%u failed=%u\n",
++ stats.bytes_processed,
++ stats.buffers_in_queue,
++ stats.buffers_in_idle,
++ stats.buffers_in_ready,
++ stats.buffers_processed,
++ stats.buffers_failed);
++ bcnt += ccnt; acnt -= ccnt; buf += ccnt;
++ }
++
+ return bcnt;
+ }
+
+@@ -220,6 +240,10 @@ static int pvr2_debugifc_do1cmd(struct pvr2_hdw *hdw,const char *buf,
+ return pvr2_hdw_cmd_decoder_reset(hdw);
+ } else if (debugifc_match_keyword(wptr,wlen,"worker")) {
+ return pvr2_hdw_untrip(hdw);
++ } else if (debugifc_match_keyword(wptr,wlen,"usbstats")) {
++ pvr2_stream_get_stats(pvr2_hdw_get_video_stream(hdw),
++ NULL, !0);
++ return 0;
+ }
+ return -EINVAL;
+ } else if (debugifc_match_keyword(wptr,wlen,"cpufw")) {
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
+index fe9991c..3a141d9 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
+@@ -32,7 +32,16 @@ pvr2_device_desc structures.
+ /* This is needed in order to pull in tuner type ids... */
+ #include <linux/i2c.h>
+ #include <media/tuner.h>
+-
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++#include "pvrusb2-hdw-internal.h"
++#include "lgdt330x.h"
++#include "s5h1409.h"
++#include "s5h1411.h"
++#include "tda10048.h"
++#include "tda18271.h"
++#include "tda8290.h"
++#include "tuner-simple.h"
++#endif
+
+
+ /*------------------------------------------------------------------------*/
+@@ -49,14 +58,19 @@ static const char *pvr2_fw1_names_29xxx[] = {
+ };
+
+ static const struct pvr2_device_desc pvr2_device_29xxx = {
+- .description = "WinTV PVR USB2 Model Category 29xxxx",
++ .description = "WinTV PVR USB2 Model Category 29xxx",
+ .shortname = "29xxx",
+ .client_modules.lst = pvr2_client_29xxx,
+ .client_modules.cnt = ARRAY_SIZE(pvr2_client_29xxx),
+ .fx2_firmware.lst = pvr2_fw1_names_29xxx,
+ .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_29xxx),
+ .flag_has_hauppauge_rom = !0,
++ .flag_has_analogtuner = !0,
++ .flag_has_fmradio = !0,
++ .flag_has_composite = !0,
++ .flag_has_svideo = !0,
+ .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
++ .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+ };
+
+
+@@ -75,7 +89,7 @@ static const char *pvr2_fw1_names_24xxx[] = {
+ };
+
+ static const struct pvr2_device_desc pvr2_device_24xxx = {
+- .description = "WinTV PVR USB2 Model Category 24xxxx",
++ .description = "WinTV PVR USB2 Model Category 24xxx",
+ .shortname = "24xxx",
+ .client_modules.lst = pvr2_client_24xxx,
+ .client_modules.cnt = ARRAY_SIZE(pvr2_client_24xxx),
+@@ -85,7 +99,12 @@ static const struct pvr2_device_desc pvr2_device_24xxx = {
+ .flag_has_wm8775 = !0,
+ .flag_has_hauppauge_rom = !0,
+ .flag_has_hauppauge_custom_ir = !0,
++ .flag_has_analogtuner = !0,
++ .flag_has_fmradio = !0,
++ .flag_has_composite = !0,
++ .flag_has_svideo = !0,
+ .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
++ .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+ };
+
+
+@@ -105,6 +124,30 @@ static const struct pvr2_device_desc pvr2_device_gotview_2 = {
+ .client_modules.cnt = ARRAY_SIZE(pvr2_client_gotview_2),
+ .flag_has_cx25840 = !0,
+ .default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
++ .flag_has_analogtuner = !0,
++ .flag_has_fmradio = !0,
++ .flag_has_composite = !0,
++ .flag_has_svideo = !0,
++ .signal_routing_scheme = PVR2_ROUTING_SCHEME_GOTVIEW,
++};
++
++
++
++/*------------------------------------------------------------------------*/
++/* GOTVIEW USB2.0 DVD Deluxe */
++
++/* (same module list as gotview_2) */
++
++static const struct pvr2_device_desc pvr2_device_gotview_2d = {
++ .description = "Gotview USB 2.0 DVD Deluxe",
++ .shortname = "gv2d",
++ .client_modules.lst = pvr2_client_gotview_2,
++ .client_modules.cnt = ARRAY_SIZE(pvr2_client_gotview_2),
++ .flag_has_cx25840 = !0,
++ .default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
++ .flag_has_analogtuner = !0,
++ .flag_has_composite = !0,
++ .flag_has_svideo = !0,
+ .signal_routing_scheme = PVR2_ROUTING_SCHEME_GOTVIEW,
+ };
+
+@@ -114,6 +157,38 @@ static const struct pvr2_device_desc pvr2_device_gotview_2 = {
+ /*------------------------------------------------------------------------*/
+ /* OnAir Creator */
+
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++static struct lgdt330x_config pvr2_lgdt3303_config = {
++ .demod_address = 0x0e,
++ .demod_chip = LGDT3303,
++ .clock_polarity_flip = 1,
++};
++
++static int pvr2_lgdt3303_attach(struct pvr2_dvb_adapter *adap)
++{
++ adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3303_config,
++ &adap->channel.hdw->i2c_adap);
++ if (adap->fe)
++ return 0;
++
++ return -EIO;
++}
++
++static int pvr2_lgh06xf_attach(struct pvr2_dvb_adapter *adap)
++{
++ dvb_attach(simple_tuner_attach, adap->fe,
++ &adap->channel.hdw->i2c_adap, 0x61,
++ TUNER_LG_TDVS_H06XF);
++
++ return 0;
++}
++
++struct pvr2_dvb_props pvr2_onair_creator_fe_props = {
++ .frontend_attach = pvr2_lgdt3303_attach,
++ .tuner_attach = pvr2_lgh06xf_attach,
++};
++#endif
++
+ static const char *pvr2_client_onair_creator[] = {
+ "saa7115",
+ "tuner",
+@@ -126,7 +201,16 @@ static const struct pvr2_device_desc pvr2_device_onair_creator = {
+ .client_modules.lst = pvr2_client_onair_creator,
+ .client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_creator),
+ .default_tuner_type = TUNER_LG_TDVS_H06XF,
++ .flag_has_analogtuner = !0,
++ .flag_has_composite = !0,
++ .flag_has_svideo = !0,
++ .flag_digital_requires_cx23416 = !0,
+ .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
++ .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR,
++ .default_std_mask = V4L2_STD_NTSC_M,
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++ .dvb_props = &pvr2_onair_creator_fe_props,
++#endif
+ };
+ #endif
+
+@@ -136,6 +220,37 @@ static const struct pvr2_device_desc pvr2_device_onair_creator = {
+ /*------------------------------------------------------------------------*/
+ /* OnAir USB 2.0 */
+
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++static struct lgdt330x_config pvr2_lgdt3302_config = {
++ .demod_address = 0x0e,
++ .demod_chip = LGDT3302,
++};
++
++static int pvr2_lgdt3302_attach(struct pvr2_dvb_adapter *adap)
++{
++ adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3302_config,
++ &adap->channel.hdw->i2c_adap);
++ if (adap->fe)
++ return 0;
++
++ return -EIO;
++}
++
++static int pvr2_fcv1236d_attach(struct pvr2_dvb_adapter *adap)
++{
++ dvb_attach(simple_tuner_attach, adap->fe,
++ &adap->channel.hdw->i2c_adap, 0x61,
++ TUNER_PHILIPS_FCV1236D);
++
++ return 0;
++}
++
++struct pvr2_dvb_props pvr2_onair_usb2_fe_props = {
++ .frontend_attach = pvr2_lgdt3302_attach,
++ .tuner_attach = pvr2_fcv1236d_attach,
++};
++#endif
++
+ static const char *pvr2_client_onair_usb2[] = {
+ "saa7115",
+ "tuner",
+@@ -147,8 +262,17 @@ static const struct pvr2_device_desc pvr2_device_onair_usb2 = {
+ .shortname = "oa2",
+ .client_modules.lst = pvr2_client_onair_usb2,
+ .client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_usb2),
+- .default_tuner_type = TUNER_PHILIPS_ATSC,
++ .default_tuner_type = TUNER_PHILIPS_FCV1236D,
++ .flag_has_analogtuner = !0,
++ .flag_has_composite = !0,
++ .flag_has_svideo = !0,
++ .flag_digital_requires_cx23416 = !0,
+ .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
++ .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR,
++ .default_std_mask = V4L2_STD_NTSC_M,
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++ .dvb_props = &pvr2_onair_usb2_fe_props,
++#endif
+ };
+ #endif
+
+@@ -157,6 +281,50 @@ static const struct pvr2_device_desc pvr2_device_onair_usb2 = {
+ /*------------------------------------------------------------------------*/
+ /* Hauppauge PVR-USB2 Model 73xxx */
+
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++static struct tda10048_config hauppauge_tda10048_config = {
++ .demod_address = 0x10 >> 1,
++ .output_mode = TDA10048_PARALLEL_OUTPUT,
++ .fwbulkwritelen = TDA10048_BULKWRITE_50,
++ .inversion = TDA10048_INVERSION_ON,
++};
++
++static struct tda829x_config tda829x_no_probe = {
++ .probe_tuner = TDA829X_DONT_PROBE,
++};
++
++static struct tda18271_config hauppauge_tda18271_dvb_config = {
++ .gate = TDA18271_GATE_ANALOG,
++};
++
++static int pvr2_tda10048_attach(struct pvr2_dvb_adapter *adap)
++{
++ adap->fe = dvb_attach(tda10048_attach, &hauppauge_tda10048_config,
++ &adap->channel.hdw->i2c_adap);
++ if (adap->fe)
++ return 0;
++
++ return -EIO;
++}
++
++static int pvr2_73xxx_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
++{
++ dvb_attach(tda829x_attach, adap->fe,
++ &adap->channel.hdw->i2c_adap, 0x42,
++ &tda829x_no_probe);
++ dvb_attach(tda18271_attach, adap->fe, 0x60,
++ &adap->channel.hdw->i2c_adap,
++ &hauppauge_tda18271_dvb_config);
++
++ return 0;
++}
++
++struct pvr2_dvb_props pvr2_73xxx_dvb_props = {
++ .frontend_attach = pvr2_tda10048_attach,
++ .tuner_attach = pvr2_73xxx_tda18271_8295_attach,
++};
++#endif
++
+ static const char *pvr2_client_73xxx[] = {
+ "cx25840",
+ "tuner",
+@@ -167,7 +335,7 @@ static const char *pvr2_fw1_names_73xxx[] = {
+ };
+
+ static const struct pvr2_device_desc pvr2_device_73xxx = {
+- .description = "WinTV PVR USB2 Model Category 73xxxx",
++ .description = "WinTV PVR USB2 Model Category 73xxx",
+ .shortname = "73xxx",
+ .client_modules.lst = pvr2_client_73xxx,
+ .client_modules.cnt = ARRAY_SIZE(pvr2_client_73xxx),
+@@ -175,15 +343,14 @@ static const struct pvr2_device_desc pvr2_device_73xxx = {
+ .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_73xxx),
+ .flag_has_cx25840 = !0,
+ .flag_has_hauppauge_rom = !0,
+-#if 0
+ .flag_has_analogtuner = !0,
+ .flag_has_composite = !0,
+ .flag_has_svideo = !0,
+ .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+ .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
+ .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+-#else
+- .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++ .dvb_props = &pvr2_73xxx_dvb_props,
+ #endif
+ };
+
+@@ -192,6 +359,80 @@ static const struct pvr2_device_desc pvr2_device_73xxx = {
+ /*------------------------------------------------------------------------*/
+ /* Hauppauge PVR-USB2 Model 75xxx */
+
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++static struct s5h1409_config pvr2_s5h1409_config = {
++ .demod_address = 0x32 >> 1,
++ .output_mode = S5H1409_PARALLEL_OUTPUT,
++ .gpio = S5H1409_GPIO_OFF,
++ .qam_if = 4000,
++ .inversion = S5H1409_INVERSION_ON,
++ .status_mode = S5H1409_DEMODLOCKING,
++};
++
++static struct s5h1411_config pvr2_s5h1411_config = {
++ .output_mode = S5H1411_PARALLEL_OUTPUT,
++ .gpio = S5H1411_GPIO_OFF,
++ .vsb_if = S5H1411_IF_44000,
++ .qam_if = S5H1411_IF_4000,
++ .inversion = S5H1411_INVERSION_ON,
++ .status_mode = S5H1411_DEMODLOCKING,
++};
++
++static struct tda18271_std_map hauppauge_tda18271_std_map = {
++ .atsc_6 = { .if_freq = 5380, .agc_mode = 3, .std = 3,
++ .if_lvl = 6, .rfagc_top = 0x37, },
++ .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 0,
++ .if_lvl = 6, .rfagc_top = 0x37, },
++};
++
++static struct tda18271_config hauppauge_tda18271_config = {
++ .std_map = &hauppauge_tda18271_std_map,
++ .gate = TDA18271_GATE_ANALOG,
++};
++
++static int pvr2_s5h1409_attach(struct pvr2_dvb_adapter *adap)
++{
++ adap->fe = dvb_attach(s5h1409_attach, &pvr2_s5h1409_config,
++ &adap->channel.hdw->i2c_adap);
++ if (adap->fe)
++ return 0;
++
++ return -EIO;
++}
++
++static int pvr2_s5h1411_attach(struct pvr2_dvb_adapter *adap)
++{
++ adap->fe = dvb_attach(s5h1411_attach, &pvr2_s5h1411_config,
++ &adap->channel.hdw->i2c_adap);
++ if (adap->fe)
++ return 0;
++
++ return -EIO;
++}
++
++static int pvr2_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
++{
++ dvb_attach(tda829x_attach, adap->fe,
++ &adap->channel.hdw->i2c_adap, 0x42,
++ &tda829x_no_probe);
++ dvb_attach(tda18271_attach, adap->fe, 0x60,
++ &adap->channel.hdw->i2c_adap,
++ &hauppauge_tda18271_config);
++
++ return 0;
++}
++
++struct pvr2_dvb_props pvr2_750xx_dvb_props = {
++ .frontend_attach = pvr2_s5h1409_attach,
++ .tuner_attach = pvr2_tda18271_8295_attach,
++};
++
++struct pvr2_dvb_props pvr2_751xx_dvb_props = {
++ .frontend_attach = pvr2_s5h1411_attach,
++ .tuner_attach = pvr2_tda18271_8295_attach,
++};
++#endif
++
+ static const char *pvr2_client_75xxx[] = {
+ "cx25840",
+ "tuner",
+@@ -201,17 +442,46 @@ static const char *pvr2_fw1_names_75xxx[] = {
+ "v4l-pvrusb2-73xxx-01.fw",
+ };
+
+-static const struct pvr2_device_desc pvr2_device_75xxx = {
+- .description = "WinTV PVR USB2 Model Category 75xxxx",
+- .shortname = "75xxx",
++static const struct pvr2_device_desc pvr2_device_750xx = {
++ .description = "WinTV PVR USB2 Model Category 750xx",
++ .shortname = "750xx",
+ .client_modules.lst = pvr2_client_75xxx,
+ .client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx),
+ .fx2_firmware.lst = pvr2_fw1_names_75xxx,
+ .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx),
+ .flag_has_cx25840 = !0,
+ .flag_has_hauppauge_rom = !0,
++ .flag_has_analogtuner = !0,
++ .flag_has_composite = !0,
++ .flag_has_svideo = !0,
+ .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
++ .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
+ .default_std_mask = V4L2_STD_NTSC_M,
++ .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++ .dvb_props = &pvr2_750xx_dvb_props,
++#endif
++};
++
++static const struct pvr2_device_desc pvr2_device_751xx = {
++ .description = "WinTV PVR USB2 Model Category 751xx",
++ .shortname = "751xx",
++ .client_modules.lst = pvr2_client_75xxx,
++ .client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx),
++ .fx2_firmware.lst = pvr2_fw1_names_75xxx,
++ .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx),
++ .flag_has_cx25840 = !0,
++ .flag_has_hauppauge_rom = !0,
++ .flag_has_analogtuner = !0,
++ .flag_has_composite = !0,
++ .flag_has_svideo = !0,
++ .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
++ .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
++ .default_std_mask = V4L2_STD_NTSC_M,
++ .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++ .dvb_props = &pvr2_751xx_dvb_props,
++#endif
+ };
+
+
+@@ -225,6 +495,8 @@ struct usb_device_id pvr2_device_table[] = {
+ .driver_info = (kernel_ulong_t)&pvr2_device_24xxx},
+ { USB_DEVICE(0x1164, 0x0622),
+ .driver_info = (kernel_ulong_t)&pvr2_device_gotview_2},
++ { USB_DEVICE(0x1164, 0x0602),
++ .driver_info = (kernel_ulong_t)&pvr2_device_gotview_2d},
+ #ifdef CONFIG_VIDEO_PVRUSB2_ONAIR_CREATOR
+ { USB_DEVICE(0x11ba, 0x1003),
+ .driver_info = (kernel_ulong_t)&pvr2_device_onair_creator},
+@@ -236,9 +508,9 @@ struct usb_device_id pvr2_device_table[] = {
+ { USB_DEVICE(0x2040, 0x7300),
+ .driver_info = (kernel_ulong_t)&pvr2_device_73xxx},
+ { USB_DEVICE(0x2040, 0x7500),
+- .driver_info = (kernel_ulong_t)&pvr2_device_75xxx},
++ .driver_info = (kernel_ulong_t)&pvr2_device_750xx},
+ { USB_DEVICE(0x2040, 0x7501),
+- .driver_info = (kernel_ulong_t)&pvr2_device_75xxx},
++ .driver_info = (kernel_ulong_t)&pvr2_device_751xx},
+ { }
+ };
+
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h
+index 64b467f..d016f8b 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h
++++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h
+@@ -23,6 +23,9 @@
+
+ #include <linux/mod_devicetable.h>
+ #include <linux/videodev2.h>
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++#include "pvrusb2-dvb.h"
++#endif
+
+ /*
+
+@@ -39,6 +42,13 @@ struct pvr2_string_table {
+ #define PVR2_ROUTING_SCHEME_HAUPPAUGE 0
+ #define PVR2_ROUTING_SCHEME_GOTVIEW 1
+
++#define PVR2_DIGITAL_SCHEME_NONE 0
++#define PVR2_DIGITAL_SCHEME_HAUPPAUGE 1
++#define PVR2_DIGITAL_SCHEME_ONAIR 2
++
++#define PVR2_LED_SCHEME_NONE 0
++#define PVR2_LED_SCHEME_HAUPPAUGE 1
++
+ /* This describes a particular hardware type (except for the USB device ID
+ which must live in a separate structure due to environmental
+ constraints). See the top of pvrusb2-hdw.c for where this is
+@@ -58,40 +68,64 @@ struct pvr2_device_desc {
+ was initialized from internal ROM. */
+ struct pvr2_string_table fx2_firmware;
+
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++ /* callback functions to handle attachment of digital tuner & demod */
++ struct pvr2_dvb_props *dvb_props;
++
++#endif
++ /* Initial standard bits to use for this device, if not zero.
++ Anything set here is also implied as an available standard.
++ Note: This is ignored if overridden on the module load line via
++ the video_std module option. */
++ v4l2_std_id default_std_mask;
++
++ /* V4L tuner type ID to use with this device (only used if the
++ driver could not discover the type any other way). */
++ int default_tuner_type;
++
+ /* Signal routing scheme used by device, contains one of
+ PVR2_ROUTING_SCHEME_XXX. Schemes have to be defined as we
+ encounter them. This is an arbitrary integer scheme id; its
+ meaning is contained entirely within the driver and is
+ interpreted by logic which must send commands to the chip-level
+ drivers (search for things which touch this field). */
+- unsigned int signal_routing_scheme;
++ unsigned char signal_routing_scheme;
+
+- /* V4L tuner type ID to use with this device (only used if the
+- driver could not discover the type any other way). */
+- int default_tuner_type;
++ /* Indicates scheme for controlling device's LED (if any). The
++ driver will turn on the LED when streaming is underway. This
++ contains one of PVR2_LED_SCHEME_XXX. */
++ unsigned char led_scheme;
+
+- /* Initial standard bits to use for this device, if not zero.
+- Anything set here is also implied as an available standard.
+- Note: This is ignored if overridden on the module load line via
+- the video_std module option. */
+- v4l2_std_id default_std_mask;
++ /* Control scheme to use if there is a digital tuner. This
++ contains one of PVR2_DIGITAL_SCHEME_XXX. This is an arbitrary
++ integer scheme id; its meaning is contained entirely within the
++ driver and is interpreted by logic which must control the
++ streaming pathway (search for things which touch this field). */
++ unsigned char digital_control_scheme;
+
+ /* If set, we don't bother trying to load cx23416 firmware. */
+- char flag_skip_cx23416_firmware;
++ unsigned int flag_skip_cx23416_firmware:1;
++
++ /* If set, the encoder must be healthy in order for digital mode to
++ work (otherwise we assume that digital streaming will work even
++ if we fail to locate firmware for the encoder). If the device
++ doesn't support digital streaming then this flag has no
++ effect. */
++ unsigned int flag_digital_requires_cx23416:1;
+
+ /* Device has a hauppauge eeprom which we can interrogate. */
+- char flag_has_hauppauge_rom;
++ unsigned int flag_has_hauppauge_rom:1;
+
+ /* Device does not require a powerup command to be issued. */
+- char flag_no_powerup;
++ unsigned int flag_no_powerup:1;
+
+ /* Device has a cx25840 - this enables special additional logic to
+ handle it. */
+- char flag_has_cx25840;
++ unsigned int flag_has_cx25840:1;
+
+ /* Device has a wm8775 - this enables special additional logic to
+ ensure that it is found. */
+- char flag_has_wm8775;
++ unsigned int flag_has_wm8775:1;
+
+ /* Device has IR hardware that can be faked into looking like a
+ normal Hauppauge i2c IR receiver. This is currently very
+@@ -101,7 +135,15 @@ struct pvr2_device_desc {
+ to virtualize the presence of the non-existant IR receiver chip and
+ implement the virtual receiver in terms of appropriate FX2
+ commands. */
+- char flag_has_hauppauge_custom_ir;
++ unsigned int flag_has_hauppauge_custom_ir:1;
++
++ /* These bits define which kinds of sources the device can handle.
++ Note: Digital tuner presence is inferred by the
++ digital_control_scheme enumeration. */
++ unsigned int flag_has_fmradio:1; /* Has FM radio receiver */
++ unsigned int flag_has_analogtuner:1; /* Has analog tuner */
++ unsigned int flag_has_composite:1; /* Has composite input */
++ unsigned int flag_has_svideo:1; /* Has s-video input */
+ };
+
+ extern struct usb_device_id pvr2_device_table[];
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c
+new file mode 100644
+index 0000000..2e64f98
+--- /dev/null
++++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.c
+@@ -0,0 +1,425 @@
++/*
++ * pvrusb2-dvb.c - linux-dvb api interface to the pvrusb2 driver.
++ *
++ * Copyright (C) 2007, 2008 Michael Krufky <mkrufky at linuxtv.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License
++ *
++ * 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/kthread.h>
++#include <linux/freezer.h>
++#include "dvbdev.h"
++#include "pvrusb2-hdw-internal.h"
++#include "pvrusb2-hdw.h"
++#include "pvrusb2-io.h"
++#include "pvrusb2-dvb.h"
++
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
++static int pvr2_dvb_feed_func(struct pvr2_dvb_adapter *adap)
++{
++ int ret;
++ unsigned int count;
++ struct pvr2_buffer *bp;
++ struct pvr2_stream *stream;
++
++ printk(KERN_DEBUG "dvb thread started\n");
++ set_freezable();
++
++ stream = adap->channel.stream->stream;
++
++ for (;;) {
++ if (kthread_should_stop()) break;
++
++ /* Not sure about this... */
++ try_to_freeze();
++
++ bp = pvr2_stream_get_ready_buffer(stream);
++ if (bp != NULL) {
++ count = pvr2_buffer_get_count(bp);
++ if (count) {
++ dvb_dmx_swfilter(
++ &adap->demux,
++ adap->buffer_storage[
++ pvr2_buffer_get_id(bp)],
++ count);
++ } else {
++ ret = pvr2_buffer_get_status(bp);
++ if (ret < 0) break;
++ }
++ ret = pvr2_buffer_queue(bp);
++ if (ret < 0) break;
++
++ /* Since we know we did something to a buffer,
++ just go back and try again. No point in
++ blocking unless we really ran out of
++ buffers to process. */
++ continue;
++ }
++
++
++ /* Wait until more buffers become available or we're
++ told not to wait any longer. */
++ ret = wait_event_interruptible(
++ adap->buffer_wait_data,
++ (pvr2_stream_get_ready_count(stream) > 0) ||
++ kthread_should_stop());
++ if (ret < 0) break;
++ }
++
++ /* If we get here and ret is < 0, then an error has occurred.
++ Probably would be a good idea to communicate that to DVB core... */
++
++ printk(KERN_DEBUG "dvb thread stopped\n");
++
++ return 0;
++}
++
++static int pvr2_dvb_feed_thread(void *data)
++{
++ int stat = pvr2_dvb_feed_func(data);
++ /* from videobuf-dvb.c: */
++ while (!kthread_should_stop()) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule();
++ }
++ return stat;
++}
++
++static void pvr2_dvb_notify(struct pvr2_dvb_adapter *adap)
++{
++ wake_up(&adap->buffer_wait_data);
++}
++
++static void pvr2_dvb_stream_end(struct pvr2_dvb_adapter *adap)
++{
++ unsigned int idx;
++ struct pvr2_stream *stream;
++
++ if (adap->thread) {
++ kthread_stop(adap->thread);
++ adap->thread = NULL;
++ }
++
++ if (adap->channel.stream) {
++ stream = adap->channel.stream->stream;
++ } else {
++ stream = NULL;
++ }
++ if (stream) {
++ pvr2_hdw_set_streaming(adap->channel.hdw, 0);
++ pvr2_stream_set_callback(stream, NULL, NULL);
++ pvr2_stream_kill(stream);
++ pvr2_stream_set_buffer_count(stream, 0);
++ pvr2_channel_claim_stream(&adap->channel, NULL);
++ }
++
++ if (adap->stream_run) {
++ for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) {
++ if (!(adap->buffer_storage[idx])) continue;
++ kfree(adap->buffer_storage[idx]);
++ adap->buffer_storage[idx] = 0;
++ }
++ adap->stream_run = 0;
++ }
++}
++
++static int pvr2_dvb_stream_do_start(struct pvr2_dvb_adapter *adap)
++{
++ struct pvr2_context *pvr = adap->channel.mc_head;
++ unsigned int idx;
++ int ret;
++ struct pvr2_buffer *bp;
++ struct pvr2_stream *stream = 0;
++
++ if (adap->stream_run) return -EIO;
++
++ ret = pvr2_channel_claim_stream(&adap->channel, &pvr->video_stream);
++ /* somebody else already has the stream */
++ if (ret < 0) return ret;
++
++ stream = adap->channel.stream->stream;
++
++ for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) {
++ adap->buffer_storage[idx] = kmalloc(PVR2_DVB_BUFFER_SIZE,
++ GFP_KERNEL);
++ if (!(adap->buffer_storage[idx])) return -ENOMEM;
++ }
++
++ pvr2_stream_set_callback(pvr->video_stream.stream,
++ (pvr2_stream_callback) pvr2_dvb_notify, adap);
++
++ ret = pvr2_stream_set_buffer_count(stream, PVR2_DVB_BUFFER_COUNT);
++ if (ret < 0) return ret;
++
++ for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) {
++ bp = pvr2_stream_get_buffer(stream, idx);
++ pvr2_buffer_set_buffer(bp,
++ adap->buffer_storage[idx],
++ PVR2_DVB_BUFFER_SIZE);
++ }
++
++ ret = pvr2_hdw_set_streaming(adap->channel.hdw, 1);
++ if (ret < 0) return ret;
++
++ while ((bp = pvr2_stream_get_idle_buffer(stream)) != 0) {
++ ret = pvr2_buffer_queue(bp);
++ if (ret < 0) return ret;
++ }
++
++ adap->thread = kthread_run(pvr2_dvb_feed_thread, adap, "pvrusb2-dvb");
++
++ if (IS_ERR(adap->thread)) {
++ ret = PTR_ERR(adap->thread);
++ adap->thread = NULL;
++ return ret;
++ }
++
++ adap->stream_run = !0;
++
++ return 0;
++}
++
++static int pvr2_dvb_stream_start(struct pvr2_dvb_adapter *adap)
++{
++ int ret = pvr2_dvb_stream_do_start(adap);
++ if (ret < 0) pvr2_dvb_stream_end(adap);
++ return ret;
++}
++
++static int pvr2_dvb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
++{
++ struct pvr2_dvb_adapter *adap = dvbdmxfeed->demux->priv;
++ int ret = 0;
++
++ if (adap == NULL) return -ENODEV;
++
++ mutex_lock(&adap->lock);
++ do {
++ if (onoff) {
++ if (!adap->feedcount) {
++ printk(KERN_DEBUG "start feeding\n");
++ ret = pvr2_dvb_stream_start(adap);
++ if (ret < 0) break;
++ }
++ (adap->feedcount)++;
++ } else if (adap->feedcount > 0) {
++ (adap->feedcount)--;
++ if (!adap->feedcount) {
++ printk(KERN_DEBUG "stop feeding\n");
++ pvr2_dvb_stream_end(adap);
++ }
++ }
++ } while (0);
++ mutex_unlock(&adap->lock);
++
++ return ret;
++}
++
++static int pvr2_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
++{
++ printk(KERN_DEBUG "start pid: 0x%04x, feedtype: %d\n",
++ dvbdmxfeed->pid, dvbdmxfeed->type);
++ return pvr2_dvb_ctrl_feed(dvbdmxfeed, 1);
++}
++
++static int pvr2_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
++{
++ printk(KERN_DEBUG "stop pid: 0x%04x, feedtype: %d\n",
++ dvbdmxfeed->pid, dvbdmxfeed->type);
++ return pvr2_dvb_ctrl_feed(dvbdmxfeed, 0);
++}
++
++static int pvr2_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
++{
++ struct pvr2_dvb_adapter *adap = fe->dvb->priv;
++ return pvr2_channel_limit_inputs(
++ &adap->channel,
++ (acquire ? (1 << PVR2_CVAL_INPUT_DTV) : 0));
++}
++
++static int pvr2_dvb_adapter_init(struct pvr2_dvb_adapter *adap)
++{
++ int ret;
++
++ ret = dvb_register_adapter(&adap->dvb_adap, "pvrusb2-dvb",
++ THIS_MODULE/*&hdw->usb_dev->owner*/,
++ &adap->channel.hdw->usb_dev->dev,
++ adapter_nr);
++ if (ret < 0) {
++ err("dvb_register_adapter failed: error %d", ret);
++ goto err;
++ }
++ adap->dvb_adap.priv = adap;
++
++ adap->demux.dmx.capabilities = DMX_TS_FILTERING |
++ DMX_SECTION_FILTERING |
++ DMX_MEMORY_BASED_FILTERING;
++ adap->demux.priv = adap;
++ adap->demux.filternum = 256;
++ adap->demux.feednum = 256;
++ adap->demux.start_feed = pvr2_dvb_start_feed;
++ adap->demux.stop_feed = pvr2_dvb_stop_feed;
++ adap->demux.write_to_decoder = NULL;
++
++ ret = dvb_dmx_init(&adap->demux);
++ if (ret < 0) {
++ err("dvb_dmx_init failed: error %d", ret);
++ goto err_dmx;
++ }
++
++ adap->dmxdev.filternum = adap->demux.filternum;
++ adap->dmxdev.demux = &adap->demux.dmx;
++ adap->dmxdev.capabilities = 0;
++
++ ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap);
++ if (ret < 0) {
++ err("dvb_dmxdev_init failed: error %d", ret);
++ goto err_dmx_dev;
++ }
++
++ dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx);
++
++ return 0;
++
++err_dmx_dev:
++ dvb_dmx_release(&adap->demux);
++err_dmx:
++ dvb_unregister_adapter(&adap->dvb_adap);
++err:
++ return ret;
++}
++
++static int pvr2_dvb_adapter_exit(struct pvr2_dvb_adapter *adap)
++{
++ printk(KERN_DEBUG "unregistering DVB devices\n");
++ dvb_net_release(&adap->dvb_net);
++ adap->demux.dmx.close(&adap->demux.dmx);
++ dvb_dmxdev_release(&adap->dmxdev);
++ dvb_dmx_release(&adap->demux);
++ dvb_unregister_adapter(&adap->dvb_adap);
++ return 0;
++}
++
++static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
++{
++ struct pvr2_hdw *hdw = adap->channel.hdw;
++ struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props;
++ int ret = 0;
++
++ if (dvb_props == NULL) {
++ err("fe_props not defined!");
++ return -EINVAL;
++ }
++
++ ret = pvr2_channel_limit_inputs(
++ &adap->channel,
++ (1 << PVR2_CVAL_INPUT_DTV));
++ if (ret) {
++ err("failed to grab control of dtv input (code=%d)",
++ ret);
++ return ret;
++ }
++
++ if (dvb_props->frontend_attach == NULL) {
++ err("frontend_attach not defined!");
++ ret = -EINVAL;
++ goto done;
++ }
++
++ if ((dvb_props->frontend_attach(adap) == 0) && (adap->fe)) {
++
++ if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) {
++ err("frontend registration failed!");
++ dvb_frontend_detach(adap->fe);
++ adap->fe = NULL;
++ ret = -ENODEV;
++ goto done;
++ }
++
++ if (dvb_props->tuner_attach)
++ dvb_props->tuner_attach(adap);
++
++ if (adap->fe->ops.analog_ops.standby)
++ adap->fe->ops.analog_ops.standby(adap->fe);
++
++ /* Ensure all frontends negotiate bus access */
++ adap->fe->ops.ts_bus_ctrl = pvr2_dvb_bus_ctrl;
++
++ } else {
++ err("no frontend was attached!");
++ ret = -ENODEV;
++ return ret;
++ }
++
++ done:
++ pvr2_channel_limit_inputs(&adap->channel, 0);
++ return ret;
++}
++
++static int pvr2_dvb_frontend_exit(struct pvr2_dvb_adapter *adap)
++{
++ if (adap->fe != NULL) {
++ dvb_unregister_frontend(adap->fe);
++ dvb_frontend_detach(adap->fe);
++ }
++ return 0;
++}
++
++static void pvr2_dvb_destroy(struct pvr2_dvb_adapter *adap)
++{
++ pvr2_dvb_stream_end(adap);
++ pvr2_dvb_frontend_exit(adap);
++ pvr2_dvb_adapter_exit(adap);
++ pvr2_channel_done(&adap->channel);
++ kfree(adap);
++}
++
++static void pvr2_dvb_internal_check(struct pvr2_channel *chp)
++{
++ struct pvr2_dvb_adapter *adap;
++ adap = container_of(chp, struct pvr2_dvb_adapter, channel);
++ if (!adap->channel.mc_head->disconnect_flag) return;
++ pvr2_dvb_destroy(adap);
++}
++
++struct pvr2_dvb_adapter *pvr2_dvb_create(struct pvr2_context *pvr)
++{
++ int ret = 0;
++ struct pvr2_dvb_adapter *adap;
++ if (!pvr->hdw->hdw_desc->dvb_props) {
++ /* Device lacks a digital interface so don't set up
++ the DVB side of the driver either. For now. */
++ return NULL;
++ }
++ adap = kzalloc(sizeof(*adap), GFP_KERNEL);
++ if (!adap) return adap;
++ pvr2_channel_init(&adap->channel, pvr);
++ adap->channel.check_func = pvr2_dvb_internal_check;
++ init_waitqueue_head(&adap->buffer_wait_data);
++ mutex_init(&adap->lock);
++ ret = pvr2_dvb_adapter_init(adap);
++ if (ret < 0) goto fail1;
++ ret = pvr2_dvb_frontend_init(adap);
++ if (ret < 0) goto fail2;
++ return adap;
++
++fail2:
++ pvr2_dvb_adapter_exit(adap);
++fail1:
++ pvr2_channel_done(&adap->channel);
++ return NULL;
++}
++
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.h b/drivers/media/video/pvrusb2/pvrusb2-dvb.h
+new file mode 100644
+index 0000000..884ff91
+--- /dev/null
++++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.h
+@@ -0,0 +1,41 @@
++#ifndef __PVRUSB2_DVB_H__
++#define __PVRUSB2_DVB_H__
++
++#include "dvb_frontend.h"
++#include "dvb_demux.h"
++#include "dvb_net.h"
++#include "dmxdev.h"
++#include "pvrusb2-context.h"
++
++#define PVR2_DVB_BUFFER_COUNT 32
++#define PVR2_DVB_BUFFER_SIZE PAGE_ALIGN(0x4000)
++
++struct pvr2_dvb_adapter {
++ struct pvr2_channel channel;
++
++ struct dvb_adapter dvb_adap;
++ struct dmxdev dmxdev;
++ struct dvb_demux demux;
++ struct dvb_net dvb_net;
++ struct dvb_frontend *fe;
++
++ int feedcount;
++ int max_feed_count;
++
++ struct task_struct *thread;
++ struct mutex lock;
++
++ unsigned int stream_run:1;
++
++ wait_queue_head_t buffer_wait_data;
++ char *buffer_storage[PVR2_DVB_BUFFER_COUNT];
++};
++
++struct pvr2_dvb_props {
++ int (*frontend_attach) (struct pvr2_dvb_adapter *);
++ int (*tuner_attach) (struct pvr2_dvb_adapter *);
++};
++
++struct pvr2_dvb_adapter *pvr2_dvb_create(struct pvr2_context *pvr);
++
++#endif /* __PVRUSB2_DVB_H__ */
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c
+index 6406287..c46d367 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c
+@@ -278,11 +278,20 @@ static int pvr2_encoder_cmd(void *ctxt,
+ ret = -EBUSY;
+ }
+ if (ret) {
++ del_timer_sync(&hdw->encoder_run_timer);
+ hdw->state_encoder_ok = 0;
+ pvr2_trace(PVR2_TRACE_STBITS,
+ "State bit %s <-- %s",
+ "state_encoder_ok",
+ (hdw->state_encoder_ok ? "true" : "false"));
++ if (hdw->state_encoder_runok) {
++ hdw->state_encoder_runok = 0;
++ pvr2_trace(PVR2_TRACE_STBITS,
++ "State bit %s <-- %s",
++ "state_encoder_runok",
++ (hdw->state_encoder_runok ?
++ "true" : "false"));
++ }
+ pvr2_trace(
+ PVR2_TRACE_ERROR_LEGS,
+ "Giving up on command."
+@@ -480,10 +489,6 @@ int pvr2_encoder_start(struct pvr2_hdw *hdw)
+ /* unmask some interrupts */
+ pvr2_write_register(hdw, 0x0048, 0xbfffffff);
+
+- /* change some GPIO data */
+- pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000481);
+- pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
+-
+ pvr2_encoder_vcmd(hdw,CX2341X_ENC_MUTE_VIDEO,1,
+ hdw->input_val == PVR2_CVAL_INPUT_RADIO ? 1 : 0);
+
+@@ -526,12 +531,6 @@ int pvr2_encoder_stop(struct pvr2_hdw *hdw)
+ break;
+ }
+
+- /* change some GPIO data */
+- /* Note: Bit d7 of dir appears to control the LED. So we shut it
+- off here. */
+- pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000401);
+- pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
+-
+ return status;
+ }
+
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h b/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h
+index ffbc6d0..abaada3 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h
++++ b/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h
+@@ -22,32 +22,41 @@
+ #ifndef _PVRUSB2_FX2_CMD_H_
+ #define _PVRUSB2_FX2_CMD_H_
+
+-#define FX2CMD_MEM_WRITE_DWORD 0x01
+-#define FX2CMD_MEM_READ_DWORD 0x02
++#define FX2CMD_MEM_WRITE_DWORD 0x01u
++#define FX2CMD_MEM_READ_DWORD 0x02u
+
+-#define FX2CMD_MEM_READ_64BYTES 0x28
++#define FX2CMD_MEM_READ_64BYTES 0x28u
+
+-#define FX2CMD_REG_WRITE 0x04
+-#define FX2CMD_REG_READ 0x05
+-#define FX2CMD_MEMSEL 0x06
++#define FX2CMD_REG_WRITE 0x04u
++#define FX2CMD_REG_READ 0x05u
++#define FX2CMD_MEMSEL 0x06u
+
+-#define FX2CMD_I2C_WRITE 0x08
+-#define FX2CMD_I2C_READ 0x09
++#define FX2CMD_I2C_WRITE 0x08u
++#define FX2CMD_I2C_READ 0x09u
+
+-#define FX2CMD_GET_USB_SPEED 0x0b
++#define FX2CMD_GET_USB_SPEED 0x0bu
+
+-#define FX2CMD_STREAMING_ON 0x36
+-#define FX2CMD_STREAMING_OFF 0x37
++#define FX2CMD_STREAMING_ON 0x36u
++#define FX2CMD_STREAMING_OFF 0x37u
+
+-#define FX2CMD_FWPOST1 0x52
++#define FX2CMD_FWPOST1 0x52u
+
+-#define FX2CMD_POWER_OFF 0xdc
+-#define FX2CMD_POWER_ON 0xde
++#define FX2CMD_POWER_OFF 0xdcu
++#define FX2CMD_POWER_ON 0xdeu
+
+-#define FX2CMD_DEEP_RESET 0xdd
++#define FX2CMD_DEEP_RESET 0xddu
+
+-#define FX2CMD_GET_EEPROM_ADDR 0xeb
+-#define FX2CMD_GET_IR_CODE 0xec
++#define FX2CMD_GET_EEPROM_ADDR 0xebu
++#define FX2CMD_GET_IR_CODE 0xecu
++
++#define FX2CMD_HCW_DEMOD_RESETIN 0xf0u
++#define FX2CMD_HCW_DTV_STREAMING_ON 0xf1u
++#define FX2CMD_HCW_DTV_STREAMING_OFF 0xf2u
++
++#define FX2CMD_ONAIR_DTV_STREAMING_ON 0xa0u
++#define FX2CMD_ONAIR_DTV_STREAMING_OFF 0xa1u
++#define FX2CMD_ONAIR_DTV_POWER_ON 0xa2u
++#define FX2CMD_ONAIR_DTV_POWER_OFF 0xa3u
+
+ #endif /* _PVRUSB2_FX2_CMD_H_ */
+
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
+index d7a216b..a3fe251 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
++++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
+@@ -163,6 +163,11 @@ struct pvr2_decoder_ctrl {
+ #define FW1_STATE_RELOAD 3
+ #define FW1_STATE_OK 4
+
++/* What state the device is in if it is a hybrid */
++#define PVR2_PATHWAY_UNKNOWN 0
++#define PVR2_PATHWAY_ANALOG 1
++#define PVR2_PATHWAY_DIGITAL 2
++
+ typedef int (*pvr2_i2c_func)(struct pvr2_hdw *,u8,u8 *,u16,u8 *, u16);
+ #define PVR2_I2C_FUNC_CNT 128
+
+@@ -182,7 +187,6 @@ struct pvr2_hdw {
+ struct workqueue_struct *workqueue;
+ struct work_struct workpoll; /* Update driver state */
+ struct work_struct worki2csync; /* Update i2c clients */
+- struct work_struct workinit; /* Driver initialization sequence */
+
+ /* Video spigot */
+ struct pvr2_stream *vid_stream;
+@@ -229,17 +233,19 @@ struct pvr2_hdw {
+
+ /* Bits of state that describe what is going on with various parts
+ of the driver. */
++ int state_pathway_ok; /* Pathway config is ok */
+ int state_encoder_ok; /* Encoder is operational */
+ int state_encoder_run; /* Encoder is running */
+ int state_encoder_config; /* Encoder is configured */
+ int state_encoder_waitok; /* Encoder pre-wait done */
++ int state_encoder_runok; /* Encoder has run for >= .25 sec */
+ int state_decoder_run; /* Decoder is running */
+ int state_usbstream_run; /* FX2 is streaming */
+ int state_decoder_quiescent; /* Decoder idle for > 50msec */
+ int state_pipeline_config; /* Pipeline is configured */
+- int state_pipeline_req; /* Somebody wants to stream */
+- int state_pipeline_pause; /* Pipeline must be paused */
+- int state_pipeline_idle; /* Pipeline not running */
++ int state_pipeline_req; /* Somebody wants to stream */
++ int state_pipeline_pause; /* Pipeline must be paused */
++ int state_pipeline_idle; /* Pipeline not running */
+
+ /* This is the master state of the driver. It is the combined
+ result of other bits of state. Examining this will indicate the
+@@ -247,6 +253,9 @@ struct pvr2_hdw {
+ PVR2_STATE_xxxx */
+ unsigned int master_state;
+
++ /* True if device led is currently on */
++ int led_on;
++
+ /* True if states must be re-evaluated */
+ int state_stale;
+
+@@ -259,6 +268,9 @@ struct pvr2_hdw {
+ /* Timer for measuring encoder pre-wait time */
+ struct timer_list encoder_wait_timer;
+
++ /* Timer for measuring encoder minimum run time */
++ struct timer_list encoder_run_timer;
++
+ /* Place to block while waiting for state changes */
+ wait_queue_head_t state_wait_data;
+
+@@ -267,6 +279,7 @@ struct pvr2_hdw {
+ int flag_disconnected; /* flag_ok == 0 due to disconnect */
+ int flag_init_ok; /* true if structure is fully initialized */
+ int fw1_state; /* current situation with fw1 */
++ int pathway_state; /* one of PVR2_PATHWAY_xxx */
+ int flag_decoder_missed;/* We've noticed missing decoder */
+ int flag_tripped; /* Indicates overall failure to start */
+
+@@ -323,6 +336,11 @@ struct pvr2_hdw {
+ int v4l_minor_number_vbi;
+ int v4l_minor_number_radio;
+
++ /* Bit mask of PVR2_CVAL_INPUT choices which are valid for the hardware */
++ unsigned int input_avail_mask;
++ /* Bit mask of PVR2_CVAL_INPUT choices which are currenly allowed */
++ unsigned int input_allowed_mask;
++
+ /* Location of eeprom or a negative number if none */
+ int eeprom_addr;
+
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+index d6955fa..0a86888 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+@@ -25,7 +25,6 @@
+ #include <linux/firmware.h>
+ #include <linux/videodev2.h>
+ #include <media/v4l2-common.h>
+-#include <asm/semaphore.h>
+ #include "pvrusb2.h"
+ #include "pvrusb2-std.h"
+ #include "pvrusb2-util.h"
+@@ -44,13 +43,13 @@
+ static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL};
+ static DEFINE_MUTEX(pvr2_unit_mtx);
+
+-static int ctlchg = 0;
++static int ctlchg;
+ static int initusbreset = 1;
+-static int procreload = 0;
++static int procreload;
+ static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 };
+ static int tolerance[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
+ static int video_std[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
+-static int init_pause_msec = 0;
++static int init_pause_msec;
+
+ module_param(ctlchg, int, S_IRUGO|S_IWUSR);
+ MODULE_PARM_DESC(ctlchg, "0=optimize ctl change 1=always accept new ctl value");
+@@ -183,6 +182,7 @@ static const char *control_values_srate[] = {
+
+ static const char *control_values_input[] = {
+ [PVR2_CVAL_INPUT_TV] = "television", /*xawtv needs this name*/
++ [PVR2_CVAL_INPUT_DTV] = "dtv",
+ [PVR2_CVAL_INPUT_RADIO] = "radio",
+ [PVR2_CVAL_INPUT_SVIDEO] = "s-video",
+ [PVR2_CVAL_INPUT_COMPOSITE] = "composite",
+@@ -216,12 +216,45 @@ static const char *pvr2_state_names[] = {
+ };
+
+
++struct pvr2_fx2cmd_descdef {
++ unsigned char id;
++ unsigned char *desc;
++};
++
++static const struct pvr2_fx2cmd_descdef pvr2_fx2cmd_desc[] = {
++ {FX2CMD_MEM_WRITE_DWORD, "write encoder dword"},
++ {FX2CMD_MEM_READ_DWORD, "read encoder dword"},
++ {FX2CMD_MEM_READ_64BYTES, "read encoder 64bytes"},
++ {FX2CMD_REG_WRITE, "write encoder register"},
++ {FX2CMD_REG_READ, "read encoder register"},
++ {FX2CMD_MEMSEL, "encoder memsel"},
++ {FX2CMD_I2C_WRITE, "i2c write"},
++ {FX2CMD_I2C_READ, "i2c read"},
++ {FX2CMD_GET_USB_SPEED, "get USB speed"},
++ {FX2CMD_STREAMING_ON, "stream on"},
++ {FX2CMD_STREAMING_OFF, "stream off"},
++ {FX2CMD_FWPOST1, "fwpost1"},
++ {FX2CMD_POWER_OFF, "power off"},
++ {FX2CMD_POWER_ON, "power on"},
++ {FX2CMD_DEEP_RESET, "deep reset"},
++ {FX2CMD_GET_EEPROM_ADDR, "get rom addr"},
++ {FX2CMD_GET_IR_CODE, "get IR code"},
++ {FX2CMD_HCW_DEMOD_RESETIN, "hcw demod resetin"},
++ {FX2CMD_HCW_DTV_STREAMING_ON, "hcw dtv stream on"},
++ {FX2CMD_HCW_DTV_STREAMING_OFF, "hcw dtv stream off"},
++ {FX2CMD_ONAIR_DTV_STREAMING_ON, "onair dtv stream on"},
++ {FX2CMD_ONAIR_DTV_STREAMING_OFF, "onair dtv stream off"},
++ {FX2CMD_ONAIR_DTV_POWER_ON, "onair dtv power on"},
++ {FX2CMD_ONAIR_DTV_POWER_OFF, "onair dtv power off"},
++};
++
++
++static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v);
+ static void pvr2_hdw_state_sched(struct pvr2_hdw *);
+ static int pvr2_hdw_state_eval(struct pvr2_hdw *);
+ static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long);
+ static void pvr2_hdw_worker_i2c(struct work_struct *work);
+ static void pvr2_hdw_worker_poll(struct work_struct *work);
+-static void pvr2_hdw_worker_init(struct work_struct *work);
+ static int pvr2_hdw_wait(struct pvr2_hdw *,int state);
+ static int pvr2_hdw_untrip_unlocked(struct pvr2_hdw *);
+ static void pvr2_hdw_state_log_state(struct pvr2_hdw *);
+@@ -232,6 +265,8 @@ static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw);
+ static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw);
+ static void pvr2_hdw_quiescent_timeout(unsigned long);
+ static void pvr2_hdw_encoder_wait_timeout(unsigned long);
++static void pvr2_hdw_encoder_run_timeout(unsigned long);
++static int pvr2_issue_simple_cmd(struct pvr2_hdw *,u32);
+ static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
+ unsigned int timeout,int probe_fl,
+ void *write_data,unsigned int write_len,
+@@ -368,26 +403,14 @@ static int ctrl_get_input(struct pvr2_ctrl *cptr,int *vp)
+ return 0;
+ }
+
+-static int ctrl_set_input(struct pvr2_ctrl *cptr,int m,int v)
++static int ctrl_check_input(struct pvr2_ctrl *cptr,int v)
+ {
+- struct pvr2_hdw *hdw = cptr->hdw;
+-
+- if (hdw->input_val != v) {
+- hdw->input_val = v;
+- hdw->input_dirty = !0;
+- }
++ return ((1 << v) & cptr->hdw->input_allowed_mask) != 0;
++}
+
+- /* Handle side effects - if we switch to a mode that needs the RF
+- tuner, then select the right frequency choice as well and mark
+- it dirty. */
+- if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+- hdw->freqSelector = 0;
+- hdw->freqDirty = !0;
+- } else if (hdw->input_val == PVR2_CVAL_INPUT_TV) {
+- hdw->freqSelector = 1;
+- hdw->freqDirty = !0;
+- }
+- return 0;
++static int ctrl_set_input(struct pvr2_ctrl *cptr,int m,int v)
++{
++ return pvr2_hdw_set_input(cptr->hdw,v);
+ }
+
+ static int ctrl_isdirty_input(struct pvr2_ctrl *cptr)
+@@ -804,6 +827,7 @@ static const struct pvr2_ctl_info control_defs[] = {
+ .name = "input",
+ .internal_id = PVR2_CID_INPUT,
+ .default_value = PVR2_CVAL_INPUT_TV,
++ .check_value = ctrl_check_input,
+ DEFREF(input),
+ DEFENUM(control_values_input),
+ },{
+@@ -983,7 +1007,7 @@ unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *hdw)
+
+ /* Set the currently tuned frequency and account for all possible
+ driver-core side effects of this action. */
+-void pvr2_hdw_set_cur_freq(struct pvr2_hdw *hdw,unsigned long val)
++static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *hdw,unsigned long val)
+ {
+ if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+ if (hdw->freqSelector) {
+@@ -1196,6 +1220,14 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
+ time we configure the encoder, then we'll fully configure it. */
+ hdw->enc_cur_valid = 0;
+
++ /* Encoder is about to be reset so note that as far as we're
++ concerned now, the encoder has never been run. */
++ del_timer_sync(&hdw->encoder_run_timer);
++ if (hdw->state_encoder_runok) {
++ hdw->state_encoder_runok = 0;
++ trace_stbit("state_encoder_runok",hdw->state_encoder_runok);
++ }
++
+ /* First prepare firmware loading */
+ ret |= pvr2_write_register(hdw, 0x0048, 0xffffffff); /*interrupt mask*/
+ ret |= pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000088); /*gpio dir*/
+@@ -1213,19 +1245,14 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
+ ret |= pvr2_write_register(hdw, 0xaa04, 0x00057810); /*unknown*/
+ ret |= pvr2_write_register(hdw, 0xaa10, 0x00148500); /*unknown*/
+ ret |= pvr2_write_register(hdw, 0xaa18, 0x00840000); /*unknown*/
+- LOCK_TAKE(hdw->ctl_lock); do {
+- hdw->cmd_buffer[0] = FX2CMD_FWPOST1;
+- ret |= pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
+- hdw->cmd_buffer[0] = FX2CMD_MEMSEL;
+- hdw->cmd_buffer[1] = 0;
+- ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,NULL,0);
+- } while (0); LOCK_GIVE(hdw->ctl_lock);
++ ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_FWPOST1);
++ ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_MEMSEL | (1 << 8) | (0 << 16));
+
+ if (ret) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "firmware2 upload prep failed, ret=%d",ret);
+ release_firmware(fw_entry);
+- return ret;
++ goto done;
+ }
+
+ /* Now send firmware */
+@@ -1238,7 +1265,8 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
+ " must be a multiple of %zu bytes",
+ fw_files[fwidx],sizeof(u32));
+ release_firmware(fw_entry);
+- return -1;
++ ret = -EINVAL;
++ goto done;
+ }
+
+ fw_ptr = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL);
+@@ -1246,7 +1274,8 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
+ release_firmware(fw_entry);
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "failed to allocate memory for firmware2 upload");
+- return -ENOMEM;
++ ret = -ENOMEM;
++ goto done;
+ }
+
+ pipe = usb_sndbulkpipe(hdw->usb_dev, PVR2_FIRMWARE_ENDPOINT);
+@@ -1277,23 +1306,27 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
+ if (ret) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "firmware2 upload transfer failure");
+- return ret;
++ goto done;
+ }
+
+ /* Finish upload */
+
+ ret |= pvr2_write_register(hdw, 0x9054, 0xffffffff); /*reset hw blocks*/
+ ret |= pvr2_write_register(hdw, 0x9058, 0xffffffe8); /*VPU ctrl*/
+- LOCK_TAKE(hdw->ctl_lock); do {
+- hdw->cmd_buffer[0] = FX2CMD_MEMSEL;
+- hdw->cmd_buffer[1] = 0;
+- ret |= pvr2_send_request(hdw,hdw->cmd_buffer,2,NULL,0);
+- } while (0); LOCK_GIVE(hdw->ctl_lock);
++ ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_MEMSEL | (1 << 8) | (0 << 16));
+
+ if (ret) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "firmware2 upload post-proc failure");
+ }
++
++ done:
++ if (hdw->hdw_desc->signal_routing_scheme ==
++ PVR2_ROUTING_SCHEME_GOTVIEW) {
++ /* Ensure that GPIO 11 is set to output for GOTVIEW
++ hardware. */
++ pvr2_hdw_gpio_chg_dir(hdw,(1 << 11),~0);
++ }
+ return ret;
+ }
+
+@@ -1365,11 +1398,6 @@ int pvr2_hdw_untrip(struct pvr2_hdw *hdw)
+ }
+
+
+-const char *pvr2_hdw_get_state_name(unsigned int id)
+-{
+- if (id >= ARRAY_SIZE(pvr2_state_names)) return NULL;
+- return pvr2_state_names[id];
+-}
+
+
+ int pvr2_hdw_get_streaming(struct pvr2_hdw *hdw)
+@@ -1496,7 +1524,7 @@ struct pvr2_std_hack {
+ default - which can always be overridden explicitly - and if the user
+ has otherwise named a default then that default will always be used in
+ place of this table. */
+-const static struct pvr2_std_hack std_eeprom_maps[] = {
++static const struct pvr2_std_hack std_eeprom_maps[] = {
+ { /* PAL(B/G) */
+ .pat = V4L2_STD_B|V4L2_STD_GH,
+ .std = V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_PAL_G,
+@@ -1713,6 +1741,13 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
+
+ if (!pvr2_hdw_dev_ok(hdw)) return;
+
++ if (hdw->hdw_desc->signal_routing_scheme ==
++ PVR2_ROUTING_SCHEME_GOTVIEW) {
++ /* Ensure that GPIO 11 is set to output for GOTVIEW
++ hardware. */
++ pvr2_hdw_gpio_chg_dir(hdw,(1 << 11),~0);
++ }
++
+ pvr2_hdw_commit_setup(hdw);
+
+ hdw->vid_stream = pvr2_stream_create();
+@@ -1806,12 +1841,37 @@ static void pvr2_hdw_setup(struct pvr2_hdw *hdw)
+ }
+
+
+-/* Create and return a structure for interacting with the underlying
+- hardware */
++/* Perform second stage initialization. Set callback pointer first so that
++ we can avoid a possible initialization race (if the kernel thread runs
++ before the callback has been set). */
++int pvr2_hdw_initialize(struct pvr2_hdw *hdw,
++ void (*callback_func)(void *),
++ void *callback_data)
++{
++ LOCK_TAKE(hdw->big_lock); do {
++ if (hdw->flag_disconnected) {
++ /* Handle a race here: If we're already
++ disconnected by this point, then give up. If we
++ get past this then we'll remain connected for
++ the duration of initialization since the entire
++ initialization sequence is now protected by the
++ big_lock. */
++ break;
++ }
++ hdw->state_data = callback_data;
++ hdw->state_func = callback_func;
++ pvr2_hdw_setup(hdw);
++ } while (0); LOCK_GIVE(hdw->big_lock);
++ return hdw->flag_init_ok;
++}
++
++
++/* Create, set up, and return a structure for interacting with the
++ underlying hardware. */
+ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
+ const struct usb_device_id *devid)
+ {
+- unsigned int idx,cnt1,cnt2;
++ unsigned int idx,cnt1,cnt2,m;
+ struct pvr2_hdw *hdw;
+ int valid_std_mask;
+ struct pvr2_ctrl *cptr;
+@@ -1835,6 +1895,10 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
+ hdw->encoder_wait_timer.data = (unsigned long)hdw;
+ hdw->encoder_wait_timer.function = pvr2_hdw_encoder_wait_timeout;
+
++ init_timer(&hdw->encoder_run_timer);
++ hdw->encoder_run_timer.data = (unsigned long)hdw;
++ hdw->encoder_run_timer.function = pvr2_hdw_encoder_run_timeout;
++
+ hdw->master_state = PVR2_STATE_DEAD;
+
+ init_waitqueue_head(&hdw->state_wait_data);
+@@ -1842,6 +1906,26 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
+ hdw->tuner_signal_stale = !0;
+ cx2341x_fill_defaults(&hdw->enc_ctl_state);
+
++ /* Calculate which inputs are OK */
++ m = 0;
++ if (hdw_desc->flag_has_analogtuner) m |= 1 << PVR2_CVAL_INPUT_TV;
++ if (hdw_desc->digital_control_scheme != PVR2_DIGITAL_SCHEME_NONE) {
++ m |= 1 << PVR2_CVAL_INPUT_DTV;
++ }
++ if (hdw_desc->flag_has_svideo) m |= 1 << PVR2_CVAL_INPUT_SVIDEO;
++ if (hdw_desc->flag_has_composite) m |= 1 << PVR2_CVAL_INPUT_COMPOSITE;
++ if (hdw_desc->flag_has_fmradio) m |= 1 << PVR2_CVAL_INPUT_RADIO;
++ hdw->input_avail_mask = m;
++ hdw->input_allowed_mask = hdw->input_avail_mask;
++
++ /* If not a hybrid device, pathway_state never changes. So
++ initialize it here to what it should forever be. */
++ if (!(hdw->input_avail_mask & (1 << PVR2_CVAL_INPUT_DTV))) {
++ hdw->pathway_state = PVR2_PATHWAY_ANALOG;
++ } else if (!(hdw->input_avail_mask & (1 << PVR2_CVAL_INPUT_TV))) {
++ hdw->pathway_state = PVR2_PATHWAY_DIGITAL;
++ }
++
+ hdw->control_cnt = CTRLDEF_COUNT;
+ hdw->control_cnt += MPEGDEF_COUNT;
+ hdw->controls = kzalloc(sizeof(struct pvr2_ctrl) * hdw->control_cnt,
+@@ -1859,6 +1943,15 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
+ cptr = hdw->controls + idx;
+ cptr->info = control_defs+idx;
+ }
++
++ /* Ensure that default input choice is a valid one. */
++ m = hdw->input_avail_mask;
++ if (m) for (idx = 0; idx < (sizeof(m) << 3); idx++) {
++ if (!((1 << idx) & m)) continue;
++ hdw->input_val = idx;
++ break;
++ }
++
+ /* Define and configure additional controls from cx2341x module. */
+ hdw->mpeg_ctrl_info = kzalloc(
+ sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT, GFP_KERNEL);
+@@ -1982,7 +2075,6 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
+ hdw->workqueue = create_singlethread_workqueue(hdw->name);
+ INIT_WORK(&hdw->workpoll,pvr2_hdw_worker_poll);
+ INIT_WORK(&hdw->worki2csync,pvr2_hdw_worker_i2c);
+- INIT_WORK(&hdw->workinit,pvr2_hdw_worker_init);
+
+ pvr2_trace(PVR2_TRACE_INIT,"Driver unit number is %d, name is %s",
+ hdw->unit_number,hdw->name);
+@@ -2004,11 +2096,11 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
+ mutex_init(&hdw->ctl_lock_mutex);
+ mutex_init(&hdw->big_lock_mutex);
+
+- queue_work(hdw->workqueue,&hdw->workinit);
+ return hdw;
+ fail:
+ if (hdw) {
+ del_timer_sync(&hdw->quiescent_timer);
++ del_timer_sync(&hdw->encoder_run_timer);
+ del_timer_sync(&hdw->encoder_wait_timer);
+ if (hdw->workqueue) {
+ flush_workqueue(hdw->workqueue);
+@@ -2065,13 +2157,14 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw)
+ {
+ if (!hdw) return;
+ pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_destroy: hdw=%p",hdw);
+- del_timer_sync(&hdw->quiescent_timer);
+- del_timer_sync(&hdw->encoder_wait_timer);
+ if (hdw->workqueue) {
+ flush_workqueue(hdw->workqueue);
+ destroy_workqueue(hdw->workqueue);
+ hdw->workqueue = NULL;
+ }
++ del_timer_sync(&hdw->quiescent_timer);
++ del_timer_sync(&hdw->encoder_run_timer);
++ del_timer_sync(&hdw->encoder_wait_timer);
+ if (hdw->fw_buffer) {
+ kfree(hdw->fw_buffer);
+ hdw->fw_buffer = NULL;
+@@ -2353,6 +2446,18 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
+ }
+ }
+
++ if (hdw->input_dirty && hdw->state_pathway_ok &&
++ (((hdw->input_val == PVR2_CVAL_INPUT_DTV) ?
++ PVR2_PATHWAY_DIGITAL : PVR2_PATHWAY_ANALOG) !=
++ hdw->pathway_state)) {
++ /* Change of mode being asked for... */
++ hdw->state_pathway_ok = 0;
++ trace_stbit("state_pathway_ok",hdw->state_pathway_ok);
++ }
++ if (!hdw->state_pathway_ok) {
++ /* Can't commit anything until pathway is ok. */
++ return 0;
++ }
+ /* If any of the below has changed, then we can't do the update
+ while the pipeline is running. Pipeline must be paused first
+ and decoder -> encoder connection be made quiescent before we
+@@ -2406,12 +2511,28 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
+ hdw->active_stream_type = hdw->desired_stream_type;
+ }
+
++ if (hdw->hdw_desc->signal_routing_scheme ==
++ PVR2_ROUTING_SCHEME_GOTVIEW) {
++ u32 b;
++ /* Handle GOTVIEW audio switching */
++ pvr2_hdw_gpio_get_out(hdw,&b);
++ if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
++ /* Set GPIO 11 */
++ pvr2_hdw_gpio_chg_out(hdw,(1 << 11),~0);
++ } else {
++ /* Clear GPIO 11 */
++ pvr2_hdw_gpio_chg_out(hdw,(1 << 11),0);
++ }
++ }
++
+ /* Now execute i2c core update */
+ pvr2_i2c_core_sync(hdw);
+
+- if (hdw->state_encoder_run) {
+- /* If encoder isn't running, then this will get worked out
+- later when we start the encoder. */
++ if ((hdw->pathway_state == PVR2_PATHWAY_ANALOG) &&
++ hdw->state_encoder_run) {
++ /* If encoder isn't running or it can't be touched, then
++ this will get worked out later when we start the
++ encoder. */
+ if (pvr2_encoder_adjust(hdw) < 0) return !0;
+ }
+
+@@ -2454,15 +2575,6 @@ static void pvr2_hdw_worker_poll(struct work_struct *work)
+ }
+
+
+-static void pvr2_hdw_worker_init(struct work_struct *work)
+-{
+- struct pvr2_hdw *hdw = container_of(work,struct pvr2_hdw,workinit);
+- LOCK_TAKE(hdw->big_lock); do {
+- pvr2_hdw_setup(hdw);
+- } while (0); LOCK_GIVE(hdw->big_lock);
+-}
+-
+-
+ static int pvr2_hdw_wait(struct pvr2_hdw *hdw,int state)
+ {
+ return wait_event_interruptible(
+@@ -2472,17 +2584,6 @@ static int pvr2_hdw_wait(struct pvr2_hdw *hdw,int state)
+ }
+
+
+-void pvr2_hdw_set_state_callback(struct pvr2_hdw *hdw,
+- void (*callback_func)(void *),
+- void *callback_data)
+-{
+- LOCK_TAKE(hdw->big_lock); do {
+- hdw->state_data = callback_data;
+- hdw->state_func = callback_func;
+- } while (0); LOCK_GIVE(hdw->big_lock);
+-}
+-
+-
+ /* Return name for this driver instance */
+ const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw)
+ {
+@@ -3051,6 +3152,67 @@ int pvr2_send_request(struct pvr2_hdw *hdw,
+ read_data,read_len);
+ }
+
++
++static int pvr2_issue_simple_cmd(struct pvr2_hdw *hdw,u32 cmdcode)
++{
++ int ret;
++ unsigned int cnt = 1;
++ unsigned int args = 0;
++ LOCK_TAKE(hdw->ctl_lock);
++ hdw->cmd_buffer[0] = cmdcode & 0xffu;
++ args = (cmdcode >> 8) & 0xffu;
++ args = (args > 2) ? 2 : args;
++ if (args) {
++ cnt += args;
++ hdw->cmd_buffer[1] = (cmdcode >> 16) & 0xffu;
++ if (args > 1) {
++ hdw->cmd_buffer[2] = (cmdcode >> 24) & 0xffu;
++ }
++ }
++ if (pvrusb2_debug & PVR2_TRACE_INIT) {
++ unsigned int idx;
++ unsigned int ccnt,bcnt;
++ char tbuf[50];
++ cmdcode &= 0xffu;
++ bcnt = 0;
++ ccnt = scnprintf(tbuf+bcnt,
++ sizeof(tbuf)-bcnt,
++ "Sending FX2 command 0x%x",cmdcode);
++ bcnt += ccnt;
++ for (idx = 0; idx < ARRAY_SIZE(pvr2_fx2cmd_desc); idx++) {
++ if (pvr2_fx2cmd_desc[idx].id == cmdcode) {
++ ccnt = scnprintf(tbuf+bcnt,
++ sizeof(tbuf)-bcnt,
++ " \"%s\"",
++ pvr2_fx2cmd_desc[idx].desc);
++ bcnt += ccnt;
++ break;
++ }
++ }
++ if (args) {
++ ccnt = scnprintf(tbuf+bcnt,
++ sizeof(tbuf)-bcnt,
++ " (%u",hdw->cmd_buffer[1]);
++ bcnt += ccnt;
++ if (args > 1) {
++ ccnt = scnprintf(tbuf+bcnt,
++ sizeof(tbuf)-bcnt,
++ ",%u",hdw->cmd_buffer[2]);
++ bcnt += ccnt;
++ }
++ ccnt = scnprintf(tbuf+bcnt,
++ sizeof(tbuf)-bcnt,
++ ")");
++ bcnt += ccnt;
++ }
++ pvr2_trace(PVR2_TRACE_INIT,"%.*s",bcnt,tbuf);
++ }
++ ret = pvr2_send_request(hdw,hdw->cmd_buffer,cnt,NULL,0);
++ LOCK_GIVE(hdw->ctl_lock);
++ return ret;
++}
++
++
+ int pvr2_write_register(struct pvr2_hdw *hdw, u16 reg, u32 data)
+ {
+ int ret;
+@@ -3158,25 +3320,19 @@ void pvr2_hdw_cpureset_assert(struct pvr2_hdw *hdw,int val)
+
+ int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *hdw)
+ {
+- int status;
+- LOCK_TAKE(hdw->ctl_lock); do {
+- pvr2_trace(PVR2_TRACE_INIT,"Requesting uproc hard reset");
+- hdw->cmd_buffer[0] = FX2CMD_DEEP_RESET;
+- status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
+- } while (0); LOCK_GIVE(hdw->ctl_lock);
+- return status;
++ return pvr2_issue_simple_cmd(hdw,FX2CMD_DEEP_RESET);
+ }
+
+
+ int pvr2_hdw_cmd_powerup(struct pvr2_hdw *hdw)
+ {
+- int status;
+- LOCK_TAKE(hdw->ctl_lock); do {
+- pvr2_trace(PVR2_TRACE_INIT,"Requesting powerup");
+- hdw->cmd_buffer[0] = FX2CMD_POWER_ON;
+- status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
+- } while (0); LOCK_GIVE(hdw->ctl_lock);
+- return status;
++ return pvr2_issue_simple_cmd(hdw,FX2CMD_POWER_ON);
++}
++
++
++int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *hdw)
++{
++ return pvr2_issue_simple_cmd(hdw,FX2CMD_POWER_OFF);
+ }
+
+
+@@ -3201,16 +3357,173 @@ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw)
+ }
+
+
++static int pvr2_hdw_cmd_hcw_demod_reset(struct pvr2_hdw *hdw, int onoff)
++{
++ hdw->flag_ok = !0;
++ return pvr2_issue_simple_cmd(hdw,
++ FX2CMD_HCW_DEMOD_RESETIN |
++ (1 << 8) |
++ ((onoff ? 1 : 0) << 16));
++}
++
++
++static int pvr2_hdw_cmd_onair_fe_power_ctrl(struct pvr2_hdw *hdw, int onoff)
++{
++ hdw->flag_ok = !0;
++ return pvr2_issue_simple_cmd(hdw,(onoff ?
++ FX2CMD_ONAIR_DTV_POWER_ON :
++ FX2CMD_ONAIR_DTV_POWER_OFF));
++}
++
++
++static int pvr2_hdw_cmd_onair_digital_path_ctrl(struct pvr2_hdw *hdw,
++ int onoff)
++{
++ return pvr2_issue_simple_cmd(hdw,(onoff ?
++ FX2CMD_ONAIR_DTV_STREAMING_ON :
++ FX2CMD_ONAIR_DTV_STREAMING_OFF));
++}
++
++
++static void pvr2_hdw_cmd_modeswitch(struct pvr2_hdw *hdw,int digitalFl)
++{
++ int cmode;
++ /* Compare digital/analog desired setting with current setting. If
++ they don't match, fix it... */
++ cmode = (digitalFl ? PVR2_PATHWAY_DIGITAL : PVR2_PATHWAY_ANALOG);
++ if (cmode == hdw->pathway_state) {
++ /* They match; nothing to do */
++ return;
++ }
++
++ switch (hdw->hdw_desc->digital_control_scheme) {
++ case PVR2_DIGITAL_SCHEME_HAUPPAUGE:
++ pvr2_hdw_cmd_hcw_demod_reset(hdw,digitalFl);
++ if (cmode == PVR2_PATHWAY_ANALOG) {
++ /* If moving to analog mode, also force the decoder
++ to reset. If no decoder is attached, then it's
++ ok to ignore this because if/when the decoder
++ attaches, it will reset itself at that time. */
++ pvr2_hdw_cmd_decoder_reset(hdw);
++ }
++ break;
++ case PVR2_DIGITAL_SCHEME_ONAIR:
++ /* Supposedly we should always have the power on whether in
++ digital or analog mode. But for now do what appears to
++ work... */
++ pvr2_hdw_cmd_onair_fe_power_ctrl(hdw,digitalFl);
++ break;
++ default: break;
++ }
++
++ pvr2_hdw_untrip_unlocked(hdw);
++ hdw->pathway_state = cmode;
++}
++
++
++void pvr2_led_ctrl_hauppauge(struct pvr2_hdw *hdw, int onoff)
++{
++ /* change some GPIO data
++ *
++ * note: bit d7 of dir appears to control the LED,
++ * so we shut it off here.
++ *
++ */
++ if (onoff) {
++ pvr2_hdw_gpio_chg_dir(hdw, 0xffffffff, 0x00000481);
++ } else {
++ pvr2_hdw_gpio_chg_dir(hdw, 0xffffffff, 0x00000401);
++ }
++ pvr2_hdw_gpio_chg_out(hdw, 0xffffffff, 0x00000000);
++}
++
++
++typedef void (*led_method_func)(struct pvr2_hdw *,int);
++
++static led_method_func led_methods[] = {
++ [PVR2_LED_SCHEME_HAUPPAUGE] = pvr2_led_ctrl_hauppauge,
++};
++
++
++/* Toggle LED */
++static void pvr2_led_ctrl(struct pvr2_hdw *hdw,int onoff)
++{
++ unsigned int scheme_id;
++ led_method_func fp;
++
++ if ((!onoff) == (!hdw->led_on)) return;
++
++ hdw->led_on = onoff != 0;
++
++ scheme_id = hdw->hdw_desc->led_scheme;
++ if (scheme_id < ARRAY_SIZE(led_methods)) {
++ fp = led_methods[scheme_id];
++ } else {
++ fp = NULL;
++ }
++
++ if (fp) (*fp)(hdw,onoff);
++}
++
++
+ /* Stop / start video stream transport */
+ static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl)
+ {
+- int status;
+- LOCK_TAKE(hdw->ctl_lock); do {
+- hdw->cmd_buffer[0] =
+- (runFl ? FX2CMD_STREAMING_ON : FX2CMD_STREAMING_OFF);
+- status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
+- } while (0); LOCK_GIVE(hdw->ctl_lock);
+- return status;
++ int ret;
++
++ /* If we're in analog mode, then just issue the usual analog
++ command. */
++ if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) {
++ return pvr2_issue_simple_cmd(hdw,
++ (runFl ?
++ FX2CMD_STREAMING_ON :
++ FX2CMD_STREAMING_OFF));
++ /*Note: Not reached */
++ }
++
++ if (hdw->pathway_state != PVR2_PATHWAY_DIGITAL) {
++ /* Whoops, we don't know what mode we're in... */
++ return -EINVAL;
++ }
++
++ /* To get here we have to be in digital mode. The mechanism here
++ is unfortunately different for different vendors. So we switch
++ on the device's digital scheme attribute in order to figure out
++ what to do. */
++ switch (hdw->hdw_desc->digital_control_scheme) {
++ case PVR2_DIGITAL_SCHEME_HAUPPAUGE:
++ return pvr2_issue_simple_cmd(hdw,
++ (runFl ?
++ FX2CMD_HCW_DTV_STREAMING_ON :
++ FX2CMD_HCW_DTV_STREAMING_OFF));
++ case PVR2_DIGITAL_SCHEME_ONAIR:
++ ret = pvr2_issue_simple_cmd(hdw,
++ (runFl ?
++ FX2CMD_STREAMING_ON :
++ FX2CMD_STREAMING_OFF));
++ if (ret) return ret;
++ return pvr2_hdw_cmd_onair_digital_path_ctrl(hdw,runFl);
++ default:
++ return -EINVAL;
++ }
++}
++
++
++/* Evaluate whether or not state_pathway_ok can change */
++static int state_eval_pathway_ok(struct pvr2_hdw *hdw)
++{
++ if (hdw->state_pathway_ok) {
++ /* Nothing to do if pathway is already ok */
++ return 0;
++ }
++ if (!hdw->state_pipeline_idle) {
++ /* Not allowed to change anything if pipeline is not idle */
++ return 0;
++ }
++ pvr2_hdw_cmd_modeswitch(hdw,hdw->input_val == PVR2_CVAL_INPUT_DTV);
++ hdw->state_pathway_ok = !0;
++ trace_stbit("state_pathway_ok",hdw->state_pathway_ok);
++ return !0;
+ }
+
+
+@@ -3223,6 +3536,12 @@ static int state_eval_encoder_ok(struct pvr2_hdw *hdw)
+ if (hdw->state_encoder_config) return 0;
+ if (hdw->state_decoder_run) return 0;
+ if (hdw->state_usbstream_run) return 0;
++ if (hdw->pathway_state == PVR2_PATHWAY_DIGITAL) {
++ if (!hdw->hdw_desc->flag_digital_requires_cx23416) return 0;
++ } else if (hdw->pathway_state != PVR2_PATHWAY_ANALOG) {
++ return 0;
++ }
++
+ if (pvr2_upload_firmware2(hdw) < 0) {
+ hdw->flag_tripped = !0;
+ trace_stbit("flag_tripped",hdw->flag_tripped);
+@@ -3248,7 +3567,9 @@ static int state_eval_encoder_config(struct pvr2_hdw *hdw)
+ /* paranoia - solve race if timer just completed */
+ del_timer_sync(&hdw->encoder_wait_timer);
+ } else {
+- if (!hdw->state_encoder_ok ||
++ if (!hdw->state_pathway_ok ||
++ (hdw->pathway_state != PVR2_PATHWAY_ANALOG) ||
++ !hdw->state_encoder_ok ||
+ !hdw->state_pipeline_idle ||
+ hdw->state_pipeline_pause ||
+ !hdw->state_pipeline_req ||
+@@ -3297,20 +3618,116 @@ static int state_eval_encoder_config(struct pvr2_hdw *hdw)
+ }
+
+
++/* Return true if the encoder should not be running. */
++static int state_check_disable_encoder_run(struct pvr2_hdw *hdw)
++{
++ if (!hdw->state_encoder_ok) {
++ /* Encoder isn't healthy at the moment, so stop it. */
++ return !0;
++ }
++ if (!hdw->state_pathway_ok) {
++ /* Mode is not understood at the moment (i.e. it wants to
++ change), so encoder must be stopped. */
++ return !0;
++ }
++
++ switch (hdw->pathway_state) {
++ case PVR2_PATHWAY_ANALOG:
++ if (!hdw->state_decoder_run) {
++ /* We're in analog mode and the decoder is not
++ running; thus the encoder should be stopped as
++ well. */
++ return !0;
++ }
++ break;
++ case PVR2_PATHWAY_DIGITAL:
++ if (hdw->state_encoder_runok) {
++ /* This is a funny case. We're in digital mode so
++ really the encoder should be stopped. However
++ if it really is running, only kill it after
++ runok has been set. This gives a chance for the
++ onair quirk to function (encoder must run
++ briefly first, at least once, before onair
++ digital streaming can work). */
++ return !0;
++ }
++ break;
++ default:
++ /* Unknown mode; so encoder should be stopped. */
++ return !0;
++ }
++
++ /* If we get here, we haven't found a reason to stop the
++ encoder. */
++ return 0;
++}
++
++
++/* Return true if the encoder should be running. */
++static int state_check_enable_encoder_run(struct pvr2_hdw *hdw)
++{
++ if (!hdw->state_encoder_ok) {
++ /* Don't run the encoder if it isn't healthy... */
++ return 0;
++ }
++ if (!hdw->state_pathway_ok) {
++ /* Don't run the encoder if we don't (yet) know what mode
++ we need to be in... */
++ return 0;
++ }
++
++ switch (hdw->pathway_state) {
++ case PVR2_PATHWAY_ANALOG:
++ if (hdw->state_decoder_run) {
++ /* In analog mode, if the decoder is running, then
++ run the encoder. */
++ return !0;
++ }
++ break;
++ case PVR2_PATHWAY_DIGITAL:
++ if ((hdw->hdw_desc->digital_control_scheme ==
++ PVR2_DIGITAL_SCHEME_ONAIR) &&
++ !hdw->state_encoder_runok) {
++ /* This is a quirk. OnAir hardware won't stream
++ digital until the encoder has been run at least
++ once, for a minimal period of time (empiricially
++ measured to be 1/4 second). So if we're on
++ OnAir hardware and the encoder has never been
++ run at all, then start the encoder. Normal
++ state machine logic in the driver will
++ automatically handle the remaining bits. */
++ return !0;
++ }
++ break;
++ default:
++ /* For completeness (unknown mode; encoder won't run ever) */
++ break;
++ }
++ /* If we get here, then we haven't found any reason to run the
++ encoder, so don't run it. */
++ return 0;
++}
++
++
+ /* Evaluate whether or not state_encoder_run can change */
+ static int state_eval_encoder_run(struct pvr2_hdw *hdw)
+ {
+ if (hdw->state_encoder_run) {
++ if (!state_check_disable_encoder_run(hdw)) return 0;
+ if (hdw->state_encoder_ok) {
+- if (hdw->state_decoder_run) return 0;
++ del_timer_sync(&hdw->encoder_run_timer);
+ if (pvr2_encoder_stop(hdw) < 0) return !0;
+ }
+ hdw->state_encoder_run = 0;
+ } else {
+- if (!hdw->state_encoder_ok) return 0;
+- if (!hdw->state_decoder_run) return 0;
++ if (!state_check_enable_encoder_run(hdw)) return 0;
+ if (pvr2_encoder_start(hdw) < 0) return !0;
+ hdw->state_encoder_run = !0;
++ if (!hdw->state_encoder_runok) {
++ hdw->encoder_run_timer.expires =
++ jiffies + (HZ*250/1000);
++ add_timer(&hdw->encoder_run_timer);
++ }
+ }
+ trace_stbit("state_encoder_run",hdw->state_encoder_run);
+ return !0;
+@@ -3339,13 +3756,27 @@ static void pvr2_hdw_encoder_wait_timeout(unsigned long data)
+ }
+
+
++/* Timeout function for encoder run timer. */
++static void pvr2_hdw_encoder_run_timeout(unsigned long data)
++{
++ struct pvr2_hdw *hdw = (struct pvr2_hdw *)data;
++ if (!hdw->state_encoder_runok) {
++ hdw->state_encoder_runok = !0;
++ trace_stbit("state_encoder_runok",hdw->state_encoder_runok);
++ hdw->state_stale = !0;
++ queue_work(hdw->workqueue,&hdw->workpoll);
++ }
++}
++
++
+ /* Evaluate whether or not state_decoder_run can change */
+ static int state_eval_decoder_run(struct pvr2_hdw *hdw)
+ {
+ if (hdw->state_decoder_run) {
+ if (hdw->state_encoder_ok) {
+ if (hdw->state_pipeline_req &&
+- !hdw->state_pipeline_pause) return 0;
++ !hdw->state_pipeline_pause &&
++ hdw->state_pathway_ok) return 0;
+ }
+ if (!hdw->flag_decoder_missed) {
+ pvr2_decoder_enable(hdw,0);
+@@ -3378,7 +3809,9 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw)
+ hopefully further stabilize the encoder. */
+ return 0;
+ }
+- if (!hdw->state_pipeline_req ||
++ if (!hdw->state_pathway_ok ||
++ (hdw->pathway_state != PVR2_PATHWAY_ANALOG) ||
++ !hdw->state_pipeline_req ||
+ hdw->state_pipeline_pause ||
+ !hdw->state_pipeline_config ||
+ !hdw->state_encoder_config ||
+@@ -3399,16 +3832,43 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw)
+ static int state_eval_usbstream_run(struct pvr2_hdw *hdw)
+ {
+ if (hdw->state_usbstream_run) {
+- if (hdw->state_encoder_ok) {
+- if (hdw->state_encoder_run) return 0;
++ int fl = !0;
++ if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) {
++ fl = (hdw->state_encoder_ok &&
++ hdw->state_encoder_run);
++ } else if ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) &&
++ (hdw->hdw_desc->flag_digital_requires_cx23416)) {
++ fl = hdw->state_encoder_ok;
++ }
++ if (fl &&
++ hdw->state_pipeline_req &&
++ !hdw->state_pipeline_pause &&
++ hdw->state_pathway_ok) {
++ return 0;
+ }
+ pvr2_hdw_cmd_usbstream(hdw,0);
+ hdw->state_usbstream_run = 0;
+ } else {
+- if (!hdw->state_encoder_ok ||
+- !hdw->state_encoder_run ||
+- !hdw->state_pipeline_req ||
+- hdw->state_pipeline_pause) return 0;
++ if (!hdw->state_pipeline_req ||
++ hdw->state_pipeline_pause ||
++ !hdw->state_pathway_ok) return 0;
++ if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) {
++ if (!hdw->state_encoder_ok ||
++ !hdw->state_encoder_run) return 0;
++ } else if ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) &&
++ (hdw->hdw_desc->flag_digital_requires_cx23416)) {
++ if (!hdw->state_encoder_ok) return 0;
++ if (hdw->state_encoder_run) return 0;
++ if (hdw->hdw_desc->digital_control_scheme ==
++ PVR2_DIGITAL_SCHEME_ONAIR) {
++ /* OnAir digital receivers won't stream
++ unless the analog encoder has run first.
++ Why? I have no idea. But don't even
++ try until we know the analog side is
++ known to have run. */
++ if (!hdw->state_encoder_runok) return 0;
++ }
++ }
+ if (pvr2_hdw_cmd_usbstream(hdw,!0) < 0) return 0;
+ hdw->state_usbstream_run = !0;
+ }
+@@ -3454,7 +3914,8 @@ static int state_update_pipeline_state(struct pvr2_hdw *hdw)
+ typedef int (*state_eval_func)(struct pvr2_hdw *);
+
+ /* Set of functions to be run to evaluate various states in the driver. */
+-const static state_eval_func eval_funcs[] = {
++static const state_eval_func eval_funcs[] = {
++ state_eval_pathway_ok,
+ state_eval_pipeline_config,
+ state_eval_encoder_ok,
+ state_eval_encoder_config,
+@@ -3502,6 +3963,34 @@ static int pvr2_hdw_state_update(struct pvr2_hdw *hdw)
+ }
+
+
++static unsigned int print_input_mask(unsigned int msk,
++ char *buf,unsigned int acnt)
++{
++ unsigned int idx,ccnt;
++ unsigned int tcnt = 0;
++ for (idx = 0; idx < ARRAY_SIZE(control_values_input); idx++) {
++ if (!((1 << idx) & msk)) continue;
++ ccnt = scnprintf(buf+tcnt,
++ acnt-tcnt,
++ "%s%s",
++ (tcnt ? ", " : ""),
++ control_values_input[idx]);
++ tcnt += ccnt;
++ }
++ return tcnt;
++}
++
++
++static const char *pvr2_pathway_state_name(int id)
++{
++ switch (id) {
++ case PVR2_PATHWAY_ANALOG: return "analog";
++ case PVR2_PATHWAY_DIGITAL: return "digital";
++ default: return "unknown";
++ }
++}
++
++
+ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which,
+ char *buf,unsigned int acnt)
+ {
+@@ -3509,13 +3998,15 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which,
+ case 0:
+ return scnprintf(
+ buf,acnt,
+- "driver:%s%s%s%s%s",
++ "driver:%s%s%s%s%s <mode=%s>",
+ (hdw->flag_ok ? " <ok>" : " <fail>"),
+ (hdw->flag_init_ok ? " <init>" : " <uninitialized>"),
+ (hdw->flag_disconnected ? " <disconnected>" :
+ " <connected>"),
+ (hdw->flag_tripped ? " <tripped>" : ""),
+- (hdw->flag_decoder_missed ? " <no decoder>" : ""));
++ (hdw->flag_decoder_missed ? " <no decoder>" : ""),
++ pvr2_pathway_state_name(hdw->pathway_state));
++
+ case 1:
+ return scnprintf(
+ buf,acnt,
+@@ -3528,7 +4019,7 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which,
+ case 2:
+ return scnprintf(
+ buf,acnt,
+- "worker:%s%s%s%s%s%s",
++ "worker:%s%s%s%s%s%s%s",
+ (hdw->state_decoder_run ?
+ " <decode:run>" :
+ (hdw->state_decoder_quiescent ?
+@@ -3538,20 +4029,65 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which,
+ (hdw->state_encoder_ok ?
+ "" : " <encode:init>"),
+ (hdw->state_encoder_run ?
+- " <encode:run>" : " <encode:stop>"),
++ (hdw->state_encoder_runok ?
++ " <encode:run>" :
++ " <encode:firstrun>") :
++ (hdw->state_encoder_runok ?
++ " <encode:stop>" :
++ " <encode:virgin>")),
+ (hdw->state_encoder_config ?
+ " <encode:configok>" :
+ (hdw->state_encoder_waitok ?
+- "" : " <encode:wait>")),
++ "" : " <encode:waitok>")),
+ (hdw->state_usbstream_run ?
+- " <usb:run>" : " <usb:stop>"));
+- break;
++ " <usb:run>" : " <usb:stop>"),
++ (hdw->state_pathway_ok ?
++ " <pathway:ok>" : ""));
+ case 3:
+ return scnprintf(
+ buf,acnt,
+ "state: %s",
+ pvr2_get_state_name(hdw->master_state));
+- break;
++ case 4: {
++ unsigned int tcnt = 0;
++ unsigned int ccnt;
++
++ ccnt = scnprintf(buf,
++ acnt,
++ "Hardware supported inputs: ");
++ tcnt += ccnt;
++ tcnt += print_input_mask(hdw->input_avail_mask,
++ buf+tcnt,
++ acnt-tcnt);
++ if (hdw->input_avail_mask != hdw->input_allowed_mask) {
++ ccnt = scnprintf(buf+tcnt,
++ acnt-tcnt,
++ "; allowed inputs: ");
++ tcnt += ccnt;
++ tcnt += print_input_mask(hdw->input_allowed_mask,
++ buf+tcnt,
++ acnt-tcnt);
++ }
++ return tcnt;
++ }
++ case 5: {
++ struct pvr2_stream_stats stats;
++ if (!hdw->vid_stream) break;
++ pvr2_stream_get_stats(hdw->vid_stream,
++ &stats,
++ 0);
++ return scnprintf(
++ buf,acnt,
++ "Bytes streamed=%u"
++ " URBs: queued=%u idle=%u ready=%u"
++ " processed=%u failed=%u",
++ stats.bytes_processed,
++ stats.buffers_in_queue,
++ stats.buffers_in_idle,
++ stats.buffers_in_ready,
++ stats.buffers_processed,
++ stats.buffers_failed);
++ }
+ default: break;
+ }
+ return 0;
+@@ -3597,6 +4133,7 @@ static int pvr2_hdw_state_eval(struct pvr2_hdw *hdw)
+ unsigned int st;
+ int state_updated = 0;
+ int callback_flag = 0;
++ int analog_mode;
+
+ pvr2_trace(PVR2_TRACE_STBITS,
+ "Drive state check START");
+@@ -3607,18 +4144,23 @@ static int pvr2_hdw_state_eval(struct pvr2_hdw *hdw)
+ /* Process all state and get back over disposition */
+ state_updated = pvr2_hdw_state_update(hdw);
+
++ analog_mode = (hdw->pathway_state != PVR2_PATHWAY_DIGITAL);
++
+ /* Update master state based upon all other states. */
+ if (!hdw->flag_ok) {
+ st = PVR2_STATE_DEAD;
+ } else if (hdw->fw1_state != FW1_STATE_OK) {
+ st = PVR2_STATE_COLD;
+- } else if (!hdw->state_encoder_ok) {
++ } else if ((analog_mode ||
++ hdw->hdw_desc->flag_digital_requires_cx23416) &&
++ !hdw->state_encoder_ok) {
+ st = PVR2_STATE_WARM;
+- } else if (hdw->flag_tripped || hdw->flag_decoder_missed) {
++ } else if (hdw->flag_tripped ||
++ (analog_mode && hdw->flag_decoder_missed)) {
+ st = PVR2_STATE_ERROR;
+- } else if (hdw->state_encoder_run &&
+- hdw->state_decoder_run &&
+- hdw->state_usbstream_run) {
++ } else if (hdw->state_usbstream_run &&
++ (!analog_mode ||
++ (hdw->state_encoder_run && hdw->state_decoder_run))) {
+ st = PVR2_STATE_RUN;
+ } else {
+ st = PVR2_STATE_READY;
+@@ -3628,6 +4170,7 @@ static int pvr2_hdw_state_eval(struct pvr2_hdw *hdw)
+ "Device state change from %s to %s",
+ pvr2_get_state_name(hdw->master_state),
+ pvr2_get_state_name(st));
++ pvr2_led_ctrl(hdw,st == PVR2_STATE_RUN);
+ hdw->master_state = st;
+ state_updated = !0;
+ callback_flag = !0;
+@@ -3657,47 +4200,6 @@ static void pvr2_hdw_state_sched(struct pvr2_hdw *hdw)
+ }
+
+
+-void pvr2_hdw_get_debug_info_unlocked(const struct pvr2_hdw *hdw,
+- struct pvr2_hdw_debug_info *ptr)
+-{
+- ptr->big_lock_held = hdw->big_lock_held;
+- ptr->ctl_lock_held = hdw->ctl_lock_held;
+- ptr->flag_disconnected = hdw->flag_disconnected;
+- ptr->flag_init_ok = hdw->flag_init_ok;
+- ptr->flag_ok = hdw->flag_ok;
+- ptr->fw1_state = hdw->fw1_state;
+- ptr->flag_decoder_missed = hdw->flag_decoder_missed;
+- ptr->flag_tripped = hdw->flag_tripped;
+- ptr->state_encoder_ok = hdw->state_encoder_ok;
+- ptr->state_encoder_run = hdw->state_encoder_run;
+- ptr->state_decoder_run = hdw->state_decoder_run;
+- ptr->state_usbstream_run = hdw->state_usbstream_run;
+- ptr->state_decoder_quiescent = hdw->state_decoder_quiescent;
+- ptr->state_pipeline_config = hdw->state_pipeline_config;
+- ptr->state_pipeline_req = hdw->state_pipeline_req;
+- ptr->state_pipeline_pause = hdw->state_pipeline_pause;
+- ptr->state_pipeline_idle = hdw->state_pipeline_idle;
+- ptr->cmd_debug_state = hdw->cmd_debug_state;
+- ptr->cmd_code = hdw->cmd_debug_code;
+- ptr->cmd_debug_write_len = hdw->cmd_debug_write_len;
+- ptr->cmd_debug_read_len = hdw->cmd_debug_read_len;
+- ptr->cmd_debug_timeout = hdw->ctl_timeout_flag;
+- ptr->cmd_debug_write_pend = hdw->ctl_write_pend_flag;
+- ptr->cmd_debug_read_pend = hdw->ctl_read_pend_flag;
+- ptr->cmd_debug_rstatus = hdw->ctl_read_urb->status;
+- ptr->cmd_debug_wstatus = hdw->ctl_read_urb->status;
+-}
+-
+-
+-void pvr2_hdw_get_debug_info_locked(struct pvr2_hdw *hdw,
+- struct pvr2_hdw_debug_info *ptr)
+-{
+- LOCK_TAKE(hdw->ctl_lock); do {
+- pvr2_hdw_get_debug_info_unlocked(hdw,ptr);
+- } while(0); LOCK_GIVE(hdw->ctl_lock);
+-}
+-
+-
+ int pvr2_hdw_gpio_get_dir(struct pvr2_hdw *hdw,u32 *dp)
+ {
+ return pvr2_read_register(hdw,PVR2_GPIO_DIR,dp);
+@@ -3757,6 +4259,80 @@ int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val)
+ }
+
+
++unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *hdw)
++{
++ return hdw->input_avail_mask;
++}
++
++
++unsigned int pvr2_hdw_get_input_allowed(struct pvr2_hdw *hdw)
++{
++ return hdw->input_allowed_mask;
++}
++
++
++static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v)
++{
++ if (hdw->input_val != v) {
++ hdw->input_val = v;
++ hdw->input_dirty = !0;
++ }
++
++ /* Handle side effects - if we switch to a mode that needs the RF
++ tuner, then select the right frequency choice as well and mark
++ it dirty. */
++ if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
++ hdw->freqSelector = 0;
++ hdw->freqDirty = !0;
++ } else if ((hdw->input_val == PVR2_CVAL_INPUT_TV) ||
++ (hdw->input_val == PVR2_CVAL_INPUT_DTV)) {
++ hdw->freqSelector = 1;
++ hdw->freqDirty = !0;
++ }
++ return 0;
++}
++
++
++int pvr2_hdw_set_input_allowed(struct pvr2_hdw *hdw,
++ unsigned int change_mask,
++ unsigned int change_val)
++{
++ int ret = 0;
++ unsigned int nv,m,idx;
++ LOCK_TAKE(hdw->big_lock);
++ do {
++ nv = hdw->input_allowed_mask & ~change_mask;
++ nv |= (change_val & change_mask);
++ nv &= hdw->input_avail_mask;
++ if (!nv) {
++ /* No legal modes left; return error instead. */
++ ret = -EPERM;
++ break;
++ }
++ hdw->input_allowed_mask = nv;
++ if ((1 << hdw->input_val) & hdw->input_allowed_mask) {
++ /* Current mode is still in the allowed mask, so
++ we're done. */
++ break;
++ }
++ /* Select and switch to a mode that is still in the allowed
++ mask */
++ if (!hdw->input_allowed_mask) {
++ /* Nothing legal; give up */
++ break;
++ }
++ m = hdw->input_allowed_mask;
++ for (idx = 0; idx < (sizeof(m) << 3); idx++) {
++ if (!((1 << idx) & m)) continue;
++ pvr2_hdw_set_input(hdw,idx);
++ break;
++ }
++ } while (0);
++ LOCK_GIVE(hdw->big_lock);
++ return ret;
++}
++
++
+ /* Find I2C address of eeprom */
+ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
+ {
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
+index 3ad7a13..20295e0 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h
++++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
+@@ -40,9 +40,10 @@
+
+ /* Legal values for the INPUT state variable */
+ #define PVR2_CVAL_INPUT_TV 0
+-#define PVR2_CVAL_INPUT_SVIDEO 1
++#define PVR2_CVAL_INPUT_DTV 1
+ #define PVR2_CVAL_INPUT_COMPOSITE 2
+-#define PVR2_CVAL_INPUT_RADIO 3
++#define PVR2_CVAL_INPUT_SVIDEO 3
++#define PVR2_CVAL_INPUT_RADIO 4
+
+ enum pvr2_config {
+ pvr2_config_empty, /* No configuration */
+@@ -90,9 +91,6 @@ enum pvr2_v4l_type {
+ /* Translate configuration enum to a string label */
+ const char *pvr2_config_get_name(enum pvr2_config);
+
+-/* Translate a master state enum to a string label */
+-const char *pvr2_hdw_get_state_name(unsigned int);
+-
+ struct pvr2_hdw;
+
+ /* Create and return a structure for interacting with the underlying
+@@ -100,14 +98,15 @@ struct pvr2_hdw;
+ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
+ const struct usb_device_id *devid);
+
++/* Perform second stage initialization, passing in a notification callback
++ for when the master state changes. */
++int pvr2_hdw_initialize(struct pvr2_hdw *,
++ void (*callback_func)(void *),
++ void *callback_data);
++
+ /* Destroy hardware interaction structure */
+ void pvr2_hdw_destroy(struct pvr2_hdw *);
+
+-/* Register a function to be called whenever the master state changes. */
+-void pvr2_hdw_set_state_callback(struct pvr2_hdw *,
+- void (*callback_func)(void *),
+- void *callback_data);
+-
+ /* Return true if in the ready (normal) state */
+ int pvr2_hdw_dev_ok(struct pvr2_hdw *);
+
+@@ -146,6 +145,23 @@ struct pvr2_ctrl *pvr2_hdw_get_ctrl_nextv4l(struct pvr2_hdw *,
+ /* Commit all control changes made up to this point */
+ int pvr2_hdw_commit_ctl(struct pvr2_hdw *);
+
++/* Return a bit mask of valid input selections for this device. Mask bits
++ * will be according to PVR_CVAL_INPUT_xxxx definitions. */
++unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *);
++
++/* Return a bit mask of allowed input selections for this device. Mask bits
++ * will be according to PVR_CVAL_INPUT_xxxx definitions. */
++unsigned int pvr2_hdw_get_input_allowed(struct pvr2_hdw *);
++
++/* Change the set of allowed input selections for this device. Both
++ change_mask and change_valu are mask bits according to
++ PVR_CVAL_INPUT_xxxx definitions. The change_mask parameter indicate
++ which settings are being changed and the change_val parameter indicates
++ whether corresponding settings are being set or cleared. */
++int pvr2_hdw_set_input_allowed(struct pvr2_hdw *,
++ unsigned int change_mask,
++ unsigned int change_val);
++
+ /* Return name for this driver instance */
+ const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *);
+
+@@ -250,6 +266,9 @@ int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *);
+ /* Execute simple reset command */
+ int pvr2_hdw_cmd_powerup(struct pvr2_hdw *);
+
++/* suspend */
++int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *);
++
+ /* Order decoder to reset */
+ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *);
+
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
+index 62867fa..793c89a 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
+@@ -35,7 +35,7 @@
+
+ */
+
+-static unsigned int i2c_scan = 0;
++static unsigned int i2c_scan;
+ module_param(i2c_scan, int, S_IRUGO|S_IWUSR);
+ MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
+
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.c b/drivers/media/video/pvrusb2/pvrusb2-io.c
+index a9889ff..7aff8b7 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-io.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-io.c
+@@ -80,6 +80,10 @@ struct pvr2_stream {
+ /* Tracking state for tolerating errors */
+ unsigned int fail_count;
+ unsigned int fail_tolerance;
++
++ unsigned int buffers_processed;
++ unsigned int buffers_failed;
++ unsigned int bytes_processed;
+ };
+
+ struct pvr2_buffer {
+@@ -446,6 +450,8 @@ static void buffer_complete(struct urb *urb)
+ (urb->status == -ENOENT) ||
+ (urb->status == -ECONNRESET) ||
+ (urb->status == -ESHUTDOWN)) {
++ (sp->buffers_processed)++;
++ sp->bytes_processed += urb->actual_length;
+ bp->used_count = urb->actual_length;
+ if (sp->fail_count) {
+ pvr2_trace(PVR2_TRACE_TOLERANCE,
+@@ -457,11 +463,13 @@ static void buffer_complete(struct urb *urb)
+ // We can tolerate this error, because we're below the
+ // threshold...
+ (sp->fail_count)++;
++ (sp->buffers_failed)++;
+ pvr2_trace(PVR2_TRACE_TOLERANCE,
+ "stream %p ignoring error %d"
+ " - fail count increased to %u",
+ sp,urb->status,sp->fail_count);
+ } else {
++ (sp->buffers_failed)++;
+ bp->status = urb->status;
+ }
+ spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+@@ -515,6 +523,28 @@ void pvr2_stream_set_callback(struct pvr2_stream *sp,
+ } while(0); mutex_unlock(&sp->mutex);
+ }
+
++void pvr2_stream_get_stats(struct pvr2_stream *sp,
++ struct pvr2_stream_stats *stats,
++ int zero_counts)
++{
++ unsigned long irq_flags;
++ spin_lock_irqsave(&sp->list_lock,irq_flags);
++ if (stats) {
++ stats->buffers_in_queue = sp->q_count;
++ stats->buffers_in_idle = sp->i_count;
++ stats->buffers_in_ready = sp->r_count;
++ stats->buffers_processed = sp->buffers_processed;
++ stats->buffers_failed = sp->buffers_failed;
++ stats->bytes_processed = sp->bytes_processed;
++ }
++ if (zero_counts) {
++ sp->buffers_processed = 0;
++ sp->buffers_failed = 0;
++ sp->bytes_processed = 0;
++ }
++ spin_unlock_irqrestore(&sp->list_lock,irq_flags);
++}
++
+ /* Query / set the nominal buffer count */
+ int pvr2_stream_get_buffer_count(struct pvr2_stream *sp)
+ {
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.h b/drivers/media/video/pvrusb2/pvrusb2-io.h
+index 93279cc..42fcf82 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-io.h
++++ b/drivers/media/video/pvrusb2/pvrusb2-io.h
+@@ -36,6 +36,15 @@ enum pvr2_buffer_state {
+ struct pvr2_stream;
+ struct pvr2_buffer;
+
++struct pvr2_stream_stats {
++ unsigned int buffers_in_queue;
++ unsigned int buffers_in_idle;
++ unsigned int buffers_in_ready;
++ unsigned int buffers_processed;
++ unsigned int buffers_failed;
++ unsigned int bytes_processed;
++};
++
+ /* Initialize / tear down stream structure */
+ struct pvr2_stream *pvr2_stream_create(void);
+ void pvr2_stream_destroy(struct pvr2_stream *);
+@@ -45,6 +54,9 @@ void pvr2_stream_setup(struct pvr2_stream *,
+ void pvr2_stream_set_callback(struct pvr2_stream *,
+ pvr2_stream_callback func,
+ void *data);
++void pvr2_stream_get_stats(struct pvr2_stream *,
++ struct pvr2_stream_stats *,
++ int zero_counts);
+
+ /* Query / set the nominal buffer count */
+ int pvr2_stream_get_buffer_count(struct pvr2_stream *);
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c
+index b63b226..332aced 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-main.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-main.c
+@@ -60,6 +60,10 @@ static void pvr_setup_attach(struct pvr2_context *pvr)
+ {
+ /* Create association with v4l layer */
+ pvr2_v4l2_create(pvr);
++#ifdef CONFIG_VIDEO_PVRUSB2_DVB
++ /* Create association with dvb layer */
++ pvr2_dvb_create(pvr);
++#endif
+ #ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
+ pvr2_sysfs_create(pvr,class_ptr);
+ #endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
+@@ -121,6 +125,12 @@ static int __init pvr_init(void)
+
+ pvr2_trace(PVR2_TRACE_INIT,"pvr_init");
+
++ ret = pvr2_context_global_init();
++ if (ret != 0) {
++ pvr2_trace(PVR2_TRACE_INIT,"pvr_init failure code=%d",ret);
++ return ret;
++ }
++
+ #ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
+ class_ptr = pvr2_sysfs_class_create();
+ #endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
+@@ -132,6 +142,8 @@ static int __init pvr_init(void)
+ if (pvrusb2_debug) info("Debug mask is %d (0x%x)",
+ pvrusb2_debug,pvrusb2_debug);
+
++ pvr2_trace(PVR2_TRACE_INIT,"pvr_init complete");
++
+ return ret;
+ }
+
+@@ -144,6 +156,10 @@ static void __exit pvr_exit(void)
+ #ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
+ pvr2_sysfs_class_destroy(class_ptr);
+ #endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
++
++ pvr2_context_global_done();
++
++ pvr2_trace(PVR2_TRACE_INIT,"pvr_exit complete");
+ }
+
+ module_init(pvr_init);
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-std.c b/drivers/media/video/pvrusb2/pvrusb2-std.c
+index da30928..fdc5a2b 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-std.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-std.c
+@@ -79,7 +79,7 @@ struct std_name {
+ #define TSTD_Nc (V4L2_STD_PAL_Nc)
+ #define TSTD_60 (V4L2_STD_PAL_60)
+
+-#define CSTD_ALL (CSTD_PAL|CSTD_NTSC|CSTD_SECAM)
++#define CSTD_ALL (CSTD_PAL|CSTD_NTSC|CSTD_ATSC|CSTD_SECAM)
+
+ /* Mapping of standard bits to color system */
+ static const struct std_name std_groups[] = {
+@@ -328,7 +328,7 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
+ struct v4l2_standard *stddefs;
+
+ if (pvrusb2_debug & PVR2_TRACE_STD) {
+- char buf[50];
++ char buf[100];
+ bcnt = pvr2_std_id_to_str(buf,sizeof(buf),id);
+ pvr2_trace(
+ PVR2_TRACE_STD,"Mapping standards mask=0x%x (%.*s)",
+@@ -352,8 +352,11 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
+ if ((id & std_mixes[idx2]) == std_mixes[idx2]) std_cnt++;
+ }
+
++ /* Don't complain about ATSC standard values */
++ fmsk &= ~CSTD_ATSC;
++
+ if (fmsk) {
+- char buf[50];
++ char buf[100];
+ bcnt = pvr2_std_id_to_str(buf,sizeof(buf),fmsk);
+ pvr2_trace(
+ PVR2_TRACE_ERROR_LEGS,
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
+index 7a1cd87..0ff7a83 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
+@@ -21,7 +21,6 @@
+
+ #include <linux/string.h>
+ #include <linux/slab.h>
+-#include <asm/semaphore.h>
+ #include "pvrusb2-sysfs.h"
+ #include "pvrusb2-hdw.h"
+ #include "pvrusb2-debug.h"
+@@ -288,6 +287,8 @@ static ssize_t store_val_norm(int id,struct device *class_dev,
+ struct pvr2_sysfs *sfp;
+ int ret;
+ sfp = (struct pvr2_sysfs *)class_dev->driver_data;
++ pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_norm(cid=%d) \"%.*s\"",
++ sfp,id,(int)count,buf);
+ ret = store_val_any(id,0,sfp,buf,count);
+ if (!ret) ret = count;
+ return ret;
+@@ -299,6 +300,8 @@ static ssize_t store_val_custom(int id,struct device *class_dev,
+ struct pvr2_sysfs *sfp;
+ int ret;
+ sfp = (struct pvr2_sysfs *)class_dev->driver_data;
++ pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_custom(cid=%d) \"%.*s\"",
++ sfp,id,(int)count,buf);
+ ret = store_val_any(id,1,sfp,buf,count);
+ if (!ret) ret = count;
+ return ret;
+@@ -605,8 +608,9 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
+
+ ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp);
+ if (ret) {
+- printk(KERN_WARNING "%s: sysfs_create_group error: %d\n",
+- __FUNCTION__, ret);
++ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++ "sysfs_create_group error: %d",
++ ret);
+ return;
+ }
+ cip->created_ok = !0;
+@@ -637,15 +641,17 @@ static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
+ sfp->debugifc = dip;
+ ret = device_create_file(sfp->class_dev,&dip->attr_debugcmd);
+ if (ret < 0) {
+- printk(KERN_WARNING "%s: device_create_file error: %d\n",
+- __FUNCTION__, ret);
++ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++ "device_create_file error: %d",
++ ret);
+ } else {
+ dip->debugcmd_created_ok = !0;
+ }
+ ret = device_create_file(sfp->class_dev,&dip->attr_debuginfo);
+ if (ret < 0) {
+- printk(KERN_WARNING "%s: device_create_file error: %d\n",
+- __FUNCTION__, ret);
++ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++ "device_create_file error: %d",
++ ret);
+ } else {
+ dip->debuginfo_created_ok = !0;
+ }
+@@ -848,8 +854,8 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
+ class_dev->driver_data = sfp;
+ ret = device_register(class_dev);
+ if (ret) {
+- printk(KERN_ERR "%s: device_register failed\n",
+- __FUNCTION__);
++ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++ "device_register failed");
+ kfree(class_dev);
+ return;
+ }
+@@ -861,8 +867,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
+ ret = device_create_file(sfp->class_dev,
+ &sfp->attr_v4l_minor_number);
+ if (ret < 0) {
+- printk(KERN_WARNING "%s: device_create_file error: %d\n",
+- __FUNCTION__, ret);
++ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++ "device_create_file error: %d",
++ ret);
+ } else {
+ sfp->v4l_minor_number_created_ok = !0;
+ }
+@@ -874,8 +881,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
+ ret = device_create_file(sfp->class_dev,
+ &sfp->attr_v4l_radio_minor_number);
+ if (ret < 0) {
+- printk(KERN_WARNING "%s: device_create_file error: %d\n",
+- __FUNCTION__, ret);
++ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++ "device_create_file error: %d",
++ ret);
+ } else {
+ sfp->v4l_radio_minor_number_created_ok = !0;
+ }
+@@ -886,8 +894,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
+ sfp->attr_unit_number.store = NULL;
+ ret = device_create_file(sfp->class_dev,&sfp->attr_unit_number);
+ if (ret < 0) {
+- printk(KERN_WARNING "%s: device_create_file error: %d\n",
+- __FUNCTION__, ret);
++ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++ "device_create_file error: %d",
++ ret);
+ } else {
+ sfp->unit_number_created_ok = !0;
+ }
+@@ -899,8 +908,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
+ ret = device_create_file(sfp->class_dev,
+ &sfp->attr_bus_info);
+ if (ret < 0) {
+- printk(KERN_WARNING "%s: device_create_file error: %d\n",
+- __FUNCTION__, ret);
++ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++ "device_create_file error: %d",
++ ret);
+ } else {
+ sfp->bus_info_created_ok = !0;
+ }
+@@ -912,8 +922,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
+ ret = device_create_file(sfp->class_dev,
+ &sfp->attr_hdw_name);
+ if (ret < 0) {
+- printk(KERN_WARNING "%s: device_create_file error: %d\n",
+- __FUNCTION__, ret);
++ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++ "device_create_file error: %d",
++ ret);
+ } else {
+ sfp->hdw_name_created_ok = !0;
+ }
+@@ -925,8 +936,9 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
+ ret = device_create_file(sfp->class_dev,
+ &sfp->attr_hdw_desc);
+ if (ret < 0) {
+- printk(KERN_WARNING "%s: device_create_file error: %d\n",
+- __FUNCTION__, ret);
++ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
++ "device_create_file error: %d",
++ ret);
+ } else {
+ sfp->hdw_desc_created_ok = !0;
+ }
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+index 8f0587e..087a182 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+@@ -57,7 +57,9 @@ struct pvr2_v4l2_fh {
+ struct pvr2_v4l2_fh *vprev;
+ wait_queue_head_t wait_data;
+ int fw_mode_flag;
+- int prev_input_val;
++ /* Map contiguous ordinal value to input id */
++ unsigned char *input_map;
++ unsigned int input_cnt;
+ };
+
+ struct pvr2_v4l2 {
+@@ -259,14 +261,21 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
+ struct v4l2_input *vi = (struct v4l2_input *)arg;
+ struct v4l2_input tmp;
+ unsigned int cnt;
++ int val;
+
+ cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
+
+ memset(&tmp,0,sizeof(tmp));
+ tmp.index = vi->index;
+ ret = 0;
+- switch (vi->index) {
++ if ((vi->index < 0) || (vi->index >= fh->input_cnt)) {
++ ret = -EINVAL;
++ break;
++ }
++ val = fh->input_map[vi->index];
++ switch (val) {
+ case PVR2_CVAL_INPUT_TV:
++ case PVR2_CVAL_INPUT_DTV:
+ case PVR2_CVAL_INPUT_RADIO:
+ tmp.type = V4L2_INPUT_TYPE_TUNER;
+ break;
+@@ -281,7 +290,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
+ if (ret < 0) break;
+
+ cnt = 0;
+- pvr2_ctrl_get_valname(cptr,vi->index,
++ pvr2_ctrl_get_valname(cptr,val,
+ tmp.name,sizeof(tmp.name)-1,&cnt);
+ tmp.name[cnt] = 0;
+
+@@ -303,22 +312,33 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
+
+ case VIDIOC_G_INPUT:
+ {
++ unsigned int idx;
+ struct pvr2_ctrl *cptr;
+ struct v4l2_input *vi = (struct v4l2_input *)arg;
+ int val;
+ cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
+ val = 0;
+ ret = pvr2_ctrl_get_value(cptr,&val);
+- vi->index = val;
++ vi->index = 0;
++ for (idx = 0; idx < fh->input_cnt; idx++) {
++ if (fh->input_map[idx] == val) {
++ vi->index = idx;
++ break;
++ }
++ }
+ break;
+ }
+
+ case VIDIOC_S_INPUT:
+ {
+ struct v4l2_input *vi = (struct v4l2_input *)arg;
++ if ((vi->index < 0) || (vi->index >= fh->input_cnt)) {
++ ret = -ERANGE;
++ break;
++ }
+ ret = pvr2_ctrl_set_value(
+ pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
+- vi->index);
++ fh->input_map[vi->index]);
+ break;
+ }
+
+@@ -858,7 +878,6 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file)
+ {
+ struct pvr2_v4l2_fh *fhp = file->private_data;
+ struct pvr2_v4l2 *vp = fhp->vhead;
+- struct pvr2_context *mp = fhp->vhead->channel.mc_head;
+ struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
+
+ pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
+@@ -875,42 +894,30 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file)
+ v4l2_prio_close(&vp->prio, &fhp->prio);
+ file->private_data = NULL;
+
+- pvr2_context_enter(mp); do {
+- /* Restore the previous input selection, if it makes sense
+- to do so. */
+- if (fhp->dev_info->v4l_type == VFL_TYPE_RADIO) {
+- struct pvr2_ctrl *cp;
+- int pval;
+- cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
+- pvr2_ctrl_get_value(cp,&pval);
+- /* Only restore if we're still selecting the radio */
+- if (pval == PVR2_CVAL_INPUT_RADIO) {
+- pvr2_ctrl_set_value(cp,fhp->prev_input_val);
+- pvr2_hdw_commit_ctl(hdw);
+- }
+- }
+-
+- if (fhp->vnext) {
+- fhp->vnext->vprev = fhp->vprev;
+- } else {
+- vp->vlast = fhp->vprev;
+- }
+- if (fhp->vprev) {
+- fhp->vprev->vnext = fhp->vnext;
+- } else {
+- vp->vfirst = fhp->vnext;
+- }
+- fhp->vnext = NULL;
+- fhp->vprev = NULL;
+- fhp->vhead = NULL;
+- pvr2_channel_done(&fhp->channel);
+- pvr2_trace(PVR2_TRACE_STRUCT,
+- "Destroying pvr_v4l2_fh id=%p",fhp);
+- kfree(fhp);
+- if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
+- pvr2_v4l2_destroy_no_lock(vp);
+- }
+- } while (0); pvr2_context_exit(mp);
++ if (fhp->vnext) {
++ fhp->vnext->vprev = fhp->vprev;
++ } else {
++ vp->vlast = fhp->vprev;
++ }
++ if (fhp->vprev) {
++ fhp->vprev->vnext = fhp->vnext;
++ } else {
++ vp->vfirst = fhp->vnext;
++ }
++ fhp->vnext = NULL;
++ fhp->vprev = NULL;
++ fhp->vhead = NULL;
++ pvr2_channel_done(&fhp->channel);
++ pvr2_trace(PVR2_TRACE_STRUCT,
++ "Destroying pvr_v4l2_fh id=%p",fhp);
++ if (fhp->input_map) {
++ kfree(fhp->input_map);
++ fhp->input_map = NULL;
++ }
++ kfree(fhp);
++ if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
++ pvr2_v4l2_destroy_no_lock(vp);
++ }
+ return 0;
+ }
+
+@@ -921,6 +928,9 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file)
+ struct pvr2_v4l2_fh *fhp;
+ struct pvr2_v4l2 *vp;
+ struct pvr2_hdw *hdw;
++ unsigned int input_mask = 0;
++ unsigned int input_cnt,idx;
++ int ret = 0;
+
+ dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
+
+@@ -943,32 +953,62 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file)
+ init_waitqueue_head(&fhp->wait_data);
+ fhp->dev_info = dip;
+
+- pvr2_context_enter(vp->channel.mc_head); do {
+- pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
+- pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
++ pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
++ pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
+
+- fhp->vnext = NULL;
+- fhp->vprev = vp->vlast;
+- if (vp->vlast) {
+- vp->vlast->vnext = fhp;
+- } else {
+- vp->vfirst = fhp;
+- }
+- vp->vlast = fhp;
+- fhp->vhead = vp;
+-
+- /* Opening the /dev/radioX device implies a mode switch.
+- So execute that here. Note that you can get the
+- IDENTICAL effect merely by opening the normal video
+- device and setting the input appropriately. */
+- if (dip->v4l_type == VFL_TYPE_RADIO) {
+- struct pvr2_ctrl *cp;
+- cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
+- pvr2_ctrl_get_value(cp,&fhp->prev_input_val);
+- pvr2_ctrl_set_value(cp,PVR2_CVAL_INPUT_RADIO);
+- pvr2_hdw_commit_ctl(hdw);
+- }
+- } while (0); pvr2_context_exit(vp->channel.mc_head);
++ if (dip->v4l_type == VFL_TYPE_RADIO) {
++ /* Opening device as a radio, legal input selection subset
++ is just the radio. */
++ input_mask = (1 << PVR2_CVAL_INPUT_RADIO);
++ } else {
++ /* Opening the main V4L device, legal input selection
++ subset includes all analog inputs. */
++ input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) |
++ (1 << PVR2_CVAL_INPUT_TV) |
++ (1 << PVR2_CVAL_INPUT_COMPOSITE) |
++ (1 << PVR2_CVAL_INPUT_SVIDEO));
++ }
++ ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask);
++ if (ret) {
++ pvr2_channel_done(&fhp->channel);
++ pvr2_trace(PVR2_TRACE_STRUCT,
++ "Destroying pvr_v4l2_fh id=%p (input mask error)",
++ fhp);
++
++ kfree(fhp);
++ return ret;
++ }
++
++ input_mask &= pvr2_hdw_get_input_available(hdw);
++ input_cnt = 0;
++ for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
++ if (input_mask & (1 << idx)) input_cnt++;
++ }
++ fhp->input_cnt = input_cnt;
++ fhp->input_map = kzalloc(input_cnt,GFP_KERNEL);
++ if (!fhp->input_map) {
++ pvr2_channel_done(&fhp->channel);
++ pvr2_trace(PVR2_TRACE_STRUCT,
++ "Destroying pvr_v4l2_fh id=%p (input map failure)",
++ fhp);
++ kfree(fhp);
++ return -ENOMEM;
++ }
++ input_cnt = 0;
++ for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
++ if (!(input_mask & (1 << idx))) continue;
++ fhp->input_map[input_cnt++] = idx;
++ }
++
++ fhp->vnext = NULL;
++ fhp->vprev = vp->vlast;
++ if (vp->vlast) {
++ vp->vlast->vnext = fhp;
++ } else {
++ vp->vfirst = fhp;
++ }
++ vp->vlast = fhp;
++ fhp->vhead = vp;
+
+ fhp->file = file;
+ file->private_data = fhp;
+@@ -1201,24 +1241,27 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
+
+ vp = kzalloc(sizeof(*vp),GFP_KERNEL);
+ if (!vp) return vp;
+- vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
+- vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
+- if (!(vp->dev_video && vp->dev_radio)) {
+- kfree(vp->dev_video);
+- kfree(vp->dev_radio);
+- kfree(vp);
+- return NULL;
+- }
+ pvr2_channel_init(&vp->channel,mnp);
+ pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
+
+ vp->channel.check_func = pvr2_v4l2_internal_check;
+
+ /* register streams */
++ vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
++ if (!vp->dev_video) goto fail;
+ pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
+- pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
++ if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) &
++ (1 << PVR2_CVAL_INPUT_RADIO)) {
++ vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
++ if (!vp->dev_radio) goto fail;
++ pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
++ }
+
+ return vp;
++ fail:
++ pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
++ pvr2_v4l2_destroy_no_lock(vp);
++ return 0;
+ }
+
+ /*
+diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
+index e0a453a..423fa7c 100644
+--- a/drivers/media/video/pwc/pwc-if.c
++++ b/drivers/media/video/pwc/pwc-if.c
+@@ -130,8 +130,8 @@ static int default_fbufs = 3; /* Default number of frame buffers */
+ #ifdef CONFIG_USB_PWC_DEBUG
+ int pwc_trace = PWC_DEBUG_LEVEL;
+ #endif
+-static int power_save = 0;
+-static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */
++static int power_save;
++static int led_on = 100, led_off; /* defaults to LED that is on while in use */
+ static int pwc_preferred_compression = 1; /* 0..3 = uncompressed..high */
+ static struct {
+ int type;
+@@ -159,7 +159,9 @@ static const struct file_operations pwc_fops = {
+ .poll = pwc_video_poll,
+ .mmap = pwc_video_mmap,
+ .ioctl = pwc_video_ioctl,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+ static struct video_device pwc_template = {
+@@ -487,7 +489,7 @@ static void pwc_reset_buffers(struct pwc_device *pdev)
+ int i;
+ unsigned long flags;
+
+- PWC_DEBUG_MEMORY(">> %s __enter__\n", __FUNCTION__);
++ PWC_DEBUG_MEMORY(">> %s __enter__\n", __func__);
+
+ spin_lock_irqsave(&pdev->ptrlock, flags);
+ pdev->full_frames = NULL;
+@@ -509,7 +511,7 @@ static void pwc_reset_buffers(struct pwc_device *pdev)
+ pdev->fill_image = 0;
+ spin_unlock_irqrestore(&pdev->ptrlock, flags);
+
+- PWC_DEBUG_MEMORY("<< %s __leaving__\n", __FUNCTION__);
++ PWC_DEBUG_MEMORY("<< %s __leaving__\n", __func__);
+ }
+
+
+@@ -786,8 +788,8 @@ static void pwc_isoc_handler(struct urb *urb)
+ } /* ..status == 0 */
+ else {
+ /* This is normally not interesting to the user, unless
+- * you are really debugging something */
+- static int iso_error = 0;
++ * you are really debugging something, default = 0 */
++ static int iso_error;
+ iso_error++;
+ if (iso_error < 20)
+ PWC_DEBUG_FLOW("Iso frame %d of USB has error %d\n", i, fst);
+@@ -1426,7 +1428,7 @@ static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
+ unsigned long page, pos = 0;
+ int index;
+
+- PWC_DEBUG_MEMORY(">> %s\n", __FUNCTION__);
++ PWC_DEBUG_MEMORY(">> %s\n", __func__);
+ pdev = vdev->priv;
+ size = vma->vm_end - vma->vm_start;
+ start = vma->vm_start;
+diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c
+index 32fbe1a..1742889 100644
+--- a/drivers/media/video/pwc/pwc-v4l.c
++++ b/drivers/media/video/pwc/pwc-v4l.c
+@@ -351,8 +351,10 @@ int pwc_video_do_ioctl(struct inode *inode, struct file *file,
+ return -EFAULT;
+
+ #ifdef CONFIG_USB_PWC_DEBUG
+- if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace)
++ if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace) {
+ v4l_printk_ioctl(cmd);
++ printk("\n");
++ }
+ #endif
+
+
+diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
+new file mode 100644
+index 0000000..7cc8e9b
+--- /dev/null
++++ b/drivers/media/video/pxa_camera.c
+@@ -0,0 +1,1206 @@
++/*
++ * V4L2 Driver for PXA camera host
++ *
++ * Copyright (C) 2006, Sascha Hauer, Pengutronix
++ * Copyright (C) 2008, Guennadi Liakhovetski <kernel at pengutronix.de>
++ *
++ * 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/init.h>
++#include <linux/module.h>
++#include <linux/io.h>
++#include <linux/delay.h>
++#include <linux/dma-mapping.h>
++#include <linux/errno.h>
++#include <linux/fs.h>
++#include <linux/interrupt.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/moduleparam.h>
++#include <linux/time.h>
++#include <linux/version.h>
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/mutex.h>
++#include <linux/clk.h>
++
++#include <media/v4l2-common.h>
++#include <media/v4l2-dev.h>
++#include <media/soc_camera.h>
++
++#include <linux/videodev2.h>
++
++#include <asm/dma.h>
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/camera.h>
++
++#define PXA_CAM_VERSION_CODE KERNEL_VERSION(0, 0, 5)
++#define PXA_CAM_DRV_NAME "pxa27x-camera"
++
++#define CICR0_SIM_MP (0 << 24)
++#define CICR0_SIM_SP (1 << 24)
++#define CICR0_SIM_MS (2 << 24)
++#define CICR0_SIM_EP (3 << 24)
++#define CICR0_SIM_ES (4 << 24)
++
++#define CICR1_DW_VAL(x) ((x) & CICR1_DW) /* Data bus width */
++#define CICR1_PPL_VAL(x) (((x) << 15) & CICR1_PPL) /* Pixels per line */
++#define CICR1_COLOR_SP_VAL(x) (((x) << 3) & CICR1_COLOR_SP) /* color space */
++#define CICR1_RGB_BPP_VAL(x) (((x) << 7) & CICR1_RGB_BPP) /* bpp for rgb */
++#define CICR1_RGBT_CONV_VAL(x) (((x) << 29) & CICR1_RGBT_CONV) /* rgbt conv */
++
++#define CICR2_BLW_VAL(x) (((x) << 24) & CICR2_BLW) /* Beginning-of-line pixel clock wait count */
++#define CICR2_ELW_VAL(x) (((x) << 16) & CICR2_ELW) /* End-of-line pixel clock wait count */
++#define CICR2_HSW_VAL(x) (((x) << 10) & CICR2_HSW) /* Horizontal sync pulse width */
++#define CICR2_BFPW_VAL(x) (((x) << 3) & CICR2_BFPW) /* Beginning-of-frame pixel clock wait count */
++#define CICR2_FSW_VAL(x) (((x) << 0) & CICR2_FSW) /* Frame stabilization wait count */
++
++#define CICR3_BFW_VAL(x) (((x) << 24) & CICR3_BFW) /* Beginning-of-frame line clock wait count */
++#define CICR3_EFW_VAL(x) (((x) << 16) & CICR3_EFW) /* End-of-frame line clock wait count */
++#define CICR3_VSW_VAL(x) (((x) << 11) & CICR3_VSW) /* Vertical sync pulse width */
++#define CICR3_LPF_VAL(x) (((x) << 0) & CICR3_LPF) /* Lines per frame */
++
++#define CICR0_IRQ_MASK (CICR0_TOM | CICR0_RDAVM | CICR0_FEM | CICR0_EOLM | \
++ CICR0_PERRM | CICR0_QDM | CICR0_CDM | CICR0_SOFM | \
++ CICR0_EOFM | CICR0_FOM)
++
++static DEFINE_MUTEX(camera_lock);
++
++/*
++ * Structures
++ */
++enum pxa_camera_active_dma {
++ DMA_Y = 0x1,
++ DMA_U = 0x2,
++ DMA_V = 0x4,
++};
++
++/* descriptor needed for the PXA DMA engine */
++struct pxa_cam_dma {
++ dma_addr_t sg_dma;
++ struct pxa_dma_desc *sg_cpu;
++ size_t sg_size;
++ int sglen;
++};
++
++/* buffer for one video frame */
++struct pxa_buffer {
++ /* common v4l buffer stuff -- must be first */
++ struct videobuf_buffer vb;
++
++ const struct soc_camera_data_format *fmt;
++
++ /* our descriptor lists for Y, U and V channels */
++ struct pxa_cam_dma dmas[3];
++
++ int inwork;
++
++ enum pxa_camera_active_dma active_dma;
++};
++
++struct pxa_camera_dev {
++ struct device *dev;
++ /* PXA27x is only supposed to handle one camera on its Quick Capture
++ * interface. If anyone ever builds hardware to enable more than
++ * one camera, they will have to modify this driver too */
++ struct soc_camera_device *icd;
++ struct clk *clk;
++
++ unsigned int irq;
++ void __iomem *base;
++
++ int channels;
++ unsigned int dma_chans[3];
++
++ struct pxacamera_platform_data *pdata;
++ struct resource *res;
++ unsigned long platform_flags;
++ unsigned long platform_mclk_10khz;
++
++ struct list_head capture;
++
++ spinlock_t lock;
++
++ struct pxa_buffer *active;
++ struct pxa_dma_desc *sg_tail[3];
++};
++
++static const char *pxa_cam_driver_description = "PXA_Camera";
++
++static unsigned int vid_limit = 16; /* Video memory limit, in Mb */
++
++/*
++ * Videobuf operations
++ */
++static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
++ unsigned int *size)
++{
++ struct soc_camera_device *icd = vq->priv_data;
++ struct soc_camera_host *ici =
++ to_soc_camera_host(icd->dev.parent);
++ struct pxa_camera_dev *pcdev = ici->priv;
++
++ dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size);
++
++ /* planar capture requires Y, U and V buffers to be page aligned */
++ if (pcdev->channels == 3) {
++ *size = PAGE_ALIGN(icd->width * icd->height); /* Y pages */
++ *size += PAGE_ALIGN(icd->width * icd->height / 2); /* U pages */
++ *size += PAGE_ALIGN(icd->width * icd->height / 2); /* V pages */
++ } else {
++ *size = icd->width * icd->height *
++ ((icd->current_fmt->depth + 7) >> 3);
++ }
++
++ if (0 == *count)
++ *count = 32;
++ while (*size * *count > vid_limit * 1024 * 1024)
++ (*count)--;
++
++ return 0;
++}
++
++static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf)
++{
++ struct soc_camera_device *icd = vq->priv_data;
++ struct soc_camera_host *ici =
++ to_soc_camera_host(icd->dev.parent);
++ struct pxa_camera_dev *pcdev = ici->priv;
++ struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
++ int i;
++
++ BUG_ON(in_interrupt());
++
++ dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
++ &buf->vb, buf->vb.baddr, buf->vb.bsize);
++
++ /* This waits until this buffer is out of danger, i.e., until it is no
++ * longer in STATE_QUEUED or STATE_ACTIVE */
++ videobuf_waiton(&buf->vb, 0, 0);
++ videobuf_dma_unmap(vq, dma);
++ videobuf_dma_free(dma);
++
++ for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) {
++ if (buf->dmas[i].sg_cpu)
++ dma_free_coherent(pcdev->dev, buf->dmas[i].sg_size,
++ buf->dmas[i].sg_cpu,
++ buf->dmas[i].sg_dma);
++ buf->dmas[i].sg_cpu = NULL;
++ }
++
++ buf->vb.state = VIDEOBUF_NEEDS_INIT;
++}
++
++static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev,
++ struct pxa_buffer *buf,
++ struct videobuf_dmabuf *dma, int channel,
++ int sglen, int sg_start, int cibr,
++ unsigned int size)
++{
++ struct pxa_cam_dma *pxa_dma = &buf->dmas[channel];
++ int i;
++
++ if (pxa_dma->sg_cpu)
++ dma_free_coherent(pcdev->dev, pxa_dma->sg_size,
++ pxa_dma->sg_cpu, pxa_dma->sg_dma);
++
++ pxa_dma->sg_size = (sglen + 1) * sizeof(struct pxa_dma_desc);
++ pxa_dma->sg_cpu = dma_alloc_coherent(pcdev->dev, pxa_dma->sg_size,
++ &pxa_dma->sg_dma, GFP_KERNEL);
++ if (!pxa_dma->sg_cpu)
++ return -ENOMEM;
++
++ pxa_dma->sglen = sglen;
++
++ for (i = 0; i < sglen; i++) {
++ int sg_i = sg_start + i;
++ struct scatterlist *sg = dma->sglist;
++ unsigned int dma_len = sg_dma_len(&sg[sg_i]), xfer_len;
++
++ pxa_dma->sg_cpu[i].dsadr = pcdev->res->start + cibr;
++ pxa_dma->sg_cpu[i].dtadr = sg_dma_address(&sg[sg_i]);
++
++ /* PXA27x Developer's Manual 27.4.4.1: round up to 8 bytes */
++ xfer_len = (min(dma_len, size) + 7) & ~7;
++
++ pxa_dma->sg_cpu[i].dcmd =
++ DCMD_FLOWSRC | DCMD_BURST8 | DCMD_INCTRGADDR | xfer_len;
++ size -= dma_len;
++ pxa_dma->sg_cpu[i].ddadr =
++ pxa_dma->sg_dma + (i + 1) * sizeof(struct pxa_dma_desc);
++ }
++
++ pxa_dma->sg_cpu[sglen - 1].ddadr = DDADR_STOP;
++ pxa_dma->sg_cpu[sglen - 1].dcmd |= DCMD_ENDIRQEN;
++
++ return 0;
++}
++
++static int pxa_videobuf_prepare(struct videobuf_queue *vq,
++ struct videobuf_buffer *vb, enum v4l2_field field)
++{
++ struct soc_camera_device *icd = vq->priv_data;
++ struct soc_camera_host *ici =
++ to_soc_camera_host(icd->dev.parent);
++ struct pxa_camera_dev *pcdev = ici->priv;
++ struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
++ int ret;
++ int sglen_y, sglen_yu = 0, sglen_u = 0, sglen_v = 0;
++ int size_y, size_u = 0, size_v = 0;
++
++ dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
++ vb, vb->baddr, vb->bsize);
++
++ /* Added list head initialization on alloc */
++ WARN_ON(!list_empty(&vb->queue));
++
++#ifdef DEBUG
++ /* This can be useful if you want to see if we actually fill
++ * the buffer with something */
++ memset((void *)vb->baddr, 0xaa, vb->bsize);
++#endif
++
++ BUG_ON(NULL == icd->current_fmt);
++
++ /* I think, in buf_prepare you only have to protect global data,
++ * the actual buffer is yours */
++ buf->inwork = 1;
++
++ if (buf->fmt != icd->current_fmt ||
++ vb->width != icd->width ||
++ vb->height != icd->height ||
++ vb->field != field) {
++ buf->fmt = icd->current_fmt;
++ vb->width = icd->width;
++ vb->height = icd->height;
++ vb->field = field;
++ vb->state = VIDEOBUF_NEEDS_INIT;
++ }
++
++ vb->size = vb->width * vb->height * ((buf->fmt->depth + 7) >> 3);
++ if (0 != vb->baddr && vb->bsize < vb->size) {
++ ret = -EINVAL;
++ goto out;
++ }
++
++ if (vb->state == VIDEOBUF_NEEDS_INIT) {
++ unsigned int size = vb->size;
++ struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
++
++ ret = videobuf_iolock(vq, vb, NULL);
++ if (ret)
++ goto fail;
++
++ if (pcdev->channels == 3) {
++ /* FIXME the calculations should be more precise */
++ sglen_y = dma->sglen / 2;
++ sglen_u = sglen_v = dma->sglen / 4 + 1;
++ sglen_yu = sglen_y + sglen_u;
++ size_y = size / 2;
++ size_u = size_v = size / 4;
++ } else {
++ sglen_y = dma->sglen;
++ size_y = size;
++ }
++
++ /* init DMA for Y channel */
++ ret = pxa_init_dma_channel(pcdev, buf, dma, 0, sglen_y,
++ 0, 0x28, size_y);
++
++ if (ret) {
++ dev_err(pcdev->dev,
++ "DMA initialization for Y/RGB failed\n");
++ goto fail;
++ }
++
++ if (pcdev->channels == 3) {
++ /* init DMA for U channel */
++ ret = pxa_init_dma_channel(pcdev, buf, dma, 1, sglen_u,
++ sglen_y, 0x30, size_u);
++ if (ret) {
++ dev_err(pcdev->dev,
++ "DMA initialization for U failed\n");
++ goto fail_u;
++ }
++
++ /* init DMA for V channel */
++ ret = pxa_init_dma_channel(pcdev, buf, dma, 2, sglen_v,
++ sglen_yu, 0x38, size_v);
++ if (ret) {
++ dev_err(pcdev->dev,
++ "DMA initialization for V failed\n");
++ goto fail_v;
++ }
++ }
++
++ vb->state = VIDEOBUF_PREPARED;
++ }
++
++ buf->inwork = 0;
++ buf->active_dma = DMA_Y;
++ if (pcdev->channels == 3)
++ buf->active_dma |= DMA_U | DMA_V;
++
++ return 0;
++
++fail_v:
++ dma_free_coherent(pcdev->dev, buf->dmas[1].sg_size,
++ buf->dmas[1].sg_cpu, buf->dmas[1].sg_dma);
++fail_u:
++ dma_free_coherent(pcdev->dev, buf->dmas[0].sg_size,
++ buf->dmas[0].sg_cpu, buf->dmas[0].sg_dma);
++fail:
++ free_buffer(vq, buf);
++out:
++ buf->inwork = 0;
++ return ret;
++}
++
++static void pxa_videobuf_queue(struct videobuf_queue *vq,
++ struct videobuf_buffer *vb)
++{
++ struct soc_camera_device *icd = vq->priv_data;
++ struct soc_camera_host *ici =
++ to_soc_camera_host(icd->dev.parent);
++ struct pxa_camera_dev *pcdev = ici->priv;
++ struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
++ struct pxa_buffer *active;
++ unsigned long flags;
++ int i;
++
++ dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
++ vb, vb->baddr, vb->bsize);
++ spin_lock_irqsave(&pcdev->lock, flags);
++
++ list_add_tail(&vb->queue, &pcdev->capture);
++
++ vb->state = VIDEOBUF_ACTIVE;
++ active = pcdev->active;
++
++ if (!active) {
++ CIFR |= CIFR_RESET_F;
++
++ for (i = 0; i < pcdev->channels; i++) {
++ DDADR(pcdev->dma_chans[i]) = buf->dmas[i].sg_dma;
++ DCSR(pcdev->dma_chans[i]) = DCSR_RUN;
++ pcdev->sg_tail[i] = buf->dmas[i].sg_cpu + buf->dmas[i].sglen - 1;
++ }
++
++ pcdev->active = buf;
++ CICR0 |= CICR0_ENB;
++ } else {
++ struct pxa_cam_dma *buf_dma;
++ struct pxa_cam_dma *act_dma;
++ int nents;
++
++ for (i = 0; i < pcdev->channels; i++) {
++ buf_dma = &buf->dmas[i];
++ act_dma = &active->dmas[i];
++ nents = buf_dma->sglen;
++
++ /* Stop DMA engine */
++ DCSR(pcdev->dma_chans[i]) = 0;
++
++ /* Add the descriptors we just initialized to
++ the currently running chain */
++ pcdev->sg_tail[i]->ddadr = buf_dma->sg_dma;
++ pcdev->sg_tail[i] = buf_dma->sg_cpu + buf_dma->sglen - 1;
++
++ /* Setup a dummy descriptor with the DMA engines current
++ * state
++ */
++ buf_dma->sg_cpu[nents].dsadr =
++ pcdev->res->start + 0x28 + i*8; /* CIBRx */
++ buf_dma->sg_cpu[nents].dtadr =
++ DTADR(pcdev->dma_chans[i]);
++ buf_dma->sg_cpu[nents].dcmd =
++ DCMD(pcdev->dma_chans[i]);
++
++ if (DDADR(pcdev->dma_chans[i]) == DDADR_STOP) {
++ /* The DMA engine is on the last
++ descriptor, set the next descriptors
++ address to the descriptors we just
++ initialized */
++ buf_dma->sg_cpu[nents].ddadr = buf_dma->sg_dma;
++ } else {
++ buf_dma->sg_cpu[nents].ddadr =
++ DDADR(pcdev->dma_chans[i]);
++ }
++
++ /* The next descriptor is the dummy descriptor */
++ DDADR(pcdev->dma_chans[i]) = buf_dma->sg_dma + nents *
++ sizeof(struct pxa_dma_desc);
++
++ DCSR(pcdev->dma_chans[i]) = DCSR_RUN;
++ }
++ }
++
++ spin_unlock_irqrestore(&pcdev->lock, flags);
++}
++
++static void pxa_videobuf_release(struct videobuf_queue *vq,
++ struct videobuf_buffer *vb)
++{
++ struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
++#ifdef DEBUG
++ struct soc_camera_device *icd = vq->priv_data;
++
++ dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
++ vb, vb->baddr, vb->bsize);
++
++ switch (vb->state) {
++ case VIDEOBUF_ACTIVE:
++ dev_dbg(&icd->dev, "%s (active)\n", __func__);
++ break;
++ case VIDEOBUF_QUEUED:
++ dev_dbg(&icd->dev, "%s (queued)\n", __func__);
++ break;
++ case VIDEOBUF_PREPARED:
++ dev_dbg(&icd->dev, "%s (prepared)\n", __func__);
++ break;
++ default:
++ dev_dbg(&icd->dev, "%s (unknown)\n", __func__);
++ break;
++ }
++#endif
++
++ free_buffer(vq, buf);
++}
++
++static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev,
++ struct videobuf_buffer *vb,
++ struct pxa_buffer *buf)
++{
++ /* _init is used to debug races, see comment in pxa_camera_reqbufs() */
++ list_del_init(&vb->queue);
++ vb->state = VIDEOBUF_DONE;
++ do_gettimeofday(&vb->ts);
++ vb->field_count++;
++ wake_up(&vb->done);
++
++ if (list_empty(&pcdev->capture)) {
++ pcdev->active = NULL;
++ DCSR(pcdev->dma_chans[0]) = 0;
++ DCSR(pcdev->dma_chans[1]) = 0;
++ DCSR(pcdev->dma_chans[2]) = 0;
++ CICR0 &= ~CICR0_ENB;
++ return;
++ }
++
++ pcdev->active = list_entry(pcdev->capture.next,
++ struct pxa_buffer, vb.queue);
++}
++
++static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev,
++ enum pxa_camera_active_dma act_dma)
++{
++ struct pxa_buffer *buf;
++ unsigned long flags;
++ u32 status, camera_status, overrun;
++ struct videobuf_buffer *vb;
++
++ spin_lock_irqsave(&pcdev->lock, flags);
++
++ status = DCSR(channel);
++ DCSR(channel) = status | DCSR_ENDINTR;
++
++ if (status & DCSR_BUSERR) {
++ dev_err(pcdev->dev, "DMA Bus Error IRQ!\n");
++ goto out;
++ }
++
++ if (!(status & DCSR_ENDINTR)) {
++ dev_err(pcdev->dev, "Unknown DMA IRQ source, "
++ "status: 0x%08x\n", status);
++ goto out;
++ }
++
++ if (!pcdev->active) {
++ dev_err(pcdev->dev, "DMA End IRQ with no active buffer!\n");
++ goto out;
++ }
++
++ camera_status = CISR;
++ overrun = CISR_IFO_0;
++ if (pcdev->channels == 3)
++ overrun |= CISR_IFO_1 | CISR_IFO_2;
++ if (camera_status & overrun) {
++ dev_dbg(pcdev->dev, "FIFO overrun! CISR: %x\n", camera_status);
++ /* Stop the Capture Interface */
++ CICR0 &= ~CICR0_ENB;
++ /* Stop DMA */
++ DCSR(channel) = 0;
++ /* Reset the FIFOs */
++ CIFR |= CIFR_RESET_F;
++ /* Enable End-Of-Frame Interrupt */
++ CICR0 &= ~CICR0_EOFM;
++ /* Restart the Capture Interface */
++ CICR0 |= CICR0_ENB;
++ goto out;
++ }
++
++ vb = &pcdev->active->vb;
++ buf = container_of(vb, struct pxa_buffer, vb);
++ WARN_ON(buf->inwork || list_empty(&vb->queue));
++ dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
++ vb, vb->baddr, vb->bsize);
++
++ buf->active_dma &= ~act_dma;
++ if (!buf->active_dma)
++ pxa_camera_wakeup(pcdev, vb, buf);
++
++out:
++ spin_unlock_irqrestore(&pcdev->lock, flags);
++}
++
++static void pxa_camera_dma_irq_y(int channel, void *data)
++{
++ struct pxa_camera_dev *pcdev = data;
++ pxa_camera_dma_irq(channel, pcdev, DMA_Y);
++}
++
++static void pxa_camera_dma_irq_u(int channel, void *data)
++{
++ struct pxa_camera_dev *pcdev = data;
++ pxa_camera_dma_irq(channel, pcdev, DMA_U);
++}
++
++static void pxa_camera_dma_irq_v(int channel, void *data)
++{
++ struct pxa_camera_dev *pcdev = data;
++ pxa_camera_dma_irq(channel, pcdev, DMA_V);
++}
++
++static struct videobuf_queue_ops pxa_videobuf_ops = {
++ .buf_setup = pxa_videobuf_setup,
++ .buf_prepare = pxa_videobuf_prepare,
++ .buf_queue = pxa_videobuf_queue,
++ .buf_release = pxa_videobuf_release,
++};
++
++static int mclk_get_divisor(struct pxa_camera_dev *pcdev)
++{
++ unsigned int mclk_10khz = pcdev->platform_mclk_10khz;
++ unsigned long div;
++ unsigned long lcdclk;
++
++ lcdclk = clk_get_rate(pcdev->clk) / 10000;
++
++ /* We verify platform_mclk_10khz != 0, so if anyone breaks it, here
++ * they get a nice Oops */
++ div = (lcdclk + 2 * mclk_10khz - 1) / (2 * mclk_10khz) - 1;
++
++ dev_dbg(pcdev->dev, "LCD clock %lukHz, target freq %dkHz, "
++ "divisor %lu\n", lcdclk * 10, mclk_10khz * 10, div);
++
++ return div;
++}
++
++static void pxa_camera_activate(struct pxa_camera_dev *pcdev)
++{
++ struct pxacamera_platform_data *pdata = pcdev->pdata;
++ u32 cicr4 = 0;
++
++ dev_dbg(pcdev->dev, "Registered platform device at %p data %p\n",
++ pcdev, pdata);
++
++ if (pdata && pdata->init) {
++ dev_dbg(pcdev->dev, "%s: Init gpios\n", __func__);
++ pdata->init(pcdev->dev);
++ }
++
++ if (pdata && pdata->power) {
++ dev_dbg(pcdev->dev, "%s: Power on camera\n", __func__);
++ pdata->power(pcdev->dev, 1);
++ }
++
++ if (pdata && pdata->reset) {
++ dev_dbg(pcdev->dev, "%s: Releasing camera reset\n",
++ __func__);
++ pdata->reset(pcdev->dev, 1);
++ }
++
++ CICR0 = 0x3FF; /* disable all interrupts */
++
++ if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
++ cicr4 |= CICR4_PCLK_EN;
++ if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
++ cicr4 |= CICR4_MCLK_EN;
++ if (pcdev->platform_flags & PXA_CAMERA_PCP)
++ cicr4 |= CICR4_PCP;
++ if (pcdev->platform_flags & PXA_CAMERA_HSP)
++ cicr4 |= CICR4_HSP;
++ if (pcdev->platform_flags & PXA_CAMERA_VSP)
++ cicr4 |= CICR4_VSP;
++
++ CICR4 = mclk_get_divisor(pcdev) | cicr4;
++
++ clk_enable(pcdev->clk);
++}
++
++static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev)
++{
++ struct pxacamera_platform_data *board = pcdev->pdata;
++
++ clk_disable(pcdev->clk);
++
++ if (board && board->reset) {
++ dev_dbg(pcdev->dev, "%s: Asserting camera reset\n",
++ __func__);
++ board->reset(pcdev->dev, 0);
++ }
++
++ if (board && board->power) {
++ dev_dbg(pcdev->dev, "%s: Power off camera\n", __func__);
++ board->power(pcdev->dev, 0);
++ }
++}
++
++static irqreturn_t pxa_camera_irq(int irq, void *data)
++{
++ struct pxa_camera_dev *pcdev = data;
++ unsigned int status = CISR;
++
++ dev_dbg(pcdev->dev, "Camera interrupt status 0x%x\n", status);
++
++ if (!status)
++ return IRQ_NONE;
++
++ CISR = status;
++
++ if (status & CISR_EOF) {
++ int i;
++ for (i = 0; i < pcdev->channels; i++) {
++ DDADR(pcdev->dma_chans[i]) =
++ pcdev->active->dmas[i].sg_dma;
++ DCSR(pcdev->dma_chans[i]) = DCSR_RUN;
++ }
++ CICR0 |= CICR0_EOFM;
++ }
++
++ return IRQ_HANDLED;
++}
++
++/* The following two functions absolutely depend on the fact, that
++ * there can be only one camera on PXA quick capture interface */
++static int pxa_camera_add_device(struct soc_camera_device *icd)
++{
++ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
++ struct pxa_camera_dev *pcdev = ici->priv;
++ int ret;
++
++ mutex_lock(&camera_lock);
++
++ if (pcdev->icd) {
++ ret = -EBUSY;
++ goto ebusy;
++ }
++
++ dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n",
++ icd->devnum);
++
++ pxa_camera_activate(pcdev);
++ ret = icd->ops->init(icd);
++
++ if (!ret)
++ pcdev->icd = icd;
++
++ebusy:
++ mutex_unlock(&camera_lock);
++
++ return ret;
++}
++
++static void pxa_camera_remove_device(struct soc_camera_device *icd)
++{
++ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
++ struct pxa_camera_dev *pcdev = ici->priv;
++
++ BUG_ON(icd != pcdev->icd);
++
++ dev_info(&icd->dev, "PXA Camera driver detached from camera %d\n",
++ icd->devnum);
++
++ /* disable capture, disable interrupts */
++ CICR0 = 0x3ff;
++
++ /* Stop DMA engine */
++ DCSR(pcdev->dma_chans[0]) = 0;
++ DCSR(pcdev->dma_chans[1]) = 0;
++ DCSR(pcdev->dma_chans[2]) = 0;
++
++ icd->ops->release(icd);
++
++ pxa_camera_deactivate(pcdev);
++
++ pcdev->icd = NULL;
++}
++
++static int test_platform_param(struct pxa_camera_dev *pcdev,
++ unsigned char buswidth, unsigned long *flags)
++{
++ /*
++ * Platform specified synchronization and pixel clock polarities are
++ * only a recommendation and are only used during probing. The PXA270
++ * quick capture interface supports both.
++ */
++ *flags = (pcdev->platform_flags & PXA_CAMERA_MASTER ?
++ SOCAM_MASTER : SOCAM_SLAVE) |
++ SOCAM_HSYNC_ACTIVE_HIGH |
++ SOCAM_HSYNC_ACTIVE_LOW |
++ SOCAM_VSYNC_ACTIVE_HIGH |
++ SOCAM_VSYNC_ACTIVE_LOW |
++ SOCAM_PCLK_SAMPLE_RISING |
++ SOCAM_PCLK_SAMPLE_FALLING;
++
++ /* If requested data width is supported by the platform, use it */
++ switch (buswidth) {
++ case 10:
++ if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10))
++ return -EINVAL;
++ *flags |= SOCAM_DATAWIDTH_10;
++ break;
++ case 9:
++ if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9))
++ return -EINVAL;
++ *flags |= SOCAM_DATAWIDTH_9;
++ break;
++ case 8:
++ if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8))
++ return -EINVAL;
++ *flags |= SOCAM_DATAWIDTH_8;
++ }
++
++ return 0;
++}
++
++static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
++{
++ struct soc_camera_host *ici =
++ to_soc_camera_host(icd->dev.parent);
++ struct pxa_camera_dev *pcdev = ici->priv;
++ unsigned long dw, bpp, bus_flags, camera_flags, common_flags;
++ u32 cicr0, cicr1, cicr4 = 0;
++ int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags);
++
++ if (ret < 0)
++ return ret;
++
++ camera_flags = icd->ops->query_bus_param(icd);
++
++ common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
++ if (!common_flags)
++ return -EINVAL;
++
++ pcdev->channels = 1;
++
++ /* Make choises, based on platform preferences */
++ if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
++ (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
++ if (pcdev->platform_flags & PXA_CAMERA_HSP)
++ common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
++ else
++ common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
++ }
++
++ if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
++ (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
++ if (pcdev->platform_flags & PXA_CAMERA_VSP)
++ common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
++ else
++ common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
++ }
++
++ if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
++ (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
++ if (pcdev->platform_flags & PXA_CAMERA_PCP)
++ common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
++ else
++ common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
++ }
++
++ ret = icd->ops->set_bus_param(icd, common_flags);
++ if (ret < 0)
++ return ret;
++
++ /* Datawidth is now guaranteed to be equal to one of the three values.
++ * We fix bit-per-pixel equal to data-width... */
++ switch (common_flags & SOCAM_DATAWIDTH_MASK) {
++ case SOCAM_DATAWIDTH_10:
++ icd->buswidth = 10;
++ dw = 4;
++ bpp = 0x40;
++ break;
++ case SOCAM_DATAWIDTH_9:
++ icd->buswidth = 9;
++ dw = 3;
++ bpp = 0x20;
++ break;
++ default:
++ /* Actually it can only be 8 now,
++ * default is just to silence compiler warnings */
++ case SOCAM_DATAWIDTH_8:
++ icd->buswidth = 8;
++ dw = 2;
++ bpp = 0;
++ }
++
++ if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
++ cicr4 |= CICR4_PCLK_EN;
++ if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
++ cicr4 |= CICR4_MCLK_EN;
++ if (common_flags & SOCAM_PCLK_SAMPLE_FALLING)
++ cicr4 |= CICR4_PCP;
++ if (common_flags & SOCAM_HSYNC_ACTIVE_LOW)
++ cicr4 |= CICR4_HSP;
++ if (common_flags & SOCAM_VSYNC_ACTIVE_LOW)
++ cicr4 |= CICR4_VSP;
++
++ cicr0 = CICR0;
++ if (cicr0 & CICR0_ENB)
++ CICR0 = cicr0 & ~CICR0_ENB;
++
++ cicr1 = CICR1_PPL_VAL(icd->width - 1) | bpp | dw;
++
++ switch (pixfmt) {
++ case V4L2_PIX_FMT_YUV422P:
++ pcdev->channels = 3;
++ cicr1 |= CICR1_YCBCR_F;
++ case V4L2_PIX_FMT_YUYV:
++ cicr1 |= CICR1_COLOR_SP_VAL(2);
++ break;
++ case V4L2_PIX_FMT_RGB555:
++ cicr1 |= CICR1_RGB_BPP_VAL(1) | CICR1_RGBT_CONV_VAL(2) |
++ CICR1_TBIT | CICR1_COLOR_SP_VAL(1);
++ break;
++ case V4L2_PIX_FMT_RGB565:
++ cicr1 |= CICR1_COLOR_SP_VAL(1) | CICR1_RGB_BPP_VAL(2);
++ break;
++ }
++
++ CICR1 = cicr1;
++ CICR2 = 0;
++ CICR3 = CICR3_LPF_VAL(icd->height - 1) |
++ CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top));
++ CICR4 = mclk_get_divisor(pcdev) | cicr4;
++
++ /* CIF interrupts are not used, only DMA */
++ CICR0 = (pcdev->platform_flags & PXA_CAMERA_MASTER ?
++ CICR0_SIM_MP : (CICR0_SL_CAP_EN | CICR0_SIM_SP)) |
++ CICR0_DMAEN | CICR0_IRQ_MASK | (cicr0 & CICR0_ENB);
++
++ return 0;
++}
++
++static int pxa_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
++{
++ struct soc_camera_host *ici =
++ to_soc_camera_host(icd->dev.parent);
++ struct pxa_camera_dev *pcdev = ici->priv;
++ unsigned long bus_flags, camera_flags;
++ int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags);
++
++ if (ret < 0)
++ return ret;
++
++ camera_flags = icd->ops->query_bus_param(icd);
++
++ return soc_camera_bus_param_compatible(camera_flags, bus_flags) ? 0 : -EINVAL;
++}
++
++static int pxa_camera_set_fmt_cap(struct soc_camera_device *icd,
++ __u32 pixfmt, struct v4l2_rect *rect)
++{
++ return icd->ops->set_fmt_cap(icd, pixfmt, rect);
++}
++
++static int pxa_camera_try_fmt_cap(struct soc_camera_device *icd,
++ struct v4l2_format *f)
++{
++ /* limit to pxa hardware capabilities */
++ if (f->fmt.pix.height < 32)
++ f->fmt.pix.height = 32;
++ if (f->fmt.pix.height > 2048)
++ f->fmt.pix.height = 2048;
++ if (f->fmt.pix.width < 48)
++ f->fmt.pix.width = 48;
++ if (f->fmt.pix.width > 2048)
++ f->fmt.pix.width = 2048;
++ f->fmt.pix.width &= ~0x01;
++
++ /* limit to sensor capabilities */
++ return icd->ops->try_fmt_cap(icd, f);
++}
++
++static int pxa_camera_reqbufs(struct soc_camera_file *icf,
++ struct v4l2_requestbuffers *p)
++{
++ int i;
++
++ /* This is for locking debugging only. I removed spinlocks and now I
++ * check whether .prepare is ever called on a linked buffer, or whether
++ * a dma IRQ can occur for an in-work or unlinked buffer. Until now
++ * it hadn't triggered */
++ for (i = 0; i < p->count; i++) {
++ struct pxa_buffer *buf = container_of(icf->vb_vidq.bufs[i],
++ struct pxa_buffer, vb);
++ buf->inwork = 0;
++ INIT_LIST_HEAD(&buf->vb.queue);
++ }
++
++ return 0;
++}
++
++static unsigned int pxa_camera_poll(struct file *file, poll_table *pt)
++{
++ struct soc_camera_file *icf = file->private_data;
++ struct pxa_buffer *buf;
++
++ buf = list_entry(icf->vb_vidq.stream.next, struct pxa_buffer,
++ vb.stream);
++
++ poll_wait(file, &buf->vb.done, pt);
++
++ if (buf->vb.state == VIDEOBUF_DONE ||
++ buf->vb.state == VIDEOBUF_ERROR)
++ return POLLIN|POLLRDNORM;
++
++ return 0;
++}
++
++static int pxa_camera_querycap(struct soc_camera_host *ici,
++ struct v4l2_capability *cap)
++{
++ /* cap->name is set by the firendly caller:-> */
++ strlcpy(cap->card, pxa_cam_driver_description, sizeof(cap->card));
++ cap->version = PXA_CAM_VERSION_CODE;
++ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
++
++ return 0;
++}
++
++static spinlock_t *pxa_camera_spinlock_alloc(struct soc_camera_file *icf)
++{
++ struct soc_camera_host *ici =
++ to_soc_camera_host(icf->icd->dev.parent);
++ struct pxa_camera_dev *pcdev = ici->priv;
++
++ return &pcdev->lock;
++}
++
++static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
++ .owner = THIS_MODULE,
++ .add = pxa_camera_add_device,
++ .remove = pxa_camera_remove_device,
++ .set_fmt_cap = pxa_camera_set_fmt_cap,
++ .try_fmt_cap = pxa_camera_try_fmt_cap,
++ .reqbufs = pxa_camera_reqbufs,
++ .poll = pxa_camera_poll,
++ .querycap = pxa_camera_querycap,
++ .try_bus_param = pxa_camera_try_bus_param,
++ .set_bus_param = pxa_camera_set_bus_param,
++ .spinlock_alloc = pxa_camera_spinlock_alloc,
++};
++
++/* Should be allocated dynamically too, but we have only one. */
++static struct soc_camera_host pxa_soc_camera_host = {
++ .drv_name = PXA_CAM_DRV_NAME,
++ .vbq_ops = &pxa_videobuf_ops,
++ .msize = sizeof(struct pxa_buffer),
++ .ops = &pxa_soc_camera_host_ops,
++};
++
++static int pxa_camera_probe(struct platform_device *pdev)
++{
++ struct pxa_camera_dev *pcdev;
++ struct resource *res;
++ void __iomem *base;
++ unsigned int irq;
++ int err = 0;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ irq = platform_get_irq(pdev, 0);
++ if (!res || !irq) {
++ err = -ENODEV;
++ goto exit;
++ }
++
++ pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL);
++ if (!pcdev) {
++ dev_err(&pdev->dev, "Could not allocate pcdev\n");
++ err = -ENOMEM;
++ goto exit;
++ }
++
++ pcdev->clk = clk_get(&pdev->dev, "CAMCLK");
++ if (IS_ERR(pcdev->clk)) {
++ err = PTR_ERR(pcdev->clk);
++ goto exit_kfree;
++ }
++
++ dev_set_drvdata(&pdev->dev, pcdev);
++ pcdev->res = res;
++
++ pcdev->pdata = pdev->dev.platform_data;
++ pcdev->platform_flags = pcdev->pdata->flags;
++ if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 |
++ PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) {
++ /* Platform hasn't set available data widths. This is bad.
++ * Warn and use a default. */
++ dev_warn(&pdev->dev, "WARNING! Platform hasn't set available "
++ "data widths, using default 10 bit\n");
++ pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_10;
++ }
++ pcdev->platform_mclk_10khz = pcdev->pdata->mclk_10khz;
++ if (!pcdev->platform_mclk_10khz) {
++ dev_warn(&pdev->dev,
++ "mclk_10khz == 0! Please, fix your platform data. "
++ "Using default 20MHz\n");
++ pcdev->platform_mclk_10khz = 2000;
++ }
++
++ INIT_LIST_HEAD(&pcdev->capture);
++ spin_lock_init(&pcdev->lock);
++
++ /*
++ * Request the regions.
++ */
++ if (!request_mem_region(res->start, res->end - res->start + 1,
++ PXA_CAM_DRV_NAME)) {
++ err = -EBUSY;
++ goto exit_clk;
++ }
++
++ base = ioremap(res->start, res->end - res->start + 1);
++ if (!base) {
++ err = -ENOMEM;
++ goto exit_release;
++ }
++ pcdev->irq = irq;
++ pcdev->base = base;
++ pcdev->dev = &pdev->dev;
++
++ /* request dma */
++ pcdev->dma_chans[0] = pxa_request_dma("CI_Y", DMA_PRIO_HIGH,
++ pxa_camera_dma_irq_y, pcdev);
++ if (pcdev->dma_chans[0] < 0) {
++ dev_err(pcdev->dev, "Can't request DMA for Y\n");
++ err = -ENOMEM;
++ goto exit_iounmap;
++ }
++ dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]);
++
++ pcdev->dma_chans[1] = pxa_request_dma("CI_U", DMA_PRIO_HIGH,
++ pxa_camera_dma_irq_u, pcdev);
++ if (pcdev->dma_chans[1] < 0) {
++ dev_err(pcdev->dev, "Can't request DMA for U\n");
++ err = -ENOMEM;
++ goto exit_free_dma_y;
++ }
++ dev_dbg(pcdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]);
++
++ pcdev->dma_chans[2] = pxa_request_dma("CI_V", DMA_PRIO_HIGH,
++ pxa_camera_dma_irq_v, pcdev);
++ if (pcdev->dma_chans[0] < 0) {
++ dev_err(pcdev->dev, "Can't request DMA for V\n");
++ err = -ENOMEM;
++ goto exit_free_dma_u;
++ }
++ dev_dbg(pcdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]);
++
++ DRCMR68 = pcdev->dma_chans[0] | DRCMR_MAPVLD;
++ DRCMR69 = pcdev->dma_chans[1] | DRCMR_MAPVLD;
++ DRCMR70 = pcdev->dma_chans[2] | DRCMR_MAPVLD;
++
++ /* request irq */
++ err = request_irq(pcdev->irq, pxa_camera_irq, 0, PXA_CAM_DRV_NAME,
++ pcdev);
++ if (err) {
++ dev_err(pcdev->dev, "Camera interrupt register failed \n");
++ goto exit_free_dma;
++ }
++
++ pxa_soc_camera_host.priv = pcdev;
++ pxa_soc_camera_host.dev.parent = &pdev->dev;
++ pxa_soc_camera_host.nr = pdev->id;
++ err = soc_camera_host_register(&pxa_soc_camera_host);
++ if (err)
++ goto exit_free_irq;
++
++ return 0;
++
++exit_free_irq:
++ free_irq(pcdev->irq, pcdev);
++exit_free_dma:
++ pxa_free_dma(pcdev->dma_chans[2]);
++exit_free_dma_u:
++ pxa_free_dma(pcdev->dma_chans[1]);
++exit_free_dma_y:
++ pxa_free_dma(pcdev->dma_chans[0]);
++exit_iounmap:
++ iounmap(base);
++exit_release:
++ release_mem_region(res->start, res->end - res->start + 1);
++exit_clk:
++ clk_put(pcdev->clk);
++exit_kfree:
++ kfree(pcdev);
++exit:
++ return err;
++}
++
++static int __devexit pxa_camera_remove(struct platform_device *pdev)
++{
++ struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev);
++ struct resource *res;
++
++ clk_put(pcdev->clk);
++
++ pxa_free_dma(pcdev->dma_chans[0]);
++ pxa_free_dma(pcdev->dma_chans[1]);
++ pxa_free_dma(pcdev->dma_chans[2]);
++ free_irq(pcdev->irq, pcdev);
++
++ soc_camera_host_unregister(&pxa_soc_camera_host);
++
++ iounmap(pcdev->base);
++
++ res = pcdev->res;
++ release_mem_region(res->start, res->end - res->start + 1);
++
++ kfree(pcdev);
++
++ dev_info(&pdev->dev, "PXA Camera driver unloaded\n");
++
++ return 0;
++}
++
++static struct platform_driver pxa_camera_driver = {
++ .driver = {
++ .name = PXA_CAM_DRV_NAME,
++ },
++ .probe = pxa_camera_probe,
++ .remove = __exit_p(pxa_camera_remove),
++};
++
++
++static int __devinit pxa_camera_init(void)
++{
++ return platform_driver_register(&pxa_camera_driver);
++}
++
++static void __exit pxa_camera_exit(void)
++{
++ return platform_driver_unregister(&pxa_camera_driver);
++}
++
++module_init(pxa_camera_init);
++module_exit(pxa_camera_exit);
++
++MODULE_DESCRIPTION("PXA27x SoC Camera Host driver");
++MODULE_AUTHOR("Guennadi Liakhovetski <kernel at pengutronix.de>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c
+index f55d6e8..ec8c65d 100644
+--- a/drivers/media/video/saa5249.c
++++ b/drivers/media/video/saa5249.c
+@@ -701,7 +701,9 @@ static const struct file_operations saa_fops = {
+ .open = saa5249_open,
+ .release = saa5249_release,
+ .ioctl = saa5249_ioctl,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c
+index 72e344a..716ee7f 100644
+--- a/drivers/media/video/saa6588.c
++++ b/drivers/media/video/saa6588.c
+@@ -44,10 +44,10 @@ static unsigned short normal_i2c[] = {
+ I2C_CLIENT_INSMOD;
+
+ /* insmod options */
+-static unsigned int debug = 0;
+-static unsigned int xtal = 0;
+-static unsigned int rbds = 0;
+-static unsigned int plvl = 0;
++static unsigned int debug;
++static unsigned int xtal;
++static unsigned int rbds;
++static unsigned int plvl;
+ static unsigned int bufblocks = 100;
+
+ module_param(debug, int, 0644);
+diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c
+index 1df2602..4aa82b3 100644
+--- a/drivers/media/video/saa7110.c
++++ b/drivers/media/video/saa7110.c
+@@ -46,7 +46,7 @@ MODULE_LICENSE("GPL");
+ #include <media/v4l2-common.h>
+ #include <linux/video_decoder.h>
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
+index a0772c5..96c3d43 100644
+--- a/drivers/media/video/saa7111.c
++++ b/drivers/media/video/saa7111.c
+@@ -55,7 +55,7 @@ MODULE_LICENSE("GPL");
+ #define I2C_NAME(s) (s)->name
+
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c
+index bf91a4f..e790755 100644
+--- a/drivers/media/video/saa7114.c
++++ b/drivers/media/video/saa7114.c
+@@ -56,7 +56,7 @@ MODULE_LICENSE("GPL");
+ #define I2C_NAME(x) (x)->name
+
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
+index 41e5e51..416d05d 100644
+--- a/drivers/media/video/saa7115.c
++++ b/drivers/media/video/saa7115.c
+@@ -57,7 +57,7 @@ MODULE_AUTHOR( "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, "
+ "Hans Verkuil, Mauro Carvalho Chehab");
+ MODULE_LICENSE("GPL");
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, bool, 0644);
+
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
+@@ -957,7 +957,7 @@ static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
+
+ if (std == V4L2_STD_PAL_M) {
+ reg |= 0x30;
+- } else if (std == V4L2_STD_PAL_N) {
++ } else if (std == V4L2_STD_PAL_Nc) {
+ reg |= 0x20;
+ } else if (std == V4L2_STD_PAL_60) {
+ reg |= 0x10;
+diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c
+index 80bf911..cedb988 100644
+--- a/drivers/media/video/saa711x.c
++++ b/drivers/media/video/saa711x.c
+@@ -48,7 +48,7 @@ MODULE_LICENSE("GPL");
+
+ #include <linux/video_decoder.h>
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, " Set the default Debug level. Default: 0 (Off) - (0-1)");
+
+diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig
+index 96bc3b1..e086f14 100644
+--- a/drivers/media/video/saa7134/Kconfig
++++ b/drivers/media/video/saa7134/Kconfig
+@@ -37,6 +37,7 @@ config VIDEO_SAA7134_DVB
+ select DVB_TDA826X if !DVB_FE_CUSTOMISE
+ select DVB_TDA827X if !DVB_FE_CUSTOMISE
+ select DVB_ISL6421 if !DVB_FE_CUSTOMISE
++ select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+ ---help---
+ This adds support for DVB cards based on the
+ Philips saa7134 chip.
+diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
+index 047add8..ba30824 100644
+--- a/drivers/media/video/saa7134/saa7134-alsa.c
++++ b/drivers/media/video/saa7134/saa7134-alsa.c
+@@ -31,7 +31,7 @@
+ #include "saa7134.h"
+ #include "saa7134-reg.h"
+
+-static unsigned int debug = 0;
++static unsigned int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug,"enable debug messages [alsa]");
+
+@@ -503,7 +503,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
+ /* release the old buffer */
+ if (substream->runtime->dma_area) {
+ saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
+- videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma);
++ videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
+ dsp_buffer_free(dev);
+ substream->runtime->dma_area = NULL;
+ }
+@@ -519,12 +519,12 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
+ return err;
+ }
+
+- if (0 != (err = videobuf_pci_dma_map(dev->pci, &dev->dmasound.dma))) {
++ if (0 != (err = videobuf_sg_dma_map(&dev->pci->dev, &dev->dmasound.dma))) {
+ dsp_buffer_free(dev);
+ return err;
+ }
+ if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) {
+- videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma);
++ videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
+ dsp_buffer_free(dev);
+ return err;
+ }
+@@ -533,7 +533,7 @@ static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
+ dev->dmasound.dma.sglen,
+ 0))) {
+ saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
+- videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma);
++ videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
+ dsp_buffer_free(dev);
+ return err;
+ }
+@@ -569,7 +569,7 @@ static int snd_card_saa7134_hw_free(struct snd_pcm_substream * substream)
+
+ if (substream->runtime->dma_area) {
+ saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
+- videobuf_pci_dma_unmap(dev->pci, &dev->dmasound.dma);
++ videobuf_sg_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
+ dsp_buffer_free(dev);
+ substream->runtime->dma_area = NULL;
+ }
+@@ -954,10 +954,8 @@ static void snd_saa7134_free(struct snd_card * card)
+ if (chip->dev->dmasound.priv_data == NULL)
+ return;
+
+- if (chip->irq >= 0) {
+- synchronize_irq(chip->irq);
++ if (chip->irq >= 0)
+ free_irq(chip->irq, &chip->dev->dmasound);
+- }
+
+ chip->dev->dmasound.priv_data = NULL;
+
+diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
+index 6f57442..9837595 100644
+--- a/drivers/media/video/saa7134/saa7134-cards.c
++++ b/drivers/media/video/saa7134/saa7134-cards.c
+@@ -22,11 +22,15 @@
+
+ #include <linux/init.h>
+ #include <linux/module.h>
++#include <linux/i2c.h>
++#include <linux/i2c-algo-bit.h>
+
+ #include "saa7134-reg.h"
+ #include "saa7134.h"
++#include "tuner-xc2028.h"
+ #include <media/v4l2-common.h>
+ #include <media/tveeprom.h>
++#include "tea5767.h"
+
+ /* commly used strings */
+ static char name_mute[] = "mute";
+@@ -1046,7 +1050,7 @@ struct saa7134_board saa7134_boards[] = {
+ },
+ [SAA7134_BOARD_MANLI_MTV002] = {
+ /* Ognjen Nastic <ognjen at logosoft.ba> */
+- .name = "Manli MuchTV M-TV002/Behold TV 403 FM",
++ .name = "Manli MuchTV M-TV002",
+ .audio_clock = 0x00200000,
+ .tuner_type = TUNER_PHILIPS_PAL,
+ .radio_type = UNSET,
+@@ -1073,7 +1077,7 @@ struct saa7134_board saa7134_boards[] = {
+ },
+ [SAA7134_BOARD_MANLI_MTV001] = {
+ /* Ognjen Nastic <ognjen at logosoft.ba> UNTESTED */
+- .name = "Manli MuchTV M-TV001/Behold TV 401",
++ .name = "Manli MuchTV M-TV001",
+ .audio_clock = 0x00200000,
+ .tuner_type = TUNER_PHILIPS_PAL,
+ .radio_type = UNSET,
+@@ -2195,6 +2199,8 @@ struct saa7134_board saa7134_boards[] = {
+ },
+ [SAA7134_BOARD_BEHOLD_409FM] = {
+ /* <http://tuner.beholder.ru>, Sergey <skiv at orel.ru> */
++ /* Beholder Intl. Ltd. 2008 */
++ /*Dmitry Belimov <d.belimov at gmail.com> */
+ .name = "Beholder BeholdTV 409 FM",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+@@ -2202,6 +2208,7 @@ struct saa7134_board saa7134_boards[] = {
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
++ .gpiomask = 0x00008000,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 3,
+@@ -2908,15 +2915,13 @@ struct saa7134_board saa7134_boards[] = {
+ }},
+ },
+ [SAA7134_BOARD_MD7134_BRIDGE_2] = {
+- /* This card has two saa7134 chips on it,
+- but only one of them is currently working.
+- The programming for the primary decoder is
+- in SAA7134_BOARD_MD7134 */
++ /* The second saa7134 on this card only serves as DVB-S host bridge */
+ .name = "Medion 7134 Bridge #2",
+ .audio_clock = 0x00187de7,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
++ .mpeg = SAA7134_MPEG_DVB,
+ },
+ [SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS] = {
+ .name = "LifeView FlyDVB-T Hybrid Cardbus/MSI TV @nywhere A/D NB",
+@@ -3330,7 +3335,7 @@ struct saa7134_board saa7134_boards[] = {
+ /* Juan Pablo Sormani <sorman at gmail.com> */
+ .name = "Encore ENLTV-FM",
+ .audio_clock = 0x00200000,
+- .tuner_type = TUNER_PHILIPS_ATSC,
++ .tuner_type = TUNER_PHILIPS_FCV1236D,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+@@ -3575,12 +3580,15 @@ struct saa7134_board saa7134_boards[] = {
+ }},
+ },
+ [SAA7134_BOARD_BEHOLD_401] = {
++ /* Beholder Intl. Ltd. 2008 */
++ /*Dmitry Belimov <d.belimov at gmail.com> */
+ .name = "Beholder BeholdTV 401",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FQ1216ME,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
++ .gpiomask = 0x00008000,
+ .inputs = {{
+ .name = name_svideo,
+ .vmux = 8,
+@@ -3601,12 +3609,15 @@ struct saa7134_board saa7134_boards[] = {
+ },
+ },
+ [SAA7134_BOARD_BEHOLD_403] = {
++ /* Beholder Intl. Ltd. 2008 */
++ /*Dmitry Belimov <d.belimov at gmail.com> */
+ .name = "Beholder BeholdTV 403",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FQ1216ME,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
++ .gpiomask = 0x00008000,
+ .inputs = {{
+ .name = name_svideo,
+ .vmux = 8,
+@@ -3623,12 +3634,15 @@ struct saa7134_board saa7134_boards[] = {
+ }},
+ },
+ [SAA7134_BOARD_BEHOLD_403FM] = {
++ /* Beholder Intl. Ltd. 2008 */
++ /*Dmitry Belimov <d.belimov at gmail.com> */
+ .name = "Beholder BeholdTV 403 FM",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FQ1216ME,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
++ .gpiomask = 0x00008000,
+ .inputs = {{
+ .name = name_svideo,
+ .vmux = 8,
+@@ -3649,6 +3663,8 @@ struct saa7134_board saa7134_boards[] = {
+ },
+ },
+ [SAA7134_BOARD_BEHOLD_405] = {
++ /* Beholder Intl. Ltd. 2008 */
++ /*Dmitry Belimov <d.belimov at gmail.com> */
+ .name = "Beholder BeholdTV 405",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+@@ -3656,6 +3672,7 @@ struct saa7134_board saa7134_boards[] = {
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
++ .gpiomask = 0x00008000,
+ .inputs = {{
+ .name = name_svideo,
+ .vmux = 8,
+@@ -3673,6 +3690,8 @@ struct saa7134_board saa7134_boards[] = {
+ },
+ [SAA7134_BOARD_BEHOLD_405FM] = {
+ /* Sergey <skiv at orel.ru> */
++ /* Beholder Intl. Ltd. 2008 */
++ /*Dmitry Belimov <d.belimov at gmail.com> */
+ .name = "Beholder BeholdTV 405 FM",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+@@ -3680,6 +3699,7 @@ struct saa7134_board saa7134_boards[] = {
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
++ .gpiomask = 0x00008000,
+ .inputs = {{
+ .name = name_svideo,
+ .vmux = 8,
+@@ -3700,6 +3720,8 @@ struct saa7134_board saa7134_boards[] = {
+ },
+ },
+ [SAA7134_BOARD_BEHOLD_407] = {
++ /* Beholder Intl. Ltd. 2008 */
++ /*Dmitry Belimov <d.belimov at gmail.com> */
+ .name = "Beholder BeholdTV 407",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+@@ -3707,7 +3729,7 @@ struct saa7134_board saa7134_boards[] = {
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+- .gpiomask = 0xc0c000,
++ .gpiomask = 0x00008000,
+ .inputs = {{
+ .name = name_svideo,
+ .vmux = 8,
+@@ -3727,6 +3749,8 @@ struct saa7134_board saa7134_boards[] = {
+ }},
+ },
+ [SAA7134_BOARD_BEHOLD_407FM] = {
++ /* Beholder Intl. Ltd. 2008 */
++ /*Dmitry Belimov <d.belimov at gmail.com> */
+ .name = "Beholder BeholdTV 407 FM",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+@@ -3734,7 +3758,7 @@ struct saa7134_board saa7134_boards[] = {
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+- .gpiomask = 0xc0c000,
++ .gpiomask = 0x00008000,
+ .inputs = {{
+ .name = name_svideo,
+ .vmux = 8,
+@@ -3759,6 +3783,8 @@ struct saa7134_board saa7134_boards[] = {
+ },
+ },
+ [SAA7134_BOARD_BEHOLD_409] = {
++ /* Beholder Intl. Ltd. 2008 */
++ /*Dmitry Belimov <d.belimov at gmail.com> */
+ .name = "Beholder BeholdTV 409",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+@@ -3766,6 +3792,7 @@ struct saa7134_board saa7134_boards[] = {
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
++ .gpiomask = 0x00008000,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 3,
+@@ -3782,6 +3809,8 @@ struct saa7134_board saa7134_boards[] = {
+ }},
+ },
+ [SAA7134_BOARD_BEHOLD_505FM] = {
++ /* Beholder Intl. Ltd. 2008 */
++ /*Dmitry Belimov <d.belimov at gmail.com> */
+ .name = "Beholder BeholdTV 505 FM/RDS",
+ .audio_clock = 0x00200000,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+@@ -3789,6 +3818,7 @@ struct saa7134_board saa7134_boards[] = {
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
++ .gpiomask = 0x00008000,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 3,
+@@ -3813,6 +3843,8 @@ struct saa7134_board saa7134_boards[] = {
+ },
+ },
+ [SAA7134_BOARD_BEHOLD_507_9FM] = {
++ /* Beholder Intl. Ltd. 2008 */
++ /*Dmitry Belimov <d.belimov at gmail.com> */
+ .name = "Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+@@ -3820,6 +3852,7 @@ struct saa7134_board saa7134_boards[] = {
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
++ .gpiomask = 0x00008000,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 3,
+@@ -3840,6 +3873,8 @@ struct saa7134_board saa7134_boards[] = {
+ },
+ },
+ [SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM] = {
++ /* Beholder Intl. Ltd. 2008 */
++ /*Dmitry Belimov <d.belimov at gmail.com> */
+ .name = "Beholder BeholdTV Columbus TVFM",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_ALPS_TSBE5_PAL,
+@@ -3847,23 +3882,28 @@ struct saa7134_board saa7134_boards[] = {
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
++ .gpiomask = 0x000A8004,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 3,
+ .amux = TV,
+ .tv = 1,
+- },{
++ .gpio = 0x000A8004,
++ }, {
+ .name = name_comp1,
+ .vmux = 1,
+ .amux = LINE1,
+- },{
++ .gpio = 0x000A8000,
++ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+- }},
++ .gpio = 0x000A8000,
++ } },
+ .radio = {
+ .name = name_radio,
+ .amux = LINE2,
++ .gpio = 0x000A8000,
+ },
+ },
+ [SAA7134_BOARD_BEHOLD_607_9FM] = {
+@@ -3992,6 +4032,221 @@ struct saa7134_board saa7134_boards[] = {
+ .gpio = 0x6000,
+ },
+ },
++ [SAA7134_BOARD_PHILIPS_SNAKE] = {
++ .name = "NXP Snake DVB-S reference design",
++ .audio_clock = 0x00200000,
++ .tuner_type = TUNER_ABSENT,
++ .radio_type = UNSET,
++ .tuner_addr = ADDR_UNSET,
++ .radio_addr = ADDR_UNSET,
++ .mpeg = SAA7134_MPEG_DVB,
++ .inputs = {{
++ .name = name_comp1,
++ .vmux = 3,
++ .amux = LINE1,
++ }, {
++ .name = name_svideo,
++ .vmux = 8,
++ .amux = LINE1,
++ } },
++ },
++ [SAA7134_BOARD_CREATIX_CTX953] = {
++ .name = "Medion/Creatix CTX953 Hybrid",
++ .audio_clock = 0x00187de7,
++ .tuner_type = TUNER_PHILIPS_TDA8290,
++ .radio_type = UNSET,
++ .tuner_addr = ADDR_UNSET,
++ .radio_addr = ADDR_UNSET,
++ .tuner_config = 0,
++ .mpeg = SAA7134_MPEG_DVB,
++ .inputs = {{
++ .name = name_tv,
++ .vmux = 1,
++ .amux = TV,
++ .tv = 1,
++ }, {
++ .name = name_comp1,
++ .vmux = 0,
++ .amux = LINE1,
++ }, {
++ .name = name_svideo,
++ .vmux = 8,
++ .amux = LINE1,
++ } },
++ },
++ [SAA7134_BOARD_MSI_TVANYWHERE_AD11] = {
++ .name = "MSI TV at nywhere A/D v1.1",
++ .audio_clock = 0x00187de7,
++ .tuner_type = TUNER_PHILIPS_TDA8290,
++ .radio_type = UNSET,
++ .tuner_addr = ADDR_UNSET,
++ .radio_addr = ADDR_UNSET,
++ .tuner_config = 2,
++ .mpeg = SAA7134_MPEG_DVB,
++ .gpiomask = 0x0200000,
++ .inputs = { {
++ .name = name_tv,
++ .vmux = 1,
++ .amux = TV,
++ .tv = 1,
++ }, {
++ .name = name_comp1,
++ .vmux = 3,
++ .amux = LINE1,
++ }, {
++ .name = name_svideo,
++ .vmux = 8,
++ .amux = LINE1,
++ } },
++ .radio = {
++ .name = name_radio,
++ .amux = TV,
++ .gpio = 0x0200000,
++ },
++ },
++ [SAA7134_BOARD_AVERMEDIA_CARDBUS_506] = {
++ .name = "AVerMedia Cardbus TV/Radio (E506R)",
++ .audio_clock = 0x187de7,
++ .tuner_type = TUNER_XC2028,
++ .radio_type = UNSET,
++ .tuner_addr = ADDR_UNSET,
++ .radio_addr = ADDR_UNSET,
++ /*
++ TODO:
++ .mpeg = SAA7134_MPEG_DVB,
++ */
++
++ .inputs = {{
++ .name = name_tv,
++ .vmux = 1,
++ .amux = TV,
++ .tv = 1,
++ }, {
++ .name = name_comp1,
++ .vmux = 3,
++ .amux = LINE2,
++ }, {
++ .name = name_svideo,
++ .vmux = 8,
++ .amux = LINE1,
++ } },
++ .radio = {
++ .name = name_radio,
++ .amux = TV,
++ },
++ },
++ [SAA7134_BOARD_AVERMEDIA_A16D] = {
++ .name = "AVerMedia Hybrid TV/Radio (A16D)",
++ .audio_clock = 0x187de7,
++ .tuner_type = TUNER_XC2028,
++ .radio_type = UNSET,
++ .tuner_addr = ADDR_UNSET,
++ .radio_addr = ADDR_UNSET,
++ .inputs = {{
++ .name = name_tv,
++ .vmux = 1,
++ .amux = TV,
++ .tv = 1,
++ }, {
++ .name = name_svideo,
++ .vmux = 8,
++ .amux = LINE1,
++ } },
++ .radio = {
++ .name = name_radio,
++ .amux = LINE1,
++ },
++ },
++ [SAA7134_BOARD_AVERMEDIA_M115] = {
++ .name = "Avermedia M115",
++ .audio_clock = 0x187de7,
++ .tuner_type = TUNER_XC2028,
++ .radio_type = UNSET,
++ .tuner_addr = ADDR_UNSET,
++ .radio_addr = ADDR_UNSET,
++ .inputs = {{
++ .name = name_tv,
++ .vmux = 1,
++ .amux = TV,
++ .tv = 1,
++ }, {
++ .name = name_comp1,
++ .vmux = 3,
++ .amux = LINE1,
++ }, {
++ .name = name_svideo,
++ .vmux = 8,
++ .amux = LINE2,
++ } },
++ },
++ [SAA7134_BOARD_VIDEOMATE_T750] = {
++ /* John Newbigin <jn at it.swin.edu.au> */
++ .name = "Compro VideoMate T750",
++ .audio_clock = 0x00187de7,
++ .tuner_type = TUNER_XC2028,
++ .radio_type = UNSET,
++ .tuner_addr = ADDR_UNSET,
++ .radio_addr = ADDR_UNSET,
++ .mpeg = SAA7134_MPEG_DVB,
++ .inputs = {{
++ .name = name_tv,
++ .vmux = 3,
++ .amux = TV,
++ .tv = 1,
++ }, {
++ .name = name_comp1,
++ .vmux = 1,
++ .amux = LINE2,
++ }, {
++ .name = name_svideo,
++ .vmux = 8,
++ .amux = LINE2,
++ } },
++ .radio = {
++ .name = name_radio,
++ .amux = TV,
++ }
++ },
++ [SAA7134_BOARD_AVERMEDIA_A700_PRO] = {
++ /* Matthias Schwarzott <zzam at gentoo.org> */
++ .name = "Avermedia DVB-S Pro A700",
++ .audio_clock = 0x00187de7,
++ .tuner_type = TUNER_ABSENT,
++ .radio_type = UNSET,
++ .tuner_addr = ADDR_UNSET,
++ .radio_addr = ADDR_UNSET,
++ /* no DVB support for now */
++ /* .mpeg = SAA7134_MPEG_DVB, */
++ .inputs = { {
++ .name = name_comp,
++ .vmux = 1,
++ .amux = LINE1,
++ }, {
++ .name = name_svideo,
++ .vmux = 6,
++ .amux = LINE1,
++ } },
++ },
++ [SAA7134_BOARD_AVERMEDIA_A700_HYBRID] = {
++ /* Matthias Schwarzott <zzam at gentoo.org> */
++ .name = "Avermedia DVB-S Hybrid+FM A700",
++ .audio_clock = 0x00187de7,
++ .tuner_type = TUNER_ABSENT, /* TUNER_XC2028 */
++ .radio_type = UNSET,
++ .tuner_addr = ADDR_UNSET,
++ .radio_addr = ADDR_UNSET,
++ /* no DVB support for now */
++ /* .mpeg = SAA7134_MPEG_DVB, */
++ .inputs = { {
++ .name = name_comp,
++ .vmux = 1,
++ .amux = LINE1,
++ }, {
++ .name = name_svideo,
++ .vmux = 6,
++ .amux = LINE1,
++ } },
++ },
+ };
+
+ const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
+@@ -4224,6 +4479,18 @@ struct pci_device_id saa7134_pci_tbl[] = {
+ .driver_data = SAA7134_BOARD_MD2819,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
++ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
++ .subvendor = 0x1461, /* Avermedia Technologies Inc */
++ .subdevice = 0xa7a1,
++ .driver_data = SAA7134_BOARD_AVERMEDIA_A700_PRO,
++ }, {
++ .vendor = PCI_VENDOR_ID_PHILIPS,
++ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
++ .subvendor = 0x1461, /* Avermedia Technologies Inc */
++ .subdevice = 0xa7a2,
++ .driver_data = SAA7134_BOARD_AVERMEDIA_A700_HYBRID,
++ }, {
++ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7130,
+ .subvendor = 0x1461, /* Avermedia Technologies Inc */
+ .subdevice = 0x2115,
+@@ -4942,7 +5209,43 @@ struct pci_device_id saa7134_pci_tbl[] = {
+ .subvendor = 0x1822, /*Twinhan Technology Co. Ltd*/
+ .subdevice = 0x0022,
+ .driver_data = SAA7134_BOARD_TWINHAN_DTV_DVB_3056,
++ }, {
++ .vendor = PCI_VENDOR_ID_PHILIPS,
++ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
++ .subvendor = 0x16be,
++ .subdevice = 0x0010, /* Medion version CTX953_V.1.4.3 */
++ .driver_data = SAA7134_BOARD_CREATIX_CTX953,
++ }, {
++ .vendor = PCI_VENDOR_ID_PHILIPS,
++ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
++ .subvendor = 0x1462, /* MSI */
++ .subdevice = 0x8625, /* TV at nywhere A/D v1.1 */
++ .driver_data = SAA7134_BOARD_MSI_TVANYWHERE_AD11,
+ },{
++ .vendor = PCI_VENDOR_ID_PHILIPS,
++ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
++ .subvendor = 0x1461, /* Avermedia Technologies Inc */
++ .subdevice = 0xf436,
++ .driver_data = SAA7134_BOARD_AVERMEDIA_CARDBUS_506,
++ }, {
++ .vendor = PCI_VENDOR_ID_PHILIPS,
++ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
++ .subvendor = 0x1461, /* Avermedia Technologies Inc */
++ .subdevice = 0xf936,
++ .driver_data = SAA7134_BOARD_AVERMEDIA_A16D,
++ }, {
++ .vendor = PCI_VENDOR_ID_PHILIPS,
++ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
++ .subvendor = 0x1461, /* Avermedia Technologies Inc */
++ .subdevice = 0xa836,
++ .driver_data = SAA7134_BOARD_AVERMEDIA_M115,
++ }, {
++ .vendor = PCI_VENDOR_ID_PHILIPS,
++ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
++ .subvendor = 0x185b,
++ .subdevice = 0xc900,
++ .driver_data = SAA7134_BOARD_VIDEOMATE_T750,
++ }, {
+ /* --- boards without eeprom + subsystem ID --- */
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7134,
+@@ -4998,6 +5301,77 @@ static void board_flyvideo(struct saa7134_dev *dev)
+ dev->name, dev->name, dev->name);
+ }
+
++static int saa7134_xc2028_callback(struct saa7134_dev *dev,
++ int command, int arg)
++{
++ switch (command) {
++ case XC2028_TUNER_RESET:
++ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0x06e20000);
++ saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0x06a20000);
++ mdelay(250);
++ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0);
++ saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0);
++ mdelay(250);
++ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0x06e20000);
++ saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0x06a20000);
++ mdelay(250);
++ saa_andorl(SAA7133_ANALOG_IO_SELECT >> 2, 0x02, 0x02);
++ saa_andorl(SAA7134_ANALOG_IN_CTRL1 >> 2, 0x81, 0x81);
++ saa_andorl(SAA7134_AUDIO_CLOCK0 >> 2, 0x03187de7, 0x03187de7);
++ saa_andorl(SAA7134_AUDIO_PLL_CTRL >> 2, 0x03, 0x03);
++ saa_andorl(SAA7134_AUDIO_CLOCKS_PER_FIELD0 >> 2,
++ 0x0001e000, 0x0001e000);
++ return 0;
++ }
++ return -EINVAL;
++}
++
++
++static int saa7134_tda8290_callback(struct saa7134_dev *dev,
++ int command, int arg)
++{
++ u8 sync_control;
++
++ switch (command) {
++ case 0: /* switch LNA gain through GPIO 22*/
++ saa7134_set_gpio(dev, 22, arg) ;
++ break;
++ case 1: /* vsync output at GPIO22. 50 / 60Hz */
++ saa_andorb(SAA7134_VIDEO_PORT_CTRL3, 0x80, 0x80);
++ saa_andorb(SAA7134_VIDEO_PORT_CTRL6, 0x0f, 0x03);
++ if (arg == 1)
++ sync_control = 11;
++ else
++ sync_control = 17;
++ saa_writeb(SAA7134_VGATE_START, sync_control);
++ saa_writeb(SAA7134_VGATE_STOP, sync_control + 1);
++ saa_andorb(SAA7134_MISC_VGATE_MSB, 0x03, 0x00);
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++int saa7134_tuner_callback(void *priv, int command, int arg)
++{
++ struct saa7134_dev *dev = priv;
++ if (dev != NULL) {
++ switch (dev->tuner_type) {
++ case TUNER_PHILIPS_TDA8290:
++ return saa7134_tda8290_callback(dev, command, arg);
++ case TUNER_XC2028:
++ return saa7134_xc2028_callback(dev, command, arg);
++ }
++ } else {
++ printk(KERN_ERR "saa7134: Error - device struct undefined.\n");
++ return -EINVAL;
++ }
++ return -EINVAL;
++}
++EXPORT_SYMBOL(saa7134_tuner_callback);
++
+ /* ----------------------------------------------------------- */
+
+ static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data)
+@@ -5067,6 +5441,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
+ case SAA7134_BOARD_VIDEOMATE_DVBT_300:
+ case SAA7134_BOARD_VIDEOMATE_DVBT_200:
+ case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
++ case SAA7134_BOARD_VIDEOMATE_T750:
+ case SAA7134_BOARD_MANLI_MTV001:
+ case SAA7134_BOARD_MANLI_MTV002:
+ case SAA7134_BOARD_BEHOLD_409FM:
+@@ -5133,11 +5508,29 @@ int saa7134_board_init1(struct saa7134_dev *dev)
+ saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08000000, 0x00000000);
+ break;
+ case SAA7134_BOARD_AVERMEDIA_CARDBUS:
+- case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
++ case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
++ case SAA7134_BOARD_AVERMEDIA_M115:
++ case SAA7134_BOARD_AVERMEDIA_A16D:
++ /* power-down tuner chip */
++ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0xffffffff, 0);
++ saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0);
++ msleep(10);
+ /* power-up tuner chip */
+ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0xffffffff, 0xffffffff);
+ saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0xffffffff);
+- msleep(1);
++ msleep(10);
++ break;
++ case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
++ /* power-down tuner chip */
++ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x000A8004, 0x000A8004);
++ saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x000A8004, 0);
++ msleep(10);
++ /* power-up tuner chip */
++ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x000A8004, 0x000A8004);
++ saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x000A8004, 0x000A8004);
++ msleep(10);
++ /* remote via GPIO */
++ dev->has_remote = SAA7134_REMOTE_GPIO;
+ break;
+ case SAA7134_BOARD_RTD_VFG7350:
+
+@@ -5160,7 +5553,6 @@ int saa7134_board_init1(struct saa7134_dev *dev)
+ dev->has_remote = SAA7134_REMOTE_I2C;
+ break;
+ case SAA7134_BOARD_AVERMEDIA_A169_B:
+- case SAA7134_BOARD_MD7134_BRIDGE_2:
+ printk("%s: %s: dual saa713x broadcast decoders\n"
+ "%s: Sorry, none of the inputs to this chip are supported yet.\n"
+ "%s: Dual decoder functionality is disabled for now, use the other chip.\n",
+@@ -5172,6 +5564,15 @@ int saa7134_board_init1(struct saa7134_dev *dev)
+ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x8c040007, 0x8c040007);
+ saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0c0007cd, 0x0c0007cd);
+ break;
++ case SAA7134_BOARD_AVERMEDIA_A700_PRO:
++ case SAA7134_BOARD_AVERMEDIA_A700_HYBRID:
++ /* write windows gpio values */
++ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x80040100, 0x80040100);
++ saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x80040100, 0x00040100);
++ printk("%s: %s: hybrid analog/dvb card\n"
++ "%s: Sorry, only the analog inputs are supported for now.\n",
++ dev->name, card(dev).name, dev->name);
++ break;
+ }
+ return 0;
+ }
+@@ -5200,11 +5601,16 @@ int saa7134_board_init2(struct saa7134_dev *dev)
+ dev->tuner_type = saa7134_boards[dev->board].tuner_type;
+
+ if (TUNER_ABSENT != dev->tuner_type) {
+- tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV;
+- tun_setup.type = dev->tuner_type;
+- tun_setup.addr = ADDR_UNSET;
++ tun_setup.mode_mask = T_RADIO |
++ T_ANALOG_TV |
++ T_DIGITAL_TV;
++ tun_setup.type = dev->tuner_type;
++ tun_setup.addr = ADDR_UNSET;
++ tun_setup.tuner_callback = saa7134_tuner_callback;
+
+- saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR, &tun_setup);
++ saa7134_i2c_call_clients(dev,
++ TUNER_SET_TYPE_ADDR,
++ &tun_setup);
+ }
+ break;
+ case SAA7134_BOARD_MD7134:
+@@ -5275,14 +5681,25 @@ int saa7134_board_init2(struct saa7134_dev *dev)
+ &tda9887_cfg);
+ }
+
+- tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV;
++ tun_setup.mode_mask = T_RADIO |
++ T_ANALOG_TV |
++ T_DIGITAL_TV;
+ tun_setup.type = dev->tuner_type;
+ tun_setup.addr = ADDR_UNSET;
+
+- saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup);
++ saa7134_i2c_call_clients(dev,
++ TUNER_SET_TYPE_ADDR, &tun_setup);
+ }
+ break;
+ case SAA7134_BOARD_PHILIPS_EUROPA:
++ if (dev->autodetected && (dev->eedata[0x41] == 0x1c)) {
++ /* Reconfigure board as Snake reference design */
++ dev->board = SAA7134_BOARD_PHILIPS_SNAKE;
++ dev->tuner_type = saa7134_boards[dev->board].tuner_type;
++ printk(KERN_INFO "%s: Reconfigured board as %s\n",
++ dev->name, saa7134_boards[dev->board].name);
++ break;
++ }
+ case SAA7134_BOARD_VIDEOMATE_DVBT_300:
+ case SAA7134_BOARD_ASUS_EUROPA2_HYBRID:
+ /* The Philips EUROPA based hybrid boards have the tuner connected through
+@@ -5333,6 +5750,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
+ case SAA7134_BOARD_MEDION_MD8800_QUADRO:
+ case SAA7134_BOARD_AVERMEDIA_SUPER_007:
+ case SAA7134_BOARD_TWINHAN_DTV_DVB_3056:
++ case SAA7134_BOARD_CREATIX_CTX953:
+ /* this is a hybrid board, initialize to analog mode
+ * and configure firmware eeprom address
+ */
+@@ -5402,13 +5820,46 @@ int saa7134_board_init2(struct saa7134_dev *dev)
+ break;
+ }
+ break;
++ case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
++ {
++ struct v4l2_priv_tun_config tea5767_cfg;
++ struct tea5767_ctrl ctl;
++
++ dev->i2c_client.addr = 0xC0;
++ /* set TEA5767(analog FM) defines */
++ memset(&ctl, 0, sizeof(ctl));
++ ctl.xtal_freq = TEA5767_HIGH_LO_13MHz;
++ tea5767_cfg.tuner = TUNER_TEA5767;
++ tea5767_cfg.priv = &ctl;
++ saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &tea5767_cfg);
++ }
++ break;
+ }
++
++ if (dev->tuner_type == TUNER_XC2028) {
++ struct v4l2_priv_tun_config xc2028_cfg;
++ struct xc2028_ctrl ctl;
++
++ memset(&xc2028_cfg, 0, sizeof(ctl));
++ memset(&ctl, 0, sizeof(ctl));
++
++ ctl.fname = XC2028_DEFAULT_FIRMWARE;
++ ctl.max_len = 64;
++
++ switch (dev->board) {
++ case SAA7134_BOARD_AVERMEDIA_A16D:
++ ctl.demod = XC3028_FE_ZARLINK456;
++ break;
++ default:
++ ctl.demod = XC3028_FE_OREN538;
++ ctl.mts = 1;
++ }
++
++ xc2028_cfg.tuner = TUNER_XC2028;
++ xc2028_cfg.priv = &ctl;
++
++ saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &xc2028_cfg);
++ }
++
+ return 0;
+ }
+-
+-/* ----------------------------------------------------------- */
+-/*
+- * Local variables:
+- * c-basic-offset: 8
+- * End:
+- */
+diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
+index 58ab163..eec1278 100644
+--- a/drivers/media/video/saa7134/saa7134-core.c
++++ b/drivers/media/video/saa7134/saa7134-core.c
+@@ -42,23 +42,23 @@ MODULE_LICENSE("GPL");
+
+ /* ------------------------------------------------------------------ */
+
+-static unsigned int irq_debug = 0;
++static unsigned int irq_debug;
+ module_param(irq_debug, int, 0644);
+ MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]");
+
+-static unsigned int core_debug = 0;
++static unsigned int core_debug;
+ module_param(core_debug, int, 0644);
+ MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
+
+-static unsigned int gpio_tracking = 0;
++static unsigned int gpio_tracking;
+ module_param(gpio_tracking, int, 0644);
+ MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]");
+
+-static unsigned int alsa = 0;
++static unsigned int alsa;
+ module_param(alsa, int, 0644);
+ MODULE_PARM_DESC(alsa,"enable ALSA DMA sound [dmasound]");
+
+-static unsigned int oss = 0;
++static unsigned int oss;
+ module_param(oss, int, 0644);
+ MODULE_PARM_DESC(oss,"enable OSS DMA sound [dmasound]");
+
+@@ -142,39 +142,6 @@ void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value)
+ }
+ }
+
+-int saa7134_tuner_callback(void *ptr, int command, int arg)
+-{
+- u8 sync_control;
+- struct saa7134_dev *dev = ptr;
+-
+- switch (dev->tuner_type) {
+- case TUNER_PHILIPS_TDA8290:
+- switch (command) {
+- case 0: /* switch LNA gain through GPIO 22*/
+- saa7134_set_gpio(dev, 22, arg) ;
+- break;
+- case 1: /* vsync output at GPIO22. 50 / 60Hz */
+- dprintk("setting GPIO22 to vsync %d\n", arg);
+- saa_andorb(SAA7134_VIDEO_PORT_CTRL3, 0x80, 0x80);
+- saa_andorb(SAA7134_VIDEO_PORT_CTRL6, 0x0f, 0x03);
+- if (arg == 1)
+- sync_control = 11;
+- else
+- sync_control = 17;
+- saa_writeb(SAA7134_VGATE_START, sync_control);
+- saa_writeb(SAA7134_VGATE_STOP, sync_control + 1);
+- saa_andorb(SAA7134_MISC_VGATE_MSB, 0x03, 0x00);
+- break;
+- default:
+- return -EINVAL;
+- }
+- break;
+- default:
+- return -ENODEV;
+- }
+- return 0;
+-}
+-
+ /* ------------------------------------------------------------------ */
+
+
+@@ -897,6 +864,10 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
+ struct saa7134_dev *dev;
+ struct saa7134_mpeg_ops *mops;
+ int err;
++ int mask;
++
++ if (saa7134_devcount == SAA7134_MAXBOARDS)
++ return -ENOMEM;
+
+ dev = kzalloc(sizeof(*dev),GFP_KERNEL);
+ if (NULL == dev)
+@@ -1094,6 +1065,11 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
+ if (TUNER_ABSENT != dev->tuner_type)
+ saa7134_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL);
+
++ if (card(dev).gpiomask != 0) {
++ mask = card(dev).gpiomask;
++ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, mask, mask);
++ saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, 0);
++ }
+ return 0;
+
+ fail4:
+diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
+index ea2be9e..2d16be2 100644
+--- a/drivers/media/video/saa7134/saa7134-dvb.c
++++ b/drivers/media/video/saa7134/saa7134-dvb.c
+@@ -33,33 +33,40 @@
+ #include "saa7134.h"
+ #include <media/v4l2-common.h>
+ #include "dvb-pll.h"
++#include <dvb_frontend.h>
+
+ #include "mt352.h"
+ #include "mt352_priv.h" /* FIXME */
+ #include "tda1004x.h"
+ #include "nxt200x.h"
++#include "tuner-xc2028.h"
+
+ #include "tda10086.h"
+ #include "tda826x.h"
+ #include "tda827x.h"
+ #include "isl6421.h"
++#include "isl6405.h"
++#include "lnbp21.h"
++#include "tuner-simple.h"
+
+ MODULE_AUTHOR("Gerd Knorr <kraxel at bytesex.org> [SuSE Labs]");
+ MODULE_LICENSE("GPL");
+
+-static unsigned int antenna_pwr = 0;
++static unsigned int antenna_pwr;
+
+ module_param(antenna_pwr, int, 0444);
+ MODULE_PARM_DESC(antenna_pwr,"enable antenna power (Pinnacle 300i)");
+
+-static int use_frontend = 0;
++static int use_frontend;
+ module_param(use_frontend, int, 0644);
+ MODULE_PARM_DESC(use_frontend,"for cards with multiple frontends (0: terrestrial, 1: satellite)");
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "Turn on/off module debugging (default:off).");
+
++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
++
+ #define dprintk(fmt, arg...) do { if (debug) \
+ printk(KERN_DEBUG "%s/dvb: " fmt, dev->name , ## arg); } while(0)
+
+@@ -91,7 +98,7 @@ static int pinnacle_antenna_pwr(struct saa7134_dev *dev, int on)
+ saa_setl(SAA7134_GPIO_GPSTATUS0 >> 2, (1 << 28));
+ udelay(10);
+ ok = saa_readl(SAA7134_GPIO_GPSTATUS0) & (1 << 27);
+- dprintk("%s %s\n", __FUNCTION__, ok ? "on" : "off");
++ dprintk("%s %s\n", __func__, ok ? "on" : "off");
+
+ if (!ok)
+ saa_clearl(SAA7134_GPIO_GPSTATUS0 >> 2, (1 << 26));
+@@ -111,7 +118,7 @@ static int mt352_pinnacle_init(struct dvb_frontend* fe)
+ static u8 irq_cfg [] = { INTERRUPT_EN_0, 0x00, 0x00, 0x00, 0x00 };
+ struct saa7134_dev *dev= fe->dvb->priv;
+
+- dprintk("%s called\n", __FUNCTION__);
++ dprintk("%s called\n", __func__);
+
+ mt352_write(fe, clock_config, sizeof(clock_config));
+ udelay(200);
+@@ -146,6 +153,26 @@ static int mt352_aver777_init(struct dvb_frontend* fe)
+ return 0;
+ }
+
++static int mt352_aver_a16d_init(struct dvb_frontend *fe)
++{
++ static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x2d };
++ static u8 reset [] = { RESET, 0x80 };
++ static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
++ static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0xa0 };
++ static u8 capt_range_cfg[] = { CAPT_RANGE, 0x33 };
++
++ mt352_write(fe, clock_config, sizeof(clock_config));
++ udelay(200);
++ mt352_write(fe, reset, sizeof(reset));
++ mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
++ mt352_write(fe, agc_cfg, sizeof(agc_cfg));
++ mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
++
++ return 0;
++}
++
++
++
+ static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters* params)
+ {
+@@ -188,6 +215,16 @@ static struct mt352_config avermedia_777 = {
+ .demod_init = mt352_aver777_init,
+ };
+
++static struct mt352_config avermedia_16d = {
++ .demod_address = 0xf,
++ .demod_init = mt352_aver_a16d_init,
++};
++
++static struct mt352_config avermedia_e506r_mt352_dev = {
++ .demod_address = (0x1e >> 1),
++ .no_tuner = 1,
++};
++
+ /* ==================================================================
+ * tda1004x based DVB-T cards, helper functions
+ */
+@@ -430,8 +467,6 @@ static struct tda1004x_config philips_europa_config = {
+ .request_firmware = philips_tda1004x_request_firmware
+ };
+
+-/* ------------------------------------------------------------------ */
+-
+ static struct tda1004x_config medion_cardbus = {
+ .demod_address = 0x08,
+ .invert = 1,
+@@ -447,47 +482,6 @@ static struct tda1004x_config medion_cardbus = {
+ * tda 1004x based cards with philips silicon tuner
+ */
+
+-static void philips_tda827x_lna_gain(struct dvb_frontend *fe, int high)
+-{
+- struct saa7134_dev *dev = fe->dvb->priv;
+- struct tda1004x_state *state = fe->demodulator_priv;
+- u8 addr = state->config->i2c_gate;
+- u8 config = state->config->tuner_config;
+- u8 GP00_CF[] = {0x20, 0x01};
+- u8 GP00_LEV[] = {0x22, 0x00};
+-
+- struct i2c_msg msg = {.addr = addr,.flags = 0,.buf = GP00_CF, .len = 2};
+- if (config) {
+- if (high) {
+- dprintk("setting LNA to high gain\n");
+- } else {
+- dprintk("setting LNA to low gain\n");
+- }
+- }
+- switch (config) {
+- case 0: /* no LNA */
+- break;
+- case 1: /* switch is GPIO 0 of tda8290 */
+- case 2:
+- /* turn Vsync off */
+- saa7134_set_gpio(dev, 22, 0);
+- GP00_LEV[1] = high ? 0 : 1;
+- if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) {
+- wprintk("could not access tda8290 at addr: 0x%02x\n",
+- addr << 1);
+- return;
+- }
+- msg.buf = GP00_LEV;
+- if (config == 2)
+- GP00_LEV[1] = high ? 1 : 0;
+- i2c_transfer(&dev->i2c_adap, &msg, 1);
+- break;
+- case 3: /* switch with GPIO of saa713x */
+- saa7134_set_gpio(dev, 22, high);
+- break;
+- }
+-}
+-
+ static int tda8290_i2c_gate_ctrl( struct dvb_frontend* fe, int enable)
+ {
+ struct tda1004x_state *state = fe->demodulator_priv;
+@@ -510,8 +504,6 @@ static int tda8290_i2c_gate_ctrl( struct dvb_frontend* fe, int enable)
+ return 0;
+ }
+
+-/* ------------------------------------------------------------------ */
+-
+ static int philips_tda827x_tuner_init(struct dvb_frontend *fe)
+ {
+ struct saa7134_dev *dev = fe->dvb->priv;
+@@ -546,28 +538,57 @@ static int philips_tda827x_tuner_sleep(struct dvb_frontend *fe)
+ return 0;
+ }
+
+-static struct tda827x_config tda827x_cfg = {
+- .lna_gain = philips_tda827x_lna_gain,
+- .init = philips_tda827x_tuner_init,
+- .sleep = philips_tda827x_tuner_sleep
+-};
+-
+-static void configure_tda827x_fe(struct saa7134_dev *dev, struct tda1004x_config *tda_conf)
++static void configure_tda827x_fe(struct saa7134_dev *dev, struct tda1004x_config *cdec_conf,
++ struct tda827x_config *tuner_conf)
+ {
+- dev->dvb.frontend = dvb_attach(tda10046_attach, tda_conf, &dev->i2c_adap);
++ dev->dvb.frontend = dvb_attach(tda10046_attach, cdec_conf, &dev->i2c_adap);
+ if (dev->dvb.frontend) {
+- if (tda_conf->i2c_gate)
++ if (cdec_conf->i2c_gate)
+ dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
+- if (dvb_attach(tda827x_attach, dev->dvb.frontend, tda_conf->tuner_address,
+- &dev->i2c_adap,&tda827x_cfg) == NULL) {
++ if (dvb_attach(tda827x_attach, dev->dvb.frontend, cdec_conf->tuner_address,
++ &dev->i2c_adap, tuner_conf) == NULL) {
+ wprintk("no tda827x tuner found at addr: %02x\n",
+- tda_conf->tuner_address);
++ cdec_conf->tuner_address);
+ }
+ }
+ }
+
+ /* ------------------------------------------------------------------ */
+
++static struct tda827x_config tda827x_cfg_0 = {
++ .tuner_callback = saa7134_tuner_callback,
++ .init = philips_tda827x_tuner_init,
++ .sleep = philips_tda827x_tuner_sleep,
++ .config = 0,
++ .switch_addr = 0
++};
++
++static struct tda827x_config tda827x_cfg_1 = {
++ .tuner_callback = saa7134_tuner_callback,
++ .init = philips_tda827x_tuner_init,
++ .sleep = philips_tda827x_tuner_sleep,
++ .config = 1,
++ .switch_addr = 0x4b
++};
++
++static struct tda827x_config tda827x_cfg_2 = {
++ .tuner_callback = saa7134_tuner_callback,
++ .init = philips_tda827x_tuner_init,
++ .sleep = philips_tda827x_tuner_sleep,
++ .config = 2,
++ .switch_addr = 0x4b
++};
++
++static struct tda827x_config tda827x_cfg_2_sw42 = {
++ .tuner_callback = saa7134_tuner_callback,
++ .init = philips_tda827x_tuner_init,
++ .sleep = philips_tda827x_tuner_sleep,
++ .config = 2,
++ .switch_addr = 0x42
++};
++
++/* ------------------------------------------------------------------ */
++
+ static struct tda1004x_config tda827x_lifeview_config = {
+ .demod_address = 0x08,
+ .invert = 1,
+@@ -590,7 +611,6 @@ static struct tda1004x_config philips_tiger_config = {
+ .if_freq = TDA10046_FREQ_045,
+ .i2c_gate = 0x4b,
+ .tuner_address = 0x61,
+- .tuner_config = 0,
+ .antenna_switch= 1,
+ .request_firmware = philips_tda1004x_request_firmware
+ };
+@@ -605,7 +625,6 @@ static struct tda1004x_config cinergy_ht_config = {
+ .if_freq = TDA10046_FREQ_045,
+ .i2c_gate = 0x4b,
+ .tuner_address = 0x61,
+- .tuner_config = 0,
+ .request_firmware = philips_tda1004x_request_firmware
+ };
+
+@@ -619,7 +638,6 @@ static struct tda1004x_config cinergy_ht_pci_config = {
+ .if_freq = TDA10046_FREQ_045,
+ .i2c_gate = 0x4b,
+ .tuner_address = 0x60,
+- .tuner_config = 0,
+ .request_firmware = philips_tda1004x_request_firmware
+ };
+
+@@ -633,7 +651,6 @@ static struct tda1004x_config philips_tiger_s_config = {
+ .if_freq = TDA10046_FREQ_045,
+ .i2c_gate = 0x4b,
+ .tuner_address = 0x61,
+- .tuner_config = 2,
+ .antenna_switch= 1,
+ .request_firmware = philips_tda1004x_request_firmware
+ };
+@@ -648,7 +665,6 @@ static struct tda1004x_config pinnacle_pctv_310i_config = {
+ .if_freq = TDA10046_FREQ_045,
+ .i2c_gate = 0x4b,
+ .tuner_address = 0x61,
+- .tuner_config = 1,
+ .request_firmware = philips_tda1004x_request_firmware
+ };
+
+@@ -662,7 +678,6 @@ static struct tda1004x_config hauppauge_hvr_1110_config = {
+ .if_freq = TDA10046_FREQ_045,
+ .i2c_gate = 0x4b,
+ .tuner_address = 0x61,
+- .tuner_config = 1,
+ .request_firmware = philips_tda1004x_request_firmware
+ };
+
+@@ -676,7 +691,6 @@ static struct tda1004x_config asus_p7131_dual_config = {
+ .if_freq = TDA10046_FREQ_045,
+ .i2c_gate = 0x4b,
+ .tuner_address = 0x61,
+- .tuner_config = 0,
+ .antenna_switch= 2,
+ .request_firmware = philips_tda1004x_request_firmware
+ };
+@@ -715,7 +729,6 @@ static struct tda1004x_config md8800_dvbt_config = {
+ .if_freq = TDA10046_FREQ_045,
+ .i2c_gate = 0x4b,
+ .tuner_address = 0x60,
+- .tuner_config = 0,
+ .request_firmware = philips_tda1004x_request_firmware
+ };
+
+@@ -729,7 +742,6 @@ static struct tda1004x_config asus_p7131_4871_config = {
+ .if_freq = TDA10046_FREQ_045,
+ .i2c_gate = 0x4b,
+ .tuner_address = 0x61,
+- .tuner_config = 2,
+ .antenna_switch= 2,
+ .request_firmware = philips_tda1004x_request_firmware
+ };
+@@ -744,7 +756,6 @@ static struct tda1004x_config asus_p7131_hybrid_lna_config = {
+ .if_freq = TDA10046_FREQ_045,
+ .i2c_gate = 0x4b,
+ .tuner_address = 0x61,
+- .tuner_config = 2,
+ .antenna_switch= 2,
+ .request_firmware = philips_tda1004x_request_firmware
+ };
+@@ -759,7 +770,6 @@ static struct tda1004x_config kworld_dvb_t_210_config = {
+ .if_freq = TDA10046_FREQ_045,
+ .i2c_gate = 0x4b,
+ .tuner_address = 0x61,
+- .tuner_config = 2,
+ .antenna_switch= 1,
+ .request_firmware = philips_tda1004x_request_firmware
+ };
+@@ -774,7 +784,6 @@ static struct tda1004x_config avermedia_super_007_config = {
+ .if_freq = TDA10046_FREQ_045,
+ .i2c_gate = 0x4b,
+ .tuner_address = 0x60,
+- .tuner_config = 0,
+ .antenna_switch= 1,
+ .request_firmware = philips_tda1004x_request_firmware
+ };
+@@ -789,7 +798,6 @@ static struct tda1004x_config twinhan_dtv_dvb_3056_config = {
+ .if_freq = TDA10046_FREQ_045,
+ .i2c_gate = 0x42,
+ .tuner_address = 0x61,
+- .tuner_config = 2,
+ .antenna_switch = 1,
+ .request_firmware = philips_tda1004x_request_firmware
+ };
+@@ -817,9 +825,10 @@ static int ads_duo_tuner_sleep(struct dvb_frontend *fe)
+ }
+
+ static struct tda827x_config ads_duo_cfg = {
+- .lna_gain = philips_tda827x_lna_gain,
++ .tuner_callback = saa7134_tuner_callback,
+ .init = ads_duo_tuner_init,
+- .sleep = ads_duo_tuner_sleep
++ .sleep = ads_duo_tuner_sleep,
++ .config = 0
+ };
+
+ static struct tda1004x_config ads_tech_duo_config = {
+@@ -842,8 +851,73 @@ static struct tda10086_config flydvbs = {
+ .demod_address = 0x0e,
+ .invert = 0,
+ .diseqc_tone = 0,
++ .xtal_freq = TDA10086_XTAL_16M,
+ };
+
++static struct tda10086_config sd1878_4m = {
++ .demod_address = 0x0e,
++ .invert = 0,
++ .diseqc_tone = 0,
++ .xtal_freq = TDA10086_XTAL_4M,
++};
++
++/* ------------------------------------------------------------------
++ * special case: lnb supply is connected to the gated i2c
++ */
++
++static int md8800_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
++{
++ int res = -EIO;
++ struct saa7134_dev *dev = fe->dvb->priv;
++ if (fe->ops.i2c_gate_ctrl) {
++ fe->ops.i2c_gate_ctrl(fe, 1);
++ if (dev->original_set_voltage)
++ res = dev->original_set_voltage(fe, voltage);
++ fe->ops.i2c_gate_ctrl(fe, 0);
++ }
++ return res;
++};
++
++static int md8800_set_high_voltage(struct dvb_frontend *fe, long arg)
++{
++ int res = -EIO;
++ struct saa7134_dev *dev = fe->dvb->priv;
++ if (fe->ops.i2c_gate_ctrl) {
++ fe->ops.i2c_gate_ctrl(fe, 1);
++ if (dev->original_set_high_voltage)
++ res = dev->original_set_high_voltage(fe, arg);
++ fe->ops.i2c_gate_ctrl(fe, 0);
++ }
++ return res;
++};
++
++static int md8800_set_voltage2(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
++{
++ struct saa7134_dev *dev = fe->dvb->priv;
++ u8 wbuf[2] = { 0x1f, 00 };
++ u8 rbuf;
++ struct i2c_msg msg[] = { { .addr = 0x08, .flags = 0, .buf = wbuf, .len = 1 },
++ { .addr = 0x08, .flags = I2C_M_RD, .buf = &rbuf, .len = 1 } };
++
++ if (i2c_transfer(&dev->i2c_adap, msg, 2) != 2)
++ return -EIO;
++ /* NOTE: this assumes that gpo1 is used, it might be bit 5 (gpo2) */
++ if (voltage == SEC_VOLTAGE_18)
++ wbuf[1] = rbuf | 0x10;
++ else
++ wbuf[1] = rbuf & 0xef;
++ msg[0].len = 2;
++ i2c_transfer(&dev->i2c_adap, msg, 1);
++ return 0;
++}
++
++static int md8800_set_high_voltage2(struct dvb_frontend *fe, long arg)
++{
++ struct saa7134_dev *dev = fe->dvb->priv;
++ wprintk("%s: sorry can't set high LNB supply voltage from here\n", __func__);
++ return -EIO;
++}
++
+ /* ==================================================================
+ * nxt200x based ATSC cards, helper functions
+ */
+@@ -863,12 +937,14 @@ static struct nxt200x_config kworldatsc110 = {
+ static int dvb_init(struct saa7134_dev *dev)
+ {
+ int ret;
++ int attach_xc3028 = 0;
++
+ /* init struct videobuf_dvb */
+ dev->ts.nr_bufs = 32;
+ dev->ts.nr_packets = 32*4;
+ dev->dvb.name = dev->name;
+- videobuf_queue_pci_init(&dev->dvb.dvbq, &saa7134_ts_qops,
+- dev->pci, &dev->slock,
++ videobuf_queue_sg_init(&dev->dvb.dvbq, &saa7134_ts_qops,
++ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_ALTERNATE,
+ sizeof(struct saa7134_buf),
+@@ -889,17 +965,25 @@ static int dvb_init(struct saa7134_dev *dev)
+ dev->dvb.frontend = dvb_attach(mt352_attach, &avermedia_777,
+ &dev->i2c_adap);
+ if (dev->dvb.frontend) {
+- dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+- NULL, DVB_PLL_PHILIPS_TD1316);
++ dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++ &dev->i2c_adap, 0x61,
++ TUNER_PHILIPS_TD1316);
+ }
+ break;
++ case SAA7134_BOARD_AVERMEDIA_A16D:
++ dprintk("avertv A16D dvb setup\n");
++ dev->dvb.frontend = dvb_attach(mt352_attach, &avermedia_16d,
++ &dev->i2c_adap);
++ attach_xc3028 = 1;
++ break;
+ case SAA7134_BOARD_MD7134:
+ dev->dvb.frontend = dvb_attach(tda10046_attach,
+ &medion_cardbus,
+ &dev->i2c_adap);
+ if (dev->dvb.frontend) {
+- dvb_attach(dvb_pll_attach, dev->dvb.frontend, medion_cardbus.tuner_address,
+- &dev->i2c_adap, DVB_PLL_FMD1216ME);
++ dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++ &dev->i2c_adap, medion_cardbus.tuner_address,
++ TUNER_PHILIPS_FMD1216ME_MK3);
+ }
+ break;
+ case SAA7134_BOARD_PHILIPS_TOUGH:
+@@ -913,7 +997,7 @@ static int dvb_init(struct saa7134_dev *dev)
+ break;
+ case SAA7134_BOARD_FLYDVBTDUO:
+ case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS:
+- configure_tda827x_fe(dev, &tda827x_lifeview_config);
++ configure_tda827x_fe(dev, &tda827x_lifeview_config, &tda827x_cfg_0);
+ break;
+ case SAA7134_BOARD_PHILIPS_EUROPA:
+ case SAA7134_BOARD_VIDEOMATE_DVBT_300:
+@@ -938,36 +1022,36 @@ static int dvb_init(struct saa7134_dev *dev)
+ }
+ break;
+ case SAA7134_BOARD_KWORLD_DVBT_210:
+- configure_tda827x_fe(dev, &kworld_dvb_t_210_config);
++ configure_tda827x_fe(dev, &kworld_dvb_t_210_config, &tda827x_cfg_2);
+ break;
+ case SAA7134_BOARD_PHILIPS_TIGER:
+- configure_tda827x_fe(dev, &philips_tiger_config);
++ configure_tda827x_fe(dev, &philips_tiger_config, &tda827x_cfg_0);
+ break;
+ case SAA7134_BOARD_PINNACLE_PCTV_310i:
+- configure_tda827x_fe(dev, &pinnacle_pctv_310i_config);
++ configure_tda827x_fe(dev, &pinnacle_pctv_310i_config, &tda827x_cfg_1);
+ break;
+ case SAA7134_BOARD_HAUPPAUGE_HVR1110:
+- configure_tda827x_fe(dev, &hauppauge_hvr_1110_config);
++ configure_tda827x_fe(dev, &hauppauge_hvr_1110_config, &tda827x_cfg_1);
+ break;
+ case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
+- configure_tda827x_fe(dev, &asus_p7131_dual_config);
++ configure_tda827x_fe(dev, &asus_p7131_dual_config, &tda827x_cfg_0);
+ break;
+ case SAA7134_BOARD_FLYDVBT_LR301:
+- configure_tda827x_fe(dev, &tda827x_lifeview_config);
++ configure_tda827x_fe(dev, &tda827x_lifeview_config, &tda827x_cfg_0);
+ break;
+ case SAA7134_BOARD_FLYDVB_TRIO:
+ if(! use_frontend) { /* terrestrial */
+- configure_tda827x_fe(dev, &lifeview_trio_config);
+- } else { /* satellite */
++ configure_tda827x_fe(dev, &lifeview_trio_config, &tda827x_cfg_0);
++ } else { /* satellite */
+ dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap);
+ if (dev->dvb.frontend) {
+ if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x63,
+ &dev->i2c_adap, 0) == NULL) {
+- wprintk("%s: Lifeview Trio, No tda826x found!\n", __FUNCTION__);
++ wprintk("%s: Lifeview Trio, No tda826x found!\n", __func__);
+ }
+ if (dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->i2c_adap,
+ 0x08, 0, 0) == NULL) {
+- wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __FUNCTION__);
++ wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __func__);
+ }
+ }
+ }
+@@ -979,18 +1063,56 @@ static int dvb_init(struct saa7134_dev *dev)
+ &dev->i2c_adap);
+ if (dev->dvb.frontend) {
+ if (dvb_attach(tda827x_attach,dev->dvb.frontend,
+- ads_tech_duo_config.tuner_address,
+- &dev->i2c_adap,&ads_duo_cfg) == NULL) {
++ ads_tech_duo_config.tuner_address, &dev->i2c_adap,
++ &ads_duo_cfg) == NULL) {
+ wprintk("no tda827x tuner found at addr: %02x\n",
+ ads_tech_duo_config.tuner_address);
+ }
+ }
+ break;
+ case SAA7134_BOARD_TEVION_DVBT_220RF:
+- configure_tda827x_fe(dev, &tevion_dvbt220rf_config);
++ configure_tda827x_fe(dev, &tevion_dvbt220rf_config, &tda827x_cfg_0);
+ break;
+ case SAA7134_BOARD_MEDION_MD8800_QUADRO:
+- configure_tda827x_fe(dev, &md8800_dvbt_config);
++ if (!use_frontend) { /* terrestrial */
++ configure_tda827x_fe(dev, &md8800_dvbt_config, &tda827x_cfg_0);
++ } else { /* satellite */
++ dev->dvb.frontend = dvb_attach(tda10086_attach,
++ &flydvbs, &dev->i2c_adap);
++ if (dev->dvb.frontend) {
++ struct dvb_frontend *fe = dev->dvb.frontend;
++ u8 dev_id = dev->eedata[2];
++ u8 data = 0xc4;
++ struct i2c_msg msg = {.addr = 0x08, .flags = 0, .len = 1};
++
++ if (dvb_attach(tda826x_attach, dev->dvb.frontend,
++ 0x60, &dev->i2c_adap, 0) == NULL)
++ wprintk("%s: Medion Quadro, no tda826x "
++ "found !\n", __func__);
++ if (dev_id != 0x08) {
++ /* we need to open the i2c gate (we know it exists) */
++ fe->ops.i2c_gate_ctrl(fe, 1);
++ if (dvb_attach(isl6405_attach, fe,
++ &dev->i2c_adap, 0x08, 0, 0) == NULL)
++ wprintk("%s: Medion Quadro, no ISL6405 "
++ "found !\n", __func__);
++ if (dev_id == 0x07) {
++ /* fire up the 2nd section of the LNB supply since
++ we can't do this from the other section */
++ msg.buf = &data;
++ i2c_transfer(&dev->i2c_adap, &msg, 1);
++ }
++ fe->ops.i2c_gate_ctrl(fe, 0);
++ dev->original_set_voltage = fe->ops.set_voltage;
++ fe->ops.set_voltage = md8800_set_voltage;
++ dev->original_set_high_voltage = fe->ops.enable_high_lnb_voltage;
++ fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage;
++ } else {
++ fe->ops.set_voltage = md8800_set_voltage2;
++ fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage2;
++ }
++ }
++ }
+ break;
+ case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180:
+ dev->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180,
+@@ -1004,8 +1126,9 @@ static int dvb_init(struct saa7134_dev *dev)
+ dev->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110,
+ &dev->i2c_adap);
+ if (dev->dvb.frontend) {
+- dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
+- NULL, DVB_PLL_TUV1236D);
++ dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++ &dev->i2c_adap, 0x61,
++ TUNER_PHILIPS_TUV1236D);
+ }
+ break;
+ case SAA7134_BOARD_FLYDVBS_LR300:
+@@ -1014,11 +1137,11 @@ static int dvb_init(struct saa7134_dev *dev)
+ if (dev->dvb.frontend) {
+ if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60,
+ &dev->i2c_adap, 0) == NULL) {
+- wprintk("%s: No tda826x found!\n", __FUNCTION__);
++ wprintk("%s: No tda826x found!\n", __func__);
+ }
+ if (dvb_attach(isl6421_attach, dev->dvb.frontend,
+ &dev->i2c_adap, 0x08, 0, 0) == NULL) {
+- wprintk("%s: No ISL6421 found!\n", __FUNCTION__);
++ wprintk("%s: No ISL6421 found!\n", __func__);
+ }
+ }
+ break;
+@@ -1030,8 +1153,9 @@ static int dvb_init(struct saa7134_dev *dev)
+ dev->original_demod_sleep = dev->dvb.frontend->ops.sleep;
+ dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
+
+- dvb_attach(dvb_pll_attach, dev->dvb.frontend, medion_cardbus.tuner_address,
+- &dev->i2c_adap, DVB_PLL_FMD1216ME);
++ dvb_attach(simple_tuner_attach, dev->dvb.frontend,
++ &dev->i2c_adap, medion_cardbus.tuner_address,
++ TUNER_PHILIPS_FMD1216ME_MK3);
+ }
+ break;
+ case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
+@@ -1044,38 +1168,107 @@ static int dvb_init(struct saa7134_dev *dev)
+ }
+ break;
+ case SAA7134_BOARD_CINERGY_HT_PCMCIA:
+- configure_tda827x_fe(dev, &cinergy_ht_config);
++ configure_tda827x_fe(dev, &cinergy_ht_config, &tda827x_cfg_0);
+ break;
+ case SAA7134_BOARD_CINERGY_HT_PCI:
+- configure_tda827x_fe(dev, &cinergy_ht_pci_config);
++ configure_tda827x_fe(dev, &cinergy_ht_pci_config, &tda827x_cfg_0);
+ break;
+ case SAA7134_BOARD_PHILIPS_TIGER_S:
+- configure_tda827x_fe(dev, &philips_tiger_s_config);
++ configure_tda827x_fe(dev, &philips_tiger_s_config, &tda827x_cfg_2);
+ break;
+ case SAA7134_BOARD_ASUS_P7131_4871:
+- configure_tda827x_fe(dev, &asus_p7131_4871_config);
++ configure_tda827x_fe(dev, &asus_p7131_4871_config, &tda827x_cfg_2);
+ break;
+ case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
+- configure_tda827x_fe(dev, &asus_p7131_hybrid_lna_config);
++ configure_tda827x_fe(dev, &asus_p7131_hybrid_lna_config, &tda827x_cfg_2);
+ break;
+ case SAA7134_BOARD_AVERMEDIA_SUPER_007:
+- configure_tda827x_fe(dev, &avermedia_super_007_config);
++ configure_tda827x_fe(dev, &avermedia_super_007_config, &tda827x_cfg_0);
+ break;
+ case SAA7134_BOARD_TWINHAN_DTV_DVB_3056:
+- configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config);
++ configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config, &tda827x_cfg_2_sw42);
++ break;
++ case SAA7134_BOARD_PHILIPS_SNAKE:
++ dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs,
++ &dev->i2c_adap);
++ if (dev->dvb.frontend) {
++ if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60,
++ &dev->i2c_adap, 0) == NULL)
++ wprintk("%s: No tda826x found!\n", __func__);
++ if (dvb_attach(lnbp21_attach, dev->dvb.frontend,
++ &dev->i2c_adap, 0, 0) == NULL)
++ wprintk("%s: No lnbp21 found!\n", __func__);
++ }
++ break;
++ case SAA7134_BOARD_CREATIX_CTX953:
++ configure_tda827x_fe(dev, &md8800_dvbt_config, &tda827x_cfg_0);
++ break;
++ case SAA7134_BOARD_MSI_TVANYWHERE_AD11:
++ configure_tda827x_fe(dev, &philips_tiger_s_config, &tda827x_cfg_2);
++ break;
++ case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
++ dev->dvb.frontend = dvb_attach(mt352_attach,
++ &avermedia_e506r_mt352_dev,
++ &dev->i2c_adap);
++ attach_xc3028 = 1;
++ break;
++ case SAA7134_BOARD_MD7134_BRIDGE_2:
++ dev->dvb.frontend = dvb_attach(tda10086_attach,
++ &sd1878_4m, &dev->i2c_adap);
++ if (dev->dvb.frontend) {
++ struct dvb_frontend *fe;
++ if (dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
++ &dev->i2c_adap, DVB_PLL_PHILIPS_SD1878_TDA8261) == NULL)
++ wprintk("%s: MD7134 DVB-S, no SD1878 "
++ "found !\n", __func__);
++ /* we need to open the i2c gate (we know it exists) */
++ fe = dev->dvb.frontend;
++ fe->ops.i2c_gate_ctrl(fe, 1);
++ if (dvb_attach(isl6405_attach, fe,
++ &dev->i2c_adap, 0x08, 0, 0) == NULL)
++ wprintk("%s: MD7134 DVB-S, no ISL6405 "
++ "found !\n", __func__);
++ fe->ops.i2c_gate_ctrl(fe, 0);
++ dev->original_set_voltage = fe->ops.set_voltage;
++ fe->ops.set_voltage = md8800_set_voltage;
++ dev->original_set_high_voltage = fe->ops.enable_high_lnb_voltage;
++ fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage;
++ }
+ break;
+ default:
+ wprintk("Huh? unknown DVB card?\n");
+ break;
+ }
+
++ if (attach_xc3028) {
++ struct dvb_frontend *fe;
++ struct xc2028_config cfg = {
++ .i2c_adap = &dev->i2c_adap,
++ .i2c_addr = 0x61,
++ };
++
++ if (!dev->dvb.frontend)
++ return -1;
++
++ fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg);
++ if (!fe) {
++ printk(KERN_ERR "%s/2: xc3028 attach failed\n",
++ dev->name);
++ dvb_frontend_detach(dev->dvb.frontend);
++ dvb_unregister_frontend(dev->dvb.frontend);
++ dev->dvb.frontend = NULL;
++ return -1;
++ }
++ }
++
+ if (NULL == dev->dvb.frontend) {
+ printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name);
+ return -1;
+ }
+
+ /* register everything else */
+- ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev);
++ ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev,
++ adapter_nr);
+
+ /* this sequence is necessary to make the tda1004x load its firmware
+ * and to enter analog mode of hybrid boards
+@@ -1106,9 +1299,22 @@ static int dvb_fini(struct saa7134_dev *dev)
+
+ /* otherwise we don't detect the tuner on next insmod */
+ saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &tda9887_cfg);
++ } else if (dev->board == SAA7134_BOARD_MEDION_MD8800_QUADRO) {
++ if ((dev->eedata[2] == 0x07) && use_frontend) {
++ /* turn off the 2nd lnb supply */
++ u8 data = 0x80;
++ struct i2c_msg msg = {.addr = 0x08, .buf = &data, .flags = 0, .len = 1};
++ struct dvb_frontend *fe;
++ fe = dev->dvb.frontend;
++ if (fe->ops.i2c_gate_ctrl) {
++ fe->ops.i2c_gate_ctrl(fe, 1);
++ i2c_transfer(&dev->i2c_adap, &msg, 1);
++ fe->ops.i2c_gate_ctrl(fe, 0);
++ }
++ }
+ }
+-
+- videobuf_dvb_unregister(&dev->dvb);
++ if (dev->dvb.frontend)
++ videobuf_dvb_unregister(&dev->dvb);
+ return 0;
+ }
+
+diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
+index 3d2ec30..1314522 100644
+--- a/drivers/media/video/saa7134/saa7134-empress.c
++++ b/drivers/media/video/saa7134/saa7134-empress.c
+@@ -40,7 +40,7 @@ static unsigned int empress_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
+ module_param_array(empress_nr, int, NULL, 0444);
+ MODULE_PARM_DESC(empress_nr,"ts device number");
+
+-static unsigned int debug = 0;
++static unsigned int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug,"enable debug messages");
+
+@@ -402,7 +402,7 @@ static int empress_init(struct saa7134_dev *dev)
+ {
+ int err;
+
+- dprintk("%s: %s\n",dev->name,__FUNCTION__);
++ dprintk("%s: %s\n",dev->name,__func__);
+ dev->empress_dev = video_device_alloc();
+ if (NULL == dev->empress_dev)
+ return -ENOMEM;
+@@ -427,8 +427,8 @@ static int empress_init(struct saa7134_dev *dev)
+ printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
+ dev->name,dev->empress_dev->minor & 0x1f);
+
+- videobuf_queue_pci_init(&dev->empress_tsq, &saa7134_ts_qops,
+- dev->pci, &dev->slock,
++ videobuf_queue_sg_init(&dev->empress_tsq, &saa7134_ts_qops,
++ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_ALTERNATE,
+ sizeof(struct saa7134_buf),
+@@ -440,7 +440,7 @@ static int empress_init(struct saa7134_dev *dev)
+
+ static int empress_fini(struct saa7134_dev *dev)
+ {
+- dprintk("%s: %s\n",dev->name,__FUNCTION__);
++ dprintk("%s: %s\n",dev->name,__func__);
+
+ if (NULL == dev->empress_dev)
+ return 0;
+diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
+index d3322c3..2ccfaba 100644
+--- a/drivers/media/video/saa7134/saa7134-i2c.c
++++ b/drivers/media/video/saa7134/saa7134-i2c.c
+@@ -33,11 +33,11 @@
+
+ /* ----------------------------------------------------------- */
+
+-static unsigned int i2c_debug = 0;
++static unsigned int i2c_debug;
+ module_param(i2c_debug, int, 0644);
+ MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]");
+
+-static unsigned int i2c_scan = 0;
++static unsigned int i2c_scan;
+ module_param(i2c_scan, int, 0444);
+ MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
+
+@@ -140,6 +140,8 @@ static inline int i2c_is_busy(enum i2c_status status)
+ {
+ switch (status) {
+ case BUSY:
++ case TO_SCL:
++ case TO_ARB:
+ return true;
+ default:
+ return false;
+diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
+index b418881..767ff30 100644
+--- a/drivers/media/video/saa7134/saa7134-input.c
++++ b/drivers/media/video/saa7134/saa7134-input.c
+@@ -27,15 +27,15 @@
+ #include "saa7134-reg.h"
+ #include "saa7134.h"
+
+-static unsigned int disable_ir = 0;
++static unsigned int disable_ir;
+ module_param(disable_ir, int, 0444);
+ MODULE_PARM_DESC(disable_ir,"disable infrared remote support");
+
+-static unsigned int ir_debug = 0;
++static unsigned int ir_debug;
+ module_param(ir_debug, int, 0644);
+ MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]");
+
+-static int pinnacle_remote = 0;
++static int pinnacle_remote;
+ module_param(pinnacle_remote, int, 0644); /* Choose Pinnacle PCTV remote */
+ MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)");
+
+@@ -331,6 +331,11 @@ int saa7134_input_init1(struct saa7134_dev *dev)
+ break;
+ case SAA7134_BOARD_MANLI_MTV001:
+ case SAA7134_BOARD_MANLI_MTV002:
++ ir_codes = ir_codes_manli;
++ mask_keycode = 0x001f00;
++ mask_keyup = 0x004000;
++ polling = 50; /* ms */
++ break;
+ case SAA7134_BOARD_BEHOLD_409FM:
+ case SAA7134_BOARD_BEHOLD_401:
+ case SAA7134_BOARD_BEHOLD_403:
+@@ -343,7 +348,13 @@ int saa7134_input_init1(struct saa7134_dev *dev)
+ case SAA7134_BOARD_BEHOLD_505FM:
+ case SAA7134_BOARD_BEHOLD_507_9FM:
+ ir_codes = ir_codes_manli;
+- mask_keycode = 0x001f00;
++ mask_keycode = 0x003f00;
++ mask_keyup = 0x004000;
++ polling = 50; /* ms */
++ break;
++ case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
++ ir_codes = ir_codes_behold_columbus;
++ mask_keycode = 0x003f00;
+ mask_keyup = 0x004000;
+ polling = 50; // ms
+ break;
+diff --git a/drivers/media/video/saa7134/saa7134-reg.h b/drivers/media/video/saa7134/saa7134-reg.h
+index ac6431b..86f5eef 100644
+--- a/drivers/media/video/saa7134/saa7134-reg.h
++++ b/drivers/media/video/saa7134/saa7134-reg.h
+@@ -365,6 +365,9 @@
+ #define SAA7135_DSP_RWSTATE_RDB (1 << 1)
+ #define SAA7135_DSP_RWSTATE_WRR (1 << 0)
+
++#define SAA7135_DSP_RWCLEAR 0x586
++#define SAA7135_DSP_RWCLEAR_RERR 1
++
+ /* ------------------------------------------------------------------ */
+ /*
+ * Local variables:
+diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c
+index f1b8fca..eae72fd 100644
+--- a/drivers/media/video/saa7134/saa7134-ts.c
++++ b/drivers/media/video/saa7134/saa7134-ts.c
+@@ -32,7 +32,7 @@
+
+ /* ------------------------------------------------------------------ */
+
+-static unsigned int ts_debug = 0;
++static unsigned int ts_debug;
+ module_param(ts_debug, int, 0644);
+ MODULE_PARM_DESC(ts_debug,"enable debug messages [ts]");
+
+diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
+index 4e98104..232af59 100644
+--- a/drivers/media/video/saa7134/saa7134-tvaudio.c
++++ b/drivers/media/video/saa7134/saa7134-tvaudio.c
+@@ -35,18 +35,18 @@
+
+ /* ------------------------------------------------------------------ */
+
+-static unsigned int audio_debug = 0;
++static unsigned int audio_debug;
+ module_param(audio_debug, int, 0644);
+ MODULE_PARM_DESC(audio_debug,"enable debug messages [tv audio]");
+
+-static unsigned int audio_ddep = 0;
++static unsigned int audio_ddep;
+ module_param(audio_ddep, int, 0644);
+ MODULE_PARM_DESC(audio_ddep,"audio ddep overwrite");
+
+ static int audio_clock_override = UNSET;
+ module_param(audio_clock_override, int, 0644);
+
+-static int audio_clock_tweak = 0;
++static int audio_clock_tweak;
+ module_param(audio_clock_tweak, int, 0644);
+ MODULE_PARM_DESC(audio_clock_tweak, "Audio clock tick fine tuning for cards with audio crystal that's slightly off (range [-1024 .. 1024])");
+
+@@ -653,6 +653,17 @@ static char *stdres[0x20] = {
+
+ #define DSP_RETRY 32
+ #define DSP_DELAY 16
++#define SAA7135_DSP_RWCLEAR_RERR 1
++
++static inline int saa_dsp_reset_error_bit(struct saa7134_dev *dev)
++{
++ int state = saa_readb(SAA7135_DSP_RWSTATE);
++ if (unlikely(state & SAA7135_DSP_RWSTATE_ERR)) {
++ d2printk("%s: resetting error bit\n", dev->name);
++ saa_writeb(SAA7135_DSP_RWCLEAR, SAA7135_DSP_RWCLEAR_RERR);
++ }
++ return 0;
++}
+
+ static inline int saa_dsp_wait_bit(struct saa7134_dev *dev, int bit)
+ {
+@@ -660,8 +671,8 @@ static inline int saa_dsp_wait_bit(struct saa7134_dev *dev, int bit)
+
+ state = saa_readb(SAA7135_DSP_RWSTATE);
+ if (unlikely(state & SAA7135_DSP_RWSTATE_ERR)) {
+- printk("%s: dsp access error\n",dev->name);
+- /* FIXME: send ack ... */
++ printk(KERN_WARNING "%s: dsp access error\n", dev->name);
++ saa_dsp_reset_error_bit(dev);
+ return -EIO;
+ }
+ while (0 == (state & bit)) {
+diff --git a/drivers/media/video/saa7134/saa7134-vbi.c b/drivers/media/video/saa7134/saa7134-vbi.c
+index f0d5ed9..cb03042 100644
+--- a/drivers/media/video/saa7134/saa7134-vbi.c
++++ b/drivers/media/video/saa7134/saa7134-vbi.c
+@@ -31,7 +31,7 @@
+
+ /* ------------------------------------------------------------------ */
+
+-static unsigned int vbi_debug = 0;
++static unsigned int vbi_debug;
+ module_param(vbi_debug, int, 0644);
+ MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");
+
+diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
+index 39c41ad..a0baf2d 100644
+--- a/drivers/media/video/saa7134/saa7134-video.c
++++ b/drivers/media/video/saa7134/saa7134-video.c
+@@ -40,7 +40,7 @@
+
+ unsigned int video_debug;
+ static unsigned int gbuffers = 8;
+-static unsigned int noninterlaced = 0;
++static unsigned int noninterlaced; /* 0 */
+ static unsigned int gbufsize = 720*576*4;
+ static unsigned int gbufsize_max = 720*576*4;
+ static char secam[] = "--";
+@@ -626,13 +626,8 @@ void saa7134_set_tvnorm_hw(struct saa7134_dev *dev)
+ {
+ saa7134_set_decoder(dev);
+
+- if (card_in(dev, dev->ctl_input).tv) {
+- if ((card(dev).tuner_type == TUNER_PHILIPS_TDA8290)
+- && ((card(dev).tuner_config == 1)
+- || (card(dev).tuner_config == 2)))
+- saa7134_set_gpio(dev, 22, 5);
++ if (card_in(dev, dev->ctl_input).tv)
+ saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id);
+- }
+ }
+
+ static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale)
+@@ -1350,14 +1345,14 @@ static int video_open(struct inode *inode, struct file *file)
+ fh->height = 576;
+ v4l2_prio_open(&dev->prio,&fh->prio);
+
+- videobuf_queue_pci_init(&fh->cap, &video_qops,
+- dev->pci, &dev->slock,
++ videobuf_queue_sg_init(&fh->cap, &video_qops,
++ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct saa7134_buf),
+ fh);
+- videobuf_queue_pci_init(&fh->vbi, &saa7134_vbi_qops,
+- dev->pci, &dev->slock,
++ videobuf_queue_sg_init(&fh->vbi, &saa7134_vbi_qops,
++ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VBI_CAPTURE,
+ V4L2_FIELD_SEQ_TB,
+ sizeof(struct saa7134_buf),
+diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
+index f940d02..924ffd1 100644
+--- a/drivers/media/video/saa7134/saa7134.h
++++ b/drivers/media/video/saa7134/saa7134.h
+@@ -253,7 +253,17 @@ struct saa7134_format {
+ #define SAA7134_BOARD_BEHOLD_607_9FM 129
+ #define SAA7134_BOARD_BEHOLD_M6 130
+ #define SAA7134_BOARD_TWINHAN_DTV_DVB_3056 131
+-#define SAA7134_BOARD_GENIUS_TVGO_A11MCE 132
++#define SAA7134_BOARD_GENIUS_TVGO_A11MCE 132
++#define SAA7134_BOARD_PHILIPS_SNAKE 133
++#define SAA7134_BOARD_CREATIX_CTX953 134
++#define SAA7134_BOARD_MSI_TVANYWHERE_AD11 135
++#define SAA7134_BOARD_AVERMEDIA_CARDBUS_506 136
++#define SAA7134_BOARD_AVERMEDIA_A16D 137
++#define SAA7134_BOARD_AVERMEDIA_M115 138
++#define SAA7134_BOARD_VIDEOMATE_T750 139
++#define SAA7134_BOARD_AVERMEDIA_A700_PRO 140
++#define SAA7134_BOARD_AVERMEDIA_A700_HYBRID 141
++
+
+ #define SAA7134_MAXBOARDS 8
+ #define SAA7134_INPUT_MAX 8
+@@ -380,9 +390,7 @@ struct saa7134_fh {
+ unsigned int radio;
+ enum v4l2_buf_type type;
+ unsigned int resources;
+-#ifdef VIDIOC_G_PRIORITY
+ enum v4l2_priority prio;
+-#endif
+
+ /* video overlay */
+ struct v4l2_window win;
+@@ -454,9 +462,7 @@ struct saa7134_dev {
+ struct list_head devlist;
+ struct mutex lock;
+ spinlock_t slock;
+-#ifdef VIDIOC_G_PRIORITY
+ struct v4l2_prio_state prio;
+-#endif
+ /* workstruct for loading modules */
+ struct work_struct request_module_wk;
+
+@@ -556,7 +562,9 @@ struct saa7134_dev {
+ #if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE)
+ /* SAA7134_MPEG_DVB only */
+ struct videobuf_dvb dvb;
+- int (*original_demod_sleep)(struct dvb_frontend* fe);
++ int (*original_demod_sleep)(struct dvb_frontend *fe);
++ int (*original_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
++ int (*original_set_high_voltage)(struct dvb_frontend *fe, long arg);
+ #endif
+ };
+
+@@ -594,7 +602,6 @@ extern int saa7134_no_overlay;
+
+ void saa7134_track_gpio(struct saa7134_dev *dev, char *msg);
+ void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value);
+-int saa7134_tuner_callback(void *ptr, int command, int arg);
+
+ #define SAA7134_PGTABLE_SIZE 4096
+
+@@ -631,6 +638,7 @@ extern struct pci_device_id __devinitdata saa7134_pci_tbl[];
+
+ extern int saa7134_board_init1(struct saa7134_dev *dev);
+ extern int saa7134_board_init2(struct saa7134_dev *dev);
++int saa7134_tuner_callback(void *priv, int command, int arg);
+
+
+ /* ----------------------------------------------------------- */
+diff --git a/drivers/media/video/saa717x.c b/drivers/media/video/saa717x.c
+new file mode 100644
+index 0000000..53c5edb
+--- /dev/null
++++ b/drivers/media/video/saa717x.c
+@@ -0,0 +1,1516 @@
++/*
++ * saa717x - Philips SAA717xHL video decoder driver
++ *
++ * Based on the saa7115 driver
++ *
++ * Changes by Ohta Kyuma <alpha292 at bremen.or.jp>
++ * - Apply to SAA717x,NEC uPD64031,uPD64083. (1/31/2004)
++ *
++ * Changes by T.Adachi (tadachi at tadachi-net.com)
++ * - support audio, video scaler etc, and checked the initialize sequence.
++ *
++ * Cleaned up by Hans Verkuil <hverkuil at xs4all.nl>
++ *
++ * Note: this is a reversed engineered driver based on captures from
++ * the I2C bus under Windows. This chip is very similar to the saa7134,
++ * though. Unfortunately, this driver is currently only working for NTSC.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++
++#include <linux/videodev.h>
++#include <linux/videodev2.h>
++#include <linux/i2c.h>
++#include <media/v4l2-common.h>
++#include <media/v4l2-i2c-drv.h>
++
++MODULE_DESCRIPTION("Philips SAA717x audio/video decoder driver");
++MODULE_AUTHOR("K. Ohta, T. Adachi, Hans Verkuil");
++MODULE_LICENSE("GPL");
++
++static int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "Debug level (0-1)");
++
++/*
++ * Generic i2c probe
++ * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
++ */
++
++struct saa717x_state {
++ v4l2_std_id std;
++ int input;
++ int enable;
++ int radio;
++ int bright;
++ int contrast;
++ int hue;
++ int sat;
++ int playback;
++ int audio;
++ int tuner_audio_mode;
++ int audio_main_mute;
++ int audio_main_vol_r;
++ int audio_main_vol_l;
++ u16 audio_main_bass;
++ u16 audio_main_treble;
++ u16 audio_main_volume;
++ u16 audio_main_balance;
++ int audio_input;
++};
++
++/* ----------------------------------------------------------------------- */
++
++/* for audio mode */
++#define TUNER_AUDIO_MONO 0 /* LL */
++#define TUNER_AUDIO_STEREO 1 /* LR */
++#define TUNER_AUDIO_LANG1 2 /* LL */
++#define TUNER_AUDIO_LANG2 3 /* RR */
++
++#define SAA717X_NTSC_WIDTH (704)
++#define SAA717X_NTSC_HEIGHT (480)
++
++/* ----------------------------------------------------------------------- */
++
++static int saa717x_write(struct i2c_client *client, u32 reg, u32 value)
++{
++ struct i2c_adapter *adap = client->adapter;
++ int fw_addr = reg == 0x454 || (reg >= 0x464 && reg <= 0x478) || reg == 0x480 || reg == 0x488;
++ unsigned char mm1[6];
++ struct i2c_msg msg;
++
++ msg.flags = 0;
++ msg.addr = client->addr;
++ mm1[0] = (reg >> 8) & 0xff;
++ mm1[1] = reg & 0xff;
++
++ if (fw_addr) {
++ mm1[4] = (value >> 16) & 0xff;
++ mm1[3] = (value >> 8) & 0xff;
++ mm1[2] = value & 0xff;
++ } else {
++ mm1[2] = value & 0xff;
++ }
++ msg.len = fw_addr ? 5 : 3; /* Long Registers have *only* three bytes! */
++ msg.buf = mm1;
++ v4l_dbg(2, debug, client, "wrote: reg 0x%03x=%08x\n", reg, value);
++ return i2c_transfer(adap, &msg, 1) == 1;
++}
++
++static void saa717x_write_regs(struct i2c_client *client, u32 *data)
++{
++ while (data[0] || data[1]) {
++ saa717x_write(client, data[0], data[1]);
++ data += 2;
++ }
++}
++
++static u32 saa717x_read(struct i2c_client *client, u32 reg)
++{
++ struct i2c_adapter *adap = client->adapter;
++ int fw_addr = (reg >= 0x404 && reg <= 0x4b8) || reg == 0x528;
++ unsigned char mm1[2];
++ unsigned char mm2[4] = { 0, 0, 0, 0 };
++ struct i2c_msg msgs[2];
++ u32 value;
++
++ msgs[0].flags = 0;
++ msgs[1].flags = I2C_M_RD;
++ msgs[0].addr = msgs[1].addr = client->addr;
++ mm1[0] = (reg >> 8) & 0xff;
++ mm1[1] = reg & 0xff;
++ msgs[0].len = 2;
++ msgs[0].buf = mm1;
++ msgs[1].len = fw_addr ? 3 : 1; /* Multibyte Registers contains *only* 3 bytes */
++ msgs[1].buf = mm2;
++ i2c_transfer(adap, msgs, 2);
++
++ if (fw_addr)
++ value = (mm2[2] & 0xff) | ((mm2[1] & 0xff) >> 8) | ((mm2[0] & 0xff) >> 16);
++ else
++ value = mm2[0] & 0xff;
++
++ v4l_dbg(2, debug, client, "read: reg 0x%03x=0x%08x\n", reg, value);
++ return value;
++}
++
++/* ----------------------------------------------------------------------- */
++
++static u32 reg_init_initialize[] =
++{
++ /* from linux driver */
++ 0x101, 0x008, /* Increment delay */
++
++ 0x103, 0x000, /* Analog input control 2 */
++ 0x104, 0x090, /* Analog input control 3 */
++ 0x105, 0x090, /* Analog input control 4 */
++ 0x106, 0x0eb, /* Horizontal sync start */
++ 0x107, 0x0e0, /* Horizontal sync stop */
++ 0x109, 0x055, /* Luminance control */
++
++ 0x10f, 0x02a, /* Chroma gain control */
++ 0x110, 0x000, /* Chroma control 2 */
++
++ 0x114, 0x045, /* analog/ADC */
++
++ 0x118, 0x040, /* RAW data gain */
++ 0x119, 0x080, /* RAW data offset */
++
++ 0x044, 0x000, /* VBI horizontal input window start (L) TASK A */
++ 0x045, 0x000, /* VBI horizontal input window start (H) TASK A */
++ 0x046, 0x0cf, /* VBI horizontal input window stop (L) TASK A */
++ 0x047, 0x002, /* VBI horizontal input window stop (H) TASK A */
++
++ 0x049, 0x000, /* VBI vertical input window start (H) TASK A */
++
++ 0x04c, 0x0d0, /* VBI horizontal output length (L) TASK A */
++ 0x04d, 0x002, /* VBI horizontal output length (H) TASK A */
++
++ 0x064, 0x080, /* Lumina brightness TASK A */
++ 0x065, 0x040, /* Luminance contrast TASK A */
++ 0x066, 0x040, /* Chroma saturation TASK A */
++ /* 067H: Reserved */
++ 0x068, 0x000, /* VBI horizontal scaling increment (L) TASK A */
++ 0x069, 0x004, /* VBI horizontal scaling increment (H) TASK A */
++ 0x06a, 0x000, /* VBI phase offset TASK A */
++
++ 0x06e, 0x000, /* Horizontal phase offset Luma TASK A */
++ 0x06f, 0x000, /* Horizontal phase offset Chroma TASK A */
++
++ 0x072, 0x000, /* Vertical filter mode TASK A */
++
++ 0x084, 0x000, /* VBI horizontal input window start (L) TAKS B */
++ 0x085, 0x000, /* VBI horizontal input window start (H) TAKS B */
++ 0x086, 0x0cf, /* VBI horizontal input window stop (L) TAKS B */
++ 0x087, 0x002, /* VBI horizontal input window stop (H) TAKS B */
++
++ 0x089, 0x000, /* VBI vertical input window start (H) TAKS B */
++
++ 0x08c, 0x0d0, /* VBI horizontal output length (L) TASK B */
++ 0x08d, 0x002, /* VBI horizontal output length (H) TASK B */
++
++ 0x0a4, 0x080, /* Lumina brightness TASK B */
++ 0x0a5, 0x040, /* Luminance contrast TASK B */
++ 0x0a6, 0x040, /* Chroma saturation TASK B */
++ /* 0A7H reserved */
++ 0x0a8, 0x000, /* VBI horizontal scaling increment (L) TASK B */
++ 0x0a9, 0x004, /* VBI horizontal scaling increment (H) TASK B */
++ 0x0aa, 0x000, /* VBI phase offset TASK B */
++
++ 0x0ae, 0x000, /* Horizontal phase offset Luma TASK B */
++ 0x0af, 0x000, /*Horizontal phase offset Chroma TASK B */
++
++ 0x0b2, 0x000, /* Vertical filter mode TASK B */
++
++ 0x00c, 0x000, /* Start point GREEN path */
++ 0x00d, 0x000, /* Start point BLUE path */
++ 0x00e, 0x000, /* Start point RED path */
++
++ 0x010, 0x010, /* GREEN path gamma curve --- */
++ 0x011, 0x020,
++ 0x012, 0x030,
++ 0x013, 0x040,
++ 0x014, 0x050,
++ 0x015, 0x060,
++ 0x016, 0x070,
++ 0x017, 0x080,
++ 0x018, 0x090,
++ 0x019, 0x0a0,
++ 0x01a, 0x0b0,
++ 0x01b, 0x0c0,
++ 0x01c, 0x0d0,
++ 0x01d, 0x0e0,
++ 0x01e, 0x0f0,
++ 0x01f, 0x0ff, /* --- GREEN path gamma curve */
++
++ 0x020, 0x010, /* BLUE path gamma curve --- */
++ 0x021, 0x020,
++ 0x022, 0x030,
++ 0x023, 0x040,
++ 0x024, 0x050,
++ 0x025, 0x060,
++ 0x026, 0x070,
++ 0x027, 0x080,
++ 0x028, 0x090,
++ 0x029, 0x0a0,
++ 0x02a, 0x0b0,
++ 0x02b, 0x0c0,
++ 0x02c, 0x0d0,
++ 0x02d, 0x0e0,
++ 0x02e, 0x0f0,
++ 0x02f, 0x0ff, /* --- BLUE path gamma curve */
++
++ 0x030, 0x010, /* RED path gamma curve --- */
++ 0x031, 0x020,
++ 0x032, 0x030,
++ 0x033, 0x040,
++ 0x034, 0x050,
++ 0x035, 0x060,
++ 0x036, 0x070,
++ 0x037, 0x080,
++ 0x038, 0x090,
++ 0x039, 0x0a0,
++ 0x03a, 0x0b0,
++ 0x03b, 0x0c0,
++ 0x03c, 0x0d0,
++ 0x03d, 0x0e0,
++ 0x03e, 0x0f0,
++ 0x03f, 0x0ff, /* --- RED path gamma curve */
++
++ 0x109, 0x085, /* Luminance control */
++
++ /**** from app start ****/
++ 0x584, 0x000, /* AGC gain control */
++ 0x585, 0x000, /* Program count */
++ 0x586, 0x003, /* Status reset */
++ 0x588, 0x0ff, /* Number of audio samples (L) */
++ 0x589, 0x00f, /* Number of audio samples (M) */
++ 0x58a, 0x000, /* Number of audio samples (H) */
++ 0x58b, 0x000, /* Audio select */
++ 0x58c, 0x010, /* Audio channel assign1 */
++ 0x58d, 0x032, /* Audio channel assign2 */
++ 0x58e, 0x054, /* Audio channel assign3 */
++ 0x58f, 0x023, /* Audio format */
++ 0x590, 0x000, /* SIF control */
++
++ 0x595, 0x000, /* ?? */
++ 0x596, 0x000, /* ?? */
++ 0x597, 0x000, /* ?? */
++
++ 0x464, 0x00, /* Digital input crossbar1 */
++
++ 0x46c, 0xbbbb10, /* Digital output selection1-3 */
++ 0x470, 0x101010, /* Digital output selection4-6 */
++
++ 0x478, 0x00, /* Sound feature control */
++
++ 0x474, 0x18, /* Softmute control */
++
++ 0x454, 0x0425b9, /* Sound Easy programming(reset) */
++ 0x454, 0x042539, /* Sound Easy programming(reset) */
++
++
++ /**** common setting( of DVD play, including scaler commands) ****/
++ 0x042, 0x003, /* Data path configuration for VBI (TASK A) */
++
++ 0x082, 0x003, /* Data path configuration for VBI (TASK B) */
++
++ 0x108, 0x0f8, /* Sync control */
++ 0x2a9, 0x0fd, /* ??? */
++ 0x102, 0x089, /* select video input "mode 9" */
++ 0x111, 0x000, /* Mode/delay control */
++
++ 0x10e, 0x00a, /* Chroma control 1 */
++
++ 0x594, 0x002, /* SIF, analog I/O select */
++
++ 0x454, 0x0425b9, /* Sound */
++ 0x454, 0x042539,
++
++ 0x111, 0x000,
++ 0x10e, 0x00a,
++ 0x464, 0x000,
++ 0x300, 0x000,
++ 0x301, 0x006,
++ 0x302, 0x000,
++ 0x303, 0x006,
++ 0x308, 0x040,
++ 0x309, 0x000,
++ 0x30a, 0x000,
++ 0x30b, 0x000,
++ 0x000, 0x002,
++ 0x001, 0x000,
++ 0x002, 0x000,
++ 0x003, 0x000,
++ 0x004, 0x033,
++ 0x040, 0x01d,
++ 0x041, 0x001,
++ 0x042, 0x004,
++ 0x043, 0x000,
++ 0x080, 0x01e,
++ 0x081, 0x001,
++ 0x082, 0x004,
++ 0x083, 0x000,
++ 0x190, 0x018,
++ 0x115, 0x000,
++ 0x116, 0x012,
++ 0x117, 0x018,
++ 0x04a, 0x011,
++ 0x08a, 0x011,
++ 0x04b, 0x000,
++ 0x08b, 0x000,
++ 0x048, 0x000,
++ 0x088, 0x000,
++ 0x04e, 0x012,
++ 0x08e, 0x012,
++ 0x058, 0x012,
++ 0x098, 0x012,
++ 0x059, 0x000,
++ 0x099, 0x000,
++ 0x05a, 0x003,
++ 0x09a, 0x003,
++ 0x05b, 0x001,
++ 0x09b, 0x001,
++ 0x054, 0x008,
++ 0x094, 0x008,
++ 0x055, 0x000,
++ 0x095, 0x000,
++ 0x056, 0x0c7,
++ 0x096, 0x0c7,
++ 0x057, 0x002,
++ 0x097, 0x002,
++ 0x0ff, 0x0ff,
++ 0x060, 0x001,
++ 0x0a0, 0x001,
++ 0x061, 0x000,
++ 0x0a1, 0x000,
++ 0x062, 0x000,
++ 0x0a2, 0x000,
++ 0x063, 0x000,
++ 0x0a3, 0x000,
++ 0x070, 0x000,
++ 0x0b0, 0x000,
++ 0x071, 0x004,
++ 0x0b1, 0x004,
++ 0x06c, 0x0e9,
++ 0x0ac, 0x0e9,
++ 0x06d, 0x003,
++ 0x0ad, 0x003,
++ 0x05c, 0x0d0,
++ 0x09c, 0x0d0,
++ 0x05d, 0x002,
++ 0x09d, 0x002,
++ 0x05e, 0x0f2,
++ 0x09e, 0x0f2,
++ 0x05f, 0x000,
++ 0x09f, 0x000,
++ 0x074, 0x000,
++ 0x0b4, 0x000,
++ 0x075, 0x000,
++ 0x0b5, 0x000,
++ 0x076, 0x000,
++ 0x0b6, 0x000,
++ 0x077, 0x000,
++ 0x0b7, 0x000,
++ 0x195, 0x008,
++ 0x0ff, 0x0ff,
++ 0x108, 0x0f8,
++ 0x111, 0x000,
++ 0x10e, 0x00a,
++ 0x2a9, 0x0fd,
++ 0x464, 0x001,
++ 0x454, 0x042135,
++ 0x598, 0x0e7,
++ 0x599, 0x07d,
++ 0x59a, 0x018,
++ 0x59c, 0x066,
++ 0x59d, 0x090,
++ 0x59e, 0x001,
++ 0x584, 0x000,
++ 0x585, 0x000,
++ 0x586, 0x003,
++ 0x588, 0x0ff,
++ 0x589, 0x00f,
++ 0x58a, 0x000,
++ 0x58b, 0x000,
++ 0x58c, 0x010,
++ 0x58d, 0x032,
++ 0x58e, 0x054,
++ 0x58f, 0x023,
++ 0x590, 0x000,
++ 0x595, 0x000,
++ 0x596, 0x000,
++ 0x597, 0x000,
++ 0x464, 0x000,
++ 0x46c, 0xbbbb10,
++ 0x470, 0x101010,
++
++
++ 0x478, 0x000,
++ 0x474, 0x018,
++ 0x454, 0x042135,
++ 0x598, 0x0e7,
++ 0x599, 0x07d,
++ 0x59a, 0x018,
++ 0x59c, 0x066,
++ 0x59d, 0x090,
++ 0x59e, 0x001,
++ 0x584, 0x000,
++ 0x585, 0x000,
++ 0x586, 0x003,
++ 0x588, 0x0ff,
++ 0x589, 0x00f,
++ 0x58a, 0x000,
++ 0x58b, 0x000,
++ 0x58c, 0x010,
++ 0x58d, 0x032,
++ 0x58e, 0x054,
++ 0x58f, 0x023,
++ 0x590, 0x000,
++ 0x595, 0x000,
++ 0x596, 0x000,
++ 0x597, 0x000,
++ 0x464, 0x000,
++ 0x46c, 0xbbbb10,
++ 0x470, 0x101010,
++
++ 0x478, 0x000,
++ 0x474, 0x018,
++ 0x454, 0x042135,
++ 0x598, 0x0e7,
++ 0x599, 0x07d,
++ 0x59a, 0x018,
++ 0x59c, 0x066,
++ 0x59d, 0x090,
++ 0x59e, 0x001,
++ 0x584, 0x000,
++ 0x585, 0x000,
++ 0x586, 0x003,
++ 0x588, 0x0ff,
++ 0x589, 0x00f,
++ 0x58a, 0x000,
++ 0x58b, 0x000,
++ 0x58c, 0x010,
++ 0x58d, 0x032,
++ 0x58e, 0x054,
++ 0x58f, 0x023,
++ 0x590, 0x000,
++ 0x595, 0x000,
++ 0x596, 0x000,
++ 0x597, 0x000,
++ 0x464, 0x000,
++ 0x46c, 0xbbbb10,
++ 0x470, 0x101010,
++ 0x478, 0x000,
++ 0x474, 0x018,
++ 0x454, 0x042135,
++ 0x193, 0x000,
++ 0x300, 0x000,
++ 0x301, 0x006,
++ 0x302, 0x000,
++ 0x303, 0x006,
++ 0x308, 0x040,
++ 0x309, 0x000,
++ 0x30a, 0x000,
++ 0x30b, 0x000,
++ 0x000, 0x002,
++ 0x001, 0x000,
++ 0x002, 0x000,
++ 0x003, 0x000,
++ 0x004, 0x033,
++ 0x040, 0x01d,
++ 0x041, 0x001,
++ 0x042, 0x004,
++ 0x043, 0x000,
++ 0x080, 0x01e,
++ 0x081, 0x001,
++ 0x082, 0x004,
++ 0x083, 0x000,
++ 0x190, 0x018,
++ 0x115, 0x000,
++ 0x116, 0x012,
++ 0x117, 0x018,
++ 0x04a, 0x011,
++ 0x08a, 0x011,
++ 0x04b, 0x000,
++ 0x08b, 0x000,
++ 0x048, 0x000,
++ 0x088, 0x000,
++ 0x04e, 0x012,
++ 0x08e, 0x012,
++ 0x058, 0x012,
++ 0x098, 0x012,
++ 0x059, 0x000,
++ 0x099, 0x000,
++ 0x05a, 0x003,
++ 0x09a, 0x003,
++ 0x05b, 0x001,
++ 0x09b, 0x001,
++ 0x054, 0x008,
++ 0x094, 0x008,
++ 0x055, 0x000,
++ 0x095, 0x000,
++ 0x056, 0x0c7,
++ 0x096, 0x0c7,
++ 0x057, 0x002,
++ 0x097, 0x002,
++ 0x060, 0x001,
++ 0x0a0, 0x001,
++ 0x061, 0x000,
++ 0x0a1, 0x000,
++ 0x062, 0x000,
++ 0x0a2, 0x000,
++ 0x063, 0x000,
++ 0x0a3, 0x000,
++ 0x070, 0x000,
++ 0x0b0, 0x000,
++ 0x071, 0x004,
++ 0x0b1, 0x004,
++ 0x06c, 0x0e9,
++ 0x0ac, 0x0e9,
++ 0x06d, 0x003,
++ 0x0ad, 0x003,
++ 0x05c, 0x0d0,
++ 0x09c, 0x0d0,
++ 0x05d, 0x002,
++ 0x09d, 0x002,
++ 0x05e, 0x0f2,
++ 0x09e, 0x0f2,
++ 0x05f, 0x000,
++ 0x09f, 0x000,
++ 0x074, 0x000,
++ 0x0b4, 0x000,
++ 0x075, 0x000,
++ 0x0b5, 0x000,
++ 0x076, 0x000,
++ 0x0b6, 0x000,
++ 0x077, 0x000,
++ 0x0b7, 0x000,
++ 0x195, 0x008,
++ 0x598, 0x0e7,
++ 0x599, 0x07d,
++ 0x59a, 0x018,
++ 0x59c, 0x066,
++ 0x59d, 0x090,
++ 0x59e, 0x001,
++ 0x584, 0x000,
++ 0x585, 0x000,
++ 0x586, 0x003,
++ 0x588, 0x0ff,
++ 0x589, 0x00f,
++ 0x58a, 0x000,
++ 0x58b, 0x000,
++ 0x58c, 0x010,
++ 0x58d, 0x032,
++ 0x58e, 0x054,
++ 0x58f, 0x023,
++ 0x590, 0x000,
++ 0x595, 0x000,
++ 0x596, 0x000,
++ 0x597, 0x000,
++ 0x464, 0x000,
++ 0x46c, 0xbbbb10,
++ 0x470, 0x101010,
++ 0x478, 0x000,
++ 0x474, 0x018,
++ 0x454, 0x042135,
++ 0x193, 0x0a6,
++ 0x108, 0x0f8,
++ 0x042, 0x003,
++ 0x082, 0x003,
++ 0x454, 0x0425b9,
++ 0x454, 0x042539,
++ 0x193, 0x000,
++ 0x193, 0x0a6,
++ 0x464, 0x000,
++
++ 0, 0
++};
++
++/* Tuner */
++static u32 reg_init_tuner_input[] = {
++ 0x108, 0x0f8, /* Sync control */
++ 0x111, 0x000, /* Mode/delay control */
++ 0x10e, 0x00a, /* Chroma control 1 */
++ 0, 0
++};
++
++/* Composite */
++static u32 reg_init_composite_input[] = {
++ 0x108, 0x0e8, /* Sync control */
++ 0x111, 0x000, /* Mode/delay control */
++ 0x10e, 0x04a, /* Chroma control 1 */
++ 0, 0
++};
++
++/* S-Video */
++static u32 reg_init_svideo_input[] = {
++ 0x108, 0x0e8, /* Sync control */
++ 0x111, 0x000, /* Mode/delay control */
++ 0x10e, 0x04a, /* Chroma control 1 */
++ 0, 0
++};
++
++static u32 reg_set_audio_template[4][2] =
++{
++ { /* for MONO
++ tadachi 6/29 DMA audio output select?
++ Register 0x46c
++ 7-4: DMA2, 3-0: DMA1 ch. DMA4, DMA3 DMA2, DMA1
++ 0: MAIN left, 1: MAIN right
++ 2: AUX1 left, 3: AUX1 right
++ 4: AUX2 left, 5: AUX2 right
++ 6: DPL left, 7: DPL right
++ 8: DPL center, 9: DPL surround
++ A: monitor output, B: digital sense */
++ 0xbbbb00,
++
++ /* tadachi 6/29 DAC and I2S output select?
++ Register 0x470
++ 7-4:DAC right ch. 3-0:DAC left ch.
++ I2S1 right,left I2S2 right,left */
++ 0x00,
++ },
++ { /* for STEREO */
++ 0xbbbb10, 0x101010,
++ },
++ { /* for LANG1 */
++ 0xbbbb00, 0x00,
++ },
++ { /* for LANG2/SAP */
++ 0xbbbb11, 0x111111,
++ }
++};
++
++
++/* Get detected audio flags (from saa7134 driver) */
++static void get_inf_dev_status(struct i2c_client *client,
++ int *dual_flag, int *stereo_flag)
++{
++ u32 reg_data3;
++
++ static char *stdres[0x20] = {
++ [0x00] = "no standard detected",
++ [0x01] = "B/G (in progress)",
++ [0x02] = "D/K (in progress)",
++ [0x03] = "M (in progress)",
++
++ [0x04] = "B/G A2",
++ [0x05] = "B/G NICAM",
++ [0x06] = "D/K A2 (1)",
++ [0x07] = "D/K A2 (2)",
++ [0x08] = "D/K A2 (3)",
++ [0x09] = "D/K NICAM",
++ [0x0a] = "L NICAM",
++ [0x0b] = "I NICAM",
++
++ [0x0c] = "M Korea",
++ [0x0d] = "M BTSC ",
++ [0x0e] = "M EIAJ",
++
++ [0x0f] = "FM radio / IF 10.7 / 50 deemp",
++ [0x10] = "FM radio / IF 10.7 / 75 deemp",
++ [0x11] = "FM radio / IF sel / 50 deemp",
++ [0x12] = "FM radio / IF sel / 75 deemp",
++
++ [0x13 ... 0x1e] = "unknown",
++ [0x1f] = "??? [in progress]",
++ };
++
++
++ *dual_flag = *stereo_flag = 0;
++
++ /* (demdec status: 0x528) */
++
++ /* read current status */
++ reg_data3 = saa717x_read(client, 0x0528);
++
++ v4l_dbg(1, debug, client, "tvaudio thread status: 0x%x [%s%s%s]\n",
++ reg_data3, stdres[reg_data3 & 0x1f],
++ (reg_data3 & 0x000020) ? ",stereo" : "",
++ (reg_data3 & 0x000040) ? ",dual" : "");
++ v4l_dbg(1, debug, client, "detailed status: "
++ "%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s\n",
++ (reg_data3 & 0x000080) ? " A2/EIAJ pilot tone " : "",
++ (reg_data3 & 0x000100) ? " A2/EIAJ dual " : "",
++ (reg_data3 & 0x000200) ? " A2/EIAJ stereo " : "",
++ (reg_data3 & 0x000400) ? " A2/EIAJ noise mute " : "",
++
++ (reg_data3 & 0x000800) ? " BTSC/FM radio pilot " : "",
++ (reg_data3 & 0x001000) ? " SAP carrier " : "",
++ (reg_data3 & 0x002000) ? " BTSC stereo noise mute " : "",
++ (reg_data3 & 0x004000) ? " SAP noise mute " : "",
++ (reg_data3 & 0x008000) ? " VDSP " : "",
++
++ (reg_data3 & 0x010000) ? " NICST " : "",
++ (reg_data3 & 0x020000) ? " NICDU " : "",
++ (reg_data3 & 0x040000) ? " NICAM muted " : "",
++ (reg_data3 & 0x080000) ? " NICAM reserve sound " : "",
++
++ (reg_data3 & 0x100000) ? " init done " : "");
++
++ if (reg_data3 & 0x000220) {
++ v4l_dbg(1, debug, client, "ST!!!\n");
++ *stereo_flag = 1;
++ }
++
++ if (reg_data3 & 0x000140) {
++ v4l_dbg(1, debug, client, "DUAL!!!\n");
++ *dual_flag = 1;
++ }
++}
++
++/* regs write to set audio mode */
++static void set_audio_mode(struct i2c_client *client, int audio_mode)
++{
++ v4l_dbg(1, debug, client, "writing registers to set audio mode by set %d\n",
++ audio_mode);
++
++ saa717x_write(client, 0x46c, reg_set_audio_template[audio_mode][0]);
++ saa717x_write(client, 0x470, reg_set_audio_template[audio_mode][1]);
++}
++
++/* write regs to video output level (bright,contrast,hue,sat) */
++static void set_video_output_level_regs(struct i2c_client *client,
++ struct saa717x_state *decoder)
++{
++ /* brightness ffh (bright) - 80h (ITU level) - 00h (dark) */
++ saa717x_write(client, 0x10a, decoder->bright);
++
++ /* contrast 7fh (max: 1.984) - 44h (ITU) - 40h (1.0) -
++ 0h (luminance off) 40: i2c dump
++ c0h (-1.0 inverse chrominance)
++ 80h (-2.0 inverse chrominance) */
++ saa717x_write(client, 0x10b, decoder->contrast);
++
++ /* saturation? 7fh(max)-40h(ITU)-0h(color off)
++ c0h (-1.0 inverse chrominance)
++ 80h (-2.0 inverse chrominance) */
++ saa717x_write(client, 0x10c, decoder->sat);
++
++ /* color hue (phase) control
++ 7fh (+178.6) - 0h (0 normal) - 80h (-180.0) */
++ saa717x_write(client, 0x10d, decoder->hue);
++}
++
++/* write regs to set audio volume, bass and treble */
++static int set_audio_regs(struct i2c_client *client,
++ struct saa717x_state *decoder)
++{
++ u8 mute = 0xac; /* -84 dB */
++ u32 val;
++ unsigned int work_l, work_r;
++
++ /* set SIF analog I/O select */
++ saa717x_write(client, 0x0594, decoder->audio_input);
++ v4l_dbg(1, debug, client, "set audio input %d\n",
++ decoder->audio_input);
++
++ /* normalize ( 65535 to 0 -> 24 to -40 (not -84)) */
++ work_l = (min(65536 - decoder->audio_main_balance, 32768) * decoder->audio_main_volume) / 32768;
++ work_r = (min(decoder->audio_main_balance, (u16)32768) * decoder->audio_main_volume) / 32768;
++ decoder->audio_main_vol_l = (long)work_l * (24 - (-40)) / 65535 - 40;
++ decoder->audio_main_vol_r = (long)work_r * (24 - (-40)) / 65535 - 40;
++
++ /* set main volume */
++ /* main volume L[7-0],R[7-0],0x00 24=24dB,-83dB, -84(mute) */
++ /* def:0dB->6dB(MPG600GR) */
++ /* if mute is on, set mute */
++ if (decoder->audio_main_mute) {
++ val = mute | (mute << 8);
++ } else {
++ val = (u8)decoder->audio_main_vol_l |
++ ((u8)decoder->audio_main_vol_r << 8);
++ }
++
++ saa717x_write(client, 0x480, val);
++
++ /* bass and treble; go to another function */
++ /* set bass and treble */
++ val = decoder->audio_main_bass | (decoder->audio_main_treble << 8);
++ saa717x_write(client, 0x488, val);
++ return 0;
++}
++
++/********** scaling staff ***********/
++static void set_h_prescale(struct i2c_client *client,
++ int task, int prescale)
++{
++ static const struct {
++ int xpsc;
++ int xacl;
++ int xc2_1;
++ int xdcg;
++ int vpfy;
++ } vals[] = {
++ /* XPSC XACL XC2_1 XDCG VPFY */
++ { 1, 0, 0, 0, 0 },
++ { 2, 2, 1, 2, 2 },
++ { 3, 4, 1, 3, 2 },
++ { 4, 8, 1, 4, 2 },
++ { 5, 8, 1, 4, 2 },
++ { 6, 8, 1, 4, 3 },
++ { 7, 8, 1, 4, 3 },
++ { 8, 15, 0, 4, 3 },
++ { 9, 15, 0, 4, 3 },
++ { 10, 16, 1, 5, 3 },
++ };
++ static const int count = ARRAY_SIZE(vals);
++ int i, task_shift;
++
++ task_shift = task * 0x40;
++ for (i = 0; i < count; i++)
++ if (vals[i].xpsc == prescale)
++ break;
++ if (i == count)
++ return;
++
++ /* horizonal prescaling */
++ saa717x_write(client, 0x60 + task_shift, vals[i].xpsc);
++ /* accumulation length */
++ saa717x_write(client, 0x61 + task_shift, vals[i].xacl);
++ /* level control */
++ saa717x_write(client, 0x62 + task_shift,
++ (vals[i].xc2_1 << 3) | vals[i].xdcg);
++ /*FIR prefilter control */
++ saa717x_write(client, 0x63 + task_shift,
++ (vals[i].vpfy << 2) | vals[i].vpfy);
++}
++
++/********** scaling staff ***********/
++static void set_v_scale(struct i2c_client *client, int task, int yscale)
++{
++ int task_shift;
++
++ task_shift = task * 0x40;
++ /* Vertical scaling ratio (LOW) */
++ saa717x_write(client, 0x70 + task_shift, yscale & 0xff);
++ /* Vertical scaling ratio (HI) */
++ saa717x_write(client, 0x71 + task_shift, yscale >> 8);
++}
++
++static int saa717x_set_audio_clock_freq(struct i2c_client *client, u32 freq)
++{
++ /* not yet implament, so saa717x_cfg_??hz_??_audio is not defined. */
++ return 0;
++}
++
++static int saa717x_set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
++{
++ struct saa717x_state *state = i2c_get_clientdata(client);
++
++ switch (ctrl->id) {
++ case V4L2_CID_BRIGHTNESS:
++ if (ctrl->value < 0 || ctrl->value > 255) {
++ v4l_err(client, "invalid brightness setting %d\n", ctrl->value);
++ return -ERANGE;
++ }
++
++ state->bright = ctrl->value;
++ v4l_dbg(1, debug, client, "bright:%d\n", state->bright);
++ saa717x_write(client, 0x10a, state->bright);
++ break;
++
++ case V4L2_CID_CONTRAST:
++ if (ctrl->value < 0 || ctrl->value > 127) {
++ v4l_err(client, "invalid contrast setting %d\n", ctrl->value);
++ return -ERANGE;
++ }
++
++ state->contrast = ctrl->value;
++ v4l_dbg(1, debug, client, "contrast:%d\n", state->contrast);
++ saa717x_write(client, 0x10b, state->contrast);
++ break;
++
++ case V4L2_CID_SATURATION:
++ if (ctrl->value < 0 || ctrl->value > 127) {
++ v4l_err(client, "invalid saturation setting %d\n", ctrl->value);
++ return -ERANGE;
++ }
++
++ state->sat = ctrl->value;
++ v4l_dbg(1, debug, client, "sat:%d\n", state->sat);
++ saa717x_write(client, 0x10c, state->sat);
++ break;
++
++ case V4L2_CID_HUE:
++ if (ctrl->value < -127 || ctrl->value > 127) {
++ v4l_err(client, "invalid hue setting %d\n", ctrl->value);
++ return -ERANGE;
++ }
++
++ state->hue = ctrl->value;
++ v4l_dbg(1, debug, client, "hue:%d\n", state->hue);
++ saa717x_write(client, 0x10d, state->hue);
++ break;
++
++ case V4L2_CID_AUDIO_MUTE:
++ state->audio_main_mute = ctrl->value;
++ set_audio_regs(client, state);
++ break;
++
++ case V4L2_CID_AUDIO_VOLUME:
++ state->audio_main_volume = ctrl->value;
++ set_audio_regs(client, state);
++ break;
++
++ case V4L2_CID_AUDIO_BALANCE:
++ state->audio_main_balance = ctrl->value;
++ set_audio_regs(client, state);
++ break;
++
++ case V4L2_CID_AUDIO_TREBLE:
++ state->audio_main_treble = ctrl->value;
++ set_audio_regs(client, state);
++ break;
++
++ case V4L2_CID_AUDIO_BASS:
++ state->audio_main_bass = ctrl->value;
++ set_audio_regs(client, state);
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static int saa717x_get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
++{
++ struct saa717x_state *state = i2c_get_clientdata(client);
++
++ switch (ctrl->id) {
++ case V4L2_CID_BRIGHTNESS:
++ ctrl->value = state->bright;
++ break;
++
++ case V4L2_CID_CONTRAST:
++ ctrl->value = state->contrast;
++ break;
++
++ case V4L2_CID_SATURATION:
++ ctrl->value = state->sat;
++ break;
++
++ case V4L2_CID_HUE:
++ ctrl->value = state->hue;
++ break;
++
++ case V4L2_CID_AUDIO_MUTE:
++ ctrl->value = state->audio_main_mute;
++ break;
++
++ case V4L2_CID_AUDIO_VOLUME:
++ ctrl->value = state->audio_main_volume;
++ break;
++
++ case V4L2_CID_AUDIO_BALANCE:
++ ctrl->value = state->audio_main_balance;
++ break;
++
++ case V4L2_CID_AUDIO_TREBLE:
++ ctrl->value = state->audio_main_treble;
++ break;
++
++ case V4L2_CID_AUDIO_BASS:
++ ctrl->value = state->audio_main_bass;
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static struct v4l2_queryctrl saa717x_qctrl[] = {
++ {
++ .id = V4L2_CID_BRIGHTNESS,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "Brightness",
++ .minimum = 0,
++ .maximum = 255,
++ .step = 1,
++ .default_value = 128,
++ .flags = 0,
++ }, {
++ .id = V4L2_CID_CONTRAST,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "Contrast",
++ .minimum = 0,
++ .maximum = 255,
++ .step = 1,
++ .default_value = 64,
++ .flags = 0,
++ }, {
++ .id = V4L2_CID_SATURATION,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "Saturation",
++ .minimum = 0,
++ .maximum = 255,
++ .step = 1,
++ .default_value = 64,
++ .flags = 0,
++ }, {
++ .id = V4L2_CID_HUE,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "Hue",
++ .minimum = -128,
++ .maximum = 127,
++ .step = 1,
++ .default_value = 0,
++ .flags = 0,
++ }, {
++ .id = V4L2_CID_AUDIO_VOLUME,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "Volume",
++ .minimum = 0,
++ .maximum = 65535,
++ .step = 65535 / 100,
++ .default_value = 58880,
++ .flags = 0,
++ }, {
++ .id = V4L2_CID_AUDIO_BALANCE,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "Balance",
++ .minimum = 0,
++ .maximum = 65535,
++ .step = 65535 / 100,
++ .default_value = 32768,
++ .flags = 0,
++ }, {
++ .id = V4L2_CID_AUDIO_MUTE,
++ .type = V4L2_CTRL_TYPE_BOOLEAN,
++ .name = "Mute",
++ .minimum = 0,
++ .maximum = 1,
++ .step = 1,
++ .default_value = 1,
++ .flags = 0,
++ }, {
++ .id = V4L2_CID_AUDIO_BASS,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "Bass",
++ .minimum = 0,
++ .maximum = 65535,
++ .step = 65535 / 100,
++ .default_value = 32768,
++ }, {
++ .id = V4L2_CID_AUDIO_TREBLE,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "Treble",
++ .minimum = 0,
++ .maximum = 65535,
++ .step = 65535 / 100,
++ .default_value = 32768,
++ },
++};
++
++static int saa717x_set_video_input(struct i2c_client *client, struct saa717x_state *decoder, int inp)
++{
++ int is_tuner = inp & 0x80; /* tuner input flag */
++
++ inp &= 0x7f;
++
++ v4l_dbg(1, debug, client, "decoder set input (%d)\n", inp);
++ /* inputs from 0-9 are available*/
++ /* saa717x have mode0-mode9 but mode5 is reserved. */
++ if (inp < 0 || inp > 9 || inp == 5)
++ return -EINVAL;
++
++ if (decoder->input != inp) {
++ int input_line = inp;
++
++ decoder->input = input_line;
++ v4l_dbg(1, debug, client, "now setting %s input %d\n",
++ input_line >= 6 ? "S-Video" : "Composite",
++ input_line);
++
++ /* select mode */
++ saa717x_write(client, 0x102,
++ (saa717x_read(client, 0x102) & 0xf0) |
++ input_line);
++
++ /* bypass chrominance trap for modes 6..9 */
++ saa717x_write(client, 0x109,
++ (saa717x_read(client, 0x109) & 0x7f) |
++ (input_line < 6 ? 0x0 : 0x80));
++
++ /* change audio_mode */
++ if (is_tuner) {
++ /* tuner */
++ set_audio_mode(client, decoder->tuner_audio_mode);
++ } else {
++ /* Force to STEREO mode if Composite or
++ * S-Video were chosen */
++ set_audio_mode(client, TUNER_AUDIO_STEREO);
++ }
++ /* change initialize procedure (Composite/S-Video) */
++ if (is_tuner)
++ saa717x_write_regs(client, reg_init_tuner_input);
++ else if (input_line >= 6)
++ saa717x_write_regs(client, reg_init_svideo_input);
++ else
++ saa717x_write_regs(client, reg_init_composite_input);
++ }
++
++ return 0;
++}
++
++static int saa717x_command(struct i2c_client *client, unsigned cmd, void *arg)
++{
++ struct saa717x_state *decoder = i2c_get_clientdata(client);
++
++ v4l_dbg(1, debug, client, "IOCTL: %08x\n", cmd);
++
++ switch (cmd) {
++ case VIDIOC_INT_AUDIO_CLOCK_FREQ:
++ return saa717x_set_audio_clock_freq(client, *(u32 *)arg);
++
++ case VIDIOC_G_CTRL:
++ return saa717x_get_v4lctrl(client, (struct v4l2_control *)arg);
++
++ case VIDIOC_S_CTRL:
++ return saa717x_set_v4lctrl(client, (struct v4l2_control *)arg);
++
++ case VIDIOC_QUERYCTRL: {
++ struct v4l2_queryctrl *qc = arg;
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(saa717x_qctrl); i++)
++ if (qc->id && qc->id == saa717x_qctrl[i].id) {
++ memcpy(qc, &saa717x_qctrl[i], sizeof(*qc));
++ return 0;
++ }
++ return -EINVAL;
++ }
++
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++ case VIDIOC_DBG_G_REGISTER: {
++ struct v4l2_register *reg = arg;
++
++ if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip))
++ return -EINVAL;
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++ reg->val = saa717x_read(client, reg->reg);
++ break;
++ }
++
++ case VIDIOC_DBG_S_REGISTER: {
++ struct v4l2_register *reg = arg;
++ u16 addr = reg->reg & 0xffff;
++ u8 val = reg->val & 0xff;
++
++ if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip))
++ return -EINVAL;
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++ saa717x_write(client, addr, val);
++ break;
++ }
++#endif
++
++ case VIDIOC_S_FMT: {
++ struct v4l2_format *fmt = (struct v4l2_format *)arg;
++ struct v4l2_pix_format *pix;
++ int prescale, h_scale, v_scale;
++
++ pix = &fmt->fmt.pix;
++ v4l_dbg(1, debug, client, "decoder set size\n");
++
++ /* FIXME need better bounds checking here */
++ if (pix->width < 1 || pix->width > 1440)
++ return -EINVAL;
++ if (pix->height < 1 || pix->height > 960)
++ return -EINVAL;
++
++ /* scaling setting */
++ /* NTSC and interlace only */
++ prescale = SAA717X_NTSC_WIDTH / pix->width;
++ if (prescale == 0)
++ prescale = 1;
++ h_scale = 1024 * SAA717X_NTSC_WIDTH / prescale / pix->width;
++ /* interlace */
++ v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / pix->height;
++
++ /* Horizontal prescaling etc */
++ set_h_prescale(client, 0, prescale);
++ set_h_prescale(client, 1, prescale);
++
++ /* Horizontal scaling increment */
++ /* TASK A */
++ saa717x_write(client, 0x6C, (u8)(h_scale & 0xFF));
++ saa717x_write(client, 0x6D, (u8)((h_scale >> 8) & 0xFF));
++ /* TASK B */
++ saa717x_write(client, 0xAC, (u8)(h_scale & 0xFF));
++ saa717x_write(client, 0xAD, (u8)((h_scale >> 8) & 0xFF));
++
++ /* Vertical prescaling etc */
++ set_v_scale(client, 0, v_scale);
++ set_v_scale(client, 1, v_scale);
++
++ /* set video output size */
++ /* video number of pixels at output */
++ /* TASK A */
++ saa717x_write(client, 0x5C, (u8)(pix->width & 0xFF));
++ saa717x_write(client, 0x5D, (u8)((pix->width >> 8) & 0xFF));
++ /* TASK B */
++ saa717x_write(client, 0x9C, (u8)(pix->width & 0xFF));
++ saa717x_write(client, 0x9D, (u8)((pix->width >> 8) & 0xFF));
++
++ /* video number of lines at output */
++ /* TASK A */
++ saa717x_write(client, 0x5E, (u8)(pix->height & 0xFF));
++ saa717x_write(client, 0x5F, (u8)((pix->height >> 8) & 0xFF));
++ /* TASK B */
++ saa717x_write(client, 0x9E, (u8)(pix->height & 0xFF));
++ saa717x_write(client, 0x9F, (u8)((pix->height >> 8) & 0xFF));
++ break;
++ }
++
++ case AUDC_SET_RADIO:
++ decoder->radio = 1;
++ break;
++
++ case VIDIOC_S_STD: {
++ v4l2_std_id std = *(v4l2_std_id *) arg;
++
++ v4l_dbg(1, debug, client, "decoder set norm ");
++ v4l_dbg(1, debug, client, "(not yet implementd)\n");
++
++ decoder->radio = 0;
++ decoder->std = std;
++ break;
++ }
++
++ case VIDIOC_INT_G_AUDIO_ROUTING: {
++ struct v4l2_routing *route = arg;
++
++ route->input = decoder->audio_input;
++ route->output = 0;
++ break;
++ }
++
++ case VIDIOC_INT_S_AUDIO_ROUTING: {
++ struct v4l2_routing *route = arg;
++
++ if (route->input < 3) { /* FIXME! --tadachi */
++ decoder->audio_input = route->input;
++ v4l_dbg(1, debug, client,
++ "set decoder audio input to %d\n",
++ decoder->audio_input);
++ set_audio_regs(client, decoder);
++ break;
++ }
++ return -ERANGE;
++ }
++
++ case VIDIOC_INT_S_VIDEO_ROUTING: {
++ struct v4l2_routing *route = arg;
++ int inp = route->input;
++
++ return saa717x_set_video_input(client, decoder, inp);
++ }
++
++ case VIDIOC_STREAMON: {
++ v4l_dbg(1, debug, client, "decoder enable output\n");
++ decoder->enable = 1;
++ saa717x_write(client, 0x193, 0xa6);
++ break;
++ }
++
++ case VIDIOC_STREAMOFF: {
++ v4l_dbg(1, debug, client, "decoder disable output\n");
++ decoder->enable = 0;
++ saa717x_write(client, 0x193, 0x26); /* right? FIXME!--tadachi */
++ break;
++ }
++
++ /* change audio mode */
++ case VIDIOC_S_TUNER: {
++ struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
++ int audio_mode;
++ char *mes[4] = {
++ "MONO", "STEREO", "LANG1", "LANG2/SAP"
++ };
++
++ audio_mode = V4L2_TUNER_MODE_STEREO;
++
++ switch (vt->audmode) {
++ case V4L2_TUNER_MODE_MONO:
++ audio_mode = TUNER_AUDIO_MONO;
++ break;
++ case V4L2_TUNER_MODE_STEREO:
++ audio_mode = TUNER_AUDIO_STEREO;
++ break;
++ case V4L2_TUNER_MODE_LANG2:
++ audio_mode = TUNER_AUDIO_LANG2;
++ break;
++ case V4L2_TUNER_MODE_LANG1:
++ audio_mode = TUNER_AUDIO_LANG1;
++ break;
++ }
++
++ v4l_dbg(1, debug, client, "change audio mode to %s\n",
++ mes[audio_mode]);
++ decoder->tuner_audio_mode = audio_mode;
++ /* The registers are not changed here. */
++ /* See DECODER_ENABLE_OUTPUT section. */
++ set_audio_mode(client, decoder->tuner_audio_mode);
++ break;
++ }
++
++ case VIDIOC_G_TUNER: {
++ struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
++ int dual_f, stereo_f;
++
++ if (decoder->radio)
++ break;
++ get_inf_dev_status(client, &dual_f, &stereo_f);
++
++ v4l_dbg(1, debug, client, "DETECT==st:%d dual:%d\n",
++ stereo_f, dual_f);
++
++ /* mono */
++ if ((dual_f == 0) && (stereo_f == 0)) {
++ vt->rxsubchans = V4L2_TUNER_SUB_MONO;
++ v4l_dbg(1, debug, client, "DETECT==MONO\n");
++ }
++
++ /* stereo */
++ if (stereo_f == 1) {
++ if (vt->audmode == V4L2_TUNER_MODE_STEREO ||
++ vt->audmode == V4L2_TUNER_MODE_LANG1) {
++ vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
++ v4l_dbg(1, debug, client, "DETECT==ST(ST)\n");
++ } else {
++ vt->rxsubchans = V4L2_TUNER_SUB_MONO;
++ v4l_dbg(1, debug, client, "DETECT==ST(MONO)\n");
++ }
++ }
++
++ /* dual */
++ if (dual_f == 1) {
++ if (vt->audmode == V4L2_TUNER_MODE_LANG2) {
++ vt->rxsubchans = V4L2_TUNER_SUB_LANG2 | V4L2_TUNER_SUB_MONO;
++ v4l_dbg(1, debug, client, "DETECT==DUAL1\n");
++ } else {
++ vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_MONO;
++ v4l_dbg(1, debug, client, "DETECT==DUAL2\n");
++ }
++ }
++ break;
++ }
++
++ case VIDIOC_LOG_STATUS:
++ /* not yet implemented */
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++/* ----------------------------------------------------------------------- */
++
++
++/* i2c implementation */
++
++/* ----------------------------------------------------------------------- */
++static int saa717x_probe(struct i2c_client *client)
++{
++ struct saa717x_state *decoder;
++ u8 id = 0;
++ char *p = "";
++
++ /* Check if the adapter supports the needed features */
++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
++ return -EIO;
++
++ snprintf(client->name, sizeof(client->name) - 1, "saa717x");
++
++ if (saa717x_write(client, 0x5a4, 0xfe) &&
++ saa717x_write(client, 0x5a5, 0x0f) &&
++ saa717x_write(client, 0x5a6, 0x00) &&
++ saa717x_write(client, 0x5a7, 0x01))
++ id = saa717x_read(client, 0x5a0);
++ if (id != 0xc2 && id != 0x32 && id != 0xf2 && id != 0x6c) {
++ v4l_dbg(1, debug, client, "saa717x not found (id=%02x)\n", id);
++ return -ENODEV;
++ }
++ if (id == 0xc2)
++ p = "saa7173";
++ else if (id == 0x32)
++ p = "saa7174A";
++ else if (id == 0x6c)
++ p = "saa7174HL";
++ else
++ p = "saa7171";
++ v4l_info(client, "%s found @ 0x%x (%s)\n", p,
++ client->addr << 1, client->adapter->name);
++
++ decoder = kzalloc(sizeof(struct saa717x_state), GFP_KERNEL);
++ i2c_set_clientdata(client, decoder);
++
++ if (decoder == NULL)
++ return -ENOMEM;
++ decoder->std = V4L2_STD_NTSC;
++ decoder->input = -1;
++ decoder->enable = 1;
++
++ /* tune these parameters */
++ decoder->bright = 0x80;
++ decoder->contrast = 0x44;
++ decoder->sat = 0x40;
++ decoder->hue = 0x00;
++
++ /* FIXME!! */
++ decoder->playback = 0; /* initially capture mode used */
++ decoder->audio = 1; /* DECODER_AUDIO_48_KHZ */
++
++ decoder->audio_input = 2; /* FIXME!! */
++
++ decoder->tuner_audio_mode = TUNER_AUDIO_STEREO;
++ /* set volume, bass and treble */
++ decoder->audio_main_vol_l = 6;
++ decoder->audio_main_vol_r = 6;
++ decoder->audio_main_bass = 0;
++ decoder->audio_main_treble = 0;
++ decoder->audio_main_mute = 0;
++ decoder->audio_main_balance = 32768;
++ /* normalize (24 to -40 (not -84) -> 65535 to 0) */
++ decoder->audio_main_volume =
++ (decoder->audio_main_vol_r + 41) * 65535 / (24 - (-40));
++
++ v4l_dbg(1, debug, client, "writing init values\n");
++
++ /* FIXME!! */
++ saa717x_write_regs(client, reg_init_initialize);
++ set_video_output_level_regs(client, decoder);
++ /* set bass,treble to 0db 20041101 K.Ohta */
++ decoder->audio_main_bass = 0;
++ decoder->audio_main_treble = 0;
++ set_audio_regs(client, decoder);
++
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule_timeout(2*HZ);
++ return 0;
++}
++
++static int saa717x_remove(struct i2c_client *client)
++{
++ kfree(i2c_get_clientdata(client));
++ return 0;
++}
++
++/* ----------------------------------------------------------------------- */
++
++static struct v4l2_i2c_driver_data v4l2_i2c_data = {
++ .name = "saa717x",
++ .driverid = I2C_DRIVERID_SAA717X,
++ .command = saa717x_command,
++ .probe = saa717x_probe,
++ .remove = saa717x_remove,
++ .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL,
++};
+diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c
+index 41f7044..02fda4e 100644
+--- a/drivers/media/video/saa7185.c
++++ b/drivers/media/video/saa7185.c
+@@ -52,7 +52,7 @@ MODULE_LICENSE("GPL");
+ #define I2C_NAME(s) (s)->name
+
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c
+index d5d7d6c..1cd6293 100644
+--- a/drivers/media/video/se401.c
++++ b/drivers/media/video/se401.c
+@@ -35,7 +35,7 @@ static const char version[] = "0.24";
+ #include <linux/usb.h>
+ #include "se401.h"
+
+-static int flickerless=0;
++static int flickerless;
+ static int video_nr = -1;
+
+ static struct usb_device_id device_table [] = {
+@@ -300,10 +300,10 @@ static void se401_button_irq(struct urb *urb)
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+- dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
++ dbg("%s - urb shutting down with status: %d", __func__, urb->status);
+ return;
+ default:
+- dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
++ dbg("%s - nonzero urb status received: %d", __func__, urb->status);
+ goto exit;
+ }
+
+@@ -315,7 +315,7 @@ exit:
+ status = usb_submit_urb (urb, GFP_ATOMIC);
+ if (status)
+ err ("%s - usb_submit_urb failed with result %d",
+- __FUNCTION__, status);
++ __func__, status);
+ }
+
+ static void se401_video_irq(struct urb *urb)
+@@ -1224,7 +1224,9 @@ static const struct file_operations se401_fops = {
+ .read = se401_read,
+ .mmap = se401_mmap,
+ .ioctl = se401_ioctl,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+ static struct video_device se401_template = {
+@@ -1279,7 +1281,7 @@ static int se401_init(struct usb_se401 *se401, int button)
+ rc=se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp));
+ se401->cheight=cp[0]+cp[1]*256;
+
+- if (!cp[2] && SE401_FORMAT_BAYER) {
++ if (!(cp[2] & SE401_FORMAT_BAYER)) {
+ err("Bayer format not supported!");
+ return 1;
+ }
+diff --git a/drivers/media/video/sn9c102/sn9c102.h b/drivers/media/video/sn9c102/sn9c102.h
+index 2e3c3de..0c8d87d 100644
+--- a/drivers/media/video/sn9c102/sn9c102.h
++++ b/drivers/media/video/sn9c102/sn9c102.h
+@@ -176,7 +176,7 @@ do { \
+ dev_info(&cam->usbdev->dev, fmt "\n", ## args); \
+ else if ((level) >= 3) \
+ dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
+- __FUNCTION__, __LINE__ , ## args); \
++ __func__, __LINE__ , ## args); \
+ } \
+ } while (0)
+ # define V4LDBG(level, name, cmd) \
+@@ -191,7 +191,7 @@ do { \
+ pr_info("sn9c102: " fmt "\n", ## args); \
+ else if ((level) == 3) \
+ pr_debug("sn9c102: [%s:%d] " fmt "\n", \
+- __FUNCTION__, __LINE__ , ## args); \
++ __func__, __LINE__ , ## args); \
+ } \
+ } while (0)
+ #else
+@@ -202,7 +202,7 @@ do { \
+
+ #undef PDBG
+ #define PDBG(fmt, args...) \
+-dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__, \
++dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__, \
+ __LINE__ , ## args)
+
+ #undef PDBGG
+diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
+index c40ba3a..5748b1e 100644
+--- a/drivers/media/video/sn9c102/sn9c102_core.c
++++ b/drivers/media/video/sn9c102/sn9c102_core.c
+@@ -464,9 +464,9 @@ sn9c102_i2c_try_read(struct sn9c102_device* cam,
+ }
+
+
+-int
+-sn9c102_i2c_try_write(struct sn9c102_device* cam,
+- const struct sn9c102_sensor* sensor, u8 address, u8 value)
++static int sn9c102_i2c_try_write(struct sn9c102_device* cam,
++ const struct sn9c102_sensor* sensor,
++ u8 address, u8 value)
+ {
+ return sn9c102_i2c_try_raw_write(cam, sensor, 3,
+ sensor->i2c_slave_id, address,
+@@ -528,7 +528,7 @@ sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
+
+ /* Search for the SOF marker (fixed part) in the header */
+ for (j = 0, b=cam->sof.bytesread; j+b < sizeof(marker); j++) {
+- if (unlikely(i+j) == len)
++ if (unlikely(i+j == len))
+ return NULL;
+ if (*(m+i+j) == marker[cam->sof.bytesread]) {
+ cam->sof.header[cam->sof.bytesread] = *(m+i+j);
+@@ -3224,7 +3224,9 @@ static const struct file_operations sn9c102_fops = {
+ .open = sn9c102_open,
+ .release = sn9c102_release,
+ .ioctl = sn9c102_ioctl,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .read = sn9c102_read,
+ .poll = sn9c102_poll,
+ .mmap = sn9c102_mmap,
+@@ -3239,7 +3241,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
+ {
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct sn9c102_device* cam;
+- static unsigned int dev_nr = 0;
++ static unsigned int dev_nr;
+ unsigned int i;
+ int err = 0, r;
+
+diff --git a/drivers/media/video/sn9c102/sn9c102_sensor.h b/drivers/media/video/sn9c102/sn9c102_sensor.h
+index 2d7d786..4af7382 100644
+--- a/drivers/media/video/sn9c102/sn9c102_sensor.h
++++ b/drivers/media/video/sn9c102/sn9c102_sensor.h
+@@ -85,9 +85,6 @@ sn9c102_attach_sensor(struct sn9c102_device* cam,
+ */
+
+ /* The "try" I2C I/O versions are used when probing the sensor */
+-extern int sn9c102_i2c_try_write(struct sn9c102_device*,
+- const struct sn9c102_sensor*, u8 address,
+- u8 value);
+ extern int sn9c102_i2c_try_read(struct sn9c102_device*,
+ const struct sn9c102_sensor*, u8 address);
+
+@@ -126,7 +123,7 @@ extern int sn9c102_write_regs(struct sn9c102_device*, const u8 valreg[][2],
+ Register adresses must be < 256.
+ */
+ #define sn9c102_write_const_regs(sn9c102_device, data...) \
+- ({ const static u8 _valreg[][2] = {data}; \
++ ({ static const u8 _valreg[][2] = {data}; \
+ sn9c102_write_regs(sn9c102_device, _valreg, ARRAY_SIZE(_valreg)); })
+
+ /*****************************************************************************/
+diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
+new file mode 100644
+index 0000000..a1b9244
+--- /dev/null
++++ b/drivers/media/video/soc_camera.c
+@@ -0,0 +1,1031 @@
++/*
++ * camera image capture (abstract) bus driver
++ *
++ * Copyright (C) 2008, Guennadi Liakhovetski <kernel at pengutronix.de>
++ *
++ * This driver provides an interface between platform-specific camera
++ * busses and camera devices. It should be used if the camera is
++ * connected not over a "proper" bus like PCI or USB, but over a
++ * special bus, like, for example, the Quick Capture interface on PXA270
++ * SoCs. Later it should also be used for i.MX31 SoCs from Freescale.
++ * It can handle multiple cameras and / or multiple busses, which can
++ * be used, e.g., in stereo-vision applications.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/device.h>
++#include <linux/list.h>
++#include <linux/err.h>
++#include <linux/mutex.h>
++#include <linux/vmalloc.h>
++
++#include <media/v4l2-common.h>
++#include <media/v4l2-dev.h>
++#include <media/soc_camera.h>
++
++static LIST_HEAD(hosts);
++static LIST_HEAD(devices);
++static DEFINE_MUTEX(list_lock);
++static DEFINE_MUTEX(video_lock);
++
++const static struct soc_camera_data_format*
++format_by_fourcc(struct soc_camera_device *icd, unsigned int fourcc)
++{
++ unsigned int i;
++
++ for (i = 0; i < icd->num_formats; i++)
++ if (icd->formats[i].fourcc == fourcc)
++ return icd->formats + i;
++ return NULL;
++}
++
++static int soc_camera_try_fmt_cap(struct file *file, void *priv,
++ struct v4l2_format *f)
++{
++ struct soc_camera_file *icf = file->private_data;
++ struct soc_camera_device *icd = icf->icd;
++ struct soc_camera_host *ici =
++ to_soc_camera_host(icd->dev.parent);
++ enum v4l2_field field;
++ const struct soc_camera_data_format *fmt;
++ int ret;
++
++ WARN_ON(priv != file->private_data);
++
++ fmt = format_by_fourcc(icd, f->fmt.pix.pixelformat);
++ if (!fmt) {
++ dev_dbg(&icd->dev, "invalid format 0x%08x\n",
++ f->fmt.pix.pixelformat);
++ return -EINVAL;
++ }
++
++ dev_dbg(&icd->dev, "fmt: 0x%08x\n", fmt->fourcc);
++
++ field = f->fmt.pix.field;
++
++ if (field == V4L2_FIELD_ANY) {
++ field = V4L2_FIELD_NONE;
++ } else if (V4L2_FIELD_NONE != field) {
++ dev_err(&icd->dev, "Field type invalid.\n");
++ return -EINVAL;
++ }
++
++ /* test physical bus parameters */
++ ret = ici->ops->try_bus_param(icd, f->fmt.pix.pixelformat);
++ if (ret)
++ return ret;
++
++ /* limit format to hardware capabilities */
++ ret = ici->ops->try_fmt_cap(icd, f);
++
++ /* calculate missing fields */
++ f->fmt.pix.field = field;
++ f->fmt.pix.bytesperline =
++ (f->fmt.pix.width * fmt->depth) >> 3;
++ f->fmt.pix.sizeimage =
++ f->fmt.pix.height * f->fmt.pix.bytesperline;
++
++ return ret;
++}
++
++static int soc_camera_enum_input(struct file *file, void *priv,
++ struct v4l2_input *inp)
++{
++ if (inp->index != 0)
++ return -EINVAL;
++
++ inp->type = V4L2_INPUT_TYPE_CAMERA;
++ inp->std = V4L2_STD_UNKNOWN;
++ strcpy(inp->name, "Camera");
++
++ return 0;
++}
++
++static int soc_camera_g_input(struct file *file, void *priv, unsigned int *i)
++{
++ *i = 0;
++
++ return 0;
++}
++
++static int soc_camera_s_input(struct file *file, void *priv, unsigned int i)
++{
++ if (i > 0)
++ return -EINVAL;
++
++ return 0;
++}
++
++static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id *a)
++{
++ return 0;
++}
++
++static int soc_camera_reqbufs(struct file *file, void *priv,
++ struct v4l2_requestbuffers *p)
++{
++ int ret;
++ struct soc_camera_file *icf = file->private_data;
++ struct soc_camera_device *icd = icf->icd;
++ struct soc_camera_host *ici =
++ to_soc_camera_host(icd->dev.parent);
++
++ WARN_ON(priv != file->private_data);
++
++ dev_dbg(&icd->dev, "%s: %d\n", __func__, p->memory);
++
++ ret = videobuf_reqbufs(&icf->vb_vidq, p);
++ if (ret < 0)
++ return ret;
++
++ return ici->ops->reqbufs(icf, p);
++}
++
++static int soc_camera_querybuf(struct file *file, void *priv,
++ struct v4l2_buffer *p)
++{
++ struct soc_camera_file *icf = file->private_data;
++
++ WARN_ON(priv != file->private_data);
++
++ return videobuf_querybuf(&icf->vb_vidq, p);
++}
++
++static int soc_camera_qbuf(struct file *file, void *priv,
++ struct v4l2_buffer *p)
++{
++ struct soc_camera_file *icf = file->private_data;
++
++ WARN_ON(priv != file->private_data);
++
++ return videobuf_qbuf(&icf->vb_vidq, p);
++}
++
++static int soc_camera_dqbuf(struct file *file, void *priv,
++ struct v4l2_buffer *p)
++{
++ struct soc_camera_file *icf = file->private_data;
++
++ WARN_ON(priv != file->private_data);
++
++ return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK);
++}
++
++static int soc_camera_open(struct inode *inode, struct file *file)
++{
++ struct video_device *vdev;
++ struct soc_camera_device *icd;
++ struct soc_camera_host *ici;
++ struct soc_camera_file *icf;
++ spinlock_t *lock;
++ int ret;
++
++ icf = vmalloc(sizeof(*icf));
++ if (!icf)
++ return -ENOMEM;
++
++ /* Protect against icd->remove() until we module_get() both drivers. */
++ mutex_lock(&video_lock);
++
++ vdev = video_devdata(file);
++ icd = container_of(vdev->dev, struct soc_camera_device, dev);
++ ici = to_soc_camera_host(icd->dev.parent);
++
++ if (!try_module_get(icd->ops->owner)) {
++ dev_err(&icd->dev, "Couldn't lock sensor driver.\n");
++ ret = -EINVAL;
++ goto emgd;
++ }
++
++ if (!try_module_get(ici->ops->owner)) {
++ dev_err(&icd->dev, "Couldn't lock capture bus driver.\n");
++ ret = -EINVAL;
++ goto emgi;
++ }
++
++ icf->icd = icd;
++
++ icf->lock = ici->ops->spinlock_alloc(icf);
++ if (!icf->lock) {
++ ret = -ENOMEM;
++ goto esla;
++ }
++
++ icd->use_count++;
++
++ /* Now we really have to activate the camera */
++ if (icd->use_count == 1) {
++ ret = ici->ops->add(icd);
++ if (ret < 0) {
++ dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);
++ icd->use_count--;
++ goto eiciadd;
++ }
++ }
++
++ mutex_unlock(&video_lock);
++
++ file->private_data = icf;
++ dev_dbg(&icd->dev, "camera device open\n");
++
++ /* We must pass NULL as dev pointer, then all pci_* dma operations
++ * transform to normal dma_* ones. */
++ videobuf_queue_sg_init(&icf->vb_vidq, ici->vbq_ops, NULL, icf->lock,
++ V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
++ ici->msize, icd);
++
++ return 0;
++
++ /* All errors are entered with the video_lock held */
++eiciadd:
++ lock = icf->lock;
++ icf->lock = NULL;
++ if (ici->ops->spinlock_free)
++ ici->ops->spinlock_free(lock);
++esla:
++ module_put(ici->ops->owner);
++emgi:
++ module_put(icd->ops->owner);
++emgd:
++ mutex_unlock(&video_lock);
++ vfree(icf);
++ return ret;
++}
++
++static int soc_camera_close(struct inode *inode, struct file *file)
++{
++ struct soc_camera_file *icf = file->private_data;
++ struct soc_camera_device *icd = icf->icd;
++ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
++ struct video_device *vdev = icd->vdev;
++ spinlock_t *lock = icf->lock;
++
++ mutex_lock(&video_lock);
++ icd->use_count--;
++ if (!icd->use_count)
++ ici->ops->remove(icd);
++ icf->lock = NULL;
++ if (ici->ops->spinlock_free)
++ ici->ops->spinlock_free(lock);
++ module_put(icd->ops->owner);
++ module_put(ici->ops->owner);
++ mutex_unlock(&video_lock);
++
++ vfree(icf);
++
++ dev_dbg(vdev->dev, "camera device close\n");
++
++ return 0;
++}
++
++static ssize_t soc_camera_read(struct file *file, char __user *buf,
++ size_t count, loff_t *ppos)
++{
++ struct soc_camera_file *icf = file->private_data;
++ struct soc_camera_device *icd = icf->icd;
++ struct video_device *vdev = icd->vdev;
++ int err = -EINVAL;
++
++ dev_err(vdev->dev, "camera device read not implemented\n");
++
++ return err;
++}
++
++static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ struct soc_camera_file *icf = file->private_data;
++ struct soc_camera_device *icd = icf->icd;
++ int err;
++
++ dev_dbg(&icd->dev, "mmap called, vma=0x%08lx\n", (unsigned long)vma);
++
++ err = videobuf_mmap_mapper(&icf->vb_vidq, vma);
++
++ dev_dbg(&icd->dev, "vma start=0x%08lx, size=%ld, ret=%d\n",
++ (unsigned long)vma->vm_start,
++ (unsigned long)vma->vm_end - (unsigned long)vma->vm_start,
++ err);
++
++ return err;
++}
++
++static unsigned int soc_camera_poll(struct file *file, poll_table *pt)
++{
++ struct soc_camera_file *icf = file->private_data;
++ struct soc_camera_device *icd = icf->icd;
++ struct soc_camera_host *ici =
++ to_soc_camera_host(icd->dev.parent);
++
++ if (list_empty(&icf->vb_vidq.stream)) {
++ dev_err(&icd->dev, "Trying to poll with no queued buffers!\n");
++ return POLLERR;
++ }
++
++ return ici->ops->poll(file, pt);
++}
++
++
++static struct file_operations soc_camera_fops = {
++ .owner = THIS_MODULE,
++ .open = soc_camera_open,
++ .release = soc_camera_close,
++ .ioctl = video_ioctl2,
++ .read = soc_camera_read,
++ .mmap = soc_camera_mmap,
++ .poll = soc_camera_poll,
++ .llseek = no_llseek,
++};
++
++
++static int soc_camera_s_fmt_cap(struct file *file, void *priv,
++ struct v4l2_format *f)
++{
++ struct soc_camera_file *icf = file->private_data;
++ struct soc_camera_device *icd = icf->icd;
++ struct soc_camera_host *ici =
++ to_soc_camera_host(icd->dev.parent);
++ int ret;
++ struct v4l2_rect rect;
++ const static struct soc_camera_data_format *data_fmt;
++
++ WARN_ON(priv != file->private_data);
++
++ data_fmt = format_by_fourcc(icd, f->fmt.pix.pixelformat);
++ if (!data_fmt)
++ return -EINVAL;
++
++ /* buswidth may be further adjusted by the ici */
++ icd->buswidth = data_fmt->depth;
++
++ ret = soc_camera_try_fmt_cap(file, icf, f);
++ if (ret < 0)
++ return ret;
++
++ rect.left = icd->x_current;
++ rect.top = icd->y_current;
++ rect.width = f->fmt.pix.width;
++ rect.height = f->fmt.pix.height;
++ ret = ici->ops->set_fmt_cap(icd, f->fmt.pix.pixelformat, &rect);
++ if (ret < 0)
++ return ret;
++
++ icd->current_fmt = data_fmt;
++ icd->width = rect.width;
++ icd->height = rect.height;
++ icf->vb_vidq.field = f->fmt.pix.field;
++ if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type)
++ dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n",
++ f->type);
++
++ dev_dbg(&icd->dev, "set width: %d height: %d\n",
++ icd->width, icd->height);
++
++ /* set physical bus parameters */
++ return ici->ops->set_bus_param(icd, f->fmt.pix.pixelformat);
++}
++
++static int soc_camera_enum_fmt_cap(struct file *file, void *priv,
++ struct v4l2_fmtdesc *f)
++{
++ struct soc_camera_file *icf = file->private_data;
++ struct soc_camera_device *icd = icf->icd;
++ const struct soc_camera_data_format *format;
++
++ WARN_ON(priv != file->private_data);
++
++ if (f->index >= icd->num_formats)
++ return -EINVAL;
++
++ format = &icd->formats[f->index];
++
++ strlcpy(f->description, format->name, sizeof(f->description));
++ f->pixelformat = format->fourcc;
++ return 0;
++}
++
++static int soc_camera_g_fmt_cap(struct file *file, void *priv,
++ struct v4l2_format *f)
++{
++ struct soc_camera_file *icf = file->private_data;
++ struct soc_camera_device *icd = icf->icd;
++
++ WARN_ON(priv != file->private_data);
++
++ f->fmt.pix.width = icd->width;
++ f->fmt.pix.height = icd->height;
++ f->fmt.pix.field = icf->vb_vidq.field;
++ f->fmt.pix.pixelformat = icd->current_fmt->fourcc;
++ f->fmt.pix.bytesperline =
++ (f->fmt.pix.width * icd->current_fmt->depth) >> 3;
++ f->fmt.pix.sizeimage =
++ f->fmt.pix.height * f->fmt.pix.bytesperline;
++ dev_dbg(&icd->dev, "current_fmt->fourcc: 0x%08x\n",
++ icd->current_fmt->fourcc);
++ return 0;
++}
++
++static int soc_camera_querycap(struct file *file, void *priv,
++ struct v4l2_capability *cap)
++{
++ struct soc_camera_file *icf = file->private_data;
++ struct soc_camera_device *icd = icf->icd;
++ struct soc_camera_host *ici =
++ to_soc_camera_host(icd->dev.parent);
++
++ WARN_ON(priv != file->private_data);
++
++ strlcpy(cap->driver, ici->drv_name, sizeof(cap->driver));
++ return ici->ops->querycap(ici, cap);
++}
++
++static int soc_camera_streamon(struct file *file, void *priv,
++ enum v4l2_buf_type i)
++{
++ struct soc_camera_file *icf = file->private_data;
++ struct soc_camera_device *icd = icf->icd;
++
++ WARN_ON(priv != file->private_data);
++
++ dev_dbg(&icd->dev, "%s\n", __func__);
++
++ if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++ return -EINVAL;
++
++ icd->ops->start_capture(icd);
++
++ /* This calls buf_queue from host driver's videobuf_queue_ops */
++ return videobuf_streamon(&icf->vb_vidq);
++}
++
++static int soc_camera_streamoff(struct file *file, void *priv,
++ enum v4l2_buf_type i)
++{
++ struct soc_camera_file *icf = file->private_data;
++ struct soc_camera_device *icd = icf->icd;
++
++ WARN_ON(priv != file->private_data);
++
++ dev_dbg(&icd->dev, "%s\n", __func__);
++
++ if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++ return -EINVAL;
++
++ /* This calls buf_release from host driver's videobuf_queue_ops for all
++ * remaining buffers. When the last buffer is freed, stop capture */
++ videobuf_streamoff(&icf->vb_vidq);
++
++ icd->ops->stop_capture(icd);
++
++ return 0;
++}
++
++static int soc_camera_queryctrl(struct file *file, void *priv,
++ struct v4l2_queryctrl *qc)
++{
++ struct soc_camera_file *icf = file->private_data;
++ struct soc_camera_device *icd = icf->icd;
++ int i;
++
++ WARN_ON(priv != file->private_data);
++
++ if (!qc->id)
++ return -EINVAL;
++
++ for (i = 0; i < icd->ops->num_controls; i++)
++ if (qc->id == icd->ops->controls[i].id) {
++ memcpy(qc, &(icd->ops->controls[i]),
++ sizeof(*qc));
++ return 0;
++ }
++
++ return -EINVAL;
++}
++
++static int soc_camera_g_ctrl(struct file *file, void *priv,
++ struct v4l2_control *ctrl)
++{
++ struct soc_camera_file *icf = file->private_data;
++ struct soc_camera_device *icd = icf->icd;
++
++ WARN_ON(priv != file->private_data);
++
++ switch (ctrl->id) {
++ case V4L2_CID_GAIN:
++ if (icd->gain == (unsigned short)~0)
++ return -EINVAL;
++ ctrl->value = icd->gain;
++ return 0;
++ case V4L2_CID_EXPOSURE:
++ if (icd->exposure == (unsigned short)~0)
++ return -EINVAL;
++ ctrl->value = icd->exposure;
++ return 0;
++ }
++
++ if (icd->ops->get_control)
++ return icd->ops->get_control(icd, ctrl);
++ return -EINVAL;
++}
++
++static int soc_camera_s_ctrl(struct file *file, void *priv,
++ struct v4l2_control *ctrl)
++{
++ struct soc_camera_file *icf = file->private_data;
++ struct soc_camera_device *icd = icf->icd;
++
++ WARN_ON(priv != file->private_data);
++
++ if (icd->ops->set_control)
++ return icd->ops->set_control(icd, ctrl);
++ return -EINVAL;
++}
++
++static int soc_camera_cropcap(struct file *file, void *fh,
++ struct v4l2_cropcap *a)
++{
++ struct soc_camera_file *icf = file->private_data;
++ struct soc_camera_device *icd = icf->icd;
++
++ a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ a->bounds.left = icd->x_min;
++ a->bounds.top = icd->y_min;
++ a->bounds.width = icd->width_max;
++ a->bounds.height = icd->height_max;
++ a->defrect.left = icd->x_min;
++ a->defrect.top = icd->y_min;
++ a->defrect.width = 640;
++ a->defrect.height = 480;
++ a->pixelaspect.numerator = 1;
++ a->pixelaspect.denominator = 1;
++
++ return 0;
++}
++
++static int soc_camera_g_crop(struct file *file, void *fh,
++ struct v4l2_crop *a)
++{
++ struct soc_camera_file *icf = file->private_data;
++ struct soc_camera_device *icd = icf->icd;
++
++ a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ a->c.left = icd->x_current;
++ a->c.top = icd->y_current;
++ a->c.width = icd->width;
++ a->c.height = icd->height;
++
++ return 0;
++}
++
++static int soc_camera_s_crop(struct file *file, void *fh,
++ struct v4l2_crop *a)
++{
++ struct soc_camera_file *icf = file->private_data;
++ struct soc_camera_device *icd = icf->icd;
++ struct soc_camera_host *ici =
++ to_soc_camera_host(icd->dev.parent);
++ int ret;
++
++ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++ return -EINVAL;
++
++ ret = ici->ops->set_fmt_cap(icd, 0, &a->c);
++ if (!ret) {
++ icd->width = a->c.width;
++ icd->height = a->c.height;
++ icd->x_current = a->c.left;
++ icd->y_current = a->c.top;
++ }
++
++ return ret;
++}
++
++static int soc_camera_g_chip_ident(struct file *file, void *fh,
++ struct v4l2_chip_ident *id)
++{
++ struct soc_camera_file *icf = file->private_data;
++ struct soc_camera_device *icd = icf->icd;
++
++ if (!icd->ops->get_chip_id)
++ return -EINVAL;
++
++ return icd->ops->get_chip_id(icd, id);
++}
++
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++static int soc_camera_g_register(struct file *file, void *fh,
++ struct v4l2_register *reg)
++{
++ struct soc_camera_file *icf = file->private_data;
++ struct soc_camera_device *icd = icf->icd;
++
++ if (!icd->ops->get_register)
++ return -EINVAL;
++
++ return icd->ops->get_register(icd, reg);
++}
++
++static int soc_camera_s_register(struct file *file, void *fh,
++ struct v4l2_register *reg)
++{
++ struct soc_camera_file *icf = file->private_data;
++ struct soc_camera_device *icd = icf->icd;
++
++ if (!icd->ops->set_register)
++ return -EINVAL;
++
++ return icd->ops->set_register(icd, reg);
++}
++#endif
++
++static int device_register_link(struct soc_camera_device *icd)
++{
++ int ret = device_register(&icd->dev);
++
++ if (ret < 0) {
++ /* Prevent calling device_unregister() */
++ icd->dev.parent = NULL;
++ dev_err(&icd->dev, "Cannot register device: %d\n", ret);
++ /* Even if probe() was unsuccessful for all registered drivers,
++ * device_register() returns 0, and we add the link, just to
++ * document this camera's control device */
++ } else if (icd->control)
++ /* Have to sysfs_remove_link() before device_unregister()? */
++ if (sysfs_create_link(&icd->dev.kobj, &icd->control->kobj,
++ "control"))
++ dev_warn(&icd->dev,
++ "Failed creating the control symlink\n");
++ return ret;
++}
++
++/* So far this function cannot fail */
++static void scan_add_host(struct soc_camera_host *ici)
++{
++ struct soc_camera_device *icd;
++
++ mutex_lock(&list_lock);
++
++ list_for_each_entry(icd, &devices, list) {
++ if (icd->iface == ici->nr) {
++ icd->dev.parent = &ici->dev;
++ device_register_link(icd);
++ }
++ }
++
++ mutex_unlock(&list_lock);
++}
++
++/* return: 0 if no match found or a match found and
++ * device_register() successful, error code otherwise */
++static int scan_add_device(struct soc_camera_device *icd)
++{
++ struct soc_camera_host *ici;
++ int ret = 0;
++
++ mutex_lock(&list_lock);
++
++ list_add_tail(&icd->list, &devices);
++
++ /* Watch out for class_for_each_device / class_find_device API by
++ * Dave Young <hidave.darkstar at gmail.com> */
++ list_for_each_entry(ici, &hosts, list) {
++ if (icd->iface == ici->nr) {
++ ret = 1;
++ icd->dev.parent = &ici->dev;
++ break;
++ }
++ }
++
++ mutex_unlock(&list_lock);
++
++ if (ret)
++ ret = device_register_link(icd);
++
++ return ret;
++}
++
++static int soc_camera_probe(struct device *dev)
++{
++ struct soc_camera_device *icd = to_soc_camera_dev(dev);
++ struct soc_camera_host *ici =
++ to_soc_camera_host(icd->dev.parent);
++ int ret;
++
++ if (!icd->ops->probe)
++ return -ENODEV;
++
++ /* We only call ->add() here to activate and probe the camera.
++ * We shall ->remove() and deactivate it immediately afterwards. */
++ ret = ici->ops->add(icd);
++ if (ret < 0)
++ return ret;
++
++ ret = icd->ops->probe(icd);
++ if (ret >= 0) {
++ const struct v4l2_queryctrl *qctrl;
++
++ qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN);
++ icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0;
++ qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
++ icd->exposure = qctrl ? qctrl->default_value :
++ (unsigned short)~0;
++ }
++ ici->ops->remove(icd);
++
++ return ret;
++}
++
++/* This is called on device_unregister, which only means we have to disconnect
++ * from the host, but not remove ourselves from the device list */
++static int soc_camera_remove(struct device *dev)
++{
++ struct soc_camera_device *icd = to_soc_camera_dev(dev);
++
++ if (icd->ops->remove)
++ icd->ops->remove(icd);
++
++ return 0;
++}
++
++static struct bus_type soc_camera_bus_type = {
++ .name = "soc-camera",
++ .probe = soc_camera_probe,
++ .remove = soc_camera_remove,
++};
++
++static struct device_driver ic_drv = {
++ .name = "camera",
++ .bus = &soc_camera_bus_type,
++ .owner = THIS_MODULE,
++};
++
++/*
++ * Image capture host - this is a host device, not a bus device, so,
++ * no bus reference, no probing.
++ */
++static struct class soc_camera_host_class = {
++ .owner = THIS_MODULE,
++ .name = "camera_host",
++};
++
++static void dummy_release(struct device *dev)
++{
++}
++
++static spinlock_t *spinlock_alloc(struct soc_camera_file *icf)
++{
++ spinlock_t *lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
++
++ if (lock)
++ spin_lock_init(lock);
++
++ return lock;
++}
++
++static void spinlock_free(spinlock_t *lock)
++{
++ kfree(lock);
++}
++
++int soc_camera_host_register(struct soc_camera_host *ici)
++{
++ int ret;
++ struct soc_camera_host *ix;
++
++ if (!ici->vbq_ops || !ici->ops->add || !ici->ops->remove)
++ return -EINVAL;
++
++ /* Number might be equal to the platform device ID */
++ sprintf(ici->dev.bus_id, "camera_host%d", ici->nr);
++ ici->dev.class = &soc_camera_host_class;
++
++ mutex_lock(&list_lock);
++ list_for_each_entry(ix, &hosts, list) {
++ if (ix->nr == ici->nr) {
++ mutex_unlock(&list_lock);
++ return -EBUSY;
++ }
++ }
++
++ list_add_tail(&ici->list, &hosts);
++ mutex_unlock(&list_lock);
++
++ ici->dev.release = dummy_release;
++
++ ret = device_register(&ici->dev);
++
++ if (ret)
++ goto edevr;
++
++ if (!ici->ops->spinlock_alloc) {
++ ici->ops->spinlock_alloc = spinlock_alloc;
++ ici->ops->spinlock_free = spinlock_free;
++ }
++
++ scan_add_host(ici);
++
++ return 0;
++
++edevr:
++ mutex_lock(&list_lock);
++ list_del(&ici->list);
++ mutex_unlock(&list_lock);
++
++ return ret;
++}
++EXPORT_SYMBOL(soc_camera_host_register);
++
++/* Unregister all clients! */
++void soc_camera_host_unregister(struct soc_camera_host *ici)
++{
++ struct soc_camera_device *icd;
++
++ mutex_lock(&list_lock);
++
++ list_del(&ici->list);
++
++ list_for_each_entry(icd, &devices, list) {
++ if (icd->dev.parent == &ici->dev) {
++ device_unregister(&icd->dev);
++ /* Not before device_unregister(), .remove
++ * needs parent to call ici->ops->remove() */
++ icd->dev.parent = NULL;
++ memset(&icd->dev.kobj, 0, sizeof(icd->dev.kobj));
++ }
++ }
++
++ mutex_unlock(&list_lock);
++
++ device_unregister(&ici->dev);
++}
++EXPORT_SYMBOL(soc_camera_host_unregister);
++
++/* Image capture device */
++int soc_camera_device_register(struct soc_camera_device *icd)
++{
++ struct soc_camera_device *ix;
++ int num = -1, i;
++
++ if (!icd)
++ return -EINVAL;
++
++ for (i = 0; i < 256 && num < 0; i++) {
++ num = i;
++ list_for_each_entry(ix, &devices, list) {
++ if (ix->iface == icd->iface && ix->devnum == i) {
++ num = -1;
++ break;
++ }
++ }
++ }
++
++ if (num < 0)
++ /* ok, we have 256 cameras on this host...
++ * man, stay reasonable... */
++ return -ENOMEM;
++
++ icd->devnum = num;
++ icd->dev.bus = &soc_camera_bus_type;
++ snprintf(icd->dev.bus_id, sizeof(icd->dev.bus_id),
++ "%u-%u", icd->iface, icd->devnum);
++
++ icd->dev.release = dummy_release;
++
++ return scan_add_device(icd);
++}
++EXPORT_SYMBOL(soc_camera_device_register);
++
++void soc_camera_device_unregister(struct soc_camera_device *icd)
++{
++ mutex_lock(&list_lock);
++ list_del(&icd->list);
++
++ /* The bus->remove will be eventually called */
++ if (icd->dev.parent)
++ device_unregister(&icd->dev);
++ mutex_unlock(&list_lock);
++}
++EXPORT_SYMBOL(soc_camera_device_unregister);
++
++int soc_camera_video_start(struct soc_camera_device *icd)
++{
++ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
++ int err = -ENOMEM;
++ struct video_device *vdev;
++
++ if (!icd->dev.parent)
++ return -ENODEV;
++
++ vdev = video_device_alloc();
++ if (!vdev)
++ goto evidallocd;
++ dev_dbg(&ici->dev, "Allocated video_device %p\n", vdev);
++
++ strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name));
++ /* Maybe better &ici->dev */
++ vdev->dev = &icd->dev;
++ vdev->type = VID_TYPE_CAPTURE;
++ vdev->current_norm = V4L2_STD_UNKNOWN;
++ vdev->fops = &soc_camera_fops;
++ vdev->release = video_device_release;
++ vdev->minor = -1;
++ vdev->tvnorms = V4L2_STD_UNKNOWN,
++ vdev->vidioc_querycap = soc_camera_querycap;
++ vdev->vidioc_g_fmt_cap = soc_camera_g_fmt_cap;
++ vdev->vidioc_enum_fmt_cap = soc_camera_enum_fmt_cap;
++ vdev->vidioc_s_fmt_cap = soc_camera_s_fmt_cap;
++ vdev->vidioc_enum_input = soc_camera_enum_input;
++ vdev->vidioc_g_input = soc_camera_g_input;
++ vdev->vidioc_s_input = soc_camera_s_input;
++ vdev->vidioc_s_std = soc_camera_s_std;
++ vdev->vidioc_reqbufs = soc_camera_reqbufs;
++ vdev->vidioc_try_fmt_cap = soc_camera_try_fmt_cap;
++ vdev->vidioc_querybuf = soc_camera_querybuf;
++ vdev->vidioc_qbuf = soc_camera_qbuf;
++ vdev->vidioc_dqbuf = soc_camera_dqbuf;
++ vdev->vidioc_streamon = soc_camera_streamon;
++ vdev->vidioc_streamoff = soc_camera_streamoff;
++ vdev->vidioc_queryctrl = soc_camera_queryctrl;
++ vdev->vidioc_g_ctrl = soc_camera_g_ctrl;
++ vdev->vidioc_s_ctrl = soc_camera_s_ctrl;
++ vdev->vidioc_cropcap = soc_camera_cropcap;
++ vdev->vidioc_g_crop = soc_camera_g_crop;
++ vdev->vidioc_s_crop = soc_camera_s_crop;
++ vdev->vidioc_g_chip_ident = soc_camera_g_chip_ident;
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++ vdev->vidioc_g_register = soc_camera_g_register;
++ vdev->vidioc_s_register = soc_camera_s_register;
++#endif
++
++ icd->current_fmt = &icd->formats[0];
++
++ err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor);
++ if (err < 0) {
++ dev_err(vdev->dev, "video_register_device failed\n");
++ goto evidregd;
++ }
++ icd->vdev = vdev;
++
++ return 0;
++
++evidregd:
++ video_device_release(vdev);
++evidallocd:
++ return err;
++}
++EXPORT_SYMBOL(soc_camera_video_start);
++
++void soc_camera_video_stop(struct soc_camera_device *icd)
++{
++ struct video_device *vdev = icd->vdev;
++
++ dev_dbg(&icd->dev, "%s\n", __func__);
++
++ if (!icd->dev.parent || !vdev)
++ return;
++
++ mutex_lock(&video_lock);
++ video_unregister_device(vdev);
++ icd->vdev = NULL;
++ mutex_unlock(&video_lock);
++}
++EXPORT_SYMBOL(soc_camera_video_stop);
++
++static int __init soc_camera_init(void)
++{
++ int ret = bus_register(&soc_camera_bus_type);
++ if (ret)
++ return ret;
++ ret = driver_register(&ic_drv);
++ if (ret)
++ goto edrvr;
++ ret = class_register(&soc_camera_host_class);
++ if (ret)
++ goto eclr;
++
++ return 0;
++
++eclr:
++ driver_unregister(&ic_drv);
++edrvr:
++ bus_unregister(&soc_camera_bus_type);
++ return ret;
++}
++
++static void __exit soc_camera_exit(void)
++{
++ class_unregister(&soc_camera_host_class);
++ driver_unregister(&ic_drv);
++ bus_unregister(&soc_camera_bus_type);
++}
++
++module_init(soc_camera_init);
++module_exit(soc_camera_exit);
++
++MODULE_DESCRIPTION("Image capture bus driver");
++MODULE_AUTHOR("Guennadi Liakhovetski <kernel at pengutronix.de>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c
+index ceba45a..9276ed9 100644
+--- a/drivers/media/video/stk-webcam.c
++++ b/drivers/media/video/stk-webcam.c
+@@ -1100,7 +1100,7 @@ static int stk_setup_format(struct stk_camera *dev)
+ && i < ARRAY_SIZE(stk_sizes))
+ i++;
+ if (i == ARRAY_SIZE(stk_sizes)) {
+- STK_ERROR("Something is broken in %s\n", __FUNCTION__);
++ STK_ERROR("Something is broken in %s\n", __func__);
+ return -EFAULT;
+ }
+ /* This registers controls some timings, not sure of what. */
+@@ -1465,7 +1465,7 @@ static void stk_camera_disconnect(struct usb_interface *interface)
+ }
+
+ #ifdef CONFIG_PM
+-int stk_camera_suspend(struct usb_interface *intf, pm_message_t message)
++static int stk_camera_suspend(struct usb_interface *intf, pm_message_t message)
+ {
+ struct stk_camera *dev = usb_get_intfdata(intf);
+ if (is_streaming(dev)) {
+@@ -1476,7 +1476,7 @@ int stk_camera_suspend(struct usb_interface *intf, pm_message_t message)
+ return 0;
+ }
+
+-int stk_camera_resume(struct usb_interface *intf)
++static int stk_camera_resume(struct usb_interface *intf)
+ {
+ struct stk_camera *dev = usb_get_intfdata(intf);
+ if (!is_initialised(dev))
+diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
+index 3fb85af..c109511 100644
+--- a/drivers/media/video/stradis.c
++++ b/drivers/media/video/stradis.c
+@@ -58,7 +58,7 @@
+
+ static struct saa7146 saa7146s[SAA7146_MAX];
+
+-static int saa_num = 0; /* number of SAA7146s in use */
++static int saa_num; /* number of SAA7146s in use */
+
+ static int video_nr = -1;
+ module_param(video_nr, int, 0);
+@@ -248,7 +248,7 @@ static void I2CBusScan(struct saa7146 *saa)
+ attach_inform(saa, i);
+ }
+
+-static int debiwait_maxwait = 0;
++static int debiwait_maxwait;
+
+ static int wait_for_debi_done(struct saa7146 *saa)
+ {
+@@ -1906,7 +1906,9 @@ static const struct file_operations saa_fops = {
+ .open = saa_open,
+ .release = saa_release,
+ .ioctl = saa_ioctl,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .read = saa_read,
+ .llseek = no_llseek,
+ .write = saa_write,
+diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c
+index afc32aa..d7f130b 100644
+--- a/drivers/media/video/stv680.c
++++ b/drivers/media/video/stv680.c
+@@ -72,15 +72,18 @@
+ #include "stv680.h"
+
+ static int video_nr = -1;
+-static int swapRGB = 0; /* default for auto sleect */
+-static int swapRGB_on = 0; /* default to allow auto select; -1=swap never, +1= swap always */
+
+-static unsigned int debug = 0;
++static int swapRGB; /* 0 = default for auto select */
++
++/* 0 = default to allow auto select; -1 = swap never, +1 = swap always */
++static int swapRGB_on;
++
++static unsigned int debug;
+
+ #define PDEBUG(level, fmt, args...) \
+ do { \
+ if (debug >= level) \
+- info("[%s:%d] " fmt, __FUNCTION__, __LINE__ , ## args); \
++ info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \
+ } while (0)
+
+
+@@ -1391,7 +1394,9 @@ static const struct file_operations stv680_fops = {
+ .read = stv680_read,
+ .mmap = stv680_mmap,
+ .ioctl = stv680_ioctl,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+ static struct video_device stv680_template = {
+diff --git a/drivers/media/video/tcm825x.c b/drivers/media/video/tcm825x.c
+index fb895f6..6943b44 100644
+--- a/drivers/media/video/tcm825x.c
++++ b/drivers/media/video/tcm825x.c
+@@ -906,7 +906,7 @@ static int __init tcm825x_init(void)
+ rval = i2c_add_driver(&tcm825x_i2c_driver);
+ if (rval)
+ printk(KERN_INFO "%s: failed registering " TCM825X_NAME "\n",
+- __FUNCTION__);
++ __func__);
+
+ return rval;
+ }
+diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c
+index 55bc89a..0ebb5b5 100644
+--- a/drivers/media/video/tda8290.c
++++ b/drivers/media/video/tda8290.c
+@@ -32,8 +32,6 @@ static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "enable verbose debug messages");
+
+-#define PREFIX "tda8290"
+-
+ /* ---------------------------------------------------------------------- */
+
+ struct tda8290_priv {
+@@ -174,7 +172,7 @@ static void tda8290_set_params(struct dvb_frontend *fe,
+ set_audio(fe, params);
+
+ if (priv->cfg.config)
+- tuner_dbg("tda827xa config is 0x%02x\n", *priv->cfg.config);
++ tuner_dbg("tda827xa config is 0x%02x\n", priv->cfg.config);
+ tuner_i2c_xfer_send(&priv->i2c_props, easy_mode, 2);
+ tuner_i2c_xfer_send(&priv->i2c_props, agc_out_on, 2);
+ tuner_i2c_xfer_send(&priv->i2c_props, soft_reset, 2);
+@@ -365,7 +363,7 @@ static void tda8295_set_params(struct dvb_frontend *fe,
+
+ set_audio(fe, params);
+
+- tuner_dbg("%s: freq = %d\n", __FUNCTION__, params->frequency);
++ tuner_dbg("%s: freq = %d\n", __func__, params->frequency);
+
+ tda8295_power(fe, 1);
+ tda8295_agc1_out(fe, 1);
+@@ -444,8 +442,7 @@ static void tda8290_init_if(struct dvb_frontend *fe)
+ unsigned char set_GP00_CF[] = { 0x20, 0x01 };
+ unsigned char set_GP01_CF[] = { 0x20, 0x0B };
+
+- if ((priv->cfg.config) &&
+- ((*priv->cfg.config == 1) || (*priv->cfg.config == 2)))
++ if ((priv->cfg.config == 1) || (priv->cfg.config == 2))
+ tuner_i2c_xfer_send(&priv->i2c_props, set_GP00_CF, 2);
+ else
+ tuner_i2c_xfer_send(&priv->i2c_props, set_GP01_CF, 2);
+@@ -590,8 +587,8 @@ static int tda829x_find_tuner(struct dvb_frontend *fe)
+ else
+ priv->ver |= TDA8275A;
+
+- tda827x_attach(fe, priv->tda827x_addr,
+- priv->i2c_props.adap, &priv->cfg);
++ tda827x_attach(fe, priv->tda827x_addr, priv->i2c_props.adap, &priv->cfg);
++ priv->cfg.switch_addr = priv->i2c_props.addr;
+ }
+ if (fe->ops.tuner_ops.init)
+ fe->ops.tuner_ops.init(fe);
+@@ -616,7 +613,7 @@ static int tda8290_probe(struct tuner_i2c_props *i2c_props)
+ if (tda8290_id[1] == TDA8290_ID) {
+ if (debug)
+ printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n",
+- __FUNCTION__, i2c_adapter_id(i2c_props->adap),
++ __func__, i2c_adapter_id(i2c_props->adap),
+ i2c_props->addr);
+ return 0;
+ }
+@@ -636,7 +633,7 @@ static int tda8295_probe(struct tuner_i2c_props *i2c_props)
+ if (tda8295_id[1] == TDA8295_ID) {
+ if (debug)
+ printk(KERN_DEBUG "%s: tda8295 detected @ %d-%04x\n",
+- __FUNCTION__, i2c_adapter_id(i2c_props->adap),
++ __func__, i2c_adapter_id(i2c_props->adap),
+ i2c_props->addr);
+ return 0;
+ }
+@@ -674,6 +671,7 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
+
+ priv->i2c_props.addr = i2c_addr;
+ priv->i2c_props.adap = i2c_adap;
++ priv->i2c_props.name = "tda829x";
+ if (cfg) {
+ priv->cfg.config = cfg->lna_cfg;
+ priv->cfg.tuner_callback = cfg->tuner_callback;
+diff --git a/drivers/media/video/tda8290.h b/drivers/media/video/tda8290.h
+index dc8ef31..d3bbf27 100644
+--- a/drivers/media/video/tda8290.h
++++ b/drivers/media/video/tda8290.h
+@@ -21,7 +21,7 @@
+ #include "dvb_frontend.h"
+
+ struct tda829x_config {
+- unsigned int *lna_cfg;
++ unsigned int lna_cfg;
+ int (*tuner_callback) (void *dev, int command, int arg);
+
+ unsigned int probe_tuner:1;
+@@ -39,7 +39,7 @@ extern struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
+ #else
+ static inline int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return -EINVAL;
+ }
+
+@@ -49,7 +49,7 @@ static inline struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
+ struct tda829x_config *cfg)
+ {
+ printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
+- __FUNCTION__);
++ __func__);
+ return NULL;
+ }
+ #endif
+diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c
+index bdca5d2..0cee002 100644
+--- a/drivers/media/video/tda9840.c
++++ b/drivers/media/video/tda9840.c
+@@ -31,11 +31,11 @@
+
+ #include "tda9840.h"
+
+-static int debug = 0; /* insmod parameter */
++static int debug; /* insmod parameter */
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
+ #define dprintk(args...) \
+- do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
++ do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0)
+
+ #define SWITCH 0x00
+ #define LEVEL_ADJUST 0x02
+diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
+index 106c93b..a0545ba 100644
+--- a/drivers/media/video/tda9887.c
++++ b/drivers/media/video/tda9887.c
+@@ -25,10 +25,12 @@ static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "enable verbose debug messages");
+
+-#define PREFIX "tda9887"
++static DEFINE_MUTEX(tda9887_list_mutex);
++static LIST_HEAD(hybrid_tuner_instance_list);
+
+ struct tda9887_priv {
+ struct tuner_i2c_props i2c_props;
++ struct list_head hybrid_tuner_instance_list;
+
+ unsigned char data[4];
+ unsigned int config;
+@@ -644,7 +646,15 @@ static int tda9887_set_config(struct dvb_frontend *fe, void *priv_cfg)
+
+ static void tda9887_release(struct dvb_frontend *fe)
+ {
+- kfree(fe->analog_demod_priv);
++ struct tda9887_priv *priv = fe->analog_demod_priv;
++
++ mutex_lock(&tda9887_list_mutex);
++
++ if (priv)
++ hybrid_tuner_release_state(priv);
++
++ mutex_unlock(&tda9887_list_mutex);
++
+ fe->analog_demod_priv = NULL;
+ }
+
+@@ -665,17 +675,29 @@ struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
+ u8 i2c_addr)
+ {
+ struct tda9887_priv *priv = NULL;
++ int instance;
+
+- priv = kzalloc(sizeof(struct tda9887_priv), GFP_KERNEL);
+- if (priv == NULL)
+- return NULL;
+- fe->analog_demod_priv = priv;
++ mutex_lock(&tda9887_list_mutex);
+
+- priv->i2c_props.addr = i2c_addr;
+- priv->i2c_props.adap = i2c_adap;
+- priv->mode = T_STANDBY;
++ instance = hybrid_tuner_request_state(struct tda9887_priv, priv,
++ hybrid_tuner_instance_list,
++ i2c_adap, i2c_addr, "tda9887");
++ switch (instance) {
++ case 0:
++ mutex_unlock(&tda9887_list_mutex);
++ return NULL;
++ break;
++ case 1:
++ fe->analog_demod_priv = priv;
++ priv->mode = T_STANDBY;
++ tuner_info("tda988[5/6/7] found\n");
++ break;
++ default:
++ fe->analog_demod_priv = priv;
++ break;
++ }
+
+- tuner_info("tda988[5/6/7] found\n");
++ mutex_unlock(&tda9887_list_mutex);
+
+ memcpy(&fe->ops.analog_ops, &tda9887_ops,
+ sizeof(struct analog_demod_ops));
+diff --git a/drivers/media/video/tda9887.h b/drivers/media/video/tda9887.h
+index 8f873a8..be49dcb 100644
+--- a/drivers/media/video/tda9887.h
++++ b/drivers/media/video/tda9887.h
+@@ -30,7 +30,7 @@ static inline struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c_adap,
+ u8 i2c_addr)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif
+diff --git a/drivers/media/video/tea5761.c b/drivers/media/video/tea5761.c
+index 5326eec..b93cdef 100644
+--- a/drivers/media/video/tea5761.c
++++ b/drivers/media/video/tea5761.c
+@@ -14,12 +14,10 @@
+ #include "tuner-i2c.h"
+ #include "tea5761.h"
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "enable verbose debug messages");
+
+-#define PREFIX "tea5761"
+-
+ struct tea5761_priv {
+ struct tuner_i2c_props i2c_props;
+
+@@ -131,7 +129,7 @@ static void tea5761_status_dump(unsigned char *buffer)
+
+ frq = 1000 * (div * 32768 / 1000 + FREQ_OFFSET + 225) / 4; /* Freq in KHz */
+
+- printk(PREFIX "Frequency %d.%03d KHz (divider = 0x%04x)\n",
++ printk(KERN_INFO "tea5761: Frequency %d.%03d KHz (divider = 0x%04x)\n",
+ frq / 1000, frq % 1000, div);
+ }
+
+@@ -249,14 +247,19 @@ int tea5761_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
+
+ if (16 != (rc = tuner_i2c_xfer_recv(&i2c, buffer, 16))) {
+ printk(KERN_WARNING "it is not a TEA5761. Received %i chars.\n", rc);
+- return EINVAL;
++ return -EINVAL;
+ }
+
+- if (!((buffer[13] != 0x2b) || (buffer[14] != 0x57) || (buffer[15] != 0x061))) {
+- printk(KERN_WARNING "Manufacturer ID= 0x%02x, Chip ID = %02x%02x. It is not a TEA5761\n",buffer[13],buffer[14],buffer[15]);
+- return EINVAL;
++ if ((buffer[13] != 0x2b) || (buffer[14] != 0x57) || (buffer[15] != 0x061)) {
++ printk(KERN_WARNING "Manufacturer ID= 0x%02x, Chip ID = %02x%02x."
++ " It is not a TEA5761\n",
++ buffer[13], buffer[14], buffer[15]);
++ return -EINVAL;
+ }
+- printk(KERN_WARNING "TEA5761 detected.\n");
++ printk(KERN_WARNING "tea5761: TEA%02x%02x detected. "
++ "Manufacturer ID= 0x%02x\n",
++ buffer[14], buffer[15], buffer[13]);
++
+ return 0;
+ }
+
+@@ -302,6 +305,7 @@ struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
+
+ priv->i2c_props.addr = i2c_addr;
+ priv->i2c_props.adap = i2c_adap;
++ priv->i2c_props.name = "tea5761";
+
+ memcpy(&fe->ops.tuner_ops, &tea5761_tuner_ops,
+ sizeof(struct dvb_tuner_ops));
+diff --git a/drivers/media/video/tea5761.h b/drivers/media/video/tea5761.h
+index 73a03b4..8eb6272 100644
+--- a/drivers/media/video/tea5761.h
++++ b/drivers/media/video/tea5761.h
+@@ -31,7 +31,7 @@ static inline int tea5761_autodetection(struct i2c_adapter* i2c_adap,
+ u8 i2c_addr)
+ {
+ printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
+- __FUNCTION__);
++ __func__);
+ return -EINVAL;
+ }
+
+@@ -39,7 +39,7 @@ static inline struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
+ struct i2c_adapter* i2c_adap,
+ u8 i2c_addr)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif
+diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c
+index e1b48d8..f6e7d7a 100644
+--- a/drivers/media/video/tea5767.c
++++ b/drivers/media/video/tea5767.c
+@@ -16,12 +16,10 @@
+ #include "tuner-i2c.h"
+ #include "tea5767.h"
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "enable verbose debug messages");
+
+-#define PREFIX "tea5767"
+-
+ /*****************************************************************************/
+
+ struct tea5767_priv {
+@@ -137,14 +135,14 @@ static void tea5767_status_dump(struct tea5767_priv *priv,
+ unsigned int div, frq;
+
+ if (TEA5767_READY_FLAG_MASK & buffer[0])
+- printk(PREFIX "Ready Flag ON\n");
++ tuner_info("Ready Flag ON\n");
+ else
+- printk(PREFIX "Ready Flag OFF\n");
++ tuner_info("Ready Flag OFF\n");
+
+ if (TEA5767_BAND_LIMIT_MASK & buffer[0])
+- printk(PREFIX "Tuner at band limit\n");
++ tuner_info("Tuner at band limit\n");
+ else
+- printk(PREFIX "Tuner not at band limit\n");
++ tuner_info("Tuner not at band limit\n");
+
+ div = ((buffer[0] & 0x3f) << 8) | buffer[1];
+
+@@ -166,23 +164,23 @@ static void tea5767_status_dump(struct tea5767_priv *priv,
+ buffer[0] = (div >> 8) & 0x3f;
+ buffer[1] = div & 0xff;
+
+- printk(PREFIX "Frequency %d.%03d KHz (divider = 0x%04x)\n",
+- frq / 1000, frq % 1000, div);
++ tuner_info("Frequency %d.%03d KHz (divider = 0x%04x)\n",
++ frq / 1000, frq % 1000, div);
+
+ if (TEA5767_STEREO_MASK & buffer[2])
+- printk(PREFIX "Stereo\n");
++ tuner_info("Stereo\n");
+ else
+- printk(PREFIX "Mono\n");
++ tuner_info("Mono\n");
+
+- printk(PREFIX "IF Counter = %d\n", buffer[2] & TEA5767_IF_CNTR_MASK);
++ tuner_info("IF Counter = %d\n", buffer[2] & TEA5767_IF_CNTR_MASK);
+
+- printk(PREFIX "ADC Level = %d\n",
+- (buffer[3] & TEA5767_ADC_LEVEL_MASK) >> 4);
++ tuner_info("ADC Level = %d\n",
++ (buffer[3] & TEA5767_ADC_LEVEL_MASK) >> 4);
+
+- printk(PREFIX "Chip ID = %d\n", (buffer[3] & TEA5767_CHIP_ID_MASK));
++ tuner_info("Chip ID = %d\n", (buffer[3] & TEA5767_CHIP_ID_MASK));
+
+- printk(PREFIX "Reserved = 0x%02x\n",
+- (buffer[4] & TEA5767_RESERVED_MASK));
++ tuner_info("Reserved = 0x%02x\n",
++ (buffer[4] & TEA5767_RESERVED_MASK));
+ }
+
+ /* Freq should be specifyed at 62.5 Hz */
+@@ -395,11 +393,6 @@ int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
+ return EINVAL;
+ }
+
+- /* It seems that tea5767 returns 0xff after the 5th byte */
+- if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) {
+- printk(KERN_WARNING "Returned more than 5 bytes. It is not a TEA5767\n");
+- return EINVAL;
+- }
+
+ return 0;
+ }
+@@ -456,6 +449,8 @@ struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
+
+ priv->i2c_props.addr = i2c_addr;
+ priv->i2c_props.adap = i2c_adap;
++ priv->i2c_props.name = "tea5767";
++
+ priv->ctrl.xtal_freq = TEA5767_HIGH_LO_32768;
+ priv->ctrl.port1 = 1;
+ priv->ctrl.port2 = 1;
+diff --git a/drivers/media/video/tea5767.h b/drivers/media/video/tea5767.h
+index a44451f..7b547c0 100644
+--- a/drivers/media/video/tea5767.h
++++ b/drivers/media/video/tea5767.h
+@@ -50,7 +50,7 @@ static inline int tea5767_autodetection(struct i2c_adapter* i2c_adap,
+ u8 i2c_addr)
+ {
+ printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
+- __FUNCTION__);
++ __func__);
+ return -EINVAL;
+ }
+
+@@ -58,7 +58,7 @@ static inline struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
+ struct i2c_adapter* i2c_adap,
+ u8 i2c_addr)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif
+diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c
+index df2fad9..9513d86 100644
+--- a/drivers/media/video/tea6415c.c
++++ b/drivers/media/video/tea6415c.c
+@@ -33,11 +33,11 @@
+
+ #include "tea6415c.h"
+
+-static int debug = 0; /* insmod parameter */
++static int debug; /* insmod parameter */
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
+ #define dprintk(args...) \
+- do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
++ do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0)
+
+ #define TEA6415C_NUM_INPUTS 8
+ #define TEA6415C_NUM_OUTPUTS 6
+diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c
+index 4ff6c63..7fd5336 100644
+--- a/drivers/media/video/tea6420.c
++++ b/drivers/media/video/tea6420.c
+@@ -33,11 +33,11 @@
+
+ #include "tea6420.h"
+
+-static int debug = 0; /* insmod parameter */
++static int debug; /* insmod parameter */
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
+ #define dprintk(args...) \
+- do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
++ do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0)
+
+ /* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */
+ static unsigned short normal_i2c[] = { I2C_ADDR_TEA6420_1, I2C_ADDR_TEA6420_2, I2C_CLIENT_END };
+diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
+index 78a09a2..2b72e10 100644
+--- a/drivers/media/video/tuner-core.c
++++ b/drivers/media/video/tuner-core.c
+@@ -68,9 +68,9 @@ static unsigned short normal_i2c[] = {
+ I2C_CLIENT_INSMOD;
+
+ /* insmod options used at init time => read/only */
+-static unsigned int addr = 0;
+-static unsigned int no_autodetect = 0;
+-static unsigned int show_i2c = 0;
++static unsigned int addr;
++static unsigned int no_autodetect;
++static unsigned int show_i2c;
+
+ /* insmod options used at runtime => read/write */
+ static int tuner_debug;
+@@ -313,24 +313,14 @@ static void tuner_i2c_address_check(struct tuner *t)
+ tuner_warn("output to v4l-dvb-maintainer at linuxtv.org\n");
+ tuner_warn("Please use subject line: \"obsolete tuner i2c address.\"\n");
+ tuner_warn("driver: %s, addr: 0x%02x, type: %d (%s)\n",
+- t->i2c->adapter->name, t->i2c->addr, t->type,
+- tuners[t->type].name);
++ t->i2c->adapter->name, t->i2c->addr, t->type, t->i2c->name);
+ tuner_warn("====================== WARNING! ======================\n");
+ }
+
+-static void attach_simple_tuner(struct tuner *t)
+-{
+- struct simple_tuner_config cfg = {
+- .type = t->type,
+- .tun = &tuners[t->type]
+- };
+- simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg);
+-}
+-
+ static void attach_tda829x(struct tuner *t)
+ {
+ struct tda829x_config cfg = {
+- .lna_cfg = &t->config,
++ .lna_cfg = t->config,
+ .tuner_callback = t->tuner_callback,
+ };
+ tda829x_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg);
+@@ -352,11 +342,6 @@ static void set_type(struct i2c_client *c, unsigned int type,
+ return;
+ }
+
+- if (type >= tuner_count) {
+- tuner_warn ("tuner 0x%02x: Tuner count greater than %d\n",c->addr,tuner_count);
+- return;
+- }
+-
+ t->type = type;
+ t->config = new_config;
+ if (tuner_callback != NULL) {
+@@ -384,19 +369,13 @@ static void set_type(struct i2c_client *c, unsigned int type,
+ break;
+ }
+ case TUNER_TEA5767:
+- if (tea5767_attach(&t->fe, t->i2c->adapter, t->i2c->addr) == NULL) {
+- t->type = TUNER_ABSENT;
+- t->mode_mask = T_UNINITIALIZED;
+- return;
+- }
++ if (!tea5767_attach(&t->fe, t->i2c->adapter, t->i2c->addr))
++ goto attach_failed;
+ t->mode_mask = T_RADIO;
+ break;
+ case TUNER_TEA5761:
+- if (tea5761_attach(&t->fe, t->i2c->adapter, t->i2c->addr) == NULL) {
+- t->type = TUNER_ABSENT;
+- t->mode_mask = T_UNINITIALIZED;
+- return;
+- }
++ if (!tea5761_attach(&t->fe, t->i2c->adapter, t->i2c->addr))
++ goto attach_failed;
+ t->mode_mask = T_RADIO;
+ break;
+ case TUNER_PHILIPS_FMD1216ME_MK3:
+@@ -409,7 +388,9 @@ static void set_type(struct i2c_client *c, unsigned int type,
+ buffer[2] = 0x86;
+ buffer[3] = 0x54;
+ i2c_master_send(c, buffer, 4);
+- attach_simple_tuner(t);
++ if (!simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr,
++ t->type))
++ goto attach_failed;
+ break;
+ case TUNER_PHILIPS_TD1316:
+ buffer[0] = 0x0b;
+@@ -417,45 +398,45 @@ static void set_type(struct i2c_client *c, unsigned int type,
+ buffer[2] = 0x86;
+ buffer[3] = 0xa4;
+ i2c_master_send(c,buffer,4);
+- attach_simple_tuner(t);
++ if (!simple_tuner_attach(&t->fe, t->i2c->adapter,
++ t->i2c->addr, t->type))
++ goto attach_failed;
+ break;
+ case TUNER_XC2028:
+ {
+ struct xc2028_config cfg = {
+ .i2c_adap = t->i2c->adapter,
+ .i2c_addr = t->i2c->addr,
+- .video_dev = c->adapter->algo_data,
+ .callback = t->tuner_callback,
+ };
+- if (!xc2028_attach(&t->fe, &cfg)) {
+- t->type = TUNER_ABSENT;
+- t->mode_mask = T_UNINITIALIZED;
+- return;
+- }
++ if (!xc2028_attach(&t->fe, &cfg))
++ goto attach_failed;
+ break;
+ }
+ case TUNER_TDA9887:
+ tda9887_attach(&t->fe, t->i2c->adapter, t->i2c->addr);
+ break;
+ case TUNER_XC5000:
++ {
++ struct dvb_tuner_ops *xc_tuner_ops;
++
+ xc5000_cfg.i2c_address = t->i2c->addr;
+ xc5000_cfg.if_khz = 5380;
+ xc5000_cfg.priv = c->adapter->algo_data;
+ xc5000_cfg.tuner_callback = t->tuner_callback;
+- if (!xc5000_attach(&t->fe, t->i2c->adapter, &xc5000_cfg)) {
+- t->type = TUNER_ABSENT;
+- t->mode_mask = T_UNINITIALIZED;
+- return;
+- }
+- {
+- struct dvb_tuner_ops *xc_tuner_ops;
++ if (!xc5000_attach(&t->fe, t->i2c->adapter, &xc5000_cfg))
++ goto attach_failed;
++
+ xc_tuner_ops = &t->fe.ops.tuner_ops;
+- if(xc_tuner_ops->init != NULL)
++ if (xc_tuner_ops->init)
+ xc_tuner_ops->init(&t->fe);
+- }
+ break;
++ }
+ default:
+- attach_simple_tuner(t);
++ if (!simple_tuner_attach(&t->fe, t->i2c->adapter,
++ t->i2c->addr, t->type))
++ goto attach_failed;
++
+ break;
+ }
+
+@@ -477,11 +458,27 @@ static void set_type(struct i2c_client *c, unsigned int type,
+ if (t->mode_mask == T_UNINITIALIZED)
+ t->mode_mask = new_mode_mask;
+
+- set_freq(c, (V4L2_TUNER_RADIO == t->mode) ? t->radio_freq : t->tv_freq);
++ /* xc2028/3028 and xc5000 requires a firmware to be set-up later
++ trying to set a frequency here will just fail
++ FIXME: better to move set_freq to the tuner code. This is needed
++ on analog tuners for PLL to properly work
++ */
++ if (t->type != TUNER_XC2028 && t->type != TUNER_XC5000)
++ set_freq(c, (V4L2_TUNER_RADIO == t->mode) ?
++ t->radio_freq : t->tv_freq);
++
+ tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
+ c->adapter->name, c->driver->driver.name, c->addr << 1, type,
+ t->mode_mask);
+ tuner_i2c_address_check(t);
++ return;
++
++attach_failed:
++ tuner_dbg("Tuner attach for type = %d failed.\n", t->type);
++ t->type = TUNER_ABSENT;
++ t->mode_mask = T_UNINITIALIZED;
++
++ return;
+ }
+
+ /*
+@@ -496,14 +493,16 @@ static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup)
+ {
+ struct tuner *t = i2c_get_clientdata(c);
+
+- tuner_dbg("set addr for type %i\n", t->type);
+-
+ if ( (t->type == UNSET && ((tun_setup->addr == ADDR_UNSET) &&
+ (t->mode_mask & tun_setup->mode_mask))) ||
+ (tun_setup->addr == c->addr)) {
+ set_type(c, tun_setup->type, tun_setup->mode_mask,
+ tun_setup->config, tun_setup->tuner_callback);
+- }
++ } else
++ tuner_dbg("set addr discarded for type %i, mask %x. "
++ "Asked to change tuner at addr 0x%02x, with mask %x\n",
++ t->type, t->mode_mask,
++ tun_setup->addr, tun_setup->mode_mask);
+ }
+
+ static inline int check_mode(struct tuner *t, char *cmd)
+@@ -759,7 +758,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
+ if (analog_ops->standby)
+ analog_ops->standby(&t->fe);
+ break;
+-#ifdef CONFIG_VIDEO_V4L1
++#ifdef CONFIG_VIDEO_ALLOW_V4L1
+ case VIDIOCSAUDIO:
+ if (check_mode(t, "VIDIOCSAUDIO") == EINVAL)
+ return 0;
+@@ -1112,8 +1111,8 @@ static int tuner_probe(struct i2c_client *client)
+ if (!no_autodetect) {
+ switch (client->addr) {
+ case 0x10:
+- if (tea5761_autodetection(t->i2c->adapter, t->i2c->addr)
+- != EINVAL) {
++ if (tea5761_autodetection(t->i2c->adapter,
++ t->i2c->addr) >= 0) {
+ t->type = TUNER_TEA5761;
+ t->mode_mask = T_RADIO;
+ t->mode = T_STANDBY;
+@@ -1125,7 +1124,7 @@ static int tuner_probe(struct i2c_client *client)
+
+ goto register_client;
+ }
+- break;
++ return -ENODEV;
+ case 0x42:
+ case 0x43:
+ case 0x4a:
+diff --git a/drivers/media/video/tuner-i2c.h b/drivers/media/video/tuner-i2c.h
+index de52e8f..3ad6c8e 100644
+--- a/drivers/media/video/tuner-i2c.h
++++ b/drivers/media/video/tuner-i2c.h
+@@ -26,6 +26,10 @@
+ struct tuner_i2c_props {
+ u8 addr;
+ struct i2c_adapter *adap;
++
++ /* used for tuner instance management */
++ int count;
++ char *name;
+ };
+
+ static inline int tuner_i2c_xfer_send(struct tuner_i2c_props *props, char *buf, int len)
+@@ -59,29 +63,111 @@ static inline int tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props,
+ return (ret == 2) ? ilen : ret;
+ }
+
+-#define tuner_warn(fmt, arg...) do { \
+- printk(KERN_WARNING "%s %d-%04x: " fmt, PREFIX, \
+- i2c_adapter_id(priv->i2c_props.adap), \
+- priv->i2c_props.addr, ##arg); \
++/* Callers must declare as a global for the module:
++ *
++ * static LIST_HEAD(hybrid_tuner_instance_list);
++ *
++ * hybrid_tuner_instance_list should be the third argument
++ * passed into hybrid_tuner_request_state().
++ *
++ * state structure must contain the following:
++ *
++ * struct list_head hybrid_tuner_instance_list;
++ * struct tuner_i2c_props i2c_props;
++ *
++ * hybrid_tuner_instance_list (both within state structure and globally)
++ * is only required if the driver is using hybrid_tuner_request_state
++ * and hybrid_tuner_release_state to manage state sharing between
++ * multiple instances of hybrid tuners.
++ */
++
++#define tuner_printk(kernlvl, i2cprops, fmt, arg...) do { \
++ printk(kernlvl "%s %d-%04x: " fmt, i2cprops.name, \
++ i2cprops.adap ? \
++ i2c_adapter_id(i2cprops.adap) : -1, \
++ i2cprops.addr, ##arg); \
+ } while (0)
+
+-#define tuner_info(fmt, arg...) do { \
+- printk(KERN_INFO "%s %d-%04x: " fmt, PREFIX, \
+- i2c_adapter_id(priv->i2c_props.adap), \
+- priv->i2c_props.addr , ##arg); \
++/* TO DO: convert all callers of these macros to pass in
++ * struct tuner_i2c_props, then remove the macro wrappers */
++
++#define __tuner_warn(i2cprops, fmt, arg...) do { \
++ tuner_printk(KERN_WARNING, i2cprops, fmt, ##arg); \
+ } while (0)
+
+-#define tuner_err(fmt, arg...) do { \
+- printk(KERN_ERR "%s %d-%04x: " fmt, PREFIX, \
+- i2c_adapter_id(priv->i2c_props.adap), \
+- priv->i2c_props.addr , ##arg); \
++#define __tuner_info(i2cprops, fmt, arg...) do { \
++ tuner_printk(KERN_INFO, i2cprops, fmt, ##arg); \
+ } while (0)
+
+-#define tuner_dbg(fmt, arg...) do { \
++#define __tuner_err(i2cprops, fmt, arg...) do { \
++ tuner_printk(KERN_ERR, i2cprops, fmt, ##arg); \
++ } while (0)
++
++#define __tuner_dbg(i2cprops, fmt, arg...) do { \
+ if ((debug)) \
+- printk(KERN_DEBUG "%s %d-%04x: " fmt, PREFIX, \
+- i2c_adapter_id(priv->i2c_props.adap), \
+- priv->i2c_props.addr , ##arg); \
++ tuner_printk(KERN_DEBUG, i2cprops, fmt, ##arg); \
+ } while (0)
+
++#define tuner_warn(fmt, arg...) __tuner_warn(priv->i2c_props, fmt, ##arg)
++#define tuner_info(fmt, arg...) __tuner_info(priv->i2c_props, fmt, ##arg)
++#define tuner_err(fmt, arg...) __tuner_err(priv->i2c_props, fmt, ##arg)
++#define tuner_dbg(fmt, arg...) __tuner_dbg(priv->i2c_props, fmt, ##arg)
++
++/****************************************************************************/
++
++/* The return value of hybrid_tuner_request_state indicates the number of
++ * instances using this tuner object.
++ *
++ * 0 - no instances, indicates an error - kzalloc must have failed
++ *
++ * 1 - one instance, indicates that the tuner object was created successfully
++ *
++ * 2 (or more) instances, indicates that an existing tuner object was found
++ */
++
++#define hybrid_tuner_request_state(type, state, list, i2cadap, i2caddr, devname)\
++({ \
++ int __ret = 0; \
++ list_for_each_entry(state, &list, hybrid_tuner_instance_list) { \
++ if (((i2cadap) && (state->i2c_props.adap)) && \
++ ((i2c_adapter_id(state->i2c_props.adap) == \
++ i2c_adapter_id(i2cadap)) && \
++ (i2caddr == state->i2c_props.addr))) { \
++ __tuner_info(state->i2c_props, \
++ "attaching existing instance\n"); \
++ state->i2c_props.count++; \
++ __ret = state->i2c_props.count; \
++ break; \
++ } \
++ } \
++ if (0 == __ret) { \
++ state = kzalloc(sizeof(type), GFP_KERNEL); \
++ if (NULL == state) \
++ goto __fail; \
++ state->i2c_props.addr = i2caddr; \
++ state->i2c_props.adap = i2cadap; \
++ state->i2c_props.name = devname; \
++ __tuner_info(state->i2c_props, \
++ "creating new instance\n"); \
++ list_add_tail(&state->hybrid_tuner_instance_list, &list);\
++ state->i2c_props.count++; \
++ __ret = state->i2c_props.count; \
++ } \
++__fail: \
++ __ret; \
++})
++
++#define hybrid_tuner_release_state(state) \
++({ \
++ int __ret; \
++ state->i2c_props.count--; \
++ __ret = state->i2c_props.count; \
++ if (!state->i2c_props.count) { \
++ __tuner_info(state->i2c_props, "destroying instance\n");\
++ list_del(&state->hybrid_tuner_instance_list); \
++ kfree(state); \
++ } \
++ __ret; \
++})
++
+ #endif /* __TUNER_I2C_H__ */
+diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c
+index c1db576..be8d903 100644
+--- a/drivers/media/video/tuner-simple.c
++++ b/drivers/media/video/tuner-simple.c
+@@ -13,15 +13,25 @@
+ #include "tuner-i2c.h"
+ #include "tuner-simple.h"
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "enable verbose debug messages");
+
+-#define PREFIX "tuner-simple"
++#define TUNER_SIMPLE_MAX 64
++static unsigned int simple_devcount;
+
+-static int offset = 0;
++static int offset;
+ module_param(offset, int, 0664);
+-MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner");
++MODULE_PARM_DESC(offset, "Allows to specify an offset for tuner");
++
++static unsigned int atv_input[TUNER_SIMPLE_MAX] = \
++ { [0 ... (TUNER_SIMPLE_MAX-1)] = 0 };
++static unsigned int dtv_input[TUNER_SIMPLE_MAX] = \
++ { [0 ... (TUNER_SIMPLE_MAX-1)] = 0 };
++module_param_array(atv_input, int, NULL, 0644);
++module_param_array(dtv_input, int, NULL, 0644);
++MODULE_PARM_DESC(atv_input, "specify atv rf input, 0 for autoselect");
++MODULE_PARM_DESC(dtv_input, "specify dtv rf input, 0 for autoselect");
+
+ /* ---------------------------------------------------------------------- */
+
+@@ -36,8 +46,8 @@ MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner");
+ */
+ #define TEMIC_SET_PAL_I 0x05
+ #define TEMIC_SET_PAL_DK 0x09
+-#define TEMIC_SET_PAL_L 0x0a // SECAM ?
+-#define TEMIC_SET_PAL_L2 0x0b // change IF !
++#define TEMIC_SET_PAL_L 0x0a /* SECAM ? */
++#define TEMIC_SET_PAL_L2 0x0b /* change IF ! */
+ #define TEMIC_SET_PAL_BG 0x0c
+
+ /* tv tuner system standard selection for Philips FQ1216ME
+@@ -90,14 +100,21 @@ MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner");
+ #define TUNER_PLL_LOCKED 0x40
+ #define TUNER_STEREO_MK3 0x04
+
++static DEFINE_MUTEX(tuner_simple_list_mutex);
++static LIST_HEAD(hybrid_tuner_instance_list);
++
+ struct tuner_simple_priv {
++ unsigned int nr;
+ u16 last_div;
++
+ struct tuner_i2c_props i2c_props;
++ struct list_head hybrid_tuner_instance_list;
+
+ unsigned int type;
+ struct tunertype *tun;
+
+ u32 frequency;
++ u32 bandwidth;
+ };
+
+ /* ---------------------------------------------------------------------- */
+@@ -107,7 +124,7 @@ static int tuner_read_status(struct dvb_frontend *fe)
+ struct tuner_simple_priv *priv = fe->tuner_priv;
+ unsigned char byte;
+
+- if (1 != tuner_i2c_xfer_recv(&priv->i2c_props,&byte,1))
++ if (1 != tuner_i2c_xfer_recv(&priv->i2c_props, &byte, 1))
+ return 0;
+
+ return byte;
+@@ -121,13 +138,13 @@ static inline int tuner_signal(const int status)
+ static inline int tuner_stereo(const int type, const int status)
+ {
+ switch (type) {
+- case TUNER_PHILIPS_FM1216ME_MK3:
+- case TUNER_PHILIPS_FM1236_MK3:
+- case TUNER_PHILIPS_FM1256_IH3:
+- case TUNER_LG_NTSC_TAPE:
+- return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
+- default:
+- return status & TUNER_STEREO;
++ case TUNER_PHILIPS_FM1216ME_MK3:
++ case TUNER_PHILIPS_FM1236_MK3:
++ case TUNER_PHILIPS_FM1256_IH3:
++ case TUNER_LG_NTSC_TAPE:
++ return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
++ default:
++ return status & TUNER_STEREO;
+ }
+ }
+
+@@ -145,7 +162,12 @@ static inline int tuner_afcstatus(const int status)
+ static int simple_get_status(struct dvb_frontend *fe, u32 *status)
+ {
+ struct tuner_simple_priv *priv = fe->tuner_priv;
+- int tuner_status = tuner_read_status(fe);
++ int tuner_status;
++
++ if (priv->i2c_props.adap == NULL)
++ return -EINVAL;
++
++ tuner_status = tuner_read_status(fe);
+
+ *status = 0;
+
+@@ -162,7 +184,12 @@ static int simple_get_status(struct dvb_frontend *fe, u32 *status)
+ static int simple_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
+ {
+ struct tuner_simple_priv *priv = fe->tuner_priv;
+- int signal = tuner_signal(tuner_read_status(fe));
++ int signal;
++
++ if (priv->i2c_props.adap == NULL)
++ return -EINVAL;
++
++ signal = tuner_signal(tuner_read_status(fe));
+
+ *strength = signal;
+
+@@ -173,174 +200,378 @@ static int simple_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
+
+ /* ---------------------------------------------------------------------- */
+
+-static int simple_set_tv_freq(struct dvb_frontend *fe,
+- struct analog_parameters *params)
++static inline char *tuner_param_name(enum param_type type)
+ {
+- struct tuner_simple_priv *priv = fe->tuner_priv;
+- u8 config, cb, tuneraddr;
+- u16 div;
+- struct tunertype *tun;
+- u8 buffer[4];
+- int rc, IFPCoff, i, j;
+- enum param_type desired_type;
+- struct tuner_params *t_params;
++ char *name;
+
+- tun = priv->tun;
++ switch (type) {
++ case TUNER_PARAM_TYPE_RADIO:
++ name = "radio";
++ break;
++ case TUNER_PARAM_TYPE_PAL:
++ name = "pal";
++ break;
++ case TUNER_PARAM_TYPE_SECAM:
++ name = "secam";
++ break;
++ case TUNER_PARAM_TYPE_NTSC:
++ name = "ntsc";
++ break;
++ case TUNER_PARAM_TYPE_DIGITAL:
++ name = "digital";
++ break;
++ default:
++ name = "unknown";
++ break;
++ }
++ return name;
++}
+
+- /* IFPCoff = Video Intermediate Frequency - Vif:
+- 940 =16*58.75 NTSC/J (Japan)
+- 732 =16*45.75 M/N STD
+- 704 =16*44 ATSC (at DVB code)
+- 632 =16*39.50 I U.K.
+- 622.4=16*38.90 B/G D/K I, L STD
+- 592 =16*37.00 D China
+- 590 =16.36.875 B Australia
+- 543.2=16*33.95 L' STD
+- 171.2=16*10.70 FM Radio (at set_radio_freq)
+- */
++static struct tuner_params *simple_tuner_params(struct dvb_frontend *fe,
++ enum param_type desired_type)
++{
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++ struct tunertype *tun = priv->tun;
++ int i;
+
+- if (params->std == V4L2_STD_NTSC_M_JP) {
+- IFPCoff = 940;
+- desired_type = TUNER_PARAM_TYPE_NTSC;
+- } else if ((params->std & V4L2_STD_MN) &&
+- !(params->std & ~V4L2_STD_MN)) {
+- IFPCoff = 732;
+- desired_type = TUNER_PARAM_TYPE_NTSC;
+- } else if (params->std == V4L2_STD_SECAM_LC) {
+- IFPCoff = 543;
+- desired_type = TUNER_PARAM_TYPE_SECAM;
+- } else {
+- IFPCoff = 623;
+- desired_type = TUNER_PARAM_TYPE_PAL;
+- }
++ for (i = 0; i < tun->count; i++)
++ if (desired_type == tun->params[i].type)
++ break;
+
+- for (j = 0; j < tun->count-1; j++) {
+- if (desired_type != tun->params[j].type)
+- continue;
+- break;
+- }
+- /* use default tuner_t_params if desired_type not available */
+- if (desired_type != tun->params[j].type) {
+- tuner_dbg("IFPCoff = %d: tuner_t_params undefined for tuner %d\n",
+- IFPCoff, priv->type);
+- j = 0;
++ /* use default tuner params if desired_type not available */
++ if (i == tun->count) {
++ tuner_dbg("desired params (%s) undefined for tuner %d\n",
++ tuner_param_name(desired_type), priv->type);
++ i = 0;
+ }
+- t_params = &tun->params[j];
++
++ tuner_dbg("using tuner params #%d (%s)\n", i,
++ tuner_param_name(tun->params[i].type));
++
++ return &tun->params[i];
++}
++
++static int simple_config_lookup(struct dvb_frontend *fe,
++ struct tuner_params *t_params,
++ int *frequency, u8 *config, u8 *cb)
++{
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++ int i;
+
+ for (i = 0; i < t_params->count; i++) {
+- if (params->frequency > t_params->ranges[i].limit)
++ if (*frequency > t_params->ranges[i].limit)
+ continue;
+ break;
+ }
+ if (i == t_params->count) {
+- tuner_dbg("TV frequency out of range (%d > %d)",
+- params->frequency, t_params->ranges[i - 1].limit);
+- params->frequency = t_params->ranges[--i].limit;
++ tuner_dbg("frequency out of range (%d > %d)\n",
++ *frequency, t_params->ranges[i - 1].limit);
++ *frequency = t_params->ranges[--i].limit;
+ }
+- config = t_params->ranges[i].config;
+- cb = t_params->ranges[i].cb;
+- /* i == 0 -> VHF_LO
+- * i == 1 -> VHF_HI
+- * i == 2 -> UHF */
+- tuner_dbg("tv: param %d, range %d\n",j,i);
++ *config = t_params->ranges[i].config;
++ *cb = t_params->ranges[i].cb;
++
++ tuner_dbg("freq = %d.%02d (%d), range = %d, "
++ "config = 0x%02x, cb = 0x%02x\n",
++ *frequency / 16, *frequency % 16 * 100 / 16, *frequency,
++ i, *config, *cb);
++
++ return i;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void simple_set_rf_input(struct dvb_frontend *fe,
++ u8 *config, u8 *cb, unsigned int rf)
++{
++ struct tuner_simple_priv *priv = fe->tuner_priv;
+
+- div=params->frequency + IFPCoff + offset;
++ switch (priv->type) {
++ case TUNER_PHILIPS_TUV1236D:
++ switch (rf) {
++ case 1:
++ *cb |= 0x08;
++ break;
++ default:
++ *cb &= ~0x08;
++ break;
++ }
++ break;
++ case TUNER_PHILIPS_FCV1236D:
++ switch (rf) {
++ case 1:
++ *cb |= 0x01;
++ break;
++ default:
++ *cb &= ~0x01;
++ break;
++ }
++ break;
++ default:
++ break;
++ }
++}
+
+- tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, Offset=%d.%02d MHz, div=%0d\n",
+- params->frequency / 16, params->frequency % 16 * 100 / 16,
+- IFPCoff / 16, IFPCoff % 16 * 100 / 16,
+- offset / 16, offset % 16 * 100 / 16,
+- div);
++static int simple_std_setup(struct dvb_frontend *fe,
++ struct analog_parameters *params,
++ u8 *config, u8 *cb)
++{
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++ u8 tuneraddr;
++ int rc;
+
+ /* tv norm specific stuff for multi-norm tuners */
+ switch (priv->type) {
+- case TUNER_PHILIPS_SECAM: // FI1216MF
++ case TUNER_PHILIPS_SECAM: /* FI1216MF */
+ /* 0x01 -> ??? no change ??? */
+ /* 0x02 -> PAL BDGHI / SECAM L */
+ /* 0x04 -> ??? PAL others / SECAM others ??? */
+- cb &= ~0x03;
+- if (params->std & V4L2_STD_SECAM_L) //also valid for V4L2_STD_SECAM
+- cb |= PHILIPS_MF_SET_STD_L;
++ *cb &= ~0x03;
++ if (params->std & V4L2_STD_SECAM_L)
++ /* also valid for V4L2_STD_SECAM */
++ *cb |= PHILIPS_MF_SET_STD_L;
+ else if (params->std & V4L2_STD_SECAM_LC)
+- cb |= PHILIPS_MF_SET_STD_LC;
++ *cb |= PHILIPS_MF_SET_STD_LC;
+ else /* V4L2_STD_B|V4L2_STD_GH */
+- cb |= PHILIPS_MF_SET_STD_BG;
++ *cb |= PHILIPS_MF_SET_STD_BG;
+ break;
+
+ case TUNER_TEMIC_4046FM5:
+- cb &= ~0x0f;
++ *cb &= ~0x0f;
+
+ if (params->std & V4L2_STD_PAL_BG) {
+- cb |= TEMIC_SET_PAL_BG;
++ *cb |= TEMIC_SET_PAL_BG;
+
+ } else if (params->std & V4L2_STD_PAL_I) {
+- cb |= TEMIC_SET_PAL_I;
++ *cb |= TEMIC_SET_PAL_I;
+
+ } else if (params->std & V4L2_STD_PAL_DK) {
+- cb |= TEMIC_SET_PAL_DK;
++ *cb |= TEMIC_SET_PAL_DK;
+
+ } else if (params->std & V4L2_STD_SECAM_L) {
+- cb |= TEMIC_SET_PAL_L;
++ *cb |= TEMIC_SET_PAL_L;
+
+ }
+ break;
+
+ case TUNER_PHILIPS_FQ1216ME:
+- cb &= ~0x0f;
++ *cb &= ~0x0f;
+
+ if (params->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) {
+- cb |= PHILIPS_SET_PAL_BGDK;
++ *cb |= PHILIPS_SET_PAL_BGDK;
+
+ } else if (params->std & V4L2_STD_PAL_I) {
+- cb |= PHILIPS_SET_PAL_I;
++ *cb |= PHILIPS_SET_PAL_I;
+
+ } else if (params->std & V4L2_STD_SECAM_L) {
+- cb |= PHILIPS_SET_PAL_L;
++ *cb |= PHILIPS_SET_PAL_L;
+
+ }
+ break;
+
+- case TUNER_PHILIPS_ATSC:
++ case TUNER_PHILIPS_FCV1236D:
+ /* 0x00 -> ATSC antenna input 1 */
+ /* 0x01 -> ATSC antenna input 2 */
+ /* 0x02 -> NTSC antenna input 1 */
+ /* 0x03 -> NTSC antenna input 2 */
+- cb &= ~0x03;
++ *cb &= ~0x03;
+ if (!(params->std & V4L2_STD_ATSC))
+- cb |= 2;
+- /* FIXME: input */
++ *cb |= 2;
+ break;
+
+ case TUNER_MICROTUNE_4042FI5:
+ /* Set the charge pump for fast tuning */
+- config |= TUNER_CHARGE_PUMP;
++ *config |= TUNER_CHARGE_PUMP;
+ break;
+
+ case TUNER_PHILIPS_TUV1236D:
++ {
+ /* 0x40 -> ATSC antenna input 1 */
+ /* 0x48 -> ATSC antenna input 2 */
+ /* 0x00 -> NTSC antenna input 1 */
+ /* 0x08 -> NTSC antenna input 2 */
+- buffer[0] = 0x14;
+- buffer[1] = 0x00;
+- buffer[2] = 0x17;
+- buffer[3] = 0x00;
+- cb &= ~0x40;
++ u8 buffer[4] = { 0x14, 0x00, 0x17, 0x00};
++ *cb &= ~0x40;
+ if (params->std & V4L2_STD_ATSC) {
+- cb |= 0x40;
++ *cb |= 0x40;
+ buffer[1] = 0x04;
+ }
+ /* set to the correct mode (analog or digital) */
+ tuneraddr = priv->i2c_props.addr;
+ priv->i2c_props.addr = 0x0a;
+- if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,&buffer[0],2)))
+- tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc);
+- if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,&buffer[2],2)))
+- tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc);
++ rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[0], 2);
++ if (2 != rc)
++ tuner_warn("i2c i/o error: rc == %d "
++ "(should be 2)\n", rc);
++ rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[2], 2);
++ if (2 != rc)
++ tuner_warn("i2c i/o error: rc == %d "
++ "(should be 2)\n", rc);
+ priv->i2c_props.addr = tuneraddr;
+- /* FIXME: input */
+ break;
+ }
++ }
++ if (atv_input[priv->nr])
++ simple_set_rf_input(fe, config, cb, atv_input[priv->nr]);
++
++ return 0;
++}
++
++static int simple_post_tune(struct dvb_frontend *fe, u8 *buffer,
++ u16 div, u8 config, u8 cb)
++{
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++ int rc;
++
++ switch (priv->type) {
++ case TUNER_LG_TDVS_H06XF:
++ /* Set the Auxiliary Byte. */
++ buffer[0] = buffer[2];
++ buffer[0] &= ~0x20;
++ buffer[0] |= 0x18;
++ buffer[1] = 0x20;
++ tuner_dbg("tv 0x%02x 0x%02x\n", buffer[0], buffer[1]);
++
++ rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 2);
++ if (2 != rc)
++ tuner_warn("i2c i/o error: rc == %d "
++ "(should be 2)\n", rc);
++ break;
++ case TUNER_MICROTUNE_4042FI5:
++ {
++ /* FIXME - this may also work for other tuners */
++ unsigned long timeout = jiffies + msecs_to_jiffies(1);
++ u8 status_byte = 0;
++
++ /* Wait until the PLL locks */
++ for (;;) {
++ if (time_after(jiffies, timeout))
++ return 0;
++ rc = tuner_i2c_xfer_recv(&priv->i2c_props,
++ &status_byte, 1);
++ if (1 != rc) {
++ tuner_warn("i2c i/o read error: rc == %d "
++ "(should be 1)\n", rc);
++ break;
++ }
++ if (status_byte & TUNER_PLL_LOCKED)
++ break;
++ udelay(10);
++ }
++
++ /* Set the charge pump for optimized phase noise figure */
++ config &= ~TUNER_CHARGE_PUMP;
++ buffer[0] = (div>>8) & 0x7f;
++ buffer[1] = div & 0xff;
++ buffer[2] = config;
++ buffer[3] = cb;
++ tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
++ buffer[0], buffer[1], buffer[2], buffer[3]);
++
++ rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
++ if (4 != rc)
++ tuner_warn("i2c i/o error: rc == %d "
++ "(should be 4)\n", rc);
++ break;
++ }
++ }
++
++ return 0;
++}
++
++static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer)
++{
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++
++ switch (priv->type) {
++ case TUNER_TENA_9533_DI:
++ case TUNER_YMEC_TVF_5533MF:
++ tuner_dbg("This tuner doesn't have FM. "
++ "Most cards have a TEA5767 for FM\n");
++ return 0;
++ case TUNER_PHILIPS_FM1216ME_MK3:
++ case TUNER_PHILIPS_FM1236_MK3:
++ case TUNER_PHILIPS_FMD1216ME_MK3:
++ case TUNER_LG_NTSC_TAPE:
++ case TUNER_PHILIPS_FM1256_IH3:
++ buffer[3] = 0x19;
++ break;
++ case TUNER_TNF_5335MF:
++ buffer[3] = 0x11;
++ break;
++ case TUNER_LG_PAL_FM:
++ buffer[3] = 0xa5;
++ break;
++ case TUNER_THOMSON_DTT761X:
++ buffer[3] = 0x39;
++ break;
++ case TUNER_MICROTUNE_4049FM5:
++ default:
++ buffer[3] = 0xa4;
++ break;
++ }
++
++ return 0;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int simple_set_tv_freq(struct dvb_frontend *fe,
++ struct analog_parameters *params)
++{
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++ u8 config, cb;
++ u16 div;
++ struct tunertype *tun;
++ u8 buffer[4];
++ int rc, IFPCoff, i;
++ enum param_type desired_type;
++ struct tuner_params *t_params;
++
++ tun = priv->tun;
++
++ /* IFPCoff = Video Intermediate Frequency - Vif:
++ 940 =16*58.75 NTSC/J (Japan)
++ 732 =16*45.75 M/N STD
++ 704 =16*44 ATSC (at DVB code)
++ 632 =16*39.50 I U.K.
++ 622.4=16*38.90 B/G D/K I, L STD
++ 592 =16*37.00 D China
++ 590 =16.36.875 B Australia
++ 543.2=16*33.95 L' STD
++ 171.2=16*10.70 FM Radio (at set_radio_freq)
++ */
++
++ if (params->std == V4L2_STD_NTSC_M_JP) {
++ IFPCoff = 940;
++ desired_type = TUNER_PARAM_TYPE_NTSC;
++ } else if ((params->std & V4L2_STD_MN) &&
++ !(params->std & ~V4L2_STD_MN)) {
++ IFPCoff = 732;
++ desired_type = TUNER_PARAM_TYPE_NTSC;
++ } else if (params->std == V4L2_STD_SECAM_LC) {
++ IFPCoff = 543;
++ desired_type = TUNER_PARAM_TYPE_SECAM;
++ } else {
++ IFPCoff = 623;
++ desired_type = TUNER_PARAM_TYPE_PAL;
++ }
++
++ t_params = simple_tuner_params(fe, desired_type);
++
++ i = simple_config_lookup(fe, t_params, ¶ms->frequency,
++ &config, &cb);
++
++ div = params->frequency + IFPCoff + offset;
++
++ tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, "
++ "Offset=%d.%02d MHz, div=%0d\n",
++ params->frequency / 16, params->frequency % 16 * 100 / 16,
++ IFPCoff / 16, IFPCoff % 16 * 100 / 16,
++ offset / 16, offset % 16 * 100 / 16, div);
++
++ /* tv norm specific stuff for multi-norm tuners */
++ simple_std_setup(fe, params, &config, &cb);
+
+ if (t_params->cb_first_if_lower_freq && div < priv->last_div) {
+ buffer[0] = config;
+@@ -357,8 +588,10 @@ static int simple_set_tv_freq(struct dvb_frontend *fe,
+ if (t_params->has_tda9887) {
+ struct v4l2_priv_tun_config tda9887_cfg;
+ int config = 0;
+- int is_secam_l = (params->std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) &&
+- !(params->std & ~(V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC));
++ int is_secam_l = (params->std & (V4L2_STD_SECAM_L |
++ V4L2_STD_SECAM_LC)) &&
++ !(params->std & ~(V4L2_STD_SECAM_L |
++ V4L2_STD_SECAM_LC));
+
+ tda9887_cfg.tuner = TUNER_TDA9887;
+ tda9887_cfg.priv = &config;
+@@ -368,8 +601,7 @@ static int simple_set_tv_freq(struct dvb_frontend *fe,
+ config |= TDA9887_PORT1_ACTIVE;
+ if (t_params->port2_active ^ t_params->port2_invert_for_secam_lc)
+ config |= TDA9887_PORT2_ACTIVE;
+- }
+- else {
++ } else {
+ if (t_params->port1_active)
+ config |= TDA9887_PORT1_ACTIVE;
+ if (t_params->port2_active)
+@@ -384,8 +616,7 @@ static int simple_set_tv_freq(struct dvb_frontend *fe,
+ config |= TDA9887_TOP(t_params->default_top_secam_mid);
+ else if (t_params->default_top_secam_high)
+ config |= TDA9887_TOP(t_params->default_top_secam_high);
+- }
+- else {
++ } else {
+ if (i == 0 && t_params->default_top_low)
+ config |= TDA9887_TOP(t_params->default_top_low);
+ else if (i == 1 && t_params->default_top_mid)
+@@ -399,56 +630,14 @@ static int simple_set_tv_freq(struct dvb_frontend *fe,
+ &tda9887_cfg);
+ }
+ tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
+- buffer[0],buffer[1],buffer[2],buffer[3]);
+-
+- if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4)))
+- tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
+-
+- switch (priv->type) {
+- case TUNER_LG_TDVS_H06XF:
+- /* Set the Auxiliary Byte. */
+- buffer[0] = buffer[2];
+- buffer[0] &= ~0x20;
+- buffer[0] |= 0x18;
+- buffer[1] = 0x20;
+- tuner_dbg("tv 0x%02x 0x%02x\n",buffer[0],buffer[1]);
+-
+- if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,2)))
+- tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc);
+- break;
+- case TUNER_MICROTUNE_4042FI5:
+- {
+- // FIXME - this may also work for other tuners
+- unsigned long timeout = jiffies + msecs_to_jiffies(1);
+- u8 status_byte = 0;
++ buffer[0], buffer[1], buffer[2], buffer[3]);
+
+- /* Wait until the PLL locks */
+- for (;;) {
+- if (time_after(jiffies,timeout))
+- return 0;
+- if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,&status_byte,1))) {
+- tuner_warn("i2c i/o read error: rc == %d (should be 1)\n",rc);
+- break;
+- }
+- if (status_byte & TUNER_PLL_LOCKED)
+- break;
+- udelay(10);
+- }
++ rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
++ if (4 != rc)
++ tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc);
+
+- /* Set the charge pump for optimized phase noise figure */
+- config &= ~TUNER_CHARGE_PUMP;
+- buffer[0] = (div>>8) & 0x7f;
+- buffer[1] = div & 0xff;
+- buffer[2] = config;
+- buffer[3] = cb;
+- tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
+- buffer[0],buffer[1],buffer[2],buffer[3]);
++ simple_post_tune(fe, &buffer[0], div, config, cb);
+
+- if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4)))
+- tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
+- break;
+- }
+- }
+ return 0;
+ }
+
+@@ -483,37 +672,13 @@ static int simple_set_radio_freq(struct dvb_frontend *fe,
+ freq += (unsigned int)(41.3*16000);
+ break;
+ default:
+- tuner_warn("Unsupported radio_if value %d\n", t_params->radio_if);
++ tuner_warn("Unsupported radio_if value %d\n",
++ t_params->radio_if);
+ return 0;
+ }
+
+ /* Bandswitch byte */
+- switch (priv->type) {
+- case TUNER_TENA_9533_DI:
+- case TUNER_YMEC_TVF_5533MF:
+- tuner_dbg("This tuner doesn't have FM. Most cards have a TEA5767 for FM\n");
+- return 0;
+- case TUNER_PHILIPS_FM1216ME_MK3:
+- case TUNER_PHILIPS_FM1236_MK3:
+- case TUNER_PHILIPS_FMD1216ME_MK3:
+- case TUNER_LG_NTSC_TAPE:
+- case TUNER_PHILIPS_FM1256_IH3:
+- buffer[3] = 0x19;
+- break;
+- case TUNER_TNF_5335MF:
+- buffer[3] = 0x11;
+- break;
+- case TUNER_LG_PAL_FM:
+- buffer[3] = 0xa5;
+- break;
+- case TUNER_THOMSON_DTT761X:
+- buffer[3] = 0x39;
+- break;
+- case TUNER_MICROTUNE_4049FM5:
+- default:
+- buffer[3] = 0xa4;
+- break;
+- }
++ simple_radio_bandswitch(fe, &buffer[0]);
+
+ buffer[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) |
+ TUNER_RATIO_SELECT_50; /* 50 kHz step */
+@@ -534,7 +699,7 @@ static int simple_set_radio_freq(struct dvb_frontend *fe,
+ }
+
+ tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n",
+- buffer[0],buffer[1],buffer[2],buffer[3]);
++ buffer[0], buffer[1], buffer[2], buffer[3]);
+ priv->last_div = div;
+
+ if (t_params->has_tda9887) {
+@@ -544,9 +709,11 @@ static int simple_set_radio_freq(struct dvb_frontend *fe,
+ tda9887_cfg.tuner = TUNER_TDA9887;
+ tda9887_cfg.priv = &config;
+
+- if (t_params->port1_active && !t_params->port1_fm_high_sensitivity)
++ if (t_params->port1_active &&
++ !t_params->port1_fm_high_sensitivity)
+ config |= TDA9887_PORT1_ACTIVE;
+- if (t_params->port2_active && !t_params->port2_fm_high_sensitivity)
++ if (t_params->port2_active &&
++ !t_params->port2_fm_high_sensitivity)
+ config |= TDA9887_PORT2_ACTIVE;
+ if (t_params->intercarrier_mode)
+ config |= TDA9887_INTERCARRIER;
+@@ -557,10 +724,11 @@ static int simple_set_radio_freq(struct dvb_frontend *fe,
+ if (t_params->radio_if == 2)
+ config |= TDA9887_RIF_41_3;
+ i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG,
+- &tda9887_cfg);
++ &tda9887_cfg);
+ }
+- if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4)))
+- tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
++ rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
++ if (4 != rc)
++ tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc);
+
+ return 0;
+ }
+@@ -571,6 +739,9 @@ static int simple_set_params(struct dvb_frontend *fe,
+ struct tuner_simple_priv *priv = fe->tuner_priv;
+ int ret = -EINVAL;
+
++ if (priv->i2c_props.adap == NULL)
++ return -EINVAL;
++
+ switch (params->mode) {
+ case V4L2_TUNER_RADIO:
+ ret = simple_set_radio_freq(fe, params);
+@@ -582,14 +753,210 @@ static int simple_set_params(struct dvb_frontend *fe,
+ priv->frequency = params->frequency * 62500;
+ break;
+ }
++ priv->bandwidth = 0;
+
+ return ret;
+ }
+
++static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf,
++ const struct dvb_frontend_parameters *params)
++{
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++
++ switch (priv->type) {
++ case TUNER_PHILIPS_FMD1216ME_MK3:
++ if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ &&
++ params->frequency >= 158870000)
++ buf[3] |= 0x08;
++ break;
++ case TUNER_PHILIPS_TD1316:
++ /* determine band */
++ buf[3] |= (params->frequency < 161000000) ? 1 :
++ (params->frequency < 444000000) ? 2 : 4;
++
++ /* setup PLL filter */
++ if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
++ buf[3] |= 1 << 3;
++ break;
++ case TUNER_PHILIPS_TUV1236D:
++ case TUNER_PHILIPS_FCV1236D:
++ {
++ unsigned int new_rf;
++
++ if (dtv_input[priv->nr])
++ new_rf = dtv_input[priv->nr];
++ else
++ switch (params->u.vsb.modulation) {
++ case QAM_64:
++ case QAM_256:
++ new_rf = 1;
++ break;
++ case VSB_8:
++ default:
++ new_rf = 0;
++ break;
++ }
++ simple_set_rf_input(fe, &buf[2], &buf[3], new_rf);
++ break;
++ }
++ default:
++ break;
++ }
++}
++
++static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf,
++ const struct dvb_frontend_parameters *params)
++{
++ /* This function returns the tuned frequency on success, 0 on error */
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++ struct tunertype *tun = priv->tun;
++ static struct tuner_params *t_params;
++ u8 config, cb;
++ u32 div;
++ int ret, frequency = params->frequency / 62500;
++
++ t_params = simple_tuner_params(fe, TUNER_PARAM_TYPE_DIGITAL);
++ ret = simple_config_lookup(fe, t_params, &frequency, &config, &cb);
++ if (ret < 0)
++ return 0; /* failure */
++
++ div = ((frequency + t_params->iffreq) * 62500 + offset +
++ tun->stepsize/2) / tun->stepsize;
++
++ buf[0] = div >> 8;
++ buf[1] = div & 0xff;
++ buf[2] = config;
++ buf[3] = cb;
++
++ simple_set_dvb(fe, buf, params);
++
++ tuner_dbg("%s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",
++ tun->name, div, buf[0], buf[1], buf[2], buf[3]);
++
++ /* calculate the frequency we set it to */
++ return (div * tun->stepsize) - t_params->iffreq;
++}
++
++static int simple_dvb_calc_regs(struct dvb_frontend *fe,
++ struct dvb_frontend_parameters *params,
++ u8 *buf, int buf_len)
++{
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++ u32 frequency;
++
++ if (buf_len < 5)
++ return -EINVAL;
++
++ frequency = simple_dvb_configure(fe, buf+1, params);
++ if (frequency == 0)
++ return -EINVAL;
++
++ buf[0] = priv->i2c_props.addr;
++
++ priv->frequency = frequency;
++ priv->bandwidth = (fe->ops.info.type == FE_OFDM) ?
++ params->u.ofdm.bandwidth : 0;
++
++ return 5;
++}
++
++static int simple_dvb_set_params(struct dvb_frontend *fe,
++ struct dvb_frontend_parameters *params)
++{
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++ u32 prev_freq, prev_bw;
++ int ret;
++ u8 buf[5];
++
++ if (priv->i2c_props.adap == NULL)
++ return -EINVAL;
++
++ prev_freq = priv->frequency;
++ prev_bw = priv->bandwidth;
++
++ ret = simple_dvb_calc_regs(fe, params, buf, 5);
++ if (ret != 5)
++ goto fail;
++
++ /* put analog demod in standby when tuning digital */
++ if (fe->ops.analog_ops.standby)
++ fe->ops.analog_ops.standby(fe);
++
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
++
++ /* buf[0] contains the i2c address, but *
++ * we already have it in i2c_props.addr */
++ ret = tuner_i2c_xfer_send(&priv->i2c_props, buf+1, 4);
++ if (ret != 4)
++ goto fail;
++
++ return 0;
++fail:
++ /* calc_regs sets frequency and bandwidth. if we failed, unset them */
++ priv->frequency = prev_freq;
++ priv->bandwidth = prev_bw;
++
++ return ret;
++}
++
++static int simple_init(struct dvb_frontend *fe)
++{
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++
++ if (priv->i2c_props.adap == NULL)
++ return -EINVAL;
++
++ if (priv->tun->initdata) {
++ int ret;
++
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
++
++ ret = tuner_i2c_xfer_send(&priv->i2c_props,
++ priv->tun->initdata + 1,
++ priv->tun->initdata[0]);
++ if (ret != priv->tun->initdata[0])
++ return ret;
++ }
++
++ return 0;
++}
++
++static int simple_sleep(struct dvb_frontend *fe)
++{
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++
++ if (priv->i2c_props.adap == NULL)
++ return -EINVAL;
++
++ if (priv->tun->sleepdata) {
++ int ret;
++
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
++
++ ret = tuner_i2c_xfer_send(&priv->i2c_props,
++ priv->tun->sleepdata + 1,
++ priv->tun->sleepdata[0]);
++ if (ret != priv->tun->sleepdata[0])
++ return ret;
++ }
++
++ return 0;
++}
+
+ static int simple_release(struct dvb_frontend *fe)
+ {
+- kfree(fe->tuner_priv);
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++
++ mutex_lock(&tuner_simple_list_mutex);
++
++ if (priv)
++ hybrid_tuner_release_state(priv);
++
++ mutex_unlock(&tuner_simple_list_mutex);
++
+ fe->tuner_priv = NULL;
+
+ return 0;
+@@ -602,10 +969,22 @@ static int simple_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+ return 0;
+ }
+
++static int simple_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
++{
++ struct tuner_simple_priv *priv = fe->tuner_priv;
++ *bandwidth = priv->bandwidth;
++ return 0;
++}
++
+ static struct dvb_tuner_ops simple_tuner_ops = {
++ .init = simple_init,
++ .sleep = simple_sleep,
+ .set_analog_params = simple_set_params,
++ .set_params = simple_dvb_set_params,
++ .calc_regs = simple_dvb_calc_regs,
+ .release = simple_release,
+ .get_frequency = simple_get_frequency,
++ .get_bandwidth = simple_get_bandwidth,
+ .get_status = simple_get_status,
+ .get_rf_strength = simple_get_rf_strength,
+ };
+@@ -613,30 +992,92 @@ static struct dvb_tuner_ops simple_tuner_ops = {
+ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c_adap,
+ u8 i2c_addr,
+- struct simple_tuner_config *cfg)
++ unsigned int type)
+ {
+ struct tuner_simple_priv *priv = NULL;
++ int instance;
+
+- priv = kzalloc(sizeof(struct tuner_simple_priv), GFP_KERNEL);
+- if (priv == NULL)
++ if (type >= tuner_count) {
++ printk(KERN_WARNING "%s: invalid tuner type: %d (max: %d)\n",
++ __func__, type, tuner_count-1);
+ return NULL;
+- fe->tuner_priv = priv;
++ }
+
+- priv->i2c_props.addr = i2c_addr;
+- priv->i2c_props.adap = i2c_adap;
+- priv->type = cfg->type;
+- priv->tun = cfg->tun;
++ /* If i2c_adap is set, check that the tuner is at the correct address.
++ * Otherwise, if i2c_adap is NULL, the tuner will be programmed directly
++ * by the digital demod via calc_regs.
++ */
++ if (i2c_adap != NULL) {
++ u8 b[1];
++ struct i2c_msg msg = {
++ .addr = i2c_addr, .flags = I2C_M_RD,
++ .buf = b, .len = 1,
++ };
++
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 1);
++
++ if (1 != i2c_transfer(i2c_adap, &msg, 1))
++ tuner_warn("unable to probe %s, proceeding anyway.",
++ tuners[type].name);
++
++ if (fe->ops.i2c_gate_ctrl)
++ fe->ops.i2c_gate_ctrl(fe, 0);
++ }
+
+- memcpy(&fe->ops.tuner_ops, &simple_tuner_ops, sizeof(struct dvb_tuner_ops));
++ mutex_lock(&tuner_simple_list_mutex);
+
+- tuner_info("type set to %d (%s)\n", cfg->type, cfg->tun->name);
++ instance = hybrid_tuner_request_state(struct tuner_simple_priv, priv,
++ hybrid_tuner_instance_list,
++ i2c_adap, i2c_addr,
++ "tuner-simple");
++ switch (instance) {
++ case 0:
++ mutex_unlock(&tuner_simple_list_mutex);
++ return NULL;
++ break;
++ case 1:
++ fe->tuner_priv = priv;
+
+- strlcpy(fe->ops.tuner_ops.info.name, cfg->tun->name, sizeof(fe->ops.tuner_ops.info.name));
++ priv->type = type;
++ priv->tun = &tuners[type];
++ priv->nr = simple_devcount++;
++ break;
++ default:
++ fe->tuner_priv = priv;
++ break;
++ }
+
+- return fe;
+-}
++ mutex_unlock(&tuner_simple_list_mutex);
++
++ memcpy(&fe->ops.tuner_ops, &simple_tuner_ops,
++ sizeof(struct dvb_tuner_ops));
++
++ tuner_info("type set to %d (%s)\n", type, priv->tun->name);
++
++ if ((debug) || ((atv_input[priv->nr] > 0) ||
++ (dtv_input[priv->nr] > 0))) {
++ if (0 == atv_input[priv->nr])
++ tuner_info("tuner %d atv rf input will be "
++ "autoselected\n", priv->nr);
++ else
++ tuner_info("tuner %d atv rf input will be "
++ "set to input %d (insmod option)\n",
++ priv->nr, atv_input[priv->nr]);
++ if (0 == dtv_input[priv->nr])
++ tuner_info("tuner %d dtv rf input will be "
++ "autoselected\n", priv->nr);
++ else
++ tuner_info("tuner %d dtv rf input will be "
++ "set to input %d (insmod option)\n",
++ priv->nr, dtv_input[priv->nr]);
++ }
+
++ strlcpy(fe->ops.tuner_ops.info.name, priv->tun->name,
++ sizeof(fe->ops.tuner_ops.info.name));
+
++ return fe;
++}
+ EXPORT_SYMBOL_GPL(simple_tuner_attach);
+
+ MODULE_DESCRIPTION("Simple 4-control-bytes style tuner driver");
+diff --git a/drivers/media/video/tuner-simple.h b/drivers/media/video/tuner-simple.h
+index 9089939..e46cf01 100644
+--- a/drivers/media/video/tuner-simple.h
++++ b/drivers/media/video/tuner-simple.h
+@@ -20,25 +20,18 @@
+ #include <linux/i2c.h>
+ #include "dvb_frontend.h"
+
+-struct simple_tuner_config
+-{
+- /* chip type */
+- unsigned int type;
+- struct tunertype *tun;
+-};
+-
+ #if defined(CONFIG_TUNER_SIMPLE) || (defined(CONFIG_TUNER_SIMPLE_MODULE) && defined(MODULE))
+ extern struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c_adap,
+ u8 i2c_addr,
+- struct simple_tuner_config *cfg);
++ unsigned int type);
+ #else
+ static inline struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c_adap,
+ u8 i2c_addr,
+- struct simple_tuner_config *cfg)
++ unsigned int type)
+ {
+- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+ }
+ #endif
+diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c
+index 883047f..10dddca 100644
+--- a/drivers/media/video/tuner-types.c
++++ b/drivers/media/video/tuner-types.c
+@@ -35,6 +35,27 @@
+ * based on the video standard in use.
+ */
+
++/* The following was taken from dvb-pll.c: */
++
++/* Set AGC TOP value to 103 dBuV:
++ * 0x80 = Control Byte
++ * 0x40 = 250 uA charge pump (irrelevant)
++ * 0x18 = Aux Byte to follow
++ * 0x06 = 64.5 kHz divider (irrelevant)
++ * 0x01 = Disable Vt (aka sleep)
++ *
++ * 0x00 = AGC Time constant 2s Iagc = 300 nA (vs 0x80 = 9 nA)
++ * 0x50 = AGC Take over point = 103 dBuV
++ */
++static u8 tua603x_agc103[] = { 2, 0x80|0x40|0x18|0x06|0x01, 0x00|0x50 };
++
++/* 0x04 = 166.67 kHz divider
++ *
++ * 0x80 = AGC Time constant 50ms Iagc = 9 uA
++ * 0x20 = AGC Take over point = 112 dBuV
++ */
++static u8 tua603x_agc112[] = { 2, 0x80|0x40|0x18|0x04|0x01, 0x80|0x20 };
++
+ /* 0-9 */
+ /* ------------ TUNER_TEMIC_PAL - TEMIC PAL ------------ */
+
+@@ -594,19 +615,31 @@ static struct tuner_params tuner_philips_pal_mk_params[] = {
+ },
+ };
+
+-/* ---- TUNER_PHILIPS_ATSC - Philips FCV1236D (ATSC/NTSC) ---- */
++/* ---- TUNER_PHILIPS_FCV1236D - Philips FCV1236D (ATSC/NTSC) ---- */
+
+-static struct tuner_range tuner_philips_fcv1236d_ranges[] = {
+- { 16 * 157.25 /*MHz*/, 0x8e, 0xa0, },
+- { 16 * 451.25 /*MHz*/, 0x8e, 0x90, },
++static struct tuner_range tuner_philips_fcv1236d_ntsc_ranges[] = {
++ { 16 * 157.25 /*MHz*/, 0x8e, 0xa2, },
++ { 16 * 451.25 /*MHz*/, 0x8e, 0x92, },
++ { 16 * 999.99 , 0x8e, 0x32, },
++};
++
++static struct tuner_range tuner_philips_fcv1236d_atsc_ranges[] = {
++ { 16 * 159.00 /*MHz*/, 0x8e, 0xa0, },
++ { 16 * 453.00 /*MHz*/, 0x8e, 0x90, },
+ { 16 * 999.99 , 0x8e, 0x30, },
+ };
+
+ static struct tuner_params tuner_philips_fcv1236d_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+- .ranges = tuner_philips_fcv1236d_ranges,
+- .count = ARRAY_SIZE(tuner_philips_fcv1236d_ranges),
++ .ranges = tuner_philips_fcv1236d_ntsc_ranges,
++ .count = ARRAY_SIZE(tuner_philips_fcv1236d_ntsc_ranges),
++ },
++ {
++ .type = TUNER_PARAM_TYPE_DIGITAL,
++ .ranges = tuner_philips_fcv1236d_atsc_ranges,
++ .count = ARRAY_SIZE(tuner_philips_fcv1236d_atsc_ranges),
++ .iffreq = 16 * 44.00,
+ },
+ };
+
+@@ -701,12 +734,24 @@ static struct tuner_range tuner_microtune_4042fi5_ntsc_ranges[] = {
+ { 16 * 999.99 , 0x8e, 0x31, },
+ };
+
++static struct tuner_range tuner_microtune_4042fi5_atsc_ranges[] = {
++ { 16 * 162.00 /*MHz*/, 0x8e, 0xa1, },
++ { 16 * 457.00 /*MHz*/, 0x8e, 0x91, },
++ { 16 * 999.99 , 0x8e, 0x31, },
++};
++
+ static struct tuner_params tuner_microtune_4042fi5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_microtune_4042fi5_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_microtune_4042fi5_ntsc_ranges),
+ },
++ {
++ .type = TUNER_PARAM_TYPE_DIGITAL,
++ .ranges = tuner_microtune_4042fi5_atsc_ranges,
++ .count = ARRAY_SIZE(tuner_microtune_4042fi5_atsc_ranges),
++ .iffreq = 16 * 44.00 /*MHz*/,
++ },
+ };
+
+ /* 50-59 */
+@@ -740,6 +785,7 @@ static struct tuner_params tuner_philips_fm1256_ih3_params[] = {
+
+ /* ------------ TUNER_THOMSON_DTT7610 - THOMSON ATSC ------------ */
+
++/* single range used for both ntsc and atsc */
+ static struct tuner_range tuner_thomson_dtt7610_ntsc_ranges[] = {
+ { 16 * 157.25 /*MHz*/, 0x8e, 0x39, },
+ { 16 * 454.00 /*MHz*/, 0x8e, 0x3a, },
+@@ -752,6 +798,12 @@ static struct tuner_params tuner_thomson_dtt7610_params[] = {
+ .ranges = tuner_thomson_dtt7610_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_thomson_dtt7610_ntsc_ranges),
+ },
++ {
++ .type = TUNER_PARAM_TYPE_DIGITAL,
++ .ranges = tuner_thomson_dtt7610_ntsc_ranges,
++ .count = ARRAY_SIZE(tuner_thomson_dtt7610_ntsc_ranges),
++ .iffreq = 16 * 44.00 /*MHz*/,
++ },
+ };
+
+ /* ------------ TUNER_PHILIPS_FQ1286 - Philips NTSC ------------ */
+@@ -855,6 +907,11 @@ static struct tuner_range tuner_thomson_dtt761x_ntsc_ranges[] = {
+ { 16 * 999.99 , 0x8e, 0x3c, },
+ };
+
++static struct tuner_range tuner_thomson_dtt761x_atsc_ranges[] = {
++ { 16 * 147.00 /*MHz*/, 0x8e, 0x39, },
++ { 16 * 417.00 /*MHz*/, 0x8e, 0x3a, },
++ { 16 * 999.99 , 0x8e, 0x3c, },
++};
+
+ static struct tuner_params tuner_thomson_dtt761x_params[] = {
+ {
+@@ -865,6 +922,12 @@ static struct tuner_params tuner_thomson_dtt761x_params[] = {
+ .fm_gain_normal = 1,
+ .radio_if = 2, /* 41.3 MHz */
+ },
++ {
++ .type = TUNER_PARAM_TYPE_DIGITAL,
++ .ranges = tuner_thomson_dtt761x_atsc_ranges,
++ .count = ARRAY_SIZE(tuner_thomson_dtt761x_atsc_ranges),
++ .iffreq = 16 * 44.00, /*MHz*/
++ },
+ };
+
+ /* ------------ TUNER_TENA_9533_DI - Philips PAL ------------ */
+@@ -891,6 +954,15 @@ static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = {
+ { 16 * 999.99 , 0x86, 0x54, },
+ };
+
++static struct tuner_range tuner_philips_fmd1216me_mk3_dvb_ranges[] = {
++ { 16 * 143.87 /*MHz*/, 0xbc, 0x41 },
++ { 16 * 158.87 /*MHz*/, 0xf4, 0x41 },
++ { 16 * 329.87 /*MHz*/, 0xbc, 0x42 },
++ { 16 * 441.87 /*MHz*/, 0xf4, 0x42 },
++ { 16 * 625.87 /*MHz*/, 0xbc, 0x44 },
++ { 16 * 803.87 /*MHz*/, 0xf4, 0x44 },
++ { 16 * 999.99 , 0xfc, 0x44 },
++};
+
+ static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = {
+ {
+@@ -904,6 +976,12 @@ static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = {
+ .port2_invert_for_secam_lc = 1,
+ .port1_set_for_fm_mono = 1,
+ },
++ {
++ .type = TUNER_PARAM_TYPE_DIGITAL,
++ .ranges = tuner_philips_fmd1216me_mk3_dvb_ranges,
++ .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_dvb_ranges),
++ .iffreq = 16 * 36.125, /*MHz*/
++ },
+ };
+
+
+@@ -915,6 +993,11 @@ static struct tuner_range tuner_tua6034_ntsc_ranges[] = {
+ { 16 * 999.99 , 0x8e, 0x04 },
+ };
+
++static struct tuner_range tuner_tua6034_atsc_ranges[] = {
++ { 16 * 165.00 /*MHz*/, 0xce, 0x01 },
++ { 16 * 450.00 /*MHz*/, 0xce, 0x02 },
++ { 16 * 999.99 , 0xce, 0x04 },
++};
+
+ static struct tuner_params tuner_lg_tdvs_h06xf_params[] = {
+ {
+@@ -922,6 +1005,12 @@ static struct tuner_params tuner_lg_tdvs_h06xf_params[] = {
+ .ranges = tuner_tua6034_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_tua6034_ntsc_ranges),
+ },
++ {
++ .type = TUNER_PARAM_TYPE_DIGITAL,
++ .ranges = tuner_tua6034_atsc_ranges,
++ .count = ARRAY_SIZE(tuner_tua6034_atsc_ranges),
++ .iffreq = 16 * 44.00,
++ },
+ };
+
+ /* ------------ TUNER_YMEC_TVF66T5_B_DFF - Philips PAL ------------ */
+@@ -974,12 +1063,30 @@ static struct tuner_range tuner_philips_td1316_pal_ranges[] = {
+ { 16 * 999.99 , 0xc8, 0xa4, },
+ };
+
++static struct tuner_range tuner_philips_td1316_dvb_ranges[] = {
++ { 16 * 93.834 /*MHz*/, 0xca, 0x60, },
++ { 16 * 123.834 /*MHz*/, 0xca, 0xa0, },
++ { 16 * 163.834 /*MHz*/, 0xca, 0xc0, },
++ { 16 * 253.834 /*MHz*/, 0xca, 0x60, },
++ { 16 * 383.834 /*MHz*/, 0xca, 0xa0, },
++ { 16 * 443.834 /*MHz*/, 0xca, 0xc0, },
++ { 16 * 583.834 /*MHz*/, 0xca, 0x60, },
++ { 16 * 793.834 /*MHz*/, 0xca, 0xa0, },
++ { 16 * 999.999 , 0xca, 0xe0, },
++};
++
+ static struct tuner_params tuner_philips_td1316_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_philips_td1316_pal_ranges,
+ .count = ARRAY_SIZE(tuner_philips_td1316_pal_ranges),
+ },
++ {
++ .type = TUNER_PARAM_TYPE_DIGITAL,
++ .ranges = tuner_philips_td1316_dvb_ranges,
++ .count = ARRAY_SIZE(tuner_philips_td1316_dvb_ranges),
++ .iffreq = 16 * 36.166667 /*MHz*/,
++ },
+ };
+
+ /* ------------ TUNER_PHILIPS_TUV1236D - Philips ATSC ------------ */
+@@ -990,6 +1097,11 @@ static struct tuner_range tuner_tuv1236d_ntsc_ranges[] = {
+ { 16 * 999.99 , 0xce, 0x04, },
+ };
+
++static struct tuner_range tuner_tuv1236d_atsc_ranges[] = {
++ { 16 * 157.25 /*MHz*/, 0xc6, 0x41, },
++ { 16 * 454.00 /*MHz*/, 0xc6, 0x42, },
++ { 16 * 999.99 , 0xc6, 0x44, },
++};
+
+ static struct tuner_params tuner_tuv1236d_params[] = {
+ {
+@@ -997,6 +1109,12 @@ static struct tuner_params tuner_tuv1236d_params[] = {
+ .ranges = tuner_tuv1236d_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_tuv1236d_ntsc_ranges),
+ },
++ {
++ .type = TUNER_PARAM_TYPE_DIGITAL,
++ .ranges = tuner_tuv1236d_atsc_ranges,
++ .count = ARRAY_SIZE(tuner_tuv1236d_atsc_ranges),
++ .iffreq = 16 * 44.00,
++ },
+ };
+
+ /* ------------ TUNER_TNF_xxx5 - Texas Instruments--------- */
+@@ -1050,17 +1168,30 @@ static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = {
+
+ /* ------------ TUNER_THOMSON_FE6600 - DViCO Hybrid PAL ------------ */
+
+-static struct tuner_range tuner_thomson_fe6600_ranges[] = {
++static struct tuner_range tuner_thomson_fe6600_pal_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0xfe, 0x11, },
+ { 16 * 442.00 /*MHz*/, 0xf6, 0x12, },
+ { 16 * 999.99 , 0xf6, 0x18, },
+ };
+
++static struct tuner_range tuner_thomson_fe6600_dvb_ranges[] = {
++ { 16 * 250.00 /*MHz*/, 0xb4, 0x12, },
++ { 16 * 455.00 /*MHz*/, 0xfe, 0x11, },
++ { 16 * 775.50 /*MHz*/, 0xbc, 0x18, },
++ { 16 * 999.99 , 0xf4, 0x18, },
++};
++
+ static struct tuner_params tuner_thomson_fe6600_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+- .ranges = tuner_thomson_fe6600_ranges,
+- .count = ARRAY_SIZE(tuner_thomson_fe6600_ranges),
++ .ranges = tuner_thomson_fe6600_pal_ranges,
++ .count = ARRAY_SIZE(tuner_thomson_fe6600_pal_ranges),
++ },
++ {
++ .type = TUNER_PARAM_TYPE_DIGITAL,
++ .ranges = tuner_thomson_fe6600_dvb_ranges,
++ .count = ARRAY_SIZE(tuner_thomson_fe6600_dvb_ranges),
++ .iffreq = 16 * 36.125 /*MHz*/,
+ },
+ };
+
+@@ -1303,10 +1434,13 @@ struct tunertype tuners[] = {
+ .params = tuner_philips_pal_mk_params,
+ .count = ARRAY_SIZE(tuner_philips_pal_mk_params),
+ },
+- [TUNER_PHILIPS_ATSC] = { /* Philips ATSC */
++ [TUNER_PHILIPS_FCV1236D] = { /* Philips ATSC */
+ .name = "Philips FCV1236D ATSC/NTSC dual in",
+ .params = tuner_philips_fcv1236d_params,
+ .count = ARRAY_SIZE(tuner_philips_fcv1236d_params),
++ .min = 16 * 53.00,
++ .max = 16 * 803.00,
++ .stepsize = 62500,
+ },
+ [TUNER_PHILIPS_FM1236_MK3] = { /* Philips NTSC */
+ .name = "Philips NTSC MK3 (FM1236MK3 or FM1236/F)",
+@@ -1342,6 +1476,9 @@ struct tunertype tuners[] = {
+ .name = "Microtune 4042 FI5 ATSC/NTSC dual in",
+ .params = tuner_microtune_4042fi5_params,
+ .count = ARRAY_SIZE(tuner_microtune_4042fi5_params),
++ .min = 16 * 57.00,
++ .max = 16 * 858.00,
++ .stepsize = 62500,
+ },
+
+ /* 50-59 */
+@@ -1359,6 +1496,9 @@ struct tunertype tuners[] = {
+ .name = "Thomson DTT 7610 (ATSC/NTSC)",
+ .params = tuner_thomson_dtt7610_params,
+ .count = ARRAY_SIZE(tuner_thomson_dtt7610_params),
++ .min = 16 * 44.00,
++ .max = 16 * 958.00,
++ .stepsize = 62500,
+ },
+ [TUNER_PHILIPS_FQ1286] = { /* Philips NTSC */
+ .name = "Philips FQ1286",
+@@ -1400,6 +1540,10 @@ struct tunertype tuners[] = {
+ .name = "Thomson DTT 761X (ATSC/NTSC)",
+ .params = tuner_thomson_dtt761x_params,
+ .count = ARRAY_SIZE(tuner_thomson_dtt761x_params),
++ .min = 16 * 57.00,
++ .max = 16 * 863.00,
++ .stepsize = 62500,
++ .initdata = tua603x_agc103,
+ },
+ [TUNER_TENA_9533_DI] = { /* Philips PAL */
+ .name = "Tena TNF9533-D/IF/TNF9533-B/DF",
+@@ -1414,11 +1558,20 @@ struct tunertype tuners[] = {
+ .name = "Philips FMD1216ME MK3 Hybrid Tuner",
+ .params = tuner_philips_fmd1216me_mk3_params,
+ .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_params),
++ .min = 16 * 50.87,
++ .max = 16 * 858.00,
++ .stepsize = 166667,
++ .initdata = tua603x_agc112,
++ .sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 },
+ },
+ [TUNER_LG_TDVS_H06XF] = { /* LGINNOTEK ATSC */
+ .name = "LG TDVS-H06xF", /* H061F, H062F & H064F */
+ .params = tuner_lg_tdvs_h06xf_params,
+ .count = ARRAY_SIZE(tuner_lg_tdvs_h06xf_params),
++ .min = 16 * 54.00,
++ .max = 16 * 863.00,
++ .stepsize = 62500,
++ .initdata = tua603x_agc103,
+ },
+ [TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */
+ .name = "Ymec TVF66T5-B/DFF",
+@@ -1434,11 +1587,17 @@ struct tunertype tuners[] = {
+ .name = "Philips TD1316 Hybrid Tuner",
+ .params = tuner_philips_td1316_params,
+ .count = ARRAY_SIZE(tuner_philips_td1316_params),
++ .min = 16 * 87.00,
++ .max = 16 * 895.00,
++ .stepsize = 166667,
+ },
+ [TUNER_PHILIPS_TUV1236D] = { /* Philips ATSC */
+ .name = "Philips TUV1236D ATSC/NTSC dual in",
+ .params = tuner_tuv1236d_params,
+ .count = ARRAY_SIZE(tuner_tuv1236d_params),
++ .min = 16 * 54.00,
++ .max = 16 * 864.00,
++ .stepsize = 62500,
+ },
+ [TUNER_TNF_5335MF] = { /* Tenna PAL/NTSC */
+ .name = "Tena TNF 5335 and similar models",
+@@ -1460,6 +1619,9 @@ struct tunertype tuners[] = {
+ .name = "Thomson FE6600",
+ .params = tuner_thomson_fe6600_params,
+ .count = ARRAY_SIZE(tuner_thomson_fe6600_params),
++ .min = 16 * 44.25,
++ .max = 16 * 858.00,
++ .stepsize = 166667,
+ },
+ [TUNER_SAMSUNG_TCPG_6121P30A] = { /* Samsung PAL */
+ .name = "Samsung TCPG 6121P30A",
+@@ -1480,5 +1642,11 @@ struct tunertype tuners[] = {
+ /* see xc5000.c for details */
+ },
+ };
++EXPORT_SYMBOL(tuners);
+
+ unsigned const int tuner_count = ARRAY_SIZE(tuners);
++EXPORT_SYMBOL(tuner_count);
++
++MODULE_DESCRIPTION("Simple tuner device type database");
++MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/video/tuner-xc2028-types.h b/drivers/media/video/tuner-xc2028-types.h
+index d0057fb..74dc46a 100644
+--- a/drivers/media/video/tuner-xc2028-types.h
++++ b/drivers/media/video/tuner-xc2028-types.h
+@@ -1,6 +1,9 @@
+ /* tuner-xc2028_types
+ *
+- * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab at infradead.org)
++ * This file includes internal tipes to be used inside tuner-xc2028.
++ * Shouldn't be included outside tuner-xc2028
++ *
++ * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab at infradead.org)
+ * This code is placed under the terms of the GNU General Public License v2
+ */
+
+@@ -54,11 +57,13 @@
+ /* LCD firmwares exist only for MTS STD/MN (PAL or NTSC/M)
+ and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr)
+ There are variants both with and without NOGD
++ Those firmwares produce better result with LCD displays
+ */
+ #define LCD (1<<12)
+
+ /* NOGD firmwares exist only for MTS STD/MN (PAL or NTSC/M)
+ and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr)
++ The NOGD firmwares don't have group delay compensation filter
+ */
+ #define NOGD (1<<13)
+
+@@ -85,11 +90,19 @@
+ /* This flag identifies that the scode table has a new format */
+ #define HAS_IF (1 << 30)
+
+-#define SCODE_TYPES (MTS|DTV6|QAM|DTV7|DTV78|DTV8|LCD|NOGD|MONO|ATSC|IF| \
+- LG60|ATI638|OREN538|OREN36|TOYOTA388|TOYOTA794| \
+- DIBCOM52|ZARLINK456|CHINA|F6MHZ|SCODE)
++/* There are different scode tables for MTS and non-MTS.
++ The MTS firmwares support mono only
++ */
++#define SCODE_TYPES (SCODE | MTS)
++
+
+-/* Newer types to be moved to videodev2.h */
++/* Newer types not defined on videodev2.h.
++ The original idea were to move all those types to videodev2.h, but
++ it seemed overkill, since, with the exception of SECAM/K3, the other
++ types seem to be autodetected.
++ It is not clear where secam/k3 is used, nor we have a feedback of this
++ working or being autodetected by the standard secam firmware.
++ */
+
+ #define V4L2_STD_SECAM_K3 (0x04000000)
+
+diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c
+index 50cf876..9e9003c 100644
+--- a/drivers/media/video/tuner-xc2028.c
++++ b/drivers/media/video/tuner-xc2028.c
+@@ -1,6 +1,6 @@
+ /* tuner-xc2028
+ *
+- * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab at infradead.org)
++ * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab at infradead.org)
+ *
+ * Copyright (c) 2007 Michel Ludwig (michel.ludwig at gmail.com)
+ * - frontend interface
+@@ -23,8 +23,6 @@
+ #include "dvb_frontend.h"
+
+
+-#define PREFIX "xc2028"
+-
+ static int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug, "enable verbose debug messages");
+@@ -43,6 +41,11 @@ MODULE_PARM_DESC(audio_std,
+ "NICAM/A\n"
+ "NICAM/B\n");
+
++static char firmware_name[FIRMWARE_NAME_MAX];
++module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0);
++MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the "
++ "default firmware name\n");
++
+ static LIST_HEAD(xc2028_list);
+ static DEFINE_MUTEX(xc2028_list_mutex);
+
+@@ -127,12 +130,12 @@ struct xc2028_data {
+ _rc; \
+ })
+
+-static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val)
++static int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val)
+ {
+ unsigned char buf[2];
+ unsigned char ibuf[2];
+
+- tuner_dbg("%s %04x called\n", __FUNCTION__, reg);
++ tuner_dbg("%s %04x called\n", __func__, reg);
+
+ buf[0] = reg >> 8;
+ buf[1] = (unsigned char) reg;
+@@ -145,7 +148,7 @@ static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val)
+ }
+
+ #define dump_firm_type(t) dump_firm_type_and_int_freq(t, 0)
+-void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq)
++static void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq)
+ {
+ if (type & BASE)
+ printk("BASE ");
+@@ -232,6 +235,7 @@ static v4l2_std_id parse_audio_std_option(void)
+ static void free_firmware(struct xc2028_data *priv)
+ {
+ int i;
++ tuner_dbg("%s called\n", __func__);
+
+ if (!priv->firm)
+ return;
+@@ -255,19 +259,24 @@ static int load_all_firmwares(struct dvb_frontend *fe)
+ int rc = 0;
+ int n, n_array;
+ char name[33];
++ char *fname;
++
++ tuner_dbg("%s called\n", __func__);
+
+- tuner_dbg("%s called\n", __FUNCTION__);
++ if (!firmware_name[0])
++ fname = priv->ctrl.fname;
++ else
++ fname = firmware_name;
+
+- tuner_dbg("Reading firmware %s\n", priv->ctrl.fname);
+- rc = request_firmware(&fw, priv->ctrl.fname,
+- &priv->i2c_props.adap->dev);
++ tuner_dbg("Reading firmware %s\n", fname);
++ rc = request_firmware(&fw, fname, &priv->i2c_props.adap->dev);
+ if (rc < 0) {
+ if (rc == -ENOENT)
+ tuner_err("Error: firmware %s not found.\n",
+- priv->ctrl.fname);
++ fname);
+ else
+ tuner_err("Error %d while requesting firmware %s \n",
+- rc, priv->ctrl.fname);
++ rc, fname);
+
+ return rc;
+ }
+@@ -276,7 +285,7 @@ static int load_all_firmwares(struct dvb_frontend *fe)
+
+ if (fw->size < sizeof(name) - 1 + 2 + 2) {
+ tuner_err("Error: firmware file %s has invalid size!\n",
+- priv->ctrl.fname);
++ fname);
+ goto corrupt;
+ }
+
+@@ -291,7 +300,7 @@ static int load_all_firmwares(struct dvb_frontend *fe)
+ p += 2;
+
+ tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n",
+- n_array, priv->ctrl.fname, name,
++ n_array, fname, name,
+ priv->firm_version >> 8, priv->firm_version & 0xff);
+
+ priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL);
+@@ -395,9 +404,9 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
+ {
+ struct xc2028_data *priv = fe->tuner_priv;
+ int i, best_i = -1, best_nr_matches = 0;
+- unsigned int ign_firm_type_mask = 0;
++ unsigned int type_mask = 0;
+
+- tuner_dbg("%s called, want type=", __FUNCTION__);
++ tuner_dbg("%s called, want type=", __func__);
+ if (debug) {
+ dump_firm_type(type);
+ printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
+@@ -412,18 +421,23 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
+ *id = V4L2_STD_PAL;
+
+ if (type & BASE)
+- type &= BASE_TYPES;
++ type_mask = BASE_TYPES;
+ else if (type & SCODE) {
+ type &= SCODE_TYPES;
+- ign_firm_type_mask = HAS_IF;
++ type_mask = SCODE_TYPES & ~HAS_IF;
+ } else if (type & DTV_TYPES)
+- type &= DTV_TYPES;
++ type_mask = DTV_TYPES;
+ else if (type & STD_SPECIFIC_TYPES)
+- type &= STD_SPECIFIC_TYPES;
++ type_mask = STD_SPECIFIC_TYPES;
++
++ type &= type_mask;
++
++ if (!(type & SCODE))
++ type_mask = ~0;
+
+ /* Seek for exact match */
+ for (i = 0; i < priv->firm_size; i++) {
+- if ((type == (priv->firm[i].type & ~ign_firm_type_mask)) &&
++ if ((type == (priv->firm[i].type & type_mask)) &&
+ (*id == priv->firm[i].id))
+ goto found;
+ }
+@@ -433,7 +447,7 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
+ v4l2_std_id match_mask;
+ int nr_matches;
+
+- if (type != (priv->firm[i].type & ~ign_firm_type_mask))
++ if (type != (priv->firm[i].type & type_mask))
+ continue;
+
+ match_mask = *id & priv->firm[i].id;
+@@ -483,7 +497,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
+ int pos, rc;
+ unsigned char *p, *endp, buf[priv->ctrl.max_len];
+
+- tuner_dbg("%s called\n", __FUNCTION__);
++ tuner_dbg("%s called\n", __func__);
+
+ pos = seek_firmware(fe, type, id);
+ if (pos < 0)
+@@ -586,7 +600,7 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type,
+ int pos, rc;
+ unsigned char *p;
+
+- tuner_dbg("%s called\n", __FUNCTION__);
++ tuner_dbg("%s called\n", __func__);
+
+ if (!int_freq) {
+ pos = seek_firmware(fe, type, id);
+@@ -650,7 +664,7 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type,
+ u16 version, hwmodel;
+ v4l2_std_id std0;
+
+- tuner_dbg("%s called\n", __FUNCTION__);
++ tuner_dbg("%s called\n", __func__);
+
+ if (!priv->firm) {
+ if (!priv->ctrl.fname) {
+@@ -770,10 +784,10 @@ check_device:
+ goto fail;
+ }
+
+- tuner_info("Device is Xceive %d version %d.%d, "
+- "firmware version %d.%d\n",
+- hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8,
+- (version & 0xf0) >> 4, version & 0xf);
++ tuner_dbg("Device is Xceive %d version %d.%d, "
++ "firmware version %d.%d\n",
++ hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8,
++ (version & 0xf0) >> 4, version & 0xf);
+
+ /* Check firmware version against what we downloaded. */
+ if (priv->firm_version != ((version & 0xf0) << 4 | (version & 0x0f))) {
+@@ -824,27 +838,34 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
+ u16 frq_lock, signal = 0;
+ int rc;
+
+- tuner_dbg("%s called\n", __FUNCTION__);
++ tuner_dbg("%s called\n", __func__);
+
+ mutex_lock(&priv->lock);
+
+ /* Sync Lock Indicator */
+ rc = xc2028_get_reg(priv, 0x0002, &frq_lock);
+- if (rc < 0 || frq_lock == 0)
++ if (rc < 0)
+ goto ret;
+
+- /* Frequency is locked. Return signal quality */
++ /* Frequency is locked */
++ if (frq_lock == 1)
++ signal = 32768;
+
+ /* Get SNR of the video signal */
+ rc = xc2028_get_reg(priv, 0x0040, &signal);
+ if (rc < 0)
+- signal = -frq_lock;
++ goto ret;
++
++ /* Use both frq_lock and signal to generate the result */
++ signal = signal || ((signal & 0x07) << 12);
+
+ ret:
+ mutex_unlock(&priv->lock);
+
+ *strength = signal;
+
++ tuner_dbg("signal strength is %d\n", signal);
++
+ return rc;
+ }
+
+@@ -861,7 +882,7 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
+ unsigned char buf[4];
+ u32 div, offset = 0;
+
+- tuner_dbg("%s called\n", __FUNCTION__);
++ tuner_dbg("%s called\n", __func__);
+
+ mutex_lock(&priv->lock);
+
+@@ -906,9 +927,11 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
+ if (rc < 0)
+ goto ret;
+
+- rc = priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1);
+- if (rc < 0)
+- goto ret;
++ /* Return code shouldn't be checked.
++ The reset CLK is needed only with tm6000.
++ Driver should work fine even if this fails.
++ */
++ priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1);
+
+ msleep(10);
+
+@@ -942,7 +965,7 @@ static int xc2028_set_analog_freq(struct dvb_frontend *fe,
+ struct xc2028_data *priv = fe->tuner_priv;
+ unsigned int type=0;
+
+- tuner_dbg("%s called\n", __FUNCTION__);
++ tuner_dbg("%s called\n", __func__);
+
+ if (p->mode == V4L2_TUNER_RADIO) {
+ type |= FM;
+@@ -975,7 +998,7 @@ static int xc2028_set_params(struct dvb_frontend *fe,
+ fe_bandwidth_t bw = BANDWIDTH_8_MHZ;
+ u16 demod = 0;
+
+- tuner_dbg("%s called\n", __FUNCTION__);
++ tuner_dbg("%s called\n", __func__);
+
+ if (priv->ctrl.d2633)
+ type |= D2633;
+@@ -1040,33 +1063,12 @@ static int xc2028_set_params(struct dvb_frontend *fe,
+ T_DIGITAL_TV, type, 0, demod);
+ }
+
+-static int xc2028_sleep(struct dvb_frontend *fe)
+-{
+- struct xc2028_data *priv = fe->tuner_priv;
+- int rc = 0;
+-
+- tuner_dbg("%s called\n", __FUNCTION__);
+-
+- mutex_lock(&priv->lock);
+-
+- if (priv->firm_version < 0x0202)
+- rc = send_seq(priv, {0x00, 0x08, 0x00, 0x00});
+- else
+- rc = send_seq(priv, {0x80, 0x08, 0x00, 0x00});
+-
+- priv->cur_fw.type = 0; /* need firmware reload */
+-
+- mutex_unlock(&priv->lock);
+-
+- return rc;
+-}
+-
+
+ static int xc2028_dvb_release(struct dvb_frontend *fe)
+ {
+ struct xc2028_data *priv = fe->tuner_priv;
+
+- tuner_dbg("%s called\n", __FUNCTION__);
++ tuner_dbg("%s called\n", __func__);
+
+ mutex_lock(&xc2028_list_mutex);
+
+@@ -1091,7 +1093,7 @@ static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+ {
+ struct xc2028_data *priv = fe->tuner_priv;
+
+- tuner_dbg("%s called\n", __FUNCTION__);
++ tuner_dbg("%s called\n", __func__);
+
+ *frequency = priv->frequency;
+
+@@ -1104,25 +1106,25 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
+ struct xc2028_ctrl *p = priv_cfg;
+ int rc = 0;
+
+- tuner_dbg("%s called\n", __FUNCTION__);
++ tuner_dbg("%s called\n", __func__);
+
+ mutex_lock(&priv->lock);
+
+- kfree(priv->ctrl.fname);
+- free_firmware(priv);
+-
+ memcpy(&priv->ctrl, p, sizeof(priv->ctrl));
+- priv->ctrl.fname = NULL;
++ if (priv->ctrl.max_len < 9)
++ priv->ctrl.max_len = 13;
+
+ if (p->fname) {
++ if (priv->ctrl.fname && strcmp(p->fname, priv->ctrl.fname)) {
++ kfree(priv->ctrl.fname);
++ free_firmware(priv);
++ }
++
+ priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL);
+ if (priv->ctrl.fname == NULL)
+ rc = -ENOMEM;
+ }
+
+- if (priv->ctrl.max_len < 9)
+- priv->ctrl.max_len = 13;
+-
+ mutex_unlock(&priv->lock);
+
+ return rc;
+@@ -1142,8 +1144,6 @@ static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = {
+ .get_frequency = xc2028_get_frequency,
+ .get_rf_strength = xc2028_signal,
+ .set_params = xc2028_set_params,
+- .sleep = xc2028_sleep,
+-
+ };
+
+ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
+@@ -1153,23 +1153,29 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
+ void *video_dev;
+
+ if (debug)
+- printk(KERN_DEBUG PREFIX ": Xcv2028/3028 init called!\n");
++ printk(KERN_DEBUG "xc2028: Xcv2028/3028 init called!\n");
+
+- if (NULL == cfg || NULL == cfg->video_dev)
++ if (NULL == cfg)
+ return NULL;
+
+ if (!fe) {
+- printk(KERN_ERR PREFIX ": No frontend!\n");
++ printk(KERN_ERR "xc2028: No frontend!\n");
+ return NULL;
+ }
+
+- video_dev = cfg->video_dev;
++ video_dev = cfg->i2c_adap->algo_data;
++
++ if (debug)
++ printk(KERN_DEBUG "xc2028: video_dev =%p\n", video_dev);
+
+ mutex_lock(&xc2028_list_mutex);
+
+ list_for_each_entry(priv, &xc2028_list, xc2028_list) {
+- if (priv->video_dev == cfg->video_dev) {
++ if (&priv->i2c_props.adap->dev == &cfg->i2c_adap->dev) {
+ video_dev = NULL;
++ if (debug)
++ printk(KERN_DEBUG "xc2028: reusing device\n");
++
+ break;
+ }
+ }
+@@ -1183,6 +1189,8 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
+
+ priv->i2c_props.addr = cfg->i2c_addr;
+ priv->i2c_props.adap = cfg->i2c_adap;
++ priv->i2c_props.name = "xc2028";
++
+ priv->video_dev = video_dev;
+ priv->tuner_callback = cfg->callback;
+ priv->ctrl.max_len = 13;
+@@ -1195,6 +1203,9 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
+ fe->tuner_priv = priv;
+ priv->count++;
+
++ if (debug)
++ printk(KERN_DEBUG "xc2028: usage count is %i\n", priv->count);
++
+ memcpy(&fe->ops.tuner_ops, &xc2028_dvb_tuner_ops,
+ sizeof(xc2028_dvb_tuner_ops));
+
+diff --git a/drivers/media/video/tuner-xc2028.h b/drivers/media/video/tuner-xc2028.h
+index 3eb8420..fc2f132 100644
+--- a/drivers/media/video/tuner-xc2028.h
++++ b/drivers/media/video/tuner-xc2028.h
+@@ -1,6 +1,6 @@
+ /* tuner-xc2028
+ *
+- * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab at infradead.org)
++ * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab at infradead.org)
+ * This code is placed under the terms of the GNU General Public License v2
+ */
+
+@@ -12,7 +12,7 @@
+ #define XC2028_DEFAULT_FIRMWARE "xc3028-v27.fw"
+
+ /* Dmoduler IF (kHz) */
+-#define XC3028_FE_DEFAULT 0
++#define XC3028_FE_DEFAULT 0 /* Don't load SCODE */
+ #define XC3028_FE_LG60 6000
+ #define XC3028_FE_ATI638 6380
+ #define XC3028_FE_OREN538 5380
+@@ -55,7 +55,7 @@ static inline struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
+ struct xc2028_config *cfg)
+ {
+ printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
+- __FUNCTION__);
++ __func__);
+ return NULL;
+ }
+ #endif
+diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
+index 01ebcec..f29a2cd 100644
+--- a/drivers/media/video/tvaudio.c
++++ b/drivers/media/video/tvaudio.c
+@@ -38,7 +38,7 @@
+ /* ---------------------------------------------------------------------- */
+ /* insmod args */
+
+-static int debug = 0; /* insmod parameter */
++static int debug; /* insmod parameter */
+ module_param(debug, int, 0644);
+
+ MODULE_DESCRIPTION("device driver for various i2c TV sound decoder / audiomux chips");
+@@ -1235,11 +1235,11 @@ static int tda9850 = 1;
+ static int tda9855 = 1;
+ static int tda9873 = 1;
+ static int tda9874a = 1;
+-static int tea6300 = 0; /* address clash with msp34xx */
+-static int tea6320 = 0; /* address clash with msp34xx */
++static int tea6300; /* default 0 - address clash with msp34xx */
++static int tea6320; /* default 0 - address clash with msp34xx */
+ static int tea6420 = 1;
+ static int pic16c54 = 1;
+-static int ta8874z = 0; /* address clash with tda9840 */
++static int ta8874z; /* default 0 - address clash with tda9840 */
+
+ module_param(tda8425, int, 0444);
+ module_param(tda9840, int, 0444);
+diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
+index dc0da44..3cf8a8e 100644
+--- a/drivers/media/video/tveeprom.c
++++ b/drivers/media/video/tveeprom.c
+@@ -745,109 +745,6 @@ int tveeprom_read(struct i2c_client *c, unsigned char *eedata, int len)
+ }
+ EXPORT_SYMBOL(tveeprom_read);
+
+-/* ----------------------------------------------------------------------- */
+-/* needed for ivtv.sf.net at the moment. Should go away in the long */
+-/* run, just call the exported tveeprom_* directly, there is no point in */
+-/* using the indirect way via i2c_driver->command() */
+-
+-static unsigned short normal_i2c[] = {
+- 0xa0 >> 1,
+- I2C_CLIENT_END,
+-};
+-
+-I2C_CLIENT_INSMOD;
+-
+-static struct i2c_driver i2c_driver_tveeprom;
+-
+-static int
+-tveeprom_command(struct i2c_client *client,
+- unsigned int cmd,
+- void *arg)
+-{
+- struct tveeprom eeprom;
+- u32 *eeprom_props = arg;
+- u8 *buf;
+-
+- switch (cmd) {
+- case 0:
+- buf = kzalloc(256, GFP_KERNEL);
+- tveeprom_read(client, buf, 256);
+- tveeprom_hauppauge_analog(client, &eeprom, buf);
+- kfree(buf);
+- eeprom_props[0] = eeprom.tuner_type;
+- eeprom_props[1] = eeprom.tuner_formats;
+- eeprom_props[2] = eeprom.model;
+- eeprom_props[3] = eeprom.revision;
+- eeprom_props[4] = eeprom.has_radio;
+- break;
+- default:
+- return -EINVAL;
+- }
+- return 0;
+-}
+-
+-static int
+-tveeprom_detect_client(struct i2c_adapter *adapter,
+- int address,
+- int kind)
+-{
+- struct i2c_client *client;
+-
+- client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+- if (NULL == client)
+- return -ENOMEM;
+- client->addr = address;
+- client->adapter = adapter;
+- client->driver = &i2c_driver_tveeprom;
+- snprintf(client->name, sizeof(client->name), "tveeprom");
+- i2c_attach_client(client);
+-
+- return 0;
+-}
+-
+-static int
+-tveeprom_attach_adapter(struct i2c_adapter *adapter)
+-{
+- if (adapter->class & I2C_CLASS_TV_ANALOG)
+- return i2c_probe(adapter, &addr_data, tveeprom_detect_client);
+- return 0;
+-}
+-
+-static int
+-tveeprom_detach_client(struct i2c_client *client)
+-{
+- int err;
+-
+- err = i2c_detach_client(client);
+- if (err < 0)
+- return err;
+- kfree(client);
+- return 0;
+-}
+-
+-static struct i2c_driver i2c_driver_tveeprom = {
+- .driver = {
+- .name = "tveeprom",
+- },
+- .id = I2C_DRIVERID_TVEEPROM,
+- .attach_adapter = tveeprom_attach_adapter,
+- .detach_client = tveeprom_detach_client,
+- .command = tveeprom_command,
+-};
+-
+-static int __init tveeprom_init(void)
+-{
+- return i2c_add_driver(&i2c_driver_tveeprom);
+-}
+-
+-static void __exit tveeprom_exit(void)
+-{
+- i2c_del_driver(&i2c_driver_tveeprom);
+-}
+-
+-module_init(tveeprom_init);
+-module_exit(tveeprom_exit);
+-
+ /*
+ * Local variables:
+ * c-basic-offset: 8
+diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c
+index b6e24e7..6a3af10 100644
+--- a/drivers/media/video/tvp5150.c
++++ b/drivers/media/video/tvp5150.c
+@@ -27,7 +27,7 @@ static unsigned short normal_i2c[] = {
+
+ I2C_CLIENT_INSMOD;
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+diff --git a/drivers/media/video/usbvideo/ibmcam.c b/drivers/media/video/usbvideo/ibmcam.c
+index 14db95e..59166b7 100644
+--- a/drivers/media/video/usbvideo/ibmcam.c
++++ b/drivers/media/video/usbvideo/ibmcam.c
+@@ -121,7 +121,7 @@ static int init_model2_yb = -1;
+
+ /* 01.01.08 - Added for RCA video in support -LO */
+ /* Settings for camera model 3 */
+-static int init_model3_input = 0;
++static int init_model3_input;
+
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
+@@ -802,6 +802,21 @@ static enum ParseState ibmcam_model2_320x240_parse_lines(
+ return scan_Continue;
+ }
+
++/*
++ * ibmcam_model3_parse_lines()
++ *
++ * | Even lines | Odd Lines |
++ * -----------------------------------|
++ * |YYY........Y|UYVYUYVY.........UYVY|
++ * |YYY........Y|UYVYUYVY.........UYVY|
++ * |............|.....................|
++ * |YYY........Y|UYVYUYVY.........UYVY|
++ * |------------+---------------------|
++ *
++ * There is one (U, V) chroma pair for every four luma (Y) values. This
++ * function reads a pair of lines at a time and obtains missing chroma values
++ * from adjacent pixels.
++ */
+ static enum ParseState ibmcam_model3_parse_lines(
+ struct uvd *uvd,
+ struct usbvideo_frame *frame,
+@@ -816,6 +831,7 @@ static enum ParseState ibmcam_model3_parse_lines(
+ const int ccm = 128; /* Color correction median - see below */
+ int i, u, v, rw, data_w=0, data_h=0, color_corr;
+ static unsigned char lineBuffer[640*3];
++ int line;
+
+ color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
+ RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1);
+@@ -869,15 +885,15 @@ static enum ParseState ibmcam_model3_parse_lines(
+ return scan_NextFrame;
+ }
+
+- /* Make sure there's enough data for the entire line */
+- len = 3 * data_w; /* <y-data> <uv-data> */
++ /* Make sure that lineBuffer can store two lines of data */
++ len = 3 * data_w; /* <y-data> <uyvy-data> */
+ assert(len <= sizeof(lineBuffer));
+
+- /* Make sure there's enough data for the entire line */
++ /* Make sure there's enough data for two lines */
+ if (RingQueue_GetLength(&uvd->dp) < len)
+ return scan_Out;
+
+- /* Suck one line out of the ring queue */
++ /* Suck two lines of data out of the ring queue */
+ RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
+
+ data = lineBuffer;
+@@ -887,15 +903,23 @@ static enum ParseState ibmcam_model3_parse_lines(
+ rw = (int)VIDEOSIZE_Y(frame->request) - (int)(frame->curline) - 1;
+ RESTRICT_TO_RANGE(rw, 0, VIDEOSIZE_Y(frame->request)-1);
+
+- for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
+- int y, rv, gv, bv; /* RGB components */
++ /* Iterate over two lines. */
++ for (line = 0; line < 2; line++) {
++ for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
++ int y;
++ int rv, gv, bv; /* RGB components */
+
+- if (i < data_w) {
+- y = data[i]; /* Luminosity is the first line */
++ if (i >= data_w) {
++ RGB24_PUTPIXEL(frame, i, rw, 0, 0, 0);
++ continue;
++ }
++
++ /* first line is YYY...Y; second is UYVY...UYVY */
++ y = data[(line == 0) ? i : (i*2 + 1)];
+
+ /* Apply static color correction */
+- u = color[i*2] + hue_corr;
+- v = color[i*2 + 1] + hue2_corr;
++ u = color[(i/2)*4] + hue_corr;
++ v = color[(i/2)*4 + 2] + hue2_corr;
+
+ /* Apply color correction */
+ if (color_corr != 0) {
+@@ -903,13 +927,21 @@ static enum ParseState ibmcam_model3_parse_lines(
+ u = 128 + ((ccm + color_corr) * (u - 128)) / ccm;
+ v = 128 + ((ccm + color_corr) * (v - 128)) / ccm;
+ }
+- } else
+- y = 0, u = v = 128;
+
+- YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv);
+- RGB24_PUTPIXEL(frame, i, rw, rv, gv, bv); /* Done by deinterlacing now */
++
++ YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv);
++ RGB24_PUTPIXEL(frame, i, rw, rv, gv, bv); /* No deinterlacing */
++ }
++
++ /* Check for the end of requested data */
++ if (rw == 0)
++ break;
++
++ /* Prepare for the second line */
++ rw--;
++ data = lineBuffer + data_w;
+ }
+- frame->deinterlace = Deinterlace_FillEvenLines;
++ frame->deinterlace = Deinterlace_None;
+
+ /*
+ * Account for number of bytes that we wrote into output V4L frame.
+diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c
+index 719b17c..1c18028 100644
+--- a/drivers/media/video/usbvideo/konicawc.c
++++ b/drivers/media/video/usbvideo/konicawc.c
+@@ -57,11 +57,11 @@ static struct usbvideo *cams;
+ static int debug;
+ #define DEBUG(n, format, arg...) \
+ if (n <= debug) { \
+- printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \
++ printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \
+ }
+ #else
+ #define DEBUG(n, arg...)
+-static const int debug = 0;
++static const int debug;
+ #endif
+
+
+diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c
+index a2acba0..32e536e 100644
+--- a/drivers/media/video/usbvideo/quickcam_messenger.c
++++ b/drivers/media/video/usbvideo/quickcam_messenger.c
+@@ -46,11 +46,11 @@
+ static int debug;
+ #define DEBUG(n, format, arg...) \
+ if (n <= debug) { \
+- printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \
++ printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \
+ }
+ #else
+ #define DEBUG(n, arg...)
+-static const int debug = 0;
++static const int debug;
+ #endif
+
+ #define DRIVER_VERSION "v0.01"
+diff --git a/drivers/media/video/usbvideo/ultracam.c b/drivers/media/video/usbvideo/ultracam.c
+index 95453c1..9544e64 100644
+--- a/drivers/media/video/usbvideo/ultracam.c
++++ b/drivers/media/video/usbvideo/ultracam.c
+@@ -28,9 +28,9 @@ typedef struct {
+
+ static struct usbvideo *cams = NULL;
+
+-static int debug = 0;
++static int debug;
+
+-static int flags = 0; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */
++static int flags; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */
+
+ static const int min_canvasWidth = 8;
+ static const int min_canvasHeight = 4;
+diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c
+index 5d363be..4128ee2 100644
+--- a/drivers/media/video/usbvideo/usbvideo.c
++++ b/drivers/media/video/usbvideo/usbvideo.c
+@@ -522,14 +522,14 @@ void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode)
+ struct usbvideo_frame *frame;
+ int num_cell = 0;
+ int scan_length = 0;
+- static int num_pass = 0;
++ static int num_pass;
+
+ if (uvd == NULL) {
+- err("%s: uvd == NULL", __FUNCTION__);
++ err("%s: uvd == NULL", __func__);
+ return;
+ }
+ if ((uvd->curframe < 0) || (uvd->curframe >= USBVIDEO_NUMFRAMES)) {
+- err("%s: uvd->curframe=%d.", __FUNCTION__, uvd->curframe);
++ err("%s: uvd->curframe=%d.", __func__, uvd->curframe);
+ return;
+ }
+
+@@ -630,15 +630,15 @@ EXPORT_SYMBOL(usbvideo_HexDump);
+ static int usbvideo_ClientIncModCount(struct uvd *uvd)
+ {
+ if (uvd == NULL) {
+- err("%s: uvd == NULL", __FUNCTION__);
++ err("%s: uvd == NULL", __func__);
+ return -EINVAL;
+ }
+ if (uvd->handle == NULL) {
+- err("%s: uvd->handle == NULL", __FUNCTION__);
++ err("%s: uvd->handle == NULL", __func__);
+ return -EINVAL;
+ }
+ if (!try_module_get(uvd->handle->md_module)) {
+- err("%s: try_module_get() == 0", __FUNCTION__);
++ err("%s: try_module_get() == 0", __func__);
+ return -ENODEV;
+ }
+ return 0;
+@@ -647,15 +647,15 @@ static int usbvideo_ClientIncModCount(struct uvd *uvd)
+ static void usbvideo_ClientDecModCount(struct uvd *uvd)
+ {
+ if (uvd == NULL) {
+- err("%s: uvd == NULL", __FUNCTION__);
++ err("%s: uvd == NULL", __func__);
+ return;
+ }
+ if (uvd->handle == NULL) {
+- err("%s: uvd->handle == NULL", __FUNCTION__);
++ err("%s: uvd->handle == NULL", __func__);
+ return;
+ }
+ if (uvd->handle->md_module == NULL) {
+- err("%s: uvd->handle->md_module == NULL", __FUNCTION__);
++ err("%s: uvd->handle->md_module == NULL", __func__);
+ return;
+ }
+ module_put(uvd->handle->md_module);
+@@ -675,13 +675,13 @@ int usbvideo_register(
+
+ /* Check parameters for sanity */
+ if ((num_cams <= 0) || (pCams == NULL) || (cbTbl == NULL)) {
+- err("%s: Illegal call", __FUNCTION__);
++ err("%s: Illegal call", __func__);
+ return -EINVAL;
+ }
+
+ /* Check registration callback - must be set! */
+ if (cbTbl->probe == NULL) {
+- err("%s: probe() is required!", __FUNCTION__);
++ err("%s: probe() is required!", __func__);
+ return -EINVAL;
+ }
+
+@@ -692,7 +692,7 @@ int usbvideo_register(
+ return -ENOMEM;
+ }
+ dbg("%s: Allocated $%p (%d. bytes) for %d. cameras",
+- __FUNCTION__, cams, base_size, num_cams);
++ __func__, cams, base_size, num_cams);
+
+ /* Copy callbacks, apply defaults for those that are not set */
+ memmove(&cams->cb, cbTbl, sizeof(cams->cb));
+@@ -721,7 +721,7 @@ int usbvideo_register(
+ up->user_data = kmalloc(up->user_size, GFP_KERNEL);
+ if (up->user_data == NULL) {
+ err("%s: Failed to allocate user_data (%d. bytes)",
+- __FUNCTION__, up->user_size);
++ __func__, up->user_size);
+ while (i) {
+ up = &cams->cam[--i];
+ kfree(up->user_data);
+@@ -730,7 +730,7 @@ int usbvideo_register(
+ return -ENOMEM;
+ }
+ dbg("%s: Allocated cams[%d].user_data=$%p (%d. bytes)",
+- __FUNCTION__, i, up->user_data, up->user_size);
++ __func__, i, up->user_data, up->user_size);
+ }
+ }
+
+@@ -776,19 +776,19 @@ void usbvideo_Deregister(struct usbvideo **pCams)
+ int i;
+
+ if (pCams == NULL) {
+- err("%s: pCams == NULL", __FUNCTION__);
++ err("%s: pCams == NULL", __func__);
+ return;
+ }
+ cams = *pCams;
+ if (cams == NULL) {
+- err("%s: cams == NULL", __FUNCTION__);
++ err("%s: cams == NULL", __func__);
+ return;
+ }
+
+- dbg("%s: Deregistering %s driver.", __FUNCTION__, cams->drvName);
++ dbg("%s: Deregistering %s driver.", __func__, cams->drvName);
+ usb_deregister(&cams->usbdrv);
+
+- dbg("%s: Deallocating cams=$%p (%d. cameras)", __FUNCTION__, cams, cams->num_cameras);
++ dbg("%s: Deallocating cams=$%p (%d. cameras)", __func__, cams, cams->num_cameras);
+ for (i=0; i < cams->num_cameras; i++) {
+ struct uvd *up = &cams->cam[i];
+ int warning = 0;
+@@ -802,16 +802,16 @@ void usbvideo_Deregister(struct usbvideo **pCams)
+ }
+ if (warning) {
+ err("%s: Warning: user_data=$%p user_size=%d.",
+- __FUNCTION__, up->user_data, up->user_size);
++ __func__, up->user_data, up->user_size);
+ } else {
+ dbg("%s: Freeing %d. $%p->user_data=$%p",
+- __FUNCTION__, i, up, up->user_data);
++ __func__, i, up, up->user_data);
+ kfree(up->user_data);
+ }
+ }
+ /* Whole array was allocated in one chunk */
+ dbg("%s: Freed %d uvd structures",
+- __FUNCTION__, cams->num_cameras);
++ __func__, cams->num_cameras);
+ kfree(cams);
+ *pCams = NULL;
+ }
+@@ -846,7 +846,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
+ int i;
+
+ if (uvd == NULL) {
+- err("%s($%p): Illegal call.", __FUNCTION__, intf);
++ err("%s($%p): Illegal call.", __func__, intf);
+ return;
+ }
+
+@@ -854,7 +854,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
+
+ usbvideo_ClientIncModCount(uvd);
+ if (uvd->debug > 0)
+- info("%s(%p.)", __FUNCTION__, intf);
++ info("%s(%p.)", __func__, intf);
+
+ mutex_lock(&uvd->lock);
+ uvd->remove_pending = 1; /* Now all ISO data will be ignored */
+@@ -870,10 +870,10 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
+
+ video_unregister_device(&uvd->vdev);
+ if (uvd->debug > 0)
+- info("%s: Video unregistered.", __FUNCTION__);
++ info("%s: Video unregistered.", __func__);
+
+ if (uvd->user)
+- info("%s: In use, disconnect pending.", __FUNCTION__);
++ info("%s: In use, disconnect pending.", __func__);
+ else
+ usbvideo_CameraRelease(uvd);
+ mutex_unlock(&uvd->lock);
+@@ -895,7 +895,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
+ static void usbvideo_CameraRelease(struct uvd *uvd)
+ {
+ if (uvd == NULL) {
+- err("%s: Illegal call", __FUNCTION__);
++ err("%s: Illegal call", __func__);
+ return;
+ }
+
+@@ -946,7 +946,9 @@ static const struct file_operations usbvideo_fops = {
+ .read = usbvideo_v4l_read,
+ .mmap = usbvideo_v4l_mmap,
+ .ioctl = usbvideo_v4l_ioctl,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+ static const struct video_device usbvideo_template = {
+@@ -1011,18 +1013,18 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd)
+ char tmp1[20], tmp2[20]; /* Buffers for printing */
+
+ if (uvd == NULL) {
+- err("%s: Illegal call.", __FUNCTION__);
++ err("%s: Illegal call.", __func__);
+ return -EINVAL;
+ }
+ if (uvd->video_endp == 0) {
+- info("%s: No video endpoint specified; data pump disabled.", __FUNCTION__);
++ info("%s: No video endpoint specified; data pump disabled.", __func__);
+ }
+ if (uvd->paletteBits == 0) {
+- err("%s: No palettes specified!", __FUNCTION__);
++ err("%s: No palettes specified!", __func__);
+ return -EINVAL;
+ }
+ if (uvd->defaultPalette == 0) {
+- info("%s: No default palette!", __FUNCTION__);
++ info("%s: No default palette!", __func__);
+ }
+
+ uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) *
+@@ -1032,19 +1034,19 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd)
+
+ if (uvd->debug > 0) {
+ info("%s: iface=%d. endpoint=$%02x paletteBits=$%08lx",
+- __FUNCTION__, uvd->iface, uvd->video_endp, uvd->paletteBits);
++ __func__, uvd->iface, uvd->video_endp, uvd->paletteBits);
+ }
+ if (uvd->dev == NULL) {
+- err("%s: uvd->dev == NULL", __FUNCTION__);
++ err("%s: uvd->dev == NULL", __func__);
+ return -EINVAL;
+ }
+- uvd->vdev.dev=&(uvd->dev->dev);
++ uvd->vdev.dev = &uvd->dev->dev;
+ if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+- err("%s: video_register_device failed", __FUNCTION__);
++ err("%s: video_register_device failed", __func__);
+ return -EPIPE;
+ }
+ if (uvd->debug > 1) {
+- info("%s: video_register_device() successful", __FUNCTION__);
++ info("%s: video_register_device() successful", __func__);
+ }
+
+ info("%s on /dev/video%d: canvas=%s videosize=%s",
+@@ -1111,14 +1113,14 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
+ int i, errCode = 0;
+
+ if (uvd->debug > 1)
+- info("%s($%p)", __FUNCTION__, dev);
++ info("%s($%p)", __func__, dev);
+
+ if (0 < usbvideo_ClientIncModCount(uvd))
+ return -ENODEV;
+ mutex_lock(&uvd->lock);
+
+ if (uvd->user) {
+- err("%s: Someone tried to open an already opened device!", __FUNCTION__);
++ err("%s: Someone tried to open an already opened device!", __func__);
+ errCode = -EBUSY;
+ } else {
+ /* Clear statistics */
+@@ -1134,7 +1136,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
+ RingQueue_Allocate(&uvd->dp, RING_QUEUE_SIZE);
+ if ((uvd->fbuf == NULL) ||
+ (!RingQueue_IsAllocated(&uvd->dp))) {
+- err("%s: Failed to allocate fbuf or dp", __FUNCTION__);
++ err("%s: Failed to allocate fbuf or dp", __func__);
+ errCode = -ENOMEM;
+ } else {
+ /* Allocate all buffers */
+@@ -1178,19 +1180,19 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
+ if (errCode == 0) {
+ if (VALID_CALLBACK(uvd, setupOnOpen)) {
+ if (uvd->debug > 1)
+- info("%s: setupOnOpen callback", __FUNCTION__);
++ info("%s: setupOnOpen callback", __func__);
+ errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd);
+ if (errCode < 0) {
+ err("%s: setupOnOpen callback failed (%d.).",
+- __FUNCTION__, errCode);
++ __func__, errCode);
+ } else if (uvd->debug > 1) {
+- info("%s: setupOnOpen callback successful", __FUNCTION__);
++ info("%s: setupOnOpen callback successful", __func__);
+ }
+ }
+ if (errCode == 0) {
+ uvd->settingsAdjusted = 0;
+ if (uvd->debug > 1)
+- info("%s: Open succeeded.", __FUNCTION__);
++ info("%s: Open succeeded.", __func__);
+ uvd->user++;
+ file->private_data = uvd;
+ }
+@@ -1200,7 +1202,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
+ if (errCode != 0)
+ usbvideo_ClientDecModCount(uvd);
+ if (uvd->debug > 0)
+- info("%s: Returning %d.", __FUNCTION__, errCode);
++ info("%s: Returning %d.", __func__, errCode);
+ return errCode;
+ }
+
+@@ -1223,7 +1225,7 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file)
+ int i;
+
+ if (uvd->debug > 1)
+- info("%s($%p)", __FUNCTION__, dev);
++ info("%s($%p)", __func__, dev);
+
+ mutex_lock(&uvd->lock);
+ GET_CALLBACK(uvd, stopDataPump)(uvd);
+@@ -1250,7 +1252,7 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file)
+ usbvideo_ClientDecModCount(uvd);
+
+ if (uvd->debug > 1)
+- info("%s: Completed.", __FUNCTION__);
++ info("%s: Completed.", __func__);
+ file->private_data = NULL;
+ return 0;
+ }
+@@ -1504,7 +1506,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
+ return -EFAULT;
+
+ if (uvd->debug >= 1)
+- info("%s: %Zd. bytes, noblock=%d.", __FUNCTION__, count, noblock);
++ info("%s: %Zd. bytes, noblock=%d.", __func__, count, noblock);
+
+ mutex_lock(&uvd->lock);
+
+@@ -1551,7 +1553,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
+ */
+ if (frmx == -1) {
+ if (uvd->defaultPalette == 0) {
+- err("%s: No default palette; don't know what to do!", __FUNCTION__);
++ err("%s: No default palette; don't know what to do!", __func__);
+ count = -EFAULT;
+ goto read_done;
+ }
+@@ -1623,7 +1625,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
+ frame->seqRead_Index += count;
+ if (uvd->debug >= 1) {
+ err("%s: {copy} count used=%Zd, new seqRead_Index=%ld",
+- __FUNCTION__, count, frame->seqRead_Index);
++ __func__, count, frame->seqRead_Index);
+ }
+
+ /* Finally check if the frame is done with and "release" it */
+@@ -1634,7 +1636,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
+ /* Mark it as available to be used again. */
+ uvd->frame[frmx].frameState = FrameState_Unused;
+ if (usbvideo_NewFrame(uvd, (frmx + 1) % USBVIDEO_NUMFRAMES)) {
+- err("%s: usbvideo_NewFrame failed.", __FUNCTION__);
++ err("%s: usbvideo_NewFrame failed.", __func__);
+ }
+ }
+ read_done:
+@@ -1741,10 +1743,10 @@ static int usbvideo_StartDataPump(struct uvd *uvd)
+ int i, errFlag;
+
+ if (uvd->debug > 1)
+- info("%s($%p)", __FUNCTION__, uvd);
++ info("%s($%p)", __func__, uvd);
+
+ if (!CAMERA_IS_OPERATIONAL(uvd)) {
+- err("%s: Camera is not operational", __FUNCTION__);
++ err("%s: Camera is not operational", __func__);
+ return -EFAULT;
+ }
+ uvd->curframe = -1;
+@@ -1752,14 +1754,14 @@ static int usbvideo_StartDataPump(struct uvd *uvd)
+ /* Alternate interface 1 is is the biggest frame size */
+ i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive);
+ if (i < 0) {
+- err("%s: usb_set_interface error", __FUNCTION__);
++ err("%s: usb_set_interface error", __func__);
+ uvd->last_error = i;
+ return -EBUSY;
+ }
+ if (VALID_CALLBACK(uvd, videoStart))
+ GET_CALLBACK(uvd, videoStart)(uvd);
+ else
+- err("%s: videoStart not set", __FUNCTION__);
++ err("%s: videoStart not set", __func__);
+
+ /* We double buffer the Iso lists */
+ for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+@@ -1784,12 +1786,12 @@ static int usbvideo_StartDataPump(struct uvd *uvd)
+ for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+ errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL);
+ if (errFlag)
+- err("%s: usb_submit_isoc(%d) ret %d", __FUNCTION__, i, errFlag);
++ err("%s: usb_submit_isoc(%d) ret %d", __func__, i, errFlag);
+ }
+
+ uvd->streaming = 1;
+ if (uvd->debug > 1)
+- info("%s: streaming=1 video_endp=$%02x", __FUNCTION__, uvd->video_endp);
++ info("%s: streaming=1 video_endp=$%02x", __func__, uvd->video_endp);
+ return 0;
+ }
+
+@@ -1811,14 +1813,14 @@ static void usbvideo_StopDataPump(struct uvd *uvd)
+ return;
+
+ if (uvd->debug > 1)
+- info("%s($%p)", __FUNCTION__, uvd);
++ info("%s($%p)", __func__, uvd);
+
+ /* Unschedule all of the iso td's */
+ for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+ usb_kill_urb(uvd->sbuf[i].urb);
+ }
+ if (uvd->debug > 1)
+- info("%s: streaming=0", __FUNCTION__);
++ info("%s: streaming=0", __func__);
+ uvd->streaming = 0;
+
+ if (!uvd->remove_pending) {
+@@ -1826,12 +1828,12 @@ static void usbvideo_StopDataPump(struct uvd *uvd)
+ if (VALID_CALLBACK(uvd, videoStop))
+ GET_CALLBACK(uvd, videoStop)(uvd);
+ else
+- err("%s: videoStop not set", __FUNCTION__);
++ err("%s: videoStop not set", __func__);
+
+ /* Set packet size to 0 */
+ j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive);
+ if (j < 0) {
+- err("%s: usb_set_interface() error %d.", __FUNCTION__, j);
++ err("%s: usb_set_interface() error %d.", __func__, j);
+ uvd->last_error = j;
+ }
+ }
+@@ -1955,12 +1957,12 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
+ struct usbvideo_frame *frame = &uvd->frame[frameNum];
+
+ if (uvd->debug >= 2)
+- info("%s($%p,%d.)", __FUNCTION__, uvd, frameNum);
++ info("%s($%p,%d.)", __func__, uvd, frameNum);
+
+ switch (frame->frameState) {
+ case FrameState_Unused:
+ if (uvd->debug >= 2)
+- info("%s: FrameState_Unused", __FUNCTION__);
++ info("%s: FrameState_Unused", __func__);
+ return -EINVAL;
+ case FrameState_Ready:
+ case FrameState_Grabbing:
+@@ -1970,7 +1972,7 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
+ redo:
+ if (!CAMERA_IS_OPERATIONAL(uvd)) {
+ if (uvd->debug >= 2)
+- info("%s: Camera is not operational (1)", __FUNCTION__);
++ info("%s: Camera is not operational (1)", __func__);
+ return -EIO;
+ }
+ ntries = 0;
+@@ -1979,24 +1981,24 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
+ signalPending = signal_pending(current);
+ if (!CAMERA_IS_OPERATIONAL(uvd)) {
+ if (uvd->debug >= 2)
+- info("%s: Camera is not operational (2)", __FUNCTION__);
++ info("%s: Camera is not operational (2)", __func__);
+ return -EIO;
+ }
+ assert(uvd->fbuf != NULL);
+ if (signalPending) {
+ if (uvd->debug >= 2)
+- info("%s: Signal=$%08x", __FUNCTION__, signalPending);
++ info("%s: Signal=$%08x", __func__, signalPending);
+ if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) {
+ usbvideo_TestPattern(uvd, 1, 0);
+ uvd->curframe = -1;
+ uvd->stats.frame_num++;
+ if (uvd->debug >= 2)
+- info("%s: Forced test pattern screen", __FUNCTION__);
++ info("%s: Forced test pattern screen", __func__);
+ return 0;
+ } else {
+ /* Standard answer: Interrupted! */
+ if (uvd->debug >= 2)
+- info("%s: Interrupted!", __FUNCTION__);
++ info("%s: Interrupted!", __func__);
+ return -EINTR;
+ }
+ } else {
+@@ -2006,17 +2008,17 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
+ else if (VALID_CALLBACK(uvd, processData))
+ GET_CALLBACK(uvd, processData)(uvd, frame);
+ else
+- err("%s: processData not set", __FUNCTION__);
++ err("%s: processData not set", __func__);
+ }
+ } while (frame->frameState == FrameState_Grabbing);
+ if (uvd->debug >= 2) {
+ info("%s: Grabbing done; state=%d. (%lu. bytes)",
+- __FUNCTION__, frame->frameState, frame->seqRead_Length);
++ __func__, frame->frameState, frame->seqRead_Length);
+ }
+ if (frame->frameState == FrameState_Error) {
+ int ret = usbvideo_NewFrame(uvd, frameNum);
+ if (ret < 0) {
+- err("%s: usbvideo_NewFrame() failed (%d.)", __FUNCTION__, ret);
++ err("%s: usbvideo_NewFrame() failed (%d.)", __func__, ret);
+ return ret;
+ }
+ goto redo;
+@@ -2048,7 +2050,7 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
+ }
+ frame->frameState = FrameState_Done_Hold;
+ if (uvd->debug >= 2)
+- info("%s: Entered FrameState_Done_Hold state.", __FUNCTION__);
++ info("%s: Entered FrameState_Done_Hold state.", __func__);
+ return 0;
+
+ case FrameState_Done_Hold:
+@@ -2059,12 +2061,12 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
+ * it will be released back into the wild to roam freely.
+ */
+ if (uvd->debug >= 2)
+- info("%s: FrameState_Done_Hold state.", __FUNCTION__);
++ info("%s: FrameState_Done_Hold state.", __func__);
+ return 0;
+ }
+
+ /* Catch-all for other cases. We shall not be here. */
+- err("%s: Invalid state %d.", __FUNCTION__, frame->frameState);
++ err("%s: Invalid state %d.", __func__, frame->frameState);
+ frame->frameState = FrameState_Unused;
+ return 0;
+ }
+@@ -2160,7 +2162,7 @@ static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd,
+ const int ccm = 128; /* Color correction median - see below */
+
+ if ((uvd == NULL) || (frame == NULL)) {
+- err("%s: Illegal call.", __FUNCTION__);
++ err("%s: Illegal call.", __func__);
+ return;
+ }
+ adj = (uvd->vpic.contrast - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
+diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c
+index da1ba02..6481935 100644
+--- a/drivers/media/video/usbvideo/vicam.c
++++ b/drivers/media/video/usbvideo/vicam.c
+@@ -48,7 +48,7 @@
+ // #define VICAM_DEBUG
+
+ #ifdef VICAM_DEBUG
+-#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __FUNCTION__, lineno, ##args)
++#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __func__, lineno, ##args)
+ #define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):%s (%d):"fmt,##args)
+ #else
+ #define DBG(fmn,args...) do {} while(0)
+@@ -1066,7 +1066,9 @@ static const struct file_operations vicam_fops = {
+ .read = vicam_read,
+ .mmap = vicam_mmap,
+ .ioctl = vicam_ioctl,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ };
+
+diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c
+index 56775ab..a9c5e5a 100644
+--- a/drivers/media/video/usbvision/usbvision-core.c
++++ b/drivers/media/video/usbvision/usbvision-core.c
+@@ -53,19 +53,21 @@
+
+ #include "usbvision.h"
+
+-static unsigned int core_debug = 0;
++static unsigned int core_debug;
+ module_param(core_debug,int,0644);
+ MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
+
+-static unsigned int force_testpattern = 0;
++static unsigned int force_testpattern;
+ module_param(force_testpattern,int,0644);
+ MODULE_PARM_DESC(force_testpattern,"enable test pattern display [core]");
+
+-static int adjustCompression = 1; // Set the compression to be adaptive
++static int adjustCompression = 1; /* Set the compression to be adaptive */
+ module_param(adjustCompression, int, 0444);
+ MODULE_PARM_DESC(adjustCompression, " Set the ADPCM compression for the device. Default: 1 (On)");
+
+-static int SwitchSVideoInput = 0; // To help people with Black and White output with using s-video input. Some cables and input device are wired differently.
++/* To help people with Black and White output with using s-video input.
++ * Some cables and input device are wired differently. */
++static int SwitchSVideoInput;
+ module_param(SwitchSVideoInput, int, 0444);
+ MODULE_PARM_DESC(SwitchSVideoInput, " Set the S-Video input. Some cables and input device are wired differently. Default: 0 (Off)");
+
+@@ -82,8 +84,10 @@ MODULE_PARM_DESC(adjust_Y_Offset, "adjust Y offset display [core]");
+
+
+ #ifdef USBVISION_DEBUG
+- #define PDEBUG(level, fmt, args...) \
+- if (core_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args)
++ #define PDEBUG(level, fmt, args...) { \
++ if (core_debug & (level)) \
++ info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \
++ }
+ #else
+ #define PDEBUG(level, fmt, args...) do {} while(0)
+ #endif
+@@ -384,7 +388,7 @@ int usbvision_scratch_alloc(struct usb_usbvision *usbvision)
+ scratch_reset(usbvision);
+ if(usbvision->scratch == NULL) {
+ err("%s: unable to allocate %d bytes for scratch",
+- __FUNCTION__, scratch_buf_size);
++ __func__, scratch_buf_size);
+ return -ENOMEM;
+ }
+ return 0;
+@@ -418,7 +422,7 @@ static void usbvision_testpattern(struct usb_usbvision *usbvision,
+ unsigned char *f;
+ int num_cell = 0;
+ int scan_length = 0;
+- static int num_pass = 0;
++ static int num_pass;
+
+ if (usbvision == NULL) {
+ printk(KERN_ERR "%s: usbvision == NULL\n", proc);
+@@ -493,7 +497,8 @@ int usbvision_decompress_alloc(struct usb_usbvision *usbvision)
+ int IFB_size = MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * 3 / 2;
+ usbvision->IntraFrameBuffer = vmalloc_32(IFB_size);
+ if (usbvision->IntraFrameBuffer == NULL) {
+- err("%s: unable to allocate %d for compr. frame buffer", __FUNCTION__, IFB_size);
++ err("%s: unable to allocate %d for compr. frame buffer",
++ __func__, IFB_size);
+ return -ENOMEM;
+ }
+ return 0;
+@@ -1430,7 +1435,7 @@ static int usbvision_compress_isochronous(struct usb_usbvision *usbvision,
+ }
+ #if ENABLE_HEXDUMP
+ if (totlen > 0) {
+- static int foo = 0;
++ static int foo;
+ if (foo < 1) {
+ printk(KERN_DEBUG "+%d.\n", usbvision->scratchlen);
+ usbvision_hexdump(data0, (totlen > 64) ? 64 : totlen);
+@@ -1516,7 +1521,7 @@ static void usbvision_isocIrq(struct urb *urb)
+
+ if(errCode) {
+ err("%s: usb_submit_urb failed: error %d",
+- __FUNCTION__, errCode);
++ __func__, errCode);
+ }
+
+ return;
+@@ -1547,7 +1552,7 @@ int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg)
+ 0, (__u16) reg, buffer, 1, HZ);
+
+ if (errCode < 0) {
+- err("%s: failed: error %d", __FUNCTION__, errCode);
++ err("%s: failed: error %d", __func__, errCode);
+ return errCode;
+ }
+ return buffer[0];
+@@ -1575,7 +1580,7 @@ int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg,
+ USB_RECIP_ENDPOINT, 0, (__u16) reg, &value, 1, HZ);
+
+ if (errCode < 0) {
+- err("%s: failed: error %d", __FUNCTION__, errCode);
++ err("%s: failed: error %d", __func__, errCode);
+ }
+ return errCode;
+ }
+@@ -1851,7 +1856,7 @@ int usbvision_set_output(struct usb_usbvision *usbvision, int width,
+ 0, (__u16) USBVISION_LXSIZE_O, value, 4, HZ);
+
+ if (errCode < 0) {
+- err("%s failed: error %d", __FUNCTION__, errCode);
++ err("%s failed: error %d", __func__, errCode);
+ return errCode;
+ }
+ usbvision->curwidth = usbvision->stretch_width * UsbWidth;
+@@ -2237,7 +2242,7 @@ static int usbvision_set_dram_settings(struct usb_usbvision *usbvision)
+ (__u16) USBVISION_DRM_PRM1, value, 8, HZ);
+
+ if (rc < 0) {
+- err("%sERROR=%d", __FUNCTION__, rc);
++ err("%sERROR=%d", __func__, rc);
+ return rc;
+ }
+
+@@ -2486,7 +2491,7 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
+
+ urb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL);
+ if (urb == NULL) {
+- err("%s: usb_alloc_urb() failed", __FUNCTION__);
++ err("%s: usb_alloc_urb() failed", __func__);
+ return -ENOMEM;
+ }
+ usbvision->sbuf[bufIdx].urb = urb;
+@@ -2520,13 +2525,13 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
+ GFP_KERNEL);
+ if (errCode) {
+ err("%s: usb_submit_urb(%d) failed: error %d",
+- __FUNCTION__, bufIdx, errCode);
++ __func__, bufIdx, errCode);
+ }
+ }
+
+ usbvision->streaming = Stream_Idle;
+ PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x",
+- __FUNCTION__,
++ __func__,
+ usbvision->video_endp);
+ return 0;
+ }
+@@ -2560,7 +2565,7 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision)
+ }
+
+
+- PDEBUG(DBG_ISOC, "%s: streaming=Stream_Off\n", __FUNCTION__);
++ PDEBUG(DBG_ISOC, "%s: streaming=Stream_Off\n", __func__);
+ usbvision->streaming = Stream_Off;
+
+ if (!usbvision->remove_pending) {
+@@ -2571,7 +2576,7 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision)
+ usbvision->ifaceAlt);
+ if (errCode < 0) {
+ err("%s: usb_set_interface() failed: error %d",
+- __FUNCTION__, errCode);
++ __func__, errCode);
+ usbvision->last_error = errCode;
+ }
+ regValue = (16-usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
+diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c
+index aabc42c..e2274d7 100644
+--- a/drivers/media/video/usbvision/usbvision-i2c.c
++++ b/drivers/media/video/usbvision/usbvision-i2c.c
+@@ -40,13 +40,15 @@
+
+ #define DBG_I2C 1<<0
+
+-static int i2c_debug = 0;
++static int i2c_debug;
+
+ module_param (i2c_debug, int, 0644); // debug_i2c_usb mode of the device driver
+ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+
+-#define PDEBUG(level, fmt, args...) \
+- if (i2c_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args)
++#define PDEBUG(level, fmt, args...) { \
++ if (i2c_debug & (level)) \
++ info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \
++ }
+
+ static int usbvision_i2c_write(struct usb_usbvision *usbvision, unsigned char addr, char *buf,
+ short len);
+diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
+index df52f8a..d97261a 100644
+--- a/drivers/media/video/usbvision/usbvision-video.c
++++ b/drivers/media/video/usbvision/usbvision-video.c
+@@ -97,10 +97,10 @@ USBVISION_DRIVER_VERSION_PATCHLEVEL)
+
+
+ #ifdef USBVISION_DEBUG
+- #define PDEBUG(level, fmt, args...) \
++ #define PDEBUG(level, fmt, args...) { \
+ if (video_debug & (level)) \
+- info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ ,\
+- ## args)
++ info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \
++ }
+ #else
+ #define PDEBUG(level, fmt, args...) do {} while(0)
+ #endif
+@@ -115,7 +115,7 @@ USBVISION_DRIVER_VERSION_PATCHLEVEL)
+
+
+ /* sequential number of usbvision device */
+-static int usbvision_nr = 0;
++static int usbvision_nr;
+
+ static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = {
+ { 1, 1, 8, V4L2_PIX_FMT_GREY , "GREY" },
+@@ -135,7 +135,7 @@ static void usbvision_release(struct usb_usbvision *usbvision);
+ /* Set the default format for ISOC endpoint */
+ static int isocMode = ISOC_MODE_COMPRESS;
+ /* Set the default Debug Mode of the device driver */
+-static int video_debug = 0;
++static int video_debug;
+ /* Set the default device to power on at startup */
+ static int PowerOnAtOpen = 1;
+ /* Sequential Number of Video Device */
+@@ -343,7 +343,7 @@ static void usbvision_create_sysfs(struct video_device *vdev)
+ return;
+ } while (0);
+
+- err("%s error: %d\n", __FUNCTION__, res);
++ err("%s error: %d\n", __func__, res);
+ }
+
+ static void usbvision_remove_sysfs(struct video_device *vdev)
+@@ -490,7 +490,7 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file)
+ mutex_unlock(&usbvision->lock);
+
+ if (usbvision->remove_pending) {
+- printk(KERN_INFO "%s: Final disconnect\n", __FUNCTION__);
++ printk(KERN_INFO "%s: Final disconnect\n", __func__);
+ usbvision_release(usbvision);
+ }
+
+@@ -522,7 +522,7 @@ static int vidioc_g_register (struct file *file, void *priv,
+ errCode = usbvision_read_reg(usbvision, reg->reg&0xff);
+ if (errCode < 0) {
+ err("%s: VIDIOC_DBG_G_REGISTER failed: error %d",
+- __FUNCTION__, errCode);
++ __func__, errCode);
+ return errCode;
+ }
+ reg->val = errCode;
+@@ -543,7 +543,7 @@ static int vidioc_s_register (struct file *file, void *priv,
+ errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val);
+ if (errCode < 0) {
+ err("%s: VIDIOC_DBG_S_REGISTER failed: error %d",
+- __FUNCTION__, errCode);
++ __func__, errCode);
+ return errCode;
+ }
+ return 0;
+@@ -1102,7 +1102,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
+ int ret,i;
+ struct usbvision_frame *frame;
+
+- PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __FUNCTION__,
++ PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __func__,
+ (unsigned long)count, noblock);
+
+ if (!USBVISION_IS_OPERATIONAL(usbvision) || (buf == NULL))
+@@ -1171,7 +1171,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
+ }
+
+ PDEBUG(DBG_IO, "%s: frmx=%d, bytes_read=%ld, scanlength=%ld",
+- __FUNCTION__,
++ __func__,
+ frame->index, frame->bytes_read, frame->scanlength);
+
+ /* copy bytes to user space; we allow for partials reads */
+@@ -1184,7 +1184,7 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
+
+ frame->bytes_read += count;
+ PDEBUG(DBG_IO, "%s: {copy} count used=%ld, new bytes_read=%ld",
+- __FUNCTION__,
++ __func__,
+ (unsigned long)count, frame->bytes_read);
+
+ /* For now, forget the frame if it has not been read in one shot. */
+@@ -1269,12 +1269,12 @@ static int usbvision_radio_open(struct inode *inode, struct file *file)
+ (struct usb_usbvision *) video_get_drvdata(dev);
+ int errCode = 0;
+
+- PDEBUG(DBG_IO, "%s:", __FUNCTION__);
++ PDEBUG(DBG_IO, "%s:", __func__);
+
+ mutex_lock(&usbvision->lock);
+
+ if (usbvision->user) {
+- err("%s: Someone tried to open an already opened USBVision Radio!", __FUNCTION__);
++ err("%s: Someone tried to open an already opened USBVision Radio!", __func__);
+ errCode = -EBUSY;
+ }
+ else {
+@@ -1342,7 +1342,7 @@ static int usbvision_radio_close(struct inode *inode, struct file *file)
+ mutex_unlock(&usbvision->lock);
+
+ if (usbvision->remove_pending) {
+- printk(KERN_INFO "%s: Final disconnect\n", __FUNCTION__);
++ printk(KERN_INFO "%s: Final disconnect\n", __func__);
+ usbvision_release(usbvision);
+ }
+
+@@ -1507,7 +1507,7 @@ static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision,
+ struct video_device *vdev;
+
+ if (usb_dev == NULL) {
+- err("%s: usbvision->dev is not set", __FUNCTION__);
++ err("%s: usbvision->dev is not set", __func__);
+ return NULL;
+ }
+
+@@ -1759,7 +1759,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf,
+ PDEBUG(DBG_PROBE, "model out of bounds %d",model);
+ return -ENODEV;
+ }
+- printk(KERN_INFO "%s: %s found\n", __FUNCTION__,
++ printk(KERN_INFO "%s: %s found\n", __func__,
+ usbvision_device_data[model].ModelString);
+
+ if (usbvision_device_data[model].Interface >= 0) {
+@@ -1771,20 +1771,20 @@ static int __devinit usbvision_probe(struct usb_interface *intf,
+ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
+ USB_ENDPOINT_XFER_ISOC) {
+ err("%s: interface %d. has non-ISO endpoint!",
+- __FUNCTION__, ifnum);
++ __func__, ifnum);
+ err("%s: Endpoint attributes %d",
+- __FUNCTION__, endpoint->bmAttributes);
++ __func__, endpoint->bmAttributes);
+ return -ENODEV;
+ }
+ if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
+ USB_DIR_OUT) {
+ err("%s: interface %d. has ISO OUT endpoint!",
+- __FUNCTION__, ifnum);
++ __func__, ifnum);
+ return -ENODEV;
+ }
+
+ if ((usbvision = usbvision_alloc(dev)) == NULL) {
+- err("%s: couldn't allocate USBVision struct", __FUNCTION__);
++ err("%s: couldn't allocate USBVision struct", __func__);
+ return -ENOMEM;
+ }
+
+@@ -1868,7 +1868,7 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf)
+ PDEBUG(DBG_PROBE, "");
+
+ if (usbvision == NULL) {
+- err("%s: usb_get_intfdata() failed", __FUNCTION__);
++ err("%s: usb_get_intfdata() failed", __func__);
+ return;
+ }
+ usb_set_intfdata (intf, NULL);
+@@ -1891,7 +1891,7 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf)
+
+ if (usbvision->user) {
+ printk(KERN_INFO "%s: In use, disconnect pending\n",
+- __FUNCTION__);
++ __func__);
+ wake_up_interruptible(&usbvision->wait_frame);
+ wake_up_interruptible(&usbvision->wait_stream);
+ } else {
+diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
+index 50e1ff9..a0f6c60 100644
+--- a/drivers/media/video/v4l1-compat.c
++++ b/drivers/media/video/v4l1-compat.c
+@@ -39,15 +39,18 @@
+ #include <linux/kmod.h>
+ #endif
+
+-static unsigned int debug = 0;
++static unsigned int debug;
+ module_param(debug, int, 0644);
+-MODULE_PARM_DESC(debug,"enable debug messages");
++MODULE_PARM_DESC(debug, "enable debug messages");
+ MODULE_AUTHOR("Bill Dirks");
+ MODULE_DESCRIPTION("v4l(1) compatibility layer for v4l2 drivers.");
+ MODULE_LICENSE("GPL");
+
+-#define dprintk(fmt, arg...) if (debug) \
+- printk(KERN_DEBUG "v4l1-compat: " fmt , ## arg)
++#define dprintk(fmt, arg...) \
++ do { \
++ if (debug) \
++ printk(KERN_DEBUG "v4l1-compat: " fmt , ## arg);\
++ } while (0)
+
+ /*
+ * I O C T L T R A N S L A T I O N
+@@ -69,14 +72,12 @@ get_v4l_control(struct inode *inode,
+ qctrl2.id = cid;
+ err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2);
+ if (err < 0)
+- dprintk("VIDIOC_QUERYCTRL: %d\n",err);
+- if (err == 0 &&
+- !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
+- {
++ dprintk("VIDIOC_QUERYCTRL: %d\n", err);
++ if (err == 0 && !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) {
+ ctrl2.id = qctrl2.id;
+ err = drv(inode, file, VIDIOC_G_CTRL, &ctrl2);
+ if (err < 0) {
+- dprintk("VIDIOC_G_CTRL: %d\n",err);
++ dprintk("VIDIOC_G_CTRL: %d\n", err);
+ return 0;
+ }
+ return ((ctrl2.value - qctrl2.minimum) * 65535
+@@ -100,11 +101,10 @@ set_v4l_control(struct inode *inode,
+ qctrl2.id = cid;
+ err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2);
+ if (err < 0)
+- dprintk("VIDIOC_QUERYCTRL: %d\n",err);
++ dprintk("VIDIOC_QUERYCTRL: %d\n", err);
+ if (err == 0 &&
+ !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED) &&
+- !(qctrl2.flags & V4L2_CTRL_FLAG_GRABBED))
+- {
++ !(qctrl2.flags & V4L2_CTRL_FLAG_GRABBED)) {
+ if (value < 0)
+ value = 0;
+ if (value > 65535)
+@@ -119,14 +119,14 @@ set_v4l_control(struct inode *inode,
+ ctrl2.value += qctrl2.minimum;
+ err = drv(inode, file, VIDIOC_S_CTRL, &ctrl2);
+ if (err < 0)
+- dprintk("VIDIOC_S_CTRL: %d\n",err);
++ dprintk("VIDIOC_S_CTRL: %d\n", err);
+ }
+ return 0;
+ }
+
+ /* ----------------------------------------------------------------- */
+
+-const static unsigned int palette2pixelformat[] = {
++static const unsigned int palette2pixelformat[] = {
+ [VIDEO_PALETTE_GREY] = V4L2_PIX_FMT_GREY,
+ [VIDEO_PALETTE_RGB555] = V4L2_PIX_FMT_RGB555,
+ [VIDEO_PALETTE_RGB565] = V4L2_PIX_FMT_RGB565,
+@@ -157,8 +157,7 @@ static unsigned int __attribute_const__
+ pixelformat_to_palette(unsigned int pixelformat)
+ {
+ int palette = 0;
+- switch (pixelformat)
+- {
++ switch (pixelformat) {
+ case V4L2_PIX_FMT_GREY:
+ palette = VIDEO_PALETTE_GREY;
+ break;
+@@ -200,14 +199,13 @@ pixelformat_to_palette(unsigned int pixelformat)
+
+ /* ----------------------------------------------------------------- */
+
+-static int poll_one(struct file *file)
++static int poll_one(struct file *file, struct poll_wqueues *pwq)
+ {
+ int retval = 1;
+ poll_table *table;
+- struct poll_wqueues pwq;
+
+- poll_initwait(&pwq);
+- table = &pwq.pt;
++ poll_initwait(pwq);
++ table = &pwq->pt;
+ for (;;) {
+ int mask;
+ set_current_state(TASK_INTERRUPTIBLE);
+@@ -222,878 +220,1073 @@ static int poll_one(struct file *file)
+ schedule();
+ }
+ set_current_state(TASK_RUNNING);
+- poll_freewait(&pwq);
++ poll_freewait(pwq);
+ return retval;
+ }
+
+-static int count_inputs(struct inode *inode,
+- struct file *file,
+- v4l2_kioctl drv)
++static int count_inputs(
++ struct inode *inode,
++ struct file *file,
++ v4l2_kioctl drv)
+ {
+ struct v4l2_input input2;
+ int i;
+
+ for (i = 0;; i++) {
+- memset(&input2,0,sizeof(input2));
++ memset(&input2, 0, sizeof(input2));
+ input2.index = i;
+- if (0 != drv(inode,file,VIDIOC_ENUMINPUT, &input2))
++ if (0 != drv(inode, file, VIDIOC_ENUMINPUT, &input2))
+ break;
+ }
+ return i;
+ }
+
+-static int check_size(struct inode *inode,
+- struct file *file,
+- v4l2_kioctl drv,
+- int *maxw, int *maxh)
++static int check_size(
++ struct inode *inode,
++ struct file *file,
++ v4l2_kioctl drv,
++ int *maxw,
++ int *maxh)
+ {
+ struct v4l2_fmtdesc desc2;
+ struct v4l2_format fmt2;
+
+- memset(&desc2,0,sizeof(desc2));
+- memset(&fmt2,0,sizeof(fmt2));
++ memset(&desc2, 0, sizeof(desc2));
++ memset(&fmt2, 0, sizeof(fmt2));
+
+ desc2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+- if (0 != drv(inode,file,VIDIOC_ENUM_FMT, &desc2))
++ if (0 != drv(inode, file, VIDIOC_ENUM_FMT, &desc2))
+ goto done;
+
+ fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ fmt2.fmt.pix.width = 10000;
+ fmt2.fmt.pix.height = 10000;
+ fmt2.fmt.pix.pixelformat = desc2.pixelformat;
+- if (0 != drv(inode,file,VIDIOC_TRY_FMT, &fmt2))
++ if (0 != drv(inode, file, VIDIOC_TRY_FMT, &fmt2))
+ goto done;
+
+ *maxw = fmt2.fmt.pix.width;
+ *maxh = fmt2.fmt.pix.height;
+
+- done:
++done:
+ return 0;
+ }
+
+ /* ----------------------------------------------------------------- */
+
+-/*
+- * This function is exported.
+- */
+-int
+-v4l_compat_translate_ioctl(struct inode *inode,
+- struct file *file,
+- int cmd,
+- void *arg,
+- v4l2_kioctl drv)
++static noinline int v4l1_compat_get_capabilities(
++ struct video_capability *cap,
++ struct inode *inode,
++ struct file *file,
++ v4l2_kioctl drv)
+ {
+- struct v4l2_capability *cap2 = NULL;
+- struct v4l2_format *fmt2 = NULL;
+- enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+-
+- struct v4l2_framebuffer fbuf2;
+- struct v4l2_input input2;
+- struct v4l2_tuner tun2;
+- struct v4l2_standard std2;
+- struct v4l2_frequency freq2;
+- struct v4l2_audio aud2;
+- struct v4l2_queryctrl qctrl2;
+- struct v4l2_buffer buf2;
+- v4l2_std_id sid;
+- int i, err = 0;
+-
+- switch (cmd) {
+- case VIDIOCGCAP: /* capability */
+- {
+- struct video_capability *cap = arg;
+-
+- cap2 = kzalloc(sizeof(*cap2), GFP_KERNEL);
+- if (!cap2) {
+- err = -ENOMEM;
+- break;
+- }
+- memset(cap, 0, sizeof(*cap));
+- memset(&fbuf2, 0, sizeof(fbuf2));
++ int err;
++ struct v4l2_framebuffer fbuf;
++ struct v4l2_capability *cap2;
++
++ cap2 = kzalloc(sizeof(*cap2), GFP_KERNEL);
++ if (!cap2) {
++ err = -ENOMEM;
++ return err;
++ }
++ memset(cap, 0, sizeof(*cap));
++ memset(&fbuf, 0, sizeof(fbuf));
+
+- err = drv(inode, file, VIDIOC_QUERYCAP, cap2);
++ err = drv(inode, file, VIDIOC_QUERYCAP, cap2);
++ if (err < 0) {
++ dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n", err);
++ goto done;
++ }
++ if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) {
++ err = drv(inode, file, VIDIOC_G_FBUF, &fbuf);
+ if (err < 0) {
+- dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n",err);
+- break;
++ dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n", err);
++ memset(&fbuf, 0, sizeof(fbuf));
+ }
+- if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) {
+- err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
+- if (err < 0) {
+- dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n",err);
+- memset(&fbuf2, 0, sizeof(fbuf2));
+- }
+- err = 0;
+- }
+-
+- memcpy(cap->name, cap2->card,
+- min(sizeof(cap->name), sizeof(cap2->card)));
+- cap->name[sizeof(cap->name) - 1] = 0;
+- if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE)
+- cap->type |= VID_TYPE_CAPTURE;
+- if (cap2->capabilities & V4L2_CAP_TUNER)
+- cap->type |= VID_TYPE_TUNER;
+- if (cap2->capabilities & V4L2_CAP_VBI_CAPTURE)
+- cap->type |= VID_TYPE_TELETEXT;
+- if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY)
+- cap->type |= VID_TYPE_OVERLAY;
+- if (fbuf2.capability & V4L2_FBUF_CAP_LIST_CLIPPING)
+- cap->type |= VID_TYPE_CLIPPING;
+-
+- cap->channels = count_inputs(inode,file,drv);
+- check_size(inode,file,drv,
+- &cap->maxwidth,&cap->maxheight);
+- cap->audios = 0; /* FIXME */
+- cap->minwidth = 48; /* FIXME */
+- cap->minheight = 32; /* FIXME */
+- break;
++ err = 0;
+ }
+- case VIDIOCGFBUF: /* get frame buffer */
+- {
+- struct video_buffer *buffer = arg;
+
+- memset(buffer, 0, sizeof(*buffer));
+- memset(&fbuf2, 0, sizeof(fbuf2));
++ memcpy(cap->name, cap2->card,
++ min(sizeof(cap->name), sizeof(cap2->card)));
++ cap->name[sizeof(cap->name) - 1] = 0;
++ if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE)
++ cap->type |= VID_TYPE_CAPTURE;
++ if (cap2->capabilities & V4L2_CAP_TUNER)
++ cap->type |= VID_TYPE_TUNER;
++ if (cap2->capabilities & V4L2_CAP_VBI_CAPTURE)
++ cap->type |= VID_TYPE_TELETEXT;
++ if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY)
++ cap->type |= VID_TYPE_OVERLAY;
++ if (fbuf.capability & V4L2_FBUF_CAP_LIST_CLIPPING)
++ cap->type |= VID_TYPE_CLIPPING;
++
++ cap->channels = count_inputs(inode, file, drv);
++ check_size(inode, file, drv,
++ &cap->maxwidth, &cap->maxheight);
++ cap->audios = 0; /* FIXME */
++ cap->minwidth = 48; /* FIXME */
++ cap->minheight = 32; /* FIXME */
++
++done:
++ kfree(cap2);
++ return err;
++}
+
+- err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
+- if (err < 0) {
+- dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n",err);
+- break;
+- }
+- buffer->base = fbuf2.base;
+- buffer->height = fbuf2.fmt.height;
+- buffer->width = fbuf2.fmt.width;
++static noinline int v4l1_compat_get_frame_buffer(
++ struct video_buffer *buffer,
++ struct inode *inode,
++ struct file *file,
++ v4l2_kioctl drv)
++{
++ int err;
++ struct v4l2_framebuffer fbuf;
+
+- switch (fbuf2.fmt.pixelformat) {
+- case V4L2_PIX_FMT_RGB332:
+- buffer->depth = 8;
+- break;
+- case V4L2_PIX_FMT_RGB555:
+- buffer->depth = 15;
+- break;
+- case V4L2_PIX_FMT_RGB565:
+- buffer->depth = 16;
+- break;
+- case V4L2_PIX_FMT_BGR24:
+- buffer->depth = 24;
+- break;
+- case V4L2_PIX_FMT_BGR32:
+- buffer->depth = 32;
+- break;
+- default:
+- buffer->depth = 0;
+- }
+- if (fbuf2.fmt.bytesperline) {
+- buffer->bytesperline = fbuf2.fmt.bytesperline;
+- if (!buffer->depth && buffer->width)
+- buffer->depth = ((fbuf2.fmt.bytesperline<<3)
+- + (buffer->width-1) )
+- /buffer->width;
+- } else {
+- buffer->bytesperline =
+- (buffer->width * buffer->depth + 7) & 7;
+- buffer->bytesperline >>= 3;
+- }
++ memset(buffer, 0, sizeof(*buffer));
++ memset(&fbuf, 0, sizeof(fbuf));
++
++ err = drv(inode, file, VIDIOC_G_FBUF, &fbuf);
++ if (err < 0) {
++ dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n", err);
++ goto done;
++ }
++ buffer->base = fbuf.base;
++ buffer->height = fbuf.fmt.height;
++ buffer->width = fbuf.fmt.width;
++
++ switch (fbuf.fmt.pixelformat) {
++ case V4L2_PIX_FMT_RGB332:
++ buffer->depth = 8;
++ break;
++ case V4L2_PIX_FMT_RGB555:
++ buffer->depth = 15;
++ break;
++ case V4L2_PIX_FMT_RGB565:
++ buffer->depth = 16;
++ break;
++ case V4L2_PIX_FMT_BGR24:
++ buffer->depth = 24;
++ break;
++ case V4L2_PIX_FMT_BGR32:
++ buffer->depth = 32;
+ break;
++ default:
++ buffer->depth = 0;
+ }
+- case VIDIOCSFBUF: /* set frame buffer */
+- {
+- struct video_buffer *buffer = arg;
+-
+- memset(&fbuf2, 0, sizeof(fbuf2));
+- fbuf2.base = buffer->base;
+- fbuf2.fmt.height = buffer->height;
+- fbuf2.fmt.width = buffer->width;
+- switch (buffer->depth) {
+- case 8:
+- fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB332;
+- break;
+- case 15:
+- fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB555;
+- break;
+- case 16:
+- fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
+- break;
+- case 24:
+- fbuf2.fmt.pixelformat = V4L2_PIX_FMT_BGR24;
+- break;
+- case 32:
+- fbuf2.fmt.pixelformat = V4L2_PIX_FMT_BGR32;
+- break;
+- }
+- fbuf2.fmt.bytesperline = buffer->bytesperline;
+- err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);
+- if (err < 0)
+- dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n",err);
++ if (fbuf.fmt.bytesperline) {
++ buffer->bytesperline = fbuf.fmt.bytesperline;
++ if (!buffer->depth && buffer->width)
++ buffer->depth = ((fbuf.fmt.bytesperline<<3)
++ + (buffer->width-1))
++ / buffer->width;
++ } else {
++ buffer->bytesperline =
++ (buffer->width * buffer->depth + 7) & 7;
++ buffer->bytesperline >>= 3;
++ }
++done:
++ return err;
++}
++
++static noinline int v4l1_compat_set_frame_buffer(
++ struct video_buffer *buffer,
++ struct inode *inode,
++ struct file *file,
++ v4l2_kioctl drv)
++{
++ int err;
++ struct v4l2_framebuffer fbuf;
++
++ memset(&fbuf, 0, sizeof(fbuf));
++ fbuf.base = buffer->base;
++ fbuf.fmt.height = buffer->height;
++ fbuf.fmt.width = buffer->width;
++ switch (buffer->depth) {
++ case 8:
++ fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB332;
++ break;
++ case 15:
++ fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB555;
++ break;
++ case 16:
++ fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
++ break;
++ case 24:
++ fbuf.fmt.pixelformat = V4L2_PIX_FMT_BGR24;
++ break;
++ case 32:
++ fbuf.fmt.pixelformat = V4L2_PIX_FMT_BGR32;
+ break;
+ }
+- case VIDIOCGWIN: /* get window or capture dimensions */
+- {
+- struct video_window *win = arg;
++ fbuf.fmt.bytesperline = buffer->bytesperline;
++ err = drv(inode, file, VIDIOC_S_FBUF, &fbuf);
++ if (err < 0)
++ dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n", err);
++ return err;
++}
+
+- fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+- if (!fmt2) {
+- err = -ENOMEM;
+- break;
+- }
+- memset(win,0,sizeof(*win));
++static noinline int v4l1_compat_get_win_cap_dimensions(
++ struct video_window *win,
++ struct inode *inode,
++ struct file *file,
++ v4l2_kioctl drv)
++{
++ int err;
++ struct v4l2_format *fmt;
+
+- fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+- err = drv(inode, file, VIDIOC_G_FMT, fmt2);
+- if (err < 0)
+- dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n",err);
+- if (err == 0) {
+- win->x = fmt2->fmt.win.w.left;
+- win->y = fmt2->fmt.win.w.top;
+- win->width = fmt2->fmt.win.w.width;
+- win->height = fmt2->fmt.win.w.height;
+- win->chromakey = fmt2->fmt.win.chromakey;
+- win->clips = NULL;
+- win->clipcount = 0;
+- break;
+- }
++ fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
++ if (!fmt) {
++ err = -ENOMEM;
++ return err;
++ }
++ memset(win, 0, sizeof(*win));
+
+- fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+- err = drv(inode, file, VIDIOC_G_FMT, fmt2);
+- if (err < 0) {
+- dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n",err);
+- break;
+- }
+- win->x = 0;
+- win->y = 0;
+- win->width = fmt2->fmt.pix.width;
+- win->height = fmt2->fmt.pix.height;
+- win->chromakey = 0;
++ fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
++ err = drv(inode, file, VIDIOC_G_FMT, fmt);
++ if (err < 0)
++ dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n", err);
++ if (err == 0) {
++ win->x = fmt->fmt.win.w.left;
++ win->y = fmt->fmt.win.w.top;
++ win->width = fmt->fmt.win.w.width;
++ win->height = fmt->fmt.win.w.height;
++ win->chromakey = fmt->fmt.win.chromakey;
+ win->clips = NULL;
+ win->clipcount = 0;
+- break;
++ goto done;
+ }
+- case VIDIOCSWIN: /* set window and/or capture dimensions */
+- {
+- struct video_window *win = arg;
+- int err1,err2;
+
+- fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+- if (!fmt2) {
+- err = -ENOMEM;
+- break;
+- }
+- fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+- drv(inode, file, VIDIOC_STREAMOFF, &fmt2->type);
+- err1 = drv(inode, file, VIDIOC_G_FMT, fmt2);
+- if (err1 < 0)
+- dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n",err);
+- if (err1 == 0) {
+- fmt2->fmt.pix.width = win->width;
+- fmt2->fmt.pix.height = win->height;
+- fmt2->fmt.pix.field = V4L2_FIELD_ANY;
+- fmt2->fmt.pix.bytesperline = 0;
+- err = drv(inode, file, VIDIOC_S_FMT, fmt2);
+- if (err < 0)
+- dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n",
+- err);
+- win->width = fmt2->fmt.pix.width;
+- win->height = fmt2->fmt.pix.height;
+- }
++ fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ err = drv(inode, file, VIDIOC_G_FMT, fmt);
++ if (err < 0) {
++ dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n", err);
++ goto done;
++ }
++ win->x = 0;
++ win->y = 0;
++ win->width = fmt->fmt.pix.width;
++ win->height = fmt->fmt.pix.height;
++ win->chromakey = 0;
++ win->clips = NULL;
++ win->clipcount = 0;
++done:
++ kfree(fmt);
++ return err;
++}
+
+- memset(fmt2,0,sizeof(*fmt2));
+- fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+- fmt2->fmt.win.w.left = win->x;
+- fmt2->fmt.win.w.top = win->y;
+- fmt2->fmt.win.w.width = win->width;
+- fmt2->fmt.win.w.height = win->height;
+- fmt2->fmt.win.chromakey = win->chromakey;
+- fmt2->fmt.win.clips = (void __user *)win->clips;
+- fmt2->fmt.win.clipcount = win->clipcount;
+- err2 = drv(inode, file, VIDIOC_S_FMT, fmt2);
+- if (err2 < 0)
+- dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n",err);
+-
+- if (err1 != 0 && err2 != 0)
+- err = err1;
+- break;
++static noinline int v4l1_compat_set_win_cap_dimensions(
++ struct video_window *win,
++ struct inode *inode,
++ struct file *file,
++ v4l2_kioctl drv)
++{
++ int err, err1, err2;
++ struct v4l2_format *fmt;
++
++ fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
++ if (!fmt) {
++ err = -ENOMEM;
++ return err;
+ }
+- case VIDIOCCAPTURE: /* turn on/off preview */
+- {
+- int *on = arg;
+-
+- if (0 == *on) {
+- /* dirty hack time. But v4l1 has no STREAMOFF
+- * equivalent in the API, and this one at
+- * least comes close ... */
+- drv(inode, file, VIDIOC_STREAMOFF, &captype);
+- }
+- err = drv(inode, file, VIDIOC_OVERLAY, arg);
++ fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ drv(inode, file, VIDIOC_STREAMOFF, &fmt->type);
++ err1 = drv(inode, file, VIDIOC_G_FMT, fmt);
++ if (err1 < 0)
++ dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n", err1);
++ if (err1 == 0) {
++ fmt->fmt.pix.width = win->width;
++ fmt->fmt.pix.height = win->height;
++ fmt->fmt.pix.field = V4L2_FIELD_ANY;
++ fmt->fmt.pix.bytesperline = 0;
++ err = drv(inode, file, VIDIOC_S_FMT, fmt);
+ if (err < 0)
+- dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n",err);
+- break;
++ dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n",
++ err);
++ win->width = fmt->fmt.pix.width;
++ win->height = fmt->fmt.pix.height;
+ }
+- case VIDIOCGCHAN: /* get input information */
+- {
+- struct video_channel *chan = arg;
+
+- memset(&input2,0,sizeof(input2));
+- input2.index = chan->channel;
+- err = drv(inode, file, VIDIOC_ENUMINPUT, &input2);
+- if (err < 0) {
+- dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: "
+- "channel=%d err=%d\n",chan->channel,err);
+- break;
+- }
+- chan->channel = input2.index;
+- memcpy(chan->name, input2.name,
+- min(sizeof(chan->name), sizeof(input2.name)));
+- chan->name[sizeof(chan->name) - 1] = 0;
+- chan->tuners = (input2.type == V4L2_INPUT_TYPE_TUNER) ? 1 : 0;
+- chan->flags = (chan->tuners) ? VIDEO_VC_TUNER : 0;
+- switch (input2.type) {
+- case V4L2_INPUT_TYPE_TUNER:
+- chan->type = VIDEO_TYPE_TV;
+- break;
+- default:
+- case V4L2_INPUT_TYPE_CAMERA:
+- chan->type = VIDEO_TYPE_CAMERA;
+- break;
+- }
+- chan->norm = 0;
+- err = drv(inode, file, VIDIOC_G_STD, &sid);
+- if (err < 0)
+- dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n",err);
+- if (err == 0) {
+- if (sid & V4L2_STD_PAL)
+- chan->norm = VIDEO_MODE_PAL;
+- if (sid & V4L2_STD_NTSC)
+- chan->norm = VIDEO_MODE_NTSC;
+- if (sid & V4L2_STD_SECAM)
+- chan->norm = VIDEO_MODE_SECAM;
+- }
+- break;
+- }
+- case VIDIOCSCHAN: /* set input */
+- {
+- struct video_channel *chan = arg;
++ memset(fmt, 0, sizeof(*fmt));
++ fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
++ fmt->fmt.win.w.left = win->x;
++ fmt->fmt.win.w.top = win->y;
++ fmt->fmt.win.w.width = win->width;
++ fmt->fmt.win.w.height = win->height;
++ fmt->fmt.win.chromakey = win->chromakey;
++ fmt->fmt.win.clips = (void __user *)win->clips;
++ fmt->fmt.win.clipcount = win->clipcount;
++ err2 = drv(inode, file, VIDIOC_S_FMT, fmt);
++ if (err2 < 0)
++ dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n", err2);
++
++ if (err1 != 0 && err2 != 0)
++ err = err1;
++ else
++ err = 0;
++ kfree(fmt);
++ return err;
++}
+
+- sid = 0;
+- err = drv(inode, file, VIDIOC_S_INPUT, &chan->channel);
+- if (err < 0)
+- dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n",err);
+- switch (chan->norm) {
+- case VIDEO_MODE_PAL:
+- sid = V4L2_STD_PAL;
+- break;
+- case VIDEO_MODE_NTSC:
+- sid = V4L2_STD_NTSC;
+- break;
+- case VIDEO_MODE_SECAM:
+- sid = V4L2_STD_SECAM;
+- break;
+- }
+- if (0 != sid) {
+- err = drv(inode, file, VIDIOC_S_STD, &sid);
+- if (err < 0)
+- dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n",err);
+- }
+- break;
++static noinline int v4l1_compat_turn_preview_on_off(
++ int *on,
++ struct inode *inode,
++ struct file *file,
++ v4l2_kioctl drv)
++{
++ int err;
++ enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++
++ if (0 == *on) {
++ /* dirty hack time. But v4l1 has no STREAMOFF
++ * equivalent in the API, and this one at
++ * least comes close ... */
++ drv(inode, file, VIDIOC_STREAMOFF, &captype);
+ }
+- case VIDIOCGPICT: /* get tone controls & partial capture format */
+- {
+- struct video_picture *pict = arg;
+-
+- fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+- if (!fmt2) {
+- err = -ENOMEM;
+- break;
+- }
++ err = drv(inode, file, VIDIOC_OVERLAY, on);
++ if (err < 0)
++ dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n", err);
++ return err;
++}
+
+- pict->brightness = get_v4l_control(inode, file,
+- V4L2_CID_BRIGHTNESS,drv);
+- pict->hue = get_v4l_control(inode, file,
+- V4L2_CID_HUE, drv);
+- pict->contrast = get_v4l_control(inode, file,
+- V4L2_CID_CONTRAST, drv);
+- pict->colour = get_v4l_control(inode, file,
+- V4L2_CID_SATURATION, drv);
+- pict->whiteness = get_v4l_control(inode, file,
+- V4L2_CID_WHITENESS, drv);
+-
+- fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+- err = drv(inode, file, VIDIOC_G_FMT, fmt2);
+- if (err < 0) {
+- dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n",err);
+- break;
+- }
++static noinline int v4l1_compat_get_input_info(
++ struct video_channel *chan,
++ struct inode *inode,
++ struct file *file,
++ v4l2_kioctl drv)
++{
++ int err;
++ struct v4l2_input input2;
++ v4l2_std_id sid;
+
+- pict->depth = ((fmt2->fmt.pix.bytesperline<<3)
+- + (fmt2->fmt.pix.width-1) )
+- /fmt2->fmt.pix.width;
+- pict->palette = pixelformat_to_palette(
+- fmt2->fmt.pix.pixelformat);
++ memset(&input2, 0, sizeof(input2));
++ input2.index = chan->channel;
++ err = drv(inode, file, VIDIOC_ENUMINPUT, &input2);
++ if (err < 0) {
++ dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: "
++ "channel=%d err=%d\n", chan->channel, err);
++ goto done;
++ }
++ chan->channel = input2.index;
++ memcpy(chan->name, input2.name,
++ min(sizeof(chan->name), sizeof(input2.name)));
++ chan->name[sizeof(chan->name) - 1] = 0;
++ chan->tuners = (input2.type == V4L2_INPUT_TYPE_TUNER) ? 1 : 0;
++ chan->flags = (chan->tuners) ? VIDEO_VC_TUNER : 0;
++ switch (input2.type) {
++ case V4L2_INPUT_TYPE_TUNER:
++ chan->type = VIDEO_TYPE_TV;
++ break;
++ default:
++ case V4L2_INPUT_TYPE_CAMERA:
++ chan->type = VIDEO_TYPE_CAMERA;
+ break;
+ }
+- case VIDIOCSPICT: /* set tone controls & partial capture format */
+- {
+- struct video_picture *pict = arg;
+- int mem_err = 0, ovl_err = 0;
++ chan->norm = 0;
++ err = drv(inode, file, VIDIOC_G_STD, &sid);
++ if (err < 0)
++ dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n", err);
++ if (err == 0) {
++ if (sid & V4L2_STD_PAL)
++ chan->norm = VIDEO_MODE_PAL;
++ if (sid & V4L2_STD_NTSC)
++ chan->norm = VIDEO_MODE_NTSC;
++ if (sid & V4L2_STD_SECAM)
++ chan->norm = VIDEO_MODE_SECAM;
++ }
++done:
++ return err;
++}
+
+- fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+- if (!fmt2) {
+- err = -ENOMEM;
+- break;
+- }
+- memset(&fbuf2, 0, sizeof(fbuf2));
+-
+- set_v4l_control(inode, file,
+- V4L2_CID_BRIGHTNESS, pict->brightness, drv);
+- set_v4l_control(inode, file,
+- V4L2_CID_HUE, pict->hue, drv);
+- set_v4l_control(inode, file,
+- V4L2_CID_CONTRAST, pict->contrast, drv);
+- set_v4l_control(inode, file,
+- V4L2_CID_SATURATION, pict->colour, drv);
+- set_v4l_control(inode, file,
+- V4L2_CID_WHITENESS, pict->whiteness, drv);
+- /*
+- * V4L1 uses this ioctl to set both memory capture and overlay
+- * pixel format, while V4L2 has two different ioctls for this.
+- * Some cards may not support one or the other, and may support
+- * different pixel formats for memory vs overlay.
+- */
+-
+- fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+- err = drv(inode, file, VIDIOC_G_FMT, fmt2);
+- /* If VIDIOC_G_FMT failed, then the driver likely doesn't
+- support memory capture. Trying to set the memory capture
+- parameters would be pointless. */
+- if (err < 0) {
+- dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n",err);
+- mem_err = -1000; /* didn't even try */
+- } else if (fmt2->fmt.pix.pixelformat !=
+- palette_to_pixelformat(pict->palette)) {
+- fmt2->fmt.pix.pixelformat = palette_to_pixelformat(
+- pict->palette);
+- mem_err = drv(inode, file, VIDIOC_S_FMT, fmt2);
+- if (mem_err < 0)
+- dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",
+- mem_err);
+- }
++static noinline int v4l1_compat_set_input(
++ struct video_channel *chan,
++ struct inode *inode,
++ struct file *file,
++ v4l2_kioctl drv)
++{
++ int err;
++ v4l2_std_id sid = 0;
+
+- err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
+- /* If VIDIOC_G_FBUF failed, then the driver likely doesn't
+- support overlay. Trying to set the overlay parameters
+- would be quite pointless. */
+- if (err < 0) {
+- dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n",err);
+- ovl_err = -1000; /* didn't even try */
+- } else if (fbuf2.fmt.pixelformat !=
+- palette_to_pixelformat(pict->palette)) {
+- fbuf2.fmt.pixelformat = palette_to_pixelformat(
+- pict->palette);
+- ovl_err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);
+- if (ovl_err < 0)
+- dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",
+- ovl_err);
+- }
+- if (ovl_err < 0 && mem_err < 0)
+- /* ioctl failed, couldn't set either parameter */
+- if (mem_err != -1000) {
+- err = mem_err;
+- } else if (ovl_err == -EPERM) {
+- err = 0;
+- } else {
+- err = ovl_err;
+- }
+- else
+- err = 0;
++ err = drv(inode, file, VIDIOC_S_INPUT, &chan->channel);
++ if (err < 0)
++ dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n", err);
++ switch (chan->norm) {
++ case VIDEO_MODE_PAL:
++ sid = V4L2_STD_PAL;
++ break;
++ case VIDEO_MODE_NTSC:
++ sid = V4L2_STD_NTSC;
++ break;
++ case VIDEO_MODE_SECAM:
++ sid = V4L2_STD_SECAM;
+ break;
+ }
+- case VIDIOCGTUNER: /* get tuner information */
+- {
+- struct video_tuner *tun = arg;
+-
+- memset(&tun2,0,sizeof(tun2));
+- err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
+- if (err < 0) {
+- dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n",err);
+- break;
+- }
+- memcpy(tun->name, tun2.name,
+- min(sizeof(tun->name), sizeof(tun2.name)));
+- tun->name[sizeof(tun->name) - 1] = 0;
+- tun->rangelow = tun2.rangelow;
+- tun->rangehigh = tun2.rangehigh;
+- tun->flags = 0;
+- tun->mode = VIDEO_MODE_AUTO;
+-
+- for (i = 0; i < 64; i++) {
+- memset(&std2,0,sizeof(std2));
+- std2.index = i;
+- if (0 != drv(inode, file, VIDIOC_ENUMSTD, &std2))
+- break;
+- if (std2.id & V4L2_STD_PAL)
+- tun->flags |= VIDEO_TUNER_PAL;
+- if (std2.id & V4L2_STD_NTSC)
+- tun->flags |= VIDEO_TUNER_NTSC;
+- if (std2.id & V4L2_STD_SECAM)
+- tun->flags |= VIDEO_TUNER_SECAM;
+- }
+-
+- err = drv(inode, file, VIDIOC_G_STD, &sid);
++ if (0 != sid) {
++ err = drv(inode, file, VIDIOC_S_STD, &sid);
+ if (err < 0)
+- dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n",err);
+- if (err == 0) {
+- if (sid & V4L2_STD_PAL)
+- tun->mode = VIDEO_MODE_PAL;
+- if (sid & V4L2_STD_NTSC)
+- tun->mode = VIDEO_MODE_NTSC;
+- if (sid & V4L2_STD_SECAM)
+- tun->mode = VIDEO_MODE_SECAM;
+- }
+-
+- if (tun2.capability & V4L2_TUNER_CAP_LOW)
+- tun->flags |= VIDEO_TUNER_LOW;
+- if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
+- tun->flags |= VIDEO_TUNER_STEREO_ON;
+- tun->signal = tun2.signal;
+- break;
++ dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n", err);
+ }
+- case VIDIOCSTUNER: /* select a tuner input */
+- {
+- struct video_tuner *tun = arg;
+- struct v4l2_tuner t;
+- memset(&t,0,sizeof(t));
+-
+- t.index=tun->tuner;
++ return err;
++}
+
+- err = drv(inode, file, VIDIOC_S_INPUT, &t);
+- if (err < 0)
+- dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n",err);
++static noinline int v4l1_compat_get_picture(
++ struct video_picture *pict,
++ struct inode *inode,
++ struct file *file,
++ v4l2_kioctl drv)
++{
++ int err;
++ struct v4l2_format *fmt;
+
+- break;
++ fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
++ if (!fmt) {
++ err = -ENOMEM;
++ return err;
+ }
+- case VIDIOCGFREQ: /* get frequency */
+- {
+- unsigned long *freq = arg;
+- memset(&freq2,0,sizeof(freq2));
+
+- freq2.tuner = 0;
+- err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
+- if (err < 0)
+- dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n",err);
+- if (0 == err)
+- *freq = freq2.frequency;
+- break;
++ pict->brightness = get_v4l_control(inode, file,
++ V4L2_CID_BRIGHTNESS, drv);
++ pict->hue = get_v4l_control(inode, file,
++ V4L2_CID_HUE, drv);
++ pict->contrast = get_v4l_control(inode, file,
++ V4L2_CID_CONTRAST, drv);
++ pict->colour = get_v4l_control(inode, file,
++ V4L2_CID_SATURATION, drv);
++ pict->whiteness = get_v4l_control(inode, file,
++ V4L2_CID_WHITENESS, drv);
++
++ fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ err = drv(inode, file, VIDIOC_G_FMT, fmt);
++ if (err < 0) {
++ dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n", err);
++ goto done;
+ }
+- case VIDIOCSFREQ: /* set frequency */
+- {
+- unsigned long *freq = arg;
+- memset(&freq2,0,sizeof(freq2));
+
+- drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
+- freq2.frequency = *freq;
+- err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2);
+- if (err < 0)
+- dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n",err);
+- break;
++ pict->depth = ((fmt->fmt.pix.bytesperline << 3)
++ + (fmt->fmt.pix.width - 1))
++ / fmt->fmt.pix.width;
++ pict->palette = pixelformat_to_palette(
++ fmt->fmt.pix.pixelformat);
++done:
++ kfree(fmt);
++ return err;
++}
++
++static noinline int v4l1_compat_set_picture(
++ struct video_picture *pict,
++ struct inode *inode,
++ struct file *file,
++ v4l2_kioctl drv)
++{
++ int err;
++ struct v4l2_framebuffer fbuf;
++ int mem_err = 0, ovl_err = 0;
++ struct v4l2_format *fmt;
++
++ fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
++ if (!fmt) {
++ err = -ENOMEM;
++ return err;
++ }
++ memset(&fbuf, 0, sizeof(fbuf));
++
++ set_v4l_control(inode, file,
++ V4L2_CID_BRIGHTNESS, pict->brightness, drv);
++ set_v4l_control(inode, file,
++ V4L2_CID_HUE, pict->hue, drv);
++ set_v4l_control(inode, file,
++ V4L2_CID_CONTRAST, pict->contrast, drv);
++ set_v4l_control(inode, file,
++ V4L2_CID_SATURATION, pict->colour, drv);
++ set_v4l_control(inode, file,
++ V4L2_CID_WHITENESS, pict->whiteness, drv);
++ /*
++ * V4L1 uses this ioctl to set both memory capture and overlay
++ * pixel format, while V4L2 has two different ioctls for this.
++ * Some cards may not support one or the other, and may support
++ * different pixel formats for memory vs overlay.
++ */
++
++ fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ err = drv(inode, file, VIDIOC_G_FMT, fmt);
++ /* If VIDIOC_G_FMT failed, then the driver likely doesn't
++ support memory capture. Trying to set the memory capture
++ parameters would be pointless. */
++ if (err < 0) {
++ dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n", err);
++ mem_err = -1000; /* didn't even try */
++ } else if (fmt->fmt.pix.pixelformat !=
++ palette_to_pixelformat(pict->palette)) {
++ fmt->fmt.pix.pixelformat = palette_to_pixelformat(
++ pict->palette);
++ mem_err = drv(inode, file, VIDIOC_S_FMT, fmt);
++ if (mem_err < 0)
++ dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",
++ mem_err);
+ }
+- case VIDIOCGAUDIO: /* get audio properties/controls */
+- {
+- struct video_audio *aud = arg;
+- memset(&aud2,0,sizeof(aud2));
+
+- err = drv(inode, file, VIDIOC_G_AUDIO, &aud2);
+- if (err < 0) {
+- dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n",err);
+- break;
+- }
+- memcpy(aud->name, aud2.name,
+- min(sizeof(aud->name), sizeof(aud2.name)));
+- aud->name[sizeof(aud->name) - 1] = 0;
+- aud->audio = aud2.index;
+- aud->flags = 0;
+- i = get_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, drv);
+- if (i >= 0) {
+- aud->volume = i;
+- aud->flags |= VIDEO_AUDIO_VOLUME;
+- }
+- i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv);
+- if (i >= 0) {
+- aud->bass = i;
+- aud->flags |= VIDEO_AUDIO_BASS;
+- }
+- i = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv);
+- if (i >= 0) {
+- aud->treble = i;
+- aud->flags |= VIDEO_AUDIO_TREBLE;
+- }
+- i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv);
+- if (i >= 0) {
+- aud->balance = i;
+- aud->flags |= VIDEO_AUDIO_BALANCE;
+- }
+- i = get_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, drv);
+- if (i >= 0) {
+- if (i)
+- aud->flags |= VIDEO_AUDIO_MUTE;
+- aud->flags |= VIDEO_AUDIO_MUTABLE;
+- }
+- aud->step = 1;
+- qctrl2.id = V4L2_CID_AUDIO_VOLUME;
+- if (drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2) == 0 &&
+- !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
+- aud->step = qctrl2.step;
+- aud->mode = 0;
+-
+- memset(&tun2,0,sizeof(tun2));
+- err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
+- if (err < 0) {
+- dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n",err);
++ err = drv(inode, file, VIDIOC_G_FBUF, &fbuf);
++ /* If VIDIOC_G_FBUF failed, then the driver likely doesn't
++ support overlay. Trying to set the overlay parameters
++ would be quite pointless. */
++ if (err < 0) {
++ dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n", err);
++ ovl_err = -1000; /* didn't even try */
++ } else if (fbuf.fmt.pixelformat !=
++ palette_to_pixelformat(pict->palette)) {
++ fbuf.fmt.pixelformat = palette_to_pixelformat(
++ pict->palette);
++ ovl_err = drv(inode, file, VIDIOC_S_FBUF, &fbuf);
++ if (ovl_err < 0)
++ dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",
++ ovl_err);
++ }
++ if (ovl_err < 0 && mem_err < 0) {
++ /* ioctl failed, couldn't set either parameter */
++ if (mem_err != -1000)
++ err = mem_err;
++ else if (ovl_err == -EPERM)
+ err = 0;
++ else
++ err = ovl_err;
++ } else
++ err = 0;
++ kfree(fmt);
++ return err;
++}
++
++static noinline int v4l1_compat_get_tuner(
++ struct video_tuner *tun,
++ struct inode *inode,
++ struct file *file,
++ v4l2_kioctl drv)
++{
++ int err, i;
++ struct v4l2_tuner tun2;
++ struct v4l2_standard std2;
++ v4l2_std_id sid;
++
++ memset(&tun2, 0, sizeof(tun2));
++ err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
++ if (err < 0) {
++ dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n", err);
++ goto done;
++ }
++ memcpy(tun->name, tun2.name,
++ min(sizeof(tun->name), sizeof(tun2.name)));
++ tun->name[sizeof(tun->name) - 1] = 0;
++ tun->rangelow = tun2.rangelow;
++ tun->rangehigh = tun2.rangehigh;
++ tun->flags = 0;
++ tun->mode = VIDEO_MODE_AUTO;
++
++ for (i = 0; i < 64; i++) {
++ memset(&std2, 0, sizeof(std2));
++ std2.index = i;
++ if (0 != drv(inode, file, VIDIOC_ENUMSTD, &std2))
+ break;
+- }
++ if (std2.id & V4L2_STD_PAL)
++ tun->flags |= VIDEO_TUNER_PAL;
++ if (std2.id & V4L2_STD_NTSC)
++ tun->flags |= VIDEO_TUNER_NTSC;
++ if (std2.id & V4L2_STD_SECAM)
++ tun->flags |= VIDEO_TUNER_SECAM;
++ }
+
+- if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2)
+- aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+- else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
+- aud->mode = VIDEO_SOUND_STEREO;
+- else if (tun2.rxsubchans & V4L2_TUNER_SUB_MONO)
+- aud->mode = VIDEO_SOUND_MONO;
+- break;
++ err = drv(inode, file, VIDIOC_G_STD, &sid);
++ if (err < 0)
++ dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n", err);
++ if (err == 0) {
++ if (sid & V4L2_STD_PAL)
++ tun->mode = VIDEO_MODE_PAL;
++ if (sid & V4L2_STD_NTSC)
++ tun->mode = VIDEO_MODE_NTSC;
++ if (sid & V4L2_STD_SECAM)
++ tun->mode = VIDEO_MODE_SECAM;
+ }
+- case VIDIOCSAUDIO: /* set audio controls */
+- {
+- struct video_audio *aud = arg;
+
+- memset(&aud2,0,sizeof(aud2));
+- memset(&tun2,0,sizeof(tun2));
++ if (tun2.capability & V4L2_TUNER_CAP_LOW)
++ tun->flags |= VIDEO_TUNER_LOW;
++ if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
++ tun->flags |= VIDEO_TUNER_STEREO_ON;
++ tun->signal = tun2.signal;
++done:
++ return err;
++}
+
+- aud2.index = aud->audio;
+- err = drv(inode, file, VIDIOC_S_AUDIO, &aud2);
+- if (err < 0) {
+- dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n",err);
+- break;
+- }
++static noinline int v4l1_compat_select_tuner(
++ struct video_tuner *tun,
++ struct inode *inode,
++ struct file *file,
++ v4l2_kioctl drv)
++{
++ int err;
++ struct v4l2_tuner t;/*84 bytes on x86_64*/
++ memset(&t, 0, sizeof(t));
+
+- set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME,
+- aud->volume, drv);
+- set_v4l_control(inode, file, V4L2_CID_AUDIO_BASS,
+- aud->bass, drv);
+- set_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE,
+- aud->treble, drv);
+- set_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE,
+- aud->balance, drv);
+- set_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE,
+- !!(aud->flags & VIDEO_AUDIO_MUTE), drv);
+-
+- err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
+- if (err < 0)
+- dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n",err);
+- if (err == 0) {
+- switch (aud->mode) {
+- default:
+- case VIDEO_SOUND_MONO:
+- case VIDEO_SOUND_LANG1:
+- tun2.audmode = V4L2_TUNER_MODE_MONO;
+- break;
+- case VIDEO_SOUND_STEREO:
+- tun2.audmode = V4L2_TUNER_MODE_STEREO;
+- break;
+- case VIDEO_SOUND_LANG2:
+- tun2.audmode = V4L2_TUNER_MODE_LANG2;
+- break;
+- }
+- err = drv(inode, file, VIDIOC_S_TUNER, &tun2);
+- if (err < 0)
+- dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n",err);
+- }
++ t.index = tun->tuner;
++
++ err = drv(inode, file, VIDIOC_S_INPUT, &t);
++ if (err < 0)
++ dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n", err);
++ return err;
++}
++
++static noinline int v4l1_compat_get_frequency(
++ unsigned long *freq,
++ struct inode *inode,
++ struct file *file,
++ v4l2_kioctl drv)
++{
++ int err;
++ struct v4l2_frequency freq2;
++ memset(&freq2, 0, sizeof(freq2));
++
++ freq2.tuner = 0;
++ err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
++ if (err < 0)
++ dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n", err);
++ if (0 == err)
++ *freq = freq2.frequency;
++ return err;
++}
++
++static noinline int v4l1_compat_set_frequency(
++ unsigned long *freq,
++ struct inode *inode,
++ struct file *file,
++ v4l2_kioctl drv)
++{
++ int err;
++ struct v4l2_frequency freq2;
++ memset(&freq2, 0, sizeof(freq2));
++
++ drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
++ freq2.frequency = *freq;
++ err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2);
++ if (err < 0)
++ dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n", err);
++ return err;
++}
++
++static noinline int v4l1_compat_get_audio(
++ struct video_audio *aud,
++ struct inode *inode,
++ struct file *file,
++ v4l2_kioctl drv)
++{
++ int err, i;
++ struct v4l2_queryctrl qctrl2;
++ struct v4l2_audio aud2;
++ struct v4l2_tuner tun2;
++ memset(&aud2, 0, sizeof(aud2));
++
++ err = drv(inode, file, VIDIOC_G_AUDIO, &aud2);
++ if (err < 0) {
++ dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n", err);
++ goto done;
++ }
++ memcpy(aud->name, aud2.name,
++ min(sizeof(aud->name), sizeof(aud2.name)));
++ aud->name[sizeof(aud->name) - 1] = 0;
++ aud->audio = aud2.index;
++ aud->flags = 0;
++ i = get_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, drv);
++ if (i >= 0) {
++ aud->volume = i;
++ aud->flags |= VIDEO_AUDIO_VOLUME;
++ }
++ i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv);
++ if (i >= 0) {
++ aud->bass = i;
++ aud->flags |= VIDEO_AUDIO_BASS;
++ }
++ i = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv);
++ if (i >= 0) {
++ aud->treble = i;
++ aud->flags |= VIDEO_AUDIO_TREBLE;
++ }
++ i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv);
++ if (i >= 0) {
++ aud->balance = i;
++ aud->flags |= VIDEO_AUDIO_BALANCE;
++ }
++ i = get_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, drv);
++ if (i >= 0) {
++ if (i)
++ aud->flags |= VIDEO_AUDIO_MUTE;
++ aud->flags |= VIDEO_AUDIO_MUTABLE;
++ }
++ aud->step = 1;
++ qctrl2.id = V4L2_CID_AUDIO_VOLUME;
++ if (drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2) == 0 &&
++ !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
++ aud->step = qctrl2.step;
++ aud->mode = 0;
++
++ memset(&tun2, 0, sizeof(tun2));
++ err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
++ if (err < 0) {
++ dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n", err);
+ err = 0;
+- break;
++ goto done;
+ }
+- case VIDIOCMCAPTURE: /* capture a frame */
+- {
+- struct video_mmap *mm = arg;
+
+- fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+- if (!fmt2) {
+- err = -ENOMEM;
+- break;
+- }
+- memset(&buf2,0,sizeof(buf2));
++ if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2)
++ aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
++ else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
++ aud->mode = VIDEO_SOUND_STEREO;
++ else if (tun2.rxsubchans & V4L2_TUNER_SUB_MONO)
++ aud->mode = VIDEO_SOUND_MONO;
++done:
++ return err;
++}
+
+- fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+- err = drv(inode, file, VIDIOC_G_FMT, fmt2);
+- if (err < 0) {
+- dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n",err);
++static noinline int v4l1_compat_set_audio(
++ struct video_audio *aud,
++ struct inode *inode,
++ struct file *file,
++ v4l2_kioctl drv)
++{
++ int err;
++ struct v4l2_audio aud2;
++ struct v4l2_tuner tun2;
++
++ memset(&aud2, 0, sizeof(aud2));
++ memset(&tun2, 0, sizeof(tun2));
++
++ aud2.index = aud->audio;
++ err = drv(inode, file, VIDIOC_S_AUDIO, &aud2);
++ if (err < 0) {
++ dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n", err);
++ goto done;
++ }
++
++ set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME,
++ aud->volume, drv);
++ set_v4l_control(inode, file, V4L2_CID_AUDIO_BASS,
++ aud->bass, drv);
++ set_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE,
++ aud->treble, drv);
++ set_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE,
++ aud->balance, drv);
++ set_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE,
++ !!(aud->flags & VIDEO_AUDIO_MUTE), drv);
++
++ err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
++ if (err < 0)
++ dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n", err);
++ if (err == 0) {
++ switch (aud->mode) {
++ default:
++ case VIDEO_SOUND_MONO:
++ case VIDEO_SOUND_LANG1:
++ tun2.audmode = V4L2_TUNER_MODE_MONO;
+ break;
+- }
+- if (mm->width != fmt2->fmt.pix.width ||
+- mm->height != fmt2->fmt.pix.height ||
+- palette_to_pixelformat(mm->format) !=
+- fmt2->fmt.pix.pixelformat)
+- {/* New capture format... */
+- fmt2->fmt.pix.width = mm->width;
+- fmt2->fmt.pix.height = mm->height;
+- fmt2->fmt.pix.pixelformat =
+- palette_to_pixelformat(mm->format);
+- fmt2->fmt.pix.field = V4L2_FIELD_ANY;
+- fmt2->fmt.pix.bytesperline = 0;
+- err = drv(inode, file, VIDIOC_S_FMT, fmt2);
+- if (err < 0) {
+- dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n",err);
+- break;
+- }
+- }
+- buf2.index = mm->frame;
+- buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+- err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
+- if (err < 0) {
+- dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n",err);
++ case VIDEO_SOUND_STEREO:
++ tun2.audmode = V4L2_TUNER_MODE_STEREO;
+ break;
+- }
+- err = drv(inode, file, VIDIOC_QBUF, &buf2);
+- if (err < 0) {
+- dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n",err);
++ case VIDEO_SOUND_LANG2:
++ tun2.audmode = V4L2_TUNER_MODE_LANG2;
+ break;
+ }
+- err = drv(inode, file, VIDIOC_STREAMON, &captype);
++ err = drv(inode, file, VIDIOC_S_TUNER, &tun2);
+ if (err < 0)
+- dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n",err);
+- break;
++ dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n", err);
+ }
+- case VIDIOCSYNC: /* wait for a frame */
+- {
+- int *i = arg;
++ err = 0;
++done:
++ return err;
++}
+
+- memset(&buf2,0,sizeof(buf2));
+- buf2.index = *i;
+- buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+- err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
+- if (err < 0) {
+- /* No such buffer */
+- dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n",err);
+- break;
+- }
+- if (!(buf2.flags & V4L2_BUF_FLAG_MAPPED)) {
+- /* Buffer is not mapped */
+- err = -EINVAL;
+- break;
+- }
++static noinline int v4l1_compat_capture_frame(
++ struct video_mmap *mm,
++ struct inode *inode,
++ struct file *file,
++ v4l2_kioctl drv)
++{
++ int err;
++ enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ struct v4l2_buffer buf;
++ struct v4l2_format *fmt;
++
++ fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
++ if (!fmt) {
++ err = -ENOMEM;
++ return err;
++ }
++ memset(&buf, 0, sizeof(buf));
+
+- /* make sure capture actually runs so we don't block forever */
+- err = drv(inode, file, VIDIOC_STREAMON, &captype);
++ fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ err = drv(inode, file, VIDIOC_G_FMT, fmt);
++ if (err < 0) {
++ dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n", err);
++ goto done;
++ }
++ if (mm->width != fmt->fmt.pix.width ||
++ mm->height != fmt->fmt.pix.height ||
++ palette_to_pixelformat(mm->format) !=
++ fmt->fmt.pix.pixelformat) {
++ /* New capture format... */
++ fmt->fmt.pix.width = mm->width;
++ fmt->fmt.pix.height = mm->height;
++ fmt->fmt.pix.pixelformat =
++ palette_to_pixelformat(mm->format);
++ fmt->fmt.pix.field = V4L2_FIELD_ANY;
++ fmt->fmt.pix.bytesperline = 0;
++ err = drv(inode, file, VIDIOC_S_FMT, fmt);
+ if (err < 0) {
+- dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n",err);
+- break;
++ dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n", err);
++ goto done;
+ }
++ }
++ buf.index = mm->frame;
++ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ err = drv(inode, file, VIDIOC_QUERYBUF, &buf);
++ if (err < 0) {
++ dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n", err);
++ goto done;
++ }
++ err = drv(inode, file, VIDIOC_QBUF, &buf);
++ if (err < 0) {
++ dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n", err);
++ goto done;
++ }
++ err = drv(inode, file, VIDIOC_STREAMON, &captype);
++ if (err < 0)
++ dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n", err);
++done:
++ kfree(fmt);
++ return err;
++}
+
+- /* Loop as long as the buffer is queued, but not done */
+- while ((buf2.flags &
+- (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))
+- == V4L2_BUF_FLAG_QUEUED)
+- {
+- err = poll_one(file);
+- if (err < 0 || /* error or sleep was interrupted */
+- err == 0) /* timeout? Shouldn't occur. */
+- break;
+- err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
+- if (err < 0)
+- dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n",err);
+- }
+- if (!(buf2.flags & V4L2_BUF_FLAG_DONE)) /* not done */
+- break;
+- do {
+- err = drv(inode, file, VIDIOC_DQBUF, &buf2);
+- if (err < 0)
+- dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n",err);
+- } while (err == 0 && buf2.index != *i);
+- break;
++static noinline int v4l1_compat_sync(
++ int *i,
++ struct inode *inode,
++ struct file *file,
++ v4l2_kioctl drv)
++{
++ int err;
++ enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ struct v4l2_buffer buf;
++ struct poll_wqueues *pwq;
++
++ memset(&buf, 0, sizeof(buf));
++ buf.index = *i;
++ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ err = drv(inode, file, VIDIOC_QUERYBUF, &buf);
++ if (err < 0) {
++ /* No such buffer */
++ dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err);
++ goto done;
++ }
++ if (!(buf.flags & V4L2_BUF_FLAG_MAPPED)) {
++ /* Buffer is not mapped */
++ err = -EINVAL;
++ goto done;
+ }
+
+- case VIDIOCGVBIFMT: /* query VBI data capture format */
+- {
+- struct vbi_format *fmt = arg;
++ /* make sure capture actually runs so we don't block forever */
++ err = drv(inode, file, VIDIOC_STREAMON, &captype);
++ if (err < 0) {
++ dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n", err);
++ goto done;
++ }
+
+- fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+- if (!fmt2) {
+- err = -ENOMEM;
++ pwq = kmalloc(sizeof(*pwq), GFP_KERNEL);
++ /* Loop as long as the buffer is queued, but not done */
++ while ((buf.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))
++ == V4L2_BUF_FLAG_QUEUED) {
++ err = poll_one(file, pwq);
++ if (err < 0 || /* error or sleep was interrupted */
++ err == 0) /* timeout? Shouldn't occur. */
+ break;
+- }
+- fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
++ err = drv(inode, file, VIDIOC_QUERYBUF, &buf);
++ if (err < 0)
++ dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err);
++ }
++ kfree(pwq);
++ if (!(buf.flags & V4L2_BUF_FLAG_DONE)) /* not done */
++ goto done;
++ do {
++ err = drv(inode, file, VIDIOC_DQBUF, &buf);
++ if (err < 0)
++ dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n", err);
++ } while (err == 0 && buf.index != *i);
++done:
++ return err;
++}
+
+- err = drv(inode, file, VIDIOC_G_FMT, fmt2);
+- if (err < 0) {
+- dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err);
+- break;
+- }
+- if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) {
+- err = -EINVAL;
+- break;
+- }
+- memset(fmt, 0, sizeof(*fmt));
+- fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line;
+- fmt->sampling_rate = fmt2->fmt.vbi.sampling_rate;
+- fmt->sample_format = VIDEO_PALETTE_RAW;
+- fmt->start[0] = fmt2->fmt.vbi.start[0];
+- fmt->count[0] = fmt2->fmt.vbi.count[0];
+- fmt->start[1] = fmt2->fmt.vbi.start[1];
+- fmt->count[1] = fmt2->fmt.vbi.count[1];
+- fmt->flags = fmt2->fmt.vbi.flags & 0x03;
+- break;
++static noinline int v4l1_compat_get_vbi_format(
++ struct vbi_format *fmt,
++ struct inode *inode,
++ struct file *file,
++ v4l2_kioctl drv)
++{
++ int err;
++ struct v4l2_format *fmt2;
++
++ fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
++ if (!fmt2) {
++ err = -ENOMEM;
++ return err;
+ }
+- case VIDIOCSVBIFMT:
+- {
+- struct vbi_format *fmt = arg;
++ fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
+
+- if (VIDEO_PALETTE_RAW != fmt->sample_format) {
+- err = -EINVAL;
+- break;
+- }
++ err = drv(inode, file, VIDIOC_G_FMT, fmt2);
++ if (err < 0) {
++ dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err);
++ goto done;
++ }
++ if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) {
++ err = -EINVAL;
++ goto done;
++ }
++ memset(fmt, 0, sizeof(*fmt));
++ fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line;
++ fmt->sampling_rate = fmt2->fmt.vbi.sampling_rate;
++ fmt->sample_format = VIDEO_PALETTE_RAW;
++ fmt->start[0] = fmt2->fmt.vbi.start[0];
++ fmt->count[0] = fmt2->fmt.vbi.count[0];
++ fmt->start[1] = fmt2->fmt.vbi.start[1];
++ fmt->count[1] = fmt2->fmt.vbi.count[1];
++ fmt->flags = fmt2->fmt.vbi.flags & 0x03;
++done:
++ kfree(fmt2);
++ return err;
++}
+
+- fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+- if (!fmt2) {
+- err = -ENOMEM;
+- break;
+- }
+- fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
+- fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line;
+- fmt2->fmt.vbi.sampling_rate = fmt->sampling_rate;
+- fmt2->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
+- fmt2->fmt.vbi.start[0] = fmt->start[0];
+- fmt2->fmt.vbi.count[0] = fmt->count[0];
+- fmt2->fmt.vbi.start[1] = fmt->start[1];
+- fmt2->fmt.vbi.count[1] = fmt->count[1];
+- fmt2->fmt.vbi.flags = fmt->flags;
+- err = drv(inode, file, VIDIOC_TRY_FMT, fmt2);
+- if (err < 0) {
+- dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err);
+- break;
+- }
++static noinline int v4l1_compat_set_vbi_format(
++ struct vbi_format *fmt,
++ struct inode *inode,
++ struct file *file,
++ v4l2_kioctl drv)
++{
++ int err;
++ struct v4l2_format *fmt2 = NULL;
+
+- if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line ||
+- fmt2->fmt.vbi.sampling_rate != fmt->sampling_rate ||
+- fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY ||
+- fmt2->fmt.vbi.start[0] != fmt->start[0] ||
+- fmt2->fmt.vbi.count[0] != fmt->count[0] ||
+- fmt2->fmt.vbi.start[1] != fmt->start[1] ||
+- fmt2->fmt.vbi.count[1] != fmt->count[1] ||
+- fmt2->fmt.vbi.flags != fmt->flags) {
+- err = -EINVAL;
+- break;
+- }
+- err = drv(inode, file, VIDIOC_S_FMT, fmt2);
+- if (err < 0)
+- dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err);
+- break;
++ if (VIDEO_PALETTE_RAW != fmt->sample_format) {
++ err = -EINVAL;
++ return err;
+ }
+
++ fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
++ if (!fmt2) {
++ err = -ENOMEM;
++ return err;
++ }
++ fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
++ fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line;
++ fmt2->fmt.vbi.sampling_rate = fmt->sampling_rate;
++ fmt2->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
++ fmt2->fmt.vbi.start[0] = fmt->start[0];
++ fmt2->fmt.vbi.count[0] = fmt->count[0];
++ fmt2->fmt.vbi.start[1] = fmt->start[1];
++ fmt2->fmt.vbi.count[1] = fmt->count[1];
++ fmt2->fmt.vbi.flags = fmt->flags;
++ err = drv(inode, file, VIDIOC_TRY_FMT, fmt2);
++ if (err < 0) {
++ dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err);
++ goto done;
++ }
++
++ if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line ||
++ fmt2->fmt.vbi.sampling_rate != fmt->sampling_rate ||
++ fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY ||
++ fmt2->fmt.vbi.start[0] != fmt->start[0] ||
++ fmt2->fmt.vbi.count[0] != fmt->count[0] ||
++ fmt2->fmt.vbi.start[1] != fmt->start[1] ||
++ fmt2->fmt.vbi.count[1] != fmt->count[1] ||
++ fmt2->fmt.vbi.flags != fmt->flags) {
++ err = -EINVAL;
++ goto done;
++ }
++ err = drv(inode, file, VIDIOC_S_FMT, fmt2);
++ if (err < 0)
++ dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err);
++done:
++ kfree(fmt2);
++ return err;
++}
++
++/*
++ * This function is exported.
++ */
++int
++v4l_compat_translate_ioctl(struct inode *inode,
++ struct file *file,
++ int cmd,
++ void *arg,
++ v4l2_kioctl drv)
++{
++ int err;
++
++ switch (cmd) {
++ case VIDIOCGCAP: /* capability */
++ err = v4l1_compat_get_capabilities(arg, inode, file, drv);
++ break;
++ case VIDIOCGFBUF: /* get frame buffer */
++ err = v4l1_compat_get_frame_buffer(arg, inode, file, drv);
++ break;
++ case VIDIOCSFBUF: /* set frame buffer */
++ err = v4l1_compat_set_frame_buffer(arg, inode, file, drv);
++ break;
++ case VIDIOCGWIN: /* get window or capture dimensions */
++ err = v4l1_compat_get_win_cap_dimensions(arg, inode, file, drv);
++ break;
++ case VIDIOCSWIN: /* set window and/or capture dimensions */
++ err = v4l1_compat_set_win_cap_dimensions(arg, inode, file, drv);
++ break;
++ case VIDIOCCAPTURE: /* turn on/off preview */
++ err = v4l1_compat_turn_preview_on_off(arg, inode, file, drv);
++ break;
++ case VIDIOCGCHAN: /* get input information */
++ err = v4l1_compat_get_input_info(arg, inode, file, drv);
++ break;
++ case VIDIOCSCHAN: /* set input */
++ err = v4l1_compat_set_input(arg, inode, file, drv);
++ break;
++ case VIDIOCGPICT: /* get tone controls & partial capture format */
++ err = v4l1_compat_get_picture(arg, inode, file, drv);
++ break;
++ case VIDIOCSPICT: /* set tone controls & partial capture format */
++ err = v4l1_compat_set_picture(arg, inode, file, drv);
++ break;
++ case VIDIOCGTUNER: /* get tuner information */
++ err = v4l1_compat_get_tuner(arg, inode, file, drv);
++ break;
++ case VIDIOCSTUNER: /* select a tuner input */
++ err = v4l1_compat_select_tuner(arg, inode, file, drv);
++ break;
++ case VIDIOCGFREQ: /* get frequency */
++ err = v4l1_compat_get_frequency(arg, inode, file, drv);
++ break;
++ case VIDIOCSFREQ: /* set frequency */
++ err = v4l1_compat_set_frequency(arg, inode, file, drv);
++ break;
++ case VIDIOCGAUDIO: /* get audio properties/controls */
++ err = v4l1_compat_get_audio(arg, inode, file, drv);
++ break;
++ case VIDIOCSAUDIO: /* set audio controls */
++ err = v4l1_compat_set_audio(arg, inode, file, drv);
++ break;
++ case VIDIOCMCAPTURE: /* capture a frame */
++ err = v4l1_compat_capture_frame(arg, inode, file, drv);
++ break;
++ case VIDIOCSYNC: /* wait for a frame */
++ err = v4l1_compat_sync(arg, inode, file, drv);
++ break;
++ case VIDIOCGVBIFMT: /* query VBI data capture format */
++ err = v4l1_compat_get_vbi_format(arg, inode, file, drv);
++ break;
++ case VIDIOCSVBIFMT:
++ err = v4l1_compat_set_vbi_format(arg, inode, file, drv);
++ break;
+ default:
+ err = -ENOIOCTLCMD;
+ break;
+ }
+
+- kfree(cap2);
+- kfree(fmt2);
+ return err;
+ }
+-
+ EXPORT_SYMBOL(v4l_compat_translate_ioctl);
+
+ /*
+diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c
+index eab79ff..fc51e49 100644
+--- a/drivers/media/video/videobuf-core.c
++++ b/drivers/media/video/videobuf-core.c
+@@ -64,32 +64,25 @@ void *videobuf_alloc(struct videobuf_queue *q)
+ return vb;
+ }
+
++#define WAITON_CONDITION (vb->state != VIDEOBUF_ACTIVE &&\
++ vb->state != VIDEOBUF_QUEUED)
+ int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr)
+ {
+- int retval = 0;
+- DECLARE_WAITQUEUE(wait, current);
+-
+ MAGIC_CHECK(vb->magic, MAGIC_BUFFER);
+- add_wait_queue(&vb->done, &wait);
+- while (vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED) {
+- if (non_blocking) {
+- retval = -EAGAIN;
+- break;
+- }
+- set_current_state(intr ? TASK_INTERRUPTIBLE
+- : TASK_UNINTERRUPTIBLE);
+- if (vb->state == VIDEOBUF_ACTIVE ||
+- vb->state == VIDEOBUF_QUEUED)
+- schedule();
+- set_current_state(TASK_RUNNING);
+- if (intr && signal_pending(current)) {
+- dprintk(1, "buffer waiton: -EINTR\n");
+- retval = -EINTR;
+- break;
+- }
++
++ if (non_blocking) {
++ if (WAITON_CONDITION)
++ return 0;
++ else
++ return -EAGAIN;
+ }
+- remove_wait_queue(&vb->done, &wait);
+- return retval;
++
++ if (intr)
++ return wait_event_interruptible(vb->done, WAITON_CONDITION);
++ else
++ wait_event(vb->done, WAITON_CONDITION);
++
++ return 0;
+ }
+
+ int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb,
+@@ -98,29 +91,22 @@ int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb,
+ MAGIC_CHECK(vb->magic, MAGIC_BUFFER);
+ MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
+
+- /* This is required to avoid OOPS on some cases,
+- since mmap_mapper() method should be called before _iolock.
+- On some cases, the mmap_mapper() is called only after scheduling.
+- */
+- if (vb->memory == V4L2_MEMORY_MMAP) {
+- wait_event_timeout(vb->done, q->is_mmapped,
+- msecs_to_jiffies(100));
+- if (!q->is_mmapped) {
+- printk(KERN_ERR
+- "Error: mmap_mapper() never called!\n");
+- return -EINVAL;
+- }
+- }
+-
+ return CALL(q, iolock, q, vb, fbuf);
+ }
+
++void *videobuf_queue_to_vmalloc (struct videobuf_queue *q,
++ struct videobuf_buffer *buf)
++{
++ return CALL(q, vmalloc, buf);
++}
++EXPORT_SYMBOL_GPL(videobuf_queue_to_vmalloc);
++
+ /* --------------------------------------------------------------------- */
+
+
+ void videobuf_queue_core_init(struct videobuf_queue *q,
+ struct videobuf_queue_ops *ops,
+- void *dev,
++ struct device *dev,
+ spinlock_t *irqlock,
+ enum v4l2_buf_type type,
+ enum v4l2_field field,
+@@ -144,10 +130,14 @@ void videobuf_queue_core_init(struct videobuf_queue *q,
+ BUG_ON(!q->ops->buf_queue);
+ BUG_ON(!q->ops->buf_release);
+
++ /* Lock is mandatory for queue_cancel to work */
++ BUG_ON(!irqlock);
++
+ /* Having implementations for abstract methods are mandatory */
+ BUG_ON(!q->int_ops);
+
+ mutex_init(&q->vb_lock);
++ init_waitqueue_head(&q->wait);
+ INIT_LIST_HEAD(&q->stream);
+ }
+
+@@ -195,19 +185,22 @@ void videobuf_queue_cancel(struct videobuf_queue *q)
+ unsigned long flags = 0;
+ int i;
+
++ q->streaming = 0;
++ q->reading = 0;
++ wake_up_interruptible_sync(&q->wait);
++
+ /* remove queued buffers from list */
+- if (q->irqlock)
+- spin_lock_irqsave(q->irqlock, flags);
++ spin_lock_irqsave(q->irqlock, flags);
+ for (i = 0; i < VIDEO_MAX_FRAME; i++) {
+ if (NULL == q->bufs[i])
+ continue;
+ if (q->bufs[i]->state == VIDEOBUF_QUEUED) {
+ list_del(&q->bufs[i]->queue);
+ q->bufs[i]->state = VIDEOBUF_ERROR;
++ wake_up_all(&q->bufs[i]->done);
+ }
+ }
+- if (q->irqlock)
+- spin_unlock_irqrestore(q->irqlock, flags);
++ spin_unlock_irqrestore(q->irqlock, flags);
+
+ /* free all buffers + clear queue */
+ for (i = 0; i < VIDEO_MAX_FRAME; i++) {
+@@ -563,14 +556,13 @@ int videobuf_qbuf(struct videobuf_queue *q,
+
+ list_add_tail(&buf->stream, &q->stream);
+ if (q->streaming) {
+- if (q->irqlock)
+- spin_lock_irqsave(q->irqlock, flags);
++ spin_lock_irqsave(q->irqlock, flags);
+ q->ops->buf_queue(q, buf);
+- if (q->irqlock)
+- spin_unlock_irqrestore(q->irqlock, flags);
++ spin_unlock_irqrestore(q->irqlock, flags);
+ }
+ dprintk(1, "qbuf: succeded\n");
+ retval = 0;
++ wake_up_interruptible_sync(&q->wait);
+
+ done:
+ mutex_unlock(&q->vb_lock);
+@@ -581,35 +573,88 @@ int videobuf_qbuf(struct videobuf_queue *q,
+ return retval;
+ }
+
+-int videobuf_dqbuf(struct videobuf_queue *q,
+- struct v4l2_buffer *b, int nonblocking)
++
++/* Locking: Caller holds q->vb_lock */
++static int stream_next_buffer_check_queue(struct videobuf_queue *q, int noblock)
+ {
+- struct videobuf_buffer *buf;
+ int retval;
+
+- MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
+-
+- mutex_lock(&q->vb_lock);
+- retval = -EBUSY;
+- if (q->reading) {
+- dprintk(1, "dqbuf: Reading running...\n");
+- goto done;
+- }
+- retval = -EINVAL;
+- if (b->type != q->type) {
+- dprintk(1, "dqbuf: Wrong type.\n");
++checks:
++ if (!q->streaming) {
++ dprintk(1, "next_buffer: Not streaming\n");
++ retval = -EINVAL;
+ goto done;
+ }
++
+ if (list_empty(&q->stream)) {
+- dprintk(1, "dqbuf: stream running\n");
+- goto done;
++ if (noblock) {
++ retval = -EAGAIN;
++ dprintk(2, "next_buffer: no buffers to dequeue\n");
++ goto done;
++ } else {
++ dprintk(2, "next_buffer: waiting on buffer\n");
++
++ /* Drop lock to avoid deadlock with qbuf */
++ mutex_unlock(&q->vb_lock);
++
++ /* Checking list_empty and streaming is safe without
++ * locks because we goto checks to validate while
++ * holding locks before proceeding */
++ retval = wait_event_interruptible(q->wait,
++ !list_empty(&q->stream) || !q->streaming);
++ mutex_lock(&q->vb_lock);
++
++ if (retval)
++ goto done;
++
++ goto checks;
++ }
+ }
++
++ retval = 0;
++
++done:
++ return retval;
++}
++
++
++/* Locking: Caller holds q->vb_lock */
++static int stream_next_buffer(struct videobuf_queue *q,
++ struct videobuf_buffer **vb, int nonblocking)
++{
++ int retval;
++ struct videobuf_buffer *buf = NULL;
++
++ retval = stream_next_buffer_check_queue(q, nonblocking);
++ if (retval)
++ goto done;
++
+ buf = list_entry(q->stream.next, struct videobuf_buffer, stream);
+ retval = videobuf_waiton(buf, nonblocking, 1);
++ if (retval < 0)
++ goto done;
++
++ *vb = buf;
++done:
++ return retval;
++}
++
++int videobuf_dqbuf(struct videobuf_queue *q,
++ struct v4l2_buffer *b, int nonblocking)
++{
++ struct videobuf_buffer *buf = NULL;
++ int retval;
++
++ MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
++
++ mutex_lock(&q->vb_lock);
++
++ retval = stream_next_buffer(q, &buf, nonblocking);
+ if (retval < 0) {
+- dprintk(1, "dqbuf: waiton returned %d\n", retval);
++ dprintk(1, "dqbuf: next_buffer error: %i\n", retval);
+ goto done;
+ }
++
+ switch (buf->state) {
+ case VIDEOBUF_ERROR:
+ dprintk(1, "dqbuf: state is error\n");
+@@ -650,14 +695,13 @@ int videobuf_streamon(struct videobuf_queue *q)
+ if (q->streaming)
+ goto done;
+ q->streaming = 1;
+- if (q->irqlock)
+- spin_lock_irqsave(q->irqlock, flags);
++ spin_lock_irqsave(q->irqlock, flags);
+ list_for_each_entry(buf, &q->stream, stream)
+ if (buf->state == VIDEOBUF_PREPARED)
+ q->ops->buf_queue(q, buf);
+- if (q->irqlock)
+- spin_unlock_irqrestore(q->irqlock, flags);
++ spin_unlock_irqrestore(q->irqlock, flags);
+
++ wake_up_interruptible_sync(&q->wait);
+ done:
+ mutex_unlock(&q->vb_lock);
+ return retval;
+@@ -670,7 +714,6 @@ static int __videobuf_streamoff(struct videobuf_queue *q)
+ return -EINVAL;
+
+ videobuf_queue_cancel(q);
+- q->streaming = 0;
+
+ return 0;
+ }
+@@ -712,11 +755,9 @@ static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q,
+ goto done;
+
+ /* start capture & wait */
+- if (q->irqlock)
+- spin_lock_irqsave(q->irqlock, flags);
++ spin_lock_irqsave(q->irqlock, flags);
+ q->ops->buf_queue(q, q->read_buf);
+- if (q->irqlock)
+- spin_unlock_irqrestore(q->irqlock, flags);
++ spin_unlock_irqrestore(q->irqlock, flags);
+ retval = videobuf_waiton(q->read_buf, 0, 0);
+ if (0 == retval) {
+ CALL(q, sync, q, q->read_buf);
+@@ -740,14 +781,13 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
+ {
+ enum v4l2_field field;
+ unsigned long flags = 0;
+- unsigned size, nbufs;
++ unsigned size = 0, nbufs = 1;
+ int retval;
+
+ MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
+
+ mutex_lock(&q->vb_lock);
+
+- nbufs = 1; size = 0;
+ q->ops->buf_setup(q, &nbufs, &size);
+
+ if (NULL == q->read_buf &&
+@@ -778,12 +818,11 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
+ q->read_buf = NULL;
+ goto done;
+ }
+- if (q->irqlock)
+- spin_lock_irqsave(q->irqlock, flags);
+
++ spin_lock_irqsave(q->irqlock, flags);
+ q->ops->buf_queue(q, q->read_buf);
+- if (q->irqlock)
+- spin_unlock_irqrestore(q->irqlock, flags);
++ spin_unlock_irqrestore(q->irqlock, flags);
++
+ q->read_off = 0;
+ }
+
+@@ -849,12 +888,10 @@ static int __videobuf_read_start(struct videobuf_queue *q)
+ return err;
+ list_add_tail(&q->bufs[i]->stream, &q->stream);
+ }
+- if (q->irqlock)
+- spin_lock_irqsave(q->irqlock, flags);
++ spin_lock_irqsave(q->irqlock, flags);
+ for (i = 0; i < count; i++)
+ q->ops->buf_queue(q, q->bufs[i]);
+- if (q->irqlock)
+- spin_unlock_irqrestore(q->irqlock, flags);
++ spin_unlock_irqrestore(q->irqlock, flags);
+ q->reading = 1;
+ return 0;
+ }
+@@ -863,7 +900,6 @@ static void __videobuf_read_stop(struct videobuf_queue *q)
+ {
+ int i;
+
+-
+ videobuf_queue_cancel(q);
+ __videobuf_mmap_free(q);
+ INIT_LIST_HEAD(&q->stream);
+@@ -874,7 +910,6 @@ static void __videobuf_read_stop(struct videobuf_queue *q)
+ q->bufs[i] = NULL;
+ }
+ q->read_buf = NULL;
+- q->reading = 0;
+
+ }
+
+@@ -919,7 +954,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
+
+ MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
+
+- dprintk(2, "%s\n", __FUNCTION__);
++ dprintk(2, "%s\n", __func__);
+ mutex_lock(&q->vb_lock);
+ retval = -EBUSY;
+ if (q->streaming)
+@@ -968,11 +1003,9 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
+ if (q->read_off == q->read_buf->size) {
+ list_add_tail(&q->read_buf->stream,
+ &q->stream);
+- if (q->irqlock)
+- spin_lock_irqsave(q->irqlock, flags);
++ spin_lock_irqsave(q->irqlock, flags);
+ q->ops->buf_queue(q, q->read_buf);
+- if (q->irqlock)
+- spin_unlock_irqrestore(q->irqlock, flags);
++ spin_unlock_irqrestore(q->irqlock, flags);
+ q->read_buf = NULL;
+ }
+ if (retval < 0)
+diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c
+index 53fed4b..03a7b94 100644
+--- a/drivers/media/video/videobuf-dma-sg.c
++++ b/drivers/media/video/videobuf-dma-sg.c
+@@ -1,5 +1,5 @@
+ /*
+- * helper functions for PCI DMA video4linux capture buffers
++ * helper functions for SG DMA video4linux capture buffers
+ *
+ * The functions expect the hardware being able to scatter gatter
+ * (i.e. the buffers are not linear in physical memory, but fragmented
+@@ -24,7 +24,7 @@
+ #include <linux/slab.h>
+ #include <linux/interrupt.h>
+
+-#include <linux/pci.h>
++#include <linux/dma-mapping.h>
+ #include <linux/vmalloc.h>
+ #include <linux/pagemap.h>
+ #include <linux/scatterlist.h>
+@@ -39,10 +39,10 @@
+ #define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \
+ { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); }
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+
+-MODULE_DESCRIPTION("helper module to manage video4linux pci dma sg buffers");
++MODULE_DESCRIPTION("helper module to manage video4linux dma sg buffers");
+ MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab at infradead.org>");
+ MODULE_LICENSE("GPL");
+
+@@ -119,10 +119,10 @@ videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset)
+
+ struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf)
+ {
+- struct videbuf_pci_sg_memory *mem=buf->priv;
+- BUG_ON (!mem);
++ struct videobuf_dma_sg_memory *mem = buf->priv;
++ BUG_ON(!mem);
+
+- MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
++ MAGIC_CHECK(mem->magic, MAGIC_SG_MEM);
+
+ return &mem->dma;
+ }
+@@ -141,9 +141,14 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
+
+ dma->direction = direction;
+ switch (dma->direction) {
+- case PCI_DMA_FROMDEVICE: rw = READ; break;
+- case PCI_DMA_TODEVICE: rw = WRITE; break;
+- default: BUG();
++ case DMA_FROM_DEVICE:
++ rw = READ;
++ break;
++ case DMA_TO_DEVICE:
++ rw = WRITE;
++ break;
++ default:
++ BUG();
+ }
+
+ first = (data & PAGE_MASK) >> PAGE_SHIFT;
+@@ -157,9 +162,6 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
+ dprintk(1,"init user [0x%lx+0x%lx => %d pages]\n",
+ data,size,dma->nr_pages);
+
+- dma->varea = (void *) data;
+-
+-
+ err = get_user_pages(current,current->mm,
+ data & PAGE_MASK, dma->nr_pages,
+ rw == READ, 1, /* force */
+@@ -216,10 +218,8 @@ int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction,
+ return 0;
+ }
+
+-int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
++int videobuf_dma_map(struct videobuf_queue* q, struct videobuf_dmabuf *dma)
+ {
+- void *dev=q->dev;
+-
+ MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
+ BUG_ON(0 == dma->nr_pages);
+
+@@ -245,11 +245,11 @@ int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
+ return -ENOMEM;
+ }
+ if (!dma->bus_addr) {
+- dma->sglen = pci_map_sg(dev,dma->sglist,
++ dma->sglen = dma_map_sg(q->dev, dma->sglist,
+ dma->nr_pages, dma->direction);
+ if (0 == dma->sglen) {
+ printk(KERN_WARNING
+- "%s: videobuf_map_sg failed\n",__FUNCTION__);
++ "%s: videobuf_map_sg failed\n",__func__);
+ kfree(dma->sglist);
+ dma->sglist = NULL;
+ dma->sglen = 0;
+@@ -259,26 +259,22 @@ int videobuf_dma_map(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
+ return 0;
+ }
+
+-int videobuf_dma_sync(struct videobuf_queue *q,struct videobuf_dmabuf *dma)
++int videobuf_dma_sync(struct videobuf_queue *q, struct videobuf_dmabuf *dma)
+ {
+- void *dev=q->dev;
+-
+- MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
++ MAGIC_CHECK(dma->magic, MAGIC_DMABUF);
+ BUG_ON(!dma->sglen);
+
+- pci_dma_sync_sg_for_cpu (dev,dma->sglist,dma->nr_pages,dma->direction);
++ dma_sync_sg_for_cpu(q->dev, dma->sglist, dma->nr_pages, dma->direction);
+ return 0;
+ }
+
+ int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma)
+ {
+- void *dev=q->dev;
+-
+- MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
++ MAGIC_CHECK(dma->magic, MAGIC_DMABUF);
+ if (!dma->sglen)
+ return 0;
+
+- pci_unmap_sg (dev,dma->sglist,dma->nr_pages,dma->direction);
++ dma_unmap_sg(q->dev, dma->sglist, dma->nr_pages, dma->direction);
+
+ kfree(dma->sglist);
+ dma->sglist = NULL;
+@@ -301,33 +297,32 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma)
+
+ vfree(dma->vmalloc);
+ dma->vmalloc = NULL;
+- dma->varea = NULL;
+
+ if (dma->bus_addr) {
+ dma->bus_addr = 0;
+ }
+- dma->direction = PCI_DMA_NONE;
++ dma->direction = DMA_NONE;
+ return 0;
+ }
+
+ /* --------------------------------------------------------------------- */
+
+-int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma)
++int videobuf_sg_dma_map(struct device *dev, struct videobuf_dmabuf *dma)
+ {
+ struct videobuf_queue q;
+
+- q.dev=pci;
++ q.dev = dev;
+
+- return (videobuf_dma_map(&q,dma));
++ return videobuf_dma_map(&q, dma);
+ }
+
+-int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma)
++int videobuf_sg_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma)
+ {
+ struct videobuf_queue q;
+
+- q.dev=pci;
++ q.dev = dev;
+
+- return (videobuf_dma_unmap(&q,dma));
++ return videobuf_dma_unmap(&q, dma);
+ }
+
+ /* --------------------------------------------------------------------- */
+@@ -347,7 +342,7 @@ videobuf_vm_close(struct vm_area_struct *vma)
+ {
+ struct videobuf_mapping *map = vma->vm_private_data;
+ struct videobuf_queue *q = map->q;
+- struct videbuf_pci_sg_memory *mem;
++ struct videobuf_dma_sg_memory *mem;
+ int i;
+
+ dprintk(2,"vm_close %p [count=%d,vma=%08lx-%08lx]\n",map,
+@@ -409,18 +404,18 @@ static struct vm_operations_struct videobuf_vm_ops =
+ };
+
+ /* ---------------------------------------------------------------------
+- * PCI handlers for the generic methods
++ * SG handlers for the generic methods
+ */
+
+ /* Allocated area consists on 3 parts:
+ struct video_buffer
+ struct <driver>_buffer (cx88_buffer, saa7134_buf, ...)
+- struct videobuf_pci_sg_memory
++ struct videobuf_dma_sg_memory
+ */
+
+ static void *__videobuf_alloc(size_t size)
+ {
+- struct videbuf_pci_sg_memory *mem;
++ struct videobuf_dma_sg_memory *mem;
+ struct videobuf_buffer *vb;
+
+ vb = kzalloc(size+sizeof(*mem),GFP_KERNEL);
+@@ -431,22 +426,32 @@ static void *__videobuf_alloc(size_t size)
+ videobuf_dma_init(&mem->dma);
+
+ dprintk(1,"%s: allocated at %p(%ld+%ld) & %p(%ld)\n",
+- __FUNCTION__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
++ __func__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
+ mem,(long)sizeof(*mem));
+
+ return vb;
+ }
+
++static void *__videobuf_to_vmalloc (struct videobuf_buffer *buf)
++{
++ struct videobuf_dma_sg_memory *mem = buf->priv;
++ BUG_ON(!mem);
++
++ MAGIC_CHECK(mem->magic, MAGIC_SG_MEM);
++
++ return mem->dma.vmalloc;
++}
++
+ static int __videobuf_iolock (struct videobuf_queue* q,
+ struct videobuf_buffer *vb,
+ struct v4l2_framebuffer *fbuf)
+ {
+ int err,pages;
+ dma_addr_t bus;
+- struct videbuf_pci_sg_memory *mem=vb->priv;
++ struct videobuf_dma_sg_memory *mem = vb->priv;
+ BUG_ON(!mem);
+
+- MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
++ MAGIC_CHECK(mem->magic, MAGIC_SG_MEM);
+
+ switch (vb->memory) {
+ case V4L2_MEMORY_MMAP:
+@@ -455,14 +460,14 @@ static int __videobuf_iolock (struct videobuf_queue* q,
+ /* no userspace addr -- kernel bounce buffer */
+ pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT;
+ err = videobuf_dma_init_kernel( &mem->dma,
+- PCI_DMA_FROMDEVICE,
++ DMA_FROM_DEVICE,
+ pages );
+ if (0 != err)
+ return err;
+ } else if (vb->memory == V4L2_MEMORY_USERPTR) {
+ /* dma directly to userspace */
+ err = videobuf_dma_init_user( &mem->dma,
+- PCI_DMA_FROMDEVICE,
++ DMA_FROM_DEVICE,
+ vb->baddr,vb->bsize );
+ if (0 != err)
+ return err;
+@@ -473,7 +478,7 @@ static int __videobuf_iolock (struct videobuf_queue* q,
+ locking inversion, so don't take it here */
+
+ err = videobuf_dma_init_user_locked(&mem->dma,
+- PCI_DMA_FROMDEVICE,
++ DMA_FROM_DEVICE,
+ vb->baddr, vb->bsize);
+ if (0 != err)
+ return err;
+@@ -490,7 +495,7 @@ static int __videobuf_iolock (struct videobuf_queue* q,
+ */
+ bus = (dma_addr_t)(unsigned long)fbuf->base + vb->boff;
+ pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT;
+- err = videobuf_dma_init_overlay(&mem->dma,PCI_DMA_FROMDEVICE,
++ err = videobuf_dma_init_overlay(&mem->dma, DMA_FROM_DEVICE,
+ bus, pages);
+ if (0 != err)
+ return err;
+@@ -498,7 +503,7 @@ static int __videobuf_iolock (struct videobuf_queue* q,
+ default:
+ BUG();
+ }
+- err = videobuf_dma_map(q,&mem->dma);
++ err = videobuf_dma_map(q, &mem->dma);
+ if (0 != err)
+ return err;
+
+@@ -508,8 +513,8 @@ static int __videobuf_iolock (struct videobuf_queue* q,
+ static int __videobuf_sync(struct videobuf_queue *q,
+ struct videobuf_buffer *buf)
+ {
+- struct videbuf_pci_sg_memory *mem=buf->priv;
+- BUG_ON (!mem);
++ struct videobuf_dma_sg_memory *mem = buf->priv;
++ BUG_ON(!mem);
+ MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
+
+ return videobuf_dma_sync(q,&mem->dma);
+@@ -532,7 +537,7 @@ static int __videobuf_mmap_free(struct videobuf_queue *q)
+ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
+ struct vm_area_struct *vma)
+ {
+- struct videbuf_pci_sg_memory *mem;
++ struct videobuf_dma_sg_memory *mem;
+ struct videobuf_mapping *map;
+ unsigned int first,last,size,i;
+ int retval;
+@@ -547,12 +552,20 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
+ goto done;
+ }
+
++ /* This function maintains backwards compatibility with V4L1 and will
++ * map more than one buffer if the vma length is equal to the combined
++ * size of multiple buffers than it will map them together. See
++ * VIDIOCGMBUF in the v4l spec
++ *
++ * TODO: Allow drivers to specify if they support this mode
++ */
++
+ /* look for first buffer to map */
+ for (first = 0; first < VIDEO_MAX_FRAME; first++) {
+ if (NULL == q->bufs[first])
+ continue;
+ mem=q->bufs[first]->priv;
+- BUG_ON (!mem);
++ BUG_ON(!mem);
+ MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
+
+ if (V4L2_MEMORY_MMAP != q->bufs[first]->memory)
+@@ -591,10 +604,16 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
+ map = kmalloc(sizeof(struct videobuf_mapping),GFP_KERNEL);
+ if (NULL == map)
+ goto done;
+- for (size = 0, i = first; i <= last; size += q->bufs[i++]->bsize) {
++
++ size = 0;
++ for (i = first; i <= last; i++) {
++ if (NULL == q->bufs[i])
++ continue;
+ q->bufs[i]->map = map;
+ q->bufs[i]->baddr = vma->vm_start + size;
++ size += q->bufs[i]->bsize;
+ }
++
+ map->count = 1;
+ map->start = vma->vm_start;
+ map->end = vma->vm_end;
+@@ -615,8 +634,8 @@ static int __videobuf_copy_to_user ( struct videobuf_queue *q,
+ char __user *data, size_t count,
+ int nonblocking )
+ {
+- struct videbuf_pci_sg_memory *mem=q->read_buf->priv;
+- BUG_ON (!mem);
++ struct videobuf_dma_sg_memory *mem = q->read_buf->priv;
++ BUG_ON(!mem);
+ MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
+
+ /* copy to userspace */
+@@ -634,8 +653,8 @@ static int __videobuf_copy_stream ( struct videobuf_queue *q,
+ int vbihack, int nonblocking )
+ {
+ unsigned int *fc;
+- struct videbuf_pci_sg_memory *mem=q->read_buf->priv;
+- BUG_ON (!mem);
++ struct videobuf_dma_sg_memory *mem = q->read_buf->priv;
++ BUG_ON(!mem);
+ MAGIC_CHECK(mem->magic,MAGIC_SG_MEM);
+
+ if (vbihack) {
+@@ -658,7 +677,7 @@ static int __videobuf_copy_stream ( struct videobuf_queue *q,
+ return count;
+ }
+
+-static struct videobuf_qtype_ops pci_ops = {
++static struct videobuf_qtype_ops sg_ops = {
+ .magic = MAGIC_QTYPE_OPS,
+
+ .alloc = __videobuf_alloc,
+@@ -668,23 +687,24 @@ static struct videobuf_qtype_ops pci_ops = {
+ .mmap_mapper = __videobuf_mmap_mapper,
+ .video_copy_to_user = __videobuf_copy_to_user,
+ .copy_stream = __videobuf_copy_stream,
++ .vmalloc = __videobuf_to_vmalloc,
+ };
+
+-void *videobuf_pci_alloc (size_t size)
++void *videobuf_sg_alloc(size_t size)
+ {
+ struct videobuf_queue q;
+
+ /* Required to make generic handler to call __videobuf_alloc */
+- q.int_ops=&pci_ops;
++ q.int_ops = &sg_ops;
+
+- q.msize=size;
++ q.msize = size;
+
+- return videobuf_alloc (&q);
++ return videobuf_alloc(&q);
+ }
+
+-void videobuf_queue_pci_init(struct videobuf_queue* q,
++void videobuf_queue_sg_init(struct videobuf_queue* q,
+ struct videobuf_queue_ops *ops,
+- void *dev,
++ struct device *dev,
+ spinlock_t *irqlock,
+ enum v4l2_buf_type type,
+ enum v4l2_field field,
+@@ -692,7 +712,7 @@ void videobuf_queue_pci_init(struct videobuf_queue* q,
+ void *priv)
+ {
+ videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize,
+- priv, &pci_ops);
++ priv, &sg_ops);
+ }
+
+ /* --------------------------------------------------------------------- */
+@@ -709,11 +729,11 @@ EXPORT_SYMBOL_GPL(videobuf_dma_sync);
+ EXPORT_SYMBOL_GPL(videobuf_dma_unmap);
+ EXPORT_SYMBOL_GPL(videobuf_dma_free);
+
+-EXPORT_SYMBOL_GPL(videobuf_pci_dma_map);
+-EXPORT_SYMBOL_GPL(videobuf_pci_dma_unmap);
+-EXPORT_SYMBOL_GPL(videobuf_pci_alloc);
++EXPORT_SYMBOL_GPL(videobuf_sg_dma_map);
++EXPORT_SYMBOL_GPL(videobuf_sg_dma_unmap);
++EXPORT_SYMBOL_GPL(videobuf_sg_alloc);
+
+-EXPORT_SYMBOL_GPL(videobuf_queue_pci_init);
++EXPORT_SYMBOL_GPL(videobuf_queue_sg_init);
+
+ /*
+ * Local variables:
+diff --git a/drivers/media/video/videobuf-dvb.c b/drivers/media/video/videobuf-dvb.c
+index b73aba6..6e4d73e 100644
+--- a/drivers/media/video/videobuf-dvb.c
++++ b/drivers/media/video/videobuf-dvb.c
+@@ -20,9 +20,10 @@
+ #include <linux/fs.h>
+ #include <linux/kthread.h>
+ #include <linux/file.h>
++
+ #include <linux/freezer.h>
+
+-#include <media/videobuf-dma-sg.h>
++#include <media/videobuf-core.h>
+ #include <media/videobuf-dvb.h>
+
+ /* ------------------------------------------------------------------ */
+@@ -30,7 +31,7 @@
+ MODULE_AUTHOR("Gerd Knorr <kraxel at bytesex.org> [SuSE Labs]");
+ MODULE_LICENSE("GPL");
+
+-static unsigned int debug = 0;
++static unsigned int debug;
+ module_param(debug, int, 0644);
+ MODULE_PARM_DESC(debug,"enable debug messages");
+
+@@ -45,7 +46,7 @@ static int videobuf_dvb_thread(void *data)
+ struct videobuf_buffer *buf;
+ unsigned long flags;
+ int err;
+- struct videobuf_dmabuf *dma;
++ void *outp;
+
+ dprintk("dvb thread started\n");
+ set_freezable();
+@@ -66,9 +67,10 @@ static int videobuf_dvb_thread(void *data)
+ try_to_freeze();
+
+ /* feed buffer data to demux */
+- dma=videobuf_to_dma(buf);
++ outp = videobuf_queue_to_vmalloc (&dvb->dvbq, buf);
++
+ if (buf->state == VIDEOBUF_DONE)
+- dvb_dmx_swfilter(&dvb->demux, dma->vmalloc,
++ dvb_dmx_swfilter(&dvb->demux, outp,
+ buf->size);
+
+ /* requeue buffer */
+@@ -138,14 +140,16 @@ static int videobuf_dvb_stop_feed(struct dvb_demux_feed *feed)
+ int videobuf_dvb_register(struct videobuf_dvb *dvb,
+ struct module *module,
+ void *adapter_priv,
+- struct device *device)
++ struct device *device,
++ short *adapter_nr)
+ {
+ int result;
+
+ mutex_init(&dvb->lock);
+
+ /* register adapter */
+- result = dvb_register_adapter(&dvb->adapter, dvb->name, module, device);
++ result = dvb_register_adapter(&dvb->adapter, dvb->name, module, device,
++ adapter_nr);
+ if (result < 0) {
+ printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n",
+ dvb->name, result);
+diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c
+index 5266ecc..c91e1d8 100644
+--- a/drivers/media/video/videobuf-vmalloc.c
++++ b/drivers/media/video/videobuf-vmalloc.c
+@@ -33,7 +33,7 @@
+ #define MAGIC_CHECK(is,should) if (unlikely((is) != (should))) \
+ { printk(KERN_ERR "magic mismatch: %x (expected %x)\n",is,should); BUG(); }
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0644);
+
+ MODULE_DESCRIPTION("helper module to manage video4linux vmalloc buffers");
+@@ -57,20 +57,26 @@ videobuf_vm_open(struct vm_area_struct *vma)
+ map->count++;
+ }
+
+-static void
+-videobuf_vm_close(struct vm_area_struct *vma)
++static void videobuf_vm_close(struct vm_area_struct *vma)
+ {
+ struct videobuf_mapping *map = vma->vm_private_data;
+ struct videobuf_queue *q = map->q;
+ int i;
+
+- dprintk(2,"vm_close %p [count=%u,vma=%08lx-%08lx]\n",map,
+- map->count,vma->vm_start,vma->vm_end);
++ dprintk(2,"vm_close %p [count=%u,vma=%08lx-%08lx]\n", map,
++ map->count, vma->vm_start, vma->vm_end);
+
+ map->count--;
+ if (0 == map->count) {
+- dprintk(1,"munmap %p q=%p\n",map,q);
++ struct videobuf_vmalloc_memory *mem;
++
++ dprintk(1, "munmap %p q=%p\n", map, q);
+ mutex_lock(&q->vb_lock);
++
++ /* We need first to cancel streams, before unmapping */
++ if (q->streaming)
++ videobuf_queue_cancel(q);
++
+ for (i = 0; i < VIDEO_MAX_FRAME; i++) {
+ if (NULL == q->bufs[i])
+ continue;
+@@ -78,14 +84,35 @@ videobuf_vm_close(struct vm_area_struct *vma)
+ if (q->bufs[i]->map != map)
+ continue;
+
+- q->ops->buf_release(q,q->bufs[i]);
++ mem = q->bufs[i]->priv;
++ if (mem) {
++ /* This callback is called only if kernel has
++ allocated memory and this memory is mmapped.
++ In this case, memory should be freed,
++ in order to do memory unmap.
++ */
++
++ MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
++
++ /* vfree is not atomic - can't be
++ called with IRQ's disabled
++ */
++ dprintk(1, "%s: buf[%d] freeing (%p)\n",
++ __func__, i, mem->vmalloc);
++
++ vfree(mem->vmalloc);
++ mem->vmalloc = NULL;
++ }
+
+ q->bufs[i]->map = NULL;
+ q->bufs[i]->baddr = 0;
+ }
+- mutex_unlock(&q->vb_lock);
++
+ kfree(map);
++
++ mutex_unlock(&q->vb_lock);
+ }
++
+ return;
+ }
+
+@@ -102,7 +129,7 @@ static struct vm_operations_struct videobuf_vm_ops =
+ /* Allocated area consists on 3 parts:
+ struct video_buffer
+ struct <driver>_buffer (cx88_buffer, saa7134_buf, ...)
+- struct videobuf_pci_sg_memory
++ struct videobuf_dma_sg_memory
+ */
+
+ static void *__videobuf_alloc(size_t size)
+@@ -116,7 +143,7 @@ static void *__videobuf_alloc(size_t size)
+ mem->magic=MAGIC_VMAL_MEM;
+
+ dprintk(1,"%s: allocated at %p(%ld+%ld) & %p(%ld)\n",
+- __FUNCTION__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
++ __func__,vb,(long)sizeof(*vb),(long)size-sizeof(*vb),
+ mem,(long)sizeof(*mem));
+
+ return vb;
+@@ -126,45 +153,74 @@ static int __videobuf_iolock (struct videobuf_queue* q,
+ struct videobuf_buffer *vb,
+ struct v4l2_framebuffer *fbuf)
+ {
++ struct videobuf_vmalloc_memory *mem = vb->priv;
+ int pages;
+- struct videobuf_vmalloc_memory *mem=vb->priv;
+
+ BUG_ON(!mem);
+
+- MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
++ MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
+
+- pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT;
++ switch (vb->memory) {
++ case V4L2_MEMORY_MMAP:
++ dprintk(1, "%s memory method MMAP\n", __func__);
+
+- /* Currently, doesn't support V4L2_MEMORY_OVERLAY */
+- if ((vb->memory != V4L2_MEMORY_MMAP) &&
+- (vb->memory != V4L2_MEMORY_USERPTR) ) {
+- printk(KERN_ERR "Method currently unsupported.\n");
+- return -EINVAL;
+- }
++ /* All handling should be done by __videobuf_mmap_mapper() */
++ if (!mem->vmalloc) {
++ printk(KERN_ERR "memory is not alloced/mmapped.\n");
++ return -EINVAL;
++ }
++ break;
++ case V4L2_MEMORY_USERPTR:
++ pages = PAGE_ALIGN(vb->size);
+
+- /* FIXME: should be tested with kernel mmap mem */
+- mem->vmalloc=vmalloc_user (PAGE_ALIGN(vb->size));
+- if (NULL == mem->vmalloc) {
+- printk(KERN_ERR "vmalloc (%d pages) failed\n",pages);
+- return -ENOMEM;
+- }
++ dprintk(1, "%s memory method USERPTR\n", __func__);
+
+- dprintk(1,"vmalloc is at addr 0x%08lx, size=%d\n",
+- (unsigned long)mem->vmalloc,
+- pages << PAGE_SHIFT);
++#if 1
++ if (vb->baddr) {
++ printk(KERN_ERR "USERPTR is currently not supported\n");
++ return -EINVAL;
++ }
++#endif
+
+- /* It seems that some kernel versions need to do remap *after*
+- the mmap() call
+- */
+- if (mem->vma) {
+- int retval=remap_vmalloc_range(mem->vma, mem->vmalloc,0);
+- kfree(mem->vma);
+- mem->vma=NULL;
+- if (retval<0) {
+- dprintk(1,"mmap app bug: remap_vmalloc_range area %p error %d\n",
+- mem->vmalloc,retval);
+- return retval;
++ /* The only USERPTR currently supported is the one needed for
++ read() method.
++ */
++
++ mem->vmalloc = vmalloc_user(pages);
++ if (!mem->vmalloc) {
++ printk(KERN_ERR "vmalloc (%d pages) failed\n", pages);
++ return -ENOMEM;
++ }
++ dprintk(1, "vmalloc is at addr %p (%d pages)\n",
++ mem->vmalloc, pages);
++
++#if 0
++ int rc;
++ /* Kernel userptr is used also by read() method. In this case,
++ there's no need to remap, since data will be copied to user
++ */
++ if (!vb->baddr)
++ return 0;
++
++ /* FIXME: to properly support USERPTR, remap should occur.
++ The code bellow won't work, since mem->vma = NULL
++ */
++ /* Try to remap memory */
++ rc = remap_vmalloc_range(mem->vma, (void *)vb->baddr, 0);
++ if (rc < 0) {
++ printk(KERN_ERR "mmap: remap failed with error %d. ", rc);
++ return -ENOMEM;
+ }
++#endif
++
++ break;
++ case V4L2_MEMORY_OVERLAY:
++ default:
++ dprintk(1, "%s memory method OVERLAY/unknown\n", __func__);
++
++ /* Currently, doesn't support V4L2_MEMORY_OVERLAY */
++ printk(KERN_ERR "Memory method currently unsupported.\n");
++ return -EINVAL;
+ }
+
+ return 0;
+@@ -180,6 +236,7 @@ static int __videobuf_mmap_free(struct videobuf_queue *q)
+ {
+ unsigned int i;
+
++ dprintk(1, "%s\n", __func__);
+ for (i = 0; i < VIDEO_MAX_FRAME; i++) {
+ if (q->bufs[i]) {
+ if (q->bufs[i]->map)
+@@ -196,10 +253,11 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
+ struct videobuf_vmalloc_memory *mem;
+ struct videobuf_mapping *map;
+ unsigned int first;
+- int retval;
++ int retval, pages;
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+
+- if (! (vma->vm_flags & VM_WRITE) || ! (vma->vm_flags & VM_SHARED))
++ dprintk(1, "%s\n", __func__);
++ if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED))
+ return -EINVAL;
+
+ /* look for first buffer to map */
+@@ -219,46 +277,55 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
+ }
+
+ /* create mapping + update buffer list */
+- map = q->bufs[first]->map = kzalloc(sizeof(struct videobuf_mapping),GFP_KERNEL);
++ map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
+ if (NULL == map)
+ return -ENOMEM;
+
++ q->bufs[first]->map = map;
+ map->start = vma->vm_start;
+ map->end = vma->vm_end;
+ map->q = q;
+
+ q->bufs[first]->baddr = vma->vm_start;
+
+- vma->vm_ops = &videobuf_vm_ops;
+- vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
+- vma->vm_private_data = map;
++ mem = q->bufs[first]->priv;
++ BUG_ON(!mem);
++ MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
+
+- mem=q->bufs[first]->priv;
+- BUG_ON (!mem);
+- MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
++ pages = PAGE_ALIGN(vma->vm_end - vma->vm_start);
++ mem->vmalloc = vmalloc_user(pages);
++ if (!mem->vmalloc) {
++ printk(KERN_ERR "vmalloc (%d pages) failed\n", pages);
++ goto error;
++ }
++ dprintk(1, "vmalloc is at addr %p (%d pages)\n",
++ mem->vmalloc, pages);
+
+ /* Try to remap memory */
+- retval=remap_vmalloc_range(vma, mem->vmalloc,0);
+- if (retval<0) {
+- dprintk(1,"mmap: postponing remap_vmalloc_range\n");
+-
+- mem->vma=kmalloc(sizeof(*vma),GFP_KERNEL);
+- if (!mem->vma) {
+- kfree(map);
+- q->bufs[first]->map=NULL;
+- return -ENOMEM;
+- }
+- memcpy(mem->vma,vma,sizeof(*vma));
++ retval = remap_vmalloc_range(vma, mem->vmalloc, 0);
++ if (retval < 0) {
++ printk(KERN_ERR "mmap: remap failed with error %d. ", retval);
++ vfree(mem->vmalloc);
++ goto error;
+ }
+
++ vma->vm_ops = &videobuf_vm_ops;
++ vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
++ vma->vm_private_data = map;
++
+ dprintk(1,"mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
+- map,q,vma->vm_start,vma->vm_end,
++ map, q, vma->vm_start, vma->vm_end,
+ (long int) q->bufs[first]->bsize,
+- vma->vm_pgoff,first);
++ vma->vm_pgoff, first);
+
+ videobuf_vm_open(vma);
+
+- return (0);
++ return 0;
++
++error:
++ mem = NULL;
++ kfree(map);
++ return -ENOMEM;
+ }
+
+ static int __videobuf_copy_to_user ( struct videobuf_queue *q,
+@@ -320,6 +387,7 @@ static struct videobuf_qtype_ops qops = {
+ .mmap_mapper = __videobuf_mmap_mapper,
+ .video_copy_to_user = __videobuf_copy_to_user,
+ .copy_stream = __videobuf_copy_stream,
++ .vmalloc = videobuf_to_vmalloc,
+ };
+
+ void videobuf_queue_vmalloc_init(struct videobuf_queue* q,
+@@ -349,13 +417,24 @@ EXPORT_SYMBOL_GPL(videobuf_to_vmalloc);
+
+ void videobuf_vmalloc_free (struct videobuf_buffer *buf)
+ {
+- struct videobuf_vmalloc_memory *mem=buf->priv;
+- BUG_ON (!mem);
++ struct videobuf_vmalloc_memory *mem = buf->priv;
+
+- MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM);
++ /* mmapped memory can't be freed here, otherwise mmapped region
++ would be released, while still needed. In this case, the memory
++ release should happen inside videobuf_vm_close().
++ So, it should free memory only if the memory were allocated for
++ read() operation.
++ */
++ if ((buf->memory != V4L2_MEMORY_USERPTR) || (buf->baddr == 0))
++ return;
++
++ if (!mem)
++ return;
++
++ MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
+
+ vfree(mem->vmalloc);
+- mem->vmalloc=NULL;
++ mem->vmalloc = NULL;
+
+ return;
+ }
+diff --git a/drivers/media/video/videocodec.c b/drivers/media/video/videocodec.c
+index 87951ec..cf24956 100644
+--- a/drivers/media/video/videocodec.c
++++ b/drivers/media/video/videocodec.c
+@@ -39,12 +39,13 @@
+
+ #ifdef CONFIG_PROC_FS
+ #include <linux/proc_fs.h>
++#include <linux/seq_file.h>
+ #include <asm/uaccess.h>
+ #endif
+
+ #include "videocodec.h"
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-4)");
+
+@@ -320,56 +321,22 @@ videocodec_unregister (const struct videocodec *codec)
+ }
+
+ #ifdef CONFIG_PROC_FS
+-/* ============ */
+-/* procfs stuff */
+-/* ============ */
+-
+-static char *videocodec_buf = NULL;
+-static int videocodec_bufsize = 0;
+-
+-static int
+-videocodec_build_table (void)
++static int proc_videocodecs_show(struct seq_file *m, void *v)
+ {
+ struct codec_list *h = codeclist_top;
+ struct attached_list *a;
+- int i = 0, size;
+-
+- // sum up amount of slaves plus their attached masters
+- while (h) {
+- i += h->attached + 1;
+- h = h->next;
+- }
+-#define LINESIZE 100
+- size = LINESIZE * (i + 1);
+
+- dprintk(3, "videocodec_build table: %d entries, %d bytes\n", i,
+- size);
+-
+- kfree(videocodec_buf);
+- videocodec_buf = kmalloc(size, GFP_KERNEL);
+-
+- if (!videocodec_buf)
+- return 0;
+-
+- i = 0;
+- i += scnprintf(videocodec_buf + i, size - 1,
+- "<S>lave or attached <M>aster name type flags magic ");
+- i += scnprintf(videocodec_buf + i, size -i - 1, "(connected as)\n");
++ seq_printf(m, "<S>lave or attached <M>aster name type flags magic ");
++ seq_printf(m, "(connected as)\n");
+
+ h = codeclist_top;
+ while (h) {
+- if (i > (size - LINESIZE))
+- break; // security check
+- i += scnprintf(videocodec_buf + i, size -i -1,
+- "S %32s %04x %08lx %08lx (TEMPLATE)\n",
++ seq_printf(m, "S %32s %04x %08lx %08lx (TEMPLATE)\n",
+ h->codec->name, h->codec->type,
+ h->codec->flags, h->codec->magic);
+ a = h->list;
+ while (a) {
+- if (i > (size - LINESIZE))
+- break; // security check
+- i += scnprintf(videocodec_buf + i, size -i -1,
+- "M %32s %04x %08lx %08lx (%s)\n",
++ seq_printf(m, "M %32s %04x %08lx %08lx (%s)\n",
+ a->codec->master_data->name,
+ a->codec->master_data->type,
+ a->codec->master_data->flags,
+@@ -380,54 +347,21 @@ videocodec_build_table (void)
+ h = h->next;
+ }
+
+- return i;
++ return 0;
+ }
+
+-//The definition:
+-//typedef int (read_proc_t)(char *page, char **start, off_t off,
+-// int count, int *eof, void *data);
+-
+-static int
+-videocodec_info (char *buffer,
+- char **buffer_location,
+- off_t offset,
+- int buffer_length,
+- int *eof,
+- void *data)
++static int proc_videocodecs_open(struct inode *inode, struct file *file)
+ {
+- int size;
+-
+- dprintk(3, "videocodec_info: offset: %ld, len %d / size %d\n",
+- offset, buffer_length, videocodec_bufsize);
+-
+- if (offset == 0) {
+- videocodec_bufsize = videocodec_build_table();
+- }
+- if ((offset < 0) || (offset >= videocodec_bufsize)) {
+- dprintk(4,
+- "videocodec_info: call delivers no result, return 0\n");
+- *eof = 1;
+- return 0;
+- }
+-
+- if (buffer_length < (videocodec_bufsize - offset)) {
+- dprintk(4, "videocodec_info: %ld needed, %d got\n",
+- videocodec_bufsize - offset, buffer_length);
+- size = buffer_length;
+- } else {
+- dprintk(4, "videocodec_info: last reading of %ld bytes\n",
+- videocodec_bufsize - offset);
+- size = videocodec_bufsize - offset;
+- *eof = 1;
+- }
+-
+- memcpy(buffer, videocodec_buf + offset, size);
+- /* doesn't work... */
+- /* copy_to_user(buffer, videocodec_buf+offset, size); */
+- /* *buffer_location = videocodec_buf+offset; */
+-
+- return size;
++ return single_open(file, proc_videocodecs_show, NULL);
+ }
++
++static const struct file_operations videocodecs_proc_fops = {
++ .owner = THIS_MODULE,
++ .open = proc_videocodecs_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
+ #endif
+
+ /* ===================== */
+@@ -444,16 +378,8 @@ videocodec_init (void)
+ VIDEOCODEC_VERSION);
+
+ #ifdef CONFIG_PROC_FS
+- videocodec_buf = NULL;
+- videocodec_bufsize = 0;
+-
+- videocodec_proc_entry = create_proc_entry("videocodecs", 0, NULL);
+- if (videocodec_proc_entry) {
+- videocodec_proc_entry->read_proc = videocodec_info;
+- videocodec_proc_entry->write_proc = NULL;
+- videocodec_proc_entry->data = NULL;
+- videocodec_proc_entry->owner = THIS_MODULE;
+- } else {
++ videocodec_proc_entry = proc_create("videocodecs", 0, NULL, &videocodecs_proc_fops);
++ if (!videocodec_proc_entry) {
+ dprintk(1, KERN_ERR "videocodec: can't init procfs.\n");
+ }
+ #endif
+@@ -465,7 +391,6 @@ videocodec_exit (void)
+ {
+ #ifdef CONFIG_PROC_FS
+ remove_proc_entry("videocodecs", NULL);
+- kfree(videocodec_buf);
+ #endif
+ }
+
+diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
+index 0d9b637..31e8af0 100644
+--- a/drivers/media/video/videodev.c
++++ b/drivers/media/video/videodev.c
+@@ -18,14 +18,14 @@
+
+ #define dbgarg(cmd, fmt, arg...) \
+ if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { \
+- printk (KERN_DEBUG "%s: ", vfd->name); \
++ printk(KERN_DEBUG "%s: ", vfd->name); \
+ v4l_printk_ioctl(cmd); \
+- printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg); \
++ printk(" " fmt, ## arg); \
+ }
+
+ #define dbgarg2(fmt, arg...) \
+ if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) \
+- printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg);
++ printk(KERN_DEBUG "%s: " fmt, vfd->name, ## arg);
+
+ #include <linux/module.h>
+ #include <linux/types.h>
+@@ -378,38 +378,45 @@ static const char *v4l2_int_ioctls[] = {
+ external ioctl messages as well as internal V4L ioctl */
+ void v4l_printk_ioctl(unsigned int cmd)
+ {
+- char *dir;
++ char *dir, *type;
+
+- switch (_IOC_DIR(cmd)) {
+- case _IOC_NONE: dir = "--"; break;
+- case _IOC_READ: dir = "r-"; break;
+- case _IOC_WRITE: dir = "-w"; break;
+- case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
+- default: dir = "*ERR*"; break;
+- }
+ switch (_IOC_TYPE(cmd)) {
+ case 'd':
+- printk("v4l2_int ioctl %s, dir=%s (0x%08x)\n",
+- (_IOC_NR(cmd) < V4L2_INT_IOCTLS) ?
+- v4l2_int_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
+- break;
++ if (_IOC_NR(cmd) >= V4L2_INT_IOCTLS) {
++ type = "v4l2_int";
++ break;
++ }
++ printk("%s", v4l2_int_ioctls[_IOC_NR(cmd)]);
++ return;
+ #ifdef CONFIG_VIDEO_V4L1_COMPAT
+ case 'v':
+- printk("v4l1 ioctl %s, dir=%s (0x%08x)\n",
+- (_IOC_NR(cmd) < V4L1_IOCTLS) ?
+- v4l1_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
+- break;
++ if (_IOC_NR(cmd) >= V4L1_IOCTLS) {
++ type = "v4l1";
++ break;
++ }
++ printk("%s", v4l1_ioctls[_IOC_NR(cmd)]);
++ return;
+ #endif
+ case 'V':
+- printk("v4l2 ioctl %s, dir=%s (0x%08x)\n",
+- (_IOC_NR(cmd) < V4L2_IOCTLS) ?
+- v4l2_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
+- break;
+-
++ if (_IOC_NR(cmd) >= V4L2_IOCTLS) {
++ type = "v4l2";
++ break;
++ }
++ printk("%s", v4l2_ioctls[_IOC_NR(cmd)]);
++ return;
+ default:
+- printk("unknown ioctl '%c', dir=%s, #%d (0x%08x)\n",
+- _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd);
++ type = "unknown";
++ }
++
++ switch (_IOC_DIR(cmd)) {
++ case _IOC_NONE: dir = "--"; break;
++ case _IOC_READ: dir = "r-"; break;
++ case _IOC_WRITE: dir = "-w"; break;
++ case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
++ default: dir = "*ERR*"; break;
+ }
++ printk("%s ioctl '%c', dir=%s, #%d (0x%08x)",
++ type, _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd);
+ }
+ EXPORT_SYMBOL(v4l_printk_ioctl);
+
+@@ -774,6 +781,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
+ if ( (vfd->debug & V4L2_DEBUG_IOCTL) &&
+ !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {
+ v4l_print_ioctl(vfd->name, cmd);
++ printk("\n");
+ }
+
+ #ifdef CONFIG_VIDEO_V4L1_COMPAT
+@@ -1853,12 +1861,20 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
+ dbgarg (cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision);
+ break;
+ }
++ default:
++ {
++ if (!vfd->vidioc_default)
++ break;
++ ret = vfd->vidioc_default(file, fh, cmd, arg);
++ break;
++ }
+ } /* switch */
+
+ if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
+ if (ret<0) {
+- printk ("%s: err:\n", vfd->name);
++ printk("%s: err: on ", vfd->name);
+ v4l_print_ioctl(vfd->name, cmd);
++ printk("\n");
+ }
+ }
+
+@@ -2019,7 +2035,7 @@ int video_register_device(struct video_device *vfd, int type, int nr)
+ break;
+ default:
+ printk(KERN_ERR "%s called with unknown type: %d\n",
+- __FUNCTION__, type);
++ __func__, type);
+ return -1;
+ }
+
+@@ -2057,7 +2073,7 @@ int video_register_device(struct video_device *vfd, int type, int nr)
+ ret = device_register(&vfd->class_dev);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: device_register failed\n",
+- __FUNCTION__);
++ __func__);
+ goto fail_minor;
+ }
+
+diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
+index 5bb7529..d545c98 100644
+--- a/drivers/media/video/vino.c
++++ b/drivers/media/video/vino.c
+@@ -333,7 +333,7 @@ struct vino_settings {
+ *
+ * Use non-zero value to enable conversion.
+ */
+-static int vino_pixel_conversion = 0;
++static int vino_pixel_conversion;
+
+ module_param_named(pixelconv, vino_pixel_conversion, int, 0);
+
+@@ -4370,8 +4370,8 @@ static int vino_ioctl(struct inode *inode, struct file *file,
+
+ /* Initialization and cleanup */
+
+-// __initdata
+-static int vino_init_stage = 0;
++/* __initdata */
++static int vino_init_stage;
+
+ static const struct file_operations vino_fops = {
+ .owner = THIS_MODULE,
+@@ -4385,8 +4385,8 @@ static const struct file_operations vino_fops = {
+
+ static struct video_device v4l_device_template = {
+ .name = "NOT SET",
+- //.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE |
+- // VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY
++ /*.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE | */
++ /* VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY */
+ .fops = &vino_fops,
+ .minor = -1,
+ };
+diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
+index 1db067c..845be18 100644
+--- a/drivers/media/video/vivi.c
++++ b/drivers/media/video/vivi.c
+@@ -146,8 +146,6 @@ struct vivi_buffer {
+
+ struct vivi_dmaqueue {
+ struct list_head active;
+- struct list_head queued;
+- struct timer_list timeout;
+
+ /* thread for generating video stream*/
+ struct task_struct *kthread;
+@@ -162,8 +160,8 @@ static LIST_HEAD(vivi_devlist);
+ struct vivi_dev {
+ struct list_head vivi_devlist;
+
+- struct mutex lock;
+ spinlock_t slock;
++ struct mutex mutex;
+
+ int users;
+
+@@ -322,24 +320,26 @@ static void gen_line(char *basep, int inipos, int wmax,
+ end:
+ return;
+ }
++
+ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
+ {
+ int h , pos = 0;
+ int hmax = buf->vb.height;
+ int wmax = buf->vb.width;
+ struct timeval ts;
+- char *tmpbuf = kmalloc(wmax * 2, GFP_KERNEL);
++ char *tmpbuf = kmalloc(wmax * 2, GFP_ATOMIC);
+ void *vbuf = videobuf_to_vmalloc(&buf->vb);
+
+ if (!tmpbuf)
+ return;
+
++ if (!vbuf)
++ return;
++
+ for (h = 0; h < hmax; h++) {
+ gen_line(tmpbuf, 0, wmax, hmax, h, dev->mv_count,
+ dev->timestr);
+- /* FIXME: replacing to __copy_to_user */
+- if (copy_to_user(vbuf + pos, tmpbuf, wmax * 2) != 0)
+- dprintk(dev, 2, "vivifill copy_to_user failed.\n");
++ memcpy(vbuf + pos, tmpbuf, wmax * 2);
+ pos += wmax*2;
+ }
+
+@@ -372,107 +372,71 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
+ dev->timestr, (unsigned long)tmpbuf, pos);
+
+ /* Advice that buffer was filled */
+- buf->vb.state = VIDEOBUF_DONE;
+ buf->vb.field_count++;
+ do_gettimeofday(&ts);
+ buf->vb.ts = ts;
+-
+- list_del(&buf->vb.queue);
+- wake_up(&buf->vb.done);
++ buf->vb.state = VIDEOBUF_DONE;
+ }
+
+-static int restart_video_queue(struct vivi_dmaqueue *dma_q);
+-
+-static void vivi_thread_tick(struct vivi_dmaqueue *dma_q)
++static void vivi_thread_tick(struct vivi_fh *fh)
+ {
+- struct vivi_buffer *buf;
+- struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
++ struct vivi_buffer *buf;
++ struct vivi_dev *dev = fh->dev;
++ struct vivi_dmaqueue *dma_q = &dev->vidq;
+
+- int bc;
++ unsigned long flags = 0;
+
+- spin_lock(&dev->slock);
+- /* Announces videobuf that all went ok */
+- for (bc = 0;; bc++) {
+- if (list_empty(&dma_q->active)) {
+- dprintk(dev, 1, "No active queue to serve\n");
+- break;
+- }
++ dprintk(dev, 1, "Thread tick\n");
+
+- buf = list_entry(dma_q->active.next,
+- struct vivi_buffer, vb.queue);
++ spin_lock_irqsave(&dev->slock, flags);
++ if (list_empty(&dma_q->active)) {
++ dprintk(dev, 1, "No active queue to serve\n");
++ goto unlock;
++ }
+
+- /* Nobody is waiting something to be done, just return */
+- if (!waitqueue_active(&buf->vb.done)) {
+- mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
+- spin_unlock(&dev->slock);
+- return;
+- }
++ buf = list_entry(dma_q->active.next,
++ struct vivi_buffer, vb.queue);
++
++ /* Nobody is waiting on this buffer, return */
++ if (!waitqueue_active(&buf->vb.done))
++ goto unlock;
+
+- do_gettimeofday(&buf->vb.ts);
+- dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i);
++ list_del(&buf->vb.queue);
+
+- /* Fill buffer */
+- vivi_fillbuff(dev, buf);
++ do_gettimeofday(&buf->vb.ts);
+
+- if (list_empty(&dma_q->active)) {
+- del_timer(&dma_q->timeout);
+- } else {
+- mod_timer(&dma_q->timeout, jiffies + BUFFER_TIMEOUT);
+- }
+- }
+- if (bc != 1)
+- dprintk(dev, 1, "%s: %d buffers handled (should be 1)\n",
+- __FUNCTION__, bc);
+- spin_unlock(&dev->slock);
++ /* Fill buffer */
++ vivi_fillbuff(dev, buf);
++ dprintk(dev, 1, "filled buffer %p\n", buf);
++
++ wake_up(&buf->vb.done);
++ dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i);
++unlock:
++ spin_unlock_irqrestore(&dev->slock, flags);
++ return;
+ }
+
+ #define frames_to_ms(frames) \
+ ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR)
+
+-static void vivi_sleep(struct vivi_dmaqueue *dma_q)
++static void vivi_sleep(struct vivi_fh *fh)
+ {
+- struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
+- int timeout, running_time;
++ struct vivi_dev *dev = fh->dev;
++ struct vivi_dmaqueue *dma_q = &dev->vidq;
++ int timeout;
+ DECLARE_WAITQUEUE(wait, current);
+
+- dprintk(dev, 1, "%s dma_q=0x%08lx\n", __FUNCTION__,
++ dprintk(dev, 1, "%s dma_q=0x%08lx\n", __func__,
+ (unsigned long)dma_q);
+
+ add_wait_queue(&dma_q->wq, &wait);
+ if (kthread_should_stop())
+ goto stop_task;
+
+- running_time = jiffies - dma_q->ini_jiffies;
+- dma_q->frame++;
+-
+ /* Calculate time to wake up */
+- timeout = msecs_to_jiffies(frames_to_ms(dma_q->frame)) - running_time;
+-
+- if (timeout > msecs_to_jiffies(frames_to_ms(2)) || timeout <= 0) {
+- int old = dma_q->frame;
+- int nframes;
+-
+- dma_q->frame = (jiffies_to_msecs(running_time) /
+- frames_to_ms(1)) + 1;
+-
+- timeout = msecs_to_jiffies(frames_to_ms(dma_q->frame))
+- - running_time;
+-
+- if (unlikely (timeout <= 0))
+- timeout = 1;
+-
+- nframes = (dma_q->frame > old)?
+- dma_q->frame - old : old - dma_q->frame;
+-
+- dprintk(dev, 1, "%ld: %s %d frames. "
+- "Current frame is %d. Will sleep for %d jiffies\n",
+- jiffies,
+- (dma_q->frame > old)? "Underrun, losed" : "Overrun of",
+- nframes, dma_q->frame, timeout);
+- } else
+- dprintk(dev, 1, "will sleep for %d jiffies\n", timeout);
++ timeout = msecs_to_jiffies(frames_to_ms(1));
+
+- vivi_thread_tick(dma_q);
++ vivi_thread_tick(fh);
+
+ schedule_timeout_interruptible(timeout);
+
+@@ -483,16 +447,15 @@ stop_task:
+
+ static int vivi_thread(void *data)
+ {
+- struct vivi_dmaqueue *dma_q = data;
+- struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
++ struct vivi_fh *fh = data;
++ struct vivi_dev *dev = fh->dev;
+
+ dprintk(dev, 1, "thread started\n");
+
+- mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
+ set_freezable();
+
+ for (;;) {
+- vivi_sleep(dma_q);
++ vivi_sleep(fh);
+
+ if (kthread_should_stop())
+ break;
+@@ -501,16 +464,17 @@ static int vivi_thread(void *data)
+ return 0;
+ }
+
+-static int vivi_start_thread(struct vivi_dmaqueue *dma_q)
++static int vivi_start_thread(struct vivi_fh *fh)
+ {
+- struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
++ struct vivi_dev *dev = fh->dev;
++ struct vivi_dmaqueue *dma_q = &dev->vidq;
+
+ dma_q->frame = 0;
+ dma_q->ini_jiffies = jiffies;
+
+- dprintk(dev, 1, "%s\n", __FUNCTION__);
++ dprintk(dev, 1, "%s\n", __func__);
+
+- dma_q->kthread = kthread_run(vivi_thread, dma_q, "vivi");
++ dma_q->kthread = kthread_run(vivi_thread, fh, "vivi");
+
+ if (IS_ERR(dma_q->kthread)) {
+ printk(KERN_ERR "vivi: kernel_thread() failed\n");
+@@ -519,7 +483,7 @@ static int vivi_start_thread(struct vivi_dmaqueue *dma_q)
+ /* Wakes thread */
+ wake_up_interruptible(&dma_q->wq);
+
+- dprintk(dev, 1, "returning from %s\n", __FUNCTION__);
++ dprintk(dev, 1, "returning from %s\n", __func__);
+ return 0;
+ }
+
+@@ -527,7 +491,7 @@ static void vivi_stop_thread(struct vivi_dmaqueue *dma_q)
+ {
+ struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
+
+- dprintk(dev, 1, "%s\n", __FUNCTION__);
++ dprintk(dev, 1, "%s\n", __func__);
+ /* shutdown control thread */
+ if (dma_q->kthread) {
+ kthread_stop(dma_q->kthread);
+@@ -535,91 +499,6 @@ static void vivi_stop_thread(struct vivi_dmaqueue *dma_q)
+ }
+ }
+
+-static int restart_video_queue(struct vivi_dmaqueue *dma_q)
+-{
+- struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
+- struct vivi_buffer *buf, *prev;
+-
+- dprintk(dev, 1, "%s dma_q=0x%08lx\n", __FUNCTION__,
+- (unsigned long)dma_q);
+-
+- if (!list_empty(&dma_q->active)) {
+- buf = list_entry(dma_q->active.next,
+- struct vivi_buffer, vb.queue);
+- dprintk(dev, 2, "restart_queue [%p/%d]: restart dma\n",
+- buf, buf->vb.i);
+-
+- dprintk(dev, 1, "Restarting video dma\n");
+- vivi_stop_thread(dma_q);
+-
+- /* cancel all outstanding capture / vbi requests */
+- list_for_each_entry_safe(buf, prev, &dma_q->active, vb.queue) {
+- list_del(&buf->vb.queue);
+- buf->vb.state = VIDEOBUF_ERROR;
+- wake_up(&buf->vb.done);
+- }
+- mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
+-
+- return 0;
+- }
+-
+- prev = NULL;
+- for (;;) {
+- if (list_empty(&dma_q->queued))
+- return 0;
+- buf = list_entry(dma_q->queued.next,
+- struct vivi_buffer, vb.queue);
+- if (NULL == prev) {
+- list_del(&buf->vb.queue);
+- list_add_tail(&buf->vb.queue, &dma_q->active);
+-
+- dprintk(dev, 1, "Restarting video dma\n");
+- vivi_stop_thread(dma_q);
+- vivi_start_thread(dma_q);
+-
+- buf->vb.state = VIDEOBUF_ACTIVE;
+- mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT);
+- dprintk(dev, 2,
+- "[%p/%d] restart_queue - first active\n",
+- buf, buf->vb.i);
+-
+- } else if (prev->vb.width == buf->vb.width &&
+- prev->vb.height == buf->vb.height &&
+- prev->fmt == buf->fmt) {
+- list_del(&buf->vb.queue);
+- list_add_tail(&buf->vb.queue, &dma_q->active);
+- buf->vb.state = VIDEOBUF_ACTIVE;
+- dprintk(dev, 2,
+- "[%p/%d] restart_queue - move to active\n",
+- buf, buf->vb.i);
+- } else {
+- return 0;
+- }
+- prev = buf;
+- }
+-}
+-
+-static void vivi_vid_timeout(unsigned long data)
+-{
+- struct vivi_dev *dev = (struct vivi_dev *)data;
+- struct vivi_dmaqueue *vidq = &dev->vidq;
+- struct vivi_buffer *buf;
+-
+- spin_lock(&dev->slock);
+-
+- while (!list_empty(&vidq->active)) {
+- buf = list_entry(vidq->active.next,
+- struct vivi_buffer, vb.queue);
+- list_del(&buf->vb.queue);
+- buf->vb.state = VIDEOBUF_ERROR;
+- wake_up(&buf->vb.done);
+- printk(KERN_INFO "vivi/0: [%p/%d] timeout\n", buf, buf->vb.i);
+- }
+- restart_video_queue(vidq);
+-
+- spin_unlock(&dev->slock);
+-}
+-
+ /* ------------------------------------------------------------------
+ Videobuf operations
+ ------------------------------------------------------------------*/
+@@ -637,7 +516,7 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
+ while (*size * *count > vid_limit * 1024 * 1024)
+ (*count)--;
+
+- dprintk(dev, 1, "%s, count=%d, size=%d\n", __FUNCTION__,
++ dprintk(dev, 1, "%s, count=%d, size=%d\n", __func__,
+ *count, *size);
+
+ return 0;
+@@ -648,13 +527,13 @@ static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf)
+ struct vivi_fh *fh = vq->priv_data;
+ struct vivi_dev *dev = fh->dev;
+
+- dprintk(dev, 1, "%s\n", __FUNCTION__);
++ dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state);
+
+ if (in_interrupt())
+ BUG();
+
+- videobuf_waiton(&buf->vb, 0, 0);
+ videobuf_vmalloc_free(&buf->vb);
++ dprintk(dev, 1, "free_buffer: freed\n");
+ buf->vb.state = VIDEOBUF_NEEDS_INIT;
+ }
+
+@@ -667,28 +546,25 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
+ struct vivi_fh *fh = vq->priv_data;
+ struct vivi_dev *dev = fh->dev;
+ struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
+- int rc, init_buffer = 0;
++ int rc;
+
+- dprintk(dev, 1, "%s, field=%d\n", __FUNCTION__, field);
++ dprintk(dev, 1, "%s, field=%d\n", __func__, field);
+
+ BUG_ON(NULL == fh->fmt);
++
+ if (fh->width < 48 || fh->width > norm_maxw() ||
+ fh->height < 32 || fh->height > norm_maxh())
+ return -EINVAL;
++
+ buf->vb.size = fh->width*fh->height*2;
+ if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
+ return -EINVAL;
+
+- if (buf->fmt != fh->fmt ||
+- buf->vb.width != fh->width ||
+- buf->vb.height != fh->height ||
+- buf->vb.field != field) {
+- buf->fmt = fh->fmt;
+- buf->vb.width = fh->width;
+- buf->vb.height = fh->height;
+- buf->vb.field = field;
+- init_buffer = 1;
+- }
++ /* These properties only change when queue is idle, see s_fmt */
++ buf->fmt = fh->fmt;
++ buf->vb.width = fh->width;
++ buf->vb.height = fh->height;
++ buf->vb.field = field;
+
+ if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+ rc = videobuf_iolock(vq, &buf->vb, NULL);
+@@ -711,45 +587,12 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+ struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
+ struct vivi_fh *fh = vq->priv_data;
+ struct vivi_dev *dev = fh->dev;
+- struct vivi_dmaqueue *vidq = &dev->vidq;
+- struct vivi_buffer *prev;
+-
+- if (!list_empty(&vidq->queued)) {
+- dprintk(dev, 1, "adding vb queue=0x%08lx\n",
+- (unsigned long)&buf->vb.queue);
+- list_add_tail(&buf->vb.queue, &vidq->queued);
+- buf->vb.state = VIDEOBUF_QUEUED;
+- dprintk(dev, 2, "[%p/%d] buffer_queue - append to queued\n",
+- buf, buf->vb.i);
+- } else if (list_empty(&vidq->active)) {
+- list_add_tail(&buf->vb.queue, &vidq->active);
+-
+- buf->vb.state = VIDEOBUF_ACTIVE;
+- mod_timer(&vidq->timeout, jiffies+BUFFER_TIMEOUT);
+- dprintk(dev, 2, "[%p/%d] buffer_queue - first active\n",
+- buf, buf->vb.i);
+-
+- vivi_start_thread(vidq);
+- } else {
+- prev = list_entry(vidq->active.prev,
+- struct vivi_buffer, vb.queue);
+- if (prev->vb.width == buf->vb.width &&
+- prev->vb.height == buf->vb.height &&
+- prev->fmt == buf->fmt) {
+- list_add_tail(&buf->vb.queue, &vidq->active);
+- buf->vb.state = VIDEOBUF_ACTIVE;
+- dprintk(dev, 2,
+- "[%p/%d] buffer_queue - append to active\n",
+- buf, buf->vb.i);
+-
+- } else {
+- list_add_tail(&buf->vb.queue, &vidq->queued);
+- buf->vb.state = VIDEOBUF_QUEUED;
+- dprintk(dev, 2,
+- "[%p/%d] buffer_queue - first queued\n",
+- buf, buf->vb.i);
+- }
+- }
++ struct vivi_dmaqueue *vidq = &dev->vidq;
++
++ dprintk(dev, 1, "%s\n", __func__);
++
++ buf->vb.state = VIDEOBUF_QUEUED;
++ list_add_tail(&buf->vb.queue, &vidq->active);
+ }
+
+ static void buffer_release(struct videobuf_queue *vq,
+@@ -758,11 +601,8 @@ static void buffer_release(struct videobuf_queue *vq,
+ struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
+ struct vivi_fh *fh = vq->priv_data;
+ struct vivi_dev *dev = (struct vivi_dev *)fh->dev;
+- struct vivi_dmaqueue *vidq = &dev->vidq;
+-
+- dprintk(dev, 1, "%s\n", __FUNCTION__);
+
+- vivi_stop_thread(vidq);
++ dprintk(dev, 1, "%s\n", __func__);
+
+ free_buffer(vq, buf);
+ }
+@@ -869,17 +709,31 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+ {
+ struct vivi_fh *fh = priv;
++ struct videobuf_queue *q = &fh->vb_vidq;
++
+ int ret = vidioc_try_fmt_cap(file, fh, f);
+ if (ret < 0)
+ return (ret);
+
++ mutex_lock(&q->vb_lock);
++
++ if (videobuf_queue_is_busy(&fh->vb_vidq)) {
++ dprintk(fh->dev, 1, "%s queue busy\n", __func__);
++ ret = -EBUSY;
++ goto out;
++ }
++
+ fh->fmt = &format;
+ fh->width = f->fmt.pix.width;
+ fh->height = f->fmt.pix.height;
+ fh->vb_vidq.field = f->fmt.pix.field;
+ fh->type = f->type;
+
+- return (0);
++ ret = 0;
++out:
++ mutex_unlock(&q->vb_lock);
++
++ return (ret);
+ }
+
+ static int vidioc_reqbufs(struct file *file, void *priv,
+@@ -1034,8 +888,9 @@ static int vivi_open(struct inode *inode, struct file *file)
+ {
+ int minor = iminor(inode);
+ struct vivi_dev *dev;
+- struct vivi_fh *fh;
++ struct vivi_fh *fh = NULL;
+ int i;
++ int retval = 0;
+
+ printk(KERN_DEBUG "vivi: open called (minor=%d)\n", minor);
+
+@@ -1045,9 +900,15 @@ static int vivi_open(struct inode *inode, struct file *file)
+ return -ENODEV;
+
+ found:
+- /* If more than one user, mutex should be added */
++ mutex_lock(&dev->mutex);
+ dev->users++;
+
++ if (dev->users > 1) {
++ dev->users--;
++ retval = -EBUSY;
++ goto unlock;
++ }
++
+ dprintk(dev, 1, "open minor=%d type=%s users=%d\n", minor,
+ v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users);
+
+@@ -1055,8 +916,13 @@ found:
+ fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+ if (NULL == fh) {
+ dev->users--;
+- return -ENOMEM;
++ retval = -ENOMEM;
++ goto unlock;
+ }
++unlock:
++ mutex_unlock(&dev->mutex);
++ if (retval)
++ return retval;
+
+ file->private_data = fh;
+ fh->dev = dev;
+@@ -1084,6 +950,8 @@ found:
+ NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED,
+ sizeof(struct vivi_buffer), fh);
+
++ vivi_start_thread(fh);
++
+ return 0;
+ }
+
+@@ -1106,7 +974,7 @@ vivi_poll(struct file *file, struct poll_table_struct *wait)
+ struct vivi_dev *dev = fh->dev;
+ struct videobuf_queue *q = &fh->vb_vidq;
+
+- dprintk(dev, 1, "%s\n", __FUNCTION__);
++ dprintk(dev, 1, "%s\n", __func__);
+
+ if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
+ return POLLERR;
+@@ -1128,7 +996,9 @@ static int vivi_close(struct inode *inode, struct file *file)
+
+ kfree(fh);
+
++ mutex_lock(&dev->mutex);
+ dev->users--;
++ mutex_unlock(&dev->mutex);
+
+ dprintk(dev, 1, "close called (minor=%d, users=%d)\n",
+ minor, dev->users);
+@@ -1182,6 +1052,7 @@ static const struct file_operations vivi_fops = {
+ .read = vivi_read,
+ .poll = vivi_poll,
+ .ioctl = video_ioctl2, /* V4L2 ioctl handler */
++ .compat_ioctl = v4l_compat_ioctl32,
+ .mmap = vivi_mmap,
+ .llseek = no_llseek,
+ };
+@@ -1236,16 +1107,11 @@ static int __init vivi_init(void)
+
+ /* init video dma queues */
+ INIT_LIST_HEAD(&dev->vidq.active);
+- INIT_LIST_HEAD(&dev->vidq.queued);
+ init_waitqueue_head(&dev->vidq.wq);
+
+ /* initialize locks */
+- mutex_init(&dev->lock);
+ spin_lock_init(&dev->slock);
+-
+- dev->vidq.timeout.function = vivi_vid_timeout;
+- dev->vidq.timeout.data = (unsigned long)dev;
+- init_timer(&dev->vidq.timeout);
++ mutex_init(&dev->mutex);
+
+ vfd = video_device_alloc();
+ if (NULL == vfd)
+diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c
+index a913385..3529302 100644
+--- a/drivers/media/video/vpx3220.c
++++ b/drivers/media/video/vpx3220.c
+@@ -40,7 +40,7 @@
+ #define I2C_VPX3220 0x86
+ #define VPX3220_DEBUG KERN_DEBUG "vpx3220: "
+
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c
+index 08aaae0..33f7026 100644
+--- a/drivers/media/video/w9966.c
++++ b/drivers/media/video/w9966.c
+@@ -61,10 +61,10 @@
+ #include <media/v4l2-common.h>
+ #include <linux/parport.h>
+
+-//#define DEBUG // Undef me for production
++/*#define DEBUG*/ /* Undef me for production */
+
+ #ifdef DEBUG
+-#define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __FUNCTION__ , ##a)
++#define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __func__ , ##a)
+ #else
+ #define DPRINTF(x...)
+ #endif
+@@ -134,7 +134,7 @@ MODULE_PARM_DESC(pardev, "pardev: where to search for\n\
+ \tEg: >pardev=parport3,aggressive,parport2,parport1< would assign\n\
+ \tcam 1 to parport3 and search every parport for cam 2 etc...");
+
+-static int parmode = 0;
++static int parmode;
+ module_param(parmode, int, 0);
+ MODULE_PARM_DESC(parmode, "parmode: transfer mode (0=auto, 1=ecp, 2=epp");
+
+@@ -188,7 +188,9 @@ static const struct file_operations w9966_fops = {
+ .open = video_exclusive_open,
+ .release = video_exclusive_release,
+ .ioctl = w9966_v4l_ioctl,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .read = w9966_v4l_read,
+ .llseek = no_llseek,
+ };
+diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c
+index 2ae1430..8405224 100644
+--- a/drivers/media/video/w9968cf.c
++++ b/drivers/media/video/w9968cf.c
+@@ -3461,7 +3461,9 @@ static const struct file_operations w9968cf_fops = {
+ .release = w9968cf_release,
+ .read = w9968cf_read,
+ .ioctl = w9968cf_ioctl,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .mmap = w9968cf_mmap,
+ .llseek = no_llseek,
+ };
+@@ -3481,7 +3483,7 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
+ enum w9968cf_model_id mod_id;
+ struct list_head* ptr;
+ u8 sc = 0; /* number of simultaneous cameras */
+- static unsigned short dev_nr = 0; /* we are handling device number n */
++ static unsigned short dev_nr; /* 0 - we are handling device number n */
+
+ if (le16_to_cpu(udev->descriptor.idVendor) == winbond_id_table[0].idVendor &&
+ le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[0].idProduct)
+diff --git a/drivers/media/video/w9968cf.h b/drivers/media/video/w9968cf.h
+index ec7696e..3c95316 100644
+--- a/drivers/media/video/w9968cf.h
++++ b/drivers/media/video/w9968cf.h
+@@ -298,7 +298,7 @@ struct w9968cf_device {
+ dev_warn(&cam->dev, fmt "\n", ## args); \
+ else if ((level) >= 5) \
+ dev_info(&cam->dev, "[%s:%d] " fmt "\n", \
+- __FUNCTION__, __LINE__ , ## args); \
++ __func__, __LINE__ , ## args); \
+ } \
+ }
+ /* For generic kernel (not device specific) messages */
+@@ -309,7 +309,7 @@ struct w9968cf_device {
+ if ((level) >= 1 && (level) <= 4) \
+ pr_info("w9968cf: " fmt "\n", ## args); \
+ else if ((level) >= 5) \
+- pr_debug("w9968cf: [%s:%d] " fmt "\n", __FUNCTION__, \
++ pr_debug("w9968cf: [%s:%d] " fmt "\n", __func__, \
+ __LINE__ , ## args); \
+ } \
+ }
+@@ -321,7 +321,7 @@ struct w9968cf_device {
+
+ #undef PDBG
+ #define PDBG(fmt, args...) \
+-dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args);
++dev_info(&cam->dev, "[%s:%d] " fmt "\n", __func__, __LINE__ , ## args);
+
+ #undef PDBGG
+ #define PDBGG(fmt, args...) do {;} while(0); /* nothing: it's a placeholder */
+diff --git a/drivers/media/video/zc0301/zc0301.h b/drivers/media/video/zc0301/zc0301.h
+index a2de50e..7bbab54 100644
+--- a/drivers/media/video/zc0301/zc0301.h
++++ b/drivers/media/video/zc0301/zc0301.h
+@@ -160,7 +160,7 @@ do { \
+ dev_info(&cam->usbdev->dev, fmt "\n", ## args); \
+ else if ((level) >= 3) \
+ dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", \
+- __FILE__, __FUNCTION__, __LINE__ , ## args); \
++ __FILE__, __func__, __LINE__ , ## args); \
+ } \
+ } while (0)
+ # define KDBG(level, fmt, args...) \
+@@ -170,7 +170,7 @@ do { \
+ pr_info("zc0301: " fmt "\n", ## args); \
+ else if ((level) == 3) \
+ pr_debug("sn9c102: [%s:%s:%d] " fmt "\n", __FILE__, \
+- __FUNCTION__, __LINE__ , ## args); \
++ __func__, __LINE__ , ## args); \
+ } \
+ } while (0)
+ # define V4LDBG(level, name, cmd) \
+@@ -186,7 +186,7 @@ do { \
+
+ #undef PDBG
+ #define PDBG(fmt, args...) \
+-dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__, \
++dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__, \
+ __LINE__ , ## args)
+
+ #undef PDBGG
+diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c
+index 2c5665c..363dd2b 100644
+--- a/drivers/media/video/zc0301/zc0301_core.c
++++ b/drivers/media/video/zc0301/zc0301_core.c
+@@ -1925,7 +1925,9 @@ static const struct file_operations zc0301_fops = {
+ .open = zc0301_open,
+ .release = zc0301_release,
+ .ioctl = zc0301_ioctl,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .read = zc0301_read,
+ .poll = zc0301_poll,
+ .mmap = zc0301_mmap,
+@@ -1939,7 +1941,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
+ {
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct zc0301_device* cam;
+- static unsigned int dev_nr = 0;
++ static unsigned int dev_nr;
+ unsigned int i;
+ int err = 0;
+
+diff --git a/drivers/media/video/zoran.h b/drivers/media/video/zoran.h
+index 498a43c..81cc3b0 100644
+--- a/drivers/media/video/zoran.h
++++ b/drivers/media/video/zoran.h
+@@ -243,10 +243,8 @@ struct zoran_format {
+ #ifdef CONFIG_VIDEO_V4L1_COMPAT
+ int palette;
+ #endif
+-#ifdef CONFIG_VIDEO_V4L2
+ __u32 fourcc;
+ int colorspace;
+-#endif
+ int depth;
+ __u32 flags;
+ __u32 vfespfr;
+@@ -271,20 +269,6 @@ struct zoran_v4l_settings {
+ const struct zoran_format *format; /* capture format */
+ };
+
+-/* whoops, this one is undeclared if !v4l2 */
+-#ifndef CONFIG_VIDEO_V4L2
+-struct v4l2_jpegcompression {
+- int quality;
+- int APPn;
+- int APP_len;
+- char APP_data[60];
+- int COM_len;
+- char COM_data[60];
+- __u32 jpeg_markers;
+- __u8 reserved[116];
+-};
+-#endif
+-
+ /* jpg-capture/-playback settings */
+ struct zoran_jpg_settings {
+ int decimation; /* this bit is used to set everything to default */
+diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c
+index 690281b..006d488 100644
+--- a/drivers/media/video/zoran_card.c
++++ b/drivers/media/video/zoran_card.c
+@@ -83,7 +83,7 @@ MODULE_PARM_DESC(decoder, "i2c TV decoder");
+ or set in in a VIDIOCSFBUF ioctl
+ */
+
+-static unsigned long vidmem = 0; /* Video memory base address */
++static unsigned long vidmem; /* default = 0 - Video memory base address */
+ module_param(vidmem, ulong, 0444);
+ MODULE_PARM_DESC(vidmem, "Default video memory base address");
+
+@@ -91,7 +91,7 @@ MODULE_PARM_DESC(vidmem, "Default video memory base address");
+ Default input and video norm at startup of the driver.
+ */
+
+-static unsigned int default_input = 0; /* 0=Composite, 1=S-Video */
++static unsigned int default_input; /* default 0 = Composite, 1 = S-Video */
+ module_param(default_input, uint, 0444);
+ MODULE_PARM_DESC(default_input,
+ "Default input (0=Composite, 1=S-Video, 2=Internal)");
+@@ -101,7 +101,7 @@ module_param(default_mux, int, 0644);
+ MODULE_PARM_DESC(default_mux,
+ "Default 6 Eyes mux setting (Input selection)");
+
+-static int default_norm = 0; /* 0=PAL, 1=NTSC 2=SECAM */
++static int default_norm; /* default 0 = PAL, 1 = NTSC 2 = SECAM */
+ module_param(default_norm, int, 0444);
+ MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)");
+
+diff --git a/drivers/media/video/zoran_card.h b/drivers/media/video/zoran_card.h
+index 8444ca0..1b5c417 100644
+--- a/drivers/media/video/zoran_card.h
++++ b/drivers/media/video/zoran_card.h
+@@ -50,4 +50,6 @@ extern int zoran_check_jpg_settings(struct zoran *zr,
+ extern void zoran_open_init_params(struct zoran *zr);
+ extern void zoran_vdev_release(struct video_device *vdev);
+
++void zr36016_write(struct videocodec *codec, u16 reg, u32 val);
++
+ #endif /* __ZORAN_CARD_H__ */
+diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c
+index f97c206..7b60533 100644
+--- a/drivers/media/video/zoran_device.c
++++ b/drivers/media/video/zoran_device.c
+@@ -60,7 +60,8 @@
+
+ extern const struct zoran_format zoran_formats[];
+
+-static int lml33dpath = 0; /* 1 will use digital path in capture
++static int lml33dpath; /* default = 0
++ * 1 will use digital path in capture
+ * mode instead of analog. It can be
+ * used for picture adjustments using
+ * tool like xawtv while watching image
+@@ -927,11 +928,6 @@ count_reset_interrupt (struct zoran *zr)
+ return isr;
+ }
+
+-/* hack */
+-extern void zr36016_write (struct videocodec *codec,
+- u16 reg,
+- u32 val);
+-
+ void
+ jpeg_start (struct zoran *zr)
+ {
+@@ -987,7 +983,7 @@ void
+ zr36057_enable_jpg (struct zoran *zr,
+ enum zoran_codec_mode mode)
+ {
+- static int zero = 0;
++ static int zero;
+ static int one = 1;
+ struct vfe_settings cap;
+ int field_size =
+@@ -1726,7 +1722,7 @@ decoder_command (struct zoran *zr,
+ return -EIO;
+
+ if (zr->card.type == LML33 &&
+- (cmd == DECODER_SET_NORM || DECODER_SET_INPUT)) {
++ (cmd == DECODER_SET_NORM || cmd == DECODER_SET_INPUT)) {
+ int res;
+
+ // Bt819 needs to reset its FIFO buffer using #FRST pin and
+diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c
+index fea4946..0134bec 100644
+--- a/drivers/media/video/zoran_driver.c
++++ b/drivers/media/video/zoran_driver.c
+@@ -85,7 +85,6 @@
+ #include "zoran_device.h"
+ #include "zoran_card.h"
+
+-#ifdef CONFIG_VIDEO_V4L2
+ /* we declare some card type definitions here, they mean
+ * the same as the v4l1 ZORAN_VID_TYPE above, except it's v4l2 */
+ #define ZORAN_V4L2_VID_FLAGS ( \
+@@ -94,19 +93,15 @@
+ V4L2_CAP_VIDEO_OUTPUT |\
+ V4L2_CAP_VIDEO_OVERLAY \
+ )
+-#endif
+
+ #include <asm/byteorder.h>
+
+-#if defined(CONFIG_VIDEO_V4L2) && defined(CONFIG_VIDEO_V4L1_COMPAT)
++#if defined(CONFIG_VIDEO_V4L1_COMPAT)
+ #define ZFMT(pal, fcc, cs) \
+ .palette = (pal), .fourcc = (fcc), .colorspace = (cs)
+-#elif defined(CONFIG_VIDEO_V4L2)
+-#define ZFMT(pal, fcc, cs) \
+- .fourcc = (fcc), .colorspace = (cs)
+ #else
+ #define ZFMT(pal, fcc, cs) \
+- .palette = (pal)
++ .fourcc = (fcc), .colorspace = (cs)
+ #endif
+
+ const struct zoran_format zoran_formats[] = {
+@@ -205,11 +200,10 @@ extern int jpg_nbufs;
+ extern int jpg_bufsize;
+ extern int pass_through;
+
+-static int lock_norm = 0; /* 1=Don't change TV standard (norm) */
++static int lock_norm; /* 0 = default 1 = Don't change TV standard (norm) */
+ module_param(lock_norm, int, 0644);
+ MODULE_PARM_DESC(lock_norm, "Prevent norm changes (1 = ignore, >1 = fail)");
+
+-#ifdef CONFIG_VIDEO_V4L2
+ /* small helper function for calculating buffersizes for v4l2
+ * we calculate the nearest higher power-of-two, which
+ * will be the recommended buffersize */
+@@ -232,7 +226,6 @@ zoran_v4l2_calc_bufsize (struct zoran_jpg_settings *settings)
+ return 8192;
+ return result;
+ }
+-#endif
+
+ /* forward references */
+ static void v4l_fbuffer_free(struct file *file);
+@@ -1709,7 +1702,6 @@ setup_overlay (struct file *file,
+ return wait_grab_pending(zr);
+ }
+
+-#ifdef CONFIG_VIDEO_V4L2
+ /* get the status of a buffer in the clients buffer queue */
+ static int
+ zoran_v4l2_buffer_status (struct file *file,
+@@ -1815,7 +1807,6 @@ zoran_v4l2_buffer_status (struct file *file,
+
+ return 0;
+ }
+-#endif
+
+ static int
+ zoran_set_norm (struct zoran *zr,
+@@ -2624,8 +2615,6 @@ zoran_do_ioctl (struct inode *inode,
+ }
+ break;
+
+-#ifdef CONFIG_VIDEO_V4L2
+-
+ /* The new video4linux2 capture interface - much nicer than video4linux1, since
+ * it allows for integrating the JPEG capturing calls inside standard v4l2
+ */
+@@ -4197,7 +4186,6 @@ zoran_do_ioctl (struct inode *inode,
+ return 0;
+ }
+ break;
+-#endif
+
+ default:
+ dprintk(1, KERN_DEBUG "%s: UNKNOWN ioctl cmd: 0x%x\n",
+@@ -4247,7 +4235,7 @@ zoran_poll (struct file *file,
+ dprintk(3,
+ KERN_DEBUG
+ "%s: %s() raw - active=%c, sync_tail=%lu/%c, pend_tail=%lu, pend_head=%lu\n",
+- ZR_DEVNAME(zr), __FUNCTION__,
++ ZR_DEVNAME(zr), __func__,
+ "FAL"[fh->v4l_buffers.active], zr->v4l_sync_tail,
+ "UPMD"[zr->v4l_buffers.buffer[frame].state],
+ zr->v4l_pend_tail, zr->v4l_pend_head);
+@@ -4269,7 +4257,7 @@ zoran_poll (struct file *file,
+ dprintk(3,
+ KERN_DEBUG
+ "%s: %s() jpg - active=%c, que_tail=%lu/%c, que_head=%lu, dma=%lu/%lu\n",
+- ZR_DEVNAME(zr), __FUNCTION__,
++ ZR_DEVNAME(zr), __func__,
+ "FAL"[fh->jpg_buffers.active], zr->jpg_que_tail,
+ "UPMD"[zr->jpg_buffers.buffer[frame].state],
+ zr->jpg_que_head, zr->jpg_dma_tail, zr->jpg_dma_head);
+@@ -4644,7 +4632,9 @@ static const struct file_operations zoran_fops = {
+ .open = zoran_open,
+ .release = zoran_close,
+ .ioctl = zoran_ioctl,
++#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
++#endif
+ .llseek = no_llseek,
+ .read = zoran_read,
+ .write = zoran_write,
+@@ -4655,9 +4645,7 @@ static const struct file_operations zoran_fops = {
+ struct video_device zoran_template __devinitdata = {
+ .name = ZORAN_NAME,
+ .type = ZORAN_VID_TYPE,
+-#ifdef CONFIG_VIDEO_V4L2
+ .type2 = ZORAN_V4L2_VID_FLAGS,
+-#endif
+ .fops = &zoran_fops,
+ .release = &zoran_vdev_release,
+ .minor = -1
+diff --git a/drivers/media/video/zr36016.c b/drivers/media/video/zr36016.c
+index dd08455..00d132b 100644
+--- a/drivers/media/video/zr36016.c
++++ b/drivers/media/video/zr36016.c
+@@ -55,11 +55,10 @@
+ #define MAX_CODECS 20
+
+ /* amount of chips attached via this driver */
+-static int zr36016_codecs = 0;
++static int zr36016_codecs;
+
+ /* debugging is available via module parameter */
+-
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-4)");
+
+diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zr36050.c
+index faae4ec..cf8b271 100644
+--- a/drivers/media/video/zr36050.c
++++ b/drivers/media/video/zr36050.c
+@@ -52,11 +52,10 @@
+ #define MAX_CODECS 20
+
+ /* amount of chips attached via this driver */
+-static int zr36050_codecs = 0;
++static int zr36050_codecs;
+
+ /* debugging is available via module parameter */
+-
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-4)");
+
+diff --git a/drivers/media/video/zr36060.c b/drivers/media/video/zr36060.c
+index 7849b65..8e74054 100644
+--- a/drivers/media/video/zr36060.c
++++ b/drivers/media/video/zr36060.c
+@@ -52,14 +52,14 @@
+ #define MAX_CODECS 20
+
+ /* amount of chips attached via this driver */
+-static int zr36060_codecs = 0;
++static int zr36060_codecs;
+
+-static int low_bitrate = 0;
++static int low_bitrate;
+ module_param(low_bitrate, bool, 0);
+ MODULE_PARM_DESC(low_bitrate, "Buz compatibility option, halves bitrate");
+
+ /* debugging is available via module parameter */
+-static int debug = 0;
++static int debug;
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "Debug level (0-4)");
+
+diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c
+index 04949c8..a0e49dc 100644
+--- a/drivers/media/video/zr364xx.c
++++ b/drivers/media/video/zr364xx.c
+@@ -62,8 +62,8 @@
+
+
+ /* Module parameters */
+-static int debug = 0;
+-static int mode = 0;
++static int debug;
++static int mode;
+
+
+ /* Module parameters interface */
+diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c
+index 946e3d3..61b98c3 100644
+--- a/drivers/memstick/core/memstick.c
++++ b/drivers/memstick/core/memstick.c
+@@ -177,16 +177,16 @@ static struct bus_type memstick_bus_type = {
+ .resume = memstick_device_resume
+ };
+
+-static void memstick_free(struct class_device *cdev)
++static void memstick_free(struct device *dev)
+ {
+- struct memstick_host *host = container_of(cdev, struct memstick_host,
+- cdev);
++ struct memstick_host *host = container_of(dev, struct memstick_host,
++ dev);
+ kfree(host);
+ }
+
+ static struct class memstick_host_class = {
+ .name = "memstick_host",
+- .release = memstick_free
++ .dev_release = memstick_free
+ };
+
+ static void memstick_free_card(struct device *dev)
+@@ -383,8 +383,8 @@ static struct memstick_dev *memstick_alloc_card(struct memstick_host *host)
+ if (card) {
+ card->host = host;
+ snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
+- "%s", host->cdev.class_id);
+- card->dev.parent = host->cdev.dev;
++ "%s", host->dev.bus_id);
++ card->dev.parent = &host->dev;
+ card->dev.bus = &memstick_bus_type;
+ card->dev.release = memstick_free_card;
+ card->check = memstick_dummy_check;
+@@ -427,7 +427,7 @@ static void memstick_check(struct work_struct *work)
+ media_checker);
+ struct memstick_dev *card;
+
+- dev_dbg(host->cdev.dev, "memstick_check started\n");
++ dev_dbg(&host->dev, "memstick_check started\n");
+ mutex_lock(&host->lock);
+ if (!host->card)
+ memstick_power_on(host);
+@@ -440,7 +440,7 @@ static void memstick_check(struct work_struct *work)
+ host->card = NULL;
+ }
+ } else {
+- dev_dbg(host->cdev.dev, "new card %02x, %02x, %02x\n",
++ dev_dbg(&host->dev, "new card %02x, %02x, %02x\n",
+ card->id.type, card->id.category, card->id.class);
+ if (host->card) {
+ if (memstick_set_rw_addr(host->card)
+@@ -465,7 +465,7 @@ static void memstick_check(struct work_struct *work)
+ host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF);
+
+ mutex_unlock(&host->lock);
+- dev_dbg(host->cdev.dev, "memstick_check finished\n");
++ dev_dbg(&host->dev, "memstick_check finished\n");
+ }
+
+ /**
+@@ -482,9 +482,9 @@ struct memstick_host *memstick_alloc_host(unsigned int extra,
+ if (host) {
+ mutex_init(&host->lock);
+ INIT_WORK(&host->media_checker, memstick_check);
+- host->cdev.class = &memstick_host_class;
+- host->cdev.dev = dev;
+- class_device_initialize(&host->cdev);
++ host->dev.class = &memstick_host_class;
++ host->dev.parent = dev;
++ device_initialize(&host->dev);
+ }
+ return host;
+ }
+@@ -507,10 +507,9 @@ int memstick_add_host(struct memstick_host *host)
+ if (rc)
+ return rc;
+
+- snprintf(host->cdev.class_id, BUS_ID_SIZE,
+- "memstick%u", host->id);
++ snprintf(host->dev.bus_id, BUS_ID_SIZE, "memstick%u", host->id);
+
+- rc = class_device_add(&host->cdev);
++ rc = device_add(&host->dev);
+ if (rc) {
+ spin_lock(&memstick_host_lock);
+ idr_remove(&memstick_host_idr, host->id);
+@@ -541,7 +540,7 @@ void memstick_remove_host(struct memstick_host *host)
+ spin_lock(&memstick_host_lock);
+ idr_remove(&memstick_host_idr, host->id);
+ spin_unlock(&memstick_host_lock);
+- class_device_del(&host->cdev);
++ device_del(&host->dev);
+ }
+ EXPORT_SYMBOL(memstick_remove_host);
+
+@@ -552,7 +551,7 @@ EXPORT_SYMBOL(memstick_remove_host);
+ void memstick_free_host(struct memstick_host *host)
+ {
+ mutex_destroy(&host->lock);
+- class_device_put(&host->cdev);
++ put_device(&host->dev);
+ }
+ EXPORT_SYMBOL(memstick_free_host);
+
+diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c
+index 557dbbb..477d0fb 100644
+--- a/drivers/memstick/core/mspro_block.c
++++ b/drivers/memstick/core/mspro_block.c
+@@ -1127,8 +1127,8 @@ static int mspro_block_init_disk(struct memstick_dev *card)
+ u64 limit = BLK_BOUNCE_HIGH;
+ unsigned long capacity;
+
+- if (host->cdev.dev->dma_mask && *(host->cdev.dev->dma_mask))
+- limit = *(host->cdev.dev->dma_mask);
++ if (host->dev.dma_mask && *(host->dev.dma_mask))
++ limit = *(host->dev.dma_mask);
+
+ for (rc = 0; msb->attr_group.attrs[rc]; ++rc) {
+ s_attr = mspro_from_sysfs_attr(msb->attr_group.attrs[rc]);
+diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c
+index 8770a5f..a054668 100644
+--- a/drivers/memstick/host/jmb38x_ms.c
++++ b/drivers/memstick/host/jmb38x_ms.c
+@@ -361,15 +361,15 @@ static int jmb38x_ms_issue_cmd(struct memstick_host *msh)
+ unsigned int data_len, cmd, t_val;
+
+ if (!(STATUS_HAS_MEDIA & readl(host->addr + STATUS))) {
+- dev_dbg(msh->cdev.dev, "no media status\n");
++ dev_dbg(&msh->dev, "no media status\n");
+ host->req->error = -ETIME;
+ return host->req->error;
+ }
+
+- dev_dbg(msh->cdev.dev, "control %08x\n",
++ dev_dbg(&msh->dev, "control %08x\n",
+ readl(host->addr + HOST_CONTROL));
+- dev_dbg(msh->cdev.dev, "status %08x\n", readl(host->addr + INT_STATUS));
+- dev_dbg(msh->cdev.dev, "hstatus %08x\n", readl(host->addr + STATUS));
++ dev_dbg(&msh->dev, "status %08x\n", readl(host->addr + INT_STATUS));
++ dev_dbg(&msh->dev, "hstatus %08x\n", readl(host->addr + STATUS));
+
+ host->cmd_flags = 0;
+ host->block_pos = 0;
+@@ -448,7 +448,7 @@ static int jmb38x_ms_issue_cmd(struct memstick_host *msh)
+ host->req->error = 0;
+
+ writel(cmd, host->addr + TPC);
+- dev_dbg(msh->cdev.dev, "executing TPC %08x, len %x\n", cmd, data_len);
++ dev_dbg(&msh->dev, "executing TPC %08x, len %x\n", cmd, data_len);
+
+ return 0;
+ }
+@@ -461,11 +461,11 @@ static void jmb38x_ms_complete_cmd(struct memstick_host *msh, int last)
+
+ del_timer(&host->timer);
+
+- dev_dbg(msh->cdev.dev, "c control %08x\n",
++ dev_dbg(&msh->dev, "c control %08x\n",
+ readl(host->addr + HOST_CONTROL));
+- dev_dbg(msh->cdev.dev, "c status %08x\n",
++ dev_dbg(&msh->dev, "c status %08x\n",
+ readl(host->addr + INT_STATUS));
+- dev_dbg(msh->cdev.dev, "c hstatus %08x\n", readl(host->addr + STATUS));
++ dev_dbg(&msh->dev, "c hstatus %08x\n", readl(host->addr + STATUS));
+
+ host->req->int_reg = readl(host->addr + STATUS) & 0xff;
+
+diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
+index c6be6eb..db3c892 100644
+--- a/drivers/message/fusion/mptbase.c
++++ b/drivers/message/fusion/mptbase.c
+@@ -79,7 +79,7 @@ MODULE_VERSION(my_VERSION);
+ /*
+ * cmd line parameters
+ */
+-static int mpt_msi_enable;
++static int mpt_msi_enable = -1;
+ module_param(mpt_msi_enable, int, 0);
+ MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");
+
+@@ -1686,6 +1686,11 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
+ ioc->bus_type = SAS;
+ }
+
++ if (ioc->bus_type == SAS && mpt_msi_enable == -1)
++ ioc->msi_enable = 1;
++ else
++ ioc->msi_enable = mpt_msi_enable;
++
+ if (ioc->errata_flag_1064)
+ pci_disable_io_access(pdev);
+
+@@ -1831,7 +1836,7 @@ mpt_suspend(struct pci_dev *pdev, pm_message_t state)
+ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+
+ free_irq(ioc->pci_irq, ioc);
+- if (mpt_msi_enable)
++ if (ioc->msi_enable)
+ pci_disable_msi(ioc->pcidev);
+ ioc->pci_irq = -1;
+ pci_save_state(pdev);
+@@ -2057,15 +2062,17 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
+ if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
+ ioc->pci_irq = -1;
+ if (ioc->pcidev->irq) {
+- if (mpt_msi_enable && !pci_enable_msi(ioc->pcidev))
++ if (ioc->msi_enable && !pci_enable_msi(ioc->pcidev))
+ printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n",
+ ioc->name);
++ else
++ ioc->msi_enable = 0;
+ rc = request_irq(ioc->pcidev->irq, mpt_interrupt,
+ IRQF_SHARED, ioc->name, ioc);
+ if (rc < 0) {
+ printk(MYIOC_s_ERR_FMT "Unable to allocate "
+ "interrupt %d!\n", ioc->name, ioc->pcidev->irq);
+- if (mpt_msi_enable)
++ if (ioc->msi_enable)
+ pci_disable_msi(ioc->pcidev);
+ return -EBUSY;
+ }
+@@ -2173,7 +2180,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
+ /*
+ * Initalize link list for inactive raid volumes.
+ */
+- init_MUTEX(&ioc->raid_data.inactive_list_mutex);
++ mutex_init(&ioc->raid_data.inactive_list_mutex);
+ INIT_LIST_HEAD(&ioc->raid_data.inactive_list);
+
+ if (ioc->bus_type == SAS) {
+@@ -2261,7 +2268,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
+ out:
+ if ((ret != 0) && irq_allocated) {
+ free_irq(ioc->pci_irq, ioc);
+- if (mpt_msi_enable)
++ if (ioc->msi_enable)
+ pci_disable_msi(ioc->pcidev);
+ }
+ return ret;
+@@ -2443,7 +2450,7 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc)
+
+ if (ioc->pci_irq != -1) {
+ free_irq(ioc->pci_irq, ioc);
+- if (mpt_msi_enable)
++ if (ioc->msi_enable)
+ pci_disable_msi(ioc->pcidev);
+ ioc->pci_irq = -1;
+ }
+@@ -5159,13 +5166,13 @@ mpt_inactive_raid_list_free(MPT_ADAPTER *ioc)
+ if (list_empty(&ioc->raid_data.inactive_list))
+ return;
+
+- down(&ioc->raid_data.inactive_list_mutex);
++ mutex_lock(&ioc->raid_data.inactive_list_mutex);
+ list_for_each_entry_safe(component_info, pNext,
+ &ioc->raid_data.inactive_list, list) {
+ list_del(&component_info->list);
+ kfree(component_info);
+ }
+- up(&ioc->raid_data.inactive_list_mutex);
++ mutex_unlock(&ioc->raid_data.inactive_list_mutex);
+ }
+
+ /**
+@@ -5224,7 +5231,7 @@ mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id)
+ if (!handle_inactive_volumes)
+ goto out;
+
+- down(&ioc->raid_data.inactive_list_mutex);
++ mutex_lock(&ioc->raid_data.inactive_list_mutex);
+ for (i = 0; i < buffer->NumPhysDisks; i++) {
+ if(mpt_raid_phys_disk_pg0(ioc,
+ buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
+@@ -5244,7 +5251,7 @@ mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id)
+ list_add_tail(&component_info->list,
+ &ioc->raid_data.inactive_list);
+ }
+- up(&ioc->raid_data.inactive_list_mutex);
++ mutex_unlock(&ioc->raid_data.inactive_list_mutex);
+
+ out:
+ if (buffer)
+diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
+index caadc68..a8f6174 100644
+--- a/drivers/message/fusion/mptbase.h
++++ b/drivers/message/fusion/mptbase.h
+@@ -51,6 +51,7 @@
+
+ #include <linux/kernel.h>
+ #include <linux/pci.h>
++#include <linux/mutex.h>
+
+ #include "lsi/mpi_type.h"
+ #include "lsi/mpi.h" /* Fusion MPI(nterface) basic defs */
+@@ -531,7 +532,7 @@ struct inactive_raid_component_info {
+ typedef struct _RaidCfgData {
+ IOCPage2_t *pIocPg2; /* table of Raid Volumes */
+ IOCPage3_t *pIocPg3; /* table of physical disks */
+- struct semaphore inactive_list_mutex;
++ struct mutex inactive_list_mutex;
+ struct list_head inactive_list; /* link list for physical
+ disk that belong in
+ inactive volumes */
+@@ -630,6 +631,7 @@ typedef struct _MPT_ADAPTER
+ int mtrr_reg;
+ struct pci_dev *pcidev; /* struct pci_dev pointer */
+ int bars; /* bitmask of BAR's that must be configured */
++ int msi_enable;
+ u8 __iomem *memmap; /* mmap address */
+ struct Scsi_Host *sh; /* Scsi Host pointer */
+ SpiCfgData spi_data; /* Scsi config. data */
+@@ -693,7 +695,6 @@ typedef struct _MPT_ADAPTER
+ struct mutex sas_discovery_mutex;
+ u8 sas_discovery_runtime;
+ u8 sas_discovery_ignore_events;
+- u16 handle;
+ int sas_index; /* index refrencing */
+ MPT_SAS_MGMT sas_mgmt;
+ struct work_struct sas_persist_task;
+diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
+index 78734e2..4684807 100644
+--- a/drivers/message/fusion/mptsas.c
++++ b/drivers/message/fusion/mptsas.c
+@@ -230,6 +230,20 @@ static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
+ return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
+ }
+
++static struct mptsas_portinfo *
++mptsas_get_hba_portinfo(MPT_ADAPTER *ioc)
++{
++ struct list_head *head = &ioc->sas_topology;
++ struct mptsas_portinfo *pi = NULL;
++
++ /* always the first entry on sas_topology list */
++
++ if (!list_empty(head))
++ pi = list_entry(head->next, struct mptsas_portinfo, list);
++
++ return pi;
++}
++
+ /*
+ * mptsas_find_portinfo_by_handle
+ *
+@@ -1290,7 +1304,7 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
+ struct mptsas_portinfo *port_info;
+
+ mutex_lock(&ioc->sas_topology_mutex);
+- port_info = mptsas_find_portinfo_by_handle(ioc, ioc->handle);
++ port_info = mptsas_get_hba_portinfo(ioc);
+ if (port_info && port_info->phy_info)
+ sas_address =
+ port_info->phy_info[0].phy->identify.sas_address;
+@@ -2028,8 +2042,7 @@ static int mptsas_probe_one_phy(struct device *dev,
+ int i;
+
+ mutex_lock(&ioc->sas_topology_mutex);
+- port_info = mptsas_find_portinfo_by_handle(ioc,
+- ioc->handle);
++ port_info = mptsas_get_hba_portinfo(ioc);
+ mutex_unlock(&ioc->sas_topology_mutex);
+
+ for (i = 0; i < port_info->num_phys; i++)
+@@ -2099,8 +2112,7 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
+
+ mptsas_sas_io_unit_pg1(ioc);
+ mutex_lock(&ioc->sas_topology_mutex);
+- ioc->handle = hba->phy_info[0].handle;
+- port_info = mptsas_find_portinfo_by_handle(ioc, ioc->handle);
++ port_info = mptsas_get_hba_portinfo(ioc);
+ if (!port_info) {
+ port_info = hba;
+ list_add_tail(&port_info->list, &ioc->sas_topology);
+diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
+index c207bda..b109bd8 100644
+--- a/drivers/message/fusion/mptscsih.c
++++ b/drivers/message/fusion/mptscsih.c
+@@ -2304,14 +2304,14 @@ mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id)
+ if (list_empty(&ioc->raid_data.inactive_list))
+ goto out;
+
+- down(&ioc->raid_data.inactive_list_mutex);
++ mutex_lock(&ioc->raid_data.inactive_list_mutex);
+ list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
+ list) {
+ if ((component_info->d.PhysDiskID == id) &&
+ (component_info->d.PhysDiskBus == channel))
+ rc = 1;
+ }
+- up(&ioc->raid_data.inactive_list_mutex);
++ mutex_unlock(&ioc->raid_data.inactive_list_mutex);
+
+ out:
+ return rc;
+@@ -2341,14 +2341,14 @@ mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
+ if (list_empty(&ioc->raid_data.inactive_list))
+ goto out;
+
+- down(&ioc->raid_data.inactive_list_mutex);
++ mutex_lock(&ioc->raid_data.inactive_list_mutex);
+ list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
+ list) {
+ if ((component_info->d.PhysDiskID == id) &&
+ (component_info->d.PhysDiskBus == channel))
+ rc = component_info->d.PhysDiskNum;
+ }
+- up(&ioc->raid_data.inactive_list_mutex);
++ mutex_unlock(&ioc->raid_data.inactive_list_mutex);
+
+ out:
+ return rc;
+@@ -3300,9 +3300,10 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
+ }
+
+ static ssize_t
+-mptscsih_version_fw_show(struct class_device *cdev, char *buf)
++mptscsih_version_fw_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *host = class_to_shost(cdev);
++ struct Scsi_Host *host = class_to_shost(dev);
+ MPT_SCSI_HOST *hd = shost_priv(host);
+ MPT_ADAPTER *ioc = hd->ioc;
+
+@@ -3312,12 +3313,13 @@ mptscsih_version_fw_show(struct class_device *cdev, char *buf)
+ (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
+ ioc->facts.FWVersion.Word & 0x000000FF);
+ }
+-static CLASS_DEVICE_ATTR(version_fw, S_IRUGO, mptscsih_version_fw_show, NULL);
++static DEVICE_ATTR(version_fw, S_IRUGO, mptscsih_version_fw_show, NULL);
+
+ static ssize_t
+-mptscsih_version_bios_show(struct class_device *cdev, char *buf)
++mptscsih_version_bios_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *host = class_to_shost(cdev);
++ struct Scsi_Host *host = class_to_shost(dev);
+ MPT_SCSI_HOST *hd = shost_priv(host);
+ MPT_ADAPTER *ioc = hd->ioc;
+
+@@ -3327,129 +3329,141 @@ mptscsih_version_bios_show(struct class_device *cdev, char *buf)
+ (ioc->biosVersion & 0x0000FF00) >> 8,
+ ioc->biosVersion & 0x000000FF);
+ }
+-static CLASS_DEVICE_ATTR(version_bios, S_IRUGO, mptscsih_version_bios_show, NULL);
++static DEVICE_ATTR(version_bios, S_IRUGO, mptscsih_version_bios_show, NULL);
+
+ static ssize_t
+-mptscsih_version_mpi_show(struct class_device *cdev, char *buf)
++mptscsih_version_mpi_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *host = class_to_shost(cdev);
++ struct Scsi_Host *host = class_to_shost(dev);
+ MPT_SCSI_HOST *hd = shost_priv(host);
+ MPT_ADAPTER *ioc = hd->ioc;
+
+ return snprintf(buf, PAGE_SIZE, "%03x\n", ioc->facts.MsgVersion);
+ }
+-static CLASS_DEVICE_ATTR(version_mpi, S_IRUGO, mptscsih_version_mpi_show, NULL);
++static DEVICE_ATTR(version_mpi, S_IRUGO, mptscsih_version_mpi_show, NULL);
+
+ static ssize_t
+-mptscsih_version_product_show(struct class_device *cdev, char *buf)
++mptscsih_version_product_show(struct device *dev,
++ struct device_attribute *attr,
++char *buf)
+ {
+- struct Scsi_Host *host = class_to_shost(cdev);
++ struct Scsi_Host *host = class_to_shost(dev);
+ MPT_SCSI_HOST *hd = shost_priv(host);
+ MPT_ADAPTER *ioc = hd->ioc;
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", ioc->prod_name);
+ }
+-static CLASS_DEVICE_ATTR(version_product, S_IRUGO,
++static DEVICE_ATTR(version_product, S_IRUGO,
+ mptscsih_version_product_show, NULL);
+
+ static ssize_t
+-mptscsih_version_nvdata_persistent_show(struct class_device *cdev, char *buf)
++mptscsih_version_nvdata_persistent_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *host = class_to_shost(cdev);
++ struct Scsi_Host *host = class_to_shost(dev);
+ MPT_SCSI_HOST *hd = shost_priv(host);
+ MPT_ADAPTER *ioc = hd->ioc;
+
+ return snprintf(buf, PAGE_SIZE, "%02xh\n",
+ ioc->nvdata_version_persistent);
+ }
+-static CLASS_DEVICE_ATTR(version_nvdata_persistent, S_IRUGO,
++static DEVICE_ATTR(version_nvdata_persistent, S_IRUGO,
+ mptscsih_version_nvdata_persistent_show, NULL);
+
+ static ssize_t
+-mptscsih_version_nvdata_default_show(struct class_device *cdev, char *buf)
++mptscsih_version_nvdata_default_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct Scsi_Host *host = class_to_shost(cdev);
++ struct Scsi_Host *host = class_to_shost(dev);
+ MPT_SCSI_HOST *hd = shost_priv(host);
+ MPT_ADAPTER *ioc = hd->ioc;
+
+ return snprintf(buf, PAGE_SIZE, "%02xh\n",ioc->nvdata_version_default);
+ }
+-static CLASS_DEVICE_ATTR(version_nvdata_default, S_IRUGO,
++static DEVICE_ATTR(version_nvdata_default, S_IRUGO,
+ mptscsih_version_nvdata_default_show, NULL);
+
+ static ssize_t
+-mptscsih_board_name_show(struct class_device *cdev, char *buf)
++mptscsih_board_name_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *host = class_to_shost(cdev);
++ struct Scsi_Host *host = class_to_shost(dev);
+ MPT_SCSI_HOST *hd = shost_priv(host);
+ MPT_ADAPTER *ioc = hd->ioc;
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_name);
+ }
+-static CLASS_DEVICE_ATTR(board_name, S_IRUGO, mptscsih_board_name_show, NULL);
++static DEVICE_ATTR(board_name, S_IRUGO, mptscsih_board_name_show, NULL);
+
+ static ssize_t
+-mptscsih_board_assembly_show(struct class_device *cdev, char *buf)
++mptscsih_board_assembly_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct Scsi_Host *host = class_to_shost(cdev);
++ struct Scsi_Host *host = class_to_shost(dev);
+ MPT_SCSI_HOST *hd = shost_priv(host);
+ MPT_ADAPTER *ioc = hd->ioc;
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_assembly);
+ }
+-static CLASS_DEVICE_ATTR(board_assembly, S_IRUGO,
++static DEVICE_ATTR(board_assembly, S_IRUGO,
+ mptscsih_board_assembly_show, NULL);
+
+ static ssize_t
+-mptscsih_board_tracer_show(struct class_device *cdev, char *buf)
++mptscsih_board_tracer_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *host = class_to_shost(cdev);
++ struct Scsi_Host *host = class_to_shost(dev);
+ MPT_SCSI_HOST *hd = shost_priv(host);
+ MPT_ADAPTER *ioc = hd->ioc;
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_tracer);
+ }
+-static CLASS_DEVICE_ATTR(board_tracer, S_IRUGO,
++static DEVICE_ATTR(board_tracer, S_IRUGO,
+ mptscsih_board_tracer_show, NULL);
+
+ static ssize_t
+-mptscsih_io_delay_show(struct class_device *cdev, char *buf)
++mptscsih_io_delay_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *host = class_to_shost(cdev);
++ struct Scsi_Host *host = class_to_shost(dev);
+ MPT_SCSI_HOST *hd = shost_priv(host);
+ MPT_ADAPTER *ioc = hd->ioc;
+
+ return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay);
+ }
+-static CLASS_DEVICE_ATTR(io_delay, S_IRUGO,
++static DEVICE_ATTR(io_delay, S_IRUGO,
+ mptscsih_io_delay_show, NULL);
+
+ static ssize_t
+-mptscsih_device_delay_show(struct class_device *cdev, char *buf)
++mptscsih_device_delay_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *host = class_to_shost(cdev);
++ struct Scsi_Host *host = class_to_shost(dev);
+ MPT_SCSI_HOST *hd = shost_priv(host);
+ MPT_ADAPTER *ioc = hd->ioc;
+
+ return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay);
+ }
+-static CLASS_DEVICE_ATTR(device_delay, S_IRUGO,
++static DEVICE_ATTR(device_delay, S_IRUGO,
+ mptscsih_device_delay_show, NULL);
+
+ static ssize_t
+-mptscsih_debug_level_show(struct class_device *cdev, char *buf)
++mptscsih_debug_level_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *host = class_to_shost(cdev);
++ struct Scsi_Host *host = class_to_shost(dev);
+ MPT_SCSI_HOST *hd = shost_priv(host);
+ MPT_ADAPTER *ioc = hd->ioc;
+
+ return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->debug_level);
+ }
+ static ssize_t
+-mptscsih_debug_level_store(struct class_device *cdev, const char *buf,
+- size_t count)
++mptscsih_debug_level_store(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+- struct Scsi_Host *host = class_to_shost(cdev);
++ struct Scsi_Host *host = class_to_shost(dev);
+ MPT_SCSI_HOST *hd = shost_priv(host);
+ MPT_ADAPTER *ioc = hd->ioc;
+ int val = 0;
+@@ -3462,22 +3476,22 @@ mptscsih_debug_level_store(struct class_device *cdev, const char *buf,
+ ioc->name, ioc->debug_level);
+ return strlen(buf);
+ }
+-static CLASS_DEVICE_ATTR(debug_level, S_IRUGO | S_IWUSR,
+- mptscsih_debug_level_show, mptscsih_debug_level_store);
+-
+-struct class_device_attribute *mptscsih_host_attrs[] = {
+- &class_device_attr_version_fw,
+- &class_device_attr_version_bios,
+- &class_device_attr_version_mpi,
+- &class_device_attr_version_product,
+- &class_device_attr_version_nvdata_persistent,
+- &class_device_attr_version_nvdata_default,
+- &class_device_attr_board_name,
+- &class_device_attr_board_assembly,
+- &class_device_attr_board_tracer,
+- &class_device_attr_io_delay,
+- &class_device_attr_device_delay,
+- &class_device_attr_debug_level,
++static DEVICE_ATTR(debug_level, S_IRUGO | S_IWUSR,
++ mptscsih_debug_level_show, mptscsih_debug_level_store);
++
++struct device_attribute *mptscsih_host_attrs[] = {
++ &dev_attr_version_fw,
++ &dev_attr_version_bios,
++ &dev_attr_version_mpi,
++ &dev_attr_version_product,
++ &dev_attr_version_nvdata_persistent,
++ &dev_attr_version_nvdata_default,
++ &dev_attr_board_name,
++ &dev_attr_board_assembly,
++ &dev_attr_board_tracer,
++ &dev_attr_io_delay,
++ &dev_attr_device_delay,
++ &dev_attr_debug_level,
+ NULL,
+ };
+ EXPORT_SYMBOL(mptscsih_host_attrs);
+diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
+index d289e97..7ea7da0 100644
+--- a/drivers/message/fusion/mptscsih.h
++++ b/drivers/message/fusion/mptscsih.h
+@@ -129,4 +129,4 @@ extern void mptscsih_timer_expired(unsigned long data);
+ extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
+ extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id);
+ extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id);
+-extern struct class_device_attribute *mptscsih_host_attrs[];
++extern struct device_attribute *mptscsih_host_attrs[];
+diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
+index 0c886c8..2566479 100644
+--- a/drivers/mfd/Kconfig
++++ b/drivers/mfd/Kconfig
+@@ -22,6 +22,22 @@ config MFD_ASIC3
+ This driver supports the ASIC3 multifunction chip found on many
+ PDAs (mainly iPAQ and HTC based ones)
+
++config HTC_EGPIO
++ bool "HTC EGPIO support"
++ depends on GENERIC_HARDIRQS && HAVE_GPIO_LIB
++ help
++ This driver supports the CPLD egpio chip present on
++ several HTC phones. It provides basic support for input
++ pins, output pins, and irqs.
++
++config HTC_PASIC3
++ tristate "HTC PASIC3 LED/DS1WM chip support"
++ help
++ This core driver provides register access for the LED/DS1WM
++ chips labeled "AIC2" and "AIC3", found on HTC Blueangel and
++ HTC Magician devices, respectively. Actual functionality is
++ handled by the leds-pasic3 and ds1wm drivers.
++
+ endmenu
+
+ menu "Multimedia Capabilities Port drivers"
+diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
+index 521cd5c..eef4e26 100644
+--- a/drivers/mfd/Makefile
++++ b/drivers/mfd/Makefile
+@@ -5,6 +5,9 @@
+ obj-$(CONFIG_MFD_SM501) += sm501.o
+ obj-$(CONFIG_MFD_ASIC3) += asic3.o
+
++obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o
++obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
++
+ obj-$(CONFIG_MCP) += mcp-core.o
+ obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o
+ obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o
+diff --git a/drivers/mfd/htc-egpio.c b/drivers/mfd/htc-egpio.c
+new file mode 100644
+index 0000000..8872cc0
+--- /dev/null
++++ b/drivers/mfd/htc-egpio.c
+@@ -0,0 +1,440 @@
++/*
++ * Support for the GPIO/IRQ expander chips present on several HTC phones.
++ * These are implemented in CPLD chips present on the board.
++ *
++ * Copyright (c) 2007 Kevin O'Connor <kevin at koconnor.net>
++ * Copyright (c) 2007 Philipp Zabel <philipp.zabel at gmail.com>
++ *
++ * This file may be distributed under the terms of the GNU GPL license.
++ */
++
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <linux/io.h>
++#include <linux/spinlock.h>
++#include <linux/platform_device.h>
++#include <linux/module.h>
++#include <linux/mfd/htc-egpio.h>
++
++struct egpio_chip {
++ int reg_start;
++ int cached_values;
++ unsigned long is_out;
++ struct device *dev;
++ struct gpio_chip chip;
++};
++
++struct egpio_info {
++ spinlock_t lock;
++
++ /* iomem info */
++ void __iomem *base_addr;
++ int bus_shift; /* byte shift */
++ int reg_shift; /* bit shift */
++ int reg_mask;
++
++ /* irq info */
++ int ack_register;
++ int ack_write;
++ u16 irqs_enabled;
++ uint irq_start;
++ int nirqs;
++ uint chained_irq;
++
++ /* egpio info */
++ struct egpio_chip *chip;
++ int nchips;
++};
++
++static inline void egpio_writew(u16 value, struct egpio_info *ei, int reg)
++{
++ writew(value, ei->base_addr + (reg << ei->bus_shift));
++}
++
++static inline u16 egpio_readw(struct egpio_info *ei, int reg)
++{
++ return readw(ei->base_addr + (reg << ei->bus_shift));
++}
++
++/*
++ * IRQs
++ */
++
++static inline void ack_irqs(struct egpio_info *ei)
++{
++ egpio_writew(ei->ack_write, ei, ei->ack_register);
++ pr_debug("EGPIO ack - write %x to base+%x\n",
++ ei->ack_write, ei->ack_register << ei->bus_shift);
++}
++
++static void egpio_ack(unsigned int irq)
++{
++}
++
++/* There does not appear to be a way to proactively mask interrupts
++ * on the egpio chip itself. So, we simply ignore interrupts that
++ * aren't desired. */
++static void egpio_mask(unsigned int irq)
++{
++ struct egpio_info *ei = get_irq_chip_data(irq);
++ ei->irqs_enabled &= ~(1 << (irq - ei->irq_start));
++ pr_debug("EGPIO mask %d %04x\n", irq, ei->irqs_enabled);
++}
++static void egpio_unmask(unsigned int irq)
++{
++ struct egpio_info *ei = get_irq_chip_data(irq);
++ ei->irqs_enabled |= 1 << (irq - ei->irq_start);
++ pr_debug("EGPIO unmask %d %04x\n", irq, ei->irqs_enabled);
++}
++
++static struct irq_chip egpio_muxed_chip = {
++ .name = "htc-egpio",
++ .ack = egpio_ack,
++ .mask = egpio_mask,
++ .unmask = egpio_unmask,
++};
++
++static void egpio_handler(unsigned int irq, struct irq_desc *desc)
++{
++ struct egpio_info *ei = get_irq_data(irq);
++ int irqpin;
++
++ /* Read current pins. */
++ unsigned long readval = egpio_readw(ei, ei->ack_register);
++ pr_debug("IRQ reg: %x\n", (unsigned int)readval);
++ /* Ack/unmask interrupts. */
++ ack_irqs(ei);
++ /* Process all set pins. */
++ readval &= ei->irqs_enabled;
++ for_each_bit(irqpin, &readval, ei->nirqs) {
++ /* Run irq handler */
++ pr_debug("got IRQ %d\n", irqpin);
++ irq = ei->irq_start + irqpin;
++ desc = &irq_desc[irq];
++ desc->handle_irq(irq, desc);
++ }
++}
++
++int htc_egpio_get_wakeup_irq(struct device *dev)
++{
++ struct egpio_info *ei = dev_get_drvdata(dev);
++
++ /* Read current pins. */
++ u16 readval = egpio_readw(ei, ei->ack_register);
++ /* Ack/unmask interrupts. */
++ ack_irqs(ei);
++ /* Return first set pin. */
++ readval &= ei->irqs_enabled;
++ return ei->irq_start + ffs(readval) - 1;
++}
++EXPORT_SYMBOL(htc_egpio_get_wakeup_irq);
++
++static inline int egpio_pos(struct egpio_info *ei, int bit)
++{
++ return bit >> ei->reg_shift;
++}
++
++static inline int egpio_bit(struct egpio_info *ei, int bit)
++{
++ return 1 << (bit & ((1 << ei->reg_shift)-1));
++}
++
++/*
++ * Input pins
++ */
++
++static int egpio_get(struct gpio_chip *chip, unsigned offset)
++{
++ struct egpio_chip *egpio;
++ struct egpio_info *ei;
++ unsigned bit;
++ int reg;
++ int value;
++
++ pr_debug("egpio_get_value(%d)\n", chip->base + offset);
++
++ egpio = container_of(chip, struct egpio_chip, chip);
++ ei = dev_get_drvdata(egpio->dev);
++ bit = egpio_bit(ei, offset);
++ reg = egpio->reg_start + egpio_pos(ei, offset);
++
++ value = egpio_readw(ei, reg);
++ pr_debug("readw(%p + %x) = %x\n",
++ ei->base_addr, reg << ei->bus_shift, value);
++ return value & bit;
++}
++
++static int egpio_direction_input(struct gpio_chip *chip, unsigned offset)
++{
++ struct egpio_chip *egpio;
++
++ egpio = container_of(chip, struct egpio_chip, chip);
++ return test_bit(offset, &egpio->is_out) ? -EINVAL : 0;
++}
++
++
++/*
++ * Output pins
++ */
++
++static void egpio_set(struct gpio_chip *chip, unsigned offset, int value)
++{
++ unsigned long flag;
++ struct egpio_chip *egpio;
++ struct egpio_info *ei;
++ unsigned bit;
++ int pos;
++ int reg;
++ int shift;
++
++ pr_debug("egpio_set(%s, %d(%d), %d)\n",
++ chip->label, offset, offset+chip->base, value);
++
++ egpio = container_of(chip, struct egpio_chip, chip);
++ ei = dev_get_drvdata(egpio->dev);
++ bit = egpio_bit(ei, offset);
++ pos = egpio_pos(ei, offset);
++ reg = egpio->reg_start + pos;
++ shift = pos << ei->reg_shift;
++
++ pr_debug("egpio %s: reg %d = 0x%04x\n", value ? "set" : "clear",
++ reg, (egpio->cached_values >> shift) & ei->reg_mask);
++
++ spin_lock_irqsave(&ei->lock, flag);
++ if (value)
++ egpio->cached_values |= (1 << offset);
++ else
++ egpio->cached_values &= ~(1 << offset);
++ egpio_writew((egpio->cached_values >> shift) & ei->reg_mask, ei, reg);
++ spin_unlock_irqrestore(&ei->lock, flag);
++}
++
++static int egpio_direction_output(struct gpio_chip *chip,
++ unsigned offset, int value)
++{
++ struct egpio_chip *egpio;
++
++ egpio = container_of(chip, struct egpio_chip, chip);
++ if (test_bit(offset, &egpio->is_out)) {
++ egpio_set(chip, offset, value);
++ return 0;
++ } else {
++ return -EINVAL;
++ }
++}
++
++static void egpio_write_cache(struct egpio_info *ei)
++{
++ int i;
++ struct egpio_chip *egpio;
++ int shift;
++
++ for (i = 0; i < ei->nchips; i++) {
++ egpio = &(ei->chip[i]);
++ if (!egpio->is_out)
++ continue;
++
++ for (shift = 0; shift < egpio->chip.ngpio;
++ shift += (1<<ei->reg_shift)) {
++
++ int reg = egpio->reg_start + egpio_pos(ei, shift);
++
++ if (!((egpio->is_out >> shift) & ei->reg_mask))
++ continue;
++
++ pr_debug("EGPIO: setting %x to %x, was %x\n", reg,
++ (egpio->cached_values >> shift) & ei->reg_mask,
++ egpio_readw(ei, reg));
++
++ egpio_writew((egpio->cached_values >> shift)
++ & ei->reg_mask, ei, reg);
++ }
++ }
++}
++
++
++/*
++ * Setup
++ */
++
++static int __init egpio_probe(struct platform_device *pdev)
++{
++ struct htc_egpio_platform_data *pdata = pdev->dev.platform_data;
++ struct resource *res;
++ struct egpio_info *ei;
++ struct gpio_chip *chip;
++ unsigned int irq, irq_end;
++ int i;
++ int ret;
++
++ /* Initialize ei data structure. */
++ ei = kzalloc(sizeof(*ei), GFP_KERNEL);
++ if (!ei)
++ return -ENOMEM;
++
++ spin_lock_init(&ei->lock);
++
++ /* Find chained irq */
++ ret = -EINVAL;
++ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
++ if (res)
++ ei->chained_irq = res->start;
++
++ /* Map egpio chip into virtual address space. */
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res)
++ goto fail;
++ ei->base_addr = ioremap_nocache(res->start, res->end - res->start);
++ if (!ei->base_addr)
++ goto fail;
++ pr_debug("EGPIO phys=%08x virt=%p\n", res->start, ei->base_addr);
++
++ if ((pdata->bus_width != 16) && (pdata->bus_width != 32))
++ goto fail;
++ ei->bus_shift = fls(pdata->bus_width - 1) - 3;
++ pr_debug("bus_shift = %d\n", ei->bus_shift);
++
++ if ((pdata->reg_width != 8) && (pdata->reg_width != 16))
++ goto fail;
++ ei->reg_shift = fls(pdata->reg_width - 1);
++ pr_debug("reg_shift = %d\n", ei->reg_shift);
++
++ ei->reg_mask = (1 << pdata->reg_width) - 1;
++
++ platform_set_drvdata(pdev, ei);
++
++ ei->nchips = pdata->num_chips;
++ ei->chip = kzalloc(sizeof(struct egpio_chip) * ei->nchips, GFP_KERNEL);
++ if (!ei) {
++ ret = -ENOMEM;
++ goto fail;
++ }
++ for (i = 0; i < ei->nchips; i++) {
++ ei->chip[i].reg_start = pdata->chip[i].reg_start;
++ ei->chip[i].cached_values = pdata->chip[i].initial_values;
++ ei->chip[i].is_out = pdata->chip[i].direction;
++ ei->chip[i].dev = &(pdev->dev);
++ chip = &(ei->chip[i].chip);
++ chip->label = "htc-egpio";
++ chip->get = egpio_get;
++ chip->set = egpio_set;
++ chip->direction_input = egpio_direction_input;
++ chip->direction_output = egpio_direction_output;
++ chip->base = pdata->chip[i].gpio_base;
++ chip->ngpio = pdata->chip[i].num_gpios;
++
++ gpiochip_add(chip);
++ }
++
++ /* Set initial pin values */
++ egpio_write_cache(ei);
++
++ ei->irq_start = pdata->irq_base;
++ ei->nirqs = pdata->num_irqs;
++ ei->ack_register = pdata->ack_register;
++
++ if (ei->chained_irq) {
++ /* Setup irq handlers */
++ ei->ack_write = 0xFFFF;
++ if (pdata->invert_acks)
++ ei->ack_write = 0;
++ irq_end = ei->irq_start + ei->nirqs;
++ for (irq = ei->irq_start; irq < irq_end; irq++) {
++ set_irq_chip(irq, &egpio_muxed_chip);
++ set_irq_chip_data(irq, ei);
++ set_irq_handler(irq, handle_simple_irq);
++ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
++ }
++ set_irq_type(ei->chained_irq, IRQ_TYPE_EDGE_RISING);
++ set_irq_data(ei->chained_irq, ei);
++ set_irq_chained_handler(ei->chained_irq, egpio_handler);
++ ack_irqs(ei);
++
++ device_init_wakeup(&pdev->dev, 1);
++ }
++
++ return 0;
++
++fail:
++ printk(KERN_ERR "EGPIO failed to setup\n");
++ kfree(ei);
++ return ret;
++}
++
++static int __exit egpio_remove(struct platform_device *pdev)
++{
++ struct egpio_info *ei = platform_get_drvdata(pdev);
++ unsigned int irq, irq_end;
++
++ if (ei->chained_irq) {
++ irq_end = ei->irq_start + ei->nirqs;
++ for (irq = ei->irq_start; irq < irq_end; irq++) {
++ set_irq_chip(irq, NULL);
++ set_irq_handler(irq, NULL);
++ set_irq_flags(irq, 0);
++ }
++ set_irq_chained_handler(ei->chained_irq, NULL);
++ device_init_wakeup(&pdev->dev, 0);
++ }
++ iounmap(ei->base_addr);
++ kfree(ei->chip);
++ kfree(ei);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int egpio_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ struct egpio_info *ei = platform_get_drvdata(pdev);
++
++ if (ei->chained_irq && device_may_wakeup(&pdev->dev))
++ enable_irq_wake(ei->chained_irq);
++ return 0;
++}
++
++static int egpio_resume(struct platform_device *pdev)
++{
++ struct egpio_info *ei = platform_get_drvdata(pdev);
++
++ if (ei->chained_irq && device_may_wakeup(&pdev->dev))
++ disable_irq_wake(ei->chained_irq);
++
++ /* Update registers from the cache, in case
++ the CPLD was powered off during suspend */
++ egpio_write_cache(ei);
++ return 0;
++}
++#else
++#define egpio_suspend NULL
++#define egpio_resume NULL
++#endif
++
++
++static struct platform_driver egpio_driver = {
++ .driver = {
++ .name = "htc-egpio",
++ },
++ .remove = __exit_p(egpio_remove),
++ .suspend = egpio_suspend,
++ .resume = egpio_resume,
++};
++
++static int __init egpio_init(void)
++{
++ return platform_driver_probe(&egpio_driver, egpio_probe);
++}
++
++static void __exit egpio_exit(void)
++{
++ platform_driver_unregister(&egpio_driver);
++}
++
++/* start early for dependencies */
++subsys_initcall(egpio_init);
++module_exit(egpio_exit)
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Kevin O'Connor <kevin at koconnor.net>");
+diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c
+new file mode 100644
+index 0000000..4edc120
+--- /dev/null
++++ b/drivers/mfd/htc-pasic3.c
+@@ -0,0 +1,262 @@
++/*
++ * Core driver for HTC PASIC3 LED/DS1WM chip.
++ *
++ * Copyright (C) 2006 Philipp Zabel <philipp.zabel at gmail.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++
++#include <linux/ds1wm.h>
++#include <linux/gpio.h>
++#include <linux/io.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/mfd/htc-pasic3.h>
++
++struct pasic3_data {
++ void __iomem *mapping;
++ unsigned int bus_shift;
++ struct platform_device *ds1wm_pdev;
++ struct platform_device *led_pdev;
++};
++
++#define REG_ADDR 5
++#define REG_DATA 6
++
++#define READ_MODE 0x80
++
++/*
++ * write to a secondary register on the PASIC3
++ */
++void pasic3_write_register(struct device *dev, u32 reg, u8 val)
++{
++ struct pasic3_data *asic = dev->driver_data;
++ int bus_shift = asic->bus_shift;
++ void __iomem *addr = asic->mapping + (REG_ADDR << bus_shift);
++ void __iomem *data = asic->mapping + (REG_DATA << bus_shift);
++
++ __raw_writeb(~READ_MODE & reg, addr);
++ __raw_writeb(val, data);
++}
++EXPORT_SYMBOL(pasic3_write_register); /* for leds-pasic3 */
++
++/*
++ * read from a secondary register on the PASIC3
++ */
++u8 pasic3_read_register(struct device *dev, u32 reg)
++{
++ struct pasic3_data *asic = dev->driver_data;
++ int bus_shift = asic->bus_shift;
++ void __iomem *addr = asic->mapping + (REG_ADDR << bus_shift);
++ void __iomem *data = asic->mapping + (REG_DATA << bus_shift);
++
++ __raw_writeb(READ_MODE | reg, addr);
++ return __raw_readb(data);
++}
++EXPORT_SYMBOL(pasic3_read_register); /* for leds-pasic3 */
++
++/*
++ * LEDs
++ */
++
++static int led_device_add(struct device *pasic3_dev,
++ const struct pasic3_leds_machinfo *pdata)
++{
++ struct pasic3_data *asic = pasic3_dev->driver_data;
++ struct platform_device *pdev;
++ int ret;
++
++ pdev = platform_device_alloc("pasic3-led", -1);
++ if (!pdev) {
++ dev_dbg(pasic3_dev, "failed to allocate LED platform device\n");
++ return -ENOMEM;
++ }
++
++ ret = platform_device_add_data(pdev, pdata,
++ sizeof(struct pasic3_leds_machinfo));
++ if (ret < 0) {
++ dev_dbg(pasic3_dev, "failed to add LED platform data\n");
++ goto exit_pdev_put;
++ }
++
++ pdev->dev.parent = pasic3_dev;
++ ret = platform_device_add(pdev);
++ if (ret < 0) {
++ dev_dbg(pasic3_dev, "failed to add LED platform device\n");
++ goto exit_pdev_put;
++ }
++
++ asic->led_pdev = pdev;
++ return 0;
++
++exit_pdev_put:
++ platform_device_put(pdev);
++ return ret;
++}
++
++/*
++ * DS1WM
++ */
++
++static void ds1wm_enable(struct platform_device *pdev)
++{
++ struct device *dev = pdev->dev.parent;
++ int c;
++
++ c = pasic3_read_register(dev, 0x28);
++ pasic3_write_register(dev, 0x28, c & 0x7f);
++
++ dev_dbg(dev, "DS1WM OWM_EN low (active) %02x\n", c & 0x7f);
++}
++
++static void ds1wm_disable(struct platform_device *pdev)
++{
++ struct device *dev = pdev->dev.parent;
++ int c;
++
++ c = pasic3_read_register(dev, 0x28);
++ pasic3_write_register(dev, 0x28, c | 0x80);
++
++ dev_dbg(dev, "DS1WM OWM_EN high (inactive) %02x\n", c | 0x80);
++}
++
++static struct ds1wm_platform_data ds1wm_pdata = {
++ .bus_shift = 2,
++ .enable = ds1wm_enable,
++ .disable = ds1wm_disable,
++};
++
++static int ds1wm_device_add(struct device *pasic3_dev, int bus_shift)
++{
++ struct pasic3_data *asic = pasic3_dev->driver_data;
++ struct platform_device *pdev;
++ int ret;
++
++ pdev = platform_device_alloc("ds1wm", -1);
++ if (!pdev) {
++ dev_dbg(pasic3_dev, "failed to allocate DS1WM platform device\n");
++ return -ENOMEM;
++ }
++
++ ret = platform_device_add_resources(pdev, pdev->resource,
++ pdev->num_resources);
++ if (ret < 0) {
++ dev_dbg(pasic3_dev, "failed to add DS1WM resources\n");
++ goto exit_pdev_put;
++ }
++
++ ds1wm_pdata.bus_shift = asic->bus_shift;
++ ret = platform_device_add_data(pdev, &ds1wm_pdata,
++ sizeof(struct ds1wm_platform_data));
++ if (ret < 0) {
++ dev_dbg(pasic3_dev, "failed to add DS1WM platform data\n");
++ goto exit_pdev_put;
++ }
++
++ pdev->dev.parent = pasic3_dev;
++ ret = platform_device_add(pdev);
++ if (ret < 0) {
++ dev_dbg(pasic3_dev, "failed to add DS1WM platform device\n");
++ goto exit_pdev_put;
++ }
++
++ asic->ds1wm_pdev = pdev;
++ return 0;
++
++exit_pdev_put:
++ platform_device_put(pdev);
++ return ret;
++}
++
++static int __init pasic3_probe(struct platform_device *pdev)
++{
++ struct pasic3_platform_data *pdata = pdev->dev.platform_data;
++ struct device *dev = &pdev->dev;
++ struct pasic3_data *asic;
++ struct resource *r;
++ int ret;
++
++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!r)
++ return -ENXIO;
++
++ if (!request_mem_region(r->start, r->end - r->start + 1, "pasic3"))
++ return -EBUSY;
++
++ asic = kzalloc(sizeof(struct pasic3_data), GFP_KERNEL);
++ if (!asic)
++ return -ENOMEM;
++
++ platform_set_drvdata(pdev, asic);
++
++ if (pdata && pdata->bus_shift)
++ asic->bus_shift = pdata->bus_shift;
++ else
++ asic->bus_shift = 2;
++
++ asic->mapping = ioremap(r->start, r->end - r->start + 1);
++ if (!asic->mapping) {
++ dev_err(dev, "couldn't ioremap PASIC3\n");
++ kfree(asic);
++ return -ENOMEM;
++ }
++
++ ret = ds1wm_device_add(dev, asic->bus_shift);
++ if (ret < 0)
++ dev_warn(dev, "failed to register DS1WM\n");
++
++ if (pdata->led_pdata) {
++ ret = led_device_add(dev, pdata->led_pdata);
++ if (ret < 0)
++ dev_warn(dev, "failed to register LED device\n");
++ }
++
++ return 0;
++}
++
++static int pasic3_remove(struct platform_device *pdev)
++{
++ struct pasic3_data *asic = platform_get_drvdata(pdev);
++ struct resource *r;
++
++ if (asic->led_pdev)
++ platform_device_unregister(asic->led_pdev);
++ if (asic->ds1wm_pdev)
++ platform_device_unregister(asic->ds1wm_pdev);
++
++ iounmap(asic->mapping);
++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ release_mem_region(r->start, r->end - r->start + 1);
++ kfree(asic);
++ return 0;
++}
++
++static struct platform_driver pasic3_driver = {
++ .driver = {
++ .name = "pasic3",
++ },
++ .remove = pasic3_remove,
++};
++
++static int __init pasic3_base_init(void)
++{
++ return platform_driver_probe(&pasic3_driver, pasic3_probe);
++}
++
++static void __exit pasic3_base_exit(void)
++{
++ platform_driver_unregister(&pasic3_driver);
++}
++
++module_init(pasic3_base_init);
++module_exit(pasic3_base_exit);
++
++MODULE_AUTHOR("Philipp Zabel <philipp.zabel at gmail.com>");
++MODULE_DESCRIPTION("Core driver for HTC PASIC3");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c
+index fdbaa77..5e85948 100644
+--- a/drivers/mfd/ucb1x00-ts.c
++++ b/drivers/mfd/ucb1x00-ts.c
+@@ -32,7 +32,6 @@
+ #include <linux/kthread.h>
+
+ #include <asm/dma.h>
+-#include <asm/semaphore.h>
+ #include <asm/arch/collie.h>
+ #include <asm/mach-types.h>
+
+diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
+index 962817e..297a48f 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -22,6 +22,39 @@ config ATMEL_PWM
+ purposes including software controlled power-efficent backlights
+ on LCD displays, motor control, and waveform generation.
+
++config ATMEL_TCLIB
++ bool "Atmel AT32/AT91 Timer/Counter Library"
++ depends on (AVR32 || ARCH_AT91)
++ help
++ Select this if you want a library to allocate the Timer/Counter
++ blocks found on many Atmel processors. This facilitates using
++ these blocks by different drivers despite processor differences.
++
++config ATMEL_TCB_CLKSRC
++ bool "TC Block Clocksource"
++ depends on ATMEL_TCLIB && GENERIC_TIME
++ default y
++ help
++ Select this to get a high precision clocksource based on a
++ TC block with a 5+ MHz base clock rate. Two timer channels
++ are combined to make a single 32-bit timer.
++
++ When GENERIC_CLOCKEVENTS is defined, the third timer channel
++ may be used as a clock event device supporting oneshot mode
++ (delays of up to two seconds) based on the 32 KiHz clock.
++
++config ATMEL_TCB_CLKSRC_BLOCK
++ int
++ depends on ATMEL_TCB_CLKSRC
++ prompt "TC Block" if ARCH_AT91RM9200 || ARCH_AT91SAM9260 || CPU_AT32AP700X
++ default 0
++ range 0 1
++ help
++ Some chips provide more than one TC block, so you have the
++ choice of which one to use for the clock framework. The other
++ TC can be used for other purposes, such as PWM generation and
++ interval timing.
++
+ config IBM_ASM
+ tristate "Device driver for IBM RSA service processor"
+ depends on X86 && PCI && INPUT && EXPERIMENTAL
+@@ -327,4 +360,16 @@ config ENCLOSURE_SERVICES
+ driver (SCSI/ATA) which supports enclosures
+ or a SCSI enclosure device (SES) to use these services.
+
++config SGI_XP
++ tristate "Support communication between SGI SSIs"
++ depends on IA64_GENERIC || IA64_SGI_SN2
++ select IA64_UNCACHED_ALLOCATOR if IA64_GENERIC || IA64_SGI_SN2
++ select GENERIC_ALLOCATOR if IA64_GENERIC || IA64_SGI_SN2
++ ---help---
++ An SGI machine can be divided into multiple Single System
++ Images which act independently of each other and have
++ hardware based memory protection from the others. Enabling
++ this feature will allow for direct communication between SSIs
++ based on a network adapter and DMA messaging.
++
+ endif # MISC_DEVICES
+diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
+index 3b12f5d..5914da4 100644
+--- a/drivers/misc/Makefile
++++ b/drivers/misc/Makefile
+@@ -10,6 +10,7 @@ obj-$(CONFIG_ACER_WMI) += acer-wmi.o
+ obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o
+ obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o
+ obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o
++obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o
+ obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o
+ obj-$(CONFIG_LKDTM) += lkdtm.o
+ obj-$(CONFIG_TIFM_CORE) += tifm_core.o
+@@ -22,3 +23,5 @@ obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o
+ obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
+ obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o
+ obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
++obj-$(CONFIG_KGDB_TESTS) += kgdbts.o
++obj-$(CONFIG_SGI_XP) += sgi-xp/
+diff --git a/drivers/misc/atmel_tclib.c b/drivers/misc/atmel_tclib.c
+new file mode 100644
+index 0000000..05dc8a3
+--- /dev/null
++++ b/drivers/misc/atmel_tclib.c
+@@ -0,0 +1,161 @@
++#include <linux/atmel_tc.h>
++#include <linux/clk.h>
++#include <linux/err.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/ioport.h>
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++
++/* Number of bytes to reserve for the iomem resource */
++#define ATMEL_TC_IOMEM_SIZE 256
++
++
++/*
++ * This is a thin library to solve the problem of how to portably allocate
++ * one of the TC blocks. For simplicity, it doesn't currently expect to
++ * share individual timers between different drivers.
++ */
++
++#if defined(CONFIG_AVR32)
++/* AVR32 has these divide PBB */
++const u8 atmel_tc_divisors[5] = { 0, 4, 8, 16, 32, };
++EXPORT_SYMBOL(atmel_tc_divisors);
++
++#elif defined(CONFIG_ARCH_AT91)
++/* AT91 has these divide MCK */
++const u8 atmel_tc_divisors[5] = { 2, 8, 32, 128, 0, };
++EXPORT_SYMBOL(atmel_tc_divisors);
++
++#endif
++
++static DEFINE_SPINLOCK(tc_list_lock);
++static LIST_HEAD(tc_list);
++
++/**
++ * atmel_tc_alloc - allocate a specified TC block
++ * @block: which block to allocate
++ * @name: name to be associated with the iomem resource
++ *
++ * Caller allocates a block. If it is available, a pointer to a
++ * pre-initialized struct atmel_tc is returned. The caller can access
++ * the registers directly through the "regs" field.
++ */
++struct atmel_tc *atmel_tc_alloc(unsigned block, const char *name)
++{
++ struct atmel_tc *tc;
++ struct platform_device *pdev = NULL;
++ struct resource *r;
++
++ spin_lock(&tc_list_lock);
++ list_for_each_entry(tc, &tc_list, node) {
++ if (tc->pdev->id == block) {
++ pdev = tc->pdev;
++ break;
++ }
++ }
++
++ if (!pdev || tc->iomem)
++ goto fail;
++
++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ r = request_mem_region(r->start, ATMEL_TC_IOMEM_SIZE, name);
++ if (!r)
++ goto fail;
++
++ tc->regs = ioremap(r->start, ATMEL_TC_IOMEM_SIZE);
++ if (!tc->regs)
++ goto fail_ioremap;
++
++ tc->iomem = r;
++
++out:
++ spin_unlock(&tc_list_lock);
++ return tc;
++
++fail_ioremap:
++ release_resource(r);
++fail:
++ tc = NULL;
++ goto out;
++}
++EXPORT_SYMBOL_GPL(atmel_tc_alloc);
++
++/**
++ * atmel_tc_free - release a specified TC block
++ * @tc: Timer/counter block that was returned by atmel_tc_alloc()
++ *
++ * This reverses the effect of atmel_tc_alloc(), unmapping the I/O
++ * registers, invalidating the resource returned by that routine and
++ * making the TC available to other drivers.
++ */
++void atmel_tc_free(struct atmel_tc *tc)
++{
++ spin_lock(&tc_list_lock);
++ if (tc->regs) {
++ iounmap(tc->regs);
++ release_resource(tc->iomem);
++ tc->regs = NULL;
++ tc->iomem = NULL;
++ }
++ spin_unlock(&tc_list_lock);
++}
++EXPORT_SYMBOL_GPL(atmel_tc_free);
++
++static int __init tc_probe(struct platform_device *pdev)
++{
++ struct atmel_tc *tc;
++ struct clk *clk;
++ int irq;
++
++ if (!platform_get_resource(pdev, IORESOURCE_MEM, 0))
++ return -EINVAL;
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0)
++ return -EINVAL;
++
++ tc = kzalloc(sizeof(struct atmel_tc), GFP_KERNEL);
++ if (!tc)
++ return -ENOMEM;
++
++ tc->pdev = pdev;
++
++ clk = clk_get(&pdev->dev, "t0_clk");
++ if (IS_ERR(clk)) {
++ kfree(tc);
++ return -EINVAL;
++ }
++
++ tc->clk[0] = clk;
++ tc->clk[1] = clk_get(&pdev->dev, "t1_clk");
++ if (IS_ERR(tc->clk[1]))
++ tc->clk[1] = clk;
++ tc->clk[2] = clk_get(&pdev->dev, "t2_clk");
++ if (IS_ERR(tc->clk[2]))
++ tc->clk[2] = clk;
++
++ tc->irq[0] = irq;
++ tc->irq[1] = platform_get_irq(pdev, 1);
++ if (tc->irq[1] < 0)
++ tc->irq[1] = irq;
++ tc->irq[2] = platform_get_irq(pdev, 2);
++ if (tc->irq[2] < 0)
++ tc->irq[2] = irq;
++
++ spin_lock(&tc_list_lock);
++ list_add_tail(&tc->node, &tc_list);
++ spin_unlock(&tc_list_lock);
++
++ return 0;
++}
++
++static struct platform_driver tc_driver = {
++ .driver.name = "atmel_tcb",
++};
++
++static int __init tc_init(void)
++{
++ return platform_driver_probe(&tc_driver, tc_probe);
++}
++arch_initcall(tc_init);
+diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c
+index 6fcb0e9..fafb57f 100644
+--- a/drivers/misc/enclosure.c
++++ b/drivers/misc/enclosure.c
+@@ -40,16 +40,16 @@ static struct class enclosure_component_class;
+ * Looks through the list of registered enclosures to see
+ * if it can find a match for a device. Returns NULL if no
+ * enclosure is found. Obtains a reference to the enclosure class
+- * device which must be released with class_device_put().
++ * device which must be released with device_put().
+ */
+ struct enclosure_device *enclosure_find(struct device *dev)
+ {
+- struct enclosure_device *edev = NULL;
++ struct enclosure_device *edev;
+
+ mutex_lock(&container_list_lock);
+ list_for_each_entry(edev, &container_list, node) {
+- if (edev->cdev.dev == dev) {
+- class_device_get(&edev->cdev);
++ if (edev->edev.parent == dev) {
++ get_device(&edev->edev);
+ mutex_unlock(&container_list_lock);
+ return edev;
+ }
+@@ -117,11 +117,11 @@ enclosure_register(struct device *dev, const char *name, int components,
+
+ edev->components = components;
+
+- edev->cdev.class = &enclosure_class;
+- edev->cdev.dev = get_device(dev);
++ edev->edev.class = &enclosure_class;
++ edev->edev.parent = get_device(dev);
+ edev->cb = cb;
+- snprintf(edev->cdev.class_id, BUS_ID_SIZE, "%s", name);
+- err = class_device_register(&edev->cdev);
++ snprintf(edev->edev.bus_id, BUS_ID_SIZE, "%s", name);
++ err = device_register(&edev->edev);
+ if (err)
+ goto err;
+
+@@ -135,7 +135,7 @@ enclosure_register(struct device *dev, const char *name, int components,
+ return edev;
+
+ err:
+- put_device(edev->cdev.dev);
++ put_device(edev->edev.parent);
+ kfree(edev);
+ return ERR_PTR(err);
+ }
+@@ -158,27 +158,28 @@ void enclosure_unregister(struct enclosure_device *edev)
+
+ for (i = 0; i < edev->components; i++)
+ if (edev->component[i].number != -1)
+- class_device_unregister(&edev->component[i].cdev);
++ device_unregister(&edev->component[i].cdev);
+
+ /* prevent any callbacks into service user */
+ edev->cb = &enclosure_null_callbacks;
+- class_device_unregister(&edev->cdev);
++ device_unregister(&edev->edev);
+ }
+ EXPORT_SYMBOL_GPL(enclosure_unregister);
+
+-static void enclosure_release(struct class_device *cdev)
++static void enclosure_release(struct device *cdev)
+ {
+ struct enclosure_device *edev = to_enclosure_device(cdev);
+
+- put_device(cdev->dev);
++ put_device(cdev->parent);
+ kfree(edev);
+ }
+
+-static void enclosure_component_release(struct class_device *cdev)
++static void enclosure_component_release(struct device *dev)
+ {
+- if (cdev->dev)
+- put_device(cdev->dev);
+- class_device_put(cdev->parent);
++ struct enclosure_component *cdev = to_enclosure_component(dev);
++
++ put_device(cdev->dev);
++ put_device(dev->parent);
+ }
+
+ /**
+@@ -201,7 +202,7 @@ enclosure_component_register(struct enclosure_device *edev,
+ const char *name)
+ {
+ struct enclosure_component *ecomp;
+- struct class_device *cdev;
++ struct device *cdev;
+ int err;
+
+ if (number >= edev->components)
+@@ -215,14 +216,14 @@ enclosure_component_register(struct enclosure_device *edev,
+ ecomp->type = type;
+ ecomp->number = number;
+ cdev = &ecomp->cdev;
+- cdev->parent = class_device_get(&edev->cdev);
++ cdev->parent = get_device(&edev->edev);
+ cdev->class = &enclosure_component_class;
+ if (name)
+- snprintf(cdev->class_id, BUS_ID_SIZE, "%s", name);
++ snprintf(cdev->bus_id, BUS_ID_SIZE, "%s", name);
+ else
+- snprintf(cdev->class_id, BUS_ID_SIZE, "%u", number);
++ snprintf(cdev->bus_id, BUS_ID_SIZE, "%u", number);
+
+- err = class_device_register(cdev);
++ err = device_register(cdev);
+ if (err)
+ ERR_PTR(err);
+
+@@ -247,18 +248,17 @@ EXPORT_SYMBOL_GPL(enclosure_component_register);
+ int enclosure_add_device(struct enclosure_device *edev, int component,
+ struct device *dev)
+ {
+- struct class_device *cdev;
++ struct enclosure_component *cdev;
+
+ if (!edev || component >= edev->components)
+ return -EINVAL;
+
+- cdev = &edev->component[component].cdev;
++ cdev = &edev->component[component];
+
+- class_device_del(cdev);
+- if (cdev->dev)
+- put_device(cdev->dev);
++ device_del(&cdev->cdev);
++ put_device(cdev->dev);
+ cdev->dev = get_device(dev);
+- return class_device_add(cdev);
++ return device_add(&cdev->cdev);
+ }
+ EXPORT_SYMBOL_GPL(enclosure_add_device);
+
+@@ -272,18 +272,17 @@ EXPORT_SYMBOL_GPL(enclosure_add_device);
+ */
+ int enclosure_remove_device(struct enclosure_device *edev, int component)
+ {
+- struct class_device *cdev;
++ struct enclosure_component *cdev;
+
+ if (!edev || component >= edev->components)
+ return -EINVAL;
+
+- cdev = &edev->component[component].cdev;
++ cdev = &edev->component[component];
+
+- class_device_del(cdev);
+- if (cdev->dev)
+- put_device(cdev->dev);
++ device_del(&cdev->cdev);
++ put_device(cdev->dev);
+ cdev->dev = NULL;
+- return class_device_add(cdev);
++ return device_add(&cdev->cdev);
+ }
+ EXPORT_SYMBOL_GPL(enclosure_remove_device);
+
+@@ -291,14 +290,16 @@ EXPORT_SYMBOL_GPL(enclosure_remove_device);
+ * sysfs pieces below
+ */
+
+-static ssize_t enclosure_show_components(struct class_device *cdev, char *buf)
++static ssize_t enclosure_show_components(struct device *cdev,
++ struct device_attribute *attr,
++ char *buf)
+ {
+ struct enclosure_device *edev = to_enclosure_device(cdev);
+
+ return snprintf(buf, 40, "%d\n", edev->components);
+ }
+
+-static struct class_device_attribute enclosure_attrs[] = {
++static struct device_attribute enclosure_attrs[] = {
+ __ATTR(components, S_IRUGO, enclosure_show_components, NULL),
+ __ATTR_NULL
+ };
+@@ -306,8 +307,8 @@ static struct class_device_attribute enclosure_attrs[] = {
+ static struct class enclosure_class = {
+ .name = "enclosure",
+ .owner = THIS_MODULE,
+- .release = enclosure_release,
+- .class_dev_attrs = enclosure_attrs,
++ .dev_release = enclosure_release,
++ .dev_attrs = enclosure_attrs,
+ };
+
+ static const char *const enclosure_status [] = {
+@@ -326,7 +327,8 @@ static const char *const enclosure_type [] = {
+ [ENCLOSURE_COMPONENT_ARRAY_DEVICE] = "array device",
+ };
+
+-static ssize_t get_component_fault(struct class_device *cdev, char *buf)
++static ssize_t get_component_fault(struct device *cdev,
++ struct device_attribute *attr, char *buf)
+ {
+ struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+ struct enclosure_component *ecomp = to_enclosure_component(cdev);
+@@ -336,8 +338,9 @@ static ssize_t get_component_fault(struct class_device *cdev, char *buf)
+ return snprintf(buf, 40, "%d\n", ecomp->fault);
+ }
+
+-static ssize_t set_component_fault(struct class_device *cdev, const char *buf,
+- size_t count)
++static ssize_t set_component_fault(struct device *cdev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+ struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+ struct enclosure_component *ecomp = to_enclosure_component(cdev);
+@@ -348,7 +351,8 @@ static ssize_t set_component_fault(struct class_device *cdev, const char *buf,
+ return count;
+ }
+
+-static ssize_t get_component_status(struct class_device *cdev, char *buf)
++static ssize_t get_component_status(struct device *cdev,
++ struct device_attribute *attr,char *buf)
+ {
+ struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+ struct enclosure_component *ecomp = to_enclosure_component(cdev);
+@@ -358,8 +362,9 @@ static ssize_t get_component_status(struct class_device *cdev, char *buf)
+ return snprintf(buf, 40, "%s\n", enclosure_status[ecomp->status]);
+ }
+
+-static ssize_t set_component_status(struct class_device *cdev, const char *buf,
+- size_t count)
++static ssize_t set_component_status(struct device *cdev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+ struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+ struct enclosure_component *ecomp = to_enclosure_component(cdev);
+@@ -380,7 +385,8 @@ static ssize_t set_component_status(struct class_device *cdev, const char *buf,
+ return -EINVAL;
+ }
+
+-static ssize_t get_component_active(struct class_device *cdev, char *buf)
++static ssize_t get_component_active(struct device *cdev,
++ struct device_attribute *attr, char *buf)
+ {
+ struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+ struct enclosure_component *ecomp = to_enclosure_component(cdev);
+@@ -390,8 +396,9 @@ static ssize_t get_component_active(struct class_device *cdev, char *buf)
+ return snprintf(buf, 40, "%d\n", ecomp->active);
+ }
+
+-static ssize_t set_component_active(struct class_device *cdev, const char *buf,
+- size_t count)
++static ssize_t set_component_active(struct device *cdev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+ struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+ struct enclosure_component *ecomp = to_enclosure_component(cdev);
+@@ -402,7 +409,8 @@ static ssize_t set_component_active(struct class_device *cdev, const char *buf,
+ return count;
+ }
+
+-static ssize_t get_component_locate(struct class_device *cdev, char *buf)
++static ssize_t get_component_locate(struct device *cdev,
++ struct device_attribute *attr, char *buf)
+ {
+ struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+ struct enclosure_component *ecomp = to_enclosure_component(cdev);
+@@ -412,8 +420,9 @@ static ssize_t get_component_locate(struct class_device *cdev, char *buf)
+ return snprintf(buf, 40, "%d\n", ecomp->locate);
+ }
+
+-static ssize_t set_component_locate(struct class_device *cdev, const char *buf,
+- size_t count)
++static ssize_t set_component_locate(struct device *cdev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+ struct enclosure_device *edev = to_enclosure_device(cdev->parent);
+ struct enclosure_component *ecomp = to_enclosure_component(cdev);
+@@ -424,7 +433,8 @@ static ssize_t set_component_locate(struct class_device *cdev, const char *buf,
+ return count;
+ }
+
+-static ssize_t get_component_type(struct class_device *cdev, char *buf)
++static ssize_t get_component_type(struct device *cdev,
++ struct device_attribute *attr, char *buf)
+ {
+ struct enclosure_component *ecomp = to_enclosure_component(cdev);
+
+@@ -432,7 +442,7 @@ static ssize_t get_component_type(struct class_device *cdev, char *buf)
+ }
+
+
+-static struct class_device_attribute enclosure_component_attrs[] = {
++static struct device_attribute enclosure_component_attrs[] = {
+ __ATTR(fault, S_IRUGO | S_IWUSR, get_component_fault,
+ set_component_fault),
+ __ATTR(status, S_IRUGO | S_IWUSR, get_component_status,
+@@ -448,8 +458,8 @@ static struct class_device_attribute enclosure_component_attrs[] = {
+ static struct class enclosure_component_class = {
+ .name = "enclosure_component",
+ .owner = THIS_MODULE,
+- .class_dev_attrs = enclosure_component_attrs,
+- .release = enclosure_component_release,
++ .dev_attrs = enclosure_component_attrs,
++ .dev_release = enclosure_component_release,
+ };
+
+ static int __init enclosure_init(void)
+diff --git a/drivers/misc/intel_menlow.c b/drivers/misc/intel_menlow.c
+index de16e88..0c0bb30 100644
+--- a/drivers/misc/intel_menlow.c
++++ b/drivers/misc/intel_menlow.c
+@@ -213,7 +213,7 @@ static int intel_menlow_memory_remove(struct acpi_device *device, int type)
+ return 0;
+ }
+
+-const static struct acpi_device_id intel_menlow_memory_ids[] = {
++static const struct acpi_device_id intel_menlow_memory_ids[] = {
+ {"INT0002", 0},
+ {"", 0},
+ };
+diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c
+new file mode 100644
+index 0000000..6d6286c
+--- /dev/null
++++ b/drivers/misc/kgdbts.c
+@@ -0,0 +1,1090 @@
++/*
++ * kgdbts is a test suite for kgdb for the sole purpose of validating
++ * that key pieces of the kgdb internals are working properly such as
++ * HW/SW breakpoints, single stepping, and NMI.
++ *
++ * Created by: Jason Wessel <jason.wessel at windriver.com>
++ *
++ * Copyright (c) 2008 Wind River Systems, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
++ * See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++/* Information about the kgdb test suite.
++ * -------------------------------------
++ *
++ * The kgdb test suite is designed as a KGDB I/O module which
++ * simulates the communications that a debugger would have with kgdb.
++ * The tests are broken up in to a line by line and referenced here as
++ * a "get" which is kgdb requesting input and "put" which is kgdb
++ * sending a response.
++ *
++ * The kgdb suite can be invoked from the kernel command line
++ * arguments system or executed dynamically at run time. The test
++ * suite uses the variable "kgdbts" to obtain the information about
++ * which tests to run and to configure the verbosity level. The
++ * following are the various characters you can use with the kgdbts=
++ * line:
++ *
++ * When using the "kgdbts=" you only choose one of the following core
++ * test types:
++ * A = Run all the core tests silently
++ * V1 = Run all the core tests with minimal output
++ * V2 = Run all the core tests in debug mode
++ *
++ * You can also specify optional tests:
++ * N## = Go to sleep with interrupts of for ## seconds
++ * to test the HW NMI watchdog
++ * F## = Break at do_fork for ## iterations
++ * S## = Break at sys_open for ## iterations
++ *
++ * NOTE: that the do_fork and sys_open tests are mutually exclusive.
++ *
++ * To invoke the kgdb test suite from boot you use a kernel start
++ * argument as follows:
++ * kgdbts=V1 kgdbwait
++ * Or if you wanted to perform the NMI test for 6 seconds and do_fork
++ * test for 100 forks, you could use:
++ * kgdbts=V1N6F100 kgdbwait
++ *
++ * The test suite can also be invoked at run time with:
++ * echo kgdbts=V1N6F100 > /sys/module/kgdbts/parameters/kgdbts
++ * Or as another example:
++ * echo kgdbts=V2 > /sys/module/kgdbts/parameters/kgdbts
++ *
++ * When developing a new kgdb arch specific implementation or
++ * using these tests for the purpose of regression testing,
++ * several invocations are required.
++ *
++ * 1) Boot with the test suite enabled by using the kernel arguments
++ * "kgdbts=V1F100 kgdbwait"
++ * ## If kgdb arch specific implementation has NMI use
++ * "kgdbts=V1N6F100
++ *
++ * 2) After the system boot run the basic test.
++ * echo kgdbts=V1 > /sys/module/kgdbts/parameters/kgdbts
++ *
++ * 3) Run the concurrency tests. It is best to use n+1
++ * while loops where n is the number of cpus you have
++ * in your system. The example below uses only two
++ * loops.
++ *
++ * ## This tests break points on sys_open
++ * while [ 1 ] ; do find / > /dev/null 2>&1 ; done &
++ * while [ 1 ] ; do find / > /dev/null 2>&1 ; done &
++ * echo kgdbts=V1S10000 > /sys/module/kgdbts/parameters/kgdbts
++ * fg # and hit control-c
++ * fg # and hit control-c
++ * ## This tests break points on do_fork
++ * while [ 1 ] ; do date > /dev/null ; done &
++ * while [ 1 ] ; do date > /dev/null ; done &
++ * echo kgdbts=V1F1000 > /sys/module/kgdbts/parameters/kgdbts
++ * fg # and hit control-c
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/kgdb.h>
++#include <linux/ctype.h>
++#include <linux/uaccess.h>
++#include <linux/syscalls.h>
++#include <linux/nmi.h>
++#include <linux/delay.h>
++#include <linux/kthread.h>
++#include <linux/delay.h>
++
++#define v1printk(a...) do { \
++ if (verbose) \
++ printk(KERN_INFO a); \
++ } while (0)
++#define v2printk(a...) do { \
++ if (verbose > 1) \
++ printk(KERN_INFO a); \
++ touch_nmi_watchdog(); \
++ } while (0)
++#define eprintk(a...) do { \
++ printk(KERN_ERR a); \
++ WARN_ON(1); \
++ } while (0)
++#define MAX_CONFIG_LEN 40
++
++static const char hexchars[] = "0123456789abcdef";
++static struct kgdb_io kgdbts_io_ops;
++static char get_buf[BUFMAX];
++static int get_buf_cnt;
++static char put_buf[BUFMAX];
++static int put_buf_cnt;
++static char scratch_buf[BUFMAX];
++static int verbose;
++static int repeat_test;
++static int test_complete;
++static int send_ack;
++static int final_ack;
++static int hw_break_val;
++static int hw_break_val2;
++#if defined(CONFIG_ARM) || defined(CONFIG_MIPS)
++static int arch_needs_sstep_emulation = 1;
++#else
++static int arch_needs_sstep_emulation;
++#endif
++static unsigned long sstep_addr;
++static int sstep_state;
++
++/* Storage for the registers, in GDB format. */
++static unsigned long kgdbts_gdb_regs[(NUMREGBYTES +
++ sizeof(unsigned long) - 1) /
++ sizeof(unsigned long)];
++static struct pt_regs kgdbts_regs;
++
++/* -1 = init not run yet, 0 = unconfigured, 1 = configured. */
++static int configured = -1;
++
++#ifdef CONFIG_KGDB_TESTS_BOOT_STRING
++static char config[MAX_CONFIG_LEN] = CONFIG_KGDB_TESTS_BOOT_STRING;
++#else
++static char config[MAX_CONFIG_LEN];
++#endif
++static struct kparam_string kps = {
++ .string = config,
++ .maxlen = MAX_CONFIG_LEN,
++};
++
++static void fill_get_buf(char *buf);
++
++struct test_struct {
++ char *get;
++ char *put;
++ void (*get_handler)(char *);
++ int (*put_handler)(char *, char *);
++};
++
++struct test_state {
++ char *name;
++ struct test_struct *tst;
++ int idx;
++ int (*run_test) (int, int);
++ int (*validate_put) (char *);
++};
++
++static struct test_state ts;
++
++static int kgdbts_unreg_thread(void *ptr)
++{
++ /* Wait until the tests are complete and then ungresiter the I/O
++ * driver.
++ */
++ while (!final_ack)
++ msleep_interruptible(1500);
++
++ if (configured)
++ kgdb_unregister_io_module(&kgdbts_io_ops);
++ configured = 0;
++
++ return 0;
++}
++
++/* This is noinline such that it can be used for a single location to
++ * place a breakpoint
++ */
++static noinline void kgdbts_break_test(void)
++{
++ v2printk("kgdbts: breakpoint complete\n");
++}
++
++/* Lookup symbol info in the kernel */
++static unsigned long lookup_addr(char *arg)
++{
++ unsigned long addr = 0;
++
++ if (!strcmp(arg, "kgdbts_break_test"))
++ addr = (unsigned long)kgdbts_break_test;
++ else if (!strcmp(arg, "sys_open"))
++ addr = (unsigned long)sys_open;
++ else if (!strcmp(arg, "do_fork"))
++ addr = (unsigned long)do_fork;
++ else if (!strcmp(arg, "hw_break_val"))
++ addr = (unsigned long)&hw_break_val;
++ return addr;
++}
++
++static void break_helper(char *bp_type, char *arg, unsigned long vaddr)
++{
++ unsigned long addr;
++
++ if (arg)
++ addr = lookup_addr(arg);
++ else
++ addr = vaddr;
++
++ sprintf(scratch_buf, "%s,%lx,%i", bp_type, addr,
++ BREAK_INSTR_SIZE);
++ fill_get_buf(scratch_buf);
++}
++
++static void sw_break(char *arg)
++{
++ break_helper("Z0", arg, 0);
++}
++
++static void sw_rem_break(char *arg)
++{
++ break_helper("z0", arg, 0);
++}
++
++static void hw_break(char *arg)
++{
++ break_helper("Z1", arg, 0);
++}
++
++static void hw_rem_break(char *arg)
++{
++ break_helper("z1", arg, 0);
++}
++
++static void hw_write_break(char *arg)
++{
++ break_helper("Z2", arg, 0);
++}
++
++static void hw_rem_write_break(char *arg)
++{
++ break_helper("z2", arg, 0);
++}
++
++static void hw_access_break(char *arg)
++{
++ break_helper("Z4", arg, 0);
++}
++
++static void hw_rem_access_break(char *arg)
++{
++ break_helper("z4", arg, 0);
++}
++
++static void hw_break_val_access(void)
++{
++ hw_break_val2 = hw_break_val;
++}
++
++static void hw_break_val_write(void)
++{
++ hw_break_val++;
++}
++
++static int check_and_rewind_pc(char *put_str, char *arg)
++{
++ unsigned long addr = lookup_addr(arg);
++ int offset = 0;
++
++ kgdb_hex2mem(&put_str[1], (char *)kgdbts_gdb_regs,
++ NUMREGBYTES);
++ gdb_regs_to_pt_regs(kgdbts_gdb_regs, &kgdbts_regs);
++ v2printk("Stopped at IP: %lx\n", instruction_pointer(&kgdbts_regs));
++#ifdef CONFIG_X86
++ /* On x86 a breakpoint stop requires it to be decremented */
++ if (addr + 1 == kgdbts_regs.ip)
++ offset = -1;
++#endif
++ if (strcmp(arg, "silent") &&
++ instruction_pointer(&kgdbts_regs) + offset != addr) {
++ eprintk("kgdbts: BP mismatch %lx expected %lx\n",
++ instruction_pointer(&kgdbts_regs) + offset, addr);
++ return 1;
++ }
++#ifdef CONFIG_X86
++ /* On x86 adjust the instruction pointer if needed */
++ kgdbts_regs.ip += offset;
++#endif
++ return 0;
++}
++
++static int check_single_step(char *put_str, char *arg)
++{
++ unsigned long addr = lookup_addr(arg);
++ /*
++ * From an arch indepent point of view the instruction pointer
++ * should be on a different instruction
++ */
++ kgdb_hex2mem(&put_str[1], (char *)kgdbts_gdb_regs,
++ NUMREGBYTES);
++ gdb_regs_to_pt_regs(kgdbts_gdb_regs, &kgdbts_regs);
++ v2printk("Singlestep stopped at IP: %lx\n",
++ instruction_pointer(&kgdbts_regs));
++ if (instruction_pointer(&kgdbts_regs) == addr) {
++ eprintk("kgdbts: SingleStep failed at %lx\n",
++ instruction_pointer(&kgdbts_regs));
++ return 1;
++ }
++
++ return 0;
++}
++
++static void write_regs(char *arg)
++{
++ memset(scratch_buf, 0, sizeof(scratch_buf));
++ scratch_buf[0] = 'G';
++ pt_regs_to_gdb_regs(kgdbts_gdb_regs, &kgdbts_regs);
++ kgdb_mem2hex((char *)kgdbts_gdb_regs, &scratch_buf[1], NUMREGBYTES);
++ fill_get_buf(scratch_buf);
++}
++
++static void skip_back_repeat_test(char *arg)
++{
++ int go_back = simple_strtol(arg, NULL, 10);
++
++ repeat_test--;
++ if (repeat_test <= 0)
++ ts.idx++;
++ else
++ ts.idx -= go_back;
++ fill_get_buf(ts.tst[ts.idx].get);
++}
++
++static int got_break(char *put_str, char *arg)
++{
++ test_complete = 1;
++ if (!strncmp(put_str+1, arg, 2)) {
++ if (!strncmp(arg, "T0", 2))
++ test_complete = 2;
++ return 0;
++ }
++ return 1;
++}
++
++static void emul_sstep_get(char *arg)
++{
++ if (!arch_needs_sstep_emulation) {
++ fill_get_buf(arg);
++ return;
++ }
++ switch (sstep_state) {
++ case 0:
++ v2printk("Emulate single step\n");
++ /* Start by looking at the current PC */
++ fill_get_buf("g");
++ break;
++ case 1:
++ /* set breakpoint */
++ break_helper("Z0", 0, sstep_addr);
++ break;
++ case 2:
++ /* Continue */
++ fill_get_buf("c");
++ break;
++ case 3:
++ /* Clear breakpoint */
++ break_helper("z0", 0, sstep_addr);
++ break;
++ default:
++ eprintk("kgdbts: ERROR failed sstep get emulation\n");
++ }
++ sstep_state++;
++}
++
++static int emul_sstep_put(char *put_str, char *arg)
++{
++ if (!arch_needs_sstep_emulation) {
++ if (!strncmp(put_str+1, arg, 2))
++ return 0;
++ return 1;
++ }
++ switch (sstep_state) {
++ case 1:
++ /* validate the "g" packet to get the IP */
++ kgdb_hex2mem(&put_str[1], (char *)kgdbts_gdb_regs,
++ NUMREGBYTES);
++ gdb_regs_to_pt_regs(kgdbts_gdb_regs, &kgdbts_regs);
++ v2printk("Stopped at IP: %lx\n",
++ instruction_pointer(&kgdbts_regs));
++ /* Want to stop at IP + break instruction size by default */
++ sstep_addr = instruction_pointer(&kgdbts_regs) +
++ BREAK_INSTR_SIZE;
++ break;
++ case 2:
++ if (strncmp(put_str, "$OK", 3)) {
++ eprintk("kgdbts: failed sstep break set\n");
++ return 1;
++ }
++ break;
++ case 3:
++ if (strncmp(put_str, "$T0", 3)) {
++ eprintk("kgdbts: failed continue sstep\n");
++ return 1;
++ }
++ break;
++ case 4:
++ if (strncmp(put_str, "$OK", 3)) {
++ eprintk("kgdbts: failed sstep break unset\n");
++ return 1;
++ }
++ /* Single step is complete so continue on! */
++ sstep_state = 0;
++ return 0;
++ default:
++ eprintk("kgdbts: ERROR failed sstep put emulation\n");
++ }
++
++ /* Continue on the same test line until emulation is complete */
++ ts.idx--;
++ return 0;
++}
++
++static int final_ack_set(char *put_str, char *arg)
++{
++ if (strncmp(put_str+1, arg, 2))
++ return 1;
++ final_ack = 1;
++ return 0;
++}
++/*
++ * Test to plant a breakpoint and detach, which should clear out the
++ * breakpoint and restore the original instruction.
++ */
++static struct test_struct plant_and_detach_test[] = {
++ { "?", "S0*" }, /* Clear break points */
++ { "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */
++ { "D", "OK" }, /* Detach */
++ { "", "" },
++};
++
++/*
++ * Simple test to write in a software breakpoint, check for the
++ * correct stop location and detach.
++ */
++static struct test_struct sw_breakpoint_test[] = {
++ { "?", "S0*" }, /* Clear break points */
++ { "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */
++ { "c", "T0*", }, /* Continue */
++ { "g", "kgdbts_break_test", 0, check_and_rewind_pc },
++ { "write", "OK", write_regs },
++ { "kgdbts_break_test", "OK", sw_rem_break }, /*remove breakpoint */
++ { "D", "OK" }, /* Detach */
++ { "D", "OK", 0, got_break }, /* If the test worked we made it here */
++ { "", "" },
++};
++
++/*
++ * Test a known bad memory read location to test the fault handler and
++ * read bytes 1-8 at the bad address
++ */
++static struct test_struct bad_read_test[] = {
++ { "?", "S0*" }, /* Clear break points */
++ { "m0,1", "E*" }, /* read 1 byte at address 1 */
++ { "m0,2", "E*" }, /* read 1 byte at address 2 */
++ { "m0,3", "E*" }, /* read 1 byte at address 3 */
++ { "m0,4", "E*" }, /* read 1 byte at address 4 */
++ { "m0,5", "E*" }, /* read 1 byte at address 5 */
++ { "m0,6", "E*" }, /* read 1 byte at address 6 */
++ { "m0,7", "E*" }, /* read 1 byte at address 7 */
++ { "m0,8", "E*" }, /* read 1 byte at address 8 */
++ { "D", "OK" }, /* Detach which removes all breakpoints and continues */
++ { "", "" },
++};
++
++/*
++ * Test for hitting a breakpoint, remove it, single step, plant it
++ * again and detach.
++ */
++static struct test_struct singlestep_break_test[] = {
++ { "?", "S0*" }, /* Clear break points */
++ { "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */
++ { "c", "T0*", }, /* Continue */
++ { "g", "kgdbts_break_test", 0, check_and_rewind_pc },
++ { "write", "OK", write_regs }, /* Write registers */
++ { "kgdbts_break_test", "OK", sw_rem_break }, /*remove breakpoint */
++ { "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */
++ { "g", "kgdbts_break_test", 0, check_single_step },
++ { "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */
++ { "c", "T0*", }, /* Continue */
++ { "g", "kgdbts_break_test", 0, check_and_rewind_pc },
++ { "write", "OK", write_regs }, /* Write registers */
++ { "D", "OK" }, /* Remove all breakpoints and continues */
++ { "", "" },
++};
++
++/*
++ * Test for hitting a breakpoint at do_fork for what ever the number
++ * of iterations required by the variable repeat_test.
++ */
++static struct test_struct do_fork_test[] = {
++ { "?", "S0*" }, /* Clear break points */
++ { "do_fork", "OK", sw_break, }, /* set sw breakpoint */
++ { "c", "T0*", }, /* Continue */
++ { "g", "do_fork", 0, check_and_rewind_pc }, /* check location */
++ { "write", "OK", write_regs }, /* Write registers */
++ { "do_fork", "OK", sw_rem_break }, /*remove breakpoint */
++ { "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */
++ { "g", "do_fork", 0, check_single_step },
++ { "do_fork", "OK", sw_break, }, /* set sw breakpoint */
++ { "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */
++ { "D", "OK", 0, final_ack_set }, /* detach and unregister I/O */
++ { "", "" },
++};
++
++/* Test for hitting a breakpoint at sys_open for what ever the number
++ * of iterations required by the variable repeat_test.
++ */
++static struct test_struct sys_open_test[] = {
++ { "?", "S0*" }, /* Clear break points */
++ { "sys_open", "OK", sw_break, }, /* set sw breakpoint */
++ { "c", "T0*", }, /* Continue */
++ { "g", "sys_open", 0, check_and_rewind_pc }, /* check location */
++ { "write", "OK", write_regs }, /* Write registers */
++ { "sys_open", "OK", sw_rem_break }, /*remove breakpoint */
++ { "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */
++ { "g", "sys_open", 0, check_single_step },
++ { "sys_open", "OK", sw_break, }, /* set sw breakpoint */
++ { "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */
++ { "D", "OK", 0, final_ack_set }, /* detach and unregister I/O */
++ { "", "" },
++};
++
++/*
++ * Test for hitting a simple hw breakpoint
++ */
++static struct test_struct hw_breakpoint_test[] = {
++ { "?", "S0*" }, /* Clear break points */
++ { "kgdbts_break_test", "OK", hw_break, }, /* set hw breakpoint */
++ { "c", "T0*", }, /* Continue */
++ { "g", "kgdbts_break_test", 0, check_and_rewind_pc },
++ { "write", "OK", write_regs },
++ { "kgdbts_break_test", "OK", hw_rem_break }, /*remove breakpoint */
++ { "D", "OK" }, /* Detach */
++ { "D", "OK", 0, got_break }, /* If the test worked we made it here */
++ { "", "" },
++};
++
++/*
++ * Test for hitting a hw write breakpoint
++ */
++static struct test_struct hw_write_break_test[] = {
++ { "?", "S0*" }, /* Clear break points */
++ { "hw_break_val", "OK", hw_write_break, }, /* set hw breakpoint */
++ { "c", "T0*", 0, got_break }, /* Continue */
++ { "g", "silent", 0, check_and_rewind_pc },
++ { "write", "OK", write_regs },
++ { "hw_break_val", "OK", hw_rem_write_break }, /*remove breakpoint */
++ { "D", "OK" }, /* Detach */
++ { "D", "OK", 0, got_break }, /* If the test worked we made it here */
++ { "", "" },
++};
++
++/*
++ * Test for hitting a hw access breakpoint
++ */
++static struct test_struct hw_access_break_test[] = {
++ { "?", "S0*" }, /* Clear break points */
++ { "hw_break_val", "OK", hw_access_break, }, /* set hw breakpoint */
++ { "c", "T0*", 0, got_break }, /* Continue */
++ { "g", "silent", 0, check_and_rewind_pc },
++ { "write", "OK", write_regs },
++ { "hw_break_val", "OK", hw_rem_access_break }, /*remove breakpoint */
++ { "D", "OK" }, /* Detach */
++ { "D", "OK", 0, got_break }, /* If the test worked we made it here */
++ { "", "" },
++};
++
++/*
++ * Test for hitting a hw access breakpoint
++ */
++static struct test_struct nmi_sleep_test[] = {
++ { "?", "S0*" }, /* Clear break points */
++ { "c", "T0*", 0, got_break }, /* Continue */
++ { "D", "OK" }, /* Detach */
++ { "D", "OK", 0, got_break }, /* If the test worked we made it here */
++ { "", "" },
++};
++
++static void fill_get_buf(char *buf)
++{
++ unsigned char checksum = 0;
++ int count = 0;
++ char ch;
++
++ strcpy(get_buf, "$");
++ strcat(get_buf, buf);
++ while ((ch = buf[count])) {
++ checksum += ch;
++ count++;
++ }
++ strcat(get_buf, "#");
++ get_buf[count + 2] = hexchars[checksum >> 4];
++ get_buf[count + 3] = hexchars[checksum & 0xf];
++ get_buf[count + 4] = '\0';
++ v2printk("get%i: %s\n", ts.idx, get_buf);
++}
++
++static int validate_simple_test(char *put_str)
++{
++ char *chk_str;
++
++ if (ts.tst[ts.idx].put_handler)
++ return ts.tst[ts.idx].put_handler(put_str,
++ ts.tst[ts.idx].put);
++
++ chk_str = ts.tst[ts.idx].put;
++ if (*put_str == '$')
++ put_str++;
++
++ while (*chk_str != '\0' && *put_str != '\0') {
++ /* If someone does a * to match the rest of the string, allow
++ * it, or stop if the recieved string is complete.
++ */
++ if (*put_str == '#' || *chk_str == '*')
++ return 0;
++ if (*put_str != *chk_str)
++ return 1;
++
++ chk_str++;
++ put_str++;
++ }
++ if (*chk_str == '\0' && (*put_str == '\0' || *put_str == '#'))
++ return 0;
++
++ return 1;
++}
++
++static int run_simple_test(int is_get_char, int chr)
++{
++ int ret = 0;
++ if (is_get_char) {
++ /* Send an ACK on the get if a prior put completed and set the
++ * send ack variable
++ */
++ if (send_ack) {
++ send_ack = 0;
++ return '+';
++ }
++ /* On the first get char, fill the transmit buffer and then
++ * take from the get_string.
++ */
++ if (get_buf_cnt == 0) {
++ if (ts.tst[ts.idx].get_handler)
++ ts.tst[ts.idx].get_handler(ts.tst[ts.idx].get);
++ else
++ fill_get_buf(ts.tst[ts.idx].get);
++ }
++
++ if (get_buf[get_buf_cnt] == '\0') {
++ eprintk("kgdbts: ERROR GET: EOB on '%s' at %i\n",
++ ts.name, ts.idx);
++ get_buf_cnt = 0;
++ fill_get_buf("D");
++ }
++ ret = get_buf[get_buf_cnt];
++ get_buf_cnt++;
++ return ret;
++ }
++
++ /* This callback is a put char which is when kgdb sends data to
++ * this I/O module.
++ */
++ if (ts.tst[ts.idx].get[0] == '\0' &&
++ ts.tst[ts.idx].put[0] == '\0') {
++ eprintk("kgdbts: ERROR: beyond end of test on"
++ " '%s' line %i\n", ts.name, ts.idx);
++ return 0;
++ }
++
++ if (put_buf_cnt >= BUFMAX) {
++ eprintk("kgdbts: ERROR: put buffer overflow on"
++ " '%s' line %i\n", ts.name, ts.idx);
++ put_buf_cnt = 0;
++ return 0;
++ }
++ /* Ignore everything until the first valid packet start '$' */
++ if (put_buf_cnt == 0 && chr != '$')
++ return 0;
++
++ put_buf[put_buf_cnt] = chr;
++ put_buf_cnt++;
++
++ /* End of packet == #XX so look for the '#' */
++ if (put_buf_cnt > 3 && put_buf[put_buf_cnt - 3] == '#') {
++ put_buf[put_buf_cnt] = '\0';
++ v2printk("put%i: %s\n", ts.idx, put_buf);
++ /* Trigger check here */
++ if (ts.validate_put && ts.validate_put(put_buf)) {
++ eprintk("kgdbts: ERROR PUT: end of test "
++ "buffer on '%s' line %i expected %s got %s\n",
++ ts.name, ts.idx, ts.tst[ts.idx].put, put_buf);
++ }
++ ts.idx++;
++ put_buf_cnt = 0;
++ get_buf_cnt = 0;
++ send_ack = 1;
++ }
++ return 0;
++}
++
++static void init_simple_test(void)
++{
++ memset(&ts, 0, sizeof(ts));
++ ts.run_test = run_simple_test;
++ ts.validate_put = validate_simple_test;
++}
++
++static void run_plant_and_detach_test(int is_early)
++{
++ char before[BREAK_INSTR_SIZE];
++ char after[BREAK_INSTR_SIZE];
++
++ probe_kernel_read(before, (char *)kgdbts_break_test,
++ BREAK_INSTR_SIZE);
++ init_simple_test();
++ ts.tst = plant_and_detach_test;
++ ts.name = "plant_and_detach_test";
++ /* Activate test with initial breakpoint */
++ if (!is_early)
++ kgdb_breakpoint();
++ probe_kernel_read(after, (char *)kgdbts_break_test,
++ BREAK_INSTR_SIZE);
++ if (memcmp(before, after, BREAK_INSTR_SIZE)) {
++ printk(KERN_CRIT "kgdbts: ERROR kgdb corrupted memory\n");
++ panic("kgdb memory corruption");
++ }
++
++ /* complete the detach test */
++ if (!is_early)
++ kgdbts_break_test();
++}
++
++static void run_breakpoint_test(int is_hw_breakpoint)
++{
++ test_complete = 0;
++ init_simple_test();
++ if (is_hw_breakpoint) {
++ ts.tst = hw_breakpoint_test;
++ ts.name = "hw_breakpoint_test";
++ } else {
++ ts.tst = sw_breakpoint_test;
++ ts.name = "sw_breakpoint_test";
++ }
++ /* Activate test with initial breakpoint */
++ kgdb_breakpoint();
++ /* run code with the break point in it */
++ kgdbts_break_test();
++ kgdb_breakpoint();
++
++ if (test_complete)
++ return;
++
++ eprintk("kgdbts: ERROR %s test failed\n", ts.name);
++}
++
++static void run_hw_break_test(int is_write_test)
++{
++ test_complete = 0;
++ init_simple_test();
++ if (is_write_test) {
++ ts.tst = hw_write_break_test;
++ ts.name = "hw_write_break_test";
++ } else {
++ ts.tst = hw_access_break_test;
++ ts.name = "hw_access_break_test";
++ }
++ /* Activate test with initial breakpoint */
++ kgdb_breakpoint();
++ hw_break_val_access();
++ if (is_write_test) {
++ if (test_complete == 2)
++ eprintk("kgdbts: ERROR %s broke on access\n",
++ ts.name);
++ hw_break_val_write();
++ }
++ kgdb_breakpoint();
++
++ if (test_complete == 1)
++ return;
++
++ eprintk("kgdbts: ERROR %s test failed\n", ts.name);
++}
++
++static void run_nmi_sleep_test(int nmi_sleep)
++{
++ unsigned long flags;
++
++ init_simple_test();
++ ts.tst = nmi_sleep_test;
++ ts.name = "nmi_sleep_test";
++ /* Activate test with initial breakpoint */
++ kgdb_breakpoint();
++ local_irq_save(flags);
++ mdelay(nmi_sleep*1000);
++ touch_nmi_watchdog();
++ local_irq_restore(flags);
++ if (test_complete != 2)
++ eprintk("kgdbts: ERROR nmi_test did not hit nmi\n");
++ kgdb_breakpoint();
++ if (test_complete == 1)
++ return;
++
++ eprintk("kgdbts: ERROR %s test failed\n", ts.name);
++}
++
++static void run_bad_read_test(void)
++{
++ init_simple_test();
++ ts.tst = bad_read_test;
++ ts.name = "bad_read_test";
++ /* Activate test with initial breakpoint */
++ kgdb_breakpoint();
++}
++
++static void run_do_fork_test(void)
++{
++ init_simple_test();
++ ts.tst = do_fork_test;
++ ts.name = "do_fork_test";
++ /* Activate test with initial breakpoint */
++ kgdb_breakpoint();
++}
++
++static void run_sys_open_test(void)
++{
++ init_simple_test();
++ ts.tst = sys_open_test;
++ ts.name = "sys_open_test";
++ /* Activate test with initial breakpoint */
++ kgdb_breakpoint();
++}
++
++static void run_singlestep_break_test(void)
++{
++ init_simple_test();
++ ts.tst = singlestep_break_test;
++ ts.name = "singlestep_breakpoint_test";
++ /* Activate test with initial breakpoint */
++ kgdb_breakpoint();
++ kgdbts_break_test();
++ kgdbts_break_test();
++}
++
++static void kgdbts_run_tests(void)
++{
++ char *ptr;
++ int fork_test = 0;
++ int sys_open_test = 0;
++ int nmi_sleep = 0;
++
++ ptr = strstr(config, "F");
++ if (ptr)
++ fork_test = simple_strtol(ptr+1, NULL, 10);
++ ptr = strstr(config, "S");
++ if (ptr)
++ sys_open_test = simple_strtol(ptr+1, NULL, 10);
++ ptr = strstr(config, "N");
++ if (ptr)
++ nmi_sleep = simple_strtol(ptr+1, NULL, 10);
++
++ /* required internal KGDB tests */
++ v1printk("kgdbts:RUN plant and detach test\n");
++ run_plant_and_detach_test(0);
++ v1printk("kgdbts:RUN sw breakpoint test\n");
++ run_breakpoint_test(0);
++ v1printk("kgdbts:RUN bad memory access test\n");
++ run_bad_read_test();
++ v1printk("kgdbts:RUN singlestep breakpoint test\n");
++ run_singlestep_break_test();
++
++ /* ===Optional tests=== */
++
++ /* All HW break point tests */
++ if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT) {
++ v1printk("kgdbts:RUN hw breakpoint test\n");
++ run_breakpoint_test(1);
++ v1printk("kgdbts:RUN hw write breakpoint test\n");
++ run_hw_break_test(1);
++ v1printk("kgdbts:RUN access write breakpoint test\n");
++ run_hw_break_test(0);
++ }
++
++ if (nmi_sleep) {
++ v1printk("kgdbts:RUN NMI sleep %i seconds test\n", nmi_sleep);
++ run_nmi_sleep_test(nmi_sleep);
++ }
++
++ /* If the do_fork test is run it will be the last test that is
++ * executed because a kernel thread will be spawned at the very
++ * end to unregister the debug hooks.
++ */
++ if (fork_test) {
++ repeat_test = fork_test;
++ printk(KERN_INFO "kgdbts:RUN do_fork for %i breakpoints\n",
++ repeat_test);
++ kthread_run(kgdbts_unreg_thread, 0, "kgdbts_unreg");
++ run_do_fork_test();
++ return;
++ }
++
++ /* If the sys_open test is run it will be the last test that is
++ * executed because a kernel thread will be spawned at the very
++ * end to unregister the debug hooks.
++ */
++ if (sys_open_test) {
++ repeat_test = sys_open_test;
++ printk(KERN_INFO "kgdbts:RUN sys_open for %i breakpoints\n",
++ repeat_test);
++ kthread_run(kgdbts_unreg_thread, 0, "kgdbts_unreg");
++ run_sys_open_test();
++ return;
++ }
++ /* Shutdown and unregister */
++ kgdb_unregister_io_module(&kgdbts_io_ops);
++ configured = 0;
++}
++
++static int kgdbts_option_setup(char *opt)
++{
++ if (strlen(opt) > MAX_CONFIG_LEN) {
++ printk(KERN_ERR "kgdbts: config string too long\n");
++ return -ENOSPC;
++ }
++ strcpy(config, opt);
++
++ verbose = 0;
++ if (strstr(config, "V1"))
++ verbose = 1;
++ if (strstr(config, "V2"))
++ verbose = 2;
++
++ return 0;
++}
++
++__setup("kgdbts=", kgdbts_option_setup);
++
++static int configure_kgdbts(void)
++{
++ int err = 0;
++
++ if (!strlen(config) || isspace(config[0]))
++ goto noconfig;
++ err = kgdbts_option_setup(config);
++ if (err)
++ goto noconfig;
++
++ final_ack = 0;
++ run_plant_and_detach_test(1);
++
++ err = kgdb_register_io_module(&kgdbts_io_ops);
++ if (err) {
++ configured = 0;
++ return err;
++ }
++ configured = 1;
++ kgdbts_run_tests();
++
++ return err;
++
++noconfig:
++ config[0] = 0;
++ configured = 0;
++
++ return err;
++}
++
++static int __init init_kgdbts(void)
++{
++ /* Already configured? */
++ if (configured == 1)
++ return 0;
++
++ return configure_kgdbts();
++}
++
++static void cleanup_kgdbts(void)
++{
++ if (configured == 1)
++ kgdb_unregister_io_module(&kgdbts_io_ops);
++}
++
++static int kgdbts_get_char(void)
++{
++ int val = 0;
++
++ if (ts.run_test)
++ val = ts.run_test(1, 0);
++
++ return val;
++}
++
++static void kgdbts_put_char(u8 chr)
++{
++ if (ts.run_test)
++ ts.run_test(0, chr);
++}
++
++static int param_set_kgdbts_var(const char *kmessage, struct kernel_param *kp)
++{
++ int len = strlen(kmessage);
++
++ if (len >= MAX_CONFIG_LEN) {
++ printk(KERN_ERR "kgdbts: config string too long\n");
++ return -ENOSPC;
++ }
++
++ /* Only copy in the string if the init function has not run yet */
++ if (configured < 0) {
++ strcpy(config, kmessage);
++ return 0;
++ }
++
++ if (kgdb_connected) {
++ printk(KERN_ERR
++ "kgdbts: Cannot reconfigure while KGDB is connected.\n");
++
++ return -EBUSY;
++ }
++
++ strcpy(config, kmessage);
++ /* Chop out \n char as a result of echo */
++ if (config[len - 1] == '\n')
++ config[len - 1] = '\0';
++
++ if (configured == 1)
++ cleanup_kgdbts();
++
++ /* Go and configure with the new params. */
++ return configure_kgdbts();
++}
++
++static void kgdbts_pre_exp_handler(void)
++{
++ /* Increment the module count when the debugger is active */
++ if (!kgdb_connected)
++ try_module_get(THIS_MODULE);
++}
++
++static void kgdbts_post_exp_handler(void)
++{
++ /* decrement the module count when the debugger detaches */
++ if (!kgdb_connected)
++ module_put(THIS_MODULE);
++}
++
++static struct kgdb_io kgdbts_io_ops = {
++ .name = "kgdbts",
++ .read_char = kgdbts_get_char,
++ .write_char = kgdbts_put_char,
++ .pre_exception = kgdbts_pre_exp_handler,
++ .post_exception = kgdbts_post_exp_handler,
++};
++
++module_init(init_kgdbts);
++module_exit(cleanup_kgdbts);
++module_param_call(kgdbts, param_set_kgdbts_var, param_get_string, &kps, 0644);
++MODULE_PARM_DESC(kgdbts, "<A|V1|V2>[F#|S#][N#]");
++MODULE_DESCRIPTION("KGDB Test Suite");
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Wind River Systems, Inc.");
++
+diff --git a/drivers/misc/sgi-xp/Makefile b/drivers/misc/sgi-xp/Makefile
+new file mode 100644
+index 0000000..b6e40a7
+--- /dev/null
++++ b/drivers/misc/sgi-xp/Makefile
+@@ -0,0 +1,11 @@
++#
++# Makefile for SGI's XP devices.
++#
++
++obj-$(CONFIG_SGI_XP) += xp.o
++xp-y := xp_main.o xp_nofault.o
++
++obj-$(CONFIG_SGI_XP) += xpc.o
++xpc-y := xpc_main.o xpc_channel.o xpc_partition.o
++
++obj-$(CONFIG_SGI_XP) += xpnet.o
+diff --git a/drivers/misc/sgi-xp/xp.h b/drivers/misc/sgi-xp/xp.h
+new file mode 100644
+index 0000000..5515234
+--- /dev/null
++++ b/drivers/misc/sgi-xp/xp.h
+@@ -0,0 +1,463 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2004-2008 Silicon Graphics, Inc. All rights reserved.
++ */
++
++/*
++ * External Cross Partition (XP) structures and defines.
++ */
++
++#ifndef _DRIVERS_MISC_SGIXP_XP_H
++#define _DRIVERS_MISC_SGIXP_XP_H
++
++#include <linux/cache.h>
++#include <linux/hardirq.h>
++#include <linux/mutex.h>
++#include <asm/sn/types.h>
++#include <asm/sn/bte.h>
++
++#ifdef USE_DBUG_ON
++#define DBUG_ON(condition) BUG_ON(condition)
++#else
++#define DBUG_ON(condition)
++#endif
++
++/*
++ * Define the maximum number of logically defined partitions the system
++ * can support. It is constrained by the maximum number of hardware
++ * partitionable regions. The term 'region' in this context refers to the
++ * minimum number of nodes that can comprise an access protection grouping.
++ * The access protection is in regards to memory, IPI and IOI.
++ *
++ * The maximum number of hardware partitionable regions is equal to the
++ * maximum number of nodes in the entire system divided by the minimum number
++ * of nodes that comprise an access protection grouping.
++ */
++#define XP_MAX_PARTITIONS 64
++
++/*
++ * Define the number of u64s required to represent all the C-brick nasids
++ * as a bitmap. The cross-partition kernel modules deal only with
++ * C-brick nasids, thus the need for bitmaps which don't account for
++ * odd-numbered (non C-brick) nasids.
++ */
++#define XP_MAX_PHYSNODE_ID (MAX_NUMALINK_NODES / 2)
++#define XP_NASID_MASK_BYTES ((XP_MAX_PHYSNODE_ID + 7) / 8)
++#define XP_NASID_MASK_WORDS ((XP_MAX_PHYSNODE_ID + 63) / 64)
++
++/*
++ * Wrapper for bte_copy() that should it return a failure status will retry
++ * the bte_copy() once in the hope that the failure was due to a temporary
++ * aberration (i.e., the link going down temporarily).
++ *
++ * src - physical address of the source of the transfer.
++ * vdst - virtual address of the destination of the transfer.
++ * len - number of bytes to transfer from source to destination.
++ * mode - see bte_copy() for definition.
++ * notification - see bte_copy() for definition.
++ *
++ * Note: xp_bte_copy() should never be called while holding a spinlock.
++ */
++static inline bte_result_t
++xp_bte_copy(u64 src, u64 vdst, u64 len, u64 mode, void *notification)
++{
++ bte_result_t ret;
++ u64 pdst = ia64_tpa(vdst);
++
++ /*
++ * Ensure that the physically mapped memory is contiguous.
++ *
++ * We do this by ensuring that the memory is from region 7 only.
++ * If the need should arise to use memory from one of the other
++ * regions, then modify the BUG_ON() statement to ensure that the
++ * memory from that region is always physically contiguous.
++ */
++ BUG_ON(REGION_NUMBER(vdst) != RGN_KERNEL);
++
++ ret = bte_copy(src, pdst, len, mode, notification);
++ if ((ret != BTE_SUCCESS) && BTE_ERROR_RETRY(ret)) {
++ if (!in_interrupt())
++ cond_resched();
++
++ ret = bte_copy(src, pdst, len, mode, notification);
++ }
++
++ return ret;
++}
++
++/*
++ * XPC establishes channel connections between the local partition and any
++ * other partition that is currently up. Over these channels, kernel-level
++ * `users' can communicate with their counterparts on the other partitions.
++ *
++ * The maxinum number of channels is limited to eight. For performance reasons,
++ * the internal cross partition structures require sixteen bytes per channel,
++ * and eight allows all of this interface-shared info to fit in one cache line.
++ *
++ * XPC_NCHANNELS reflects the total number of channels currently defined.
++ * If the need for additional channels arises, one can simply increase
++ * XPC_NCHANNELS accordingly. If the day should come where that number
++ * exceeds the MAXIMUM number of channels allowed (eight), then one will need
++ * to make changes to the XPC code to allow for this.
++ */
++#define XPC_MEM_CHANNEL 0 /* memory channel number */
++#define XPC_NET_CHANNEL 1 /* network channel number */
++
++#define XPC_NCHANNELS 2 /* #of defined channels */
++#define XPC_MAX_NCHANNELS 8 /* max #of channels allowed */
++
++#if XPC_NCHANNELS > XPC_MAX_NCHANNELS
++#error XPC_NCHANNELS exceeds MAXIMUM allowed.
++#endif
++
++/*
++ * The format of an XPC message is as follows:
++ *
++ * +-------+--------------------------------+
++ * | flags |////////////////////////////////|
++ * +-------+--------------------------------+
++ * | message # |
++ * +----------------------------------------+
++ * | payload (user-defined message) |
++ * | |
++ * :
++ * | |
++ * +----------------------------------------+
++ *
++ * The size of the payload is defined by the user via xpc_connect(). A user-
++ * defined message resides in the payload area.
++ *
++ * The user should have no dealings with the message header, but only the
++ * message's payload. When a message entry is allocated (via xpc_allocate())
++ * a pointer to the payload area is returned and not the actual beginning of
++ * the XPC message. The user then constructs a message in the payload area
++ * and passes that pointer as an argument on xpc_send() or xpc_send_notify().
++ *
++ * The size of a message entry (within a message queue) must be a cacheline
++ * sized multiple in order to facilitate the BTE transfer of messages from one
++ * message queue to another. A macro, XPC_MSG_SIZE(), is provided for the user
++ * that wants to fit as many msg entries as possible in a given memory size
++ * (e.g. a memory page).
++ */
++struct xpc_msg {
++ u8 flags; /* FOR XPC INTERNAL USE ONLY */
++ u8 reserved[7]; /* FOR XPC INTERNAL USE ONLY */
++ s64 number; /* FOR XPC INTERNAL USE ONLY */
++
++ u64 payload; /* user defined portion of message */
++};
++
++#define XPC_MSG_PAYLOAD_OFFSET (u64) (&((struct xpc_msg *)0)->payload)
++#define XPC_MSG_SIZE(_payload_size) \
++ L1_CACHE_ALIGN(XPC_MSG_PAYLOAD_OFFSET + (_payload_size))
++
++/*
++ * Define the return values and values passed to user's callout functions.
++ * (It is important to add new value codes at the end just preceding
++ * xpcUnknownReason, which must have the highest numerical value.)
++ */
++enum xpc_retval {
++ xpcSuccess = 0,
++
++ xpcNotConnected, /* 1: channel is not connected */
++ xpcConnected, /* 2: channel connected (opened) */
++ xpcRETIRED1, /* 3: (formerly xpcDisconnected) */
++
++ xpcMsgReceived, /* 4: message received */
++ xpcMsgDelivered, /* 5: message delivered and acknowledged */
++
++ xpcRETIRED2, /* 6: (formerly xpcTransferFailed) */
++
++ xpcNoWait, /* 7: operation would require wait */
++ xpcRetry, /* 8: retry operation */
++ xpcTimeout, /* 9: timeout in xpc_allocate_msg_wait() */
++ xpcInterrupted, /* 10: interrupted wait */
++
++ xpcUnequalMsgSizes, /* 11: message size disparity between sides */
++ xpcInvalidAddress, /* 12: invalid address */
++
++ xpcNoMemory, /* 13: no memory available for XPC structures */
++ xpcLackOfResources, /* 14: insufficient resources for operation */
++ xpcUnregistered, /* 15: channel is not registered */
++ xpcAlreadyRegistered, /* 16: channel is already registered */
++
++ xpcPartitionDown, /* 17: remote partition is down */
++ xpcNotLoaded, /* 18: XPC module is not loaded */
++ xpcUnloading, /* 19: this side is unloading XPC module */
++
++ xpcBadMagic, /* 20: XPC MAGIC string not found */
++
++ xpcReactivating, /* 21: remote partition was reactivated */
++
++ xpcUnregistering, /* 22: this side is unregistering channel */
++ xpcOtherUnregistering, /* 23: other side is unregistering channel */
++
++ xpcCloneKThread, /* 24: cloning kernel thread */
++ xpcCloneKThreadFailed, /* 25: cloning kernel thread failed */
++
++ xpcNoHeartbeat, /* 26: remote partition has no heartbeat */
++
++ xpcPioReadError, /* 27: PIO read error */
++ xpcPhysAddrRegFailed, /* 28: registration of phys addr range failed */
++
++ xpcBteDirectoryError, /* 29: maps to BTEFAIL_DIR */
++ xpcBtePoisonError, /* 30: maps to BTEFAIL_POISON */
++ xpcBteWriteError, /* 31: maps to BTEFAIL_WERR */
++ xpcBteAccessError, /* 32: maps to BTEFAIL_ACCESS */
++ xpcBtePWriteError, /* 33: maps to BTEFAIL_PWERR */
++ xpcBtePReadError, /* 34: maps to BTEFAIL_PRERR */
++ xpcBteTimeOutError, /* 35: maps to BTEFAIL_TOUT */
++ xpcBteXtalkError, /* 36: maps to BTEFAIL_XTERR */
++ xpcBteNotAvailable, /* 37: maps to BTEFAIL_NOTAVAIL */
++ xpcBteUnmappedError, /* 38: unmapped BTEFAIL_ error */
++
++ xpcBadVersion, /* 39: bad version number */
++ xpcVarsNotSet, /* 40: the XPC variables are not set up */
++ xpcNoRsvdPageAddr, /* 41: unable to get rsvd page's phys addr */
++ xpcInvalidPartid, /* 42: invalid partition ID */
++ xpcLocalPartid, /* 43: local partition ID */
++
++ xpcOtherGoingDown, /* 44: other side going down, reason unknown */
++ xpcSystemGoingDown, /* 45: system is going down, reason unknown */
++ xpcSystemHalt, /* 46: system is being halted */
++ xpcSystemReboot, /* 47: system is being rebooted */
++ xpcSystemPoweroff, /* 48: system is being powered off */
++
++ xpcDisconnecting, /* 49: channel disconnecting (closing) */
++
++ xpcOpenCloseError, /* 50: channel open/close protocol error */
++
++ xpcDisconnected, /* 51: channel disconnected (closed) */
++
++ xpcBteSh2Start, /* 52: BTE CRB timeout */
++
++ /* 53: 0x1 BTE Error Response Short */
++ xpcBteSh2RspShort = xpcBteSh2Start + BTEFAIL_SH2_RESP_SHORT,
++
++ /* 54: 0x2 BTE Error Response Long */
++ xpcBteSh2RspLong = xpcBteSh2Start + BTEFAIL_SH2_RESP_LONG,
++
++ /* 56: 0x4 BTE Error Response DSB */
++ xpcBteSh2RspDSB = xpcBteSh2Start + BTEFAIL_SH2_RESP_DSP,
++
++ /* 60: 0x8 BTE Error Response Access */
++ xpcBteSh2RspAccess = xpcBteSh2Start + BTEFAIL_SH2_RESP_ACCESS,
++
++ /* 68: 0x10 BTE Error CRB timeout */
++ xpcBteSh2CRBTO = xpcBteSh2Start + BTEFAIL_SH2_CRB_TO,
++
++ /* 84: 0x20 BTE Error NACK limit */
++ xpcBteSh2NACKLimit = xpcBteSh2Start + BTEFAIL_SH2_NACK_LIMIT,
++
++ /* 115: BTE end */
++ xpcBteSh2End = xpcBteSh2Start + BTEFAIL_SH2_ALL,
++
++ xpcUnknownReason /* 116: unknown reason - must be last in enum */
++};
++
++/*
++ * Define the callout function types used by XPC to update the user on
++ * connection activity and state changes (via the user function registered by
++ * xpc_connect()) and to notify them of messages received and delivered (via
++ * the user function registered by xpc_send_notify()).
++ *
++ * The two function types are xpc_channel_func and xpc_notify_func and
++ * both share the following arguments, with the exception of "data", which
++ * only xpc_channel_func has.
++ *
++ * Arguments:
++ *
++ * reason - reason code. (See following table.)
++ * partid - partition ID associated with condition.
++ * ch_number - channel # associated with condition.
++ * data - pointer to optional data. (See following table.)
++ * key - pointer to optional user-defined value provided as the "key"
++ * argument to xpc_connect() or xpc_send_notify().
++ *
++ * In the following table the "Optional Data" column applies to callouts made
++ * to functions registered by xpc_connect(). A "NA" in that column indicates
++ * that this reason code can be passed to functions registered by
++ * xpc_send_notify() (i.e. they don't have data arguments).
++ *
++ * Also, the first three reason codes in the following table indicate
++ * success, whereas the others indicate failure. When a failure reason code
++ * is received, one can assume that the channel is not connected.
++ *
++ *
++ * Reason Code | Cause | Optional Data
++ * =====================+================================+=====================
++ * xpcConnected | connection has been established| max #of entries
++ * | to the specified partition on | allowed in message
++ * | the specified channel | queue
++ * ---------------------+--------------------------------+---------------------
++ * xpcMsgReceived | an XPC message arrived from | address of payload
++ * | the specified partition on the |
++ * | specified channel | [the user must call
++ * | | xpc_received() when
++ * | | finished with the
++ * | | payload]
++ * ---------------------+--------------------------------+---------------------
++ * xpcMsgDelivered | notification that the message | NA
++ * | was delivered to the intended |
++ * | recipient and that they have |
++ * | acknowledged its receipt by |
++ * | calling xpc_received() |
++ * =====================+================================+=====================
++ * xpcUnequalMsgSizes | can't connect to the specified | NULL
++ * | partition on the specified |
++ * | channel because of mismatched |
++ * | message sizes |
++ * ---------------------+--------------------------------+---------------------
++ * xpcNoMemory | insufficient memory avaiable | NULL
++ * | to allocate message queue |
++ * ---------------------+--------------------------------+---------------------
++ * xpcLackOfResources | lack of resources to create | NULL
++ * | the necessary kthreads to |
++ * | support the channel |
++ * ---------------------+--------------------------------+---------------------
++ * xpcUnregistering | this side's user has | NULL or NA
++ * | unregistered by calling |
++ * | xpc_disconnect() |
++ * ---------------------+--------------------------------+---------------------
++ * xpcOtherUnregistering| the other side's user has | NULL or NA
++ * | unregistered by calling |
++ * | xpc_disconnect() |
++ * ---------------------+--------------------------------+---------------------
++ * xpcNoHeartbeat | the other side's XPC is no | NULL or NA
++ * | longer heartbeating |
++ * | |
++ * ---------------------+--------------------------------+---------------------
++ * xpcUnloading | this side's XPC module is | NULL or NA
++ * | being unloaded |
++ * | |
++ * ---------------------+--------------------------------+---------------------
++ * xpcOtherUnloading | the other side's XPC module is | NULL or NA
++ * | is being unloaded |
++ * | |
++ * ---------------------+--------------------------------+---------------------
++ * xpcPioReadError | xp_nofault_PIOR() returned an | NULL or NA
++ * | error while sending an IPI |
++ * | |
++ * ---------------------+--------------------------------+---------------------
++ * xpcInvalidAddress | the address either received or | NULL or NA
++ * | sent by the specified partition|
++ * | is invalid |
++ * ---------------------+--------------------------------+---------------------
++ * xpcBteNotAvailable | attempt to pull data from the | NULL or NA
++ * xpcBtePoisonError | specified partition over the |
++ * xpcBteWriteError | specified channel via a |
++ * xpcBteAccessError | bte_copy() failed |
++ * xpcBteTimeOutError | |
++ * xpcBteXtalkError | |
++ * xpcBteDirectoryError | |
++ * xpcBteGenericError | |
++ * xpcBteUnmappedError | |
++ * ---------------------+--------------------------------+---------------------
++ * xpcUnknownReason | the specified channel to the | NULL or NA
++ * | specified partition was |
++ * | unavailable for unknown reasons|
++ * =====================+================================+=====================
++ */
++
++typedef void (*xpc_channel_func) (enum xpc_retval reason, partid_t partid,
++ int ch_number, void *data, void *key);
++
++typedef void (*xpc_notify_func) (enum xpc_retval reason, partid_t partid,
++ int ch_number, void *key);
++
++/*
++ * The following is a registration entry. There is a global array of these,
++ * one per channel. It is used to record the connection registration made
++ * by the users of XPC. As long as a registration entry exists, for any
++ * partition that comes up, XPC will attempt to establish a connection on
++ * that channel. Notification that a connection has been made will occur via
++ * the xpc_channel_func function.
++ *
++ * The 'func' field points to the function to call when aynchronous
++ * notification is required for such events as: a connection established/lost,
++ * or an incoming message received, or an error condition encountered. A
++ * non-NULL 'func' field indicates that there is an active registration for
++ * the channel.
++ */
++struct xpc_registration {
++ struct mutex mutex;
++ xpc_channel_func func; /* function to call */
++ void *key; /* pointer to user's key */
++ u16 nentries; /* #of msg entries in local msg queue */
++ u16 msg_size; /* message queue's message size */
++ u32 assigned_limit; /* limit on #of assigned kthreads */
++ u32 idle_limit; /* limit on #of idle kthreads */
++} ____cacheline_aligned;
++
++#define XPC_CHANNEL_REGISTERED(_c) (xpc_registrations[_c].func != NULL)
++
++/* the following are valid xpc_allocate() flags */
++#define XPC_WAIT 0 /* wait flag */
++#define XPC_NOWAIT 1 /* no wait flag */
++
++struct xpc_interface {
++ void (*connect) (int);
++ void (*disconnect) (int);
++ enum xpc_retval (*allocate) (partid_t, int, u32, void **);
++ enum xpc_retval (*send) (partid_t, int, void *);
++ enum xpc_retval (*send_notify) (partid_t, int, void *,
++ xpc_notify_func, void *);
++ void (*received) (partid_t, int, void *);
++ enum xpc_retval (*partid_to_nasids) (partid_t, void *);
++};
++
++extern struct xpc_interface xpc_interface;
++
++extern void xpc_set_interface(void (*)(int),
++ void (*)(int),
++ enum xpc_retval (*)(partid_t, int, u32, void **),
++ enum xpc_retval (*)(partid_t, int, void *),
++ enum xpc_retval (*)(partid_t, int, void *,
++ xpc_notify_func, void *),
++ void (*)(partid_t, int, void *),
++ enum xpc_retval (*)(partid_t, void *));
++extern void xpc_clear_interface(void);
++
++extern enum xpc_retval xpc_connect(int, xpc_channel_func, void *, u16,
++ u16, u32, u32);
++extern void xpc_disconnect(int);
++
++static inline enum xpc_retval
++xpc_allocate(partid_t partid, int ch_number, u32 flags, void **payload)
++{
++ return xpc_interface.allocate(partid, ch_number, flags, payload);
++}
++
++static inline enum xpc_retval
++xpc_send(partid_t partid, int ch_number, void *payload)
++{
++ return xpc_interface.send(partid, ch_number, payload);
++}
++
++static inline enum xpc_retval
++xpc_send_notify(partid_t partid, int ch_number, void *payload,
++ xpc_notify_func func, void *key)
++{
++ return xpc_interface.send_notify(partid, ch_number, payload, func, key);
++}
++
++static inline void
++xpc_received(partid_t partid, int ch_number, void *payload)
++{
++ return xpc_interface.received(partid, ch_number, payload);
++}
++
++static inline enum xpc_retval
++xpc_partid_to_nasids(partid_t partid, void *nasids)
++{
++ return xpc_interface.partid_to_nasids(partid, nasids);
++}
++
++extern u64 xp_nofault_PIOR_target;
++extern int xp_nofault_PIOR(void *);
++extern int xp_error_PIOR(void);
++
++#endif /* _DRIVERS_MISC_SGIXP_XP_H */
+diff --git a/drivers/misc/sgi-xp/xp_main.c b/drivers/misc/sgi-xp/xp_main.c
+new file mode 100644
+index 0000000..1fbf99b
+--- /dev/null
++++ b/drivers/misc/sgi-xp/xp_main.c
+@@ -0,0 +1,279 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (c) 2004-2008 Silicon Graphics, Inc. All Rights Reserved.
++ */
++
++/*
++ * Cross Partition (XP) base.
++ *
++ * XP provides a base from which its users can interact
++ * with XPC, yet not be dependent on XPC.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/interrupt.h>
++#include <linux/module.h>
++#include <linux/mutex.h>
++#include <asm/sn/intr.h>
++#include <asm/sn/sn_sal.h>
++#include "xp.h"
++
++/*
++ * The export of xp_nofault_PIOR needs to happen here since it is defined
++ * in drivers/misc/sgi-xp/xp_nofault.S. The target of the nofault read is
++ * defined here.
++ */
++EXPORT_SYMBOL_GPL(xp_nofault_PIOR);
++
++u64 xp_nofault_PIOR_target;
++EXPORT_SYMBOL_GPL(xp_nofault_PIOR_target);
++
++/*
++ * xpc_registrations[] keeps track of xpc_connect()'s done by the kernel-level
++ * users of XPC.
++ */
++struct xpc_registration xpc_registrations[XPC_NCHANNELS];
++EXPORT_SYMBOL_GPL(xpc_registrations);
++
++/*
++ * Initialize the XPC interface to indicate that XPC isn't loaded.
++ */
++static enum xpc_retval
++xpc_notloaded(void)
++{
++ return xpcNotLoaded;
++}
++
++struct xpc_interface xpc_interface = {
++ (void (*)(int))xpc_notloaded,
++ (void (*)(int))xpc_notloaded,
++ (enum xpc_retval(*)(partid_t, int, u32, void **))xpc_notloaded,
++ (enum xpc_retval(*)(partid_t, int, void *))xpc_notloaded,
++ (enum xpc_retval(*)(partid_t, int, void *, xpc_notify_func, void *))
++ xpc_notloaded,
++ (void (*)(partid_t, int, void *))xpc_notloaded,
++ (enum xpc_retval(*)(partid_t, void *))xpc_notloaded
++};
++EXPORT_SYMBOL_GPL(xpc_interface);
++
++/*
++ * XPC calls this when it (the XPC module) has been loaded.
++ */
++void
++xpc_set_interface(void (*connect) (int),
++ void (*disconnect) (int),
++ enum xpc_retval (*allocate) (partid_t, int, u32, void **),
++ enum xpc_retval (*send) (partid_t, int, void *),
++ enum xpc_retval (*send_notify) (partid_t, int, void *,
++ xpc_notify_func, void *),
++ void (*received) (partid_t, int, void *),
++ enum xpc_retval (*partid_to_nasids) (partid_t, void *))
++{
++ xpc_interface.connect = connect;
++ xpc_interface.disconnect = disconnect;
++ xpc_interface.allocate = allocate;
++ xpc_interface.send = send;
++ xpc_interface.send_notify = send_notify;
++ xpc_interface.received = received;
++ xpc_interface.partid_to_nasids = partid_to_nasids;
++}
++EXPORT_SYMBOL_GPL(xpc_set_interface);
++
++/*
++ * XPC calls this when it (the XPC module) is being unloaded.
++ */
++void
++xpc_clear_interface(void)
++{
++ xpc_interface.connect = (void (*)(int))xpc_notloaded;
++ xpc_interface.disconnect = (void (*)(int))xpc_notloaded;
++ xpc_interface.allocate = (enum xpc_retval(*)(partid_t, int, u32,
++ void **))xpc_notloaded;
++ xpc_interface.send = (enum xpc_retval(*)(partid_t, int, void *))
++ xpc_notloaded;
++ xpc_interface.send_notify = (enum xpc_retval(*)(partid_t, int, void *,
++ xpc_notify_func,
++ void *))xpc_notloaded;
++ xpc_interface.received = (void (*)(partid_t, int, void *))
++ xpc_notloaded;
++ xpc_interface.partid_to_nasids = (enum xpc_retval(*)(partid_t, void *))
++ xpc_notloaded;
++}
++EXPORT_SYMBOL_GPL(xpc_clear_interface);
++
++/*
++ * Register for automatic establishment of a channel connection whenever
++ * a partition comes up.
++ *
++ * Arguments:
++ *
++ * ch_number - channel # to register for connection.
++ * func - function to call for asynchronous notification of channel
++ * state changes (i.e., connection, disconnection, error) and
++ * the arrival of incoming messages.
++ * key - pointer to optional user-defined value that gets passed back
++ * to the user on any callouts made to func.
++ * payload_size - size in bytes of the XPC message's payload area which
++ * contains a user-defined message. The user should make
++ * this large enough to hold their largest message.
++ * nentries - max #of XPC message entries a message queue can contain.
++ * The actual number, which is determined when a connection
++ * is established and may be less then requested, will be
++ * passed to the user via the xpcConnected callout.
++ * assigned_limit - max number of kthreads allowed to be processing
++ * messages (per connection) at any given instant.
++ * idle_limit - max number of kthreads allowed to be idle at any given
++ * instant.
++ */
++enum xpc_retval
++xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
++ u16 nentries, u32 assigned_limit, u32 idle_limit)
++{
++ struct xpc_registration *registration;
++
++ DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
++ DBUG_ON(payload_size == 0 || nentries == 0);
++ DBUG_ON(func == NULL);
++ DBUG_ON(assigned_limit == 0 || idle_limit > assigned_limit);
++
++ registration = &xpc_registrations[ch_number];
++
++ if (mutex_lock_interruptible(®istration->mutex) != 0)
++ return xpcInterrupted;
++
++ /* if XPC_CHANNEL_REGISTERED(ch_number) */
++ if (registration->func != NULL) {
++ mutex_unlock(®istration->mutex);
++ return xpcAlreadyRegistered;
++ }
++
++ /* register the channel for connection */
++ registration->msg_size = XPC_MSG_SIZE(payload_size);
++ registration->nentries = nentries;
++ registration->assigned_limit = assigned_limit;
++ registration->idle_limit = idle_limit;
++ registration->key = key;
++ registration->func = func;
++
++ mutex_unlock(®istration->mutex);
++
++ xpc_interface.connect(ch_number);
++
++ return xpcSuccess;
++}
++EXPORT_SYMBOL_GPL(xpc_connect);
++
++/*
++ * Remove the registration for automatic connection of the specified channel
++ * when a partition comes up.
++ *
++ * Before returning this xpc_disconnect() will wait for all connections on the
++ * specified channel have been closed/torndown. So the caller can be assured
++ * that they will not be receiving any more callouts from XPC to their
++ * function registered via xpc_connect().
++ *
++ * Arguments:
++ *
++ * ch_number - channel # to unregister.
++ */
++void
++xpc_disconnect(int ch_number)
++{
++ struct xpc_registration *registration;
++
++ DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
++
++ registration = &xpc_registrations[ch_number];
++
++ /*
++ * We've decided not to make this a down_interruptible(), since we
++ * figured XPC's users will just turn around and call xpc_disconnect()
++ * again anyways, so we might as well wait, if need be.
++ */
++ mutex_lock(®istration->mutex);
++
++ /* if !XPC_CHANNEL_REGISTERED(ch_number) */
++ if (registration->func == NULL) {
++ mutex_unlock(®istration->mutex);
++ return;
++ }
++
++ /* remove the connection registration for the specified channel */
++ registration->func = NULL;
++ registration->key = NULL;
++ registration->nentries = 0;
++ registration->msg_size = 0;
++ registration->assigned_limit = 0;
++ registration->idle_limit = 0;
++
++ xpc_interface.disconnect(ch_number);
++
++ mutex_unlock(®istration->mutex);
++
++ return;
++}
++EXPORT_SYMBOL_GPL(xpc_disconnect);
++
++int __init
++xp_init(void)
++{
++ int ret, ch_number;
++ u64 func_addr = *(u64 *)xp_nofault_PIOR;
++ u64 err_func_addr = *(u64 *)xp_error_PIOR;
++
++ if (!ia64_platform_is("sn2"))
++ return -ENODEV;
++
++ /*
++ * Register a nofault code region which performs a cross-partition
++ * PIO read. If the PIO read times out, the MCA handler will consume
++ * the error and return to a kernel-provided instruction to indicate
++ * an error. This PIO read exists because it is guaranteed to timeout
++ * if the destination is down (AMO operations do not timeout on at
++ * least some CPUs on Shubs <= v1.2, which unfortunately we have to
++ * work around).
++ */
++ ret = sn_register_nofault_code(func_addr, err_func_addr, err_func_addr,
++ 1, 1);
++ if (ret != 0) {
++ printk(KERN_ERR "XP: can't register nofault code, error=%d\n",
++ ret);
++ }
++ /*
++ * Setup the nofault PIO read target. (There is no special reason why
++ * SH_IPI_ACCESS was selected.)
++ */
++ if (is_shub2())
++ xp_nofault_PIOR_target = SH2_IPI_ACCESS0;
++ else
++ xp_nofault_PIOR_target = SH1_IPI_ACCESS;
++
++ /* initialize the connection registration mutex */
++ for (ch_number = 0; ch_number < XPC_NCHANNELS; ch_number++)
++ mutex_init(&xpc_registrations[ch_number].mutex);
++
++ return 0;
++}
++
++module_init(xp_init);
++
++void __exit
++xp_exit(void)
++{
++ u64 func_addr = *(u64 *)xp_nofault_PIOR;
++ u64 err_func_addr = *(u64 *)xp_error_PIOR;
++
++ /* unregister the PIO read nofault code region */
++ (void)sn_register_nofault_code(func_addr, err_func_addr,
++ err_func_addr, 1, 0);
++}
++
++module_exit(xp_exit);
++
++MODULE_AUTHOR("Silicon Graphics, Inc.");
++MODULE_DESCRIPTION("Cross Partition (XP) base");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/misc/sgi-xp/xp_nofault.S b/drivers/misc/sgi-xp/xp_nofault.S
+new file mode 100644
+index 0000000..e38d433
+--- /dev/null
++++ b/drivers/misc/sgi-xp/xp_nofault.S
+@@ -0,0 +1,35 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (c) 2004-2008 Silicon Graphics, Inc. All Rights Reserved.
++ */
++
++/*
++ * The xp_nofault_PIOR function takes a pointer to a remote PIO register
++ * and attempts to load and consume a value from it. This function
++ * will be registered as a nofault code block. In the event that the
++ * PIO read fails, the MCA handler will force the error to look
++ * corrected and vector to the xp_error_PIOR which will return an error.
++ *
++ * The definition of "consumption" and the time it takes for an MCA
++ * to surface is processor implementation specific. This code
++ * is sufficient on Itanium through the Montvale processor family.
++ * It may need to be adjusted for future processor implementations.
++ *
++ * extern int xp_nofault_PIOR(void *remote_register);
++ */
++
++ .global xp_nofault_PIOR
++xp_nofault_PIOR:
++ mov r8=r0 // Stage a success return value
++ ld8.acq r9=[r32];; // PIO Read the specified register
++ adds r9=1,r9;; // Add to force consumption
++ srlz.i;; // Allow time for MCA to surface
++ br.ret.sptk.many b0;; // Return success
++
++ .global xp_error_PIOR
++xp_error_PIOR:
++ mov r8=1 // Return value of 1
++ br.ret.sptk.many b0;; // Return failure
+diff --git a/drivers/misc/sgi-xp/xpc.h b/drivers/misc/sgi-xp/xpc.h
+new file mode 100644
+index 0000000..9eb6d4a
+--- /dev/null
++++ b/drivers/misc/sgi-xp/xpc.h
+@@ -0,0 +1,1187 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (c) 2004-2008 Silicon Graphics, Inc. All Rights Reserved.
++ */
++
++/*
++ * Cross Partition Communication (XPC) structures and macros.
++ */
++
++#ifndef _DRIVERS_MISC_SGIXP_XPC_H
++#define _DRIVERS_MISC_SGIXP_XPC_H
++
++#include <linux/interrupt.h>
++#include <linux/sysctl.h>
++#include <linux/device.h>
++#include <linux/mutex.h>
++#include <linux/completion.h>
++#include <asm/pgtable.h>
++#include <asm/processor.h>
++#include <asm/sn/bte.h>
++#include <asm/sn/clksupport.h>
++#include <asm/sn/addrs.h>
++#include <asm/sn/mspec.h>
++#include <asm/sn/shub_mmr.h>
++#include "xp.h"
++
++/*
++ * XPC Version numbers consist of a major and minor number. XPC can always
++ * talk to versions with same major #, and never talk to versions with a
++ * different major #.
++ */
++#define _XPC_VERSION(_maj, _min) (((_maj) << 4) | ((_min) & 0xf))
++#define XPC_VERSION_MAJOR(_v) ((_v) >> 4)
++#define XPC_VERSION_MINOR(_v) ((_v) & 0xf)
++
++/*
++ * The next macros define word or bit representations for given
++ * C-brick nasid in either the SAL provided bit array representing
++ * nasids in the partition/machine or the AMO_t array used for
++ * inter-partition initiation communications.
++ *
++ * For SN2 machines, C-Bricks are alway even numbered NASIDs. As
++ * such, some space will be saved by insisting that nasid information
++ * passed from SAL always be packed for C-Bricks and the
++ * cross-partition interrupts use the same packing scheme.
++ */
++#define XPC_NASID_W_INDEX(_n) (((_n) / 64) / 2)
++#define XPC_NASID_B_INDEX(_n) (((_n) / 2) & (64 - 1))
++#define XPC_NASID_IN_ARRAY(_n, _p) ((_p)[XPC_NASID_W_INDEX(_n)] & \
++ (1UL << XPC_NASID_B_INDEX(_n)))
++#define XPC_NASID_FROM_W_B(_w, _b) (((_w) * 64 + (_b)) * 2)
++
++#define XPC_HB_DEFAULT_INTERVAL 5 /* incr HB every x secs */
++#define XPC_HB_CHECK_DEFAULT_INTERVAL 20 /* check HB every x secs */
++
++/* define the process name of HB checker and the CPU it is pinned to */
++#define XPC_HB_CHECK_THREAD_NAME "xpc_hb"
++#define XPC_HB_CHECK_CPU 0
++
++/* define the process name of the discovery thread */
++#define XPC_DISCOVERY_THREAD_NAME "xpc_discovery"
++
++/*
++ * the reserved page
++ *
++ * SAL reserves one page of memory per partition for XPC. Though a full page
++ * in length (16384 bytes), its starting address is not page aligned, but it
++ * is cacheline aligned. The reserved page consists of the following:
++ *
++ * reserved page header
++ *
++ * The first cacheline of the reserved page contains the header
++ * (struct xpc_rsvd_page). Before SAL initialization has completed,
++ * SAL has set up the following fields of the reserved page header:
++ * SAL_signature, SAL_version, partid, and nasids_size. The other
++ * fields are set up by XPC. (xpc_rsvd_page points to the local
++ * partition's reserved page.)
++ *
++ * part_nasids mask
++ * mach_nasids mask
++ *
++ * SAL also sets up two bitmaps (or masks), one that reflects the actual
++ * nasids in this partition (part_nasids), and the other that reflects
++ * the actual nasids in the entire machine (mach_nasids). We're only
++ * interested in the even numbered nasids (which contain the processors
++ * and/or memory), so we only need half as many bits to represent the
++ * nasids. The part_nasids mask is located starting at the first cacheline
++ * following the reserved page header. The mach_nasids mask follows right
++ * after the part_nasids mask. The size in bytes of each mask is reflected
++ * by the reserved page header field 'nasids_size'. (Local partition's
++ * mask pointers are xpc_part_nasids and xpc_mach_nasids.)
++ *
++ * vars
++ * vars part
++ *
++ * Immediately following the mach_nasids mask are the XPC variables
++ * required by other partitions. First are those that are generic to all
++ * partitions (vars), followed on the next available cacheline by those
++ * which are partition specific (vars part). These are setup by XPC.
++ * (Local partition's vars pointers are xpc_vars and xpc_vars_part.)
++ *
++ * Note: Until vars_pa is set, the partition XPC code has not been initialized.
++ */
++struct xpc_rsvd_page {
++ u64 SAL_signature; /* SAL: unique signature */
++ u64 SAL_version; /* SAL: version */
++ u8 partid; /* SAL: partition ID */
++ u8 version;
++ u8 pad1[6]; /* align to next u64 in cacheline */
++ u64 vars_pa; /* physical address of struct xpc_vars */
++ struct timespec stamp; /* time when reserved page was setup by XPC */
++ u64 pad2[9]; /* align to last u64 in cacheline */
++ u64 nasids_size; /* SAL: size of each nasid mask in bytes */
++};
++
++#define XPC_RP_VERSION _XPC_VERSION(1, 1) /* version 1.1 of the reserved page */
++
++#define XPC_SUPPORTS_RP_STAMP(_version) \
++ (_version >= _XPC_VERSION(1, 1))
++
++/*
++ * compare stamps - the return value is:
++ *
++ * < 0, if stamp1 < stamp2
++ * = 0, if stamp1 == stamp2
++ * > 0, if stamp1 > stamp2
++ */
++static inline int
++xpc_compare_stamps(struct timespec *stamp1, struct timespec *stamp2)
++{
++ int ret;
++
++ ret = stamp1->tv_sec - stamp2->tv_sec;
++ if (ret == 0)
++ ret = stamp1->tv_nsec - stamp2->tv_nsec;
++
++ return ret;
++}
++
++/*
++ * Define the structures by which XPC variables can be exported to other
++ * partitions. (There are two: struct xpc_vars and struct xpc_vars_part)
++ */
++
++/*
++ * The following structure describes the partition generic variables
++ * needed by other partitions in order to properly initialize.
++ *
++ * struct xpc_vars version number also applies to struct xpc_vars_part.
++ * Changes to either structure and/or related functionality should be
++ * reflected by incrementing either the major or minor version numbers
++ * of struct xpc_vars.
++ */
++struct xpc_vars {
++ u8 version;
++ u64 heartbeat;
++ u64 heartbeating_to_mask;
++ u64 heartbeat_offline; /* if 0, heartbeat should be changing */
++ int act_nasid;
++ int act_phys_cpuid;
++ u64 vars_part_pa;
++ u64 amos_page_pa; /* paddr of page of AMOs from MSPEC driver */
++ AMO_t *amos_page; /* vaddr of page of AMOs from MSPEC driver */
++};
++
++#define XPC_V_VERSION _XPC_VERSION(3, 1) /* version 3.1 of the cross vars */
++
++#define XPC_SUPPORTS_DISENGAGE_REQUEST(_version) \
++ (_version >= _XPC_VERSION(3, 1))
++
++static inline int
++xpc_hb_allowed(partid_t partid, struct xpc_vars *vars)
++{
++ return ((vars->heartbeating_to_mask & (1UL << partid)) != 0);
++}
++
++static inline void
++xpc_allow_hb(partid_t partid, struct xpc_vars *vars)
++{
++ u64 old_mask, new_mask;
++
++ do {
++ old_mask = vars->heartbeating_to_mask;
++ new_mask = (old_mask | (1UL << partid));
++ } while (cmpxchg(&vars->heartbeating_to_mask, old_mask, new_mask) !=
++ old_mask);
++}
++
++static inline void
++xpc_disallow_hb(partid_t partid, struct xpc_vars *vars)
++{
++ u64 old_mask, new_mask;
++
++ do {
++ old_mask = vars->heartbeating_to_mask;
++ new_mask = (old_mask & ~(1UL << partid));
++ } while (cmpxchg(&vars->heartbeating_to_mask, old_mask, new_mask) !=
++ old_mask);
++}
++
++/*
++ * The AMOs page consists of a number of AMO variables which are divided into
++ * four groups, The first two groups are used to identify an IRQ's sender.
++ * These two groups consist of 64 and 128 AMO variables respectively. The last
++ * two groups, consisting of just one AMO variable each, are used to identify
++ * the remote partitions that are currently engaged (from the viewpoint of
++ * the XPC running on the remote partition).
++ */
++#define XPC_NOTIFY_IRQ_AMOS 0
++#define XPC_ACTIVATE_IRQ_AMOS (XPC_NOTIFY_IRQ_AMOS + XP_MAX_PARTITIONS)
++#define XPC_ENGAGED_PARTITIONS_AMO (XPC_ACTIVATE_IRQ_AMOS + XP_NASID_MASK_WORDS)
++#define XPC_DISENGAGE_REQUEST_AMO (XPC_ENGAGED_PARTITIONS_AMO + 1)
++
++/*
++ * The following structure describes the per partition specific variables.
++ *
++ * An array of these structures, one per partition, will be defined. As a
++ * partition becomes active XPC will copy the array entry corresponding to
++ * itself from that partition. It is desirable that the size of this
++ * structure evenly divide into a cacheline, such that none of the entries
++ * in this array crosses a cacheline boundary. As it is now, each entry
++ * occupies half a cacheline.
++ */
++struct xpc_vars_part {
++ u64 magic;
++
++ u64 openclose_args_pa; /* physical address of open and close args */
++ u64 GPs_pa; /* physical address of Get/Put values */
++
++ u64 IPI_amo_pa; /* physical address of IPI AMO_t structure */
++ int IPI_nasid; /* nasid of where to send IPIs */
++ int IPI_phys_cpuid; /* physical CPU ID of where to send IPIs */
++
++ u8 nchannels; /* #of defined channels supported */
++
++ u8 reserved[23]; /* pad to a full 64 bytes */
++};
++
++/*
++ * The vars_part MAGIC numbers play a part in the first contact protocol.
++ *
++ * MAGIC1 indicates that the per partition specific variables for a remote
++ * partition have been initialized by this partition.
++ *
++ * MAGIC2 indicates that this partition has pulled the remote partititions
++ * per partition variables that pertain to this partition.
++ */
++#define XPC_VP_MAGIC1 0x0053524156435058L /* 'XPCVARS\0'L (little endian) */
++#define XPC_VP_MAGIC2 0x0073726176435058L /* 'XPCvars\0'L (little endian) */
++
++/* the reserved page sizes and offsets */
++
++#define XPC_RP_HEADER_SIZE L1_CACHE_ALIGN(sizeof(struct xpc_rsvd_page))
++#define XPC_RP_VARS_SIZE L1_CACHE_ALIGN(sizeof(struct xpc_vars))
++
++#define XPC_RP_PART_NASIDS(_rp) ((u64 *)((u8 *)(_rp) + XPC_RP_HEADER_SIZE))
++#define XPC_RP_MACH_NASIDS(_rp) (XPC_RP_PART_NASIDS(_rp) + xp_nasid_mask_words)
++#define XPC_RP_VARS(_rp) ((struct xpc_vars *)(XPC_RP_MACH_NASIDS(_rp) + \
++ xp_nasid_mask_words))
++#define XPC_RP_VARS_PART(_rp) ((struct xpc_vars_part *) \
++ ((u8 *)XPC_RP_VARS(_rp) + XPC_RP_VARS_SIZE))
++
++/*
++ * Functions registered by add_timer() or called by kernel_thread() only
++ * allow for a single 64-bit argument. The following macros can be used to
++ * pack and unpack two (32-bit, 16-bit or 8-bit) arguments into or out from
++ * the passed argument.
++ */
++#define XPC_PACK_ARGS(_arg1, _arg2) \
++ ((((u64) _arg1) & 0xffffffff) | \
++ ((((u64) _arg2) & 0xffffffff) << 32))
++
++#define XPC_UNPACK_ARG1(_args) (((u64) _args) & 0xffffffff)
++#define XPC_UNPACK_ARG2(_args) ((((u64) _args) >> 32) & 0xffffffff)
++
++/*
++ * Define a Get/Put value pair (pointers) used with a message queue.
++ */
++struct xpc_gp {
++ s64 get; /* Get value */
++ s64 put; /* Put value */
++};
++
++#define XPC_GP_SIZE \
++ L1_CACHE_ALIGN(sizeof(struct xpc_gp) * XPC_NCHANNELS)
++
++/*
++ * Define a structure that contains arguments associated with opening and
++ * closing a channel.
++ */
++struct xpc_openclose_args {
++ u16 reason; /* reason why channel is closing */
++ u16 msg_size; /* sizeof each message entry */
++ u16 remote_nentries; /* #of message entries in remote msg queue */
++ u16 local_nentries; /* #of message entries in local msg queue */
++ u64 local_msgqueue_pa; /* physical address of local message queue */
++};
++
++#define XPC_OPENCLOSE_ARGS_SIZE \
++ L1_CACHE_ALIGN(sizeof(struct xpc_openclose_args) * XPC_NCHANNELS)
++
++/* struct xpc_msg flags */
++
++#define XPC_M_DONE 0x01 /* msg has been received/consumed */
++#define XPC_M_READY 0x02 /* msg is ready to be sent */
++#define XPC_M_INTERRUPT 0x04 /* send interrupt when msg consumed */
++
++#define XPC_MSG_ADDRESS(_payload) \
++ ((struct xpc_msg *)((u8 *)(_payload) - XPC_MSG_PAYLOAD_OFFSET))
++
++/*
++ * Defines notify entry.
++ *
++ * This is used to notify a message's sender that their message was received
++ * and consumed by the intended recipient.
++ */
++struct xpc_notify {
++ u8 type; /* type of notification */
++
++ /* the following two fields are only used if type == XPC_N_CALL */
++ xpc_notify_func func; /* user's notify function */
++ void *key; /* pointer to user's key */
++};
++
++/* struct xpc_notify type of notification */
++
++#define XPC_N_CALL 0x01 /* notify function provided by user */
++
++/*
++ * Define the structure that manages all the stuff required by a channel. In
++ * particular, they are used to manage the messages sent across the channel.
++ *
++ * This structure is private to a partition, and is NOT shared across the
++ * partition boundary.
++ *
++ * There is an array of these structures for each remote partition. It is
++ * allocated at the time a partition becomes active. The array contains one
++ * of these structures for each potential channel connection to that partition.
++ *
++ * Each of these structures manages two message queues (circular buffers).
++ * They are allocated at the time a channel connection is made. One of
++ * these message queues (local_msgqueue) holds the locally created messages
++ * that are destined for the remote partition. The other of these message
++ * queues (remote_msgqueue) is a locally cached copy of the remote partition's
++ * own local_msgqueue.
++ *
++ * The following is a description of the Get/Put pointers used to manage these
++ * two message queues. Consider the local_msgqueue to be on one partition
++ * and the remote_msgqueue to be its cached copy on another partition. A
++ * description of what each of the lettered areas contains is included.
++ *
++ *
++ * local_msgqueue remote_msgqueue
++ *
++ * |/////////| |/////////|
++ * w_remote_GP.get --> +---------+ |/////////|
++ * | F | |/////////|
++ * remote_GP.get --> +---------+ +---------+ <-- local_GP->get
++ * | | | |
++ * | | | E |
++ * | | | |
++ * | | +---------+ <-- w_local_GP.get
++ * | B | |/////////|
++ * | | |////D////|
++ * | | |/////////|
++ * | | +---------+ <-- w_remote_GP.put
++ * | | |////C////|
++ * local_GP->put --> +---------+ +---------+ <-- remote_GP.put
++ * | | |/////////|
++ * | A | |/////////|
++ * | | |/////////|
++ * w_local_GP.put --> +---------+ |/////////|
++ * |/////////| |/////////|
++ *
++ *
++ * ( remote_GP.[get|put] are cached copies of the remote
++ * partition's local_GP->[get|put], and thus their values can
++ * lag behind their counterparts on the remote partition. )
++ *
++ *
++ * A - Messages that have been allocated, but have not yet been sent to the
++ * remote partition.
++ *
++ * B - Messages that have been sent, but have not yet been acknowledged by the
++ * remote partition as having been received.
++ *
++ * C - Area that needs to be prepared for the copying of sent messages, by
++ * the clearing of the message flags of any previously received messages.
++ *
++ * D - Area into which sent messages are to be copied from the remote
++ * partition's local_msgqueue and then delivered to their intended
++ * recipients. [ To allow for a multi-message copy, another pointer
++ * (next_msg_to_pull) has been added to keep track of the next message
++ * number needing to be copied (pulled). It chases after w_remote_GP.put.
++ * Any messages lying between w_local_GP.get and next_msg_to_pull have
++ * been copied and are ready to be delivered. ]
++ *
++ * E - Messages that have been copied and delivered, but have not yet been
++ * acknowledged by the recipient as having been received.
++ *
++ * F - Messages that have been acknowledged, but XPC has not yet notified the
++ * sender that the message was received by its intended recipient.
++ * This is also an area that needs to be prepared for the allocating of
++ * new messages, by the clearing of the message flags of the acknowledged
++ * messages.
++ */
++struct xpc_channel {
++ partid_t partid; /* ID of remote partition connected */
++ spinlock_t lock; /* lock for updating this structure */
++ u32 flags; /* general flags */
++
++ enum xpc_retval reason; /* reason why channel is disconnect'g */
++ int reason_line; /* line# disconnect initiated from */
++
++ u16 number; /* channel # */
++
++ u16 msg_size; /* sizeof each msg entry */
++ u16 local_nentries; /* #of msg entries in local msg queue */
++ u16 remote_nentries; /* #of msg entries in remote msg queue */
++
++ void *local_msgqueue_base; /* base address of kmalloc'd space */
++ struct xpc_msg *local_msgqueue; /* local message queue */
++ void *remote_msgqueue_base; /* base address of kmalloc'd space */
++ struct xpc_msg *remote_msgqueue; /* cached copy of remote partition's */
++ /* local message queue */
++ u64 remote_msgqueue_pa; /* phys addr of remote partition's */
++ /* local message queue */
++
++ atomic_t references; /* #of external references to queues */
++
++ atomic_t n_on_msg_allocate_wq; /* #on msg allocation wait queue */
++ wait_queue_head_t msg_allocate_wq; /* msg allocation wait queue */
++
++ u8 delayed_IPI_flags; /* IPI flags received, but delayed */
++ /* action until channel disconnected */
++
++ /* queue of msg senders who want to be notified when msg received */
++
++ atomic_t n_to_notify; /* #of msg senders to notify */
++ struct xpc_notify *notify_queue; /* notify queue for messages sent */
++
++ xpc_channel_func func; /* user's channel function */
++ void *key; /* pointer to user's key */
++
++ struct mutex msg_to_pull_mutex; /* next msg to pull serialization */
++ struct completion wdisconnect_wait; /* wait for channel disconnect */
++
++ struct xpc_openclose_args *local_openclose_args; /* args passed on */
++ /* opening or closing of channel */
++
++ /* various flavors of local and remote Get/Put values */
++
++ struct xpc_gp *local_GP; /* local Get/Put values */
++ struct xpc_gp remote_GP; /* remote Get/Put values */
++ struct xpc_gp w_local_GP; /* working local Get/Put values */
++ struct xpc_gp w_remote_GP; /* working remote Get/Put values */
++ s64 next_msg_to_pull; /* Put value of next msg to pull */
++
++ /* kthread management related fields */
++
++ atomic_t kthreads_assigned; /* #of kthreads assigned to channel */
++ u32 kthreads_assigned_limit; /* limit on #of kthreads assigned */
++ atomic_t kthreads_idle; /* #of kthreads idle waiting for work */
++ u32 kthreads_idle_limit; /* limit on #of kthreads idle */
++ atomic_t kthreads_active; /* #of kthreads actively working */
++
++ wait_queue_head_t idle_wq; /* idle kthread wait queue */
++
++} ____cacheline_aligned;
++
++/* struct xpc_channel flags */
++
++#define XPC_C_WASCONNECTED 0x00000001 /* channel was connected */
++
++#define XPC_C_ROPENREPLY 0x00000002 /* remote open channel reply */
++#define XPC_C_OPENREPLY 0x00000004 /* local open channel reply */
++#define XPC_C_ROPENREQUEST 0x00000008 /* remote open channel request */
++#define XPC_C_OPENREQUEST 0x00000010 /* local open channel request */
++
++#define XPC_C_SETUP 0x00000020 /* channel's msgqueues are alloc'd */
++#define XPC_C_CONNECTEDCALLOUT 0x00000040 /* connected callout initiated */
++#define XPC_C_CONNECTEDCALLOUT_MADE \
++ 0x00000080 /* connected callout completed */
++#define XPC_C_CONNECTED 0x00000100 /* local channel is connected */
++#define XPC_C_CONNECTING 0x00000200 /* channel is being connected */
++
++#define XPC_C_RCLOSEREPLY 0x00000400 /* remote close channel reply */
++#define XPC_C_CLOSEREPLY 0x00000800 /* local close channel reply */
++#define XPC_C_RCLOSEREQUEST 0x00001000 /* remote close channel request */
++#define XPC_C_CLOSEREQUEST 0x00002000 /* local close channel request */
++
++#define XPC_C_DISCONNECTED 0x00004000 /* channel is disconnected */
++#define XPC_C_DISCONNECTING 0x00008000 /* channel is being disconnected */
++#define XPC_C_DISCONNECTINGCALLOUT \
++ 0x00010000 /* disconnecting callout initiated */
++#define XPC_C_DISCONNECTINGCALLOUT_MADE \
++ 0x00020000 /* disconnecting callout completed */
++#define XPC_C_WDISCONNECT 0x00040000 /* waiting for channel disconnect */
++
++/*
++ * Manages channels on a partition basis. There is one of these structures
++ * for each partition (a partition will never utilize the structure that
++ * represents itself).
++ */
++struct xpc_partition {
++
++ /* XPC HB infrastructure */
++
++ u8 remote_rp_version; /* version# of partition's rsvd pg */
++ struct timespec remote_rp_stamp; /* time when rsvd pg was initialized */
++ u64 remote_rp_pa; /* phys addr of partition's rsvd pg */
++ u64 remote_vars_pa; /* phys addr of partition's vars */
++ u64 remote_vars_part_pa; /* phys addr of partition's vars part */
++ u64 last_heartbeat; /* HB at last read */
++ u64 remote_amos_page_pa; /* phys addr of partition's amos page */
++ int remote_act_nasid; /* active part's act/deact nasid */
++ int remote_act_phys_cpuid; /* active part's act/deact phys cpuid */
++ u32 act_IRQ_rcvd; /* IRQs since activation */
++ spinlock_t act_lock; /* protect updating of act_state */
++ u8 act_state; /* from XPC HB viewpoint */
++ u8 remote_vars_version; /* version# of partition's vars */
++ enum xpc_retval reason; /* reason partition is deactivating */
++ int reason_line; /* line# deactivation initiated from */
++ int reactivate_nasid; /* nasid in partition to reactivate */
++
++ unsigned long disengage_request_timeout; /* timeout in jiffies */
++ struct timer_list disengage_request_timer;
++
++ /* XPC infrastructure referencing and teardown control */
++
++ u8 setup_state; /* infrastructure setup state */
++ wait_queue_head_t teardown_wq; /* kthread waiting to teardown infra */
++ atomic_t references; /* #of references to infrastructure */
++
++ /*
++ * NONE OF THE PRECEDING FIELDS OF THIS STRUCTURE WILL BE CLEARED WHEN
++ * XPC SETS UP THE NECESSARY INFRASTRUCTURE TO SUPPORT CROSS PARTITION
++ * COMMUNICATION. ALL OF THE FOLLOWING FIELDS WILL BE CLEARED. (THE
++ * 'nchannels' FIELD MUST BE THE FIRST OF THE FIELDS TO BE CLEARED.)
++ */
++
++ u8 nchannels; /* #of defined channels supported */
++ atomic_t nchannels_active; /* #of channels that are not DISCONNECTED */
++ atomic_t nchannels_engaged; /* #of channels engaged with remote part */
++ struct xpc_channel *channels; /* array of channel structures */
++
++ void *local_GPs_base; /* base address of kmalloc'd space */
++ struct xpc_gp *local_GPs; /* local Get/Put values */
++ void *remote_GPs_base; /* base address of kmalloc'd space */
++ struct xpc_gp *remote_GPs; /* copy of remote partition's local */
++ /* Get/Put values */
++ u64 remote_GPs_pa; /* phys address of remote partition's local */
++ /* Get/Put values */
++
++ /* fields used to pass args when opening or closing a channel */
++
++ void *local_openclose_args_base; /* base address of kmalloc'd space */
++ struct xpc_openclose_args *local_openclose_args; /* local's args */
++ void *remote_openclose_args_base; /* base address of kmalloc'd space */
++ struct xpc_openclose_args *remote_openclose_args; /* copy of remote's */
++ /* args */
++ u64 remote_openclose_args_pa; /* phys addr of remote's args */
++
++ /* IPI sending, receiving and handling related fields */
++
++ int remote_IPI_nasid; /* nasid of where to send IPIs */
++ int remote_IPI_phys_cpuid; /* phys CPU ID of where to send IPIs */
++ AMO_t *remote_IPI_amo_va; /* address of remote IPI AMO_t structure */
++
++ AMO_t *local_IPI_amo_va; /* address of IPI AMO_t structure */
++ u64 local_IPI_amo; /* IPI amo flags yet to be handled */
++ char IPI_owner[8]; /* IPI owner's name */
++ struct timer_list dropped_IPI_timer; /* dropped IPI timer */
++
++ spinlock_t IPI_lock; /* IPI handler lock */
++
++ /* channel manager related fields */
++
++ atomic_t channel_mgr_requests; /* #of requests to activate chan mgr */
++ wait_queue_head_t channel_mgr_wq; /* channel mgr's wait queue */
++
++} ____cacheline_aligned;
++
++/* struct xpc_partition act_state values (for XPC HB) */
++
++#define XPC_P_INACTIVE 0x00 /* partition is not active */
++#define XPC_P_ACTIVATION_REQ 0x01 /* created thread to activate */
++#define XPC_P_ACTIVATING 0x02 /* activation thread started */
++#define XPC_P_ACTIVE 0x03 /* xpc_partition_up() was called */
++#define XPC_P_DEACTIVATING 0x04 /* partition deactivation initiated */
++
++#define XPC_DEACTIVATE_PARTITION(_p, _reason) \
++ xpc_deactivate_partition(__LINE__, (_p), (_reason))
++
++/* struct xpc_partition setup_state values */
++
++#define XPC_P_UNSET 0x00 /* infrastructure was never setup */
++#define XPC_P_SETUP 0x01 /* infrastructure is setup */
++#define XPC_P_WTEARDOWN 0x02 /* waiting to teardown infrastructure */
++#define XPC_P_TORNDOWN 0x03 /* infrastructure is torndown */
++
++/*
++ * struct xpc_partition IPI_timer #of seconds to wait before checking for
++ * dropped IPIs. These occur whenever an IPI amo write doesn't complete until
++ * after the IPI was received.
++ */
++#define XPC_P_DROPPED_IPI_WAIT (0.25 * HZ)
++
++/* number of seconds to wait for other partitions to disengage */
++#define XPC_DISENGAGE_REQUEST_DEFAULT_TIMELIMIT 90
++
++/* interval in seconds to print 'waiting disengagement' messages */
++#define XPC_DISENGAGE_PRINTMSG_INTERVAL 10
++
++#define XPC_PARTID(_p) ((partid_t) ((_p) - &xpc_partitions[0]))
++
++/* found in xp_main.c */
++extern struct xpc_registration xpc_registrations[];
++
++/* found in xpc_main.c */
++extern struct device *xpc_part;
++extern struct device *xpc_chan;
++extern int xpc_disengage_request_timelimit;
++extern int xpc_disengage_request_timedout;
++extern irqreturn_t xpc_notify_IRQ_handler(int, void *);
++extern void xpc_dropped_IPI_check(struct xpc_partition *);
++extern void xpc_activate_partition(struct xpc_partition *);
++extern void xpc_activate_kthreads(struct xpc_channel *, int);
++extern void xpc_create_kthreads(struct xpc_channel *, int, int);
++extern void xpc_disconnect_wait(int);
++
++/* found in xpc_partition.c */
++extern int xpc_exiting;
++extern struct xpc_vars *xpc_vars;
++extern struct xpc_rsvd_page *xpc_rsvd_page;
++extern struct xpc_vars_part *xpc_vars_part;
++extern struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1];
++extern char *xpc_remote_copy_buffer;
++extern void *xpc_remote_copy_buffer_base;
++extern void *xpc_kmalloc_cacheline_aligned(size_t, gfp_t, void **);
++extern struct xpc_rsvd_page *xpc_rsvd_page_init(void);
++extern void xpc_allow_IPI_ops(void);
++extern void xpc_restrict_IPI_ops(void);
++extern int xpc_identify_act_IRQ_sender(void);
++extern int xpc_partition_disengaged(struct xpc_partition *);
++extern enum xpc_retval xpc_mark_partition_active(struct xpc_partition *);
++extern void xpc_mark_partition_inactive(struct xpc_partition *);
++extern void xpc_discovery(void);
++extern void xpc_check_remote_hb(void);
++extern void xpc_deactivate_partition(const int, struct xpc_partition *,
++ enum xpc_retval);
++extern enum xpc_retval xpc_initiate_partid_to_nasids(partid_t, void *);
++
++/* found in xpc_channel.c */
++extern void xpc_initiate_connect(int);
++extern void xpc_initiate_disconnect(int);
++extern enum xpc_retval xpc_initiate_allocate(partid_t, int, u32, void **);
++extern enum xpc_retval xpc_initiate_send(partid_t, int, void *);
++extern enum xpc_retval xpc_initiate_send_notify(partid_t, int, void *,
++ xpc_notify_func, void *);
++extern void xpc_initiate_received(partid_t, int, void *);
++extern enum xpc_retval xpc_setup_infrastructure(struct xpc_partition *);
++extern enum xpc_retval xpc_pull_remote_vars_part(struct xpc_partition *);
++extern void xpc_process_channel_activity(struct xpc_partition *);
++extern void xpc_connected_callout(struct xpc_channel *);
++extern void xpc_deliver_msg(struct xpc_channel *);
++extern void xpc_disconnect_channel(const int, struct xpc_channel *,
++ enum xpc_retval, unsigned long *);
++extern void xpc_disconnect_callout(struct xpc_channel *, enum xpc_retval);
++extern void xpc_partition_going_down(struct xpc_partition *, enum xpc_retval);
++extern void xpc_teardown_infrastructure(struct xpc_partition *);
++
++static inline void
++xpc_wakeup_channel_mgr(struct xpc_partition *part)
++{
++ if (atomic_inc_return(&part->channel_mgr_requests) == 1)
++ wake_up(&part->channel_mgr_wq);
++}
++
++/*
++ * These next two inlines are used to keep us from tearing down a channel's
++ * msg queues while a thread may be referencing them.
++ */
++static inline void
++xpc_msgqueue_ref(struct xpc_channel *ch)
++{
++ atomic_inc(&ch->references);
++}
++
++static inline void
++xpc_msgqueue_deref(struct xpc_channel *ch)
++{
++ s32 refs = atomic_dec_return(&ch->references);
++
++ DBUG_ON(refs < 0);
++ if (refs == 0)
++ xpc_wakeup_channel_mgr(&xpc_partitions[ch->partid]);
++}
++
++#define XPC_DISCONNECT_CHANNEL(_ch, _reason, _irqflgs) \
++ xpc_disconnect_channel(__LINE__, _ch, _reason, _irqflgs)
++
++/*
++ * These two inlines are used to keep us from tearing down a partition's
++ * setup infrastructure while a thread may be referencing it.
++ */
++static inline void
++xpc_part_deref(struct xpc_partition *part)
++{
++ s32 refs = atomic_dec_return(&part->references);
++
++ DBUG_ON(refs < 0);
++ if (refs == 0 && part->setup_state == XPC_P_WTEARDOWN)
++ wake_up(&part->teardown_wq);
++}
++
++static inline int
++xpc_part_ref(struct xpc_partition *part)
++{
++ int setup;
++
++ atomic_inc(&part->references);
++ setup = (part->setup_state == XPC_P_SETUP);
++ if (!setup)
++ xpc_part_deref(part);
++
++ return setup;
++}
++
++/*
++ * The following macro is to be used for the setting of the reason and
++ * reason_line fields in both the struct xpc_channel and struct xpc_partition
++ * structures.
++ */
++#define XPC_SET_REASON(_p, _reason, _line) \
++ { \
++ (_p)->reason = _reason; \
++ (_p)->reason_line = _line; \
++ }
++
++/*
++ * This next set of inlines are used to keep track of when a partition is
++ * potentially engaged in accessing memory belonging to another partition.
++ */
++
++static inline void
++xpc_mark_partition_engaged(struct xpc_partition *part)
++{
++ unsigned long irq_flags;
++ AMO_t *amo = (AMO_t *)__va(part->remote_amos_page_pa +
++ (XPC_ENGAGED_PARTITIONS_AMO *
++ sizeof(AMO_t)));
++
++ local_irq_save(irq_flags);
++
++ /* set bit corresponding to our partid in remote partition's AMO */
++ FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_OR,
++ (1UL << sn_partition_id));
++ /*
++ * We must always use the nofault function regardless of whether we
++ * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
++ * didn't, we'd never know that the other partition is down and would
++ * keep sending IPIs and AMOs to it until the heartbeat times out.
++ */
++ (void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
++ variable),
++ xp_nofault_PIOR_target));
++
++ local_irq_restore(irq_flags);
++}
++
++static inline void
++xpc_mark_partition_disengaged(struct xpc_partition *part)
++{
++ unsigned long irq_flags;
++ AMO_t *amo = (AMO_t *)__va(part->remote_amos_page_pa +
++ (XPC_ENGAGED_PARTITIONS_AMO *
++ sizeof(AMO_t)));
++
++ local_irq_save(irq_flags);
++
++ /* clear bit corresponding to our partid in remote partition's AMO */
++ FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
++ ~(1UL << sn_partition_id));
++ /*
++ * We must always use the nofault function regardless of whether we
++ * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
++ * didn't, we'd never know that the other partition is down and would
++ * keep sending IPIs and AMOs to it until the heartbeat times out.
++ */
++ (void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
++ variable),
++ xp_nofault_PIOR_target));
++
++ local_irq_restore(irq_flags);
++}
++
++static inline void
++xpc_request_partition_disengage(struct xpc_partition *part)
++{
++ unsigned long irq_flags;
++ AMO_t *amo = (AMO_t *)__va(part->remote_amos_page_pa +
++ (XPC_DISENGAGE_REQUEST_AMO * sizeof(AMO_t)));
++
++ local_irq_save(irq_flags);
++
++ /* set bit corresponding to our partid in remote partition's AMO */
++ FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_OR,
++ (1UL << sn_partition_id));
++ /*
++ * We must always use the nofault function regardless of whether we
++ * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
++ * didn't, we'd never know that the other partition is down and would
++ * keep sending IPIs and AMOs to it until the heartbeat times out.
++ */
++ (void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
++ variable),
++ xp_nofault_PIOR_target));
++
++ local_irq_restore(irq_flags);
++}
++
++static inline void
++xpc_cancel_partition_disengage_request(struct xpc_partition *part)
++{
++ unsigned long irq_flags;
++ AMO_t *amo = (AMO_t *)__va(part->remote_amos_page_pa +
++ (XPC_DISENGAGE_REQUEST_AMO * sizeof(AMO_t)));
++
++ local_irq_save(irq_flags);
++
++ /* clear bit corresponding to our partid in remote partition's AMO */
++ FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
++ ~(1UL << sn_partition_id));
++ /*
++ * We must always use the nofault function regardless of whether we
++ * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
++ * didn't, we'd never know that the other partition is down and would
++ * keep sending IPIs and AMOs to it until the heartbeat times out.
++ */
++ (void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
++ variable),
++ xp_nofault_PIOR_target));
++
++ local_irq_restore(irq_flags);
++}
++
++static inline u64
++xpc_partition_engaged(u64 partid_mask)
++{
++ AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO;
++
++ /* return our partition's AMO variable ANDed with partid_mask */
++ return (FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) &
++ partid_mask);
++}
++
++static inline u64
++xpc_partition_disengage_requested(u64 partid_mask)
++{
++ AMO_t *amo = xpc_vars->amos_page + XPC_DISENGAGE_REQUEST_AMO;
++
++ /* return our partition's AMO variable ANDed with partid_mask */
++ return (FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) &
++ partid_mask);
++}
++
++static inline void
++xpc_clear_partition_engaged(u64 partid_mask)
++{
++ AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO;
++
++ /* clear bit(s) based on partid_mask in our partition's AMO */
++ FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
++ ~partid_mask);
++}
++
++static inline void
++xpc_clear_partition_disengage_request(u64 partid_mask)
++{
++ AMO_t *amo = xpc_vars->amos_page + XPC_DISENGAGE_REQUEST_AMO;
++
++ /* clear bit(s) based on partid_mask in our partition's AMO */
++ FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
++ ~partid_mask);
++}
++
++/*
++ * The following set of macros and inlines are used for the sending and
++ * receiving of IPIs (also known as IRQs). There are two flavors of IPIs,
++ * one that is associated with partition activity (SGI_XPC_ACTIVATE) and
++ * the other that is associated with channel activity (SGI_XPC_NOTIFY).
++ */
++
++static inline u64
++xpc_IPI_receive(AMO_t *amo)
++{
++ return FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_CLEAR);
++}
++
++static inline enum xpc_retval
++xpc_IPI_send(AMO_t *amo, u64 flag, int nasid, int phys_cpuid, int vector)
++{
++ int ret = 0;
++ unsigned long irq_flags;
++
++ local_irq_save(irq_flags);
++
++ FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_OR, flag);
++ sn_send_IPI_phys(nasid, phys_cpuid, vector, 0);
++
++ /*
++ * We must always use the nofault function regardless of whether we
++ * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
++ * didn't, we'd never know that the other partition is down and would
++ * keep sending IPIs and AMOs to it until the heartbeat times out.
++ */
++ ret = xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->variable),
++ xp_nofault_PIOR_target));
++
++ local_irq_restore(irq_flags);
++
++ return ((ret == 0) ? xpcSuccess : xpcPioReadError);
++}
++
++/*
++ * IPIs associated with SGI_XPC_ACTIVATE IRQ.
++ */
++
++/*
++ * Flag the appropriate AMO variable and send an IPI to the specified node.
++ */
++static inline void
++xpc_activate_IRQ_send(u64 amos_page_pa, int from_nasid, int to_nasid,
++ int to_phys_cpuid)
++{
++ int w_index = XPC_NASID_W_INDEX(from_nasid);
++ int b_index = XPC_NASID_B_INDEX(from_nasid);
++ AMO_t *amos = (AMO_t *)__va(amos_page_pa +
++ (XPC_ACTIVATE_IRQ_AMOS * sizeof(AMO_t)));
++
++ (void)xpc_IPI_send(&amos[w_index], (1UL << b_index), to_nasid,
++ to_phys_cpuid, SGI_XPC_ACTIVATE);
++}
++
++static inline void
++xpc_IPI_send_activate(struct xpc_vars *vars)
++{
++ xpc_activate_IRQ_send(vars->amos_page_pa, cnodeid_to_nasid(0),
++ vars->act_nasid, vars->act_phys_cpuid);
++}
++
++static inline void
++xpc_IPI_send_activated(struct xpc_partition *part)
++{
++ xpc_activate_IRQ_send(part->remote_amos_page_pa, cnodeid_to_nasid(0),
++ part->remote_act_nasid,
++ part->remote_act_phys_cpuid);
++}
++
++static inline void
++xpc_IPI_send_reactivate(struct xpc_partition *part)
++{
++ xpc_activate_IRQ_send(xpc_vars->amos_page_pa, part->reactivate_nasid,
++ xpc_vars->act_nasid, xpc_vars->act_phys_cpuid);
++}
++
++static inline void
++xpc_IPI_send_disengage(struct xpc_partition *part)
++{
++ xpc_activate_IRQ_send(part->remote_amos_page_pa, cnodeid_to_nasid(0),
++ part->remote_act_nasid,
++ part->remote_act_phys_cpuid);
++}
++
++/*
++ * IPIs associated with SGI_XPC_NOTIFY IRQ.
++ */
++
++/*
++ * Send an IPI to the remote partition that is associated with the
++ * specified channel.
++ */
++#define XPC_NOTIFY_IRQ_SEND(_ch, _ipi_f, _irq_f) \
++ xpc_notify_IRQ_send(_ch, _ipi_f, #_ipi_f, _irq_f)
++
++static inline void
++xpc_notify_IRQ_send(struct xpc_channel *ch, u8 ipi_flag, char *ipi_flag_string,
++ unsigned long *irq_flags)
++{
++ struct xpc_partition *part = &xpc_partitions[ch->partid];
++ enum xpc_retval ret;
++
++ if (likely(part->act_state != XPC_P_DEACTIVATING)) {
++ ret = xpc_IPI_send(part->remote_IPI_amo_va,
++ (u64)ipi_flag << (ch->number * 8),
++ part->remote_IPI_nasid,
++ part->remote_IPI_phys_cpuid, SGI_XPC_NOTIFY);
++ dev_dbg(xpc_chan, "%s sent to partid=%d, channel=%d, ret=%d\n",
++ ipi_flag_string, ch->partid, ch->number, ret);
++ if (unlikely(ret != xpcSuccess)) {
++ if (irq_flags != NULL)
++ spin_unlock_irqrestore(&ch->lock, *irq_flags);
++ XPC_DEACTIVATE_PARTITION(part, ret);
++ if (irq_flags != NULL)
++ spin_lock_irqsave(&ch->lock, *irq_flags);
++ }
++ }
++}
++
++/*
++ * Make it look like the remote partition, which is associated with the
++ * specified channel, sent us an IPI. This faked IPI will be handled
++ * by xpc_dropped_IPI_check().
++ */
++#define XPC_NOTIFY_IRQ_SEND_LOCAL(_ch, _ipi_f) \
++ xpc_notify_IRQ_send_local(_ch, _ipi_f, #_ipi_f)
++
++static inline void
++xpc_notify_IRQ_send_local(struct xpc_channel *ch, u8 ipi_flag,
++ char *ipi_flag_string)
++{
++ struct xpc_partition *part = &xpc_partitions[ch->partid];
++
++ FETCHOP_STORE_OP(TO_AMO((u64)&part->local_IPI_amo_va->variable),
++ FETCHOP_OR, ((u64)ipi_flag << (ch->number * 8)));
++ dev_dbg(xpc_chan, "%s sent local from partid=%d, channel=%d\n",
++ ipi_flag_string, ch->partid, ch->number);
++}
++
++/*
++ * The sending and receiving of IPIs includes the setting of an AMO variable
++ * to indicate the reason the IPI was sent. The 64-bit variable is divided
++ * up into eight bytes, ordered from right to left. Byte zero pertains to
++ * channel 0, byte one to channel 1, and so on. Each byte is described by
++ * the following IPI flags.
++ */
++
++#define XPC_IPI_CLOSEREQUEST 0x01
++#define XPC_IPI_CLOSEREPLY 0x02
++#define XPC_IPI_OPENREQUEST 0x04
++#define XPC_IPI_OPENREPLY 0x08
++#define XPC_IPI_MSGREQUEST 0x10
++
++/* given an AMO variable and a channel#, get its associated IPI flags */
++#define XPC_GET_IPI_FLAGS(_amo, _c) ((u8) (((_amo) >> ((_c) * 8)) & 0xff))
++#define XPC_SET_IPI_FLAGS(_amo, _c, _f) (_amo) |= ((u64) (_f) << ((_c) * 8))
++
++#define XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(_amo) ((_amo) & 0x0f0f0f0f0f0f0f0fUL)
++#define XPC_ANY_MSG_IPI_FLAGS_SET(_amo) ((_amo) & 0x1010101010101010UL)
++
++static inline void
++xpc_IPI_send_closerequest(struct xpc_channel *ch, unsigned long *irq_flags)
++{
++ struct xpc_openclose_args *args = ch->local_openclose_args;
++
++ args->reason = ch->reason;
++
++ XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_CLOSEREQUEST, irq_flags);
++}
++
++static inline void
++xpc_IPI_send_closereply(struct xpc_channel *ch, unsigned long *irq_flags)
++{
++ XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_CLOSEREPLY, irq_flags);
++}
++
++static inline void
++xpc_IPI_send_openrequest(struct xpc_channel *ch, unsigned long *irq_flags)
++{
++ struct xpc_openclose_args *args = ch->local_openclose_args;
++
++ args->msg_size = ch->msg_size;
++ args->local_nentries = ch->local_nentries;
++
++ XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_OPENREQUEST, irq_flags);
++}
++
++static inline void
++xpc_IPI_send_openreply(struct xpc_channel *ch, unsigned long *irq_flags)
++{
++ struct xpc_openclose_args *args = ch->local_openclose_args;
++
++ args->remote_nentries = ch->remote_nentries;
++ args->local_nentries = ch->local_nentries;
++ args->local_msgqueue_pa = __pa(ch->local_msgqueue);
++
++ XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_OPENREPLY, irq_flags);
++}
++
++static inline void
++xpc_IPI_send_msgrequest(struct xpc_channel *ch)
++{
++ XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_MSGREQUEST, NULL);
++}
++
++static inline void
++xpc_IPI_send_local_msgrequest(struct xpc_channel *ch)
++{
++ XPC_NOTIFY_IRQ_SEND_LOCAL(ch, XPC_IPI_MSGREQUEST);
++}
++
++/*
++ * Memory for XPC's AMO variables is allocated by the MSPEC driver. These
++ * pages are located in the lowest granule. The lowest granule uses 4k pages
++ * for cached references and an alternate TLB handler to never provide a
++ * cacheable mapping for the entire region. This will prevent speculative
++ * reading of cached copies of our lines from being issued which will cause
++ * a PI FSB Protocol error to be generated by the SHUB. For XPC, we need 64
++ * AMO variables (based on XP_MAX_PARTITIONS) for message notification and an
++ * additional 128 AMO variables (based on XP_NASID_MASK_WORDS) for partition
++ * activation and 2 AMO variables for partition deactivation.
++ */
++static inline AMO_t *
++xpc_IPI_init(int index)
++{
++ AMO_t *amo = xpc_vars->amos_page + index;
++
++ (void)xpc_IPI_receive(amo); /* clear AMO variable */
++ return amo;
++}
++
++static inline enum xpc_retval
++xpc_map_bte_errors(bte_result_t error)
++{
++ if (error == BTE_SUCCESS)
++ return xpcSuccess;
++
++ if (is_shub2()) {
++ if (BTE_VALID_SH2_ERROR(error))
++ return xpcBteSh2Start + error;
++ return xpcBteUnmappedError;
++ }
++ switch (error) {
++ case BTE_SUCCESS:
++ return xpcSuccess;
++ case BTEFAIL_DIR:
++ return xpcBteDirectoryError;
++ case BTEFAIL_POISON:
++ return xpcBtePoisonError;
++ case BTEFAIL_WERR:
++ return xpcBteWriteError;
++ case BTEFAIL_ACCESS:
++ return xpcBteAccessError;
++ case BTEFAIL_PWERR:
++ return xpcBtePWriteError;
++ case BTEFAIL_PRERR:
++ return xpcBtePReadError;
++ case BTEFAIL_TOUT:
++ return xpcBteTimeOutError;
++ case BTEFAIL_XTERR:
++ return xpcBteXtalkError;
++ case BTEFAIL_NOTAVAIL:
++ return xpcBteNotAvailable;
++ default:
++ return xpcBteUnmappedError;
++ }
++}
++
++/*
++ * Check to see if there is any channel activity to/from the specified
++ * partition.
++ */
++static inline void
++xpc_check_for_channel_activity(struct xpc_partition *part)
++{
++ u64 IPI_amo;
++ unsigned long irq_flags;
++
++ IPI_amo = xpc_IPI_receive(part->local_IPI_amo_va);
++ if (IPI_amo == 0)
++ return;
++
++ spin_lock_irqsave(&part->IPI_lock, irq_flags);
++ part->local_IPI_amo |= IPI_amo;
++ spin_unlock_irqrestore(&part->IPI_lock, irq_flags);
++
++ dev_dbg(xpc_chan, "received IPI from partid=%d, IPI_amo=0x%lx\n",
++ XPC_PARTID(part), IPI_amo);
++
++ xpc_wakeup_channel_mgr(part);
++}
++
++#endif /* _DRIVERS_MISC_SGIXP_XPC_H */
+diff --git a/drivers/misc/sgi-xp/xpc_channel.c b/drivers/misc/sgi-xp/xpc_channel.c
+new file mode 100644
+index 0000000..bfcb9ea
+--- /dev/null
++++ b/drivers/misc/sgi-xp/xpc_channel.c
+@@ -0,0 +1,2243 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (c) 2004-2008 Silicon Graphics, Inc. All Rights Reserved.
++ */
++
++/*
++ * Cross Partition Communication (XPC) channel support.
++ *
++ * This is the part of XPC that manages the channels and
++ * sends/receives messages across them to/from other partitions.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/cache.h>
++#include <linux/interrupt.h>
++#include <linux/mutex.h>
++#include <linux/completion.h>
++#include <asm/sn/bte.h>
++#include <asm/sn/sn_sal.h>
++#include "xpc.h"
++
++/*
++ * Guarantee that the kzalloc'd memory is cacheline aligned.
++ */
++static void *
++xpc_kzalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
++{
++ /* see if kzalloc will give us cachline aligned memory by default */
++ *base = kzalloc(size, flags);
++ if (*base == NULL)
++ return NULL;
++
++ if ((u64)*base == L1_CACHE_ALIGN((u64)*base))
++ return *base;
++
++ kfree(*base);
++
++ /* nope, we'll have to do it ourselves */
++ *base = kzalloc(size + L1_CACHE_BYTES, flags);
++ if (*base == NULL)
++ return NULL;
++
++ return (void *)L1_CACHE_ALIGN((u64)*base);
++}
++
++/*
++ * Set up the initial values for the XPartition Communication channels.
++ */
++static void
++xpc_initialize_channels(struct xpc_partition *part, partid_t partid)
++{
++ int ch_number;
++ struct xpc_channel *ch;
++
++ for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
++ ch = &part->channels[ch_number];
++
++ ch->partid = partid;
++ ch->number = ch_number;
++ ch->flags = XPC_C_DISCONNECTED;
++
++ ch->local_GP = &part->local_GPs[ch_number];
++ ch->local_openclose_args =
++ &part->local_openclose_args[ch_number];
++
++ atomic_set(&ch->kthreads_assigned, 0);
++ atomic_set(&ch->kthreads_idle, 0);
++ atomic_set(&ch->kthreads_active, 0);
++
++ atomic_set(&ch->references, 0);
++ atomic_set(&ch->n_to_notify, 0);
++
++ spin_lock_init(&ch->lock);
++ mutex_init(&ch->msg_to_pull_mutex);
++ init_completion(&ch->wdisconnect_wait);
++
++ atomic_set(&ch->n_on_msg_allocate_wq, 0);
++ init_waitqueue_head(&ch->msg_allocate_wq);
++ init_waitqueue_head(&ch->idle_wq);
++ }
++}
++
++/*
++ * Setup the infrastructure necessary to support XPartition Communication
++ * between the specified remote partition and the local one.
++ */
++enum xpc_retval
++xpc_setup_infrastructure(struct xpc_partition *part)
++{
++ int ret, cpuid;
++ struct timer_list *timer;
++ partid_t partid = XPC_PARTID(part);
++
++ /*
++ * Zero out MOST of the entry for this partition. Only the fields
++ * starting with `nchannels' will be zeroed. The preceding fields must
++ * remain `viable' across partition ups and downs, since they may be
++ * referenced during this memset() operation.
++ */
++ memset(&part->nchannels, 0, sizeof(struct xpc_partition) -
++ offsetof(struct xpc_partition, nchannels));
++
++ /*
++ * Allocate all of the channel structures as a contiguous chunk of
++ * memory.
++ */
++ part->channels = kzalloc(sizeof(struct xpc_channel) * XPC_NCHANNELS,
++ GFP_KERNEL);
++ if (part->channels == NULL) {
++ dev_err(xpc_chan, "can't get memory for channels\n");
++ return xpcNoMemory;
++ }
++
++ part->nchannels = XPC_NCHANNELS;
++
++ /* allocate all the required GET/PUT values */
++
++ part->local_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE,
++ GFP_KERNEL,
++ &part->local_GPs_base);
++ if (part->local_GPs == NULL) {
++ kfree(part->channels);
++ part->channels = NULL;
++ dev_err(xpc_chan, "can't get memory for local get/put "
++ "values\n");
++ return xpcNoMemory;
++ }
++
++ part->remote_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE,
++ GFP_KERNEL,
++ &part->
++ remote_GPs_base);
++ if (part->remote_GPs == NULL) {
++ dev_err(xpc_chan, "can't get memory for remote get/put "
++ "values\n");
++ kfree(part->local_GPs_base);
++ part->local_GPs = NULL;
++ kfree(part->channels);
++ part->channels = NULL;
++ return xpcNoMemory;
++ }
++
++ /* allocate all the required open and close args */
++
++ part->local_openclose_args =
++ xpc_kzalloc_cacheline_aligned(XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL,
++ &part->local_openclose_args_base);
++ if (part->local_openclose_args == NULL) {
++ dev_err(xpc_chan, "can't get memory for local connect args\n");
++ kfree(part->remote_GPs_base);
++ part->remote_GPs = NULL;
++ kfree(part->local_GPs_base);
++ part->local_GPs = NULL;
++ kfree(part->channels);
++ part->channels = NULL;
++ return xpcNoMemory;
++ }
++
++ part->remote_openclose_args =
++ xpc_kzalloc_cacheline_aligned(XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL,
++ &part->remote_openclose_args_base);
++ if (part->remote_openclose_args == NULL) {
++ dev_err(xpc_chan, "can't get memory for remote connect args\n");
++ kfree(part->local_openclose_args_base);
++ part->local_openclose_args = NULL;
++ kfree(part->remote_GPs_base);
++ part->remote_GPs = NULL;
++ kfree(part->local_GPs_base);
++ part->local_GPs = NULL;
++ kfree(part->channels);
++ part->channels = NULL;
++ return xpcNoMemory;
++ }
++
++ xpc_initialize_channels(part, partid);
++
++ atomic_set(&part->nchannels_active, 0);
++ atomic_set(&part->nchannels_engaged, 0);
++
++ /* local_IPI_amo were set to 0 by an earlier memset() */
++
++ /* Initialize this partitions AMO_t structure */
++ part->local_IPI_amo_va = xpc_IPI_init(partid);
++
++ spin_lock_init(&part->IPI_lock);
++
++ atomic_set(&part->channel_mgr_requests, 1);
++ init_waitqueue_head(&part->channel_mgr_wq);
++
++ sprintf(part->IPI_owner, "xpc%02d", partid);
++ ret = request_irq(SGI_XPC_NOTIFY, xpc_notify_IRQ_handler, IRQF_SHARED,
++ part->IPI_owner, (void *)(u64)partid);
++ if (ret != 0) {
++ dev_err(xpc_chan, "can't register NOTIFY IRQ handler, "
++ "errno=%d\n", -ret);
++ kfree(part->remote_openclose_args_base);
++ part->remote_openclose_args = NULL;
++ kfree(part->local_openclose_args_base);
++ part->local_openclose_args = NULL;
++ kfree(part->remote_GPs_base);
++ part->remote_GPs = NULL;
++ kfree(part->local_GPs_base);
++ part->local_GPs = NULL;
++ kfree(part->channels);
++ part->channels = NULL;
++ return xpcLackOfResources;
++ }
++
++ /* Setup a timer to check for dropped IPIs */
++ timer = &part->dropped_IPI_timer;
++ init_timer(timer);
++ timer->function = (void (*)(unsigned long))xpc_dropped_IPI_check;
++ timer->data = (unsigned long)part;
++ timer->expires = jiffies + XPC_P_DROPPED_IPI_WAIT;
++ add_timer(timer);
++
++ /*
++ * With the setting of the partition setup_state to XPC_P_SETUP, we're
++ * declaring that this partition is ready to go.
++ */
++ part->setup_state = XPC_P_SETUP;
++
++ /*
++ * Setup the per partition specific variables required by the
++ * remote partition to establish channel connections with us.
++ *
++ * The setting of the magic # indicates that these per partition
++ * specific variables are ready to be used.
++ */
++ xpc_vars_part[partid].GPs_pa = __pa(part->local_GPs);
++ xpc_vars_part[partid].openclose_args_pa =
++ __pa(part->local_openclose_args);
++ xpc_vars_part[partid].IPI_amo_pa = __pa(part->local_IPI_amo_va);
++ cpuid = raw_smp_processor_id(); /* any CPU in this partition will do */
++ xpc_vars_part[partid].IPI_nasid = cpuid_to_nasid(cpuid);
++ xpc_vars_part[partid].IPI_phys_cpuid = cpu_physical_id(cpuid);
++ xpc_vars_part[partid].nchannels = part->nchannels;
++ xpc_vars_part[partid].magic = XPC_VP_MAGIC1;
++
++ return xpcSuccess;
++}
++
++/*
++ * Create a wrapper that hides the underlying mechanism for pulling a cacheline
++ * (or multiple cachelines) from a remote partition.
++ *
++ * src must be a cacheline aligned physical address on the remote partition.
++ * dst must be a cacheline aligned virtual address on this partition.
++ * cnt must be an cacheline sized
++ */
++static enum xpc_retval
++xpc_pull_remote_cachelines(struct xpc_partition *part, void *dst,
++ const void *src, size_t cnt)
++{
++ bte_result_t bte_ret;
++
++ DBUG_ON((u64)src != L1_CACHE_ALIGN((u64)src));
++ DBUG_ON((u64)dst != L1_CACHE_ALIGN((u64)dst));
++ DBUG_ON(cnt != L1_CACHE_ALIGN(cnt));
++
++ if (part->act_state == XPC_P_DEACTIVATING)
++ return part->reason;
++
++ bte_ret = xp_bte_copy((u64)src, (u64)dst, (u64)cnt,
++ (BTE_NORMAL | BTE_WACQUIRE), NULL);
++ if (bte_ret == BTE_SUCCESS)
++ return xpcSuccess;
++
++ dev_dbg(xpc_chan, "xp_bte_copy() from partition %d failed, ret=%d\n",
++ XPC_PARTID(part), bte_ret);
++
++ return xpc_map_bte_errors(bte_ret);
++}
++
++/*
++ * Pull the remote per partition specific variables from the specified
++ * partition.
++ */
++enum xpc_retval
++xpc_pull_remote_vars_part(struct xpc_partition *part)
++{
++ u8 buffer[L1_CACHE_BYTES * 2];
++ struct xpc_vars_part *pulled_entry_cacheline =
++ (struct xpc_vars_part *)L1_CACHE_ALIGN((u64)buffer);
++ struct xpc_vars_part *pulled_entry;
++ u64 remote_entry_cacheline_pa, remote_entry_pa;
++ partid_t partid = XPC_PARTID(part);
++ enum xpc_retval ret;
++
++ /* pull the cacheline that contains the variables we're interested in */
++
++ DBUG_ON(part->remote_vars_part_pa !=
++ L1_CACHE_ALIGN(part->remote_vars_part_pa));
++ DBUG_ON(sizeof(struct xpc_vars_part) != L1_CACHE_BYTES / 2);
++
++ remote_entry_pa = part->remote_vars_part_pa +
++ sn_partition_id * sizeof(struct xpc_vars_part);
++
++ remote_entry_cacheline_pa = (remote_entry_pa & ~(L1_CACHE_BYTES - 1));
++
++ pulled_entry = (struct xpc_vars_part *)((u64)pulled_entry_cacheline +
++ (remote_entry_pa &
++ (L1_CACHE_BYTES - 1)));
++
++ ret = xpc_pull_remote_cachelines(part, pulled_entry_cacheline,
++ (void *)remote_entry_cacheline_pa,
++ L1_CACHE_BYTES);
++ if (ret != xpcSuccess) {
++ dev_dbg(xpc_chan, "failed to pull XPC vars_part from "
++ "partition %d, ret=%d\n", partid, ret);
++ return ret;
++ }
++
++ /* see if they've been set up yet */
++
++ if (pulled_entry->magic != XPC_VP_MAGIC1 &&
++ pulled_entry->magic != XPC_VP_MAGIC2) {
++
++ if (pulled_entry->magic != 0) {
++ dev_dbg(xpc_chan, "partition %d's XPC vars_part for "
++ "partition %d has bad magic value (=0x%lx)\n",
++ partid, sn_partition_id, pulled_entry->magic);
++ return xpcBadMagic;
++ }
++
++ /* they've not been initialized yet */
++ return xpcRetry;
++ }
++
++ if (xpc_vars_part[partid].magic == XPC_VP_MAGIC1) {
++
++ /* validate the variables */
++
++ if (pulled_entry->GPs_pa == 0 ||
++ pulled_entry->openclose_args_pa == 0 ||
++ pulled_entry->IPI_amo_pa == 0) {
++
++ dev_err(xpc_chan, "partition %d's XPC vars_part for "
++ "partition %d are not valid\n", partid,
++ sn_partition_id);
++ return xpcInvalidAddress;
++ }
++
++ /* the variables we imported look to be valid */
++
++ part->remote_GPs_pa = pulled_entry->GPs_pa;
++ part->remote_openclose_args_pa =
++ pulled_entry->openclose_args_pa;
++ part->remote_IPI_amo_va =
++ (AMO_t *)__va(pulled_entry->IPI_amo_pa);
++ part->remote_IPI_nasid = pulled_entry->IPI_nasid;
++ part->remote_IPI_phys_cpuid = pulled_entry->IPI_phys_cpuid;
++
++ if (part->nchannels > pulled_entry->nchannels)
++ part->nchannels = pulled_entry->nchannels;
++
++ /* let the other side know that we've pulled their variables */
++
++ xpc_vars_part[partid].magic = XPC_VP_MAGIC2;
++ }
++
++ if (pulled_entry->magic == XPC_VP_MAGIC1)
++ return xpcRetry;
++
++ return xpcSuccess;
++}
++
++/*
++ * Get the IPI flags and pull the openclose args and/or remote GPs as needed.
++ */
++static u64
++xpc_get_IPI_flags(struct xpc_partition *part)
++{
++ unsigned long irq_flags;
++ u64 IPI_amo;
++ enum xpc_retval ret;
++
++ /*
++ * See if there are any IPI flags to be handled.
++ */
++
++ spin_lock_irqsave(&part->IPI_lock, irq_flags);
++ IPI_amo = part->local_IPI_amo;
++ if (IPI_amo != 0)
++ part->local_IPI_amo = 0;
++
++ spin_unlock_irqrestore(&part->IPI_lock, irq_flags);
++
++ if (XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(IPI_amo)) {
++ ret = xpc_pull_remote_cachelines(part,
++ part->remote_openclose_args,
++ (void *)part->
++ remote_openclose_args_pa,
++ XPC_OPENCLOSE_ARGS_SIZE);
++ if (ret != xpcSuccess) {
++ XPC_DEACTIVATE_PARTITION(part, ret);
++
++ dev_dbg(xpc_chan, "failed to pull openclose args from "
++ "partition %d, ret=%d\n", XPC_PARTID(part),
++ ret);
++
++ /* don't bother processing IPIs anymore */
++ IPI_amo = 0;
++ }
++ }
++
++ if (XPC_ANY_MSG_IPI_FLAGS_SET(IPI_amo)) {
++ ret = xpc_pull_remote_cachelines(part, part->remote_GPs,
++ (void *)part->remote_GPs_pa,
++ XPC_GP_SIZE);
++ if (ret != xpcSuccess) {
++ XPC_DEACTIVATE_PARTITION(part, ret);
++
++ dev_dbg(xpc_chan, "failed to pull GPs from partition "
++ "%d, ret=%d\n", XPC_PARTID(part), ret);
++
++ /* don't bother processing IPIs anymore */
++ IPI_amo = 0;
++ }
++ }
++
++ return IPI_amo;
++}
++
++/*
++ * Allocate the local message queue and the notify queue.
++ */
++static enum xpc_retval
++xpc_allocate_local_msgqueue(struct xpc_channel *ch)
++{
++ unsigned long irq_flags;
++ int nentries;
++ size_t nbytes;
++
++ for (nentries = ch->local_nentries; nentries > 0; nentries--) {
++
++ nbytes = nentries * ch->msg_size;
++ ch->local_msgqueue = xpc_kzalloc_cacheline_aligned(nbytes,
++ GFP_KERNEL,
++ &ch->local_msgqueue_base);
++ if (ch->local_msgqueue == NULL)
++ continue;
++
++ nbytes = nentries * sizeof(struct xpc_notify);
++ ch->notify_queue = kzalloc(nbytes, GFP_KERNEL);
++ if (ch->notify_queue == NULL) {
++ kfree(ch->local_msgqueue_base);
++ ch->local_msgqueue = NULL;
++ continue;
++ }
++
++ spin_lock_irqsave(&ch->lock, irq_flags);
++ if (nentries < ch->local_nentries) {
++ dev_dbg(xpc_chan, "nentries=%d local_nentries=%d, "
++ "partid=%d, channel=%d\n", nentries,
++ ch->local_nentries, ch->partid, ch->number);
++
++ ch->local_nentries = nentries;
++ }
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++ return xpcSuccess;
++ }
++
++ dev_dbg(xpc_chan, "can't get memory for local message queue and notify "
++ "queue, partid=%d, channel=%d\n", ch->partid, ch->number);
++ return xpcNoMemory;
++}
++
++/*
++ * Allocate the cached remote message queue.
++ */
++static enum xpc_retval
++xpc_allocate_remote_msgqueue(struct xpc_channel *ch)
++{
++ unsigned long irq_flags;
++ int nentries;
++ size_t nbytes;
++
++ DBUG_ON(ch->remote_nentries <= 0);
++
++ for (nentries = ch->remote_nentries; nentries > 0; nentries--) {
++
++ nbytes = nentries * ch->msg_size;
++ ch->remote_msgqueue = xpc_kzalloc_cacheline_aligned(nbytes,
++ GFP_KERNEL,
++ &ch->remote_msgqueue_base);
++ if (ch->remote_msgqueue == NULL)
++ continue;
++
++ spin_lock_irqsave(&ch->lock, irq_flags);
++ if (nentries < ch->remote_nentries) {
++ dev_dbg(xpc_chan, "nentries=%d remote_nentries=%d, "
++ "partid=%d, channel=%d\n", nentries,
++ ch->remote_nentries, ch->partid, ch->number);
++
++ ch->remote_nentries = nentries;
++ }
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++ return xpcSuccess;
++ }
++
++ dev_dbg(xpc_chan, "can't get memory for cached remote message queue, "
++ "partid=%d, channel=%d\n", ch->partid, ch->number);
++ return xpcNoMemory;
++}
++
++/*
++ * Allocate message queues and other stuff associated with a channel.
++ *
++ * Note: Assumes all of the channel sizes are filled in.
++ */
++static enum xpc_retval
++xpc_allocate_msgqueues(struct xpc_channel *ch)
++{
++ unsigned long irq_flags;
++ enum xpc_retval ret;
++
++ DBUG_ON(ch->flags & XPC_C_SETUP);
++
++ ret = xpc_allocate_local_msgqueue(ch);
++ if (ret != xpcSuccess)
++ return ret;
++
++ ret = xpc_allocate_remote_msgqueue(ch);
++ if (ret != xpcSuccess) {
++ kfree(ch->local_msgqueue_base);
++ ch->local_msgqueue = NULL;
++ kfree(ch->notify_queue);
++ ch->notify_queue = NULL;
++ return ret;
++ }
++
++ spin_lock_irqsave(&ch->lock, irq_flags);
++ ch->flags |= XPC_C_SETUP;
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++
++ return xpcSuccess;
++}
++
++/*
++ * Process a connect message from a remote partition.
++ *
++ * Note: xpc_process_connect() is expecting to be called with the
++ * spin_lock_irqsave held and will leave it locked upon return.
++ */
++static void
++xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags)
++{
++ enum xpc_retval ret;
++
++ DBUG_ON(!spin_is_locked(&ch->lock));
++
++ if (!(ch->flags & XPC_C_OPENREQUEST) ||
++ !(ch->flags & XPC_C_ROPENREQUEST)) {
++ /* nothing more to do for now */
++ return;
++ }
++ DBUG_ON(!(ch->flags & XPC_C_CONNECTING));
++
++ if (!(ch->flags & XPC_C_SETUP)) {
++ spin_unlock_irqrestore(&ch->lock, *irq_flags);
++ ret = xpc_allocate_msgqueues(ch);
++ spin_lock_irqsave(&ch->lock, *irq_flags);
++
++ if (ret != xpcSuccess)
++ XPC_DISCONNECT_CHANNEL(ch, ret, irq_flags);
++
++ if (ch->flags & (XPC_C_CONNECTED | XPC_C_DISCONNECTING))
++ return;
++
++ DBUG_ON(!(ch->flags & XPC_C_SETUP));
++ DBUG_ON(ch->local_msgqueue == NULL);
++ DBUG_ON(ch->remote_msgqueue == NULL);
++ }
++
++ if (!(ch->flags & XPC_C_OPENREPLY)) {
++ ch->flags |= XPC_C_OPENREPLY;
++ xpc_IPI_send_openreply(ch, irq_flags);
++ }
++
++ if (!(ch->flags & XPC_C_ROPENREPLY))
++ return;
++
++ DBUG_ON(ch->remote_msgqueue_pa == 0);
++
++ ch->flags = (XPC_C_CONNECTED | XPC_C_SETUP); /* clear all else */
++
++ dev_info(xpc_chan, "channel %d to partition %d connected\n",
++ ch->number, ch->partid);
++
++ spin_unlock_irqrestore(&ch->lock, *irq_flags);
++ xpc_create_kthreads(ch, 1, 0);
++ spin_lock_irqsave(&ch->lock, *irq_flags);
++}
++
++/*
++ * Notify those who wanted to be notified upon delivery of their message.
++ */
++static void
++xpc_notify_senders(struct xpc_channel *ch, enum xpc_retval reason, s64 put)
++{
++ struct xpc_notify *notify;
++ u8 notify_type;
++ s64 get = ch->w_remote_GP.get - 1;
++
++ while (++get < put && atomic_read(&ch->n_to_notify) > 0) {
++
++ notify = &ch->notify_queue[get % ch->local_nentries];
++
++ /*
++ * See if the notify entry indicates it was associated with
++ * a message who's sender wants to be notified. It is possible
++ * that it is, but someone else is doing or has done the
++ * notification.
++ */
++ notify_type = notify->type;
++ if (notify_type == 0 ||
++ cmpxchg(¬ify->type, notify_type, 0) != notify_type) {
++ continue;
++ }
++
++ DBUG_ON(notify_type != XPC_N_CALL);
++
++ atomic_dec(&ch->n_to_notify);
++
++ if (notify->func != NULL) {
++ dev_dbg(xpc_chan, "notify->func() called, notify=0x%p, "
++ "msg_number=%ld, partid=%d, channel=%d\n",
++ (void *)notify, get, ch->partid, ch->number);
++
++ notify->func(reason, ch->partid, ch->number,
++ notify->key);
++
++ dev_dbg(xpc_chan, "notify->func() returned, "
++ "notify=0x%p, msg_number=%ld, partid=%d, "
++ "channel=%d\n", (void *)notify, get,
++ ch->partid, ch->number);
++ }
++ }
++}
++
++/*
++ * Free up message queues and other stuff that were allocated for the specified
++ * channel.
++ *
++ * Note: ch->reason and ch->reason_line are left set for debugging purposes,
++ * they're cleared when XPC_C_DISCONNECTED is cleared.
++ */
++static void
++xpc_free_msgqueues(struct xpc_channel *ch)
++{
++ DBUG_ON(!spin_is_locked(&ch->lock));
++ DBUG_ON(atomic_read(&ch->n_to_notify) != 0);
++
++ ch->remote_msgqueue_pa = 0;
++ ch->func = NULL;
++ ch->key = NULL;
++ ch->msg_size = 0;
++ ch->local_nentries = 0;
++ ch->remote_nentries = 0;
++ ch->kthreads_assigned_limit = 0;
++ ch->kthreads_idle_limit = 0;
++
++ ch->local_GP->get = 0;
++ ch->local_GP->put = 0;
++ ch->remote_GP.get = 0;
++ ch->remote_GP.put = 0;
++ ch->w_local_GP.get = 0;
++ ch->w_local_GP.put = 0;
++ ch->w_remote_GP.get = 0;
++ ch->w_remote_GP.put = 0;
++ ch->next_msg_to_pull = 0;
++
++ if (ch->flags & XPC_C_SETUP) {
++ ch->flags &= ~XPC_C_SETUP;
++
++ dev_dbg(xpc_chan, "ch->flags=0x%x, partid=%d, channel=%d\n",
++ ch->flags, ch->partid, ch->number);
++
++ kfree(ch->local_msgqueue_base);
++ ch->local_msgqueue = NULL;
++ kfree(ch->remote_msgqueue_base);
++ ch->remote_msgqueue = NULL;
++ kfree(ch->notify_queue);
++ ch->notify_queue = NULL;
++ }
++}
++
++/*
++ * spin_lock_irqsave() is expected to be held on entry.
++ */
++static void
++xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
++{
++ struct xpc_partition *part = &xpc_partitions[ch->partid];
++ u32 channel_was_connected = (ch->flags & XPC_C_WASCONNECTED);
++
++ DBUG_ON(!spin_is_locked(&ch->lock));
++
++ if (!(ch->flags & XPC_C_DISCONNECTING))
++ return;
++
++ DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
++
++ /* make sure all activity has settled down first */
++
++ if (atomic_read(&ch->kthreads_assigned) > 0 ||
++ atomic_read(&ch->references) > 0) {
++ return;
++ }
++ DBUG_ON((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
++ !(ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE));
++
++ if (part->act_state == XPC_P_DEACTIVATING) {
++ /* can't proceed until the other side disengages from us */
++ if (xpc_partition_engaged(1UL << ch->partid))
++ return;
++
++ } else {
++
++ /* as long as the other side is up do the full protocol */
++
++ if (!(ch->flags & XPC_C_RCLOSEREQUEST))
++ return;
++
++ if (!(ch->flags & XPC_C_CLOSEREPLY)) {
++ ch->flags |= XPC_C_CLOSEREPLY;
++ xpc_IPI_send_closereply(ch, irq_flags);
++ }
++
++ if (!(ch->flags & XPC_C_RCLOSEREPLY))
++ return;
++ }
++
++ /* wake those waiting for notify completion */
++ if (atomic_read(&ch->n_to_notify) > 0) {
++ /* >>> we do callout while holding ch->lock */
++ xpc_notify_senders(ch, ch->reason, ch->w_local_GP.put);
++ }
++
++ /* both sides are disconnected now */
++
++ if (ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE) {
++ spin_unlock_irqrestore(&ch->lock, *irq_flags);
++ xpc_disconnect_callout(ch, xpcDisconnected);
++ spin_lock_irqsave(&ch->lock, *irq_flags);
++ }
++
++ /* it's now safe to free the channel's message queues */
++ xpc_free_msgqueues(ch);
++
++ /* mark disconnected, clear all other flags except XPC_C_WDISCONNECT */
++ ch->flags = (XPC_C_DISCONNECTED | (ch->flags & XPC_C_WDISCONNECT));
++
++ atomic_dec(&part->nchannels_active);
++
++ if (channel_was_connected) {
++ dev_info(xpc_chan, "channel %d to partition %d disconnected, "
++ "reason=%d\n", ch->number, ch->partid, ch->reason);
++ }
++
++ if (ch->flags & XPC_C_WDISCONNECT) {
++ /* we won't lose the CPU since we're holding ch->lock */
++ complete(&ch->wdisconnect_wait);
++ } else if (ch->delayed_IPI_flags) {
++ if (part->act_state != XPC_P_DEACTIVATING) {
++ /* time to take action on any delayed IPI flags */
++ spin_lock(&part->IPI_lock);
++ XPC_SET_IPI_FLAGS(part->local_IPI_amo, ch->number,
++ ch->delayed_IPI_flags);
++ spin_unlock(&part->IPI_lock);
++ }
++ ch->delayed_IPI_flags = 0;
++ }
++}
++
++/*
++ * Process a change in the channel's remote connection state.
++ */
++static void
++xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
++ u8 IPI_flags)
++{
++ unsigned long irq_flags;
++ struct xpc_openclose_args *args =
++ &part->remote_openclose_args[ch_number];
++ struct xpc_channel *ch = &part->channels[ch_number];
++ enum xpc_retval reason;
++
++ spin_lock_irqsave(&ch->lock, irq_flags);
++
++again:
++
++ if ((ch->flags & XPC_C_DISCONNECTED) &&
++ (ch->flags & XPC_C_WDISCONNECT)) {
++ /*
++ * Delay processing IPI flags until thread waiting disconnect
++ * has had a chance to see that the channel is disconnected.
++ */
++ ch->delayed_IPI_flags |= IPI_flags;
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++ return;
++ }
++
++ if (IPI_flags & XPC_IPI_CLOSEREQUEST) {
++
++ dev_dbg(xpc_chan, "XPC_IPI_CLOSEREQUEST (reason=%d) received "
++ "from partid=%d, channel=%d\n", args->reason,
++ ch->partid, ch->number);
++
++ /*
++ * If RCLOSEREQUEST is set, we're probably waiting for
++ * RCLOSEREPLY. We should find it and a ROPENREQUEST packed
++ * with this RCLOSEREQUEST in the IPI_flags.
++ */
++
++ if (ch->flags & XPC_C_RCLOSEREQUEST) {
++ DBUG_ON(!(ch->flags & XPC_C_DISCONNECTING));
++ DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
++ DBUG_ON(!(ch->flags & XPC_C_CLOSEREPLY));
++ DBUG_ON(ch->flags & XPC_C_RCLOSEREPLY);
++
++ DBUG_ON(!(IPI_flags & XPC_IPI_CLOSEREPLY));
++ IPI_flags &= ~XPC_IPI_CLOSEREPLY;
++ ch->flags |= XPC_C_RCLOSEREPLY;
++
++ /* both sides have finished disconnecting */
++ xpc_process_disconnect(ch, &irq_flags);
++ DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED));
++ goto again;
++ }
++
++ if (ch->flags & XPC_C_DISCONNECTED) {
++ if (!(IPI_flags & XPC_IPI_OPENREQUEST)) {
++ if ((XPC_GET_IPI_FLAGS(part->local_IPI_amo,
++ ch_number) &
++ XPC_IPI_OPENREQUEST)) {
++
++ DBUG_ON(ch->delayed_IPI_flags != 0);
++ spin_lock(&part->IPI_lock);
++ XPC_SET_IPI_FLAGS(part->local_IPI_amo,
++ ch_number,
++ XPC_IPI_CLOSEREQUEST);
++ spin_unlock(&part->IPI_lock);
++ }
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++ return;
++ }
++
++ XPC_SET_REASON(ch, 0, 0);
++ ch->flags &= ~XPC_C_DISCONNECTED;
++
++ atomic_inc(&part->nchannels_active);
++ ch->flags |= (XPC_C_CONNECTING | XPC_C_ROPENREQUEST);
++ }
++
++ IPI_flags &= ~(XPC_IPI_OPENREQUEST | XPC_IPI_OPENREPLY);
++
++ /*
++ * The meaningful CLOSEREQUEST connection state fields are:
++ * reason = reason connection is to be closed
++ */
++
++ ch->flags |= XPC_C_RCLOSEREQUEST;
++
++ if (!(ch->flags & XPC_C_DISCONNECTING)) {
++ reason = args->reason;
++ if (reason <= xpcSuccess || reason > xpcUnknownReason)
++ reason = xpcUnknownReason;
++ else if (reason == xpcUnregistering)
++ reason = xpcOtherUnregistering;
++
++ XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags);
++
++ DBUG_ON(IPI_flags & XPC_IPI_CLOSEREPLY);
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++ return;
++ }
++
++ xpc_process_disconnect(ch, &irq_flags);
++ }
++
++ if (IPI_flags & XPC_IPI_CLOSEREPLY) {
++
++ dev_dbg(xpc_chan, "XPC_IPI_CLOSEREPLY received from partid=%d,"
++ " channel=%d\n", ch->partid, ch->number);
++
++ if (ch->flags & XPC_C_DISCONNECTED) {
++ DBUG_ON(part->act_state != XPC_P_DEACTIVATING);
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++ return;
++ }
++
++ DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
++
++ if (!(ch->flags & XPC_C_RCLOSEREQUEST)) {
++ if ((XPC_GET_IPI_FLAGS(part->local_IPI_amo, ch_number)
++ & XPC_IPI_CLOSEREQUEST)) {
++
++ DBUG_ON(ch->delayed_IPI_flags != 0);
++ spin_lock(&part->IPI_lock);
++ XPC_SET_IPI_FLAGS(part->local_IPI_amo,
++ ch_number,
++ XPC_IPI_CLOSEREPLY);
++ spin_unlock(&part->IPI_lock);
++ }
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++ return;
++ }
++
++ ch->flags |= XPC_C_RCLOSEREPLY;
++
++ if (ch->flags & XPC_C_CLOSEREPLY) {
++ /* both sides have finished disconnecting */
++ xpc_process_disconnect(ch, &irq_flags);
++ }
++ }
++
++ if (IPI_flags & XPC_IPI_OPENREQUEST) {
++
++ dev_dbg(xpc_chan, "XPC_IPI_OPENREQUEST (msg_size=%d, "
++ "local_nentries=%d) received from partid=%d, "
++ "channel=%d\n", args->msg_size, args->local_nentries,
++ ch->partid, ch->number);
++
++ if (part->act_state == XPC_P_DEACTIVATING ||
++ (ch->flags & XPC_C_ROPENREQUEST)) {
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++ return;
++ }
++
++ if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_WDISCONNECT)) {
++ ch->delayed_IPI_flags |= XPC_IPI_OPENREQUEST;
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++ return;
++ }
++ DBUG_ON(!(ch->flags & (XPC_C_DISCONNECTED |
++ XPC_C_OPENREQUEST)));
++ DBUG_ON(ch->flags & (XPC_C_ROPENREQUEST | XPC_C_ROPENREPLY |
++ XPC_C_OPENREPLY | XPC_C_CONNECTED));
++
++ /*
++ * The meaningful OPENREQUEST connection state fields are:
++ * msg_size = size of channel's messages in bytes
++ * local_nentries = remote partition's local_nentries
++ */
++ if (args->msg_size == 0 || args->local_nentries == 0) {
++ /* assume OPENREQUEST was delayed by mistake */
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++ return;
++ }
++
++ ch->flags |= (XPC_C_ROPENREQUEST | XPC_C_CONNECTING);
++ ch->remote_nentries = args->local_nentries;
++
++ if (ch->flags & XPC_C_OPENREQUEST) {
++ if (args->msg_size != ch->msg_size) {
++ XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes,
++ &irq_flags);
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++ return;
++ }
++ } else {
++ ch->msg_size = args->msg_size;
++
++ XPC_SET_REASON(ch, 0, 0);
++ ch->flags &= ~XPC_C_DISCONNECTED;
++
++ atomic_inc(&part->nchannels_active);
++ }
++
++ xpc_process_connect(ch, &irq_flags);
++ }
++
++ if (IPI_flags & XPC_IPI_OPENREPLY) {
++
++ dev_dbg(xpc_chan, "XPC_IPI_OPENREPLY (local_msgqueue_pa=0x%lx, "
++ "local_nentries=%d, remote_nentries=%d) received from "
++ "partid=%d, channel=%d\n", args->local_msgqueue_pa,
++ args->local_nentries, args->remote_nentries,
++ ch->partid, ch->number);
++
++ if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED)) {
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++ return;
++ }
++ if (!(ch->flags & XPC_C_OPENREQUEST)) {
++ XPC_DISCONNECT_CHANNEL(ch, xpcOpenCloseError,
++ &irq_flags);
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++ return;
++ }
++
++ DBUG_ON(!(ch->flags & XPC_C_ROPENREQUEST));
++ DBUG_ON(ch->flags & XPC_C_CONNECTED);
++
++ /*
++ * The meaningful OPENREPLY connection state fields are:
++ * local_msgqueue_pa = physical address of remote
++ * partition's local_msgqueue
++ * local_nentries = remote partition's local_nentries
++ * remote_nentries = remote partition's remote_nentries
++ */
++ DBUG_ON(args->local_msgqueue_pa == 0);
++ DBUG_ON(args->local_nentries == 0);
++ DBUG_ON(args->remote_nentries == 0);
++
++ ch->flags |= XPC_C_ROPENREPLY;
++ ch->remote_msgqueue_pa = args->local_msgqueue_pa;
++
++ if (args->local_nentries < ch->remote_nentries) {
++ dev_dbg(xpc_chan, "XPC_IPI_OPENREPLY: new "
++ "remote_nentries=%d, old remote_nentries=%d, "
++ "partid=%d, channel=%d\n",
++ args->local_nentries, ch->remote_nentries,
++ ch->partid, ch->number);
++
++ ch->remote_nentries = args->local_nentries;
++ }
++ if (args->remote_nentries < ch->local_nentries) {
++ dev_dbg(xpc_chan, "XPC_IPI_OPENREPLY: new "
++ "local_nentries=%d, old local_nentries=%d, "
++ "partid=%d, channel=%d\n",
++ args->remote_nentries, ch->local_nentries,
++ ch->partid, ch->number);
++
++ ch->local_nentries = args->remote_nentries;
++ }
++
++ xpc_process_connect(ch, &irq_flags);
++ }
++
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++}
++
++/*
++ * Attempt to establish a channel connection to a remote partition.
++ */
++static enum xpc_retval
++xpc_connect_channel(struct xpc_channel *ch)
++{
++ unsigned long irq_flags;
++ struct xpc_registration *registration = &xpc_registrations[ch->number];
++
++ if (mutex_trylock(®istration->mutex) == 0)
++ return xpcRetry;
++
++ if (!XPC_CHANNEL_REGISTERED(ch->number)) {
++ mutex_unlock(®istration->mutex);
++ return xpcUnregistered;
++ }
++
++ spin_lock_irqsave(&ch->lock, irq_flags);
++
++ DBUG_ON(ch->flags & XPC_C_CONNECTED);
++ DBUG_ON(ch->flags & XPC_C_OPENREQUEST);
++
++ if (ch->flags & XPC_C_DISCONNECTING) {
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++ mutex_unlock(®istration->mutex);
++ return ch->reason;
++ }
++
++ /* add info from the channel connect registration to the channel */
++
++ ch->kthreads_assigned_limit = registration->assigned_limit;
++ ch->kthreads_idle_limit = registration->idle_limit;
++ DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0);
++ DBUG_ON(atomic_read(&ch->kthreads_idle) != 0);
++ DBUG_ON(atomic_read(&ch->kthreads_active) != 0);
++
++ ch->func = registration->func;
++ DBUG_ON(registration->func == NULL);
++ ch->key = registration->key;
++
++ ch->local_nentries = registration->nentries;
++
++ if (ch->flags & XPC_C_ROPENREQUEST) {
++ if (registration->msg_size != ch->msg_size) {
++ /* the local and remote sides aren't the same */
++
++ /*
++ * Because XPC_DISCONNECT_CHANNEL() can block we're
++ * forced to up the registration sema before we unlock
++ * the channel lock. But that's okay here because we're
++ * done with the part that required the registration
++ * sema. XPC_DISCONNECT_CHANNEL() requires that the
++ * channel lock be locked and will unlock and relock
++ * the channel lock as needed.
++ */
++ mutex_unlock(®istration->mutex);
++ XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes,
++ &irq_flags);
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++ return xpcUnequalMsgSizes;
++ }
++ } else {
++ ch->msg_size = registration->msg_size;
++
++ XPC_SET_REASON(ch, 0, 0);
++ ch->flags &= ~XPC_C_DISCONNECTED;
++
++ atomic_inc(&xpc_partitions[ch->partid].nchannels_active);
++ }
++
++ mutex_unlock(®istration->mutex);
++
++ /* initiate the connection */
++
++ ch->flags |= (XPC_C_OPENREQUEST | XPC_C_CONNECTING);
++ xpc_IPI_send_openrequest(ch, &irq_flags);
++
++ xpc_process_connect(ch, &irq_flags);
++
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++
++ return xpcSuccess;
++}
++
++/*
++ * Clear some of the msg flags in the local message queue.
++ */
++static inline void
++xpc_clear_local_msgqueue_flags(struct xpc_channel *ch)
++{
++ struct xpc_msg *msg;
++ s64 get;
++
++ get = ch->w_remote_GP.get;
++ do {
++ msg = (struct xpc_msg *)((u64)ch->local_msgqueue +
++ (get % ch->local_nentries) *
++ ch->msg_size);
++ msg->flags = 0;
++ } while (++get < ch->remote_GP.get);
++}
++
++/*
++ * Clear some of the msg flags in the remote message queue.
++ */
++static inline void
++xpc_clear_remote_msgqueue_flags(struct xpc_channel *ch)
++{
++ struct xpc_msg *msg;
++ s64 put;
++
++ put = ch->w_remote_GP.put;
++ do {
++ msg = (struct xpc_msg *)((u64)ch->remote_msgqueue +
++ (put % ch->remote_nentries) *
++ ch->msg_size);
++ msg->flags = 0;
++ } while (++put < ch->remote_GP.put);
++}
++
++static void
++xpc_process_msg_IPI(struct xpc_partition *part, int ch_number)
++{
++ struct xpc_channel *ch = &part->channels[ch_number];
++ int nmsgs_sent;
++
++ ch->remote_GP = part->remote_GPs[ch_number];
++
++ /* See what, if anything, has changed for each connected channel */
++
++ xpc_msgqueue_ref(ch);
++
++ if (ch->w_remote_GP.get == ch->remote_GP.get &&
++ ch->w_remote_GP.put == ch->remote_GP.put) {
++ /* nothing changed since GPs were last pulled */
++ xpc_msgqueue_deref(ch);
++ return;
++ }
++
++ if (!(ch->flags & XPC_C_CONNECTED)) {
++ xpc_msgqueue_deref(ch);
++ return;
++ }
++
++ /*
++ * First check to see if messages recently sent by us have been
++ * received by the other side. (The remote GET value will have
++ * changed since we last looked at it.)
++ */
++
++ if (ch->w_remote_GP.get != ch->remote_GP.get) {
++
++ /*
++ * We need to notify any senders that want to be notified
++ * that their sent messages have been received by their
++ * intended recipients. We need to do this before updating
++ * w_remote_GP.get so that we don't allocate the same message
++ * queue entries prematurely (see xpc_allocate_msg()).
++ */
++ if (atomic_read(&ch->n_to_notify) > 0) {
++ /*
++ * Notify senders that messages sent have been
++ * received and delivered by the other side.
++ */
++ xpc_notify_senders(ch, xpcMsgDelivered,
++ ch->remote_GP.get);
++ }
++
++ /*
++ * Clear msg->flags in previously sent messages, so that
++ * they're ready for xpc_allocate_msg().
++ */
++ xpc_clear_local_msgqueue_flags(ch);
++
++ ch->w_remote_GP.get = ch->remote_GP.get;
++
++ dev_dbg(xpc_chan, "w_remote_GP.get changed to %ld, partid=%d, "
++ "channel=%d\n", ch->w_remote_GP.get, ch->partid,
++ ch->number);
++
++ /*
++ * If anyone was waiting for message queue entries to become
++ * available, wake them up.
++ */
++ if (atomic_read(&ch->n_on_msg_allocate_wq) > 0)
++ wake_up(&ch->msg_allocate_wq);
++ }
++
++ /*
++ * Now check for newly sent messages by the other side. (The remote
++ * PUT value will have changed since we last looked at it.)
++ */
++
++ if (ch->w_remote_GP.put != ch->remote_GP.put) {
++ /*
++ * Clear msg->flags in previously received messages, so that
++ * they're ready for xpc_get_deliverable_msg().
++ */
++ xpc_clear_remote_msgqueue_flags(ch);
++
++ ch->w_remote_GP.put = ch->remote_GP.put;
++
++ dev_dbg(xpc_chan, "w_remote_GP.put changed to %ld, partid=%d, "
++ "channel=%d\n", ch->w_remote_GP.put, ch->partid,
++ ch->number);
++
++ nmsgs_sent = ch->w_remote_GP.put - ch->w_local_GP.get;
++ if (nmsgs_sent > 0) {
++ dev_dbg(xpc_chan, "msgs waiting to be copied and "
++ "delivered=%d, partid=%d, channel=%d\n",
++ nmsgs_sent, ch->partid, ch->number);
++
++ if (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE)
++ xpc_activate_kthreads(ch, nmsgs_sent);
++ }
++ }
++
++ xpc_msgqueue_deref(ch);
++}
++
++void
++xpc_process_channel_activity(struct xpc_partition *part)
++{
++ unsigned long irq_flags;
++ u64 IPI_amo, IPI_flags;
++ struct xpc_channel *ch;
++ int ch_number;
++ u32 ch_flags;
++
++ IPI_amo = xpc_get_IPI_flags(part);
++
++ /*
++ * Initiate channel connections for registered channels.
++ *
++ * For each connected channel that has pending messages activate idle
++ * kthreads and/or create new kthreads as needed.
++ */
++
++ for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
++ ch = &part->channels[ch_number];
++
++ /*
++ * Process any open or close related IPI flags, and then deal
++ * with connecting or disconnecting the channel as required.
++ */
++
++ IPI_flags = XPC_GET_IPI_FLAGS(IPI_amo, ch_number);
++
++ if (XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(IPI_flags))
++ xpc_process_openclose_IPI(part, ch_number, IPI_flags);
++
++ ch_flags = ch->flags; /* need an atomic snapshot of flags */
++
++ if (ch_flags & XPC_C_DISCONNECTING) {
++ spin_lock_irqsave(&ch->lock, irq_flags);
++ xpc_process_disconnect(ch, &irq_flags);
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++ continue;
++ }
++
++ if (part->act_state == XPC_P_DEACTIVATING)
++ continue;
++
++ if (!(ch_flags & XPC_C_CONNECTED)) {
++ if (!(ch_flags & XPC_C_OPENREQUEST)) {
++ DBUG_ON(ch_flags & XPC_C_SETUP);
++ (void)xpc_connect_channel(ch);
++ } else {
++ spin_lock_irqsave(&ch->lock, irq_flags);
++ xpc_process_connect(ch, &irq_flags);
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++ }
++ continue;
++ }
++
++ /*
++ * Process any message related IPI flags, this may involve the
++ * activation of kthreads to deliver any pending messages sent
++ * from the other partition.
++ */
++
++ if (XPC_ANY_MSG_IPI_FLAGS_SET(IPI_flags))
++ xpc_process_msg_IPI(part, ch_number);
++ }
++}
++
++/*
++ * XPC's heartbeat code calls this function to inform XPC that a partition is
++ * going down. XPC responds by tearing down the XPartition Communication
++ * infrastructure used for the just downed partition.
++ *
++ * XPC's heartbeat code will never call this function and xpc_partition_up()
++ * at the same time. Nor will it ever make multiple calls to either function
++ * at the same time.
++ */
++void
++xpc_partition_going_down(struct xpc_partition *part, enum xpc_retval reason)
++{
++ unsigned long irq_flags;
++ int ch_number;
++ struct xpc_channel *ch;
++
++ dev_dbg(xpc_chan, "deactivating partition %d, reason=%d\n",
++ XPC_PARTID(part), reason);
++
++ if (!xpc_part_ref(part)) {
++ /* infrastructure for this partition isn't currently set up */
++ return;
++ }
++
++ /* disconnect channels associated with the partition going down */
++
++ for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
++ ch = &part->channels[ch_number];
++
++ xpc_msgqueue_ref(ch);
++ spin_lock_irqsave(&ch->lock, irq_flags);
++
++ XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags);
++
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++ xpc_msgqueue_deref(ch);
++ }
++
++ xpc_wakeup_channel_mgr(part);
++
++ xpc_part_deref(part);
++}
++
++/*
++ * Teardown the infrastructure necessary to support XPartition Communication
++ * between the specified remote partition and the local one.
++ */
++void
++xpc_teardown_infrastructure(struct xpc_partition *part)
++{
++ partid_t partid = XPC_PARTID(part);
++
++ /*
++ * We start off by making this partition inaccessible to local
++ * processes by marking it as no longer setup. Then we make it
++ * inaccessible to remote processes by clearing the XPC per partition
++ * specific variable's magic # (which indicates that these variables
++ * are no longer valid) and by ignoring all XPC notify IPIs sent to
++ * this partition.
++ */
++
++ DBUG_ON(atomic_read(&part->nchannels_engaged) != 0);
++ DBUG_ON(atomic_read(&part->nchannels_active) != 0);
++ DBUG_ON(part->setup_state != XPC_P_SETUP);
++ part->setup_state = XPC_P_WTEARDOWN;
++
++ xpc_vars_part[partid].magic = 0;
++
++ free_irq(SGI_XPC_NOTIFY, (void *)(u64)partid);
++
++ /*
++ * Before proceeding with the teardown we have to wait until all
++ * existing references cease.
++ */
++ wait_event(part->teardown_wq, (atomic_read(&part->references) == 0));
++
++ /* now we can begin tearing down the infrastructure */
++
++ part->setup_state = XPC_P_TORNDOWN;
++
++ /* in case we've still got outstanding timers registered... */
++ del_timer_sync(&part->dropped_IPI_timer);
++
++ kfree(part->remote_openclose_args_base);
++ part->remote_openclose_args = NULL;
++ kfree(part->local_openclose_args_base);
++ part->local_openclose_args = NULL;
++ kfree(part->remote_GPs_base);
++ part->remote_GPs = NULL;
++ kfree(part->local_GPs_base);
++ part->local_GPs = NULL;
++ kfree(part->channels);
++ part->channels = NULL;
++ part->local_IPI_amo_va = NULL;
++}
++
++/*
++ * Called by XP at the time of channel connection registration to cause
++ * XPC to establish connections to all currently active partitions.
++ */
++void
++xpc_initiate_connect(int ch_number)
++{
++ partid_t partid;
++ struct xpc_partition *part;
++ struct xpc_channel *ch;
++
++ DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
++
++ for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
++ part = &xpc_partitions[partid];
++
++ if (xpc_part_ref(part)) {
++ ch = &part->channels[ch_number];
++
++ /*
++ * Initiate the establishment of a connection on the
++ * newly registered channel to the remote partition.
++ */
++ xpc_wakeup_channel_mgr(part);
++ xpc_part_deref(part);
++ }
++ }
++}
++
++void
++xpc_connected_callout(struct xpc_channel *ch)
++{
++ /* let the registerer know that a connection has been established */
++
++ if (ch->func != NULL) {
++ dev_dbg(xpc_chan, "ch->func() called, reason=xpcConnected, "
++ "partid=%d, channel=%d\n", ch->partid, ch->number);
++
++ ch->func(xpcConnected, ch->partid, ch->number,
++ (void *)(u64)ch->local_nentries, ch->key);
++
++ dev_dbg(xpc_chan, "ch->func() returned, reason=xpcConnected, "
++ "partid=%d, channel=%d\n", ch->partid, ch->number);
++ }
++}
++
++/*
++ * Called by XP at the time of channel connection unregistration to cause
++ * XPC to teardown all current connections for the specified channel.
++ *
++ * Before returning xpc_initiate_disconnect() will wait until all connections
++ * on the specified channel have been closed/torndown. So the caller can be
++ * assured that they will not be receiving any more callouts from XPC to the
++ * function they registered via xpc_connect().
++ *
++ * Arguments:
++ *
++ * ch_number - channel # to unregister.
++ */
++void
++xpc_initiate_disconnect(int ch_number)
++{
++ unsigned long irq_flags;
++ partid_t partid;
++ struct xpc_partition *part;
++ struct xpc_channel *ch;
++
++ DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
++
++ /* initiate the channel disconnect for every active partition */
++ for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
++ part = &xpc_partitions[partid];
++
++ if (xpc_part_ref(part)) {
++ ch = &part->channels[ch_number];
++ xpc_msgqueue_ref(ch);
++
++ spin_lock_irqsave(&ch->lock, irq_flags);
++
++ if (!(ch->flags & XPC_C_DISCONNECTED)) {
++ ch->flags |= XPC_C_WDISCONNECT;
++
++ XPC_DISCONNECT_CHANNEL(ch, xpcUnregistering,
++ &irq_flags);
++ }
++
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++
++ xpc_msgqueue_deref(ch);
++ xpc_part_deref(part);
++ }
++ }
++
++ xpc_disconnect_wait(ch_number);
++}
++
++/*
++ * To disconnect a channel, and reflect it back to all who may be waiting.
++ *
++ * An OPEN is not allowed until XPC_C_DISCONNECTING is cleared by
++ * xpc_process_disconnect(), and if set, XPC_C_WDISCONNECT is cleared by
++ * xpc_disconnect_wait().
++ *
++ * THE CHANNEL IS TO BE LOCKED BY THE CALLER AND WILL REMAIN LOCKED UPON RETURN.
++ */
++void
++xpc_disconnect_channel(const int line, struct xpc_channel *ch,
++ enum xpc_retval reason, unsigned long *irq_flags)
++{
++ u32 channel_was_connected = (ch->flags & XPC_C_CONNECTED);
++
++ DBUG_ON(!spin_is_locked(&ch->lock));
++
++ if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED))
++ return;
++
++ DBUG_ON(!(ch->flags & (XPC_C_CONNECTING | XPC_C_CONNECTED)));
++
++ dev_dbg(xpc_chan, "reason=%d, line=%d, partid=%d, channel=%d\n",
++ reason, line, ch->partid, ch->number);
++
++ XPC_SET_REASON(ch, reason, line);
++
++ ch->flags |= (XPC_C_CLOSEREQUEST | XPC_C_DISCONNECTING);
++ /* some of these may not have been set */
++ ch->flags &= ~(XPC_C_OPENREQUEST | XPC_C_OPENREPLY |
++ XPC_C_ROPENREQUEST | XPC_C_ROPENREPLY |
++ XPC_C_CONNECTING | XPC_C_CONNECTED);
++
++ xpc_IPI_send_closerequest(ch, irq_flags);
++
++ if (channel_was_connected)
++ ch->flags |= XPC_C_WASCONNECTED;
++
++ spin_unlock_irqrestore(&ch->lock, *irq_flags);
++
++ /* wake all idle kthreads so they can exit */
++ if (atomic_read(&ch->kthreads_idle) > 0) {
++ wake_up_all(&ch->idle_wq);
++
++ } else if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
++ !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) {
++ /* start a kthread that will do the xpcDisconnecting callout */
++ xpc_create_kthreads(ch, 1, 1);
++ }
++
++ /* wake those waiting to allocate an entry from the local msg queue */
++ if (atomic_read(&ch->n_on_msg_allocate_wq) > 0)
++ wake_up(&ch->msg_allocate_wq);
++
++ spin_lock_irqsave(&ch->lock, *irq_flags);
++}
++
++void
++xpc_disconnect_callout(struct xpc_channel *ch, enum xpc_retval reason)
++{
++ /*
++ * Let the channel's registerer know that the channel is being
++ * disconnected. We don't want to do this if the registerer was never
++ * informed of a connection being made.
++ */
++
++ if (ch->func != NULL) {
++ dev_dbg(xpc_chan, "ch->func() called, reason=%d, partid=%d, "
++ "channel=%d\n", reason, ch->partid, ch->number);
++
++ ch->func(reason, ch->partid, ch->number, NULL, ch->key);
++
++ dev_dbg(xpc_chan, "ch->func() returned, reason=%d, partid=%d, "
++ "channel=%d\n", reason, ch->partid, ch->number);
++ }
++}
++
++/*
++ * Wait for a message entry to become available for the specified channel,
++ * but don't wait any longer than 1 jiffy.
++ */
++static enum xpc_retval
++xpc_allocate_msg_wait(struct xpc_channel *ch)
++{
++ enum xpc_retval ret;
++
++ if (ch->flags & XPC_C_DISCONNECTING) {
++ DBUG_ON(ch->reason == xpcInterrupted);
++ return ch->reason;
++ }
++
++ atomic_inc(&ch->n_on_msg_allocate_wq);
++ ret = interruptible_sleep_on_timeout(&ch->msg_allocate_wq, 1);
++ atomic_dec(&ch->n_on_msg_allocate_wq);
++
++ if (ch->flags & XPC_C_DISCONNECTING) {
++ ret = ch->reason;
++ DBUG_ON(ch->reason == xpcInterrupted);
++ } else if (ret == 0) {
++ ret = xpcTimeout;
++ } else {
++ ret = xpcInterrupted;
++ }
++
++ return ret;
++}
++
++/*
++ * Allocate an entry for a message from the message queue associated with the
++ * specified channel.
++ */
++static enum xpc_retval
++xpc_allocate_msg(struct xpc_channel *ch, u32 flags,
++ struct xpc_msg **address_of_msg)
++{
++ struct xpc_msg *msg;
++ enum xpc_retval ret;
++ s64 put;
++
++ /* this reference will be dropped in xpc_send_msg() */
++ xpc_msgqueue_ref(ch);
++
++ if (ch->flags & XPC_C_DISCONNECTING) {
++ xpc_msgqueue_deref(ch);
++ return ch->reason;
++ }
++ if (!(ch->flags & XPC_C_CONNECTED)) {
++ xpc_msgqueue_deref(ch);
++ return xpcNotConnected;
++ }
++
++ /*
++ * Get the next available message entry from the local message queue.
++ * If none are available, we'll make sure that we grab the latest
++ * GP values.
++ */
++ ret = xpcTimeout;
++
++ while (1) {
++
++ put = ch->w_local_GP.put;
++ rmb(); /* guarantee that .put loads before .get */
++ if (put - ch->w_remote_GP.get < ch->local_nentries) {
++
++ /* There are available message entries. We need to try
++ * to secure one for ourselves. We'll do this by trying
++ * to increment w_local_GP.put as long as someone else
++ * doesn't beat us to it. If they do, we'll have to
++ * try again.
++ */
++ if (cmpxchg(&ch->w_local_GP.put, put, put + 1) == put) {
++ /* we got the entry referenced by put */
++ break;
++ }
++ continue; /* try again */
++ }
++
++ /*
++ * There aren't any available msg entries at this time.
++ *
++ * In waiting for a message entry to become available,
++ * we set a timeout in case the other side is not
++ * sending completion IPIs. This lets us fake an IPI
++ * that will cause the IPI handler to fetch the latest
++ * GP values as if an IPI was sent by the other side.
++ */
++ if (ret == xpcTimeout)
++ xpc_IPI_send_local_msgrequest(ch);
++
++ if (flags & XPC_NOWAIT) {
++ xpc_msgqueue_deref(ch);
++ return xpcNoWait;
++ }
++
++ ret = xpc_allocate_msg_wait(ch);
++ if (ret != xpcInterrupted && ret != xpcTimeout) {
++ xpc_msgqueue_deref(ch);
++ return ret;
++ }
++ }
++
++ /* get the message's address and initialize it */
++ msg = (struct xpc_msg *)((u64)ch->local_msgqueue +
++ (put % ch->local_nentries) * ch->msg_size);
++
++ DBUG_ON(msg->flags != 0);
++ msg->number = put;
++
++ dev_dbg(xpc_chan, "w_local_GP.put changed to %ld; msg=0x%p, "
++ "msg_number=%ld, partid=%d, channel=%d\n", put + 1,
++ (void *)msg, msg->number, ch->partid, ch->number);
++
++ *address_of_msg = msg;
++
++ return xpcSuccess;
++}
++
++/*
++ * Allocate an entry for a message from the message queue associated with the
++ * specified channel. NOTE that this routine can sleep waiting for a message
++ * entry to become available. To not sleep, pass in the XPC_NOWAIT flag.
++ *
++ * Arguments:
++ *
++ * partid - ID of partition to which the channel is connected.
++ * ch_number - channel #.
++ * flags - see xpc.h for valid flags.
++ * payload - address of the allocated payload area pointer (filled in on
++ * return) in which the user-defined message is constructed.
++ */
++enum xpc_retval
++xpc_initiate_allocate(partid_t partid, int ch_number, u32 flags, void **payload)
++{
++ struct xpc_partition *part = &xpc_partitions[partid];
++ enum xpc_retval ret = xpcUnknownReason;
++ struct xpc_msg *msg = NULL;
++
++ DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
++ DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
++
++ *payload = NULL;
++
++ if (xpc_part_ref(part)) {
++ ret = xpc_allocate_msg(&part->channels[ch_number], flags, &msg);
++ xpc_part_deref(part);
++
++ if (msg != NULL)
++ *payload = &msg->payload;
++ }
++
++ return ret;
++}
++
++/*
++ * Now we actually send the messages that are ready to be sent by advancing
++ * the local message queue's Put value and then send an IPI to the recipient
++ * partition.
++ */
++static void
++xpc_send_msgs(struct xpc_channel *ch, s64 initial_put)
++{
++ struct xpc_msg *msg;
++ s64 put = initial_put + 1;
++ int send_IPI = 0;
++
++ while (1) {
++
++ while (1) {
++ if (put == ch->w_local_GP.put)
++ break;
++
++ msg = (struct xpc_msg *)((u64)ch->local_msgqueue +
++ (put % ch->local_nentries) *
++ ch->msg_size);
++
++ if (!(msg->flags & XPC_M_READY))
++ break;
++
++ put++;
++ }
++
++ if (put == initial_put) {
++ /* nothing's changed */
++ break;
++ }
++
++ if (cmpxchg_rel(&ch->local_GP->put, initial_put, put) !=
++ initial_put) {
++ /* someone else beat us to it */
++ DBUG_ON(ch->local_GP->put < initial_put);
++ break;
++ }
++
++ /* we just set the new value of local_GP->put */
++
++ dev_dbg(xpc_chan, "local_GP->put changed to %ld, partid=%d, "
++ "channel=%d\n", put, ch->partid, ch->number);
++
++ send_IPI = 1;
++
++ /*
++ * We need to ensure that the message referenced by
++ * local_GP->put is not XPC_M_READY or that local_GP->put
++ * equals w_local_GP.put, so we'll go have a look.
++ */
++ initial_put = put;
++ }
++
++ if (send_IPI)
++ xpc_IPI_send_msgrequest(ch);
++}
++
++/*
++ * Common code that does the actual sending of the message by advancing the
++ * local message queue's Put value and sends an IPI to the partition the
++ * message is being sent to.
++ */
++static enum xpc_retval
++xpc_send_msg(struct xpc_channel *ch, struct xpc_msg *msg, u8 notify_type,
++ xpc_notify_func func, void *key)
++{
++ enum xpc_retval ret = xpcSuccess;
++ struct xpc_notify *notify = notify;
++ s64 put, msg_number = msg->number;
++
++ DBUG_ON(notify_type == XPC_N_CALL && func == NULL);
++ DBUG_ON((((u64)msg - (u64)ch->local_msgqueue) / ch->msg_size) !=
++ msg_number % ch->local_nentries);
++ DBUG_ON(msg->flags & XPC_M_READY);
++
++ if (ch->flags & XPC_C_DISCONNECTING) {
++ /* drop the reference grabbed in xpc_allocate_msg() */
++ xpc_msgqueue_deref(ch);
++ return ch->reason;
++ }
++
++ if (notify_type != 0) {
++ /*
++ * Tell the remote side to send an ACK interrupt when the
++ * message has been delivered.
++ */
++ msg->flags |= XPC_M_INTERRUPT;
++
++ atomic_inc(&ch->n_to_notify);
++
++ notify = &ch->notify_queue[msg_number % ch->local_nentries];
++ notify->func = func;
++ notify->key = key;
++ notify->type = notify_type;
++
++ /* >>> is a mb() needed here? */
++
++ if (ch->flags & XPC_C_DISCONNECTING) {
++ /*
++ * An error occurred between our last error check and
++ * this one. We will try to clear the type field from
++ * the notify entry. If we succeed then
++ * xpc_disconnect_channel() didn't already process
++ * the notify entry.
++ */
++ if (cmpxchg(¬ify->type, notify_type, 0) ==
++ notify_type) {
++ atomic_dec(&ch->n_to_notify);
++ ret = ch->reason;
++ }
++
++ /* drop the reference grabbed in xpc_allocate_msg() */
++ xpc_msgqueue_deref(ch);
++ return ret;
++ }
++ }
++
++ msg->flags |= XPC_M_READY;
++
++ /*
++ * The preceding store of msg->flags must occur before the following
++ * load of ch->local_GP->put.
++ */
++ mb();
++
++ /* see if the message is next in line to be sent, if so send it */
++
++ put = ch->local_GP->put;
++ if (put == msg_number)
++ xpc_send_msgs(ch, put);
++
++ /* drop the reference grabbed in xpc_allocate_msg() */
++ xpc_msgqueue_deref(ch);
++ return ret;
++}
++
++/*
++ * Send a message previously allocated using xpc_initiate_allocate() on the
++ * specified channel connected to the specified partition.
++ *
++ * This routine will not wait for the message to be received, nor will
++ * notification be given when it does happen. Once this routine has returned
++ * the message entry allocated via xpc_initiate_allocate() is no longer
++ * accessable to the caller.
++ *
++ * This routine, although called by users, does not call xpc_part_ref() to
++ * ensure that the partition infrastructure is in place. It relies on the
++ * fact that we called xpc_msgqueue_ref() in xpc_allocate_msg().
++ *
++ * Arguments:
++ *
++ * partid - ID of partition to which the channel is connected.
++ * ch_number - channel # to send message on.
++ * payload - pointer to the payload area allocated via
++ * xpc_initiate_allocate().
++ */
++enum xpc_retval
++xpc_initiate_send(partid_t partid, int ch_number, void *payload)
++{
++ struct xpc_partition *part = &xpc_partitions[partid];
++ struct xpc_msg *msg = XPC_MSG_ADDRESS(payload);
++ enum xpc_retval ret;
++
++ dev_dbg(xpc_chan, "msg=0x%p, partid=%d, channel=%d\n", (void *)msg,
++ partid, ch_number);
++
++ DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
++ DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
++ DBUG_ON(msg == NULL);
++
++ ret = xpc_send_msg(&part->channels[ch_number], msg, 0, NULL, NULL);
++
++ return ret;
++}
++
++/*
++ * Send a message previously allocated using xpc_initiate_allocate on the
++ * specified channel connected to the specified partition.
++ *
++ * This routine will not wait for the message to be sent. Once this routine
++ * has returned the message entry allocated via xpc_initiate_allocate() is no
++ * longer accessable to the caller.
++ *
++ * Once the remote end of the channel has received the message, the function
++ * passed as an argument to xpc_initiate_send_notify() will be called. This
++ * allows the sender to free up or re-use any buffers referenced by the
++ * message, but does NOT mean the message has been processed at the remote
++ * end by a receiver.
++ *
++ * If this routine returns an error, the caller's function will NOT be called.
++ *
++ * This routine, although called by users, does not call xpc_part_ref() to
++ * ensure that the partition infrastructure is in place. It relies on the
++ * fact that we called xpc_msgqueue_ref() in xpc_allocate_msg().
++ *
++ * Arguments:
++ *
++ * partid - ID of partition to which the channel is connected.
++ * ch_number - channel # to send message on.
++ * payload - pointer to the payload area allocated via
++ * xpc_initiate_allocate().
++ * func - function to call with asynchronous notification of message
++ * receipt. THIS FUNCTION MUST BE NON-BLOCKING.
++ * key - user-defined key to be passed to the function when it's called.
++ */
++enum xpc_retval
++xpc_initiate_send_notify(partid_t partid, int ch_number, void *payload,
++ xpc_notify_func func, void *key)
++{
++ struct xpc_partition *part = &xpc_partitions[partid];
++ struct xpc_msg *msg = XPC_MSG_ADDRESS(payload);
++ enum xpc_retval ret;
++
++ dev_dbg(xpc_chan, "msg=0x%p, partid=%d, channel=%d\n", (void *)msg,
++ partid, ch_number);
++
++ DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
++ DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
++ DBUG_ON(msg == NULL);
++ DBUG_ON(func == NULL);
++
++ ret = xpc_send_msg(&part->channels[ch_number], msg, XPC_N_CALL,
++ func, key);
++ return ret;
++}
++
++static struct xpc_msg *
++xpc_pull_remote_msg(struct xpc_channel *ch, s64 get)
++{
++ struct xpc_partition *part = &xpc_partitions[ch->partid];
++ struct xpc_msg *remote_msg, *msg;
++ u32 msg_index, nmsgs;
++ u64 msg_offset;
++ enum xpc_retval ret;
++
++ if (mutex_lock_interruptible(&ch->msg_to_pull_mutex) != 0) {
++ /* we were interrupted by a signal */
++ return NULL;
++ }
++
++ while (get >= ch->next_msg_to_pull) {
++
++ /* pull as many messages as are ready and able to be pulled */
++
++ msg_index = ch->next_msg_to_pull % ch->remote_nentries;
++
++ DBUG_ON(ch->next_msg_to_pull >= ch->w_remote_GP.put);
++ nmsgs = ch->w_remote_GP.put - ch->next_msg_to_pull;
++ if (msg_index + nmsgs > ch->remote_nentries) {
++ /* ignore the ones that wrap the msg queue for now */
++ nmsgs = ch->remote_nentries - msg_index;
++ }
++
++ msg_offset = msg_index * ch->msg_size;
++ msg = (struct xpc_msg *)((u64)ch->remote_msgqueue + msg_offset);
++ remote_msg = (struct xpc_msg *)(ch->remote_msgqueue_pa +
++ msg_offset);
++
++ ret = xpc_pull_remote_cachelines(part, msg, remote_msg,
++ nmsgs * ch->msg_size);
++ if (ret != xpcSuccess) {
++
++ dev_dbg(xpc_chan, "failed to pull %d msgs starting with"
++ " msg %ld from partition %d, channel=%d, "
++ "ret=%d\n", nmsgs, ch->next_msg_to_pull,
++ ch->partid, ch->number, ret);
++
++ XPC_DEACTIVATE_PARTITION(part, ret);
++
++ mutex_unlock(&ch->msg_to_pull_mutex);
++ return NULL;
++ }
++
++ ch->next_msg_to_pull += nmsgs;
++ }
++
++ mutex_unlock(&ch->msg_to_pull_mutex);
++
++ /* return the message we were looking for */
++ msg_offset = (get % ch->remote_nentries) * ch->msg_size;
++ msg = (struct xpc_msg *)((u64)ch->remote_msgqueue + msg_offset);
++
++ return msg;
++}
++
++/*
++ * Get a message to be delivered.
++ */
++static struct xpc_msg *
++xpc_get_deliverable_msg(struct xpc_channel *ch)
++{
++ struct xpc_msg *msg = NULL;
++ s64 get;
++
++ do {
++ if (ch->flags & XPC_C_DISCONNECTING)
++ break;
++
++ get = ch->w_local_GP.get;
++ rmb(); /* guarantee that .get loads before .put */
++ if (get == ch->w_remote_GP.put)
++ break;
++
++ /* There are messages waiting to be pulled and delivered.
++ * We need to try to secure one for ourselves. We'll do this
++ * by trying to increment w_local_GP.get and hope that no one
++ * else beats us to it. If they do, we'll we'll simply have
++ * to try again for the next one.
++ */
++
++ if (cmpxchg(&ch->w_local_GP.get, get, get + 1) == get) {
++ /* we got the entry referenced by get */
++
++ dev_dbg(xpc_chan, "w_local_GP.get changed to %ld, "
++ "partid=%d, channel=%d\n", get + 1,
++ ch->partid, ch->number);
++
++ /* pull the message from the remote partition */
++
++ msg = xpc_pull_remote_msg(ch, get);
++
++ DBUG_ON(msg != NULL && msg->number != get);
++ DBUG_ON(msg != NULL && (msg->flags & XPC_M_DONE));
++ DBUG_ON(msg != NULL && !(msg->flags & XPC_M_READY));
++
++ break;
++ }
++
++ } while (1);
++
++ return msg;
++}
++
++/*
++ * Deliver a message to its intended recipient.
++ */
++void
++xpc_deliver_msg(struct xpc_channel *ch)
++{
++ struct xpc_msg *msg;
++
++ msg = xpc_get_deliverable_msg(ch);
++ if (msg != NULL) {
++
++ /*
++ * This ref is taken to protect the payload itself from being
++ * freed before the user is finished with it, which the user
++ * indicates by calling xpc_initiate_received().
++ */
++ xpc_msgqueue_ref(ch);
++
++ atomic_inc(&ch->kthreads_active);
++
++ if (ch->func != NULL) {
++ dev_dbg(xpc_chan, "ch->func() called, msg=0x%p, "
++ "msg_number=%ld, partid=%d, channel=%d\n",
++ (void *)msg, msg->number, ch->partid,
++ ch->number);
++
++ /* deliver the message to its intended recipient */
++ ch->func(xpcMsgReceived, ch->partid, ch->number,
++ &msg->payload, ch->key);
++
++ dev_dbg(xpc_chan, "ch->func() returned, msg=0x%p, "
++ "msg_number=%ld, partid=%d, channel=%d\n",
++ (void *)msg, msg->number, ch->partid,
++ ch->number);
++ }
++
++ atomic_dec(&ch->kthreads_active);
++ }
++}
++
++/*
++ * Now we actually acknowledge the messages that have been delivered and ack'd
++ * by advancing the cached remote message queue's Get value and if requested
++ * send an IPI to the message sender's partition.
++ */
++static void
++xpc_acknowledge_msgs(struct xpc_channel *ch, s64 initial_get, u8 msg_flags)
++{
++ struct xpc_msg *msg;
++ s64 get = initial_get + 1;
++ int send_IPI = 0;
++
++ while (1) {
++
++ while (1) {
++ if (get == ch->w_local_GP.get)
++ break;
++
++ msg = (struct xpc_msg *)((u64)ch->remote_msgqueue +
++ (get % ch->remote_nentries) *
++ ch->msg_size);
++
++ if (!(msg->flags & XPC_M_DONE))
++ break;
++
++ msg_flags |= msg->flags;
++ get++;
++ }
++
++ if (get == initial_get) {
++ /* nothing's changed */
++ break;
++ }
++
++ if (cmpxchg_rel(&ch->local_GP->get, initial_get, get) !=
++ initial_get) {
++ /* someone else beat us to it */
++ DBUG_ON(ch->local_GP->get <= initial_get);
++ break;
++ }
++
++ /* we just set the new value of local_GP->get */
++
++ dev_dbg(xpc_chan, "local_GP->get changed to %ld, partid=%d, "
++ "channel=%d\n", get, ch->partid, ch->number);
++
++ send_IPI = (msg_flags & XPC_M_INTERRUPT);
++
++ /*
++ * We need to ensure that the message referenced by
++ * local_GP->get is not XPC_M_DONE or that local_GP->get
++ * equals w_local_GP.get, so we'll go have a look.
++ */
++ initial_get = get;
++ }
++
++ if (send_IPI)
++ xpc_IPI_send_msgrequest(ch);
++}
++
++/*
++ * Acknowledge receipt of a delivered message.
++ *
++ * If a message has XPC_M_INTERRUPT set, send an interrupt to the partition
++ * that sent the message.
++ *
++ * This function, although called by users, does not call xpc_part_ref() to
++ * ensure that the partition infrastructure is in place. It relies on the
++ * fact that we called xpc_msgqueue_ref() in xpc_deliver_msg().
++ *
++ * Arguments:
++ *
++ * partid - ID of partition to which the channel is connected.
++ * ch_number - channel # message received on.
++ * payload - pointer to the payload area allocated via
++ * xpc_initiate_allocate().
++ */
++void
++xpc_initiate_received(partid_t partid, int ch_number, void *payload)
++{
++ struct xpc_partition *part = &xpc_partitions[partid];
++ struct xpc_channel *ch;
++ struct xpc_msg *msg = XPC_MSG_ADDRESS(payload);
++ s64 get, msg_number = msg->number;
++
++ DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
++ DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
++
++ ch = &part->channels[ch_number];
++
++ dev_dbg(xpc_chan, "msg=0x%p, msg_number=%ld, partid=%d, channel=%d\n",
++ (void *)msg, msg_number, ch->partid, ch->number);
++
++ DBUG_ON((((u64)msg - (u64)ch->remote_msgqueue) / ch->msg_size) !=
++ msg_number % ch->remote_nentries);
++ DBUG_ON(msg->flags & XPC_M_DONE);
++
++ msg->flags |= XPC_M_DONE;
++
++ /*
++ * The preceding store of msg->flags must occur before the following
++ * load of ch->local_GP->get.
++ */
++ mb();
++
++ /*
++ * See if this message is next in line to be acknowledged as having
++ * been delivered.
++ */
++ get = ch->local_GP->get;
++ if (get == msg_number)
++ xpc_acknowledge_msgs(ch, get, msg->flags);
++
++ /* the call to xpc_msgqueue_ref() was done by xpc_deliver_msg() */
++ xpc_msgqueue_deref(ch);
++}
+diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c
+new file mode 100644
+index 0000000..f673ba9
+--- /dev/null
++++ b/drivers/misc/sgi-xp/xpc_main.c
+@@ -0,0 +1,1323 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (c) 2004-2008 Silicon Graphics, Inc. All Rights Reserved.
++ */
++
++/*
++ * Cross Partition Communication (XPC) support - standard version.
++ *
++ * XPC provides a message passing capability that crosses partition
++ * boundaries. This module is made up of two parts:
++ *
++ * partition This part detects the presence/absence of other
++ * partitions. It provides a heartbeat and monitors
++ * the heartbeats of other partitions.
++ *
++ * channel This part manages the channels and sends/receives
++ * messages across them to/from other partitions.
++ *
++ * There are a couple of additional functions residing in XP, which
++ * provide an interface to XPC for its users.
++ *
++ *
++ * Caveats:
++ *
++ * . We currently have no way to determine which nasid an IPI came
++ * from. Thus, xpc_IPI_send() does a remote AMO write followed by
++ * an IPI. The AMO indicates where data is to be pulled from, so
++ * after the IPI arrives, the remote partition checks the AMO word.
++ * The IPI can actually arrive before the AMO however, so other code
++ * must periodically check for this case. Also, remote AMO operations
++ * do not reliably time out. Thus we do a remote PIO read solely to
++ * know whether the remote partition is down and whether we should
++ * stop sending IPIs to it. This remote PIO read operation is set up
++ * in a special nofault region so SAL knows to ignore (and cleanup)
++ * any errors due to the remote AMO write, PIO read, and/or PIO
++ * write operations.
++ *
++ * If/when new hardware solves this IPI problem, we should abandon
++ * the current approach.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/cache.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/reboot.h>
++#include <linux/completion.h>
++#include <linux/kdebug.h>
++#include <linux/kthread.h>
++#include <linux/uaccess.h>
++#include <asm/sn/intr.h>
++#include <asm/sn/sn_sal.h>
++#include "xpc.h"
++
++/* define two XPC debug device structures to be used with dev_dbg() et al */
++
++struct device_driver xpc_dbg_name = {
++ .name = "xpc"
++};
++
++struct device xpc_part_dbg_subname = {
++ .bus_id = {0}, /* set to "part" at xpc_init() time */
++ .driver = &xpc_dbg_name
++};
++
++struct device xpc_chan_dbg_subname = {
++ .bus_id = {0}, /* set to "chan" at xpc_init() time */
++ .driver = &xpc_dbg_name
++};
++
++struct device *xpc_part = &xpc_part_dbg_subname;
++struct device *xpc_chan = &xpc_chan_dbg_subname;
++
++static int xpc_kdebug_ignore;
++
++/* systune related variables for /proc/sys directories */
++
++static int xpc_hb_interval = XPC_HB_DEFAULT_INTERVAL;
++static int xpc_hb_min_interval = 1;
++static int xpc_hb_max_interval = 10;
++
++static int xpc_hb_check_interval = XPC_HB_CHECK_DEFAULT_INTERVAL;
++static int xpc_hb_check_min_interval = 10;
++static int xpc_hb_check_max_interval = 120;
++
++int xpc_disengage_request_timelimit = XPC_DISENGAGE_REQUEST_DEFAULT_TIMELIMIT;
++static int xpc_disengage_request_min_timelimit; /* = 0 */
++static int xpc_disengage_request_max_timelimit = 120;
++
++static ctl_table xpc_sys_xpc_hb_dir[] = {
++ {
++ .ctl_name = CTL_UNNUMBERED,
++ .procname = "hb_interval",
++ .data = &xpc_hb_interval,
++ .maxlen = sizeof(int),
++ .mode = 0644,
++ .proc_handler = &proc_dointvec_minmax,
++ .strategy = &sysctl_intvec,
++ .extra1 = &xpc_hb_min_interval,
++ .extra2 = &xpc_hb_max_interval},
++ {
++ .ctl_name = CTL_UNNUMBERED,
++ .procname = "hb_check_interval",
++ .data = &xpc_hb_check_interval,
++ .maxlen = sizeof(int),
++ .mode = 0644,
++ .proc_handler = &proc_dointvec_minmax,
++ .strategy = &sysctl_intvec,
++ .extra1 = &xpc_hb_check_min_interval,
++ .extra2 = &xpc_hb_check_max_interval},
++ {}
++};
++static ctl_table xpc_sys_xpc_dir[] = {
++ {
++ .ctl_name = CTL_UNNUMBERED,
++ .procname = "hb",
++ .mode = 0555,
++ .child = xpc_sys_xpc_hb_dir},
++ {
++ .ctl_name = CTL_UNNUMBERED,
++ .procname = "disengage_request_timelimit",
++ .data = &xpc_disengage_request_timelimit,
++ .maxlen = sizeof(int),
++ .mode = 0644,
++ .proc_handler = &proc_dointvec_minmax,
++ .strategy = &sysctl_intvec,
++ .extra1 = &xpc_disengage_request_min_timelimit,
++ .extra2 = &xpc_disengage_request_max_timelimit},
++ {}
++};
++static ctl_table xpc_sys_dir[] = {
++ {
++ .ctl_name = CTL_UNNUMBERED,
++ .procname = "xpc",
++ .mode = 0555,
++ .child = xpc_sys_xpc_dir},
++ {}
++};
++static struct ctl_table_header *xpc_sysctl;
++
++/* non-zero if any remote partition disengage request was timed out */
++int xpc_disengage_request_timedout;
++
++/* #of IRQs received */
++static atomic_t xpc_act_IRQ_rcvd;
++
++/* IRQ handler notifies this wait queue on receipt of an IRQ */
++static DECLARE_WAIT_QUEUE_HEAD(xpc_act_IRQ_wq);
++
++static unsigned long xpc_hb_check_timeout;
++
++/* notification that the xpc_hb_checker thread has exited */
++static DECLARE_COMPLETION(xpc_hb_checker_exited);
++
++/* notification that the xpc_discovery thread has exited */
++static DECLARE_COMPLETION(xpc_discovery_exited);
++
++static struct timer_list xpc_hb_timer;
++
++static void xpc_kthread_waitmsgs(struct xpc_partition *, struct xpc_channel *);
++
++static int xpc_system_reboot(struct notifier_block *, unsigned long, void *);
++static struct notifier_block xpc_reboot_notifier = {
++ .notifier_call = xpc_system_reboot,
++};
++
++static int xpc_system_die(struct notifier_block *, unsigned long, void *);
++static struct notifier_block xpc_die_notifier = {
++ .notifier_call = xpc_system_die,
++};
++
++/*
++ * Timer function to enforce the timelimit on the partition disengage request.
++ */
++static void
++xpc_timeout_partition_disengage_request(unsigned long data)
++{
++ struct xpc_partition *part = (struct xpc_partition *)data;
++
++ DBUG_ON(time_before(jiffies, part->disengage_request_timeout));
++
++ (void)xpc_partition_disengaged(part);
++
++ DBUG_ON(part->disengage_request_timeout != 0);
++ DBUG_ON(xpc_partition_engaged(1UL << XPC_PARTID(part)) != 0);
++}
++
++/*
++ * Notify the heartbeat check thread that an IRQ has been received.
++ */
++static irqreturn_t
++xpc_act_IRQ_handler(int irq, void *dev_id)
++{
++ atomic_inc(&xpc_act_IRQ_rcvd);
++ wake_up_interruptible(&xpc_act_IRQ_wq);
++ return IRQ_HANDLED;
++}
++
++/*
++ * Timer to produce the heartbeat. The timer structures function is
++ * already set when this is initially called. A tunable is used to
++ * specify when the next timeout should occur.
++ */
++static void
++xpc_hb_beater(unsigned long dummy)
++{
++ xpc_vars->heartbeat++;
++
++ if (time_after_eq(jiffies, xpc_hb_check_timeout))
++ wake_up_interruptible(&xpc_act_IRQ_wq);
++
++ xpc_hb_timer.expires = jiffies + (xpc_hb_interval * HZ);
++ add_timer(&xpc_hb_timer);
++}
++
++/*
++ * This thread is responsible for nearly all of the partition
++ * activation/deactivation.
++ */
++static int
++xpc_hb_checker(void *ignore)
++{
++ int last_IRQ_count = 0;
++ int new_IRQ_count;
++ int force_IRQ = 0;
++
++ /* this thread was marked active by xpc_hb_init() */
++
++ set_cpus_allowed(current, cpumask_of_cpu(XPC_HB_CHECK_CPU));
++
++ /* set our heartbeating to other partitions into motion */
++ xpc_hb_check_timeout = jiffies + (xpc_hb_check_interval * HZ);
++ xpc_hb_beater(0);
++
++ while (!xpc_exiting) {
++
++ dev_dbg(xpc_part, "woke up with %d ticks rem; %d IRQs have "
++ "been received\n",
++ (int)(xpc_hb_check_timeout - jiffies),
++ atomic_read(&xpc_act_IRQ_rcvd) - last_IRQ_count);
++
++ /* checking of remote heartbeats is skewed by IRQ handling */
++ if (time_after_eq(jiffies, xpc_hb_check_timeout)) {
++ dev_dbg(xpc_part, "checking remote heartbeats\n");
++ xpc_check_remote_hb();
++
++ /*
++ * We need to periodically recheck to ensure no
++ * IPI/AMO pairs have been missed. That check
++ * must always reset xpc_hb_check_timeout.
++ */
++ force_IRQ = 1;
++ }
++
++ /* check for outstanding IRQs */
++ new_IRQ_count = atomic_read(&xpc_act_IRQ_rcvd);
++ if (last_IRQ_count < new_IRQ_count || force_IRQ != 0) {
++ force_IRQ = 0;
++
++ dev_dbg(xpc_part, "found an IRQ to process; will be "
++ "resetting xpc_hb_check_timeout\n");
++
++ last_IRQ_count += xpc_identify_act_IRQ_sender();
++ if (last_IRQ_count < new_IRQ_count) {
++ /* retry once to help avoid missing AMO */
++ (void)xpc_identify_act_IRQ_sender();
++ }
++ last_IRQ_count = new_IRQ_count;
++
++ xpc_hb_check_timeout = jiffies +
++ (xpc_hb_check_interval * HZ);
++ }
++
++ /* wait for IRQ or timeout */
++ (void)wait_event_interruptible(xpc_act_IRQ_wq,
++ (last_IRQ_count <
++ atomic_read(&xpc_act_IRQ_rcvd)
++ || time_after_eq(jiffies,
++ xpc_hb_check_timeout) ||
++ xpc_exiting));
++ }
++
++ dev_dbg(xpc_part, "heartbeat checker is exiting\n");
++
++ /* mark this thread as having exited */
++ complete(&xpc_hb_checker_exited);
++ return 0;
++}
++
++/*
++ * This thread will attempt to discover other partitions to activate
++ * based on info provided by SAL. This new thread is short lived and
++ * will exit once discovery is complete.
++ */
++static int
++xpc_initiate_discovery(void *ignore)
++{
++ xpc_discovery();
++
++ dev_dbg(xpc_part, "discovery thread is exiting\n");
++
++ /* mark this thread as having exited */
++ complete(&xpc_discovery_exited);
++ return 0;
++}
++
++/*
++ * Establish first contact with the remote partititon. This involves pulling
++ * the XPC per partition variables from the remote partition and waiting for
++ * the remote partition to pull ours.
++ */
++static enum xpc_retval
++xpc_make_first_contact(struct xpc_partition *part)
++{
++ enum xpc_retval ret;
++
++ while ((ret = xpc_pull_remote_vars_part(part)) != xpcSuccess) {
++ if (ret != xpcRetry) {
++ XPC_DEACTIVATE_PARTITION(part, ret);
++ return ret;
++ }
++
++ dev_dbg(xpc_chan, "waiting to make first contact with "
++ "partition %d\n", XPC_PARTID(part));
++
++ /* wait a 1/4 of a second or so */
++ (void)msleep_interruptible(250);
++
++ if (part->act_state == XPC_P_DEACTIVATING)
++ return part->reason;
++ }
++
++ return xpc_mark_partition_active(part);
++}
++
++/*
++ * The first kthread assigned to a newly activated partition is the one
++ * created by XPC HB with which it calls xpc_partition_up(). XPC hangs on to
++ * that kthread until the partition is brought down, at which time that kthread
++ * returns back to XPC HB. (The return of that kthread will signify to XPC HB
++ * that XPC has dismantled all communication infrastructure for the associated
++ * partition.) This kthread becomes the channel manager for that partition.
++ *
++ * Each active partition has a channel manager, who, besides connecting and
++ * disconnecting channels, will ensure that each of the partition's connected
++ * channels has the required number of assigned kthreads to get the work done.
++ */
++static void
++xpc_channel_mgr(struct xpc_partition *part)
++{
++ while (part->act_state != XPC_P_DEACTIVATING ||
++ atomic_read(&part->nchannels_active) > 0 ||
++ !xpc_partition_disengaged(part)) {
++
++ xpc_process_channel_activity(part);
++
++ /*
++ * Wait until we've been requested to activate kthreads or
++ * all of the channel's message queues have been torn down or
++ * a signal is pending.
++ *
++ * The channel_mgr_requests is set to 1 after being awakened,
++ * This is done to prevent the channel mgr from making one pass
++ * through the loop for each request, since he will
++ * be servicing all the requests in one pass. The reason it's
++ * set to 1 instead of 0 is so that other kthreads will know
++ * that the channel mgr is running and won't bother trying to
++ * wake him up.
++ */
++ atomic_dec(&part->channel_mgr_requests);
++ (void)wait_event_interruptible(part->channel_mgr_wq,
++ (atomic_read(&part->channel_mgr_requests) > 0 ||
++ part->local_IPI_amo != 0 ||
++ (part->act_state == XPC_P_DEACTIVATING &&
++ atomic_read(&part->nchannels_active) == 0 &&
++ xpc_partition_disengaged(part))));
++ atomic_set(&part->channel_mgr_requests, 1);
++ }
++}
++
++/*
++ * When XPC HB determines that a partition has come up, it will create a new
++ * kthread and that kthread will call this function to attempt to set up the
++ * basic infrastructure used for Cross Partition Communication with the newly
++ * upped partition.
++ *
++ * The kthread that was created by XPC HB and which setup the XPC
++ * infrastructure will remain assigned to the partition until the partition
++ * goes down. At which time the kthread will teardown the XPC infrastructure
++ * and then exit.
++ *
++ * XPC HB will put the remote partition's XPC per partition specific variables
++ * physical address into xpc_partitions[partid].remote_vars_part_pa prior to
++ * calling xpc_partition_up().
++ */
++static void
++xpc_partition_up(struct xpc_partition *part)
++{
++ DBUG_ON(part->channels != NULL);
++
++ dev_dbg(xpc_chan, "activating partition %d\n", XPC_PARTID(part));
++
++ if (xpc_setup_infrastructure(part) != xpcSuccess)
++ return;
++
++ /*
++ * The kthread that XPC HB called us with will become the
++ * channel manager for this partition. It will not return
++ * back to XPC HB until the partition's XPC infrastructure
++ * has been dismantled.
++ */
++
++ (void)xpc_part_ref(part); /* this will always succeed */
++
++ if (xpc_make_first_contact(part) == xpcSuccess)
++ xpc_channel_mgr(part);
++
++ xpc_part_deref(part);
++
++ xpc_teardown_infrastructure(part);
++}
++
++static int
++xpc_activating(void *__partid)
++{
++ partid_t partid = (u64)__partid;
++ struct xpc_partition *part = &xpc_partitions[partid];
++ unsigned long irq_flags;
++
++ DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
++
++ spin_lock_irqsave(&part->act_lock, irq_flags);
++
++ if (part->act_state == XPC_P_DEACTIVATING) {
++ part->act_state = XPC_P_INACTIVE;
++ spin_unlock_irqrestore(&part->act_lock, irq_flags);
++ part->remote_rp_pa = 0;
++ return 0;
++ }
++
++ /* indicate the thread is activating */
++ DBUG_ON(part->act_state != XPC_P_ACTIVATION_REQ);
++ part->act_state = XPC_P_ACTIVATING;
++
++ XPC_SET_REASON(part, 0, 0);
++ spin_unlock_irqrestore(&part->act_lock, irq_flags);
++
++ dev_dbg(xpc_part, "bringing partition %d up\n", partid);
++
++ /*
++ * Register the remote partition's AMOs with SAL so it can handle
++ * and cleanup errors within that address range should the remote
++ * partition go down. We don't unregister this range because it is
++ * difficult to tell when outstanding writes to the remote partition
++ * are finished and thus when it is safe to unregister. This should
++ * not result in wasted space in the SAL xp_addr_region table because
++ * we should get the same page for remote_amos_page_pa after module
++ * reloads and system reboots.
++ */
++ if (sn_register_xp_addr_region(part->remote_amos_page_pa,
++ PAGE_SIZE, 1) < 0) {
++ dev_warn(xpc_part, "xpc_partition_up(%d) failed to register "
++ "xp_addr region\n", partid);
++
++ spin_lock_irqsave(&part->act_lock, irq_flags);
++ part->act_state = XPC_P_INACTIVE;
++ XPC_SET_REASON(part, xpcPhysAddrRegFailed, __LINE__);
++ spin_unlock_irqrestore(&part->act_lock, irq_flags);
++ part->remote_rp_pa = 0;
++ return 0;
++ }
++
++ xpc_allow_hb(partid, xpc_vars);
++ xpc_IPI_send_activated(part);
++
++ /*
++ * xpc_partition_up() holds this thread and marks this partition as
++ * XPC_P_ACTIVE by calling xpc_hb_mark_active().
++ */
++ (void)xpc_partition_up(part);
++
++ xpc_disallow_hb(partid, xpc_vars);
++ xpc_mark_partition_inactive(part);
++
++ if (part->reason == xpcReactivating) {
++ /* interrupting ourselves results in activating partition */
++ xpc_IPI_send_reactivate(part);
++ }
++
++ return 0;
++}
++
++void
++xpc_activate_partition(struct xpc_partition *part)
++{
++ partid_t partid = XPC_PARTID(part);
++ unsigned long irq_flags;
++ struct task_struct *kthread;
++
++ spin_lock_irqsave(&part->act_lock, irq_flags);
++
++ DBUG_ON(part->act_state != XPC_P_INACTIVE);
++
++ part->act_state = XPC_P_ACTIVATION_REQ;
++ XPC_SET_REASON(part, xpcCloneKThread, __LINE__);
++
++ spin_unlock_irqrestore(&part->act_lock, irq_flags);
++
++ kthread = kthread_run(xpc_activating, (void *)((u64)partid), "xpc%02d",
++ partid);
++ if (IS_ERR(kthread)) {
++ spin_lock_irqsave(&part->act_lock, irq_flags);
++ part->act_state = XPC_P_INACTIVE;
++ XPC_SET_REASON(part, xpcCloneKThreadFailed, __LINE__);
++ spin_unlock_irqrestore(&part->act_lock, irq_flags);
++ }
++}
++
++/*
++ * Handle the receipt of a SGI_XPC_NOTIFY IRQ by seeing whether the specified
++ * partition actually sent it. Since SGI_XPC_NOTIFY IRQs may be shared by more
++ * than one partition, we use an AMO_t structure per partition to indicate
++ * whether a partition has sent an IPI or not. If it has, then wake up the
++ * associated kthread to handle it.
++ *
++ * All SGI_XPC_NOTIFY IRQs received by XPC are the result of IPIs sent by XPC
++ * running on other partitions.
++ *
++ * Noteworthy Arguments:
++ *
++ * irq - Interrupt ReQuest number. NOT USED.
++ *
++ * dev_id - partid of IPI's potential sender.
++ */
++irqreturn_t
++xpc_notify_IRQ_handler(int irq, void *dev_id)
++{
++ partid_t partid = (partid_t) (u64)dev_id;
++ struct xpc_partition *part = &xpc_partitions[partid];
++
++ DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
++
++ if (xpc_part_ref(part)) {
++ xpc_check_for_channel_activity(part);
++
++ xpc_part_deref(part);
++ }
++ return IRQ_HANDLED;
++}
++
++/*
++ * Check to see if xpc_notify_IRQ_handler() dropped any IPIs on the floor
++ * because the write to their associated IPI amo completed after the IRQ/IPI
++ * was received.
++ */
++void
++xpc_dropped_IPI_check(struct xpc_partition *part)
++{
++ if (xpc_part_ref(part)) {
++ xpc_check_for_channel_activity(part);
++
++ part->dropped_IPI_timer.expires = jiffies +
++ XPC_P_DROPPED_IPI_WAIT;
++ add_timer(&part->dropped_IPI_timer);
++ xpc_part_deref(part);
++ }
++}
++
++void
++xpc_activate_kthreads(struct xpc_channel *ch, int needed)
++{
++ int idle = atomic_read(&ch->kthreads_idle);
++ int assigned = atomic_read(&ch->kthreads_assigned);
++ int wakeup;
++
++ DBUG_ON(needed <= 0);
++
++ if (idle > 0) {
++ wakeup = (needed > idle) ? idle : needed;
++ needed -= wakeup;
++
++ dev_dbg(xpc_chan, "wakeup %d idle kthreads, partid=%d, "
++ "channel=%d\n", wakeup, ch->partid, ch->number);
++
++ /* only wakeup the requested number of kthreads */
++ wake_up_nr(&ch->idle_wq, wakeup);
++ }
++
++ if (needed <= 0)
++ return;
++
++ if (needed + assigned > ch->kthreads_assigned_limit) {
++ needed = ch->kthreads_assigned_limit - assigned;
++ if (needed <= 0)
++ return;
++ }
++
++ dev_dbg(xpc_chan, "create %d new kthreads, partid=%d, channel=%d\n",
++ needed, ch->partid, ch->number);
++
++ xpc_create_kthreads(ch, needed, 0);
++}
++
++/*
++ * This function is where XPC's kthreads wait for messages to deliver.
++ */
++static void
++xpc_kthread_waitmsgs(struct xpc_partition *part, struct xpc_channel *ch)
++{
++ do {
++ /* deliver messages to their intended recipients */
++
++ while (ch->w_local_GP.get < ch->w_remote_GP.put &&
++ !(ch->flags & XPC_C_DISCONNECTING)) {
++ xpc_deliver_msg(ch);
++ }
++
++ if (atomic_inc_return(&ch->kthreads_idle) >
++ ch->kthreads_idle_limit) {
++ /* too many idle kthreads on this channel */
++ atomic_dec(&ch->kthreads_idle);
++ break;
++ }
++
++ dev_dbg(xpc_chan, "idle kthread calling "
++ "wait_event_interruptible_exclusive()\n");
++
++ (void)wait_event_interruptible_exclusive(ch->idle_wq,
++ (ch->w_local_GP.get < ch->w_remote_GP.put ||
++ (ch->flags & XPC_C_DISCONNECTING)));
++
++ atomic_dec(&ch->kthreads_idle);
++
++ } while (!(ch->flags & XPC_C_DISCONNECTING));
++}
++
++static int
++xpc_kthread_start(void *args)
++{
++ partid_t partid = XPC_UNPACK_ARG1(args);
++ u16 ch_number = XPC_UNPACK_ARG2(args);
++ struct xpc_partition *part = &xpc_partitions[partid];
++ struct xpc_channel *ch;
++ int n_needed;
++ unsigned long irq_flags;
++
++ dev_dbg(xpc_chan, "kthread starting, partid=%d, channel=%d\n",
++ partid, ch_number);
++
++ ch = &part->channels[ch_number];
++
++ if (!(ch->flags & XPC_C_DISCONNECTING)) {
++
++ /* let registerer know that connection has been established */
++
++ spin_lock_irqsave(&ch->lock, irq_flags);
++ if (!(ch->flags & XPC_C_CONNECTEDCALLOUT)) {
++ ch->flags |= XPC_C_CONNECTEDCALLOUT;
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++
++ xpc_connected_callout(ch);
++
++ spin_lock_irqsave(&ch->lock, irq_flags);
++ ch->flags |= XPC_C_CONNECTEDCALLOUT_MADE;
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++
++ /*
++ * It is possible that while the callout was being
++ * made that the remote partition sent some messages.
++ * If that is the case, we may need to activate
++ * additional kthreads to help deliver them. We only
++ * need one less than total #of messages to deliver.
++ */
++ n_needed = ch->w_remote_GP.put - ch->w_local_GP.get - 1;
++ if (n_needed > 0 && !(ch->flags & XPC_C_DISCONNECTING))
++ xpc_activate_kthreads(ch, n_needed);
++
++ } else {
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++ }
++
++ xpc_kthread_waitmsgs(part, ch);
++ }
++
++ /* let registerer know that connection is disconnecting */
++
++ spin_lock_irqsave(&ch->lock, irq_flags);
++ if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
++ !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) {
++ ch->flags |= XPC_C_DISCONNECTINGCALLOUT;
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++
++ xpc_disconnect_callout(ch, xpcDisconnecting);
++
++ spin_lock_irqsave(&ch->lock, irq_flags);
++ ch->flags |= XPC_C_DISCONNECTINGCALLOUT_MADE;
++ }
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++
++ if (atomic_dec_return(&ch->kthreads_assigned) == 0) {
++ if (atomic_dec_return(&part->nchannels_engaged) == 0) {
++ xpc_mark_partition_disengaged(part);
++ xpc_IPI_send_disengage(part);
++ }
++ }
++
++ xpc_msgqueue_deref(ch);
++
++ dev_dbg(xpc_chan, "kthread exiting, partid=%d, channel=%d\n",
++ partid, ch_number);
++
++ xpc_part_deref(part);
++ return 0;
++}
++
++/*
++ * For each partition that XPC has established communications with, there is
++ * a minimum of one kernel thread assigned to perform any operation that
++ * may potentially sleep or block (basically the callouts to the asynchronous
++ * functions registered via xpc_connect()).
++ *
++ * Additional kthreads are created and destroyed by XPC as the workload
++ * demands.
++ *
++ * A kthread is assigned to one of the active channels that exists for a given
++ * partition.
++ */
++void
++xpc_create_kthreads(struct xpc_channel *ch, int needed,
++ int ignore_disconnecting)
++{
++ unsigned long irq_flags;
++ u64 args = XPC_PACK_ARGS(ch->partid, ch->number);
++ struct xpc_partition *part = &xpc_partitions[ch->partid];
++ struct task_struct *kthread;
++
++ while (needed-- > 0) {
++
++ /*
++ * The following is done on behalf of the newly created
++ * kthread. That kthread is responsible for doing the
++ * counterpart to the following before it exits.
++ */
++ if (ignore_disconnecting) {
++ if (!atomic_inc_not_zero(&ch->kthreads_assigned)) {
++ /* kthreads assigned had gone to zero */
++ BUG_ON(!(ch->flags &
++ XPC_C_DISCONNECTINGCALLOUT_MADE));
++ break;
++ }
++
++ } else if (ch->flags & XPC_C_DISCONNECTING) {
++ break;
++
++ } else if (atomic_inc_return(&ch->kthreads_assigned) == 1) {
++ if (atomic_inc_return(&part->nchannels_engaged) == 1)
++ xpc_mark_partition_engaged(part);
++ }
++ (void)xpc_part_ref(part);
++ xpc_msgqueue_ref(ch);
++
++ kthread = kthread_run(xpc_kthread_start, (void *)args,
++ "xpc%02dc%d", ch->partid, ch->number);
++ if (IS_ERR(kthread)) {
++ /* the fork failed */
++
++ /*
++ * NOTE: if (ignore_disconnecting &&
++ * !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) is true,
++ * then we'll deadlock if all other kthreads assigned
++ * to this channel are blocked in the channel's
++ * registerer, because the only thing that will unblock
++ * them is the xpcDisconnecting callout that this
++ * failed kthread_run() would have made.
++ */
++
++ if (atomic_dec_return(&ch->kthreads_assigned) == 0 &&
++ atomic_dec_return(&part->nchannels_engaged) == 0) {
++ xpc_mark_partition_disengaged(part);
++ xpc_IPI_send_disengage(part);
++ }
++ xpc_msgqueue_deref(ch);
++ xpc_part_deref(part);
++
++ if (atomic_read(&ch->kthreads_assigned) <
++ ch->kthreads_idle_limit) {
++ /*
++ * Flag this as an error only if we have an
++ * insufficient #of kthreads for the channel
++ * to function.
++ */
++ spin_lock_irqsave(&ch->lock, irq_flags);
++ XPC_DISCONNECT_CHANNEL(ch, xpcLackOfResources,
++ &irq_flags);
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++ }
++ break;
++ }
++ }
++}
++
++void
++xpc_disconnect_wait(int ch_number)
++{
++ unsigned long irq_flags;
++ partid_t partid;
++ struct xpc_partition *part;
++ struct xpc_channel *ch;
++ int wakeup_channel_mgr;
++
++ /* now wait for all callouts to the caller's function to cease */
++ for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
++ part = &xpc_partitions[partid];
++
++ if (!xpc_part_ref(part))
++ continue;
++
++ ch = &part->channels[ch_number];
++
++ if (!(ch->flags & XPC_C_WDISCONNECT)) {
++ xpc_part_deref(part);
++ continue;
++ }
++
++ wait_for_completion(&ch->wdisconnect_wait);
++
++ spin_lock_irqsave(&ch->lock, irq_flags);
++ DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED));
++ wakeup_channel_mgr = 0;
++
++ if (ch->delayed_IPI_flags) {
++ if (part->act_state != XPC_P_DEACTIVATING) {
++ spin_lock(&part->IPI_lock);
++ XPC_SET_IPI_FLAGS(part->local_IPI_amo,
++ ch->number,
++ ch->delayed_IPI_flags);
++ spin_unlock(&part->IPI_lock);
++ wakeup_channel_mgr = 1;
++ }
++ ch->delayed_IPI_flags = 0;
++ }
++
++ ch->flags &= ~XPC_C_WDISCONNECT;
++ spin_unlock_irqrestore(&ch->lock, irq_flags);
++
++ if (wakeup_channel_mgr)
++ xpc_wakeup_channel_mgr(part);
++
++ xpc_part_deref(part);
++ }
++}
++
++static void
++xpc_do_exit(enum xpc_retval reason)
++{
++ partid_t partid;
++ int active_part_count, printed_waiting_msg = 0;
++ struct xpc_partition *part;
++ unsigned long printmsg_time, disengage_request_timeout = 0;
++
++ /* a 'rmmod XPC' and a 'reboot' cannot both end up here together */
++ DBUG_ON(xpc_exiting == 1);
++
++ /*
++ * Let the heartbeat checker thread and the discovery thread
++ * (if one is running) know that they should exit. Also wake up
++ * the heartbeat checker thread in case it's sleeping.
++ */
++ xpc_exiting = 1;
++ wake_up_interruptible(&xpc_act_IRQ_wq);
++
++ /* ignore all incoming interrupts */
++ free_irq(SGI_XPC_ACTIVATE, NULL);
++
++ /* wait for the discovery thread to exit */
++ wait_for_completion(&xpc_discovery_exited);
++
++ /* wait for the heartbeat checker thread to exit */
++ wait_for_completion(&xpc_hb_checker_exited);
++
++ /* sleep for a 1/3 of a second or so */
++ (void)msleep_interruptible(300);
++
++ /* wait for all partitions to become inactive */
++
++ printmsg_time = jiffies + (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ);
++ xpc_disengage_request_timedout = 0;
++
++ do {
++ active_part_count = 0;
++
++ for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
++ part = &xpc_partitions[partid];
++
++ if (xpc_partition_disengaged(part) &&
++ part->act_state == XPC_P_INACTIVE) {
++ continue;
++ }
++
++ active_part_count++;
++
++ XPC_DEACTIVATE_PARTITION(part, reason);
++
++ if (part->disengage_request_timeout >
++ disengage_request_timeout) {
++ disengage_request_timeout =
++ part->disengage_request_timeout;
++ }
++ }
++
++ if (xpc_partition_engaged(-1UL)) {
++ if (time_after(jiffies, printmsg_time)) {
++ dev_info(xpc_part, "waiting for remote "
++ "partitions to disengage, timeout in "
++ "%ld seconds\n",
++ (disengage_request_timeout - jiffies)
++ / HZ);
++ printmsg_time = jiffies +
++ (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ);
++ printed_waiting_msg = 1;
++ }
++
++ } else if (active_part_count > 0) {
++ if (printed_waiting_msg) {
++ dev_info(xpc_part, "waiting for local partition"
++ " to disengage\n");
++ printed_waiting_msg = 0;
++ }
++
++ } else {
++ if (!xpc_disengage_request_timedout) {
++ dev_info(xpc_part, "all partitions have "
++ "disengaged\n");
++ }
++ break;
++ }
++
++ /* sleep for a 1/3 of a second or so */
++ (void)msleep_interruptible(300);
++
++ } while (1);
++
++ DBUG_ON(xpc_partition_engaged(-1UL));
++
++ /* indicate to others that our reserved page is uninitialized */
++ xpc_rsvd_page->vars_pa = 0;
++
++ /* now it's time to eliminate our heartbeat */
++ del_timer_sync(&xpc_hb_timer);
++ DBUG_ON(xpc_vars->heartbeating_to_mask != 0);
++
++ if (reason == xpcUnloading) {
++ /* take ourselves off of the reboot_notifier_list */
++ (void)unregister_reboot_notifier(&xpc_reboot_notifier);
++
++ /* take ourselves off of the die_notifier list */
++ (void)unregister_die_notifier(&xpc_die_notifier);
++ }
++
++ /* close down protections for IPI operations */
++ xpc_restrict_IPI_ops();
++
++ /* clear the interface to XPC's functions */
++ xpc_clear_interface();
++
++ if (xpc_sysctl)
++ unregister_sysctl_table(xpc_sysctl);
++
++ kfree(xpc_remote_copy_buffer_base);
++}
++
++/*
++ * This function is called when the system is being rebooted.
++ */
++static int
++xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused)
++{
++ enum xpc_retval reason;
++
++ switch (event) {
++ case SYS_RESTART:
++ reason = xpcSystemReboot;
++ break;
++ case SYS_HALT:
++ reason = xpcSystemHalt;
++ break;
++ case SYS_POWER_OFF:
++ reason = xpcSystemPoweroff;
++ break;
++ default:
++ reason = xpcSystemGoingDown;
++ }
++
++ xpc_do_exit(reason);
++ return NOTIFY_DONE;
++}
++
++/*
++ * Notify other partitions to disengage from all references to our memory.
++ */
++static void
++xpc_die_disengage(void)
++{
++ struct xpc_partition *part;
++ partid_t partid;
++ unsigned long engaged;
++ long time, printmsg_time, disengage_request_timeout;
++
++ /* keep xpc_hb_checker thread from doing anything (just in case) */
++ xpc_exiting = 1;
++
++ xpc_vars->heartbeating_to_mask = 0; /* indicate we're deactivated */
++
++ for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
++ part = &xpc_partitions[partid];
++
++ if (!XPC_SUPPORTS_DISENGAGE_REQUEST(part->
++ remote_vars_version)) {
++
++ /* just in case it was left set by an earlier XPC */
++ xpc_clear_partition_engaged(1UL << partid);
++ continue;
++ }
++
++ if (xpc_partition_engaged(1UL << partid) ||
++ part->act_state != XPC_P_INACTIVE) {
++ xpc_request_partition_disengage(part);
++ xpc_mark_partition_disengaged(part);
++ xpc_IPI_send_disengage(part);
++ }
++ }
++
++ time = rtc_time();
++ printmsg_time = time +
++ (XPC_DISENGAGE_PRINTMSG_INTERVAL * sn_rtc_cycles_per_second);
++ disengage_request_timeout = time +
++ (xpc_disengage_request_timelimit * sn_rtc_cycles_per_second);
++
++ /* wait for all other partitions to disengage from us */
++
++ while (1) {
++ engaged = xpc_partition_engaged(-1UL);
++ if (!engaged) {
++ dev_info(xpc_part, "all partitions have disengaged\n");
++ break;
++ }
++
++ time = rtc_time();
++ if (time >= disengage_request_timeout) {
++ for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
++ if (engaged & (1UL << partid)) {
++ dev_info(xpc_part, "disengage from "
++ "remote partition %d timed "
++ "out\n", partid);
++ }
++ }
++ break;
++ }
++
++ if (time >= printmsg_time) {
++ dev_info(xpc_part, "waiting for remote partitions to "
++ "disengage, timeout in %ld seconds\n",
++ (disengage_request_timeout - time) /
++ sn_rtc_cycles_per_second);
++ printmsg_time = time +
++ (XPC_DISENGAGE_PRINTMSG_INTERVAL *
++ sn_rtc_cycles_per_second);
++ }
++ }
++}
++
++/*
++ * This function is called when the system is being restarted or halted due
++ * to some sort of system failure. If this is the case we need to notify the
++ * other partitions to disengage from all references to our memory.
++ * This function can also be called when our heartbeater could be offlined
++ * for a time. In this case we need to notify other partitions to not worry
++ * about the lack of a heartbeat.
++ */
++static int
++xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused)
++{
++ switch (event) {
++ case DIE_MACHINE_RESTART:
++ case DIE_MACHINE_HALT:
++ xpc_die_disengage();
++ break;
++
++ case DIE_KDEBUG_ENTER:
++ /* Should lack of heartbeat be ignored by other partitions? */
++ if (!xpc_kdebug_ignore)
++ break;
++
++ /* fall through */
++ case DIE_MCA_MONARCH_ENTER:
++ case DIE_INIT_MONARCH_ENTER:
++ xpc_vars->heartbeat++;
++ xpc_vars->heartbeat_offline = 1;
++ break;
++
++ case DIE_KDEBUG_LEAVE:
++ /* Is lack of heartbeat being ignored by other partitions? */
++ if (!xpc_kdebug_ignore)
++ break;
++
++ /* fall through */
++ case DIE_MCA_MONARCH_LEAVE:
++ case DIE_INIT_MONARCH_LEAVE:
++ xpc_vars->heartbeat++;
++ xpc_vars->heartbeat_offline = 0;
++ break;
++ }
++
++ return NOTIFY_DONE;
++}
++
++int __init
++xpc_init(void)
++{
++ int ret;
++ partid_t partid;
++ struct xpc_partition *part;
++ struct task_struct *kthread;
++ size_t buf_size;
++
++ if (!ia64_platform_is("sn2"))
++ return -ENODEV;
++
++ buf_size = max(XPC_RP_VARS_SIZE,
++ XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES);
++ xpc_remote_copy_buffer = xpc_kmalloc_cacheline_aligned(buf_size,
++ GFP_KERNEL,
++ &xpc_remote_copy_buffer_base);
++ if (xpc_remote_copy_buffer == NULL)
++ return -ENOMEM;
++
++ snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part");
++ snprintf(xpc_chan->bus_id, BUS_ID_SIZE, "chan");
++
++ xpc_sysctl = register_sysctl_table(xpc_sys_dir);
++
++ /*
++ * The first few fields of each entry of xpc_partitions[] need to
++ * be initialized now so that calls to xpc_connect() and
++ * xpc_disconnect() can be made prior to the activation of any remote
++ * partition. NOTE THAT NONE OF THE OTHER FIELDS BELONGING TO THESE
++ * ENTRIES ARE MEANINGFUL UNTIL AFTER AN ENTRY'S CORRESPONDING
++ * PARTITION HAS BEEN ACTIVATED.
++ */
++ for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
++ part = &xpc_partitions[partid];
++
++ DBUG_ON((u64)part != L1_CACHE_ALIGN((u64)part));
++
++ part->act_IRQ_rcvd = 0;
++ spin_lock_init(&part->act_lock);
++ part->act_state = XPC_P_INACTIVE;
++ XPC_SET_REASON(part, 0, 0);
++
++ init_timer(&part->disengage_request_timer);
++ part->disengage_request_timer.function =
++ xpc_timeout_partition_disengage_request;
++ part->disengage_request_timer.data = (unsigned long)part;
++
++ part->setup_state = XPC_P_UNSET;
++ init_waitqueue_head(&part->teardown_wq);
++ atomic_set(&part->references, 0);
++ }
++
++ /*
++ * Open up protections for IPI operations (and AMO operations on
++ * Shub 1.1 systems).
++ */
++ xpc_allow_IPI_ops();
++
++ /*
++ * Interrupts being processed will increment this atomic variable and
++ * awaken the heartbeat thread which will process the interrupts.
++ */
++ atomic_set(&xpc_act_IRQ_rcvd, 0);
++
++ /*
++ * This is safe to do before the xpc_hb_checker thread has started
++ * because the handler releases a wait queue. If an interrupt is
++ * received before the thread is waiting, it will not go to sleep,
++ * but rather immediately process the interrupt.
++ */
++ ret = request_irq(SGI_XPC_ACTIVATE, xpc_act_IRQ_handler, 0,
++ "xpc hb", NULL);
++ if (ret != 0) {
++ dev_err(xpc_part, "can't register ACTIVATE IRQ handler, "
++ "errno=%d\n", -ret);
++
++ xpc_restrict_IPI_ops();
++
++ if (xpc_sysctl)
++ unregister_sysctl_table(xpc_sysctl);
++
++ kfree(xpc_remote_copy_buffer_base);
++ return -EBUSY;
++ }
++
++ /*
++ * Fill the partition reserved page with the information needed by
++ * other partitions to discover we are alive and establish initial
++ * communications.
++ */
++ xpc_rsvd_page = xpc_rsvd_page_init();
++ if (xpc_rsvd_page == NULL) {
++ dev_err(xpc_part, "could not setup our reserved page\n");
++
++ free_irq(SGI_XPC_ACTIVATE, NULL);
++ xpc_restrict_IPI_ops();
++
++ if (xpc_sysctl)
++ unregister_sysctl_table(xpc_sysctl);
++
++ kfree(xpc_remote_copy_buffer_base);
++ return -EBUSY;
++ }
++
++ /* add ourselves to the reboot_notifier_list */
++ ret = register_reboot_notifier(&xpc_reboot_notifier);
++ if (ret != 0)
++ dev_warn(xpc_part, "can't register reboot notifier\n");
++
++ /* add ourselves to the die_notifier list */
++ ret = register_die_notifier(&xpc_die_notifier);
++ if (ret != 0)
++ dev_warn(xpc_part, "can't register die notifier\n");
++
++ init_timer(&xpc_hb_timer);
++ xpc_hb_timer.function = xpc_hb_beater;
++
++ /*
++ * The real work-horse behind xpc. This processes incoming
++ * interrupts and monitors remote heartbeats.
++ */
++ kthread = kthread_run(xpc_hb_checker, NULL, XPC_HB_CHECK_THREAD_NAME);
++ if (IS_ERR(kthread)) {
++ dev_err(xpc_part, "failed while forking hb check thread\n");
++
++ /* indicate to others that our reserved page is uninitialized */
++ xpc_rsvd_page->vars_pa = 0;
++
++ /* take ourselves off of the reboot_notifier_list */
++ (void)unregister_reboot_notifier(&xpc_reboot_notifier);
++
++ /* take ourselves off of the die_notifier list */
++ (void)unregister_die_notifier(&xpc_die_notifier);
++
++ del_timer_sync(&xpc_hb_timer);
++ free_irq(SGI_XPC_ACTIVATE, NULL);
++ xpc_restrict_IPI_ops();
++
++ if (xpc_sysctl)
++ unregister_sysctl_table(xpc_sysctl);
++
++ kfree(xpc_remote_copy_buffer_base);
++ return -EBUSY;
++ }
++
++ /*
++ * Startup a thread that will attempt to discover other partitions to
++ * activate based on info provided by SAL. This new thread is short
++ * lived and will exit once discovery is complete.
++ */
++ kthread = kthread_run(xpc_initiate_discovery, NULL,
++ XPC_DISCOVERY_THREAD_NAME);
++ if (IS_ERR(kthread)) {
++ dev_err(xpc_part, "failed while forking discovery thread\n");
++
++ /* mark this new thread as a non-starter */
++ complete(&xpc_discovery_exited);
++
++ xpc_do_exit(xpcUnloading);
++ return -EBUSY;
++ }
++
++ /* set the interface to point at XPC's functions */
++ xpc_set_interface(xpc_initiate_connect, xpc_initiate_disconnect,
++ xpc_initiate_allocate, xpc_initiate_send,
++ xpc_initiate_send_notify, xpc_initiate_received,
++ xpc_initiate_partid_to_nasids);
++
++ return 0;
++}
++
++module_init(xpc_init);
++
++void __exit
++xpc_exit(void)
++{
++ xpc_do_exit(xpcUnloading);
++}
++
++module_exit(xpc_exit);
++
++MODULE_AUTHOR("Silicon Graphics, Inc.");
++MODULE_DESCRIPTION("Cross Partition Communication (XPC) support");
++MODULE_LICENSE("GPL");
++
++module_param(xpc_hb_interval, int, 0);
++MODULE_PARM_DESC(xpc_hb_interval, "Number of seconds between "
++ "heartbeat increments.");
++
++module_param(xpc_hb_check_interval, int, 0);
++MODULE_PARM_DESC(xpc_hb_check_interval, "Number of seconds between "
++ "heartbeat checks.");
++
++module_param(xpc_disengage_request_timelimit, int, 0);
++MODULE_PARM_DESC(xpc_disengage_request_timelimit, "Number of seconds to wait "
++ "for disengage request to complete.");
++
++module_param(xpc_kdebug_ignore, int, 0);
++MODULE_PARM_DESC(xpc_kdebug_ignore, "Should lack of heartbeat be ignored by "
++ "other partitions when dropping into kdebug.");
+diff --git a/drivers/misc/sgi-xp/xpc_partition.c b/drivers/misc/sgi-xp/xpc_partition.c
+new file mode 100644
+index 0000000..27e200e
+--- /dev/null
++++ b/drivers/misc/sgi-xp/xpc_partition.c
+@@ -0,0 +1,1174 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (c) 2004-2008 Silicon Graphics, Inc. All Rights Reserved.
++ */
++
++/*
++ * Cross Partition Communication (XPC) partition support.
++ *
++ * This is the part of XPC that detects the presence/absence of
++ * other partitions. It provides a heartbeat and monitors the
++ * heartbeats of other partitions.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/sysctl.h>
++#include <linux/cache.h>
++#include <linux/mmzone.h>
++#include <linux/nodemask.h>
++#include <asm/uncached.h>
++#include <asm/sn/bte.h>
++#include <asm/sn/intr.h>
++#include <asm/sn/sn_sal.h>
++#include <asm/sn/nodepda.h>
++#include <asm/sn/addrs.h>
++#include "xpc.h"
++
++/* XPC is exiting flag */
++int xpc_exiting;
++
++/* SH_IPI_ACCESS shub register value on startup */
++static u64 xpc_sh1_IPI_access;
++static u64 xpc_sh2_IPI_access0;
++static u64 xpc_sh2_IPI_access1;
++static u64 xpc_sh2_IPI_access2;
++static u64 xpc_sh2_IPI_access3;
++
++/* original protection values for each node */
++u64 xpc_prot_vec[MAX_NUMNODES];
++
++/* this partition's reserved page pointers */
++struct xpc_rsvd_page *xpc_rsvd_page;
++static u64 *xpc_part_nasids;
++static u64 *xpc_mach_nasids;
++struct xpc_vars *xpc_vars;
++struct xpc_vars_part *xpc_vars_part;
++
++static int xp_nasid_mask_bytes; /* actual size in bytes of nasid mask */
++static int xp_nasid_mask_words; /* actual size in words of nasid mask */
++
++/*
++ * For performance reasons, each entry of xpc_partitions[] is cacheline
++ * aligned. And xpc_partitions[] is padded with an additional entry at the
++ * end so that the last legitimate entry doesn't share its cacheline with
++ * another variable.
++ */
++struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1];
++
++/*
++ * Generic buffer used to store a local copy of portions of a remote
++ * partition's reserved page (either its header and part_nasids mask,
++ * or its vars).
++ */
++char *xpc_remote_copy_buffer;
++void *xpc_remote_copy_buffer_base;
++
++/*
++ * Guarantee that the kmalloc'd memory is cacheline aligned.
++ */
++void *
++xpc_kmalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
++{
++ /* see if kmalloc will give us cachline aligned memory by default */
++ *base = kmalloc(size, flags);
++ if (*base == NULL)
++ return NULL;
++
++ if ((u64)*base == L1_CACHE_ALIGN((u64)*base))
++ return *base;
++
++ kfree(*base);
++
++ /* nope, we'll have to do it ourselves */
++ *base = kmalloc(size + L1_CACHE_BYTES, flags);
++ if (*base == NULL)
++ return NULL;
++
++ return (void *)L1_CACHE_ALIGN((u64)*base);
++}
++
++/*
++ * Given a nasid, get the physical address of the partition's reserved page
++ * for that nasid. This function returns 0 on any error.
++ */
++static u64
++xpc_get_rsvd_page_pa(int nasid)
++{
++ bte_result_t bte_res;
++ s64 status;
++ u64 cookie = 0;
++ u64 rp_pa = nasid; /* seed with nasid */
++ u64 len = 0;
++ u64 buf = buf;
++ u64 buf_len = 0;
++ void *buf_base = NULL;
++
++ while (1) {
++
++ status = sn_partition_reserved_page_pa(buf, &cookie, &rp_pa,
++ &len);
++
++ dev_dbg(xpc_part, "SAL returned with status=%li, cookie="
++ "0x%016lx, address=0x%016lx, len=0x%016lx\n",
++ status, cookie, rp_pa, len);
++
++ if (status != SALRET_MORE_PASSES)
++ break;
++
++ if (L1_CACHE_ALIGN(len) > buf_len) {
++ kfree(buf_base);
++ buf_len = L1_CACHE_ALIGN(len);
++ buf = (u64)xpc_kmalloc_cacheline_aligned(buf_len,
++ GFP_KERNEL,
++ &buf_base);
++ if (buf_base == NULL) {
++ dev_err(xpc_part, "unable to kmalloc "
++ "len=0x%016lx\n", buf_len);
++ status = SALRET_ERROR;
++ break;
++ }
++ }
++
++ bte_res = xp_bte_copy(rp_pa, buf, buf_len,
++ (BTE_NOTIFY | BTE_WACQUIRE), NULL);
++ if (bte_res != BTE_SUCCESS) {
++ dev_dbg(xpc_part, "xp_bte_copy failed %i\n", bte_res);
++ status = SALRET_ERROR;
++ break;
++ }
++ }
++
++ kfree(buf_base);
++
++ if (status != SALRET_OK)
++ rp_pa = 0;
++
++ dev_dbg(xpc_part, "reserved page at phys address 0x%016lx\n", rp_pa);
++ return rp_pa;
++}
++
++/*
++ * Fill the partition reserved page with the information needed by
++ * other partitions to discover we are alive and establish initial
++ * communications.
++ */
++struct xpc_rsvd_page *
++xpc_rsvd_page_init(void)
++{
++ struct xpc_rsvd_page *rp;
++ AMO_t *amos_page;
++ u64 rp_pa, nasid_array = 0;
++ int i, ret;
++
++ /* get the local reserved page's address */
++
++ preempt_disable();
++ rp_pa = xpc_get_rsvd_page_pa(cpuid_to_nasid(smp_processor_id()));
++ preempt_enable();
++ if (rp_pa == 0) {
++ dev_err(xpc_part, "SAL failed to locate the reserved page\n");
++ return NULL;
++ }
++ rp = (struct xpc_rsvd_page *)__va(rp_pa);
++
++ if (rp->partid != sn_partition_id) {
++ dev_err(xpc_part, "the reserved page's partid of %d should be "
++ "%d\n", rp->partid, sn_partition_id);
++ return NULL;
++ }
++
++ rp->version = XPC_RP_VERSION;
++
++ /* establish the actual sizes of the nasid masks */
++ if (rp->SAL_version == 1) {
++ /* SAL_version 1 didn't set the nasids_size field */
++ rp->nasids_size = 128;
++ }
++ xp_nasid_mask_bytes = rp->nasids_size;
++ xp_nasid_mask_words = xp_nasid_mask_bytes / 8;
++
++ /* setup the pointers to the various items in the reserved page */
++ xpc_part_nasids = XPC_RP_PART_NASIDS(rp);
++ xpc_mach_nasids = XPC_RP_MACH_NASIDS(rp);
++ xpc_vars = XPC_RP_VARS(rp);
++ xpc_vars_part = XPC_RP_VARS_PART(rp);
++
++ /*
++ * Before clearing xpc_vars, see if a page of AMOs had been previously
++ * allocated. If not we'll need to allocate one and set permissions
++ * so that cross-partition AMOs are allowed.
++ *
++ * The allocated AMO page needs MCA reporting to remain disabled after
++ * XPC has unloaded. To make this work, we keep a copy of the pointer
++ * to this page (i.e., amos_page) in the struct xpc_vars structure,
++ * which is pointed to by the reserved page, and re-use that saved copy
++ * on subsequent loads of XPC. This AMO page is never freed, and its
++ * memory protections are never restricted.
++ */
++ amos_page = xpc_vars->amos_page;
++ if (amos_page == NULL) {
++ amos_page = (AMO_t *)TO_AMO(uncached_alloc_page(0));
++ if (amos_page == NULL) {
++ dev_err(xpc_part, "can't allocate page of AMOs\n");
++ return NULL;
++ }
++
++ /*
++ * Open up AMO-R/W to cpu. This is done for Shub 1.1 systems
++ * when xpc_allow_IPI_ops() is called via xpc_hb_init().
++ */
++ if (!enable_shub_wars_1_1()) {
++ ret = sn_change_memprotect(ia64_tpa((u64)amos_page),
++ PAGE_SIZE,
++ SN_MEMPROT_ACCESS_CLASS_1,
++ &nasid_array);
++ if (ret != 0) {
++ dev_err(xpc_part, "can't change memory "
++ "protections\n");
++ uncached_free_page(__IA64_UNCACHED_OFFSET |
++ TO_PHYS((u64)amos_page));
++ return NULL;
++ }
++ }
++ } else if (!IS_AMO_ADDRESS((u64)amos_page)) {
++ /*
++ * EFI's XPBOOT can also set amos_page in the reserved page,
++ * but it happens to leave it as an uncached physical address
++ * and we need it to be an uncached virtual, so we'll have to
++ * convert it.
++ */
++ if (!IS_AMO_PHYS_ADDRESS((u64)amos_page)) {
++ dev_err(xpc_part, "previously used amos_page address "
++ "is bad = 0x%p\n", (void *)amos_page);
++ return NULL;
++ }
++ amos_page = (AMO_t *)TO_AMO((u64)amos_page);
++ }
++
++ /* clear xpc_vars */
++ memset(xpc_vars, 0, sizeof(struct xpc_vars));
++
++ xpc_vars->version = XPC_V_VERSION;
++ xpc_vars->act_nasid = cpuid_to_nasid(0);
++ xpc_vars->act_phys_cpuid = cpu_physical_id(0);
++ xpc_vars->vars_part_pa = __pa(xpc_vars_part);
++ xpc_vars->amos_page_pa = ia64_tpa((u64)amos_page);
++ xpc_vars->amos_page = amos_page; /* save for next load of XPC */
++
++ /* clear xpc_vars_part */
++ memset((u64 *)xpc_vars_part, 0, sizeof(struct xpc_vars_part) *
++ XP_MAX_PARTITIONS);
++
++ /* initialize the activate IRQ related AMO variables */
++ for (i = 0; i < xp_nasid_mask_words; i++)
++ (void)xpc_IPI_init(XPC_ACTIVATE_IRQ_AMOS + i);
++
++ /* initialize the engaged remote partitions related AMO variables */
++ (void)xpc_IPI_init(XPC_ENGAGED_PARTITIONS_AMO);
++ (void)xpc_IPI_init(XPC_DISENGAGE_REQUEST_AMO);
++
++ /* timestamp of when reserved page was setup by XPC */
++ rp->stamp = CURRENT_TIME;
++
++ /*
++ * This signifies to the remote partition that our reserved
++ * page is initialized.
++ */
++ rp->vars_pa = __pa(xpc_vars);
++
++ return rp;
++}
++
++/*
++ * Change protections to allow IPI operations (and AMO operations on
++ * Shub 1.1 systems).
++ */
++void
++xpc_allow_IPI_ops(void)
++{
++ int node;
++ int nasid;
++
++ /* >>> Change SH_IPI_ACCESS code to use SAL call once it is available */
++
++ if (is_shub2()) {
++ xpc_sh2_IPI_access0 =
++ (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH2_IPI_ACCESS0));
++ xpc_sh2_IPI_access1 =
++ (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH2_IPI_ACCESS1));
++ xpc_sh2_IPI_access2 =
++ (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH2_IPI_ACCESS2));
++ xpc_sh2_IPI_access3 =
++ (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH2_IPI_ACCESS3));
++
++ for_each_online_node(node) {
++ nasid = cnodeid_to_nasid(node);
++ HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS0),
++ -1UL);
++ HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS1),
++ -1UL);
++ HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS2),
++ -1UL);
++ HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS3),
++ -1UL);
++ }
++
++ } else {
++ xpc_sh1_IPI_access =
++ (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH1_IPI_ACCESS));
++
++ for_each_online_node(node) {
++ nasid = cnodeid_to_nasid(node);
++ HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH1_IPI_ACCESS),
++ -1UL);
++
++ /*
++ * Since the BIST collides with memory operations on
++ * SHUB 1.1 sn_change_memprotect() cannot be used.
++ */
++ if (enable_shub_wars_1_1()) {
++ /* open up everything */
++ xpc_prot_vec[node] = (u64)HUB_L((u64 *)
++ GLOBAL_MMR_ADDR
++ (nasid,
++ SH1_MD_DQLP_MMR_DIR_PRIVEC0));
++ HUB_S((u64 *)
++ GLOBAL_MMR_ADDR(nasid,
++ SH1_MD_DQLP_MMR_DIR_PRIVEC0),
++ -1UL);
++ HUB_S((u64 *)
++ GLOBAL_MMR_ADDR(nasid,
++ SH1_MD_DQRP_MMR_DIR_PRIVEC0),
++ -1UL);
++ }
++ }
++ }
++}
++
++/*
++ * Restrict protections to disallow IPI operations (and AMO operations on
++ * Shub 1.1 systems).
++ */
++void
++xpc_restrict_IPI_ops(void)
++{
++ int node;
++ int nasid;
++
++ /* >>> Change SH_IPI_ACCESS code to use SAL call once it is available */
++
++ if (is_shub2()) {
++
++ for_each_online_node(node) {
++ nasid = cnodeid_to_nasid(node);
++ HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS0),
++ xpc_sh2_IPI_access0);
++ HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS1),
++ xpc_sh2_IPI_access1);
++ HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS2),
++ xpc_sh2_IPI_access2);
++ HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS3),
++ xpc_sh2_IPI_access3);
++ }
++
++ } else {
++
++ for_each_online_node(node) {
++ nasid = cnodeid_to_nasid(node);
++ HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH1_IPI_ACCESS),
++ xpc_sh1_IPI_access);
++
++ if (enable_shub_wars_1_1()) {
++ HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid,
++ SH1_MD_DQLP_MMR_DIR_PRIVEC0),
++ xpc_prot_vec[node]);
++ HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid,
++ SH1_MD_DQRP_MMR_DIR_PRIVEC0),
++ xpc_prot_vec[node]);
++ }
++ }
++ }
++}
++
++/*
++ * At periodic intervals, scan through all active partitions and ensure
++ * their heartbeat is still active. If not, the partition is deactivated.
++ */
++void
++xpc_check_remote_hb(void)
++{
++ struct xpc_vars *remote_vars;
++ struct xpc_partition *part;
++ partid_t partid;
++ bte_result_t bres;
++
++ remote_vars = (struct xpc_vars *)xpc_remote_copy_buffer;
++
++ for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
++
++ if (xpc_exiting)
++ break;
++
++ if (partid == sn_partition_id)
++ continue;
++
++ part = &xpc_partitions[partid];
++
++ if (part->act_state == XPC_P_INACTIVE ||
++ part->act_state == XPC_P_DEACTIVATING) {
++ continue;
++ }
++
++ /* pull the remote_hb cache line */
++ bres = xp_bte_copy(part->remote_vars_pa,
++ (u64)remote_vars,
++ XPC_RP_VARS_SIZE,
++ (BTE_NOTIFY | BTE_WACQUIRE), NULL);
++ if (bres != BTE_SUCCESS) {
++ XPC_DEACTIVATE_PARTITION(part,
++ xpc_map_bte_errors(bres));
++ continue;
++ }
++
++ dev_dbg(xpc_part, "partid = %d, heartbeat = %ld, last_heartbeat"
++ " = %ld, heartbeat_offline = %ld, HB_mask = 0x%lx\n",
++ partid, remote_vars->heartbeat, part->last_heartbeat,
++ remote_vars->heartbeat_offline,
++ remote_vars->heartbeating_to_mask);
++
++ if (((remote_vars->heartbeat == part->last_heartbeat) &&
++ (remote_vars->heartbeat_offline == 0)) ||
++ !xpc_hb_allowed(sn_partition_id, remote_vars)) {
++
++ XPC_DEACTIVATE_PARTITION(part, xpcNoHeartbeat);
++ continue;
++ }
++
++ part->last_heartbeat = remote_vars->heartbeat;
++ }
++}
++
++/*
++ * Get a copy of a portion of the remote partition's rsvd page.
++ *
++ * remote_rp points to a buffer that is cacheline aligned for BTE copies and
++ * is large enough to contain a copy of their reserved page header and
++ * part_nasids mask.
++ */
++static enum xpc_retval
++xpc_get_remote_rp(int nasid, u64 *discovered_nasids,
++ struct xpc_rsvd_page *remote_rp, u64 *remote_rp_pa)
++{
++ int bres, i;
++
++ /* get the reserved page's physical address */
++
++ *remote_rp_pa = xpc_get_rsvd_page_pa(nasid);
++ if (*remote_rp_pa == 0)
++ return xpcNoRsvdPageAddr;
++
++ /* pull over the reserved page header and part_nasids mask */
++ bres = xp_bte_copy(*remote_rp_pa, (u64)remote_rp,
++ XPC_RP_HEADER_SIZE + xp_nasid_mask_bytes,
++ (BTE_NOTIFY | BTE_WACQUIRE), NULL);
++ if (bres != BTE_SUCCESS)
++ return xpc_map_bte_errors(bres);
++
++ if (discovered_nasids != NULL) {
++ u64 *remote_part_nasids = XPC_RP_PART_NASIDS(remote_rp);
++
++ for (i = 0; i < xp_nasid_mask_words; i++)
++ discovered_nasids[i] |= remote_part_nasids[i];
++ }
++
++ /* check that the partid is for another partition */
++
++ if (remote_rp->partid < 1 ||
++ remote_rp->partid > (XP_MAX_PARTITIONS - 1)) {
++ return xpcInvalidPartid;
++ }
++
++ if (remote_rp->partid == sn_partition_id)
++ return xpcLocalPartid;
++
++ if (XPC_VERSION_MAJOR(remote_rp->version) !=
++ XPC_VERSION_MAJOR(XPC_RP_VERSION)) {
++ return xpcBadVersion;
++ }
++
++ return xpcSuccess;
++}
++
++/*
++ * Get a copy of the remote partition's XPC variables from the reserved page.
++ *
++ * remote_vars points to a buffer that is cacheline aligned for BTE copies and
++ * assumed to be of size XPC_RP_VARS_SIZE.
++ */
++static enum xpc_retval
++xpc_get_remote_vars(u64 remote_vars_pa, struct xpc_vars *remote_vars)
++{
++ int bres;
++
++ if (remote_vars_pa == 0)
++ return xpcVarsNotSet;
++
++ /* pull over the cross partition variables */
++ bres = xp_bte_copy(remote_vars_pa, (u64)remote_vars, XPC_RP_VARS_SIZE,
++ (BTE_NOTIFY | BTE_WACQUIRE), NULL);
++ if (bres != BTE_SUCCESS)
++ return xpc_map_bte_errors(bres);
++
++ if (XPC_VERSION_MAJOR(remote_vars->version) !=
++ XPC_VERSION_MAJOR(XPC_V_VERSION)) {
++ return xpcBadVersion;
++ }
++
++ return xpcSuccess;
++}
++
++/*
++ * Update the remote partition's info.
++ */
++static void
++xpc_update_partition_info(struct xpc_partition *part, u8 remote_rp_version,
++ struct timespec *remote_rp_stamp, u64 remote_rp_pa,
++ u64 remote_vars_pa, struct xpc_vars *remote_vars)
++{
++ part->remote_rp_version = remote_rp_version;
++ dev_dbg(xpc_part, " remote_rp_version = 0x%016x\n",
++ part->remote_rp_version);
++
++ part->remote_rp_stamp = *remote_rp_stamp;
++ dev_dbg(xpc_part, " remote_rp_stamp (tv_sec = 0x%lx tv_nsec = 0x%lx\n",
++ part->remote_rp_stamp.tv_sec, part->remote_rp_stamp.tv_nsec);
++
++ part->remote_rp_pa = remote_rp_pa;
++ dev_dbg(xpc_part, " remote_rp_pa = 0x%016lx\n", part->remote_rp_pa);
++
++ part->remote_vars_pa = remote_vars_pa;
++ dev_dbg(xpc_part, " remote_vars_pa = 0x%016lx\n",
++ part->remote_vars_pa);
++
++ part->last_heartbeat = remote_vars->heartbeat;
++ dev_dbg(xpc_part, " last_heartbeat = 0x%016lx\n",
++ part->last_heartbeat);
++
++ part->remote_vars_part_pa = remote_vars->vars_part_pa;
++ dev_dbg(xpc_part, " remote_vars_part_pa = 0x%016lx\n",
++ part->remote_vars_part_pa);
++
++ part->remote_act_nasid = remote_vars->act_nasid;
++ dev_dbg(xpc_part, " remote_act_nasid = 0x%x\n",
++ part->remote_act_nasid);
++
++ part->remote_act_phys_cpuid = remote_vars->act_phys_cpuid;
++ dev_dbg(xpc_part, " remote_act_phys_cpuid = 0x%x\n",
++ part->remote_act_phys_cpuid);
++
++ part->remote_amos_page_pa = remote_vars->amos_page_pa;
++ dev_dbg(xpc_part, " remote_amos_page_pa = 0x%lx\n",
++ part->remote_amos_page_pa);
++
++ part->remote_vars_version = remote_vars->version;
++ dev_dbg(xpc_part, " remote_vars_version = 0x%x\n",
++ part->remote_vars_version);
++}
++
++/*
++ * Prior code has determined the nasid which generated an IPI. Inspect
++ * that nasid to determine if its partition needs to be activated or
++ * deactivated.
++ *
++ * A partition is consider "awaiting activation" if our partition
++ * flags indicate it is not active and it has a heartbeat. A
++ * partition is considered "awaiting deactivation" if our partition
++ * flags indicate it is active but it has no heartbeat or it is not
++ * sending its heartbeat to us.
++ *
++ * To determine the heartbeat, the remote nasid must have a properly
++ * initialized reserved page.
++ */
++static void
++xpc_identify_act_IRQ_req(int nasid)
++{
++ struct xpc_rsvd_page *remote_rp;
++ struct xpc_vars *remote_vars;
++ u64 remote_rp_pa;
++ u64 remote_vars_pa;
++ int remote_rp_version;
++ int reactivate = 0;
++ int stamp_diff;
++ struct timespec remote_rp_stamp = { 0, 0 };
++ partid_t partid;
++ struct xpc_partition *part;
++ enum xpc_retval ret;
++
++ /* pull over the reserved page structure */
++
++ remote_rp = (struct xpc_rsvd_page *)xpc_remote_copy_buffer;
++
++ ret = xpc_get_remote_rp(nasid, NULL, remote_rp, &remote_rp_pa);
++ if (ret != xpcSuccess) {
++ dev_warn(xpc_part, "unable to get reserved page from nasid %d, "
++ "which sent interrupt, reason=%d\n", nasid, ret);
++ return;
++ }
++
++ remote_vars_pa = remote_rp->vars_pa;
++ remote_rp_version = remote_rp->version;
++ if (XPC_SUPPORTS_RP_STAMP(remote_rp_version))
++ remote_rp_stamp = remote_rp->stamp;
++
++ partid = remote_rp->partid;
++ part = &xpc_partitions[partid];
++
++ /* pull over the cross partition variables */
++
++ remote_vars = (struct xpc_vars *)xpc_remote_copy_buffer;
++
++ ret = xpc_get_remote_vars(remote_vars_pa, remote_vars);
++ if (ret != xpcSuccess) {
++
++ dev_warn(xpc_part, "unable to get XPC variables from nasid %d, "
++ "which sent interrupt, reason=%d\n", nasid, ret);
++
++ XPC_DEACTIVATE_PARTITION(part, ret);
++ return;
++ }
++
++ part->act_IRQ_rcvd++;
++
++ dev_dbg(xpc_part, "partid for nasid %d is %d; IRQs = %d; HB = "
++ "%ld:0x%lx\n", (int)nasid, (int)partid, part->act_IRQ_rcvd,
++ remote_vars->heartbeat, remote_vars->heartbeating_to_mask);
++
++ if (xpc_partition_disengaged(part) &&
++ part->act_state == XPC_P_INACTIVE) {
++
++ xpc_update_partition_info(part, remote_rp_version,
++ &remote_rp_stamp, remote_rp_pa,
++ remote_vars_pa, remote_vars);
++
++ if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version)) {
++ if (xpc_partition_disengage_requested(1UL << partid)) {
++ /*
++ * Other side is waiting on us to disengage,
++ * even though we already have.
++ */
++ return;
++ }
++ } else {
++ /* other side doesn't support disengage requests */
++ xpc_clear_partition_disengage_request(1UL << partid);
++ }
++
++ xpc_activate_partition(part);
++ return;
++ }
++
++ DBUG_ON(part->remote_rp_version == 0);
++ DBUG_ON(part->remote_vars_version == 0);
++
++ if (!XPC_SUPPORTS_RP_STAMP(part->remote_rp_version)) {
++ DBUG_ON(XPC_SUPPORTS_DISENGAGE_REQUEST(part->
++ remote_vars_version));
++
++ if (!XPC_SUPPORTS_RP_STAMP(remote_rp_version)) {
++ DBUG_ON(XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->
++ version));
++ /* see if the other side rebooted */
++ if (part->remote_amos_page_pa ==
++ remote_vars->amos_page_pa &&
++ xpc_hb_allowed(sn_partition_id, remote_vars)) {
++ /* doesn't look that way, so ignore the IPI */
++ return;
++ }
++ }
++
++ /*
++ * Other side rebooted and previous XPC didn't support the
++ * disengage request, so we don't need to do anything special.
++ */
++
++ xpc_update_partition_info(part, remote_rp_version,
++ &remote_rp_stamp, remote_rp_pa,
++ remote_vars_pa, remote_vars);
++ part->reactivate_nasid = nasid;
++ XPC_DEACTIVATE_PARTITION(part, xpcReactivating);
++ return;
++ }
++
++ DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version));
++
++ if (!XPC_SUPPORTS_RP_STAMP(remote_rp_version)) {
++ DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->version));
++
++ /*
++ * Other side rebooted and previous XPC did support the
++ * disengage request, but the new one doesn't.
++ */
++
++ xpc_clear_partition_engaged(1UL << partid);
++ xpc_clear_partition_disengage_request(1UL << partid);
++
++ xpc_update_partition_info(part, remote_rp_version,
++ &remote_rp_stamp, remote_rp_pa,
++ remote_vars_pa, remote_vars);
++ reactivate = 1;
++
++ } else {
++ DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->version));
++
++ stamp_diff = xpc_compare_stamps(&part->remote_rp_stamp,
++ &remote_rp_stamp);
++ if (stamp_diff != 0) {
++ DBUG_ON(stamp_diff >= 0);
++
++ /*
++ * Other side rebooted and the previous XPC did support
++ * the disengage request, as does the new one.
++ */
++
++ DBUG_ON(xpc_partition_engaged(1UL << partid));
++ DBUG_ON(xpc_partition_disengage_requested(1UL <<
++ partid));
++
++ xpc_update_partition_info(part, remote_rp_version,
++ &remote_rp_stamp,
++ remote_rp_pa, remote_vars_pa,
++ remote_vars);
++ reactivate = 1;
++ }
++ }
++
++ if (part->disengage_request_timeout > 0 &&
++ !xpc_partition_disengaged(part)) {
++ /* still waiting on other side to disengage from us */
++ return;
++ }
++
++ if (reactivate) {
++ part->reactivate_nasid = nasid;
++ XPC_DEACTIVATE_PARTITION(part, xpcReactivating);
++
++ } else if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version) &&
++ xpc_partition_disengage_requested(1UL << partid)) {
++ XPC_DEACTIVATE_PARTITION(part, xpcOtherGoingDown);
++ }
++}
++
++/*
++ * Loop through the activation AMO variables and process any bits
++ * which are set. Each bit indicates a nasid sending a partition
++ * activation or deactivation request.
++ *
++ * Return #of IRQs detected.
++ */
++int
++xpc_identify_act_IRQ_sender(void)
++{
++ int word, bit;
++ u64 nasid_mask;
++ u64 nasid; /* remote nasid */
++ int n_IRQs_detected = 0;
++ AMO_t *act_amos;
++
++ act_amos = xpc_vars->amos_page + XPC_ACTIVATE_IRQ_AMOS;
++
++ /* scan through act AMO variable looking for non-zero entries */
++ for (word = 0; word < xp_nasid_mask_words; word++) {
++
++ if (xpc_exiting)
++ break;
++
++ nasid_mask = xpc_IPI_receive(&act_amos[word]);
++ if (nasid_mask == 0) {
++ /* no IRQs from nasids in this variable */
++ continue;
++ }
++
++ dev_dbg(xpc_part, "AMO[%d] gave back 0x%lx\n", word,
++ nasid_mask);
++
++ /*
++ * If this nasid has been added to the machine since
++ * our partition was reset, this will retain the
++ * remote nasid in our reserved pages machine mask.
++ * This is used in the event of module reload.
++ */
++ xpc_mach_nasids[word] |= nasid_mask;
++
++ /* locate the nasid(s) which sent interrupts */
++
++ for (bit = 0; bit < (8 * sizeof(u64)); bit++) {
++ if (nasid_mask & (1UL << bit)) {
++ n_IRQs_detected++;
++ nasid = XPC_NASID_FROM_W_B(word, bit);
++ dev_dbg(xpc_part, "interrupt from nasid %ld\n",
++ nasid);
++ xpc_identify_act_IRQ_req(nasid);
++ }
++ }
++ }
++ return n_IRQs_detected;
++}
++
++/*
++ * See if the other side has responded to a partition disengage request
++ * from us.
++ */
++int
++xpc_partition_disengaged(struct xpc_partition *part)
++{
++ partid_t partid = XPC_PARTID(part);
++ int disengaged;
++
++ disengaged = (xpc_partition_engaged(1UL << partid) == 0);
++ if (part->disengage_request_timeout) {
++ if (!disengaged) {
++ if (time_before(jiffies,
++ part->disengage_request_timeout)) {
++ /* timelimit hasn't been reached yet */
++ return 0;
++ }
++
++ /*
++ * Other side hasn't responded to our disengage
++ * request in a timely fashion, so assume it's dead.
++ */
++
++ dev_info(xpc_part, "disengage from remote partition %d "
++ "timed out\n", partid);
++ xpc_disengage_request_timedout = 1;
++ xpc_clear_partition_engaged(1UL << partid);
++ disengaged = 1;
++ }
++ part->disengage_request_timeout = 0;
++
++ /* cancel the timer function, provided it's not us */
++ if (!in_interrupt()) {
++ del_singleshot_timer_sync(&part->
++ disengage_request_timer);
++ }
++
++ DBUG_ON(part->act_state != XPC_P_DEACTIVATING &&
++ part->act_state != XPC_P_INACTIVE);
++ if (part->act_state != XPC_P_INACTIVE)
++ xpc_wakeup_channel_mgr(part);
++
++ if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version))
++ xpc_cancel_partition_disengage_request(part);
++ }
++ return disengaged;
++}
++
++/*
++ * Mark specified partition as active.
++ */
++enum xpc_retval
++xpc_mark_partition_active(struct xpc_partition *part)
++{
++ unsigned long irq_flags;
++ enum xpc_retval ret;
++
++ dev_dbg(xpc_part, "setting partition %d to ACTIVE\n", XPC_PARTID(part));
++
++ spin_lock_irqsave(&part->act_lock, irq_flags);
++ if (part->act_state == XPC_P_ACTIVATING) {
++ part->act_state = XPC_P_ACTIVE;
++ ret = xpcSuccess;
++ } else {
++ DBUG_ON(part->reason == xpcSuccess);
++ ret = part->reason;
++ }
++ spin_unlock_irqrestore(&part->act_lock, irq_flags);
++
++ return ret;
++}
++
++/*
++ * Notify XPC that the partition is down.
++ */
++void
++xpc_deactivate_partition(const int line, struct xpc_partition *part,
++ enum xpc_retval reason)
++{
++ unsigned long irq_flags;
++
++ spin_lock_irqsave(&part->act_lock, irq_flags);
++
++ if (part->act_state == XPC_P_INACTIVE) {
++ XPC_SET_REASON(part, reason, line);
++ spin_unlock_irqrestore(&part->act_lock, irq_flags);
++ if (reason == xpcReactivating) {
++ /* we interrupt ourselves to reactivate partition */
++ xpc_IPI_send_reactivate(part);
++ }
++ return;
++ }
++ if (part->act_state == XPC_P_DEACTIVATING) {
++ if ((part->reason == xpcUnloading && reason != xpcUnloading) ||
++ reason == xpcReactivating) {
++ XPC_SET_REASON(part, reason, line);
++ }
++ spin_unlock_irqrestore(&part->act_lock, irq_flags);
++ return;
++ }
++
++ part->act_state = XPC_P_DEACTIVATING;
++ XPC_SET_REASON(part, reason, line);
++
++ spin_unlock_irqrestore(&part->act_lock, irq_flags);
++
++ if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version)) {
++ xpc_request_partition_disengage(part);
++ xpc_IPI_send_disengage(part);
++
++ /* set a timelimit on the disengage request */
++ part->disengage_request_timeout = jiffies +
++ (xpc_disengage_request_timelimit * HZ);
++ part->disengage_request_timer.expires =
++ part->disengage_request_timeout;
++ add_timer(&part->disengage_request_timer);
++ }
++
++ dev_dbg(xpc_part, "bringing partition %d down, reason = %d\n",
++ XPC_PARTID(part), reason);
++
++ xpc_partition_going_down(part, reason);
++}
++
++/*
++ * Mark specified partition as inactive.
++ */
++void
++xpc_mark_partition_inactive(struct xpc_partition *part)
++{
++ unsigned long irq_flags;
++
++ dev_dbg(xpc_part, "setting partition %d to INACTIVE\n",
++ XPC_PARTID(part));
++
++ spin_lock_irqsave(&part->act_lock, irq_flags);
++ part->act_state = XPC_P_INACTIVE;
++ spin_unlock_irqrestore(&part->act_lock, irq_flags);
++ part->remote_rp_pa = 0;
++}
++
++/*
++ * SAL has provided a partition and machine mask. The partition mask
++ * contains a bit for each even nasid in our partition. The machine
++ * mask contains a bit for each even nasid in the entire machine.
++ *
++ * Using those two bit arrays, we can determine which nasids are
++ * known in the machine. Each should also have a reserved page
++ * initialized if they are available for partitioning.
++ */
++void
++xpc_discovery(void)
++{
++ void *remote_rp_base;
++ struct xpc_rsvd_page *remote_rp;
++ struct xpc_vars *remote_vars;
++ u64 remote_rp_pa;
++ u64 remote_vars_pa;
++ int region;
++ int region_size;
++ int max_regions;
++ int nasid;
++ struct xpc_rsvd_page *rp;
++ partid_t partid;
++ struct xpc_partition *part;
++ u64 *discovered_nasids;
++ enum xpc_retval ret;
++
++ remote_rp = xpc_kmalloc_cacheline_aligned(XPC_RP_HEADER_SIZE +
++ xp_nasid_mask_bytes,
++ GFP_KERNEL, &remote_rp_base);
++ if (remote_rp == NULL)
++ return;
++
++ remote_vars = (struct xpc_vars *)remote_rp;
++
++ discovered_nasids = kzalloc(sizeof(u64) * xp_nasid_mask_words,
++ GFP_KERNEL);
++ if (discovered_nasids == NULL) {
++ kfree(remote_rp_base);
++ return;
++ }
++
++ rp = (struct xpc_rsvd_page *)xpc_rsvd_page;
++
++ /*
++ * The term 'region' in this context refers to the minimum number of
++ * nodes that can comprise an access protection grouping. The access
++ * protection is in regards to memory, IOI and IPI.
++ */
++ max_regions = 64;
++ region_size = sn_region_size;
++
++ switch (region_size) {
++ case 128:
++ max_regions *= 2;
++ case 64:
++ max_regions *= 2;
++ case 32:
++ max_regions *= 2;
++ region_size = 16;
++ DBUG_ON(!is_shub2());
++ }
++
++ for (region = 0; region < max_regions; region++) {
++
++ if (xpc_exiting)
++ break;
++
++ dev_dbg(xpc_part, "searching region %d\n", region);
++
++ for (nasid = (region * region_size * 2);
++ nasid < ((region + 1) * region_size * 2); nasid += 2) {
++
++ if (xpc_exiting)
++ break;
++
++ dev_dbg(xpc_part, "checking nasid %d\n", nasid);
++
++ if (XPC_NASID_IN_ARRAY(nasid, xpc_part_nasids)) {
++ dev_dbg(xpc_part, "PROM indicates Nasid %d is "
++ "part of the local partition; skipping "
++ "region\n", nasid);
++ break;
++ }
++
++ if (!(XPC_NASID_IN_ARRAY(nasid, xpc_mach_nasids))) {
++ dev_dbg(xpc_part, "PROM indicates Nasid %d was "
++ "not on Numa-Link network at reset\n",
++ nasid);
++ continue;
++ }
++
++ if (XPC_NASID_IN_ARRAY(nasid, discovered_nasids)) {
++ dev_dbg(xpc_part, "Nasid %d is part of a "
++ "partition which was previously "
++ "discovered\n", nasid);
++ continue;
++ }
++
++ /* pull over the reserved page structure */
++
++ ret = xpc_get_remote_rp(nasid, discovered_nasids,
++ remote_rp, &remote_rp_pa);
++ if (ret != xpcSuccess) {
++ dev_dbg(xpc_part, "unable to get reserved page "
++ "from nasid %d, reason=%d\n", nasid,
++ ret);
++
++ if (ret == xpcLocalPartid)
++ break;
++
++ continue;
++ }
++
++ remote_vars_pa = remote_rp->vars_pa;
++
++ partid = remote_rp->partid;
++ part = &xpc_partitions[partid];
++
++ /* pull over the cross partition variables */
++
++ ret = xpc_get_remote_vars(remote_vars_pa, remote_vars);
++ if (ret != xpcSuccess) {
++ dev_dbg(xpc_part, "unable to get XPC variables "
++ "from nasid %d, reason=%d\n", nasid,
++ ret);
++
++ XPC_DEACTIVATE_PARTITION(part, ret);
++ continue;
++ }
++
++ if (part->act_state != XPC_P_INACTIVE) {
++ dev_dbg(xpc_part, "partition %d on nasid %d is "
++ "already activating\n", partid, nasid);
++ break;
++ }
++
++ /*
++ * Register the remote partition's AMOs with SAL so it
++ * can handle and cleanup errors within that address
++ * range should the remote partition go down. We don't
++ * unregister this range because it is difficult to
++ * tell when outstanding writes to the remote partition
++ * are finished and thus when it is thus safe to
++ * unregister. This should not result in wasted space
++ * in the SAL xp_addr_region table because we should
++ * get the same page for remote_act_amos_pa after
++ * module reloads and system reboots.
++ */
++ if (sn_register_xp_addr_region
++ (remote_vars->amos_page_pa, PAGE_SIZE, 1) < 0) {
++ dev_dbg(xpc_part,
++ "partition %d failed to "
++ "register xp_addr region 0x%016lx\n",
++ partid, remote_vars->amos_page_pa);
++
++ XPC_SET_REASON(part, xpcPhysAddrRegFailed,
++ __LINE__);
++ break;
++ }
++
++ /*
++ * The remote nasid is valid and available.
++ * Send an interrupt to that nasid to notify
++ * it that we are ready to begin activation.
++ */
++ dev_dbg(xpc_part, "sending an interrupt to AMO 0x%lx, "
++ "nasid %d, phys_cpuid 0x%x\n",
++ remote_vars->amos_page_pa,
++ remote_vars->act_nasid,
++ remote_vars->act_phys_cpuid);
++
++ if (XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->
++ version)) {
++ part->remote_amos_page_pa =
++ remote_vars->amos_page_pa;
++ xpc_mark_partition_disengaged(part);
++ xpc_cancel_partition_disengage_request(part);
++ }
++ xpc_IPI_send_activate(remote_vars);
++ }
++ }
++
++ kfree(discovered_nasids);
++ kfree(remote_rp_base);
++}
++
++/*
++ * Given a partid, get the nasids owned by that partition from the
++ * remote partition's reserved page.
++ */
++enum xpc_retval
++xpc_initiate_partid_to_nasids(partid_t partid, void *nasid_mask)
++{
++ struct xpc_partition *part;
++ u64 part_nasid_pa;
++ int bte_res;
++
++ part = &xpc_partitions[partid];
++ if (part->remote_rp_pa == 0)
++ return xpcPartitionDown;
++
++ memset(nasid_mask, 0, XP_NASID_MASK_BYTES);
++
++ part_nasid_pa = (u64)XPC_RP_PART_NASIDS(part->remote_rp_pa);
++
++ bte_res = xp_bte_copy(part_nasid_pa, (u64)nasid_mask,
++ xp_nasid_mask_bytes, (BTE_NOTIFY | BTE_WACQUIRE),
++ NULL);
++
++ return xpc_map_bte_errors(bte_res);
++}
+diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c
+new file mode 100644
+index 0000000..a9543c6
+--- /dev/null
++++ b/drivers/misc/sgi-xp/xpnet.c
+@@ -0,0 +1,677 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 1999-2008 Silicon Graphics, Inc. All rights reserved.
++ */
++
++/*
++ * Cross Partition Network Interface (XPNET) support
++ *
++ * XPNET provides a virtual network layered on top of the Cross
++ * Partition communication layer.
++ *
++ * XPNET provides direct point-to-point and broadcast-like support
++ * for an ethernet-like device. The ethernet broadcast medium is
++ * replaced with a point-to-point message structure which passes
++ * pointers to a DMA-capable block that a remote partition should
++ * retrieve and pass to the upper level networking layer.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/delay.h>
++#include <linux/ethtool.h>
++#include <linux/mii.h>
++#include <linux/smp.h>
++#include <linux/string.h>
++#include <asm/sn/bte.h>
++#include <asm/sn/io.h>
++#include <asm/sn/sn_sal.h>
++#include <asm/atomic.h>
++#include "xp.h"
++
++/*
++ * The message payload transferred by XPC.
++ *
++ * buf_pa is the physical address where the DMA should pull from.
++ *
++ * NOTE: for performance reasons, buf_pa should _ALWAYS_ begin on a
++ * cacheline boundary. To accomplish this, we record the number of
++ * bytes from the beginning of the first cacheline to the first useful
++ * byte of the skb (leadin_ignore) and the number of bytes from the
++ * last useful byte of the skb to the end of the last cacheline
++ * (tailout_ignore).
++ *
++ * size is the number of bytes to transfer which includes the skb->len
++ * (useful bytes of the senders skb) plus the leadin and tailout
++ */
++struct xpnet_message {
++ u16 version; /* Version for this message */
++ u16 embedded_bytes; /* #of bytes embedded in XPC message */
++ u32 magic; /* Special number indicating this is xpnet */
++ u64 buf_pa; /* phys address of buffer to retrieve */
++ u32 size; /* #of bytes in buffer */
++ u8 leadin_ignore; /* #of bytes to ignore at the beginning */
++ u8 tailout_ignore; /* #of bytes to ignore at the end */
++ unsigned char data; /* body of small packets */
++};
++
++/*
++ * Determine the size of our message, the cacheline aligned size,
++ * and then the number of message will request from XPC.
++ *
++ * XPC expects each message to exist in an individual cacheline.
++ */
++#define XPNET_MSG_SIZE (L1_CACHE_BYTES - XPC_MSG_PAYLOAD_OFFSET)
++#define XPNET_MSG_DATA_MAX \
++ (XPNET_MSG_SIZE - (u64)(&((struct xpnet_message *)0)->data))
++#define XPNET_MSG_ALIGNED_SIZE (L1_CACHE_ALIGN(XPNET_MSG_SIZE))
++#define XPNET_MSG_NENTRIES (PAGE_SIZE / XPNET_MSG_ALIGNED_SIZE)
++
++#define XPNET_MAX_KTHREADS (XPNET_MSG_NENTRIES + 1)
++#define XPNET_MAX_IDLE_KTHREADS (XPNET_MSG_NENTRIES + 1)
++
++/*
++ * Version number of XPNET implementation. XPNET can always talk to versions
++ * with same major #, and never talk to versions with a different version.
++ */
++#define _XPNET_VERSION(_major, _minor) (((_major) << 4) | (_minor))
++#define XPNET_VERSION_MAJOR(_v) ((_v) >> 4)
++#define XPNET_VERSION_MINOR(_v) ((_v) & 0xf)
++
++#define XPNET_VERSION _XPNET_VERSION(1, 0) /* version 1.0 */
++#define XPNET_VERSION_EMBED _XPNET_VERSION(1, 1) /* version 1.1 */
++#define XPNET_MAGIC 0x88786984 /* "XNET" */
++
++#define XPNET_VALID_MSG(_m) \
++ ((XPNET_VERSION_MAJOR(_m->version) == XPNET_VERSION_MAJOR(XPNET_VERSION)) \
++ && (msg->magic == XPNET_MAGIC))
++
++#define XPNET_DEVICE_NAME "xp0"
++
++/*
++ * When messages are queued with xpc_send_notify, a kmalloc'd buffer
++ * of the following type is passed as a notification cookie. When the
++ * notification function is called, we use the cookie to decide
++ * whether all outstanding message sends have completed. The skb can
++ * then be released.
++ */
++struct xpnet_pending_msg {
++ struct list_head free_list;
++ struct sk_buff *skb;
++ atomic_t use_count;
++};
++
++/* driver specific structure pointed to by the device structure */
++struct xpnet_dev_private {
++ struct net_device_stats stats;
++};
++
++struct net_device *xpnet_device;
++
++/*
++ * When we are notified of other partitions activating, we add them to
++ * our bitmask of partitions to which we broadcast.
++ */
++static u64 xpnet_broadcast_partitions;
++/* protect above */
++static DEFINE_SPINLOCK(xpnet_broadcast_lock);
++
++/*
++ * Since the Block Transfer Engine (BTE) is being used for the transfer
++ * and it relies upon cache-line size transfers, we need to reserve at
++ * least one cache-line for head and tail alignment. The BTE is
++ * limited to 8MB transfers.
++ *
++ * Testing has shown that changing MTU to greater than 64KB has no effect
++ * on TCP as the two sides negotiate a Max Segment Size that is limited
++ * to 64K. Other protocols May use packets greater than this, but for
++ * now, the default is 64KB.
++ */
++#define XPNET_MAX_MTU (0x800000UL - L1_CACHE_BYTES)
++/* 32KB has been determined to be the ideal */
++#define XPNET_DEF_MTU (0x8000UL)
++
++/*
++ * The partition id is encapsulated in the MAC address. The following
++ * define locates the octet the partid is in.
++ */
++#define XPNET_PARTID_OCTET 1
++#define XPNET_LICENSE_OCTET 2
++
++/*
++ * Define the XPNET debug device structure that is to be used with dev_dbg(),
++ * dev_err(), dev_warn(), and dev_info().
++ */
++struct device_driver xpnet_dbg_name = {
++ .name = "xpnet"
++};
++
++struct device xpnet_dbg_subname = {
++ .bus_id = {0}, /* set to "" */
++ .driver = &xpnet_dbg_name
++};
++
++struct device *xpnet = &xpnet_dbg_subname;
++
++/*
++ * Packet was recevied by XPC and forwarded to us.
++ */
++static void
++xpnet_receive(partid_t partid, int channel, struct xpnet_message *msg)
++{
++ struct sk_buff *skb;
++ bte_result_t bret;
++ struct xpnet_dev_private *priv =
++ (struct xpnet_dev_private *)xpnet_device->priv;
++
++ if (!XPNET_VALID_MSG(msg)) {
++ /*
++ * Packet with a different XPC version. Ignore.
++ */
++ xpc_received(partid, channel, (void *)msg);
++
++ priv->stats.rx_errors++;
++
++ return;
++ }
++ dev_dbg(xpnet, "received 0x%lx, %d, %d, %d\n", msg->buf_pa, msg->size,
++ msg->leadin_ignore, msg->tailout_ignore);
++
++ /* reserve an extra cache line */
++ skb = dev_alloc_skb(msg->size + L1_CACHE_BYTES);
++ if (!skb) {
++ dev_err(xpnet, "failed on dev_alloc_skb(%d)\n",
++ msg->size + L1_CACHE_BYTES);
++
++ xpc_received(partid, channel, (void *)msg);
++
++ priv->stats.rx_errors++;
++
++ return;
++ }
++
++ /*
++ * The allocated skb has some reserved space.
++ * In order to use bte_copy, we need to get the
++ * skb->data pointer moved forward.
++ */
++ skb_reserve(skb, (L1_CACHE_BYTES - ((u64)skb->data &
++ (L1_CACHE_BYTES - 1)) +
++ msg->leadin_ignore));
++
++ /*
++ * Update the tail pointer to indicate data actually
++ * transferred.
++ */
++ skb_put(skb, (msg->size - msg->leadin_ignore - msg->tailout_ignore));
++
++ /*
++ * Move the data over from the other side.
++ */
++ if ((XPNET_VERSION_MINOR(msg->version) == 1) &&
++ (msg->embedded_bytes != 0)) {
++ dev_dbg(xpnet, "copying embedded message. memcpy(0x%p, 0x%p, "
++ "%lu)\n", skb->data, &msg->data,
++ (size_t)msg->embedded_bytes);
++
++ skb_copy_to_linear_data(skb, &msg->data,
++ (size_t)msg->embedded_bytes);
++ } else {
++ dev_dbg(xpnet, "transferring buffer to the skb->data area;\n\t"
++ "bte_copy(0x%p, 0x%p, %hu)\n", (void *)msg->buf_pa,
++ (void *)__pa((u64)skb->data & ~(L1_CACHE_BYTES - 1)),
++ msg->size);
++
++ bret = bte_copy(msg->buf_pa,
++ __pa((u64)skb->data & ~(L1_CACHE_BYTES - 1)),
++ msg->size, (BTE_NOTIFY | BTE_WACQUIRE), NULL);
++
++ if (bret != BTE_SUCCESS) {
++ /*
++ * >>> Need better way of cleaning skb. Currently skb
++ * >>> appears in_use and we can't just call
++ * >>> dev_kfree_skb.
++ */
++ dev_err(xpnet, "bte_copy(0x%p, 0x%p, 0x%hx) returned "
++ "error=0x%x\n", (void *)msg->buf_pa,
++ (void *)__pa((u64)skb->data &
++ ~(L1_CACHE_BYTES - 1)),
++ msg->size, bret);
++
++ xpc_received(partid, channel, (void *)msg);
++
++ priv->stats.rx_errors++;
++
++ return;
++ }
++ }
++
++ dev_dbg(xpnet, "<skb->head=0x%p skb->data=0x%p skb->tail=0x%p "
++ "skb->end=0x%p skb->len=%d\n", (void *)skb->head,
++ (void *)skb->data, skb_tail_pointer(skb), skb_end_pointer(skb),
++ skb->len);
++
++ skb->protocol = eth_type_trans(skb, xpnet_device);
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++
++ dev_dbg(xpnet, "passing skb to network layer\n"
++ KERN_DEBUG "\tskb->head=0x%p skb->data=0x%p skb->tail=0x%p "
++ "skb->end=0x%p skb->len=%d\n",
++ (void *)skb->head, (void *)skb->data, skb_tail_pointer(skb),
++ skb_end_pointer(skb), skb->len);
++
++ xpnet_device->last_rx = jiffies;
++ priv->stats.rx_packets++;
++ priv->stats.rx_bytes += skb->len + ETH_HLEN;
++
++ netif_rx_ni(skb);
++ xpc_received(partid, channel, (void *)msg);
++}
++
++/*
++ * This is the handler which XPC calls during any sort of change in
++ * state or message reception on a connection.
++ */
++static void
++xpnet_connection_activity(enum xpc_retval reason, partid_t partid, int channel,
++ void *data, void *key)
++{
++ long bp;
++
++ DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
++ DBUG_ON(channel != XPC_NET_CHANNEL);
++
++ switch (reason) {
++ case xpcMsgReceived: /* message received */
++ DBUG_ON(data == NULL);
++
++ xpnet_receive(partid, channel, (struct xpnet_message *)data);
++ break;
++
++ case xpcConnected: /* connection completed to a partition */
++ spin_lock_bh(&xpnet_broadcast_lock);
++ xpnet_broadcast_partitions |= 1UL << (partid - 1);
++ bp = xpnet_broadcast_partitions;
++ spin_unlock_bh(&xpnet_broadcast_lock);
++
++ netif_carrier_on(xpnet_device);
++
++ dev_dbg(xpnet, "%s connection created to partition %d; "
++ "xpnet_broadcast_partitions=0x%lx\n",
++ xpnet_device->name, partid, bp);
++ break;
++
++ default:
++ spin_lock_bh(&xpnet_broadcast_lock);
++ xpnet_broadcast_partitions &= ~(1UL << (partid - 1));
++ bp = xpnet_broadcast_partitions;
++ spin_unlock_bh(&xpnet_broadcast_lock);
++
++ if (bp == 0)
++ netif_carrier_off(xpnet_device);
++
++ dev_dbg(xpnet, "%s disconnected from partition %d; "
++ "xpnet_broadcast_partitions=0x%lx\n",
++ xpnet_device->name, partid, bp);
++ break;
++
++ }
++}
++
++static int
++xpnet_dev_open(struct net_device *dev)
++{
++ enum xpc_retval ret;
++
++ dev_dbg(xpnet, "calling xpc_connect(%d, 0x%p, NULL, %ld, %ld, %ld, "
++ "%ld)\n", XPC_NET_CHANNEL, xpnet_connection_activity,
++ XPNET_MSG_SIZE, XPNET_MSG_NENTRIES, XPNET_MAX_KTHREADS,
++ XPNET_MAX_IDLE_KTHREADS);
++
++ ret = xpc_connect(XPC_NET_CHANNEL, xpnet_connection_activity, NULL,
++ XPNET_MSG_SIZE, XPNET_MSG_NENTRIES,
++ XPNET_MAX_KTHREADS, XPNET_MAX_IDLE_KTHREADS);
++ if (ret != xpcSuccess) {
++ dev_err(xpnet, "ifconfig up of %s failed on XPC connect, "
++ "ret=%d\n", dev->name, ret);
++
++ return -ENOMEM;
++ }
++
++ dev_dbg(xpnet, "ifconfig up of %s; XPC connected\n", dev->name);
++
++ return 0;
++}
++
++static int
++xpnet_dev_stop(struct net_device *dev)
++{
++ xpc_disconnect(XPC_NET_CHANNEL);
++
++ dev_dbg(xpnet, "ifconfig down of %s; XPC disconnected\n", dev->name);
++
++ return 0;
++}
++
++static int
++xpnet_dev_change_mtu(struct net_device *dev, int new_mtu)
++{
++ /* 68 comes from min TCP+IP+MAC header */
++ if ((new_mtu < 68) || (new_mtu > XPNET_MAX_MTU)) {
++ dev_err(xpnet, "ifconfig %s mtu %d failed; value must be "
++ "between 68 and %ld\n", dev->name, new_mtu,
++ XPNET_MAX_MTU);
++ return -EINVAL;
++ }
++
++ dev->mtu = new_mtu;
++ dev_dbg(xpnet, "ifconfig %s mtu set to %d\n", dev->name, new_mtu);
++ return 0;
++}
++
++/*
++ * Required for the net_device structure.
++ */
++static int
++xpnet_dev_set_config(struct net_device *dev, struct ifmap *new_map)
++{
++ return 0;
++}
++
++/*
++ * Return statistics to the caller.
++ */
++static struct net_device_stats *
++xpnet_dev_get_stats(struct net_device *dev)
++{
++ struct xpnet_dev_private *priv;
++
++ priv = (struct xpnet_dev_private *)dev->priv;
++
++ return &priv->stats;
++}
++
++/*
++ * Notification that the other end has received the message and
++ * DMA'd the skb information. At this point, they are done with
++ * our side. When all recipients are done processing, we
++ * release the skb and then release our pending message structure.
++ */
++static void
++xpnet_send_completed(enum xpc_retval reason, partid_t partid, int channel,
++ void *__qm)
++{
++ struct xpnet_pending_msg *queued_msg = (struct xpnet_pending_msg *)__qm;
++
++ DBUG_ON(queued_msg == NULL);
++
++ dev_dbg(xpnet, "message to %d notified with reason %d\n",
++ partid, reason);
++
++ if (atomic_dec_return(&queued_msg->use_count) == 0) {
++ dev_dbg(xpnet, "all acks for skb->head=-x%p\n",
++ (void *)queued_msg->skb->head);
++
++ dev_kfree_skb_any(queued_msg->skb);
++ kfree(queued_msg);
++ }
++}
++
++/*
++ * Network layer has formatted a packet (skb) and is ready to place it
++ * "on the wire". Prepare and send an xpnet_message to all partitions
++ * which have connected with us and are targets of this packet.
++ *
++ * MAC-NOTE: For the XPNET driver, the MAC address contains the
++ * destination partition_id. If the destination partition id word
++ * is 0xff, this packet is to broadcast to all partitions.
++ */
++static int
++xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++ struct xpnet_pending_msg *queued_msg;
++ enum xpc_retval ret;
++ struct xpnet_message *msg;
++ u64 start_addr, end_addr;
++ long dp;
++ u8 second_mac_octet;
++ partid_t dest_partid;
++ struct xpnet_dev_private *priv;
++ u16 embedded_bytes;
++
++ priv = (struct xpnet_dev_private *)dev->priv;
++
++ dev_dbg(xpnet, ">skb->head=0x%p skb->data=0x%p skb->tail=0x%p "
++ "skb->end=0x%p skb->len=%d\n", (void *)skb->head,
++ (void *)skb->data, skb_tail_pointer(skb), skb_end_pointer(skb),
++ skb->len);
++
++ /*
++ * The xpnet_pending_msg tracks how many outstanding
++ * xpc_send_notifies are relying on this skb. When none
++ * remain, release the skb.
++ */
++ queued_msg = kmalloc(sizeof(struct xpnet_pending_msg), GFP_ATOMIC);
++ if (queued_msg == NULL) {
++ dev_warn(xpnet, "failed to kmalloc %ld bytes; dropping "
++ "packet\n", sizeof(struct xpnet_pending_msg));
++
++ priv->stats.tx_errors++;
++
++ return -ENOMEM;
++ }
++
++ /* get the beginning of the first cacheline and end of last */
++ start_addr = ((u64)skb->data & ~(L1_CACHE_BYTES - 1));
++ end_addr = L1_CACHE_ALIGN((u64)skb_tail_pointer(skb));
++
++ /* calculate how many bytes to embed in the XPC message */
++ embedded_bytes = 0;
++ if (unlikely(skb->len <= XPNET_MSG_DATA_MAX)) {
++ /* skb->data does fit so embed */
++ embedded_bytes = skb->len;
++ }
++
++ /*
++ * Since the send occurs asynchronously, we set the count to one
++ * and begin sending. Any sends that happen to complete before
++ * we are done sending will not free the skb. We will be left
++ * with that task during exit. This also handles the case of
++ * a packet destined for a partition which is no longer up.
++ */
++ atomic_set(&queued_msg->use_count, 1);
++ queued_msg->skb = skb;
++
++ second_mac_octet = skb->data[XPNET_PARTID_OCTET];
++ if (second_mac_octet == 0xff) {
++ /* we are being asked to broadcast to all partitions */
++ dp = xpnet_broadcast_partitions;
++ } else if (second_mac_octet != 0) {
++ dp = xpnet_broadcast_partitions &
++ (1UL << (second_mac_octet - 1));
++ } else {
++ /* 0 is an invalid partid. Ignore */
++ dp = 0;
++ }
++ dev_dbg(xpnet, "destination Partitions mask (dp) = 0x%lx\n", dp);
++
++ /*
++ * If we wanted to allow promiscuous mode to work like an
++ * unswitched network, this would be a good point to OR in a
++ * mask of partitions which should be receiving all packets.
++ */
++
++ /*
++ * Main send loop.
++ */
++ for (dest_partid = 1; dp && dest_partid < XP_MAX_PARTITIONS;
++ dest_partid++) {
++
++ if (!(dp & (1UL << (dest_partid - 1)))) {
++ /* not destined for this partition */
++ continue;
++ }
++
++ /* remove this partition from the destinations mask */
++ dp &= ~(1UL << (dest_partid - 1));
++
++ /* found a partition to send to */
++
++ ret = xpc_allocate(dest_partid, XPC_NET_CHANNEL,
++ XPC_NOWAIT, (void **)&msg);
++ if (unlikely(ret != xpcSuccess))
++ continue;
++
++ msg->embedded_bytes = embedded_bytes;
++ if (unlikely(embedded_bytes != 0)) {
++ msg->version = XPNET_VERSION_EMBED;
++ dev_dbg(xpnet, "calling memcpy(0x%p, 0x%p, 0x%lx)\n",
++ &msg->data, skb->data, (size_t)embedded_bytes);
++ skb_copy_from_linear_data(skb, &msg->data,
++ (size_t)embedded_bytes);
++ } else {
++ msg->version = XPNET_VERSION;
++ }
++ msg->magic = XPNET_MAGIC;
++ msg->size = end_addr - start_addr;
++ msg->leadin_ignore = (u64)skb->data - start_addr;
++ msg->tailout_ignore = end_addr - (u64)skb_tail_pointer(skb);
++ msg->buf_pa = __pa(start_addr);
++
++ dev_dbg(xpnet, "sending XPC message to %d:%d\n"
++ KERN_DEBUG "msg->buf_pa=0x%lx, msg->size=%u, "
++ "msg->leadin_ignore=%u, msg->tailout_ignore=%u\n",
++ dest_partid, XPC_NET_CHANNEL, msg->buf_pa, msg->size,
++ msg->leadin_ignore, msg->tailout_ignore);
++
++ atomic_inc(&queued_msg->use_count);
++
++ ret = xpc_send_notify(dest_partid, XPC_NET_CHANNEL, msg,
++ xpnet_send_completed, queued_msg);
++ if (unlikely(ret != xpcSuccess)) {
++ atomic_dec(&queued_msg->use_count);
++ continue;
++ }
++ }
++
++ if (atomic_dec_return(&queued_msg->use_count) == 0) {
++ dev_dbg(xpnet, "no partitions to receive packet destined for "
++ "%d\n", dest_partid);
++
++ dev_kfree_skb(skb);
++ kfree(queued_msg);
++ }
++
++ priv->stats.tx_packets++;
++ priv->stats.tx_bytes += skb->len;
++
++ return 0;
++}
++
++/*
++ * Deal with transmit timeouts coming from the network layer.
++ */
++static void
++xpnet_dev_tx_timeout(struct net_device *dev)
++{
++ struct xpnet_dev_private *priv;
++
++ priv = (struct xpnet_dev_private *)dev->priv;
++
++ priv->stats.tx_errors++;
++ return;
++}
++
++static int __init
++xpnet_init(void)
++{
++ int i;
++ u32 license_num;
++ int result = -ENOMEM;
++
++ if (!ia64_platform_is("sn2"))
++ return -ENODEV;
++
++ dev_info(xpnet, "registering network device %s\n", XPNET_DEVICE_NAME);
++
++ /*
++ * use ether_setup() to init the majority of our device
++ * structure and then override the necessary pieces.
++ */
++ xpnet_device = alloc_netdev(sizeof(struct xpnet_dev_private),
++ XPNET_DEVICE_NAME, ether_setup);
++ if (xpnet_device == NULL)
++ return -ENOMEM;
++
++ netif_carrier_off(xpnet_device);
++
++ xpnet_device->mtu = XPNET_DEF_MTU;
++ xpnet_device->change_mtu = xpnet_dev_change_mtu;
++ xpnet_device->open = xpnet_dev_open;
++ xpnet_device->get_stats = xpnet_dev_get_stats;
++ xpnet_device->stop = xpnet_dev_stop;
++ xpnet_device->hard_start_xmit = xpnet_dev_hard_start_xmit;
++ xpnet_device->tx_timeout = xpnet_dev_tx_timeout;
++ xpnet_device->set_config = xpnet_dev_set_config;
++
++ /*
++ * Multicast assumes the LSB of the first octet is set for multicast
++ * MAC addresses. We chose the first octet of the MAC to be unlikely
++ * to collide with any vendor's officially issued MAC.
++ */
++ xpnet_device->dev_addr[0] = 0xfe;
++ xpnet_device->dev_addr[XPNET_PARTID_OCTET] = sn_partition_id;
++ license_num = sn_partition_serial_number_val();
++ for (i = 3; i >= 0; i--) {
++ xpnet_device->dev_addr[XPNET_LICENSE_OCTET + i] =
++ license_num & 0xff;
++ license_num = license_num >> 8;
++ }
++
++ /*
++ * ether_setup() sets this to a multicast device. We are
++ * really not supporting multicast at this time.
++ */
++ xpnet_device->flags &= ~IFF_MULTICAST;
++
++ /*
++ * No need to checksum as it is a DMA transfer. The BTE will
++ * report an error if the data is not retrievable and the
++ * packet will be dropped.
++ */
++ xpnet_device->features = NETIF_F_NO_CSUM;
++
++ result = register_netdev(xpnet_device);
++ if (result != 0)
++ free_netdev(xpnet_device);
++
++ return result;
++}
++
++module_init(xpnet_init);
++
++static void __exit
++xpnet_exit(void)
++{
++ dev_info(xpnet, "unregistering network device %s\n",
++ xpnet_device[0].name);
++
++ unregister_netdev(xpnet_device);
++
++ free_netdev(xpnet_device);
++}
++
++module_exit(xpnet_exit);
++
++MODULE_AUTHOR("Silicon Graphics, Inc.");
++MODULE_DESCRIPTION("Cross Partition Network adapter (XPNET)");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
+index b966674..01ced4c 100644
+--- a/drivers/mmc/core/core.c
++++ b/drivers/mmc/core/core.c
+@@ -35,10 +35,6 @@
+ #include "sd_ops.h"
+ #include "sdio_ops.h"
+
+-extern int mmc_attach_mmc(struct mmc_host *host, u32 ocr);
+-extern int mmc_attach_sd(struct mmc_host *host, u32 ocr);
+-extern int mmc_attach_sdio(struct mmc_host *host, u32 ocr);
+-
+ static struct workqueue_struct *workqueue;
+
+ /*
+@@ -516,7 +512,7 @@ static void mmc_power_off(struct mmc_host *host)
+ /*
+ * Cleanup when the last reference to the bus operator is dropped.
+ */
+-void __mmc_release_bus(struct mmc_host *host)
++static void __mmc_release_bus(struct mmc_host *host)
+ {
+ BUG_ON(!host);
+ BUG_ON(host->bus_refs);
+diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
+index cfa8e15..cdb332b 100644
+--- a/drivers/mmc/core/core.h
++++ b/drivers/mmc/core/core.h
+@@ -46,6 +46,10 @@ void mmc_rescan(struct work_struct *work);
+ void mmc_start_host(struct mmc_host *host);
+ void mmc_stop_host(struct mmc_host *host);
+
++int mmc_attach_mmc(struct mmc_host *host, u32 ocr);
++int mmc_attach_sd(struct mmc_host *host, u32 ocr);
++int mmc_attach_sdio(struct mmc_host *host, u32 ocr);
++
+ extern int use_spi_crc;
+
+ #endif
+diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
+index c65d203..1d795c5 100644
+--- a/drivers/mmc/core/host.c
++++ b/drivers/mmc/core/host.c
+@@ -2,7 +2,7 @@
+ * linux/drivers/mmc/core/host.c
+ *
+ * Copyright (C) 2003 Russell King, All Rights Reserved.
+- * Copyright (C) 2007 Pierre Ossman
++ * Copyright (C) 2007-2008 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+@@ -57,12 +57,25 @@ static DEFINE_SPINLOCK(mmc_host_lock);
+ */
+ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
+ {
++ int err;
+ struct mmc_host *host;
+
++ if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
++ return NULL;
++
+ host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
+ if (!host)
+ return NULL;
+
++ spin_lock(&mmc_host_lock);
++ err = idr_get_new(&mmc_host_idr, host, &host->index);
++ spin_unlock(&mmc_host_lock);
++ if (err)
++ goto free;
++
++ snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
++ "mmc%d", host->index);
++
+ host->parent = dev;
+ host->class_dev.parent = dev;
+ host->class_dev.class = &mmc_host_class;
+@@ -85,6 +98,10 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
+ host->max_blk_count = PAGE_CACHE_SIZE / 512;
+
+ return host;
++
++free:
++ kfree(host);
++ return NULL;
+ }
+
+ EXPORT_SYMBOL(mmc_alloc_host);
+@@ -104,18 +121,6 @@ int mmc_add_host(struct mmc_host *host)
+ WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) &&
+ !host->ops->enable_sdio_irq);
+
+- if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
+- return -ENOMEM;
+-
+- spin_lock(&mmc_host_lock);
+- err = idr_get_new(&mmc_host_idr, host, &host->index);
+- spin_unlock(&mmc_host_lock);
+- if (err)
+- return err;
+-
+- snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
+- "mmc%d", host->index);
+-
+ led_trigger_register_simple(host->class_dev.bus_id, &host->led);
+
+ err = device_add(&host->class_dev);
+@@ -144,10 +149,6 @@ void mmc_remove_host(struct mmc_host *host)
+ device_del(&host->class_dev);
+
+ led_trigger_unregister_simple(host->led);
+-
+- spin_lock(&mmc_host_lock);
+- idr_remove(&mmc_host_idr, host->index);
+- spin_unlock(&mmc_host_lock);
+ }
+
+ EXPORT_SYMBOL(mmc_remove_host);
+@@ -160,6 +161,10 @@ EXPORT_SYMBOL(mmc_remove_host);
+ */
+ void mmc_free_host(struct mmc_host *host)
+ {
++ spin_lock(&mmc_host_lock);
++ idr_remove(&mmc_host_idr, host->index);
++ spin_unlock(&mmc_host_lock);
++
+ put_device(&host->class_dev);
+ }
+
+diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
+index 3bd3021..c292e12 100644
+--- a/drivers/mmc/core/sdio_irq.c
++++ b/drivers/mmc/core/sdio_irq.c
+@@ -128,12 +128,12 @@ static int sdio_irq_thread(void *_host)
+ }
+ }
+
+- set_task_state(current, TASK_INTERRUPTIBLE);
++ set_current_state(TASK_INTERRUPTIBLE);
+ if (host->caps & MMC_CAP_SDIO_IRQ)
+ host->ops->enable_sdio_irq(host, 1);
+ if (!kthread_should_stop())
+ schedule_timeout(period);
+- set_task_state(current, TASK_RUNNING);
++ set_current_state(TASK_RUNNING);
+ } while (!kthread_should_stop());
+
+ if (host->caps & MMC_CAP_SDIO_IRQ)
+diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c
+index e1fca58..c8fa095 100644
+--- a/drivers/mmc/core/sdio_ops.c
++++ b/drivers/mmc/core/sdio_ops.c
+@@ -17,6 +17,7 @@
+ #include <linux/mmc/sdio.h>
+
+ #include "core.h"
++#include "sdio_ops.h"
+
+ int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
+ {
+diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
+index 90c358b..14759e9 100644
+--- a/drivers/mmc/host/omap.c
++++ b/drivers/mmc/host/omap.c
+@@ -32,6 +32,7 @@
+ #include <asm/mach-types.h>
+
+ #include <asm/arch/board.h>
++#include <asm/arch/mmc.h>
+ #include <asm/arch/gpio.h>
+ #include <asm/arch/dma.h>
+ #include <asm/arch/mux.h>
+@@ -93,9 +94,27 @@
+
+ /* Specifies how often in millisecs to poll for card status changes
+ * when the cover switch is open */
+-#define OMAP_MMC_SWITCH_POLL_DELAY 500
+-
+-static int mmc_omap_enable_poll = 1;
++#define OMAP_MMC_COVER_POLL_DELAY 500
++
++struct mmc_omap_host;
++
++struct mmc_omap_slot {
++ int id;
++ unsigned int vdd;
++ u16 saved_con;
++ u16 bus_mode;
++ unsigned int fclk_freq;
++ unsigned powered:1;
++
++ struct tasklet_struct cover_tasklet;
++ struct timer_list cover_timer;
++ unsigned cover_open;
++
++ struct mmc_request *mrq;
++ struct mmc_omap_host *host;
++ struct mmc_host *mmc;
++ struct omap_mmc_slot_data *pdata;
++};
+
+ struct mmc_omap_host {
+ int initialized;
+@@ -115,6 +134,15 @@ struct mmc_omap_host {
+ unsigned char bus_mode;
+ unsigned char hw_bus_mode;
+
++ struct work_struct cmd_abort_work;
++ unsigned abort:1;
++ struct timer_list cmd_abort_timer;
++
++ struct work_struct slot_release_work;
++ struct mmc_omap_slot *next_slot;
++ struct work_struct send_stop_work;
++ struct mmc_data *stop_data;
++
+ unsigned int sg_len;
+ int sg_idx;
+ u16 * buffer;
+@@ -131,63 +159,178 @@ struct mmc_omap_host {
+ unsigned dma_len;
+
+ short power_pin;
+- short wp_pin;
+
+- int switch_pin;
+- struct work_struct switch_work;
+- struct timer_list switch_timer;
+- int switch_last_state;
++ struct mmc_omap_slot *slots[OMAP_MMC_MAX_SLOTS];
++ struct mmc_omap_slot *current_slot;
++ spinlock_t slot_lock;
++ wait_queue_head_t slot_wq;
++ int nr_slots;
++
++ struct timer_list clk_timer;
++ spinlock_t clk_lock; /* for changing enabled state */
++ unsigned int fclk_enabled:1;
++
++ struct omap_mmc_platform_data *pdata;
+ };
+
+-static inline int
+-mmc_omap_cover_is_open(struct mmc_omap_host *host)
++void mmc_omap_fclk_offdelay(struct mmc_omap_slot *slot)
+ {
+- if (host->switch_pin < 0)
+- return 0;
+- return omap_get_gpio_datain(host->switch_pin);
++ unsigned long tick_ns;
++
++ if (slot != NULL && slot->host->fclk_enabled && slot->fclk_freq > 0) {
++ tick_ns = (1000000000 + slot->fclk_freq - 1) / slot->fclk_freq;
++ ndelay(8 * tick_ns);
++ }
+ }
+
+-static ssize_t
+-mmc_omap_show_cover_switch(struct device *dev,
+- struct device_attribute *attr, char *buf)
++void mmc_omap_fclk_enable(struct mmc_omap_host *host, unsigned int enable)
+ {
+- struct mmc_omap_host *host = dev_get_drvdata(dev);
++ unsigned long flags;
+
+- return sprintf(buf, "%s\n", mmc_omap_cover_is_open(host) ? "open" :
+- "closed");
++ spin_lock_irqsave(&host->clk_lock, flags);
++ if (host->fclk_enabled != enable) {
++ host->fclk_enabled = enable;
++ if (enable)
++ clk_enable(host->fclk);
++ else
++ clk_disable(host->fclk);
++ }
++ spin_unlock_irqrestore(&host->clk_lock, flags);
+ }
+
+-static DEVICE_ATTR(cover_switch, S_IRUGO, mmc_omap_show_cover_switch, NULL);
++static void mmc_omap_select_slot(struct mmc_omap_slot *slot, int claimed)
++{
++ struct mmc_omap_host *host = slot->host;
++ unsigned long flags;
+
+-static ssize_t
+-mmc_omap_show_enable_poll(struct device *dev,
+- struct device_attribute *attr, char *buf)
++ if (claimed)
++ goto no_claim;
++ spin_lock_irqsave(&host->slot_lock, flags);
++ while (host->mmc != NULL) {
++ spin_unlock_irqrestore(&host->slot_lock, flags);
++ wait_event(host->slot_wq, host->mmc == NULL);
++ spin_lock_irqsave(&host->slot_lock, flags);
++ }
++ host->mmc = slot->mmc;
++ spin_unlock_irqrestore(&host->slot_lock, flags);
++no_claim:
++ del_timer(&host->clk_timer);
++ if (host->current_slot != slot || !claimed)
++ mmc_omap_fclk_offdelay(host->current_slot);
++
++ if (host->current_slot != slot) {
++ OMAP_MMC_WRITE(host, CON, slot->saved_con & 0xFC00);
++ if (host->pdata->switch_slot != NULL)
++ host->pdata->switch_slot(mmc_dev(slot->mmc), slot->id);
++ host->current_slot = slot;
++ }
++
++ if (claimed) {
++ mmc_omap_fclk_enable(host, 1);
++
++ /* Doing the dummy read here seems to work around some bug
++ * at least in OMAP24xx silicon where the command would not
++ * start after writing the CMD register. Sigh. */
++ OMAP_MMC_READ(host, CON);
++
++ OMAP_MMC_WRITE(host, CON, slot->saved_con);
++ } else
++ mmc_omap_fclk_enable(host, 0);
++}
++
++static void mmc_omap_start_request(struct mmc_omap_host *host,
++ struct mmc_request *req);
++
++static void mmc_omap_slot_release_work(struct work_struct *work)
+ {
+- return snprintf(buf, PAGE_SIZE, "%d\n", mmc_omap_enable_poll);
++ struct mmc_omap_host *host = container_of(work, struct mmc_omap_host,
++ slot_release_work);
++ struct mmc_omap_slot *next_slot = host->next_slot;
++ struct mmc_request *rq;
++
++ host->next_slot = NULL;
++ mmc_omap_select_slot(next_slot, 1);
++
++ rq = next_slot->mrq;
++ next_slot->mrq = NULL;
++ mmc_omap_start_request(host, rq);
+ }
+
+-static ssize_t
+-mmc_omap_store_enable_poll(struct device *dev,
+- struct device_attribute *attr, const char *buf,
+- size_t size)
++static void mmc_omap_release_slot(struct mmc_omap_slot *slot, int clk_enabled)
+ {
+- int enable_poll;
++ struct mmc_omap_host *host = slot->host;
++ unsigned long flags;
++ int i;
++
++ BUG_ON(slot == NULL || host->mmc == NULL);
++
++ if (clk_enabled)
++ /* Keeps clock running for at least 8 cycles on valid freq */
++ mod_timer(&host->clk_timer, jiffies + HZ/10);
++ else {
++ del_timer(&host->clk_timer);
++ mmc_omap_fclk_offdelay(slot);
++ mmc_omap_fclk_enable(host, 0);
++ }
+
+- if (sscanf(buf, "%10d", &enable_poll) != 1)
+- return -EINVAL;
++ spin_lock_irqsave(&host->slot_lock, flags);
++ /* Check for any pending requests */
++ for (i = 0; i < host->nr_slots; i++) {
++ struct mmc_omap_slot *new_slot;
+
+- if (enable_poll != mmc_omap_enable_poll) {
+- struct mmc_omap_host *host = dev_get_drvdata(dev);
++ if (host->slots[i] == NULL || host->slots[i]->mrq == NULL)
++ continue;
+
+- mmc_omap_enable_poll = enable_poll;
+- if (enable_poll && host->switch_pin >= 0)
+- schedule_work(&host->switch_work);
++ BUG_ON(host->next_slot != NULL);
++ new_slot = host->slots[i];
++ /* The current slot should not have a request in queue */
++ BUG_ON(new_slot == host->current_slot);
++
++ host->next_slot = new_slot;
++ host->mmc = new_slot->mmc;
++ spin_unlock_irqrestore(&host->slot_lock, flags);
++ schedule_work(&host->slot_release_work);
++ return;
+ }
+- return size;
++
++ host->mmc = NULL;
++ wake_up(&host->slot_wq);
++ spin_unlock_irqrestore(&host->slot_lock, flags);
++}
++
++static inline
++int mmc_omap_cover_is_open(struct mmc_omap_slot *slot)
++{
++ if (slot->pdata->get_cover_state)
++ return slot->pdata->get_cover_state(mmc_dev(slot->mmc),
++ slot->id);
++ return 0;
++}
++
++static ssize_t
++mmc_omap_show_cover_switch(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev);
++ struct mmc_omap_slot *slot = mmc_priv(mmc);
++
++ return sprintf(buf, "%s\n", mmc_omap_cover_is_open(slot) ? "open" :
++ "closed");
+ }
+
+-static DEVICE_ATTR(enable_poll, 0664,
+- mmc_omap_show_enable_poll, mmc_omap_store_enable_poll);
++static DEVICE_ATTR(cover_switch, S_IRUGO, mmc_omap_show_cover_switch, NULL);
++
++static ssize_t
++mmc_omap_show_slot_name(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev);
++ struct mmc_omap_slot *slot = mmc_priv(mmc);
++
++ return sprintf(buf, "%s\n", slot->pdata->name);
++}
++
++static DEVICE_ATTR(slot_name, S_IRUGO, mmc_omap_show_slot_name, NULL);
+
+ static void
+ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
+@@ -233,7 +376,7 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
+
+ cmdreg = cmd->opcode | (resptype << 8) | (cmdtype << 12);
+
+- if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
++ if (host->current_slot->bus_mode == MMC_BUSMODE_OPENDRAIN)
+ cmdreg |= 1 << 6;
+
+ if (cmd->flags & MMC_RSP_BUSY)
+@@ -242,7 +385,7 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
+ if (host->data && !(host->data->flags & MMC_DATA_WRITE))
+ cmdreg |= 1 << 15;
+
+- clk_enable(host->fclk);
++ mod_timer(&host->cmd_abort_timer, jiffies + HZ/2);
+
+ OMAP_MMC_WRITE(host, CTO, 200);
+ OMAP_MMC_WRITE(host, ARGL, cmd->arg & 0xffff);
+@@ -257,26 +400,46 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
+ }
+
+ static void
++mmc_omap_release_dma(struct mmc_omap_host *host, struct mmc_data *data,
++ int abort)
++{
++ enum dma_data_direction dma_data_dir;
++
++ BUG_ON(host->dma_ch < 0);
++ if (data->error)
++ omap_stop_dma(host->dma_ch);
++ /* Release DMA channel lazily */
++ mod_timer(&host->dma_timer, jiffies + HZ);
++ if (data->flags & MMC_DATA_WRITE)
++ dma_data_dir = DMA_TO_DEVICE;
++ else
++ dma_data_dir = DMA_FROM_DEVICE;
++ dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_len,
++ dma_data_dir);
++}
++
++static void mmc_omap_send_stop_work(struct work_struct *work)
++{
++ struct mmc_omap_host *host = container_of(work, struct mmc_omap_host,
++ send_stop_work);
++ struct mmc_omap_slot *slot = host->current_slot;
++ struct mmc_data *data = host->stop_data;
++ unsigned long tick_ns;
++
++ tick_ns = (1000000000 + slot->fclk_freq - 1)/slot->fclk_freq;
++ ndelay(8*tick_ns);
++
++ mmc_omap_start_command(host, data->stop);
++}
++
++static void
+ mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
+ {
+- if (host->dma_in_use) {
+- enum dma_data_direction dma_data_dir;
+-
+- BUG_ON(host->dma_ch < 0);
+- if (data->error)
+- omap_stop_dma(host->dma_ch);
+- /* Release DMA channel lazily */
+- mod_timer(&host->dma_timer, jiffies + HZ);
+- if (data->flags & MMC_DATA_WRITE)
+- dma_data_dir = DMA_TO_DEVICE;
+- else
+- dma_data_dir = DMA_FROM_DEVICE;
+- dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_len,
+- dma_data_dir);
+- }
++ if (host->dma_in_use)
++ mmc_omap_release_dma(host, data, data->error);
++
+ host->data = NULL;
+ host->sg_len = 0;
+- clk_disable(host->fclk);
+
+ /* NOTE: MMC layer will sometimes poll-wait CMD13 next, issuing
+ * dozens of requests until the card finishes writing data.
+@@ -284,12 +447,58 @@ mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
+ */
+
+ if (!data->stop) {
++ struct mmc_host *mmc;
++
+ host->mrq = NULL;
+- mmc_request_done(host->mmc, data->mrq);
++ mmc = host->mmc;
++ mmc_omap_release_slot(host->current_slot, 1);
++ mmc_request_done(mmc, data->mrq);
+ return;
+ }
+
+- mmc_omap_start_command(host, data->stop);
++ host->stop_data = data;
++ schedule_work(&host->send_stop_work);
++}
++
++static void
++mmc_omap_send_abort(struct mmc_omap_host *host, int maxloops)
++{
++ struct mmc_omap_slot *slot = host->current_slot;
++ unsigned int restarts, passes, timeout;
++ u16 stat = 0;
++
++ /* Sending abort takes 80 clocks. Have some extra and round up */
++ timeout = (120*1000000 + slot->fclk_freq - 1)/slot->fclk_freq;
++ restarts = 0;
++ while (restarts < maxloops) {
++ OMAP_MMC_WRITE(host, STAT, 0xFFFF);
++ OMAP_MMC_WRITE(host, CMD, (3 << 12) | (1 << 7));
++
++ passes = 0;
++ while (passes < timeout) {
++ stat = OMAP_MMC_READ(host, STAT);
++ if (stat & OMAP_MMC_STAT_END_OF_CMD)
++ goto out;
++ udelay(1);
++ passes++;
++ }
++
++ restarts++;
++ }
++out:
++ OMAP_MMC_WRITE(host, STAT, stat);
++}
++
++static void
++mmc_omap_abort_xfer(struct mmc_omap_host *host, struct mmc_data *data)
++{
++ if (host->dma_in_use)
++ mmc_omap_release_dma(host, data, 1);
++
++ host->data = NULL;
++ host->sg_len = 0;
++
++ mmc_omap_send_abort(host, 10000);
+ }
+
+ static void
+@@ -345,6 +554,8 @@ mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
+ {
+ host->cmd = NULL;
+
++ del_timer(&host->cmd_abort_timer);
++
+ if (cmd->flags & MMC_RSP_PRESENT) {
+ if (cmd->flags & MMC_RSP_136) {
+ /* response type 2 */
+@@ -369,10 +580,66 @@ mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
+ }
+
+ if (host->data == NULL || cmd->error) {
++ struct mmc_host *mmc;
++
++ if (host->data != NULL)
++ mmc_omap_abort_xfer(host, host->data);
+ host->mrq = NULL;
+- clk_disable(host->fclk);
+- mmc_request_done(host->mmc, cmd->mrq);
++ mmc = host->mmc;
++ mmc_omap_release_slot(host->current_slot, 1);
++ mmc_request_done(mmc, cmd->mrq);
++ }
++}
++
++/*
++ * Abort stuck command. Can occur when card is removed while it is being
++ * read.
++ */
++static void mmc_omap_abort_command(struct work_struct *work)
++{
++ struct mmc_omap_host *host = container_of(work, struct mmc_omap_host,
++ cmd_abort_work);
++ BUG_ON(!host->cmd);
++
++ dev_dbg(mmc_dev(host->mmc), "Aborting stuck command CMD%d\n",
++ host->cmd->opcode);
++
++ if (host->cmd->error == 0)
++ host->cmd->error = -ETIMEDOUT;
++
++ if (host->data == NULL) {
++ struct mmc_command *cmd;
++ struct mmc_host *mmc;
++
++ cmd = host->cmd;
++ host->cmd = NULL;
++ mmc_omap_send_abort(host, 10000);
++
++ host->mrq = NULL;
++ mmc = host->mmc;
++ mmc_omap_release_slot(host->current_slot, 1);
++ mmc_request_done(mmc, cmd->mrq);
++ } else
++ mmc_omap_cmd_done(host, host->cmd);
++
++ host->abort = 0;
++ enable_irq(host->irq);
++}
++
++static void
++mmc_omap_cmd_timer(unsigned long data)
++{
++ struct mmc_omap_host *host = (struct mmc_omap_host *) data;
++ unsigned long flags;
++
++ spin_lock_irqsave(&host->slot_lock, flags);
++ if (host->cmd != NULL && !host->abort) {
++ OMAP_MMC_WRITE(host, IE, 0);
++ disable_irq(host->irq);
++ host->abort = 1;
++ schedule_work(&host->cmd_abort_work);
+ }
++ spin_unlock_irqrestore(&host->slot_lock, flags);
+ }
+
+ /* PIO only */
+@@ -388,6 +655,14 @@ mmc_omap_sg_to_buf(struct mmc_omap_host *host)
+ host->buffer_bytes_left = host->total_bytes_left;
+ }
+
++static void
++mmc_omap_clk_timer(unsigned long data)
++{
++ struct mmc_omap_host *host = (struct mmc_omap_host *) data;
++
++ mmc_omap_fclk_enable(host, 0);
++}
++
+ /* PIO only */
+ static void
+ mmc_omap_xfer_data(struct mmc_omap_host *host, int write)
+@@ -436,11 +711,12 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
+ u16 status;
+ int end_command;
+ int end_transfer;
+- int transfer_error;
++ int transfer_error, cmd_error;
+
+ if (host->cmd == NULL && host->data == NULL) {
+ status = OMAP_MMC_READ(host, STAT);
+- dev_info(mmc_dev(host->mmc),"spurious irq 0x%04x\n", status);
++ dev_info(mmc_dev(host->slots[0]->mmc),
++ "Spurious IRQ 0x%04x\n", status);
+ if (status != 0) {
+ OMAP_MMC_WRITE(host, STAT, status);
+ OMAP_MMC_WRITE(host, IE, 0);
+@@ -451,12 +727,19 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
+ end_command = 0;
+ end_transfer = 0;
+ transfer_error = 0;
++ cmd_error = 0;
+
+ while ((status = OMAP_MMC_READ(host, STAT)) != 0) {
++ int cmd;
++
+ OMAP_MMC_WRITE(host, STAT, status);
++ if (host->cmd != NULL)
++ cmd = host->cmd->opcode;
++ else
++ cmd = -1;
+ #ifdef CONFIG_MMC_DEBUG
+ dev_dbg(mmc_dev(host->mmc), "MMC IRQ %04x (CMD %d): ",
+- status, host->cmd != NULL ? host->cmd->opcode : -1);
++ status, cmd);
+ mmc_omap_report_irq(status);
+ printk("\n");
+ #endif
+@@ -468,12 +751,12 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
+ mmc_omap_xfer_data(host, 1);
+ }
+
+- if (status & OMAP_MMC_STAT_END_OF_DATA) {
++ if (status & OMAP_MMC_STAT_END_OF_DATA)
+ end_transfer = 1;
+- }
+
+ if (status & OMAP_MMC_STAT_DATA_TOUT) {
+- dev_dbg(mmc_dev(host->mmc), "data timeout\n");
++ dev_dbg(mmc_dev(host->mmc), "data timeout (CMD%d)\n",
++ cmd);
+ if (host->data) {
+ host->data->error = -ETIMEDOUT;
+ transfer_error = 1;
+@@ -495,17 +778,16 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
+ if (status & OMAP_MMC_STAT_CMD_TOUT) {
+ /* Timeouts are routine with some commands */
+ if (host->cmd) {
+- if (host->cmd->opcode != MMC_ALL_SEND_CID &&
+- host->cmd->opcode !=
+- MMC_SEND_OP_COND &&
+- host->cmd->opcode !=
+- MMC_APP_CMD &&
+- !mmc_omap_cover_is_open(host))
++ struct mmc_omap_slot *slot =
++ host->current_slot;
++ if (slot == NULL ||
++ !mmc_omap_cover_is_open(slot))
+ dev_err(mmc_dev(host->mmc),
+- "command timeout, CMD %d\n",
+- host->cmd->opcode);
++ "command timeout (CMD%d)\n",
++ cmd);
+ host->cmd->error = -ETIMEDOUT;
+ end_command = 1;
++ cmd_error = 1;
+ }
+ }
+
+@@ -513,9 +795,10 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
+ if (host->cmd) {
+ dev_err(mmc_dev(host->mmc),
+ "command CRC error (CMD%d, arg 0x%08x)\n",
+- host->cmd->opcode, host->cmd->arg);
++ cmd, host->cmd->arg);
+ host->cmd->error = -EILSEQ;
+ end_command = 1;
++ cmd_error = 1;
+ } else
+ dev_err(mmc_dev(host->mmc),
+ "command CRC error without cmd?\n");
+@@ -524,13 +807,13 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
+ if (status & OMAP_MMC_STAT_CARD_ERR) {
+ dev_dbg(mmc_dev(host->mmc),
+ "ignoring card status error (CMD%d)\n",
+- host->cmd->opcode);
++ cmd);
+ end_command = 1;
+ }
+
+ /*
+ * NOTE: On 1610 the END_OF_CMD may come too early when
+- * starting a write
++ * starting a write
+ */
+ if ((status & OMAP_MMC_STAT_END_OF_CMD) &&
+ (!(status & OMAP_MMC_STAT_A_EMPTY))) {
+@@ -538,63 +821,72 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
+ }
+ }
+
+- if (end_command) {
++ if (cmd_error && host->data) {
++ del_timer(&host->cmd_abort_timer);
++ host->abort = 1;
++ OMAP_MMC_WRITE(host, IE, 0);
++ disable_irq(host->irq);
++ schedule_work(&host->cmd_abort_work);
++ return IRQ_HANDLED;
++ }
++
++ if (end_command)
+ mmc_omap_cmd_done(host, host->cmd);
++ if (host->data != NULL) {
++ if (transfer_error)
++ mmc_omap_xfer_done(host, host->data);
++ else if (end_transfer)
++ mmc_omap_end_of_data(host, host->data);
+ }
+- if (transfer_error)
+- mmc_omap_xfer_done(host, host->data);
+- else if (end_transfer)
+- mmc_omap_end_of_data(host, host->data);
+
+ return IRQ_HANDLED;
+ }
+
+-static irqreturn_t mmc_omap_switch_irq(int irq, void *dev_id)
++void omap_mmc_notify_cover_event(struct device *dev, int num, int is_closed)
+ {
+- struct mmc_omap_host *host = (struct mmc_omap_host *) dev_id;
++ int cover_open;
++ struct mmc_omap_host *host = dev_get_drvdata(dev);
++ struct mmc_omap_slot *slot = host->slots[num];
+
+- schedule_work(&host->switch_work);
++ BUG_ON(num >= host->nr_slots);
+
+- return IRQ_HANDLED;
++ /* Other subsystems can call in here before we're initialised. */
++ if (host->nr_slots == 0 || !host->slots[num])
++ return;
++
++ cover_open = mmc_omap_cover_is_open(slot);
++ if (cover_open != slot->cover_open) {
++ slot->cover_open = cover_open;
++ sysfs_notify(&slot->mmc->class_dev.kobj, NULL, "cover_switch");
++ }
++
++ tasklet_hi_schedule(&slot->cover_tasklet);
+ }
+
+-static void mmc_omap_switch_timer(unsigned long arg)
++static void mmc_omap_cover_timer(unsigned long arg)
+ {
+- struct mmc_omap_host *host = (struct mmc_omap_host *) arg;
+-
+- schedule_work(&host->switch_work);
++ struct mmc_omap_slot *slot = (struct mmc_omap_slot *) arg;
++ tasklet_schedule(&slot->cover_tasklet);
+ }
+
+-static void mmc_omap_switch_handler(struct work_struct *work)
++static void mmc_omap_cover_handler(unsigned long param)
+ {
+- struct mmc_omap_host *host = container_of(work, struct mmc_omap_host, switch_work);
+- struct mmc_card *card;
+- static int complained = 0;
+- int cards = 0, cover_open;
++ struct mmc_omap_slot *slot = (struct mmc_omap_slot *)param;
++ int cover_open = mmc_omap_cover_is_open(slot);
+
+- if (host->switch_pin == -1)
++ mmc_detect_change(slot->mmc, 0);
++ if (!cover_open)
+ return;
+- cover_open = mmc_omap_cover_is_open(host);
+- if (cover_open != host->switch_last_state) {
+- kobject_uevent(&host->dev->kobj, KOBJ_CHANGE);
+- host->switch_last_state = cover_open;
+- }
+- mmc_detect_change(host->mmc, 0);
+- list_for_each_entry(card, &host->mmc->cards, node) {
+- if (mmc_card_present(card))
+- cards++;
+- }
+- if (mmc_omap_cover_is_open(host)) {
+- if (!complained) {
+- dev_info(mmc_dev(host->mmc), "cover is open\n");
+- complained = 1;
+- }
+- if (mmc_omap_enable_poll)
+- mod_timer(&host->switch_timer, jiffies +
+- msecs_to_jiffies(OMAP_MMC_SWITCH_POLL_DELAY));
+- } else {
+- complained = 0;
+- }
++
++ /*
++ * If no card is inserted, we postpone polling until
++ * the cover has been closed.
++ */
++ if (slot->mmc->card == NULL || !mmc_card_present(slot->mmc->card))
++ return;
++
++ mod_timer(&slot->cover_timer,
++ jiffies + msecs_to_jiffies(OMAP_MMC_COVER_POLL_DELAY));
+ }
+
+ /* Prepare to transfer the next segment of a scatterlist */
+@@ -765,13 +1057,12 @@ static inline void set_cmd_timeout(struct mmc_omap_host *host, struct mmc_reques
+
+ static inline void set_data_timeout(struct mmc_omap_host *host, struct mmc_request *req)
+ {
+- int timeout;
++ unsigned int timeout, cycle_ns;
+ u16 reg;
+
+- /* Convert ns to clock cycles by assuming 20MHz frequency
+- * 1 cycle at 20MHz = 500 ns
+- */
+- timeout = req->data->timeout_clks + req->data->timeout_ns / 500;
++ cycle_ns = 1000000000 / host->current_slot->fclk_freq;
++ timeout = req->data->timeout_ns / cycle_ns;
++ timeout += req->data->timeout_clks;
+
+ /* Check if we need to use timeout multiplier register */
+ reg = OMAP_MMC_READ(host, SDIO);
+@@ -854,11 +1145,10 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
+ }
+ }
+
+-static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req)
++static void mmc_omap_start_request(struct mmc_omap_host *host,
++ struct mmc_request *req)
+ {
+- struct mmc_omap_host *host = mmc_priv(mmc);
+-
+- WARN_ON(host->mrq != NULL);
++ BUG_ON(host->mrq != NULL);
+
+ host->mrq = req;
+
+@@ -867,60 +1157,56 @@ static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req)
+ mmc_omap_start_command(host, req->cmd);
+ if (host->dma_in_use)
+ omap_start_dma(host->dma_ch);
++ BUG_ON(irqs_disabled());
+ }
+
+-static void innovator_fpga_socket_power(int on)
++static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req)
+ {
+-#if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP15XX)
+- if (on) {
+- fpga_write(fpga_read(OMAP1510_FPGA_POWER) | (1 << 3),
+- OMAP1510_FPGA_POWER);
+- } else {
+- fpga_write(fpga_read(OMAP1510_FPGA_POWER) & ~(1 << 3),
+- OMAP1510_FPGA_POWER);
+- }
+-#endif
++ struct mmc_omap_slot *slot = mmc_priv(mmc);
++ struct mmc_omap_host *host = slot->host;
++ unsigned long flags;
++
++ spin_lock_irqsave(&host->slot_lock, flags);
++ if (host->mmc != NULL) {
++ BUG_ON(slot->mrq != NULL);
++ slot->mrq = req;
++ spin_unlock_irqrestore(&host->slot_lock, flags);
++ return;
++ } else
++ host->mmc = mmc;
++ spin_unlock_irqrestore(&host->slot_lock, flags);
++ mmc_omap_select_slot(slot, 1);
++ mmc_omap_start_request(host, req);
+ }
+
+-/*
+- * Turn the socket power on/off. Innovator uses FPGA, most boards
+- * probably use GPIO.
+- */
+-static void mmc_omap_power(struct mmc_omap_host *host, int on)
++static void mmc_omap_set_power(struct mmc_omap_slot *slot, int power_on,
++ int vdd)
+ {
+- if (on) {
+- if (machine_is_omap_innovator())
+- innovator_fpga_socket_power(1);
+- else if (machine_is_omap_h2())
+- tps65010_set_gpio_out_value(GPIO3, HIGH);
+- else if (machine_is_omap_h3())
+- /* GPIO 4 of TPS65010 sends SD_EN signal */
+- tps65010_set_gpio_out_value(GPIO4, HIGH);
+- else if (cpu_is_omap24xx()) {
+- u16 reg = OMAP_MMC_READ(host, CON);
+- OMAP_MMC_WRITE(host, CON, reg | (1 << 11));
+- } else
+- if (host->power_pin >= 0)
+- omap_set_gpio_dataout(host->power_pin, 1);
+- } else {
+- if (machine_is_omap_innovator())
+- innovator_fpga_socket_power(0);
+- else if (machine_is_omap_h2())
+- tps65010_set_gpio_out_value(GPIO3, LOW);
+- else if (machine_is_omap_h3())
+- tps65010_set_gpio_out_value(GPIO4, LOW);
+- else if (cpu_is_omap24xx()) {
+- u16 reg = OMAP_MMC_READ(host, CON);
+- OMAP_MMC_WRITE(host, CON, reg & ~(1 << 11));
+- } else
+- if (host->power_pin >= 0)
+- omap_set_gpio_dataout(host->power_pin, 0);
++ struct mmc_omap_host *host;
++
++ host = slot->host;
++
++ if (slot->pdata->set_power != NULL)
++ slot->pdata->set_power(mmc_dev(slot->mmc), slot->id, power_on,
++ vdd);
++
++ if (cpu_is_omap24xx()) {
++ u16 w;
++
++ if (power_on) {
++ w = OMAP_MMC_READ(host, CON);
++ OMAP_MMC_WRITE(host, CON, w | (1 << 11));
++ } else {
++ w = OMAP_MMC_READ(host, CON);
++ OMAP_MMC_WRITE(host, CON, w & ~(1 << 11));
++ }
+ }
+ }
+
+ static int mmc_omap_calc_divisor(struct mmc_host *mmc, struct mmc_ios *ios)
+ {
+- struct mmc_omap_host *host = mmc_priv(mmc);
++ struct mmc_omap_slot *slot = mmc_priv(mmc);
++ struct mmc_omap_host *host = slot->host;
+ int func_clk_rate = clk_get_rate(host->fclk);
+ int dsor;
+
+@@ -936,7 +1222,8 @@ static int mmc_omap_calc_divisor(struct mmc_host *mmc, struct mmc_ios *ios)
+
+ if (dsor > 250)
+ dsor = 250;
+- dsor++;
++
++ slot->fclk_freq = func_clk_rate / dsor;
+
+ if (ios->bus_width == MMC_BUS_WIDTH_4)
+ dsor |= 1 << 15;
+@@ -946,28 +1233,40 @@ static int mmc_omap_calc_divisor(struct mmc_host *mmc, struct mmc_ios *ios)
+
+ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+ {
+- struct mmc_omap_host *host = mmc_priv(mmc);
+- int dsor;
+- int i;
++ struct mmc_omap_slot *slot = mmc_priv(mmc);
++ struct mmc_omap_host *host = slot->host;
++ int i, dsor;
++ int clk_enabled;
++
++ mmc_omap_select_slot(slot, 0);
+
+ dsor = mmc_omap_calc_divisor(mmc, ios);
+- host->bus_mode = ios->bus_mode;
+- host->hw_bus_mode = host->bus_mode;
+
++ if (ios->vdd != slot->vdd)
++ slot->vdd = ios->vdd;
++
++ clk_enabled = 0;
+ switch (ios->power_mode) {
+ case MMC_POWER_OFF:
+- mmc_omap_power(host, 0);
++ mmc_omap_set_power(slot, 0, ios->vdd);
+ break;
+ case MMC_POWER_UP:
+ /* Cannot touch dsor yet, just power up MMC */
+- mmc_omap_power(host, 1);
+- return;
++ mmc_omap_set_power(slot, 1, ios->vdd);
++ goto exit;
+ case MMC_POWER_ON:
++ mmc_omap_fclk_enable(host, 1);
++ clk_enabled = 1;
+ dsor |= 1 << 11;
+ break;
+ }
+
+- clk_enable(host->fclk);
++ if (slot->bus_mode != ios->bus_mode) {
++ if (slot->pdata->set_bus_mode != NULL)
++ slot->pdata->set_bus_mode(mmc_dev(mmc), slot->id,
++ ios->bus_mode);
++ slot->bus_mode = ios->bus_mode;
++ }
+
+ /* On insanely high arm_per frequencies something sometimes
+ * goes somehow out of sync, and the POW bit is not being set,
+@@ -975,43 +1274,143 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+ * Writing to the CON register twice seems to do the trick. */
+ for (i = 0; i < 2; i++)
+ OMAP_MMC_WRITE(host, CON, dsor);
++ slot->saved_con = dsor;
+ if (ios->power_mode == MMC_POWER_ON) {
++ /* worst case at 400kHz, 80 cycles makes 200 microsecs */
++ int usecs = 250;
++
+ /* Send clock cycles, poll completion */
+ OMAP_MMC_WRITE(host, IE, 0);
+ OMAP_MMC_WRITE(host, STAT, 0xffff);
+ OMAP_MMC_WRITE(host, CMD, 1 << 7);
+- while ((OMAP_MMC_READ(host, STAT) & 1) == 0);
++ while (usecs > 0 && (OMAP_MMC_READ(host, STAT) & 1) == 0) {
++ udelay(1);
++ usecs--;
++ }
+ OMAP_MMC_WRITE(host, STAT, 1);
+ }
+- clk_disable(host->fclk);
+-}
+-
+-static int mmc_omap_get_ro(struct mmc_host *mmc)
+-{
+- struct mmc_omap_host *host = mmc_priv(mmc);
+
+- return host->wp_pin && omap_get_gpio_datain(host->wp_pin);
++exit:
++ mmc_omap_release_slot(slot, clk_enabled);
+ }
+
+ static const struct mmc_host_ops mmc_omap_ops = {
+ .request = mmc_omap_request,
+ .set_ios = mmc_omap_set_ios,
+- .get_ro = mmc_omap_get_ro,
+ };
+
+-static int __init mmc_omap_probe(struct platform_device *pdev)
++static int __init mmc_omap_new_slot(struct mmc_omap_host *host, int id)
+ {
+- struct omap_mmc_conf *minfo = pdev->dev.platform_data;
++ struct mmc_omap_slot *slot = NULL;
+ struct mmc_host *mmc;
++ int r;
++
++ mmc = mmc_alloc_host(sizeof(struct mmc_omap_slot), host->dev);
++ if (mmc == NULL)
++ return -ENOMEM;
++
++ slot = mmc_priv(mmc);
++ slot->host = host;
++ slot->mmc = mmc;
++ slot->id = id;
++ slot->pdata = &host->pdata->slots[id];
++
++ host->slots[id] = slot;
++
++ mmc->caps = MMC_CAP_MULTIWRITE;
++ if (host->pdata->conf.wire4)
++ mmc->caps |= MMC_CAP_4_BIT_DATA;
++
++ mmc->ops = &mmc_omap_ops;
++ mmc->f_min = 400000;
++
++ if (cpu_class_is_omap2())
++ mmc->f_max = 48000000;
++ else
++ mmc->f_max = 24000000;
++ if (host->pdata->max_freq)
++ mmc->f_max = min(host->pdata->max_freq, mmc->f_max);
++ mmc->ocr_avail = slot->pdata->ocr_mask;
++
++ /* Use scatterlist DMA to reduce per-transfer costs.
++ * NOTE max_seg_size assumption that small blocks aren't
++ * normally used (except e.g. for reading SD registers).
++ */
++ mmc->max_phys_segs = 32;
++ mmc->max_hw_segs = 32;
++ mmc->max_blk_size = 2048; /* BLEN is 11 bits (+1) */
++ mmc->max_blk_count = 2048; /* NBLK is 11 bits (+1) */
++ mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
++ mmc->max_seg_size = mmc->max_req_size;
++
++ r = mmc_add_host(mmc);
++ if (r < 0)
++ goto err_remove_host;
++
++ if (slot->pdata->name != NULL) {
++ r = device_create_file(&mmc->class_dev,
++ &dev_attr_slot_name);
++ if (r < 0)
++ goto err_remove_host;
++ }
++
++ if (slot->pdata->get_cover_state != NULL) {
++ r = device_create_file(&mmc->class_dev,
++ &dev_attr_cover_switch);
++ if (r < 0)
++ goto err_remove_slot_name;
++
++ setup_timer(&slot->cover_timer, mmc_omap_cover_timer,
++ (unsigned long)slot);
++ tasklet_init(&slot->cover_tasklet, mmc_omap_cover_handler,
++ (unsigned long)slot);
++ tasklet_schedule(&slot->cover_tasklet);
++ }
++
++ return 0;
++
++err_remove_slot_name:
++ if (slot->pdata->name != NULL)
++ device_remove_file(&mmc->class_dev, &dev_attr_slot_name);
++err_remove_host:
++ mmc_remove_host(mmc);
++ mmc_free_host(mmc);
++ return r;
++}
++
++static void mmc_omap_remove_slot(struct mmc_omap_slot *slot)
++{
++ struct mmc_host *mmc = slot->mmc;
++
++ if (slot->pdata->name != NULL)
++ device_remove_file(&mmc->class_dev, &dev_attr_slot_name);
++ if (slot->pdata->get_cover_state != NULL)
++ device_remove_file(&mmc->class_dev, &dev_attr_cover_switch);
++
++ tasklet_kill(&slot->cover_tasklet);
++ del_timer_sync(&slot->cover_timer);
++ flush_scheduled_work();
++
++ mmc_remove_host(mmc);
++ mmc_free_host(mmc);
++}
++
++static int __init mmc_omap_probe(struct platform_device *pdev)
++{
++ struct omap_mmc_platform_data *pdata = pdev->dev.platform_data;
+ struct mmc_omap_host *host = NULL;
+ struct resource *res;
+- int ret = 0;
++ int i, ret = 0;
+ int irq;
+
+- if (minfo == NULL) {
++ if (pdata == NULL) {
+ dev_err(&pdev->dev, "platform data missing\n");
+ return -ENXIO;
+ }
++ if (pdata->nr_slots == 0) {
++ dev_err(&pdev->dev, "no slots\n");
++ return -ENXIO;
++ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ irq = platform_get_irq(pdev, 0);
+@@ -1019,28 +1418,46 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
+ return -ENXIO;
+
+ res = request_mem_region(res->start, res->end - res->start + 1,
+- pdev->name);
++ pdev->name);
+ if (res == NULL)
+ return -EBUSY;
+
+- mmc = mmc_alloc_host(sizeof(struct mmc_omap_host), &pdev->dev);
+- if (mmc == NULL) {
++ host = kzalloc(sizeof(struct mmc_omap_host), GFP_KERNEL);
++ if (host == NULL) {
+ ret = -ENOMEM;
+ goto err_free_mem_region;
+ }
+
+- host = mmc_priv(mmc);
+- host->mmc = mmc;
++ INIT_WORK(&host->slot_release_work, mmc_omap_slot_release_work);
++ INIT_WORK(&host->send_stop_work, mmc_omap_send_stop_work);
++
++ INIT_WORK(&host->cmd_abort_work, mmc_omap_abort_command);
++ setup_timer(&host->cmd_abort_timer, mmc_omap_cmd_timer,
++ (unsigned long) host);
++
++ spin_lock_init(&host->clk_lock);
++ setup_timer(&host->clk_timer, mmc_omap_clk_timer, (unsigned long) host);
+
+ spin_lock_init(&host->dma_lock);
+- init_timer(&host->dma_timer);
+- host->dma_timer.function = mmc_omap_dma_timer;
+- host->dma_timer.data = (unsigned long) host;
++ setup_timer(&host->dma_timer, mmc_omap_dma_timer, (unsigned long) host);
++ spin_lock_init(&host->slot_lock);
++ init_waitqueue_head(&host->slot_wq);
++
++ host->pdata = pdata;
++ host->dev = &pdev->dev;
++ platform_set_drvdata(pdev, host);
+
+ host->id = pdev->id;
+ host->mem_res = res;
+ host->irq = irq;
+
++ host->use_dma = 1;
++ host->dma_ch = -1;
++
++ host->irq = irq;
++ host->phys_base = host->mem_res->start;
++ host->virt_base = (void __iomem *) IO_ADDRESS(host->phys_base);
++
+ if (cpu_is_omap24xx()) {
+ host->iclk = clk_get(&pdev->dev, "mmc_ick");
+ if (IS_ERR(host->iclk))
+@@ -1058,109 +1475,34 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
+ goto err_free_iclk;
+ }
+
+- /* REVISIT:
+- * Also, use minfo->cover to decide how to manage
+- * the card detect sensing.
+- */
+- host->power_pin = minfo->power_pin;
+- host->switch_pin = minfo->switch_pin;
+- host->wp_pin = minfo->wp_pin;
+- host->use_dma = 1;
+- host->dma_ch = -1;
+-
+- host->irq = irq;
+- host->phys_base = host->mem_res->start;
+- host->virt_base = (void __iomem *) IO_ADDRESS(host->phys_base);
+-
+- mmc->ops = &mmc_omap_ops;
+- mmc->f_min = 400000;
+- mmc->f_max = 24000000;
+- mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+- mmc->caps = MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK;
+-
+- if (minfo->wire4)
+- mmc->caps |= MMC_CAP_4_BIT_DATA;
+-
+- /* Use scatterlist DMA to reduce per-transfer costs.
+- * NOTE max_seg_size assumption that small blocks aren't
+- * normally used (except e.g. for reading SD registers).
+- */
+- mmc->max_phys_segs = 32;
+- mmc->max_hw_segs = 32;
+- mmc->max_blk_size = 2048; /* BLEN is 11 bits (+1) */
+- mmc->max_blk_count = 2048; /* NBLK is 11 bits (+1) */
+- mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
+- mmc->max_seg_size = mmc->max_req_size;
+-
+- if (host->power_pin >= 0) {
+- if ((ret = omap_request_gpio(host->power_pin)) != 0) {
+- dev_err(mmc_dev(host->mmc),
+- "Unable to get GPIO pin for MMC power\n");
+- goto err_free_fclk;
+- }
+- omap_set_gpio_direction(host->power_pin, 0);
+- }
+-
+ ret = request_irq(host->irq, mmc_omap_irq, 0, DRIVER_NAME, host);
+ if (ret)
+- goto err_free_power_gpio;
++ goto err_free_fclk;
+
+- host->dev = &pdev->dev;
+- platform_set_drvdata(pdev, host);
++ if (pdata->init != NULL) {
++ ret = pdata->init(&pdev->dev);
++ if (ret < 0)
++ goto err_free_irq;
++ }
+
+- if (host->switch_pin >= 0) {
+- INIT_WORK(&host->switch_work, mmc_omap_switch_handler);
+- init_timer(&host->switch_timer);
+- host->switch_timer.function = mmc_omap_switch_timer;
+- host->switch_timer.data = (unsigned long) host;
+- if (omap_request_gpio(host->switch_pin) != 0) {
+- dev_warn(mmc_dev(host->mmc), "Unable to get GPIO pin for MMC cover switch\n");
+- host->switch_pin = -1;
+- goto no_switch;
+- }
++ host->nr_slots = pdata->nr_slots;
++ for (i = 0; i < pdata->nr_slots; i++) {
++ ret = mmc_omap_new_slot(host, i);
++ if (ret < 0) {
++ while (--i >= 0)
++ mmc_omap_remove_slot(host->slots[i]);
+
+- omap_set_gpio_direction(host->switch_pin, 1);
+- ret = request_irq(OMAP_GPIO_IRQ(host->switch_pin),
+- mmc_omap_switch_irq, IRQF_TRIGGER_RISING, DRIVER_NAME, host);
+- if (ret) {
+- dev_warn(mmc_dev(host->mmc), "Unable to get IRQ for MMC cover switch\n");
+- omap_free_gpio(host->switch_pin);
+- host->switch_pin = -1;
+- goto no_switch;
+- }
+- ret = device_create_file(&pdev->dev, &dev_attr_cover_switch);
+- if (ret == 0) {
+- ret = device_create_file(&pdev->dev, &dev_attr_enable_poll);
+- if (ret != 0)
+- device_remove_file(&pdev->dev, &dev_attr_cover_switch);
++ goto err_plat_cleanup;
+ }
+- if (ret) {
+- dev_warn(mmc_dev(host->mmc), "Unable to create sysfs attributes\n");
+- free_irq(OMAP_GPIO_IRQ(host->switch_pin), host);
+- omap_free_gpio(host->switch_pin);
+- host->switch_pin = -1;
+- goto no_switch;
+- }
+- if (mmc_omap_enable_poll && mmc_omap_cover_is_open(host))
+- schedule_work(&host->switch_work);
+ }
+
+- mmc_add_host(mmc);
+-
+ return 0;
+
+-no_switch:
+- /* FIXME: Free other resources too. */
+- if (host) {
+- if (host->iclk && !IS_ERR(host->iclk))
+- clk_put(host->iclk);
+- if (host->fclk && !IS_ERR(host->fclk))
+- clk_put(host->fclk);
+- mmc_free_host(host->mmc);
+- }
+-err_free_power_gpio:
+- if (host->power_pin >= 0)
+- omap_free_gpio(host->power_pin);
++err_plat_cleanup:
++ if (pdata->cleanup)
++ pdata->cleanup(&pdev->dev);
++err_free_irq:
++ free_irq(host->irq, host);
+ err_free_fclk:
+ clk_put(host->fclk);
+ err_free_iclk:
+@@ -1169,7 +1511,7 @@ err_free_iclk:
+ clk_put(host->iclk);
+ }
+ err_free_mmc_host:
+- mmc_free_host(host->mmc);
++ kfree(host);
+ err_free_mem_region:
+ release_mem_region(res->start, res->end - res->start + 1);
+ return ret;
+@@ -1178,25 +1520,18 @@ err_free_mem_region:
+ static int mmc_omap_remove(struct platform_device *pdev)
+ {
+ struct mmc_omap_host *host = platform_get_drvdata(pdev);
++ int i;
+
+ platform_set_drvdata(pdev, NULL);
+
+ BUG_ON(host == NULL);
+
+- mmc_remove_host(host->mmc);
+- free_irq(host->irq, host);
++ for (i = 0; i < host->nr_slots; i++)
++ mmc_omap_remove_slot(host->slots[i]);
++
++ if (host->pdata->cleanup)
++ host->pdata->cleanup(&pdev->dev);
+
+- if (host->power_pin >= 0)
+- omap_free_gpio(host->power_pin);
+- if (host->switch_pin >= 0) {
+- device_remove_file(&pdev->dev, &dev_attr_enable_poll);
+- device_remove_file(&pdev->dev, &dev_attr_cover_switch);
+- free_irq(OMAP_GPIO_IRQ(host->switch_pin), host);
+- omap_free_gpio(host->switch_pin);
+- host->switch_pin = -1;
+- del_timer_sync(&host->switch_timer);
+- flush_scheduled_work();
+- }
+ if (host->iclk && !IS_ERR(host->iclk))
+ clk_put(host->iclk);
+ if (host->fclk && !IS_ERR(host->fclk))
+@@ -1205,7 +1540,7 @@ static int mmc_omap_remove(struct platform_device *pdev)
+ release_mem_region(pdev->resource[0].start,
+ pdev->resource[0].end - pdev->resource[0].start + 1);
+
+- mmc_free_host(host->mmc);
++ kfree(host);
+
+ return 0;
+ }
+@@ -1213,35 +1548,47 @@ static int mmc_omap_remove(struct platform_device *pdev)
+ #ifdef CONFIG_PM
+ static int mmc_omap_suspend(struct platform_device *pdev, pm_message_t mesg)
+ {
+- int ret = 0;
++ int i, ret = 0;
+ struct mmc_omap_host *host = platform_get_drvdata(pdev);
+
+- if (host && host->suspended)
++ if (host == NULL || host->suspended)
+ return 0;
+
+- if (host) {
+- ret = mmc_suspend_host(host->mmc, mesg);
+- if (ret == 0)
+- host->suspended = 1;
++ for (i = 0; i < host->nr_slots; i++) {
++ struct mmc_omap_slot *slot;
++
++ slot = host->slots[i];
++ ret = mmc_suspend_host(slot->mmc, mesg);
++ if (ret < 0) {
++ while (--i >= 0) {
++ slot = host->slots[i];
++ mmc_resume_host(slot->mmc);
++ }
++ return ret;
++ }
+ }
+- return ret;
++ host->suspended = 1;
++ return 0;
+ }
+
+ static int mmc_omap_resume(struct platform_device *pdev)
+ {
+- int ret = 0;
++ int i, ret = 0;
+ struct mmc_omap_host *host = platform_get_drvdata(pdev);
+
+- if (host && !host->suspended)
++ if (host == NULL || !host->suspended)
+ return 0;
+
+- if (host) {
+- ret = mmc_resume_host(host->mmc);
+- if (ret == 0)
+- host->suspended = 0;
+- }
++ for (i = 0; i < host->nr_slots; i++) {
++ struct mmc_omap_slot *slot;
++ slot = host->slots[i];
++ ret = mmc_resume_host(slot->mmc);
++ if (ret < 0)
++ return ret;
+
+- return ret;
++ host->suspended = 0;
++ }
++ return 0;
+ }
+ #else
+ #define mmc_omap_suspend NULL
+diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
+index 4b673aa..07c2048 100644
+--- a/drivers/mmc/host/sdhci.c
++++ b/drivers/mmc/host/sdhci.c
+@@ -1,7 +1,7 @@
+ /*
+ * linux/drivers/mmc/host/sdhci.c - Secure Digital Host Controller Interface driver
+ *
+- * Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
++ * Copyright (C) 2005-2008 Pierre Ossman, 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
+@@ -19,6 +19,8 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/scatterlist.h>
+
++#include <linux/leds.h>
++
+ #include <linux/mmc/host.h>
+
+ #include "sdhci.h"
+@@ -30,10 +32,6 @@
+
+ static unsigned int debug_quirks = 0;
+
+-/* For multi controllers in one platform case */
+-static u16 chip_index = 0;
+-static spinlock_t index_lock;
+-
+ /*
+ * Different quirks to handle when the hardware deviates from a strict
+ * interpretation of the SDHCI specification.
+@@ -43,7 +41,7 @@ static spinlock_t index_lock;
+ #define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1<<0)
+ /* Controller has bad caps bits, but really supports DMA */
+ #define SDHCI_QUIRK_FORCE_DMA (1<<1)
+-/* Controller doesn't like some resets when there is no card inserted. */
++/* Controller doesn't like to be reset when there is no card inserted. */
+ #define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2)
+ /* Controller doesn't like clearing the power reg before a change */
+ #define SDHCI_QUIRK_SINGLE_POWER_WRITE (1<<3)
+@@ -71,13 +69,21 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
+ {
+ .vendor = PCI_VENDOR_ID_RICOH,
+ .device = PCI_DEVICE_ID_RICOH_R5C822,
+- .subvendor = PCI_ANY_ID,
++ .subvendor = PCI_VENDOR_ID_SAMSUNG,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = SDHCI_QUIRK_FORCE_DMA |
+ SDHCI_QUIRK_NO_CARD_NO_RESET,
+ },
+
+ {
++ .vendor = PCI_VENDOR_ID_RICOH,
++ .device = PCI_DEVICE_ID_RICOH_R5C822,
++ .subvendor = PCI_ANY_ID,
++ .subdevice = PCI_ANY_ID,
++ .driver_data = SDHCI_QUIRK_FORCE_DMA,
++ },
++
++ {
+ .vendor = PCI_VENDOR_ID_TI,
+ .device = PCI_DEVICE_ID_TI_XX21_XX11_SD,
+ .subvendor = PCI_ANY_ID,
+@@ -256,6 +262,24 @@ static void sdhci_deactivate_led(struct sdhci_host *host)
+ writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
+ }
+
++#ifdef CONFIG_LEDS_CLASS
++static void sdhci_led_control(struct led_classdev *led,
++ enum led_brightness brightness)
++{
++ struct sdhci_host *host = container_of(led, struct sdhci_host, led);
++ unsigned long flags;
++
++ spin_lock_irqsave(&host->lock, flags);
++
++ if (brightness == LED_OFF)
++ sdhci_deactivate_led(host);
++ else
++ sdhci_activate_led(host);
++
++ spin_unlock_irqrestore(&host->lock, flags);
++}
++#endif
++
+ /*****************************************************************************\
+ * *
+ * Core functions *
+@@ -773,7 +797,9 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+
+ WARN_ON(host->mrq != NULL);
+
++#ifndef CONFIG_LEDS_CLASS
+ sdhci_activate_led(host);
++#endif
+
+ host->mrq = mrq;
+
+@@ -965,7 +991,9 @@ static void sdhci_tasklet_finish(unsigned long param)
+ host->cmd = NULL;
+ host->data = NULL;
+
++#ifndef CONFIG_LEDS_CLASS
+ sdhci_deactivate_led(host);
++#endif
+
+ mmiowb();
+ spin_unlock_irqrestore(&host->lock, flags);
+@@ -1105,7 +1133,8 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
+ goto out;
+ }
+
+- DBG("*** %s got interrupt: 0x%08x\n", host->slot_descr, intmask);
++ DBG("*** %s got interrupt: 0x%08x\n",
++ mmc_hostname(host->mmc), intmask);
+
+ if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
+ writel(intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE),
+@@ -1235,7 +1264,7 @@ static int sdhci_resume (struct pci_dev *pdev)
+ if (chip->hosts[i]->flags & SDHCI_USE_DMA)
+ pci_set_master(pdev);
+ ret = request_irq(chip->hosts[i]->irq, sdhci_irq,
+- IRQF_SHARED, chip->hosts[i]->slot_descr,
++ IRQF_SHARED, mmc_hostname(chip->hosts[i]->mmc),
+ chip->hosts[i]);
+ if (ret)
+ return ret;
+@@ -1324,9 +1353,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
+
+ DBG("slot %d at 0x%08lx, irq %d\n", slot, host->addr, host->irq);
+
+- snprintf(host->slot_descr, 20, "sdhc%d:slot%d", chip->index, slot);
+-
+- ret = pci_request_region(pdev, host->bar, host->slot_descr);
++ ret = pci_request_region(pdev, host->bar, mmc_hostname(mmc));
+ if (ret)
+ goto free;
+
+@@ -1343,7 +1370,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
+ version = (version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT;
+ if (version > 1) {
+ printk(KERN_ERR "%s: Unknown controller version (%d). "
+- "You may experience problems.\n", host->slot_descr,
++ "You may experience problems.\n", mmc_hostname(mmc),
+ version);
+ }
+
+@@ -1366,13 +1393,13 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
+ (host->flags & SDHCI_USE_DMA)) {
+ printk(KERN_WARNING "%s: Will use DMA "
+ "mode even though HW doesn't fully "
+- "claim to support it.\n", host->slot_descr);
++ "claim to support it.\n", mmc_hostname(mmc));
+ }
+
+ if (host->flags & SDHCI_USE_DMA) {
+ if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+ printk(KERN_WARNING "%s: No suitable DMA available. "
+- "Falling back to PIO.\n", host->slot_descr);
++ "Falling back to PIO.\n", mmc_hostname(mmc));
+ host->flags &= ~SDHCI_USE_DMA;
+ }
+ }
+@@ -1386,7 +1413,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
+ (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
+ if (host->max_clk == 0) {
+ printk(KERN_ERR "%s: Hardware doesn't specify base clock "
+- "frequency.\n", host->slot_descr);
++ "frequency.\n", mmc_hostname(mmc));
+ ret = -ENODEV;
+ goto unmap;
+ }
+@@ -1396,7 +1423,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
+ (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT;
+ if (host->timeout_clk == 0) {
+ printk(KERN_ERR "%s: Hardware doesn't specify timeout clock "
+- "frequency.\n", host->slot_descr);
++ "frequency.\n", mmc_hostname(mmc));
+ ret = -ENODEV;
+ goto unmap;
+ }
+@@ -1424,7 +1451,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
+
+ if (mmc->ocr_avail == 0) {
+ printk(KERN_ERR "%s: Hardware doesn't report any "
+- "support voltages.\n", host->slot_descr);
++ "support voltages.\n", mmc_hostname(mmc));
+ ret = -ENODEV;
+ goto unmap;
+ }
+@@ -1458,8 +1485,8 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
+ */
+ mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT;
+ if (mmc->max_blk_size >= 3) {
+- printk(KERN_WARNING "%s: Invalid maximum block size, assuming 512\n",
+- host->slot_descr);
++ printk(KERN_WARNING "%s: Invalid maximum block size, "
++ "assuming 512 bytes\n", mmc_hostname(mmc));
+ mmc->max_blk_size = 512;
+ } else
+ mmc->max_blk_size = 512 << mmc->max_blk_size;
+@@ -1480,7 +1507,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
+ setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host);
+
+ ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
+- host->slot_descr, host);
++ mmc_hostname(mmc), host);
+ if (ret)
+ goto untasklet;
+
+@@ -1490,16 +1517,32 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
+ sdhci_dumpregs(host);
+ #endif
+
++#ifdef CONFIG_LEDS_CLASS
++ host->led.name = mmc_hostname(mmc);
++ host->led.brightness = LED_OFF;
++ host->led.default_trigger = mmc_hostname(mmc);
++ host->led.brightness_set = sdhci_led_control;
++
++ ret = led_classdev_register(&pdev->dev, &host->led);
++ if (ret)
++ goto reset;
++#endif
++
+ mmiowb();
+
+ mmc_add_host(mmc);
+
+- printk(KERN_INFO "%s: SDHCI at 0x%08lx irq %d %s\n", mmc_hostname(mmc),
+- host->addr, host->irq,
++ printk(KERN_INFO "%s: SDHCI at 0x%08lx irq %d %s\n",
++ mmc_hostname(mmc), host->addr, host->irq,
+ (host->flags & SDHCI_USE_DMA)?"DMA":"PIO");
+
+ return 0;
+
++#ifdef CONFIG_LEDS_CLASS
++reset:
++ sdhci_reset(host, SDHCI_RESET_ALL);
++ free_irq(host->irq, host);
++#endif
+ untasklet:
+ tasklet_kill(&host->card_tasklet);
+ tasklet_kill(&host->finish_tasklet);
+@@ -1527,6 +1570,10 @@ static void sdhci_remove_slot(struct pci_dev *pdev, int slot)
+
+ mmc_remove_host(mmc);
+
++#ifdef CONFIG_LEDS_CLASS
++ led_classdev_unregister(&host->led);
++#endif
++
+ sdhci_reset(host, SDHCI_RESET_ALL);
+
+ free_irq(host->irq, host);
+@@ -1589,11 +1636,6 @@ static int __devinit sdhci_probe(struct pci_dev *pdev,
+ chip->num_slots = slots;
+ pci_set_drvdata(pdev, chip);
+
+- /* Add for multi controller case */
+- spin_lock(&index_lock);
+- chip->index = chip_index++;
+- spin_unlock(&index_lock);
+-
+ for (i = 0;i < slots;i++) {
+ ret = sdhci_probe_slot(pdev, i);
+ if (ret) {
+@@ -1654,8 +1696,6 @@ static int __init sdhci_drv_init(void)
+ ": Secure Digital Host Controller Interface driver\n");
+ printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
+
+- spin_lock_init(&index_lock);
+-
+ return pci_register_driver(&sdhci_driver);
+ }
+
+diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
+index d5a38f1..7fb02e1 100644
+--- a/drivers/mmc/host/sdhci.h
++++ b/drivers/mmc/host/sdhci.h
+@@ -1,7 +1,7 @@
+ /*
+ * linux/drivers/mmc/host/sdhci.h - Secure Digital Host Controller Interface driver
+ *
+- * Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
++ * Copyright (C) 2005-2008 Pierre Ossman, 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
+@@ -168,6 +168,10 @@ struct sdhci_host {
+ struct sdhci_chip *chip;
+ struct mmc_host *mmc; /* MMC structure */
+
++#ifdef CONFIG_LEDS_CLASS
++ struct led_classdev led; /* LED control */
++#endif
++
+ spinlock_t lock; /* Mutex */
+
+ int flags; /* Host attributes */
+@@ -190,8 +194,6 @@ struct sdhci_host {
+ int offset; /* Offset into current sg */
+ int remain; /* Bytes left in current */
+
+- char slot_descr[20]; /* Name for reservations */
+-
+ int irq; /* Device IRQ */
+ int bar; /* PCI BAR index */
+ unsigned long addr; /* Bus address */
+@@ -208,7 +210,6 @@ struct sdhci_chip {
+
+ unsigned long quirks;
+
+- int index; /* Index for chip0, chip1 ...*/
+ int num_slots; /* Slots on controller */
+ struct sdhci_host *hosts[0]; /* Pointers to hosts */
+ };
+diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
+index e850334..eed06d0 100644
+--- a/drivers/mtd/Kconfig
++++ b/drivers/mtd/Kconfig
+@@ -158,6 +158,12 @@ config MTD_OF_PARTS
+ the partition map from the children of the flash node,
+ as described in Documentation/powerpc/booting-without-of.txt.
+
++config MTD_AR7_PARTS
++ tristate "TI AR7 partitioning support"
++ depends on MTD_PARTITIONS
++ ---help---
++ TI AR7 partitioning support
++
+ comment "User Modules And Translation Layers"
+
+ config MTD_CHAR
+diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
+index 538e33d..4b77335 100644
+--- a/drivers/mtd/Makefile
++++ b/drivers/mtd/Makefile
+@@ -11,6 +11,7 @@ obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o
+ obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
+ obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
+ obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
++obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o
+ obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o
+
+ # 'Users' - code which presents functionality to userspace.
+diff --git a/drivers/mtd/ar7part.c b/drivers/mtd/ar7part.c
+new file mode 100644
+index 0000000..ecf170b
+--- /dev/null
++++ b/drivers/mtd/ar7part.c
+@@ -0,0 +1,151 @@
++/*
++ * Copyright © 2007 Eugene Konev <ejka at openwrt.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ * TI AR7 flash partition table.
++ * Based on ar7 map by Felix Fietkau <nbd at openwrt.org>
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/slab.h>
++
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#include <linux/bootmem.h>
++#include <linux/magic.h>
++
++#define AR7_PARTS 4
++#define ROOT_OFFSET 0xe0000
++
++#define LOADER_MAGIC1 le32_to_cpu(0xfeedfa42)
++#define LOADER_MAGIC2 le32_to_cpu(0xfeed1281)
++
++#ifndef SQUASHFS_MAGIC
++#define SQUASHFS_MAGIC 0x73717368
++#endif
++
++struct ar7_bin_rec {
++ unsigned int checksum;
++ unsigned int length;
++ unsigned int address;
++};
++
++static struct mtd_partition ar7_parts[AR7_PARTS];
++
++static int create_mtd_partitions(struct mtd_info *master,
++ struct mtd_partition **pparts,
++ unsigned long origin)
++{
++ struct ar7_bin_rec header;
++ unsigned int offset;
++ size_t len;
++ unsigned int pre_size = master->erasesize, post_size = 0;
++ unsigned int root_offset = ROOT_OFFSET;
++
++ int retries = 10;
++
++ ar7_parts[0].name = "loader";
++ ar7_parts[0].offset = 0;
++ ar7_parts[0].size = master->erasesize;
++ ar7_parts[0].mask_flags = MTD_WRITEABLE;
++
++ ar7_parts[1].name = "config";
++ ar7_parts[1].offset = 0;
++ ar7_parts[1].size = master->erasesize;
++ ar7_parts[1].mask_flags = 0;
++
++ do { /* Try 10 blocks starting from master->erasesize */
++ offset = pre_size;
++ master->read(master, offset,
++ sizeof(header), &len, (uint8_t *)&header);
++ if (!strncmp((char *)&header, "TIENV0.8", 8))
++ ar7_parts[1].offset = pre_size;
++ if (header.checksum == LOADER_MAGIC1)
++ break;
++ if (header.checksum == LOADER_MAGIC2)
++ break;
++ pre_size += master->erasesize;
++ } while (retries--);
++
++ pre_size = offset;
++
++ if (!ar7_parts[1].offset) {
++ ar7_parts[1].offset = master->size - master->erasesize;
++ post_size = master->erasesize;
++ }
++
++ switch (header.checksum) {
++ case LOADER_MAGIC1:
++ while (header.length) {
++ offset += sizeof(header) + header.length;
++ master->read(master, offset, sizeof(header),
++ &len, (uint8_t *)&header);
++ }
++ root_offset = offset + sizeof(header) + 4;
++ break;
++ case LOADER_MAGIC2:
++ while (header.length) {
++ offset += sizeof(header) + header.length;
++ master->read(master, offset, sizeof(header),
++ &len, (uint8_t *)&header);
++ }
++ root_offset = offset + sizeof(header) + 4 + 0xff;
++ root_offset &= ~(uint32_t)0xff;
++ break;
++ default:
++ printk(KERN_WARNING "Unknown magic: %08x\n", header.checksum);
++ break;
++ }
++
++ master->read(master, root_offset,
++ sizeof(header), &len, (u8 *)&header);
++ if (header.checksum != SQUASHFS_MAGIC) {
++ root_offset += master->erasesize - 1;
++ root_offset &= ~(master->erasesize - 1);
++ }
++
++ ar7_parts[2].name = "linux";
++ ar7_parts[2].offset = pre_size;
++ ar7_parts[2].size = master->size - pre_size - post_size;
++ ar7_parts[2].mask_flags = 0;
++
++ ar7_parts[3].name = "rootfs";
++ ar7_parts[3].offset = root_offset;
++ ar7_parts[3].size = master->size - root_offset - post_size;
++ ar7_parts[3].mask_flags = 0;
++
++ *pparts = ar7_parts;
++ return AR7_PARTS;
++}
++
++static struct mtd_part_parser ar7_parser = {
++ .owner = THIS_MODULE,
++ .parse_fn = create_mtd_partitions,
++ .name = "ar7part",
++};
++
++static int __init ar7_parser_init(void)
++{
++ return register_mtd_parser(&ar7_parser);
++}
++
++module_init(ar7_parser_init);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR( "Felix Fietkau <nbd at openwrt.org>, "
++ "Eugene Konev <ejka at openwrt.org>");
++MODULE_DESCRIPTION("MTD partitioning for TI AR7");
+diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
+index 0080452..e812df6 100644
+--- a/drivers/mtd/chips/cfi_cmdset_0001.c
++++ b/drivers/mtd/chips/cfi_cmdset_0001.c
+@@ -384,7 +384,7 @@ read_pri_intelext(struct map_info *map, __u16 adr)
+ if (extp_size > 4096) {
+ printk(KERN_ERR
+ "%s: cfi_pri_intelext is too fat\n",
+- __FUNCTION__);
++ __func__);
+ return NULL;
+ }
+ goto again;
+@@ -619,6 +619,9 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
+ sizeof(struct cfi_intelext_blockinfo);
+ }
+
++ if (!numparts)
++ numparts = 1;
++
+ /* Programming Region info */
+ if (extp->MinorVersion >= '4') {
+ struct cfi_intelext_programming_regioninfo *prinfo;
+@@ -641,7 +644,7 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
+ if ((1 << partshift) < mtd->erasesize) {
+ printk( KERN_ERR
+ "%s: bad number of hw partitions (%d)\n",
+- __FUNCTION__, numparts);
++ __func__, numparts);
+ return -EINVAL;
+ }
+
+@@ -1071,10 +1074,10 @@ static int __xipram xip_wait_for_operation(
+ chip->state = newstate;
+ map_write(map, CMD(0xff), adr);
+ (void) map_read(map, adr);
+- asm volatile (".rep 8; nop; .endr");
++ xip_iprefetch();
+ local_irq_enable();
+ spin_unlock(chip->mutex);
+- asm volatile (".rep 8; nop; .endr");
++ xip_iprefetch();
+ cond_resched();
+
+ /*
+@@ -2013,7 +2016,7 @@ static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
+
+ #ifdef DEBUG_LOCK_BITS
+ printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
+- __FUNCTION__, ofs, len);
++ __func__, ofs, len);
+ cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
+ ofs, len, NULL);
+ #endif
+@@ -2023,7 +2026,7 @@ static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
+
+ #ifdef DEBUG_LOCK_BITS
+ printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
+- __FUNCTION__, ret);
++ __func__, ret);
+ cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
+ ofs, len, NULL);
+ #endif
+@@ -2037,7 +2040,7 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+
+ #ifdef DEBUG_LOCK_BITS
+ printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
+- __FUNCTION__, ofs, len);
++ __func__, ofs, len);
+ cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
+ ofs, len, NULL);
+ #endif
+@@ -2047,7 +2050,7 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+
+ #ifdef DEBUG_LOCK_BITS
+ printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
+- __FUNCTION__, ret);
++ __func__, ret);
+ cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
+ ofs, len, NULL);
+ #endif
+diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
+index 458d477..f7fcc63 100644
+--- a/drivers/mtd/chips/cfi_cmdset_0002.c
++++ b/drivers/mtd/chips/cfi_cmdset_0002.c
+@@ -220,6 +220,28 @@ static void fixup_use_atmel_lock(struct mtd_info *mtd, void *param)
+ mtd->flags |= MTD_POWERUP_LOCK;
+ }
+
++static void fixup_s29gl064n_sectors(struct mtd_info *mtd, void *param)
++{
++ struct map_info *map = mtd->priv;
++ struct cfi_private *cfi = map->fldrv_priv;
++
++ if ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) == 0x003f) {
++ cfi->cfiq->EraseRegionInfo[0] |= 0x0040;
++ pr_warning("%s: Bad S29GL064N CFI data, adjust from 64 to 128 sectors\n", mtd->name);
++ }
++}
++
++static void fixup_s29gl032n_sectors(struct mtd_info *mtd, void *param)
++{
++ struct map_info *map = mtd->priv;
++ struct cfi_private *cfi = map->fldrv_priv;
++
++ if ((cfi->cfiq->EraseRegionInfo[1] & 0xffff) == 0x007e) {
++ cfi->cfiq->EraseRegionInfo[1] &= ~0x0040;
++ pr_warning("%s: Bad S29GL032N CFI data, adjust from 127 to 63 sectors\n", mtd->name);
++ }
++}
++
+ static struct cfi_fixup cfi_fixup_table[] = {
+ { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL },
+ #ifdef AMD_BOOTLOC_BUG
+@@ -231,6 +253,10 @@ static struct cfi_fixup cfi_fixup_table[] = {
+ { CFI_MFR_AMD, 0x0056, fixup_use_secsi, NULL, },
+ { CFI_MFR_AMD, 0x005C, fixup_use_secsi, NULL, },
+ { CFI_MFR_AMD, 0x005F, fixup_use_secsi, NULL, },
++ { CFI_MFR_AMD, 0x0c01, fixup_s29gl064n_sectors, NULL, },
++ { CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors, NULL, },
++ { CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors, NULL, },
++ { CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors, NULL, },
+ #if !FORCE_WORD_WRITE
+ { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, },
+ #endif
+@@ -723,10 +749,10 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip,
+ chip->erase_suspended = 1;
+ map_write(map, CMD(0xf0), adr);
+ (void) map_read(map, adr);
+- asm volatile (".rep 8; nop; .endr");
++ xip_iprefetch();
+ local_irq_enable();
+ spin_unlock(chip->mutex);
+- asm volatile (".rep 8; nop; .endr");
++ xip_iprefetch();
+ cond_resched();
+
+ /*
+diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c
+index 492e2ab..1b720cc 100644
+--- a/drivers/mtd/chips/cfi_cmdset_0020.c
++++ b/drivers/mtd/chips/cfi_cmdset_0020.c
+@@ -445,7 +445,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
+ retry:
+
+ #ifdef DEBUG_CFI_FEATURES
+- printk("%s: chip->state[%d]\n", __FUNCTION__, chip->state);
++ printk("%s: chip->state[%d]\n", __func__, chip->state);
+ #endif
+ spin_lock_bh(chip->mutex);
+
+@@ -463,7 +463,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
+ map_write(map, CMD(0x70), cmd_adr);
+ chip->state = FL_STATUS;
+ #ifdef DEBUG_CFI_FEATURES
+- printk("%s: 1 status[%x]\n", __FUNCTION__, map_read(map, cmd_adr));
++ printk("%s: 1 status[%x]\n", __func__, map_read(map, cmd_adr));
+ #endif
+
+ case FL_STATUS:
+@@ -591,7 +591,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
+ /* check for errors: 'lock bit', 'VPP', 'dead cell'/'unerased cell' or 'incorrect cmd' -- saw */
+ if (map_word_bitsset(map, status, CMD(0x3a))) {
+ #ifdef DEBUG_CFI_FEATURES
+- printk("%s: 2 status[%lx]\n", __FUNCTION__, status.x[0]);
++ printk("%s: 2 status[%lx]\n", __func__, status.x[0]);
+ #endif
+ /* clear status */
+ map_write(map, CMD(0x50), cmd_adr);
+@@ -625,9 +625,9 @@ static int cfi_staa_write_buffers (struct mtd_info *mtd, loff_t to,
+ ofs = to - (chipnum << cfi->chipshift);
+
+ #ifdef DEBUG_CFI_FEATURES
+- printk("%s: map_bankwidth(map)[%x]\n", __FUNCTION__, map_bankwidth(map));
+- printk("%s: chipnum[%x] wbufsize[%x]\n", __FUNCTION__, chipnum, wbufsize);
+- printk("%s: ofs[%x] len[%x]\n", __FUNCTION__, ofs, len);
++ printk("%s: map_bankwidth(map)[%x]\n", __func__, map_bankwidth(map));
++ printk("%s: chipnum[%x] wbufsize[%x]\n", __func__, chipnum, wbufsize);
++ printk("%s: ofs[%x] len[%x]\n", __func__, ofs, len);
+ #endif
+
+ /* Write buffer is worth it only if more than one word to write... */
+@@ -893,7 +893,8 @@ retry:
+ return ret;
+ }
+
+-int cfi_staa_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
++static int cfi_staa_erase_varsize(struct mtd_info *mtd,
++ struct erase_info *instr)
+ { struct map_info *map = mtd->priv;
+ struct cfi_private *cfi = map->fldrv_priv;
+ unsigned long adr, len;
+diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c
+index f651b6e..a4463a9 100644
+--- a/drivers/mtd/chips/cfi_probe.c
++++ b/drivers/mtd/chips/cfi_probe.c
+@@ -39,7 +39,7 @@ struct mtd_info *cfi_probe(struct map_info *map);
+ #define xip_allowed(base, map) \
+ do { \
+ (void) map_read(map, base); \
+- asm volatile (".rep 8; nop; .endr"); \
++ xip_iprefetch(); \
+ local_irq_enable(); \
+ } while (0)
+
+@@ -232,6 +232,11 @@ static int __xipram cfi_chip_setup(struct map_info *map,
+ cfi->mfr = cfi_read_query16(map, base);
+ cfi->id = cfi_read_query16(map, base + ofs_factor);
+
++ /* Get AMD/Spansion extended JEDEC ID */
++ if (cfi->mfr == CFI_MFR_AMD && (cfi->id & 0xff) == 0x7e)
++ cfi->id = cfi_read_query(map, base + 0xe * ofs_factor) << 8 |
++ cfi_read_query(map, base + 0xf * ofs_factor);
++
+ /* Put it back into Read Mode */
+ cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
+ /* ... even if it's an Intel chip */
+diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c
+index 2e51496..72e0022 100644
+--- a/drivers/mtd/chips/cfi_util.c
++++ b/drivers/mtd/chips/cfi_util.c
+@@ -65,7 +65,7 @@ __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* n
+
+ #ifdef CONFIG_MTD_XIP
+ (void) map_read(map, base);
+- asm volatile (".rep 8; nop; .endr");
++ xip_iprefetch();
+ local_irq_enable();
+ #endif
+
+diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
+index 4be51a8..aa07575 100644
+--- a/drivers/mtd/chips/jedec_probe.c
++++ b/drivers/mtd/chips/jedec_probe.c
+@@ -132,6 +132,8 @@
+ #define M29F800AB 0x0058
+ #define M29W800DT 0x00D7
+ #define M29W800DB 0x005B
++#define M29W400DT 0x00EE
++#define M29W400DB 0x00EF
+ #define M29W160DT 0x22C4
+ #define M29W160DB 0x2249
+ #define M29W040B 0x00E3
+@@ -160,6 +162,7 @@
+ #define SST49LF030A 0x001C
+ #define SST49LF040A 0x0051
+ #define SST49LF080A 0x005B
++#define SST36VF3203 0x7354
+
+ /* Toshiba */
+ #define TC58FVT160 0x00C2
+@@ -1113,7 +1116,7 @@ static const struct amd_flash_info jedec_table[] = {
+ .regions = {
+ ERASEINFO(0x10000,8),
+ }
+- }, {
++ }, {
+ .mfr_id = MANUFACTURER_MACRONIX,
+ .dev_id = MX29F016,
+ .name = "Macronix MX29F016",
+@@ -1125,7 +1128,7 @@ static const struct amd_flash_info jedec_table[] = {
+ .regions = {
+ ERASEINFO(0x10000,32),
+ }
+- }, {
++ }, {
+ .mfr_id = MANUFACTURER_MACRONIX,
+ .dev_id = MX29F004T,
+ .name = "Macronix MX29F004T",
+@@ -1140,7 +1143,7 @@ static const struct amd_flash_info jedec_table[] = {
+ ERASEINFO(0x02000,2),
+ ERASEINFO(0x04000,1),
+ }
+- }, {
++ }, {
+ .mfr_id = MANUFACTURER_MACRONIX,
+ .dev_id = MX29F004B,
+ .name = "Macronix MX29F004B",
+@@ -1218,7 +1221,7 @@ static const struct amd_flash_info jedec_table[] = {
+ .regions = {
+ ERASEINFO(0x40000,16),
+ }
+- }, {
++ }, {
+ .mfr_id = MANUFACTURER_SST,
+ .dev_id = SST39LF512,
+ .name = "SST 39LF512",
+@@ -1230,7 +1233,7 @@ static const struct amd_flash_info jedec_table[] = {
+ .regions = {
+ ERASEINFO(0x01000,16),
+ }
+- }, {
++ }, {
+ .mfr_id = MANUFACTURER_SST,
+ .dev_id = SST39LF010,
+ .name = "SST 39LF010",
+@@ -1242,7 +1245,7 @@ static const struct amd_flash_info jedec_table[] = {
+ .regions = {
+ ERASEINFO(0x01000,32),
+ }
+- }, {
++ }, {
+ .mfr_id = MANUFACTURER_SST,
+ .dev_id = SST29EE020,
+ .name = "SST 29EE020",
+@@ -1276,7 +1279,7 @@ static const struct amd_flash_info jedec_table[] = {
+ .regions = {
+ ERASEINFO(0x01000,64),
+ }
+- }, {
++ }, {
+ .mfr_id = MANUFACTURER_SST,
+ .dev_id = SST39LF040,
+ .name = "SST 39LF040",
+@@ -1288,7 +1291,7 @@ static const struct amd_flash_info jedec_table[] = {
+ .regions = {
+ ERASEINFO(0x01000,128),
+ }
+- }, {
++ }, {
+ .mfr_id = MANUFACTURER_SST,
+ .dev_id = SST39SF010A,
+ .name = "SST 39SF010A",
+@@ -1300,7 +1303,7 @@ static const struct amd_flash_info jedec_table[] = {
+ .regions = {
+ ERASEINFO(0x01000,32),
+ }
+- }, {
++ }, {
+ .mfr_id = MANUFACTURER_SST,
+ .dev_id = SST39SF020A,
+ .name = "SST 39SF020A",
+@@ -1412,6 +1415,18 @@ static const struct amd_flash_info jedec_table[] = {
+ ERASEINFO(0x1000,256)
+ }
+ }, {
++ .mfr_id = MANUFACTURER_SST,
++ .dev_id = SST36VF3203,
++ .name = "SST 36VF3203",
++ .devtypes = CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8,
++ .uaddr = MTD_UADDR_0x0AAA_0x0555,
++ .dev_size = SIZE_4MiB,
++ .cmd_set = P_ID_AMD_STD,
++ .nr_regions = 1,
++ .regions = {
++ ERASEINFO(0x10000,64),
++ }
++ }, {
+ .mfr_id = MANUFACTURER_ST,
+ .dev_id = M29F800AB,
+ .name = "ST M29F800AB",
+@@ -1426,7 +1441,7 @@ static const struct amd_flash_info jedec_table[] = {
+ ERASEINFO(0x08000,1),
+ ERASEINFO(0x10000,15),
+ }
+- }, {
++ }, {
+ .mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */
+ .dev_id = M29W800DT,
+ .name = "ST M29W800DT",
+@@ -1456,6 +1471,36 @@ static const struct amd_flash_info jedec_table[] = {
+ ERASEINFO(0x08000,1),
+ ERASEINFO(0x10000,15)
+ }
++ }, {
++ .mfr_id = MANUFACTURER_ST,
++ .dev_id = M29W400DT,
++ .name = "ST M29W400DT",
++ .devtypes = CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8,
++ .uaddr = MTD_UADDR_0x0AAA_0x0555,
++ .dev_size = SIZE_512KiB,
++ .cmd_set = P_ID_AMD_STD,
++ .nr_regions = 4,
++ .regions = {
++ ERASEINFO(0x04000,7),
++ ERASEINFO(0x02000,1),
++ ERASEINFO(0x08000,2),
++ ERASEINFO(0x10000,1)
++ }
++ }, {
++ .mfr_id = MANUFACTURER_ST,
++ .dev_id = M29W400DB,
++ .name = "ST M29W400DB",
++ .devtypes = CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8,
++ .uaddr = MTD_UADDR_0x0AAA_0x0555,
++ .dev_size = SIZE_512KiB,
++ .cmd_set = P_ID_AMD_STD,
++ .nr_regions = 4,
++ .regions = {
++ ERASEINFO(0x04000,1),
++ ERASEINFO(0x02000,2),
++ ERASEINFO(0x08000,1),
++ ERASEINFO(0x10000,7)
++ }
+ }, {
+ .mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */
+ .dev_id = M29W160DT,
+@@ -1486,7 +1531,7 @@ static const struct amd_flash_info jedec_table[] = {
+ ERASEINFO(0x08000,1),
+ ERASEINFO(0x10000,31)
+ }
+- }, {
++ }, {
+ .mfr_id = MANUFACTURER_ST,
+ .dev_id = M29W040B,
+ .name = "ST M29W040B",
+@@ -1498,7 +1543,7 @@ static const struct amd_flash_info jedec_table[] = {
+ .regions = {
+ ERASEINFO(0x10000,8),
+ }
+- }, {
++ }, {
+ .mfr_id = MANUFACTURER_ST,
+ .dev_id = M50FW040,
+ .name = "ST M50FW040",
+@@ -1510,7 +1555,7 @@ static const struct amd_flash_info jedec_table[] = {
+ .regions = {
+ ERASEINFO(0x10000,8),
+ }
+- }, {
++ }, {
+ .mfr_id = MANUFACTURER_ST,
+ .dev_id = M50FW080,
+ .name = "ST M50FW080",
+@@ -1522,7 +1567,7 @@ static const struct amd_flash_info jedec_table[] = {
+ .regions = {
+ ERASEINFO(0x10000,16),
+ }
+- }, {
++ }, {
+ .mfr_id = MANUFACTURER_ST,
+ .dev_id = M50FW016,
+ .name = "ST M50FW016",
+diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c
+index b44292a..e472a0e 100644
+--- a/drivers/mtd/cmdlinepart.c
++++ b/drivers/mtd/cmdlinepart.c
+@@ -119,7 +119,8 @@ static struct mtd_partition * newpart(char *s,
+ char *p;
+
+ name = ++s;
+- if ((p = strchr(name, delim)) == 0)
++ p = strchr(name, delim);
++ if (!p)
+ {
+ printk(KERN_ERR ERRP "no closing %c found in partition name\n", delim);
+ return NULL;
+@@ -159,9 +160,10 @@ static struct mtd_partition * newpart(char *s,
+ return NULL;
+ }
+ /* more partitions follow, parse them */
+- if ((parts = newpart(s + 1, &s, num_parts,
+- this_part + 1, &extra_mem, extra_mem_size)) == 0)
+- return NULL;
++ parts = newpart(s + 1, &s, num_parts, this_part + 1,
++ &extra_mem, extra_mem_size);
++ if (!parts)
++ return NULL;
+ }
+ else
+ { /* this is the last partition: allocate space for all */
+@@ -308,9 +310,6 @@ static int parse_cmdline_partitions(struct mtd_info *master,
+ struct cmdline_mtd_partition *part;
+ char *mtd_id = master->name;
+
+- if(!cmdline)
+- return -EINVAL;
+-
+ /* parse command line */
+ if (!cmdline_parsed)
+ mtdpart_setup_real(cmdline);
+@@ -341,7 +340,7 @@ static int parse_cmdline_partitions(struct mtd_info *master,
+ return part->num_parts;
+ }
+ }
+- return -EINVAL;
++ return 0;
+ }
+
+
+diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
+index 811d56f..35ed110 100644
+--- a/drivers/mtd/devices/Kconfig
++++ b/drivers/mtd/devices/Kconfig
+@@ -77,6 +77,13 @@ config MTD_M25P80
+ if you want to specify device partitioning or to use a device which
+ doesn't support the JEDEC ID instruction.
+
++config M25PXX_USE_FAST_READ
++ bool "Use FAST_READ OPCode allowing SPI CLK <= 50MHz"
++ depends on MTD_M25P80
++ default y
++ help
++ This option enables FAST_READ access supported by ST M25Pxx.
++
+ config MTD_SLRAM
+ tristate "Uncached system RAM"
+ help
+diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
+index ad1880c..519d942 100644
+--- a/drivers/mtd/devices/block2mtd.c
++++ b/drivers/mtd/devices/block2mtd.c
+@@ -305,7 +305,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
+ }
+ list_add(&dev->list, &blkmtd_device_list);
+ INFO("mtd%d: [%s] erase_size = %dKiB [%d]", dev->mtd.index,
+- dev->mtd.name + strlen("blkmtd: "),
++ dev->mtd.name + strlen("block2mtd: "),
+ dev->mtd.erasesize >> 10, dev->mtd.erasesize);
+ return dev;
+
+@@ -366,9 +366,9 @@ static inline void kill_final_newline(char *str)
+ }
+
+
+-#define parse_err(fmt, args...) do { \
+- ERROR("block2mtd: " fmt "\n", ## args); \
+- return 0; \
++#define parse_err(fmt, args...) do { \
++ ERROR(fmt, ## args); \
++ return 0; \
+ } while (0)
+
+ #ifndef MODULE
+@@ -473,7 +473,7 @@ static void __devexit block2mtd_exit(void)
+ block2mtd_sync(&dev->mtd);
+ del_mtd_device(&dev->mtd);
+ INFO("mtd%d: [%s] removed", dev->mtd.index,
+- dev->mtd.name + strlen("blkmtd: "));
++ dev->mtd.name + strlen("block2mtd: "));
+ list_del(&dev->list);
+ block2mtd_free_device(dev);
+ }
+diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c
+index 99fd210..1d324e5 100644
+--- a/drivers/mtd/devices/lart.c
++++ b/drivers/mtd/devices/lart.c
+@@ -275,7 +275,7 @@ static __u8 read8 (__u32 offset)
+ {
+ volatile __u8 *data = (__u8 *) (FLASH_OFFSET + offset);
+ #ifdef LART_DEBUG
+- printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.2x\n",__FUNCTION__,offset,*data);
++ printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.2x\n", __func__, offset, *data);
+ #endif
+ return (*data);
+ }
+@@ -284,7 +284,7 @@ static __u32 read32 (__u32 offset)
+ {
+ volatile __u32 *data = (__u32 *) (FLASH_OFFSET + offset);
+ #ifdef LART_DEBUG
+- printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.8x\n",__FUNCTION__,offset,*data);
++ printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.8x\n", __func__, offset, *data);
+ #endif
+ return (*data);
+ }
+@@ -294,7 +294,7 @@ static void write32 (__u32 x,__u32 offset)
+ volatile __u32 *data = (__u32 *) (FLASH_OFFSET + offset);
+ *data = x;
+ #ifdef LART_DEBUG
+- printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n",__FUNCTION__,offset,*data);
++ printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n", __func__, offset, *data);
+ #endif
+ }
+
+@@ -337,7 +337,7 @@ static inline int erase_block (__u32 offset)
+ __u32 status;
+
+ #ifdef LART_DEBUG
+- printk (KERN_DEBUG "%s(): 0x%.8x\n",__FUNCTION__,offset);
++ printk (KERN_DEBUG "%s(): 0x%.8x\n", __func__, offset);
+ #endif
+
+ /* erase and confirm */
+@@ -371,7 +371,7 @@ static int flash_erase (struct mtd_info *mtd,struct erase_info *instr)
+ int i,first;
+
+ #ifdef LART_DEBUG
+- printk (KERN_DEBUG "%s(addr = 0x%.8x, len = %d)\n",__FUNCTION__,instr->addr,instr->len);
++ printk (KERN_DEBUG "%s(addr = 0x%.8x, len = %d)\n", __func__, instr->addr, instr->len);
+ #endif
+
+ /* sanity checks */
+@@ -442,7 +442,7 @@ static int flash_erase (struct mtd_info *mtd,struct erase_info *instr)
+ static int flash_read (struct mtd_info *mtd,loff_t from,size_t len,size_t *retlen,u_char *buf)
+ {
+ #ifdef LART_DEBUG
+- printk (KERN_DEBUG "%s(from = 0x%.8x, len = %d)\n",__FUNCTION__,(__u32) from,len);
++ printk (KERN_DEBUG "%s(from = 0x%.8x, len = %d)\n", __func__, (__u32)from, len);
+ #endif
+
+ /* sanity checks */
+@@ -488,7 +488,7 @@ static inline int write_dword (__u32 offset,__u32 x)
+ __u32 status;
+
+ #ifdef LART_DEBUG
+- printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n",__FUNCTION__,offset,x);
++ printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n", __func__, offset, x);
+ #endif
+
+ /* setup writing */
+@@ -524,7 +524,7 @@ static int flash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen
+ int i,n;
+
+ #ifdef LART_DEBUG
+- printk (KERN_DEBUG "%s(to = 0x%.8x, len = %d)\n",__FUNCTION__,(__u32) to,len);
++ printk (KERN_DEBUG "%s(to = 0x%.8x, len = %d)\n", __func__, (__u32)to, len);
+ #endif
+
+ *retlen = 0;
+diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
+index 98df5bc..25efd33 100644
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -33,7 +33,7 @@
+ /* Flash opcodes. */
+ #define OPCODE_WREN 0x06 /* Write enable */
+ #define OPCODE_RDSR 0x05 /* Read status register */
+-#define OPCODE_READ 0x03 /* Read data bytes (low frequency) */
++#define OPCODE_NORM_READ 0x03 /* Read data bytes (low frequency) */
+ #define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */
+ #define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */
+ #define OPCODE_BE_4K 0x20 /* Erase 4KiB block */
+@@ -52,7 +52,15 @@
+
+ /* Define max times to check status register before we give up. */
+ #define MAX_READY_WAIT_COUNT 100000
++#define CMD_SIZE 4
+
++#ifdef CONFIG_M25PXX_USE_FAST_READ
++#define OPCODE_READ OPCODE_FAST_READ
++#define FAST_READ_DUMMY_BYTE 1
++#else
++#define OPCODE_READ OPCODE_NORM_READ
++#define FAST_READ_DUMMY_BYTE 0
++#endif
+
+ #ifdef CONFIG_MTD_PARTITIONS
+ #define mtd_has_partitions() (1)
+@@ -68,7 +76,7 @@ struct m25p {
+ struct mtd_info mtd;
+ unsigned partitioned:1;
+ u8 erase_opcode;
+- u8 command[4];
++ u8 command[CMD_SIZE + FAST_READ_DUMMY_BYTE];
+ };
+
+ static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
+@@ -151,7 +159,7 @@ static int wait_till_ready(struct m25p *flash)
+ static int erase_sector(struct m25p *flash, u32 offset)
+ {
+ DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB at 0x%08x\n",
+- flash->spi->dev.bus_id, __FUNCTION__,
++ flash->spi->dev.bus_id, __func__,
+ flash->mtd.erasesize / 1024, offset);
+
+ /* Wait until finished previous write command. */
+@@ -167,7 +175,7 @@ static int erase_sector(struct m25p *flash, u32 offset)
+ flash->command[2] = offset >> 8;
+ flash->command[3] = offset;
+
+- spi_write(flash->spi, flash->command, sizeof(flash->command));
++ spi_write(flash->spi, flash->command, CMD_SIZE);
+
+ return 0;
+ }
+@@ -188,7 +196,7 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
+ u32 addr,len;
+
+ DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n",
+- flash->spi->dev.bus_id, __FUNCTION__, "at",
++ flash->spi->dev.bus_id, __func__, "at",
+ (u32)instr->addr, instr->len);
+
+ /* sanity checks */
+@@ -240,7 +248,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
+ struct spi_message m;
+
+ DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
+- flash->spi->dev.bus_id, __FUNCTION__, "from",
++ flash->spi->dev.bus_id, __func__, "from",
+ (u32)from, len);
+
+ /* sanity checks */
+@@ -253,8 +261,12 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
+ spi_message_init(&m);
+ memset(t, 0, (sizeof t));
+
++ /* NOTE:
++ * OPCODE_FAST_READ (if available) is faster.
++ * Should add 1 byte DUMMY_BYTE.
++ */
+ t[0].tx_buf = flash->command;
+- t[0].len = sizeof(flash->command);
++ t[0].len = CMD_SIZE + FAST_READ_DUMMY_BYTE;
+ spi_message_add_tail(&t[0], &m);
+
+ t[1].rx_buf = buf;
+@@ -287,7 +299,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
+
+ spi_sync(flash->spi, &m);
+
+- *retlen = m.actual_length - sizeof(flash->command);
++ *retlen = m.actual_length - CMD_SIZE - FAST_READ_DUMMY_BYTE;
+
+ mutex_unlock(&flash->lock);
+
+@@ -308,7 +320,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
+ struct spi_message m;
+
+ DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
+- flash->spi->dev.bus_id, __FUNCTION__, "to",
++ flash->spi->dev.bus_id, __func__, "to",
+ (u32)to, len);
+
+ if (retlen)
+@@ -325,7 +337,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
+ memset(t, 0, (sizeof t));
+
+ t[0].tx_buf = flash->command;
+- t[0].len = sizeof(flash->command);
++ t[0].len = CMD_SIZE;
+ spi_message_add_tail(&t[0], &m);
+
+ t[1].tx_buf = buf;
+@@ -354,7 +366,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
+
+ spi_sync(flash->spi, &m);
+
+- *retlen = m.actual_length - sizeof(flash->command);
++ *retlen = m.actual_length - CMD_SIZE;
+ } else {
+ u32 i;
+
+@@ -364,7 +376,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
+ t[1].len = page_size;
+ spi_sync(flash->spi, &m);
+
+- *retlen = m.actual_length - sizeof(flash->command);
++ *retlen = m.actual_length - CMD_SIZE;
+
+ /* write everything in PAGESIZE chunks */
+ for (i = page_size; i < len; i += page_size) {
+@@ -387,8 +399,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
+ spi_sync(flash->spi, &m);
+
+ if (retlen)
+- *retlen += m.actual_length
+- - sizeof(flash->command);
++ *retlen += m.actual_length - CMD_SIZE;
+ }
+ }
+
+@@ -435,6 +446,7 @@ static struct flash_info __devinitdata m25p_data [] = {
+ { "at25fs040", 0x1f6604, 64 * 1024, 8, SECT_4K, },
+
+ { "at25df041a", 0x1f4401, 64 * 1024, 8, SECT_4K, },
++ { "at25df641", 0x1f4800, 64 * 1024, 128, SECT_4K, },
+
+ { "at26f004", 0x1f0400, 64 * 1024, 8, SECT_4K, },
+ { "at26df081a", 0x1f4501, 64 * 1024, 16, SECT_4K, },
+diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c
+index e427c82..bf485ff 100644
+--- a/drivers/mtd/devices/mtdram.c
++++ b/drivers/mtd/devices/mtdram.c
+@@ -17,6 +17,7 @@
+ #include <linux/init.h>
+ #include <linux/mtd/compatmac.h>
+ #include <linux/mtd/mtd.h>
++#include <linux/mtd/mtdram.h>
+
+ static unsigned long total_size = CONFIG_MTDRAM_TOTAL_SIZE;
+ static unsigned long erase_size = CONFIG_MTDRAM_ERASE_SIZE;
+diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c
+index 180298b..5f96018 100644
+--- a/drivers/mtd/devices/phram.c
++++ b/drivers/mtd/devices/phram.c
+@@ -282,7 +282,7 @@ static int phram_setup(const char *val, struct kernel_param *kp)
+ }
+
+ module_param_call(phram, phram_setup, NULL, NULL, 000);
+-MODULE_PARM_DESC(phram,"Memory region to map. \"map=<name>,<start>,<length>\"");
++MODULE_PARM_DESC(phram, "Memory region to map. \"phram=<name>,<start>,<length>\"");
+
+
+ static int __init init_phram(void)
+diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
+index c815d0f..4a79b18 100644
+--- a/drivers/mtd/ftl.c
++++ b/drivers/mtd/ftl.c
+@@ -136,8 +136,6 @@ typedef struct partition_t {
+ #endif
+ } partition_t;
+
+-void ftl_freepart(partition_t *part);
+-
+ /* Partition state flags */
+ #define FTL_FORMATTED 0x01
+
+@@ -1014,7 +1012,7 @@ static int ftl_writesect(struct mtd_blktrans_dev *dev,
+
+ /*====================================================================*/
+
+-void ftl_freepart(partition_t *part)
++static void ftl_freepart(partition_t *part)
+ {
+ vfree(part->VirtualBlockMap);
+ part->VirtualBlockMap = NULL;
+@@ -1069,7 +1067,7 @@ static void ftl_remove_dev(struct mtd_blktrans_dev *dev)
+ kfree(dev);
+ }
+
+-struct mtd_blktrans_ops ftl_tr = {
++static struct mtd_blktrans_ops ftl_tr = {
+ .name = "ftl",
+ .major = FTL_MAJOR,
+ .part_bits = PART_BITS,
+diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c
+index b8917be..c551d2f 100644
+--- a/drivers/mtd/inftlmount.c
++++ b/drivers/mtd/inftlmount.c
+@@ -41,11 +41,6 @@
+
+ char inftlmountrev[]="$Revision: 1.18 $";
+
+-extern int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+- size_t *retlen, uint8_t *buf);
+-extern int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+- size_t *retlen, uint8_t *buf);
+-
+ /*
+ * find_boot_record: Find the INFTL Media Header and its Spare copy which
+ * contains the various device information of the INFTL partition and
+diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
+index 12c2536..1bd69aa 100644
+--- a/drivers/mtd/maps/Kconfig
++++ b/drivers/mtd/maps/Kconfig
+@@ -21,6 +21,9 @@ config MTD_PHYSMAP
+ particular board as well as the bus width, either statically
+ with config options or at run-time.
+
++ To compile this driver as a module, choose M here: the
++ module will be called physmap.
++
+ config MTD_PHYSMAP_START
+ hex "Physical start address of flash mapping"
+ depends on MTD_PHYSMAP
+diff --git a/drivers/mtd/maps/bast-flash.c b/drivers/mtd/maps/bast-flash.c
+index fc3b267..1f49206 100644
+--- a/drivers/mtd/maps/bast-flash.c
++++ b/drivers/mtd/maps/bast-flash.c
+@@ -137,7 +137,7 @@ static int bast_flash_probe(struct platform_device *pdev)
+ if (info->map.size > AREA_MAXSIZE)
+ info->map.size = AREA_MAXSIZE;
+
+- pr_debug("%s: area %08lx, size %ld\n", __FUNCTION__,
++ pr_debug("%s: area %08lx, size %ld\n", __func__,
+ info->map.phys, info->map.size);
+
+ info->area = request_mem_region(res->start, info->map.size,
+@@ -149,7 +149,7 @@ static int bast_flash_probe(struct platform_device *pdev)
+ }
+
+ info->map.virt = ioremap(res->start, info->map.size);
+- pr_debug("%s: virt at %08x\n", __FUNCTION__, (int)info->map.virt);
++ pr_debug("%s: virt at %08x\n", __func__, (int)info->map.virt);
+
+ if (info->map.virt == 0) {
+ printk(KERN_ERR PFX "failed to ioremap() region\n");
+@@ -223,3 +223,4 @@ module_exit(bast_flash_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Ben Dooks <ben at simtec.co.uk>");
+ MODULE_DESCRIPTION("BAST MTD Map driver");
++MODULE_ALIAS("platform:bast-nor");
+diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c
+index 688ef49..59d8fb4 100644
+--- a/drivers/mtd/maps/ck804xrom.c
++++ b/drivers/mtd/maps/ck804xrom.c
+@@ -28,6 +28,9 @@
+
+ #define ROM_PROBE_STEP_SIZE (64*1024)
+
++#define DEV_CK804 1
++#define DEV_MCP55 2
++
+ struct ck804xrom_window {
+ void __iomem *virt;
+ unsigned long phys;
+@@ -45,8 +48,9 @@ struct ck804xrom_map_info {
+ char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
+ };
+
+-
+-/* The 2 bits controlling the window size are often set to allow reading
++/*
++ * The following applies to ck804 only:
++ * The 2 bits controlling the window size are often set to allow reading
+ * the BIOS, but too small to allow writing, since the lock registers are
+ * 4MiB lower in the address space than the data.
+ *
+@@ -58,10 +62,17 @@ struct ck804xrom_map_info {
+ * If only the 7 Bit is set, it is a 4MiB window. Otherwise, a
+ * 64KiB window.
+ *
++ * The following applies to mcp55 only:
++ * The 15 bits controlling the window size are distributed as follows:
++ * byte @0x88: bit 0..7
++ * byte @0x8c: bit 8..15
++ * word @0x90: bit 16..30
++ * If all bits are enabled, we have a 16? MiB window
++ * Please set win_size_bits to 0x7fffffff if you actually want to do something
+ */
+ static uint win_size_bits = 0;
+ module_param(win_size_bits, uint, 0);
+-MODULE_PARM_DESC(win_size_bits, "ROM window size bits override for 0x88 byte, normally set by BIOS.");
++MODULE_PARM_DESC(win_size_bits, "ROM window size bits override, normally set by BIOS.");
+
+ static struct ck804xrom_window ck804xrom_window = {
+ .maps = LIST_HEAD_INIT(ck804xrom_window.maps),
+@@ -102,10 +113,11 @@ static void ck804xrom_cleanup(struct ck804xrom_window *window)
+
+
+ static int __devinit ck804xrom_init_one (struct pci_dev *pdev,
+- const struct pci_device_id *ent)
++ const struct pci_device_id *ent)
+ {
+ static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
+ u8 byte;
++ u16 word;
+ struct ck804xrom_window *window = &ck804xrom_window;
+ struct ck804xrom_map_info *map = NULL;
+ unsigned long map_top;
+@@ -113,26 +125,42 @@ static int __devinit ck804xrom_init_one (struct pci_dev *pdev,
+ /* Remember the pci dev I find the window in */
+ window->pdev = pci_dev_get(pdev);
+
+- /* Enable the selected rom window. This is often incorrectly
+- * set up by the BIOS, and the 4MiB offset for the lock registers
+- * requires the full 5MiB of window space.
+- *
+- * This 'write, then read' approach leaves the bits for
+- * other uses of the hardware info.
+- */
+- pci_read_config_byte(pdev, 0x88, &byte);
+- pci_write_config_byte(pdev, 0x88, byte | win_size_bits );
+-
+-
+- /* Assume the rom window is properly setup, and find it's size */
+- pci_read_config_byte(pdev, 0x88, &byte);
+-
+- if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6)))
+- window->phys = 0xffb00000; /* 5MiB */
+- else if ((byte & (1<<7)) == (1<<7))
+- window->phys = 0xffc00000; /* 4MiB */
+- else
+- window->phys = 0xffff0000; /* 64KiB */
++ switch (ent->driver_data) {
++ case DEV_CK804:
++ /* Enable the selected rom window. This is often incorrectly
++ * set up by the BIOS, and the 4MiB offset for the lock registers
++ * requires the full 5MiB of window space.
++ *
++ * This 'write, then read' approach leaves the bits for
++ * other uses of the hardware info.
++ */
++ pci_read_config_byte(pdev, 0x88, &byte);
++ pci_write_config_byte(pdev, 0x88, byte | win_size_bits );
++
++ /* Assume the rom window is properly setup, and find it's size */
++ pci_read_config_byte(pdev, 0x88, &byte);
++
++ if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6)))
++ window->phys = 0xffb00000; /* 5MiB */
++ else if ((byte & (1<<7)) == (1<<7))
++ window->phys = 0xffc00000; /* 4MiB */
++ else
++ window->phys = 0xffff0000; /* 64KiB */
++ break;
++
++ case DEV_MCP55:
++ pci_read_config_byte(pdev, 0x88, &byte);
++ pci_write_config_byte(pdev, 0x88, byte | (win_size_bits & 0xff));
++
++ pci_read_config_byte(pdev, 0x8c, &byte);
++ pci_write_config_byte(pdev, 0x8c, byte | ((win_size_bits & 0xff00) >> 8));
++
++ pci_read_config_word(pdev, 0x90, &word);
++ pci_write_config_word(pdev, 0x90, word | ((win_size_bits & 0x7fff0000) >> 16));
++
++ window->phys = 0xff000000; /* 16MiB, hardcoded for now */
++ break;
++ }
+
+ window->size = 0xffffffffUL - window->phys + 1UL;
+
+@@ -303,8 +331,15 @@ static void __devexit ck804xrom_remove_one (struct pci_dev *pdev)
+ }
+
+ static struct pci_device_id ck804xrom_pci_tbl[] = {
+- { PCI_VENDOR_ID_NVIDIA, 0x0051,
+- PCI_ANY_ID, PCI_ANY_ID, }, /* nvidia ck804 */
++ { PCI_VENDOR_ID_NVIDIA, 0x0051, PCI_ANY_ID, PCI_ANY_ID, DEV_CK804 },
++ { PCI_VENDOR_ID_NVIDIA, 0x0360, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
++ { PCI_VENDOR_ID_NVIDIA, 0x0361, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
++ { PCI_VENDOR_ID_NVIDIA, 0x0362, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
++ { PCI_VENDOR_ID_NVIDIA, 0x0363, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
++ { PCI_VENDOR_ID_NVIDIA, 0x0364, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
++ { PCI_VENDOR_ID_NVIDIA, 0x0365, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
++ { PCI_VENDOR_ID_NVIDIA, 0x0366, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
++ { PCI_VENDOR_ID_NVIDIA, 0x0367, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
+ { 0, }
+ };
+
+@@ -332,7 +367,7 @@ static int __init init_ck804xrom(void)
+ break;
+ }
+ if (pdev) {
+- retVal = ck804xrom_init_one(pdev, &ck804xrom_pci_tbl[0]);
++ retVal = ck804xrom_init_one(pdev, id);
+ pci_dev_put(pdev);
+ return retVal;
+ }
+diff --git a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c
+index 6946d80..325c888 100644
+--- a/drivers/mtd/maps/integrator-flash.c
++++ b/drivers/mtd/maps/integrator-flash.c
+@@ -190,6 +190,7 @@ static struct platform_driver armflash_driver = {
+ .remove = armflash_remove,
+ .driver = {
+ .name = "armflash",
++ .owner = THIS_MODULE,
+ },
+ };
+
+@@ -209,3 +210,4 @@ module_exit(armflash_exit);
+ MODULE_AUTHOR("ARM Ltd");
+ MODULE_DESCRIPTION("ARM Integrator CFI map driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:armflash");
+diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c
+index c26488a..c8396b8 100644
+--- a/drivers/mtd/maps/ixp2000.c
++++ b/drivers/mtd/maps/ixp2000.c
+@@ -253,6 +253,7 @@ static struct platform_driver ixp2000_flash_driver = {
+ .remove = ixp2000_flash_remove,
+ .driver = {
+ .name = "IXP2000-Flash",
++ .owner = THIS_MODULE,
+ },
+ };
+
+@@ -270,4 +271,4 @@ module_init(ixp2000_flash_init);
+ module_exit(ixp2000_flash_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Deepak Saxena <dsaxena at plexity.net>");
+-
++MODULE_ALIAS("platform:IXP2000-Flash");
+diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c
+index 7a828e3..01f19a4 100644
+--- a/drivers/mtd/maps/ixp4xx.c
++++ b/drivers/mtd/maps/ixp4xx.c
+@@ -275,6 +275,7 @@ static struct platform_driver ixp4xx_flash_driver = {
+ .remove = ixp4xx_flash_remove,
+ .driver = {
+ .name = "IXP4XX-Flash",
++ .owner = THIS_MODULE,
+ },
+ };
+
+@@ -295,3 +296,4 @@ module_exit(ixp4xx_flash_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems");
+ MODULE_AUTHOR("Deepak Saxena");
++MODULE_ALIAS("platform:IXP4XX-Flash");
+diff --git a/drivers/mtd/maps/omap_nor.c b/drivers/mtd/maps/omap_nor.c
+index e8d9ae5..240b0e2 100644
+--- a/drivers/mtd/maps/omap_nor.c
++++ b/drivers/mtd/maps/omap_nor.c
+@@ -70,7 +70,7 @@ static void omap_set_vpp(struct map_info *map, int enable)
+ }
+ }
+
+-static int __devinit omapflash_probe(struct platform_device *pdev)
++static int __init omapflash_probe(struct platform_device *pdev)
+ {
+ int err;
+ struct omapflash_info *info;
+@@ -130,7 +130,7 @@ out_free_info:
+ return err;
+ }
+
+-static int __devexit omapflash_remove(struct platform_device *pdev)
++static int __exit omapflash_remove(struct platform_device *pdev)
+ {
+ struct omapflash_info *info = platform_get_drvdata(pdev);
+
+@@ -152,16 +152,16 @@ static int __devexit omapflash_remove(struct platform_device *pdev)
+ }
+
+ static struct platform_driver omapflash_driver = {
+- .probe = omapflash_probe,
+- .remove = __devexit_p(omapflash_remove),
++ .remove = __exit_p(omapflash_remove),
+ .driver = {
+ .name = "omapflash",
++ .owner = THIS_MODULE,
+ },
+ };
+
+ static int __init omapflash_init(void)
+ {
+- return platform_driver_register(&omapflash_driver);
++ return platform_driver_probe(&omapflash_driver, omapflash_probe);
+ }
+
+ static void __exit omapflash_exit(void)
+@@ -174,4 +174,4 @@ module_exit(omapflash_exit);
+
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("MTD NOR map driver for TI OMAP boards");
+-
++MODULE_ALIAS("platform:omapflash");
+diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
+index eaeb56a..1912d96 100644
+--- a/drivers/mtd/maps/pcmciamtd.c
++++ b/drivers/mtd/maps/pcmciamtd.c
+@@ -33,7 +33,7 @@ MODULE_PARM_DESC(debug, "Set Debug Level 0=quiet, 5=noisy");
+ #undef DEBUG
+ #define DEBUG(n, format, arg...) \
+ if (n <= debug) { \
+- printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \
++ printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \
+ }
+
+ #else
+diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
+index bc4649a..183255f 100644
+--- a/drivers/mtd/maps/physmap.c
++++ b/drivers/mtd/maps/physmap.c
+@@ -242,6 +242,7 @@ static struct platform_driver physmap_flash_driver = {
+ .shutdown = physmap_flash_shutdown,
+ .driver = {
+ .name = "physmap-flash",
++ .owner = THIS_MODULE,
+ },
+ };
+
+@@ -319,3 +320,10 @@ module_exit(physmap_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("David Woodhouse <dwmw2 at infradead.org>");
+ MODULE_DESCRIPTION("Generic configurable MTD map driver");
++
++/* legacy platform drivers can't hotplug or coldplg */
++#ifndef PHYSMAP_COMPAT
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:physmap-flash");
++#endif
++
+diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c
+index 894c0b2..f0b10ca 100644
+--- a/drivers/mtd/maps/plat-ram.c
++++ b/drivers/mtd/maps/plat-ram.c
+@@ -47,6 +47,7 @@ struct platram_info {
+ struct mtd_info *mtd;
+ struct map_info map;
+ struct mtd_partition *partitions;
++ bool free_partitions;
+ struct resource *area;
+ struct platdata_mtd_ram *pdata;
+ };
+@@ -98,7 +99,8 @@ static int platram_remove(struct platform_device *pdev)
+ #ifdef CONFIG_MTD_PARTITIONS
+ if (info->partitions) {
+ del_mtd_partitions(info->mtd);
+- kfree(info->partitions);
++ if (info->free_partitions)
++ kfree(info->partitions);
+ }
+ #endif
+ del_mtd_device(info->mtd);
+@@ -176,7 +178,8 @@ static int platram_probe(struct platform_device *pdev)
+
+ info->map.phys = res->start;
+ info->map.size = (res->end - res->start) + 1;
+- info->map.name = pdata->mapname != NULL ? pdata->mapname : (char *)pdev->name;
++ info->map.name = pdata->mapname != NULL ?
++ (char *)pdata->mapname : (char *)pdev->name;
+ info->map.bankwidth = pdata->bankwidth;
+
+ /* register our usage of the memory area */
+@@ -203,9 +206,19 @@ static int platram_probe(struct platform_device *pdev)
+
+ dev_dbg(&pdev->dev, "initialised map, probing for mtd\n");
+
+- /* probe for the right mtd map driver */
++ /* probe for the right mtd map driver
++ * supplied by the platform_data struct */
++
++ if (pdata->map_probes != 0) {
++ const char **map_probes = pdata->map_probes;
++
++ for ( ; !info->mtd && *map_probes; map_probes++)
++ info->mtd = do_map_probe(*map_probes , &info->map);
++ }
++ /* fallback to map_ram */
++ else
++ info->mtd = do_map_probe("map_ram", &info->map);
+
+- info->mtd = do_map_probe("map_ram" , &info->map);
+ if (info->mtd == NULL) {
+ dev_err(&pdev->dev, "failed to probe for map_ram\n");
+ err = -ENOMEM;
+@@ -220,19 +233,21 @@ static int platram_probe(struct platform_device *pdev)
+ * to add this device whole */
+
+ #ifdef CONFIG_MTD_PARTITIONS
+- if (pdata->nr_partitions > 0) {
+- const char **probes = { NULL };
+-
+- if (pdata->probes)
+- probes = (const char **)pdata->probes;
+-
+- err = parse_mtd_partitions(info->mtd, probes,
++ if (!pdata->nr_partitions) {
++ /* try to probe using the supplied probe type */
++ if (pdata->probes) {
++ err = parse_mtd_partitions(info->mtd, pdata->probes,
+ &info->partitions, 0);
+- if (err > 0) {
+- err = add_mtd_partitions(info->mtd, info->partitions,
+- err);
++ info->free_partitions = 1;
++ if (err > 0)
++ err = add_mtd_partitions(info->mtd,
++ info->partitions, err);
+ }
+ }
++ /* use the static mapping */
++ else
++ err = add_mtd_partitions(info->mtd, pdata->partitions,
++ pdata->nr_partitions);
+ #endif /* CONFIG_MTD_PARTITIONS */
+
+ if (add_mtd_device(info->mtd)) {
+@@ -240,7 +255,9 @@ static int platram_probe(struct platform_device *pdev)
+ err = -ENOMEM;
+ }
+
+- dev_info(&pdev->dev, "registered mtd device\n");
++ if (!err)
++ dev_info(&pdev->dev, "registered mtd device\n");
++
+ return err;
+
+ exit_free:
+@@ -251,6 +268,9 @@ static int platram_probe(struct platform_device *pdev)
+
+ /* device driver info */
+
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:mtd-ram");
++
+ static struct platform_driver platram_driver = {
+ .probe = platram_probe,
+ .remove = platram_remove,
+diff --git a/drivers/mtd/maps/pmcmsp-flash.c b/drivers/mtd/maps/pmcmsp-flash.c
+index 02bde8c..f43ba28 100644
+--- a/drivers/mtd/maps/pmcmsp-flash.c
++++ b/drivers/mtd/maps/pmcmsp-flash.c
+@@ -46,7 +46,7 @@ static struct mtd_partition **msp_parts;
+ static struct map_info *msp_maps;
+ static int fcnt;
+
+-#define DEBUG_MARKER printk(KERN_NOTICE "%s[%d]\n",__FUNCTION__,__LINE__)
++#define DEBUG_MARKER printk(KERN_NOTICE "%s[%d]\n", __func__, __LINE__)
+
+ int __init init_msp_flash(void)
+ {
+diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
+index f904e6b..c7d5a52 100644
+--- a/drivers/mtd/maps/sa1100-flash.c
++++ b/drivers/mtd/maps/sa1100-flash.c
+@@ -456,6 +456,7 @@ static struct platform_driver sa1100_mtd_driver = {
+ .shutdown = sa1100_mtd_shutdown,
+ .driver = {
+ .name = "flash",
++ .owner = THIS_MODULE,
+ },
+ };
+
+@@ -475,3 +476,4 @@ module_exit(sa1100_mtd_exit);
+ MODULE_AUTHOR("Nicolas Pitre");
+ MODULE_DESCRIPTION("SA1100 CFI map driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:flash");
+diff --git a/drivers/mtd/maps/sharpsl-flash.c b/drivers/mtd/maps/sharpsl-flash.c
+index 12fe53c..917dc77 100644
+--- a/drivers/mtd/maps/sharpsl-flash.c
++++ b/drivers/mtd/maps/sharpsl-flash.c
+@@ -92,7 +92,7 @@ int __init init_sharpsl(void)
+ parts = sharpsl_partitions;
+ nb_parts = ARRAY_SIZE(sharpsl_partitions);
+
+- printk(KERN_NOTICE "Using %s partision definition\n", part_type);
++ printk(KERN_NOTICE "Using %s partition definition\n", part_type);
+ add_mtd_partitions(mymtd, parts, nb_parts);
+
+ return 0;
+diff --git a/drivers/mtd/maps/tqm8xxl.c b/drivers/mtd/maps/tqm8xxl.c
+index 37e4ded..5217340 100644
+--- a/drivers/mtd/maps/tqm8xxl.c
++++ b/drivers/mtd/maps/tqm8xxl.c
+@@ -124,7 +124,7 @@ int __init init_tqm_mtd(void)
+ //request maximum flash size address space
+ start_scan_addr = ioremap(flash_addr, flash_size);
+ if (!start_scan_addr) {
+- printk(KERN_WARNING "%s:Failed to ioremap address:0x%x\n", __FUNCTION__, flash_addr);
++ printk(KERN_WARNING "%s:Failed to ioremap address:0x%x\n", __func__, flash_addr);
+ return -EIO;
+ }
+
+@@ -132,7 +132,7 @@ int __init init_tqm_mtd(void)
+ if(mtd_size >= flash_size)
+ break;
+
+- printk(KERN_INFO "%s: chip probing count %d\n", __FUNCTION__, idx);
++ printk(KERN_INFO "%s: chip probing count %d\n", __func__, idx);
+
+ map_banks[idx] = kzalloc(sizeof(struct map_info), GFP_KERNEL);
+ if(map_banks[idx] == NULL) {
+@@ -178,7 +178,7 @@ int __init init_tqm_mtd(void)
+ mtd_size += mtd_banks[idx]->size;
+ num_banks++;
+
+- printk(KERN_INFO "%s: bank%d, name:%s, size:%dbytes \n", __FUNCTION__, num_banks,
++ printk(KERN_INFO "%s: bank%d, name:%s, size:%dbytes \n", __func__, num_banks,
+ mtd_banks[idx]->name, mtd_banks[idx]->size);
+ }
+ }
+diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c
+index d3cf050..5a680e1 100644
+--- a/drivers/mtd/mtdoops.c
++++ b/drivers/mtd/mtdoops.c
+@@ -35,7 +35,7 @@
+
+ #define OOPS_PAGE_SIZE 4096
+
+-struct mtdoops_context {
++static struct mtdoops_context {
+ int mtd_index;
+ struct work_struct work_erase;
+ struct work_struct work_write;
+diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
+index 4a3c675..5076faf 100644
+--- a/drivers/mtd/nand/Kconfig
++++ b/drivers/mtd/nand/Kconfig
+@@ -278,6 +278,54 @@ config MTD_NAND_AT91
+ help
+ Enables support for NAND Flash / Smart Media Card interface
+ on Atmel AT91 processors.
++choice
++ prompt "ECC management for NAND Flash / SmartMedia on AT91"
++ depends on MTD_NAND_AT91
++
++config MTD_NAND_AT91_ECC_HW
++ bool "Hardware ECC"
++ depends on ARCH_AT91SAM9263 || ARCH_AT91SAM9260
++ help
++ Uses hardware ECC provided by the at91sam9260/at91sam9263 chip
++ instead of software ECC.
++ The hardware ECC controller is capable of single bit error
++ correction and 2-bit random detection per page.
++
++ NB : hardware and software ECC schemes are incompatible.
++ If you switch from one to another, you'll have to erase your
++ mtd partition.
++
++ If unsure, say Y
++
++config MTD_NAND_AT91_ECC_SOFT
++ bool "Software ECC"
++ help
++ Uses software ECC.
++
++ NB : hardware and software ECC schemes are incompatible.
++ If you switch from one to another, you'll have to erase your
++ mtd partition.
++
++config MTD_NAND_AT91_ECC_NONE
++ bool "No ECC (testing only, DANGEROUS)"
++ depends on DEBUG_KERNEL
++ help
++ No ECC will be used.
++ It's not a good idea and it should be reserved for testing
++ purpose only.
++
++ If unsure, say N
++
++ endchoice
++
++endchoice
++
++config MTD_NAND_PXA3xx
++ bool "Support for NAND flash devices on PXA3xx"
++ depends on MTD_NAND && PXA3xx
++ help
++ This enables the driver for the NAND flash device found on
++ PXA3xx processors
+
+ config MTD_NAND_CM_X270
+ tristate "Support for NAND Flash on CM-X270 modules"
+@@ -314,7 +362,7 @@ config MTD_ALAUDA
+
+ config MTD_NAND_ORION
+ tristate "NAND Flash support for Marvell Orion SoC"
+- depends on ARCH_ORION && MTD_NAND
++ depends on PLAT_ORION && MTD_NAND
+ help
+ This enables the NAND flash controller on Orion machines.
+
+@@ -330,4 +378,12 @@ config MTD_NAND_FSL_ELBC
+ Enabling this option will enable you to use this to control
+ external NAND devices.
+
++config MTD_NAND_FSL_UPM
++ tristate "Support for NAND on Freescale UPM"
++ depends on MTD_NAND && OF_GPIO && (PPC_83xx || PPC_85xx)
++ select FSL_LBC
++ help
++ Enables support for NAND Flash chips wired onto Freescale PowerPC
++ processor localbus with User-Programmable Machine support.
++
+ endif # MTD_NAND
+diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
+index 80d575e..a6e74a4 100644
+--- a/drivers/mtd/nand/Makefile
++++ b/drivers/mtd/nand/Makefile
+@@ -27,10 +27,12 @@ obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o
+ obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o
+ obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o
+ obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o
++obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx_nand.o
+ obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o
+ obj-$(CONFIG_MTD_ALAUDA) += alauda.o
+ obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o
+ obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o
+ obj-$(CONFIG_MTD_NAND_FSL_ELBC) += fsl_elbc_nand.o
++obj-$(CONFIG_MTD_NAND_FSL_UPM) += fsl_upm.o
+
+ nand-objs := nand_base.o nand_bbt.o
+diff --git a/drivers/mtd/nand/at91_nand.c b/drivers/mtd/nand/at91_nand.c
+index c9fb2ac..414ceae 100644
+--- a/drivers/mtd/nand/at91_nand.c
++++ b/drivers/mtd/nand/at91_nand.c
+@@ -9,6 +9,15 @@
+ * Derived from drivers/mtd/spia.c
+ * Copyright (C) 2000 Steven J. Hill (sjhill at cotw.com)
+ *
++ *
++ * Add Hardware ECC support for AT91SAM9260 / AT91SAM9263
++ * Richard Genoud (richard.genoud at gmail.com), Adeneo Copyright (C) 2007
++ *
++ * Derived from Das U-Boot source code
++ * (u-boot-1.1.5/board/atmel/at91sam9263ek/nand.c)
++ * (C) Copyright 2006 ATMEL Rousset, Lacressonniere Nicolas
++ *
++ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+@@ -29,11 +38,59 @@
+ #include <asm/arch/board.h>
+ #include <asm/arch/gpio.h>
+
++#ifdef CONFIG_MTD_NAND_AT91_ECC_HW
++#define hard_ecc 1
++#else
++#define hard_ecc 0
++#endif
++
++#ifdef CONFIG_MTD_NAND_AT91_ECC_NONE
++#define no_ecc 1
++#else
++#define no_ecc 0
++#endif
++
++/* Register access macros */
++#define ecc_readl(add, reg) \
++ __raw_readl(add + AT91_ECC_##reg)
++#define ecc_writel(add, reg, value) \
++ __raw_writel((value), add + AT91_ECC_##reg)
++
++#include <asm/arch/at91_ecc.h> /* AT91SAM9260/3 ECC registers */
++
++/* oob layout for large page size
++ * bad block info is on bytes 0 and 1
++ * the bytes have to be consecutives to avoid
++ * several NAND_CMD_RNDOUT during read
++ */
++static struct nand_ecclayout at91_oobinfo_large = {
++ .eccbytes = 4,
++ .eccpos = {60, 61, 62, 63},
++ .oobfree = {
++ {2, 58}
++ },
++};
++
++/* oob layout for small page size
++ * bad block info is on bytes 4 and 5
++ * the bytes have to be consecutives to avoid
++ * several NAND_CMD_RNDOUT during read
++ */
++static struct nand_ecclayout at91_oobinfo_small = {
++ .eccbytes = 4,
++ .eccpos = {0, 1, 2, 3},
++ .oobfree = {
++ {6, 10}
++ },
++};
++
+ struct at91_nand_host {
+ struct nand_chip nand_chip;
+ struct mtd_info mtd;
+ void __iomem *io_base;
+ struct at91_nand_data *board;
++ struct device *dev;
++ void __iomem *ecc;
+ };
+
+ /*
+@@ -44,6 +101,12 @@ static void at91_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+ struct nand_chip *nand_chip = mtd->priv;
+ struct at91_nand_host *host = nand_chip->priv;
+
++ if (host->board->enable_pin && (ctrl & NAND_CTRL_CHANGE)) {
++ if (ctrl & NAND_NCE)
++ at91_set_gpio_value(host->board->enable_pin, 0);
++ else
++ at91_set_gpio_value(host->board->enable_pin, 1);
++ }
+ if (cmd == NAND_CMD_NONE)
+ return;
+
+@@ -82,8 +145,217 @@ static void at91_nand_disable(struct at91_nand_host *host)
+ at91_set_gpio_value(host->board->enable_pin, 1);
+ }
+
++/*
++ * write oob for small pages
++ */
++static int at91_nand_write_oob_512(struct mtd_info *mtd,
++ struct nand_chip *chip, int page)
++{
++ int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
++ int eccsize = chip->ecc.size, length = mtd->oobsize;
++ int len, pos, status = 0;
++ const uint8_t *bufpoi = chip->oob_poi;
++
++ pos = eccsize + chunk;
++
++ chip->cmdfunc(mtd, NAND_CMD_SEQIN, pos, page);
++ len = min_t(int, length, chunk);
++ chip->write_buf(mtd, bufpoi, len);
++ bufpoi += len;
++ length -= len;
++ if (length > 0)
++ chip->write_buf(mtd, bufpoi, length);
++
++ chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
++ status = chip->waitfunc(mtd, chip);
++
++ return status & NAND_STATUS_FAIL ? -EIO : 0;
++
++}
++
++/*
++ * read oob for small pages
++ */
++static int at91_nand_read_oob_512(struct mtd_info *mtd,
++ struct nand_chip *chip, int page, int sndcmd)
++{
++ if (sndcmd) {
++ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
++ sndcmd = 0;
++ }
++ chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
++ return sndcmd;
++}
++
++/*
++ * Calculate HW ECC
++ *
++ * function called after a write
++ *
++ * mtd: MTD block structure
++ * dat: raw data (unused)
++ * ecc_code: buffer for ECC
++ */
++static int at91_nand_calculate(struct mtd_info *mtd,
++ const u_char *dat, unsigned char *ecc_code)
++{
++ struct nand_chip *nand_chip = mtd->priv;
++ struct at91_nand_host *host = nand_chip->priv;
++ uint32_t *eccpos = nand_chip->ecc.layout->eccpos;
++ unsigned int ecc_value;
++
++ /* get the first 2 ECC bytes */
++ ecc_value = ecc_readl(host->ecc, PR);
++
++ ecc_code[eccpos[0]] = ecc_value & 0xFF;
++ ecc_code[eccpos[1]] = (ecc_value >> 8) & 0xFF;
++
++ /* get the last 2 ECC bytes */
++ ecc_value = ecc_readl(host->ecc, NPR) & AT91_ECC_NPARITY;
++
++ ecc_code[eccpos[2]] = ecc_value & 0xFF;
++ ecc_code[eccpos[3]] = (ecc_value >> 8) & 0xFF;
++
++ return 0;
++}
++
++/*
++ * HW ECC read page function
++ *
++ * mtd: mtd info structure
++ * chip: nand chip info structure
++ * buf: buffer to store read data
++ */
++static int at91_nand_read_page(struct mtd_info *mtd,
++ struct nand_chip *chip, uint8_t *buf)
++{
++ int eccsize = chip->ecc.size;
++ int eccbytes = chip->ecc.bytes;
++ uint32_t *eccpos = chip->ecc.layout->eccpos;
++ uint8_t *p = buf;
++ uint8_t *oob = chip->oob_poi;
++ uint8_t *ecc_pos;
++ int stat;
++
++ /* read the page */
++ chip->read_buf(mtd, p, eccsize);
++
++ /* move to ECC position if needed */
++ if (eccpos[0] != 0) {
++ /* This only works on large pages
++ * because the ECC controller waits for
++ * NAND_CMD_RNDOUTSTART after the
++ * NAND_CMD_RNDOUT.
++ * anyway, for small pages, the eccpos[0] == 0
++ */
++ chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
++ mtd->writesize + eccpos[0], -1);
++ }
++
++ /* the ECC controller needs to read the ECC just after the data */
++ ecc_pos = oob + eccpos[0];
++ chip->read_buf(mtd, ecc_pos, eccbytes);
++
++ /* check if there's an error */
++ stat = chip->ecc.correct(mtd, p, oob, NULL);
++
++ if (stat < 0)
++ mtd->ecc_stats.failed++;
++ else
++ mtd->ecc_stats.corrected += stat;
++
++ /* get back to oob start (end of page) */
++ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
++
++ /* read the oob */
++ chip->read_buf(mtd, oob, mtd->oobsize);
++
++ return 0;
++}
++
++/*
++ * HW ECC Correction
++ *
++ * function called after a read
++ *
++ * mtd: MTD block structure
++ * dat: raw data read from the chip
++ * read_ecc: ECC from the chip (unused)
++ * isnull: unused
++ *
++ * Detect and correct a 1 bit error for a page
++ */
++static int at91_nand_correct(struct mtd_info *mtd, u_char *dat,
++ u_char *read_ecc, u_char *isnull)
++{
++ struct nand_chip *nand_chip = mtd->priv;
++ struct at91_nand_host *host = nand_chip->priv;
++ unsigned int ecc_status;
++ unsigned int ecc_word, ecc_bit;
++
++ /* get the status from the Status Register */
++ ecc_status = ecc_readl(host->ecc, SR);
++
++ /* if there's no error */
++ if (likely(!(ecc_status & AT91_ECC_RECERR)))
++ return 0;
++
++ /* get error bit offset (4 bits) */
++ ecc_bit = ecc_readl(host->ecc, PR) & AT91_ECC_BITADDR;
++ /* get word address (12 bits) */
++ ecc_word = ecc_readl(host->ecc, PR) & AT91_ECC_WORDADDR;
++ ecc_word >>= 4;
++
++ /* if there are multiple errors */
++ if (ecc_status & AT91_ECC_MULERR) {
++ /* check if it is a freshly erased block
++ * (filled with 0xff) */
++ if ((ecc_bit == AT91_ECC_BITADDR)
++ && (ecc_word == (AT91_ECC_WORDADDR >> 4))) {
++ /* the block has just been erased, return OK */
++ return 0;
++ }
++ /* it doesn't seems to be a freshly
++ * erased block.
++ * We can't correct so many errors */
++ dev_dbg(host->dev, "at91_nand : multiple errors detected."
++ " Unable to correct.\n");
++ return -EIO;
++ }
++
++ /* if there's a single bit error : we can correct it */
++ if (ecc_status & AT91_ECC_ECCERR) {
++ /* there's nothing much to do here.
++ * the bit error is on the ECC itself.
++ */
++ dev_dbg(host->dev, "at91_nand : one bit error on ECC code."
++ " Nothing to correct\n");
++ return 0;
++ }
++
++ dev_dbg(host->dev, "at91_nand : one bit error on data."
++ " (word offset in the page :"
++ " 0x%x bit offset : 0x%x)\n",
++ ecc_word, ecc_bit);
++ /* correct the error */
++ if (nand_chip->options & NAND_BUSWIDTH_16) {
++ /* 16 bits words */
++ ((unsigned short *) dat)[ecc_word] ^= (1 << ecc_bit);
++ } else {
++ /* 8 bits words */
++ dat[ecc_word] ^= (1 << ecc_bit);
++ }
++ dev_dbg(host->dev, "at91_nand : error corrected\n");
++ return 1;
++}
++
++/*
++ * Enable HW ECC : unsused
++ */
++static void at91_nand_hwctl(struct mtd_info *mtd, int mode) { ; }
++
+ #ifdef CONFIG_MTD_PARTITIONS
+-const char *part_probes[] = { "cmdlinepart", NULL };
++static const char *part_probes[] = { "cmdlinepart", NULL };
+ #endif
+
+ /*
+@@ -94,6 +366,8 @@ static int __init at91_nand_probe(struct platform_device *pdev)
+ struct at91_nand_host *host;
+ struct mtd_info *mtd;
+ struct nand_chip *nand_chip;
++ struct resource *regs;
++ struct resource *mem;
+ int res;
+
+ #ifdef CONFIG_MTD_PARTITIONS
+@@ -108,8 +382,13 @@ static int __init at91_nand_probe(struct platform_device *pdev)
+ return -ENOMEM;
+ }
+
+- host->io_base = ioremap(pdev->resource[0].start,
+- pdev->resource[0].end - pdev->resource[0].start + 1);
++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!mem) {
++ printk(KERN_ERR "at91_nand: can't get I/O resource mem\n");
++ return -ENXIO;
++ }
++
++ host->io_base = ioremap(mem->start, mem->end - mem->start + 1);
+ if (host->io_base == NULL) {
+ printk(KERN_ERR "at91_nand: ioremap failed\n");
+ kfree(host);
+@@ -119,6 +398,7 @@ static int __init at91_nand_probe(struct platform_device *pdev)
+ mtd = &host->mtd;
+ nand_chip = &host->nand_chip;
+ host->board = pdev->dev.platform_data;
++ host->dev = &pdev->dev;
+
+ nand_chip->priv = host; /* link the private data structures */
+ mtd->priv = nand_chip;
+@@ -132,7 +412,32 @@ static int __init at91_nand_probe(struct platform_device *pdev)
+ if (host->board->rdy_pin)
+ nand_chip->dev_ready = at91_nand_device_ready;
+
++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++ if (!regs && hard_ecc) {
++ printk(KERN_ERR "at91_nand: can't get I/O resource "
++ "regs\nFalling back on software ECC\n");
++ }
++
+ nand_chip->ecc.mode = NAND_ECC_SOFT; /* enable ECC */
++ if (no_ecc)
++ nand_chip->ecc.mode = NAND_ECC_NONE;
++ if (hard_ecc && regs) {
++ host->ecc = ioremap(regs->start, regs->end - regs->start + 1);
++ if (host->ecc == NULL) {
++ printk(KERN_ERR "at91_nand: ioremap failed\n");
++ res = -EIO;
++ goto err_ecc_ioremap;
++ }
++ nand_chip->ecc.mode = NAND_ECC_HW_SYNDROME;
++ nand_chip->ecc.calculate = at91_nand_calculate;
++ nand_chip->ecc.correct = at91_nand_correct;
++ nand_chip->ecc.hwctl = at91_nand_hwctl;
++ nand_chip->ecc.read_page = at91_nand_read_page;
++ nand_chip->ecc.bytes = 4;
++ nand_chip->ecc.prepad = 0;
++ nand_chip->ecc.postpad = 0;
++ }
++
+ nand_chip->chip_delay = 20; /* 20us command delay time */
+
+ if (host->board->bus_width_16) /* 16-bit bus width */
+@@ -149,8 +454,53 @@ static int __init at91_nand_probe(struct platform_device *pdev)
+ }
+ }
+
+- /* Scan to find existance of the device */
+- if (nand_scan(mtd, 1)) {
++ /* first scan to find the device and get the page size */
++ if (nand_scan_ident(mtd, 1)) {
++ res = -ENXIO;
++ goto out;
++ }
++
++ if (nand_chip->ecc.mode == NAND_ECC_HW_SYNDROME) {
++ /* ECC is calculated for the whole page (1 step) */
++ nand_chip->ecc.size = mtd->writesize;
++
++ /* set ECC page size and oob layout */
++ switch (mtd->writesize) {
++ case 512:
++ nand_chip->ecc.layout = &at91_oobinfo_small;
++ nand_chip->ecc.read_oob = at91_nand_read_oob_512;
++ nand_chip->ecc.write_oob = at91_nand_write_oob_512;
++ ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_528);
++ break;
++ case 1024:
++ nand_chip->ecc.layout = &at91_oobinfo_large;
++ ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_1056);
++ break;
++ case 2048:
++ nand_chip->ecc.layout = &at91_oobinfo_large;
++ ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_2112);
++ break;
++ case 4096:
++ nand_chip->ecc.layout = &at91_oobinfo_large;
++ ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_4224);
++ break;
++ default:
++ /* page size not handled by HW ECC */
++ /* switching back to soft ECC */
++ nand_chip->ecc.mode = NAND_ECC_SOFT;
++ nand_chip->ecc.calculate = NULL;
++ nand_chip->ecc.correct = NULL;
++ nand_chip->ecc.hwctl = NULL;
++ nand_chip->ecc.read_page = NULL;
++ nand_chip->ecc.postpad = 0;
++ nand_chip->ecc.prepad = 0;
++ nand_chip->ecc.bytes = 0;
++ break;
++ }
++ }
++
++ /* second phase scan */
++ if (nand_scan_tail(mtd)) {
+ res = -ENXIO;
+ goto out;
+ }
+@@ -179,9 +529,15 @@ static int __init at91_nand_probe(struct platform_device *pdev)
+ if (!res)
+ return res;
+
++#ifdef CONFIG_MTD_PARTITIONS
+ release:
++#endif
+ nand_release(mtd);
++
+ out:
++ iounmap(host->ecc);
++
++err_ecc_ioremap:
+ at91_nand_disable(host);
+ platform_set_drvdata(pdev, NULL);
+ iounmap(host->io_base);
+@@ -202,6 +558,7 @@ static int __devexit at91_nand_remove(struct platform_device *pdev)
+ at91_nand_disable(host);
+
+ iounmap(host->io_base);
++ iounmap(host->ecc);
+ kfree(host);
+
+ return 0;
+@@ -233,4 +590,5 @@ module_exit(at91_nand_exit);
+
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Rick Bronson");
+-MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91RM9200");
++MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91RM9200 / AT91SAM9");
++MODULE_ALIAS("platform:at91_nand");
+diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c
+index 747042a..e87a572 100644
+--- a/drivers/mtd/nand/bf5xx_nand.c
++++ b/drivers/mtd/nand/bf5xx_nand.c
+@@ -1,6 +1,6 @@
+ /* linux/drivers/mtd/nand/bf5xx_nand.c
+ *
+- * Copyright 2006-2007 Analog Devices Inc.
++ * Copyright 2006-2008 Analog Devices Inc.
+ * http://blackfin.uclinux.org/
+ * Bryan Wu <bryan.wu at analog.com>
+ *
+@@ -74,7 +74,7 @@ static int hardware_ecc = 1;
+ static int hardware_ecc;
+ #endif
+
+-static unsigned short bfin_nfc_pin_req[] =
++static const unsigned short bfin_nfc_pin_req[] =
+ {P_NAND_CE,
+ P_NAND_RB,
+ P_NAND_D0,
+@@ -581,12 +581,6 @@ static int bf5xx_nand_hw_init(struct bf5xx_nand_info *info)
+ bfin_write_NFC_IRQSTAT(val);
+ SSYNC();
+
+- if (peripheral_request_list(bfin_nfc_pin_req, DRV_NAME)) {
+- printk(KERN_ERR DRV_NAME
+- ": Requesting Peripherals failed\n");
+- return -EFAULT;
+- }
+-
+ /* DMA initialization */
+ if (bf5xx_nand_dma_init(info))
+ err = -ENXIO;
+@@ -654,6 +648,12 @@ static int bf5xx_nand_probe(struct platform_device *pdev)
+
+ dev_dbg(&pdev->dev, "(%p)\n", pdev);
+
++ if (peripheral_request_list(bfin_nfc_pin_req, DRV_NAME)) {
++ printk(KERN_ERR DRV_NAME
++ ": Requesting Peripherals failed\n");
++ return -EFAULT;
++ }
++
+ if (!plat) {
+ dev_err(&pdev->dev, "no platform specific information\n");
+ goto exit_error;
+@@ -803,3 +803,4 @@ module_exit(bf5xx_nand_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR(DRV_AUTHOR);
+ MODULE_DESCRIPTION(DRV_DESC);
++MODULE_ALIAS("platform:" DRV_NAME);
+diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c
+index 8dab696..3370a80 100644
+--- a/drivers/mtd/nand/cs553x_nand.c
++++ b/drivers/mtd/nand/cs553x_nand.c
+@@ -279,7 +279,7 @@ static int is_geode(void)
+
+
+ #ifdef CONFIG_MTD_PARTITIONS
+-const char *part_probes[] = { "cmdlinepart", NULL };
++static const char *part_probes[] = { "cmdlinepart", NULL };
+ #endif
+
+
+diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
+index b025dfe..4b69aac 100644
+--- a/drivers/mtd/nand/fsl_elbc_nand.c
++++ b/drivers/mtd/nand/fsl_elbc_nand.c
+@@ -36,207 +36,12 @@
+ #include <linux/mtd/partitions.h>
+
+ #include <asm/io.h>
+-
++#include <asm/fsl_lbc.h>
+
+ #define MAX_BANKS 8
+ #define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */
+ #define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */
+
+-struct elbc_bank {
+- __be32 br; /**< Base Register */
+-#define BR_BA 0xFFFF8000
+-#define BR_BA_SHIFT 15
+-#define BR_PS 0x00001800
+-#define BR_PS_SHIFT 11
+-#define BR_PS_8 0x00000800 /* Port Size 8 bit */
+-#define BR_PS_16 0x00001000 /* Port Size 16 bit */
+-#define BR_PS_32 0x00001800 /* Port Size 32 bit */
+-#define BR_DECC 0x00000600
+-#define BR_DECC_SHIFT 9
+-#define BR_DECC_OFF 0x00000000 /* HW ECC checking and generation off */
+-#define BR_DECC_CHK 0x00000200 /* HW ECC checking on, generation off */
+-#define BR_DECC_CHK_GEN 0x00000400 /* HW ECC checking and generation on */
+-#define BR_WP 0x00000100
+-#define BR_WP_SHIFT 8
+-#define BR_MSEL 0x000000E0
+-#define BR_MSEL_SHIFT 5
+-#define BR_MS_GPCM 0x00000000 /* GPCM */
+-#define BR_MS_FCM 0x00000020 /* FCM */
+-#define BR_MS_SDRAM 0x00000060 /* SDRAM */
+-#define BR_MS_UPMA 0x00000080 /* UPMA */
+-#define BR_MS_UPMB 0x000000A0 /* UPMB */
+-#define BR_MS_UPMC 0x000000C0 /* UPMC */
+-#define BR_V 0x00000001
+-#define BR_V_SHIFT 0
+-#define BR_RES ~(BR_BA|BR_PS|BR_DECC|BR_WP|BR_MSEL|BR_V)
+-
+- __be32 or; /**< Base Register */
+-#define OR0 0x5004
+-#define OR1 0x500C
+-#define OR2 0x5014
+-#define OR3 0x501C
+-#define OR4 0x5024
+-#define OR5 0x502C
+-#define OR6 0x5034
+-#define OR7 0x503C
+-
+-#define OR_FCM_AM 0xFFFF8000
+-#define OR_FCM_AM_SHIFT 15
+-#define OR_FCM_BCTLD 0x00001000
+-#define OR_FCM_BCTLD_SHIFT 12
+-#define OR_FCM_PGS 0x00000400
+-#define OR_FCM_PGS_SHIFT 10
+-#define OR_FCM_CSCT 0x00000200
+-#define OR_FCM_CSCT_SHIFT 9
+-#define OR_FCM_CST 0x00000100
+-#define OR_FCM_CST_SHIFT 8
+-#define OR_FCM_CHT 0x00000080
+-#define OR_FCM_CHT_SHIFT 7
+-#define OR_FCM_SCY 0x00000070
+-#define OR_FCM_SCY_SHIFT 4
+-#define OR_FCM_SCY_1 0x00000010
+-#define OR_FCM_SCY_2 0x00000020
+-#define OR_FCM_SCY_3 0x00000030
+-#define OR_FCM_SCY_4 0x00000040
+-#define OR_FCM_SCY_5 0x00000050
+-#define OR_FCM_SCY_6 0x00000060
+-#define OR_FCM_SCY_7 0x00000070
+-#define OR_FCM_RST 0x00000008
+-#define OR_FCM_RST_SHIFT 3
+-#define OR_FCM_TRLX 0x00000004
+-#define OR_FCM_TRLX_SHIFT 2
+-#define OR_FCM_EHTR 0x00000002
+-#define OR_FCM_EHTR_SHIFT 1
+-};
+-
+-struct elbc_regs {
+- struct elbc_bank bank[8];
+- u8 res0[0x28];
+- __be32 mar; /**< UPM Address Register */
+- u8 res1[0x4];
+- __be32 mamr; /**< UPMA Mode Register */
+- __be32 mbmr; /**< UPMB Mode Register */
+- __be32 mcmr; /**< UPMC Mode Register */
+- u8 res2[0x8];
+- __be32 mrtpr; /**< Memory Refresh Timer Prescaler Register */
+- __be32 mdr; /**< UPM Data Register */
+- u8 res3[0x4];
+- __be32 lsor; /**< Special Operation Initiation Register */
+- __be32 lsdmr; /**< SDRAM Mode Register */
+- u8 res4[0x8];
+- __be32 lurt; /**< UPM Refresh Timer */
+- __be32 lsrt; /**< SDRAM Refresh Timer */
+- u8 res5[0x8];
+- __be32 ltesr; /**< Transfer Error Status Register */
+-#define LTESR_BM 0x80000000
+-#define LTESR_FCT 0x40000000
+-#define LTESR_PAR 0x20000000
+-#define LTESR_WP 0x04000000
+-#define LTESR_ATMW 0x00800000
+-#define LTESR_ATMR 0x00400000
+-#define LTESR_CS 0x00080000
+-#define LTESR_CC 0x00000001
+-#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
+- __be32 ltedr; /**< Transfer Error Disable Register */
+- __be32 lteir; /**< Transfer Error Interrupt Register */
+- __be32 lteatr; /**< Transfer Error Attributes Register */
+- __be32 ltear; /**< Transfer Error Address Register */
+- u8 res6[0xC];
+- __be32 lbcr; /**< Configuration Register */
+-#define LBCR_LDIS 0x80000000
+-#define LBCR_LDIS_SHIFT 31
+-#define LBCR_BCTLC 0x00C00000
+-#define LBCR_BCTLC_SHIFT 22
+-#define LBCR_AHD 0x00200000
+-#define LBCR_LPBSE 0x00020000
+-#define LBCR_LPBSE_SHIFT 17
+-#define LBCR_EPAR 0x00010000
+-#define LBCR_EPAR_SHIFT 16
+-#define LBCR_BMT 0x0000FF00
+-#define LBCR_BMT_SHIFT 8
+-#define LBCR_INIT 0x00040000
+- __be32 lcrr; /**< Clock Ratio Register */
+-#define LCRR_DBYP 0x80000000
+-#define LCRR_DBYP_SHIFT 31
+-#define LCRR_BUFCMDC 0x30000000
+-#define LCRR_BUFCMDC_SHIFT 28
+-#define LCRR_ECL 0x03000000
+-#define LCRR_ECL_SHIFT 24
+-#define LCRR_EADC 0x00030000
+-#define LCRR_EADC_SHIFT 16
+-#define LCRR_CLKDIV 0x0000000F
+-#define LCRR_CLKDIV_SHIFT 0
+- u8 res7[0x8];
+- __be32 fmr; /**< Flash Mode Register */
+-#define FMR_CWTO 0x0000F000
+-#define FMR_CWTO_SHIFT 12
+-#define FMR_BOOT 0x00000800
+-#define FMR_ECCM 0x00000100
+-#define FMR_AL 0x00000030
+-#define FMR_AL_SHIFT 4
+-#define FMR_OP 0x00000003
+-#define FMR_OP_SHIFT 0
+- __be32 fir; /**< Flash Instruction Register */
+-#define FIR_OP0 0xF0000000
+-#define FIR_OP0_SHIFT 28
+-#define FIR_OP1 0x0F000000
+-#define FIR_OP1_SHIFT 24
+-#define FIR_OP2 0x00F00000
+-#define FIR_OP2_SHIFT 20
+-#define FIR_OP3 0x000F0000
+-#define FIR_OP3_SHIFT 16
+-#define FIR_OP4 0x0000F000
+-#define FIR_OP4_SHIFT 12
+-#define FIR_OP5 0x00000F00
+-#define FIR_OP5_SHIFT 8
+-#define FIR_OP6 0x000000F0
+-#define FIR_OP6_SHIFT 4
+-#define FIR_OP7 0x0000000F
+-#define FIR_OP7_SHIFT 0
+-#define FIR_OP_NOP 0x0 /* No operation and end of sequence */
+-#define FIR_OP_CA 0x1 /* Issue current column address */
+-#define FIR_OP_PA 0x2 /* Issue current block+page address */
+-#define FIR_OP_UA 0x3 /* Issue user defined address */
+-#define FIR_OP_CM0 0x4 /* Issue command from FCR[CMD0] */
+-#define FIR_OP_CM1 0x5 /* Issue command from FCR[CMD1] */
+-#define FIR_OP_CM2 0x6 /* Issue command from FCR[CMD2] */
+-#define FIR_OP_CM3 0x7 /* Issue command from FCR[CMD3] */
+-#define FIR_OP_WB 0x8 /* Write FBCR bytes from FCM buffer */
+-#define FIR_OP_WS 0x9 /* Write 1 or 2 bytes from MDR[AS] */
+-#define FIR_OP_RB 0xA /* Read FBCR bytes to FCM buffer */
+-#define FIR_OP_RS 0xB /* Read 1 or 2 bytes to MDR[AS] */
+-#define FIR_OP_CW0 0xC /* Wait then issue FCR[CMD0] */
+-#define FIR_OP_CW1 0xD /* Wait then issue FCR[CMD1] */
+-#define FIR_OP_RBW 0xE /* Wait then read FBCR bytes */
+-#define FIR_OP_RSW 0xE /* Wait then read 1 or 2 bytes */
+- __be32 fcr; /**< Flash Command Register */
+-#define FCR_CMD0 0xFF000000
+-#define FCR_CMD0_SHIFT 24
+-#define FCR_CMD1 0x00FF0000
+-#define FCR_CMD1_SHIFT 16
+-#define FCR_CMD2 0x0000FF00
+-#define FCR_CMD2_SHIFT 8
+-#define FCR_CMD3 0x000000FF
+-#define FCR_CMD3_SHIFT 0
+- __be32 fbar; /**< Flash Block Address Register */
+-#define FBAR_BLK 0x00FFFFFF
+- __be32 fpar; /**< Flash Page Address Register */
+-#define FPAR_SP_PI 0x00007C00
+-#define FPAR_SP_PI_SHIFT 10
+-#define FPAR_SP_MS 0x00000200
+-#define FPAR_SP_CI 0x000001FF
+-#define FPAR_SP_CI_SHIFT 0
+-#define FPAR_LP_PI 0x0003F000
+-#define FPAR_LP_PI_SHIFT 12
+-#define FPAR_LP_MS 0x00000800
+-#define FPAR_LP_CI 0x000007FF
+-#define FPAR_LP_CI_SHIFT 0
+- __be32 fbcr; /**< Flash Byte Count Register */
+-#define FBCR_BC 0x00000FFF
+- u8 res11[0x8];
+- u8 res8[0xF00];
+-};
+-
+ struct fsl_elbc_ctrl;
+
+ /* mtd information per set */
+@@ -261,7 +66,7 @@ struct fsl_elbc_ctrl {
+
+ /* device info */
+ struct device *dev;
+- struct elbc_regs __iomem *regs;
++ struct fsl_lbc_regs __iomem *regs;
+ int irq;
+ wait_queue_head_t irq_wait;
+ unsigned int irq_status; /* status read from LTESR by irq handler */
+@@ -322,7 +127,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
+ struct nand_chip *chip = mtd->priv;
+ struct fsl_elbc_mtd *priv = chip->priv;
+ struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+- struct elbc_regs __iomem *lbc = ctrl->regs;
++ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ int buf_num;
+
+ ctrl->page = page_addr;
+@@ -363,7 +168,7 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
+ struct nand_chip *chip = mtd->priv;
+ struct fsl_elbc_mtd *priv = chip->priv;
+ struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+- struct elbc_regs __iomem *lbc = ctrl->regs;
++ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+
+ /* Setup the FMR[OP] to execute without write protection */
+ out_be32(&lbc->fmr, priv->fmr | 3);
+@@ -379,11 +184,11 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
+ in_be32(&lbc->fbar), in_be32(&lbc->fpar),
+ in_be32(&lbc->fbcr), priv->bank);
+
++ ctrl->irq_status = 0;
+ /* execute special operation */
+ out_be32(&lbc->lsor, priv->bank);
+
+ /* wait for FCM complete flag or timeout */
+- ctrl->irq_status = 0;
+ wait_event_timeout(ctrl->irq_wait, ctrl->irq_status,
+ FCM_TIMEOUT_MSECS * HZ/1000);
+ ctrl->status = ctrl->irq_status;
+@@ -406,7 +211,7 @@ static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
+ {
+ struct fsl_elbc_mtd *priv = chip->priv;
+ struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+- struct elbc_regs __iomem *lbc = ctrl->regs;
++ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+
+ if (priv->page_size) {
+ out_be32(&lbc->fir,
+@@ -439,7 +244,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
+ struct nand_chip *chip = mtd->priv;
+ struct fsl_elbc_mtd *priv = chip->priv;
+ struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+- struct elbc_regs __iomem *lbc = ctrl->regs;
++ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+
+ ctrl->use_mdr = 0;
+
+@@ -541,19 +346,20 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
+ ctrl->column = column;
+ ctrl->oob = 0;
+
+- fcr = (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT) |
+- (NAND_CMD_SEQIN << FCR_CMD2_SHIFT);
+-
+ if (priv->page_size) {
++ fcr = (NAND_CMD_SEQIN << FCR_CMD0_SHIFT) |
++ (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT);
++
+ out_be32(&lbc->fir,
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_CA << FIR_OP1_SHIFT) |
+ (FIR_OP_PA << FIR_OP2_SHIFT) |
+ (FIR_OP_WB << FIR_OP3_SHIFT) |
+ (FIR_OP_CW1 << FIR_OP4_SHIFT));
+-
+- fcr |= NAND_CMD_READ0 << FCR_CMD0_SHIFT;
+ } else {
++ fcr = (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT) |
++ (NAND_CMD_SEQIN << FCR_CMD2_SHIFT);
++
+ out_be32(&lbc->fir,
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_CM2 << FIR_OP1_SHIFT) |
+@@ -675,7 +481,7 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
+ struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+ unsigned int bufsize = mtd->writesize + mtd->oobsize;
+
+- if (len < 0) {
++ if (len <= 0) {
+ dev_err(ctrl->dev, "write_buf of %d bytes", len);
+ ctrl->status = 0;
+ return;
+@@ -690,6 +496,15 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
+ }
+
+ memcpy_toio(&ctrl->addr[ctrl->index], buf, len);
++ /*
++ * This is workaround for the weird elbc hangs during nand write,
++ * Scott Wood says: "...perhaps difference in how long it takes a
++ * write to make it through the localbus compared to a write to IMMR
++ * is causing problems, and sync isn't helping for some reason."
++ * Reading back the last byte helps though.
++ */
++ in_8(&ctrl->addr[ctrl->index] + len - 1);
++
+ ctrl->index += len;
+ }
+
+@@ -775,7 +590,7 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
+ {
+ struct fsl_elbc_mtd *priv = chip->priv;
+ struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+- struct elbc_regs __iomem *lbc = ctrl->regs;
++ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+
+ if (ctrl->status != LTESR_CC)
+ return NAND_STATUS_FAIL;
+@@ -807,7 +622,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
+ struct nand_chip *chip = mtd->priv;
+ struct fsl_elbc_mtd *priv = chip->priv;
+ struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+- struct elbc_regs __iomem *lbc = ctrl->regs;
++ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ unsigned int al;
+
+ /* calculate FMR Address Length field */
+@@ -861,7 +676,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
+ /* adjust Option Register and ECC to match Flash page size */
+ if (mtd->writesize == 512) {
+ priv->page_size = 0;
+- clrbits32(&lbc->bank[priv->bank].or, ~OR_FCM_PGS);
++ clrbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS);
+ } else if (mtd->writesize == 2048) {
+ priv->page_size = 1;
+ setbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS);
+@@ -882,11 +697,6 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
+ return -1;
+ }
+
+- /* The default u-boot configuration on MPC8313ERDB causes errors;
+- * more delay is needed. This should be safe for other boards
+- * as well.
+- */
+- setbits32(&lbc->bank[priv->bank].or, 0x70);
+ return 0;
+ }
+
+@@ -922,7 +732,7 @@ static void fsl_elbc_write_page(struct mtd_info *mtd,
+ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
+ {
+ struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+- struct elbc_regs __iomem *lbc = ctrl->regs;
++ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ struct nand_chip *chip = &priv->chip;
+
+ dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank);
+@@ -974,6 +784,8 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
+
+ nand_release(&priv->mtd);
+
++ kfree(priv->mtd.name);
++
+ if (priv->vbase)
+ iounmap(priv->vbase);
+
+@@ -986,7 +798,7 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
+ static int fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
+ struct device_node *node)
+ {
+- struct elbc_regs __iomem *lbc = ctrl->regs;
++ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ struct fsl_elbc_mtd *priv;
+ struct resource res;
+ #ifdef CONFIG_MTD_PARTITIONS
+@@ -1034,6 +846,12 @@ static int fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
+ goto err;
+ }
+
++ priv->mtd.name = kasprintf(GFP_KERNEL, "%x.flash", res.start);
++ if (!priv->mtd.name) {
++ ret = -ENOMEM;
++ goto err;
++ }
++
+ ret = fsl_elbc_chip_init(priv);
+ if (ret)
+ goto err;
+@@ -1083,7 +901,7 @@ err:
+
+ static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl)
+ {
+- struct elbc_regs __iomem *lbc = ctrl->regs;
++ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+
+ /* clear event registers */
+ setbits32(&lbc->ltesr, LTESR_NAND_MASK);
+@@ -1128,7 +946,7 @@ static int __devexit fsl_elbc_ctrl_remove(struct of_device *ofdev)
+ static irqreturn_t fsl_elbc_ctrl_irq(int irqno, void *data)
+ {
+ struct fsl_elbc_ctrl *ctrl = data;
+- struct elbc_regs __iomem *lbc = ctrl->regs;
++ struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+ __be32 status = in_be32(&lbc->ltesr) & LTESR_NAND_MASK;
+
+ if (status) {
+diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
+new file mode 100644
+index 0000000..1ebfd87
+--- /dev/null
++++ b/drivers/mtd/nand/fsl_upm.c
+@@ -0,0 +1,291 @@
++/*
++ * Freescale UPM NAND driver.
++ *
++ * Copyright © 2007-2008 MontaVista Software, Inc.
++ *
++ * Author: Anton Vorontsov <avorontsov at ru.mvista.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/kernel.h>
++#include <linux/module.h>
++#include <linux/mtd/nand.h>
++#include <linux/mtd/nand_ecc.h>
++#include <linux/mtd/partitions.h>
++#include <linux/mtd/mtd.h>
++#include <linux/of_platform.h>
++#include <linux/of_gpio.h>
++#include <linux/io.h>
++#include <asm/fsl_lbc.h>
++
++struct fsl_upm_nand {
++ struct device *dev;
++ struct mtd_info mtd;
++ struct nand_chip chip;
++ int last_ctrl;
++#ifdef CONFIG_MTD_PARTITIONS
++ struct mtd_partition *parts;
++#endif
++
++ struct fsl_upm upm;
++ uint8_t upm_addr_offset;
++ uint8_t upm_cmd_offset;
++ void __iomem *io_base;
++ int rnb_gpio;
++ const uint32_t *wait_pattern;
++ const uint32_t *wait_write;
++ int chip_delay;
++};
++
++#define to_fsl_upm_nand(mtd) container_of(mtd, struct fsl_upm_nand, mtd)
++
++static int fun_chip_ready(struct mtd_info *mtd)
++{
++ struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
++
++ if (gpio_get_value(fun->rnb_gpio))
++ return 1;
++
++ dev_vdbg(fun->dev, "busy\n");
++ return 0;
++}
++
++static void fun_wait_rnb(struct fsl_upm_nand *fun)
++{
++ int cnt = 1000000;
++
++ if (fun->rnb_gpio >= 0) {
++ while (--cnt && !fun_chip_ready(&fun->mtd))
++ cpu_relax();
++ }
++
++ if (!cnt)
++ dev_err(fun->dev, "tired waiting for RNB\n");
++}
++
++static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
++{
++ struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
++
++ if (!(ctrl & fun->last_ctrl)) {
++ fsl_upm_end_pattern(&fun->upm);
++
++ if (cmd == NAND_CMD_NONE)
++ return;
++
++ fun->last_ctrl = ctrl & (NAND_ALE | NAND_CLE);
++ }
++
++ if (ctrl & NAND_CTRL_CHANGE) {
++ if (ctrl & NAND_ALE)
++ fsl_upm_start_pattern(&fun->upm, fun->upm_addr_offset);
++ else if (ctrl & NAND_CLE)
++ fsl_upm_start_pattern(&fun->upm, fun->upm_cmd_offset);
++ }
++
++ fsl_upm_run_pattern(&fun->upm, fun->io_base, cmd);
++
++ if (fun->wait_pattern)
++ fun_wait_rnb(fun);
++}
++
++static uint8_t fun_read_byte(struct mtd_info *mtd)
++{
++ struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
++
++ return in_8(fun->chip.IO_ADDR_R);
++}
++
++static void fun_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
++{
++ struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
++ int i;
++
++ for (i = 0; i < len; i++)
++ buf[i] = in_8(fun->chip.IO_ADDR_R);
++}
++
++static void fun_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
++{
++ struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
++ int i;
++
++ for (i = 0; i < len; i++) {
++ out_8(fun->chip.IO_ADDR_W, buf[i]);
++ if (fun->wait_write)
++ fun_wait_rnb(fun);
++ }
++}
++
++static int __devinit fun_chip_init(struct fsl_upm_nand *fun)
++{
++ int ret;
++#ifdef CONFIG_MTD_PARTITIONS
++ static const char *part_types[] = { "cmdlinepart", NULL, };
++#endif
++
++ fun->chip.IO_ADDR_R = fun->io_base;
++ fun->chip.IO_ADDR_W = fun->io_base;
++ fun->chip.cmd_ctrl = fun_cmd_ctrl;
++ fun->chip.chip_delay = fun->chip_delay;
++ fun->chip.read_byte = fun_read_byte;
++ fun->chip.read_buf = fun_read_buf;
++ fun->chip.write_buf = fun_write_buf;
++ fun->chip.ecc.mode = NAND_ECC_SOFT;
++
++ if (fun->rnb_gpio >= 0)
++ fun->chip.dev_ready = fun_chip_ready;
++
++ fun->mtd.priv = &fun->chip;
++ fun->mtd.owner = THIS_MODULE;
++
++ ret = nand_scan(&fun->mtd, 1);
++ if (ret)
++ return ret;
++
++ fun->mtd.name = fun->dev->bus_id;
++
++#ifdef CONFIG_MTD_PARTITIONS
++ ret = parse_mtd_partitions(&fun->mtd, part_types, &fun->parts, 0);
++ if (ret > 0)
++ return add_mtd_partitions(&fun->mtd, fun->parts, ret);
++#endif
++ return add_mtd_device(&fun->mtd);
++}
++
++static int __devinit fun_probe(struct of_device *ofdev,
++ const struct of_device_id *ofid)
++{
++ struct fsl_upm_nand *fun;
++ struct resource io_res;
++ const uint32_t *prop;
++ int ret;
++ int size;
++
++ fun = kzalloc(sizeof(*fun), GFP_KERNEL);
++ if (!fun)
++ return -ENOMEM;
++
++ ret = of_address_to_resource(ofdev->node, 0, &io_res);
++ if (ret) {
++ dev_err(&ofdev->dev, "can't get IO base\n");
++ goto err1;
++ }
++
++ ret = fsl_upm_find(io_res.start, &fun->upm);
++ if (ret) {
++ dev_err(&ofdev->dev, "can't find UPM\n");
++ goto err1;
++ }
++
++ prop = of_get_property(ofdev->node, "fsl,upm-addr-offset", &size);
++ if (!prop || size != sizeof(uint32_t)) {
++ dev_err(&ofdev->dev, "can't get UPM address offset\n");
++ ret = -EINVAL;
++ goto err2;
++ }
++ fun->upm_addr_offset = *prop;
++
++ prop = of_get_property(ofdev->node, "fsl,upm-cmd-offset", &size);
++ if (!prop || size != sizeof(uint32_t)) {
++ dev_err(&ofdev->dev, "can't get UPM command offset\n");
++ ret = -EINVAL;
++ goto err2;
++ }
++ fun->upm_cmd_offset = *prop;
++
++ fun->rnb_gpio = of_get_gpio(ofdev->node, 0);
++ if (fun->rnb_gpio >= 0) {
++ ret = gpio_request(fun->rnb_gpio, ofdev->dev.bus_id);
++ if (ret) {
++ dev_err(&ofdev->dev, "can't request RNB gpio\n");
++ goto err2;
++ }
++ gpio_direction_input(fun->rnb_gpio);
++ } else if (fun->rnb_gpio == -EINVAL) {
++ dev_err(&ofdev->dev, "specified RNB gpio is invalid\n");
++ goto err2;
++ }
++
++ fun->io_base = devm_ioremap_nocache(&ofdev->dev, io_res.start,
++ io_res.end - io_res.start + 1);
++ if (!fun->io_base) {
++ ret = -ENOMEM;
++ goto err2;
++ }
++
++ fun->dev = &ofdev->dev;
++ fun->last_ctrl = NAND_CLE;
++ fun->wait_pattern = of_get_property(ofdev->node, "fsl,wait-pattern",
++ NULL);
++ fun->wait_write = of_get_property(ofdev->node, "fsl,wait-write", NULL);
++
++ prop = of_get_property(ofdev->node, "chip-delay", NULL);
++ if (prop)
++ fun->chip_delay = *prop;
++ else
++ fun->chip_delay = 50;
++
++ ret = fun_chip_init(fun);
++ if (ret)
++ goto err2;
++
++ dev_set_drvdata(&ofdev->dev, fun);
++
++ return 0;
++err2:
++ if (fun->rnb_gpio >= 0)
++ gpio_free(fun->rnb_gpio);
++err1:
++ kfree(fun);
++
++ return ret;
++}
++
++static int __devexit fun_remove(struct of_device *ofdev)
++{
++ struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev);
++
++ nand_release(&fun->mtd);
++
++ if (fun->rnb_gpio >= 0)
++ gpio_free(fun->rnb_gpio);
++
++ kfree(fun);
++
++ return 0;
++}
++
++static struct of_device_id of_fun_match[] = {
++ { .compatible = "fsl,upm-nand" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, of_fun_match);
++
++static struct of_platform_driver of_fun_driver = {
++ .name = "fsl,upm-nand",
++ .match_table = of_fun_match,
++ .probe = fun_probe,
++ .remove = __devexit_p(fun_remove),
++};
++
++static int __init fun_module_init(void)
++{
++ return of_register_platform_driver(&of_fun_driver);
++}
++module_init(fun_module_init);
++
++static void __exit fun_module_exit(void)
++{
++ of_unregister_platform_driver(&of_fun_driver);
++}
++module_exit(fun_module_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Anton Vorontsov <avorontsov at ru.mvista.com>");
++MODULE_DESCRIPTION("Driver for NAND chips working through Freescale "
++ "LocalBus User-Programmable Machine");
+diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
+index 7acb1a0..ba1bdf7 100644
+--- a/drivers/mtd/nand/nand_base.c
++++ b/drivers/mtd/nand/nand_base.c
+@@ -2229,6 +2229,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
+ {
+ struct nand_flash_dev *type = NULL;
+ int i, dev_id, maf_idx;
++ int tmp_id, tmp_manf;
+
+ /* Select the device */
+ chip->select_chip(mtd, 0);
+@@ -2240,6 +2241,26 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
+ *maf_id = chip->read_byte(mtd);
+ dev_id = chip->read_byte(mtd);
+
++ /* Try again to make sure, as some systems the bus-hold or other
++ * interface concerns can cause random data which looks like a
++ * possibly credible NAND flash to appear. If the two results do
++ * not match, ignore the device completely.
++ */
++
++ chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
++
++ /* Read manufacturer and device IDs */
++
++ tmp_manf = chip->read_byte(mtd);
++ tmp_id = chip->read_byte(mtd);
++
++ if (tmp_manf != *maf_id || tmp_id != dev_id) {
++ printk(KERN_INFO "%s: second ID read did not match "
++ "%02x,%02x against %02x,%02x\n", __func__,
++ *maf_id, dev_id, tmp_manf, tmp_id);
++ return ERR_PTR(-ENODEV);
++ }
++
+ /* Lookup the flash id */
+ for (i = 0; nand_flash_ids[i].name != NULL; i++) {
+ if (dev_id == nand_flash_ids[i].id) {
+diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
+index 1c0e89f..955959e 100644
+--- a/drivers/mtd/nand/ndfc.c
++++ b/drivers/mtd/nand/ndfc.c
+@@ -317,3 +317,5 @@ module_exit(ndfc_nand_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Thomas Gleixner <tglx at linutronix.de>");
+ MODULE_DESCRIPTION("Platform driver for NDFC");
++MODULE_ALIAS("platform:ndfc-chip");
++MODULE_ALIAS("platform:ndfc-nand");
+diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c
+index 9162cca..59e05a1 100644
+--- a/drivers/mtd/nand/orion_nand.c
++++ b/drivers/mtd/nand/orion_nand.c
+@@ -18,8 +18,8 @@
+ #include <linux/mtd/partitions.h>
+ #include <asm/io.h>
+ #include <asm/sizes.h>
+-#include <asm/arch/platform.h>
+ #include <asm/arch/hardware.h>
++#include <asm/plat-orion/orion_nand.h>
+
+ #ifdef CONFIG_MTD_CMDLINE_PARTS
+ static const char *part_probes[] = { "cmdlinepart", NULL };
+@@ -169,3 +169,4 @@ module_exit(orion_nand_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Tzachi Perelstein");
+ MODULE_DESCRIPTION("NAND glue for Orion platforms");
++MODULE_ALIAS("platform:orion_nand");
+diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c
+index f6d5c2a..f674c54 100644
+--- a/drivers/mtd/nand/plat_nand.c
++++ b/drivers/mtd/nand/plat_nand.c
+@@ -54,6 +54,7 @@ static int __init plat_nand_probe(struct platform_device *pdev)
+ data->chip.priv = &data;
+ data->mtd.priv = &data->chip;
+ data->mtd.owner = THIS_MODULE;
++ data->mtd.name = pdev->dev.bus_id;
+
+ data->chip.IO_ADDR_R = data->io_base;
+ data->chip.IO_ADDR_W = data->io_base;
+@@ -150,3 +151,4 @@ module_exit(plat_nand_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Vitaly Wool");
+ MODULE_DESCRIPTION("Simple generic NAND driver");
++MODULE_ALIAS("platform:gen_nand");
+diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
+new file mode 100644
+index 0000000..fceb468
+--- /dev/null
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -0,0 +1,1249 @@
++/*
++ * drivers/mtd/nand/pxa3xx_nand.c
++ *
++ * Copyright © 2005 Intel Corporation
++ * Copyright © 2006 Marvell International Ltd.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/dma-mapping.h>
++#include <linux/delay.h>
++#include <linux/clk.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/nand.h>
++#include <linux/mtd/partitions.h>
++#include <linux/io.h>
++#include <linux/irq.h>
++#include <asm/dma.h>
++
++#include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa3xx_nand.h>
++
++#define CHIP_DELAY_TIMEOUT (2 * HZ/10)
++
++/* registers and bit definitions */
++#define NDCR (0x00) /* Control register */
++#define NDTR0CS0 (0x04) /* Timing Parameter 0 for CS0 */
++#define NDTR1CS0 (0x0C) /* Timing Parameter 1 for CS0 */
++#define NDSR (0x14) /* Status Register */
++#define NDPCR (0x18) /* Page Count Register */
++#define NDBDR0 (0x1C) /* Bad Block Register 0 */
++#define NDBDR1 (0x20) /* Bad Block Register 1 */
++#define NDDB (0x40) /* Data Buffer */
++#define NDCB0 (0x48) /* Command Buffer0 */
++#define NDCB1 (0x4C) /* Command Buffer1 */
++#define NDCB2 (0x50) /* Command Buffer2 */
++
++#define NDCR_SPARE_EN (0x1 << 31)
++#define NDCR_ECC_EN (0x1 << 30)
++#define NDCR_DMA_EN (0x1 << 29)
++#define NDCR_ND_RUN (0x1 << 28)
++#define NDCR_DWIDTH_C (0x1 << 27)
++#define NDCR_DWIDTH_M (0x1 << 26)
++#define NDCR_PAGE_SZ (0x1 << 24)
++#define NDCR_NCSX (0x1 << 23)
++#define NDCR_ND_MODE (0x3 << 21)
++#define NDCR_NAND_MODE (0x0)
++#define NDCR_CLR_PG_CNT (0x1 << 20)
++#define NDCR_CLR_ECC (0x1 << 19)
++#define NDCR_RD_ID_CNT_MASK (0x7 << 16)
++#define NDCR_RD_ID_CNT(x) (((x) << 16) & NDCR_RD_ID_CNT_MASK)
++
++#define NDCR_RA_START (0x1 << 15)
++#define NDCR_PG_PER_BLK (0x1 << 14)
++#define NDCR_ND_ARB_EN (0x1 << 12)
++
++#define NDSR_MASK (0xfff)
++#define NDSR_RDY (0x1 << 11)
++#define NDSR_CS0_PAGED (0x1 << 10)
++#define NDSR_CS1_PAGED (0x1 << 9)
++#define NDSR_CS0_CMDD (0x1 << 8)
++#define NDSR_CS1_CMDD (0x1 << 7)
++#define NDSR_CS0_BBD (0x1 << 6)
++#define NDSR_CS1_BBD (0x1 << 5)
++#define NDSR_DBERR (0x1 << 4)
++#define NDSR_SBERR (0x1 << 3)
++#define NDSR_WRDREQ (0x1 << 2)
++#define NDSR_RDDREQ (0x1 << 1)
++#define NDSR_WRCMDREQ (0x1)
++
++#define NDCB0_AUTO_RS (0x1 << 25)
++#define NDCB0_CSEL (0x1 << 24)
++#define NDCB0_CMD_TYPE_MASK (0x7 << 21)
++#define NDCB0_CMD_TYPE(x) (((x) << 21) & NDCB0_CMD_TYPE_MASK)
++#define NDCB0_NC (0x1 << 20)
++#define NDCB0_DBC (0x1 << 19)
++#define NDCB0_ADDR_CYC_MASK (0x7 << 16)
++#define NDCB0_ADDR_CYC(x) (((x) << 16) & NDCB0_ADDR_CYC_MASK)
++#define NDCB0_CMD2_MASK (0xff << 8)
++#define NDCB0_CMD1_MASK (0xff)
++#define NDCB0_ADDR_CYC_SHIFT (16)
++
++/* dma-able I/O address for the NAND data and commands */
++#define NDCB0_DMA_ADDR (0x43100048)
++#define NDDB_DMA_ADDR (0x43100040)
++
++/* macros for registers read/write */
++#define nand_writel(info, off, val) \
++ __raw_writel((val), (info)->mmio_base + (off))
++
++#define nand_readl(info, off) \
++ __raw_readl((info)->mmio_base + (off))
++
++/* error code and state */
++enum {
++ ERR_NONE = 0,
++ ERR_DMABUSERR = -1,
++ ERR_SENDCMD = -2,
++ ERR_DBERR = -3,
++ ERR_BBERR = -4,
++};
++
++enum {
++ STATE_READY = 0,
++ STATE_CMD_HANDLE,
++ STATE_DMA_READING,
++ STATE_DMA_WRITING,
++ STATE_DMA_DONE,
++ STATE_PIO_READING,
++ STATE_PIO_WRITING,
++};
++
++struct pxa3xx_nand_timing {
++ unsigned int tCH; /* Enable signal hold time */
++ unsigned int tCS; /* Enable signal setup time */
++ unsigned int tWH; /* ND_nWE high duration */
++ unsigned int tWP; /* ND_nWE pulse time */
++ unsigned int tRH; /* ND_nRE high duration */
++ unsigned int tRP; /* ND_nRE pulse width */
++ unsigned int tR; /* ND_nWE high to ND_nRE low for read */
++ unsigned int tWHR; /* ND_nWE high to ND_nRE low for status read */
++ unsigned int tAR; /* ND_ALE low to ND_nRE low delay */
++};
++
++struct pxa3xx_nand_cmdset {
++ uint16_t read1;
++ uint16_t read2;
++ uint16_t program;
++ uint16_t read_status;
++ uint16_t read_id;
++ uint16_t erase;
++ uint16_t reset;
++ uint16_t lock;
++ uint16_t unlock;
++ uint16_t lock_status;
++};
++
++struct pxa3xx_nand_flash {
++ struct pxa3xx_nand_timing *timing; /* NAND Flash timing */
++ struct pxa3xx_nand_cmdset *cmdset;
++
++ uint32_t page_per_block;/* Pages per block (PG_PER_BLK) */
++ uint32_t page_size; /* Page size in bytes (PAGE_SZ) */
++ uint32_t flash_width; /* Width of Flash memory (DWIDTH_M) */
++ uint32_t dfc_width; /* Width of flash controller(DWIDTH_C) */
++ uint32_t num_blocks; /* Number of physical blocks in Flash */
++ uint32_t chip_id;
++
++ /* NOTE: these are automatically calculated, do not define */
++ size_t oob_size;
++ size_t read_id_bytes;
++
++ unsigned int col_addr_cycles;
++ unsigned int row_addr_cycles;
++};
++
++struct pxa3xx_nand_info {
++ struct nand_chip nand_chip;
++
++ struct platform_device *pdev;
++ struct pxa3xx_nand_flash *flash_info;
++
++ struct clk *clk;
++ void __iomem *mmio_base;
++
++ unsigned int buf_start;
++ unsigned int buf_count;
++
++ /* DMA information */
++ int drcmr_dat;
++ int drcmr_cmd;
++
++ unsigned char *data_buff;
++ dma_addr_t data_buff_phys;
++ size_t data_buff_size;
++ int data_dma_ch;
++ struct pxa_dma_desc *data_desc;
++ dma_addr_t data_desc_addr;
++
++ uint32_t reg_ndcr;
++
++ /* saved column/page_addr during CMD_SEQIN */
++ int seqin_column;
++ int seqin_page_addr;
++
++ /* relate to the command */
++ unsigned int state;
++
++ int use_ecc; /* use HW ECC ? */
++ int use_dma; /* use DMA ? */
++
++ size_t data_size; /* data size in FIFO */
++ int retcode;
++ struct completion cmd_complete;
++
++ /* generated NDCBx register values */
++ uint32_t ndcb0;
++ uint32_t ndcb1;
++ uint32_t ndcb2;
++};
++
++static int use_dma = 1;
++module_param(use_dma, bool, 0444);
++MODULE_PARM_DESC(use_dma, "enable DMA for data transfering to/from NAND HW");
++
++static struct pxa3xx_nand_cmdset smallpage_cmdset = {
++ .read1 = 0x0000,
++ .read2 = 0x0050,
++ .program = 0x1080,
++ .read_status = 0x0070,
++ .read_id = 0x0090,
++ .erase = 0xD060,
++ .reset = 0x00FF,
++ .lock = 0x002A,
++ .unlock = 0x2423,
++ .lock_status = 0x007A,
++};
++
++static struct pxa3xx_nand_cmdset largepage_cmdset = {
++ .read1 = 0x3000,
++ .read2 = 0x0050,
++ .program = 0x1080,
++ .read_status = 0x0070,
++ .read_id = 0x0090,
++ .erase = 0xD060,
++ .reset = 0x00FF,
++ .lock = 0x002A,
++ .unlock = 0x2423,
++ .lock_status = 0x007A,
++};
++
++static struct pxa3xx_nand_timing samsung512MbX16_timing = {
++ .tCH = 10,
++ .tCS = 0,
++ .tWH = 20,
++ .tWP = 40,
++ .tRH = 30,
++ .tRP = 40,
++ .tR = 11123,
++ .tWHR = 110,
++ .tAR = 10,
++};
++
++static struct pxa3xx_nand_flash samsung512MbX16 = {
++ .timing = &samsung512MbX16_timing,
++ .cmdset = &smallpage_cmdset,
++ .page_per_block = 32,
++ .page_size = 512,
++ .flash_width = 16,
++ .dfc_width = 16,
++ .num_blocks = 4096,
++ .chip_id = 0x46ec,
++};
++
++static struct pxa3xx_nand_timing micron_timing = {
++ .tCH = 10,
++ .tCS = 25,
++ .tWH = 15,
++ .tWP = 25,
++ .tRH = 15,
++ .tRP = 25,
++ .tR = 25000,
++ .tWHR = 60,
++ .tAR = 10,
++};
++
++static struct pxa3xx_nand_flash micron1GbX8 = {
++ .timing = µn_timing,
++ .cmdset = &largepage_cmdset,
++ .page_per_block = 64,
++ .page_size = 2048,
++ .flash_width = 8,
++ .dfc_width = 8,
++ .num_blocks = 1024,
++ .chip_id = 0xa12c,
++};
++
++static struct pxa3xx_nand_flash micron1GbX16 = {
++ .timing = µn_timing,
++ .cmdset = &largepage_cmdset,
++ .page_per_block = 64,
++ .page_size = 2048,
++ .flash_width = 16,
++ .dfc_width = 16,
++ .num_blocks = 1024,
++ .chip_id = 0xb12c,
++};
++
++static struct pxa3xx_nand_flash *builtin_flash_types[] = {
++ &samsung512MbX16,
++ µn1GbX8,
++ µn1GbX16,
++};
++
++#define NDTR0_tCH(c) (min((c), 7) << 19)
++#define NDTR0_tCS(c) (min((c), 7) << 16)
++#define NDTR0_tWH(c) (min((c), 7) << 11)
++#define NDTR0_tWP(c) (min((c), 7) << 8)
++#define NDTR0_tRH(c) (min((c), 7) << 3)
++#define NDTR0_tRP(c) (min((c), 7) << 0)
++
++#define NDTR1_tR(c) (min((c), 65535) << 16)
++#define NDTR1_tWHR(c) (min((c), 15) << 4)
++#define NDTR1_tAR(c) (min((c), 15) << 0)
++
++/* convert nano-seconds to nand flash controller clock cycles */
++#define ns2cycle(ns, clk) (int)(((ns) * (clk / 1000000) / 1000) + 1)
++
++static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
++ struct pxa3xx_nand_timing *t)
++{
++ unsigned long nand_clk = clk_get_rate(info->clk);
++ uint32_t ndtr0, ndtr1;
++
++ ndtr0 = NDTR0_tCH(ns2cycle(t->tCH, nand_clk)) |
++ NDTR0_tCS(ns2cycle(t->tCS, nand_clk)) |
++ NDTR0_tWH(ns2cycle(t->tWH, nand_clk)) |
++ NDTR0_tWP(ns2cycle(t->tWP, nand_clk)) |
++ NDTR0_tRH(ns2cycle(t->tRH, nand_clk)) |
++ NDTR0_tRP(ns2cycle(t->tRP, nand_clk));
++
++ ndtr1 = NDTR1_tR(ns2cycle(t->tR, nand_clk)) |
++ NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) |
++ NDTR1_tAR(ns2cycle(t->tAR, nand_clk));
++
++ nand_writel(info, NDTR0CS0, ndtr0);
++ nand_writel(info, NDTR1CS0, ndtr1);
++}
++
++#define WAIT_EVENT_TIMEOUT 10
++
++static int wait_for_event(struct pxa3xx_nand_info *info, uint32_t event)
++{
++ int timeout = WAIT_EVENT_TIMEOUT;
++ uint32_t ndsr;
++
++ while (timeout--) {
++ ndsr = nand_readl(info, NDSR) & NDSR_MASK;
++ if (ndsr & event) {
++ nand_writel(info, NDSR, ndsr);
++ return 0;
++ }
++ udelay(10);
++ }
++
++ return -ETIMEDOUT;
++}
++
++static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
++ uint16_t cmd, int column, int page_addr)
++{
++ struct pxa3xx_nand_flash *f = info->flash_info;
++ struct pxa3xx_nand_cmdset *cmdset = f->cmdset;
++
++ /* calculate data size */
++ switch (f->page_size) {
++ case 2048:
++ info->data_size = (info->use_ecc) ? 2088 : 2112;
++ break;
++ case 512:
++ info->data_size = (info->use_ecc) ? 520 : 528;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ /* generate values for NDCBx registers */
++ info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
++ info->ndcb1 = 0;
++ info->ndcb2 = 0;
++ info->ndcb0 |= NDCB0_ADDR_CYC(f->row_addr_cycles + f->col_addr_cycles);
++
++ if (f->col_addr_cycles == 2) {
++ /* large block, 2 cycles for column address
++ * row address starts from 3rd cycle
++ */
++ info->ndcb1 |= (page_addr << 16) | (column & 0xffff);
++ if (f->row_addr_cycles == 3)
++ info->ndcb2 = (page_addr >> 16) & 0xff;
++ } else
++ /* small block, 1 cycles for column address
++ * row address starts from 2nd cycle
++ */
++ info->ndcb1 = (page_addr << 8) | (column & 0xff);
++
++ if (cmd == cmdset->program)
++ info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS;
++
++ return 0;
++}
++
++static int prepare_erase_cmd(struct pxa3xx_nand_info *info,
++ uint16_t cmd, int page_addr)
++{
++ info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
++ info->ndcb0 |= NDCB0_CMD_TYPE(2) | NDCB0_AUTO_RS | NDCB0_ADDR_CYC(3);
++ info->ndcb1 = page_addr;
++ info->ndcb2 = 0;
++ return 0;
++}
++
++static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd)
++{
++ struct pxa3xx_nand_cmdset *cmdset = info->flash_info->cmdset;
++
++ info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
++ info->ndcb1 = 0;
++ info->ndcb2 = 0;
++
++ if (cmd == cmdset->read_id) {
++ info->ndcb0 |= NDCB0_CMD_TYPE(3);
++ info->data_size = 8;
++ } else if (cmd == cmdset->read_status) {
++ info->ndcb0 |= NDCB0_CMD_TYPE(4);
++ info->data_size = 8;
++ } else if (cmd == cmdset->reset || cmd == cmdset->lock ||
++ cmd == cmdset->unlock) {
++ info->ndcb0 |= NDCB0_CMD_TYPE(5);
++ } else
++ return -EINVAL;
++
++ return 0;
++}
++
++static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
++{
++ uint32_t ndcr;
++
++ ndcr = nand_readl(info, NDCR);
++ nand_writel(info, NDCR, ndcr & ~int_mask);
++}
++
++static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
++{
++ uint32_t ndcr;
++
++ ndcr = nand_readl(info, NDCR);
++ nand_writel(info, NDCR, ndcr | int_mask);
++}
++
++/* NOTE: it is a must to set ND_RUN firstly, then write command buffer
++ * otherwise, it does not work
++ */
++static int write_cmd(struct pxa3xx_nand_info *info)
++{
++ uint32_t ndcr;
++
++ /* clear status bits and run */
++ nand_writel(info, NDSR, NDSR_MASK);
++
++ ndcr = info->reg_ndcr;
++
++ ndcr |= info->use_ecc ? NDCR_ECC_EN : 0;
++ ndcr |= info->use_dma ? NDCR_DMA_EN : 0;
++ ndcr |= NDCR_ND_RUN;
++
++ nand_writel(info, NDCR, ndcr);
++
++ if (wait_for_event(info, NDSR_WRCMDREQ)) {
++ printk(KERN_ERR "timed out writing command\n");
++ return -ETIMEDOUT;
++ }
++
++ nand_writel(info, NDCB0, info->ndcb0);
++ nand_writel(info, NDCB0, info->ndcb1);
++ nand_writel(info, NDCB0, info->ndcb2);
++ return 0;
++}
++
++static int handle_data_pio(struct pxa3xx_nand_info *info)
++{
++ int ret, timeout = CHIP_DELAY_TIMEOUT;
++
++ switch (info->state) {
++ case STATE_PIO_WRITING:
++ __raw_writesl(info->mmio_base + NDDB, info->data_buff,
++ info->data_size << 2);
++
++ enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
++
++ ret = wait_for_completion_timeout(&info->cmd_complete, timeout);
++ if (!ret) {
++ printk(KERN_ERR "program command time out\n");
++ return -1;
++ }
++ break;
++ case STATE_PIO_READING:
++ __raw_readsl(info->mmio_base + NDDB, info->data_buff,
++ info->data_size << 2);
++ break;
++ default:
++ printk(KERN_ERR "%s: invalid state %d\n", __func__,
++ info->state);
++ return -EINVAL;
++ }
++
++ info->state = STATE_READY;
++ return 0;
++}
++
++static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out)
++{
++ struct pxa_dma_desc *desc = info->data_desc;
++ int dma_len = ALIGN(info->data_size, 32);
++
++ desc->ddadr = DDADR_STOP;
++ desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len;
++
++ if (dir_out) {
++ desc->dsadr = info->data_buff_phys;
++ desc->dtadr = NDDB_DMA_ADDR;
++ desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG;
++ } else {
++ desc->dtadr = info->data_buff_phys;
++ desc->dsadr = NDDB_DMA_ADDR;
++ desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC;
++ }
++
++ DRCMR(info->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch;
++ DDADR(info->data_dma_ch) = info->data_desc_addr;
++ DCSR(info->data_dma_ch) |= DCSR_RUN;
++}
++
++static void pxa3xx_nand_data_dma_irq(int channel, void *data)
++{
++ struct pxa3xx_nand_info *info = data;
++ uint32_t dcsr;
++
++ dcsr = DCSR(channel);
++ DCSR(channel) = dcsr;
++
++ if (dcsr & DCSR_BUSERR) {
++ info->retcode = ERR_DMABUSERR;
++ complete(&info->cmd_complete);
++ }
++
++ if (info->state == STATE_DMA_WRITING) {
++ info->state = STATE_DMA_DONE;
++ enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
++ } else {
++ info->state = STATE_READY;
++ complete(&info->cmd_complete);
++ }
++}
++
++static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
++{
++ struct pxa3xx_nand_info *info = devid;
++ unsigned int status;
++
++ status = nand_readl(info, NDSR);
++
++ if (status & (NDSR_RDDREQ | NDSR_DBERR)) {
++ if (status & NDSR_DBERR)
++ info->retcode = ERR_DBERR;
++
++ disable_int(info, NDSR_RDDREQ | NDSR_DBERR);
++
++ if (info->use_dma) {
++ info->state = STATE_DMA_READING;
++ start_data_dma(info, 0);
++ } else {
++ info->state = STATE_PIO_READING;
++ complete(&info->cmd_complete);
++ }
++ } else if (status & NDSR_WRDREQ) {
++ disable_int(info, NDSR_WRDREQ);
++ if (info->use_dma) {
++ info->state = STATE_DMA_WRITING;
++ start_data_dma(info, 1);
++ } else {
++ info->state = STATE_PIO_WRITING;
++ complete(&info->cmd_complete);
++ }
++ } else if (status & (NDSR_CS0_BBD | NDSR_CS0_CMDD)) {
++ if (status & NDSR_CS0_BBD)
++ info->retcode = ERR_BBERR;
++
++ disable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
++ info->state = STATE_READY;
++ complete(&info->cmd_complete);
++ }
++ nand_writel(info, NDSR, status);
++ return IRQ_HANDLED;
++}
++
++static int pxa3xx_nand_do_cmd(struct pxa3xx_nand_info *info, uint32_t event)
++{
++ uint32_t ndcr;
++ int ret, timeout = CHIP_DELAY_TIMEOUT;
++
++ if (write_cmd(info)) {
++ info->retcode = ERR_SENDCMD;
++ goto fail_stop;
++ }
++
++ info->state = STATE_CMD_HANDLE;
++
++ enable_int(info, event);
++
++ ret = wait_for_completion_timeout(&info->cmd_complete, timeout);
++ if (!ret) {
++ printk(KERN_ERR "command execution timed out\n");
++ info->retcode = ERR_SENDCMD;
++ goto fail_stop;
++ }
++
++ if (info->use_dma == 0 && info->data_size > 0)
++ if (handle_data_pio(info))
++ goto fail_stop;
++
++ return 0;
++
++fail_stop:
++ ndcr = nand_readl(info, NDCR);
++ nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
++ udelay(10);
++ return -ETIMEDOUT;
++}
++
++static int pxa3xx_nand_dev_ready(struct mtd_info *mtd)
++{
++ struct pxa3xx_nand_info *info = mtd->priv;
++ return (nand_readl(info, NDSR) & NDSR_RDY) ? 1 : 0;
++}
++
++static inline int is_buf_blank(uint8_t *buf, size_t len)
++{
++ for (; len > 0; len--)
++ if (*buf++ != 0xff)
++ return 0;
++ return 1;
++}
++
++static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
++ int column, int page_addr)
++{
++ struct pxa3xx_nand_info *info = mtd->priv;
++ struct pxa3xx_nand_flash *flash_info = info->flash_info;
++ struct pxa3xx_nand_cmdset *cmdset = flash_info->cmdset;
++ int ret;
++
++ info->use_dma = (use_dma) ? 1 : 0;
++ info->use_ecc = 0;
++ info->data_size = 0;
++ info->state = STATE_READY;
++
++ init_completion(&info->cmd_complete);
++
++ switch (command) {
++ case NAND_CMD_READOOB:
++ /* disable HW ECC to get all the OOB data */
++ info->buf_count = mtd->writesize + mtd->oobsize;
++ info->buf_start = mtd->writesize + column;
++
++ if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr))
++ break;
++
++ pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR);
++
++ /* We only are OOB, so if the data has error, does not matter */
++ if (info->retcode == ERR_DBERR)
++ info->retcode = ERR_NONE;
++ break;
++
++ case NAND_CMD_READ0:
++ info->use_ecc = 1;
++ info->retcode = ERR_NONE;
++ info->buf_start = column;
++ info->buf_count = mtd->writesize + mtd->oobsize;
++ memset(info->data_buff, 0xFF, info->buf_count);
++
++ if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr))
++ break;
++
++ pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR);
++
++ if (info->retcode == ERR_DBERR) {
++ /* for blank page (all 0xff), HW will calculate its ECC as
++ * 0, which is different from the ECC information within
++ * OOB, ignore such double bit errors
++ */
++ if (is_buf_blank(info->data_buff, mtd->writesize))
++ info->retcode = ERR_NONE;
++ }
++ break;
++ case NAND_CMD_SEQIN:
++ info->buf_start = column;
++ info->buf_count = mtd->writesize + mtd->oobsize;
++ memset(info->data_buff, 0xff, info->buf_count);
++
++ /* save column/page_addr for next CMD_PAGEPROG */
++ info->seqin_column = column;
++ info->seqin_page_addr = page_addr;
++ break;
++ case NAND_CMD_PAGEPROG:
++ info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 : 1;
++
++ if (prepare_read_prog_cmd(info, cmdset->program,
++ info->seqin_column, info->seqin_page_addr))
++ break;
++
++ pxa3xx_nand_do_cmd(info, NDSR_WRDREQ);
++ break;
++ case NAND_CMD_ERASE1:
++ if (prepare_erase_cmd(info, cmdset->erase, page_addr))
++ break;
++
++ pxa3xx_nand_do_cmd(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
++ break;
++ case NAND_CMD_ERASE2:
++ break;
++ case NAND_CMD_READID:
++ case NAND_CMD_STATUS:
++ info->use_dma = 0; /* force PIO read */
++ info->buf_start = 0;
++ info->buf_count = (command == NAND_CMD_READID) ?
++ flash_info->read_id_bytes : 1;
++
++ if (prepare_other_cmd(info, (command == NAND_CMD_READID) ?
++ cmdset->read_id : cmdset->read_status))
++ break;
++
++ pxa3xx_nand_do_cmd(info, NDSR_RDDREQ);
++ break;
++ case NAND_CMD_RESET:
++ if (prepare_other_cmd(info, cmdset->reset))
++ break;
++
++ ret = pxa3xx_nand_do_cmd(info, NDSR_CS0_CMDD);
++ if (ret == 0) {
++ int timeout = 2;
++ uint32_t ndcr;
++
++ while (timeout--) {
++ if (nand_readl(info, NDSR) & NDSR_RDY)
++ break;
++ msleep(10);
++ }
++
++ ndcr = nand_readl(info, NDCR);
++ nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
++ }
++ break;
++ default:
++ printk(KERN_ERR "non-supported command.\n");
++ break;
++ }
++
++ if (info->retcode == ERR_DBERR) {
++ printk(KERN_ERR "double bit error @ page %08x\n", page_addr);
++ info->retcode = ERR_NONE;
++ }
++}
++
++static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
++{
++ struct pxa3xx_nand_info *info = mtd->priv;
++ char retval = 0xFF;
++
++ if (info->buf_start < info->buf_count)
++ /* Has just send a new command? */
++ retval = info->data_buff[info->buf_start++];
++
++ return retval;
++}
++
++static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
++{
++ struct pxa3xx_nand_info *info = mtd->priv;
++ u16 retval = 0xFFFF;
++
++ if (!(info->buf_start & 0x01) && info->buf_start < info->buf_count) {
++ retval = *((u16 *)(info->data_buff+info->buf_start));
++ info->buf_start += 2;
++ }
++ return retval;
++}
++
++static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
++{
++ struct pxa3xx_nand_info *info = mtd->priv;
++ int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
++
++ memcpy(buf, info->data_buff + info->buf_start, real_len);
++ info->buf_start += real_len;
++}
++
++static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
++ const uint8_t *buf, int len)
++{
++ struct pxa3xx_nand_info *info = mtd->priv;
++ int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
++
++ memcpy(info->data_buff + info->buf_start, buf, real_len);
++ info->buf_start += real_len;
++}
++
++static int pxa3xx_nand_verify_buf(struct mtd_info *mtd,
++ const uint8_t *buf, int len)
++{
++ return 0;
++}
++
++static void pxa3xx_nand_select_chip(struct mtd_info *mtd, int chip)
++{
++ return;
++}
++
++static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
++{
++ struct pxa3xx_nand_info *info = mtd->priv;
++
++ /* pxa3xx_nand_send_command has waited for command complete */
++ if (this->state == FL_WRITING || this->state == FL_ERASING) {
++ if (info->retcode == ERR_NONE)
++ return 0;
++ else {
++ /*
++ * any error make it return 0x01 which will tell
++ * the caller the erase and write fail
++ */
++ return 0x01;
++ }
++ }
++
++ return 0;
++}
++
++static void pxa3xx_nand_ecc_hwctl(struct mtd_info *mtd, int mode)
++{
++ return;
++}
++
++static int pxa3xx_nand_ecc_calculate(struct mtd_info *mtd,
++ const uint8_t *dat, uint8_t *ecc_code)
++{
++ return 0;
++}
++
++static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd,
++ uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc)
++{
++ struct pxa3xx_nand_info *info = mtd->priv;
++ /*
++ * Any error include ERR_SEND_CMD, ERR_DBERR, ERR_BUSERR, we
++ * consider it as a ecc error which will tell the caller the
++ * read fail We have distinguish all the errors, but the
++ * nand_read_ecc only check this function return value
++ */
++ if (info->retcode != ERR_NONE)
++ return -1;
++
++ return 0;
++}
++
++static int __readid(struct pxa3xx_nand_info *info, uint32_t *id)
++{
++ struct pxa3xx_nand_flash *f = info->flash_info;
++ struct pxa3xx_nand_cmdset *cmdset = f->cmdset;
++ uint32_t ndcr;
++ uint8_t id_buff[8];
++
++ if (prepare_other_cmd(info, cmdset->read_id)) {
++ printk(KERN_ERR "failed to prepare command\n");
++ return -EINVAL;
++ }
++
++ /* Send command */
++ if (write_cmd(info))
++ goto fail_timeout;
++
++ /* Wait for CMDDM(command done successfully) */
++ if (wait_for_event(info, NDSR_RDDREQ))
++ goto fail_timeout;
++
++ __raw_readsl(info->mmio_base + NDDB, id_buff, 2);
++ *id = id_buff[0] | (id_buff[1] << 8);
++ return 0;
++
++fail_timeout:
++ ndcr = nand_readl(info, NDCR);
++ nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
++ udelay(10);
++ return -ETIMEDOUT;
++}
++
++static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
++ struct pxa3xx_nand_flash *f)
++{
++ struct platform_device *pdev = info->pdev;
++ struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
++ uint32_t ndcr = 0x00000FFF; /* disable all interrupts */
++
++ if (f->page_size != 2048 && f->page_size != 512)
++ return -EINVAL;
++
++ if (f->flash_width != 16 && f->flash_width != 8)
++ return -EINVAL;
++
++ /* calculate flash information */
++ f->oob_size = (f->page_size == 2048) ? 64 : 16;
++ f->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
++
++ /* calculate addressing information */
++ f->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
++
++ if (f->num_blocks * f->page_per_block > 65536)
++ f->row_addr_cycles = 3;
++ else
++ f->row_addr_cycles = 2;
++
++ ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
++ ndcr |= (f->col_addr_cycles == 2) ? NDCR_RA_START : 0;
++ ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0;
++ ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0;
++ ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0;
++ ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
++
++ ndcr |= NDCR_RD_ID_CNT(f->read_id_bytes);
++ ndcr |= NDCR_SPARE_EN; /* enable spare by default */
++
++ info->reg_ndcr = ndcr;
++
++ pxa3xx_nand_set_timing(info, f->timing);
++ info->flash_info = f;
++ return 0;
++}
++
++static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info)
++{
++ struct pxa3xx_nand_flash *f;
++ uint32_t id;
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(builtin_flash_types); i++) {
++
++ f = builtin_flash_types[i];
++
++ if (pxa3xx_nand_config_flash(info, f))
++ continue;
++
++ if (__readid(info, &id))
++ continue;
++
++ if (id == f->chip_id)
++ return 0;
++ }
++
++ return -ENODEV;
++}
++
++/* the maximum possible buffer size for large page with OOB data
++ * is: 2048 + 64 = 2112 bytes, allocate a page here for both the
++ * data buffer and the DMA descriptor
++ */
++#define MAX_BUFF_SIZE PAGE_SIZE
++
++static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
++{
++ struct platform_device *pdev = info->pdev;
++ int data_desc_offset = MAX_BUFF_SIZE - sizeof(struct pxa_dma_desc);
++
++ if (use_dma == 0) {
++ info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
++ if (info->data_buff == NULL)
++ return -ENOMEM;
++ return 0;
++ }
++
++ info->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE,
++ &info->data_buff_phys, GFP_KERNEL);
++ if (info->data_buff == NULL) {
++ dev_err(&pdev->dev, "failed to allocate dma buffer\n");
++ return -ENOMEM;
++ }
++
++ info->data_buff_size = MAX_BUFF_SIZE;
++ info->data_desc = (void *)info->data_buff + data_desc_offset;
++ info->data_desc_addr = info->data_buff_phys + data_desc_offset;
++
++ info->data_dma_ch = pxa_request_dma("nand-data", DMA_PRIO_LOW,
++ pxa3xx_nand_data_dma_irq, info);
++ if (info->data_dma_ch < 0) {
++ dev_err(&pdev->dev, "failed to request data dma\n");
++ dma_free_coherent(&pdev->dev, info->data_buff_size,
++ info->data_buff, info->data_buff_phys);
++ return info->data_dma_ch;
++ }
++
++ return 0;
++}
++
++static struct nand_ecclayout hw_smallpage_ecclayout = {
++ .eccbytes = 6,
++ .eccpos = {8, 9, 10, 11, 12, 13 },
++ .oobfree = { {2, 6} }
++};
++
++static struct nand_ecclayout hw_largepage_ecclayout = {
++ .eccbytes = 24,
++ .eccpos = {
++ 40, 41, 42, 43, 44, 45, 46, 47,
++ 48, 49, 50, 51, 52, 53, 54, 55,
++ 56, 57, 58, 59, 60, 61, 62, 63},
++ .oobfree = { {2, 38} }
++};
++
++static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
++ struct pxa3xx_nand_info *info)
++{
++ struct pxa3xx_nand_flash *f = info->flash_info;
++ struct nand_chip *this = &info->nand_chip;
++
++ this->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0;
++
++ this->waitfunc = pxa3xx_nand_waitfunc;
++ this->select_chip = pxa3xx_nand_select_chip;
++ this->dev_ready = pxa3xx_nand_dev_ready;
++ this->cmdfunc = pxa3xx_nand_cmdfunc;
++ this->read_word = pxa3xx_nand_read_word;
++ this->read_byte = pxa3xx_nand_read_byte;
++ this->read_buf = pxa3xx_nand_read_buf;
++ this->write_buf = pxa3xx_nand_write_buf;
++ this->verify_buf = pxa3xx_nand_verify_buf;
++
++ this->ecc.mode = NAND_ECC_HW;
++ this->ecc.hwctl = pxa3xx_nand_ecc_hwctl;
++ this->ecc.calculate = pxa3xx_nand_ecc_calculate;
++ this->ecc.correct = pxa3xx_nand_ecc_correct;
++ this->ecc.size = f->page_size;
++
++ if (f->page_size == 2048)
++ this->ecc.layout = &hw_largepage_ecclayout;
++ else
++ this->ecc.layout = &hw_smallpage_ecclayout;
++
++ this->chip_delay = 25;
++}
++
++static int pxa3xx_nand_probe(struct platform_device *pdev)
++{
++ struct pxa3xx_nand_platform_data *pdata;
++ struct pxa3xx_nand_info *info;
++ struct nand_chip *this;
++ struct mtd_info *mtd;
++ struct resource *r;
++ int ret = 0, irq;
++
++ pdata = pdev->dev.platform_data;
++
++ if (!pdata) {
++ dev_err(&pdev->dev, "no platform data defined\n");
++ return -ENODEV;
++ }
++
++ mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct pxa3xx_nand_info),
++ GFP_KERNEL);
++ if (!mtd) {
++ dev_err(&pdev->dev, "failed to allocate memory\n");
++ return -ENOMEM;
++ }
++
++ info = (struct pxa3xx_nand_info *)(&mtd[1]);
++ info->pdev = pdev;
++
++ this = &info->nand_chip;
++ mtd->priv = info;
++
++ info->clk = clk_get(&pdev->dev, "NANDCLK");
++ if (IS_ERR(info->clk)) {
++ dev_err(&pdev->dev, "failed to get nand clock\n");
++ ret = PTR_ERR(info->clk);
++ goto fail_free_mtd;
++ }
++ clk_enable(info->clk);
++
++ r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
++ if (r == NULL) {
++ dev_err(&pdev->dev, "no resource defined for data DMA\n");
++ ret = -ENXIO;
++ goto fail_put_clk;
++ }
++ info->drcmr_dat = r->start;
++
++ r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
++ if (r == NULL) {
++ dev_err(&pdev->dev, "no resource defined for command DMA\n");
++ ret = -ENXIO;
++ goto fail_put_clk;
++ }
++ info->drcmr_cmd = r->start;
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0) {
++ dev_err(&pdev->dev, "no IRQ resource defined\n");
++ ret = -ENXIO;
++ goto fail_put_clk;
++ }
++
++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (r == NULL) {
++ dev_err(&pdev->dev, "no IO memory resource defined\n");
++ ret = -ENODEV;
++ goto fail_put_clk;
++ }
++
++ r = request_mem_region(r->start, r->end - r->start + 1, pdev->name);
++ if (r == NULL) {
++ dev_err(&pdev->dev, "failed to request memory resource\n");
++ ret = -EBUSY;
++ goto fail_put_clk;
++ }
++
++ info->mmio_base = ioremap(r->start, r->end - r->start + 1);
++ if (info->mmio_base == NULL) {
++ dev_err(&pdev->dev, "ioremap() failed\n");
++ ret = -ENODEV;
++ goto fail_free_res;
++ }
++
++ ret = pxa3xx_nand_init_buff(info);
++ if (ret)
++ goto fail_free_io;
++
++ ret = request_irq(IRQ_NAND, pxa3xx_nand_irq, IRQF_DISABLED,
++ pdev->name, info);
++ if (ret < 0) {
++ dev_err(&pdev->dev, "failed to request IRQ\n");
++ goto fail_free_buf;
++ }
++
++ ret = pxa3xx_nand_detect_flash(info);
++ if (ret) {
++ dev_err(&pdev->dev, "failed to detect flash\n");
++ ret = -ENODEV;
++ goto fail_free_irq;
++ }
++
++ pxa3xx_nand_init_mtd(mtd, info);
++
++ platform_set_drvdata(pdev, mtd);
++
++ if (nand_scan(mtd, 1)) {
++ dev_err(&pdev->dev, "failed to scan nand\n");
++ ret = -ENXIO;
++ goto fail_free_irq;
++ }
++
++ return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts);
++
++fail_free_irq:
++ free_irq(IRQ_NAND, info);
++fail_free_buf:
++ if (use_dma) {
++ pxa_free_dma(info->data_dma_ch);
++ dma_free_coherent(&pdev->dev, info->data_buff_size,
++ info->data_buff, info->data_buff_phys);
++ } else
++ kfree(info->data_buff);
++fail_free_io:
++ iounmap(info->mmio_base);
++fail_free_res:
++ release_mem_region(r->start, r->end - r->start + 1);
++fail_put_clk:
++ clk_disable(info->clk);
++ clk_put(info->clk);
++fail_free_mtd:
++ kfree(mtd);
++ return ret;
++}
++
++static int pxa3xx_nand_remove(struct platform_device *pdev)
++{
++ struct mtd_info *mtd = platform_get_drvdata(pdev);
++ struct pxa3xx_nand_info *info = mtd->priv;
++
++ platform_set_drvdata(pdev, NULL);
++
++ del_mtd_device(mtd);
++ del_mtd_partitions(mtd);
++ free_irq(IRQ_NAND, info);
++ if (use_dma) {
++ pxa_free_dma(info->data_dma_ch);
++ dma_free_writecombine(&pdev->dev, info->data_buff_size,
++ info->data_buff, info->data_buff_phys);
++ } else
++ kfree(info->data_buff);
++ kfree(mtd);
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
++ struct pxa3xx_nand_info *info = mtd->priv;
++
++ if (info->state != STATE_READY) {
++ dev_err(&pdev->dev, "driver busy, state = %d\n", info->state);
++ return -EAGAIN;
++ }
++
++ return 0;
++}
++
++static int pxa3xx_nand_resume(struct platform_device *pdev)
++{
++ struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
++ struct pxa3xx_nand_info *info = mtd->priv;
++
++ clk_enable(info->clk);
++
++ return pxa3xx_nand_config_flash(info);
++}
++#else
++#define pxa3xx_nand_suspend NULL
++#define pxa3xx_nand_resume NULL
++#endif
++
++static struct platform_driver pxa3xx_nand_driver = {
++ .driver = {
++ .name = "pxa3xx-nand",
++ },
++ .probe = pxa3xx_nand_probe,
++ .remove = pxa3xx_nand_remove,
++ .suspend = pxa3xx_nand_suspend,
++ .resume = pxa3xx_nand_resume,
++};
++
++static int __init pxa3xx_nand_init(void)
++{
++ return platform_driver_register(&pxa3xx_nand_driver);
++}
++module_init(pxa3xx_nand_init);
++
++static void __exit pxa3xx_nand_exit(void)
++{
++ platform_driver_unregister(&pxa3xx_nand_driver);
++}
++module_exit(pxa3xx_nand_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("PXA3xx NAND controller driver");
+diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c
+index 0f6ac25..26f8821 100644
+--- a/drivers/mtd/nand/rtc_from4.c
++++ b/drivers/mtd/nand/rtc_from4.c
+@@ -478,6 +478,7 @@ static int __init rtc_from4_init(void)
+ struct nand_chip *this;
+ unsigned short bcr1, bcr2, wcr2;
+ int i;
++ int ret;
+
+ /* Allocate memory for MTD device structure and private data */
+ rtc_from4_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
+@@ -537,6 +538,22 @@ static int __init rtc_from4_init(void)
+ this->ecc.hwctl = rtc_from4_enable_hwecc;
+ this->ecc.calculate = rtc_from4_calculate_ecc;
+ this->ecc.correct = rtc_from4_correct_data;
++
++ /* We could create the decoder on demand, if memory is a concern.
++ * This way we have it handy, if an error happens
++ *
++ * Symbolsize is 10 (bits)
++ * Primitve polynomial is x^10+x^3+1
++ * first consecutive root is 0
++ * primitve element to generate roots = 1
++ * generator polinomial degree = 6
++ */
++ rs_decoder = init_rs(10, 0x409, 0, 1, 6);
++ if (!rs_decoder) {
++ printk(KERN_ERR "Could not create a RS decoder\n");
++ ret = -ENOMEM;
++ goto err_1;
++ }
+ #else
+ printk(KERN_INFO "rtc_from4_init: using software ECC detection.\n");
+
+@@ -549,8 +566,8 @@ static int __init rtc_from4_init(void)
+
+ /* Scan to find existence of the device */
+ if (nand_scan(rtc_from4_mtd, RTC_FROM4_MAX_CHIPS)) {
+- kfree(rtc_from4_mtd);
+- return -ENXIO;
++ ret = -ENXIO;
++ goto err_2;
+ }
+
+ /* Perform 'device recovery' for each chip in case there was a power loss. */
+@@ -566,28 +583,19 @@ static int __init rtc_from4_init(void)
+ #endif
+
+ /* Register the partitions */
+- add_mtd_partitions(rtc_from4_mtd, partition_info, NUM_PARTITIONS);
++ ret = add_mtd_partitions(rtc_from4_mtd, partition_info, NUM_PARTITIONS);
++ if (ret)
++ goto err_3;
+
+-#ifdef RTC_FROM4_HWECC
+- /* We could create the decoder on demand, if memory is a concern.
+- * This way we have it handy, if an error happens
+- *
+- * Symbolsize is 10 (bits)
+- * Primitve polynomial is x^10+x^3+1
+- * first consecutive root is 0
+- * primitve element to generate roots = 1
+- * generator polinomial degree = 6
+- */
+- rs_decoder = init_rs(10, 0x409, 0, 1, 6);
+- if (!rs_decoder) {
+- printk(KERN_ERR "Could not create a RS decoder\n");
+- nand_release(rtc_from4_mtd);
+- kfree(rtc_from4_mtd);
+- return -ENOMEM;
+- }
+-#endif
+ /* Return happy */
+ return 0;
++err_3:
++ nand_release(rtc_from4_mtd);
++err_2:
++ free_rs(rs_decoder);
++err_1:
++ kfree(rtc_from4_mtd);
++ return ret;
+ }
+
+ module_init(rtc_from4_init);
+diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
+index 9260ad9..b34a460 100644
+--- a/drivers/mtd/nand/s3c2410.c
++++ b/drivers/mtd/nand/s3c2410.c
+@@ -119,8 +119,7 @@ struct s3c2410_nand_info {
+ void __iomem *sel_reg;
+ int sel_bit;
+ int mtd_count;
+-
+- unsigned long save_nfconf;
++ unsigned long save_sel;
+
+ enum s3c_cpu_type cpu_type;
+ };
+@@ -358,6 +357,14 @@ static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
+ if (diff0 == 0 && diff1 == 0 && diff2 == 0)
+ return 0; /* ECC is ok */
+
++ /* sometimes people do not think about using the ECC, so check
++ * to see if we have an 0xff,0xff,0xff read ECC and then ignore
++ * the error, on the assumption that this is an un-eccd page.
++ */
++ if (read_ecc[0] == 0xff && read_ecc[1] == 0xff && read_ecc[2] == 0xff
++ && info->platform->ignore_unset_ecc)
++ return 0;
++
+ /* Can we correct this ECC (ie, one row and column change).
+ * Note, this is similar to the 256 error code on smartmedia */
+
+@@ -473,7 +480,7 @@ static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u
+ ecc_code[1] = ecc >> 8;
+ ecc_code[2] = ecc >> 16;
+
+- pr_debug("%s: returning ecc %06lx\n", __func__, ecc);
++ pr_debug("%s: returning ecc %06lx\n", __func__, ecc & 0xffffff);
+
+ return 0;
+ }
+@@ -644,9 +651,6 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
+ chip->ecc.calculate = s3c2410_nand_calculate_ecc;
+ chip->ecc.correct = s3c2410_nand_correct_data;
+ chip->ecc.mode = NAND_ECC_HW;
+- chip->ecc.size = 512;
+- chip->ecc.bytes = 3;
+- chip->ecc.layout = &nand_hw_eccoob;
+
+ switch (info->cpu_type) {
+ case TYPE_S3C2410:
+@@ -668,6 +672,40 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
+ } else {
+ chip->ecc.mode = NAND_ECC_SOFT;
+ }
++
++ if (set->ecc_layout != NULL)
++ chip->ecc.layout = set->ecc_layout;
++
++ if (set->disable_ecc)
++ chip->ecc.mode = NAND_ECC_NONE;
++}
++
++/* s3c2410_nand_update_chip
++ *
++ * post-probe chip update, to change any items, such as the
++ * layout for large page nand
++ */
++
++static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
++ struct s3c2410_nand_mtd *nmtd)
++{
++ struct nand_chip *chip = &nmtd->chip;
++
++ printk("%s: chip %p: %d\n", __func__, chip, chip->page_shift);
++
++ if (hardware_ecc) {
++ /* change the behaviour depending on wether we are using
++ * the large or small page nand device */
++
++ if (chip->page_shift > 10) {
++ chip->ecc.size = 256;
++ chip->ecc.bytes = 3;
++ } else {
++ chip->ecc.size = 512;
++ chip->ecc.bytes = 3;
++ chip->ecc.layout = &nand_hw_eccoob;
++ }
++ }
+ }
+
+ /* s3c2410_nand_probe
+@@ -776,9 +814,12 @@ static int s3c24xx_nand_probe(struct platform_device *pdev,
+
+ s3c2410_nand_init_chip(info, nmtd, sets);
+
+- nmtd->scan_res = nand_scan(&nmtd->mtd, (sets) ? sets->nr_chips : 1);
++ nmtd->scan_res = nand_scan_ident(&nmtd->mtd,
++ (sets) ? sets->nr_chips : 1);
+
+ if (nmtd->scan_res == 0) {
++ s3c2410_nand_update_chip(info, nmtd);
++ nand_scan_tail(&nmtd->mtd);
+ s3c2410_nand_add_partition(info, nmtd, sets);
+ }
+
+@@ -810,15 +851,14 @@ static int s3c24xx_nand_suspend(struct platform_device *dev, pm_message_t pm)
+ struct s3c2410_nand_info *info = platform_get_drvdata(dev);
+
+ if (info) {
+- info->save_nfconf = readl(info->regs + S3C2410_NFCONF);
++ info->save_sel = readl(info->sel_reg);
+
+ /* For the moment, we must ensure nFCE is high during
+ * the time we are suspended. This really should be
+ * handled by suspending the MTDs we are using, but
+ * that is currently not the case. */
+
+- writel(info->save_nfconf | info->sel_bit,
+- info->regs + S3C2410_NFCONF);
++ writel(info->save_sel | info->sel_bit, info->sel_reg);
+
+ if (!allow_clk_stop(info))
+ clk_disable(info->clk);
+@@ -830,7 +870,7 @@ static int s3c24xx_nand_suspend(struct platform_device *dev, pm_message_t pm)
+ static int s3c24xx_nand_resume(struct platform_device *dev)
+ {
+ struct s3c2410_nand_info *info = platform_get_drvdata(dev);
+- unsigned long nfconf;
++ unsigned long sel;
+
+ if (info) {
+ clk_enable(info->clk);
+@@ -838,10 +878,10 @@ static int s3c24xx_nand_resume(struct platform_device *dev)
+
+ /* Restore the state of the nFCE line. */
+
+- nfconf = readl(info->regs + S3C2410_NFCONF);
+- nfconf &= ~info->sel_bit;
+- nfconf |= info->save_nfconf & info->sel_bit;
+- writel(nfconf, info->regs + S3C2410_NFCONF);
++ sel = readl(info->sel_reg);
++ sel &= ~info->sel_bit;
++ sel |= info->save_sel & info->sel_bit;
++ writel(sel, info->sel_reg);
+
+ if (allow_clk_stop(info))
+ clk_disable(info->clk);
+@@ -927,3 +967,6 @@ module_exit(s3c2410_nand_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Ben Dooks <ben at simtec.co.uk>");
+ MODULE_DESCRIPTION("S3C24XX MTD NAND driver");
++MODULE_ALIAS("platform:s3c2410-nand");
++MODULE_ALIAS("platform:s3c2412-nand");
++MODULE_ALIAS("platform:s3c2440-nand");
+diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c
+index 0513cbc..345e6ef 100644
+--- a/drivers/mtd/nftlmount.c
++++ b/drivers/mtd/nftlmount.c
+@@ -33,11 +33,6 @@
+
+ char nftlmountrev[]="$Revision: 1.41 $";
+
+-extern int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+- size_t *retlen, uint8_t *buf);
+-extern int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+- size_t *retlen, uint8_t *buf);
+-
+ /* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the
+ * various device information of the NFTL partition and Bad Unit Table. Update
+ * the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[]
+diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
+index f86e069..4f80c2f 100644
+--- a/drivers/mtd/ofpart.c
++++ b/drivers/mtd/ofpart.c
+@@ -72,3 +72,5 @@ int __devinit of_mtd_parse_partitions(struct device *dev,
+ return nr_parts;
+ }
+ EXPORT_SYMBOL(of_mtd_parse_partitions);
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
+index 8d7d21b..5d7965f 100644
+--- a/drivers/mtd/onenand/onenand_base.c
++++ b/drivers/mtd/onenand/onenand_base.c
+@@ -329,6 +329,21 @@ static int onenand_wait(struct mtd_info *mtd, int state)
+ printk(KERN_ERR "onenand_wait: controller error = 0x%04x\n", ctrl);
+ if (ctrl & ONENAND_CTRL_LOCK)
+ printk(KERN_ERR "onenand_wait: it's locked error.\n");
++ if (state == FL_READING) {
++ /*
++ * A power loss while writing can result in a page
++ * becoming unreadable. When the device is mounted
++ * again, reading that page gives controller errors.
++ * Upper level software like JFFS2 treat -EIO as fatal,
++ * refusing to mount at all. That means it is necessary
++ * to treat the error as an ECC error to allow recovery.
++ * Note that typically in this case, the eraseblock can
++ * still be erased and rewritten i.e. it has not become
++ * a bad block.
++ */
++ mtd->ecc_stats.failed++;
++ return -EBADMSG;
++ }
+ return -EIO;
+ }
+
+@@ -1336,7 +1351,7 @@ static int onenand_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
+ }
+
+ /* Reject writes, which are not page aligned */
+- if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) {
++ if (unlikely(NOTALIGNED(to) || NOTALIGNED(len))) {
+ printk(KERN_ERR "onenand_panic_write: Attempt to write not page aligned data\n");
+ return -EINVAL;
+ }
+@@ -1466,7 +1481,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
+ }
+
+ /* Reject writes, which are not page aligned */
+- if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) {
++ if (unlikely(NOTALIGNED(to) || NOTALIGNED(len))) {
+ printk(KERN_ERR "onenand_write_ops_nolock: Attempt to write not page aligned data\n");
+ return -EINVAL;
+ }
+@@ -2052,7 +2067,7 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+ *
+ * Check lock status
+ */
+-static void onenand_check_lock_status(struct onenand_chip *this)
++static int onenand_check_lock_status(struct onenand_chip *this)
+ {
+ unsigned int value, block, status;
+ unsigned int end;
+@@ -2070,9 +2085,13 @@ static void onenand_check_lock_status(struct onenand_chip *this)
+
+ /* Check lock status */
+ status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
+- if (!(status & ONENAND_WP_US))
++ if (!(status & ONENAND_WP_US)) {
+ printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status);
++ return 0;
++ }
+ }
++
++ return 1;
+ }
+
+ /**
+@@ -2081,9 +2100,11 @@ static void onenand_check_lock_status(struct onenand_chip *this)
+ *
+ * Unlock all blocks
+ */
+-static int onenand_unlock_all(struct mtd_info *mtd)
++static void onenand_unlock_all(struct mtd_info *mtd)
+ {
+ struct onenand_chip *this = mtd->priv;
++ loff_t ofs = 0;
++ size_t len = this->chipsize;
+
+ if (this->options & ONENAND_HAS_UNLOCK_ALL) {
+ /* Set start block address */
+@@ -2099,23 +2120,19 @@ static int onenand_unlock_all(struct mtd_info *mtd)
+ & ONENAND_CTRL_ONGO)
+ continue;
+
++ /* Check lock status */
++ if (onenand_check_lock_status(this))
++ return;
++
+ /* Workaround for all block unlock in DDP */
+ if (ONENAND_IS_DDP(this)) {
+- /* 1st block on another chip */
+- loff_t ofs = this->chipsize >> 1;
+- size_t len = mtd->erasesize;
+-
+- onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
++ /* All blocks on another chip */
++ ofs = this->chipsize >> 1;
++ len = this->chipsize >> 1;
+ }
+-
+- onenand_check_lock_status(this);
+-
+- return 0;
+ }
+
+- onenand_do_lock_cmd(mtd, 0x0, this->chipsize, ONENAND_CMD_UNLOCK);
+-
+- return 0;
++ onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
+ }
+
+ #ifdef CONFIG_MTD_ONENAND_OTP
+diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c
+index aecdd50..2f53b51 100644
+--- a/drivers/mtd/onenand/onenand_bbt.c
++++ b/drivers/mtd/onenand/onenand_bbt.c
+@@ -17,9 +17,6 @@
+ #include <linux/mtd/onenand.h>
+ #include <linux/mtd/compatmac.h>
+
+-extern int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
+- struct mtd_oob_ops *ops);
+-
+ /**
+ * check_short_pattern - [GENERIC] check if a pattern is in the buffer
+ * @param buf the buffer to search
+diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c
+index 823fba4..c84e454 100644
+--- a/drivers/mtd/rfd_ftl.c
++++ b/drivers/mtd/rfd_ftl.c
+@@ -823,7 +823,7 @@ static void rfd_ftl_remove_dev(struct mtd_blktrans_dev *dev)
+ kfree(part);
+ }
+
+-struct mtd_blktrans_ops rfd_ftl_tr = {
++static struct mtd_blktrans_ops rfd_ftl_tr = {
+ .name = "rfd",
+ .major = RFD_FTL_MAJOR,
+ .part_bits = PART_BITS,
+diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig
+index b9daf15..3f06310 100644
+--- a/drivers/mtd/ubi/Kconfig
++++ b/drivers/mtd/ubi/Kconfig
+@@ -24,8 +24,13 @@ config MTD_UBI_WL_THRESHOLD
+ erase counter value and the lowest erase counter value of eraseblocks
+ of UBI devices. When this threshold is exceeded, UBI starts performing
+ wear leveling by means of moving data from eraseblock with low erase
+- counter to eraseblocks with high erase counter. Leave the default
+- value if unsure.
++ counter to eraseblocks with high erase counter.
++
++ The default value should be OK for SLC NAND flashes, NOR flashes and
++ other flashes which have eraseblock life-cycle 100000 or more.
++ However, in case of MLC NAND flashes which typically have eraseblock
++ life-cycle less then 10000, the threshold should be lessened (e.g.,
++ to 128 or 256, although it does not have to be power of 2).
+
+ config MTD_UBI_BEB_RESERVE
+ int "Percentage of reserved eraseblocks for bad eraseblocks handling"
+diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
+index 2759604..961416a 100644
+--- a/drivers/mtd/ubi/build.c
++++ b/drivers/mtd/ubi/build.c
+@@ -606,8 +606,16 @@ static int io_init(struct ubi_device *ubi)
+ ubi->ro_mode = 1;
+ }
+
+- dbg_msg("leb_size %d", ubi->leb_size);
+- dbg_msg("ro_mode %d", ubi->ro_mode);
++ ubi_msg("physical eraseblock size: %d bytes (%d KiB)",
++ ubi->peb_size, ubi->peb_size >> 10);
++ ubi_msg("logical eraseblock size: %d bytes", ubi->leb_size);
++ ubi_msg("smallest flash I/O unit: %d", ubi->min_io_size);
++ if (ubi->hdrs_min_io_size != ubi->min_io_size)
++ ubi_msg("sub-page size: %d",
++ ubi->hdrs_min_io_size);
++ ubi_msg("VID header offset: %d (aligned %d)",
++ ubi->vid_hdr_offset, ubi->vid_hdr_aloffset);
++ ubi_msg("data offset: %d", ubi->leb_start);
+
+ /*
+ * Note, ideally, we have to initialize ubi->bad_peb_count here. But
+@@ -755,8 +763,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
+ mutex_init(&ubi->volumes_mutex);
+ spin_lock_init(&ubi->volumes_lock);
+
+- dbg_msg("attaching mtd%d to ubi%d: VID header offset %d",
+- mtd->index, ubi_num, vid_hdr_offset);
++ ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num);
+
+ err = io_init(ubi);
+ if (err)
+@@ -804,15 +811,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
+ ubi_msg("attached mtd%d to ubi%d", mtd->index, ubi_num);
+ ubi_msg("MTD device name: \"%s\"", mtd->name);
+ ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20);
+- ubi_msg("physical eraseblock size: %d bytes (%d KiB)",
+- ubi->peb_size, ubi->peb_size >> 10);
+- ubi_msg("logical eraseblock size: %d bytes", ubi->leb_size);
+ ubi_msg("number of good PEBs: %d", ubi->good_peb_count);
+ ubi_msg("number of bad PEBs: %d", ubi->bad_peb_count);
+- ubi_msg("smallest flash I/O unit: %d", ubi->min_io_size);
+- ubi_msg("VID header offset: %d (aligned %d)",
+- ubi->vid_hdr_offset, ubi->vid_hdr_aloffset);
+- ubi_msg("data offset: %d", ubi->leb_start);
+ ubi_msg("max. allowed volumes: %d", ubi->vtbl_slots);
+ ubi_msg("wear-leveling threshold: %d", CONFIG_MTD_UBI_WL_THRESHOLD);
+ ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT);
+@@ -950,8 +950,7 @@ static int __init ubi_init(void)
+ BUILD_BUG_ON(sizeof(struct ubi_vid_hdr) != 64);
+
+ if (mtd_devs > UBI_MAX_DEVICES) {
+- printk(KERN_ERR "UBI error: too many MTD devices, "
+- "maximum is %d\n", UBI_MAX_DEVICES);
++ ubi_err("too many MTD devices, maximum is %d", UBI_MAX_DEVICES);
+ return -EINVAL;
+ }
+
+@@ -959,25 +958,25 @@ static int __init ubi_init(void)
+ ubi_class = class_create(THIS_MODULE, UBI_NAME_STR);
+ if (IS_ERR(ubi_class)) {
+ err = PTR_ERR(ubi_class);
+- printk(KERN_ERR "UBI error: cannot create UBI class\n");
++ ubi_err("cannot create UBI class");
+ goto out;
+ }
+
+ err = class_create_file(ubi_class, &ubi_version);
+ if (err) {
+- printk(KERN_ERR "UBI error: cannot create sysfs file\n");
++ ubi_err("cannot create sysfs file");
+ goto out_class;
+ }
+
+ err = misc_register(&ubi_ctrl_cdev);
+ if (err) {
+- printk(KERN_ERR "UBI error: cannot register device\n");
++ ubi_err("cannot register device");
+ goto out_version;
+ }
+
+ ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab",
+- sizeof(struct ubi_wl_entry),
+- 0, 0, NULL);
++ sizeof(struct ubi_wl_entry),
++ 0, 0, NULL);
+ if (!ubi_wl_entry_slab)
+ goto out_dev_unreg;
+
+@@ -1000,8 +999,7 @@ static int __init ubi_init(void)
+ mutex_unlock(&ubi_devices_mutex);
+ if (err < 0) {
+ put_mtd_device(mtd);
+- printk(KERN_ERR "UBI error: cannot attach mtd%d\n",
+- mtd->index);
++ ubi_err("cannot attach mtd%d", mtd->index);
+ goto out_detach;
+ }
+ }
+@@ -1023,7 +1021,7 @@ out_version:
+ out_class:
+ class_destroy(ubi_class);
+ out:
+- printk(KERN_ERR "UBI error: cannot initialize UBI, error %d\n", err);
++ ubi_err("UBI error: cannot initialize UBI, error %d", err);
+ return err;
+ }
+ module_init(ubi_init);
+diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
+index 51c40b1..8ea99d8 100644
+--- a/drivers/mtd/ubi/debug.h
++++ b/drivers/mtd/ubi/debug.h
+@@ -41,7 +41,7 @@
+ /* Generic debugging message */
+ #define dbg_msg(fmt, ...) \
+ printk(KERN_DEBUG "UBI DBG (pid %d): %s: " fmt "\n", \
+- current->pid, __FUNCTION__, ##__VA_ARGS__)
++ current->pid, __func__, ##__VA_ARGS__)
+
+ #define ubi_dbg_dump_stack() dump_stack()
+
+@@ -99,8 +99,10 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req);
+ #ifdef CONFIG_MTD_UBI_DEBUG_MSG_BLD
+ /* Initialization and build messages */
+ #define dbg_bld(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
++#define UBI_IO_DEBUG 1
+ #else
+ #define dbg_bld(fmt, ...) ({})
++#define UBI_IO_DEBUG 0
+ #endif
+
+ #ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_BITFLIPS
+diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c
+index d397219..e909b39 100644
+--- a/drivers/mtd/ubi/gluebi.c
++++ b/drivers/mtd/ubi/gluebi.c
+@@ -291,11 +291,12 @@ int ubi_create_gluebi(struct ubi_device *ubi, struct ubi_volume *vol)
+ /*
+ * In case of dynamic volume, MTD device size is just volume size. In
+ * case of a static volume the size is equivalent to the amount of data
+- * bytes, which is zero at this moment and will be changed after volume
+- * update.
++ * bytes.
+ */
+ if (vol->vol_type == UBI_DYNAMIC_VOLUME)
+ mtd->size = vol->usable_leb_size * vol->reserved_pebs;
++ else
++ mtd->size = vol->used_bytes;
+
+ if (add_mtd_device(mtd)) {
+ ubi_err("cannot not add MTD device\n");
+diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
+index db3efde..4ac11df 100644
+--- a/drivers/mtd/ubi/io.c
++++ b/drivers/mtd/ubi/io.c
+@@ -631,6 +631,8 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
+
+ dbg_io("read EC header from PEB %d", pnum);
+ ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
++ if (UBI_IO_DEBUG)
++ verbose = 1;
+
+ err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE);
+ if (err) {
+@@ -904,6 +906,8 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
+
+ dbg_io("read VID header from PEB %d", pnum);
+ ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
++ if (UBI_IO_DEBUG)
++ verbose = 1;
+
+ p = (char *)vid_hdr - ubi->vid_hdr_shift;
+ err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
+diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
+index 05aa3e7..96d410e 100644
+--- a/drivers/mtd/ubi/scan.c
++++ b/drivers/mtd/ubi/scan.c
+@@ -42,6 +42,7 @@
+
+ #include <linux/err.h>
+ #include <linux/crc32.h>
++#include <asm/div64.h>
+ #include "ubi.h"
+
+ #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+@@ -92,27 +93,6 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec,
+ }
+
+ /**
+- * commit_to_mean_value - commit intermediate results to the final mean erase
+- * counter value.
+- * @si: scanning information
+- *
+- * This is a helper function which calculates partial mean erase counter mean
+- * value and adds it to the resulting mean value. As we can work only in
+- * integer arithmetic and we want to calculate the mean value of erase counter
+- * accurately, we first sum erase counter values in @si->ec_sum variable and
+- * count these components in @si->ec_count. If this temporary @si->ec_sum is
+- * going to overflow, we calculate the partial mean value
+- * (@si->ec_sum/@si->ec_count) and add it to @si->mean_ec.
+- */
+-static void commit_to_mean_value(struct ubi_scan_info *si)
+-{
+- si->ec_sum /= si->ec_count;
+- if (si->ec_sum % si->ec_count >= si->ec_count / 2)
+- si->mean_ec += 1;
+- si->mean_ec += si->ec_sum;
+-}
+-
+-/**
+ * validate_vid_hdr - check that volume identifier header is correct and
+ * consistent.
+ * @vid_hdr: the volume identifier header to check
+@@ -901,15 +881,8 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum
+
+ adjust_mean_ec:
+ if (!ec_corr) {
+- if (si->ec_sum + ec < ec) {
+- commit_to_mean_value(si);
+- si->ec_sum = 0;
+- si->ec_count = 0;
+- } else {
+- si->ec_sum += ec;
+- si->ec_count += 1;
+- }
+-
++ si->ec_sum += ec;
++ si->ec_count += 1;
+ if (ec > si->max_ec)
+ si->max_ec = ec;
+ if (ec < si->min_ec)
+@@ -965,9 +938,11 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
+
+ dbg_msg("scanning is finished");
+
+- /* Finish mean erase counter calculations */
+- if (si->ec_count)
+- commit_to_mean_value(si);
++ /* Calculate mean erase counter */
++ if (si->ec_count) {
++ do_div(si->ec_sum, si->ec_count);
++ si->mean_ec = si->ec_sum;
++ }
+
+ if (si->is_empty)
+ ubi_msg("empty MTD device detected");
+diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h
+index 46d444a..966b9b6 100644
+--- a/drivers/mtd/ubi/scan.h
++++ b/drivers/mtd/ubi/scan.h
+@@ -124,7 +124,7 @@ struct ubi_scan_info {
+ int max_ec;
+ unsigned long long max_sqnum;
+ int mean_ec;
+- int ec_sum;
++ uint64_t ec_sum;
+ int ec_count;
+ };
+
+diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h
+new file mode 100644
+index 0000000..c3185d9
+--- /dev/null
++++ b/drivers/mtd/ubi/ubi-media.h
+@@ -0,0 +1,372 @@
++/*
++ * Copyright (c) International Business Machines Corp., 2006
++ *
++ * 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
++ *
++ * Authors: Artem Bityutskiy (ÐиÑÑÑкий ÐÑÑÑм)
++ * Thomas Gleixner
++ * Frank Haverkamp
++ * Oliver Lohmann
++ * Andreas Arnez
++ */
++
++/*
++ * This file defines the layout of UBI headers and all the other UBI on-flash
++ * data structures.
++ */
++
++#ifndef __UBI_MEDIA_H__
++#define __UBI_MEDIA_H__
++
++#include <asm/byteorder.h>
++
++/* The version of UBI images supported by this implementation */
++#define UBI_VERSION 1
++
++/* The highest erase counter value supported by this implementation */
++#define UBI_MAX_ERASECOUNTER 0x7FFFFFFF
++
++/* The initial CRC32 value used when calculating CRC checksums */
++#define UBI_CRC32_INIT 0xFFFFFFFFU
++
++/* Erase counter header magic number (ASCII "UBI#") */
++#define UBI_EC_HDR_MAGIC 0x55424923
++/* Volume identifier header magic number (ASCII "UBI!") */
++#define UBI_VID_HDR_MAGIC 0x55424921
++
++/*
++ * Volume type constants used in the volume identifier header.
++ *
++ * @UBI_VID_DYNAMIC: dynamic volume
++ * @UBI_VID_STATIC: static volume
++ */
++enum {
++ UBI_VID_DYNAMIC = 1,
++ UBI_VID_STATIC = 2
++};
++
++/*
++ * Volume flags used in the volume table record.
++ *
++ * @UBI_VTBL_AUTORESIZE_FLG: auto-resize this volume
++ *
++ * %UBI_VTBL_AUTORESIZE_FLG flag can be set only for one volume in the volume
++ * table. UBI automatically re-sizes the volume which has this flag and makes
++ * the volume to be of largest possible size. This means that if after the
++ * initialization UBI finds out that there are available physical eraseblocks
++ * present on the device, it automatically appends all of them to the volume
++ * (the physical eraseblocks reserved for bad eraseblocks handling and other
++ * reserved physical eraseblocks are not taken). So, if there is a volume with
++ * the %UBI_VTBL_AUTORESIZE_FLG flag set, the amount of available logical
++ * eraseblocks will be zero after UBI is loaded, because all of them will be
++ * reserved for this volume. Note, the %UBI_VTBL_AUTORESIZE_FLG bit is cleared
++ * after the volume had been initialized.
++ *
++ * The auto-resize feature is useful for device production purposes. For
++ * example, different NAND flash chips may have different amount of initial bad
++ * eraseblocks, depending of particular chip instance. Manufacturers of NAND
++ * chips usually guarantee that the amount of initial bad eraseblocks does not
++ * exceed certain percent, e.g. 2%. When one creates an UBI image which will be
++ * flashed to the end devices in production, he does not know the exact amount
++ * of good physical eraseblocks the NAND chip on the device will have, but this
++ * number is required to calculate the volume sized and put them to the volume
++ * table of the UBI image. In this case, one of the volumes (e.g., the one
++ * which will store the root file system) is marked as "auto-resizable", and
++ * UBI will adjust its size on the first boot if needed.
++ *
++ * Note, first UBI reserves some amount of physical eraseblocks for bad
++ * eraseblock handling, and then re-sizes the volume, not vice-versa. This
++ * means that the pool of reserved physical eraseblocks will always be present.
++ */
++enum {
++ UBI_VTBL_AUTORESIZE_FLG = 0x01,
++};
++
++/*
++ * Compatibility constants used by internal volumes.
++ *
++ * @UBI_COMPAT_DELETE: delete this internal volume before anything is written
++ * to the flash
++ * @UBI_COMPAT_RO: attach this device in read-only mode
++ * @UBI_COMPAT_PRESERVE: preserve this internal volume - do not touch its
++ * physical eraseblocks, don't allow the wear-leveling unit to move them
++ * @UBI_COMPAT_REJECT: reject this UBI image
++ */
++enum {
++ UBI_COMPAT_DELETE = 1,
++ UBI_COMPAT_RO = 2,
++ UBI_COMPAT_PRESERVE = 4,
++ UBI_COMPAT_REJECT = 5
++};
++
++/* Sizes of UBI headers */
++#define UBI_EC_HDR_SIZE sizeof(struct ubi_ec_hdr)
++#define UBI_VID_HDR_SIZE sizeof(struct ubi_vid_hdr)
++
++/* Sizes of UBI headers without the ending CRC */
++#define UBI_EC_HDR_SIZE_CRC (UBI_EC_HDR_SIZE - sizeof(__be32))
++#define UBI_VID_HDR_SIZE_CRC (UBI_VID_HDR_SIZE - sizeof(__be32))
++
++/**
++ * struct ubi_ec_hdr - UBI erase counter header.
++ * @magic: erase counter header magic number (%UBI_EC_HDR_MAGIC)
++ * @version: version of UBI implementation which is supposed to accept this
++ * UBI image
++ * @padding1: reserved for future, zeroes
++ * @ec: the erase counter
++ * @vid_hdr_offset: where the VID header starts
++ * @data_offset: where the user data start
++ * @padding2: reserved for future, zeroes
++ * @hdr_crc: erase counter header CRC checksum
++ *
++ * The erase counter header takes 64 bytes and has a plenty of unused space for
++ * future usage. The unused fields are zeroed. The @version field is used to
++ * indicate the version of UBI implementation which is supposed to be able to
++ * work with this UBI image. If @version is greater then the current UBI
++ * version, the image is rejected. This may be useful in future if something
++ * is changed radically. This field is duplicated in the volume identifier
++ * header.
++ *
++ * The @vid_hdr_offset and @data_offset fields contain the offset of the the
++ * volume identifier header and user data, relative to the beginning of the
++ * physical eraseblock. These values have to be the same for all physical
++ * eraseblocks.
++ */
++struct ubi_ec_hdr {
++ __be32 magic;
++ __u8 version;
++ __u8 padding1[3];
++ __be64 ec; /* Warning: the current limit is 31-bit anyway! */
++ __be32 vid_hdr_offset;
++ __be32 data_offset;
++ __u8 padding2[36];
++ __be32 hdr_crc;
++} __attribute__ ((packed));
++
++/**
++ * struct ubi_vid_hdr - on-flash UBI volume identifier header.
++ * @magic: volume identifier header magic number (%UBI_VID_HDR_MAGIC)
++ * @version: UBI implementation version which is supposed to accept this UBI
++ * image (%UBI_VERSION)
++ * @vol_type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC)
++ * @copy_flag: if this logical eraseblock was copied from another physical
++ * eraseblock (for wear-leveling reasons)
++ * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE,
++ * %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT)
++ * @vol_id: ID of this volume
++ * @lnum: logical eraseblock number
++ * @leb_ver: version of this logical eraseblock (IMPORTANT: obsolete, to be
++ * removed, kept only for not breaking older UBI users)
++ * @data_size: how many bytes of data this logical eraseblock contains
++ * @used_ebs: total number of used logical eraseblocks in this volume
++ * @data_pad: how many bytes at the end of this physical eraseblock are not
++ * used
++ * @data_crc: CRC checksum of the data stored in this logical eraseblock
++ * @padding1: reserved for future, zeroes
++ * @sqnum: sequence number
++ * @padding2: reserved for future, zeroes
++ * @hdr_crc: volume identifier header CRC checksum
++ *
++ * The @sqnum is the value of the global sequence counter at the time when this
++ * VID header was created. The global sequence counter is incremented each time
++ * UBI writes a new VID header to the flash, i.e. when it maps a logical
++ * eraseblock to a new physical eraseblock. The global sequence counter is an
++ * unsigned 64-bit integer and we assume it never overflows. The @sqnum
++ * (sequence number) is used to distinguish between older and newer versions of
++ * logical eraseblocks.
++ *
++ * There are 2 situations when there may be more then one physical eraseblock
++ * corresponding to the same logical eraseblock, i.e., having the same @vol_id
++ * and @lnum values in the volume identifier header. Suppose we have a logical
++ * eraseblock L and it is mapped to the physical eraseblock P.
++ *
++ * 1. Because UBI may erase physical eraseblocks asynchronously, the following
++ * situation is possible: L is asynchronously erased, so P is scheduled for
++ * erasure, then L is written to,i.e. mapped to another physical eraseblock P1,
++ * so P1 is written to, then an unclean reboot happens. Result - there are 2
++ * physical eraseblocks P and P1 corresponding to the same logical eraseblock
++ * L. But P1 has greater sequence number, so UBI picks P1 when it attaches the
++ * flash.
++ *
++ * 2. From time to time UBI moves logical eraseblocks to other physical
++ * eraseblocks for wear-leveling reasons. If, for example, UBI moves L from P
++ * to P1, and an unclean reboot happens before P is physically erased, there
++ * are two physical eraseblocks P and P1 corresponding to L and UBI has to
++ * select one of them when the flash is attached. The @sqnum field says which
++ * PEB is the original (obviously P will have lower @sqnum) and the copy. But
++ * it is not enough to select the physical eraseblock with the higher sequence
++ * number, because the unclean reboot could have happen in the middle of the
++ * copying process, so the data in P is corrupted. It is also not enough to
++ * just select the physical eraseblock with lower sequence number, because the
++ * data there may be old (consider a case if more data was added to P1 after
++ * the copying). Moreover, the unclean reboot may happen when the erasure of P
++ * was just started, so it result in unstable P, which is "mostly" OK, but
++ * still has unstable bits.
++ *
++ * UBI uses the @copy_flag field to indicate that this logical eraseblock is a
++ * copy. UBI also calculates data CRC when the data is moved and stores it at
++ * the @data_crc field of the copy (P1). So when UBI needs to pick one physical
++ * eraseblock of two (P or P1), the @copy_flag of the newer one (P1) is
++ * examined. If it is cleared, the situation* is simple and the newer one is
++ * picked. If it is set, the data CRC of the copy (P1) is examined. If the CRC
++ * checksum is correct, this physical eraseblock is selected (P1). Otherwise
++ * the older one (P) is selected.
++ *
++ * Note, there is an obsolete @leb_ver field which was used instead of @sqnum
++ * in the past. But it is not used anymore and we keep it in order to be able
++ * to deal with old UBI images. It will be removed at some point.
++ *
++ * There are 2 sorts of volumes in UBI: user volumes and internal volumes.
++ * Internal volumes are not seen from outside and are used for various internal
++ * UBI purposes. In this implementation there is only one internal volume - the
++ * layout volume. Internal volumes are the main mechanism of UBI extensions.
++ * For example, in future one may introduce a journal internal volume. Internal
++ * volumes have their own reserved range of IDs.
++ *
++ * The @compat field is only used for internal volumes and contains the "degree
++ * of their compatibility". It is always zero for user volumes. This field
++ * provides a mechanism to introduce UBI extensions and to be still compatible
++ * with older UBI binaries. For example, if someone introduced a journal in
++ * future, he would probably use %UBI_COMPAT_DELETE compatibility for the
++ * journal volume. And in this case, older UBI binaries, which know nothing
++ * about the journal volume, would just delete this volume and work perfectly
++ * fine. This is similar to what Ext2fs does when it is fed by an Ext3fs image
++ * - it just ignores the Ext3fs journal.
++ *
++ * The @data_crc field contains the CRC checksum of the contents of the logical
++ * eraseblock if this is a static volume. In case of dynamic volumes, it does
++ * not contain the CRC checksum as a rule. The only exception is when the
++ * data of the physical eraseblock was moved by the wear-leveling unit, then
++ * the wear-leveling unit calculates the data CRC and stores it in the
++ * @data_crc field. And of course, the @copy_flag is %in this case.
++ *
++ * The @data_size field is used only for static volumes because UBI has to know
++ * how many bytes of data are stored in this eraseblock. For dynamic volumes,
++ * this field usually contains zero. The only exception is when the data of the
++ * physical eraseblock was moved to another physical eraseblock for
++ * wear-leveling reasons. In this case, UBI calculates CRC checksum of the
++ * contents and uses both @data_crc and @data_size fields. In this case, the
++ * @data_size field contains data size.
++ *
++ * The @used_ebs field is used only for static volumes and indicates how many
++ * eraseblocks the data of the volume takes. For dynamic volumes this field is
++ * not used and always contains zero.
++ *
++ * The @data_pad is calculated when volumes are created using the alignment
++ * parameter. So, effectively, the @data_pad field reduces the size of logical
++ * eraseblocks of this volume. This is very handy when one uses block-oriented
++ * software (say, cramfs) on top of the UBI volume.
++ */
++struct ubi_vid_hdr {
++ __be32 magic;
++ __u8 version;
++ __u8 vol_type;
++ __u8 copy_flag;
++ __u8 compat;
++ __be32 vol_id;
++ __be32 lnum;
++ __be32 leb_ver; /* obsolete, to be removed, don't use */
++ __be32 data_size;
++ __be32 used_ebs;
++ __be32 data_pad;
++ __be32 data_crc;
++ __u8 padding1[4];
++ __be64 sqnum;
++ __u8 padding2[12];
++ __be32 hdr_crc;
++} __attribute__ ((packed));
++
++/* Internal UBI volumes count */
++#define UBI_INT_VOL_COUNT 1
++
++/*
++ * Starting ID of internal volumes. There is reserved room for 4096 internal
++ * volumes.
++ */
++#define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096)
++
++/* The layout volume contains the volume table */
++
++#define UBI_LAYOUT_VOLUME_ID UBI_INTERNAL_VOL_START
++#define UBI_LAYOUT_VOLUME_TYPE UBI_VID_DYNAMIC
++#define UBI_LAYOUT_VOLUME_ALIGN 1
++#define UBI_LAYOUT_VOLUME_EBS 2
++#define UBI_LAYOUT_VOLUME_NAME "layout volume"
++#define UBI_LAYOUT_VOLUME_COMPAT UBI_COMPAT_REJECT
++
++/* The maximum number of volumes per one UBI device */
++#define UBI_MAX_VOLUMES 128
++
++/* The maximum volume name length */
++#define UBI_VOL_NAME_MAX 127
++
++/* Size of the volume table record */
++#define UBI_VTBL_RECORD_SIZE sizeof(struct ubi_vtbl_record)
++
++/* Size of the volume table record without the ending CRC */
++#define UBI_VTBL_RECORD_SIZE_CRC (UBI_VTBL_RECORD_SIZE - sizeof(__be32))
++
++/**
++ * struct ubi_vtbl_record - a record in the volume table.
++ * @reserved_pebs: how many physical eraseblocks are reserved for this volume
++ * @alignment: volume alignment
++ * @data_pad: how many bytes are unused at the end of the each physical
++ * eraseblock to satisfy the requested alignment
++ * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
++ * @upd_marker: if volume update was started but not finished
++ * @name_len: volume name length
++ * @name: the volume name
++ * @flags: volume flags (%UBI_VTBL_AUTORESIZE_FLG)
++ * @padding: reserved, zeroes
++ * @crc: a CRC32 checksum of the record
++ *
++ * The volume table records are stored in the volume table, which is stored in
++ * the layout volume. The layout volume consists of 2 logical eraseblock, each
++ * of which contains a copy of the volume table (i.e., the volume table is
++ * duplicated). The volume table is an array of &struct ubi_vtbl_record
++ * objects indexed by the volume ID.
++ *
++ * If the size of the logical eraseblock is large enough to fit
++ * %UBI_MAX_VOLUMES records, the volume table contains %UBI_MAX_VOLUMES
++ * records. Otherwise, it contains as many records as it can fit (i.e., size of
++ * logical eraseblock divided by sizeof(struct ubi_vtbl_record)).
++ *
++ * The @upd_marker flag is used to implement volume update. It is set to %1
++ * before update and set to %0 after the update. So if the update operation was
++ * interrupted, UBI knows that the volume is corrupted.
++ *
++ * The @alignment field is specified when the volume is created and cannot be
++ * later changed. It may be useful, for example, when a block-oriented file
++ * system works on top of UBI. The @data_pad field is calculated using the
++ * logical eraseblock size and @alignment. The alignment must be multiple to the
++ * minimal flash I/O unit. If @alignment is 1, all the available space of
++ * the physical eraseblocks is used.
++ *
++ * Empty records contain all zeroes and the CRC checksum of those zeroes.
++ */
++struct ubi_vtbl_record {
++ __be32 reserved_pebs;
++ __be32 alignment;
++ __be32 data_pad;
++ __u8 vol_type;
++ __u8 upd_marker;
++ __be16 name_len;
++ __u8 name[UBI_VOL_NAME_MAX+1];
++ __u8 flags;
++ __u8 padding[23];
++ __be32 crc;
++} __attribute__ ((packed));
++
++#endif /* !__UBI_MEDIA_H__ */
+diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
+index a548c1d..67dcbd1 100644
+--- a/drivers/mtd/ubi/ubi.h
++++ b/drivers/mtd/ubi/ubi.h
+@@ -37,10 +37,9 @@
+ #include <linux/string.h>
+ #include <linux/vmalloc.h>
+ #include <linux/mtd/mtd.h>
+-
+-#include <mtd/ubi-header.h>
+ #include <linux/mtd/ubi.h>
+
++#include "ubi-media.h"
+ #include "scan.h"
+ #include "debug.h"
+
+@@ -54,10 +53,10 @@
+ #define ubi_msg(fmt, ...) printk(KERN_NOTICE "UBI: " fmt "\n", ##__VA_ARGS__)
+ /* UBI warning messages */
+ #define ubi_warn(fmt, ...) printk(KERN_WARNING "UBI warning: %s: " fmt "\n", \
+- __FUNCTION__, ##__VA_ARGS__)
++ __func__, ##__VA_ARGS__)
+ /* UBI error messages */
+ #define ubi_err(fmt, ...) printk(KERN_ERR "UBI error: %s: " fmt "\n", \
+- __FUNCTION__, ##__VA_ARGS__)
++ __func__, ##__VA_ARGS__)
+
+ /* Lowest number PEBs reserved for bad PEB handling */
+ #define MIN_RESEVED_PEBS 2
+diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c
+index 8fafac9..54dac06 100644
+--- a/drivers/net/3c509.c
++++ b/drivers/net/3c509.c
+@@ -54,25 +54,24 @@
+ v1.19a 28Oct2002 Davud Ruggiero <jdr at farfalle.com>
+ - Increase *read_eeprom udelay to workaround oops with 2 cards.
+ v1.19b 08Nov2002 Marc Zyngier <maz at wild-wind.fr.eu.org>
+- - Introduce driver model for EISA cards.
++ - Introduce driver model for EISA cards.
++ v1.20 04Feb2008 Ondrej Zary <linux at rainbow-software.org>
++ - convert to isa_driver and pnp_driver and some cleanups
+ */
+
+ #define DRV_NAME "3c509"
+-#define DRV_VERSION "1.19b"
+-#define DRV_RELDATE "08Nov2002"
++#define DRV_VERSION "1.20"
++#define DRV_RELDATE "04Feb2008"
+
+ /* A few values that may be tweaked. */
+
+ /* Time in jiffies before concluding the transmitter is hung. */
+ #define TX_TIMEOUT (400*HZ/1000)
+-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+-static int max_interrupt_work = 10;
+
+ #include <linux/module.h>
+-#ifdef CONFIG_MCA
+ #include <linux/mca.h>
+-#endif
+-#include <linux/isapnp.h>
++#include <linux/isa.h>
++#include <linux/pnp.h>
+ #include <linux/string.h>
+ #include <linux/interrupt.h>
+ #include <linux/errno.h>
+@@ -97,10 +96,6 @@ static int max_interrupt_work = 10;
+
+ static char version[] __initdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker at scyld.com\n";
+
+-#if defined(CONFIG_PM) && (defined(CONFIG_MCA) || defined(CONFIG_EISA))
+-#define EL3_SUSPEND
+-#endif
+-
+ #ifdef EL3_DEBUG
+ static int el3_debug = EL3_DEBUG;
+ #else
+@@ -111,6 +106,7 @@ static int el3_debug = 2;
+ * a global variable so that the mca/eisa probe routines can increment
+ * it */
+ static int el3_cards = 0;
++#define EL3_MAX_CARDS 8
+
+ /* To minimize the size of the driver source I only define operating
+ constants if they are used several times. You'll need the manual
+@@ -119,7 +115,7 @@ static int el3_cards = 0;
+ #define EL3_DATA 0x00
+ #define EL3_CMD 0x0e
+ #define EL3_STATUS 0x0e
+-#define EEPROM_READ 0x80
++#define EEPROM_READ 0x80
+
+ #define EL3_IO_EXTENT 16
+
+@@ -168,23 +164,31 @@ enum RxFilter {
+ */
+ #define SKB_QUEUE_SIZE 64
+
++enum el3_cardtype { EL3_ISA, EL3_PNP, EL3_MCA, EL3_EISA };
++
+ struct el3_private {
+ struct net_device_stats stats;
+- struct net_device *next_dev;
+ spinlock_t lock;
+ /* skb send-queue */
+ int head, size;
+ struct sk_buff *queue[SKB_QUEUE_SIZE];
+- enum {
+- EL3_MCA,
+- EL3_PNP,
+- EL3_EISA,
+- } type; /* type of device */
+- struct device *dev;
++ enum el3_cardtype type;
+ };
+-static int id_port __initdata = 0x110; /* Start with 0x110 to avoid new sound cards.*/
+-static struct net_device *el3_root_dev;
++static int id_port;
++static int current_tag;
++static struct net_device *el3_devs[EL3_MAX_CARDS];
++
++/* Parameters that may be passed into the module. */
++static int debug = -1;
++static int irq[] = {-1, -1, -1, -1, -1, -1, -1, -1};
++/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
++static int max_interrupt_work = 10;
++#ifdef CONFIG_PNP
++static int nopnp;
++#endif
+
++static int __init el3_common_init(struct net_device *dev);
++static void el3_common_remove(struct net_device *dev);
+ static ushort id_read_eeprom(int index);
+ static ushort read_eeprom(int ioaddr, int index);
+ static int el3_open(struct net_device *dev);
+@@ -199,7 +203,7 @@ static void el3_tx_timeout (struct net_device *dev);
+ static void el3_down(struct net_device *dev);
+ static void el3_up(struct net_device *dev);
+ static const struct ethtool_ops ethtool_ops;
+-#ifdef EL3_SUSPEND
++#ifdef CONFIG_PM
+ static int el3_suspend(struct device *, pm_message_t);
+ static int el3_resume(struct device *);
+ #else
+@@ -209,13 +213,272 @@ static int el3_resume(struct device *);
+
+
+ /* generic device remove for all device types */
+-#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+ static int el3_device_remove (struct device *device);
+-#endif
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+ static void el3_poll_controller(struct net_device *dev);
+ #endif
+
++/* Return 0 on success, 1 on error, 2 when found already detected PnP card */
++static int el3_isa_id_sequence(__be16 *phys_addr)
++{
++ short lrs_state = 0xff;
++ int i;
++
++ /* ISA boards are detected by sending the ID sequence to the
++ ID_PORT. We find cards past the first by setting the 'current_tag'
++ on cards as they are found. Cards with their tag set will not
++ respond to subsequent ID sequences. */
++
++ outb(0x00, id_port);
++ outb(0x00, id_port);
++ for (i = 0; i < 255; i++) {
++ outb(lrs_state, id_port);
++ lrs_state <<= 1;
++ lrs_state = lrs_state & 0x100 ? lrs_state ^ 0xcf : lrs_state;
++ }
++ /* For the first probe, clear all board's tag registers. */
++ if (current_tag == 0)
++ outb(0xd0, id_port);
++ else /* Otherwise kill off already-found boards. */
++ outb(0xd8, id_port);
++ if (id_read_eeprom(7) != 0x6d50)
++ return 1;
++ /* Read in EEPROM data, which does contention-select.
++ Only the lowest address board will stay "on-line".
++ 3Com got the byte order backwards. */
++ for (i = 0; i < 3; i++)
++ phys_addr[i] = htons(id_read_eeprom(i));
++#ifdef CONFIG_PNP
++ if (!nopnp) {
++ /* The ISA PnP 3c509 cards respond to the ID sequence too.
++ This check is needed in order not to register them twice. */
++ for (i = 0; i < el3_cards; i++) {
++ struct el3_private *lp = netdev_priv(el3_devs[i]);
++ if (lp->type == EL3_PNP
++ && !memcmp(phys_addr, el3_devs[i]->dev_addr,
++ ETH_ALEN)) {
++ if (el3_debug > 3)
++ printk(KERN_DEBUG "3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n",
++ phys_addr[0] & 0xff, phys_addr[0] >> 8,
++ phys_addr[1] & 0xff, phys_addr[1] >> 8,
++ phys_addr[2] & 0xff, phys_addr[2] >> 8);
++ /* Set the adaptor tag so that the next card can be found. */
++ outb(0xd0 + ++current_tag, id_port);
++ return 2;
++ }
++ }
++ }
++#endif /* CONFIG_PNP */
++ return 0;
++
++}
++
++static void __devinit el3_dev_fill(struct net_device *dev, __be16 *phys_addr,
++ int ioaddr, int irq, int if_port,
++ enum el3_cardtype type)
++{
++ struct el3_private *lp = netdev_priv(dev);
++
++ memcpy(dev->dev_addr, phys_addr, ETH_ALEN);
++ dev->base_addr = ioaddr;
++ dev->irq = irq;
++ dev->if_port = if_port;
++ lp->type = type;
++}
++
++static int __devinit el3_isa_match(struct device *pdev,
++ unsigned int ndev)
++{
++ struct net_device *dev;
++ int ioaddr, isa_irq, if_port, err;
++ unsigned int iobase;
++ __be16 phys_addr[3];
++
++ while ((err = el3_isa_id_sequence(phys_addr)) == 2)
++ ; /* Skip to next card when PnP card found */
++ if (err == 1)
++ return 0;
++
++ iobase = id_read_eeprom(8);
++ if_port = iobase >> 14;
++ ioaddr = 0x200 + ((iobase & 0x1f) << 4);
++ if (irq[el3_cards] > 1 && irq[el3_cards] < 16)
++ isa_irq = irq[el3_cards];
++ else
++ isa_irq = id_read_eeprom(9) >> 12;
++
++ dev = alloc_etherdev(sizeof(struct el3_private));
++ if (!dev)
++ return -ENOMEM;
++
++ netdev_boot_setup_check(dev);
++
++ if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509-isa")) {
++ free_netdev(dev);
++ return 0;
++ }
++
++ /* Set the adaptor tag so that the next card can be found. */
++ outb(0xd0 + ++current_tag, id_port);
++
++ /* Activate the adaptor at the EEPROM location. */
++ outb((ioaddr >> 4) | 0xe0, id_port);
++
++ EL3WINDOW(0);
++ if (inw(ioaddr) != 0x6d50) {
++ free_netdev(dev);
++ return 0;
++ }
++
++ /* Free the interrupt so that some other card can use it. */
++ outw(0x0f00, ioaddr + WN0_IRQ);
++
++ el3_dev_fill(dev, phys_addr, ioaddr, isa_irq, if_port, EL3_ISA);
++ dev_set_drvdata(pdev, dev);
++ if (el3_common_init(dev)) {
++ free_netdev(dev);
++ return 0;
++ }
++
++ el3_devs[el3_cards++] = dev;
++ return 1;
++}
++
++static int __devexit el3_isa_remove(struct device *pdev,
++ unsigned int ndev)
++{
++ el3_device_remove(pdev);
++ dev_set_drvdata(pdev, NULL);
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int el3_isa_suspend(struct device *dev, unsigned int n,
++ pm_message_t state)
++{
++ current_tag = 0;
++ return el3_suspend(dev, state);
++}
++
++static int el3_isa_resume(struct device *dev, unsigned int n)
++{
++ struct net_device *ndev = dev_get_drvdata(dev);
++ int ioaddr = ndev->base_addr, err;
++ __be16 phys_addr[3];
++
++ while ((err = el3_isa_id_sequence(phys_addr)) == 2)
++ ; /* Skip to next card when PnP card found */
++ if (err == 1)
++ return 0;
++ /* Set the adaptor tag so that the next card can be found. */
++ outb(0xd0 + ++current_tag, id_port);
++ /* Enable the card */
++ outb((ioaddr >> 4) | 0xe0, id_port);
++ EL3WINDOW(0);
++ if (inw(ioaddr) != 0x6d50)
++ return 1;
++ /* Free the interrupt so that some other card can use it. */
++ outw(0x0f00, ioaddr + WN0_IRQ);
++ return el3_resume(dev);
++}
++#endif
++
++static struct isa_driver el3_isa_driver = {
++ .match = el3_isa_match,
++ .remove = __devexit_p(el3_isa_remove),
++#ifdef CONFIG_PM
++ .suspend = el3_isa_suspend,
++ .resume = el3_isa_resume,
++#endif
++ .driver = {
++ .name = "3c509"
++ },
++};
++static int isa_registered;
++
++#ifdef CONFIG_PNP
++static struct pnp_device_id el3_pnp_ids[] = {
++ { .id = "TCM5090" }, /* 3Com Etherlink III (TP) */
++ { .id = "TCM5091" }, /* 3Com Etherlink III */
++ { .id = "TCM5094" }, /* 3Com Etherlink III (combo) */
++ { .id = "TCM5095" }, /* 3Com Etherlink III (TPO) */
++ { .id = "TCM5098" }, /* 3Com Etherlink III (TPC) */
++ { .id = "PNP80f7" }, /* 3Com Etherlink III compatible */
++ { .id = "PNP80f8" }, /* 3Com Etherlink III compatible */
++ { .id = "" }
++};
++MODULE_DEVICE_TABLE(pnp, el3_pnp_ids);
++
++static int __devinit el3_pnp_probe(struct pnp_dev *pdev,
++ const struct pnp_device_id *id)
++{
++ short i;
++ int ioaddr, irq, if_port;
++ u16 phys_addr[3];
++ struct net_device *dev = NULL;
++ int err;
++
++ ioaddr = pnp_port_start(pdev, 0);
++ if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509-pnp"))
++ return -EBUSY;
++ irq = pnp_irq(pdev, 0);
++ EL3WINDOW(0);
++ for (i = 0; i < 3; i++)
++ phys_addr[i] = htons(read_eeprom(ioaddr, i));
++ if_port = read_eeprom(ioaddr, 8) >> 14;
++ dev = alloc_etherdev(sizeof(struct el3_private));
++ if (!dev) {
++ release_region(ioaddr, EL3_IO_EXTENT);
++ return -ENOMEM;
++ }
++ SET_NETDEV_DEV(dev, &pdev->dev);
++ netdev_boot_setup_check(dev);
++
++ el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_PNP);
++ pnp_set_drvdata(pdev, dev);
++ err = el3_common_init(dev);
++
++ if (err) {
++ pnp_set_drvdata(pdev, NULL);
++ free_netdev(dev);
++ return err;
++ }
++
++ el3_devs[el3_cards++] = dev;
++ return 0;
++}
++
++static void __devexit el3_pnp_remove(struct pnp_dev *pdev)
++{
++ el3_common_remove(pnp_get_drvdata(pdev));
++ pnp_set_drvdata(pdev, NULL);
++}
++
++#ifdef CONFIG_PM
++static int el3_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
++{
++ return el3_suspend(&pdev->dev, state);
++}
++
++static int el3_pnp_resume(struct pnp_dev *pdev)
++{
++ return el3_resume(&pdev->dev);
++}
++#endif
++
++static struct pnp_driver el3_pnp_driver = {
++ .name = "3c509",
++ .id_table = el3_pnp_ids,
++ .probe = el3_pnp_probe,
++ .remove = __devexit_p(el3_pnp_remove),
++#ifdef CONFIG_PM
++ .suspend = el3_pnp_suspend,
++ .resume = el3_pnp_resume,
++#endif
++};
++static int pnp_registered;
++#endif /* CONFIG_PNP */
++
+ #ifdef CONFIG_EISA
+ static struct eisa_device_id el3_eisa_ids[] = {
+ { "TCM5092" },
+@@ -230,13 +493,14 @@ static int el3_eisa_probe (struct device *device);
+ static struct eisa_driver el3_eisa_driver = {
+ .id_table = el3_eisa_ids,
+ .driver = {
+- .name = "3c509",
++ .name = "3c579",
+ .probe = el3_eisa_probe,
+ .remove = __devexit_p (el3_device_remove),
+ .suspend = el3_suspend,
+ .resume = el3_resume,
+ }
+ };
++static int eisa_registered;
+ #endif
+
+ #ifdef CONFIG_MCA
+@@ -271,45 +535,9 @@ static struct mca_driver el3_mca_driver = {
+ .resume = el3_resume,
+ },
+ };
++static int mca_registered;
+ #endif /* CONFIG_MCA */
+
+-#if defined(__ISAPNP__)
+-static struct isapnp_device_id el3_isapnp_adapters[] __initdata = {
+- { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+- ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5090),
+- (long) "3Com Etherlink III (TP)" },
+- { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+- ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5091),
+- (long) "3Com Etherlink III" },
+- { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+- ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5094),
+- (long) "3Com Etherlink III (combo)" },
+- { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+- ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5095),
+- (long) "3Com Etherlink III (TPO)" },
+- { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+- ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5098),
+- (long) "3Com Etherlink III (TPC)" },
+- { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+- ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_FUNCTION(0x80f7),
+- (long) "3Com Etherlink III compatible" },
+- { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+- ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_FUNCTION(0x80f8),
+- (long) "3Com Etherlink III compatible" },
+- { } /* terminate list */
+-};
+-
+-static __be16 el3_isapnp_phys_addr[8][3];
+-static int nopnp;
+-#endif /* __ISAPNP__ */
+-
+-/* With the driver model introduction for EISA devices, both init
+- * and cleanup have been split :
+- * - EISA devices probe/remove starts in el3_eisa_probe/el3_device_remove
+- * - MCA/ISA still use el3_probe
+- *
+- * Both call el3_common_init/el3_common_remove. */
+-
+ static int __init el3_common_init(struct net_device *dev)
+ {
+ struct el3_private *lp = netdev_priv(dev);
+@@ -360,231 +588,11 @@ static int __init el3_common_init(struct net_device *dev)
+
+ static void el3_common_remove (struct net_device *dev)
+ {
+- struct el3_private *lp = netdev_priv(dev);
+-
+- (void) lp; /* Keep gcc quiet... */
+-#if defined(__ISAPNP__)
+- if (lp->type == EL3_PNP)
+- pnp_device_detach(to_pnp_dev(lp->dev));
+-#endif
+-
+ unregister_netdev (dev);
+ release_region(dev->base_addr, EL3_IO_EXTENT);
+ free_netdev (dev);
+ }
+
+-static int __init el3_probe(int card_idx)
+-{
+- struct net_device *dev;
+- struct el3_private *lp;
+- short lrs_state = 0xff, i;
+- int ioaddr, irq, if_port;
+- __be16 phys_addr[3];
+- static int current_tag;
+- int err = -ENODEV;
+-#if defined(__ISAPNP__)
+- static int pnp_cards;
+- struct pnp_dev *idev = NULL;
+- int pnp_found = 0;
+-
+- if (nopnp == 1)
+- goto no_pnp;
+-
+- for (i=0; el3_isapnp_adapters[i].vendor != 0; i++) {
+- int j;
+- while ((idev = pnp_find_dev(NULL,
+- el3_isapnp_adapters[i].vendor,
+- el3_isapnp_adapters[i].function,
+- idev))) {
+- if (pnp_device_attach(idev) < 0)
+- continue;
+- if (pnp_activate_dev(idev) < 0) {
+-__again:
+- pnp_device_detach(idev);
+- continue;
+- }
+- if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0))
+- goto __again;
+- ioaddr = pnp_port_start(idev, 0);
+- if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509 PnP")) {
+- pnp_device_detach(idev);
+- return -EBUSY;
+- }
+- irq = pnp_irq(idev, 0);
+- if (el3_debug > 3)
+- printk ("ISAPnP reports %s at i/o 0x%x, irq %d\n",
+- (char*) el3_isapnp_adapters[i].driver_data, ioaddr, irq);
+- EL3WINDOW(0);
+- for (j = 0; j < 3; j++)
+- el3_isapnp_phys_addr[pnp_cards][j] =
+- phys_addr[j] =
+- htons(read_eeprom(ioaddr, j));
+- if_port = read_eeprom(ioaddr, 8) >> 14;
+- dev = alloc_etherdev(sizeof (struct el3_private));
+- if (!dev) {
+- release_region(ioaddr, EL3_IO_EXTENT);
+- pnp_device_detach(idev);
+- return -ENOMEM;
+- }
+-
+- SET_NETDEV_DEV(dev, &idev->dev);
+- pnp_cards++;
+-
+- netdev_boot_setup_check(dev);
+- pnp_found = 1;
+- goto found;
+- }
+- }
+-no_pnp:
+-#endif /* __ISAPNP__ */
+-
+- /* Select an open I/O location at 0x1*0 to do contention select. */
+- for ( ; id_port < 0x200; id_port += 0x10) {
+- if (!request_region(id_port, 1, "3c509"))
+- continue;
+- outb(0x00, id_port);
+- outb(0xff, id_port);
+- if (inb(id_port) & 0x01){
+- release_region(id_port, 1);
+- break;
+- } else
+- release_region(id_port, 1);
+- }
+- if (id_port >= 0x200) {
+- /* Rare -- do we really need a warning? */
+- printk(" WARNING: No I/O port available for 3c509 activation.\n");
+- return -ENODEV;
+- }
+-
+- /* Next check for all ISA bus boards by sending the ID sequence to the
+- ID_PORT. We find cards past the first by setting the 'current_tag'
+- on cards as they are found. Cards with their tag set will not
+- respond to subsequent ID sequences. */
+-
+- outb(0x00, id_port);
+- outb(0x00, id_port);
+- for(i = 0; i < 255; i++) {
+- outb(lrs_state, id_port);
+- lrs_state <<= 1;
+- lrs_state = lrs_state & 0x100 ? lrs_state ^ 0xcf : lrs_state;
+- }
+-
+- /* For the first probe, clear all board's tag registers. */
+- if (current_tag == 0)
+- outb(0xd0, id_port);
+- else /* Otherwise kill off already-found boards. */
+- outb(0xd8, id_port);
+-
+- if (id_read_eeprom(7) != 0x6d50) {
+- return -ENODEV;
+- }
+-
+- /* Read in EEPROM data, which does contention-select.
+- Only the lowest address board will stay "on-line".
+- 3Com got the byte order backwards. */
+- for (i = 0; i < 3; i++) {
+- phys_addr[i] = htons(id_read_eeprom(i));
+- }
+-
+-#if defined(__ISAPNP__)
+- if (nopnp == 0) {
+- /* The ISA PnP 3c509 cards respond to the ID sequence.
+- This check is needed in order not to register them twice. */
+- for (i = 0; i < pnp_cards; i++) {
+- if (phys_addr[0] == el3_isapnp_phys_addr[i][0] &&
+- phys_addr[1] == el3_isapnp_phys_addr[i][1] &&
+- phys_addr[2] == el3_isapnp_phys_addr[i][2])
+- {
+- if (el3_debug > 3)
+- printk("3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n",
+- phys_addr[0] & 0xff, phys_addr[0] >> 8,
+- phys_addr[1] & 0xff, phys_addr[1] >> 8,
+- phys_addr[2] & 0xff, phys_addr[2] >> 8);
+- /* Set the adaptor tag so that the next card can be found. */
+- outb(0xd0 + ++current_tag, id_port);
+- goto no_pnp;
+- }
+- }
+- }
+-#endif /* __ISAPNP__ */
+-
+- {
+- unsigned int iobase = id_read_eeprom(8);
+- if_port = iobase >> 14;
+- ioaddr = 0x200 + ((iobase & 0x1f) << 4);
+- }
+- irq = id_read_eeprom(9) >> 12;
+-
+- dev = alloc_etherdev(sizeof (struct el3_private));
+- if (!dev)
+- return -ENOMEM;
+-
+- netdev_boot_setup_check(dev);
+-
+- /* Set passed-in IRQ or I/O Addr. */
+- if (dev->irq > 1 && dev->irq < 16)
+- irq = dev->irq;
+-
+- if (dev->base_addr) {
+- if (dev->mem_end == 0x3c509 /* Magic key */
+- && dev->base_addr >= 0x200 && dev->base_addr <= 0x3e0)
+- ioaddr = dev->base_addr & 0x3f0;
+- else if (dev->base_addr != ioaddr)
+- goto out;
+- }
+-
+- if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509")) {
+- err = -EBUSY;
+- goto out;
+- }
+-
+- /* Set the adaptor tag so that the next card can be found. */
+- outb(0xd0 + ++current_tag, id_port);
+-
+- /* Activate the adaptor at the EEPROM location. */
+- outb((ioaddr >> 4) | 0xe0, id_port);
+-
+- EL3WINDOW(0);
+- if (inw(ioaddr) != 0x6d50)
+- goto out1;
+-
+- /* Free the interrupt so that some other card can use it. */
+- outw(0x0f00, ioaddr + WN0_IRQ);
+-
+-#if defined(__ISAPNP__)
+- found: /* PNP jumps here... */
+-#endif /* __ISAPNP__ */
+-
+- memcpy(dev->dev_addr, phys_addr, sizeof(phys_addr));
+- dev->base_addr = ioaddr;
+- dev->irq = irq;
+- dev->if_port = if_port;
+- lp = netdev_priv(dev);
+-#if defined(__ISAPNP__)
+- lp->dev = &idev->dev;
+- if (pnp_found)
+- lp->type = EL3_PNP;
+-#endif
+- err = el3_common_init(dev);
+-
+- if (err)
+- goto out1;
+-
+- el3_cards++;
+- lp->next_dev = el3_root_dev;
+- el3_root_dev = dev;
+- return 0;
+-
+-out1:
+-#if defined(__ISAPNP__)
+- if (idev)
+- pnp_device_detach(idev);
+-#endif
+-out:
+- free_netdev(dev);
+- return err;
+-}
+-
+ #ifdef CONFIG_MCA
+ static int __init el3_mca_probe(struct device *device)
+ {
+@@ -596,7 +604,6 @@ static int __init el3_mca_probe(struct device *device)
+ * redone for multi-card detection by ZP Gu (zpg at castle.net)
+ * now works as a module */
+
+- struct el3_private *lp;
+ short i;
+ int ioaddr, irq, if_port;
+ u16 phys_addr[3];
+@@ -613,7 +620,7 @@ static int __init el3_mca_probe(struct device *device)
+ irq = pos5 & 0x0f;
+
+
+- printk("3c529: found %s at slot %d\n",
++ printk(KERN_INFO "3c529: found %s at slot %d\n",
+ el3_mca_adapter_names[mdev->index], slot + 1);
+
+ /* claim the slot */
+@@ -626,7 +633,7 @@ static int __init el3_mca_probe(struct device *device)
+ irq = mca_device_transform_irq(mdev, irq);
+ ioaddr = mca_device_transform_ioport(mdev, ioaddr);
+ if (el3_debug > 2) {
+- printk("3c529: irq %d ioaddr 0x%x ifport %d\n", irq, ioaddr, if_port);
++ printk(KERN_DEBUG "3c529: irq %d ioaddr 0x%x ifport %d\n", irq, ioaddr, if_port);
+ }
+ EL3WINDOW(0);
+ for (i = 0; i < 3; i++) {
+@@ -641,13 +648,7 @@ static int __init el3_mca_probe(struct device *device)
+
+ netdev_boot_setup_check(dev);
+
+- memcpy(dev->dev_addr, phys_addr, sizeof(phys_addr));
+- dev->base_addr = ioaddr;
+- dev->irq = irq;
+- dev->if_port = if_port;
+- lp = netdev_priv(dev);
+- lp->dev = device;
+- lp->type = EL3_MCA;
++ el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_MCA);
+ device->driver_data = dev;
+ err = el3_common_init(dev);
+
+@@ -657,7 +658,7 @@ static int __init el3_mca_probe(struct device *device)
+ return -ENOMEM;
+ }
+
+- el3_cards++;
++ el3_devs[el3_cards++] = dev;
+ return 0;
+ }
+
+@@ -666,7 +667,6 @@ static int __init el3_mca_probe(struct device *device)
+ #ifdef CONFIG_EISA
+ static int __init el3_eisa_probe (struct device *device)
+ {
+- struct el3_private *lp;
+ short i;
+ int ioaddr, irq, if_port;
+ u16 phys_addr[3];
+@@ -678,7 +678,7 @@ static int __init el3_eisa_probe (struct device *device)
+ edev = to_eisa_device (device);
+ ioaddr = edev->base_addr;
+
+- if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509"))
++ if (!request_region(ioaddr, EL3_IO_EXTENT, "3c579-eisa"))
+ return -EBUSY;
+
+ /* Change the register set to the configuration window 0. */
+@@ -700,13 +700,7 @@ static int __init el3_eisa_probe (struct device *device)
+
+ netdev_boot_setup_check(dev);
+
+- memcpy(dev->dev_addr, phys_addr, sizeof(phys_addr));
+- dev->base_addr = ioaddr;
+- dev->irq = irq;
+- dev->if_port = if_port;
+- lp = netdev_priv(dev);
+- lp->dev = device;
+- lp->type = EL3_EISA;
++ el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_EISA);
+ eisa_set_drvdata (edev, dev);
+ err = el3_common_init(dev);
+
+@@ -716,12 +710,11 @@ static int __init el3_eisa_probe (struct device *device)
+ return err;
+ }
+
+- el3_cards++;
++ el3_devs[el3_cards++] = dev;
+ return 0;
+ }
+ #endif
+
+-#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+ /* This remove works for all device types.
+ *
+ * The net dev must be stored in the driver_data field */
+@@ -734,7 +727,6 @@ static int __devexit el3_device_remove (struct device *device)
+ el3_common_remove (dev);
+ return 0;
+ }
+-#endif
+
+ /* Read a word from the EEPROM using the regular EEPROM access register.
+ Assume that we are in register window zero.
+@@ -749,7 +741,7 @@ static ushort read_eeprom(int ioaddr, int index)
+ }
+
+ /* Read a word from the EEPROM when in the ISA ID probe state. */
+-static ushort __init id_read_eeprom(int index)
++static ushort id_read_eeprom(int index)
+ {
+ int bit, word = 0;
+
+@@ -765,7 +757,7 @@ static ushort __init id_read_eeprom(int index)
+ word = (word << 1) + (inb(id_port) & 0x01);
+
+ if (el3_debug > 3)
+- printk(" 3c509 EEPROM word %d %#4.4x.\n", index, word);
++ printk(KERN_DEBUG " 3c509 EEPROM word %d %#4.4x.\n", index, word);
+
+ return word;
+ }
+@@ -787,13 +779,13 @@ el3_open(struct net_device *dev)
+
+ EL3WINDOW(0);
+ if (el3_debug > 3)
+- printk("%s: Opening, IRQ %d status@%x %4.4x.\n", dev->name,
++ printk(KERN_DEBUG "%s: Opening, IRQ %d status@%x %4.4x.\n", dev->name,
+ dev->irq, ioaddr + EL3_STATUS, inw(ioaddr + EL3_STATUS));
+
+ el3_up(dev);
+
+ if (el3_debug > 3)
+- printk("%s: Opened 3c509 IRQ %d status %4.4x.\n",
++ printk(KERN_DEBUG "%s: Opened 3c509 IRQ %d status %4.4x.\n",
+ dev->name, dev->irq, inw(ioaddr + EL3_STATUS));
+
+ return 0;
+@@ -806,7 +798,7 @@ el3_tx_timeout (struct net_device *dev)
+ int ioaddr = dev->base_addr;
+
+ /* Transmitter timeout, serious problems. */
+- printk("%s: transmit timed out, Tx_status %2.2x status %4.4x "
++ printk(KERN_WARNING "%s: transmit timed out, Tx_status %2.2x status %4.4x "
+ "Tx FIFO room %d.\n",
+ dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS),
+ inw(ioaddr + TX_FREE));
+@@ -831,7 +823,7 @@ el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ lp->stats.tx_bytes += skb->len;
+
+ if (el3_debug > 4) {
+- printk("%s: el3_start_xmit(length = %u) called, status %4.4x.\n",
++ printk(KERN_DEBUG "%s: el3_start_xmit(length = %u) called, status %4.4x.\n",
+ dev->name, skb->len, inw(ioaddr + EL3_STATUS));
+ }
+ #if 0
+@@ -840,7 +832,7 @@ el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ ushort status = inw(ioaddr + EL3_STATUS);
+ if (status & 0x0001 /* IRQ line active, missed one. */
+ && inw(ioaddr + EL3_STATUS) & 1) { /* Make sure. */
+- printk("%s: Missed interrupt, status then %04x now %04x"
++ printk(KERN_DEBUG "%s: Missed interrupt, status then %04x now %04x"
+ " Tx %2.2x Rx %4.4x.\n", dev->name, status,
+ inw(ioaddr + EL3_STATUS), inb(ioaddr + TX_STATUS),
+ inw(ioaddr + RX_STATUS));
+@@ -914,7 +906,7 @@ el3_interrupt(int irq, void *dev_id)
+
+ if (el3_debug > 4) {
+ status = inw(ioaddr + EL3_STATUS);
+- printk("%s: interrupt, status %4.4x.\n", dev->name, status);
++ printk(KERN_DEBUG "%s: interrupt, status %4.4x.\n", dev->name, status);
+ }
+
+ while ((status = inw(ioaddr + EL3_STATUS)) &
+@@ -925,7 +917,7 @@ el3_interrupt(int irq, void *dev_id)
+
+ if (status & TxAvailable) {
+ if (el3_debug > 5)
+- printk(" TX room bit was handled.\n");
++ printk(KERN_DEBUG " TX room bit was handled.\n");
+ /* There's room in the FIFO for a full-sized packet. */
+ outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
+ netif_wake_queue (dev);
+@@ -964,7 +956,7 @@ el3_interrupt(int irq, void *dev_id)
+ }
+
+ if (--i < 0) {
+- printk("%s: Infinite loop in interrupt, status %4.4x.\n",
++ printk(KERN_ERR "%s: Infinite loop in interrupt, status %4.4x.\n",
+ dev->name, status);
+ /* Clear all interrupts. */
+ outw(AckIntr | 0xFF, ioaddr + EL3_CMD);
+@@ -975,7 +967,7 @@ el3_interrupt(int irq, void *dev_id)
+ }
+
+ if (el3_debug > 4) {
+- printk("%s: exiting interrupt, status %4.4x.\n", dev->name,
++ printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n", dev->name,
+ inw(ioaddr + EL3_STATUS));
+ }
+ spin_unlock(&lp->lock);
+@@ -1450,7 +1442,7 @@ el3_up(struct net_device *dev)
+ }
+
+ /* Power Management support functions */
+-#ifdef EL3_SUSPEND
++#ifdef CONFIG_PM
+
+ static int
+ el3_suspend(struct device *pdev, pm_message_t state)
+@@ -1500,79 +1492,102 @@ el3_resume(struct device *pdev)
+ return 0;
+ }
+
+-#endif /* EL3_SUSPEND */
+-
+-/* Parameters that may be passed into the module. */
+-static int debug = -1;
+-static int irq[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+-static int xcvr[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
++#endif /* CONFIG_PM */
+
+ module_param(debug,int, 0);
+ module_param_array(irq, int, NULL, 0);
+-module_param_array(xcvr, int, NULL, 0);
+ module_param(max_interrupt_work, int, 0);
+ MODULE_PARM_DESC(debug, "debug level (0-6)");
+ MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
+-MODULE_PARM_DESC(xcvr,"transceiver(s) (0=internal, 1=external)");
+ MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt");
+-#if defined(__ISAPNP__)
++#ifdef CONFIG_PNP
+ module_param(nopnp, int, 0);
+ MODULE_PARM_DESC(nopnp, "disable ISA PnP support (0-1)");
+-MODULE_DEVICE_TABLE(isapnp, el3_isapnp_adapters);
+-#endif /* __ISAPNP__ */
+-MODULE_DESCRIPTION("3Com Etherlink III (3c509, 3c509B) ISA/PnP ethernet driver");
++#endif /* CONFIG_PNP */
++MODULE_DESCRIPTION("3Com Etherlink III (3c509, 3c509B, 3c529, 3c579) ethernet driver");
+ MODULE_LICENSE("GPL");
+
+ static int __init el3_init_module(void)
+ {
+ int ret = 0;
+- el3_cards = 0;
+
+ if (debug >= 0)
+ el3_debug = debug;
+
+- el3_root_dev = NULL;
+- while (el3_probe(el3_cards) == 0) {
+- if (irq[el3_cards] > 1)
+- el3_root_dev->irq = irq[el3_cards];
+- if (xcvr[el3_cards] >= 0)
+- el3_root_dev->if_port = xcvr[el3_cards];
+- el3_cards++;
++#ifdef CONFIG_PNP
++ if (!nopnp) {
++ ret = pnp_register_driver(&el3_pnp_driver);
++ if (!ret)
++ pnp_registered = 1;
++ }
++#endif
++ /* Select an open I/O location at 0x1*0 to do ISA contention select. */
++ /* Start with 0x110 to avoid some sound cards.*/
++ for (id_port = 0x110 ; id_port < 0x200; id_port += 0x10) {
++ if (!request_region(id_port, 1, "3c509-control"))
++ continue;
++ outb(0x00, id_port);
++ outb(0xff, id_port);
++ if (inb(id_port) & 0x01)
++ break;
++ else
++ release_region(id_port, 1);
++ }
++ if (id_port >= 0x200) {
++ id_port = 0;
++ printk(KERN_ERR "No I/O port available for 3c509 activation.\n");
++ } else {
++ ret = isa_register_driver(&el3_isa_driver, EL3_MAX_CARDS);
++ if (!ret)
++ isa_registered = 1;
+ }
+-
+ #ifdef CONFIG_EISA
+ ret = eisa_driver_register(&el3_eisa_driver);
++ if (!ret)
++ eisa_registered = 1;
+ #endif
+ #ifdef CONFIG_MCA
+- {
+- int err = mca_register_driver(&el3_mca_driver);
+- if (ret == 0)
+- ret = err;
+- }
++ ret = mca_register_driver(&el3_mca_driver);
++ if (!ret)
++ mca_registered = 1;
++#endif
++
++#ifdef CONFIG_PNP
++ if (pnp_registered)
++ ret = 0;
++#endif
++ if (isa_registered)
++ ret = 0;
++#ifdef CONFIG_EISA
++ if (eisa_registered)
++ ret = 0;
++#endif
++#ifdef CONFIG_MCA
++ if (mca_registered)
++ ret = 0;
+ #endif
+ return ret;
+ }
+
+ static void __exit el3_cleanup_module(void)
+ {
+- struct net_device *next_dev;
+-
+- while (el3_root_dev) {
+- struct el3_private *lp = netdev_priv(el3_root_dev);
+-
+- next_dev = lp->next_dev;
+- el3_common_remove (el3_root_dev);
+- el3_root_dev = next_dev;
+- }
+-
++#ifdef CONFIG_PNP
++ if (pnp_registered)
++ pnp_unregister_driver(&el3_pnp_driver);
++#endif
++ if (isa_registered)
++ isa_unregister_driver(&el3_isa_driver);
++ if (id_port)
++ release_region(id_port, 1);
+ #ifdef CONFIG_EISA
+- eisa_driver_unregister (&el3_eisa_driver);
++ if (eisa_registered)
++ eisa_driver_unregister(&el3_eisa_driver);
+ #endif
+ #ifdef CONFIG_MCA
+- mca_unregister_driver(&el3_mca_driver);
++ if (mca_registered)
++ mca_unregister_driver(&el3_mca_driver);
+ #endif
+ }
+
+ module_init (el3_init_module);
+ module_exit (el3_cleanup_module);
+-
+diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c
+index b72b89d..fae295b 100644
+--- a/drivers/net/3c527.c
++++ b/drivers/net/3c527.c
+@@ -103,8 +103,8 @@ DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Richard Procter <rnp at paradise.net.
+ #include <linux/ethtool.h>
+ #include <linux/completion.h>
+ #include <linux/bitops.h>
++#include <linux/semaphore.h>
+
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+ #include <asm/io.h>
+diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
+index be6e918..53bd903 100644
+--- a/drivers/net/8139too.c
++++ b/drivers/net/8139too.c
+@@ -966,8 +966,8 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
+
+ addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6;
+ for (i = 0; i < 3; i++)
+- ((u16 *) (dev->dev_addr))[i] =
+- le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len));
++ ((__le16 *) (dev->dev_addr))[i] =
++ cpu_to_le16(read_eeprom (ioaddr, i + 7, addr_len));
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+
+ /* The Rtl8139-specific entries in the device structure. */
+@@ -1373,8 +1373,8 @@ static void rtl8139_hw_start (struct net_device *dev)
+ /* unlock Config[01234] and BMCR register writes */
+ RTL_W8_F (Cfg9346, Cfg9346_Unlock);
+ /* Restore our idea of the MAC address. */
+- RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0)));
+- RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4)));
++ RTL_W32_F (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0)));
++ RTL_W32_F (MAC0 + 4, le16_to_cpu (*(__le16 *) (dev->dev_addr + 4)));
+
+ /* Must enable Tx/Rx before setting transfer thresholds! */
+ RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
+@@ -1945,7 +1945,7 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
+ rmb();
+
+ /* read size+status of next frame from DMA ring buffer */
+- rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset));
++ rx_status = le32_to_cpu (*(__le32 *) (rx_ring + ring_offset));
+ rx_size = rx_status >> 16;
+ pkt_size = rx_size - 4;
+
+diff --git a/drivers/net/8390.c b/drivers/net/8390.c
+index a828076..a499e86 100644
+--- a/drivers/net/8390.c
++++ b/drivers/net/8390.c
+@@ -48,14 +48,16 @@ EXPORT_SYMBOL(__alloc_ei_netdev);
+
+ #if defined(MODULE)
+
+-int init_module(void)
++static int __init ns8390_module_init(void)
+ {
+ return 0;
+ }
+
+-void cleanup_module(void)
++static void __exit ns8390_module_exit(void)
+ {
+ }
+
++module_init(ns8390_module_init);
++module_exit(ns8390_module_exit);
+ #endif /* MODULE */
+ MODULE_LICENSE("GPL");
+diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
+index 3a0b20a..0697aa8 100644
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -467,6 +467,13 @@ config SNI_82596
+ Say Y here to support the on-board Intel 82596 ethernet controller
+ built into SNI RM machines.
+
++config KORINA
++ tristate "Korina (IDT RC32434) Ethernet support"
++ depends on NET_ETHERNET && MIKROTIK_RB500
++ help
++ If you have a Mikrotik RouterBoard 500 or IDT RC32434
++ based system say Y. Otherwise say N.
++
+ config MIPS_JAZZ_SONIC
+ tristate "MIPS JAZZ onboard SONIC Ethernet support"
+ depends on MACH_JAZZ
+@@ -820,7 +827,7 @@ config ULTRA32
+
+ config BFIN_MAC
+ tristate "Blackfin 527/536/537 on-chip mac support"
+- depends on NET_ETHERNET && (BF527 || BF537 || BF536) && (!BF537_PORT_H)
++ depends on NET_ETHERNET && (BF527 || BF537 || BF536)
+ select CRC32
+ select MII
+ select PHYLIB
+@@ -1431,7 +1438,7 @@ config CS89x0
+ config TC35815
+ tristate "TOSHIBA TC35815 Ethernet support"
+ depends on NET_PCI && PCI && MIPS
+- select MII
++ select PHYLIB
+
+ config EEPRO100
+ tristate "EtherExpressPro/100 support (eepro100, original Becker driver)"
+@@ -2220,93 +2227,6 @@ config SKY2_DEBUG
+
+ If unsure, say N.
+
+-config SK98LIN
+- tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support (DEPRECATED)"
+- depends on PCI
+- ---help---
+- Say Y here if you have a Marvell Yukon or SysKonnect SK-98xx/SK-95xx
+- compliant Gigabit Ethernet Adapter.
+-
+- This driver supports the original Yukon chipset. This driver is
+- deprecated and will be removed from the kernel in the near future,
+- it has been replaced by the skge driver. skge is cleaner and
+- seems to work better.
+-
+- This driver does not support the newer Yukon2 chipset. A separate
+- driver, sky2, is provided to support Yukon2-based adapters.
+-
+- The following adapters are supported by this driver:
+- - 3Com 3C940 Gigabit LOM Ethernet Adapter
+- - 3Com 3C941 Gigabit LOM Ethernet Adapter
+- - Allied Telesyn AT-2970LX Gigabit Ethernet Adapter
+- - Allied Telesyn AT-2970LX/2SC Gigabit Ethernet Adapter
+- - Allied Telesyn AT-2970SX Gigabit Ethernet Adapter
+- - Allied Telesyn AT-2970SX/2SC Gigabit Ethernet Adapter
+- - Allied Telesyn AT-2970TX Gigabit Ethernet Adapter
+- - Allied Telesyn AT-2970TX/2TX Gigabit Ethernet Adapter
+- - Allied Telesyn AT-2971SX Gigabit Ethernet Adapter
+- - Allied Telesyn AT-2971T Gigabit Ethernet Adapter
+- - Belkin Gigabit Desktop Card 10/100/1000Base-T Adapter, Copper RJ-45
+- - EG1032 v2 Instant Gigabit Network Adapter
+- - EG1064 v2 Instant Gigabit Network Adapter
+- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Abit)
+- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Albatron)
+- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Asus)
+- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (ECS)
+- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Epox)
+- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Foxconn)
+- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Gigabyte)
+- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Iwill)
+- - Marvell 88E8050 Gigabit LOM Ethernet Adapter (Intel)
+- - Marvell RDK-8001 Adapter
+- - Marvell RDK-8002 Adapter
+- - Marvell RDK-8003 Adapter
+- - Marvell RDK-8004 Adapter
+- - Marvell RDK-8006 Adapter
+- - Marvell RDK-8007 Adapter
+- - Marvell RDK-8008 Adapter
+- - Marvell RDK-8009 Adapter
+- - Marvell RDK-8010 Adapter
+- - Marvell RDK-8011 Adapter
+- - Marvell RDK-8012 Adapter
+- - Marvell RDK-8052 Adapter
+- - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (32 bit)
+- - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (64 bit)
+- - N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L)
+- - SK-9521 10/100/1000Base-T Adapter
+- - SK-9521 V2.0 10/100/1000Base-T Adapter
+- - SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T)
+- - SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter
+- - SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link)
+- - SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX)
+- - SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter
+- - SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link)
+- - SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX)
+- - SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter
+- - SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link)
+- - SK-9851 V2.0 Gigabit Ethernet 1000Base-SX Adapter
+- - SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition)
+- - SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter
+- - SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link)
+- - SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX)
+- - SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter
+- - SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link)
+- - SMC EZ Card 1000 (SMC9452TXV.2)
+-
+- The adapters support Jumbo Frames.
+- The dual link adapters support link-failover and dual port features.
+- Both Marvell Yukon and SysKonnect SK-98xx/SK-95xx adapters support
+- the scatter-gather functionality with sendfile(). Please refer to
+- <file:Documentation/networking/sk98lin.txt> for more information about
+- optional driver parameters.
+- Questions concerning this driver may be addressed to:
+- <linux at syskonnect.de>
+-
+- If you want to compile this driver as a module ( = code which can be
+- inserted in and removed from the running kernel whenever you want),
+- say M here and read <file:Documentation/kbuild/modules.txt>. The module will
+- be called sk98lin. This is recommended.
+-
+ config VIA_VELOCITY
+ tristate "VIA Velocity support"
+ depends on PCI
+@@ -2358,6 +2278,7 @@ config TSI108_ETH
+ config GELIC_NET
+ tristate "PS3 Gigabit Ethernet driver"
+ depends on PPC_PS3
++ select PS3_SYS_MANAGER
+ help
+ This driver supports the network device on the PS3 game
+ console. This driver has built-in support for Ethernet.
+@@ -2415,7 +2336,7 @@ config UGETH_TX_ON_DEMAND
+
+ config MV643XX_ETH
+ tristate "Marvell Discovery (643XX) and Orion ethernet support"
+- depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32) || ARCH_ORION
++ depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32) || PLAT_ORION
+ select MII
+ help
+ This driver supports the gigabit ethernet MACs in the
+diff --git a/drivers/net/Makefile b/drivers/net/Makefile
+index 3b1ea32..2f1f3f2 100644
+--- a/drivers/net/Makefile
++++ b/drivers/net/Makefile
+@@ -15,7 +15,7 @@ obj-$(CONFIG_CHELSIO_T3) += cxgb3/
+ obj-$(CONFIG_EHEA) += ehea/
+ obj-$(CONFIG_CAN) += can/
+ obj-$(CONFIG_BONDING) += bonding/
+-obj-$(CONFIG_ATL1) += atl1/
++obj-$(CONFIG_ATL1) += atlx/
+ obj-$(CONFIG_GIANFAR) += gianfar_driver.o
+ obj-$(CONFIG_TEHUTI) += tehuti.o
+
+@@ -75,7 +75,6 @@ ps3_gelic-objs += ps3_gelic_net.o $(gelic_wireless-y)
+ obj-$(CONFIG_TC35815) += tc35815.o
+ obj-$(CONFIG_SKGE) += skge.o
+ obj-$(CONFIG_SKY2) += sky2.o
+-obj-$(CONFIG_SK98LIN) += sk98lin/
+ obj-$(CONFIG_SKFP) += skfp/
+ obj-$(CONFIG_VIA_RHINE) += via-rhine.o
+ obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
+@@ -191,6 +190,7 @@ obj-$(CONFIG_ZORRO8390) += zorro8390.o
+ obj-$(CONFIG_HPLANCE) += hplance.o 7990.o
+ obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o
+ obj-$(CONFIG_EQUALIZER) += eql.o
++obj-$(CONFIG_KORINA) += korina.o
+ obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o
+ obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o
+ obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o
+@@ -218,7 +218,8 @@ obj-$(CONFIG_SMC911X) += smc911x.o
+ obj-$(CONFIG_BFIN_MAC) += bfin_mac.o
+ obj-$(CONFIG_DM9000) += dm9000.o
+ obj-$(CONFIG_FEC_8XX) += fec_8xx/
+-obj-$(CONFIG_PASEMI_MAC) += pasemi_mac.o
++obj-$(CONFIG_PASEMI_MAC) += pasemi_mac_driver.o
++pasemi_mac_driver-objs := pasemi_mac.o pasemi_mac_ethtool.o
+ obj-$(CONFIG_MLX4_CORE) += mlx4/
+ obj-$(CONFIG_ENC28J60) += enc28j60.o
+
+diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
+index c59c806..bdc4c0b 100644
+--- a/drivers/net/arcnet/arcnet.c
++++ b/drivers/net/arcnet/arcnet.c
+@@ -940,7 +940,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
+
+ /* is the RECON info empty or old? */
+ if (!lp->first_recon || !lp->last_recon ||
+- jiffies - lp->last_recon > HZ * 10) {
++ time_after(jiffies, lp->last_recon + HZ * 10)) {
+ if (lp->network_down)
+ BUGMSG(D_NORMAL, "reconfiguration detected: cabling restored?\n");
+ lp->first_recon = lp->last_recon = jiffies;
+@@ -974,7 +974,8 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
+ lp->num_recons = 1;
+ }
+ }
+- } else if (lp->network_down && jiffies - lp->last_recon > HZ * 10) {
++ } else if (lp->network_down &&
++ time_after(jiffies, lp->last_recon + HZ * 10)) {
+ if (lp->network_down)
+ BUGMSG(D_NORMAL, "cabling restored?\n");
+ lp->first_recon = lp->last_recon = 0;
+diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c
+index 7cf0a25..8b51313 100644
+--- a/drivers/net/arcnet/com20020.c
++++ b/drivers/net/arcnet/com20020.c
+@@ -348,14 +348,15 @@ MODULE_LICENSE("GPL");
+
+ #ifdef MODULE
+
+-int init_module(void)
++static int __init com20020_module_init(void)
+ {
+ BUGLVL(D_NORMAL) printk(VERSION);
+ return 0;
+ }
+
+-void cleanup_module(void)
++static void __exit com20020_module_exit(void)
+ {
+ }
+-
++module_init(com20020_module_init);
++module_exit(com20020_module_exit);
+ #endif /* MODULE */
+diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c
+index 0ae0d83..1e39e78 100644
+--- a/drivers/net/arm/at91_ether.c
++++ b/drivers/net/arm/at91_ether.c
+@@ -1043,7 +1043,9 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add
+ } else if (machine_is_csb337()) {
+ /* mix link activity status into LED2 link state */
+ write_phy(phy_address, MII_LEDCTRL_REG, 0x0d22);
+- }
++ } else if (machine_is_ecbat91())
++ write_phy(phy_address, MII_LEDCTRL_REG, 0x156A);
++
+ disable_mdi();
+ spin_unlock_irq(&lp->lock);
+
+@@ -1246,3 +1248,4 @@ module_exit(at91ether_exit)
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver");
+ MODULE_AUTHOR("Andrew Victor");
++MODULE_ALIAS("platform:" DRV_NAME);
+diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
+index 91a6590..ecd8fc6 100644
+--- a/drivers/net/arm/ep93xx_eth.c
++++ b/drivers/net/arm/ep93xx_eth.c
+@@ -897,6 +897,7 @@ static struct platform_driver ep93xx_eth_driver = {
+ .remove = ep93xx_eth_remove,
+ .driver = {
+ .name = "ep93xx-eth",
++ .owner = THIS_MODULE,
+ },
+ };
+
+@@ -914,3 +915,4 @@ static void __exit ep93xx_eth_cleanup_module(void)
+ module_init(ep93xx_eth_init_module);
+ module_exit(ep93xx_eth_cleanup_module);
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:ep93xx-eth");
+diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c
+index 24d81f9..7e874d4 100644
+--- a/drivers/net/at1700.c
++++ b/drivers/net/at1700.c
+@@ -881,7 +881,7 @@ MODULE_PARM_DESC(io, "AT1700/FMV18X I/O base address");
+ MODULE_PARM_DESC(irq, "AT1700/FMV18X IRQ number");
+ MODULE_PARM_DESC(net_debug, "AT1700/FMV18X debug level (0-6)");
+
+-int __init init_module(void)
++static int __init at1700_module_init(void)
+ {
+ if (io == 0)
+ printk("at1700: You should not use auto-probing with insmod!\n");
+@@ -891,13 +891,14 @@ int __init init_module(void)
+ return 0;
+ }
+
+-void __exit
+-cleanup_module(void)
++static void __exit at1700_module_exit(void)
+ {
+ unregister_netdev(dev_at1700);
+ cleanup_card(dev_at1700);
+ free_netdev(dev_at1700);
+ }
++module_init(at1700_module_init);
++module_exit(at1700_module_exit);
+ #endif /* MODULE */
+ MODULE_LICENSE("GPL");
+
+diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c
+index 13c293b..4cceaac 100644
+--- a/drivers/net/atarilance.c
++++ b/drivers/net/atarilance.c
+@@ -1155,7 +1155,7 @@ static int lance_set_mac_address( struct net_device *dev, void *addr )
+ #ifdef MODULE
+ static struct net_device *atarilance_dev;
+
+-int __init init_module(void)
++static int __init atarilance_module_init(void)
+ {
+ atarilance_dev = atarilance_probe(-1);
+ if (IS_ERR(atarilance_dev))
+@@ -1163,13 +1163,14 @@ int __init init_module(void)
+ return 0;
+ }
+
+-void __exit cleanup_module(void)
++static void __exit atarilance_module_exit(void)
+ {
+ unregister_netdev(atarilance_dev);
+ free_irq(atarilance_dev->irq, atarilance_dev);
+ free_netdev(atarilance_dev);
+ }
+-
++module_init(atarilance_module_init);
++module_exit(atarilance_module_exit);
+ #endif /* MODULE */
+
+
+diff --git a/drivers/net/atl1/Makefile b/drivers/net/atl1/Makefile
+deleted file mode 100644
+index a6b707e..0000000
+--- a/drivers/net/atl1/Makefile
++++ /dev/null
+@@ -1,2 +0,0 @@
+-obj-$(CONFIG_ATL1) += atl1.o
+-atl1-y += atl1_main.o atl1_hw.o atl1_ethtool.o atl1_param.o
+diff --git a/drivers/net/atl1/atl1.h b/drivers/net/atl1/atl1.h
+deleted file mode 100644
+index ff4765f..0000000
+--- a/drivers/net/atl1/atl1.h
++++ /dev/null
+@@ -1,286 +0,0 @@
+-/*
+- * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+- * Copyright(c) 2006 Chris Snook <csnook at redhat.com>
+- * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
+- *
+- * 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 _ATL1_H_
+-#define _ATL1_H_
+-
+-#include <linux/types.h>
+-#include <linux/if_vlan.h>
+-
+-#include "atl1_hw.h"
+-
+-/* function prototypes needed by multiple files */
+-s32 atl1_up(struct atl1_adapter *adapter);
+-void atl1_down(struct atl1_adapter *adapter);
+-int atl1_reset(struct atl1_adapter *adapter);
+-s32 atl1_setup_ring_resources(struct atl1_adapter *adapter);
+-void atl1_free_ring_resources(struct atl1_adapter *adapter);
+-
+-extern char atl1_driver_name[];
+-extern char atl1_driver_version[];
+-extern const struct ethtool_ops atl1_ethtool_ops;
+-
+-struct atl1_adapter;
+-
+-#define ATL1_MAX_INTR 3
+-#define ATL1_MAX_TX_BUF_LEN 0x3000 /* 12288 bytes */
+-
+-#define ATL1_DEFAULT_TPD 256
+-#define ATL1_MAX_TPD 1024
+-#define ATL1_MIN_TPD 64
+-#define ATL1_DEFAULT_RFD 512
+-#define ATL1_MIN_RFD 128
+-#define ATL1_MAX_RFD 2048
+-
+-#define ATL1_GET_DESC(R, i, type) (&(((type *)((R)->desc))[i]))
+-#define ATL1_RFD_DESC(R, i) ATL1_GET_DESC(R, i, struct rx_free_desc)
+-#define ATL1_TPD_DESC(R, i) ATL1_GET_DESC(R, i, struct tx_packet_desc)
+-#define ATL1_RRD_DESC(R, i) ATL1_GET_DESC(R, i, struct rx_return_desc)
+-
+-/*
+- * This detached comment is preserved for documentation purposes only.
+- * It was originally attached to some code that got deleted, but seems
+- * important enough to keep around...
+- *
+- * <begin detached comment>
+- * Some workarounds require millisecond delays and are run during interrupt
+- * context. Most notably, when establishing link, the phy may need tweaking
+- * but cannot process phy register reads/writes faster than millisecond
+- * intervals...and we establish link due to a "link status change" interrupt.
+- * <end detached comment>
+- */
+-
+-/*
+- * atl1_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 atl1_ring_header {
+- void *desc; /* virtual address */
+- dma_addr_t dma; /* physical address*/
+- unsigned int size; /* length in bytes */
+-};
+-
+-/*
+- * atl1_buffer is wrapper around a pointer to a socket buffer
+- * so a DMA handle can be stored along with the skb
+- */
+-struct atl1_buffer {
+- struct sk_buff *skb; /* socket buffer */
+- u16 length; /* rx buffer length */
+- u16 alloced; /* 1 if skb allocated */
+- dma_addr_t dma;
+-};
+-
+-/* transmit packet descriptor (tpd) ring */
+-struct atl1_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 hw_idx; /* hardware index */
+- atomic_t next_to_clean;
+- atomic_t next_to_use;
+- struct atl1_buffer *buffer_info;
+-};
+-
+-/* receive free descriptor (rfd) ring */
+-struct atl1_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 */
+- atomic_t next_to_use;
+- u16 next_to_clean;
+- struct atl1_buffer *buffer_info;
+-};
+-
+-/* receive return descriptor (rrd) ring */
+-struct atl1_rrd_ring {
+- void *desc; /* descriptor ring virtual address */
+- dma_addr_t dma; /* descriptor ring physical address */
+- unsigned int size; /* descriptor ring length in bytes */
+- u16 count; /* number of descriptors in the ring */
+- u16 next_to_use;
+- atomic_t next_to_clean;
+-};
+-
+-/* coalescing message block (cmb) */
+-struct atl1_cmb {
+- struct coals_msg_block *cmb;
+- dma_addr_t dma;
+-};
+-
+-/* statistics message block (smb) */
+-struct atl1_smb {
+- struct stats_msg_block *smb;
+- dma_addr_t dma;
+-};
+-
+-/* Statistics counters */
+-struct atl1_sft_stats {
+- u64 rx_packets;
+- u64 tx_packets;
+- u64 rx_bytes;
+- u64 tx_bytes;
+- u64 multicast;
+- u64 collisions;
+- u64 rx_errors;
+- u64 rx_length_errors;
+- u64 rx_crc_errors;
+- u64 rx_frame_errors;
+- u64 rx_fifo_errors;
+- u64 rx_missed_errors;
+- u64 tx_errors;
+- u64 tx_fifo_errors;
+- u64 tx_aborted_errors;
+- u64 tx_window_errors;
+- u64 tx_carrier_errors;
+- u64 tx_pause; /* num pause packets transmitted. */
+- u64 excecol; /* num tx packets w/ excessive collisions. */
+- u64 deffer; /* num tx packets deferred */
+- u64 scc; /* num packets subsequently transmitted
+- * successfully w/ single prior collision. */
+- u64 mcc; /* num packets subsequently transmitted
+- * successfully w/ multiple prior collisions. */
+- u64 latecol; /* num tx packets w/ late collisions. */
+- u64 tx_underun; /* num tx packets aborted due to transmit
+- * FIFO underrun, or TRD FIFO underrun */
+- u64 tx_trunc; /* num tx packets truncated due to size
+- * exceeding MTU, regardless whether truncated
+- * by the chip or not. (The name doesn't really
+- * reflect the meaning in this case.) */
+- u64 rx_pause; /* num Pause packets received. */
+- u64 rx_rrd_ov;
+- u64 rx_trunc;
+-};
+-
+-/* hardware structure */
+-struct atl1_hw {
+- u8 __iomem *hw_addr;
+- struct atl1_adapter *back;
+- enum atl1_dma_order dma_ord;
+- enum atl1_dma_rcb rcb_value;
+- enum atl1_dma_req_block dmar_block;
+- enum atl1_dma_req_block dmaw_block;
+- u8 preamble_len;
+- u8 max_retry; /* Retransmission maximum, after which the
+- * packet will be discarded */
+- u8 jam_ipg; /* IPG to start JAM for collision based flow
+- * control in half-duplex mode. In units of
+- * 8-bit time */
+- u8 ipgt; /* Desired back to back inter-packet gap.
+- * The default is 96-bit time */
+- u8 min_ifg; /* Minimum number of IFG to enforce in between
+- * receive frames. Frame gap below such IFP
+- * is dropped */
+- u8 ipgr1; /* 64bit Carrier-Sense window */
+- u8 ipgr2; /* 96-bit IPG window */
+- u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned
+- * burst. Each TPD is 16 bytes long */
+- u8 rfd_burst; /* Number of RFD to prefetch in cache-aligned
+- * burst. Each RFD is 12 bytes long */
+- u8 rfd_fetch_gap;
+- u8 rrd_burst; /* Threshold number of RRDs that can be retired
+- * in a burst. Each RRD is 16 bytes long */
+- u8 tpd_fetch_th;
+- u8 tpd_fetch_gap;
+- u16 tx_jumbo_task_th;
+- u16 txf_burst; /* Number of data bytes to read in a cache-
+- * aligned burst. Each SRAM entry is 8 bytes */
+- u16 rx_jumbo_th; /* Jumbo packet size for non-VLAN packet. VLAN
+- * packets should add 4 bytes */
+- u16 rx_jumbo_lkah;
+- u16 rrd_ret_timer; /* RRD retirement timer. Decrement by 1 after
+- * every 512ns passes. */
+- u16 lcol; /* Collision Window */
+-
+- u16 cmb_tpd;
+- u16 cmb_rrd;
+- u16 cmb_rx_timer;
+- u16 cmb_tx_timer;
+- u32 smb_timer;
+- u16 media_type;
+- u16 autoneg_advertised;
+-
+- u16 mii_autoneg_adv_reg;
+- u16 mii_1000t_ctrl_reg;
+-
+- u32 max_frame_size;
+- u32 min_frame_size;
+-
+- u16 dev_rev;
+-
+- /* spi flash */
+- u8 flash_vendor;
+-
+- u8 mac_addr[ETH_ALEN];
+- u8 perm_mac_addr[ETH_ALEN];
+-
+- bool phy_configured;
+-};
+-
+-struct atl1_adapter {
+- struct net_device *netdev;
+- struct pci_dev *pdev;
+- struct net_device_stats net_stats;
+- struct atl1_sft_stats soft_stats;
+- struct vlan_group *vlgrp;
+- u32 rx_buffer_len;
+- u32 wol;
+- u16 link_speed;
+- u16 link_duplex;
+- spinlock_t lock;
+- struct work_struct tx_timeout_task;
+- struct work_struct link_chg_task;
+- struct work_struct pcie_dma_to_rst_task;
+- struct timer_list watchdog_timer;
+- struct timer_list phy_config_timer;
+- bool phy_timer_pending;
+-
+- /* all descriptor rings' memory */
+- struct atl1_ring_header ring_header;
+-
+- /* TX */
+- struct atl1_tpd_ring tpd_ring;
+- spinlock_t mb_lock;
+-
+- /* RX */
+- struct atl1_rfd_ring rfd_ring;
+- struct atl1_rrd_ring rrd_ring;
+- u64 hw_csum_err;
+- u64 hw_csum_good;
+-
+- u16 imt; /* interrupt moderator timer (2us resolution */
+- u16 ict; /* interrupt clear timer (2us resolution */
+- struct mii_if_info mii; /* MII interface info */
+-
+- /* structs defined in atl1_hw.h */
+- u32 bd_number; /* board number */
+- bool pci_using_64;
+- struct atl1_hw hw;
+- struct atl1_smb smb;
+- struct atl1_cmb cmb;
+-};
+-
+-#endif /* _ATL1_H_ */
+diff --git a/drivers/net/atl1/atl1_ethtool.c b/drivers/net/atl1/atl1_ethtool.c
+deleted file mode 100644
+index 68a83be..0000000
+--- a/drivers/net/atl1/atl1_ethtool.c
++++ /dev/null
+@@ -1,505 +0,0 @@
+-/*
+- * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+- * Copyright(c) 2006 Chris Snook <csnook at redhat.com>
+- * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
+- *
+- * 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/types.h>
+-#include <linux/pci.h>
+-#include <linux/ethtool.h>
+-#include <linux/netdevice.h>
+-#include <linux/mii.h>
+-#include <asm/uaccess.h>
+-
+-#include "atl1.h"
+-
+-struct atl1_stats {
+- char stat_string[ETH_GSTRING_LEN];
+- int sizeof_stat;
+- int stat_offset;
+-};
+-
+-#define ATL1_STAT(m) sizeof(((struct atl1_adapter *)0)->m), \
+- offsetof(struct atl1_adapter, m)
+-
+-static struct atl1_stats atl1_gstrings_stats[] = {
+- {"rx_packets", ATL1_STAT(soft_stats.rx_packets)},
+- {"tx_packets", ATL1_STAT(soft_stats.tx_packets)},
+- {"rx_bytes", ATL1_STAT(soft_stats.rx_bytes)},
+- {"tx_bytes", ATL1_STAT(soft_stats.tx_bytes)},
+- {"rx_errors", ATL1_STAT(soft_stats.rx_errors)},
+- {"tx_errors", ATL1_STAT(soft_stats.tx_errors)},
+- {"rx_dropped", ATL1_STAT(net_stats.rx_dropped)},
+- {"tx_dropped", ATL1_STAT(net_stats.tx_dropped)},
+- {"multicast", ATL1_STAT(soft_stats.multicast)},
+- {"collisions", ATL1_STAT(soft_stats.collisions)},
+- {"rx_length_errors", ATL1_STAT(soft_stats.rx_length_errors)},
+- {"rx_over_errors", ATL1_STAT(soft_stats.rx_missed_errors)},
+- {"rx_crc_errors", ATL1_STAT(soft_stats.rx_crc_errors)},
+- {"rx_frame_errors", ATL1_STAT(soft_stats.rx_frame_errors)},
+- {"rx_fifo_errors", ATL1_STAT(soft_stats.rx_fifo_errors)},
+- {"rx_missed_errors", ATL1_STAT(soft_stats.rx_missed_errors)},
+- {"tx_aborted_errors", ATL1_STAT(soft_stats.tx_aborted_errors)},
+- {"tx_carrier_errors", ATL1_STAT(soft_stats.tx_carrier_errors)},
+- {"tx_fifo_errors", ATL1_STAT(soft_stats.tx_fifo_errors)},
+- {"tx_window_errors", ATL1_STAT(soft_stats.tx_window_errors)},
+- {"tx_abort_exce_coll", ATL1_STAT(soft_stats.excecol)},
+- {"tx_abort_late_coll", ATL1_STAT(soft_stats.latecol)},
+- {"tx_deferred_ok", ATL1_STAT(soft_stats.deffer)},
+- {"tx_single_coll_ok", ATL1_STAT(soft_stats.scc)},
+- {"tx_multi_coll_ok", ATL1_STAT(soft_stats.mcc)},
+- {"tx_underun", ATL1_STAT(soft_stats.tx_underun)},
+- {"tx_trunc", ATL1_STAT(soft_stats.tx_trunc)},
+- {"tx_pause", ATL1_STAT(soft_stats.tx_pause)},
+- {"rx_pause", ATL1_STAT(soft_stats.rx_pause)},
+- {"rx_rrd_ov", ATL1_STAT(soft_stats.rx_rrd_ov)},
+- {"rx_trunc", ATL1_STAT(soft_stats.rx_trunc)}
+-};
+-
+-static void atl1_get_ethtool_stats(struct net_device *netdev,
+- struct ethtool_stats *stats, u64 *data)
+-{
+- struct atl1_adapter *adapter = netdev_priv(netdev);
+- int i;
+- char *p;
+-
+- for (i = 0; i < ARRAY_SIZE(atl1_gstrings_stats); i++) {
+- p = (char *)adapter+atl1_gstrings_stats[i].stat_offset;
+- data[i] = (atl1_gstrings_stats[i].sizeof_stat ==
+- sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+- }
+-
+-}
+-
+-static int atl1_get_sset_count(struct net_device *netdev, int sset)
+-{
+- switch (sset) {
+- case ETH_SS_STATS:
+- return ARRAY_SIZE(atl1_gstrings_stats);
+- default:
+- return -EOPNOTSUPP;
+- }
+-}
+-
+-static int atl1_get_settings(struct net_device *netdev,
+- struct ethtool_cmd *ecmd)
+-{
+- struct atl1_adapter *adapter = netdev_priv(netdev);
+- struct atl1_hw *hw = &adapter->hw;
+-
+- ecmd->supported = (SUPPORTED_10baseT_Half |
+- SUPPORTED_10baseT_Full |
+- SUPPORTED_100baseT_Half |
+- SUPPORTED_100baseT_Full |
+- SUPPORTED_1000baseT_Full |
+- SUPPORTED_Autoneg | SUPPORTED_TP);
+- ecmd->advertising = ADVERTISED_TP;
+- if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+- hw->media_type == MEDIA_TYPE_1000M_FULL) {
+- ecmd->advertising |= ADVERTISED_Autoneg;
+- if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR) {
+- ecmd->advertising |= ADVERTISED_Autoneg;
+- ecmd->advertising |=
+- (ADVERTISED_10baseT_Half |
+- ADVERTISED_10baseT_Full |
+- ADVERTISED_100baseT_Half |
+- ADVERTISED_100baseT_Full |
+- ADVERTISED_1000baseT_Full);
+- }
+- else
+- ecmd->advertising |= (ADVERTISED_1000baseT_Full);
+- }
+- ecmd->port = PORT_TP;
+- ecmd->phy_address = 0;
+- ecmd->transceiver = XCVR_INTERNAL;
+-
+- if (netif_carrier_ok(adapter->netdev)) {
+- u16 link_speed, link_duplex;
+- atl1_get_speed_and_duplex(hw, &link_speed, &link_duplex);
+- ecmd->speed = link_speed;
+- if (link_duplex == FULL_DUPLEX)
+- ecmd->duplex = DUPLEX_FULL;
+- else
+- ecmd->duplex = DUPLEX_HALF;
+- } else {
+- ecmd->speed = -1;
+- ecmd->duplex = -1;
+- }
+- if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+- hw->media_type == MEDIA_TYPE_1000M_FULL)
+- ecmd->autoneg = AUTONEG_ENABLE;
+- else
+- ecmd->autoneg = AUTONEG_DISABLE;
+-
+- return 0;
+-}
+-
+-static int atl1_set_settings(struct net_device *netdev,
+- struct ethtool_cmd *ecmd)
+-{
+- struct atl1_adapter *adapter = netdev_priv(netdev);
+- struct atl1_hw *hw = &adapter->hw;
+- u16 phy_data;
+- int ret_val = 0;
+- u16 old_media_type = hw->media_type;
+-
+- if (netif_running(adapter->netdev)) {
+- dev_dbg(&adapter->pdev->dev, "ethtool shutting down adapter\n");
+- atl1_down(adapter);
+- }
+-
+- if (ecmd->autoneg == AUTONEG_ENABLE)
+- hw->media_type = MEDIA_TYPE_AUTO_SENSOR;
+- else {
+- if (ecmd->speed == SPEED_1000) {
+- if (ecmd->duplex != DUPLEX_FULL) {
+- dev_warn(&adapter->pdev->dev,
+- "can't force to 1000M half duplex\n");
+- ret_val = -EINVAL;
+- goto exit_sset;
+- }
+- hw->media_type = MEDIA_TYPE_1000M_FULL;
+- } else if (ecmd->speed == SPEED_100) {
+- if (ecmd->duplex == DUPLEX_FULL) {
+- hw->media_type = MEDIA_TYPE_100M_FULL;
+- } else
+- hw->media_type = MEDIA_TYPE_100M_HALF;
+- } else {
+- if (ecmd->duplex == DUPLEX_FULL)
+- hw->media_type = MEDIA_TYPE_10M_FULL;
+- else
+- hw->media_type = MEDIA_TYPE_10M_HALF;
+- }
+- }
+- switch (hw->media_type) {
+- case MEDIA_TYPE_AUTO_SENSOR:
+- ecmd->advertising =
+- ADVERTISED_10baseT_Half |
+- ADVERTISED_10baseT_Full |
+- ADVERTISED_100baseT_Half |
+- ADVERTISED_100baseT_Full |
+- ADVERTISED_1000baseT_Full |
+- ADVERTISED_Autoneg | ADVERTISED_TP;
+- break;
+- case MEDIA_TYPE_1000M_FULL:
+- ecmd->advertising =
+- ADVERTISED_1000baseT_Full |
+- ADVERTISED_Autoneg | ADVERTISED_TP;
+- break;
+- default:
+- ecmd->advertising = 0;
+- break;
+- }
+- if (atl1_phy_setup_autoneg_adv(hw)) {
+- ret_val = -EINVAL;
+- dev_warn(&adapter->pdev->dev,
+- "invalid ethtool speed/duplex setting\n");
+- goto exit_sset;
+- }
+- if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+- hw->media_type == MEDIA_TYPE_1000M_FULL)
+- phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
+- else {
+- switch (hw->media_type) {
+- case MEDIA_TYPE_100M_FULL:
+- phy_data =
+- MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
+- MII_CR_RESET;
+- break;
+- case MEDIA_TYPE_100M_HALF:
+- phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+- break;
+- case MEDIA_TYPE_10M_FULL:
+- phy_data =
+- MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
+- break;
+- default: /* MEDIA_TYPE_10M_HALF: */
+- phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+- break;
+- }
+- }
+- atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+-exit_sset:
+- if (ret_val)
+- hw->media_type = old_media_type;
+-
+- if (netif_running(adapter->netdev)) {
+- dev_dbg(&adapter->pdev->dev, "ethtool starting adapter\n");
+- atl1_up(adapter);
+- } else if (!ret_val) {
+- dev_dbg(&adapter->pdev->dev, "ethtool resetting adapter\n");
+- atl1_reset(adapter);
+- }
+- return ret_val;
+-}
+-
+-static void atl1_get_drvinfo(struct net_device *netdev,
+- struct ethtool_drvinfo *drvinfo)
+-{
+- struct atl1_adapter *adapter = netdev_priv(netdev);
+-
+- strncpy(drvinfo->driver, atl1_driver_name, sizeof(drvinfo->driver));
+- strncpy(drvinfo->version, atl1_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->eedump_len = ATL1_EEDUMP_LEN;
+-}
+-
+-static void atl1_get_wol(struct net_device *netdev,
+- struct ethtool_wolinfo *wol)
+-{
+- struct atl1_adapter *adapter = netdev_priv(netdev);
+-
+- wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
+- wol->wolopts = 0;
+- if (adapter->wol & ATL1_WUFC_EX)
+- wol->wolopts |= WAKE_UCAST;
+- if (adapter->wol & ATL1_WUFC_MC)
+- wol->wolopts |= WAKE_MCAST;
+- if (adapter->wol & ATL1_WUFC_BC)
+- wol->wolopts |= WAKE_BCAST;
+- if (adapter->wol & ATL1_WUFC_MAG)
+- wol->wolopts |= WAKE_MAGIC;
+- return;
+-}
+-
+-static int atl1_set_wol(struct net_device *netdev,
+- struct ethtool_wolinfo *wol)
+-{
+- struct atl1_adapter *adapter = netdev_priv(netdev);
+-
+- if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
+- return -EOPNOTSUPP;
+- adapter->wol = 0;
+- if (wol->wolopts & WAKE_UCAST)
+- adapter->wol |= ATL1_WUFC_EX;
+- if (wol->wolopts & WAKE_MCAST)
+- adapter->wol |= ATL1_WUFC_MC;
+- if (wol->wolopts & WAKE_BCAST)
+- adapter->wol |= ATL1_WUFC_BC;
+- if (wol->wolopts & WAKE_MAGIC)
+- adapter->wol |= ATL1_WUFC_MAG;
+- return 0;
+-}
+-
+-static void atl1_get_ringparam(struct net_device *netdev,
+- struct ethtool_ringparam *ring)
+-{
+- struct atl1_adapter *adapter = netdev_priv(netdev);
+- struct atl1_tpd_ring *txdr = &adapter->tpd_ring;
+- struct atl1_rfd_ring *rxdr = &adapter->rfd_ring;
+-
+- ring->rx_max_pending = ATL1_MAX_RFD;
+- ring->tx_max_pending = ATL1_MAX_TPD;
+- ring->rx_mini_max_pending = 0;
+- ring->rx_jumbo_max_pending = 0;
+- ring->rx_pending = rxdr->count;
+- ring->tx_pending = txdr->count;
+- ring->rx_mini_pending = 0;
+- ring->rx_jumbo_pending = 0;
+-}
+-
+-static int atl1_set_ringparam(struct net_device *netdev,
+- struct ethtool_ringparam *ring)
+-{
+- struct atl1_adapter *adapter = netdev_priv(netdev);
+- struct atl1_tpd_ring *tpdr = &adapter->tpd_ring;
+- struct atl1_rrd_ring *rrdr = &adapter->rrd_ring;
+- struct atl1_rfd_ring *rfdr = &adapter->rfd_ring;
+-
+- struct atl1_tpd_ring tpd_old, tpd_new;
+- struct atl1_rfd_ring rfd_old, rfd_new;
+- struct atl1_rrd_ring rrd_old, rrd_new;
+- struct atl1_ring_header rhdr_old, rhdr_new;
+- int err;
+-
+- tpd_old = adapter->tpd_ring;
+- rfd_old = adapter->rfd_ring;
+- rrd_old = adapter->rrd_ring;
+- rhdr_old = adapter->ring_header;
+-
+- if (netif_running(adapter->netdev))
+- atl1_down(adapter);
+-
+- rfdr->count = (u16) max(ring->rx_pending, (u32) ATL1_MIN_RFD);
+- rfdr->count = rfdr->count > ATL1_MAX_RFD ? ATL1_MAX_RFD :
+- rfdr->count;
+- rfdr->count = (rfdr->count + 3) & ~3;
+- rrdr->count = rfdr->count;
+-
+- tpdr->count = (u16) max(ring->tx_pending, (u32) ATL1_MIN_TPD);
+- tpdr->count = tpdr->count > ATL1_MAX_TPD ? ATL1_MAX_TPD :
+- tpdr->count;
+- tpdr->count = (tpdr->count + 3) & ~3;
+-
+- if (netif_running(adapter->netdev)) {
+- /* try to get new resources before deleting old */
+- err = atl1_setup_ring_resources(adapter);
+- if (err)
+- goto err_setup_ring;
+-
+- /*
+- * save the new, restore the old in order to free it,
+- * then restore the new back again
+- */
+-
+- rfd_new = adapter->rfd_ring;
+- rrd_new = adapter->rrd_ring;
+- tpd_new = adapter->tpd_ring;
+- rhdr_new = adapter->ring_header;
+- adapter->rfd_ring = rfd_old;
+- adapter->rrd_ring = rrd_old;
+- adapter->tpd_ring = tpd_old;
+- adapter->ring_header = rhdr_old;
+- atl1_free_ring_resources(adapter);
+- adapter->rfd_ring = rfd_new;
+- adapter->rrd_ring = rrd_new;
+- adapter->tpd_ring = tpd_new;
+- adapter->ring_header = rhdr_new;
+-
+- err = atl1_up(adapter);
+- if (err)
+- return err;
+- }
+- return 0;
+-
+-err_setup_ring:
+- adapter->rfd_ring = rfd_old;
+- adapter->rrd_ring = rrd_old;
+- adapter->tpd_ring = tpd_old;
+- adapter->ring_header = rhdr_old;
+- atl1_up(adapter);
+- return err;
+-}
+-
+-static void atl1_get_pauseparam(struct net_device *netdev,
+- struct ethtool_pauseparam *epause)
+-{
+- struct atl1_adapter *adapter = netdev_priv(netdev);
+- struct atl1_hw *hw = &adapter->hw;
+-
+- if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+- hw->media_type == MEDIA_TYPE_1000M_FULL) {
+- epause->autoneg = AUTONEG_ENABLE;
+- } else {
+- epause->autoneg = AUTONEG_DISABLE;
+- }
+- epause->rx_pause = 1;
+- epause->tx_pause = 1;
+-}
+-
+-static int atl1_set_pauseparam(struct net_device *netdev,
+- struct ethtool_pauseparam *epause)
+-{
+- struct atl1_adapter *adapter = netdev_priv(netdev);
+- struct atl1_hw *hw = &adapter->hw;
+-
+- if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+- hw->media_type == MEDIA_TYPE_1000M_FULL) {
+- epause->autoneg = AUTONEG_ENABLE;
+- } else {
+- epause->autoneg = AUTONEG_DISABLE;
+- }
+-
+- epause->rx_pause = 1;
+- epause->tx_pause = 1;
+-
+- return 0;
+-}
+-
+-static u32 atl1_get_rx_csum(struct net_device *netdev)
+-{
+- return 1;
+-}
+-
+-static void atl1_get_strings(struct net_device *netdev, u32 stringset,
+- u8 *data)
+-{
+- u8 *p = data;
+- int i;
+-
+- switch (stringset) {
+- case ETH_SS_STATS:
+- for (i = 0; i < ARRAY_SIZE(atl1_gstrings_stats); i++) {
+- memcpy(p, atl1_gstrings_stats[i].stat_string,
+- ETH_GSTRING_LEN);
+- p += ETH_GSTRING_LEN;
+- }
+- break;
+- }
+-}
+-
+-static int atl1_nway_reset(struct net_device *netdev)
+-{
+- struct atl1_adapter *adapter = netdev_priv(netdev);
+- struct atl1_hw *hw = &adapter->hw;
+-
+- if (netif_running(netdev)) {
+- u16 phy_data;
+- atl1_down(adapter);
+-
+- if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+- hw->media_type == MEDIA_TYPE_1000M_FULL) {
+- phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
+- } else {
+- switch (hw->media_type) {
+- case MEDIA_TYPE_100M_FULL:
+- phy_data = MII_CR_FULL_DUPLEX |
+- MII_CR_SPEED_100 | MII_CR_RESET;
+- break;
+- case MEDIA_TYPE_100M_HALF:
+- phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+- break;
+- case MEDIA_TYPE_10M_FULL:
+- phy_data = MII_CR_FULL_DUPLEX |
+- MII_CR_SPEED_10 | MII_CR_RESET;
+- break;
+- default: /* MEDIA_TYPE_10M_HALF */
+- phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+- }
+- }
+- atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+- atl1_up(adapter);
+- }
+- return 0;
+-}
+-
+-const struct ethtool_ops atl1_ethtool_ops = {
+- .get_settings = atl1_get_settings,
+- .set_settings = atl1_set_settings,
+- .get_drvinfo = atl1_get_drvinfo,
+- .get_wol = atl1_get_wol,
+- .set_wol = atl1_set_wol,
+- .get_ringparam = atl1_get_ringparam,
+- .set_ringparam = atl1_set_ringparam,
+- .get_pauseparam = atl1_get_pauseparam,
+- .set_pauseparam = atl1_set_pauseparam,
+- .get_rx_csum = atl1_get_rx_csum,
+- .set_tx_csum = ethtool_op_set_tx_hw_csum,
+- .get_link = ethtool_op_get_link,
+- .set_sg = ethtool_op_set_sg,
+- .get_strings = atl1_get_strings,
+- .nway_reset = atl1_nway_reset,
+- .get_ethtool_stats = atl1_get_ethtool_stats,
+- .get_sset_count = atl1_get_sset_count,
+- .set_tso = ethtool_op_set_tso,
+-};
+diff --git a/drivers/net/atl1/atl1_hw.c b/drivers/net/atl1/atl1_hw.c
+deleted file mode 100644
+index 9d3bd22..0000000
+--- a/drivers/net/atl1/atl1_hw.c
++++ /dev/null
+@@ -1,720 +0,0 @@
+-/*
+- * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+- * Copyright(c) 2006 Chris Snook <csnook at redhat.com>
+- * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
+- *
+- * 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/types.h>
+-#include <linux/pci.h>
+-#include <linux/delay.h>
+-#include <linux/if_vlan.h>
+-#include <linux/etherdevice.h>
+-#include <linux/crc32.h>
+-#include <asm/byteorder.h>
+-
+-#include "atl1.h"
+-
+-/*
+- * Reset the transmit and receive units; mask and clear all interrupts.
+- * hw - Struct containing variables accessed by shared code
+- * return : ATL1_SUCCESS or idle status (if error)
+- */
+-s32 atl1_reset_hw(struct atl1_hw *hw)
+-{
+- struct pci_dev *pdev = hw->back->pdev;
+- u32 icr;
+- int i;
+-
+- /*
+- * Clear Interrupt mask to stop board from generating
+- * interrupts & Clear any pending interrupt events
+- */
+- /*
+- * iowrite32(0, hw->hw_addr + REG_IMR);
+- * iowrite32(0xffffffff, hw->hw_addr + REG_ISR);
+- */
+-
+- /*
+- * 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.
+- */
+- iowrite32(MASTER_CTRL_SOFT_RST, hw->hw_addr + REG_MASTER_CTRL);
+- ioread32(hw->hw_addr + REG_MASTER_CTRL);
+-
+- iowrite16(1, hw->hw_addr + REG_GPHY_ENABLE);
+- ioread16(hw->hw_addr + REG_GPHY_ENABLE);
+-
+- msleep(1); /* delay about 1ms */
+-
+- /* Wait at least 10ms for All module to be Idle */
+- for (i = 0; i < 10; i++) {
+- icr = ioread32(hw->hw_addr + REG_IDLE_STATUS);
+- if (!icr)
+- break;
+- msleep(1); /* delay 1 ms */
+- cpu_relax(); /* FIXME: is this still the right way to do this? */
+- }
+-
+- if (icr) {
+- dev_dbg(&pdev->dev, "ICR = 0x%x\n", icr);
+- return icr;
+- }
+-
+- return ATL1_SUCCESS;
+-}
+-
+-/* function about EEPROM
+- *
+- * check_eeprom_exist
+- * return 0 if eeprom exist
+- */
+-static int atl1_check_eeprom_exist(struct atl1_hw *hw)
+-{
+- u32 value;
+- value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
+- if (value & SPI_FLASH_CTRL_EN_VPD) {
+- value &= ~SPI_FLASH_CTRL_EN_VPD;
+- iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
+- }
+-
+- value = ioread16(hw->hw_addr + REG_PCIE_CAP_LIST);
+- return ((value & 0xFF00) == 0x6C00) ? 0 : 1;
+-}
+-
+-static bool atl1_read_eeprom(struct atl1_hw *hw, u32 offset, u32 *p_value)
+-{
+- int i;
+- u32 control;
+-
+- if (offset & 3)
+- return false; /* address do not align */
+-
+- iowrite32(0, hw->hw_addr + REG_VPD_DATA);
+- control = (offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT;
+- iowrite32(control, hw->hw_addr + REG_VPD_CAP);
+- ioread32(hw->hw_addr + REG_VPD_CAP);
+-
+- for (i = 0; i < 10; i++) {
+- msleep(2);
+- control = ioread32(hw->hw_addr + REG_VPD_CAP);
+- if (control & VPD_CAP_VPD_FLAG)
+- break;
+- }
+- if (control & VPD_CAP_VPD_FLAG) {
+- *p_value = ioread32(hw->hw_addr + REG_VPD_DATA);
+- return true;
+- }
+- return false; /* timeout */
+-}
+-
+-/*
+- * Reads the value from a PHY register
+- * hw - Struct containing variables accessed by shared code
+- * reg_addr - address of the PHY register to read
+- */
+-s32 atl1_read_phy_reg(struct atl1_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;
+- iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
+- ioread32(hw->hw_addr + REG_MDIO_CTRL);
+-
+- for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+- udelay(2);
+- val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
+- if (!(val & (MDIO_START | MDIO_BUSY)))
+- break;
+- }
+- if (!(val & (MDIO_START | MDIO_BUSY))) {
+- *phy_data = (u16) val;
+- return ATL1_SUCCESS;
+- }
+- return ATL1_ERR_PHY;
+-}
+-
+-#define CUSTOM_SPI_CS_SETUP 2
+-#define CUSTOM_SPI_CLK_HI 2
+-#define CUSTOM_SPI_CLK_LO 2
+-#define CUSTOM_SPI_CS_HOLD 2
+-#define CUSTOM_SPI_CS_HI 3
+-
+-static bool atl1_spi_read(struct atl1_hw *hw, u32 addr, u32 *buf)
+-{
+- int i;
+- u32 value;
+-
+- iowrite32(0, hw->hw_addr + REG_SPI_DATA);
+- iowrite32(addr, hw->hw_addr + REG_SPI_ADDR);
+-
+- value = SPI_FLASH_CTRL_WAIT_READY |
+- (CUSTOM_SPI_CS_SETUP & SPI_FLASH_CTRL_CS_SETUP_MASK) <<
+- SPI_FLASH_CTRL_CS_SETUP_SHIFT | (CUSTOM_SPI_CLK_HI &
+- SPI_FLASH_CTRL_CLK_HI_MASK) <<
+- SPI_FLASH_CTRL_CLK_HI_SHIFT | (CUSTOM_SPI_CLK_LO &
+- SPI_FLASH_CTRL_CLK_LO_MASK) <<
+- SPI_FLASH_CTRL_CLK_LO_SHIFT | (CUSTOM_SPI_CS_HOLD &
+- SPI_FLASH_CTRL_CS_HOLD_MASK) <<
+- SPI_FLASH_CTRL_CS_HOLD_SHIFT | (CUSTOM_SPI_CS_HI &
+- SPI_FLASH_CTRL_CS_HI_MASK) <<
+- SPI_FLASH_CTRL_CS_HI_SHIFT | (1 & SPI_FLASH_CTRL_INS_MASK) <<
+- SPI_FLASH_CTRL_INS_SHIFT;
+-
+- iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
+-
+- value |= SPI_FLASH_CTRL_START;
+- iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
+- ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
+-
+- for (i = 0; i < 10; i++) {
+- msleep(1); /* 1ms */
+- value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
+- if (!(value & SPI_FLASH_CTRL_START))
+- break;
+- }
+-
+- if (value & SPI_FLASH_CTRL_START)
+- return false;
+-
+- *buf = ioread32(hw->hw_addr + REG_SPI_DATA);
+-
+- return true;
+-}
+-
+-/*
+- * get_permanent_address
+- * return 0 if get valid mac address,
+- */
+-static int atl1_get_permanent_address(struct atl1_hw *hw)
+-{
+- u32 addr[2];
+- u32 i, control;
+- u16 reg;
+- u8 eth_addr[ETH_ALEN];
+- bool key_valid;
+-
+- if (is_valid_ether_addr(hw->perm_mac_addr))
+- return 0;
+-
+- /* init */
+- addr[0] = addr[1] = 0;
+-
+- if (!atl1_check_eeprom_exist(hw)) { /* eeprom exist */
+- reg = 0;
+- key_valid = false;
+- /* Read out all EEPROM content */
+- i = 0;
+- while (1) {
+- if (atl1_read_eeprom(hw, i + 0x100, &control)) {
+- if (key_valid) {
+- if (reg == REG_MAC_STA_ADDR)
+- addr[0] = control;
+- else if (reg == (REG_MAC_STA_ADDR + 4))
+- addr[1] = control;
+- key_valid = false;
+- } else if ((control & 0xff) == 0x5A) {
+- key_valid = true;
+- reg = (u16) (control >> 16);
+- } else
+- break; /* assume data end while encount an invalid KEYWORD */
+- } else
+- break; /* read error */
+- i += 4;
+- }
+-
+- *(u32 *) ð_addr[2] = swab32(addr[0]);
+- *(u16 *) ð_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;
+- }
+-
+- /* see if SPI FLAGS exist ? */
+- addr[0] = addr[1] = 0;
+- reg = 0;
+- key_valid = false;
+- i = 0;
+- while (1) {
+- if (atl1_spi_read(hw, i + 0x1f000, &control)) {
+- if (key_valid) {
+- if (reg == REG_MAC_STA_ADDR)
+- addr[0] = control;
+- else if (reg == (REG_MAC_STA_ADDR + 4))
+- addr[1] = control;
+- key_valid = false;
+- } else if ((control & 0xff) == 0x5A) {
+- key_valid = true;
+- reg = (u16) (control >> 16);
+- } else
+- break; /* data end */
+- } else
+- break; /* read error */
+- i += 4;
+- }
+-
+- *(u32 *) ð_addr[2] = swab32(addr[0]);
+- *(u16 *) ð_addr[0] = swab16(*(u16 *) &addr[1]);
+- if (is_valid_ether_addr(eth_addr)) {
+- memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+- return 0;
+- }
+-
+- /*
+- * On some motherboards, the MAC address is written by the
+- * BIOS directly to the MAC register during POST, and is
+- * not stored in eeprom. If all else thus far has failed
+- * to fetch the permanent MAC address, try reading it directly.
+- */
+- addr[0] = ioread32(hw->hw_addr + REG_MAC_STA_ADDR);
+- addr[1] = ioread16(hw->hw_addr + (REG_MAC_STA_ADDR + 4));
+- *(u32 *) ð_addr[2] = swab32(addr[0]);
+- *(u16 *) ð_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;
+-}
+-
+-/*
+- * Reads the adapter's MAC address from the EEPROM
+- * hw - Struct containing variables accessed by shared code
+- */
+-s32 atl1_read_mac_addr(struct atl1_hw *hw)
+-{
+- u16 i;
+-
+- if (atl1_get_permanent_address(hw))
+- random_ether_addr(hw->perm_mac_addr);
+-
+- for (i = 0; i < ETH_ALEN; i++)
+- hw->mac_addr[i] = hw->perm_mac_addr[i];
+- return ATL1_SUCCESS;
+-}
+-
+-/*
+- * Hashes an address to determine its location in the multicast table
+- * hw - Struct containing variables accessed by shared code
+- * mc_addr - the multicast address to hash
+- *
+- * atl1_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 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr)
+-{
+- u32 crc32, 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 atl1_hash_set(struct atl1_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 7 bits 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 = ioread32((hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
+- mta |= (1 << hash_bit);
+- iowrite32(mta, (hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
+-}
+-
+-/*
+- * 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
+- */
+-s32 atl1_write_phy_reg(struct atl1_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;
+- iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
+- ioread32(hw->hw_addr + REG_MDIO_CTRL);
+-
+- for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+- udelay(2);
+- val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
+- if (!(val & (MDIO_START | MDIO_BUSY)))
+- break;
+- }
+-
+- if (!(val & (MDIO_START | MDIO_BUSY)))
+- return ATL1_SUCCESS;
+-
+- return ATL1_ERR_PHY;
+-}
+-
+-/*
+- * Make L001's PHY out of Power Saving State (bug)
+- * hw - Struct containing variables accessed by shared code
+- * when power on, L001's PHY always on Power saving State
+- * (Gigabit Link forbidden)
+- */
+-static s32 atl1_phy_leave_power_saving(struct atl1_hw *hw)
+-{
+- s32 ret;
+- ret = atl1_write_phy_reg(hw, 29, 0x0029);
+- if (ret)
+- return ret;
+- return atl1_write_phy_reg(hw, 30, 0);
+-}
+-
+-/*
+- *TODO: do something or get rid of this
+- */
+-s32 atl1_phy_enter_power_saving(struct atl1_hw *hw)
+-{
+-/* s32 ret_val;
+- * u16 phy_data;
+- */
+-
+-/*
+- ret_val = atl1_write_phy_reg(hw, ...);
+- ret_val = atl1_write_phy_reg(hw, ...);
+- ....
+-*/
+- return ATL1_SUCCESS;
+-}
+-
+-/*
+- * Resets the PHY and make all config validate
+- * hw - Struct containing variables accessed by shared code
+- *
+- * Sets bit 15 and 12 of the MII Control regiser (for F001 bug)
+- */
+-static s32 atl1_phy_reset(struct atl1_hw *hw)
+-{
+- struct pci_dev *pdev = hw->back->pdev;
+- s32 ret_val;
+- u16 phy_data;
+-
+- if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+- hw->media_type == MEDIA_TYPE_1000M_FULL)
+- phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
+- else {
+- switch (hw->media_type) {
+- case MEDIA_TYPE_100M_FULL:
+- phy_data =
+- MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
+- MII_CR_RESET;
+- break;
+- case MEDIA_TYPE_100M_HALF:
+- phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+- break;
+- case MEDIA_TYPE_10M_FULL:
+- phy_data =
+- MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
+- break;
+- default: /* MEDIA_TYPE_10M_HALF: */
+- phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+- break;
+- }
+- }
+-
+- ret_val = atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+- if (ret_val) {
+- u32 val;
+- int i;
+- /* pcie serdes link may be down! */
+- dev_dbg(&pdev->dev, "pcie phy link down\n");
+-
+- for (i = 0; i < 25; i++) {
+- msleep(1);
+- val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
+- if (!(val & (MDIO_START | MDIO_BUSY)))
+- break;
+- }
+-
+- if ((val & (MDIO_START | MDIO_BUSY)) != 0) {
+- dev_warn(&pdev->dev, "pcie link down at least 25ms\n");
+- return ret_val;
+- }
+- }
+- return ATL1_SUCCESS;
+-}
+-
+-/*
+- * Configures PHY autoneg and flow control advertisement settings
+- * hw - Struct containing variables accessed by shared code
+- */
+-s32 atl1_phy_setup_autoneg_adv(struct atl1_hw *hw)
+-{
+- s32 ret_val;
+- s16 mii_autoneg_adv_reg;
+- s16 mii_1000t_ctrl_reg;
+-
+- /* Read the MII Auto-Neg Advertisement Register (Address 4). */
+- mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;
+-
+- /* Read the MII 1000Base-T Control Register (Address 9). */
+- mii_1000t_ctrl_reg = MII_AT001_CR_1000T_DEFAULT_CAP_MASK;
+-
+- /*
+- * First we clear all the 10/100 mb speed bits in the Auto-Neg
+- * Advertisement Register (Address 4) and the 1000 mb speed bits in
+- * the 1000Base-T Control Register (Address 9).
+- */
+- mii_autoneg_adv_reg &= ~MII_AR_SPEED_MASK;
+- mii_1000t_ctrl_reg &= ~MII_AT001_CR_1000T_SPEED_MASK;
+-
+- /*
+- * Need to parse media_type and set up
+- * the appropriate PHY registers.
+- */
+- switch (hw->media_type) {
+- case MEDIA_TYPE_AUTO_SENSOR:
+- mii_autoneg_adv_reg |= (MII_AR_10T_HD_CAPS |
+- MII_AR_10T_FD_CAPS |
+- MII_AR_100TX_HD_CAPS |
+- MII_AR_100TX_FD_CAPS);
+- mii_1000t_ctrl_reg |= MII_AT001_CR_1000T_FD_CAPS;
+- break;
+-
+- case MEDIA_TYPE_1000M_FULL:
+- mii_1000t_ctrl_reg |= MII_AT001_CR_1000T_FD_CAPS;
+- break;
+-
+- case MEDIA_TYPE_100M_FULL:
+- mii_autoneg_adv_reg |= MII_AR_100TX_FD_CAPS;
+- break;
+-
+- case MEDIA_TYPE_100M_HALF:
+- mii_autoneg_adv_reg |= MII_AR_100TX_HD_CAPS;
+- break;
+-
+- case MEDIA_TYPE_10M_FULL:
+- mii_autoneg_adv_reg |= MII_AR_10T_FD_CAPS;
+- break;
+-
+- default:
+- mii_autoneg_adv_reg |= MII_AR_10T_HD_CAPS;
+- break;
+- }
+-
+- /* flow control fixed to enable all */
+- mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE);
+-
+- hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;
+- hw->mii_1000t_ctrl_reg = mii_1000t_ctrl_reg;
+-
+- ret_val = atl1_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);
+- if (ret_val)
+- return ret_val;
+-
+- ret_val = atl1_write_phy_reg(hw, MII_AT001_CR, mii_1000t_ctrl_reg);
+- if (ret_val)
+- return ret_val;
+-
+- return ATL1_SUCCESS;
+-}
+-
+-/*
+- * Configures link settings.
+- * hw - Struct containing variables accessed by shared code
+- * Assumes the hardware has previously been reset and the
+- * transmitter and receiver are not enabled.
+- */
+-static s32 atl1_setup_link(struct atl1_hw *hw)
+-{
+- struct pci_dev *pdev = hw->back->pdev;
+- s32 ret_val;
+-
+- /*
+- * Options:
+- * PHY will advertise value(s) parsed from
+- * autoneg_advertised and fc
+- * no matter what autoneg is , We will not wait link result.
+- */
+- ret_val = atl1_phy_setup_autoneg_adv(hw);
+- if (ret_val) {
+- dev_dbg(&pdev->dev, "error setting up autonegotiation\n");
+- return ret_val;
+- }
+- /* SW.Reset , En-Auto-Neg if needed */
+- ret_val = atl1_phy_reset(hw);
+- if (ret_val) {
+- dev_dbg(&pdev->dev, "error resetting phy\n");
+- return ret_val;
+- }
+- hw->phy_configured = true;
+- return ret_val;
+-}
+-
+-static struct atl1_spi_flash_dev flash_table[] = {
+-/* MFR_NAME WRSR READ PRGM WREN WRDI RDSR RDID SECTOR_ERASE CHIP_ERASE */
+- {"Atmel", 0x00, 0x03, 0x02, 0x06, 0x04, 0x05, 0x15, 0x52, 0x62},
+- {"SST", 0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0x90, 0x20, 0x60},
+- {"ST", 0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0xAB, 0xD8, 0xC7},
+-};
+-
+-static void atl1_init_flash_opcode(struct atl1_hw *hw)
+-{
+- if (hw->flash_vendor >= ARRAY_SIZE(flash_table))
+- hw->flash_vendor = 0; /* ATMEL */
+-
+- /* Init OP table */
+- iowrite8(flash_table[hw->flash_vendor].cmd_program,
+- hw->hw_addr + REG_SPI_FLASH_OP_PROGRAM);
+- iowrite8(flash_table[hw->flash_vendor].cmd_sector_erase,
+- hw->hw_addr + REG_SPI_FLASH_OP_SC_ERASE);
+- iowrite8(flash_table[hw->flash_vendor].cmd_chip_erase,
+- hw->hw_addr + REG_SPI_FLASH_OP_CHIP_ERASE);
+- iowrite8(flash_table[hw->flash_vendor].cmd_rdid,
+- hw->hw_addr + REG_SPI_FLASH_OP_RDID);
+- iowrite8(flash_table[hw->flash_vendor].cmd_wren,
+- hw->hw_addr + REG_SPI_FLASH_OP_WREN);
+- iowrite8(flash_table[hw->flash_vendor].cmd_rdsr,
+- hw->hw_addr + REG_SPI_FLASH_OP_RDSR);
+- iowrite8(flash_table[hw->flash_vendor].cmd_wrsr,
+- hw->hw_addr + REG_SPI_FLASH_OP_WRSR);
+- iowrite8(flash_table[hw->flash_vendor].cmd_read,
+- hw->hw_addr + REG_SPI_FLASH_OP_READ);
+-}
+-
+-/*
+- * Performs basic configuration of the adapter.
+- * hw - Struct containing variables accessed by shared code
+- * Assumes that the controller has previously been reset and is in a
+- * post-reset uninitialized state. Initializes multicast table,
+- * and Calls routines to setup link
+- * Leaves the transmit and receive units disabled and uninitialized.
+- */
+-s32 atl1_init_hw(struct atl1_hw *hw)
+-{
+- u32 ret_val = 0;
+-
+- /* Zero out the Multicast HASH table */
+- iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
+- /* clear the old settings from the multicast hash table */
+- iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
+-
+- atl1_init_flash_opcode(hw);
+-
+- if (!hw->phy_configured) {
+- /* enable GPHY LinkChange Interrrupt */
+- ret_val = atl1_write_phy_reg(hw, 18, 0xC00);
+- if (ret_val)
+- return ret_val;
+- /* make PHY out of power-saving state */
+- ret_val = atl1_phy_leave_power_saving(hw);
+- if (ret_val)
+- return ret_val;
+- /* Call a subroutine to configure the link */
+- ret_val = atl1_setup_link(hw);
+- }
+- return ret_val;
+-}
+-
+-/*
+- * 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
+- */
+-s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex)
+-{
+- struct pci_dev *pdev = hw->back->pdev;
+- s32 ret_val;
+- u16 phy_data;
+-
+- /* ; --- Read PHY Specific Status Register (17) */
+- ret_val = atl1_read_phy_reg(hw, MII_AT001_PSSR, &phy_data);
+- if (ret_val)
+- return ret_val;
+-
+- if (!(phy_data & MII_AT001_PSSR_SPD_DPLX_RESOLVED))
+- return ATL1_ERR_PHY_RES;
+-
+- switch (phy_data & MII_AT001_PSSR_SPEED) {
+- case MII_AT001_PSSR_1000MBS:
+- *speed = SPEED_1000;
+- break;
+- case MII_AT001_PSSR_100MBS:
+- *speed = SPEED_100;
+- break;
+- case MII_AT001_PSSR_10MBS:
+- *speed = SPEED_10;
+- break;
+- default:
+- dev_dbg(&pdev->dev, "error getting speed\n");
+- return ATL1_ERR_PHY_SPEED;
+- break;
+- }
+- if (phy_data & MII_AT001_PSSR_DPLX)
+- *duplex = FULL_DUPLEX;
+- else
+- *duplex = HALF_DUPLEX;
+-
+- return ATL1_SUCCESS;
+-}
+-
+-void atl1_set_mac_addr(struct atl1_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]));
+- iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
+- /* high dword */
+- value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
+- iowrite32(value, (hw->hw_addr + REG_MAC_STA_ADDR) + (1 << 2));
+-}
+diff --git a/drivers/net/atl1/atl1_hw.h b/drivers/net/atl1/atl1_hw.h
+deleted file mode 100644
+index 939aa0f..0000000
+--- a/drivers/net/atl1/atl1_hw.h
++++ /dev/null
+@@ -1,946 +0,0 @@
+-/*
+- * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+- * Copyright(c) 2006 Chris Snook <csnook at redhat.com>
+- * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
+- *
+- * 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.
+- *
+- * There are a lot of defines in here that are unused and/or have cryptic
+- * names. Please leave them alone, as they're the closest thing we have
+- * to a spec from Attansic at present. *ahem* -- CHS
+- */
+-
+-#ifndef _ATL1_HW_H_
+-#define _ATL1_HW_H_
+-
+-#include <linux/types.h>
+-#include <linux/mii.h>
+-
+-struct atl1_adapter;
+-struct atl1_hw;
+-
+-/* function prototypes needed by multiple files */
+-s32 atl1_phy_setup_autoneg_adv(struct atl1_hw *hw);
+-s32 atl1_write_phy_reg(struct atl1_hw *hw, u32 reg_addr, u16 phy_data);
+-s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex);
+-s32 atl1_read_mac_addr(struct atl1_hw *hw);
+-s32 atl1_init_hw(struct atl1_hw *hw);
+-s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex);
+-s32 atl1_set_speed_and_duplex(struct atl1_hw *hw, u16 speed, u16 duplex);
+-u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr);
+-void atl1_hash_set(struct atl1_hw *hw, u32 hash_value);
+-s32 atl1_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data);
+-void atl1_set_mac_addr(struct atl1_hw *hw);
+-s32 atl1_phy_enter_power_saving(struct atl1_hw *hw);
+-s32 atl1_reset_hw(struct atl1_hw *hw);
+-void atl1_check_options(struct atl1_adapter *adapter);
+-
+-/* register definitions */
+-#define REG_PCIE_CAP_LIST 0x58
+-
+-#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_SPI_FLASH_CTRL 0x200
+-#define SPI_FLASH_CTRL_STS_NON_RDY 0x1
+-#define SPI_FLASH_CTRL_STS_WEN 0x2
+-#define SPI_FLASH_CTRL_STS_WPEN 0x80
+-#define SPI_FLASH_CTRL_DEV_STS_MASK 0xFF
+-#define SPI_FLASH_CTRL_DEV_STS_SHIFT 0
+-#define SPI_FLASH_CTRL_INS_MASK 0x7
+-#define SPI_FLASH_CTRL_INS_SHIFT 8
+-#define SPI_FLASH_CTRL_START 0x800
+-#define SPI_FLASH_CTRL_EN_VPD 0x2000
+-#define SPI_FLASH_CTRL_LDSTART 0x8000
+-#define SPI_FLASH_CTRL_CS_HI_MASK 0x3
+-#define SPI_FLASH_CTRL_CS_HI_SHIFT 16
+-#define SPI_FLASH_CTRL_CS_HOLD_MASK 0x3
+-#define SPI_FLASH_CTRL_CS_HOLD_SHIFT 18
+-#define SPI_FLASH_CTRL_CLK_LO_MASK 0x3
+-#define SPI_FLASH_CTRL_CLK_LO_SHIFT 20
+-#define SPI_FLASH_CTRL_CLK_HI_MASK 0x3
+-#define SPI_FLASH_CTRL_CLK_HI_SHIFT 22
+-#define SPI_FLASH_CTRL_CS_SETUP_MASK 0x3
+-#define SPI_FLASH_CTRL_CS_SETUP_SHIFT 24
+-#define SPI_FLASH_CTRL_EROM_PGSZ_MASK 0x3
+-#define SPI_FLASH_CTRL_EROM_PGSZ_SHIFT 26
+-#define SPI_FLASH_CTRL_WAIT_READY 0x10000000
+-
+-#define REG_SPI_ADDR 0x204
+-
+-#define REG_SPI_DATA 0x208
+-
+-#define REG_SPI_FLASH_CONFIG 0x20C
+-#define SPI_FLASH_CONFIG_LD_ADDR_MASK 0xFFFFFF
+-#define SPI_FLASH_CONFIG_LD_ADDR_SHIFT 0
+-#define SPI_FLASH_CONFIG_VPD_ADDR_MASK 0x3
+-#define SPI_FLASH_CONFIG_VPD_ADDR_SHIFT 24
+-#define SPI_FLASH_CONFIG_LD_EXIST 0x4000000
+-
+-#define REG_SPI_FLASH_OP_PROGRAM 0x210
+-#define REG_SPI_FLASH_OP_SC_ERASE 0x211
+-#define REG_SPI_FLASH_OP_CHIP_ERASE 0x212
+-#define REG_SPI_FLASH_OP_RDID 0x213
+-#define REG_SPI_FLASH_OP_WREN 0x214
+-#define REG_SPI_FLASH_OP_RDSR 0x215
+-#define REG_SPI_FLASH_OP_WRSR 0x216
+-#define REG_SPI_FLASH_OP_READ 0x217
+-
+-#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_CTRL_EXT_PIPE 0x2
+-#define PCIE_DEV_MISC_CTRL_RETRY_BUFDIS 0x1
+-#define PCIE_DEV_MISC_CTRL_SPIROM_EXIST 0x4
+-#define PCIE_DEV_MISC_CTRL_SERDES_ENDIAN 0x8
+-#define PCIE_DEV_MISC_CTRL_SERDES_SEL_DIN 0x10
+-
+-/* Selene Master Control Register */
+-#define REG_MASTER_CTRL 0x1400
+-#define MASTER_CTRL_SOFT_RST 0x1
+-#define MASTER_CTRL_MTIMER_EN 0x2
+-#define MASTER_CTRL_ITIMER_EN 0x4
+-#define MASTER_CTRL_MANUAL_INT 0x8
+-#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 0xff
+-
+-/* Timer Initial Value Register */
+-#define REG_MANUAL_TIMER_INIT 0x1404
+-
+-/* IRQ ModeratorTimer Initial Value Register */
+-#define REG_IRQ_MODU_TIMER_INIT 0x1408
+-
+-#define REG_GPHY_ENABLE 0x140C
+-
+-/* IRQ Anti-Lost Timer Initial Value Register */
+-#define REG_CMBDISDMA_TIMER 0x140E
+-
+-/* Block IDLE Status Register */
+-#define REG_IDLE_STATUS 0x1410
+-#define IDLE_STATUS_RXMAC 1
+-#define IDLE_STATUS_TXMAC 2
+-#define IDLE_STATUS_RXQ 4
+-#define IDLE_STATUS_TXQ 8
+-#define IDLE_STATUS_DMAR 0x10
+-#define IDLE_STATUS_DMAW 0x20
+-#define IDLE_STATUS_SMB 0x40
+-#define IDLE_STATUS_CMB 0x80
+-
+-/* MDIO Control Register */
+-#define REG_MDIO_CTRL 0x1414
+-#define MDIO_DATA_MASK 0xffff
+-#define MDIO_DATA_SHIFT 0
+-#define MDIO_REG_ADDR_MASK 0x1f
+-#define MDIO_REG_ADDR_SHIFT 16
+-#define MDIO_RW 0x200000
+-#define MDIO_SUP_PREAMBLE 0x400000
+-#define MDIO_START 0x800000
+-#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_WAIT_TIMES 30
+-
+-/* MII PHY Status Register */
+-#define REG_PHY_STATUS 0x1418
+-
+-/* BIST Control and Status Register0 (for the Packet Memory) */
+-#define REG_BIST0_CTRL 0x141c
+-#define BIST0_NOW 0x1
+-#define BIST0_SRAM_FAIL 0x2
+-#define BIST0_FUSE_FLAG 0x4
+-#define REG_BIST1_CTRL 0x1420
+-#define BIST1_NOW 0x1
+-#define BIST1_SRAM_FAIL 0x2
+-#define BIST1_FUSE_FLAG 0x4
+-
+-/* MAC Control Register */
+-#define REG_MAC_CTRL 0x1480
+-#define MAC_CTRL_TX_EN 1
+-#define MAC_CTRL_RX_EN 2
+-#define MAC_CTRL_TX_FLOW 4
+-#define MAC_CTRL_RX_FLOW 8
+-#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 0x300000
+-#define MAC_CTRL_SPEED_1000 2
+-#define MAC_CTRL_SPEED_10_100 1
+-#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
+-
+-/* MAC IPG/IFG Control Register */
+-#define REG_MAC_IPG_IFG 0x1484
+-#define MAC_IPG_IFG_IPGT_SHIFT 0
+-#define MAC_IPG_IFG_IPGT_MASK 0x7f
+-#define MAC_IPG_IFG_MIFG_SHIFT 8
+-#define MAC_IPG_IFG_MIFG_MASK 0xff
+-#define MAC_IPG_IFG_IPGR1_SHIFT 16
+-#define MAC_IPG_IFG_IPGR1_MASK 0x7f
+-#define MAC_IPG_IFG_IPGR2_SHIFT 24
+-#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
+-#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
+-#define MAC_HALF_DUPLX_CTRL_ABEBE 0x80000
+-#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT 20
+-#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK 0xf
+-#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT 24
+-#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK 0xf
+-
+-/* 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 REG_SRAM_RFD_ADDR 0x1500
+-#define REG_SRAM_RFD_LEN (REG_SRAM_RFD_ADDR+ 4)
+-#define REG_SRAM_RRD_ADDR (REG_SRAM_RFD_ADDR+ 8)
+-#define REG_SRAM_RRD_LEN (REG_SRAM_RFD_ADDR+12)
+-#define REG_SRAM_TPD_ADDR (REG_SRAM_RFD_ADDR+16)
+-#define REG_SRAM_TPD_LEN (REG_SRAM_RFD_ADDR+20)
+-#define REG_SRAM_TRD_ADDR (REG_SRAM_RFD_ADDR+24)
+-#define REG_SRAM_TRD_LEN (REG_SRAM_RFD_ADDR+28)
+-#define REG_SRAM_RXF_ADDR (REG_SRAM_RFD_ADDR+32)
+-#define REG_SRAM_RXF_LEN (REG_SRAM_RFD_ADDR+36)
+-#define REG_SRAM_TXF_ADDR (REG_SRAM_RFD_ADDR+40)
+-#define REG_SRAM_TXF_LEN (REG_SRAM_RFD_ADDR+44)
+-#define REG_SRAM_TCPH_PATH_ADDR (REG_SRAM_RFD_ADDR+48)
+-#define SRAM_TCPH_ADDR_MASK 0x0fff
+-#define SRAM_TCPH_ADDR_SHIFT 0
+-#define SRAM_PATH_ADDR_MASK 0x0fff
+-#define SRAM_PATH_ADDR_SHIFT 16
+-
+-/* Load Ptr Register */
+-#define REG_LOAD_PTR (REG_SRAM_RFD_ADDR+52)
+-
+-/* Descriptor Control register */
+-#define REG_DESC_BASE_ADDR_HI 0x1540
+-#define REG_DESC_RFD_ADDR_LO (REG_DESC_BASE_ADDR_HI+4)
+-#define REG_DESC_RRD_ADDR_LO (REG_DESC_BASE_ADDR_HI+8)
+-#define REG_DESC_TPD_ADDR_LO (REG_DESC_BASE_ADDR_HI+12)
+-#define REG_DESC_CMB_ADDR_LO (REG_DESC_BASE_ADDR_HI+16)
+-#define REG_DESC_SMB_ADDR_LO (REG_DESC_BASE_ADDR_HI+20)
+-#define REG_DESC_RFD_RRD_RING_SIZE (REG_DESC_BASE_ADDR_HI+24)
+-#define DESC_RFD_RING_SIZE_MASK 0x7ff
+-#define DESC_RFD_RING_SIZE_SHIFT 0
+-#define DESC_RRD_RING_SIZE_MASK 0x7ff
+-#define DESC_RRD_RING_SIZE_SHIFT 16
+-#define REG_DESC_TPD_RING_SIZE (REG_DESC_BASE_ADDR_HI+28)
+-#define DESC_TPD_RING_SIZE_MASK 0x3ff
+-#define DESC_TPD_RING_SIZE_SHIFT 0
+-
+-/* TXQ Control Register */
+-#define REG_TXQ_CTRL 0x1580
+-#define TXQ_CTRL_TPD_BURST_NUM_SHIFT 0
+-#define TXQ_CTRL_TPD_BURST_NUM_MASK 0x1f
+-#define TXQ_CTRL_EN 0x20
+-#define TXQ_CTRL_ENH_MODE 0x40
+-#define TXQ_CTRL_TPD_FETCH_TH_SHIFT 8
+-#define TXQ_CTRL_TPD_FETCH_TH_MASK 0x3f
+-#define TXQ_CTRL_TXF_BURST_NUM_SHIFT 16
+-#define TXQ_CTRL_TXF_BURST_NUM_MASK 0xffff
+-
+-/* Jumbo packet Threshold for task offload */
+-#define REG_TX_JUMBO_TASK_TH_TPD_IPG 0x1584
+-#define TX_JUMBO_TASK_TH_MASK 0x7ff
+-#define TX_JUMBO_TASK_TH_SHIFT 0
+-#define TX_TPD_MIN_IPG_MASK 0x1f
+-#define TX_TPD_MIN_IPG_SHIFT 16
+-
+-/* RXQ Control Register */
+-#define REG_RXQ_CTRL 0x15a0
+-#define RXQ_CTRL_RFD_BURST_NUM_SHIFT 0
+-#define RXQ_CTRL_RFD_BURST_NUM_MASK 0xff
+-#define RXQ_CTRL_RRD_BURST_THRESH_SHIFT 8
+-#define RXQ_CTRL_RRD_BURST_THRESH_MASK 0xff
+-#define RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT 16
+-#define RXQ_CTRL_RFD_PREF_MIN_IPG_MASK 0x1f
+-#define RXQ_CTRL_CUT_THRU_EN 0x40000000
+-#define RXQ_CTRL_EN 0x80000000
+-
+-/* Rx jumbo packet threshold and rrd retirement timer */
+-#define REG_RXQ_JMBOSZ_RRDTIM (REG_RXQ_CTRL+ 4)
+-#define RXQ_JMBOSZ_TH_MASK 0x7ff
+-#define RXQ_JMBOSZ_TH_SHIFT 0
+-#define RXQ_JMBO_LKAH_MASK 0xf
+-#define RXQ_JMBO_LKAH_SHIFT 11
+-#define RXQ_RRD_TIMER_MASK 0xffff
+-#define RXQ_RRD_TIMER_SHIFT 16
+-
+-/* RFD flow control register */
+-#define REG_RXQ_RXF_PAUSE_THRESH (REG_RXQ_CTRL+ 8)
+-#define RXQ_RXF_PAUSE_TH_HI_SHIFT 16
+-#define RXQ_RXF_PAUSE_TH_HI_MASK 0xfff
+-#define RXQ_RXF_PAUSE_TH_LO_SHIFT 0
+-#define RXQ_RXF_PAUSE_TH_LO_MASK 0xfff
+-
+-/* RRD flow control register */
+-#define REG_RXQ_RRD_PAUSE_THRESH (REG_RXQ_CTRL+12)
+-#define RXQ_RRD_PAUSE_TH_HI_SHIFT 0
+-#define RXQ_RRD_PAUSE_TH_HI_MASK 0xfff
+-#define RXQ_RRD_PAUSE_TH_LO_SHIFT 16
+-#define RXQ_RRD_PAUSE_TH_LO_MASK 0xfff
+-
+-/* 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_SHIFT 4
+-#define DMA_CTRL_DMAR_BURST_LEN_MASK 7
+-#define DMA_CTRL_DMAW_BURST_LEN_SHIFT 7
+-#define DMA_CTRL_DMAW_BURST_LEN_MASK 7
+-#define DMA_CTRL_DMAR_EN 0x400
+-#define DMA_CTRL_DMAW_EN 0x800
+-
+-/* CMB/SMB Control Register */
+-#define REG_CSMB_CTRL 0x15d0
+-#define CSMB_CTRL_CMB_NOW 1
+-#define CSMB_CTRL_SMB_NOW 2
+-#define CSMB_CTRL_CMB_EN 4
+-#define CSMB_CTRL_SMB_EN 8
+-
+-/* CMB DMA Write Threshold Register */
+-#define REG_CMB_WRITE_TH (REG_CSMB_CTRL+ 4)
+-#define CMB_RRD_TH_SHIFT 0
+-#define CMB_RRD_TH_MASK 0x7ff
+-#define CMB_TPD_TH_SHIFT 16
+-#define CMB_TPD_TH_MASK 0x7ff
+-
+-/* RX/TX count-down timer to trigger CMB-write. 2us resolution. */
+-#define REG_CMB_WRITE_TIMER (REG_CSMB_CTRL+ 8)
+-#define CMB_RX_TM_SHIFT 0
+-#define CMB_RX_TM_MASK 0xffff
+-#define CMB_TX_TM_SHIFT 16
+-#define CMB_TX_TM_MASK 0xffff
+-
+-/* Number of packet received since last CMB write */
+-#define REG_CMB_RX_PKT_CNT (REG_CSMB_CTRL+12)
+-
+-/* Number of packet transmitted since last CMB write */
+-#define REG_CMB_TX_PKT_CNT (REG_CSMB_CTRL+16)
+-
+-/* SMB auto DMA timer register */
+-#define REG_SMB_TIMER (REG_CSMB_CTRL+20)
+-
+-/* Mailbox Register */
+-#define REG_MAILBOX 0x15f0
+-#define MB_RFD_PROD_INDX_SHIFT 0
+-#define MB_RFD_PROD_INDX_MASK 0x7ff
+-#define MB_RRD_CONS_INDX_SHIFT 11
+-#define MB_RRD_CONS_INDX_MASK 0x7ff
+-#define MB_TPD_PROD_INDX_SHIFT 22
+-#define MB_TPD_PROD_INDX_MASK 0x3ff
+-
+-/* Interrupt Status Register */
+-#define REG_ISR 0x1600
+-#define ISR_SMB 1
+-#define ISR_TIMER 2
+-#define ISR_MANUAL 4
+-#define ISR_RXF_OV 8
+-#define ISR_RFD_UNRUN 0x10
+-#define ISR_RRD_OV 0x20
+-#define ISR_TXF_UNRUN 0x40
+-#define ISR_LINK 0x80
+-#define ISR_HOST_RFD_UNRUN 0x100
+-#define ISR_HOST_RRD_OV 0x200
+-#define ISR_DMAR_TO_RST 0x400
+-#define ISR_DMAW_TO_RST 0x800
+-#define ISR_GPHY 0x1000
+-#define ISR_RX_PKT 0x10000
+-#define ISR_TX_PKT 0x20000
+-#define ISR_TX_DMA 0x40000
+-#define ISR_RX_DMA 0x80000
+-#define ISR_CMB_RX 0x100000
+-#define ISR_CMB_TX 0x200000
+-#define ISR_MAC_RX 0x400000
+-#define ISR_MAC_TX 0x800000
+-#define ISR_UR_DETECTED 0x1000000
+-#define ISR_FERR_DETECTED 0x2000000
+-#define ISR_NFERR_DETECTED 0x4000000
+-#define ISR_CERR_DETECTED 0x8000000
+-#define ISR_PHY_LINKDOWN 0x10000000
+-#define ISR_DIS_SMB 0x20000000
+-#define ISR_DIS_DMA 0x40000000
+-#define ISR_DIS_INT 0x80000000
+-
+-/* Interrupt Mask Register */
+-#define REG_IMR 0x1604
+-
+-/* Normal Interrupt mask */
+-#define IMR_NORMAL_MASK (\
+- ISR_SMB |\
+- ISR_GPHY |\
+- ISR_PHY_LINKDOWN|\
+- ISR_DMAR_TO_RST |\
+- ISR_DMAW_TO_RST |\
+- ISR_CMB_TX |\
+- ISR_CMB_RX )
+-
+-/* Debug Interrupt Mask (enable all interrupt) */
+-#define IMR_DEBUG_MASK (\
+- ISR_SMB |\
+- ISR_TIMER |\
+- ISR_MANUAL |\
+- ISR_RXF_OV |\
+- ISR_RFD_UNRUN |\
+- ISR_RRD_OV |\
+- ISR_TXF_UNRUN |\
+- ISR_LINK |\
+- ISR_CMB_TX |\
+- ISR_CMB_RX |\
+- ISR_RX_PKT |\
+- ISR_TX_PKT |\
+- ISR_MAC_RX |\
+- ISR_MAC_TX )
+-
+-/* Interrupt Status Register */
+-#define REG_RFD_RRD_IDX 0x1800
+-#define REG_TPD_IDX 0x1804
+-
+-/* MII definition */
+-/* PHY Common Register */
+-#define MII_AT001_CR 0x09
+-#define MII_AT001_SR 0x0A
+-#define MII_AT001_ESR 0x0F
+-#define MII_AT001_PSCR 0x10
+-#define MII_AT001_PSSR 0x11
+-
+-/* PHY Control Register */
+-#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */
+-#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */
+-#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
+-#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
+-#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */
+-#define MII_CR_POWER_DOWN 0x0800 /* Power down */
+-#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
+-#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */
+-#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */
+-#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */
+-#define MII_CR_SPEED_MASK 0x2040
+-#define MII_CR_SPEED_1000 0x0040
+-#define MII_CR_SPEED_100 0x2000
+-#define MII_CR_SPEED_10 0x0000
+-
+-/* PHY Status Register */
+-#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */
+-#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */
+-#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */
+-#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */
+-#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */
+-#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */
+-#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */
+-#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */
+-#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */
+-#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */
+-#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */
+-#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */
+-#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */
+-#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */
+-#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */
+-
+-/* Link partner ability register. */
+-#define MII_LPA_SLCT 0x001f /* Same as advertise selector */
+-#define MII_LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */
+-#define MII_LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */
+-#define MII_LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */
+-#define MII_LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */
+-#define MII_LPA_100BASE4 0x0200 /* 100BASE-T4 */
+-#define MII_LPA_PAUSE 0x0400 /* PAUSE */
+-#define MII_LPA_ASYPAUSE 0x0800 /* Asymmetrical PAUSE */
+-#define MII_LPA_RFAULT 0x2000 /* Link partner faulted */
+-#define MII_LPA_LPACK 0x4000 /* Link partner acked us */
+-#define MII_LPA_NPAGE 0x8000 /* Next page bit */
+-
+-/* Autoneg Advertisement Register */
+-#define MII_AR_SELECTOR_FIELD 0x0001 /* indicates IEEE 802.3 CSMA/CD */
+-#define MII_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */
+-#define MII_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */
+-#define MII_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */
+-#define MII_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */
+-#define MII_AR_100T4_CAPS 0x0200 /* 100T4 Capable */
+-#define MII_AR_PAUSE 0x0400 /* Pause operation desired */
+-#define MII_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */
+-#define MII_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */
+-#define MII_AR_NEXT_PAGE 0x8000 /* Next Page ability supported */
+-#define MII_AR_SPEED_MASK 0x01E0
+-#define MII_AR_DEFAULT_CAP_MASK 0x0DE0
+-
+-/* 1000BASE-T Control Register */
+-#define MII_AT001_CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */
+-#define MII_AT001_CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */
+-#define MII_AT001_CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device port, 0=DTE device */
+-#define MII_AT001_CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master, 0=Configure PHY as Slave */
+-#define MII_AT001_CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value, 0=Automatic Master/Slave config */
+-#define MII_AT001_CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */
+-#define MII_AT001_CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */
+-#define MII_AT001_CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */
+-#define MII_AT001_CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */
+-#define MII_AT001_CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */
+-#define MII_AT001_CR_1000T_SPEED_MASK 0x0300
+-#define MII_AT001_CR_1000T_DEFAULT_CAP_MASK 0x0300
+-
+-/* 1000BASE-T Status Register */
+-#define MII_AT001_SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */
+-#define MII_AT001_SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */
+-#define MII_AT001_SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
+-#define MII_AT001_SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */
+-#define MII_AT001_SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local TX is Master, 0=Slave */
+-#define MII_AT001_SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */
+-#define MII_AT001_SR_1000T_REMOTE_RX_STATUS_SHIFT 12
+-#define MII_AT001_SR_1000T_LOCAL_RX_STATUS_SHIFT 13
+-
+-/* Extended Status Register */
+-#define MII_AT001_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */
+-#define MII_AT001_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */
+-#define MII_AT001_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */
+-#define MII_AT001_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */
+-
+-/* AT001 PHY Specific Control Register */
+-#define MII_AT001_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Function disabled */
+-#define MII_AT001_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */
+-#define MII_AT001_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled */
+-#define MII_AT001_PSCR_MAC_POWERDOWN 0x0008
+-#define MII_AT001_PSCR_CLK125_DISABLE 0x0010 /* 1=CLK125 low, 0=CLK125 toggling */
+-#define MII_AT001_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5, Manual MDI configuration */
+-#define MII_AT001_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */
+-#define MII_AT001_PSCR_AUTO_X_1000T 0x0040 /* 1000BASE-T: Auto crossover, 100BASE-TX/10BASE-T: MDI Mode */
+-#define MII_AT001_PSCR_AUTO_X_MODE 0x0060 /* Auto crossover enabled all speeds. */
+-#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE 0x0080 /* 1=Enable Extended 10BASE-T distance (Lower 10BASE-T RX Threshold), 0=Normal 10BASE-T RX Threshold */
+-#define MII_AT001_PSCR_MII_5BIT_ENABLE 0x0100 /* 1=5-Bit interface in 100BASE-TX, 0=MII interface in 100BASE-TX */
+-#define MII_AT001_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler disable */
+-#define MII_AT001_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */
+-#define MII_AT001_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */
+-#define MII_AT001_PSCR_POLARITY_REVERSAL_SHIFT 1
+-#define MII_AT001_PSCR_AUTO_X_MODE_SHIFT 5
+-#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7
+-
+-/* AT001 PHY Specific Status Register */
+-#define MII_AT001_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */
+-#define MII_AT001_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */
+-#define MII_AT001_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */
+-#define MII_AT001_PSSR_10MBS 0x0000 /* 00=10Mbs */
+-#define MII_AT001_PSSR_100MBS 0x4000 /* 01=100Mbs */
+-#define MII_AT001_PSSR_1000MBS 0x8000 /* 10=1000Mbs */
+-
+-/* PCI Command Register Bit Definitions */
+-#define PCI_REG_COMMAND 0x04 /* PCI Command Register */
+-#define CMD_IO_SPACE 0x0001
+-#define CMD_MEMORY_SPACE 0x0002
+-#define CMD_BUS_MASTER 0x0004
+-
+-/* Wake Up Filter Control */
+-#define ATL1_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
+-#define ATL1_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */
+-#define ATL1_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */
+-#define ATL1_WUFC_MC 0x00000008 /* Multicast Wakeup Enable */
+-#define ATL1_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */
+-
+-/* Error Codes */
+-#define ATL1_SUCCESS 0
+-#define ATL1_ERR_EEPROM 1
+-#define ATL1_ERR_PHY 2
+-#define ATL1_ERR_CONFIG 3
+-#define ATL1_ERR_PARAM 4
+-#define ATL1_ERR_MAC_TYPE 5
+-#define ATL1_ERR_PHY_TYPE 6
+-#define ATL1_ERR_PHY_SPEED 7
+-#define ATL1_ERR_PHY_RES 8
+-
+-#define SPEED_0 0xffff
+-#define SPEED_10 10
+-#define SPEED_100 100
+-#define SPEED_1000 1000
+-#define HALF_DUPLEX 1
+-#define FULL_DUPLEX 2
+-
+-#define MEDIA_TYPE_AUTO_SENSOR 0
+-#define MEDIA_TYPE_1000M_FULL 1
+-#define MEDIA_TYPE_100M_FULL 2
+-#define MEDIA_TYPE_100M_HALF 3
+-#define MEDIA_TYPE_10M_FULL 4
+-#define MEDIA_TYPE_10M_HALF 5
+-
+-#define ADVERTISE_10_HALF 0x0001
+-#define ADVERTISE_10_FULL 0x0002
+-#define ADVERTISE_100_HALF 0x0004
+-#define ADVERTISE_100_FULL 0x0008
+-#define ADVERTISE_1000_HALF 0x0010
+-#define ADVERTISE_1000_FULL 0x0020
+-#define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x002F /* Everything but 1000-Half */
+-#define AUTONEG_ADVERTISE_10_100_ALL 0x000F /* All 10/100 speeds */
+-#define AUTONEG_ADVERTISE_10_ALL 0x0003 /* 10Mbps Full & Half speeds */
+-
+-#define MAX_JUMBO_FRAME_SIZE 0x2800
+-
+-#define PHY_AUTO_NEG_TIME 45 /* 4.5 Seconds */
+-#define PHY_FORCE_TIME 20 /* 2.0 Seconds */
+-
+-/* For checksumming , the sum of all words in the EEPROM should equal 0xBABA */
+-#define EEPROM_SUM 0xBABA
+-
+-#define ATL1_EEDUMP_LEN 48
+-
+-/* Statistics counters collected by the MAC */
+-struct stats_msg_block {
+- /* rx */
+- u32 rx_ok; /* The number of good packet received. */
+- u32 rx_bcast; /* The number of good broadcast packet received. */
+- u32 rx_mcast; /* The number of good multicast packet received. */
+- u32 rx_pause; /* The number of Pause packet received. */
+- u32 rx_ctrl; /* The number of Control packet received other than Pause frame. */
+- u32 rx_fcs_err; /* The number of packets with bad FCS. */
+- u32 rx_len_err; /* The number of packets with mismatch of length field and actual size. */
+- u32 rx_byte_cnt; /* The number of bytes of good packet received. FCS is NOT included. */
+- u32 rx_runt; /* The number of packets received that are less than 64 byte long and with good FCS. */
+- u32 rx_frag; /* The number of packets received that are less than 64 byte long and with bad FCS. */
+- u32 rx_sz_64; /* The number of good and bad packets received that are 64 byte long. */
+- u32 rx_sz_65_127; /* The number of good and bad packets received that are between 65 and 127-byte long. */
+- u32 rx_sz_128_255; /* The number of good and bad packets received that are between 128 and 255-byte long. */
+- u32 rx_sz_256_511; /* The number of good and bad packets received that are between 256 and 511-byte long. */
+- u32 rx_sz_512_1023; /* The number of good and bad packets received that are between 512 and 1023-byte long. */
+- u32 rx_sz_1024_1518; /* The number of good and bad packets received that are between 1024 and 1518-byte long. */
+- u32 rx_sz_1519_max; /* The number of good and bad packets received that are between 1519-byte and MTU. */
+- u32 rx_sz_ov; /* The number of good and bad packets received that are more than MTU size šC truncated by Selene. */
+- u32 rx_rxf_ov; /* The number of frame dropped due to occurrence of RX FIFO overflow. */
+- u32 rx_rrd_ov; /* The number of frame dropped due to occurrence of RRD overflow. */
+- u32 rx_align_err; /* Alignment Error */
+- u32 rx_bcast_byte_cnt; /* The byte count of broadcast packet received, excluding FCS. */
+- u32 rx_mcast_byte_cnt; /* The byte count of multicast packet received, excluding FCS. */
+- u32 rx_err_addr; /* The number of packets dropped due to address filtering. */
+-
+- /* tx */
+- u32 tx_ok; /* The number of good packet transmitted. */
+- u32 tx_bcast; /* The number of good broadcast packet transmitted. */
+- u32 tx_mcast; /* The number of good multicast packet transmitted. */
+- u32 tx_pause; /* The number of Pause packet transmitted. */
+- u32 tx_exc_defer; /* The number of packets transmitted with excessive deferral. */
+- u32 tx_ctrl; /* The number of packets transmitted is a control frame, excluding Pause frame. */
+- u32 tx_defer; /* The number of packets transmitted that is deferred. */
+- u32 tx_byte_cnt; /* The number of bytes of data transmitted. FCS is NOT included. */
+- u32 tx_sz_64; /* The number of good and bad packets transmitted that are 64 byte long. */
+- u32 tx_sz_65_127; /* The number of good and bad packets transmitted that are between 65 and 127-byte long. */
+- u32 tx_sz_128_255; /* The number of good and bad packets transmitted that are between 128 and 255-byte long. */
+- u32 tx_sz_256_511; /* The number of good and bad packets transmitted that are between 256 and 511-byte long. */
+- u32 tx_sz_512_1023; /* The number of good and bad packets transmitted that are between 512 and 1023-byte long. */
+- u32 tx_sz_1024_1518; /* The number of good and bad packets transmitted that are between 1024 and 1518-byte long. */
+- u32 tx_sz_1519_max; /* The number of good and bad packets transmitted that are between 1519-byte and MTU. */
+- u32 tx_1_col; /* The number of packets subsequently transmitted successfully with a single prior collision. */
+- u32 tx_2_col; /* The number of packets subsequently transmitted successfully with multiple prior collisions. */
+- u32 tx_late_col; /* The number of packets transmitted with late collisions. */
+- u32 tx_abort_col; /* The number of transmit packets aborted due to excessive collisions. */
+- u32 tx_underrun; /* The number of transmit packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */
+- u32 tx_rd_eop; /* The number of times that read beyond the EOP into the next frame area when TRD was not written timely */
+- u32 tx_len_err; /* The number of transmit packets with length field does NOT match the actual frame size. */
+- u32 tx_trunc; /* The number of transmit packets truncated due to size exceeding MTU. */
+- u32 tx_bcast_byte; /* The byte count of broadcast packet transmitted, excluding FCS. */
+- u32 tx_mcast_byte; /* The byte count of multicast packet transmitted, excluding FCS. */
+- u32 smb_updated; /* 1: SMB Updated. This is used by software as the indication of the statistics update.
+- * Software should clear this bit as soon as retrieving the statistics information. */
+-};
+-
+-/* Coalescing Message Block */
+-struct coals_msg_block {
+- u32 int_stats; /* interrupt status */
+- u16 rrd_prod_idx; /* TRD Producer Index. */
+- u16 rfd_cons_idx; /* RFD Consumer Index. */
+- u16 update; /* Selene sets this bit every time it DMA the CMB to host memory.
+- * Software supposes to clear this bit when CMB information is processed. */
+- u16 tpd_cons_idx; /* TPD Consumer Index. */
+-};
+-
+-/* RRD descriptor */
+-struct rx_return_desc {
+- u8 num_buf; /* Number of RFD buffers used by the received packet */
+- u8 resved;
+- u16 buf_indx; /* RFD Index of the first buffer */
+- union {
+- u32 valid;
+- struct {
+- u16 rx_chksum;
+- u16 pkt_size;
+- } xsum_sz;
+- } xsz;
+-
+- u16 pkt_flg; /* Packet flags */
+- u16 err_flg; /* Error flags */
+- u16 resved2;
+- u16 vlan_tag; /* VLAN TAG */
+-};
+-
+-#define PACKET_FLAG_ETH_TYPE 0x0080
+-#define PACKET_FLAG_VLAN_INS 0x0100
+-#define PACKET_FLAG_ERR 0x0200
+-#define PACKET_FLAG_IPV4 0x0400
+-#define PACKET_FLAG_UDP 0x0800
+-#define PACKET_FLAG_TCP 0x1000
+-#define PACKET_FLAG_BCAST 0x2000
+-#define PACKET_FLAG_MCAST 0x4000
+-#define PACKET_FLAG_PAUSE 0x8000
+-
+-#define ERR_FLAG_CRC 0x0001
+-#define ERR_FLAG_CODE 0x0002
+-#define ERR_FLAG_DRIBBLE 0x0004
+-#define ERR_FLAG_RUNT 0x0008
+-#define ERR_FLAG_OV 0x0010
+-#define ERR_FLAG_TRUNC 0x0020
+-#define ERR_FLAG_IP_CHKSUM 0x0040
+-#define ERR_FLAG_L4_CHKSUM 0x0080
+-#define ERR_FLAG_LEN 0x0100
+-#define ERR_FLAG_DES_ADDR 0x0200
+-
+-/* RFD descriptor */
+-struct rx_free_desc {
+- __le64 buffer_addr; /* Address of the descriptor's data buffer */
+- __le16 buf_len; /* Size of the receive buffer in host memory, in byte */
+- u16 coalese; /* Update consumer index to host after the reception of this frame */
+- /* __attribute__ ((packed)) is required */
+-} __attribute__ ((packed));
+-
+-/* tsopu defines */
+-#define TSO_PARAM_BUFLEN_MASK 0x3FFF
+-#define TSO_PARAM_BUFLEN_SHIFT 0
+-#define TSO_PARAM_DMAINT_MASK 0x0001
+-#define TSO_PARAM_DMAINT_SHIFT 14
+-#define TSO_PARAM_PKTNT_MASK 0x0001
+-#define TSO_PARAM_PKTINT_SHIFT 15
+-#define TSO_PARAM_VLANTAG_MASK 0xFFFF
+-#define TSO_PARAM_VLAN_SHIFT 16
+-
+-/* tsopl defines */
+-#define TSO_PARAM_EOP_MASK 0x0001
+-#define TSO_PARAM_EOP_SHIFT 0
+-#define TSO_PARAM_COALESCE_MASK 0x0001
+-#define TSO_PARAM_COALESCE_SHIFT 1
+-#define TSO_PARAM_INSVLAG_MASK 0x0001
+-#define TSO_PARAM_INSVLAG_SHIFT 2
+-#define TSO_PARAM_CUSTOMCKSUM_MASK 0x0001
+-#define TSO_PARAM_CUSTOMCKSUM_SHIFT 3
+-#define TSO_PARAM_SEGMENT_MASK 0x0001
+-#define TSO_PARAM_SEGMENT_SHIFT 4
+-#define TSO_PARAM_IPCKSUM_MASK 0x0001
+-#define TSO_PARAM_IPCKSUM_SHIFT 5
+-#define TSO_PARAM_TCPCKSUM_MASK 0x0001
+-#define TSO_PARAM_TCPCKSUM_SHIFT 6
+-#define TSO_PARAM_UDPCKSUM_MASK 0x0001
+-#define TSO_PARAM_UDPCKSUM_SHIFT 7
+-#define TSO_PARAM_VLANTAGGED_MASK 0x0001
+-#define TSO_PARAM_VLANTAGGED_SHIFT 8
+-#define TSO_PARAM_ETHTYPE_MASK 0x0001
+-#define TSO_PARAM_ETHTYPE_SHIFT 9
+-#define TSO_PARAM_IPHL_MASK 0x000F
+-#define TSO_PARAM_IPHL_SHIFT 10
+-#define TSO_PARAM_TCPHDRLEN_MASK 0x000F
+-#define TSO_PARAM_TCPHDRLEN_SHIFT 14
+-#define TSO_PARAM_HDRFLAG_MASK 0x0001
+-#define TSO_PARAM_HDRFLAG_SHIFT 18
+-#define TSO_PARAM_MSS_MASK 0x1FFF
+-#define TSO_PARAM_MSS_SHIFT 19
+-
+-/* csumpu defines */
+-#define CSUM_PARAM_BUFLEN_MASK 0x3FFF
+-#define CSUM_PARAM_BUFLEN_SHIFT 0
+-#define CSUM_PARAM_DMAINT_MASK 0x0001
+-#define CSUM_PARAM_DMAINT_SHIFT 14
+-#define CSUM_PARAM_PKTINT_MASK 0x0001
+-#define CSUM_PARAM_PKTINT_SHIFT 15
+-#define CSUM_PARAM_VALANTAG_MASK 0xFFFF
+-#define CSUM_PARAM_VALAN_SHIFT 16
+-
+-/* csumpl defines*/
+-#define CSUM_PARAM_EOP_MASK 0x0001
+-#define CSUM_PARAM_EOP_SHIFT 0
+-#define CSUM_PARAM_COALESCE_MASK 0x0001
+-#define CSUM_PARAM_COALESCE_SHIFT 1
+-#define CSUM_PARAM_INSVLAG_MASK 0x0001
+-#define CSUM_PARAM_INSVLAG_SHIFT 2
+-#define CSUM_PARAM_CUSTOMCKSUM_MASK 0x0001
+-#define CSUM_PARAM_CUSTOMCKSUM_SHIFT 3
+-#define CSUM_PARAM_SEGMENT_MASK 0x0001
+-#define CSUM_PARAM_SEGMENT_SHIFT 4
+-#define CSUM_PARAM_IPCKSUM_MASK 0x0001
+-#define CSUM_PARAM_IPCKSUM_SHIFT 5
+-#define CSUM_PARAM_TCPCKSUM_MASK 0x0001
+-#define CSUM_PARAM_TCPCKSUM_SHIFT 6
+-#define CSUM_PARAM_UDPCKSUM_MASK 0x0001
+-#define CSUM_PARAM_UDPCKSUM_SHIFT 7
+-#define CSUM_PARAM_VLANTAGGED_MASK 0x0001
+-#define CSUM_PARAM_VLANTAGGED_SHIFT 8
+-#define CSUM_PARAM_ETHTYPE_MASK 0x0001
+-#define CSUM_PARAM_ETHTYPE_SHIFT 9
+-#define CSUM_PARAM_IPHL_MASK 0x000F
+-#define CSUM_PARAM_IPHL_SHIFT 10
+-#define CSUM_PARAM_PLOADOFFSET_MASK 0x00FF
+-#define CSUM_PARAM_PLOADOFFSET_SHIFT 16
+-#define CSUM_PARAM_XSUMOFFSET_MASK 0x00FF
+-#define CSUM_PARAM_XSUMOFFSET_SHIFT 24
+-
+-/* TPD descriptor */
+-struct tso_param {
+- /* The order of these declarations is important -- don't change it */
+- u32 tsopu; /* tso_param upper word */
+- u32 tsopl; /* tso_param lower word */
+-};
+-
+-struct csum_param {
+- /* The order of these declarations is important -- don't change it */
+- u32 csumpu; /* csum_param upper word */
+- u32 csumpl; /* csum_param lower word */
+-};
+-
+-union tpd_descr {
+- u64 data;
+- struct csum_param csum;
+- struct tso_param tso;
+-};
+-
+-struct tx_packet_desc {
+- __le64 buffer_addr;
+- union tpd_descr desc;
+-};
+-
+-/* DMA Order Settings */
+-enum atl1_dma_order {
+- atl1_dma_ord_in = 1,
+- atl1_dma_ord_enh = 2,
+- atl1_dma_ord_out = 4
+-};
+-
+-enum atl1_dma_rcb {
+- atl1_rcb_64 = 0,
+- atl1_rcb_128 = 1
+-};
+-
+-enum atl1_dma_req_block {
+- atl1_dma_req_128 = 0,
+- atl1_dma_req_256 = 1,
+- atl1_dma_req_512 = 2,
+- atl1_dma_req_1024 = 3,
+- atl1_dma_req_2048 = 4,
+- atl1_dma_req_4096 = 5
+-};
+-
+-struct atl1_spi_flash_dev {
+- const char *manu_name; /* manufacturer id */
+- /* op-code */
+- u8 cmd_wrsr;
+- u8 cmd_read;
+- u8 cmd_program;
+- u8 cmd_wren;
+- u8 cmd_wrdi;
+- u8 cmd_rdsr;
+- u8 cmd_rdid;
+- u8 cmd_sector_erase;
+- u8 cmd_chip_erase;
+-};
+-
+-#endif /* _ATL1_HW_H_ */
+diff --git a/drivers/net/atl1/atl1_main.c b/drivers/net/atl1/atl1_main.c
+deleted file mode 100644
+index 129b8b3..0000000
+--- a/drivers/net/atl1/atl1_main.c
++++ /dev/null
+@@ -1,2450 +0,0 @@
+-/*
+- * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+- * Copyright(c) 2006 Chris Snook <csnook at redhat.com>
+- * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
+- *
+- * 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.
+- *
+- * The full GNU General Public License is included in this distribution in the
+- * file called COPYING.
+- *
+- * Contact Information:
+- * Xiong Huang <xiong_huang at attansic.com>
+- * Attansic Technology Corp. 3F 147, Xianzheng 9th Road, Zhubei,
+- * Xinzhu 302, TAIWAN, REPUBLIC OF CHINA
+- *
+- * Chris Snook <csnook at redhat.com>
+- * Jay Cliburn <jcliburn at gmail.com>
+- *
+- * This version is adapted from the Attansic reference driver for
+- * inclusion in the Linux kernel. It is currently under heavy development.
+- * A very incomplete list of things that need to be dealt with:
+- *
+- * TODO:
+- * Fix TSO; tx performance is horrible with TSO enabled.
+- * Wake on LAN.
+- * Add more ethtool functions.
+- * Fix abstruse irq enable/disable condition described here:
+- * http://marc.theaimsgroup.com/?l=linux-netdev&m=116398508500553&w=2
+- *
+- * NEEDS TESTING:
+- * VLAN
+- * multicast
+- * promiscuous mode
+- * interrupt coalescing
+- * SMP torture testing
+- */
+-
+-#include <linux/types.h>
+-#include <linux/netdevice.h>
+-#include <linux/pci.h>
+-#include <linux/spinlock.h>
+-#include <linux/slab.h>
+-#include <linux/string.h>
+-#include <linux/skbuff.h>
+-#include <linux/etherdevice.h>
+-#include <linux/if_vlan.h>
+-#include <linux/if_ether.h>
+-#include <linux/irqreturn.h>
+-#include <linux/workqueue.h>
+-#include <linux/timer.h>
+-#include <linux/jiffies.h>
+-#include <linux/hardirq.h>
+-#include <linux/interrupt.h>
+-#include <linux/irqflags.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/net.h>
+-#include <linux/pm.h>
+-#include <linux/in.h>
+-#include <linux/ip.h>
+-#include <linux/tcp.h>
+-#include <linux/compiler.h>
+-#include <linux/delay.h>
+-#include <linux/mii.h>
+-#include <net/checksum.h>
+-
+-#include <asm/atomic.h>
+-#include <asm/byteorder.h>
+-
+-#include "atl1.h"
+-
+-#define DRIVER_VERSION "2.0.7"
+-
+-char atl1_driver_name[] = "atl1";
+-static const char atl1_driver_string[] = "Attansic L1 Ethernet Network Driver";
+-static const char atl1_copyright[] = "Copyright(c) 2005-2006 Attansic Corporation.";
+-char atl1_driver_version[] = DRIVER_VERSION;
+-
+-MODULE_AUTHOR
+- ("Attansic Corporation <xiong_huang at attansic.com>, Chris Snook <csnook at redhat.com>, Jay Cliburn <jcliburn at gmail.com>");
+-MODULE_DESCRIPTION("Attansic 1000M Ethernet Network Driver");
+-MODULE_LICENSE("GPL");
+-MODULE_VERSION(DRIVER_VERSION);
+-
+-/*
+- * atl1_pci_tbl - PCI Device ID Table
+- */
+-static const struct pci_device_id atl1_pci_tbl[] = {
+- {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1)},
+- /* required last entry */
+- {0,}
+-};
+-
+-MODULE_DEVICE_TABLE(pci, atl1_pci_tbl);
+-
+-/*
+- * atl1_sw_init - Initialize general software structures (struct atl1_adapter)
+- * @adapter: board private structure to initialize
+- *
+- * atl1_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 atl1_sw_init(struct atl1_adapter *adapter)
+-{
+- struct atl1_hw *hw = &adapter->hw;
+- struct net_device *netdev = adapter->netdev;
+-
+- hw->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
+- hw->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
+-
+- adapter->wol = 0;
+- adapter->rx_buffer_len = (hw->max_frame_size + 7) & ~7;
+- adapter->ict = 50000; /* 100ms */
+- adapter->link_speed = SPEED_0; /* hardware init */
+- adapter->link_duplex = FULL_DUPLEX;
+-
+- hw->phy_configured = false;
+- hw->preamble_len = 7;
+- hw->ipgt = 0x60;
+- hw->min_ifg = 0x50;
+- hw->ipgr1 = 0x40;
+- hw->ipgr2 = 0x60;
+- hw->max_retry = 0xf;
+- hw->lcol = 0x37;
+- hw->jam_ipg = 7;
+- hw->rfd_burst = 8;
+- hw->rrd_burst = 8;
+- hw->rfd_fetch_gap = 1;
+- hw->rx_jumbo_th = adapter->rx_buffer_len / 8;
+- hw->rx_jumbo_lkah = 1;
+- hw->rrd_ret_timer = 16;
+- hw->tpd_burst = 4;
+- hw->tpd_fetch_th = 16;
+- hw->txf_burst = 0x100;
+- hw->tx_jumbo_task_th = (hw->max_frame_size + 7) >> 3;
+- hw->tpd_fetch_gap = 1;
+- hw->rcb_value = atl1_rcb_64;
+- hw->dma_ord = atl1_dma_ord_enh;
+- hw->dmar_block = atl1_dma_req_256;
+- hw->dmaw_block = atl1_dma_req_256;
+- hw->cmb_rrd = 4;
+- hw->cmb_tpd = 4;
+- hw->cmb_rx_timer = 1; /* about 2us */
+- hw->cmb_tx_timer = 1; /* about 2us */
+- hw->smb_timer = 100000; /* about 200ms */
+-
+- spin_lock_init(&adapter->lock);
+- spin_lock_init(&adapter->mb_lock);
+-
+- return 0;
+-}
+-
+-static int mdio_read(struct net_device *netdev, int phy_id, int reg_num)
+-{
+- struct atl1_adapter *adapter = netdev_priv(netdev);
+- u16 result;
+-
+- atl1_read_phy_reg(&adapter->hw, reg_num & 0x1f, &result);
+-
+- return result;
+-}
+-
+-static void mdio_write(struct net_device *netdev, int phy_id, int reg_num,
+- int val)
+-{
+- struct atl1_adapter *adapter = netdev_priv(netdev);
+-
+- atl1_write_phy_reg(&adapter->hw, reg_num, val);
+-}
+-
+-/*
+- * atl1_mii_ioctl -
+- * @netdev:
+- * @ifreq:
+- * @cmd:
+- */
+-static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+-{
+- struct atl1_adapter *adapter = netdev_priv(netdev);
+- unsigned long flags;
+- int retval;
+-
+- if (!netif_running(netdev))
+- return -EINVAL;
+-
+- spin_lock_irqsave(&adapter->lock, flags);
+- retval = generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
+- spin_unlock_irqrestore(&adapter->lock, flags);
+-
+- return retval;
+-}
+-
+-/*
+- * atl1_ioctl -
+- * @netdev:
+- * @ifreq:
+- * @cmd:
+- */
+-static int atl1_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+-{
+- switch (cmd) {
+- case SIOCGMIIPHY:
+- case SIOCGMIIREG:
+- case SIOCSMIIREG:
+- return atl1_mii_ioctl(netdev, ifr, cmd);
+- default:
+- return -EOPNOTSUPP;
+- }
+-}
+-
+-/*
+- * atl1_setup_mem_resources - allocate Tx / RX descriptor resources
+- * @adapter: board private structure
+- *
+- * Return 0 on success, negative on failure
+- */
+-s32 atl1_setup_ring_resources(struct atl1_adapter *adapter)
+-{
+- struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+- struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+- struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+- struct atl1_ring_header *ring_header = &adapter->ring_header;
+- struct pci_dev *pdev = adapter->pdev;
+- int size;
+- u8 offset = 0;
+-
+- size = sizeof(struct atl1_buffer) * (tpd_ring->count + rfd_ring->count);
+- tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL);
+- if (unlikely(!tpd_ring->buffer_info)) {
+- dev_err(&pdev->dev, "kzalloc failed , size = D%d\n", size);
+- goto err_nomem;
+- }
+- rfd_ring->buffer_info =
+- (struct atl1_buffer *)(tpd_ring->buffer_info + tpd_ring->count);
+-
+- /* real ring DMA buffer
+- * each ring/block may need up to 8 bytes for alignment, hence the
+- * additional 40 bytes tacked onto the end.
+- */
+- ring_header->size = size =
+- sizeof(struct tx_packet_desc) * tpd_ring->count
+- + sizeof(struct rx_free_desc) * rfd_ring->count
+- + sizeof(struct rx_return_desc) * rrd_ring->count
+- + sizeof(struct coals_msg_block)
+- + sizeof(struct stats_msg_block)
+- + 40;
+-
+- ring_header->desc = pci_alloc_consistent(pdev, ring_header->size,
+- &ring_header->dma);
+- if (unlikely(!ring_header->desc)) {
+- dev_err(&pdev->dev, "pci_alloc_consistent failed\n");
+- goto err_nomem;
+- }
+-
+- memset(ring_header->desc, 0, ring_header->size);
+-
+- /* init TPD ring */
+- tpd_ring->dma = ring_header->dma;
+- offset = (tpd_ring->dma & 0x7) ? (8 - (ring_header->dma & 0x7)) : 0;
+- tpd_ring->dma += offset;
+- tpd_ring->desc = (u8 *) ring_header->desc + offset;
+- tpd_ring->size = sizeof(struct tx_packet_desc) * tpd_ring->count;
+-
+- /* init RFD ring */
+- rfd_ring->dma = tpd_ring->dma + tpd_ring->size;
+- offset = (rfd_ring->dma & 0x7) ? (8 - (rfd_ring->dma & 0x7)) : 0;
+- rfd_ring->dma += offset;
+- rfd_ring->desc = (u8 *) tpd_ring->desc + (tpd_ring->size + offset);
+- rfd_ring->size = sizeof(struct rx_free_desc) * rfd_ring->count;
+-
+-
+- /* init RRD ring */
+- rrd_ring->dma = rfd_ring->dma + rfd_ring->size;
+- offset = (rrd_ring->dma & 0x7) ? (8 - (rrd_ring->dma & 0x7)) : 0;
+- rrd_ring->dma += offset;
+- rrd_ring->desc = (u8 *) rfd_ring->desc + (rfd_ring->size + offset);
+- rrd_ring->size = sizeof(struct rx_return_desc) * rrd_ring->count;
+-
+-
+- /* init CMB */
+- adapter->cmb.dma = rrd_ring->dma + rrd_ring->size;
+- offset = (adapter->cmb.dma & 0x7) ? (8 - (adapter->cmb.dma & 0x7)) : 0;
+- adapter->cmb.dma += offset;
+- adapter->cmb.cmb = (struct coals_msg_block *)
+- ((u8 *) rrd_ring->desc + (rrd_ring->size + offset));
+-
+- /* init SMB */
+- adapter->smb.dma = adapter->cmb.dma + sizeof(struct coals_msg_block);
+- offset = (adapter->smb.dma & 0x7) ? (8 - (adapter->smb.dma & 0x7)) : 0;
+- adapter->smb.dma += offset;
+- adapter->smb.smb = (struct stats_msg_block *)
+- ((u8 *) adapter->cmb.cmb +
+- (sizeof(struct coals_msg_block) + offset));
+-
+- return ATL1_SUCCESS;
+-
+-err_nomem:
+- kfree(tpd_ring->buffer_info);
+- return -ENOMEM;
+-}
+-
+-static void atl1_init_ring_ptrs(struct atl1_adapter *adapter)
+-{
+- struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+- struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+- struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+-
+- atomic_set(&tpd_ring->next_to_use, 0);
+- atomic_set(&tpd_ring->next_to_clean, 0);
+-
+- rfd_ring->next_to_clean = 0;
+- atomic_set(&rfd_ring->next_to_use, 0);
+-
+- rrd_ring->next_to_use = 0;
+- atomic_set(&rrd_ring->next_to_clean, 0);
+-}
+-
+-/*
+- * atl1_clean_rx_ring - Free RFD Buffers
+- * @adapter: board private structure
+- */
+-static void atl1_clean_rx_ring(struct atl1_adapter *adapter)
+-{
+- struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+- struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+- struct atl1_buffer *buffer_info;
+- struct pci_dev *pdev = adapter->pdev;
+- unsigned long size;
+- unsigned int i;
+-
+- /* Free all the Rx ring sk_buffs */
+- for (i = 0; i < rfd_ring->count; i++) {
+- buffer_info = &rfd_ring->buffer_info[i];
+- if (buffer_info->dma) {
+- pci_unmap_page(pdev, buffer_info->dma,
+- buffer_info->length, PCI_DMA_FROMDEVICE);
+- buffer_info->dma = 0;
+- }
+- if (buffer_info->skb) {
+- dev_kfree_skb(buffer_info->skb);
+- buffer_info->skb = NULL;
+- }
+- }
+-
+- size = sizeof(struct atl1_buffer) * rfd_ring->count;
+- memset(rfd_ring->buffer_info, 0, size);
+-
+- /* Zero out the descriptor ring */
+- memset(rfd_ring->desc, 0, rfd_ring->size);
+-
+- rfd_ring->next_to_clean = 0;
+- atomic_set(&rfd_ring->next_to_use, 0);
+-
+- rrd_ring->next_to_use = 0;
+- atomic_set(&rrd_ring->next_to_clean, 0);
+-}
+-
+-/*
+- * atl1_clean_tx_ring - Free Tx Buffers
+- * @adapter: board private structure
+- */
+-static void atl1_clean_tx_ring(struct atl1_adapter *adapter)
+-{
+- struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+- struct atl1_buffer *buffer_info;
+- struct pci_dev *pdev = adapter->pdev;
+- unsigned long size;
+- unsigned int i;
+-
+- /* Free all the Tx ring sk_buffs */
+- for (i = 0; i < tpd_ring->count; i++) {
+- buffer_info = &tpd_ring->buffer_info[i];
+- if (buffer_info->dma) {
+- pci_unmap_page(pdev, buffer_info->dma,
+- buffer_info->length, PCI_DMA_TODEVICE);
+- buffer_info->dma = 0;
+- }
+- }
+-
+- for (i = 0; i < tpd_ring->count; i++) {
+- buffer_info = &tpd_ring->buffer_info[i];
+- if (buffer_info->skb) {
+- dev_kfree_skb_any(buffer_info->skb);
+- buffer_info->skb = NULL;
+- }
+- }
+-
+- size = sizeof(struct atl1_buffer) * tpd_ring->count;
+- memset(tpd_ring->buffer_info, 0, size);
+-
+- /* Zero out the descriptor ring */
+- memset(tpd_ring->desc, 0, tpd_ring->size);
+-
+- atomic_set(&tpd_ring->next_to_use, 0);
+- atomic_set(&tpd_ring->next_to_clean, 0);
+-}
+-
+-/*
+- * atl1_free_ring_resources - Free Tx / RX descriptor Resources
+- * @adapter: board private structure
+- *
+- * Free all transmit software resources
+- */
+-void atl1_free_ring_resources(struct atl1_adapter *adapter)
+-{
+- struct pci_dev *pdev = adapter->pdev;
+- struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+- struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+- struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+- struct atl1_ring_header *ring_header = &adapter->ring_header;
+-
+- atl1_clean_tx_ring(adapter);
+- atl1_clean_rx_ring(adapter);
+-
+- kfree(tpd_ring->buffer_info);
+- pci_free_consistent(pdev, ring_header->size, ring_header->desc,
+- ring_header->dma);
+-
+- tpd_ring->buffer_info = NULL;
+- tpd_ring->desc = NULL;
+- tpd_ring->dma = 0;
+-
+- rfd_ring->buffer_info = NULL;
+- rfd_ring->desc = NULL;
+- rfd_ring->dma = 0;
+-
+- rrd_ring->desc = NULL;
+- rrd_ring->dma = 0;
+-}
+-
+-static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter)
+-{
+- u32 value;
+- struct atl1_hw *hw = &adapter->hw;
+- struct net_device *netdev = adapter->netdev;
+- /* Config MAC CTRL Register */
+- value = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN;
+- /* duplex */
+- if (FULL_DUPLEX == adapter->link_duplex)
+- value |= MAC_CTRL_DUPLX;
+- /* speed */
+- value |= ((u32) ((SPEED_1000 == adapter->link_speed) ?
+- MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) <<
+- MAC_CTRL_SPEED_SHIFT);
+- /* flow control */
+- value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
+- /* PAD & CRC */
+- value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
+- /* preamble length */
+- value |= (((u32) adapter->hw.preamble_len
+- & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
+- /* vlan */
+- if (adapter->vlgrp)
+- value |= MAC_CTRL_RMV_VLAN;
+- /* rx checksum
+- if (adapter->rx_csum)
+- value |= MAC_CTRL_RX_CHKSUM_EN;
+- */
+- /* filter mode */
+- value |= MAC_CTRL_BC_EN;
+- if (netdev->flags & IFF_PROMISC)
+- value |= MAC_CTRL_PROMIS_EN;
+- else if (netdev->flags & IFF_ALLMULTI)
+- value |= MAC_CTRL_MC_ALL_EN;
+- /* value |= MAC_CTRL_LOOPBACK; */
+- iowrite32(value, hw->hw_addr + REG_MAC_CTRL);
+-}
+-
+-/*
+- * atl1_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 atl1_set_mac(struct net_device *netdev, void *p)
+-{
+- struct atl1_adapter *adapter = netdev_priv(netdev);
+- struct sockaddr *addr = p;
+-
+- if (netif_running(netdev))
+- return -EBUSY;
+-
+- if (!is_valid_ether_addr(addr->sa_data))
+- return -EADDRNOTAVAIL;
+-
+- memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+- memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
+-
+- atl1_set_mac_addr(&adapter->hw);
+- return 0;
+-}
+-
+-static u32 atl1_check_link(struct atl1_adapter *adapter)
+-{
+- struct atl1_hw *hw = &adapter->hw;
+- struct net_device *netdev = adapter->netdev;
+- u32 ret_val;
+- u16 speed, duplex, phy_data;
+- int reconfig = 0;
+-
+- /* MII_BMSR must read twice */
+- atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
+- atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
+- if (!(phy_data & BMSR_LSTATUS)) { /* link down */
+- if (netif_carrier_ok(netdev)) { /* old link state: Up */
+- dev_info(&adapter->pdev->dev, "link is down\n");
+- adapter->link_speed = SPEED_0;
+- netif_carrier_off(netdev);
+- netif_stop_queue(netdev);
+- }
+- return ATL1_SUCCESS;
+- }
+-
+- /* Link Up */
+- ret_val = atl1_get_speed_and_duplex(hw, &speed, &duplex);
+- if (ret_val)
+- return ret_val;
+-
+- switch (hw->media_type) {
+- case MEDIA_TYPE_1000M_FULL:
+- if (speed != SPEED_1000 || duplex != FULL_DUPLEX)
+- reconfig = 1;
+- break;
+- case MEDIA_TYPE_100M_FULL:
+- if (speed != SPEED_100 || duplex != FULL_DUPLEX)
+- reconfig = 1;
+- break;
+- case MEDIA_TYPE_100M_HALF:
+- if (speed != SPEED_100 || duplex != HALF_DUPLEX)
+- reconfig = 1;
+- break;
+- case MEDIA_TYPE_10M_FULL:
+- if (speed != SPEED_10 || duplex != FULL_DUPLEX)
+- reconfig = 1;
+- break;
+- case MEDIA_TYPE_10M_HALF:
+- if (speed != SPEED_10 || duplex != HALF_DUPLEX)
+- reconfig = 1;
+- break;
+- }
+-
+- /* link result is our setting */
+- if (!reconfig) {
+- if (adapter->link_speed != speed
+- || adapter->link_duplex != duplex) {
+- adapter->link_speed = speed;
+- adapter->link_duplex = duplex;
+- atl1_setup_mac_ctrl(adapter);
+- dev_info(&adapter->pdev->dev,
+- "%s link is up %d Mbps %s\n",
+- netdev->name, adapter->link_speed,
+- adapter->link_duplex == FULL_DUPLEX ?
+- "full duplex" : "half duplex");
+- }
+- if (!netif_carrier_ok(netdev)) { /* Link down -> Up */
+- netif_carrier_on(netdev);
+- netif_wake_queue(netdev);
+- }
+- return ATL1_SUCCESS;
+- }
+-
+- /* change orignal link status */
+- if (netif_carrier_ok(netdev)) {
+- adapter->link_speed = SPEED_0;
+- netif_carrier_off(netdev);
+- netif_stop_queue(netdev);
+- }
+-
+- if (hw->media_type != MEDIA_TYPE_AUTO_SENSOR &&
+- hw->media_type != MEDIA_TYPE_1000M_FULL) {
+- switch (hw->media_type) {
+- case MEDIA_TYPE_100M_FULL:
+- phy_data = MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
+- MII_CR_RESET;
+- break;
+- case MEDIA_TYPE_100M_HALF:
+- phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+- break;
+- case MEDIA_TYPE_10M_FULL:
+- phy_data =
+- MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
+- break;
+- default: /* MEDIA_TYPE_10M_HALF: */
+- phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+- break;
+- }
+- atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+- return ATL1_SUCCESS;
+- }
+-
+- /* auto-neg, insert timer to re-config phy */
+- if (!adapter->phy_timer_pending) {
+- adapter->phy_timer_pending = true;
+- mod_timer(&adapter->phy_config_timer, jiffies + 3 * HZ);
+- }
+-
+- return ATL1_SUCCESS;
+-}
+-
+-static void atl1_check_for_link(struct atl1_adapter *adapter)
+-{
+- struct net_device *netdev = adapter->netdev;
+- u16 phy_data = 0;
+-
+- spin_lock(&adapter->lock);
+- adapter->phy_timer_pending = false;
+- atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+- atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+- spin_unlock(&adapter->lock);
+-
+- /* notify upper layer link down ASAP */
+- if (!(phy_data & BMSR_LSTATUS)) { /* Link Down */
+- if (netif_carrier_ok(netdev)) { /* old link state: Up */
+- dev_info(&adapter->pdev->dev, "%s link is down\n",
+- netdev->name);
+- adapter->link_speed = SPEED_0;
+- netif_carrier_off(netdev);
+- netif_stop_queue(netdev);
+- }
+- }
+- schedule_work(&adapter->link_chg_task);
+-}
+-
+-/*
+- * atl1_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 atl1_set_multi(struct net_device *netdev)
+-{
+- struct atl1_adapter *adapter = netdev_priv(netdev);
+- struct atl1_hw *hw = &adapter->hw;
+- struct dev_mc_list *mc_ptr;
+- u32 rctl;
+- u32 hash_value;
+-
+- /* Check for Promiscuous and All Multicast modes */
+- rctl = ioread32(hw->hw_addr + REG_MAC_CTRL);
+- if (netdev->flags & IFF_PROMISC)
+- rctl |= MAC_CTRL_PROMIS_EN;
+- else if (netdev->flags & IFF_ALLMULTI) {
+- rctl |= MAC_CTRL_MC_ALL_EN;
+- rctl &= ~MAC_CTRL_PROMIS_EN;
+- } else
+- rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
+-
+- iowrite32(rctl, hw->hw_addr + REG_MAC_CTRL);
+-
+- /* clear the old settings from the multicast hash table */
+- iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
+- iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
+-
+- /* compute 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 = atl1_hash_mc_addr(hw, mc_ptr->dmi_addr);
+- atl1_hash_set(hw, hash_value);
+- }
+-}
+-
+-/*
+- * atl1_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 atl1_change_mtu(struct net_device *netdev, int new_mtu)
+-{
+- struct atl1_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)) {
+- dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
+- return -EINVAL;
+- }
+-
+- adapter->hw.max_frame_size = max_frame;
+- adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3;
+- adapter->rx_buffer_len = (max_frame + 7) & ~7;
+- adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8;
+-
+- netdev->mtu = new_mtu;
+- if ((old_mtu != new_mtu) && netif_running(netdev)) {
+- atl1_down(adapter);
+- atl1_up(adapter);
+- }
+-
+- return 0;
+-}
+-
+-static void set_flow_ctrl_old(struct atl1_adapter *adapter)
+-{
+- u32 hi, lo, value;
+-
+- /* RFD Flow Control */
+- value = adapter->rfd_ring.count;
+- hi = value / 16;
+- if (hi < 2)
+- hi = 2;
+- lo = value * 7 / 8;
+-
+- value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
+- ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
+- iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
+-
+- /* RRD Flow Control */
+- value = adapter->rrd_ring.count;
+- lo = value / 16;
+- hi = value * 7 / 8;
+- if (lo < 2)
+- lo = 2;
+- value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
+- ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
+- iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
+-}
+-
+-static void set_flow_ctrl_new(struct atl1_hw *hw)
+-{
+- u32 hi, lo, value;
+-
+- /* RXF Flow Control */
+- value = ioread32(hw->hw_addr + REG_SRAM_RXF_LEN);
+- lo = value / 16;
+- if (lo < 192)
+- lo = 192;
+- hi = value * 7 / 8;
+- if (hi < lo)
+- hi = lo + 16;
+- value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
+- ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
+- iowrite32(value, hw->hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
+-
+- /* RRD Flow Control */
+- value = ioread32(hw->hw_addr + REG_SRAM_RRD_LEN);
+- lo = value / 8;
+- hi = value * 7 / 8;
+- if (lo < 2)
+- lo = 2;
+- if (hi < lo)
+- hi = lo + 3;
+- value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
+- ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
+- iowrite32(value, hw->hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
+-}
+-
+-/*
+- * atl1_configure - Configure Transmit&Receive Unit after Reset
+- * @adapter: board private structure
+- *
+- * Configure the Tx /Rx unit of the MAC after a reset.
+- */
+-static u32 atl1_configure(struct atl1_adapter *adapter)
+-{
+- struct atl1_hw *hw = &adapter->hw;
+- u32 value;
+-
+- /* clear interrupt status */
+- iowrite32(0xffffffff, adapter->hw.hw_addr + REG_ISR);
+-
+- /* set MAC Address */
+- value = (((u32) hw->mac_addr[2]) << 24) |
+- (((u32) hw->mac_addr[3]) << 16) |
+- (((u32) hw->mac_addr[4]) << 8) |
+- (((u32) hw->mac_addr[5]));
+- iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
+- value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
+- iowrite32(value, hw->hw_addr + (REG_MAC_STA_ADDR + 4));
+-
+- /* tx / rx ring */
+-
+- /* HI base address */
+- iowrite32((u32) ((adapter->tpd_ring.dma & 0xffffffff00000000ULL) >> 32),
+- hw->hw_addr + REG_DESC_BASE_ADDR_HI);
+- /* LO base address */
+- iowrite32((u32) (adapter->rfd_ring.dma & 0x00000000ffffffffULL),
+- hw->hw_addr + REG_DESC_RFD_ADDR_LO);
+- iowrite32((u32) (adapter->rrd_ring.dma & 0x00000000ffffffffULL),
+- hw->hw_addr + REG_DESC_RRD_ADDR_LO);
+- iowrite32((u32) (adapter->tpd_ring.dma & 0x00000000ffffffffULL),
+- hw->hw_addr + REG_DESC_TPD_ADDR_LO);
+- iowrite32((u32) (adapter->cmb.dma & 0x00000000ffffffffULL),
+- hw->hw_addr + REG_DESC_CMB_ADDR_LO);
+- iowrite32((u32) (adapter->smb.dma & 0x00000000ffffffffULL),
+- hw->hw_addr + REG_DESC_SMB_ADDR_LO);
+-
+- /* element count */
+- value = adapter->rrd_ring.count;
+- value <<= 16;
+- value += adapter->rfd_ring.count;
+- iowrite32(value, hw->hw_addr + REG_DESC_RFD_RRD_RING_SIZE);
+- iowrite32(adapter->tpd_ring.count, hw->hw_addr +
+- REG_DESC_TPD_RING_SIZE);
+-
+- /* Load Ptr */
+- iowrite32(1, hw->hw_addr + REG_LOAD_PTR);
+-
+- /* config Mailbox */
+- value = ((atomic_read(&adapter->tpd_ring.next_to_use)
+- & MB_TPD_PROD_INDX_MASK) << MB_TPD_PROD_INDX_SHIFT) |
+- ((atomic_read(&adapter->rrd_ring.next_to_clean)
+- & MB_RRD_CONS_INDX_MASK) << MB_RRD_CONS_INDX_SHIFT) |
+- ((atomic_read(&adapter->rfd_ring.next_to_use)
+- & MB_RFD_PROD_INDX_MASK) << MB_RFD_PROD_INDX_SHIFT);
+- iowrite32(value, hw->hw_addr + REG_MAILBOX);
+-
+- /* config IPG/IFG */
+- value = (((u32) hw->ipgt & MAC_IPG_IFG_IPGT_MASK)
+- << MAC_IPG_IFG_IPGT_SHIFT) |
+- (((u32) hw->min_ifg & MAC_IPG_IFG_MIFG_MASK)
+- << MAC_IPG_IFG_MIFG_SHIFT) |
+- (((u32) hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK)
+- << MAC_IPG_IFG_IPGR1_SHIFT) |
+- (((u32) hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK)
+- << MAC_IPG_IFG_IPGR2_SHIFT);
+- iowrite32(value, hw->hw_addr + REG_MAC_IPG_IFG);
+-
+- /* config Half-Duplex Control */
+- value = ((u32) hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) |
+- (((u32) hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK)
+- << MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) |
+- MAC_HALF_DUPLX_CTRL_EXC_DEF_EN |
+- (0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) |
+- (((u32) hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK)
+- << MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT);
+- iowrite32(value, hw->hw_addr + REG_MAC_HALF_DUPLX_CTRL);
+-
+- /* set Interrupt Moderator Timer */
+- iowrite16(adapter->imt, hw->hw_addr + REG_IRQ_MODU_TIMER_INIT);
+- iowrite32(MASTER_CTRL_ITIMER_EN, hw->hw_addr + REG_MASTER_CTRL);
+-
+- /* set Interrupt Clear Timer */
+- iowrite16(adapter->ict, hw->hw_addr + REG_CMBDISDMA_TIMER);
+-
+- /* set max frame size hw will accept */
+- iowrite32(hw->max_frame_size, hw->hw_addr + REG_MTU);
+-
+- /* jumbo size & rrd retirement timer */
+- value = (((u32) hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK)
+- << RXQ_JMBOSZ_TH_SHIFT) |
+- (((u32) hw->rx_jumbo_lkah & RXQ_JMBO_LKAH_MASK)
+- << RXQ_JMBO_LKAH_SHIFT) |
+- (((u32) hw->rrd_ret_timer & RXQ_RRD_TIMER_MASK)
+- << RXQ_RRD_TIMER_SHIFT);
+- iowrite32(value, hw->hw_addr + REG_RXQ_JMBOSZ_RRDTIM);
+-
+- /* Flow Control */
+- switch (hw->dev_rev) {
+- case 0x8001:
+- case 0x9001:
+- case 0x9002:
+- case 0x9003:
+- set_flow_ctrl_old(adapter);
+- break;
+- default:
+- set_flow_ctrl_new(hw);
+- break;
+- }
+-
+- /* config TXQ */
+- value = (((u32) hw->tpd_burst & TXQ_CTRL_TPD_BURST_NUM_MASK)
+- << TXQ_CTRL_TPD_BURST_NUM_SHIFT) |
+- (((u32) hw->txf_burst & TXQ_CTRL_TXF_BURST_NUM_MASK)
+- << TXQ_CTRL_TXF_BURST_NUM_SHIFT) |
+- (((u32) hw->tpd_fetch_th & TXQ_CTRL_TPD_FETCH_TH_MASK)
+- << TXQ_CTRL_TPD_FETCH_TH_SHIFT) | TXQ_CTRL_ENH_MODE |
+- TXQ_CTRL_EN;
+- iowrite32(value, hw->hw_addr + REG_TXQ_CTRL);
+-
+- /* min tpd fetch gap & tx jumbo packet size threshold for taskoffload */
+- value = (((u32) hw->tx_jumbo_task_th & TX_JUMBO_TASK_TH_MASK)
+- << TX_JUMBO_TASK_TH_SHIFT) |
+- (((u32) hw->tpd_fetch_gap & TX_TPD_MIN_IPG_MASK)
+- << TX_TPD_MIN_IPG_SHIFT);
+- iowrite32(value, hw->hw_addr + REG_TX_JUMBO_TASK_TH_TPD_IPG);
+-
+- /* config RXQ */
+- value = (((u32) hw->rfd_burst & RXQ_CTRL_RFD_BURST_NUM_MASK)
+- << RXQ_CTRL_RFD_BURST_NUM_SHIFT) |
+- (((u32) hw->rrd_burst & RXQ_CTRL_RRD_BURST_THRESH_MASK)
+- << RXQ_CTRL_RRD_BURST_THRESH_SHIFT) |
+- (((u32) hw->rfd_fetch_gap & RXQ_CTRL_RFD_PREF_MIN_IPG_MASK)
+- << RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT) | RXQ_CTRL_CUT_THRU_EN |
+- RXQ_CTRL_EN;
+- iowrite32(value, hw->hw_addr + REG_RXQ_CTRL);
+-
+- /* config DMA Engine */
+- value = ((((u32) hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
+- << DMA_CTRL_DMAR_BURST_LEN_SHIFT) |
+- ((((u32) hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK)
+- << DMA_CTRL_DMAW_BURST_LEN_SHIFT) | DMA_CTRL_DMAR_EN |
+- DMA_CTRL_DMAW_EN;
+- value |= (u32) hw->dma_ord;
+- if (atl1_rcb_128 == hw->rcb_value)
+- value |= DMA_CTRL_RCB_VALUE;
+- iowrite32(value, hw->hw_addr + REG_DMA_CTRL);
+-
+- /* config CMB / SMB */
+- value = (hw->cmb_tpd > adapter->tpd_ring.count) ?
+- hw->cmb_tpd : adapter->tpd_ring.count;
+- value <<= 16;
+- value |= hw->cmb_rrd;
+- iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TH);
+- value = hw->cmb_rx_timer | ((u32) hw->cmb_tx_timer << 16);
+- iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TIMER);
+- iowrite32(hw->smb_timer, hw->hw_addr + REG_SMB_TIMER);
+-
+- /* --- enable CMB / SMB */
+- value = CSMB_CTRL_CMB_EN | CSMB_CTRL_SMB_EN;
+- iowrite32(value, hw->hw_addr + REG_CSMB_CTRL);
+-
+- value = ioread32(adapter->hw.hw_addr + REG_ISR);
+- if (unlikely((value & ISR_PHY_LINKDOWN) != 0))
+- value = 1; /* config failed */
+- else
+- value = 0;
+-
+- /* clear all interrupt status */
+- iowrite32(0x3fffffff, adapter->hw.hw_addr + REG_ISR);
+- iowrite32(0, adapter->hw.hw_addr + REG_ISR);
+- return value;
+-}
+-
+-/*
+- * atl1_pcie_patch - Patch for PCIE module
+- */
+-static void atl1_pcie_patch(struct atl1_adapter *adapter)
+-{
+- u32 value;
+-
+- /* much vendor magic here */
+- value = 0x6500;
+- iowrite32(value, adapter->hw.hw_addr + 0x12FC);
+- /* pcie flow control mode change */
+- value = ioread32(adapter->hw.hw_addr + 0x1008);
+- value |= 0x8000;
+- iowrite32(value, adapter->hw.hw_addr + 0x1008);
+-}
+-
+-/*
+- * When ACPI resume on some VIA MotherBoard, the Interrupt Disable bit/0x400
+- * on PCI Command register is disable.
+- * The function enable this bit.
+- * Brackett, 2006/03/15
+- */
+-static void atl1_via_workaround(struct atl1_adapter *adapter)
+-{
+- unsigned long value;
+-
+- value = ioread16(adapter->hw.hw_addr + PCI_COMMAND);
+- if (value & PCI_COMMAND_INTX_DISABLE)
+- value &= ~PCI_COMMAND_INTX_DISABLE;
+- iowrite32(value, adapter->hw.hw_addr + PCI_COMMAND);
+-}
+-
+-/*
+- * atl1_irq_enable - Enable default interrupt generation settings
+- * @adapter: board private structure
+- */
+-static void atl1_irq_enable(struct atl1_adapter *adapter)
+-{
+- iowrite32(IMR_NORMAL_MASK, adapter->hw.hw_addr + REG_IMR);
+- ioread32(adapter->hw.hw_addr + REG_IMR);
+-}
+-
+-/*
+- * atl1_irq_disable - Mask off interrupt generation on the NIC
+- * @adapter: board private structure
+- */
+-static void atl1_irq_disable(struct atl1_adapter *adapter)
+-{
+- iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+- ioread32(adapter->hw.hw_addr + REG_IMR);
+- synchronize_irq(adapter->pdev->irq);
+-}
+-
+-static void atl1_clear_phy_int(struct atl1_adapter *adapter)
+-{
+- u16 phy_data;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&adapter->lock, flags);
+- atl1_read_phy_reg(&adapter->hw, 19, &phy_data);
+- spin_unlock_irqrestore(&adapter->lock, flags);
+-}
+-
+-static void atl1_inc_smb(struct atl1_adapter *adapter)
+-{
+- struct stats_msg_block *smb = adapter->smb.smb;
+-
+- /* Fill out the OS statistics structure */
+- adapter->soft_stats.rx_packets += smb->rx_ok;
+- adapter->soft_stats.tx_packets += smb->tx_ok;
+- adapter->soft_stats.rx_bytes += smb->rx_byte_cnt;
+- adapter->soft_stats.tx_bytes += smb->tx_byte_cnt;
+- adapter->soft_stats.multicast += smb->rx_mcast;
+- adapter->soft_stats.collisions += (smb->tx_1_col + smb->tx_2_col * 2 +
+- smb->tx_late_col + smb->tx_abort_col * adapter->hw.max_retry);
+-
+- /* Rx Errors */
+- adapter->soft_stats.rx_errors += (smb->rx_frag + smb->rx_fcs_err +
+- smb->rx_len_err + smb->rx_sz_ov + smb->rx_rxf_ov +
+- smb->rx_rrd_ov + smb->rx_align_err);
+- adapter->soft_stats.rx_fifo_errors += smb->rx_rxf_ov;
+- adapter->soft_stats.rx_length_errors += smb->rx_len_err;
+- adapter->soft_stats.rx_crc_errors += smb->rx_fcs_err;
+- adapter->soft_stats.rx_frame_errors += smb->rx_align_err;
+- adapter->soft_stats.rx_missed_errors += (smb->rx_rrd_ov +
+- smb->rx_rxf_ov);
+-
+- adapter->soft_stats.rx_pause += smb->rx_pause;
+- adapter->soft_stats.rx_rrd_ov += smb->rx_rrd_ov;
+- adapter->soft_stats.rx_trunc += smb->rx_sz_ov;
+-
+- /* Tx Errors */
+- adapter->soft_stats.tx_errors += (smb->tx_late_col +
+- smb->tx_abort_col + smb->tx_underrun + smb->tx_trunc);
+- adapter->soft_stats.tx_fifo_errors += smb->tx_underrun;
+- adapter->soft_stats.tx_aborted_errors += smb->tx_abort_col;
+- adapter->soft_stats.tx_window_errors += smb->tx_late_col;
+-
+- adapter->soft_stats.excecol += smb->tx_abort_col;
+- adapter->soft_stats.deffer += smb->tx_defer;
+- adapter->soft_stats.scc += smb->tx_1_col;
+- adapter->soft_stats.mcc += smb->tx_2_col;
+- adapter->soft_stats.latecol += smb->tx_late_col;
+- adapter->soft_stats.tx_underun += smb->tx_underrun;
+- adapter->soft_stats.tx_trunc += smb->tx_trunc;
+- adapter->soft_stats.tx_pause += smb->tx_pause;
+-
+- adapter->net_stats.rx_packets = adapter->soft_stats.rx_packets;
+- adapter->net_stats.tx_packets = adapter->soft_stats.tx_packets;
+- adapter->net_stats.rx_bytes = adapter->soft_stats.rx_bytes;
+- adapter->net_stats.tx_bytes = adapter->soft_stats.tx_bytes;
+- adapter->net_stats.multicast = adapter->soft_stats.multicast;
+- adapter->net_stats.collisions = adapter->soft_stats.collisions;
+- adapter->net_stats.rx_errors = adapter->soft_stats.rx_errors;
+- adapter->net_stats.rx_over_errors =
+- adapter->soft_stats.rx_missed_errors;
+- adapter->net_stats.rx_length_errors =
+- adapter->soft_stats.rx_length_errors;
+- adapter->net_stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors;
+- adapter->net_stats.rx_frame_errors =
+- adapter->soft_stats.rx_frame_errors;
+- adapter->net_stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors;
+- adapter->net_stats.rx_missed_errors =
+- adapter->soft_stats.rx_missed_errors;
+- adapter->net_stats.tx_errors = adapter->soft_stats.tx_errors;
+- adapter->net_stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors;
+- adapter->net_stats.tx_aborted_errors =
+- adapter->soft_stats.tx_aborted_errors;
+- adapter->net_stats.tx_window_errors =
+- adapter->soft_stats.tx_window_errors;
+- adapter->net_stats.tx_carrier_errors =
+- adapter->soft_stats.tx_carrier_errors;
+-}
+-
+-/*
+- * atl1_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 *atl1_get_stats(struct net_device *netdev)
+-{
+- struct atl1_adapter *adapter = netdev_priv(netdev);
+- return &adapter->net_stats;
+-}
+-
+-static void atl1_update_mailbox(struct atl1_adapter *adapter)
+-{
+- unsigned long flags;
+- u32 tpd_next_to_use;
+- u32 rfd_next_to_use;
+- u32 rrd_next_to_clean;
+- u32 value;
+-
+- spin_lock_irqsave(&adapter->mb_lock, flags);
+-
+- tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
+- rfd_next_to_use = atomic_read(&adapter->rfd_ring.next_to_use);
+- rrd_next_to_clean = atomic_read(&adapter->rrd_ring.next_to_clean);
+-
+- value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
+- MB_RFD_PROD_INDX_SHIFT) |
+- ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
+- MB_RRD_CONS_INDX_SHIFT) |
+- ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
+- MB_TPD_PROD_INDX_SHIFT);
+- iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
+-
+- spin_unlock_irqrestore(&adapter->mb_lock, flags);
+-}
+-
+-static void atl1_clean_alloc_flag(struct atl1_adapter *adapter,
+- struct rx_return_desc *rrd, u16 offset)
+-{
+- struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+-
+- while (rfd_ring->next_to_clean != (rrd->buf_indx + offset)) {
+- rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced = 0;
+- if (++rfd_ring->next_to_clean == rfd_ring->count) {
+- rfd_ring->next_to_clean = 0;
+- }
+- }
+-}
+-
+-static void atl1_update_rfd_index(struct atl1_adapter *adapter,
+- struct rx_return_desc *rrd)
+-{
+- u16 num_buf;
+-
+- num_buf = (rrd->xsz.xsum_sz.pkt_size + adapter->rx_buffer_len - 1) /
+- adapter->rx_buffer_len;
+- if (rrd->num_buf == num_buf)
+- /* clean alloc flag for bad rrd */
+- atl1_clean_alloc_flag(adapter, rrd, num_buf);
+-}
+-
+-static void atl1_rx_checksum(struct atl1_adapter *adapter,
+- struct rx_return_desc *rrd, struct sk_buff *skb)
+-{
+- struct pci_dev *pdev = adapter->pdev;
+-
+- skb->ip_summed = CHECKSUM_NONE;
+-
+- if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
+- if (rrd->err_flg & (ERR_FLAG_CRC | ERR_FLAG_TRUNC |
+- ERR_FLAG_CODE | ERR_FLAG_OV)) {
+- adapter->hw_csum_err++;
+- dev_printk(KERN_DEBUG, &pdev->dev,
+- "rx checksum error\n");
+- return;
+- }
+- }
+-
+- /* not IPv4 */
+- if (!(rrd->pkt_flg & PACKET_FLAG_IPV4))
+- /* checksum is invalid, but it's not an IPv4 pkt, so ok */
+- return;
+-
+- /* IPv4 packet */
+- if (likely(!(rrd->err_flg &
+- (ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM)))) {
+- skb->ip_summed = CHECKSUM_UNNECESSARY;
+- adapter->hw_csum_good++;
+- return;
+- }
+-
+- /* IPv4, but hardware thinks its checksum is wrong */
+- dev_printk(KERN_DEBUG, &pdev->dev,
+- "hw csum wrong, pkt_flag:%x, err_flag:%x\n",
+- rrd->pkt_flg, rrd->err_flg);
+- skb->ip_summed = CHECKSUM_COMPLETE;
+- skb->csum = htons(rrd->xsz.xsum_sz.rx_chksum);
+- adapter->hw_csum_err++;
+- return;
+-}
+-
+-/*
+- * atl1_alloc_rx_buffers - Replace used receive buffers
+- * @adapter: address of board private structure
+- */
+-static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter)
+-{
+- struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+- struct pci_dev *pdev = adapter->pdev;
+- struct page *page;
+- unsigned long offset;
+- struct atl1_buffer *buffer_info, *next_info;
+- struct sk_buff *skb;
+- u16 num_alloc = 0;
+- u16 rfd_next_to_use, next_next;
+- struct rx_free_desc *rfd_desc;
+-
+- next_next = rfd_next_to_use = atomic_read(&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 (!buffer_info->alloced && !next_info->alloced) {
+- if (buffer_info->skb) {
+- buffer_info->alloced = 1;
+- goto next;
+- }
+-
+- rfd_desc = ATL1_RFD_DESC(rfd_ring, rfd_next_to_use);
+-
+- skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
+- if (unlikely(!skb)) { /* Better luck next round */
+- adapter->net_stats.rx_dropped++;
+- 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
+- */
+- skb_reserve(skb, NET_IP_ALIGN);
+-
+- buffer_info->alloced = 1;
+- buffer_info->skb = skb;
+- buffer_info->length = (u16) adapter->rx_buffer_len;
+- page = virt_to_page(skb->data);
+- offset = (unsigned long)skb->data & ~PAGE_MASK;
+- buffer_info->dma = pci_map_page(pdev, page, offset,
+- adapter->rx_buffer_len,
+- PCI_DMA_FROMDEVICE);
+- rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
+- rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len);
+- rfd_desc->coalese = 0;
+-
+-next:
+- rfd_next_to_use = next_next;
+- if (unlikely(++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) {
+- /*
+- * Force memory writes to complete before letting h/w
+- * know there are new descriptors to fetch. (Only
+- * applicable for weak-ordered memory model archs,
+- * such as IA-64).
+- */
+- wmb();
+- atomic_set(&rfd_ring->next_to_use, (int)rfd_next_to_use);
+- }
+- return num_alloc;
+-}
+-
+-static void atl1_intr_rx(struct atl1_adapter *adapter)
+-{
+- int i, count;
+- u16 length;
+- u16 rrd_next_to_clean;
+- u32 value;
+- struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+- struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+- struct atl1_buffer *buffer_info;
+- struct rx_return_desc *rrd;
+- struct sk_buff *skb;
+-
+- count = 0;
+-
+- rrd_next_to_clean = atomic_read(&rrd_ring->next_to_clean);
+-
+- while (1) {
+- rrd = ATL1_RRD_DESC(rrd_ring, rrd_next_to_clean);
+- i = 1;
+- if (likely(rrd->xsz.valid)) { /* packet valid */
+-chk_rrd:
+- /* check rrd status */
+- if (likely(rrd->num_buf == 1))
+- goto rrd_ok;
+-
+- /* rrd seems to be bad */
+- if (unlikely(i-- > 0)) {
+- /* rrd may not be DMAed completely */
+- dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+- "incomplete RRD DMA transfer\n");
+- udelay(1);
+- goto chk_rrd;
+- }
+- /* bad rrd */
+- dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+- "bad RRD\n");
+- /* see if update RFD index */
+- if (rrd->num_buf > 1)
+- atl1_update_rfd_index(adapter, rrd);
+-
+- /* update rrd */
+- rrd->xsz.valid = 0;
+- if (++rrd_next_to_clean == rrd_ring->count)
+- rrd_next_to_clean = 0;
+- count++;
+- continue;
+- } else { /* current rrd still not be updated */
+-
+- break;
+- }
+-rrd_ok:
+- /* clean alloc flag for bad rrd */
+- atl1_clean_alloc_flag(adapter, rrd, 0);
+-
+- buffer_info = &rfd_ring->buffer_info[rrd->buf_indx];
+- if (++rfd_ring->next_to_clean == rfd_ring->count)
+- rfd_ring->next_to_clean = 0;
+-
+- /* update rrd next to clean */
+- if (++rrd_next_to_clean == rrd_ring->count)
+- rrd_next_to_clean = 0;
+- count++;
+-
+- if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
+- if (!(rrd->err_flg &
+- (ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM
+- | ERR_FLAG_LEN))) {
+- /* packet error, don't need upstream */
+- buffer_info->alloced = 0;
+- rrd->xsz.valid = 0;
+- continue;
+- }
+- }
+-
+- /* Good Receive */
+- pci_unmap_page(adapter->pdev, buffer_info->dma,
+- buffer_info->length, PCI_DMA_FROMDEVICE);
+- skb = buffer_info->skb;
+- length = le16_to_cpu(rrd->xsz.xsum_sz.pkt_size);
+-
+- skb_put(skb, length - ETH_FCS_LEN);
+-
+- /* Receive Checksum Offload */
+- atl1_rx_checksum(adapter, rrd, skb);
+- skb->protocol = eth_type_trans(skb, adapter->netdev);
+-
+- if (adapter->vlgrp && (rrd->pkt_flg & PACKET_FLAG_VLAN_INS)) {
+- u16 vlan_tag = (rrd->vlan_tag >> 4) |
+- ((rrd->vlan_tag & 7) << 13) |
+- ((rrd->vlan_tag & 8) << 9);
+- vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag);
+- } else
+- netif_rx(skb);
+-
+- /* let protocol layer free skb */
+- buffer_info->skb = NULL;
+- buffer_info->alloced = 0;
+- rrd->xsz.valid = 0;
+-
+- adapter->netdev->last_rx = jiffies;
+- }
+-
+- atomic_set(&rrd_ring->next_to_clean, rrd_next_to_clean);
+-
+- atl1_alloc_rx_buffers(adapter);
+-
+- /* update mailbox ? */
+- if (count) {
+- u32 tpd_next_to_use;
+- u32 rfd_next_to_use;
+-
+- spin_lock(&adapter->mb_lock);
+-
+- tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
+- rfd_next_to_use =
+- atomic_read(&adapter->rfd_ring.next_to_use);
+- rrd_next_to_clean =
+- atomic_read(&adapter->rrd_ring.next_to_clean);
+- value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
+- MB_RFD_PROD_INDX_SHIFT) |
+- ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
+- MB_RRD_CONS_INDX_SHIFT) |
+- ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
+- MB_TPD_PROD_INDX_SHIFT);
+- iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
+- spin_unlock(&adapter->mb_lock);
+- }
+-}
+-
+-static void atl1_intr_tx(struct atl1_adapter *adapter)
+-{
+- struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+- struct atl1_buffer *buffer_info;
+- u16 sw_tpd_next_to_clean;
+- u16 cmb_tpd_next_to_clean;
+-
+- sw_tpd_next_to_clean = atomic_read(&tpd_ring->next_to_clean);
+- cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx);
+-
+- while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) {
+- struct tx_packet_desc *tpd;
+-
+- tpd = ATL1_TPD_DESC(tpd_ring, sw_tpd_next_to_clean);
+- buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean];
+- if (buffer_info->dma) {
+- 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;
+- }
+- tpd->buffer_addr = 0;
+- tpd->desc.data = 0;
+-
+- if (++sw_tpd_next_to_clean == tpd_ring->count)
+- sw_tpd_next_to_clean = 0;
+- }
+- atomic_set(&tpd_ring->next_to_clean, sw_tpd_next_to_clean);
+-
+- if (netif_queue_stopped(adapter->netdev)
+- && netif_carrier_ok(adapter->netdev))
+- netif_wake_queue(adapter->netdev);
+-}
+-
+-static u16 atl1_tpd_avail(struct atl1_tpd_ring *tpd_ring)
+-{
+- u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean);
+- u16 next_to_use = atomic_read(&tpd_ring->next_to_use);
+- return ((next_to_clean > next_to_use) ?
+- next_to_clean - next_to_use - 1 :
+- tpd_ring->count + next_to_clean - next_to_use - 1);
+-}
+-
+-static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,
+- struct tso_param *tso)
+-{
+- /* We enter this function holding a spinlock. */
+- u8 ipofst;
+- int err;
+-
+- if (skb_shinfo(skb)->gso_size) {
+- if (skb_header_cloned(skb)) {
+- err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+- if (unlikely(err))
+- return err;
+- }
+-
+- if (skb->protocol == ntohs(ETH_P_IP)) {
+- struct iphdr *iph = ip_hdr(skb);
+-
+- iph->tot_len = 0;
+- iph->check = 0;
+- tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
+- iph->daddr, 0, IPPROTO_TCP, 0);
+- ipofst = skb_network_offset(skb);
+- if (ipofst != ETH_HLEN) /* 802.3 frame */
+- tso->tsopl |= 1 << TSO_PARAM_ETHTYPE_SHIFT;
+-
+- tso->tsopl |= (iph->ihl &
+- CSUM_PARAM_IPHL_MASK) << CSUM_PARAM_IPHL_SHIFT;
+- tso->tsopl |= (tcp_hdrlen(skb) &
+- TSO_PARAM_TCPHDRLEN_MASK) <<
+- TSO_PARAM_TCPHDRLEN_SHIFT;
+- tso->tsopl |= (skb_shinfo(skb)->gso_size &
+- TSO_PARAM_MSS_MASK) << TSO_PARAM_MSS_SHIFT;
+- tso->tsopl |= 1 << TSO_PARAM_IPCKSUM_SHIFT;
+- tso->tsopl |= 1 << TSO_PARAM_TCPCKSUM_SHIFT;
+- tso->tsopl |= 1 << TSO_PARAM_SEGMENT_SHIFT;
+- return true;
+- }
+- }
+- return false;
+-}
+-
+-static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
+- struct csum_param *csum)
+-{
+- u8 css, cso;
+-
+- if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+- cso = skb_transport_offset(skb);
+- css = cso + skb->csum_offset;
+- if (unlikely(cso & 0x1)) {
+- dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+- "payload offset not an even number\n");
+- return -1;
+- }
+- csum->csumpl |= (cso & CSUM_PARAM_PLOADOFFSET_MASK) <<
+- CSUM_PARAM_PLOADOFFSET_SHIFT;
+- csum->csumpl |= (css & CSUM_PARAM_XSUMOFFSET_MASK) <<
+- CSUM_PARAM_XSUMOFFSET_SHIFT;
+- csum->csumpl |= 1 << CSUM_PARAM_CUSTOMCKSUM_SHIFT;
+- return true;
+- }
+-
+- return true;
+-}
+-
+-static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
+- bool tcp_seg)
+-{
+- /* We enter this function holding a spinlock. */
+- struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+- struct atl1_buffer *buffer_info;
+- struct page *page;
+- int first_buf_len = skb->len;
+- unsigned long offset;
+- unsigned int nr_frags;
+- unsigned int f;
+- u16 tpd_next_to_use;
+- u16 proto_hdr_len;
+- u16 len12;
+-
+- first_buf_len -= skb->data_len;
+- nr_frags = skb_shinfo(skb)->nr_frags;
+- tpd_next_to_use = atomic_read(&tpd_ring->next_to_use);
+- buffer_info = &tpd_ring->buffer_info[tpd_next_to_use];
+- if (unlikely(buffer_info->skb))
+- BUG();
+- buffer_info->skb = NULL; /* put skb in last TPD */
+-
+- if (tcp_seg) {
+- /* TSO/GSO */
+- proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+- buffer_info->length = proto_hdr_len;
+- page = virt_to_page(skb->data);
+- offset = (unsigned long)skb->data & ~PAGE_MASK;
+- buffer_info->dma = pci_map_page(adapter->pdev, page,
+- offset, proto_hdr_len,
+- PCI_DMA_TODEVICE);
+-
+- if (++tpd_next_to_use == tpd_ring->count)
+- tpd_next_to_use = 0;
+-
+- if (first_buf_len > proto_hdr_len) {
+- int i, m;
+-
+- len12 = first_buf_len - proto_hdr_len;
+- m = (len12 + ATL1_MAX_TX_BUF_LEN - 1) /
+- ATL1_MAX_TX_BUF_LEN;
+- for (i = 0; i < m; i++) {
+- buffer_info =
+- &tpd_ring->buffer_info[tpd_next_to_use];
+- buffer_info->skb = NULL;
+- buffer_info->length =
+- (ATL1_MAX_TX_BUF_LEN >=
+- len12) ? ATL1_MAX_TX_BUF_LEN : len12;
+- len12 -= buffer_info->length;
+- page = virt_to_page(skb->data +
+- (proto_hdr_len +
+- i * ATL1_MAX_TX_BUF_LEN));
+- offset = (unsigned long)(skb->data +
+- (proto_hdr_len +
+- i * ATL1_MAX_TX_BUF_LEN)) & ~PAGE_MASK;
+- buffer_info->dma = pci_map_page(adapter->pdev,
+- page, offset, buffer_info->length,
+- PCI_DMA_TODEVICE);
+- if (++tpd_next_to_use == tpd_ring->count)
+- tpd_next_to_use = 0;
+- }
+- }
+- } else {
+- /* not TSO/GSO */
+- buffer_info->length = first_buf_len;
+- page = virt_to_page(skb->data);
+- offset = (unsigned long)skb->data & ~PAGE_MASK;
+- buffer_info->dma = pci_map_page(adapter->pdev, page,
+- offset, first_buf_len, PCI_DMA_TODEVICE);
+- if (++tpd_next_to_use == tpd_ring->count)
+- tpd_next_to_use = 0;
+- }
+-
+- for (f = 0; f < nr_frags; f++) {
+- struct skb_frag_struct *frag;
+- u16 lenf, i, m;
+-
+- frag = &skb_shinfo(skb)->frags[f];
+- lenf = frag->size;
+-
+- m = (lenf + ATL1_MAX_TX_BUF_LEN - 1) / ATL1_MAX_TX_BUF_LEN;
+- for (i = 0; i < m; i++) {
+- buffer_info = &tpd_ring->buffer_info[tpd_next_to_use];
+- if (unlikely(buffer_info->skb))
+- BUG();
+- buffer_info->skb = NULL;
+- buffer_info->length = (lenf > ATL1_MAX_TX_BUF_LEN) ?
+- ATL1_MAX_TX_BUF_LEN : lenf;
+- lenf -= buffer_info->length;
+- buffer_info->dma = pci_map_page(adapter->pdev,
+- frag->page,
+- frag->page_offset + (i * ATL1_MAX_TX_BUF_LEN),
+- buffer_info->length, PCI_DMA_TODEVICE);
+-
+- if (++tpd_next_to_use == tpd_ring->count)
+- tpd_next_to_use = 0;
+- }
+- }
+-
+- /* last tpd's buffer-info */
+- buffer_info->skb = skb;
+-}
+-
+-static void atl1_tx_queue(struct atl1_adapter *adapter, int count,
+- union tpd_descr *descr)
+-{
+- /* We enter this function holding a spinlock. */
+- struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+- int j;
+- u32 val;
+- struct atl1_buffer *buffer_info;
+- struct tx_packet_desc *tpd;
+- u16 tpd_next_to_use = atomic_read(&tpd_ring->next_to_use);
+-
+- for (j = 0; j < count; j++) {
+- buffer_info = &tpd_ring->buffer_info[tpd_next_to_use];
+- tpd = ATL1_TPD_DESC(&adapter->tpd_ring, tpd_next_to_use);
+- tpd->desc.csum.csumpu = descr->csum.csumpu;
+- tpd->desc.csum.csumpl = descr->csum.csumpl;
+- tpd->desc.tso.tsopu = descr->tso.tsopu;
+- tpd->desc.tso.tsopl = descr->tso.tsopl;
+- tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
+- tpd->desc.data = descr->data;
+- tpd->desc.csum.csumpu |= (cpu_to_le16(buffer_info->length) &
+- CSUM_PARAM_BUFLEN_MASK) << CSUM_PARAM_BUFLEN_SHIFT;
+-
+- val = (descr->tso.tsopl >> TSO_PARAM_SEGMENT_SHIFT) &
+- TSO_PARAM_SEGMENT_MASK;
+- if (val && !j)
+- tpd->desc.tso.tsopl |= 1 << TSO_PARAM_HDRFLAG_SHIFT;
+-
+- if (j == (count - 1))
+- tpd->desc.csum.csumpl |= 1 << CSUM_PARAM_EOP_SHIFT;
+-
+- if (++tpd_next_to_use == tpd_ring->count)
+- tpd_next_to_use = 0;
+- }
+- /*
+- * Force memory writes to complete before letting h/w
+- * know there are new descriptors to fetch. (Only
+- * applicable for weak-ordered memory model archs,
+- * such as IA-64).
+- */
+- wmb();
+-
+- atomic_set(&tpd_ring->next_to_use, (int)tpd_next_to_use);
+-}
+-
+-static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+-{
+- struct atl1_adapter *adapter = netdev_priv(netdev);
+- int len = skb->len;
+- int tso;
+- int count = 1;
+- int ret_val;
+- u32 val;
+- union tpd_descr param;
+- u16 frag_size;
+- u16 vlan_tag;
+- unsigned long flags;
+- unsigned int nr_frags = 0;
+- unsigned int mss = 0;
+- unsigned int f;
+- unsigned int proto_hdr_len;
+-
+- len -= skb->data_len;
+-
+- if (unlikely(skb->len == 0)) {
+- dev_kfree_skb_any(skb);
+- return NETDEV_TX_OK;
+- }
+-
+- param.data = 0;
+- param.tso.tsopu = 0;
+- param.tso.tsopl = 0;
+- param.csum.csumpu = 0;
+- param.csum.csumpl = 0;
+-
+- /* nr_frags will be nonzero if we're doing scatter/gather (SG) */
+- nr_frags = skb_shinfo(skb)->nr_frags;
+- for (f = 0; f < nr_frags; f++) {
+- frag_size = skb_shinfo(skb)->frags[f].size;
+- if (frag_size)
+- count += (frag_size + ATL1_MAX_TX_BUF_LEN - 1) /
+- ATL1_MAX_TX_BUF_LEN;
+- }
+-
+- /* mss will be nonzero if we're doing segment offload (TSO/GSO) */
+- mss = skb_shinfo(skb)->gso_size;
+- if (mss) {
+- if (skb->protocol == htons(ETH_P_IP)) {
+- proto_hdr_len = (skb_transport_offset(skb) +
+- tcp_hdrlen(skb));
+- if (unlikely(proto_hdr_len > len)) {
+- dev_kfree_skb_any(skb);
+- return NETDEV_TX_OK;
+- }
+- /* need additional TPD ? */
+- if (proto_hdr_len != len)
+- count += (len - proto_hdr_len +
+- ATL1_MAX_TX_BUF_LEN - 1) /
+- ATL1_MAX_TX_BUF_LEN;
+- }
+- }
+-
+- if (!spin_trylock_irqsave(&adapter->lock, flags)) {
+- /* Can't get lock - tell upper layer to requeue */
+- dev_printk(KERN_DEBUG, &adapter->pdev->dev, "tx locked\n");
+- return NETDEV_TX_LOCKED;
+- }
+-
+- if (atl1_tpd_avail(&adapter->tpd_ring) < count) {
+- /* not enough descriptors */
+- netif_stop_queue(netdev);
+- spin_unlock_irqrestore(&adapter->lock, flags);
+- dev_printk(KERN_DEBUG, &adapter->pdev->dev, "tx busy\n");
+- return NETDEV_TX_BUSY;
+- }
+-
+- param.data = 0;
+-
+- if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+- vlan_tag = vlan_tx_tag_get(skb);
+- vlan_tag = (vlan_tag << 4) | (vlan_tag >> 13) |
+- ((vlan_tag >> 9) & 0x8);
+- param.csum.csumpl |= 1 << CSUM_PARAM_INSVLAG_SHIFT;
+- param.csum.csumpu |= (vlan_tag & CSUM_PARAM_VALANTAG_MASK) <<
+- CSUM_PARAM_VALAN_SHIFT;
+- }
+-
+- tso = atl1_tso(adapter, skb, ¶m.tso);
+- if (tso < 0) {
+- spin_unlock_irqrestore(&adapter->lock, flags);
+- dev_kfree_skb_any(skb);
+- return NETDEV_TX_OK;
+- }
+-
+- if (!tso) {
+- ret_val = atl1_tx_csum(adapter, skb, ¶m.csum);
+- if (ret_val < 0) {
+- spin_unlock_irqrestore(&adapter->lock, flags);
+- dev_kfree_skb_any(skb);
+- return NETDEV_TX_OK;
+- }
+- }
+-
+- val = (param.csum.csumpl >> CSUM_PARAM_SEGMENT_SHIFT) &
+- CSUM_PARAM_SEGMENT_MASK;
+- atl1_tx_map(adapter, skb, 1 == val);
+- atl1_tx_queue(adapter, count, ¶m);
+- netdev->trans_start = jiffies;
+- spin_unlock_irqrestore(&adapter->lock, flags);
+- atl1_update_mailbox(adapter);
+- return NETDEV_TX_OK;
+-}
+-
+-/*
+- * atl1_intr - Interrupt Handler
+- * @irq: interrupt number
+- * @data: pointer to a network interface device structure
+- * @pt_regs: CPU registers structure
+- */
+-static irqreturn_t atl1_intr(int irq, void *data)
+-{
+- struct atl1_adapter *adapter = netdev_priv(data);
+- u32 status;
+- int max_ints = 10;
+-
+- status = adapter->cmb.cmb->int_stats;
+- if (!status)
+- return IRQ_NONE;
+-
+- do {
+- /* clear CMB interrupt status at once */
+- adapter->cmb.cmb->int_stats = 0;
+-
+- if (status & ISR_GPHY) /* clear phy status */
+- atl1_clear_phy_int(adapter);
+-
+- /* clear ISR status, and Enable CMB DMA/Disable Interrupt */
+- iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR);
+-
+- /* check if SMB intr */
+- if (status & ISR_SMB)
+- atl1_inc_smb(adapter);
+-
+- /* check if PCIE PHY Link down */
+- if (status & ISR_PHY_LINKDOWN) {
+- dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+- "pcie phy link down %x\n", status);
+- if (netif_running(adapter->netdev)) { /* reset MAC */
+- iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+- schedule_work(&adapter->pcie_dma_to_rst_task);
+- return IRQ_HANDLED;
+- }
+- }
+-
+- /* check if DMA read/write error ? */
+- if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
+- dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+- "pcie DMA r/w error (status = 0x%x)\n",
+- status);
+- iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+- schedule_work(&adapter->pcie_dma_to_rst_task);
+- return IRQ_HANDLED;
+- }
+-
+- /* link event */
+- if (status & ISR_GPHY) {
+- adapter->soft_stats.tx_carrier_errors++;
+- atl1_check_for_link(adapter);
+- }
+-
+- /* transmit event */
+- if (status & ISR_CMB_TX)
+- atl1_intr_tx(adapter);
+-
+- /* rx exception */
+- if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN |
+- ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
+- ISR_HOST_RRD_OV | ISR_CMB_RX))) {
+- if (status & (ISR_RXF_OV | ISR_RFD_UNRUN |
+- ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
+- ISR_HOST_RRD_OV))
+- dev_printk(KERN_DEBUG, &adapter->pdev->dev,
+- "rx exception, ISR = 0x%x\n", status);
+- atl1_intr_rx(adapter);
+- }
+-
+- if (--max_ints < 0)
+- break;
+-
+- } while ((status = adapter->cmb.cmb->int_stats));
+-
+- /* re-enable Interrupt */
+- iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR);
+- return IRQ_HANDLED;
+-}
+-
+-/*
+- * atl1_watchdog - Timer Call-back
+- * @data: pointer to netdev cast into an unsigned long
+- */
+-static void atl1_watchdog(unsigned long data)
+-{
+- struct atl1_adapter *adapter = (struct atl1_adapter *)data;
+-
+- /* Reset the timer */
+- mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+-}
+-
+-/*
+- * atl1_phy_config - Timer Call-back
+- * @data: pointer to netdev cast into an unsigned long
+- */
+-static void atl1_phy_config(unsigned long data)
+-{
+- struct atl1_adapter *adapter = (struct atl1_adapter *)data;
+- struct atl1_hw *hw = &adapter->hw;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&adapter->lock, flags);
+- adapter->phy_timer_pending = false;
+- atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
+- atl1_write_phy_reg(hw, MII_AT001_CR, hw->mii_1000t_ctrl_reg);
+- atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN);
+- spin_unlock_irqrestore(&adapter->lock, flags);
+-}
+-
+-/*
+- * atl1_tx_timeout - Respond to a Tx Hang
+- * @netdev: network interface device structure
+- */
+-static void atl1_tx_timeout(struct net_device *netdev)
+-{
+- struct atl1_adapter *adapter = netdev_priv(netdev);
+- /* Do the reset outside of interrupt context */
+- schedule_work(&adapter->tx_timeout_task);
+-}
+-
+-/*
+- * Orphaned vendor comment left intact here:
+- * <vendor comment>
+- * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT
+- * will assert. We do soft reset <0x1400=1> according
+- * with the SPEC. BUT, it seemes that PCIE or DMA
+- * state-machine will not be reset. DMAR_TO_INT will
+- * assert again and again.
+- * </vendor comment>
+- */
+-static void atl1_tx_timeout_task(struct work_struct *work)
+-{
+- struct atl1_adapter *adapter =
+- container_of(work, struct atl1_adapter, tx_timeout_task);
+- struct net_device *netdev = adapter->netdev;
+-
+- netif_device_detach(netdev);
+- atl1_down(adapter);
+- atl1_up(adapter);
+- netif_device_attach(netdev);
+-}
+-
+-/*
+- * atl1_link_chg_task - deal with link change event Out of interrupt context
+- */
+-static void atl1_link_chg_task(struct work_struct *work)
+-{
+- struct atl1_adapter *adapter =
+- container_of(work, struct atl1_adapter, link_chg_task);
+- unsigned long flags;
+-
+- spin_lock_irqsave(&adapter->lock, flags);
+- atl1_check_link(adapter);
+- spin_unlock_irqrestore(&adapter->lock, flags);
+-}
+-
+-static void atl1_vlan_rx_register(struct net_device *netdev,
+- struct vlan_group *grp)
+-{
+- struct atl1_adapter *adapter = netdev_priv(netdev);
+- unsigned long flags;
+- u32 ctrl;
+-
+- spin_lock_irqsave(&adapter->lock, flags);
+- /* atl1_irq_disable(adapter); */
+- adapter->vlgrp = grp;
+-
+- if (grp) {
+- /* enable VLAN tag insert/strip */
+- ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
+- ctrl |= MAC_CTRL_RMV_VLAN;
+- iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
+- } else {
+- /* disable VLAN tag insert/strip */
+- ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
+- ctrl &= ~MAC_CTRL_RMV_VLAN;
+- iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
+- }
+-
+- /* atl1_irq_enable(adapter); */
+- spin_unlock_irqrestore(&adapter->lock, flags);
+-}
+-
+-static void atl1_restore_vlan(struct atl1_adapter *adapter)
+-{
+- atl1_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+-}
+-
+-int atl1_reset(struct atl1_adapter *adapter)
+-{
+- int ret;
+-
+- ret = atl1_reset_hw(&adapter->hw);
+- if (ret != ATL1_SUCCESS)
+- return ret;
+- return atl1_init_hw(&adapter->hw);
+-}
+-
+-s32 atl1_up(struct atl1_adapter *adapter)
+-{
+- struct net_device *netdev = adapter->netdev;
+- int err;
+- int irq_flags = IRQF_SAMPLE_RANDOM;
+-
+- /* hardware has been reset, we need to reload some things */
+- atl1_set_multi(netdev);
+- atl1_init_ring_ptrs(adapter);
+- atl1_restore_vlan(adapter);
+- err = atl1_alloc_rx_buffers(adapter);
+- if (unlikely(!err)) /* no RX BUFFER allocated */
+- return -ENOMEM;
+-
+- if (unlikely(atl1_configure(adapter))) {
+- err = -EIO;
+- goto err_up;
+- }
+-
+- err = pci_enable_msi(adapter->pdev);
+- if (err) {
+- dev_info(&adapter->pdev->dev,
+- "Unable to enable MSI: %d\n", err);
+- irq_flags |= IRQF_SHARED;
+- }
+-
+- err = request_irq(adapter->pdev->irq, &atl1_intr, irq_flags,
+- netdev->name, netdev);
+- if (unlikely(err))
+- goto err_up;
+-
+- mod_timer(&adapter->watchdog_timer, jiffies);
+- atl1_irq_enable(adapter);
+- atl1_check_link(adapter);
+- return 0;
+-
+-err_up:
+- pci_disable_msi(adapter->pdev);
+- /* free rx_buffers */
+- atl1_clean_rx_ring(adapter);
+- return err;
+-}
+-
+-void atl1_down(struct atl1_adapter *adapter)
+-{
+- struct net_device *netdev = adapter->netdev;
+-
+- del_timer_sync(&adapter->watchdog_timer);
+- del_timer_sync(&adapter->phy_config_timer);
+- adapter->phy_timer_pending = false;
+-
+- atl1_irq_disable(adapter);
+- free_irq(adapter->pdev->irq, netdev);
+- pci_disable_msi(adapter->pdev);
+- atl1_reset_hw(&adapter->hw);
+- adapter->cmb.cmb->int_stats = 0;
+-
+- adapter->link_speed = SPEED_0;
+- adapter->link_duplex = -1;
+- netif_carrier_off(netdev);
+- netif_stop_queue(netdev);
+-
+- atl1_clean_tx_ring(adapter);
+- atl1_clean_rx_ring(adapter);
+-}
+-
+-/*
+- * atl1_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 atl1_open(struct net_device *netdev)
+-{
+- struct atl1_adapter *adapter = netdev_priv(netdev);
+- int err;
+-
+- /* allocate transmit descriptors */
+- err = atl1_setup_ring_resources(adapter);
+- if (err)
+- return err;
+-
+- err = atl1_up(adapter);
+- if (err)
+- goto err_up;
+-
+- return 0;
+-
+-err_up:
+- atl1_reset(adapter);
+- return err;
+-}
+-
+-/*
+- * atl1_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 atl1_close(struct net_device *netdev)
+-{
+- struct atl1_adapter *adapter = netdev_priv(netdev);
+- atl1_down(adapter);
+- atl1_free_ring_resources(adapter);
+- return 0;
+-}
+-
+-#ifdef CONFIG_PM
+-static int atl1_suspend(struct pci_dev *pdev, pm_message_t state)
+-{
+- struct net_device *netdev = pci_get_drvdata(pdev);
+- struct atl1_adapter *adapter = netdev_priv(netdev);
+- struct atl1_hw *hw = &adapter->hw;
+- u32 ctrl = 0;
+- u32 wufc = adapter->wol;
+-
+- netif_device_detach(netdev);
+- if (netif_running(netdev))
+- atl1_down(adapter);
+-
+- atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
+- atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
+- if (ctrl & BMSR_LSTATUS)
+- wufc &= ~ATL1_WUFC_LNKC;
+-
+- /* reduce speed to 10/100M */
+- if (wufc) {
+- atl1_phy_enter_power_saving(hw);
+- /* if resume, let driver to re- setup link */
+- hw->phy_configured = false;
+- atl1_set_mac_addr(hw);
+- atl1_set_multi(netdev);
+-
+- ctrl = 0;
+- /* turn on magic packet wol */
+- if (wufc & ATL1_WUFC_MAG)
+- ctrl = WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
+-
+- /* turn on Link change WOL */
+- if (wufc & ATL1_WUFC_LNKC)
+- ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN);
+- iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL);
+-
+- /* turn on all-multi mode if wake on multicast is enabled */
+- ctrl = ioread32(hw->hw_addr + REG_MAC_CTRL);
+- ctrl &= ~MAC_CTRL_DBG;
+- ctrl &= ~MAC_CTRL_PROMIS_EN;
+- if (wufc & ATL1_WUFC_MC)
+- ctrl |= MAC_CTRL_MC_ALL_EN;
+- else
+- ctrl &= ~MAC_CTRL_MC_ALL_EN;
+-
+- /* turn on broadcast mode if wake on-BC is enabled */
+- if (wufc & ATL1_WUFC_BC)
+- ctrl |= MAC_CTRL_BC_EN;
+- else
+- ctrl &= ~MAC_CTRL_BC_EN;
+-
+- /* enable RX */
+- ctrl |= MAC_CTRL_RX_EN;
+- iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL);
+- pci_enable_wake(pdev, PCI_D3hot, 1);
+- pci_enable_wake(pdev, PCI_D3cold, 1);
+- } else {
+- iowrite32(0, hw->hw_addr + REG_WOL_CTRL);
+- pci_enable_wake(pdev, PCI_D3hot, 0);
+- pci_enable_wake(pdev, PCI_D3cold, 0);
+- }
+-
+- pci_save_state(pdev);
+- pci_disable_device(pdev);
+-
+- pci_set_power_state(pdev, PCI_D3hot);
+-
+- return 0;
+-}
+-
+-static int atl1_resume(struct pci_dev *pdev)
+-{
+- struct net_device *netdev = pci_get_drvdata(pdev);
+- struct atl1_adapter *adapter = netdev_priv(netdev);
+- u32 ret_val;
+-
+- pci_set_power_state(pdev, 0);
+- pci_restore_state(pdev);
+-
+- ret_val = pci_enable_device(pdev);
+- pci_enable_wake(pdev, PCI_D3hot, 0);
+- pci_enable_wake(pdev, PCI_D3cold, 0);
+-
+- iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL);
+- atl1_reset(adapter);
+-
+- if (netif_running(netdev))
+- atl1_up(adapter);
+- netif_device_attach(netdev);
+-
+- atl1_via_workaround(adapter);
+-
+- return 0;
+-}
+-#else
+-#define atl1_suspend NULL
+-#define atl1_resume NULL
+-#endif
+-
+-#ifdef CONFIG_NET_POLL_CONTROLLER
+-static void atl1_poll_controller(struct net_device *netdev)
+-{
+- disable_irq(netdev->irq);
+- atl1_intr(netdev->irq, netdev);
+- enable_irq(netdev->irq);
+-}
+-#endif
+-
+-/*
+- * atl1_probe - Device Initialization Routine
+- * @pdev: PCI device information struct
+- * @ent: entry in atl1_pci_tbl
+- *
+- * Returns 0 on success, negative on failure
+- *
+- * atl1_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 atl1_probe(struct pci_dev *pdev,
+- const struct pci_device_id *ent)
+-{
+- struct net_device *netdev;
+- struct atl1_adapter *adapter;
+- static int cards_found = 0;
+- int err;
+-
+- err = pci_enable_device(pdev);
+- if (err)
+- return err;
+-
+- /*
+- * The atl1 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.
+- */
+- err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+- if (err) {
+- dev_err(&pdev->dev, "no usable DMA configuration\n");
+- goto err_dma;
+- }
+- /* Mark all PCI regions associated with PCI device
+- * pdev as being reserved by owner atl1_driver_name
+- */
+- err = pci_request_regions(pdev, atl1_driver_name);
+- if (err)
+- goto err_request_regions;
+-
+- /* Enables bus-mastering on the device and calls
+- * pcibios_set_master to do the needed arch specific settings
+- */
+- pci_set_master(pdev);
+-
+- netdev = alloc_etherdev(sizeof(struct atl1_adapter));
+- if (!netdev) {
+- err = -ENOMEM;
+- goto err_alloc_etherdev;
+- }
+- SET_NETDEV_DEV(netdev, &pdev->dev);
+-
+- pci_set_drvdata(pdev, netdev);
+- adapter = netdev_priv(netdev);
+- adapter->netdev = netdev;
+- adapter->pdev = pdev;
+- adapter->hw.back = adapter;
+-
+- adapter->hw.hw_addr = pci_iomap(pdev, 0, 0);
+- if (!adapter->hw.hw_addr) {
+- err = -EIO;
+- goto err_pci_iomap;
+- }
+- /* get device revision number */
+- adapter->hw.dev_rev = ioread16(adapter->hw.hw_addr +
+- (REG_MASTER_CTRL + 2));
+- dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
+-
+- /* set default ring resource counts */
+- adapter->rfd_ring.count = adapter->rrd_ring.count = ATL1_DEFAULT_RFD;
+- adapter->tpd_ring.count = ATL1_DEFAULT_TPD;
+-
+- adapter->mii.dev = netdev;
+- adapter->mii.mdio_read = mdio_read;
+- adapter->mii.mdio_write = mdio_write;
+- adapter->mii.phy_id_mask = 0x1f;
+- adapter->mii.reg_num_mask = 0x1f;
+-
+- netdev->open = &atl1_open;
+- netdev->stop = &atl1_close;
+- netdev->hard_start_xmit = &atl1_xmit_frame;
+- netdev->get_stats = &atl1_get_stats;
+- netdev->set_multicast_list = &atl1_set_multi;
+- netdev->set_mac_address = &atl1_set_mac;
+- netdev->change_mtu = &atl1_change_mtu;
+- netdev->do_ioctl = &atl1_ioctl;
+- netdev->tx_timeout = &atl1_tx_timeout;
+- netdev->watchdog_timeo = 5 * HZ;
+-#ifdef CONFIG_NET_POLL_CONTROLLER
+- netdev->poll_controller = atl1_poll_controller;
+-#endif
+- netdev->vlan_rx_register = atl1_vlan_rx_register;
+-
+- netdev->ethtool_ops = &atl1_ethtool_ops;
+- adapter->bd_number = cards_found;
+-
+- /* setup the private structure */
+- err = atl1_sw_init(adapter);
+- if (err)
+- goto err_common;
+-
+- netdev->features = NETIF_F_HW_CSUM;
+- netdev->features |= NETIF_F_SG;
+- netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
+-
+- /*
+- * FIXME - Until tso performance gets fixed, disable the feature.
+- * Enable it with ethtool -K if desired.
+- */
+- /* netdev->features |= NETIF_F_TSO; */
+-
+- netdev->features |= NETIF_F_LLTX;
+-
+- /*
+- * patch for some L1 of old version,
+- * the final version of L1 may not need these
+- * patches
+- */
+- /* atl1_pcie_patch(adapter); */
+-
+- /* really reset GPHY core */
+- iowrite16(0, adapter->hw.hw_addr + REG_GPHY_ENABLE);
+-
+- /*
+- * reset the controller to
+- * put the device in a known good starting state
+- */
+- if (atl1_reset_hw(&adapter->hw)) {
+- err = -EIO;
+- goto err_common;
+- }
+-
+- /* copy the MAC address out of the EEPROM */
+- atl1_read_mac_addr(&adapter->hw);
+- memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
+-
+- if (!is_valid_ether_addr(netdev->dev_addr)) {
+- err = -EIO;
+- goto err_common;
+- }
+-
+- atl1_check_options(adapter);
+-
+- /* pre-init the MAC, and setup link */
+- err = atl1_init_hw(&adapter->hw);
+- if (err) {
+- err = -EIO;
+- goto err_common;
+- }
+-
+- atl1_pcie_patch(adapter);
+- /* assume we have no link for now */
+- netif_carrier_off(netdev);
+- netif_stop_queue(netdev);
+-
+- init_timer(&adapter->watchdog_timer);
+- adapter->watchdog_timer.function = &atl1_watchdog;
+- adapter->watchdog_timer.data = (unsigned long)adapter;
+-
+- init_timer(&adapter->phy_config_timer);
+- adapter->phy_config_timer.function = &atl1_phy_config;
+- adapter->phy_config_timer.data = (unsigned long)adapter;
+- adapter->phy_timer_pending = false;
+-
+- INIT_WORK(&adapter->tx_timeout_task, atl1_tx_timeout_task);
+-
+- INIT_WORK(&adapter->link_chg_task, atl1_link_chg_task);
+-
+- INIT_WORK(&adapter->pcie_dma_to_rst_task, atl1_tx_timeout_task);
+-
+- err = register_netdev(netdev);
+- if (err)
+- goto err_common;
+-
+- cards_found++;
+- atl1_via_workaround(adapter);
+- return 0;
+-
+-err_common:
+- pci_iounmap(pdev, adapter->hw.hw_addr);
+-err_pci_iomap:
+- free_netdev(netdev);
+-err_alloc_etherdev:
+- pci_release_regions(pdev);
+-err_dma:
+-err_request_regions:
+- pci_disable_device(pdev);
+- return err;
+-}
+-
+-/*
+- * atl1_remove - Device Removal Routine
+- * @pdev: PCI device information struct
+- *
+- * atl1_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 atl1_remove(struct pci_dev *pdev)
+-{
+- struct net_device *netdev = pci_get_drvdata(pdev);
+- struct atl1_adapter *adapter;
+- /* Device not available. Return. */
+- if (!netdev)
+- return;
+-
+- adapter = netdev_priv(netdev);
+-
+- /* Some atl1 boards lack persistent storage for their MAC, and get it
+- * from the BIOS during POST. If we've been messing with the MAC
+- * address, we need to save the permanent one.
+- */
+- if (memcmp(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN)) {
+- memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr,
+- ETH_ALEN);
+- atl1_set_mac_addr(&adapter->hw);
+- }
+-
+- iowrite16(0, adapter->hw.hw_addr + REG_GPHY_ENABLE);
+- unregister_netdev(netdev);
+- pci_iounmap(pdev, adapter->hw.hw_addr);
+- pci_release_regions(pdev);
+- free_netdev(netdev);
+- pci_disable_device(pdev);
+-}
+-
+-static struct pci_driver atl1_driver = {
+- .name = atl1_driver_name,
+- .id_table = atl1_pci_tbl,
+- .probe = atl1_probe,
+- .remove = __devexit_p(atl1_remove),
+- .suspend = atl1_suspend,
+- .resume = atl1_resume
+-};
+-
+-/*
+- * atl1_exit_module - Driver Exit Cleanup Routine
+- *
+- * atl1_exit_module is called just before the driver is removed
+- * from memory.
+- */
+-static void __exit atl1_exit_module(void)
+-{
+- pci_unregister_driver(&atl1_driver);
+-}
+-
+-/*
+- * atl1_init_module - Driver Registration Routine
+- *
+- * atl1_init_module is the first routine called when the driver is
+- * loaded. All it does is register with the PCI subsystem.
+- */
+-static int __init atl1_init_module(void)
+-{
+- return pci_register_driver(&atl1_driver);
+-}
+-
+-module_init(atl1_init_module);
+-module_exit(atl1_exit_module);
+diff --git a/drivers/net/atl1/atl1_param.c b/drivers/net/atl1/atl1_param.c
+deleted file mode 100644
+index 4246bb9..0000000
+--- a/drivers/net/atl1/atl1_param.c
++++ /dev/null
+@@ -1,203 +0,0 @@
+-/*
+- * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+- * Copyright(c) 2006 Chris Snook <csnook at redhat.com>
+- * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
+- *
+- * 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/types.h>
+-#include <linux/moduleparam.h>
+-#include <linux/pci.h>
+-#include "atl1.h"
+-
+-/*
+- * This is the only thing that needs to be changed to adjust the
+- * maximum number of ports that the driver can manage.
+- */
+-#define ATL1_MAX_NIC 4
+-
+-#define OPTION_UNSET -1
+-#define OPTION_DISABLED 0
+-#define OPTION_ENABLED 1
+-
+-#define ATL1_PARAM_INIT { [0 ... ATL1_MAX_NIC] = OPTION_UNSET }
+-
+-/*
+- * Interrupt Moderate Timer in units of 2 us
+- *
+- * Valid Range: 10-65535
+- *
+- * Default Value: 100 (200us)
+- */
+-static int __devinitdata int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
+-static int num_int_mod_timer = 0;
+-module_param_array_named(int_mod_timer, int_mod_timer, int, &num_int_mod_timer, 0);
+-MODULE_PARM_DESC(int_mod_timer, "Interrupt moderator timer");
+-
+-/*
+- * flash_vendor
+- *
+- * Valid Range: 0-2
+- *
+- * 0 - Atmel
+- * 1 - SST
+- * 2 - ST
+- *
+- * Default Value: 0
+- */
+-static int __devinitdata flash_vendor[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
+-static int num_flash_vendor = 0;
+-module_param_array_named(flash_vendor, flash_vendor, int, &num_flash_vendor, 0);
+-MODULE_PARM_DESC(flash_vendor, "SPI flash vendor");
+-
+-#define DEFAULT_INT_MOD_CNT 100 /* 200us */
+-#define MAX_INT_MOD_CNT 65000
+-#define MIN_INT_MOD_CNT 50
+-
+-#define FLASH_VENDOR_DEFAULT 0
+-#define FLASH_VENDOR_MIN 0
+-#define FLASH_VENDOR_MAX 2
+-
+-struct atl1_option {
+- enum { enable_option, range_option, list_option } type;
+- char *name;
+- char *err;
+- int def;
+- union {
+- struct { /* range_option info */
+- int min;
+- int max;
+- } r;
+- struct { /* list_option info */
+- int nr;
+- struct atl1_opt_list {
+- int i;
+- char *str;
+- } *p;
+- } l;
+- } arg;
+-};
+-
+-static int __devinit atl1_validate_option(int *value, struct atl1_option *opt, struct pci_dev *pdev)
+-{
+- if (*value == OPTION_UNSET) {
+- *value = opt->def;
+- return 0;
+- }
+-
+- switch (opt->type) {
+- case enable_option:
+- switch (*value) {
+- case OPTION_ENABLED:
+- dev_info(&pdev->dev, "%s enabled\n", opt->name);
+- return 0;
+- case OPTION_DISABLED:
+- dev_info(&pdev->dev, "%s disabled\n", opt->name);
+- return 0;
+- }
+- break;
+- case range_option:
+- if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
+- dev_info(&pdev->dev, "%s set to %i\n", opt->name,
+- *value);
+- return 0;
+- }
+- break;
+- case list_option:{
+- int i;
+- struct atl1_opt_list *ent;
+-
+- for (i = 0; i < opt->arg.l.nr; i++) {
+- ent = &opt->arg.l.p[i];
+- if (*value == ent->i) {
+- if (ent->str[0] != '\0')
+- dev_info(&pdev->dev, "%s\n",
+- ent->str);
+- return 0;
+- }
+- }
+- }
+- break;
+-
+- default:
+- break;
+- }
+-
+- dev_info(&pdev->dev, "invalid %s specified (%i) %s\n",
+- opt->name, *value, opt->err);
+- *value = opt->def;
+- return -1;
+-}
+-
+-/*
+- * atl1_check_options - Range Checking for Command Line Parameters
+- * @adapter: board private structure
+- *
+- * This routine checks all command line parameters for valid user
+- * input. If an invalid value is given, or if no user specified
+- * value exists, a default value is used. The final value is stored
+- * in a variable in the adapter structure.
+- */
+-void __devinit atl1_check_options(struct atl1_adapter *adapter)
+-{
+- struct pci_dev *pdev = adapter->pdev;
+- int bd = adapter->bd_number;
+- if (bd >= ATL1_MAX_NIC) {
+- dev_notice(&pdev->dev, "no configuration for board#%i\n", bd);
+- dev_notice(&pdev->dev, "using defaults for all values\n");
+- }
+- { /* Interrupt Moderate Timer */
+- struct atl1_option opt = {
+- .type = range_option,
+- .name = "Interrupt Moderator Timer",
+- .err = "using default of "
+- __MODULE_STRING(DEFAULT_INT_MOD_CNT),
+- .def = DEFAULT_INT_MOD_CNT,
+- .arg = {.r =
+- {.min = MIN_INT_MOD_CNT,.max = MAX_INT_MOD_CNT}}
+- };
+- int val;
+- if (num_int_mod_timer > bd) {
+- val = int_mod_timer[bd];
+- atl1_validate_option(&val, &opt, pdev);
+- adapter->imt = (u16) val;
+- } else
+- adapter->imt = (u16) (opt.def);
+- }
+-
+- { /* Flash Vendor */
+- struct atl1_option opt = {
+- .type = range_option,
+- .name = "SPI Flash Vendor",
+- .err = "using default of "
+- __MODULE_STRING(FLASH_VENDOR_DEFAULT),
+- .def = DEFAULT_INT_MOD_CNT,
+- .arg = {.r =
+- {.min = FLASH_VENDOR_MIN,.max =
+- FLASH_VENDOR_MAX}}
+- };
+- int val;
+- if (num_flash_vendor > bd) {
+- val = flash_vendor[bd];
+- atl1_validate_option(&val, &opt, pdev);
+- adapter->hw.flash_vendor = (u8) val;
+- } else
+- adapter->hw.flash_vendor = (u8) (opt.def);
+- }
+-}
+diff --git a/drivers/net/atlx/Makefile b/drivers/net/atlx/Makefile
+new file mode 100644
+index 0000000..ca45553
+--- /dev/null
++++ b/drivers/net/atlx/Makefile
+@@ -0,0 +1 @@
++obj-$(CONFIG_ATL1) += atl1.o
+diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c
+new file mode 100644
+index 0000000..0afe522
+--- /dev/null
++++ b/drivers/net/atlx/atl1.c
+@@ -0,0 +1,3702 @@
++/*
++ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
++ * Copyright(c) 2006 - 2007 Chris Snook <csnook at redhat.com>
++ * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
++ *
++ * 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.
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called COPYING.
++ *
++ * Contact Information:
++ * Xiong Huang <xiong_huang at attansic.com>
++ * Attansic Technology Corp. 3F 147, Xianzheng 9th Road, Zhubei,
++ * Xinzhu 302, TAIWAN, REPUBLIC OF CHINA
++ *
++ * Chris Snook <csnook at redhat.com>
++ * Jay Cliburn <jcliburn at gmail.com>
++ *
++ * This version is adapted from the Attansic reference driver for
++ * inclusion in the Linux kernel. It is currently under heavy development.
++ * A very incomplete list of things that need to be dealt with:
++ *
++ * TODO:
++ * Wake on LAN.
++ * Add more ethtool functions.
++ * Fix abstruse irq enable/disable condition described here:
++ * http://marc.theaimsgroup.com/?l=linux-netdev&m=116398508500553&w=2
++ *
++ * NEEDS TESTING:
++ * VLAN
++ * multicast
++ * promiscuous mode
++ * interrupt coalescing
++ * SMP torture testing
++ */
++
++#include <asm/atomic.h>
++#include <asm/byteorder.h>
++
++#include <linux/compiler.h>
++#include <linux/crc32.h>
++#include <linux/delay.h>
++#include <linux/dma-mapping.h>
++#include <linux/etherdevice.h>
++#include <linux/hardirq.h>
++#include <linux/if_ether.h>
++#include <linux/if_vlan.h>
++#include <linux/in.h>
++#include <linux/interrupt.h>
++#include <linux/ip.h>
++#include <linux/irqflags.h>
++#include <linux/irqreturn.h>
++#include <linux/jiffies.h>
++#include <linux/mii.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/net.h>
++#include <linux/netdevice.h>
++#include <linux/pci.h>
++#include <linux/pci_ids.h>
++#include <linux/pm.h>
++#include <linux/skbuff.h>
++#include <linux/slab.h>
++#include <linux/spinlock.h>
++#include <linux/string.h>
++#include <linux/tcp.h>
++#include <linux/timer.h>
++#include <linux/types.h>
++#include <linux/workqueue.h>
++
++#include <net/checksum.h>
++
++#include "atl1.h"
++
++/* Temporary hack for merging atl1 and atl2 */
++#include "atlx.c"
++
++/*
++ * This is the only thing that needs to be changed to adjust the
++ * maximum number of ports that the driver can manage.
++ */
++#define ATL1_MAX_NIC 4
++
++#define OPTION_UNSET -1
++#define OPTION_DISABLED 0
++#define OPTION_ENABLED 1
++
++#define ATL1_PARAM_INIT { [0 ... ATL1_MAX_NIC] = OPTION_UNSET }
++
++/*
++ * Interrupt Moderate Timer in units of 2 us
++ *
++ * Valid Range: 10-65535
++ *
++ * Default Value: 100 (200us)
++ */
++static int __devinitdata int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
++static int num_int_mod_timer;
++module_param_array_named(int_mod_timer, int_mod_timer, int,
++ &num_int_mod_timer, 0);
++MODULE_PARM_DESC(int_mod_timer, "Interrupt moderator timer");
++
++#define DEFAULT_INT_MOD_CNT 100 /* 200us */
++#define MAX_INT_MOD_CNT 65000
++#define MIN_INT_MOD_CNT 50
++
++struct atl1_option {
++ enum { enable_option, range_option, list_option } type;
++ char *name;
++ char *err;
++ int def;
++ union {
++ struct { /* range_option info */
++ int min;
++ int max;
++ } r;
++ struct { /* list_option info */
++ int nr;
++ struct atl1_opt_list {
++ int i;
++ char *str;
++ } *p;
++ } l;
++ } arg;
++};
++
++static int __devinit atl1_validate_option(int *value, struct atl1_option *opt,
++ struct pci_dev *pdev)
++{
++ if (*value == OPTION_UNSET) {
++ *value = opt->def;
++ return 0;
++ }
++
++ switch (opt->type) {
++ case enable_option:
++ switch (*value) {
++ case OPTION_ENABLED:
++ dev_info(&pdev->dev, "%s enabled\n", opt->name);
++ return 0;
++ case OPTION_DISABLED:
++ dev_info(&pdev->dev, "%s disabled\n", opt->name);
++ return 0;
++ }
++ break;
++ case range_option:
++ if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
++ dev_info(&pdev->dev, "%s set to %i\n", opt->name,
++ *value);
++ return 0;
++ }
++ break;
++ case list_option:{
++ int i;
++ struct atl1_opt_list *ent;
++
++ for (i = 0; i < opt->arg.l.nr; i++) {
++ ent = &opt->arg.l.p[i];
++ if (*value == ent->i) {
++ if (ent->str[0] != '\0')
++ dev_info(&pdev->dev, "%s\n",
++ ent->str);
++ return 0;
++ }
++ }
++ }
++ break;
++
++ default:
++ break;
++ }
++
++ dev_info(&pdev->dev, "invalid %s specified (%i) %s\n",
++ opt->name, *value, opt->err);
++ *value = opt->def;
++ return -1;
++}
++
++/*
++ * atl1_check_options - Range Checking for Command Line Parameters
++ * @adapter: board private structure
++ *
++ * This routine checks all command line parameters for valid user
++ * input. If an invalid value is given, or if no user specified
++ * value exists, a default value is used. The final value is stored
++ * in a variable in the adapter structure.
++ */
++void __devinit atl1_check_options(struct atl1_adapter *adapter)
++{
++ struct pci_dev *pdev = adapter->pdev;
++ int bd = adapter->bd_number;
++ if (bd >= ATL1_MAX_NIC) {
++ dev_notice(&pdev->dev, "no configuration for board#%i\n", bd);
++ dev_notice(&pdev->dev, "using defaults for all values\n");
++ }
++ { /* Interrupt Moderate Timer */
++ struct atl1_option opt = {
++ .type = range_option,
++ .name = "Interrupt Moderator Timer",
++ .err = "using default of "
++ __MODULE_STRING(DEFAULT_INT_MOD_CNT),
++ .def = DEFAULT_INT_MOD_CNT,
++ .arg = {.r = {.min = MIN_INT_MOD_CNT,
++ .max = MAX_INT_MOD_CNT} }
++ };
++ int val;
++ if (num_int_mod_timer > bd) {
++ val = int_mod_timer[bd];
++ atl1_validate_option(&val, &opt, pdev);
++ adapter->imt = (u16) val;
++ } else
++ adapter->imt = (u16) (opt.def);
++ }
++}
++
++/*
++ * atl1_pci_tbl - PCI Device ID Table
++ */
++static const struct pci_device_id atl1_pci_tbl[] = {
++ {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1)},
++ /* required last entry */
++ {0,}
++};
++MODULE_DEVICE_TABLE(pci, atl1_pci_tbl);
++
++static const u32 atl1_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
++ NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP;
++
++static int debug = -1;
++module_param(debug, int, 0);
++MODULE_PARM_DESC(debug, "Message level (0=none,...,16=all)");
++
++/*
++ * 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 s32 atl1_reset_hw(struct atl1_hw *hw)
++{
++ struct pci_dev *pdev = hw->back->pdev;
++ struct atl1_adapter *adapter = hw->back;
++ u32 icr;
++ int i;
++
++ /*
++ * Clear Interrupt mask to stop board from generating
++ * interrupts & Clear any pending interrupt events
++ */
++ /*
++ * iowrite32(0, hw->hw_addr + REG_IMR);
++ * iowrite32(0xffffffff, hw->hw_addr + REG_ISR);
++ */
++
++ /*
++ * 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.
++ */
++ iowrite32(MASTER_CTRL_SOFT_RST, hw->hw_addr + REG_MASTER_CTRL);
++ ioread32(hw->hw_addr + REG_MASTER_CTRL);
++
++ iowrite16(1, hw->hw_addr + REG_PHY_ENABLE);
++ ioread16(hw->hw_addr + REG_PHY_ENABLE);
++
++ /* delay about 1ms */
++ msleep(1);
++
++ /* Wait at least 10ms for All module to be Idle */
++ for (i = 0; i < 10; i++) {
++ icr = ioread32(hw->hw_addr + REG_IDLE_STATUS);
++ if (!icr)
++ break;
++ /* delay 1 ms */
++ msleep(1);
++ /* FIXME: still the right way to do this? */
++ cpu_relax();
++ }
++
++ if (icr) {
++ if (netif_msg_hw(adapter))
++ dev_dbg(&pdev->dev, "ICR = 0x%x\n", icr);
++ return icr;
++ }
++
++ return 0;
++}
++
++/* function about EEPROM
++ *
++ * check_eeprom_exist
++ * return 0 if eeprom exist
++ */
++static int atl1_check_eeprom_exist(struct atl1_hw *hw)
++{
++ u32 value;
++ value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
++ if (value & SPI_FLASH_CTRL_EN_VPD) {
++ value &= ~SPI_FLASH_CTRL_EN_VPD;
++ iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
++ }
++
++ value = ioread16(hw->hw_addr + REG_PCIE_CAP_LIST);
++ return ((value & 0xFF00) == 0x6C00) ? 0 : 1;
++}
++
++static bool atl1_read_eeprom(struct atl1_hw *hw, u32 offset, u32 *p_value)
++{
++ int i;
++ u32 control;
++
++ if (offset & 3)
++ /* address do not align */
++ return false;
++
++ iowrite32(0, hw->hw_addr + REG_VPD_DATA);
++ control = (offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT;
++ iowrite32(control, hw->hw_addr + REG_VPD_CAP);
++ ioread32(hw->hw_addr + REG_VPD_CAP);
++
++ for (i = 0; i < 10; i++) {
++ msleep(2);
++ control = ioread32(hw->hw_addr + REG_VPD_CAP);
++ if (control & VPD_CAP_VPD_FLAG)
++ break;
++ }
++ if (control & VPD_CAP_VPD_FLAG) {
++ *p_value = ioread32(hw->hw_addr + REG_VPD_DATA);
++ return true;
++ }
++ /* timeout */
++ return false;
++}
++
++/*
++ * Reads the value from a PHY register
++ * hw - Struct containing variables accessed by shared code
++ * reg_addr - address of the PHY register to read
++ */
++s32 atl1_read_phy_reg(struct atl1_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;
++ iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
++ ioread32(hw->hw_addr + REG_MDIO_CTRL);
++
++ for (i = 0; i < MDIO_WAIT_TIMES; i++) {
++ udelay(2);
++ val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
++ if (!(val & (MDIO_START | MDIO_BUSY)))
++ break;
++ }
++ if (!(val & (MDIO_START | MDIO_BUSY))) {
++ *phy_data = (u16) val;
++ return 0;
++ }
++ return ATLX_ERR_PHY;
++}
++
++#define CUSTOM_SPI_CS_SETUP 2
++#define CUSTOM_SPI_CLK_HI 2
++#define CUSTOM_SPI_CLK_LO 2
++#define CUSTOM_SPI_CS_HOLD 2
++#define CUSTOM_SPI_CS_HI 3
++
++static bool atl1_spi_read(struct atl1_hw *hw, u32 addr, u32 *buf)
++{
++ int i;
++ u32 value;
++
++ iowrite32(0, hw->hw_addr + REG_SPI_DATA);
++ iowrite32(addr, hw->hw_addr + REG_SPI_ADDR);
++
++ value = SPI_FLASH_CTRL_WAIT_READY |
++ (CUSTOM_SPI_CS_SETUP & SPI_FLASH_CTRL_CS_SETUP_MASK) <<
++ SPI_FLASH_CTRL_CS_SETUP_SHIFT | (CUSTOM_SPI_CLK_HI &
++ SPI_FLASH_CTRL_CLK_HI_MASK) <<
++ SPI_FLASH_CTRL_CLK_HI_SHIFT | (CUSTOM_SPI_CLK_LO &
++ SPI_FLASH_CTRL_CLK_LO_MASK) <<
++ SPI_FLASH_CTRL_CLK_LO_SHIFT | (CUSTOM_SPI_CS_HOLD &
++ SPI_FLASH_CTRL_CS_HOLD_MASK) <<
++ SPI_FLASH_CTRL_CS_HOLD_SHIFT | (CUSTOM_SPI_CS_HI &
++ SPI_FLASH_CTRL_CS_HI_MASK) <<
++ SPI_FLASH_CTRL_CS_HI_SHIFT | (1 & SPI_FLASH_CTRL_INS_MASK) <<
++ SPI_FLASH_CTRL_INS_SHIFT;
++
++ iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
++
++ value |= SPI_FLASH_CTRL_START;
++ iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
++ ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
++
++ for (i = 0; i < 10; i++) {
++ msleep(1);
++ value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
++ if (!(value & SPI_FLASH_CTRL_START))
++ break;
++ }
++
++ if (value & SPI_FLASH_CTRL_START)
++ return false;
++
++ *buf = ioread32(hw->hw_addr + REG_SPI_DATA);
++
++ return true;
++}
++
++/*
++ * get_permanent_address
++ * return 0 if get valid mac address,
++ */
++static int atl1_get_permanent_address(struct atl1_hw *hw)
++{
++ u32 addr[2];
++ u32 i, control;
++ u16 reg;
++ u8 eth_addr[ETH_ALEN];
++ bool key_valid;
++
++ if (is_valid_ether_addr(hw->perm_mac_addr))
++ return 0;
++
++ /* init */
++ addr[0] = addr[1] = 0;
++
++ if (!atl1_check_eeprom_exist(hw)) {
++ reg = 0;
++ key_valid = false;
++ /* Read out all EEPROM content */
++ i = 0;
++ while (1) {
++ if (atl1_read_eeprom(hw, i + 0x100, &control)) {
++ if (key_valid) {
++ if (reg == REG_MAC_STA_ADDR)
++ addr[0] = control;
++ else if (reg == (REG_MAC_STA_ADDR + 4))
++ addr[1] = control;
++ key_valid = false;
++ } else if ((control & 0xff) == 0x5A) {
++ key_valid = true;
++ reg = (u16) (control >> 16);
++ } else
++ break;
++ } else
++ /* read error */
++ break;
++ i += 4;
++ }
++
++ *(u32 *) ð_addr[2] = swab32(addr[0]);
++ *(u16 *) ð_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;
++ }
++
++ /* see if SPI FLAGS exist ? */
++ addr[0] = addr[1] = 0;
++ reg = 0;
++ key_valid = false;
++ i = 0;
++ while (1) {
++ if (atl1_spi_read(hw, i + 0x1f000, &control)) {
++ if (key_valid) {
++ if (reg == REG_MAC_STA_ADDR)
++ addr[0] = control;
++ else if (reg == (REG_MAC_STA_ADDR + 4))
++ addr[1] = control;
++ key_valid = false;
++ } else if ((control & 0xff) == 0x5A) {
++ key_valid = true;
++ reg = (u16) (control >> 16);
++ } else
++ /* data end */
++ break;
++ } else
++ /* read error */
++ break;
++ i += 4;
++ }
++
++ *(u32 *) ð_addr[2] = swab32(addr[0]);
++ *(u16 *) ð_addr[0] = swab16(*(u16 *) &addr[1]);
++ if (is_valid_ether_addr(eth_addr)) {
++ memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
++ return 0;
++ }
++
++ /*
++ * On some motherboards, the MAC address is written by the
++ * BIOS directly to the MAC register during POST, and is
++ * not stored in eeprom. If all else thus far has failed
++ * to fetch the permanent MAC address, try reading it directly.
++ */
++ addr[0] = ioread32(hw->hw_addr + REG_MAC_STA_ADDR);
++ addr[1] = ioread16(hw->hw_addr + (REG_MAC_STA_ADDR + 4));
++ *(u32 *) ð_addr[2] = swab32(addr[0]);
++ *(u16 *) ð_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;
++}
++
++/*
++ * Reads the adapter's MAC address from the EEPROM
++ * hw - Struct containing variables accessed by shared code
++ */
++s32 atl1_read_mac_addr(struct atl1_hw *hw)
++{
++ u16 i;
++
++ if (atl1_get_permanent_address(hw))
++ random_ether_addr(hw->perm_mac_addr);
++
++ for (i = 0; i < ETH_ALEN; i++)
++ hw->mac_addr[i] = hw->perm_mac_addr[i];
++ return 0;
++}
++
++/*
++ * Hashes an address to determine its location in the multicast table
++ * hw - Struct containing variables accessed by shared code
++ * mc_addr - the multicast address to hash
++ *
++ * atl1_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 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr)
++{
++ u32 crc32, 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 atl1_hash_set(struct atl1_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 7 bits 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 = ioread32((hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
++ mta |= (1 << hash_bit);
++ iowrite32(mta, (hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
++}
++
++/*
++ * 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
++ */
++static s32 atl1_write_phy_reg(struct atl1_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;
++ iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
++ ioread32(hw->hw_addr + REG_MDIO_CTRL);
++
++ for (i = 0; i < MDIO_WAIT_TIMES; i++) {
++ udelay(2);
++ val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
++ if (!(val & (MDIO_START | MDIO_BUSY)))
++ break;
++ }
++
++ if (!(val & (MDIO_START | MDIO_BUSY)))
++ return 0;
++
++ return ATLX_ERR_PHY;
++}
++
++/*
++ * Make L001's PHY out of Power Saving State (bug)
++ * hw - Struct containing variables accessed by shared code
++ * when power on, L001's PHY always on Power saving State
++ * (Gigabit Link forbidden)
++ */
++static s32 atl1_phy_leave_power_saving(struct atl1_hw *hw)
++{
++ s32 ret;
++ ret = atl1_write_phy_reg(hw, 29, 0x0029);
++ if (ret)
++ return ret;
++ return atl1_write_phy_reg(hw, 30, 0);
++}
++
++/*
++ *TODO: do something or get rid of this
++ */
++#ifdef CONFIG_PM
++static s32 atl1_phy_enter_power_saving(struct atl1_hw *hw)
++{
++/* s32 ret_val;
++ * u16 phy_data;
++ */
++
++/*
++ ret_val = atl1_write_phy_reg(hw, ...);
++ ret_val = atl1_write_phy_reg(hw, ...);
++ ....
++*/
++ return 0;
++}
++#endif
++
++/*
++ * Resets the PHY and make all config validate
++ * hw - Struct containing variables accessed by shared code
++ *
++ * Sets bit 15 and 12 of the MII Control regiser (for F001 bug)
++ */
++static s32 atl1_phy_reset(struct atl1_hw *hw)
++{
++ struct pci_dev *pdev = hw->back->pdev;
++ struct atl1_adapter *adapter = hw->back;
++ s32 ret_val;
++ u16 phy_data;
++
++ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
++ hw->media_type == MEDIA_TYPE_1000M_FULL)
++ phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
++ else {
++ switch (hw->media_type) {
++ case MEDIA_TYPE_100M_FULL:
++ phy_data =
++ MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
++ MII_CR_RESET;
++ break;
++ case MEDIA_TYPE_100M_HALF:
++ phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
++ break;
++ case MEDIA_TYPE_10M_FULL:
++ phy_data =
++ MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
++ break;
++ default:
++ /* MEDIA_TYPE_10M_HALF: */
++ phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
++ break;
++ }
++ }
++
++ ret_val = atl1_write_phy_reg(hw, MII_BMCR, phy_data);
++ if (ret_val) {
++ u32 val;
++ int i;
++ /* pcie serdes link may be down! */
++ if (netif_msg_hw(adapter))
++ dev_dbg(&pdev->dev, "pcie phy link down\n");
++
++ for (i = 0; i < 25; i++) {
++ msleep(1);
++ val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
++ if (!(val & (MDIO_START | MDIO_BUSY)))
++ break;
++ }
++
++ if ((val & (MDIO_START | MDIO_BUSY)) != 0) {
++ if (netif_msg_hw(adapter))
++ dev_warn(&pdev->dev,
++ "pcie link down at least 25ms\n");
++ return ret_val;
++ }
++ }
++ return 0;
++}
++
++/*
++ * Configures PHY autoneg and flow control advertisement settings
++ * hw - Struct containing variables accessed by shared code
++ */
++static s32 atl1_phy_setup_autoneg_adv(struct atl1_hw *hw)
++{
++ s32 ret_val;
++ s16 mii_autoneg_adv_reg;
++ s16 mii_1000t_ctrl_reg;
++
++ /* Read the MII Auto-Neg Advertisement Register (Address 4). */
++ mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;
++
++ /* Read the MII 1000Base-T Control Register (Address 9). */
++ mii_1000t_ctrl_reg = MII_ATLX_CR_1000T_DEFAULT_CAP_MASK;
++
++ /*
++ * First we clear all the 10/100 mb speed bits in the Auto-Neg
++ * Advertisement Register (Address 4) and the 1000 mb speed bits in
++ * the 1000Base-T Control Register (Address 9).
++ */
++ mii_autoneg_adv_reg &= ~MII_AR_SPEED_MASK;
++ mii_1000t_ctrl_reg &= ~MII_ATLX_CR_1000T_SPEED_MASK;
++
++ /*
++ * Need to parse media_type and set up
++ * the appropriate PHY registers.
++ */
++ switch (hw->media_type) {
++ case MEDIA_TYPE_AUTO_SENSOR:
++ mii_autoneg_adv_reg |= (MII_AR_10T_HD_CAPS |
++ MII_AR_10T_FD_CAPS |
++ MII_AR_100TX_HD_CAPS |
++ MII_AR_100TX_FD_CAPS);
++ mii_1000t_ctrl_reg |= MII_ATLX_CR_1000T_FD_CAPS;
++ break;
++
++ case MEDIA_TYPE_1000M_FULL:
++ mii_1000t_ctrl_reg |= MII_ATLX_CR_1000T_FD_CAPS;
++ break;
++
++ case MEDIA_TYPE_100M_FULL:
++ mii_autoneg_adv_reg |= MII_AR_100TX_FD_CAPS;
++ break;
++
++ case MEDIA_TYPE_100M_HALF:
++ mii_autoneg_adv_reg |= MII_AR_100TX_HD_CAPS;
++ break;
++
++ case MEDIA_TYPE_10M_FULL:
++ mii_autoneg_adv_reg |= MII_AR_10T_FD_CAPS;
++ break;
++
++ default:
++ mii_autoneg_adv_reg |= MII_AR_10T_HD_CAPS;
++ break;
++ }
++
++ /* flow control fixed to enable all */
++ mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE);
++
++ hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;
++ hw->mii_1000t_ctrl_reg = mii_1000t_ctrl_reg;
++
++ ret_val = atl1_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);
++ if (ret_val)
++ return ret_val;
++
++ ret_val = atl1_write_phy_reg(hw, MII_ATLX_CR, mii_1000t_ctrl_reg);
++ if (ret_val)
++ return ret_val;
++
++ return 0;
++}
++
++/*
++ * Configures link settings.
++ * hw - Struct containing variables accessed by shared code
++ * Assumes the hardware has previously been reset and the
++ * transmitter and receiver are not enabled.
++ */
++static s32 atl1_setup_link(struct atl1_hw *hw)
++{
++ struct pci_dev *pdev = hw->back->pdev;
++ struct atl1_adapter *adapter = hw->back;
++ s32 ret_val;
++
++ /*
++ * Options:
++ * PHY will advertise value(s) parsed from
++ * autoneg_advertised and fc
++ * no matter what autoneg is , We will not wait link result.
++ */
++ ret_val = atl1_phy_setup_autoneg_adv(hw);
++ if (ret_val) {
++ if (netif_msg_link(adapter))
++ dev_dbg(&pdev->dev,
++ "error setting up autonegotiation\n");
++ return ret_val;
++ }
++ /* SW.Reset , En-Auto-Neg if needed */
++ ret_val = atl1_phy_reset(hw);
++ if (ret_val) {
++ if (netif_msg_link(adapter))
++ dev_dbg(&pdev->dev, "error resetting phy\n");
++ return ret_val;
++ }
++ hw->phy_configured = true;
++ return ret_val;
++}
++
++static void atl1_init_flash_opcode(struct atl1_hw *hw)
++{
++ if (hw->flash_vendor >= ARRAY_SIZE(flash_table))
++ /* Atmel */
++ hw->flash_vendor = 0;
++
++ /* Init OP table */
++ iowrite8(flash_table[hw->flash_vendor].cmd_program,
++ hw->hw_addr + REG_SPI_FLASH_OP_PROGRAM);
++ iowrite8(flash_table[hw->flash_vendor].cmd_sector_erase,
++ hw->hw_addr + REG_SPI_FLASH_OP_SC_ERASE);
++ iowrite8(flash_table[hw->flash_vendor].cmd_chip_erase,
++ hw->hw_addr + REG_SPI_FLASH_OP_CHIP_ERASE);
++ iowrite8(flash_table[hw->flash_vendor].cmd_rdid,
++ hw->hw_addr + REG_SPI_FLASH_OP_RDID);
++ iowrite8(flash_table[hw->flash_vendor].cmd_wren,
++ hw->hw_addr + REG_SPI_FLASH_OP_WREN);
++ iowrite8(flash_table[hw->flash_vendor].cmd_rdsr,
++ hw->hw_addr + REG_SPI_FLASH_OP_RDSR);
++ iowrite8(flash_table[hw->flash_vendor].cmd_wrsr,
++ hw->hw_addr + REG_SPI_FLASH_OP_WRSR);
++ iowrite8(flash_table[hw->flash_vendor].cmd_read,
++ hw->hw_addr + REG_SPI_FLASH_OP_READ);
++}
++
++/*
++ * Performs basic configuration of the adapter.
++ * hw - Struct containing variables accessed by shared code
++ * Assumes that the controller has previously been reset and is in a
++ * post-reset uninitialized state. Initializes multicast table,
++ * and Calls routines to setup link
++ * Leaves the transmit and receive units disabled and uninitialized.
++ */
++static s32 atl1_init_hw(struct atl1_hw *hw)
++{
++ u32 ret_val = 0;
++
++ /* Zero out the Multicast HASH table */
++ iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
++ /* clear the old settings from the multicast hash table */
++ iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
++
++ atl1_init_flash_opcode(hw);
++
++ if (!hw->phy_configured) {
++ /* enable GPHY LinkChange Interrrupt */
++ ret_val = atl1_write_phy_reg(hw, 18, 0xC00);
++ if (ret_val)
++ return ret_val;
++ /* make PHY out of power-saving state */
++ ret_val = atl1_phy_leave_power_saving(hw);
++ if (ret_val)
++ return ret_val;
++ /* Call a subroutine to configure the link */
++ ret_val = atl1_setup_link(hw);
++ }
++ return ret_val;
++}
++
++/*
++ * 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
++ */
++static s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex)
++{
++ struct pci_dev *pdev = hw->back->pdev;
++ struct atl1_adapter *adapter = hw->back;
++ s32 ret_val;
++ u16 phy_data;
++
++ /* ; --- Read PHY Specific Status Register (17) */
++ ret_val = atl1_read_phy_reg(hw, MII_ATLX_PSSR, &phy_data);
++ if (ret_val)
++ return ret_val;
++
++ if (!(phy_data & MII_ATLX_PSSR_SPD_DPLX_RESOLVED))
++ return ATLX_ERR_PHY_RES;
++
++ switch (phy_data & MII_ATLX_PSSR_SPEED) {
++ case MII_ATLX_PSSR_1000MBS:
++ *speed = SPEED_1000;
++ break;
++ case MII_ATLX_PSSR_100MBS:
++ *speed = SPEED_100;
++ break;
++ case MII_ATLX_PSSR_10MBS:
++ *speed = SPEED_10;
++ break;
++ default:
++ if (netif_msg_hw(adapter))
++ dev_dbg(&pdev->dev, "error getting speed\n");
++ return ATLX_ERR_PHY_SPEED;
++ break;
++ }
++ if (phy_data & MII_ATLX_PSSR_DPLX)
++ *duplex = FULL_DUPLEX;
++ else
++ *duplex = HALF_DUPLEX;
++
++ return 0;
++}
++
++void atl1_set_mac_addr(struct atl1_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]));
++ iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
++ /* high dword */
++ value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
++ iowrite32(value, (hw->hw_addr + REG_MAC_STA_ADDR) + (1 << 2));
++}
++
++/*
++ * atl1_sw_init - Initialize general software structures (struct atl1_adapter)
++ * @adapter: board private structure to initialize
++ *
++ * atl1_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 atl1_sw_init(struct atl1_adapter *adapter)
++{
++ struct atl1_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
++
++ hw->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
++ hw->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
++
++ adapter->wol = 0;
++ adapter->rx_buffer_len = (hw->max_frame_size + 7) & ~7;
++ adapter->ict = 50000; /* 100ms */
++ adapter->link_speed = SPEED_0; /* hardware init */
++ adapter->link_duplex = FULL_DUPLEX;
++
++ hw->phy_configured = false;
++ hw->preamble_len = 7;
++ hw->ipgt = 0x60;
++ hw->min_ifg = 0x50;
++ hw->ipgr1 = 0x40;
++ hw->ipgr2 = 0x60;
++ hw->max_retry = 0xf;
++ hw->lcol = 0x37;
++ hw->jam_ipg = 7;
++ hw->rfd_burst = 8;
++ hw->rrd_burst = 8;
++ hw->rfd_fetch_gap = 1;
++ hw->rx_jumbo_th = adapter->rx_buffer_len / 8;
++ hw->rx_jumbo_lkah = 1;
++ hw->rrd_ret_timer = 16;
++ hw->tpd_burst = 4;
++ hw->tpd_fetch_th = 16;
++ hw->txf_burst = 0x100;
++ hw->tx_jumbo_task_th = (hw->max_frame_size + 7) >> 3;
++ hw->tpd_fetch_gap = 1;
++ hw->rcb_value = atl1_rcb_64;
++ hw->dma_ord = atl1_dma_ord_enh;
++ hw->dmar_block = atl1_dma_req_256;
++ hw->dmaw_block = atl1_dma_req_256;
++ hw->cmb_rrd = 4;
++ hw->cmb_tpd = 4;
++ hw->cmb_rx_timer = 1; /* about 2us */
++ hw->cmb_tx_timer = 1; /* about 2us */
++ hw->smb_timer = 100000; /* about 200ms */
++
++ spin_lock_init(&adapter->lock);
++ spin_lock_init(&adapter->mb_lock);
++
++ return 0;
++}
++
++static int mdio_read(struct net_device *netdev, int phy_id, int reg_num)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ u16 result;
++
++ atl1_read_phy_reg(&adapter->hw, reg_num & 0x1f, &result);
++
++ return result;
++}
++
++static void mdio_write(struct net_device *netdev, int phy_id, int reg_num,
++ int val)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++
++ atl1_write_phy_reg(&adapter->hw, reg_num, val);
++}
++
++/*
++ * atl1_mii_ioctl -
++ * @netdev:
++ * @ifreq:
++ * @cmd:
++ */
++static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ unsigned long flags;
++ int retval;
++
++ if (!netif_running(netdev))
++ return -EINVAL;
++
++ spin_lock_irqsave(&adapter->lock, flags);
++ retval = generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
++ spin_unlock_irqrestore(&adapter->lock, flags);
++
++ return retval;
++}
++
++/*
++ * atl1_setup_mem_resources - allocate Tx / RX descriptor resources
++ * @adapter: board private structure
++ *
++ * Return 0 on success, negative on failure
++ */
++static s32 atl1_setup_ring_resources(struct atl1_adapter *adapter)
++{
++ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
++ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
++ struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
++ struct atl1_ring_header *ring_header = &adapter->ring_header;
++ struct pci_dev *pdev = adapter->pdev;
++ int size;
++ u8 offset = 0;
++
++ size = sizeof(struct atl1_buffer) * (tpd_ring->count + rfd_ring->count);
++ tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL);
++ if (unlikely(!tpd_ring->buffer_info)) {
++ if (netif_msg_drv(adapter))
++ dev_err(&pdev->dev, "kzalloc failed , size = D%d\n",
++ size);
++ goto err_nomem;
++ }
++ rfd_ring->buffer_info =
++ (struct atl1_buffer *)(tpd_ring->buffer_info + tpd_ring->count);
++
++ /*
++ * real ring DMA buffer
++ * each ring/block may need up to 8 bytes for alignment, hence the
++ * additional 40 bytes tacked onto the end.
++ */
++ ring_header->size = size =
++ sizeof(struct tx_packet_desc) * tpd_ring->count
++ + sizeof(struct rx_free_desc) * rfd_ring->count
++ + sizeof(struct rx_return_desc) * rrd_ring->count
++ + sizeof(struct coals_msg_block)
++ + sizeof(struct stats_msg_block)
++ + 40;
++
++ ring_header->desc = pci_alloc_consistent(pdev, ring_header->size,
++ &ring_header->dma);
++ if (unlikely(!ring_header->desc)) {
++ if (netif_msg_drv(adapter))
++ dev_err(&pdev->dev, "pci_alloc_consistent failed\n");
++ goto err_nomem;
++ }
++
++ memset(ring_header->desc, 0, ring_header->size);
++
++ /* init TPD ring */
++ tpd_ring->dma = ring_header->dma;
++ offset = (tpd_ring->dma & 0x7) ? (8 - (ring_header->dma & 0x7)) : 0;
++ tpd_ring->dma += offset;
++ tpd_ring->desc = (u8 *) ring_header->desc + offset;
++ tpd_ring->size = sizeof(struct tx_packet_desc) * tpd_ring->count;
++
++ /* init RFD ring */
++ rfd_ring->dma = tpd_ring->dma + tpd_ring->size;
++ offset = (rfd_ring->dma & 0x7) ? (8 - (rfd_ring->dma & 0x7)) : 0;
++ rfd_ring->dma += offset;
++ rfd_ring->desc = (u8 *) tpd_ring->desc + (tpd_ring->size + offset);
++ rfd_ring->size = sizeof(struct rx_free_desc) * rfd_ring->count;
++
++
++ /* init RRD ring */
++ rrd_ring->dma = rfd_ring->dma + rfd_ring->size;
++ offset = (rrd_ring->dma & 0x7) ? (8 - (rrd_ring->dma & 0x7)) : 0;
++ rrd_ring->dma += offset;
++ rrd_ring->desc = (u8 *) rfd_ring->desc + (rfd_ring->size + offset);
++ rrd_ring->size = sizeof(struct rx_return_desc) * rrd_ring->count;
++
++
++ /* init CMB */
++ adapter->cmb.dma = rrd_ring->dma + rrd_ring->size;
++ offset = (adapter->cmb.dma & 0x7) ? (8 - (adapter->cmb.dma & 0x7)) : 0;
++ adapter->cmb.dma += offset;
++ adapter->cmb.cmb = (struct coals_msg_block *)
++ ((u8 *) rrd_ring->desc + (rrd_ring->size + offset));
++
++ /* init SMB */
++ adapter->smb.dma = adapter->cmb.dma + sizeof(struct coals_msg_block);
++ offset = (adapter->smb.dma & 0x7) ? (8 - (adapter->smb.dma & 0x7)) : 0;
++ adapter->smb.dma += offset;
++ adapter->smb.smb = (struct stats_msg_block *)
++ ((u8 *) adapter->cmb.cmb +
++ (sizeof(struct coals_msg_block) + offset));
++
++ return 0;
++
++err_nomem:
++ kfree(tpd_ring->buffer_info);
++ return -ENOMEM;
++}
++
++static void atl1_init_ring_ptrs(struct atl1_adapter *adapter)
++{
++ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
++ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
++ struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
++
++ atomic_set(&tpd_ring->next_to_use, 0);
++ atomic_set(&tpd_ring->next_to_clean, 0);
++
++ rfd_ring->next_to_clean = 0;
++ atomic_set(&rfd_ring->next_to_use, 0);
++
++ rrd_ring->next_to_use = 0;
++ atomic_set(&rrd_ring->next_to_clean, 0);
++}
++
++/*
++ * atl1_clean_rx_ring - Free RFD Buffers
++ * @adapter: board private structure
++ */
++static void atl1_clean_rx_ring(struct atl1_adapter *adapter)
++{
++ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
++ struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
++ struct atl1_buffer *buffer_info;
++ struct pci_dev *pdev = adapter->pdev;
++ unsigned long size;
++ unsigned int i;
++
++ /* Free all the Rx ring sk_buffs */
++ for (i = 0; i < rfd_ring->count; i++) {
++ buffer_info = &rfd_ring->buffer_info[i];
++ if (buffer_info->dma) {
++ pci_unmap_page(pdev, buffer_info->dma,
++ buffer_info->length, PCI_DMA_FROMDEVICE);
++ buffer_info->dma = 0;
++ }
++ if (buffer_info->skb) {
++ dev_kfree_skb(buffer_info->skb);
++ buffer_info->skb = NULL;
++ }
++ }
++
++ size = sizeof(struct atl1_buffer) * rfd_ring->count;
++ memset(rfd_ring->buffer_info, 0, size);
++
++ /* Zero out the descriptor ring */
++ memset(rfd_ring->desc, 0, rfd_ring->size);
++
++ rfd_ring->next_to_clean = 0;
++ atomic_set(&rfd_ring->next_to_use, 0);
++
++ rrd_ring->next_to_use = 0;
++ atomic_set(&rrd_ring->next_to_clean, 0);
++}
++
++/*
++ * atl1_clean_tx_ring - Free Tx Buffers
++ * @adapter: board private structure
++ */
++static void atl1_clean_tx_ring(struct atl1_adapter *adapter)
++{
++ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
++ struct atl1_buffer *buffer_info;
++ struct pci_dev *pdev = adapter->pdev;
++ unsigned long size;
++ unsigned int i;
++
++ /* Free all the Tx ring sk_buffs */
++ for (i = 0; i < tpd_ring->count; i++) {
++ buffer_info = &tpd_ring->buffer_info[i];
++ if (buffer_info->dma) {
++ pci_unmap_page(pdev, buffer_info->dma,
++ buffer_info->length, PCI_DMA_TODEVICE);
++ buffer_info->dma = 0;
++ }
++ }
++
++ for (i = 0; i < tpd_ring->count; i++) {
++ buffer_info = &tpd_ring->buffer_info[i];
++ if (buffer_info->skb) {
++ dev_kfree_skb_any(buffer_info->skb);
++ buffer_info->skb = NULL;
++ }
++ }
++
++ size = sizeof(struct atl1_buffer) * tpd_ring->count;
++ memset(tpd_ring->buffer_info, 0, size);
++
++ /* Zero out the descriptor ring */
++ memset(tpd_ring->desc, 0, tpd_ring->size);
++
++ atomic_set(&tpd_ring->next_to_use, 0);
++ atomic_set(&tpd_ring->next_to_clean, 0);
++}
++
++/*
++ * atl1_free_ring_resources - Free Tx / RX descriptor Resources
++ * @adapter: board private structure
++ *
++ * Free all transmit software resources
++ */
++static void atl1_free_ring_resources(struct atl1_adapter *adapter)
++{
++ struct pci_dev *pdev = adapter->pdev;
++ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
++ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
++ struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
++ struct atl1_ring_header *ring_header = &adapter->ring_header;
++
++ atl1_clean_tx_ring(adapter);
++ atl1_clean_rx_ring(adapter);
++
++ kfree(tpd_ring->buffer_info);
++ pci_free_consistent(pdev, ring_header->size, ring_header->desc,
++ ring_header->dma);
++
++ tpd_ring->buffer_info = NULL;
++ tpd_ring->desc = NULL;
++ tpd_ring->dma = 0;
++
++ rfd_ring->buffer_info = NULL;
++ rfd_ring->desc = NULL;
++ rfd_ring->dma = 0;
++
++ rrd_ring->desc = NULL;
++ rrd_ring->dma = 0;
++}
++
++static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter)
++{
++ u32 value;
++ struct atl1_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
++ /* Config MAC CTRL Register */
++ value = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN;
++ /* duplex */
++ if (FULL_DUPLEX == adapter->link_duplex)
++ value |= MAC_CTRL_DUPLX;
++ /* speed */
++ value |= ((u32) ((SPEED_1000 == adapter->link_speed) ?
++ MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) <<
++ MAC_CTRL_SPEED_SHIFT);
++ /* flow control */
++ value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
++ /* PAD & CRC */
++ value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
++ /* preamble length */
++ value |= (((u32) adapter->hw.preamble_len
++ & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
++ /* vlan */
++ if (adapter->vlgrp)
++ value |= MAC_CTRL_RMV_VLAN;
++ /* rx checksum
++ if (adapter->rx_csum)
++ value |= MAC_CTRL_RX_CHKSUM_EN;
++ */
++ /* filter mode */
++ value |= MAC_CTRL_BC_EN;
++ if (netdev->flags & IFF_PROMISC)
++ value |= MAC_CTRL_PROMIS_EN;
++ else if (netdev->flags & IFF_ALLMULTI)
++ value |= MAC_CTRL_MC_ALL_EN;
++ /* value |= MAC_CTRL_LOOPBACK; */
++ iowrite32(value, hw->hw_addr + REG_MAC_CTRL);
++}
++
++static u32 atl1_check_link(struct atl1_adapter *adapter)
++{
++ struct atl1_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
++ u32 ret_val;
++ u16 speed, duplex, phy_data;
++ int reconfig = 0;
++
++ /* MII_BMSR must read twice */
++ atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
++ atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
++ if (!(phy_data & BMSR_LSTATUS)) {
++ /* link down */
++ if (netif_carrier_ok(netdev)) {
++ /* old link state: Up */
++ if (netif_msg_link(adapter))
++ dev_info(&adapter->pdev->dev, "link is down\n");
++ adapter->link_speed = SPEED_0;
++ netif_carrier_off(netdev);
++ netif_stop_queue(netdev);
++ }
++ return 0;
++ }
++
++ /* Link Up */
++ ret_val = atl1_get_speed_and_duplex(hw, &speed, &duplex);
++ if (ret_val)
++ return ret_val;
++
++ switch (hw->media_type) {
++ case MEDIA_TYPE_1000M_FULL:
++ if (speed != SPEED_1000 || duplex != FULL_DUPLEX)
++ reconfig = 1;
++ break;
++ case MEDIA_TYPE_100M_FULL:
++ if (speed != SPEED_100 || duplex != FULL_DUPLEX)
++ reconfig = 1;
++ break;
++ case MEDIA_TYPE_100M_HALF:
++ if (speed != SPEED_100 || duplex != HALF_DUPLEX)
++ reconfig = 1;
++ break;
++ case MEDIA_TYPE_10M_FULL:
++ if (speed != SPEED_10 || duplex != FULL_DUPLEX)
++ reconfig = 1;
++ break;
++ case MEDIA_TYPE_10M_HALF:
++ if (speed != SPEED_10 || duplex != HALF_DUPLEX)
++ reconfig = 1;
++ break;
++ }
++
++ /* link result is our setting */
++ if (!reconfig) {
++ if (adapter->link_speed != speed
++ || adapter->link_duplex != duplex) {
++ adapter->link_speed = speed;
++ adapter->link_duplex = duplex;
++ atl1_setup_mac_ctrl(adapter);
++ if (netif_msg_link(adapter))
++ dev_info(&adapter->pdev->dev,
++ "%s link is up %d Mbps %s\n",
++ netdev->name, adapter->link_speed,
++ adapter->link_duplex == FULL_DUPLEX ?
++ "full duplex" : "half duplex");
++ }
++ if (!netif_carrier_ok(netdev)) {
++ /* Link down -> Up */
++ netif_carrier_on(netdev);
++ netif_wake_queue(netdev);
++ }
++ return 0;
++ }
++
++ /* change original link status */
++ if (netif_carrier_ok(netdev)) {
++ adapter->link_speed = SPEED_0;
++ netif_carrier_off(netdev);
++ netif_stop_queue(netdev);
++ }
++
++ if (hw->media_type != MEDIA_TYPE_AUTO_SENSOR &&
++ hw->media_type != MEDIA_TYPE_1000M_FULL) {
++ switch (hw->media_type) {
++ case MEDIA_TYPE_100M_FULL:
++ phy_data = MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
++ MII_CR_RESET;
++ break;
++ case MEDIA_TYPE_100M_HALF:
++ phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
++ break;
++ case MEDIA_TYPE_10M_FULL:
++ phy_data =
++ MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
++ break;
++ default:
++ /* MEDIA_TYPE_10M_HALF: */
++ phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
++ break;
++ }
++ atl1_write_phy_reg(hw, MII_BMCR, phy_data);
++ return 0;
++ }
++
++ /* auto-neg, insert timer to re-config phy */
++ if (!adapter->phy_timer_pending) {
++ adapter->phy_timer_pending = true;
++ mod_timer(&adapter->phy_config_timer, jiffies + 3 * HZ);
++ }
++
++ return 0;
++}
++
++static void set_flow_ctrl_old(struct atl1_adapter *adapter)
++{
++ u32 hi, lo, value;
++
++ /* RFD Flow Control */
++ value = adapter->rfd_ring.count;
++ hi = value / 16;
++ if (hi < 2)
++ hi = 2;
++ lo = value * 7 / 8;
++
++ value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
++ ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
++ iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
++
++ /* RRD Flow Control */
++ value = adapter->rrd_ring.count;
++ lo = value / 16;
++ hi = value * 7 / 8;
++ if (lo < 2)
++ lo = 2;
++ value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
++ ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
++ iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
++}
++
++static void set_flow_ctrl_new(struct atl1_hw *hw)
++{
++ u32 hi, lo, value;
++
++ /* RXF Flow Control */
++ value = ioread32(hw->hw_addr + REG_SRAM_RXF_LEN);
++ lo = value / 16;
++ if (lo < 192)
++ lo = 192;
++ hi = value * 7 / 8;
++ if (hi < lo)
++ hi = lo + 16;
++ value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
++ ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
++ iowrite32(value, hw->hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
++
++ /* RRD Flow Control */
++ value = ioread32(hw->hw_addr + REG_SRAM_RRD_LEN);
++ lo = value / 8;
++ hi = value * 7 / 8;
++ if (lo < 2)
++ lo = 2;
++ if (hi < lo)
++ hi = lo + 3;
++ value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
++ ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
++ iowrite32(value, hw->hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
++}
++
++/*
++ * atl1_configure - Configure Transmit&Receive Unit after Reset
++ * @adapter: board private structure
++ *
++ * Configure the Tx /Rx unit of the MAC after a reset.
++ */
++static u32 atl1_configure(struct atl1_adapter *adapter)
++{
++ struct atl1_hw *hw = &adapter->hw;
++ u32 value;
++
++ /* clear interrupt status */
++ iowrite32(0xffffffff, adapter->hw.hw_addr + REG_ISR);
++
++ /* set MAC Address */
++ value = (((u32) hw->mac_addr[2]) << 24) |
++ (((u32) hw->mac_addr[3]) << 16) |
++ (((u32) hw->mac_addr[4]) << 8) |
++ (((u32) hw->mac_addr[5]));
++ iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
++ value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
++ iowrite32(value, hw->hw_addr + (REG_MAC_STA_ADDR + 4));
++
++ /* tx / rx ring */
++
++ /* HI base address */
++ iowrite32((u32) ((adapter->tpd_ring.dma & 0xffffffff00000000ULL) >> 32),
++ hw->hw_addr + REG_DESC_BASE_ADDR_HI);
++ /* LO base address */
++ iowrite32((u32) (adapter->rfd_ring.dma & 0x00000000ffffffffULL),
++ hw->hw_addr + REG_DESC_RFD_ADDR_LO);
++ iowrite32((u32) (adapter->rrd_ring.dma & 0x00000000ffffffffULL),
++ hw->hw_addr + REG_DESC_RRD_ADDR_LO);
++ iowrite32((u32) (adapter->tpd_ring.dma & 0x00000000ffffffffULL),
++ hw->hw_addr + REG_DESC_TPD_ADDR_LO);
++ iowrite32((u32) (adapter->cmb.dma & 0x00000000ffffffffULL),
++ hw->hw_addr + REG_DESC_CMB_ADDR_LO);
++ iowrite32((u32) (adapter->smb.dma & 0x00000000ffffffffULL),
++ hw->hw_addr + REG_DESC_SMB_ADDR_LO);
++
++ /* element count */
++ value = adapter->rrd_ring.count;
++ value <<= 16;
++ value += adapter->rfd_ring.count;
++ iowrite32(value, hw->hw_addr + REG_DESC_RFD_RRD_RING_SIZE);
++ iowrite32(adapter->tpd_ring.count, hw->hw_addr +
++ REG_DESC_TPD_RING_SIZE);
++
++ /* Load Ptr */
++ iowrite32(1, hw->hw_addr + REG_LOAD_PTR);
++
++ /* config Mailbox */
++ value = ((atomic_read(&adapter->tpd_ring.next_to_use)
++ & MB_TPD_PROD_INDX_MASK) << MB_TPD_PROD_INDX_SHIFT) |
++ ((atomic_read(&adapter->rrd_ring.next_to_clean)
++ & MB_RRD_CONS_INDX_MASK) << MB_RRD_CONS_INDX_SHIFT) |
++ ((atomic_read(&adapter->rfd_ring.next_to_use)
++ & MB_RFD_PROD_INDX_MASK) << MB_RFD_PROD_INDX_SHIFT);
++ iowrite32(value, hw->hw_addr + REG_MAILBOX);
++
++ /* config IPG/IFG */
++ value = (((u32) hw->ipgt & MAC_IPG_IFG_IPGT_MASK)
++ << MAC_IPG_IFG_IPGT_SHIFT) |
++ (((u32) hw->min_ifg & MAC_IPG_IFG_MIFG_MASK)
++ << MAC_IPG_IFG_MIFG_SHIFT) |
++ (((u32) hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK)
++ << MAC_IPG_IFG_IPGR1_SHIFT) |
++ (((u32) hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK)
++ << MAC_IPG_IFG_IPGR2_SHIFT);
++ iowrite32(value, hw->hw_addr + REG_MAC_IPG_IFG);
++
++ /* config Half-Duplex Control */
++ value = ((u32) hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) |
++ (((u32) hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK)
++ << MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) |
++ MAC_HALF_DUPLX_CTRL_EXC_DEF_EN |
++ (0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) |
++ (((u32) hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK)
++ << MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT);
++ iowrite32(value, hw->hw_addr + REG_MAC_HALF_DUPLX_CTRL);
++
++ /* set Interrupt Moderator Timer */
++ iowrite16(adapter->imt, hw->hw_addr + REG_IRQ_MODU_TIMER_INIT);
++ iowrite32(MASTER_CTRL_ITIMER_EN, hw->hw_addr + REG_MASTER_CTRL);
++
++ /* set Interrupt Clear Timer */
++ iowrite16(adapter->ict, hw->hw_addr + REG_CMBDISDMA_TIMER);
++
++ /* set max frame size hw will accept */
++ iowrite32(hw->max_frame_size, hw->hw_addr + REG_MTU);
++
++ /* jumbo size & rrd retirement timer */
++ value = (((u32) hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK)
++ << RXQ_JMBOSZ_TH_SHIFT) |
++ (((u32) hw->rx_jumbo_lkah & RXQ_JMBO_LKAH_MASK)
++ << RXQ_JMBO_LKAH_SHIFT) |
++ (((u32) hw->rrd_ret_timer & RXQ_RRD_TIMER_MASK)
++ << RXQ_RRD_TIMER_SHIFT);
++ iowrite32(value, hw->hw_addr + REG_RXQ_JMBOSZ_RRDTIM);
++
++ /* Flow Control */
++ switch (hw->dev_rev) {
++ case 0x8001:
++ case 0x9001:
++ case 0x9002:
++ case 0x9003:
++ set_flow_ctrl_old(adapter);
++ break;
++ default:
++ set_flow_ctrl_new(hw);
++ break;
++ }
++
++ /* config TXQ */
++ value = (((u32) hw->tpd_burst & TXQ_CTRL_TPD_BURST_NUM_MASK)
++ << TXQ_CTRL_TPD_BURST_NUM_SHIFT) |
++ (((u32) hw->txf_burst & TXQ_CTRL_TXF_BURST_NUM_MASK)
++ << TXQ_CTRL_TXF_BURST_NUM_SHIFT) |
++ (((u32) hw->tpd_fetch_th & TXQ_CTRL_TPD_FETCH_TH_MASK)
++ << TXQ_CTRL_TPD_FETCH_TH_SHIFT) | TXQ_CTRL_ENH_MODE |
++ TXQ_CTRL_EN;
++ iowrite32(value, hw->hw_addr + REG_TXQ_CTRL);
++
++ /* min tpd fetch gap & tx jumbo packet size threshold for taskoffload */
++ value = (((u32) hw->tx_jumbo_task_th & TX_JUMBO_TASK_TH_MASK)
++ << TX_JUMBO_TASK_TH_SHIFT) |
++ (((u32) hw->tpd_fetch_gap & TX_TPD_MIN_IPG_MASK)
++ << TX_TPD_MIN_IPG_SHIFT);
++ iowrite32(value, hw->hw_addr + REG_TX_JUMBO_TASK_TH_TPD_IPG);
++
++ /* config RXQ */
++ value = (((u32) hw->rfd_burst & RXQ_CTRL_RFD_BURST_NUM_MASK)
++ << RXQ_CTRL_RFD_BURST_NUM_SHIFT) |
++ (((u32) hw->rrd_burst & RXQ_CTRL_RRD_BURST_THRESH_MASK)
++ << RXQ_CTRL_RRD_BURST_THRESH_SHIFT) |
++ (((u32) hw->rfd_fetch_gap & RXQ_CTRL_RFD_PREF_MIN_IPG_MASK)
++ << RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT) | RXQ_CTRL_CUT_THRU_EN |
++ RXQ_CTRL_EN;
++ iowrite32(value, hw->hw_addr + REG_RXQ_CTRL);
++
++ /* config DMA Engine */
++ value = ((((u32) hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
++ << DMA_CTRL_DMAR_BURST_LEN_SHIFT) |
++ ((((u32) hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK)
++ << DMA_CTRL_DMAW_BURST_LEN_SHIFT) | DMA_CTRL_DMAR_EN |
++ DMA_CTRL_DMAW_EN;
++ value |= (u32) hw->dma_ord;
++ if (atl1_rcb_128 == hw->rcb_value)
++ value |= DMA_CTRL_RCB_VALUE;
++ iowrite32(value, hw->hw_addr + REG_DMA_CTRL);
++
++ /* config CMB / SMB */
++ value = (hw->cmb_tpd > adapter->tpd_ring.count) ?
++ hw->cmb_tpd : adapter->tpd_ring.count;
++ value <<= 16;
++ value |= hw->cmb_rrd;
++ iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TH);
++ value = hw->cmb_rx_timer | ((u32) hw->cmb_tx_timer << 16);
++ iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TIMER);
++ iowrite32(hw->smb_timer, hw->hw_addr + REG_SMB_TIMER);
++
++ /* --- enable CMB / SMB */
++ value = CSMB_CTRL_CMB_EN | CSMB_CTRL_SMB_EN;
++ iowrite32(value, hw->hw_addr + REG_CSMB_CTRL);
++
++ value = ioread32(adapter->hw.hw_addr + REG_ISR);
++ if (unlikely((value & ISR_PHY_LINKDOWN) != 0))
++ value = 1; /* config failed */
++ else
++ value = 0;
++
++ /* clear all interrupt status */
++ iowrite32(0x3fffffff, adapter->hw.hw_addr + REG_ISR);
++ iowrite32(0, adapter->hw.hw_addr + REG_ISR);
++ return value;
++}
++
++/*
++ * atl1_pcie_patch - Patch for PCIE module
++ */
++static void atl1_pcie_patch(struct atl1_adapter *adapter)
++{
++ u32 value;
++
++ /* much vendor magic here */
++ value = 0x6500;
++ iowrite32(value, adapter->hw.hw_addr + 0x12FC);
++ /* pcie flow control mode change */
++ value = ioread32(adapter->hw.hw_addr + 0x1008);
++ value |= 0x8000;
++ iowrite32(value, adapter->hw.hw_addr + 0x1008);
++}
++
++/*
++ * When ACPI resume on some VIA MotherBoard, the Interrupt Disable bit/0x400
++ * on PCI Command register is disable.
++ * The function enable this bit.
++ * Brackett, 2006/03/15
++ */
++static void atl1_via_workaround(struct atl1_adapter *adapter)
++{
++ unsigned long value;
++
++ value = ioread16(adapter->hw.hw_addr + PCI_COMMAND);
++ if (value & PCI_COMMAND_INTX_DISABLE)
++ value &= ~PCI_COMMAND_INTX_DISABLE;
++ iowrite32(value, adapter->hw.hw_addr + PCI_COMMAND);
++}
++
++static void atl1_inc_smb(struct atl1_adapter *adapter)
++{
++ struct stats_msg_block *smb = adapter->smb.smb;
++
++ /* Fill out the OS statistics structure */
++ adapter->soft_stats.rx_packets += smb->rx_ok;
++ adapter->soft_stats.tx_packets += smb->tx_ok;
++ adapter->soft_stats.rx_bytes += smb->rx_byte_cnt;
++ adapter->soft_stats.tx_bytes += smb->tx_byte_cnt;
++ adapter->soft_stats.multicast += smb->rx_mcast;
++ adapter->soft_stats.collisions += (smb->tx_1_col + smb->tx_2_col * 2 +
++ smb->tx_late_col + smb->tx_abort_col * adapter->hw.max_retry);
++
++ /* Rx Errors */
++ adapter->soft_stats.rx_errors += (smb->rx_frag + smb->rx_fcs_err +
++ smb->rx_len_err + smb->rx_sz_ov + smb->rx_rxf_ov +
++ smb->rx_rrd_ov + smb->rx_align_err);
++ adapter->soft_stats.rx_fifo_errors += smb->rx_rxf_ov;
++ adapter->soft_stats.rx_length_errors += smb->rx_len_err;
++ adapter->soft_stats.rx_crc_errors += smb->rx_fcs_err;
++ adapter->soft_stats.rx_frame_errors += smb->rx_align_err;
++ adapter->soft_stats.rx_missed_errors += (smb->rx_rrd_ov +
++ smb->rx_rxf_ov);
++
++ adapter->soft_stats.rx_pause += smb->rx_pause;
++ adapter->soft_stats.rx_rrd_ov += smb->rx_rrd_ov;
++ adapter->soft_stats.rx_trunc += smb->rx_sz_ov;
++
++ /* Tx Errors */
++ adapter->soft_stats.tx_errors += (smb->tx_late_col +
++ smb->tx_abort_col + smb->tx_underrun + smb->tx_trunc);
++ adapter->soft_stats.tx_fifo_errors += smb->tx_underrun;
++ adapter->soft_stats.tx_aborted_errors += smb->tx_abort_col;
++ adapter->soft_stats.tx_window_errors += smb->tx_late_col;
++
++ adapter->soft_stats.excecol += smb->tx_abort_col;
++ adapter->soft_stats.deffer += smb->tx_defer;
++ adapter->soft_stats.scc += smb->tx_1_col;
++ adapter->soft_stats.mcc += smb->tx_2_col;
++ adapter->soft_stats.latecol += smb->tx_late_col;
++ adapter->soft_stats.tx_underun += smb->tx_underrun;
++ adapter->soft_stats.tx_trunc += smb->tx_trunc;
++ adapter->soft_stats.tx_pause += smb->tx_pause;
++
++ adapter->net_stats.rx_packets = adapter->soft_stats.rx_packets;
++ adapter->net_stats.tx_packets = adapter->soft_stats.tx_packets;
++ adapter->net_stats.rx_bytes = adapter->soft_stats.rx_bytes;
++ adapter->net_stats.tx_bytes = adapter->soft_stats.tx_bytes;
++ adapter->net_stats.multicast = adapter->soft_stats.multicast;
++ adapter->net_stats.collisions = adapter->soft_stats.collisions;
++ adapter->net_stats.rx_errors = adapter->soft_stats.rx_errors;
++ adapter->net_stats.rx_over_errors =
++ adapter->soft_stats.rx_missed_errors;
++ adapter->net_stats.rx_length_errors =
++ adapter->soft_stats.rx_length_errors;
++ adapter->net_stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors;
++ adapter->net_stats.rx_frame_errors =
++ adapter->soft_stats.rx_frame_errors;
++ adapter->net_stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors;
++ adapter->net_stats.rx_missed_errors =
++ adapter->soft_stats.rx_missed_errors;
++ adapter->net_stats.tx_errors = adapter->soft_stats.tx_errors;
++ adapter->net_stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors;
++ adapter->net_stats.tx_aborted_errors =
++ adapter->soft_stats.tx_aborted_errors;
++ adapter->net_stats.tx_window_errors =
++ adapter->soft_stats.tx_window_errors;
++ adapter->net_stats.tx_carrier_errors =
++ adapter->soft_stats.tx_carrier_errors;
++}
++
++static void atl1_update_mailbox(struct atl1_adapter *adapter)
++{
++ unsigned long flags;
++ u32 tpd_next_to_use;
++ u32 rfd_next_to_use;
++ u32 rrd_next_to_clean;
++ u32 value;
++
++ spin_lock_irqsave(&adapter->mb_lock, flags);
++
++ tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
++ rfd_next_to_use = atomic_read(&adapter->rfd_ring.next_to_use);
++ rrd_next_to_clean = atomic_read(&adapter->rrd_ring.next_to_clean);
++
++ value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
++ MB_RFD_PROD_INDX_SHIFT) |
++ ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
++ MB_RRD_CONS_INDX_SHIFT) |
++ ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
++ MB_TPD_PROD_INDX_SHIFT);
++ iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
++
++ spin_unlock_irqrestore(&adapter->mb_lock, flags);
++}
++
++static void atl1_clean_alloc_flag(struct atl1_adapter *adapter,
++ struct rx_return_desc *rrd, u16 offset)
++{
++ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
++
++ while (rfd_ring->next_to_clean != (rrd->buf_indx + offset)) {
++ rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced = 0;
++ if (++rfd_ring->next_to_clean == rfd_ring->count) {
++ rfd_ring->next_to_clean = 0;
++ }
++ }
++}
++
++static void atl1_update_rfd_index(struct atl1_adapter *adapter,
++ struct rx_return_desc *rrd)
++{
++ u16 num_buf;
++
++ num_buf = (rrd->xsz.xsum_sz.pkt_size + adapter->rx_buffer_len - 1) /
++ adapter->rx_buffer_len;
++ if (rrd->num_buf == num_buf)
++ /* clean alloc flag for bad rrd */
++ atl1_clean_alloc_flag(adapter, rrd, num_buf);
++}
++
++static void atl1_rx_checksum(struct atl1_adapter *adapter,
++ struct rx_return_desc *rrd, struct sk_buff *skb)
++{
++ struct pci_dev *pdev = adapter->pdev;
++
++ skb->ip_summed = CHECKSUM_NONE;
++
++ if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
++ if (rrd->err_flg & (ERR_FLAG_CRC | ERR_FLAG_TRUNC |
++ ERR_FLAG_CODE | ERR_FLAG_OV)) {
++ adapter->hw_csum_err++;
++ if (netif_msg_rx_err(adapter))
++ dev_printk(KERN_DEBUG, &pdev->dev,
++ "rx checksum error\n");
++ return;
++ }
++ }
++
++ /* not IPv4 */
++ if (!(rrd->pkt_flg & PACKET_FLAG_IPV4))
++ /* checksum is invalid, but it's not an IPv4 pkt, so ok */
++ return;
++
++ /* IPv4 packet */
++ if (likely(!(rrd->err_flg &
++ (ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM)))) {
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++ adapter->hw_csum_good++;
++ return;
++ }
++
++ /* IPv4, but hardware thinks its checksum is wrong */
++ if (netif_msg_rx_err(adapter))
++ dev_printk(KERN_DEBUG, &pdev->dev,
++ "hw csum wrong, pkt_flag:%x, err_flag:%x\n",
++ rrd->pkt_flg, rrd->err_flg);
++ skb->ip_summed = CHECKSUM_COMPLETE;
++ skb->csum = htons(rrd->xsz.xsum_sz.rx_chksum);
++ adapter->hw_csum_err++;
++ return;
++}
++
++/*
++ * atl1_alloc_rx_buffers - Replace used receive buffers
++ * @adapter: address of board private structure
++ */
++static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter)
++{
++ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
++ struct pci_dev *pdev = adapter->pdev;
++ struct page *page;
++ unsigned long offset;
++ struct atl1_buffer *buffer_info, *next_info;
++ struct sk_buff *skb;
++ u16 num_alloc = 0;
++ u16 rfd_next_to_use, next_next;
++ struct rx_free_desc *rfd_desc;
++
++ next_next = rfd_next_to_use = atomic_read(&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 (!buffer_info->alloced && !next_info->alloced) {
++ if (buffer_info->skb) {
++ buffer_info->alloced = 1;
++ goto next;
++ }
++
++ rfd_desc = ATL1_RFD_DESC(rfd_ring, rfd_next_to_use);
++
++ skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
++ if (unlikely(!skb)) {
++ /* Better luck next round */
++ adapter->net_stats.rx_dropped++;
++ 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
++ */
++ skb_reserve(skb, NET_IP_ALIGN);
++
++ buffer_info->alloced = 1;
++ buffer_info->skb = skb;
++ buffer_info->length = (u16) adapter->rx_buffer_len;
++ page = virt_to_page(skb->data);
++ offset = (unsigned long)skb->data & ~PAGE_MASK;
++ buffer_info->dma = pci_map_page(pdev, page, offset,
++ adapter->rx_buffer_len,
++ PCI_DMA_FROMDEVICE);
++ rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
++ rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len);
++ rfd_desc->coalese = 0;
++
++next:
++ rfd_next_to_use = next_next;
++ if (unlikely(++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) {
++ /*
++ * Force memory writes to complete before letting h/w
++ * know there are new descriptors to fetch. (Only
++ * applicable for weak-ordered memory model archs,
++ * such as IA-64).
++ */
++ wmb();
++ atomic_set(&rfd_ring->next_to_use, (int)rfd_next_to_use);
++ }
++ return num_alloc;
++}
++
++static void atl1_intr_rx(struct atl1_adapter *adapter)
++{
++ int i, count;
++ u16 length;
++ u16 rrd_next_to_clean;
++ u32 value;
++ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
++ struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
++ struct atl1_buffer *buffer_info;
++ struct rx_return_desc *rrd;
++ struct sk_buff *skb;
++
++ count = 0;
++
++ rrd_next_to_clean = atomic_read(&rrd_ring->next_to_clean);
++
++ while (1) {
++ rrd = ATL1_RRD_DESC(rrd_ring, rrd_next_to_clean);
++ i = 1;
++ if (likely(rrd->xsz.valid)) { /* packet valid */
++chk_rrd:
++ /* check rrd status */
++ if (likely(rrd->num_buf == 1))
++ goto rrd_ok;
++ else if (netif_msg_rx_err(adapter)) {
++ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++ "unexpected RRD buffer count\n");
++ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++ "rx_buf_len = %d\n",
++ adapter->rx_buffer_len);
++ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++ "RRD num_buf = %d\n",
++ rrd->num_buf);
++ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++ "RRD pkt_len = %d\n",
++ rrd->xsz.xsum_sz.pkt_size);
++ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++ "RRD pkt_flg = 0x%08X\n",
++ rrd->pkt_flg);
++ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++ "RRD err_flg = 0x%08X\n",
++ rrd->err_flg);
++ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++ "RRD vlan_tag = 0x%08X\n",
++ rrd->vlan_tag);
++ }
++
++ /* rrd seems to be bad */
++ if (unlikely(i-- > 0)) {
++ /* rrd may not be DMAed completely */
++ udelay(1);
++ goto chk_rrd;
++ }
++ /* bad rrd */
++ if (netif_msg_rx_err(adapter))
++ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++ "bad RRD\n");
++ /* see if update RFD index */
++ if (rrd->num_buf > 1)
++ atl1_update_rfd_index(adapter, rrd);
++
++ /* update rrd */
++ rrd->xsz.valid = 0;
++ if (++rrd_next_to_clean == rrd_ring->count)
++ rrd_next_to_clean = 0;
++ count++;
++ continue;
++ } else { /* current rrd still not be updated */
++
++ break;
++ }
++rrd_ok:
++ /* clean alloc flag for bad rrd */
++ atl1_clean_alloc_flag(adapter, rrd, 0);
++
++ buffer_info = &rfd_ring->buffer_info[rrd->buf_indx];
++ if (++rfd_ring->next_to_clean == rfd_ring->count)
++ rfd_ring->next_to_clean = 0;
++
++ /* update rrd next to clean */
++ if (++rrd_next_to_clean == rrd_ring->count)
++ rrd_next_to_clean = 0;
++ count++;
++
++ if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
++ if (!(rrd->err_flg &
++ (ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM
++ | ERR_FLAG_LEN))) {
++ /* packet error, don't need upstream */
++ buffer_info->alloced = 0;
++ rrd->xsz.valid = 0;
++ continue;
++ }
++ }
++
++ /* Good Receive */
++ pci_unmap_page(adapter->pdev, buffer_info->dma,
++ buffer_info->length, PCI_DMA_FROMDEVICE);
++ skb = buffer_info->skb;
++ length = le16_to_cpu(rrd->xsz.xsum_sz.pkt_size);
++
++ skb_put(skb, length - ETH_FCS_LEN);
++
++ /* Receive Checksum Offload */
++ atl1_rx_checksum(adapter, rrd, skb);
++ skb->protocol = eth_type_trans(skb, adapter->netdev);
++
++ if (adapter->vlgrp && (rrd->pkt_flg & PACKET_FLAG_VLAN_INS)) {
++ u16 vlan_tag = (rrd->vlan_tag >> 4) |
++ ((rrd->vlan_tag & 7) << 13) |
++ ((rrd->vlan_tag & 8) << 9);
++ vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag);
++ } else
++ netif_rx(skb);
++
++ /* let protocol layer free skb */
++ buffer_info->skb = NULL;
++ buffer_info->alloced = 0;
++ rrd->xsz.valid = 0;
++
++ adapter->netdev->last_rx = jiffies;
++ }
++
++ atomic_set(&rrd_ring->next_to_clean, rrd_next_to_clean);
++
++ atl1_alloc_rx_buffers(adapter);
++
++ /* update mailbox ? */
++ if (count) {
++ u32 tpd_next_to_use;
++ u32 rfd_next_to_use;
++
++ spin_lock(&adapter->mb_lock);
++
++ tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
++ rfd_next_to_use =
++ atomic_read(&adapter->rfd_ring.next_to_use);
++ rrd_next_to_clean =
++ atomic_read(&adapter->rrd_ring.next_to_clean);
++ value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
++ MB_RFD_PROD_INDX_SHIFT) |
++ ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
++ MB_RRD_CONS_INDX_SHIFT) |
++ ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
++ MB_TPD_PROD_INDX_SHIFT);
++ iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
++ spin_unlock(&adapter->mb_lock);
++ }
++}
++
++static void atl1_intr_tx(struct atl1_adapter *adapter)
++{
++ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
++ struct atl1_buffer *buffer_info;
++ u16 sw_tpd_next_to_clean;
++ u16 cmb_tpd_next_to_clean;
++
++ sw_tpd_next_to_clean = atomic_read(&tpd_ring->next_to_clean);
++ cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx);
++
++ while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) {
++ struct tx_packet_desc *tpd;
++
++ tpd = ATL1_TPD_DESC(tpd_ring, sw_tpd_next_to_clean);
++ buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean];
++ if (buffer_info->dma) {
++ 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;
++ }
++
++ if (++sw_tpd_next_to_clean == tpd_ring->count)
++ sw_tpd_next_to_clean = 0;
++ }
++ atomic_set(&tpd_ring->next_to_clean, sw_tpd_next_to_clean);
++
++ if (netif_queue_stopped(adapter->netdev)
++ && netif_carrier_ok(adapter->netdev))
++ netif_wake_queue(adapter->netdev);
++}
++
++static u16 atl1_tpd_avail(struct atl1_tpd_ring *tpd_ring)
++{
++ u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean);
++ u16 next_to_use = atomic_read(&tpd_ring->next_to_use);
++ return ((next_to_clean > next_to_use) ?
++ next_to_clean - next_to_use - 1 :
++ tpd_ring->count + next_to_clean - next_to_use - 1);
++}
++
++static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,
++ struct tx_packet_desc *ptpd)
++{
++ /* spinlock held */
++ u8 hdr_len, ip_off;
++ u32 real_len;
++ int err;
++
++ if (skb_shinfo(skb)->gso_size) {
++ if (skb_header_cloned(skb)) {
++ err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
++ if (unlikely(err))
++ return -1;
++ }
++
++ if (skb->protocol == ntohs(ETH_P_IP)) {
++ struct iphdr *iph = ip_hdr(skb);
++
++ real_len = (((unsigned char *)iph - skb->data) +
++ ntohs(iph->tot_len));
++ if (real_len < skb->len)
++ pskb_trim(skb, real_len);
++ hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
++ if (skb->len == hdr_len) {
++ iph->check = 0;
++ tcp_hdr(skb)->check =
++ ~csum_tcpudp_magic(iph->saddr,
++ iph->daddr, tcp_hdrlen(skb),
++ IPPROTO_TCP, 0);
++ ptpd->word3 |= (iph->ihl & TPD_IPHL_MASK) <<
++ TPD_IPHL_SHIFT;
++ ptpd->word3 |= ((tcp_hdrlen(skb) >> 2) &
++ TPD_TCPHDRLEN_MASK) <<
++ TPD_TCPHDRLEN_SHIFT;
++ ptpd->word3 |= 1 << TPD_IP_CSUM_SHIFT;
++ ptpd->word3 |= 1 << TPD_TCP_CSUM_SHIFT;
++ return 1;
++ }
++
++ iph->check = 0;
++ tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
++ iph->daddr, 0, IPPROTO_TCP, 0);
++ ip_off = (unsigned char *)iph -
++ (unsigned char *) skb_network_header(skb);
++ if (ip_off == 8) /* 802.3-SNAP frame */
++ ptpd->word3 |= 1 << TPD_ETHTYPE_SHIFT;
++ else if (ip_off != 0)
++ return -2;
++
++ ptpd->word3 |= (iph->ihl & TPD_IPHL_MASK) <<
++ TPD_IPHL_SHIFT;
++ ptpd->word3 |= ((tcp_hdrlen(skb) >> 2) &
++ TPD_TCPHDRLEN_MASK) << TPD_TCPHDRLEN_SHIFT;
++ ptpd->word3 |= (skb_shinfo(skb)->gso_size &
++ TPD_MSS_MASK) << TPD_MSS_SHIFT;
++ ptpd->word3 |= 1 << TPD_SEGMENT_EN_SHIFT;
++ return 3;
++ }
++ }
++ return false;
++}
++
++static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
++ struct tx_packet_desc *ptpd)
++{
++ u8 css, cso;
++
++ if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
++ css = (u8) (skb->csum_start - skb_headroom(skb));
++ cso = css + (u8) skb->csum_offset;
++ if (unlikely(css & 0x1)) {
++ /* L1 hardware requires an even number here */
++ if (netif_msg_tx_err(adapter))
++ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++ "payload offset not an even number\n");
++ return -1;
++ }
++ ptpd->word3 |= (css & TPD_PLOADOFFSET_MASK) <<
++ TPD_PLOADOFFSET_SHIFT;
++ ptpd->word3 |= (cso & TPD_CCSUMOFFSET_MASK) <<
++ TPD_CCSUMOFFSET_SHIFT;
++ ptpd->word3 |= 1 << TPD_CUST_CSUM_EN_SHIFT;
++ return true;
++ }
++ return 0;
++}
++
++static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb,
++ struct tx_packet_desc *ptpd)
++{
++ /* spinlock held */
++ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
++ struct atl1_buffer *buffer_info;
++ u16 buf_len = skb->len;
++ struct page *page;
++ unsigned long offset;
++ unsigned int nr_frags;
++ unsigned int f;
++ int retval;
++ u16 next_to_use;
++ u16 data_len;
++ u8 hdr_len;
++
++ buf_len -= skb->data_len;
++ nr_frags = skb_shinfo(skb)->nr_frags;
++ next_to_use = atomic_read(&tpd_ring->next_to_use);
++ buffer_info = &tpd_ring->buffer_info[next_to_use];
++ if (unlikely(buffer_info->skb))
++ BUG();
++ /* put skb in last TPD */
++ buffer_info->skb = NULL;
++
++ retval = (ptpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK;
++ if (retval) {
++ /* TSO */
++ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
++ buffer_info->length = hdr_len;
++ page = virt_to_page(skb->data);
++ offset = (unsigned long)skb->data & ~PAGE_MASK;
++ buffer_info->dma = pci_map_page(adapter->pdev, page,
++ offset, hdr_len,
++ PCI_DMA_TODEVICE);
++
++ if (++next_to_use == tpd_ring->count)
++ next_to_use = 0;
++
++ if (buf_len > hdr_len) {
++ int i, nseg;
++
++ data_len = buf_len - hdr_len;
++ nseg = (data_len + ATL1_MAX_TX_BUF_LEN - 1) /
++ ATL1_MAX_TX_BUF_LEN;
++ for (i = 0; i < nseg; i++) {
++ buffer_info =
++ &tpd_ring->buffer_info[next_to_use];
++ buffer_info->skb = NULL;
++ buffer_info->length =
++ (ATL1_MAX_TX_BUF_LEN >=
++ data_len) ? ATL1_MAX_TX_BUF_LEN : data_len;
++ data_len -= buffer_info->length;
++ page = virt_to_page(skb->data +
++ (hdr_len + i * ATL1_MAX_TX_BUF_LEN));
++ offset = (unsigned long)(skb->data +
++ (hdr_len + i * ATL1_MAX_TX_BUF_LEN)) &
++ ~PAGE_MASK;
++ buffer_info->dma = pci_map_page(adapter->pdev,
++ page, offset, buffer_info->length,
++ PCI_DMA_TODEVICE);
++ if (++next_to_use == tpd_ring->count)
++ next_to_use = 0;
++ }
++ }
++ } else {
++ /* not TSO */
++ buffer_info->length = buf_len;
++ page = virt_to_page(skb->data);
++ offset = (unsigned long)skb->data & ~PAGE_MASK;
++ buffer_info->dma = pci_map_page(adapter->pdev, page,
++ offset, buf_len, PCI_DMA_TODEVICE);
++ if (++next_to_use == tpd_ring->count)
++ next_to_use = 0;
++ }
++
++ for (f = 0; f < nr_frags; f++) {
++ struct skb_frag_struct *frag;
++ u16 i, nseg;
++
++ frag = &skb_shinfo(skb)->frags[f];
++ buf_len = frag->size;
++
++ nseg = (buf_len + ATL1_MAX_TX_BUF_LEN - 1) /
++ ATL1_MAX_TX_BUF_LEN;
++ for (i = 0; i < nseg; i++) {
++ buffer_info = &tpd_ring->buffer_info[next_to_use];
++ if (unlikely(buffer_info->skb))
++ BUG();
++ buffer_info->skb = NULL;
++ buffer_info->length = (buf_len > ATL1_MAX_TX_BUF_LEN) ?
++ ATL1_MAX_TX_BUF_LEN : buf_len;
++ buf_len -= buffer_info->length;
++ buffer_info->dma = pci_map_page(adapter->pdev,
++ frag->page,
++ frag->page_offset + (i * ATL1_MAX_TX_BUF_LEN),
++ buffer_info->length, PCI_DMA_TODEVICE);
++
++ if (++next_to_use == tpd_ring->count)
++ next_to_use = 0;
++ }
++ }
++
++ /* last tpd's buffer-info */
++ buffer_info->skb = skb;
++}
++
++static void atl1_tx_queue(struct atl1_adapter *adapter, u16 count,
++ struct tx_packet_desc *ptpd)
++{
++ /* spinlock held */
++ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
++ struct atl1_buffer *buffer_info;
++ struct tx_packet_desc *tpd;
++ u16 j;
++ u32 val;
++ u16 next_to_use = (u16) atomic_read(&tpd_ring->next_to_use);
++
++ for (j = 0; j < count; j++) {
++ buffer_info = &tpd_ring->buffer_info[next_to_use];
++ tpd = ATL1_TPD_DESC(&adapter->tpd_ring, next_to_use);
++ if (tpd != ptpd)
++ memcpy(tpd, ptpd, sizeof(struct tx_packet_desc));
++ tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
++ tpd->word2 = (cpu_to_le16(buffer_info->length) &
++ TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT;
++
++ /*
++ * if this is the first packet in a TSO chain, set
++ * TPD_HDRFLAG, otherwise, clear it.
++ */
++ val = (tpd->word3 >> TPD_SEGMENT_EN_SHIFT) &
++ TPD_SEGMENT_EN_MASK;
++ if (val) {
++ if (!j)
++ tpd->word3 |= 1 << TPD_HDRFLAG_SHIFT;
++ else
++ tpd->word3 &= ~(1 << TPD_HDRFLAG_SHIFT);
++ }
++
++ if (j == (count - 1))
++ tpd->word3 |= 1 << TPD_EOP_SHIFT;
++
++ if (++next_to_use == tpd_ring->count)
++ next_to_use = 0;
++ }
++ /*
++ * Force memory writes to complete before letting h/w
++ * know there are new descriptors to fetch. (Only
++ * applicable for weak-ordered memory model archs,
++ * such as IA-64).
++ */
++ wmb();
++
++ atomic_set(&tpd_ring->next_to_use, next_to_use);
++}
++
++static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
++ int len = skb->len;
++ int tso;
++ int count = 1;
++ int ret_val;
++ struct tx_packet_desc *ptpd;
++ u16 frag_size;
++ u16 vlan_tag;
++ unsigned long flags;
++ unsigned int nr_frags = 0;
++ unsigned int mss = 0;
++ unsigned int f;
++ unsigned int proto_hdr_len;
++
++ len -= skb->data_len;
++
++ if (unlikely(skb->len <= 0)) {
++ dev_kfree_skb_any(skb);
++ return NETDEV_TX_OK;
++ }
++
++ nr_frags = skb_shinfo(skb)->nr_frags;
++ for (f = 0; f < nr_frags; f++) {
++ frag_size = skb_shinfo(skb)->frags[f].size;
++ if (frag_size)
++ count += (frag_size + ATL1_MAX_TX_BUF_LEN - 1) /
++ ATL1_MAX_TX_BUF_LEN;
++ }
++
++ mss = skb_shinfo(skb)->gso_size;
++ if (mss) {
++ if (skb->protocol == ntohs(ETH_P_IP)) {
++ proto_hdr_len = (skb_transport_offset(skb) +
++ tcp_hdrlen(skb));
++ if (unlikely(proto_hdr_len > len)) {
++ dev_kfree_skb_any(skb);
++ return NETDEV_TX_OK;
++ }
++ /* need additional TPD ? */
++ if (proto_hdr_len != len)
++ count += (len - proto_hdr_len +
++ ATL1_MAX_TX_BUF_LEN - 1) /
++ ATL1_MAX_TX_BUF_LEN;
++ }
++ }
++
++ if (!spin_trylock_irqsave(&adapter->lock, flags)) {
++ /* Can't get lock - tell upper layer to requeue */
++ if (netif_msg_tx_queued(adapter))
++ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++ "tx locked\n");
++ return NETDEV_TX_LOCKED;
++ }
++
++ if (atl1_tpd_avail(&adapter->tpd_ring) < count) {
++ /* not enough descriptors */
++ netif_stop_queue(netdev);
++ spin_unlock_irqrestore(&adapter->lock, flags);
++ if (netif_msg_tx_queued(adapter))
++ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++ "tx busy\n");
++ return NETDEV_TX_BUSY;
++ }
++
++ ptpd = ATL1_TPD_DESC(tpd_ring,
++ (u16) atomic_read(&tpd_ring->next_to_use));
++ memset(ptpd, 0, sizeof(struct tx_packet_desc));
++
++ if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
++ vlan_tag = vlan_tx_tag_get(skb);
++ vlan_tag = (vlan_tag << 4) | (vlan_tag >> 13) |
++ ((vlan_tag >> 9) & 0x8);
++ ptpd->word3 |= 1 << TPD_INS_VL_TAG_SHIFT;
++ ptpd->word3 |= (vlan_tag & TPD_VL_TAGGED_MASK) <<
++ TPD_VL_TAGGED_SHIFT;
++ }
++
++ tso = atl1_tso(adapter, skb, ptpd);
++ if (tso < 0) {
++ spin_unlock_irqrestore(&adapter->lock, flags);
++ dev_kfree_skb_any(skb);
++ return NETDEV_TX_OK;
++ }
++
++ if (!tso) {
++ ret_val = atl1_tx_csum(adapter, skb, ptpd);
++ if (ret_val < 0) {
++ spin_unlock_irqrestore(&adapter->lock, flags);
++ dev_kfree_skb_any(skb);
++ return NETDEV_TX_OK;
++ }
++ }
++
++ atl1_tx_map(adapter, skb, ptpd);
++ atl1_tx_queue(adapter, count, ptpd);
++ atl1_update_mailbox(adapter);
++ spin_unlock_irqrestore(&adapter->lock, flags);
++ netdev->trans_start = jiffies;
++ return NETDEV_TX_OK;
++}
++
++/*
++ * atl1_intr - Interrupt Handler
++ * @irq: interrupt number
++ * @data: pointer to a network interface device structure
++ * @pt_regs: CPU registers structure
++ */
++static irqreturn_t atl1_intr(int irq, void *data)
++{
++ struct atl1_adapter *adapter = netdev_priv(data);
++ u32 status;
++ int max_ints = 10;
++
++ status = adapter->cmb.cmb->int_stats;
++ if (!status)
++ return IRQ_NONE;
++
++ do {
++ /* clear CMB interrupt status at once */
++ adapter->cmb.cmb->int_stats = 0;
++
++ if (status & ISR_GPHY) /* clear phy status */
++ atlx_clear_phy_int(adapter);
++
++ /* clear ISR status, and Enable CMB DMA/Disable Interrupt */
++ iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR);
++
++ /* check if SMB intr */
++ if (status & ISR_SMB)
++ atl1_inc_smb(adapter);
++
++ /* check if PCIE PHY Link down */
++ if (status & ISR_PHY_LINKDOWN) {
++ if (netif_msg_intr(adapter))
++ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++ "pcie phy link down %x\n", status);
++ if (netif_running(adapter->netdev)) { /* reset MAC */
++ iowrite32(0, adapter->hw.hw_addr + REG_IMR);
++ schedule_work(&adapter->pcie_dma_to_rst_task);
++ return IRQ_HANDLED;
++ }
++ }
++
++ /* check if DMA read/write error ? */
++ if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
++ if (netif_msg_intr(adapter))
++ dev_printk(KERN_DEBUG, &adapter->pdev->dev,
++ "pcie DMA r/w error (status = 0x%x)\n",
++ status);
++ iowrite32(0, adapter->hw.hw_addr + REG_IMR);
++ schedule_work(&adapter->pcie_dma_to_rst_task);
++ return IRQ_HANDLED;
++ }
++
++ /* link event */
++ if (status & ISR_GPHY) {
++ adapter->soft_stats.tx_carrier_errors++;
++ atl1_check_for_link(adapter);
++ }
++
++ /* transmit event */
++ if (status & ISR_CMB_TX)
++ atl1_intr_tx(adapter);
++
++ /* rx exception */
++ if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN |
++ ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
++ ISR_HOST_RRD_OV | ISR_CMB_RX))) {
++ if (status & (ISR_RXF_OV | ISR_RFD_UNRUN |
++ ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
++ ISR_HOST_RRD_OV))
++ if (netif_msg_intr(adapter))
++ dev_printk(KERN_DEBUG,
++ &adapter->pdev->dev,
++ "rx exception, ISR = 0x%x\n",
++ status);
++ atl1_intr_rx(adapter);
++ }
++
++ if (--max_ints < 0)
++ break;
++
++ } while ((status = adapter->cmb.cmb->int_stats));
++
++ /* re-enable Interrupt */
++ iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR);
++ return IRQ_HANDLED;
++}
++
++/*
++ * atl1_watchdog - Timer Call-back
++ * @data: pointer to netdev cast into an unsigned long
++ */
++static void atl1_watchdog(unsigned long data)
++{
++ struct atl1_adapter *adapter = (struct atl1_adapter *)data;
++
++ /* Reset the timer */
++ mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
++}
++
++/*
++ * atl1_phy_config - Timer Call-back
++ * @data: pointer to netdev cast into an unsigned long
++ */
++static void atl1_phy_config(unsigned long data)
++{
++ struct atl1_adapter *adapter = (struct atl1_adapter *)data;
++ struct atl1_hw *hw = &adapter->hw;
++ unsigned long flags;
++
++ spin_lock_irqsave(&adapter->lock, flags);
++ adapter->phy_timer_pending = false;
++ atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
++ atl1_write_phy_reg(hw, MII_ATLX_CR, hw->mii_1000t_ctrl_reg);
++ atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN);
++ spin_unlock_irqrestore(&adapter->lock, flags);
++}
++
++/*
++ * Orphaned vendor comment left intact here:
++ * <vendor comment>
++ * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT
++ * will assert. We do soft reset <0x1400=1> according
++ * with the SPEC. BUT, it seemes that PCIE or DMA
++ * state-machine will not be reset. DMAR_TO_INT will
++ * assert again and again.
++ * </vendor comment>
++ */
++
++static int atl1_reset(struct atl1_adapter *adapter)
++{
++ int ret;
++ ret = atl1_reset_hw(&adapter->hw);
++ if (ret)
++ return ret;
++ return atl1_init_hw(&adapter->hw);
++}
++
++static s32 atl1_up(struct atl1_adapter *adapter)
++{
++ struct net_device *netdev = adapter->netdev;
++ int err;
++ int irq_flags = IRQF_SAMPLE_RANDOM;
++
++ /* hardware has been reset, we need to reload some things */
++ atlx_set_multi(netdev);
++ atl1_init_ring_ptrs(adapter);
++ atlx_restore_vlan(adapter);
++ err = atl1_alloc_rx_buffers(adapter);
++ if (unlikely(!err))
++ /* no RX BUFFER allocated */
++ return -ENOMEM;
++
++ if (unlikely(atl1_configure(adapter))) {
++ err = -EIO;
++ goto err_up;
++ }
++
++ err = pci_enable_msi(adapter->pdev);
++ if (err) {
++ if (netif_msg_ifup(adapter))
++ dev_info(&adapter->pdev->dev,
++ "Unable to enable MSI: %d\n", err);
++ irq_flags |= IRQF_SHARED;
++ }
++
++ err = request_irq(adapter->pdev->irq, &atl1_intr, irq_flags,
++ netdev->name, netdev);
++ if (unlikely(err))
++ goto err_up;
++
++ mod_timer(&adapter->watchdog_timer, jiffies);
++ atlx_irq_enable(adapter);
++ atl1_check_link(adapter);
++ return 0;
++
++err_up:
++ pci_disable_msi(adapter->pdev);
++ /* free rx_buffers */
++ atl1_clean_rx_ring(adapter);
++ return err;
++}
++
++static void atl1_down(struct atl1_adapter *adapter)
++{
++ struct net_device *netdev = adapter->netdev;
++
++ del_timer_sync(&adapter->watchdog_timer);
++ del_timer_sync(&adapter->phy_config_timer);
++ adapter->phy_timer_pending = false;
++
++ atlx_irq_disable(adapter);
++ free_irq(adapter->pdev->irq, netdev);
++ pci_disable_msi(adapter->pdev);
++ atl1_reset_hw(&adapter->hw);
++ adapter->cmb.cmb->int_stats = 0;
++
++ adapter->link_speed = SPEED_0;
++ adapter->link_duplex = -1;
++ netif_carrier_off(netdev);
++ netif_stop_queue(netdev);
++
++ atl1_clean_tx_ring(adapter);
++ atl1_clean_rx_ring(adapter);
++}
++
++static void atl1_tx_timeout_task(struct work_struct *work)
++{
++ struct atl1_adapter *adapter =
++ container_of(work, struct atl1_adapter, tx_timeout_task);
++ struct net_device *netdev = adapter->netdev;
++
++ netif_device_detach(netdev);
++ atl1_down(adapter);
++ atl1_up(adapter);
++ netif_device_attach(netdev);
++}
++
++/*
++ * atl1_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 atl1_change_mtu(struct net_device *netdev, int new_mtu)
++{
++ struct atl1_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;
++ }
++
++ adapter->hw.max_frame_size = max_frame;
++ adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3;
++ adapter->rx_buffer_len = (max_frame + 7) & ~7;
++ adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8;
++
++ netdev->mtu = new_mtu;
++ if ((old_mtu != new_mtu) && netif_running(netdev)) {
++ atl1_down(adapter);
++ atl1_up(adapter);
++ }
++
++ return 0;
++}
++
++/*
++ * atl1_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 atl1_open(struct net_device *netdev)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ int err;
++
++ /* allocate transmit descriptors */
++ err = atl1_setup_ring_resources(adapter);
++ if (err)
++ return err;
++
++ err = atl1_up(adapter);
++ if (err)
++ goto err_up;
++
++ return 0;
++
++err_up:
++ atl1_reset(adapter);
++ return err;
++}
++
++/*
++ * atl1_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 atl1_close(struct net_device *netdev)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ atl1_down(adapter);
++ atl1_free_ring_resources(adapter);
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int atl1_suspend(struct pci_dev *pdev, pm_message_t state)
++{
++ struct net_device *netdev = pci_get_drvdata(pdev);
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ struct atl1_hw *hw = &adapter->hw;
++ u32 ctrl = 0;
++ u32 wufc = adapter->wol;
++
++ netif_device_detach(netdev);
++ if (netif_running(netdev))
++ atl1_down(adapter);
++
++ atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
++ atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
++ if (ctrl & BMSR_LSTATUS)
++ wufc &= ~ATLX_WUFC_LNKC;
++
++ /* reduce speed to 10/100M */
++ if (wufc) {
++ atl1_phy_enter_power_saving(hw);
++ /* if resume, let driver to re- setup link */
++ hw->phy_configured = false;
++ atl1_set_mac_addr(hw);
++ atlx_set_multi(netdev);
++
++ ctrl = 0;
++ /* turn on magic packet wol */
++ if (wufc & ATLX_WUFC_MAG)
++ ctrl = WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
++
++ /* turn on Link change WOL */
++ if (wufc & ATLX_WUFC_LNKC)
++ ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN);
++ iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL);
++
++ /* turn on all-multi mode if wake on multicast is enabled */
++ ctrl = ioread32(hw->hw_addr + REG_MAC_CTRL);
++ ctrl &= ~MAC_CTRL_DBG;
++ ctrl &= ~MAC_CTRL_PROMIS_EN;
++ if (wufc & ATLX_WUFC_MC)
++ ctrl |= MAC_CTRL_MC_ALL_EN;
++ else
++ ctrl &= ~MAC_CTRL_MC_ALL_EN;
++
++ /* turn on broadcast mode if wake on-BC is enabled */
++ if (wufc & ATLX_WUFC_BC)
++ ctrl |= MAC_CTRL_BC_EN;
++ else
++ ctrl &= ~MAC_CTRL_BC_EN;
++
++ /* enable RX */
++ ctrl |= MAC_CTRL_RX_EN;
++ iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL);
++ pci_enable_wake(pdev, PCI_D3hot, 1);
++ pci_enable_wake(pdev, PCI_D3cold, 1);
++ } else {
++ iowrite32(0, hw->hw_addr + REG_WOL_CTRL);
++ pci_enable_wake(pdev, PCI_D3hot, 0);
++ pci_enable_wake(pdev, PCI_D3cold, 0);
++ }
++
++ pci_save_state(pdev);
++ pci_disable_device(pdev);
++
++ pci_set_power_state(pdev, PCI_D3hot);
++
++ return 0;
++}
++
++static int atl1_resume(struct pci_dev *pdev)
++{
++ struct net_device *netdev = pci_get_drvdata(pdev);
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ u32 err;
++
++ pci_set_power_state(pdev, PCI_D0);
++ pci_restore_state(pdev);
++
++ /* FIXME: check and handle */
++ err = pci_enable_device(pdev);
++ pci_enable_wake(pdev, PCI_D3hot, 0);
++ pci_enable_wake(pdev, PCI_D3cold, 0);
++
++ iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL);
++ atl1_reset(adapter);
++
++ if (netif_running(netdev))
++ atl1_up(adapter);
++ netif_device_attach(netdev);
++
++ atl1_via_workaround(adapter);
++
++ return 0;
++}
++#else
++#define atl1_suspend NULL
++#define atl1_resume NULL
++#endif
++
++#ifdef CONFIG_NET_POLL_CONTROLLER
++static void atl1_poll_controller(struct net_device *netdev)
++{
++ disable_irq(netdev->irq);
++ atl1_intr(netdev->irq, netdev);
++ enable_irq(netdev->irq);
++}
++#endif
++
++/*
++ * atl1_probe - Device Initialization Routine
++ * @pdev: PCI device information struct
++ * @ent: entry in atl1_pci_tbl
++ *
++ * Returns 0 on success, negative on failure
++ *
++ * atl1_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 atl1_probe(struct pci_dev *pdev,
++ const struct pci_device_id *ent)
++{
++ struct net_device *netdev;
++ struct atl1_adapter *adapter;
++ static int cards_found = 0;
++ int err;
++
++ err = pci_enable_device(pdev);
++ if (err)
++ return err;
++
++ /*
++ * The atl1 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.
++ */
++ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
++ if (err) {
++ dev_err(&pdev->dev, "no usable DMA configuration\n");
++ goto err_dma;
++ }
++ /*
++ * Mark all PCI regions associated with PCI device
++ * pdev as being reserved by owner atl1_driver_name
++ */
++ err = pci_request_regions(pdev, ATLX_DRIVER_NAME);
++ if (err)
++ goto err_request_regions;
++
++ /*
++ * Enables bus-mastering on the device and calls
++ * pcibios_set_master to do the needed arch specific settings
++ */
++ pci_set_master(pdev);
++
++ netdev = alloc_etherdev(sizeof(struct atl1_adapter));
++ if (!netdev) {
++ err = -ENOMEM;
++ goto err_alloc_etherdev;
++ }
++ SET_NETDEV_DEV(netdev, &pdev->dev);
++
++ pci_set_drvdata(pdev, netdev);
++ adapter = netdev_priv(netdev);
++ adapter->netdev = netdev;
++ adapter->pdev = pdev;
++ adapter->hw.back = adapter;
++ adapter->msg_enable = netif_msg_init(debug, atl1_default_msg);
++
++ adapter->hw.hw_addr = pci_iomap(pdev, 0, 0);
++ if (!adapter->hw.hw_addr) {
++ err = -EIO;
++ goto err_pci_iomap;
++ }
++ /* get device revision number */
++ adapter->hw.dev_rev = ioread16(adapter->hw.hw_addr +
++ (REG_MASTER_CTRL + 2));
++ if (netif_msg_probe(adapter))
++ dev_info(&pdev->dev, "version %s\n", ATLX_DRIVER_VERSION);
++
++ /* set default ring resource counts */
++ adapter->rfd_ring.count = adapter->rrd_ring.count = ATL1_DEFAULT_RFD;
++ adapter->tpd_ring.count = ATL1_DEFAULT_TPD;
++
++ adapter->mii.dev = netdev;
++ adapter->mii.mdio_read = mdio_read;
++ adapter->mii.mdio_write = mdio_write;
++ adapter->mii.phy_id_mask = 0x1f;
++ adapter->mii.reg_num_mask = 0x1f;
++
++ netdev->open = &atl1_open;
++ netdev->stop = &atl1_close;
++ netdev->hard_start_xmit = &atl1_xmit_frame;
++ netdev->get_stats = &atlx_get_stats;
++ netdev->set_multicast_list = &atlx_set_multi;
++ netdev->set_mac_address = &atl1_set_mac;
++ netdev->change_mtu = &atl1_change_mtu;
++ netdev->do_ioctl = &atlx_ioctl;
++ netdev->tx_timeout = &atlx_tx_timeout;
++ netdev->watchdog_timeo = 5 * HZ;
++#ifdef CONFIG_NET_POLL_CONTROLLER
++ netdev->poll_controller = atl1_poll_controller;
++#endif
++ netdev->vlan_rx_register = atlx_vlan_rx_register;
++
++ netdev->ethtool_ops = &atl1_ethtool_ops;
++ adapter->bd_number = cards_found;
++
++ /* setup the private structure */
++ err = atl1_sw_init(adapter);
++ if (err)
++ goto err_common;
++
++ netdev->features = NETIF_F_HW_CSUM;
++ netdev->features |= NETIF_F_SG;
++ netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
++ netdev->features |= NETIF_F_TSO;
++ netdev->features |= NETIF_F_LLTX;
++
++ /*
++ * patch for some L1 of old version,
++ * the final version of L1 may not need these
++ * patches
++ */
++ /* atl1_pcie_patch(adapter); */
++
++ /* really reset GPHY core */
++ iowrite16(0, adapter->hw.hw_addr + REG_PHY_ENABLE);
++
++ /*
++ * reset the controller to
++ * put the device in a known good starting state
++ */
++ if (atl1_reset_hw(&adapter->hw)) {
++ err = -EIO;
++ goto err_common;
++ }
++
++ /* copy the MAC address out of the EEPROM */
++ atl1_read_mac_addr(&adapter->hw);
++ memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
++
++ if (!is_valid_ether_addr(netdev->dev_addr)) {
++ err = -EIO;
++ goto err_common;
++ }
++
++ atl1_check_options(adapter);
++
++ /* pre-init the MAC, and setup link */
++ err = atl1_init_hw(&adapter->hw);
++ if (err) {
++ err = -EIO;
++ goto err_common;
++ }
++
++ atl1_pcie_patch(adapter);
++ /* assume we have no link for now */
++ netif_carrier_off(netdev);
++ netif_stop_queue(netdev);
++
++ init_timer(&adapter->watchdog_timer);
++ adapter->watchdog_timer.function = &atl1_watchdog;
++ adapter->watchdog_timer.data = (unsigned long)adapter;
++
++ init_timer(&adapter->phy_config_timer);
++ adapter->phy_config_timer.function = &atl1_phy_config;
++ adapter->phy_config_timer.data = (unsigned long)adapter;
++ adapter->phy_timer_pending = false;
++
++ INIT_WORK(&adapter->tx_timeout_task, atl1_tx_timeout_task);
++
++ INIT_WORK(&adapter->link_chg_task, atlx_link_chg_task);
++
++ INIT_WORK(&adapter->pcie_dma_to_rst_task, atl1_tx_timeout_task);
++
++ err = register_netdev(netdev);
++ if (err)
++ goto err_common;
++
++ cards_found++;
++ atl1_via_workaround(adapter);
++ return 0;
++
++err_common:
++ pci_iounmap(pdev, adapter->hw.hw_addr);
++err_pci_iomap:
++ free_netdev(netdev);
++err_alloc_etherdev:
++ pci_release_regions(pdev);
++err_dma:
++err_request_regions:
++ pci_disable_device(pdev);
++ return err;
++}
++
++/*
++ * atl1_remove - Device Removal Routine
++ * @pdev: PCI device information struct
++ *
++ * atl1_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 atl1_remove(struct pci_dev *pdev)
++{
++ struct net_device *netdev = pci_get_drvdata(pdev);
++ struct atl1_adapter *adapter;
++ /* Device not available. Return. */
++ if (!netdev)
++ return;
++
++ adapter = netdev_priv(netdev);
++
++ /*
++ * Some atl1 boards lack persistent storage for their MAC, and get it
++ * from the BIOS during POST. If we've been messing with the MAC
++ * address, we need to save the permanent one.
++ */
++ if (memcmp(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN)) {
++ memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr,
++ ETH_ALEN);
++ atl1_set_mac_addr(&adapter->hw);
++ }
++
++ iowrite16(0, adapter->hw.hw_addr + REG_PHY_ENABLE);
++ unregister_netdev(netdev);
++ pci_iounmap(pdev, adapter->hw.hw_addr);
++ pci_release_regions(pdev);
++ free_netdev(netdev);
++ pci_disable_device(pdev);
++}
++
++static struct pci_driver atl1_driver = {
++ .name = ATLX_DRIVER_NAME,
++ .id_table = atl1_pci_tbl,
++ .probe = atl1_probe,
++ .remove = __devexit_p(atl1_remove),
++ .suspend = atl1_suspend,
++ .resume = atl1_resume
++};
++
++/*
++ * atl1_exit_module - Driver Exit Cleanup Routine
++ *
++ * atl1_exit_module is called just before the driver is removed
++ * from memory.
++ */
++static void __exit atl1_exit_module(void)
++{
++ pci_unregister_driver(&atl1_driver);
++}
++
++/*
++ * atl1_init_module - Driver Registration Routine
++ *
++ * atl1_init_module is the first routine called when the driver is
++ * loaded. All it does is register with the PCI subsystem.
++ */
++static int __init atl1_init_module(void)
++{
++ return pci_register_driver(&atl1_driver);
++}
++
++module_init(atl1_init_module);
++module_exit(atl1_exit_module);
++
++struct atl1_stats {
++ char stat_string[ETH_GSTRING_LEN];
++ int sizeof_stat;
++ int stat_offset;
++};
++
++#define ATL1_STAT(m) \
++ sizeof(((struct atl1_adapter *)0)->m), offsetof(struct atl1_adapter, m)
++
++static struct atl1_stats atl1_gstrings_stats[] = {
++ {"rx_packets", ATL1_STAT(soft_stats.rx_packets)},
++ {"tx_packets", ATL1_STAT(soft_stats.tx_packets)},
++ {"rx_bytes", ATL1_STAT(soft_stats.rx_bytes)},
++ {"tx_bytes", ATL1_STAT(soft_stats.tx_bytes)},
++ {"rx_errors", ATL1_STAT(soft_stats.rx_errors)},
++ {"tx_errors", ATL1_STAT(soft_stats.tx_errors)},
++ {"rx_dropped", ATL1_STAT(net_stats.rx_dropped)},
++ {"tx_dropped", ATL1_STAT(net_stats.tx_dropped)},
++ {"multicast", ATL1_STAT(soft_stats.multicast)},
++ {"collisions", ATL1_STAT(soft_stats.collisions)},
++ {"rx_length_errors", ATL1_STAT(soft_stats.rx_length_errors)},
++ {"rx_over_errors", ATL1_STAT(soft_stats.rx_missed_errors)},
++ {"rx_crc_errors", ATL1_STAT(soft_stats.rx_crc_errors)},
++ {"rx_frame_errors", ATL1_STAT(soft_stats.rx_frame_errors)},
++ {"rx_fifo_errors", ATL1_STAT(soft_stats.rx_fifo_errors)},
++ {"rx_missed_errors", ATL1_STAT(soft_stats.rx_missed_errors)},
++ {"tx_aborted_errors", ATL1_STAT(soft_stats.tx_aborted_errors)},
++ {"tx_carrier_errors", ATL1_STAT(soft_stats.tx_carrier_errors)},
++ {"tx_fifo_errors", ATL1_STAT(soft_stats.tx_fifo_errors)},
++ {"tx_window_errors", ATL1_STAT(soft_stats.tx_window_errors)},
++ {"tx_abort_exce_coll", ATL1_STAT(soft_stats.excecol)},
++ {"tx_abort_late_coll", ATL1_STAT(soft_stats.latecol)},
++ {"tx_deferred_ok", ATL1_STAT(soft_stats.deffer)},
++ {"tx_single_coll_ok", ATL1_STAT(soft_stats.scc)},
++ {"tx_multi_coll_ok", ATL1_STAT(soft_stats.mcc)},
++ {"tx_underun", ATL1_STAT(soft_stats.tx_underun)},
++ {"tx_trunc", ATL1_STAT(soft_stats.tx_trunc)},
++ {"tx_pause", ATL1_STAT(soft_stats.tx_pause)},
++ {"rx_pause", ATL1_STAT(soft_stats.rx_pause)},
++ {"rx_rrd_ov", ATL1_STAT(soft_stats.rx_rrd_ov)},
++ {"rx_trunc", ATL1_STAT(soft_stats.rx_trunc)}
++};
++
++static void atl1_get_ethtool_stats(struct net_device *netdev,
++ struct ethtool_stats *stats, u64 *data)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ int i;
++ char *p;
++
++ for (i = 0; i < ARRAY_SIZE(atl1_gstrings_stats); i++) {
++ p = (char *)adapter+atl1_gstrings_stats[i].stat_offset;
++ data[i] = (atl1_gstrings_stats[i].sizeof_stat ==
++ sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
++ }
++
++}
++
++static int atl1_get_sset_count(struct net_device *netdev, int sset)
++{
++ switch (sset) {
++ case ETH_SS_STATS:
++ return ARRAY_SIZE(atl1_gstrings_stats);
++ default:
++ return -EOPNOTSUPP;
++ }
++}
++
++static int atl1_get_settings(struct net_device *netdev,
++ struct ethtool_cmd *ecmd)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ struct atl1_hw *hw = &adapter->hw;
++
++ ecmd->supported = (SUPPORTED_10baseT_Half |
++ SUPPORTED_10baseT_Full |
++ SUPPORTED_100baseT_Half |
++ SUPPORTED_100baseT_Full |
++ SUPPORTED_1000baseT_Full |
++ SUPPORTED_Autoneg | SUPPORTED_TP);
++ ecmd->advertising = ADVERTISED_TP;
++ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
++ hw->media_type == MEDIA_TYPE_1000M_FULL) {
++ ecmd->advertising |= ADVERTISED_Autoneg;
++ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR) {
++ ecmd->advertising |= ADVERTISED_Autoneg;
++ ecmd->advertising |=
++ (ADVERTISED_10baseT_Half |
++ ADVERTISED_10baseT_Full |
++ ADVERTISED_100baseT_Half |
++ ADVERTISED_100baseT_Full |
++ ADVERTISED_1000baseT_Full);
++ } else
++ ecmd->advertising |= (ADVERTISED_1000baseT_Full);
++ }
++ ecmd->port = PORT_TP;
++ ecmd->phy_address = 0;
++ ecmd->transceiver = XCVR_INTERNAL;
++
++ if (netif_carrier_ok(adapter->netdev)) {
++ u16 link_speed, link_duplex;
++ atl1_get_speed_and_duplex(hw, &link_speed, &link_duplex);
++ ecmd->speed = link_speed;
++ if (link_duplex == FULL_DUPLEX)
++ ecmd->duplex = DUPLEX_FULL;
++ else
++ ecmd->duplex = DUPLEX_HALF;
++ } else {
++ ecmd->speed = -1;
++ ecmd->duplex = -1;
++ }
++ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
++ hw->media_type == MEDIA_TYPE_1000M_FULL)
++ ecmd->autoneg = AUTONEG_ENABLE;
++ else
++ ecmd->autoneg = AUTONEG_DISABLE;
++
++ return 0;
++}
++
++static int atl1_set_settings(struct net_device *netdev,
++ struct ethtool_cmd *ecmd)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ struct atl1_hw *hw = &adapter->hw;
++ u16 phy_data;
++ int ret_val = 0;
++ u16 old_media_type = hw->media_type;
++
++ if (netif_running(adapter->netdev)) {
++ if (netif_msg_link(adapter))
++ dev_dbg(&adapter->pdev->dev,
++ "ethtool shutting down adapter\n");
++ atl1_down(adapter);
++ }
++
++ if (ecmd->autoneg == AUTONEG_ENABLE)
++ hw->media_type = MEDIA_TYPE_AUTO_SENSOR;
++ 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");
++ ret_val = -EINVAL;
++ goto exit_sset;
++ }
++ hw->media_type = MEDIA_TYPE_1000M_FULL;
++ } else if (ecmd->speed == SPEED_100) {
++ if (ecmd->duplex == DUPLEX_FULL)
++ hw->media_type = MEDIA_TYPE_100M_FULL;
++ else
++ hw->media_type = MEDIA_TYPE_100M_HALF;
++ } else {
++ if (ecmd->duplex == DUPLEX_FULL)
++ hw->media_type = MEDIA_TYPE_10M_FULL;
++ else
++ hw->media_type = MEDIA_TYPE_10M_HALF;
++ }
++ }
++ switch (hw->media_type) {
++ case MEDIA_TYPE_AUTO_SENSOR:
++ ecmd->advertising =
++ ADVERTISED_10baseT_Half |
++ ADVERTISED_10baseT_Full |
++ ADVERTISED_100baseT_Half |
++ ADVERTISED_100baseT_Full |
++ ADVERTISED_1000baseT_Full |
++ ADVERTISED_Autoneg | ADVERTISED_TP;
++ break;
++ case MEDIA_TYPE_1000M_FULL:
++ ecmd->advertising =
++ ADVERTISED_1000baseT_Full |
++ ADVERTISED_Autoneg | ADVERTISED_TP;
++ break;
++ default:
++ ecmd->advertising = 0;
++ break;
++ }
++ if (atl1_phy_setup_autoneg_adv(hw)) {
++ ret_val = -EINVAL;
++ if (netif_msg_link(adapter))
++ dev_warn(&adapter->pdev->dev,
++ "invalid ethtool speed/duplex setting\n");
++ goto exit_sset;
++ }
++ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
++ hw->media_type == MEDIA_TYPE_1000M_FULL)
++ phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
++ else {
++ switch (hw->media_type) {
++ case MEDIA_TYPE_100M_FULL:
++ phy_data =
++ MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
++ MII_CR_RESET;
++ break;
++ case MEDIA_TYPE_100M_HALF:
++ phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
++ break;
++ case MEDIA_TYPE_10M_FULL:
++ phy_data =
++ MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
++ break;
++ default:
++ /* MEDIA_TYPE_10M_HALF: */
++ phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
++ break;
++ }
++ }
++ atl1_write_phy_reg(hw, MII_BMCR, phy_data);
++exit_sset:
++ if (ret_val)
++ hw->media_type = old_media_type;
++
++ if (netif_running(adapter->netdev)) {
++ if (netif_msg_link(adapter))
++ dev_dbg(&adapter->pdev->dev,
++ "ethtool starting adapter\n");
++ atl1_up(adapter);
++ } else if (!ret_val) {
++ if (netif_msg_link(adapter))
++ dev_dbg(&adapter->pdev->dev,
++ "ethtool resetting adapter\n");
++ atl1_reset(adapter);
++ }
++ return ret_val;
++}
++
++static void atl1_get_drvinfo(struct net_device *netdev,
++ struct ethtool_drvinfo *drvinfo)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++
++ strncpy(drvinfo->driver, ATLX_DRIVER_NAME, sizeof(drvinfo->driver));
++ strncpy(drvinfo->version, ATLX_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->eedump_len = ATL1_EEDUMP_LEN;
++}
++
++static void atl1_get_wol(struct net_device *netdev,
++ struct ethtool_wolinfo *wol)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++
++ wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
++ wol->wolopts = 0;
++ if (adapter->wol & ATLX_WUFC_EX)
++ wol->wolopts |= WAKE_UCAST;
++ if (adapter->wol & ATLX_WUFC_MC)
++ wol->wolopts |= WAKE_MCAST;
++ if (adapter->wol & ATLX_WUFC_BC)
++ wol->wolopts |= WAKE_BCAST;
++ if (adapter->wol & ATLX_WUFC_MAG)
++ wol->wolopts |= WAKE_MAGIC;
++ return;
++}
++
++static int atl1_set_wol(struct net_device *netdev,
++ struct ethtool_wolinfo *wol)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++
++ if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
++ return -EOPNOTSUPP;
++ adapter->wol = 0;
++ if (wol->wolopts & WAKE_UCAST)
++ adapter->wol |= ATLX_WUFC_EX;
++ if (wol->wolopts & WAKE_MCAST)
++ adapter->wol |= ATLX_WUFC_MC;
++ if (wol->wolopts & WAKE_BCAST)
++ adapter->wol |= ATLX_WUFC_BC;
++ if (wol->wolopts & WAKE_MAGIC)
++ adapter->wol |= ATLX_WUFC_MAG;
++ return 0;
++}
++
++static u32 atl1_get_msglevel(struct net_device *netdev)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ return adapter->msg_enable;
++}
++
++static void atl1_set_msglevel(struct net_device *netdev, u32 value)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ adapter->msg_enable = value;
++}
++
++static int atl1_get_regs_len(struct net_device *netdev)
++{
++ return ATL1_REG_COUNT * sizeof(u32);
++}
++
++static void atl1_get_regs(struct net_device *netdev, struct ethtool_regs *regs,
++ void *p)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ struct atl1_hw *hw = &adapter->hw;
++ unsigned int i;
++ u32 *regbuf = p;
++
++ for (i = 0; i < ATL1_REG_COUNT; i++) {
++ /*
++ * This switch statement avoids reserved regions
++ * of register space.
++ */
++ switch (i) {
++ case 6 ... 9:
++ case 14:
++ case 29 ... 31:
++ case 34 ... 63:
++ case 75 ... 127:
++ case 136 ... 1023:
++ case 1027 ... 1087:
++ case 1091 ... 1151:
++ case 1194 ... 1195:
++ case 1200 ... 1201:
++ case 1206 ... 1213:
++ case 1216 ... 1279:
++ case 1290 ... 1311:
++ case 1323 ... 1343:
++ case 1358 ... 1359:
++ case 1368 ... 1375:
++ case 1378 ... 1383:
++ case 1388 ... 1391:
++ case 1393 ... 1395:
++ case 1402 ... 1403:
++ case 1410 ... 1471:
++ case 1522 ... 1535:
++ /* reserved region; don't read it */
++ regbuf[i] = 0;
++ break;
++ default:
++ /* unreserved region */
++ regbuf[i] = ioread32(hw->hw_addr + (i * sizeof(u32)));
++ }
++ }
++}
++
++static void atl1_get_ringparam(struct net_device *netdev,
++ struct ethtool_ringparam *ring)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ struct atl1_tpd_ring *txdr = &adapter->tpd_ring;
++ struct atl1_rfd_ring *rxdr = &adapter->rfd_ring;
++
++ ring->rx_max_pending = ATL1_MAX_RFD;
++ ring->tx_max_pending = ATL1_MAX_TPD;
++ ring->rx_mini_max_pending = 0;
++ ring->rx_jumbo_max_pending = 0;
++ ring->rx_pending = rxdr->count;
++ ring->tx_pending = txdr->count;
++ ring->rx_mini_pending = 0;
++ ring->rx_jumbo_pending = 0;
++}
++
++static int atl1_set_ringparam(struct net_device *netdev,
++ struct ethtool_ringparam *ring)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ struct atl1_tpd_ring *tpdr = &adapter->tpd_ring;
++ struct atl1_rrd_ring *rrdr = &adapter->rrd_ring;
++ struct atl1_rfd_ring *rfdr = &adapter->rfd_ring;
++
++ struct atl1_tpd_ring tpd_old, tpd_new;
++ struct atl1_rfd_ring rfd_old, rfd_new;
++ struct atl1_rrd_ring rrd_old, rrd_new;
++ struct atl1_ring_header rhdr_old, rhdr_new;
++ int err;
++
++ tpd_old = adapter->tpd_ring;
++ rfd_old = adapter->rfd_ring;
++ rrd_old = adapter->rrd_ring;
++ rhdr_old = adapter->ring_header;
++
++ if (netif_running(adapter->netdev))
++ atl1_down(adapter);
++
++ rfdr->count = (u16) max(ring->rx_pending, (u32) ATL1_MIN_RFD);
++ rfdr->count = rfdr->count > ATL1_MAX_RFD ? ATL1_MAX_RFD :
++ rfdr->count;
++ rfdr->count = (rfdr->count + 3) & ~3;
++ rrdr->count = rfdr->count;
++
++ tpdr->count = (u16) max(ring->tx_pending, (u32) ATL1_MIN_TPD);
++ tpdr->count = tpdr->count > ATL1_MAX_TPD ? ATL1_MAX_TPD :
++ tpdr->count;
++ tpdr->count = (tpdr->count + 3) & ~3;
++
++ if (netif_running(adapter->netdev)) {
++ /* try to get new resources before deleting old */
++ err = atl1_setup_ring_resources(adapter);
++ if (err)
++ goto err_setup_ring;
++
++ /*
++ * save the new, restore the old in order to free it,
++ * then restore the new back again
++ */
++
++ rfd_new = adapter->rfd_ring;
++ rrd_new = adapter->rrd_ring;
++ tpd_new = adapter->tpd_ring;
++ rhdr_new = adapter->ring_header;
++ adapter->rfd_ring = rfd_old;
++ adapter->rrd_ring = rrd_old;
++ adapter->tpd_ring = tpd_old;
++ adapter->ring_header = rhdr_old;
++ atl1_free_ring_resources(adapter);
++ adapter->rfd_ring = rfd_new;
++ adapter->rrd_ring = rrd_new;
++ adapter->tpd_ring = tpd_new;
++ adapter->ring_header = rhdr_new;
++
++ err = atl1_up(adapter);
++ if (err)
++ return err;
++ }
++ return 0;
++
++err_setup_ring:
++ adapter->rfd_ring = rfd_old;
++ adapter->rrd_ring = rrd_old;
++ adapter->tpd_ring = tpd_old;
++ adapter->ring_header = rhdr_old;
++ atl1_up(adapter);
++ return err;
++}
++
++static void atl1_get_pauseparam(struct net_device *netdev,
++ struct ethtool_pauseparam *epause)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ struct atl1_hw *hw = &adapter->hw;
++
++ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
++ hw->media_type == MEDIA_TYPE_1000M_FULL) {
++ epause->autoneg = AUTONEG_ENABLE;
++ } else {
++ epause->autoneg = AUTONEG_DISABLE;
++ }
++ epause->rx_pause = 1;
++ epause->tx_pause = 1;
++}
++
++static int atl1_set_pauseparam(struct net_device *netdev,
++ struct ethtool_pauseparam *epause)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ struct atl1_hw *hw = &adapter->hw;
++
++ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
++ hw->media_type == MEDIA_TYPE_1000M_FULL) {
++ epause->autoneg = AUTONEG_ENABLE;
++ } else {
++ epause->autoneg = AUTONEG_DISABLE;
++ }
++
++ epause->rx_pause = 1;
++ epause->tx_pause = 1;
++
++ return 0;
++}
++
++/* FIXME: is this right? -- CHS */
++static u32 atl1_get_rx_csum(struct net_device *netdev)
++{
++ return 1;
++}
++
++static void atl1_get_strings(struct net_device *netdev, u32 stringset,
++ u8 *data)
++{
++ u8 *p = data;
++ int i;
++
++ switch (stringset) {
++ case ETH_SS_STATS:
++ for (i = 0; i < ARRAY_SIZE(atl1_gstrings_stats); i++) {
++ memcpy(p, atl1_gstrings_stats[i].stat_string,
++ ETH_GSTRING_LEN);
++ p += ETH_GSTRING_LEN;
++ }
++ break;
++ }
++}
++
++static int atl1_nway_reset(struct net_device *netdev)
++{
++ struct atl1_adapter *adapter = netdev_priv(netdev);
++ struct atl1_hw *hw = &adapter->hw;
++
++ if (netif_running(netdev)) {
++ u16 phy_data;
++ atl1_down(adapter);
++
++ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
++ hw->media_type == MEDIA_TYPE_1000M_FULL) {
++ phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
++ } else {
++ switch (hw->media_type) {
++ case MEDIA_TYPE_100M_FULL:
++ phy_data = MII_CR_FULL_DUPLEX |
++ MII_CR_SPEED_100 | MII_CR_RESET;
++ break;
++ case MEDIA_TYPE_100M_HALF:
++ phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
++ break;
++ case MEDIA_TYPE_10M_FULL:
++ phy_data = MII_CR_FULL_DUPLEX |
++ MII_CR_SPEED_10 | MII_CR_RESET;
++ break;
++ default:
++ /* MEDIA_TYPE_10M_HALF */
++ phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
++ }
++ }
++ atl1_write_phy_reg(hw, MII_BMCR, phy_data);
++ atl1_up(adapter);
++ }
++ return 0;
++}
++
++const struct ethtool_ops atl1_ethtool_ops = {
++ .get_settings = atl1_get_settings,
++ .set_settings = atl1_set_settings,
++ .get_drvinfo = atl1_get_drvinfo,
++ .get_wol = atl1_get_wol,
++ .set_wol = atl1_set_wol,
++ .get_msglevel = atl1_get_msglevel,
++ .set_msglevel = atl1_set_msglevel,
++ .get_regs_len = atl1_get_regs_len,
++ .get_regs = atl1_get_regs,
++ .get_ringparam = atl1_get_ringparam,
++ .set_ringparam = atl1_set_ringparam,
++ .get_pauseparam = atl1_get_pauseparam,
++ .set_pauseparam = atl1_set_pauseparam,
++ .get_rx_csum = atl1_get_rx_csum,
++ .set_tx_csum = ethtool_op_set_tx_hw_csum,
++ .get_link = ethtool_op_get_link,
++ .set_sg = ethtool_op_set_sg,
++ .get_strings = atl1_get_strings,
++ .nway_reset = atl1_nway_reset,
++ .get_ethtool_stats = atl1_get_ethtool_stats,
++ .get_sset_count = atl1_get_sset_count,
++ .set_tso = ethtool_op_set_tso,
++};
+diff --git a/drivers/net/atlx/atl1.h b/drivers/net/atlx/atl1.h
+new file mode 100644
+index 0000000..51893d6
+--- /dev/null
++++ b/drivers/net/atlx/atl1.h
+@@ -0,0 +1,796 @@
++/*
++ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
++ * Copyright(c) 2006 - 2007 Chris Snook <csnook at redhat.com>
++ * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
++ *
++ * 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 ATL1_H
++#define ATL1_H
++
++#include <linux/compiler.h>
++#include <linux/ethtool.h>
++#include <linux/if_vlan.h>
++#include <linux/mii.h>
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/spinlock.h>
++#include <linux/timer.h>
++#include <linux/types.h>
++#include <linux/workqueue.h>
++
++#include "atlx.h"
++
++#define ATLX_DRIVER_NAME "atl1"
++
++MODULE_DESCRIPTION("Atheros L1 Gigabit Ethernet Driver");
++
++#define atlx_adapter atl1_adapter
++#define atlx_check_for_link atl1_check_for_link
++#define atlx_check_link atl1_check_link
++#define atlx_hash_mc_addr atl1_hash_mc_addr
++#define atlx_hash_set atl1_hash_set
++#define atlx_hw atl1_hw
++#define atlx_mii_ioctl atl1_mii_ioctl
++#define atlx_read_phy_reg atl1_read_phy_reg
++#define atlx_set_mac atl1_set_mac
++#define atlx_set_mac_addr atl1_set_mac_addr
++
++struct atl1_adapter;
++struct atl1_hw;
++
++/* function prototypes needed by multiple files */
++u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr);
++void atl1_hash_set(struct atl1_hw *hw, u32 hash_value);
++s32 atl1_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data);
++void atl1_set_mac_addr(struct atl1_hw *hw);
++static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
++ int cmd);
++static u32 atl1_check_link(struct atl1_adapter *adapter);
++
++extern const struct ethtool_ops atl1_ethtool_ops;
++
++/* hardware definitions specific to L1 */
++
++/* Block IDLE Status Register */
++#define IDLE_STATUS_RXMAC 0x1
++#define IDLE_STATUS_TXMAC 0x2
++#define IDLE_STATUS_RXQ 0x4
++#define IDLE_STATUS_TXQ 0x8
++#define IDLE_STATUS_DMAR 0x10
++#define IDLE_STATUS_DMAW 0x20
++#define IDLE_STATUS_SMB 0x40
++#define IDLE_STATUS_CMB 0x80
++
++/* MDIO Control Register */
++#define MDIO_WAIT_TIMES 30
++
++/* MAC Control Register */
++#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 0x300000
++#define MAC_CTRL_SPEED_1000 0x2
++#define MAC_CTRL_SPEED_10_100 0x1
++#define MAC_CTRL_DBG_TX_BKPRESURE 0x400000
++#define MAC_CTRL_TX_HUGE 0x800000
++#define MAC_CTRL_RX_CHKSUM_EN 0x1000000
++#define MAC_CTRL_DBG 0x8000000
++
++/* Wake-On-Lan control register */
++#define WOL_CLK_SWITCH_EN 0x8000
++#define WOL_PT5_EN 0x200000
++#define WOL_PT6_EN 0x400000
++#define WOL_PT5_MATCH 0x8000000
++#define WOL_PT6_MATCH 0x10000000
++
++/* 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 Registers, low 32 bits */
++#define REG_SRAM_RFD_LEN 0x1504
++#define REG_SRAM_RRD_ADDR 0x1508
++#define REG_SRAM_RRD_LEN 0x150C
++#define REG_SRAM_TPD_ADDR 0x1510
++#define REG_SRAM_TPD_LEN 0x1514
++#define REG_SRAM_TRD_ADDR 0x1518
++#define REG_SRAM_TRD_LEN 0x151C
++#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_PATH_ADDR 0x1530
++#define SRAM_TCPH_ADDR_MASK 0xFFF
++#define SRAM_TCPH_ADDR_SHIFT 0
++#define SRAM_PATH_ADDR_MASK 0xFFF
++#define SRAM_PATH_ADDR_SHIFT 16
++
++/* Load Ptr Register */
++#define REG_LOAD_PTR 0x1534
++
++/* Descriptor Control registers, low 32 bits */
++#define REG_DESC_RFD_ADDR_LO 0x1544
++#define REG_DESC_RRD_ADDR_LO 0x1548
++#define REG_DESC_TPD_ADDR_LO 0x154C
++#define REG_DESC_CMB_ADDR_LO 0x1550
++#define REG_DESC_SMB_ADDR_LO 0x1554
++#define REG_DESC_RFD_RRD_RING_SIZE 0x1558
++#define DESC_RFD_RING_SIZE_MASK 0x7FF
++#define DESC_RFD_RING_SIZE_SHIFT 0
++#define DESC_RRD_RING_SIZE_MASK 0x7FF
++#define DESC_RRD_RING_SIZE_SHIFT 16
++#define REG_DESC_TPD_RING_SIZE 0x155C
++#define DESC_TPD_RING_SIZE_MASK 0x3FF
++#define DESC_TPD_RING_SIZE_SHIFT 0
++
++/* TXQ Control Register */
++#define REG_TXQ_CTRL 0x1580
++#define TXQ_CTRL_TPD_BURST_NUM_SHIFT 0
++#define TXQ_CTRL_TPD_BURST_NUM_MASK 0x1F
++#define TXQ_CTRL_EN 0x20
++#define TXQ_CTRL_ENH_MODE 0x40
++#define TXQ_CTRL_TPD_FETCH_TH_SHIFT 8
++#define TXQ_CTRL_TPD_FETCH_TH_MASK 0x3F
++#define TXQ_CTRL_TXF_BURST_NUM_SHIFT 16
++#define TXQ_CTRL_TXF_BURST_NUM_MASK 0xFFFF
++
++/* Jumbo packet Threshold for task offload */
++#define REG_TX_JUMBO_TASK_TH_TPD_IPG 0x1584
++#define TX_JUMBO_TASK_TH_MASK 0x7FF
++#define TX_JUMBO_TASK_TH_SHIFT 0
++#define TX_TPD_MIN_IPG_MASK 0x1F
++#define TX_TPD_MIN_IPG_SHIFT 16
++
++/* RXQ Control Register */
++#define REG_RXQ_CTRL 0x15A0
++#define RXQ_CTRL_RFD_BURST_NUM_SHIFT 0
++#define RXQ_CTRL_RFD_BURST_NUM_MASK 0xFF
++#define RXQ_CTRL_RRD_BURST_THRESH_SHIFT 8
++#define RXQ_CTRL_RRD_BURST_THRESH_MASK 0xFF
++#define RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT 16
++#define RXQ_CTRL_RFD_PREF_MIN_IPG_MASK 0x1F
++#define RXQ_CTRL_CUT_THRU_EN 0x40000000
++#define RXQ_CTRL_EN 0x80000000
++
++/* Rx jumbo packet threshold and rrd retirement timer */
++#define REG_RXQ_JMBOSZ_RRDTIM 0x15A4
++#define RXQ_JMBOSZ_TH_MASK 0x7FF
++#define RXQ_JMBOSZ_TH_SHIFT 0
++#define RXQ_JMBO_LKAH_MASK 0xF
++#define RXQ_JMBO_LKAH_SHIFT 11
++#define RXQ_RRD_TIMER_MASK 0xFFFF
++#define RXQ_RRD_TIMER_SHIFT 16
++
++/* RFD flow control register */
++#define REG_RXQ_RXF_PAUSE_THRESH 0x15A8
++#define RXQ_RXF_PAUSE_TH_HI_SHIFT 16
++#define RXQ_RXF_PAUSE_TH_HI_MASK 0xFFF
++#define RXQ_RXF_PAUSE_TH_LO_SHIFT 0
++#define RXQ_RXF_PAUSE_TH_LO_MASK 0xFFF
++
++/* RRD flow control register */
++#define REG_RXQ_RRD_PAUSE_THRESH 0x15AC
++#define RXQ_RRD_PAUSE_TH_HI_SHIFT 0
++#define RXQ_RRD_PAUSE_TH_HI_MASK 0xFFF
++#define RXQ_RRD_PAUSE_TH_LO_SHIFT 16
++#define RXQ_RRD_PAUSE_TH_LO_MASK 0xFFF
++
++/* 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_SHIFT 4
++#define DMA_CTRL_DMAR_BURST_LEN_MASK 7
++#define DMA_CTRL_DMAW_BURST_LEN_SHIFT 7
++#define DMA_CTRL_DMAW_BURST_LEN_MASK 7
++#define DMA_CTRL_DMAR_EN 0x400
++#define DMA_CTRL_DMAW_EN 0x800
++
++/* CMB/SMB Control Register */
++#define REG_CSMB_CTRL 0x15D0
++#define CSMB_CTRL_CMB_NOW 1
++#define CSMB_CTRL_SMB_NOW 2
++#define CSMB_CTRL_CMB_EN 4
++#define CSMB_CTRL_SMB_EN 8
++
++/* CMB DMA Write Threshold Register */
++#define REG_CMB_WRITE_TH 0x15D4
++#define CMB_RRD_TH_SHIFT 0
++#define CMB_RRD_TH_MASK 0x7FF
++#define CMB_TPD_TH_SHIFT 16
++#define CMB_TPD_TH_MASK 0x7FF
++
++/* RX/TX count-down timer to trigger CMB-write. 2us resolution. */
++#define REG_CMB_WRITE_TIMER 0x15D8
++#define CMB_RX_TM_SHIFT 0
++#define CMB_RX_TM_MASK 0xFFFF
++#define CMB_TX_TM_SHIFT 16
++#define CMB_TX_TM_MASK 0xFFFF
++
++/* Number of packet received since last CMB write */
++#define REG_CMB_RX_PKT_CNT 0x15DC
++
++/* Number of packet transmitted since last CMB write */
++#define REG_CMB_TX_PKT_CNT 0x15E0
++
++/* SMB auto DMA timer register */
++#define REG_SMB_TIMER 0x15E4
++
++/* Mailbox Register */
++#define REG_MAILBOX 0x15F0
++#define MB_RFD_PROD_INDX_SHIFT 0
++#define MB_RFD_PROD_INDX_MASK 0x7FF
++#define MB_RRD_CONS_INDX_SHIFT 11
++#define MB_RRD_CONS_INDX_MASK 0x7FF
++#define MB_TPD_PROD_INDX_SHIFT 22
++#define MB_TPD_PROD_INDX_MASK 0x3FF
++
++/* Interrupt Status Register */
++#define ISR_SMB 0x1
++#define ISR_TIMER 0x2
++#define ISR_MANUAL 0x4
++#define ISR_RXF_OV 0x8
++#define ISR_RFD_UNRUN 0x10
++#define ISR_RRD_OV 0x20
++#define ISR_TXF_UNRUN 0x40
++#define ISR_LINK 0x80
++#define ISR_HOST_RFD_UNRUN 0x100
++#define ISR_HOST_RRD_OV 0x200
++#define ISR_DMAR_TO_RST 0x400
++#define ISR_DMAW_TO_RST 0x800
++#define ISR_GPHY 0x1000
++#define ISR_RX_PKT 0x10000
++#define ISR_TX_PKT 0x20000
++#define ISR_TX_DMA 0x40000
++#define ISR_RX_DMA 0x80000
++#define ISR_CMB_RX 0x100000
++#define ISR_CMB_TX 0x200000
++#define ISR_MAC_RX 0x400000
++#define ISR_MAC_TX 0x800000
++#define ISR_DIS_SMB 0x20000000
++#define ISR_DIS_DMA 0x40000000
++
++/* Normal Interrupt mask */
++#define IMR_NORMAL_MASK (\
++ ISR_SMB |\
++ ISR_GPHY |\
++ ISR_PHY_LINKDOWN|\
++ ISR_DMAR_TO_RST |\
++ ISR_DMAW_TO_RST |\
++ ISR_CMB_TX |\
++ ISR_CMB_RX)
++
++/* Debug Interrupt Mask (enable all interrupt) */
++#define IMR_DEBUG_MASK (\
++ ISR_SMB |\
++ ISR_TIMER |\
++ ISR_MANUAL |\
++ ISR_RXF_OV |\
++ ISR_RFD_UNRUN |\
++ ISR_RRD_OV |\
++ ISR_TXF_UNRUN |\
++ ISR_LINK |\
++ ISR_CMB_TX |\
++ ISR_CMB_RX |\
++ ISR_RX_PKT |\
++ ISR_TX_PKT |\
++ ISR_MAC_RX |\
++ ISR_MAC_TX)
++
++#define MEDIA_TYPE_1000M_FULL 1
++#define MEDIA_TYPE_100M_FULL 2
++#define MEDIA_TYPE_100M_HALF 3
++#define MEDIA_TYPE_10M_FULL 4
++#define MEDIA_TYPE_10M_HALF 5
++
++#define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x002F /* All but 1000-Half */
++
++#define MAX_JUMBO_FRAME_SIZE 10240
++
++#define ATL1_EEDUMP_LEN 48
++
++/* Statistics counters collected by the MAC */
++struct stats_msg_block {
++ /* rx */
++ u32 rx_ok; /* good RX packets */
++ u32 rx_bcast; /* good RX broadcast packets */
++ u32 rx_mcast; /* good RX multicast packets */
++ u32 rx_pause; /* RX pause frames */
++ u32 rx_ctrl; /* RX control packets other than pause frames */
++ u32 rx_fcs_err; /* RX packets with bad FCS */
++ u32 rx_len_err; /* RX packets with length != actual size */
++ u32 rx_byte_cnt; /* good bytes received. FCS is NOT included */
++ u32 rx_runt; /* RX packets < 64 bytes with good FCS */
++ u32 rx_frag; /* RX packets < 64 bytes with bad FCS */
++ u32 rx_sz_64; /* 64 byte RX packets */
++ u32 rx_sz_65_127;
++ u32 rx_sz_128_255;
++ u32 rx_sz_256_511;
++ u32 rx_sz_512_1023;
++ u32 rx_sz_1024_1518;
++ u32 rx_sz_1519_max; /* 1519 byte to MTU RX packets */
++ u32 rx_sz_ov; /* truncated RX packets > MTU */
++ u32 rx_rxf_ov; /* frames dropped due to RX FIFO overflow */
++ u32 rx_rrd_ov; /* frames dropped due to RRD overflow */
++ u32 rx_align_err; /* alignment errors */
++ u32 rx_bcast_byte_cnt; /* RX broadcast bytes, excluding FCS */
++ u32 rx_mcast_byte_cnt; /* RX multicast bytes, excluding FCS */
++ u32 rx_err_addr; /* packets dropped due to address filtering */
++
++ /* tx */
++ u32 tx_ok; /* good TX packets */
++ u32 tx_bcast; /* good TX broadcast packets */
++ u32 tx_mcast; /* good TX multicast packets */
++ u32 tx_pause; /* TX pause frames */
++ u32 tx_exc_defer; /* TX packets deferred excessively */
++ u32 tx_ctrl; /* TX control frames, excluding pause frames */
++ u32 tx_defer; /* TX packets deferred */
++ u32 tx_byte_cnt; /* bytes transmitted, FCS is NOT included */
++ u32 tx_sz_64; /* 64 byte TX packets */
++ u32 tx_sz_65_127;
++ u32 tx_sz_128_255;
++ u32 tx_sz_256_511;
++ u32 tx_sz_512_1023;
++ u32 tx_sz_1024_1518;
++ u32 tx_sz_1519_max; /* 1519 byte to MTU TX packets */
++ u32 tx_1_col; /* packets TX after a single collision */
++ u32 tx_2_col; /* packets TX after multiple collisions */
++ u32 tx_late_col; /* TX packets with late collisions */
++ u32 tx_abort_col; /* TX packets aborted w/excessive collisions */
++ u32 tx_underrun; /* TX packets aborted due to TX FIFO underrun
++ * or TRD FIFO underrun */
++ u32 tx_rd_eop; /* reads beyond the EOP into the next frame
++ * when TRD was not written timely */
++ u32 tx_len_err; /* TX packets where length != actual size */
++ u32 tx_trunc; /* TX packets truncated due to size > MTU */
++ u32 tx_bcast_byte; /* broadcast bytes transmitted, excluding FCS */
++ u32 tx_mcast_byte; /* multicast bytes transmitted, excluding FCS */
++ u32 smb_updated; /* 1: SMB Updated. This is used by software to
++ * indicate the statistics update. Software
++ * should clear this bit after retrieving the
++ * statistics information. */
++};
++
++/* Coalescing Message Block */
++struct coals_msg_block {
++ u32 int_stats; /* interrupt status */
++ u16 rrd_prod_idx; /* TRD Producer Index. */
++ u16 rfd_cons_idx; /* RFD Consumer Index. */
++ u16 update; /* Selene sets this bit every time it DMAs the
++ * CMB to host memory. Software should clear
++ * this bit when CMB info is processed. */
++ u16 tpd_cons_idx; /* TPD Consumer Index. */
++};
++
++/* RRD descriptor */
++struct rx_return_desc {
++ u8 num_buf; /* Number of RFD buffers used by the received packet */
++ u8 resved;
++ u16 buf_indx; /* RFD Index of the first buffer */
++ union {
++ u32 valid;
++ struct {
++ u16 rx_chksum;
++ u16 pkt_size;
++ } xsum_sz;
++ } xsz;
++
++ u16 pkt_flg; /* Packet flags */
++ u16 err_flg; /* Error flags */
++ u16 resved2;
++ u16 vlan_tag; /* VLAN TAG */
++};
++
++#define PACKET_FLAG_ETH_TYPE 0x0080
++#define PACKET_FLAG_VLAN_INS 0x0100
++#define PACKET_FLAG_ERR 0x0200
++#define PACKET_FLAG_IPV4 0x0400
++#define PACKET_FLAG_UDP 0x0800
++#define PACKET_FLAG_TCP 0x1000
++#define PACKET_FLAG_BCAST 0x2000
++#define PACKET_FLAG_MCAST 0x4000
++#define PACKET_FLAG_PAUSE 0x8000
++
++#define ERR_FLAG_CRC 0x0001
++#define ERR_FLAG_CODE 0x0002
++#define ERR_FLAG_DRIBBLE 0x0004
++#define ERR_FLAG_RUNT 0x0008
++#define ERR_FLAG_OV 0x0010
++#define ERR_FLAG_TRUNC 0x0020
++#define ERR_FLAG_IP_CHKSUM 0x0040
++#define ERR_FLAG_L4_CHKSUM 0x0080
++#define ERR_FLAG_LEN 0x0100
++#define ERR_FLAG_DES_ADDR 0x0200
++
++/* RFD descriptor */
++struct rx_free_desc {
++ __le64 buffer_addr; /* Address of the descriptor's data buffer */
++ __le16 buf_len; /* Size of the receive buffer in host memory */
++ u16 coalese; /* Update consumer index to host after the
++ * reception of this frame */
++ /* __attribute__ ((packed)) is required */
++} __attribute__ ((packed));
++
++/*
++ * The L1 transmit packet descriptor is comprised of four 32-bit words.
++ *
++ * 31 0
++ * +---------------------------------------+
++ * | Word 0: Buffer addr lo |
++ * +---------------------------------------+
++ * | Word 1: Buffer addr hi |
++ * +---------------------------------------+
++ * | Word 2 |
++ * +---------------------------------------+
++ * | Word 3 |
++ * +---------------------------------------+
++ *
++ * Words 0 and 1 combine to form a 64-bit buffer address.
++ *
++ * Word 2 is self explanatory in the #define block below.
++ *
++ * Word 3 has two forms, depending upon the state of bits 3 and 4.
++ * If bits 3 and 4 are both zero, then bits 14:31 are unused by the
++ * hardware. Otherwise, if either bit 3 or 4 is set, the definition
++ * of bits 14:31 vary according to the following depiction.
++ *
++ * 0 End of packet 0 End of packet
++ * 1 Coalesce 1 Coalesce
++ * 2 Insert VLAN tag 2 Insert VLAN tag
++ * 3 Custom csum enable = 0 3 Custom csum enable = 1
++ * 4 Segment enable = 1 4 Segment enable = 0
++ * 5 Generate IP checksum 5 Generate IP checksum
++ * 6 Generate TCP checksum 6 Generate TCP checksum
++ * 7 Generate UDP checksum 7 Generate UDP checksum
++ * 8 VLAN tagged 8 VLAN tagged
++ * 9 Ethernet frame type 9 Ethernet frame type
++ * 10-+ 10-+
++ * 11 | IP hdr length (10:13) 11 | IP hdr length (10:13)
++ * 12 | (num 32-bit words) 12 | (num 32-bit words)
++ * 13-+ 13-+
++ * 14-+ 14 Unused
++ * 15 | TCP hdr length (14:17) 15 Unused
++ * 16 | (num 32-bit words) 16-+
++ * 17-+ 17 |
++ * 18 Header TPD flag 18 |
++ * 19-+ 19 | Payload offset
++ * 20 | 20 | (16:23)
++ * 21 | 21 |
++ * 22 | 22 |
++ * 23 | 23-+
++ * 24 | 24-+
++ * 25 | MSS (19:31) 25 |
++ * 26 | 26 |
++ * 27 | 27 | Custom csum offset
++ * 28 | 28 | (24:31)
++ * 29 | 29 |
++ * 30 | 30 |
++ * 31-+ 31-+
++ */
++
++/* tpd word 2 */
++#define TPD_BUFLEN_MASK 0x3FFF
++#define TPD_BUFLEN_SHIFT 0
++#define TPD_DMAINT_MASK 0x0001
++#define TPD_DMAINT_SHIFT 14
++#define TPD_PKTNT_MASK 0x0001
++#define TPD_PKTINT_SHIFT 15
++#define TPD_VLANTAG_MASK 0xFFFF
++#define TPD_VLAN_SHIFT 16
++
++/* tpd word 3 bits 0:13 */
++#define TPD_EOP_MASK 0x0001
++#define TPD_EOP_SHIFT 0
++#define TPD_COALESCE_MASK 0x0001
++#define TPD_COALESCE_SHIFT 1
++#define TPD_INS_VL_TAG_MASK 0x0001
++#define TPD_INS_VL_TAG_SHIFT 2
++#define TPD_CUST_CSUM_EN_MASK 0x0001
++#define TPD_CUST_CSUM_EN_SHIFT 3
++#define TPD_SEGMENT_EN_MASK 0x0001
++#define TPD_SEGMENT_EN_SHIFT 4
++#define TPD_IP_CSUM_MASK 0x0001
++#define TPD_IP_CSUM_SHIFT 5
++#define TPD_TCP_CSUM_MASK 0x0001
++#define TPD_TCP_CSUM_SHIFT 6
++#define TPD_UDP_CSUM_MASK 0x0001
++#define TPD_UDP_CSUM_SHIFT 7
++#define TPD_VL_TAGGED_MASK 0x0001
++#define TPD_VL_TAGGED_SHIFT 8
++#define TPD_ETHTYPE_MASK 0x0001
++#define TPD_ETHTYPE_SHIFT 9
++#define TPD_IPHL_MASK 0x000F
++#define TPD_IPHL_SHIFT 10
++
++/* tpd word 3 bits 14:31 if segment enabled */
++#define TPD_TCPHDRLEN_MASK 0x000F
++#define TPD_TCPHDRLEN_SHIFT 14
++#define TPD_HDRFLAG_MASK 0x0001
++#define TPD_HDRFLAG_SHIFT 18
++#define TPD_MSS_MASK 0x1FFF
++#define TPD_MSS_SHIFT 19
++
++/* tpd word 3 bits 16:31 if custom csum enabled */
++#define TPD_PLOADOFFSET_MASK 0x00FF
++#define TPD_PLOADOFFSET_SHIFT 16
++#define TPD_CCSUMOFFSET_MASK 0x00FF
++#define TPD_CCSUMOFFSET_SHIFT 24
++
++struct tx_packet_desc {
++ __le64 buffer_addr;
++ __le32 word2;
++ __le32 word3;
++};
++
++/* DMA Order Settings */
++enum atl1_dma_order {
++ atl1_dma_ord_in = 1,
++ atl1_dma_ord_enh = 2,
++ atl1_dma_ord_out = 4
++};
++
++enum atl1_dma_rcb {
++ atl1_rcb_64 = 0,
++ atl1_rcb_128 = 1
++};
++
++enum atl1_dma_req_block {
++ atl1_dma_req_128 = 0,
++ atl1_dma_req_256 = 1,
++ atl1_dma_req_512 = 2,
++ atl1_dma_req_1024 = 3,
++ atl1_dma_req_2048 = 4,
++ atl1_dma_req_4096 = 5
++};
++
++#define ATL1_MAX_INTR 3
++#define ATL1_MAX_TX_BUF_LEN 0x3000 /* 12288 bytes */
++
++#define ATL1_DEFAULT_TPD 256
++#define ATL1_MAX_TPD 1024
++#define ATL1_MIN_TPD 64
++#define ATL1_DEFAULT_RFD 512
++#define ATL1_MIN_RFD 128
++#define ATL1_MAX_RFD 2048
++#define ATL1_REG_COUNT 1538
++
++#define ATL1_GET_DESC(R, i, type) (&(((type *)((R)->desc))[i]))
++#define ATL1_RFD_DESC(R, i) ATL1_GET_DESC(R, i, struct rx_free_desc)
++#define ATL1_TPD_DESC(R, i) ATL1_GET_DESC(R, i, struct tx_packet_desc)
++#define ATL1_RRD_DESC(R, i) ATL1_GET_DESC(R, i, struct rx_return_desc)
++
++/*
++ * atl1_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 atl1_ring_header {
++ void *desc; /* virtual address */
++ dma_addr_t dma; /* physical address*/
++ unsigned int size; /* length in bytes */
++};
++
++/*
++ * atl1_buffer is wrapper around a pointer to a socket buffer
++ * so a DMA handle can be stored along with the skb
++ */
++struct atl1_buffer {
++ struct sk_buff *skb; /* socket buffer */
++ u16 length; /* rx buffer length */
++ u16 alloced; /* 1 if skb allocated */
++ dma_addr_t dma;
++};
++
++/* transmit packet descriptor (tpd) ring */
++struct atl1_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 hw_idx; /* hardware index */
++ atomic_t next_to_clean;
++ atomic_t next_to_use;
++ struct atl1_buffer *buffer_info;
++};
++
++/* receive free descriptor (rfd) ring */
++struct atl1_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 */
++ atomic_t next_to_use;
++ u16 next_to_clean;
++ struct atl1_buffer *buffer_info;
++};
++
++/* receive return descriptor (rrd) ring */
++struct atl1_rrd_ring {
++ void *desc; /* descriptor ring virtual address */
++ dma_addr_t dma; /* descriptor ring physical address */
++ unsigned int size; /* descriptor ring length in bytes */
++ u16 count; /* number of descriptors in the ring */
++ u16 next_to_use;
++ atomic_t next_to_clean;
++};
++
++/* coalescing message block (cmb) */
++struct atl1_cmb {
++ struct coals_msg_block *cmb;
++ dma_addr_t dma;
++};
++
++/* statistics message block (smb) */
++struct atl1_smb {
++ struct stats_msg_block *smb;
++ dma_addr_t dma;
++};
++
++/* Statistics counters */
++struct atl1_sft_stats {
++ u64 rx_packets;
++ u64 tx_packets;
++ u64 rx_bytes;
++ u64 tx_bytes;
++ u64 multicast;
++ u64 collisions;
++ u64 rx_errors;
++ u64 rx_length_errors;
++ u64 rx_crc_errors;
++ u64 rx_frame_errors;
++ u64 rx_fifo_errors;
++ u64 rx_missed_errors;
++ u64 tx_errors;
++ u64 tx_fifo_errors;
++ u64 tx_aborted_errors;
++ u64 tx_window_errors;
++ u64 tx_carrier_errors;
++ u64 tx_pause; /* TX pause frames */
++ u64 excecol; /* TX packets w/ excessive collisions */
++ u64 deffer; /* TX packets deferred */
++ u64 scc; /* packets TX after a single collision */
++ u64 mcc; /* packets TX after multiple collisions */
++ u64 latecol; /* TX packets w/ late collisions */
++ u64 tx_underun; /* TX packets aborted due to TX FIFO underrun
++ * or TRD FIFO underrun */
++ u64 tx_trunc; /* TX packets truncated due to size > MTU */
++ u64 rx_pause; /* num Pause packets received. */
++ u64 rx_rrd_ov;
++ u64 rx_trunc;
++};
++
++/* hardware structure */
++struct atl1_hw {
++ u8 __iomem *hw_addr;
++ struct atl1_adapter *back;
++ enum atl1_dma_order dma_ord;
++ enum atl1_dma_rcb rcb_value;
++ enum atl1_dma_req_block dmar_block;
++ enum atl1_dma_req_block dmaw_block;
++ u8 preamble_len;
++ u8 max_retry;
++ u8 jam_ipg; /* IPG to start JAM for collision based flow
++ * control in half-duplex mode. In units of
++ * 8-bit time */
++ u8 ipgt; /* Desired back to back inter-packet gap.
++ * The default is 96-bit time */
++ u8 min_ifg; /* Minimum number of IFG to enforce in between
++ * receive frames. Frame gap below such IFP
++ * is dropped */
++ u8 ipgr1; /* 64bit Carrier-Sense window */
++ u8 ipgr2; /* 96-bit IPG window */
++ u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned
++ * burst. Each TPD is 16 bytes long */
++ u8 rfd_burst; /* Number of RFD to prefetch in cache-aligned
++ * burst. Each RFD is 12 bytes long */
++ u8 rfd_fetch_gap;
++ u8 rrd_burst; /* Threshold number of RRDs that can be retired
++ * in a burst. Each RRD is 16 bytes long */
++ u8 tpd_fetch_th;
++ u8 tpd_fetch_gap;
++ u16 tx_jumbo_task_th;
++ u16 txf_burst; /* Number of data bytes to read in a cache-
++ * aligned burst. Each SRAM entry is 8 bytes */
++ u16 rx_jumbo_th; /* Jumbo packet size for non-VLAN packet. VLAN
++ * packets should add 4 bytes */
++ u16 rx_jumbo_lkah;
++ u16 rrd_ret_timer; /* RRD retirement timer. Decrement by 1 after
++ * every 512ns passes. */
++ u16 lcol; /* Collision Window */
++
++ u16 cmb_tpd;
++ u16 cmb_rrd;
++ u16 cmb_rx_timer;
++ u16 cmb_tx_timer;
++ u32 smb_timer;
++ u16 media_type;
++ u16 autoneg_advertised;
++
++ u16 mii_autoneg_adv_reg;
++ u16 mii_1000t_ctrl_reg;
++
++ u32 max_frame_size;
++ u32 min_frame_size;
++
++ u16 dev_rev;
++
++ /* spi flash */
++ u8 flash_vendor;
++
++ u8 mac_addr[ETH_ALEN];
++ u8 perm_mac_addr[ETH_ALEN];
++
++ bool phy_configured;
++};
++
++struct atl1_adapter {
++ struct net_device *netdev;
++ struct pci_dev *pdev;
++ struct net_device_stats net_stats;
++ struct atl1_sft_stats soft_stats;
++ struct vlan_group *vlgrp;
++ u32 rx_buffer_len;
++ u32 wol;
++ u16 link_speed;
++ u16 link_duplex;
++ spinlock_t lock;
++ struct work_struct tx_timeout_task;
++ struct work_struct link_chg_task;
++ struct work_struct pcie_dma_to_rst_task;
++ struct timer_list watchdog_timer;
++ struct timer_list phy_config_timer;
++ bool phy_timer_pending;
++
++ /* all descriptor rings' memory */
++ struct atl1_ring_header ring_header;
++
++ /* TX */
++ struct atl1_tpd_ring tpd_ring;
++ spinlock_t mb_lock;
++
++ /* RX */
++ struct atl1_rfd_ring rfd_ring;
++ struct atl1_rrd_ring rrd_ring;
++ u64 hw_csum_err;
++ u64 hw_csum_good;
++ u32 msg_enable;
++ u16 imt; /* interrupt moderator timer (2us resolution) */
++ u16 ict; /* interrupt clear timer (2us resolution */
++ struct mii_if_info mii; /* MII interface info */
++
++ u32 bd_number; /* board number */
++ bool pci_using_64;
++ struct atl1_hw hw;
++ struct atl1_smb smb;
++ struct atl1_cmb cmb;
++};
++
++#endif /* ATL1_H */
+diff --git a/drivers/net/atlx/atlx.c b/drivers/net/atlx/atlx.c
+new file mode 100644
+index 0000000..f06b854
+--- /dev/null
++++ b/drivers/net/atlx/atlx.c
+@@ -0,0 +1,256 @@
++/* atlx.c -- common functions for Attansic network drivers
++ *
++ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
++ * Copyright(c) 2006 - 2007 Chris Snook <csnook at redhat.com>
++ * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
++ * 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.
++ */
++
++/* Including this file like a header is a temporary hack, I promise. -- CHS */
++#ifndef ATLX_C
++#define ATLX_C
++
++#include <linux/device.h>
++#include <linux/errno.h>
++#include <linux/etherdevice.h>
++#include <linux/if.h>
++#include <linux/netdevice.h>
++#include <linux/socket.h>
++#include <linux/sockios.h>
++#include <linux/spinlock.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/workqueue.h>
++
++#include "atlx.h"
++
++static struct atlx_spi_flash_dev flash_table[] = {
++/* MFR_NAME WRSR READ PRGM WREN WRDI RDSR RDID SEC_ERS CHIP_ERS */
++ {"Atmel", 0x00, 0x03, 0x02, 0x06, 0x04, 0x05, 0x15, 0x52, 0x62},
++ {"SST", 0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0x90, 0x20, 0x60},
++ {"ST", 0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0xAB, 0xD8, 0xC7},
++};
++
++static int atlx_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
++{
++ switch (cmd) {
++ case SIOCGMIIPHY:
++ case SIOCGMIIREG:
++ case SIOCSMIIREG:
++ return atlx_mii_ioctl(netdev, ifr, cmd);
++ default:
++ return -EOPNOTSUPP;
++ }
++}
++
++/*
++ * atlx_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 atlx_set_mac(struct net_device *netdev, void *p)
++{
++ struct atlx_adapter *adapter = netdev_priv(netdev);
++ struct sockaddr *addr = p;
++
++ if (netif_running(netdev))
++ return -EBUSY;
++
++ if (!is_valid_ether_addr(addr->sa_data))
++ return -EADDRNOTAVAIL;
++
++ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
++ memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
++
++ atlx_set_mac_addr(&adapter->hw);
++ return 0;
++}
++
++static void atlx_check_for_link(struct atlx_adapter *adapter)
++{
++ struct net_device *netdev = adapter->netdev;
++ u16 phy_data = 0;
++
++ spin_lock(&adapter->lock);
++ adapter->phy_timer_pending = false;
++ atlx_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
++ atlx_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
++ spin_unlock(&adapter->lock);
++
++ /* notify upper layer link down ASAP */
++ if (!(phy_data & BMSR_LSTATUS)) {
++ /* Link Down */
++ if (netif_carrier_ok(netdev)) {
++ /* old link state: Up */
++ dev_info(&adapter->pdev->dev, "%s link is down\n",
++ netdev->name);
++ adapter->link_speed = SPEED_0;
++ netif_carrier_off(netdev);
++ netif_stop_queue(netdev);
++ }
++ }
++ schedule_work(&adapter->link_chg_task);
++}
++
++/*
++ * atlx_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 atlx_set_multi(struct net_device *netdev)
++{
++ struct atlx_adapter *adapter = netdev_priv(netdev);
++ struct atlx_hw *hw = &adapter->hw;
++ struct dev_mc_list *mc_ptr;
++ u32 rctl;
++ u32 hash_value;
++
++ /* Check for Promiscuous and All Multicast modes */
++ rctl = ioread32(hw->hw_addr + REG_MAC_CTRL);
++ if (netdev->flags & IFF_PROMISC)
++ rctl |= MAC_CTRL_PROMIS_EN;
++ else if (netdev->flags & IFF_ALLMULTI) {
++ rctl |= MAC_CTRL_MC_ALL_EN;
++ rctl &= ~MAC_CTRL_PROMIS_EN;
++ } else
++ rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
++
++ iowrite32(rctl, hw->hw_addr + REG_MAC_CTRL);
++
++ /* clear the old settings from the multicast hash table */
++ iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
++ iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
++
++ /* compute 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 = atlx_hash_mc_addr(hw, mc_ptr->dmi_addr);
++ atlx_hash_set(hw, hash_value);
++ }
++}
++
++/*
++ * atlx_irq_enable - Enable default interrupt generation settings
++ * @adapter: board private structure
++ */
++static void atlx_irq_enable(struct atlx_adapter *adapter)
++{
++ iowrite32(IMR_NORMAL_MASK, adapter->hw.hw_addr + REG_IMR);
++ ioread32(adapter->hw.hw_addr + REG_IMR);
++}
++
++/*
++ * atlx_irq_disable - Mask off interrupt generation on the NIC
++ * @adapter: board private structure
++ */
++static void atlx_irq_disable(struct atlx_adapter *adapter)
++{
++ iowrite32(0, adapter->hw.hw_addr + REG_IMR);
++ ioread32(adapter->hw.hw_addr + REG_IMR);
++ synchronize_irq(adapter->pdev->irq);
++}
++
++static void atlx_clear_phy_int(struct atlx_adapter *adapter)
++{
++ u16 phy_data;
++ unsigned long flags;
++
++ spin_lock_irqsave(&adapter->lock, flags);
++ atlx_read_phy_reg(&adapter->hw, 19, &phy_data);
++ spin_unlock_irqrestore(&adapter->lock, flags);
++}
++
++/*
++ * atlx_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 *atlx_get_stats(struct net_device *netdev)
++{
++ struct atlx_adapter *adapter = netdev_priv(netdev);
++ return &adapter->net_stats;
++}
++
++/*
++ * atlx_tx_timeout - Respond to a Tx Hang
++ * @netdev: network interface device structure
++ */
++static void atlx_tx_timeout(struct net_device *netdev)
++{
++ struct atlx_adapter *adapter = netdev_priv(netdev);
++ /* Do the reset outside of interrupt context */
++ schedule_work(&adapter->tx_timeout_task);
++}
++
++/*
++ * atlx_link_chg_task - deal with link change event Out of interrupt context
++ */
++static void atlx_link_chg_task(struct work_struct *work)
++{
++ struct atlx_adapter *adapter;
++ unsigned long flags;
++
++ adapter = container_of(work, struct atlx_adapter, link_chg_task);
++
++ spin_lock_irqsave(&adapter->lock, flags);
++ atlx_check_link(adapter);
++ spin_unlock_irqrestore(&adapter->lock, flags);
++}
++
++static void atlx_vlan_rx_register(struct net_device *netdev,
++ struct vlan_group *grp)
++{
++ struct atlx_adapter *adapter = netdev_priv(netdev);
++ unsigned long flags;
++ u32 ctrl;
++
++ spin_lock_irqsave(&adapter->lock, flags);
++ /* atlx_irq_disable(adapter); FIXME: confirm/remove */
++ adapter->vlgrp = grp;
++
++ if (grp) {
++ /* enable VLAN tag insert/strip */
++ ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
++ ctrl |= MAC_CTRL_RMV_VLAN;
++ iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
++ } else {
++ /* disable VLAN tag insert/strip */
++ ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
++ ctrl &= ~MAC_CTRL_RMV_VLAN;
++ iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
++ }
++
++ /* atlx_irq_enable(adapter); FIXME */
++ spin_unlock_irqrestore(&adapter->lock, flags);
++}
++
++static void atlx_restore_vlan(struct atlx_adapter *adapter)
++{
++ atlx_vlan_rx_register(adapter->netdev, adapter->vlgrp);
++}
++
++#endif /* ATLX_C */
+diff --git a/drivers/net/atlx/atlx.h b/drivers/net/atlx/atlx.h
+new file mode 100644
+index 0000000..3be7c09
+--- /dev/null
++++ b/drivers/net/atlx/atlx.h
+@@ -0,0 +1,506 @@
++/* atlx_hw.h -- common hardware definitions for Attansic network drivers
++ *
++ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
++ * Copyright(c) 2006 - 2007 Chris Snook <csnook at redhat.com>
++ * Copyright(c) 2006 Jay Cliburn <jcliburn at gmail.com>
++ * 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.
++ */
++
++#ifndef ATLX_H
++#define ATLX_H
++
++#include <linux/module.h>
++#include <linux/types.h>
++
++#define ATLX_DRIVER_VERSION "2.1.1"
++MODULE_AUTHOR("Xiong Huang <xiong.huang at atheros.com>, \
++ Chris Snook <csnook at redhat.com>, Jay Cliburn <jcliburn at gmail.com>");
++MODULE_LICENSE("GPL");
++MODULE_VERSION(ATLX_DRIVER_VERSION);
++
++#define ATLX_ERR_PHY 2
++#define ATLX_ERR_PHY_SPEED 7
++#define ATLX_ERR_PHY_RES 8
++
++#define SPEED_0 0xffff
++#define SPEED_10 10
++#define SPEED_100 100
++#define SPEED_1000 1000
++#define HALF_DUPLEX 1
++#define FULL_DUPLEX 2
++
++#define MEDIA_TYPE_AUTO_SENSOR 0
++
++/* register definitions */
++#define REG_PM_CTRLSTAT 0x44
++
++#define REG_PCIE_CAP_LIST 0x58
++
++#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_SPI_FLASH_CTRL 0x200
++#define SPI_FLASH_CTRL_STS_NON_RDY 0x1
++#define SPI_FLASH_CTRL_STS_WEN 0x2
++#define SPI_FLASH_CTRL_STS_WPEN 0x80
++#define SPI_FLASH_CTRL_DEV_STS_MASK 0xFF
++#define SPI_FLASH_CTRL_DEV_STS_SHIFT 0
++#define SPI_FLASH_CTRL_INS_MASK 0x7
++#define SPI_FLASH_CTRL_INS_SHIFT 8
++#define SPI_FLASH_CTRL_START 0x800
++#define SPI_FLASH_CTRL_EN_VPD 0x2000
++#define SPI_FLASH_CTRL_LDSTART 0x8000
++#define SPI_FLASH_CTRL_CS_HI_MASK 0x3
++#define SPI_FLASH_CTRL_CS_HI_SHIFT 16
++#define SPI_FLASH_CTRL_CS_HOLD_MASK 0x3
++#define SPI_FLASH_CTRL_CS_HOLD_SHIFT 18
++#define SPI_FLASH_CTRL_CLK_LO_MASK 0x3
++#define SPI_FLASH_CTRL_CLK_LO_SHIFT 20
++#define SPI_FLASH_CTRL_CLK_HI_MASK 0x3
++#define SPI_FLASH_CTRL_CLK_HI_SHIFT 22
++#define SPI_FLASH_CTRL_CS_SETUP_MASK 0x3
++#define SPI_FLASH_CTRL_CS_SETUP_SHIFT 24
++#define SPI_FLASH_CTRL_EROM_PGSZ_MASK 0x3
++#define SPI_FLASH_CTRL_EROM_PGSZ_SHIFT 26
++#define SPI_FLASH_CTRL_WAIT_READY 0x10000000
++
++#define REG_SPI_ADDR 0x204
++
++#define REG_SPI_DATA 0x208
++
++#define REG_SPI_FLASH_CONFIG 0x20C
++#define SPI_FLASH_CONFIG_LD_ADDR_MASK 0xFFFFFF
++#define SPI_FLASH_CONFIG_LD_ADDR_SHIFT 0
++#define SPI_FLASH_CONFIG_VPD_ADDR_MASK 0x3
++#define SPI_FLASH_CONFIG_VPD_ADDR_SHIFT 24
++#define SPI_FLASH_CONFIG_LD_EXIST 0x4000000
++
++#define REG_SPI_FLASH_OP_PROGRAM 0x210
++#define REG_SPI_FLASH_OP_SC_ERASE 0x211
++#define REG_SPI_FLASH_OP_CHIP_ERASE 0x212
++#define REG_SPI_FLASH_OP_RDID 0x213
++#define REG_SPI_FLASH_OP_WREN 0x214
++#define REG_SPI_FLASH_OP_RDSR 0x215
++#define REG_SPI_FLASH_OP_WRSR 0x216
++#define REG_SPI_FLASH_OP_READ 0x217
++
++#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 /* FIXME: define or remove */
++#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_CTRL_EXT_PIPE 0x2
++#define PCIE_DEV_MISC_CTRL_RETRY_BUFDIS 0x1
++#define PCIE_DEV_MISC_CTRL_SPIROM_EXIST 0x4
++#define PCIE_DEV_MISC_CTRL_SERDES_ENDIAN 0x8
++#define PCIE_DEV_MISC_CTRL_SERDES_SEL_DIN 0x10
++
++#define REG_PCIE_PHYMISC 0x1000
++#define PCIE_PHYMISC_FORCE_RCV_DET 0x4
++
++#define REG_PCIE_DLL_TX_CTRL1 0x1104
++#define PCIE_DLL_TX_CTRL1_SEL_NOR_CLK 0x400
++#define PCIE_DLL_TX_CTRL1_DEF 0x568
++
++#define REG_LTSSM_TEST_MODE 0x12FC
++#define LTSSM_TEST_MODE_DEF 0x6500
++
++/* Master Control Register */
++#define REG_MASTER_CTRL 0x1400
++#define MASTER_CTRL_SOFT_RST 0x1
++#define MASTER_CTRL_MTIMER_EN 0x2
++#define MASTER_CTRL_ITIMER_EN 0x4
++#define MASTER_CTRL_MANUAL_INT 0x8
++#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 0xFF
++
++/* Timer Initial Value Register */
++#define REG_MANUAL_TIMER_INIT 0x1404
++
++/* IRQ Moderator Timer Initial Value Register */
++#define REG_IRQ_MODU_TIMER_INIT 0x1408
++
++#define REG_PHY_ENABLE 0x140C
++
++/* IRQ Anti-Lost Timer Initial Value Register */
++#define REG_CMBDISDMA_TIMER 0x140E
++
++/* Block IDLE Status Register */
++#define REG_IDLE_STATUS 0x1410
++
++/* MDIO Control Register */
++#define REG_MDIO_CTRL 0x1414
++#define MDIO_DATA_MASK 0xFFFF
++#define MDIO_DATA_SHIFT 0
++#define MDIO_REG_ADDR_MASK 0x1F
++#define MDIO_REG_ADDR_SHIFT 16
++#define MDIO_RW 0x200000
++#define MDIO_SUP_PREAMBLE 0x400000
++#define MDIO_START 0x800000
++#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
++
++/* MII PHY Status Register */
++#define REG_PHY_STATUS 0x1418
++
++/* BIST Control and Status Register0 (for the Packet Memory) */
++#define REG_BIST0_CTRL 0x141C
++#define BIST0_NOW 0x1
++#define BIST0_SRAM_FAIL 0x2
++#define BIST0_FUSE_FLAG 0x4
++#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 1
++#define SERDES_LOCK_DETECT_EN 2
++
++/* MAC Control Register */
++#define REG_MAC_CTRL 0x1480
++#define MAC_CTRL_TX_EN 1
++#define MAC_CTRL_RX_EN 2
++#define MAC_CTRL_TX_FLOW 4
++#define MAC_CTRL_RX_FLOW 8
++#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_MC_ALL_EN 0x2000000
++#define MAC_CTRL_BC_EN 0x4000000
++
++/* MAC IPG/IFG Control Register */
++#define REG_MAC_IPG_IFG 0x1484
++#define MAC_IPG_IFG_IPGT_SHIFT 0
++#define MAC_IPG_IFG_IPGT_MASK 0x7F
++#define MAC_IPG_IFG_MIFG_SHIFT 8
++#define MAC_IPG_IFG_MIFG_MASK 0xFF
++#define MAC_IPG_IFG_IPGR1_SHIFT 16
++#define MAC_IPG_IFG_IPGR1_MASK 0x7F
++#define MAC_IPG_IFG_IPGR2_SHIFT 24
++#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
++#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
++#define MAC_HALF_DUPLX_CTRL_ABEBE 0x80000
++#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT 20
++#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK 0xF
++#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT 24
++#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK 0xF
++
++/* Maximum Frame Length Control Register */
++#define REG_MTU 0x149C
++
++/* Wake-On-Lan control register */
++#define REG_WOL_CTRL 0x14A0
++#define WOL_PATTERN_EN 0x1
++#define WOL_PATTERN_PME_EN 0x2
++#define WOL_MAGIC_EN 0x4
++#define WOL_MAGIC_PME_EN 0x8
++#define WOL_LINK_CHG_EN 0x10
++#define WOL_LINK_CHG_PME_EN 0x20
++#define WOL_PATTERN_ST 0x100
++#define WOL_MAGIC_ST 0x200
++#define WOL_LINKCHG_ST 0x400
++#define WOL_PT0_EN 0x10000
++#define WOL_PT1_EN 0x20000
++#define WOL_PT2_EN 0x40000
++#define WOL_PT3_EN 0x80000
++#define WOL_PT4_EN 0x100000
++#define WOL_PT0_MATCH 0x1000000
++#define WOL_PT1_MATCH 0x2000000
++#define WOL_PT2_MATCH 0x4000000
++#define WOL_PT3_MATCH 0x8000000
++#define WOL_PT4_MATCH 0x10000000
++
++/* Internal SRAM Partition Register, high 32 bits */
++#define REG_SRAM_RFD_ADDR 0x1500
++
++/* Descriptor Control register, high 32 bits */
++#define REG_DESC_BASE_ADDR_HI 0x1540
++
++/* Interrupt Status Register */
++#define REG_ISR 0x1600
++#define ISR_UR_DETECTED 0x1000000
++#define ISR_FERR_DETECTED 0x2000000
++#define ISR_NFERR_DETECTED 0x4000000
++#define ISR_CERR_DETECTED 0x8000000
++#define ISR_PHY_LINKDOWN 0x10000000
++#define ISR_DIS_INT 0x80000000
++
++/* Interrupt Mask Register */
++#define REG_IMR 0x1604
++
++#define REG_RFD_RRD_IDX 0x1800
++#define REG_TPD_IDX 0x1804
++
++/* MII definitions */
++
++/* PHY Common Register */
++#define MII_ATLX_CR 0x09
++#define MII_ATLX_SR 0x0A
++#define MII_ATLX_ESR 0x0F
++#define MII_ATLX_PSCR 0x10
++#define MII_ATLX_PSSR 0x11
++
++/* PHY Control Register */
++#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100,
++ * 00=10
++ */
++#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */
++#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
++#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
++#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */
++#define MII_CR_POWER_DOWN 0x0800 /* Power down */
++#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
++#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100,
++ * 00=10
++ */
++#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */
++#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */
++#define MII_CR_SPEED_MASK 0x2040
++#define MII_CR_SPEED_1000 0x0040
++#define MII_CR_SPEED_100 0x2000
++#define MII_CR_SPEED_10 0x0000
++
++/* PHY Status Register */
++#define MII_SR_EXTENDED_CAPS 0x0001 /* Ext register capabilities */
++#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */
++#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */
++#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */
++#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */
++#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */
++#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */
++#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext stat info in Reg 0x0F */
++#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */
++#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */
++#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */
++#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */
++#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */
++#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */
++#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */
++
++/* Link partner ability register */
++#define MII_LPA_SLCT 0x001f /* Same as advertise selector */
++#define MII_LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */
++#define MII_LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */
++#define MII_LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */
++#define MII_LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */
++#define MII_LPA_100BASE4 0x0200 /* 100BASE-T4 */
++#define MII_LPA_PAUSE 0x0400 /* PAUSE */
++#define MII_LPA_ASYPAUSE 0x0800 /* Asymmetrical PAUSE */
++#define MII_LPA_RFAULT 0x2000 /* Link partner faulted */
++#define MII_LPA_LPACK 0x4000 /* Link partner acked us */
++#define MII_LPA_NPAGE 0x8000 /* Next page bit */
++
++/* Autoneg Advertisement Register */
++#define MII_AR_SELECTOR_FIELD 0x0001 /* IEEE 802.3 CSMA/CD */
++#define MII_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */
++#define MII_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */
++#define MII_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */
++#define MII_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */
++#define MII_AR_100T4_CAPS 0x0200 /* 100T4 Capable */
++#define MII_AR_PAUSE 0x0400 /* Pause operation desired */
++#define MII_AR_ASM_DIR 0x0800 /* Asymmetric Pause Dir bit */
++#define MII_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */
++#define MII_AR_NEXT_PAGE 0x8000 /* Next Page ability support */
++#define MII_AR_SPEED_MASK 0x01E0
++#define MII_AR_DEFAULT_CAP_MASK 0x0DE0
++
++/* 1000BASE-T Control Register */
++#define MII_ATLX_CR_1000T_HD_CAPS 0x0100 /* Adv 1000T HD cap */
++#define MII_ATLX_CR_1000T_FD_CAPS 0x0200 /* Adv 1000T FD cap */
++#define MII_ATLX_CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device,
++ * 0=DTE device */
++#define MII_ATLX_CR_1000T_MS_VALUE 0x0800 /* 1=Config PHY as Master,
++ * 0=Configure PHY as Slave */
++#define MII_ATLX_CR_1000T_MS_ENABLE 0x1000 /* 1=Man Master/Slave config,
++ * 0=Auto Master/Slave config
++ */
++#define MII_ATLX_CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */
++#define MII_ATLX_CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */
++#define MII_ATLX_CR_1000T_TEST_MODE_2 0x4000 /* Master Xmit Jitter test */
++#define MII_ATLX_CR_1000T_TEST_MODE_3 0x6000 /* Slave Xmit Jitter test */
++#define MII_ATLX_CR_1000T_TEST_MODE_4 0x8000 /* Xmitter Distortion test */
++#define MII_ATLX_CR_1000T_SPEED_MASK 0x0300
++#define MII_ATLX_CR_1000T_DEFAULT_CAP_MASK 0x0300
++
++/* 1000BASE-T Status Register */
++#define MII_ATLX_SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */
++#define MII_ATLX_SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */
++#define MII_ATLX_SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
++#define MII_ATLX_SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */
++#define MII_ATLX_SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local TX is Master
++ * 0=Slave
++ */
++#define MII_ATLX_SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config
++ * fault */
++#define MII_ATLX_SR_1000T_REMOTE_RX_STATUS_SHIFT 12
++#define MII_ATLX_SR_1000T_LOCAL_RX_STATUS_SHIFT 13
++
++/* Extended Status Register */
++#define MII_ATLX_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */
++#define MII_ATLX_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */
++#define MII_ATLX_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */
++#define MII_ATLX_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */
++
++/* ATLX PHY Specific Control Register */
++#define MII_ATLX_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Func disabled */
++#define MII_ATLX_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enbld */
++#define MII_ATLX_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled */
++#define MII_ATLX_PSCR_MAC_POWERDOWN 0x0008
++#define MII_ATLX_PSCR_CLK125_DISABLE 0x0010 /* 1=CLK125 low
++ * 0=CLK125 toggling
++ */
++#define MII_ATLX_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5,
++ * Manual MDI configuration
++ */
++#define MII_ATLX_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */
++#define MII_ATLX_PSCR_AUTO_X_1000T 0x0040 /* 1000BASE-T: Auto crossover
++ * 100BASE-TX/10BASE-T: MDI
++ * Mode */
++#define MII_ATLX_PSCR_AUTO_X_MODE 0x0060 /* Auto crossover enabled
++ * all speeds.
++ */
++#define MII_ATLX_PSCR_10BT_EXT_DIST_ENABLE 0x0080 /* 1=Enable Extended
++ * 10BASE-T distance
++ * (Lower 10BASE-T RX
++ * Threshold)
++ * 0=Normal 10BASE-T RX
++ * Threshold
++ */
++#define MII_ATLX_PSCR_MII_5BIT_ENABLE 0x0100 /* 1=5-Bit interface in
++ * 100BASE-TX
++ * 0=MII interface in
++ * 100BASE-TX
++ */
++#define MII_ATLX_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler dsbl */
++#define MII_ATLX_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */
++#define MII_ATLX_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */
++#define MII_ATLX_PSCR_POLARITY_REVERSAL_SHIFT 1
++#define MII_ATLX_PSCR_AUTO_X_MODE_SHIFT 5
++#define MII_ATLX_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7
++
++/* ATLX PHY Specific Status Register */
++#define MII_ATLX_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */
++#define MII_ATLX_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */
++#define MII_ATLX_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */
++#define MII_ATLX_PSSR_10MBS 0x0000 /* 00=10Mbs */
++#define MII_ATLX_PSSR_100MBS 0x4000 /* 01=100Mbs */
++#define MII_ATLX_PSSR_1000MBS 0x8000 /* 10=1000Mbs */
++
++/* PCI Command Register Bit Definitions */
++#define PCI_REG_COMMAND 0x04 /* PCI Command Register */
++#define CMD_IO_SPACE 0x0001
++#define CMD_MEMORY_SPACE 0x0002
++#define CMD_BUS_MASTER 0x0004
++
++/* Wake Up Filter Control */
++#define ATLX_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
++#define ATLX_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */
++#define ATLX_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */
++#define ATLX_WUFC_MC 0x00000008 /* Multicast Wakeup Enable */
++#define ATLX_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */
++
++#define ADVERTISE_10_HALF 0x0001
++#define ADVERTISE_10_FULL 0x0002
++#define ADVERTISE_100_HALF 0x0004
++#define ADVERTISE_100_FULL 0x0008
++#define ADVERTISE_1000_HALF 0x0010
++#define ADVERTISE_1000_FULL 0x0020
++#define AUTONEG_ADVERTISE_10_100_ALL 0x000F /* All 10/100 speeds */
++#define AUTONEG_ADVERTISE_10_ALL 0x0003 /* 10Mbps Full & Half speeds */
++
++#define PHY_AUTO_NEG_TIME 45 /* 4.5 Seconds */
++#define PHY_FORCE_TIME 20 /* 2.0 Seconds */
++
++/* For checksumming, the sum of all words in the EEPROM should equal 0xBABA */
++#define EEPROM_SUM 0xBABA
++#define NODE_ADDRESS_SIZE 6
++
++struct atlx_spi_flash_dev {
++ const char *manu_name; /* manufacturer id */
++ /* op-code */
++ u8 cmd_wrsr;
++ u8 cmd_read;
++ u8 cmd_program;
++ u8 cmd_wren;
++ u8 cmd_wrdi;
++ u8 cmd_rdsr;
++ u8 cmd_rdid;
++ u8 cmd_sector_erase;
++ u8 cmd_chip_erase;
++};
++
++#endif /* ATLX_H */
+diff --git a/drivers/net/atp.c b/drivers/net/atp.c
+index 62f09e5..3d44333 100644
+--- a/drivers/net/atp.c
++++ b/drivers/net/atp.c
+@@ -378,8 +378,8 @@ static void __init get_node_ID(struct net_device *dev)
+ sa_offset = 15;
+
+ for (i = 0; i < 3; i++)
+- ((u16 *)dev->dev_addr)[i] =
+- be16_to_cpu(eeprom_op(ioaddr, EE_READ(sa_offset + i)));
++ ((__be16 *)dev->dev_addr)[i] =
++ cpu_to_be16(eeprom_op(ioaddr, EE_READ(sa_offset + i)));
+
+ write_reg(ioaddr, CMR2, CMR2_NULL);
+ }
+diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
+index 504b7ce..3634b5f 100644
+--- a/drivers/net/au1000_eth.c
++++ b/drivers/net/au1000_eth.c
+@@ -701,7 +701,7 @@ static struct net_device * au1000_probe(int port_num)
+ aup->mii_bus.write = mdiobus_write;
+ aup->mii_bus.reset = mdiobus_reset;
+ aup->mii_bus.name = "au1000_eth_mii";
+- aup->mii_bus.id = aup->mac_id;
++ snprintf(aup->mii_bus.id, MII_BUS_ID_SIZE, "%x", aup->mac_id);
+ aup->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+ for(i = 0; i < PHY_MAX_ADDR; ++i)
+ aup->mii_bus.irq[i] = PHY_POLL;
+@@ -709,11 +709,11 @@ static struct net_device * au1000_probe(int port_num)
+ /* if known, set corresponding PHY IRQs */
+ #if defined(AU1XXX_PHY_STATIC_CONFIG)
+ # if defined(AU1XXX_PHY0_IRQ)
+- if (AU1XXX_PHY0_BUSID == aup->mii_bus.id)
++ if (AU1XXX_PHY0_BUSID == aup->mac_id)
+ aup->mii_bus.irq[AU1XXX_PHY0_ADDR] = AU1XXX_PHY0_IRQ;
+ # endif
+ # if defined(AU1XXX_PHY1_IRQ)
+- if (AU1XXX_PHY1_BUSID == aup->mii_bus.id)
++ if (AU1XXX_PHY1_BUSID == aup->mac_id)
+ aup->mii_bus.irq[AU1XXX_PHY1_ADDR] = AU1XXX_PHY1_IRQ;
+ # endif
+ #endif
+diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c
+index 194949a..0b4adf4 100644
+--- a/drivers/net/ax88796.c
++++ b/drivers/net/ax88796.c
+@@ -1005,3 +1005,4 @@ module_exit(axdrv_exit);
+ MODULE_DESCRIPTION("AX88796 10/100 Ethernet platform driver");
+ MODULE_AUTHOR("Ben Dooks, <ben at simtec.co.uk>");
+ MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:ax88796");
+diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
+index 26b2dd5..4fec858 100644
+--- a/drivers/net/bfin_mac.c
++++ b/drivers/net/bfin_mac.c
+@@ -47,6 +47,7 @@
+ MODULE_AUTHOR(DRV_AUTHOR);
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION(DRV_DESC);
++MODULE_ALIAS("platform:bfin_mac");
+
+ #if defined(CONFIG_BFIN_MAC_USE_L1)
+ # define bfin_mac_alloc(dma_handle, size) l1_data_sram_zalloc(size)
+@@ -969,7 +970,7 @@ static int __init bf537mac_probe(struct net_device *dev)
+ lp->mii_bus.write = mdiobus_write;
+ lp->mii_bus.reset = mdiobus_reset;
+ lp->mii_bus.name = "bfin_mac_mdio";
+- lp->mii_bus.id = 0;
++ snprintf(lp->mii_bus.id, MII_BUS_ID_SIZE, "0");
+ lp->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+ for (i = 0; i < PHY_MAX_ADDR; ++i)
+ lp->mii_bus.irq[i] = PHY_POLL;
+@@ -1089,8 +1090,9 @@ static struct platform_driver bfin_mac_driver = {
+ .resume = bfin_mac_resume,
+ .suspend = bfin_mac_suspend,
+ .driver = {
+- .name = DRV_NAME,
+- },
++ .name = DRV_NAME,
++ .owner = THIS_MODULE,
++ },
+ };
+
+ static int __init bfin_mac_init(void)
+@@ -1106,3 +1108,4 @@ static void __exit bfin_mac_cleanup(void)
+ }
+
+ module_exit(bfin_mac_cleanup);
++
+diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
+index d16e0e1..ebb539e 100644
+--- a/drivers/net/bonding/bond_3ad.c
++++ b/drivers/net/bonding/bond_3ad.c
+@@ -2429,7 +2429,7 @@ int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct pac
+ struct slave *slave = NULL;
+ int ret = NET_RX_DROP;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ goto out;
+
+ if (!(dev->flags & IFF_MASTER))
+diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
+index 3f58c3d..5a67372 100644
+--- a/drivers/net/bonding/bond_alb.c
++++ b/drivers/net/bonding/bond_alb.c
+@@ -345,7 +345,7 @@ static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct
+ struct arp_pkt *arp = (struct arp_pkt *)skb->data;
+ int res = NET_RX_DROP;
+
+- if (bond_dev->nd_net != &init_net)
++ if (dev_net(bond_dev) != &init_net)
+ goto out;
+
+ if (!(bond_dev->flags & IFF_MASTER))
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index 0f06753..6e91b4b 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -2629,7 +2629,7 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack
+ unsigned char *arp_ptr;
+ __be32 sip, tip;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ goto out;
+
+ if (!(dev->priv_flags & IFF_BONDING) || !(dev->flags & IFF_MASTER))
+@@ -2646,10 +2646,7 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack
+ if (!slave || !slave_do_arp_validate(bond, slave))
+ goto out_unlock;
+
+- /* ARP header, plus 2 device addresses, plus 2 IP addresses. */
+- if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
+- (2 * dev->addr_len) +
+- (2 * sizeof(u32)))))
++ if (!pskb_may_pull(skb, arp_hdr_len(dev)))
+ goto out_unlock;
+
+ arp = arp_hdr(skb);
+@@ -3068,8 +3065,6 @@ out:
+
+ #ifdef CONFIG_PROC_FS
+
+-#define SEQ_START_TOKEN ((void *)1)
+-
+ static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
+ {
+ struct bonding *bond = seq->private;
+@@ -3473,7 +3468,7 @@ static int bond_netdev_event(struct notifier_block *this, unsigned long event, v
+ {
+ struct net_device *event_dev = (struct net_device *)ptr;
+
+- if (event_dev->nd_net != &init_net)
++ if (dev_net(event_dev) != &init_net)
+ return NOTIFY_DONE;
+
+ dprintk("event_dev: %s, event: %lx\n",
+@@ -3511,6 +3506,9 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event,
+ struct bonding *bond, *bond_next;
+ struct vlan_entry *vlan, *vlan_next;
+
++ if (dev_net(ifa->ifa_dev->dev) != &init_net)
++ return NOTIFY_DONE;
++
+ list_for_each_entry_safe(bond, bond_next, &bond_dev_list, bond_list) {
+ if (bond->dev == event_dev) {
+ switch (event) {
+diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
+index 14299f8..93e1363 100644
+--- a/drivers/net/cassini.c
++++ b/drivers/net/cassini.c
+@@ -532,8 +532,7 @@ static void cas_spare_free(struct cas *cp)
+ /* free spare buffers */
+ INIT_LIST_HEAD(&list);
+ spin_lock(&cp->rx_spare_lock);
+- list_splice(&cp->rx_spare_list, &list);
+- INIT_LIST_HEAD(&cp->rx_spare_list);
++ list_splice_init(&cp->rx_spare_list, &list);
+ spin_unlock(&cp->rx_spare_lock);
+ list_for_each_safe(elem, tmp, &list) {
+ cas_page_free(cp, list_entry(elem, cas_page_t, list));
+@@ -546,13 +545,11 @@ static void cas_spare_free(struct cas *cp)
+ * lock than used everywhere else to manipulate this list.
+ */
+ spin_lock(&cp->rx_inuse_lock);
+- list_splice(&cp->rx_inuse_list, &list);
+- INIT_LIST_HEAD(&cp->rx_inuse_list);
++ list_splice_init(&cp->rx_inuse_list, &list);
+ spin_unlock(&cp->rx_inuse_lock);
+ #else
+ spin_lock(&cp->rx_spare_lock);
+- list_splice(&cp->rx_inuse_list, &list);
+- INIT_LIST_HEAD(&cp->rx_inuse_list);
++ list_splice_init(&cp->rx_inuse_list, &list);
+ spin_unlock(&cp->rx_spare_lock);
+ #endif
+ list_for_each_safe(elem, tmp, &list) {
+@@ -573,8 +570,7 @@ static void cas_spare_recover(struct cas *cp, const gfp_t flags)
+ /* make a local copy of the list */
+ INIT_LIST_HEAD(&list);
+ spin_lock(&cp->rx_inuse_lock);
+- list_splice(&cp->rx_inuse_list, &list);
+- INIT_LIST_HEAD(&cp->rx_inuse_list);
++ list_splice_init(&cp->rx_inuse_list, &list);
+ spin_unlock(&cp->rx_inuse_lock);
+
+ list_for_each_safe(elem, tmp, &list) {
+diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
+index c85194f..2b5740b 100644
+--- a/drivers/net/cpmac.c
++++ b/drivers/net/cpmac.c
+@@ -42,6 +42,7 @@
+ MODULE_AUTHOR("Eugene Konev <ejka at imfi.kspu.ru>");
+ MODULE_DESCRIPTION("TI AR7 ethernet driver (CPMAC)");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:cpmac");
+
+ static int debug_level = 8;
+ static int dumb_switch;
+@@ -987,7 +988,7 @@ static int external_switch;
+ static int __devinit cpmac_probe(struct platform_device *pdev)
+ {
+ int rc, phy_id, i;
+- int mdio_bus_id = cpmac_mii.id;
++ char *mdio_bus_id = "0";
+ struct resource *mem;
+ struct cpmac_priv *priv;
+ struct net_device *dev;
+@@ -1008,8 +1009,6 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
+ if (external_switch || dumb_switch) {
+ struct fixed_phy_status status = {};
+
+- mdio_bus_id = 0;
+-
+ /*
+ * FIXME: this should be in the platform code!
+ * Since there is not platform code at all (that is,
+@@ -1105,6 +1104,7 @@ static int __devexit cpmac_remove(struct platform_device *pdev)
+
+ static struct platform_driver cpmac_driver = {
+ .driver.name = "cpmac",
++ .driver.owner = THIS_MODULE,
+ .probe = cpmac_probe,
+ .remove = __devexit_p(cpmac_remove),
+ };
+@@ -1143,6 +1143,7 @@ int __devinit cpmac_init(void)
+ }
+
+ cpmac_mii.phy_mask = ~(mask | 0x80000000);
++ snprintf(cpmac_mii.id, MII_BUS_ID_SIZE, "0");
+
+ res = mdiobus_register(&cpmac_mii);
+ if (res)
+diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h
+index eb305a0..4fdb13f 100644
+--- a/drivers/net/cxgb3/adapter.h
++++ b/drivers/net/cxgb3/adapter.h
+@@ -43,7 +43,6 @@
+ #include <linux/mutex.h>
+ #include <linux/bitops.h>
+ #include "t3cdev.h"
+-#include <asm/semaphore.h>
+ #include <asm/io.h>
+
+ struct vlan_group;
+diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
+index fd2e05b..05e5f59 100644
+--- a/drivers/net/cxgb3/cxgb3_main.c
++++ b/drivers/net/cxgb3/cxgb3_main.c
+@@ -1014,8 +1014,8 @@ static int offload_open(struct net_device *dev)
+ adapter->port[0]->mtu : 0xffff);
+ init_smt(adapter);
+
+- /* Never mind if the next step fails */
+- sysfs_create_group(&tdev->lldev->dev.kobj, &offload_attr_group);
++ if (sysfs_create_group(&tdev->lldev->dev.kobj, &offload_attr_group))
++ dev_dbg(&dev->dev, "cannot create sysfs group\n");
+
+ /* Call back all registered clients */
+ cxgb3_add_clients(tdev);
+diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c
+index 901c824..ff9c013 100644
+--- a/drivers/net/cxgb3/cxgb3_offload.c
++++ b/drivers/net/cxgb3/cxgb3_offload.c
+@@ -833,10 +833,26 @@ static int do_trace(struct t3cdev *dev, struct sk_buff *skb)
+ return 0;
+ }
+
++/*
++ * That skb would better have come from process_responses() where we abuse
++ * ->priority and ->csum to carry our data. NB: if we get to per-arch
++ * ->csum, the things might get really interesting here.
++ */
++
++static inline u32 get_hwtid(struct sk_buff *skb)
++{
++ return ntohl((__force __be32)skb->priority) >> 8 & 0xfffff;
++}
++
++static inline u32 get_opcode(struct sk_buff *skb)
++{
++ return G_OPCODE(ntohl((__force __be32)skb->csum));
++}
++
+ static int do_term(struct t3cdev *dev, struct sk_buff *skb)
+ {
+- unsigned int hwtid = ntohl(skb->priority) >> 8 & 0xfffff;
+- unsigned int opcode = G_OPCODE(ntohl(skb->csum));
++ unsigned int hwtid = get_hwtid(skb);
++ unsigned int opcode = get_opcode(skb);
+ struct t3c_tid_entry *t3c_tid;
+
+ t3c_tid = lookup_tid(&(T3C_DATA(dev))->tid_maps, hwtid);
+@@ -914,7 +930,7 @@ int process_rx(struct t3cdev *dev, struct sk_buff **skbs, int n)
+ {
+ while (n--) {
+ struct sk_buff *skb = *skbs++;
+- unsigned int opcode = G_OPCODE(ntohl(skb->csum));
++ unsigned int opcode = get_opcode(skb);
+ int ret = cpl_handlers[opcode] (dev, skb);
+
+ #if VALIDATE_TID
+diff --git a/drivers/net/cxgb3/l2t.c b/drivers/net/cxgb3/l2t.c
+index 865faee..f510140 100644
+--- a/drivers/net/cxgb3/l2t.c
++++ b/drivers/net/cxgb3/l2t.c
+@@ -407,7 +407,7 @@ found:
+ } else if (neigh->nud_state & (NUD_CONNECTED|NUD_STALE))
+ setup_l2e_send_pending(dev, NULL, e);
+ } else {
+- e->state = neigh_is_connected(neigh) ?
++ e->state = neigh->nud_state & NUD_CONNECTED ?
+ L2T_STATE_VALID : L2T_STATE_STALE;
+ if (memcmp(e->dmac, neigh->ha, 6))
+ setup_l2e_send_pending(dev, NULL, e);
+diff --git a/drivers/net/cxgb3/t3cdev.h b/drivers/net/cxgb3/t3cdev.h
+index 77fcc1a..a18c8a1 100644
+--- a/drivers/net/cxgb3/t3cdev.h
++++ b/drivers/net/cxgb3/t3cdev.h
+@@ -34,7 +34,6 @@
+
+ #include <linux/list.h>
+ #include <asm/atomic.h>
+-#include <asm/semaphore.h>
+ #include <linux/netdevice.h>
+ #include <linux/proc_fs.h>
+ #include <linux/skbuff.h>
+diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
+index ddc30c4..c062aac 100644
+--- a/drivers/net/defxx.c
++++ b/drivers/net/defxx.c
+@@ -971,7 +971,8 @@ static int __devinit dfx_driver_init(struct net_device *dev,
+ int alloc_size; /* total buffer size needed */
+ char *top_v, *curr_v; /* virtual addrs into memory block */
+ dma_addr_t top_p, curr_p; /* physical addrs into memory block */
+- u32 data, le32; /* host data register value */
++ u32 data; /* host data register value */
++ __le32 le32;
+ char *board_name = NULL;
+
+ DBG_printk("In dfx_driver_init...\n");
+diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
+index d63cc93..e6fe261 100644
+--- a/drivers/net/dm9000.c
++++ b/drivers/net/dm9000.c
+@@ -1418,3 +1418,4 @@ module_exit(dm9000_cleanup);
+ MODULE_AUTHOR("Sascha Hauer, Ben Dooks");
+ MODULE_DESCRIPTION("Davicom DM9000 network driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:dm9000");
+diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
+index 3b84028..31feae1 100644
+--- a/drivers/net/e1000/e1000.h
++++ b/drivers/net/e1000/e1000.h
+@@ -161,13 +161,13 @@ struct e1000_buffer {
+ struct sk_buff *skb;
+ dma_addr_t dma;
+ unsigned long time_stamp;
+- uint16_t length;
+- uint16_t next_to_watch;
++ u16 length;
++ u16 next_to_watch;
+ };
+
+
+ struct e1000_ps_page { struct page *ps_page[PS_PAGE_BUFFERS]; };
+-struct e1000_ps_page_dma { uint64_t ps_page_dma[PS_PAGE_BUFFERS]; };
++struct e1000_ps_page_dma { u64 ps_page_dma[PS_PAGE_BUFFERS]; };
+
+ struct e1000_tx_ring {
+ /* pointer to the descriptor ring memory */
+@@ -186,9 +186,9 @@ struct e1000_tx_ring {
+ struct e1000_buffer *buffer_info;
+
+ spinlock_t tx_lock;
+- uint16_t tdh;
+- uint16_t tdt;
+- boolean_t last_tx_tso;
++ u16 tdh;
++ u16 tdt;
++ bool last_tx_tso;
+ };
+
+ struct e1000_rx_ring {
+@@ -213,8 +213,8 @@ struct e1000_rx_ring {
+ /* cpu for rx queue */
+ int cpu;
+
+- uint16_t rdh;
+- uint16_t rdt;
++ u16 rdh;
++ u16 rdt;
+ };
+
+ #define E1000_DESC_UNUSED(R) \
+@@ -237,31 +237,30 @@ struct e1000_adapter {
+ struct timer_list watchdog_timer;
+ struct timer_list phy_info_timer;
+ struct vlan_group *vlgrp;
+- uint16_t mng_vlan_id;
+- uint32_t bd_number;
+- uint32_t rx_buffer_len;
+- uint32_t wol;
+- uint32_t smartspeed;
+- uint32_t en_mng_pt;
+- uint16_t link_speed;
+- uint16_t link_duplex;
++ u16 mng_vlan_id;
++ u32 bd_number;
++ u32 rx_buffer_len;
++ u32 wol;
++ u32 smartspeed;
++ u32 en_mng_pt;
++ u16 link_speed;
++ u16 link_duplex;
+ spinlock_t stats_lock;
+ #ifdef CONFIG_E1000_NAPI
+ spinlock_t tx_queue_lock;
+ #endif
+- atomic_t irq_sem;
+ unsigned int total_tx_bytes;
+ unsigned int total_tx_packets;
+ unsigned int total_rx_bytes;
+ unsigned int total_rx_packets;
+ /* Interrupt Throttle Rate */
+- uint32_t itr;
+- uint32_t itr_setting;
+- uint16_t tx_itr;
+- uint16_t rx_itr;
++ u32 itr;
++ u32 itr_setting;
++ u16 tx_itr;
++ u16 rx_itr;
+
+ struct work_struct reset_task;
+- uint8_t fc_autoneg;
++ u8 fc_autoneg;
+
+ struct timer_list blink_timer;
+ unsigned long led_status;
+@@ -270,30 +269,30 @@ struct e1000_adapter {
+ struct e1000_tx_ring *tx_ring; /* One per active queue */
+ unsigned int restart_queue;
+ unsigned long tx_queue_len;
+- uint32_t txd_cmd;
+- uint32_t tx_int_delay;
+- uint32_t tx_abs_int_delay;
+- uint32_t gotcl;
+- uint64_t gotcl_old;
+- uint64_t tpt_old;
+- uint64_t colc_old;
+- uint32_t tx_timeout_count;
+- uint32_t tx_fifo_head;
+- uint32_t tx_head_addr;
+- uint32_t tx_fifo_size;
+- uint8_t tx_timeout_factor;
++ u32 txd_cmd;
++ u32 tx_int_delay;
++ u32 tx_abs_int_delay;
++ u32 gotcl;
++ u64 gotcl_old;
++ u64 tpt_old;
++ u64 colc_old;
++ u32 tx_timeout_count;
++ u32 tx_fifo_head;
++ u32 tx_head_addr;
++ u32 tx_fifo_size;
++ u8 tx_timeout_factor;
+ atomic_t tx_fifo_stall;
+- boolean_t pcix_82544;
+- boolean_t detect_tx_hung;
++ bool pcix_82544;
++ bool detect_tx_hung;
+
+ /* RX */
+ #ifdef CONFIG_E1000_NAPI
+- boolean_t (*clean_rx) (struct e1000_adapter *adapter,
+- struct e1000_rx_ring *rx_ring,
+- int *work_done, int work_to_do);
++ bool (*clean_rx) (struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rx_ring,
++ int *work_done, int work_to_do);
+ #else
+- boolean_t (*clean_rx) (struct e1000_adapter *adapter,
+- struct e1000_rx_ring *rx_ring);
++ bool (*clean_rx) (struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rx_ring);
+ #endif
+ void (*alloc_rx_buf) (struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+@@ -306,17 +305,17 @@ struct e1000_adapter {
+ int num_tx_queues;
+ int num_rx_queues;
+
+- uint64_t hw_csum_err;
+- uint64_t hw_csum_good;
+- uint64_t rx_hdr_split;
+- uint32_t alloc_rx_buff_failed;
+- uint32_t rx_int_delay;
+- uint32_t rx_abs_int_delay;
+- boolean_t rx_csum;
++ u64 hw_csum_err;
++ u64 hw_csum_good;
++ u64 rx_hdr_split;
++ u32 alloc_rx_buff_failed;
++ u32 rx_int_delay;
++ u32 rx_abs_int_delay;
++ bool rx_csum;
+ unsigned int rx_ps_pages;
+- uint32_t gorcl;
+- uint64_t gorcl_old;
+- uint16_t rx_ps_bsize0;
++ u32 gorcl;
++ u64 gorcl_old;
++ u16 rx_ps_bsize0;
+
+
+ /* OS defined structs */
+@@ -330,19 +329,19 @@ struct e1000_adapter {
+ struct e1000_phy_info phy_info;
+ struct e1000_phy_stats phy_stats;
+
+- uint32_t test_icr;
++ u32 test_icr;
+ struct e1000_tx_ring test_tx_ring;
+ struct e1000_rx_ring test_rx_ring;
+
+ int msg_enable;
+- boolean_t have_msi;
++ bool have_msi;
+
+ /* to not mess up cache alignment, always add to the bottom */
+- boolean_t tso_force;
+- boolean_t smart_power_down; /* phy smart power down */
+- boolean_t quad_port_a;
++ bool tso_force;
++ bool smart_power_down; /* phy smart power down */
++ bool quad_port_a;
+ unsigned long flags;
+- uint32_t eeprom_wol;
++ u32 eeprom_wol;
+ };
+
+ enum e1000_state_t {
+diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
+index 85e66f4..701531e 100644
+--- a/drivers/net/e1000/e1000_ethtool.c
++++ b/drivers/net/e1000/e1000_ethtool.c
+@@ -36,7 +36,7 @@ extern int e1000_up(struct e1000_adapter *adapter);
+ extern void e1000_down(struct e1000_adapter *adapter);
+ extern void e1000_reinit_locked(struct e1000_adapter *adapter);
+ extern void e1000_reset(struct e1000_adapter *adapter);
+-extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
++extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx);
+ extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
+ extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
+ extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
+@@ -289,7 +289,7 @@ e1000_set_pauseparam(struct net_device *netdev,
+ return retval;
+ }
+
+-static uint32_t
++static u32
+ e1000_get_rx_csum(struct net_device *netdev)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+@@ -297,7 +297,7 @@ e1000_get_rx_csum(struct net_device *netdev)
+ }
+
+ static int
+-e1000_set_rx_csum(struct net_device *netdev, uint32_t data)
++e1000_set_rx_csum(struct net_device *netdev, u32 data)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ adapter->rx_csum = data;
+@@ -309,14 +309,14 @@ e1000_set_rx_csum(struct net_device *netdev, uint32_t data)
+ return 0;
+ }
+
+-static uint32_t
++static u32
+ e1000_get_tx_csum(struct net_device *netdev)
+ {
+ return (netdev->features & NETIF_F_HW_CSUM) != 0;
+ }
+
+ static int
+-e1000_set_tx_csum(struct net_device *netdev, uint32_t data)
++e1000_set_tx_csum(struct net_device *netdev, u32 data)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+
+@@ -335,7 +335,7 @@ e1000_set_tx_csum(struct net_device *netdev, uint32_t data)
+ }
+
+ static int
+-e1000_set_tso(struct net_device *netdev, uint32_t data)
++e1000_set_tso(struct net_device *netdev, u32 data)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ if ((adapter->hw.mac_type < e1000_82544) ||
+@@ -353,11 +353,11 @@ e1000_set_tso(struct net_device *netdev, uint32_t data)
+ netdev->features &= ~NETIF_F_TSO6;
+
+ DPRINTK(PROBE, INFO, "TSO is %s\n", data ? "Enabled" : "Disabled");
+- adapter->tso_force = TRUE;
++ adapter->tso_force = true;
+ return 0;
+ }
+
+-static uint32_t
++static u32
+ e1000_get_msglevel(struct net_device *netdev)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+@@ -365,7 +365,7 @@ e1000_get_msglevel(struct net_device *netdev)
+ }
+
+ static void
+-e1000_set_msglevel(struct net_device *netdev, uint32_t data)
++e1000_set_msglevel(struct net_device *netdev, u32 data)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ adapter->msg_enable = data;
+@@ -375,7 +375,7 @@ static int
+ e1000_get_regs_len(struct net_device *netdev)
+ {
+ #define E1000_REGS_LEN 32
+- return E1000_REGS_LEN * sizeof(uint32_t);
++ return E1000_REGS_LEN * sizeof(u32);
+ }
+
+ static void
+@@ -384,10 +384,10 @@ e1000_get_regs(struct net_device *netdev,
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
+- uint32_t *regs_buff = p;
+- uint16_t phy_data;
++ u32 *regs_buff = p;
++ u16 phy_data;
+
+- memset(p, 0, E1000_REGS_LEN * sizeof(uint32_t));
++ memset(p, 0, E1000_REGS_LEN * sizeof(u32));
+
+ regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;
+
+@@ -412,44 +412,44 @@ e1000_get_regs(struct net_device *netdev,
+ IGP01E1000_PHY_AGC_A);
+ e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_A &
+ IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+- regs_buff[13] = (uint32_t)phy_data; /* cable length */
++ regs_buff[13] = (u32)phy_data; /* cable length */
+ e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
+ IGP01E1000_PHY_AGC_B);
+ e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_B &
+ IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+- regs_buff[14] = (uint32_t)phy_data; /* cable length */
++ regs_buff[14] = (u32)phy_data; /* cable length */
+ e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
+ IGP01E1000_PHY_AGC_C);
+ e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_C &
+ IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+- regs_buff[15] = (uint32_t)phy_data; /* cable length */
++ regs_buff[15] = (u32)phy_data; /* cable length */
+ e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
+ IGP01E1000_PHY_AGC_D);
+ e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_D &
+ IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+- regs_buff[16] = (uint32_t)phy_data; /* cable length */
++ regs_buff[16] = (u32)phy_data; /* cable length */
+ regs_buff[17] = 0; /* extended 10bt distance (not needed) */
+ e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0);
+ e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS &
+ IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+- regs_buff[18] = (uint32_t)phy_data; /* cable polarity */
++ regs_buff[18] = (u32)phy_data; /* cable polarity */
+ e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
+ IGP01E1000_PHY_PCS_INIT_REG);
+ e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG &
+ IGP01E1000_PHY_PAGE_SELECT, &phy_data);
+- regs_buff[19] = (uint32_t)phy_data; /* cable polarity */
++ regs_buff[19] = (u32)phy_data; /* cable polarity */
+ regs_buff[20] = 0; /* polarity correction enabled (always) */
+ regs_buff[22] = 0; /* phy receive errors (unavailable) */
+ regs_buff[23] = regs_buff[18]; /* mdix mode */
+ e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0);
+ } else {
+ e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
+- regs_buff[13] = (uint32_t)phy_data; /* cable length */
++ regs_buff[13] = (u32)phy_data; /* cable length */
+ regs_buff[14] = 0; /* Dummy (to align w/ IGP phy reg dump) */
+ regs_buff[15] = 0; /* Dummy (to align w/ IGP phy reg dump) */
+ regs_buff[16] = 0; /* Dummy (to align w/ IGP phy reg dump) */
+ e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+- regs_buff[17] = (uint32_t)phy_data; /* extended 10bt distance */
++ regs_buff[17] = (u32)phy_data; /* extended 10bt distance */
+ regs_buff[18] = regs_buff[13]; /* cable polarity */
+ regs_buff[19] = 0; /* Dummy (to align w/ IGP phy reg dump) */
+ regs_buff[20] = regs_buff[17]; /* polarity correction */
+@@ -459,7 +459,7 @@ e1000_get_regs(struct net_device *netdev,
+ }
+ regs_buff[21] = adapter->phy_stats.idle_errors; /* phy idle errors */
+ e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
+- regs_buff[24] = (uint32_t)phy_data; /* phy local receiver status */
++ regs_buff[24] = (u32)phy_data; /* phy local receiver status */
+ regs_buff[25] = regs_buff[24]; /* phy remote receiver status */
+ if (hw->mac_type >= e1000_82540 &&
+ hw->mac_type < e1000_82571 &&
+@@ -477,14 +477,14 @@ e1000_get_eeprom_len(struct net_device *netdev)
+
+ static int
+ e1000_get_eeprom(struct net_device *netdev,
+- struct ethtool_eeprom *eeprom, uint8_t *bytes)
++ struct ethtool_eeprom *eeprom, u8 *bytes)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
+- uint16_t *eeprom_buff;
++ u16 *eeprom_buff;
+ int first_word, last_word;
+ int ret_val = 0;
+- uint16_t i;
++ u16 i;
+
+ if (eeprom->len == 0)
+ return -EINVAL;
+@@ -494,7 +494,7 @@ e1000_get_eeprom(struct net_device *netdev,
+ first_word = eeprom->offset >> 1;
+ last_word = (eeprom->offset + eeprom->len - 1) >> 1;
+
+- eeprom_buff = kmalloc(sizeof(uint16_t) *
++ eeprom_buff = kmalloc(sizeof(u16) *
+ (last_word - first_word + 1), GFP_KERNEL);
+ if (!eeprom_buff)
+ return -ENOMEM;
+@@ -514,7 +514,7 @@ e1000_get_eeprom(struct net_device *netdev,
+ for (i = 0; i < last_word - first_word + 1; i++)
+ le16_to_cpus(&eeprom_buff[i]);
+
+- memcpy(bytes, (uint8_t *)eeprom_buff + (eeprom->offset & 1),
++ memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1),
+ eeprom->len);
+ kfree(eeprom_buff);
+
+@@ -523,14 +523,14 @@ e1000_get_eeprom(struct net_device *netdev,
+
+ static int
+ e1000_set_eeprom(struct net_device *netdev,
+- struct ethtool_eeprom *eeprom, uint8_t *bytes)
++ struct ethtool_eeprom *eeprom, u8 *bytes)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
+- uint16_t *eeprom_buff;
++ u16 *eeprom_buff;
+ void *ptr;
+ int max_len, first_word, last_word, ret_val = 0;
+- uint16_t i;
++ u16 i;
+
+ if (eeprom->len == 0)
+ return -EOPNOTSUPP;
+@@ -590,7 +590,7 @@ e1000_get_drvinfo(struct net_device *netdev,
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ char firmware_version[32];
+- uint16_t eeprom_data;
++ u16 eeprom_data;
+
+ strncpy(drvinfo->driver, e1000_driver_name, 32);
+ strncpy(drvinfo->version, e1000_driver_version, 32);
+@@ -674,13 +674,13 @@ e1000_set_ringparam(struct net_device *netdev,
+ adapter->tx_ring = txdr;
+ adapter->rx_ring = rxdr;
+
+- rxdr->count = max(ring->rx_pending,(uint32_t)E1000_MIN_RXD);
+- rxdr->count = min(rxdr->count,(uint32_t)(mac_type < e1000_82544 ?
++ rxdr->count = max(ring->rx_pending,(u32)E1000_MIN_RXD);
++ rxdr->count = min(rxdr->count,(u32)(mac_type < e1000_82544 ?
+ E1000_MAX_RXD : E1000_MAX_82544_RXD));
+ rxdr->count = ALIGN(rxdr->count, REQ_RX_DESCRIPTOR_MULTIPLE);
+
+- txdr->count = max(ring->tx_pending,(uint32_t)E1000_MIN_TXD);
+- txdr->count = min(txdr->count,(uint32_t)(mac_type < e1000_82544 ?
++ txdr->count = max(ring->tx_pending,(u32)E1000_MIN_TXD);
++ txdr->count = min(txdr->count,(u32)(mac_type < e1000_82544 ?
+ E1000_MAX_TXD : E1000_MAX_82544_TXD));
+ txdr->count = ALIGN(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE);
+
+@@ -728,13 +728,13 @@ err_setup:
+ return err;
+ }
+
+-static bool reg_pattern_test(struct e1000_adapter *adapter, uint64_t *data,
+- int reg, uint32_t mask, uint32_t write)
++static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data,
++ int reg, u32 mask, u32 write)
+ {
+- static const uint32_t test[] =
++ static const u32 test[] =
+ {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
+- uint8_t __iomem *address = adapter->hw.hw_addr + reg;
+- uint32_t read;
++ u8 __iomem *address = adapter->hw.hw_addr + reg;
++ u32 read;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(test); i++) {
+@@ -751,11 +751,11 @@ static bool reg_pattern_test(struct e1000_adapter *adapter, uint64_t *data,
+ return false;
+ }
+
+-static bool reg_set_and_check(struct e1000_adapter *adapter, uint64_t *data,
+- int reg, uint32_t mask, uint32_t write)
++static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data,
++ int reg, u32 mask, u32 write)
+ {
+- uint8_t __iomem *address = adapter->hw.hw_addr + reg;
+- uint32_t read;
++ u8 __iomem *address = adapter->hw.hw_addr + reg;
++ u32 read;
+
+ writel(write & mask, address);
+ read = readl(address);
+@@ -788,10 +788,10 @@ static bool reg_set_and_check(struct e1000_adapter *adapter, uint64_t *data,
+ } while (0)
+
+ static int
+-e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
++e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
+ {
+- uint32_t value, before, after;
+- uint32_t i, toggle;
++ u32 value, before, after;
++ u32 i, toggle;
+
+ /* The status register is Read Only, so a write should fail.
+ * Some bits that get toggled are ignored.
+@@ -884,11 +884,11 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
+ }
+
+ static int
+-e1000_eeprom_test(struct e1000_adapter *adapter, uint64_t *data)
++e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data)
+ {
+- uint16_t temp;
+- uint16_t checksum = 0;
+- uint16_t i;
++ u16 temp;
++ u16 checksum = 0;
++ u16 i;
+
+ *data = 0;
+ /* Read and add up the contents of the EEPROM */
+@@ -901,7 +901,7 @@ e1000_eeprom_test(struct e1000_adapter *adapter, uint64_t *data)
+ }
+
+ /* If Checksum is not Correct return error else test passed */
+- if ((checksum != (uint16_t) EEPROM_SUM) && !(*data))
++ if ((checksum != (u16) EEPROM_SUM) && !(*data))
+ *data = 2;
+
+ return *data;
+@@ -919,11 +919,12 @@ e1000_test_intr(int irq, void *data)
+ }
+
+ static int
+-e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
++e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
+ {
+ struct net_device *netdev = adapter->netdev;
+- uint32_t mask, i=0, shared_int = TRUE;
+- uint32_t irq = adapter->pdev->irq;
++ u32 mask, i = 0;
++ bool shared_int = true;
++ u32 irq = adapter->pdev->irq;
+
+ *data = 0;
+
+@@ -931,7 +932,7 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
+ /* Hook up test interrupt handler just for this test */
+ if (!request_irq(irq, &e1000_test_intr, IRQF_PROBE_SHARED, netdev->name,
+ netdev))
+- shared_int = FALSE;
++ shared_int = false;
+ else if (request_irq(irq, &e1000_test_intr, IRQF_SHARED,
+ netdev->name, netdev)) {
+ *data = 1;
+@@ -1069,7 +1070,7 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
+ struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
+ struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
+ struct pci_dev *pdev = adapter->pdev;
+- uint32_t rctl;
++ u32 rctl;
+ int i, ret_val;
+
+ /* Setup Tx descriptor ring and Tx buffers */
+@@ -1095,8 +1096,8 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
+ txdr->next_to_use = txdr->next_to_clean = 0;
+
+ E1000_WRITE_REG(&adapter->hw, TDBAL,
+- ((uint64_t) txdr->dma & 0x00000000FFFFFFFF));
+- E1000_WRITE_REG(&adapter->hw, TDBAH, ((uint64_t) txdr->dma >> 32));
++ ((u64) txdr->dma & 0x00000000FFFFFFFF));
++ E1000_WRITE_REG(&adapter->hw, TDBAH, ((u64) txdr->dma >> 32));
+ E1000_WRITE_REG(&adapter->hw, TDLEN,
+ txdr->count * sizeof(struct e1000_tx_desc));
+ E1000_WRITE_REG(&adapter->hw, TDH, 0);
+@@ -1152,8 +1153,8 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
+ rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN);
+ E1000_WRITE_REG(&adapter->hw, RDBAL,
+- ((uint64_t) rxdr->dma & 0xFFFFFFFF));
+- E1000_WRITE_REG(&adapter->hw, RDBAH, ((uint64_t) rxdr->dma >> 32));
++ ((u64) rxdr->dma & 0xFFFFFFFF));
++ E1000_WRITE_REG(&adapter->hw, RDBAH, ((u64) rxdr->dma >> 32));
+ E1000_WRITE_REG(&adapter->hw, RDLEN, rxdr->size);
+ E1000_WRITE_REG(&adapter->hw, RDH, 0);
+ E1000_WRITE_REG(&adapter->hw, RDT, 0);
+@@ -1201,7 +1202,7 @@ e1000_phy_disable_receiver(struct e1000_adapter *adapter)
+ static void
+ e1000_phy_reset_clk_and_crs(struct e1000_adapter *adapter)
+ {
+- uint16_t phy_reg;
++ u16 phy_reg;
+
+ /* Because we reset the PHY above, we need to re-force TX_CLK in the
+ * Extended PHY Specific Control Register to 25MHz clock. This
+@@ -1225,8 +1226,8 @@ e1000_phy_reset_clk_and_crs(struct e1000_adapter *adapter)
+ static int
+ e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter)
+ {
+- uint32_t ctrl_reg;
+- uint16_t phy_reg;
++ u32 ctrl_reg;
++ u16 phy_reg;
+
+ /* Setup the Device Control Register for PHY loopback test. */
+
+@@ -1292,10 +1293,10 @@ e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter)
+ static int
+ e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
+ {
+- uint32_t ctrl_reg = 0;
+- uint32_t stat_reg = 0;
++ u32 ctrl_reg = 0;
++ u32 stat_reg = 0;
+
+- adapter->hw.autoneg = FALSE;
++ adapter->hw.autoneg = false;
+
+ if (adapter->hw.phy_type == e1000_phy_m88) {
+ /* Auto-MDI/MDIX Off */
+@@ -1362,8 +1363,8 @@ e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
+ static int
+ e1000_set_phy_loopback(struct e1000_adapter *adapter)
+ {
+- uint16_t phy_reg = 0;
+- uint16_t count = 0;
++ u16 phy_reg = 0;
++ u16 count = 0;
+
+ switch (adapter->hw.mac_type) {
+ case e1000_82543:
+@@ -1415,7 +1416,7 @@ static int
+ e1000_setup_loopback_test(struct e1000_adapter *adapter)
+ {
+ struct e1000_hw *hw = &adapter->hw;
+- uint32_t rctl;
++ u32 rctl;
+
+ if (hw->media_type == e1000_media_type_fiber ||
+ hw->media_type == e1000_media_type_internal_serdes) {
+@@ -1450,8 +1451,8 @@ static void
+ e1000_loopback_cleanup(struct e1000_adapter *adapter)
+ {
+ struct e1000_hw *hw = &adapter->hw;
+- uint32_t rctl;
+- uint16_t phy_reg;
++ u32 rctl;
++ u16 phy_reg;
+
+ rctl = E1000_READ_REG(hw, RCTL);
+ rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
+@@ -1473,7 +1474,7 @@ e1000_loopback_cleanup(struct e1000_adapter *adapter)
+ case e1000_82545_rev_3:
+ case e1000_82546_rev_3:
+ default:
+- hw->autoneg = TRUE;
++ hw->autoneg = true;
+ if (hw->phy_type == e1000_phy_gg82563)
+ e1000_write_phy_reg(hw,
+ GG82563_PHY_KMRN_MODE_CTRL,
+@@ -1577,7 +1578,7 @@ e1000_run_loopback_test(struct e1000_adapter *adapter)
+ }
+
+ static int
+-e1000_loopback_test(struct e1000_adapter *adapter, uint64_t *data)
++e1000_loopback_test(struct e1000_adapter *adapter, u64 *data)
+ {
+ /* PHY loopback cannot be performed if SoL/IDER
+ * sessions are active */
+@@ -1602,18 +1603,18 @@ out:
+ }
+
+ static int
+-e1000_link_test(struct e1000_adapter *adapter, uint64_t *data)
++e1000_link_test(struct e1000_adapter *adapter, u64 *data)
+ {
+ *data = 0;
+ if (adapter->hw.media_type == e1000_media_type_internal_serdes) {
+ int i = 0;
+- adapter->hw.serdes_link_down = TRUE;
++ adapter->hw.serdes_link_down = true;
+
+ /* On some blade server designs, link establishment
+ * could take as long as 2-3 minutes */
+ do {
+ e1000_check_for_link(&adapter->hw);
+- if (adapter->hw.serdes_link_down == FALSE)
++ if (!adapter->hw.serdes_link_down)
+ return *data;
+ msleep(20);
+ } while (i++ < 3750);
+@@ -1646,19 +1647,19 @@ e1000_get_sset_count(struct net_device *netdev, int sset)
+
+ static void
+ e1000_diag_test(struct net_device *netdev,
+- struct ethtool_test *eth_test, uint64_t *data)
++ struct ethtool_test *eth_test, u64 *data)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+- boolean_t if_running = netif_running(netdev);
++ bool if_running = netif_running(netdev);
+
+ set_bit(__E1000_TESTING, &adapter->flags);
+ if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
+ /* Offline tests */
+
+ /* save speed, duplex, autoneg settings */
+- uint16_t autoneg_advertised = adapter->hw.autoneg_advertised;
+- uint8_t forced_speed_duplex = adapter->hw.forced_speed_duplex;
+- uint8_t autoneg = adapter->hw.autoneg;
++ u16 autoneg_advertised = adapter->hw.autoneg_advertised;
++ u8 forced_speed_duplex = adapter->hw.forced_speed_duplex;
++ u8 autoneg = adapter->hw.autoneg;
+
+ DPRINTK(HW, INFO, "offline testing starting\n");
+
+@@ -1876,7 +1877,7 @@ e1000_led_blink_callback(unsigned long data)
+ }
+
+ static int
+-e1000_phys_id(struct net_device *netdev, uint32_t data)
++e1000_phys_id(struct net_device *netdev, u32 data)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+
+@@ -1926,7 +1927,7 @@ e1000_nway_reset(struct net_device *netdev)
+
+ static void
+ e1000_get_ethtool_stats(struct net_device *netdev,
+- struct ethtool_stats *stats, uint64_t *data)
++ struct ethtool_stats *stats, u64 *data)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ int i;
+@@ -1935,15 +1936,15 @@ e1000_get_ethtool_stats(struct net_device *netdev,
+ for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
+ char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset;
+ data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
+- sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p;
++ sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+ }
+ /* BUG_ON(i != E1000_STATS_LEN); */
+ }
+
+ static void
+-e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
++e1000_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
+ {
+- uint8_t *p = data;
++ u8 *p = data;
+ int i;
+
+ switch (stringset) {
+diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
+index 7c6888c..9a4b6cb 100644
+--- a/drivers/net/e1000/e1000_hw.c
++++ b/drivers/net/e1000/e1000_hw.c
+@@ -33,106 +33,107 @@
+
+ #include "e1000_hw.h"
+
+-static int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask);
+-static void e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask);
+-static int32_t e1000_read_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *data);
+-static int32_t e1000_write_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t data);
+-static int32_t e1000_get_software_semaphore(struct e1000_hw *hw);
++static s32 e1000_swfw_sync_acquire(struct e1000_hw *hw, u16 mask);
++static void e1000_swfw_sync_release(struct e1000_hw *hw, u16 mask);
++static s32 e1000_read_kmrn_reg(struct e1000_hw *hw, u32 reg_addr, u16 *data);
++static s32 e1000_write_kmrn_reg(struct e1000_hw *hw, u32 reg_addr, u16 data);
++static s32 e1000_get_software_semaphore(struct e1000_hw *hw);
+ static void e1000_release_software_semaphore(struct e1000_hw *hw);
+
+-static uint8_t e1000_arc_subsystem_valid(struct e1000_hw *hw);
+-static int32_t e1000_check_downshift(struct e1000_hw *hw);
+-static int32_t e1000_check_polarity(struct e1000_hw *hw, e1000_rev_polarity *polarity);
++static u8 e1000_arc_subsystem_valid(struct e1000_hw *hw);
++static s32 e1000_check_downshift(struct e1000_hw *hw);
++static s32 e1000_check_polarity(struct e1000_hw *hw, e1000_rev_polarity *polarity);
+ static void e1000_clear_hw_cntrs(struct e1000_hw *hw);
+ static void e1000_clear_vfta(struct e1000_hw *hw);
+-static int32_t e1000_commit_shadow_ram(struct e1000_hw *hw);
+-static int32_t e1000_config_dsp_after_link_change(struct e1000_hw *hw, boolean_t link_up);
+-static int32_t e1000_config_fc_after_link_up(struct e1000_hw *hw);
+-static int32_t e1000_detect_gig_phy(struct e1000_hw *hw);
+-static int32_t e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t bank);
+-static int32_t e1000_get_auto_rd_done(struct e1000_hw *hw);
+-static int32_t e1000_get_cable_length(struct e1000_hw *hw, uint16_t *min_length, uint16_t *max_length);
+-static int32_t e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw);
+-static int32_t e1000_get_phy_cfg_done(struct e1000_hw *hw);
+-static int32_t e1000_get_software_flag(struct e1000_hw *hw);
+-static int32_t e1000_ich8_cycle_init(struct e1000_hw *hw);
+-static int32_t e1000_ich8_flash_cycle(struct e1000_hw *hw, uint32_t timeout);
+-static int32_t e1000_id_led_init(struct e1000_hw *hw);
+-static int32_t e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw, uint32_t cnf_base_addr, uint32_t cnf_size);
+-static int32_t e1000_init_lcd_from_nvm(struct e1000_hw *hw);
++static s32 e1000_commit_shadow_ram(struct e1000_hw *hw);
++static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw,
++ bool link_up);
++static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw);
++static s32 e1000_detect_gig_phy(struct e1000_hw *hw);
++static s32 e1000_erase_ich8_4k_segment(struct e1000_hw *hw, u32 bank);
++static s32 e1000_get_auto_rd_done(struct e1000_hw *hw);
++static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length, u16 *max_length);
++static s32 e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw);
++static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw);
++static s32 e1000_get_software_flag(struct e1000_hw *hw);
++static s32 e1000_ich8_cycle_init(struct e1000_hw *hw);
++static s32 e1000_ich8_flash_cycle(struct e1000_hw *hw, u32 timeout);
++static s32 e1000_id_led_init(struct e1000_hw *hw);
++static s32 e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw, u32 cnf_base_addr, u32 cnf_size);
++static s32 e1000_init_lcd_from_nvm(struct e1000_hw *hw);
+ static void e1000_init_rx_addrs(struct e1000_hw *hw);
+ static void e1000_initialize_hardware_bits(struct e1000_hw *hw);
+-static boolean_t e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw);
+-static int32_t e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw);
+-static int32_t e1000_mng_enable_host_if(struct e1000_hw *hw);
+-static int32_t e1000_mng_host_if_write(struct e1000_hw *hw, uint8_t *buffer, uint16_t length, uint16_t offset, uint8_t *sum);
+-static int32_t e1000_mng_write_cmd_header(struct e1000_hw* hw, struct e1000_host_mng_command_header* hdr);
+-static int32_t e1000_mng_write_commit(struct e1000_hw *hw);
+-static int32_t e1000_phy_ife_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
+-static int32_t e1000_phy_igp_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
+-static int32_t e1000_read_eeprom_eerd(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data);
+-static int32_t e1000_write_eeprom_eewr(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data);
+-static int32_t e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd);
+-static int32_t e1000_phy_m88_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
++static bool e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw);
++static s32 e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw);
++static s32 e1000_mng_enable_host_if(struct e1000_hw *hw);
++static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length, u16 offset, u8 *sum);
++static s32 e1000_mng_write_cmd_header(struct e1000_hw* hw, struct e1000_host_mng_command_header* hdr);
++static s32 e1000_mng_write_commit(struct e1000_hw *hw);
++static s32 e1000_phy_ife_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
++static s32 e1000_phy_igp_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
++static s32 e1000_read_eeprom_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
++static s32 e1000_write_eeprom_eewr(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
++static s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd);
++static s32 e1000_phy_m88_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
+ static void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw);
+-static int32_t e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t *data);
+-static int32_t e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t byte);
+-static int32_t e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t byte);
+-static int32_t e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t *data);
+-static int32_t e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size, uint16_t *data);
+-static int32_t e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size, uint16_t data);
+-static int32_t e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data);
+-static int32_t e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data);
++static s32 e1000_read_ich8_byte(struct e1000_hw *hw, u32 index, u8 *data);
++static s32 e1000_verify_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte);
++static s32 e1000_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte);
++static s32 e1000_read_ich8_word(struct e1000_hw *hw, u32 index, u16 *data);
++static s32 e1000_read_ich8_data(struct e1000_hw *hw, u32 index, u32 size, u16 *data);
++static s32 e1000_write_ich8_data(struct e1000_hw *hw, u32 index, u32 size, u16 data);
++static s32 e1000_read_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
++static s32 e1000_write_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
+ static void e1000_release_software_flag(struct e1000_hw *hw);
+-static int32_t e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active);
+-static int32_t e1000_set_d0_lplu_state(struct e1000_hw *hw, boolean_t active);
+-static int32_t e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop);
++static s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active);
++static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active);
++static s32 e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, u32 no_snoop);
+ static void e1000_set_pci_express_master_disable(struct e1000_hw *hw);
+-static int32_t e1000_wait_autoneg(struct e1000_hw *hw);
+-static void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value);
+-static int32_t e1000_set_phy_type(struct e1000_hw *hw);
++static s32 e1000_wait_autoneg(struct e1000_hw *hw);
++static void e1000_write_reg_io(struct e1000_hw *hw, u32 offset, u32 value);
++static s32 e1000_set_phy_type(struct e1000_hw *hw);
+ static void e1000_phy_init_script(struct e1000_hw *hw);
+-static int32_t e1000_setup_copper_link(struct e1000_hw *hw);
+-static int32_t e1000_setup_fiber_serdes_link(struct e1000_hw *hw);
+-static int32_t e1000_adjust_serdes_amplitude(struct e1000_hw *hw);
+-static int32_t e1000_phy_force_speed_duplex(struct e1000_hw *hw);
+-static int32_t e1000_config_mac_to_phy(struct e1000_hw *hw);
+-static void e1000_raise_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl);
+-static void e1000_lower_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl);
+-static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, uint32_t data,
+- uint16_t count);
+-static uint16_t e1000_shift_in_mdi_bits(struct e1000_hw *hw);
+-static int32_t e1000_phy_reset_dsp(struct e1000_hw *hw);
+-static int32_t e1000_write_eeprom_spi(struct e1000_hw *hw, uint16_t offset,
+- uint16_t words, uint16_t *data);
+-static int32_t e1000_write_eeprom_microwire(struct e1000_hw *hw,
+- uint16_t offset, uint16_t words,
+- uint16_t *data);
+-static int32_t e1000_spi_eeprom_ready(struct e1000_hw *hw);
+-static void e1000_raise_ee_clk(struct e1000_hw *hw, uint32_t *eecd);
+-static void e1000_lower_ee_clk(struct e1000_hw *hw, uint32_t *eecd);
+-static void e1000_shift_out_ee_bits(struct e1000_hw *hw, uint16_t data,
+- uint16_t count);
+-static int32_t e1000_write_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,
+- uint16_t phy_data);
+-static int32_t e1000_read_phy_reg_ex(struct e1000_hw *hw,uint32_t reg_addr,
+- uint16_t *phy_data);
+-static uint16_t e1000_shift_in_ee_bits(struct e1000_hw *hw, uint16_t count);
+-static int32_t e1000_acquire_eeprom(struct e1000_hw *hw);
++static s32 e1000_setup_copper_link(struct e1000_hw *hw);
++static s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw);
++static s32 e1000_adjust_serdes_amplitude(struct e1000_hw *hw);
++static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw);
++static s32 e1000_config_mac_to_phy(struct e1000_hw *hw);
++static void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl);
++static void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl);
++static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data,
++ u16 count);
++static u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw);
++static s32 e1000_phy_reset_dsp(struct e1000_hw *hw);
++static s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset,
++ u16 words, u16 *data);
++static s32 e1000_write_eeprom_microwire(struct e1000_hw *hw,
++ u16 offset, u16 words,
++ u16 *data);
++static s32 e1000_spi_eeprom_ready(struct e1000_hw *hw);
++static void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd);
++static void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd);
++static void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data,
++ u16 count);
++static s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
++ u16 phy_data);
++static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw,u32 reg_addr,
++ u16 *phy_data);
++static u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count);
++static s32 e1000_acquire_eeprom(struct e1000_hw *hw);
+ static void e1000_release_eeprom(struct e1000_hw *hw);
+ static void e1000_standby_eeprom(struct e1000_hw *hw);
+-static int32_t e1000_set_vco_speed(struct e1000_hw *hw);
+-static int32_t e1000_polarity_reversal_workaround(struct e1000_hw *hw);
+-static int32_t e1000_set_phy_mode(struct e1000_hw *hw);
+-static int32_t e1000_host_if_read_cookie(struct e1000_hw *hw, uint8_t *buffer);
+-static uint8_t e1000_calculate_mng_checksum(char *buffer, uint32_t length);
+-static int32_t e1000_configure_kmrn_for_10_100(struct e1000_hw *hw,
+- uint16_t duplex);
+-static int32_t e1000_configure_kmrn_for_1000(struct e1000_hw *hw);
++static s32 e1000_set_vco_speed(struct e1000_hw *hw);
++static s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw);
++static s32 e1000_set_phy_mode(struct e1000_hw *hw);
++static s32 e1000_host_if_read_cookie(struct e1000_hw *hw, u8 *buffer);
++static u8 e1000_calculate_mng_checksum(char *buffer, u32 length);
++static s32 e1000_configure_kmrn_for_10_100(struct e1000_hw *hw,
++ u16 duplex);
++static s32 e1000_configure_kmrn_for_1000(struct e1000_hw *hw);
+
+ /* IGP cable length table */
+ static const
+-uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =
++u16 e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =
+ { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25,
+ 25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40,
+@@ -143,7 +144,7 @@ uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =
+ 110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120};
+
+ static const
+-uint16_t e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] =
++u16 e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] =
+ { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21,
+ 0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41,
+ 6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61,
+@@ -158,7 +159,7 @@ uint16_t e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] =
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_set_phy_type(struct e1000_hw *hw)
+ {
+ DEBUGFUNC("e1000_set_phy_type");
+@@ -212,8 +213,8 @@ e1000_set_phy_type(struct e1000_hw *hw)
+ static void
+ e1000_phy_init_script(struct e1000_hw *hw)
+ {
+- uint32_t ret_val;
+- uint16_t phy_saved_data;
++ u32 ret_val;
++ u16 phy_saved_data;
+
+ DEBUGFUNC("e1000_phy_init_script");
+
+@@ -271,7 +272,7 @@ e1000_phy_init_script(struct e1000_hw *hw)
+ e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
+
+ if (hw->mac_type == e1000_82547) {
+- uint16_t fused, fine, coarse;
++ u16 fused, fine, coarse;
+
+ /* Move to analog registers page */
+ e1000_read_phy_reg(hw, IGP01E1000_ANALOG_SPARE_FUSE_STATUS, &fused);
+@@ -305,7 +306,7 @@ e1000_phy_init_script(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_set_mac_type(struct e1000_hw *hw)
+ {
+ DEBUGFUNC("e1000_set_mac_type");
+@@ -425,22 +426,22 @@ e1000_set_mac_type(struct e1000_hw *hw)
+
+ switch (hw->mac_type) {
+ case e1000_ich8lan:
+- hw->swfwhw_semaphore_present = TRUE;
+- hw->asf_firmware_present = TRUE;
++ hw->swfwhw_semaphore_present = true;
++ hw->asf_firmware_present = true;
+ break;
+ case e1000_80003es2lan:
+- hw->swfw_sync_present = TRUE;
++ hw->swfw_sync_present = true;
+ /* fall through */
+ case e1000_82571:
+ case e1000_82572:
+ case e1000_82573:
+- hw->eeprom_semaphore_present = TRUE;
++ hw->eeprom_semaphore_present = true;
+ /* fall through */
+ case e1000_82541:
+ case e1000_82547:
+ case e1000_82541_rev_2:
+ case e1000_82547_rev_2:
+- hw->asf_firmware_present = TRUE;
++ hw->asf_firmware_present = true;
+ break;
+ default:
+ break;
+@@ -450,20 +451,20 @@ e1000_set_mac_type(struct e1000_hw *hw)
+ * FD mode
+ */
+ if (hw->mac_type == e1000_82543)
+- hw->bad_tx_carr_stats_fd = TRUE;
++ hw->bad_tx_carr_stats_fd = true;
+
+ /* capable of receiving management packets to the host */
+ if (hw->mac_type >= e1000_82571)
+- hw->has_manc2h = TRUE;
++ hw->has_manc2h = true;
+
+ /* In rare occasions, ESB2 systems would end up started without
+ * the RX unit being turned on.
+ */
+ if (hw->mac_type == e1000_80003es2lan)
+- hw->rx_needs_kicking = TRUE;
++ hw->rx_needs_kicking = true;
+
+ if (hw->mac_type > e1000_82544)
+- hw->has_smbus = TRUE;
++ hw->has_smbus = true;
+
+ return E1000_SUCCESS;
+ }
+@@ -476,13 +477,13 @@ e1000_set_mac_type(struct e1000_hw *hw)
+ void
+ e1000_set_media_type(struct e1000_hw *hw)
+ {
+- uint32_t status;
++ u32 status;
+
+ DEBUGFUNC("e1000_set_media_type");
+
+ if (hw->mac_type != e1000_82543) {
+ /* tbi_compatibility is only valid on 82543 */
+- hw->tbi_compatibility_en = FALSE;
++ hw->tbi_compatibility_en = false;
+ }
+
+ switch (hw->device_id) {
+@@ -513,7 +514,7 @@ e1000_set_media_type(struct e1000_hw *hw)
+ if (status & E1000_STATUS_TBIMODE) {
+ hw->media_type = e1000_media_type_fiber;
+ /* tbi_compatibility not valid on fiber */
+- hw->tbi_compatibility_en = FALSE;
++ hw->tbi_compatibility_en = false;
+ } else {
+ hw->media_type = e1000_media_type_copper;
+ }
+@@ -527,17 +528,17 @@ e1000_set_media_type(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_reset_hw(struct e1000_hw *hw)
+ {
+- uint32_t ctrl;
+- uint32_t ctrl_ext;
+- uint32_t icr;
+- uint32_t manc;
+- uint32_t led_ctrl;
+- uint32_t timeout;
+- uint32_t extcnf_ctrl;
+- int32_t ret_val;
++ u32 ctrl;
++ u32 ctrl_ext;
++ u32 icr;
++ u32 manc;
++ u32 led_ctrl;
++ u32 timeout;
++ u32 extcnf_ctrl;
++ s32 ret_val;
+
+ DEBUGFUNC("e1000_reset_hw");
+
+@@ -569,7 +570,7 @@ e1000_reset_hw(struct e1000_hw *hw)
+ E1000_WRITE_FLUSH(hw);
+
+ /* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */
+- hw->tbi_compatibility_on = FALSE;
++ hw->tbi_compatibility_on = false;
+
+ /* Delay to allow any outstanding PCI transactions to complete before
+ * resetting the device
+@@ -682,7 +683,7 @@ e1000_reset_hw(struct e1000_hw *hw)
+ msleep(20);
+ break;
+ case e1000_82573:
+- if (e1000_is_onboard_nvm_eeprom(hw) == FALSE) {
++ if (!e1000_is_onboard_nvm_eeprom(hw)) {
+ udelay(10);
+ ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ ctrl_ext |= E1000_CTRL_EXT_EE_RST;
+@@ -729,7 +730,7 @@ e1000_reset_hw(struct e1000_hw *hw)
+ }
+
+ if (hw->mac_type == e1000_ich8lan) {
+- uint32_t kab = E1000_READ_REG(hw, KABGTXD);
++ u32 kab = E1000_READ_REG(hw, KABGTXD);
+ kab |= E1000_KABGTXD_BGSQLBIAS;
+ E1000_WRITE_REG(hw, KABGTXD, kab);
+ }
+@@ -751,10 +752,10 @@ e1000_initialize_hardware_bits(struct e1000_hw *hw)
+ {
+ if ((hw->mac_type >= e1000_82571) && (!hw->initialize_hw_bits_disable)) {
+ /* Settings common to all PCI-express silicon */
+- uint32_t reg_ctrl, reg_ctrl_ext;
+- uint32_t reg_tarc0, reg_tarc1;
+- uint32_t reg_tctl;
+- uint32_t reg_txdctl, reg_txdctl1;
++ u32 reg_ctrl, reg_ctrl_ext;
++ u32 reg_tarc0, reg_tarc1;
++ u32 reg_tctl;
++ u32 reg_txdctl, reg_txdctl1;
+
+ /* link autonegotiation/sync workarounds */
+ reg_tarc0 = E1000_READ_REG(hw, TARC0);
+@@ -865,15 +866,15 @@ e1000_initialize_hardware_bits(struct e1000_hw *hw)
+ * configuration and flow control settings. Clears all on-chip counters. Leaves
+ * the transmit and receive units disabled and uninitialized.
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_init_hw(struct e1000_hw *hw)
+ {
+- uint32_t ctrl;
+- uint32_t i;
+- int32_t ret_val;
+- uint32_t mta_size;
+- uint32_t reg_data;
+- uint32_t ctrl_ext;
++ u32 ctrl;
++ u32 i;
++ s32 ret_val;
++ u32 mta_size;
++ u32 reg_data;
++ u32 ctrl_ext;
+
+ DEBUGFUNC("e1000_init_hw");
+
+@@ -1019,7 +1020,7 @@ e1000_init_hw(struct e1000_hw *hw)
+
+
+ if (hw->mac_type == e1000_82573) {
+- uint32_t gcr = E1000_READ_REG(hw, GCR);
++ u32 gcr = E1000_READ_REG(hw, GCR);
+ gcr |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
+ E1000_WRITE_REG(hw, GCR, gcr);
+ }
+@@ -1053,11 +1054,11 @@ e1000_init_hw(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code.
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_adjust_serdes_amplitude(struct e1000_hw *hw)
+ {
+- uint16_t eeprom_data;
+- int32_t ret_val;
++ u16 eeprom_data;
++ s32 ret_val;
+
+ DEBUGFUNC("e1000_adjust_serdes_amplitude");
+
+@@ -1099,12 +1100,12 @@ e1000_adjust_serdes_amplitude(struct e1000_hw *hw)
+ * established. Assumes the hardware has previously been reset and the
+ * transmitter and receiver are not enabled.
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_setup_link(struct e1000_hw *hw)
+ {
+- uint32_t ctrl_ext;
+- int32_t ret_val;
+- uint16_t eeprom_data;
++ u32 ctrl_ext;
++ s32 ret_val;
++ u16 eeprom_data;
+
+ DEBUGFUNC("e1000_setup_link");
+
+@@ -1232,15 +1233,15 @@ e1000_setup_link(struct e1000_hw *hw)
+ * link. Assumes the hardware has been previously reset and the transmitter
+ * and receiver are not enabled.
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
+ {
+- uint32_t ctrl;
+- uint32_t status;
+- uint32_t txcw = 0;
+- uint32_t i;
+- uint32_t signal = 0;
+- int32_t ret_val;
++ u32 ctrl;
++ u32 status;
++ u32 txcw = 0;
++ u32 i;
++ u32 signal = 0;
++ s32 ret_val;
+
+ DEBUGFUNC("e1000_setup_fiber_serdes_link");
+
+@@ -1379,12 +1380,12 @@ e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_copper_link_preconfig(struct e1000_hw *hw)
+ {
+- uint32_t ctrl;
+- int32_t ret_val;
+- uint16_t phy_data;
++ u32 ctrl;
++ s32 ret_val;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_copper_link_preconfig");
+
+@@ -1428,7 +1429,7 @@ e1000_copper_link_preconfig(struct e1000_hw *hw)
+ if (hw->mac_type <= e1000_82543 ||
+ hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 ||
+ hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2)
+- hw->phy_reset_disable = FALSE;
++ hw->phy_reset_disable = false;
+
+ return E1000_SUCCESS;
+ }
+@@ -1439,12 +1440,12 @@ e1000_copper_link_preconfig(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *********************************************************************/
+-static int32_t
++static s32
+ e1000_copper_link_igp_setup(struct e1000_hw *hw)
+ {
+- uint32_t led_ctrl;
+- int32_t ret_val;
+- uint16_t phy_data;
++ u32 led_ctrl;
++ s32 ret_val;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_copper_link_igp_setup");
+
+@@ -1470,7 +1471,7 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw)
+ /* The NVM settings will configure LPLU in D3 for IGP2 and IGP3 PHYs */
+ if (hw->phy_type == e1000_phy_igp) {
+ /* disable lplu d3 during driver init */
+- ret_val = e1000_set_d3_lplu_state(hw, FALSE);
++ ret_val = e1000_set_d3_lplu_state(hw, false);
+ if (ret_val) {
+ DEBUGOUT("Error Disabling LPLU D3\n");
+ return ret_val;
+@@ -1478,7 +1479,7 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw)
+ }
+
+ /* disable lplu d0 during driver init */
+- ret_val = e1000_set_d0_lplu_state(hw, FALSE);
++ ret_val = e1000_set_d0_lplu_state(hw, false);
+ if (ret_val) {
+ DEBUGOUT("Error Disabling LPLU D0\n");
+ return ret_val;
+@@ -1586,12 +1587,12 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *********************************************************************/
+-static int32_t
++static s32
+ e1000_copper_link_ggp_setup(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t phy_data;
+- uint32_t reg_data;
++ s32 ret_val;
++ u16 phy_data;
++ u32 reg_data;
+
+ DEBUGFUNC("e1000_copper_link_ggp_setup");
+
+@@ -1691,7 +1692,7 @@ e1000_copper_link_ggp_setup(struct e1000_hw *hw)
+ * firmware will have already initialized them. We only initialize
+ * them if the HW is not in IAMT mode.
+ */
+- if (e1000_check_mng_mode(hw) == FALSE) {
++ if (!e1000_check_mng_mode(hw)) {
+ /* Enable Electrical Idle on the PHY */
+ phy_data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE;
+ ret_val = e1000_write_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
+@@ -1734,11 +1735,11 @@ e1000_copper_link_ggp_setup(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *********************************************************************/
+-static int32_t
++static s32
+ e1000_copper_link_mgp_setup(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t phy_data;
++ s32 ret_val;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_copper_link_mgp_setup");
+
+@@ -1838,11 +1839,11 @@ e1000_copper_link_mgp_setup(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *********************************************************************/
+-static int32_t
++static s32
+ e1000_copper_link_autoneg(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t phy_data;
++ s32 ret_val;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_copper_link_autoneg");
+
+@@ -1892,7 +1893,7 @@ e1000_copper_link_autoneg(struct e1000_hw *hw)
+ }
+ }
+
+- hw->get_link_status = TRUE;
++ hw->get_link_status = true;
+
+ return E1000_SUCCESS;
+ }
+@@ -1909,10 +1910,10 @@ e1000_copper_link_autoneg(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_copper_link_postconfig(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
++ s32 ret_val;
+ DEBUGFUNC("e1000_copper_link_postconfig");
+
+ if (hw->mac_type >= e1000_82544) {
+@@ -1932,7 +1933,7 @@ e1000_copper_link_postconfig(struct e1000_hw *hw)
+
+ /* Config DSP to improve Giga link quality */
+ if (hw->phy_type == e1000_phy_igp) {
+- ret_val = e1000_config_dsp_after_link_change(hw, TRUE);
++ ret_val = e1000_config_dsp_after_link_change(hw, true);
+ if (ret_val) {
+ DEBUGOUT("Error Configuring DSP after link up\n");
+ return ret_val;
+@@ -1947,13 +1948,13 @@ e1000_copper_link_postconfig(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_setup_copper_link(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t i;
+- uint16_t phy_data;
+- uint16_t reg_data;
++ s32 ret_val;
++ u16 i;
++ u16 phy_data;
++ u16 reg_data;
+
+ DEBUGFUNC("e1000_setup_copper_link");
+
+@@ -2061,12 +2062,12 @@ e1000_setup_copper_link(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
+-e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, uint16_t duplex)
++static s32
++e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, u16 duplex)
+ {
+- int32_t ret_val = E1000_SUCCESS;
+- uint32_t tipg;
+- uint16_t reg_data;
++ s32 ret_val = E1000_SUCCESS;
++ u32 tipg;
++ u16 reg_data;
+
+ DEBUGFUNC("e1000_configure_kmrn_for_10_100");
+
+@@ -2097,12 +2098,12 @@ e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, uint16_t duplex)
+ return ret_val;
+ }
+
+-static int32_t
++static s32
+ e1000_configure_kmrn_for_1000(struct e1000_hw *hw)
+ {
+- int32_t ret_val = E1000_SUCCESS;
+- uint16_t reg_data;
+- uint32_t tipg;
++ s32 ret_val = E1000_SUCCESS;
++ u16 reg_data;
++ u32 tipg;
+
+ DEBUGFUNC("e1000_configure_kmrn_for_1000");
+
+@@ -2134,12 +2135,12 @@ e1000_configure_kmrn_for_1000(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-int32_t
++s32
+ e1000_phy_setup_autoneg(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t mii_autoneg_adv_reg;
+- uint16_t mii_1000t_ctrl_reg;
++ s32 ret_val;
++ u16 mii_autoneg_adv_reg;
++ u16 mii_1000t_ctrl_reg;
+
+ DEBUGFUNC("e1000_phy_setup_autoneg");
+
+@@ -2283,15 +2284,15 @@ e1000_phy_setup_autoneg(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
+ {
+- uint32_t ctrl;
+- int32_t ret_val;
+- uint16_t mii_ctrl_reg;
+- uint16_t mii_status_reg;
+- uint16_t phy_data;
+- uint16_t i;
++ u32 ctrl;
++ s32 ret_val;
++ u16 mii_ctrl_reg;
++ u16 mii_status_reg;
++ u16 phy_data;
++ u16 i;
+
+ DEBUGFUNC("e1000_phy_force_speed_duplex");
+
+@@ -2537,7 +2538,7 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
+ void
+ e1000_config_collision_dist(struct e1000_hw *hw)
+ {
+- uint32_t tctl, coll_dist;
++ u32 tctl, coll_dist;
+
+ DEBUGFUNC("e1000_config_collision_dist");
+
+@@ -2564,12 +2565,12 @@ e1000_config_collision_dist(struct e1000_hw *hw)
+ * The contents of the PHY register containing the needed information need to
+ * be passed in.
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_config_mac_to_phy(struct e1000_hw *hw)
+ {
+- uint32_t ctrl;
+- int32_t ret_val;
+- uint16_t phy_data;
++ u32 ctrl;
++ s32 ret_val;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_config_mac_to_phy");
+
+@@ -2623,10 +2624,10 @@ e1000_config_mac_to_phy(struct e1000_hw *hw)
+ * by the PHY rather than the MAC. Software must also configure these
+ * bits when link is forced on a fiber connection.
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_force_mac_fc(struct e1000_hw *hw)
+ {
+- uint32_t ctrl;
++ u32 ctrl;
+
+ DEBUGFUNC("e1000_force_mac_fc");
+
+@@ -2690,15 +2691,15 @@ e1000_force_mac_fc(struct e1000_hw *hw)
+ * based on the flow control negotiated by the PHY. In TBI mode, the TFCE
+ * and RFCE bits will be automaticaly set to the negotiated flow control mode.
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_config_fc_after_link_up(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t mii_status_reg;
+- uint16_t mii_nway_adv_reg;
+- uint16_t mii_nway_lp_ability_reg;
+- uint16_t speed;
+- uint16_t duplex;
++ s32 ret_val;
++ u16 mii_status_reg;
++ u16 mii_nway_adv_reg;
++ u16 mii_nway_lp_ability_reg;
++ u16 speed;
++ u16 duplex;
+
+ DEBUGFUNC("e1000_config_fc_after_link_up");
+
+@@ -2895,17 +2896,17 @@ e1000_config_fc_after_link_up(struct e1000_hw *hw)
+ *
+ * Called by any function that needs to check the link status of the adapter.
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_check_for_link(struct e1000_hw *hw)
+ {
+- uint32_t rxcw = 0;
+- uint32_t ctrl;
+- uint32_t status;
+- uint32_t rctl;
+- uint32_t icr;
+- uint32_t signal = 0;
+- int32_t ret_val;
+- uint16_t phy_data;
++ u32 rxcw = 0;
++ u32 ctrl;
++ u32 status;
++ u32 rctl;
++ u32 icr;
++ u32 signal = 0;
++ s32 ret_val;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_check_for_link");
+
+@@ -2923,7 +2924,7 @@ e1000_check_for_link(struct e1000_hw *hw)
+ if (hw->media_type == e1000_media_type_fiber) {
+ signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
+ if (status & E1000_STATUS_LU)
+- hw->get_link_status = FALSE;
++ hw->get_link_status = false;
+ }
+ }
+
+@@ -2947,7 +2948,7 @@ e1000_check_for_link(struct e1000_hw *hw)
+ return ret_val;
+
+ if (phy_data & MII_SR_LINK_STATUS) {
+- hw->get_link_status = FALSE;
++ hw->get_link_status = false;
+ /* Check if there was DownShift, must be checked immediately after
+ * link-up */
+ e1000_check_downshift(hw);
+@@ -2973,7 +2974,7 @@ e1000_check_for_link(struct e1000_hw *hw)
+
+ } else {
+ /* No link detected */
+- e1000_config_dsp_after_link_change(hw, FALSE);
++ e1000_config_dsp_after_link_change(hw, false);
+ return 0;
+ }
+
+@@ -2983,7 +2984,7 @@ e1000_check_for_link(struct e1000_hw *hw)
+ if (!hw->autoneg) return -E1000_ERR_CONFIG;
+
+ /* optimize the dsp settings for the igp phy */
+- e1000_config_dsp_after_link_change(hw, TRUE);
++ e1000_config_dsp_after_link_change(hw, true);
+
+ /* We have a M88E1000 PHY and Auto-Neg is enabled. If we
+ * have Si on board that is 82544 or newer, Auto
+@@ -3021,7 +3022,7 @@ e1000_check_for_link(struct e1000_hw *hw)
+ * at gigabit speed, we turn on TBI compatibility.
+ */
+ if (hw->tbi_compatibility_en) {
+- uint16_t speed, duplex;
++ u16 speed, duplex;
+ ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex);
+ if (ret_val) {
+ DEBUGOUT("Error getting link speed and duplex\n");
+@@ -3036,7 +3037,7 @@ e1000_check_for_link(struct e1000_hw *hw)
+ rctl = E1000_READ_REG(hw, RCTL);
+ rctl &= ~E1000_RCTL_SBP;
+ E1000_WRITE_REG(hw, RCTL, rctl);
+- hw->tbi_compatibility_on = FALSE;
++ hw->tbi_compatibility_on = false;
+ }
+ } else {
+ /* If TBI compatibility is was previously off, turn it on. For
+@@ -3045,7 +3046,7 @@ e1000_check_for_link(struct e1000_hw *hw)
+ * will look like CRC errors to to the hardware.
+ */
+ if (!hw->tbi_compatibility_on) {
+- hw->tbi_compatibility_on = TRUE;
++ hw->tbi_compatibility_on = true;
+ rctl = E1000_READ_REG(hw, RCTL);
+ rctl |= E1000_RCTL_SBP;
+ E1000_WRITE_REG(hw, RCTL, rctl);
+@@ -3098,7 +3099,7 @@ e1000_check_for_link(struct e1000_hw *hw)
+ E1000_WRITE_REG(hw, TXCW, hw->txcw);
+ E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU));
+
+- hw->serdes_link_down = FALSE;
++ hw->serdes_link_down = false;
+ }
+ /* If we force link for non-auto-negotiation switch, check link status
+ * based on MAC synchronization for internal serdes media type.
+@@ -3109,11 +3110,11 @@ e1000_check_for_link(struct e1000_hw *hw)
+ udelay(10);
+ if (E1000_RXCW_SYNCH & E1000_READ_REG(hw, RXCW)) {
+ if (!(rxcw & E1000_RXCW_IV)) {
+- hw->serdes_link_down = FALSE;
++ hw->serdes_link_down = false;
+ DEBUGOUT("SERDES: Link is up.\n");
+ }
+ } else {
+- hw->serdes_link_down = TRUE;
++ hw->serdes_link_down = true;
+ DEBUGOUT("SERDES: Link is down.\n");
+ }
+ }
+@@ -3131,14 +3132,14 @@ e1000_check_for_link(struct e1000_hw *hw)
+ * speed - Speed of the connection
+ * duplex - Duplex setting of the connection
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_get_speed_and_duplex(struct e1000_hw *hw,
+- uint16_t *speed,
+- uint16_t *duplex)
++ u16 *speed,
++ u16 *duplex)
+ {
+- uint32_t status;
+- int32_t ret_val;
+- uint16_t phy_data;
++ u32 status;
++ s32 ret_val;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_get_speed_and_duplex");
+
+@@ -3213,12 +3214,12 @@ e1000_get_speed_and_duplex(struct e1000_hw *hw,
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_wait_autoneg(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t i;
+- uint16_t phy_data;
++ s32 ret_val;
++ u16 i;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_wait_autoneg");
+ DEBUGOUT("Waiting for Auto-Neg to complete.\n");
+@@ -3250,7 +3251,7 @@ e1000_wait_autoneg(struct e1000_hw *hw)
+ ******************************************************************************/
+ static void
+ e1000_raise_mdi_clk(struct e1000_hw *hw,
+- uint32_t *ctrl)
++ u32 *ctrl)
+ {
+ /* Raise the clock input to the Management Data Clock (by setting the MDC
+ * bit), and then delay 10 microseconds.
+@@ -3268,7 +3269,7 @@ e1000_raise_mdi_clk(struct e1000_hw *hw,
+ ******************************************************************************/
+ static void
+ e1000_lower_mdi_clk(struct e1000_hw *hw,
+- uint32_t *ctrl)
++ u32 *ctrl)
+ {
+ /* Lower the clock input to the Management Data Clock (by clearing the MDC
+ * bit), and then delay 10 microseconds.
+@@ -3289,11 +3290,11 @@ e1000_lower_mdi_clk(struct e1000_hw *hw,
+ ******************************************************************************/
+ static void
+ e1000_shift_out_mdi_bits(struct e1000_hw *hw,
+- uint32_t data,
+- uint16_t count)
++ u32 data,
++ u16 count)
+ {
+- uint32_t ctrl;
+- uint32_t mask;
++ u32 ctrl;
++ u32 mask;
+
+ /* We need to shift "count" number of bits out to the PHY. So, the value
+ * in the "data" parameter will be shifted out to the PHY one bit at a
+@@ -3337,12 +3338,12 @@ e1000_shift_out_mdi_bits(struct e1000_hw *hw,
+ *
+ * Bits are shifted in in MSB to LSB order.
+ ******************************************************************************/
+-static uint16_t
++static u16
+ e1000_shift_in_mdi_bits(struct e1000_hw *hw)
+ {
+- uint32_t ctrl;
+- uint16_t data = 0;
+- uint8_t i;
++ u32 ctrl;
++ u16 data = 0;
++ u8 i;
+
+ /* In order to read a register from the PHY, we need to shift in a total
+ * of 18 bits from the PHY. The first two bit (turnaround) times are used
+@@ -3383,13 +3384,13 @@ e1000_shift_in_mdi_bits(struct e1000_hw *hw)
+ return data;
+ }
+
+-static int32_t
+-e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask)
++static s32
++e1000_swfw_sync_acquire(struct e1000_hw *hw, u16 mask)
+ {
+- uint32_t swfw_sync = 0;
+- uint32_t swmask = mask;
+- uint32_t fwmask = mask << 16;
+- int32_t timeout = 200;
++ u32 swfw_sync = 0;
++ u32 swmask = mask;
++ u32 fwmask = mask << 16;
++ s32 timeout = 200;
+
+ DEBUGFUNC("e1000_swfw_sync_acquire");
+
+@@ -3428,10 +3429,10 @@ e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask)
+ }
+
+ static void
+-e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask)
++e1000_swfw_sync_release(struct e1000_hw *hw, u16 mask)
+ {
+- uint32_t swfw_sync;
+- uint32_t swmask = mask;
++ u32 swfw_sync;
++ u32 swmask = mask;
+
+ DEBUGFUNC("e1000_swfw_sync_release");
+
+@@ -3463,13 +3464,13 @@ e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask)
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to read
+ ******************************************************************************/
+-int32_t
++s32
+ e1000_read_phy_reg(struct e1000_hw *hw,
+- uint32_t reg_addr,
+- uint16_t *phy_data)
++ u32 reg_addr,
++ u16 *phy_data)
+ {
+- uint32_t ret_val;
+- uint16_t swfw;
++ u32 ret_val;
++ u16 swfw;
+
+ DEBUGFUNC("e1000_read_phy_reg");
+
+@@ -3487,7 +3488,7 @@ e1000_read_phy_reg(struct e1000_hw *hw,
+ hw->phy_type == e1000_phy_igp_2) &&
+ (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
+ ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
+- (uint16_t)reg_addr);
++ (u16)reg_addr);
+ if (ret_val) {
+ e1000_swfw_sync_release(hw, swfw);
+ return ret_val;
+@@ -3498,14 +3499,14 @@ e1000_read_phy_reg(struct e1000_hw *hw,
+ /* Select Configuration Page */
+ if ((reg_addr & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
+ ret_val = e1000_write_phy_reg_ex(hw, GG82563_PHY_PAGE_SELECT,
+- (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT));
++ (u16)((u16)reg_addr >> GG82563_PAGE_SHIFT));
+ } else {
+ /* Use Alternative Page Select register to access
+ * registers 30 and 31
+ */
+ ret_val = e1000_write_phy_reg_ex(hw,
+ GG82563_PHY_PAGE_SELECT_ALT,
+- (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT));
++ (u16)((u16)reg_addr >> GG82563_PAGE_SHIFT));
+ }
+
+ if (ret_val) {
+@@ -3522,13 +3523,13 @@ e1000_read_phy_reg(struct e1000_hw *hw,
+ return ret_val;
+ }
+
+-static int32_t
+-e1000_read_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,
+- uint16_t *phy_data)
++static s32
++e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
++ u16 *phy_data)
+ {
+- uint32_t i;
+- uint32_t mdic = 0;
+- const uint32_t phy_addr = 1;
++ u32 i;
++ u32 mdic = 0;
++ const u32 phy_addr = 1;
+
+ DEBUGFUNC("e1000_read_phy_reg_ex");
+
+@@ -3562,7 +3563,7 @@ e1000_read_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,
+ DEBUGOUT("MDI Error\n");
+ return -E1000_ERR_PHY;
+ }
+- *phy_data = (uint16_t) mdic;
++ *phy_data = (u16) mdic;
+ } else {
+ /* We must first send a preamble through the MDIO pin to signal the
+ * beginning of an MII instruction. This is done by sending 32
+@@ -3602,12 +3603,12 @@ e1000_read_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,
+ * reg_addr - address of the PHY register to write
+ * data - data to write to the PHY
+ ******************************************************************************/
+-int32_t
+-e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr,
+- uint16_t phy_data)
++s32
++e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr,
++ u16 phy_data)
+ {
+- uint32_t ret_val;
+- uint16_t swfw;
++ u32 ret_val;
++ u16 swfw;
+
+ DEBUGFUNC("e1000_write_phy_reg");
+
+@@ -3625,7 +3626,7 @@ e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr,
+ hw->phy_type == e1000_phy_igp_2) &&
+ (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
+ ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
+- (uint16_t)reg_addr);
++ (u16)reg_addr);
+ if (ret_val) {
+ e1000_swfw_sync_release(hw, swfw);
+ return ret_val;
+@@ -3636,14 +3637,14 @@ e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr,
+ /* Select Configuration Page */
+ if ((reg_addr & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
+ ret_val = e1000_write_phy_reg_ex(hw, GG82563_PHY_PAGE_SELECT,
+- (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT));
++ (u16)((u16)reg_addr >> GG82563_PAGE_SHIFT));
+ } else {
+ /* Use Alternative Page Select register to access
+ * registers 30 and 31
+ */
+ ret_val = e1000_write_phy_reg_ex(hw,
+ GG82563_PHY_PAGE_SELECT_ALT,
+- (uint16_t)((uint16_t)reg_addr >> GG82563_PAGE_SHIFT));
++ (u16)((u16)reg_addr >> GG82563_PAGE_SHIFT));
+ }
+
+ if (ret_val) {
+@@ -3660,13 +3661,13 @@ e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr,
+ return ret_val;
+ }
+
+-static int32_t
+-e1000_write_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,
+- uint16_t phy_data)
++static s32
++e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
++ u16 phy_data)
+ {
+- uint32_t i;
+- uint32_t mdic = 0;
+- const uint32_t phy_addr = 1;
++ u32 i;
++ u32 mdic = 0;
++ const u32 phy_addr = 1;
+
+ DEBUGFUNC("e1000_write_phy_reg_ex");
+
+@@ -3680,7 +3681,7 @@ e1000_write_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,
+ * for the PHY register in the MDI Control register. The MAC will take
+ * care of interfacing with the PHY to send the desired data.
+ */
+- mdic = (((uint32_t) phy_data) |
++ mdic = (((u32) phy_data) |
+ (reg_addr << E1000_MDIC_REG_SHIFT) |
+ (phy_addr << E1000_MDIC_PHY_SHIFT) |
+ (E1000_MDIC_OP_WRITE));
+@@ -3714,7 +3715,7 @@ e1000_write_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,
+ mdic = ((PHY_TURNAROUND) | (reg_addr << 2) | (phy_addr << 7) |
+ (PHY_OP_WRITE << 12) | (PHY_SOF << 14));
+ mdic <<= 16;
+- mdic |= (uint32_t) phy_data;
++ mdic |= (u32) phy_data;
+
+ e1000_shift_out_mdi_bits(hw, mdic, 32);
+ }
+@@ -3722,13 +3723,13 @@ e1000_write_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr,
+ return E1000_SUCCESS;
+ }
+
+-static int32_t
++static s32
+ e1000_read_kmrn_reg(struct e1000_hw *hw,
+- uint32_t reg_addr,
+- uint16_t *data)
++ u32 reg_addr,
++ u16 *data)
+ {
+- uint32_t reg_val;
+- uint16_t swfw;
++ u32 reg_val;
++ u16 swfw;
+ DEBUGFUNC("e1000_read_kmrn_reg");
+
+ if ((hw->mac_type == e1000_80003es2lan) &&
+@@ -3749,19 +3750,19 @@ e1000_read_kmrn_reg(struct e1000_hw *hw,
+
+ /* Read the data returned */
+ reg_val = E1000_READ_REG(hw, KUMCTRLSTA);
+- *data = (uint16_t)reg_val;
++ *data = (u16)reg_val;
+
+ e1000_swfw_sync_release(hw, swfw);
+ return E1000_SUCCESS;
+ }
+
+-static int32_t
++static s32
+ e1000_write_kmrn_reg(struct e1000_hw *hw,
+- uint32_t reg_addr,
+- uint16_t data)
++ u32 reg_addr,
++ u16 data)
+ {
+- uint32_t reg_val;
+- uint16_t swfw;
++ u32 reg_val;
++ u16 swfw;
+ DEBUGFUNC("e1000_write_kmrn_reg");
+
+ if ((hw->mac_type == e1000_80003es2lan) &&
+@@ -3787,13 +3788,13 @@ e1000_write_kmrn_reg(struct e1000_hw *hw,
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-int32_t
++s32
+ e1000_phy_hw_reset(struct e1000_hw *hw)
+ {
+- uint32_t ctrl, ctrl_ext;
+- uint32_t led_ctrl;
+- int32_t ret_val;
+- uint16_t swfw;
++ u32 ctrl, ctrl_ext;
++ u32 led_ctrl;
++ s32 ret_val;
++ u16 swfw;
+
+ DEBUGFUNC("e1000_phy_hw_reset");
+
+@@ -3881,11 +3882,11 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
+ *
+ * Sets bit 15 of the MII Control register
+ ******************************************************************************/
+-int32_t
++s32
+ e1000_phy_reset(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t phy_data;
++ s32 ret_val;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_phy_reset");
+
+@@ -3936,9 +3937,9 @@ e1000_phy_reset(struct e1000_hw *hw)
+ void
+ e1000_phy_powerdown_workaround(struct e1000_hw *hw)
+ {
+- int32_t reg;
+- uint16_t phy_data;
+- int32_t retry = 0;
++ s32 reg;
++ u16 phy_data;
++ s32 retry = 0;
+
+ DEBUGFUNC("e1000_phy_powerdown_workaround");
+
+@@ -3986,13 +3987,13 @@ e1000_phy_powerdown_workaround(struct e1000_hw *hw)
+ *
+ * hw - struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- int32_t reg;
+- int32_t cnt;
+- uint16_t phy_data;
++ s32 ret_val;
++ s32 reg;
++ s32 cnt;
++ u16 phy_data;
+
+ if (hw->kmrn_lock_loss_workaround_disabled)
+ return E1000_SUCCESS;
+@@ -4039,12 +4040,12 @@ e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_detect_gig_phy(struct e1000_hw *hw)
+ {
+- int32_t phy_init_status, ret_val;
+- uint16_t phy_id_high, phy_id_low;
+- boolean_t match = FALSE;
++ s32 phy_init_status, ret_val;
++ u16 phy_id_high, phy_id_low;
++ bool match = false;
+
+ DEBUGFUNC("e1000_detect_gig_phy");
+
+@@ -4075,46 +4076,46 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
+ if (ret_val)
+ return ret_val;
+
+- hw->phy_id = (uint32_t) (phy_id_high << 16);
++ hw->phy_id = (u32) (phy_id_high << 16);
+ udelay(20);
+ ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low);
+ if (ret_val)
+ return ret_val;
+
+- hw->phy_id |= (uint32_t) (phy_id_low & PHY_REVISION_MASK);
+- hw->phy_revision = (uint32_t) phy_id_low & ~PHY_REVISION_MASK;
++ hw->phy_id |= (u32) (phy_id_low & PHY_REVISION_MASK);
++ hw->phy_revision = (u32) phy_id_low & ~PHY_REVISION_MASK;
+
+ switch (hw->mac_type) {
+ case e1000_82543:
+- if (hw->phy_id == M88E1000_E_PHY_ID) match = TRUE;
++ if (hw->phy_id == M88E1000_E_PHY_ID) match = true;
+ break;
+ case e1000_82544:
+- if (hw->phy_id == M88E1000_I_PHY_ID) match = TRUE;
++ if (hw->phy_id == M88E1000_I_PHY_ID) match = true;
+ break;
+ case e1000_82540:
+ case e1000_82545:
+ case e1000_82545_rev_3:
+ case e1000_82546:
+ case e1000_82546_rev_3:
+- if (hw->phy_id == M88E1011_I_PHY_ID) match = TRUE;
++ if (hw->phy_id == M88E1011_I_PHY_ID) match = true;
+ break;
+ case e1000_82541:
+ case e1000_82541_rev_2:
+ case e1000_82547:
+ case e1000_82547_rev_2:
+- if (hw->phy_id == IGP01E1000_I_PHY_ID) match = TRUE;
++ if (hw->phy_id == IGP01E1000_I_PHY_ID) match = true;
+ break;
+ case e1000_82573:
+- if (hw->phy_id == M88E1111_I_PHY_ID) match = TRUE;
++ if (hw->phy_id == M88E1111_I_PHY_ID) match = true;
+ break;
+ case e1000_80003es2lan:
+- if (hw->phy_id == GG82563_E_PHY_ID) match = TRUE;
++ if (hw->phy_id == GG82563_E_PHY_ID) match = true;
+ break;
+ case e1000_ich8lan:
+- if (hw->phy_id == IGP03E1000_E_PHY_ID) match = TRUE;
+- if (hw->phy_id == IFE_E_PHY_ID) match = TRUE;
+- if (hw->phy_id == IFE_PLUS_E_PHY_ID) match = TRUE;
+- if (hw->phy_id == IFE_C_E_PHY_ID) match = TRUE;
++ if (hw->phy_id == IGP03E1000_E_PHY_ID) match = true;
++ if (hw->phy_id == IFE_E_PHY_ID) match = true;
++ if (hw->phy_id == IFE_PLUS_E_PHY_ID) match = true;
++ if (hw->phy_id == IFE_C_E_PHY_ID) match = true;
+ break;
+ default:
+ DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type);
+@@ -4135,10 +4136,10 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_phy_reset_dsp(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
++ s32 ret_val;
+ DEBUGFUNC("e1000_phy_reset_dsp");
+
+ do {
+@@ -4162,12 +4163,12 @@ e1000_phy_reset_dsp(struct e1000_hw *hw)
+ * hw - Struct containing variables accessed by shared code
+ * phy_info - PHY information structure
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_phy_igp_get_info(struct e1000_hw *hw,
+ struct e1000_phy_info *phy_info)
+ {
+- int32_t ret_val;
+- uint16_t phy_data, min_length, max_length, average;
++ s32 ret_val;
++ u16 phy_data, min_length, max_length, average;
+ e1000_rev_polarity polarity;
+
+ DEBUGFUNC("e1000_phy_igp_get_info");
+@@ -4239,12 +4240,12 @@ e1000_phy_igp_get_info(struct e1000_hw *hw,
+ * hw - Struct containing variables accessed by shared code
+ * phy_info - PHY information structure
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_phy_ife_get_info(struct e1000_hw *hw,
+ struct e1000_phy_info *phy_info)
+ {
+- int32_t ret_val;
+- uint16_t phy_data;
++ s32 ret_val;
++ u16 phy_data;
+ e1000_rev_polarity polarity;
+
+ DEBUGFUNC("e1000_phy_ife_get_info");
+@@ -4289,12 +4290,12 @@ e1000_phy_ife_get_info(struct e1000_hw *hw,
+ * hw - Struct containing variables accessed by shared code
+ * phy_info - PHY information structure
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_phy_m88_get_info(struct e1000_hw *hw,
+ struct e1000_phy_info *phy_info)
+ {
+- int32_t ret_val;
+- uint16_t phy_data;
++ s32 ret_val;
++ u16 phy_data;
+ e1000_rev_polarity polarity;
+
+ DEBUGFUNC("e1000_phy_m88_get_info");
+@@ -4368,12 +4369,12 @@ e1000_phy_m88_get_info(struct e1000_hw *hw,
+ * hw - Struct containing variables accessed by shared code
+ * phy_info - PHY information structure
+ ******************************************************************************/
+-int32_t
++s32
+ e1000_phy_get_info(struct e1000_hw *hw,
+ struct e1000_phy_info *phy_info)
+ {
+- int32_t ret_val;
+- uint16_t phy_data;
++ s32 ret_val;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_phy_get_info");
+
+@@ -4414,7 +4415,7 @@ e1000_phy_get_info(struct e1000_hw *hw,
+ return e1000_phy_m88_get_info(hw, phy_info);
+ }
+
+-int32_t
++s32
+ e1000_validate_mdi_setting(struct e1000_hw *hw)
+ {
+ DEBUGFUNC("e1000_validate_mdi_settings");
+@@ -4435,13 +4436,13 @@ e1000_validate_mdi_setting(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_init_eeprom_params(struct e1000_hw *hw)
+ {
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+- uint32_t eecd = E1000_READ_REG(hw, EECD);
+- int32_t ret_val = E1000_SUCCESS;
+- uint16_t eeprom_size;
++ u32 eecd = E1000_READ_REG(hw, EECD);
++ s32 ret_val = E1000_SUCCESS;
++ u16 eeprom_size;
+
+ DEBUGFUNC("e1000_init_eeprom_params");
+
+@@ -4455,8 +4456,8 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+ eeprom->opcode_bits = 3;
+ eeprom->address_bits = 6;
+ eeprom->delay_usec = 50;
+- eeprom->use_eerd = FALSE;
+- eeprom->use_eewr = FALSE;
++ eeprom->use_eerd = false;
++ eeprom->use_eewr = false;
+ break;
+ case e1000_82540:
+ case e1000_82545:
+@@ -4473,8 +4474,8 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+ eeprom->word_size = 64;
+ eeprom->address_bits = 6;
+ }
+- eeprom->use_eerd = FALSE;
+- eeprom->use_eewr = FALSE;
++ eeprom->use_eerd = false;
++ eeprom->use_eewr = false;
+ break;
+ case e1000_82541:
+ case e1000_82541_rev_2:
+@@ -4503,8 +4504,8 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+ eeprom->address_bits = 6;
+ }
+ }
+- eeprom->use_eerd = FALSE;
+- eeprom->use_eewr = FALSE;
++ eeprom->use_eerd = false;
++ eeprom->use_eewr = false;
+ break;
+ case e1000_82571:
+ case e1000_82572:
+@@ -4518,8 +4519,8 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+ eeprom->page_size = 8;
+ eeprom->address_bits = 8;
+ }
+- eeprom->use_eerd = FALSE;
+- eeprom->use_eewr = FALSE;
++ eeprom->use_eerd = false;
++ eeprom->use_eewr = false;
+ break;
+ case e1000_82573:
+ eeprom->type = e1000_eeprom_spi;
+@@ -4532,9 +4533,9 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+ eeprom->page_size = 8;
+ eeprom->address_bits = 8;
+ }
+- eeprom->use_eerd = TRUE;
+- eeprom->use_eewr = TRUE;
+- if (e1000_is_onboard_nvm_eeprom(hw) == FALSE) {
++ eeprom->use_eerd = true;
++ eeprom->use_eewr = true;
++ if (!e1000_is_onboard_nvm_eeprom(hw)) {
+ eeprom->type = e1000_eeprom_flash;
+ eeprom->word_size = 2048;
+
+@@ -4555,24 +4556,24 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+ eeprom->page_size = 8;
+ eeprom->address_bits = 8;
+ }
+- eeprom->use_eerd = TRUE;
+- eeprom->use_eewr = FALSE;
++ eeprom->use_eerd = true;
++ eeprom->use_eewr = false;
+ break;
+ case e1000_ich8lan:
+ {
+- int32_t i = 0;
+- uint32_t flash_size = E1000_READ_ICH_FLASH_REG(hw, ICH_FLASH_GFPREG);
++ s32 i = 0;
++ u32 flash_size = E1000_READ_ICH_FLASH_REG(hw, ICH_FLASH_GFPREG);
+
+ eeprom->type = e1000_eeprom_ich8;
+- eeprom->use_eerd = FALSE;
+- eeprom->use_eewr = FALSE;
++ eeprom->use_eerd = false;
++ eeprom->use_eewr = false;
+ eeprom->word_size = E1000_SHADOW_RAM_WORDS;
+
+ /* Zero the shadow RAM structure. But don't load it from NVM
+ * so as to save time for driver init */
+ if (hw->eeprom_shadow_ram != NULL) {
+ for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
+- hw->eeprom_shadow_ram[i].modified = FALSE;
++ hw->eeprom_shadow_ram[i].modified = false;
+ hw->eeprom_shadow_ram[i].eeprom_word = 0xFFFF;
+ }
+ }
+@@ -4585,7 +4586,7 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+
+ hw->flash_bank_size *= ICH_FLASH_SECTOR_SIZE;
+
+- hw->flash_bank_size /= 2 * sizeof(uint16_t);
++ hw->flash_bank_size /= 2 * sizeof(u16);
+
+ break;
+ }
+@@ -4610,7 +4611,7 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+ if (eeprom_size)
+ eeprom_size++;
+ } else {
+- eeprom_size = (uint16_t)((eecd & E1000_EECD_SIZE_EX_MASK) >>
++ eeprom_size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
+ E1000_EECD_SIZE_EX_SHIFT);
+ }
+
+@@ -4627,7 +4628,7 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
+ *****************************************************************************/
+ static void
+ e1000_raise_ee_clk(struct e1000_hw *hw,
+- uint32_t *eecd)
++ u32 *eecd)
+ {
+ /* Raise the clock input to the EEPROM (by setting the SK bit), and then
+ * wait <delay> microseconds.
+@@ -4646,7 +4647,7 @@ e1000_raise_ee_clk(struct e1000_hw *hw,
+ *****************************************************************************/
+ static void
+ e1000_lower_ee_clk(struct e1000_hw *hw,
+- uint32_t *eecd)
++ u32 *eecd)
+ {
+ /* Lower the clock input to the EEPROM (by clearing the SK bit), and then
+ * wait 50 microseconds.
+@@ -4666,12 +4667,12 @@ e1000_lower_ee_clk(struct e1000_hw *hw,
+ *****************************************************************************/
+ static void
+ e1000_shift_out_ee_bits(struct e1000_hw *hw,
+- uint16_t data,
+- uint16_t count)
++ u16 data,
++ u16 count)
+ {
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+- uint32_t eecd;
+- uint32_t mask;
++ u32 eecd;
++ u32 mask;
+
+ /* We need to shift "count" bits out to the EEPROM. So, value in the
+ * "data" parameter will be shifted out to the EEPROM one bit at a time.
+@@ -4717,13 +4718,13 @@ e1000_shift_out_ee_bits(struct e1000_hw *hw,
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-static uint16_t
++static u16
+ e1000_shift_in_ee_bits(struct e1000_hw *hw,
+- uint16_t count)
++ u16 count)
+ {
+- uint32_t eecd;
+- uint32_t i;
+- uint16_t data;
++ u32 eecd;
++ u32 i;
++ u16 data;
+
+ /* In order to read a register from the EEPROM, we need to shift 'count'
+ * bits in from the EEPROM. Bits are "shifted in" by raising the clock
+@@ -4761,11 +4762,11 @@ e1000_shift_in_ee_bits(struct e1000_hw *hw,
+ * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This
+ * function should be called before issuing a command to the EEPROM.
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_acquire_eeprom(struct e1000_hw *hw)
+ {
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+- uint32_t eecd, i=0;
++ u32 eecd, i=0;
+
+ DEBUGFUNC("e1000_acquire_eeprom");
+
+@@ -4824,7 +4825,7 @@ static void
+ e1000_standby_eeprom(struct e1000_hw *hw)
+ {
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+- uint32_t eecd;
++ u32 eecd;
+
+ eecd = E1000_READ_REG(hw, EECD);
+
+@@ -4872,7 +4873,7 @@ e1000_standby_eeprom(struct e1000_hw *hw)
+ static void
+ e1000_release_eeprom(struct e1000_hw *hw)
+ {
+- uint32_t eecd;
++ u32 eecd;
+
+ DEBUGFUNC("e1000_release_eeprom");
+
+@@ -4920,11 +4921,11 @@ e1000_release_eeprom(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_spi_eeprom_ready(struct e1000_hw *hw)
+ {
+- uint16_t retry_count = 0;
+- uint8_t spi_stat_reg;
++ u16 retry_count = 0;
++ u8 spi_stat_reg;
+
+ DEBUGFUNC("e1000_spi_eeprom_ready");
+
+@@ -4937,7 +4938,7 @@ e1000_spi_eeprom_ready(struct e1000_hw *hw)
+ do {
+ e1000_shift_out_ee_bits(hw, EEPROM_RDSR_OPCODE_SPI,
+ hw->eeprom.opcode_bits);
+- spi_stat_reg = (uint8_t)e1000_shift_in_ee_bits(hw, 8);
++ spi_stat_reg = (u8)e1000_shift_in_ee_bits(hw, 8);
+ if (!(spi_stat_reg & EEPROM_STATUS_RDY_SPI))
+ break;
+
+@@ -4966,14 +4967,14 @@ e1000_spi_eeprom_ready(struct e1000_hw *hw)
+ * data - word read from the EEPROM
+ * words - number of words to read
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_read_eeprom(struct e1000_hw *hw,
+- uint16_t offset,
+- uint16_t words,
+- uint16_t *data)
++ u16 offset,
++ u16 words,
++ u16 *data)
+ {
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+- uint32_t i = 0;
++ u32 i = 0;
+
+ DEBUGFUNC("e1000_read_eeprom");
+
+@@ -4994,15 +4995,14 @@ e1000_read_eeprom(struct e1000_hw *hw,
+ * directly. In this case, we need to acquire the EEPROM so that
+ * FW or other port software does not interrupt.
+ */
+- if (e1000_is_onboard_nvm_eeprom(hw) == TRUE &&
+- hw->eeprom.use_eerd == FALSE) {
++ if (e1000_is_onboard_nvm_eeprom(hw) && !hw->eeprom.use_eerd) {
+ /* Prepare the EEPROM for bit-bang reading */
+ if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
+ return -E1000_ERR_EEPROM;
+ }
+
+ /* Eerd register EEPROM access requires no eeprom aquire/release */
+- if (eeprom->use_eerd == TRUE)
++ if (eeprom->use_eerd)
+ return e1000_read_eeprom_eerd(hw, offset, words, data);
+
+ /* ICH EEPROM access is done via the ICH flash controller */
+@@ -5012,8 +5012,8 @@ e1000_read_eeprom(struct e1000_hw *hw,
+ /* Set up the SPI or Microwire EEPROM for bit-bang reading. We have
+ * acquired the EEPROM at this point, so any returns should relase it */
+ if (eeprom->type == e1000_eeprom_spi) {
+- uint16_t word_in;
+- uint8_t read_opcode = EEPROM_READ_OPCODE_SPI;
++ u16 word_in;
++ u8 read_opcode = EEPROM_READ_OPCODE_SPI;
+
+ if (e1000_spi_eeprom_ready(hw)) {
+ e1000_release_eeprom(hw);
+@@ -5028,7 +5028,7 @@ e1000_read_eeprom(struct e1000_hw *hw,
+
+ /* Send the READ command (opcode + addr) */
+ e1000_shift_out_ee_bits(hw, read_opcode, eeprom->opcode_bits);
+- e1000_shift_out_ee_bits(hw, (uint16_t)(offset*2), eeprom->address_bits);
++ e1000_shift_out_ee_bits(hw, (u16)(offset*2), eeprom->address_bits);
+
+ /* Read the data. The address of the eeprom internally increments with
+ * each byte (spi) being read, saving on the overhead of eeprom setup
+@@ -5044,7 +5044,7 @@ e1000_read_eeprom(struct e1000_hw *hw,
+ /* Send the READ command (opcode + addr) */
+ e1000_shift_out_ee_bits(hw, EEPROM_READ_OPCODE_MICROWIRE,
+ eeprom->opcode_bits);
+- e1000_shift_out_ee_bits(hw, (uint16_t)(offset + i),
++ e1000_shift_out_ee_bits(hw, (u16)(offset + i),
+ eeprom->address_bits);
+
+ /* Read the data. For microwire, each word requires the overhead
+@@ -5068,14 +5068,14 @@ e1000_read_eeprom(struct e1000_hw *hw,
+ * data - word read from the EEPROM
+ * words - number of words to read
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_read_eeprom_eerd(struct e1000_hw *hw,
+- uint16_t offset,
+- uint16_t words,
+- uint16_t *data)
++ u16 offset,
++ u16 words,
++ u16 *data)
+ {
+- uint32_t i, eerd = 0;
+- int32_t error = 0;
++ u32 i, eerd = 0;
++ s32 error = 0;
+
+ for (i = 0; i < words; i++) {
+ eerd = ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) +
+@@ -5102,15 +5102,15 @@ e1000_read_eeprom_eerd(struct e1000_hw *hw,
+ * data - word read from the EEPROM
+ * words - number of words to read
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_write_eeprom_eewr(struct e1000_hw *hw,
+- uint16_t offset,
+- uint16_t words,
+- uint16_t *data)
++ u16 offset,
++ u16 words,
++ u16 *data)
+ {
+- uint32_t register_value = 0;
+- uint32_t i = 0;
+- int32_t error = 0;
++ u32 register_value = 0;
++ u32 i = 0;
++ s32 error = 0;
+
+ if (e1000_swfw_sync_acquire(hw, E1000_SWFW_EEP_SM))
+ return -E1000_ERR_SWFW_SYNC;
+@@ -5143,12 +5143,12 @@ e1000_write_eeprom_eewr(struct e1000_hw *hw,
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd)
+ {
+- uint32_t attempts = 100000;
+- uint32_t i, reg = 0;
+- int32_t done = E1000_ERR_EEPROM;
++ u32 attempts = 100000;
++ u32 i, reg = 0;
++ s32 done = E1000_ERR_EEPROM;
+
+ for (i = 0; i < attempts; i++) {
+ if (eerd == E1000_EEPROM_POLL_READ)
+@@ -5171,15 +5171,15 @@ e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd)
+ *
+ * hw - Struct containing variables accessed by shared code
+ ****************************************************************************/
+-static boolean_t
++static bool
+ e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw)
+ {
+- uint32_t eecd = 0;
++ u32 eecd = 0;
+
+ DEBUGFUNC("e1000_is_onboard_nvm_eeprom");
+
+ if (hw->mac_type == e1000_ich8lan)
+- return FALSE;
++ return false;
+
+ if (hw->mac_type == e1000_82573) {
+ eecd = E1000_READ_REG(hw, EECD);
+@@ -5189,10 +5189,10 @@ e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw)
+
+ /* If both bits are set, device is Flash type */
+ if (eecd == 0x03) {
+- return FALSE;
++ return false;
+ }
+ }
+- return TRUE;
++ return true;
+ }
+
+ /******************************************************************************
+@@ -5204,16 +5204,15 @@ e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw)
+ * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is
+ * valid.
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_validate_eeprom_checksum(struct e1000_hw *hw)
+ {
+- uint16_t checksum = 0;
+- uint16_t i, eeprom_data;
++ u16 checksum = 0;
++ u16 i, eeprom_data;
+
+ DEBUGFUNC("e1000_validate_eeprom_checksum");
+
+- if ((hw->mac_type == e1000_82573) &&
+- (e1000_is_onboard_nvm_eeprom(hw) == FALSE)) {
++ if ((hw->mac_type == e1000_82573) && !e1000_is_onboard_nvm_eeprom(hw)) {
+ /* Check bit 4 of word 10h. If it is 0, firmware is done updating
+ * 10h-12h. Checksum may need to be fixed. */
+ e1000_read_eeprom(hw, 0x10, 1, &eeprom_data);
+@@ -5253,7 +5252,7 @@ e1000_validate_eeprom_checksum(struct e1000_hw *hw)
+ checksum += eeprom_data;
+ }
+
+- if (checksum == (uint16_t) EEPROM_SUM)
++ if (checksum == (u16) EEPROM_SUM)
+ return E1000_SUCCESS;
+ else {
+ DEBUGOUT("EEPROM Checksum Invalid\n");
+@@ -5269,12 +5268,12 @@ e1000_validate_eeprom_checksum(struct e1000_hw *hw)
+ * Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA.
+ * Writes the difference to word offset 63 of the EEPROM.
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_update_eeprom_checksum(struct e1000_hw *hw)
+ {
+- uint32_t ctrl_ext;
+- uint16_t checksum = 0;
+- uint16_t i, eeprom_data;
++ u32 ctrl_ext;
++ u16 checksum = 0;
++ u16 i, eeprom_data;
+
+ DEBUGFUNC("e1000_update_eeprom_checksum");
+
+@@ -5285,7 +5284,7 @@ e1000_update_eeprom_checksum(struct e1000_hw *hw)
+ }
+ checksum += eeprom_data;
+ }
+- checksum = (uint16_t) EEPROM_SUM - checksum;
++ checksum = (u16) EEPROM_SUM - checksum;
+ if (e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) {
+ DEBUGOUT("EEPROM Write Error\n");
+ return -E1000_ERR_EEPROM;
+@@ -5314,14 +5313,14 @@ e1000_update_eeprom_checksum(struct e1000_hw *hw)
+ * If e1000_update_eeprom_checksum is not called after this function, the
+ * EEPROM will most likely contain an invalid checksum.
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_write_eeprom(struct e1000_hw *hw,
+- uint16_t offset,
+- uint16_t words,
+- uint16_t *data)
++ u16 offset,
++ u16 words,
++ u16 *data)
+ {
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+- int32_t status = 0;
++ s32 status = 0;
+
+ DEBUGFUNC("e1000_write_eeprom");
+
+@@ -5339,7 +5338,7 @@ e1000_write_eeprom(struct e1000_hw *hw,
+ }
+
+ /* 82573 writes only through eewr */
+- if (eeprom->use_eewr == TRUE)
++ if (eeprom->use_eewr)
+ return e1000_write_eeprom_eewr(hw, offset, words, data);
+
+ if (eeprom->type == e1000_eeprom_ich8)
+@@ -5371,19 +5370,19 @@ e1000_write_eeprom(struct e1000_hw *hw,
+ * data - pointer to array of 8 bit words to be written to the EEPROM
+ *
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_write_eeprom_spi(struct e1000_hw *hw,
+- uint16_t offset,
+- uint16_t words,
+- uint16_t *data)
++ u16 offset,
++ u16 words,
++ u16 *data)
+ {
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+- uint16_t widx = 0;
++ u16 widx = 0;
+
+ DEBUGFUNC("e1000_write_eeprom_spi");
+
+ while (widx < words) {
+- uint8_t write_opcode = EEPROM_WRITE_OPCODE_SPI;
++ u8 write_opcode = EEPROM_WRITE_OPCODE_SPI;
+
+ if (e1000_spi_eeprom_ready(hw)) return -E1000_ERR_EEPROM;
+
+@@ -5402,14 +5401,14 @@ e1000_write_eeprom_spi(struct e1000_hw *hw,
+ /* Send the Write command (8-bit opcode + addr) */
+ e1000_shift_out_ee_bits(hw, write_opcode, eeprom->opcode_bits);
+
+- e1000_shift_out_ee_bits(hw, (uint16_t)((offset + widx)*2),
++ e1000_shift_out_ee_bits(hw, (u16)((offset + widx)*2),
+ eeprom->address_bits);
+
+ /* Send the data */
+
+ /* Loop to allow for up to whole page write (32 bytes) of eeprom */
+ while (widx < words) {
+- uint16_t word_out = data[widx];
++ u16 word_out = data[widx];
+ word_out = (word_out >> 8) | (word_out << 8);
+ e1000_shift_out_ee_bits(hw, word_out, 16);
+ widx++;
+@@ -5437,16 +5436,16 @@ e1000_write_eeprom_spi(struct e1000_hw *hw,
+ * data - pointer to array of 16 bit words to be written to the EEPROM
+ *
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_write_eeprom_microwire(struct e1000_hw *hw,
+- uint16_t offset,
+- uint16_t words,
+- uint16_t *data)
++ u16 offset,
++ u16 words,
++ u16 *data)
+ {
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+- uint32_t eecd;
+- uint16_t words_written = 0;
+- uint16_t i = 0;
++ u32 eecd;
++ u16 words_written = 0;
++ u16 i = 0;
+
+ DEBUGFUNC("e1000_write_eeprom_microwire");
+
+@@ -5457,9 +5456,9 @@ e1000_write_eeprom_microwire(struct e1000_hw *hw,
+ * EEPROM into write/erase mode.
+ */
+ e1000_shift_out_ee_bits(hw, EEPROM_EWEN_OPCODE_MICROWIRE,
+- (uint16_t)(eeprom->opcode_bits + 2));
++ (u16)(eeprom->opcode_bits + 2));
+
+- e1000_shift_out_ee_bits(hw, 0, (uint16_t)(eeprom->address_bits - 2));
++ e1000_shift_out_ee_bits(hw, 0, (u16)(eeprom->address_bits - 2));
+
+ /* Prepare the EEPROM */
+ e1000_standby_eeprom(hw);
+@@ -5469,7 +5468,7 @@ e1000_write_eeprom_microwire(struct e1000_hw *hw,
+ e1000_shift_out_ee_bits(hw, EEPROM_WRITE_OPCODE_MICROWIRE,
+ eeprom->opcode_bits);
+
+- e1000_shift_out_ee_bits(hw, (uint16_t)(offset + words_written),
++ e1000_shift_out_ee_bits(hw, (u16)(offset + words_written),
+ eeprom->address_bits);
+
+ /* Send the data */
+@@ -5507,9 +5506,9 @@ e1000_write_eeprom_microwire(struct e1000_hw *hw,
+ * EEPROM out of write/erase mode.
+ */
+ e1000_shift_out_ee_bits(hw, EEPROM_EWDS_OPCODE_MICROWIRE,
+- (uint16_t)(eeprom->opcode_bits + 2));
++ (u16)(eeprom->opcode_bits + 2));
+
+- e1000_shift_out_ee_bits(hw, 0, (uint16_t)(eeprom->address_bits - 2));
++ e1000_shift_out_ee_bits(hw, 0, (u16)(eeprom->address_bits - 2));
+
+ return E1000_SUCCESS;
+ }
+@@ -5524,19 +5523,19 @@ e1000_write_eeprom_microwire(struct e1000_hw *hw,
+ * data - word read from the EEPROM
+ * words - number of words to read
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_commit_shadow_ram(struct e1000_hw *hw)
+ {
+- uint32_t attempts = 100000;
+- uint32_t eecd = 0;
+- uint32_t flop = 0;
+- uint32_t i = 0;
+- int32_t error = E1000_SUCCESS;
+- uint32_t old_bank_offset = 0;
+- uint32_t new_bank_offset = 0;
+- uint8_t low_byte = 0;
+- uint8_t high_byte = 0;
+- boolean_t sector_write_failed = FALSE;
++ u32 attempts = 100000;
++ u32 eecd = 0;
++ u32 flop = 0;
++ u32 i = 0;
++ s32 error = E1000_SUCCESS;
++ u32 old_bank_offset = 0;
++ u32 new_bank_offset = 0;
++ u8 low_byte = 0;
++ u8 high_byte = 0;
++ bool sector_write_failed = false;
+
+ if (hw->mac_type == e1000_82573) {
+ /* The flop register will be used to determine if flash type is STM */
+@@ -5588,24 +5587,24 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
+ e1000_erase_ich8_4k_segment(hw, 0);
+ }
+
+- sector_write_failed = FALSE;
++ sector_write_failed = false;
+ /* Loop for every byte in the shadow RAM,
+ * which is in units of words. */
+ for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
+ /* Determine whether to write the value stored
+ * in the other NVM bank or a modified value stored
+ * in the shadow RAM */
+- if (hw->eeprom_shadow_ram[i].modified == TRUE) {
+- low_byte = (uint8_t)hw->eeprom_shadow_ram[i].eeprom_word;
++ if (hw->eeprom_shadow_ram[i].modified) {
++ low_byte = (u8)hw->eeprom_shadow_ram[i].eeprom_word;
+ udelay(100);
+ error = e1000_verify_write_ich8_byte(hw,
+ (i << 1) + new_bank_offset, low_byte);
+
+ if (error != E1000_SUCCESS)
+- sector_write_failed = TRUE;
++ sector_write_failed = true;
+ else {
+ high_byte =
+- (uint8_t)(hw->eeprom_shadow_ram[i].eeprom_word >> 8);
++ (u8)(hw->eeprom_shadow_ram[i].eeprom_word >> 8);
+ udelay(100);
+ }
+ } else {
+@@ -5616,7 +5615,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
+ (i << 1) + new_bank_offset, low_byte);
+
+ if (error != E1000_SUCCESS)
+- sector_write_failed = TRUE;
++ sector_write_failed = true;
+ else {
+ e1000_read_ich8_byte(hw, (i << 1) + old_bank_offset + 1,
+ &high_byte);
+@@ -5624,10 +5623,10 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
+ }
+ }
+
+- /* If the write of the low byte was successful, go ahread and
++ /* If the write of the low byte was successful, go ahead and
+ * write the high byte while checking to make sure that if it
+ * is the signature byte, then it is handled properly */
+- if (sector_write_failed == FALSE) {
++ if (!sector_write_failed) {
+ /* If the word is 0x13, then make sure the signature bits
+ * (15:14) are 11b until the commit has completed.
+ * This will allow us to write 10b which indicates the
+@@ -5640,7 +5639,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
+ error = e1000_verify_write_ich8_byte(hw,
+ (i << 1) + new_bank_offset + 1, high_byte);
+ if (error != E1000_SUCCESS)
+- sector_write_failed = TRUE;
++ sector_write_failed = true;
+
+ } else {
+ /* If the write failed then break from the loop and
+@@ -5651,7 +5650,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
+
+ /* Don't bother writing the segment valid bits if sector
+ * programming failed. */
+- if (sector_write_failed == FALSE) {
++ if (!sector_write_failed) {
+ /* Finally validate the new segment by setting bit 15:14
+ * to 10b in word 0x13 , this can be done without an
+ * erase as well since these bits are 11 to start with
+@@ -5673,7 +5672,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
+
+ /* Clear the now not used entry in the cache */
+ for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
+- hw->eeprom_shadow_ram[i].modified = FALSE;
++ hw->eeprom_shadow_ram[i].modified = false;
+ hw->eeprom_shadow_ram[i].eeprom_word = 0xFFFF;
+ }
+ }
+@@ -5688,11 +5687,11 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_read_mac_addr(struct e1000_hw * hw)
+ {
+- uint16_t offset;
+- uint16_t eeprom_data, i;
++ u16 offset;
++ u16 eeprom_data, i;
+
+ DEBUGFUNC("e1000_read_mac_addr");
+
+@@ -5702,8 +5701,8 @@ e1000_read_mac_addr(struct e1000_hw * hw)
+ DEBUGOUT("EEPROM Read Error\n");
+ return -E1000_ERR_EEPROM;
+ }
+- hw->perm_mac_addr[i] = (uint8_t) (eeprom_data & 0x00FF);
+- hw->perm_mac_addr[i+1] = (uint8_t) (eeprom_data >> 8);
++ hw->perm_mac_addr[i] = (u8) (eeprom_data & 0x00FF);
++ hw->perm_mac_addr[i+1] = (u8) (eeprom_data >> 8);
+ }
+
+ switch (hw->mac_type) {
+@@ -5735,8 +5734,8 @@ e1000_read_mac_addr(struct e1000_hw * hw)
+ static void
+ e1000_init_rx_addrs(struct e1000_hw *hw)
+ {
+- uint32_t i;
+- uint32_t rar_num;
++ u32 i;
++ u32 rar_num;
+
+ DEBUGFUNC("e1000_init_rx_addrs");
+
+@@ -5750,7 +5749,7 @@ e1000_init_rx_addrs(struct e1000_hw *hw)
+ /* Reserve a spot for the Locally Administered Address to work around
+ * an 82571 issue in which a reset on one port will reload the MAC on
+ * the other port. */
+- if ((hw->mac_type == e1000_82571) && (hw->laa_is_present == TRUE))
++ if ((hw->mac_type == e1000_82571) && (hw->laa_is_present))
+ rar_num -= 1;
+ if (hw->mac_type == e1000_ich8lan)
+ rar_num = E1000_RAR_ENTRIES_ICH8LAN;
+@@ -5771,11 +5770,11 @@ e1000_init_rx_addrs(struct e1000_hw *hw)
+ * hw - Struct containing variables accessed by shared code
+ * mc_addr - the multicast address to hash
+ *****************************************************************************/
+-uint32_t
++u32
+ e1000_hash_mc_addr(struct e1000_hw *hw,
+- uint8_t *mc_addr)
++ u8 *mc_addr)
+ {
+- uint32_t hash_value = 0;
++ u32 hash_value = 0;
+
+ /* The portion of the address that is used for the hash table is
+ * determined by the mc_filter_type setting.
+@@ -5788,37 +5787,37 @@ e1000_hash_mc_addr(struct e1000_hw *hw,
+ case 0:
+ if (hw->mac_type == e1000_ich8lan) {
+ /* [47:38] i.e. 0x158 for above example address */
+- hash_value = ((mc_addr[4] >> 6) | (((uint16_t) mc_addr[5]) << 2));
++ hash_value = ((mc_addr[4] >> 6) | (((u16) mc_addr[5]) << 2));
+ } else {
+ /* [47:36] i.e. 0x563 for above example address */
+- hash_value = ((mc_addr[4] >> 4) | (((uint16_t) mc_addr[5]) << 4));
++ hash_value = ((mc_addr[4] >> 4) | (((u16) mc_addr[5]) << 4));
+ }
+ break;
+ case 1:
+ if (hw->mac_type == e1000_ich8lan) {
+ /* [46:37] i.e. 0x2B1 for above example address */
+- hash_value = ((mc_addr[4] >> 5) | (((uint16_t) mc_addr[5]) << 3));
++ hash_value = ((mc_addr[4] >> 5) | (((u16) mc_addr[5]) << 3));
+ } else {
+ /* [46:35] i.e. 0xAC6 for above example address */
+- hash_value = ((mc_addr[4] >> 3) | (((uint16_t) mc_addr[5]) << 5));
++ hash_value = ((mc_addr[4] >> 3) | (((u16) mc_addr[5]) << 5));
+ }
+ break;
+ case 2:
+ if (hw->mac_type == e1000_ich8lan) {
+ /*[45:36] i.e. 0x163 for above example address */
+- hash_value = ((mc_addr[4] >> 4) | (((uint16_t) mc_addr[5]) << 4));
++ hash_value = ((mc_addr[4] >> 4) | (((u16) mc_addr[5]) << 4));
+ } else {
+ /* [45:34] i.e. 0x5D8 for above example address */
+- hash_value = ((mc_addr[4] >> 2) | (((uint16_t) mc_addr[5]) << 6));
++ hash_value = ((mc_addr[4] >> 2) | (((u16) mc_addr[5]) << 6));
+ }
+ break;
+ case 3:
+ if (hw->mac_type == e1000_ich8lan) {
+ /* [43:34] i.e. 0x18D for above example address */
+- hash_value = ((mc_addr[4] >> 2) | (((uint16_t) mc_addr[5]) << 6));
++ hash_value = ((mc_addr[4] >> 2) | (((u16) mc_addr[5]) << 6));
+ } else {
+ /* [43:32] i.e. 0x634 for above example address */
+- hash_value = ((mc_addr[4]) | (((uint16_t) mc_addr[5]) << 8));
++ hash_value = ((mc_addr[4]) | (((u16) mc_addr[5]) << 8));
+ }
+ break;
+ }
+@@ -5838,11 +5837,11 @@ e1000_hash_mc_addr(struct e1000_hw *hw,
+ *****************************************************************************/
+ void
+ e1000_mta_set(struct e1000_hw *hw,
+- uint32_t hash_value)
++ u32 hash_value)
+ {
+- uint32_t hash_bit, hash_reg;
+- uint32_t mta;
+- uint32_t temp;
++ u32 hash_bit, hash_reg;
++ u32 mta;
++ u32 temp;
+
+ /* The MTA is a register array of 128 32-bit registers.
+ * It is treated like an array of 4096 bits. We want to set
+@@ -5887,18 +5886,18 @@ e1000_mta_set(struct e1000_hw *hw,
+ *****************************************************************************/
+ void
+ e1000_rar_set(struct e1000_hw *hw,
+- uint8_t *addr,
+- uint32_t index)
++ u8 *addr,
++ u32 index)
+ {
+- uint32_t rar_low, rar_high;
++ u32 rar_low, rar_high;
+
+ /* HW expects these in little endian so we reverse the byte order
+ * from network order (big endian) to little endian
+ */
+- rar_low = ((uint32_t) addr[0] |
+- ((uint32_t) addr[1] << 8) |
+- ((uint32_t) addr[2] << 16) | ((uint32_t) addr[3] << 24));
+- rar_high = ((uint32_t) addr[4] | ((uint32_t) addr[5] << 8));
++ rar_low = ((u32) addr[0] |
++ ((u32) addr[1] << 8) |
++ ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
++ rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
+
+ /* Disable Rx and flush all Rx frames before enabling RSS to avoid Rx
+ * unit hang.
+@@ -5922,7 +5921,7 @@ e1000_rar_set(struct e1000_hw *hw,
+ case e1000_82571:
+ case e1000_82572:
+ case e1000_80003es2lan:
+- if (hw->leave_av_bit_off == TRUE)
++ if (hw->leave_av_bit_off)
+ break;
+ default:
+ /* Indicate to hardware the Address is Valid. */
+@@ -5945,10 +5944,10 @@ e1000_rar_set(struct e1000_hw *hw,
+ *****************************************************************************/
+ void
+ e1000_write_vfta(struct e1000_hw *hw,
+- uint32_t offset,
+- uint32_t value)
++ u32 offset,
++ u32 value)
+ {
+- uint32_t temp;
++ u32 temp;
+
+ if (hw->mac_type == e1000_ich8lan)
+ return;
+@@ -5973,10 +5972,10 @@ e1000_write_vfta(struct e1000_hw *hw,
+ static void
+ e1000_clear_vfta(struct e1000_hw *hw)
+ {
+- uint32_t offset;
+- uint32_t vfta_value = 0;
+- uint32_t vfta_offset = 0;
+- uint32_t vfta_bit_in_reg = 0;
++ u32 offset;
++ u32 vfta_value = 0;
++ u32 vfta_offset = 0;
++ u32 vfta_bit_in_reg = 0;
+
+ if (hw->mac_type == e1000_ich8lan)
+ return;
+@@ -6004,15 +6003,15 @@ e1000_clear_vfta(struct e1000_hw *hw)
+ }
+ }
+
+-static int32_t
++static s32
+ e1000_id_led_init(struct e1000_hw * hw)
+ {
+- uint32_t ledctl;
+- const uint32_t ledctl_mask = 0x000000FF;
+- const uint32_t ledctl_on = E1000_LEDCTL_MODE_LED_ON;
+- const uint32_t ledctl_off = E1000_LEDCTL_MODE_LED_OFF;
+- uint16_t eeprom_data, i, temp;
+- const uint16_t led_mask = 0x0F;
++ u32 ledctl;
++ const u32 ledctl_mask = 0x000000FF;
++ const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON;
++ const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF;
++ u16 eeprom_data, i, temp;
++ const u16 led_mask = 0x0F;
+
+ DEBUGFUNC("e1000_id_led_init");
+
+@@ -6087,11 +6086,11 @@ e1000_id_led_init(struct e1000_hw * hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_setup_led(struct e1000_hw *hw)
+ {
+- uint32_t ledctl;
+- int32_t ret_val = E1000_SUCCESS;
++ u32 ledctl;
++ s32 ret_val = E1000_SUCCESS;
+
+ DEBUGFUNC("e1000_setup_led");
+
+@@ -6112,7 +6111,7 @@ e1000_setup_led(struct e1000_hw *hw)
+ if (ret_val)
+ return ret_val;
+ ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
+- (uint16_t)(hw->phy_spd_default &
++ (u16)(hw->phy_spd_default &
+ ~IGP01E1000_GMII_SPD));
+ if (ret_val)
+ return ret_val;
+@@ -6146,11 +6145,11 @@ e1000_setup_led(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_blink_led_start(struct e1000_hw *hw)
+ {
+- int16_t i;
+- uint32_t ledctl_blink = 0;
++ s16 i;
++ u32 ledctl_blink = 0;
+
+ DEBUGFUNC("e1000_id_led_blink_on");
+
+@@ -6181,10 +6180,10 @@ e1000_blink_led_start(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_cleanup_led(struct e1000_hw *hw)
+ {
+- int32_t ret_val = E1000_SUCCESS;
++ s32 ret_val = E1000_SUCCESS;
+
+ DEBUGFUNC("e1000_cleanup_led");
+
+@@ -6223,10 +6222,10 @@ e1000_cleanup_led(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_led_on(struct e1000_hw *hw)
+ {
+- uint32_t ctrl = E1000_READ_REG(hw, CTRL);
++ u32 ctrl = E1000_READ_REG(hw, CTRL);
+
+ DEBUGFUNC("e1000_led_on");
+
+@@ -6274,10 +6273,10 @@ e1000_led_on(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_led_off(struct e1000_hw *hw)
+ {
+- uint32_t ctrl = E1000_READ_REG(hw, CTRL);
++ u32 ctrl = E1000_READ_REG(hw, CTRL);
+
+ DEBUGFUNC("e1000_led_off");
+
+@@ -6328,7 +6327,7 @@ e1000_led_off(struct e1000_hw *hw)
+ static void
+ e1000_clear_hw_cntrs(struct e1000_hw *hw)
+ {
+- volatile uint32_t temp;
++ volatile u32 temp;
+
+ temp = E1000_READ_REG(hw, CRCERRS);
+ temp = E1000_READ_REG(hw, SYMERRS);
+@@ -6425,7 +6424,7 @@ e1000_clear_hw_cntrs(struct e1000_hw *hw)
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Call this after e1000_init_hw. You may override the IFS defaults by setting
+- * hw->ifs_params_forced to TRUE. However, you must initialize hw->
++ * hw->ifs_params_forced to true. However, you must initialize hw->
+ * current_ifs_val, ifs_min_val, ifs_max_val, ifs_step_size, and ifs_ratio
+ * before calling this function.
+ *****************************************************************************/
+@@ -6442,7 +6441,7 @@ e1000_reset_adaptive(struct e1000_hw *hw)
+ hw->ifs_step_size = IFS_STEP;
+ hw->ifs_ratio = IFS_RATIO;
+ }
+- hw->in_ifs_mode = FALSE;
++ hw->in_ifs_mode = false;
+ E1000_WRITE_REG(hw, AIT, 0);
+ } else {
+ DEBUGOUT("Not in Adaptive IFS mode!\n");
+@@ -6465,7 +6464,7 @@ e1000_update_adaptive(struct e1000_hw *hw)
+ if (hw->adaptive_ifs) {
+ if ((hw->collision_delta * hw->ifs_ratio) > hw->tx_packet_delta) {
+ if (hw->tx_packet_delta > MIN_NUM_XMITS) {
+- hw->in_ifs_mode = TRUE;
++ hw->in_ifs_mode = true;
+ if (hw->current_ifs_val < hw->ifs_max_val) {
+ if (hw->current_ifs_val == 0)
+ hw->current_ifs_val = hw->ifs_min_val;
+@@ -6477,7 +6476,7 @@ e1000_update_adaptive(struct e1000_hw *hw)
+ } else {
+ if (hw->in_ifs_mode && (hw->tx_packet_delta <= MIN_NUM_XMITS)) {
+ hw->current_ifs_val = 0;
+- hw->in_ifs_mode = FALSE;
++ hw->in_ifs_mode = false;
+ E1000_WRITE_REG(hw, AIT, 0);
+ }
+ }
+@@ -6496,10 +6495,10 @@ e1000_update_adaptive(struct e1000_hw *hw)
+ void
+ e1000_tbi_adjust_stats(struct e1000_hw *hw,
+ struct e1000_hw_stats *stats,
+- uint32_t frame_len,
+- uint8_t *mac_addr)
++ u32 frame_len,
++ u8 *mac_addr)
+ {
+- uint64_t carry_bit;
++ u64 carry_bit;
+
+ /* First adjust the frame length. */
+ frame_len--;
+@@ -6528,7 +6527,7 @@ e1000_tbi_adjust_stats(struct e1000_hw *hw,
+ * since the test for a multicast frame will test positive on
+ * a broadcast frame.
+ */
+- if ((mac_addr[0] == (uint8_t) 0xff) && (mac_addr[1] == (uint8_t) 0xff))
++ if ((mac_addr[0] == (u8) 0xff) && (mac_addr[1] == (u8) 0xff))
+ /* Broadcast packet */
+ stats->bprc++;
+ else if (*mac_addr & 0x01)
+@@ -6574,9 +6573,9 @@ e1000_tbi_adjust_stats(struct e1000_hw *hw,
+ void
+ e1000_get_bus_info(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t pci_ex_link_status;
+- uint32_t status;
++ s32 ret_val;
++ u16 pci_ex_link_status;
++ u32 status;
+
+ switch (hw->mac_type) {
+ case e1000_82542_rev2_0:
+@@ -6648,8 +6647,8 @@ e1000_get_bus_info(struct e1000_hw *hw)
+ *****************************************************************************/
+ static void
+ e1000_write_reg_io(struct e1000_hw *hw,
+- uint32_t offset,
+- uint32_t value)
++ u32 offset,
++ u32 value)
+ {
+ unsigned long io_addr = hw->io_base;
+ unsigned long io_data = hw->io_base + 4;
+@@ -6673,15 +6672,15 @@ e1000_write_reg_io(struct e1000_hw *hw,
+ * register to the minimum and maximum range.
+ * For IGP phy's, the function calculates the range by the AGC registers.
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_get_cable_length(struct e1000_hw *hw,
+- uint16_t *min_length,
+- uint16_t *max_length)
++ u16 *min_length,
++ u16 *max_length)
+ {
+- int32_t ret_val;
+- uint16_t agc_value = 0;
+- uint16_t i, phy_data;
+- uint16_t cable_length;
++ s32 ret_val;
++ u16 agc_value = 0;
++ u16 i, phy_data;
++ u16 cable_length;
+
+ DEBUGFUNC("e1000_get_cable_length");
+
+@@ -6752,9 +6751,9 @@ e1000_get_cable_length(struct e1000_hw *hw,
+ break;
+ }
+ } else if (hw->phy_type == e1000_phy_igp) { /* For IGP PHY */
+- uint16_t cur_agc_value;
+- uint16_t min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
+- uint16_t agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
++ u16 cur_agc_value;
++ u16 min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
++ u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
+ {IGP01E1000_PHY_AGC_A,
+ IGP01E1000_PHY_AGC_B,
+ IGP01E1000_PHY_AGC_C,
+@@ -6800,9 +6799,9 @@ e1000_get_cable_length(struct e1000_hw *hw,
+ IGP01E1000_AGC_RANGE;
+ } else if (hw->phy_type == e1000_phy_igp_2 ||
+ hw->phy_type == e1000_phy_igp_3) {
+- uint16_t cur_agc_index, max_agc_index = 0;
+- uint16_t min_agc_index = IGP02E1000_AGC_LENGTH_TABLE_SIZE - 1;
+- uint16_t agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] =
++ u16 cur_agc_index, max_agc_index = 0;
++ u16 min_agc_index = IGP02E1000_AGC_LENGTH_TABLE_SIZE - 1;
++ u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] =
+ {IGP02E1000_PHY_AGC_A,
+ IGP02E1000_PHY_AGC_B,
+ IGP02E1000_PHY_AGC_C,
+@@ -6864,12 +6863,12 @@ e1000_get_cable_length(struct e1000_hw *hw,
+ * return 0. If the link speed is 1000 Mbps the polarity status is in the
+ * IGP01E1000_PHY_PCS_INIT_REG.
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_check_polarity(struct e1000_hw *hw,
+ e1000_rev_polarity *polarity)
+ {
+- int32_t ret_val;
+- uint16_t phy_data;
++ s32 ret_val;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_check_polarity");
+
+@@ -6940,11 +6939,11 @@ e1000_check_polarity(struct e1000_hw *hw,
+ * Link Health register. In IGP this bit is latched high, so the driver must
+ * read it immediately after link is established.
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_check_downshift(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t phy_data;
++ s32 ret_val;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_check_downshift");
+
+@@ -6968,7 +6967,7 @@ e1000_check_downshift(struct e1000_hw *hw)
+ M88E1000_PSSR_DOWNSHIFT_SHIFT;
+ } else if (hw->phy_type == e1000_phy_ife) {
+ /* e1000_phy_ife supports 10/100 speed only */
+- hw->speed_downgraded = FALSE;
++ hw->speed_downgraded = false;
+ }
+
+ return E1000_SUCCESS;
+@@ -6986,18 +6985,18 @@ e1000_check_downshift(struct e1000_hw *hw)
+ *
+ ****************************************************************************/
+
+-static int32_t
++static s32
+ e1000_config_dsp_after_link_change(struct e1000_hw *hw,
+- boolean_t link_up)
++ bool link_up)
+ {
+- int32_t ret_val;
+- uint16_t phy_data, phy_saved_data, speed, duplex, i;
+- uint16_t dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
++ s32 ret_val;
++ u16 phy_data, phy_saved_data, speed, duplex, i;
++ u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
+ {IGP01E1000_PHY_AGC_PARAM_A,
+ IGP01E1000_PHY_AGC_PARAM_B,
+ IGP01E1000_PHY_AGC_PARAM_C,
+ IGP01E1000_PHY_AGC_PARAM_D};
+- uint16_t min_length, max_length;
++ u16 min_length, max_length;
+
+ DEBUGFUNC("e1000_config_dsp_after_link_change");
+
+@@ -7039,8 +7038,8 @@ e1000_config_dsp_after_link_change(struct e1000_hw *hw,
+ if ((hw->ffe_config_state == e1000_ffe_config_enabled) &&
+ (min_length < e1000_igp_cable_length_50)) {
+
+- uint16_t ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20;
+- uint32_t idle_errs = 0;
++ u16 ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20;
++ u32 idle_errs = 0;
+
+ /* clear previous idle error counts */
+ ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS,
+@@ -7174,11 +7173,11 @@ e1000_config_dsp_after_link_change(struct e1000_hw *hw,
+ *
+ * hw - Struct containing variables accessed by shared code
+ ****************************************************************************/
+-static int32_t
++static s32
+ e1000_set_phy_mode(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t eeprom_data;
++ s32 ret_val;
++ u16 eeprom_data;
+
+ DEBUGFUNC("e1000_set_phy_mode");
+
+@@ -7198,7 +7197,7 @@ e1000_set_phy_mode(struct e1000_hw *hw)
+ if (ret_val)
+ return ret_val;
+
+- hw->phy_reset_disable = FALSE;
++ hw->phy_reset_disable = false;
+ }
+ }
+
+@@ -7219,13 +7218,13 @@ e1000_set_phy_mode(struct e1000_hw *hw)
+ *
+ ****************************************************************************/
+
+-static int32_t
++static s32
+ e1000_set_d3_lplu_state(struct e1000_hw *hw,
+- boolean_t active)
++ bool active)
+ {
+- uint32_t phy_ctrl = 0;
+- int32_t ret_val;
+- uint16_t phy_data;
++ u32 phy_ctrl = 0;
++ s32 ret_val;
++ u16 phy_data;
+ DEBUGFUNC("e1000_set_d3_lplu_state");
+
+ if (hw->phy_type != e1000_phy_igp && hw->phy_type != e1000_phy_igp_2
+@@ -7349,13 +7348,13 @@ e1000_set_d3_lplu_state(struct e1000_hw *hw,
+ *
+ ****************************************************************************/
+
+-static int32_t
++static s32
+ e1000_set_d0_lplu_state(struct e1000_hw *hw,
+- boolean_t active)
++ bool active)
+ {
+- uint32_t phy_ctrl = 0;
+- int32_t ret_val;
+- uint16_t phy_data;
++ u32 phy_ctrl = 0;
++ s32 ret_val;
++ u16 phy_data;
+ DEBUGFUNC("e1000_set_d0_lplu_state");
+
+ if (hw->mac_type <= e1000_82547_rev_2)
+@@ -7440,12 +7439,12 @@ e1000_set_d0_lplu_state(struct e1000_hw *hw,
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_set_vco_speed(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t default_page = 0;
+- uint16_t phy_data;
++ s32 ret_val;
++ u16 default_page = 0;
++ u16 phy_data;
+
+ DEBUGFUNC("e1000_set_vco_speed");
+
+@@ -7504,18 +7503,18 @@ e1000_set_vco_speed(struct e1000_hw *hw)
+ *
+ * returns: - E1000_SUCCESS .
+ ****************************************************************************/
+-static int32_t
+-e1000_host_if_read_cookie(struct e1000_hw * hw, uint8_t *buffer)
++static s32
++e1000_host_if_read_cookie(struct e1000_hw * hw, u8 *buffer)
+ {
+- uint8_t i;
+- uint32_t offset = E1000_MNG_DHCP_COOKIE_OFFSET;
+- uint8_t length = E1000_MNG_DHCP_COOKIE_LENGTH;
++ u8 i;
++ u32 offset = E1000_MNG_DHCP_COOKIE_OFFSET;
++ u8 length = E1000_MNG_DHCP_COOKIE_LENGTH;
+
+ length = (length >> 2);
+ offset = (offset >> 2);
+
+ for (i = 0; i < length; i++) {
+- *((uint32_t *) buffer + i) =
++ *((u32 *) buffer + i) =
+ E1000_READ_REG_ARRAY_DWORD(hw, HOST_IF, offset + i);
+ }
+ return E1000_SUCCESS;
+@@ -7531,11 +7530,11 @@ e1000_host_if_read_cookie(struct e1000_hw * hw, uint8_t *buffer)
+ * timeout
+ * - E1000_SUCCESS for success.
+ ****************************************************************************/
+-static int32_t
++static s32
+ e1000_mng_enable_host_if(struct e1000_hw * hw)
+ {
+- uint32_t hicr;
+- uint8_t i;
++ u32 hicr;
++ u8 i;
+
+ /* Check that the host interface is enabled. */
+ hicr = E1000_READ_REG(hw, HICR);
+@@ -7565,14 +7564,14 @@ e1000_mng_enable_host_if(struct e1000_hw * hw)
+ *
+ * returns - E1000_SUCCESS for success.
+ ****************************************************************************/
+-static int32_t
+-e1000_mng_host_if_write(struct e1000_hw * hw, uint8_t *buffer,
+- uint16_t length, uint16_t offset, uint8_t *sum)
++static s32
++e1000_mng_host_if_write(struct e1000_hw * hw, u8 *buffer,
++ u16 length, u16 offset, u8 *sum)
+ {
+- uint8_t *tmp;
+- uint8_t *bufptr = buffer;
+- uint32_t data = 0;
+- uint16_t remaining, i, j, prev_bytes;
++ u8 *tmp;
++ u8 *bufptr = buffer;
++ u32 data = 0;
++ u16 remaining, i, j, prev_bytes;
+
+ /* sum = only sum of the data and it is not checksum */
+
+@@ -7580,14 +7579,14 @@ e1000_mng_host_if_write(struct e1000_hw * hw, uint8_t *buffer,
+ return -E1000_ERR_PARAM;
+ }
+
+- tmp = (uint8_t *)&data;
++ tmp = (u8 *)&data;
+ prev_bytes = offset & 0x3;
+ offset &= 0xFFFC;
+ offset >>= 2;
+
+ if (prev_bytes) {
+ data = E1000_READ_REG_ARRAY_DWORD(hw, HOST_IF, offset);
+- for (j = prev_bytes; j < sizeof(uint32_t); j++) {
++ for (j = prev_bytes; j < sizeof(u32); j++) {
+ *(tmp + j) = *bufptr++;
+ *sum += *(tmp + j);
+ }
+@@ -7605,7 +7604,7 @@ e1000_mng_host_if_write(struct e1000_hw * hw, uint8_t *buffer,
+ /* The device driver writes the relevant command block into the
+ * ram area. */
+ for (i = 0; i < length; i++) {
+- for (j = 0; j < sizeof(uint32_t); j++) {
++ for (j = 0; j < sizeof(u32); j++) {
+ *(tmp + j) = *bufptr++;
+ *sum += *(tmp + j);
+ }
+@@ -7613,7 +7612,7 @@ e1000_mng_host_if_write(struct e1000_hw * hw, uint8_t *buffer,
+ E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, offset + i, data);
+ }
+ if (remaining) {
+- for (j = 0; j < sizeof(uint32_t); j++) {
++ for (j = 0; j < sizeof(u32); j++) {
+ if (j < remaining)
+ *(tmp + j) = *bufptr++;
+ else
+@@ -7633,23 +7632,23 @@ e1000_mng_host_if_write(struct e1000_hw * hw, uint8_t *buffer,
+ *
+ * returns - E1000_SUCCESS for success.
+ ****************************************************************************/
+-static int32_t
++static s32
+ e1000_mng_write_cmd_header(struct e1000_hw * hw,
+ struct e1000_host_mng_command_header * hdr)
+ {
+- uint16_t i;
+- uint8_t sum;
+- uint8_t *buffer;
++ u16 i;
++ u8 sum;
++ u8 *buffer;
+
+ /* Write the whole command header structure which includes sum of
+ * the buffer */
+
+- uint16_t length = sizeof(struct e1000_host_mng_command_header);
++ u16 length = sizeof(struct e1000_host_mng_command_header);
+
+ sum = hdr->checksum;
+ hdr->checksum = 0;
+
+- buffer = (uint8_t *) hdr;
++ buffer = (u8 *) hdr;
+ i = length;
+ while (i--)
+ sum += buffer[i];
+@@ -7659,7 +7658,7 @@ e1000_mng_write_cmd_header(struct e1000_hw * hw,
+ length >>= 2;
+ /* The device driver writes the relevant command block into the ram area. */
+ for (i = 0; i < length; i++) {
+- E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, i, *((uint32_t *) hdr + i));
++ E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, i, *((u32 *) hdr + i));
+ E1000_WRITE_FLUSH(hw);
+ }
+
+@@ -7673,10 +7672,10 @@ e1000_mng_write_cmd_header(struct e1000_hw * hw,
+ *
+ * returns - E1000_SUCCESS for success.
+ ****************************************************************************/
+-static int32_t
++static s32
+ e1000_mng_write_commit(struct e1000_hw * hw)
+ {
+- uint32_t hicr;
++ u32 hicr;
+
+ hicr = E1000_READ_REG(hw, HICR);
+ /* Setting this bit tells the ARC that a new command is pending. */
+@@ -7689,35 +7688,35 @@ e1000_mng_write_commit(struct e1000_hw * hw)
+ /*****************************************************************************
+ * This function checks the mode of the firmware.
+ *
+- * returns - TRUE when the mode is IAMT or FALSE.
++ * returns - true when the mode is IAMT or false.
+ ****************************************************************************/
+-boolean_t
++bool
+ e1000_check_mng_mode(struct e1000_hw *hw)
+ {
+- uint32_t fwsm;
++ u32 fwsm;
+
+ fwsm = E1000_READ_REG(hw, FWSM);
+
+ if (hw->mac_type == e1000_ich8lan) {
+ if ((fwsm & E1000_FWSM_MODE_MASK) ==
+ (E1000_MNG_ICH_IAMT_MODE << E1000_FWSM_MODE_SHIFT))
+- return TRUE;
++ return true;
+ } else if ((fwsm & E1000_FWSM_MODE_MASK) ==
+ (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT))
+- return TRUE;
++ return true;
+
+- return FALSE;
++ return false;
+ }
+
+
+ /*****************************************************************************
+ * This function writes the dhcp info .
+ ****************************************************************************/
+-int32_t
+-e1000_mng_write_dhcp_info(struct e1000_hw * hw, uint8_t *buffer,
+- uint16_t length)
++s32
++e1000_mng_write_dhcp_info(struct e1000_hw * hw, u8 *buffer,
++ u16 length)
+ {
+- int32_t ret_val;
++ s32 ret_val;
+ struct e1000_host_mng_command_header hdr;
+
+ hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
+@@ -7745,11 +7744,11 @@ e1000_mng_write_dhcp_info(struct e1000_hw * hw, uint8_t *buffer,
+ *
+ * returns - checksum of buffer contents.
+ ****************************************************************************/
+-static uint8_t
+-e1000_calculate_mng_checksum(char *buffer, uint32_t length)
++static u8
++e1000_calculate_mng_checksum(char *buffer, u32 length)
+ {
+- uint8_t sum = 0;
+- uint32_t i;
++ u8 sum = 0;
++ u32 i;
+
+ if (!buffer)
+ return 0;
+@@ -7757,23 +7756,23 @@ e1000_calculate_mng_checksum(char *buffer, uint32_t length)
+ for (i=0; i < length; i++)
+ sum += buffer[i];
+
+- return (uint8_t) (0 - sum);
++ return (u8) (0 - sum);
+ }
+
+ /*****************************************************************************
+ * This function checks whether tx pkt filtering needs to be enabled or not.
+ *
+- * returns - TRUE for packet filtering or FALSE.
++ * returns - true for packet filtering or false.
+ ****************************************************************************/
+-boolean_t
++bool
+ e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
+ {
+ /* called in init as well as watchdog timer functions */
+
+- int32_t ret_val, checksum;
+- boolean_t tx_filter = FALSE;
++ s32 ret_val, checksum;
++ bool tx_filter = false;
+ struct e1000_host_mng_dhcp_cookie *hdr = &(hw->mng_cookie);
+- uint8_t *buffer = (uint8_t *) &(hw->mng_cookie);
++ u8 *buffer = (u8 *) &(hw->mng_cookie);
+
+ if (e1000_check_mng_mode(hw)) {
+ ret_val = e1000_mng_enable_host_if(hw);
+@@ -7787,11 +7786,11 @@ e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
+ E1000_MNG_DHCP_COOKIE_LENGTH)) {
+ if (hdr->status &
+ E1000_MNG_DHCP_COOKIE_STATUS_PARSING_SUPPORT)
+- tx_filter = TRUE;
++ tx_filter = true;
+ } else
+- tx_filter = TRUE;
++ tx_filter = true;
+ } else
+- tx_filter = TRUE;
++ tx_filter = true;
+ }
+ }
+
+@@ -7804,41 +7803,41 @@ e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+- * returns: - TRUE/FALSE
++ * returns: - true/false
+ *
+ *****************************************************************************/
+-uint32_t
++u32
+ e1000_enable_mng_pass_thru(struct e1000_hw *hw)
+ {
+- uint32_t manc;
+- uint32_t fwsm, factps;
++ u32 manc;
++ u32 fwsm, factps;
+
+ if (hw->asf_firmware_present) {
+ manc = E1000_READ_REG(hw, MANC);
+
+ if (!(manc & E1000_MANC_RCV_TCO_EN) ||
+ !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
+- return FALSE;
+- if (e1000_arc_subsystem_valid(hw) == TRUE) {
++ return false;
++ if (e1000_arc_subsystem_valid(hw)) {
+ fwsm = E1000_READ_REG(hw, FWSM);
+ factps = E1000_READ_REG(hw, FACTPS);
+
+ if ((((fwsm & E1000_FWSM_MODE_MASK) >> E1000_FWSM_MODE_SHIFT) ==
+ e1000_mng_mode_pt) && !(factps & E1000_FACTPS_MNGCG))
+- return TRUE;
++ return true;
+ } else
+ if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN))
+- return TRUE;
++ return true;
+ }
+- return FALSE;
++ return false;
+ }
+
+-static int32_t
++static s32
+ e1000_polarity_reversal_workaround(struct e1000_hw *hw)
+ {
+- int32_t ret_val;
+- uint16_t mii_status_reg;
+- uint16_t i;
++ s32 ret_val;
++ u16 mii_status_reg;
++ u16 i;
+
+ /* Polarity reversal workaround for forced 10F/10H links. */
+
+@@ -7930,7 +7929,7 @@ e1000_polarity_reversal_workaround(struct e1000_hw *hw)
+ static void
+ e1000_set_pci_express_master_disable(struct e1000_hw *hw)
+ {
+- uint32_t ctrl;
++ u32 ctrl;
+
+ DEBUGFUNC("e1000_set_pci_express_master_disable");
+
+@@ -7953,10 +7952,10 @@ e1000_set_pci_express_master_disable(struct e1000_hw *hw)
+ * E1000_SUCCESS master requests disabled.
+ *
+ ******************************************************************************/
+-int32_t
++s32
+ e1000_disable_pciex_master(struct e1000_hw *hw)
+ {
+- int32_t timeout = MASTER_DISABLE_TIMEOUT; /* 80ms */
++ s32 timeout = MASTER_DISABLE_TIMEOUT; /* 80ms */
+
+ DEBUGFUNC("e1000_disable_pciex_master");
+
+@@ -7991,10 +7990,10 @@ e1000_disable_pciex_master(struct e1000_hw *hw)
+ * E1000_SUCCESS at any other case.
+ *
+ ******************************************************************************/
+-static int32_t
++static s32
+ e1000_get_auto_rd_done(struct e1000_hw *hw)
+ {
+- int32_t timeout = AUTO_READ_DONE_TIMEOUT;
++ s32 timeout = AUTO_READ_DONE_TIMEOUT;
+
+ DEBUGFUNC("e1000_get_auto_rd_done");
+
+@@ -8039,11 +8038,11 @@ e1000_get_auto_rd_done(struct e1000_hw *hw)
+ * E1000_SUCCESS at any other case.
+ *
+ ***************************************************************************/
+-static int32_t
++static s32
+ e1000_get_phy_cfg_done(struct e1000_hw *hw)
+ {
+- int32_t timeout = PHY_CFG_TIMEOUT;
+- uint32_t cfg_mask = E1000_EEPROM_CFG_DONE;
++ s32 timeout = PHY_CFG_TIMEOUT;
++ u32 cfg_mask = E1000_EEPROM_CFG_DONE;
+
+ DEBUGFUNC("e1000_get_phy_cfg_done");
+
+@@ -8086,11 +8085,11 @@ e1000_get_phy_cfg_done(struct e1000_hw *hw)
+ * E1000_SUCCESS at any other case.
+ *
+ ***************************************************************************/
+-static int32_t
++static s32
+ e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
+ {
+- int32_t timeout;
+- uint32_t swsm;
++ s32 timeout;
++ u32 swsm;
+
+ DEBUGFUNC("e1000_get_hw_eeprom_semaphore");
+
+@@ -8139,7 +8138,7 @@ e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
+ static void
+ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
+ {
+- uint32_t swsm;
++ u32 swsm;
+
+ DEBUGFUNC("e1000_put_hw_eeprom_semaphore");
+
+@@ -8165,11 +8164,11 @@ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
+ * E1000_SUCCESS at any other case.
+ *
+ ***************************************************************************/
+-static int32_t
++static s32
+ e1000_get_software_semaphore(struct e1000_hw *hw)
+ {
+- int32_t timeout = hw->eeprom.word_size + 1;
+- uint32_t swsm;
++ s32 timeout = hw->eeprom.word_size + 1;
++ u32 swsm;
+
+ DEBUGFUNC("e1000_get_software_semaphore");
+
+@@ -8204,7 +8203,7 @@ e1000_get_software_semaphore(struct e1000_hw *hw)
+ static void
+ e1000_release_software_semaphore(struct e1000_hw *hw)
+ {
+- uint32_t swsm;
++ u32 swsm;
+
+ DEBUGFUNC("e1000_release_software_semaphore");
+
+@@ -8229,11 +8228,11 @@ e1000_release_software_semaphore(struct e1000_hw *hw)
+ * E1000_SUCCESS
+ *
+ *****************************************************************************/
+-int32_t
++s32
+ e1000_check_phy_reset_block(struct e1000_hw *hw)
+ {
+- uint32_t manc = 0;
+- uint32_t fwsm = 0;
++ u32 manc = 0;
++ u32 fwsm = 0;
+
+ if (hw->mac_type == e1000_ich8lan) {
+ fwsm = E1000_READ_REG(hw, FWSM);
+@@ -8247,10 +8246,10 @@ e1000_check_phy_reset_block(struct e1000_hw *hw)
+ E1000_BLK_PHY_RESET : E1000_SUCCESS;
+ }
+
+-static uint8_t
++static u8
+ e1000_arc_subsystem_valid(struct e1000_hw *hw)
+ {
+- uint32_t fwsm;
++ u32 fwsm;
+
+ /* On 8257x silicon, registers in the range of 0x8800 - 0x8FFC
+ * may not be provided a DMA clock when no manageability features are
+@@ -8264,14 +8263,14 @@ e1000_arc_subsystem_valid(struct e1000_hw *hw)
+ case e1000_80003es2lan:
+ fwsm = E1000_READ_REG(hw, FWSM);
+ if ((fwsm & E1000_FWSM_MODE_MASK) != 0)
+- return TRUE;
++ return true;
+ break;
+ case e1000_ich8lan:
+- return TRUE;
++ return true;
+ default:
+ break;
+ }
+- return FALSE;
++ return false;
+ }
+
+
+@@ -8284,10 +8283,10 @@ e1000_arc_subsystem_valid(struct e1000_hw *hw)
+ * returns: E1000_SUCCESS
+ *
+ *****************************************************************************/
+-static int32_t
+-e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop)
++static s32
++e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, u32 no_snoop)
+ {
+- uint32_t gcr_reg = 0;
++ u32 gcr_reg = 0;
+
+ DEBUGFUNC("e1000_set_pci_ex_no_snoop");
+
+@@ -8304,7 +8303,7 @@ e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop)
+ E1000_WRITE_REG(hw, GCR, gcr_reg);
+ }
+ if (hw->mac_type == e1000_ich8lan) {
+- uint32_t ctrl_ext;
++ u32 ctrl_ext;
+
+ E1000_WRITE_REG(hw, GCR, PCI_EX_82566_SNOOP_ALL);
+
+@@ -8325,11 +8324,11 @@ e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop)
+ * hw: Struct containing variables accessed by shared code
+ *
+ ***************************************************************************/
+-static int32_t
++static s32
+ e1000_get_software_flag(struct e1000_hw *hw)
+ {
+- int32_t timeout = PHY_CFG_TIMEOUT;
+- uint32_t extcnf_ctrl;
++ s32 timeout = PHY_CFG_TIMEOUT;
++ u32 extcnf_ctrl;
+
+ DEBUGFUNC("e1000_get_software_flag");
+
+@@ -8367,7 +8366,7 @@ e1000_get_software_flag(struct e1000_hw *hw)
+ static void
+ e1000_release_software_flag(struct e1000_hw *hw)
+ {
+- uint32_t extcnf_ctrl;
++ u32 extcnf_ctrl;
+
+ DEBUGFUNC("e1000_release_software_flag");
+
+@@ -8389,16 +8388,16 @@ e1000_release_software_flag(struct e1000_hw *hw)
+ * data - word read from the EEPROM
+ * words - number of words to read
+ *****************************************************************************/
+-static int32_t
+-e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
+- uint16_t *data)
++static s32
++e1000_read_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
++ u16 *data)
+ {
+- int32_t error = E1000_SUCCESS;
+- uint32_t flash_bank = 0;
+- uint32_t act_offset = 0;
+- uint32_t bank_offset = 0;
+- uint16_t word = 0;
+- uint16_t i = 0;
++ s32 error = E1000_SUCCESS;
++ u32 flash_bank = 0;
++ u32 act_offset = 0;
++ u32 bank_offset = 0;
++ u16 word = 0;
++ u16 i = 0;
+
+ /* We need to know which is the valid flash bank. In the event
+ * that we didn't allocate eeprom_shadow_ram, we may not be
+@@ -8417,7 +8416,7 @@ e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
+
+ for (i = 0; i < words; i++) {
+ if (hw->eeprom_shadow_ram != NULL &&
+- hw->eeprom_shadow_ram[offset+i].modified == TRUE) {
++ hw->eeprom_shadow_ram[offset+i].modified) {
+ data[i] = hw->eeprom_shadow_ram[offset+i].eeprom_word;
+ } else {
+ /* The NVM part needs a byte offset, hence * 2 */
+@@ -8445,12 +8444,12 @@ e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
+ * words - number of words to write
+ * data - words to write to the EEPROM
+ *****************************************************************************/
+-static int32_t
+-e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
+- uint16_t *data)
++static s32
++e1000_write_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
++ u16 *data)
+ {
+- uint32_t i = 0;
+- int32_t error = E1000_SUCCESS;
++ u32 i = 0;
++ s32 error = E1000_SUCCESS;
+
+ error = e1000_get_software_flag(hw);
+ if (error != E1000_SUCCESS)
+@@ -8466,7 +8465,7 @@ e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
+ if (hw->eeprom_shadow_ram != NULL) {
+ for (i = 0; i < words; i++) {
+ if ((offset + i) < E1000_SHADOW_RAM_WORDS) {
+- hw->eeprom_shadow_ram[offset+i].modified = TRUE;
++ hw->eeprom_shadow_ram[offset+i].modified = true;
+ hw->eeprom_shadow_ram[offset+i].eeprom_word = data[i];
+ } else {
+ error = -E1000_ERR_EEPROM;
+@@ -8492,12 +8491,12 @@ e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
+ *
+ * hw - The pointer to the hw structure
+ ****************************************************************************/
+-static int32_t
++static s32
+ e1000_ich8_cycle_init(struct e1000_hw *hw)
+ {
+ union ich8_hws_flash_status hsfsts;
+- int32_t error = E1000_ERR_EEPROM;
+- int32_t i = 0;
++ s32 error = E1000_ERR_EEPROM;
++ s32 i = 0;
+
+ DEBUGFUNC("e1000_ich8_cycle_init");
+
+@@ -8559,13 +8558,13 @@ e1000_ich8_cycle_init(struct e1000_hw *hw)
+ *
+ * hw - The pointer to the hw structure
+ ****************************************************************************/
+-static int32_t
+-e1000_ich8_flash_cycle(struct e1000_hw *hw, uint32_t timeout)
++static s32
++e1000_ich8_flash_cycle(struct e1000_hw *hw, u32 timeout)
+ {
+ union ich8_hws_flash_ctrl hsflctl;
+ union ich8_hws_flash_status hsfsts;
+- int32_t error = E1000_ERR_EEPROM;
+- uint32_t i = 0;
++ s32 error = E1000_ERR_EEPROM;
++ u32 i = 0;
+
+ /* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */
+ hsflctl.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
+@@ -8594,16 +8593,16 @@ e1000_ich8_flash_cycle(struct e1000_hw *hw, uint32_t timeout)
+ * size - Size of data to read, 1=byte 2=word
+ * data - Pointer to the word to store the value read.
+ *****************************************************************************/
+-static int32_t
+-e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
+- uint32_t size, uint16_t* data)
++static s32
++e1000_read_ich8_data(struct e1000_hw *hw, u32 index,
++ u32 size, u16* data)
+ {
+ union ich8_hws_flash_status hsfsts;
+ union ich8_hws_flash_ctrl hsflctl;
+- uint32_t flash_linear_address;
+- uint32_t flash_data = 0;
+- int32_t error = -E1000_ERR_EEPROM;
+- int32_t count = 0;
++ u32 flash_linear_address;
++ u32 flash_data = 0;
++ s32 error = -E1000_ERR_EEPROM;
++ s32 count = 0;
+
+ DEBUGFUNC("e1000_read_ich8_data");
+
+@@ -8641,9 +8640,9 @@ e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
+ if (error == E1000_SUCCESS) {
+ flash_data = E1000_READ_ICH_FLASH_REG(hw, ICH_FLASH_FDATA0);
+ if (size == 1) {
+- *data = (uint8_t)(flash_data & 0x000000FF);
++ *data = (u8)(flash_data & 0x000000FF);
+ } else if (size == 2) {
+- *data = (uint16_t)(flash_data & 0x0000FFFF);
++ *data = (u16)(flash_data & 0x0000FFFF);
+ }
+ break;
+ } else {
+@@ -8673,16 +8672,16 @@ e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
+ * size - Size of data to read, 1=byte 2=word
+ * data - The byte(s) to write to the NVM.
+ *****************************************************************************/
+-static int32_t
+-e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size,
+- uint16_t data)
++static s32
++e1000_write_ich8_data(struct e1000_hw *hw, u32 index, u32 size,
++ u16 data)
+ {
+ union ich8_hws_flash_status hsfsts;
+ union ich8_hws_flash_ctrl hsflctl;
+- uint32_t flash_linear_address;
+- uint32_t flash_data = 0;
+- int32_t error = -E1000_ERR_EEPROM;
+- int32_t count = 0;
++ u32 flash_linear_address;
++ u32 flash_data = 0;
++ s32 error = -E1000_ERR_EEPROM;
++ s32 count = 0;
+
+ DEBUGFUNC("e1000_write_ich8_data");
+
+@@ -8711,9 +8710,9 @@ e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size,
+ E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_address);
+
+ if (size == 1)
+- flash_data = (uint32_t)data & 0x00FF;
++ flash_data = (u32)data & 0x00FF;
+ else
+- flash_data = (uint32_t)data;
++ flash_data = (u32)data;
+
+ E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FDATA0, flash_data);
+
+@@ -8748,15 +8747,15 @@ e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size,
+ * index - The index of the byte to read.
+ * data - Pointer to a byte to store the value read.
+ *****************************************************************************/
+-static int32_t
+-e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t* data)
++static s32
++e1000_read_ich8_byte(struct e1000_hw *hw, u32 index, u8* data)
+ {
+- int32_t status = E1000_SUCCESS;
+- uint16_t word = 0;
++ s32 status = E1000_SUCCESS;
++ u16 word = 0;
+
+ status = e1000_read_ich8_data(hw, index, 1, &word);
+ if (status == E1000_SUCCESS) {
+- *data = (uint8_t)word;
++ *data = (u8)word;
+ }
+
+ return status;
+@@ -8771,11 +8770,11 @@ e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t* data)
+ * index - The index of the byte to write.
+ * byte - The byte to write to the NVM.
+ *****************************************************************************/
+-static int32_t
+-e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t byte)
++static s32
++e1000_verify_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte)
+ {
+- int32_t error = E1000_SUCCESS;
+- int32_t program_retries = 0;
++ s32 error = E1000_SUCCESS;
++ s32 program_retries = 0;
+
+ DEBUGOUT2("Byte := %2.2X Offset := %d\n", byte, index);
+
+@@ -8804,11 +8803,11 @@ e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t byte)
+ * index - The index of the byte to read.
+ * data - The byte to write to the NVM.
+ *****************************************************************************/
+-static int32_t
+-e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t data)
++static s32
++e1000_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 data)
+ {
+- int32_t status = E1000_SUCCESS;
+- uint16_t word = (uint16_t)data;
++ s32 status = E1000_SUCCESS;
++ u16 word = (u16)data;
+
+ status = e1000_write_ich8_data(hw, index, 1, word);
+
+@@ -8822,10 +8821,10 @@ e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t data)
+ * index - The starting byte index of the word to read.
+ * data - Pointer to a word to store the value read.
+ *****************************************************************************/
+-static int32_t
+-e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t *data)
++static s32
++e1000_read_ich8_word(struct e1000_hw *hw, u32 index, u16 *data)
+ {
+- int32_t status = E1000_SUCCESS;
++ s32 status = E1000_SUCCESS;
+ status = e1000_read_ich8_data(hw, index, 2, data);
+ return status;
+ }
+@@ -8841,19 +8840,19 @@ e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t *data)
+ * amount of NVM used in each bank is a *minimum* of 4 KBytes, but in fact the
+ * bank size may be 4, 8 or 64 KBytes
+ *****************************************************************************/
+-static int32_t
+-e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t bank)
++static s32
++e1000_erase_ich8_4k_segment(struct e1000_hw *hw, u32 bank)
+ {
+ union ich8_hws_flash_status hsfsts;
+ union ich8_hws_flash_ctrl hsflctl;
+- uint32_t flash_linear_address;
+- int32_t count = 0;
+- int32_t error = E1000_ERR_EEPROM;
+- int32_t iteration;
+- int32_t sub_sector_size = 0;
+- int32_t bank_size;
+- int32_t j = 0;
+- int32_t error_flag = 0;
++ u32 flash_linear_address;
++ s32 count = 0;
++ s32 error = E1000_ERR_EEPROM;
++ s32 iteration;
++ s32 sub_sector_size = 0;
++ s32 bank_size;
++ s32 j = 0;
++ s32 error_flag = 0;
+
+ hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
+
+@@ -8931,16 +8930,16 @@ e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t bank)
+ return error;
+ }
+
+-static int32_t
++static s32
+ e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
+- uint32_t cnf_base_addr, uint32_t cnf_size)
++ u32 cnf_base_addr, u32 cnf_size)
+ {
+- uint32_t ret_val = E1000_SUCCESS;
+- uint16_t word_addr, reg_data, reg_addr;
+- uint16_t i;
++ u32 ret_val = E1000_SUCCESS;
++ u16 word_addr, reg_data, reg_addr;
++ u16 i;
+
+ /* cnf_base_addr is in DWORD */
+- word_addr = (uint16_t)(cnf_base_addr << 1);
++ word_addr = (u16)(cnf_base_addr << 1);
+
+ /* cnf_size is returned in size of dwords */
+ for (i = 0; i < cnf_size; i++) {
+@@ -8956,7 +8955,7 @@ e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
+ if (ret_val != E1000_SUCCESS)
+ return ret_val;
+
+- ret_val = e1000_write_phy_reg_ex(hw, (uint32_t)reg_addr, reg_data);
++ ret_val = e1000_write_phy_reg_ex(hw, (u32)reg_addr, reg_data);
+
+ e1000_release_software_flag(hw);
+ }
+@@ -8973,10 +8972,10 @@ e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
+ *
+ * hw: Struct containing variables accessed by shared code
+ *****************************************************************************/
+-static int32_t
++static s32
+ e1000_init_lcd_from_nvm(struct e1000_hw *hw)
+ {
+- uint32_t reg_data, cnf_base_addr, cnf_size, ret_val, loop;
++ u32 reg_data, cnf_base_addr, cnf_size, ret_val, loop;
+
+ if (hw->phy_type != e1000_phy_igp_3)
+ return E1000_SUCCESS;
+diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
+index a6c3c34..99fce2c 100644
+--- a/drivers/net/e1000/e1000_hw.h
++++ b/drivers/net/e1000/e1000_hw.h
+@@ -100,8 +100,8 @@ typedef enum {
+ } e1000_fc_type;
+
+ struct e1000_shadow_ram {
+- uint16_t eeprom_word;
+- boolean_t modified;
++ u16 eeprom_word;
++ bool modified;
+ };
+
+ /* PCI bus types */
+@@ -263,19 +263,19 @@ struct e1000_phy_info {
+ };
+
+ struct e1000_phy_stats {
+- uint32_t idle_errors;
+- uint32_t receive_errors;
++ u32 idle_errors;
++ u32 receive_errors;
+ };
+
+ struct e1000_eeprom_info {
+ e1000_eeprom_type type;
+- uint16_t word_size;
+- uint16_t opcode_bits;
+- uint16_t address_bits;
+- uint16_t delay_usec;
+- uint16_t page_size;
+- boolean_t use_eerd;
+- boolean_t use_eewr;
++ u16 word_size;
++ u16 opcode_bits;
++ u16 address_bits;
++ u16 delay_usec;
++ u16 page_size;
++ bool use_eerd;
++ bool use_eewr;
+ };
+
+ /* Flex ASF Information */
+@@ -308,34 +308,34 @@ typedef enum {
+
+ /* Function prototypes */
+ /* Initialization */
+-int32_t e1000_reset_hw(struct e1000_hw *hw);
+-int32_t e1000_init_hw(struct e1000_hw *hw);
+-int32_t e1000_set_mac_type(struct e1000_hw *hw);
++s32 e1000_reset_hw(struct e1000_hw *hw);
++s32 e1000_init_hw(struct e1000_hw *hw);
++s32 e1000_set_mac_type(struct e1000_hw *hw);
+ void e1000_set_media_type(struct e1000_hw *hw);
+
+ /* Link Configuration */
+-int32_t e1000_setup_link(struct e1000_hw *hw);
+-int32_t e1000_phy_setup_autoneg(struct e1000_hw *hw);
++s32 e1000_setup_link(struct e1000_hw *hw);
++s32 e1000_phy_setup_autoneg(struct e1000_hw *hw);
+ void e1000_config_collision_dist(struct e1000_hw *hw);
+-int32_t e1000_check_for_link(struct e1000_hw *hw);
+-int32_t e1000_get_speed_and_duplex(struct e1000_hw *hw, uint16_t *speed, uint16_t *duplex);
+-int32_t e1000_force_mac_fc(struct e1000_hw *hw);
++s32 e1000_check_for_link(struct e1000_hw *hw);
++s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex);
++s32 e1000_force_mac_fc(struct e1000_hw *hw);
+
+ /* PHY */
+-int32_t e1000_read_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *phy_data);
+-int32_t e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t data);
+-int32_t e1000_phy_hw_reset(struct e1000_hw *hw);
+-int32_t e1000_phy_reset(struct e1000_hw *hw);
+-int32_t e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
+-int32_t e1000_validate_mdi_setting(struct e1000_hw *hw);
++s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 *phy_data);
++s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 data);
++s32 e1000_phy_hw_reset(struct e1000_hw *hw);
++s32 e1000_phy_reset(struct e1000_hw *hw);
++s32 e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
++s32 e1000_validate_mdi_setting(struct e1000_hw *hw);
+
+ void e1000_phy_powerdown_workaround(struct e1000_hw *hw);
+
+ /* EEPROM Functions */
+-int32_t e1000_init_eeprom_params(struct e1000_hw *hw);
++s32 e1000_init_eeprom_params(struct e1000_hw *hw);
+
+ /* MNG HOST IF functions */
+-uint32_t e1000_enable_mng_pass_thru(struct e1000_hw *hw);
++u32 e1000_enable_mng_pass_thru(struct e1000_hw *hw);
+
+ #define E1000_MNG_DHCP_TX_PAYLOAD_CMD 64
+ #define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8 /* Host Interface data length */
+@@ -354,80 +354,80 @@ uint32_t e1000_enable_mng_pass_thru(struct e1000_hw *hw);
+ #define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F
+
+ struct e1000_host_mng_command_header {
+- uint8_t command_id;
+- uint8_t checksum;
+- uint16_t reserved1;
+- uint16_t reserved2;
+- uint16_t command_length;
++ u8 command_id;
++ u8 checksum;
++ u16 reserved1;
++ u16 reserved2;
++ u16 command_length;
+ };
+
+ struct e1000_host_mng_command_info {
+ struct e1000_host_mng_command_header command_header; /* Command Head/Command Result Head has 4 bytes */
+- uint8_t command_data[E1000_HI_MAX_MNG_DATA_LENGTH]; /* Command data can length 0..0x658*/
++ u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH]; /* Command data can length 0..0x658*/
+ };
+ #ifdef __BIG_ENDIAN
+ struct e1000_host_mng_dhcp_cookie{
+- uint32_t signature;
+- uint16_t vlan_id;
+- uint8_t reserved0;
+- uint8_t status;
+- uint32_t reserved1;
+- uint8_t checksum;
+- uint8_t reserved3;
+- uint16_t reserved2;
++ u32 signature;
++ u16 vlan_id;
++ u8 reserved0;
++ u8 status;
++ u32 reserved1;
++ u8 checksum;
++ u8 reserved3;
++ u16 reserved2;
+ };
+ #else
+ struct e1000_host_mng_dhcp_cookie{
+- uint32_t signature;
+- uint8_t status;
+- uint8_t reserved0;
+- uint16_t vlan_id;
+- uint32_t reserved1;
+- uint16_t reserved2;
+- uint8_t reserved3;
+- uint8_t checksum;
++ u32 signature;
++ u8 status;
++ u8 reserved0;
++ u16 vlan_id;
++ u32 reserved1;
++ u16 reserved2;
++ u8 reserved3;
++ u8 checksum;
+ };
+ #endif
+
+-int32_t e1000_mng_write_dhcp_info(struct e1000_hw *hw, uint8_t *buffer,
+- uint16_t length);
+-boolean_t e1000_check_mng_mode(struct e1000_hw *hw);
+-boolean_t e1000_enable_tx_pkt_filtering(struct e1000_hw *hw);
+-int32_t e1000_read_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data);
+-int32_t e1000_validate_eeprom_checksum(struct e1000_hw *hw);
+-int32_t e1000_update_eeprom_checksum(struct e1000_hw *hw);
+-int32_t e1000_write_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data);
+-int32_t e1000_read_mac_addr(struct e1000_hw * hw);
++s32 e1000_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer,
++ u16 length);
++bool e1000_check_mng_mode(struct e1000_hw *hw);
++bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw);
++s32 e1000_read_eeprom(struct e1000_hw *hw, u16 reg, u16 words, u16 *data);
++s32 e1000_validate_eeprom_checksum(struct e1000_hw *hw);
++s32 e1000_update_eeprom_checksum(struct e1000_hw *hw);
++s32 e1000_write_eeprom(struct e1000_hw *hw, u16 reg, u16 words, u16 *data);
++s32 e1000_read_mac_addr(struct e1000_hw * hw);
+
+ /* Filters (multicast, vlan, receive) */
+-uint32_t e1000_hash_mc_addr(struct e1000_hw *hw, uint8_t * mc_addr);
+-void e1000_mta_set(struct e1000_hw *hw, uint32_t hash_value);
+-void e1000_rar_set(struct e1000_hw *hw, uint8_t * mc_addr, uint32_t rar_index);
+-void e1000_write_vfta(struct e1000_hw *hw, uint32_t offset, uint32_t value);
++u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 * mc_addr);
++void e1000_mta_set(struct e1000_hw *hw, u32 hash_value);
++void e1000_rar_set(struct e1000_hw *hw, u8 * mc_addr, u32 rar_index);
++void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value);
+
+ /* LED functions */
+-int32_t e1000_setup_led(struct e1000_hw *hw);
+-int32_t e1000_cleanup_led(struct e1000_hw *hw);
+-int32_t e1000_led_on(struct e1000_hw *hw);
+-int32_t e1000_led_off(struct e1000_hw *hw);
+-int32_t e1000_blink_led_start(struct e1000_hw *hw);
++s32 e1000_setup_led(struct e1000_hw *hw);
++s32 e1000_cleanup_led(struct e1000_hw *hw);
++s32 e1000_led_on(struct e1000_hw *hw);
++s32 e1000_led_off(struct e1000_hw *hw);
++s32 e1000_blink_led_start(struct e1000_hw *hw);
+
+ /* Adaptive IFS Functions */
+
+ /* Everything else */
+ void e1000_reset_adaptive(struct e1000_hw *hw);
+ void e1000_update_adaptive(struct e1000_hw *hw);
+-void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats, uint32_t frame_len, uint8_t * mac_addr);
++void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats, u32 frame_len, u8 * mac_addr);
+ void e1000_get_bus_info(struct e1000_hw *hw);
+ void e1000_pci_set_mwi(struct e1000_hw *hw);
+ void e1000_pci_clear_mwi(struct e1000_hw *hw);
+-int32_t e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value);
++s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
+ void e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc);
+ int e1000_pcix_get_mmrbc(struct e1000_hw *hw);
+ /* Port I/O is only supported on 82544 and newer */
+-void e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value);
+-int32_t e1000_disable_pciex_master(struct e1000_hw *hw);
+-int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
++void e1000_io_write(struct e1000_hw *hw, unsigned long port, u32 value);
++s32 e1000_disable_pciex_master(struct e1000_hw *hw);
++s32 e1000_check_phy_reset_block(struct e1000_hw *hw);
+
+
+ #define E1000_READ_REG_IO(a, reg) \
+@@ -596,8 +596,8 @@ struct e1000_rx_desc {
+ __le64 buffer_addr; /* Address of the descriptor's data buffer */
+ __le16 length; /* Length of data DMAed into data buffer */
+ __le16 csum; /* Packet checksum */
+- uint8_t status; /* Descriptor status */
+- uint8_t errors; /* Descriptor Errors */
++ u8 status; /* Descriptor status */
++ u8 errors; /* Descriptor Errors */
+ __le16 special;
+ };
+
+@@ -718,15 +718,15 @@ struct e1000_tx_desc {
+ __le32 data;
+ struct {
+ __le16 length; /* Data buffer length */
+- uint8_t cso; /* Checksum offset */
+- uint8_t cmd; /* Descriptor control */
++ u8 cso; /* Checksum offset */
++ u8 cmd; /* Descriptor control */
+ } flags;
+ } lower;
+ union {
+ __le32 data;
+ struct {
+- uint8_t status; /* Descriptor status */
+- uint8_t css; /* Checksum start */
++ u8 status; /* Descriptor status */
++ u8 css; /* Checksum start */
+ __le16 special;
+ } fields;
+ } upper;
+@@ -759,16 +759,16 @@ struct e1000_context_desc {
+ union {
+ __le32 ip_config;
+ struct {
+- uint8_t ipcss; /* IP checksum start */
+- uint8_t ipcso; /* IP checksum offset */
++ u8 ipcss; /* IP checksum start */
++ u8 ipcso; /* IP checksum offset */
+ __le16 ipcse; /* IP checksum end */
+ } ip_fields;
+ } lower_setup;
+ union {
+ __le32 tcp_config;
+ struct {
+- uint8_t tucss; /* TCP checksum start */
+- uint8_t tucso; /* TCP checksum offset */
++ u8 tucss; /* TCP checksum start */
++ u8 tucso; /* TCP checksum offset */
+ __le16 tucse; /* TCP checksum end */
+ } tcp_fields;
+ } upper_setup;
+@@ -776,8 +776,8 @@ struct e1000_context_desc {
+ union {
+ __le32 data;
+ struct {
+- uint8_t status; /* Descriptor status */
+- uint8_t hdr_len; /* Header length */
++ u8 status; /* Descriptor status */
++ u8 hdr_len; /* Header length */
+ __le16 mss; /* Maximum segment size */
+ } fields;
+ } tcp_seg_setup;
+@@ -790,15 +790,15 @@ struct e1000_data_desc {
+ __le32 data;
+ struct {
+ __le16 length; /* Data buffer length */
+- uint8_t typ_len_ext; /* */
+- uint8_t cmd; /* */
++ u8 typ_len_ext; /* */
++ u8 cmd; /* */
+ } flags;
+ } lower;
+ union {
+ __le32 data;
+ struct {
+- uint8_t status; /* Descriptor status */
+- uint8_t popts; /* Packet Options */
++ u8 status; /* Descriptor status */
++ u8 popts; /* Packet Options */
+ __le16 special; /* */
+ } fields;
+ } upper;
+@@ -825,8 +825,8 @@ struct e1000_rar {
+
+ /* IPv4 Address Table Entry */
+ struct e1000_ipv4_at_entry {
+- volatile uint32_t ipv4_addr; /* IP Address (RW) */
+- volatile uint32_t reserved;
++ volatile u32 ipv4_addr; /* IP Address (RW) */
++ volatile u32 reserved;
+ };
+
+ /* Four wakeup IP addresses are supported */
+@@ -837,25 +837,25 @@ struct e1000_ipv4_at_entry {
+
+ /* IPv6 Address Table Entry */
+ struct e1000_ipv6_at_entry {
+- volatile uint8_t ipv6_addr[16];
++ volatile u8 ipv6_addr[16];
+ };
+
+ /* Flexible Filter Length Table Entry */
+ struct e1000_fflt_entry {
+- volatile uint32_t length; /* Flexible Filter Length (RW) */
+- volatile uint32_t reserved;
++ volatile u32 length; /* Flexible Filter Length (RW) */
++ volatile u32 reserved;
+ };
+
+ /* Flexible Filter Mask Table Entry */
+ struct e1000_ffmt_entry {
+- volatile uint32_t mask; /* Flexible Filter Mask (RW) */
+- volatile uint32_t reserved;
++ volatile u32 mask; /* Flexible Filter Mask (RW) */
++ volatile u32 reserved;
+ };
+
+ /* Flexible Filter Value Table Entry */
+ struct e1000_ffvt_entry {
+- volatile uint32_t value; /* Flexible Filter Value (RW) */
+- volatile uint32_t reserved;
++ volatile u32 value; /* Flexible Filter Value (RW) */
++ volatile u32 reserved;
+ };
+
+ /* Four Flexible Filters are supported */
+@@ -1309,89 +1309,89 @@ struct e1000_ffvt_entry {
+
+ /* Statistics counters collected by the MAC */
+ struct e1000_hw_stats {
+- uint64_t crcerrs;
+- uint64_t algnerrc;
+- uint64_t symerrs;
+- uint64_t rxerrc;
+- uint64_t txerrc;
+- uint64_t mpc;
+- uint64_t scc;
+- uint64_t ecol;
+- uint64_t mcc;
+- uint64_t latecol;
+- uint64_t colc;
+- uint64_t dc;
+- uint64_t tncrs;
+- uint64_t sec;
+- uint64_t cexterr;
+- uint64_t rlec;
+- uint64_t xonrxc;
+- uint64_t xontxc;
+- uint64_t xoffrxc;
+- uint64_t xofftxc;
+- uint64_t fcruc;
+- uint64_t prc64;
+- uint64_t prc127;
+- uint64_t prc255;
+- uint64_t prc511;
+- uint64_t prc1023;
+- uint64_t prc1522;
+- uint64_t gprc;
+- uint64_t bprc;
+- uint64_t mprc;
+- uint64_t gptc;
+- uint64_t gorcl;
+- uint64_t gorch;
+- uint64_t gotcl;
+- uint64_t gotch;
+- uint64_t rnbc;
+- uint64_t ruc;
+- uint64_t rfc;
+- uint64_t roc;
+- uint64_t rlerrc;
+- uint64_t rjc;
+- uint64_t mgprc;
+- uint64_t mgpdc;
+- uint64_t mgptc;
+- uint64_t torl;
+- uint64_t torh;
+- uint64_t totl;
+- uint64_t toth;
+- uint64_t tpr;
+- uint64_t tpt;
+- uint64_t ptc64;
+- uint64_t ptc127;
+- uint64_t ptc255;
+- uint64_t ptc511;
+- uint64_t ptc1023;
+- uint64_t ptc1522;
+- uint64_t mptc;
+- uint64_t bptc;
+- uint64_t tsctc;
+- uint64_t tsctfc;
+- uint64_t iac;
+- uint64_t icrxptc;
+- uint64_t icrxatc;
+- uint64_t ictxptc;
+- uint64_t ictxatc;
+- uint64_t ictxqec;
+- uint64_t ictxqmtc;
+- uint64_t icrxdmtc;
+- uint64_t icrxoc;
++ u64 crcerrs;
++ u64 algnerrc;
++ u64 symerrs;
++ u64 rxerrc;
++ u64 txerrc;
++ u64 mpc;
++ u64 scc;
++ u64 ecol;
++ u64 mcc;
++ u64 latecol;
++ u64 colc;
++ u64 dc;
++ u64 tncrs;
++ u64 sec;
++ u64 cexterr;
++ u64 rlec;
++ u64 xonrxc;
++ u64 xontxc;
++ u64 xoffrxc;
++ u64 xofftxc;
++ u64 fcruc;
++ u64 prc64;
++ u64 prc127;
++ u64 prc255;
++ u64 prc511;
++ u64 prc1023;
++ u64 prc1522;
++ u64 gprc;
++ u64 bprc;
++ u64 mprc;
++ u64 gptc;
++ u64 gorcl;
++ u64 gorch;
++ u64 gotcl;
++ u64 gotch;
++ u64 rnbc;
++ u64 ruc;
++ u64 rfc;
++ u64 roc;
++ u64 rlerrc;
++ u64 rjc;
++ u64 mgprc;
++ u64 mgpdc;
++ u64 mgptc;
++ u64 torl;
++ u64 torh;
++ u64 totl;
++ u64 toth;
++ u64 tpr;
++ u64 tpt;
++ u64 ptc64;
++ u64 ptc127;
++ u64 ptc255;
++ u64 ptc511;
++ u64 ptc1023;
++ u64 ptc1522;
++ u64 mptc;
++ u64 bptc;
++ u64 tsctc;
++ u64 tsctfc;
++ u64 iac;
++ u64 icrxptc;
++ u64 icrxatc;
++ u64 ictxptc;
++ u64 ictxatc;
++ u64 ictxqec;
++ u64 ictxqmtc;
++ u64 icrxdmtc;
++ u64 icrxoc;
+ };
+
+ /* Structure containing variables used by the shared code (e1000_hw.c) */
+ struct e1000_hw {
+- uint8_t __iomem *hw_addr;
+- uint8_t __iomem *flash_address;
++ u8 __iomem *hw_addr;
++ u8 __iomem *flash_address;
+ e1000_mac_type mac_type;
+ e1000_phy_type phy_type;
+- uint32_t phy_init_script;
++ u32 phy_init_script;
+ e1000_media_type media_type;
+ void *back;
+ struct e1000_shadow_ram *eeprom_shadow_ram;
+- uint32_t flash_bank_size;
+- uint32_t flash_base_addr;
++ u32 flash_bank_size;
++ u32 flash_base_addr;
+ e1000_fc_type fc;
+ e1000_bus_speed bus_speed;
+ e1000_bus_width bus_width;
+@@ -1400,75 +1400,75 @@ struct e1000_hw {
+ e1000_ms_type master_slave;
+ e1000_ms_type original_master_slave;
+ e1000_ffe_config ffe_config_state;
+- uint32_t asf_firmware_present;
+- uint32_t eeprom_semaphore_present;
+- uint32_t swfw_sync_present;
+- uint32_t swfwhw_semaphore_present;
++ u32 asf_firmware_present;
++ u32 eeprom_semaphore_present;
++ u32 swfw_sync_present;
++ u32 swfwhw_semaphore_present;
+ unsigned long io_base;
+- uint32_t phy_id;
+- uint32_t phy_revision;
+- uint32_t phy_addr;
+- uint32_t original_fc;
+- uint32_t txcw;
+- uint32_t autoneg_failed;
+- uint32_t max_frame_size;
+- uint32_t min_frame_size;
+- uint32_t mc_filter_type;
+- uint32_t num_mc_addrs;
+- uint32_t collision_delta;
+- uint32_t tx_packet_delta;
+- uint32_t ledctl_default;
+- uint32_t ledctl_mode1;
+- uint32_t ledctl_mode2;
+- boolean_t tx_pkt_filtering;
++ u32 phy_id;
++ u32 phy_revision;
++ u32 phy_addr;
++ u32 original_fc;
++ u32 txcw;
++ u32 autoneg_failed;
++ u32 max_frame_size;
++ u32 min_frame_size;
++ u32 mc_filter_type;
++ u32 num_mc_addrs;
++ u32 collision_delta;
++ u32 tx_packet_delta;
++ u32 ledctl_default;
++ u32 ledctl_mode1;
++ u32 ledctl_mode2;
++ bool tx_pkt_filtering;
+ struct e1000_host_mng_dhcp_cookie mng_cookie;
+- uint16_t phy_spd_default;
+- uint16_t autoneg_advertised;
+- uint16_t pci_cmd_word;
+- uint16_t fc_high_water;
+- uint16_t fc_low_water;
+- uint16_t fc_pause_time;
+- uint16_t current_ifs_val;
+- uint16_t ifs_min_val;
+- uint16_t ifs_max_val;
+- uint16_t ifs_step_size;
+- uint16_t ifs_ratio;
+- uint16_t device_id;
+- uint16_t vendor_id;
+- uint16_t subsystem_id;
+- uint16_t subsystem_vendor_id;
+- uint8_t revision_id;
+- uint8_t autoneg;
+- uint8_t mdix;
+- uint8_t forced_speed_duplex;
+- uint8_t wait_autoneg_complete;
+- uint8_t dma_fairness;
+- uint8_t mac_addr[NODE_ADDRESS_SIZE];
+- uint8_t perm_mac_addr[NODE_ADDRESS_SIZE];
+- boolean_t disable_polarity_correction;
+- boolean_t speed_downgraded;
++ u16 phy_spd_default;
++ u16 autoneg_advertised;
++ u16 pci_cmd_word;
++ u16 fc_high_water;
++ u16 fc_low_water;
++ u16 fc_pause_time;
++ u16 current_ifs_val;
++ u16 ifs_min_val;
++ u16 ifs_max_val;
++ u16 ifs_step_size;
++ u16 ifs_ratio;
++ u16 device_id;
++ u16 vendor_id;
++ u16 subsystem_id;
++ u16 subsystem_vendor_id;
++ u8 revision_id;
++ u8 autoneg;
++ u8 mdix;
++ u8 forced_speed_duplex;
++ u8 wait_autoneg_complete;
++ u8 dma_fairness;
++ u8 mac_addr[NODE_ADDRESS_SIZE];
++ u8 perm_mac_addr[NODE_ADDRESS_SIZE];
++ bool disable_polarity_correction;
++ bool speed_downgraded;
+ e1000_smart_speed smart_speed;
+ e1000_dsp_config dsp_config_state;
+- boolean_t get_link_status;
+- boolean_t serdes_link_down;
+- boolean_t tbi_compatibility_en;
+- boolean_t tbi_compatibility_on;
+- boolean_t laa_is_present;
+- boolean_t phy_reset_disable;
+- boolean_t initialize_hw_bits_disable;
+- boolean_t fc_send_xon;
+- boolean_t fc_strict_ieee;
+- boolean_t report_tx_early;
+- boolean_t adaptive_ifs;
+- boolean_t ifs_params_forced;
+- boolean_t in_ifs_mode;
+- boolean_t mng_reg_access_disabled;
+- boolean_t leave_av_bit_off;
+- boolean_t kmrn_lock_loss_workaround_disabled;
+- boolean_t bad_tx_carr_stats_fd;
+- boolean_t has_manc2h;
+- boolean_t rx_needs_kicking;
+- boolean_t has_smbus;
++ bool get_link_status;
++ bool serdes_link_down;
++ bool tbi_compatibility_en;
++ bool tbi_compatibility_on;
++ bool laa_is_present;
++ bool phy_reset_disable;
++ bool initialize_hw_bits_disable;
++ bool fc_send_xon;
++ bool fc_strict_ieee;
++ bool report_tx_early;
++ bool adaptive_ifs;
++ bool ifs_params_forced;
++ bool in_ifs_mode;
++ bool mng_reg_access_disabled;
++ bool leave_av_bit_off;
++ bool kmrn_lock_loss_workaround_disabled;
++ bool bad_tx_carr_stats_fd;
++ bool has_manc2h;
++ bool rx_needs_kicking;
++ bool has_smbus;
+ };
+
+
+@@ -2165,14 +2165,14 @@ typedef enum {
+ #define E1000_HI_COMMAND_TIMEOUT 500 /* Time in ms to process HI command */
+
+ struct e1000_host_command_header {
+- uint8_t command_id;
+- uint8_t command_length;
+- uint8_t command_options; /* I/F bits for command, status for return */
+- uint8_t checksum;
++ u8 command_id;
++ u8 command_length;
++ u8 command_options; /* I/F bits for command, status for return */
++ u8 checksum;
+ };
+ struct e1000_host_command_info {
+ struct e1000_host_command_header command_header; /* Command Head/Command Result Head has 4 bytes */
+- uint8_t command_data[E1000_HI_MAX_DATA_LENGTH]; /* Command data can length 0..252 */
++ u8 command_data[E1000_HI_MAX_DATA_LENGTH]; /* Command data can length 0..252 */
+ };
+
+ /* Host SMB register #0 */
+@@ -2495,7 +2495,7 @@ struct e1000_host_command_info {
+ /* Number of milliseconds we wait for PHY configuration done after MAC reset */
+ #define PHY_CFG_TIMEOUT 100
+
+-#define E1000_TX_BUFFER_SIZE ((uint32_t)1514)
++#define E1000_TX_BUFFER_SIZE ((u32)1514)
+
+ /* The carrier extension symbol, as received by the NIC. */
+ #define CARRIER_EXTENSION 0x0F
+@@ -2518,11 +2518,11 @@ struct e1000_host_command_info {
+ * Typical use:
+ * ...
+ * if (TBI_ACCEPT) {
+- * accept_frame = TRUE;
++ * accept_frame = true;
+ * e1000_tbi_adjust_stats(adapter, MacAddress);
+ * frame_length--;
+ * } else {
+- * accept_frame = FALSE;
++ * accept_frame = false;
+ * }
+ * ...
+ */
+@@ -3312,68 +3312,68 @@ struct e1000_host_command_info {
+ /* Offset 04h HSFSTS */
+ union ich8_hws_flash_status {
+ struct ich8_hsfsts {
+-#ifdef E1000_BIG_ENDIAN
+- uint16_t reserved2 :6;
+- uint16_t fldesvalid :1;
+- uint16_t flockdn :1;
+- uint16_t flcdone :1;
+- uint16_t flcerr :1;
+- uint16_t dael :1;
+- uint16_t berasesz :2;
+- uint16_t flcinprog :1;
+- uint16_t reserved1 :2;
++#ifdef __BIG_ENDIAN
++ u16 reserved2 :6;
++ u16 fldesvalid :1;
++ u16 flockdn :1;
++ u16 flcdone :1;
++ u16 flcerr :1;
++ u16 dael :1;
++ u16 berasesz :2;
++ u16 flcinprog :1;
++ u16 reserved1 :2;
+ #else
+- uint16_t flcdone :1; /* bit 0 Flash Cycle Done */
+- uint16_t flcerr :1; /* bit 1 Flash Cycle Error */
+- uint16_t dael :1; /* bit 2 Direct Access error Log */
+- uint16_t berasesz :2; /* bit 4:3 Block/Sector Erase Size */
+- uint16_t flcinprog :1; /* bit 5 flash SPI cycle in Progress */
+- uint16_t reserved1 :2; /* bit 13:6 Reserved */
+- uint16_t reserved2 :6; /* bit 13:6 Reserved */
+- uint16_t fldesvalid :1; /* bit 14 Flash Descriptor Valid */
+- uint16_t flockdn :1; /* bit 15 Flash Configuration Lock-Down */
++ u16 flcdone :1; /* bit 0 Flash Cycle Done */
++ u16 flcerr :1; /* bit 1 Flash Cycle Error */
++ u16 dael :1; /* bit 2 Direct Access error Log */
++ u16 berasesz :2; /* bit 4:3 Block/Sector Erase Size */
++ u16 flcinprog :1; /* bit 5 flash SPI cycle in Progress */
++ u16 reserved1 :2; /* bit 13:6 Reserved */
++ u16 reserved2 :6; /* bit 13:6 Reserved */
++ u16 fldesvalid :1; /* bit 14 Flash Descriptor Valid */
++ u16 flockdn :1; /* bit 15 Flash Configuration Lock-Down */
+ #endif
+ } hsf_status;
+- uint16_t regval;
++ u16 regval;
+ };
+
+ /* ICH8 GbE Flash Hardware Sequencing Flash control Register bit breakdown */
+ /* Offset 06h FLCTL */
+ union ich8_hws_flash_ctrl {
+ struct ich8_hsflctl {
+-#ifdef E1000_BIG_ENDIAN
+- uint16_t fldbcount :2;
+- uint16_t flockdn :6;
+- uint16_t flcgo :1;
+- uint16_t flcycle :2;
+- uint16_t reserved :5;
++#ifdef __BIG_ENDIAN
++ u16 fldbcount :2;
++ u16 flockdn :6;
++ u16 flcgo :1;
++ u16 flcycle :2;
++ u16 reserved :5;
+ #else
+- uint16_t flcgo :1; /* 0 Flash Cycle Go */
+- uint16_t flcycle :2; /* 2:1 Flash Cycle */
+- uint16_t reserved :5; /* 7:3 Reserved */
+- uint16_t fldbcount :2; /* 9:8 Flash Data Byte Count */
+- uint16_t flockdn :6; /* 15:10 Reserved */
++ u16 flcgo :1; /* 0 Flash Cycle Go */
++ u16 flcycle :2; /* 2:1 Flash Cycle */
++ u16 reserved :5; /* 7:3 Reserved */
++ u16 fldbcount :2; /* 9:8 Flash Data Byte Count */
++ u16 flockdn :6; /* 15:10 Reserved */
+ #endif
+ } hsf_ctrl;
+- uint16_t regval;
++ u16 regval;
+ };
+
+ /* ICH8 Flash Region Access Permissions */
+ union ich8_hws_flash_regacc {
+ struct ich8_flracc {
+-#ifdef E1000_BIG_ENDIAN
+- uint32_t gmwag :8;
+- uint32_t gmrag :8;
+- uint32_t grwa :8;
+- uint32_t grra :8;
++#ifdef __BIG_ENDIAN
++ u32 gmwag :8;
++ u32 gmrag :8;
++ u32 grwa :8;
++ u32 grra :8;
+ #else
+- uint32_t grra :8; /* 0:7 GbE region Read Access */
+- uint32_t grwa :8; /* 8:15 GbE region Write Access */
+- uint32_t gmrag :8; /* 23:16 GbE Master Read Access Grant */
+- uint32_t gmwag :8; /* 31:24 GbE Master Write Access Grant */
++ u32 grra :8; /* 0:7 GbE region Read Access */
++ u32 grwa :8; /* 8:15 GbE region Write Access */
++ u32 gmrag :8; /* 23:16 GbE Master Read Access Grant */
++ u32 gmwag :8; /* 31:24 GbE Master Write Access Grant */
+ #endif
+ } hsf_flregacc;
+- uint16_t regval;
++ u16 regval;
+ };
+
+ /* Miscellaneous PHY bit definitions. */
+diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
+index 0991648..59579b1 100644
+--- a/drivers/net/e1000/e1000_main.c
++++ b/drivers/net/e1000/e1000_main.c
+@@ -127,7 +127,7 @@ int e1000_up(struct e1000_adapter *adapter);
+ void e1000_down(struct e1000_adapter *adapter);
+ void e1000_reinit_locked(struct e1000_adapter *adapter);
+ void e1000_reset(struct e1000_adapter *adapter);
+-int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx);
++int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx);
+ int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
+ int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
+ void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
+@@ -169,21 +169,21 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
+ static int e1000_set_mac(struct net_device *netdev, void *p);
+ static irqreturn_t e1000_intr(int irq, void *data);
+ static irqreturn_t e1000_intr_msi(int irq, void *data);
+-static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter,
+- struct e1000_tx_ring *tx_ring);
++static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
++ struct e1000_tx_ring *tx_ring);
+ #ifdef CONFIG_E1000_NAPI
+ static int e1000_clean(struct napi_struct *napi, int budget);
+-static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter,
+- struct e1000_rx_ring *rx_ring,
+- int *work_done, int work_to_do);
+-static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+- struct e1000_rx_ring *rx_ring,
+- int *work_done, int work_to_do);
++static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rx_ring,
++ int *work_done, int work_to_do);
++static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rx_ring,
++ int *work_done, int work_to_do);
+ #else
+-static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter,
+- struct e1000_rx_ring *rx_ring);
+-static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+- struct e1000_rx_ring *rx_ring);
++static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rx_ring);
++static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rx_ring);
+ #endif
+ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+@@ -203,8 +203,8 @@ static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
+ struct sk_buff *skb);
+
+ static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp);
+-static void e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
+-static void e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
++static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
++static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
+ static void e1000_restore_vlan(struct e1000_adapter *adapter);
+
+ static int e1000_suspend(struct pci_dev *pdev, pm_message_t state);
+@@ -347,7 +347,6 @@ static void e1000_free_irq(struct e1000_adapter *adapter)
+ static void
+ e1000_irq_disable(struct e1000_adapter *adapter)
+ {
+- atomic_inc(&adapter->irq_sem);
+ E1000_WRITE_REG(&adapter->hw, IMC, ~0);
+ E1000_WRITE_FLUSH(&adapter->hw);
+ synchronize_irq(adapter->pdev->irq);
+@@ -361,18 +360,16 @@ e1000_irq_disable(struct e1000_adapter *adapter)
+ static void
+ e1000_irq_enable(struct e1000_adapter *adapter)
+ {
+- if (likely(atomic_dec_and_test(&adapter->irq_sem))) {
+- E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK);
+- E1000_WRITE_FLUSH(&adapter->hw);
+- }
++ E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK);
++ E1000_WRITE_FLUSH(&adapter->hw);
+ }
+
+ static void
+ e1000_update_mng_vlan(struct e1000_adapter *adapter)
+ {
+ struct net_device *netdev = adapter->netdev;
+- uint16_t vid = adapter->hw.mng_cookie.vlan_id;
+- uint16_t old_vid = adapter->mng_vlan_id;
++ u16 vid = adapter->hw.mng_cookie.vlan_id;
++ u16 old_vid = adapter->mng_vlan_id;
+ if (adapter->vlgrp) {
+ if (!vlan_group_get_device(adapter->vlgrp, vid)) {
+ if (adapter->hw.mng_cookie.status &
+@@ -382,7 +379,7 @@ e1000_update_mng_vlan(struct e1000_adapter *adapter)
+ } else
+ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
+
+- if ((old_vid != (uint16_t)E1000_MNG_VLAN_NONE) &&
++ if ((old_vid != (u16)E1000_MNG_VLAN_NONE) &&
+ (vid != old_vid) &&
+ !vlan_group_get_device(adapter->vlgrp, old_vid))
+ e1000_vlan_rx_kill_vid(netdev, old_vid);
+@@ -405,8 +402,8 @@ e1000_update_mng_vlan(struct e1000_adapter *adapter)
+ static void
+ e1000_release_hw_control(struct e1000_adapter *adapter)
+ {
+- uint32_t ctrl_ext;
+- uint32_t swsm;
++ u32 ctrl_ext;
++ u32 swsm;
+
+ /* Let firmware taken over control of h/w */
+ switch (adapter->hw.mac_type) {
+@@ -442,8 +439,8 @@ e1000_release_hw_control(struct e1000_adapter *adapter)
+ static void
+ e1000_get_hw_control(struct e1000_adapter *adapter)
+ {
+- uint32_t ctrl_ext;
+- uint32_t swsm;
++ u32 ctrl_ext;
++ u32 swsm;
+
+ /* Let firmware know the driver has taken over */
+ switch (adapter->hw.mac_type) {
+@@ -469,7 +466,7 @@ static void
+ e1000_init_manageability(struct e1000_adapter *adapter)
+ {
+ if (adapter->en_mng_pt) {
+- uint32_t manc = E1000_READ_REG(&adapter->hw, MANC);
++ u32 manc = E1000_READ_REG(&adapter->hw, MANC);
+
+ /* disable hardware interception of ARP */
+ manc &= ~(E1000_MANC_ARP_EN);
+@@ -478,7 +475,7 @@ e1000_init_manageability(struct e1000_adapter *adapter)
+ /* this will probably generate destination unreachable messages
+ * from the host OS, but the packets will be handled on SMBUS */
+ if (adapter->hw.has_manc2h) {
+- uint32_t manc2h = E1000_READ_REG(&adapter->hw, MANC2H);
++ u32 manc2h = E1000_READ_REG(&adapter->hw, MANC2H);
+
+ manc |= E1000_MANC_EN_MNG2HOST;
+ #define E1000_MNG2HOST_PORT_623 (1 << 5)
+@@ -496,7 +493,7 @@ static void
+ e1000_release_manageability(struct e1000_adapter *adapter)
+ {
+ if (adapter->en_mng_pt) {
+- uint32_t manc = E1000_READ_REG(&adapter->hw, MANC);
++ u32 manc = E1000_READ_REG(&adapter->hw, MANC);
+
+ /* re-enable hardware interception of ARP */
+ manc |= E1000_MANC_ARP_EN;
+@@ -569,7 +566,7 @@ int e1000_up(struct e1000_adapter *adapter)
+
+ void e1000_power_up_phy(struct e1000_adapter *adapter)
+ {
+- uint16_t mii_reg = 0;
++ u16 mii_reg = 0;
+
+ /* Just clear the power down bit to wake the phy back up */
+ if (adapter->hw.media_type == e1000_media_type_copper) {
+@@ -584,13 +581,13 @@ void e1000_power_up_phy(struct e1000_adapter *adapter)
+ static void e1000_power_down_phy(struct e1000_adapter *adapter)
+ {
+ /* Power down the PHY so no link is implied when interface is down *
+- * The PHY cannot be powered down if any of the following is TRUE *
++ * The PHY cannot be powered down if any of the following is true *
+ * (a) WoL is enabled
+ * (b) AMT is active
+ * (c) SoL/IDER session is active */
+ if (!adapter->wol && adapter->hw.mac_type >= e1000_82540 &&
+ adapter->hw.media_type == e1000_media_type_copper) {
+- uint16_t mii_reg = 0;
++ u16 mii_reg = 0;
+
+ switch (adapter->hw.mac_type) {
+ case e1000_82540:
+@@ -638,7 +635,6 @@ e1000_down(struct e1000_adapter *adapter)
+
+ #ifdef CONFIG_E1000_NAPI
+ napi_disable(&adapter->napi);
+- atomic_set(&adapter->irq_sem, 0);
+ #endif
+ e1000_irq_disable(adapter);
+
+@@ -671,9 +667,9 @@ e1000_reinit_locked(struct e1000_adapter *adapter)
+ void
+ e1000_reset(struct e1000_adapter *adapter)
+ {
+- uint32_t pba = 0, tx_space, min_tx_space, min_rx_space;
+- uint16_t fc_high_water_mark = E1000_FC_HIGH_DIFF;
+- boolean_t legacy_pba_adjust = FALSE;
++ u32 pba = 0, tx_space, min_tx_space, min_rx_space;
++ u16 fc_high_water_mark = E1000_FC_HIGH_DIFF;
++ bool legacy_pba_adjust = false;
+
+ /* Repartition Pba for greater than 9k mtu
+ * To take effect CTRL.RST is required.
+@@ -687,7 +683,7 @@ e1000_reset(struct e1000_adapter *adapter)
+ case e1000_82540:
+ case e1000_82541:
+ case e1000_82541_rev_2:
+- legacy_pba_adjust = TRUE;
++ legacy_pba_adjust = true;
+ pba = E1000_PBA_48K;
+ break;
+ case e1000_82545:
+@@ -698,7 +694,7 @@ e1000_reset(struct e1000_adapter *adapter)
+ break;
+ case e1000_82547:
+ case e1000_82547_rev_2:
+- legacy_pba_adjust = TRUE;
++ legacy_pba_adjust = true;
+ pba = E1000_PBA_30K;
+ break;
+ case e1000_82571:
+@@ -716,7 +712,7 @@ e1000_reset(struct e1000_adapter *adapter)
+ break;
+ }
+
+- if (legacy_pba_adjust == TRUE) {
++ if (legacy_pba_adjust) {
+ if (adapter->netdev->mtu > E1000_RXBUFFER_8192)
+ pba -= 8; /* allocate more FIFO for Tx */
+
+@@ -819,7 +815,7 @@ e1000_reset(struct e1000_adapter *adapter)
+ adapter->hw.mac_type <= e1000_82547_rev_2 &&
+ adapter->hw.autoneg == 1 &&
+ adapter->hw.autoneg_advertised == ADVERTISE_1000_FULL) {
+- uint32_t ctrl = E1000_READ_REG(&adapter->hw, CTRL);
++ u32 ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+ /* clear phy power management bit if we are in gig only mode,
+ * which if enabled will attempt negotiation to 100Mb, which
+ * can cause a loss of link at power off or driver unload */
+@@ -836,7 +832,7 @@ e1000_reset(struct e1000_adapter *adapter)
+ if (!adapter->smart_power_down &&
+ (adapter->hw.mac_type == e1000_82571 ||
+ adapter->hw.mac_type == e1000_82572)) {
+- uint16_t phy_data = 0;
++ u16 phy_data = 0;
+ /* speed up time to link by disabling smart power down, ignore
+ * the return value of this function because there is nothing
+ * different we would do if it failed */
+@@ -930,8 +926,8 @@ e1000_probe(struct pci_dev *pdev,
+ static int cards_found = 0;
+ static int global_quad_port_a = 0; /* global ksp3 port a indication */
+ int i, err, pci_using_dac;
+- uint16_t eeprom_data = 0;
+- uint16_t eeprom_apme_mask = E1000_EEPROM_APME;
++ u16 eeprom_data = 0;
++ u16 eeprom_apme_mask = E1000_EEPROM_APME;
+ DECLARE_MAC_BUF(mac);
+
+ if ((err = pci_enable_device(pdev)))
+@@ -1366,15 +1362,15 @@ e1000_sw_init(struct e1000_adapter *adapter)
+
+ e1000_set_media_type(hw);
+
+- hw->wait_autoneg_complete = FALSE;
+- hw->tbi_compatibility_en = TRUE;
+- hw->adaptive_ifs = TRUE;
++ hw->wait_autoneg_complete = false;
++ hw->tbi_compatibility_en = true;
++ hw->adaptive_ifs = true;
+
+ /* Copper options */
+
+ if (hw->media_type == e1000_media_type_copper) {
+ hw->mdix = AUTO_ALL_MODES;
+- hw->disable_polarity_correction = FALSE;
++ hw->disable_polarity_correction = false;
+ hw->master_slave = E1000_MASTER_SLAVE;
+ }
+
+@@ -1396,7 +1392,6 @@ e1000_sw_init(struct e1000_adapter *adapter)
+ #endif
+
+ /* Explicitly disable IRQ since the NIC can be in any state. */
+- atomic_set(&adapter->irq_sem, 0);
+ e1000_irq_disable(adapter);
+
+ spin_lock_init(&adapter->stats_lock);
+@@ -1576,7 +1571,7 @@ e1000_close(struct net_device *netdev)
+ * @start: address of beginning of memory
+ * @len: length of memory
+ **/
+-static boolean_t
++static bool
+ e1000_check_64k_bound(struct e1000_adapter *adapter,
+ void *start, unsigned long len)
+ {
+@@ -1587,10 +1582,10 @@ e1000_check_64k_bound(struct e1000_adapter *adapter,
+ * write location to cross 64k boundary due to errata 23 */
+ if (adapter->hw.mac_type == e1000_82545 ||
+ adapter->hw.mac_type == e1000_82546) {
+- return ((begin ^ (end - 1)) >> 16) != 0 ? FALSE : TRUE;
++ return ((begin ^ (end - 1)) >> 16) != 0 ? false : true;
+ }
+
+- return TRUE;
++ return true;
+ }
+
+ /**
+@@ -1707,10 +1702,10 @@ e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
+ static void
+ e1000_configure_tx(struct e1000_adapter *adapter)
+ {
+- uint64_t tdba;
++ u64 tdba;
+ struct e1000_hw *hw = &adapter->hw;
+- uint32_t tdlen, tctl, tipg, tarc;
+- uint32_t ipgr1, ipgr2;
++ u32 tdlen, tctl, tipg, tarc;
++ u32 ipgr1, ipgr2;
+
+ /* Setup the HW Tx Head and Tail descriptor pointers */
+
+@@ -1952,10 +1947,10 @@ e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
+ static void
+ e1000_setup_rctl(struct e1000_adapter *adapter)
+ {
+- uint32_t rctl, rfctl;
+- uint32_t psrctl = 0;
++ u32 rctl, rfctl;
++ u32 psrctl = 0;
+ #ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT
+- uint32_t pages = 0;
++ u32 pages = 0;
+ #endif
+
+ rctl = E1000_READ_REG(&adapter->hw, RCTL);
+@@ -2070,9 +2065,9 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
+ static void
+ e1000_configure_rx(struct e1000_adapter *adapter)
+ {
+- uint64_t rdba;
++ u64 rdba;
+ struct e1000_hw *hw = &adapter->hw;
+- uint32_t rdlen, rctl, rxcsum, ctrl_ext;
++ u32 rdlen, rctl, rxcsum, ctrl_ext;
+
+ if (adapter->rx_ps_pages) {
+ /* this is a 32 byte descriptor */
+@@ -2133,7 +2128,7 @@ e1000_configure_rx(struct e1000_adapter *adapter)
+ /* Enable 82543 Receive Checksum Offload for TCP and UDP */
+ if (hw->mac_type >= e1000_82543) {
+ rxcsum = E1000_READ_REG(hw, RXCSUM);
+- if (adapter->rx_csum == TRUE) {
++ if (adapter->rx_csum) {
+ rxcsum |= E1000_RXCSUM_TUOFL;
+
+ /* Enable 82571 IPv4 payload checksum for UDP fragments
+@@ -2392,7 +2387,7 @@ static void
+ e1000_enter_82542_rst(struct e1000_adapter *adapter)
+ {
+ struct net_device *netdev = adapter->netdev;
+- uint32_t rctl;
++ u32 rctl;
+
+ e1000_pci_clear_mwi(&adapter->hw);
+
+@@ -2410,7 +2405,7 @@ static void
+ e1000_leave_82542_rst(struct e1000_adapter *adapter)
+ {
+ struct net_device *netdev = adapter->netdev;
+- uint32_t rctl;
++ u32 rctl;
+
+ rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ rctl &= ~E1000_RCTL_RST;
+@@ -2495,8 +2490,8 @@ e1000_set_rx_mode(struct net_device *netdev)
+ struct e1000_hw *hw = &adapter->hw;
+ struct dev_addr_list *uc_ptr;
+ struct dev_addr_list *mc_ptr;
+- uint32_t rctl;
+- uint32_t hash_value;
++ u32 rctl;
++ u32 hash_value;
+ int i, rar_entries = E1000_RAR_ENTRIES;
+ int mta_reg_count = (hw->mac_type == e1000_ich8lan) ?
+ E1000_NUM_MTA_REGISTERS_ICH8LAN :
+@@ -2600,7 +2595,7 @@ e1000_82547_tx_fifo_stall(unsigned long data)
+ {
+ struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+ struct net_device *netdev = adapter->netdev;
+- uint32_t tctl;
++ u32 tctl;
+
+ if (atomic_read(&adapter->tx_fifo_stall)) {
+ if ((E1000_READ_REG(&adapter->hw, TDT) ==
+@@ -2642,8 +2637,8 @@ e1000_watchdog(unsigned long data)
+ struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+ struct net_device *netdev = adapter->netdev;
+ struct e1000_tx_ring *txdr = adapter->tx_ring;
+- uint32_t link, tctl;
+- int32_t ret_val;
++ u32 link, tctl;
++ s32 ret_val;
+
+ ret_val = e1000_check_for_link(&adapter->hw);
+ if ((ret_val == E1000_ERR_PHY) &&
+@@ -2668,8 +2663,8 @@ e1000_watchdog(unsigned long data)
+
+ if (link) {
+ if (!netif_carrier_ok(netdev)) {
+- uint32_t ctrl;
+- boolean_t txb2b = 1;
++ u32 ctrl;
++ bool txb2b = true;
+ e1000_get_speed_and_duplex(&adapter->hw,
+ &adapter->link_speed,
+ &adapter->link_duplex);
+@@ -2691,12 +2686,12 @@ e1000_watchdog(unsigned long data)
+ adapter->tx_timeout_factor = 1;
+ switch (adapter->link_speed) {
+ case SPEED_10:
+- txb2b = 0;
++ txb2b = false;
+ netdev->tx_queue_len = 10;
+ adapter->tx_timeout_factor = 8;
+ break;
+ case SPEED_100:
+- txb2b = 0;
++ txb2b = false;
+ netdev->tx_queue_len = 100;
+ /* maybe add some timeout factor ? */
+ break;
+@@ -2704,8 +2699,8 @@ e1000_watchdog(unsigned long data)
+
+ if ((adapter->hw.mac_type == e1000_82571 ||
+ adapter->hw.mac_type == e1000_82572) &&
+- txb2b == 0) {
+- uint32_t tarc0;
++ !txb2b) {
++ u32 tarc0;
+ tarc0 = E1000_READ_REG(&adapter->hw, TARC0);
+ tarc0 &= ~(1 << 21);
+ E1000_WRITE_REG(&adapter->hw, TARC0, tarc0);
+@@ -2747,7 +2742,7 @@ e1000_watchdog(unsigned long data)
+ /* make sure the receive unit is started */
+ if (adapter->hw.rx_needs_kicking) {
+ struct e1000_hw *hw = &adapter->hw;
+- uint32_t rctl = E1000_READ_REG(hw, RCTL);
++ u32 rctl = E1000_READ_REG(hw, RCTL);
+ E1000_WRITE_REG(hw, RCTL, rctl | E1000_RCTL_EN);
+ }
+ }
+@@ -2802,7 +2797,7 @@ e1000_watchdog(unsigned long data)
+ E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0);
+
+ /* Force detection of hung controller every watchdog period */
+- adapter->detect_tx_hung = TRUE;
++ adapter->detect_tx_hung = true;
+
+ /* With 82571 controllers, LAA may be overwritten due to controller
+ * reset from the other port. Set the appropriate LAA in RAR[0] */
+@@ -2837,7 +2832,7 @@ enum latency_range {
+ * @bytes: the number of bytes during this measurement interval
+ **/
+ static unsigned int e1000_update_itr(struct e1000_adapter *adapter,
+- uint16_t itr_setting,
++ u16 itr_setting,
+ int packets,
+ int bytes)
+ {
+@@ -2889,8 +2884,8 @@ update_itr_done:
+ static void e1000_set_itr(struct e1000_adapter *adapter)
+ {
+ struct e1000_hw *hw = &adapter->hw;
+- uint16_t current_itr;
+- uint32_t new_itr = adapter->itr;
++ u16 current_itr;
++ u32 new_itr = adapter->itr;
+
+ if (unlikely(hw->mac_type < e1000_82540))
+ return;
+@@ -2964,9 +2959,9 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+ struct e1000_context_desc *context_desc;
+ struct e1000_buffer *buffer_info;
+ unsigned int i;
+- uint32_t cmd_length = 0;
+- uint16_t ipcse = 0, tucse, mss;
+- uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
++ u32 cmd_length = 0;
++ u16 ipcse = 0, tucse, mss;
++ u8 ipcss, ipcso, tucss, tucso, hdr_len;
+ int err;
+
+ if (skb_is_gso(skb)) {
+@@ -3025,19 +3020,19 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+ if (++i == tx_ring->count) i = 0;
+ tx_ring->next_to_use = i;
+
+- return TRUE;
++ return true;
+ }
+- return FALSE;
++ return false;
+ }
+
+-static boolean_t
++static bool
+ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+ struct sk_buff *skb)
+ {
+ struct e1000_context_desc *context_desc;
+ struct e1000_buffer *buffer_info;
+ unsigned int i;
+- uint8_t css;
++ u8 css;
+
+ if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+ css = skb_transport_offset(skb);
+@@ -3060,10 +3055,10 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+ if (unlikely(++i == tx_ring->count)) i = 0;
+ tx_ring->next_to_use = i;
+
+- return TRUE;
++ return true;
+ }
+
+- return FALSE;
++ return false;
+ }
+
+ #define E1000_MAX_TXD_PWR 12
+@@ -3182,7 +3177,7 @@ e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+ {
+ struct e1000_tx_desc *tx_desc = NULL;
+ struct e1000_buffer *buffer_info;
+- uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
++ u32 txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
+ unsigned int i;
+
+ if (likely(tx_flags & E1000_TX_FLAGS_TSO)) {
+@@ -3246,8 +3241,8 @@ e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
+ static int
+ e1000_82547_fifo_workaround(struct e1000_adapter *adapter, struct sk_buff *skb)
+ {
+- uint32_t fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head;
+- uint32_t skb_fifo_len = skb->len + E1000_FIFO_HDR;
++ u32 fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head;
++ u32 skb_fifo_len = skb->len + E1000_FIFO_HDR;
+
+ skb_fifo_len = ALIGN(skb_fifo_len, E1000_FIFO_HDR);
+
+@@ -3274,7 +3269,7 @@ static int
+ e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb)
+ {
+ struct e1000_hw *hw = &adapter->hw;
+- uint16_t length, offset;
++ u16 length, offset;
+ if (vlan_tx_tag_present(skb)) {
+ if (!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) &&
+ ( adapter->hw.mng_cookie.status &
+@@ -3285,17 +3280,17 @@ e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb)
+ struct ethhdr *eth = (struct ethhdr *) skb->data;
+ if ((htons(ETH_P_IP) == eth->h_proto)) {
+ const struct iphdr *ip =
+- (struct iphdr *)((uint8_t *)skb->data+14);
++ (struct iphdr *)((u8 *)skb->data+14);
+ if (IPPROTO_UDP == ip->protocol) {
+ struct udphdr *udp =
+- (struct udphdr *)((uint8_t *)ip +
++ (struct udphdr *)((u8 *)ip +
+ (ip->ihl << 2));
+ if (ntohs(udp->dest) == 67) {
+- offset = (uint8_t *)udp + 8 - skb->data;
++ offset = (u8 *)udp + 8 - skb->data;
+ length = skb->len - offset;
+
+ return e1000_mng_write_dhcp_info(hw,
+- (uint8_t *)udp + 8,
++ (u8 *)udp + 8,
+ length);
+ }
+ }
+@@ -3375,7 +3370,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ * overrun the FIFO, adjust the max buffer len if mss
+ * drops. */
+ if (mss) {
+- uint8_t hdr_len;
++ u8 hdr_len;
+ max_per_txd = min(mss << 2, max_per_txd);
+ max_txd_pwr = fls(max_per_txd) - 1;
+
+@@ -3562,7 +3557,7 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
+- uint16_t eeprom_data = 0;
++ u16 eeprom_data = 0;
+
+ if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
+ (max_frame > MAX_JUMBO_FRAME_SIZE)) {
+@@ -3657,7 +3652,7 @@ e1000_update_stats(struct e1000_adapter *adapter)
+ struct e1000_hw *hw = &adapter->hw;
+ struct pci_dev *pdev = adapter->pdev;
+ unsigned long flags;
+- uint16_t phy_tmp;
++ u16 phy_tmp;
+
+ #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
+
+@@ -3834,13 +3829,10 @@ e1000_intr_msi(int irq, void *data)
+ #ifndef CONFIG_E1000_NAPI
+ int i;
+ #endif
+- uint32_t icr = E1000_READ_REG(hw, ICR);
++ u32 icr = E1000_READ_REG(hw, ICR);
++
++ /* in NAPI mode read ICR disables interrupts using IAM */
+
+-#ifdef CONFIG_E1000_NAPI
+- /* read ICR disables interrupts using IAM, so keep up with our
+- * enable/disable accounting */
+- atomic_inc(&adapter->irq_sem);
+-#endif
+ if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
+ hw->get_link_status = 1;
+ /* 80003ES2LAN workaround-- For packet buffer work-around on
+@@ -3849,7 +3841,7 @@ e1000_intr_msi(int irq, void *data)
+ if (netif_carrier_ok(netdev) &&
+ (adapter->hw.mac_type == e1000_80003es2lan)) {
+ /* disable receives */
+- uint32_t rctl = E1000_READ_REG(hw, RCTL);
++ u32 rctl = E1000_READ_REG(hw, RCTL);
+ E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN);
+ }
+ /* guard against interrupt when we're going down */
+@@ -3896,7 +3888,7 @@ e1000_intr(int irq, void *data)
+ struct net_device *netdev = data;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
+- uint32_t rctl, icr = E1000_READ_REG(hw, ICR);
++ u32 rctl, icr = E1000_READ_REG(hw, ICR);
+ #ifndef CONFIG_E1000_NAPI
+ int i;
+ #endif
+@@ -3910,12 +3902,8 @@ e1000_intr(int irq, void *data)
+ !(icr & E1000_ICR_INT_ASSERTED)))
+ return IRQ_NONE;
+
+- /* Interrupt Auto-Mask...upon reading ICR,
+- * interrupts are masked. No need for the
+- * IMC write, but it does mean we should
+- * account for it ASAP. */
+- if (likely(hw->mac_type >= e1000_82571))
+- atomic_inc(&adapter->irq_sem);
++ /* Interrupt Auto-Mask...upon reading ICR, interrupts are masked. No
++ * need for the IMC write */
+ #endif
+
+ if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
+@@ -3939,7 +3927,6 @@ e1000_intr(int irq, void *data)
+ #ifdef CONFIG_E1000_NAPI
+ if (unlikely(hw->mac_type < e1000_82571)) {
+ /* disable interrupts, without the synchronize_irq bit */
+- atomic_inc(&adapter->irq_sem);
+ E1000_WRITE_REG(hw, IMC, ~0);
+ E1000_WRITE_FLUSH(hw);
+ }
+@@ -3964,10 +3951,8 @@ e1000_intr(int irq, void *data)
+ * in dead lock. Writing IMC forces 82547 into
+ * de-assertion state.
+ */
+- if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2) {
+- atomic_inc(&adapter->irq_sem);
++ if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
+ E1000_WRITE_REG(hw, IMC, ~0);
+- }
+
+ adapter->total_tx_bytes = 0;
+ adapter->total_rx_bytes = 0;
+@@ -4038,7 +4023,7 @@ e1000_clean(struct napi_struct *napi, int budget)
+ * @adapter: board private structure
+ **/
+
+-static boolean_t
++static bool
+ e1000_clean_tx_irq(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring)
+ {
+@@ -4049,7 +4034,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
+ #ifdef CONFIG_E1000_NAPI
+ unsigned int count = 0;
+ #endif
+- boolean_t cleaned = FALSE;
++ bool cleaned = false;
+ unsigned int total_tx_bytes=0, total_tx_packets=0;
+
+ i = tx_ring->next_to_clean;
+@@ -4057,7 +4042,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
+ eop_desc = E1000_TX_DESC(*tx_ring, eop);
+
+ while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
+- for (cleaned = FALSE; !cleaned; ) {
++ for (cleaned = false; !cleaned; ) {
+ tx_desc = E1000_TX_DESC(*tx_ring, i);
+ buffer_info = &tx_ring->buffer_info[i];
+ cleaned = (i == eop);
+@@ -4105,7 +4090,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
+ if (adapter->detect_tx_hung) {
+ /* Detect a transmit hang in hardware, this serializes the
+ * check with the clearing of time_stamp and movement of i */
+- adapter->detect_tx_hung = FALSE;
++ adapter->detect_tx_hung = false;
+ if (tx_ring->buffer_info[eop].dma &&
+ time_after(jiffies, tx_ring->buffer_info[eop].time_stamp +
+ (adapter->tx_timeout_factor * HZ))
+@@ -4154,11 +4139,11 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
+
+ static void
+ e1000_rx_checksum(struct e1000_adapter *adapter,
+- uint32_t status_err, uint32_t csum,
++ u32 status_err, u32 csum,
+ struct sk_buff *skb)
+ {
+- uint16_t status = (uint16_t)status_err;
+- uint8_t errors = (uint8_t)(status_err >> 24);
++ u16 status = (u16)status_err;
++ u8 errors = (u8)(status_err >> 24);
+ skb->ip_summed = CHECKSUM_NONE;
+
+ /* 82543 or newer only */
+@@ -4200,7 +4185,7 @@ e1000_rx_checksum(struct e1000_adapter *adapter,
+ * @adapter: board private structure
+ **/
+
+-static boolean_t
++static bool
+ #ifdef CONFIG_E1000_NAPI
+ e1000_clean_rx_irq(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+@@ -4215,11 +4200,11 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
+ struct e1000_rx_desc *rx_desc, *next_rxd;
+ struct e1000_buffer *buffer_info, *next_buffer;
+ unsigned long flags;
+- uint32_t length;
+- uint8_t last_byte;
++ u32 length;
++ u8 last_byte;
+ unsigned int i;
+ int cleaned_count = 0;
+- boolean_t cleaned = FALSE;
++ bool cleaned = false;
+ unsigned int total_rx_bytes=0, total_rx_packets=0;
+
+ i = rx_ring->next_to_clean;
+@@ -4247,7 +4232,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
+
+ next_buffer = &rx_ring->buffer_info[i];
+
+- cleaned = TRUE;
++ cleaned = true;
+ cleaned_count++;
+ pci_unmap_single(pdev,
+ buffer_info->dma,
+@@ -4316,8 +4301,8 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
+
+ /* Receive Checksum Offload */
+ e1000_rx_checksum(adapter,
+- (uint32_t)(status) |
+- ((uint32_t)(rx_desc->errors) << 24),
++ (u32)(status) |
++ ((u32)(rx_desc->errors) << 24),
+ le16_to_cpu(rx_desc->csum), skb);
+
+ skb->protocol = eth_type_trans(skb, netdev);
+@@ -4373,7 +4358,7 @@ next_desc:
+ * @adapter: board private structure
+ **/
+
+-static boolean_t
++static bool
+ #ifdef CONFIG_E1000_NAPI
+ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+@@ -4391,9 +4376,9 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+ struct e1000_ps_page_dma *ps_page_dma;
+ struct sk_buff *skb;
+ unsigned int i, j;
+- uint32_t length, staterr;
++ u32 length, staterr;
+ int cleaned_count = 0;
+- boolean_t cleaned = FALSE;
++ bool cleaned = false;
+ unsigned int total_rx_bytes=0, total_rx_packets=0;
+
+ i = rx_ring->next_to_clean;
+@@ -4420,7 +4405,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+
+ next_buffer = &rx_ring->buffer_info[i];
+
+- cleaned = TRUE;
++ cleaned = true;
+ cleaned_count++;
+ pci_unmap_single(pdev, buffer_info->dma,
+ buffer_info->length,
+@@ -4774,8 +4759,8 @@ no_buffers:
+ static void
+ e1000_smartspeed(struct e1000_adapter *adapter)
+ {
+- uint16_t phy_status;
+- uint16_t phy_ctrl;
++ u16 phy_status;
++ u16 phy_ctrl;
+
+ if ((adapter->hw.phy_type != e1000_phy_igp) || !adapter->hw.autoneg ||
+ !(adapter->hw.autoneg_advertised & ADVERTISE_1000_FULL))
+@@ -4854,8 +4839,8 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct mii_ioctl_data *data = if_mii(ifr);
+ int retval;
+- uint16_t mii_reg;
+- uint16_t spddplx;
++ u16 mii_reg;
++ u16 spddplx;
+ unsigned long flags;
+
+ if (adapter->hw.media_type != e1000_media_type_copper)
+@@ -4974,11 +4959,11 @@ e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc)
+ pcix_set_mmrbc(adapter->pdev, mmrbc);
+ }
+
+-int32_t
+-e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
++s32
++e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
+ {
+ struct e1000_adapter *adapter = hw->back;
+- uint16_t cap_offset;
++ u16 cap_offset;
+
+ cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
+ if (!cap_offset)
+@@ -4990,7 +4975,7 @@ e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
+ }
+
+ void
+-e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value)
++e1000_io_write(struct e1000_hw *hw, unsigned long port, u32 value)
+ {
+ outl(value, port);
+ }
+@@ -4999,9 +4984,10 @@ static void
+ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+- uint32_t ctrl, rctl;
++ u32 ctrl, rctl;
+
+- e1000_irq_disable(adapter);
++ if (!test_bit(__E1000_DOWN, &adapter->flags))
++ e1000_irq_disable(adapter);
+ adapter->vlgrp = grp;
+
+ if (grp) {
+@@ -5030,7 +5016,7 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+ rctl &= ~E1000_RCTL_VFE;
+ E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ if (adapter->mng_vlan_id !=
+- (uint16_t)E1000_MNG_VLAN_NONE) {
++ (u16)E1000_MNG_VLAN_NONE) {
+ e1000_vlan_rx_kill_vid(netdev,
+ adapter->mng_vlan_id);
+ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
+@@ -5038,14 +5024,15 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+ }
+ }
+
+- e1000_irq_enable(adapter);
++ if (!test_bit(__E1000_DOWN, &adapter->flags))
++ e1000_irq_enable(adapter);
+ }
+
+ static void
+-e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
++e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+- uint32_t vfta, index;
++ u32 vfta, index;
+
+ if ((adapter->hw.mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
+@@ -5059,14 +5046,16 @@ e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
+ }
+
+ static void
+-e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
++e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+- uint32_t vfta, index;
++ u32 vfta, index;
+
+- e1000_irq_disable(adapter);
++ if (!test_bit(__E1000_DOWN, &adapter->flags))
++ e1000_irq_disable(adapter);
+ vlan_group_set_device(adapter->vlgrp, vid, NULL);
+- e1000_irq_enable(adapter);
++ if (!test_bit(__E1000_DOWN, &adapter->flags))
++ e1000_irq_enable(adapter);
+
+ if ((adapter->hw.mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
+@@ -5089,7 +5078,7 @@ e1000_restore_vlan(struct e1000_adapter *adapter)
+ e1000_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+
+ if (adapter->vlgrp) {
+- uint16_t vid;
++ u16 vid;
+ for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+ if (!vlan_group_get_device(adapter->vlgrp, vid))
+ continue;
+@@ -5099,7 +5088,7 @@ e1000_restore_vlan(struct e1000_adapter *adapter)
+ }
+
+ int
+-e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx)
++e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
+ {
+ adapter->hw.autoneg = 0;
+
+@@ -5140,8 +5129,8 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
+ {
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+- uint32_t ctrl, ctrl_ext, rctl, status;
+- uint32_t wufc = adapter->wol;
++ u32 ctrl, ctrl_ext, rctl, status;
++ u32 wufc = adapter->wol;
+ #ifdef CONFIG_PM
+ int retval = 0;
+ #endif
+@@ -5238,7 +5227,7 @@ e1000_resume(struct pci_dev *pdev)
+ {
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+- uint32_t err;
++ u32 err;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h
+index 10af742..365626d 100644
+--- a/drivers/net/e1000/e1000_osdep.h
++++ b/drivers/net/e1000/e1000_osdep.h
+@@ -41,13 +41,6 @@
+ #include <linux/interrupt.h>
+ #include <linux/sched.h>
+
+-typedef enum {
+-#undef FALSE
+- FALSE = 0,
+-#undef TRUE
+- TRUE = 1
+-} boolean_t;
+-
+ #ifdef DBG
+ #define DEBUGOUT(S) printk(KERN_DEBUG S "\n")
+ #define DEBUGOUT1(S, A...) printk(KERN_DEBUG S "\n", A)
+diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c
+index 7fe2031..462351c 100644
+--- a/drivers/net/e1000e/82571.c
++++ b/drivers/net/e1000e/82571.c
+@@ -1,7 +1,7 @@
+ /*******************************************************************************
+
+ Intel PRO/1000 Linux driver
+- Copyright(c) 1999 - 2007 Intel Corporation.
++ Copyright(c) 1999 - 2008 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+@@ -29,6 +29,9 @@
+ /*
+ * 82571EB Gigabit Ethernet Controller
+ * 82571EB Gigabit Ethernet Controller (Fiber)
++ * 82571EB Dual Port Gigabit Mezzanine Adapter
++ * 82571EB Quad Port Gigabit Mezzanine Adapter
++ * 82571PT Gigabit PT Quad Port Server ExpressModule
+ * 82572EI Gigabit Ethernet Controller (Copper)
+ * 82572EI Gigabit Ethernet Controller (Fiber)
+ * 82572EI Gigabit Ethernet Controller
+@@ -72,7 +75,7 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw)
+ struct e1000_phy_info *phy = &hw->phy;
+ s32 ret_val;
+
+- if (hw->media_type != e1000_media_type_copper) {
++ if (hw->phy.media_type != e1000_media_type_copper) {
+ phy->type = e1000_phy_none;
+ return 0;
+ }
+@@ -150,7 +153,8 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)
+ if (((eecd >> 15) & 0x3) == 0x3) {
+ nvm->type = e1000_nvm_flash_hw;
+ nvm->word_size = 2048;
+- /* Autonomous Flash update bit must be cleared due
++ /*
++ * Autonomous Flash update bit must be cleared due
+ * to Flash update issue.
+ */
+ eecd &= ~E1000_EECD_AUPDEN;
+@@ -159,13 +163,18 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)
+ }
+ /* Fall Through */
+ default:
+- nvm->type = e1000_nvm_eeprom_spi;
++ nvm->type = e1000_nvm_eeprom_spi;
+ size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
+ E1000_EECD_SIZE_EX_SHIFT);
+- /* Added to a constant, "size" becomes the left-shift value
++ /*
++ * Added to a constant, "size" becomes the left-shift value
+ * for setting word_size.
+ */
+ size += NVM_WORD_SIZE_BASE_SHIFT;
++
++ /* EEPROM access above 16k is unsupported */
++ if (size > 14)
++ size = 14;
+ nvm->word_size = 1 << size;
+ break;
+ }
+@@ -190,16 +199,16 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
+ case E1000_DEV_ID_82571EB_FIBER:
+ case E1000_DEV_ID_82572EI_FIBER:
+ case E1000_DEV_ID_82571EB_QUAD_FIBER:
+- hw->media_type = e1000_media_type_fiber;
++ hw->phy.media_type = e1000_media_type_fiber;
+ break;
+ case E1000_DEV_ID_82571EB_SERDES:
+ case E1000_DEV_ID_82572EI_SERDES:
+ case E1000_DEV_ID_82571EB_SERDES_DUAL:
+ case E1000_DEV_ID_82571EB_SERDES_QUAD:
+- hw->media_type = e1000_media_type_internal_serdes;
++ hw->phy.media_type = e1000_media_type_internal_serdes;
+ break;
+ default:
+- hw->media_type = e1000_media_type_copper;
++ hw->phy.media_type = e1000_media_type_copper;
+ break;
+ }
+
+@@ -208,25 +217,28 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
+ /* Set rar entry count */
+ mac->rar_entry_count = E1000_RAR_ENTRIES;
+ /* Set if manageability features are enabled. */
+- mac->arc_subsystem_valid =
+- (er32(FWSM) & E1000_FWSM_MODE_MASK) ? 1 : 0;
++ mac->arc_subsystem_valid = (er32(FWSM) & E1000_FWSM_MODE_MASK) ? 1 : 0;
+
+ /* check for link */
+- switch (hw->media_type) {
++ switch (hw->phy.media_type) {
+ case e1000_media_type_copper:
+ func->setup_physical_interface = e1000_setup_copper_link_82571;
+ func->check_for_link = e1000e_check_for_copper_link;
+ func->get_link_up_info = e1000e_get_speed_and_duplex_copper;
+ break;
+ case e1000_media_type_fiber:
+- func->setup_physical_interface = e1000_setup_fiber_serdes_link_82571;
++ func->setup_physical_interface =
++ e1000_setup_fiber_serdes_link_82571;
+ func->check_for_link = e1000e_check_for_fiber_link;
+- func->get_link_up_info = e1000e_get_speed_and_duplex_fiber_serdes;
++ func->get_link_up_info =
++ e1000e_get_speed_and_duplex_fiber_serdes;
+ break;
+ case e1000_media_type_internal_serdes:
+- func->setup_physical_interface = e1000_setup_fiber_serdes_link_82571;
++ func->setup_physical_interface =
++ e1000_setup_fiber_serdes_link_82571;
+ func->check_for_link = e1000e_check_for_serdes_link;
+- func->get_link_up_info = e1000e_get_speed_and_duplex_fiber_serdes;
++ func->get_link_up_info =
++ e1000e_get_speed_and_duplex_fiber_serdes;
+ break;
+ default:
+ return -E1000_ERR_CONFIG;
+@@ -236,7 +248,7 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
+ return 0;
+ }
+
+-static s32 e1000_get_invariants_82571(struct e1000_adapter *adapter)
++static s32 e1000_get_variants_82571(struct e1000_adapter *adapter)
+ {
+ struct e1000_hw *hw = &adapter->hw;
+ static int global_quad_port_a; /* global port a indication */
+@@ -322,10 +334,12 @@ static s32 e1000_get_phy_id_82571(struct e1000_hw *hw)
+ switch (hw->mac.type) {
+ case e1000_82571:
+ case e1000_82572:
+- /* The 82571 firmware may still be configuring the PHY.
++ /*
++ * The 82571 firmware may still be configuring the PHY.
+ * In this case, we cannot access the PHY until the
+ * configuration is done. So we explicitly set the
+- * PHY ID. */
++ * PHY ID.
++ */
+ phy->id = IGP01E1000_I_PHY_ID;
+ break;
+ case e1000_82573:
+@@ -479,8 +493,10 @@ static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw)
+ if (ret_val)
+ return ret_val;
+
+- /* If our nvm is an EEPROM, then we're done
+- * otherwise, commit the checksum to the flash NVM. */
++ /*
++ * If our nvm is an EEPROM, then we're done
++ * otherwise, commit the checksum to the flash NVM.
++ */
+ if (hw->nvm.type != e1000_nvm_flash_hw)
+ return ret_val;
+
+@@ -496,7 +512,8 @@ static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw)
+
+ /* Reset the firmware if using STM opcode. */
+ if ((er32(FLOP) & 0xFF00) == E1000_STM_OPCODE) {
+- /* The enabling of and the actual reset must be done
++ /*
++ * The enabling of and the actual reset must be done
+ * in two write cycles.
+ */
+ ew32(HICR, E1000_HICR_FW_RESET_ENABLE);
+@@ -557,8 +574,10 @@ static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset,
+ u32 eewr = 0;
+ s32 ret_val = 0;
+
+- /* A check for invalid values: offset too large, too many words,
+- * and not enough words. */
++ /*
++ * A check for invalid values: offset too large, too many words,
++ * and not enough words.
++ */
+ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
+ (words == 0)) {
+ hw_dbg(hw, "nvm parameter(s) out of bounds\n");
+@@ -645,30 +664,32 @@ static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active)
+ } else {
+ data &= ~IGP02E1000_PM_D0_LPLU;
+ ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data);
+- /* LPLU and SmartSpeed are mutually exclusive. LPLU is used
++ /*
++ * LPLU and SmartSpeed are mutually exclusive. LPLU is used
+ * during Dx states where the power conservation is most
+ * important. During driver activity we should enable
+- * SmartSpeed, so performance is maintained. */
++ * SmartSpeed, so performance is maintained.
++ */
+ if (phy->smart_speed == e1000_smart_speed_on) {
+ ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+- &data);
++ &data);
+ if (ret_val)
+ return ret_val;
+
+ data |= IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+- data);
++ data);
+ if (ret_val)
+ return ret_val;
+ } else if (phy->smart_speed == e1000_smart_speed_off) {
+ ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+- &data);
++ &data);
+ if (ret_val)
+ return ret_val;
+
+ data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+- data);
++ data);
+ if (ret_val)
+ return ret_val;
+ }
+@@ -693,7 +714,8 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
+ s32 ret_val;
+ u16 i = 0;
+
+- /* Prevent the PCI-E bus from sticking if there is no TLP connection
++ /*
++ * Prevent the PCI-E bus from sticking if there is no TLP connection
+ * on the last TLP read/write transaction when MAC is reset.
+ */
+ ret_val = e1000e_disable_pcie_master(hw);
+@@ -709,8 +731,10 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
+
+ msleep(10);
+
+- /* Must acquire the MDIO ownership before MAC reset.
+- * Ownership defaults to firmware after a reset. */
++ /*
++ * Must acquire the MDIO ownership before MAC reset.
++ * Ownership defaults to firmware after a reset.
++ */
+ if (hw->mac.type == e1000_82573) {
+ extcnf_ctrl = er32(EXTCNF_CTRL);
+ extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
+@@ -747,7 +771,8 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
+ /* We don't want to continue accessing MAC registers. */
+ return ret_val;
+
+- /* Phy configuration from NVM just starts after EECD_AUTO_RD is set.
++ /*
++ * Phy configuration from NVM just starts after EECD_AUTO_RD is set.
+ * Need to wait for Phy configuration completion before accessing
+ * NVM and Phy.
+ */
+@@ -793,7 +818,8 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
+ e1000e_clear_vfta(hw);
+
+ /* Setup the receive address. */
+- /* If, however, a locally administered address was assigned to the
++ /*
++ * If, however, a locally administered address was assigned to the
+ * 82571, we must reserve a RAR for it to work around an issue where
+ * resetting one port will reload the MAC on the other port.
+ */
+@@ -810,19 +836,19 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
+ ret_val = e1000_setup_link_82571(hw);
+
+ /* Set the transmit descriptor write-back policy */
+- reg_data = er32(TXDCTL);
++ reg_data = er32(TXDCTL(0));
+ reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
+ E1000_TXDCTL_FULL_TX_DESC_WB |
+ E1000_TXDCTL_COUNT_DESC;
+- ew32(TXDCTL, reg_data);
++ ew32(TXDCTL(0), reg_data);
+
+ /* ...for both queues. */
+ if (mac->type != e1000_82573) {
+- reg_data = er32(TXDCTL1);
++ reg_data = er32(TXDCTL(1));
+ reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
+ E1000_TXDCTL_FULL_TX_DESC_WB |
+ E1000_TXDCTL_COUNT_DESC;
+- ew32(TXDCTL1, reg_data);
++ ew32(TXDCTL(1), reg_data);
+ } else {
+ e1000e_enable_tx_pkt_filtering(hw);
+ reg_data = er32(GCR);
+@@ -830,7 +856,8 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
+ ew32(GCR, reg_data);
+ }
+
+- /* Clear all of the statistics registers (clear on read). It is
++ /*
++ * Clear all of the statistics registers (clear on read). It is
+ * important that we do this after we have tried to establish link
+ * because the symbol error count will increment wildly if there
+ * is no link.
+@@ -851,17 +878,17 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
+ u32 reg;
+
+ /* Transmit Descriptor Control 0 */
+- reg = er32(TXDCTL);
++ reg = er32(TXDCTL(0));
+ reg |= (1 << 22);
+- ew32(TXDCTL, reg);
++ ew32(TXDCTL(0), reg);
+
+ /* Transmit Descriptor Control 1 */
+- reg = er32(TXDCTL1);
++ reg = er32(TXDCTL(1));
+ reg |= (1 << 22);
+- ew32(TXDCTL1, reg);
++ ew32(TXDCTL(1), reg);
+
+ /* Transmit Arbitration Control 0 */
+- reg = er32(TARC0);
++ reg = er32(TARC(0));
+ reg &= ~(0xF << 27); /* 30:27 */
+ switch (hw->mac.type) {
+ case e1000_82571:
+@@ -871,10 +898,10 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
+ default:
+ break;
+ }
+- ew32(TARC0, reg);
++ ew32(TARC(0), reg);
+
+ /* Transmit Arbitration Control 1 */
+- reg = er32(TARC1);
++ reg = er32(TARC(1));
+ switch (hw->mac.type) {
+ case e1000_82571:
+ case e1000_82572:
+@@ -884,7 +911,7 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
+ reg &= ~(1 << 28);
+ else
+ reg |= (1 << 28);
+- ew32(TARC1, reg);
++ ew32(TARC(1), reg);
+ break;
+ default:
+ break;
+@@ -922,7 +949,8 @@ void e1000e_clear_vfta(struct e1000_hw *hw)
+
+ if (hw->mac.type == e1000_82573) {
+ if (hw->mng_cookie.vlan_id != 0) {
+- /* The VFTA is a 4096b bit-field, each identifying
++ /*
++ * The VFTA is a 4096b bit-field, each identifying
+ * a single VLAN ID. The following operations
+ * determine which 32b entry (i.e. offset) into the
+ * array we want to set the VLAN ID (i.e. bit) of
+@@ -936,7 +964,8 @@ void e1000e_clear_vfta(struct e1000_hw *hw)
+ }
+ }
+ for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
+- /* If the offset we want to clear is the same offset of the
++ /*
++ * If the offset we want to clear is the same offset of the
+ * manageability VLAN ID, then clear all bits except that of
+ * the manageability unit.
+ */
+@@ -947,7 +976,7 @@ void e1000e_clear_vfta(struct e1000_hw *hw)
+ }
+
+ /**
+- * e1000_mc_addr_list_update_82571 - Update Multicast addresses
++ * e1000_update_mc_addr_list_82571 - Update Multicast addresses
+ * @hw: pointer to the HW structure
+ * @mc_addr_list: array of multicast addresses to program
+ * @mc_addr_count: number of multicast addresses to program
+@@ -959,7 +988,7 @@ void e1000e_clear_vfta(struct e1000_hw *hw)
+ * The parameter rar_count will usually be hw->mac.rar_entry_count
+ * unless there are workarounds that change this.
+ **/
+-static void e1000_mc_addr_list_update_82571(struct e1000_hw *hw,
++static void e1000_update_mc_addr_list_82571(struct e1000_hw *hw,
+ u8 *mc_addr_list,
+ u32 mc_addr_count,
+ u32 rar_used_count,
+@@ -968,8 +997,8 @@ static void e1000_mc_addr_list_update_82571(struct e1000_hw *hw,
+ if (e1000e_get_laa_state_82571(hw))
+ rar_count--;
+
+- e1000e_mc_addr_list_update_generic(hw, mc_addr_list, mc_addr_count,
+- rar_used_count, rar_count);
++ e1000e_update_mc_addr_list_generic(hw, mc_addr_list, mc_addr_count,
++ rar_used_count, rar_count);
+ }
+
+ /**
+@@ -984,12 +1013,13 @@ static void e1000_mc_addr_list_update_82571(struct e1000_hw *hw,
+ **/
+ static s32 e1000_setup_link_82571(struct e1000_hw *hw)
+ {
+- /* 82573 does not have a word in the NVM to determine
++ /*
++ * 82573 does not have a word in the NVM to determine
+ * the default flow control setting, so we explicitly
+ * set it to full.
+ */
+ if (hw->mac.type == e1000_82573)
+- hw->mac.fc = e1000_fc_full;
++ hw->fc.type = e1000_fc_full;
+
+ return e1000e_setup_link(hw);
+ }
+@@ -1050,14 +1080,14 @@ static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw)
+ switch (hw->mac.type) {
+ case e1000_82571:
+ case e1000_82572:
+- /* If SerDes loopback mode is entered, there is no form
++ /*
++ * If SerDes loopback mode is entered, there is no form
+ * of reset to take the adapter out of that mode. So we
+ * have to explicitly take the adapter out of loopback
+ * mode. This prevents drivers from twiddling their thumbs
+ * if another tool failed to take it out of loopback mode.
+ */
+- ew32(SCTL,
+- E1000_SCTL_DISABLE_SERDES_LOOPBACK);
++ ew32(SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK);
+ break;
+ default:
+ break;
+@@ -1124,7 +1154,8 @@ void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state)
+
+ /* If workaround is activated... */
+ if (state)
+- /* Hold a copy of the LAA in RAR[14] This is done so that
++ /*
++ * Hold a copy of the LAA in RAR[14] This is done so that
+ * between the time RAR[0] gets clobbered and the time it
+ * gets fixed, the actual LAA is in one of the RARs and no
+ * incoming packets directed to this port are dropped.
+@@ -1152,7 +1183,8 @@ static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw)
+ if (nvm->type != e1000_nvm_flash_hw)
+ return 0;
+
+- /* Check bit 4 of word 10h. If it is 0, firmware is done updating
++ /*
++ * Check bit 4 of word 10h. If it is 0, firmware is done updating
+ * 10h-12h. Checksum may need to be fixed.
+ */
+ ret_val = e1000_read_nvm(hw, 0x10, 1, &data);
+@@ -1160,7 +1192,8 @@ static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw)
+ return ret_val;
+
+ if (!(data & 0x10)) {
+- /* Read 0x23 and check bit 15. This bit is a 1
++ /*
++ * Read 0x23 and check bit 15. This bit is a 1
+ * when the checksum has already been fixed. If
+ * the checksum is still wrong and this bit is a
+ * 1, we need to return bad checksum. Otherwise,
+@@ -1240,7 +1273,7 @@ static struct e1000_mac_operations e82571_mac_ops = {
+ /* .get_link_up_info: media type dependent */
+ .led_on = e1000e_led_on_generic,
+ .led_off = e1000e_led_off_generic,
+- .mc_addr_list_update = e1000_mc_addr_list_update_82571,
++ .update_mc_addr_list = e1000_update_mc_addr_list_82571,
+ .reset_hw = e1000_reset_hw_82571,
+ .init_hw = e1000_init_hw_82571,
+ .setup_link = e1000_setup_link_82571,
+@@ -1293,18 +1326,16 @@ struct e1000_info e1000_82571_info = {
+ .mac = e1000_82571,
+ .flags = FLAG_HAS_HW_VLAN_FILTER
+ | FLAG_HAS_JUMBO_FRAMES
+- | FLAG_HAS_STATS_PTC_PRC
+ | FLAG_HAS_WOL
+ | FLAG_APME_IN_CTRL3
+ | FLAG_RX_CSUM_ENABLED
+ | FLAG_HAS_CTRLEXT_ON_LOAD
+- | FLAG_HAS_STATS_ICR_ICT
+ | FLAG_HAS_SMART_POWER_DOWN
+ | FLAG_RESET_OVERWRITES_LAA /* errata */
+ | FLAG_TARC_SPEED_MODE_BIT /* errata */
+ | FLAG_APME_CHECK_PORT_B,
+ .pba = 38,
+- .get_invariants = e1000_get_invariants_82571,
++ .get_variants = e1000_get_variants_82571,
+ .mac_ops = &e82571_mac_ops,
+ .phy_ops = &e82_phy_ops_igp,
+ .nvm_ops = &e82571_nvm_ops,
+@@ -1314,15 +1345,13 @@ struct e1000_info e1000_82572_info = {
+ .mac = e1000_82572,
+ .flags = FLAG_HAS_HW_VLAN_FILTER
+ | FLAG_HAS_JUMBO_FRAMES
+- | FLAG_HAS_STATS_PTC_PRC
+ | FLAG_HAS_WOL
+ | FLAG_APME_IN_CTRL3
+ | FLAG_RX_CSUM_ENABLED
+ | FLAG_HAS_CTRLEXT_ON_LOAD
+- | FLAG_HAS_STATS_ICR_ICT
+ | FLAG_TARC_SPEED_MODE_BIT, /* errata */
+ .pba = 38,
+- .get_invariants = e1000_get_invariants_82571,
++ .get_variants = e1000_get_variants_82571,
+ .mac_ops = &e82571_mac_ops,
+ .phy_ops = &e82_phy_ops_igp,
+ .nvm_ops = &e82571_nvm_ops,
+@@ -1332,17 +1361,15 @@ struct e1000_info e1000_82573_info = {
+ .mac = e1000_82573,
+ .flags = FLAG_HAS_HW_VLAN_FILTER
+ | FLAG_HAS_JUMBO_FRAMES
+- | FLAG_HAS_STATS_PTC_PRC
+ | FLAG_HAS_WOL
+ | FLAG_APME_IN_CTRL3
+ | FLAG_RX_CSUM_ENABLED
+- | FLAG_HAS_STATS_ICR_ICT
+ | FLAG_HAS_SMART_POWER_DOWN
+ | FLAG_HAS_AMT
+ | FLAG_HAS_ERT
+ | FLAG_HAS_SWSM_ON_LOAD,
+ .pba = 20,
+- .get_invariants = e1000_get_invariants_82571,
++ .get_variants = e1000_get_variants_82571,
+ .mac_ops = &e82571_mac_ops,
+ .phy_ops = &e82_phy_ops_m88,
+ .nvm_ops = &e82571_nvm_ops,
+diff --git a/drivers/net/e1000e/Makefile b/drivers/net/e1000e/Makefile
+index 650f866..360c913 100644
+--- a/drivers/net/e1000e/Makefile
++++ b/drivers/net/e1000e/Makefile
+@@ -1,7 +1,7 @@
+ ################################################################################
+ #
+ # Intel PRO/1000 Linux driver
+-# Copyright(c) 1999 - 2007 Intel Corporation.
++# Copyright(c) 1999 - 2008 Intel Corporation.
+ #
+ # This program is free software; you can redistribute it and/or modify it
+ # under the terms and conditions of the GNU General Public License,
+diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h
+index a4f511f..2a53875 100644
+--- a/drivers/net/e1000e/defines.h
++++ b/drivers/net/e1000e/defines.h
+@@ -1,7 +1,7 @@
+ /*******************************************************************************
+
+ Intel PRO/1000 Linux driver
+- Copyright(c) 1999 - 2007 Intel Corporation.
++ Copyright(c) 1999 - 2008 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+@@ -120,10 +120,10 @@
+ #define E1000_MANC_ARP_EN 0x00002000 /* Enable ARP Request Filtering */
+ #define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */
+ #define E1000_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */
+-#define E1000_MANC_EN_MAC_ADDR_FILTER 0x00100000 /* Enable MAC address
+- * filtering */
+-#define E1000_MANC_EN_MNG2HOST 0x00200000 /* Enable MNG packets to host
+- * memory */
++/* Enable MAC address filtering */
++#define E1000_MANC_EN_MAC_ADDR_FILTER 0x00100000
++/* Enable MNG packets to host memory */
++#define E1000_MANC_EN_MNG2HOST 0x00200000
+
+ /* Receive Control */
+ #define E1000_RCTL_EN 0x00000002 /* enable */
+@@ -135,25 +135,26 @@
+ #define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */
+ #define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */
+ #define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */
+-#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min threshold size */
++#define E1000_RCTL_RDMTS_HALF 0x00000000 /* Rx desc min threshold size */
+ #define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */
+ #define E1000_RCTL_BAM 0x00008000 /* broadcast enable */
+ /* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */
+-#define E1000_RCTL_SZ_2048 0x00000000 /* rx buffer size 2048 */
+-#define E1000_RCTL_SZ_1024 0x00010000 /* rx buffer size 1024 */
+-#define E1000_RCTL_SZ_512 0x00020000 /* rx buffer size 512 */
+-#define E1000_RCTL_SZ_256 0x00030000 /* rx buffer size 256 */
++#define E1000_RCTL_SZ_2048 0x00000000 /* Rx buffer size 2048 */
++#define E1000_RCTL_SZ_1024 0x00010000 /* Rx buffer size 1024 */
++#define E1000_RCTL_SZ_512 0x00020000 /* Rx buffer size 512 */
++#define E1000_RCTL_SZ_256 0x00030000 /* Rx buffer size 256 */
+ /* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */
+-#define E1000_RCTL_SZ_16384 0x00010000 /* rx buffer size 16384 */
+-#define E1000_RCTL_SZ_8192 0x00020000 /* rx buffer size 8192 */
+-#define E1000_RCTL_SZ_4096 0x00030000 /* rx buffer size 4096 */
++#define E1000_RCTL_SZ_16384 0x00010000 /* Rx buffer size 16384 */
++#define E1000_RCTL_SZ_8192 0x00020000 /* Rx buffer size 8192 */
++#define E1000_RCTL_SZ_4096 0x00030000 /* Rx buffer size 4096 */
+ #define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */
+ #define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */
+ #define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */
+ #define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */
+ #define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */
+
+-/* Use byte values for the following shift parameters
++/*
++ * Use byte values for the following shift parameters
+ * Usage:
+ * psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) &
+ * E1000_PSRCTL_BSIZE0_MASK) |
+@@ -183,6 +184,7 @@
+ #define E1000_SWFW_EEP_SM 0x1
+ #define E1000_SWFW_PHY0_SM 0x2
+ #define E1000_SWFW_PHY1_SM 0x4
++#define E1000_SWFW_CSR_SM 0x8
+
+ /* Device Control */
+ #define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */
+@@ -206,7 +208,8 @@
+ #define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */
+ #define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */
+
+-/* Bit definitions for the Management Data IO (MDIO) and Management Data
++/*
++ * Bit definitions for the Management Data IO (MDIO) and Management Data
+ * Clock (MDC) pins in the Device Control Register.
+ */
+
+@@ -279,7 +282,7 @@
+ #define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */
+
+ /* Transmit Control */
+-#define E1000_TCTL_EN 0x00000002 /* enable tx */
++#define E1000_TCTL_EN 0x00000002 /* enable Tx */
+ #define E1000_TCTL_PSP 0x00000008 /* pad short packets */
+ #define E1000_TCTL_CT 0x00000ff0 /* collision threshold */
+ #define E1000_TCTL_COLD 0x003ff000 /* collision distance */
+@@ -337,8 +340,8 @@
+ #define E1000_KABGTXD_BGSQLBIAS 0x00050000
+
+ /* PBA constants */
+-#define E1000_PBA_8K 0x0008 /* 8KB, default Rx allocation */
+-#define E1000_PBA_16K 0x0010 /* 16KB, default TX allocation */
++#define E1000_PBA_8K 0x0008 /* 8KB */
++#define E1000_PBA_16K 0x0010 /* 16KB */
+
+ #define E1000_PBS_16K E1000_PBA_16K
+
+@@ -356,12 +359,13 @@
+ /* Interrupt Cause Read */
+ #define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */
+ #define E1000_ICR_LSC 0x00000004 /* Link Status Change */
+-#define E1000_ICR_RXSEQ 0x00000008 /* rx sequence error */
+-#define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */
+-#define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 0) */
++#define E1000_ICR_RXSEQ 0x00000008 /* Rx sequence error */
++#define E1000_ICR_RXDMT0 0x00000010 /* Rx desc min. threshold (0) */
++#define E1000_ICR_RXT0 0x00000080 /* Rx timer intr (ring 0) */
+ #define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver should claim the interrupt */
+
+-/* This defines the bits that are set in the Interrupt Mask
++/*
++ * This defines the bits that are set in the Interrupt Mask
+ * Set/Read Register. Each bit is documented below:
+ * o RXT0 = Receiver Timer Interrupt (ring 0)
+ * o TXDW = Transmit Descriptor Written Back
+@@ -379,21 +383,22 @@
+ /* Interrupt Mask Set */
+ #define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */
+ #define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */
+-#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */
+-#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */
+-#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */
++#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */
++#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */
++#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* Rx timer intr */
+
+ /* Interrupt Cause Set */
+ #define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */
+ #define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */
++#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */
+
+ /* Transmit Descriptor Control */
+ #define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */
+ #define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL Writeback Threshold */
+ #define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */
+ #define E1000_TXDCTL_MAX_TX_DESC_PREFETCH 0x0100001F /* GRAN=1, PTHRESH=31 */
+-#define E1000_TXDCTL_COUNT_DESC 0x00400000 /* Enable the counting of desc.
+- still to be processed. */
++/* Enable the counting of desc. still to be processed. */
++#define E1000_TXDCTL_COUNT_DESC 0x00400000
+
+ /* Flow Control Constants */
+ #define FLOW_CONTROL_ADDRESS_LOW 0x00C28001
+@@ -404,7 +409,8 @@
+ #define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */
+
+ /* Receive Address */
+-/* Number of high/low register pairs in the RAR. The RAR (Receive Address
++/*
++ * Number of high/low register pairs in the RAR. The RAR (Receive Address
+ * Registers) holds the directed and multicast addresses that we monitor.
+ * Technically, we have 16 spots. However, we reserve one of these spots
+ * (RAR[15]) for our directed address used by controllers with
+@@ -522,8 +528,10 @@
+ #define PHY_ID2 0x03 /* Phy Id Reg (word 2) */
+ #define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */
+ #define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */
++#define PHY_AUTONEG_EXP 0x06 /* Autoneg Expansion Reg */
+ #define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */
+ #define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
++#define PHY_EXT_STATUS 0x0F /* Extended Status Reg */
+
+ /* NVM Control */
+ #define E1000_EECD_SK 0x00000001 /* NVM Clock */
+@@ -533,8 +541,8 @@
+ #define E1000_EECD_REQ 0x00000040 /* NVM Access Request */
+ #define E1000_EECD_GNT 0x00000080 /* NVM Access Grant */
+ #define E1000_EECD_SIZE 0x00000200 /* NVM Size (0=64 word 1=256 word) */
+-#define E1000_EECD_ADDR_BITS 0x00000400 /* NVM Addressing bits based on type
+- * (0-small, 1-large) */
++/* NVM Addressing bits based on type (0-small, 1-large) */
++#define E1000_EECD_ADDR_BITS 0x00000400
+ #define E1000_NVM_GRANT_ATTEMPTS 1000 /* NVM # attempts to gain grant */
+ #define E1000_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */
+ #define E1000_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */
+@@ -626,7 +634,8 @@
+ #define MAX_PHY_MULTI_PAGE_REG 0xF
+
+ /* Bit definitions for valid PHY IDs. */
+-/* I = Integrated
++/*
++ * I = Integrated
+ * E = External
+ */
+ #define M88E1000_E_PHY_ID 0x01410C50
+@@ -653,37 +662,37 @@
+ #define M88E1000_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5 */
+ /* Manual MDI configuration */
+ #define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */
+-#define M88E1000_PSCR_AUTO_X_1000T 0x0040 /* 1000BASE-T: Auto crossover,
+- * 100BASE-TX/10BASE-T:
+- * MDI Mode
+- */
+-#define M88E1000_PSCR_AUTO_X_MODE 0x0060 /* Auto crossover enabled
+- * all speeds.
+- */
+- /* 1=Enable Extended 10BASE-T distance
+- * (Lower 10BASE-T RX Threshold)
+- * 0=Normal 10BASE-T RX Threshold */
+- /* 1=5-Bit interface in 100BASE-TX
+- * 0=MII interface in 100BASE-TX */
+-#define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */
++/* 1000BASE-T: Auto crossover, 100BASE-TX/10BASE-T: MDI Mode */
++#define M88E1000_PSCR_AUTO_X_1000T 0x0040
++/* Auto crossover enabled all speeds */
++#define M88E1000_PSCR_AUTO_X_MODE 0x0060
++/*
++ * 1=Enable Extended 10BASE-T distance (Lower 10BASE-T Rx Threshold)
++ * 0=Normal 10BASE-T Rx Threshold
++ */
++#define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */
+
+ /* M88E1000 PHY Specific Status Register */
+ #define M88E1000_PSSR_REV_POLARITY 0x0002 /* 1=Polarity reversed */
+ #define M88E1000_PSSR_DOWNSHIFT 0x0020 /* 1=Downshifted */
+ #define M88E1000_PSSR_MDIX 0x0040 /* 1=MDIX; 0=MDI */
+-#define M88E1000_PSSR_CABLE_LENGTH 0x0380 /* 0=<50M;1=50-80M;2=80-110M;
+- * 3=110-140M;4=>140M */
++/* 0=<50M; 1=50-80M; 2=80-110M; 3=110-140M; 4=>140M */
++#define M88E1000_PSSR_CABLE_LENGTH 0x0380
+ #define M88E1000_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */
+ #define M88E1000_PSSR_1000MBS 0x8000 /* 10=1000Mbs */
+
+ #define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7
+
+-/* Number of times we will attempt to autonegotiate before downshifting if we
+- * are the master */
++/*
++ * Number of times we will attempt to autonegotiate before downshifting if we
++ * are the master
++ */
+ #define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00
+ #define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X 0x0000
+-/* Number of times we will attempt to autonegotiate before downshifting if we
+- * are the slave */
++/*
++ * Number of times we will attempt to autonegotiate before downshifting if we
++ * are the slave
++ */
+ #define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK 0x0300
+ #define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X 0x0100
+ #define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */
+@@ -692,7 +701,8 @@
+ #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK 0x0E00
+ #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X 0x0800
+
+-/* Bits...
++/*
++ * Bits...
+ * 15-5: page
+ * 4-0: register offset
+ */
+diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
+index 327c062..38bfd0d 100644
+--- a/drivers/net/e1000e/e1000.h
++++ b/drivers/net/e1000e/e1000.h
+@@ -1,7 +1,7 @@
+ /*******************************************************************************
+
+ Intel PRO/1000 Linux driver
+- Copyright(c) 1999 - 2007 Intel Corporation.
++ Copyright(c) 1999 - 2008 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+@@ -61,14 +61,17 @@ struct e1000_info;
+ ndev_printk(KERN_NOTICE , netdev, format, ## arg)
+
+
+-/* TX/RX descriptor defines */
++/* Tx/Rx descriptor defines */
+ #define E1000_DEFAULT_TXD 256
+ #define E1000_MAX_TXD 4096
+-#define E1000_MIN_TXD 80
++#define E1000_MIN_TXD 64
+
+ #define E1000_DEFAULT_RXD 256
+ #define E1000_MAX_RXD 4096
+-#define E1000_MIN_RXD 80
++#define E1000_MIN_RXD 64
++
++#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */
++#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */
+
+ /* Early Receive defines */
+ #define E1000_ERT_2048 0x100
+@@ -114,13 +117,13 @@ struct e1000_buffer {
+ dma_addr_t dma;
+ struct sk_buff *skb;
+ union {
+- /* TX */
++ /* Tx */
+ struct {
+ unsigned long time_stamp;
+ u16 length;
+ u16 next_to_watch;
+ };
+- /* RX */
++ /* Rx */
+ /* arrays of page information for packet split */
+ struct e1000_ps_page *ps_pages;
+ };
+@@ -147,6 +150,18 @@ struct e1000_ring {
+ struct e1000_queue_stats stats;
+ };
+
++/* PHY register snapshot values */
++struct e1000_phy_regs {
++ u16 bmcr; /* basic mode control register */
++ u16 bmsr; /* basic mode status register */
++ u16 advertise; /* auto-negotiation advertisement */
++ u16 lpa; /* link partner ability register */
++ u16 expansion; /* auto-negotiation expansion reg */
++ u16 ctrl1000; /* 1000BASE-T control register */
++ u16 stat1000; /* 1000BASE-T status register */
++ u16 estatus; /* extended status register */
++};
++
+ /* board specific private data structure */
+ struct e1000_adapter {
+ struct timer_list watchdog_timer;
+@@ -167,9 +182,6 @@ struct e1000_adapter {
+
+ spinlock_t tx_queue_lock; /* prevent concurrent tail updates */
+
+- /* this is still needed for 82571 and above */
+- atomic_t irq_sem;
+-
+ /* track device up/down/testing state */
+ unsigned long state;
+
+@@ -180,7 +192,7 @@ struct e1000_adapter {
+ u16 rx_itr;
+
+ /*
+- * TX
++ * Tx
+ */
+ struct e1000_ring *tx_ring /* One per active queue */
+ ____cacheline_aligned_in_smp;
+@@ -202,11 +214,11 @@ struct e1000_adapter {
+ unsigned int total_rx_bytes;
+ unsigned int total_rx_packets;
+
+- /* TX stats */
++ /* Tx stats */
+ u64 tpt_old;
+ u64 colc_old;
+- u64 gotcl_old;
+- u32 gotcl;
++ u32 gotc;
++ u64 gotc_old;
+ u32 tx_timeout_count;
+ u32 tx_fifo_head;
+ u32 tx_head_addr;
+@@ -214,7 +226,7 @@ struct e1000_adapter {
+ u32 tx_dma_failed;
+
+ /*
+- * RX
++ * Rx
+ */
+ bool (*clean_rx) (struct e1000_adapter *adapter,
+ int *work_done, int work_to_do)
+@@ -226,17 +238,19 @@ struct e1000_adapter {
+ u32 rx_int_delay;
+ u32 rx_abs_int_delay;
+
+- /* RX stats */
++ /* Rx stats */
+ u64 hw_csum_err;
+ u64 hw_csum_good;
+ u64 rx_hdr_split;
+- u64 gorcl_old;
+- u32 gorcl;
++ u32 gorc;
++ u64 gorc_old;
+ u32 alloc_rx_buff_failed;
+ u32 rx_dma_failed;
+
+ unsigned int rx_ps_pages;
+ u16 rx_ps_bsize0;
++ u32 max_frame_size;
++ u32 min_frame_size;
+
+ /* OS defined structs */
+ struct net_device *netdev;
+@@ -251,6 +265,9 @@ struct e1000_adapter {
+ struct e1000_phy_info phy_info;
+ struct e1000_phy_stats phy_stats;
+
++ /* Snapshot of PHY registers */
++ struct e1000_phy_regs phy_regs;
++
+ struct e1000_ring test_tx_ring;
+ struct e1000_ring test_rx_ring;
+ u32 test_icr;
+@@ -261,7 +278,7 @@ struct e1000_adapter {
+ u32 wol;
+ u32 pba;
+
+- u8 fc_autoneg;
++ bool fc_autoneg;
+
+ unsigned long led_status;
+
+@@ -272,7 +289,7 @@ struct e1000_info {
+ enum e1000_mac_type mac;
+ unsigned int flags;
+ u32 pba;
+- s32 (*get_invariants)(struct e1000_adapter *);
++ s32 (*get_variants)(struct e1000_adapter *);
+ struct e1000_mac_operations *mac_ops;
+ struct e1000_phy_operations *phy_ops;
+ struct e1000_nvm_operations *nvm_ops;
+@@ -287,8 +304,6 @@ struct e1000_info {
+ #define FLAG_HAS_CTRLEXT_ON_LOAD (1 << 5)
+ #define FLAG_HAS_SWSM_ON_LOAD (1 << 6)
+ #define FLAG_HAS_JUMBO_FRAMES (1 << 7)
+-#define FLAG_HAS_STATS_ICR_ICT (1 << 9)
+-#define FLAG_HAS_STATS_PTC_PRC (1 << 10)
+ #define FLAG_HAS_SMART_POWER_DOWN (1 << 11)
+ #define FLAG_IS_QUAD_PORT_A (1 << 12)
+ #define FLAG_IS_QUAD_PORT (1 << 13)
+@@ -308,6 +323,7 @@ struct e1000_info {
+ #define FLAG_MSI_ENABLED (1 << 27)
+ #define FLAG_RX_CSUM_ENABLED (1 << 28)
+ #define FLAG_TSO_FORCE (1 << 29)
++#define FLAG_RX_RESTART_NOW (1 << 30)
+
+ #define E1000_RX_DESC_PS(R, i) \
+ (&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
+@@ -357,7 +373,7 @@ extern struct e1000_info e1000_ich8_info;
+ extern struct e1000_info e1000_ich9_info;
+ extern struct e1000_info e1000_es2_info;
+
+-extern s32 e1000e_read_part_num(struct e1000_hw *hw, u32 *part_num);
++extern s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num);
+
+ extern s32 e1000e_commit_phy(struct e1000_hw *hw);
+
+@@ -390,9 +406,11 @@ extern s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw);
+ extern s32 e1000e_setup_link(struct e1000_hw *hw);
+ extern void e1000e_clear_vfta(struct e1000_hw *hw);
+ extern void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count);
+-extern void e1000e_mc_addr_list_update_generic(struct e1000_hw *hw,
+- u8 *mc_addr_list, u32 mc_addr_count,
+- u32 rar_used_count, u32 rar_count);
++extern void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw,
++ u8 *mc_addr_list,
++ u32 mc_addr_count,
++ u32 rar_used_count,
++ u32 rar_count);
+ extern void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index);
+ extern s32 e1000e_set_fc_watermarks(struct e1000_hw *hw);
+ extern void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop);
+@@ -431,6 +449,8 @@ extern s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data);
+ extern s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
+ u32 usec_interval, bool *success);
+ extern s32 e1000e_phy_reset_dsp(struct e1000_hw *hw);
++extern s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
++extern s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
+ extern s32 e1000e_check_downshift(struct e1000_hw *hw);
+
+ static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw)
+@@ -462,7 +482,6 @@ extern s32 e1000e_acquire_nvm(struct e1000_hw *hw);
+ extern s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
+ extern s32 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw);
+ extern s32 e1000e_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg);
+-extern s32 e1000e_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
+ extern s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
+ extern s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw);
+ extern void e1000e_release_nvm(struct e1000_hw *hw);
+diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/e1000e/es2lan.c
+index 88657ad..dc552d7 100644
+--- a/drivers/net/e1000e/es2lan.c
++++ b/drivers/net/e1000e/es2lan.c
+@@ -1,7 +1,7 @@
+ /*******************************************************************************
+
+ Intel PRO/1000 Linux driver
+- Copyright(c) 1999 - 2007 Intel Corporation.
++ Copyright(c) 1999 - 2008 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+@@ -41,6 +41,7 @@
+ #define E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL 0x00
+ #define E1000_KMRNCTRLSTA_OFFSET_INB_CTRL 0x02
+ #define E1000_KMRNCTRLSTA_OFFSET_HD_CTRL 0x10
++#define E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE 0x1F
+
+ #define E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS 0x0008
+ #define E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS 0x0800
+@@ -48,6 +49,7 @@
+
+ #define E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT 0x0004
+ #define E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT 0x0000
++#define E1000_KMRNCTRLSTA_OPMODE_E_IDLE 0x2000
+
+ #define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */
+ #define DEFAULT_TCTL_EXT_GCEX_80003ES2LAN 0x00010000
+@@ -85,6 +87,9 @@
+ /* Kumeran Mode Control Register (Page 193, Register 16) */
+ #define GG82563_KMCR_PASS_FALSE_CARRIER 0x0800
+
++/* Max number of times Kumeran read/write should be validated */
++#define GG82563_MAX_KMRN_RETRY 0x5
++
+ /* Power Management Control Register (Page 193, Register 20) */
+ #define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE 0x0001
+ /* 1=Enable SERDES Electrical Idle */
+@@ -92,7 +97,8 @@
+ /* In-Band Control Register (Page 194, Register 18) */
+ #define GG82563_ICR_DIS_PADDING 0x0010 /* Disable Padding */
+
+-/* A table for the GG82563 cable length where the range is defined
++/*
++ * A table for the GG82563 cable length where the range is defined
+ * with a lower bound at "index" and the upper bound at
+ * "index + 5".
+ */
+@@ -118,7 +124,7 @@ static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw)
+ struct e1000_phy_info *phy = &hw->phy;
+ s32 ret_val;
+
+- if (hw->media_type != e1000_media_type_copper) {
++ if (hw->phy.media_type != e1000_media_type_copper) {
+ phy->type = e1000_phy_none;
+ return 0;
+ }
+@@ -167,15 +173,20 @@ static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw)
+ break;
+ }
+
+- nvm->type = e1000_nvm_eeprom_spi;
++ nvm->type = e1000_nvm_eeprom_spi;
+
+ size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
+ E1000_EECD_SIZE_EX_SHIFT);
+
+- /* Added to a constant, "size" becomes the left-shift value
++ /*
++ * Added to a constant, "size" becomes the left-shift value
+ * for setting word_size.
+ */
+ size += NVM_WORD_SIZE_BASE_SHIFT;
++
++ /* EEPROM access above 16k is unsupported */
++ if (size > 14)
++ size = 14;
+ nvm->word_size = 1 << size;
+
+ return 0;
+@@ -196,10 +207,10 @@ static s32 e1000_init_mac_params_80003es2lan(struct e1000_adapter *adapter)
+ /* Set media type */
+ switch (adapter->pdev->device) {
+ case E1000_DEV_ID_80003ES2LAN_SERDES_DPT:
+- hw->media_type = e1000_media_type_internal_serdes;
++ hw->phy.media_type = e1000_media_type_internal_serdes;
+ break;
+ default:
+- hw->media_type = e1000_media_type_copper;
++ hw->phy.media_type = e1000_media_type_copper;
+ break;
+ }
+
+@@ -208,11 +219,10 @@ static s32 e1000_init_mac_params_80003es2lan(struct e1000_adapter *adapter)
+ /* Set rar entry count */
+ mac->rar_entry_count = E1000_RAR_ENTRIES;
+ /* Set if manageability features are enabled. */
+- mac->arc_subsystem_valid =
+- (er32(FWSM) & E1000_FWSM_MODE_MASK) ? 1 : 0;
++ mac->arc_subsystem_valid = (er32(FWSM) & E1000_FWSM_MODE_MASK) ? 1 : 0;
+
+ /* check for link */
+- switch (hw->media_type) {
++ switch (hw->phy.media_type) {
+ case e1000_media_type_copper:
+ func->setup_physical_interface = e1000_setup_copper_link_80003es2lan;
+ func->check_for_link = e1000e_check_for_copper_link;
+@@ -233,7 +243,7 @@ static s32 e1000_init_mac_params_80003es2lan(struct e1000_adapter *adapter)
+ return 0;
+ }
+
+-static s32 e1000_get_invariants_80003es2lan(struct e1000_adapter *adapter)
++static s32 e1000_get_variants_80003es2lan(struct e1000_adapter *adapter)
+ {
+ struct e1000_hw *hw = &adapter->hw;
+ s32 rc;
+@@ -265,6 +275,7 @@ static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw)
+ u16 mask;
+
+ mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
++ mask |= E1000_SWFW_CSR_SM;
+
+ return e1000_acquire_swfw_sync_80003es2lan(hw, mask);
+ }
+@@ -281,6 +292,8 @@ static void e1000_release_phy_80003es2lan(struct e1000_hw *hw)
+ u16 mask;
+
+ mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
++ mask |= E1000_SWFW_CSR_SM;
++
+ e1000_release_swfw_sync_80003es2lan(hw, mask);
+ }
+
+@@ -344,8 +357,10 @@ static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask)
+ if (!(swfw_sync & (fwmask | swmask)))
+ break;
+
+- /* Firmware currently using resource (fwmask)
+- * or other software thread using resource (swmask) */
++ /*
++ * Firmware currently using resource (fwmask)
++ * or other software thread using resource (swmask)
++ */
+ e1000e_put_hw_semaphore(hw);
+ mdelay(5);
+ i++;
+@@ -403,41 +418,51 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
+ u32 page_select;
+ u16 temp;
+
++ ret_val = e1000_acquire_phy_80003es2lan(hw);
++ if (ret_val)
++ return ret_val;
++
+ /* Select Configuration Page */
+- if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG)
++ if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
+ page_select = GG82563_PHY_PAGE_SELECT;
+- else
+- /* Use Alternative Page Select register to access
++ } else {
++ /*
++ * Use Alternative Page Select register to access
+ * registers 30 and 31
+ */
+ page_select = GG82563_PHY_PAGE_SELECT_ALT;
++ }
+
+ temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT);
+- ret_val = e1000e_write_phy_reg_m88(hw, page_select, temp);
+- if (ret_val)
++ ret_val = e1000e_write_phy_reg_mdic(hw, page_select, temp);
++ if (ret_val) {
++ e1000_release_phy_80003es2lan(hw);
+ return ret_val;
++ }
+
+- /* The "ready" bit in the MDIC register may be incorrectly set
++ /*
++ * The "ready" bit in the MDIC register may be incorrectly set
+ * before the device has completed the "Page Select" MDI
+ * transaction. So we wait 200us after each MDI command...
+ */
+ udelay(200);
+
+ /* ...and verify the command was successful. */
+- ret_val = e1000e_read_phy_reg_m88(hw, page_select, &temp);
++ ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp);
+
+ if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
+ ret_val = -E1000_ERR_PHY;
++ e1000_release_phy_80003es2lan(hw);
+ return ret_val;
+ }
+
+ udelay(200);
+
+- ret_val = e1000e_read_phy_reg_m88(hw,
+- MAX_PHY_REG_ADDRESS & offset,
+- data);
++ ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
++ data);
+
+ udelay(200);
++ e1000_release_phy_80003es2lan(hw);
+
+ return ret_val;
+ }
+@@ -458,40 +483,51 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
+ u32 page_select;
+ u16 temp;
+
++ ret_val = e1000_acquire_phy_80003es2lan(hw);
++ if (ret_val)
++ return ret_val;
++
+ /* Select Configuration Page */
+- if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG)
++ if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
+ page_select = GG82563_PHY_PAGE_SELECT;
+- else
+- /* Use Alternative Page Select register to access
++ } else {
++ /*
++ * Use Alternative Page Select register to access
+ * registers 30 and 31
+ */
+ page_select = GG82563_PHY_PAGE_SELECT_ALT;
++ }
+
+ temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT);
+- ret_val = e1000e_write_phy_reg_m88(hw, page_select, temp);
+- if (ret_val)
++ ret_val = e1000e_write_phy_reg_mdic(hw, page_select, temp);
++ if (ret_val) {
++ e1000_release_phy_80003es2lan(hw);
+ return ret_val;
++ }
+
+
+- /* The "ready" bit in the MDIC register may be incorrectly set
++ /*
++ * The "ready" bit in the MDIC register may be incorrectly set
+ * before the device has completed the "Page Select" MDI
+ * transaction. So we wait 200us after each MDI command...
+ */
+ udelay(200);
+
+ /* ...and verify the command was successful. */
+- ret_val = e1000e_read_phy_reg_m88(hw, page_select, &temp);
++ ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp);
+
+- if (((u16)offset >> GG82563_PAGE_SHIFT) != temp)
++ if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
++ e1000_release_phy_80003es2lan(hw);
+ return -E1000_ERR_PHY;
++ }
+
+ udelay(200);
+
+- ret_val = e1000e_write_phy_reg_m88(hw,
+- MAX_PHY_REG_ADDRESS & offset,
+- data);
++ ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
++ data);
+
+ udelay(200);
++ e1000_release_phy_80003es2lan(hw);
+
+ return ret_val;
+ }
+@@ -554,7 +590,8 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
+ u16 phy_data;
+ bool link;
+
+- /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI
++ /*
++ * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI
+ * forced whenever speed and duplex are forced.
+ */
+ ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+@@ -583,7 +620,7 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
+
+ udelay(1);
+
+- if (hw->phy.wait_for_link) {
++ if (hw->phy.autoneg_wait_to_complete) {
+ hw_dbg(hw, "Waiting for forced speed/duplex link "
+ "on GG82563 phy.\n");
+
+@@ -593,7 +630,8 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
+ return ret_val;
+
+ if (!link) {
+- /* We didn't get link.
++ /*
++ * We didn't get link.
+ * Reset the DSP and cross our fingers.
+ */
+ ret_val = e1000e_phy_reset_dsp(hw);
+@@ -612,7 +650,8 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
+ if (ret_val)
+ return ret_val;
+
+- /* Resetting the phy means we need to verify the TX_CLK corresponds
++ /*
++ * Resetting the phy means we need to verify the TX_CLK corresponds
+ * to the link speed. 10Mbps -> 2.5MHz, else 25MHz.
+ */
+ phy_data &= ~GG82563_MSCR_TX_CLK_MASK;
+@@ -621,7 +660,8 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
+ else
+ phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25;
+
+- /* In addition, we must re-enable CRS on Tx for both half and full
++ /*
++ * In addition, we must re-enable CRS on Tx for both half and full
+ * duplex.
+ */
+ phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
+@@ -671,7 +711,7 @@ static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed,
+ {
+ s32 ret_val;
+
+- if (hw->media_type == e1000_media_type_copper) {
++ if (hw->phy.media_type == e1000_media_type_copper) {
+ ret_val = e1000e_get_speed_and_duplex_copper(hw,
+ speed,
+ duplex);
+@@ -704,7 +744,8 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
+ u32 icr;
+ s32 ret_val;
+
+- /* Prevent the PCI-E bus from sticking if there is no TLP connection
++ /*
++ * Prevent the PCI-E bus from sticking if there is no TLP connection
+ * on the last TLP read/write transaction when MAC is reset.
+ */
+ ret_val = e1000e_disable_pcie_master(hw);
+@@ -776,16 +817,16 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
+ ret_val = e1000e_setup_link(hw);
+
+ /* Set the transmit descriptor write-back policy */
+- reg_data = er32(TXDCTL);
++ reg_data = er32(TXDCTL(0));
+ reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
+ E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC;
+- ew32(TXDCTL, reg_data);
++ ew32(TXDCTL(0), reg_data);
+
+ /* ...for both queues. */
+- reg_data = er32(TXDCTL1);
++ reg_data = er32(TXDCTL(1));
+ reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
+ E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC;
+- ew32(TXDCTL1, reg_data);
++ ew32(TXDCTL(1), reg_data);
+
+ /* Enable retransmit on late collisions */
+ reg_data = er32(TCTL);
+@@ -808,7 +849,8 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
+ reg_data &= ~0x00100000;
+ E1000_WRITE_REG_ARRAY(hw, E1000_FFLT, 0x0001, reg_data);
+
+- /* Clear all of the statistics registers (clear on read). It is
++ /*
++ * Clear all of the statistics registers (clear on read). It is
+ * important that we do this after we have tried to establish link
+ * because the symbol error count will increment wildly if there
+ * is no link.
+@@ -829,29 +871,29 @@ static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw)
+ u32 reg;
+
+ /* Transmit Descriptor Control 0 */
+- reg = er32(TXDCTL);
++ reg = er32(TXDCTL(0));
+ reg |= (1 << 22);
+- ew32(TXDCTL, reg);
++ ew32(TXDCTL(0), reg);
+
+ /* Transmit Descriptor Control 1 */
+- reg = er32(TXDCTL1);
++ reg = er32(TXDCTL(1));
+ reg |= (1 << 22);
+- ew32(TXDCTL1, reg);
++ ew32(TXDCTL(1), reg);
+
+ /* Transmit Arbitration Control 0 */
+- reg = er32(TARC0);
++ reg = er32(TARC(0));
+ reg &= ~(0xF << 27); /* 30:27 */
+- if (hw->media_type != e1000_media_type_copper)
++ if (hw->phy.media_type != e1000_media_type_copper)
+ reg &= ~(1 << 20);
+- ew32(TARC0, reg);
++ ew32(TARC(0), reg);
+
+ /* Transmit Arbitration Control 1 */
+- reg = er32(TARC1);
++ reg = er32(TARC(1));
+ if (er32(TCTL) & E1000_TCTL_MULR)
+ reg &= ~(1 << 28);
+ else
+ reg |= (1 << 28);
+- ew32(TARC1, reg);
++ ew32(TARC(1), reg);
+ }
+
+ /**
+@@ -865,10 +907,10 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
+ struct e1000_phy_info *phy = &hw->phy;
+ s32 ret_val;
+ u32 ctrl_ext;
+- u16 data;
++ u32 i = 0;
++ u16 data, data2;
+
+- ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL,
+- &data);
++ ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL, &data);
+ if (ret_val)
+ return ret_val;
+
+@@ -876,12 +918,12 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
+ /* Use 25MHz for both link down and 1000Base-T for Tx clock. */
+ data |= GG82563_MSCR_TX_CLK_1000MBPS_25;
+
+- ret_val = e1e_wphy(hw, GG82563_PHY_MAC_SPEC_CTRL,
+- data);
++ ret_val = e1e_wphy(hw, GG82563_PHY_MAC_SPEC_CTRL, data);
+ if (ret_val)
+ return ret_val;
+
+- /* Options:
++ /*
++ * Options:
+ * MDI/MDI-X = 0 (default)
+ * 0 - Auto for all speeds
+ * 1 - MDI mode
+@@ -907,7 +949,8 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
+ break;
+ }
+
+- /* Options:
++ /*
++ * Options:
+ * disable_polarity_correction = 0 (default)
+ * Automatic Correction for Reversed Cable Polarity
+ * 0 - Disabled
+@@ -928,14 +971,25 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
+ return ret_val;
+ }
+
+- /* Bypass RX and TX FIFO's */
+- ret_val = e1000e_write_kmrn_reg(hw,
+- E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL,
+- E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS |
++ /* Bypass Rx and Tx FIFO's */
++ ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL,
++ E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS |
+ E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS);
+ if (ret_val)
+ return ret_val;
+
++ ret_val = e1000e_read_kmrn_reg(hw,
++ E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE,
++ &data);
++ if (ret_val)
++ return ret_val;
++ data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE;
++ ret_val = e1000e_write_kmrn_reg(hw,
++ E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE,
++ data);
++ if (ret_val)
++ return ret_val;
++
+ ret_val = e1e_rphy(hw, GG82563_PHY_SPEC_CTRL_2, &data);
+ if (ret_val)
+ return ret_val;
+@@ -953,7 +1007,8 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
+ if (ret_val)
+ return ret_val;
+
+- /* Do not init these registers when the HW is in IAMT mode, since the
++ /*
++ * Do not init these registers when the HW is in IAMT mode, since the
+ * firmware will have already initialized them. We only initialize
+ * them if the HW is not in IAMT mode.
+ */
+@@ -964,9 +1019,18 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
+ if (ret_val)
+ return ret_val;
+
+- ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &data);
+- if (ret_val)
+- return ret_val;
++ do {
++ ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL,
++ &data);
++ if (ret_val)
++ return ret_val;
++
++ ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL,
++ &data2);
++ if (ret_val)
++ return ret_val;
++ i++;
++ } while ((data != data2) && (i < GG82563_MAX_KMRN_RETRY));
+
+ data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
+ ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, data);
+@@ -974,7 +1038,8 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
+ return ret_val;
+ }
+
+- /* Workaround: Disable padding in Kumeran interface in the MAC
++ /*
++ * Workaround: Disable padding in Kumeran interface in the MAC
+ * and in the PHY to avoid CRC errors.
+ */
+ ret_val = e1e_rphy(hw, GG82563_PHY_INBAND_CTRL, &data);
+@@ -1007,9 +1072,11 @@ static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw)
+ ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+ ew32(CTRL, ctrl);
+
+- /* Set the mac to wait the maximum time between each
++ /*
++ * Set the mac to wait the maximum time between each
+ * iteration and increase the max iterations when
+- * polling the phy; this fixes erroneous timeouts at 10Mbps. */
++ * polling the phy; this fixes erroneous timeouts at 10Mbps.
++ */
+ ret_val = e1000e_write_kmrn_reg(hw, GG82563_REG(0x34, 4), 0xFFFF);
+ if (ret_val)
+ return ret_val;
+@@ -1026,9 +1093,8 @@ static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw)
+ if (ret_val)
+ return ret_val;
+ reg_data |= E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING;
+- ret_val = e1000e_write_kmrn_reg(hw,
+- E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
+- reg_data);
++ ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
++ reg_data);
+ if (ret_val)
+ return ret_val;
+
+@@ -1053,12 +1119,12 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
+ {
+ s32 ret_val;
+ u32 tipg;
+- u16 reg_data;
++ u32 i = 0;
++ u16 reg_data, reg_data2;
+
+ reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT;
+- ret_val = e1000e_write_kmrn_reg(hw,
+- E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
+- reg_data);
++ ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
++ reg_data);
+ if (ret_val)
+ return ret_val;
+
+@@ -1068,9 +1134,16 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
+ tipg |= DEFAULT_TIPG_IPGT_10_100_80003ES2LAN;
+ ew32(TIPG, tipg);
+
+- ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data);
+- if (ret_val)
+- return ret_val;
++ do {
++ ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data);
++ if (ret_val)
++ return ret_val;
++
++ ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data2);
++ if (ret_val)
++ return ret_val;
++ i++;
++ } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
+
+ if (duplex == HALF_DUPLEX)
+ reg_data |= GG82563_KMCR_PASS_FALSE_CARRIER;
+@@ -1092,13 +1165,13 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
+ static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
+ {
+ s32 ret_val;
+- u16 reg_data;
++ u16 reg_data, reg_data2;
+ u32 tipg;
++ u32 i = 0;
+
+ reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT;
+- ret_val = e1000e_write_kmrn_reg(hw,
+- E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
+- reg_data);
++ ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
++ reg_data);
+ if (ret_val)
+ return ret_val;
+
+@@ -1108,9 +1181,16 @@ static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
+ tipg |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN;
+ ew32(TIPG, tipg);
+
+- ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data);
+- if (ret_val)
+- return ret_val;
++ do {
++ ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data);
++ if (ret_val)
++ return ret_val;
++
++ ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data2);
++ if (ret_val)
++ return ret_val;
++ i++;
++ } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
+
+ reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
+ ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
+@@ -1175,7 +1255,7 @@ static struct e1000_mac_operations es2_mac_ops = {
+ .get_link_up_info = e1000_get_link_up_info_80003es2lan,
+ .led_on = e1000e_led_on_generic,
+ .led_off = e1000e_led_off_generic,
+- .mc_addr_list_update = e1000e_mc_addr_list_update_generic,
++ .update_mc_addr_list = e1000e_update_mc_addr_list_generic,
+ .reset_hw = e1000_reset_hw_80003es2lan,
+ .init_hw = e1000_init_hw_80003es2lan,
+ .setup_link = e1000e_setup_link,
+@@ -1212,19 +1292,17 @@ struct e1000_info e1000_es2_info = {
+ .mac = e1000_80003es2lan,
+ .flags = FLAG_HAS_HW_VLAN_FILTER
+ | FLAG_HAS_JUMBO_FRAMES
+- | FLAG_HAS_STATS_PTC_PRC
+ | FLAG_HAS_WOL
+ | FLAG_APME_IN_CTRL3
+ | FLAG_RX_CSUM_ENABLED
+ | FLAG_HAS_CTRLEXT_ON_LOAD
+- | FLAG_HAS_STATS_ICR_ICT
+ | FLAG_RX_NEEDS_RESTART /* errata */
+ | FLAG_TARC_SET_BIT_ZERO /* errata */
+ | FLAG_APME_CHECK_PORT_B
+ | FLAG_DISABLE_FC_PAUSE_TIME /* errata */
+ | FLAG_TIPG_MEDIUM_FOR_80003ESLAN,
+ .pba = 38,
+- .get_invariants = e1000_get_invariants_80003es2lan,
++ .get_variants = e1000_get_variants_80003es2lan,
+ .mac_ops = &es2_mac_ops,
+ .phy_ops = &es2_phy_ops,
+ .nvm_ops = &es2_nvm_ops,
+diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
+index f77a742..ce045ac 100644
+--- a/drivers/net/e1000e/ethtool.c
++++ b/drivers/net/e1000e/ethtool.c
+@@ -1,7 +1,7 @@
+ /*******************************************************************************
+
+ Intel PRO/1000 Linux driver
+- Copyright(c) 1999 - 2007 Intel Corporation.
++ Copyright(c) 1999 - 2008 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+@@ -46,8 +46,8 @@ struct e1000_stats {
+ static const struct e1000_stats e1000_gstrings_stats[] = {
+ { "rx_packets", E1000_STAT(stats.gprc) },
+ { "tx_packets", E1000_STAT(stats.gptc) },
+- { "rx_bytes", E1000_STAT(stats.gorcl) },
+- { "tx_bytes", E1000_STAT(stats.gotcl) },
++ { "rx_bytes", E1000_STAT(stats.gorc) },
++ { "tx_bytes", E1000_STAT(stats.gotc) },
+ { "rx_broadcast", E1000_STAT(stats.bprc) },
+ { "tx_broadcast", E1000_STAT(stats.bptc) },
+ { "rx_multicast", E1000_STAT(stats.mprc) },
+@@ -83,7 +83,7 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
+ { "rx_flow_control_xoff", E1000_STAT(stats.xoffrxc) },
+ { "tx_flow_control_xon", E1000_STAT(stats.xontxc) },
+ { "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) },
+- { "rx_long_byte_count", E1000_STAT(stats.gorcl) },
++ { "rx_long_byte_count", E1000_STAT(stats.gorc) },
+ { "rx_csum_offload_good", E1000_STAT(hw_csum_good) },
+ { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) },
+ { "rx_header_split", E1000_STAT(rx_hdr_split) },
+@@ -102,7 +102,7 @@ static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = {
+ "Interrupt test (offline)", "Loopback test (offline)",
+ "Link test (on/offline)"
+ };
+-#define E1000_TEST_LEN ARRAY_SIZE(e1000_gstrings_test)
++#define E1000_TEST_LEN ARRAY_SIZE(e1000_gstrings_test)
+
+ static int e1000_get_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd)
+@@ -111,7 +111,7 @@ static int e1000_get_settings(struct net_device *netdev,
+ struct e1000_hw *hw = &adapter->hw;
+ u32 status;
+
+- if (hw->media_type == e1000_media_type_copper) {
++ if (hw->phy.media_type == e1000_media_type_copper) {
+
+ ecmd->supported = (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+@@ -165,7 +165,7 @@ static int e1000_get_settings(struct net_device *netdev,
+ ecmd->duplex = -1;
+ }
+
+- ecmd->autoneg = ((hw->media_type == e1000_media_type_fiber) ||
++ ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) ||
+ hw->mac.autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE;
+ return 0;
+ }
+@@ -187,7 +187,7 @@ static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
+ mac->autoneg = 0;
+
+ /* Fiber NICs only allow 1000 gbps Full duplex */
+- if ((adapter->hw.media_type == e1000_media_type_fiber) &&
++ if ((adapter->hw.phy.media_type == e1000_media_type_fiber) &&
+ spddplx != (SPEED_1000 + DUPLEX_FULL)) {
+ ndev_err(adapter->netdev, "Unsupported Speed/Duplex "
+ "configuration\n");
+@@ -226,8 +226,10 @@ static int e1000_set_settings(struct net_device *netdev,
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
+
+- /* When SoL/IDER sessions are active, autoneg/speed/duplex
+- * cannot be changed */
++ /*
++ * When SoL/IDER sessions are active, autoneg/speed/duplex
++ * cannot be changed
++ */
+ if (e1000_check_reset_block(hw)) {
+ ndev_err(netdev, "Cannot change link "
+ "characteristics when SoL/IDER is active.\n");
+@@ -239,7 +241,7 @@ static int e1000_set_settings(struct net_device *netdev,
+
+ if (ecmd->autoneg == AUTONEG_ENABLE) {
+ hw->mac.autoneg = 1;
+- if (hw->media_type == e1000_media_type_fiber)
++ if (hw->phy.media_type == e1000_media_type_fiber)
+ hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full |
+ ADVERTISED_FIBRE |
+ ADVERTISED_Autoneg;
+@@ -248,6 +250,8 @@ static int e1000_set_settings(struct net_device *netdev,
+ ADVERTISED_TP |
+ ADVERTISED_Autoneg;
+ ecmd->advertising = hw->phy.autoneg_advertised;
++ if (adapter->fc_autoneg)
++ hw->fc.original_type = e1000_fc_default;
+ } else {
+ if (e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) {
+ clear_bit(__E1000_RESETTING, &adapter->state);
+@@ -277,11 +281,11 @@ static void e1000_get_pauseparam(struct net_device *netdev,
+ pause->autoneg =
+ (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
+
+- if (hw->mac.fc == e1000_fc_rx_pause) {
++ if (hw->fc.type == e1000_fc_rx_pause) {
+ pause->rx_pause = 1;
+- } else if (hw->mac.fc == e1000_fc_tx_pause) {
++ } else if (hw->fc.type == e1000_fc_tx_pause) {
+ pause->tx_pause = 1;
+- } else if (hw->mac.fc == e1000_fc_full) {
++ } else if (hw->fc.type == e1000_fc_full) {
+ pause->rx_pause = 1;
+ pause->tx_pause = 1;
+ }
+@@ -300,18 +304,18 @@ static int e1000_set_pauseparam(struct net_device *netdev,
+ msleep(1);
+
+ if (pause->rx_pause && pause->tx_pause)
+- hw->mac.fc = e1000_fc_full;
++ hw->fc.type = e1000_fc_full;
+ else if (pause->rx_pause && !pause->tx_pause)
+- hw->mac.fc = e1000_fc_rx_pause;
++ hw->fc.type = e1000_fc_rx_pause;
+ else if (!pause->rx_pause && pause->tx_pause)
+- hw->mac.fc = e1000_fc_tx_pause;
++ hw->fc.type = e1000_fc_tx_pause;
+ else if (!pause->rx_pause && !pause->tx_pause)
+- hw->mac.fc = e1000_fc_none;
++ hw->fc.type = e1000_fc_none;
+
+- hw->mac.original_fc = hw->mac.fc;
++ hw->fc.original_type = hw->fc.type;
+
+ if (adapter->fc_autoneg == AUTONEG_ENABLE) {
+- hw->mac.fc = e1000_fc_default;
++ hw->fc.type = e1000_fc_default;
+ if (netif_running(adapter->netdev)) {
+ e1000e_down(adapter);
+ e1000e_up(adapter);
+@@ -319,7 +323,7 @@ static int e1000_set_pauseparam(struct net_device *netdev,
+ e1000e_reset(adapter);
+ }
+ } else {
+- retval = ((hw->media_type == e1000_media_type_fiber) ?
++ retval = ((hw->phy.media_type == e1000_media_type_fiber) ?
+ hw->mac.ops.setup_link(hw) : e1000e_force_mac_fc(hw));
+ }
+
+@@ -558,8 +562,10 @@ static int e1000_set_eeprom(struct net_device *netdev,
+ ret_val = e1000_write_nvm(hw, first_word,
+ last_word - first_word + 1, eeprom_buff);
+
+- /* Update the checksum over the first part of the EEPROM if needed
+- * and flush shadow RAM for 82573 controllers */
++ /*
++ * Update the checksum over the first part of the EEPROM if needed
++ * and flush shadow RAM for 82573 controllers
++ */
+ if ((ret_val == 0) && ((first_word <= NVM_CHECKSUM_REG) ||
+ (hw->mac.type == e1000_82573)))
+ e1000e_update_nvm_checksum(hw);
+@@ -578,8 +584,10 @@ static void e1000_get_drvinfo(struct net_device *netdev,
+ strncpy(drvinfo->driver, e1000e_driver_name, 32);
+ strncpy(drvinfo->version, e1000e_driver_version, 32);
+
+- /* EEPROM image version # is reported as firmware version # for
+- * PCI-E controllers */
++ /*
++ * EEPROM image version # is reported as firmware version # for
++ * PCI-E controllers
++ */
+ e1000_read_nvm(&adapter->hw, 5, 1, &eeprom_data);
+ sprintf(firmware_version, "%d.%d-%d",
+ (eeprom_data & 0xF000) >> 12,
+@@ -633,10 +641,17 @@ static int e1000_set_ringparam(struct net_device *netdev,
+ tx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL);
+ if (!tx_ring)
+ goto err_alloc_tx;
++ /*
++ * use a memcpy to save any previously configured
++ * items like napi structs from having to be
++ * reinitialized
++ */
++ memcpy(tx_ring, tx_old, sizeof(struct e1000_ring));
+
+ rx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL);
+ if (!rx_ring)
+ goto err_alloc_rx;
++ memcpy(rx_ring, rx_old, sizeof(struct e1000_ring));
+
+ adapter->tx_ring = tx_ring;
+ adapter->rx_ring = rx_ring;
+@@ -658,8 +673,10 @@ static int e1000_set_ringparam(struct net_device *netdev,
+ if (err)
+ goto err_setup_tx;
+
+- /* save the new, restore the old in order to free it,
+- * then restore the new back again */
++ /*
++ * restore the old in order to free it,
++ * then add in the new
++ */
+ adapter->rx_ring = rx_old;
+ adapter->tx_ring = tx_old;
+ e1000e_free_rx_resources(adapter);
+@@ -690,61 +707,55 @@ err_setup:
+ return err;
+ }
+
+-static bool reg_pattern_test_array(struct e1000_adapter *adapter, u64 *data,
+- int reg, int offset, u32 mask, u32 write)
++static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data,
++ int reg, int offset, u32 mask, u32 write)
+ {
+- int i;
+- u32 read;
++ u32 pat, val;
+ static const u32 test[] =
+ {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
+- for (i = 0; i < ARRAY_SIZE(test); i++) {
++ for (pat = 0; pat < ARRAY_SIZE(test); pat++) {
+ E1000_WRITE_REG_ARRAY(&adapter->hw, reg, offset,
+- (test[i] & write));
+- read = E1000_READ_REG_ARRAY(&adapter->hw, reg, offset);
+- if (read != (test[i] & write & mask)) {
++ (test[pat] & write));
++ val = E1000_READ_REG_ARRAY(&adapter->hw, reg, offset);
++ if (val != (test[pat] & write & mask)) {
+ ndev_err(adapter->netdev, "pattern test reg %04X "
+ "failed: got 0x%08X expected 0x%08X\n",
+ reg + offset,
+- read, (test[i] & write & mask));
++ val, (test[pat] & write & mask));
+ *data = reg;
+- return true;
++ return 1;
+ }
+ }
+- return false;
++ return 0;
+ }
+
+ static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data,
+ int reg, u32 mask, u32 write)
+ {
+- u32 read;
++ u32 val;
+ __ew32(&adapter->hw, reg, write & mask);
+- read = __er32(&adapter->hw, reg);
+- if ((write & mask) != (read & mask)) {
++ val = __er32(&adapter->hw, reg);
++ if ((write & mask) != (val & mask)) {
+ ndev_err(adapter->netdev, "set/check reg %04X test failed: "
+- "got 0x%08X expected 0x%08X\n", reg, (read & mask),
++ "got 0x%08X expected 0x%08X\n", reg, (val & mask),
+ (write & mask));
+ *data = reg;
+- return true;
++ return 1;
+ }
+- return false;
++ return 0;
+ }
+-
+-#define REG_PATTERN_TEST(R, M, W) \
+- do { \
+- if (reg_pattern_test_array(adapter, data, R, 0, M, W)) \
+- return 1; \
+- } while (0)
+-
+-#define REG_PATTERN_TEST_ARRAY(R, offset, M, W) \
+- do { \
+- if (reg_pattern_test_array(adapter, data, R, offset, M, W)) \
+- return 1; \
++#define REG_PATTERN_TEST_ARRAY(reg, offset, mask, write) \
++ do { \
++ if (reg_pattern_test(adapter, data, reg, offset, mask, write)) \
++ return 1; \
+ } while (0)
++#define REG_PATTERN_TEST(reg, mask, write) \
++ REG_PATTERN_TEST_ARRAY(reg, 0, mask, write)
+
+-#define REG_SET_AND_CHECK(R, M, W) \
+- do { \
+- if (reg_set_and_check(adapter, data, R, M, W)) \
+- return 1; \
++#define REG_SET_AND_CHECK(reg, mask, write) \
++ do { \
++ if (reg_set_and_check(adapter, data, reg, mask, write)) \
++ return 1; \
+ } while (0)
+
+ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
+@@ -758,7 +769,8 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
+ u32 i;
+ u32 toggle;
+
+- /* The status register is Read Only, so a write should fail.
++ /*
++ * The status register is Read Only, so a write should fail.
+ * Some bits that get toggled are ignored.
+ */
+ switch (mac->type) {
+@@ -908,7 +920,8 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
+ mask = 1 << i;
+
+ if (!shared_int) {
+- /* Disable the interrupt to be reported in
++ /*
++ * Disable the interrupt to be reported in
+ * the cause register and then force the same
+ * interrupt and see if one gets posted. If
+ * an interrupt was posted to the bus, the
+@@ -925,7 +938,8 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
+ }
+ }
+
+- /* Enable the interrupt to be reported in
++ /*
++ * Enable the interrupt to be reported in
+ * the cause register and then force the same
+ * interrupt and see if one gets posted. If
+ * an interrupt was not posted to the bus, the
+@@ -942,7 +956,8 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
+ }
+
+ if (!shared_int) {
+- /* Disable the other interrupts to be reported in
++ /*
++ * Disable the other interrupts to be reported in
+ * the cause register and then force the other
+ * interrupts and see if any get posted. If
+ * an interrupt was posted to the bus, the
+@@ -1024,7 +1039,6 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
+ struct pci_dev *pdev = adapter->pdev;
+ struct e1000_hw *hw = &adapter->hw;
+ u32 rctl;
+- int size;
+ int i;
+ int ret_val;
+
+@@ -1033,13 +1047,13 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
+ if (!tx_ring->count)
+ tx_ring->count = E1000_DEFAULT_TXD;
+
+- size = tx_ring->count * sizeof(struct e1000_buffer);
+- tx_ring->buffer_info = kmalloc(size, GFP_KERNEL);
+- if (!tx_ring->buffer_info) {
++ tx_ring->buffer_info = kcalloc(tx_ring->count,
++ sizeof(struct e1000_buffer),
++ GFP_KERNEL);
++ if (!(tx_ring->buffer_info)) {
+ ret_val = 1;
+ goto err_nomem;
+ }
+- memset(tx_ring->buffer_info, 0, size);
+
+ tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc);
+ tx_ring->size = ALIGN(tx_ring->size, 4096);
+@@ -1049,21 +1063,17 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
+ ret_val = 2;
+ goto err_nomem;
+ }
+- memset(tx_ring->desc, 0, tx_ring->size);
+ tx_ring->next_to_use = 0;
+ tx_ring->next_to_clean = 0;
+
+- ew32(TDBAL,
+- ((u64) tx_ring->dma & 0x00000000FFFFFFFF));
++ ew32(TDBAL, ((u64) tx_ring->dma & 0x00000000FFFFFFFF));
+ ew32(TDBAH, ((u64) tx_ring->dma >> 32));
+- ew32(TDLEN,
+- tx_ring->count * sizeof(struct e1000_tx_desc));
++ ew32(TDLEN, tx_ring->count * sizeof(struct e1000_tx_desc));
+ ew32(TDH, 0);
+ ew32(TDT, 0);
+- ew32(TCTL,
+- E1000_TCTL_PSP | E1000_TCTL_EN |
+- E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT |
+- E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT);
++ ew32(TCTL, E1000_TCTL_PSP | E1000_TCTL_EN | E1000_TCTL_MULR |
++ E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT |
++ E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT);
+
+ for (i = 0; i < tx_ring->count; i++) {
+ struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*tx_ring, i);
+@@ -1085,12 +1095,11 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
+ ret_val = 4;
+ goto err_nomem;
+ }
+- tx_desc->buffer_addr = cpu_to_le64(
+- tx_ring->buffer_info[i].dma);
++ tx_desc->buffer_addr = cpu_to_le64(tx_ring->buffer_info[i].dma);
+ tx_desc->lower.data = cpu_to_le32(skb->len);
+ tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP |
+ E1000_TXD_CMD_IFCS |
+- E1000_TXD_CMD_RPS);
++ E1000_TXD_CMD_RS);
+ tx_desc->upper.data = 0;
+ }
+
+@@ -1099,13 +1108,13 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
+ if (!rx_ring->count)
+ rx_ring->count = E1000_DEFAULT_RXD;
+
+- size = rx_ring->count * sizeof(struct e1000_buffer);
+- rx_ring->buffer_info = kmalloc(size, GFP_KERNEL);
+- if (!rx_ring->buffer_info) {
++ rx_ring->buffer_info = kcalloc(rx_ring->count,
++ sizeof(struct e1000_buffer),
++ GFP_KERNEL);
++ if (!(rx_ring->buffer_info)) {
+ ret_val = 5;
+ goto err_nomem;
+ }
+- memset(rx_ring->buffer_info, 0, size);
+
+ rx_ring->size = rx_ring->count * sizeof(struct e1000_rx_desc);
+ rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size,
+@@ -1114,7 +1123,6 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
+ ret_val = 6;
+ goto err_nomem;
+ }
+- memset(rx_ring->desc, 0, rx_ring->size);
+ rx_ring->next_to_use = 0;
+ rx_ring->next_to_clean = 0;
+
+@@ -1126,6 +1134,8 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
+ ew32(RDH, 0);
+ ew32(RDT, 0);
+ rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 |
++ E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_LPE |
++ E1000_RCTL_SBP | E1000_RCTL_SECRC |
+ E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
+ (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT);
+ ew32(RCTL, rctl);
+@@ -1175,21 +1185,22 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
+ u32 ctrl_reg = 0;
+ u32 stat_reg = 0;
+
+- adapter->hw.mac.autoneg = 0;
++ hw->mac.autoneg = 0;
+
+- if (adapter->hw.phy.type == e1000_phy_m88) {
++ if (hw->phy.type == e1000_phy_m88) {
+ /* Auto-MDI/MDIX Off */
+ e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, 0x0808);
+ /* reset to update Auto-MDI/MDIX */
+ e1e_wphy(hw, PHY_CONTROL, 0x9140);
+ /* autoneg off */
+ e1e_wphy(hw, PHY_CONTROL, 0x8140);
+- } else if (adapter->hw.phy.type == e1000_phy_gg82563)
++ } else if (hw->phy.type == e1000_phy_gg82563)
+ e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x1CC);
+
+ ctrl_reg = er32(CTRL);
+
+- if (adapter->hw.phy.type == e1000_phy_ife) {
++ switch (hw->phy.type) {
++ case e1000_phy_ife:
+ /* force 100, set loopback */
+ e1e_wphy(hw, PHY_CONTROL, 0x6100);
+
+@@ -1199,9 +1210,11 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
+ E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
+ E1000_CTRL_SPD_100 |/* Force Speed to 100 */
+ E1000_CTRL_FD); /* Force Duplex to FULL */
+- } else {
++ break;
++ default:
+ /* force 1000, set loopback */
+ e1e_wphy(hw, PHY_CONTROL, 0x4140);
++ mdelay(250);
+
+ /* Now set up the MAC to the same speed/duplex as the PHY. */
+ ctrl_reg = er32(CTRL);
+@@ -1210,14 +1223,20 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
+ E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
+ E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */
+ E1000_CTRL_FD); /* Force Duplex to FULL */
++
++ if ((adapter->hw.mac.type == e1000_ich8lan) ||
++ (adapter->hw.mac.type == e1000_ich9lan))
++ ctrl_reg |= E1000_CTRL_SLU; /* Set Link Up */
+ }
+
+- if (adapter->hw.media_type == e1000_media_type_copper &&
+- adapter->hw.phy.type == e1000_phy_m88) {
++ if (hw->phy.media_type == e1000_media_type_copper &&
++ hw->phy.type == e1000_phy_m88) {
+ ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */
+ } else {
+- /* Set the ILOS bit on the fiber Nic if half duplex link is
+- * detected. */
++ /*
++ * Set the ILOS bit on the fiber Nic if half duplex link is
++ * detected.
++ */
+ stat_reg = er32(STATUS);
+ if ((stat_reg & E1000_STATUS_FD) == 0)
+ ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU);
+@@ -1225,10 +1244,11 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
+
+ ew32(CTRL, ctrl_reg);
+
+- /* Disable the receiver on the PHY so when a cable is plugged in, the
++ /*
++ * Disable the receiver on the PHY so when a cable is plugged in, the
+ * PHY does not begin to autoneg when a cable is reconnected to the NIC.
+ */
+- if (adapter->hw.phy.type == e1000_phy_m88)
++ if (hw->phy.type == e1000_phy_m88)
+ e1000_phy_disable_receiver(adapter);
+
+ udelay(500);
+@@ -1244,8 +1264,10 @@ static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter)
+
+ /* special requirements for 82571/82572 fiber adapters */
+
+- /* jump through hoops to make sure link is up because serdes
+- * link is hardwired up */
++ /*
++ * jump through hoops to make sure link is up because serdes
++ * link is hardwired up
++ */
+ ctrl |= E1000_CTRL_SLU;
+ ew32(CTRL, ctrl);
+
+@@ -1263,8 +1285,10 @@ static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter)
+ ew32(CTRL, ctrl);
+ }
+
+- /* special write to serdes control register to enable SerDes analog
+- * loopback */
++ /*
++ * special write to serdes control register to enable SerDes analog
++ * loopback
++ */
+ #define E1000_SERDES_LB_ON 0x410
+ ew32(SCTL, E1000_SERDES_LB_ON);
+ msleep(10);
+@@ -1279,8 +1303,10 @@ static int e1000_set_es2lan_mac_loopback(struct e1000_adapter *adapter)
+ u32 ctrlext = er32(CTRL_EXT);
+ u32 ctrl = er32(CTRL);
+
+- /* save CTRL_EXT to restore later, reuse an empty variable (unused
+- on mac_type 80003es2lan) */
++ /*
++ * save CTRL_EXT to restore later, reuse an empty variable (unused
++ * on mac_type 80003es2lan)
++ */
+ adapter->tx_fifo_head = ctrlext;
+
+ /* clear the serdes mode bits, putting the device into mac loopback */
+@@ -1302,7 +1328,7 @@ static int e1000_set_es2lan_mac_loopback(struct e1000_adapter *adapter)
+ #define KMRNCTRLSTA_OPMODE (0x1F << 16)
+ #define KMRNCTRLSTA_OPMODE_1GB_FD_GMII 0x0582
+ ew32(KMRNCTRLSTA,
+- (KMRNCTRLSTA_OPMODE | KMRNCTRLSTA_OPMODE_1GB_FD_GMII));
++ (KMRNCTRLSTA_OPMODE | KMRNCTRLSTA_OPMODE_1GB_FD_GMII));
+
+ return 0;
+ }
+@@ -1312,8 +1338,8 @@ static int e1000_setup_loopback_test(struct e1000_adapter *adapter)
+ struct e1000_hw *hw = &adapter->hw;
+ u32 rctl;
+
+- if (hw->media_type == e1000_media_type_fiber ||
+- hw->media_type == e1000_media_type_internal_serdes) {
++ if (hw->phy.media_type == e1000_media_type_fiber ||
++ hw->phy.media_type == e1000_media_type_internal_serdes) {
+ switch (hw->mac.type) {
+ case e1000_80003es2lan:
+ return e1000_set_es2lan_mac_loopback(adapter);
+@@ -1328,7 +1354,7 @@ static int e1000_setup_loopback_test(struct e1000_adapter *adapter)
+ ew32(RCTL, rctl);
+ return 0;
+ }
+- } else if (hw->media_type == e1000_media_type_copper) {
++ } else if (hw->phy.media_type == e1000_media_type_copper) {
+ return e1000_integrated_phy_loopback(adapter);
+ }
+
+@@ -1347,18 +1373,17 @@ static void e1000_loopback_cleanup(struct e1000_adapter *adapter)
+
+ switch (hw->mac.type) {
+ case e1000_80003es2lan:
+- if (hw->media_type == e1000_media_type_fiber ||
+- hw->media_type == e1000_media_type_internal_serdes) {
++ if (hw->phy.media_type == e1000_media_type_fiber ||
++ hw->phy.media_type == e1000_media_type_internal_serdes) {
+ /* restore CTRL_EXT, stealing space from tx_fifo_head */
+- ew32(CTRL_EXT,
+- adapter->tx_fifo_head);
++ ew32(CTRL_EXT, adapter->tx_fifo_head);
+ adapter->tx_fifo_head = 0;
+ }
+ /* fall through */
+ case e1000_82571:
+ case e1000_82572:
+- if (hw->media_type == e1000_media_type_fiber ||
+- hw->media_type == e1000_media_type_internal_serdes) {
++ if (hw->phy.media_type == e1000_media_type_fiber ||
++ hw->phy.media_type == e1000_media_type_internal_serdes) {
+ #define E1000_SERDES_LB_OFF 0x400
+ ew32(SCTL, E1000_SERDES_LB_OFF);
+ msleep(10);
+@@ -1414,7 +1439,8 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
+
+ ew32(RDT, rx_ring->count - 1);
+
+- /* Calculate the loop count based on the largest descriptor ring
++ /*
++ * Calculate the loop count based on the largest descriptor ring
+ * The idea is to wrap the largest ring a number of times using 64
+ * send/receive pairs during each loop
+ */
+@@ -1428,8 +1454,8 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
+ l = 0;
+ for (j = 0; j <= lc; j++) { /* loop count loop */
+ for (i = 0; i < 64; i++) { /* send the packets */
+- e1000_create_lbtest_frame(
+- tx_ring->buffer_info[i].skb, 1024);
++ e1000_create_lbtest_frame(tx_ring->buffer_info[k].skb,
++ 1024);
+ pci_dma_sync_single_for_device(pdev,
+ tx_ring->buffer_info[k].dma,
+ tx_ring->buffer_info[k].length,
+@@ -1454,7 +1480,8 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
+ l++;
+ if (l == rx_ring->count)
+ l = 0;
+- /* time + 20 msecs (200 msecs on 2.4) is more than
++ /*
++ * time + 20 msecs (200 msecs on 2.4) is more than
+ * enough time to complete the receives, if it's
+ * exceeded, break and error off
+ */
+@@ -1463,7 +1490,7 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
+ ret_val = 13; /* ret_val is the same as mis-compare */
+ break;
+ }
+- if (jiffies >= (time + 2)) {
++ if (jiffies >= (time + 20)) {
+ ret_val = 14; /* error code for time out error */
+ break;
+ }
+@@ -1473,8 +1500,10 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
+
+ static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data)
+ {
+- /* PHY loopback cannot be performed if SoL/IDER
+- * sessions are active */
++ /*
++ * PHY loopback cannot be performed if SoL/IDER
++ * sessions are active
++ */
+ if (e1000_check_reset_block(&adapter->hw)) {
+ ndev_err(adapter->netdev, "Cannot do PHY loopback test "
+ "when SoL/IDER is active.\n");
+@@ -1504,12 +1533,14 @@ static int e1000_link_test(struct e1000_adapter *adapter, u64 *data)
+ struct e1000_hw *hw = &adapter->hw;
+
+ *data = 0;
+- if (hw->media_type == e1000_media_type_internal_serdes) {
++ if (hw->phy.media_type == e1000_media_type_internal_serdes) {
+ int i = 0;
+ hw->mac.serdes_has_link = 0;
+
+- /* On some blade server designs, link establishment
+- * could take as long as 2-3 minutes */
++ /*
++ * On some blade server designs, link establishment
++ * could take as long as 2-3 minutes
++ */
+ do {
+ hw->mac.ops.check_for_link(hw);
+ if (hw->mac.serdes_has_link)
+@@ -1562,8 +1593,10 @@ static void e1000_diag_test(struct net_device *netdev,
+
+ ndev_info(netdev, "offline testing starting\n");
+
+- /* Link test performed before hardware reset so autoneg doesn't
+- * interfere with test result */
++ /*
++ * Link test performed before hardware reset so autoneg doesn't
++ * interfere with test result
++ */
+ if (e1000_link_test(adapter, &data[4]))
+ eth_test->flags |= ETH_TEST_FL_FAILED;
+
+@@ -1596,9 +1629,9 @@ static void e1000_diag_test(struct net_device *netdev,
+ adapter->hw.mac.autoneg = autoneg;
+
+ /* force this routine to wait until autoneg complete/timeout */
+- adapter->hw.phy.wait_for_link = 1;
++ adapter->hw.phy.autoneg_wait_to_complete = 1;
+ e1000e_reset(adapter);
+- adapter->hw.phy.wait_for_link = 0;
++ adapter->hw.phy.autoneg_wait_to_complete = 0;
+
+ clear_bit(__E1000_TESTING, &adapter->state);
+ if (if_running)
+@@ -1737,6 +1770,47 @@ static int e1000_phys_id(struct net_device *netdev, u32 data)
+ return 0;
+ }
+
++static int e1000_get_coalesce(struct net_device *netdev,
++ struct ethtool_coalesce *ec)
++{
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++
++ if (adapter->itr_setting <= 3)
++ ec->rx_coalesce_usecs = adapter->itr_setting;
++ else
++ ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting;
++
++ return 0;
++}
++
++static int e1000_set_coalesce(struct net_device *netdev,
++ struct ethtool_coalesce *ec)
++{
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++ struct e1000_hw *hw = &adapter->hw;
++
++ if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) ||
++ ((ec->rx_coalesce_usecs > 3) &&
++ (ec->rx_coalesce_usecs < E1000_MIN_ITR_USECS)) ||
++ (ec->rx_coalesce_usecs == 2))
++ return -EINVAL;
++
++ if (ec->rx_coalesce_usecs <= 3) {
++ adapter->itr = 20000;
++ adapter->itr_setting = ec->rx_coalesce_usecs;
++ } else {
++ adapter->itr = (1000000 / ec->rx_coalesce_usecs);
++ adapter->itr_setting = adapter->itr & ~3;
++ }
++
++ if (adapter->itr_setting != 0)
++ ew32(ITR, 1000000000 / (adapter->itr * 256));
++ else
++ ew32(ITR, 0);
++
++ return 0;
++}
++
+ static int e1000_nway_reset(struct net_device *netdev)
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+@@ -1768,8 +1842,7 @@ static void e1000_get_strings(struct net_device *netdev, u32 stringset,
+
+ switch (stringset) {
+ case ETH_SS_TEST:
+- memcpy(data, *e1000_gstrings_test,
+- sizeof(e1000_gstrings_test));
++ memcpy(data, *e1000_gstrings_test, sizeof(e1000_gstrings_test));
+ break;
+ case ETH_SS_STATS:
+ for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
+@@ -1813,6 +1886,8 @@ static const struct ethtool_ops e1000_ethtool_ops = {
+ .phys_id = e1000_phys_id,
+ .get_ethtool_stats = e1000_get_ethtool_stats,
+ .get_sset_count = e1000e_get_sset_count,
++ .get_coalesce = e1000_get_coalesce,
++ .set_coalesce = e1000_set_coalesce,
+ };
+
+ void e1000e_set_ethtool_ops(struct net_device *netdev)
+diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
+index 916025b..a930e6d 100644
+--- a/drivers/net/e1000e/hw.h
++++ b/drivers/net/e1000e/hw.h
+@@ -1,7 +1,7 @@
+ /*******************************************************************************
+
+ Intel PRO/1000 Linux driver
+- Copyright(c) 1999 - 2007 Intel Corporation.
++ Copyright(c) 1999 - 2008 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+@@ -66,14 +66,14 @@ enum e1e_registers {
+ E1000_IMS = 0x000D0, /* Interrupt Mask Set - RW */
+ E1000_IMC = 0x000D8, /* Interrupt Mask Clear - WO */
+ E1000_IAM = 0x000E0, /* Interrupt Acknowledge Auto Mask */
+- E1000_RCTL = 0x00100, /* RX Control - RW */
++ E1000_RCTL = 0x00100, /* Rx Control - RW */
+ E1000_FCTTV = 0x00170, /* Flow Control Transmit Timer Value - RW */
+- E1000_TXCW = 0x00178, /* TX Configuration Word - RW */
+- E1000_RXCW = 0x00180, /* RX Configuration Word - RO */
+- E1000_TCTL = 0x00400, /* TX Control - RW */
+- E1000_TCTL_EXT = 0x00404, /* Extended TX Control - RW */
+- E1000_TIPG = 0x00410, /* TX Inter-packet gap -RW */
+- E1000_AIT = 0x00458, /* Adaptive Interframe Spacing Throttle - RW */
++ E1000_TXCW = 0x00178, /* Tx Configuration Word - RW */
++ E1000_RXCW = 0x00180, /* Rx Configuration Word - RO */
++ E1000_TCTL = 0x00400, /* Tx Control - RW */
++ E1000_TCTL_EXT = 0x00404, /* Extended Tx Control - RW */
++ E1000_TIPG = 0x00410, /* Tx Inter-packet gap -RW */
++ E1000_AIT = 0x00458, /* Adaptive Interframe Spacing Throttle -RW */
+ E1000_LEDCTL = 0x00E00, /* LED Control - RW */
+ E1000_EXTCNF_CTRL = 0x00F00, /* Extended Configuration Control */
+ E1000_EXTCNF_SIZE = 0x00F08, /* Extended Configuration Size */
+@@ -87,12 +87,14 @@ enum e1e_registers {
+ E1000_FCRTL = 0x02160, /* Flow Control Receive Threshold Low - RW */
+ E1000_FCRTH = 0x02168, /* Flow Control Receive Threshold High - RW */
+ E1000_PSRCTL = 0x02170, /* Packet Split Receive Control - RW */
+- E1000_RDBAL = 0x02800, /* RX Descriptor Base Address Low - RW */
+- E1000_RDBAH = 0x02804, /* RX Descriptor Base Address High - RW */
+- E1000_RDLEN = 0x02808, /* RX Descriptor Length - RW */
+- E1000_RDH = 0x02810, /* RX Descriptor Head - RW */
+- E1000_RDT = 0x02818, /* RX Descriptor Tail - RW */
+- E1000_RDTR = 0x02820, /* RX Delay Timer - RW */
++ E1000_RDBAL = 0x02800, /* Rx Descriptor Base Address Low - RW */
++ E1000_RDBAH = 0x02804, /* Rx Descriptor Base Address High - RW */
++ E1000_RDLEN = 0x02808, /* Rx Descriptor Length - RW */
++ E1000_RDH = 0x02810, /* Rx Descriptor Head - RW */
++ E1000_RDT = 0x02818, /* Rx Descriptor Tail - RW */
++ E1000_RDTR = 0x02820, /* Rx Delay Timer - RW */
++ E1000_RXDCTL_BASE = 0x02828, /* Rx Descriptor Control - RW */
++#define E1000_RXDCTL(_n) (E1000_RXDCTL_BASE + (_n << 8))
+ E1000_RADV = 0x0282C, /* RX Interrupt Absolute Delay Timer - RW */
+
+ /* Convenience macros
+@@ -105,17 +107,17 @@ enum e1e_registers {
+ */
+ #define E1000_RDBAL_REG(_n) (E1000_RDBAL + (_n << 8))
+ E1000_KABGTXD = 0x03004, /* AFE Band Gap Transmit Ref Data */
+- E1000_TDBAL = 0x03800, /* TX Descriptor Base Address Low - RW */
+- E1000_TDBAH = 0x03804, /* TX Descriptor Base Address High - RW */
+- E1000_TDLEN = 0x03808, /* TX Descriptor Length - RW */
+- E1000_TDH = 0x03810, /* TX Descriptor Head - RW */
+- E1000_TDT = 0x03818, /* TX Descriptor Tail - RW */
+- E1000_TIDV = 0x03820, /* TX Interrupt Delay Value - RW */
+- E1000_TXDCTL = 0x03828, /* TX Descriptor Control - RW */
+- E1000_TADV = 0x0382C, /* TX Interrupt Absolute Delay Val - RW */
+- E1000_TARC0 = 0x03840, /* TX Arbitration Count (0) */
+- E1000_TXDCTL1 = 0x03928, /* TX Descriptor Control (1) - RW */
+- E1000_TARC1 = 0x03940, /* TX Arbitration Count (1) */
++ E1000_TDBAL = 0x03800, /* Tx Descriptor Base Address Low - RW */
++ E1000_TDBAH = 0x03804, /* Tx Descriptor Base Address High - RW */
++ E1000_TDLEN = 0x03808, /* Tx Descriptor Length - RW */
++ E1000_TDH = 0x03810, /* Tx Descriptor Head - RW */
++ E1000_TDT = 0x03818, /* Tx Descriptor Tail - RW */
++ E1000_TIDV = 0x03820, /* Tx Interrupt Delay Value - RW */
++ E1000_TXDCTL_BASE = 0x03828, /* Tx Descriptor Control - RW */
++#define E1000_TXDCTL(_n) (E1000_TXDCTL_BASE + (_n << 8))
++ E1000_TADV = 0x0382C, /* Tx Interrupt Absolute Delay Val - RW */
++ E1000_TARC_BASE = 0x03840, /* Tx Arbitration Count (0) */
++#define E1000_TARC(_n) (E1000_TARC_BASE + (_n << 8))
+ E1000_CRCERRS = 0x04000, /* CRC Error Count - R/clr */
+ E1000_ALGNERRC = 0x04004, /* Alignment Error Count - R/clr */
+ E1000_SYMERRS = 0x04008, /* Symbol Error Count - R/clr */
+@@ -127,53 +129,53 @@ enum e1e_registers {
+ E1000_LATECOL = 0x04020, /* Late Collision Count - R/clr */
+ E1000_COLC = 0x04028, /* Collision Count - R/clr */
+ E1000_DC = 0x04030, /* Defer Count - R/clr */
+- E1000_TNCRS = 0x04034, /* TX-No CRS - R/clr */
++ E1000_TNCRS = 0x04034, /* Tx-No CRS - R/clr */
+ E1000_SEC = 0x04038, /* Sequence Error Count - R/clr */
+ E1000_CEXTERR = 0x0403C, /* Carrier Extension Error Count - R/clr */
+ E1000_RLEC = 0x04040, /* Receive Length Error Count - R/clr */
+- E1000_XONRXC = 0x04048, /* XON RX Count - R/clr */
+- E1000_XONTXC = 0x0404C, /* XON TX Count - R/clr */
+- E1000_XOFFRXC = 0x04050, /* XOFF RX Count - R/clr */
+- E1000_XOFFTXC = 0x04054, /* XOFF TX Count - R/clr */
+- E1000_FCRUC = 0x04058, /* Flow Control RX Unsupported Count- R/clr */
+- E1000_PRC64 = 0x0405C, /* Packets RX (64 bytes) - R/clr */
+- E1000_PRC127 = 0x04060, /* Packets RX (65-127 bytes) - R/clr */
+- E1000_PRC255 = 0x04064, /* Packets RX (128-255 bytes) - R/clr */
+- E1000_PRC511 = 0x04068, /* Packets RX (255-511 bytes) - R/clr */
+- E1000_PRC1023 = 0x0406C, /* Packets RX (512-1023 bytes) - R/clr */
+- E1000_PRC1522 = 0x04070, /* Packets RX (1024-1522 bytes) - R/clr */
+- E1000_GPRC = 0x04074, /* Good Packets RX Count - R/clr */
+- E1000_BPRC = 0x04078, /* Broadcast Packets RX Count - R/clr */
+- E1000_MPRC = 0x0407C, /* Multicast Packets RX Count - R/clr */
+- E1000_GPTC = 0x04080, /* Good Packets TX Count - R/clr */
+- E1000_GORCL = 0x04088, /* Good Octets RX Count Low - R/clr */
+- E1000_GORCH = 0x0408C, /* Good Octets RX Count High - R/clr */
+- E1000_GOTCL = 0x04090, /* Good Octets TX Count Low - R/clr */
+- E1000_GOTCH = 0x04094, /* Good Octets TX Count High - R/clr */
+- E1000_RNBC = 0x040A0, /* RX No Buffers Count - R/clr */
+- E1000_RUC = 0x040A4, /* RX Undersize Count - R/clr */
+- E1000_RFC = 0x040A8, /* RX Fragment Count - R/clr */
+- E1000_ROC = 0x040AC, /* RX Oversize Count - R/clr */
+- E1000_RJC = 0x040B0, /* RX Jabber Count - R/clr */
+- E1000_MGTPRC = 0x040B4, /* Management Packets RX Count - R/clr */
++ E1000_XONRXC = 0x04048, /* XON Rx Count - R/clr */
++ E1000_XONTXC = 0x0404C, /* XON Tx Count - R/clr */
++ E1000_XOFFRXC = 0x04050, /* XOFF Rx Count - R/clr */
++ E1000_XOFFTXC = 0x04054, /* XOFF Tx Count - R/clr */
++ E1000_FCRUC = 0x04058, /* Flow Control Rx Unsupported Count- R/clr */
++ E1000_PRC64 = 0x0405C, /* Packets Rx (64 bytes) - R/clr */
++ E1000_PRC127 = 0x04060, /* Packets Rx (65-127 bytes) - R/clr */
++ E1000_PRC255 = 0x04064, /* Packets Rx (128-255 bytes) - R/clr */
++ E1000_PRC511 = 0x04068, /* Packets Rx (255-511 bytes) - R/clr */
++ E1000_PRC1023 = 0x0406C, /* Packets Rx (512-1023 bytes) - R/clr */
++ E1000_PRC1522 = 0x04070, /* Packets Rx (1024-1522 bytes) - R/clr */
++ E1000_GPRC = 0x04074, /* Good Packets Rx Count - R/clr */
++ E1000_BPRC = 0x04078, /* Broadcast Packets Rx Count - R/clr */
++ E1000_MPRC = 0x0407C, /* Multicast Packets Rx Count - R/clr */
++ E1000_GPTC = 0x04080, /* Good Packets Tx Count - R/clr */
++ E1000_GORCL = 0x04088, /* Good Octets Rx Count Low - R/clr */
++ E1000_GORCH = 0x0408C, /* Good Octets Rx Count High - R/clr */
++ E1000_GOTCL = 0x04090, /* Good Octets Tx Count Low - R/clr */
++ E1000_GOTCH = 0x04094, /* Good Octets Tx Count High - R/clr */
++ E1000_RNBC = 0x040A0, /* Rx No Buffers Count - R/clr */
++ E1000_RUC = 0x040A4, /* Rx Undersize Count - R/clr */
++ E1000_RFC = 0x040A8, /* Rx Fragment Count - R/clr */
++ E1000_ROC = 0x040AC, /* Rx Oversize Count - R/clr */
++ E1000_RJC = 0x040B0, /* Rx Jabber Count - R/clr */
++ E1000_MGTPRC = 0x040B4, /* Management Packets Rx Count - R/clr */
+ E1000_MGTPDC = 0x040B8, /* Management Packets Dropped Count - R/clr */
+- E1000_MGTPTC = 0x040BC, /* Management Packets TX Count - R/clr */
+- E1000_TORL = 0x040C0, /* Total Octets RX Low - R/clr */
+- E1000_TORH = 0x040C4, /* Total Octets RX High - R/clr */
+- E1000_TOTL = 0x040C8, /* Total Octets TX Low - R/clr */
+- E1000_TOTH = 0x040CC, /* Total Octets TX High - R/clr */
+- E1000_TPR = 0x040D0, /* Total Packets RX - R/clr */
+- E1000_TPT = 0x040D4, /* Total Packets TX - R/clr */
+- E1000_PTC64 = 0x040D8, /* Packets TX (64 bytes) - R/clr */
+- E1000_PTC127 = 0x040DC, /* Packets TX (65-127 bytes) - R/clr */
+- E1000_PTC255 = 0x040E0, /* Packets TX (128-255 bytes) - R/clr */
+- E1000_PTC511 = 0x040E4, /* Packets TX (256-511 bytes) - R/clr */
+- E1000_PTC1023 = 0x040E8, /* Packets TX (512-1023 bytes) - R/clr */
+- E1000_PTC1522 = 0x040EC, /* Packets TX (1024-1522 Bytes) - R/clr */
+- E1000_MPTC = 0x040F0, /* Multicast Packets TX Count - R/clr */
+- E1000_BPTC = 0x040F4, /* Broadcast Packets TX Count - R/clr */
+- E1000_TSCTC = 0x040F8, /* TCP Segmentation Context TX - R/clr */
+- E1000_TSCTFC = 0x040FC, /* TCP Segmentation Context TX Fail - R/clr */
++ E1000_MGTPTC = 0x040BC, /* Management Packets Tx Count - R/clr */
++ E1000_TORL = 0x040C0, /* Total Octets Rx Low - R/clr */
++ E1000_TORH = 0x040C4, /* Total Octets Rx High - R/clr */
++ E1000_TOTL = 0x040C8, /* Total Octets Tx Low - R/clr */
++ E1000_TOTH = 0x040CC, /* Total Octets Tx High - R/clr */
++ E1000_TPR = 0x040D0, /* Total Packets Rx - R/clr */
++ E1000_TPT = 0x040D4, /* Total Packets Tx - R/clr */
++ E1000_PTC64 = 0x040D8, /* Packets Tx (64 bytes) - R/clr */
++ E1000_PTC127 = 0x040DC, /* Packets Tx (65-127 bytes) - R/clr */
++ E1000_PTC255 = 0x040E0, /* Packets Tx (128-255 bytes) - R/clr */
++ E1000_PTC511 = 0x040E4, /* Packets Tx (256-511 bytes) - R/clr */
++ E1000_PTC1023 = 0x040E8, /* Packets Tx (512-1023 bytes) - R/clr */
++ E1000_PTC1522 = 0x040EC, /* Packets Tx (1024-1522 Bytes) - R/clr */
++ E1000_MPTC = 0x040F0, /* Multicast Packets Tx Count - R/clr */
++ E1000_BPTC = 0x040F4, /* Broadcast Packets Tx Count - R/clr */
++ E1000_TSCTC = 0x040F8, /* TCP Segmentation Context Tx - R/clr */
++ E1000_TSCTFC = 0x040FC, /* TCP Segmentation Context Tx Fail - R/clr */
+ E1000_IAC = 0x04100, /* Interrupt Assertion Count */
+ E1000_ICRXPTC = 0x04104, /* Irq Cause Rx Packet Timer Expire Count */
+ E1000_ICRXATC = 0x04108, /* Irq Cause Rx Abs Timer Expire Count */
+@@ -183,7 +185,7 @@ enum e1e_registers {
+ E1000_ICTXQMTC = 0x0411C, /* Irq Cause Tx Queue MinThreshold Count */
+ E1000_ICRXDMTC = 0x04120, /* Irq Cause Rx Desc MinThreshold Count */
+ E1000_ICRXOC = 0x04124, /* Irq Cause Receiver Overrun Count */
+- E1000_RXCSUM = 0x05000, /* RX Checksum Control - RW */
++ E1000_RXCSUM = 0x05000, /* Rx Checksum Control - RW */
+ E1000_RFCTL = 0x05008, /* Receive Filter Control */
+ E1000_MTA = 0x05200, /* Multicast Table Array - RW Array */
+ E1000_RA = 0x05400, /* Receive Address - RW Array */
+@@ -250,8 +252,8 @@ enum e1e_registers {
+ #define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F
+
+ #define E1000_HICR_EN 0x01 /* Enable bit - RO */
+-#define E1000_HICR_C 0x02 /* Driver sets this bit when done
+- * to put command in RAM */
++/* Driver sets this bit when done to put command in RAM */
++#define E1000_HICR_C 0x02
+ #define E1000_HICR_FW_RESET_ENABLE 0x40
+ #define E1000_HICR_FW_RESET 0x80
+
+@@ -400,7 +402,7 @@ enum e1000_rev_polarity{
+ e1000_rev_polarity_undefined = 0xFF
+ };
+
+-enum e1000_fc_mode {
++enum e1000_fc_type {
+ e1000_fc_none = 0,
+ e1000_fc_rx_pause,
+ e1000_fc_tx_pause,
+@@ -590,10 +592,8 @@ struct e1000_hw_stats {
+ u64 bprc;
+ u64 mprc;
+ u64 gptc;
+- u64 gorcl;
+- u64 gorch;
+- u64 gotcl;
+- u64 gotch;
++ u64 gorc;
++ u64 gotc;
+ u64 rnbc;
+ u64 ruc;
+ u64 rfc;
+@@ -602,10 +602,8 @@ struct e1000_hw_stats {
+ u64 mgprc;
+ u64 mgpdc;
+ u64 mgptc;
+- u64 torl;
+- u64 torh;
+- u64 totl;
+- u64 toth;
++ u64 tor;
++ u64 tot;
+ u64 tpr;
+ u64 tpt;
+ u64 ptc64;
+@@ -685,8 +683,7 @@ struct e1000_mac_operations {
+ s32 (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *);
+ s32 (*led_on)(struct e1000_hw *);
+ s32 (*led_off)(struct e1000_hw *);
+- void (*mc_addr_list_update)(struct e1000_hw *, u8 *, u32, u32,
+- u32);
++ void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32, u32, u32);
+ s32 (*reset_hw)(struct e1000_hw *);
+ s32 (*init_hw)(struct e1000_hw *);
+ s32 (*setup_link)(struct e1000_hw *);
+@@ -728,16 +725,12 @@ struct e1000_mac_info {
+ u8 perm_addr[6];
+
+ enum e1000_mac_type type;
+- enum e1000_fc_mode fc;
+- enum e1000_fc_mode original_fc;
+
+ u32 collision_delta;
+ u32 ledctl_default;
+ u32 ledctl_mode1;
+ u32 ledctl_mode2;
+- u32 max_frame_size;
+ u32 mc_filter_type;
+- u32 min_frame_size;
+ u32 tx_packet_delta;
+ u32 txcw;
+
+@@ -748,9 +741,6 @@ struct e1000_mac_info {
+ u16 ifs_step_size;
+ u16 mta_reg_count;
+ u16 rar_entry_count;
+- u16 fc_high_water;
+- u16 fc_low_water;
+- u16 fc_pause_time;
+
+ u8 forced_speed_duplex;
+
+@@ -780,6 +770,8 @@ struct e1000_phy_info {
+ u32 reset_delay_us; /* in usec */
+ u32 revision;
+
++ enum e1000_media_type media_type;
++
+ u16 autoneg_advertised;
+ u16 autoneg_mask;
+ u16 cable_length;
+@@ -792,7 +784,7 @@ struct e1000_phy_info {
+ bool is_mdix;
+ bool polarity_correction;
+ bool speed_downgraded;
+- bool wait_for_link;
++ bool autoneg_wait_to_complete;
+ };
+
+ struct e1000_nvm_info {
+@@ -817,6 +809,16 @@ struct e1000_bus_info {
+ u16 func;
+ };
+
++struct e1000_fc_info {
++ u32 high_water; /* Flow control high-water mark */
++ u32 low_water; /* Flow control low-water mark */
++ u16 pause_time; /* Flow control pause timer */
++ bool send_xon; /* Flow control send XON */
++ bool strict_ieee; /* Strict IEEE mode */
++ enum e1000_fc_type type; /* Type of flow control */
++ enum e1000_fc_type original_type;
++};
++
+ struct e1000_dev_spec_82571 {
+ bool laa_is_present;
+ bool alt_mac_addr_is_present;
+@@ -841,6 +843,7 @@ struct e1000_hw {
+ u8 __iomem *flash_address;
+
+ struct e1000_mac_info mac;
++ struct e1000_fc_info fc;
+ struct e1000_phy_info phy;
+ struct e1000_nvm_info nvm;
+ struct e1000_bus_info bus;
+@@ -850,8 +853,6 @@ struct e1000_hw {
+ struct e1000_dev_spec_82571 e82571;
+ struct e1000_dev_spec_ich8lan ich8lan;
+ } dev_spec;
+-
+- enum e1000_media_type media_type;
+ };
+
+ #ifdef DEBUG
+diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
+index 0ae3955..768485d 100644
+--- a/drivers/net/e1000e/ich8lan.c
++++ b/drivers/net/e1000e/ich8lan.c
+@@ -1,7 +1,7 @@
+ /*******************************************************************************
+
+ Intel PRO/1000 Linux driver
+- Copyright(c) 1999 - 2007 Intel Corporation.
++ Copyright(c) 1999 - 2008 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+@@ -243,8 +243,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
+ u32 sector_end_addr;
+ u16 i;
+
+- /* Can't read flash registers if the register set isn't mapped.
+- */
++ /* Can't read flash registers if the register set isn't mapped. */
+ if (!hw->flash_address) {
+ hw_dbg(hw, "ERROR: Flash registers not mapped\n");
+ return -E1000_ERR_CONFIG;
+@@ -254,17 +253,21 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
+
+ gfpreg = er32flash(ICH_FLASH_GFPREG);
+
+- /* sector_X_addr is a "sector"-aligned address (4096 bytes)
++ /*
++ * sector_X_addr is a "sector"-aligned address (4096 bytes)
+ * Add 1 to sector_end_addr since this sector is included in
+- * the overall size. */
++ * the overall size.
++ */
+ sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK;
+ sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1;
+
+ /* flash_base_addr is byte-aligned */
+ nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT;
+
+- /* find total size of the NVM, then cut in half since the total
+- * size represents two separate NVM banks. */
++ /*
++ * find total size of the NVM, then cut in half since the total
++ * size represents two separate NVM banks.
++ */
+ nvm->flash_bank_size = (sector_end_addr - sector_base_addr)
+ << FLASH_SECTOR_ADDR_SHIFT;
+ nvm->flash_bank_size /= 2;
+@@ -295,7 +298,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter)
+ struct e1000_mac_info *mac = &hw->mac;
+
+ /* Set media type function pointer */
+- hw->media_type = e1000_media_type_copper;
++ hw->phy.media_type = e1000_media_type_copper;
+
+ /* Set mta register count */
+ mac->mta_reg_count = 32;
+@@ -313,7 +316,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter)
+ return 0;
+ }
+
+-static s32 e1000_get_invariants_ich8lan(struct e1000_adapter *adapter)
++static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
+ {
+ struct e1000_hw *hw = &adapter->hw;
+ s32 rc;
+@@ -450,7 +453,7 @@ static s32 e1000_phy_force_speed_duplex_ich8lan(struct e1000_hw *hw)
+
+ udelay(1);
+
+- if (phy->wait_for_link) {
++ if (phy->autoneg_wait_to_complete) {
+ hw_dbg(hw, "Waiting for forced speed/duplex link on IFE phy.\n");
+
+ ret_val = e1000e_phy_has_link_generic(hw,
+@@ -496,7 +499,8 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
+ if (ret_val)
+ return ret_val;
+
+- /* Initialize the PHY from the NVM on ICH platforms. This
++ /*
++ * Initialize the PHY from the NVM on ICH platforms. This
+ * is needed due to an issue where the NVM configuration is
+ * not properly autoloaded after power transitions.
+ * Therefore, after each PHY reset, we will load the
+@@ -523,7 +527,8 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
+ udelay(100);
+ } while ((!data) && --loop);
+
+- /* If basic configuration is incomplete before the above loop
++ /*
++ * If basic configuration is incomplete before the above loop
+ * count reaches 0, loading the configuration from NVM will
+ * leave the PHY in a bad state possibly resulting in no link.
+ */
+@@ -536,8 +541,10 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
+ data &= ~E1000_STATUS_LAN_INIT_DONE;
+ ew32(STATUS, data);
+
+- /* Make sure HW does not configure LCD from PHY
+- * extended configuration before SW configuration */
++ /*
++ * Make sure HW does not configure LCD from PHY
++ * extended configuration before SW configuration
++ */
+ data = er32(EXTCNF_CTRL);
+ if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
+ return 0;
+@@ -551,8 +558,7 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
+ cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;
+ cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
+
+- /* Configure LCD from extended configuration
+- * region. */
++ /* Configure LCD from extended configuration region. */
+
+ /* cnf_base_addr is in DWORD */
+ word_addr = (u16)(cnf_base_addr << 1);
+@@ -681,8 +687,8 @@ static s32 e1000_check_polarity_ife_ich8lan(struct e1000_hw *hw)
+ s32 ret_val;
+ u16 phy_data, offset, mask;
+
+- /* Polarity is determined based on the reversal feature
+- * being enabled.
++ /*
++ * Polarity is determined based on the reversal feature being enabled.
+ */
+ if (phy->polarity_correction) {
+ offset = IFE_PHY_EXTENDED_STATUS_CONTROL;
+@@ -731,8 +737,10 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
+ phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU;
+ ew32(PHY_CTRL, phy_ctrl);
+
+- /* Call gig speed drop workaround on LPLU before accessing
+- * any PHY registers */
++ /*
++ * Call gig speed drop workaround on LPLU before accessing
++ * any PHY registers
++ */
+ if ((hw->mac.type == e1000_ich8lan) &&
+ (hw->phy.type == e1000_phy_igp_3))
+ e1000e_gig_downshift_workaround_ich8lan(hw);
+@@ -747,30 +755,32 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
+ phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU;
+ ew32(PHY_CTRL, phy_ctrl);
+
+- /* LPLU and SmartSpeed are mutually exclusive. LPLU is used
++ /*
++ * LPLU and SmartSpeed are mutually exclusive. LPLU is used
+ * during Dx states where the power conservation is most
+ * important. During driver activity we should enable
+- * SmartSpeed, so performance is maintained. */
++ * SmartSpeed, so performance is maintained.
++ */
+ if (phy->smart_speed == e1000_smart_speed_on) {
+ ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+- &data);
++ &data);
+ if (ret_val)
+ return ret_val;
+
+ data |= IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+- data);
++ data);
+ if (ret_val)
+ return ret_val;
+ } else if (phy->smart_speed == e1000_smart_speed_off) {
+ ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+- &data);
++ &data);
+ if (ret_val)
+ return ret_val;
+
+ data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+- data);
++ data);
+ if (ret_val)
+ return ret_val;
+ }
+@@ -804,34 +814,32 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
+ if (!active) {
+ phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU;
+ ew32(PHY_CTRL, phy_ctrl);
+- /* LPLU and SmartSpeed are mutually exclusive. LPLU is used
++ /*
++ * LPLU and SmartSpeed are mutually exclusive. LPLU is used
+ * during Dx states where the power conservation is most
+ * important. During driver activity we should enable
+- * SmartSpeed, so performance is maintained. */
++ * SmartSpeed, so performance is maintained.
++ */
+ if (phy->smart_speed == e1000_smart_speed_on) {
+- ret_val = e1e_rphy(hw,
+- IGP01E1000_PHY_PORT_CONFIG,
+- &data);
++ ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
++ &data);
+ if (ret_val)
+ return ret_val;
+
+ data |= IGP01E1000_PSCFR_SMART_SPEED;
+- ret_val = e1e_wphy(hw,
+- IGP01E1000_PHY_PORT_CONFIG,
+- data);
++ ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
++ data);
+ if (ret_val)
+ return ret_val;
+ } else if (phy->smart_speed == e1000_smart_speed_off) {
+- ret_val = e1e_rphy(hw,
+- IGP01E1000_PHY_PORT_CONFIG,
+- &data);
++ ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
++ &data);
+ if (ret_val)
+ return ret_val;
+
+ data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+- ret_val = e1e_wphy(hw,
+- IGP01E1000_PHY_PORT_CONFIG,
+- data);
++ ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
++ data);
+ if (ret_val)
+ return ret_val;
+ }
+@@ -841,23 +849,21 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
+ phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU;
+ ew32(PHY_CTRL, phy_ctrl);
+
+- /* Call gig speed drop workaround on LPLU before accessing
+- * any PHY registers */
++ /*
++ * Call gig speed drop workaround on LPLU before accessing
++ * any PHY registers
++ */
+ if ((hw->mac.type == e1000_ich8lan) &&
+ (hw->phy.type == e1000_phy_igp_3))
+ e1000e_gig_downshift_workaround_ich8lan(hw);
+
+ /* When LPLU is enabled, we should disable SmartSpeed */
+- ret_val = e1e_rphy(hw,
+- IGP01E1000_PHY_PORT_CONFIG,
+- &data);
++ ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, &data);
+ if (ret_val)
+ return ret_val;
+
+ data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+- ret_val = e1e_wphy(hw,
+- IGP01E1000_PHY_PORT_CONFIG,
+- data);
++ ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, data);
+ }
+
+ return 0;
+@@ -944,7 +950,8 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
+
+ ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
+
+- /* Either we should have a hardware SPI cycle in progress
++ /*
++ * Either we should have a hardware SPI cycle in progress
+ * bit to check against, in order to start a new cycle or
+ * FDONE bit should be changed in the hardware so that it
+ * is 1 after hardware reset, which can then be used as an
+@@ -953,15 +960,19 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
+ */
+
+ if (hsfsts.hsf_status.flcinprog == 0) {
+- /* There is no cycle running at present,
+- * so we can start a cycle */
+- /* Begin by setting Flash Cycle Done. */
++ /*
++ * There is no cycle running at present,
++ * so we can start a cycle
++ * Begin by setting Flash Cycle Done.
++ */
+ hsfsts.hsf_status.flcdone = 1;
+ ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
+ ret_val = 0;
+ } else {
+- /* otherwise poll for sometime so the current
+- * cycle has a chance to end before giving up. */
++ /*
++ * otherwise poll for sometime so the current
++ * cycle has a chance to end before giving up.
++ */
+ for (i = 0; i < ICH_FLASH_READ_COMMAND_TIMEOUT; i++) {
+ hsfsts.regval = __er16flash(hw, ICH_FLASH_HSFSTS);
+ if (hsfsts.hsf_status.flcinprog == 0) {
+@@ -971,8 +982,10 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
+ udelay(1);
+ }
+ if (ret_val == 0) {
+- /* Successful in waiting for previous cycle to timeout,
+- * now set the Flash Cycle Done. */
++ /*
++ * Successful in waiting for previous cycle to timeout,
++ * now set the Flash Cycle Done.
++ */
+ hsfsts.hsf_status.flcdone = 1;
+ ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
+ } else {
+@@ -1077,10 +1090,12 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
+ ret_val = e1000_flash_cycle_ich8lan(hw,
+ ICH_FLASH_READ_COMMAND_TIMEOUT);
+
+- /* Check if FCERR is set to 1, if set to 1, clear it
++ /*
++ * Check if FCERR is set to 1, if set to 1, clear it
+ * and try the whole sequence a few more times, else
+ * read in (shift in) the Flash Data0, the order is
+- * least significant byte first msb to lsb */
++ * least significant byte first msb to lsb
++ */
+ if (ret_val == 0) {
+ flash_data = er32flash(ICH_FLASH_FDATA0);
+ if (size == 1) {
+@@ -1090,7 +1105,8 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
+ }
+ break;
+ } else {
+- /* If we've gotten here, then things are probably
++ /*
++ * If we've gotten here, then things are probably
+ * completely hosed, but if the error condition is
+ * detected, it won't hurt to give it another try...
+ * ICH_FLASH_CYCLE_REPEAT_COUNT times.
+@@ -1168,18 +1184,20 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
+
+ ret_val = e1000e_update_nvm_checksum_generic(hw);
+ if (ret_val)
+- return ret_val;;
++ return ret_val;
+
+ if (nvm->type != e1000_nvm_flash_sw)
+- return ret_val;;
++ return ret_val;
+
+ ret_val = e1000_acquire_swflag_ich8lan(hw);
+ if (ret_val)
+- return ret_val;;
++ return ret_val;
+
+- /* We're writing to the opposite bank so if we're on bank 1,
++ /*
++ * We're writing to the opposite bank so if we're on bank 1,
+ * write to bank 0 etc. We also need to erase the segment that
+- * is going to be written */
++ * is going to be written
++ */
+ if (!(er32(EECD) & E1000_EECD_SEC1VAL)) {
+ new_bank_offset = nvm->flash_bank_size;
+ old_bank_offset = 0;
+@@ -1191,9 +1209,11 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
+ }
+
+ for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) {
+- /* Determine whether to write the value stored
++ /*
++ * Determine whether to write the value stored
+ * in the other NVM bank or a modified value stored
+- * in the shadow RAM */
++ * in the shadow RAM
++ */
+ if (dev_spec->shadow_ram[i].modified) {
+ data = dev_spec->shadow_ram[i].value;
+ } else {
+@@ -1202,12 +1222,14 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
+ &data);
+ }
+
+- /* If the word is 0x13, then make sure the signature bits
++ /*
++ * If the word is 0x13, then make sure the signature bits
+ * (15:14) are 11b until the commit has completed.
+ * This will allow us to write 10b which indicates the
+ * signature is valid. We want to do this after the write
+ * has completed so that we don't mark the segment valid
+- * while the write is still in progress */
++ * while the write is still in progress
++ */
+ if (i == E1000_ICH_NVM_SIG_WORD)
+ data |= E1000_ICH_NVM_SIG_MASK;
+
+@@ -1230,18 +1252,22 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
+ break;
+ }
+
+- /* Don't bother writing the segment valid bits if sector
+- * programming failed. */
++ /*
++ * Don't bother writing the segment valid bits if sector
++ * programming failed.
++ */
+ if (ret_val) {
+ hw_dbg(hw, "Flash commit failed.\n");
+ e1000_release_swflag_ich8lan(hw);
+ return ret_val;
+ }
+
+- /* Finally validate the new segment by setting bit 15:14
++ /*
++ * Finally validate the new segment by setting bit 15:14
+ * to 10b in word 0x13 , this can be done without an
+ * erase as well since these bits are 11 to start with
+- * and we need to change bit 14 to 0b */
++ * and we need to change bit 14 to 0b
++ */
+ act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD;
+ e1000_read_flash_word_ich8lan(hw, act_offset, &data);
+ data &= 0xBFFF;
+@@ -1253,10 +1279,12 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
+ return ret_val;
+ }
+
+- /* And invalidate the previously valid segment by setting
++ /*
++ * And invalidate the previously valid segment by setting
+ * its signature word (0x13) high_byte to 0b. This can be
+ * done without an erase because flash erase sets all bits
+- * to 1's. We can write 1's to 0's without an erase */
++ * to 1's. We can write 1's to 0's without an erase
++ */
+ act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1;
+ ret_val = e1000_retry_write_flash_byte_ich8lan(hw, act_offset, 0);
+ if (ret_val) {
+@@ -1272,7 +1300,8 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
+
+ e1000_release_swflag_ich8lan(hw);
+
+- /* Reload the EEPROM, or else modifications will not appear
++ /*
++ * Reload the EEPROM, or else modifications will not appear
+ * until after the next adapter reset.
+ */
+ e1000e_reload_nvm(hw);
+@@ -1294,7 +1323,8 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw)
+ s32 ret_val;
+ u16 data;
+
+- /* Read 0x19 and check bit 6. If this bit is 0, the checksum
++ /*
++ * Read 0x19 and check bit 6. If this bit is 0, the checksum
+ * needs to be fixed. This bit is an indication that the NVM
+ * was prepared by OEM software and did not calculate the
+ * checksum...a likely scenario.
+@@ -1364,14 +1394,17 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
+
+ ew32flash(ICH_FLASH_FDATA0, flash_data);
+
+- /* check if FCERR is set to 1 , if set to 1, clear it
+- * and try the whole sequence a few more times else done */
++ /*
++ * check if FCERR is set to 1 , if set to 1, clear it
++ * and try the whole sequence a few more times else done
++ */
+ ret_val = e1000_flash_cycle_ich8lan(hw,
+ ICH_FLASH_WRITE_COMMAND_TIMEOUT);
+ if (!ret_val)
+ break;
+
+- /* If we're here, then things are most likely
++ /*
++ * If we're here, then things are most likely
+ * completely hosed, but if the error condition
+ * is detected, it won't hurt to give it another
+ * try...ICH_FLASH_CYCLE_REPEAT_COUNT times.
+@@ -1462,9 +1495,10 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
+
+ hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
+
+- /* Determine HW Sector size: Read BERASE bits of hw flash status
+- * register */
+- /* 00: The Hw sector is 256 bytes, hence we need to erase 16
++ /*
++ * Determine HW Sector size: Read BERASE bits of hw flash status
++ * register
++ * 00: The Hw sector is 256 bytes, hence we need to erase 16
+ * consecutive sectors. The start index for the nth Hw sector
+ * can be calculated as = bank * 4096 + n * 256
+ * 01: The Hw sector is 4K bytes, hence we need to erase 1 sector.
+@@ -1511,13 +1545,16 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
+ if (ret_val)
+ return ret_val;
+
+- /* Write a value 11 (block Erase) in Flash
+- * Cycle field in hw flash control */
++ /*
++ * Write a value 11 (block Erase) in Flash
++ * Cycle field in hw flash control
++ */
+ hsflctl.regval = er16flash(ICH_FLASH_HSFCTL);
+ hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE;
+ ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval);
+
+- /* Write the last 24 bits of an index within the
++ /*
++ * Write the last 24 bits of an index within the
+ * block into Flash Linear address field in Flash
+ * Address.
+ */
+@@ -1529,13 +1566,14 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
+ if (ret_val == 0)
+ break;
+
+- /* Check if FCERR is set to 1. If 1,
++ /*
++ * Check if FCERR is set to 1. If 1,
+ * clear it and try the whole sequence
+- * a few more times else Done */
++ * a few more times else Done
++ */
+ hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
+ if (hsfsts.hsf_status.flcerr == 1)
+- /* repeat for some time before
+- * giving up */
++ /* repeat for some time before giving up */
+ continue;
+ else if (hsfsts.hsf_status.flcdone == 0)
+ return ret_val;
+@@ -1585,7 +1623,8 @@ static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw)
+
+ ret_val = e1000e_get_bus_info_pcie(hw);
+
+- /* ICH devices are "PCI Express"-ish. They have
++ /*
++ * ICH devices are "PCI Express"-ish. They have
+ * a configuration space, but do not contain
+ * PCI Express Capability registers, so bus width
+ * must be hardcoded.
+@@ -1608,7 +1647,8 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
+ u32 ctrl, icr, kab;
+ s32 ret_val;
+
+- /* Prevent the PCI-E bus from sticking if there is no TLP connection
++ /*
++ * Prevent the PCI-E bus from sticking if there is no TLP connection
+ * on the last TLP read/write transaction when MAC is reset.
+ */
+ ret_val = e1000e_disable_pcie_master(hw);
+@@ -1619,7 +1659,8 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
+ hw_dbg(hw, "Masking off all interrupts\n");
+ ew32(IMC, 0xffffffff);
+
+- /* Disable the Transmit and Receive units. Then delay to allow
++ /*
++ * Disable the Transmit and Receive units. Then delay to allow
+ * any pending transactions to complete before we hit the MAC
+ * with the global reset.
+ */
+@@ -1640,7 +1681,8 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
+ ctrl = er32(CTRL);
+
+ if (!e1000_check_reset_block(hw)) {
+- /* PHY HW reset requires MAC CORE reset at the same
++ /*
++ * PHY HW reset requires MAC CORE reset at the same
+ * time to make sure the interface between MAC and the
+ * external PHY is reset.
+ */
+@@ -1711,21 +1753,23 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
+ ret_val = e1000_setup_link_ich8lan(hw);
+
+ /* Set the transmit descriptor write-back policy for both queues */
+- txdctl = er32(TXDCTL);
++ txdctl = er32(TXDCTL(0));
+ txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
+ E1000_TXDCTL_FULL_TX_DESC_WB;
+ txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) |
+ E1000_TXDCTL_MAX_TX_DESC_PREFETCH;
+- ew32(TXDCTL, txdctl);
+- txdctl = er32(TXDCTL1);
++ ew32(TXDCTL(0), txdctl);
++ txdctl = er32(TXDCTL(1));
+ txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
+ E1000_TXDCTL_FULL_TX_DESC_WB;
+ txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) |
+ E1000_TXDCTL_MAX_TX_DESC_PREFETCH;
+- ew32(TXDCTL1, txdctl);
++ ew32(TXDCTL(1), txdctl);
+
+- /* ICH8 has opposite polarity of no_snoop bits.
+- * By default, we should use snoop behavior. */
++ /*
++ * ICH8 has opposite polarity of no_snoop bits.
++ * By default, we should use snoop behavior.
++ */
+ if (mac->type == e1000_ich8lan)
+ snoop = PCIE_ICH8_SNOOP_ALL;
+ else
+@@ -1736,7 +1780,8 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
+ ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
+ ew32(CTRL_EXT, ctrl_ext);
+
+- /* Clear all of the statistics registers (clear on read). It is
++ /*
++ * Clear all of the statistics registers (clear on read). It is
+ * important that we do this after we have tried to establish link
+ * because the symbol error count will increment wildly if there
+ * is no link.
+@@ -1762,30 +1807,30 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
+ ew32(CTRL_EXT, reg);
+
+ /* Transmit Descriptor Control 0 */
+- reg = er32(TXDCTL);
++ reg = er32(TXDCTL(0));
+ reg |= (1 << 22);
+- ew32(TXDCTL, reg);
++ ew32(TXDCTL(0), reg);
+
+ /* Transmit Descriptor Control 1 */
+- reg = er32(TXDCTL1);
++ reg = er32(TXDCTL(1));
+ reg |= (1 << 22);
+- ew32(TXDCTL1, reg);
++ ew32(TXDCTL(1), reg);
+
+ /* Transmit Arbitration Control 0 */
+- reg = er32(TARC0);
++ reg = er32(TARC(0));
+ if (hw->mac.type == e1000_ich8lan)
+ reg |= (1 << 28) | (1 << 29);
+ reg |= (1 << 23) | (1 << 24) | (1 << 26) | (1 << 27);
+- ew32(TARC0, reg);
++ ew32(TARC(0), reg);
+
+ /* Transmit Arbitration Control 1 */
+- reg = er32(TARC1);
++ reg = er32(TARC(1));
+ if (er32(TCTL) & E1000_TCTL_MULR)
+ reg &= ~(1 << 28);
+ else
+ reg |= (1 << 28);
+ reg |= (1 << 24) | (1 << 26) | (1 << 30);
+- ew32(TARC1, reg);
++ ew32(TARC(1), reg);
+
+ /* Device Status */
+ if (hw->mac.type == e1000_ich8lan) {
+@@ -1807,29 +1852,29 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
+ **/
+ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)
+ {
+- struct e1000_mac_info *mac = &hw->mac;
+ s32 ret_val;
+
+ if (e1000_check_reset_block(hw))
+ return 0;
+
+- /* ICH parts do not have a word in the NVM to determine
++ /*
++ * ICH parts do not have a word in the NVM to determine
+ * the default flow control setting, so we explicitly
+ * set it to full.
+ */
+- if (mac->fc == e1000_fc_default)
+- mac->fc = e1000_fc_full;
++ if (hw->fc.type == e1000_fc_default)
++ hw->fc.type = e1000_fc_full;
+
+- mac->original_fc = mac->fc;
++ hw->fc.original_type = hw->fc.type;
+
+- hw_dbg(hw, "After fix-ups FlowControl is now = %x\n", mac->fc);
++ hw_dbg(hw, "After fix-ups FlowControl is now = %x\n", hw->fc.type);
+
+ /* Continue to configure the copper link. */
+ ret_val = e1000_setup_copper_link_ich8lan(hw);
+ if (ret_val)
+ return ret_val;
+
+- ew32(FCTTV, mac->fc_pause_time);
++ ew32(FCTTV, hw->fc.pause_time);
+
+ return e1000e_set_fc_watermarks(hw);
+ }
+@@ -1853,9 +1898,11 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
+ ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+ ew32(CTRL, ctrl);
+
+- /* Set the mac to wait the maximum time between each iteration
++ /*
++ * Set the mac to wait the maximum time between each iteration
+ * and increase the max iterations when polling the phy;
+- * this fixes erroneous timeouts at 10Mbps. */
++ * this fixes erroneous timeouts at 10Mbps.
++ */
+ ret_val = e1000e_write_kmrn_reg(hw, GG82563_REG(0x34, 4), 0xFFFF);
+ if (ret_val)
+ return ret_val;
+@@ -1882,7 +1929,7 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
+ * @speed: pointer to store current link speed
+ * @duplex: pointer to store the current link duplex
+ *
+- * Calls the generic get_speed_and_duplex to retreive the current link
++ * Calls the generic get_speed_and_duplex to retrieve the current link
+ * information and then calls the Kumeran lock loss workaround for links at
+ * gigabit speeds.
+ **/
+@@ -1930,9 +1977,11 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw)
+ if (!dev_spec->kmrn_lock_loss_workaround_enabled)
+ return 0;
+
+- /* Make sure link is up before proceeding. If not just return.
++ /*
++ * Make sure link is up before proceeding. If not just return.
+ * Attempting this while link is negotiating fouled up link
+- * stability */
++ * stability
++ */
+ ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link);
+ if (!link)
+ return 0;
+@@ -1961,8 +2010,10 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw)
+ E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
+ ew32(PHY_CTRL, phy_ctrl);
+
+- /* Call gig speed drop workaround on Gig disable before accessing
+- * any PHY registers */
++ /*
++ * Call gig speed drop workaround on Gig disable before accessing
++ * any PHY registers
++ */
+ e1000e_gig_downshift_workaround_ich8lan(hw);
+
+ /* unable to acquire PCS lock */
+@@ -1970,7 +2021,7 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw)
+ }
+
+ /**
+- * e1000_set_kmrn_lock_loss_workaound_ich8lan - Set Kumeran workaround state
++ * e1000_set_kmrn_lock_loss_workaround_ich8lan - Set Kumeran workaround state
+ * @hw: pointer to the HW structure
+ * @state: boolean value used to set the current Kumeran workaround state
+ *
+@@ -2017,8 +2068,10 @@ void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw)
+ E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
+ ew32(PHY_CTRL, reg);
+
+- /* Call gig speed drop workaround on Gig disable before
+- * accessing any PHY registers */
++ /*
++ * Call gig speed drop workaround on Gig disable before
++ * accessing any PHY registers
++ */
+ if (hw->mac.type == e1000_ich8lan)
+ e1000e_gig_downshift_workaround_ich8lan(hw);
+
+@@ -2158,7 +2211,7 @@ static struct e1000_mac_operations ich8_mac_ops = {
+ .get_link_up_info = e1000_get_link_up_info_ich8lan,
+ .led_on = e1000_led_on_ich8lan,
+ .led_off = e1000_led_off_ich8lan,
+- .mc_addr_list_update = e1000e_mc_addr_list_update_generic,
++ .update_mc_addr_list = e1000e_update_mc_addr_list_generic,
+ .reset_hw = e1000_reset_hw_ich8lan,
+ .init_hw = e1000_init_hw_ich8lan,
+ .setup_link = e1000_setup_link_ich8lan,
+@@ -2200,7 +2253,7 @@ struct e1000_info e1000_ich8_info = {
+ | FLAG_HAS_FLASH
+ | FLAG_APME_IN_WUC,
+ .pba = 8,
+- .get_invariants = e1000_get_invariants_ich8lan,
++ .get_variants = e1000_get_variants_ich8lan,
+ .mac_ops = &ich8_mac_ops,
+ .phy_ops = &ich8_phy_ops,
+ .nvm_ops = &ich8_nvm_ops,
+@@ -2217,7 +2270,7 @@ struct e1000_info e1000_ich9_info = {
+ | FLAG_HAS_FLASH
+ | FLAG_APME_IN_WUC,
+ .pba = 10,
+- .get_invariants = e1000_get_invariants_ich8lan,
++ .get_variants = e1000_get_variants_ich8lan,
+ .mac_ops = &ich8_mac_ops,
+ .phy_ops = &ich8_phy_ops,
+ .nvm_ops = &ich8_nvm_ops,
+diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c
+index 95f75a4..f1f4e9d 100644
+--- a/drivers/net/e1000e/lib.c
++++ b/drivers/net/e1000e/lib.c
+@@ -1,7 +1,7 @@
+ /*******************************************************************************
+
+ Intel PRO/1000 Linux driver
+- Copyright(c) 1999 - 2007 Intel Corporation.
++ Copyright(c) 1999 - 2008 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+@@ -43,8 +43,8 @@ enum e1000_mng_mode {
+
+ #define E1000_FACTPS_MNGCG 0x20000000
+
+-#define E1000_IAMT_SIGNATURE 0x544D4149 /* Intel(R) Active Management
+- * Technology signature */
++/* Intel(R) Active Management Technology signature */
++#define E1000_IAMT_SIGNATURE 0x544D4149
+
+ /**
+ * e1000e_get_bus_info_pcie - Get PCIe bus information
+@@ -142,7 +142,8 @@ void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index)
+ {
+ u32 rar_low, rar_high;
+
+- /* HW expects these in little endian so we reverse the byte order
++ /*
++ * HW expects these in little endian so we reverse the byte order
+ * from network order (big endian) to little endian
+ */
+ rar_low = ((u32) addr[0] |
+@@ -171,7 +172,8 @@ static void e1000_mta_set(struct e1000_hw *hw, u32 hash_value)
+ {
+ u32 hash_bit, hash_reg, mta;
+
+- /* The MTA is a register array of 32-bit registers. It is
++ /*
++ * The MTA is a register array of 32-bit registers. It is
+ * treated like an array of (32*mta_reg_count) 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
+@@ -208,12 +210,15 @@ static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
+ /* Register count multiplied by bits per register */
+ hash_mask = (hw->mac.mta_reg_count * 32) - 1;
+
+- /* For a mc_filter_type of 0, bit_shift is the number of left-shifts
+- * where 0xFF would still fall within the hash mask. */
++ /*
++ * For a mc_filter_type of 0, bit_shift is the number of left-shifts
++ * where 0xFF would still fall within the hash mask.
++ */
+ while (hash_mask >> bit_shift != 0xFF)
+ bit_shift++;
+
+- /* The portion of the address that is used for the hash table
++ /*
++ * The portion of the address that is used for the hash table
+ * is determined by the mc_filter_type setting.
+ * The algorithm is such that there is a total of 8 bits of shifting.
+ * The bit_shift for a mc_filter_type of 0 represents the number of
+@@ -224,8 +229,8 @@ static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
+ * cases are a variation of this algorithm...essentially raising the
+ * number of bits to shift mc_addr[5] left, while still keeping the
+ * 8-bit shifting total.
+- */
+- /* For example, given the following Destination MAC Address and an
++ *
++ * For example, given the following Destination MAC Address and an
+ * mta register count of 128 (thus a 4096-bit vector and 0xFFF mask),
+ * we can see that the bit_shift for case 0 is 4. These are the hash
+ * values resulting from each mc_filter_type...
+@@ -260,7 +265,7 @@ static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
+ }
+
+ /**
+- * e1000e_mc_addr_list_update_generic - Update Multicast addresses
++ * e1000e_update_mc_addr_list_generic - Update Multicast addresses
+ * @hw: pointer to the HW structure
+ * @mc_addr_list: array of multicast addresses to program
+ * @mc_addr_count: number of multicast addresses to program
+@@ -272,14 +277,15 @@ static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
+ * The parameter rar_count will usually be hw->mac.rar_entry_count
+ * unless there are workarounds that change this.
+ **/
+-void e1000e_mc_addr_list_update_generic(struct e1000_hw *hw,
+- u8 *mc_addr_list, u32 mc_addr_count,
+- u32 rar_used_count, u32 rar_count)
++void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw,
++ u8 *mc_addr_list, u32 mc_addr_count,
++ u32 rar_used_count, u32 rar_count)
+ {
+ u32 hash_value;
+ u32 i;
+
+- /* Load the first set of multicast addresses into the exact
++ /*
++ * Load the first set of multicast addresses into the exact
+ * filters (RAR). If there are not enough to fill the RAR
+ * array, clear the filters.
+ */
+@@ -375,7 +381,8 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
+ s32 ret_val;
+ bool link;
+
+- /* We only want to go out to the PHY registers to see if Auto-Neg
++ /*
++ * We only want to go out to the PHY registers to see if Auto-Neg
+ * has completed and/or if our link status has changed. The
+ * get_link_status flag is set upon receiving a Link Status
+ * Change or Rx Sequence Error interrupt.
+@@ -383,7 +390,8 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
+ if (!mac->get_link_status)
+ return 0;
+
+- /* First we want to see if the MII Status Register reports
++ /*
++ * First we want to see if the MII Status Register reports
+ * link. If so, then we want to get the current speed/duplex
+ * of the PHY.
+ */
+@@ -396,11 +404,14 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
+
+ mac->get_link_status = 0;
+
+- /* Check if there was DownShift, must be checked
+- * immediately after link-up */
++ /*
++ * Check if there was DownShift, must be checked
++ * immediately after link-up
++ */
+ e1000e_check_downshift(hw);
+
+- /* If we are forcing speed/duplex, then we simply return since
++ /*
++ * If we are forcing speed/duplex, then we simply return since
+ * we have already determined whether we have link or not.
+ */
+ if (!mac->autoneg) {
+@@ -408,13 +419,15 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
+ return ret_val;
+ }
+
+- /* Auto-Neg is enabled. Auto Speed Detection takes care
++ /*
++ * Auto-Neg is enabled. Auto Speed Detection takes care
+ * of MAC speed/duplex configuration. So we only need to
+ * configure Collision Distance in the MAC.
+ */
+ e1000e_config_collision_dist(hw);
+
+- /* Configure Flow Control now that Auto-Neg has completed.
++ /*
++ * Configure Flow Control now that Auto-Neg has completed.
+ * First, we need to restore the desired flow control
+ * settings because we may have had to re-autoneg with a
+ * different link partner.
+@@ -446,7 +459,8 @@ s32 e1000e_check_for_fiber_link(struct e1000_hw *hw)
+ status = er32(STATUS);
+ rxcw = er32(RXCW);
+
+- /* If we don't have link (auto-negotiation failed or link partner
++ /*
++ * If we don't have link (auto-negotiation failed or link partner
+ * cannot auto-negotiate), the cable is plugged in (we have signal),
+ * and our link partner is not trying to auto-negotiate with us (we
+ * are receiving idles or data), we need to force link up. We also
+@@ -477,7 +491,8 @@ s32 e1000e_check_for_fiber_link(struct e1000_hw *hw)
+ return ret_val;
+ }
+ } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
+- /* If we are forcing link and we are receiving /C/ ordered
++ /*
++ * If we are forcing link and we are receiving /C/ ordered
+ * sets, re-enable auto-negotiation in the TXCW register
+ * and disable forced link in the Device Control register
+ * in an attempt to auto-negotiate with our link partner.
+@@ -511,7 +526,8 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
+ status = er32(STATUS);
+ rxcw = er32(RXCW);
+
+- /* If we don't have link (auto-negotiation failed or link partner
++ /*
++ * If we don't have link (auto-negotiation failed or link partner
+ * cannot auto-negotiate), and our link partner is not trying to
+ * auto-negotiate with us (we are receiving idles or data),
+ * we need to force link up. We also need to give auto-negotiation
+@@ -540,7 +556,8 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
+ return ret_val;
+ }
+ } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
+- /* If we are forcing link and we are receiving /C/ ordered
++ /*
++ * If we are forcing link and we are receiving /C/ ordered
+ * sets, re-enable auto-negotiation in the TXCW register
+ * and disable forced link in the Device Control register
+ * in an attempt to auto-negotiate with our link partner.
+@@ -551,7 +568,8 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
+
+ mac->serdes_has_link = 1;
+ } else if (!(E1000_TXCW_ANE & er32(TXCW))) {
+- /* If we force link for non-auto-negotiation switch, check
++ /*
++ * If we force link for non-auto-negotiation switch, check
+ * link status based on MAC synchronization for internal
+ * serdes media type.
+ */
+@@ -585,11 +603,11 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
+ **/
+ static s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
+ {
+- struct e1000_mac_info *mac = &hw->mac;
+ s32 ret_val;
+ u16 nvm_data;
+
+- /* Read and store word 0x0F of the EEPROM. This word contains bits
++ /*
++ * Read and store word 0x0F of the EEPROM. This word contains bits
+ * that determine the hardware's default PAUSE (flow control) mode,
+ * a bit that determines whether the HW defaults to enabling or
+ * disabling auto-negotiation, and the direction of the
+@@ -605,12 +623,12 @@ static s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
+ }
+
+ if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0)
+- mac->fc = e1000_fc_none;
++ hw->fc.type = e1000_fc_none;
+ else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) ==
+ NVM_WORD0F_ASM_DIR)
+- mac->fc = e1000_fc_tx_pause;
++ hw->fc.type = e1000_fc_tx_pause;
+ else
+- mac->fc = e1000_fc_full;
++ hw->fc.type = e1000_fc_full;
+
+ return 0;
+ }
+@@ -630,7 +648,8 @@ s32 e1000e_setup_link(struct e1000_hw *hw)
+ struct e1000_mac_info *mac = &hw->mac;
+ s32 ret_val;
+
+- /* In the case of the phy reset being blocked, we already have a link.
++ /*
++ * In the case of the phy reset being blocked, we already have a link.
+ * We do not need to set it up again.
+ */
+ if (e1000_check_reset_block(hw))
+@@ -640,26 +659,28 @@ s32 e1000e_setup_link(struct e1000_hw *hw)
+ * If flow control is set to default, set flow control based on
+ * the EEPROM flow control settings.
+ */
+- if (mac->fc == e1000_fc_default) {
++ if (hw->fc.type == e1000_fc_default) {
+ ret_val = e1000_set_default_fc_generic(hw);
+ if (ret_val)
+ return ret_val;
+ }
+
+- /* We want to save off the original Flow Control configuration just
++ /*
++ * We want to save off the original Flow Control configuration just
+ * in case we get disconnected and then reconnected into a different
+ * hub or switch with different Flow Control capabilities.
+ */
+- mac->original_fc = mac->fc;
++ hw->fc.original_type = hw->fc.type;
+
+- hw_dbg(hw, "After fix-ups FlowControl is now = %x\n", mac->fc);
++ hw_dbg(hw, "After fix-ups FlowControl is now = %x\n", hw->fc.type);
+
+ /* Call the necessary media_type subroutine to configure the link. */
+ ret_val = mac->ops.setup_physical_interface(hw);
+ if (ret_val)
+ return ret_val;
+
+- /* Initialize the flow control address, type, and PAUSE timer
++ /*
++ * Initialize the flow control address, type, and PAUSE timer
+ * registers to their default values. This is done even if flow
+ * control is disabled, because it does not hurt anything to
+ * initialize these registers.
+@@ -669,7 +690,7 @@ s32 e1000e_setup_link(struct e1000_hw *hw)
+ ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH);
+ ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW);
+
+- ew32(FCTTV, mac->fc_pause_time);
++ ew32(FCTTV, hw->fc.pause_time);
+
+ return e1000e_set_fc_watermarks(hw);
+ }
+@@ -686,7 +707,8 @@ static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
+ struct e1000_mac_info *mac = &hw->mac;
+ u32 txcw;
+
+- /* Check for a software override of the flow control settings, and
++ /*
++ * Check for a software override of the flow control settings, and
+ * setup the device accordingly. If auto-negotiation is enabled, then
+ * software will have to set the "PAUSE" bits to the correct value in
+ * the Transmit Config Word Register (TXCW) and re-start auto-
+@@ -700,31 +722,34 @@ static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
+ * but not send pause frames).
+ * 2: Tx flow control is enabled (we can send pause frames but we
+ * do not support receiving pause frames).
+- * 3: Both Rx and TX flow control (symmetric) are enabled.
++ * 3: Both Rx and Tx flow control (symmetric) are enabled.
+ */
+- switch (mac->fc) {
++ switch (hw->fc.type) {
+ case e1000_fc_none:
+ /* Flow control completely disabled by a software over-ride. */
+ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);
+ break;
+ case e1000_fc_rx_pause:
+- /* RX Flow control is enabled and TX Flow control is disabled
++ /*
++ * Rx Flow control is enabled and Tx Flow control is disabled
+ * by a software over-ride. Since there really isn't a way to
+- * advertise that we are capable of RX Pause ONLY, we will
+- * advertise that we support both symmetric and asymmetric RX
++ * advertise that we are capable of Rx Pause ONLY, we will
++ * advertise that we support both symmetric and asymmetric Rx
+ * PAUSE. Later, we will disable the adapter's ability to send
+ * PAUSE frames.
+ */
+ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
+ break;
+ case e1000_fc_tx_pause:
+- /* TX Flow control is enabled, and RX Flow control is disabled,
++ /*
++ * Tx Flow control is enabled, and Rx Flow control is disabled,
+ * by a software over-ride.
+ */
+ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
+ break;
+ case e1000_fc_full:
+- /* Flow control (both RX and TX) is enabled by a software
++ /*
++ * Flow control (both Rx and Tx) is enabled by a software
+ * over-ride.
+ */
+ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
+@@ -754,7 +779,8 @@ static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
+ u32 i, status;
+ s32 ret_val;
+
+- /* If we have a signal (the cable is plugged in, or assumed true for
++ /*
++ * If we have a signal (the cable is plugged in, or assumed true for
+ * serdes media) then poll for a "Link-Up" indication in the Device
+ * Status Register. Time-out if a link isn't seen in 500 milliseconds
+ * seconds (Auto-negotiation should complete in less than 500
+@@ -769,7 +795,8 @@ static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
+ if (i == FIBER_LINK_UP_LIMIT) {
+ hw_dbg(hw, "Never got a valid link from auto-neg!!!\n");
+ mac->autoneg_failed = 1;
+- /* AutoNeg failed to achieve a link, so we'll call
++ /*
++ * AutoNeg failed to achieve a link, so we'll call
+ * mac->check_for_link. This routine will force the
+ * link up if we detect a signal. This will allow us to
+ * communicate with non-autonegotiating link partners.
+@@ -811,7 +838,8 @@ s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw)
+ if (ret_val)
+ return ret_val;
+
+- /* Since auto-negotiation is enabled, take the link out of reset (the
++ /*
++ * Since auto-negotiation is enabled, take the link out of reset (the
+ * link will be in reset, because we previously reset the chip). This
+ * will restart auto-negotiation. If auto-negotiation is successful
+ * then the link-up status bit will be set and the flow control enable
+@@ -823,11 +851,12 @@ s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw)
+ e1e_flush();
+ msleep(1);
+
+- /* For these adapters, the SW defineable pin 1 is set when the optics
++ /*
++ * For these adapters, the SW definable pin 1 is set when the optics
+ * detect a signal. If we have a signal, then poll for a "Link-Up"
+ * indication.
+ */
+- if (hw->media_type == e1000_media_type_internal_serdes ||
++ if (hw->phy.media_type == e1000_media_type_internal_serdes ||
+ (er32(CTRL) & E1000_CTRL_SWDPIN1)) {
+ ret_val = e1000_poll_fiber_serdes_link_generic(hw);
+ } else {
+@@ -864,27 +893,28 @@ void e1000e_config_collision_dist(struct e1000_hw *hw)
+ *
+ * Sets the flow control high/low threshold (watermark) registers. If
+ * flow control XON frame transmission is enabled, then set XON frame
+- * tansmission as well.
++ * transmission as well.
+ **/
+ s32 e1000e_set_fc_watermarks(struct e1000_hw *hw)
+ {
+- struct e1000_mac_info *mac = &hw->mac;
+ u32 fcrtl = 0, fcrth = 0;
+
+- /* Set the flow control receive threshold registers. Normally,
++ /*
++ * Set the flow control receive threshold registers. Normally,
+ * these registers will be set to a default threshold that may be
+ * adjusted later by the driver's runtime code. However, if the
+ * ability to transmit pause frames is not enabled, then these
+ * registers will be set to 0.
+ */
+- if (mac->fc & e1000_fc_tx_pause) {
+- /* We need to set up the Receive Threshold high and low water
++ if (hw->fc.type & e1000_fc_tx_pause) {
++ /*
++ * We need to set up the Receive Threshold high and low water
+ * marks as well as (optionally) enabling the transmission of
+ * XON frames.
+ */
+- fcrtl = mac->fc_low_water;
++ fcrtl = hw->fc.low_water;
+ fcrtl |= E1000_FCRTL_XONE;
+- fcrth = mac->fc_high_water;
++ fcrth = hw->fc.high_water;
+ }
+ ew32(FCRTL, fcrtl);
+ ew32(FCRTH, fcrth);
+@@ -904,18 +934,18 @@ s32 e1000e_set_fc_watermarks(struct e1000_hw *hw)
+ **/
+ s32 e1000e_force_mac_fc(struct e1000_hw *hw)
+ {
+- struct e1000_mac_info *mac = &hw->mac;
+ u32 ctrl;
+
+ ctrl = er32(CTRL);
+
+- /* Because we didn't get link via the internal auto-negotiation
++ /*
++ * Because we didn't get link via the internal auto-negotiation
+ * mechanism (we either forced link or we got link via PHY
+ * auto-neg), we have to manually enable/disable transmit an
+ * receive flow control.
+ *
+ * The "Case" statement below enables/disable flow control
+- * according to the "mac->fc" parameter.
++ * according to the "hw->fc.type" parameter.
+ *
+ * The possible values of the "fc" parameter are:
+ * 0: Flow control is completely disabled
+@@ -923,12 +953,12 @@ s32 e1000e_force_mac_fc(struct e1000_hw *hw)
+ * frames but not send pause frames).
+ * 2: Tx flow control is enabled (we can send pause frames
+ * frames but we do not receive pause frames).
+- * 3: Both Rx and TX flow control (symmetric) is enabled.
++ * 3: Both Rx and Tx flow control (symmetric) is enabled.
+ * other: No other values should be possible at this point.
+ */
+- hw_dbg(hw, "mac->fc = %u\n", mac->fc);
++ hw_dbg(hw, "hw->fc.type = %u\n", hw->fc.type);
+
+- switch (mac->fc) {
++ switch (hw->fc.type) {
+ case e1000_fc_none:
+ ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
+ break;
+@@ -970,16 +1000,17 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
+ u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg;
+ u16 speed, duplex;
+
+- /* Check for the case where we have fiber media and auto-neg failed
++ /*
++ * Check for the case where we have fiber media and auto-neg failed
+ * so we had to force link. In this case, we need to force the
+ * configuration of the MAC to match the "fc" parameter.
+ */
+ if (mac->autoneg_failed) {
+- if (hw->media_type == e1000_media_type_fiber ||
+- hw->media_type == e1000_media_type_internal_serdes)
++ if (hw->phy.media_type == e1000_media_type_fiber ||
++ hw->phy.media_type == e1000_media_type_internal_serdes)
+ ret_val = e1000e_force_mac_fc(hw);
+ } else {
+- if (hw->media_type == e1000_media_type_copper)
++ if (hw->phy.media_type == e1000_media_type_copper)
+ ret_val = e1000e_force_mac_fc(hw);
+ }
+
+@@ -988,13 +1019,15 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
+ return ret_val;
+ }
+
+- /* Check for the case where we have copper media and auto-neg is
++ /*
++ * Check for the case where we have copper media and auto-neg is
+ * enabled. In this case, we need to check and see if Auto-Neg
+ * has completed, and if so, how the PHY and link partner has
+ * flow control configured.
+ */
+- if ((hw->media_type == e1000_media_type_copper) && mac->autoneg) {
+- /* Read the MII Status Register and check to see if AutoNeg
++ if ((hw->phy.media_type == e1000_media_type_copper) && mac->autoneg) {
++ /*
++ * Read the MII Status Register and check to see if AutoNeg
+ * has completed. We read this twice because this reg has
+ * some "sticky" (latched) bits.
+ */
+@@ -1011,7 +1044,8 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
+ return ret_val;
+ }
+
+- /* The AutoNeg process has completed, so we now need to
++ /*
++ * The AutoNeg process has completed, so we now need to
+ * read both the Auto Negotiation Advertisement
+ * Register (Address 4) and the Auto_Negotiation Base
+ * Page Ability Register (Address 5) to determine how
+@@ -1024,7 +1058,8 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
+ if (ret_val)
+ return ret_val;
+
+- /* Two bits in the Auto Negotiation Advertisement Register
++ /*
++ * Two bits in the Auto Negotiation Advertisement Register
+ * (Address 4) and two bits in the Auto Negotiation Base
+ * Page Ability Register (Address 5) determine flow control
+ * for both the PHY and the link partner. The following
+@@ -1045,8 +1080,8 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
+ * 1 | 1 | 0 | 0 | e1000_fc_none
+ * 1 | 1 | 0 | 1 | e1000_fc_rx_pause
+ *
+- */
+- /* Are both PAUSE bits set to 1? If so, this implies
++ *
++ * Are both PAUSE bits set to 1? If so, this implies
+ * Symmetric Flow Control is enabled at both ends. The
+ * ASM_DIR bits are irrelevant per the spec.
+ *
+@@ -1060,22 +1095,24 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
+ */
+ if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
+ (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
+- /* Now we need to check if the user selected RX ONLY
++ /*
++ * Now we need to check if the user selected Rx ONLY
+ * of pause frames. In this case, we had to advertise
+- * FULL flow control because we could not advertise RX
++ * FULL flow control because we could not advertise Rx
+ * ONLY. Hence, we must now check to see if we need to
+ * turn OFF the TRANSMISSION of PAUSE frames.
+ */
+- if (mac->original_fc == e1000_fc_full) {
+- mac->fc = e1000_fc_full;
++ if (hw->fc.original_type == e1000_fc_full) {
++ hw->fc.type = e1000_fc_full;
+ hw_dbg(hw, "Flow Control = FULL.\r\n");
+ } else {
+- mac->fc = e1000_fc_rx_pause;
++ hw->fc.type = e1000_fc_rx_pause;
+ hw_dbg(hw, "Flow Control = "
+ "RX PAUSE frames only.\r\n");
+ }
+ }
+- /* For receiving PAUSE frames ONLY.
++ /*
++ * For receiving PAUSE frames ONLY.
+ *
+ * LOCAL DEVICE | LINK PARTNER
+ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+@@ -1087,10 +1124,11 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
+ (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
+ (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
+ (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
+- mac->fc = e1000_fc_tx_pause;
+- hw_dbg(hw, "Flow Control = TX PAUSE frames only.\r\n");
++ hw->fc.type = e1000_fc_tx_pause;
++ hw_dbg(hw, "Flow Control = Tx PAUSE frames only.\r\n");
+ }
+- /* For transmitting PAUSE frames ONLY.
++ /*
++ * For transmitting PAUSE frames ONLY.
+ *
+ * LOCAL DEVICE | LINK PARTNER
+ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+@@ -1102,18 +1140,19 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
+ (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
+ !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
+ (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
+- mac->fc = e1000_fc_rx_pause;
+- hw_dbg(hw, "Flow Control = RX PAUSE frames only.\r\n");
++ hw->fc.type = e1000_fc_rx_pause;
++ hw_dbg(hw, "Flow Control = Rx PAUSE frames only.\r\n");
+ } else {
+ /*
+ * Per the IEEE spec, at this point flow control
+ * should be disabled.
+ */
+- mac->fc = e1000_fc_none;
++ hw->fc.type = e1000_fc_none;
+ hw_dbg(hw, "Flow Control = NONE.\r\n");
+ }
+
+- /* Now we need to do one last check... If we auto-
++ /*
++ * Now we need to do one last check... If we auto-
+ * negotiated to HALF DUPLEX, flow control should not be
+ * enabled per IEEE 802.3 spec.
+ */
+@@ -1124,9 +1163,10 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
+ }
+
+ if (duplex == HALF_DUPLEX)
+- mac->fc = e1000_fc_none;
++ hw->fc.type = e1000_fc_none;
+
+- /* Now we call a subroutine to actually force the MAC
++ /*
++ * Now we call a subroutine to actually force the MAC
+ * controller to use the correct flow control settings.
+ */
+ ret_val = e1000e_force_mac_fc(hw);
+@@ -1393,13 +1433,15 @@ s32 e1000e_blink_led(struct e1000_hw *hw)
+ u32 ledctl_blink = 0;
+ u32 i;
+
+- if (hw->media_type == e1000_media_type_fiber) {
++ if (hw->phy.media_type == e1000_media_type_fiber) {
+ /* always blink LED0 for PCI-E fiber */
+ ledctl_blink = E1000_LEDCTL_LED0_BLINK |
+ (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT);
+ } else {
+- /* set the blink bit for each LED that's "on" (0x0E)
+- * in ledctl_mode2 */
++ /*
++ * set the blink bit for each LED that's "on" (0x0E)
++ * in ledctl_mode2
++ */
+ ledctl_blink = hw->mac.ledctl_mode2;
+ for (i = 0; i < 4; i++)
+ if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) ==
+@@ -1423,7 +1465,7 @@ s32 e1000e_led_on_generic(struct e1000_hw *hw)
+ {
+ u32 ctrl;
+
+- switch (hw->media_type) {
++ switch (hw->phy.media_type) {
+ case e1000_media_type_fiber:
+ ctrl = er32(CTRL);
+ ctrl &= ~E1000_CTRL_SWDPIN0;
+@@ -1450,7 +1492,7 @@ s32 e1000e_led_off_generic(struct e1000_hw *hw)
+ {
+ u32 ctrl;
+
+- switch (hw->media_type) {
++ switch (hw->phy.media_type) {
+ case e1000_media_type_fiber:
+ ctrl = er32(CTRL);
+ ctrl |= E1000_CTRL_SWDPIN0;
+@@ -1562,8 +1604,7 @@ void e1000e_update_adaptive(struct e1000_hw *hw)
+ else
+ mac->current_ifs_val +=
+ mac->ifs_step_size;
+- ew32(AIT,
+- mac->current_ifs_val);
++ ew32(AIT, mac->current_ifs_val);
+ }
+ }
+ } else {
+@@ -1826,10 +1867,12 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
+ udelay(1);
+ timeout = NVM_MAX_RETRY_SPI;
+
+- /* Read "Status Register" repeatedly until the LSB is cleared.
++ /*
++ * Read "Status Register" repeatedly until the LSB is cleared.
+ * The EEPROM will signal that the command has been completed
+ * by clearing bit 0 of the internal status register. If it's
+- * not cleared within 'timeout', then error out. */
++ * not cleared within 'timeout', then error out.
++ */
+ while (timeout) {
+ e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI,
+ hw->nvm.opcode_bits);
+@@ -1852,62 +1895,6 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
+ }
+
+ /**
+- * e1000e_read_nvm_spi - Reads EEPROM using SPI
+- * @hw: pointer to the HW structure
+- * @offset: offset of word in the EEPROM to read
+- * @words: number of words to read
+- * @data: word read from the EEPROM
+- *
+- * Reads a 16 bit word from the EEPROM.
+- **/
+-s32 e1000e_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+-{
+- struct e1000_nvm_info *nvm = &hw->nvm;
+- u32 i = 0;
+- s32 ret_val;
+- u16 word_in;
+- u8 read_opcode = NVM_READ_OPCODE_SPI;
+-
+- /* A check for invalid values: offset too large, too many words,
+- * and not enough words. */
+- if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
+- (words == 0)) {
+- hw_dbg(hw, "nvm parameter(s) out of bounds\n");
+- return -E1000_ERR_NVM;
+- }
+-
+- ret_val = nvm->ops.acquire_nvm(hw);
+- if (ret_val)
+- return ret_val;
+-
+- ret_val = e1000_ready_nvm_eeprom(hw);
+- if (ret_val) {
+- nvm->ops.release_nvm(hw);
+- return ret_val;
+- }
+-
+- e1000_standby_nvm(hw);
+-
+- if ((nvm->address_bits == 8) && (offset >= 128))
+- read_opcode |= NVM_A8_OPCODE_SPI;
+-
+- /* Send the READ command (opcode + addr) */
+- e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits);
+- e1000_shift_out_eec_bits(hw, (u16)(offset*2), nvm->address_bits);
+-
+- /* Read the data. SPI NVMs increment the address with each byte
+- * read and will roll over if reading beyond the end. This allows
+- * us to read the whole NVM from any offset */
+- for (i = 0; i < words; i++) {
+- word_in = e1000_shift_in_eec_bits(hw, 16);
+- data[i] = (word_in >> 8) | (word_in << 8);
+- }
+-
+- nvm->ops.release_nvm(hw);
+- return 0;
+-}
+-
+-/**
+ * e1000e_read_nvm_eerd - Reads EEPROM using EERD register
+ * @hw: pointer to the HW structure
+ * @offset: offset of word in the EEPROM to read
+@@ -1922,8 +1909,10 @@ s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+ u32 i, eerd = 0;
+ s32 ret_val = 0;
+
+- /* A check for invalid values: offset too large, too many words,
+- * and not enough words. */
++ /*
++ * A check for invalid values: offset too large, too many words,
++ * too many words for the offset, and not enough words.
++ */
+ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
+ (words == 0)) {
+ hw_dbg(hw, "nvm parameter(s) out of bounds\n");
+@@ -1939,8 +1928,7 @@ s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+ if (ret_val)
+ break;
+
+- data[i] = (er32(EERD) >>
+- E1000_NVM_RW_REG_DATA);
++ data[i] = (er32(EERD) >> E1000_NVM_RW_REG_DATA);
+ }
+
+ return ret_val;
+@@ -1964,8 +1952,10 @@ s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+ s32 ret_val;
+ u16 widx = 0;
+
+- /* A check for invalid values: offset too large, too many words,
+- * and not enough words. */
++ /*
++ * A check for invalid values: offset too large, too many words,
++ * and not enough words.
++ */
+ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
+ (words == 0)) {
+ hw_dbg(hw, "nvm parameter(s) out of bounds\n");
+@@ -1995,8 +1985,10 @@ s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+
+ e1000_standby_nvm(hw);
+
+- /* Some SPI eeproms use the 8th address bit embedded in the
+- * opcode */
++ /*
++ * Some SPI eeproms use the 8th address bit embedded in the
++ * opcode
++ */
+ if ((nvm->address_bits == 8) && (offset >= 128))
+ write_opcode |= NVM_A8_OPCODE_SPI;
+
+@@ -2041,9 +2033,9 @@ s32 e1000e_read_mac_addr(struct e1000_hw *hw)
+ /* Check for an alternate MAC address. An alternate MAC
+ * address can be setup by pre-boot software and must be
+ * treated like a permanent address and must override the
+- * actual permanent MAC address. */
++ * actual permanent MAC address.*/
+ ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1,
+- &mac_addr_offset);
++ &mac_addr_offset);
+ if (ret_val) {
+ hw_dbg(hw, "NVM Read Error\n");
+ return ret_val;
+@@ -2056,7 +2048,7 @@ s32 e1000e_read_mac_addr(struct e1000_hw *hw)
+ mac_addr_offset += ETH_ALEN/sizeof(u16);
+
+ /* make sure we have a valid mac address here
+- * before using it */
++ * before using it */
+ ret_val = e1000_read_nvm(hw, mac_addr_offset, 1,
+ &nvm_data);
+ if (ret_val) {
+@@ -2068,7 +2060,7 @@ s32 e1000e_read_mac_addr(struct e1000_hw *hw)
+ }
+
+ if (mac_addr_offset)
+- hw->dev_spec.e82571.alt_mac_addr_is_present = 1;
++ hw->dev_spec.e82571.alt_mac_addr_is_present = 1;
+ }
+
+ for (i = 0; i < ETH_ALEN; i += 2) {
+@@ -2244,7 +2236,7 @@ bool e1000e_check_mng_mode(struct e1000_hw *hw)
+ }
+
+ /**
+- * e1000e_enable_tx_pkt_filtering - Enable packet filtering on TX
++ * e1000e_enable_tx_pkt_filtering - Enable packet filtering on Tx
+ * @hw: pointer to the HW structure
+ *
+ * Enables packet filtering on transmit packets if manageability is enabled
+@@ -2264,7 +2256,8 @@ bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw)
+ return 0;
+ }
+
+- /* If we can't read from the host interface for whatever
++ /*
++ * If we can't read from the host interface for whatever
+ * reason, disable filtering.
+ */
+ ret_val = e1000_mng_enable_host_if(hw);
+@@ -2282,7 +2275,8 @@ bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw)
+ hdr->checksum = 0;
+ csum = e1000_calculate_checksum((u8 *)hdr,
+ E1000_MNG_DHCP_COOKIE_LENGTH);
+- /* If either the checksums or signature don't match, then
++ /*
++ * If either the checksums or signature don't match, then
+ * the cookie area isn't considered valid, in which case we
+ * take the safe route of assuming Tx filtering is enabled.
+ */
+@@ -2374,8 +2368,10 @@ static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer,
+ /* Calculate length in DWORDs */
+ length >>= 2;
+
+- /* The device driver writes the relevant command block into the
+- * ram area. */
++ /*
++ * The device driver writes the relevant command block into the
++ * ram area.
++ */
+ for (i = 0; i < length; i++) {
+ for (j = 0; j < sizeof(u32); j++) {
+ *(tmp + j) = *bufptr++;
+@@ -2481,7 +2477,7 @@ bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw)
+ return ret_val;
+ }
+
+-s32 e1000e_read_part_num(struct e1000_hw *hw, u32 *part_num)
++s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num)
+ {
+ s32 ret_val;
+ u16 nvm_data;
+@@ -2491,14 +2487,14 @@ s32 e1000e_read_part_num(struct e1000_hw *hw, u32 *part_num)
+ hw_dbg(hw, "NVM Read Error\n");
+ return ret_val;
+ }
+- *part_num = (u32)(nvm_data << 16);
++ *pba_num = (u32)(nvm_data << 16);
+
+ ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_1, 1, &nvm_data);
+ if (ret_val) {
+ hw_dbg(hw, "NVM Read Error\n");
+ return ret_val;
+ }
+- *part_num |= nvm_data;
++ *pba_num |= nvm_data;
+
+ return 0;
+ }
+diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
+index fc5c63f..8991ab8 100644
+--- a/drivers/net/e1000e/netdev.c
++++ b/drivers/net/e1000e/netdev.c
+@@ -1,7 +1,7 @@
+ /*******************************************************************************
+
+ Intel PRO/1000 Linux driver
+- Copyright(c) 1999 - 2007 Intel Corporation.
++ Copyright(c) 1999 - 2008 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+@@ -46,7 +46,7 @@
+
+ #include "e1000.h"
+
+-#define DRV_VERSION "0.2.0"
++#define DRV_VERSION "0.2.1"
+ char e1000e_driver_name[] = "e1000e";
+ const char e1000e_driver_version[] = DRV_VERSION;
+
+@@ -82,7 +82,7 @@ static int e1000_desc_unused(struct e1000_ring *ring)
+ }
+
+ /**
+- * e1000_receive_skb - helper function to handle rx indications
++ * e1000_receive_skb - helper function to handle Rx indications
+ * @adapter: board private structure
+ * @status: descriptor status field as written by hardware
+ * @vlan: descriptor vlan field as written by hardware (no le/be conversion)
+@@ -138,8 +138,9 @@ static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
+ /* TCP checksum is good */
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ } else {
+- /* IP fragment with UDP payload */
+- /* Hardware complements the payload checksum, so we undo it
++ /*
++ * IP fragment with UDP payload
++ * Hardware complements the payload checksum, so we undo it
+ * and then put the value in host order for further stack use.
+ */
+ __sum16 sum = (__force __sum16)htons(csum);
+@@ -182,7 +183,8 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
+ break;
+ }
+
+- /* Make buffer alignment 2 beyond a 16 byte boundary
++ /*
++ * 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
+ */
+@@ -213,10 +215,12 @@ map_skb:
+ if (i-- == 0)
+ i = (rx_ring->count - 1);
+
+- /* Force memory writes to complete before letting h/w
++ /*
++ * Force memory writes to complete before letting h/w
+ * know there are new descriptors to fetch. (Only
+ * applicable for weak-ordered memory model archs,
+- * such as IA-64). */
++ * such as IA-64).
++ */
+ wmb();
+ writel(i, adapter->hw.hw_addr + rx_ring->tail);
+ }
+@@ -285,7 +289,8 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
+ break;
+ }
+
+- /* Make buffer alignment 2 beyond a 16 byte boundary
++ /*
++ * 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
+ */
+@@ -319,12 +324,15 @@ no_buffers:
+ if (!(i--))
+ i = (rx_ring->count - 1);
+
+- /* Force memory writes to complete before letting h/w
++ /*
++ * Force memory writes to complete before letting h/w
+ * know there are new descriptors to fetch. (Only
+ * applicable for weak-ordered memory model archs,
+- * such as IA-64). */
++ * such as IA-64).
++ */
+ wmb();
+- /* Hardware increments by 16 bytes, but packet split
++ /*
++ * Hardware increments by 16 bytes, but packet split
+ * descriptors are 32 bytes...so we increment tail
+ * twice as much.
+ */
+@@ -409,9 +417,11 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
+ total_rx_bytes += length;
+ total_rx_packets++;
+
+- /* code added for copybreak, this should improve
++ /*
++ * code added for copybreak, this should improve
+ * performance for small packets with large amounts
+- * of reassembly being done in the stack */
++ * of reassembly being done in the stack
++ */
+ if (length < copybreak) {
+ struct sk_buff *new_skb =
+ netdev_alloc_skb(netdev, length + NET_IP_ALIGN);
+@@ -456,10 +466,10 @@ next_desc:
+ if (cleaned_count)
+ adapter->alloc_rx_buf(adapter, cleaned_count);
+
+- adapter->total_rx_packets += total_rx_packets;
+ adapter->total_rx_bytes += total_rx_bytes;
+- adapter->net_stats.rx_packets += total_rx_packets;
++ adapter->total_rx_packets += total_rx_packets;
+ adapter->net_stats.rx_bytes += total_rx_bytes;
++ adapter->net_stats.rx_packets += total_rx_packets;
+ return cleaned;
+ }
+
+@@ -581,22 +591,23 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
+ }
+
+ if (adapter->detect_tx_hung) {
+- /* Detect a transmit hang in hardware, this serializes the
+- * check with the clearing of time_stamp and movement of i */
++ /*
++ * Detect a transmit hang in hardware, this serializes the
++ * check with the clearing of time_stamp and movement of i
++ */
+ adapter->detect_tx_hung = 0;
+ if (tx_ring->buffer_info[eop].dma &&
+ time_after(jiffies, tx_ring->buffer_info[eop].time_stamp
+ + (adapter->tx_timeout_factor * HZ))
+- && !(er32(STATUS) &
+- E1000_STATUS_TXOFF)) {
++ && !(er32(STATUS) & E1000_STATUS_TXOFF)) {
+ e1000_print_tx_hang(adapter);
+ netif_stop_queue(netdev);
+ }
+ }
+ adapter->total_tx_bytes += total_tx_bytes;
+ adapter->total_tx_packets += total_tx_packets;
+- adapter->net_stats.tx_packets += total_tx_packets;
+ adapter->net_stats.tx_bytes += total_tx_bytes;
++ adapter->net_stats.tx_packets += total_tx_packets;
+ return cleaned;
+ }
+
+@@ -677,21 +688,28 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+ skb_put(skb, length);
+
+ {
+- /* this looks ugly, but it seems compiler issues make it
+- more efficient than reusing j */
++ /*
++ * this looks ugly, but it seems compiler issues make it
++ * more efficient than reusing j
++ */
+ int l1 = le16_to_cpu(rx_desc->wb.upper.length[0]);
+
+- /* page alloc/put takes too long and effects small packet
+- * throughput, so unsplit small packets and save the alloc/put*/
++ /*
++ * page alloc/put takes too long and effects small packet
++ * throughput, so unsplit small packets and save the alloc/put
++ * only valid in softirq (napi) context to call kmap_*
++ */
+ if (l1 && (l1 <= copybreak) &&
+ ((length + l1) <= adapter->rx_ps_bsize0)) {
+ u8 *vaddr;
+
+ ps_page = &buffer_info->ps_pages[0];
+
+- /* there is no documentation about how to call
++ /*
++ * there is no documentation about how to call
+ * kmap_atomic, so we can't hold the mapping
+- * very long */
++ * very long
++ */
+ pci_dma_sync_single_for_cpu(pdev, ps_page->dma,
+ PAGE_SIZE, PCI_DMA_FROMDEVICE);
+ vaddr = kmap_atomic(ps_page->page, KM_SKB_DATA_SOFTIRQ);
+@@ -757,10 +775,10 @@ next_desc:
+ if (cleaned_count)
+ adapter->alloc_rx_buf(adapter, cleaned_count);
+
+- adapter->total_rx_packets += total_rx_packets;
+ adapter->total_rx_bytes += total_rx_bytes;
+- adapter->net_stats.rx_packets += total_rx_packets;
++ adapter->total_rx_packets += total_rx_packets;
+ adapter->net_stats.rx_bytes += total_rx_bytes;
++ adapter->net_stats.rx_packets += total_rx_packets;
+ return cleaned;
+ }
+
+@@ -836,26 +854,31 @@ static irqreturn_t e1000_intr_msi(int irq, void *data)
+ struct e1000_hw *hw = &adapter->hw;
+ u32 icr = er32(ICR);
+
+- /* read ICR disables interrupts using IAM, so keep up with our
+- * enable/disable accounting */
+- atomic_inc(&adapter->irq_sem);
++ /*
++ * read ICR disables interrupts using IAM
++ */
+
+ if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
+ hw->mac.get_link_status = 1;
+- /* ICH8 workaround-- Call gig speed drop workaround on cable
+- * disconnect (LSC) before accessing any PHY registers */
++ /*
++ * ICH8 workaround-- Call gig speed drop workaround on cable
++ * disconnect (LSC) before accessing any PHY registers
++ */
+ if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&
+ (!(er32(STATUS) & E1000_STATUS_LU)))
+ e1000e_gig_downshift_workaround_ich8lan(hw);
+
+- /* 80003ES2LAN workaround-- For packet buffer work-around on
++ /*
++ * 80003ES2LAN workaround-- For packet buffer work-around on
+ * link down event; disable receives here in the ISR and reset
+- * adapter in watchdog */
++ * adapter in watchdog
++ */
+ if (netif_carrier_ok(netdev) &&
+ adapter->flags & FLAG_RX_NEEDS_RESTART) {
+ /* disable receives */
+ u32 rctl = er32(RCTL);
+ ew32(RCTL, rctl & ~E1000_RCTL_EN);
++ adapter->flags |= FLAG_RX_RESTART_NOW;
+ }
+ /* guard against interrupt when we're going down */
+ if (!test_bit(__E1000_DOWN, &adapter->state))
+@@ -868,8 +891,6 @@ static irqreturn_t e1000_intr_msi(int irq, void *data)
+ adapter->total_rx_bytes = 0;
+ adapter->total_rx_packets = 0;
+ __netif_rx_schedule(netdev, &adapter->napi);
+- } else {
+- atomic_dec(&adapter->irq_sem);
+ }
+
+ return IRQ_HANDLED;
+@@ -890,26 +911,31 @@ static irqreturn_t e1000_intr(int irq, void *data)
+ if (!icr)
+ return IRQ_NONE; /* Not our interrupt */
+
+- /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is
+- * not set, then the adapter didn't send an interrupt */
++ /*
++ * IMS will not auto-mask if INT_ASSERTED is not set, and if it is
++ * not set, then the adapter didn't send an interrupt
++ */
+ if (!(icr & E1000_ICR_INT_ASSERTED))
+ return IRQ_NONE;
+
+- /* Interrupt Auto-Mask...upon reading ICR,
++ /*
++ * Interrupt Auto-Mask...upon reading ICR,
+ * interrupts are masked. No need for the
+- * IMC write, but it does mean we should
+- * account for it ASAP. */
+- atomic_inc(&adapter->irq_sem);
++ * IMC write
++ */
+
+ if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
+ hw->mac.get_link_status = 1;
+- /* ICH8 workaround-- Call gig speed drop workaround on cable
+- * disconnect (LSC) before accessing any PHY registers */
++ /*
++ * ICH8 workaround-- Call gig speed drop workaround on cable
++ * disconnect (LSC) before accessing any PHY registers
++ */
+ if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&
+ (!(er32(STATUS) & E1000_STATUS_LU)))
+ e1000e_gig_downshift_workaround_ich8lan(hw);
+
+- /* 80003ES2LAN workaround--
++ /*
++ * 80003ES2LAN workaround--
+ * For packet buffer work-around on link down event;
+ * disable receives here in the ISR and
+ * reset adapter in watchdog
+@@ -919,6 +945,7 @@ static irqreturn_t e1000_intr(int irq, void *data)
+ /* disable receives */
+ rctl = er32(RCTL);
+ ew32(RCTL, rctl & ~E1000_RCTL_EN);
++ adapter->flags |= FLAG_RX_RESTART_NOW;
+ }
+ /* guard against interrupt when we're going down */
+ if (!test_bit(__E1000_DOWN, &adapter->state))
+@@ -931,8 +958,6 @@ static irqreturn_t e1000_intr(int irq, void *data)
+ adapter->total_rx_bytes = 0;
+ adapter->total_rx_packets = 0;
+ __netif_rx_schedule(netdev, &adapter->napi);
+- } else {
+- atomic_dec(&adapter->irq_sem);
+ }
+
+ return IRQ_HANDLED;
+@@ -983,7 +1008,6 @@ static void e1000_irq_disable(struct e1000_adapter *adapter)
+ {
+ struct e1000_hw *hw = &adapter->hw;
+
+- atomic_inc(&adapter->irq_sem);
+ ew32(IMC, ~0);
+ e1e_flush();
+ synchronize_irq(adapter->pdev->irq);
+@@ -996,10 +1020,8 @@ static void e1000_irq_enable(struct e1000_adapter *adapter)
+ {
+ struct e1000_hw *hw = &adapter->hw;
+
+- if (atomic_dec_and_test(&adapter->irq_sem)) {
+- ew32(IMS, IMS_ENABLE_MASK);
+- e1e_flush();
+- }
++ ew32(IMS, IMS_ENABLE_MASK);
++ e1e_flush();
+ }
+
+ /**
+@@ -1023,8 +1045,7 @@ static void e1000_get_hw_control(struct e1000_adapter *adapter)
+ ew32(SWSM, swsm | E1000_SWSM_DRV_LOAD);
+ } else if (adapter->flags & FLAG_HAS_CTRLEXT_ON_LOAD) {
+ ctrl_ext = er32(CTRL_EXT);
+- ew32(CTRL_EXT,
+- ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
++ ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
+ }
+ }
+
+@@ -1050,8 +1071,7 @@ static void e1000_release_hw_control(struct e1000_adapter *adapter)
+ ew32(SWSM, swsm & ~E1000_SWSM_DRV_LOAD);
+ } else if (adapter->flags & FLAG_HAS_CTRLEXT_ON_LOAD) {
+ ctrl_ext = er32(CTRL_EXT);
+- ew32(CTRL_EXT,
+- ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
++ ew32(CTRL_EXT, ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
+ }
+ }
+
+@@ -1353,9 +1373,11 @@ static void e1000_set_itr(struct e1000_adapter *adapter)
+
+ set_itr_now:
+ if (new_itr != adapter->itr) {
+- /* this attempts to bias the interrupt rate towards Bulk
++ /*
++ * this attempts to bias the interrupt rate towards Bulk
+ * by adding intermediate steps when interrupt rate is
+- * increasing */
++ * increasing
++ */
+ new_itr = new_itr > adapter->itr ?
+ min(adapter->itr + (new_itr >> 2), new_itr) :
+ new_itr;
+@@ -1366,7 +1388,7 @@ set_itr_now:
+
+ /**
+ * e1000_clean - NAPI Rx polling callback
+- * @adapter: board private structure
++ * @napi: struct associated with this polling callback
+ * @budget: amount of packets driver is allowed to process this poll
+ **/
+ static int e1000_clean(struct napi_struct *napi, int budget)
+@@ -1378,10 +1400,12 @@ static int e1000_clean(struct napi_struct *napi, int budget)
+ /* Must NOT use netdev_priv macro here. */
+ adapter = poll_dev->priv;
+
+- /* e1000_clean is called per-cpu. This lock protects
++ /*
++ * e1000_clean is called per-cpu. This lock protects
+ * tx_ring from being cleaned by multiple cpus
+ * simultaneously. A failure obtaining the lock means
+- * tx_ring is currently being cleaned anyway. */
++ * tx_ring is currently being cleaned anyway.
++ */
+ if (spin_trylock(&adapter->tx_queue_lock)) {
+ tx_cleaned = e1000_clean_tx_irq(adapter);
+ spin_unlock(&adapter->tx_queue_lock);
+@@ -1427,9 +1451,12 @@ static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
+ struct e1000_hw *hw = &adapter->hw;
+ u32 vfta, index;
+
+- e1000_irq_disable(adapter);
++ if (!test_bit(__E1000_DOWN, &adapter->state))
++ e1000_irq_disable(adapter);
+ vlan_group_set_device(adapter->vlgrp, vid, NULL);
+- e1000_irq_enable(adapter);
++
++ if (!test_bit(__E1000_DOWN, &adapter->state))
++ e1000_irq_enable(adapter);
+
+ if ((adapter->hw.mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN) &&
+@@ -1480,7 +1507,8 @@ static void e1000_vlan_rx_register(struct net_device *netdev,
+ struct e1000_hw *hw = &adapter->hw;
+ u32 ctrl, rctl;
+
+- e1000_irq_disable(adapter);
++ if (!test_bit(__E1000_DOWN, &adapter->state))
++ e1000_irq_disable(adapter);
+ adapter->vlgrp = grp;
+
+ if (grp) {
+@@ -1517,7 +1545,8 @@ static void e1000_vlan_rx_register(struct net_device *netdev,
+ }
+ }
+
+- e1000_irq_enable(adapter);
++ if (!test_bit(__E1000_DOWN, &adapter->state))
++ e1000_irq_enable(adapter);
+ }
+
+ static void e1000_restore_vlan(struct e1000_adapter *adapter)
+@@ -1546,9 +1575,11 @@ static void e1000_init_manageability(struct e1000_adapter *adapter)
+
+ manc = er32(MANC);
+
+- /* enable receiving management packets to the host. this will probably
++ /*
++ * enable receiving management packets to the host. this will probably
+ * generate destination unreachable messages from the host OS, but
+- * the packets will be handled on SMBUS */
++ * the packets will be handled on SMBUS
++ */
+ manc |= E1000_MANC_EN_MNG2HOST;
+ manc2h = er32(MANC2H);
+ #define E1000_MNG2HOST_PORT_623 (1 << 5)
+@@ -1598,7 +1629,7 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
+
+ /* Set the Tx Interrupt Delay register */
+ ew32(TIDV, adapter->tx_int_delay);
+- /* tx irq moderation */
++ /* Tx irq moderation */
+ ew32(TADV, adapter->tx_abs_int_delay);
+
+ /* Program the Transmit Control Register */
+@@ -1608,22 +1639,24 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
+ (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
+
+ if (adapter->flags & FLAG_TARC_SPEED_MODE_BIT) {
+- tarc = er32(TARC0);
+- /* set the speed mode bit, we'll clear it if we're not at
+- * gigabit link later */
++ tarc = er32(TARC(0));
++ /*
++ * set the speed mode bit, we'll clear it if we're not at
++ * gigabit link later
++ */
+ #define SPEED_MODE_BIT (1 << 21)
+ tarc |= SPEED_MODE_BIT;
+- ew32(TARC0, tarc);
++ ew32(TARC(0), tarc);
+ }
+
+ /* errata: program both queues to unweighted RR */
+ if (adapter->flags & FLAG_TARC_SET_BIT_ZERO) {
+- tarc = er32(TARC0);
++ tarc = er32(TARC(0));
+ tarc |= 1;
+- ew32(TARC0, tarc);
+- tarc = er32(TARC1);
++ ew32(TARC(0), tarc);
++ tarc = er32(TARC(1));
+ tarc |= 1;
+- ew32(TARC1, tarc);
++ ew32(TARC(1), tarc);
+ }
+
+ e1000e_config_collision_dist(hw);
+@@ -1731,8 +1764,10 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
+ /* Configure extra packet-split registers */
+ rfctl = er32(RFCTL);
+ rfctl |= E1000_RFCTL_EXTEN;
+- /* disable packet split support for IPv6 extension headers,
+- * because some malformed IPv6 headers can hang the RX */
++ /*
++ * disable packet split support for IPv6 extension headers,
++ * because some malformed IPv6 headers can hang the Rx
++ */
+ rfctl |= (E1000_RFCTL_IPV6_EX_DIS |
+ E1000_RFCTL_NEW_IPV6_EXT_DIS);
+
+@@ -1761,6 +1796,8 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
+ }
+
+ ew32(RCTL, rctl);
++ /* just started the receive unit, no need to restart */
++ adapter->flags &= ~FLAG_RX_RESTART_NOW;
+ }
+
+ /**
+@@ -1801,8 +1838,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
+ /* irq moderation */
+ ew32(RADV, adapter->rx_abs_int_delay);
+ if (adapter->itr_setting != 0)
+- ew32(ITR,
+- 1000000000 / (adapter->itr * 256));
++ ew32(ITR, 1000000000 / (adapter->itr * 256));
+
+ ctrl_ext = er32(CTRL_EXT);
+ /* Reset delay timers after every interrupt */
+@@ -1813,8 +1849,10 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
+ ew32(CTRL_EXT, ctrl_ext);
+ e1e_flush();
+
+- /* Setup the HW Rx Head and Tail Descriptor Pointers and
+- * the Base and Length of the Rx Descriptor Ring */
++ /*
++ * Setup the HW Rx Head and Tail Descriptor Pointers and
++ * the Base and Length of the Rx Descriptor Ring
++ */
+ rdba = rx_ring->dma;
+ ew32(RDBAL, (rdba & DMA_32BIT_MASK));
+ ew32(RDBAH, (rdba >> 32));
+@@ -1829,8 +1867,10 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
+ if (adapter->flags & FLAG_RX_CSUM_ENABLED) {
+ rxcsum |= E1000_RXCSUM_TUOFL;
+
+- /* IPv4 payload checksum for UDP fragments must be
+- * used in conjunction with packet-split. */
++ /*
++ * IPv4 payload checksum for UDP fragments must be
++ * used in conjunction with packet-split.
++ */
+ if (adapter->rx_ps_pages)
+ rxcsum |= E1000_RXCSUM_IPPCSE;
+ } else {
+@@ -1839,9 +1879,11 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
+ }
+ ew32(RXCSUM, rxcsum);
+
+- /* Enable early receives on supported devices, only takes effect when
++ /*
++ * Enable early receives on supported devices, only takes effect when
+ * packet size is equal or larger than the specified value (in 8 byte
+- * units), e.g. using jumbo frames when setting to E1000_ERT_2048 */
++ * units), e.g. using jumbo frames when setting to E1000_ERT_2048
++ */
+ if ((adapter->flags & FLAG_HAS_ERT) &&
+ (adapter->netdev->mtu > ETH_DATA_LEN))
+ ew32(ERT, E1000_ERT_2048);
+@@ -1851,7 +1893,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
+ }
+
+ /**
+- * e1000_mc_addr_list_update - Update Multicast addresses
++ * e1000_update_mc_addr_list - Update Multicast addresses
+ * @hw: pointer to the HW structure
+ * @mc_addr_list: array of multicast addresses to program
+ * @mc_addr_count: number of multicast addresses to program
+@@ -1865,11 +1907,11 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
+ * exists and all implementations are handled in the generic version of this
+ * function.
+ **/
+-static void e1000_mc_addr_list_update(struct e1000_hw *hw, u8 *mc_addr_list,
+- u32 mc_addr_count, u32 rar_used_count,
+- u32 rar_count)
++static void e1000_update_mc_addr_list(struct e1000_hw *hw, u8 *mc_addr_list,
++ u32 mc_addr_count, u32 rar_used_count,
++ u32 rar_count)
+ {
+- hw->mac.ops.mc_addr_list_update(hw, mc_addr_list, mc_addr_count,
++ hw->mac.ops.update_mc_addr_list(hw, mc_addr_list, mc_addr_count,
+ rar_used_count, rar_count);
+ }
+
+@@ -1923,7 +1965,7 @@ static void e1000_set_multi(struct net_device *netdev)
+ mc_ptr = mc_ptr->next;
+ }
+
+- e1000_mc_addr_list_update(hw, mta_list, i, 1,
++ e1000_update_mc_addr_list(hw, mta_list, i, 1,
+ mac->rar_entry_count);
+ kfree(mta_list);
+ } else {
+@@ -1931,13 +1973,12 @@ static void e1000_set_multi(struct net_device *netdev)
+ * if we're called from probe, we might not have
+ * anything to do here, so clear out the list
+ */
+- e1000_mc_addr_list_update(hw, NULL, 0, 1,
+- mac->rar_entry_count);
++ e1000_update_mc_addr_list(hw, NULL, 0, 1, mac->rar_entry_count);
+ }
+ }
+
+ /**
+- * e1000_configure - configure the hardware for RX and TX
++ * e1000_configure - configure the hardware for Rx and Tx
+ * @adapter: private board structure
+ **/
+ static void e1000_configure(struct e1000_adapter *adapter)
+@@ -1950,8 +1991,7 @@ static void e1000_configure(struct e1000_adapter *adapter)
+ e1000_configure_tx(adapter);
+ e1000_setup_rctl(adapter);
+ e1000_configure_rx(adapter);
+- adapter->alloc_rx_buf(adapter,
+- e1000_desc_unused(adapter->rx_ring));
++ adapter->alloc_rx_buf(adapter, e1000_desc_unused(adapter->rx_ring));
+ }
+
+ /**
+@@ -1967,9 +2007,11 @@ void e1000e_power_up_phy(struct e1000_adapter *adapter)
+ u16 mii_reg = 0;
+
+ /* Just clear the power down bit to wake the phy back up */
+- if (adapter->hw.media_type == e1000_media_type_copper) {
+- /* according to the manual, the phy will retain its
+- * settings across a power-down/up cycle */
++ if (adapter->hw.phy.media_type == e1000_media_type_copper) {
++ /*
++ * According to the manual, the phy will retain its
++ * settings across a power-down/up cycle
++ */
+ e1e_rphy(&adapter->hw, PHY_CONTROL, &mii_reg);
+ mii_reg &= ~MII_CR_POWER_DOWN;
+ e1e_wphy(&adapter->hw, PHY_CONTROL, mii_reg);
+@@ -1994,12 +2036,11 @@ static void e1000_power_down_phy(struct e1000_adapter *adapter)
+ return;
+
+ /* non-copper PHY? */
+- if (adapter->hw.media_type != e1000_media_type_copper)
++ if (adapter->hw.phy.media_type != e1000_media_type_copper)
+ return;
+
+ /* reset is blocked because of a SoL/IDER session */
+- if (e1000e_check_mng_mode(hw) ||
+- e1000_check_reset_block(hw))
++ if (e1000e_check_mng_mode(hw) || e1000_check_reset_block(hw))
+ return;
+
+ /* manageability (AMT) is enabled */
+@@ -2019,51 +2060,61 @@ static void e1000_power_down_phy(struct e1000_adapter *adapter)
+ * This function boots the hardware and enables some settings that
+ * require a configuration cycle of the hardware - those cannot be
+ * set/changed during runtime. After reset the device needs to be
+- * properly configured for rx, tx etc.
++ * properly configured for Rx, Tx etc.
+ */
+ void e1000e_reset(struct e1000_adapter *adapter)
+ {
+ struct e1000_mac_info *mac = &adapter->hw.mac;
++ struct e1000_fc_info *fc = &adapter->hw.fc;
+ struct e1000_hw *hw = &adapter->hw;
+ u32 tx_space, min_tx_space, min_rx_space;
+- u32 pba;
++ u32 pba = adapter->pba;
+ u16 hwm;
+
+- ew32(PBA, adapter->pba);
++ /* reset Packet Buffer Allocation to default */
++ ew32(PBA, pba);
+
+- if (mac->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN ) {
+- /* To maintain wire speed transmits, the Tx FIFO should be
++ if (adapter->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN) {
++ /*
++ * To maintain wire speed transmits, the Tx FIFO should be
+ * large enough to accommodate two full transmit packets,
+ * rounded up to the next 1KB and expressed in KB. Likewise,
+ * the Rx FIFO should be large enough to accommodate at least
+ * one full receive packet and is similarly rounded up and
+- * expressed in KB. */
++ * expressed in KB.
++ */
+ pba = er32(PBA);
+ /* upper 16 bits has Tx packet buffer allocation size in KB */
+ tx_space = pba >> 16;
+ /* lower 16 bits has Rx packet buffer allocation size in KB */
+ pba &= 0xffff;
+- /* the tx fifo also stores 16 bytes of information about the tx
+- * but don't include ethernet FCS because hardware appends it */
+- min_tx_space = (mac->max_frame_size +
++ /*
++ * the Tx fifo also stores 16 bytes of information about the tx
++ * but don't include ethernet FCS because hardware appends it
++ */
++ min_tx_space = (adapter->max_frame_size +
+ sizeof(struct e1000_tx_desc) -
+ ETH_FCS_LEN) * 2;
+ min_tx_space = ALIGN(min_tx_space, 1024);
+ min_tx_space >>= 10;
+ /* software strips receive CRC, so leave room for it */
+- min_rx_space = mac->max_frame_size;
++ min_rx_space = adapter->max_frame_size;
+ min_rx_space = ALIGN(min_rx_space, 1024);
+ min_rx_space >>= 10;
+
+- /* If current Tx allocation is less than the min Tx FIFO size,
++ /*
++ * If current Tx allocation is less than the min Tx FIFO size,
+ * and the min Tx FIFO size is less than the current Rx FIFO
+- * allocation, take space away from current Rx allocation */
++ * allocation, take space away from current Rx allocation
++ */
+ if ((tx_space < min_tx_space) &&
+ ((min_tx_space - tx_space) < pba)) {
+ pba -= min_tx_space - tx_space;
+
+- /* if short on rx space, rx wins and must trump tx
+- * adjustment or use Early Receive if available */
++ /*
++ * if short on Rx space, Rx wins and must trump tx
++ * adjustment or use Early Receive if available
++ */
+ if ((pba < min_rx_space) &&
+ (!(adapter->flags & FLAG_HAS_ERT)))
+ /* ERT enabled in e1000_configure_rx */
+@@ -2074,29 +2125,33 @@ void e1000e_reset(struct e1000_adapter *adapter)
+ }
+
+
+- /* flow control settings */
+- /* The high water mark must be low enough to fit one full frame
++ /*
++ * flow control settings
++ *
++ * The high water mark must be low enough to fit one full frame
+ * (or the size used for early receive) above it in the Rx FIFO.
+ * Set it to the lower of:
+ * - 90% of the Rx FIFO size, and
+ * - the full Rx FIFO size minus the early receive size (for parts
+ * with ERT support assuming ERT set to E1000_ERT_2048), or
+- * - the full Rx FIFO size minus one full frame */
++ * - the full Rx FIFO size minus one full frame
++ */
+ if (adapter->flags & FLAG_HAS_ERT)
+- hwm = min(((adapter->pba << 10) * 9 / 10),
+- ((adapter->pba << 10) - (E1000_ERT_2048 << 3)));
++ hwm = min(((pba << 10) * 9 / 10),
++ ((pba << 10) - (E1000_ERT_2048 << 3)));
+ else
+- hwm = min(((adapter->pba << 10) * 9 / 10),
+- ((adapter->pba << 10) - mac->max_frame_size));
++ hwm = min(((pba << 10) * 9 / 10),
++ ((pba << 10) - adapter->max_frame_size));
+
+- mac->fc_high_water = hwm & 0xFFF8; /* 8-byte granularity */
+- mac->fc_low_water = mac->fc_high_water - 8;
++ fc->high_water = hwm & 0xFFF8; /* 8-byte granularity */
++ fc->low_water = fc->high_water - 8;
+
+ if (adapter->flags & FLAG_DISABLE_FC_PAUSE_TIME)
+- mac->fc_pause_time = 0xFFFF;
++ fc->pause_time = 0xFFFF;
+ else
+- mac->fc_pause_time = E1000_FC_PAUSE_TIME;
+- mac->fc = mac->original_fc;
++ fc->pause_time = E1000_FC_PAUSE_TIME;
++ fc->send_xon = 1;
++ fc->type = fc->original_type;
+
+ /* Allow time for pending master requests to run */
+ mac->ops.reset_hw(hw);
+@@ -2115,9 +2170,11 @@ void e1000e_reset(struct e1000_adapter *adapter)
+
+ if (!(adapter->flags & FLAG_SMART_POWER_DOWN)) {
+ u16 phy_data = 0;
+- /* speed up time to link by disabling smart power down, ignore
++ /*
++ * speed up time to link by disabling smart power down, ignore
+ * the return value of this function because there is nothing
+- * different we would do if it failed */
++ * different we would do if it failed
++ */
+ e1e_rphy(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data);
+ phy_data &= ~IGP02E1000_PM_SPD;
+ e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, phy_data);
+@@ -2147,8 +2204,10 @@ void e1000e_down(struct e1000_adapter *adapter)
+ struct e1000_hw *hw = &adapter->hw;
+ u32 tctl, rctl;
+
+- /* signal that we're down so the interrupt handler does not
+- * reschedule our watchdog timer */
++ /*
++ * signal that we're down so the interrupt handler does not
++ * reschedule our watchdog timer
++ */
+ set_bit(__E1000_DOWN, &adapter->state);
+
+ /* disable receives in the hardware */
+@@ -2167,7 +2226,6 @@ void e1000e_down(struct e1000_adapter *adapter)
+ msleep(10);
+
+ napi_disable(&adapter->napi);
+- atomic_set(&adapter->irq_sem, 0);
+ e1000_irq_disable(adapter);
+
+ del_timer_sync(&adapter->watchdog_timer);
+@@ -2208,13 +2266,12 @@ void e1000e_reinit_locked(struct e1000_adapter *adapter)
+ **/
+ static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
+ {
+- struct e1000_hw *hw = &adapter->hw;
+ struct net_device *netdev = adapter->netdev;
+
+ adapter->rx_buffer_len = ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN;
+ adapter->rx_ps_bsize0 = 128;
+- hw->mac.max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
+- hw->mac.min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
++ adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
++ adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
+
+ adapter->tx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL);
+ if (!adapter->tx_ring)
+@@ -2227,7 +2284,6 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
+ spin_lock_init(&adapter->tx_queue_lock);
+
+ /* Explicitly disable IRQ since the NIC can be in any state. */
+- atomic_set(&adapter->irq_sem, 0);
+ e1000_irq_disable(adapter);
+
+ spin_lock_init(&adapter->stats_lock);
+@@ -2281,16 +2337,20 @@ static int e1000_open(struct net_device *netdev)
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN))
+ e1000_update_mng_vlan(adapter);
+
+- /* If AMT is enabled, let the firmware know that the network
+- * interface is now open */
++ /*
++ * If AMT is enabled, let the firmware know that the network
++ * interface is now open
++ */
+ if ((adapter->flags & FLAG_HAS_AMT) &&
+ e1000e_check_mng_mode(&adapter->hw))
+ e1000_get_hw_control(adapter);
+
+- /* before we allocate an interrupt, we must be ready to handle it.
++ /*
++ * before we allocate an interrupt, we must be ready to handle it.
+ * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt
+ * as soon as we call pci_request_irq, so we have to setup our
+- * clean_rx handler before we do so. */
++ * clean_rx handler before we do so.
++ */
+ e1000_configure(adapter);
+
+ err = e1000_request_irq(adapter);
+@@ -2344,16 +2404,20 @@ static int e1000_close(struct net_device *netdev)
+ e1000e_free_tx_resources(adapter);
+ e1000e_free_rx_resources(adapter);
+
+- /* kill manageability vlan ID if supported, but not if a vlan with
+- * the same ID is registered on the host OS (let 8021q kill it) */
++ /*
++ * kill manageability vlan ID if supported, but not if a vlan with
++ * the same ID is registered on the host OS (let 8021q kill it)
++ */
+ if ((adapter->hw.mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN) &&
+ !(adapter->vlgrp &&
+ vlan_group_get_device(adapter->vlgrp, adapter->mng_vlan_id)))
+ e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
+
+- /* If AMT is enabled, let the firmware know that the network
+- * interface is now closed */
++ /*
++ * If AMT is enabled, let the firmware know that the network
++ * interface is now closed
++ */
+ if ((adapter->flags & FLAG_HAS_AMT) &&
+ e1000e_check_mng_mode(&adapter->hw))
+ e1000_release_hw_control(adapter);
+@@ -2384,12 +2448,14 @@ static int e1000_set_mac(struct net_device *netdev, void *p)
+ /* activate the work around */
+ e1000e_set_laa_state_82571(&adapter->hw, 1);
+
+- /* Hold a copy of the LAA in RAR[14] This is done so that
++ /*
++ * Hold a copy of the LAA in RAR[14] This is done so that
+ * between the time RAR[0] gets clobbered and the time it
+ * gets fixed (in e1000_watchdog), the actual LAA is in one
+ * of the RARs and no incoming packets directed to this port
+ * are dropped. Eventually the LAA will be in RAR[0] and
+- * RAR[14] */
++ * RAR[14]
++ */
+ e1000e_rar_set(&adapter->hw,
+ adapter->hw.mac.addr,
+ adapter->hw.mac.rar_entry_count - 1);
+@@ -2398,8 +2464,10 @@ static int e1000_set_mac(struct net_device *netdev, void *p)
+ return 0;
+ }
+
+-/* Need to wait a few seconds after link up to get diagnostic information from
+- * the phy */
++/*
++ * Need to wait a few seconds after link up to get diagnostic information from
++ * the phy
++ */
+ static void e1000_update_phy_info(unsigned long data)
+ {
+ struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+@@ -2430,63 +2498,35 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
+
+ spin_lock_irqsave(&adapter->stats_lock, irq_flags);
+
+- /* these counters are modified from e1000_adjust_tbi_stats,
++ /*
++ * these counters are modified from e1000_adjust_tbi_stats,
+ * called from the interrupt context, so they must only
+ * be written while holding adapter->stats_lock
+ */
+
+ adapter->stats.crcerrs += er32(CRCERRS);
+ adapter->stats.gprc += er32(GPRC);
+- adapter->stats.gorcl += er32(GORCL);
+- adapter->stats.gorch += er32(GORCH);
++ adapter->stats.gorc += er32(GORCL);
++ er32(GORCH); /* Clear gorc */
+ adapter->stats.bprc += er32(BPRC);
+ adapter->stats.mprc += er32(MPRC);
+ adapter->stats.roc += er32(ROC);
+
+- if (adapter->flags & FLAG_HAS_STATS_PTC_PRC) {
+- adapter->stats.prc64 += er32(PRC64);
+- adapter->stats.prc127 += er32(PRC127);
+- adapter->stats.prc255 += er32(PRC255);
+- adapter->stats.prc511 += er32(PRC511);
+- adapter->stats.prc1023 += er32(PRC1023);
+- adapter->stats.prc1522 += er32(PRC1522);
+- adapter->stats.symerrs += er32(SYMERRS);
+- adapter->stats.sec += er32(SEC);
+- }
+-
+ adapter->stats.mpc += er32(MPC);
+ adapter->stats.scc += er32(SCC);
+ adapter->stats.ecol += er32(ECOL);
+ adapter->stats.mcc += er32(MCC);
+ adapter->stats.latecol += er32(LATECOL);
+ adapter->stats.dc += er32(DC);
+- adapter->stats.rlec += er32(RLEC);
+ adapter->stats.xonrxc += er32(XONRXC);
+ adapter->stats.xontxc += er32(XONTXC);
+ adapter->stats.xoffrxc += er32(XOFFRXC);
+ adapter->stats.xofftxc += er32(XOFFTXC);
+- adapter->stats.fcruc += er32(FCRUC);
+ adapter->stats.gptc += er32(GPTC);
+- adapter->stats.gotcl += er32(GOTCL);
+- adapter->stats.gotch += er32(GOTCH);
++ adapter->stats.gotc += er32(GOTCL);
++ er32(GOTCH); /* Clear gotc */
+ adapter->stats.rnbc += er32(RNBC);
+ adapter->stats.ruc += er32(RUC);
+- adapter->stats.rfc += er32(RFC);
+- adapter->stats.rjc += er32(RJC);
+- adapter->stats.torl += er32(TORL);
+- adapter->stats.torh += er32(TORH);
+- adapter->stats.totl += er32(TOTL);
+- adapter->stats.toth += er32(TOTH);
+- adapter->stats.tpr += er32(TPR);
+-
+- if (adapter->flags & FLAG_HAS_STATS_PTC_PRC) {
+- adapter->stats.ptc64 += er32(PTC64);
+- adapter->stats.ptc127 += er32(PTC127);
+- adapter->stats.ptc255 += er32(PTC255);
+- adapter->stats.ptc511 += er32(PTC511);
+- adapter->stats.ptc1023 += er32(PTC1023);
+- adapter->stats.ptc1522 += er32(PTC1522);
+- }
+
+ adapter->stats.mptc += er32(MPTC);
+ adapter->stats.bptc += er32(BPTC);
+@@ -2505,27 +2545,16 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
+ adapter->stats.tsctc += er32(TSCTC);
+ adapter->stats.tsctfc += er32(TSCTFC);
+
+- adapter->stats.iac += er32(IAC);
+-
+- if (adapter->flags & FLAG_HAS_STATS_ICR_ICT) {
+- adapter->stats.icrxoc += er32(ICRXOC);
+- adapter->stats.icrxptc += er32(ICRXPTC);
+- adapter->stats.icrxatc += er32(ICRXATC);
+- adapter->stats.ictxptc += er32(ICTXPTC);
+- adapter->stats.ictxatc += er32(ICTXATC);
+- adapter->stats.ictxqec += er32(ICTXQEC);
+- adapter->stats.ictxqmtc += er32(ICTXQMTC);
+- adapter->stats.icrxdmtc += er32(ICRXDMTC);
+- }
+-
+ /* Fill out the OS statistics structure */
+ adapter->net_stats.multicast = adapter->stats.mprc;
+ adapter->net_stats.collisions = adapter->stats.colc;
+
+ /* Rx Errors */
+
+- /* RLEC on some newer hardware can be incorrect so build
+- * our own version based on RUC and ROC */
++ /*
++ * RLEC on some newer hardware can be incorrect so build
++ * our own version based on RUC and ROC
++ */
+ adapter->net_stats.rx_errors = adapter->stats.rxerrc +
+ adapter->stats.crcerrs + adapter->stats.algnerrc +
+ adapter->stats.ruc + adapter->stats.roc +
+@@ -2546,7 +2575,7 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
+ /* Tx Dropped needs to be maintained elsewhere */
+
+ /* Phy Stats */
+- if (hw->media_type == e1000_media_type_copper) {
++ if (hw->phy.media_type == e1000_media_type_copper) {
+ if ((adapter->link_speed == SPEED_1000) &&
+ (!e1e_rphy(hw, PHY_1000T_STATUS, &phy_tmp))) {
+ phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK;
+@@ -2562,10 +2591,58 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
+ spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);
+ }
+
++/**
++ * e1000_phy_read_status - Update the PHY register status snapshot
++ * @adapter: board private structure
++ **/
++static void e1000_phy_read_status(struct e1000_adapter *adapter)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ struct e1000_phy_regs *phy = &adapter->phy_regs;
++ int ret_val;
++ unsigned long irq_flags;
++
++
++ spin_lock_irqsave(&adapter->stats_lock, irq_flags);
++
++ if ((er32(STATUS) & E1000_STATUS_LU) &&
++ (adapter->hw.phy.media_type == e1000_media_type_copper)) {
++ ret_val = e1e_rphy(hw, PHY_CONTROL, &phy->bmcr);
++ ret_val |= e1e_rphy(hw, PHY_STATUS, &phy->bmsr);
++ ret_val |= e1e_rphy(hw, PHY_AUTONEG_ADV, &phy->advertise);
++ ret_val |= e1e_rphy(hw, PHY_LP_ABILITY, &phy->lpa);
++ ret_val |= e1e_rphy(hw, PHY_AUTONEG_EXP, &phy->expansion);
++ ret_val |= e1e_rphy(hw, PHY_1000T_CTRL, &phy->ctrl1000);
++ ret_val |= e1e_rphy(hw, PHY_1000T_STATUS, &phy->stat1000);
++ ret_val |= e1e_rphy(hw, PHY_EXT_STATUS, &phy->estatus);
++ if (ret_val)
++ ndev_warn(adapter->netdev,
++ "Error reading PHY register\n");
++ } else {
++ /*
++ * Do not read PHY registers if link is not up
++ * Set values to typical power-on defaults
++ */
++ phy->bmcr = (BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_FULLDPLX);
++ phy->bmsr = (BMSR_100FULL | BMSR_100HALF | BMSR_10FULL |
++ BMSR_10HALF | BMSR_ESTATEN | BMSR_ANEGCAPABLE |
++ BMSR_ERCAP);
++ phy->advertise = (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP |
++ ADVERTISE_ALL | ADVERTISE_CSMA);
++ phy->lpa = 0;
++ phy->expansion = EXPANSION_ENABLENPAGE;
++ phy->ctrl1000 = ADVERTISE_1000FULL;
++ phy->stat1000 = 0;
++ phy->estatus = (ESTATUS_1000_TFULL | ESTATUS_1000_THALF);
++ }
++
++ spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);
++}
++
+ static void e1000_print_link_info(struct e1000_adapter *adapter)
+ {
+- struct net_device *netdev = adapter->netdev;
+ struct e1000_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
+ u32 ctrl = er32(CTRL);
+
+ ndev_info(netdev,
+@@ -2579,6 +2656,62 @@ static void e1000_print_link_info(struct e1000_adapter *adapter)
+ ((ctrl & E1000_CTRL_TFCE) ? "TX" : "None" )));
+ }
+
++static bool e1000_has_link(struct e1000_adapter *adapter)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ bool link_active = 0;
++ s32 ret_val = 0;
++
++ /*
++ * get_link_status is set on LSC (link status) interrupt or
++ * Rx sequence error interrupt. get_link_status will stay
++ * false until the check_for_link establishes link
++ * for copper adapters ONLY
++ */
++ switch (hw->phy.media_type) {
++ case e1000_media_type_copper:
++ if (hw->mac.get_link_status) {
++ ret_val = hw->mac.ops.check_for_link(hw);
++ link_active = !hw->mac.get_link_status;
++ } else {
++ link_active = 1;
++ }
++ break;
++ case e1000_media_type_fiber:
++ ret_val = hw->mac.ops.check_for_link(hw);
++ link_active = !!(er32(STATUS) & E1000_STATUS_LU);
++ break;
++ case e1000_media_type_internal_serdes:
++ ret_val = hw->mac.ops.check_for_link(hw);
++ link_active = adapter->hw.mac.serdes_has_link;
++ break;
++ default:
++ case e1000_media_type_unknown:
++ break;
++ }
++
++ if ((ret_val == E1000_ERR_PHY) && (hw->phy.type == e1000_phy_igp_3) &&
++ (er32(CTRL) & E1000_PHY_CTRL_GBE_DISABLE)) {
++ /* See e1000_kmrn_lock_loss_workaround_ich8lan() */
++ ndev_info(adapter->netdev,
++ "Gigabit has been disabled, downgrading speed\n");
++ }
++
++ return link_active;
++}
++
++static void e1000e_enable_receives(struct e1000_adapter *adapter)
++{
++ /* make sure the receive unit is started */
++ if ((adapter->flags & FLAG_RX_NEEDS_RESTART) &&
++ (adapter->flags & FLAG_RX_RESTART_NOW)) {
++ struct e1000_hw *hw = &adapter->hw;
++ u32 rctl = er32(RCTL);
++ ew32(RCTL, rctl | E1000_RCTL_EN);
++ adapter->flags &= ~FLAG_RX_RESTART_NOW;
++ }
++}
++
+ /**
+ * e1000_watchdog - Timer Call-back
+ * @data: pointer to adapter cast into an unsigned long
+@@ -2597,48 +2730,36 @@ static void e1000_watchdog_task(struct work_struct *work)
+ {
+ struct e1000_adapter *adapter = container_of(work,
+ struct e1000_adapter, watchdog_task);
+-
+ struct net_device *netdev = adapter->netdev;
+ struct e1000_mac_info *mac = &adapter->hw.mac;
+ struct e1000_ring *tx_ring = adapter->tx_ring;
+ struct e1000_hw *hw = &adapter->hw;
+ u32 link, tctl;
+- s32 ret_val;
+ int tx_pending = 0;
+
+- if ((netif_carrier_ok(netdev)) &&
+- (er32(STATUS) & E1000_STATUS_LU))
++ link = e1000_has_link(adapter);
++ if ((netif_carrier_ok(netdev)) && link) {
++ e1000e_enable_receives(adapter);
+ goto link_up;
+-
+- ret_val = mac->ops.check_for_link(hw);
+- if ((ret_val == E1000_ERR_PHY) &&
+- (adapter->hw.phy.type == e1000_phy_igp_3) &&
+- (er32(CTRL) &
+- E1000_PHY_CTRL_GBE_DISABLE)) {
+- /* See e1000_kmrn_lock_loss_workaround_ich8lan() */
+- ndev_info(netdev,
+- "Gigabit has been disabled, downgrading speed\n");
+ }
+
+ if ((e1000e_enable_tx_pkt_filtering(hw)) &&
+ (adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id))
+ e1000_update_mng_vlan(adapter);
+
+- if ((adapter->hw.media_type == e1000_media_type_internal_serdes) &&
+- !(er32(TXCW) & E1000_TXCW_ANE))
+- link = adapter->hw.mac.serdes_has_link;
+- else
+- link = er32(STATUS) & E1000_STATUS_LU;
+-
+ if (link) {
+ if (!netif_carrier_ok(netdev)) {
+ bool txb2b = 1;
++ /* update snapshot of PHY registers on LSC */
++ e1000_phy_read_status(adapter);
+ mac->ops.get_link_up_info(&adapter->hw,
+ &adapter->link_speed,
+ &adapter->link_duplex);
+ e1000_print_link_info(adapter);
+- /* tweak tx_queue_len according to speed/duplex
+- * and adjust the timeout factor */
++ /*
++ * tweak tx_queue_len according to speed/duplex
++ * and adjust the timeout factor
++ */
+ netdev->tx_queue_len = adapter->tx_queue_len;
+ adapter->tx_timeout_factor = 1;
+ switch (adapter->link_speed) {
+@@ -2654,18 +2775,22 @@ static void e1000_watchdog_task(struct work_struct *work)
+ break;
+ }
+
+- /* workaround: re-program speed mode bit after
+- * link-up event */
++ /*
++ * workaround: re-program speed mode bit after
++ * link-up event
++ */
+ if ((adapter->flags & FLAG_TARC_SPEED_MODE_BIT) &&
+ !txb2b) {
+ u32 tarc0;
+- tarc0 = er32(TARC0);
++ tarc0 = er32(TARC(0));
+ tarc0 &= ~SPEED_MODE_BIT;
+- ew32(TARC0, tarc0);
++ ew32(TARC(0), tarc0);
+ }
+
+- /* disable TSO for pcie and 10/100 speeds, to avoid
+- * some hardware issues */
++ /*
++ * disable TSO for pcie and 10/100 speeds, to avoid
++ * some hardware issues
++ */
+ if (!(adapter->flags & FLAG_TSO_FORCE)) {
+ switch (adapter->link_speed) {
+ case SPEED_10:
+@@ -2685,8 +2810,10 @@ static void e1000_watchdog_task(struct work_struct *work)
+ }
+ }
+
+- /* enable transmits in the hardware, need to do this
+- * after setting TARC0 */
++ /*
++ * enable transmits in the hardware, need to do this
++ * after setting TARC(0)
++ */
+ tctl = er32(TCTL);
+ tctl |= E1000_TCTL_EN;
+ ew32(TCTL, tctl);
+@@ -2697,13 +2824,6 @@ static void e1000_watchdog_task(struct work_struct *work)
+ if (!test_bit(__E1000_DOWN, &adapter->state))
+ mod_timer(&adapter->phy_info_timer,
+ round_jiffies(jiffies + 2 * HZ));
+- } else {
+- /* make sure the receive unit is started */
+- if (adapter->flags & FLAG_RX_NEEDS_RESTART) {
+- u32 rctl = er32(RCTL);
+- ew32(RCTL, rctl |
+- E1000_RCTL_EN);
+- }
+ }
+ } else {
+ if (netif_carrier_ok(netdev)) {
+@@ -2729,10 +2849,10 @@ link_up:
+ mac->collision_delta = adapter->stats.colc - adapter->colc_old;
+ adapter->colc_old = adapter->stats.colc;
+
+- adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old;
+- adapter->gorcl_old = adapter->stats.gorcl;
+- adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old;
+- adapter->gotcl_old = adapter->stats.gotcl;
++ adapter->gorc = adapter->stats.gorc - adapter->gorc_old;
++ adapter->gorc_old = adapter->stats.gorc;
++ adapter->gotc = adapter->stats.gotc - adapter->gotc_old;
++ adapter->gotc_old = adapter->stats.gotc;
+
+ e1000e_update_adaptive(&adapter->hw);
+
+@@ -2740,23 +2860,27 @@ link_up:
+ tx_pending = (e1000_desc_unused(tx_ring) + 1 <
+ tx_ring->count);
+ if (tx_pending) {
+- /* We've lost link, so the controller stops DMA,
++ /*
++ * We've lost link, so the controller stops DMA,
+ * but we've got queued Tx work that's never going
+ * to get done, so reset controller to flush Tx.
+- * (Do the reset outside of interrupt context). */
++ * (Do the reset outside of interrupt context).
++ */
+ adapter->tx_timeout_count++;
+ schedule_work(&adapter->reset_task);
+ }
+ }
+
+- /* Cause software interrupt to ensure rx ring is cleaned */
++ /* Cause software interrupt to ensure Rx ring is cleaned */
+ ew32(ICS, E1000_ICS_RXDMT0);
+
+ /* Force detection of hung controller every watchdog period */
+ adapter->detect_tx_hung = 1;
+
+- /* With 82571 controllers, LAA may be overwritten due to controller
+- * reset from the other port. Set the appropriate LAA in RAR[0] */
++ /*
++ * With 82571 controllers, LAA may be overwritten due to controller
++ * reset from the other port. Set the appropriate LAA in RAR[0]
++ */
+ if (e1000e_get_laa_state_82571(hw))
+ e1000e_rar_set(hw, adapter->hw.mac.addr, 0);
+
+@@ -3032,16 +3156,20 @@ static void e1000_tx_queue(struct e1000_adapter *adapter,
+
+ tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
+
+- /* Force memory writes to complete before letting h/w
++ /*
++ * Force memory writes to complete before letting h/w
+ * know there are new descriptors to fetch. (Only
+ * applicable for weak-ordered memory model archs,
+- * such as IA-64). */
++ * such as IA-64).
++ */
+ wmb();
+
+ tx_ring->next_to_use = i;
+ writel(i, adapter->hw.hw_addr + tx_ring->tail);
+- /* we need this if more than one processor can write to our tail
+- * at a time, it synchronizes IO on IA64/Altix systems */
++ /*
++ * we need this if more than one processor can write to our tail
++ * at a time, it synchronizes IO on IA64/Altix systems
++ */
+ mmiowb();
+ }
+
+@@ -3089,13 +3217,17 @@ static int __e1000_maybe_stop_tx(struct net_device *netdev, int size)
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+
+ netif_stop_queue(netdev);
+- /* Herbert's original patch had:
++ /*
++ * Herbert's original patch had:
+ * smp_mb__after_netif_stop_queue();
+- * but since that doesn't exist yet, just open code it. */
++ * but since that doesn't exist yet, just open code it.
++ */
+ smp_mb();
+
+- /* We need to check again in a case another CPU has just
+- * made room available. */
++ /*
++ * We need to check again in a case another CPU has just
++ * made room available.
++ */
+ if (e1000_desc_unused(adapter->tx_ring) < size)
+ return -EBUSY;
+
+@@ -3142,21 +3274,29 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ }
+
+ mss = skb_shinfo(skb)->gso_size;
+- /* The controller does a simple calculation to
++ /*
++ * The controller does a simple calculation to
+ * make sure there is enough room in the FIFO before
+ * initiating the DMA for each buffer. The calc is:
+ * 4 = ceil(buffer len/mss). To make sure we don't
+ * overrun the FIFO, adjust the max buffer len if mss
+- * drops. */
++ * drops.
++ */
+ if (mss) {
+ u8 hdr_len;
+ max_per_txd = min(mss << 2, max_per_txd);
+ max_txd_pwr = fls(max_per_txd) - 1;
+
+- /* TSO Workaround for 82571/2/3 Controllers -- if skb->data
+- * points to just header, pull a few bytes of payload from
+- * frags into skb->data */
++ /*
++ * TSO Workaround for 82571/2/3 Controllers -- if skb->data
++ * points to just header, pull a few bytes of payload from
++ * frags into skb->data
++ */
+ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
++ /*
++ * we do this workaround for ES2LAN, but it is un-necessary,
++ * avoiding it could save a lot of cycles
++ */
+ if (skb->data_len && (hdr_len == len)) {
+ unsigned int pull_size;
+
+@@ -3190,8 +3330,10 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ /* Collision - tell upper layer to requeue */
+ return NETDEV_TX_LOCKED;
+
+- /* need: count + 2 desc gap to keep tail from touching
+- * head, otherwise try next time */
++ /*
++ * need: count + 2 desc gap to keep tail from touching
++ * head, otherwise try next time
++ */
+ if (e1000_maybe_stop_tx(netdev, count + 2)) {
+ spin_unlock_irqrestore(&adapter->tx_queue_lock, irq_flags);
+ return NETDEV_TX_BUSY;
+@@ -3216,9 +3358,11 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ else if (e1000_tx_csum(adapter, skb))
+ tx_flags |= E1000_TX_FLAGS_CSUM;
+
+- /* Old method was to assume IPv4 packet by default if TSO was enabled.
++ /*
++ * Old method was to assume IPv4 packet by default if TSO was enabled.
+ * 82571 hardware supports TSO capabilities for IPv6 as well...
+- * no longer assume, we must. */
++ * no longer assume, we must.
++ */
+ if (skb->protocol == htons(ETH_P_IP))
+ tx_flags |= E1000_TX_FLAGS_IPV4;
+
+@@ -3316,14 +3460,16 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
+ while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
+ msleep(1);
+ /* e1000e_down has a dependency on max_frame_size */
+- adapter->hw.mac.max_frame_size = max_frame;
++ adapter->max_frame_size = max_frame;
+ if (netif_running(netdev))
+ e1000e_down(adapter);
+
+- /* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
++ /*
++ * NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
+ * means we reserve 2 more, this pushes us to allocate from the next
+ * larger slab size.
+- * i.e. RXBUFFER_2048 --> size-4096 slab */
++ * i.e. RXBUFFER_2048 --> size-4096 slab
++ */
+
+ if (max_frame <= 256)
+ adapter->rx_buffer_len = 256;
+@@ -3340,7 +3486,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
+ if ((max_frame == ETH_FRAME_LEN + ETH_FCS_LEN) ||
+ (max_frame == ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN))
+ adapter->rx_buffer_len = ETH_FRAME_LEN + VLAN_HLEN
+- + ETH_FCS_LEN ;
++ + ETH_FCS_LEN;
+
+ ndev_info(netdev, "changing MTU from %d to %d\n",
+ netdev->mtu, new_mtu);
+@@ -3361,9 +3507,8 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
+ {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct mii_ioctl_data *data = if_mii(ifr);
+- unsigned long irq_flags;
+
+- if (adapter->hw.media_type != e1000_media_type_copper)
++ if (adapter->hw.phy.media_type != e1000_media_type_copper)
+ return -EOPNOTSUPP;
+
+ switch (cmd) {
+@@ -3373,13 +3518,40 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
+ case SIOCGMIIREG:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+- spin_lock_irqsave(&adapter->stats_lock, irq_flags);
+- if (e1e_rphy(&adapter->hw, data->reg_num & 0x1F,
+- &data->val_out)) {
+- spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);
++ switch (data->reg_num & 0x1F) {
++ case MII_BMCR:
++ data->val_out = adapter->phy_regs.bmcr;
++ break;
++ case MII_BMSR:
++ data->val_out = adapter->phy_regs.bmsr;
++ break;
++ case MII_PHYSID1:
++ data->val_out = (adapter->hw.phy.id >> 16);
++ break;
++ case MII_PHYSID2:
++ data->val_out = (adapter->hw.phy.id & 0xFFFF);
++ break;
++ case MII_ADVERTISE:
++ data->val_out = adapter->phy_regs.advertise;
++ break;
++ case MII_LPA:
++ data->val_out = adapter->phy_regs.lpa;
++ break;
++ case MII_EXPANSION:
++ data->val_out = adapter->phy_regs.expansion;
++ break;
++ case MII_CTRL1000:
++ data->val_out = adapter->phy_regs.ctrl1000;
++ break;
++ case MII_STAT1000:
++ data->val_out = adapter->phy_regs.stat1000;
++ break;
++ case MII_ESTATUS:
++ data->val_out = adapter->phy_regs.estatus;
++ break;
++ default:
+ return -EIO;
+ }
+- spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);
+ break;
+ case SIOCSMIIREG:
+ default:
+@@ -3445,8 +3617,9 @@ static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
+ E1000_CTRL_EN_PHY_PWR_MGMT;
+ ew32(CTRL, ctrl);
+
+- if (adapter->hw.media_type == e1000_media_type_fiber ||
+- adapter->hw.media_type == e1000_media_type_internal_serdes) {
++ if (adapter->hw.phy.media_type == e1000_media_type_fiber ||
++ adapter->hw.phy.media_type ==
++ e1000_media_type_internal_serdes) {
+ /* keep the laser running in D3 */
+ ctrl_ext = er32(CTRL_EXT);
+ ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA;
+@@ -3476,8 +3649,10 @@ static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
+ if (adapter->hw.phy.type == e1000_phy_igp_3)
+ e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw);
+
+- /* Release control of h/w to f/w. If f/w is AMT enabled, this
+- * would have already happened in close and is redundant. */
++ /*
++ * Release control of h/w to f/w. If f/w is AMT enabled, this
++ * would have already happened in close and is redundant.
++ */
+ e1000_release_hw_control(adapter);
+
+ pci_disable_device(pdev);
+@@ -3552,9 +3727,11 @@ static int e1000_resume(struct pci_dev *pdev)
+
+ netif_device_attach(netdev);
+
+- /* If the controller has AMT, do not set DRV_LOAD until the interface
++ /*
++ * If the controller has AMT, do not set DRV_LOAD until the interface
+ * is up. For all other cases, let the f/w know that the h/w is now
+- * under the control of the driver. */
++ * under the control of the driver.
++ */
+ if (!(adapter->flags & FLAG_HAS_AMT) || !e1000e_check_mng_mode(&adapter->hw))
+ e1000_get_hw_control(adapter);
+
+@@ -3630,6 +3807,7 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+ pci_set_master(pdev);
++ pci_restore_state(pdev);
+
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ pci_enable_wake(pdev, PCI_D3cold, 0);
+@@ -3665,9 +3843,11 @@ static void e1000_io_resume(struct pci_dev *pdev)
+
+ netif_device_attach(netdev);
+
+- /* If the controller has AMT, do not set DRV_LOAD until the interface
++ /*
++ * If the controller has AMT, do not set DRV_LOAD until the interface
+ * is up. For all other cases, let the f/w know that the h/w is now
+- * under the control of the driver. */
++ * under the control of the driver.
++ */
+ if (!(adapter->flags & FLAG_HAS_AMT) ||
+ !e1000e_check_mng_mode(&adapter->hw))
+ e1000_get_hw_control(adapter);
+@@ -3678,7 +3858,7 @@ static void e1000_print_device_info(struct e1000_adapter *adapter)
+ {
+ struct e1000_hw *hw = &adapter->hw;
+ struct net_device *netdev = adapter->netdev;
+- u32 part_num;
++ u32 pba_num;
+
+ /* print bus type/speed/width info */
+ ndev_info(netdev, "(PCI Express:2.5GB/s:%s) "
+@@ -3693,10 +3873,10 @@ static void e1000_print_device_info(struct e1000_adapter *adapter)
+ ndev_info(netdev, "Intel(R) PRO/%s Network Connection\n",
+ (hw->phy.type == e1000_phy_ife)
+ ? "10/100" : "1000");
+- e1000e_read_part_num(hw, &part_num);
++ e1000e_read_pba_num(hw, &pba_num);
+ ndev_info(netdev, "MAC: %d, PHY: %d, PBA No: %06x-%03x\n",
+ hw->mac.type, hw->phy.type,
+- (part_num >> 8), (part_num & 0xff));
++ (pba_num >> 8), (pba_num & 0xff));
+ }
+
+ /**
+@@ -3754,6 +3934,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
+ goto err_pci_reg;
+
+ pci_set_master(pdev);
++ pci_save_state(pdev);
+
+ err = -ENOMEM;
+ netdev = alloc_etherdev(sizeof(struct e1000_adapter));
+@@ -3828,16 +4009,16 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
+ memcpy(&hw->nvm.ops, ei->nvm_ops, sizeof(hw->nvm.ops));
+ memcpy(&hw->phy.ops, ei->phy_ops, sizeof(hw->phy.ops));
+
+- err = ei->get_invariants(adapter);
++ err = ei->get_variants(adapter);
+ if (err)
+ goto err_hw_init;
+
+ hw->mac.ops.get_bus_info(&adapter->hw);
+
+- adapter->hw.phy.wait_for_link = 0;
++ adapter->hw.phy.autoneg_wait_to_complete = 0;
+
+ /* Copper options */
+- if (adapter->hw.media_type == e1000_media_type_copper) {
++ if (adapter->hw.phy.media_type == e1000_media_type_copper) {
+ adapter->hw.phy.mdix = AUTO_ALL_MODES;
+ adapter->hw.phy.disable_polarity_correction = 0;
+ adapter->hw.phy.ms_type = e1000_ms_hw_default;
+@@ -3861,15 +4042,19 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
+ if (pci_using_dac)
+ netdev->features |= NETIF_F_HIGHDMA;
+
+- /* We should not be using LLTX anymore, but we are still TX faster with
+- * it. */
++ /*
++ * We should not be using LLTX anymore, but we are still Tx faster with
++ * it.
++ */
+ netdev->features |= NETIF_F_LLTX;
+
+ if (e1000e_enable_mng_pass_thru(&adapter->hw))
+ adapter->flags |= FLAG_MNG_PT_ENABLED;
+
+- /* before reading the NVM, reset the controller to
+- * put the device in a known good starting state */
++ /*
++ * before reading the NVM, reset the controller to
++ * put the device in a known good starting state
++ */
+ adapter->hw.mac.ops.reset_hw(&adapter->hw);
+
+ /*
+@@ -3919,8 +4104,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
+ /* Initialize link parameters. User can change them with ethtool */
+ adapter->hw.mac.autoneg = 1;
+ adapter->fc_autoneg = 1;
+- adapter->hw.mac.original_fc = e1000_fc_default;
+- adapter->hw.mac.fc = e1000_fc_default;
++ adapter->hw.fc.original_type = e1000_fc_default;
++ adapter->hw.fc.type = e1000_fc_default;
+ adapter->hw.phy.autoneg_advertised = 0x2f;
+
+ /* ring size defaults */
+@@ -3963,9 +4148,11 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
+ /* reset the hardware with the new settings */
+ e1000e_reset(adapter);
+
+- /* If the controller has AMT, do not set DRV_LOAD until the interface
++ /*
++ * If the controller has AMT, do not set DRV_LOAD until the interface
+ * is up. For all other cases, let the f/w know that the h/w is now
+- * under the control of the driver. */
++ * under the control of the driver.
++ */
+ if (!(adapter->flags & FLAG_HAS_AMT) ||
+ !e1000e_check_mng_mode(&adapter->hw))
+ e1000_get_hw_control(adapter);
+@@ -4022,16 +4209,20 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+
+- /* flush_scheduled work may reschedule our watchdog task, so
+- * explicitly disable watchdog tasks from being rescheduled */
++ /*
++ * flush_scheduled work may reschedule our watchdog task, so
++ * explicitly disable watchdog tasks from being rescheduled
++ */
+ set_bit(__E1000_DOWN, &adapter->state);
+ del_timer_sync(&adapter->watchdog_timer);
+ del_timer_sync(&adapter->phy_info_timer);
+
+ flush_scheduled_work();
+
+- /* Release control of h/w to f/w. If f/w is AMT enabled, this
+- * would have already happened in close and is redundant. */
++ /*
++ * Release control of h/w to f/w. If f/w is AMT enabled, this
++ * would have already happened in close and is redundant.
++ */
+ e1000_release_hw_control(adapter);
+
+ unregister_netdev(netdev);
+@@ -4069,13 +4260,16 @@ static struct pci_device_id e1000_pci_tbl[] = {
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES_DUAL), board_82571 },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES_QUAD), board_82571 },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571PT_QUAD_COPPER), board_82571 },
++
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI), board_82572 },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_COPPER), board_82572 },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_FIBER), board_82572 },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_SERDES), board_82572 },
++
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_82573E), board_82573 },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_82573E_IAMT), board_82573 },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_82573L), board_82573 },
++
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_COPPER_DPT),
+ board_80003es2lan },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_COPPER_SPT),
+@@ -4084,6 +4278,7 @@ static struct pci_device_id e1000_pci_tbl[] = {
+ board_80003es2lan },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_SERDES_SPT),
+ board_80003es2lan },
++
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IFE), board_ich8lan },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IFE_G), board_ich8lan },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IFE_GT), board_ich8lan },
+@@ -4091,6 +4286,7 @@ static struct pci_device_id e1000_pci_tbl[] = {
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_C), board_ich8lan },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_M), board_ich8lan },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_M_AMT), board_ich8lan },
++
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE), board_ich9lan },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE_G), board_ich9lan },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE_GT), board_ich9lan },
+@@ -4108,7 +4304,7 @@ static struct pci_driver e1000_driver = {
+ .probe = e1000_probe,
+ .remove = __devexit_p(e1000_remove),
+ #ifdef CONFIG_PM
+- /* Power Managment Hooks */
++ /* Power Management Hooks */
+ .suspend = e1000_suspend,
+ .resume = e1000_resume,
+ #endif
+@@ -4127,7 +4323,7 @@ static int __init e1000_init_module(void)
+ int ret;
+ printk(KERN_INFO "%s: Intel(R) PRO/1000 Network Driver - %s\n",
+ e1000e_driver_name, e1000e_driver_version);
+- printk(KERN_INFO "%s: Copyright (c) 1999-2007 Intel Corporation.\n",
++ printk(KERN_INFO "%s: Copyright (c) 1999-2008 Intel Corporation.\n",
+ e1000e_driver_name);
+ ret = pci_register_driver(&e1000_driver);
+
+diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c
+index df266c3..a66b92e 100644
+--- a/drivers/net/e1000e/param.c
++++ b/drivers/net/e1000e/param.c
+@@ -1,7 +1,7 @@
+ /*******************************************************************************
+
+ Intel PRO/1000 Linux driver
+- Copyright(c) 1999 - 2007 Intel Corporation.
++ Copyright(c) 1999 - 2008 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+@@ -30,7 +30,8 @@
+
+ #include "e1000.h"
+
+-/* This is the only thing that needs to be changed to adjust the
++/*
++ * This is the only thing that needs to be changed to adjust the
+ * maximum number of ports that the driver can manage.
+ */
+
+@@ -46,7 +47,8 @@ module_param(copybreak, uint, 0644);
+ MODULE_PARM_DESC(copybreak,
+ "Maximum size of packet that is copied to a new buffer on receive");
+
+-/* All parameters are treated the same, as an integer array of values.
++/*
++ * All parameters are treated the same, as an integer array of values.
+ * This macro just reduces the need to repeat the same declaration code
+ * over and over (plus this helps to avoid typo bugs).
+ */
+@@ -60,8 +62,9 @@ MODULE_PARM_DESC(copybreak,
+ MODULE_PARM_DESC(X, desc);
+
+
+-/* Transmit Interrupt Delay in units of 1.024 microseconds
+- * Tx interrupt delay needs to typically be set to something non zero
++/*
++ * Transmit Interrupt Delay in units of 1.024 microseconds
++ * Tx interrupt delay needs to typically be set to something non zero
+ *
+ * Valid Range: 0-65535
+ */
+@@ -70,7 +73,8 @@ E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
+ #define MAX_TXDELAY 0xFFFF
+ #define MIN_TXDELAY 0
+
+-/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
++/*
++ * Transmit Absolute Interrupt Delay in units of 1.024 microseconds
+ *
+ * Valid Range: 0-65535
+ */
+@@ -79,8 +83,9 @@ E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
+ #define MAX_TXABSDELAY 0xFFFF
+ #define MIN_TXABSDELAY 0
+
+-/* Receive Interrupt Delay in units of 1.024 microseconds
+- * hardware will likely hang if you set this to anything but zero.
++/*
++ * Receive Interrupt Delay in units of 1.024 microseconds
++ * hardware will likely hang if you set this to anything but zero.
+ *
+ * Valid Range: 0-65535
+ */
+@@ -89,7 +94,8 @@ E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
+ #define MAX_RXDELAY 0xFFFF
+ #define MIN_RXDELAY 0
+
+-/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
++/*
++ * Receive Absolute Interrupt Delay in units of 1.024 microseconds
+ *
+ * Valid Range: 0-65535
+ */
+@@ -98,7 +104,8 @@ E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
+ #define MAX_RXABSDELAY 0xFFFF
+ #define MIN_RXABSDELAY 0
+
+-/* Interrupt Throttle Rate (interrupts/sec)
++/*
++ * Interrupt Throttle Rate (interrupts/sec)
+ *
+ * Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
+ */
+@@ -107,7 +114,8 @@ E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
+ #define MAX_ITR 100000
+ #define MIN_ITR 100
+
+-/* Enable Smart Power Down of the PHY
++/*
++ * Enable Smart Power Down of the PHY
+ *
+ * Valid Range: 0, 1
+ *
+@@ -115,7 +123,8 @@ E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
+ */
+ E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
+
+-/* Enable Kumeran Lock Loss workaround
++/*
++ * Enable Kumeran Lock Loss workaround
+ *
+ * Valid Range: 0, 1
+ *
+diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c
+index dab3c46..e102332 100644
+--- a/drivers/net/e1000e/phy.c
++++ b/drivers/net/e1000e/phy.c
+@@ -1,7 +1,7 @@
+ /*******************************************************************************
+
+ Intel PRO/1000 Linux driver
+- Copyright(c) 1999 - 2007 Intel Corporation.
++ Copyright(c) 1999 - 2008 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+@@ -116,7 +116,7 @@ s32 e1000e_phy_reset_dsp(struct e1000_hw *hw)
+ }
+
+ /**
+- * e1000_read_phy_reg_mdic - Read MDI control register
++ * e1000e_read_phy_reg_mdic - Read MDI control register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to be read
+ * @data: pointer to the read data
+@@ -124,7 +124,7 @@ s32 e1000e_phy_reset_dsp(struct e1000_hw *hw)
+ * Reads the MDI control register in the PHY at offset and stores the
+ * information read to data.
+ **/
+-static s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
++s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
+ {
+ struct e1000_phy_info *phy = &hw->phy;
+ u32 i, mdic = 0;
+@@ -134,7 +134,8 @@ static s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
+ return -E1000_ERR_PARAM;
+ }
+
+- /* Set up Op-code, Phy Address, and register offset in the MDI
++ /*
++ * Set up Op-code, Phy Address, and register offset in the MDI
+ * Control register. The MAC will take care of interfacing with the
+ * PHY to retrieve the desired data.
+ */
+@@ -144,8 +145,12 @@ static s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
+
+ ew32(MDIC, mdic);
+
+- /* Poll the ready bit to see if the MDI read completed */
+- for (i = 0; i < 64; i++) {
++ /*
++ * Poll the ready bit to see if the MDI read completed
++ * Increasing the time out as testing showed failures with
++ * the lower time out
++ */
++ for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
+ udelay(50);
+ mdic = er32(MDIC);
+ if (mdic & E1000_MDIC_READY)
+@@ -165,14 +170,14 @@ static s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
+ }
+
+ /**
+- * e1000_write_phy_reg_mdic - Write MDI control register
++ * e1000e_write_phy_reg_mdic - Write MDI control register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to write to
+ * @data: data to write to register at offset
+ *
+ * Writes data to MDI control register in the PHY at offset.
+ **/
+-static s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
++s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
+ {
+ struct e1000_phy_info *phy = &hw->phy;
+ u32 i, mdic = 0;
+@@ -182,7 +187,8 @@ static s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
+ return -E1000_ERR_PARAM;
+ }
+
+- /* Set up Op-code, Phy Address, and register offset in the MDI
++ /*
++ * Set up Op-code, Phy Address, and register offset in the MDI
+ * Control register. The MAC will take care of interfacing with the
+ * PHY to retrieve the desired data.
+ */
+@@ -193,9 +199,13 @@ static s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
+
+ ew32(MDIC, mdic);
+
+- /* Poll the ready bit to see if the MDI read completed */
+- for (i = 0; i < E1000_GEN_POLL_TIMEOUT; i++) {
+- udelay(5);
++ /*
++ * Poll the ready bit to see if the MDI read completed
++ * Increasing the time out as testing showed failures with
++ * the lower time out
++ */
++ for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
++ udelay(50);
+ mdic = er32(MDIC);
+ if (mdic & E1000_MDIC_READY)
+ break;
+@@ -204,6 +214,10 @@ static s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
+ hw_dbg(hw, "MDI Write did not complete\n");
+ return -E1000_ERR_PHY;
+ }
++ if (mdic & E1000_MDIC_ERROR) {
++ hw_dbg(hw, "MDI Error\n");
++ return -E1000_ERR_PHY;
++ }
+
+ return 0;
+ }
+@@ -226,9 +240,8 @@ s32 e1000e_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data)
+ if (ret_val)
+ return ret_val;
+
+- ret_val = e1000_read_phy_reg_mdic(hw,
+- MAX_PHY_REG_ADDRESS & offset,
+- data);
++ ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
++ data);
+
+ hw->phy.ops.release_phy(hw);
+
+@@ -252,9 +265,8 @@ s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data)
+ if (ret_val)
+ return ret_val;
+
+- ret_val = e1000_write_phy_reg_mdic(hw,
+- MAX_PHY_REG_ADDRESS & offset,
+- data);
++ ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
++ data);
+
+ hw->phy.ops.release_phy(hw);
+
+@@ -280,18 +292,17 @@ s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data)
+ return ret_val;
+
+ if (offset > MAX_PHY_MULTI_PAGE_REG) {
+- ret_val = e1000_write_phy_reg_mdic(hw,
+- IGP01E1000_PHY_PAGE_SELECT,
+- (u16)offset);
++ ret_val = e1000e_write_phy_reg_mdic(hw,
++ IGP01E1000_PHY_PAGE_SELECT,
++ (u16)offset);
+ if (ret_val) {
+ hw->phy.ops.release_phy(hw);
+ return ret_val;
+ }
+ }
+
+- ret_val = e1000_read_phy_reg_mdic(hw,
+- MAX_PHY_REG_ADDRESS & offset,
+- data);
++ ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
++ data);
+
+ hw->phy.ops.release_phy(hw);
+
+@@ -316,18 +327,17 @@ s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data)
+ return ret_val;
+
+ if (offset > MAX_PHY_MULTI_PAGE_REG) {
+- ret_val = e1000_write_phy_reg_mdic(hw,
+- IGP01E1000_PHY_PAGE_SELECT,
+- (u16)offset);
++ ret_val = e1000e_write_phy_reg_mdic(hw,
++ IGP01E1000_PHY_PAGE_SELECT,
++ (u16)offset);
+ if (ret_val) {
+ hw->phy.ops.release_phy(hw);
+ return ret_val;
+ }
+ }
+
+- ret_val = e1000_write_phy_reg_mdic(hw,
+- MAX_PHY_REG_ADDRESS & offset,
+- data);
++ ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
++ data);
+
+ hw->phy.ops.release_phy(hw);
+
+@@ -409,14 +419,17 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
+ s32 ret_val;
+ u16 phy_data;
+
+- /* Enable CRS on TX. This must be set for half-duplex operation. */
++ /* Enable CRS on Tx. This must be set for half-duplex operation. */
+ ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+- phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
++ /* For newer PHYs this bit is downshift enable */
++ if (phy->type == e1000_phy_m88)
++ phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
+
+- /* Options:
++ /*
++ * Options:
+ * MDI/MDI-X = 0 (default)
+ * 0 - Auto for all speeds
+ * 1 - MDI mode
+@@ -441,7 +454,8 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
+ break;
+ }
+
+- /* Options:
++ /*
++ * Options:
+ * disable_polarity_correction = 0 (default)
+ * Automatic Correction for Reversed Cable Polarity
+ * 0 - Disabled
+@@ -455,8 +469,9 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
+ if (ret_val)
+ return ret_val;
+
+- if (phy->revision < 4) {
+- /* Force TX_CLK in the Extended PHY Specific Control Register
++ if ((phy->type == e1000_phy_m88) && (phy->revision < 4)) {
++ /*
++ * Force TX_CLK in the Extended PHY Specific Control Register
+ * to 25MHz clock.
+ */
+ ret_val = e1e_rphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
+@@ -509,8 +524,11 @@ s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw)
+ return ret_val;
+ }
+
+- /* Wait 15ms for MAC to configure PHY from NVM settings. */
+- msleep(15);
++ /*
++ * Wait 100ms for MAC to configure PHY from NVM settings, to avoid
++ * timeout issues when LFS is enabled.
++ */
++ msleep(100);
+
+ /* disable lplu d0 during driver init */
+ ret_val = e1000_set_d0_lplu_state(hw, 0);
+@@ -543,19 +561,21 @@ s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw)
+
+ /* set auto-master slave resolution settings */
+ if (hw->mac.autoneg) {
+- /* when autonegotiation advertisement is only 1000Mbps then we
++ /*
++ * when autonegotiation advertisement is only 1000Mbps then we
+ * should disable SmartSpeed and enable Auto MasterSlave
+- * resolution as hardware default. */
++ * resolution as hardware default.
++ */
+ if (phy->autoneg_advertised == ADVERTISE_1000_FULL) {
+ /* Disable SmartSpeed */
+ ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+- &data);
++ &data);
+ if (ret_val)
+ return ret_val;
+
+ data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+- data);
++ data);
+ if (ret_val)
+ return ret_val;
+
+@@ -630,14 +650,16 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
+ return ret_val;
+ }
+
+- /* Need to parse both autoneg_advertised and fc and set up
++ /*
++ * Need to parse both autoneg_advertised and fc and set up
+ * the appropriate PHY registers. First we will parse for
+ * autoneg_advertised software override. Since we can advertise
+ * a plethora of combinations, we need to check each bit
+ * individually.
+ */
+
+- /* First we clear all the 10/100 mb speed bits in the Auto-Neg
++ /*
++ * First we clear all the 10/100 mb speed bits in the Auto-Neg
+ * Advertisement Register (Address 4) and the 1000 mb speed bits in
+ * the 1000Base-T Control Register (Address 9).
+ */
+@@ -683,7 +705,8 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
+ mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
+ }
+
+- /* Check for a software override of the flow control settings, and
++ /*
++ * Check for a software override of the flow control settings, and
+ * setup the PHY advertisement registers accordingly. If
+ * auto-negotiation is enabled, then software will have to set the
+ * "PAUSE" bits to the correct value in the Auto-Negotiation
+@@ -696,38 +719,42 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
+ * but not send pause frames).
+ * 2: Tx flow control is enabled (we can send pause frames
+ * but we do not support receiving pause frames).
+- * 3: Both Rx and TX flow control (symmetric) are enabled.
++ * 3: Both Rx and Tx flow control (symmetric) are enabled.
+ * other: No software override. The flow control configuration
+ * in the EEPROM is used.
+ */
+- switch (hw->mac.fc) {
++ switch (hw->fc.type) {
+ case e1000_fc_none:
+- /* Flow control (RX & TX) is completely disabled by a
++ /*
++ * Flow control (Rx & Tx) is completely disabled by a
+ * software over-ride.
+ */
+ mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
+ break;
+ case e1000_fc_rx_pause:
+- /* RX Flow control is enabled, and TX Flow control is
++ /*
++ * Rx Flow control is enabled, and Tx Flow control is
+ * disabled, by a software over-ride.
+- */
+- /* Since there really isn't a way to advertise that we are
+- * capable of RX Pause ONLY, we will advertise that we
+- * support both symmetric and asymmetric RX PAUSE. Later
++ *
++ * Since there really isn't a way to advertise that we are
++ * capable of Rx Pause ONLY, we will advertise that we
++ * support both symmetric and asymmetric Rx PAUSE. Later
+ * (in e1000e_config_fc_after_link_up) we will disable the
+ * hw's ability to send PAUSE frames.
+ */
+ mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
+ break;
+ case e1000_fc_tx_pause:
+- /* TX Flow control is enabled, and RX Flow control is
++ /*
++ * Tx Flow control is enabled, and Rx Flow control is
+ * disabled, by a software over-ride.
+ */
+ mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
+ mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
+ break;
+ case e1000_fc_full:
+- /* Flow control (both RX and TX) is enabled by a software
++ /*
++ * Flow control (both Rx and Tx) is enabled by a software
+ * over-ride.
+ */
+ mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
+@@ -758,7 +785,7 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
+ * Performs initial bounds checking on autoneg advertisement parameter, then
+ * configure to advertise the full capability. Setup the PHY to autoneg
+ * and restart the negotiation process between the link partner. If
+- * wait_for_link, then wait for autoneg to complete before exiting.
++ * autoneg_wait_to_complete, then wait for autoneg to complete before exiting.
+ **/
+ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
+ {
+@@ -766,12 +793,14 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
+ s32 ret_val;
+ u16 phy_ctrl;
+
+- /* Perform some bounds checking on the autoneg advertisement
++ /*
++ * Perform some bounds checking on the autoneg advertisement
+ * parameter.
+ */
+ phy->autoneg_advertised &= phy->autoneg_mask;
+
+- /* If autoneg_advertised is zero, we assume it was not defaulted
++ /*
++ * If autoneg_advertised is zero, we assume it was not defaulted
+ * by the calling code so we set to advertise full capability.
+ */
+ if (phy->autoneg_advertised == 0)
+@@ -785,7 +814,8 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
+ }
+ hw_dbg(hw, "Restarting Auto-Neg\n");
+
+- /* Restart auto-negotiation by setting the Auto Neg Enable bit and
++ /*
++ * Restart auto-negotiation by setting the Auto Neg Enable bit and
+ * the Auto Neg Restart bit in the PHY control register.
+ */
+ ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_ctrl);
+@@ -797,10 +827,11 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
+ if (ret_val)
+ return ret_val;
+
+- /* Does the user want to wait for Auto-Neg to complete here, or
++ /*
++ * Does the user want to wait for Auto-Neg to complete here, or
+ * check at a later time (for example, callback routine).
+ */
+- if (phy->wait_for_link) {
++ if (phy->autoneg_wait_to_complete) {
+ ret_val = e1000_wait_autoneg(hw);
+ if (ret_val) {
+ hw_dbg(hw, "Error while waiting for "
+@@ -829,14 +860,18 @@ s32 e1000e_setup_copper_link(struct e1000_hw *hw)
+ bool link;
+
+ if (hw->mac.autoneg) {
+- /* Setup autoneg and flow control advertisement and perform
+- * autonegotiation. */
++ /*
++ * Setup autoneg and flow control advertisement and perform
++ * autonegotiation.
++ */
+ ret_val = e1000_copper_link_autoneg(hw);
+ if (ret_val)
+ return ret_val;
+ } else {
+- /* PHY will be set to 10H, 10F, 100H or 100F
+- * depending on user settings. */
++ /*
++ * PHY will be set to 10H, 10F, 100H or 100F
++ * depending on user settings.
++ */
+ hw_dbg(hw, "Forcing Speed and Duplex\n");
+ ret_val = e1000_phy_force_speed_duplex(hw);
+ if (ret_val) {
+@@ -845,7 +880,8 @@ s32 e1000e_setup_copper_link(struct e1000_hw *hw)
+ }
+ }
+
+- /* Check link status. Wait up to 100 microseconds for link to become
++ /*
++ * Check link status. Wait up to 100 microseconds for link to become
+ * valid.
+ */
+ ret_val = e1000e_phy_has_link_generic(hw,
+@@ -891,7 +927,8 @@ s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw)
+ if (ret_val)
+ return ret_val;
+
+- /* Clear Auto-Crossover to force MDI manually. IGP requires MDI
++ /*
++ * Clear Auto-Crossover to force MDI manually. IGP requires MDI
+ * forced whenever speed and duplex are forced.
+ */
+ ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
+@@ -909,7 +946,7 @@ s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw)
+
+ udelay(1);
+
+- if (phy->wait_for_link) {
++ if (phy->autoneg_wait_to_complete) {
+ hw_dbg(hw, "Waiting for forced speed/duplex link on IGP phy.\n");
+
+ ret_val = e1000e_phy_has_link_generic(hw,
+@@ -941,7 +978,7 @@ s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw)
+ * Calls the PHY setup function to force speed and duplex. Clears the
+ * auto-crossover to force MDI manually. Resets the PHY to commit the
+ * changes. If time expires while waiting for link up, we reset the DSP.
+- * After reset, TX_CLK and CRS on TX must be set. Return successful upon
++ * After reset, TX_CLK and CRS on Tx must be set. Return successful upon
+ * successful completion, else return corresponding error code.
+ **/
+ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
+@@ -951,7 +988,8 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
+ u16 phy_data;
+ bool link;
+
+- /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI
++ /*
++ * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI
+ * forced whenever speed and duplex are forced.
+ */
+ ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+@@ -980,7 +1018,7 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
+
+ udelay(1);
+
+- if (phy->wait_for_link) {
++ if (phy->autoneg_wait_to_complete) {
+ hw_dbg(hw, "Waiting for forced speed/duplex link on M88 phy.\n");
+
+ ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
+@@ -989,10 +1027,12 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
+ return ret_val;
+
+ if (!link) {
+- /* We didn't get link.
++ /*
++ * We didn't get link.
+ * Reset the DSP and cross our fingers.
+ */
+- ret_val = e1e_wphy(hw, M88E1000_PHY_PAGE_SELECT, 0x001d);
++ ret_val = e1e_wphy(hw, M88E1000_PHY_PAGE_SELECT,
++ 0x001d);
+ if (ret_val)
+ return ret_val;
+ ret_val = e1000e_phy_reset_dsp(hw);
+@@ -1011,7 +1051,8 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
+ if (ret_val)
+ return ret_val;
+
+- /* Resetting the phy means we need to re-force TX_CLK in the
++ /*
++ * Resetting the phy means we need to re-force TX_CLK in the
+ * Extended PHY Specific Control Register to 25MHz clock from
+ * the reset value of 2.5MHz.
+ */
+@@ -1020,7 +1061,8 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
+ if (ret_val)
+ return ret_val;
+
+- /* In addition, we must re-enable CRS on Tx for both half and full
++ /*
++ * In addition, we must re-enable CRS on Tx for both half and full
+ * duplex.
+ */
+ ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+@@ -1051,7 +1093,7 @@ void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl)
+ u32 ctrl;
+
+ /* Turn off flow control when forcing speed/duplex */
+- mac->fc = e1000_fc_none;
++ hw->fc.type = e1000_fc_none;
+
+ /* Force speed/duplex on the mac */
+ ctrl = er32(CTRL);
+@@ -1119,35 +1161,35 @@ s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active)
+
+ if (!active) {
+ data &= ~IGP02E1000_PM_D3_LPLU;
+- ret_val = e1e_wphy(hw,
+- IGP02E1000_PHY_POWER_MGMT,
+- data);
++ ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data);
+ if (ret_val)
+ return ret_val;
+- /* LPLU and SmartSpeed are mutually exclusive. LPLU is used
++ /*
++ * LPLU and SmartSpeed are mutually exclusive. LPLU is used
+ * during Dx states where the power conservation is most
+ * important. During driver activity we should enable
+- * SmartSpeed, so performance is maintained. */
++ * SmartSpeed, so performance is maintained.
++ */
+ if (phy->smart_speed == e1000_smart_speed_on) {
+ ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+- &data);
++ &data);
+ if (ret_val)
+ return ret_val;
+
+ data |= IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+- data);
++ data);
+ if (ret_val)
+ return ret_val;
+ } else if (phy->smart_speed == e1000_smart_speed_off) {
+ ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+- &data);
++ &data);
+ if (ret_val)
+ return ret_val;
+
+ data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,
+- data);
++ data);
+ if (ret_val)
+ return ret_val;
+ }
+@@ -1249,8 +1291,10 @@ static s32 e1000_check_polarity_igp(struct e1000_hw *hw)
+ s32 ret_val;
+ u16 data, offset, mask;
+
+- /* Polarity is determined based on the speed of
+- * our connection. */
++ /*
++ * Polarity is determined based on the speed of
++ * our connection.
++ */
+ ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_STATUS, &data);
+ if (ret_val)
+ return ret_val;
+@@ -1260,7 +1304,8 @@ static s32 e1000_check_polarity_igp(struct e1000_hw *hw)
+ offset = IGP01E1000_PHY_PCS_INIT_REG;
+ mask = IGP01E1000_PHY_POLARITY_MASK;
+ } else {
+- /* This really only applies to 10Mbps since
++ /*
++ * This really only applies to 10Mbps since
+ * there is no polarity for 100Mbps (always 0).
+ */
+ offset = IGP01E1000_PHY_PORT_STATUS;
+@@ -1278,7 +1323,7 @@ static s32 e1000_check_polarity_igp(struct e1000_hw *hw)
+ }
+
+ /**
+- * e1000_wait_autoneg - Wait for auto-neg compeletion
++ * e1000_wait_autoneg - Wait for auto-neg completion
+ * @hw: pointer to the HW structure
+ *
+ * Waits for auto-negotiation to complete or for the auto-negotiation time
+@@ -1302,7 +1347,8 @@ static s32 e1000_wait_autoneg(struct e1000_hw *hw)
+ msleep(100);
+ }
+
+- /* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
++ /*
++ * PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
+ * has completed.
+ */
+ return ret_val;
+@@ -1324,7 +1370,8 @@ s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
+ u16 i, phy_status;
+
+ for (i = 0; i < iterations; i++) {
+- /* Some PHYs require the PHY_STATUS register to be read
++ /*
++ * Some PHYs require the PHY_STATUS register to be read
+ * twice due to the link bit being sticky. No harm doing
+ * it across the board.
+ */
+@@ -1412,10 +1459,12 @@ s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw)
+ if (ret_val)
+ return ret_val;
+
+- /* Getting bits 15:9, which represent the combination of
++ /*
++ * Getting bits 15:9, which represent the combination of
+ * course and fine gain values. The result is a number
+ * that can be put into the lookup table to obtain the
+- * approximate cable length. */
++ * approximate cable length.
++ */
+ cur_agc_index = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
+ IGP02E1000_AGC_LENGTH_MASK;
+
+@@ -1466,7 +1515,7 @@ s32 e1000e_get_phy_info_m88(struct e1000_hw *hw)
+ u16 phy_data;
+ bool link;
+
+- if (hw->media_type != e1000_media_type_copper) {
++ if (hw->phy.media_type != e1000_media_type_copper) {
+ hw_dbg(hw, "Phy info is only valid for copper media\n");
+ return -E1000_ERR_CONFIG;
+ }
+diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
+index a8d3280..f5dacce 100644
+--- a/drivers/net/ehea/ehea.h
++++ b/drivers/net/ehea/ehea.h
+@@ -422,7 +422,7 @@ struct ehea_fw_handle_entry {
+ struct ehea_fw_handle_array {
+ struct ehea_fw_handle_entry *arr;
+ int num_entries;
+- struct semaphore lock;
++ struct mutex lock;
+ };
+
+ struct ehea_bcmc_reg_entry {
+@@ -435,7 +435,7 @@ struct ehea_bcmc_reg_entry {
+ struct ehea_bcmc_reg_array {
+ struct ehea_bcmc_reg_entry *arr;
+ int num_entries;
+- struct semaphore lock;
++ struct mutex lock;
+ };
+
+ #define EHEA_PORT_UP 1
+@@ -453,7 +453,7 @@ struct ehea_port {
+ struct vlan_group *vgrp;
+ struct ehea_eq *qp_eq;
+ struct work_struct reset_task;
+- struct semaphore port_lock;
++ struct mutex port_lock;
+ char int_aff_name[EHEA_IRQ_NAME_SIZE];
+ int allmulti; /* Indicates IFF_ALLMULTI state */
+ int promisc; /* Indicates IFF_PROMISC state */
+diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
+index f460b62..f9bc21c 100644
+--- a/drivers/net/ehea/ehea_main.c
++++ b/drivers/net/ehea/ehea_main.c
+@@ -36,6 +36,7 @@
+ #include <linux/notifier.h>
+ #include <linux/reboot.h>
+ #include <asm/kexec.h>
++#include <linux/mutex.h>
+
+ #include <net/ip.h>
+
+@@ -99,7 +100,7 @@ static int port_name_cnt;
+ static LIST_HEAD(adapter_list);
+ u64 ehea_driver_flags;
+ struct work_struct ehea_rereg_mr_task;
+-struct semaphore dlpar_mem_lock;
++static DEFINE_MUTEX(dlpar_mem_lock);
+ struct ehea_fw_handle_array ehea_fw_handles;
+ struct ehea_bcmc_reg_array ehea_bcmc_regs;
+
+@@ -1761,7 +1762,7 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa)
+
+ memcpy(dev->dev_addr, mac_addr->sa_data, dev->addr_len);
+
+- down(&ehea_bcmc_regs.lock);
++ mutex_lock(&ehea_bcmc_regs.lock);
+
+ /* Deregister old MAC in pHYP */
+ ret = ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
+@@ -1779,7 +1780,7 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa)
+
+ out_upregs:
+ ehea_update_bcmc_registrations();
+- up(&ehea_bcmc_regs.lock);
++ mutex_unlock(&ehea_bcmc_regs.lock);
+ out_free:
+ kfree(cb0);
+ out:
+@@ -1941,7 +1942,7 @@ static void ehea_set_multicast_list(struct net_device *dev)
+ }
+ ehea_promiscuous(dev, 0);
+
+- down(&ehea_bcmc_regs.lock);
++ mutex_lock(&ehea_bcmc_regs.lock);
+
+ if (dev->flags & IFF_ALLMULTI) {
+ ehea_allmulti(dev, 1);
+@@ -1972,7 +1973,7 @@ static void ehea_set_multicast_list(struct net_device *dev)
+ }
+ out:
+ ehea_update_bcmc_registrations();
+- up(&ehea_bcmc_regs.lock);
++ mutex_unlock(&ehea_bcmc_regs.lock);
+ return;
+ }
+
+@@ -2455,7 +2456,7 @@ static int ehea_up(struct net_device *dev)
+ if (port->state == EHEA_PORT_UP)
+ return 0;
+
+- down(&ehea_fw_handles.lock);
++ mutex_lock(&ehea_fw_handles.lock);
+
+ ret = ehea_port_res_setup(port, port->num_def_qps,
+ port->num_add_tx_qps);
+@@ -2493,7 +2494,7 @@ static int ehea_up(struct net_device *dev)
+ }
+ }
+
+- down(&ehea_bcmc_regs.lock);
++ mutex_lock(&ehea_bcmc_regs.lock);
+
+ ret = ehea_broadcast_reg_helper(port, H_REG_BCMC);
+ if (ret) {
+@@ -2516,10 +2517,10 @@ out:
+ ehea_info("Failed starting %s. ret=%i", dev->name, ret);
+
+ ehea_update_bcmc_registrations();
+- up(&ehea_bcmc_regs.lock);
++ mutex_unlock(&ehea_bcmc_regs.lock);
+
+ ehea_update_firmware_handles();
+- up(&ehea_fw_handles.lock);
++ mutex_unlock(&ehea_fw_handles.lock);
+
+ return ret;
+ }
+@@ -2545,7 +2546,7 @@ static int ehea_open(struct net_device *dev)
+ int ret;
+ struct ehea_port *port = netdev_priv(dev);
+
+- down(&port->port_lock);
++ mutex_lock(&port->port_lock);
+
+ if (netif_msg_ifup(port))
+ ehea_info("enabling port %s", dev->name);
+@@ -2556,7 +2557,7 @@ static int ehea_open(struct net_device *dev)
+ netif_start_queue(dev);
+ }
+
+- up(&port->port_lock);
++ mutex_unlock(&port->port_lock);
+
+ return ret;
+ }
+@@ -2569,18 +2570,18 @@ static int ehea_down(struct net_device *dev)
+ if (port->state == EHEA_PORT_DOWN)
+ return 0;
+
+- down(&ehea_bcmc_regs.lock);
++ mutex_lock(&ehea_fw_handles.lock);
++
++ mutex_lock(&ehea_bcmc_regs.lock);
+ ehea_drop_multicast_list(dev);
+ ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
+
+ ehea_free_interrupts(dev);
+
+- down(&ehea_fw_handles.lock);
+-
+ port->state = EHEA_PORT_DOWN;
+
+ ehea_update_bcmc_registrations();
+- up(&ehea_bcmc_regs.lock);
++ mutex_unlock(&ehea_bcmc_regs.lock);
+
+ ret = ehea_clean_all_portres(port);
+ if (ret)
+@@ -2588,7 +2589,7 @@ static int ehea_down(struct net_device *dev)
+ dev->name, ret);
+
+ ehea_update_firmware_handles();
+- up(&ehea_fw_handles.lock);
++ mutex_unlock(&ehea_fw_handles.lock);
+
+ return ret;
+ }
+@@ -2602,15 +2603,15 @@ static int ehea_stop(struct net_device *dev)
+ ehea_info("disabling port %s", dev->name);
+
+ flush_scheduled_work();
+- down(&port->port_lock);
++ mutex_lock(&port->port_lock);
+ netif_stop_queue(dev);
+ port_napi_disable(port);
+ ret = ehea_down(dev);
+- up(&port->port_lock);
++ mutex_unlock(&port->port_lock);
+ return ret;
+ }
+
+-void ehea_purge_sq(struct ehea_qp *orig_qp)
++static void ehea_purge_sq(struct ehea_qp *orig_qp)
+ {
+ struct ehea_qp qp = *orig_qp;
+ struct ehea_qp_init_attr *init_attr = &qp.init_attr;
+@@ -2624,7 +2625,7 @@ void ehea_purge_sq(struct ehea_qp *orig_qp)
+ }
+ }
+
+-void ehea_flush_sq(struct ehea_port *port)
++static void ehea_flush_sq(struct ehea_port *port)
+ {
+ int i;
+
+@@ -2820,7 +2821,7 @@ static void ehea_reset_port(struct work_struct *work)
+ struct net_device *dev = port->netdev;
+
+ port->resets++;
+- down(&port->port_lock);
++ mutex_lock(&port->port_lock);
+ netif_stop_queue(dev);
+
+ port_napi_disable(port);
+@@ -2840,7 +2841,7 @@ static void ehea_reset_port(struct work_struct *work)
+
+ netif_wake_queue(dev);
+ out:
+- up(&port->port_lock);
++ mutex_unlock(&port->port_lock);
+ return;
+ }
+
+@@ -2849,7 +2850,7 @@ static void ehea_rereg_mrs(struct work_struct *work)
+ int ret, i;
+ struct ehea_adapter *adapter;
+
+- down(&dlpar_mem_lock);
++ mutex_lock(&dlpar_mem_lock);
+ ehea_info("LPAR memory enlarged - re-initializing driver");
+
+ list_for_each_entry(adapter, &adapter_list, list)
+@@ -2857,22 +2858,24 @@ static void ehea_rereg_mrs(struct work_struct *work)
+ /* Shutdown all ports */
+ for (i = 0; i < EHEA_MAX_PORTS; i++) {
+ struct ehea_port *port = adapter->port[i];
++ struct net_device *dev;
+
+- if (port) {
+- struct net_device *dev = port->netdev;
++ if (!port)
++ continue;
+
+- if (dev->flags & IFF_UP) {
+- down(&port->port_lock);
+- netif_stop_queue(dev);
+- ehea_flush_sq(port);
+- ret = ehea_stop_qps(dev);
+- if (ret) {
+- up(&port->port_lock);
+- goto out;
+- }
+- port_napi_disable(port);
+- up(&port->port_lock);
++ dev = port->netdev;
++
++ if (dev->flags & IFF_UP) {
++ mutex_lock(&port->port_lock);
++ netif_stop_queue(dev);
++ ehea_flush_sq(port);
++ ret = ehea_stop_qps(dev);
++ if (ret) {
++ mutex_unlock(&port->port_lock);
++ goto out;
+ }
++ port_napi_disable(port);
++ mutex_unlock(&port->port_lock);
+ }
+ }
+
+@@ -2912,17 +2915,17 @@ static void ehea_rereg_mrs(struct work_struct *work)
+ struct net_device *dev = port->netdev;
+
+ if (dev->flags & IFF_UP) {
+- down(&port->port_lock);
++ mutex_lock(&port->port_lock);
+ port_napi_enable(port);
+ ret = ehea_restart_qps(dev);
+ if (!ret)
+ netif_wake_queue(dev);
+- up(&port->port_lock);
++ mutex_unlock(&port->port_lock);
+ }
+ }
+ }
+ }
+- up(&dlpar_mem_lock);
++ mutex_unlock(&dlpar_mem_lock);
+ ehea_info("re-initializing driver complete");
+ out:
+ return;
+@@ -3083,7 +3086,7 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
+
+ port = netdev_priv(dev);
+
+- sema_init(&port->port_lock, 1);
++ mutex_init(&port->port_lock);
+ port->state = EHEA_PORT_DOWN;
+ port->sig_comp_iv = sq_entries / 10;
+
+@@ -3362,7 +3365,7 @@ static int __devinit ehea_probe_adapter(struct of_device *dev,
+ ehea_error("Invalid ibmebus device probed");
+ return -EINVAL;
+ }
+- down(&ehea_fw_handles.lock);
++ mutex_lock(&ehea_fw_handles.lock);
+
+ adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
+ if (!adapter) {
+@@ -3446,7 +3449,7 @@ out_free_ad:
+
+ out:
+ ehea_update_firmware_handles();
+- up(&ehea_fw_handles.lock);
++ mutex_unlock(&ehea_fw_handles.lock);
+ return ret;
+ }
+
+@@ -3465,7 +3468,7 @@ static int __devexit ehea_remove(struct of_device *dev)
+
+ flush_scheduled_work();
+
+- down(&ehea_fw_handles.lock);
++ mutex_lock(&ehea_fw_handles.lock);
+
+ ibmebus_free_irq(adapter->neq->attr.ist1, adapter);
+ tasklet_kill(&adapter->neq_tasklet);
+@@ -3476,7 +3479,7 @@ static int __devexit ehea_remove(struct of_device *dev)
+ kfree(adapter);
+
+ ehea_update_firmware_handles();
+- up(&ehea_fw_handles.lock);
++ mutex_unlock(&ehea_fw_handles.lock);
+
+ return 0;
+ }
+@@ -3563,9 +3566,8 @@ int __init ehea_module_init(void)
+ memset(&ehea_fw_handles, 0, sizeof(ehea_fw_handles));
+ memset(&ehea_bcmc_regs, 0, sizeof(ehea_bcmc_regs));
+
+- sema_init(&dlpar_mem_lock, 1);
+- sema_init(&ehea_fw_handles.lock, 1);
+- sema_init(&ehea_bcmc_regs.lock, 1);
++ mutex_init(&ehea_fw_handles.lock);
++ mutex_init(&ehea_bcmc_regs.lock);
+
+ ret = check_module_parm();
+ if (ret)
+diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
+index fe59c27..e5e6352 100644
+--- a/drivers/net/fec_mpc52xx.c
++++ b/drivers/net/fec_mpc52xx.c
+@@ -198,7 +198,7 @@ static int mpc52xx_fec_init_phy(struct net_device *dev)
+ struct phy_device *phydev;
+ char phy_id[BUS_ID_SIZE];
+
+- snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT,
++ snprintf(phy_id, BUS_ID_SIZE, "%x:%02x",
+ (unsigned int)dev->base_addr, priv->phy_addr);
+
+ priv->link = PHY_DOWN;
+diff --git a/drivers/net/fec_mpc52xx_phy.c b/drivers/net/fec_mpc52xx_phy.c
+index 1d0cd1d..f563444 100644
+--- a/drivers/net/fec_mpc52xx_phy.c
++++ b/drivers/net/fec_mpc52xx_phy.c
+@@ -124,7 +124,7 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of, const struct of_device_i
+ goto out_free;
+ }
+
+- bus->id = res.start;
++ snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start);
+ bus->priv = priv;
+
+ bus->dev = dev;
+diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
+index 9f088a4..35f66d4 100644
+--- a/drivers/net/forcedeth.c
++++ b/drivers/net/forcedeth.c
+@@ -29,90 +29,6 @@
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+- * Changelog:
+- * 0.01: 05 Oct 2003: First release that compiles without warnings.
+- * 0.02: 05 Oct 2003: Fix bug for nv_drain_tx: do not try to free NULL skbs.
+- * Check all PCI BARs for the register window.
+- * udelay added to mii_rw.
+- * 0.03: 06 Oct 2003: Initialize dev->irq.
+- * 0.04: 07 Oct 2003: Initialize np->lock, reduce handled irqs, add printks.
+- * 0.05: 09 Oct 2003: printk removed again, irq status print tx_timeout.
+- * 0.06: 10 Oct 2003: MAC Address read updated, pff flag generation updated,
+- * irq mask updated
+- * 0.07: 14 Oct 2003: Further irq mask updates.
+- * 0.08: 20 Oct 2003: rx_desc.Length initialization added, nv_alloc_rx refill
+- * added into irq handler, NULL check for drain_ring.
+- * 0.09: 20 Oct 2003: Basic link speed irq implementation. Only handle the
+- * requested interrupt sources.
+- * 0.10: 20 Oct 2003: First cleanup for release.
+- * 0.11: 21 Oct 2003: hexdump for tx added, rx buffer sizes increased.
+- * MAC Address init fix, set_multicast cleanup.
+- * 0.12: 23 Oct 2003: Cleanups for release.
+- * 0.13: 25 Oct 2003: Limit for concurrent tx packets increased to 10.
+- * Set link speed correctly. start rx before starting
+- * tx (nv_start_rx sets the link speed).
+- * 0.14: 25 Oct 2003: Nic dependant irq mask.
+- * 0.15: 08 Nov 2003: fix smp deadlock with set_multicast_list during
+- * open.
+- * 0.16: 15 Nov 2003: include file cleanup for ppc64, rx buffer size
+- * increased to 1628 bytes.
+- * 0.17: 16 Nov 2003: undo rx buffer size increase. Substract 1 from
+- * the tx length.
+- * 0.18: 17 Nov 2003: fix oops due to late initialization of dev_stats
+- * 0.19: 29 Nov 2003: Handle RxNoBuf, detect & handle invalid mac
+- * addresses, really stop rx if already running
+- * in nv_start_rx, clean up a bit.
+- * 0.20: 07 Dec 2003: alloc fixes
+- * 0.21: 12 Jan 2004: additional alloc fix, nic polling fix.
+- * 0.22: 19 Jan 2004: reprogram timer to a sane rate, avoid lockup
+- * on close.
+- * 0.23: 26 Jan 2004: various small cleanups
+- * 0.24: 27 Feb 2004: make driver even less anonymous in backtraces
+- * 0.25: 09 Mar 2004: wol support
+- * 0.26: 03 Jun 2004: netdriver specific annotation, sparse-related fixes
+- * 0.27: 19 Jun 2004: Gigabit support, new descriptor rings,
+- * added CK804/MCP04 device IDs, code fixes
+- * for registers, link status and other minor fixes.
+- * 0.28: 21 Jun 2004: Big cleanup, making driver mostly endian safe
+- * 0.29: 31 Aug 2004: Add backup timer for link change notification.
+- * 0.30: 25 Sep 2004: rx checksum support for nf 250 Gb. Add rx reset
+- * into nv_close, otherwise reenabling for wol can
+- * cause DMA to kfree'd memory.
+- * 0.31: 14 Nov 2004: ethtool support for getting/setting link
+- * capabilities.
+- * 0.32: 16 Apr 2005: RX_ERROR4 handling added.
+- * 0.33: 16 May 2005: Support for MCP51 added.
+- * 0.34: 18 Jun 2005: Add DEV_NEED_LINKTIMER to all nForce nics.
+- * 0.35: 26 Jun 2005: Support for MCP55 added.
+- * 0.36: 28 Jun 2005: Add jumbo frame support.
+- * 0.37: 10 Jul 2005: Additional ethtool support, cleanup of pci id list
+- * 0.38: 16 Jul 2005: tx irq rewrite: Use global flags instead of
+- * per-packet flags.
+- * 0.39: 18 Jul 2005: Add 64bit descriptor support.
+- * 0.40: 19 Jul 2005: Add support for mac address change.
+- * 0.41: 30 Jul 2005: Write back original MAC in nv_close instead
+- * of nv_remove
+- * 0.42: 06 Aug 2005: Fix lack of link speed initialization
+- * in the second (and later) nv_open call
+- * 0.43: 10 Aug 2005: Add support for tx checksum.
+- * 0.44: 20 Aug 2005: Add support for scatter gather and segmentation.
+- * 0.45: 18 Sep 2005: Remove nv_stop/start_rx from every link check
+- * 0.46: 20 Oct 2005: Add irq optimization modes.
+- * 0.47: 26 Oct 2005: Add phyaddr 0 in phy scan.
+- * 0.48: 24 Dec 2005: Disable TSO, bugfix for pci_map_single
+- * 0.49: 10 Dec 2005: Fix tso for large buffers.
+- * 0.50: 20 Jan 2006: Add 8021pq tagging support.
+- * 0.51: 20 Jan 2006: Add 64bit consistent memory allocation for rings.
+- * 0.52: 20 Jan 2006: Add MSI/MSIX support.
+- * 0.53: 19 Mar 2006: Fix init from low power mode and add hw reset.
+- * 0.54: 21 Mar 2006: Fix spin locks for multi irqs and cleanup.
+- * 0.55: 22 Mar 2006: Add flow control (pause frame).
+- * 0.56: 22 Mar 2006: Additional ethtool config and moduleparam support.
+- * 0.57: 14 May 2006: Mac address set in probe/remove and order corrections.
+- * 0.58: 30 Oct 2006: Added support for sideband management unit.
+- * 0.59: 30 Oct 2006: Added support for recoverable error.
+- * 0.60: 20 Jan 2007: Code optimizations for rings, rx & tx data paths, and stats.
+- *
+ * Known bugs:
+ * We suspect that on some hardware no TX done interrupts are generated.
+ * This means recovery from netif_stop_queue only happens if the hw timer
+@@ -123,11 +39,6 @@
+ * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
+ * superfluous timer interrupts from the nic.
+ */
+-#ifdef CONFIG_FORCEDETH_NAPI
+-#define DRIVERNAPI "-NAPI"
+-#else
+-#define DRIVERNAPI
+-#endif
+ #define FORCEDETH_VERSION "0.61"
+ #define DRV_NAME "forcedeth"
+
+@@ -185,6 +96,7 @@
+ #define DEV_HAS_PAUSEFRAME_TX_V2 0x10000 /* device supports tx pause frames version 2 */
+ #define DEV_HAS_PAUSEFRAME_TX_V3 0x20000 /* device supports tx pause frames version 3 */
+ #define DEV_NEED_TX_LIMIT 0x40000 /* device needs to limit tx */
++#define DEV_HAS_GEAR_MODE 0x80000 /* device supports gear mode */
+
+ enum {
+ NvRegIrqStatus = 0x000,
+@@ -263,11 +175,13 @@ enum {
+ NvRegReceiverStatus = 0x98,
+ #define NVREG_RCVSTAT_BUSY 0x01
+
+- NvRegRandomSeed = 0x9c,
+-#define NVREG_RNDSEED_MASK 0x00ff
+-#define NVREG_RNDSEED_FORCE 0x7f00
+-#define NVREG_RNDSEED_FORCE2 0x2d00
+-#define NVREG_RNDSEED_FORCE3 0x7400
++ NvRegSlotTime = 0x9c,
++#define NVREG_SLOTTIME_LEGBF_ENABLED 0x80000000
++#define NVREG_SLOTTIME_10_100_FULL 0x00007f00
++#define NVREG_SLOTTIME_1000_FULL 0x0003ff00
++#define NVREG_SLOTTIME_HALF 0x0000ff00
++#define NVREG_SLOTTIME_DEFAULT 0x00007f00
++#define NVREG_SLOTTIME_MASK 0x000000ff
+
+ NvRegTxDeferral = 0xA0,
+ #define NVREG_TX_DEFERRAL_DEFAULT 0x15050f
+@@ -290,6 +204,11 @@ enum {
+
+ NvRegPhyInterface = 0xC0,
+ #define PHY_RGMII 0x10000000
++ NvRegBackOffControl = 0xC4,
++#define NVREG_BKOFFCTRL_DEFAULT 0x70000000
++#define NVREG_BKOFFCTRL_SEED_MASK 0x000003ff
++#define NVREG_BKOFFCTRL_SELECT 24
++#define NVREG_BKOFFCTRL_GEAR 12
+
+ NvRegTxRingPhysAddr = 0x100,
+ NvRegRxRingPhysAddr = 0x104,
+@@ -441,6 +360,7 @@ union ring_type {
+
+ #define NV_TX_LASTPACKET (1<<16)
+ #define NV_TX_RETRYERROR (1<<19)
++#define NV_TX_RETRYCOUNT_MASK (0xF<<20)
+ #define NV_TX_FORCED_INTERRUPT (1<<24)
+ #define NV_TX_DEFERRED (1<<26)
+ #define NV_TX_CARRIERLOST (1<<27)
+@@ -451,6 +371,7 @@ union ring_type {
+
+ #define NV_TX2_LASTPACKET (1<<29)
+ #define NV_TX2_RETRYERROR (1<<18)
++#define NV_TX2_RETRYCOUNT_MASK (0xF<<19)
+ #define NV_TX2_FORCED_INTERRUPT (1<<30)
+ #define NV_TX2_DEFERRED (1<<25)
+ #define NV_TX2_CARRIERLOST (1<<26)
+@@ -562,16 +483,22 @@ union ring_type {
+ #define DESC_VER_3 3
+
+ /* PHY defines */
+-#define PHY_OUI_MARVELL 0x5043
+-#define PHY_OUI_CICADA 0x03f1
+-#define PHY_OUI_VITESSE 0x01c1
+-#define PHY_OUI_REALTEK 0x0732
++#define PHY_OUI_MARVELL 0x5043
++#define PHY_OUI_CICADA 0x03f1
++#define PHY_OUI_VITESSE 0x01c1
++#define PHY_OUI_REALTEK 0x0732
++#define PHY_OUI_REALTEK2 0x0020
+ #define PHYID1_OUI_MASK 0x03ff
+ #define PHYID1_OUI_SHFT 6
+ #define PHYID2_OUI_MASK 0xfc00
+ #define PHYID2_OUI_SHFT 10
+ #define PHYID2_MODEL_MASK 0x03f0
+-#define PHY_MODEL_MARVELL_E3016 0x220
++#define PHY_MODEL_REALTEK_8211 0x0110
++#define PHY_REV_MASK 0x0001
++#define PHY_REV_REALTEK_8211B 0x0000
++#define PHY_REV_REALTEK_8211C 0x0001
++#define PHY_MODEL_REALTEK_8201 0x0200
++#define PHY_MODEL_MARVELL_E3016 0x0220
+ #define PHY_MARVELL_E3016_INITMASK 0x0300
+ #define PHY_CICADA_INIT1 0x0f000
+ #define PHY_CICADA_INIT2 0x0e00
+@@ -598,10 +525,18 @@ union ring_type {
+ #define PHY_REALTEK_INIT_REG1 0x1f
+ #define PHY_REALTEK_INIT_REG2 0x19
+ #define PHY_REALTEK_INIT_REG3 0x13
++#define PHY_REALTEK_INIT_REG4 0x14
++#define PHY_REALTEK_INIT_REG5 0x18
++#define PHY_REALTEK_INIT_REG6 0x11
+ #define PHY_REALTEK_INIT1 0x0000
+ #define PHY_REALTEK_INIT2 0x8e00
+ #define PHY_REALTEK_INIT3 0x0001
+ #define PHY_REALTEK_INIT4 0xad17
++#define PHY_REALTEK_INIT5 0xfb54
++#define PHY_REALTEK_INIT6 0xf5c7
++#define PHY_REALTEK_INIT7 0x1000
++#define PHY_REALTEK_INIT8 0x0003
++#define PHY_REALTEK_INIT_MSK1 0x0003
+
+ #define PHY_GIGABIT 0x0100
+
+@@ -780,6 +715,7 @@ struct fe_priv {
+ int wolenabled;
+ unsigned int phy_oui;
+ unsigned int phy_model;
++ unsigned int phy_rev;
+ u16 gigabit;
+ int intr_test;
+ int recover_error;
+@@ -793,6 +729,7 @@ struct fe_priv {
+ u32 txrxctl_bits;
+ u32 vlanctl_bits;
+ u32 driver_data;
++ u32 device_id;
+ u32 register_size;
+ int rx_csum;
+ u32 mac_in_use;
+@@ -903,6 +840,16 @@ enum {
+ };
+ static int dma_64bit = NV_DMA_64BIT_ENABLED;
+
++/*
++ * Crossover Detection
++ * Realtek 8201 phy + some OEM boards do not work properly.
++ */
++enum {
++ NV_CROSSOVER_DETECTION_DISABLED,
++ NV_CROSSOVER_DETECTION_ENABLED
++};
++static int phy_cross = NV_CROSSOVER_DETECTION_DISABLED;
++
+ static inline struct fe_priv *get_nvpriv(struct net_device *dev)
+ {
+ return netdev_priv(dev);
+@@ -930,6 +877,13 @@ static inline u32 nv_descr_getlength_ex(struct ring_desc_ex *prd, u32 v)
+ return le32_to_cpu(prd->flaglen) & LEN_MASK_V2;
+ }
+
++static bool nv_optimized(struct fe_priv *np)
++{
++ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
++ return false;
++ return true;
++}
++
+ static int reg_delay(struct net_device *dev, int offset, u32 mask, u32 target,
+ int delay, int delaymax, const char *msg)
+ {
+@@ -966,7 +920,7 @@ static void setup_hw_rings(struct net_device *dev, int rxtx_flags)
+ struct fe_priv *np = get_nvpriv(dev);
+ u8 __iomem *base = get_hwbase(dev);
+
+- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++ if (!nv_optimized(np)) {
+ if (rxtx_flags & NV_SETUP_RX_RING) {
+ writel(dma_low(np->ring_addr), base + NvRegRxRingPhysAddr);
+ }
+@@ -989,7 +943,7 @@ static void free_rings(struct net_device *dev)
+ {
+ struct fe_priv *np = get_nvpriv(dev);
+
+- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++ if (!nv_optimized(np)) {
+ if (np->rx_ring.orig)
+ pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (np->rx_ring_size + np->tx_ring_size),
+ np->rx_ring.orig, np->ring_addr);
+@@ -1160,25 +1114,53 @@ static int phy_init(struct net_device *dev)
+ }
+ }
+ if (np->phy_oui == PHY_OUI_REALTEK) {
+- if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+- printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+- return PHY_ERROR;
+- }
+- if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
+- printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+- return PHY_ERROR;
+- }
+- if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
+- printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+- return PHY_ERROR;
+- }
+- if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
+- printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+- return PHY_ERROR;
++ if (np->phy_model == PHY_MODEL_REALTEK_8211 &&
++ np->phy_rev == PHY_REV_REALTEK_8211B) {
++ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
++ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++ return PHY_ERROR;
++ }
++ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
++ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++ return PHY_ERROR;
++ }
++ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
++ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++ return PHY_ERROR;
++ }
++ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
++ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++ return PHY_ERROR;
++ }
++ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG4, PHY_REALTEK_INIT5)) {
++ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++ return PHY_ERROR;
++ }
++ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG5, PHY_REALTEK_INIT6)) {
++ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++ return PHY_ERROR;
++ }
++ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
++ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++ return PHY_ERROR;
++ }
+ }
+- if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+- printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+- return PHY_ERROR;
++ if (np->phy_model == PHY_MODEL_REALTEK_8201) {
++ if (np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_32 ||
++ np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_33 ||
++ np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_34 ||
++ np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_35 ||
++ np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_36 ||
++ np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_37 ||
++ np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_38 ||
++ np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_39) {
++ phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, MII_READ);
++ phy_reserved |= PHY_REALTEK_INIT7;
++ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, phy_reserved)) {
++ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++ return PHY_ERROR;
++ }
++ }
+ }
+ }
+
+@@ -1318,26 +1300,71 @@ static int phy_init(struct net_device *dev)
+ }
+ }
+ if (np->phy_oui == PHY_OUI_REALTEK) {
+- /* reset could have cleared these out, set them back */
+- if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+- printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+- return PHY_ERROR;
+- }
+- if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
+- printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+- return PHY_ERROR;
+- }
+- if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
+- printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+- return PHY_ERROR;
+- }
+- if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
+- printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+- return PHY_ERROR;
++ if (np->phy_model == PHY_MODEL_REALTEK_8211 &&
++ np->phy_rev == PHY_REV_REALTEK_8211B) {
++ /* reset could have cleared these out, set them back */
++ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
++ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++ return PHY_ERROR;
++ }
++ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
++ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++ return PHY_ERROR;
++ }
++ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
++ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++ return PHY_ERROR;
++ }
++ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
++ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++ return PHY_ERROR;
++ }
++ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG4, PHY_REALTEK_INIT5)) {
++ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++ return PHY_ERROR;
++ }
++ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG5, PHY_REALTEK_INIT6)) {
++ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++ return PHY_ERROR;
++ }
++ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
++ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++ return PHY_ERROR;
++ }
+ }
+- if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+- printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+- return PHY_ERROR;
++ if (np->phy_model == PHY_MODEL_REALTEK_8201) {
++ if (np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_32 ||
++ np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_33 ||
++ np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_34 ||
++ np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_35 ||
++ np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_36 ||
++ np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_37 ||
++ np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_38 ||
++ np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_39) {
++ phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, MII_READ);
++ phy_reserved |= PHY_REALTEK_INIT7;
++ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, phy_reserved)) {
++ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++ return PHY_ERROR;
++ }
++ }
++ if (phy_cross == NV_CROSSOVER_DETECTION_DISABLED) {
++ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
++ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++ return PHY_ERROR;
++ }
++ phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, MII_READ);
++ phy_reserved &= ~PHY_REALTEK_INIT_MSK1;
++ phy_reserved |= PHY_REALTEK_INIT3;
++ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, phy_reserved)) {
++ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++ return PHY_ERROR;
++ }
++ if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
++ printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
++ return PHY_ERROR;
++ }
++ }
+ }
+ }
+
+@@ -1435,6 +1462,18 @@ static void nv_stop_tx(struct net_device *dev)
+ base + NvRegTransmitPoll);
+ }
+
++static void nv_start_rxtx(struct net_device *dev)
++{
++ nv_start_rx(dev);
++ nv_start_tx(dev);
++}
++
++static void nv_stop_rxtx(struct net_device *dev)
++{
++ nv_stop_rx(dev);
++ nv_stop_tx(dev);
++}
++
+ static void nv_txrx_reset(struct net_device *dev)
+ {
+ struct fe_priv *np = netdev_priv(dev);
+@@ -1657,7 +1696,7 @@ static void nv_do_rx_refill(unsigned long data)
+ } else {
+ disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
+ }
+- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
++ if (!nv_optimized(np))
+ retcode = nv_alloc_rx(dev);
+ else
+ retcode = nv_alloc_rx_optimized(dev);
+@@ -1682,8 +1721,10 @@ static void nv_init_rx(struct net_device *dev)
+ {
+ struct fe_priv *np = netdev_priv(dev);
+ int i;
++
+ np->get_rx = np->put_rx = np->first_rx = np->rx_ring;
+- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
++
++ if (!nv_optimized(np))
+ np->last_rx.orig = &np->rx_ring.orig[np->rx_ring_size-1];
+ else
+ np->last_rx.ex = &np->rx_ring.ex[np->rx_ring_size-1];
+@@ -1691,7 +1732,7 @@ static void nv_init_rx(struct net_device *dev)
+ np->last_rx_ctx = &np->rx_skb[np->rx_ring_size-1];
+
+ for (i = 0; i < np->rx_ring_size; i++) {
+- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++ if (!nv_optimized(np)) {
+ np->rx_ring.orig[i].flaglen = 0;
+ np->rx_ring.orig[i].buf = 0;
+ } else {
+@@ -1709,8 +1750,10 @@ static void nv_init_tx(struct net_device *dev)
+ {
+ struct fe_priv *np = netdev_priv(dev);
+ int i;
++
+ np->get_tx = np->put_tx = np->first_tx = np->tx_ring;
+- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
++
++ if (!nv_optimized(np))
+ np->last_tx.orig = &np->tx_ring.orig[np->tx_ring_size-1];
+ else
+ np->last_tx.ex = &np->tx_ring.ex[np->tx_ring_size-1];
+@@ -1721,7 +1764,7 @@ static void nv_init_tx(struct net_device *dev)
+ np->tx_end_flip = NULL;
+
+ for (i = 0; i < np->tx_ring_size; i++) {
+- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++ if (!nv_optimized(np)) {
+ np->tx_ring.orig[i].flaglen = 0;
+ np->tx_ring.orig[i].buf = 0;
+ } else {
+@@ -1744,7 +1787,8 @@ static int nv_init_ring(struct net_device *dev)
+
+ nv_init_tx(dev);
+ nv_init_rx(dev);
+- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
++
++ if (!nv_optimized(np))
+ return nv_alloc_rx(dev);
+ else
+ return nv_alloc_rx_optimized(dev);
+@@ -1775,7 +1819,7 @@ static void nv_drain_tx(struct net_device *dev)
+ unsigned int i;
+
+ for (i = 0; i < np->tx_ring_size; i++) {
+- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++ if (!nv_optimized(np)) {
+ np->tx_ring.orig[i].flaglen = 0;
+ np->tx_ring.orig[i].buf = 0;
+ } else {
+@@ -1802,7 +1846,7 @@ static void nv_drain_rx(struct net_device *dev)
+ int i;
+
+ for (i = 0; i < np->rx_ring_size; i++) {
+- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++ if (!nv_optimized(np)) {
+ np->rx_ring.orig[i].flaglen = 0;
+ np->rx_ring.orig[i].buf = 0;
+ } else {
+@@ -1823,7 +1867,7 @@ static void nv_drain_rx(struct net_device *dev)
+ }
+ }
+
+-static void drain_ring(struct net_device *dev)
++static void nv_drain_rxtx(struct net_device *dev)
+ {
+ nv_drain_tx(dev);
+ nv_drain_rx(dev);
+@@ -1834,6 +1878,115 @@ static inline u32 nv_get_empty_tx_slots(struct fe_priv *np)
+ return (u32)(np->tx_ring_size - ((np->tx_ring_size + (np->put_tx_ctx - np->get_tx_ctx)) % np->tx_ring_size));
+ }
+
++static void nv_legacybackoff_reseed(struct net_device *dev)
++{
++ u8 __iomem *base = get_hwbase(dev);
++ u32 reg;
++ u32 low;
++ int tx_status = 0;
++
++ reg = readl(base + NvRegSlotTime) & ~NVREG_SLOTTIME_MASK;
++ get_random_bytes(&low, sizeof(low));
++ reg |= low & NVREG_SLOTTIME_MASK;
++
++ /* Need to stop tx before change takes effect.
++ * Caller has already gained np->lock.
++ */
++ tx_status = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_START;
++ if (tx_status)
++ nv_stop_tx(dev);
++ nv_stop_rx(dev);
++ writel(reg, base + NvRegSlotTime);
++ if (tx_status)
++ nv_start_tx(dev);
++ nv_start_rx(dev);
++}
++
++/* Gear Backoff Seeds */
++#define BACKOFF_SEEDSET_ROWS 8
++#define BACKOFF_SEEDSET_LFSRS 15
++
++/* Known Good seed sets */
++static const u32 main_seedset[BACKOFF_SEEDSET_ROWS][BACKOFF_SEEDSET_LFSRS] = {
++ {145, 155, 165, 175, 185, 196, 235, 245, 255, 265, 275, 285, 660, 690, 874},
++ {245, 255, 265, 575, 385, 298, 335, 345, 355, 366, 375, 385, 761, 790, 974},
++ {145, 155, 165, 175, 185, 196, 235, 245, 255, 265, 275, 285, 660, 690, 874},
++ {245, 255, 265, 575, 385, 298, 335, 345, 355, 366, 375, 386, 761, 790, 974},
++ {266, 265, 276, 585, 397, 208, 345, 355, 365, 376, 385, 396, 771, 700, 984},
++ {266, 265, 276, 586, 397, 208, 346, 355, 365, 376, 285, 396, 771, 700, 984},
++ {366, 365, 376, 686, 497, 308, 447, 455, 466, 476, 485, 496, 871, 800, 84},
++ {466, 465, 476, 786, 597, 408, 547, 555, 566, 576, 585, 597, 971, 900, 184}};
++
++static const u32 gear_seedset[BACKOFF_SEEDSET_ROWS][BACKOFF_SEEDSET_LFSRS] = {
++ {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375, 30, 295},
++ {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395},
++ {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 397},
++ {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375, 30, 295},
++ {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375, 30, 295},
++ {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395},
++ {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395},
++ {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395}};
++
++static void nv_gear_backoff_reseed(struct net_device *dev)
++{
++ u8 __iomem *base = get_hwbase(dev);
++ u32 miniseed1, miniseed2, miniseed2_reversed, miniseed3, miniseed3_reversed;
++ u32 temp, seedset, combinedSeed;
++ int i;
++
++ /* Setup seed for free running LFSR */
++ /* We are going to read the time stamp counter 3 times
++ and swizzle bits around to increase randomness */
++ get_random_bytes(&miniseed1, sizeof(miniseed1));
++ miniseed1 &= 0x0fff;
++ if (miniseed1 == 0)
++ miniseed1 = 0xabc;
++
++ get_random_bytes(&miniseed2, sizeof(miniseed2));
++ miniseed2 &= 0x0fff;
++ if (miniseed2 == 0)
++ miniseed2 = 0xabc;
++ miniseed2_reversed =
++ ((miniseed2 & 0xF00) >> 8) |
++ (miniseed2 & 0x0F0) |
++ ((miniseed2 & 0x00F) << 8);
++
++ get_random_bytes(&miniseed3, sizeof(miniseed3));
++ miniseed3 &= 0x0fff;
++ if (miniseed3 == 0)
++ miniseed3 = 0xabc;
++ miniseed3_reversed =
++ ((miniseed3 & 0xF00) >> 8) |
++ (miniseed3 & 0x0F0) |
++ ((miniseed3 & 0x00F) << 8);
++
++ combinedSeed = ((miniseed1 ^ miniseed2_reversed) << 12) |
++ (miniseed2 ^ miniseed3_reversed);
++
++ /* Seeds can not be zero */
++ if ((combinedSeed & NVREG_BKOFFCTRL_SEED_MASK) == 0)
++ combinedSeed |= 0x08;
++ if ((combinedSeed & (NVREG_BKOFFCTRL_SEED_MASK << NVREG_BKOFFCTRL_GEAR)) == 0)
++ combinedSeed |= 0x8000;
++
++ /* No need to disable tx here */
++ temp = NVREG_BKOFFCTRL_DEFAULT | (0 << NVREG_BKOFFCTRL_SELECT);
++ temp |= combinedSeed & NVREG_BKOFFCTRL_SEED_MASK;
++ temp |= combinedSeed >> NVREG_BKOFFCTRL_GEAR;
++ writel(temp,base + NvRegBackOffControl);
++
++ /* Setup seeds for all gear LFSRs. */
++ get_random_bytes(&seedset, sizeof(seedset));
++ seedset = seedset % BACKOFF_SEEDSET_ROWS;
++ for (i = 1; i <= BACKOFF_SEEDSET_LFSRS; i++)
++ {
++ temp = NVREG_BKOFFCTRL_DEFAULT | (i << NVREG_BKOFFCTRL_SELECT);
++ temp |= main_seedset[seedset][i-1] & 0x3ff;
++ temp |= ((gear_seedset[seedset][i-1] & 0x3ff) << NVREG_BKOFFCTRL_GEAR);
++ writel(temp, base + NvRegBackOffControl);
++ }
++}
++
+ /*
+ * nv_start_xmit: dev->hard_start_xmit function
+ * Called with netif_tx_lock held.
+@@ -2153,6 +2306,8 @@ static void nv_tx_done(struct net_device *dev)
+ dev->stats.tx_fifo_errors++;
+ if (flags & NV_TX_CARRIERLOST)
+ dev->stats.tx_carrier_errors++;
++ if ((flags & NV_TX_RETRYERROR) && !(flags & NV_TX_RETRYCOUNT_MASK))
++ nv_legacybackoff_reseed(dev);
+ dev->stats.tx_errors++;
+ } else {
+ dev->stats.tx_packets++;
+@@ -2168,6 +2323,8 @@ static void nv_tx_done(struct net_device *dev)
+ dev->stats.tx_fifo_errors++;
+ if (flags & NV_TX2_CARRIERLOST)
+ dev->stats.tx_carrier_errors++;
++ if ((flags & NV_TX2_RETRYERROR) && !(flags & NV_TX2_RETRYCOUNT_MASK))
++ nv_legacybackoff_reseed(dev);
+ dev->stats.tx_errors++;
+ } else {
+ dev->stats.tx_packets++;
+@@ -2209,6 +2366,15 @@ static void nv_tx_done_optimized(struct net_device *dev, int limit)
+ if (flags & NV_TX2_LASTPACKET) {
+ if (!(flags & NV_TX2_ERROR))
+ dev->stats.tx_packets++;
++ else {
++ if ((flags & NV_TX2_RETRYERROR) && !(flags & NV_TX2_RETRYCOUNT_MASK)) {
++ if (np->driver_data & DEV_HAS_GEAR_MODE)
++ nv_gear_backoff_reseed(dev);
++ else
++ nv_legacybackoff_reseed(dev);
++ }
++ }
++
+ dev_kfree_skb_any(np->get_tx_ctx->skb);
+ np->get_tx_ctx->skb = NULL;
+
+@@ -2260,7 +2426,7 @@ static void nv_tx_timeout(struct net_device *dev)
+ }
+ printk(KERN_INFO "%s: Dumping tx ring\n", dev->name);
+ for (i=0;i<np->tx_ring_size;i+= 4) {
+- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++ if (!nv_optimized(np)) {
+ printk(KERN_INFO "%03x: %08x %08x // %08x %08x // %08x %08x // %08x %08x\n",
+ i,
+ le32_to_cpu(np->tx_ring.orig[i].buf),
+@@ -2296,7 +2462,7 @@ static void nv_tx_timeout(struct net_device *dev)
+ nv_stop_tx(dev);
+
+ /* 2) check that the packets were not sent already: */
+- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
++ if (!nv_optimized(np))
+ nv_tx_done(dev);
+ else
+ nv_tx_done_optimized(dev, np->tx_ring_size);
+@@ -2663,12 +2829,10 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
+ netif_tx_lock_bh(dev);
+ spin_lock(&np->lock);
+ /* stop engines */
+- nv_stop_rx(dev);
+- nv_stop_tx(dev);
++ nv_stop_rxtx(dev);
+ nv_txrx_reset(dev);
+ /* drain rx queue */
+- nv_drain_rx(dev);
+- nv_drain_tx(dev);
++ nv_drain_rxtx(dev);
+ /* reinit driver view of the rx queue */
+ set_bufsize(dev);
+ if (nv_init_ring(dev)) {
+@@ -2685,8 +2849,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
+ pci_push(base);
+
+ /* restart rx engine */
+- nv_start_rx(dev);
+- nv_start_tx(dev);
++ nv_start_rxtx(dev);
+ spin_unlock(&np->lock);
+ netif_tx_unlock_bh(dev);
+ nv_enable_irq(dev);
+@@ -2973,15 +3136,14 @@ set_speed:
+ }
+
+ if (np->gigabit == PHY_GIGABIT) {
+- phyreg = readl(base + NvRegRandomSeed);
++ phyreg = readl(base + NvRegSlotTime);
+ phyreg &= ~(0x3FF00);
+- if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_10)
+- phyreg |= NVREG_RNDSEED_FORCE3;
+- else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100)
+- phyreg |= NVREG_RNDSEED_FORCE2;
++ if (((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_10) ||
++ ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100))
++ phyreg |= NVREG_SLOTTIME_10_100_FULL;
+ else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000)
+- phyreg |= NVREG_RNDSEED_FORCE;
+- writel(phyreg, base + NvRegRandomSeed);
++ phyreg |= NVREG_SLOTTIME_1000_FULL;
++ writel(phyreg, base + NvRegSlotTime);
+ }
+
+ phyreg = readl(base + NvRegPhyInterface);
+@@ -3393,7 +3555,7 @@ static int nv_napi_poll(struct napi_struct *napi, int budget)
+ unsigned long flags;
+ int pkts, retcode;
+
+- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++ if (!nv_optimized(np)) {
+ pkts = nv_rx_process(dev, budget);
+ retcode = nv_alloc_rx(dev);
+ } else {
+@@ -3634,7 +3796,7 @@ static int nv_request_irq(struct net_device *dev, int intr_test)
+ if (intr_test) {
+ handler = nv_nic_irq_test;
+ } else {
+- if (np->desc_ver == DESC_VER_3)
++ if (nv_optimized(np))
+ handler = nv_nic_irq_optimized;
+ else
+ handler = nv_nic_irq;
+@@ -3787,12 +3949,10 @@ static void nv_do_nic_poll(unsigned long data)
+ netif_tx_lock_bh(dev);
+ spin_lock(&np->lock);
+ /* stop engines */
+- nv_stop_rx(dev);
+- nv_stop_tx(dev);
++ nv_stop_rxtx(dev);
+ nv_txrx_reset(dev);
+ /* drain rx queue */
+- nv_drain_rx(dev);
+- nv_drain_tx(dev);
++ nv_drain_rxtx(dev);
+ /* reinit driver view of the rx queue */
+ set_bufsize(dev);
+ if (nv_init_ring(dev)) {
+@@ -3809,8 +3969,7 @@ static void nv_do_nic_poll(unsigned long data)
+ pci_push(base);
+
+ /* restart rx engine */
+- nv_start_rx(dev);
+- nv_start_tx(dev);
++ nv_start_rxtx(dev);
+ spin_unlock(&np->lock);
+ netif_tx_unlock_bh(dev);
+ }
+@@ -3821,7 +3980,7 @@ static void nv_do_nic_poll(unsigned long data)
+ pci_push(base);
+
+ if (!using_multi_irqs(dev)) {
+- if (np->desc_ver == DESC_VER_3)
++ if (nv_optimized(np))
+ nv_nic_irq_optimized(0, dev);
+ else
+ nv_nic_irq(0, dev);
+@@ -3860,7 +4019,8 @@ static void nv_do_stats_poll(unsigned long data)
+ nv_get_hw_stats(dev);
+
+ if (!np->in_shutdown)
+- mod_timer(&np->stats_poll, jiffies + STATS_INTERVAL);
++ mod_timer(&np->stats_poll,
++ round_jiffies(jiffies + STATS_INTERVAL));
+ }
+
+ static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+@@ -4018,8 +4178,7 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+ netif_tx_lock_bh(dev);
+ spin_lock(&np->lock);
+ /* stop engines */
+- nv_stop_rx(dev);
+- nv_stop_tx(dev);
++ nv_stop_rxtx(dev);
+ spin_unlock(&np->lock);
+ netif_tx_unlock_bh(dev);
+ }
+@@ -4125,8 +4284,7 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+ }
+
+ if (netif_running(dev)) {
+- nv_start_rx(dev);
+- nv_start_tx(dev);
++ nv_start_rxtx(dev);
+ nv_enable_irq(dev);
+ }
+
+@@ -4169,8 +4327,7 @@ static int nv_nway_reset(struct net_device *dev)
+ netif_tx_lock_bh(dev);
+ spin_lock(&np->lock);
+ /* stop engines */
+- nv_stop_rx(dev);
+- nv_stop_tx(dev);
++ nv_stop_rxtx(dev);
+ spin_unlock(&np->lock);
+ netif_tx_unlock_bh(dev);
+ printk(KERN_INFO "%s: link down.\n", dev->name);
+@@ -4190,8 +4347,7 @@ static int nv_nway_reset(struct net_device *dev)
+ }
+
+ if (netif_running(dev)) {
+- nv_start_rx(dev);
+- nv_start_tx(dev);
++ nv_start_rxtx(dev);
+ nv_enable_irq(dev);
+ }
+ ret = 0;
+@@ -4248,7 +4404,7 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri
+ }
+
+ /* allocate new rings */
+- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++ if (!nv_optimized(np)) {
+ rxtx_ring = pci_alloc_consistent(np->pci_dev,
+ sizeof(struct ring_desc) * (ring->rx_pending + ring->tx_pending),
+ &ring_addr);
+@@ -4261,7 +4417,7 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri
+ tx_skbuff = kmalloc(sizeof(struct nv_skb_map) * ring->tx_pending, GFP_KERNEL);
+ if (!rxtx_ring || !rx_skbuff || !tx_skbuff) {
+ /* fall back to old rings */
+- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++ if (!nv_optimized(np)) {
+ if (rxtx_ring)
+ pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (ring->rx_pending + ring->tx_pending),
+ rxtx_ring, ring_addr);
+@@ -4282,12 +4438,10 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri
+ netif_tx_lock_bh(dev);
+ spin_lock(&np->lock);
+ /* stop engines */
+- nv_stop_rx(dev);
+- nv_stop_tx(dev);
++ nv_stop_rxtx(dev);
+ nv_txrx_reset(dev);
+ /* drain queues */
+- nv_drain_rx(dev);
+- nv_drain_tx(dev);
++ nv_drain_rxtx(dev);
+ /* delete queues */
+ free_rings(dev);
+ }
+@@ -4295,7 +4449,8 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri
+ /* set new values */
+ np->rx_ring_size = ring->rx_pending;
+ np->tx_ring_size = ring->tx_pending;
+- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++
++ if (!nv_optimized(np)) {
+ np->rx_ring.orig = (struct ring_desc*)rxtx_ring;
+ np->tx_ring.orig = &np->rx_ring.orig[np->rx_ring_size];
+ } else {
+@@ -4327,8 +4482,7 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri
+ pci_push(base);
+
+ /* restart engines */
+- nv_start_rx(dev);
+- nv_start_tx(dev);
++ nv_start_rxtx(dev);
+ spin_unlock(&np->lock);
+ netif_tx_unlock_bh(dev);
+ nv_enable_irq(dev);
+@@ -4369,8 +4523,7 @@ static int nv_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam*
+ netif_tx_lock_bh(dev);
+ spin_lock(&np->lock);
+ /* stop engines */
+- nv_stop_rx(dev);
+- nv_stop_tx(dev);
++ nv_stop_rxtx(dev);
+ spin_unlock(&np->lock);
+ netif_tx_unlock_bh(dev);
+ }
+@@ -4411,8 +4564,7 @@ static int nv_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam*
+ }
+
+ if (netif_running(dev)) {
+- nv_start_rx(dev);
+- nv_start_tx(dev);
++ nv_start_rxtx(dev);
+ nv_enable_irq(dev);
+ }
+ return 0;
+@@ -4648,8 +4800,7 @@ static int nv_loopback_test(struct net_device *dev)
+ pci_push(base);
+
+ /* restart rx engine */
+- nv_start_rx(dev);
+- nv_start_tx(dev);
++ nv_start_rxtx(dev);
+
+ /* setup packet for tx */
+ pkt_len = ETH_DATA_LEN;
+@@ -4667,7 +4818,7 @@ static int nv_loopback_test(struct net_device *dev)
+ for (i = 0; i < pkt_len; i++)
+ pkt_data[i] = (u8)(i & 0xff);
+
+- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++ if (!nv_optimized(np)) {
+ np->tx_ring.orig[0].buf = cpu_to_le32(test_dma_addr);
+ np->tx_ring.orig[0].flaglen = cpu_to_le32((pkt_len-1) | np->tx_flags | tx_flags_extra);
+ } else {
+@@ -4681,7 +4832,7 @@ static int nv_loopback_test(struct net_device *dev)
+ msleep(500);
+
+ /* check for rx of the packet */
+- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++ if (!nv_optimized(np)) {
+ flags = le32_to_cpu(np->rx_ring.orig[0].flaglen);
+ len = nv_descr_getlength(&np->rx_ring.orig[0], np->desc_ver);
+
+@@ -4727,12 +4878,10 @@ static int nv_loopback_test(struct net_device *dev)
+ dev_kfree_skb_any(tx_skb);
+ out:
+ /* stop engines */
+- nv_stop_rx(dev);
+- nv_stop_tx(dev);
++ nv_stop_rxtx(dev);
+ nv_txrx_reset(dev);
+ /* drain rx queue */
+- nv_drain_rx(dev);
+- nv_drain_tx(dev);
++ nv_drain_rxtx(dev);
+
+ if (netif_running(dev)) {
+ writel(misc1_flags, base + NvRegMisc1);
+@@ -4770,12 +4919,10 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64
+ writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus);
+ }
+ /* stop engines */
+- nv_stop_rx(dev);
+- nv_stop_tx(dev);
++ nv_stop_rxtx(dev);
+ nv_txrx_reset(dev);
+ /* drain rx queue */
+- nv_drain_rx(dev);
+- nv_drain_tx(dev);
++ nv_drain_rxtx(dev);
+ spin_unlock_irq(&np->lock);
+ netif_tx_unlock_bh(dev);
+ }
+@@ -4816,8 +4963,7 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64
+ writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
+ pci_push(base);
+ /* restart rx engine */
+- nv_start_rx(dev);
+- nv_start_tx(dev);
++ nv_start_rxtx(dev);
+ netif_start_queue(dev);
+ #ifdef CONFIG_FORCEDETH_NAPI
+ napi_enable(&np->napi);
+@@ -4927,6 +5073,7 @@ static int nv_open(struct net_device *dev)
+ u8 __iomem *base = get_hwbase(dev);
+ int ret = 1;
+ int oom, i;
++ u32 low;
+
+ dprintk(KERN_DEBUG "nv_open: begin\n");
+
+@@ -4986,8 +5133,20 @@ static int nv_open(struct net_device *dev)
+ writel(np->rx_buf_sz, base + NvRegOffloadConfig);
+
+ writel(readl(base + NvRegReceiverStatus), base + NvRegReceiverStatus);
+- get_random_bytes(&i, sizeof(i));
+- writel(NVREG_RNDSEED_FORCE | (i&NVREG_RNDSEED_MASK), base + NvRegRandomSeed);
++
++ get_random_bytes(&low, sizeof(low));
++ low &= NVREG_SLOTTIME_MASK;
++ if (np->desc_ver == DESC_VER_1) {
++ writel(low|NVREG_SLOTTIME_DEFAULT, base + NvRegSlotTime);
++ } else {
++ if (!(np->driver_data & DEV_HAS_GEAR_MODE)) {
++ /* setup legacy backoff */
++ writel(NVREG_SLOTTIME_LEGBF_ENABLED|NVREG_SLOTTIME_10_100_FULL|low, base + NvRegSlotTime);
++ } else {
++ writel(NVREG_SLOTTIME_10_100_FULL, base + NvRegSlotTime);
++ nv_gear_backoff_reseed(dev);
++ }
++ }
+ writel(NVREG_TX_DEFERRAL_DEFAULT, base + NvRegTxDeferral);
+ writel(NVREG_RX_DEFERRAL_DEFAULT, base + NvRegRxDeferral);
+ if (poll_interval == -1) {
+@@ -5046,8 +5205,7 @@ static int nv_open(struct net_device *dev)
+ * to init hw */
+ np->linkspeed = 0;
+ ret = nv_update_linkspeed(dev);
+- nv_start_rx(dev);
+- nv_start_tx(dev);
++ nv_start_rxtx(dev);
+ netif_start_queue(dev);
+ #ifdef CONFIG_FORCEDETH_NAPI
+ napi_enable(&np->napi);
+@@ -5064,13 +5222,14 @@ static int nv_open(struct net_device *dev)
+
+ /* start statistics timer */
+ if (np->driver_data & (DEV_HAS_STATISTICS_V1|DEV_HAS_STATISTICS_V2))
+- mod_timer(&np->stats_poll, jiffies + STATS_INTERVAL);
++ mod_timer(&np->stats_poll,
++ round_jiffies(jiffies + STATS_INTERVAL));
+
+ spin_unlock_irq(&np->lock);
+
+ return 0;
+ out_drain:
+- drain_ring(dev);
++ nv_drain_rxtx(dev);
+ return ret;
+ }
+
+@@ -5093,8 +5252,7 @@ static int nv_close(struct net_device *dev)
+
+ netif_stop_queue(dev);
+ spin_lock_irq(&np->lock);
+- nv_stop_tx(dev);
+- nv_stop_rx(dev);
++ nv_stop_rxtx(dev);
+ nv_txrx_reset(dev);
+
+ /* disable interrupts on the nic or we will lock up */
+@@ -5107,7 +5265,7 @@ static int nv_close(struct net_device *dev)
+
+ nv_free_irq(dev);
+
+- drain_ring(dev);
++ nv_drain_rxtx(dev);
+
+ if (np->wolenabled) {
+ writel(NVREG_PFF_ALWAYS|NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags);
+@@ -5195,6 +5353,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
+
+ /* copy of driver data */
+ np->driver_data = id->driver_data;
++ /* copy of device id */
++ np->device_id = id->device;
+
+ /* handle different descriptor versions */
+ if (id->driver_data & DEV_HAS_HIGH_DMA) {
+@@ -5267,7 +5427,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
+ np->rx_ring_size = RX_RING_DEFAULT;
+ np->tx_ring_size = TX_RING_DEFAULT;
+
+- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
++ if (!nv_optimized(np)) {
+ np->rx_ring.orig = pci_alloc_consistent(pci_dev,
+ sizeof(struct ring_desc) * (np->rx_ring_size + np->tx_ring_size),
+ &np->ring_addr);
+@@ -5289,7 +5449,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
+
+ dev->open = nv_open;
+ dev->stop = nv_close;
+- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
++
++ if (!nv_optimized(np))
+ dev->hard_start_xmit = nv_start_xmit;
+ else
+ dev->hard_start_xmit = nv_start_xmit_optimized;
+@@ -5483,6 +5644,14 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
+ pci_name(pci_dev), id1, id2, phyaddr);
+ np->phyaddr = phyaddr;
+ np->phy_oui = id1 | id2;
++
++ /* Realtek hardcoded phy id1 to all zero's on certain phys */
++ if (np->phy_oui == PHY_OUI_REALTEK2)
++ np->phy_oui = PHY_OUI_REALTEK;
++ /* Setup phy revision for Realtek */
++ if (np->phy_oui == PHY_OUI_REALTEK && np->phy_model == PHY_MODEL_REALTEK_8211)
++ np->phy_rev = mii_rw(dev, phyaddr, MII_RESV1, MII_READ) & PHY_REV_MASK;
++
+ break;
+ }
+ if (i == 33) {
+@@ -5561,6 +5730,28 @@ out:
+ return err;
+ }
+
++static void nv_restore_phy(struct net_device *dev)
++{
++ struct fe_priv *np = netdev_priv(dev);
++ u16 phy_reserved, mii_control;
++
++ if (np->phy_oui == PHY_OUI_REALTEK &&
++ np->phy_model == PHY_MODEL_REALTEK_8201 &&
++ phy_cross == NV_CROSSOVER_DETECTION_DISABLED) {
++ mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3);
++ phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, MII_READ);
++ phy_reserved &= ~PHY_REALTEK_INIT_MSK1;
++ phy_reserved |= PHY_REALTEK_INIT8;
++ mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, phy_reserved);
++ mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1);
++
++ /* restart auto negotiation */
++ mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
++ mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE);
++ mii_rw(dev, np->phyaddr, MII_BMCR, mii_control);
++ }
++}
++
+ static void __devexit nv_remove(struct pci_dev *pci_dev)
+ {
+ struct net_device *dev = pci_get_drvdata(pci_dev);
+@@ -5577,6 +5768,9 @@ static void __devexit nv_remove(struct pci_dev *pci_dev)
+ writel(readl(base + NvRegTransmitPoll) & ~NVREG_TRANSMITPOLL_MAC_ADDR_REV,
+ base + NvRegTransmitPoll);
+
++ /* restore any phy related changes */
++ nv_restore_phy(dev);
++
+ /* free all structures */
+ free_rings(dev);
+ iounmap(get_hwbase(dev));
+@@ -5716,83 +5910,83 @@ static struct pci_device_id pci_tbl[] = {
+ },
+ { /* MCP65 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_20),
+- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_NEED_TX_LIMIT,
++ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ },
+ { /* MCP65 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_21),
+- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT,
++ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ },
+ { /* MCP65 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_22),
+- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT,
++ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ },
+ { /* MCP65 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23),
+- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT,
++ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ },
+ { /* MCP67 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_24),
+- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
++ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE,
+ },
+ { /* MCP67 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_25),
+- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
++ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE,
+ },
+ { /* MCP67 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_26),
+- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
++ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE,
+ },
+ { /* MCP67 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_27),
+- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
++ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE,
+ },
+ { /* MCP73 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_28),
+- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
++ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE,
+ },
+ { /* MCP73 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_29),
+- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
++ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE,
+ },
+ { /* MCP73 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_30),
+- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
++ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE,
+ },
+ { /* MCP73 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_31),
+- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
++ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE,
+ },
+ { /* MCP77 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_32),
+- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
++ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ },
+ { /* MCP77 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_33),
+- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
++ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ },
+ { /* MCP77 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_34),
+- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
++ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ },
+ { /* MCP77 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_35),
+- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
++ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ },
+ { /* MCP79 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_36),
+- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
++ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ },
+ { /* MCP79 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_37),
+- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
++ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ },
+ { /* MCP79 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_38),
+- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
++ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ },
+ { /* MCP79 Ethernet Controller */
+ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_39),
+- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
++ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ },
+ {0,},
+ };
+@@ -5828,6 +6022,8 @@ module_param(msix, int, 0);
+ MODULE_PARM_DESC(msix, "MSIX interrupts are enabled by setting to 1 and disabled by setting to 0.");
+ module_param(dma_64bit, int, 0);
+ MODULE_PARM_DESC(dma_64bit, "High DMA is enabled by setting to 1 and disabled by setting to 0.");
++module_param(phy_cross, int, 0);
++MODULE_PARM_DESC(phy_cross, "Phy crossover detection for Realtek 8201 phy is enabled by setting to 1 and disabled by setting to 0.");
+
+ MODULE_AUTHOR("Manfred Spraul <manfred at colorfullife.com>");
+ MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver");
+diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
+index 940e204..67b4b07 100644
+--- a/drivers/net/fs_enet/fs_enet-main.c
++++ b/drivers/net/fs_enet/fs_enet-main.c
+@@ -1178,7 +1178,7 @@ static int __devinit find_phy(struct device_node *np,
+
+ data = of_get_property(np, "fixed-link", NULL);
+ if (data) {
+- snprintf(fpi->bus_id, 16, PHY_ID_FMT, 0, *data);
++ snprintf(fpi->bus_id, 16, "%x:%02x", 0, *data);
+ return 0;
+ }
+
+@@ -1202,7 +1202,7 @@ static int __devinit find_phy(struct device_node *np,
+ if (!data || len != 4)
+ goto out_put_mdio;
+
+- snprintf(fpi->bus_id, 16, PHY_ID_FMT, res.start, *data);
++ snprintf(fpi->bus_id, 16, "%x:%02x", res.start, *data);
+
+ out_put_mdio:
+ of_node_put(mdionode);
+diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
+index b8e4a73..1620030 100644
+--- a/drivers/net/fs_enet/mii-bitbang.c
++++ b/drivers/net/fs_enet/mii-bitbang.c
+@@ -130,7 +130,7 @@ static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
+ * we get is an int, and the odds of multiple bitbang mdio buses
+ * is low enough that it's not worth going too crazy.
+ */
+- bus->id = res.start;
++ snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start);
+
+ data = of_get_property(np, "fsl,mdio-pin", &len);
+ if (!data || len != 4)
+@@ -307,7 +307,7 @@ static int __devinit fs_enet_mdio_probe(struct device *dev)
+ return -ENOMEM;
+
+ new_bus->name = "BB MII Bus",
+- new_bus->id = pdev->id;
++ snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
+
+ new_bus->phy_mask = ~0x9;
+ pdata = (struct fs_mii_bb_platform_info *)pdev->dev.platform_data;
+diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
+index a89cf15..ba75efc 100644
+--- a/drivers/net/fs_enet/mii-fec.c
++++ b/drivers/net/fs_enet/mii-fec.c
+@@ -196,7 +196,7 @@ static int __devinit fs_enet_mdio_probe(struct of_device *ofdev,
+ if (ret)
+ return ret;
+
+- new_bus->id = res.start;
++ snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", res.start);
+
+ fec->fecp = ioremap(res.start, res.end - res.start + 1);
+ if (!fec->fecp)
+@@ -309,7 +309,7 @@ static int __devinit fs_enet_fec_mdio_probe(struct device *dev)
+ new_bus->read = &fs_enet_fec_mii_read,
+ new_bus->write = &fs_enet_fec_mii_write,
+ new_bus->reset = &fs_enet_fec_mii_reset,
+- new_bus->id = pdev->id;
++ snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
+
+ pdata = (struct fs_mii_fec_platform_info *)pdev->dev.platform_data;
+
+diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
+index 718cf77..99a4b99 100644
+--- a/drivers/net/gianfar.c
++++ b/drivers/net/gianfar.c
+@@ -98,7 +98,6 @@
+ #include "gianfar_mii.h"
+
+ #define TX_TIMEOUT (1*HZ)
+-#define SKB_ALLOC_TIMEOUT 1000000
+ #undef BRIEF_GFAR_ERRORS
+ #undef VERBOSE_GFAR_ERRORS
+
+@@ -115,7 +114,9 @@ static int gfar_enet_open(struct net_device *dev);
+ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev);
+ static void gfar_timeout(struct net_device *dev);
+ static int gfar_close(struct net_device *dev);
+-struct sk_buff *gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp);
++struct sk_buff *gfar_new_skb(struct net_device *dev);
++static void gfar_new_rxbdp(struct net_device *dev, struct rxbd8 *bdp,
++ struct sk_buff *skb);
+ static int gfar_set_mac_address(struct net_device *dev);
+ static int gfar_change_mtu(struct net_device *dev, int new_mtu);
+ static irqreturn_t gfar_error(int irq, void *dev_id);
+@@ -783,14 +784,21 @@ int startup_gfar(struct net_device *dev)
+
+ rxbdp = priv->rx_bd_base;
+ for (i = 0; i < priv->rx_ring_size; i++) {
+- struct sk_buff *skb = NULL;
++ struct sk_buff *skb;
+
+- rxbdp->status = 0;
++ skb = gfar_new_skb(dev);
+
+- skb = gfar_new_skb(dev, rxbdp);
++ if (!skb) {
++ printk(KERN_ERR "%s: Can't allocate RX buffers\n",
++ dev->name);
++
++ goto err_rxalloc_fail;
++ }
+
+ priv->rx_skbuff[i] = skb;
+
++ gfar_new_rxbdp(dev, rxbdp, skb);
++
+ rxbdp++;
+ }
+
+@@ -916,6 +924,7 @@ rx_irq_fail:
+ tx_irq_fail:
+ free_irq(priv->interruptError, dev);
+ err_irq_fail:
++err_rxalloc_fail:
+ rx_skb_fail:
+ free_skb_resources(priv);
+ tx_skb_fail:
+@@ -1185,7 +1194,7 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu)
+ int frame_size = new_mtu + ETH_HLEN;
+
+ if (priv->vlan_enable)
+- frame_size += VLAN_ETH_HLEN;
++ frame_size += VLAN_HLEN;
+
+ if (gfar_uses_fcb(priv))
+ frame_size += GMAC_FCB_LEN;
+@@ -1250,17 +1259,12 @@ static void gfar_timeout(struct net_device *dev)
+ }
+
+ /* Interrupt Handler for Transmit complete */
+-static irqreturn_t gfar_transmit(int irq, void *dev_id)
++int gfar_clean_tx_ring(struct net_device *dev)
+ {
+- struct net_device *dev = (struct net_device *) dev_id;
+- struct gfar_private *priv = netdev_priv(dev);
+ struct txbd8 *bdp;
++ struct gfar_private *priv = netdev_priv(dev);
++ int howmany = 0;
+
+- /* Clear IEVENT */
+- gfar_write(&priv->regs->ievent, IEVENT_TX_MASK);
+-
+- /* Lock priv */
+- spin_lock(&priv->txlock);
+ bdp = priv->dirty_tx;
+ while ((bdp->status & TXBD_READY) == 0) {
+ /* If dirty_tx and cur_tx are the same, then either the */
+@@ -1269,7 +1273,7 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id)
+ if ((bdp == priv->cur_tx) && (netif_queue_stopped(dev) == 0))
+ break;
+
+- dev->stats.tx_packets++;
++ howmany++;
+
+ /* Deferred means some collisions occurred during transmit, */
+ /* but we eventually sent the packet. */
+@@ -1278,11 +1282,15 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id)
+
+ /* Free the sk buffer associated with this TxBD */
+ dev_kfree_skb_irq(priv->tx_skbuff[priv->skb_dirtytx]);
++
+ priv->tx_skbuff[priv->skb_dirtytx] = NULL;
+ priv->skb_dirtytx =
+ (priv->skb_dirtytx +
+ 1) & TX_RING_MOD_MASK(priv->tx_ring_size);
+
++ /* Clean BD length for empty detection */
++ bdp->length = 0;
++
+ /* update bdp to point at next bd in the ring (wrapping if necessary) */
+ if (bdp->status & TXBD_WRAP)
+ bdp = priv->tx_bd_base;
+@@ -1297,31 +1305,69 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id)
+ netif_wake_queue(dev);
+ } /* while ((bdp->status & TXBD_READY) == 0) */
+
++ dev->stats.tx_packets += howmany;
++
++ return howmany;
++}
++
++/* Interrupt Handler for Transmit complete */
++static irqreturn_t gfar_transmit(int irq, void *dev_id)
++{
++ struct net_device *dev = (struct net_device *) dev_id;
++ struct gfar_private *priv = netdev_priv(dev);
++
++ /* Clear IEVENT */
++ gfar_write(&priv->regs->ievent, IEVENT_TX_MASK);
++
++ /* Lock priv */
++ spin_lock(&priv->txlock);
++
++ gfar_clean_tx_ring(dev);
++
+ /* If we are coalescing the interrupts, reset the timer */
+ /* Otherwise, clear it */
+- if (priv->txcoalescing)
++ if (likely(priv->txcoalescing)) {
++ gfar_write(&priv->regs->txic, 0);
+ gfar_write(&priv->regs->txic,
+ mk_ic_value(priv->txcount, priv->txtime));
+- else
+- gfar_write(&priv->regs->txic, 0);
++ }
+
+ spin_unlock(&priv->txlock);
+
+ return IRQ_HANDLED;
+ }
+
+-struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
++static void gfar_new_rxbdp(struct net_device *dev, struct rxbd8 *bdp,
++ struct sk_buff *skb)
++{
++ struct gfar_private *priv = netdev_priv(dev);
++ u32 * status_len = (u32 *)bdp;
++ u16 flags;
++
++ bdp->bufPtr = dma_map_single(&dev->dev, skb->data,
++ priv->rx_buffer_size, DMA_FROM_DEVICE);
++
++ flags = RXBD_EMPTY | RXBD_INTERRUPT;
++
++ if (bdp == priv->rx_bd_base + priv->rx_ring_size - 1)
++ flags |= RXBD_WRAP;
++
++ eieio();
++
++ *status_len = (u32)flags << 16;
++}
++
++
++struct sk_buff * gfar_new_skb(struct net_device *dev)
+ {
+ unsigned int alignamount;
+ struct gfar_private *priv = netdev_priv(dev);
+ struct sk_buff *skb = NULL;
+- unsigned int timeout = SKB_ALLOC_TIMEOUT;
+
+ /* We have to allocate the skb, so keep trying till we succeed */
+- while ((!skb) && timeout--)
+- skb = dev_alloc_skb(priv->rx_buffer_size + RXBUF_ALIGNMENT);
++ skb = netdev_alloc_skb(dev, priv->rx_buffer_size + RXBUF_ALIGNMENT);
+
+- if (NULL == skb)
++ if (!skb)
+ return NULL;
+
+ alignamount = RXBUF_ALIGNMENT -
+@@ -1332,15 +1378,6 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
+ */
+ skb_reserve(skb, alignamount);
+
+- bdp->bufPtr = dma_map_single(&dev->dev, skb->data,
+- priv->rx_buffer_size, DMA_FROM_DEVICE);
+-
+- bdp->length = 0;
+-
+- /* Mark the buffer empty */
+- eieio();
+- bdp->status |= (RXBD_EMPTY | RXBD_INTERRUPT);
+-
+ return skb;
+ }
+
+@@ -1392,15 +1429,15 @@ irqreturn_t gfar_receive(int irq, void *dev_id)
+ unsigned long flags;
+ #endif
+
+- /* Clear IEVENT, so rx interrupt isn't called again
+- * because of this interrupt */
+- gfar_write(&priv->regs->ievent, IEVENT_RX_MASK);
+-
+ /* support NAPI */
+ #ifdef CONFIG_GFAR_NAPI
++ /* Clear IEVENT, so interrupts aren't called again
++ * because of the packets that have already arrived */
++ gfar_write(&priv->regs->ievent, IEVENT_RTX_MASK);
++
+ if (netif_rx_schedule_prep(dev, &priv->napi)) {
+ tempval = gfar_read(&priv->regs->imask);
+- tempval &= IMASK_RX_DISABLED;
++ tempval &= IMASK_RTX_DISABLED;
+ gfar_write(&priv->regs->imask, tempval);
+
+ __netif_rx_schedule(dev, &priv->napi);
+@@ -1411,17 +1448,20 @@ irqreturn_t gfar_receive(int irq, void *dev_id)
+ gfar_read(&priv->regs->imask));
+ }
+ #else
++ /* Clear IEVENT, so rx interrupt isn't called again
++ * because of this interrupt */
++ gfar_write(&priv->regs->ievent, IEVENT_RX_MASK);
+
+ spin_lock_irqsave(&priv->rxlock, flags);
+ gfar_clean_rx_ring(dev, priv->rx_ring_size);
+
+ /* If we are coalescing interrupts, update the timer */
+ /* Otherwise, clear it */
+- if (priv->rxcoalescing)
++ if (likely(priv->rxcoalescing)) {
++ gfar_write(&priv->regs->rxic, 0);
+ gfar_write(&priv->regs->rxic,
+ mk_ic_value(priv->rxcount, priv->rxtime));
+- else
+- gfar_write(&priv->regs->rxic, 0);
++ }
+
+ spin_unlock_irqrestore(&priv->rxlock, flags);
+ #endif
+@@ -1523,12 +1563,31 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
+ bdp = priv->cur_rx;
+
+ while (!((bdp->status & RXBD_EMPTY) || (--rx_work_limit < 0))) {
++ struct sk_buff *newskb;
+ rmb();
++
++ /* Add another skb for the future */
++ newskb = gfar_new_skb(dev);
++
+ skb = priv->rx_skbuff[priv->skb_currx];
+
+- if (!(bdp->status &
+- (RXBD_LARGE | RXBD_SHORT | RXBD_NONOCTET
+- | RXBD_CRCERR | RXBD_OVERRUN | RXBD_TRUNCATED))) {
++ /* We drop the frame if we failed to allocate a new buffer */
++ if (unlikely(!newskb || !(bdp->status & RXBD_LAST) ||
++ bdp->status & RXBD_ERR)) {
++ count_errors(bdp->status, dev);
++
++ if (unlikely(!newskb))
++ newskb = skb;
++
++ if (skb) {
++ dma_unmap_single(&priv->dev->dev,
++ bdp->bufPtr,
++ priv->rx_buffer_size,
++ DMA_FROM_DEVICE);
++
++ dev_kfree_skb_any(skb);
++ }
++ } else {
+ /* Increment the number of packets */
+ dev->stats.rx_packets++;
+ howmany++;
+@@ -1539,23 +1598,14 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
+ gfar_process_frame(dev, skb, pkt_len);
+
+ dev->stats.rx_bytes += pkt_len;
+- } else {
+- count_errors(bdp->status, dev);
+-
+- if (skb)
+- dev_kfree_skb_any(skb);
+-
+- priv->rx_skbuff[priv->skb_currx] = NULL;
+ }
+
+ dev->last_rx = jiffies;
+
+- /* Clear the status flags for this buffer */
+- bdp->status &= ~RXBD_STATS;
++ priv->rx_skbuff[priv->skb_currx] = newskb;
+
+- /* Add another skb for the future */
+- skb = gfar_new_skb(dev, bdp);
+- priv->rx_skbuff[priv->skb_currx] = skb;
++ /* Setup the new bdp */
++ gfar_new_rxbdp(dev, bdp, newskb);
+
+ /* Update to the next pointer */
+ if (bdp->status & RXBD_WRAP)
+@@ -1565,9 +1615,8 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
+
+ /* update to point at the next skb */
+ priv->skb_currx =
+- (priv->skb_currx +
+- 1) & RX_RING_MOD_MASK(priv->rx_ring_size);
+-
++ (priv->skb_currx + 1) &
++ RX_RING_MOD_MASK(priv->rx_ring_size);
+ }
+
+ /* Update the current rxbd pointer to be the next one */
+@@ -1582,6 +1631,13 @@ static int gfar_poll(struct napi_struct *napi, int budget)
+ struct gfar_private *priv = container_of(napi, struct gfar_private, napi);
+ struct net_device *dev = priv->dev;
+ int howmany;
++ unsigned long flags;
++
++ /* If we fail to get the lock, don't bother with the TX BDs */
++ if (spin_trylock_irqsave(&priv->txlock, flags)) {
++ gfar_clean_tx_ring(dev);
++ spin_unlock_irqrestore(&priv->txlock, flags);
++ }
+
+ howmany = gfar_clean_rx_ring(dev, budget);
+
+@@ -1595,11 +1651,11 @@ static int gfar_poll(struct napi_struct *napi, int budget)
+
+ /* If we are coalescing interrupts, update the timer */
+ /* Otherwise, clear it */
+- if (priv->rxcoalescing)
++ if (likely(priv->rxcoalescing)) {
++ gfar_write(&priv->regs->rxic, 0);
+ gfar_write(&priv->regs->rxic,
+ mk_ic_value(priv->rxcount, priv->rxtime));
+- else
+- gfar_write(&priv->regs->rxic, 0);
++ }
+ }
+
+ return howmany;
+@@ -1975,12 +2031,16 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
+ return IRQ_HANDLED;
+ }
+
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:fsl-gianfar");
++
+ /* Structure for a device driver */
+ static struct platform_driver gfar_driver = {
+ .probe = gfar_probe,
+ .remove = gfar_remove,
+ .driver = {
+ .name = "fsl-gianfar",
++ .owner = THIS_MODULE,
+ },
+ };
+
+diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
+index 46cd773..0d08836 100644
+--- a/drivers/net/gianfar.h
++++ b/drivers/net/gianfar.h
+@@ -102,7 +102,7 @@ extern const char gfar_driver_version[];
+ #define DEFAULT_FIFO_TX_STARVE 0x40
+ #define DEFAULT_FIFO_TX_STARVE_OFF 0x80
+ #define DEFAULT_BD_STASH 1
+-#define DEFAULT_STASH_LENGTH 64
++#define DEFAULT_STASH_LENGTH 96
+ #define DEFAULT_STASH_INDEX 0
+
+ /* The number of Exact Match registers */
+@@ -124,11 +124,18 @@ extern const char gfar_driver_version[];
+
+ #define DEFAULT_TX_COALESCE 1
+ #define DEFAULT_TXCOUNT 16
+-#define DEFAULT_TXTIME 4
++#define DEFAULT_TXTIME 21
+
++#define DEFAULT_RXTIME 21
++
++/* Non NAPI Case */
++#ifndef CONFIG_GFAR_NAPI
+ #define DEFAULT_RX_COALESCE 1
+ #define DEFAULT_RXCOUNT 16
+-#define DEFAULT_RXTIME 4
++#else
++#define DEFAULT_RX_COALESCE 0
++#define DEFAULT_RXCOUNT 0
++#endif /* CONFIG_GFAR_NAPI */
+
+ #define TBIPA_VALUE 0x1f
+ #define MIIMCFG_INIT_VALUE 0x00000007
+@@ -242,6 +249,7 @@ extern const char gfar_driver_version[];
+ #define IEVENT_PERR 0x00000001
+ #define IEVENT_RX_MASK (IEVENT_RXB0 | IEVENT_RXF0)
+ #define IEVENT_TX_MASK (IEVENT_TXB | IEVENT_TXF)
++#define IEVENT_RTX_MASK (IEVENT_RX_MASK | IEVENT_TX_MASK)
+ #define IEVENT_ERR_MASK \
+ (IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \
+ IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC \
+@@ -269,11 +277,12 @@ extern const char gfar_driver_version[];
+ #define IMASK_FIQ 0x00000004
+ #define IMASK_DPE 0x00000002
+ #define IMASK_PERR 0x00000001
+-#define IMASK_RX_DISABLED ~(IMASK_RXFEN0 | IMASK_BSY)
+ #define IMASK_DEFAULT (IMASK_TXEEN | IMASK_TXFEN | IMASK_TXBEN | \
+ IMASK_RXFEN0 | IMASK_BSY | IMASK_EBERR | IMASK_BABR | \
+ IMASK_XFUN | IMASK_RXC | IMASK_BABT | IMASK_DPE \
+ | IMASK_PERR)
++#define IMASK_RTX_DISABLED ((~(IMASK_RXFEN0 | IMASK_TXFEN | IMASK_BSY)) \
++ & IMASK_DEFAULT)
+
+ /* Fifo management */
+ #define FIFO_TX_THR_MASK 0x01ff
+@@ -340,6 +349,9 @@ extern const char gfar_driver_version[];
+ #define RXBD_OVERRUN 0x0002
+ #define RXBD_TRUNCATED 0x0001
+ #define RXBD_STATS 0x01ff
++#define RXBD_ERR (RXBD_LARGE | RXBD_SHORT | RXBD_NONOCTET \
++ | RXBD_CRCERR | RXBD_OVERRUN \
++ | RXBD_TRUNCATED)
+
+ /* Rx FCB status field bits */
+ #define RXFCB_VLN 0x8000
+diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
+index 2432762..b889892 100644
+--- a/drivers/net/gianfar_mii.c
++++ b/drivers/net/gianfar_mii.c
+@@ -173,7 +173,7 @@ int gfar_mdio_probe(struct device *dev)
+ new_bus->read = &gfar_mdio_read,
+ new_bus->write = &gfar_mdio_write,
+ new_bus->reset = &gfar_mdio_reset,
+- new_bus->id = pdev->id;
++ snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
+
+ pdata = (struct gianfar_mdio_data *)pdev->dev.platform_data;
+
+diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
+index 0a9b751..1da55dd 100644
+--- a/drivers/net/hamradio/6pack.c
++++ b/drivers/net/hamradio/6pack.c
+@@ -33,7 +33,7 @@
+ #include <linux/init.h>
+ #include <linux/ip.h>
+ #include <linux/tcp.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+ #include <asm/atomic.h>
+
+ #define SIXPACK_VERSION "Revision: 0.3.0"
+diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
+index 5ddf8b0..5f4b4c6 100644
+--- a/drivers/net/hamradio/bpqether.c
++++ b/drivers/net/hamradio/bpqether.c
+@@ -172,7 +172,7 @@ static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty
+ struct ethhdr *eth;
+ struct bpqdev *bpq;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ goto drop;
+
+ if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+@@ -553,7 +553,7 @@ static int bpq_device_event(struct notifier_block *this,unsigned long event, voi
+ {
+ struct net_device *dev = (struct net_device *)ptr;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ if (!dev_is_ethdev(dev))
+diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
+index e04bf99..0b94833 100644
+--- a/drivers/net/hamradio/dmascc.c
++++ b/drivers/net/hamradio/dmascc.c
+@@ -1083,15 +1083,12 @@ static void start_timer(struct scc_priv *priv, int t, int r15)
+ if (t == 0) {
+ tm_isr(priv);
+ } else if (t > 0) {
+- save_flags(flags);
+- cli();
+ outb(t & 0xFF, priv->tmr_cnt);
+ outb((t >> 8) & 0xFF, priv->tmr_cnt);
+ if (priv->type != TYPE_TWIN) {
+ write_scc(priv, R15, r15 | CTSIE);
+ priv->rr0 |= CTS;
+ }
+- restore_flags(flags);
+ }
+ }
+
+diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
+index 378a239..5d2108c 100644
+--- a/drivers/net/ibm_newemac/core.c
++++ b/drivers/net/ibm_newemac/core.c
+@@ -43,6 +43,8 @@
+ #include <asm/io.h>
+ #include <asm/dma.h>
+ #include <asm/uaccess.h>
++#include <asm/dcr.h>
++#include <asm/dcr-regs.h>
+
+ #include "core.h"
+
+@@ -127,10 +129,35 @@ static struct device_node *emac_boot_list[EMAC_BOOT_LIST_SIZE];
+ static inline void emac_report_timeout_error(struct emac_instance *dev,
+ const char *error)
+ {
+- if (net_ratelimit())
++ if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX |
++ EMAC_FTR_440EP_PHY_CLK_FIX))
++ DBG(dev, "%s" NL, error);
++ else if (net_ratelimit())
+ printk(KERN_ERR "%s: %s\n", dev->ndev->name, error);
+ }
+
++/* EMAC PHY clock workaround:
++ * 440EP/440GR has more sane SDR0_MFR register implementation than 440GX,
++ * which allows controlling each EMAC clock
++ */
++static inline void emac_rx_clk_tx(struct emac_instance *dev)
++{
++#ifdef CONFIG_PPC_DCR_NATIVE
++ if (emac_has_feature(dev, EMAC_FTR_440EP_PHY_CLK_FIX))
++ dcri_clrset(SDR0, SDR0_MFR,
++ 0, SDR0_MFR_ECS >> dev->cell_index);
++#endif
++}
++
++static inline void emac_rx_clk_default(struct emac_instance *dev)
++{
++#ifdef CONFIG_PPC_DCR_NATIVE
++ if (emac_has_feature(dev, EMAC_FTR_440EP_PHY_CLK_FIX))
++ dcri_clrset(SDR0, SDR0_MFR,
++ SDR0_MFR_ECS >> dev->cell_index, 0);
++#endif
++}
++
+ /* PHY polling intervals */
+ #define PHY_POLL_LINK_ON HZ
+ #define PHY_POLL_LINK_OFF (HZ / 5)
+@@ -524,7 +551,10 @@ static int emac_configure(struct emac_instance *dev)
+ rx_size = dev->rx_fifo_size_gige;
+
+ if (dev->ndev->mtu > ETH_DATA_LEN) {
+- mr1 |= EMAC_MR1_JPSM;
++ if (emac_has_feature(dev, EMAC_FTR_EMAC4))
++ mr1 |= EMAC4_MR1_JPSM;
++ else
++ mr1 |= EMAC_MR1_JPSM;
+ dev->stop_timeout = STOP_TIMEOUT_1000_JUMBO;
+ } else
+ dev->stop_timeout = STOP_TIMEOUT_1000;
+@@ -708,7 +738,7 @@ static int __emac_mdio_read(struct emac_instance *dev, u8 id, u8 reg)
+ rgmii_get_mdio(dev->rgmii_dev, dev->rgmii_port);
+
+ /* Wait for management interface to become idle */
+- n = 10;
++ n = 20;
+ while (!emac_phy_done(dev, in_be32(&p->stacr))) {
+ udelay(1);
+ if (!--n) {
+@@ -733,7 +763,7 @@ static int __emac_mdio_read(struct emac_instance *dev, u8 id, u8 reg)
+ out_be32(&p->stacr, r);
+
+ /* Wait for read to complete */
+- n = 100;
++ n = 200;
+ while (!emac_phy_done(dev, (r = in_be32(&p->stacr)))) {
+ udelay(1);
+ if (!--n) {
+@@ -780,7 +810,7 @@ static void __emac_mdio_write(struct emac_instance *dev, u8 id, u8 reg,
+ rgmii_get_mdio(dev->rgmii_dev, dev->rgmii_port);
+
+ /* Wait for management interface to be idle */
+- n = 10;
++ n = 20;
+ while (!emac_phy_done(dev, in_be32(&p->stacr))) {
+ udelay(1);
+ if (!--n) {
+@@ -806,7 +836,7 @@ static void __emac_mdio_write(struct emac_instance *dev, u8 id, u8 reg,
+ out_be32(&p->stacr, r);
+
+ /* Wait for write to complete */
+- n = 100;
++ n = 200;
+ while (!emac_phy_done(dev, in_be32(&p->stacr))) {
+ udelay(1);
+ if (!--n) {
+@@ -1094,9 +1124,11 @@ static int emac_open(struct net_device *ndev)
+ int link_poll_interval;
+ if (dev->phy.def->ops->poll_link(&dev->phy)) {
+ dev->phy.def->ops->read_link(&dev->phy);
++ emac_rx_clk_default(dev);
+ netif_carrier_on(dev->ndev);
+ link_poll_interval = PHY_POLL_LINK_ON;
+ } else {
++ emac_rx_clk_tx(dev);
+ netif_carrier_off(dev->ndev);
+ link_poll_interval = PHY_POLL_LINK_OFF;
+ }
+@@ -1174,6 +1206,7 @@ static void emac_link_timer(struct work_struct *work)
+
+ if (dev->phy.def->ops->poll_link(&dev->phy)) {
+ if (!netif_carrier_ok(dev->ndev)) {
++ emac_rx_clk_default(dev);
+ /* Get new link parameters */
+ dev->phy.def->ops->read_link(&dev->phy);
+
+@@ -1186,6 +1219,7 @@ static void emac_link_timer(struct work_struct *work)
+ link_poll_interval = PHY_POLL_LINK_ON;
+ } else {
+ if (netif_carrier_ok(dev->ndev)) {
++ emac_rx_clk_tx(dev);
+ netif_carrier_off(dev->ndev);
+ netif_tx_disable(dev->ndev);
+ emac_reinitialize(dev);
+@@ -2237,7 +2271,7 @@ static int __devinit emac_of_bus_notify(struct notifier_block *nb,
+ return 0;
+ }
+
+-static struct notifier_block emac_of_bus_notifier = {
++static struct notifier_block emac_of_bus_notifier __devinitdata = {
+ .notifier_call = emac_of_bus_notify
+ };
+
+@@ -2330,6 +2364,19 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
+ dev->phy.mdio_read = emac_mdio_read;
+ dev->phy.mdio_write = emac_mdio_write;
+
++ /* Enable internal clock source */
++#ifdef CONFIG_PPC_DCR_NATIVE
++ if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX))
++ dcri_clrset(SDR0, SDR0_MFR, 0, SDR0_MFR_ECS);
++#endif
++ /* PHY clock workaround */
++ emac_rx_clk_tx(dev);
++
++ /* Enable internal clock source on 440GX*/
++#ifdef CONFIG_PPC_DCR_NATIVE
++ if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX))
++ dcri_clrset(SDR0, SDR0_MFR, 0, SDR0_MFR_ECS);
++#endif
+ /* Configure EMAC with defaults so we can at least use MDIO
+ * This is needed mostly for 440GX
+ */
+@@ -2362,6 +2409,12 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
+ if (!emac_mii_phy_probe(&dev->phy, i))
+ break;
+ }
++
++ /* Enable external clock source */
++#ifdef CONFIG_PPC_DCR_NATIVE
++ if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX))
++ dcri_clrset(SDR0, SDR0_MFR, SDR0_MFR_ECS, 0);
++#endif
+ mutex_unlock(&emac_phy_map_lock);
+ if (i == 0x20) {
+ printk(KERN_WARNING "%s: can't find PHY!\n", np->full_name);
+@@ -2487,8 +2540,15 @@ static int __devinit emac_init_config(struct emac_instance *dev)
+ }
+
+ /* Check EMAC version */
+- if (of_device_is_compatible(np, "ibm,emac4"))
++ if (of_device_is_compatible(np, "ibm,emac4")) {
+ dev->features |= EMAC_FTR_EMAC4;
++ if (of_device_is_compatible(np, "ibm,emac-440gx"))
++ dev->features |= EMAC_FTR_440GX_PHY_CLK_FIX;
++ } else {
++ if (of_device_is_compatible(np, "ibm,emac-440ep") ||
++ of_device_is_compatible(np, "ibm,emac-440gr"))
++ dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX;
++ }
+
+ /* Fixup some feature bits based on the device tree */
+ if (of_get_property(np, "has-inverted-stacr-oc", NULL))
+@@ -2559,8 +2619,11 @@ static int __devinit emac_probe(struct of_device *ofdev,
+ struct device_node **blist = NULL;
+ int err, i;
+
+- /* Skip unused/unwired EMACS */
+- if (of_get_property(np, "unused", NULL))
++ /* Skip unused/unwired EMACS. We leave the check for an unused
++ * property here for now, but new flat device trees should set a
++ * status property to "disabled" instead.
++ */
++ if (of_get_property(np, "unused", NULL) || !of_device_is_available(np))
+ return -ENODEV;
+
+ /* Find ourselves in the bootlist if we are there */
+diff --git a/drivers/net/ibm_newemac/core.h b/drivers/net/ibm_newemac/core.h
+index 4e74d82..1683db9 100644
+--- a/drivers/net/ibm_newemac/core.h
++++ b/drivers/net/ibm_newemac/core.h
+@@ -301,6 +301,14 @@ struct emac_instance {
+ * Set if we have new type STACR with STAOPC
+ */
+ #define EMAC_FTR_HAS_NEW_STACR 0x00000040
++/*
++ * Set if we need phy clock workaround for 440gx
++ */
++#define EMAC_FTR_440GX_PHY_CLK_FIX 0x00000080
++/*
++ * Set if we need phy clock workaround for 440ep or 440gr
++ */
++#define EMAC_FTR_440EP_PHY_CLK_FIX 0x00000100
+
+
+ /* Right now, we don't quite handle the always/possible masks on the
+@@ -312,8 +320,8 @@ enum {
+
+ EMAC_FTRS_POSSIBLE =
+ #ifdef CONFIG_IBM_NEW_EMAC_EMAC4
+- EMAC_FTR_EMAC4 | EMAC_FTR_HAS_NEW_STACR |
+- EMAC_FTR_STACR_OC_INVERT |
++ EMAC_FTR_EMAC4 | EMAC_FTR_HAS_NEW_STACR |
++ EMAC_FTR_STACR_OC_INVERT | EMAC_FTR_440GX_PHY_CLK_FIX |
+ #endif
+ #ifdef CONFIG_IBM_NEW_EMAC_TAH
+ EMAC_FTR_HAS_TAH |
+@@ -324,7 +332,7 @@ enum {
+ #ifdef CONFIG_IBM_NEW_EMAC_RGMII
+ EMAC_FTR_HAS_RGMII |
+ #endif
+- 0,
++ EMAC_FTR_440EP_PHY_CLK_FIX,
+ };
+
+ static inline int emac_has_feature(struct emac_instance *dev,
+diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c
+index 6869f08..10c267b 100644
+--- a/drivers/net/ibm_newemac/mal.c
++++ b/drivers/net/ibm_newemac/mal.c
+@@ -61,8 +61,8 @@ int __devinit mal_register_commac(struct mal_instance *mal,
+ return 0;
+ }
+
+-void __devexit mal_unregister_commac(struct mal_instance *mal,
+- struct mal_commac *commac)
++void mal_unregister_commac(struct mal_instance *mal,
++ struct mal_commac *commac)
+ {
+ unsigned long flags;
+
+@@ -136,6 +136,14 @@ void mal_enable_rx_channel(struct mal_instance *mal, int channel)
+ {
+ unsigned long flags;
+
++ /*
++ * On some 4xx PPC's (e.g. 460EX/GT), the rx channel is a multiple
++ * of 8, but enabling in MAL_RXCASR needs the divided by 8 value
++ * for the bitmask
++ */
++ if (!(channel % 8))
++ channel >>= 3;
++
+ spin_lock_irqsave(&mal->lock, flags);
+
+ MAL_DBG(mal, "enable_rx(%d)" NL, channel);
+@@ -148,6 +156,14 @@ void mal_enable_rx_channel(struct mal_instance *mal, int channel)
+
+ void mal_disable_rx_channel(struct mal_instance *mal, int channel)
+ {
++ /*
++ * On some 4xx PPC's (e.g. 460EX/GT), the rx channel is a multiple
++ * of 8, but enabling in MAL_RXCASR needs the divided by 8 value
++ * for the bitmask
++ */
++ if (!(channel % 8))
++ channel >>= 3;
++
+ set_mal_dcrn(mal, MAL_RXCARR, MAL_CHAN_MASK(channel));
+
+ MAL_DBG(mal, "disable_rx(%d)" NL, channel);
+diff --git a/drivers/net/ibm_newemac/rgmii.c b/drivers/net/ibm_newemac/rgmii.c
+index 5757788..e32da3d 100644
+--- a/drivers/net/ibm_newemac/rgmii.c
++++ b/drivers/net/ibm_newemac/rgmii.c
+@@ -179,7 +179,7 @@ void rgmii_put_mdio(struct of_device *ofdev, int input)
+ mutex_unlock(&dev->lock);
+ }
+
+-void __devexit rgmii_detach(struct of_device *ofdev, int input)
++void rgmii_detach(struct of_device *ofdev, int input)
+ {
+ struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev);
+ struct rgmii_regs __iomem *p = dev->base;
+diff --git a/drivers/net/ibm_newemac/tah.c b/drivers/net/ibm_newemac/tah.c
+index b023d10..30173a9 100644
+--- a/drivers/net/ibm_newemac/tah.c
++++ b/drivers/net/ibm_newemac/tah.c
+@@ -35,7 +35,7 @@ int __devinit tah_attach(struct of_device *ofdev, int channel)
+ return 0;
+ }
+
+-void __devexit tah_detach(struct of_device *ofdev, int channel)
++void tah_detach(struct of_device *ofdev, int channel)
+ {
+ struct tah_instance *dev = dev_get_drvdata(&ofdev->dev);
+
+diff --git a/drivers/net/ibm_newemac/zmii.c b/drivers/net/ibm_newemac/zmii.c
+index 2ea472a..17b1541 100644
+--- a/drivers/net/ibm_newemac/zmii.c
++++ b/drivers/net/ibm_newemac/zmii.c
+@@ -189,7 +189,7 @@ void zmii_set_speed(struct of_device *ofdev, int input, int speed)
+ mutex_unlock(&dev->lock);
+ }
+
+-void __devexit zmii_detach(struct of_device *ofdev, int input)
++void zmii_detach(struct of_device *ofdev, int input)
+ {
+ struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev);
+
+diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
+index 57772be..ce4fc2e 100644
+--- a/drivers/net/ibmveth.c
++++ b/drivers/net/ibmveth.c
+@@ -49,7 +49,6 @@
+ #include <linux/in.h>
+ #include <linux/ip.h>
+ #include <net/net_namespace.h>
+-#include <asm/semaphore.h>
+ #include <asm/hvcall.h>
+ #include <asm/atomic.h>
+ #include <asm/vio.h>
+@@ -1259,26 +1258,7 @@ static void ibmveth_proc_unregister_driver(void)
+ remove_proc_entry(IBMVETH_PROC_DIR, init_net.proc_net);
+ }
+
+-static void *ibmveth_seq_start(struct seq_file *seq, loff_t *pos)
+-{
+- if (*pos == 0) {
+- return (void *)1;
+- } else {
+- return NULL;
+- }
+-}
+-
+-static void *ibmveth_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+-{
+- ++*pos;
+- return NULL;
+-}
+-
+-static void ibmveth_seq_stop(struct seq_file *seq, void *v)
+-{
+-}
+-
+-static int ibmveth_seq_show(struct seq_file *seq, void *v)
++static int ibmveth_show(struct seq_file *seq, void *v)
+ {
+ struct ibmveth_adapter *adapter = seq->private;
+ char *current_mac = ((char*) &adapter->netdev->dev_addr);
+@@ -1302,27 +1282,10 @@ static int ibmveth_seq_show(struct seq_file *seq, void *v)
+
+ return 0;
+ }
+-static struct seq_operations ibmveth_seq_ops = {
+- .start = ibmveth_seq_start,
+- .next = ibmveth_seq_next,
+- .stop = ibmveth_seq_stop,
+- .show = ibmveth_seq_show,
+-};
+
+ static int ibmveth_proc_open(struct inode *inode, struct file *file)
+ {
+- struct seq_file *seq;
+- struct proc_dir_entry *proc;
+- int rc;
+-
+- rc = seq_open(file, &ibmveth_seq_ops);
+- if (!rc) {
+- /* recover the pointer buried in proc_dir_entry data */
+- seq = file->private_data;
+- proc = PDE(inode);
+- seq->private = proc->data;
+- }
+- return rc;
++ return single_open(file, ibmveth_show, PDE(inode)->data);
+ }
+
+ static const struct file_operations ibmveth_proc_fops = {
+@@ -1330,7 +1293,7 @@ static const struct file_operations ibmveth_proc_fops = {
+ .open = ibmveth_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = seq_release,
++ .release = single_release,
+ };
+
+ static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter)
+diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
+index aaee02e..ae398f0 100644
+--- a/drivers/net/igb/igb_main.c
++++ b/drivers/net/igb/igb_main.c
+@@ -871,6 +871,7 @@ static int __devinit igb_probe(struct pci_dev *pdev,
+ goto err_pci_reg;
+
+ pci_set_master(pdev);
++ pci_save_state(pdev);
+
+ err = -ENOMEM;
+ netdev = alloc_etherdev(sizeof(struct igb_adapter));
+@@ -4079,6 +4080,7 @@ static pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev)
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+ pci_set_master(pdev);
++ pci_restore_state(pdev);
+
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ pci_enable_wake(pdev, PCI_D3cold, 0);
+diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c
+index 9f58452..083b0dd 100644
+--- a/drivers/net/irda/ali-ircc.c
++++ b/drivers/net/irda/ali-ircc.c
+@@ -60,6 +60,7 @@ static struct platform_driver ali_ircc_driver = {
+ .resume = ali_ircc_resume,
+ .driver = {
+ .name = ALI_IRCC_DRIVER_NAME,
++ .owner = THIS_MODULE,
+ },
+ };
+
+@@ -2256,6 +2257,7 @@ static void FIR2SIR(int iobase)
+ MODULE_AUTHOR("Benjamin Kong <benjamin_kong at ali.com.tw>");
+ MODULE_DESCRIPTION("ALi FIR Controller Driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:" ALI_IRCC_DRIVER_NAME);
+
+
+ module_param_array(io, int, NULL, 0);
+diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
+index 8c09344..d5c2d27 100644
+--- a/drivers/net/irda/pxaficp_ir.c
++++ b/drivers/net/irda/pxaficp_ir.c
+@@ -36,6 +36,7 @@
+ #include <asm/hardware.h>
+ #include <asm/arch/irda.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+
+ #ifdef CONFIG_MACH_MAINSTONE
+ #include <asm/arch/mainstone.h>
+@@ -831,6 +832,11 @@ static int pxa_irda_probe(struct platform_device *pdev)
+ if (err)
+ goto err_mem_5;
+
++ if (si->pdata->startup)
++ err = si->pdata->startup(si->dev);
++ if (err)
++ goto err_startup;
++
+ dev->hard_start_xmit = pxa_irda_hard_xmit;
+ dev->open = pxa_irda_start;
+ dev->stop = pxa_irda_stop;
+@@ -856,6 +862,9 @@ static int pxa_irda_probe(struct platform_device *pdev)
+ dev_set_drvdata(&pdev->dev, dev);
+
+ if (err) {
++ if (si->pdata->shutdown)
++ si->pdata->shutdown(si->dev);
++err_startup:
+ kfree(si->tx_buff.head);
+ err_mem_5:
+ kfree(si->rx_buff.head);
+@@ -881,6 +890,8 @@ static int pxa_irda_remove(struct platform_device *_dev)
+ if (dev) {
+ struct pxa_irda *si = netdev_priv(dev);
+ unregister_netdev(dev);
++ if (si->pdata->shutdown)
++ si->pdata->shutdown(si->dev);
+ kfree(si->tx_buff.head);
+ kfree(si->rx_buff.head);
+ clk_put(si->fir_clk);
+@@ -897,6 +908,7 @@ static int pxa_irda_remove(struct platform_device *_dev)
+ static struct platform_driver pxa_ir_driver = {
+ .driver = {
+ .name = "pxa2xx-ir",
++ .owner = THIS_MODULE,
+ },
+ .probe = pxa_irda_probe,
+ .remove = pxa_irda_remove,
+@@ -918,3 +930,4 @@ module_init(pxa_irda_init);
+ module_exit(pxa_irda_exit);
+
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:pxa2xx-ir");
+diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c
+index 056639f..1bc8518 100644
+--- a/drivers/net/irda/sa1100_ir.c
++++ b/drivers/net/irda/sa1100_ir.c
+@@ -1008,6 +1008,7 @@ static struct platform_driver sa1100ir_driver = {
+ .resume = sa1100_irda_resume,
+ .driver = {
+ .name = "sa11x0-ir",
++ .owner = THIS_MODULE,
+ },
+ };
+
+@@ -1041,3 +1042,4 @@ MODULE_LICENSE("GPL");
+ MODULE_PARM_DESC(power_level, "IrDA power level, 1 (low) to 3 (high)");
+ MODULE_PARM_DESC(tx_lpm, "Enable transmitter low power (1.6us) mode");
+ MODULE_PARM_DESC(max_rate, "Maximum baud rate (4000000, 115200, 57600, 38400, 19200, 9600)");
++MODULE_ALIAS("platform:sa11x0-ir");
+diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
+index 58d3bb6..b8d0639 100644
+--- a/drivers/net/iseries_veth.c
++++ b/drivers/net/iseries_veth.c
+@@ -308,7 +308,8 @@ static void veth_complete_allocation(void *parm, int number)
+
+ static int veth_allocate_events(HvLpIndex rlp, int number)
+ {
+- struct veth_allocation vc = { COMPLETION_INITIALIZER(vc.c), 0 };
++ struct veth_allocation vc =
++ { COMPLETION_INITIALIZER_ONSTACK(vc.c), 0 };
+
+ mf_allocate_lp_events(rlp, HvLpEvent_Type_VirtualLan,
+ sizeof(struct veth_lpevent), number,
+diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h
+index 3d2e721..16f9c75 100644
+--- a/drivers/net/ixgb/ixgb.h
++++ b/drivers/net/ixgb/ixgb.h
+@@ -117,8 +117,8 @@ struct ixgb_buffer {
+ struct sk_buff *skb;
+ dma_addr_t dma;
+ unsigned long time_stamp;
+- uint16_t length;
+- uint16_t next_to_watch;
++ u16 length;
++ u16 next_to_watch;
+ };
+
+ struct ixgb_desc_ring {
+@@ -152,13 +152,12 @@ struct ixgb_desc_ring {
+ struct ixgb_adapter {
+ struct timer_list watchdog_timer;
+ struct vlan_group *vlgrp;
+- uint32_t bd_number;
+- uint32_t rx_buffer_len;
+- uint32_t part_num;
+- uint16_t link_speed;
+- uint16_t link_duplex;
++ u32 bd_number;
++ u32 rx_buffer_len;
++ u32 part_num;
++ u16 link_speed;
++ u16 link_duplex;
+ spinlock_t tx_lock;
+- atomic_t irq_sem;
+ struct work_struct tx_timeout_task;
+
+ struct timer_list blink_timer;
+@@ -168,20 +167,20 @@ struct ixgb_adapter {
+ struct ixgb_desc_ring tx_ring ____cacheline_aligned_in_smp;
+ unsigned int restart_queue;
+ unsigned long timeo_start;
+- uint32_t tx_cmd_type;
+- uint64_t hw_csum_tx_good;
+- uint64_t hw_csum_tx_error;
+- uint32_t tx_int_delay;
+- uint32_t tx_timeout_count;
+- boolean_t tx_int_delay_enable;
+- boolean_t detect_tx_hung;
++ u32 tx_cmd_type;
++ u64 hw_csum_tx_good;
++ u64 hw_csum_tx_error;
++ u32 tx_int_delay;
++ u32 tx_timeout_count;
++ bool tx_int_delay_enable;
++ bool detect_tx_hung;
+
+ /* RX */
+ struct ixgb_desc_ring rx_ring;
+- uint64_t hw_csum_rx_error;
+- uint64_t hw_csum_rx_good;
+- uint32_t rx_int_delay;
+- boolean_t rx_csum;
++ u64 hw_csum_rx_error;
++ u64 hw_csum_rx_good;
++ u32 rx_int_delay;
++ bool rx_csum;
+
+ /* OS defined structs */
+ struct napi_struct napi;
+@@ -193,8 +192,17 @@ struct ixgb_adapter {
+ struct ixgb_hw hw;
+ u16 msg_enable;
+ struct ixgb_hw_stats stats;
+- uint32_t alloc_rx_buff_failed;
+- boolean_t have_msi;
++ u32 alloc_rx_buff_failed;
++ bool have_msi;
++ unsigned long flags;
++};
++
++enum ixgb_state_t {
++ /* TBD
++ __IXGB_TESTING,
++ __IXGB_RESETTING,
++ */
++ __IXGB_DOWN
+ };
+
+ /* Exported from other modules */
+@@ -203,4 +211,14 @@ extern void ixgb_set_ethtool_ops(struct net_device *netdev);
+ extern char ixgb_driver_name[];
+ extern const char ixgb_driver_version[];
+
++extern int ixgb_up(struct ixgb_adapter *adapter);
++extern void ixgb_down(struct ixgb_adapter *adapter, bool kill_watchdog);
++extern void ixgb_reset(struct ixgb_adapter *adapter);
++extern int ixgb_setup_rx_resources(struct ixgb_adapter *adapter);
++extern int ixgb_setup_tx_resources(struct ixgb_adapter *adapter);
++extern void ixgb_free_rx_resources(struct ixgb_adapter *adapter);
++extern void ixgb_free_tx_resources(struct ixgb_adapter *adapter);
++extern void ixgb_update_stats(struct ixgb_adapter *adapter);
++
++
+ #endif /* _IXGB_H_ */
+diff --git a/drivers/net/ixgb/ixgb_ee.c b/drivers/net/ixgb/ixgb_ee.c
+index e8eb0fd..2f7ed52 100644
+--- a/drivers/net/ixgb/ixgb_ee.c
++++ b/drivers/net/ixgb/ixgb_ee.c
+@@ -29,14 +29,14 @@
+ #include "ixgb_hw.h"
+ #include "ixgb_ee.h"
+ /* Local prototypes */
+-static uint16_t ixgb_shift_in_bits(struct ixgb_hw *hw);
++static u16 ixgb_shift_in_bits(struct ixgb_hw *hw);
+
+ static void ixgb_shift_out_bits(struct ixgb_hw *hw,
+- uint16_t data,
+- uint16_t count);
++ u16 data,
++ u16 count);
+ static void ixgb_standby_eeprom(struct ixgb_hw *hw);
+
+-static boolean_t ixgb_wait_eeprom_command(struct ixgb_hw *hw);
++static bool ixgb_wait_eeprom_command(struct ixgb_hw *hw);
+
+ static void ixgb_cleanup_eeprom(struct ixgb_hw *hw);
+
+@@ -48,7 +48,7 @@ static void ixgb_cleanup_eeprom(struct ixgb_hw *hw);
+ *****************************************************************************/
+ static void
+ ixgb_raise_clock(struct ixgb_hw *hw,
+- uint32_t *eecd_reg)
++ u32 *eecd_reg)
+ {
+ /* Raise the clock input to the EEPROM (by setting the SK bit), and then
+ * wait 50 microseconds.
+@@ -67,7 +67,7 @@ ixgb_raise_clock(struct ixgb_hw *hw,
+ *****************************************************************************/
+ static void
+ ixgb_lower_clock(struct ixgb_hw *hw,
+- uint32_t *eecd_reg)
++ u32 *eecd_reg)
+ {
+ /* Lower the clock input to the EEPROM (by clearing the SK bit), and then
+ * wait 50 microseconds.
+@@ -87,11 +87,11 @@ ixgb_lower_clock(struct ixgb_hw *hw,
+ *****************************************************************************/
+ static void
+ ixgb_shift_out_bits(struct ixgb_hw *hw,
+- uint16_t data,
+- uint16_t count)
++ u16 data,
++ u16 count)
+ {
+- uint32_t eecd_reg;
+- uint32_t mask;
++ u32 eecd_reg;
++ u32 mask;
+
+ /* We need to shift "count" bits out to the EEPROM. So, value in the
+ * "data" parameter will be shifted out to the EEPROM one bit at a time.
+@@ -133,12 +133,12 @@ ixgb_shift_out_bits(struct ixgb_hw *hw,
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-static uint16_t
++static u16
+ ixgb_shift_in_bits(struct ixgb_hw *hw)
+ {
+- uint32_t eecd_reg;
+- uint32_t i;
+- uint16_t data;
++ u32 eecd_reg;
++ u32 i;
++ u16 data;
+
+ /* In order to read a register from the EEPROM, we need to shift 16 bits
+ * in from the EEPROM. Bits are "shifted in" by raising the clock input to
+@@ -179,7 +179,7 @@ ixgb_shift_in_bits(struct ixgb_hw *hw)
+ static void
+ ixgb_setup_eeprom(struct ixgb_hw *hw)
+ {
+- uint32_t eecd_reg;
++ u32 eecd_reg;
+
+ eecd_reg = IXGB_READ_REG(hw, EECD);
+
+@@ -201,7 +201,7 @@ ixgb_setup_eeprom(struct ixgb_hw *hw)
+ static void
+ ixgb_standby_eeprom(struct ixgb_hw *hw)
+ {
+- uint32_t eecd_reg;
++ u32 eecd_reg;
+
+ eecd_reg = IXGB_READ_REG(hw, EECD);
+
+@@ -235,7 +235,7 @@ ixgb_standby_eeprom(struct ixgb_hw *hw)
+ static void
+ ixgb_clock_eeprom(struct ixgb_hw *hw)
+ {
+- uint32_t eecd_reg;
++ u32 eecd_reg;
+
+ eecd_reg = IXGB_READ_REG(hw, EECD);
+
+@@ -259,7 +259,7 @@ ixgb_clock_eeprom(struct ixgb_hw *hw)
+ static void
+ ixgb_cleanup_eeprom(struct ixgb_hw *hw)
+ {
+- uint32_t eecd_reg;
++ u32 eecd_reg;
+
+ eecd_reg = IXGB_READ_REG(hw, EECD);
+
+@@ -279,14 +279,14 @@ ixgb_cleanup_eeprom(struct ixgb_hw *hw)
+ * The command is done when the EEPROM's data out pin goes high.
+ *
+ * Returns:
+- * TRUE: EEPROM data pin is high before timeout.
+- * FALSE: Time expired.
++ * true: EEPROM data pin is high before timeout.
++ * false: Time expired.
+ *****************************************************************************/
+-static boolean_t
++static bool
+ ixgb_wait_eeprom_command(struct ixgb_hw *hw)
+ {
+- uint32_t eecd_reg;
+- uint32_t i;
++ u32 eecd_reg;
++ u32 i;
+
+ /* Toggle the CS line. This in effect tells to EEPROM to actually execute
+ * the command in question.
+@@ -301,12 +301,12 @@ ixgb_wait_eeprom_command(struct ixgb_hw *hw)
+ eecd_reg = IXGB_READ_REG(hw, EECD);
+
+ if(eecd_reg & IXGB_EECD_DO)
+- return (TRUE);
++ return (true);
+
+ udelay(50);
+ }
+ ASSERT(0);
+- return (FALSE);
++ return (false);
+ }
+
+ /******************************************************************************
+@@ -319,22 +319,22 @@ ixgb_wait_eeprom_command(struct ixgb_hw *hw)
+ * valid.
+ *
+ * Returns:
+- * TRUE: Checksum is valid
+- * FALSE: Checksum is not valid.
++ * true: Checksum is valid
++ * false: Checksum is not valid.
+ *****************************************************************************/
+-boolean_t
++bool
+ ixgb_validate_eeprom_checksum(struct ixgb_hw *hw)
+ {
+- uint16_t checksum = 0;
+- uint16_t i;
++ u16 checksum = 0;
++ u16 i;
+
+ for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++)
+ checksum += ixgb_read_eeprom(hw, i);
+
+- if(checksum == (uint16_t) EEPROM_SUM)
+- return (TRUE);
++ if(checksum == (u16) EEPROM_SUM)
++ return (true);
+ else
+- return (FALSE);
++ return (false);
+ }
+
+ /******************************************************************************
+@@ -348,13 +348,13 @@ ixgb_validate_eeprom_checksum(struct ixgb_hw *hw)
+ void
+ ixgb_update_eeprom_checksum(struct ixgb_hw *hw)
+ {
+- uint16_t checksum = 0;
+- uint16_t i;
++ u16 checksum = 0;
++ u16 i;
+
+ for(i = 0; i < EEPROM_CHECKSUM_REG; i++)
+ checksum += ixgb_read_eeprom(hw, i);
+
+- checksum = (uint16_t) EEPROM_SUM - checksum;
++ checksum = (u16) EEPROM_SUM - checksum;
+
+ ixgb_write_eeprom(hw, EEPROM_CHECKSUM_REG, checksum);
+ return;
+@@ -372,7 +372,7 @@ ixgb_update_eeprom_checksum(struct ixgb_hw *hw)
+ *
+ *****************************************************************************/
+ void
+-ixgb_write_eeprom(struct ixgb_hw *hw, uint16_t offset, uint16_t data)
++ixgb_write_eeprom(struct ixgb_hw *hw, u16 offset, u16 data)
+ {
+ struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+
+@@ -425,11 +425,11 @@ ixgb_write_eeprom(struct ixgb_hw *hw, uint16_t offset, uint16_t data)
+ * Returns:
+ * The 16-bit value read from the eeprom
+ *****************************************************************************/
+-uint16_t
++u16
+ ixgb_read_eeprom(struct ixgb_hw *hw,
+- uint16_t offset)
++ u16 offset)
+ {
+- uint16_t data;
++ u16 data;
+
+ /* Prepare the EEPROM for reading */
+ ixgb_setup_eeprom(hw);
+@@ -457,14 +457,14 @@ ixgb_read_eeprom(struct ixgb_hw *hw,
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Returns:
+- * TRUE: if eeprom read is successful
+- * FALSE: otherwise.
++ * true: if eeprom read is successful
++ * false: otherwise.
+ *****************************************************************************/
+-boolean_t
++bool
+ ixgb_get_eeprom_data(struct ixgb_hw *hw)
+ {
+- uint16_t i;
+- uint16_t checksum = 0;
++ u16 i;
++ u16 checksum = 0;
+ struct ixgb_ee_map_type *ee_map;
+
+ DEBUGFUNC("ixgb_get_eeprom_data");
+@@ -473,27 +473,27 @@ ixgb_get_eeprom_data(struct ixgb_hw *hw)
+
+ DEBUGOUT("ixgb_ee: Reading eeprom data\n");
+ for(i = 0; i < IXGB_EEPROM_SIZE ; i++) {
+- uint16_t ee_data;
++ u16 ee_data;
+ ee_data = ixgb_read_eeprom(hw, i);
+ checksum += ee_data;
+ hw->eeprom[i] = cpu_to_le16(ee_data);
+ }
+
+- if (checksum != (uint16_t) EEPROM_SUM) {
++ if (checksum != (u16) EEPROM_SUM) {
+ DEBUGOUT("ixgb_ee: Checksum invalid.\n");
+ /* clear the init_ctrl_reg_1 to signify that the cache is
+ * invalidated */
+ ee_map->init_ctrl_reg_1 = cpu_to_le16(EEPROM_ICW1_SIGNATURE_CLEAR);
+- return (FALSE);
++ return (false);
+ }
+
+ if ((ee_map->init_ctrl_reg_1 & cpu_to_le16(EEPROM_ICW1_SIGNATURE_MASK))
+ != cpu_to_le16(EEPROM_ICW1_SIGNATURE_VALID)) {
+ DEBUGOUT("ixgb_ee: Signature invalid.\n");
+- return(FALSE);
++ return(false);
+ }
+
+- return(TRUE);
++ return(true);
+ }
+
+ /******************************************************************************
+@@ -503,17 +503,17 @@ ixgb_get_eeprom_data(struct ixgb_hw *hw)
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Returns:
+- * TRUE: eeprom signature was good and the eeprom read was successful
+- * FALSE: otherwise.
++ * true: eeprom signature was good and the eeprom read was successful
++ * false: otherwise.
+ ******************************************************************************/
+-static boolean_t
++static bool
+ ixgb_check_and_get_eeprom_data (struct ixgb_hw* hw)
+ {
+ struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+
+ if ((ee_map->init_ctrl_reg_1 & cpu_to_le16(EEPROM_ICW1_SIGNATURE_MASK))
+ == cpu_to_le16(EEPROM_ICW1_SIGNATURE_VALID)) {
+- return (TRUE);
++ return (true);
+ } else {
+ return ixgb_get_eeprom_data(hw);
+ }
+@@ -529,11 +529,11 @@ ixgb_check_and_get_eeprom_data (struct ixgb_hw* hw)
+ * Word at indexed offset in eeprom, if valid, 0 otherwise.
+ ******************************************************************************/
+ __le16
+-ixgb_get_eeprom_word(struct ixgb_hw *hw, uint16_t index)
++ixgb_get_eeprom_word(struct ixgb_hw *hw, u16 index)
+ {
+
+ if ((index < IXGB_EEPROM_SIZE) &&
+- (ixgb_check_and_get_eeprom_data(hw) == TRUE)) {
++ (ixgb_check_and_get_eeprom_data(hw) == true)) {
+ return(hw->eeprom[index]);
+ }
+
+@@ -550,14 +550,14 @@ ixgb_get_eeprom_word(struct ixgb_hw *hw, uint16_t index)
+ ******************************************************************************/
+ void
+ ixgb_get_ee_mac_addr(struct ixgb_hw *hw,
+- uint8_t *mac_addr)
++ u8 *mac_addr)
+ {
+ int i;
+ struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+
+ DEBUGFUNC("ixgb_get_ee_mac_addr");
+
+- if (ixgb_check_and_get_eeprom_data(hw) == TRUE) {
++ if (ixgb_check_and_get_eeprom_data(hw) == true) {
+ for (i = 0; i < IXGB_ETH_LENGTH_OF_ADDRESS; i++) {
+ mac_addr[i] = ee_map->mac_addr[i];
+ DEBUGOUT2("mac(%d) = %.2X\n", i, mac_addr[i]);
+@@ -574,10 +574,10 @@ ixgb_get_ee_mac_addr(struct ixgb_hw *hw,
+ * Returns:
+ * PBA number if EEPROM contents are valid, 0 otherwise
+ ******************************************************************************/
+-uint32_t
++u32
+ ixgb_get_ee_pba_number(struct ixgb_hw *hw)
+ {
+- if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
++ if (ixgb_check_and_get_eeprom_data(hw) == true)
+ return (le16_to_cpu(hw->eeprom[EEPROM_PBA_1_2_REG])
+ | (le16_to_cpu(hw->eeprom[EEPROM_PBA_3_4_REG])<<16));
+
+@@ -593,12 +593,12 @@ ixgb_get_ee_pba_number(struct ixgb_hw *hw)
+ * Returns:
+ * Device Id if EEPROM contents are valid, 0 otherwise
+ ******************************************************************************/
+-uint16_t
++u16
+ ixgb_get_ee_device_id(struct ixgb_hw *hw)
+ {
+ struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+
+- if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
++ if (ixgb_check_and_get_eeprom_data(hw) == true)
+ return (le16_to_cpu(ee_map->device_id));
+
+ return (0);
+diff --git a/drivers/net/ixgb/ixgb_ee.h b/drivers/net/ixgb/ixgb_ee.h
+index 7908bf3..4b7bd0d 100644
+--- a/drivers/net/ixgb/ixgb_ee.h
++++ b/drivers/net/ixgb/ixgb_ee.h
+@@ -75,7 +75,7 @@
+
+ /* EEPROM structure */
+ struct ixgb_ee_map_type {
+- uint8_t mac_addr[IXGB_ETH_LENGTH_OF_ADDRESS];
++ u8 mac_addr[IXGB_ETH_LENGTH_OF_ADDRESS];
+ __le16 compatibility;
+ __le16 reserved1[4];
+ __le32 pba_number;
+@@ -88,19 +88,19 @@ struct ixgb_ee_map_type {
+ __le16 oem_reserved[16];
+ __le16 swdpins_reg;
+ __le16 circuit_ctrl_reg;
+- uint8_t d3_power;
+- uint8_t d0_power;
++ u8 d3_power;
++ u8 d0_power;
+ __le16 reserved2[28];
+ __le16 checksum;
+ };
+
+ /* EEPROM Functions */
+-uint16_t ixgb_read_eeprom(struct ixgb_hw *hw, uint16_t reg);
++u16 ixgb_read_eeprom(struct ixgb_hw *hw, u16 reg);
+
+-boolean_t ixgb_validate_eeprom_checksum(struct ixgb_hw *hw);
++bool ixgb_validate_eeprom_checksum(struct ixgb_hw *hw);
+
+ void ixgb_update_eeprom_checksum(struct ixgb_hw *hw);
+
+-void ixgb_write_eeprom(struct ixgb_hw *hw, uint16_t reg, uint16_t data);
++void ixgb_write_eeprom(struct ixgb_hw *hw, u16 reg, u16 data);
+
+ #endif /* IXGB_EE_H */
+diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
+index 75f3a68..8464d8a 100644
+--- a/drivers/net/ixgb/ixgb_ethtool.c
++++ b/drivers/net/ixgb/ixgb_ethtool.c
+@@ -32,15 +32,6 @@
+
+ #include <asm/uaccess.h>
+
+-extern int ixgb_up(struct ixgb_adapter *adapter);
+-extern void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog);
+-extern void ixgb_reset(struct ixgb_adapter *adapter);
+-extern int ixgb_setup_rx_resources(struct ixgb_adapter *adapter);
+-extern int ixgb_setup_tx_resources(struct ixgb_adapter *adapter);
+-extern void ixgb_free_rx_resources(struct ixgb_adapter *adapter);
+-extern void ixgb_free_tx_resources(struct ixgb_adapter *adapter);
+-extern void ixgb_update_stats(struct ixgb_adapter *adapter);
+-
+ #define IXGB_ALL_RAR_ENTRIES 16
+
+ struct ixgb_stats {
+@@ -136,7 +127,7 @@ ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+ return -EINVAL;
+
+ if(netif_running(adapter->netdev)) {
+- ixgb_down(adapter, TRUE);
++ ixgb_down(adapter, true);
+ ixgb_reset(adapter);
+ ixgb_up(adapter);
+ ixgb_set_speed_duplex(netdev);
+@@ -185,7 +176,7 @@ ixgb_set_pauseparam(struct net_device *netdev,
+ hw->fc.type = ixgb_fc_none;
+
+ if(netif_running(adapter->netdev)) {
+- ixgb_down(adapter, TRUE);
++ ixgb_down(adapter, true);
+ ixgb_up(adapter);
+ ixgb_set_speed_duplex(netdev);
+ } else
+@@ -194,7 +185,7 @@ ixgb_set_pauseparam(struct net_device *netdev,
+ return 0;
+ }
+
+-static uint32_t
++static u32
+ ixgb_get_rx_csum(struct net_device *netdev)
+ {
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+@@ -203,14 +194,14 @@ ixgb_get_rx_csum(struct net_device *netdev)
+ }
+
+ static int
+-ixgb_set_rx_csum(struct net_device *netdev, uint32_t data)
++ixgb_set_rx_csum(struct net_device *netdev, u32 data)
+ {
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+
+ adapter->rx_csum = data;
+
+ if(netif_running(netdev)) {
+- ixgb_down(adapter,TRUE);
++ ixgb_down(adapter, true);
+ ixgb_up(adapter);
+ ixgb_set_speed_duplex(netdev);
+ } else
+@@ -218,14 +209,14 @@ ixgb_set_rx_csum(struct net_device *netdev, uint32_t data)
+ return 0;
+ }
+
+-static uint32_t
++static u32
+ ixgb_get_tx_csum(struct net_device *netdev)
+ {
+ return (netdev->features & NETIF_F_HW_CSUM) != 0;
+ }
+
+ static int
+-ixgb_set_tx_csum(struct net_device *netdev, uint32_t data)
++ixgb_set_tx_csum(struct net_device *netdev, u32 data)
+ {
+ if (data)
+ netdev->features |= NETIF_F_HW_CSUM;
+@@ -236,7 +227,7 @@ ixgb_set_tx_csum(struct net_device *netdev, uint32_t data)
+ }
+
+ static int
+-ixgb_set_tso(struct net_device *netdev, uint32_t data)
++ixgb_set_tso(struct net_device *netdev, u32 data)
+ {
+ if(data)
+ netdev->features |= NETIF_F_TSO;
+@@ -245,7 +236,7 @@ ixgb_set_tso(struct net_device *netdev, uint32_t data)
+ return 0;
+ }
+
+-static uint32_t
++static u32
+ ixgb_get_msglevel(struct net_device *netdev)
+ {
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+@@ -253,7 +244,7 @@ ixgb_get_msglevel(struct net_device *netdev)
+ }
+
+ static void
+-ixgb_set_msglevel(struct net_device *netdev, uint32_t data)
++ixgb_set_msglevel(struct net_device *netdev, u32 data)
+ {
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+ adapter->msg_enable = data;
+@@ -263,7 +254,7 @@ ixgb_set_msglevel(struct net_device *netdev, uint32_t data)
+ static int
+ ixgb_get_regs_len(struct net_device *netdev)
+ {
+-#define IXGB_REG_DUMP_LEN 136*sizeof(uint32_t)
++#define IXGB_REG_DUMP_LEN 136*sizeof(u32)
+ return IXGB_REG_DUMP_LEN;
+ }
+
+@@ -273,9 +264,9 @@ ixgb_get_regs(struct net_device *netdev,
+ {
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+ struct ixgb_hw *hw = &adapter->hw;
+- uint32_t *reg = p;
+- uint32_t *reg_start = reg;
+- uint8_t i;
++ u32 *reg = p;
++ u32 *reg_start = reg;
++ u8 i;
+
+ /* the 1 (one) below indicates an attempt at versioning, if the
+ * interface in ethtool or the driver changes, this 1 should be
+@@ -404,7 +395,7 @@ ixgb_get_regs(struct net_device *netdev,
+ *reg++ = IXGB_GET_STAT(adapter, xofftxc); /* 134 */
+ *reg++ = IXGB_GET_STAT(adapter, rjc); /* 135 */
+
+- regs->len = (reg - reg_start) * sizeof(uint32_t);
++ regs->len = (reg - reg_start) * sizeof(u32);
+ }
+
+ static int
+@@ -416,7 +407,7 @@ ixgb_get_eeprom_len(struct net_device *netdev)
+
+ static int
+ ixgb_get_eeprom(struct net_device *netdev,
+- struct ethtool_eeprom *eeprom, uint8_t *bytes)
++ struct ethtool_eeprom *eeprom, u8 *bytes)
+ {
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+ struct ixgb_hw *hw = &adapter->hw;
+@@ -454,7 +445,7 @@ ixgb_get_eeprom(struct net_device *netdev,
+ eeprom_buff[i] = ixgb_get_eeprom_word(hw, (first_word + i));
+ }
+
+- memcpy(bytes, (uint8_t *)eeprom_buff + (eeprom->offset & 1),
++ memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1),
+ eeprom->len);
+ kfree(eeprom_buff);
+
+@@ -464,14 +455,14 @@ geeprom_error:
+
+ static int
+ ixgb_set_eeprom(struct net_device *netdev,
+- struct ethtool_eeprom *eeprom, uint8_t *bytes)
++ struct ethtool_eeprom *eeprom, u8 *bytes)
+ {
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+ struct ixgb_hw *hw = &adapter->hw;
+- uint16_t *eeprom_buff;
++ u16 *eeprom_buff;
+ void *ptr;
+ int max_len, first_word, last_word;
+- uint16_t i;
++ u16 i;
+
+ if(eeprom->len == 0)
+ return -EINVAL;
+@@ -570,14 +561,14 @@ ixgb_set_ringparam(struct net_device *netdev,
+ return -EINVAL;
+
+ if(netif_running(adapter->netdev))
+- ixgb_down(adapter,TRUE);
++ ixgb_down(adapter, true);
+
+- rxdr->count = max(ring->rx_pending,(uint32_t)MIN_RXD);
+- rxdr->count = min(rxdr->count,(uint32_t)MAX_RXD);
++ rxdr->count = max(ring->rx_pending,(u32)MIN_RXD);
++ rxdr->count = min(rxdr->count,(u32)MAX_RXD);
+ rxdr->count = ALIGN(rxdr->count, IXGB_REQ_RX_DESCRIPTOR_MULTIPLE);
+
+- txdr->count = max(ring->tx_pending,(uint32_t)MIN_TXD);
+- txdr->count = min(txdr->count,(uint32_t)MAX_TXD);
++ txdr->count = max(ring->tx_pending,(u32)MIN_TXD);
++ txdr->count = min(txdr->count,(u32)MAX_TXD);
+ txdr->count = ALIGN(txdr->count, IXGB_REQ_TX_DESCRIPTOR_MULTIPLE);
+
+ if(netif_running(adapter->netdev)) {
+@@ -633,7 +624,7 @@ ixgb_led_blink_callback(unsigned long data)
+ }
+
+ static int
+-ixgb_phys_id(struct net_device *netdev, uint32_t data)
++ixgb_phys_id(struct net_device *netdev, u32 data)
+ {
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+
+@@ -669,7 +660,7 @@ ixgb_get_sset_count(struct net_device *netdev, int sset)
+
+ static void
+ ixgb_get_ethtool_stats(struct net_device *netdev,
+- struct ethtool_stats *stats, uint64_t *data)
++ struct ethtool_stats *stats, u64 *data)
+ {
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+ int i;
+@@ -678,12 +669,12 @@ ixgb_get_ethtool_stats(struct net_device *netdev,
+ for(i = 0; i < IXGB_STATS_LEN; i++) {
+ char *p = (char *)adapter+ixgb_gstrings_stats[i].stat_offset;
+ data[i] = (ixgb_gstrings_stats[i].sizeof_stat ==
+- sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p;
++ sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+ }
+ }
+
+ static void
+-ixgb_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
++ixgb_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
+ {
+ int i;
+
+diff --git a/drivers/net/ixgb/ixgb_hw.c b/drivers/net/ixgb/ixgb_hw.c
+index 80a8b98..04d2003 100644
+--- a/drivers/net/ixgb/ixgb_hw.c
++++ b/drivers/net/ixgb/ixgb_hw.c
+@@ -35,13 +35,13 @@
+
+ /* Local function prototypes */
+
+-static uint32_t ixgb_hash_mc_addr(struct ixgb_hw *hw, uint8_t * mc_addr);
++static u32 ixgb_hash_mc_addr(struct ixgb_hw *hw, u8 * mc_addr);
+
+-static void ixgb_mta_set(struct ixgb_hw *hw, uint32_t hash_value);
++static void ixgb_mta_set(struct ixgb_hw *hw, u32 hash_value);
+
+ static void ixgb_get_bus_info(struct ixgb_hw *hw);
+
+-static boolean_t ixgb_link_reset(struct ixgb_hw *hw);
++static bool ixgb_link_reset(struct ixgb_hw *hw);
+
+ static void ixgb_optics_reset(struct ixgb_hw *hw);
+
+@@ -55,18 +55,18 @@ static void ixgb_clear_vfta(struct ixgb_hw *hw);
+
+ static void ixgb_init_rx_addrs(struct ixgb_hw *hw);
+
+-static uint16_t ixgb_read_phy_reg(struct ixgb_hw *hw,
+- uint32_t reg_address,
+- uint32_t phy_address,
+- uint32_t device_type);
++static u16 ixgb_read_phy_reg(struct ixgb_hw *hw,
++ u32 reg_address,
++ u32 phy_address,
++ u32 device_type);
+
+-static boolean_t ixgb_setup_fc(struct ixgb_hw *hw);
++static bool ixgb_setup_fc(struct ixgb_hw *hw);
+
+-static boolean_t mac_addr_valid(uint8_t *mac_addr);
++static bool mac_addr_valid(u8 *mac_addr);
+
+-static uint32_t ixgb_mac_reset(struct ixgb_hw *hw)
++static u32 ixgb_mac_reset(struct ixgb_hw *hw)
+ {
+- uint32_t ctrl_reg;
++ u32 ctrl_reg;
+
+ ctrl_reg = IXGB_CTRL0_RST |
+ IXGB_CTRL0_SDP3_DIR | /* All pins are Output=1 */
+@@ -114,11 +114,11 @@ static uint32_t ixgb_mac_reset(struct ixgb_hw *hw)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-boolean_t
++bool
+ ixgb_adapter_stop(struct ixgb_hw *hw)
+ {
+- uint32_t ctrl_reg;
+- uint32_t icr_reg;
++ u32 ctrl_reg;
++ u32 icr_reg;
+
+ DEBUGFUNC("ixgb_adapter_stop");
+
+@@ -127,13 +127,13 @@ ixgb_adapter_stop(struct ixgb_hw *hw)
+ */
+ if(hw->adapter_stopped) {
+ DEBUGOUT("Exiting because the adapter is already stopped!!!\n");
+- return FALSE;
++ return false;
+ }
+
+ /* Set the Adapter Stopped flag so other driver functions stop
+ * touching the Hardware.
+ */
+- hw->adapter_stopped = TRUE;
++ hw->adapter_stopped = true;
+
+ /* Clear interrupt mask to stop board from generating interrupts */
+ DEBUGOUT("Masking off all interrupts\n");
+@@ -179,8 +179,8 @@ ixgb_adapter_stop(struct ixgb_hw *hw)
+ static ixgb_xpak_vendor
+ ixgb_identify_xpak_vendor(struct ixgb_hw *hw)
+ {
+- uint32_t i;
+- uint16_t vendor_name[5];
++ u32 i;
++ u16 vendor_name[5];
+ ixgb_xpak_vendor xpak_vendor;
+
+ DEBUGFUNC("ixgb_identify_xpak_vendor");
+@@ -286,15 +286,15 @@ ixgb_identify_phy(struct ixgb_hw *hw)
+ * Leaves the transmit and receive units disabled and uninitialized.
+ *
+ * Returns:
+- * TRUE if successful,
+- * FALSE if unrecoverable problems were encountered.
++ * true if successful,
++ * false if unrecoverable problems were encountered.
+ *****************************************************************************/
+-boolean_t
++bool
+ ixgb_init_hw(struct ixgb_hw *hw)
+ {
+- uint32_t i;
+- uint32_t ctrl_reg;
+- boolean_t status;
++ u32 i;
++ u32 ctrl_reg;
++ bool status;
+
+ DEBUGFUNC("ixgb_init_hw");
+
+@@ -318,9 +318,8 @@ ixgb_init_hw(struct ixgb_hw *hw)
+ /* Delay a few ms just to allow the reset to complete */
+ msleep(IXGB_DELAY_AFTER_EE_RESET);
+
+- if (ixgb_get_eeprom_data(hw) == FALSE) {
+- return(FALSE);
+- }
++ if (!ixgb_get_eeprom_data(hw))
++ return false;
+
+ /* Use the device id to determine the type of phy/transceiver. */
+ hw->device_id = ixgb_get_ee_device_id(hw);
+@@ -337,11 +336,11 @@ ixgb_init_hw(struct ixgb_hw *hw)
+ */
+ if (!mac_addr_valid(hw->curr_mac_addr)) {
+ DEBUGOUT("MAC address invalid after ixgb_init_rx_addrs\n");
+- return(FALSE);
++ return(false);
+ }
+
+ /* tell the routines in this file they can access hardware again */
+- hw->adapter_stopped = FALSE;
++ hw->adapter_stopped = false;
+
+ /* Fill in the bus_info structure */
+ ixgb_get_bus_info(hw);
+@@ -378,7 +377,7 @@ ixgb_init_hw(struct ixgb_hw *hw)
+ static void
+ ixgb_init_rx_addrs(struct ixgb_hw *hw)
+ {
+- uint32_t i;
++ u32 i;
+
+ DEBUGFUNC("ixgb_init_rx_addrs");
+
+@@ -438,13 +437,13 @@ ixgb_init_rx_addrs(struct ixgb_hw *hw)
+ *****************************************************************************/
+ void
+ ixgb_mc_addr_list_update(struct ixgb_hw *hw,
+- uint8_t *mc_addr_list,
+- uint32_t mc_addr_count,
+- uint32_t pad)
++ u8 *mc_addr_list,
++ u32 mc_addr_count,
++ u32 pad)
+ {
+- uint32_t hash_value;
+- uint32_t i;
+- uint32_t rar_used_count = 1; /* RAR[0] is used for our MAC address */
++ u32 hash_value;
++ u32 i;
++ u32 rar_used_count = 1; /* RAR[0] is used for our MAC address */
+
+ DEBUGFUNC("ixgb_mc_addr_list_update");
+
+@@ -516,11 +515,11 @@ ixgb_mc_addr_list_update(struct ixgb_hw *hw,
+ * Returns:
+ * The hash value
+ *****************************************************************************/
+-static uint32_t
++static u32
+ ixgb_hash_mc_addr(struct ixgb_hw *hw,
+- uint8_t *mc_addr)
++ u8 *mc_addr)
+ {
+- uint32_t hash_value = 0;
++ u32 hash_value = 0;
+
+ DEBUGFUNC("ixgb_hash_mc_addr");
+
+@@ -534,18 +533,18 @@ ixgb_hash_mc_addr(struct ixgb_hw *hw,
+ case 0:
+ /* [47:36] i.e. 0x563 for above example address */
+ hash_value =
+- ((mc_addr[4] >> 4) | (((uint16_t) mc_addr[5]) << 4));
++ ((mc_addr[4] >> 4) | (((u16) mc_addr[5]) << 4));
+ break;
+ case 1: /* [46:35] i.e. 0xAC6 for above example address */
+ hash_value =
+- ((mc_addr[4] >> 3) | (((uint16_t) mc_addr[5]) << 5));
++ ((mc_addr[4] >> 3) | (((u16) mc_addr[5]) << 5));
+ break;
+ case 2: /* [45:34] i.e. 0x5D8 for above example address */
+ hash_value =
+- ((mc_addr[4] >> 2) | (((uint16_t) mc_addr[5]) << 6));
++ ((mc_addr[4] >> 2) | (((u16) mc_addr[5]) << 6));
+ break;
+ case 3: /* [43:32] i.e. 0x634 for above example address */
+- hash_value = ((mc_addr[4]) | (((uint16_t) mc_addr[5]) << 8));
++ hash_value = ((mc_addr[4]) | (((u16) mc_addr[5]) << 8));
+ break;
+ default:
+ /* Invalid mc_filter_type, what should we do? */
+@@ -566,10 +565,10 @@ ixgb_hash_mc_addr(struct ixgb_hw *hw,
+ *****************************************************************************/
+ static void
+ ixgb_mta_set(struct ixgb_hw *hw,
+- uint32_t hash_value)
++ u32 hash_value)
+ {
+- uint32_t hash_bit, hash_reg;
+- uint32_t mta_reg;
++ u32 hash_bit, hash_reg;
++ u32 mta_reg;
+
+ /* The MTA is a register array of 128 32-bit registers.
+ * It is treated like an array of 4096 bits. We want to set
+@@ -600,23 +599,23 @@ ixgb_mta_set(struct ixgb_hw *hw,
+ *****************************************************************************/
+ void
+ ixgb_rar_set(struct ixgb_hw *hw,
+- uint8_t *addr,
+- uint32_t index)
++ u8 *addr,
++ u32 index)
+ {
+- uint32_t rar_low, rar_high;
++ u32 rar_low, rar_high;
+
+ DEBUGFUNC("ixgb_rar_set");
+
+ /* HW expects these in little endian so we reverse the byte order
+ * from network order (big endian) to little endian
+ */
+- rar_low = ((uint32_t) addr[0] |
+- ((uint32_t)addr[1] << 8) |
+- ((uint32_t)addr[2] << 16) |
+- ((uint32_t)addr[3] << 24));
++ rar_low = ((u32) addr[0] |
++ ((u32)addr[1] << 8) |
++ ((u32)addr[2] << 16) |
++ ((u32)addr[3] << 24));
+
+- rar_high = ((uint32_t) addr[4] |
+- ((uint32_t)addr[5] << 8) |
++ rar_high = ((u32) addr[4] |
++ ((u32)addr[5] << 8) |
+ IXGB_RAH_AV);
+
+ IXGB_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low);
+@@ -633,8 +632,8 @@ ixgb_rar_set(struct ixgb_hw *hw,
+ *****************************************************************************/
+ void
+ ixgb_write_vfta(struct ixgb_hw *hw,
+- uint32_t offset,
+- uint32_t value)
++ u32 offset,
++ u32 value)
+ {
+ IXGB_WRITE_REG_ARRAY(hw, VFTA, offset, value);
+ return;
+@@ -648,7 +647,7 @@ ixgb_write_vfta(struct ixgb_hw *hw,
+ static void
+ ixgb_clear_vfta(struct ixgb_hw *hw)
+ {
+- uint32_t offset;
++ u32 offset;
+
+ for(offset = 0; offset < IXGB_VLAN_FILTER_TBL_SIZE; offset++)
+ IXGB_WRITE_REG_ARRAY(hw, VFTA, offset, 0);
+@@ -661,12 +660,12 @@ ixgb_clear_vfta(struct ixgb_hw *hw)
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+
+-static boolean_t
++static bool
+ ixgb_setup_fc(struct ixgb_hw *hw)
+ {
+- uint32_t ctrl_reg;
+- uint32_t pap_reg = 0; /* by default, assume no pause time */
+- boolean_t status = TRUE;
++ u32 ctrl_reg;
++ u32 pap_reg = 0; /* by default, assume no pause time */
++ bool status = true;
+
+ DEBUGFUNC("ixgb_setup_fc");
+
+@@ -763,15 +762,15 @@ ixgb_setup_fc(struct ixgb_hw *hw)
+ * This requires that first an address cycle command is sent, followed by a
+ * read command.
+ *****************************************************************************/
+-static uint16_t
++static u16
+ ixgb_read_phy_reg(struct ixgb_hw *hw,
+- uint32_t reg_address,
+- uint32_t phy_address,
+- uint32_t device_type)
++ u32 reg_address,
++ u32 phy_address,
++ u32 device_type)
+ {
+- uint32_t i;
+- uint32_t data;
+- uint32_t command = 0;
++ u32 i;
++ u32 data;
++ u32 command = 0;
+
+ ASSERT(reg_address <= IXGB_MAX_PHY_REG_ADDRESS);
+ ASSERT(phy_address <= IXGB_MAX_PHY_ADDRESS);
+@@ -836,7 +835,7 @@ ixgb_read_phy_reg(struct ixgb_hw *hw,
+ */
+ data = IXGB_READ_REG(hw, MSRWD);
+ data >>= IXGB_MSRWD_READ_DATA_SHIFT;
+- return((uint16_t) data);
++ return((u16) data);
+ }
+
+ /******************************************************************************
+@@ -858,20 +857,20 @@ ixgb_read_phy_reg(struct ixgb_hw *hw,
+ *****************************************************************************/
+ static void
+ ixgb_write_phy_reg(struct ixgb_hw *hw,
+- uint32_t reg_address,
+- uint32_t phy_address,
+- uint32_t device_type,
+- uint16_t data)
++ u32 reg_address,
++ u32 phy_address,
++ u32 device_type,
++ u16 data)
+ {
+- uint32_t i;
+- uint32_t command = 0;
++ u32 i;
++ u32 command = 0;
+
+ ASSERT(reg_address <= IXGB_MAX_PHY_REG_ADDRESS);
+ ASSERT(phy_address <= IXGB_MAX_PHY_ADDRESS);
+ ASSERT(device_type <= IXGB_MAX_PHY_DEV_TYPE);
+
+ /* Put the data in the MDIO Read/Write Data register */
+- IXGB_WRITE_REG(hw, MSRWD, (uint32_t)data);
++ IXGB_WRITE_REG(hw, MSRWD, (u32)data);
+
+ /* Setup and write the address cycle command */
+ command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT) |
+@@ -940,8 +939,8 @@ ixgb_write_phy_reg(struct ixgb_hw *hw,
+ void
+ ixgb_check_for_link(struct ixgb_hw *hw)
+ {
+- uint32_t status_reg;
+- uint32_t xpcss_reg;
++ u32 status_reg;
++ u32 xpcss_reg;
+
+ DEBUGFUNC("ixgb_check_for_link");
+
+@@ -950,7 +949,7 @@ ixgb_check_for_link(struct ixgb_hw *hw)
+
+ if ((xpcss_reg & IXGB_XPCSS_ALIGN_STATUS) &&
+ (status_reg & IXGB_STATUS_LU)) {
+- hw->link_up = TRUE;
++ hw->link_up = true;
+ } else if (!(xpcss_reg & IXGB_XPCSS_ALIGN_STATUS) &&
+ (status_reg & IXGB_STATUS_LU)) {
+ DEBUGOUT("XPCSS Not Aligned while Status:LU is set.\n");
+@@ -974,10 +973,10 @@ ixgb_check_for_link(struct ixgb_hw *hw)
+ *
+ * Called by any function that needs to check the link status of the adapter.
+ *****************************************************************************/
+-boolean_t ixgb_check_for_bad_link(struct ixgb_hw *hw)
++bool ixgb_check_for_bad_link(struct ixgb_hw *hw)
+ {
+- uint32_t newLFC, newRFC;
+- boolean_t bad_link_returncode = FALSE;
++ u32 newLFC, newRFC;
++ bool bad_link_returncode = false;
+
+ if (hw->phy_type == ixgb_phy_type_txn17401) {
+ newLFC = IXGB_READ_REG(hw, LFC);
+@@ -986,7 +985,7 @@ boolean_t ixgb_check_for_bad_link(struct ixgb_hw *hw)
+ || (hw->lastRFC + 250 < newRFC)) {
+ DEBUGOUT
+ ("BAD LINK! too many LFC/RFC since last check\n");
+- bad_link_returncode = TRUE;
++ bad_link_returncode = true;
+ }
+ hw->lastLFC = newLFC;
+ hw->lastRFC = newRFC;
+@@ -1003,7 +1002,7 @@ boolean_t ixgb_check_for_bad_link(struct ixgb_hw *hw)
+ static void
+ ixgb_clear_hw_cntrs(struct ixgb_hw *hw)
+ {
+- volatile uint32_t temp_reg;
++ volatile u32 temp_reg;
+
+ DEBUGFUNC("ixgb_clear_hw_cntrs");
+
+@@ -1084,7 +1083,7 @@ ixgb_clear_hw_cntrs(struct ixgb_hw *hw)
+ void
+ ixgb_led_on(struct ixgb_hw *hw)
+ {
+- uint32_t ctrl0_reg = IXGB_READ_REG(hw, CTRL0);
++ u32 ctrl0_reg = IXGB_READ_REG(hw, CTRL0);
+
+ /* To turn on the LED, clear software-definable pin 0 (SDP0). */
+ ctrl0_reg &= ~IXGB_CTRL0_SDP0;
+@@ -1100,7 +1099,7 @@ ixgb_led_on(struct ixgb_hw *hw)
+ void
+ ixgb_led_off(struct ixgb_hw *hw)
+ {
+- uint32_t ctrl0_reg = IXGB_READ_REG(hw, CTRL0);
++ u32 ctrl0_reg = IXGB_READ_REG(hw, CTRL0);
+
+ /* To turn off the LED, set software-definable pin 0 (SDP0). */
+ ctrl0_reg |= IXGB_CTRL0_SDP0;
+@@ -1116,7 +1115,7 @@ ixgb_led_off(struct ixgb_hw *hw)
+ static void
+ ixgb_get_bus_info(struct ixgb_hw *hw)
+ {
+- uint32_t status_reg;
++ u32 status_reg;
+
+ status_reg = IXGB_READ_REG(hw, STATUS);
+
+@@ -1155,21 +1154,21 @@ ixgb_get_bus_info(struct ixgb_hw *hw)
+ * mac_addr - pointer to MAC address.
+ *
+ *****************************************************************************/
+-static boolean_t
+-mac_addr_valid(uint8_t *mac_addr)
++static bool
++mac_addr_valid(u8 *mac_addr)
+ {
+- boolean_t is_valid = TRUE;
++ bool is_valid = true;
+ DEBUGFUNC("mac_addr_valid");
+
+ /* Make sure it is not a multicast address */
+ if (IS_MULTICAST(mac_addr)) {
+ DEBUGOUT("MAC address is multicast\n");
+- is_valid = FALSE;
++ is_valid = false;
+ }
+ /* Not a broadcast address */
+ else if (IS_BROADCAST(mac_addr)) {
+ DEBUGOUT("MAC address is broadcast\n");
+- is_valid = FALSE;
++ is_valid = false;
+ }
+ /* Reject the zero address */
+ else if (mac_addr[0] == 0 &&
+@@ -1179,7 +1178,7 @@ mac_addr_valid(uint8_t *mac_addr)
+ mac_addr[4] == 0 &&
+ mac_addr[5] == 0) {
+ DEBUGOUT("MAC address is all zeros\n");
+- is_valid = FALSE;
++ is_valid = false;
+ }
+ return (is_valid);
+ }
+@@ -1190,12 +1189,12 @@ mac_addr_valid(uint8_t *mac_addr)
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+-static boolean_t
++static bool
+ ixgb_link_reset(struct ixgb_hw *hw)
+ {
+- boolean_t link_status = FALSE;
+- uint8_t wait_retries = MAX_RESET_ITERATIONS;
+- uint8_t lrst_retries = MAX_RESET_ITERATIONS;
++ bool link_status = false;
++ u8 wait_retries = MAX_RESET_ITERATIONS;
++ u8 lrst_retries = MAX_RESET_ITERATIONS;
+
+ do {
+ /* Reset the link */
+@@ -1208,7 +1207,7 @@ ixgb_link_reset(struct ixgb_hw *hw)
+ link_status =
+ ((IXGB_READ_REG(hw, STATUS) & IXGB_STATUS_LU)
+ && (IXGB_READ_REG(hw, XPCSS) &
+- IXGB_XPCSS_ALIGN_STATUS)) ? TRUE : FALSE;
++ IXGB_XPCSS_ALIGN_STATUS)) ? true : false;
+ } while (!link_status && --wait_retries);
+
+ } while (!link_status && --lrst_retries);
+@@ -1225,7 +1224,7 @@ static void
+ ixgb_optics_reset(struct ixgb_hw *hw)
+ {
+ if (hw->phy_type == ixgb_phy_type_txn17401) {
+- uint16_t mdio_reg;
++ u16 mdio_reg;
+
+ ixgb_write_phy_reg(hw,
+ MDIO_PMA_PMD_CR1,
+diff --git a/drivers/net/ixgb/ixgb_hw.h b/drivers/net/ixgb/ixgb_hw.h
+index 4f176ff..39cfa47 100644
+--- a/drivers/net/ixgb/ixgb_hw.h
++++ b/drivers/net/ixgb/ixgb_hw.h
+@@ -538,8 +538,8 @@ struct ixgb_rx_desc {
+ __le64 buff_addr;
+ __le16 length;
+ __le16 reserved;
+- uint8_t status;
+- uint8_t errors;
++ u8 status;
++ u8 errors;
+ __le16 special;
+ };
+
+@@ -570,8 +570,8 @@ struct ixgb_rx_desc {
+ struct ixgb_tx_desc {
+ __le64 buff_addr;
+ __le32 cmd_type_len;
+- uint8_t status;
+- uint8_t popts;
++ u8 status;
++ u8 popts;
+ __le16 vlan;
+ };
+
+@@ -595,15 +595,15 @@ struct ixgb_tx_desc {
+ #define IXGB_TX_DESC_SPECIAL_PRI_SHIFT IXGB_RX_DESC_SPECIAL_PRI_SHIFT /* Priority is in upper 3 of 16 */
+
+ struct ixgb_context_desc {
+- uint8_t ipcss;
+- uint8_t ipcso;
++ u8 ipcss;
++ u8 ipcso;
+ __le16 ipcse;
+- uint8_t tucss;
+- uint8_t tucso;
++ u8 tucss;
++ u8 tucso;
+ __le16 tucse;
+ __le32 cmd_type_len;
+- uint8_t status;
+- uint8_t hdr_len;
++ u8 status;
++ u8 hdr_len;
+ __le16 mss;
+ };
+
+@@ -637,33 +637,33 @@ struct ixgb_context_desc {
+
+ /* This structure takes a 64k flash and maps it for identification commands */
+ struct ixgb_flash_buffer {
+- uint8_t manufacturer_id;
+- uint8_t device_id;
+- uint8_t filler1[0x2AA8];
+- uint8_t cmd2;
+- uint8_t filler2[0x2AAA];
+- uint8_t cmd1;
+- uint8_t filler3[0xAAAA];
++ u8 manufacturer_id;
++ u8 device_id;
++ u8 filler1[0x2AA8];
++ u8 cmd2;
++ u8 filler2[0x2AAA];
++ u8 cmd1;
++ u8 filler3[0xAAAA];
+ };
+
+ /*
+ * This is a little-endian specific check.
+ */
+ #define IS_MULTICAST(Address) \
+- (boolean_t)(((uint8_t *)(Address))[0] & ((uint8_t)0x01))
++ (bool)(((u8 *)(Address))[0] & ((u8)0x01))
+
+ /*
+ * Check whether an address is broadcast.
+ */
+ #define IS_BROADCAST(Address) \
+- ((((uint8_t *)(Address))[0] == ((uint8_t)0xff)) && (((uint8_t *)(Address))[1] == ((uint8_t)0xff)))
++ ((((u8 *)(Address))[0] == ((u8)0xff)) && (((u8 *)(Address))[1] == ((u8)0xff)))
+
+ /* Flow control parameters */
+ struct ixgb_fc {
+- uint32_t high_water; /* Flow Control High-water */
+- uint32_t low_water; /* Flow Control Low-water */
+- uint16_t pause_time; /* Flow Control Pause timer */
+- boolean_t send_xon; /* Flow control send XON */
++ u32 high_water; /* Flow Control High-water */
++ u32 low_water; /* Flow Control Low-water */
++ u16 pause_time; /* Flow Control Pause timer */
++ bool send_xon; /* Flow control send XON */
+ ixgb_fc_type type; /* Type of flow control */
+ };
+
+@@ -685,139 +685,139 @@ struct ixgb_bus {
+ };
+
+ struct ixgb_hw {
+- uint8_t __iomem *hw_addr;/* Base Address of the hardware */
++ u8 __iomem *hw_addr;/* Base Address of the hardware */
+ void *back; /* Pointer to OS-dependent struct */
+ struct ixgb_fc fc; /* Flow control parameters */
+ struct ixgb_bus bus; /* Bus parameters */
+- uint32_t phy_id; /* Phy Identifier */
+- uint32_t phy_addr; /* XGMII address of Phy */
++ u32 phy_id; /* Phy Identifier */
++ u32 phy_addr; /* XGMII address of Phy */
+ ixgb_mac_type mac_type; /* Identifier for MAC controller */
+ ixgb_phy_type phy_type; /* Transceiver/phy identifier */
+- uint32_t max_frame_size; /* Maximum frame size supported */
+- uint32_t mc_filter_type; /* Multicast filter hash type */
+- uint32_t num_mc_addrs; /* Number of current Multicast addrs */
+- uint8_t curr_mac_addr[IXGB_ETH_LENGTH_OF_ADDRESS]; /* Individual address currently programmed in MAC */
+- uint32_t num_tx_desc; /* Number of Transmit descriptors */
+- uint32_t num_rx_desc; /* Number of Receive descriptors */
+- uint32_t rx_buffer_size; /* Size of Receive buffer */
+- boolean_t link_up; /* TRUE if link is valid */
+- boolean_t adapter_stopped; /* State of adapter */
+- uint16_t device_id; /* device id from PCI configuration space */
+- uint16_t vendor_id; /* vendor id from PCI configuration space */
+- uint8_t revision_id; /* revision id from PCI configuration space */
+- uint16_t subsystem_vendor_id; /* subsystem vendor id from PCI configuration space */
+- uint16_t subsystem_id; /* subsystem id from PCI configuration space */
+- uint32_t bar0; /* Base Address registers */
+- uint32_t bar1;
+- uint32_t bar2;
+- uint32_t bar3;
+- uint16_t pci_cmd_word; /* PCI command register id from PCI configuration space */
++ u32 max_frame_size; /* Maximum frame size supported */
++ u32 mc_filter_type; /* Multicast filter hash type */
++ u32 num_mc_addrs; /* Number of current Multicast addrs */
++ u8 curr_mac_addr[IXGB_ETH_LENGTH_OF_ADDRESS]; /* Individual address currently programmed in MAC */
++ u32 num_tx_desc; /* Number of Transmit descriptors */
++ u32 num_rx_desc; /* Number of Receive descriptors */
++ u32 rx_buffer_size; /* Size of Receive buffer */
++ bool link_up; /* true if link is valid */
++ bool adapter_stopped; /* State of adapter */
++ u16 device_id; /* device id from PCI configuration space */
++ u16 vendor_id; /* vendor id from PCI configuration space */
++ u8 revision_id; /* revision id from PCI configuration space */
++ u16 subsystem_vendor_id; /* subsystem vendor id from PCI configuration space */
++ u16 subsystem_id; /* subsystem id from PCI configuration space */
++ u32 bar0; /* Base Address registers */
++ u32 bar1;
++ u32 bar2;
++ u32 bar3;
++ u16 pci_cmd_word; /* PCI command register id from PCI configuration space */
+ __le16 eeprom[IXGB_EEPROM_SIZE]; /* EEPROM contents read at init time */
+ unsigned long io_base; /* Our I/O mapped location */
+- uint32_t lastLFC;
+- uint32_t lastRFC;
++ u32 lastLFC;
++ u32 lastRFC;
+ };
+
+ /* Statistics reported by the hardware */
+ struct ixgb_hw_stats {
+- uint64_t tprl;
+- uint64_t tprh;
+- uint64_t gprcl;
+- uint64_t gprch;
+- uint64_t bprcl;
+- uint64_t bprch;
+- uint64_t mprcl;
+- uint64_t mprch;
+- uint64_t uprcl;
+- uint64_t uprch;
+- uint64_t vprcl;
+- uint64_t vprch;
+- uint64_t jprcl;
+- uint64_t jprch;
+- uint64_t gorcl;
+- uint64_t gorch;
+- uint64_t torl;
+- uint64_t torh;
+- uint64_t rnbc;
+- uint64_t ruc;
+- uint64_t roc;
+- uint64_t rlec;
+- uint64_t crcerrs;
+- uint64_t icbc;
+- uint64_t ecbc;
+- uint64_t mpc;
+- uint64_t tptl;
+- uint64_t tpth;
+- uint64_t gptcl;
+- uint64_t gptch;
+- uint64_t bptcl;
+- uint64_t bptch;
+- uint64_t mptcl;
+- uint64_t mptch;
+- uint64_t uptcl;
+- uint64_t uptch;
+- uint64_t vptcl;
+- uint64_t vptch;
+- uint64_t jptcl;
+- uint64_t jptch;
+- uint64_t gotcl;
+- uint64_t gotch;
+- uint64_t totl;
+- uint64_t toth;
+- uint64_t dc;
+- uint64_t plt64c;
+- uint64_t tsctc;
+- uint64_t tsctfc;
+- uint64_t ibic;
+- uint64_t rfc;
+- uint64_t lfc;
+- uint64_t pfrc;
+- uint64_t pftc;
+- uint64_t mcfrc;
+- uint64_t mcftc;
+- uint64_t xonrxc;
+- uint64_t xontxc;
+- uint64_t xoffrxc;
+- uint64_t xofftxc;
+- uint64_t rjc;
++ u64 tprl;
++ u64 tprh;
++ u64 gprcl;
++ u64 gprch;
++ u64 bprcl;
++ u64 bprch;
++ u64 mprcl;
++ u64 mprch;
++ u64 uprcl;
++ u64 uprch;
++ u64 vprcl;
++ u64 vprch;
++ u64 jprcl;
++ u64 jprch;
++ u64 gorcl;
++ u64 gorch;
++ u64 torl;
++ u64 torh;
++ u64 rnbc;
++ u64 ruc;
++ u64 roc;
++ u64 rlec;
++ u64 crcerrs;
++ u64 icbc;
++ u64 ecbc;
++ u64 mpc;
++ u64 tptl;
++ u64 tpth;
++ u64 gptcl;
++ u64 gptch;
++ u64 bptcl;
++ u64 bptch;
++ u64 mptcl;
++ u64 mptch;
++ u64 uptcl;
++ u64 uptch;
++ u64 vptcl;
++ u64 vptch;
++ u64 jptcl;
++ u64 jptch;
++ u64 gotcl;
++ u64 gotch;
++ u64 totl;
++ u64 toth;
++ u64 dc;
++ u64 plt64c;
++ u64 tsctc;
++ u64 tsctfc;
++ u64 ibic;
++ u64 rfc;
++ u64 lfc;
++ u64 pfrc;
++ u64 pftc;
++ u64 mcfrc;
++ u64 mcftc;
++ u64 xonrxc;
++ u64 xontxc;
++ u64 xoffrxc;
++ u64 xofftxc;
++ u64 rjc;
+ };
+
+ /* Function Prototypes */
+-extern boolean_t ixgb_adapter_stop(struct ixgb_hw *hw);
+-extern boolean_t ixgb_init_hw(struct ixgb_hw *hw);
+-extern boolean_t ixgb_adapter_start(struct ixgb_hw *hw);
++extern bool ixgb_adapter_stop(struct ixgb_hw *hw);
++extern bool ixgb_init_hw(struct ixgb_hw *hw);
++extern bool ixgb_adapter_start(struct ixgb_hw *hw);
+ extern void ixgb_check_for_link(struct ixgb_hw *hw);
+-extern boolean_t ixgb_check_for_bad_link(struct ixgb_hw *hw);
++extern bool ixgb_check_for_bad_link(struct ixgb_hw *hw);
+
+ extern void ixgb_rar_set(struct ixgb_hw *hw,
+- uint8_t *addr,
+- uint32_t index);
++ u8 *addr,
++ u32 index);
+
+
+ /* Filters (multicast, vlan, receive) */
+ extern void ixgb_mc_addr_list_update(struct ixgb_hw *hw,
+- uint8_t *mc_addr_list,
+- uint32_t mc_addr_count,
+- uint32_t pad);
++ u8 *mc_addr_list,
++ u32 mc_addr_count,
++ u32 pad);
+
+ /* Vfta functions */
+ extern void ixgb_write_vfta(struct ixgb_hw *hw,
+- uint32_t offset,
+- uint32_t value);
++ u32 offset,
++ u32 value);
+
+ /* Access functions to eeprom data */
+-void ixgb_get_ee_mac_addr(struct ixgb_hw *hw, uint8_t *mac_addr);
+-uint32_t ixgb_get_ee_pba_number(struct ixgb_hw *hw);
+-uint16_t ixgb_get_ee_device_id(struct ixgb_hw *hw);
+-boolean_t ixgb_get_eeprom_data(struct ixgb_hw *hw);
+-__le16 ixgb_get_eeprom_word(struct ixgb_hw *hw, uint16_t index);
++void ixgb_get_ee_mac_addr(struct ixgb_hw *hw, u8 *mac_addr);
++u32 ixgb_get_ee_pba_number(struct ixgb_hw *hw);
++u16 ixgb_get_ee_device_id(struct ixgb_hw *hw);
++bool ixgb_get_eeprom_data(struct ixgb_hw *hw);
++__le16 ixgb_get_eeprom_word(struct ixgb_hw *hw, u16 index);
+
+ /* Everything else */
+ void ixgb_led_on(struct ixgb_hw *hw);
+ void ixgb_led_off(struct ixgb_hw *hw);
+ void ixgb_write_pci_cfg(struct ixgb_hw *hw,
+- uint32_t reg,
+- uint16_t * value);
++ u32 reg,
++ u16 * value);
+
+
+ #endif /* _IXGB_HW_H_ */
+diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
+index 6738b4d..cb8dadd 100644
+--- a/drivers/net/ixgb/ixgb_main.c
++++ b/drivers/net/ixgb/ixgb_main.c
+@@ -67,7 +67,7 @@ MODULE_DEVICE_TABLE(pci, ixgb_pci_tbl);
+ /* Local Function Prototypes */
+
+ int ixgb_up(struct ixgb_adapter *adapter);
+-void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog);
++void ixgb_down(struct ixgb_adapter *adapter, bool kill_watchdog);
+ void ixgb_reset(struct ixgb_adapter *adapter);
+ int ixgb_setup_tx_resources(struct ixgb_adapter *adapter);
+ int ixgb_setup_rx_resources(struct ixgb_adapter *adapter);
+@@ -94,22 +94,22 @@ static struct net_device_stats *ixgb_get_stats(struct net_device *netdev);
+ static int ixgb_change_mtu(struct net_device *netdev, int new_mtu);
+ static int ixgb_set_mac(struct net_device *netdev, void *p);
+ static irqreturn_t ixgb_intr(int irq, void *data);
+-static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter);
++static bool ixgb_clean_tx_irq(struct ixgb_adapter *adapter);
+
+ #ifdef CONFIG_IXGB_NAPI
+ static int ixgb_clean(struct napi_struct *napi, int budget);
+-static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter,
+- int *work_done, int work_to_do);
++static bool ixgb_clean_rx_irq(struct ixgb_adapter *adapter,
++ int *work_done, int work_to_do);
+ #else
+-static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter);
++static bool ixgb_clean_rx_irq(struct ixgb_adapter *adapter);
+ #endif
+ static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter);
+ static void ixgb_tx_timeout(struct net_device *dev);
+ static void ixgb_tx_timeout_task(struct work_struct *work);
+ static void ixgb_vlan_rx_register(struct net_device *netdev,
+ struct vlan_group *grp);
+-static void ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
+-static void ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
++static void ixgb_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
++static void ixgb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
+ static void ixgb_restore_vlan(struct ixgb_adapter *adapter);
+
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+@@ -197,7 +197,6 @@ module_exit(ixgb_exit_module);
+ static void
+ ixgb_irq_disable(struct ixgb_adapter *adapter)
+ {
+- atomic_inc(&adapter->irq_sem);
+ IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
+ IXGB_WRITE_FLUSH(&adapter->hw);
+ synchronize_irq(adapter->pdev->irq);
+@@ -211,14 +210,12 @@ ixgb_irq_disable(struct ixgb_adapter *adapter)
+ static void
+ ixgb_irq_enable(struct ixgb_adapter *adapter)
+ {
+- if(atomic_dec_and_test(&adapter->irq_sem)) {
+- u32 val = IXGB_INT_RXT0 | IXGB_INT_RXDMT0 |
+- IXGB_INT_TXDW | IXGB_INT_LSC;
+- if (adapter->hw.subsystem_vendor_id == SUN_SUBVENDOR_ID)
+- val |= IXGB_INT_GPI0;
+- IXGB_WRITE_REG(&adapter->hw, IMS, val);
+- IXGB_WRITE_FLUSH(&adapter->hw);
+- }
++ u32 val = IXGB_INT_RXT0 | IXGB_INT_RXDMT0 |
++ IXGB_INT_TXDW | IXGB_INT_LSC;
++ if (adapter->hw.subsystem_vendor_id == SUN_SUBVENDOR_ID)
++ val |= IXGB_INT_GPI0;
++ IXGB_WRITE_REG(&adapter->hw, IMS, val);
++ IXGB_WRITE_FLUSH(&adapter->hw);
+ }
+
+ int
+@@ -274,7 +271,7 @@ ixgb_up(struct ixgb_adapter *adapter)
+
+ if(hw->max_frame_size >
+ IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH) {
+- uint32_t ctrl0 = IXGB_READ_REG(hw, CTRL0);
++ u32 ctrl0 = IXGB_READ_REG(hw, CTRL0);
+
+ if(!(ctrl0 & IXGB_CTRL0_JFE)) {
+ ctrl0 |= IXGB_CTRL0_JFE;
+@@ -283,26 +280,30 @@ ixgb_up(struct ixgb_adapter *adapter)
+ }
+ }
+
+- mod_timer(&adapter->watchdog_timer, jiffies);
++ clear_bit(__IXGB_DOWN, &adapter->flags);
+
+ #ifdef CONFIG_IXGB_NAPI
+ napi_enable(&adapter->napi);
+ #endif
+ ixgb_irq_enable(adapter);
+
++ mod_timer(&adapter->watchdog_timer, jiffies);
++
+ return 0;
+ }
+
+ void
+-ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)
++ixgb_down(struct ixgb_adapter *adapter, bool kill_watchdog)
+ {
+ struct net_device *netdev = adapter->netdev;
+
++ /* prevent the interrupt handler from restarting watchdog */
++ set_bit(__IXGB_DOWN, &adapter->flags);
++
+ #ifdef CONFIG_IXGB_NAPI
+ napi_disable(&adapter->napi);
+- atomic_set(&adapter->irq_sem, 0);
+ #endif
+-
++ /* waiting for NAPI to complete can re-enable interrupts */
+ ixgb_irq_disable(adapter);
+ free_irq(adapter->pdev->irq, netdev);
+
+@@ -589,9 +590,9 @@ ixgb_sw_init(struct ixgb_adapter *adapter)
+ /* enable flow control to be programmed */
+ hw->fc.send_xon = 1;
+
+- atomic_set(&adapter->irq_sem, 1);
+ spin_lock_init(&adapter->tx_lock);
+
++ set_bit(__IXGB_DOWN, &adapter->flags);
+ return 0;
+ }
+
+@@ -656,7 +657,7 @@ ixgb_close(struct net_device *netdev)
+ {
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+
+- ixgb_down(adapter, TRUE);
++ ixgb_down(adapter, true);
+
+ ixgb_free_tx_resources(adapter);
+ ixgb_free_rx_resources(adapter);
+@@ -717,9 +718,9 @@ ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
+ static void
+ ixgb_configure_tx(struct ixgb_adapter *adapter)
+ {
+- uint64_t tdba = adapter->tx_ring.dma;
+- uint32_t tdlen = adapter->tx_ring.count * sizeof(struct ixgb_tx_desc);
+- uint32_t tctl;
++ u64 tdba = adapter->tx_ring.dma;
++ u32 tdlen = adapter->tx_ring.count * sizeof(struct ixgb_tx_desc);
++ u32 tctl;
+ struct ixgb_hw *hw = &adapter->hw;
+
+ /* Setup the Base and Length of the Tx Descriptor Ring
+@@ -805,7 +806,7 @@ ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
+ static void
+ ixgb_setup_rctl(struct ixgb_adapter *adapter)
+ {
+- uint32_t rctl;
++ u32 rctl;
+
+ rctl = IXGB_READ_REG(&adapter->hw, RCTL);
+
+@@ -840,12 +841,12 @@ ixgb_setup_rctl(struct ixgb_adapter *adapter)
+ static void
+ ixgb_configure_rx(struct ixgb_adapter *adapter)
+ {
+- uint64_t rdba = adapter->rx_ring.dma;
+- uint32_t rdlen = adapter->rx_ring.count * sizeof(struct ixgb_rx_desc);
++ u64 rdba = adapter->rx_ring.dma;
++ u32 rdlen = adapter->rx_ring.count * sizeof(struct ixgb_rx_desc);
+ struct ixgb_hw *hw = &adapter->hw;
+- uint32_t rctl;
+- uint32_t rxcsum;
+- uint32_t rxdctl;
++ u32 rctl;
++ u32 rxcsum;
++ u32 rxdctl;
+
+ /* make sure receives are disabled while setting up the descriptors */
+
+@@ -881,7 +882,7 @@ ixgb_configure_rx(struct ixgb_adapter *adapter)
+ IXGB_WRITE_REG(hw, RXDCTL, rxdctl);
+
+ /* Enable Receive Checksum Offload for TCP and UDP */
+- if(adapter->rx_csum == TRUE) {
++ if (adapter->rx_csum) {
+ rxcsum = IXGB_READ_REG(hw, RXCSUM);
+ rxcsum |= IXGB_RXCSUM_TUOFL;
+ IXGB_WRITE_REG(hw, RXCSUM, rxcsum);
+@@ -1078,7 +1079,7 @@ ixgb_set_multi(struct net_device *netdev)
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+ struct ixgb_hw *hw = &adapter->hw;
+ struct dev_mc_list *mc_ptr;
+- uint32_t rctl;
++ u32 rctl;
+ int i;
+
+ /* Check for Promiscuous and All Multicast modes */
+@@ -1098,7 +1099,7 @@ ixgb_set_multi(struct net_device *netdev)
+ rctl |= IXGB_RCTL_MPE;
+ IXGB_WRITE_REG(hw, RCTL, rctl);
+ } else {
+- uint8_t mta[IXGB_MAX_NUM_MULTICAST_ADDRESSES *
++ u8 mta[IXGB_MAX_NUM_MULTICAST_ADDRESSES *
+ IXGB_ETH_LENGTH_OF_ADDRESS];
+
+ IXGB_WRITE_REG(hw, RCTL, rctl);
+@@ -1164,7 +1165,7 @@ ixgb_watchdog(unsigned long data)
+ }
+
+ /* Force detection of hung controller every watchdog period */
+- adapter->detect_tx_hung = TRUE;
++ adapter->detect_tx_hung = true;
+
+ /* generate an interrupt to force clean up of any stragglers */
+ IXGB_WRITE_REG(&adapter->hw, ICS, IXGB_INT_TXDW);
+@@ -1182,8 +1183,8 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
+ {
+ struct ixgb_context_desc *context_desc;
+ unsigned int i;
+- uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
+- uint16_t ipcse, tucse, mss;
++ u8 ipcss, ipcso, tucss, tucso, hdr_len;
++ u16 ipcse, tucse, mss;
+ int err;
+
+ if (likely(skb_is_gso(skb))) {
+@@ -1243,12 +1244,12 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
+ return 0;
+ }
+
+-static boolean_t
++static bool
+ ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
+ {
+ struct ixgb_context_desc *context_desc;
+ unsigned int i;
+- uint8_t css, cso;
++ u8 css, cso;
+
+ if(likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+ struct ixgb_buffer *buffer_info;
+@@ -1264,7 +1265,7 @@ ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
+ context_desc->tucso = cso;
+ context_desc->tucse = 0;
+ /* zero out any previously existing data in one instruction */
+- *(uint32_t *)&(context_desc->ipcss) = 0;
++ *(u32 *)&(context_desc->ipcss) = 0;
+ context_desc->status = 0;
+ context_desc->hdr_len = 0;
+ context_desc->mss = 0;
+@@ -1275,10 +1276,10 @@ ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
+ if(++i == adapter->tx_ring.count) i = 0;
+ adapter->tx_ring.next_to_use = i;
+
+- return TRUE;
++ return true;
+ }
+
+- return FALSE;
++ return false;
+ }
+
+ #define IXGB_MAX_TXD_PWR 14
+@@ -1371,9 +1372,9 @@ ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,int tx_flags)
+ struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
+ struct ixgb_tx_desc *tx_desc = NULL;
+ struct ixgb_buffer *buffer_info;
+- uint32_t cmd_type_len = adapter->tx_cmd_type;
+- uint8_t status = 0;
+- uint8_t popts = 0;
++ u32 cmd_type_len = adapter->tx_cmd_type;
++ u8 status = 0;
++ u8 popts = 0;
+ unsigned int i;
+
+ if(tx_flags & IXGB_TX_FLAGS_TSO) {
+@@ -1464,14 +1465,18 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ int vlan_id = 0;
+ int tso;
+
++ if (test_bit(__IXGB_DOWN, &adapter->flags)) {
++ dev_kfree_skb(skb);
++ return NETDEV_TX_OK;
++ }
++
+ if(skb->len <= 0) {
+ dev_kfree_skb_any(skb);
+ return 0;
+ }
+
+ #ifdef NETIF_F_LLTX
+- local_irq_save(flags);
+- if (!spin_trylock(&adapter->tx_lock)) {
++ if (!spin_trylock_irqsave(&adapter->tx_lock, flags)) {
+ /* Collision - tell upper layer to requeue */
+ local_irq_restore(flags);
+ return NETDEV_TX_LOCKED;
+@@ -1548,7 +1553,7 @@ ixgb_tx_timeout_task(struct work_struct *work)
+ container_of(work, struct ixgb_adapter, tx_timeout_task);
+
+ adapter->tx_timeout_count++;
+- ixgb_down(adapter, TRUE);
++ ixgb_down(adapter, true);
+ ixgb_up(adapter);
+ }
+
+@@ -1595,7 +1600,7 @@ ixgb_change_mtu(struct net_device *netdev, int new_mtu)
+ netdev->mtu = new_mtu;
+
+ if ((old_max_frame != max_frame) && netif_running(netdev)) {
+- ixgb_down(adapter, TRUE);
++ ixgb_down(adapter, true);
+ ixgb_up(adapter);
+ }
+
+@@ -1745,7 +1750,7 @@ ixgb_intr(int irq, void *data)
+ struct net_device *netdev = data;
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+ struct ixgb_hw *hw = &adapter->hw;
+- uint32_t icr = IXGB_READ_REG(hw, ICR);
++ u32 icr = IXGB_READ_REG(hw, ICR);
+ #ifndef CONFIG_IXGB_NAPI
+ unsigned int i;
+ #endif
+@@ -1753,9 +1758,9 @@ ixgb_intr(int irq, void *data)
+ if(unlikely(!icr))
+ return IRQ_NONE; /* Not our interrupt */
+
+- if(unlikely(icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC))) {
+- mod_timer(&adapter->watchdog_timer, jiffies);
+- }
++ if (unlikely(icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC)))
++ if (!test_bit(__IXGB_DOWN, &adapter->flags))
++ mod_timer(&adapter->watchdog_timer, jiffies);
+
+ #ifdef CONFIG_IXGB_NAPI
+ if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
+@@ -1764,7 +1769,6 @@ ixgb_intr(int irq, void *data)
+ of the posted write is intentionally left out.
+ */
+
+- atomic_inc(&adapter->irq_sem);
+ IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
+ __netif_rx_schedule(netdev, &adapter->napi);
+ }
+@@ -1812,7 +1816,7 @@ ixgb_clean(struct napi_struct *napi, int budget)
+ * @adapter: board private structure
+ **/
+
+-static boolean_t
++static bool
+ ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
+ {
+ struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
+@@ -1820,7 +1824,7 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
+ struct ixgb_tx_desc *tx_desc, *eop_desc;
+ struct ixgb_buffer *buffer_info;
+ unsigned int i, eop;
+- boolean_t cleaned = FALSE;
++ bool cleaned = false;
+
+ i = tx_ring->next_to_clean;
+ eop = tx_ring->buffer_info[i].next_to_watch;
+@@ -1828,7 +1832,7 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
+
+ while(eop_desc->status & IXGB_TX_DESC_STATUS_DD) {
+
+- for(cleaned = FALSE; !cleaned; ) {
++ for (cleaned = false; !cleaned; ) {
+ tx_desc = IXGB_TX_DESC(*tx_ring, i);
+ buffer_info = &tx_ring->buffer_info[i];
+
+@@ -1839,7 +1843,7 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
+
+ ixgb_unmap_and_free_tx_resource(adapter, buffer_info);
+
+- *(uint32_t *)&(tx_desc->status) = 0;
++ *(u32 *)&(tx_desc->status) = 0;
+
+ cleaned = (i == eop);
+ if(++i == tx_ring->count) i = 0;
+@@ -1862,7 +1866,7 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
+ if(adapter->detect_tx_hung) {
+ /* detect a transmit hang in hardware, this serializes the
+ * check with the clearing of time_stamp and movement of i */
+- adapter->detect_tx_hung = FALSE;
++ adapter->detect_tx_hung = false;
+ if (tx_ring->buffer_info[eop].dma &&
+ time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + HZ)
+ && !(IXGB_READ_REG(&adapter->hw, STATUS) &
+@@ -1932,7 +1936,7 @@ ixgb_rx_checksum(struct ixgb_adapter *adapter,
+ * @adapter: board private structure
+ **/
+
+-static boolean_t
++static bool
+ #ifdef CONFIG_IXGB_NAPI
+ ixgb_clean_rx_irq(struct ixgb_adapter *adapter, int *work_done, int work_to_do)
+ #else
+@@ -1944,9 +1948,9 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
+ struct pci_dev *pdev = adapter->pdev;
+ struct ixgb_rx_desc *rx_desc, *next_rxd;
+ struct ixgb_buffer *buffer_info, *next_buffer, *next2_buffer;
+- uint32_t length;
++ u32 length;
+ unsigned int i, j;
+- boolean_t cleaned = FALSE;
++ bool cleaned = false;
+
+ i = rx_ring->next_to_clean;
+ rx_desc = IXGB_RX_DESC(*rx_ring, i);
+@@ -1980,7 +1984,7 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
+ next_skb = next_buffer->skb;
+ prefetch(next_skb);
+
+- cleaned = TRUE;
++ cleaned = true;
+
+ pci_unmap_single(pdev,
+ buffer_info->dma,
+@@ -2162,7 +2166,7 @@ static void
+ ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+ {
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+- uint32_t ctrl, rctl;
++ u32 ctrl, rctl;
+
+ ixgb_irq_disable(adapter);
+ adapter->vlgrp = grp;
+@@ -2193,14 +2197,16 @@ ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+ IXGB_WRITE_REG(&adapter->hw, RCTL, rctl);
+ }
+
+- ixgb_irq_enable(adapter);
++ /* don't enable interrupts unless we are UP */
++ if (adapter->netdev->flags & IFF_UP)
++ ixgb_irq_enable(adapter);
+ }
+
+ static void
+-ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
++ixgb_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
+ {
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+- uint32_t vfta, index;
++ u32 vfta, index;
+
+ /* add VID to filter table */
+
+@@ -2211,18 +2217,20 @@ ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
+ }
+
+ static void
+-ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
++ixgb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
+ {
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+- uint32_t vfta, index;
++ u32 vfta, index;
+
+ ixgb_irq_disable(adapter);
+
+ vlan_group_set_device(adapter->vlgrp, vid, NULL);
+
+- ixgb_irq_enable(adapter);
++ /* don't enable interrupts unless we are UP */
++ if (adapter->netdev->flags & IFF_UP)
++ ixgb_irq_enable(adapter);
+
+- /* remove VID from filter table*/
++ /* remove VID from filter table */
+
+ index = (vid >> 5) & 0x7F;
+ vfta = IXGB_READ_REG_ARRAY(&adapter->hw, VFTA, index);
+@@ -2236,7 +2244,7 @@ ixgb_restore_vlan(struct ixgb_adapter *adapter)
+ ixgb_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+
+ if(adapter->vlgrp) {
+- uint16_t vid;
++ u16 vid;
+ for(vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+ if(!vlan_group_get_device(adapter->vlgrp, vid))
+ continue;
+@@ -2277,7 +2285,7 @@ static pci_ers_result_t ixgb_io_error_detected (struct pci_dev *pdev,
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+
+ if(netif_running(netdev))
+- ixgb_down(adapter, TRUE);
++ ixgb_down(adapter, true);
+
+ pci_disable_device(pdev);
+
+diff --git a/drivers/net/ixgb/ixgb_osdep.h b/drivers/net/ixgb/ixgb_osdep.h
+index 9e04a6b..4be1b27 100644
+--- a/drivers/net/ixgb/ixgb_osdep.h
++++ b/drivers/net/ixgb/ixgb_osdep.h
+@@ -39,13 +39,6 @@
+ #include <linux/interrupt.h>
+ #include <linux/sched.h>
+
+-typedef enum {
+-#undef FALSE
+- FALSE = 0,
+-#undef TRUE
+- TRUE = 1
+-} boolean_t;
+-
+ #undef ASSERT
+ #define ASSERT(x) if(!(x)) BUG()
+ #define MSGOUT(S, A, B) printk(KERN_DEBUG S "\n", A, B)
+diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
+index d0bf206..d981134 100644
+--- a/drivers/net/ixgbe/ixgbe.h
++++ b/drivers/net/ixgbe/ixgbe.h
+@@ -36,6 +36,9 @@
+ #include "ixgbe_type.h"
+ #include "ixgbe_common.h"
+
++#ifdef CONFIG_DCA
++#include <linux/dca.h>
++#endif
+
+ #define IXGBE_ERR(args...) printk(KERN_ERR "ixgbe: " args)
+
+@@ -120,7 +123,6 @@ struct ixgbe_queue_stats {
+ };
+
+ struct ixgbe_ring {
+- struct ixgbe_adapter *adapter; /* backlink */
+ void *desc; /* descriptor ring memory */
+ dma_addr_t dma; /* phys. address of descriptor ring */
+ unsigned int size; /* length in bytes */
+@@ -128,6 +130,7 @@ struct ixgbe_ring {
+ unsigned int next_to_use;
+ unsigned int next_to_clean;
+
++ int queue_index; /* needed for multiqueue queue management */
+ union {
+ struct ixgbe_tx_buffer *tx_buffer_info;
+ struct ixgbe_rx_buffer *rx_buffer_info;
+@@ -136,8 +139,21 @@ struct ixgbe_ring {
+ u16 head;
+ u16 tail;
+
++ unsigned int total_bytes;
++ unsigned int total_packets;
+
++ u16 reg_idx; /* holds the special value that gets the hardware register
++ * offset associated with this ring, which is different
++ * for DCE and RSS modes */
++
++#ifdef CONFIG_DCA
++ /* cpu for tx queue */
++ int cpu;
++#endif
+ struct ixgbe_queue_stats stats;
++ u8 v_idx; /* maps directly to the index for this ring in the hardware
++ * vector array, can also be used for finding the bit in EICR
++ * and friends that represents the vector for this ring */
+
+ u32 eims_value;
+ u16 itr_register;
+@@ -146,6 +162,33 @@ struct ixgbe_ring {
+ u16 work_limit; /* max work per interrupt */
+ };
+
++#define RING_F_VMDQ 1
++#define RING_F_RSS 2
++#define IXGBE_MAX_RSS_INDICES 16
++#define IXGBE_MAX_VMDQ_INDICES 16
++struct ixgbe_ring_feature {
++ int indices;
++ int mask;
++};
++
++#define MAX_RX_QUEUES 64
++#define MAX_TX_QUEUES 32
++
++/* MAX_MSIX_Q_VECTORS of these are allocated,
++ * but we only use one per queue-specific vector.
++ */
++struct ixgbe_q_vector {
++ struct ixgbe_adapter *adapter;
++ struct napi_struct napi;
++ DECLARE_BITMAP(rxr_idx, MAX_RX_QUEUES); /* Rx ring indices */
++ DECLARE_BITMAP(txr_idx, MAX_TX_QUEUES); /* Tx ring indices */
++ u8 rxr_count; /* Rx ring count assigned to this vector */
++ u8 txr_count; /* Tx ring count assigned to this vector */
++ u8 tx_eitr;
++ u8 rx_eitr;
++ u32 eitr;
++};
++
+ /* Helper macros to switch between ints/sec and what the register uses.
+ * And yes, it's the same math going both ways.
+ */
+@@ -166,6 +209,14 @@ struct ixgbe_ring {
+
+ #define IXGBE_MAX_JUMBO_FRAME_SIZE 16128
+
++#define OTHER_VECTOR 1
++#define NON_Q_VECTORS (OTHER_VECTOR)
++
++#define MAX_MSIX_Q_VECTORS 16
++#define MIN_MSIX_Q_VECTORS 2
++#define MAX_MSIX_COUNT (MAX_MSIX_Q_VECTORS + NON_Q_VECTORS)
++#define MIN_MSIX_COUNT (MIN_MSIX_Q_VECTORS + NON_Q_VECTORS)
++
+ /* board specific private data structure */
+ struct ixgbe_adapter {
+ struct timer_list watchdog_timer;
+@@ -173,10 +224,16 @@ struct ixgbe_adapter {
+ u16 bd_number;
+ u16 rx_buf_len;
+ struct work_struct reset_task;
++ struct ixgbe_q_vector q_vector[MAX_MSIX_Q_VECTORS];
++ char name[MAX_MSIX_COUNT][IFNAMSIZ + 5];
++
++ /* Interrupt Throttle Rate */
++ u32 itr_setting;
++ u16 eitr_low;
++ u16 eitr_high;
+
+ /* TX */
+ struct ixgbe_ring *tx_ring; /* One per active queue */
+- struct napi_struct napi;
+ u64 restart_queue;
+ u64 lsc_int;
+ u64 hw_tso_ctxt;
+@@ -192,22 +249,27 @@ struct ixgbe_adapter {
+ u64 non_eop_descs;
+ int num_tx_queues;
+ int num_rx_queues;
++ int num_msix_vectors;
++ struct ixgbe_ring_feature ring_feature[3];
+ struct msix_entry *msix_entries;
+
+ u64 rx_hdr_split;
+ u32 alloc_rx_page_failed;
+ u32 alloc_rx_buff_failed;
+
++ /* Some features need tri-state capability,
++ * thus the additional *_CAPABLE flags.
++ */
+ u32 flags;
+-#define IXGBE_FLAG_RX_CSUM_ENABLED (u32)(1)
++#define IXGBE_FLAG_RX_CSUM_ENABLED (u32)(1 << 0)
+ #define IXGBE_FLAG_MSI_ENABLED (u32)(1 << 1)
+-#define IXGBE_FLAG_MSIX_ENABLED (u32)(1 << 2)
+-#define IXGBE_FLAG_RX_PS_ENABLED (u32)(1 << 3)
+-#define IXGBE_FLAG_IN_NETPOLL (u32)(1 << 4)
+-
+- /* Interrupt Throttle Rate */
+- u32 rx_eitr;
+- u32 tx_eitr;
++#define IXGBE_FLAG_MSIX_ENABLED (u32)(1 << 2)
++#define IXGBE_FLAG_RX_PS_ENABLED (u32)(1 << 3)
++#define IXGBE_FLAG_IN_NETPOLL (u32)(1 << 4)
++#define IXGBE_FLAG_IMIR_ENABLED (u32)(1 << 5)
++#define IXGBE_FLAG_RSS_ENABLED (u32)(1 << 6)
++#define IXGBE_FLAG_VMDQ_ENABLED (u32)(1 << 7)
++#define IXGBE_FLAG_DCA_ENABLED (u32)(1 << 8)
+
+ /* OS defined structs */
+ struct net_device *netdev;
+@@ -218,7 +280,10 @@ struct ixgbe_adapter {
+ struct ixgbe_hw hw;
+ u16 msg_enable;
+ struct ixgbe_hw_stats stats;
+- char lsc_name[IFNAMSIZ + 5];
++
++ /* Interrupt Throttle Rate */
++ u32 rx_eitr;
++ u32 tx_eitr;
+
+ unsigned long state;
+ u64 tx_busy;
+diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
+index a119cbd..4e46377 100644
+--- a/drivers/net/ixgbe/ixgbe_ethtool.c
++++ b/drivers/net/ixgbe/ixgbe_ethtool.c
+@@ -246,13 +246,26 @@ static int ixgbe_set_tx_csum(struct net_device *netdev, u32 data)
+
+ static int ixgbe_set_tso(struct net_device *netdev, u32 data)
+ {
+-
+ if (data) {
+ netdev->features |= NETIF_F_TSO;
+ netdev->features |= NETIF_F_TSO6;
+ } else {
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ struct ixgbe_adapter *adapter = netdev_priv(netdev);
++ int i;
++#endif
++ netif_stop_queue(netdev);
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ for (i = 0; i < adapter->num_tx_queues; i++)
++ netif_stop_subqueue(netdev, i);
++#endif
+ netdev->features &= ~NETIF_F_TSO;
+ netdev->features &= ~NETIF_F_TSO6;
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ for (i = 0; i < adapter->num_tx_queues; i++)
++ netif_start_subqueue(netdev, i);
++#endif
++ netif_start_queue(netdev);
+ }
+ return 0;
+ }
+@@ -873,13 +886,13 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
+ {
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+- if (adapter->rx_eitr == 0)
+- ec->rx_coalesce_usecs = 0;
++ if (adapter->rx_eitr < IXGBE_MIN_ITR_USECS)
++ ec->rx_coalesce_usecs = adapter->rx_eitr;
+ else
+ ec->rx_coalesce_usecs = 1000000 / adapter->rx_eitr;
+
+- if (adapter->tx_eitr == 0)
+- ec->tx_coalesce_usecs = 0;
++ if (adapter->tx_eitr < IXGBE_MIN_ITR_USECS)
++ ec->tx_coalesce_usecs = adapter->tx_eitr;
+ else
+ ec->tx_coalesce_usecs = 1000000 / adapter->tx_eitr;
+
+@@ -893,22 +906,26 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+ if ((ec->rx_coalesce_usecs > IXGBE_MAX_ITR_USECS) ||
+- ((ec->rx_coalesce_usecs > 0) &&
++ ((ec->rx_coalesce_usecs != 0) &&
++ (ec->rx_coalesce_usecs != 1) &&
++ (ec->rx_coalesce_usecs != 3) &&
+ (ec->rx_coalesce_usecs < IXGBE_MIN_ITR_USECS)))
+ return -EINVAL;
+ if ((ec->tx_coalesce_usecs > IXGBE_MAX_ITR_USECS) ||
+- ((ec->tx_coalesce_usecs > 0) &&
++ ((ec->tx_coalesce_usecs != 0) &&
++ (ec->tx_coalesce_usecs != 1) &&
++ (ec->tx_coalesce_usecs != 3) &&
+ (ec->tx_coalesce_usecs < IXGBE_MIN_ITR_USECS)))
+ return -EINVAL;
+
+ /* convert to rate of irq's per second */
+- if (ec->rx_coalesce_usecs == 0)
+- adapter->rx_eitr = 0;
++ if (ec->rx_coalesce_usecs < IXGBE_MIN_ITR_USECS)
++ adapter->rx_eitr = ec->rx_coalesce_usecs;
+ else
+ adapter->rx_eitr = (1000000 / ec->rx_coalesce_usecs);
+
+- if (ec->tx_coalesce_usecs == 0)
+- adapter->tx_eitr = 0;
++ if (ec->tx_coalesce_usecs < IXGBE_MIN_ITR_USECS)
++ adapter->tx_eitr = ec->rx_coalesce_usecs;
+ else
+ adapter->tx_eitr = (1000000 / ec->tx_coalesce_usecs);
+
+diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
+index c2095ce..7b85922 100644
+--- a/drivers/net/ixgbe/ixgbe_main.c
++++ b/drivers/net/ixgbe/ixgbe_main.c
+@@ -48,7 +48,7 @@ char ixgbe_driver_name[] = "ixgbe";
+ static const char ixgbe_driver_string[] =
+ "Intel(R) 10 Gigabit PCI Express Network Driver";
+
+-#define DRV_VERSION "1.1.18"
++#define DRV_VERSION "1.3.18-k2"
+ const char ixgbe_driver_version[] = DRV_VERSION;
+ static const char ixgbe_copyright[] =
+ "Copyright (c) 1999-2007 Intel Corporation.";
+@@ -80,6 +80,16 @@ static struct pci_device_id ixgbe_pci_tbl[] = {
+ };
+ MODULE_DEVICE_TABLE(pci, ixgbe_pci_tbl);
+
++#ifdef CONFIG_DCA
++static int ixgbe_notify_dca(struct notifier_block *, unsigned long event,
++ void *p);
++static struct notifier_block dca_notifier = {
++ .notifier_call = ixgbe_notify_dca,
++ .next = NULL,
++ .priority = 0
++};
++#endif
++
+ MODULE_AUTHOR("Intel Corporation, <linux.nics at intel.com>");
+ MODULE_DESCRIPTION("Intel(R) 10 Gigabit PCI Express Network Driver");
+ MODULE_LICENSE("GPL");
+@@ -256,26 +266,125 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter,
+ * sees the new next_to_clean.
+ */
+ smp_mb();
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ if (__netif_subqueue_stopped(netdev, tx_ring->queue_index) &&
++ !test_bit(__IXGBE_DOWN, &adapter->state)) {
++ netif_wake_subqueue(netdev, tx_ring->queue_index);
++ adapter->restart_queue++;
++ }
++#else
+ if (netif_queue_stopped(netdev) &&
+ !test_bit(__IXGBE_DOWN, &adapter->state)) {
+ netif_wake_queue(netdev);
+ adapter->restart_queue++;
+ }
++#endif
+ }
+
+ if (adapter->detect_tx_hung)
+ if (ixgbe_check_tx_hang(adapter, tx_ring, eop, eop_desc))
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ netif_stop_subqueue(netdev, tx_ring->queue_index);
++#else
+ netif_stop_queue(netdev);
++#endif
+
+ if (total_tx_packets >= tx_ring->work_limit)
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, tx_ring->eims_value);
+
++ tx_ring->total_bytes += total_tx_bytes;
++ tx_ring->total_packets += total_tx_packets;
+ adapter->net_stats.tx_bytes += total_tx_bytes;
+ adapter->net_stats.tx_packets += total_tx_packets;
+ cleaned = total_tx_packets ? true : false;
+ return cleaned;
+ }
+
++#ifdef CONFIG_DCA
++static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter,
++ struct ixgbe_ring *rxr)
++{
++ u32 rxctrl;
++ int cpu = get_cpu();
++ int q = rxr - adapter->rx_ring;
++
++ if (rxr->cpu != cpu) {
++ rxctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_DCA_RXCTRL(q));
++ rxctrl &= ~IXGBE_DCA_RXCTRL_CPUID_MASK;
++ rxctrl |= dca_get_tag(cpu);
++ rxctrl |= IXGBE_DCA_RXCTRL_DESC_DCA_EN;
++ rxctrl |= IXGBE_DCA_RXCTRL_HEAD_DCA_EN;
++ IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_RXCTRL(q), rxctrl);
++ rxr->cpu = cpu;
++ }
++ put_cpu();
++}
++
++static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter,
++ struct ixgbe_ring *txr)
++{
++ u32 txctrl;
++ int cpu = get_cpu();
++ int q = txr - adapter->tx_ring;
++
++ if (txr->cpu != cpu) {
++ txctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_DCA_TXCTRL(q));
++ txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK;
++ txctrl |= dca_get_tag(cpu);
++ txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN;
++ IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_TXCTRL(q), txctrl);
++ txr->cpu = cpu;
++ }
++ put_cpu();
++}
++
++static void ixgbe_setup_dca(struct ixgbe_adapter *adapter)
++{
++ int i;
++
++ if (!(adapter->flags & IXGBE_FLAG_DCA_ENABLED))
++ return;
++
++ for (i = 0; i < adapter->num_tx_queues; i++) {
++ adapter->tx_ring[i].cpu = -1;
++ ixgbe_update_tx_dca(adapter, &adapter->tx_ring[i]);
++ }
++ for (i = 0; i < adapter->num_rx_queues; i++) {
++ adapter->rx_ring[i].cpu = -1;
++ ixgbe_update_rx_dca(adapter, &adapter->rx_ring[i]);
++ }
++}
++
++static int __ixgbe_notify_dca(struct device *dev, void *data)
++{
++ struct net_device *netdev = dev_get_drvdata(dev);
++ struct ixgbe_adapter *adapter = netdev_priv(netdev);
++ unsigned long event = *(unsigned long *)data;
++
++ switch (event) {
++ case DCA_PROVIDER_ADD:
++ adapter->flags |= IXGBE_FLAG_DCA_ENABLED;
++ /* Always use CB2 mode, difference is masked
++ * in the CB driver. */
++ IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 2);
++ if (dca_add_requester(dev) == 0) {
++ ixgbe_setup_dca(adapter);
++ break;
++ }
++ /* Fall Through since DCA is disabled. */
++ case DCA_PROVIDER_REMOVE:
++ if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
++ dca_remove_requester(dev);
++ adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED;
++ IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 1);
++ }
++ break;
++ }
++
++ return 0;
++}
++
++#endif /* CONFIG_DCA */
+ /**
+ * ixgbe_receive_skb - Send a completed packet up the stack
+ * @adapter: board private structure
+@@ -556,10 +665,15 @@ next_desc:
+ adapter->net_stats.rx_bytes += total_rx_bytes;
+ adapter->net_stats.rx_packets += total_rx_packets;
+
++ rx_ring->total_packets += total_rx_packets;
++ rx_ring->total_bytes += total_rx_bytes;
++ adapter->net_stats.rx_bytes += total_rx_bytes;
++ adapter->net_stats.rx_packets += total_rx_packets;
++
+ return cleaned;
+ }
+
+-#define IXGBE_MAX_INTR 10
++static int ixgbe_clean_rxonly(struct napi_struct *, int);
+ /**
+ * ixgbe_configure_msix - Configure MSI-X hardware
+ * @adapter: board private structure
+@@ -569,28 +683,195 @@ next_desc:
+ **/
+ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
+ {
+- int i, vector = 0;
++ struct ixgbe_q_vector *q_vector;
++ int i, j, q_vectors, v_idx, r_idx;
++ u32 mask;
+
+- for (i = 0; i < adapter->num_tx_queues; i++) {
+- ixgbe_set_ivar(adapter, IXGBE_IVAR_TX_QUEUE(i),
+- IXGBE_MSIX_VECTOR(vector));
+- writel(EITR_INTS_PER_SEC_TO_REG(adapter->tx_eitr),
+- adapter->hw.hw_addr + adapter->tx_ring[i].itr_register);
+- vector++;
+- }
++ q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+
+- for (i = 0; i < adapter->num_rx_queues; i++) {
+- ixgbe_set_ivar(adapter, IXGBE_IVAR_RX_QUEUE(i),
+- IXGBE_MSIX_VECTOR(vector));
+- writel(EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr),
+- adapter->hw.hw_addr + adapter->rx_ring[i].itr_register);
+- vector++;
++ /* Populate the IVAR table and set the ITR values to the
++ * corresponding register.
++ */
++ for (v_idx = 0; v_idx < q_vectors; v_idx++) {
++ q_vector = &adapter->q_vector[v_idx];
++ /* XXX for_each_bit(...) */
++ r_idx = find_first_bit(q_vector->rxr_idx,
++ adapter->num_rx_queues);
++
++ for (i = 0; i < q_vector->rxr_count; i++) {
++ j = adapter->rx_ring[r_idx].reg_idx;
++ ixgbe_set_ivar(adapter, IXGBE_IVAR_RX_QUEUE(j), v_idx);
++ r_idx = find_next_bit(q_vector->rxr_idx,
++ adapter->num_rx_queues,
++ r_idx + 1);
++ }
++ r_idx = find_first_bit(q_vector->txr_idx,
++ adapter->num_tx_queues);
++
++ for (i = 0; i < q_vector->txr_count; i++) {
++ j = adapter->tx_ring[r_idx].reg_idx;
++ ixgbe_set_ivar(adapter, IXGBE_IVAR_TX_QUEUE(j), v_idx);
++ r_idx = find_next_bit(q_vector->txr_idx,
++ adapter->num_tx_queues,
++ r_idx + 1);
++ }
++
++ /* if this is a tx only vector use half the irq (tx) rate */
++ if (q_vector->txr_count && !q_vector->rxr_count)
++ q_vector->eitr = adapter->tx_eitr;
++ else
++ /* rx only or mixed */
++ q_vector->eitr = adapter->rx_eitr;
++
++ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(v_idx),
++ EITR_INTS_PER_SEC_TO_REG(q_vector->eitr));
+ }
+
+- vector = adapter->num_tx_queues + adapter->num_rx_queues;
+- ixgbe_set_ivar(adapter, IXGBE_IVAR_OTHER_CAUSES_INDEX,
+- IXGBE_MSIX_VECTOR(vector));
+- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(vector), 1950);
++ ixgbe_set_ivar(adapter, IXGBE_IVAR_OTHER_CAUSES_INDEX, v_idx);
++ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(v_idx), 1950);
++
++ /* set up to autoclear timer, lsc, and the vectors */
++ mask = IXGBE_EIMS_ENABLE_MASK;
++ mask &= ~IXGBE_EIMS_OTHER;
++ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, mask);
++}
++
++enum latency_range {
++ lowest_latency = 0,
++ low_latency = 1,
++ bulk_latency = 2,
++ latency_invalid = 255
++};
++
++/**
++ * ixgbe_update_itr - update the dynamic ITR value based on statistics
++ * @adapter: pointer to adapter
++ * @eitr: eitr setting (ints per sec) to give last timeslice
++ * @itr_setting: current throttle rate in ints/second
++ * @packets: the number of packets during this measurement interval
++ * @bytes: the number of bytes during this measurement interval
++ *
++ * Stores a new ITR value based on packets and byte
++ * counts during the last interrupt. The advantage of per interrupt
++ * computation is faster updates and more accurate ITR for the current
++ * traffic pattern. Constants in this function were computed
++ * based on theoretical maximum wire speed and thresholds were set based
++ * on testing data as well as attempting to minimize response time
++ * while increasing bulk throughput.
++ * this functionality is controlled by the InterruptThrottleRate module
++ * parameter (see ixgbe_param.c)
++ **/
++static u8 ixgbe_update_itr(struct ixgbe_adapter *adapter,
++ u32 eitr, u8 itr_setting,
++ int packets, int bytes)
++{
++ unsigned int retval = itr_setting;
++ u32 timepassed_us;
++ u64 bytes_perint;
++
++ if (packets == 0)
++ goto update_itr_done;
++
++
++ /* simple throttlerate management
++ * 0-20MB/s lowest (100000 ints/s)
++ * 20-100MB/s low (20000 ints/s)
++ * 100-1249MB/s bulk (8000 ints/s)
++ */
++ /* what was last interrupt timeslice? */
++ timepassed_us = 1000000/eitr;
++ bytes_perint = bytes / timepassed_us; /* bytes/usec */
++
++ switch (itr_setting) {
++ case lowest_latency:
++ if (bytes_perint > adapter->eitr_low)
++ retval = low_latency;
++ break;
++ case low_latency:
++ if (bytes_perint > adapter->eitr_high)
++ retval = bulk_latency;
++ else if (bytes_perint <= adapter->eitr_low)
++ retval = lowest_latency;
++ break;
++ case bulk_latency:
++ if (bytes_perint <= adapter->eitr_high)
++ retval = low_latency;
++ break;
++ }
++
++update_itr_done:
++ return retval;
++}
++
++static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector)
++{
++ struct ixgbe_adapter *adapter = q_vector->adapter;
++ struct ixgbe_hw *hw = &adapter->hw;
++ u32 new_itr;
++ u8 current_itr, ret_itr;
++ int i, r_idx, v_idx = ((void *)q_vector - (void *)(adapter->q_vector)) /
++ sizeof(struct ixgbe_q_vector);
++ struct ixgbe_ring *rx_ring, *tx_ring;
++
++ r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
++ for (i = 0; i < q_vector->txr_count; i++) {
++ tx_ring = &(adapter->tx_ring[r_idx]);
++ ret_itr = ixgbe_update_itr(adapter, q_vector->eitr,
++ q_vector->tx_eitr,
++ tx_ring->total_packets,
++ tx_ring->total_bytes);
++ /* if the result for this queue would decrease interrupt
++ * rate for this vector then use that result */
++ q_vector->tx_eitr = ((q_vector->tx_eitr > ret_itr) ?
++ q_vector->tx_eitr - 1 : ret_itr);
++ r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
++ r_idx + 1);
++ }
++
++ r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
++ for (i = 0; i < q_vector->rxr_count; i++) {
++ rx_ring = &(adapter->rx_ring[r_idx]);
++ ret_itr = ixgbe_update_itr(adapter, q_vector->eitr,
++ q_vector->rx_eitr,
++ rx_ring->total_packets,
++ rx_ring->total_bytes);
++ /* if the result for this queue would decrease interrupt
++ * rate for this vector then use that result */
++ q_vector->rx_eitr = ((q_vector->rx_eitr > ret_itr) ?
++ q_vector->rx_eitr - 1 : ret_itr);
++ r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues,
++ r_idx + 1);
++ }
++
++ current_itr = max(q_vector->rx_eitr, q_vector->tx_eitr);
++
++ switch (current_itr) {
++ /* counts and packets in update_itr are dependent on these numbers */
++ case lowest_latency:
++ new_itr = 100000;
++ break;
++ case low_latency:
++ new_itr = 20000; /* aka hwitr = ~200 */
++ break;
++ case bulk_latency:
++ default:
++ new_itr = 8000;
++ break;
++ }
++
++ if (new_itr != q_vector->eitr) {
++ u32 itr_reg;
++ /* do an exponential smoothing */
++ new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100);
++ q_vector->eitr = new_itr;
++ itr_reg = EITR_INTS_PER_SEC_TO_REG(new_itr);
++ /* must write high and low 16 bits to reset counter */
++ DPRINTK(TX_ERR, DEBUG, "writing eitr(%d): %08X\n", v_idx,
++ itr_reg);
++ IXGBE_WRITE_REG(hw, IXGBE_EITR(v_idx), itr_reg | (itr_reg)<<16);
++ }
++
++ return;
+ }
+
+ static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
+@@ -614,153 +895,302 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
+
+ static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data)
+ {
+- struct ixgbe_ring *txr = data;
+- struct ixgbe_adapter *adapter = txr->adapter;
++ struct ixgbe_q_vector *q_vector = data;
++ struct ixgbe_adapter *adapter = q_vector->adapter;
++ struct ixgbe_ring *txr;
++ int i, r_idx;
+
+- ixgbe_clean_tx_irq(adapter, txr);
++ if (!q_vector->txr_count)
++ return IRQ_HANDLED;
++
++ r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
++ for (i = 0; i < q_vector->txr_count; i++) {
++ txr = &(adapter->tx_ring[r_idx]);
++#ifdef CONFIG_DCA
++ if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
++ ixgbe_update_tx_dca(adapter, txr);
++#endif
++ txr->total_bytes = 0;
++ txr->total_packets = 0;
++ ixgbe_clean_tx_irq(adapter, txr);
++ r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues,
++ r_idx + 1);
++ }
+
+ return IRQ_HANDLED;
+ }
+
++/**
++ * ixgbe_msix_clean_rx - single unshared vector rx clean (all queues)
++ * @irq: unused
++ * @data: pointer to our q_vector struct for this interrupt vector
++ **/
+ static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data)
+ {
+- struct ixgbe_ring *rxr = data;
+- struct ixgbe_adapter *adapter = rxr->adapter;
++ struct ixgbe_q_vector *q_vector = data;
++ struct ixgbe_adapter *adapter = q_vector->adapter;
++ struct ixgbe_ring *rxr;
++ int r_idx;
++
++ r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
++ if (!q_vector->rxr_count)
++ return IRQ_HANDLED;
++
++ rxr = &(adapter->rx_ring[r_idx]);
++ /* disable interrupts on this vector only */
++ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, rxr->v_idx);
++ rxr->total_bytes = 0;
++ rxr->total_packets = 0;
++ netif_rx_schedule(adapter->netdev, &q_vector->napi);
++
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t ixgbe_msix_clean_many(int irq, void *data)
++{
++ ixgbe_msix_clean_rx(irq, data);
++ ixgbe_msix_clean_tx(irq, data);
+
+- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, rxr->eims_value);
+- netif_rx_schedule(adapter->netdev, &adapter->napi);
+ return IRQ_HANDLED;
+ }
+
++/**
++ * ixgbe_clean_rxonly - msix (aka one shot) rx clean routine
++ * @napi: napi struct with our devices info in it
++ * @budget: amount of work driver is allowed to do this pass, in packets
++ *
++ **/
+ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)
+ {
+- struct ixgbe_adapter *adapter = container_of(napi,
+- struct ixgbe_adapter, napi);
+- struct net_device *netdev = adapter->netdev;
++ struct ixgbe_q_vector *q_vector =
++ container_of(napi, struct ixgbe_q_vector, napi);
++ struct ixgbe_adapter *adapter = q_vector->adapter;
++ struct ixgbe_ring *rxr;
+ int work_done = 0;
+- struct ixgbe_ring *rxr = adapter->rx_ring;
++ long r_idx;
+
+- /* Keep link state information with original netdev */
+- if (!netif_carrier_ok(netdev))
+- goto quit_polling;
++ r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
++ rxr = &(adapter->rx_ring[r_idx]);
++#ifdef CONFIG_DCA
++ if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
++ ixgbe_update_rx_dca(adapter, rxr);
++#endif
+
+ ixgbe_clean_rx_irq(adapter, rxr, &work_done, budget);
+
+- /* If no Tx and not enough Rx work done, exit the polling mode */
+- if ((work_done < budget) || !netif_running(netdev)) {
+-quit_polling:
+- netif_rx_complete(netdev, napi);
++ /* If all Rx work done, exit the polling mode */
++ if (work_done < budget) {
++ netif_rx_complete(adapter->netdev, napi);
++ if (adapter->rx_eitr < IXGBE_MIN_ITR_USECS)
++ ixgbe_set_itr_msix(q_vector);
+ if (!test_bit(__IXGBE_DOWN, &adapter->state))
+- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS,
+- rxr->eims_value);
++ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, rxr->v_idx);
+ }
+
+ return work_done;
+ }
+
++static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx,
++ int r_idx)
++{
++ a->q_vector[v_idx].adapter = a;
++ set_bit(r_idx, a->q_vector[v_idx].rxr_idx);
++ a->q_vector[v_idx].rxr_count++;
++ a->rx_ring[r_idx].v_idx = 1 << v_idx;
++}
++
++static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx,
++ int r_idx)
++{
++ a->q_vector[v_idx].adapter = a;
++ set_bit(r_idx, a->q_vector[v_idx].txr_idx);
++ a->q_vector[v_idx].txr_count++;
++ a->tx_ring[r_idx].v_idx = 1 << v_idx;
++}
++
+ /**
+- * ixgbe_setup_msix - Initialize MSI-X interrupts
++ * ixgbe_map_rings_to_vectors - Maps descriptor rings to vectors
++ * @adapter: board private structure to initialize
++ * @vectors: allotted vector count for descriptor rings
+ *
+- * ixgbe_setup_msix allocates MSI-X vectors and requests
+- * interrutps from the kernel.
++ * This function maps descriptor rings to the queue-specific vectors
++ * we were allotted through the MSI-X enabling code. Ideally, we'd have
++ * one vector per ring/queue, but on a constrained vector budget, we
++ * group the rings as "efficiently" as possible. You would add new
++ * mapping configurations in here.
+ **/
+-static int ixgbe_setup_msix(struct ixgbe_adapter *adapter)
+-{
+- struct net_device *netdev = adapter->netdev;
+- int i, int_vector = 0, err = 0;
+- int max_msix_count;
++static int ixgbe_map_rings_to_vectors(struct ixgbe_adapter *adapter,
++ int vectors)
++{
++ int v_start = 0;
++ int rxr_idx = 0, txr_idx = 0;
++ int rxr_remaining = adapter->num_rx_queues;
++ int txr_remaining = adapter->num_tx_queues;
++ int i, j;
++ int rqpv, tqpv;
++ int err = 0;
++
++ /* No mapping required if MSI-X is disabled. */
++ if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED))
++ goto out;
+
+- /* +1 for the LSC interrupt */
+- max_msix_count = adapter->num_rx_queues + adapter->num_tx_queues + 1;
+- adapter->msix_entries = kcalloc(max_msix_count,
+- sizeof(struct msix_entry), GFP_KERNEL);
+- if (!adapter->msix_entries)
+- return -ENOMEM;
++ /*
++ * The ideal configuration...
++ * We have enough vectors to map one per queue.
++ */
++ if (vectors == adapter->num_rx_queues + adapter->num_tx_queues) {
++ for (; rxr_idx < rxr_remaining; v_start++, rxr_idx++)
++ map_vector_to_rxq(adapter, v_start, rxr_idx);
+
+- for (i = 0; i < max_msix_count; i++)
+- adapter->msix_entries[i].entry = i;
++ for (; txr_idx < txr_remaining; v_start++, txr_idx++)
++ map_vector_to_txq(adapter, v_start, txr_idx);
+
+- err = pci_enable_msix(adapter->pdev, adapter->msix_entries,
+- max_msix_count);
+- if (err)
+ goto out;
++ }
+
+- for (i = 0; i < adapter->num_tx_queues; i++) {
+- sprintf(adapter->tx_ring[i].name, "%s-tx%d", netdev->name, i);
+- err = request_irq(adapter->msix_entries[int_vector].vector,
+- &ixgbe_msix_clean_tx,
+- 0,
+- adapter->tx_ring[i].name,
+- &(adapter->tx_ring[i]));
+- if (err) {
+- DPRINTK(PROBE, ERR,
+- "request_irq failed for MSIX interrupt "
+- "Error: %d\n", err);
+- goto release_irqs;
++ /*
++ * If we don't have enough vectors for a 1-to-1
++ * mapping, we'll have to group them so there are
++ * multiple queues per vector.
++ */
++ /* Re-adjusting *qpv takes care of the remainder. */
++ for (i = v_start; i < vectors; i++) {
++ rqpv = DIV_ROUND_UP(rxr_remaining, vectors - i);
++ for (j = 0; j < rqpv; j++) {
++ map_vector_to_rxq(adapter, i, rxr_idx);
++ rxr_idx++;
++ rxr_remaining--;
++ }
++ }
++ for (i = v_start; i < vectors; i++) {
++ tqpv = DIV_ROUND_UP(txr_remaining, vectors - i);
++ for (j = 0; j < tqpv; j++) {
++ map_vector_to_txq(adapter, i, txr_idx);
++ txr_idx++;
++ txr_remaining--;
+ }
+- adapter->tx_ring[i].eims_value =
+- (1 << IXGBE_MSIX_VECTOR(int_vector));
+- adapter->tx_ring[i].itr_register = IXGBE_EITR(int_vector);
+- int_vector++;
+ }
+
+- for (i = 0; i < adapter->num_rx_queues; i++) {
+- if (strlen(netdev->name) < (IFNAMSIZ - 5))
+- sprintf(adapter->rx_ring[i].name,
+- "%s-rx%d", netdev->name, i);
+- else
+- memcpy(adapter->rx_ring[i].name,
+- netdev->name, IFNAMSIZ);
+- err = request_irq(adapter->msix_entries[int_vector].vector,
+- &ixgbe_msix_clean_rx, 0,
+- adapter->rx_ring[i].name,
+- &(adapter->rx_ring[i]));
++out:
++ return err;
++}
++
++/**
++ * ixgbe_request_msix_irqs - Initialize MSI-X interrupts
++ * @adapter: board private structure
++ *
++ * ixgbe_request_msix_irqs allocates MSI-X vectors and requests
++ * interrupts from the kernel.
++ **/
++static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
++{
++ struct net_device *netdev = adapter->netdev;
++ irqreturn_t (*handler)(int, void *);
++ int i, vector, q_vectors, err;
++
++ /* Decrement for Other and TCP Timer vectors */
++ q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
++
++ /* Map the Tx/Rx rings to the vectors we were allotted. */
++ err = ixgbe_map_rings_to_vectors(adapter, q_vectors);
++ if (err)
++ goto out;
++
++#define SET_HANDLER(_v) ((!(_v)->rxr_count) ? &ixgbe_msix_clean_tx : \
++ (!(_v)->txr_count) ? &ixgbe_msix_clean_rx : \
++ &ixgbe_msix_clean_many)
++ for (vector = 0; vector < q_vectors; vector++) {
++ handler = SET_HANDLER(&adapter->q_vector[vector]);
++ sprintf(adapter->name[vector], "%s:v%d-%s",
++ netdev->name, vector,
++ (handler == &ixgbe_msix_clean_rx) ? "Rx" :
++ ((handler == &ixgbe_msix_clean_tx) ? "Tx" : "TxRx"));
++ err = request_irq(adapter->msix_entries[vector].vector,
++ handler, 0, adapter->name[vector],
++ &(adapter->q_vector[vector]));
+ if (err) {
+ DPRINTK(PROBE, ERR,
+ "request_irq failed for MSIX interrupt "
+ "Error: %d\n", err);
+- goto release_irqs;
++ goto free_queue_irqs;
+ }
+-
+- adapter->rx_ring[i].eims_value =
+- (1 << IXGBE_MSIX_VECTOR(int_vector));
+- adapter->rx_ring[i].itr_register = IXGBE_EITR(int_vector);
+- int_vector++;
+ }
+
+- sprintf(adapter->lsc_name, "%s-lsc", netdev->name);
+- err = request_irq(adapter->msix_entries[int_vector].vector,
+- &ixgbe_msix_lsc, 0, adapter->lsc_name, netdev);
++ sprintf(adapter->name[vector], "%s:lsc", netdev->name);
++ err = request_irq(adapter->msix_entries[vector].vector,
++ &ixgbe_msix_lsc, 0, adapter->name[vector], netdev);
+ if (err) {
+ DPRINTK(PROBE, ERR,
+ "request_irq for msix_lsc failed: %d\n", err);
+- goto release_irqs;
++ goto free_queue_irqs;
+ }
+
+- /* FIXME: implement netif_napi_remove() instead */
+- adapter->napi.poll = ixgbe_clean_rxonly;
+- adapter->flags |= IXGBE_FLAG_MSIX_ENABLED;
+ return 0;
+
+-release_irqs:
+- int_vector--;
+- for (; int_vector >= adapter->num_tx_queues; int_vector--)
+- free_irq(adapter->msix_entries[int_vector].vector,
+- &(adapter->rx_ring[int_vector -
+- adapter->num_tx_queues]));
+-
+- for (; int_vector >= 0; int_vector--)
+- free_irq(adapter->msix_entries[int_vector].vector,
+- &(adapter->tx_ring[int_vector]));
+-out:
++free_queue_irqs:
++ for (i = vector - 1; i >= 0; i--)
++ free_irq(adapter->msix_entries[--vector].vector,
++ &(adapter->q_vector[i]));
++ adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
++ pci_disable_msix(adapter->pdev);
+ kfree(adapter->msix_entries);
+ adapter->msix_entries = NULL;
+- adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
++out:
+ return err;
+ }
+
++static void ixgbe_set_itr(struct ixgbe_adapter *adapter)
++{
++ struct ixgbe_hw *hw = &adapter->hw;
++ struct ixgbe_q_vector *q_vector = adapter->q_vector;
++ u8 current_itr;
++ u32 new_itr = q_vector->eitr;
++ struct ixgbe_ring *rx_ring = &adapter->rx_ring[0];
++ struct ixgbe_ring *tx_ring = &adapter->tx_ring[0];
++
++ q_vector->tx_eitr = ixgbe_update_itr(adapter, new_itr,
++ q_vector->tx_eitr,
++ tx_ring->total_packets,
++ tx_ring->total_bytes);
++ q_vector->rx_eitr = ixgbe_update_itr(adapter, new_itr,
++ q_vector->rx_eitr,
++ rx_ring->total_packets,
++ rx_ring->total_bytes);
++
++ current_itr = max(q_vector->rx_eitr, q_vector->tx_eitr);
++
++ switch (current_itr) {
++ /* counts and packets in update_itr are dependent on these numbers */
++ case lowest_latency:
++ new_itr = 100000;
++ break;
++ case low_latency:
++ new_itr = 20000; /* aka hwitr = ~200 */
++ break;
++ case bulk_latency:
++ new_itr = 8000;
++ break;
++ default:
++ break;
++ }
++
++ if (new_itr != q_vector->eitr) {
++ u32 itr_reg;
++ /* do an exponential smoothing */
++ new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100);
++ q_vector->eitr = new_itr;
++ itr_reg = EITR_INTS_PER_SEC_TO_REG(new_itr);
++ /* must write high and low 16 bits to reset counter */
++ IXGBE_WRITE_REG(hw, IXGBE_EITR(0), itr_reg | (itr_reg)<<16);
++ }
++
++ return;
++}
++
++static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter);
++
+ /**
+- * ixgbe_intr - Interrupt Handler
++ * ixgbe_intr - legacy mode Interrupt Handler
+ * @irq: interrupt number
+ * @data: pointer to a network interface device structure
+ * @pt_regs: CPU registers structure
+@@ -772,8 +1202,10 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 eicr;
+
+- eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
+
++ /* for NAPI, using EIAM to auto-mask tx/rx interrupt bits on read
++ * therefore no explict interrupt disable is necessary */
++ eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
+ if (!eicr)
+ return IRQ_NONE; /* Not our interrupt */
+
+@@ -782,16 +1214,33 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
+ if (!test_bit(__IXGBE_DOWN, &adapter->state))
+ mod_timer(&adapter->watchdog_timer, jiffies);
+ }
+- if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
+- /* Disable interrupts and register for poll. The flush of the
+- * posted write is intentionally left out. */
+- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
+- __netif_rx_schedule(netdev, &adapter->napi);
++
++
++ if (netif_rx_schedule_prep(netdev, &adapter->q_vector[0].napi)) {
++ adapter->tx_ring[0].total_packets = 0;
++ adapter->tx_ring[0].total_bytes = 0;
++ adapter->rx_ring[0].total_packets = 0;
++ adapter->rx_ring[0].total_bytes = 0;
++ /* would disable interrupts here but EIAM disabled it */
++ __netif_rx_schedule(netdev, &adapter->q_vector[0].napi);
+ }
+
+ return IRQ_HANDLED;
+ }
+
++static inline void ixgbe_reset_q_vectors(struct ixgbe_adapter *adapter)
++{
++ int i, q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
++
++ for (i = 0; i < q_vectors; i++) {
++ struct ixgbe_q_vector *q_vector = &adapter->q_vector[i];
++ bitmap_zero(q_vector->rxr_idx, MAX_RX_QUEUES);
++ bitmap_zero(q_vector->txr_idx, MAX_TX_QUEUES);
++ q_vector->rxr_count = 0;
++ q_vector->txr_count = 0;
++ }
++}
++
+ /**
+ * ixgbe_request_irq - initialize interrupts
+ * @adapter: board private structure
+@@ -799,40 +1248,24 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
+ * Attempts to configure interrupts using the best available
+ * capabilities of the hardware and kernel.
+ **/
+-static int ixgbe_request_irq(struct ixgbe_adapter *adapter, u32 *num_rx_queues)
++static int ixgbe_request_irq(struct ixgbe_adapter *adapter)
+ {
+ struct net_device *netdev = adapter->netdev;
+- int flags, err;
+- irq_handler_t handler = ixgbe_intr;
+-
+- flags = IRQF_SHARED;
+-
+- err = ixgbe_setup_msix(adapter);
+- if (!err)
+- goto request_done;
+-
+- /*
+- * if we can't do MSI-X, fall through and try MSI
+- * No need to reallocate memory since we're decreasing the number of
+- * queues. We just won't use the other ones, also it is freed correctly
+- * on ixgbe_remove.
+- */
+- *num_rx_queues = 1;
++ int err;
+
+- /* do MSI */
+- err = pci_enable_msi(adapter->pdev);
+- if (!err) {
+- adapter->flags |= IXGBE_FLAG_MSI_ENABLED;
+- flags &= ~IRQF_SHARED;
+- handler = &ixgbe_intr;
++ if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
++ err = ixgbe_request_msix_irqs(adapter);
++ } else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) {
++ err = request_irq(adapter->pdev->irq, &ixgbe_intr, 0,
++ netdev->name, netdev);
++ } else {
++ err = request_irq(adapter->pdev->irq, &ixgbe_intr, IRQF_SHARED,
++ netdev->name, netdev);
+ }
+
+- err = request_irq(adapter->pdev->irq, handler, flags,
+- netdev->name, netdev);
+ if (err)
+ DPRINTK(PROBE, ERR, "request_irq failed, Error %d\n", err);
+
+-request_done:
+ return err;
+ }
+
+@@ -841,28 +1274,22 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter)
+ struct net_device *netdev = adapter->netdev;
+
+ if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
+- int i;
++ int i, q_vectors;
+
+- for (i = 0; i < adapter->num_tx_queues; i++)
+- free_irq(adapter->msix_entries[i].vector,
+- &(adapter->tx_ring[i]));
+- for (i = 0; i < adapter->num_rx_queues; i++)
+- free_irq(adapter->msix_entries[i +
+- adapter->num_tx_queues].vector,
+- &(adapter->rx_ring[i]));
+- i = adapter->num_rx_queues + adapter->num_tx_queues;
++ q_vectors = adapter->num_msix_vectors;
++
++ i = q_vectors - 1;
+ free_irq(adapter->msix_entries[i].vector, netdev);
+- pci_disable_msix(adapter->pdev);
+- kfree(adapter->msix_entries);
+- adapter->msix_entries = NULL;
+- adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
+- return;
+- }
+
+- free_irq(adapter->pdev->irq, netdev);
+- if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) {
+- pci_disable_msi(adapter->pdev);
+- adapter->flags &= ~IXGBE_FLAG_MSI_ENABLED;
++ i--;
++ for (; i >= 0; i--) {
++ free_irq(adapter->msix_entries[i].vector,
++ &(adapter->q_vector[i]));
++ }
++
++ ixgbe_reset_q_vectors(adapter);
++ } else {
++ free_irq(adapter->pdev->irq, netdev);
+ }
+ }
+
+@@ -874,7 +1301,13 @@ static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter)
+ {
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
+ IXGBE_WRITE_FLUSH(&adapter->hw);
+- synchronize_irq(adapter->pdev->irq);
++ if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
++ int i;
++ for (i = 0; i < adapter->num_msix_vectors; i++)
++ synchronize_irq(adapter->msix_entries[i].vector);
++ } else {
++ synchronize_irq(adapter->pdev->irq);
++ }
+ }
+
+ /**
+@@ -883,12 +1316,9 @@ static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter)
+ **/
+ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter)
+ {
+- if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
+- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC,
+- (IXGBE_EIMS_ENABLE_MASK &
+- ~(IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC)));
+- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS,
+- IXGBE_EIMS_ENABLE_MASK);
++ u32 mask;
++ mask = IXGBE_EIMS_ENABLE_MASK;
++ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
+ IXGBE_WRITE_FLUSH(&adapter->hw);
+ }
+
+@@ -898,20 +1328,18 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter)
+ **/
+ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter)
+ {
+- int i;
+ struct ixgbe_hw *hw = &adapter->hw;
+
+- if (adapter->rx_eitr)
+- IXGBE_WRITE_REG(hw, IXGBE_EITR(0),
+- EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr));
+-
+- /* for re-triggering the interrupt in non-NAPI mode */
+- adapter->rx_ring[0].eims_value = (1 << IXGBE_MSIX_VECTOR(0));
+- adapter->tx_ring[0].eims_value = (1 << IXGBE_MSIX_VECTOR(0));
++ IXGBE_WRITE_REG(hw, IXGBE_EITR(0),
++ EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr));
+
+ ixgbe_set_ivar(adapter, IXGBE_IVAR_RX_QUEUE(0), 0);
+- for (i = 0; i < adapter->num_tx_queues; i++)
+- ixgbe_set_ivar(adapter, IXGBE_IVAR_TX_QUEUE(i), i);
++ ixgbe_set_ivar(adapter, IXGBE_IVAR_TX_QUEUE(0), 0);
++
++ map_vector_to_rxq(adapter, 0, 0);
++ map_vector_to_txq(adapter, 0, 0);
++
++ DPRINTK(HW, INFO, "Legacy interrupt IVAR setup done\n");
+ }
+
+ /**
+@@ -924,23 +1352,29 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter)
+ {
+ u64 tdba;
+ struct ixgbe_hw *hw = &adapter->hw;
+- u32 i, tdlen;
++ u32 i, j, tdlen, txctrl;
+
+ /* Setup the HW Tx Head and Tail descriptor pointers */
+ for (i = 0; i < adapter->num_tx_queues; i++) {
++ j = adapter->tx_ring[i].reg_idx;
+ tdba = adapter->tx_ring[i].dma;
+ tdlen = adapter->tx_ring[i].count *
+- sizeof(union ixgbe_adv_tx_desc);
+- IXGBE_WRITE_REG(hw, IXGBE_TDBAL(i), (tdba & DMA_32BIT_MASK));
+- IXGBE_WRITE_REG(hw, IXGBE_TDBAH(i), (tdba >> 32));
+- IXGBE_WRITE_REG(hw, IXGBE_TDLEN(i), tdlen);
+- IXGBE_WRITE_REG(hw, IXGBE_TDH(i), 0);
+- IXGBE_WRITE_REG(hw, IXGBE_TDT(i), 0);
+- adapter->tx_ring[i].head = IXGBE_TDH(i);
+- adapter->tx_ring[i].tail = IXGBE_TDT(i);
++ sizeof(union ixgbe_adv_tx_desc);
++ IXGBE_WRITE_REG(hw, IXGBE_TDBAL(j),
++ (tdba & DMA_32BIT_MASK));
++ IXGBE_WRITE_REG(hw, IXGBE_TDBAH(j), (tdba >> 32));
++ IXGBE_WRITE_REG(hw, IXGBE_TDLEN(j), tdlen);
++ IXGBE_WRITE_REG(hw, IXGBE_TDH(j), 0);
++ IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0);
++ adapter->tx_ring[i].head = IXGBE_TDH(j);
++ adapter->tx_ring[i].tail = IXGBE_TDT(j);
++ /* Disable Tx Head Writeback RO bit, since this hoses
++ * bookkeeping if things aren't delivered in order.
++ */
++ txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(i));
++ txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
++ IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i), txctrl);
+ }
+-
+- IXGBE_WRITE_REG(hw, IXGBE_TIPG, IXGBE_TIPG_FIBER_DEFAULT);
+ }
+
+ #define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \
+@@ -959,13 +1393,12 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct net_device *netdev = adapter->netdev;
+ int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
++ int i, j;
+ u32 rdlen, rxctrl, rxcsum;
+ u32 random[10];
+- u32 reta, mrqc;
+- int i;
+ u32 fctrl, hlreg0;
+- u32 srrctl;
+ u32 pages;
++ u32 reta = 0, mrqc, srrctl;
+
+ /* Decide whether to use packet split mode or not */
+ if (netdev->mtu > ETH_DATA_LEN)
+@@ -985,6 +1418,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
+
+ fctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
+ fctrl |= IXGBE_FCTRL_BAM;
++ fctrl |= IXGBE_FCTRL_DPF; /* discard pause frames when FC enabled */
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, fctrl);
+
+ hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
+@@ -1036,37 +1470,23 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
+ adapter->rx_ring[i].tail = IXGBE_RDT(i);
+ }
+
+- if (adapter->num_rx_queues > 1) {
+- /* Random 40bytes used as random key in RSS hash function */
+- get_random_bytes(&random[0], 40);
+-
+- switch (adapter->num_rx_queues) {
+- case 8:
+- case 4:
+- /* Bits [3:0] in each byte refers the Rx queue no */
+- reta = 0x00010203;
+- break;
+- case 2:
+- reta = 0x00010001;
+- break;
+- default:
+- reta = 0x00000000;
+- break;
+- }
+-
++ if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
+ /* Fill out redirection table */
+- for (i = 0; i < 32; i++) {
+- IXGBE_WRITE_REG_ARRAY(hw, IXGBE_RETA(0), i, reta);
+- if (adapter->num_rx_queues > 4) {
+- i++;
+- IXGBE_WRITE_REG_ARRAY(hw, IXGBE_RETA(0), i,
+- 0x04050607);
+- }
++ for (i = 0, j = 0; i < 128; i++, j++) {
++ if (j == adapter->ring_feature[RING_F_RSS].indices)
++ j = 0;
++ /* reta = 4-byte sliding window of
++ * 0x00..(indices-1)(indices-1)00..etc. */
++ reta = (reta << 8) | (j * 0x11);
++ if ((i & 3) == 3)
++ IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta);
+ }
+
+ /* Fill out hash function seeds */
++ /* XXX use a random constant here to glue certain flows */
++ get_random_bytes(&random[0], 40);
+ for (i = 0; i < 10; i++)
+- IXGBE_WRITE_REG_ARRAY(hw, IXGBE_RSSRK(0), i, random[i]);
++ IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), random[i]);
+
+ mrqc = IXGBE_MRQC_RSSEN
+ /* Perform hash on these packet types */
+@@ -1080,26 +1500,23 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
+ | IXGBE_MRQC_RSS_FIELD_IPV6_UDP
+ | IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP;
+ IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
++ }
+
+- /* Multiqueue and packet checksumming are mutually exclusive. */
+- rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
++ rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
++
++ if (adapter->flags & IXGBE_FLAG_RSS_ENABLED ||
++ adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED) {
++ /* Disable indicating checksum in descriptor, enables
++ * RSS hash */
+ rxcsum |= IXGBE_RXCSUM_PCSD;
+- IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
+- } else {
+- /* Enable Receive Checksum Offload for TCP and UDP */
+- rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
+- if (adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED) {
+- /* Enable IPv4 payload checksum for UDP fragments
+- * Must be used in conjunction with packet-split. */
+- rxcsum |= IXGBE_RXCSUM_IPPCSE;
+- } else {
+- /* don't need to clear IPPCSE as it defaults to 0 */
+- }
+- IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
+ }
+- /* Enable Receives */
+- IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl);
+- rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
++ if (!(rxcsum & IXGBE_RXCSUM_PCSD)) {
++ /* Enable IPv4 payload checksum for UDP fragments
++ * if PCSD is not set */
++ rxcsum |= IXGBE_RXCSUM_IPPCSE;
++ }
++
++ IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
+ }
+
+ static void ixgbe_vlan_rx_register(struct net_device *netdev,
+@@ -1219,6 +1636,42 @@ static void ixgbe_set_multi(struct net_device *netdev)
+
+ }
+
++static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter)
++{
++ int q_idx;
++ struct ixgbe_q_vector *q_vector;
++ int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
++
++ /* legacy and MSI only use one vector */
++ if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED))
++ q_vectors = 1;
++
++ for (q_idx = 0; q_idx < q_vectors; q_idx++) {
++ q_vector = &adapter->q_vector[q_idx];
++ if (!q_vector->rxr_count)
++ continue;
++ napi_enable(&q_vector->napi);
++ }
++}
++
++static void ixgbe_napi_disable_all(struct ixgbe_adapter *adapter)
++{
++ int q_idx;
++ struct ixgbe_q_vector *q_vector;
++ int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
++
++ /* legacy and MSI only use one vector */
++ if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED))
++ q_vectors = 1;
++
++ for (q_idx = 0; q_idx < q_vectors; q_idx++) {
++ q_vector = &adapter->q_vector[q_idx];
++ if (!q_vector->rxr_count)
++ continue;
++ napi_disable(&q_vector->napi);
++ }
++}
++
+ static void ixgbe_configure(struct ixgbe_adapter *adapter)
+ {
+ struct net_device *netdev = adapter->netdev;
+@@ -1238,30 +1691,35 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter)
+ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
+ {
+ struct net_device *netdev = adapter->netdev;
+- int i;
+- u32 gpie = 0;
+ struct ixgbe_hw *hw = &adapter->hw;
+- u32 txdctl, rxdctl, mhadd;
++ int i, j = 0;
+ int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
++ u32 txdctl, rxdctl, mhadd;
++ u32 gpie;
+
+ ixgbe_get_hw_control(adapter);
+
+- if (adapter->flags & (IXGBE_FLAG_MSIX_ENABLED |
+- IXGBE_FLAG_MSI_ENABLED)) {
++ if ((adapter->flags & IXGBE_FLAG_MSIX_ENABLED) ||
++ (adapter->flags & IXGBE_FLAG_MSI_ENABLED)) {
+ if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
+ gpie = (IXGBE_GPIE_MSIX_MODE | IXGBE_GPIE_EIAME |
+ IXGBE_GPIE_PBA_SUPPORT | IXGBE_GPIE_OCD);
+ } else {
+ /* MSI only */
+- gpie = (IXGBE_GPIE_EIAME |
+- IXGBE_GPIE_PBA_SUPPORT);
++ gpie = 0;
+ }
+- IXGBE_WRITE_REG(&adapter->hw, IXGBE_GPIE, gpie);
+- gpie = IXGBE_READ_REG(&adapter->hw, IXGBE_GPIE);
++ /* XXX: to interrupt immediately for EICS writes, enable this */
++ /* gpie |= IXGBE_GPIE_EIMEN; */
++ IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
+ }
+
+- mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
++ if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
++ /* legacy interrupts, use EIAM to auto-mask when reading EICR,
++ * specifically only auto mask tx and rx interrupts */
++ IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE);
++ }
+
++ mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
+ if (max_frame != (mhadd >> IXGBE_MHADD_MFS_SHIFT)) {
+ mhadd &= ~IXGBE_MHADD_MFS_MASK;
+ mhadd |= max_frame << IXGBE_MHADD_MFS_SHIFT;
+@@ -1270,15 +1728,21 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
+ }
+
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+- txdctl = IXGBE_READ_REG(&adapter->hw, IXGBE_TXDCTL(i));
++ j = adapter->tx_ring[i].reg_idx;
++ txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
+ txdctl |= IXGBE_TXDCTL_ENABLE;
+- IXGBE_WRITE_REG(&adapter->hw, IXGBE_TXDCTL(i), txdctl);
++ IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl);
+ }
+
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+- rxdctl = IXGBE_READ_REG(&adapter->hw, IXGBE_RXDCTL(i));
++ j = adapter->rx_ring[i].reg_idx;
++ rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j));
++ /* enable PTHRESH=32 descriptors (half the internal cache)
++ * and HTHRESH=0 descriptors (to minimize latency on fetch),
++ * this also removes a pesky rx_no_buffer_count increment */
++ rxdctl |= 0x0020;
+ rxdctl |= IXGBE_RXDCTL_ENABLE;
+- IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXDCTL(i), rxdctl);
++ IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(j), rxdctl);
+ }
+ /* enable all receives */
+ rxdctl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
+@@ -1291,7 +1755,11 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
+ ixgbe_configure_msi_and_legacy(adapter);
+
+ clear_bit(__IXGBE_DOWN, &adapter->state);
+- napi_enable(&adapter->napi);
++ ixgbe_napi_enable_all(adapter);
++
++ /* clear any pending interrupts, may auto mask */
++ IXGBE_READ_REG(hw, IXGBE_EICR);
++
+ ixgbe_irq_enable(adapter);
+
+ /* bring the link up in the watchdog, this could race with our first
+@@ -1333,7 +1801,7 @@ static int ixgbe_resume(struct pci_dev *pdev)
+ {
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+- u32 err, num_rx_queues = adapter->num_rx_queues;
++ u32 err;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+@@ -1349,7 +1817,7 @@ static int ixgbe_resume(struct pci_dev *pdev)
+ pci_enable_wake(pdev, PCI_D3cold, 0);
+
+ if (netif_running(netdev)) {
+- err = ixgbe_request_irq(adapter, &num_rx_queues);
++ err = ixgbe_request_irq(adapter);
+ if (err)
+ return err;
+ }
+@@ -1449,27 +1917,27 @@ static void ixgbe_clean_tx_ring(struct ixgbe_adapter *adapter,
+ }
+
+ /**
+- * ixgbe_clean_all_tx_rings - Free Tx Buffers for all queues
++ * ixgbe_clean_all_rx_rings - Free Rx Buffers for all queues
+ * @adapter: board private structure
+ **/
+-static void ixgbe_clean_all_tx_rings(struct ixgbe_adapter *adapter)
++static void ixgbe_clean_all_rx_rings(struct ixgbe_adapter *adapter)
+ {
+ int i;
+
+- for (i = 0; i < adapter->num_tx_queues; i++)
+- ixgbe_clean_tx_ring(adapter, &adapter->tx_ring[i]);
++ for (i = 0; i < adapter->num_rx_queues; i++)
++ ixgbe_clean_rx_ring(adapter, &adapter->rx_ring[i]);
+ }
+
+ /**
+- * ixgbe_clean_all_rx_rings - Free Rx Buffers for all queues
++ * ixgbe_clean_all_tx_rings - Free Tx Buffers for all queues
+ * @adapter: board private structure
+ **/
+-static void ixgbe_clean_all_rx_rings(struct ixgbe_adapter *adapter)
++static void ixgbe_clean_all_tx_rings(struct ixgbe_adapter *adapter)
+ {
+ int i;
+
+- for (i = 0; i < adapter->num_rx_queues; i++)
+- ixgbe_clean_rx_ring(adapter, &adapter->rx_ring[i]);
++ for (i = 0; i < adapter->num_tx_queues; i++)
++ ixgbe_clean_tx_ring(adapter, &adapter->tx_ring[i]);
+ }
+
+ void ixgbe_down(struct ixgbe_adapter *adapter)
+@@ -1493,10 +1961,9 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
+ IXGBE_WRITE_FLUSH(&adapter->hw);
+ msleep(10);
+
+- napi_disable(&adapter->napi);
+-
+ ixgbe_irq_disable(adapter);
+
++ ixgbe_napi_disable_all(adapter);
+ del_timer_sync(&adapter->watchdog_timer);
+
+ netif_carrier_off(netdev);
+@@ -1547,27 +2014,37 @@ static void ixgbe_shutdown(struct pci_dev *pdev)
+ }
+
+ /**
+- * ixgbe_clean - NAPI Rx polling callback
+- * @adapter: board private structure
++ * ixgbe_poll - NAPI Rx polling callback
++ * @napi: structure for representing this polling device
++ * @budget: how many packets driver is allowed to clean
++ *
++ * This function is used for legacy and MSI, NAPI mode
+ **/
+-static int ixgbe_clean(struct napi_struct *napi, int budget)
++static int ixgbe_poll(struct napi_struct *napi, int budget)
+ {
+- struct ixgbe_adapter *adapter = container_of(napi,
+- struct ixgbe_adapter, napi);
+- struct net_device *netdev = adapter->netdev;
++ struct ixgbe_q_vector *q_vector = container_of(napi,
++ struct ixgbe_q_vector, napi);
++ struct ixgbe_adapter *adapter = q_vector->adapter;
+ int tx_cleaned = 0, work_done = 0;
+
+- /* In non-MSIX case, there is no multi-Tx/Rx queue */
++#ifdef CONFIG_DCA
++ if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
++ ixgbe_update_tx_dca(adapter, adapter->tx_ring);
++ ixgbe_update_rx_dca(adapter, adapter->rx_ring);
++ }
++#endif
++
+ tx_cleaned = ixgbe_clean_tx_irq(adapter, adapter->tx_ring);
+- ixgbe_clean_rx_irq(adapter, &adapter->rx_ring[0], &work_done,
+- budget);
++ ixgbe_clean_rx_irq(adapter, adapter->rx_ring, &work_done, budget);
+
+ if (tx_cleaned)
+ work_done = budget;
+
+ /* If budget not fully consumed, exit the polling mode */
+ if (work_done < budget) {
+- netif_rx_complete(netdev, napi);
++ netif_rx_complete(adapter->netdev, napi);
++ if (adapter->rx_eitr < IXGBE_MIN_ITR_USECS)
++ ixgbe_set_itr(adapter);
+ if (!test_bit(__IXGBE_DOWN, &adapter->state))
+ ixgbe_irq_enable(adapter);
+ }
+@@ -1597,6 +2074,136 @@ static void ixgbe_reset_task(struct work_struct *work)
+ ixgbe_reinit_locked(adapter);
+ }
+
++static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter,
++ int vectors)
++{
++ int err, vector_threshold;
++
++ /* We'll want at least 3 (vector_threshold):
++ * 1) TxQ[0] Cleanup
++ * 2) RxQ[0] Cleanup
++ * 3) Other (Link Status Change, etc.)
++ * 4) TCP Timer (optional)
++ */
++ vector_threshold = MIN_MSIX_COUNT;
++
++ /* The more we get, the more we will assign to Tx/Rx Cleanup
++ * for the separate queues...where Rx Cleanup >= Tx Cleanup.
++ * Right now, we simply care about how many we'll get; we'll
++ * set them up later while requesting irq's.
++ */
++ while (vectors >= vector_threshold) {
++ err = pci_enable_msix(adapter->pdev, adapter->msix_entries,
++ vectors);
++ if (!err) /* Success in acquiring all requested vectors. */
++ break;
++ else if (err < 0)
++ vectors = 0; /* Nasty failure, quit now */
++ else /* err == number of vectors we should try again with */
++ vectors = err;
++ }
++
++ if (vectors < vector_threshold) {
++ /* Can't allocate enough MSI-X interrupts? Oh well.
++ * This just means we'll go with either a single MSI
++ * vector or fall back to legacy interrupts.
++ */
++ DPRINTK(HW, DEBUG, "Unable to allocate MSI-X interrupts\n");
++ adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
++ kfree(adapter->msix_entries);
++ adapter->msix_entries = NULL;
++ adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
++ adapter->num_tx_queues = 1;
++ adapter->num_rx_queues = 1;
++ } else {
++ adapter->flags |= IXGBE_FLAG_MSIX_ENABLED; /* Woot! */
++ adapter->num_msix_vectors = vectors;
++ }
++}
++
++static void __devinit ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
++{
++ int nrq, ntq;
++ int feature_mask = 0, rss_i, rss_m;
++
++ /* Number of supported queues */
++ switch (adapter->hw.mac.type) {
++ case ixgbe_mac_82598EB:
++ rss_i = adapter->ring_feature[RING_F_RSS].indices;
++ rss_m = 0;
++ feature_mask |= IXGBE_FLAG_RSS_ENABLED;
++
++ switch (adapter->flags & feature_mask) {
++ case (IXGBE_FLAG_RSS_ENABLED):
++ rss_m = 0xF;
++ nrq = rss_i;
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ ntq = rss_i;
++#else
++ ntq = 1;
++#endif
++ break;
++ case 0:
++ default:
++ rss_i = 0;
++ rss_m = 0;
++ nrq = 1;
++ ntq = 1;
++ break;
++ }
++
++ adapter->ring_feature[RING_F_RSS].indices = rss_i;
++ adapter->ring_feature[RING_F_RSS].mask = rss_m;
++ break;
++ default:
++ nrq = 1;
++ ntq = 1;
++ break;
++ }
++
++ adapter->num_rx_queues = nrq;
++ adapter->num_tx_queues = ntq;
++}
++
++/**
++ * ixgbe_cache_ring_register - Descriptor ring to register mapping
++ * @adapter: board private structure to initialize
++ *
++ * Once we know the feature-set enabled for the device, we'll cache
++ * the register offset the descriptor ring is assigned to.
++ **/
++static void __devinit ixgbe_cache_ring_register(struct ixgbe_adapter *adapter)
++{
++ /* TODO: Remove all uses of the indices in the cases where multiple
++ * features are OR'd together, if the feature set makes sense.
++ */
++ int feature_mask = 0, rss_i;
++ int i, txr_idx, rxr_idx;
++
++ /* Number of supported queues */
++ switch (adapter->hw.mac.type) {
++ case ixgbe_mac_82598EB:
++ rss_i = adapter->ring_feature[RING_F_RSS].indices;
++ txr_idx = 0;
++ rxr_idx = 0;
++ feature_mask |= IXGBE_FLAG_RSS_ENABLED;
++ switch (adapter->flags & feature_mask) {
++ case (IXGBE_FLAG_RSS_ENABLED):
++ for (i = 0; i < adapter->num_rx_queues; i++)
++ adapter->rx_ring[i].reg_idx = i;
++ for (i = 0; i < adapter->num_tx_queues; i++)
++ adapter->tx_ring[i].reg_idx = i;
++ break;
++ case 0:
++ default:
++ break;
++ }
++ break;
++ default:
++ break;
++ }
++}
++
+ /**
+ * ixgbe_alloc_queues - Allocate memory for all rings
+ * @adapter: board private structure to initialize
+@@ -1612,25 +2219,167 @@ static int __devinit ixgbe_alloc_queues(struct ixgbe_adapter *adapter)
+ adapter->tx_ring = kcalloc(adapter->num_tx_queues,
+ sizeof(struct ixgbe_ring), GFP_KERNEL);
+ if (!adapter->tx_ring)
+- return -ENOMEM;
+-
+- for (i = 0; i < adapter->num_tx_queues; i++)
+- adapter->tx_ring[i].count = IXGBE_DEFAULT_TXD;
++ goto err_tx_ring_allocation;
+
+ adapter->rx_ring = kcalloc(adapter->num_rx_queues,
+ sizeof(struct ixgbe_ring), GFP_KERNEL);
+- if (!adapter->rx_ring) {
+- kfree(adapter->tx_ring);
+- return -ENOMEM;
+- }
++ if (!adapter->rx_ring)
++ goto err_rx_ring_allocation;
+
++ for (i = 0; i < adapter->num_tx_queues; i++) {
++ adapter->tx_ring[i].count = IXGBE_DEFAULT_TXD;
++ adapter->tx_ring[i].queue_index = i;
++ }
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+- adapter->rx_ring[i].adapter = adapter;
+- adapter->rx_ring[i].itr_register = IXGBE_EITR(i);
+ adapter->rx_ring[i].count = IXGBE_DEFAULT_RXD;
++ adapter->rx_ring[i].queue_index = i;
++ }
++
++ ixgbe_cache_ring_register(adapter);
++
++ return 0;
++
++err_rx_ring_allocation:
++ kfree(adapter->tx_ring);
++err_tx_ring_allocation:
++ return -ENOMEM;
++}
++
++/**
++ * ixgbe_set_interrupt_capability - set MSI-X or MSI if supported
++ * @adapter: board private structure to initialize
++ *
++ * Attempt to configure the interrupts using the best available
++ * capabilities of the hardware and the kernel.
++ **/
++static int __devinit ixgbe_set_interrupt_capability(struct ixgbe_adapter
++ *adapter)
++{
++ int err = 0;
++ int vector, v_budget;
++
++ /*
++ * It's easy to be greedy for MSI-X vectors, but it really
++ * doesn't do us much good if we have a lot more vectors
++ * than CPU's. So let's be conservative and only ask for
++ * (roughly) twice the number of vectors as there are CPU's.
++ */
++ v_budget = min(adapter->num_rx_queues + adapter->num_tx_queues,
++ (int)(num_online_cpus() * 2)) + NON_Q_VECTORS;
++
++ /*
++ * At the same time, hardware can only support a maximum of
++ * MAX_MSIX_COUNT vectors. With features such as RSS and VMDq,
++ * we can easily reach upwards of 64 Rx descriptor queues and
++ * 32 Tx queues. Thus, we cap it off in those rare cases where
++ * the cpu count also exceeds our vector limit.
++ */
++ v_budget = min(v_budget, MAX_MSIX_COUNT);
++
++ /* A failure in MSI-X entry allocation isn't fatal, but it does
++ * mean we disable MSI-X capabilities of the adapter. */
++ adapter->msix_entries = kcalloc(v_budget,
++ sizeof(struct msix_entry), GFP_KERNEL);
++ if (!adapter->msix_entries) {
++ adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
++ ixgbe_set_num_queues(adapter);
++ kfree(adapter->tx_ring);
++ kfree(adapter->rx_ring);
++ err = ixgbe_alloc_queues(adapter);
++ if (err) {
++ DPRINTK(PROBE, ERR, "Unable to allocate memory "
++ "for queues\n");
++ goto out;
++ }
++
++ goto try_msi;
++ }
++
++ for (vector = 0; vector < v_budget; vector++)
++ adapter->msix_entries[vector].entry = vector;
++
++ ixgbe_acquire_msix_vectors(adapter, v_budget);
++
++ if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
++ goto out;
++
++try_msi:
++ err = pci_enable_msi(adapter->pdev);
++ if (!err) {
++ adapter->flags |= IXGBE_FLAG_MSI_ENABLED;
++ } else {
++ DPRINTK(HW, DEBUG, "Unable to allocate MSI interrupt, "
++ "falling back to legacy. Error: %d\n", err);
++ /* reset err */
++ err = 0;
++ }
++
++out:
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ /* Notify the stack of the (possibly) reduced Tx Queue count. */
++ adapter->netdev->egress_subqueue_count = adapter->num_tx_queues;
++#endif
++
++ return err;
++}
++
++static void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter)
++{
++ if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
++ adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
++ pci_disable_msix(adapter->pdev);
++ kfree(adapter->msix_entries);
++ adapter->msix_entries = NULL;
++ } else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) {
++ adapter->flags &= ~IXGBE_FLAG_MSI_ENABLED;
++ pci_disable_msi(adapter->pdev);
+ }
++ return;
++}
++
++/**
++ * ixgbe_init_interrupt_scheme - Determine proper interrupt scheme
++ * @adapter: board private structure to initialize
++ *
++ * We determine which interrupt scheme to use based on...
++ * - Kernel support (MSI, MSI-X)
++ * - which can be user-defined (via MODULE_PARAM)
++ * - Hardware queue count (num_*_queues)
++ * - defined by miscellaneous hardware support/features (RSS, etc.)
++ **/
++static int __devinit ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter)
++{
++ int err;
++
++ /* Number of supported queues */
++ ixgbe_set_num_queues(adapter);
++
++ err = ixgbe_alloc_queues(adapter);
++ if (err) {
++ DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n");
++ goto err_alloc_queues;
++ }
++
++ err = ixgbe_set_interrupt_capability(adapter);
++ if (err) {
++ DPRINTK(PROBE, ERR, "Unable to setup interrupt capabilities\n");
++ goto err_set_interrupt;
++ }
++
++ DPRINTK(DRV, INFO, "Multiqueue %s: Rx Queue count = %u, "
++ "Tx Queue count = %u\n",
++ (adapter->num_rx_queues > 1) ? "Enabled" :
++ "Disabled", adapter->num_rx_queues, adapter->num_tx_queues);
++
++ set_bit(__IXGBE_DOWN, &adapter->state);
+
+ return 0;
++
++err_set_interrupt:
++ kfree(adapter->tx_ring);
++ kfree(adapter->rx_ring);
++err_alloc_queues:
++ return err;
+ }
+
+ /**
+@@ -1645,11 +2394,22 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
+ {
+ struct ixgbe_hw *hw = &adapter->hw;
+ struct pci_dev *pdev = adapter->pdev;
++ unsigned int rss;
++
++ /* Set capability flags */
++ rss = min(IXGBE_MAX_RSS_INDICES, (int)num_online_cpus());
++ adapter->ring_feature[RING_F_RSS].indices = rss;
++ adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
++
++ /* Enable Dynamic interrupt throttling by default */
++ adapter->rx_eitr = 1;
++ adapter->tx_eitr = 1;
+
+ /* default flow control settings */
+ hw->fc.original_type = ixgbe_fc_full;
+ hw->fc.type = ixgbe_fc_full;
+
++ /* select 10G link by default */
+ hw->mac.link_mode_select = IXGBE_AUTOC_LMS_10G_LINK_NO_AN;
+ if (hw->mac.ops.reset(hw)) {
+ dev_err(&pdev->dev, "HW Init failed\n");
+@@ -1667,16 +2427,9 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
+ return -EIO;
+ }
+
+- /* Set the default values */
+- adapter->num_rx_queues = IXGBE_DEFAULT_RXQ;
+- adapter->num_tx_queues = 1;
++ /* enable rx csum by default */
+ adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED;
+
+- if (ixgbe_alloc_queues(adapter)) {
+- dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
+- return -ENOMEM;
+- }
+-
+ set_bit(__IXGBE_DOWN, &adapter->state);
+
+ return 0;
+@@ -1716,7 +2469,6 @@ int ixgbe_setup_tx_resources(struct ixgbe_adapter *adapter,
+ return -ENOMEM;
+ }
+
+- txdr->adapter = adapter;
+ txdr->next_to_use = 0;
+ txdr->next_to_clean = 0;
+ txdr->work_limit = txdr->count;
+@@ -1735,7 +2487,7 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
+ struct ixgbe_ring *rxdr)
+ {
+ struct pci_dev *pdev = adapter->pdev;
+- int size, desc_len;
++ int size;
+
+ size = sizeof(struct ixgbe_rx_buffer) * rxdr->count;
+ rxdr->rx_buffer_info = vmalloc(size);
+@@ -1746,10 +2498,8 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
+ }
+ memset(rxdr->rx_buffer_info, 0, size);
+
+- desc_len = sizeof(union ixgbe_adv_rx_desc);
+-
+ /* Round up to nearest 4K */
+- rxdr->size = rxdr->count * desc_len;
++ rxdr->size = rxdr->count * sizeof(union ixgbe_adv_rx_desc);
+ rxdr->size = ALIGN(rxdr->size, 4096);
+
+ rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
+@@ -1763,7 +2513,6 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
+
+ rxdr->next_to_clean = 0;
+ rxdr->next_to_use = 0;
+- rxdr->adapter = adapter;
+
+ return 0;
+ }
+@@ -1841,8 +2590,7 @@ static void ixgbe_free_all_rx_resources(struct ixgbe_adapter *adapter)
+ }
+
+ /**
+- * ixgbe_setup_all_tx_resources - wrapper to allocate Tx resources
+- * (Descriptors) for all queues
++ * ixgbe_setup_all_tx_resources - allocate all queues Tx resources
+ * @adapter: board private structure
+ *
+ * If this function returns with an error, then it's possible one or
+@@ -1868,8 +2616,7 @@ static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter)
+ }
+
+ /**
+- * ixgbe_setup_all_rx_resources - wrapper to allocate Rx resources
+- * (Descriptors) for all queues
++ * ixgbe_setup_all_rx_resources - allocate all queues Rx resources
+ * @adapter: board private structure
+ *
+ * If this function returns with an error, then it's possible one or
+@@ -1911,6 +2658,9 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
+ (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE))
+ return -EINVAL;
+
++ DPRINTK(PROBE, INFO, "changing MTU from %d to %d\n",
++ netdev->mtu, new_mtu);
++ /* must set new MTU before calling down or up */
+ netdev->mtu = new_mtu;
+
+ if (netif_running(netdev))
+@@ -1935,23 +2685,16 @@ static int ixgbe_open(struct net_device *netdev)
+ {
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ int err;
+- u32 num_rx_queues = adapter->num_rx_queues;
+
+ /* disallow open during test */
+ if (test_bit(__IXGBE_TESTING, &adapter->state))
+ return -EBUSY;
+
+-try_intr_reinit:
+ /* allocate transmit descriptors */
+ err = ixgbe_setup_all_tx_resources(adapter);
+ if (err)
+ goto err_setup_tx;
+
+- if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
+- num_rx_queues = 1;
+- adapter->num_rx_queues = num_rx_queues;
+- }
+-
+ /* allocate receive descriptors */
+ err = ixgbe_setup_all_rx_resources(adapter);
+ if (err)
+@@ -1959,31 +2702,10 @@ try_intr_reinit:
+
+ ixgbe_configure(adapter);
+
+- err = ixgbe_request_irq(adapter, &num_rx_queues);
++ err = ixgbe_request_irq(adapter);
+ if (err)
+ goto err_req_irq;
+
+- /* ixgbe_request might have reduced num_rx_queues */
+- if (num_rx_queues < adapter->num_rx_queues) {
+- /* We didn't get MSI-X, so we need to release everything,
+- * set our Rx queue count to num_rx_queues, and redo the
+- * whole init process.
+- */
+- ixgbe_free_irq(adapter);
+- if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) {
+- pci_disable_msi(adapter->pdev);
+- adapter->flags &= ~IXGBE_FLAG_MSI_ENABLED;
+- }
+- ixgbe_free_all_rx_resources(adapter);
+- ixgbe_free_all_tx_resources(adapter);
+- adapter->num_rx_queues = num_rx_queues;
+-
+- /* Reset the hardware, and start over. */
+- ixgbe_reset(adapter);
+-
+- goto try_intr_reinit;
+- }
+-
+ err = ixgbe_up_complete(adapter);
+ if (err)
+ goto err_up;
+@@ -2119,6 +2841,9 @@ static void ixgbe_watchdog(unsigned long data)
+ struct net_device *netdev = adapter->netdev;
+ bool link_up;
+ u32 link_speed = 0;
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ int i;
++#endif
+
+ adapter->hw.mac.ops.check_link(&adapter->hw, &(link_speed), &link_up);
+
+@@ -2140,6 +2865,10 @@ static void ixgbe_watchdog(unsigned long data)
+
+ netif_carrier_on(netdev);
+ netif_wake_queue(netdev);
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ for (i = 0; i < adapter->num_tx_queues; i++)
++ netif_wake_subqueue(netdev, i);
++#endif
+ } else {
+ /* Force detection of hung controller */
+ adapter->detect_tx_hung = true;
+@@ -2154,10 +2883,23 @@ static void ixgbe_watchdog(unsigned long data)
+
+ ixgbe_update_stats(adapter);
+
+- /* Reset the timer */
+- if (!test_bit(__IXGBE_DOWN, &adapter->state))
++ if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
++ /* Cause software interrupt to ensure rx rings are cleaned */
++ if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
++ u32 eics =
++ (1 << (adapter->num_msix_vectors - NON_Q_VECTORS)) - 1;
++ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, eics);
++ } else {
++ /* for legacy and MSI interrupts don't set any bits that
++ * are enabled for EIAM, because this operation would
++ * set *both* EIMS and EICS for any bit in EIAM */
++ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS,
++ (IXGBE_EICS_TCP_TIMER | IXGBE_EICS_OTHER));
++ }
++ /* Reset the timer */
+ mod_timer(&adapter->watchdog_timer,
+ round_jiffies(jiffies + 2 * HZ));
++ }
+ }
+
+ static int ixgbe_tso(struct ixgbe_adapter *adapter,
+@@ -2170,7 +2912,6 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter,
+ struct ixgbe_tx_buffer *tx_buffer_info;
+ u32 vlan_macip_lens = 0, type_tucmd_mlhl = 0;
+ u32 mss_l4len_idx = 0, l4len;
+- *hdr_len = 0;
+
+ if (skb_is_gso(skb)) {
+ if (skb_header_cloned(skb)) {
+@@ -2454,7 +3195,11 @@ static int __ixgbe_maybe_stop_tx(struct net_device *netdev,
+ {
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ netif_stop_subqueue(netdev, tx_ring->queue_index);
++#else
+ netif_stop_queue(netdev);
++#endif
+ /* Herbert's original patch had:
+ * smp_mb__after_netif_stop_queue();
+ * but since that doesn't exist yet, just open code it. */
+@@ -2466,7 +3211,11 @@ static int __ixgbe_maybe_stop_tx(struct net_device *netdev,
+ return -EBUSY;
+
+ /* A reprieve! - use start_queue because it doesn't call schedule */
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ netif_wake_subqueue(netdev, tx_ring->queue_index);
++#else
+ netif_wake_queue(netdev);
++#endif
+ ++adapter->restart_queue;
+ return 0;
+ }
+@@ -2487,15 +3236,18 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ unsigned int len = skb->len;
+ unsigned int first;
+ unsigned int tx_flags = 0;
+- u8 hdr_len;
+- int tso;
++ u8 hdr_len = 0;
++ int r_idx = 0, tso;
+ unsigned int mss = 0;
+ int count = 0;
+ unsigned int f;
+ unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
+ len -= skb->data_len;
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ r_idx = (adapter->num_tx_queues - 1) & skb->queue_mapping;
++#endif
++ tx_ring = &adapter->tx_ring[r_idx];
+
+- tx_ring = adapter->tx_ring;
+
+ if (skb->len <= 0) {
+ dev_kfree_skb(skb);
+@@ -2604,6 +3356,31 @@ static void ixgbe_netpoll(struct net_device *netdev)
+ #endif
+
+ /**
++ * ixgbe_napi_add_all - prep napi structs for use
++ * @adapter: private struct
++ * helper function to napi_add each possible q_vector->napi
++ */
++static void ixgbe_napi_add_all(struct ixgbe_adapter *adapter)
++{
++ int i, q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
++ int (*poll)(struct napi_struct *, int);
++
++ if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
++ poll = &ixgbe_clean_rxonly;
++ } else {
++ poll = &ixgbe_poll;
++ /* only one q_vector for legacy modes */
++ q_vectors = 1;
++ }
++
++ for (i = 0; i < q_vectors; i++) {
++ struct ixgbe_q_vector *q_vector = &adapter->q_vector[i];
++ netif_napi_add(adapter->netdev, &q_vector->napi,
++ (*poll), 64);
++ }
++}
++
++/**
+ * ixgbe_probe - Device Initialization Routine
+ * @pdev: PCI device information struct
+ * @ent: entry in ixgbe_pci_tbl
+@@ -2654,8 +3431,13 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
+ }
+
+ pci_set_master(pdev);
++ pci_save_state(pdev);
+
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ netdev = alloc_etherdev_mq(sizeof(struct ixgbe_adapter), MAX_TX_QUEUES);
++#else
+ netdev = alloc_etherdev(sizeof(struct ixgbe_adapter));
++#endif
+ if (!netdev) {
+ err = -ENOMEM;
+ goto err_alloc_etherdev;
+@@ -2696,7 +3478,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
+ ixgbe_set_ethtool_ops(netdev);
+ netdev->tx_timeout = &ixgbe_tx_timeout;
+ netdev->watchdog_timeo = 5 * HZ;
+- netif_napi_add(netdev, &adapter->napi, ixgbe_clean, 64);
+ netdev->vlan_rx_register = ixgbe_vlan_rx_register;
+ netdev->vlan_rx_add_vid = ixgbe_vlan_rx_add_vid;
+ netdev->vlan_rx_kill_vid = ixgbe_vlan_rx_kill_vid;
+@@ -2719,6 +3500,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
+
+ /* Setup hw api */
+ memcpy(&hw->mac.ops, ii->mac_ops, sizeof(hw->mac.ops));
++ hw->mac.type = ii->mac;
+
+ err = ii->get_invariants(hw);
+ if (err)
+@@ -2741,6 +3523,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
+ if (pci_using_dac)
+ netdev->features |= NETIF_F_HIGHDMA;
+
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ netdev->features |= NETIF_F_MULTI_QUEUE;
++#endif
+
+ /* make sure the EEPROM is good */
+ if (ixgbe_validate_eeprom_checksum(hw, NULL) < 0) {
+@@ -2770,9 +3555,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
+ hw->fc.low_water = IXGBE_DEFAULT_FCRTL;
+ hw->fc.pause_time = IXGBE_DEFAULT_FCPAUSE;
+
+- /* Interrupt Throttle Rate */
+- adapter->rx_eitr = (1000000 / IXGBE_DEFAULT_ITR_RX_USECS);
+- adapter->tx_eitr = (1000000 / IXGBE_DEFAULT_ITR_TX_USECS);
++ err = ixgbe_init_interrupt_scheme(adapter);
++ if (err)
++ goto err_sw_init;
+
+ /* print bus type/speed/width info */
+ pci_read_config_word(pdev, IXGBE_PCI_LINK_STATUS, &link_status);
+@@ -2808,12 +3593,27 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
+
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ for (i = 0; i < adapter->num_tx_queues; i++)
++ netif_stop_subqueue(netdev, i);
++#endif
++
++ ixgbe_napi_add_all(adapter);
+
+ strcpy(netdev->name, "eth%d");
+ err = register_netdev(netdev);
+ if (err)
+ goto err_register;
+
++#ifdef CONFIG_DCA
++ if (dca_add_requester(&pdev->dev) == 0) {
++ adapter->flags |= IXGBE_FLAG_DCA_ENABLED;
++ /* always use CB2 mode, difference is masked
++ * in the CB driver */
++ IXGBE_WRITE_REG(hw, IXGBE_DCA_CTRL, 2);
++ ixgbe_setup_dca(adapter);
++ }
++#endif
+
+ dev_info(&pdev->dev, "Intel(R) 10 Gigabit Network Connection\n");
+ cards_found++;
+@@ -2823,6 +3623,7 @@ err_register:
+ ixgbe_release_hw_control(adapter);
+ err_hw_init:
+ err_sw_init:
++ ixgbe_reset_interrupt_capability(adapter);
+ err_eeprom:
+ iounmap(hw->hw_addr);
+ err_ioremap:
+@@ -2854,16 +3655,27 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
+
+ flush_scheduled_work();
+
++#ifdef CONFIG_DCA
++ if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
++ adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED;
++ dca_remove_requester(&pdev->dev);
++ IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 1);
++ }
++
++#endif
+ unregister_netdev(netdev);
+
+- ixgbe_release_hw_control(adapter);
++ ixgbe_reset_interrupt_capability(adapter);
+
+- kfree(adapter->tx_ring);
+- kfree(adapter->rx_ring);
++ ixgbe_release_hw_control(adapter);
+
+ iounmap(adapter->hw.hw_addr);
+ pci_release_regions(pdev);
+
++ DPRINTK(PROBE, INFO, "complete\n");
++ kfree(adapter->tx_ring);
++ kfree(adapter->rx_ring);
++
+ free_netdev(netdev);
+
+ pci_disable_device(pdev);
+@@ -2910,6 +3722,7 @@ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev)
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+ pci_set_master(pdev);
++ pci_restore_state(pdev);
+
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ pci_enable_wake(pdev, PCI_D3cold, 0);
+@@ -2975,6 +3788,10 @@ static int __init ixgbe_init_module(void)
+
+ printk(KERN_INFO "%s: %s\n", ixgbe_driver_name, ixgbe_copyright);
+
++#ifdef CONFIG_DCA
++ dca_register_notify(&dca_notifier);
++
++#endif
+ ret = pci_register_driver(&ixgbe_driver);
+ return ret;
+ }
+@@ -2988,8 +3805,25 @@ module_init(ixgbe_init_module);
+ **/
+ static void __exit ixgbe_exit_module(void)
+ {
++#ifdef CONFIG_DCA
++ dca_unregister_notify(&dca_notifier);
++#endif
+ pci_unregister_driver(&ixgbe_driver);
+ }
++
++#ifdef CONFIG_DCA
++static int ixgbe_notify_dca(struct notifier_block *nb, unsigned long event,
++ void *p)
++{
++ int ret_val;
++
++ ret_val = driver_for_each_device(&ixgbe_driver.driver, NULL, &event,
++ __ixgbe_notify_dca);
++
++ return ret_val ? NOTIFY_BAD : NOTIFY_DONE;
++}
++#endif /* CONFIG_DCA */
++
+ module_exit(ixgbe_exit_module);
+
+ /* ixgbe_main.c */
+diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c
+index 5c154fe..0794482 100644
+--- a/drivers/net/jazzsonic.c
++++ b/drivers/net/jazzsonic.c
+@@ -249,6 +249,7 @@ out:
+ MODULE_DESCRIPTION("Jazz SONIC ethernet driver");
+ module_param(sonic_debug, int, 0);
+ MODULE_PARM_DESC(sonic_debug, "jazzsonic debug level (1-4)");
++MODULE_ALIAS("platform:jazzsonic");
+
+ #include "sonic.c"
+
+@@ -271,6 +272,7 @@ static struct platform_driver jazz_sonic_driver = {
+ .remove = __devexit_p(jazz_sonic_device_remove),
+ .driver = {
+ .name = jazz_sonic_string,
++ .owner = THIS_MODULE,
+ },
+ };
+
+diff --git a/drivers/net/korina.c b/drivers/net/korina.c
+new file mode 100644
+index 0000000..e185763
+--- /dev/null
++++ b/drivers/net/korina.c
+@@ -0,0 +1,1230 @@
++/*
++ * Driver for the IDT RC32434 (Korina) on-chip ethernet controller.
++ *
++ * Copyright 2004 IDT Inc. (rischelp at idt.com)
++ * Copyright 2006 Felix Fietkau <nbd at openwrt.org>
++ * Copyright 2008 Florian Fainelli <florian at openwrt.org>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Writing to a DMA status register:
++ *
++ * When writing to the status register, you should mask the bit you have
++ * been testing the status register with. Both Tx and Rx DMA registers
++ * should stick to this procedure.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/moduleparam.h>
++#include <linux/sched.h>
++#include <linux/ctype.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/in.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/delay.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
++#include <linux/errno.h>
++#include <linux/platform_device.h>
++#include <linux/mii.h>
++#include <linux/ethtool.h>
++#include <linux/crc32.h>
++
++#include <asm/bootinfo.h>
++#include <asm/system.h>
++#include <asm/bitops.h>
++#include <asm/pgtable.h>
++#include <asm/segment.h>
++#include <asm/io.h>
++#include <asm/dma.h>
++
++#include <asm/mach-rc32434/rb.h>
++#include <asm/mach-rc32434/rc32434.h>
++#include <asm/mach-rc32434/eth.h>
++#include <asm/mach-rc32434/dma_v.h>
++
++#define DRV_NAME "korina"
++#define DRV_VERSION "0.10"
++#define DRV_RELDATE "04Mar2008"
++
++#define STATION_ADDRESS_HIGH(dev) (((dev)->dev_addr[0] << 8) | \
++ ((dev)->dev_addr[1]))
++#define STATION_ADDRESS_LOW(dev) (((dev)->dev_addr[2] << 24) | \
++ ((dev)->dev_addr[3] << 16) | \
++ ((dev)->dev_addr[4] << 8) | \
++ ((dev)->dev_addr[5]))
++
++#define MII_CLOCK 1250000 /* no more than 2.5MHz */
++
++/* the following must be powers of two */
++#define KORINA_NUM_RDS 64 /* number of receive descriptors */
++#define KORINA_NUM_TDS 64 /* number of transmit descriptors */
++
++#define KORINA_RBSIZE 536 /* size of one resource buffer = Ether MTU */
++#define KORINA_RDS_MASK (KORINA_NUM_RDS - 1)
++#define KORINA_TDS_MASK (KORINA_NUM_TDS - 1)
++#define RD_RING_SIZE (KORINA_NUM_RDS * sizeof(struct dma_desc))
++#define TD_RING_SIZE (KORINA_NUM_TDS * sizeof(struct dma_desc))
++
++#define TX_TIMEOUT (6000 * HZ / 1000)
++
++enum chain_status { desc_filled, desc_empty };
++#define IS_DMA_FINISHED(X) (((X) & (DMA_DESC_FINI)) != 0)
++#define IS_DMA_DONE(X) (((X) & (DMA_DESC_DONE)) != 0)
++#define RCVPKT_LENGTH(X) (((X) & ETH_RX_LEN) >> ETH_RX_LEN_BIT)
++
++/* Information that need to be kept for each board. */
++struct korina_private {
++ struct eth_regs *eth_regs;
++ struct dma_reg *rx_dma_regs;
++ struct dma_reg *tx_dma_regs;
++ struct dma_desc *td_ring; /* transmit descriptor ring */
++ struct dma_desc *rd_ring; /* receive descriptor ring */
++
++ struct sk_buff *tx_skb[KORINA_NUM_TDS];
++ struct sk_buff *rx_skb[KORINA_NUM_RDS];
++
++ int rx_next_done;
++ int rx_chain_head;
++ int rx_chain_tail;
++ enum chain_status rx_chain_status;
++
++ int tx_next_done;
++ int tx_chain_head;
++ int tx_chain_tail;
++ enum chain_status tx_chain_status;
++ int tx_count;
++ int tx_full;
++
++ int rx_irq;
++ int tx_irq;
++ int ovr_irq;
++ int und_irq;
++
++ spinlock_t lock; /* NIC xmit lock */
++
++ int dma_halt_cnt;
++ int dma_run_cnt;
++ struct napi_struct napi;
++ struct mii_if_info mii_if;
++ struct net_device *dev;
++ int phy_addr;
++};
++
++extern unsigned int idt_cpu_freq;
++
++static inline void korina_start_dma(struct dma_reg *ch, u32 dma_addr)
++{
++ writel(0, &ch->dmandptr);
++ writel(dma_addr, &ch->dmadptr);
++}
++
++static inline void korina_abort_dma(struct net_device *dev,
++ struct dma_reg *ch)
++{
++ if (readl(&ch->dmac) & DMA_CHAN_RUN_BIT) {
++ writel(0x10, &ch->dmac);
++
++ while (!(readl(&ch->dmas) & DMA_STAT_HALT))
++ dev->trans_start = jiffies;
++
++ writel(0, &ch->dmas);
++ }
++
++ writel(0, &ch->dmadptr);
++ writel(0, &ch->dmandptr);
++}
++
++static inline void korina_chain_dma(struct dma_reg *ch, u32 dma_addr)
++{
++ writel(dma_addr, &ch->dmandptr);
++}
++
++static void korina_abort_tx(struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++
++ korina_abort_dma(dev, lp->tx_dma_regs);
++}
++
++static void korina_abort_rx(struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++
++ korina_abort_dma(dev, lp->rx_dma_regs);
++}
++
++static void korina_start_rx(struct korina_private *lp,
++ struct dma_desc *rd)
++{
++ korina_start_dma(lp->rx_dma_regs, CPHYSADDR(rd));
++}
++
++static void korina_chain_rx(struct korina_private *lp,
++ struct dma_desc *rd)
++{
++ korina_chain_dma(lp->rx_dma_regs, CPHYSADDR(rd));
++}
++
++/* transmit packet */
++static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ unsigned long flags;
++ u32 length;
++ u32 chain_index;
++ struct dma_desc *td;
++
++ spin_lock_irqsave(&lp->lock, flags);
++
++ td = &lp->td_ring[lp->tx_chain_tail];
++
++ /* stop queue when full, drop pkts if queue already full */
++ if (lp->tx_count >= (KORINA_NUM_TDS - 2)) {
++ lp->tx_full = 1;
++
++ if (lp->tx_count == (KORINA_NUM_TDS - 2))
++ netif_stop_queue(dev);
++ else {
++ dev->stats.tx_dropped++;
++ dev_kfree_skb_any(skb);
++ spin_unlock_irqrestore(&lp->lock, flags);
++
++ return NETDEV_TX_BUSY;
++ }
++ }
++
++ lp->tx_count++;
++
++ lp->tx_skb[lp->tx_chain_tail] = skb;
++
++ length = skb->len;
++ dma_cache_wback((u32)skb->data, skb->len);
++
++ /* Setup the transmit descriptor. */
++ dma_cache_inv((u32) td, sizeof(*td));
++ td->ca = CPHYSADDR(skb->data);
++ chain_index = (lp->tx_chain_tail - 1) &
++ KORINA_TDS_MASK;
++
++ if (readl(&(lp->tx_dma_regs->dmandptr)) == 0) {
++ if (lp->tx_chain_status == desc_empty) {
++ /* Update tail */
++ td->control = DMA_COUNT(length) |
++ DMA_DESC_COF | DMA_DESC_IOF;
++ /* Move tail */
++ lp->tx_chain_tail = chain_index;
++ /* Write to NDPTR */
++ writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]),
++ &lp->tx_dma_regs->dmandptr);
++ /* Move head to tail */
++ lp->tx_chain_head = lp->tx_chain_tail;
++ } else {
++ /* Update tail */
++ td->control = DMA_COUNT(length) |
++ DMA_DESC_COF | DMA_DESC_IOF;
++ /* Link to prev */
++ lp->td_ring[chain_index].control &=
++ ~DMA_DESC_COF;
++ /* Link to prev */
++ lp->td_ring[chain_index].link = CPHYSADDR(td);
++ /* Move tail */
++ lp->tx_chain_tail = chain_index;
++ /* Write to NDPTR */
++ writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]),
++ &(lp->tx_dma_regs->dmandptr));
++ /* Move head to tail */
++ lp->tx_chain_head = lp->tx_chain_tail;
++ lp->tx_chain_status = desc_empty;
++ }
++ } else {
++ if (lp->tx_chain_status == desc_empty) {
++ /* Update tail */
++ td->control = DMA_COUNT(length) |
++ DMA_DESC_COF | DMA_DESC_IOF;
++ /* Move tail */
++ lp->tx_chain_tail = chain_index;
++ lp->tx_chain_status = desc_filled;
++ netif_stop_queue(dev);
++ } else {
++ /* Update tail */
++ td->control = DMA_COUNT(length) |
++ DMA_DESC_COF | DMA_DESC_IOF;
++ lp->td_ring[chain_index].control &=
++ ~DMA_DESC_COF;
++ lp->td_ring[chain_index].link = CPHYSADDR(td);
++ lp->tx_chain_tail = chain_index;
++ }
++ }
++ dma_cache_wback((u32) td, sizeof(*td));
++
++ dev->trans_start = jiffies;
++ spin_unlock_irqrestore(&lp->lock, flags);
++
++ return NETDEV_TX_OK;
++}
++
++static int mdio_read(struct net_device *dev, int mii_id, int reg)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ int ret;
++
++ mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8);
++
++ writel(0, &lp->eth_regs->miimcfg);
++ writel(0, &lp->eth_regs->miimcmd);
++ writel(mii_id | reg, &lp->eth_regs->miimaddr);
++ writel(ETH_MII_CMD_SCN, &lp->eth_regs->miimcmd);
++
++ ret = (int)(readl(&lp->eth_regs->miimrdd));
++ return ret;
++}
++
++static void mdio_write(struct net_device *dev, int mii_id, int reg, int val)
++{
++ struct korina_private *lp = netdev_priv(dev);
++
++ mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8);
++
++ writel(0, &lp->eth_regs->miimcfg);
++ writel(1, &lp->eth_regs->miimcmd);
++ writel(mii_id | reg, &lp->eth_regs->miimaddr);
++ writel(ETH_MII_CMD_SCN, &lp->eth_regs->miimcmd);
++ writel(val, &lp->eth_regs->miimwtd);
++}
++
++/* Ethernet Rx DMA interrupt */
++static irqreturn_t korina_rx_dma_interrupt(int irq, void *dev_id)
++{
++ struct net_device *dev = dev_id;
++ struct korina_private *lp = netdev_priv(dev);
++ u32 dmas, dmasm;
++ irqreturn_t retval;
++
++ dmas = readl(&lp->rx_dma_regs->dmas);
++ if (dmas & (DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR)) {
++ netif_rx_schedule_prep(dev, &lp->napi);
++
++ dmasm = readl(&lp->rx_dma_regs->dmasm);
++ writel(dmasm | (DMA_STAT_DONE |
++ DMA_STAT_HALT | DMA_STAT_ERR),
++ &lp->rx_dma_regs->dmasm);
++
++ if (dmas & DMA_STAT_ERR)
++ printk(KERN_ERR DRV_NAME "%s: DMA error\n", dev->name);
++
++ retval = IRQ_HANDLED;
++ } else
++ retval = IRQ_NONE;
++
++ return retval;
++}
++
++static int korina_rx(struct net_device *dev, int limit)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ struct dma_desc *rd = &lp->rd_ring[lp->rx_next_done];
++ struct sk_buff *skb, *skb_new;
++ u8 *pkt_buf;
++ u32 devcs, pkt_len, dmas, rx_free_desc;
++ int count;
++
++ dma_cache_inv((u32)rd, sizeof(*rd));
++
++ for (count = 0; count < limit; count++) {
++
++ devcs = rd->devcs;
++
++ /* Update statistics counters */
++ if (devcs & ETH_RX_CRC)
++ dev->stats.rx_crc_errors++;
++ if (devcs & ETH_RX_LOR)
++ dev->stats.rx_length_errors++;
++ if (devcs & ETH_RX_LE)
++ dev->stats.rx_length_errors++;
++ if (devcs & ETH_RX_OVR)
++ dev->stats.rx_over_errors++;
++ if (devcs & ETH_RX_CV)
++ dev->stats.rx_frame_errors++;
++ if (devcs & ETH_RX_CES)
++ dev->stats.rx_length_errors++;
++ if (devcs & ETH_RX_MP)
++ dev->stats.multicast++;
++
++ if ((devcs & ETH_RX_LD) != ETH_RX_LD) {
++ /* check that this is a whole packet
++ * WARNING: DMA_FD bit incorrectly set
++ * in Rc32434 (errata ref #077) */
++ dev->stats.rx_errors++;
++ dev->stats.rx_dropped++;
++ }
++
++ while ((rx_free_desc = KORINA_RBSIZE - (u32)DMA_COUNT(rd->control)) != 0) {
++ /* init the var. used for the later
++ * operations within the while loop */
++ skb_new = NULL;
++ pkt_len = RCVPKT_LENGTH(devcs);
++ skb = lp->rx_skb[lp->rx_next_done];
++
++ if ((devcs & ETH_RX_ROK)) {
++ /* must be the (first and) last
++ * descriptor then */
++ pkt_buf = (u8 *)lp->rx_skb[lp->rx_next_done]->data;
++
++ /* invalidate the cache */
++ dma_cache_inv((unsigned long)pkt_buf, pkt_len - 4);
++
++ /* Malloc up new buffer. */
++ skb_new = netdev_alloc_skb(dev, KORINA_RBSIZE + 2);
++
++ if (!skb_new)
++ break;
++ /* Do not count the CRC */
++ skb_put(skb, pkt_len - 4);
++ skb->protocol = eth_type_trans(skb, dev);
++
++ /* Pass the packet to upper layers */
++ netif_receive_skb(skb);
++ dev->last_rx = jiffies;
++ dev->stats.rx_packets++;
++ dev->stats.rx_bytes += pkt_len;
++
++ /* Update the mcast stats */
++ if (devcs & ETH_RX_MP)
++ dev->stats.multicast++;
++
++ lp->rx_skb[lp->rx_next_done] = skb_new;
++ }
++
++ rd->devcs = 0;
++
++ /* Restore descriptor's curr_addr */
++ if (skb_new)
++ rd->ca = CPHYSADDR(skb_new->data);
++ else
++ rd->ca = CPHYSADDR(skb->data);
++
++ rd->control = DMA_COUNT(KORINA_RBSIZE) |
++ DMA_DESC_COD | DMA_DESC_IOD;
++ lp->rd_ring[(lp->rx_next_done - 1) &
++ KORINA_RDS_MASK].control &=
++ ~DMA_DESC_COD;
++
++ lp->rx_next_done = (lp->rx_next_done + 1) & KORINA_RDS_MASK;
++ dma_cache_wback((u32)rd, sizeof(*rd));
++ rd = &lp->rd_ring[lp->rx_next_done];
++ writel(~DMA_STAT_DONE, &lp->rx_dma_regs->dmas);
++ }
++ }
++
++ dmas = readl(&lp->rx_dma_regs->dmas);
++
++ if (dmas & DMA_STAT_HALT) {
++ writel(~(DMA_STAT_HALT | DMA_STAT_ERR),
++ &lp->rx_dma_regs->dmas);
++
++ lp->dma_halt_cnt++;
++ rd->devcs = 0;
++ skb = lp->rx_skb[lp->rx_next_done];
++ rd->ca = CPHYSADDR(skb->data);
++ dma_cache_wback((u32)rd, sizeof(*rd));
++ korina_chain_rx(lp, rd);
++ }
++
++ return count;
++}
++
++static int korina_poll(struct napi_struct *napi, int budget)
++{
++ struct korina_private *lp =
++ container_of(napi, struct korina_private, napi);
++ struct net_device *dev = lp->dev;
++ int work_done;
++
++ work_done = korina_rx(dev, budget);
++ if (work_done < budget) {
++ netif_rx_complete(dev, napi);
++
++ writel(readl(&lp->rx_dma_regs->dmasm) &
++ ~(DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR),
++ &lp->rx_dma_regs->dmasm);
++ }
++ return work_done;
++}
++
++/*
++ * Set or clear the multicast filter for this adaptor.
++ */
++static void korina_multicast_list(struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ unsigned long flags;
++ struct dev_mc_list *dmi = dev->mc_list;
++ u32 recognise = ETH_ARC_AB; /* always accept broadcasts */
++ int i;
++
++ /* Set promiscuous mode */
++ if (dev->flags & IFF_PROMISC)
++ recognise |= ETH_ARC_PRO;
++
++ else if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 4))
++ /* All multicast and broadcast */
++ recognise |= ETH_ARC_AM;
++
++ /* Build the hash table */
++ if (dev->mc_count > 4) {
++ u16 hash_table[4];
++ u32 crc;
++
++ for (i = 0; i < 4; i++)
++ hash_table[i] = 0;
++
++ for (i = 0; i < dev->mc_count; i++) {
++ char *addrs = dmi->dmi_addr;
++
++ dmi = dmi->next;
++
++ if (!(*addrs & 1))
++ continue;
++
++ crc = ether_crc_le(6, addrs);
++ crc >>= 26;
++ hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf));
++ }
++ /* Accept filtered multicast */
++ recognise |= ETH_ARC_AFM;
++
++ /* Fill the MAC hash tables with their values */
++ writel((u32)(hash_table[1] << 16 | hash_table[0]),
++ &lp->eth_regs->ethhash0);
++ writel((u32)(hash_table[3] << 16 | hash_table[2]),
++ &lp->eth_regs->ethhash1);
++ }
++
++ spin_lock_irqsave(&lp->lock, flags);
++ writel(recognise, &lp->eth_regs->etharc);
++ spin_unlock_irqrestore(&lp->lock, flags);
++}
++
++static void korina_tx(struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ struct dma_desc *td = &lp->td_ring[lp->tx_next_done];
++ u32 devcs;
++ u32 dmas;
++
++ spin_lock(&lp->lock);
++
++ /* Process all desc that are done */
++ while (IS_DMA_FINISHED(td->control)) {
++ if (lp->tx_full == 1) {
++ netif_wake_queue(dev);
++ lp->tx_full = 0;
++ }
++
++ devcs = lp->td_ring[lp->tx_next_done].devcs;
++ if ((devcs & (ETH_TX_FD | ETH_TX_LD)) !=
++ (ETH_TX_FD | ETH_TX_LD)) {
++ dev->stats.tx_errors++;
++ dev->stats.tx_dropped++;
++
++ /* Should never happen */
++ printk(KERN_ERR DRV_NAME "%s: split tx ignored\n",
++ dev->name);
++ } else if (devcs & ETH_TX_TOK) {
++ dev->stats.tx_packets++;
++ dev->stats.tx_bytes +=
++ lp->tx_skb[lp->tx_next_done]->len;
++ } else {
++ dev->stats.tx_errors++;
++ dev->stats.tx_dropped++;
++
++ /* Underflow */
++ if (devcs & ETH_TX_UND)
++ dev->stats.tx_fifo_errors++;
++
++ /* Oversized frame */
++ if (devcs & ETH_TX_OF)
++ dev->stats.tx_aborted_errors++;
++
++ /* Excessive deferrals */
++ if (devcs & ETH_TX_ED)
++ dev->stats.tx_carrier_errors++;
++
++ /* Collisions: medium busy */
++ if (devcs & ETH_TX_EC)
++ dev->stats.collisions++;
++
++ /* Late collision */
++ if (devcs & ETH_TX_LC)
++ dev->stats.tx_window_errors++;
++ }
++
++ /* We must always free the original skb */
++ if (lp->tx_skb[lp->tx_next_done]) {
++ dev_kfree_skb_any(lp->tx_skb[lp->tx_next_done]);
++ lp->tx_skb[lp->tx_next_done] = NULL;
++ }
++
++ lp->td_ring[lp->tx_next_done].control = DMA_DESC_IOF;
++ lp->td_ring[lp->tx_next_done].devcs = ETH_TX_FD | ETH_TX_LD;
++ lp->td_ring[lp->tx_next_done].link = 0;
++ lp->td_ring[lp->tx_next_done].ca = 0;
++ lp->tx_count--;
++
++ /* Go on to next transmission */
++ lp->tx_next_done = (lp->tx_next_done + 1) & KORINA_TDS_MASK;
++ td = &lp->td_ring[lp->tx_next_done];
++
++ }
++
++ /* Clear the DMA status register */
++ dmas = readl(&lp->tx_dma_regs->dmas);
++ writel(~dmas, &lp->tx_dma_regs->dmas);
++
++ writel(readl(&lp->tx_dma_regs->dmasm) &
++ ~(DMA_STAT_FINI | DMA_STAT_ERR),
++ &lp->tx_dma_regs->dmasm);
++
++ spin_unlock(&lp->lock);
++}
++
++static irqreturn_t
++korina_tx_dma_interrupt(int irq, void *dev_id)
++{
++ struct net_device *dev = dev_id;
++ struct korina_private *lp = netdev_priv(dev);
++ u32 dmas, dmasm;
++ irqreturn_t retval;
++
++ dmas = readl(&lp->tx_dma_regs->dmas);
++
++ if (dmas & (DMA_STAT_FINI | DMA_STAT_ERR)) {
++ korina_tx(dev);
++
++ dmasm = readl(&lp->tx_dma_regs->dmasm);
++ writel(dmasm | (DMA_STAT_FINI | DMA_STAT_ERR),
++ &lp->tx_dma_regs->dmasm);
++
++ if (lp->tx_chain_status == desc_filled &&
++ (readl(&(lp->tx_dma_regs->dmandptr)) == 0)) {
++ writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]),
++ &(lp->tx_dma_regs->dmandptr));
++ lp->tx_chain_status = desc_empty;
++ lp->tx_chain_head = lp->tx_chain_tail;
++ dev->trans_start = jiffies;
++ }
++ if (dmas & DMA_STAT_ERR)
++ printk(KERN_ERR DRV_NAME "%s: DMA error\n", dev->name);
++
++ retval = IRQ_HANDLED;
++ } else
++ retval = IRQ_NONE;
++
++ return retval;
++}
++
++
++static void korina_check_media(struct net_device *dev, unsigned int init_media)
++{
++ struct korina_private *lp = netdev_priv(dev);
++
++ mii_check_media(&lp->mii_if, 0, init_media);
++
++ if (lp->mii_if.full_duplex)
++ writel(readl(&lp->eth_regs->ethmac2) | ETH_MAC2_FD,
++ &lp->eth_regs->ethmac2);
++ else
++ writel(readl(&lp->eth_regs->ethmac2) & ~ETH_MAC2_FD,
++ &lp->eth_regs->ethmac2);
++}
++
++static void korina_set_carrier(struct mii_if_info *mii)
++{
++ if (mii->force_media) {
++ /* autoneg is off: Link is always assumed to be up */
++ if (!netif_carrier_ok(mii->dev))
++ netif_carrier_on(mii->dev);
++ } else /* Let MMI library update carrier status */
++ korina_check_media(mii->dev, 0);
++}
++
++static int korina_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ struct mii_ioctl_data *data = if_mii(rq);
++ int rc;
++
++ if (!netif_running(dev))
++ return -EINVAL;
++ spin_lock_irq(&lp->lock);
++ rc = generic_mii_ioctl(&lp->mii_if, data, cmd, NULL);
++ spin_unlock_irq(&lp->lock);
++ korina_set_carrier(&lp->mii_if);
++
++ return rc;
++}
++
++/* ethtool helpers */
++static void netdev_get_drvinfo(struct net_device *dev,
++ struct ethtool_drvinfo *info)
++{
++ struct korina_private *lp = netdev_priv(dev);
++
++ strcpy(info->driver, DRV_NAME);
++ strcpy(info->version, DRV_VERSION);
++ strcpy(info->bus_info, lp->dev->name);
++}
++
++static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ int rc;
++
++ spin_lock_irq(&lp->lock);
++ rc = mii_ethtool_gset(&lp->mii_if, cmd);
++ spin_unlock_irq(&lp->lock);
++
++ return rc;
++}
++
++static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ int rc;
++
++ spin_lock_irq(&lp->lock);
++ rc = mii_ethtool_sset(&lp->mii_if, cmd);
++ spin_unlock_irq(&lp->lock);
++ korina_set_carrier(&lp->mii_if);
++
++ return rc;
++}
++
++static u32 netdev_get_link(struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++
++ return mii_link_ok(&lp->mii_if);
++}
++
++static struct ethtool_ops netdev_ethtool_ops = {
++ .get_drvinfo = netdev_get_drvinfo,
++ .get_settings = netdev_get_settings,
++ .set_settings = netdev_set_settings,
++ .get_link = netdev_get_link,
++};
++
++static void korina_alloc_ring(struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ int i;
++
++ /* Initialize the transmit descriptors */
++ for (i = 0; i < KORINA_NUM_TDS; i++) {
++ lp->td_ring[i].control = DMA_DESC_IOF;
++ lp->td_ring[i].devcs = ETH_TX_FD | ETH_TX_LD;
++ lp->td_ring[i].ca = 0;
++ lp->td_ring[i].link = 0;
++ }
++ lp->tx_next_done = lp->tx_chain_head = lp->tx_chain_tail =
++ lp->tx_full = lp->tx_count = 0;
++ lp->tx_chain_status = desc_empty;
++
++ /* Initialize the receive descriptors */
++ for (i = 0; i < KORINA_NUM_RDS; i++) {
++ struct sk_buff *skb = lp->rx_skb[i];
++
++ skb = dev_alloc_skb(KORINA_RBSIZE + 2);
++ if (!skb)
++ break;
++ skb_reserve(skb, 2);
++ lp->rx_skb[i] = skb;
++ lp->rd_ring[i].control = DMA_DESC_IOD |
++ DMA_COUNT(KORINA_RBSIZE);
++ lp->rd_ring[i].devcs = 0;
++ lp->rd_ring[i].ca = CPHYSADDR(skb->data);
++ lp->rd_ring[i].link = CPHYSADDR(&lp->rd_ring[i+1]);
++ }
++
++ /* loop back */
++ lp->rd_ring[i].link = CPHYSADDR(&lp->rd_ring[0]);
++ lp->rx_next_done = 0;
++
++ lp->rd_ring[i].control |= DMA_DESC_COD;
++ lp->rx_chain_head = 0;
++ lp->rx_chain_tail = 0;
++ lp->rx_chain_status = desc_empty;
++}
++
++static void korina_free_ring(struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ int i;
++
++ for (i = 0; i < KORINA_NUM_RDS; i++) {
++ lp->rd_ring[i].control = 0;
++ if (lp->rx_skb[i])
++ dev_kfree_skb_any(lp->rx_skb[i]);
++ lp->rx_skb[i] = NULL;
++ }
++
++ for (i = 0; i < KORINA_NUM_TDS; i++) {
++ lp->td_ring[i].control = 0;
++ if (lp->tx_skb[i])
++ dev_kfree_skb_any(lp->tx_skb[i]);
++ lp->tx_skb[i] = NULL;
++ }
++}
++
++/*
++ * Initialize the RC32434 ethernet controller.
++ */
++static int korina_init(struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++
++ /* Disable DMA */
++ korina_abort_tx(dev);
++ korina_abort_rx(dev);
++
++ /* reset ethernet logic */
++ writel(0, &lp->eth_regs->ethintfc);
++ while ((readl(&lp->eth_regs->ethintfc) & ETH_INT_FC_RIP))
++ dev->trans_start = jiffies;
++
++ /* Enable Ethernet Interface */
++ writel(ETH_INT_FC_EN, &lp->eth_regs->ethintfc);
++
++ /* Allocate rings */
++ korina_alloc_ring(dev);
++
++ writel(0, &lp->rx_dma_regs->dmas);
++ /* Start Rx DMA */
++ korina_start_rx(lp, &lp->rd_ring[0]);
++
++ writel(readl(&lp->tx_dma_regs->dmasm) &
++ ~(DMA_STAT_FINI | DMA_STAT_ERR),
++ &lp->tx_dma_regs->dmasm);
++ writel(readl(&lp->rx_dma_regs->dmasm) &
++ ~(DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR),
++ &lp->rx_dma_regs->dmasm);
++
++ /* Accept only packets destined for this Ethernet device address */
++ writel(ETH_ARC_AB, &lp->eth_regs->etharc);
++
++ /* Set all Ether station address registers to their initial values */
++ writel(STATION_ADDRESS_LOW(dev), &lp->eth_regs->ethsal0);
++ writel(STATION_ADDRESS_HIGH(dev), &lp->eth_regs->ethsah0);
++
++ writel(STATION_ADDRESS_LOW(dev), &lp->eth_regs->ethsal1);
++ writel(STATION_ADDRESS_HIGH(dev), &lp->eth_regs->ethsah1);
++
++ writel(STATION_ADDRESS_LOW(dev), &lp->eth_regs->ethsal2);
++ writel(STATION_ADDRESS_HIGH(dev), &lp->eth_regs->ethsah2);
++
++ writel(STATION_ADDRESS_LOW(dev), &lp->eth_regs->ethsal3);
++ writel(STATION_ADDRESS_HIGH(dev), &lp->eth_regs->ethsah3);
++
++
++ /* Frame Length Checking, Pad Enable, CRC Enable, Full Duplex set */
++ writel(ETH_MAC2_PE | ETH_MAC2_CEN | ETH_MAC2_FD,
++ &lp->eth_regs->ethmac2);
++
++ /* Back to back inter-packet-gap */
++ writel(0x15, &lp->eth_regs->ethipgt);
++ /* Non - Back to back inter-packet-gap */
++ writel(0x12, &lp->eth_regs->ethipgr);
++
++ /* Management Clock Prescaler Divisor
++ * Clock independent setting */
++ writel(((idt_cpu_freq) / MII_CLOCK + 1) & ~1,
++ &lp->eth_regs->ethmcp);
++
++ /* don't transmit until fifo contains 48b */
++ writel(48, &lp->eth_regs->ethfifott);
++
++ writel(ETH_MAC1_RE, &lp->eth_regs->ethmac1);
++
++ napi_enable(&lp->napi);
++ netif_start_queue(dev);
++
++ return 0;
++}
++
++/*
++ * Restart the RC32434 ethernet controller.
++ * FIXME: check the return status where we call it
++ */
++static int korina_restart(struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ int ret;
++
++ /*
++ * Disable interrupts
++ */
++ disable_irq(lp->rx_irq);
++ disable_irq(lp->tx_irq);
++ disable_irq(lp->ovr_irq);
++ disable_irq(lp->und_irq);
++
++ writel(readl(&lp->tx_dma_regs->dmasm) |
++ DMA_STAT_FINI | DMA_STAT_ERR,
++ &lp->tx_dma_regs->dmasm);
++ writel(readl(&lp->rx_dma_regs->dmasm) |
++ DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR,
++ &lp->rx_dma_regs->dmasm);
++
++ korina_free_ring(dev);
++
++ ret = korina_init(dev);
++ if (ret < 0) {
++ printk(KERN_ERR DRV_NAME "%s: cannot restart device\n",
++ dev->name);
++ return ret;
++ }
++ korina_multicast_list(dev);
++
++ enable_irq(lp->und_irq);
++ enable_irq(lp->ovr_irq);
++ enable_irq(lp->tx_irq);
++ enable_irq(lp->rx_irq);
++
++ return ret;
++}
++
++static void korina_clear_and_restart(struct net_device *dev, u32 value)
++{
++ struct korina_private *lp = netdev_priv(dev);
++
++ netif_stop_queue(dev);
++ writel(value, &lp->eth_regs->ethintfc);
++ korina_restart(dev);
++}
++
++/* Ethernet Tx Underflow interrupt */
++static irqreturn_t korina_und_interrupt(int irq, void *dev_id)
++{
++ struct net_device *dev = dev_id;
++ struct korina_private *lp = netdev_priv(dev);
++ unsigned int und;
++
++ spin_lock(&lp->lock);
++
++ und = readl(&lp->eth_regs->ethintfc);
++
++ if (und & ETH_INT_FC_UND)
++ korina_clear_and_restart(dev, und & ~ETH_INT_FC_UND);
++
++ spin_unlock(&lp->lock);
++
++ return IRQ_HANDLED;
++}
++
++static void korina_tx_timeout(struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ unsigned long flags;
++
++ spin_lock_irqsave(&lp->lock, flags);
++ korina_restart(dev);
++ spin_unlock_irqrestore(&lp->lock, flags);
++}
++
++/* Ethernet Rx Overflow interrupt */
++static irqreturn_t
++korina_ovr_interrupt(int irq, void *dev_id)
++{
++ struct net_device *dev = dev_id;
++ struct korina_private *lp = netdev_priv(dev);
++ unsigned int ovr;
++
++ spin_lock(&lp->lock);
++ ovr = readl(&lp->eth_regs->ethintfc);
++
++ if (ovr & ETH_INT_FC_OVR)
++ korina_clear_and_restart(dev, ovr & ~ETH_INT_FC_OVR);
++
++ spin_unlock(&lp->lock);
++
++ return IRQ_HANDLED;
++}
++
++#ifdef CONFIG_NET_POLL_CONTROLLER
++static void korina_poll_controller(struct net_device *dev)
++{
++ disable_irq(dev->irq);
++ korina_tx_dma_interrupt(dev->irq, dev);
++ enable_irq(dev->irq);
++}
++#endif
++
++static int korina_open(struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ int ret;
++
++ /* Initialize */
++ ret = korina_init(dev);
++ if (ret < 0) {
++ printk(KERN_ERR DRV_NAME "%s: cannot open device\n", dev->name);
++ goto out;
++ }
++
++ /* Install the interrupt handler
++ * that handles the Done Finished
++ * Ovr and Und Events */
++ ret = request_irq(lp->rx_irq, &korina_rx_dma_interrupt,
++ IRQF_SHARED | IRQF_DISABLED, "Korina ethernet Rx", dev);
++ if (ret < 0) {
++ printk(KERN_ERR DRV_NAME "%s: unable to get Rx DMA IRQ %d\n",
++ dev->name, lp->rx_irq);
++ goto err_release;
++ }
++ ret = request_irq(lp->tx_irq, &korina_tx_dma_interrupt,
++ IRQF_SHARED | IRQF_DISABLED, "Korina ethernet Tx", dev);
++ if (ret < 0) {
++ printk(KERN_ERR DRV_NAME "%s: unable to get Tx DMA IRQ %d\n",
++ dev->name, lp->tx_irq);
++ goto err_free_rx_irq;
++ }
++
++ /* Install handler for overrun error. */
++ ret = request_irq(lp->ovr_irq, &korina_ovr_interrupt,
++ IRQF_SHARED | IRQF_DISABLED, "Ethernet Overflow", dev);
++ if (ret < 0) {
++ printk(KERN_ERR DRV_NAME"%s: unable to get OVR IRQ %d\n",
++ dev->name, lp->ovr_irq);
++ goto err_free_tx_irq;
++ }
++
++ /* Install handler for underflow error. */
++ ret = request_irq(lp->und_irq, &korina_und_interrupt,
++ IRQF_SHARED | IRQF_DISABLED, "Ethernet Underflow", dev);
++ if (ret < 0) {
++ printk(KERN_ERR DRV_NAME "%s: unable to get UND IRQ %d\n",
++ dev->name, lp->und_irq);
++ goto err_free_ovr_irq;
++ }
++out:
++ return ret;
++
++err_free_ovr_irq:
++ free_irq(lp->ovr_irq, dev);
++err_free_tx_irq:
++ free_irq(lp->tx_irq, dev);
++err_free_rx_irq:
++ free_irq(lp->rx_irq, dev);
++err_release:
++ korina_free_ring(dev);
++ goto out;
++}
++
++static int korina_close(struct net_device *dev)
++{
++ struct korina_private *lp = netdev_priv(dev);
++ u32 tmp;
++
++ /* Disable interrupts */
++ disable_irq(lp->rx_irq);
++ disable_irq(lp->tx_irq);
++ disable_irq(lp->ovr_irq);
++ disable_irq(lp->und_irq);
++
++ korina_abort_tx(dev);
++ tmp = readl(&lp->tx_dma_regs->dmasm);
++ tmp = tmp | DMA_STAT_FINI | DMA_STAT_ERR;
++ writel(tmp, &lp->tx_dma_regs->dmasm);
++
++ korina_abort_rx(dev);
++ tmp = readl(&lp->rx_dma_regs->dmasm);
++ tmp = tmp | DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR;
++ writel(tmp, &lp->rx_dma_regs->dmasm);
++
++ korina_free_ring(dev);
++
++ free_irq(lp->rx_irq, dev);
++ free_irq(lp->tx_irq, dev);
++ free_irq(lp->ovr_irq, dev);
++ free_irq(lp->und_irq, dev);
++
++ return 0;
++}
++
++static int korina_probe(struct platform_device *pdev)
++{
++ struct korina_device *bif = platform_get_drvdata(pdev);
++ struct korina_private *lp;
++ struct net_device *dev;
++ struct resource *r;
++ int rc;
++
++ dev = alloc_etherdev(sizeof(struct korina_private));
++ if (!dev) {
++ printk(KERN_ERR DRV_NAME ": alloc_etherdev failed\n");
++ return -ENOMEM;
++ }
++ SET_NETDEV_DEV(dev, &pdev->dev);
++ platform_set_drvdata(pdev, dev);
++ lp = netdev_priv(dev);
++
++ bif->dev = dev;
++ memcpy(dev->dev_addr, bif->mac, 6);
++
++ lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx");
++ lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx");
++ lp->ovr_irq = platform_get_irq_byname(pdev, "korina_ovr");
++ lp->und_irq = platform_get_irq_byname(pdev, "korina_und");
++
++ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_regs");
++ dev->base_addr = r->start;
++ lp->eth_regs = ioremap_nocache(r->start, r->end - r->start);
++ if (!lp->eth_regs) {
++ printk(KERN_ERR DRV_NAME "cannot remap registers\n");
++ rc = -ENXIO;
++ goto probe_err_out;
++ }
++
++ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_dma_rx");
++ lp->rx_dma_regs = ioremap_nocache(r->start, r->end - r->start);
++ if (!lp->rx_dma_regs) {
++ printk(KERN_ERR DRV_NAME "cannot remap Rx DMA registers\n");
++ rc = -ENXIO;
++ goto probe_err_dma_rx;
++ }
++
++ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_dma_tx");
++ lp->tx_dma_regs = ioremap_nocache(r->start, r->end - r->start);
++ if (!lp->tx_dma_regs) {
++ printk(KERN_ERR DRV_NAME "cannot remap Tx DMA registers\n");
++ rc = -ENXIO;
++ goto probe_err_dma_tx;
++ }
++
++ lp->td_ring = kmalloc(TD_RING_SIZE + RD_RING_SIZE, GFP_KERNEL);
++ if (!lp->td_ring) {
++ printk(KERN_ERR DRV_NAME "cannot allocate descriptors\n");
++ rc = -ENXIO;
++ goto probe_err_td_ring;
++ }
++
++ dma_cache_inv((unsigned long)(lp->td_ring),
++ TD_RING_SIZE + RD_RING_SIZE);
++
++ /* now convert TD_RING pointer to KSEG1 */
++ lp->td_ring = (struct dma_desc *)KSEG1ADDR(lp->td_ring);
++ lp->rd_ring = &lp->td_ring[KORINA_NUM_TDS];
++
++ spin_lock_init(&lp->lock);
++ /* just use the rx dma irq */
++ dev->irq = lp->rx_irq;
++ lp->dev = dev;
++
++ dev->open = korina_open;
++ dev->stop = korina_close;
++ dev->hard_start_xmit = korina_send_packet;
++ dev->set_multicast_list = &korina_multicast_list;
++ dev->ethtool_ops = &netdev_ethtool_ops;
++ dev->tx_timeout = korina_tx_timeout;
++ dev->watchdog_timeo = TX_TIMEOUT;
++ dev->do_ioctl = &korina_ioctl;
++#ifdef CONFIG_NET_POLL_CONTROLLER
++ dev->poll_controller = korina_poll_controller;
++#endif
++ netif_napi_add(dev, &lp->napi, korina_poll, 64);
++
++ lp->phy_addr = (((lp->rx_irq == 0x2c? 1:0) << 8) | 0x05);
++ lp->mii_if.dev = dev;
++ lp->mii_if.mdio_read = mdio_read;
++ lp->mii_if.mdio_write = mdio_write;
++ lp->mii_if.phy_id = lp->phy_addr;
++ lp->mii_if.phy_id_mask = 0x1f;
++ lp->mii_if.reg_num_mask = 0x1f;
++
++ rc = register_netdev(dev);
++ if (rc < 0) {
++ printk(KERN_ERR DRV_NAME
++ ": cannot register net device %d\n", rc);
++ goto probe_err_register;
++ }
++out:
++ return rc;
++
++probe_err_register:
++ kfree(lp->td_ring);
++probe_err_td_ring:
++ iounmap(lp->tx_dma_regs);
++probe_err_dma_tx:
++ iounmap(lp->rx_dma_regs);
++probe_err_dma_rx:
++ iounmap(lp->eth_regs);
++probe_err_out:
++ free_netdev(dev);
++ goto out;
++}
++
++static int korina_remove(struct platform_device *pdev)
++{
++ struct korina_device *bif = platform_get_drvdata(pdev);
++ struct korina_private *lp = netdev_priv(bif->dev);
++
++ iounmap(lp->eth_regs);
++ iounmap(lp->rx_dma_regs);
++ iounmap(lp->tx_dma_regs);
++
++ platform_set_drvdata(pdev, NULL);
++ unregister_netdev(bif->dev);
++ free_netdev(bif->dev);
++
++ return 0;
++}
++
++static struct platform_driver korina_driver = {
++ .driver.name = "korina",
++ .probe = korina_probe,
++ .remove = korina_remove,
++};
++
++static int __init korina_init_module(void)
++{
++ return platform_driver_register(&korina_driver);
++}
++
++static void korina_cleanup_module(void)
++{
++ return platform_driver_unregister(&korina_driver);
++}
++
++module_init(korina_init_module);
++module_exit(korina_cleanup_module);
++
++MODULE_AUTHOR("Philip Rischel <rischelp at idt.com>");
++MODULE_AUTHOR("Felix Fietkau <nbd at openwrt.org>");
++MODULE_AUTHOR("Florian Fainelli <florian at openwrt.org>");
++MODULE_DESCRIPTION("IDT RC32434 (Korina) Ethernet driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
+index f2a6e71..41b774b 100644
+--- a/drivers/net/loopback.c
++++ b/drivers/net/loopback.c
+@@ -258,7 +258,7 @@ static __net_init int loopback_net_init(struct net *net)
+ if (!dev)
+ goto out;
+
+- dev->nd_net = net;
++ dev_net_set(dev, net);
+ err = register_netdev(dev);
+ if (err)
+ goto out_free_netdev;
+diff --git a/drivers/net/macb.c b/drivers/net/macb.c
+index 489c7c3..92dccd4 100644
+--- a/drivers/net/macb.c
++++ b/drivers/net/macb.c
+@@ -246,7 +246,7 @@ static int macb_mii_init(struct macb *bp)
+ bp->mii_bus.read = &macb_mdio_read;
+ bp->mii_bus.write = &macb_mdio_write;
+ bp->mii_bus.reset = &macb_mdio_reset;
+- bp->mii_bus.id = bp->pdev->id;
++ snprintf(bp->mii_bus.id, MII_BUS_ID_SIZE, "%x", bp->pdev->id);
+ bp->mii_bus.priv = bp;
+ bp->mii_bus.dev = &bp->dev->dev;
+ pdata = bp->pdev->dev.platform_data;
+@@ -1281,6 +1281,7 @@ static struct platform_driver macb_driver = {
+ .remove = __exit_p(macb_remove),
+ .driver = {
+ .name = "macb",
++ .owner = THIS_MODULE,
+ },
+ };
+
+@@ -1300,3 +1301,4 @@ module_exit(macb_exit);
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Atmel MACB Ethernet driver");
+ MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen at atmel.com>");
++MODULE_ALIAS("platform:macb");
+diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
+index f651a81..2056cfc 100644
+--- a/drivers/net/macvlan.c
++++ b/drivers/net/macvlan.c
+@@ -402,7 +402,7 @@ static int macvlan_newlink(struct net_device *dev,
+ if (!tb[IFLA_LINK])
+ return -EINVAL;
+
+- lowerdev = __dev_get_by_index(dev->nd_net, nla_get_u32(tb[IFLA_LINK]));
++ lowerdev = __dev_get_by_index(dev_net(dev), nla_get_u32(tb[IFLA_LINK]));
+ if (lowerdev == NULL)
+ return -ENODEV;
+
+diff --git a/drivers/net/meth.c b/drivers/net/meth.c
+index cdaa8fc..0b32648 100644
+--- a/drivers/net/meth.c
++++ b/drivers/net/meth.c
+@@ -830,6 +830,7 @@ static struct platform_driver meth_driver = {
+ .remove = __devexit_p(meth_remove),
+ .driver = {
+ .name = "meth",
++ .owner = THIS_MODULE,
+ }
+ };
+
+@@ -855,3 +856,4 @@ module_exit(meth_exit_module);
+ MODULE_AUTHOR("Ilya Volynets <ilya at theIlya.com>");
+ MODULE_DESCRIPTION("SGI O2 Builtin Fast Ethernet driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:meth");
+diff --git a/drivers/net/mlx4/catas.c b/drivers/net/mlx4/catas.c
+index 6b32ec9..aa95287 100644
+--- a/drivers/net/mlx4/catas.c
++++ b/drivers/net/mlx4/catas.c
+@@ -69,7 +69,7 @@ static void poll_catas(unsigned long dev_ptr)
+ if (readl(priv->catas_err.map)) {
+ dump_err_buf(dev);
+
+- mlx4_dispatch_event(dev, MLX4_EVENT_TYPE_LOCAL_CATAS_ERROR, 0, 0);
++ mlx4_dispatch_event(dev, MLX4_DEV_EVENT_CATASTROPHIC_ERROR, 0);
+
+ if (internal_err_reset) {
+ spin_lock(&catas_lock);
+diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c
+index db49051..70dff94 100644
+--- a/drivers/net/mlx4/cmd.c
++++ b/drivers/net/mlx4/cmd.c
+@@ -106,7 +106,8 @@ struct mlx4_cmd_context {
+ u16 token;
+ };
+
+-static int mlx4_status_to_errno(u8 status) {
++static int mlx4_status_to_errno(u8 status)
++{
+ static const int trans_table[] = {
+ [CMD_STAT_INTERNAL_ERR] = -EIO,
+ [CMD_STAT_BAD_OP] = -EPERM,
+diff --git a/drivers/net/mlx4/cq.c b/drivers/net/mlx4/cq.c
+index d4441fe..caa5bcf 100644
+--- a/drivers/net/mlx4/cq.c
++++ b/drivers/net/mlx4/cq.c
+@@ -38,6 +38,7 @@
+ #include <linux/hardirq.h>
+
+ #include <linux/mlx4/cmd.h>
++#include <linux/mlx4/cq.h>
+
+ #include "mlx4.h"
+ #include "icm.h"
+@@ -47,21 +48,19 @@ struct mlx4_cq_context {
+ u16 reserved1[3];
+ __be16 page_offset;
+ __be32 logsize_usrpage;
+- u8 reserved2;
+- u8 cq_period;
+- u8 reserved3;
+- u8 cq_max_count;
+- u8 reserved4[3];
++ __be16 cq_period;
++ __be16 cq_max_count;
++ u8 reserved2[3];
+ u8 comp_eqn;
+ u8 log_page_size;
+- u8 reserved5[2];
++ u8 reserved3[2];
+ u8 mtt_base_addr_h;
+ __be32 mtt_base_addr_l;
+ __be32 last_notified_index;
+ __be32 solicit_producer_index;
+ __be32 consumer_index;
+ __be32 producer_index;
+- u32 reserved6[2];
++ u32 reserved4[2];
+ __be64 db_rec_addr;
+ };
+
+@@ -121,6 +120,13 @@ static int mlx4_SW2HW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
+ MLX4_CMD_TIME_CLASS_A);
+ }
+
++static int mlx4_MODIFY_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
++ int cq_num, u32 opmod)
++{
++ return mlx4_cmd(dev, mailbox->dma, cq_num, opmod, MLX4_CMD_MODIFY_CQ,
++ MLX4_CMD_TIME_CLASS_A);
++}
++
+ static int mlx4_HW2SW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
+ int cq_num)
+ {
+@@ -129,6 +135,58 @@ static int mlx4_HW2SW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
+ MLX4_CMD_TIME_CLASS_A);
+ }
+
++int mlx4_cq_modify(struct mlx4_dev *dev, struct mlx4_cq *cq,
++ u16 count, u16 period)
++{
++ struct mlx4_cmd_mailbox *mailbox;
++ struct mlx4_cq_context *cq_context;
++ int err;
++
++ mailbox = mlx4_alloc_cmd_mailbox(dev);
++ if (IS_ERR(mailbox))
++ return PTR_ERR(mailbox);
++
++ cq_context = mailbox->buf;
++ memset(cq_context, 0, sizeof *cq_context);
++
++ cq_context->cq_max_count = cpu_to_be16(count);
++ cq_context->cq_period = cpu_to_be16(period);
++
++ err = mlx4_MODIFY_CQ(dev, mailbox, cq->cqn, 1);
++
++ mlx4_free_cmd_mailbox(dev, mailbox);
++ return err;
++}
++EXPORT_SYMBOL_GPL(mlx4_cq_modify);
++
++int mlx4_cq_resize(struct mlx4_dev *dev, struct mlx4_cq *cq,
++ int entries, struct mlx4_mtt *mtt)
++{
++ struct mlx4_cmd_mailbox *mailbox;
++ struct mlx4_cq_context *cq_context;
++ u64 mtt_addr;
++ int err;
++
++ mailbox = mlx4_alloc_cmd_mailbox(dev);
++ if (IS_ERR(mailbox))
++ return PTR_ERR(mailbox);
++
++ cq_context = mailbox->buf;
++ memset(cq_context, 0, sizeof *cq_context);
++
++ cq_context->logsize_usrpage = cpu_to_be32(ilog2(entries) << 24);
++ cq_context->log_page_size = mtt->page_shift - 12;
++ mtt_addr = mlx4_mtt_addr(dev, mtt);
++ cq_context->mtt_base_addr_h = mtt_addr >> 32;
++ cq_context->mtt_base_addr_l = cpu_to_be32(mtt_addr & 0xffffffff);
++
++ err = mlx4_MODIFY_CQ(dev, mailbox, cq->cqn, 1);
++
++ mlx4_free_cmd_mailbox(dev, mailbox);
++ return err;
++}
++EXPORT_SYMBOL_GPL(mlx4_cq_resize);
++
+ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
+ struct mlx4_uar *uar, u64 db_rec, struct mlx4_cq *cq)
+ {
+diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c
+index 9c36c20..e141a15 100644
+--- a/drivers/net/mlx4/eq.c
++++ b/drivers/net/mlx4/eq.c
+@@ -202,7 +202,10 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
+ break;
+
+ case MLX4_EVENT_TYPE_PORT_CHANGE:
+- mlx4_dispatch_event(dev, eqe->type, eqe->subtype,
++ mlx4_dispatch_event(dev,
++ eqe->subtype == MLX4_PORT_CHANGE_SUBTYPE_ACTIVE ?
++ MLX4_DEV_EVENT_PORT_UP :
++ MLX4_DEV_EVENT_PORT_DOWN,
+ be32_to_cpu(eqe->event.port_change.port) >> 28);
+ break;
+
+diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
+index 61dc495..d82f275 100644
+--- a/drivers/net/mlx4/fw.c
++++ b/drivers/net/mlx4/fw.c
+@@ -133,6 +133,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
+ #define QUERY_DEV_CAP_MAX_AV_OFFSET 0x27
+ #define QUERY_DEV_CAP_MAX_REQ_QP_OFFSET 0x29
+ #define QUERY_DEV_CAP_MAX_RES_QP_OFFSET 0x2b
++#define QUERY_DEV_CAP_MAX_GSO_OFFSET 0x2d
+ #define QUERY_DEV_CAP_MAX_RDMA_OFFSET 0x2f
+ #define QUERY_DEV_CAP_RSZ_SRQ_OFFSET 0x33
+ #define QUERY_DEV_CAP_ACK_DELAY_OFFSET 0x35
+@@ -215,6 +216,13 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
+ dev_cap->max_requester_per_qp = 1 << (field & 0x3f);
+ MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_RES_QP_OFFSET);
+ dev_cap->max_responder_per_qp = 1 << (field & 0x3f);
++ MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GSO_OFFSET);
++ field &= 0x1f;
++ if (!field)
++ dev_cap->max_gso_sz = 0;
++ else
++ dev_cap->max_gso_sz = 1 << field;
++
+ MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_RDMA_OFFSET);
+ dev_cap->max_rdma_global = 1 << (field & 0x3f);
+ MLX4_GET(field, outbox, QUERY_DEV_CAP_ACK_DELAY_OFFSET);
+@@ -377,6 +385,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
+ dev_cap->max_sq_desc_sz, dev_cap->max_sq_sg);
+ mlx4_dbg(dev, "Max RQ desc size: %d, max RQ S/G: %d\n",
+ dev_cap->max_rq_desc_sz, dev_cap->max_rq_sg);
++ mlx4_dbg(dev, "Max GSO size: %d\n", dev_cap->max_gso_sz);
+
+ dump_dev_cap_flags(dev, dev_cap->flags);
+
+@@ -696,6 +705,10 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
+ /* Check port for UD address vector: */
+ *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1);
+
++ /* Enable IPoIB checksumming if we can: */
++ if (dev->caps.flags & MLX4_DEV_CAP_FLAG_IPOIB_CSUM)
++ *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 3);
++
+ /* QPC/EEC/CQC/EQC/RDMARC attributes */
+
+ MLX4_PUT(inbox, param->qpc_base, INIT_HCA_QPC_BASE_OFFSET);
+diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
+index e16dec8..306cb9b 100644
+--- a/drivers/net/mlx4/fw.h
++++ b/drivers/net/mlx4/fw.h
+@@ -96,6 +96,7 @@ struct mlx4_dev_cap {
+ u8 bmme_flags;
+ u32 reserved_lkey;
+ u64 max_icm_sz;
++ int max_gso_sz;
+ };
+
+ struct mlx4_adapter {
+diff --git a/drivers/net/mlx4/intf.c b/drivers/net/mlx4/intf.c
+index be5d9e9..4a6c4d5 100644
+--- a/drivers/net/mlx4/intf.c
++++ b/drivers/net/mlx4/intf.c
+@@ -30,8 +30,6 @@
+ * SOFTWARE.
+ */
+
+-#include <linux/mlx4/driver.h>
+-
+ #include "mlx4.h"
+
+ struct mlx4_device_context {
+@@ -113,8 +111,7 @@ void mlx4_unregister_interface(struct mlx4_interface *intf)
+ }
+ EXPORT_SYMBOL_GPL(mlx4_unregister_interface);
+
+-void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_event type,
+- int subtype, int port)
++void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type, int port)
+ {
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct mlx4_device_context *dev_ctx;
+@@ -124,8 +121,7 @@ void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_event type,
+
+ list_for_each_entry(dev_ctx, &priv->ctx_list, list)
+ if (dev_ctx->intf->event)
+- dev_ctx->intf->event(dev, dev_ctx->context, type,
+- subtype, port);
++ dev_ctx->intf->event(dev, dev_ctx->context, type, port);
+
+ spin_unlock_irqrestore(&priv->ctx_lock, flags);
+ }
+diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
+index 08bfc13..49a4aca 100644
+--- a/drivers/net/mlx4/main.c
++++ b/drivers/net/mlx4/main.c
+@@ -76,7 +76,7 @@ static char mlx4_version[] __devinitdata =
+ DRV_VERSION " (" DRV_RELDATE ")\n";
+
+ static struct mlx4_profile default_profile = {
+- .num_qp = 1 << 16,
++ .num_qp = 1 << 17,
+ .num_srq = 1 << 16,
+ .rdmarc_per_qp = 1 << 4,
+ .num_cq = 1 << 16,
+@@ -159,6 +159,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
+ dev->caps.page_size_cap = ~(u32) (dev_cap->min_page_sz - 1);
+ dev->caps.flags = dev_cap->flags;
+ dev->caps.stat_rate_support = dev_cap->stat_rate_support;
++ dev->caps.max_gso_sz = dev_cap->max_gso_sz;
+
+ return 0;
+ }
+@@ -735,8 +736,7 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ }
+
+ /*
+- * Check for BARs. We expect 0: 1MB, 2: 8MB, 4: DDR (may not
+- * be present)
++ * Check for BARs. We expect 0: 1MB
+ */
+ if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) ||
+ pci_resource_len(pdev, 0) != 1 << 20) {
+diff --git a/drivers/net/mlx4/mcg.c b/drivers/net/mlx4/mcg.c
+index a99e772..57f7f1f 100644
+--- a/drivers/net/mlx4/mcg.c
++++ b/drivers/net/mlx4/mcg.c
+@@ -190,10 +190,6 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16])
+ }
+ index += dev->caps.num_mgms;
+
+- err = mlx4_READ_MCG(dev, index, mailbox);
+- if (err)
+- goto out;
+-
+ memset(mgm, 0, sizeof *mgm);
+ memcpy(mgm->gid, gid, 16);
+ }
+@@ -301,12 +297,10 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16])
+ mgm->qp[loc] = mgm->qp[i - 1];
+ mgm->qp[i - 1] = 0;
+
+- err = mlx4_WRITE_MCG(dev, index, mailbox);
+- if (err)
+- goto out;
+-
+- if (i != 1)
++ if (i != 1) {
++ err = mlx4_WRITE_MCG(dev, index, mailbox);
+ goto out;
++ }
+
+ if (prev == -1) {
+ /* Remove entry from MGM */
+diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
+index 53a1cdd..7333681 100644
+--- a/drivers/net/mlx4/mlx4.h
++++ b/drivers/net/mlx4/mlx4.h
+@@ -42,6 +42,7 @@
+ #include <linux/timer.h>
+
+ #include <linux/mlx4/device.h>
++#include <linux/mlx4/driver.h>
+ #include <linux/mlx4/doorbell.h>
+
+ #define DRV_NAME "mlx4_core"
+@@ -313,8 +314,7 @@ void mlx4_catas_cleanup(void);
+ int mlx4_restart_one(struct pci_dev *pdev);
+ int mlx4_register_device(struct mlx4_dev *dev);
+ void mlx4_unregister_device(struct mlx4_dev *dev);
+-void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_event type,
+- int subtype, int port);
++void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type, int port);
+
+ struct mlx4_dev_cap;
+ struct mlx4_init_hca_param;
+diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
+index 771139e..381b36e 100644
+--- a/drivers/net/mv643xx_eth.c
++++ b/drivers/net/mv643xx_eth.c
+@@ -3,7 +3,8 @@
+ * Copyright (C) 2002 Matthew Dharm <mdharm at momenco.com>
+ *
+ * Based on the 64360 driver from:
+- * Copyright (C) 2002 rabeeh at galileo.co.il
++ * Copyright (C) 2002 Rabeeh Khoury <rabeeh at galileo.co.il>
++ * Rabeeh Khoury <rabeeh at marvell.com>
+ *
+ * Copyright (C) 2003 PMC-Sierra, Inc.,
+ * written by Manish Lachwani
+@@ -16,6 +17,9 @@
+ * Copyright (C) 2004 Steven J. Hill <sjhill1 at rockwellcollins.com>
+ * <sjhill at realitydiluted.com>
+ *
++ * Copyright (C) 2007-2008 Marvell Semiconductor
++ * Lennert Buytenhek <buytenh at marvell.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
+@@ -63,20 +67,6 @@
+ #define MV643XX_TX_FAST_REFILL
+ #undef MV643XX_COAL
+
+-/*
+- * Number of RX / TX descriptors on RX / TX rings.
+- * Note that allocating RX descriptors is done by allocating the RX
+- * ring AND a preallocated RX buffers (skb's) for each descriptor.
+- * The TX descriptors only allocates the TX descriptors ring,
+- * with no pre allocated TX buffers (skb's are allocated by higher layers.
+- */
+-
+-/* Default TX ring size is 1000 descriptors */
+-#define MV643XX_DEFAULT_TX_QUEUE_SIZE 1000
+-
+-/* Default RX ring size is 400 descriptors */
+-#define MV643XX_DEFAULT_RX_QUEUE_SIZE 400
+-
+ #define MV643XX_TX_COAL 100
+ #ifdef MV643XX_COAL
+ #define MV643XX_RX_COAL 100
+@@ -434,14 +424,6 @@ typedef enum _eth_func_ret_status {
+ ETH_QUEUE_LAST_RESOURCE /* Ring resources about to exhaust. */
+ } ETH_FUNC_RET_STATUS;
+
+-typedef enum _eth_target {
+- ETH_TARGET_DRAM,
+- ETH_TARGET_DEVICE,
+- ETH_TARGET_CBS,
+- ETH_TARGET_PCI0,
+- ETH_TARGET_PCI1
+-} ETH_TARGET;
+-
+ /* These are for big-endian machines. Little endian needs different
+ * definitions.
+ */
+@@ -586,43 +568,44 @@ struct mv643xx_private {
+
+ /* Static function declarations */
+ static void eth_port_init(struct mv643xx_private *mp);
+-static void eth_port_reset(unsigned int eth_port_num);
++static void eth_port_reset(struct mv643xx_private *mp);
+ static void eth_port_start(struct net_device *dev);
+
+-static void ethernet_phy_reset(unsigned int eth_port_num);
++static void ethernet_phy_reset(struct mv643xx_private *mp);
+
+-static void eth_port_write_smi_reg(unsigned int eth_port_num,
++static void eth_port_write_smi_reg(struct mv643xx_private *mp,
+ unsigned int phy_reg, unsigned int value);
+
+-static void eth_port_read_smi_reg(unsigned int eth_port_num,
++static void eth_port_read_smi_reg(struct mv643xx_private *mp,
+ unsigned int phy_reg, unsigned int *value);
+
+-static void eth_clear_mib_counters(unsigned int eth_port_num);
++static void eth_clear_mib_counters(struct mv643xx_private *mp);
+
+ static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp,
+ struct pkt_info *p_pkt_info);
+ static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv643xx_private *mp,
+ struct pkt_info *p_pkt_info);
+
+-static void eth_port_uc_addr_get(unsigned int port_num, unsigned char *p_addr);
+-static void eth_port_uc_addr_set(unsigned int port_num, unsigned char *p_addr);
++static void eth_port_uc_addr_get(struct mv643xx_private *mp,
++ unsigned char *p_addr);
++static void eth_port_uc_addr_set(struct mv643xx_private *mp,
++ unsigned char *p_addr);
+ static void eth_port_set_multicast_list(struct net_device *);
+-static void mv643xx_eth_port_enable_tx(unsigned int port_num,
++static void mv643xx_eth_port_enable_tx(struct mv643xx_private *mp,
+ unsigned int queues);
+-static void mv643xx_eth_port_enable_rx(unsigned int port_num,
++static void mv643xx_eth_port_enable_rx(struct mv643xx_private *mp,
+ unsigned int queues);
+-static unsigned int mv643xx_eth_port_disable_tx(unsigned int port_num);
+-static unsigned int mv643xx_eth_port_disable_rx(unsigned int port_num);
++static unsigned int mv643xx_eth_port_disable_tx(struct mv643xx_private *mp);
++static unsigned int mv643xx_eth_port_disable_rx(struct mv643xx_private *mp);
+ static int mv643xx_eth_open(struct net_device *);
+ static int mv643xx_eth_stop(struct net_device *);
+-static int mv643xx_eth_change_mtu(struct net_device *, int);
+-static void eth_port_init_mac_tables(unsigned int eth_port_num);
++static void eth_port_init_mac_tables(struct mv643xx_private *mp);
+ #ifdef MV643XX_NAPI
+ static int mv643xx_poll(struct napi_struct *napi, int budget);
+ #endif
+-static int ethernet_phy_get(unsigned int eth_port_num);
+-static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr);
+-static int ethernet_phy_detect(unsigned int eth_port_num);
++static int ethernet_phy_get(struct mv643xx_private *mp);
++static void ethernet_phy_set(struct mv643xx_private *mp, int phy_addr);
++static int ethernet_phy_detect(struct mv643xx_private *mp);
+ static int mv643xx_mdio_read(struct net_device *dev, int phy_id, int location);
+ static void mv643xx_mdio_write(struct net_device *dev, int phy_id, int location, int val);
+ static int mv643xx_eth_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+@@ -636,12 +619,12 @@ static void __iomem *mv643xx_eth_base;
+ /* used to protect SMI_REG, which is shared across ports */
+ static DEFINE_SPINLOCK(mv643xx_eth_phy_lock);
+
+-static inline u32 mv_read(int offset)
++static inline u32 rdl(struct mv643xx_private *mp, int offset)
+ {
+ return readl(mv643xx_eth_base + offset);
+ }
+
+-static inline void mv_write(int offset, u32 data)
++static inline void wrl(struct mv643xx_private *mp, int offset, u32 data)
+ {
+ writel(data, mv643xx_eth_base + offset);
+ }
+@@ -659,18 +642,19 @@ static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu)
+ return -EINVAL;
+
+ dev->mtu = new_mtu;
++ if (!netif_running(dev))
++ return 0;
++
+ /*
+- * Stop then re-open the interface. This will allocate RX skb's with
+- * the new MTU.
+- * There is a possible danger that the open will not successed, due
+- * to memory is full, which might fail the open function.
++ * Stop and then re-open the interface. This will allocate RX
++ * skbs of the new MTU.
++ * There is a possible danger that the open will not succeed,
++ * due to memory being full, which might fail the open function.
+ */
+- if (netif_running(dev)) {
+- mv643xx_eth_stop(dev);
+- if (mv643xx_eth_open(dev))
+- printk(KERN_ERR
+- "%s: Fatal error on opening device\n",
+- dev->name);
++ mv643xx_eth_stop(dev);
++ if (mv643xx_eth_open(dev)) {
++ printk(KERN_ERR "%s: Fatal error on opening device\n",
++ dev->name);
+ }
+
+ return 0;
+@@ -748,10 +732,9 @@ static inline void mv643xx_eth_rx_refill_descs_timer_wrapper(unsigned long data)
+ static void mv643xx_eth_update_mac_address(struct net_device *dev)
+ {
+ struct mv643xx_private *mp = netdev_priv(dev);
+- unsigned int port_num = mp->port_num;
+
+- eth_port_init_mac_tables(port_num);
+- eth_port_uc_addr_set(port_num, dev->dev_addr);
++ eth_port_init_mac_tables(mp);
++ eth_port_uc_addr_set(mp, dev->dev_addr);
+ }
+
+ /*
+@@ -767,12 +750,12 @@ static void mv643xx_eth_set_rx_mode(struct net_device *dev)
+ struct mv643xx_private *mp = netdev_priv(dev);
+ u32 config_reg;
+
+- config_reg = mv_read(PORT_CONFIG_REG(mp->port_num));
++ config_reg = rdl(mp, PORT_CONFIG_REG(mp->port_num));
+ if (dev->flags & IFF_PROMISC)
+ config_reg |= (u32) UNICAST_PROMISCUOUS_MODE;
+ else
+ config_reg &= ~(u32) UNICAST_PROMISCUOUS_MODE;
+- mv_write(PORT_CONFIG_REG(mp->port_num), config_reg);
++ wrl(mp, PORT_CONFIG_REG(mp->port_num), config_reg);
+
+ eth_port_set_multicast_list(dev);
+ }
+@@ -826,14 +809,14 @@ static void mv643xx_eth_tx_timeout_task(struct work_struct *ugly)
+ {
+ struct mv643xx_private *mp = container_of(ugly, struct mv643xx_private,
+ tx_timeout_task);
+- struct net_device *dev = mp->mii.dev; /* yuck */
++ struct net_device *dev = mp->dev;
+
+ if (!netif_running(dev))
+ return;
+
+ netif_stop_queue(dev);
+
+- eth_port_reset(mp->port_num);
++ eth_port_reset(mp);
+ eth_port_start(dev);
+
+ if (mp->tx_ring_size - mp->tx_desc_count >= MAX_DESCS_PER_SKB)
+@@ -845,7 +828,7 @@ static void mv643xx_eth_tx_timeout_task(struct work_struct *ugly)
+ *
+ * If force is non-zero, frees uncompleted descriptors as well
+ */
+-int mv643xx_eth_free_tx_descs(struct net_device *dev, int force)
++static int mv643xx_eth_free_tx_descs(struct net_device *dev, int force)
+ {
+ struct mv643xx_private *mp = netdev_priv(dev);
+ struct eth_tx_desc *desc;
+@@ -1008,7 +991,7 @@ static void mv643xx_eth_update_pscr(struct net_device *dev,
+ u32 o_pscr, n_pscr;
+ unsigned int queues;
+
+- o_pscr = mv_read(PORT_SERIAL_CONTROL_REG(port_num));
++ o_pscr = rdl(mp, PORT_SERIAL_CONTROL_REG(port_num));
+ n_pscr = o_pscr;
+
+ /* clear speed, duplex and rx buffer size fields */
+@@ -1031,16 +1014,16 @@ static void mv643xx_eth_update_pscr(struct net_device *dev,
+
+ if (n_pscr != o_pscr) {
+ if ((o_pscr & SERIAL_PORT_ENABLE) == 0)
+- mv_write(PORT_SERIAL_CONTROL_REG(port_num), n_pscr);
++ wrl(mp, PORT_SERIAL_CONTROL_REG(port_num), n_pscr);
+ else {
+- queues = mv643xx_eth_port_disable_tx(port_num);
++ queues = mv643xx_eth_port_disable_tx(mp);
+
+ o_pscr &= ~SERIAL_PORT_ENABLE;
+- mv_write(PORT_SERIAL_CONTROL_REG(port_num), o_pscr);
+- mv_write(PORT_SERIAL_CONTROL_REG(port_num), n_pscr);
+- mv_write(PORT_SERIAL_CONTROL_REG(port_num), n_pscr);
++ wrl(mp, PORT_SERIAL_CONTROL_REG(port_num), o_pscr);
++ wrl(mp, PORT_SERIAL_CONTROL_REG(port_num), n_pscr);
++ wrl(mp, PORT_SERIAL_CONTROL_REG(port_num), n_pscr);
+ if (queues)
+- mv643xx_eth_port_enable_tx(port_num, queues);
++ mv643xx_eth_port_enable_tx(mp, queues);
+ }
+ }
+ }
+@@ -1064,13 +1047,13 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id)
+ unsigned int port_num = mp->port_num;
+
+ /* Read interrupt cause registers */
+- eth_int_cause = mv_read(INTERRUPT_CAUSE_REG(port_num)) &
++ eth_int_cause = rdl(mp, INTERRUPT_CAUSE_REG(port_num)) &
+ ETH_INT_UNMASK_ALL;
+ if (eth_int_cause & ETH_INT_CAUSE_EXT) {
+- eth_int_cause_ext = mv_read(
++ eth_int_cause_ext = rdl(mp,
+ INTERRUPT_CAUSE_EXTEND_REG(port_num)) &
+ ETH_INT_UNMASK_ALL_EXT;
+- mv_write(INTERRUPT_CAUSE_EXTEND_REG(port_num),
++ wrl(mp, INTERRUPT_CAUSE_EXTEND_REG(port_num),
+ ~eth_int_cause_ext);
+ }
+
+@@ -1081,8 +1064,7 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id)
+ if (mii_link_ok(&mp->mii)) {
+ mii_ethtool_gset(&mp->mii, &cmd);
+ mv643xx_eth_update_pscr(dev, &cmd);
+- mv643xx_eth_port_enable_tx(port_num,
+- ETH_TX_QUEUES_ENABLED);
++ mv643xx_eth_port_enable_tx(mp, ETH_TX_QUEUES_ENABLED);
+ if (!netif_carrier_ok(dev)) {
+ netif_carrier_on(dev);
+ if (mp->tx_ring_size - mp->tx_desc_count >=
+@@ -1098,10 +1080,10 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id)
+ #ifdef MV643XX_NAPI
+ if (eth_int_cause & ETH_INT_CAUSE_RX) {
+ /* schedule the NAPI poll routine to maintain port */
+- mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
++ wrl(mp, INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
+
+ /* wait for previous write to complete */
+- mv_read(INTERRUPT_MASK_REG(port_num));
++ rdl(mp, INTERRUPT_MASK_REG(port_num));
+
+ netif_rx_schedule(dev, &mp->napi);
+ }
+@@ -1136,7 +1118,7 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id)
+ * , and the required delay of the interrupt in usec.
+ *
+ * INPUT:
+- * unsigned int eth_port_num Ethernet port number
++ * struct mv643xx_private *mp Ethernet port
+ * unsigned int t_clk t_clk of the MV-643xx chip in HZ units
+ * unsigned int delay Delay in usec
+ *
+@@ -1147,15 +1129,16 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id)
+ * The interrupt coalescing value set in the gigE port.
+ *
+ */
+-static unsigned int eth_port_set_rx_coal(unsigned int eth_port_num,
++static unsigned int eth_port_set_rx_coal(struct mv643xx_private *mp,
+ unsigned int t_clk, unsigned int delay)
+ {
++ unsigned int port_num = mp->port_num;
+ unsigned int coal = ((t_clk / 1000000) * delay) / 64;
+
+ /* Set RX Coalescing mechanism */
+- mv_write(SDMA_CONFIG_REG(eth_port_num),
++ wrl(mp, SDMA_CONFIG_REG(port_num),
+ ((coal & 0x3fff) << 8) |
+- (mv_read(SDMA_CONFIG_REG(eth_port_num))
++ (rdl(mp, SDMA_CONFIG_REG(port_num))
+ & 0xffc000ff));
+
+ return coal;
+@@ -1174,7 +1157,7 @@ static unsigned int eth_port_set_rx_coal(unsigned int eth_port_num,
+ * MV-643xx chip and the required delay in the interrupt in uSec
+ *
+ * INPUT:
+- * unsigned int eth_port_num Ethernet port number
++ * struct mv643xx_private *mp Ethernet port
+ * unsigned int t_clk t_clk of the MV-643xx chip in HZ units
+ * unsigned int delay Delay in uSeconds
+ *
+@@ -1185,13 +1168,14 @@ static unsigned int eth_port_set_rx_coal(unsigned int eth_port_num,
+ * The interrupt coalescing value set in the gigE port.
+ *
+ */
+-static unsigned int eth_port_set_tx_coal(unsigned int eth_port_num,
++static unsigned int eth_port_set_tx_coal(struct mv643xx_private *mp,
+ unsigned int t_clk, unsigned int delay)
+ {
+- unsigned int coal;
+- coal = ((t_clk / 1000000) * delay) / 64;
++ unsigned int coal = ((t_clk / 1000000) * delay) / 64;
++
+ /* Set TX Coalescing mechanism */
+- mv_write(TX_FIFO_URGENT_THRESHOLD_REG(eth_port_num), coal << 4);
++ wrl(mp, TX_FIFO_URGENT_THRESHOLD_REG(mp->port_num), coal << 4);
++
+ return coal;
+ }
+
+@@ -1327,16 +1311,15 @@ static int mv643xx_eth_open(struct net_device *dev)
+ int err;
+
+ /* Clear any pending ethernet port interrupts */
+- mv_write(INTERRUPT_CAUSE_REG(port_num), 0);
+- mv_write(INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
++ wrl(mp, INTERRUPT_CAUSE_REG(port_num), 0);
++ wrl(mp, INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+ /* wait for previous write to complete */
+- mv_read (INTERRUPT_CAUSE_EXTEND_REG(port_num));
++ rdl(mp, INTERRUPT_CAUSE_EXTEND_REG(port_num));
+
+ err = request_irq(dev->irq, mv643xx_eth_int_handler,
+ IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, dev);
+ if (err) {
+- printk(KERN_ERR "Can not assign IRQ number to MV643XX_eth%d\n",
+- port_num);
++ printk(KERN_ERR "%s: Can not assign IRQ\n", dev->name);
+ return -EAGAIN;
+ }
+
+@@ -1430,17 +1413,17 @@ static int mv643xx_eth_open(struct net_device *dev)
+
+ #ifdef MV643XX_COAL
+ mp->rx_int_coal =
+- eth_port_set_rx_coal(port_num, 133000000, MV643XX_RX_COAL);
++ eth_port_set_rx_coal(mp, 133000000, MV643XX_RX_COAL);
+ #endif
+
+ mp->tx_int_coal =
+- eth_port_set_tx_coal(port_num, 133000000, MV643XX_TX_COAL);
++ eth_port_set_tx_coal(mp, 133000000, MV643XX_TX_COAL);
+
+ /* Unmask phy and link status changes interrupts */
+- mv_write(INTERRUPT_EXTEND_MASK_REG(port_num), ETH_INT_UNMASK_ALL_EXT);
++ wrl(mp, INTERRUPT_EXTEND_MASK_REG(port_num), ETH_INT_UNMASK_ALL_EXT);
+
+ /* Unmask RX buffer and TX end interrupt */
+- mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
++ wrl(mp, INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
+
+ return 0;
+
+@@ -1459,7 +1442,7 @@ static void mv643xx_eth_free_tx_rings(struct net_device *dev)
+ struct mv643xx_private *mp = netdev_priv(dev);
+
+ /* Stop Tx Queues */
+- mv643xx_eth_port_disable_tx(mp->port_num);
++ mv643xx_eth_port_disable_tx(mp);
+
+ /* Free outstanding skb's on TX ring */
+ mv643xx_eth_free_all_tx_descs(dev);
+@@ -1477,11 +1460,10 @@ static void mv643xx_eth_free_tx_rings(struct net_device *dev)
+ static void mv643xx_eth_free_rx_rings(struct net_device *dev)
+ {
+ struct mv643xx_private *mp = netdev_priv(dev);
+- unsigned int port_num = mp->port_num;
+ int curr;
+
+ /* Stop RX Queues */
+- mv643xx_eth_port_disable_rx(port_num);
++ mv643xx_eth_port_disable_rx(mp);
+
+ /* Free preallocated skb's on RX rings */
+ for (curr = 0; mp->rx_desc_count && curr < mp->rx_ring_size; curr++) {
+@@ -1520,9 +1502,9 @@ static int mv643xx_eth_stop(struct net_device *dev)
+ unsigned int port_num = mp->port_num;
+
+ /* Mask all interrupts on ethernet port */
+- mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
++ wrl(mp, INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
+ /* wait for previous write to complete */
+- mv_read(INTERRUPT_MASK_REG(port_num));
++ rdl(mp, INTERRUPT_MASK_REG(port_num));
+
+ #ifdef MV643XX_NAPI
+ napi_disable(&mp->napi);
+@@ -1530,7 +1512,7 @@ static int mv643xx_eth_stop(struct net_device *dev)
+ netif_carrier_off(dev);
+ netif_stop_queue(dev);
+
+- eth_port_reset(mp->port_num);
++ eth_port_reset(mp);
+
+ mv643xx_eth_free_tx_rings(dev);
+ mv643xx_eth_free_rx_rings(dev);
+@@ -1561,15 +1543,15 @@ static int mv643xx_poll(struct napi_struct *napi, int budget)
+ #endif
+
+ work_done = 0;
+- if ((mv_read(RX_CURRENT_QUEUE_DESC_PTR_0(port_num)))
++ if ((rdl(mp, RX_CURRENT_QUEUE_DESC_PTR_0(port_num)))
+ != (u32) mp->rx_used_desc_q)
+ work_done = mv643xx_eth_receive_queue(dev, budget);
+
+ if (work_done < budget) {
+ netif_rx_complete(dev, napi);
+- mv_write(INTERRUPT_CAUSE_REG(port_num), 0);
+- mv_write(INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+- mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
++ wrl(mp, INTERRUPT_CAUSE_REG(port_num), 0);
++ wrl(mp, INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
++ wrl(mp, INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
+ }
+
+ return work_done;
+@@ -1723,7 +1705,7 @@ static void eth_tx_submit_descs_for_skb(struct mv643xx_private *mp,
+
+ /* ensure all descriptors are written before poking hardware */
+ wmb();
+- mv643xx_eth_port_enable_tx(mp->port_num, ETH_TX_QUEUES_ENABLED);
++ mv643xx_eth_port_enable_tx(mp, ETH_TX_QUEUES_ENABLED);
+
+ mp->tx_desc_count += nr_frags + 1;
+ }
+@@ -1739,25 +1721,23 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ unsigned long flags;
+
+ BUG_ON(netif_queue_stopped(dev));
+- BUG_ON(skb == NULL);
++
++ if (has_tiny_unaligned_frags(skb) && __skb_linearize(skb)) {
++ stats->tx_dropped++;
++ printk(KERN_DEBUG "%s: failed to linearize tiny "
++ "unaligned fragment\n", dev->name);
++ return NETDEV_TX_BUSY;
++ }
++
++ spin_lock_irqsave(&mp->lock, flags);
+
+ if (mp->tx_ring_size - mp->tx_desc_count < MAX_DESCS_PER_SKB) {
+ printk(KERN_ERR "%s: transmit with queue full\n", dev->name);
+ netif_stop_queue(dev);
+- return 1;
+- }
+-
+- if (has_tiny_unaligned_frags(skb)) {
+- if (__skb_linearize(skb)) {
+- stats->tx_dropped++;
+- printk(KERN_DEBUG "%s: failed to linearize tiny "
+- "unaligned fragment\n", dev->name);
+- return 1;
+- }
++ spin_unlock_irqrestore(&mp->lock, flags);
++ return NETDEV_TX_BUSY;
+ }
+
+- spin_lock_irqsave(&mp->lock, flags);
+-
+ eth_tx_submit_descs_for_skb(mp, skb);
+ stats->tx_bytes += skb->len;
+ stats->tx_packets++;
+@@ -1768,7 +1748,7 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
+
+ spin_unlock_irqrestore(&mp->lock, flags);
+
+- return 0; /* success */
++ return NETDEV_TX_OK;
+ }
+
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+@@ -1777,13 +1757,13 @@ static void mv643xx_netpoll(struct net_device *netdev)
+ struct mv643xx_private *mp = netdev_priv(netdev);
+ int port_num = mp->port_num;
+
+- mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
++ wrl(mp, INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
+ /* wait for previous write to complete */
+- mv_read(INTERRUPT_MASK_REG(port_num));
++ rdl(mp, INTERRUPT_MASK_REG(port_num));
+
+ mv643xx_eth_int_handler(netdev->irq, netdev);
+
+- mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
++ wrl(mp, INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
+ }
+ #endif
+
+@@ -1900,7 +1880,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
+ port_num = mp->port_num = pd->port_number;
+
+ /* set default config values */
+- eth_port_uc_addr_get(port_num, dev->dev_addr);
++ eth_port_uc_addr_get(mp, dev->dev_addr);
+ mp->rx_ring_size = PORT_DEFAULT_RECEIVE_QUEUE_SIZE;
+ mp->tx_ring_size = PORT_DEFAULT_TRANSMIT_QUEUE_SIZE;
+
+@@ -1908,7 +1888,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
+ memcpy(dev->dev_addr, pd->mac_addr, 6);
+
+ if (pd->phy_addr || pd->force_phy_addr)
+- ethernet_phy_set(port_num, pd->phy_addr);
++ ethernet_phy_set(mp, pd->phy_addr);
+
+ if (pd->rx_queue_size)
+ mp->rx_ring_size = pd->rx_queue_size;
+@@ -1933,19 +1913,18 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
+ mp->mii.dev = dev;
+ mp->mii.mdio_read = mv643xx_mdio_read;
+ mp->mii.mdio_write = mv643xx_mdio_write;
+- mp->mii.phy_id = ethernet_phy_get(port_num);
++ mp->mii.phy_id = ethernet_phy_get(mp);
+ mp->mii.phy_id_mask = 0x3f;
+ mp->mii.reg_num_mask = 0x1f;
+
+- err = ethernet_phy_detect(port_num);
++ err = ethernet_phy_detect(mp);
+ if (err) {
+- pr_debug("MV643xx ethernet port %d: "
+- "No PHY detected at addr %d\n",
+- port_num, ethernet_phy_get(port_num));
++ pr_debug("%s: No PHY detected at addr %d\n",
++ dev->name, ethernet_phy_get(mp));
+ goto out;
+ }
+
+- ethernet_phy_reset(port_num);
++ ethernet_phy_reset(mp);
+ mp->mii.supports_gmii = mii_check_gmii_support(&mp->mii);
+ mv643xx_init_ethtool_cmd(dev, mp->mii.phy_id, speed, duplex, &cmd);
+ mv643xx_eth_update_pscr(dev, &cmd);
+@@ -2006,9 +1985,11 @@ static int mv643xx_eth_remove(struct platform_device *pdev)
+
+ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
+ {
++ static int mv643xx_version_printed = 0;
+ struct resource *res;
+
+- printk(KERN_NOTICE "MV-643xx 10/100/1000 Ethernet Driver\n");
++ if (!mv643xx_version_printed++)
++ printk(KERN_NOTICE "MV-643xx 10/100/1000 Ethernet Driver\n");
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL)
+@@ -2037,10 +2018,10 @@ static void mv643xx_eth_shutdown(struct platform_device *pdev)
+ unsigned int port_num = mp->port_num;
+
+ /* Mask all interrupts on ethernet port */
+- mv_write(INTERRUPT_MASK_REG(port_num), 0);
+- mv_read (INTERRUPT_MASK_REG(port_num));
++ wrl(mp, INTERRUPT_MASK_REG(port_num), 0);
++ rdl(mp, INTERRUPT_MASK_REG(port_num));
+
+- eth_port_reset(port_num);
++ eth_port_reset(mp);
+ }
+
+ static struct platform_driver mv643xx_eth_driver = {
+@@ -2049,6 +2030,7 @@ static struct platform_driver mv643xx_eth_driver = {
+ .shutdown = mv643xx_eth_shutdown,
+ .driver = {
+ .name = MV643XX_ETH_NAME,
++ .owner = THIS_MODULE,
+ },
+ };
+
+@@ -2057,6 +2039,7 @@ static struct platform_driver mv643xx_eth_shared_driver = {
+ .remove = mv643xx_eth_shared_remove,
+ .driver = {
+ .name = MV643XX_ETH_SHARED_NAME,
++ .owner = THIS_MODULE,
+ },
+ };
+
+@@ -2104,7 +2087,8 @@ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR( "Rabeeh Khoury, Assaf Hoffman, Matthew Dharm, Manish Lachwani"
+ " and Dale Farnsworth");
+ MODULE_DESCRIPTION("Ethernet driver for Marvell MV643XX");
+-MODULE_ALIAS("platform:mv643xx_eth");
++MODULE_ALIAS("platform:" MV643XX_ETH_NAME);
++MODULE_ALIAS("platform:" MV643XX_ETH_SHARED_NAME);
+
+ /*
+ * The second part is the low level driver of the gigE ethernet ports.
+@@ -2229,12 +2213,9 @@ MODULE_ALIAS("platform:mv643xx_eth");
+ * return_info Tx/Rx user resource return information.
+ */
+
+-/* PHY routines */
+-static int ethernet_phy_get(unsigned int eth_port_num);
+-static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr);
+-
+ /* Ethernet Port routines */
+-static void eth_port_set_filter_table_entry(int table, unsigned char entry);
++static void eth_port_set_filter_table_entry(struct mv643xx_private *mp,
++ int table, unsigned char entry);
+
+ /*
+ * eth_port_init - Initialize the Ethernet port driver
+@@ -2264,9 +2245,9 @@ static void eth_port_init(struct mv643xx_private *mp)
+ {
+ mp->rx_resource_err = 0;
+
+- eth_port_reset(mp->port_num);
++ eth_port_reset(mp);
+
+- eth_port_init_mac_tables(mp->port_num);
++ eth_port_init_mac_tables(mp);
+ }
+
+ /*
+@@ -2306,28 +2287,28 @@ static void eth_port_start(struct net_device *dev)
+
+ /* Assignment of Tx CTRP of given queue */
+ tx_curr_desc = mp->tx_curr_desc_q;
+- mv_write(TX_CURRENT_QUEUE_DESC_PTR_0(port_num),
++ wrl(mp, TX_CURRENT_QUEUE_DESC_PTR_0(port_num),
+ (u32)((struct eth_tx_desc *)mp->tx_desc_dma + tx_curr_desc));
+
+ /* Assignment of Rx CRDP of given queue */
+ rx_curr_desc = mp->rx_curr_desc_q;
+- mv_write(RX_CURRENT_QUEUE_DESC_PTR_0(port_num),
++ wrl(mp, RX_CURRENT_QUEUE_DESC_PTR_0(port_num),
+ (u32)((struct eth_rx_desc *)mp->rx_desc_dma + rx_curr_desc));
+
+ /* Add the assigned Ethernet address to the port's address table */
+- eth_port_uc_addr_set(port_num, dev->dev_addr);
++ eth_port_uc_addr_set(mp, dev->dev_addr);
+
+ /* Assign port configuration and command. */
+- mv_write(PORT_CONFIG_REG(port_num),
++ wrl(mp, PORT_CONFIG_REG(port_num),
+ PORT_CONFIG_DEFAULT_VALUE);
+
+- mv_write(PORT_CONFIG_EXTEND_REG(port_num),
++ wrl(mp, PORT_CONFIG_EXTEND_REG(port_num),
+ PORT_CONFIG_EXTEND_DEFAULT_VALUE);
+
+- pscr = mv_read(PORT_SERIAL_CONTROL_REG(port_num));
++ pscr = rdl(mp, PORT_SERIAL_CONTROL_REG(port_num));
+
+ pscr &= ~(SERIAL_PORT_ENABLE | FORCE_LINK_PASS);
+- mv_write(PORT_SERIAL_CONTROL_REG(port_num), pscr);
++ wrl(mp, PORT_SERIAL_CONTROL_REG(port_num), pscr);
+
+ pscr |= DISABLE_AUTO_NEG_FOR_FLOW_CTRL |
+ DISABLE_AUTO_NEG_SPEED_GMII |
+@@ -2335,32 +2316,34 @@ static void eth_port_start(struct net_device *dev)
+ DO_NOT_FORCE_LINK_FAIL |
+ SERIAL_PORT_CONTROL_RESERVED;
+
+- mv_write(PORT_SERIAL_CONTROL_REG(port_num), pscr);
++ wrl(mp, PORT_SERIAL_CONTROL_REG(port_num), pscr);
+
+ pscr |= SERIAL_PORT_ENABLE;
+- mv_write(PORT_SERIAL_CONTROL_REG(port_num), pscr);
++ wrl(mp, PORT_SERIAL_CONTROL_REG(port_num), pscr);
+
+ /* Assign port SDMA configuration */
+- mv_write(SDMA_CONFIG_REG(port_num),
++ wrl(mp, SDMA_CONFIG_REG(port_num),
+ PORT_SDMA_CONFIG_DEFAULT_VALUE);
+
+ /* Enable port Rx. */
+- mv643xx_eth_port_enable_rx(port_num, ETH_RX_QUEUES_ENABLED);
++ mv643xx_eth_port_enable_rx(mp, ETH_RX_QUEUES_ENABLED);
+
+ /* Disable port bandwidth limits by clearing MTU register */
+- mv_write(MAXIMUM_TRANSMIT_UNIT(port_num), 0);
++ wrl(mp, MAXIMUM_TRANSMIT_UNIT(port_num), 0);
+
+ /* save phy settings across reset */
+ mv643xx_get_settings(dev, ðtool_cmd);
+- ethernet_phy_reset(mp->port_num);
++ ethernet_phy_reset(mp);
+ mv643xx_set_settings(dev, ðtool_cmd);
+ }
+
+ /*
+ * eth_port_uc_addr_set - Write a MAC address into the port's hw registers
+ */
+-static void eth_port_uc_addr_set(unsigned int port_num, unsigned char *p_addr)
++static void eth_port_uc_addr_set(struct mv643xx_private *mp,
++ unsigned char *p_addr)
+ {
++ unsigned int port_num = mp->port_num;
+ unsigned int mac_h;
+ unsigned int mac_l;
+ int table;
+@@ -2369,24 +2352,26 @@ static void eth_port_uc_addr_set(unsigned int port_num, unsigned char *p_addr)
+ mac_h = (p_addr[0] << 24) | (p_addr[1] << 16) | (p_addr[2] << 8) |
+ (p_addr[3] << 0);
+
+- mv_write(MAC_ADDR_LOW(port_num), mac_l);
+- mv_write(MAC_ADDR_HIGH(port_num), mac_h);
++ wrl(mp, MAC_ADDR_LOW(port_num), mac_l);
++ wrl(mp, MAC_ADDR_HIGH(port_num), mac_h);
+
+ /* Accept frames with this address */
+ table = DA_FILTER_UNICAST_TABLE_BASE(port_num);
+- eth_port_set_filter_table_entry(table, p_addr[5] & 0x0f);
++ eth_port_set_filter_table_entry(mp, table, p_addr[5] & 0x0f);
+ }
+
+ /*
+ * eth_port_uc_addr_get - Read the MAC address from the port's hw registers
+ */
+-static void eth_port_uc_addr_get(unsigned int port_num, unsigned char *p_addr)
++static void eth_port_uc_addr_get(struct mv643xx_private *mp,
++ unsigned char *p_addr)
+ {
++ unsigned int port_num = mp->port_num;
+ unsigned int mac_h;
+ unsigned int mac_l;
+
+- mac_h = mv_read(MAC_ADDR_HIGH(port_num));
+- mac_l = mv_read(MAC_ADDR_LOW(port_num));
++ mac_h = rdl(mp, MAC_ADDR_HIGH(port_num));
++ mac_l = rdl(mp, MAC_ADDR_LOW(port_num));
+
+ p_addr[0] = (mac_h >> 24) & 0xff;
+ p_addr[1] = (mac_h >> 16) & 0xff;
+@@ -2405,7 +2390,8 @@ static void eth_port_uc_addr_get(unsigned int port_num, unsigned char *p_addr)
+ * 3-1 Queue (ETH_Q0=0)
+ * 7-4 Reserved = 0;
+ */
+-static void eth_port_set_filter_table_entry(int table, unsigned char entry)
++static void eth_port_set_filter_table_entry(struct mv643xx_private *mp,
++ int table, unsigned char entry)
+ {
+ unsigned int table_reg;
+ unsigned int tbl_offset;
+@@ -2415,9 +2401,9 @@ static void eth_port_set_filter_table_entry(int table, unsigned char entry)
+ reg_offset = entry % 4; /* Entry offset within the register */
+
+ /* Set "accepts frame bit" at specified table entry */
+- table_reg = mv_read(table + tbl_offset);
++ table_reg = rdl(mp, table + tbl_offset);
+ table_reg |= 0x01 << (8 * reg_offset);
+- mv_write(table + tbl_offset, table_reg);
++ wrl(mp, table + tbl_offset, table_reg);
+ }
+
+ /*
+@@ -2434,8 +2420,9 @@ static void eth_port_set_filter_table_entry(int table, unsigned char entry)
+ * In either case, eth_port_set_filter_table_entry() is then called
+ * to set to set the actual table entry.
+ */
+-static void eth_port_mc_addr(unsigned int eth_port_num, unsigned char *p_addr)
++static void eth_port_mc_addr(struct mv643xx_private *mp, unsigned char *p_addr)
+ {
++ unsigned int port_num = mp->port_num;
+ unsigned int mac_h;
+ unsigned int mac_l;
+ unsigned char crc_result = 0;
+@@ -2446,9 +2433,8 @@ static void eth_port_mc_addr(unsigned int eth_port_num, unsigned char *p_addr)
+
+ if ((p_addr[0] == 0x01) && (p_addr[1] == 0x00) &&
+ (p_addr[2] == 0x5E) && (p_addr[3] == 0x00) && (p_addr[4] == 0x00)) {
+- table = DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+- (eth_port_num);
+- eth_port_set_filter_table_entry(table, p_addr[5]);
++ table = DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(port_num);
++ eth_port_set_filter_table_entry(mp, table, p_addr[5]);
+ return;
+ }
+
+@@ -2520,8 +2506,8 @@ static void eth_port_mc_addr(unsigned int eth_port_num, unsigned char *p_addr)
+ for (i = 0; i < 8; i++)
+ crc_result = crc_result | (crc[i] << i);
+
+- table = DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num);
+- eth_port_set_filter_table_entry(table, crc_result);
++ table = DA_FILTER_OTHER_MULTICAST_TABLE_BASE(port_num);
++ eth_port_set_filter_table_entry(mp, table, crc_result);
+ }
+
+ /*
+@@ -2550,7 +2536,7 @@ static void eth_port_set_multicast_list(struct net_device *dev)
+ * 3-1 Queue ETH_Q0=0
+ * 7-4 Reserved = 0;
+ */
+- mv_write(DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
++ wrl(mp, DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
+
+ /* Set all entries in DA filter other multicast
+ * table (Ex_dFOMT)
+@@ -2560,7 +2546,7 @@ static void eth_port_set_multicast_list(struct net_device *dev)
+ * 3-1 Queue ETH_Q0=0
+ * 7-4 Reserved = 0;
+ */
+- mv_write(DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
++ wrl(mp, DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
+ }
+ return;
+ }
+@@ -2570,11 +2556,11 @@ static void eth_port_set_multicast_list(struct net_device *dev)
+ */
+ for (table_index = 0; table_index <= 0xFC; table_index += 4) {
+ /* Clear DA filter special multicast table (Ex_dFSMT) */
+- mv_write(DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
++ wrl(mp, DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+ (eth_port_num) + table_index, 0);
+
+ /* Clear DA filter other multicast table (Ex_dFOMT) */
+- mv_write(DA_FILTER_OTHER_MULTICAST_TABLE_BASE
++ wrl(mp, DA_FILTER_OTHER_MULTICAST_TABLE_BASE
+ (eth_port_num) + table_index, 0);
+ }
+
+@@ -2583,7 +2569,7 @@ static void eth_port_set_multicast_list(struct net_device *dev)
+ (i < 256) && (mc_list != NULL) && (i < dev->mc_count);
+ i++, mc_list = mc_list->next)
+ if (mc_list->dmi_addrlen == 6)
+- eth_port_mc_addr(eth_port_num, mc_list->dmi_addr);
++ eth_port_mc_addr(mp, mc_list->dmi_addr);
+ }
+
+ /*
+@@ -2594,7 +2580,7 @@ static void eth_port_set_multicast_list(struct net_device *dev)
+ * Other Multicast) and set each entry to 0.
+ *
+ * INPUT:
+- * unsigned int eth_port_num Ethernet Port number.
++ * struct mv643xx_private *mp Ethernet Port.
+ *
+ * OUTPUT:
+ * Multicast and Unicast packets are rejected.
+@@ -2602,22 +2588,23 @@ static void eth_port_set_multicast_list(struct net_device *dev)
+ * RETURN:
+ * None.
+ */
+-static void eth_port_init_mac_tables(unsigned int eth_port_num)
++static void eth_port_init_mac_tables(struct mv643xx_private *mp)
+ {
++ unsigned int port_num = mp->port_num;
+ int table_index;
+
+ /* Clear DA filter unicast table (Ex_dFUT) */
+ for (table_index = 0; table_index <= 0xC; table_index += 4)
+- mv_write(DA_FILTER_UNICAST_TABLE_BASE
+- (eth_port_num) + table_index, 0);
++ wrl(mp, DA_FILTER_UNICAST_TABLE_BASE(port_num) +
++ table_index, 0);
+
+ for (table_index = 0; table_index <= 0xFC; table_index += 4) {
+ /* Clear DA filter special multicast table (Ex_dFSMT) */
+- mv_write(DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+- (eth_port_num) + table_index, 0);
++ wrl(mp, DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(port_num) +
++ table_index, 0);
+ /* Clear DA filter other multicast table (Ex_dFOMT) */
+- mv_write(DA_FILTER_OTHER_MULTICAST_TABLE_BASE
+- (eth_port_num) + table_index, 0);
++ wrl(mp, DA_FILTER_OTHER_MULTICAST_TABLE_BASE(port_num) +
++ table_index, 0);
+ }
+ }
+
+@@ -2629,7 +2616,7 @@ static void eth_port_init_mac_tables(unsigned int eth_port_num)
+ * A read from the MIB counter will reset the counter.
+ *
+ * INPUT:
+- * unsigned int eth_port_num Ethernet Port number.
++ * struct mv643xx_private *mp Ethernet Port.
+ *
+ * OUTPUT:
+ * After reading all MIB counters, the counters resets.
+@@ -2638,19 +2625,20 @@ static void eth_port_init_mac_tables(unsigned int eth_port_num)
+ * MIB counter value.
+ *
+ */
+-static void eth_clear_mib_counters(unsigned int eth_port_num)
++static void eth_clear_mib_counters(struct mv643xx_private *mp)
+ {
++ unsigned int port_num = mp->port_num;
+ int i;
+
+ /* Perform dummy reads from MIB counters */
+ for (i = ETH_MIB_GOOD_OCTETS_RECEIVED_LOW; i < ETH_MIB_LATE_COLLISION;
+ i += 4)
+- mv_read(MIB_COUNTERS_BASE(eth_port_num) + i);
++ rdl(mp, MIB_COUNTERS_BASE(port_num) + i);
+ }
+
+ static inline u32 read_mib(struct mv643xx_private *mp, int offset)
+ {
+- return mv_read(MIB_COUNTERS_BASE(mp->port_num) + offset);
++ return rdl(mp, MIB_COUNTERS_BASE(mp->port_num) + offset);
+ }
+
+ static void eth_update_mib_counters(struct mv643xx_private *mp)
+@@ -2686,7 +2674,7 @@ static void eth_update_mib_counters(struct mv643xx_private *mp)
+ * the specified port.
+ *
+ * INPUT:
+- * unsigned int eth_port_num Ethernet Port number.
++ * struct mv643xx_private *mp Ethernet Port.
+ *
+ * OUTPUT:
+ * None
+@@ -2696,22 +2684,22 @@ static void eth_update_mib_counters(struct mv643xx_private *mp)
+ * -ENODEV on failure
+ *
+ */
+-static int ethernet_phy_detect(unsigned int port_num)
++static int ethernet_phy_detect(struct mv643xx_private *mp)
+ {
+ unsigned int phy_reg_data0;
+ int auto_neg;
+
+- eth_port_read_smi_reg(port_num, 0, &phy_reg_data0);
++ eth_port_read_smi_reg(mp, 0, &phy_reg_data0);
+ auto_neg = phy_reg_data0 & 0x1000;
+ phy_reg_data0 ^= 0x1000; /* invert auto_neg */
+- eth_port_write_smi_reg(port_num, 0, phy_reg_data0);
++ eth_port_write_smi_reg(mp, 0, phy_reg_data0);
+
+- eth_port_read_smi_reg(port_num, 0, &phy_reg_data0);
++ eth_port_read_smi_reg(mp, 0, &phy_reg_data0);
+ if ((phy_reg_data0 & 0x1000) == auto_neg)
+ return -ENODEV; /* change didn't take */
+
+ phy_reg_data0 ^= 0x1000;
+- eth_port_write_smi_reg(port_num, 0, phy_reg_data0);
++ eth_port_write_smi_reg(mp, 0, phy_reg_data0);
+ return 0;
+ }
+
+@@ -2722,7 +2710,7 @@ static int ethernet_phy_detect(unsigned int port_num)
+ * This routine returns the given ethernet port PHY address.
+ *
+ * INPUT:
+- * unsigned int eth_port_num Ethernet Port number.
++ * struct mv643xx_private *mp Ethernet Port.
+ *
+ * OUTPUT:
+ * None.
+@@ -2731,13 +2719,13 @@ static int ethernet_phy_detect(unsigned int port_num)
+ * PHY address.
+ *
+ */
+-static int ethernet_phy_get(unsigned int eth_port_num)
++static int ethernet_phy_get(struct mv643xx_private *mp)
+ {
+ unsigned int reg_data;
+
+- reg_data = mv_read(PHY_ADDR_REG);
++ reg_data = rdl(mp, PHY_ADDR_REG);
+
+- return ((reg_data >> (5 * eth_port_num)) & 0x1f);
++ return ((reg_data >> (5 * mp->port_num)) & 0x1f);
+ }
+
+ /*
+@@ -2747,7 +2735,7 @@ static int ethernet_phy_get(unsigned int eth_port_num)
+ * This routine sets the given ethernet port PHY address.
+ *
+ * INPUT:
+- * unsigned int eth_port_num Ethernet Port number.
++ * struct mv643xx_private *mp Ethernet Port.
+ * int phy_addr PHY address.
+ *
+ * OUTPUT:
+@@ -2757,15 +2745,15 @@ static int ethernet_phy_get(unsigned int eth_port_num)
+ * None.
+ *
+ */
+-static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr)
++static void ethernet_phy_set(struct mv643xx_private *mp, int phy_addr)
+ {
+ u32 reg_data;
+- int addr_shift = 5 * eth_port_num;
++ int addr_shift = 5 * mp->port_num;
+
+- reg_data = mv_read(PHY_ADDR_REG);
++ reg_data = rdl(mp, PHY_ADDR_REG);
+ reg_data &= ~(0x1f << addr_shift);
+ reg_data |= (phy_addr & 0x1f) << addr_shift;
+- mv_write(PHY_ADDR_REG, reg_data);
++ wrl(mp, PHY_ADDR_REG, reg_data);
+ }
+
+ /*
+@@ -2775,7 +2763,7 @@ static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr)
+ * This routine utilizes the SMI interface to reset the ethernet port PHY.
+ *
+ * INPUT:
+- * unsigned int eth_port_num Ethernet Port number.
++ * struct mv643xx_private *mp Ethernet Port.
+ *
+ * OUTPUT:
+ * The PHY is reset.
+@@ -2784,51 +2772,52 @@ static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr)
+ * None.
+ *
+ */
+-static void ethernet_phy_reset(unsigned int eth_port_num)
++static void ethernet_phy_reset(struct mv643xx_private *mp)
+ {
+ unsigned int phy_reg_data;
+
+ /* Reset the PHY */
+- eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data);
++ eth_port_read_smi_reg(mp, 0, &phy_reg_data);
+ phy_reg_data |= 0x8000; /* Set bit 15 to reset the PHY */
+- eth_port_write_smi_reg(eth_port_num, 0, phy_reg_data);
++ eth_port_write_smi_reg(mp, 0, phy_reg_data);
+
+ /* wait for PHY to come out of reset */
+ do {
+ udelay(1);
+- eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data);
++ eth_port_read_smi_reg(mp, 0, &phy_reg_data);
+ } while (phy_reg_data & 0x8000);
+ }
+
+-static void mv643xx_eth_port_enable_tx(unsigned int port_num,
++static void mv643xx_eth_port_enable_tx(struct mv643xx_private *mp,
+ unsigned int queues)
+ {
+- mv_write(TRANSMIT_QUEUE_COMMAND_REG(port_num), queues);
++ wrl(mp, TRANSMIT_QUEUE_COMMAND_REG(mp->port_num), queues);
+ }
+
+-static void mv643xx_eth_port_enable_rx(unsigned int port_num,
++static void mv643xx_eth_port_enable_rx(struct mv643xx_private *mp,
+ unsigned int queues)
+ {
+- mv_write(RECEIVE_QUEUE_COMMAND_REG(port_num), queues);
++ wrl(mp, RECEIVE_QUEUE_COMMAND_REG(mp->port_num), queues);
+ }
+
+-static unsigned int mv643xx_eth_port_disable_tx(unsigned int port_num)
++static unsigned int mv643xx_eth_port_disable_tx(struct mv643xx_private *mp)
+ {
++ unsigned int port_num = mp->port_num;
+ u32 queues;
+
+ /* Stop Tx port activity. Check port Tx activity. */
+- queues = mv_read(TRANSMIT_QUEUE_COMMAND_REG(port_num)) & 0xFF;
++ queues = rdl(mp, TRANSMIT_QUEUE_COMMAND_REG(port_num)) & 0xFF;
+ if (queues) {
+ /* Issue stop command for active queues only */
+- mv_write(TRANSMIT_QUEUE_COMMAND_REG(port_num), (queues << 8));
++ wrl(mp, TRANSMIT_QUEUE_COMMAND_REG(port_num), (queues << 8));
+
+ /* Wait for all Tx activity to terminate. */
+ /* Check port cause register that all Tx queues are stopped */
+- while (mv_read(TRANSMIT_QUEUE_COMMAND_REG(port_num)) & 0xFF)
++ while (rdl(mp, TRANSMIT_QUEUE_COMMAND_REG(port_num)) & 0xFF)
+ udelay(PHY_WAIT_MICRO_SECONDS);
+
+ /* Wait for Tx FIFO to empty */
+- while (mv_read(PORT_STATUS_REG(port_num)) &
++ while (rdl(mp, PORT_STATUS_REG(port_num)) &
+ ETH_PORT_TX_FIFO_EMPTY)
+ udelay(PHY_WAIT_MICRO_SECONDS);
+ }
+@@ -2836,19 +2825,20 @@ static unsigned int mv643xx_eth_port_disable_tx(unsigned int port_num)
+ return queues;
+ }
+
+-static unsigned int mv643xx_eth_port_disable_rx(unsigned int port_num)
++static unsigned int mv643xx_eth_port_disable_rx(struct mv643xx_private *mp)
+ {
++ unsigned int port_num = mp->port_num;
+ u32 queues;
+
+ /* Stop Rx port activity. Check port Rx activity. */
+- queues = mv_read(RECEIVE_QUEUE_COMMAND_REG(port_num)) & 0xFF;
++ queues = rdl(mp, RECEIVE_QUEUE_COMMAND_REG(port_num)) & 0xFF;
+ if (queues) {
+ /* Issue stop command for active queues only */
+- mv_write(RECEIVE_QUEUE_COMMAND_REG(port_num), (queues << 8));
++ wrl(mp, RECEIVE_QUEUE_COMMAND_REG(port_num), (queues << 8));
+
+ /* Wait for all Rx activity to terminate. */
+ /* Check port cause register that all Rx queues are stopped */
+- while (mv_read(RECEIVE_QUEUE_COMMAND_REG(port_num)) & 0xFF)
++ while (rdl(mp, RECEIVE_QUEUE_COMMAND_REG(port_num)) & 0xFF)
+ udelay(PHY_WAIT_MICRO_SECONDS);
+ }
+
+@@ -2864,7 +2854,7 @@ static unsigned int mv643xx_eth_port_disable_rx(unsigned int port_num)
+ * idle state after this command is performed and the port is disabled.
+ *
+ * INPUT:
+- * unsigned int eth_port_num Ethernet Port number.
++ * struct mv643xx_private *mp Ethernet Port.
+ *
+ * OUTPUT:
+ * Channel activity is halted.
+@@ -2873,22 +2863,23 @@ static unsigned int mv643xx_eth_port_disable_rx(unsigned int port_num)
+ * None.
+ *
+ */
+-static void eth_port_reset(unsigned int port_num)
++static void eth_port_reset(struct mv643xx_private *mp)
+ {
++ unsigned int port_num = mp->port_num;
+ unsigned int reg_data;
+
+- mv643xx_eth_port_disable_tx(port_num);
+- mv643xx_eth_port_disable_rx(port_num);
++ mv643xx_eth_port_disable_tx(mp);
++ mv643xx_eth_port_disable_rx(mp);
+
+ /* Clear all MIB counters */
+- eth_clear_mib_counters(port_num);
++ eth_clear_mib_counters(mp);
+
+ /* Reset the Enable bit in the Configuration Register */
+- reg_data = mv_read(PORT_SERIAL_CONTROL_REG(port_num));
++ reg_data = rdl(mp, PORT_SERIAL_CONTROL_REG(port_num));
+ reg_data &= ~(SERIAL_PORT_ENABLE |
+ DO_NOT_FORCE_LINK_FAIL |
+ FORCE_LINK_PASS);
+- mv_write(PORT_SERIAL_CONTROL_REG(port_num), reg_data);
++ wrl(mp, PORT_SERIAL_CONTROL_REG(port_num), reg_data);
+ }
+
+
+@@ -2900,7 +2891,7 @@ static void eth_port_reset(unsigned int port_num)
+ * order to perform PHY register read.
+ *
+ * INPUT:
+- * unsigned int port_num Ethernet Port number.
++ * struct mv643xx_private *mp Ethernet Port.
+ * unsigned int phy_reg PHY register address offset.
+ * unsigned int *value Register value buffer.
+ *
+@@ -2912,10 +2903,10 @@ static void eth_port_reset(unsigned int port_num)
+ * true otherwise.
+ *
+ */
+-static void eth_port_read_smi_reg(unsigned int port_num,
++static void eth_port_read_smi_reg(struct mv643xx_private *mp,
+ unsigned int phy_reg, unsigned int *value)
+ {
+- int phy_addr = ethernet_phy_get(port_num);
++ int phy_addr = ethernet_phy_get(mp);
+ unsigned long flags;
+ int i;
+
+@@ -2923,27 +2914,27 @@ static void eth_port_read_smi_reg(unsigned int port_num,
+ spin_lock_irqsave(&mv643xx_eth_phy_lock, flags);
+
+ /* wait for the SMI register to become available */
+- for (i = 0; mv_read(SMI_REG) & ETH_SMI_BUSY; i++) {
++ for (i = 0; rdl(mp, SMI_REG) & ETH_SMI_BUSY; i++) {
+ if (i == PHY_WAIT_ITERATIONS) {
+- printk("mv643xx PHY busy timeout, port %d\n", port_num);
++ printk("%s: PHY busy timeout\n", mp->dev->name);
+ goto out;
+ }
+ udelay(PHY_WAIT_MICRO_SECONDS);
+ }
+
+- mv_write(SMI_REG,
++ wrl(mp, SMI_REG,
+ (phy_addr << 16) | (phy_reg << 21) | ETH_SMI_OPCODE_READ);
+
+ /* now wait for the data to be valid */
+- for (i = 0; !(mv_read(SMI_REG) & ETH_SMI_READ_VALID); i++) {
++ for (i = 0; !(rdl(mp, SMI_REG) & ETH_SMI_READ_VALID); i++) {
+ if (i == PHY_WAIT_ITERATIONS) {
+- printk("mv643xx PHY read timeout, port %d\n", port_num);
++ printk("%s: PHY read timeout\n", mp->dev->name);
+ goto out;
+ }
+ udelay(PHY_WAIT_MICRO_SECONDS);
+ }
+
+- *value = mv_read(SMI_REG) & 0xffff;
++ *value = rdl(mp, SMI_REG) & 0xffff;
+ out:
+ spin_unlock_irqrestore(&mv643xx_eth_phy_lock, flags);
+ }
+@@ -2956,7 +2947,7 @@ out:
+ * order to perform writes to PHY registers.
+ *
+ * INPUT:
+- * unsigned int eth_port_num Ethernet Port number.
++ * struct mv643xx_private *mp Ethernet Port.
+ * unsigned int phy_reg PHY register address offset.
+ * unsigned int value Register value.
+ *
+@@ -2968,29 +2959,28 @@ out:
+ * true otherwise.
+ *
+ */
+-static void eth_port_write_smi_reg(unsigned int eth_port_num,
++static void eth_port_write_smi_reg(struct mv643xx_private *mp,
+ unsigned int phy_reg, unsigned int value)
+ {
+ int phy_addr;
+ int i;
+ unsigned long flags;
+
+- phy_addr = ethernet_phy_get(eth_port_num);
++ phy_addr = ethernet_phy_get(mp);
+
+ /* the SMI register is a shared resource */
+ spin_lock_irqsave(&mv643xx_eth_phy_lock, flags);
+
+ /* wait for the SMI register to become available */
+- for (i = 0; mv_read(SMI_REG) & ETH_SMI_BUSY; i++) {
++ for (i = 0; rdl(mp, SMI_REG) & ETH_SMI_BUSY; i++) {
+ if (i == PHY_WAIT_ITERATIONS) {
+- printk("mv643xx PHY busy timeout, port %d\n",
+- eth_port_num);
++ printk("%s: PHY busy timeout\n", mp->dev->name);
+ goto out;
+ }
+ udelay(PHY_WAIT_MICRO_SECONDS);
+ }
+
+- mv_write(SMI_REG, (phy_addr << 16) | (phy_reg << 21) |
++ wrl(mp, SMI_REG, (phy_addr << 16) | (phy_reg << 21) |
+ ETH_SMI_OPCODE_WRITE | (value & 0xffff));
+ out:
+ spin_unlock_irqrestore(&mv643xx_eth_phy_lock, flags);
+@@ -3001,17 +2991,17 @@ out:
+ */
+ static int mv643xx_mdio_read(struct net_device *dev, int phy_id, int location)
+ {
+- int val;
+ struct mv643xx_private *mp = netdev_priv(dev);
++ int val;
+
+- eth_port_read_smi_reg(mp->port_num, location, &val);
++ eth_port_read_smi_reg(mp, location, &val);
+ return val;
+ }
+
+ static void mv643xx_mdio_write(struct net_device *dev, int phy_id, int location, int val)
+ {
+ struct mv643xx_private *mp = netdev_priv(dev);
+- eth_port_write_smi_reg(mp->port_num, location, val);
++ eth_port_write_smi_reg(mp, location, val);
+ }
+
+ /*
+@@ -3156,7 +3146,7 @@ struct mv643xx_stats {
+ int stat_offset;
+ };
+
+-#define MV643XX_STAT(m) sizeof(((struct mv643xx_private *)0)->m), \
++#define MV643XX_STAT(m) FIELD_SIZEOF(struct mv643xx_private, m), \
+ offsetof(struct mv643xx_private, m)
+
+ static const struct mv643xx_stats mv643xx_gstrings_stats[] = {
+diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
+index 385f69c..46119bb 100644
+--- a/drivers/net/natsemi.c
++++ b/drivers/net/natsemi.c
+@@ -511,10 +511,10 @@ enum PhyCtrl_bits {
+ /* Note that using only 32 bit fields simplifies conversion to big-endian
+ architectures. */
+ struct netdev_desc {
+- u32 next_desc;
+- s32 cmd_status;
+- u32 addr;
+- u32 software_use;
++ __le32 next_desc;
++ __le32 cmd_status;
++ __le32 addr;
++ __le32 software_use;
+ };
+
+ /* Bits in network_desc.status */
+@@ -786,7 +786,8 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
+ struct netdev_private *np;
+ int i, option, irq, chip_idx = ent->driver_data;
+ static int find_cnt = -1;
+- unsigned long iostart, iosize;
++ resource_size_t iostart;
++ unsigned long iosize;
+ void __iomem *ioaddr;
+ const int pcibar = 1; /* PCI base address register */
+ int prev_eedata;
+@@ -946,10 +947,11 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
+ goto err_create_file;
+
+ if (netif_msg_drv(np)) {
+- printk(KERN_INFO "natsemi %s: %s at %#08lx "
++ printk(KERN_INFO "natsemi %s: %s at %#08llx "
+ "(%s), %s, IRQ %d",
+- dev->name, natsemi_pci_info[chip_idx].name, iostart,
+- pci_name(np->pci_dev), print_mac(mac, dev->dev_addr), irq);
++ dev->name, natsemi_pci_info[chip_idx].name,
++ (unsigned long long)iostart, pci_name(np->pci_dev),
++ print_mac(mac, dev->dev_addr), irq);
+ if (dev->if_port == PORT_TP)
+ printk(", port TP.\n");
+ else if (np->ignore_phy)
+@@ -2018,7 +2020,7 @@ static void drain_rx(struct net_device *dev)
+ /* Free all the skbuffs in the Rx queue. */
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ np->rx_ring[i].cmd_status = 0;
+- np->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */
++ np->rx_ring[i].addr = cpu_to_le32(0xBADF00D0); /* An invalid address. */
+ if (np->rx_skbuff[i]) {
+ pci_unmap_single(np->pci_dev,
+ np->rx_dma[i], buflen,
+diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c
+index 78d34af..dc442e3 100644
+--- a/drivers/net/netx-eth.c
++++ b/drivers/net/netx-eth.c
+@@ -502,4 +502,4 @@ module_exit(netx_eth_cleanup);
+
+ MODULE_AUTHOR("Sascha Hauer, Pengutronix");
+ MODULE_LICENSE("GPL");
+-
++MODULE_ALIAS("platform:" CARDNAME);
+diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
+index 7f20a03..8cb29f5 100644
+--- a/drivers/net/netxen/netxen_nic.h
++++ b/drivers/net/netxen/netxen_nic.h
+@@ -95,23 +95,6 @@
+
+ #define ADDR_IN_WINDOW1(off) \
+ ((off > NETXEN_CRB_PCIX_HOST2) && (off < NETXEN_CRB_MAX)) ? 1 : 0
+-/*
+- * In netxen_nic_down(), we must wait for any pending callback requests into
+- * netxen_watchdog_task() to complete; eg otherwise the watchdog_timer could be
+- * reenabled right after it is deleted in netxen_nic_down(). FLUSH_SCHEDULED_WORK()
+- * does this synchronization.
+- *
+- * Normally, schedule_work()/flush_scheduled_work() could have worked, but
+- * netxen_nic_close() is invoked with kernel rtnl lock held. netif_carrier_off()
+- * call in netxen_nic_close() triggers a schedule_work(&linkwatch_work), and a
+- * subsequent call to flush_scheduled_work() in netxen_nic_down() would cause
+- * linkwatch_event() to be executed which also attempts to acquire the rtnl
+- * lock thus causing a deadlock.
+- */
+-
+-#define SCHEDULE_WORK(tp) queue_work(netxen_workq, tp)
+-#define FLUSH_SCHEDULED_WORK() flush_workqueue(netxen_workq)
+-extern struct workqueue_struct *netxen_workq;
+
+ /*
+ * normalize a 64MB crb address to 32MB PCI window
+@@ -1050,7 +1033,6 @@ void netxen_halt_pegs(struct netxen_adapter *adapter);
+ int netxen_rom_se(struct netxen_adapter *adapter, int addr);
+
+ /* Functions from netxen_nic_isr.c */
+-int netxen_nic_link_ok(struct netxen_adapter *adapter);
+ void netxen_initialize_adapter_sw(struct netxen_adapter *adapter);
+ void netxen_initialize_adapter_hw(struct netxen_adapter *adapter);
+ void *netxen_alloc(struct pci_dev *pdev, size_t sz, dma_addr_t * ptr,
+diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h
+index 160f605..24d027e 100644
+--- a/drivers/net/netxen/netxen_nic_hdr.h
++++ b/drivers/net/netxen/netxen_nic_hdr.h
+@@ -34,7 +34,6 @@
+ #include <linux/kernel.h>
+ #include <linux/version.h>
+
+-#include <asm/semaphore.h>
+ #include <linux/spinlock.h>
+ #include <asm/irq.h>
+ #include <linux/init.h>
+diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
+index 05748ca..af73564 100644
+--- a/drivers/net/netxen/netxen_nic_hw.c
++++ b/drivers/net/netxen/netxen_nic_hw.c
+@@ -1132,8 +1132,8 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
+ u32 fw_minor = 0;
+ u32 fw_build = 0;
+ char brd_name[NETXEN_MAX_SHORT_NAME];
+- struct netxen_new_user_info user_info;
+- int i, addr = NETXEN_USER_START;
++ char serial_num[32];
++ int i, addr;
+ __le32 *ptr32;
+
+ struct netxen_board_info *board_info = &(adapter->ahw.boardcfg);
+@@ -1150,10 +1150,10 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
+ valid = 0;
+ }
+ if (valid) {
+- ptr32 = (u32 *) & user_info;
+- for (i = 0;
+- i < sizeof(struct netxen_new_user_info) / sizeof(u32);
+- i++) {
++ ptr32 = (u32 *)&serial_num;
++ addr = NETXEN_USER_START +
++ offsetof(struct netxen_new_user_info, serial_num);
++ for (i = 0; i < 8; i++) {
+ if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) {
+ printk("%s: ERROR reading %s board userarea.\n",
+ netxen_nic_driver_name,
+@@ -1163,10 +1163,11 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
+ ptr32++;
+ addr += sizeof(u32);
+ }
++
+ get_brd_name_by_type(board_info->board_type, brd_name);
+
+ printk("NetXen %s Board S/N %s Chip id 0x%x\n",
+- brd_name, user_info.serial_num, board_info->chip_id);
++ brd_name, serial_num, board_info->chip_id);
+
+ printk("NetXen %s Board #%d, Chip id 0x%x\n",
+ board_info->board_type == 0x0b ? "XGB" : "GBE",
+diff --git a/drivers/net/netxen/netxen_nic_isr.c b/drivers/net/netxen/netxen_nic_isr.c
+index c81313b..f487615 100644
+--- a/drivers/net/netxen/netxen_nic_isr.c
++++ b/drivers/net/netxen/netxen_nic_isr.c
+@@ -172,6 +172,7 @@ void netxen_nic_gbe_handle_phy_intr(struct netxen_adapter *adapter)
+ netxen_nic_isr_other(adapter);
+ }
+
++#if 0
+ int netxen_nic_link_ok(struct netxen_adapter *adapter)
+ {
+ switch (adapter->ahw.board_type) {
+@@ -189,6 +190,7 @@ int netxen_nic_link_ok(struct netxen_adapter *adapter)
+
+ return 0;
+ }
++#endif /* 0 */
+
+ void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter)
+ {
+diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
+index a8fb439..7144c25 100644
+--- a/drivers/net/netxen/netxen_nic_main.c
++++ b/drivers/net/netxen/netxen_nic_main.c
+@@ -86,7 +86,24 @@ static struct pci_device_id netxen_pci_tbl[] __devinitdata = {
+
+ MODULE_DEVICE_TABLE(pci, netxen_pci_tbl);
+
+-struct workqueue_struct *netxen_workq;
++/*
++ * In netxen_nic_down(), we must wait for any pending callback requests into
++ * netxen_watchdog_task() to complete; eg otherwise the watchdog_timer could be
++ * reenabled right after it is deleted in netxen_nic_down().
++ * FLUSH_SCHEDULED_WORK() does this synchronization.
++ *
++ * Normally, schedule_work()/flush_scheduled_work() could have worked, but
++ * netxen_nic_close() is invoked with kernel rtnl lock held. netif_carrier_off()
++ * call in netxen_nic_close() triggers a schedule_work(&linkwatch_work), and a
++ * subsequent call to flush_scheduled_work() in netxen_nic_down() would cause
++ * linkwatch_event() to be executed which also attempts to acquire the rtnl
++ * lock thus causing a deadlock.
++ */
++
++static struct workqueue_struct *netxen_workq;
++#define SCHEDULE_WORK(tp) queue_work(netxen_workq, tp)
++#define FLUSH_SCHEDULED_WORK() flush_workqueue(netxen_workq)
++
+ static void netxen_watchdog(unsigned long);
+
+ static void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
+diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c
+index 26aa8fe..a316dcc 100644
+--- a/drivers/net/ni52.c
++++ b/drivers/net/ni52.c
+@@ -134,10 +134,10 @@ static int fifo = 0x8; /* don't change */
+ #define ni_disint() { outb(0, dev->base_addr + NI52_INTDIS); }
+ #define ni_enaint() { outb(0, dev->base_addr + NI52_INTENA); }
+
+-#define make32(ptr16) (p->memtop + (short) (ptr16))
+-#define make24(ptr32) ((unsigned long)(ptr32)) - p->base
+-#define make16(ptr32) ((unsigned short) ((unsigned long)(ptr32)\
+- - (unsigned long) p->memtop))
++#define make32(ptr16) ((void __iomem *)(p->memtop + (short) (ptr16)))
++#define make24(ptr32) ((char __iomem *)(ptr32)) - p->base
++#define make16(ptr32) ((unsigned short) ((char __iomem *)(ptr32)\
++ - p->memtop))
+
+ /******************* how to calculate the buffers *****************************
+
+@@ -179,34 +179,35 @@ static void ni52_timeout(struct net_device *dev);
+
+ /* helper-functions */
+ static int init586(struct net_device *dev);
+-static int check586(struct net_device *dev, char *where, unsigned size);
++static int check586(struct net_device *dev, unsigned size);
+ static void alloc586(struct net_device *dev);
+ static void startrecv586(struct net_device *dev);
+-static void *alloc_rfa(struct net_device *dev, void *ptr);
++static void __iomem *alloc_rfa(struct net_device *dev, void __iomem *ptr);
+ static void ni52_rcv_int(struct net_device *dev);
+ static void ni52_xmt_int(struct net_device *dev);
+ static void ni52_rnr_int(struct net_device *dev);
+
+ struct priv {
+ struct net_device_stats stats;
+- unsigned long base;
+- char *memtop;
++ char __iomem *base;
++ char __iomem *mapped;
++ char __iomem *memtop;
+ spinlock_t spinlock;
+ int reset;
+- struct rfd_struct *rfd_last, *rfd_top, *rfd_first;
+- struct scp_struct *scp;
+- struct iscp_struct *iscp;
+- struct scb_struct *scb;
+- struct tbd_struct *xmit_buffs[NUM_XMIT_BUFFS];
++ struct rfd_struct __iomem *rfd_last, *rfd_top, *rfd_first;
++ struct scp_struct __iomem *scp;
++ struct iscp_struct __iomem *iscp;
++ struct scb_struct __iomem *scb;
++ struct tbd_struct __iomem *xmit_buffs[NUM_XMIT_BUFFS];
+ #if (NUM_XMIT_BUFFS == 1)
+- struct transmit_cmd_struct *xmit_cmds[2];
+- struct nop_cmd_struct *nop_cmds[2];
++ struct transmit_cmd_struct __iomem *xmit_cmds[2];
++ struct nop_cmd_struct __iomem *nop_cmds[2];
+ #else
+- struct transmit_cmd_struct *xmit_cmds[NUM_XMIT_BUFFS];
+- struct nop_cmd_struct *nop_cmds[NUM_XMIT_BUFFS];
++ struct transmit_cmd_struct __iomem *xmit_cmds[NUM_XMIT_BUFFS];
++ struct nop_cmd_struct __iomem *nop_cmds[NUM_XMIT_BUFFS];
+ #endif
+ int nop_point, num_recv_buffs;
+- char *xmit_cbuffs[NUM_XMIT_BUFFS];
++ char __iomem *xmit_cbuffs[NUM_XMIT_BUFFS];
+ int xmit_count, xmit_last;
+ };
+
+@@ -240,7 +241,8 @@ static void wait_for_scb_cmd_ruc(struct net_device *dev)
+ udelay(4);
+ if (i == 16383) {
+ printk(KERN_ERR "%s: scb_cmd (ruc) timed out: %04x,%04x .. disabling i82586!!\n",
+- dev->name, p->scb->cmd_ruc, p->scb->rus);
++ dev->name, readb(&p->scb->cmd_ruc),
++ readb(&p->scb->rus));
+ if (!p->reset) {
+ p->reset = 1;
+ ni_reset586();
+@@ -249,9 +251,9 @@ static void wait_for_scb_cmd_ruc(struct net_device *dev)
+ }
+ }
+
+-static void wait_for_stat_compl(void *p)
++static void wait_for_stat_compl(void __iomem *p)
+ {
+- struct nop_cmd_struct *addr = p;
++ struct nop_cmd_struct __iomem *addr = p;
+ int i;
+ for (i = 0; i < 32767; i++) {
+ if (readw(&((addr)->cmd_status)) & STAT_COMPL)
+@@ -293,47 +295,58 @@ static int ni52_open(struct net_device *dev)
+ return 0; /* most done by init */
+ }
+
++static int check_iscp(struct net_device *dev, void __iomem *addr)
++{
++ struct iscp_struct __iomem *iscp = addr;
++ struct priv *p = dev->priv;
++ memset_io(iscp, 0, sizeof(struct iscp_struct));
++
++ writel(make24(iscp), &p->scp->iscp);
++ writeb(1, &iscp->busy);
++
++ ni_reset586();
++ ni_attn586();
++ mdelay(32); /* wait a while... */
++ /* i82586 clears 'busy' after successful init */
++ if (readb(&iscp->busy))
++ return 0;
++ return 1;
++}
++
+ /**********************************************
+ * Check to see if there's an 82586 out there.
+ */
+-static int check586(struct net_device *dev, char *where, unsigned size)
++static int check586(struct net_device *dev, unsigned size)
+ {
+- struct priv pb;
+- struct priv *p = /* (struct priv *) dev->priv*/ &pb;
+- char *iscp_addrs[2];
++ struct priv *p = dev->priv;
+ int i;
+
+- p->base = (unsigned long) isa_bus_to_virt((unsigned long)where)
+- + size - 0x01000000;
+- p->memtop = isa_bus_to_virt((unsigned long)where) + size;
+- p->scp = (struct scp_struct *)(p->base + SCP_DEFAULT_ADDRESS);
+- memset_io((char *)p->scp, 0, sizeof(struct scp_struct));
++ p->mapped = ioremap(dev->mem_start, size);
++ if (!p->mapped)
++ return 0;
++
++ p->base = p->mapped + size - 0x01000000;
++ p->memtop = p->mapped + size;
++ p->scp = (struct scp_struct __iomem *)(p->base + SCP_DEFAULT_ADDRESS);
++ p->scb = (struct scb_struct __iomem *) p->mapped;
++ p->iscp = (struct iscp_struct __iomem *)p->scp - 1;
++ memset_io(p->scp, 0, sizeof(struct scp_struct));
+ for (i = 0; i < sizeof(struct scp_struct); i++)
+ /* memory was writeable? */
+- if (readb((char *)p->scp + i))
+- return 0;
++ if (readb((char __iomem *)p->scp + i))
++ goto Enodev;
+ writeb(SYSBUSVAL, &p->scp->sysbus); /* 1 = 8Bit-Bus, 0 = 16 Bit */
+ if (readb(&p->scp->sysbus) != SYSBUSVAL)
+- return 0;
+-
+- iscp_addrs[0] = isa_bus_to_virt((unsigned long)where);
+- iscp_addrs[1] = (char *) p->scp - sizeof(struct iscp_struct);
++ goto Enodev;
+
+- for (i = 0; i < 2; i++) {
+- p->iscp = (struct iscp_struct *) iscp_addrs[i];
+- memset_io((char *)p->iscp, 0, sizeof(struct iscp_struct));
+-
+- writel(make24(p->iscp), &p->scp->iscp);
+- writeb(1, &p->iscp->busy);
+-
+- ni_reset586();
+- ni_attn586();
+- mdelay(32); /* wait a while... */
+- /* i82586 clears 'busy' after successful init */
+- if (readb(&p->iscp->busy))
+- return 0;
+- }
++ if (!check_iscp(dev, p->mapped))
++ goto Enodev;
++ if (!check_iscp(dev, p->iscp))
++ goto Enodev;
+ return 1;
++Enodev:
++ iounmap(p->mapped);
++ return 0;
+ }
+
+ /******************************************************************
+@@ -346,13 +359,6 @@ static void alloc586(struct net_device *dev)
+ ni_reset586();
+ mdelay(32);
+
+- spin_lock_init(&p->spinlock);
+-
+- p->scp = (struct scp_struct *) (p->base + SCP_DEFAULT_ADDRESS);
+- p->scb = (struct scb_struct *) isa_bus_to_virt(dev->mem_start);
+- p->iscp = (struct iscp_struct *)
+- ((char *)p->scp - sizeof(struct iscp_struct));
+-
+ memset_io(p->iscp, 0, sizeof(struct iscp_struct));
+ memset_io(p->scp , 0, sizeof(struct scp_struct));
+
+@@ -371,7 +377,7 @@ static void alloc586(struct net_device *dev)
+
+ p->reset = 0;
+
+- memset_io((char *)p->scb, 0, sizeof(struct scb_struct));
++ memset_io(p->scb, 0, sizeof(struct scb_struct));
+ }
+
+ /* set: io,irq,memstart,memend or set it when calling insmod */
+@@ -387,12 +393,15 @@ struct net_device * __init ni52_probe(int unit)
+ {
+ struct net_device *dev = alloc_etherdev(sizeof(struct priv));
+ static int ports[] = {0x300, 0x280, 0x360 , 0x320 , 0x340, 0};
++ struct priv *p;
+ int *port;
+ int err = 0;
+
+ if (!dev)
+ return ERR_PTR(-ENOMEM);
+
++ p = dev->priv;
++
+ if (unit >= 0) {
+ sprintf(dev->name, "eth%d", unit);
+ netdev_boot_setup_check(dev);
+@@ -427,6 +436,7 @@ got_it:
+ goto out1;
+ return dev;
+ out1:
++ iounmap(p->mapped);
+ release_region(dev->base_addr, NI52_TOTAL_SIZE);
+ out:
+ free_netdev(dev);
+@@ -436,12 +446,15 @@ out:
+ static int __init ni52_probe1(struct net_device *dev, int ioaddr)
+ {
+ int i, size, retval;
++ struct priv *priv = dev->priv;
+
+ dev->base_addr = ioaddr;
+ dev->irq = irq;
+ dev->mem_start = memstart;
+ dev->mem_end = memend;
+
++ spin_lock_init(&priv->spinlock);
++
+ if (!request_region(ioaddr, NI52_TOTAL_SIZE, DRV_NAME))
+ return -EBUSY;
+
+@@ -474,7 +487,7 @@ static int __init ni52_probe1(struct net_device *dev, int ioaddr)
+ retval = -ENODEV;
+ goto out;
+ }
+- if (!check586(dev, (char *)dev->mem_start, size)) {
++ if (!check586(dev, size)) {
+ printk(KERN_ERR "?memcheck, Can't find memory at 0x%lx with size %d!\n", dev->mem_start, size);
+ retval = -ENODEV;
+ goto out;
+@@ -483,9 +496,9 @@ static int __init ni52_probe1(struct net_device *dev, int ioaddr)
+ if (dev->mem_start != 0) {
+ /* no auto-mem-probe */
+ size = 0x4000; /* check for 16K mem */
+- if (!check586(dev, (char *) dev->mem_start, size)) {
++ if (!check586(dev, size)) {
+ size = 0x2000; /* check for 8K mem */
+- if (!check586(dev, (char *)dev->mem_start, size)) {
++ if (!check586(dev, size)) {
+ printk(KERN_ERR "?memprobe, Can't find memory at 0x%lx!\n", dev->mem_start);
+ retval = -ENODEV;
+ goto out;
+@@ -504,11 +517,11 @@ static int __init ni52_probe1(struct net_device *dev, int ioaddr)
+ }
+ dev->mem_start = memaddrs[i];
+ size = 0x2000; /* check for 8K mem */
+- if (check586(dev, (char *)dev->mem_start, size))
++ if (check586(dev, size))
+ /* 8K-check */
+ break;
+ size = 0x4000; /* check for 16K mem */
+- if (check586(dev, (char *)dev->mem_start, size))
++ if (check586(dev, size))
+ /* 16K-check */
+ break;
+ }
+@@ -517,19 +530,13 @@ static int __init ni52_probe1(struct net_device *dev, int ioaddr)
+ dev->mem_end = dev->mem_start + size;
+ #endif
+
+- memset((char *)dev->priv, 0, sizeof(struct priv));
+-
+- ((struct priv *)(dev->priv))->memtop =
+- isa_bus_to_virt(dev->mem_start) + size;
+- ((struct priv *)(dev->priv))->base = (unsigned long)
+- isa_bus_to_virt(dev->mem_start) + size - 0x01000000;
+ alloc586(dev);
+
+ /* set number of receive-buffs according to memsize */
+ if (size == 0x2000)
+- ((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_8;
++ priv->num_recv_buffs = NUM_RECV_BUFFS_8;
+ else
+- ((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_16;
++ priv->num_recv_buffs = NUM_RECV_BUFFS_16;
+
+ printk(KERN_DEBUG "Memaddr: 0x%lx, Memsize: %d, ",
+ dev->mem_start, size);
+@@ -546,6 +553,7 @@ static int __init ni52_probe1(struct net_device *dev, int ioaddr)
+ if (!dev->irq) {
+ printk("?autoirq, Failed to detect IRQ line!\n");
+ retval = -EAGAIN;
++ iounmap(priv->mapped);
+ goto out;
+ }
+ printk("IRQ %d (autodetected).\n", dev->irq);
+@@ -578,19 +586,19 @@ out:
+
+ static int init586(struct net_device *dev)
+ {
+- void *ptr;
++ void __iomem *ptr;
+ int i, result = 0;
+ struct priv *p = (struct priv *)dev->priv;
+- struct configure_cmd_struct *cfg_cmd;
+- struct iasetup_cmd_struct *ias_cmd;
+- struct tdr_cmd_struct *tdr_cmd;
+- struct mcsetup_cmd_struct *mc_cmd;
++ struct configure_cmd_struct __iomem *cfg_cmd;
++ struct iasetup_cmd_struct __iomem *ias_cmd;
++ struct tdr_cmd_struct __iomem *tdr_cmd;
++ struct mcsetup_cmd_struct __iomem *mc_cmd;
+ struct dev_mc_list *dmi = dev->mc_list;
+ int num_addrs = dev->mc_count;
+
+- ptr = (void *) ((char *)p->scb + sizeof(struct scb_struct));
++ ptr = p->scb + 1;
+
+- cfg_cmd = (struct configure_cmd_struct *)ptr; /* configure-command */
++ cfg_cmd = ptr; /* configure-command */
+ writew(0, &cfg_cmd->cmd_status);
+ writew(CMD_CONFIGURE | CMD_LAST, &cfg_cmd->cmd_cmd);
+ writew(0xFFFF, &cfg_cmd->cmd_link);
+@@ -609,7 +617,7 @@ static int init586(struct net_device *dev)
+ writeb(0xf2, &cfg_cmd->time_high);
+ writeb(0x00, &cfg_cmd->promisc);;
+ if (dev->flags & IFF_ALLMULTI) {
+- int len = ((char *) p->iscp - (char *) ptr - 8) / 6;
++ int len = ((char __iomem *)p->iscp - (char __iomem *)ptr - 8) / 6;
+ if (num_addrs > len) {
+ printk(KERN_ERR "%s: switching to promisc. mode\n",
+ dev->name);
+@@ -620,7 +628,7 @@ static int init586(struct net_device *dev)
+ writeb(0x01, &cfg_cmd->promisc);
+ writeb(0x00, &cfg_cmd->carr_coll);
+ writew(make16(cfg_cmd), &p->scb->cbl_offset);
+- writew(0, &p->scb->cmd_ruc);
++ writeb(0, &p->scb->cmd_ruc);
+
+ writeb(CUC_START, &p->scb->cmd_cuc); /* cmd.-unit start */
+ ni_attn586();
+@@ -638,13 +646,13 @@ static int init586(struct net_device *dev)
+ * individual address setup
+ */
+
+- ias_cmd = (struct iasetup_cmd_struct *)ptr;
++ ias_cmd = ptr;
+
+ writew(0, &ias_cmd->cmd_status);
+ writew(CMD_IASETUP | CMD_LAST, &ias_cmd->cmd_cmd);
+ writew(0xffff, &ias_cmd->cmd_link);
+
+- memcpy_toio((char *)&ias_cmd->iaddr, (char *)dev->dev_addr, ETH_ALEN);
++ memcpy_toio(&ias_cmd->iaddr, (char *)dev->dev_addr, ETH_ALEN);
+
+ writew(make16(ias_cmd), &p->scb->cbl_offset);
+
+@@ -663,7 +671,7 @@ static int init586(struct net_device *dev)
+ * TDR, wire check .. e.g. no resistor e.t.c
+ */
+
+- tdr_cmd = (struct tdr_cmd_struct *)ptr;
++ tdr_cmd = ptr;
+
+ writew(0, &tdr_cmd->cmd_status);
+ writew(CMD_TDR | CMD_LAST, &tdr_cmd->cmd_cmd);
+@@ -707,14 +715,14 @@ static int init586(struct net_device *dev)
+ * Multicast setup
+ */
+ if (num_addrs && !(dev->flags & IFF_PROMISC)) {
+- mc_cmd = (struct mcsetup_cmd_struct *) ptr;
++ mc_cmd = ptr;
+ writew(0, &mc_cmd->cmd_status);
+ writew(CMD_MCSETUP | CMD_LAST, &mc_cmd->cmd_cmd);
+ writew(0xffff, &mc_cmd->cmd_link);
+ writew(num_addrs * 6, &mc_cmd->mc_cnt);
+
+ for (i = 0; i < num_addrs; i++, dmi = dmi->next)
+- memcpy_toio((char *) mc_cmd->mc_list[i],
++ memcpy_toio(mc_cmd->mc_list[i],
+ dmi->dmi_addr, 6);
+
+ writew(make16(mc_cmd), &p->scb->cbl_offset);
+@@ -733,43 +741,43 @@ static int init586(struct net_device *dev)
+ */
+ #if (NUM_XMIT_BUFFS == 1)
+ for (i = 0; i < 2; i++) {
+- p->nop_cmds[i] = (struct nop_cmd_struct *)ptr;
++ p->nop_cmds[i] = ptr;
+ writew(CMD_NOP, &p->nop_cmds[i]->cmd_cmd);
+ writew(0, &p->nop_cmds[i]->cmd_status);
+ writew(make16(p->nop_cmds[i]), &p->nop_cmds[i]->cmd_link);
+- ptr = (char *) ptr + sizeof(struct nop_cmd_struct);
++ ptr = ptr + sizeof(struct nop_cmd_struct);
+ }
+ #else
+ for (i = 0; i < NUM_XMIT_BUFFS; i++) {
+- p->nop_cmds[i] = (struct nop_cmd_struct *)ptr;
++ p->nop_cmds[i] = ptr;
+ writew(CMD_NOP, &p->nop_cmds[i]->cmd_cmd);
+ writew(0, &p->nop_cmds[i]->cmd_status);
+ writew(make16(p->nop_cmds[i]), &p->nop_cmds[i]->cmd_link);
+- ptr = (char *) ptr + sizeof(struct nop_cmd_struct);
++ ptr = ptr + sizeof(struct nop_cmd_struct);
+ }
+ #endif
+
+- ptr = alloc_rfa(dev, (void *)ptr); /* init receive-frame-area */
++ ptr = alloc_rfa(dev, ptr); /* init receive-frame-area */
+
+ /*
+ * alloc xmit-buffs / init xmit_cmds
+ */
+ for (i = 0; i < NUM_XMIT_BUFFS; i++) {
+ /* Transmit cmd/buff 0 */
+- p->xmit_cmds[i] = (struct transmit_cmd_struct *)ptr;
+- ptr = (char *) ptr + sizeof(struct transmit_cmd_struct);
+- p->xmit_cbuffs[i] = (char *)ptr; /* char-buffs */
+- ptr = (char *) ptr + XMIT_BUFF_SIZE;
+- p->xmit_buffs[i] = (struct tbd_struct *)ptr; /* TBD */
+- ptr = (char *) ptr + sizeof(struct tbd_struct);
+- if ((void *)ptr > (void *)p->iscp) {
++ p->xmit_cmds[i] = ptr;
++ ptr = ptr + sizeof(struct transmit_cmd_struct);
++ p->xmit_cbuffs[i] = ptr; /* char-buffs */
++ ptr = ptr + XMIT_BUFF_SIZE;
++ p->xmit_buffs[i] = ptr; /* TBD */
++ ptr = ptr + sizeof(struct tbd_struct);
++ if ((void __iomem *)ptr > (void __iomem *)p->iscp) {
+ printk(KERN_ERR "%s: not enough shared-mem for your configuration!\n",
+ dev->name);
+ return 1;
+ }
+- memset_io((char *)(p->xmit_cmds[i]), 0,
++ memset_io(p->xmit_cmds[i], 0,
+ sizeof(struct transmit_cmd_struct));
+- memset_io((char *)(p->xmit_buffs[i]), 0,
++ memset_io(p->xmit_buffs[i], 0,
+ sizeof(struct tbd_struct));
+ writew(make16(p->nop_cmds[(i+1)%NUM_XMIT_BUFFS]),
+ &p->xmit_cmds[i]->cmd_link);
+@@ -816,14 +824,14 @@ static int init586(struct net_device *dev)
+ * It sets up the Receive Frame Area (RFA).
+ */
+
+-static void *alloc_rfa(struct net_device *dev, void *ptr)
++static void __iomem *alloc_rfa(struct net_device *dev, void __iomem *ptr)
+ {
+- struct rfd_struct *rfd = (struct rfd_struct *)ptr;
+- struct rbd_struct *rbd;
++ struct rfd_struct __iomem *rfd = ptr;
++ struct rbd_struct __iomem *rbd;
+ int i;
+ struct priv *p = (struct priv *) dev->priv;
+
+- memset_io((char *) rfd, 0,
++ memset_io(rfd, 0,
+ sizeof(struct rfd_struct) * (p->num_recv_buffs + rfdadd));
+ p->rfd_first = rfd;
+
+@@ -835,20 +843,19 @@ static void *alloc_rfa(struct net_device *dev, void *ptr)
+ /* RU suspend */
+ writeb(RFD_SUSP, &rfd[p->num_recv_buffs-1+rfdadd].last);
+
+- ptr = (void *) (rfd + (p->num_recv_buffs + rfdadd));
++ ptr = rfd + (p->num_recv_buffs + rfdadd);
+
+- rbd = (struct rbd_struct *) ptr;
+- ptr = (void *) (rbd + p->num_recv_buffs);
++ rbd = ptr;
++ ptr = rbd + p->num_recv_buffs;
+
+ /* clr descriptors */
+- memset_io((char *)rbd, 0,
+- sizeof(struct rbd_struct) * (p->num_recv_buffs));
++ memset_io(rbd, 0, sizeof(struct rbd_struct) * (p->num_recv_buffs));
+
+ for (i = 0; i < p->num_recv_buffs; i++) {
+ writew(make16(rbd + (i+1) % p->num_recv_buffs), &rbd[i].next);
+ writew(RECV_BUFF_SIZE, &rbd[i].size);
+ writel(make24(ptr), &rbd[i].buffer);
+- ptr = (char *) ptr + RECV_BUFF_SIZE;
++ ptr = ptr + RECV_BUFF_SIZE;
+ }
+ p->rfd_top = p->rfd_first;
+ p->rfd_last = p->rfd_first + (p->num_recv_buffs - 1 + rfdadd);
+@@ -892,7 +899,7 @@ static irqreturn_t ni52_interrupt(int irq, void *dev_id)
+ if (readb(&p->scb->rus) & RU_SUSPEND) {
+ /* special case: RU_SUSPEND */
+ wait_for_scb_cmd(dev);
+- p->scb->cmd_ruc = RUC_RESUME;
++ writeb(RUC_RESUME, &p->scb->cmd_ruc);
+ ni_attn586();
+ wait_for_scb_cmd_ruc(dev);
+ } else {
+@@ -919,7 +926,7 @@ static irqreturn_t ni52_interrupt(int irq, void *dev_id)
+
+ /* Wait for ack. (ni52_xmt_int can be faster than ack!!) */
+ wait_for_scb_cmd(dev);
+- if (p->scb->cmd_cuc) { /* timed out? */
++ if (readb(&p->scb->cmd_cuc)) { /* timed out? */
+ printk(KERN_ERR "%s: Acknowledge timed out.\n",
+ dev->name);
+ ni_disint();
+@@ -942,14 +949,14 @@ static void ni52_rcv_int(struct net_device *dev)
+ int status, cnt = 0;
+ unsigned short totlen;
+ struct sk_buff *skb;
+- struct rbd_struct *rbd;
++ struct rbd_struct __iomem *rbd;
+ struct priv *p = (struct priv *)dev->priv;
+
+ if (debuglevel > 0)
+ printk("R");
+
+ for (; (status = readb(&p->rfd_top->stat_high)) & RFD_COMPL;) {
+- rbd = (struct rbd_struct *) make32(p->rfd_top->rbd_offset);
++ rbd = make32(readw(&p->rfd_top->rbd_offset));
+ if (status & RFD_OK) { /* frame received without error? */
+ totlen = readw(&rbd->status);
+ if (totlen & RBD_LAST) {
+@@ -960,7 +967,7 @@ static void ni52_rcv_int(struct net_device *dev)
+ if (skb != NULL) {
+ skb_reserve(skb, 2);
+ skb_put(skb, totlen);
+- skb_copy_to_linear_data(skb, (char *)p->base + (unsigned long) rbd->buffer, totlen);
++ memcpy_fromio(skb->data, p->base + readl(&rbd->buffer), totlen);
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
+ dev->last_rx = jiffies;
+@@ -979,7 +986,7 @@ static void ni52_rcv_int(struct net_device *dev)
+ break;
+ }
+ writew(0, &rbd->status);
+- rbd = (struct rbd_struct *) make32(readl(&rbd->next));
++ rbd = make32(readw(&rbd->next));
+ }
+ totlen += rstat & RBD_MASK;
+ writew(0, &rbd->status);
+@@ -997,7 +1004,7 @@ static void ni52_rcv_int(struct net_device *dev)
+ writew(0xffff, &p->rfd_top->rbd_offset);
+ writeb(0, &p->rfd_last->last); /* delete RFD_SUSP */
+ p->rfd_last = p->rfd_top;
+- p->rfd_top = (struct rfd_struct *) make32(p->rfd_top->next); /* step to next RFD */
++ p->rfd_top = make32(readw(&p->rfd_top->next)); /* step to next RFD */
+ writew(make16(p->rfd_top), &p->scb->rfa_offset);
+
+ if (debuglevel > 0)
+@@ -1042,11 +1049,12 @@ static void ni52_rnr_int(struct net_device *dev)
+ ni_attn586();
+ wait_for_scb_cmd_ruc(dev); /* wait for accept cmd. */
+
+- alloc_rfa(dev, (char *)p->rfd_first);
++ alloc_rfa(dev, p->rfd_first);
+ /* maybe add a check here, before restarting the RU */
+ startrecv586(dev); /* restart RU */
+
+- printk(KERN_ERR "%s: Receive-Unit restarted. Status: %04x\n", dev->name, p->scb->rus);
++ printk(KERN_ERR "%s: Receive-Unit restarted. Status: %04x\n",
++ dev->name, readb(&p->scb->rus));
+
+ }
+
+@@ -1178,12 +1186,11 @@ static int ni52_send_packet(struct sk_buff *skb, struct net_device *dev)
+
+ netif_stop_queue(dev);
+
+- skb_copy_from_linear_data(skb, (char *)p->xmit_cbuffs[p->xmit_count],
+- skb->len);
++ memcpy_toio(p->xmit_cbuffs[p->xmit_count], skb->data, skb->len);
+ len = skb->len;
+ if (len < ETH_ZLEN) {
+ len = ETH_ZLEN;
+- memset((char *)p->xmit_cbuffs[p->xmit_count]+skb->len, 0,
++ memset_io(p->xmit_cbuffs[p->xmit_count]+skb->len, 0,
+ len - skb->len);
+ }
+
+@@ -1191,14 +1198,14 @@ static int ni52_send_packet(struct sk_buff *skb, struct net_device *dev)
+ # ifdef NO_NOPCOMMANDS
+
+ #ifdef DEBUG
+- if (p->scb->cus & CU_ACTIVE) {
++ if (readb(&p->scb->cus) & CU_ACTIVE) {
+ printk(KERN_ERR "%s: Hmmm .. CU is still running and we wanna send a new packet.\n", dev->name);
+ printk(KERN_ERR "%s: stat: %04x %04x\n",
+ dev->name, readb(&p->scb->cus),
+ readw(&p->xmit_cmds[0]->cmd_status));
+ }
+ #endif
+- writew(TBD_LAST | len, &p->xmit_buffs[0]->size);;
++ writew(TBD_LAST | len, &p->xmit_buffs[0]->size);
+ for (i = 0; i < 16; i++) {
+ writew(0, &p->xmit_cmds[0]->cmd_status);
+ wait_for_scb_cmd(dev);
+@@ -1330,7 +1337,9 @@ int __init init_module(void)
+
+ void __exit cleanup_module(void)
+ {
++ struct priv *p = dev_ni52->priv;
+ unregister_netdev(dev_ni52);
++ iounmap(p->mapped);
+ release_region(dev_ni52->base_addr, NI52_TOTAL_SIZE);
+ free_netdev(dev_ni52);
+ }
+diff --git a/drivers/net/ni52.h b/drivers/net/ni52.h
+index 1f28a4d..0a03b28 100644
+--- a/drivers/net/ni52.h
++++ b/drivers/net/ni52.h
+@@ -39,8 +39,8 @@ struct scp_struct
+ u16 zero_dum0; /* has to be zero */
+ u8 sysbus; /* 0=16Bit,1=8Bit */
+ u8 zero_dum1; /* has to be zero for 586 */
+- u8 zero_dum2;
+- u8 zero_dum3;
++ u16 zero_dum2;
++ u16 zero_dum3;
+ u32 iscp; /* pointer to the iscp-block */
+ };
+
+diff --git a/drivers/net/niu.c b/drivers/net/niu.c
+index d11ba61..4009c4c 100644
+--- a/drivers/net/niu.c
++++ b/drivers/net/niu.c
+@@ -33,8 +33,8 @@
+
+ #define DRV_MODULE_NAME "niu"
+ #define PFX DRV_MODULE_NAME ": "
+-#define DRV_MODULE_VERSION "0.7"
+-#define DRV_MODULE_RELDATE "February 18, 2008"
++#define DRV_MODULE_VERSION "0.8"
++#define DRV_MODULE_RELDATE "April 24, 2008"
+
+ static char version[] __devinitdata =
+ DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+@@ -113,6 +113,8 @@ do { if ((np)->msg_enable & NETIF_MSG_##TYPE) \
+ #define niu_unlock_parent(np, flags) \
+ spin_unlock_irqrestore(&np->parent->lock, flags)
+
++static int serdes_init_10g_serdes(struct niu *np);
++
+ static int __niu_wait_bits_clear_mac(struct niu *np, unsigned long reg,
+ u64 bits, int limit, int delay)
+ {
+@@ -671,11 +673,16 @@ static int serdes_init_10g(struct niu *np)
+ }
+
+ if ((sig & mask) != val) {
++ if (np->flags & NIU_FLAGS_HOTPLUG_PHY) {
++ np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT;
++ return 0;
++ }
+ dev_err(np->device, PFX "Port %u signal bits [%08x] are not "
+ "[%08x]\n", np->port, (int) (sig & mask), (int) val);
+ return -ENODEV;
+ }
+-
++ if (np->flags & NIU_FLAGS_HOTPLUG_PHY)
++ np->flags |= NIU_FLAGS_HOTPLUG_PHY_PRESENT;
+ return 0;
+ }
+
+@@ -706,6 +713,251 @@ static int serdes_init_1g(struct niu *np)
+ return 0;
+ }
+
++static int serdes_init_1g_serdes(struct niu *np)
++{
++ struct niu_link_config *lp = &np->link_config;
++ unsigned long ctrl_reg, test_cfg_reg, pll_cfg, i;
++ u64 ctrl_val, test_cfg_val, sig, mask, val;
++ int err;
++ u64 reset_val, val_rd;
++
++ val = ENET_SERDES_PLL_HRATE0 | ENET_SERDES_PLL_HRATE1 |
++ ENET_SERDES_PLL_HRATE2 | ENET_SERDES_PLL_HRATE3 |
++ ENET_SERDES_PLL_FBDIV0;
++ switch (np->port) {
++ case 0:
++ reset_val = ENET_SERDES_RESET_0;
++ ctrl_reg = ENET_SERDES_0_CTRL_CFG;
++ test_cfg_reg = ENET_SERDES_0_TEST_CFG;
++ pll_cfg = ENET_SERDES_0_PLL_CFG;
++ break;
++ case 1:
++ reset_val = ENET_SERDES_RESET_1;
++ ctrl_reg = ENET_SERDES_1_CTRL_CFG;
++ test_cfg_reg = ENET_SERDES_1_TEST_CFG;
++ pll_cfg = ENET_SERDES_1_PLL_CFG;
++ break;
++
++ default:
++ return -EINVAL;
++ }
++ ctrl_val = (ENET_SERDES_CTRL_SDET_0 |
++ ENET_SERDES_CTRL_SDET_1 |
++ ENET_SERDES_CTRL_SDET_2 |
++ ENET_SERDES_CTRL_SDET_3 |
++ (0x5 << ENET_SERDES_CTRL_EMPH_0_SHIFT) |
++ (0x5 << ENET_SERDES_CTRL_EMPH_1_SHIFT) |
++ (0x5 << ENET_SERDES_CTRL_EMPH_2_SHIFT) |
++ (0x5 << ENET_SERDES_CTRL_EMPH_3_SHIFT) |
++ (0x1 << ENET_SERDES_CTRL_LADJ_0_SHIFT) |
++ (0x1 << ENET_SERDES_CTRL_LADJ_1_SHIFT) |
++ (0x1 << ENET_SERDES_CTRL_LADJ_2_SHIFT) |
++ (0x1 << ENET_SERDES_CTRL_LADJ_3_SHIFT));
++ test_cfg_val = 0;
++
++ if (lp->loopback_mode == LOOPBACK_PHY) {
++ test_cfg_val |= ((ENET_TEST_MD_PAD_LOOPBACK <<
++ ENET_SERDES_TEST_MD_0_SHIFT) |
++ (ENET_TEST_MD_PAD_LOOPBACK <<
++ ENET_SERDES_TEST_MD_1_SHIFT) |
++ (ENET_TEST_MD_PAD_LOOPBACK <<
++ ENET_SERDES_TEST_MD_2_SHIFT) |
++ (ENET_TEST_MD_PAD_LOOPBACK <<
++ ENET_SERDES_TEST_MD_3_SHIFT));
++ }
++
++ nw64(ENET_SERDES_RESET, reset_val);
++ mdelay(20);
++ val_rd = nr64(ENET_SERDES_RESET);
++ val_rd &= ~reset_val;
++ nw64(pll_cfg, val);
++ nw64(ctrl_reg, ctrl_val);
++ nw64(test_cfg_reg, test_cfg_val);
++ nw64(ENET_SERDES_RESET, val_rd);
++ mdelay(2000);
++
++ /* Initialize all 4 lanes of the SERDES. */
++ for (i = 0; i < 4; i++) {
++ u32 rxtx_ctrl, glue0;
++
++ err = esr_read_rxtx_ctrl(np, i, &rxtx_ctrl);
++ if (err)
++ return err;
++ err = esr_read_glue0(np, i, &glue0);
++ if (err)
++ return err;
++
++ rxtx_ctrl &= ~(ESR_RXTX_CTRL_VMUXLO);
++ rxtx_ctrl |= (ESR_RXTX_CTRL_ENSTRETCH |
++ (2 << ESR_RXTX_CTRL_VMUXLO_SHIFT));
++
++ glue0 &= ~(ESR_GLUE_CTRL0_SRATE |
++ ESR_GLUE_CTRL0_THCNT |
++ ESR_GLUE_CTRL0_BLTIME);
++ glue0 |= (ESR_GLUE_CTRL0_RXLOSENAB |
++ (0xf << ESR_GLUE_CTRL0_SRATE_SHIFT) |
++ (0xff << ESR_GLUE_CTRL0_THCNT_SHIFT) |
++ (BLTIME_300_CYCLES <<
++ ESR_GLUE_CTRL0_BLTIME_SHIFT));
++
++ err = esr_write_rxtx_ctrl(np, i, rxtx_ctrl);
++ if (err)
++ return err;
++ err = esr_write_glue0(np, i, glue0);
++ if (err)
++ return err;
++ }
++
++
++ sig = nr64(ESR_INT_SIGNALS);
++ switch (np->port) {
++ case 0:
++ val = (ESR_INT_SRDY0_P0 | ESR_INT_DET0_P0);
++ mask = val;
++ break;
++
++ case 1:
++ val = (ESR_INT_SRDY0_P1 | ESR_INT_DET0_P1);
++ mask = val;
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ if ((sig & mask) != val) {
++ dev_err(np->device, PFX "Port %u signal bits [%08x] are not "
++ "[%08x]\n", np->port, (int) (sig & mask), (int) val);
++ return -ENODEV;
++ }
++
++ return 0;
++}
++
++static int link_status_1g_serdes(struct niu *np, int *link_up_p)
++{
++ struct niu_link_config *lp = &np->link_config;
++ int link_up;
++ u64 val;
++ u16 current_speed;
++ unsigned long flags;
++ u8 current_duplex;
++
++ link_up = 0;
++ current_speed = SPEED_INVALID;
++ current_duplex = DUPLEX_INVALID;
++
++ spin_lock_irqsave(&np->lock, flags);
++
++ val = nr64_pcs(PCS_MII_STAT);
++
++ if (val & PCS_MII_STAT_LINK_STATUS) {
++ link_up = 1;
++ current_speed = SPEED_1000;
++ current_duplex = DUPLEX_FULL;
++ }
++
++ lp->active_speed = current_speed;
++ lp->active_duplex = current_duplex;
++ spin_unlock_irqrestore(&np->lock, flags);
++
++ *link_up_p = link_up;
++ return 0;
++}
++
++
++static int link_status_10g_serdes(struct niu *np, int *link_up_p)
++{
++ unsigned long flags;
++ struct niu_link_config *lp = &np->link_config;
++ int link_up = 0;
++ int link_ok = 1;
++ u64 val, val2;
++ u16 current_speed;
++ u8 current_duplex;
++
++ if (!(np->flags & NIU_FLAGS_10G))
++ return link_status_1g_serdes(np, link_up_p);
++
++ current_speed = SPEED_INVALID;
++ current_duplex = DUPLEX_INVALID;
++ spin_lock_irqsave(&np->lock, flags);
++
++ val = nr64_xpcs(XPCS_STATUS(0));
++ val2 = nr64_mac(XMAC_INTER2);
++ if (val2 & 0x01000000)
++ link_ok = 0;
++
++ if ((val & 0x1000ULL) && link_ok) {
++ link_up = 1;
++ current_speed = SPEED_10000;
++ current_duplex = DUPLEX_FULL;
++ }
++ lp->active_speed = current_speed;
++ lp->active_duplex = current_duplex;
++ spin_unlock_irqrestore(&np->lock, flags);
++ *link_up_p = link_up;
++ return 0;
++}
++
++
++static int link_status_1g_rgmii(struct niu *np, int *link_up_p)
++{
++ struct niu_link_config *lp = &np->link_config;
++ u16 current_speed, bmsr;
++ unsigned long flags;
++ u8 current_duplex;
++ int err, link_up;
++
++ link_up = 0;
++ current_speed = SPEED_INVALID;
++ current_duplex = DUPLEX_INVALID;
++
++ spin_lock_irqsave(&np->lock, flags);
++
++ err = -EINVAL;
++
++ err = mii_read(np, np->phy_addr, MII_BMSR);
++ if (err < 0)
++ goto out;
++
++ bmsr = err;
++ if (bmsr & BMSR_LSTATUS) {
++ u16 adv, lpa, common, estat;
++
++ err = mii_read(np, np->phy_addr, MII_ADVERTISE);
++ if (err < 0)
++ goto out;
++ adv = err;
++
++ err = mii_read(np, np->phy_addr, MII_LPA);
++ if (err < 0)
++ goto out;
++ lpa = err;
++
++ common = adv & lpa;
++
++ err = mii_read(np, np->phy_addr, MII_ESTATUS);
++ if (err < 0)
++ goto out;
++ estat = err;
++ link_up = 1;
++ current_speed = SPEED_1000;
++ current_duplex = DUPLEX_FULL;
++
++ }
++ lp->active_speed = current_speed;
++ lp->active_duplex = current_duplex;
++ err = 0;
++
++out:
++ spin_unlock_irqrestore(&np->lock, flags);
++
++ *link_up_p = link_up;
++ return err;
++}
++
++
+ static int bcm8704_reset(struct niu *np)
+ {
+ int err, limit;
+@@ -751,6 +1003,28 @@ static int bcm8704_user_dev3_readback(struct niu *np, int reg)
+ return 0;
+ }
+
++static int bcm8706_init_user_dev3(struct niu *np)
++{
++ int err;
++
++
++ err = mdio_read(np, np->phy_addr, BCM8704_USER_DEV3_ADDR,
++ BCM8704_USER_OPT_DIGITAL_CTRL);
++ if (err < 0)
++ return err;
++ err &= ~USER_ODIG_CTRL_GPIOS;
++ err |= (0x3 << USER_ODIG_CTRL_GPIOS_SHIFT);
++ err |= USER_ODIG_CTRL_RESV2;
++ err = mdio_write(np, np->phy_addr, BCM8704_USER_DEV3_ADDR,
++ BCM8704_USER_OPT_DIGITAL_CTRL, err);
++ if (err)
++ return err;
++
++ mdelay(1000);
++
++ return 0;
++}
++
+ static int bcm8704_init_user_dev3(struct niu *np)
+ {
+ int err;
+@@ -880,33 +1154,11 @@ static int xcvr_init_10g_mrvl88x2011(struct niu *np)
+ MRVL88X2011_10G_PMD_TX_DIS, MRVL88X2011_ENA_PMDTX);
+ }
+
+-static int xcvr_init_10g_bcm8704(struct niu *np)
++
++static int xcvr_diag_bcm870x(struct niu *np)
+ {
+- struct niu_link_config *lp = &np->link_config;
+ u16 analog_stat0, tx_alarm_status;
+- int err;
+-
+- err = bcm8704_reset(np);
+- if (err)
+- return err;
+-
+- err = bcm8704_init_user_dev3(np);
+- if (err)
+- return err;
+-
+- err = mdio_read(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
+- MII_BMCR);
+- if (err < 0)
+- return err;
+- err &= ~BMCR_LOOPBACK;
+-
+- if (lp->loopback_mode == LOOPBACK_MAC)
+- err |= BMCR_LOOPBACK;
+-
+- err = mdio_write(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
+- MII_BMCR, err);
+- if (err)
+- return err;
++ int err = 0;
+
+ #if 1
+ err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR,
+@@ -964,6 +1216,89 @@ static int xcvr_init_10g_bcm8704(struct niu *np)
+ return 0;
+ }
+
++static int xcvr_10g_set_lb_bcm870x(struct niu *np)
++{
++ struct niu_link_config *lp = &np->link_config;
++ int err;
++
++ err = mdio_read(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
++ MII_BMCR);
++ if (err < 0)
++ return err;
++
++ err &= ~BMCR_LOOPBACK;
++
++ if (lp->loopback_mode == LOOPBACK_MAC)
++ err |= BMCR_LOOPBACK;
++
++ err = mdio_write(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
++ MII_BMCR, err);
++ if (err)
++ return err;
++
++ return 0;
++}
++
++static int xcvr_init_10g_bcm8706(struct niu *np)
++{
++ int err = 0;
++ u64 val;
++
++ if ((np->flags & NIU_FLAGS_HOTPLUG_PHY) &&
++ (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT) == 0)
++ return err;
++
++ val = nr64_mac(XMAC_CONFIG);
++ val &= ~XMAC_CONFIG_LED_POLARITY;
++ val |= XMAC_CONFIG_FORCE_LED_ON;
++ nw64_mac(XMAC_CONFIG, val);
++
++ val = nr64(MIF_CONFIG);
++ val |= MIF_CONFIG_INDIRECT_MODE;
++ nw64(MIF_CONFIG, val);
++
++ err = bcm8704_reset(np);
++ if (err)
++ return err;
++
++ err = xcvr_10g_set_lb_bcm870x(np);
++ if (err)
++ return err;
++
++ err = bcm8706_init_user_dev3(np);
++ if (err)
++ return err;
++
++ err = xcvr_diag_bcm870x(np);
++ if (err)
++ return err;
++
++ return 0;
++}
++
++static int xcvr_init_10g_bcm8704(struct niu *np)
++{
++ int err;
++
++ err = bcm8704_reset(np);
++ if (err)
++ return err;
++
++ err = bcm8704_init_user_dev3(np);
++ if (err)
++ return err;
++
++ err = xcvr_10g_set_lb_bcm870x(np);
++ if (err)
++ return err;
++
++ err = xcvr_diag_bcm870x(np);
++ if (err)
++ return err;
++
++ return 0;
++}
++
+ static int xcvr_init_10g(struct niu *np)
+ {
+ int phy_id, err;
+@@ -1022,6 +1357,69 @@ static int mii_reset(struct niu *np)
+ return 0;
+ }
+
++
++
++static int xcvr_init_1g_rgmii(struct niu *np)
++{
++ int err;
++ u64 val;
++ u16 bmcr, bmsr, estat;
++
++ val = nr64(MIF_CONFIG);
++ val &= ~MIF_CONFIG_INDIRECT_MODE;
++ nw64(MIF_CONFIG, val);
++
++ err = mii_reset(np);
++ if (err)
++ return err;
++
++ err = mii_read(np, np->phy_addr, MII_BMSR);
++ if (err < 0)
++ return err;
++ bmsr = err;
++
++ estat = 0;
++ if (bmsr & BMSR_ESTATEN) {
++ err = mii_read(np, np->phy_addr, MII_ESTATUS);
++ if (err < 0)
++ return err;
++ estat = err;
++ }
++
++ bmcr = 0;
++ err = mii_write(np, np->phy_addr, MII_BMCR, bmcr);
++ if (err)
++ return err;
++
++ if (bmsr & BMSR_ESTATEN) {
++ u16 ctrl1000 = 0;
++
++ if (estat & ESTATUS_1000_TFULL)
++ ctrl1000 |= ADVERTISE_1000FULL;
++ err = mii_write(np, np->phy_addr, MII_CTRL1000, ctrl1000);
++ if (err)
++ return err;
++ }
++
++ bmcr = (BMCR_SPEED1000 | BMCR_FULLDPLX);
++
++ err = mii_write(np, np->phy_addr, MII_BMCR, bmcr);
++ if (err)
++ return err;
++
++ err = mii_read(np, np->phy_addr, MII_BMCR);
++ if (err < 0)
++ return err;
++ bmcr = mii_read(np, np->phy_addr, MII_BMCR);
++
++ err = mii_read(np, np->phy_addr, MII_BMSR);
++ if (err < 0)
++ return err;
++
++ return 0;
++}
++
++
+ static int mii_init_common(struct niu *np)
+ {
+ struct niu_link_config *lp = &np->link_config;
+@@ -1238,6 +1636,59 @@ out:
+ return err;
+ }
+
++static int link_status_10g_bcm8706(struct niu *np, int *link_up_p)
++{
++ int err, link_up;
++ link_up = 0;
++
++ err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR,
++ BCM8704_PMD_RCV_SIGDET);
++ if (err < 0)
++ goto out;
++ if (!(err & PMD_RCV_SIGDET_GLOBAL)) {
++ err = 0;
++ goto out;
++ }
++
++ err = mdio_read(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
++ BCM8704_PCS_10G_R_STATUS);
++ if (err < 0)
++ goto out;
++
++ if (!(err & PCS_10G_R_STATUS_BLK_LOCK)) {
++ err = 0;
++ goto out;
++ }
++
++ err = mdio_read(np, np->phy_addr, BCM8704_PHYXS_DEV_ADDR,
++ BCM8704_PHYXS_XGXS_LANE_STAT);
++ if (err < 0)
++ goto out;
++ if (err != (PHYXS_XGXS_LANE_STAT_ALINGED |
++ PHYXS_XGXS_LANE_STAT_MAGIC |
++ PHYXS_XGXS_LANE_STAT_PATTEST |
++ PHYXS_XGXS_LANE_STAT_LANE3 |
++ PHYXS_XGXS_LANE_STAT_LANE2 |
++ PHYXS_XGXS_LANE_STAT_LANE1 |
++ PHYXS_XGXS_LANE_STAT_LANE0)) {
++ err = 0;
++ np->link_config.active_speed = SPEED_INVALID;
++ np->link_config.active_duplex = DUPLEX_INVALID;
++ goto out;
++ }
++
++ link_up = 1;
++ np->link_config.active_speed = SPEED_10000;
++ np->link_config.active_duplex = DUPLEX_FULL;
++ err = 0;
++
++out:
++ *link_up_p = link_up;
++ if (np->flags & NIU_FLAGS_HOTPLUG_PHY)
++ err = 0;
++ return err;
++}
++
+ static int link_status_10g_bcom(struct niu *np, int *link_up_p)
+ {
+ int err, link_up;
+@@ -1317,6 +1768,82 @@ static int link_status_10g(struct niu *np, int *link_up_p)
+ return err;
+ }
+
++static int niu_10g_phy_present(struct niu *np)
++{
++ u64 sig, mask, val;
++
++ sig = nr64(ESR_INT_SIGNALS);
++ switch (np->port) {
++ case 0:
++ mask = ESR_INT_SIGNALS_P0_BITS;
++ val = (ESR_INT_SRDY0_P0 |
++ ESR_INT_DET0_P0 |
++ ESR_INT_XSRDY_P0 |
++ ESR_INT_XDP_P0_CH3 |
++ ESR_INT_XDP_P0_CH2 |
++ ESR_INT_XDP_P0_CH1 |
++ ESR_INT_XDP_P0_CH0);
++ break;
++
++ case 1:
++ mask = ESR_INT_SIGNALS_P1_BITS;
++ val = (ESR_INT_SRDY0_P1 |
++ ESR_INT_DET0_P1 |
++ ESR_INT_XSRDY_P1 |
++ ESR_INT_XDP_P1_CH3 |
++ ESR_INT_XDP_P1_CH2 |
++ ESR_INT_XDP_P1_CH1 |
++ ESR_INT_XDP_P1_CH0);
++ break;
++
++ default:
++ return 0;
++ }
++
++ if ((sig & mask) != val)
++ return 0;
++ return 1;
++}
++
++static int link_status_10g_hotplug(struct niu *np, int *link_up_p)
++{
++ unsigned long flags;
++ int err = 0;
++ int phy_present;
++ int phy_present_prev;
++
++ spin_lock_irqsave(&np->lock, flags);
++
++ if (np->link_config.loopback_mode == LOOPBACK_DISABLED) {
++ phy_present_prev = (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT) ?
++ 1 : 0;
++ phy_present = niu_10g_phy_present(np);
++ if (phy_present != phy_present_prev) {
++ /* state change */
++ if (phy_present) {
++ np->flags |= NIU_FLAGS_HOTPLUG_PHY_PRESENT;
++ if (np->phy_ops->xcvr_init)
++ err = np->phy_ops->xcvr_init(np);
++ if (err) {
++ /* debounce */
++ np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT;
++ }
++ } else {
++ np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT;
++ *link_up_p = 0;
++ niuwarn(LINK, "%s: Hotplug PHY Removed\n",
++ np->dev->name);
++ }
++ }
++ if (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT)
++ err = link_status_10g_bcm8706(np, link_up_p);
++ }
++
++ spin_unlock_irqrestore(&np->lock, flags);
++
++ return err;
++}
++
+ static int link_status_1g(struct niu *np, int *link_up_p)
+ {
+ struct niu_link_config *lp = &np->link_config;
+@@ -1429,6 +1956,16 @@ static void niu_timer(unsigned long __opaque)
+ add_timer(&np->timer);
+ }
+
++static const struct niu_phy_ops phy_ops_10g_serdes = {
++ .serdes_init = serdes_init_10g_serdes,
++ .link_status = link_status_10g_serdes,
++};
++
++static const struct niu_phy_ops phy_ops_1g_rgmii = {
++ .xcvr_init = xcvr_init_1g_rgmii,
++ .link_status = link_status_1g_rgmii,
++};
++
+ static const struct niu_phy_ops phy_ops_10g_fiber_niu = {
+ .serdes_init = serdes_init_niu,
+ .xcvr_init = xcvr_init_10g,
+@@ -1441,6 +1978,12 @@ static const struct niu_phy_ops phy_ops_10g_fiber = {
+ .link_status = link_status_10g,
+ };
+
++static const struct niu_phy_ops phy_ops_10g_fiber_hotplug = {
++ .serdes_init = serdes_init_10g,
++ .xcvr_init = xcvr_init_10g_bcm8706,
++ .link_status = link_status_10g_hotplug,
++};
++
+ static const struct niu_phy_ops phy_ops_10g_copper = {
+ .serdes_init = serdes_init_10g,
+ .link_status = link_status_10g, /* XXX */
+@@ -1472,6 +2015,11 @@ static const struct niu_phy_template phy_template_10g_fiber = {
+ .phy_addr_base = 8,
+ };
+
++static const struct niu_phy_template phy_template_10g_fiber_hotplug = {
++ .ops = &phy_ops_10g_fiber_hotplug,
++ .phy_addr_base = 8,
++};
++
+ static const struct niu_phy_template phy_template_10g_copper = {
+ .ops = &phy_ops_10g_copper,
+ .phy_addr_base = 10,
+@@ -1487,6 +2035,152 @@ static const struct niu_phy_template phy_template_1g_copper = {
+ .phy_addr_base = 0,
+ };
+
++static const struct niu_phy_template phy_template_1g_rgmii = {
++ .ops = &phy_ops_1g_rgmii,
++ .phy_addr_base = 0,
++};
++
++static const struct niu_phy_template phy_template_10g_serdes = {
++ .ops = &phy_ops_10g_serdes,
++ .phy_addr_base = 0,
++};
++
++static int niu_atca_port_num[4] = {
++ 0, 0, 11, 10
++};
++
++static int serdes_init_10g_serdes(struct niu *np)
++{
++ struct niu_link_config *lp = &np->link_config;
++ unsigned long ctrl_reg, test_cfg_reg, pll_cfg, i;
++ u64 ctrl_val, test_cfg_val, sig, mask, val;
++ int err;
++ u64 reset_val;
++
++ switch (np->port) {
++ case 0:
++ reset_val = ENET_SERDES_RESET_0;
++ ctrl_reg = ENET_SERDES_0_CTRL_CFG;
++ test_cfg_reg = ENET_SERDES_0_TEST_CFG;
++ pll_cfg = ENET_SERDES_0_PLL_CFG;
++ break;
++ case 1:
++ reset_val = ENET_SERDES_RESET_1;
++ ctrl_reg = ENET_SERDES_1_CTRL_CFG;
++ test_cfg_reg = ENET_SERDES_1_TEST_CFG;
++ pll_cfg = ENET_SERDES_1_PLL_CFG;
++ break;
++
++ default:
++ return -EINVAL;
++ }
++ ctrl_val = (ENET_SERDES_CTRL_SDET_0 |
++ ENET_SERDES_CTRL_SDET_1 |
++ ENET_SERDES_CTRL_SDET_2 |
++ ENET_SERDES_CTRL_SDET_3 |
++ (0x5 << ENET_SERDES_CTRL_EMPH_0_SHIFT) |
++ (0x5 << ENET_SERDES_CTRL_EMPH_1_SHIFT) |
++ (0x5 << ENET_SERDES_CTRL_EMPH_2_SHIFT) |
++ (0x5 << ENET_SERDES_CTRL_EMPH_3_SHIFT) |
++ (0x1 << ENET_SERDES_CTRL_LADJ_0_SHIFT) |
++ (0x1 << ENET_SERDES_CTRL_LADJ_1_SHIFT) |
++ (0x1 << ENET_SERDES_CTRL_LADJ_2_SHIFT) |
++ (0x1 << ENET_SERDES_CTRL_LADJ_3_SHIFT));
++ test_cfg_val = 0;
++
++ if (lp->loopback_mode == LOOPBACK_PHY) {
++ test_cfg_val |= ((ENET_TEST_MD_PAD_LOOPBACK <<
++ ENET_SERDES_TEST_MD_0_SHIFT) |
++ (ENET_TEST_MD_PAD_LOOPBACK <<
++ ENET_SERDES_TEST_MD_1_SHIFT) |
++ (ENET_TEST_MD_PAD_LOOPBACK <<
++ ENET_SERDES_TEST_MD_2_SHIFT) |
++ (ENET_TEST_MD_PAD_LOOPBACK <<
++ ENET_SERDES_TEST_MD_3_SHIFT));
++ }
++
++ esr_reset(np);
++ nw64(pll_cfg, ENET_SERDES_PLL_FBDIV2);
++ nw64(ctrl_reg, ctrl_val);
++ nw64(test_cfg_reg, test_cfg_val);
++
++ /* Initialize all 4 lanes of the SERDES. */
++ for (i = 0; i < 4; i++) {
++ u32 rxtx_ctrl, glue0;
++
++ err = esr_read_rxtx_ctrl(np, i, &rxtx_ctrl);
++ if (err)
++ return err;
++ err = esr_read_glue0(np, i, &glue0);
++ if (err)
++ return err;
++
++ rxtx_ctrl &= ~(ESR_RXTX_CTRL_VMUXLO);
++ rxtx_ctrl |= (ESR_RXTX_CTRL_ENSTRETCH |
++ (2 << ESR_RXTX_CTRL_VMUXLO_SHIFT));
++
++ glue0 &= ~(ESR_GLUE_CTRL0_SRATE |
++ ESR_GLUE_CTRL0_THCNT |
++ ESR_GLUE_CTRL0_BLTIME);
++ glue0 |= (ESR_GLUE_CTRL0_RXLOSENAB |
++ (0xf << ESR_GLUE_CTRL0_SRATE_SHIFT) |
++ (0xff << ESR_GLUE_CTRL0_THCNT_SHIFT) |
++ (BLTIME_300_CYCLES <<
++ ESR_GLUE_CTRL0_BLTIME_SHIFT));
++
++ err = esr_write_rxtx_ctrl(np, i, rxtx_ctrl);
++ if (err)
++ return err;
++ err = esr_write_glue0(np, i, glue0);
++ if (err)
++ return err;
++ }
++
++
++ sig = nr64(ESR_INT_SIGNALS);
++ switch (np->port) {
++ case 0:
++ mask = ESR_INT_SIGNALS_P0_BITS;
++ val = (ESR_INT_SRDY0_P0 |
++ ESR_INT_DET0_P0 |
++ ESR_INT_XSRDY_P0 |
++ ESR_INT_XDP_P0_CH3 |
++ ESR_INT_XDP_P0_CH2 |
++ ESR_INT_XDP_P0_CH1 |
++ ESR_INT_XDP_P0_CH0);
++ break;
++
++ case 1:
++ mask = ESR_INT_SIGNALS_P1_BITS;
++ val = (ESR_INT_SRDY0_P1 |
++ ESR_INT_DET0_P1 |
++ ESR_INT_XSRDY_P1 |
++ ESR_INT_XDP_P1_CH3 |
++ ESR_INT_XDP_P1_CH2 |
++ ESR_INT_XDP_P1_CH1 |
++ ESR_INT_XDP_P1_CH0);
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ if ((sig & mask) != val) {
++ int err;
++ err = serdes_init_1g_serdes(np);
++ if (!err) {
++ np->flags &= ~NIU_FLAGS_10G;
++ np->mac_xcvr = MAC_XCVR_PCS;
++ } else {
++ dev_err(np->device, PFX "Port %u 10G/1G SERDES Link Failed \n",
++ np->port);
++ return -ENODEV;
++ }
++ }
++
++ return 0;
++}
++
+ static int niu_determine_phy_disposition(struct niu *np)
+ {
+ struct niu_parent *parent = np->parent;
+@@ -1498,7 +2192,10 @@ static int niu_determine_phy_disposition(struct niu *np)
+ tp = &phy_template_niu;
+ phy_addr_off += np->port;
+ } else {
+- switch (np->flags & (NIU_FLAGS_10G | NIU_FLAGS_FIBER)) {
++ switch (np->flags &
++ (NIU_FLAGS_10G |
++ NIU_FLAGS_FIBER |
++ NIU_FLAGS_XCVR_SERDES)) {
+ case 0:
+ /* 1G copper */
+ tp = &phy_template_1g_copper;
+@@ -1527,6 +2224,32 @@ static int niu_determine_phy_disposition(struct niu *np)
+ plat_type == PLAT_TYPE_VF_P1)
+ phy_addr_off = 8;
+ phy_addr_off += np->port;
++ if (np->flags & NIU_FLAGS_HOTPLUG_PHY) {
++ tp = &phy_template_10g_fiber_hotplug;
++ if (np->port == 0)
++ phy_addr_off = 8;
++ if (np->port == 1)
++ phy_addr_off = 12;
++ }
++ break;
++
++ case NIU_FLAGS_10G | NIU_FLAGS_XCVR_SERDES:
++ case NIU_FLAGS_XCVR_SERDES | NIU_FLAGS_FIBER:
++ case NIU_FLAGS_XCVR_SERDES:
++ switch(np->port) {
++ case 0:
++ case 1:
++ tp = &phy_template_10g_serdes;
++ break;
++ case 2:
++ case 3:
++ tp = &phy_template_1g_rgmii;
++ break;
++ default:
++ return -EINVAL;
++ break;
++ }
++ phy_addr_off = niu_atca_port_num[np->port];
+ break;
+
+ default:
+@@ -4139,6 +4862,12 @@ static void niu_init_xif_xmac(struct niu *np)
+ struct niu_link_config *lp = &np->link_config;
+ u64 val;
+
++ if (np->flags & NIU_FLAGS_XCVR_SERDES) {
++ val = nr64(MIF_CONFIG);
++ val |= MIF_CONFIG_ATCA_GE;
++ nw64(MIF_CONFIG, val);
++ }
++
+ val = nr64_mac(XMAC_CONFIG);
+ val &= ~XMAC_CONFIG_SEL_POR_CLK_SRC;
+
+@@ -4155,7 +4884,8 @@ static void niu_init_xif_xmac(struct niu *np)
+ val &= ~XMAC_CONFIG_LFS_DISABLE;
+ } else {
+ val |= XMAC_CONFIG_LFS_DISABLE;
+- if (!(np->flags & NIU_FLAGS_FIBER))
++ if (!(np->flags & NIU_FLAGS_FIBER) &&
++ !(np->flags & NIU_FLAGS_XCVR_SERDES))
+ val |= XMAC_CONFIG_1G_PCS_BYPASS;
+ else
+ val &= ~XMAC_CONFIG_1G_PCS_BYPASS;
+@@ -4224,16 +4954,26 @@ static void niu_init_xif(struct niu *np)
+
+ static void niu_pcs_mii_reset(struct niu *np)
+ {
++ int limit = 1000;
+ u64 val = nr64_pcs(PCS_MII_CTL);
+ val |= PCS_MII_CTL_RST;
+ nw64_pcs(PCS_MII_CTL, val);
++ while ((--limit >= 0) && (val & PCS_MII_CTL_RST)) {
++ udelay(100);
++ val = nr64_pcs(PCS_MII_CTL);
++ }
+ }
+
+ static void niu_xpcs_reset(struct niu *np)
+ {
++ int limit = 1000;
+ u64 val = nr64_xpcs(XPCS_CONTROL1);
+ val |= XPCS_CONTROL1_RESET;
+ nw64_xpcs(XPCS_CONTROL1, val);
++ while ((--limit >= 0) && (val & XPCS_CONTROL1_RESET)) {
++ udelay(100);
++ val = nr64_xpcs(XPCS_CONTROL1);
++ }
+ }
+
+ static int niu_init_pcs(struct niu *np)
+@@ -4241,7 +4981,9 @@ static int niu_init_pcs(struct niu *np)
+ struct niu_link_config *lp = &np->link_config;
+ u64 val;
+
+- switch (np->flags & (NIU_FLAGS_10G | NIU_FLAGS_FIBER)) {
++ switch (np->flags & (NIU_FLAGS_10G |
++ NIU_FLAGS_FIBER |
++ NIU_FLAGS_XCVR_SERDES)) {
+ case NIU_FLAGS_FIBER:
+ /* 1G fiber */
+ nw64_pcs(PCS_CONF, PCS_CONF_MASK | PCS_CONF_ENABLE);
+@@ -4251,6 +4993,8 @@ static int niu_init_pcs(struct niu *np)
+
+ case NIU_FLAGS_10G:
+ case NIU_FLAGS_10G | NIU_FLAGS_FIBER:
++ case NIU_FLAGS_10G | NIU_FLAGS_XCVR_SERDES:
++ /* 10G SERDES */
+ if (!(np->flags & NIU_FLAGS_XMAC))
+ return -EINVAL;
+
+@@ -4273,8 +5017,18 @@ static int niu_init_pcs(struct niu *np)
+ (void) nr64_xpcs(XPCS_SYMERR_CNT23);
+ break;
+
++
++ case NIU_FLAGS_XCVR_SERDES:
++ /* 1G SERDES */
++ niu_pcs_mii_reset(np);
++ nw64_pcs(PCS_CONF, PCS_CONF_MASK | PCS_CONF_ENABLE);
++ nw64_pcs(PCS_DPATH_MODE, 0);
++ break;
++
+ case 0:
+ /* 1G copper */
++ case NIU_FLAGS_XCVR_SERDES | NIU_FLAGS_FIBER:
++ /* 1G RGMII FIBER */
+ nw64_pcs(PCS_DPATH_MODE, PCS_DPATH_MODE_MII);
+ niu_pcs_mii_reset(np);
+ break;
+@@ -6254,6 +7008,37 @@ static int __devinit niu_phy_type_prop_decode(struct niu *np,
+ return 0;
+ }
+
++/* niu board models have a trailing dash version incremented
++ * with HW rev change. Need to ingnore the dash version while
++ * checking for match
++ *
++ * for example, for the 10G card the current vpd.board_model
++ * is 501-5283-04, of which -04 is the dash version and have
++ * to be ignored
++ */
++static int niu_board_model_match(struct niu *np, const char *model)
++{
++ return !strncmp(np->vpd.board_model, model, strlen(model));
++}
++
++static int niu_pci_vpd_get_nports(struct niu *np)
++{
++ int ports = 0;
++
++ if ((niu_board_model_match(np, NIU_QGC_LP_BM_STR)) ||
++ (niu_board_model_match(np, NIU_QGC_PEM_BM_STR)) ||
++ (niu_board_model_match(np, NIU_ALONSO_BM_STR))) {
++ ports = 4;
++ } else if ((niu_board_model_match(np, NIU_2XGF_LP_BM_STR)) ||
++ (niu_board_model_match(np, NIU_2XGF_PEM_BM_STR)) ||
++ (niu_board_model_match(np, NIU_FOXXY_BM_STR)) ||
++ (niu_board_model_match(np, NIU_2XGF_MRVL_BM_STR))) {
++ ports = 2;
++ }
++
++ return ports;
++}
++
+ static void __devinit niu_pci_vpd_validate(struct niu *np)
+ {
+ struct net_device *dev = np->dev;
+@@ -6268,7 +7053,22 @@ static void __devinit niu_pci_vpd_validate(struct niu *np)
+ return;
+ }
+
+- if (niu_phy_type_prop_decode(np, np->vpd.phy_type)) {
++ if (!strcmp(np->vpd.model, "SUNW,CP3220") ||
++ !strcmp(np->vpd.model, "SUNW,CP3260")) {
++ np->flags |= NIU_FLAGS_10G;
++ np->flags &= ~NIU_FLAGS_FIBER;
++ np->flags |= NIU_FLAGS_XCVR_SERDES;
++ np->mac_xcvr = MAC_XCVR_PCS;
++ if (np->port > 1) {
++ np->flags |= NIU_FLAGS_FIBER;
++ np->flags &= ~NIU_FLAGS_10G;
++ }
++ if (np->flags & NIU_FLAGS_10G)
++ np->mac_xcvr = MAC_XCVR_XPCS;
++ } else if (niu_board_model_match(np, NIU_FOXXY_BM_STR)) {
++ np->flags |= (NIU_FLAGS_10G | NIU_FLAGS_FIBER |
++ NIU_FLAGS_HOTPLUG_PHY);
++ } else if (niu_phy_type_prop_decode(np, np->vpd.phy_type)) {
+ dev_err(np->device, PFX "Illegal phy string [%s].\n",
+ np->vpd.phy_type);
+ dev_err(np->device, PFX "Falling back to SPROM.\n");
+@@ -6456,11 +7256,17 @@ static int __devinit niu_get_and_validate_port(struct niu *np)
+ if (parent->plat_type == PLAT_TYPE_NIU) {
+ parent->num_ports = 2;
+ } else {
+- parent->num_ports = nr64(ESPC_NUM_PORTS_MACS) &
+- ESPC_NUM_PORTS_MACS_VAL;
+-
+- if (!parent->num_ports)
+- parent->num_ports = 4;
++ parent->num_ports = niu_pci_vpd_get_nports(np);
++ if (!parent->num_ports) {
++ /* Fall back to SPROM as last resort.
++ * This will fail on most cards.
++ */
++ parent->num_ports = nr64(ESPC_NUM_PORTS_MACS) &
++ ESPC_NUM_PORTS_MACS_VAL;
++
++ if (!parent->num_ports)
++ return -ENODEV;
++ }
+ }
+ }
+
+@@ -6484,7 +7290,8 @@ static int __devinit phy_record(struct niu_parent *parent,
+ return 0;
+ if (type == PHY_TYPE_PMA_PMD || type == PHY_TYPE_PCS) {
+ if (((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM8704) &&
+- ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_MRVL88X2011))
++ ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_MRVL88X2011) &&
++ ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM8706))
+ return 0;
+ } else {
+ if ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM5464R)
+@@ -6731,80 +7538,98 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent)
+ u32 val;
+ int err;
+
+- err = fill_phy_probe_info(np, parent, info);
+- if (err)
+- return err;
+-
+- num_10g = count_10g_ports(info, &lowest_10g);
+- num_1g = count_1g_ports(info, &lowest_1g);
+-
+- switch ((num_10g << 4) | num_1g) {
+- case 0x24:
+- if (lowest_1g == 10)
+- parent->plat_type = PLAT_TYPE_VF_P0;
+- else if (lowest_1g == 26)
+- parent->plat_type = PLAT_TYPE_VF_P1;
+- else
+- goto unknown_vg_1g_port;
+-
+- /* fallthru */
+- case 0x22:
+- val = (phy_encode(PORT_TYPE_10G, 0) |
+- phy_encode(PORT_TYPE_10G, 1) |
++ if (!strcmp(np->vpd.model, "SUNW,CP3220") ||
++ !strcmp(np->vpd.model, "SUNW,CP3260")) {
++ num_10g = 0;
++ num_1g = 2;
++ parent->plat_type = PLAT_TYPE_ATCA_CP3220;
++ parent->num_ports = 4;
++ val = (phy_encode(PORT_TYPE_1G, 0) |
++ phy_encode(PORT_TYPE_1G, 1) |
+ phy_encode(PORT_TYPE_1G, 2) |
+ phy_encode(PORT_TYPE_1G, 3));
+- break;
+-
+- case 0x20:
++ } else if (niu_board_model_match(np, NIU_FOXXY_BM_STR)) {
++ num_10g = 2;
++ num_1g = 0;
++ parent->num_ports = 2;
+ val = (phy_encode(PORT_TYPE_10G, 0) |
+ phy_encode(PORT_TYPE_10G, 1));
+- break;
++ } else {
++ err = fill_phy_probe_info(np, parent, info);
++ if (err)
++ return err;
+
+- case 0x10:
+- val = phy_encode(PORT_TYPE_10G, np->port);
+- break;
++ num_10g = count_10g_ports(info, &lowest_10g);
++ num_1g = count_1g_ports(info, &lowest_1g);
+
+- case 0x14:
+- if (lowest_1g == 10)
+- parent->plat_type = PLAT_TYPE_VF_P0;
+- else if (lowest_1g == 26)
+- parent->plat_type = PLAT_TYPE_VF_P1;
+- else
+- goto unknown_vg_1g_port;
++ switch ((num_10g << 4) | num_1g) {
++ case 0x24:
++ if (lowest_1g == 10)
++ parent->plat_type = PLAT_TYPE_VF_P0;
++ else if (lowest_1g == 26)
++ parent->plat_type = PLAT_TYPE_VF_P1;
++ else
++ goto unknown_vg_1g_port;
+
+- /* fallthru */
+- case 0x13:
+- if ((lowest_10g & 0x7) == 0)
++ /* fallthru */
++ case 0x22:
+ val = (phy_encode(PORT_TYPE_10G, 0) |
+- phy_encode(PORT_TYPE_1G, 1) |
+- phy_encode(PORT_TYPE_1G, 2) |
+- phy_encode(PORT_TYPE_1G, 3));
+- else
+- val = (phy_encode(PORT_TYPE_1G, 0) |
+ phy_encode(PORT_TYPE_10G, 1) |
+ phy_encode(PORT_TYPE_1G, 2) |
+ phy_encode(PORT_TYPE_1G, 3));
+- break;
++ break;
+
+- case 0x04:
+- if (lowest_1g == 10)
+- parent->plat_type = PLAT_TYPE_VF_P0;
+- else if (lowest_1g == 26)
+- parent->plat_type = PLAT_TYPE_VF_P1;
+- else
+- goto unknown_vg_1g_port;
++ case 0x20:
++ val = (phy_encode(PORT_TYPE_10G, 0) |
++ phy_encode(PORT_TYPE_10G, 1));
++ break;
+
+- val = (phy_encode(PORT_TYPE_1G, 0) |
+- phy_encode(PORT_TYPE_1G, 1) |
+- phy_encode(PORT_TYPE_1G, 2) |
+- phy_encode(PORT_TYPE_1G, 3));
+- break;
++ case 0x10:
++ val = phy_encode(PORT_TYPE_10G, np->port);
++ break;
+
+- default:
+- printk(KERN_ERR PFX "Unsupported port config "
+- "10G[%d] 1G[%d]\n",
+- num_10g, num_1g);
+- return -EINVAL;
++ case 0x14:
++ if (lowest_1g == 10)
++ parent->plat_type = PLAT_TYPE_VF_P0;
++ else if (lowest_1g == 26)
++ parent->plat_type = PLAT_TYPE_VF_P1;
++ else
++ goto unknown_vg_1g_port;
++
++ /* fallthru */
++ case 0x13:
++ if ((lowest_10g & 0x7) == 0)
++ val = (phy_encode(PORT_TYPE_10G, 0) |
++ phy_encode(PORT_TYPE_1G, 1) |
++ phy_encode(PORT_TYPE_1G, 2) |
++ phy_encode(PORT_TYPE_1G, 3));
++ else
++ val = (phy_encode(PORT_TYPE_1G, 0) |
++ phy_encode(PORT_TYPE_10G, 1) |
++ phy_encode(PORT_TYPE_1G, 2) |
++ phy_encode(PORT_TYPE_1G, 3));
++ break;
++
++ case 0x04:
++ if (lowest_1g == 10)
++ parent->plat_type = PLAT_TYPE_VF_P0;
++ else if (lowest_1g == 26)
++ parent->plat_type = PLAT_TYPE_VF_P1;
++ else
++ goto unknown_vg_1g_port;
++
++ val = (phy_encode(PORT_TYPE_1G, 0) |
++ phy_encode(PORT_TYPE_1G, 1) |
++ phy_encode(PORT_TYPE_1G, 2) |
++ phy_encode(PORT_TYPE_1G, 3));
++ break;
++
++ default:
++ printk(KERN_ERR PFX "Unsupported port config "
++ "10G[%d] 1G[%d]\n",
++ num_10g, num_1g);
++ return -EINVAL;
++ }
+ }
+
+ parent->port_phy = val;
+@@ -7189,15 +8014,16 @@ static int __devinit niu_get_invariants(struct niu *np)
+
+ have_props = !err;
+
+- err = niu_get_and_validate_port(np);
+- if (err)
+- return err;
+-
+ err = niu_init_mac_ipp_pcs_base(np);
+ if (err)
+ return err;
+
+- if (!have_props) {
++ if (have_props) {
++ err = niu_get_and_validate_port(np);
++ if (err)
++ return err;
++
++ } else {
+ if (np->parent->plat_type == PLAT_TYPE_NIU)
+ return -EINVAL;
+
+@@ -7209,10 +8035,17 @@ static int __devinit niu_get_invariants(struct niu *np)
+ niu_pci_vpd_fetch(np, offset);
+ nw64(ESPC_PIO_EN, 0);
+
+- if (np->flags & NIU_FLAGS_VPD_VALID)
++ if (np->flags & NIU_FLAGS_VPD_VALID) {
+ niu_pci_vpd_validate(np);
++ err = niu_get_and_validate_port(np);
++ if (err)
++ return err;
++ }
+
+ if (!(np->flags & NIU_FLAGS_VPD_VALID)) {
++ err = niu_get_and_validate_port(np);
++ if (err)
++ return err;
+ err = niu_pci_probe_sprom(np);
+ if (err)
+ return err;
+@@ -7599,14 +8432,25 @@ static void __devinit niu_device_announce(struct niu *np)
+ pr_info("%s: NIU Ethernet %s\n",
+ dev->name, print_mac(mac, dev->dev_addr));
+
+- pr_info("%s: Port type[%s] mode[%s:%s] XCVR[%s] phy[%s]\n",
+- dev->name,
+- (np->flags & NIU_FLAGS_XMAC ? "XMAC" : "BMAC"),
+- (np->flags & NIU_FLAGS_10G ? "10G" : "1G"),
+- (np->flags & NIU_FLAGS_FIBER ? "FIBER" : "COPPER"),
+- (np->mac_xcvr == MAC_XCVR_MII ? "MII" :
+- (np->mac_xcvr == MAC_XCVR_PCS ? "PCS" : "XPCS")),
+- np->vpd.phy_type);
++ if (np->parent->plat_type == PLAT_TYPE_ATCA_CP3220) {
++ pr_info("%s: Port type[%s] mode[%s:%s] XCVR[%s] phy[%s]\n",
++ dev->name,
++ (np->flags & NIU_FLAGS_XMAC ? "XMAC" : "BMAC"),
++ (np->flags & NIU_FLAGS_10G ? "10G" : "1G"),
++ (np->flags & NIU_FLAGS_FIBER ? "RGMII FIBER" : "SERDES"),
++ (np->mac_xcvr == MAC_XCVR_MII ? "MII" :
++ (np->mac_xcvr == MAC_XCVR_PCS ? "PCS" : "XPCS")),
++ np->vpd.phy_type);
++ } else {
++ pr_info("%s: Port type[%s] mode[%s:%s] XCVR[%s] phy[%s]\n",
++ dev->name,
++ (np->flags & NIU_FLAGS_XMAC ? "XMAC" : "BMAC"),
++ (np->flags & NIU_FLAGS_10G ? "10G" : "1G"),
++ (np->flags & NIU_FLAGS_FIBER ? "FIBER" : "COPPER"),
++ (np->mac_xcvr == MAC_XCVR_MII ? "MII" :
++ (np->mac_xcvr == MAC_XCVR_PCS ? "PCS" : "XPCS")),
++ np->vpd.phy_type);
++ }
+ }
+
+ static int __devinit niu_pci_init_one(struct pci_dev *pdev,
+diff --git a/drivers/net/niu.h b/drivers/net/niu.h
+index 59dc05f..97ffbe1 100644
+--- a/drivers/net/niu.h
++++ b/drivers/net/niu.h
+@@ -2537,6 +2537,7 @@ struct fcram_hash_ipv6 {
+
+ #define NIU_PHY_ID_MASK 0xfffff0f0
+ #define NIU_PHY_ID_BCM8704 0x00206030
++#define NIU_PHY_ID_BCM8706 0x00206035
+ #define NIU_PHY_ID_BCM5464R 0x002060b0
+ #define NIU_PHY_ID_MRVL88X2011 0x01410020
+
+@@ -2937,6 +2938,15 @@ struct rx_ring_info {
+
+ #define NIU_MAX_MTU 9216
+
++/* VPD strings */
++#define NIU_QGC_LP_BM_STR "501-7606"
++#define NIU_2XGF_LP_BM_STR "501-7283"
++#define NIU_QGC_PEM_BM_STR "501-7765"
++#define NIU_2XGF_PEM_BM_STR "501-7626"
++#define NIU_ALONSO_BM_STR "373-0202"
++#define NIU_FOXXY_BM_STR "501-7961"
++#define NIU_2XGF_MRVL_BM_STR "SK-6E82"
++
+ #define NIU_VPD_MIN_MAJOR 3
+ #define NIU_VPD_MIN_MINOR 4
+
+@@ -3061,6 +3071,7 @@ struct niu_parent {
+ #define PLAT_TYPE_NIU 0x02
+ #define PLAT_TYPE_VF_P0 0x03
+ #define PLAT_TYPE_VF_P1 0x04
++#define PLAT_TYPE_ATCA_CP3220 0x08
+
+ u8 num_ports;
+
+@@ -3198,10 +3209,13 @@ struct niu {
+ struct niu_parent *parent;
+
+ u32 flags;
++#define NIU_FLAGS_HOTPLUG_PHY_PRESENT 0x02000000 /* Removebale PHY detected*/
++#define NIU_FLAGS_HOTPLUG_PHY 0x01000000 /* Removebale PHY */
++#define NIU_FLAGS_VPD_VALID 0x00800000 /* VPD has valid version */
+ #define NIU_FLAGS_MSIX 0x00400000 /* MSI-X in use */
+ #define NIU_FLAGS_MCAST 0x00200000 /* multicast filter enabled */
+ #define NIU_FLAGS_PROMISC 0x00100000 /* PROMISC enabled */
+-#define NIU_FLAGS_VPD_VALID 0x00080000 /* VPD has valid version */
++#define NIU_FLAGS_XCVR_SERDES 0x00080000 /* 0=PHY 1=SERDES */
+ #define NIU_FLAGS_10G 0x00040000 /* 0=1G 1=10G */
+ #define NIU_FLAGS_FIBER 0x00020000 /* 0=COPPER 1=FIBER */
+ #define NIU_FLAGS_XMAC 0x00010000 /* 0=BMAC 1=XMAC */
+diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
+index 2e39e02..3b2a6c5 100644
+--- a/drivers/net/pasemi_mac.c
++++ b/drivers/net/pasemi_mac.c
+@@ -55,15 +55,10 @@
+ * - Multiqueue RX/TX
+ */
+
+-
+-/* Must be a power of two */
+-#define RX_RING_SIZE 2048
+-#define TX_RING_SIZE 4096
+-
+ #define LRO_MAX_AGGR 64
+
+ #define PE_MIN_MTU 64
+-#define PE_MAX_MTU 1500
++#define PE_MAX_MTU 9000
+ #define PE_DEF_MTU ETH_DATA_LEN
+
+ #define DEFAULT_MSG_ENABLE \
+@@ -76,16 +71,6 @@
+ NETIF_MSG_RX_ERR | \
+ NETIF_MSG_TX_ERR)
+
+-#define TX_DESC(tx, num) ((tx)->chan.ring_virt[(num) & (TX_RING_SIZE-1)])
+-#define TX_DESC_INFO(tx, num) ((tx)->ring_info[(num) & (TX_RING_SIZE-1)])
+-#define RX_DESC(rx, num) ((rx)->chan.ring_virt[(num) & (RX_RING_SIZE-1)])
+-#define RX_DESC_INFO(rx, num) ((rx)->ring_info[(num) & (RX_RING_SIZE-1)])
+-#define RX_BUFF(rx, num) ((rx)->buffers[(num) & (RX_RING_SIZE-1)])
+-
+-#define RING_USED(ring) (((ring)->next_to_fill - (ring)->next_to_clean) \
+- & ((ring)->size - 1))
+-#define RING_AVAIL(ring) ((ring->size) - RING_USED(ring))
+-
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR ("Olof Johansson <olof at lixom.net>");
+ MODULE_DESCRIPTION("PA Semi PWRficient Ethernet driver");
+@@ -94,6 +79,8 @@ static int debug = -1; /* -1 == use DEFAULT_MSG_ENABLE as value */
+ module_param(debug, int, 0);
+ MODULE_PARM_DESC(debug, "PA Semi MAC bitmapped debugging message enable value");
+
++extern const struct ethtool_ops pasemi_mac_ethtool_ops;
++
+ static int translation_enabled(void)
+ {
+ #if defined(CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE)
+@@ -322,6 +309,104 @@ static int pasemi_mac_unmap_tx_skb(struct pasemi_mac *mac,
+ return (nfrags + 3) & ~1;
+ }
+
++static struct pasemi_mac_csring *pasemi_mac_setup_csring(struct pasemi_mac *mac)
++{
++ struct pasemi_mac_csring *ring;
++ u32 val;
++ unsigned int cfg;
++ int chno;
++
++ ring = pasemi_dma_alloc_chan(TXCHAN, sizeof(struct pasemi_mac_csring),
++ offsetof(struct pasemi_mac_csring, chan));
++
++ if (!ring) {
++ dev_err(&mac->pdev->dev, "Can't allocate checksum channel\n");
++ goto out_chan;
++ }
++
++ chno = ring->chan.chno;
++
++ ring->size = CS_RING_SIZE;
++ ring->next_to_fill = 0;
++
++ /* Allocate descriptors */
++ if (pasemi_dma_alloc_ring(&ring->chan, CS_RING_SIZE))
++ goto out_ring_desc;
++
++ write_dma_reg(PAS_DMA_TXCHAN_BASEL(chno),
++ PAS_DMA_TXCHAN_BASEL_BRBL(ring->chan.ring_dma));
++ val = PAS_DMA_TXCHAN_BASEU_BRBH(ring->chan.ring_dma >> 32);
++ val |= PAS_DMA_TXCHAN_BASEU_SIZ(CS_RING_SIZE >> 3);
++
++ write_dma_reg(PAS_DMA_TXCHAN_BASEU(chno), val);
++
++ ring->events[0] = pasemi_dma_alloc_flag();
++ ring->events[1] = pasemi_dma_alloc_flag();
++ if (ring->events[0] < 0 || ring->events[1] < 0)
++ goto out_flags;
++
++ pasemi_dma_clear_flag(ring->events[0]);
++ pasemi_dma_clear_flag(ring->events[1]);
++
++ ring->fun = pasemi_dma_alloc_fun();
++ if (ring->fun < 0)
++ goto out_fun;
++
++ cfg = PAS_DMA_TXCHAN_CFG_TY_FUNC | PAS_DMA_TXCHAN_CFG_UP |
++ PAS_DMA_TXCHAN_CFG_TATTR(ring->fun) |
++ PAS_DMA_TXCHAN_CFG_LPSQ | PAS_DMA_TXCHAN_CFG_LPDQ;
++
++ if (translation_enabled())
++ cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR;
++
++ write_dma_reg(PAS_DMA_TXCHAN_CFG(chno), cfg);
++
++ /* enable channel */
++ pasemi_dma_start_chan(&ring->chan, PAS_DMA_TXCHAN_TCMDSTA_SZ |
++ PAS_DMA_TXCHAN_TCMDSTA_DB |
++ PAS_DMA_TXCHAN_TCMDSTA_DE |
++ PAS_DMA_TXCHAN_TCMDSTA_DA);
++
++ return ring;
++
++out_fun:
++out_flags:
++ if (ring->events[0] >= 0)
++ pasemi_dma_free_flag(ring->events[0]);
++ if (ring->events[1] >= 0)
++ pasemi_dma_free_flag(ring->events[1]);
++ pasemi_dma_free_ring(&ring->chan);
++out_ring_desc:
++ pasemi_dma_free_chan(&ring->chan);
++out_chan:
++
++ return NULL;
++}
++
++static void pasemi_mac_setup_csrings(struct pasemi_mac *mac)
++{
++ int i;
++ mac->cs[0] = pasemi_mac_setup_csring(mac);
++ if (mac->type == MAC_TYPE_XAUI)
++ mac->cs[1] = pasemi_mac_setup_csring(mac);
++ else
++ mac->cs[1] = 0;
++
++ for (i = 0; i < MAX_CS; i++)
++ if (mac->cs[i])
++ mac->num_cs++;
++}
++
++static void pasemi_mac_free_csring(struct pasemi_mac_csring *csring)
++{
++ pasemi_dma_stop_chan(&csring->chan);
++ pasemi_dma_free_flag(csring->events[0]);
++ pasemi_dma_free_flag(csring->events[1]);
++ pasemi_dma_free_ring(&csring->chan);
++ pasemi_dma_free_chan(&csring->chan);
++ pasemi_dma_free_fun(csring->fun);
++}
++
+ static int pasemi_mac_setup_rx_resources(const struct net_device *dev)
+ {
+ struct pasemi_mac_rxring *ring;
+@@ -445,7 +530,7 @@ pasemi_mac_setup_tx_resources(const struct net_device *dev)
+ cfg = PAS_DMA_TXCHAN_CFG_TY_IFACE |
+ PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) |
+ PAS_DMA_TXCHAN_CFG_UP |
+- PAS_DMA_TXCHAN_CFG_WT(2);
++ PAS_DMA_TXCHAN_CFG_WT(4);
+
+ if (translation_enabled())
+ cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR;
+@@ -810,13 +895,21 @@ restart:
+ u64 mactx = TX_DESC(txring, i);
+ struct sk_buff *skb;
+
+- skb = TX_DESC_INFO(txring, i+1).skb;
+- nr_frags = TX_DESC_INFO(txring, i).dma;
+-
+ if ((mactx & XCT_MACTX_E) ||
+ (*chan->status & PAS_STATUS_ERROR))
+ pasemi_mac_tx_error(mac, mactx);
+
++ /* Skip over control descriptors */
++ if (!(mactx & XCT_MACTX_LLEN_M)) {
++ TX_DESC(txring, i) = 0;
++ TX_DESC(txring, i+1) = 0;
++ buf_count = 2;
++ continue;
++ }
++
++ skb = TX_DESC_INFO(txring, i+1).skb;
++ nr_frags = TX_DESC_INFO(txring, i).dma;
++
+ if (unlikely(mactx & XCT_MACTX_O))
+ /* Not yet transmitted */
+ break;
+@@ -1012,7 +1105,7 @@ static int pasemi_mac_phy_init(struct net_device *dev)
+ goto err;
+
+ phy_id = *prop;
+- snprintf(mac->phy_id, BUS_ID_SIZE, PHY_ID_FMT, (int)r.start, phy_id);
++ snprintf(mac->phy_id, BUS_ID_SIZE, "%x:%02x", (int)r.start, phy_id);
+
+ of_node_put(phy_dn);
+
+@@ -1041,13 +1134,7 @@ static int pasemi_mac_open(struct net_device *dev)
+ {
+ struct pasemi_mac *mac = netdev_priv(dev);
+ unsigned int flags;
+- int ret;
+-
+- /* enable rx section */
+- write_dma_reg(PAS_DMA_COM_RXCMD, PAS_DMA_COM_RXCMD_EN);
+-
+- /* enable tx section */
+- write_dma_reg(PAS_DMA_COM_TXCMD, PAS_DMA_COM_TXCMD_EN);
++ int i, ret;
+
+ flags = PAS_MAC_CFG_TXP_FCE | PAS_MAC_CFG_TXP_FPC(3) |
+ PAS_MAC_CFG_TXP_SL(3) | PAS_MAC_CFG_TXP_COB(0xf) |
+@@ -1064,6 +1151,19 @@ static int pasemi_mac_open(struct net_device *dev)
+ if (!mac->tx)
+ goto out_tx_ring;
+
++ /* We might already have allocated rings in case mtu was changed
++ * before interface was brought up.
++ */
++ if (dev->mtu > 1500 && !mac->num_cs) {
++ pasemi_mac_setup_csrings(mac);
++ if (!mac->num_cs)
++ goto out_tx_ring;
++ }
++
++ /* Zero out rmon counters */
++ for (i = 0; i < 32; i++)
++ write_mac_reg(mac, PAS_MAC_RMON(i), 0);
++
+ /* 0x3ff with 33MHz clock is about 31us */
+ write_iob_reg(PAS_IOB_DMA_COM_TIMEOUTCFG,
+ PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0x3ff));
+@@ -1247,7 +1347,7 @@ static int pasemi_mac_close(struct net_device *dev)
+ {
+ struct pasemi_mac *mac = netdev_priv(dev);
+ unsigned int sta;
+- int rxch, txch;
++ int rxch, txch, i;
+
+ rxch = rx_ring(mac)->chan.chno;
+ txch = tx_ring(mac)->chan.chno;
+@@ -1292,6 +1392,13 @@ static int pasemi_mac_close(struct net_device *dev)
+ free_irq(mac->tx->chan.irq, mac->tx);
+ free_irq(mac->rx->chan.irq, mac->rx);
+
++ for (i = 0; i < mac->num_cs; i++) {
++ pasemi_mac_free_csring(mac->cs[i]);
++ mac->cs[i] = NULL;
++ }
++
++ mac->num_cs = 0;
++
+ /* Free resources */
+ pasemi_mac_free_rx_resources(mac);
+ pasemi_mac_free_tx_resources(mac);
+@@ -1299,35 +1406,113 @@ static int pasemi_mac_close(struct net_device *dev)
+ return 0;
+ }
+
++static void pasemi_mac_queue_csdesc(const struct sk_buff *skb,
++ const dma_addr_t *map,
++ const unsigned int *map_size,
++ struct pasemi_mac_txring *txring,
++ struct pasemi_mac_csring *csring)
++{
++ u64 fund;
++ dma_addr_t cs_dest;
++ const int nh_off = skb_network_offset(skb);
++ const int nh_len = skb_network_header_len(skb);
++ const int nfrags = skb_shinfo(skb)->nr_frags;
++ int cs_size, i, fill, hdr, cpyhdr, evt;
++ dma_addr_t csdma;
++
++ fund = XCT_FUN_ST | XCT_FUN_RR_8BRES |
++ XCT_FUN_O | XCT_FUN_FUN(csring->fun) |
++ XCT_FUN_CRM_SIG | XCT_FUN_LLEN(skb->len - nh_off) |
++ XCT_FUN_SHL(nh_len >> 2) | XCT_FUN_SE;
++
++ switch (ip_hdr(skb)->protocol) {
++ case IPPROTO_TCP:
++ fund |= XCT_FUN_SIG_TCP4;
++ /* TCP checksum is 16 bytes into the header */
++ cs_dest = map[0] + skb_transport_offset(skb) + 16;
++ break;
++ case IPPROTO_UDP:
++ fund |= XCT_FUN_SIG_UDP4;
++ /* UDP checksum is 6 bytes into the header */
++ cs_dest = map[0] + skb_transport_offset(skb) + 6;
++ break;
++ default:
++ BUG();
++ }
++
++ /* Do the checksum offloaded */
++ fill = csring->next_to_fill;
++ hdr = fill;
++
++ CS_DESC(csring, fill++) = fund;
++ /* Room for 8BRES. Checksum result is really 2 bytes into it */
++ csdma = csring->chan.ring_dma + (fill & (CS_RING_SIZE-1)) * 8 + 2;
++ CS_DESC(csring, fill++) = 0;
++
++ CS_DESC(csring, fill) = XCT_PTR_LEN(map_size[0]-nh_off) | XCT_PTR_ADDR(map[0]+nh_off);
++ for (i = 1; i <= nfrags; i++)
++ CS_DESC(csring, fill+i) = XCT_PTR_LEN(map_size[i]) | XCT_PTR_ADDR(map[i]);
++
++ fill += i;
++ if (fill & 1)
++ fill++;
++
++ /* Copy the result into the TCP packet */
++ cpyhdr = fill;
++ CS_DESC(csring, fill++) = XCT_FUN_O | XCT_FUN_FUN(csring->fun) |
++ XCT_FUN_LLEN(2) | XCT_FUN_SE;
++ CS_DESC(csring, fill++) = XCT_PTR_LEN(2) | XCT_PTR_ADDR(cs_dest) | XCT_PTR_T;
++ CS_DESC(csring, fill++) = XCT_PTR_LEN(2) | XCT_PTR_ADDR(csdma);
++ fill++;
++
++ evt = !csring->last_event;
++ csring->last_event = evt;
++
++ /* Event handshaking with MAC TX */
++ CS_DESC(csring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O |
++ CTRL_CMD_ETYPE_SET | CTRL_CMD_REG(csring->events[evt]);
++ CS_DESC(csring, fill++) = 0;
++ CS_DESC(csring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O |
++ CTRL_CMD_ETYPE_WCLR | CTRL_CMD_REG(csring->events[!evt]);
++ CS_DESC(csring, fill++) = 0;
++ csring->next_to_fill = fill & (CS_RING_SIZE-1);
++
++ cs_size = fill - hdr;
++ write_dma_reg(PAS_DMA_TXCHAN_INCR(csring->chan.chno), (cs_size) >> 1);
++
++ /* TX-side event handshaking */
++ fill = txring->next_to_fill;
++ TX_DESC(txring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O |
++ CTRL_CMD_ETYPE_WSET | CTRL_CMD_REG(csring->events[evt]);
++ TX_DESC(txring, fill++) = 0;
++ TX_DESC(txring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O |
++ CTRL_CMD_ETYPE_CLR | CTRL_CMD_REG(csring->events[!evt]);
++ TX_DESC(txring, fill++) = 0;
++ txring->next_to_fill = fill;
++
++ write_dma_reg(PAS_DMA_TXCHAN_INCR(txring->chan.chno), 2);
++
++ return;
++}
++
+ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
+ {
+- struct pasemi_mac *mac = netdev_priv(dev);
+- struct pasemi_mac_txring *txring;
+- u64 dflags, mactx;
++ struct pasemi_mac * const mac = netdev_priv(dev);
++ struct pasemi_mac_txring * const txring = tx_ring(mac);
++ struct pasemi_mac_csring *csring;
++ u64 dflags = 0;
++ u64 mactx;
+ dma_addr_t map[MAX_SKB_FRAGS+1];
+ unsigned int map_size[MAX_SKB_FRAGS+1];
+ unsigned long flags;
+ int i, nfrags;
+ int fill;
++ const int nh_off = skb_network_offset(skb);
++ const int nh_len = skb_network_header_len(skb);
+
+- dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_CRC_PAD;
+-
+- if (skb->ip_summed == CHECKSUM_PARTIAL) {
+- const unsigned char *nh = skb_network_header(skb);
++ prefetch(&txring->ring_info);
+
+- switch (ip_hdr(skb)->protocol) {
+- case IPPROTO_TCP:
+- dflags |= XCT_MACTX_CSUM_TCP;
+- dflags |= XCT_MACTX_IPH(skb_network_header_len(skb) >> 2);
+- dflags |= XCT_MACTX_IPO(nh - skb->data);
+- break;
+- case IPPROTO_UDP:
+- dflags |= XCT_MACTX_CSUM_UDP;
+- dflags |= XCT_MACTX_IPH(skb_network_header_len(skb) >> 2);
+- dflags |= XCT_MACTX_IPO(nh - skb->data);
+- break;
+- }
+- }
++ dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_CRC_PAD;
+
+ nfrags = skb_shinfo(skb)->nr_frags;
+
+@@ -1350,24 +1535,46 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
+ }
+ }
+
+- mactx = dflags | XCT_MACTX_LLEN(skb->len);
++ if (skb->ip_summed == CHECKSUM_PARTIAL && skb->len <= 1540) {
++ switch (ip_hdr(skb)->protocol) {
++ case IPPROTO_TCP:
++ dflags |= XCT_MACTX_CSUM_TCP;
++ dflags |= XCT_MACTX_IPH(nh_len >> 2);
++ dflags |= XCT_MACTX_IPO(nh_off);
++ break;
++ case IPPROTO_UDP:
++ dflags |= XCT_MACTX_CSUM_UDP;
++ dflags |= XCT_MACTX_IPH(nh_len >> 2);
++ dflags |= XCT_MACTX_IPO(nh_off);
++ break;
++ default:
++ WARN_ON(1);
++ }
++ }
+
+- txring = tx_ring(mac);
++ mactx = dflags | XCT_MACTX_LLEN(skb->len);
+
+ spin_lock_irqsave(&txring->lock, flags);
+
+- fill = txring->next_to_fill;
+-
+ /* Avoid stepping on the same cache line that the DMA controller
+ * is currently about to send, so leave at least 8 words available.
+ * Total free space needed is mactx + fragments + 8
+ */
+- if (RING_AVAIL(txring) < nfrags + 10) {
++ if (RING_AVAIL(txring) < nfrags + 14) {
+ /* no room -- stop the queue and wait for tx intr */
+ netif_stop_queue(dev);
+ goto out_err;
+ }
+
++ /* Queue up checksum + event descriptors, if needed */
++ if (mac->num_cs && skb->ip_summed == CHECKSUM_PARTIAL && skb->len > 1540) {
++ csring = mac->cs[mac->last_cs];
++ mac->last_cs = (mac->last_cs + 1) % mac->num_cs;
++
++ pasemi_mac_queue_csdesc(skb, map, map_size, txring, csring);
++ }
++
++ fill = txring->next_to_fill;
+ TX_DESC(txring, fill) = mactx;
+ TX_DESC_INFO(txring, fill).dma = nfrags;
+ fill++;
+@@ -1441,12 +1648,33 @@ static int pasemi_mac_poll(struct napi_struct *napi, int budget)
+ return pkts;
+ }
+
++#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 pasemi_mac_netpoll(struct net_device *dev)
++{
++ const struct pasemi_mac *mac = netdev_priv(dev);
++
++ disable_irq(mac->tx->chan.irq);
++ pasemi_mac_tx_intr(mac->tx->chan.irq, mac->tx);
++ enable_irq(mac->tx->chan.irq);
++
++ disable_irq(mac->rx->chan.irq);
++ pasemi_mac_rx_intr(mac->rx->chan.irq, mac->rx);
++ enable_irq(mac->rx->chan.irq);
++}
++#endif
++
+ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu)
+ {
+ struct pasemi_mac *mac = netdev_priv(dev);
+ unsigned int reg;
+- unsigned int rcmdsta;
++ unsigned int rcmdsta = 0;
+ int running;
++ int ret = 0;
+
+ if (new_mtu < PE_MIN_MTU || new_mtu > PE_MAX_MTU)
+ return -EINVAL;
+@@ -1468,6 +1696,16 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu)
+ pasemi_mac_pause_rxint(mac);
+ pasemi_mac_clean_rx(rx_ring(mac), RX_RING_SIZE);
+ pasemi_mac_free_rx_buffers(mac);
++
++ }
++
++ /* Setup checksum channels if large MTU and none already allocated */
++ if (new_mtu > 1500 && !mac->num_cs) {
++ pasemi_mac_setup_csrings(mac);
++ if (!mac->num_cs) {
++ ret = -ENOMEM;
++ goto out;
++ }
+ }
+
+ /* Change maxf, i.e. what size frames are accepted.
+@@ -1482,6 +1720,7 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu)
+ /* MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
+ mac->bufsz = new_mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128;
+
++out:
+ if (running) {
+ write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
+ rcmdsta | PAS_DMA_RXINT_RCMDSTA_EN);
+@@ -1494,7 +1733,7 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu)
+ pasemi_mac_intf_enable(mac);
+ }
+
+- return 0;
++ return ret;
+ }
+
+ static int __devinit
+@@ -1528,7 +1767,7 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ netif_napi_add(dev, &mac->napi, pasemi_mac_poll, 64);
+
+ dev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX | NETIF_F_SG |
+- NETIF_F_HIGHDMA;
++ NETIF_F_HIGHDMA | NETIF_F_GSO;
+
+ mac->lro_mgr.max_aggr = LRO_MAX_AGGR;
+ mac->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS;
+@@ -1588,8 +1827,12 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ dev->mtu = PE_DEF_MTU;
+ /* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
+ mac->bufsz = dev->mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128;
++#ifdef CONFIG_NET_POLL_CONTROLLER
++ dev->poll_controller = pasemi_mac_netpoll;
++#endif
+
+ dev->change_mtu = pasemi_mac_change_mtu;
++ dev->ethtool_ops = &pasemi_mac_ethtool_ops;
+
+ if (err)
+ goto out;
+diff --git a/drivers/net/pasemi_mac.h b/drivers/net/pasemi_mac.h
+index 99e7b93..1a115ec 100644
+--- a/drivers/net/pasemi_mac.h
++++ b/drivers/net/pasemi_mac.h
+@@ -26,7 +26,14 @@
+ #include <linux/spinlock.h>
+ #include <linux/phy.h>
+
++/* Must be a power of two */
++#define RX_RING_SIZE 2048
++#define TX_RING_SIZE 4096
++#define CS_RING_SIZE (TX_RING_SIZE*2)
++
++
+ #define MAX_LRO_DESCRIPTORS 8
++#define MAX_CS 2
+
+ struct pasemi_mac_txring {
+ struct pasemi_dmachan chan; /* Must be first */
+@@ -51,6 +58,15 @@ struct pasemi_mac_rxring {
+ struct pasemi_mac *mac; /* Needed in intr handler */
+ };
+
++struct pasemi_mac_csring {
++ struct pasemi_dmachan chan;
++ unsigned int size;
++ unsigned int next_to_fill;
++ int events[2];
++ int last_event;
++ int fun;
++};
++
+ struct pasemi_mac {
+ struct net_device *netdev;
+ struct pci_dev *pdev;
+@@ -60,10 +76,12 @@ struct pasemi_mac {
+ struct napi_struct napi;
+
+ int bufsz; /* RX ring buffer size */
++ int last_cs;
++ int num_cs;
++ u32 dma_if;
+ u8 type;
+ #define MAC_TYPE_GMAC 1
+ #define MAC_TYPE_XAUI 2
+- u32 dma_if;
+
+ u8 mac_addr[6];
+
+@@ -74,6 +92,7 @@ struct pasemi_mac {
+
+ struct pasemi_mac_txring *tx;
+ struct pasemi_mac_rxring *rx;
++ struct pasemi_mac_csring *cs[MAX_CS];
+ char tx_irq_name[10]; /* "eth%d tx" */
+ char rx_irq_name[10]; /* "eth%d rx" */
+ int link;
+@@ -90,6 +109,16 @@ struct pasemi_mac_buffer {
+ dma_addr_t dma;
+ };
+
++#define TX_DESC(tx, num) ((tx)->chan.ring_virt[(num) & (TX_RING_SIZE-1)])
++#define TX_DESC_INFO(tx, num) ((tx)->ring_info[(num) & (TX_RING_SIZE-1)])
++#define RX_DESC(rx, num) ((rx)->chan.ring_virt[(num) & (RX_RING_SIZE-1)])
++#define RX_DESC_INFO(rx, num) ((rx)->ring_info[(num) & (RX_RING_SIZE-1)])
++#define RX_BUFF(rx, num) ((rx)->buffers[(num) & (RX_RING_SIZE-1)])
++#define CS_DESC(cs, num) ((cs)->chan.ring_virt[(num) & (CS_RING_SIZE-1)])
++
++#define RING_USED(ring) (((ring)->next_to_fill - (ring)->next_to_clean) \
++ & ((ring)->size - 1))
++#define RING_AVAIL(ring) ((ring->size) - RING_USED(ring))
+
+ /* PCI register offsets and formats */
+
+@@ -101,6 +130,7 @@ enum {
+ PAS_MAC_CFG_ADR0 = 0x8c,
+ PAS_MAC_CFG_ADR1 = 0x90,
+ PAS_MAC_CFG_TXP = 0x98,
++ PAS_MAC_CFG_RMON = 0x100,
+ PAS_MAC_IPC_CHNL = 0x208,
+ };
+
+@@ -172,6 +202,8 @@ enum {
+ #define PAS_MAC_CFG_TXP_TIFG(x) (((x) << PAS_MAC_CFG_TXP_TIFG_S) & \
+ PAS_MAC_CFG_TXP_TIFG_M)
+
++#define PAS_MAC_RMON(r) (0x100+(r)*4)
++
+ #define PAS_MAC_IPC_CHNL_DCHNO_M 0x003f0000
+ #define PAS_MAC_IPC_CHNL_DCHNO_S 16
+ #define PAS_MAC_IPC_CHNL_DCHNO(x) (((x) << PAS_MAC_IPC_CHNL_DCHNO_S) & \
+@@ -181,4 +213,5 @@ enum {
+ #define PAS_MAC_IPC_CHNL_BCH(x) (((x) << PAS_MAC_IPC_CHNL_BCH_S) & \
+ PAS_MAC_IPC_CHNL_BCH_M)
+
++
+ #endif /* PASEMI_MAC_H */
+diff --git a/drivers/net/pasemi_mac_ethtool.c b/drivers/net/pasemi_mac_ethtool.c
+new file mode 100644
+index 0000000..5e8df3a
+--- /dev/null
++++ b/drivers/net/pasemi_mac_ethtool.c
+@@ -0,0 +1,159 @@
++/*
++ * Copyright (C) 2006-2008 PA Semi, Inc
++ *
++ * Ethtool hooks for the PA Semi PWRficient onchip 1G/10G Ethernet MACs
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++
++#include <linux/netdevice.h>
++#include <linux/ethtool.h>
++#include <linux/pci.h>
++#include <linux/inet_lro.h>
++
++#include <asm/pasemi_dma.h>
++#include "pasemi_mac.h"
++
++static struct {
++ const char str[ETH_GSTRING_LEN];
++} ethtool_stats_keys[] = {
++ { "rx-drops" },
++ { "rx-bytes" },
++ { "rx-packets" },
++ { "rx-broadcast-packets" },
++ { "rx-multicast-packets" },
++ { "rx-crc-errors" },
++ { "rx-undersize-errors" },
++ { "rx-oversize-errors" },
++ { "rx-short-fragment-errors" },
++ { "rx-jabber-errors" },
++ { "rx-64-byte-packets" },
++ { "rx-65-127-byte-packets" },
++ { "rx-128-255-byte-packets" },
++ { "rx-256-511-byte-packets" },
++ { "rx-512-1023-byte-packets" },
++ { "rx-1024-1518-byte-packets" },
++ { "rx-pause-frames" },
++ { "tx-bytes" },
++ { "tx-packets" },
++ { "tx-broadcast-packets" },
++ { "tx-multicast-packets" },
++ { "tx-collisions" },
++ { "tx-late-collisions" },
++ { "tx-excessive-collisions" },
++ { "tx-crc-errors" },
++ { "tx-undersize-errors" },
++ { "tx-oversize-errors" },
++ { "tx-64-byte-packets" },
++ { "tx-65-127-byte-packets" },
++ { "tx-128-255-byte-packets" },
++ { "tx-256-511-byte-packets" },
++ { "tx-512-1023-byte-packets" },
++ { "tx-1024-1518-byte-packets" },
++};
++
++static int
++pasemi_mac_ethtool_get_settings(struct net_device *netdev,
++ struct ethtool_cmd *cmd)
++{
++ struct pasemi_mac *mac = netdev_priv(netdev);
++ struct phy_device *phydev = mac->phydev;
++
++ return phy_ethtool_gset(phydev, cmd);
++}
++
++static void
++pasemi_mac_ethtool_get_drvinfo(struct net_device *netdev,
++ struct ethtool_drvinfo *drvinfo)
++{
++ struct pasemi_mac *mac;
++ mac = netdev_priv(netdev);
++
++ /* clear and fill out info */
++ memset(drvinfo, 0, sizeof(struct ethtool_drvinfo));
++ strncpy(drvinfo->driver, "pasemi_mac", 12);
++ strcpy(drvinfo->version, "N/A");
++ strcpy(drvinfo->fw_version, "N/A");
++ strncpy(drvinfo->bus_info, pci_name(mac->pdev), 32);
++}
++
++static u32
++pasemi_mac_ethtool_get_msglevel(struct net_device *netdev)
++{
++ struct pasemi_mac *mac = netdev_priv(netdev);
++ return mac->msg_enable;
++}
++
++static void
++pasemi_mac_ethtool_set_msglevel(struct net_device *netdev,
++ u32 level)
++{
++ struct pasemi_mac *mac = netdev_priv(netdev);
++ mac->msg_enable = level;
++}
++
++
++static void
++pasemi_mac_ethtool_get_ringparam(struct net_device *netdev,
++ struct ethtool_ringparam *ering)
++{
++ struct pasemi_mac *mac = netdev->priv;
++
++ ering->tx_max_pending = TX_RING_SIZE/2;
++ ering->tx_pending = RING_USED(mac->tx)/2;
++ ering->rx_max_pending = RX_RING_SIZE/4;
++ ering->rx_pending = RING_USED(mac->rx)/4;
++}
++
++static int pasemi_mac_get_sset_count(struct net_device *netdev, int sset)
++{
++ switch (sset) {
++ case ETH_SS_STATS:
++ return ARRAY_SIZE(ethtool_stats_keys);
++ default:
++ return -EOPNOTSUPP;
++ }
++}
++
++static void pasemi_mac_get_ethtool_stats(struct net_device *netdev,
++ struct ethtool_stats *stats, u64 *data)
++{
++ struct pasemi_mac *mac = netdev->priv;
++ int i;
++
++ data[0] = pasemi_read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if))
++ >> PAS_DMA_RXINT_RCMDSTA_DROPS_S;
++ for (i = 0; i < 32; i++)
++ data[1+i] = pasemi_read_mac_reg(mac->dma_if, PAS_MAC_RMON(i));
++}
++
++static void pasemi_mac_get_strings(struct net_device *netdev, u32 stringset,
++ u8 *data)
++{
++ memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys));
++}
++
++const struct ethtool_ops pasemi_mac_ethtool_ops = {
++ .get_settings = pasemi_mac_ethtool_get_settings,
++ .get_drvinfo = pasemi_mac_ethtool_get_drvinfo,
++ .get_msglevel = pasemi_mac_ethtool_get_msglevel,
++ .set_msglevel = pasemi_mac_ethtool_set_msglevel,
++ .get_link = ethtool_op_get_link,
++ .get_ringparam = pasemi_mac_ethtool_get_ringparam,
++ .get_strings = pasemi_mac_get_strings,
++ .get_sset_count = pasemi_mac_get_sset_count,
++ .get_ethtool_stats = pasemi_mac_get_ethtool_stats,
++};
++
+diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
+index 5b80358..60c5cfe 100644
+--- a/drivers/net/phy/broadcom.c
++++ b/drivers/net/phy/broadcom.c
+@@ -99,6 +99,41 @@ static int bcm54xx_config_intr(struct phy_device *phydev)
+ return err;
+ }
+
++static int bcm5481_config_aneg(struct phy_device *phydev)
++{
++ int ret;
++
++ /* Aneg firsly. */
++ ret = genphy_config_aneg(phydev);
++
++ /* Then we can set up the delay. */
++ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
++ u16 reg;
++
++ /*
++ * There is no BCM5481 specification available, so down
++ * here is everything we know about "register 0x18". This
++ * at least helps BCM5481 to successfuly receive packets
++ * on MPC8360E-RDK board. Peter Barada <peterb at logicpd.com>
++ * says: "This sets delay between the RXD and RXC signals
++ * instead of using trace lengths to achieve timing".
++ */
++
++ /* Set RDX clk delay. */
++ reg = 0x7 | (0x7 << 12);
++ phy_write(phydev, 0x18, reg);
++
++ reg = phy_read(phydev, 0x18);
++ /* Set RDX-RXC skew. */
++ reg |= (1 << 8);
++ /* Write bits 14:0. */
++ reg |= (1 << 15);
++ phy_write(phydev, 0x18, reg);
++ }
++
++ return ret;
++}
++
+ static struct phy_driver bcm5411_driver = {
+ .phy_id = 0x00206070,
+ .phy_id_mask = 0xfffffff0,
+@@ -141,8 +176,36 @@ static struct phy_driver bcm5461_driver = {
+ .driver = { .owner = THIS_MODULE },
+ };
+
++static struct phy_driver bcm5464_driver = {
++ .phy_id = 0x002060b0,
++ .phy_id_mask = 0xfffffff0,
++ .name = "Broadcom BCM5464",
++ .features = PHY_GBIT_FEATURES,
++ .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
++ .config_init = bcm54xx_config_init,
++ .config_aneg = genphy_config_aneg,
++ .read_status = genphy_read_status,
++ .ack_interrupt = bcm54xx_ack_interrupt,
++ .config_intr = bcm54xx_config_intr,
++ .driver = { .owner = THIS_MODULE },
++};
++
++static struct phy_driver bcm5481_driver = {
++ .phy_id = 0x0143bca0,
++ .phy_id_mask = 0xfffffff0,
++ .name = "Broadcom BCM5481",
++ .features = PHY_GBIT_FEATURES,
++ .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
++ .config_init = bcm54xx_config_init,
++ .config_aneg = bcm5481_config_aneg,
++ .read_status = genphy_read_status,
++ .ack_interrupt = bcm54xx_ack_interrupt,
++ .config_intr = bcm54xx_config_intr,
++ .driver = { .owner = THIS_MODULE },
++};
++
+ static struct phy_driver bcm5482_driver = {
+- .phy_id = 0x0143bcb0,
++ .phy_id = 0x0143bcb0,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Broadcom BCM5482",
+ .features = PHY_GBIT_FEATURES,
+@@ -168,12 +231,22 @@ static int __init broadcom_init(void)
+ ret = phy_driver_register(&bcm5461_driver);
+ if (ret)
+ goto out_5461;
++ ret = phy_driver_register(&bcm5464_driver);
++ if (ret)
++ goto out_5464;
++ ret = phy_driver_register(&bcm5481_driver);
++ if (ret)
++ goto out_5481;
+ ret = phy_driver_register(&bcm5482_driver);
+ if (ret)
+ goto out_5482;
+ return ret;
+
+ out_5482:
++ phy_driver_unregister(&bcm5481_driver);
++out_5481:
++ phy_driver_unregister(&bcm5464_driver);
++out_5464:
+ phy_driver_unregister(&bcm5461_driver);
+ out_5461:
+ phy_driver_unregister(&bcm5421_driver);
+@@ -186,6 +259,8 @@ out_5411:
+ static void __exit broadcom_exit(void)
+ {
+ phy_driver_unregister(&bcm5482_driver);
++ phy_driver_unregister(&bcm5481_driver);
++ phy_driver_unregister(&bcm5464_driver);
+ phy_driver_unregister(&bcm5461_driver);
+ phy_driver_unregister(&bcm5421_driver);
+ phy_driver_unregister(&bcm5411_driver);
+diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
+index ca9b040..4e07956 100644
+--- a/drivers/net/phy/fixed.c
++++ b/drivers/net/phy/fixed.c
+@@ -213,7 +213,7 @@ static int __init fixed_mdio_bus_init(void)
+ goto err_pdev;
+ }
+
+- fmb->mii_bus.id = 0;
++ snprintf(fmb->mii_bus.id, MII_BUS_ID_SIZE, "0");
+ fmb->mii_bus.name = "Fixed MDIO Bus";
+ fmb->mii_bus.dev = &pdev->dev;
+ fmb->mii_bus.read = &fixed_mdio_read;
+diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
+index 963630c..94e0b7e 100644
+--- a/drivers/net/phy/mdio_bus.c
++++ b/drivers/net/phy/mdio_bus.c
+@@ -89,6 +89,9 @@ int mdiobus_register(struct mii_bus *bus)
+
+ phydev->bus = bus;
+
++ /* Run all of the fixups for this PHY */
++ phy_scan_fixups(phydev);
++
+ err = device_register(&phydev->dev);
+
+ if (err) {
+diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
+index 12fccb1..3c18bb5 100644
+--- a/drivers/net/phy/phy.c
++++ b/drivers/net/phy/phy.c
+@@ -406,8 +406,10 @@ int phy_mii_ioctl(struct phy_device *phydev,
+
+ if (mii_data->reg_num == MII_BMCR
+ && val & BMCR_RESET
+- && phydev->drv->config_init)
++ && phydev->drv->config_init) {
++ phy_scan_fixups(phydev);
+ phydev->drv->config_init(phydev);
++ }
+ break;
+
+ default:
+diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
+index f4c4fd8..ddf8d51 100644
+--- a/drivers/net/phy/phy_device.c
++++ b/drivers/net/phy/phy_device.c
+@@ -53,6 +53,96 @@ static void phy_device_release(struct device *dev)
+ phy_device_free(to_phy_device(dev));
+ }
+
++static LIST_HEAD(phy_fixup_list);
++static DEFINE_MUTEX(phy_fixup_lock);
++
++/*
++ * Creates a new phy_fixup and adds it to the list
++ * @bus_id: A string which matches phydev->dev.bus_id (or PHY_ANY_ID)
++ * @phy_uid: Used to match against phydev->phy_id (the UID of the PHY)
++ * It can also be PHY_ANY_UID
++ * @phy_uid_mask: Applied to phydev->phy_id and fixup->phy_uid before
++ * comparison
++ * @run: The actual code to be run when a matching PHY is found
++ */
++int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask,
++ int (*run)(struct phy_device *))
++{
++ struct phy_fixup *fixup;
++
++ fixup = kzalloc(sizeof(struct phy_fixup), GFP_KERNEL);
++ if (!fixup)
++ return -ENOMEM;
++
++ strncpy(fixup->bus_id, bus_id, BUS_ID_SIZE);
++ fixup->phy_uid = phy_uid;
++ fixup->phy_uid_mask = phy_uid_mask;
++ fixup->run = run;
++
++ mutex_lock(&phy_fixup_lock);
++ list_add_tail(&fixup->list, &phy_fixup_list);
++ mutex_unlock(&phy_fixup_lock);
++
++ return 0;
++}
++EXPORT_SYMBOL(phy_register_fixup);
++
++/* Registers a fixup to be run on any PHY with the UID in phy_uid */
++int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask,
++ int (*run)(struct phy_device *))
++{
++ return phy_register_fixup(PHY_ANY_ID, phy_uid, phy_uid_mask, run);
++}
++EXPORT_SYMBOL(phy_register_fixup_for_uid);
++
++/* Registers a fixup to be run on the PHY with id string bus_id */
++int phy_register_fixup_for_id(const char *bus_id,
++ int (*run)(struct phy_device *))
++{
++ return phy_register_fixup(bus_id, PHY_ANY_UID, 0xffffffff, run);
++}
++EXPORT_SYMBOL(phy_register_fixup_for_id);
++
++/*
++ * Returns 1 if fixup matches phydev in bus_id and phy_uid.
++ * Fixups can be set to match any in one or more fields.
++ */
++static int phy_needs_fixup(struct phy_device *phydev, struct phy_fixup *fixup)
++{
++ if (strcmp(fixup->bus_id, phydev->dev.bus_id) != 0)
++ if (strcmp(fixup->bus_id, PHY_ANY_ID) != 0)
++ return 0;
++
++ if ((fixup->phy_uid & fixup->phy_uid_mask) !=
++ (phydev->phy_id & fixup->phy_uid_mask))
++ if (fixup->phy_uid != PHY_ANY_UID)
++ return 0;
++
++ return 1;
++}
++
++/* Runs any matching fixups for this phydev */
++int phy_scan_fixups(struct phy_device *phydev)
++{
++ struct phy_fixup *fixup;
++
++ mutex_lock(&phy_fixup_lock);
++ list_for_each_entry(fixup, &phy_fixup_list, list) {
++ if (phy_needs_fixup(phydev, fixup)) {
++ int err;
++
++ err = fixup->run(phydev);
++
++ if (err < 0)
++ return err;
++ }
++ }
++ mutex_unlock(&phy_fixup_lock);
++
++ return 0;
++}
++EXPORT_SYMBOL(phy_scan_fixups);
++
+ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id)
+ {
+ struct phy_device *dev;
+@@ -86,35 +176,55 @@ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id)
+ EXPORT_SYMBOL(phy_device_create);
+
+ /**
+- * get_phy_device - reads the specified PHY device and returns its @phy_device struct
++ * get_phy_id - reads the specified addr for its ID.
+ * @bus: the target MII bus
+ * @addr: PHY address on the MII bus
++ * @phy_id: where to store the ID retrieved.
+ *
+ * Description: Reads the ID registers of the PHY at @addr on the
+- * @bus, then allocates and returns the phy_device to represent it.
++ * @bus, stores it in @phy_id and returns zero on success.
+ */
+-struct phy_device * get_phy_device(struct mii_bus *bus, int addr)
++int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id)
+ {
+ int phy_reg;
+- u32 phy_id;
+- struct phy_device *dev = NULL;
+
+ /* Grab the bits from PHYIR1, and put them
+ * in the upper half */
+ phy_reg = bus->read(bus, addr, MII_PHYSID1);
+
+ if (phy_reg < 0)
+- return ERR_PTR(phy_reg);
++ return -EIO;
+
+- phy_id = (phy_reg & 0xffff) << 16;
++ *phy_id = (phy_reg & 0xffff) << 16;
+
+ /* Grab the bits from PHYIR2, and put them in the lower half */
+ phy_reg = bus->read(bus, addr, MII_PHYSID2);
+
+ if (phy_reg < 0)
+- return ERR_PTR(phy_reg);
++ return -EIO;
++
++ *phy_id |= (phy_reg & 0xffff);
++
++ return 0;
++}
++
++/**
++ * get_phy_device - reads the specified PHY device and returns its @phy_device struct
++ * @bus: the target MII bus
++ * @addr: PHY address on the MII bus
++ *
++ * Description: Reads the ID registers of the PHY at @addr on the
++ * @bus, then allocates and returns the phy_device to represent it.
++ */
++struct phy_device * get_phy_device(struct mii_bus *bus, int addr)
++{
++ struct phy_device *dev = NULL;
++ u32 phy_id;
++ int r;
+
+- phy_id |= (phy_reg & 0xffff);
++ r = get_phy_id(bus, addr, &phy_id);
++ if (r)
++ return ERR_PTR(r);
+
+ /* If the phy_id is all Fs, there is no device there */
+ if (0xffffffff == phy_id)
+@@ -159,13 +269,13 @@ void phy_prepare_link(struct phy_device *phydev,
+ * choose to call only the subset of functions which provide
+ * the desired functionality.
+ */
+-struct phy_device * phy_connect(struct net_device *dev, const char *phy_id,
++struct phy_device * phy_connect(struct net_device *dev, const char *bus_id,
+ void (*handler)(struct net_device *), u32 flags,
+ phy_interface_t interface)
+ {
+ struct phy_device *phydev;
+
+- phydev = phy_attach(dev, phy_id, flags, interface);
++ phydev = phy_attach(dev, bus_id, flags, interface);
+
+ if (IS_ERR(phydev))
+ return phydev;
+@@ -206,7 +316,7 @@ static int phy_compare_id(struct device *dev, void *data)
+ /**
+ * phy_attach - attach a network device to a particular PHY device
+ * @dev: network device to attach
+- * @phy_id: PHY device to attach
++ * @bus_id: PHY device to attach
+ * @flags: PHY device's dev_flags
+ * @interface: PHY device's interface
+ *
+@@ -218,7 +328,7 @@ static int phy_compare_id(struct device *dev, void *data)
+ * change. The phy_device is returned to the attaching driver.
+ */
+ struct phy_device *phy_attach(struct net_device *dev,
+- const char *phy_id, u32 flags, phy_interface_t interface)
++ const char *bus_id, u32 flags, phy_interface_t interface)
+ {
+ struct bus_type *bus = &mdio_bus_type;
+ struct phy_device *phydev;
+@@ -226,12 +336,12 @@ struct phy_device *phy_attach(struct net_device *dev,
+
+ /* Search the list of PHY devices on the mdio bus for the
+ * PHY with the requested name */
+- d = bus_find_device(bus, NULL, (void *)phy_id, phy_compare_id);
++ d = bus_find_device(bus, NULL, (void *)bus_id, phy_compare_id);
+
+ if (d) {
+ phydev = to_phy_device(d);
+ } else {
+- printk(KERN_ERR "%s not found\n", phy_id);
++ printk(KERN_ERR "%s not found\n", bus_id);
+ return ERR_PTR(-ENODEV);
+ }
+
+@@ -251,7 +361,7 @@ struct phy_device *phy_attach(struct net_device *dev,
+
+ if (phydev->attached_dev) {
+ printk(KERN_ERR "%s: %s already attached\n",
+- dev->name, phy_id);
++ dev->name, bus_id);
+ return ERR_PTR(-EBUSY);
+ }
+
+@@ -267,6 +377,11 @@ struct phy_device *phy_attach(struct net_device *dev,
+ if (phydev->drv->config_init) {
+ int err;
+
++ err = phy_scan_fixups(phydev);
++
++ if (err < 0)
++ return ERR_PTR(err);
++
+ err = phydev->drv->config_init(phydev);
+
+ if (err < 0)
+@@ -375,6 +490,7 @@ EXPORT_SYMBOL(genphy_config_advert);
+ */
+ int genphy_setup_forced(struct phy_device *phydev)
+ {
++ int err;
+ int ctl = 0;
+
+ phydev->pause = phydev->asym_pause = 0;
+@@ -387,17 +503,26 @@ int genphy_setup_forced(struct phy_device *phydev)
+ if (DUPLEX_FULL == phydev->duplex)
+ ctl |= BMCR_FULLDPLX;
+
+- ctl = phy_write(phydev, MII_BMCR, ctl);
++ err = phy_write(phydev, MII_BMCR, ctl);
+
+- if (ctl < 0)
+- return ctl;
++ if (err < 0)
++ return err;
++
++ /*
++ * Run the fixups on this PHY, just in case the
++ * board code needs to change something after a reset
++ */
++ err = phy_scan_fixups(phydev);
++
++ if (err < 0)
++ return err;
+
+ /* We just reset the device, so we'd better configure any
+ * settings the PHY requires to operate */
+ if (phydev->drv->config_init)
+- ctl = phydev->drv->config_init(phydev);
++ err = phydev->drv->config_init(phydev);
+
+- return ctl;
++ return err;
+ }
+
+
+diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
+index 4dc5b4b..d3207c0 100644
+--- a/drivers/net/ppp_generic.c
++++ b/drivers/net/ppp_generic.c
+@@ -123,7 +123,6 @@ struct ppp {
+ u32 minseq; /* MP: min of most recent seqnos */
+ struct sk_buff_head mrq; /* MP: receive reconstruction queue */
+ #endif /* CONFIG_PPP_MULTILINK */
+- struct net_device_stats stats; /* statistics */
+ #ifdef CONFIG_PPP_FILTER
+ struct sock_filter *pass_filter; /* filter for packets to pass */
+ struct sock_filter *active_filter;/* filter for pkts to reset idle */
+@@ -914,18 +913,10 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
+
+ outf:
+ kfree_skb(skb);
+- ++ppp->stats.tx_dropped;
++ ++ppp->dev->stats.tx_dropped;
+ return 0;
+ }
+
+-static struct net_device_stats *
+-ppp_net_stats(struct net_device *dev)
+-{
+- struct ppp *ppp = (struct ppp *) dev->priv;
+-
+- return &ppp->stats;
+-}
+-
+ static int
+ ppp_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ {
+@@ -1095,8 +1086,8 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
+ #endif /* CONFIG_PPP_FILTER */
+ }
+
+- ++ppp->stats.tx_packets;
+- ppp->stats.tx_bytes += skb->len - 2;
++ ++ppp->dev->stats.tx_packets;
++ ppp->dev->stats.tx_bytes += skb->len - 2;
+
+ switch (proto) {
+ case PPP_IP:
+@@ -1171,7 +1162,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
+ drop:
+ if (skb)
+ kfree_skb(skb);
+- ++ppp->stats.tx_errors;
++ ++ppp->dev->stats.tx_errors;
+ }
+
+ /*
+@@ -1409,7 +1400,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
+ spin_unlock_bh(&pch->downl);
+ if (ppp->debug & 1)
+ printk(KERN_ERR "PPP: no memory (fragment)\n");
+- ++ppp->stats.tx_errors;
++ ++ppp->dev->stats.tx_errors;
+ ++ppp->nxseq;
+ return 1; /* abandon the frame */
+ }
+@@ -1538,7 +1529,7 @@ ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
+
+ if (skb->len > 0)
+ /* note: a 0-length skb is used as an error indication */
+- ++ppp->stats.rx_length_errors;
++ ++ppp->dev->stats.rx_length_errors;
+
+ kfree_skb(skb);
+ ppp_receive_error(ppp);
+@@ -1547,7 +1538,7 @@ ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
+ static void
+ ppp_receive_error(struct ppp *ppp)
+ {
+- ++ppp->stats.rx_errors;
++ ++ppp->dev->stats.rx_errors;
+ if (ppp->vj)
+ slhc_toss(ppp->vj);
+ }
+@@ -1627,8 +1618,8 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
+ break;
+ }
+
+- ++ppp->stats.rx_packets;
+- ppp->stats.rx_bytes += skb->len - 2;
++ ++ppp->dev->stats.rx_packets;
++ ppp->dev->stats.rx_bytes += skb->len - 2;
+
+ npi = proto_to_npindex(proto);
+ if (npi < 0) {
+@@ -1806,7 +1797,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
+ */
+ if (seq_before(seq, ppp->nextseq)) {
+ kfree_skb(skb);
+- ++ppp->stats.rx_dropped;
++ ++ppp->dev->stats.rx_dropped;
+ ppp_receive_error(ppp);
+ return;
+ }
+@@ -1928,7 +1919,7 @@ ppp_mp_reconstruct(struct ppp *ppp)
+ /* Got a complete packet yet? */
+ if (lost == 0 && (p->BEbits & E) && (head->BEbits & B)) {
+ if (len > ppp->mrru + 2) {
+- ++ppp->stats.rx_length_errors;
++ ++ppp->dev->stats.rx_length_errors;
+ printk(KERN_DEBUG "PPP: reconstructed packet"
+ " is too long (%d)\n", len);
+ } else if (p == head) {
+@@ -1937,7 +1928,7 @@ ppp_mp_reconstruct(struct ppp *ppp)
+ skb = skb_get(p);
+ break;
+ } else if ((skb = dev_alloc_skb(len)) == NULL) {
+- ++ppp->stats.rx_missed_errors;
++ ++ppp->dev->stats.rx_missed_errors;
+ printk(KERN_DEBUG "PPP: no memory for "
+ "reconstructed packet");
+ } else {
+@@ -1966,7 +1957,7 @@ ppp_mp_reconstruct(struct ppp *ppp)
+ if (ppp->debug & 1)
+ printk(KERN_DEBUG " missed pkts %u..%u\n",
+ ppp->nextseq, head->sequence-1);
+- ++ppp->stats.rx_dropped;
++ ++ppp->dev->stats.rx_dropped;
+ ppp_receive_error(ppp);
+ }
+
+@@ -2377,12 +2368,12 @@ ppp_get_stats(struct ppp *ppp, struct ppp_stats *st)
+ struct slcompress *vj = ppp->vj;
+
+ memset(st, 0, sizeof(*st));
+- st->p.ppp_ipackets = ppp->stats.rx_packets;
+- st->p.ppp_ierrors = ppp->stats.rx_errors;
+- st->p.ppp_ibytes = ppp->stats.rx_bytes;
+- st->p.ppp_opackets = ppp->stats.tx_packets;
+- st->p.ppp_oerrors = ppp->stats.tx_errors;
+- st->p.ppp_obytes = ppp->stats.tx_bytes;
++ st->p.ppp_ipackets = ppp->dev->stats.rx_packets;
++ st->p.ppp_ierrors = ppp->dev->stats.rx_errors;
++ st->p.ppp_ibytes = ppp->dev->stats.rx_bytes;
++ st->p.ppp_opackets = ppp->dev->stats.tx_packets;
++ st->p.ppp_oerrors = ppp->dev->stats.tx_errors;
++ st->p.ppp_obytes = ppp->dev->stats.tx_bytes;
+ if (!vj)
+ return;
+ st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed;
+@@ -2436,7 +2427,6 @@ ppp_create_interface(int unit, int *retp)
+ dev->priv = ppp;
+
+ dev->hard_start_xmit = ppp_start_xmit;
+- dev->get_stats = ppp_net_stats;
+ dev->do_ioctl = ppp_net_ioctl;
+
+ ret = -EEXIST;
+diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
+index ac0ac98..4fad4dd 100644
+--- a/drivers/net/pppoe.c
++++ b/drivers/net/pppoe.c
+@@ -301,7 +301,7 @@ static int pppoe_device_event(struct notifier_block *this,
+ {
+ struct net_device *dev = (struct net_device *) ptr;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ /* Only look at sockets that are using this specific device. */
+@@ -392,7 +392,7 @@ static int pppoe_rcv(struct sk_buff *skb,
+ if (!(skb = skb_share_check(skb, GFP_ATOMIC)))
+ goto out;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ goto drop;
+
+ if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
+@@ -424,7 +424,7 @@ static int pppoe_disc_rcv(struct sk_buff *skb,
+ struct pppoe_hdr *ph;
+ struct pppox_sock *po;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ goto abort;
+
+ if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
+diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c
+index 7eb6e7e..e365efb 100644
+--- a/drivers/net/ps3_gelic_net.c
++++ b/drivers/net/ps3_gelic_net.c
+@@ -1266,6 +1266,85 @@ int gelic_net_set_rx_csum(struct net_device *netdev, u32 data)
+ return 0;
+ }
+
++static void gelic_net_get_wol(struct net_device *netdev,
++ struct ethtool_wolinfo *wol)
++{
++ if (0 <= ps3_compare_firmware_version(2, 2, 0))
++ wol->supported = WAKE_MAGIC;
++ else
++ wol->supported = 0;
++
++ wol->wolopts = ps3_sys_manager_get_wol() ? wol->supported : 0;
++ memset(&wol->sopass, 0, sizeof(wol->sopass));
++}
++static int gelic_net_set_wol(struct net_device *netdev,
++ struct ethtool_wolinfo *wol)
++{
++ int status;
++ struct gelic_card *card;
++ u64 v1, v2;
++
++ if (ps3_compare_firmware_version(2, 2, 0) < 0 ||
++ !capable(CAP_NET_ADMIN))
++ return -EPERM;
++
++ if (wol->wolopts & ~WAKE_MAGIC)
++ return -EINVAL;
++
++ card = netdev_card(netdev);
++ if (wol->wolopts & WAKE_MAGIC) {
++ status = lv1_net_control(bus_id(card), dev_id(card),
++ GELIC_LV1_SET_WOL,
++ GELIC_LV1_WOL_MAGIC_PACKET,
++ 0, GELIC_LV1_WOL_MP_ENABLE,
++ &v1, &v2);
++ if (status) {
++ pr_info("%s: enabling WOL failed %d\n", __func__,
++ status);
++ status = -EIO;
++ goto done;
++ }
++ status = lv1_net_control(bus_id(card), dev_id(card),
++ GELIC_LV1_SET_WOL,
++ GELIC_LV1_WOL_ADD_MATCH_ADDR,
++ 0, GELIC_LV1_WOL_MATCH_ALL,
++ &v1, &v2);
++ if (!status)
++ ps3_sys_manager_set_wol(1);
++ else {
++ pr_info("%s: enabling WOL filter failed %d\n",
++ __func__, status);
++ status = -EIO;
++ }
++ } else {
++ status = lv1_net_control(bus_id(card), dev_id(card),
++ GELIC_LV1_SET_WOL,
++ GELIC_LV1_WOL_MAGIC_PACKET,
++ 0, GELIC_LV1_WOL_MP_DISABLE,
++ &v1, &v2);
++ if (status) {
++ pr_info("%s: disabling WOL failed %d\n", __func__,
++ status);
++ status = -EIO;
++ goto done;
++ }
++ status = lv1_net_control(bus_id(card), dev_id(card),
++ GELIC_LV1_SET_WOL,
++ GELIC_LV1_WOL_DELETE_MATCH_ADDR,
++ 0, GELIC_LV1_WOL_MATCH_ALL,
++ &v1, &v2);
++ if (!status)
++ ps3_sys_manager_set_wol(0);
++ else {
++ pr_info("%s: removing WOL filter failed %d\n",
++ __func__, status);
++ status = -EIO;
++ }
++ }
++done:
++ return status;
++}
++
+ static struct ethtool_ops gelic_ether_ethtool_ops = {
+ .get_drvinfo = gelic_net_get_drvinfo,
+ .get_settings = gelic_ether_get_settings,
+@@ -1274,6 +1353,8 @@ static struct ethtool_ops gelic_ether_ethtool_ops = {
+ .set_tx_csum = ethtool_op_set_tx_csum,
+ .get_rx_csum = gelic_net_get_rx_csum,
+ .set_rx_csum = gelic_net_set_rx_csum,
++ .get_wol = gelic_net_get_wol,
++ .set_wol = gelic_net_set_wol,
+ };
+
+ /**
+diff --git a/drivers/net/ps3_gelic_net.h b/drivers/net/ps3_gelic_net.h
+index 1d39d06..520f143 100644
+--- a/drivers/net/ps3_gelic_net.h
++++ b/drivers/net/ps3_gelic_net.h
+@@ -182,12 +182,32 @@ enum gelic_lv1_net_control_code {
+ GELIC_LV1_GET_ETH_PORT_STATUS = 2,
+ GELIC_LV1_SET_NEGOTIATION_MODE = 3,
+ GELIC_LV1_GET_VLAN_ID = 4,
++ GELIC_LV1_SET_WOL = 5,
+ GELIC_LV1_GET_CHANNEL = 6,
+ GELIC_LV1_POST_WLAN_CMD = 9,
+ GELIC_LV1_GET_WLAN_CMD_RESULT = 10,
+ GELIC_LV1_GET_WLAN_EVENT = 11
+ };
+
++/* for GELIC_LV1_SET_WOL */
++enum gelic_lv1_wol_command {
++ GELIC_LV1_WOL_MAGIC_PACKET = 1,
++ GELIC_LV1_WOL_ADD_MATCH_ADDR = 6,
++ GELIC_LV1_WOL_DELETE_MATCH_ADDR = 7,
++};
++
++/* for GELIC_LV1_WOL_MAGIC_PACKET */
++enum gelic_lv1_wol_mp_arg {
++ GELIC_LV1_WOL_MP_DISABLE = 0,
++ GELIC_LV1_WOL_MP_ENABLE = 1,
++};
++
++/* for GELIC_LV1_WOL_{ADD,DELETE}_MATCH_ADDR */
++enum gelic_lv1_wol_match_arg {
++ GELIC_LV1_WOL_MATCH_INDIVIDUAL = 0,
++ GELIC_LV1_WOL_MATCH_ALL = 1,
++};
++
+ /* status returened from GET_ETH_PORT_STATUS */
+ enum gelic_lv1_ether_port_status {
+ GELIC_LV1_ETHER_LINK_UP = 0x0000000000000001L,
+diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c
+index c16de51..0d32123 100644
+--- a/drivers/net/ps3_gelic_wireless.c
++++ b/drivers/net/ps3_gelic_wireless.c
+@@ -87,7 +87,7 @@ static inline int wpa2_capable(void)
+
+ static inline int precise_ie(void)
+ {
+- return 0; /* FIXME */
++ return (0 <= ps3_compare_firmware_version(2, 2, 0));
+ }
+ /*
+ * post_eurus_cmd helpers
+diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
+index a6aeb9d..b7f7b22 100644
+--- a/drivers/net/qla3xxx.c
++++ b/drivers/net/qla3xxx.c
+@@ -2472,8 +2472,7 @@ static int ql_send_map(struct ql3_adapter *qdev,
+
+ if (seg_cnt == 1) {
+ /* Terminate the last segment. */
+- oal_entry->len =
+- cpu_to_le32(le32_to_cpu(oal_entry->len) | OAL_LAST_ENTRY);
++ oal_entry->len |= cpu_to_le32(OAL_LAST_ENTRY);
+ } else {
+ oal = tx_cb->oal;
+ for (completed_segs=0; completed_segs<frag_cnt; completed_segs++,seg++) {
+@@ -2530,8 +2529,7 @@ static int ql_send_map(struct ql3_adapter *qdev,
+ frag->size);
+ }
+ /* Terminate the last segment. */
+- oal_entry->len =
+- cpu_to_le32(le32_to_cpu(oal_entry->len) | OAL_LAST_ENTRY);
++ oal_entry->len |= cpu_to_le32(OAL_LAST_ENTRY);
+ }
+
+ return NETDEV_TX_OK;
+diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
+index c082cf0..157fd93 100644
+--- a/drivers/net/s2io.c
++++ b/drivers/net/s2io.c
+@@ -50,6 +50,8 @@
+ * Possible values '1' for enable , '0' for disable.
+ * Default is '2' - which means disable in promisc mode
+ * and enable in non-promiscuous mode.
++ * multiq: This parameter used to enable/disable MULTIQUEUE support.
++ * Possible values '1' for enable and '0' for disable. Default is '0'
+ ************************************************************************/
+
+ #include <linux/module.h>
+@@ -84,7 +86,7 @@
+ #include "s2io.h"
+ #include "s2io-regs.h"
+
+-#define DRV_VERSION "2.0.26.20"
++#define DRV_VERSION "2.0.26.22"
+
+ /* S2io Driver name & version. */
+ static char s2io_driver_name[] = "Neterion";
+@@ -115,20 +117,6 @@ static inline int RXD_IS_UP2DT(struct RxD_t *rxdp)
+
+ #define LINK_IS_UP(val64) (!(val64 & (ADAPTER_STATUS_RMAC_REMOTE_FAULT | \
+ ADAPTER_STATUS_RMAC_LOCAL_FAULT)))
+-#define TASKLET_IN_USE test_and_set_bit(0, (&sp->tasklet_status))
+-#define PANIC 1
+-#define LOW 2
+-static inline int rx_buffer_level(struct s2io_nic * sp, int rxb_size, int ring)
+-{
+- struct mac_info *mac_control;
+-
+- mac_control = &sp->mac_control;
+- if (rxb_size <= rxd_count[sp->rxd_mode])
+- return PANIC;
+- else if ((mac_control->rings[ring].pkt_cnt - rxb_size) > 16)
+- return LOW;
+- return 0;
+-}
+
+ static inline int is_s2io_card_up(const struct s2io_nic * sp)
+ {
+@@ -386,6 +374,26 @@ static void s2io_vlan_rx_register(struct net_device *dev,
+ /* A flag indicating whether 'RX_PA_CFG_STRIP_VLAN_TAG' bit is set or not */
+ static int vlan_strip_flag;
+
++/* Unregister the vlan */
++static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid)
++{
++ int i;
++ struct s2io_nic *nic = dev->priv;
++ unsigned long flags[MAX_TX_FIFOS];
++ struct mac_info *mac_control = &nic->mac_control;
++ struct config_param *config = &nic->config;
++
++ for (i = 0; i < config->tx_fifo_num; i++)
++ spin_lock_irqsave(&mac_control->fifos[i].tx_lock, flags[i]);
++
++ if (nic->vlgrp)
++ vlan_group_set_device(nic->vlgrp, vid, NULL);
++
++ for (i = config->tx_fifo_num - 1; i >= 0; i--)
++ spin_unlock_irqrestore(&mac_control->fifos[i].tx_lock,
++ flags[i]);
++}
++
+ /*
+ * Constants to be programmed into the Xena's registers, to configure
+ * the XAUI.
+@@ -456,10 +464,9 @@ MODULE_VERSION(DRV_VERSION);
+
+
+ /* Module Loadable parameters. */
+-S2IO_PARM_INT(tx_fifo_num, 1);
++S2IO_PARM_INT(tx_fifo_num, FIFO_DEFAULT_NUM);
+ S2IO_PARM_INT(rx_ring_num, 1);
+-
+-
++S2IO_PARM_INT(multiq, 0);
+ S2IO_PARM_INT(rx_ring_mode, 1);
+ S2IO_PARM_INT(use_continuous_tx_intrs, 1);
+ S2IO_PARM_INT(rmac_pause_time, 0x100);
+@@ -469,6 +476,8 @@ S2IO_PARM_INT(shared_splits, 0);
+ S2IO_PARM_INT(tmac_util_period, 5);
+ S2IO_PARM_INT(rmac_util_period, 5);
+ S2IO_PARM_INT(l3l4hdr_size, 128);
++/* 0 is no steering, 1 is Priority steering, 2 is Default steering */
++S2IO_PARM_INT(tx_steering_type, TX_DEFAULT_STEERING);
+ /* Frequency of Rx desc syncs expressed as power of 2 */
+ S2IO_PARM_INT(rxsync_frequency, 3);
+ /* Interrupt type. Values can be 0(INTA), 2(MSI_X) */
+@@ -533,6 +542,101 @@ static struct pci_driver s2io_driver = {
+ /* A simplifier macro used both by init and free shared_mem Fns(). */
+ #define TXD_MEM_PAGE_CNT(len, per_each) ((len+per_each - 1) / per_each)
+
++/* netqueue manipulation helper functions */
++static inline void s2io_stop_all_tx_queue(struct s2io_nic *sp)
++{
++ int i;
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ if (sp->config.multiq) {
++ for (i = 0; i < sp->config.tx_fifo_num; i++)
++ netif_stop_subqueue(sp->dev, i);
++ } else
++#endif
++ {
++ for (i = 0; i < sp->config.tx_fifo_num; i++)
++ sp->mac_control.fifos[i].queue_state = FIFO_QUEUE_STOP;
++ netif_stop_queue(sp->dev);
++ }
++}
++
++static inline void s2io_stop_tx_queue(struct s2io_nic *sp, int fifo_no)
++{
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ if (sp->config.multiq)
++ netif_stop_subqueue(sp->dev, fifo_no);
++ else
++#endif
++ {
++ sp->mac_control.fifos[fifo_no].queue_state =
++ FIFO_QUEUE_STOP;
++ netif_stop_queue(sp->dev);
++ }
++}
++
++static inline void s2io_start_all_tx_queue(struct s2io_nic *sp)
++{
++ int i;
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ if (sp->config.multiq) {
++ for (i = 0; i < sp->config.tx_fifo_num; i++)
++ netif_start_subqueue(sp->dev, i);
++ } else
++#endif
++ {
++ for (i = 0; i < sp->config.tx_fifo_num; i++)
++ sp->mac_control.fifos[i].queue_state = FIFO_QUEUE_START;
++ netif_start_queue(sp->dev);
++ }
++}
++
++static inline void s2io_start_tx_queue(struct s2io_nic *sp, int fifo_no)
++{
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ if (sp->config.multiq)
++ netif_start_subqueue(sp->dev, fifo_no);
++ else
++#endif
++ {
++ sp->mac_control.fifos[fifo_no].queue_state =
++ FIFO_QUEUE_START;
++ netif_start_queue(sp->dev);
++ }
++}
++
++static inline void s2io_wake_all_tx_queue(struct s2io_nic *sp)
++{
++ int i;
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ if (sp->config.multiq) {
++ for (i = 0; i < sp->config.tx_fifo_num; i++)
++ netif_wake_subqueue(sp->dev, i);
++ } else
++#endif
++ {
++ for (i = 0; i < sp->config.tx_fifo_num; i++)
++ sp->mac_control.fifos[i].queue_state = FIFO_QUEUE_START;
++ netif_wake_queue(sp->dev);
++ }
++}
++
++static inline void s2io_wake_tx_queue(
++ struct fifo_info *fifo, int cnt, u8 multiq)
++{
++
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ if (multiq) {
++ if (cnt && __netif_subqueue_stopped(fifo->dev, fifo->fifo_no))
++ netif_wake_subqueue(fifo->dev, fifo->fifo_no);
++ } else
++#endif
++ if (cnt && (fifo->queue_state == FIFO_QUEUE_STOP)) {
++ if (netif_queue_stopped(fifo->dev)) {
++ fifo->queue_state = FIFO_QUEUE_START;
++ netif_wake_queue(fifo->dev);
++ }
++ }
++}
++
+ /**
+ * init_shared_mem - Allocation and Initialization of Memory
+ * @nic: Device private variable.
+@@ -614,6 +718,7 @@ static int init_shared_mem(struct s2io_nic *nic)
+ mac_control->fifos[i].fifo_no = i;
+ mac_control->fifos[i].nic = nic;
+ mac_control->fifos[i].max_txds = MAX_SKB_FRAGS + 2;
++ mac_control->fifos[i].dev = dev;
+
+ for (j = 0; j < page_num; j++) {
+ int k = 0;
+@@ -2339,7 +2444,7 @@ static void free_tx_buffers(struct s2io_nic *nic)
+ for (i = 0; i < config->tx_fifo_num; i++) {
+ unsigned long flags;
+ spin_lock_irqsave(&mac_control->fifos[i].tx_lock, flags);
+- for (j = 0; j < config->tx_cfg[i].fifo_len - 1; j++) {
++ for (j = 0; j < config->tx_cfg[i].fifo_len; j++) {
+ txdp = (struct TxD *) \
+ mac_control->fifos[i].list_info[j].list_virt_addr;
+ skb = s2io_txdl_getskb(&mac_control->fifos[i], txdp, j);
+@@ -2425,7 +2530,6 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
+ struct config_param *config;
+ u64 tmp;
+ struct buffAdd *ba;
+- unsigned long flags;
+ struct RxD_t *first_rxdp = NULL;
+ u64 Buffer0_ptr = 0, Buffer1_ptr = 0;
+ struct RxD1 *rxdp1;
+@@ -2473,15 +2577,7 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
+ DBG_PRINT(INTR_DBG, "%s: Next block at: %p\n",
+ dev->name, rxdp);
+ }
+- if(!napi) {
+- spin_lock_irqsave(&nic->put_lock, flags);
+- mac_control->rings[ring_no].put_pos =
+- (block_no * (rxd_count[nic->rxd_mode] + 1)) + off;
+- spin_unlock_irqrestore(&nic->put_lock, flags);
+- } else {
+- mac_control->rings[ring_no].put_pos =
+- (block_no * (rxd_count[nic->rxd_mode] + 1)) + off;
+- }
++
+ if ((rxdp->Control_1 & RXD_OWN_XENA) &&
+ ((nic->rxd_mode == RXD_MODE_3B) &&
+ (rxdp->Control_2 & s2BIT(0)))) {
+@@ -2859,7 +2955,7 @@ static void rx_intr_handler(struct ring_info *ring_data)
+ {
+ struct s2io_nic *nic = ring_data->nic;
+ struct net_device *dev = (struct net_device *) nic->dev;
+- int get_block, put_block, put_offset;
++ int get_block, put_block;
+ struct rx_curr_get_info get_info, put_info;
+ struct RxD_t *rxdp;
+ struct sk_buff *skb;
+@@ -2868,19 +2964,11 @@ static void rx_intr_handler(struct ring_info *ring_data)
+ struct RxD1* rxdp1;
+ struct RxD3* rxdp3;
+
+- spin_lock(&nic->rx_lock);
+-
+ get_info = ring_data->rx_curr_get_info;
+ get_block = get_info.block_index;
+ memcpy(&put_info, &ring_data->rx_curr_put_info, sizeof(put_info));
+ put_block = put_info.block_index;
+ rxdp = ring_data->rx_blocks[get_block].rxds[get_info.offset].virt_addr;
+- if (!napi) {
+- spin_lock(&nic->put_lock);
+- put_offset = ring_data->put_pos;
+- spin_unlock(&nic->put_lock);
+- } else
+- put_offset = ring_data->put_pos;
+
+ while (RXD_IS_UP2DT(rxdp)) {
+ /*
+@@ -2897,7 +2985,6 @@ static void rx_intr_handler(struct ring_info *ring_data)
+ DBG_PRINT(ERR_DBG, "%s: The skb is ",
+ dev->name);
+ DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
+- spin_unlock(&nic->rx_lock);
+ return;
+ }
+ if (nic->rxd_mode == RXD_MODE_1) {
+@@ -2948,13 +3035,11 @@ static void rx_intr_handler(struct ring_info *ring_data)
+ struct lro *lro = &nic->lro0_n[i];
+ if (lro->in_use) {
+ update_L3L4_header(nic, lro);
+- queue_rx_frame(lro->parent);
++ queue_rx_frame(lro->parent, lro->vlan_tag);
+ clear_lro_session(lro);
+ }
+ }
+ }
+-
+- spin_unlock(&nic->rx_lock);
+ }
+
+ /**
+@@ -2972,10 +3057,10 @@ static void rx_intr_handler(struct ring_info *ring_data)
+ static void tx_intr_handler(struct fifo_info *fifo_data)
+ {
+ struct s2io_nic *nic = fifo_data->nic;
+- struct net_device *dev = (struct net_device *) nic->dev;
+ struct tx_curr_get_info get_info, put_info;
+- struct sk_buff *skb;
++ struct sk_buff *skb = NULL;
+ struct TxD *txdlp;
++ int pkt_cnt = 0;
+ unsigned long flags = 0;
+ u8 err_mask;
+
+@@ -3036,6 +3121,7 @@ static void tx_intr_handler(struct fifo_info *fifo_data)
+ DBG_PRINT(ERR_DBG, "in Tx Free Intr\n");
+ return;
+ }
++ pkt_cnt++;
+
+ /* Updating the statistics block */
+ nic->stats.tx_bytes += skb->len;
+@@ -3051,8 +3137,7 @@ static void tx_intr_handler(struct fifo_info *fifo_data)
+ get_info.offset;
+ }
+
+- if (netif_queue_stopped(dev))
+- netif_wake_queue(dev);
++ s2io_wake_tx_queue(fifo_data, pkt_cnt, nic->config.multiq);
+
+ spin_unlock_irqrestore(&fifo_data->tx_lock, flags);
+ }
+@@ -3933,8 +4018,7 @@ static int s2io_open(struct net_device *dev)
+ err = -ENODEV;
+ goto hw_init_failed;
+ }
+-
+- netif_start_queue(dev);
++ s2io_start_all_tx_queue(sp);
+ return 0;
+
+ hw_init_failed:
+@@ -3979,8 +4063,7 @@ static int s2io_close(struct net_device *dev)
+ if (!is_s2io_card_up(sp))
+ return 0;
+
+- netif_stop_queue(dev);
+-
++ s2io_stop_all_tx_queue(sp);
+ /* delete all populated mac entries */
+ for (offset = 1; offset < config->max_mc_addr; offset++) {
+ tmp64 = do_s2io_read_unicast_mc(sp, offset);
+@@ -3988,7 +4071,6 @@ static int s2io_close(struct net_device *dev)
+ do_s2io_delete_unicast_mc(sp, tmp64);
+ }
+
+- /* Reset card, kill tasklet and free Tx and Rx buffers. */
+ s2io_card_down(sp);
+
+ return 0;
+@@ -4016,11 +4098,12 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
+ struct TxFIFO_element __iomem *tx_fifo;
+ unsigned long flags = 0;
+ u16 vlan_tag = 0;
+- int vlan_priority = 0;
+ struct fifo_info *fifo = NULL;
+ struct mac_info *mac_control;
+ struct config_param *config;
++ int do_spin_lock = 1;
+ int offload_type;
++ int enable_per_list_interrupt = 0;
+ struct swStat *stats = &sp->mac_control.stats_info->sw_stat;
+
+ mac_control = &sp->mac_control;
+@@ -4042,15 +4125,67 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
+ }
+
+ queue = 0;
+- /* Get Fifo number to Transmit based on vlan priority */
+- if (sp->vlgrp && vlan_tx_tag_present(skb)) {
++ if (sp->vlgrp && vlan_tx_tag_present(skb))
+ vlan_tag = vlan_tx_tag_get(skb);
+- vlan_priority = vlan_tag >> 13;
+- queue = config->fifo_mapping[vlan_priority];
++ if (sp->config.tx_steering_type == TX_DEFAULT_STEERING) {
++ if (skb->protocol == htons(ETH_P_IP)) {
++ struct iphdr *ip;
++ struct tcphdr *th;
++ ip = ip_hdr(skb);
++
++ if ((ip->frag_off & htons(IP_OFFSET|IP_MF)) == 0) {
++ th = (struct tcphdr *)(((unsigned char *)ip) +
++ ip->ihl*4);
++
++ if (ip->protocol == IPPROTO_TCP) {
++ queue_len = sp->total_tcp_fifos;
++ queue = (ntohs(th->source) +
++ ntohs(th->dest)) &
++ sp->fifo_selector[queue_len - 1];
++ if (queue >= queue_len)
++ queue = queue_len - 1;
++ } else if (ip->protocol == IPPROTO_UDP) {
++ queue_len = sp->total_udp_fifos;
++ queue = (ntohs(th->source) +
++ ntohs(th->dest)) &
++ sp->fifo_selector[queue_len - 1];
++ if (queue >= queue_len)
++ queue = queue_len - 1;
++ queue += sp->udp_fifo_idx;
++ if (skb->len > 1024)
++ enable_per_list_interrupt = 1;
++ do_spin_lock = 0;
++ }
++ }
++ }
++ } else if (sp->config.tx_steering_type == TX_PRIORITY_STEERING)
++ /* get fifo number based on skb->priority value */
++ queue = config->fifo_mapping
++ [skb->priority & (MAX_TX_FIFOS - 1)];
++ fifo = &mac_control->fifos[queue];
++
++ if (do_spin_lock)
++ spin_lock_irqsave(&fifo->tx_lock, flags);
++ else {
++ if (unlikely(!spin_trylock_irqsave(&fifo->tx_lock, flags)))
++ return NETDEV_TX_LOCKED;
++ }
++
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ if (sp->config.multiq) {
++ if (__netif_subqueue_stopped(dev, fifo->fifo_no)) {
++ spin_unlock_irqrestore(&fifo->tx_lock, flags);
++ return NETDEV_TX_BUSY;
++ }
++ } else
++#endif
++ if (unlikely(fifo->queue_state == FIFO_QUEUE_STOP)) {
++ if (netif_queue_stopped(dev)) {
++ spin_unlock_irqrestore(&fifo->tx_lock, flags);
++ return NETDEV_TX_BUSY;
++ }
+ }
+
+- fifo = &mac_control->fifos[queue];
+- spin_lock_irqsave(&fifo->tx_lock, flags);
+ put_off = (u16) fifo->tx_curr_put_info.offset;
+ get_off = (u16) fifo->tx_curr_get_info.offset;
+ txdp = (struct TxD *) fifo->list_info[put_off].list_virt_addr;
+@@ -4060,7 +4195,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
+ if (txdp->Host_Control ||
+ ((put_off+1) == queue_len ? 0 : (put_off+1)) == get_off) {
+ DBG_PRINT(TX_DBG, "Error in xmit, No free TXDs.\n");
+- netif_stop_queue(dev);
++ s2io_stop_tx_queue(sp, fifo->fifo_no);
+ dev_kfree_skb(skb);
+ spin_unlock_irqrestore(&fifo->tx_lock, flags);
+ return 0;
+@@ -4079,8 +4214,10 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
+ txdp->Control_1 |= TXD_GATHER_CODE_FIRST;
+ txdp->Control_1 |= TXD_LIST_OWN_XENA;
+ txdp->Control_2 |= TXD_INT_NUMBER(fifo->fifo_no);
+-
+- if (sp->vlgrp && vlan_tx_tag_present(skb)) {
++ if (enable_per_list_interrupt)
++ if (put_off & (queue_len >> 5))
++ txdp->Control_2 |= TXD_INT_TYPE_PER_LIST;
++ if (vlan_tag) {
+ txdp->Control_2 |= TXD_VLAN_ENABLE;
+ txdp->Control_2 |= TXD_VLAN_TAG(vlan_tag);
+ }
+@@ -4095,11 +4232,12 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
+ txdp->Control_1 |= TXD_UFO_MSS(ufo_size);
+ txdp->Control_1 |= TXD_BUFFER0_SIZE(8);
+ #ifdef __BIG_ENDIAN
++ /* both variants do cpu_to_be64(be32_to_cpu(...)) */
+ fifo->ufo_in_band_v[put_off] =
+- (u64)skb_shinfo(skb)->ip6_frag_id;
++ (__force u64)skb_shinfo(skb)->ip6_frag_id;
+ #else
+ fifo->ufo_in_band_v[put_off] =
+- (u64)skb_shinfo(skb)->ip6_frag_id << 32;
++ (__force u64)skb_shinfo(skb)->ip6_frag_id << 32;
+ #endif
+ txdp->Host_Control = (unsigned long)fifo->ufo_in_band_v;
+ txdp->Buffer_Pointer = pci_map_single(sp->pdev,
+@@ -4166,7 +4304,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
+ DBG_PRINT(TX_DBG,
+ "No free TxDs for xmit, Put: 0x%x Get:0x%x\n",
+ put_off, get_off);
+- netif_stop_queue(dev);
++ s2io_stop_tx_queue(sp, fifo->fifo_no);
+ }
+ mac_control->stats_info->sw_stat.mem_allocated += skb->truesize;
+ dev->trans_start = jiffies;
+@@ -4178,7 +4316,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
+ return 0;
+ pci_map_failed:
+ stats->pci_map_fail_cnt++;
+- netif_stop_queue(dev);
++ s2io_stop_tx_queue(sp, fifo->fifo_no);
+ stats->mem_freed += skb->truesize;
+ dev_kfree_skb(skb);
+ spin_unlock_irqrestore(&fifo->tx_lock, flags);
+@@ -4197,29 +4335,9 @@ s2io_alarm_handle(unsigned long data)
+
+ static int s2io_chk_rx_buffers(struct s2io_nic *sp, int rng_n)
+ {
+- int rxb_size, level;
+-
+- if (!sp->lro) {
+- rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]);
+- level = rx_buffer_level(sp, rxb_size, rng_n);
+-
+- if ((level == PANIC) && (!TASKLET_IN_USE)) {
+- int ret;
+- DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__);
+- DBG_PRINT(INTR_DBG, "PANIC levels\n");
+- if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) {
+- DBG_PRINT(INFO_DBG, "Out of memory in %s",
+- __FUNCTION__);
+- clear_bit(0, (&sp->tasklet_status));
+- return -1;
+- }
+- clear_bit(0, (&sp->tasklet_status));
+- } else if (level == LOW)
+- tasklet_schedule(&sp->task);
+-
+- } else if (fill_rx_buffers(sp, rng_n) == -ENOMEM) {
+- DBG_PRINT(INFO_DBG, "%s:Out of memory", sp->dev->name);
+- DBG_PRINT(INFO_DBG, " in Rx Intr!!\n");
++ if (fill_rx_buffers(sp, rng_n) == -ENOMEM) {
++ DBG_PRINT(INFO_DBG, "%s:Out of memory", sp->dev->name);
++ DBG_PRINT(INFO_DBG, " in Rx Intr!!\n");
+ }
+ return 0;
+ }
+@@ -4590,7 +4708,7 @@ static void s2io_handle_errors(void * dev_id)
+ return;
+
+ reset:
+- netif_stop_queue(dev);
++ s2io_stop_all_tx_queue(sp);
+ schedule_work(&sp->rst_timer_task);
+ sw_stat->soft_reset_cnt++;
+ return;
+@@ -6577,16 +6695,15 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
+
+ dev->mtu = new_mtu;
+ if (netif_running(dev)) {
++ s2io_stop_all_tx_queue(sp);
+ s2io_card_down(sp);
+- netif_stop_queue(dev);
+ ret = s2io_card_up(sp);
+ if (ret) {
+ DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
+ __FUNCTION__);
+ return ret;
+ }
+- if (netif_queue_stopped(dev))
+- netif_wake_queue(dev);
++ s2io_wake_all_tx_queue(sp);
+ } else { /* Device is down */
+ struct XENA_dev_config __iomem *bar0 = sp->bar0;
+ u64 val64 = new_mtu;
+@@ -6598,49 +6715,6 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
+ }
+
+ /**
+- * s2io_tasklet - Bottom half of the ISR.
+- * @dev_adr : address of the device structure in dma_addr_t format.
+- * Description:
+- * This is the tasklet or the bottom half of the ISR. This is
+- * an extension of the ISR which is scheduled by the scheduler to be run
+- * when the load on the CPU is low. All low priority tasks of the ISR can
+- * be pushed into the tasklet. For now the tasklet is used only to
+- * replenish the Rx buffers in the Rx buffer descriptors.
+- * Return value:
+- * void.
+- */
+-
+-static void s2io_tasklet(unsigned long dev_addr)
+-{
+- struct net_device *dev = (struct net_device *) dev_addr;
+- struct s2io_nic *sp = dev->priv;
+- int i, ret;
+- struct mac_info *mac_control;
+- struct config_param *config;
+-
+- mac_control = &sp->mac_control;
+- config = &sp->config;
+-
+- if (!TASKLET_IN_USE) {
+- for (i = 0; i < config->rx_ring_num; i++) {
+- ret = fill_rx_buffers(sp, i);
+- if (ret == -ENOMEM) {
+- DBG_PRINT(INFO_DBG, "%s: Out of ",
+- dev->name);
+- DBG_PRINT(INFO_DBG, "memory in tasklet\n");
+- break;
+- } else if (ret == -EFILL) {
+- DBG_PRINT(INFO_DBG,
+- "%s: Rx Ring %d is full\n",
+- dev->name, i);
+- break;
+- }
+- }
+- clear_bit(0, (&sp->tasklet_status));
+- }
+-}
+-
+-/**
+ * s2io_set_link - Set the LInk status
+ * @data: long pointer to device private structue
+ * Description: Sets the link status for the adapter
+@@ -6694,7 +6768,7 @@ static void s2io_set_link(struct work_struct *work)
+ } else {
+ DBG_PRINT(ERR_DBG, "%s: Error: ", dev->name);
+ DBG_PRINT(ERR_DBG, "device is not Quiescent\n");
+- netif_stop_queue(dev);
++ s2io_stop_all_tx_queue(nic);
+ }
+ }
+ val64 = readq(&bar0->adapter_control);
+@@ -6921,11 +6995,11 @@ static int s2io_add_isr(struct s2io_nic * sp)
+ if(!(sp->msix_info[i].addr &&
+ sp->msix_info[i].data)) {
+ DBG_PRINT(ERR_DBG, "%s @ Addr:0x%llx "
+- "Data:0x%lx\n",sp->desc[i],
++ "Data:0x%llx\n",sp->desc[i],
+ (unsigned long long)
+ sp->msix_info[i].addr,
+- (unsigned long)
+- ntohl(sp->msix_info[i].data));
++ (unsigned long long)
++ sp->msix_info[i].data);
+ } else {
+ msix_tx_cnt++;
+ }
+@@ -6939,11 +7013,11 @@ static int s2io_add_isr(struct s2io_nic * sp)
+ if(!(sp->msix_info[i].addr &&
+ sp->msix_info[i].data)) {
+ DBG_PRINT(ERR_DBG, "%s @ Addr:0x%llx "
+- "Data:0x%lx\n",sp->desc[i],
++ "Data:0x%llx\n",sp->desc[i],
+ (unsigned long long)
+ sp->msix_info[i].addr,
+- (unsigned long)
+- ntohl(sp->msix_info[i].data));
++ (unsigned long long)
++ sp->msix_info[i].data);
+ } else {
+ msix_rx_cnt++;
+ }
+@@ -6989,7 +7063,6 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
+ {
+ int cnt = 0;
+ struct XENA_dev_config __iomem *bar0 = sp->bar0;
+- unsigned long flags;
+ register u64 val64 = 0;
+ struct config_param *config;
+ config = &sp->config;
+@@ -7014,9 +7087,6 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
+
+ s2io_rem_isr(sp);
+
+- /* Kill tasklet. */
+- tasklet_kill(&sp->task);
+-
+ /* Check if the device is Quiescent and then Reset the NIC */
+ while(do_io) {
+ /* As per the HW requirement we need to replenish the
+@@ -7051,9 +7121,7 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
+ free_tx_buffers(sp);
+
+ /* Free all Rx buffers */
+- spin_lock_irqsave(&sp->rx_lock, flags);
+ free_rx_buffers(sp);
+- spin_unlock_irqrestore(&sp->rx_lock, flags);
+
+ clear_bit(__S2IO_STATE_LINK_TASK, &(sp->state));
+ }
+@@ -7142,9 +7210,6 @@ static int s2io_card_up(struct s2io_nic * sp)
+
+ S2IO_TIMER_CONF(sp->alarm_timer, s2io_alarm_handle, sp, (HZ/2));
+
+- /* Enable tasklet for the device */
+- tasklet_init(&sp->task, s2io_tasklet, (unsigned long) dev);
+-
+ /* Enable select interrupts */
+ en_dis_err_alarms(sp, ENA_ALL_INTRS, ENABLE_INTRS);
+ if (sp->config.intr_type != INTA)
+@@ -7184,7 +7249,7 @@ static void s2io_restart_nic(struct work_struct *work)
+ DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
+ dev->name);
+ }
+- netif_wake_queue(dev);
++ s2io_wake_all_tx_queue(sp);
+ DBG_PRINT(ERR_DBG, "%s: was reset by Tx watchdog timer\n",
+ dev->name);
+ out_unlock:
+@@ -7374,7 +7439,8 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
+ {
+ lro_append_pkt(sp, lro,
+ skb, tcp_len);
+- queue_rx_frame(lro->parent);
++ queue_rx_frame(lro->parent,
++ lro->vlan_tag);
+ clear_lro_session(lro);
+ sp->mac_control.stats_info->
+ sw_stat.flush_max_pkts++;
+@@ -7385,7 +7451,8 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
+ lro->frags_len;
+ sp->mac_control.stats_info->
+ sw_stat.sending_both++;
+- queue_rx_frame(lro->parent);
++ queue_rx_frame(lro->parent,
++ lro->vlan_tag);
+ clear_lro_session(lro);
+ goto send_up;
+ case 0: /* sessions exceeded */
+@@ -7411,31 +7478,12 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
+ */
+ skb->ip_summed = CHECKSUM_NONE;
+ }
+- } else {
++ } else
+ skb->ip_summed = CHECKSUM_NONE;
+- }
++
+ sp->mac_control.stats_info->sw_stat.mem_freed += skb->truesize;
+- if (!sp->lro) {
+- skb->protocol = eth_type_trans(skb, dev);
+- if ((sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2) &&
+- vlan_strip_flag)) {
+- /* Queueing the vlan frame to the upper layer */
+- if (napi)
+- vlan_hwaccel_receive_skb(skb, sp->vlgrp,
+- RXD_GET_VLAN_TAG(rxdp->Control_2));
+- else
+- vlan_hwaccel_rx(skb, sp->vlgrp,
+- RXD_GET_VLAN_TAG(rxdp->Control_2));
+- } else {
+- if (napi)
+- netif_receive_skb(skb);
+- else
+- netif_rx(skb);
+- }
+- } else {
+ send_up:
+- queue_rx_frame(skb);
+- }
++ queue_rx_frame(skb, RXD_GET_VLAN_TAG(rxdp->Control_2));
+ dev->last_rx = jiffies;
+ aggregate:
+ atomic_dec(&sp->rx_bufs_left[ring_no]);
+@@ -7463,6 +7511,7 @@ static void s2io_link(struct s2io_nic * sp, int link)
+ init_tti(sp, link);
+ if (link == LINK_DOWN) {
+ DBG_PRINT(ERR_DBG, "%s: Link down\n", dev->name);
++ s2io_stop_all_tx_queue(sp);
+ netif_carrier_off(dev);
+ if(sp->mac_control.stats_info->sw_stat.link_up_cnt)
+ sp->mac_control.stats_info->sw_stat.link_up_time =
+@@ -7475,6 +7524,7 @@ static void s2io_link(struct s2io_nic * sp, int link)
+ jiffies - sp->start_time;
+ sp->mac_control.stats_info->sw_stat.link_up_cnt++;
+ netif_carrier_on(dev);
++ s2io_wake_all_tx_queue(sp);
+ }
+ }
+ sp->last_link_state = link;
+@@ -7511,20 +7561,48 @@ static void s2io_init_pci(struct s2io_nic * sp)
+ pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd);
+ }
+
+-static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type)
++static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type,
++ u8 *dev_multiq)
+ {
+ if ((tx_fifo_num > MAX_TX_FIFOS) ||
+- (tx_fifo_num < FIFO_DEFAULT_NUM)) {
++ (tx_fifo_num < 1)) {
+ DBG_PRINT(ERR_DBG, "s2io: Requested number of tx fifos "
+ "(%d) not supported\n", tx_fifo_num);
+- tx_fifo_num =
+- ((tx_fifo_num > MAX_TX_FIFOS)? MAX_TX_FIFOS :
+- ((tx_fifo_num < FIFO_DEFAULT_NUM) ? FIFO_DEFAULT_NUM :
+- tx_fifo_num));
++
++ if (tx_fifo_num < 1)
++ tx_fifo_num = 1;
++ else
++ tx_fifo_num = MAX_TX_FIFOS;
++
+ DBG_PRINT(ERR_DBG, "s2io: Default to %d ", tx_fifo_num);
+ DBG_PRINT(ERR_DBG, "tx fifos\n");
+ }
+
++#ifndef CONFIG_NETDEVICES_MULTIQUEUE
++ if (multiq) {
++ DBG_PRINT(ERR_DBG, "s2io: Multiqueue support not enabled\n");
++ multiq = 0;
++ }
++#endif
++ if (multiq)
++ *dev_multiq = multiq;
++
++ if (tx_steering_type && (1 == tx_fifo_num)) {
++ if (tx_steering_type != TX_DEFAULT_STEERING)
++ DBG_PRINT(ERR_DBG,
++ "s2io: Tx steering is not supported with "
++ "one fifo. Disabling Tx steering.\n");
++ tx_steering_type = NO_STEERING;
++ }
++
++ if ((tx_steering_type < NO_STEERING) ||
++ (tx_steering_type > TX_DEFAULT_STEERING)) {
++ DBG_PRINT(ERR_DBG, "s2io: Requested transmit steering not "
++ "supported\n");
++ DBG_PRINT(ERR_DBG, "s2io: Disabling transmit steering\n");
++ tx_steering_type = NO_STEERING;
++ }
++
+ if ( rx_ring_num > 8) {
+ DBG_PRINT(ERR_DBG, "s2io: Requested number of Rx rings not "
+ "supported\n");
+@@ -7616,9 +7694,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
+ struct config_param *config;
+ int mode;
+ u8 dev_intr_type = intr_type;
++ u8 dev_multiq = 0;
+ DECLARE_MAC_BUF(mac);
+
+- if ((ret = s2io_verify_parm(pdev, &dev_intr_type)))
++ ret = s2io_verify_parm(pdev, &dev_intr_type, &dev_multiq);
++ if (ret)
+ return ret;
+
+ if ((ret = pci_enable_device(pdev))) {
+@@ -7649,7 +7729,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
+ pci_disable_device(pdev);
+ return -ENODEV;
+ }
+-
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ if (dev_multiq)
++ dev = alloc_etherdev_mq(sizeof(struct s2io_nic), tx_fifo_num);
++ else
++#endif
+ dev = alloc_etherdev(sizeof(struct s2io_nic));
+ if (dev == NULL) {
+ DBG_PRINT(ERR_DBG, "Device allocation failed\n");
+@@ -7698,17 +7782,45 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
+ config = &sp->config;
+
+ config->napi = napi;
++ config->tx_steering_type = tx_steering_type;
+
+ /* Tx side parameters. */
+- config->tx_fifo_num = tx_fifo_num;
+- for (i = 0; i < MAX_TX_FIFOS; i++) {
++ if (config->tx_steering_type == TX_PRIORITY_STEERING)
++ config->tx_fifo_num = MAX_TX_FIFOS;
++ else
++ config->tx_fifo_num = tx_fifo_num;
++
++ /* Initialize the fifos used for tx steering */
++ if (config->tx_fifo_num < 5) {
++ if (config->tx_fifo_num == 1)
++ sp->total_tcp_fifos = 1;
++ else
++ sp->total_tcp_fifos = config->tx_fifo_num - 1;
++ sp->udp_fifo_idx = config->tx_fifo_num - 1;
++ sp->total_udp_fifos = 1;
++ sp->other_fifo_idx = sp->total_tcp_fifos - 1;
++ } else {
++ sp->total_tcp_fifos = (tx_fifo_num - FIFO_UDP_MAX_NUM -
++ FIFO_OTHER_MAX_NUM);
++ sp->udp_fifo_idx = sp->total_tcp_fifos;
++ sp->total_udp_fifos = FIFO_UDP_MAX_NUM;
++ sp->other_fifo_idx = sp->udp_fifo_idx + FIFO_UDP_MAX_NUM;
++ }
++
++ config->multiq = dev_multiq;
++ for (i = 0; i < config->tx_fifo_num; i++) {
+ config->tx_cfg[i].fifo_len = tx_fifo_len[i];
+ config->tx_cfg[i].fifo_priority = i;
+ }
+
+ /* mapping the QoS priority to the configured fifos */
+ for (i = 0; i < MAX_TX_FIFOS; i++)
+- config->fifo_mapping[i] = fifo_map[config->tx_fifo_num][i];
++ config->fifo_mapping[i] = fifo_map[config->tx_fifo_num - 1][i];
++
++ /* map the hashing selector table to the configured fifos */
++ for (i = 0; i < config->tx_fifo_num; i++)
++ sp->fifo_selector[i] = fifo_selector[i];
++
+
+ config->tx_intr_type = TXD_INT_TYPE_UTILZ;
+ for (i = 0; i < config->tx_fifo_num; i++) {
+@@ -7793,6 +7905,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
+ SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
+ dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+ dev->vlan_rx_register = s2io_vlan_rx_register;
++ dev->vlan_rx_kill_vid = (void *)s2io_vlan_rx_kill_vid;
+
+ /*
+ * will use eth_mac_addr() for dev->set_mac_address
+@@ -7813,7 +7926,10 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
+ dev->features |= NETIF_F_UFO;
+ dev->features |= NETIF_F_HW_CSUM;
+ }
+-
++#ifdef CONFIG_NETDEVICES_MULTIQUEUE
++ if (config->multiq)
++ dev->features |= NETIF_F_MULTI_QUEUE;
++#endif
+ dev->tx_timeout = &s2io_tx_watchdog;
+ dev->watchdog_timeo = WATCH_DOG_TIMEOUT;
+ INIT_WORK(&sp->rst_timer_task, s2io_restart_nic);
+@@ -7896,20 +8012,15 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
+ s2io_reset(sp);
+
+ /*
+- * Initialize the tasklet status and link state flags
++ * Initialize link state flags
+ * and the card state parameter
+ */
+- sp->tasklet_status = 0;
+ sp->state = 0;
+
+ /* Initialize spinlocks */
+ for (i = 0; i < sp->config.tx_fifo_num; i++)
+ spin_lock_init(&mac_control->fifos[i].tx_lock);
+
+- if (!napi)
+- spin_lock_init(&sp->put_lock);
+- spin_lock_init(&sp->rx_lock);
+-
+ /*
+ * SXE-002: Configure link and activity LED to init state
+ * on driver load.
+@@ -7962,6 +8073,10 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
+
+ if (napi)
+ DBG_PRINT(ERR_DBG, "%s: NAPI enabled\n", dev->name);
++
++ DBG_PRINT(ERR_DBG, "%s: Using %d Tx fifo(s)\n", dev->name,
++ sp->config.tx_fifo_num);
++
+ switch(sp->config.intr_type) {
+ case INTA:
+ DBG_PRINT(ERR_DBG, "%s: Interrupt type INTA\n", dev->name);
+@@ -7970,6 +8085,29 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
+ DBG_PRINT(ERR_DBG, "%s: Interrupt type MSI-X\n", dev->name);
+ break;
+ }
++ if (sp->config.multiq) {
++ for (i = 0; i < sp->config.tx_fifo_num; i++)
++ mac_control->fifos[i].multiq = config->multiq;
++ DBG_PRINT(ERR_DBG, "%s: Multiqueue support enabled\n",
++ dev->name);
++ } else
++ DBG_PRINT(ERR_DBG, "%s: Multiqueue support disabled\n",
++ dev->name);
++
++ switch (sp->config.tx_steering_type) {
++ case NO_STEERING:
++ DBG_PRINT(ERR_DBG, "%s: No steering enabled for"
++ " transmit\n", dev->name);
++ break;
++ case TX_PRIORITY_STEERING:
++ DBG_PRINT(ERR_DBG, "%s: Priority steering enabled for"
++ " transmit\n", dev->name);
++ break;
++ case TX_DEFAULT_STEERING:
++ DBG_PRINT(ERR_DBG, "%s: Default steering enabled for"
++ " transmit\n", dev->name);
++ }
++
+ if (sp->lro)
+ DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n",
+ dev->name);
+@@ -8064,7 +8202,8 @@ module_init(s2io_starter);
+ module_exit(s2io_closer);
+
+ static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip,
+- struct tcphdr **tcp, struct RxD_t *rxdp)
++ struct tcphdr **tcp, struct RxD_t *rxdp,
++ struct s2io_nic *sp)
+ {
+ int ip_off;
+ u8 l2_type = (u8)((rxdp->Control_1 >> 37) & 0x7), ip_len;
+@@ -8075,19 +8214,20 @@ static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip,
+ return -1;
+ }
+
+- /* TODO:
+- * By default the VLAN field in the MAC is stripped by the card, if this
+- * feature is turned off in rx_pa_cfg register, then the ip_off field
+- * has to be shifted by a further 2 bytes
+- */
+- switch (l2_type) {
+- case 0: /* DIX type */
+- case 4: /* DIX type with VLAN */
+- ip_off = HEADER_ETHERNET_II_802_3_SIZE;
+- break;
++ /* Checking for DIX type or DIX type with VLAN */
++ if ((l2_type == 0)
++ || (l2_type == 4)) {
++ ip_off = HEADER_ETHERNET_II_802_3_SIZE;
++ /*
++ * If vlan stripping is disabled and the frame is VLAN tagged,
++ * shift the offset by the VLAN header size bytes.
++ */
++ if ((!vlan_strip_flag) &&
++ (rxdp->Control_1 & RXD_FRAME_VLAN_TAG))
++ ip_off += HEADER_VLAN_SIZE;
++ } else {
+ /* LLC, SNAP etc are considered non-mergeable */
+- default:
+- return -1;
++ return -1;
+ }
+
+ *ip = (struct iphdr *)((u8 *)buffer + ip_off);
+@@ -8114,7 +8254,7 @@ static inline int get_l4_pyld_length(struct iphdr *ip, struct tcphdr *tcp)
+ }
+
+ static void initiate_new_session(struct lro *lro, u8 *l2h,
+- struct iphdr *ip, struct tcphdr *tcp, u32 tcp_pyld_len)
++ struct iphdr *ip, struct tcphdr *tcp, u32 tcp_pyld_len, u16 vlan_tag)
+ {
+ DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
+ lro->l2h = l2h;
+@@ -8125,6 +8265,7 @@ static void initiate_new_session(struct lro *lro, u8 *l2h,
+ lro->sg_num = 1;
+ lro->total_len = ntohs(ip->tot_len);
+ lro->frags_len = 0;
++ lro->vlan_tag = vlan_tag;
+ /*
+ * check if we saw TCP timestamp. Other consistency checks have
+ * already been done.
+@@ -8256,15 +8397,16 @@ s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro,
+ struct iphdr *ip;
+ struct tcphdr *tcph;
+ int ret = 0, i;
++ u16 vlan_tag = 0;
+
+ if (!(ret = check_L2_lro_capable(buffer, &ip, (struct tcphdr **)tcp,
+- rxdp))) {
++ rxdp, sp))) {
+ DBG_PRINT(INFO_DBG,"IP Saddr: %x Daddr: %x\n",
+ ip->saddr, ip->daddr);
+- } else {
++ } else
+ return ret;
+- }
+
++ vlan_tag = RXD_GET_VLAN_TAG(rxdp->Control_2);
+ tcph = (struct tcphdr *)*tcp;
+ *tcp_len = get_l4_pyld_length(ip, tcph);
+ for (i=0; i<MAX_LRO_SESSIONS; i++) {
+@@ -8324,7 +8466,8 @@ s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro,
+
+ switch (ret) {
+ case 3:
+- initiate_new_session(*lro, buffer, ip, tcph, *tcp_len);
++ initiate_new_session(*lro, buffer, ip, tcph, *tcp_len,
++ vlan_tag);
+ break;
+ case 2:
+ update_L3L4_header(sp, *lro);
+@@ -8352,15 +8495,25 @@ static void clear_lro_session(struct lro *lro)
+ memset(lro, 0, lro_struct_size);
+ }
+
+-static void queue_rx_frame(struct sk_buff *skb)
++static void queue_rx_frame(struct sk_buff *skb, u16 vlan_tag)
+ {
+ struct net_device *dev = skb->dev;
++ struct s2io_nic *sp = dev->priv;
+
+ skb->protocol = eth_type_trans(skb, dev);
+- if (napi)
+- netif_receive_skb(skb);
+- else
+- netif_rx(skb);
++ if (sp->vlgrp && vlan_tag
++ && (vlan_strip_flag)) {
++ /* Queueing the vlan frame to the upper layer */
++ if (sp->config.napi)
++ vlan_hwaccel_receive_skb(skb, sp->vlgrp, vlan_tag);
++ else
++ vlan_hwaccel_rx(skb, sp->vlgrp, vlan_tag);
++ } else {
++ if (sp->config.napi)
++ netif_receive_skb(skb);
++ else
++ netif_rx(skb);
++ }
+ }
+
+ static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro,
+diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
+index 64b88eb..ce53a02 100644
+--- a/drivers/net/s2io.h
++++ b/drivers/net/s2io.h
+@@ -360,7 +360,10 @@ struct stat_block {
+ #define MAX_TX_FIFOS 8
+ #define MAX_RX_RINGS 8
+
+-#define FIFO_DEFAULT_NUM 1
++#define FIFO_DEFAULT_NUM 5
++#define FIFO_UDP_MAX_NUM 2 /* 0 - even, 1 -odd ports */
++#define FIFO_OTHER_MAX_NUM 1
++
+
+ #define MAX_RX_DESC_1 (MAX_RX_RINGS * MAX_RX_BLOCKS_PER_RING * 127 )
+ #define MAX_RX_DESC_2 (MAX_RX_RINGS * MAX_RX_BLOCKS_PER_RING * 85 )
+@@ -379,6 +382,8 @@ static int fifo_map[][MAX_TX_FIFOS] = {
+ {0, 1, 2, 3, 4, 5, 6, 7},
+ };
+
++static u16 fifo_selector[MAX_TX_FIFOS] = {0, 1, 3, 3, 7, 7, 7, 7};
++
+ /* Maintains Per FIFO related information. */
+ struct tx_fifo_config {
+ #define MAX_AVAILABLE_TXDS 8192
+@@ -431,6 +436,12 @@ struct config_param {
+ /* Tx Side */
+ u32 tx_fifo_num; /*Number of Tx FIFOs */
+
++ /* 0-No steering, 1-Priority steering, 2-Default fifo map */
++#define NO_STEERING 0
++#define TX_PRIORITY_STEERING 0x1
++#define TX_DEFAULT_STEERING 0x2
++ u8 tx_steering_type;
++
+ u8 fifo_mapping[MAX_TX_FIFOS];
+ struct tx_fifo_config tx_cfg[MAX_TX_FIFOS]; /*Per-Tx FIFO config */
+ u32 max_txds; /*Max no. of Tx buffer descriptor per TxDL */
+@@ -464,6 +475,7 @@ struct config_param {
+ int max_mc_addr; /* xena=64 herc=256 */
+ int max_mac_addr; /* xena=16 herc=64 */
+ int mc_start_offset; /* xena=16 herc=64 */
++ u8 multiq;
+ };
+
+ /* Structure representing MAC Addrs */
+@@ -534,6 +546,7 @@ struct RxD_t {
+ #define RXD_OWN_XENA s2BIT(7)
+ #define RXD_T_CODE (s2BIT(12)|s2BIT(13)|s2BIT(14)|s2BIT(15))
+ #define RXD_FRAME_PROTO vBIT(0xFFFF,24,8)
++#define RXD_FRAME_VLAN_TAG s2BIT(24)
+ #define RXD_FRAME_PROTO_IPV4 s2BIT(27)
+ #define RXD_FRAME_PROTO_IPV6 s2BIT(28)
+ #define RXD_FRAME_IP_FRAG s2BIT(29)
+@@ -690,9 +703,6 @@ struct ring_info {
+ */
+ struct rx_curr_get_info rx_curr_get_info;
+
+- /* Index to the absolute position of the put pointer of Rx ring */
+- int put_pos;
+-
+ /* Buffer Address store. */
+ struct buffAdd **ba;
+ struct s2io_nic *nic;
+@@ -720,6 +730,15 @@ struct fifo_info {
+ * the buffers
+ */
+ struct tx_curr_get_info tx_curr_get_info;
++#define FIFO_QUEUE_START 0
++#define FIFO_QUEUE_STOP 1
++ int queue_state;
++
++ /* copy of sp->dev pointer */
++ struct net_device *dev;
++
++ /* copy of multiq status */
++ u8 multiq;
+
+ /* Per fifo lock */
+ spinlock_t tx_lock;
+@@ -808,10 +827,11 @@ struct lro {
+ int sg_num;
+ int in_use;
+ __be16 window;
++ u16 vlan_tag;
+ u32 cur_tsval;
+ __be32 cur_tsecr;
+ u8 saw_ts;
+-};
++} ____cacheline_aligned;
+
+ /* These flags represent the devices temporary state */
+ enum s2io_device_state_t
+@@ -845,8 +865,6 @@ struct s2io_nic {
+ int device_enabled_once;
+
+ char name[60];
+- struct tasklet_struct task;
+- volatile unsigned long tasklet_status;
+
+ /* Timer that handles I/O errors/exceptions */
+ struct timer_list alarm_timer;
+@@ -856,8 +874,6 @@ struct s2io_nic {
+
+ atomic_t rx_bufs_left[MAX_RX_RINGS];
+
+- spinlock_t put_lock;
+-
+ #define PROMISC 1
+ #define ALL_MULTI 2
+
+@@ -885,6 +901,27 @@ struct s2io_nic {
+ */
+ int rx_csum;
+
++ /* Below variables are used for fifo selection to transmit a packet */
++ u16 fifo_selector[MAX_TX_FIFOS];
++
++ /* Total fifos for tcp packets */
++ u8 total_tcp_fifos;
++
++ /*
++ * Beginning index of udp for udp packets
++ * Value will be equal to
++ * (tx_fifo_num - FIFO_UDP_MAX_NUM - FIFO_OTHER_MAX_NUM)
++ */
++ u8 udp_fifo_idx;
++
++ u8 total_udp_fifos;
++
++ /*
++ * Beginning index of fifo for all other packets
++ * Value will be equal to (tx_fifo_num - FIFO_OTHER_MAX_NUM)
++ */
++ u8 other_fifo_idx;
++
+ /* after blink, the adapter must be restored with original
+ * values.
+ */
+@@ -920,7 +957,6 @@ struct s2io_nic {
+ u8 lro;
+ u16 lro_max_aggr_per_sess;
+ volatile unsigned long state;
+- spinlock_t rx_lock;
+ u64 general_int_mask;
+ #define VPD_STRING_LEN 80
+ u8 product_name[VPD_STRING_LEN];
+@@ -1050,7 +1086,6 @@ static void s2io_handle_errors(void * dev_id);
+ static int s2io_starter(void);
+ static void s2io_closer(void);
+ static void s2io_tx_watchdog(struct net_device *dev);
+-static void s2io_tasklet(unsigned long dev_addr);
+ static void s2io_set_multicast(struct net_device *dev);
+ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp);
+ static void s2io_link(struct s2io_nic * sp, int link);
+@@ -1087,7 +1122,7 @@ static int
+ s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro,
+ struct RxD_t *rxdp, struct s2io_nic *sp);
+ static void clear_lro_session(struct lro *lro);
+-static void queue_rx_frame(struct sk_buff *skb);
++static void queue_rx_frame(struct sk_buff *skb, u16 vlan_tag);
+ static void update_L3L4_header(struct s2io_nic *sp, struct lro *lro);
+ static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro,
+ struct sk_buff *skb, u32 tcp_len);
+diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c
+index 487f9d2..5986cec 100644
+--- a/drivers/net/sb1000.c
++++ b/drivers/net/sb1000.c
+@@ -88,31 +88,31 @@ static int sb1000_close(struct net_device *dev);
+
+
+ /* SB1000 hardware routines to be used during open/configuration phases */
+-static inline int card_wait_for_busy_clear(const int ioaddr[],
++static int card_wait_for_busy_clear(const int ioaddr[],
+ const char* name);
+-static inline int card_wait_for_ready(const int ioaddr[], const char* name,
++static int card_wait_for_ready(const int ioaddr[], const char* name,
+ unsigned char in[]);
+ static int card_send_command(const int ioaddr[], const char* name,
+ const unsigned char out[], unsigned char in[]);
+
+ /* SB1000 hardware routines to be used during frame rx interrupt */
+-static inline int sb1000_wait_for_ready(const int ioaddr[], const char* name);
+-static inline int sb1000_wait_for_ready_clear(const int ioaddr[],
++static int sb1000_wait_for_ready(const int ioaddr[], const char* name);
++static int sb1000_wait_for_ready_clear(const int ioaddr[],
+ const char* name);
+-static inline void sb1000_send_command(const int ioaddr[], const char* name,
++static void sb1000_send_command(const int ioaddr[], const char* name,
+ const unsigned char out[]);
+-static inline void sb1000_read_status(const int ioaddr[], unsigned char in[]);
+-static inline void sb1000_issue_read_command(const int ioaddr[],
++static void sb1000_read_status(const int ioaddr[], unsigned char in[]);
++static void sb1000_issue_read_command(const int ioaddr[],
+ const char* name);
+
+ /* SB1000 commands for open/configuration */
+-static inline int sb1000_reset(const int ioaddr[], const char* name);
+-static inline int sb1000_check_CRC(const int ioaddr[], const char* name);
++static int sb1000_reset(const int ioaddr[], const char* name);
++static int sb1000_check_CRC(const int ioaddr[], const char* name);
+ static inline int sb1000_start_get_set_command(const int ioaddr[],
+ const char* name);
+-static inline int sb1000_end_get_set_command(const int ioaddr[],
++static int sb1000_end_get_set_command(const int ioaddr[],
+ const char* name);
+-static inline int sb1000_activate(const int ioaddr[], const char* name);
++static int sb1000_activate(const int ioaddr[], const char* name);
+ static int sb1000_get_firmware_version(const int ioaddr[],
+ const char* name, unsigned char version[], int do_end);
+ static int sb1000_get_frequency(const int ioaddr[], const char* name,
+@@ -125,8 +125,8 @@ static int sb1000_set_PIDs(const int ioaddr[], const char* name,
+ const short PID[]);
+
+ /* SB1000 commands for frame rx interrupt */
+-static inline int sb1000_rx(struct net_device *dev);
+-static inline void sb1000_error_dpc(struct net_device *dev);
++static int sb1000_rx(struct net_device *dev);
++static void sb1000_error_dpc(struct net_device *dev);
+
+ static const struct pnp_device_id sb1000_pnp_ids[] = {
+ { "GIC1000", 0 },
+@@ -250,7 +250,7 @@ static struct pnp_driver sb1000_driver = {
+ static const int TimeOutJiffies = (875 * HZ) / 100;
+
+ /* Card Wait For Busy Clear (cannot be used during an interrupt) */
+-static inline int
++static int
+ card_wait_for_busy_clear(const int ioaddr[], const char* name)
+ {
+ unsigned char a;
+@@ -274,7 +274,7 @@ card_wait_for_busy_clear(const int ioaddr[], const char* name)
+ }
+
+ /* Card Wait For Ready (cannot be used during an interrupt) */
+-static inline int
++static int
+ card_wait_for_ready(const int ioaddr[], const char* name, unsigned char in[])
+ {
+ unsigned char a;
+@@ -354,7 +354,7 @@ card_send_command(const int ioaddr[], const char* name,
+ static const int Sb1000TimeOutJiffies = 7 * HZ;
+
+ /* Card Wait For Ready (to be used during frame rx) */
+-static inline int
++static int
+ sb1000_wait_for_ready(const int ioaddr[], const char* name)
+ {
+ unsigned long timeout;
+@@ -380,7 +380,7 @@ sb1000_wait_for_ready(const int ioaddr[], const char* name)
+ }
+
+ /* Card Wait For Ready Clear (to be used during frame rx) */
+-static inline int
++static int
+ sb1000_wait_for_ready_clear(const int ioaddr[], const char* name)
+ {
+ unsigned long timeout;
+@@ -405,7 +405,7 @@ sb1000_wait_for_ready_clear(const int ioaddr[], const char* name)
+ }
+
+ /* Card Send Command (to be used during frame rx) */
+-static inline void
++static void
+ sb1000_send_command(const int ioaddr[], const char* name,
+ const unsigned char out[])
+ {
+@@ -422,7 +422,7 @@ sb1000_send_command(const int ioaddr[], const char* name,
+ }
+
+ /* Card Read Status (to be used during frame rx) */
+-static inline void
++static void
+ sb1000_read_status(const int ioaddr[], unsigned char in[])
+ {
+ in[1] = inb(ioaddr[0] + 1);
+@@ -434,10 +434,10 @@ sb1000_read_status(const int ioaddr[], unsigned char in[])
+ }
+
+ /* Issue Read Command (to be used during frame rx) */
+-static inline void
++static void
+ sb1000_issue_read_command(const int ioaddr[], const char* name)
+ {
+- const unsigned char Command0[6] = {0x20, 0x00, 0x00, 0x01, 0x00, 0x00};
++ static const unsigned char Command0[6] = {0x20, 0x00, 0x00, 0x01, 0x00, 0x00};
+
+ sb1000_wait_for_ready_clear(ioaddr, name);
+ outb(0xa0, ioaddr[0] + 6);
+@@ -450,12 +450,13 @@ sb1000_issue_read_command(const int ioaddr[], const char* name)
+ * SB1000 commands for open/configuration
+ */
+ /* reset SB1000 card */
+-static inline int
++static int
+ sb1000_reset(const int ioaddr[], const char* name)
+ {
++ static const unsigned char Command0[6] = {0x80, 0x16, 0x00, 0x00, 0x00, 0x00};
++
+ unsigned char st[7];
+ int port, status;
+- const unsigned char Command0[6] = {0x80, 0x16, 0x00, 0x00, 0x00, 0x00};
+
+ port = ioaddr[1] + 6;
+ outb(0x4, port);
+@@ -479,12 +480,13 @@ sb1000_reset(const int ioaddr[], const char* name)
+ }
+
+ /* check SB1000 firmware CRC */
+-static inline int
++static int
+ sb1000_check_CRC(const int ioaddr[], const char* name)
+ {
++ static const unsigned char Command0[6] = {0x80, 0x1f, 0x00, 0x00, 0x00, 0x00};
++
+ unsigned char st[7];
+ int crc, status;
+- const unsigned char Command0[6] = {0x80, 0x1f, 0x00, 0x00, 0x00, 0x00};
+
+ /* check CRC */
+ if ((status = card_send_command(ioaddr, name, Command0, st)))
+@@ -498,32 +500,35 @@ sb1000_check_CRC(const int ioaddr[], const char* name)
+ static inline int
+ sb1000_start_get_set_command(const int ioaddr[], const char* name)
+ {
++ static const unsigned char Command0[6] = {0x80, 0x1b, 0x00, 0x00, 0x00, 0x00};
++
+ unsigned char st[7];
+- const unsigned char Command0[6] = {0x80, 0x1b, 0x00, 0x00, 0x00, 0x00};
+
+ return card_send_command(ioaddr, name, Command0, st);
+ }
+
+-static inline int
++static int
+ sb1000_end_get_set_command(const int ioaddr[], const char* name)
+ {
++ static const unsigned char Command0[6] = {0x80, 0x1b, 0x02, 0x00, 0x00, 0x00};
++ static const unsigned char Command1[6] = {0x20, 0x00, 0x00, 0x00, 0x00, 0x00};
++
+ unsigned char st[7];
+ int status;
+- const unsigned char Command0[6] = {0x80, 0x1b, 0x02, 0x00, 0x00, 0x00};
+- const unsigned char Command1[6] = {0x20, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+ if ((status = card_send_command(ioaddr, name, Command0, st)))
+ return status;
+ return card_send_command(ioaddr, name, Command1, st);
+ }
+
+-static inline int
++static int
+ sb1000_activate(const int ioaddr[], const char* name)
+ {
++ static const unsigned char Command0[6] = {0x80, 0x11, 0x00, 0x00, 0x00, 0x00};
++ static const unsigned char Command1[6] = {0x80, 0x16, 0x00, 0x00, 0x00, 0x00};
++
+ unsigned char st[7];
+ int status;
+- const unsigned char Command0[6] = {0x80, 0x11, 0x00, 0x00, 0x00, 0x00};
+- const unsigned char Command1[6] = {0x80, 0x16, 0x00, 0x00, 0x00, 0x00};
+
+ ssleep(1);
+ if ((status = card_send_command(ioaddr, name, Command0, st)))
+@@ -544,9 +549,10 @@ static int
+ sb1000_get_firmware_version(const int ioaddr[], const char* name,
+ unsigned char version[], int do_end)
+ {
++ static const unsigned char Command0[6] = {0x80, 0x23, 0x00, 0x00, 0x00, 0x00};
++
+ unsigned char st[7];
+ int status;
+- const unsigned char Command0[6] = {0x80, 0x23, 0x00, 0x00, 0x00, 0x00};
+
+ if ((status = sb1000_start_get_set_command(ioaddr, name)))
+ return status;
+@@ -566,9 +572,10 @@ sb1000_get_firmware_version(const int ioaddr[], const char* name,
+ static int
+ sb1000_get_frequency(const int ioaddr[], const char* name, int* frequency)
+ {
++ static const unsigned char Command0[6] = {0x80, 0x44, 0x00, 0x00, 0x00, 0x00};
++
+ unsigned char st[7];
+ int status;
+- const unsigned char Command0[6] = {0x80, 0x44, 0x00, 0x00, 0x00, 0x00};
+
+ udelay(1000);
+ if ((status = sb1000_start_get_set_command(ioaddr, name)))
+@@ -613,12 +620,13 @@ sb1000_set_frequency(const int ioaddr[], const char* name, int frequency)
+ static int
+ sb1000_get_PIDs(const int ioaddr[], const char* name, short PID[])
+ {
++ static const unsigned char Command0[6] = {0x80, 0x40, 0x00, 0x00, 0x00, 0x00};
++ static const unsigned char Command1[6] = {0x80, 0x41, 0x00, 0x00, 0x00, 0x00};
++ static const unsigned char Command2[6] = {0x80, 0x42, 0x00, 0x00, 0x00, 0x00};
++ static const unsigned char Command3[6] = {0x80, 0x43, 0x00, 0x00, 0x00, 0x00};
++
+ unsigned char st[7];
+ int status;
+- const unsigned char Command0[6] = {0x80, 0x40, 0x00, 0x00, 0x00, 0x00};
+- const unsigned char Command1[6] = {0x80, 0x41, 0x00, 0x00, 0x00, 0x00};
+- const unsigned char Command2[6] = {0x80, 0x42, 0x00, 0x00, 0x00, 0x00};
+- const unsigned char Command3[6] = {0x80, 0x43, 0x00, 0x00, 0x00, 0x00};
+
+ udelay(1000);
+ if ((status = sb1000_start_get_set_command(ioaddr, name)))
+@@ -647,6 +655,8 @@ sb1000_get_PIDs(const int ioaddr[], const char* name, short PID[])
+ static int
+ sb1000_set_PIDs(const int ioaddr[], const char* name, const short PID[])
+ {
++ static const unsigned char Command4[6] = {0x80, 0x2e, 0x00, 0x00, 0x00, 0x00};
++
+ unsigned char st[7];
+ short p;
+ int status;
+@@ -654,7 +664,6 @@ sb1000_set_PIDs(const int ioaddr[], const char* name, const short PID[])
+ unsigned char Command1[6] = {0x80, 0x32, 0x00, 0x00, 0x00, 0x00};
+ unsigned char Command2[6] = {0x80, 0x33, 0x00, 0x00, 0x00, 0x00};
+ unsigned char Command3[6] = {0x80, 0x34, 0x00, 0x00, 0x00, 0x00};
+- const unsigned char Command4[6] = {0x80, 0x2e, 0x00, 0x00, 0x00, 0x00};
+
+ udelay(1000);
+ if ((status = sb1000_start_get_set_command(ioaddr, name)))
+@@ -694,7 +703,7 @@ sb1000_set_PIDs(const int ioaddr[], const char* name, const short PID[])
+ }
+
+
+-static inline void
++static void
+ sb1000_print_status_buffer(const char* name, unsigned char st[],
+ unsigned char buffer[], int size)
+ {
+@@ -725,7 +734,7 @@ sb1000_print_status_buffer(const char* name, unsigned char st[],
+ /* receive a single frame and assemble datagram
+ * (this is the heart of the interrupt routine)
+ */
+-static inline int
++static int
+ sb1000_rx(struct net_device *dev)
+ {
+
+@@ -888,14 +897,15 @@ dropped_frame:
+ return -1;
+ }
+
+-static inline void
++static void
+ sb1000_error_dpc(struct net_device *dev)
+ {
++ static const unsigned char Command0[6] = {0x80, 0x26, 0x00, 0x00, 0x00, 0x00};
++
+ char *name;
+ unsigned char st[5];
+ int ioaddr[2];
+ struct sb1000_private *lp = netdev_priv(dev);
+- const unsigned char Command0[6] = {0x80, 0x26, 0x00, 0x00, 0x00, 0x00};
+ const int ErrorDpcCounterInitialize = 200;
+
+ ioaddr[0] = dev->base_addr;
+@@ -1077,14 +1087,15 @@ sb1000_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ /* SB1000 interrupt handler. */
+ static irqreturn_t sb1000_interrupt(int irq, void *dev_id)
+ {
++ static const unsigned char Command0[6] = {0x80, 0x2c, 0x00, 0x00, 0x00, 0x00};
++ static const unsigned char Command1[6] = {0x80, 0x2e, 0x00, 0x00, 0x00, 0x00};
++
+ char *name;
+ unsigned char st;
+ int ioaddr[2];
+ struct net_device *dev = dev_id;
+ struct sb1000_private *lp = netdev_priv(dev);
+
+- const unsigned char Command0[6] = {0x80, 0x2c, 0x00, 0x00, 0x00, 0x00};
+- const unsigned char Command1[6] = {0x80, 0x2e, 0x00, 0x00, 0x00, 0x00};
+ const int MaxRxErrorCount = 6;
+
+ ioaddr[0] = dev->base_addr;
+diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
+index 7b53d65..888b7de 100644
+--- a/drivers/net/sb1250-mac.c
++++ b/drivers/net/sb1250-mac.c
+@@ -2374,7 +2374,7 @@ static int sbmac_init(struct platform_device *pldev, long long base)
+ dev->name, base, print_mac(mac, eaddr));
+
+ sc->mii_bus.name = sbmac_mdio_string;
+- sc->mii_bus.id = idx;
++ snprintf(sc->mii_bus.id, MII_BUS_ID_SIZE, "%x", idx);
+ sc->mii_bus.priv = sc;
+ sc->mii_bus.read = sbmac_mii_read;
+ sc->mii_bus.write = sbmac_mii_write;
+diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c
+index 15fcee5..f64a860 100644
+--- a/drivers/net/sc92031.c
++++ b/drivers/net/sc92031.c
+@@ -311,7 +311,6 @@ struct sc92031_priv {
+
+ /* for dev->get_stats */
+ long rx_value;
+- struct net_device_stats stats;
+ };
+
+ /* I don't know which registers can be safely read; however, I can guess
+@@ -421,7 +420,7 @@ static void _sc92031_tx_clear(struct net_device *dev)
+
+ while (priv->tx_head - priv->tx_tail > 0) {
+ priv->tx_tail++;
+- priv->stats.tx_dropped++;
++ dev->stats.tx_dropped++;
+ }
+ priv->tx_head = priv->tx_tail = 0;
+ }
+@@ -676,27 +675,27 @@ static void _sc92031_tx_tasklet(struct net_device *dev)
+ priv->tx_tail++;
+
+ if (tx_status & TxStatOK) {
+- priv->stats.tx_bytes += tx_status & 0x1fff;
+- priv->stats.tx_packets++;
++ dev->stats.tx_bytes += tx_status & 0x1fff;
++ dev->stats.tx_packets++;
+ /* Note: TxCarrierLost is always asserted at 100mbps. */
+- priv->stats.collisions += (tx_status >> 22) & 0xf;
++ dev->stats.collisions += (tx_status >> 22) & 0xf;
+ }
+
+ if (tx_status & (TxOutOfWindow | TxAborted)) {
+- priv->stats.tx_errors++;
++ dev->stats.tx_errors++;
+
+ if (tx_status & TxAborted)
+- priv->stats.tx_aborted_errors++;
++ dev->stats.tx_aborted_errors++;
+
+ if (tx_status & TxCarrierLost)
+- priv->stats.tx_carrier_errors++;
++ dev->stats.tx_carrier_errors++;
+
+ if (tx_status & TxOutOfWindow)
+- priv->stats.tx_window_errors++;
++ dev->stats.tx_window_errors++;
+ }
+
+ if (tx_status & TxUnderrun)
+- priv->stats.tx_fifo_errors++;
++ dev->stats.tx_fifo_errors++;
+ }
+
+ if (priv->tx_tail != old_tx_tail)
+@@ -704,27 +703,29 @@ static void _sc92031_tx_tasklet(struct net_device *dev)
+ netif_wake_queue(dev);
+ }
+
+-static void _sc92031_rx_tasklet_error(u32 rx_status,
+- struct sc92031_priv *priv, unsigned rx_size)
++static void _sc92031_rx_tasklet_error(struct net_device *dev,
++ u32 rx_status, unsigned rx_size)
+ {
+ if(rx_size > (MAX_ETH_FRAME_SIZE + 4) || rx_size < 16) {
+- priv->stats.rx_errors++;
+- priv->stats.rx_length_errors++;
++ dev->stats.rx_errors++;
++ dev->stats.rx_length_errors++;
+ }
+
+ if (!(rx_status & RxStatesOK)) {
+- priv->stats.rx_errors++;
++ dev->stats.rx_errors++;
+
+ if (rx_status & (RxHugeFrame | RxSmallFrame))
+- priv->stats.rx_length_errors++;
++ dev->stats.rx_length_errors++;
+
+ if (rx_status & RxBadAlign)
+- priv->stats.rx_frame_errors++;
++ dev->stats.rx_frame_errors++;
+
+ if (!(rx_status & RxCRCOK))
+- priv->stats.rx_crc_errors++;
+- } else
++ dev->stats.rx_crc_errors++;
++ } else {
++ struct sc92031_priv *priv = netdev_priv(dev);
+ priv->rx_loss++;
++ }
+ }
+
+ static void _sc92031_rx_tasklet(struct net_device *dev)
+@@ -783,7 +784,7 @@ static void _sc92031_rx_tasklet(struct net_device *dev)
+ || rx_size > (MAX_ETH_FRAME_SIZE + 4)
+ || rx_size < 16
+ || !(rx_status & RxStatesOK))) {
+- _sc92031_rx_tasklet_error(rx_status, priv, rx_size);
++ _sc92031_rx_tasklet_error(dev, rx_status, rx_size);
+ break;
+ }
+
+@@ -795,7 +796,7 @@ static void _sc92031_rx_tasklet(struct net_device *dev)
+
+ rx_len -= rx_size_align + 4;
+
+- skb = dev_alloc_skb(pkt_size + NET_IP_ALIGN);
++ skb = netdev_alloc_skb(dev, pkt_size + NET_IP_ALIGN);
+ if (unlikely(!skb)) {
+ if (printk_ratelimit())
+ printk(KERN_ERR "%s: Couldn't allocate a skb_buff for a packet of size %u\n",
+@@ -818,11 +819,11 @@ static void _sc92031_rx_tasklet(struct net_device *dev)
+ dev->last_rx = jiffies;
+ netif_rx(skb);
+
+- priv->stats.rx_bytes += pkt_size;
+- priv->stats.rx_packets++;
++ dev->stats.rx_bytes += pkt_size;
++ dev->stats.rx_packets++;
+
+ if (rx_status & Rx_Multicast)
+- priv->stats.multicast++;
++ dev->stats.multicast++;
+
+ next:
+ rx_ring_offset = (rx_ring_offset + rx_size_align) % RX_BUF_LEN;
+@@ -835,13 +836,11 @@ static void _sc92031_rx_tasklet(struct net_device *dev)
+
+ static void _sc92031_link_tasklet(struct net_device *dev)
+ {
+- struct sc92031_priv *priv = netdev_priv(dev);
+-
+ if (_sc92031_check_media(dev))
+ netif_wake_queue(dev);
+ else {
+ netif_stop_queue(dev);
+- priv->stats.tx_carrier_errors++;
++ dev->stats.tx_carrier_errors++;
+ }
+ }
+
+@@ -866,11 +865,11 @@ static void sc92031_tasklet(unsigned long data)
+ _sc92031_rx_tasklet(dev);
+
+ if (intr_status & RxOverflow)
+- priv->stats.rx_errors++;
++ dev->stats.rx_errors++;
+
+ if (intr_status & TimeOut) {
+- priv->stats.rx_errors++;
+- priv->stats.rx_length_errors++;
++ dev->stats.rx_errors++;
++ dev->stats.rx_length_errors++;
+ }
+
+ if (intr_status & (LinkFail | LinkOK))
+@@ -936,38 +935,36 @@ static struct net_device_stats *sc92031_get_stats(struct net_device *dev)
+
+ if (temp == 0xffff) {
+ priv->rx_value += temp;
+- priv->stats.rx_fifo_errors = priv->rx_value;
+- } else {
+- priv->stats.rx_fifo_errors = temp + priv->rx_value;
+- }
++ dev->stats.rx_fifo_errors = priv->rx_value;
++ } else
++ dev->stats.rx_fifo_errors = temp + priv->rx_value;
+
+ spin_unlock_bh(&priv->lock);
+ }
+
+- return &priv->stats;
++ return &dev->stats;
+ }
+
+ static int sc92031_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+- int err = 0;
+ struct sc92031_priv *priv = netdev_priv(dev);
+ void __iomem *port_base = priv->port_base;
+-
+ unsigned len;
+ unsigned entry;
+ u32 tx_status;
+
++ if (skb_padto(skb, ETH_ZLEN))
++ return NETDEV_TX_OK;
++
+ if (unlikely(skb->len > TX_BUF_SIZE)) {
+- err = -EMSGSIZE;
+- priv->stats.tx_dropped++;
++ dev->stats.tx_dropped++;
+ goto out;
+ }
+
+ spin_lock(&priv->lock);
+
+ if (unlikely(!netif_carrier_ok(dev))) {
+- err = -ENOLINK;
+- priv->stats.tx_dropped++;
++ dev->stats.tx_dropped++;
+ goto out_unlock;
+ }
+
+@@ -978,11 +975,6 @@ static int sc92031_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ skb_copy_and_csum_dev(skb, priv->tx_bufs + entry * TX_BUF_SIZE);
+
+ len = skb->len;
+- if (unlikely(len < ETH_ZLEN)) {
+- memset(priv->tx_bufs + entry * TX_BUF_SIZE + len,
+- 0, ETH_ZLEN - len);
+- len = ETH_ZLEN;
+- }
+
+ wmb();
+
+@@ -1009,7 +1001,7 @@ out_unlock:
+ out:
+ dev_kfree_skb(skb);
+
+- return err;
++ return NETDEV_TX_OK;
+ }
+
+ static int sc92031_open(struct net_device *dev)
+diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
+index 78994ed..6261201 100644
+--- a/drivers/net/sgiseeq.c
++++ b/drivers/net/sgiseeq.c
+@@ -825,7 +825,8 @@ static struct platform_driver sgiseeq_driver = {
+ .probe = sgiseeq_probe,
+ .remove = __devexit_p(sgiseeq_remove),
+ .driver = {
+- .name = "sgiseeq"
++ .name = "sgiseeq",
++ .owner = THIS_MODULE,
+ }
+ };
+
+@@ -850,3 +851,4 @@ module_exit(sgiseeq_module_exit);
+ MODULE_DESCRIPTION("SGI Seeq 8003 driver");
+ MODULE_AUTHOR("Linux/MIPS Mailing List <linux-mips at linux-mips.org>");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:sgiseeq");
+diff --git a/drivers/net/sk98lin/Makefile b/drivers/net/sk98lin/Makefile
+deleted file mode 100644
+index afd900d..0000000
+--- a/drivers/net/sk98lin/Makefile
++++ /dev/null
+@@ -1,87 +0,0 @@
+-#
+-# Makefile for the SysKonnect SK-98xx device driver.
+-#
+-
+-
+-#
+-# Standalone driver params
+-# SKPARAM += -DSK_KERNEL_24
+-# SKPARAM += -DSK_KERNEL_24_26
+-# SKPARAM += -DSK_KERNEL_26
+-# SKPARAM += -DSK_KERNEL_22_24
+-
+-obj-$(CONFIG_SK98LIN) += sk98lin.o
+-sk98lin-objs := \
+- skge.o \
+- skethtool.o \
+- skdim.o \
+- skaddr.o \
+- skgehwt.o \
+- skgeinit.o \
+- skgepnmi.o \
+- skgesirq.o \
+- ski2c.o \
+- sklm80.o \
+- skqueue.o \
+- skrlmt.o \
+- sktimer.o \
+- skvpd.o \
+- skxmac2.o
+-
+-# DBGDEF = \
+-# -DDEBUG
+-
+-ifdef DEBUG
+-DBGDEF += \
+--DSK_DEBUG_CHKMOD=0x00000000L \
+--DSK_DEBUG_CHKCAT=0x00000000L
+-endif
+-
+-
+-# **** possible debug modules for SK_DEBUG_CHKMOD *****************
+-# SK_DBGMOD_MERR 0x00000001L /* general module error indication */
+-# SK_DBGMOD_HWM 0x00000002L /* Hardware init module */
+-# SK_DBGMOD_RLMT 0x00000004L /* RLMT module */
+-# SK_DBGMOD_VPD 0x00000008L /* VPD module */
+-# SK_DBGMOD_I2C 0x00000010L /* I2C module */
+-# SK_DBGMOD_PNMI 0x00000020L /* PNMI module */
+-# SK_DBGMOD_CSUM 0x00000040L /* CSUM module */
+-# SK_DBGMOD_ADDR 0x00000080L /* ADDR module */
+-# SK_DBGMOD_DRV 0x00010000L /* DRV module */
+-
+-# **** possible debug categories for SK_DEBUG_CHKCAT **************
+-# *** common modules ***
+-# SK_DBGCAT_INIT 0x00000001L module/driver initialization
+-# SK_DBGCAT_CTRL 0x00000002L controlling: add/rmv MCA/MAC and other controls (IOCTL)
+-# SK_DBGCAT_ERR 0x00000004L error handling paths
+-# SK_DBGCAT_TX 0x00000008L transmit path
+-# SK_DBGCAT_RX 0x00000010L receive path
+-# SK_DBGCAT_IRQ 0x00000020L general IRQ handling
+-# SK_DBGCAT_QUEUE 0x00000040L any queue management
+-# SK_DBGCAT_DUMP 0x00000080L large data output e.g. hex dump
+-# SK_DBGCAT_FATAL 0x00000100L large data output e.g. hex dump
+-
+-# *** driver (file skge.c) ***
+-# SK_DBGCAT_DRV_ENTRY 0x00010000 entry points
+-# SK_DBGCAT_DRV_??? 0x00020000 not used
+-# SK_DBGCAT_DRV_MCA 0x00040000 multicast
+-# SK_DBGCAT_DRV_TX_PROGRESS 0x00080000 tx path
+-# SK_DBGCAT_DRV_RX_PROGRESS 0x00100000 rx path
+-# SK_DBGCAT_DRV_PROGRESS 0x00200000 general runtime
+-# SK_DBGCAT_DRV_??? 0x00400000 not used
+-# SK_DBGCAT_DRV_PROM 0x00800000 promiscuous mode
+-# SK_DBGCAT_DRV_TX_FRAME 0x01000000 display tx frames
+-# SK_DBGCAT_DRV_ERROR 0x02000000 error conditions
+-# SK_DBGCAT_DRV_INT_SRC 0x04000000 interrupts sources
+-# SK_DBGCAT_DRV_EVENT 0x08000000 driver events
+-
+-EXTRA_CFLAGS += -Idrivers/net/sk98lin -DSK_DIAG_SUPPORT -DGENESIS -DYUKON $(DBGDEF) $(SKPARAM)
+-
+-clean:
+- rm -f core *.o *.a *.s
+-
+-
+-
+-
+-
+-
+diff --git a/drivers/net/sk98lin/h/lm80.h b/drivers/net/sk98lin/h/lm80.h
+deleted file mode 100644
+index 4e2dbbf..0000000
+--- a/drivers/net/sk98lin/h/lm80.h
++++ /dev/null
+@@ -1,179 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: lm80.h
+- * Project: Gigabit Ethernet Adapters, Common Modules
+- * Version: $Revision: 1.6 $
+- * Date: $Date: 2003/05/13 17:26:52 $
+- * Purpose: Contains all defines for the LM80 Chip
+- * (National Semiconductor).
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#ifndef __INC_LM80_H
+-#define __INC_LM80_H
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif /* __cplusplus */
+-
+-/* defines ********************************************************************/
+-
+-/*
+- * LM80 register definition
+- *
+- * All registers are 8 bit wide
+- */
+-#define LM80_CFG 0x00 /* Configuration Register */
+-#define LM80_ISRC_1 0x01 /* Interrupt Status Register 1 */
+-#define LM80_ISRC_2 0x02 /* Interrupt Status Register 2 */
+-#define LM80_IMSK_1 0x03 /* Interrupt Mask Register 1 */
+-#define LM80_IMSK_2 0x04 /* Interrupt Mask Register 2 */
+-#define LM80_FAN_CTRL 0x05 /* Fan Devisor/RST#/OS# Register */
+-#define LM80_TEMP_CTRL 0x06 /* OS# Config, Temp Res. Reg */
+- /* 0x07 - 0x1f reserved */
+- /* current values */
+-#define LM80_VT0_IN 0x20 /* current Voltage 0 value */
+-#define LM80_VT1_IN 0x21 /* current Voltage 1 value */
+-#define LM80_VT2_IN 0x22 /* current Voltage 2 value */
+-#define LM80_VT3_IN 0x23 /* current Voltage 3 value */
+-#define LM80_VT4_IN 0x24 /* current Voltage 4 value */
+-#define LM80_VT5_IN 0x25 /* current Voltage 5 value */
+-#define LM80_VT6_IN 0x26 /* current Voltage 6 value */
+-#define LM80_TEMP_IN 0x27 /* current Temperature value */
+-#define LM80_FAN1_IN 0x28 /* current Fan 1 count */
+-#define LM80_FAN2_IN 0x29 /* current Fan 2 count */
+- /* limit values */
+-#define LM80_VT0_HIGH_LIM 0x2a /* high limit val for Voltage 0 */
+-#define LM80_VT0_LOW_LIM 0x2b /* low limit val for Voltage 0 */
+-#define LM80_VT1_HIGH_LIM 0x2c /* high limit val for Voltage 1 */
+-#define LM80_VT1_LOW_LIM 0x2d /* low limit val for Voltage 1 */
+-#define LM80_VT2_HIGH_LIM 0x2e /* high limit val for Voltage 2 */
+-#define LM80_VT2_LOW_LIM 0x2f /* low limit val for Voltage 2 */
+-#define LM80_VT3_HIGH_LIM 0x30 /* high limit val for Voltage 3 */
+-#define LM80_VT3_LOW_LIM 0x31 /* low limit val for Voltage 3 */
+-#define LM80_VT4_HIGH_LIM 0x32 /* high limit val for Voltage 4 */
+-#define LM80_VT4_LOW_LIM 0x33 /* low limit val for Voltage 4 */
+-#define LM80_VT5_HIGH_LIM 0x34 /* high limit val for Voltage 5 */
+-#define LM80_VT5_LOW_LIM 0x35 /* low limit val for Voltage 5 */
+-#define LM80_VT6_HIGH_LIM 0x36 /* high limit val for Voltage 6 */
+-#define LM80_VT6_LOW_LIM 0x37 /* low limit val for Voltage 6 */
+-#define LM80_THOT_LIM_UP 0x38 /* hot temperature limit (high) */
+-#define LM80_THOT_LIM_LO 0x39 /* hot temperature limit (low) */
+-#define LM80_TOS_LIM_UP 0x3a /* OS temperature limit (high) */
+-#define LM80_TOS_LIM_LO 0x3b /* OS temperature limit (low) */
+-#define LM80_FAN1_COUNT_LIM 0x3c /* Fan 1 count limit (high) */
+-#define LM80_FAN2_COUNT_LIM 0x3d /* Fan 2 count limit (low) */
+- /* 0x3e - 0x3f reserved */
+-
+-/*
+- * LM80 bit definitions
+- */
+-
+-/* LM80_CFG Configuration Register */
+-#define LM80_CFG_START (1<<0) /* start monitoring operation */
+-#define LM80_CFG_INT_ENA (1<<1) /* enables the INT# Interrupt output */
+-#define LM80_CFG_INT_POL (1<<2) /* INT# pol: 0 act low, 1 act high */
+-#define LM80_CFG_INT_CLR (1<<3) /* disables INT#/RST_OUT#/OS# outputs */
+-#define LM80_CFG_RESET (1<<4) /* signals a reset */
+-#define LM80_CFG_CHASS_CLR (1<<5) /* clears Chassis Intrusion (CI) pin */
+-#define LM80_CFG_GPO (1<<6) /* drives the GPO# pin */
+-#define LM80_CFG_INIT (1<<7) /* restore power on defaults */
+-
+-/* LM80_ISRC_1 Interrupt Status Register 1 */
+-/* LM80_IMSK_1 Interrupt Mask Register 1 */
+-#define LM80_IS_VT0 (1<<0) /* limit exceeded for Voltage 0 */
+-#define LM80_IS_VT1 (1<<1) /* limit exceeded for Voltage 1 */
+-#define LM80_IS_VT2 (1<<2) /* limit exceeded for Voltage 2 */
+-#define LM80_IS_VT3 (1<<3) /* limit exceeded for Voltage 3 */
+-#define LM80_IS_VT4 (1<<4) /* limit exceeded for Voltage 4 */
+-#define LM80_IS_VT5 (1<<5) /* limit exceeded for Voltage 5 */
+-#define LM80_IS_VT6 (1<<6) /* limit exceeded for Voltage 6 */
+-#define LM80_IS_INT_IN (1<<7) /* state of INT_IN# */
+-
+-/* LM80_ISRC_2 Interrupt Status Register 2 */
+-/* LM80_IMSK_2 Interrupt Mask Register 2 */
+-#define LM80_IS_TEMP (1<<0) /* HOT temperature limit exceeded */
+-#define LM80_IS_BTI (1<<1) /* state of BTI# pin */
+-#define LM80_IS_FAN1 (1<<2) /* count limit exceeded for Fan 1 */
+-#define LM80_IS_FAN2 (1<<3) /* count limit exceeded for Fan 2 */
+-#define LM80_IS_CI (1<<4) /* Chassis Intrusion occured */
+-#define LM80_IS_OS (1<<5) /* OS temperature limit exceeded */
+- /* bit 6 and 7 are reserved in LM80_ISRC_2 */
+-#define LM80_IS_HT_IRQ_MD (1<<6) /* Hot temperature interrupt mode */
+-#define LM80_IS_OT_IRQ_MD (1<<7) /* OS temperature interrupt mode */
+-
+-/* LM80_FAN_CTRL Fan Devisor/RST#/OS# Register */
+-#define LM80_FAN1_MD_SEL (1<<0) /* Fan 1 mode select */
+-#define LM80_FAN2_MD_SEL (1<<1) /* Fan 2 mode select */
+-#define LM80_FAN1_PRM_CTL (3<<2) /* Fan 1 speed control */
+-#define LM80_FAN2_PRM_CTL (3<<4) /* Fan 2 speed control */
+-#define LM80_FAN_OS_ENA (1<<6) /* enable OS mode on RST_OUT#/OS# pins*/
+-#define LM80_FAN_RST_ENA (1<<7) /* sets RST_OUT#/OS# pins in RST mode */
+-
+-/* LM80_TEMP_CTRL OS# Config, Temp Res. Reg */
+-#define LM80_TEMP_OS_STAT (1<<0) /* mirrors the state of RST_OUT#/OS# */
+-#define LM80_TEMP_OS_POL (1<<1) /* select OS# polarity */
+-#define LM80_TEMP_OS_MODE (1<<2) /* selects Interrupt mode */
+-#define LM80_TEMP_RES (1<<3) /* selects 9 or 11 bit temp resulution*/
+-#define LM80_TEMP_LSB (0xf<<4)/* 4 LSBs of 11 bit temp data */
+-#define LM80_TEMP_LSB_9 (1<<7) /* LSB of 9 bit temperature data */
+-
+- /* 0x07 - 0x1f reserved */
+-/* LM80_VT0_IN current Voltage 0 value */
+-/* LM80_VT1_IN current Voltage 1 value */
+-/* LM80_VT2_IN current Voltage 2 value */
+-/* LM80_VT3_IN current Voltage 3 value */
+-/* LM80_VT4_IN current Voltage 4 value */
+-/* LM80_VT5_IN current Voltage 5 value */
+-/* LM80_VT6_IN current Voltage 6 value */
+-/* LM80_TEMP_IN current temperature value */
+-/* LM80_FAN1_IN current Fan 1 count */
+-/* LM80_FAN2_IN current Fan 2 count */
+-/* LM80_VT0_HIGH_LIM high limit val for Voltage 0 */
+-/* LM80_VT0_LOW_LIM low limit val for Voltage 0 */
+-/* LM80_VT1_HIGH_LIM high limit val for Voltage 1 */
+-/* LM80_VT1_LOW_LIM low limit val for Voltage 1 */
+-/* LM80_VT2_HIGH_LIM high limit val for Voltage 2 */
+-/* LM80_VT2_LOW_LIM low limit val for Voltage 2 */
+-/* LM80_VT3_HIGH_LIM high limit val for Voltage 3 */
+-/* LM80_VT3_LOW_LIM low limit val for Voltage 3 */
+-/* LM80_VT4_HIGH_LIM high limit val for Voltage 4 */
+-/* LM80_VT4_LOW_LIM low limit val for Voltage 4 */
+-/* LM80_VT5_HIGH_LIM high limit val for Voltage 5 */
+-/* LM80_VT5_LOW_LIM low limit val for Voltage 5 */
+-/* LM80_VT6_HIGH_LIM high limit val for Voltage 6 */
+-/* LM80_VT6_LOW_LIM low limit val for Voltage 6 */
+-/* LM80_THOT_LIM_UP hot temperature limit (high) */
+-/* LM80_THOT_LIM_LO hot temperature limit (low) */
+-/* LM80_TOS_LIM_UP OS temperature limit (high) */
+-/* LM80_TOS_LIM_LO OS temperature limit (low) */
+-/* LM80_FAN1_COUNT_LIM Fan 1 count limit (high) */
+-/* LM80_FAN2_COUNT_LIM Fan 2 count limit (low) */
+- /* 0x3e - 0x3f reserved */
+-
+-#define LM80_ADDR 0x28 /* LM80 default addr */
+-
+-/* typedefs *******************************************************************/
+-
+-
+-/* function prototypes ********************************************************/
+-
+-#ifdef __cplusplus
+-}
+-#endif /* __cplusplus */
+-
+-#endif /* __INC_LM80_H */
+diff --git a/drivers/net/sk98lin/h/skaddr.h b/drivers/net/sk98lin/h/skaddr.h
+deleted file mode 100644
+index 423ad06..0000000
+--- a/drivers/net/sk98lin/h/skaddr.h
++++ /dev/null
+@@ -1,285 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skaddr.h
+- * Project: Gigabit Ethernet Adapters, ADDR-Modul
+- * Version: $Revision: 1.29 $
+- * Date: $Date: 2003/05/13 16:57:24 $
+- * Purpose: Header file for Address Management (MC, UC, Prom).
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * Description:
+- *
+- * This module is intended to manage multicast addresses and promiscuous mode
+- * on GEnesis adapters.
+- *
+- * Include File Hierarchy:
+- *
+- * "skdrv1st.h"
+- * ...
+- * "sktypes.h"
+- * "skqueue.h"
+- * "skaddr.h"
+- * ...
+- * "skdrv2nd.h"
+- *
+- ******************************************************************************/
+-
+-#ifndef __INC_SKADDR_H
+-#define __INC_SKADDR_H
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif /* cplusplus */
+-
+-/* defines ********************************************************************/
+-
+-#define SK_MAC_ADDR_LEN 6 /* Length of MAC address. */
+-#define SK_MAX_ADDRS 14 /* #Addrs for exact match. */
+-
+-/* ----- Common return values ----- */
+-
+-#define SK_ADDR_SUCCESS 0 /* Function returned successfully. */
+-#define SK_ADDR_ILLEGAL_PORT 100 /* Port number too high. */
+-#define SK_ADDR_TOO_EARLY 101 /* Function called too early. */
+-
+-/* ----- Clear/Add flag bits ----- */
+-
+-#define SK_ADDR_PERMANENT 1 /* RLMT Address */
+-
+-/* ----- Additional Clear flag bits ----- */
+-
+-#define SK_MC_SW_ONLY 2 /* Do not update HW when clearing. */
+-
+-/* ----- Override flag bits ----- */
+-
+-#define SK_ADDR_LOGICAL_ADDRESS 0
+-#define SK_ADDR_VIRTUAL_ADDRESS (SK_ADDR_LOGICAL_ADDRESS) /* old */
+-#define SK_ADDR_PHYSICAL_ADDRESS 1
+-#define SK_ADDR_CLEAR_LOGICAL 2
+-#define SK_ADDR_SET_LOGICAL 4
+-
+-/* ----- Override return values ----- */
+-
+-#define SK_ADDR_OVERRIDE_SUCCESS (SK_ADDR_SUCCESS)
+-#define SK_ADDR_DUPLICATE_ADDRESS 1
+-#define SK_ADDR_MULTICAST_ADDRESS 2
+-
+-/* ----- Partitioning of excact match table ----- */
+-
+-#define SK_ADDR_EXACT_MATCHES 16 /* #Exact match entries. */
+-
+-#define SK_ADDR_FIRST_MATCH_RLMT 1
+-#define SK_ADDR_LAST_MATCH_RLMT 2
+-#define SK_ADDR_FIRST_MATCH_DRV 3
+-#define SK_ADDR_LAST_MATCH_DRV (SK_ADDR_EXACT_MATCHES - 1)
+-
+-/* ----- SkAddrMcAdd/SkAddrMcUpdate return values ----- */
+-
+-#define SK_MC_FILTERING_EXACT 0 /* Exact filtering. */
+-#define SK_MC_FILTERING_INEXACT 1 /* Inexact filtering. */
+-
+-/* ----- Additional SkAddrMcAdd return values ----- */
+-
+-#define SK_MC_ILLEGAL_ADDRESS 2 /* Illegal address. */
+-#define SK_MC_ILLEGAL_PORT 3 /* Illegal port (not the active one). */
+-#define SK_MC_RLMT_OVERFLOW 4 /* Too many RLMT mc addresses. */
+-
+-/* Promiscuous mode bits ----- */
+-
+-#define SK_PROM_MODE_NONE 0 /* Normal receive. */
+-#define SK_PROM_MODE_LLC 1 /* Receive all LLC frames. */
+-#define SK_PROM_MODE_ALL_MC 2 /* Receive all multicast frames. */
+-/* #define SK_PROM_MODE_NON_LLC 4 */ /* Receive all non-LLC frames. */
+-
+-/* Macros */
+-
+-#ifdef OLD_STUFF
+-#ifndef SK_ADDR_EQUAL
+-/*
+- * "&" instead of "&&" allows better optimization on IA-64.
+- * The replacement is safe here, as all bytes exist.
+- */
+-#ifndef SK_ADDR_DWORD_COMPARE
+-#define SK_ADDR_EQUAL(A1,A2) ( \
+- (((SK_U8 *)(A1))[5] == ((SK_U8 *)(A2))[5]) & \
+- (((SK_U8 *)(A1))[4] == ((SK_U8 *)(A2))[4]) & \
+- (((SK_U8 *)(A1))[3] == ((SK_U8 *)(A2))[3]) & \
+- (((SK_U8 *)(A1))[2] == ((SK_U8 *)(A2))[2]) & \
+- (((SK_U8 *)(A1))[1] == ((SK_U8 *)(A2))[1]) & \
+- (((SK_U8 *)(A1))[0] == ((SK_U8 *)(A2))[0]))
+-#else /* SK_ADDR_DWORD_COMPARE */
+-#define SK_ADDR_EQUAL(A1,A2) ( \
+- (*(SK_U32 *)&(((SK_U8 *)(A1))[2]) == *(SK_U32 *)&(((SK_U8 *)(A2))[2])) & \
+- (*(SK_U32 *)&(((SK_U8 *)(A1))[0]) == *(SK_U32 *)&(((SK_U8 *)(A2))[0])))
+-#endif /* SK_ADDR_DWORD_COMPARE */
+-#endif /* SK_ADDR_EQUAL */
+-#endif /* 0 */
+-
+-#ifndef SK_ADDR_EQUAL
+-#ifndef SK_ADDR_DWORD_COMPARE
+-#define SK_ADDR_EQUAL(A1,A2) ( \
+- (((SK_U8 SK_FAR *)(A1))[5] == ((SK_U8 SK_FAR *)(A2))[5]) & \
+- (((SK_U8 SK_FAR *)(A1))[4] == ((SK_U8 SK_FAR *)(A2))[4]) & \
+- (((SK_U8 SK_FAR *)(A1))[3] == ((SK_U8 SK_FAR *)(A2))[3]) & \
+- (((SK_U8 SK_FAR *)(A1))[2] == ((SK_U8 SK_FAR *)(A2))[2]) & \
+- (((SK_U8 SK_FAR *)(A1))[1] == ((SK_U8 SK_FAR *)(A2))[1]) & \
+- (((SK_U8 SK_FAR *)(A1))[0] == ((SK_U8 SK_FAR *)(A2))[0]))
+-#else /* SK_ADDR_DWORD_COMPARE */
+-#define SK_ADDR_EQUAL(A1,A2) ( \
+- (*(SK_U16 SK_FAR *)&(((SK_U8 SK_FAR *)(A1))[4]) == \
+- *(SK_U16 SK_FAR *)&(((SK_U8 SK_FAR *)(A2))[4])) && \
+- (*(SK_U32 SK_FAR *)&(((SK_U8 SK_FAR *)(A1))[0]) == \
+- *(SK_U32 SK_FAR *)&(((SK_U8 SK_FAR *)(A2))[0])))
+-#endif /* SK_ADDR_DWORD_COMPARE */
+-#endif /* SK_ADDR_EQUAL */
+-
+-/* typedefs *******************************************************************/
+-
+-typedef struct s_MacAddr {
+- SK_U8 a[SK_MAC_ADDR_LEN];
+-} SK_MAC_ADDR;
+-
+-
+-/* SK_FILTER is used to ensure alignment of the filter. */
+-typedef union s_InexactFilter {
+- SK_U8 Bytes[8];
+- SK_U64 Val; /* Dummy entry for alignment only. */
+-} SK_FILTER64;
+-
+-
+-typedef struct s_AddrNet SK_ADDR_NET;
+-
+-
+-typedef struct s_AddrPort {
+-
+-/* ----- Public part (read-only) ----- */
+-
+- SK_MAC_ADDR CurrentMacAddress; /* Current physical MAC Address. */
+- SK_MAC_ADDR PermanentMacAddress; /* Permanent physical MAC Address. */
+- int PromMode; /* Promiscuous Mode. */
+-
+-/* ----- Private part ----- */
+-
+- SK_MAC_ADDR PreviousMacAddress; /* Prev. phys. MAC Address. */
+- SK_BOOL CurrentMacAddressSet; /* CurrentMacAddress is set. */
+- SK_U8 Align01;
+-
+- SK_U32 FirstExactMatchRlmt;
+- SK_U32 NextExactMatchRlmt;
+- SK_U32 FirstExactMatchDrv;
+- SK_U32 NextExactMatchDrv;
+- SK_MAC_ADDR Exact[SK_ADDR_EXACT_MATCHES];
+- SK_FILTER64 InexactFilter; /* For 64-bit hash register. */
+- SK_FILTER64 InexactRlmtFilter; /* For 64-bit hash register. */
+- SK_FILTER64 InexactDrvFilter; /* For 64-bit hash register. */
+-} SK_ADDR_PORT;
+-
+-
+-struct s_AddrNet {
+-/* ----- Public part (read-only) ----- */
+-
+- SK_MAC_ADDR CurrentMacAddress; /* Logical MAC Address. */
+- SK_MAC_ADDR PermanentMacAddress; /* Logical MAC Address. */
+-
+-/* ----- Private part ----- */
+-
+- SK_U32 ActivePort; /* View of module ADDR. */
+- SK_BOOL CurrentMacAddressSet; /* CurrentMacAddress is set. */
+- SK_U8 Align01;
+- SK_U16 Align02;
+-};
+-
+-
+-typedef struct s_Addr {
+-
+-/* ----- Public part (read-only) ----- */
+-
+- SK_ADDR_NET Net[SK_MAX_NETS];
+- SK_ADDR_PORT Port[SK_MAX_MACS];
+-
+-/* ----- Private part ----- */
+-} SK_ADDR;
+-
+-/* function prototypes ********************************************************/
+-
+-#ifndef SK_KR_PROTO
+-
+-/* Functions provided by SkAddr */
+-
+-/* ANSI/C++ compliant function prototypes */
+-
+-extern int SkAddrInit(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Level);
+-
+-extern int SkAddrMcClear(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- SK_U32 PortNumber,
+- int Flags);
+-
+-extern int SkAddrMcAdd(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- SK_U32 PortNumber,
+- SK_MAC_ADDR *pMc,
+- int Flags);
+-
+-extern int SkAddrMcUpdate(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- SK_U32 PortNumber);
+-
+-extern int SkAddrOverride(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- SK_U32 PortNumber,
+- SK_MAC_ADDR SK_FAR *pNewAddr,
+- int Flags);
+-
+-extern int SkAddrPromiscuousChange(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- SK_U32 PortNumber,
+- int NewPromMode);
+-
+-#ifndef SK_SLIM
+-extern int SkAddrSwap(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- SK_U32 FromPortNumber,
+- SK_U32 ToPortNumber);
+-#endif
+-
+-#else /* defined(SK_KR_PROTO)) */
+-
+-/* Non-ANSI/C++ compliant function prototypes */
+-
+-#error KR-style prototypes are not yet provided.
+-
+-#endif /* defined(SK_KR_PROTO)) */
+-
+-
+-#ifdef __cplusplus
+-}
+-#endif /* __cplusplus */
+-
+-#endif /* __INC_SKADDR_H */
+diff --git a/drivers/net/sk98lin/h/skcsum.h b/drivers/net/sk98lin/h/skcsum.h
+deleted file mode 100644
+index 6e256bd..0000000
+--- a/drivers/net/sk98lin/h/skcsum.h
++++ /dev/null
+@@ -1,213 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skcsum.h
+- * Project: GEnesis - SysKonnect SK-NET Gigabit Ethernet (SK-98xx)
+- * Version: $Revision: 1.10 $
+- * Date: $Date: 2003/08/20 13:59:57 $
+- * Purpose: Store/verify Internet checksum in send/receive packets.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2001 SysKonnect GmbH.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * Description:
+- *
+- * Public header file for the "GEnesis" common module "CSUM".
+- *
+- * "GEnesis" is an abbreviation of "Gigabit Ethernet Network System in Silicon"
+- * and is the code name of this SysKonnect project.
+- *
+- * Compilation Options:
+- *
+- * SK_USE_CSUM - Define if CSUM is to be used. Otherwise, CSUM will be an
+- * empty module.
+- *
+- * SKCS_OVERWRITE_PROTO - Define to overwrite the default protocol id
+- * definitions. In this case, all SKCS_PROTO_xxx definitions must be made
+- * external.
+- *
+- * SKCS_OVERWRITE_STATUS - Define to overwrite the default return status
+- * definitions. In this case, all SKCS_STATUS_xxx definitions must be made
+- * external.
+- *
+- * Include File Hierarchy:
+- *
+- * "h/skcsum.h"
+- * "h/sktypes.h"
+- * "h/skqueue.h"
+- *
+- ******************************************************************************/
+-
+-#ifndef __INC_SKCSUM_H
+-#define __INC_SKCSUM_H
+-
+-#include "h/sktypes.h"
+-#include "h/skqueue.h"
+-
+-/* defines ********************************************************************/
+-
+-/*
+- * Define the default bit flags for 'SKCS_PACKET_INFO.ProtocolFlags' if no user
+- * overwrite.
+- */
+-#ifndef SKCS_OVERWRITE_PROTO /* User overwrite? */
+-#define SKCS_PROTO_IP 0x1 /* IP (Internet Protocol version 4) */
+-#define SKCS_PROTO_TCP 0x2 /* TCP (Transmission Control Protocol) */
+-#define SKCS_PROTO_UDP 0x4 /* UDP (User Datagram Protocol) */
+-
+-/* Indices for protocol statistics. */
+-#define SKCS_PROTO_STATS_IP 0
+-#define SKCS_PROTO_STATS_UDP 1
+-#define SKCS_PROTO_STATS_TCP 2
+-#define SKCS_NUM_PROTOCOLS 3 /* Number of supported protocols. */
+-#endif /* !SKCS_OVERWRITE_PROTO */
+-
+-/*
+- * Define the default SKCS_STATUS type and values if no user overwrite.
+- *
+- * SKCS_STATUS_UNKNOWN_IP_VERSION - Not an IP v4 frame.
+- * SKCS_STATUS_IP_CSUM_ERROR - IP checksum error.
+- * SKCS_STATUS_IP_CSUM_ERROR_TCP - IP checksum error in TCP frame.
+- * SKCS_STATUS_IP_CSUM_ERROR_UDP - IP checksum error in UDP frame
+- * SKCS_STATUS_IP_FRAGMENT - IP fragment (IP checksum ok).
+- * SKCS_STATUS_IP_CSUM_OK - IP checksum ok (not a TCP or UDP frame).
+- * SKCS_STATUS_TCP_CSUM_ERROR - TCP checksum error (IP checksum ok).
+- * SKCS_STATUS_UDP_CSUM_ERROR - UDP checksum error (IP checksum ok).
+- * SKCS_STATUS_TCP_CSUM_OK - IP and TCP checksum ok.
+- * SKCS_STATUS_UDP_CSUM_OK - IP and UDP checksum ok.
+- * SKCS_STATUS_IP_CSUM_OK_NO_UDP - IP checksum OK and no UDP checksum.
+- */
+-#ifndef SKCS_OVERWRITE_STATUS /* User overwrite? */
+-#define SKCS_STATUS int /* Define status type. */
+-
+-#define SKCS_STATUS_UNKNOWN_IP_VERSION 1
+-#define SKCS_STATUS_IP_CSUM_ERROR 2
+-#define SKCS_STATUS_IP_FRAGMENT 3
+-#define SKCS_STATUS_IP_CSUM_OK 4
+-#define SKCS_STATUS_TCP_CSUM_ERROR 5
+-#define SKCS_STATUS_UDP_CSUM_ERROR 6
+-#define SKCS_STATUS_TCP_CSUM_OK 7
+-#define SKCS_STATUS_UDP_CSUM_OK 8
+-/* needed for Microsoft */
+-#define SKCS_STATUS_IP_CSUM_ERROR_UDP 9
+-#define SKCS_STATUS_IP_CSUM_ERROR_TCP 10
+-/* UDP checksum may be omitted */
+-#define SKCS_STATUS_IP_CSUM_OK_NO_UDP 11
+-#endif /* !SKCS_OVERWRITE_STATUS */
+-
+-/* Clear protocol statistics event. */
+-#define SK_CSUM_EVENT_CLEAR_PROTO_STATS 1
+-
+-/*
+- * Add two values in one's complement.
+- *
+- * Note: One of the two input values may be "longer" than 16-bit, but then the
+- * resulting sum may be 17 bits long. In this case, add zero to the result using
+- * SKCS_OC_ADD() again.
+- *
+- * Result = Value1 + Value2
+- */
+-#define SKCS_OC_ADD(Result, Value1, Value2) { \
+- unsigned long Sum; \
+- \
+- Sum = (unsigned long) (Value1) + (unsigned long) (Value2); \
+- /* Add-in any carry. */ \
+- (Result) = (Sum & 0xffff) + (Sum >> 16); \
+-}
+-
+-/*
+- * Subtract two values in one's complement.
+- *
+- * Result = Value1 - Value2
+- */
+-#define SKCS_OC_SUB(Result, Value1, Value2) \
+- SKCS_OC_ADD((Result), (Value1), ~(Value2) & 0xffff)
+-
+-/* typedefs *******************************************************************/
+-
+-/*
+- * SKCS_PROTO_STATS - The CSUM protocol statistics structure.
+- *
+- * There is one instance of this structure for each protocol supported.
+- */
+-typedef struct s_CsProtocolStatistics {
+- SK_U64 RxOkCts; /* Receive checksum ok. */
+- SK_U64 RxUnableCts; /* Unable to verify receive checksum. */
+- SK_U64 RxErrCts; /* Receive checksum error. */
+- SK_U64 TxOkCts; /* Transmit checksum ok. */
+- SK_U64 TxUnableCts; /* Unable to calculate checksum in hw. */
+-} SKCS_PROTO_STATS;
+-
+-/*
+- * s_Csum - The CSUM module context structure.
+- */
+-typedef struct s_Csum {
+- /* Enabled receive SK_PROTO_XXX bit flags. */
+- unsigned ReceiveFlags[SK_MAX_NETS];
+-#ifdef TX_CSUM
+- unsigned TransmitFlags[SK_MAX_NETS];
+-#endif /* TX_CSUM */
+-
+- /* The protocol statistics structure; one per supported protocol. */
+- SKCS_PROTO_STATS ProtoStats[SK_MAX_NETS][SKCS_NUM_PROTOCOLS];
+-} SK_CSUM;
+-
+-/*
+- * SKCS_PACKET_INFO - The packet information structure.
+- */
+-typedef struct s_CsPacketInfo {
+- /* Bit field specifiying the desired/found protocols. */
+- unsigned ProtocolFlags;
+-
+- /* Length of complete IP header, including any option fields. */
+- unsigned IpHeaderLength;
+-
+- /* IP header checksum. */
+- unsigned IpHeaderChecksum;
+-
+- /* TCP/UDP pseudo header checksum. */
+- unsigned PseudoHeaderChecksum;
+-} SKCS_PACKET_INFO;
+-
+-/* function prototypes ********************************************************/
+-
+-#ifndef SK_CS_CALCULATE_CHECKSUM
+-extern unsigned SkCsCalculateChecksum(
+- void *pData,
+- unsigned Length);
+-#endif /* SK_CS_CALCULATE_CHECKSUM */
+-
+-extern int SkCsEvent(
+- SK_AC *pAc,
+- SK_IOC Ioc,
+- SK_U32 Event,
+- SK_EVPARA Param);
+-
+-extern SKCS_STATUS SkCsGetReceiveInfo(
+- SK_AC *pAc,
+- void *pIpHeader,
+- unsigned Checksum1,
+- unsigned Checksum2,
+- int NetNumber);
+-
+-extern void SkCsSetReceiveFlags(
+- SK_AC *pAc,
+- unsigned ReceiveFlags,
+- unsigned *pChecksum1Offset,
+- unsigned *pChecksum2Offset,
+- int NetNumber);
+-
+-#endif /* __INC_SKCSUM_H */
+diff --git a/drivers/net/sk98lin/h/skdebug.h b/drivers/net/sk98lin/h/skdebug.h
+deleted file mode 100644
+index 3cba171..0000000
+--- a/drivers/net/sk98lin/h/skdebug.h
++++ /dev/null
+@@ -1,74 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skdebug.h
+- * Project: Gigabit Ethernet Adapters, Common Modules
+- * Version: $Revision: 1.14 $
+- * Date: $Date: 2003/05/13 17:26:00 $
+- * Purpose: SK specific DEBUG support
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#ifndef __INC_SKDEBUG_H
+-#define __INC_SKDEBUG_H
+-
+-#ifdef DEBUG
+-#ifndef SK_DBG_MSG
+-#define SK_DBG_MSG(pAC,comp,cat,arg) \
+- if ( ((comp) & SK_DBG_CHKMOD(pAC)) && \
+- ((cat) & SK_DBG_CHKCAT(pAC)) ) { \
+- SK_DBG_PRINTF arg ; \
+- }
+-#endif
+-#else
+-#define SK_DBG_MSG(pAC,comp,lev,arg)
+-#endif
+-
+-/* PLS NOTE:
+- * =========
+- * Due to any restrictions of kernel printf routines do not use other
+- * format identifiers as: %x %d %c %s .
+- * Never use any combined format identifiers such as: %lx %ld in your
+- * printf - argument (arg) because some OS specific kernel printfs may
+- * only support some basic identifiers.
+- */
+-
+-/* Debug modules */
+-
+-#define SK_DBGMOD_MERR 0x00000001L /* general module error indication */
+-#define SK_DBGMOD_HWM 0x00000002L /* Hardware init module */
+-#define SK_DBGMOD_RLMT 0x00000004L /* RLMT module */
+-#define SK_DBGMOD_VPD 0x00000008L /* VPD module */
+-#define SK_DBGMOD_I2C 0x00000010L /* I2C module */
+-#define SK_DBGMOD_PNMI 0x00000020L /* PNMI module */
+-#define SK_DBGMOD_CSUM 0x00000040L /* CSUM module */
+-#define SK_DBGMOD_ADDR 0x00000080L /* ADDR module */
+-#define SK_DBGMOD_PECP 0x00000100L /* PECP module */
+-#define SK_DBGMOD_POWM 0x00000200L /* Power Management module */
+-
+-/* Debug events */
+-
+-#define SK_DBGCAT_INIT 0x00000001L /* module/driver initialization */
+-#define SK_DBGCAT_CTRL 0x00000002L /* controlling devices */
+-#define SK_DBGCAT_ERR 0x00000004L /* error handling paths */
+-#define SK_DBGCAT_TX 0x00000008L /* transmit path */
+-#define SK_DBGCAT_RX 0x00000010L /* receive path */
+-#define SK_DBGCAT_IRQ 0x00000020L /* general IRQ handling */
+-#define SK_DBGCAT_QUEUE 0x00000040L /* any queue management */
+-#define SK_DBGCAT_DUMP 0x00000080L /* large data output e.g. hex dump */
+-#define SK_DBGCAT_FATAL 0x00000100L /* fatal error */
+-
+-#endif /* __INC_SKDEBUG_H */
+diff --git a/drivers/net/sk98lin/h/skdrv1st.h b/drivers/net/sk98lin/h/skdrv1st.h
+deleted file mode 100644
+index 91b8d4f..0000000
+--- a/drivers/net/sk98lin/h/skdrv1st.h
++++ /dev/null
+@@ -1,188 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skdrv1st.h
+- * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.4 $
+- * Date: $Date: 2003/11/12 14:28:14 $
+- * Purpose: First header file for driver and all other modules
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * Description:
+- *
+- * This is the first include file of the driver, which includes all
+- * neccessary system header files and some of the GEnesis header files.
+- * It also defines some basic items.
+- *
+- * Include File Hierarchy:
+- *
+- * see skge.c
+- *
+- ******************************************************************************/
+-
+-#ifndef __INC_SKDRV1ST_H
+-#define __INC_SKDRV1ST_H
+-
+-typedef struct s_AC SK_AC;
+-
+-/* Set card versions */
+-#define SK_FAR
+-
+-/* override some default functions with optimized linux functions */
+-
+-#define SK_PNMI_STORE_U16(p,v) memcpy((char*)(p),(char*)&(v),2)
+-#define SK_PNMI_STORE_U32(p,v) memcpy((char*)(p),(char*)&(v),4)
+-#define SK_PNMI_STORE_U64(p,v) memcpy((char*)(p),(char*)&(v),8)
+-#define SK_PNMI_READ_U16(p,v) memcpy((char*)&(v),(char*)(p),2)
+-#define SK_PNMI_READ_U32(p,v) memcpy((char*)&(v),(char*)(p),4)
+-#define SK_PNMI_READ_U64(p,v) memcpy((char*)&(v),(char*)(p),8)
+-
+-#define SK_ADDR_EQUAL(a1,a2) (!memcmp(a1,a2,6))
+-
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/string.h>
+-#include <linux/errno.h>
+-#include <linux/ioport.h>
+-#include <linux/slab.h>
+-#include <linux/interrupt.h>
+-#include <linux/pci.h>
+-#include <linux/bitops.h>
+-#include <asm/byteorder.h>
+-#include <asm/io.h>
+-#include <asm/irq.h>
+-#include <linux/netdevice.h>
+-#include <linux/etherdevice.h>
+-#include <linux/skbuff.h>
+-
+-#include <linux/init.h>
+-#include <asm/uaccess.h>
+-#include <net/checksum.h>
+-
+-#define SK_CS_CALCULATE_CHECKSUM
+-#ifndef CONFIG_X86_64
+-#define SkCsCalculateChecksum(p,l) ((~ip_compute_csum(p, l)) & 0xffff)
+-#else
+-#define SkCsCalculateChecksum(p,l) ((~ip_fast_csum(p, l)) & 0xffff)
+-#endif
+-
+-#include "h/sktypes.h"
+-#include "h/skerror.h"
+-#include "h/skdebug.h"
+-#include "h/lm80.h"
+-#include "h/xmac_ii.h"
+-
+-#ifdef __LITTLE_ENDIAN
+-#define SK_LITTLE_ENDIAN
+-#else
+-#define SK_BIG_ENDIAN
+-#endif
+-
+-#define SK_NET_DEVICE net_device
+-
+-
+-/* we use gethrtime(), return unit: nanoseconds */
+-#define SK_TICKS_PER_SEC 100
+-
+-#define SK_MEM_MAPPED_IO
+-
+-// #define SK_RLMT_SLOW_LOOKAHEAD
+-
+-#define SK_MAX_MACS 2
+-#define SK_MAX_NETS 2
+-
+-#define SK_IOC char __iomem *
+-
+-typedef struct s_DrvRlmtMbuf SK_MBUF;
+-
+-#define SK_CONST64 INT64_C
+-#define SK_CONSTU64 UINT64_C
+-
+-#define SK_MEMCPY(dest,src,size) memcpy(dest,src,size)
+-#define SK_MEMCMP(s1,s2,size) memcmp(s1,s2,size)
+-#define SK_MEMSET(dest,val,size) memset(dest,val,size)
+-#define SK_STRLEN(pStr) strlen((char*)(pStr))
+-#define SK_STRNCPY(pDest,pSrc,size) strncpy((char*)(pDest),(char*)(pSrc),size)
+-#define SK_STRCMP(pStr1,pStr2) strcmp((char*)(pStr1),(char*)(pStr2))
+-
+-/* macros to access the adapter */
+-#define SK_OUT8(b,a,v) writeb((v), ((b)+(a)))
+-#define SK_OUT16(b,a,v) writew((v), ((b)+(a)))
+-#define SK_OUT32(b,a,v) writel((v), ((b)+(a)))
+-#define SK_IN8(b,a,pv) (*(pv) = readb((b)+(a)))
+-#define SK_IN16(b,a,pv) (*(pv) = readw((b)+(a)))
+-#define SK_IN32(b,a,pv) (*(pv) = readl((b)+(a)))
+-
+-#define int8_t char
+-#define int16_t short
+-#define int32_t long
+-#define int64_t long long
+-#define uint8_t u_char
+-#define uint16_t u_short
+-#define uint32_t u_long
+-#define uint64_t unsigned long long
+-#define t_scalar_t int
+-#define t_uscalar_t unsigned int
+-#define uintptr_t unsigned long
+-
+-#define __CONCAT__(A,B) A##B
+-
+-#define INT32_C(a) __CONCAT__(a,L)
+-#define INT64_C(a) __CONCAT__(a,LL)
+-#define UINT32_C(a) __CONCAT__(a,UL)
+-#define UINT64_C(a) __CONCAT__(a,ULL)
+-
+-#ifdef DEBUG
+-#define SK_DBG_PRINTF printk
+-#ifndef SK_DEBUG_CHKMOD
+-#define SK_DEBUG_CHKMOD 0
+-#endif
+-#ifndef SK_DEBUG_CHKCAT
+-#define SK_DEBUG_CHKCAT 0
+-#endif
+-/* those come from the makefile */
+-#define SK_DBG_CHKMOD(pAC) (SK_DEBUG_CHKMOD)
+-#define SK_DBG_CHKCAT(pAC) (SK_DEBUG_CHKCAT)
+-
+-extern void SkDbgPrintf(const char *format,...);
+-
+-#define SK_DBGMOD_DRV 0x00010000
+-
+-/**** possible driver debug categories ********************************/
+-#define SK_DBGCAT_DRV_ENTRY 0x00010000
+-#define SK_DBGCAT_DRV_SAP 0x00020000
+-#define SK_DBGCAT_DRV_MCA 0x00040000
+-#define SK_DBGCAT_DRV_TX_PROGRESS 0x00080000
+-#define SK_DBGCAT_DRV_RX_PROGRESS 0x00100000
+-#define SK_DBGCAT_DRV_PROGRESS 0x00200000
+-#define SK_DBGCAT_DRV_MSG 0x00400000
+-#define SK_DBGCAT_DRV_PROM 0x00800000
+-#define SK_DBGCAT_DRV_TX_FRAME 0x01000000
+-#define SK_DBGCAT_DRV_ERROR 0x02000000
+-#define SK_DBGCAT_DRV_INT_SRC 0x04000000
+-#define SK_DBGCAT_DRV_EVENT 0x08000000
+-
+-#endif
+-
+-#define SK_ERR_LOG SkErrorLog
+-
+-extern void SkErrorLog(SK_AC*, int, int, char*);
+-
+-#endif
+-
+diff --git a/drivers/net/sk98lin/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h
+deleted file mode 100644
+index 3fa6717..0000000
+--- a/drivers/net/sk98lin/h/skdrv2nd.h
++++ /dev/null
+@@ -1,447 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skdrv2nd.h
+- * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.10 $
+- * Date: $Date: 2003/12/11 16:04:45 $
+- * Purpose: Second header file for driver and all other modules
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * Description:
+- *
+- * This is the second include file of the driver, which includes all other
+- * neccessary files and defines all structures and constants used by the
+- * driver and the common modules.
+- *
+- * Include File Hierarchy:
+- *
+- * see skge.c
+- *
+- ******************************************************************************/
+-
+-#ifndef __INC_SKDRV2ND_H
+-#define __INC_SKDRV2ND_H
+-
+-#include "h/skqueue.h"
+-#include "h/skgehwt.h"
+-#include "h/sktimer.h"
+-#include "h/ski2c.h"
+-#include "h/skgepnmi.h"
+-#include "h/skvpd.h"
+-#include "h/skgehw.h"
+-#include "h/skgeinit.h"
+-#include "h/skaddr.h"
+-#include "h/skgesirq.h"
+-#include "h/skcsum.h"
+-#include "h/skrlmt.h"
+-#include "h/skgedrv.h"
+-
+-
+-extern SK_MBUF *SkDrvAllocRlmtMbuf(SK_AC*, SK_IOC, unsigned);
+-extern void SkDrvFreeRlmtMbuf(SK_AC*, SK_IOC, SK_MBUF*);
+-extern SK_U64 SkOsGetTime(SK_AC*);
+-extern int SkPciReadCfgDWord(SK_AC*, int, SK_U32*);
+-extern int SkPciReadCfgWord(SK_AC*, int, SK_U16*);
+-extern int SkPciReadCfgByte(SK_AC*, int, SK_U8*);
+-extern int SkPciWriteCfgWord(SK_AC*, int, SK_U16);
+-extern int SkPciWriteCfgByte(SK_AC*, int, SK_U8);
+-extern int SkDrvEvent(SK_AC*, SK_IOC IoC, SK_U32, SK_EVPARA);
+-
+-#ifdef SK_DIAG_SUPPORT
+-extern int SkDrvEnterDiagMode(SK_AC *pAc);
+-extern int SkDrvLeaveDiagMode(SK_AC *pAc);
+-#endif
+-
+-struct s_DrvRlmtMbuf {
+- SK_MBUF *pNext; /* Pointer to next RLMT Mbuf. */
+- SK_U8 *pData; /* Data buffer (virtually contig.). */
+- unsigned Size; /* Data buffer size. */
+- unsigned Length; /* Length of packet (<= Size). */
+- SK_U32 PortIdx; /* Receiving/transmitting port. */
+-#ifdef SK_RLMT_MBUF_PRIVATE
+- SK_RLMT_MBUF Rlmt; /* Private part for RLMT. */
+-#endif /* SK_RLMT_MBUF_PRIVATE */
+- struct sk_buff *pOs; /* Pointer to message block */
+-};
+-
+-
+-/*
+- * Time macros
+- */
+-#if SK_TICKS_PER_SEC == 100
+-#define SK_PNMI_HUNDREDS_SEC(t) (t)
+-#else
+-#define SK_PNMI_HUNDREDS_SEC(t) ((((unsigned long)t) * 100) / \
+- (SK_TICKS_PER_SEC))
+-#endif
+-
+-/*
+- * New SkOsGetTime
+- */
+-#define SkOsGetTimeCurrent(pAC, pUsec) {\
+- struct timeval t;\
+- do_gettimeofday(&t);\
+- *pUsec = ((((t.tv_sec) * 1000000L)+t.tv_usec)/10000);\
+-}
+-
+-
+-/*
+- * ioctl definitions
+- */
+-#define SK_IOCTL_BASE (SIOCDEVPRIVATE)
+-#define SK_IOCTL_GETMIB (SK_IOCTL_BASE + 0)
+-#define SK_IOCTL_SETMIB (SK_IOCTL_BASE + 1)
+-#define SK_IOCTL_PRESETMIB (SK_IOCTL_BASE + 2)
+-#define SK_IOCTL_GEN (SK_IOCTL_BASE + 3)
+-#define SK_IOCTL_DIAG (SK_IOCTL_BASE + 4)
+-
+-typedef struct s_IOCTL SK_GE_IOCTL;
+-
+-struct s_IOCTL {
+- char __user * pData;
+- unsigned int Len;
+-};
+-
+-
+-/*
+- * define sizes of descriptor rings in bytes
+- */
+-
+-#define TX_RING_SIZE (8*1024)
+-#define RX_RING_SIZE (24*1024)
+-
+-/*
+- * Buffer size for ethernet packets
+- */
+-#define ETH_BUF_SIZE 1540
+-#define ETH_MAX_MTU 1514
+-#define ETH_MIN_MTU 60
+-#define ETH_MULTICAST_BIT 0x01
+-#define SK_JUMBO_MTU 9000
+-
+-/*
+- * transmit priority selects the queue: LOW=asynchron, HIGH=synchron
+- */
+-#define TX_PRIO_LOW 0
+-#define TX_PRIO_HIGH 1
+-
+-/*
+- * alignment of rx/tx descriptors
+- */
+-#define DESCR_ALIGN 64
+-
+-/*
+- * definitions for pnmi. TODO
+- */
+-#define SK_DRIVER_RESET(pAC, IoC) 0
+-#define SK_DRIVER_SENDEVENT(pAC, IoC) 0
+-#define SK_DRIVER_SELFTEST(pAC, IoC) 0
+-/* For get mtu you must add an own function */
+-#define SK_DRIVER_GET_MTU(pAc,IoC,i) 0
+-#define SK_DRIVER_SET_MTU(pAc,IoC,i,v) 0
+-#define SK_DRIVER_PRESET_MTU(pAc,IoC,i,v) 0
+-
+-/*
+-** Interim definition of SK_DRV_TIMER placed in this file until
+-** common modules have been finalized
+-*/
+-#define SK_DRV_TIMER 11
+-#define SK_DRV_MODERATION_TIMER 1
+-#define SK_DRV_MODERATION_TIMER_LENGTH 1000000 /* 1 second */
+-#define SK_DRV_RX_CLEANUP_TIMER 2
+-#define SK_DRV_RX_CLEANUP_TIMER_LENGTH 1000000 /* 100 millisecs */
+-
+-/*
+-** Definitions regarding transmitting frames
+-** any calculating any checksum.
+-*/
+-#define C_LEN_ETHERMAC_HEADER_DEST_ADDR 6
+-#define C_LEN_ETHERMAC_HEADER_SRC_ADDR 6
+-#define C_LEN_ETHERMAC_HEADER_LENTYPE 2
+-#define C_LEN_ETHERMAC_HEADER ( (C_LEN_ETHERMAC_HEADER_DEST_ADDR) + \
+- (C_LEN_ETHERMAC_HEADER_SRC_ADDR) + \
+- (C_LEN_ETHERMAC_HEADER_LENTYPE) )
+-
+-#define C_LEN_ETHERMTU_MINSIZE 46
+-#define C_LEN_ETHERMTU_MAXSIZE_STD 1500
+-#define C_LEN_ETHERMTU_MAXSIZE_JUMBO 9000
+-
+-#define C_LEN_ETHERNET_MINSIZE ( (C_LEN_ETHERMAC_HEADER) + \
+- (C_LEN_ETHERMTU_MINSIZE) )
+-
+-#define C_OFFSET_IPHEADER C_LEN_ETHERMAC_HEADER
+-#define C_OFFSET_IPHEADER_IPPROTO 9
+-#define C_OFFSET_TCPHEADER_TCPCS 16
+-#define C_OFFSET_UDPHEADER_UDPCS 6
+-
+-#define C_OFFSET_IPPROTO ( (C_LEN_ETHERMAC_HEADER) + \
+- (C_OFFSET_IPHEADER_IPPROTO) )
+-
+-#define C_PROTO_ID_UDP 17 /* refer to RFC 790 or Stevens' */
+-#define C_PROTO_ID_TCP 6 /* TCP/IP illustrated for details */
+-
+-/* TX and RX descriptors *****************************************************/
+-
+-typedef struct s_RxD RXD; /* the receive descriptor */
+-
+-struct s_RxD {
+- volatile SK_U32 RBControl; /* Receive Buffer Control */
+- SK_U32 VNextRxd; /* Next receive descriptor,low dword */
+- SK_U32 VDataLow; /* Receive buffer Addr, low dword */
+- SK_U32 VDataHigh; /* Receive buffer Addr, high dword */
+- SK_U32 FrameStat; /* Receive Frame Status word */
+- SK_U32 TimeStamp; /* Time stamp from XMAC */
+- SK_U32 TcpSums; /* TCP Sum 2 / TCP Sum 1 */
+- SK_U32 TcpSumStarts; /* TCP Sum Start 2 / TCP Sum Start 1 */
+- RXD *pNextRxd; /* Pointer to next Rxd */
+- struct sk_buff *pMBuf; /* Pointer to Linux' socket buffer */
+-};
+-
+-typedef struct s_TxD TXD; /* the transmit descriptor */
+-
+-struct s_TxD {
+- volatile SK_U32 TBControl; /* Transmit Buffer Control */
+- SK_U32 VNextTxd; /* Next transmit descriptor,low dword */
+- SK_U32 VDataLow; /* Transmit Buffer Addr, low dword */
+- SK_U32 VDataHigh; /* Transmit Buffer Addr, high dword */
+- SK_U32 FrameStat; /* Transmit Frame Status Word */
+- SK_U32 TcpSumOfs; /* Reserved / TCP Sum Offset */
+- SK_U16 TcpSumSt; /* TCP Sum Start */
+- SK_U16 TcpSumWr; /* TCP Sum Write */
+- SK_U32 TcpReserved; /* not used */
+- TXD *pNextTxd; /* Pointer to next Txd */
+- struct sk_buff *pMBuf; /* Pointer to Linux' socket buffer */
+-};
+-
+-/* Used interrupt bits in the interrupts source register *********************/
+-
+-#define DRIVER_IRQS ((IS_IRQ_SW) | \
+- (IS_R1_F) |(IS_R2_F) | \
+- (IS_XS1_F) |(IS_XA1_F) | \
+- (IS_XS2_F) |(IS_XA2_F))
+-
+-#define SPECIAL_IRQS ((IS_HW_ERR) |(IS_I2C_READY) | \
+- (IS_EXT_REG) |(IS_TIMINT) | \
+- (IS_PA_TO_RX1) |(IS_PA_TO_RX2) | \
+- (IS_PA_TO_TX1) |(IS_PA_TO_TX2) | \
+- (IS_MAC1) |(IS_LNK_SYNC_M1)| \
+- (IS_MAC2) |(IS_LNK_SYNC_M2)| \
+- (IS_R1_C) |(IS_R2_C) | \
+- (IS_XS1_C) |(IS_XA1_C) | \
+- (IS_XS2_C) |(IS_XA2_C))
+-
+-#define IRQ_MASK ((IS_IRQ_SW) | \
+- (IS_R1_B) |(IS_R1_F) |(IS_R2_B) |(IS_R2_F) | \
+- (IS_XS1_B) |(IS_XS1_F) |(IS_XA1_B)|(IS_XA1_F)| \
+- (IS_XS2_B) |(IS_XS2_F) |(IS_XA2_B)|(IS_XA2_F)| \
+- (IS_HW_ERR) |(IS_I2C_READY)| \
+- (IS_EXT_REG) |(IS_TIMINT) | \
+- (IS_PA_TO_RX1) |(IS_PA_TO_RX2)| \
+- (IS_PA_TO_TX1) |(IS_PA_TO_TX2)| \
+- (IS_MAC1) |(IS_MAC2) | \
+- (IS_R1_C) |(IS_R2_C) | \
+- (IS_XS1_C) |(IS_XA1_C) | \
+- (IS_XS2_C) |(IS_XA2_C))
+-
+-#define IRQ_HWE_MASK (IS_ERR_MSK) /* enable all HW irqs */
+-
+-typedef struct s_DevNet DEV_NET;
+-
+-struct s_DevNet {
+- int PortNr;
+- int NetNr;
+- SK_AC *pAC;
+-};
+-
+-typedef struct s_TxPort TX_PORT;
+-
+-struct s_TxPort {
+- /* the transmit descriptor rings */
+- caddr_t pTxDescrRing; /* descriptor area memory */
+- SK_U64 VTxDescrRing; /* descr. area bus virt. addr. */
+- TXD *pTxdRingHead; /* Head of Tx rings */
+- TXD *pTxdRingTail; /* Tail of Tx rings */
+- TXD *pTxdRingPrev; /* descriptor sent previously */
+- int TxdRingFree; /* # of free entrys */
+- spinlock_t TxDesRingLock; /* serialize descriptor accesses */
+- SK_IOC HwAddr; /* bmu registers address */
+- int PortIndex; /* index number of port (0 or 1) */
+-};
+-
+-typedef struct s_RxPort RX_PORT;
+-
+-struct s_RxPort {
+- /* the receive descriptor rings */
+- caddr_t pRxDescrRing; /* descriptor area memory */
+- SK_U64 VRxDescrRing; /* descr. area bus virt. addr. */
+- RXD *pRxdRingHead; /* Head of Rx rings */
+- RXD *pRxdRingTail; /* Tail of Rx rings */
+- RXD *pRxdRingPrev; /* descriptor given to BMU previously */
+- int RxdRingFree; /* # of free entrys */
+- int RxCsum; /* use receive checksum hardware */
+- spinlock_t RxDesRingLock; /* serialize descriptor accesses */
+- int RxFillLimit; /* limit for buffers in ring */
+- SK_IOC HwAddr; /* bmu registers address */
+- int PortIndex; /* index number of port (0 or 1) */
+-};
+-
+-/* Definitions needed for interrupt moderation *******************************/
+-
+-#define IRQ_EOF_AS_TX ((IS_XA1_F) | (IS_XA2_F))
+-#define IRQ_EOF_SY_TX ((IS_XS1_F) | (IS_XS2_F))
+-#define IRQ_MASK_TX_ONLY ((IRQ_EOF_AS_TX)| (IRQ_EOF_SY_TX))
+-#define IRQ_MASK_RX_ONLY ((IS_R1_F) | (IS_R2_F))
+-#define IRQ_MASK_SP_ONLY (SPECIAL_IRQS)
+-#define IRQ_MASK_TX_RX ((IRQ_MASK_TX_ONLY)| (IRQ_MASK_RX_ONLY))
+-#define IRQ_MASK_SP_RX ((SPECIAL_IRQS) | (IRQ_MASK_RX_ONLY))
+-#define IRQ_MASK_SP_TX ((SPECIAL_IRQS) | (IRQ_MASK_TX_ONLY))
+-#define IRQ_MASK_RX_TX_SP ((SPECIAL_IRQS) | (IRQ_MASK_TX_RX))
+-
+-#define C_INT_MOD_NONE 1
+-#define C_INT_MOD_STATIC 2
+-#define C_INT_MOD_DYNAMIC 4
+-
+-#define C_CLK_FREQ_GENESIS 53215000 /* shorter: 53.125 MHz */
+-#define C_CLK_FREQ_YUKON 78215000 /* shorter: 78.125 MHz */
+-
+-#define C_INTS_PER_SEC_DEFAULT 2000
+-#define C_INT_MOD_ENABLE_PERCENTAGE 50 /* if higher 50% enable */
+-#define C_INT_MOD_DISABLE_PERCENTAGE 50 /* if lower 50% disable */
+-#define C_INT_MOD_IPS_LOWER_RANGE 30
+-#define C_INT_MOD_IPS_UPPER_RANGE 40000
+-
+-
+-typedef struct s_DynIrqModInfo DIM_INFO;
+-struct s_DynIrqModInfo {
+- unsigned long PrevTimeVal;
+- unsigned int PrevSysLoad;
+- unsigned int PrevUsedTime;
+- unsigned int PrevTotalTime;
+- int PrevUsedDescrRatio;
+- int NbrProcessedDescr;
+- SK_U64 PrevPort0RxIntrCts;
+- SK_U64 PrevPort1RxIntrCts;
+- SK_U64 PrevPort0TxIntrCts;
+- SK_U64 PrevPort1TxIntrCts;
+- SK_BOOL ModJustEnabled; /* Moderation just enabled yes/no */
+-
+- int MaxModIntsPerSec; /* Moderation Threshold */
+- int MaxModIntsPerSecUpperLimit; /* Upper limit for DIM */
+- int MaxModIntsPerSecLowerLimit; /* Lower limit for DIM */
+-
+- long MaskIrqModeration; /* ModIrqType (eg. 'TxRx') */
+- SK_BOOL DisplayStats; /* Stats yes/no */
+- SK_BOOL AutoSizing; /* Resize DIM-timer on/off */
+- int IntModTypeSelect; /* EnableIntMod (eg. 'dynamic') */
+-
+- SK_TIMER ModTimer; /* just some timer */
+-};
+-
+-typedef struct s_PerStrm PER_STRM;
+-
+-#define SK_ALLOC_IRQ 0x00000001
+-
+-#ifdef SK_DIAG_SUPPORT
+-#define DIAG_ACTIVE 1
+-#define DIAG_NOTACTIVE 0
+-#endif
+-
+-/****************************************************************************
+- * Per board structure / Adapter Context structure:
+- * Allocated within attach(9e) and freed within detach(9e).
+- * Contains all 'per device' necessary handles, flags, locks etc.:
+- */
+-struct s_AC {
+- SK_GEINIT GIni; /* GE init struct */
+- SK_PNMI Pnmi; /* PNMI data struct */
+- SK_VPD vpd; /* vpd data struct */
+- SK_QUEUE Event; /* Event queue */
+- SK_HWT Hwt; /* Hardware Timer control struct */
+- SK_TIMCTRL Tim; /* Software Timer control struct */
+- SK_I2C I2c; /* I2C relevant data structure */
+- SK_ADDR Addr; /* for Address module */
+- SK_CSUM Csum; /* for checksum module */
+- SK_RLMT Rlmt; /* for rlmt module */
+- spinlock_t SlowPathLock; /* Normal IRQ lock */
+- struct timer_list BlinkTimer; /* for LED blinking */
+- int LedsOn;
+- SK_PNMI_STRUCT_DATA PnmiStruct; /* structure to get all Pnmi-Data */
+- int RlmtMode; /* link check mode to set */
+- int RlmtNets; /* Number of nets */
+-
+- SK_IOC IoBase; /* register set of adapter */
+- int BoardLevel; /* level of active hw init (0-2) */
+-
+- SK_U32 AllocFlag; /* flag allocation of resources */
+- struct pci_dev *PciDev; /* for access to pci config space */
+- struct SK_NET_DEVICE *dev[2]; /* pointer to device struct */
+-
+- int RxBufSize; /* length of receive buffers */
+- struct net_device_stats stats; /* linux 'netstat -i' statistics */
+- int Index; /* internal board index number */
+-
+- /* adapter RAM sizes for queues of active port */
+- int RxQueueSize; /* memory used for receive queue */
+- int TxSQueueSize; /* memory used for sync. tx queue */
+- int TxAQueueSize; /* memory used for async. tx queue */
+-
+- int PromiscCount; /* promiscuous mode counter */
+- int AllMultiCount; /* allmulticast mode counter */
+- int MulticCount; /* number of different MC */
+- /* addresses for this board */
+- /* (may be more than HW can)*/
+-
+- int HWRevision; /* Hardware revision */
+- int ActivePort; /* the active XMAC port */
+- int MaxPorts; /* number of activated ports */
+- int TxDescrPerRing; /* # of descriptors per tx ring */
+- int RxDescrPerRing; /* # of descriptors per rx ring */
+-
+- caddr_t pDescrMem; /* Pointer to the descriptor area */
+- dma_addr_t pDescrMemDMA; /* PCI DMA address of area */
+-
+- /* the port structures with descriptor rings */
+- TX_PORT TxPort[SK_MAX_MACS][2];
+- RX_PORT RxPort[SK_MAX_MACS];
+-
+- SK_BOOL CheckQueue; /* check event queue soon */
+- SK_TIMER DrvCleanupTimer;/* to check for pending descriptors */
+- DIM_INFO DynIrqModInfo; /* all data related to DIM */
+-
+- /* Only for tests */
+- int PortDown;
+- int ChipsetType; /* Chipset family type
+- * 0 == Genesis family support
+- * 1 == Yukon family support
+- */
+-#ifdef SK_DIAG_SUPPORT
+- SK_U32 DiagModeActive; /* is diag active? */
+- SK_BOOL DiagFlowCtrl; /* for control purposes */
+- SK_PNMI_STRUCT_DATA PnmiBackup; /* backup structure for all Pnmi-Data */
+- SK_BOOL WasIfUp[SK_MAX_MACS]; /* for OpenClose while
+- * DIAG is busy with NIC
+- */
+-#endif
+-
+-};
+-
+-
+-#endif /* __INC_SKDRV2ND_H */
+-
+diff --git a/drivers/net/sk98lin/h/skerror.h b/drivers/net/sk98lin/h/skerror.h
+deleted file mode 100644
+index da062f7..0000000
+--- a/drivers/net/sk98lin/h/skerror.h
++++ /dev/null
+@@ -1,55 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skerror.h
+- * Project: Gigabit Ethernet Adapters, Common Modules
+- * Version: $Revision: 1.7 $
+- * Date: $Date: 2003/05/13 17:25:13 $
+- * Purpose: SK specific Error log support
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#ifndef _INC_SKERROR_H_
+-#define _INC_SKERROR_H_
+-
+-/*
+- * Define Error Classes
+- */
+-#define SK_ERRCL_OTHER (0) /* Other error */
+-#define SK_ERRCL_CONFIG (1L<<0) /* Configuration error */
+-#define SK_ERRCL_INIT (1L<<1) /* Initialization error */
+-#define SK_ERRCL_NORES (1L<<2) /* Out of Resources error */
+-#define SK_ERRCL_SW (1L<<3) /* Internal Software error */
+-#define SK_ERRCL_HW (1L<<4) /* Hardware Failure */
+-#define SK_ERRCL_COMM (1L<<5) /* Communication error */
+-
+-
+-/*
+- * Define Error Code Bases
+- */
+-#define SK_ERRBASE_RLMT 100 /* Base Error number for RLMT */
+-#define SK_ERRBASE_HWINIT 200 /* Base Error number for HWInit */
+-#define SK_ERRBASE_VPD 300 /* Base Error number for VPD */
+-#define SK_ERRBASE_PNMI 400 /* Base Error number for PNMI */
+-#define SK_ERRBASE_CSUM 500 /* Base Error number for Checksum */
+-#define SK_ERRBASE_SIRQ 600 /* Base Error number for Special IRQ */
+-#define SK_ERRBASE_I2C 700 /* Base Error number for I2C module */
+-#define SK_ERRBASE_QUEUE 800 /* Base Error number for Scheduler */
+-#define SK_ERRBASE_ADDR 900 /* Base Error number for Address module */
+-#define SK_ERRBASE_PECP 1000 /* Base Error number for PECP */
+-#define SK_ERRBASE_DRV 1100 /* Base Error number for Driver */
+-
+-#endif /* _INC_SKERROR_H_ */
+diff --git a/drivers/net/sk98lin/h/skgedrv.h b/drivers/net/sk98lin/h/skgedrv.h
+deleted file mode 100644
+index 44fd4c3..0000000
+--- a/drivers/net/sk98lin/h/skgedrv.h
++++ /dev/null
+@@ -1,51 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skgedrv.h
+- * Project: Gigabit Ethernet Adapters, Common Modules
+- * Version: $Revision: 1.10 $
+- * Date: $Date: 2003/07/04 12:25:01 $
+- * Purpose: Interface with the driver
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#ifndef __INC_SKGEDRV_H_
+-#define __INC_SKGEDRV_H_
+-
+-/* defines ********************************************************************/
+-
+-/*
+- * Define the driver events.
+- * Usually the events are defined by the destination module.
+- * In case of the driver we put the definition of the events here.
+- */
+-#define SK_DRV_PORT_RESET 1 /* The port needs to be reset */
+-#define SK_DRV_NET_UP 2 /* The net is operational */
+-#define SK_DRV_NET_DOWN 3 /* The net is down */
+-#define SK_DRV_SWITCH_SOFT 4 /* Ports switch with both links connected */
+-#define SK_DRV_SWITCH_HARD 5 /* Port switch due to link failure */
+-#define SK_DRV_RLMT_SEND 6 /* Send a RLMT packet */
+-#define SK_DRV_ADAP_FAIL 7 /* The whole adapter fails */
+-#define SK_DRV_PORT_FAIL 8 /* One port fails */
+-#define SK_DRV_SWITCH_INTERN 9 /* Port switch by the driver itself */
+-#define SK_DRV_POWER_DOWN 10 /* Power down mode */
+-#define SK_DRV_TIMER 11 /* Timer for free use */
+-#ifdef SK_NO_RLMT
+-#define SK_DRV_LINK_UP 12 /* Link Up event for driver */
+-#define SK_DRV_LINK_DOWN 13 /* Link Down event for driver */
+-#endif
+-#define SK_DRV_DOWNSHIFT_DET 14 /* Downshift 4-Pair / 2-Pair (YUKON only) */
+-#endif /* __INC_SKGEDRV_H_ */
+diff --git a/drivers/net/sk98lin/h/skgehw.h b/drivers/net/sk98lin/h/skgehw.h
+deleted file mode 100644
+index f6282b7..0000000
+--- a/drivers/net/sk98lin/h/skgehw.h
++++ /dev/null
+@@ -1,2126 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skgehw.h
+- * Project: Gigabit Ethernet Adapters, Common Modules
+- * Version: $Revision: 1.56 $
+- * Date: $Date: 2003/09/23 09:01:00 $
+- * Purpose: Defines and Macros for the Gigabit Ethernet Adapter Product Family
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#ifndef __INC_SKGEHW_H
+-#define __INC_SKGEHW_H
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif /* __cplusplus */
+-
+-/* defines ********************************************************************/
+-
+-#define BIT_31 (1UL << 31)
+-#define BIT_30 (1L << 30)
+-#define BIT_29 (1L << 29)
+-#define BIT_28 (1L << 28)
+-#define BIT_27 (1L << 27)
+-#define BIT_26 (1L << 26)
+-#define BIT_25 (1L << 25)
+-#define BIT_24 (1L << 24)
+-#define BIT_23 (1L << 23)
+-#define BIT_22 (1L << 22)
+-#define BIT_21 (1L << 21)
+-#define BIT_20 (1L << 20)
+-#define BIT_19 (1L << 19)
+-#define BIT_18 (1L << 18)
+-#define BIT_17 (1L << 17)
+-#define BIT_16 (1L << 16)
+-#define BIT_15 (1L << 15)
+-#define BIT_14 (1L << 14)
+-#define BIT_13 (1L << 13)
+-#define BIT_12 (1L << 12)
+-#define BIT_11 (1L << 11)
+-#define BIT_10 (1L << 10)
+-#define BIT_9 (1L << 9)
+-#define BIT_8 (1L << 8)
+-#define BIT_7 (1L << 7)
+-#define BIT_6 (1L << 6)
+-#define BIT_5 (1L << 5)
+-#define BIT_4 (1L << 4)
+-#define BIT_3 (1L << 3)
+-#define BIT_2 (1L << 2)
+-#define BIT_1 (1L << 1)
+-#define BIT_0 1L
+-
+-#define BIT_15S (1U << 15)
+-#define BIT_14S (1 << 14)
+-#define BIT_13S (1 << 13)
+-#define BIT_12S (1 << 12)
+-#define BIT_11S (1 << 11)
+-#define BIT_10S (1 << 10)
+-#define BIT_9S (1 << 9)
+-#define BIT_8S (1 << 8)
+-#define BIT_7S (1 << 7)
+-#define BIT_6S (1 << 6)
+-#define BIT_5S (1 << 5)
+-#define BIT_4S (1 << 4)
+-#define BIT_3S (1 << 3)
+-#define BIT_2S (1 << 2)
+-#define BIT_1S (1 << 1)
+-#define BIT_0S 1
+-
+-#define SHIFT31(x) ((x) << 31)
+-#define SHIFT30(x) ((x) << 30)
+-#define SHIFT29(x) ((x) << 29)
+-#define SHIFT28(x) ((x) << 28)
+-#define SHIFT27(x) ((x) << 27)
+-#define SHIFT26(x) ((x) << 26)
+-#define SHIFT25(x) ((x) << 25)
+-#define SHIFT24(x) ((x) << 24)
+-#define SHIFT23(x) ((x) << 23)
+-#define SHIFT22(x) ((x) << 22)
+-#define SHIFT21(x) ((x) << 21)
+-#define SHIFT20(x) ((x) << 20)
+-#define SHIFT19(x) ((x) << 19)
+-#define SHIFT18(x) ((x) << 18)
+-#define SHIFT17(x) ((x) << 17)
+-#define SHIFT16(x) ((x) << 16)
+-#define SHIFT15(x) ((x) << 15)
+-#define SHIFT14(x) ((x) << 14)
+-#define SHIFT13(x) ((x) << 13)
+-#define SHIFT12(x) ((x) << 12)
+-#define SHIFT11(x) ((x) << 11)
+-#define SHIFT10(x) ((x) << 10)
+-#define SHIFT9(x) ((x) << 9)
+-#define SHIFT8(x) ((x) << 8)
+-#define SHIFT7(x) ((x) << 7)
+-#define SHIFT6(x) ((x) << 6)
+-#define SHIFT5(x) ((x) << 5)
+-#define SHIFT4(x) ((x) << 4)
+-#define SHIFT3(x) ((x) << 3)
+-#define SHIFT2(x) ((x) << 2)
+-#define SHIFT1(x) ((x) << 1)
+-#define SHIFT0(x) ((x) << 0)
+-
+-/*
+- * Configuration Space header
+- * Since this module is used for different OS', those may be
+- * duplicate on some of them (e.g. Linux). But to keep the
+- * common source, we have to live with this...
+- */
+-#define PCI_VENDOR_ID 0x00 /* 16 bit Vendor ID */
+-#define PCI_DEVICE_ID 0x02 /* 16 bit Device ID */
+-#define PCI_COMMAND 0x04 /* 16 bit Command */
+-#define PCI_STATUS 0x06 /* 16 bit Status */
+-#define PCI_REV_ID 0x08 /* 8 bit Revision ID */
+-#define PCI_CLASS_CODE 0x09 /* 24 bit Class Code */
+-#define PCI_CACHE_LSZ 0x0c /* 8 bit Cache Line Size */
+-#define PCI_LAT_TIM 0x0d /* 8 bit Latency Timer */
+-#define PCI_HEADER_T 0x0e /* 8 bit Header Type */
+-#define PCI_BIST 0x0f /* 8 bit Built-in selftest */
+-#define PCI_BASE_1ST 0x10 /* 32 bit 1st Base address */
+-#define PCI_BASE_2ND 0x14 /* 32 bit 2nd Base address */
+- /* Byte 0x18..0x2b: reserved */
+-#define PCI_SUB_VID 0x2c /* 16 bit Subsystem Vendor ID */
+-#define PCI_SUB_ID 0x2e /* 16 bit Subsystem ID */
+-#define PCI_BASE_ROM 0x30 /* 32 bit Expansion ROM Base Address */
+-#define PCI_CAP_PTR 0x34 /* 8 bit Capabilities Ptr */
+- /* Byte 0x35..0x3b: reserved */
+-#define PCI_IRQ_LINE 0x3c /* 8 bit Interrupt Line */
+-#define PCI_IRQ_PIN 0x3d /* 8 bit Interrupt Pin */
+-#define PCI_MIN_GNT 0x3e /* 8 bit Min_Gnt */
+-#define PCI_MAX_LAT 0x3f /* 8 bit Max_Lat */
+- /* Device Dependent Region */
+-#define PCI_OUR_REG_1 0x40 /* 32 bit Our Register 1 */
+-#define PCI_OUR_REG_2 0x44 /* 32 bit Our Register 2 */
+- /* Power Management Region */
+-#define PCI_PM_CAP_ID 0x48 /* 8 bit Power Management Cap. ID */
+-#define PCI_PM_NITEM 0x49 /* 8 bit Next Item Ptr */
+-#define PCI_PM_CAP_REG 0x4a /* 16 bit Power Management Capabilities */
+-#define PCI_PM_CTL_STS 0x4c /* 16 bit Power Manag. Control/Status */
+- /* Byte 0x4e: reserved */
+-#define PCI_PM_DAT_REG 0x4f /* 8 bit Power Manag. Data Register */
+- /* VPD Region */
+-#define PCI_VPD_CAP_ID 0x50 /* 8 bit VPD Cap. ID */
+-#define PCI_VPD_NITEM 0x51 /* 8 bit Next Item Ptr */
+-#define PCI_VPD_ADR_REG 0x52 /* 16 bit VPD Address Register */
+-#define PCI_VPD_DAT_REG 0x54 /* 32 bit VPD Data Register */
+- /* Byte 0x58..0x59: reserved */
+-#define PCI_SER_LD_CTRL 0x5a /* 16 bit SEEPROM Loader Ctrl (YUKON only) */
+- /* Byte 0x5c..0xff: reserved */
+-
+-/*
+- * I2C Address (PCI Config)
+- *
+- * Note: The temperature and voltage sensors are relocated on a different
+- * I2C bus.
+- */
+-#define I2C_ADDR_VPD 0xa0 /* I2C address for the VPD EEPROM */
+-
+-/*
+- * Define Bits and Values of the registers
+- */
+-/* PCI_COMMAND 16 bit Command */
+- /* Bit 15..11: reserved */
+-#define PCI_INT_DIS BIT_10S /* Interrupt INTx# disable (PCI 2.3) */
+-#define PCI_FBTEN BIT_9S /* Fast Back-To-Back enable */
+-#define PCI_SERREN BIT_8S /* SERR enable */
+-#define PCI_ADSTEP BIT_7S /* Address Stepping */
+-#define PCI_PERREN BIT_6S /* Parity Report Response enable */
+-#define PCI_VGA_SNOOP BIT_5S /* VGA palette snoop */
+-#define PCI_MWIEN BIT_4S /* Memory write an inv cycl ena */
+-#define PCI_SCYCEN BIT_3S /* Special Cycle enable */
+-#define PCI_BMEN BIT_2S /* Bus Master enable */
+-#define PCI_MEMEN BIT_1S /* Memory Space Access enable */
+-#define PCI_IOEN BIT_0S /* I/O Space Access enable */
+-
+-#define PCI_COMMAND_VAL (PCI_FBTEN | PCI_SERREN | PCI_PERREN | PCI_MWIEN |\
+- PCI_BMEN | PCI_MEMEN | PCI_IOEN)
+-
+-/* PCI_STATUS 16 bit Status */
+-#define PCI_PERR BIT_15S /* Parity Error */
+-#define PCI_SERR BIT_14S /* Signaled SERR */
+-#define PCI_RMABORT BIT_13S /* Received Master Abort */
+-#define PCI_RTABORT BIT_12S /* Received Target Abort */
+- /* Bit 11: reserved */
+-#define PCI_DEVSEL (3<<9) /* Bit 10.. 9: DEVSEL Timing */
+-#define PCI_DEV_FAST (0<<9) /* fast */
+-#define PCI_DEV_MEDIUM (1<<9) /* medium */
+-#define PCI_DEV_SLOW (2<<9) /* slow */
+-#define PCI_DATAPERR BIT_8S /* DATA Parity error detected */
+-#define PCI_FB2BCAP BIT_7S /* Fast Back-to-Back Capability */
+-#define PCI_UDF BIT_6S /* User Defined Features */
+-#define PCI_66MHZCAP BIT_5S /* 66 MHz PCI bus clock capable */
+-#define PCI_NEWCAP BIT_4S /* New cap. list implemented */
+-#define PCI_INT_STAT BIT_3S /* Interrupt INTx# Status (PCI 2.3) */
+- /* Bit 2.. 0: reserved */
+-
+-#define PCI_ERRBITS (PCI_PERR | PCI_SERR | PCI_RMABORT | PCI_RTABORT |\
+- PCI_DATAPERR)
+-
+-/* PCI_CLASS_CODE 24 bit Class Code */
+-/* Byte 2: Base Class (02) */
+-/* Byte 1: SubClass (00) */
+-/* Byte 0: Programming Interface (00) */
+-
+-/* PCI_CACHE_LSZ 8 bit Cache Line Size */
+-/* Possible values: 0,2,4,8,16,32,64,128 */
+-
+-/* PCI_HEADER_T 8 bit Header Type */
+-#define PCI_HD_MF_DEV BIT_7S /* 0= single, 1= multi-func dev */
+-#define PCI_HD_TYPE 0x7f /* Bit 6..0: Header Layout 0= normal */
+-
+-/* PCI_BIST 8 bit Built-in selftest */
+-/* Built-in Self test not supported (optional) */
+-
+-/* PCI_BASE_1ST 32 bit 1st Base address */
+-#define PCI_MEMSIZE 0x4000L /* use 16 kB Memory Base */
+-#define PCI_MEMBASE_MSK 0xffffc000L /* Bit 31..14: Memory Base Address */
+-#define PCI_MEMSIZE_MSK 0x00003ff0L /* Bit 13.. 4: Memory Size Req. */
+-#define PCI_PREFEN BIT_3 /* Prefetchable */
+-#define PCI_MEM_TYP (3L<<2) /* Bit 2.. 1: Memory Type */
+-#define PCI_MEM32BIT (0L<<1) /* Base addr anywhere in 32 Bit range */
+-#define PCI_MEM1M (1L<<1) /* Base addr below 1 MegaByte */
+-#define PCI_MEM64BIT (2L<<1) /* Base addr anywhere in 64 Bit range */
+-#define PCI_MEMSPACE BIT_0 /* Memory Space Indicator */
+-
+-/* PCI_BASE_2ND 32 bit 2nd Base address */
+-#define PCI_IOBASE 0xffffff00L /* Bit 31.. 8: I/O Base address */
+-#define PCI_IOSIZE 0x000000fcL /* Bit 7.. 2: I/O Size Requirements */
+- /* Bit 1: reserved */
+-#define PCI_IOSPACE BIT_0 /* I/O Space Indicator */
+-
+-/* PCI_BASE_ROM 32 bit Expansion ROM Base Address */
+-#define PCI_ROMBASE_MSK 0xfffe0000L /* Bit 31..17: ROM Base address */
+-#define PCI_ROMBASE_SIZ (0x1cL<<14) /* Bit 16..14: Treat as Base or Size */
+-#define PCI_ROMSIZE (0x38L<<11) /* Bit 13..11: ROM Size Requirements */
+- /* Bit 10.. 1: reserved */
+-#define PCI_ROMEN BIT_0 /* Address Decode enable */
+-
+-/* Device Dependent Region */
+-/* PCI_OUR_REG_1 32 bit Our Register 1 */
+- /* Bit 31..29: reserved */
+-#define PCI_PHY_COMA BIT_28 /* Set PHY to Coma Mode (YUKON only) */
+-#define PCI_TEST_CAL BIT_27 /* Test PCI buffer calib. (YUKON only) */
+-#define PCI_EN_CAL BIT_26 /* Enable PCI buffer calib. (YUKON only) */
+-#define PCI_VIO BIT_25 /* PCI I/O Voltage, 0 = 3.3V, 1 = 5V */
+-#define PCI_DIS_BOOT BIT_24 /* Disable BOOT via ROM */
+-#define PCI_EN_IO BIT_23 /* Mapping to I/O space */
+-#define PCI_EN_FPROM BIT_22 /* Enable FLASH mapping to memory */
+- /* 1 = Map Flash to memory */
+- /* 0 = Disable addr. dec */
+-#define PCI_PAGESIZE (3L<<20) /* Bit 21..20: FLASH Page Size */
+-#define PCI_PAGE_16 (0L<<20) /* 16 k pages */
+-#define PCI_PAGE_32K (1L<<20) /* 32 k pages */
+-#define PCI_PAGE_64K (2L<<20) /* 64 k pages */
+-#define PCI_PAGE_128K (3L<<20) /* 128 k pages */
+- /* Bit 19: reserved */
+-#define PCI_PAGEREG (7L<<16) /* Bit 18..16: Page Register */
+-#define PCI_NOTAR BIT_15 /* No turnaround cycle */
+-#define PCI_FORCE_BE BIT_14 /* Assert all BEs on MR */
+-#define PCI_DIS_MRL BIT_13 /* Disable Mem Read Line */
+-#define PCI_DIS_MRM BIT_12 /* Disable Mem Read Multiple */
+-#define PCI_DIS_MWI BIT_11 /* Disable Mem Write & Invalidate */
+-#define PCI_DISC_CLS BIT_10 /* Disc: cacheLsz bound */
+-#define PCI_BURST_DIS BIT_9 /* Burst Disable */
+-#define PCI_DIS_PCI_CLK BIT_8 /* Disable PCI clock driving */
+-#define PCI_SKEW_DAS (0xfL<<4) /* Bit 7.. 4: Skew Ctrl, DAS Ext */
+-#define PCI_SKEW_BASE 0xfL /* Bit 3.. 0: Skew Ctrl, Base */
+-
+-
+-/* PCI_OUR_REG_2 32 bit Our Register 2 */
+-#define PCI_VPD_WR_THR (0xffL<<24) /* Bit 31..24: VPD Write Threshold */
+-#define PCI_DEV_SEL (0x7fL<<17) /* Bit 23..17: EEPROM Device Select */
+-#define PCI_VPD_ROM_SZ (7L<<14) /* Bit 16..14: VPD ROM Size */
+- /* Bit 13..12: reserved */
+-#define PCI_PATCH_DIR (0xfL<<8) /* Bit 11.. 8: Ext Patches dir 3..0 */
+-#define PCI_PATCH_DIR_3 BIT_11
+-#define PCI_PATCH_DIR_2 BIT_10
+-#define PCI_PATCH_DIR_1 BIT_9
+-#define PCI_PATCH_DIR_0 BIT_8
+-#define PCI_EXT_PATCHS (0xfL<<4) /* Bit 7.. 4: Extended Patches 3..0 */
+-#define PCI_EXT_PATCH_3 BIT_7
+-#define PCI_EXT_PATCH_2 BIT_6
+-#define PCI_EXT_PATCH_1 BIT_5
+-#define PCI_EXT_PATCH_0 BIT_4
+-#define PCI_EN_DUMMY_RD BIT_3 /* Enable Dummy Read */
+-#define PCI_REV_DESC BIT_2 /* Reverse Desc. Bytes */
+- /* Bit 1: reserved */
+-#define PCI_USEDATA64 BIT_0 /* Use 64Bit Data bus ext */
+-
+-
+-/* Power Management Region */
+-/* PCI_PM_CAP_REG 16 bit Power Management Capabilities */
+-#define PCI_PME_SUP_MSK (0x1f<<11) /* Bit 15..11: PM Event Support Mask */
+-#define PCI_PME_D3C_SUP BIT_15S /* PME from D3cold Support (if Vaux) */
+-#define PCI_PME_D3H_SUP BIT_14S /* PME from D3hot Support */
+-#define PCI_PME_D2_SUP BIT_13S /* PME from D2 Support */
+-#define PCI_PME_D1_SUP BIT_12S /* PME from D1 Support */
+-#define PCI_PME_D0_SUP BIT_11S /* PME from D0 Support */
+-#define PCI_PM_D2_SUP BIT_10S /* D2 Support in 33 MHz mode */
+-#define PCI_PM_D1_SUP BIT_9S /* D1 Support */
+- /* Bit 8.. 6: reserved */
+-#define PCI_PM_DSI BIT_5S /* Device Specific Initialization */
+-#define PCI_PM_APS BIT_4S /* Auxialiary Power Source */
+-#define PCI_PME_CLOCK BIT_3S /* PM Event Clock */
+-#define PCI_PM_VER_MSK 7 /* Bit 2.. 0: PM PCI Spec. version */
+-
+-/* PCI_PM_CTL_STS 16 bit Power Management Control/Status */
+-#define PCI_PME_STATUS BIT_15S /* PME Status (YUKON only) */
+-#define PCI_PM_DAT_SCL (3<<13) /* Bit 14..13: Data Reg. scaling factor */
+-#define PCI_PM_DAT_SEL (0xf<<9) /* Bit 12.. 9: PM data selector field */
+-#define PCI_PME_EN BIT_8S /* Enable PME# generation (YUKON only) */
+- /* Bit 7.. 2: reserved */
+-#define PCI_PM_STATE_MSK 3 /* Bit 1.. 0: Power Management State */
+-
+-#define PCI_PM_STATE_D0 0 /* D0: Operational (default) */
+-#define PCI_PM_STATE_D1 1 /* D1: (YUKON only) */
+-#define PCI_PM_STATE_D2 2 /* D2: (YUKON only) */
+-#define PCI_PM_STATE_D3 3 /* D3: HOT, Power Down and Reset */
+-
+-/* VPD Region */
+-/* PCI_VPD_ADR_REG 16 bit VPD Address Register */
+-#define PCI_VPD_FLAG BIT_15S /* starts VPD rd/wr cycle */
+-#define PCI_VPD_ADR_MSK 0x7fffL /* Bit 14.. 0: VPD address mask */
+-
+-/* Control Register File (Address Map) */
+-
+-/*
+- * Bank 0
+- */
+-#define B0_RAP 0x0000 /* 8 bit Register Address Port */
+- /* 0x0001 - 0x0003: reserved */
+-#define B0_CTST 0x0004 /* 16 bit Control/Status register */
+-#define B0_LED 0x0006 /* 8 Bit LED register */
+-#define B0_POWER_CTRL 0x0007 /* 8 Bit Power Control reg (YUKON only) */
+-#define B0_ISRC 0x0008 /* 32 bit Interrupt Source Register */
+-#define B0_IMSK 0x000c /* 32 bit Interrupt Mask Register */
+-#define B0_HWE_ISRC 0x0010 /* 32 bit HW Error Interrupt Src Reg */
+-#define B0_HWE_IMSK 0x0014 /* 32 bit HW Error Interrupt Mask Reg */
+-#define B0_SP_ISRC 0x0018 /* 32 bit Special Interrupt Source Reg */
+- /* 0x001c: reserved */
+-
+-/* B0 XMAC 1 registers (GENESIS only) */
+-#define B0_XM1_IMSK 0x0020 /* 16 bit r/w XMAC 1 Interrupt Mask Register*/
+- /* 0x0022 - 0x0027: reserved */
+-#define B0_XM1_ISRC 0x0028 /* 16 bit ro XMAC 1 Interrupt Status Reg */
+- /* 0x002a - 0x002f: reserved */
+-#define B0_XM1_PHY_ADDR 0x0030 /* 16 bit r/w XMAC 1 PHY Address Register */
+- /* 0x0032 - 0x0033: reserved */
+-#define B0_XM1_PHY_DATA 0x0034 /* 16 bit r/w XMAC 1 PHY Data Register */
+- /* 0x0036 - 0x003f: reserved */
+-
+-/* B0 XMAC 2 registers (GENESIS only) */
+-#define B0_XM2_IMSK 0x0040 /* 16 bit r/w XMAC 2 Interrupt Mask Register*/
+- /* 0x0042 - 0x0047: reserved */
+-#define B0_XM2_ISRC 0x0048 /* 16 bit ro XMAC 2 Interrupt Status Reg */
+- /* 0x004a - 0x004f: reserved */
+-#define B0_XM2_PHY_ADDR 0x0050 /* 16 bit r/w XMAC 2 PHY Address Register */
+- /* 0x0052 - 0x0053: reserved */
+-#define B0_XM2_PHY_DATA 0x0054 /* 16 bit r/w XMAC 2 PHY Data Register */
+- /* 0x0056 - 0x005f: reserved */
+-
+-/* BMU Control Status Registers */
+-#define B0_R1_CSR 0x0060 /* 32 bit BMU Ctrl/Stat Rx Queue 1 */
+-#define B0_R2_CSR 0x0064 /* 32 bit BMU Ctrl/Stat Rx Queue 2 */
+-#define B0_XS1_CSR 0x0068 /* 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */
+-#define B0_XA1_CSR 0x006c /* 32 bit BMU Ctrl/Stat Async Tx Queue 1*/
+-#define B0_XS2_CSR 0x0070 /* 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */
+-#define B0_XA2_CSR 0x0074 /* 32 bit BMU Ctrl/Stat Async Tx Queue 2*/
+- /* 0x0078 - 0x007f: reserved */
+-
+-/*
+- * Bank 1
+- * - completely empty (this is the RAP Block window)
+- * Note: if RAP = 1 this page is reserved
+- */
+-
+-/*
+- * Bank 2
+- */
+-/* NA reg = 48 bit Network Address Register, 3x16 or 8x8 bit readable */
+-#define B2_MAC_1 0x0100 /* NA reg MAC Address 1 */
+- /* 0x0106 - 0x0107: reserved */
+-#define B2_MAC_2 0x0108 /* NA reg MAC Address 2 */
+- /* 0x010e - 0x010f: reserved */
+-#define B2_MAC_3 0x0110 /* NA reg MAC Address 3 */
+- /* 0x0116 - 0x0117: reserved */
+-#define B2_CONN_TYP 0x0118 /* 8 bit Connector type */
+-#define B2_PMD_TYP 0x0119 /* 8 bit PMD type */
+-#define B2_MAC_CFG 0x011a /* 8 bit MAC Configuration / Chip Revision */
+-#define B2_CHIP_ID 0x011b /* 8 bit Chip Identification Number */
+- /* Eprom registers are currently of no use */
+-#define B2_E_0 0x011c /* 8 bit EPROM Byte 0 (ext. SRAM size */
+-#define B2_E_1 0x011d /* 8 bit EPROM Byte 1 (PHY type) */
+-#define B2_E_2 0x011e /* 8 bit EPROM Byte 2 */
+-#define B2_E_3 0x011f /* 8 bit EPROM Byte 3 */
+-#define B2_FAR 0x0120 /* 32 bit Flash-Prom Addr Reg/Cnt */
+-#define B2_FDP 0x0124 /* 8 bit Flash-Prom Data Port */
+- /* 0x0125 - 0x0127: reserved */
+-#define B2_LD_CTRL 0x0128 /* 8 bit EPROM loader control register */
+-#define B2_LD_TEST 0x0129 /* 8 bit EPROM loader test register */
+- /* 0x012a - 0x012f: reserved */
+-#define B2_TI_INI 0x0130 /* 32 bit Timer Init Value */
+-#define B2_TI_VAL 0x0134 /* 32 bit Timer Value */
+-#define B2_TI_CTRL 0x0138 /* 8 bit Timer Control */
+-#define B2_TI_TEST 0x0139 /* 8 Bit Timer Test */
+- /* 0x013a - 0x013f: reserved */
+-#define B2_IRQM_INI 0x0140 /* 32 bit IRQ Moderation Timer Init Reg.*/
+-#define B2_IRQM_VAL 0x0144 /* 32 bit IRQ Moderation Timer Value */
+-#define B2_IRQM_CTRL 0x0148 /* 8 bit IRQ Moderation Timer Control */
+-#define B2_IRQM_TEST 0x0149 /* 8 bit IRQ Moderation Timer Test */
+-#define B2_IRQM_MSK 0x014c /* 32 bit IRQ Moderation Mask */
+-#define B2_IRQM_HWE_MSK 0x0150 /* 32 bit IRQ Moderation HW Error Mask */
+- /* 0x0154 - 0x0157: reserved */
+-#define B2_TST_CTRL1 0x0158 /* 8 bit Test Control Register 1 */
+-#define B2_TST_CTRL2 0x0159 /* 8 bit Test Control Register 2 */
+- /* 0x015a - 0x015b: reserved */
+-#define B2_GP_IO 0x015c /* 32 bit General Purpose I/O Register */
+-#define B2_I2C_CTRL 0x0160 /* 32 bit I2C HW Control Register */
+-#define B2_I2C_DATA 0x0164 /* 32 bit I2C HW Data Register */
+-#define B2_I2C_IRQ 0x0168 /* 32 bit I2C HW IRQ Register */
+-#define B2_I2C_SW 0x016c /* 32 bit I2C SW Port Register */
+-
+-/* Blink Source Counter (GENESIS only) */
+-#define B2_BSC_INI 0x0170 /* 32 bit Blink Source Counter Init Val */
+-#define B2_BSC_VAL 0x0174 /* 32 bit Blink Source Counter Value */
+-#define B2_BSC_CTRL 0x0178 /* 8 bit Blink Source Counter Control */
+-#define B2_BSC_STAT 0x0179 /* 8 bit Blink Source Counter Status */
+-#define B2_BSC_TST 0x017a /* 16 bit Blink Source Counter Test Reg */
+- /* 0x017c - 0x017f: reserved */
+-
+-/*
+- * Bank 3
+- */
+-/* RAM Random Registers */
+-#define B3_RAM_ADDR 0x0180 /* 32 bit RAM Address, to read or write */
+-#define B3_RAM_DATA_LO 0x0184 /* 32 bit RAM Data Word (low dWord) */
+-#define B3_RAM_DATA_HI 0x0188 /* 32 bit RAM Data Word (high dWord) */
+- /* 0x018c - 0x018f: reserved */
+-
+-/* RAM Interface Registers */
+-/*
+- * The HW-Spec. calls this registers Timeout Value 0..11. But this names are
+- * not usable in SW. Please notice these are NOT real timeouts, these are
+- * the number of qWords transferred continuously.
+- */
+-#define B3_RI_WTO_R1 0x0190 /* 8 bit WR Timeout Queue R1 (TO0) */
+-#define B3_RI_WTO_XA1 0x0191 /* 8 bit WR Timeout Queue XA1 (TO1) */
+-#define B3_RI_WTO_XS1 0x0192 /* 8 bit WR Timeout Queue XS1 (TO2) */
+-#define B3_RI_RTO_R1 0x0193 /* 8 bit RD Timeout Queue R1 (TO3) */
+-#define B3_RI_RTO_XA1 0x0194 /* 8 bit RD Timeout Queue XA1 (TO4) */
+-#define B3_RI_RTO_XS1 0x0195 /* 8 bit RD Timeout Queue XS1 (TO5) */
+-#define B3_RI_WTO_R2 0x0196 /* 8 bit WR Timeout Queue R2 (TO6) */
+-#define B3_RI_WTO_XA2 0x0197 /* 8 bit WR Timeout Queue XA2 (TO7) */
+-#define B3_RI_WTO_XS2 0x0198 /* 8 bit WR Timeout Queue XS2 (TO8) */
+-#define B3_RI_RTO_R2 0x0199 /* 8 bit RD Timeout Queue R2 (TO9) */
+-#define B3_RI_RTO_XA2 0x019a /* 8 bit RD Timeout Queue XA2 (TO10)*/
+-#define B3_RI_RTO_XS2 0x019b /* 8 bit RD Timeout Queue XS2 (TO11)*/
+-#define B3_RI_TO_VAL 0x019c /* 8 bit Current Timeout Count Val */
+- /* 0x019d - 0x019f: reserved */
+-#define B3_RI_CTRL 0x01a0 /* 16 bit RAM Interface Control Register */
+-#define B3_RI_TEST 0x01a2 /* 8 bit RAM Interface Test Register */
+- /* 0x01a3 - 0x01af: reserved */
+-
+-/* MAC Arbiter Registers (GENESIS only) */
+-/* these are the no. of qWord transferred continuously and NOT real timeouts */
+-#define B3_MA_TOINI_RX1 0x01b0 /* 8 bit Timeout Init Val Rx Path MAC 1 */
+-#define B3_MA_TOINI_RX2 0x01b1 /* 8 bit Timeout Init Val Rx Path MAC 2 */
+-#define B3_MA_TOINI_TX1 0x01b2 /* 8 bit Timeout Init Val Tx Path MAC 1 */
+-#define B3_MA_TOINI_TX2 0x01b3 /* 8 bit Timeout Init Val Tx Path MAC 2 */
+-#define B3_MA_TOVAL_RX1 0x01b4 /* 8 bit Timeout Value Rx Path MAC 1 */
+-#define B3_MA_TOVAL_RX2 0x01b5 /* 8 bit Timeout Value Rx Path MAC 1 */
+-#define B3_MA_TOVAL_TX1 0x01b6 /* 8 bit Timeout Value Tx Path MAC 2 */
+-#define B3_MA_TOVAL_TX2 0x01b7 /* 8 bit Timeout Value Tx Path MAC 2 */
+-#define B3_MA_TO_CTRL 0x01b8 /* 16 bit MAC Arbiter Timeout Ctrl Reg */
+-#define B3_MA_TO_TEST 0x01ba /* 16 bit MAC Arbiter Timeout Test Reg */
+- /* 0x01bc - 0x01bf: reserved */
+-#define B3_MA_RCINI_RX1 0x01c0 /* 8 bit Recovery Init Val Rx Path MAC 1 */
+-#define B3_MA_RCINI_RX2 0x01c1 /* 8 bit Recovery Init Val Rx Path MAC 2 */
+-#define B3_MA_RCINI_TX1 0x01c2 /* 8 bit Recovery Init Val Tx Path MAC 1 */
+-#define B3_MA_RCINI_TX2 0x01c3 /* 8 bit Recovery Init Val Tx Path MAC 2 */
+-#define B3_MA_RCVAL_RX1 0x01c4 /* 8 bit Recovery Value Rx Path MAC 1 */
+-#define B3_MA_RCVAL_RX2 0x01c5 /* 8 bit Recovery Value Rx Path MAC 1 */
+-#define B3_MA_RCVAL_TX1 0x01c6 /* 8 bit Recovery Value Tx Path MAC 2 */
+-#define B3_MA_RCVAL_TX2 0x01c7 /* 8 bit Recovery Value Tx Path MAC 2 */
+-#define B3_MA_RC_CTRL 0x01c8 /* 16 bit MAC Arbiter Recovery Ctrl Reg */
+-#define B3_MA_RC_TEST 0x01ca /* 16 bit MAC Arbiter Recovery Test Reg */
+- /* 0x01cc - 0x01cf: reserved */
+-
+-/* Packet Arbiter Registers (GENESIS only) */
+-/* these are real timeouts */
+-#define B3_PA_TOINI_RX1 0x01d0 /* 16 bit Timeout Init Val Rx Path MAC 1 */
+- /* 0x01d2 - 0x01d3: reserved */
+-#define B3_PA_TOINI_RX2 0x01d4 /* 16 bit Timeout Init Val Rx Path MAC 2 */
+- /* 0x01d6 - 0x01d7: reserved */
+-#define B3_PA_TOINI_TX1 0x01d8 /* 16 bit Timeout Init Val Tx Path MAC 1 */
+- /* 0x01da - 0x01db: reserved */
+-#define B3_PA_TOINI_TX2 0x01dc /* 16 bit Timeout Init Val Tx Path MAC 2 */
+- /* 0x01de - 0x01df: reserved */
+-#define B3_PA_TOVAL_RX1 0x01e0 /* 16 bit Timeout Val Rx Path MAC 1 */
+- /* 0x01e2 - 0x01e3: reserved */
+-#define B3_PA_TOVAL_RX2 0x01e4 /* 16 bit Timeout Val Rx Path MAC 2 */
+- /* 0x01e6 - 0x01e7: reserved */
+-#define B3_PA_TOVAL_TX1 0x01e8 /* 16 bit Timeout Val Tx Path MAC 1 */
+- /* 0x01ea - 0x01eb: reserved */
+-#define B3_PA_TOVAL_TX2 0x01ec /* 16 bit Timeout Val Tx Path MAC 2 */
+- /* 0x01ee - 0x01ef: reserved */
+-#define B3_PA_CTRL 0x01f0 /* 16 bit Packet Arbiter Ctrl Register */
+-#define B3_PA_TEST 0x01f2 /* 16 bit Packet Arbiter Test Register */
+- /* 0x01f4 - 0x01ff: reserved */
+-
+-/*
+- * Bank 4 - 5
+- */
+-/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */
+-#define TXA_ITI_INI 0x0200 /* 32 bit Tx Arb Interval Timer Init Val*/
+-#define TXA_ITI_VAL 0x0204 /* 32 bit Tx Arb Interval Timer Value */
+-#define TXA_LIM_INI 0x0208 /* 32 bit Tx Arb Limit Counter Init Val */
+-#define TXA_LIM_VAL 0x020c /* 32 bit Tx Arb Limit Counter Value */
+-#define TXA_CTRL 0x0210 /* 8 bit Tx Arbiter Control Register */
+-#define TXA_TEST 0x0211 /* 8 bit Tx Arbiter Test Register */
+-#define TXA_STAT 0x0212 /* 8 bit Tx Arbiter Status Register */
+- /* 0x0213 - 0x027f: reserved */
+- /* 0x0280 - 0x0292: MAC 2 */
+- /* 0x0213 - 0x027f: reserved */
+-
+-/*
+- * Bank 6
+- */
+-/* External registers (GENESIS only) */
+-#define B6_EXT_REG 0x0300
+-
+-/*
+- * Bank 7
+- */
+-/* This is a copy of the Configuration register file (lower half) */
+-#define B7_CFG_SPC 0x0380
+-
+-/*
+- * Bank 8 - 15
+- */
+-/* Receive and Transmit Queue Registers, use Q_ADDR() to access */
+-#define B8_Q_REGS 0x0400
+-
+-/* Queue Register Offsets, use Q_ADDR() to access */
+-#define Q_D 0x00 /* 8*32 bit Current Descriptor */
+-#define Q_DA_L 0x20 /* 32 bit Current Descriptor Address Low dWord */
+-#define Q_DA_H 0x24 /* 32 bit Current Descriptor Address High dWord */
+-#define Q_AC_L 0x28 /* 32 bit Current Address Counter Low dWord */
+-#define Q_AC_H 0x2c /* 32 bit Current Address Counter High dWord */
+-#define Q_BC 0x30 /* 32 bit Current Byte Counter */
+-#define Q_CSR 0x34 /* 32 bit BMU Control/Status Register */
+-#define Q_F 0x38 /* 32 bit Flag Register */
+-#define Q_T1 0x3c /* 32 bit Test Register 1 */
+-#define Q_T1_TR 0x3c /* 8 bit Test Register 1 Transfer SM */
+-#define Q_T1_WR 0x3d /* 8 bit Test Register 1 Write Descriptor SM */
+-#define Q_T1_RD 0x3e /* 8 bit Test Register 1 Read Descriptor SM */
+-#define Q_T1_SV 0x3f /* 8 bit Test Register 1 Supervisor SM */
+-#define Q_T2 0x40 /* 32 bit Test Register 2 */
+-#define Q_T3 0x44 /* 32 bit Test Register 3 */
+- /* 0x48 - 0x7f: reserved */
+-
+-/*
+- * Bank 16 - 23
+- */
+-/* RAM Buffer Registers */
+-#define B16_RAM_REGS 0x0800
+-
+-/* RAM Buffer Register Offsets, use RB_ADDR() to access */
+-#define RB_START 0x00 /* 32 bit RAM Buffer Start Address */
+-#define RB_END 0x04 /* 32 bit RAM Buffer End Address */
+-#define RB_WP 0x08 /* 32 bit RAM Buffer Write Pointer */
+-#define RB_RP 0x0c /* 32 bit RAM Buffer Read Pointer */
+-#define RB_RX_UTPP 0x10 /* 32 bit Rx Upper Threshold, Pause Pack */
+-#define RB_RX_LTPP 0x14 /* 32 bit Rx Lower Threshold, Pause Pack */
+-#define RB_RX_UTHP 0x18 /* 32 bit Rx Upper Threshold, High Prio */
+-#define RB_RX_LTHP 0x1c /* 32 bit Rx Lower Threshold, High Prio */
+- /* 0x10 - 0x1f: reserved at Tx RAM Buffer Registers */
+-#define RB_PC 0x20 /* 32 bit RAM Buffer Packet Counter */
+-#define RB_LEV 0x24 /* 32 bit RAM Buffer Level Register */
+-#define RB_CTRL 0x28 /* 8 bit RAM Buffer Control Register */
+-#define RB_TST1 0x29 /* 8 bit RAM Buffer Test Register 1 */
+-#define RB_TST2 0x2A /* 8 bit RAM Buffer Test Register 2 */
+- /* 0x2c - 0x7f: reserved */
+-
+-/*
+- * Bank 24
+- */
+-/*
+- * Receive MAC FIFO, Receive LED, and Link_Sync regs (GENESIS only)
+- * use MR_ADDR() to access
+- */
+-#define RX_MFF_EA 0x0c00 /* 32 bit Receive MAC FIFO End Address */
+-#define RX_MFF_WP 0x0c04 /* 32 bit Receive MAC FIFO Write Pointer */
+- /* 0x0c08 - 0x0c0b: reserved */
+-#define RX_MFF_RP 0x0c0c /* 32 bit Receive MAC FIFO Read Pointer */
+-#define RX_MFF_PC 0x0c10 /* 32 bit Receive MAC FIFO Packet Cnt */
+-#define RX_MFF_LEV 0x0c14 /* 32 bit Receive MAC FIFO Level */
+-#define RX_MFF_CTRL1 0x0c18 /* 16 bit Receive MAC FIFO Control Reg 1*/
+-#define RX_MFF_STAT_TO 0x0c1a /* 8 bit Receive MAC Status Timeout */
+-#define RX_MFF_TIST_TO 0x0c1b /* 8 bit Receive MAC Time Stamp Timeout */
+-#define RX_MFF_CTRL2 0x0c1c /* 8 bit Receive MAC FIFO Control Reg 2*/
+-#define RX_MFF_TST1 0x0c1d /* 8 bit Receive MAC FIFO Test Reg 1 */
+-#define RX_MFF_TST2 0x0c1e /* 8 bit Receive MAC FIFO Test Reg 2 */
+- /* 0x0c1f: reserved */
+-#define RX_LED_INI 0x0c20 /* 32 bit Receive LED Cnt Init Value */
+-#define RX_LED_VAL 0x0c24 /* 32 bit Receive LED Cnt Current Value */
+-#define RX_LED_CTRL 0x0c28 /* 8 bit Receive LED Cnt Control Reg */
+-#define RX_LED_TST 0x0c29 /* 8 bit Receive LED Cnt Test Register */
+- /* 0x0c2a - 0x0c2f: reserved */
+-#define LNK_SYNC_INI 0x0c30 /* 32 bit Link Sync Cnt Init Value */
+-#define LNK_SYNC_VAL 0x0c34 /* 32 bit Link Sync Cnt Current Value */
+-#define LNK_SYNC_CTRL 0x0c38 /* 8 bit Link Sync Cnt Control Register */
+-#define LNK_SYNC_TST 0x0c39 /* 8 bit Link Sync Cnt Test Register */
+- /* 0x0c3a - 0x0c3b: reserved */
+-#define LNK_LED_REG 0x0c3c /* 8 bit Link LED Register */
+- /* 0x0c3d - 0x0c3f: reserved */
+-
+-/* Receive GMAC FIFO (YUKON only), use MR_ADDR() to access */
+-#define RX_GMF_EA 0x0c40 /* 32 bit Rx GMAC FIFO End Address */
+-#define RX_GMF_AF_THR 0x0c44 /* 32 bit Rx GMAC FIFO Almost Full Thresh. */
+-#define RX_GMF_CTRL_T 0x0c48 /* 32 bit Rx GMAC FIFO Control/Test */
+-#define RX_GMF_FL_MSK 0x0c4c /* 32 bit Rx GMAC FIFO Flush Mask */
+-#define RX_GMF_FL_THR 0x0c50 /* 32 bit Rx GMAC FIFO Flush Threshold */
+- /* 0x0c54 - 0x0c5f: reserved */
+-#define RX_GMF_WP 0x0c60 /* 32 bit Rx GMAC FIFO Write Pointer */
+- /* 0x0c64 - 0x0c67: reserved */
+-#define RX_GMF_WLEV 0x0c68 /* 32 bit Rx GMAC FIFO Write Level */
+- /* 0x0c6c - 0x0c6f: reserved */
+-#define RX_GMF_RP 0x0c70 /* 32 bit Rx GMAC FIFO Read Pointer */
+- /* 0x0c74 - 0x0c77: reserved */
+-#define RX_GMF_RLEV 0x0c78 /* 32 bit Rx GMAC FIFO Read Level */
+- /* 0x0c7c - 0x0c7f: reserved */
+-
+-/*
+- * Bank 25
+- */
+- /* 0x0c80 - 0x0cbf: MAC 2 */
+- /* 0x0cc0 - 0x0cff: reserved */
+-
+-/*
+- * Bank 26
+- */
+-/*
+- * Transmit MAC FIFO and Transmit LED Registers (GENESIS only),
+- * use MR_ADDR() to access
+- */
+-#define TX_MFF_EA 0x0d00 /* 32 bit Transmit MAC FIFO End Address */
+-#define TX_MFF_WP 0x0d04 /* 32 bit Transmit MAC FIFO WR Pointer */
+-#define TX_MFF_WSP 0x0d08 /* 32 bit Transmit MAC FIFO WR Shadow Ptr */
+-#define TX_MFF_RP 0x0d0c /* 32 bit Transmit MAC FIFO RD Pointer */
+-#define TX_MFF_PC 0x0d10 /* 32 bit Transmit MAC FIFO Packet Cnt */
+-#define TX_MFF_LEV 0x0d14 /* 32 bit Transmit MAC FIFO Level */
+-#define TX_MFF_CTRL1 0x0d18 /* 16 bit Transmit MAC FIFO Ctrl Reg 1 */
+-#define TX_MFF_WAF 0x0d1a /* 8 bit Transmit MAC Wait after flush */
+- /* 0x0c1b: reserved */
+-#define TX_MFF_CTRL2 0x0d1c /* 8 bit Transmit MAC FIFO Ctrl Reg 2 */
+-#define TX_MFF_TST1 0x0d1d /* 8 bit Transmit MAC FIFO Test Reg 1 */
+-#define TX_MFF_TST2 0x0d1e /* 8 bit Transmit MAC FIFO Test Reg 2 */
+- /* 0x0d1f: reserved */
+-#define TX_LED_INI 0x0d20 /* 32 bit Transmit LED Cnt Init Value */
+-#define TX_LED_VAL 0x0d24 /* 32 bit Transmit LED Cnt Current Val */
+-#define TX_LED_CTRL 0x0d28 /* 8 bit Transmit LED Cnt Control Reg */
+-#define TX_LED_TST 0x0d29 /* 8 bit Transmit LED Cnt Test Reg */
+- /* 0x0d2a - 0x0d3f: reserved */
+-
+-/* Transmit GMAC FIFO (YUKON only), use MR_ADDR() to access */
+-#define TX_GMF_EA 0x0d40 /* 32 bit Tx GMAC FIFO End Address */
+-#define TX_GMF_AE_THR 0x0d44 /* 32 bit Tx GMAC FIFO Almost Empty Thresh.*/
+-#define TX_GMF_CTRL_T 0x0d48 /* 32 bit Tx GMAC FIFO Control/Test */
+- /* 0x0d4c - 0x0d5f: reserved */
+-#define TX_GMF_WP 0x0d60 /* 32 bit Tx GMAC FIFO Write Pointer */
+-#define TX_GMF_WSP 0x0d64 /* 32 bit Tx GMAC FIFO Write Shadow Ptr. */
+-#define TX_GMF_WLEV 0x0d68 /* 32 bit Tx GMAC FIFO Write Level */
+- /* 0x0d6c - 0x0d6f: reserved */
+-#define TX_GMF_RP 0x0d70 /* 32 bit Tx GMAC FIFO Read Pointer */
+-#define TX_GMF_RSTP 0x0d74 /* 32 bit Tx GMAC FIFO Restart Pointer */
+-#define TX_GMF_RLEV 0x0d78 /* 32 bit Tx GMAC FIFO Read Level */
+- /* 0x0d7c - 0x0d7f: reserved */
+-
+-/*
+- * Bank 27
+- */
+- /* 0x0d80 - 0x0dbf: MAC 2 */
+- /* 0x0daa - 0x0dff: reserved */
+-
+-/*
+- * Bank 28
+- */
+-/* Descriptor Poll Timer Registers */
+-#define B28_DPT_INI 0x0e00 /* 24 bit Descriptor Poll Timer Init Val */
+-#define B28_DPT_VAL 0x0e04 /* 24 bit Descriptor Poll Timer Curr Val */
+-#define B28_DPT_CTRL 0x0e08 /* 8 bit Descriptor Poll Timer Ctrl Reg */
+- /* 0x0e09: reserved */
+-#define B28_DPT_TST 0x0e0a /* 8 bit Descriptor Poll Timer Test Reg */
+- /* 0x0e0b: reserved */
+-
+-/* Time Stamp Timer Registers (YUKON only) */
+- /* 0x0e10: reserved */
+-#define GMAC_TI_ST_VAL 0x0e14 /* 32 bit Time Stamp Timer Curr Val */
+-#define GMAC_TI_ST_CTRL 0x0e18 /* 8 bit Time Stamp Timer Ctrl Reg */
+- /* 0x0e19: reserved */
+-#define GMAC_TI_ST_TST 0x0e1a /* 8 bit Time Stamp Timer Test Reg */
+- /* 0x0e1b - 0x0e7f: reserved */
+-
+-/*
+- * Bank 29
+- */
+- /* 0x0e80 - 0x0efc: reserved */
+-
+-/*
+- * Bank 30
+- */
+-/* GMAC and GPHY Control Registers (YUKON only) */
+-#define GMAC_CTRL 0x0f00 /* 32 bit GMAC Control Reg */
+-#define GPHY_CTRL 0x0f04 /* 32 bit GPHY Control Reg */
+-#define GMAC_IRQ_SRC 0x0f08 /* 8 bit GMAC Interrupt Source Reg */
+- /* 0x0f09 - 0x0f0b: reserved */
+-#define GMAC_IRQ_MSK 0x0f0c /* 8 bit GMAC Interrupt Mask Reg */
+- /* 0x0f0d - 0x0f0f: reserved */
+-#define GMAC_LINK_CTRL 0x0f10 /* 16 bit Link Control Reg */
+- /* 0x0f14 - 0x0f1f: reserved */
+-
+-/* Wake-up Frame Pattern Match Control Registers (YUKON only) */
+-
+-#define WOL_REG_OFFS 0x20 /* HW-Bug: Address is + 0x20 against spec. */
+-
+-#define WOL_CTRL_STAT 0x0f20 /* 16 bit WOL Control/Status Reg */
+-#define WOL_MATCH_CTL 0x0f22 /* 8 bit WOL Match Control Reg */
+-#define WOL_MATCH_RES 0x0f23 /* 8 bit WOL Match Result Reg */
+-#define WOL_MAC_ADDR_LO 0x0f24 /* 32 bit WOL MAC Address Low */
+-#define WOL_MAC_ADDR_HI 0x0f28 /* 16 bit WOL MAC Address High */
+-#define WOL_PATT_RPTR 0x0f2c /* 8 bit WOL Pattern Read Ptr */
+-
+-/* use this macro to access above registers */
+-#define WOL_REG(Reg) ((Reg) + (pAC->GIni.GIWolOffs))
+-
+-
+-/* WOL Pattern Length Registers (YUKON only) */
+-
+-#define WOL_PATT_LEN_LO 0x0f30 /* 32 bit WOL Pattern Length 3..0 */
+-#define WOL_PATT_LEN_HI 0x0f34 /* 24 bit WOL Pattern Length 6..4 */
+-
+-/* WOL Pattern Counter Registers (YUKON only) */
+-
+-#define WOL_PATT_CNT_0 0x0f38 /* 32 bit WOL Pattern Counter 3..0 */
+-#define WOL_PATT_CNT_4 0x0f3c /* 24 bit WOL Pattern Counter 6..4 */
+- /* 0x0f40 - 0x0f7f: reserved */
+-
+-/*
+- * Bank 31
+- */
+-/* 0x0f80 - 0x0fff: reserved */
+-
+-/*
+- * Bank 32 - 33
+- */
+-#define WOL_PATT_RAM_1 0x1000 /* WOL Pattern RAM Link 1 */
+-
+-/*
+- * Bank 0x22 - 0x3f
+- */
+-/* 0x1100 - 0x1fff: reserved */
+-
+-/*
+- * Bank 0x40 - 0x4f
+- */
+-#define BASE_XMAC_1 0x2000 /* XMAC 1 registers */
+-
+-/*
+- * Bank 0x50 - 0x5f
+- */
+-
+-#define BASE_GMAC_1 0x2800 /* GMAC 1 registers */
+-
+-/*
+- * Bank 0x60 - 0x6f
+- */
+-#define BASE_XMAC_2 0x3000 /* XMAC 2 registers */
+-
+-/*
+- * Bank 0x70 - 0x7f
+- */
+-#define BASE_GMAC_2 0x3800 /* GMAC 2 registers */
+-
+-/*
+- * Control Register Bit Definitions:
+- */
+-/* B0_RAP 8 bit Register Address Port */
+- /* Bit 7: reserved */
+-#define RAP_RAP 0x3f /* Bit 6..0: 0 = block 0,..,6f = block 6f */
+-
+-/* B0_CTST 16 bit Control/Status register */
+- /* Bit 15..14: reserved */
+-#define CS_CLK_RUN_HOT BIT_13S /* CLK_RUN hot m. (YUKON-Lite only) */
+-#define CS_CLK_RUN_RST BIT_12S /* CLK_RUN reset (YUKON-Lite only) */
+-#define CS_CLK_RUN_ENA BIT_11S /* CLK_RUN enable (YUKON-Lite only) */
+-#define CS_VAUX_AVAIL BIT_10S /* VAUX available (YUKON only) */
+-#define CS_BUS_CLOCK BIT_9S /* Bus Clock 0/1 = 33/66 MHz */
+-#define CS_BUS_SLOT_SZ BIT_8S /* Slot Size 0/1 = 32/64 bit slot */
+-#define CS_ST_SW_IRQ BIT_7S /* Set IRQ SW Request */
+-#define CS_CL_SW_IRQ BIT_6S /* Clear IRQ SW Request */
+-#define CS_STOP_DONE BIT_5S /* Stop Master is finished */
+-#define CS_STOP_MAST BIT_4S /* Command Bit to stop the master */
+-#define CS_MRST_CLR BIT_3S /* Clear Master reset */
+-#define CS_MRST_SET BIT_2S /* Set Master reset */
+-#define CS_RST_CLR BIT_1S /* Clear Software reset */
+-#define CS_RST_SET BIT_0S /* Set Software reset */
+-
+-/* B0_LED 8 Bit LED register */
+- /* Bit 7.. 2: reserved */
+-#define LED_STAT_ON BIT_1S /* Status LED on */
+-#define LED_STAT_OFF BIT_0S /* Status LED off */
+-
+-/* B0_POWER_CTRL 8 Bit Power Control reg (YUKON only) */
+-#define PC_VAUX_ENA BIT_7 /* Switch VAUX Enable */
+-#define PC_VAUX_DIS BIT_6 /* Switch VAUX Disable */
+-#define PC_VCC_ENA BIT_5 /* Switch VCC Enable */
+-#define PC_VCC_DIS BIT_4 /* Switch VCC Disable */
+-#define PC_VAUX_ON BIT_3 /* Switch VAUX On */
+-#define PC_VAUX_OFF BIT_2 /* Switch VAUX Off */
+-#define PC_VCC_ON BIT_1 /* Switch VCC On */
+-#define PC_VCC_OFF BIT_0 /* Switch VCC Off */
+-
+-/* B0_ISRC 32 bit Interrupt Source Register */
+-/* B0_IMSK 32 bit Interrupt Mask Register */
+-/* B0_SP_ISRC 32 bit Special Interrupt Source Reg */
+-/* B2_IRQM_MSK 32 bit IRQ Moderation Mask */
+-#define IS_ALL_MSK 0xbfffffffUL /* All Interrupt bits */
+-#define IS_HW_ERR BIT_31 /* Interrupt HW Error */
+- /* Bit 30: reserved */
+-#define IS_PA_TO_RX1 BIT_29 /* Packet Arb Timeout Rx1 */
+-#define IS_PA_TO_RX2 BIT_28 /* Packet Arb Timeout Rx2 */
+-#define IS_PA_TO_TX1 BIT_27 /* Packet Arb Timeout Tx1 */
+-#define IS_PA_TO_TX2 BIT_26 /* Packet Arb Timeout Tx2 */
+-#define IS_I2C_READY BIT_25 /* IRQ on end of I2C Tx */
+-#define IS_IRQ_SW BIT_24 /* SW forced IRQ */
+-#define IS_EXT_REG BIT_23 /* IRQ from LM80 or PHY (GENESIS only) */
+- /* IRQ from PHY (YUKON only) */
+-#define IS_TIMINT BIT_22 /* IRQ from Timer */
+-#define IS_MAC1 BIT_21 /* IRQ from MAC 1 */
+-#define IS_LNK_SYNC_M1 BIT_20 /* Link Sync Cnt wrap MAC 1 */
+-#define IS_MAC2 BIT_19 /* IRQ from MAC 2 */
+-#define IS_LNK_SYNC_M2 BIT_18 /* Link Sync Cnt wrap MAC 2 */
+-/* Receive Queue 1 */
+-#define IS_R1_B BIT_17 /* Q_R1 End of Buffer */
+-#define IS_R1_F BIT_16 /* Q_R1 End of Frame */
+-#define IS_R1_C BIT_15 /* Q_R1 Encoding Error */
+-/* Receive Queue 2 */
+-#define IS_R2_B BIT_14 /* Q_R2 End of Buffer */
+-#define IS_R2_F BIT_13 /* Q_R2 End of Frame */
+-#define IS_R2_C BIT_12 /* Q_R2 Encoding Error */
+-/* Synchronous Transmit Queue 1 */
+-#define IS_XS1_B BIT_11 /* Q_XS1 End of Buffer */
+-#define IS_XS1_F BIT_10 /* Q_XS1 End of Frame */
+-#define IS_XS1_C BIT_9 /* Q_XS1 Encoding Error */
+-/* Asynchronous Transmit Queue 1 */
+-#define IS_XA1_B BIT_8 /* Q_XA1 End of Buffer */
+-#define IS_XA1_F BIT_7 /* Q_XA1 End of Frame */
+-#define IS_XA1_C BIT_6 /* Q_XA1 Encoding Error */
+-/* Synchronous Transmit Queue 2 */
+-#define IS_XS2_B BIT_5 /* Q_XS2 End of Buffer */
+-#define IS_XS2_F BIT_4 /* Q_XS2 End of Frame */
+-#define IS_XS2_C BIT_3 /* Q_XS2 Encoding Error */
+-/* Asynchronous Transmit Queue 2 */
+-#define IS_XA2_B BIT_2 /* Q_XA2 End of Buffer */
+-#define IS_XA2_F BIT_1 /* Q_XA2 End of Frame */
+-#define IS_XA2_C BIT_0 /* Q_XA2 Encoding Error */
+-
+-
+-/* B0_HWE_ISRC 32 bit HW Error Interrupt Src Reg */
+-/* B0_HWE_IMSK 32 bit HW Error Interrupt Mask Reg */
+-/* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */
+-#define IS_ERR_MSK 0x00000fffL /* All Error bits */
+- /* Bit 31..14: reserved */
+-#define IS_IRQ_TIST_OV BIT_13 /* Time Stamp Timer Overflow (YUKON only) */
+-#define IS_IRQ_SENSOR BIT_12 /* IRQ from Sensor (YUKON only) */
+-#define IS_IRQ_MST_ERR BIT_11 /* IRQ master error detected */
+-#define IS_IRQ_STAT BIT_10 /* IRQ status exception */
+-#define IS_NO_STAT_M1 BIT_9 /* No Rx Status from MAC 1 */
+-#define IS_NO_STAT_M2 BIT_8 /* No Rx Status from MAC 2 */
+-#define IS_NO_TIST_M1 BIT_7 /* No Time Stamp from MAC 1 */
+-#define IS_NO_TIST_M2 BIT_6 /* No Time Stamp from MAC 2 */
+-#define IS_RAM_RD_PAR BIT_5 /* RAM Read Parity Error */
+-#define IS_RAM_WR_PAR BIT_4 /* RAM Write Parity Error */
+-#define IS_M1_PAR_ERR BIT_3 /* MAC 1 Parity Error */
+-#define IS_M2_PAR_ERR BIT_2 /* MAC 2 Parity Error */
+-#define IS_R1_PAR_ERR BIT_1 /* Queue R1 Parity Error */
+-#define IS_R2_PAR_ERR BIT_0 /* Queue R2 Parity Error */
+-
+-/* B2_CONN_TYP 8 bit Connector type */
+-/* B2_PMD_TYP 8 bit PMD type */
+-/* Values of connector and PMD type comply to SysKonnect internal std */
+-
+-/* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */
+-#define CFG_CHIP_R_MSK (0xf<<4) /* Bit 7.. 4: Chip Revision */
+- /* Bit 3.. 2: reserved */
+-#define CFG_DIS_M2_CLK BIT_1S /* Disable Clock for 2nd MAC */
+-#define CFG_SNG_MAC BIT_0S /* MAC Config: 0=2 MACs / 1=1 MAC*/
+-
+-/* B2_CHIP_ID 8 bit Chip Identification Number */
+-#define CHIP_ID_GENESIS 0x0a /* Chip ID for GENESIS */
+-#define CHIP_ID_YUKON 0xb0 /* Chip ID for YUKON */
+-#define CHIP_ID_YUKON_LITE 0xb1 /* Chip ID for YUKON-Lite (Rev. A1-A3) */
+-#define CHIP_ID_YUKON_LP 0xb2 /* Chip ID for YUKON-LP */
+-
+-#define CHIP_REV_YU_LITE_A1 3 /* Chip Rev. for YUKON-Lite A1,A2 */
+-#define CHIP_REV_YU_LITE_A3 7 /* Chip Rev. for YUKON-Lite A3 */
+-
+-/* B2_FAR 32 bit Flash-Prom Addr Reg/Cnt */
+-#define FAR_ADDR 0x1ffffL /* Bit 16.. 0: FPROM Address mask */
+-
+-/* B2_LD_CTRL 8 bit EPROM loader control register */
+-/* Bits are currently reserved */
+-
+-/* B2_LD_TEST 8 bit EPROM loader test register */
+- /* Bit 7.. 4: reserved */
+-#define LD_T_ON BIT_3S /* Loader Test mode on */
+-#define LD_T_OFF BIT_2S /* Loader Test mode off */
+-#define LD_T_STEP BIT_1S /* Decrement FPROM addr. Counter */
+-#define LD_START BIT_0S /* Start loading FPROM */
+-
+-/*
+- * Timer Section
+- */
+-/* B2_TI_CTRL 8 bit Timer control */
+-/* B2_IRQM_CTRL 8 bit IRQ Moderation Timer Control */
+- /* Bit 7.. 3: reserved */
+-#define TIM_START BIT_2S /* Start Timer */
+-#define TIM_STOP BIT_1S /* Stop Timer */
+-#define TIM_CLR_IRQ BIT_0S /* Clear Timer IRQ (!IRQM) */
+-
+-/* B2_TI_TEST 8 Bit Timer Test */
+-/* B2_IRQM_TEST 8 bit IRQ Moderation Timer Test */
+-/* B28_DPT_TST 8 bit Descriptor Poll Timer Test Reg */
+- /* Bit 7.. 3: reserved */
+-#define TIM_T_ON BIT_2S /* Test mode on */
+-#define TIM_T_OFF BIT_1S /* Test mode off */
+-#define TIM_T_STEP BIT_0S /* Test step */
+-
+-/* B28_DPT_INI 32 bit Descriptor Poll Timer Init Val */
+-/* B28_DPT_VAL 32 bit Descriptor Poll Timer Curr Val */
+- /* Bit 31..24: reserved */
+-#define DPT_MSK 0x00ffffffL /* Bit 23.. 0: Desc Poll Timer Bits */
+-
+-/* B28_DPT_CTRL 8 bit Descriptor Poll Timer Ctrl Reg */
+- /* Bit 7.. 2: reserved */
+-#define DPT_START BIT_1S /* Start Descriptor Poll Timer */
+-#define DPT_STOP BIT_0S /* Stop Descriptor Poll Timer */
+-
+-/* B2_E_3 8 bit lower 4 bits used for HW self test result */
+-#define B2_E3_RES_MASK 0x0f
+-
+-/* B2_TST_CTRL1 8 bit Test Control Register 1 */
+-#define TST_FRC_DPERR_MR BIT_7S /* force DATAPERR on MST RD */
+-#define TST_FRC_DPERR_MW BIT_6S /* force DATAPERR on MST WR */
+-#define TST_FRC_DPERR_TR BIT_5S /* force DATAPERR on TRG RD */
+-#define TST_FRC_DPERR_TW BIT_4S /* force DATAPERR on TRG WR */
+-#define TST_FRC_APERR_M BIT_3S /* force ADDRPERR on MST */
+-#define TST_FRC_APERR_T BIT_2S /* force ADDRPERR on TRG */
+-#define TST_CFG_WRITE_ON BIT_1S /* Enable Config Reg WR */
+-#define TST_CFG_WRITE_OFF BIT_0S /* Disable Config Reg WR */
+-
+-/* B2_TST_CTRL2 8 bit Test Control Register 2 */
+- /* Bit 7.. 4: reserved */
+- /* force the following error on the next master read/write */
+-#define TST_FRC_DPERR_MR64 BIT_3S /* DataPERR RD 64 */
+-#define TST_FRC_DPERR_MW64 BIT_2S /* DataPERR WR 64 */
+-#define TST_FRC_APERR_1M64 BIT_1S /* AddrPERR on 1. phase */
+-#define TST_FRC_APERR_2M64 BIT_0S /* AddrPERR on 2. phase */
+-
+-/* B2_GP_IO 32 bit General Purpose I/O Register */
+- /* Bit 31..26: reserved */
+-#define GP_DIR_9 BIT_25 /* IO_9 direct, 0=In/1=Out */
+-#define GP_DIR_8 BIT_24 /* IO_8 direct, 0=In/1=Out */
+-#define GP_DIR_7 BIT_23 /* IO_7 direct, 0=In/1=Out */
+-#define GP_DIR_6 BIT_22 /* IO_6 direct, 0=In/1=Out */
+-#define GP_DIR_5 BIT_21 /* IO_5 direct, 0=In/1=Out */
+-#define GP_DIR_4 BIT_20 /* IO_4 direct, 0=In/1=Out */
+-#define GP_DIR_3 BIT_19 /* IO_3 direct, 0=In/1=Out */
+-#define GP_DIR_2 BIT_18 /* IO_2 direct, 0=In/1=Out */
+-#define GP_DIR_1 BIT_17 /* IO_1 direct, 0=In/1=Out */
+-#define GP_DIR_0 BIT_16 /* IO_0 direct, 0=In/1=Out */
+- /* Bit 15..10: reserved */
+-#define GP_IO_9 BIT_9 /* IO_9 pin */
+-#define GP_IO_8 BIT_8 /* IO_8 pin */
+-#define GP_IO_7 BIT_7 /* IO_7 pin */
+-#define GP_IO_6 BIT_6 /* IO_6 pin */
+-#define GP_IO_5 BIT_5 /* IO_5 pin */
+-#define GP_IO_4 BIT_4 /* IO_4 pin */
+-#define GP_IO_3 BIT_3 /* IO_3 pin */
+-#define GP_IO_2 BIT_2 /* IO_2 pin */
+-#define GP_IO_1 BIT_1 /* IO_1 pin */
+-#define GP_IO_0 BIT_0 /* IO_0 pin */
+-
+-/* B2_I2C_CTRL 32 bit I2C HW Control Register */
+-#define I2C_FLAG BIT_31 /* Start read/write if WR */
+-#define I2C_ADDR (0x7fffL<<16) /* Bit 30..16: Addr to be RD/WR */
+-#define I2C_DEV_SEL (0x7fL<<9) /* Bit 15.. 9: I2C Device Select */
+- /* Bit 8.. 5: reserved */
+-#define I2C_BURST_LEN BIT_4 /* Burst Len, 1/4 bytes */
+-#define I2C_DEV_SIZE (7<<1) /* Bit 3.. 1: I2C Device Size */
+-#define I2C_025K_DEV (0<<1) /* 0: 256 Bytes or smal. */
+-#define I2C_05K_DEV (1<<1) /* 1: 512 Bytes */
+-#define I2C_1K_DEV (2<<1) /* 2: 1024 Bytes */
+-#define I2C_2K_DEV (3<<1) /* 3: 2048 Bytes */
+-#define I2C_4K_DEV (4<<1) /* 4: 4096 Bytes */
+-#define I2C_8K_DEV (5<<1) /* 5: 8192 Bytes */
+-#define I2C_16K_DEV (6<<1) /* 6: 16384 Bytes */
+-#define I2C_32K_DEV (7<<1) /* 7: 32768 Bytes */
+-#define I2C_STOP BIT_0 /* Interrupt I2C transfer */
+-
+-/* B2_I2C_IRQ 32 bit I2C HW IRQ Register */
+- /* Bit 31.. 1 reserved */
+-#define I2C_CLR_IRQ BIT_0 /* Clear I2C IRQ */
+-
+-/* B2_I2C_SW 32 bit (8 bit access) I2C HW SW Port Register */
+- /* Bit 7.. 3: reserved */
+-#define I2C_DATA_DIR BIT_2S /* direction of I2C_DATA */
+-#define I2C_DATA BIT_1S /* I2C Data Port */
+-#define I2C_CLK BIT_0S /* I2C Clock Port */
+-
+-/*
+- * I2C Address
+- */
+-#define I2C_SENS_ADDR LM80_ADDR /* I2C Sensor Address, (Volt and Temp)*/
+-
+-
+-/* B2_BSC_CTRL 8 bit Blink Source Counter Control */
+- /* Bit 7.. 2: reserved */
+-#define BSC_START BIT_1S /* Start Blink Source Counter */
+-#define BSC_STOP BIT_0S /* Stop Blink Source Counter */
+-
+-/* B2_BSC_STAT 8 bit Blink Source Counter Status */
+- /* Bit 7.. 1: reserved */
+-#define BSC_SRC BIT_0S /* Blink Source, 0=Off / 1=On */
+-
+-/* B2_BSC_TST 16 bit Blink Source Counter Test Reg */
+-#define BSC_T_ON BIT_2S /* Test mode on */
+-#define BSC_T_OFF BIT_1S /* Test mode off */
+-#define BSC_T_STEP BIT_0S /* Test step */
+-
+-
+-/* B3_RAM_ADDR 32 bit RAM Address, to read or write */
+- /* Bit 31..19: reserved */
+-#define RAM_ADR_RAN 0x0007ffffL /* Bit 18.. 0: RAM Address Range */
+-
+-/* RAM Interface Registers */
+-/* B3_RI_CTRL 16 bit RAM Iface Control Register */
+- /* Bit 15..10: reserved */
+-#define RI_CLR_RD_PERR BIT_9S /* Clear IRQ RAM Read Parity Err */
+-#define RI_CLR_WR_PERR BIT_8S /* Clear IRQ RAM Write Parity Err*/
+- /* Bit 7.. 2: reserved */
+-#define RI_RST_CLR BIT_1S /* Clear RAM Interface Reset */
+-#define RI_RST_SET BIT_0S /* Set RAM Interface Reset */
+-
+-/* B3_RI_TEST 8 bit RAM Iface Test Register */
+- /* Bit 15.. 4: reserved */
+-#define RI_T_EV BIT_3S /* Timeout Event occured */
+-#define RI_T_ON BIT_2S /* Timeout Timer Test On */
+-#define RI_T_OFF BIT_1S /* Timeout Timer Test Off */
+-#define RI_T_STEP BIT_0S /* Timeout Timer Step */
+-
+-/* MAC Arbiter Registers */
+-/* B3_MA_TO_CTRL 16 bit MAC Arbiter Timeout Ctrl Reg */
+- /* Bit 15.. 4: reserved */
+-#define MA_FOE_ON BIT_3S /* XMAC Fast Output Enable ON */
+-#define MA_FOE_OFF BIT_2S /* XMAC Fast Output Enable OFF */
+-#define MA_RST_CLR BIT_1S /* Clear MAC Arbiter Reset */
+-#define MA_RST_SET BIT_0S /* Set MAC Arbiter Reset */
+-
+-/* B3_MA_RC_CTRL 16 bit MAC Arbiter Recovery Ctrl Reg */
+- /* Bit 15.. 8: reserved */
+-#define MA_ENA_REC_TX2 BIT_7S /* Enable Recovery Timer TX2 */
+-#define MA_DIS_REC_TX2 BIT_6S /* Disable Recovery Timer TX2 */
+-#define MA_ENA_REC_TX1 BIT_5S /* Enable Recovery Timer TX1 */
+-#define MA_DIS_REC_TX1 BIT_4S /* Disable Recovery Timer TX1 */
+-#define MA_ENA_REC_RX2 BIT_3S /* Enable Recovery Timer RX2 */
+-#define MA_DIS_REC_RX2 BIT_2S /* Disable Recovery Timer RX2 */
+-#define MA_ENA_REC_RX1 BIT_1S /* Enable Recovery Timer RX1 */
+-#define MA_DIS_REC_RX1 BIT_0S /* Disable Recovery Timer RX1 */
+-
+-/* Packet Arbiter Registers */
+-/* B3_PA_CTRL 16 bit Packet Arbiter Ctrl Register */
+- /* Bit 15..14: reserved */
+-#define PA_CLR_TO_TX2 BIT_13S /* Clear IRQ Packet Timeout TX2 */
+-#define PA_CLR_TO_TX1 BIT_12S /* Clear IRQ Packet Timeout TX1 */
+-#define PA_CLR_TO_RX2 BIT_11S /* Clear IRQ Packet Timeout RX2 */
+-#define PA_CLR_TO_RX1 BIT_10S /* Clear IRQ Packet Timeout RX1 */
+-#define PA_ENA_TO_TX2 BIT_9S /* Enable Timeout Timer TX2 */
+-#define PA_DIS_TO_TX2 BIT_8S /* Disable Timeout Timer TX2 */
+-#define PA_ENA_TO_TX1 BIT_7S /* Enable Timeout Timer TX1 */
+-#define PA_DIS_TO_TX1 BIT_6S /* Disable Timeout Timer TX1 */
+-#define PA_ENA_TO_RX2 BIT_5S /* Enable Timeout Timer RX2 */
+-#define PA_DIS_TO_RX2 BIT_4S /* Disable Timeout Timer RX2 */
+-#define PA_ENA_TO_RX1 BIT_3S /* Enable Timeout Timer RX1 */
+-#define PA_DIS_TO_RX1 BIT_2S /* Disable Timeout Timer RX1 */
+-#define PA_RST_CLR BIT_1S /* Clear MAC Arbiter Reset */
+-#define PA_RST_SET BIT_0S /* Set MAC Arbiter Reset */
+-
+-#define PA_ENA_TO_ALL (PA_ENA_TO_RX1 | PA_ENA_TO_RX2 |\
+- PA_ENA_TO_TX1 | PA_ENA_TO_TX2)
+-
+-/* Rx/Tx Path related Arbiter Test Registers */
+-/* B3_MA_TO_TEST 16 bit MAC Arbiter Timeout Test Reg */
+-/* B3_MA_RC_TEST 16 bit MAC Arbiter Recovery Test Reg */
+-/* B3_PA_TEST 16 bit Packet Arbiter Test Register */
+-/* Bit 15, 11, 7, and 3 are reserved in B3_PA_TEST */
+-#define TX2_T_EV BIT_15S /* TX2 Timeout/Recv Event occured */
+-#define TX2_T_ON BIT_14S /* TX2 Timeout/Recv Timer Test On */
+-#define TX2_T_OFF BIT_13S /* TX2 Timeout/Recv Timer Tst Off */
+-#define TX2_T_STEP BIT_12S /* TX2 Timeout/Recv Timer Step */
+-#define TX1_T_EV BIT_11S /* TX1 Timeout/Recv Event occured */
+-#define TX1_T_ON BIT_10S /* TX1 Timeout/Recv Timer Test On */
+-#define TX1_T_OFF BIT_9S /* TX1 Timeout/Recv Timer Tst Off */
+-#define TX1_T_STEP BIT_8S /* TX1 Timeout/Recv Timer Step */
+-#define RX2_T_EV BIT_7S /* RX2 Timeout/Recv Event occured */
+-#define RX2_T_ON BIT_6S /* RX2 Timeout/Recv Timer Test On */
+-#define RX2_T_OFF BIT_5S /* RX2 Timeout/Recv Timer Tst Off */
+-#define RX2_T_STEP BIT_4S /* RX2 Timeout/Recv Timer Step */
+-#define RX1_T_EV BIT_3S /* RX1 Timeout/Recv Event occured */
+-#define RX1_T_ON BIT_2S /* RX1 Timeout/Recv Timer Test On */
+-#define RX1_T_OFF BIT_1S /* RX1 Timeout/Recv Timer Tst Off */
+-#define RX1_T_STEP BIT_0S /* RX1 Timeout/Recv Timer Step */
+-
+-
+-/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */
+-/* TXA_ITI_INI 32 bit Tx Arb Interval Timer Init Val */
+-/* TXA_ITI_VAL 32 bit Tx Arb Interval Timer Value */
+-/* TXA_LIM_INI 32 bit Tx Arb Limit Counter Init Val */
+-/* TXA_LIM_VAL 32 bit Tx Arb Limit Counter Value */
+- /* Bit 31..24: reserved */
+-#define TXA_MAX_VAL 0x00ffffffUL/* Bit 23.. 0: Max TXA Timer/Cnt Val */
+-
+-/* TXA_CTRL 8 bit Tx Arbiter Control Register */
+-#define TXA_ENA_FSYNC BIT_7S /* Enable force of sync Tx queue */
+-#define TXA_DIS_FSYNC BIT_6S /* Disable force of sync Tx queue */
+-#define TXA_ENA_ALLOC BIT_5S /* Enable alloc of free bandwidth */
+-#define TXA_DIS_ALLOC BIT_4S /* Disable alloc of free bandwidth */
+-#define TXA_START_RC BIT_3S /* Start sync Rate Control */
+-#define TXA_STOP_RC BIT_2S /* Stop sync Rate Control */
+-#define TXA_ENA_ARB BIT_1S /* Enable Tx Arbiter */
+-#define TXA_DIS_ARB BIT_0S /* Disable Tx Arbiter */
+-
+-/* TXA_TEST 8 bit Tx Arbiter Test Register */
+- /* Bit 7.. 6: reserved */
+-#define TXA_INT_T_ON BIT_5S /* Tx Arb Interval Timer Test On */
+-#define TXA_INT_T_OFF BIT_4S /* Tx Arb Interval Timer Test Off */
+-#define TXA_INT_T_STEP BIT_3S /* Tx Arb Interval Timer Step */
+-#define TXA_LIM_T_ON BIT_2S /* Tx Arb Limit Timer Test On */
+-#define TXA_LIM_T_OFF BIT_1S /* Tx Arb Limit Timer Test Off */
+-#define TXA_LIM_T_STEP BIT_0S /* Tx Arb Limit Timer Step */
+-
+-/* TXA_STAT 8 bit Tx Arbiter Status Register */
+- /* Bit 7.. 1: reserved */
+-#define TXA_PRIO_XS BIT_0S /* sync queue has prio to send */
+-
+-/* Q_BC 32 bit Current Byte Counter */
+- /* Bit 31..16: reserved */
+-#define BC_MAX 0xffff /* Bit 15.. 0: Byte counter */
+-
+-/* BMU Control Status Registers */
+-/* B0_R1_CSR 32 bit BMU Ctrl/Stat Rx Queue 1 */
+-/* B0_R2_CSR 32 bit BMU Ctrl/Stat Rx Queue 2 */
+-/* B0_XA1_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */
+-/* B0_XS1_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 1 */
+-/* B0_XA2_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */
+-/* B0_XS2_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 2 */
+-/* Q_CSR 32 bit BMU Control/Status Register */
+- /* Bit 31..25: reserved */
+-#define CSR_SV_IDLE BIT_24 /* BMU SM Idle */
+- /* Bit 23..22: reserved */
+-#define CSR_DESC_CLR BIT_21 /* Clear Reset for Descr */
+-#define CSR_DESC_SET BIT_20 /* Set Reset for Descr */
+-#define CSR_FIFO_CLR BIT_19 /* Clear Reset for FIFO */
+-#define CSR_FIFO_SET BIT_18 /* Set Reset for FIFO */
+-#define CSR_HPI_RUN BIT_17 /* Release HPI SM */
+-#define CSR_HPI_RST BIT_16 /* Reset HPI SM to Idle */
+-#define CSR_SV_RUN BIT_15 /* Release Supervisor SM */
+-#define CSR_SV_RST BIT_14 /* Reset Supervisor SM */
+-#define CSR_DREAD_RUN BIT_13 /* Release Descr Read SM */
+-#define CSR_DREAD_RST BIT_12 /* Reset Descr Read SM */
+-#define CSR_DWRITE_RUN BIT_11 /* Release Descr Write SM */
+-#define CSR_DWRITE_RST BIT_10 /* Reset Descr Write SM */
+-#define CSR_TRANS_RUN BIT_9 /* Release Transfer SM */
+-#define CSR_TRANS_RST BIT_8 /* Reset Transfer SM */
+-#define CSR_ENA_POL BIT_7 /* Enable Descr Polling */
+-#define CSR_DIS_POL BIT_6 /* Disable Descr Polling */
+-#define CSR_STOP BIT_5 /* Stop Rx/Tx Queue */
+-#define CSR_START BIT_4 /* Start Rx/Tx Queue */
+-#define CSR_IRQ_CL_P BIT_3 /* (Rx) Clear Parity IRQ */
+-#define CSR_IRQ_CL_B BIT_2 /* Clear EOB IRQ */
+-#define CSR_IRQ_CL_F BIT_1 /* Clear EOF IRQ */
+-#define CSR_IRQ_CL_C BIT_0 /* Clear ERR IRQ */
+-
+-#define CSR_SET_RESET (CSR_DESC_SET | CSR_FIFO_SET | CSR_HPI_RST |\
+- CSR_SV_RST | CSR_DREAD_RST | CSR_DWRITE_RST |\
+- CSR_TRANS_RST)
+-#define CSR_CLR_RESET (CSR_DESC_CLR | CSR_FIFO_CLR | CSR_HPI_RUN |\
+- CSR_SV_RUN | CSR_DREAD_RUN | CSR_DWRITE_RUN |\
+- CSR_TRANS_RUN)
+-
+-/* Q_F 32 bit Flag Register */
+- /* Bit 31..28: reserved */
+-#define F_ALM_FULL BIT_27 /* Rx FIFO: almost full */
+-#define F_EMPTY BIT_27 /* Tx FIFO: empty flag */
+-#define F_FIFO_EOF BIT_26 /* Tag (EOF Flag) bit in FIFO */
+-#define F_WM_REACHED BIT_25 /* Watermark reached */
+- /* reserved */
+-#define F_FIFO_LEVEL (0x1fL<<16) /* Bit 23..16: # of Qwords in FIFO */
+- /* Bit 15..11: reserved */
+-#define F_WATER_MARK 0x0007ffL /* Bit 10.. 0: Watermark */
+-
+-/* Q_T1 32 bit Test Register 1 */
+-/* Holds four State Machine control Bytes */
+-#define SM_CTRL_SV_MSK (0xffL<<24) /* Bit 31..24: Control Supervisor SM */
+-#define SM_CTRL_RD_MSK (0xffL<<16) /* Bit 23..16: Control Read Desc SM */
+-#define SM_CTRL_WR_MSK (0xffL<<8) /* Bit 15.. 8: Control Write Desc SM */
+-#define SM_CTRL_TR_MSK 0xffL /* Bit 7.. 0: Control Transfer SM */
+-
+-/* Q_T1_TR 8 bit Test Register 1 Transfer SM */
+-/* Q_T1_WR 8 bit Test Register 1 Write Descriptor SM */
+-/* Q_T1_RD 8 bit Test Register 1 Read Descriptor SM */
+-/* Q_T1_SV 8 bit Test Register 1 Supervisor SM */
+-
+-/* The control status byte of each machine looks like ... */
+-#define SM_STATE 0xf0 /* Bit 7.. 4: State which shall be loaded */
+-#define SM_LOAD BIT_3S /* Load the SM with SM_STATE */
+-#define SM_TEST_ON BIT_2S /* Switch on SM Test Mode */
+-#define SM_TEST_OFF BIT_1S /* Go off the Test Mode */
+-#define SM_STEP BIT_0S /* Step the State Machine */
+-/* The encoding of the states is not supported by the Diagnostics Tool */
+-
+-/* Q_T2 32 bit Test Register 2 */
+- /* Bit 31.. 8: reserved */
+-#define T2_AC_T_ON BIT_7 /* Address Counter Test Mode on */
+-#define T2_AC_T_OFF BIT_6 /* Address Counter Test Mode off */
+-#define T2_BC_T_ON BIT_5 /* Byte Counter Test Mode on */
+-#define T2_BC_T_OFF BIT_4 /* Byte Counter Test Mode off */
+-#define T2_STEP04 BIT_3 /* Inc AC/Dec BC by 4 */
+-#define T2_STEP03 BIT_2 /* Inc AC/Dec BC by 3 */
+-#define T2_STEP02 BIT_1 /* Inc AC/Dec BC by 2 */
+-#define T2_STEP01 BIT_0 /* Inc AC/Dec BC by 1 */
+-
+-/* Q_T3 32 bit Test Register 3 */
+- /* Bit 31.. 7: reserved */
+-#define T3_MUX_MSK (7<<4) /* Bit 6.. 4: Mux Position */
+- /* Bit 3: reserved */
+-#define T3_VRAM_MSK 7 /* Bit 2.. 0: Virtual RAM Buffer Address */
+-
+-/* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */
+-/* RB_START 32 bit RAM Buffer Start Address */
+-/* RB_END 32 bit RAM Buffer End Address */
+-/* RB_WP 32 bit RAM Buffer Write Pointer */
+-/* RB_RP 32 bit RAM Buffer Read Pointer */
+-/* RB_RX_UTPP 32 bit Rx Upper Threshold, Pause Pack */
+-/* RB_RX_LTPP 32 bit Rx Lower Threshold, Pause Pack */
+-/* RB_RX_UTHP 32 bit Rx Upper Threshold, High Prio */
+-/* RB_RX_LTHP 32 bit Rx Lower Threshold, High Prio */
+-/* RB_PC 32 bit RAM Buffer Packet Counter */
+-/* RB_LEV 32 bit RAM Buffer Level Register */
+- /* Bit 31..19: reserved */
+-#define RB_MSK 0x0007ffff /* Bit 18.. 0: RAM Buffer Pointer Bits */
+-
+-/* RB_TST2 8 bit RAM Buffer Test Register 2 */
+- /* Bit 7.. 4: reserved */
+-#define RB_PC_DEC BIT_3S /* Packet Counter Decrem */
+-#define RB_PC_T_ON BIT_2S /* Packet Counter Test On */
+-#define RB_PC_T_OFF BIT_1S /* Packet Counter Tst Off */
+-#define RB_PC_INC BIT_0S /* Packet Counter Increm */
+-
+-/* RB_TST1 8 bit RAM Buffer Test Register 1 */
+- /* Bit 7: reserved */
+-#define RB_WP_T_ON BIT_6S /* Write Pointer Test On */
+-#define RB_WP_T_OFF BIT_5S /* Write Pointer Test Off */
+-#define RB_WP_INC BIT_4S /* Write Pointer Increm */
+- /* Bit 3: reserved */
+-#define RB_RP_T_ON BIT_2S /* Read Pointer Test On */
+-#define RB_RP_T_OFF BIT_1S /* Read Pointer Test Off */
+-#define RB_RP_DEC BIT_0S /* Read Pointer Decrement */
+-
+-/* RB_CTRL 8 bit RAM Buffer Control Register */
+- /* Bit 7.. 6: reserved */
+-#define RB_ENA_STFWD BIT_5S /* Enable Store & Forward */
+-#define RB_DIS_STFWD BIT_4S /* Disable Store & Forward */
+-#define RB_ENA_OP_MD BIT_3S /* Enable Operation Mode */
+-#define RB_DIS_OP_MD BIT_2S /* Disable Operation Mode */
+-#define RB_RST_CLR BIT_1S /* Clear RAM Buf STM Reset */
+-#define RB_RST_SET BIT_0S /* Set RAM Buf STM Reset */
+-
+-
+-/* Receive and Transmit MAC FIFO Registers (GENESIS only) */
+-
+-/* RX_MFF_EA 32 bit Receive MAC FIFO End Address */
+-/* RX_MFF_WP 32 bit Receive MAC FIFO Write Pointer */
+-/* RX_MFF_RP 32 bit Receive MAC FIFO Read Pointer */
+-/* RX_MFF_PC 32 bit Receive MAC FIFO Packet Counter */
+-/* RX_MFF_LEV 32 bit Receive MAC FIFO Level */
+-/* TX_MFF_EA 32 bit Transmit MAC FIFO End Address */
+-/* TX_MFF_WP 32 bit Transmit MAC FIFO Write Pointer */
+-/* TX_MFF_WSP 32 bit Transmit MAC FIFO WR Shadow Pointer */
+-/* TX_MFF_RP 32 bit Transmit MAC FIFO Read Pointer */
+-/* TX_MFF_PC 32 bit Transmit MAC FIFO Packet Cnt */
+-/* TX_MFF_LEV 32 bit Transmit MAC FIFO Level */
+- /* Bit 31.. 6: reserved */
+-#define MFF_MSK 0x007fL /* Bit 5.. 0: MAC FIFO Address/Ptr Bits */
+-
+-/* RX_MFF_CTRL1 16 bit Receive MAC FIFO Control Reg 1 */
+- /* Bit 15..14: reserved */
+-#define MFF_ENA_RDY_PAT BIT_13S /* Enable Ready Patch */
+-#define MFF_DIS_RDY_PAT BIT_12S /* Disable Ready Patch */
+-#define MFF_ENA_TIM_PAT BIT_11S /* Enable Timing Patch */
+-#define MFF_DIS_TIM_PAT BIT_10S /* Disable Timing Patch */
+-#define MFF_ENA_ALM_FUL BIT_9S /* Enable AlmostFull Sign */
+-#define MFF_DIS_ALM_FUL BIT_8S /* Disable AlmostFull Sign */
+-#define MFF_ENA_PAUSE BIT_7S /* Enable Pause Signaling */
+-#define MFF_DIS_PAUSE BIT_6S /* Disable Pause Signaling */
+-#define MFF_ENA_FLUSH BIT_5S /* Enable Frame Flushing */
+-#define MFF_DIS_FLUSH BIT_4S /* Disable Frame Flushing */
+-#define MFF_ENA_TIST BIT_3S /* Enable Time Stamp Gener */
+-#define MFF_DIS_TIST BIT_2S /* Disable Time Stamp Gener */
+-#define MFF_CLR_INTIST BIT_1S /* Clear IRQ No Time Stamp */
+-#define MFF_CLR_INSTAT BIT_0S /* Clear IRQ No Status */
+-
+-#define MFF_RX_CTRL_DEF MFF_ENA_TIM_PAT
+-
+-/* TX_MFF_CTRL1 16 bit Transmit MAC FIFO Control Reg 1 */
+-#define MFF_CLR_PERR BIT_15S /* Clear Parity Error IRQ */
+- /* Bit 14: reserved */
+-#define MFF_ENA_PKT_REC BIT_13S /* Enable Packet Recovery */
+-#define MFF_DIS_PKT_REC BIT_12S /* Disable Packet Recovery */
+-/* MFF_ENA_TIM_PAT (see RX_MFF_CTRL1) Bit 11: Enable Timing Patch */
+-/* MFF_DIS_TIM_PAT (see RX_MFF_CTRL1) Bit 10: Disable Timing Patch */
+-/* MFF_ENA_ALM_FUL (see RX_MFF_CTRL1) Bit 9: Enable Almost Full Sign */
+-/* MFF_DIS_ALM_FUL (see RX_MFF_CTRL1) Bit 8: Disable Almost Full Sign */
+-#define MFF_ENA_W4E BIT_7S /* Enable Wait for Empty */
+-#define MFF_DIS_W4E BIT_6S /* Disable Wait for Empty */
+-/* MFF_ENA_FLUSH (see RX_MFF_CTRL1) Bit 5: Enable Frame Flushing */
+-/* MFF_DIS_FLUSH (see RX_MFF_CTRL1) Bit 4: Disable Frame Flushing */
+-#define MFF_ENA_LOOPB BIT_3S /* Enable Loopback */
+-#define MFF_DIS_LOOPB BIT_2S /* Disable Loopback */
+-#define MFF_CLR_MAC_RST BIT_1S /* Clear XMAC Reset */
+-#define MFF_SET_MAC_RST BIT_0S /* Set XMAC Reset */
+-
+-#define MFF_TX_CTRL_DEF (MFF_ENA_PKT_REC | MFF_ENA_TIM_PAT | MFF_ENA_FLUSH)
+-
+-/* RX_MFF_TST2 8 bit Receive MAC FIFO Test Register 2 */
+-/* TX_MFF_TST2 8 bit Transmit MAC FIFO Test Register 2 */
+- /* Bit 7: reserved */
+-#define MFF_WSP_T_ON BIT_6S /* Tx: Write Shadow Ptr TestOn */
+-#define MFF_WSP_T_OFF BIT_5S /* Tx: Write Shadow Ptr TstOff */
+-#define MFF_WSP_INC BIT_4S /* Tx: Write Shadow Ptr Increment */
+-#define MFF_PC_DEC BIT_3S /* Packet Counter Decrement */
+-#define MFF_PC_T_ON BIT_2S /* Packet Counter Test On */
+-#define MFF_PC_T_OFF BIT_1S /* Packet Counter Test Off */
+-#define MFF_PC_INC BIT_0S /* Packet Counter Increment */
+-
+-/* RX_MFF_TST1 8 bit Receive MAC FIFO Test Register 1 */
+-/* TX_MFF_TST1 8 bit Transmit MAC FIFO Test Register 1 */
+- /* Bit 7: reserved */
+-#define MFF_WP_T_ON BIT_6S /* Write Pointer Test On */
+-#define MFF_WP_T_OFF BIT_5S /* Write Pointer Test Off */
+-#define MFF_WP_INC BIT_4S /* Write Pointer Increm */
+- /* Bit 3: reserved */
+-#define MFF_RP_T_ON BIT_2S /* Read Pointer Test On */
+-#define MFF_RP_T_OFF BIT_1S /* Read Pointer Test Off */
+-#define MFF_RP_DEC BIT_0S /* Read Pointer Decrement */
+-
+-/* RX_MFF_CTRL2 8 bit Receive MAC FIFO Control Reg 2 */
+-/* TX_MFF_CTRL2 8 bit Transmit MAC FIFO Control Reg 2 */
+- /* Bit 7..4: reserved */
+-#define MFF_ENA_OP_MD BIT_3S /* Enable Operation Mode */
+-#define MFF_DIS_OP_MD BIT_2S /* Disable Operation Mode */
+-#define MFF_RST_CLR BIT_1S /* Clear MAC FIFO Reset */
+-#define MFF_RST_SET BIT_0S /* Set MAC FIFO Reset */
+-
+-
+-/* Link LED Counter Registers (GENESIS only) */
+-
+-/* RX_LED_CTRL 8 bit Receive LED Cnt Control Reg */
+-/* TX_LED_CTRL 8 bit Transmit LED Cnt Control Reg */
+-/* LNK_SYNC_CTRL 8 bit Link Sync Cnt Control Register */
+- /* Bit 7.. 3: reserved */
+-#define LED_START BIT_2S /* Start Timer */
+-#define LED_STOP BIT_1S /* Stop Timer */
+-#define LED_STATE BIT_0S /* Rx/Tx: LED State, 1=LED on */
+-#define LED_CLR_IRQ BIT_0S /* Lnk: Clear Link IRQ */
+-
+-/* RX_LED_TST 8 bit Receive LED Cnt Test Register */
+-/* TX_LED_TST 8 bit Transmit LED Cnt Test Register */
+-/* LNK_SYNC_TST 8 bit Link Sync Cnt Test Register */
+- /* Bit 7.. 3: reserved */
+-#define LED_T_ON BIT_2S /* LED Counter Test mode On */
+-#define LED_T_OFF BIT_1S /* LED Counter Test mode Off */
+-#define LED_T_STEP BIT_0S /* LED Counter Step */
+-
+-/* LNK_LED_REG 8 bit Link LED Register */
+- /* Bit 7.. 6: reserved */
+-#define LED_BLK_ON BIT_5S /* Link LED Blinking On */
+-#define LED_BLK_OFF BIT_4S /* Link LED Blinking Off */
+-#define LED_SYNC_ON BIT_3S /* Use Sync Wire to switch LED */
+-#define LED_SYNC_OFF BIT_2S /* Disable Sync Wire Input */
+-#define LED_ON BIT_1S /* switch LED on */
+-#define LED_OFF BIT_0S /* switch LED off */
+-
+-/* Receive and Transmit GMAC FIFO Registers (YUKON only) */
+-
+-/* RX_GMF_EA 32 bit Rx GMAC FIFO End Address */
+-/* RX_GMF_AF_THR 32 bit Rx GMAC FIFO Almost Full Thresh. */
+-/* RX_GMF_WP 32 bit Rx GMAC FIFO Write Pointer */
+-/* RX_GMF_WLEV 32 bit Rx GMAC FIFO Write Level */
+-/* RX_GMF_RP 32 bit Rx GMAC FIFO Read Pointer */
+-/* RX_GMF_RLEV 32 bit Rx GMAC FIFO Read Level */
+-/* TX_GMF_EA 32 bit Tx GMAC FIFO End Address */
+-/* TX_GMF_AE_THR 32 bit Tx GMAC FIFO Almost Empty Thresh.*/
+-/* TX_GMF_WP 32 bit Tx GMAC FIFO Write Pointer */
+-/* TX_GMF_WSP 32 bit Tx GMAC FIFO Write Shadow Ptr. */
+-/* TX_GMF_WLEV 32 bit Tx GMAC FIFO Write Level */
+-/* TX_GMF_RP 32 bit Tx GMAC FIFO Read Pointer */
+-/* TX_GMF_RSTP 32 bit Tx GMAC FIFO Restart Pointer */
+-/* TX_GMF_RLEV 32 bit Tx GMAC FIFO Read Level */
+-
+-/* RX_GMF_CTRL_T 32 bit Rx GMAC FIFO Control/Test */
+- /* Bits 31..15: reserved */
+-#define GMF_WP_TST_ON BIT_14 /* Write Pointer Test On */
+-#define GMF_WP_TST_OFF BIT_13 /* Write Pointer Test Off */
+-#define GMF_WP_STEP BIT_12 /* Write Pointer Step/Increment */
+- /* Bit 11: reserved */
+-#define GMF_RP_TST_ON BIT_10 /* Read Pointer Test On */
+-#define GMF_RP_TST_OFF BIT_9 /* Read Pointer Test Off */
+-#define GMF_RP_STEP BIT_8 /* Read Pointer Step/Increment */
+-#define GMF_RX_F_FL_ON BIT_7 /* Rx FIFO Flush Mode On */
+-#define GMF_RX_F_FL_OFF BIT_6 /* Rx FIFO Flush Mode Off */
+-#define GMF_CLI_RX_FO BIT_5 /* Clear IRQ Rx FIFO Overrun */
+-#define GMF_CLI_RX_FC BIT_4 /* Clear IRQ Rx Frame Complete */
+-#define GMF_OPER_ON BIT_3 /* Operational Mode On */
+-#define GMF_OPER_OFF BIT_2 /* Operational Mode Off */
+-#define GMF_RST_CLR BIT_1 /* Clear GMAC FIFO Reset */
+-#define GMF_RST_SET BIT_0 /* Set GMAC FIFO Reset */
+-
+-/* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test */
+- /* Bits 31..19: reserved */
+-#define GMF_WSP_TST_ON BIT_18 /* Write Shadow Pointer Test On */
+-#define GMF_WSP_TST_OFF BIT_17 /* Write Shadow Pointer Test Off */
+-#define GMF_WSP_STEP BIT_16 /* Write Shadow Pointer Step/Increment */
+- /* Bits 15..7: same as for RX_GMF_CTRL_T */
+-#define GMF_CLI_TX_FU BIT_6 /* Clear IRQ Tx FIFO Underrun */
+-#define GMF_CLI_TX_FC BIT_5 /* Clear IRQ Tx Frame Complete */
+-#define GMF_CLI_TX_PE BIT_4 /* Clear IRQ Tx Parity Error */
+- /* Bits 3..0: same as for RX_GMF_CTRL_T */
+-
+-#define GMF_RX_CTRL_DEF (GMF_OPER_ON | GMF_RX_F_FL_ON)
+-#define GMF_TX_CTRL_DEF GMF_OPER_ON
+-
+-#define RX_GMF_FL_THR_DEF 0x0a /* Rx GMAC FIFO Flush Threshold default */
+-
+-/* GMAC_TI_ST_CTRL 8 bit Time Stamp Timer Ctrl Reg (YUKON only) */
+- /* Bit 7.. 3: reserved */
+-#define GMT_ST_START BIT_2S /* Start Time Stamp Timer */
+-#define GMT_ST_STOP BIT_1S /* Stop Time Stamp Timer */
+-#define GMT_ST_CLR_IRQ BIT_0S /* Clear Time Stamp Timer IRQ */
+-
+-/* GMAC_CTRL 32 bit GMAC Control Reg (YUKON only) */
+- /* Bits 31.. 8: reserved */
+-#define GMC_H_BURST_ON BIT_7 /* Half Duplex Burst Mode On */
+-#define GMC_H_BURST_OFF BIT_6 /* Half Duplex Burst Mode Off */
+-#define GMC_F_LOOPB_ON BIT_5 /* FIFO Loopback On */
+-#define GMC_F_LOOPB_OFF BIT_4 /* FIFO Loopback Off */
+-#define GMC_PAUSE_ON BIT_3 /* Pause On */
+-#define GMC_PAUSE_OFF BIT_2 /* Pause Off */
+-#define GMC_RST_CLR BIT_1 /* Clear GMAC Reset */
+-#define GMC_RST_SET BIT_0 /* Set GMAC Reset */
+-
+-/* GPHY_CTRL 32 bit GPHY Control Reg (YUKON only) */
+- /* Bits 31..29: reserved */
+-#define GPC_SEL_BDT BIT_28 /* Select Bi-Dir. Transfer for MDC/MDIO */
+-#define GPC_INT_POL_HI BIT_27 /* IRQ Polarity is Active HIGH */
+-#define GPC_75_OHM BIT_26 /* Use 75 Ohm Termination instead of 50 */
+-#define GPC_DIS_FC BIT_25 /* Disable Automatic Fiber/Copper Detection */
+-#define GPC_DIS_SLEEP BIT_24 /* Disable Energy Detect */
+-#define GPC_HWCFG_M_3 BIT_23 /* HWCFG_MODE[3] */
+-#define GPC_HWCFG_M_2 BIT_22 /* HWCFG_MODE[2] */
+-#define GPC_HWCFG_M_1 BIT_21 /* HWCFG_MODE[1] */
+-#define GPC_HWCFG_M_0 BIT_20 /* HWCFG_MODE[0] */
+-#define GPC_ANEG_0 BIT_19 /* ANEG[0] */
+-#define GPC_ENA_XC BIT_18 /* Enable MDI crossover */
+-#define GPC_DIS_125 BIT_17 /* Disable 125 MHz clock */
+-#define GPC_ANEG_3 BIT_16 /* ANEG[3] */
+-#define GPC_ANEG_2 BIT_15 /* ANEG[2] */
+-#define GPC_ANEG_1 BIT_14 /* ANEG[1] */
+-#define GPC_ENA_PAUSE BIT_13 /* Enable Pause (SYM_OR_REM) */
+-#define GPC_PHYADDR_4 BIT_12 /* Bit 4 of Phy Addr */
+-#define GPC_PHYADDR_3 BIT_11 /* Bit 3 of Phy Addr */
+-#define GPC_PHYADDR_2 BIT_10 /* Bit 2 of Phy Addr */
+-#define GPC_PHYADDR_1 BIT_9 /* Bit 1 of Phy Addr */
+-#define GPC_PHYADDR_0 BIT_8 /* Bit 0 of Phy Addr */
+- /* Bits 7..2: reserved */
+-#define GPC_RST_CLR BIT_1 /* Clear GPHY Reset */
+-#define GPC_RST_SET BIT_0 /* Set GPHY Reset */
+-
+-#define GPC_HWCFG_GMII_COP (GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | \
+- GPC_HWCFG_M_1 | GPC_HWCFG_M_0)
+-
+-#define GPC_HWCFG_GMII_FIB ( GPC_HWCFG_M_2 | \
+- GPC_HWCFG_M_1 | GPC_HWCFG_M_0)
+-
+-#define GPC_ANEG_ADV_ALL_M (GPC_ANEG_3 | GPC_ANEG_2 | \
+- GPC_ANEG_1 | GPC_ANEG_0)
+-
+-/* forced speed and duplex mode (don't mix with other ANEG bits) */
+-#define GPC_FRC10MBIT_HALF 0
+-#define GPC_FRC10MBIT_FULL GPC_ANEG_0
+-#define GPC_FRC100MBIT_HALF GPC_ANEG_1
+-#define GPC_FRC100MBIT_FULL (GPC_ANEG_0 | GPC_ANEG_1)
+-
+-/* auto-negotiation with limited advertised speeds */
+-/* mix only with master/slave settings (for copper) */
+-#define GPC_ADV_1000_HALF GPC_ANEG_2
+-#define GPC_ADV_1000_FULL GPC_ANEG_3
+-#define GPC_ADV_ALL (GPC_ANEG_2 | GPC_ANEG_3)
+-
+-/* master/slave settings */
+-/* only for copper with 1000 Mbps */
+-#define GPC_FORCE_MASTER 0
+-#define GPC_FORCE_SLAVE GPC_ANEG_0
+-#define GPC_PREF_MASTER GPC_ANEG_1
+-#define GPC_PREF_SLAVE (GPC_ANEG_1 | GPC_ANEG_0)
+-
+-/* GMAC_IRQ_SRC 8 bit GMAC Interrupt Source Reg (YUKON only) */
+-/* GMAC_IRQ_MSK 8 bit GMAC Interrupt Mask Reg (YUKON only) */
+-#define GM_IS_TX_CO_OV BIT_5 /* Transmit Counter Overflow IRQ */
+-#define GM_IS_RX_CO_OV BIT_4 /* Receive Counter Overflow IRQ */
+-#define GM_IS_TX_FF_UR BIT_3 /* Transmit FIFO Underrun */
+-#define GM_IS_TX_COMPL BIT_2 /* Frame Transmission Complete */
+-#define GM_IS_RX_FF_OR BIT_1 /* Receive FIFO Overrun */
+-#define GM_IS_RX_COMPL BIT_0 /* Frame Reception Complete */
+-
+-#define GMAC_DEF_MSK (GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | \
+- GM_IS_TX_FF_UR)
+-
+-/* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */
+- /* Bits 15.. 2: reserved */
+-#define GMLC_RST_CLR BIT_1S /* Clear GMAC Link Reset */
+-#define GMLC_RST_SET BIT_0S /* Set GMAC Link Reset */
+-
+-
+-/* WOL_CTRL_STAT 16 bit WOL Control/Status Reg */
+-#define WOL_CTL_LINK_CHG_OCC BIT_15S
+-#define WOL_CTL_MAGIC_PKT_OCC BIT_14S
+-#define WOL_CTL_PATTERN_OCC BIT_13S
+-
+-#define WOL_CTL_CLEAR_RESULT BIT_12S
+-
+-#define WOL_CTL_ENA_PME_ON_LINK_CHG BIT_11S
+-#define WOL_CTL_DIS_PME_ON_LINK_CHG BIT_10S
+-#define WOL_CTL_ENA_PME_ON_MAGIC_PKT BIT_9S
+-#define WOL_CTL_DIS_PME_ON_MAGIC_PKT BIT_8S
+-#define WOL_CTL_ENA_PME_ON_PATTERN BIT_7S
+-#define WOL_CTL_DIS_PME_ON_PATTERN BIT_6S
+-
+-#define WOL_CTL_ENA_LINK_CHG_UNIT BIT_5S
+-#define WOL_CTL_DIS_LINK_CHG_UNIT BIT_4S
+-#define WOL_CTL_ENA_MAGIC_PKT_UNIT BIT_3S
+-#define WOL_CTL_DIS_MAGIC_PKT_UNIT BIT_2S
+-#define WOL_CTL_ENA_PATTERN_UNIT BIT_1S
+-#define WOL_CTL_DIS_PATTERN_UNIT BIT_0S
+-
+-#define WOL_CTL_DEFAULT \
+- (WOL_CTL_DIS_PME_ON_LINK_CHG | \
+- WOL_CTL_DIS_PME_ON_PATTERN | \
+- WOL_CTL_DIS_PME_ON_MAGIC_PKT | \
+- WOL_CTL_DIS_LINK_CHG_UNIT | \
+- WOL_CTL_DIS_PATTERN_UNIT | \
+- WOL_CTL_DIS_MAGIC_PKT_UNIT)
+-
+-/* WOL_MATCH_CTL 8 bit WOL Match Control Reg */
+-#define WOL_CTL_PATT_ENA(x) (BIT_0 << (x))
+-
+-#define SK_NUM_WOL_PATTERN 7
+-#define SK_PATTERN_PER_WORD 4
+-#define SK_BITMASK_PATTERN 7
+-#define SK_POW_PATTERN_LENGTH 128
+-
+-#define WOL_LENGTH_MSK 0x7f
+-#define WOL_LENGTH_SHIFT 8
+-
+-
+-/* Receive and Transmit Descriptors ******************************************/
+-
+-/* Transmit Descriptor struct */
+-typedef struct s_HwTxd {
+- SK_U32 volatile TxCtrl; /* Transmit Buffer Control Field */
+- SK_U32 TxNext; /* Physical Address Pointer to the next TxD */
+- SK_U32 TxAdrLo; /* Physical Tx Buffer Address lower dword */
+- SK_U32 TxAdrHi; /* Physical Tx Buffer Address upper dword */
+- SK_U32 TxStat; /* Transmit Frame Status Word */
+-#ifndef SK_USE_REV_DESC
+- SK_U16 TxTcpOffs; /* TCP Checksum Calculation Start Value */
+- SK_U16 TxRes1; /* 16 bit reserved field */
+- SK_U16 TxTcpWp; /* TCP Checksum Write Position */
+- SK_U16 TxTcpSp; /* TCP Checksum Calculation Start Position */
+-#else /* SK_USE_REV_DESC */
+- SK_U16 TxRes1; /* 16 bit reserved field */
+- SK_U16 TxTcpOffs; /* TCP Checksum Calculation Start Value */
+- SK_U16 TxTcpSp; /* TCP Checksum Calculation Start Position */
+- SK_U16 TxTcpWp; /* TCP Checksum Write Position */
+-#endif /* SK_USE_REV_DESC */
+- SK_U32 TxRes2; /* 32 bit reserved field */
+-} SK_HWTXD;
+-
+-/* Receive Descriptor struct */
+-typedef struct s_HwRxd {
+- SK_U32 volatile RxCtrl; /* Receive Buffer Control Field */
+- SK_U32 RxNext; /* Physical Address Pointer to the next RxD */
+- SK_U32 RxAdrLo; /* Physical Rx Buffer Address lower dword */
+- SK_U32 RxAdrHi; /* Physical Rx Buffer Address upper dword */
+- SK_U32 RxStat; /* Receive Frame Status Word */
+- SK_U32 RxTiSt; /* Receive Time Stamp (from XMAC on GENESIS) */
+-#ifndef SK_USE_REV_DESC
+- SK_U16 RxTcpSum1; /* TCP Checksum 1 */
+- SK_U16 RxTcpSum2; /* TCP Checksum 2 */
+- SK_U16 RxTcpSp1; /* TCP Checksum Calculation Start Position 1 */
+- SK_U16 RxTcpSp2; /* TCP Checksum Calculation Start Position 2 */
+-#else /* SK_USE_REV_DESC */
+- SK_U16 RxTcpSum2; /* TCP Checksum 2 */
+- SK_U16 RxTcpSum1; /* TCP Checksum 1 */
+- SK_U16 RxTcpSp2; /* TCP Checksum Calculation Start Position 2 */
+- SK_U16 RxTcpSp1; /* TCP Checksum Calculation Start Position 1 */
+-#endif /* SK_USE_REV_DESC */
+-} SK_HWRXD;
+-
+-/*
+- * Drivers which use the reverse descriptor feature (PCI_OUR_REG_2)
+- * should set the define SK_USE_REV_DESC.
+- * Structures are 'normaly' not endianess dependent. But in
+- * this case the SK_U16 fields are bound to bit positions inside the
+- * descriptor. RxTcpSum1 e.g. must start at bit 0 within the 6.th DWord.
+- * The bit positions inside a DWord are of course endianess dependent and
+- * swaps if the DWord is swapped by the hardware.
+- */
+-
+-
+-/* Descriptor Bit Definition */
+-/* TxCtrl Transmit Buffer Control Field */
+-/* RxCtrl Receive Buffer Control Field */
+-#define BMU_OWN BIT_31 /* OWN bit: 0=host/1=BMU */
+-#define BMU_STF BIT_30 /* Start of Frame */
+-#define BMU_EOF BIT_29 /* End of Frame */
+-#define BMU_IRQ_EOB BIT_28 /* Req "End of Buffer" IRQ */
+-#define BMU_IRQ_EOF BIT_27 /* Req "End of Frame" IRQ */
+-/* TxCtrl specific bits */
+-#define BMU_STFWD BIT_26 /* (Tx) Store & Forward Frame */
+-#define BMU_NO_FCS BIT_25 /* (Tx) Disable MAC FCS (CRC) generation */
+-#define BMU_SW BIT_24 /* (Tx) 1 bit res. for SW use */
+-/* RxCtrl specific bits */
+-#define BMU_DEV_0 BIT_26 /* (Rx) Transfer data to Dev0 */
+-#define BMU_STAT_VAL BIT_25 /* (Rx) Rx Status Valid */
+-#define BMU_TIST_VAL BIT_24 /* (Rx) Rx TimeStamp Valid */
+- /* Bit 23..16: BMU Check Opcodes */
+-#define BMU_CHECK (0x55L<<16) /* Default BMU check */
+-#define BMU_TCP_CHECK (0x56L<<16) /* Descr with TCP ext */
+-#define BMU_UDP_CHECK (0x57L<<16) /* Descr with UDP ext (YUKON only) */
+-#define BMU_BBC 0xffffL /* Bit 15.. 0: Buffer Byte Counter */
+-
+-/* TxStat Transmit Frame Status Word */
+-/* RxStat Receive Frame Status Word */
+-/*
+- *Note: TxStat is reserved for ASIC loopback mode only
+- *
+- * The Bits of the Status words are defined in xmac_ii.h
+- * (see XMR_FS bits)
+- */
+-
+-/* macros ********************************************************************/
+-
+-/* Receive and Transmit Queues */
+-#define Q_R1 0x0000 /* Receive Queue 1 */
+-#define Q_R2 0x0080 /* Receive Queue 2 */
+-#define Q_XS1 0x0200 /* Synchronous Transmit Queue 1 */
+-#define Q_XA1 0x0280 /* Asynchronous Transmit Queue 1 */
+-#define Q_XS2 0x0300 /* Synchronous Transmit Queue 2 */
+-#define Q_XA2 0x0380 /* Asynchronous Transmit Queue 2 */
+-
+-/*
+- * Macro Q_ADDR()
+- *
+- * Use this macro to access the Receive and Transmit Queue Registers.
+- *
+- * para:
+- * Queue Queue to access.
+- * Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, and Q_XA2
+- * Offs Queue register offset.
+- * Values: Q_D, Q_DA_L ... Q_T2, Q_T3
+- *
+- * usage SK_IN32(pAC, Q_ADDR(Q_R2, Q_BC), pVal)
+- */
+-#define Q_ADDR(Queue, Offs) (B8_Q_REGS + (Queue) + (Offs))
+-
+-/*
+- * Macro RB_ADDR()
+- *
+- * Use this macro to access the RAM Buffer Registers.
+- *
+- * para:
+- * Queue Queue to access.
+- * Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, and Q_XA2
+- * Offs Queue register offset.
+- * Values: RB_START, RB_END ... RB_LEV, RB_CTRL
+- *
+- * usage SK_IN32(pAC, RB_ADDR(Q_R2, RB_RP), pVal)
+- */
+-#define RB_ADDR(Queue, Offs) (B16_RAM_REGS + (Queue) + (Offs))
+-
+-
+-/* MAC Related Registers */
+-#define MAC_1 0 /* belongs to the port near the slot */
+-#define MAC_2 1 /* belongs to the port far away from the slot */
+-
+-/*
+- * Macro MR_ADDR()
+- *
+- * Use this macro to access a MAC Related Registers inside the ASIC.
+- *
+- * para:
+- * Mac MAC to access.
+- * Values: MAC_1, MAC_2
+- * Offs MAC register offset.
+- * Values: RX_MFF_EA, RX_MFF_WP ... LNK_LED_REG,
+- * TX_MFF_EA, TX_MFF_WP ... TX_LED_TST
+- *
+- * usage SK_IN32(pAC, MR_ADDR(MAC_1, TX_MFF_EA), pVal)
+- */
+-#define MR_ADDR(Mac, Offs) (((Mac) << 7) + (Offs))
+-
+-#ifdef SK_LITTLE_ENDIAN
+-#define XM_WORD_LO 0
+-#define XM_WORD_HI 1
+-#else /* !SK_LITTLE_ENDIAN */
+-#define XM_WORD_LO 1
+-#define XM_WORD_HI 0
+-#endif /* !SK_LITTLE_ENDIAN */
+-
+-
+-/*
+- * macros to access the XMAC (GENESIS only)
+- *
+- * XM_IN16(), to read a 16 bit register (e.g. XM_MMU_CMD)
+- * XM_OUT16(), to write a 16 bit register (e.g. XM_MMU_CMD)
+- * XM_IN32(), to read a 32 bit register (e.g. XM_TX_EV_CNT)
+- * XM_OUT32(), to write a 32 bit register (e.g. XM_TX_EV_CNT)
+- * XM_INADDR(), to read a network address register (e.g. XM_SRC_CHK)
+- * XM_OUTADDR(), to write a network address register (e.g. XM_SRC_CHK)
+- * XM_INHASH(), to read the XM_HSM_CHK register
+- * XM_OUTHASH() to write the XM_HSM_CHK register
+- *
+- * para:
+- * Mac XMAC to access values: MAC_1 or MAC_2
+- * IoC I/O context needed for SK I/O macros
+- * Reg XMAC Register to read or write
+- * (p)Val Value or pointer to the value which should be read or written
+- *
+- * usage: XM_OUT16(IoC, MAC_1, XM_MMU_CMD, Value);
+- */
+-
+-#define XMA(Mac, Reg) \
+- ((BASE_XMAC_1 + (Mac) * (BASE_XMAC_2 - BASE_XMAC_1)) | ((Reg) << 1))
+-
+-#define XM_IN16(IoC, Mac, Reg, pVal) \
+- SK_IN16((IoC), XMA((Mac), (Reg)), (pVal))
+-
+-#define XM_OUT16(IoC, Mac, Reg, Val) \
+- SK_OUT16((IoC), XMA((Mac), (Reg)), (Val))
+-
+-#define XM_IN32(IoC, Mac, Reg, pVal) { \
+- SK_IN16((IoC), XMA((Mac), (Reg)), \
+- (SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_LO]); \
+- SK_IN16((IoC), XMA((Mac), (Reg+2)), \
+- (SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_HI]); \
+-}
+-
+-#define XM_OUT32(IoC, Mac, Reg, Val) { \
+- SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL)); \
+- SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16)(((Val) >> 16) & 0xffffL));\
+-}
+-
+-/* Remember: we are always writing to / reading from LITTLE ENDIAN memory */
+-
+-#define XM_INADDR(IoC, Mac, Reg, pVal) { \
+- SK_U16 Word; \
+- SK_U8 *pByte; \
+- pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \
+- SK_IN16((IoC), XMA((Mac), (Reg)), &Word); \
+- pByte[0] = (SK_U8)(Word & 0x00ff); \
+- pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \
+- SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word); \
+- pByte[2] = (SK_U8)(Word & 0x00ff); \
+- pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \
+- SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word); \
+- pByte[4] = (SK_U8)(Word & 0x00ff); \
+- pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \
+-}
+-
+-#define XM_OUTADDR(IoC, Mac, Reg, pVal) { \
+- SK_U8 SK_FAR *pByte; \
+- pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \
+- SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16) \
+- (((SK_U16)(pByte[0]) & 0x00ff) | \
+- (((SK_U16)(pByte[1]) << 8) & 0xff00))); \
+- SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16) \
+- (((SK_U16)(pByte[2]) & 0x00ff) | \
+- (((SK_U16)(pByte[3]) << 8) & 0xff00))); \
+- SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16) \
+- (((SK_U16)(pByte[4]) & 0x00ff) | \
+- (((SK_U16)(pByte[5]) << 8) & 0xff00))); \
+-}
+-
+-#define XM_INHASH(IoC, Mac, Reg, pVal) { \
+- SK_U16 Word; \
+- SK_U8 SK_FAR *pByte; \
+- pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \
+- SK_IN16((IoC), XMA((Mac), (Reg)), &Word); \
+- pByte[0] = (SK_U8)(Word & 0x00ff); \
+- pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \
+- SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word); \
+- pByte[2] = (SK_U8)(Word & 0x00ff); \
+- pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \
+- SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word); \
+- pByte[4] = (SK_U8)(Word & 0x00ff); \
+- pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \
+- SK_IN16((IoC), XMA((Mac), (Reg+6)), &Word); \
+- pByte[6] = (SK_U8)(Word & 0x00ff); \
+- pByte[7] = (SK_U8)((Word >> 8) & 0x00ff); \
+-}
+-
+-#define XM_OUTHASH(IoC, Mac, Reg, pVal) { \
+- SK_U8 SK_FAR *pByte; \
+- pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \
+- SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16) \
+- (((SK_U16)(pByte[0]) & 0x00ff)| \
+- (((SK_U16)(pByte[1]) << 8) & 0xff00))); \
+- SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16) \
+- (((SK_U16)(pByte[2]) & 0x00ff)| \
+- (((SK_U16)(pByte[3]) << 8) & 0xff00))); \
+- SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16) \
+- (((SK_U16)(pByte[4]) & 0x00ff)| \
+- (((SK_U16)(pByte[5]) << 8) & 0xff00))); \
+- SK_OUT16((IoC), XMA((Mac), (Reg+6)), (SK_U16) \
+- (((SK_U16)(pByte[6]) & 0x00ff)| \
+- (((SK_U16)(pByte[7]) << 8) & 0xff00))); \
+-}
+-
+-/*
+- * macros to access the GMAC (YUKON only)
+- *
+- * GM_IN16(), to read a 16 bit register (e.g. GM_GP_STAT)
+- * GM_OUT16(), to write a 16 bit register (e.g. GM_GP_CTRL)
+- * GM_IN32(), to read a 32 bit register (e.g. GM_)
+- * GM_OUT32(), to write a 32 bit register (e.g. GM_)
+- * GM_INADDR(), to read a network address register (e.g. GM_SRC_ADDR_1L)
+- * GM_OUTADDR(), to write a network address register (e.g. GM_SRC_ADDR_2L)
+- * GM_INHASH(), to read the GM_MC_ADDR_H1 register
+- * GM_OUTHASH() to write the GM_MC_ADDR_H1 register
+- *
+- * para:
+- * Mac GMAC to access values: MAC_1 or MAC_2
+- * IoC I/O context needed for SK I/O macros
+- * Reg GMAC Register to read or write
+- * (p)Val Value or pointer to the value which should be read or written
+- *
+- * usage: GM_OUT16(IoC, MAC_1, GM_GP_CTRL, Value);
+- */
+-
+-#define GMA(Mac, Reg) \
+- ((BASE_GMAC_1 + (Mac) * (BASE_GMAC_2 - BASE_GMAC_1)) | (Reg))
+-
+-#define GM_IN16(IoC, Mac, Reg, pVal) \
+- SK_IN16((IoC), GMA((Mac), (Reg)), (pVal))
+-
+-#define GM_OUT16(IoC, Mac, Reg, Val) \
+- SK_OUT16((IoC), GMA((Mac), (Reg)), (Val))
+-
+-#define GM_IN32(IoC, Mac, Reg, pVal) { \
+- SK_IN16((IoC), GMA((Mac), (Reg)), \
+- (SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_LO]); \
+- SK_IN16((IoC), GMA((Mac), (Reg+4)), \
+- (SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_HI]); \
+-}
+-
+-#define GM_OUT32(IoC, Mac, Reg, Val) { \
+- SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL)); \
+- SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16)(((Val) >> 16) & 0xffffL));\
+-}
+-
+-#define GM_INADDR(IoC, Mac, Reg, pVal) { \
+- SK_U16 Word; \
+- SK_U8 *pByte; \
+- pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \
+- SK_IN16((IoC), GMA((Mac), (Reg)), &Word); \
+- pByte[0] = (SK_U8)(Word & 0x00ff); \
+- pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \
+- SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word); \
+- pByte[2] = (SK_U8)(Word & 0x00ff); \
+- pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \
+- SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word); \
+- pByte[4] = (SK_U8)(Word & 0x00ff); \
+- pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \
+-}
+-
+-#define GM_OUTADDR(IoC, Mac, Reg, pVal) { \
+- SK_U8 SK_FAR *pByte; \
+- pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \
+- SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16) \
+- (((SK_U16)(pByte[0]) & 0x00ff) | \
+- (((SK_U16)(pByte[1]) << 8) & 0xff00))); \
+- SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16) \
+- (((SK_U16)(pByte[2]) & 0x00ff) | \
+- (((SK_U16)(pByte[3]) << 8) & 0xff00))); \
+- SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16) \
+- (((SK_U16)(pByte[4]) & 0x00ff) | \
+- (((SK_U16)(pByte[5]) << 8) & 0xff00))); \
+-}
+-
+-#define GM_INHASH(IoC, Mac, Reg, pVal) { \
+- SK_U16 Word; \
+- SK_U8 *pByte; \
+- pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \
+- SK_IN16((IoC), GMA((Mac), (Reg)), &Word); \
+- pByte[0] = (SK_U8)(Word & 0x00ff); \
+- pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \
+- SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word); \
+- pByte[2] = (SK_U8)(Word & 0x00ff); \
+- pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \
+- SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word); \
+- pByte[4] = (SK_U8)(Word & 0x00ff); \
+- pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \
+- SK_IN16((IoC), GMA((Mac), (Reg+12)), &Word); \
+- pByte[6] = (SK_U8)(Word & 0x00ff); \
+- pByte[7] = (SK_U8)((Word >> 8) & 0x00ff); \
+-}
+-
+-#define GM_OUTHASH(IoC, Mac, Reg, pVal) { \
+- SK_U8 *pByte; \
+- pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \
+- SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16) \
+- (((SK_U16)(pByte[0]) & 0x00ff)| \
+- (((SK_U16)(pByte[1]) << 8) & 0xff00))); \
+- SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16) \
+- (((SK_U16)(pByte[2]) & 0x00ff)| \
+- (((SK_U16)(pByte[3]) << 8) & 0xff00))); \
+- SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16) \
+- (((SK_U16)(pByte[4]) & 0x00ff)| \
+- (((SK_U16)(pByte[5]) << 8) & 0xff00))); \
+- SK_OUT16((IoC), GMA((Mac), (Reg+12)), (SK_U16) \
+- (((SK_U16)(pByte[6]) & 0x00ff)| \
+- (((SK_U16)(pByte[7]) << 8) & 0xff00))); \
+-}
+-
+-/*
+- * Different MAC Types
+- */
+-#define SK_MAC_XMAC 0 /* Xaqti XMAC II */
+-#define SK_MAC_GMAC 1 /* Marvell GMAC */
+-
+-/*
+- * Different PHY Types
+- */
+-#define SK_PHY_XMAC 0 /* integrated in XMAC II */
+-#define SK_PHY_BCOM 1 /* Broadcom BCM5400 */
+-#define SK_PHY_LONE 2 /* Level One LXT1000 */
+-#define SK_PHY_NAT 3 /* National DP83891 */
+-#define SK_PHY_MARV_COPPER 4 /* Marvell 88E1011S */
+-#define SK_PHY_MARV_FIBER 5 /* Marvell 88E1011S working on fiber */
+-
+-/*
+- * PHY addresses (bits 12..8 of PHY address reg)
+- */
+-#define PHY_ADDR_XMAC (0<<8)
+-#define PHY_ADDR_BCOM (1<<8)
+-#define PHY_ADDR_LONE (3<<8)
+-#define PHY_ADDR_NAT (0<<8)
+-
+-/* GPHY address (bits 15..11 of SMI control reg) */
+-#define PHY_ADDR_MARV 0
+-
+-/*
+- * macros to access the PHY
+- *
+- * PHY_READ() read a 16 bit value from the PHY
+- * PHY_WRITE() write a 16 bit value to the PHY
+- *
+- * para:
+- * IoC I/O context needed for SK I/O macros
+- * pPort Pointer to port struct for PhyAddr
+- * Mac XMAC to access values: MAC_1 or MAC_2
+- * PhyReg PHY Register to read or write
+- * (p)Val Value or pointer to the value which should be read or
+- * written.
+- *
+- * usage: PHY_READ(IoC, pPort, MAC_1, PHY_CTRL, Value);
+- * Warning: a PHY_READ on an uninitialized PHY (PHY still in reset) never
+- * comes back. This is checked in DEBUG mode.
+- */
+-#ifndef DEBUG
+-#define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) { \
+- SK_U16 Mmu; \
+- \
+- XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \
+- XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \
+- if ((pPort)->PhyType != SK_PHY_XMAC) { \
+- do { \
+- XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \
+- } while ((Mmu & XM_MMU_PHY_RDY) == 0); \
+- XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \
+- } \
+-}
+-#else
+-#define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) { \
+- SK_U16 Mmu; \
+- int __i = 0; \
+- \
+- XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \
+- XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \
+- if ((pPort)->PhyType != SK_PHY_XMAC) { \
+- do { \
+- XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \
+- __i++; \
+- if (__i > 100000) { \
+- SK_DBG_PRINTF("*****************************\n"); \
+- SK_DBG_PRINTF("PHY_READ on uninitialized PHY\n"); \
+- SK_DBG_PRINTF("*****************************\n"); \
+- break; \
+- } \
+- } while ((Mmu & XM_MMU_PHY_RDY) == 0); \
+- XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \
+- } \
+-}
+-#endif /* DEBUG */
+-
+-#define PHY_WRITE(IoC, pPort, Mac, PhyReg, Val) { \
+- SK_U16 Mmu; \
+- \
+- if ((pPort)->PhyType != SK_PHY_XMAC) { \
+- do { \
+- XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \
+- } while ((Mmu & XM_MMU_PHY_BUSY) != 0); \
+- } \
+- XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \
+- XM_OUT16((IoC), (Mac), XM_PHY_DATA, (Val)); \
+- if ((pPort)->PhyType != SK_PHY_XMAC) { \
+- do { \
+- XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \
+- } while ((Mmu & XM_MMU_PHY_BUSY) != 0); \
+- } \
+-}
+-
+-/*
+- * Macro PCI_C()
+- *
+- * Use this macro to access PCI config register from the I/O space.
+- *
+- * para:
+- * Addr PCI configuration register to access.
+- * Values: PCI_VENDOR_ID ... PCI_VPD_ADR_REG,
+- *
+- * usage SK_IN16(pAC, PCI_C(PCI_VENDOR_ID), pVal);
+- */
+-#define PCI_C(Addr) (B7_CFG_SPC + (Addr)) /* PCI Config Space */
+-
+-/*
+- * Macro SK_HW_ADDR(Base, Addr)
+- *
+- * Calculates the effective HW address
+- *
+- * para:
+- * Base I/O or memory base address
+- * Addr Address offset
+- *
+- * usage: May be used in SK_INxx and SK_OUTxx macros
+- * #define SK_IN8(pAC, Addr, pVal) ...\
+- * *pVal = (SK_U8)inp(SK_HW_ADDR(pAC->Hw.Iop, Addr)))
+- */
+-#ifdef SK_MEM_MAPPED_IO
+-#define SK_HW_ADDR(Base, Addr) ((Base) + (Addr))
+-#else /* SK_MEM_MAPPED_IO */
+-#define SK_HW_ADDR(Base, Addr) \
+- ((Base) + (((Addr) & 0x7f) | (((Addr) >> 7 > 0) ? 0x80 : 0)))
+-#endif /* SK_MEM_MAPPED_IO */
+-
+-#define SZ_LONG (sizeof(SK_U32))
+-
+-/*
+- * Macro SK_HWAC_LINK_LED()
+- *
+- * Use this macro to set the link LED mode.
+- * para:
+- * pAC Pointer to adapter context struct
+- * IoC I/O context needed for SK I/O macros
+- * Port Port number
+- * Mode Mode to set for this LED
+- */
+-#define SK_HWAC_LINK_LED(pAC, IoC, Port, Mode) \
+- SK_OUT8(IoC, MR_ADDR(Port, LNK_LED_REG), Mode);
+-
+-
+-/* typedefs *******************************************************************/
+-
+-
+-/* function prototypes ********************************************************/
+-
+-#ifdef __cplusplus
+-}
+-#endif /* __cplusplus */
+-
+-#endif /* __INC_SKGEHW_H */
+diff --git a/drivers/net/sk98lin/h/skgehwt.h b/drivers/net/sk98lin/h/skgehwt.h
+deleted file mode 100644
+index e6b0016..0000000
+--- a/drivers/net/sk98lin/h/skgehwt.h
++++ /dev/null
+@@ -1,48 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skhwt.h
+- * Project: Gigabit Ethernet Adapters, Event Scheduler Module
+- * Version: $Revision: 1.7 $
+- * Date: $Date: 2003/09/16 12:55:08 $
+- * Purpose: Defines for the hardware timer functions
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- * SKGEHWT.H contains all defines and types for the timer functions
+- */
+-
+-#ifndef _SKGEHWT_H_
+-#define _SKGEHWT_H_
+-
+-/*
+- * SK Hardware Timer
+- * - needed wherever the HWT module is used
+- * - use in Adapters context name pAC->Hwt
+- */
+-typedef struct s_Hwt {
+- SK_U32 TStart; /* HWT start */
+- SK_U32 TStop; /* HWT stop */
+- int TActive; /* HWT: flag : active/inactive */
+-} SK_HWT;
+-
+-extern void SkHwtInit(SK_AC *pAC, SK_IOC Ioc);
+-extern void SkHwtStart(SK_AC *pAC, SK_IOC Ioc, SK_U32 Time);
+-extern void SkHwtStop(SK_AC *pAC, SK_IOC Ioc);
+-extern SK_U32 SkHwtRead(SK_AC *pAC, SK_IOC Ioc);
+-extern void SkHwtIsr(SK_AC *pAC, SK_IOC Ioc);
+-#endif /* _SKGEHWT_H_ */
+diff --git a/drivers/net/sk98lin/h/skgei2c.h b/drivers/net/sk98lin/h/skgei2c.h
+deleted file mode 100644
+index d9b6f6d..0000000
+--- a/drivers/net/sk98lin/h/skgei2c.h
++++ /dev/null
+@@ -1,210 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skgei2c.h
+- * Project: Gigabit Ethernet Adapters, TWSI-Module
+- * Version: $Revision: 1.25 $
+- * Date: $Date: 2003/10/20 09:06:05 $
+- * Purpose: Special defines for TWSI
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- * SKGEI2C.H contains all SK-98xx specific defines for the TWSI handling
+- */
+-
+-#ifndef _INC_SKGEI2C_H_
+-#define _INC_SKGEI2C_H_
+-
+-/*
+- * Macros to access the B2_I2C_CTRL
+- */
+-#define SK_I2C_CTL(IoC, flag, dev, dev_size, reg, burst) \
+- SK_OUT32(IoC, B2_I2C_CTRL,\
+- (flag ? 0x80000000UL : 0x0L) | \
+- (((SK_U32)reg << 16) & I2C_ADDR) | \
+- (((SK_U32)dev << 9) & I2C_DEV_SEL) | \
+- (dev_size & I2C_DEV_SIZE) | \
+- ((burst << 4) & I2C_BURST_LEN))
+-
+-#define SK_I2C_STOP(IoC) { \
+- SK_U32 I2cCtrl; \
+- SK_IN32(IoC, B2_I2C_CTRL, &I2cCtrl); \
+- SK_OUT32(IoC, B2_I2C_CTRL, I2cCtrl | I2C_STOP); \
+-}
+-
+-#define SK_I2C_GET_CTL(IoC, pI2cCtrl) SK_IN32(IoC, B2_I2C_CTRL, pI2cCtrl)
+-
+-/*
+- * Macros to access the TWSI SW Registers
+- */
+-#define SK_I2C_SET_BIT(IoC, SetBits) { \
+- SK_U8 OrgBits; \
+- SK_IN8(IoC, B2_I2C_SW, &OrgBits); \
+- SK_OUT8(IoC, B2_I2C_SW, OrgBits | (SK_U8)(SetBits)); \
+-}
+-
+-#define SK_I2C_CLR_BIT(IoC, ClrBits) { \
+- SK_U8 OrgBits; \
+- SK_IN8(IoC, B2_I2C_SW, &OrgBits); \
+- SK_OUT8(IoC, B2_I2C_SW, OrgBits & ~((SK_U8)(ClrBits))); \
+-}
+-
+-#define SK_I2C_GET_SW(IoC, pI2cSw) SK_IN8(IoC, B2_I2C_SW, pI2cSw)
+-
+-/*
+- * define the possible sensor states
+- */
+-#define SK_SEN_IDLE 0 /* Idle: sensor not read */
+-#define SK_SEN_VALUE 1 /* Value Read cycle */
+-#define SK_SEN_VALEXT 2 /* Extended Value Read cycle */
+-
+-/*
+- * Conversion factor to convert read Voltage sensor to milli Volt
+- * Conversion factor to convert read Temperature sensor to 10th degree Celsius
+- */
+-#define SK_LM80_VT_LSB 22 /* 22mV LSB resolution */
+-#define SK_LM80_TEMP_LSB 10 /* 1 degree LSB resolution */
+-#define SK_LM80_TEMPEXT_LSB 5 /* 0.5 degree LSB resolution for ext. val. */
+-
+-/*
+- * formula: counter = (22500*60)/(rpm * divisor * pulses/2)
+- * assuming: 6500rpm, 4 pulses, divisor 1
+- */
+-#define SK_LM80_FAN_FAKTOR ((22500L*60)/(1*2))
+-
+-/*
+- * Define sensor management data
+- * Maximum is reached on Genesis copper dual port and Yukon-64
+- * Board specific maximum is in pAC->I2c.MaxSens
+- */
+-#define SK_MAX_SENSORS 8 /* maximal no. of installed sensors */
+-#define SK_MIN_SENSORS 5 /* minimal no. of installed sensors */
+-
+-/*
+- * To watch the state machine (SM) use the timer in two ways
+- * instead of one as hitherto
+- */
+-#define SK_TIMER_WATCH_SM 0 /* Watch the SM to finish in a spec. time */
+-#define SK_TIMER_NEW_GAUGING 1 /* Start a new gauging when timer expires */
+-
+-/*
+- * Defines for the individual thresholds
+- */
+-
+-/* Temperature sensor */
+-#define SK_SEN_TEMP_HIGH_ERR 800 /* Temperature High Err Threshold */
+-#define SK_SEN_TEMP_HIGH_WARN 700 /* Temperature High Warn Threshold */
+-#define SK_SEN_TEMP_LOW_WARN 100 /* Temperature Low Warn Threshold */
+-#define SK_SEN_TEMP_LOW_ERR 0 /* Temperature Low Err Threshold */
+-
+-/* VCC which should be 5 V */
+-#define SK_SEN_PCI_5V_HIGH_ERR 5588 /* Voltage PCI High Err Threshold */
+-#define SK_SEN_PCI_5V_HIGH_WARN 5346 /* Voltage PCI High Warn Threshold */
+-#define SK_SEN_PCI_5V_LOW_WARN 4664 /* Voltage PCI Low Warn Threshold */
+-#define SK_SEN_PCI_5V_LOW_ERR 4422 /* Voltage PCI Low Err Threshold */
+-
+-/*
+- * VIO may be 5 V or 3.3 V. Initialization takes two parts:
+- * 1. Initialize lowest lower limit and highest higher limit.
+- * 2. After the first value is read correct the upper or the lower limit to
+- * the appropriate C constant.
+- *
+- * Warning limits are +-5% of the exepected voltage.
+- * Error limits are +-10% of the expected voltage.
+- */
+-
+-/* Bug fix AF: 16.Aug.2001: Correct the init base of LM80 sensor */
+-
+-#define SK_SEN_PCI_IO_5V_HIGH_ERR 5566 /* + 10% V PCI-IO High Err Threshold */
+-#define SK_SEN_PCI_IO_5V_HIGH_WARN 5324 /* + 5% V PCI-IO High Warn Threshold */
+- /* 5000 mVolt */
+-#define SK_SEN_PCI_IO_5V_LOW_WARN 4686 /* - 5% V PCI-IO Low Warn Threshold */
+-#define SK_SEN_PCI_IO_5V_LOW_ERR 4444 /* - 10% V PCI-IO Low Err Threshold */
+-
+-#define SK_SEN_PCI_IO_RANGE_LIMITER 4000 /* 4000 mV range delimiter */
+-
+-/* correction values for the second pass */
+-#define SK_SEN_PCI_IO_3V3_HIGH_ERR 3850 /* + 15% V PCI-IO High Err Threshold */
+-#define SK_SEN_PCI_IO_3V3_HIGH_WARN 3674 /* + 10% V PCI-IO High Warn Threshold */
+- /* 3300 mVolt */
+-#define SK_SEN_PCI_IO_3V3_LOW_WARN 2926 /* - 10% V PCI-IO Low Warn Threshold */
+-#define SK_SEN_PCI_IO_3V3_LOW_ERR 2772 /* - 15% V PCI-IO Low Err Threshold */
+-
+-/*
+- * VDD voltage
+- */
+-#define SK_SEN_VDD_HIGH_ERR 3630 /* Voltage ASIC High Err Threshold */
+-#define SK_SEN_VDD_HIGH_WARN 3476 /* Voltage ASIC High Warn Threshold */
+-#define SK_SEN_VDD_LOW_WARN 3146 /* Voltage ASIC Low Warn Threshold */
+-#define SK_SEN_VDD_LOW_ERR 2970 /* Voltage ASIC Low Err Threshold */
+-
+-/*
+- * PHY PLL 3V3 voltage
+- */
+-#define SK_SEN_PLL_3V3_HIGH_ERR 3630 /* Voltage PMA High Err Threshold */
+-#define SK_SEN_PLL_3V3_HIGH_WARN 3476 /* Voltage PMA High Warn Threshold */
+-#define SK_SEN_PLL_3V3_LOW_WARN 3146 /* Voltage PMA Low Warn Threshold */
+-#define SK_SEN_PLL_3V3_LOW_ERR 2970 /* Voltage PMA Low Err Threshold */
+-
+-/*
+- * VAUX (YUKON only)
+- */
+-#define SK_SEN_VAUX_3V3_HIGH_ERR 3630 /* Voltage VAUX High Err Threshold */
+-#define SK_SEN_VAUX_3V3_HIGH_WARN 3476 /* Voltage VAUX High Warn Threshold */
+-#define SK_SEN_VAUX_3V3_LOW_WARN 3146 /* Voltage VAUX Low Warn Threshold */
+-#define SK_SEN_VAUX_3V3_LOW_ERR 2970 /* Voltage VAUX Low Err Threshold */
+-#define SK_SEN_VAUX_0V_WARN_ERR 0 /* if VAUX not present */
+-#define SK_SEN_VAUX_RANGE_LIMITER 1000 /* 1000 mV range delimiter */
+-
+-/*
+- * PHY 2V5 voltage
+- */
+-#define SK_SEN_PHY_2V5_HIGH_ERR 2750 /* Voltage PHY High Err Threshold */
+-#define SK_SEN_PHY_2V5_HIGH_WARN 2640 /* Voltage PHY High Warn Threshold */
+-#define SK_SEN_PHY_2V5_LOW_WARN 2376 /* Voltage PHY Low Warn Threshold */
+-#define SK_SEN_PHY_2V5_LOW_ERR 2222 /* Voltage PHY Low Err Threshold */
+-
+-/*
+- * ASIC Core 1V5 voltage (YUKON only)
+- */
+-#define SK_SEN_CORE_1V5_HIGH_ERR 1650 /* Voltage ASIC Core High Err Threshold */
+-#define SK_SEN_CORE_1V5_HIGH_WARN 1575 /* Voltage ASIC Core High Warn Threshold */
+-#define SK_SEN_CORE_1V5_LOW_WARN 1425 /* Voltage ASIC Core Low Warn Threshold */
+-#define SK_SEN_CORE_1V5_LOW_ERR 1350 /* Voltage ASIC Core Low Err Threshold */
+-
+-/*
+- * FAN 1 speed
+- */
+-/* assuming: 6500rpm +-15%, 4 pulses,
+- * warning at: 80 %
+- * error at: 70 %
+- * no upper limit
+- */
+-#define SK_SEN_FAN_HIGH_ERR 20000 /* FAN Speed High Err Threshold */
+-#define SK_SEN_FAN_HIGH_WARN 20000 /* FAN Speed High Warn Threshold */
+-#define SK_SEN_FAN_LOW_WARN 5200 /* FAN Speed Low Warn Threshold */
+-#define SK_SEN_FAN_LOW_ERR 4550 /* FAN Speed Low Err Threshold */
+-
+-/*
+- * Some Voltages need dynamic thresholds
+- */
+-#define SK_SEN_DYN_INIT_NONE 0 /* No dynamic init of thresholds */
+-#define SK_SEN_DYN_INIT_PCI_IO 10 /* Init PCI-IO with new thresholds */
+-#define SK_SEN_DYN_INIT_VAUX 11 /* Init VAUX with new thresholds */
+-
+-extern int SkLm80ReadSensor(SK_AC *pAC, SK_IOC IoC, SK_SENSOR *pSen);
+-#endif /* n_INC_SKGEI2C_H */
+diff --git a/drivers/net/sk98lin/h/skgeinit.h b/drivers/net/sk98lin/h/skgeinit.h
+deleted file mode 100644
+index 143e635..0000000
+--- a/drivers/net/sk98lin/h/skgeinit.h
++++ /dev/null
+@@ -1,797 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skgeinit.h
+- * Project: Gigabit Ethernet Adapters, Common Modules
+- * Version: $Revision: 1.83 $
+- * Date: $Date: 2003/09/16 14:07:37 $
+- * Purpose: Structures and prototypes for the GE Init Module
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#ifndef __INC_SKGEINIT_H_
+-#define __INC_SKGEINIT_H_
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif /* __cplusplus */
+-
+-/* defines ********************************************************************/
+-
+-#define SK_TEST_VAL 0x11335577UL
+-
+-/* modifying Link LED behaviour (used with SkGeLinkLED()) */
+-#define SK_LNK_OFF LED_OFF
+-#define SK_LNK_ON (LED_ON | LED_BLK_OFF | LED_SYNC_OFF)
+-#define SK_LNK_BLINK (LED_ON | LED_BLK_ON | LED_SYNC_ON)
+-#define SK_LNK_PERM (LED_ON | LED_BLK_OFF | LED_SYNC_ON)
+-#define SK_LNK_TST (LED_ON | LED_BLK_ON | LED_SYNC_OFF)
+-
+-/* parameter 'Mode' when calling SK_HWAC_LINK_LED() */
+-#define SK_LED_OFF LED_OFF
+-#define SK_LED_ACTIVE (LED_ON | LED_BLK_OFF | LED_SYNC_OFF)
+-#define SK_LED_STANDBY (LED_ON | LED_BLK_ON | LED_SYNC_OFF)
+-
+-/* addressing LED Registers in SkGeXmitLED() */
+-#define XMIT_LED_INI 0
+-#define XMIT_LED_CNT (RX_LED_VAL - RX_LED_INI)
+-#define XMIT_LED_CTRL (RX_LED_CTRL- RX_LED_INI)
+-#define XMIT_LED_TST (RX_LED_TST - RX_LED_INI)
+-
+-/* parameter 'Mode' when calling SkGeXmitLED() */
+-#define SK_LED_DIS 0
+-#define SK_LED_ENA 1
+-#define SK_LED_TST 2
+-
+-/* Counter and Timer constants, for a host clock of 62.5 MHz */
+-#define SK_XMIT_DUR 0x002faf08UL /* 50 ms */
+-#define SK_BLK_DUR 0x01dcd650UL /* 500 ms */
+-
+-#define SK_DPOLL_DEF 0x00ee6b28UL /* 250 ms at 62.5 MHz */
+-
+-#define SK_DPOLL_MAX 0x00ffffffUL /* 268 ms at 62.5 MHz */
+- /* 215 ms at 78.12 MHz */
+-
+-#define SK_FACT_62 100 /* is given in percent */
+-#define SK_FACT_53 85 /* on GENESIS: 53.12 MHz */
+-#define SK_FACT_78 125 /* on YUKON: 78.12 MHz */
+-
+-/* Timeout values */
+-#define SK_MAC_TO_53 72 /* MAC arbiter timeout */
+-#define SK_PKT_TO_53 0x2000 /* Packet arbiter timeout */
+-#define SK_PKT_TO_MAX 0xffff /* Maximum value */
+-#define SK_RI_TO_53 36 /* RAM interface timeout */
+-
+-#define SK_PHY_ACC_TO 600000 /* PHY access timeout */
+-
+-/* RAM Buffer High Pause Threshold values */
+-#define SK_RB_ULPP ( 8 * 1024) /* Upper Level in kB/8 */
+-#define SK_RB_LLPP_S (10 * 1024) /* Lower Level for small Queues */
+-#define SK_RB_LLPP_B (16 * 1024) /* Lower Level for big Queues */
+-
+-#ifndef SK_BMU_RX_WM
+-#define SK_BMU_RX_WM 0x600 /* BMU Rx Watermark */
+-#endif
+-#ifndef SK_BMU_TX_WM
+-#define SK_BMU_TX_WM 0x600 /* BMU Tx Watermark */
+-#endif
+-
+-/* XMAC II Rx High Watermark */
+-#define SK_XM_RX_HI_WM 0x05aa /* 1450 */
+-
+-/* XMAC II Tx Threshold */
+-#define SK_XM_THR_REDL 0x01fb /* .. for redundant link usage */
+-#define SK_XM_THR_SL 0x01fb /* .. for single link adapters */
+-#define SK_XM_THR_MULL 0x01fb /* .. for multiple link usage */
+-#define SK_XM_THR_JUMBO 0x03fc /* .. for jumbo frame usage */
+-
+-/* values for GIPortUsage */
+-#define SK_RED_LINK 1 /* redundant link usage */
+-#define SK_MUL_LINK 2 /* multiple link usage */
+-#define SK_JUMBO_LINK 3 /* driver uses jumbo frames */
+-
+-/* Minimum RAM Buffer Rx Queue Size */
+-#define SK_MIN_RXQ_SIZE 16 /* 16 kB */
+-
+-/* Minimum RAM Buffer Tx Queue Size */
+-#define SK_MIN_TXQ_SIZE 16 /* 16 kB */
+-
+-/* Queue Size units */
+-#define QZ_UNITS 0x7
+-#define QZ_STEP 8
+-
+-/* Percentage of queue size from whole memory */
+-/* 80 % for receive */
+-#define RAM_QUOTA_RX 80L
+-/* 0% for sync transfer */
+-#define RAM_QUOTA_SYNC 0L
+-/* the rest (20%) is taken for async transfer */
+-
+-/* Get the rounded queue size in Bytes in 8k steps */
+-#define ROUND_QUEUE_SIZE(SizeInBytes) \
+- ((((unsigned long) (SizeInBytes) + (QZ_STEP*1024L)-1) / 1024) & \
+- ~(QZ_STEP-1))
+-
+-/* Get the rounded queue size in KBytes in 8k steps */
+-#define ROUND_QUEUE_SIZE_KB(Kilobytes) \
+- ROUND_QUEUE_SIZE((Kilobytes) * 1024L)
+-
+-/* Types of RAM Buffer Queues */
+-#define SK_RX_SRAM_Q 1 /* small receive queue */
+-#define SK_RX_BRAM_Q 2 /* big receive queue */
+-#define SK_TX_RAM_Q 3 /* small or big transmit queue */
+-
+-/* parameter 'Dir' when calling SkGeStopPort() */
+-#define SK_STOP_TX 1 /* Stops the transmit path, resets the XMAC */
+-#define SK_STOP_RX 2 /* Stops the receive path */
+-#define SK_STOP_ALL 3 /* Stops Rx and Tx path, resets the XMAC */
+-
+-/* parameter 'RstMode' when calling SkGeStopPort() */
+-#define SK_SOFT_RST 1 /* perform a software reset */
+-#define SK_HARD_RST 2 /* perform a hardware reset */
+-
+-/* Init Levels */
+-#define SK_INIT_DATA 0 /* Init level 0: init data structures */
+-#define SK_INIT_IO 1 /* Init level 1: init with IOs */
+-#define SK_INIT_RUN 2 /* Init level 2: init for run time */
+-
+-/* Link Mode Parameter */
+-#define SK_LMODE_HALF 1 /* Half Duplex Mode */
+-#define SK_LMODE_FULL 2 /* Full Duplex Mode */
+-#define SK_LMODE_AUTOHALF 3 /* AutoHalf Duplex Mode */
+-#define SK_LMODE_AUTOFULL 4 /* AutoFull Duplex Mode */
+-#define SK_LMODE_AUTOBOTH 5 /* AutoBoth Duplex Mode */
+-#define SK_LMODE_AUTOSENSE 6 /* configured mode auto sensing */
+-#define SK_LMODE_INDETERMINATED 7 /* indeterminated */
+-
+-/* Auto-negotiation timeout in 100ms granularity */
+-#define SK_AND_MAX_TO 6 /* Wait 600 msec before link comes up */
+-
+-/* Auto-negotiation error codes */
+-#define SK_AND_OK 0 /* no error */
+-#define SK_AND_OTHER 1 /* other error than below */
+-#define SK_AND_DUP_CAP 2 /* Duplex capabilities error */
+-
+-
+-/* Link Speed Capabilities */
+-#define SK_LSPEED_CAP_AUTO (1<<0) /* Automatic resolution */
+-#define SK_LSPEED_CAP_10MBPS (1<<1) /* 10 Mbps */
+-#define SK_LSPEED_CAP_100MBPS (1<<2) /* 100 Mbps */
+-#define SK_LSPEED_CAP_1000MBPS (1<<3) /* 1000 Mbps */
+-#define SK_LSPEED_CAP_INDETERMINATED (1<<4) /* indeterminated */
+-
+-/* Link Speed Parameter */
+-#define SK_LSPEED_AUTO 1 /* Automatic resolution */
+-#define SK_LSPEED_10MBPS 2 /* 10 Mbps */
+-#define SK_LSPEED_100MBPS 3 /* 100 Mbps */
+-#define SK_LSPEED_1000MBPS 4 /* 1000 Mbps */
+-#define SK_LSPEED_INDETERMINATED 5 /* indeterminated */
+-
+-/* Link Speed Current State */
+-#define SK_LSPEED_STAT_UNKNOWN 1
+-#define SK_LSPEED_STAT_10MBPS 2
+-#define SK_LSPEED_STAT_100MBPS 3
+-#define SK_LSPEED_STAT_1000MBPS 4
+-#define SK_LSPEED_STAT_INDETERMINATED 5
+-
+-
+-/* Link Capability Parameter */
+-#define SK_LMODE_CAP_HALF (1<<0) /* Half Duplex Mode */
+-#define SK_LMODE_CAP_FULL (1<<1) /* Full Duplex Mode */
+-#define SK_LMODE_CAP_AUTOHALF (1<<2) /* AutoHalf Duplex Mode */
+-#define SK_LMODE_CAP_AUTOFULL (1<<3) /* AutoFull Duplex Mode */
+-#define SK_LMODE_CAP_INDETERMINATED (1<<4) /* indeterminated */
+-
+-/* Link Mode Current State */
+-#define SK_LMODE_STAT_UNKNOWN 1 /* Unknown Duplex Mode */
+-#define SK_LMODE_STAT_HALF 2 /* Half Duplex Mode */
+-#define SK_LMODE_STAT_FULL 3 /* Full Duplex Mode */
+-#define SK_LMODE_STAT_AUTOHALF 4 /* Half Duplex Mode obtained by Auto-Neg */
+-#define SK_LMODE_STAT_AUTOFULL 5 /* Full Duplex Mode obtained by Auto-Neg */
+-#define SK_LMODE_STAT_INDETERMINATED 6 /* indeterminated */
+-
+-/* Flow Control Mode Parameter (and capabilities) */
+-#define SK_FLOW_MODE_NONE 1 /* No Flow-Control */
+-#define SK_FLOW_MODE_LOC_SEND 2 /* Local station sends PAUSE */
+-#define SK_FLOW_MODE_SYMMETRIC 3 /* Both stations may send PAUSE */
+-#define SK_FLOW_MODE_SYM_OR_REM 4 /* Both stations may send PAUSE or
+- * just the remote station may send PAUSE
+- */
+-#define SK_FLOW_MODE_INDETERMINATED 5 /* indeterminated */
+-
+-/* Flow Control Status Parameter */
+-#define SK_FLOW_STAT_NONE 1 /* No Flow Control */
+-#define SK_FLOW_STAT_REM_SEND 2 /* Remote Station sends PAUSE */
+-#define SK_FLOW_STAT_LOC_SEND 3 /* Local station sends PAUSE */
+-#define SK_FLOW_STAT_SYMMETRIC 4 /* Both station may send PAUSE */
+-#define SK_FLOW_STAT_INDETERMINATED 5 /* indeterminated */
+-
+-/* Master/Slave Mode Capabilities */
+-#define SK_MS_CAP_AUTO (1<<0) /* Automatic resolution */
+-#define SK_MS_CAP_MASTER (1<<1) /* This station is master */
+-#define SK_MS_CAP_SLAVE (1<<2) /* This station is slave */
+-#define SK_MS_CAP_INDETERMINATED (1<<3) /* indeterminated */
+-
+-/* Set Master/Slave Mode Parameter (and capabilities) */
+-#define SK_MS_MODE_AUTO 1 /* Automatic resolution */
+-#define SK_MS_MODE_MASTER 2 /* This station is master */
+-#define SK_MS_MODE_SLAVE 3 /* This station is slave */
+-#define SK_MS_MODE_INDETERMINATED 4 /* indeterminated */
+-
+-/* Master/Slave Status Parameter */
+-#define SK_MS_STAT_UNSET 1 /* The M/S status is not set */
+-#define SK_MS_STAT_MASTER 2 /* This station is master */
+-#define SK_MS_STAT_SLAVE 3 /* This station is slave */
+-#define SK_MS_STAT_FAULT 4 /* M/S resolution failed */
+-#define SK_MS_STAT_INDETERMINATED 5 /* indeterminated */
+-
+-/* parameter 'Mode' when calling SkXmSetRxCmd() */
+-#define SK_STRIP_FCS_ON (1<<0) /* Enable FCS stripping of Rx frames */
+-#define SK_STRIP_FCS_OFF (1<<1) /* Disable FCS stripping of Rx frames */
+-#define SK_STRIP_PAD_ON (1<<2) /* Enable pad byte stripping of Rx fr */
+-#define SK_STRIP_PAD_OFF (1<<3) /* Disable pad byte stripping of Rx fr */
+-#define SK_LENERR_OK_ON (1<<4) /* Don't chk fr for in range len error */
+-#define SK_LENERR_OK_OFF (1<<5) /* Check frames for in range len error */
+-#define SK_BIG_PK_OK_ON (1<<6) /* Don't set Rx Error bit for big frames */
+-#define SK_BIG_PK_OK_OFF (1<<7) /* Set Rx Error bit for big frames */
+-#define SK_SELF_RX_ON (1<<8) /* Enable Rx of own packets */
+-#define SK_SELF_RX_OFF (1<<9) /* Disable Rx of own packets */
+-
+-/* parameter 'Para' when calling SkMacSetRxTxEn() */
+-#define SK_MAC_LOOPB_ON (1<<0) /* Enable MAC Loopback Mode */
+-#define SK_MAC_LOOPB_OFF (1<<1) /* Disable MAC Loopback Mode */
+-#define SK_PHY_LOOPB_ON (1<<2) /* Enable PHY Loopback Mode */
+-#define SK_PHY_LOOPB_OFF (1<<3) /* Disable PHY Loopback Mode */
+-#define SK_PHY_FULLD_ON (1<<4) /* Enable GMII Full Duplex */
+-#define SK_PHY_FULLD_OFF (1<<5) /* Disable GMII Full Duplex */
+-
+-/* States of PState */
+-#define SK_PRT_RESET 0 /* the port is reset */
+-#define SK_PRT_STOP 1 /* the port is stopped (similar to SW reset) */
+-#define SK_PRT_INIT 2 /* the port is initialized */
+-#define SK_PRT_RUN 3 /* the port has an active link */
+-
+-/* PHY power down modes */
+-#define PHY_PM_OPERATIONAL_MODE 0 /* PHY operational mode */
+-#define PHY_PM_DEEP_SLEEP 1 /* coma mode --> minimal power */
+-#define PHY_PM_IEEE_POWER_DOWN 2 /* IEEE 22.2.4.1.5 compl. power down */
+-#define PHY_PM_ENERGY_DETECT 3 /* energy detect */
+-#define PHY_PM_ENERGY_DETECT_PLUS 4 /* energy detect plus */
+-
+-/* Default receive frame limit for Workaround of XMAC Errata */
+-#define SK_DEF_RX_WA_LIM SK_CONSTU64(100)
+-
+-/* values for GILedBlinkCtrl (LED Blink Control) */
+-#define SK_ACT_LED_BLINK (1<<0) /* Active LED blinking */
+-#define SK_DUP_LED_NORMAL (1<<1) /* Duplex LED normal */
+-#define SK_LED_LINK100_ON (1<<2) /* Link 100M LED on */
+-
+-/* Link Partner Status */
+-#define SK_LIPA_UNKNOWN 0 /* Link partner is in unknown state */
+-#define SK_LIPA_MANUAL 1 /* Link partner is in detected manual state */
+-#define SK_LIPA_AUTO 2 /* Link partner is in auto-negotiation state */
+-
+-/* Maximum Restarts before restart is ignored (3Com WA) */
+-#define SK_MAX_LRESTART 3 /* Max. 3 times the link is restarted */
+-
+-/* Max. Auto-neg. timeouts before link detection in sense mode is reset */
+-#define SK_MAX_ANEG_TO 10 /* Max. 10 times the sense mode is reset */
+-
+-/* structures *****************************************************************/
+-
+-/*
+- * MAC specific functions
+- */
+-typedef struct s_GeMacFunc {
+- int (*pFnMacUpdateStats)(SK_AC *pAC, SK_IOC IoC, unsigned int Port);
+- int (*pFnMacStatistic)(SK_AC *pAC, SK_IOC IoC, unsigned int Port,
+- SK_U16 StatAddr, SK_U32 SK_FAR *pVal);
+- int (*pFnMacResetCounter)(SK_AC *pAC, SK_IOC IoC, unsigned int Port);
+- int (*pFnMacOverflow)(SK_AC *pAC, SK_IOC IoC, unsigned int Port,
+- SK_U16 IStatus, SK_U64 SK_FAR *pVal);
+-} SK_GEMACFUNC;
+-
+-/*
+- * Port Structure
+- */
+-typedef struct s_GePort {
+-#ifndef SK_DIAG
+- SK_TIMER PWaTimer; /* Workaround Timer */
+- SK_TIMER HalfDupChkTimer;
+-#endif /* SK_DIAG */
+- SK_U32 PPrevShorts; /* Previous Short Counter checking */
+- SK_U32 PPrevFcs; /* Previous FCS Error Counter checking */
+- SK_U64 PPrevRx; /* Previous RxOk Counter checking */
+- SK_U64 PRxLim; /* Previous RxOk Counter checking */
+- SK_U64 LastOctets; /* For half duplex hang check */
+- int PLinkResCt; /* Link Restart Counter */
+- int PAutoNegTimeOut;/* Auto-negotiation timeout current value */
+- int PAutoNegTOCt; /* Auto-negotiation Timeout Counter */
+- int PRxQSize; /* Port Rx Queue Size in kB */
+- int PXSQSize; /* Port Synchronous Transmit Queue Size in kB */
+- int PXAQSize; /* Port Asynchronous Transmit Queue Size in kB */
+- SK_U32 PRxQRamStart; /* Receive Queue RAM Buffer Start Address */
+- SK_U32 PRxQRamEnd; /* Receive Queue RAM Buffer End Address */
+- SK_U32 PXsQRamStart; /* Sync Tx Queue RAM Buffer Start Address */
+- SK_U32 PXsQRamEnd; /* Sync Tx Queue RAM Buffer End Address */
+- SK_U32 PXaQRamStart; /* Async Tx Queue RAM Buffer Start Address */
+- SK_U32 PXaQRamEnd; /* Async Tx Queue RAM Buffer End Address */
+- SK_U32 PRxOverCnt; /* Receive Overflow Counter */
+- int PRxQOff; /* Rx Queue Address Offset */
+- int PXsQOff; /* Synchronous Tx Queue Address Offset */
+- int PXaQOff; /* Asynchronous Tx Queue Address Offset */
+- int PhyType; /* PHY used on this port */
+- int PState; /* Port status (reset, stop, init, run) */
+- SK_U16 PhyId1; /* PHY Id1 on this port */
+- SK_U16 PhyAddr; /* MDIO/MDC PHY address */
+- SK_U16 PIsave; /* Saved Interrupt status word */
+- SK_U16 PSsave; /* Saved PHY status word */
+- SK_U16 PGmANegAdv; /* Saved GPhy AutoNegAdvertisment register */
+- SK_BOOL PHWLinkUp; /* The hardware Link is up (wiring) */
+- SK_BOOL PLinkBroken; /* Is Link broken ? */
+- SK_BOOL PCheckPar; /* Do we check for parity errors ? */
+- SK_BOOL HalfDupTimerActive;
+- SK_U8 PLinkCap; /* Link Capabilities */
+- SK_U8 PLinkModeConf; /* Link Mode configured */
+- SK_U8 PLinkMode; /* Link Mode currently used */
+- SK_U8 PLinkModeStatus;/* Link Mode Status */
+- SK_U8 PLinkSpeedCap; /* Link Speed Capabilities(10/100/1000 Mbps) */
+- SK_U8 PLinkSpeed; /* configured Link Speed (10/100/1000 Mbps) */
+- SK_U8 PLinkSpeedUsed; /* current Link Speed (10/100/1000 Mbps) */
+- SK_U8 PFlowCtrlCap; /* Flow Control Capabilities */
+- SK_U8 PFlowCtrlMode; /* Flow Control Mode */
+- SK_U8 PFlowCtrlStatus;/* Flow Control Status */
+- SK_U8 PMSCap; /* Master/Slave Capabilities */
+- SK_U8 PMSMode; /* Master/Slave Mode */
+- SK_U8 PMSStatus; /* Master/Slave Status */
+- SK_BOOL PAutoNegFail; /* Auto-negotiation fail flag */
+- SK_U8 PLipaAutoNeg; /* Auto-negotiation possible with Link Partner */
+- SK_U8 PCableLen; /* Cable Length */
+- SK_U8 PMdiPairLen[4]; /* MDI[0..3] Pair Length */
+- SK_U8 PMdiPairSts[4]; /* MDI[0..3] Pair Diagnostic Status */
+- SK_U8 PPhyPowerState; /* PHY current power state */
+- int PMacColThres; /* MAC Collision Threshold */
+- int PMacJamLen; /* MAC Jam length */
+- int PMacJamIpgVal; /* MAC Jam IPG */
+- int PMacJamIpgData; /* MAC IPG Jam to Data */
+- int PMacIpgData; /* MAC Data IPG */
+- SK_BOOL PMacLimit4; /* reset collision counter and backoff algorithm */
+-} SK_GEPORT;
+-
+-/*
+- * Gigabit Ethernet Initialization Struct
+- * (has to be included in the adapter context)
+- */
+-typedef struct s_GeInit {
+- int GIChipId; /* Chip Identification Number */
+- int GIChipRev; /* Chip Revision Number */
+- SK_U8 GIPciHwRev; /* PCI HW Revision Number */
+- SK_BOOL GIGenesis; /* Genesis adapter ? */
+- SK_BOOL GIYukon; /* YUKON-A1/Bx chip */
+- SK_BOOL GIYukonLite; /* YUKON-Lite chip */
+- SK_BOOL GICopperType; /* Copper Type adapter ? */
+- SK_BOOL GIPciSlot64; /* 64-bit PCI Slot */
+- SK_BOOL GIPciClock66; /* 66 MHz PCI Clock */
+- SK_BOOL GIVauxAvail; /* VAUX available (YUKON) */
+- SK_BOOL GIYukon32Bit; /* 32-Bit YUKON adapter */
+- SK_U16 GILedBlinkCtrl; /* LED Blink Control */
+- int GIMacsFound; /* Number of MACs found on this adapter */
+- int GIMacType; /* MAC Type used on this adapter */
+- int GIHstClkFact; /* Host Clock Factor (62.5 / HstClk * 100) */
+- int GIPortUsage; /* Driver Port Usage */
+- int GILevel; /* Initialization Level completed */
+- int GIRamSize; /* The RAM size of the adapter in kB */
+- int GIWolOffs; /* WOL Register Offset (HW-Bug in Rev. A) */
+- SK_U32 GIRamOffs; /* RAM Address Offset for addr calculation */
+- SK_U32 GIPollTimerVal; /* Descr. Poll Timer Init Val (HstClk ticks) */
+- SK_U32 GIValIrqMask; /* Value for Interrupt Mask */
+- SK_U32 GITimeStampCnt; /* Time Stamp High Counter (YUKON only) */
+- SK_GEPORT GP[SK_MAX_MACS];/* Port Dependent Information */
+- SK_GEMACFUNC GIFunc; /* MAC depedent functions */
+-} SK_GEINIT;
+-
+-/*
+- * Error numbers and messages for skxmac2.c and skgeinit.c
+- */
+-#define SKERR_HWI_E001 (SK_ERRBASE_HWINIT)
+-#define SKERR_HWI_E001MSG "SkXmClrExactAddr() has got illegal parameters"
+-#define SKERR_HWI_E002 (SKERR_HWI_E001+1)
+-#define SKERR_HWI_E002MSG "SkGeInit(): Level 1 call missing"
+-#define SKERR_HWI_E003 (SKERR_HWI_E002+1)
+-#define SKERR_HWI_E003MSG "SkGeInit() called with illegal init Level"
+-#define SKERR_HWI_E004 (SKERR_HWI_E003+1)
+-#define SKERR_HWI_E004MSG "SkGeInitPort(): Queue Size illegal configured"
+-#define SKERR_HWI_E005 (SKERR_HWI_E004+1)
+-#define SKERR_HWI_E005MSG "SkGeInitPort(): cannot init running ports"
+-#define SKERR_HWI_E006 (SKERR_HWI_E005+1)
+-#define SKERR_HWI_E006MSG "SkGeMacInit(): PState does not match HW state"
+-#define SKERR_HWI_E007 (SKERR_HWI_E006+1)
+-#define SKERR_HWI_E007MSG "SkXmInitDupMd() called with invalid Dup Mode"
+-#define SKERR_HWI_E008 (SKERR_HWI_E007+1)
+-#define SKERR_HWI_E008MSG "SkXmSetRxCmd() called with invalid Mode"
+-#define SKERR_HWI_E009 (SKERR_HWI_E008+1)
+-#define SKERR_HWI_E009MSG "SkGeCfgSync() called although PXSQSize zero"
+-#define SKERR_HWI_E010 (SKERR_HWI_E009+1)
+-#define SKERR_HWI_E010MSG "SkGeCfgSync() called with invalid parameters"
+-#define SKERR_HWI_E011 (SKERR_HWI_E010+1)
+-#define SKERR_HWI_E011MSG "SkGeInitPort(): Receive Queue Size too small"
+-#define SKERR_HWI_E012 (SKERR_HWI_E011+1)
+-#define SKERR_HWI_E012MSG "SkGeInitPort(): invalid Queue Size specified"
+-#define SKERR_HWI_E013 (SKERR_HWI_E012+1)
+-#define SKERR_HWI_E013MSG "SkGeInitPort(): cfg changed for running queue"
+-#define SKERR_HWI_E014 (SKERR_HWI_E013+1)
+-#define SKERR_HWI_E014MSG "SkGeInitPort(): unknown GIPortUsage specified"
+-#define SKERR_HWI_E015 (SKERR_HWI_E014+1)
+-#define SKERR_HWI_E015MSG "Illegal Link mode parameter"
+-#define SKERR_HWI_E016 (SKERR_HWI_E015+1)
+-#define SKERR_HWI_E016MSG "Illegal Flow control mode parameter"
+-#define SKERR_HWI_E017 (SKERR_HWI_E016+1)
+-#define SKERR_HWI_E017MSG "Illegal value specified for GIPollTimerVal"
+-#define SKERR_HWI_E018 (SKERR_HWI_E017+1)
+-#define SKERR_HWI_E018MSG "FATAL: SkGeStopPort() does not terminate (Tx)"
+-#define SKERR_HWI_E019 (SKERR_HWI_E018+1)
+-#define SKERR_HWI_E019MSG "Illegal Speed parameter"
+-#define SKERR_HWI_E020 (SKERR_HWI_E019+1)
+-#define SKERR_HWI_E020MSG "Illegal Master/Slave parameter"
+-#define SKERR_HWI_E021 (SKERR_HWI_E020+1)
+-#define SKERR_HWI_E021MSG "MacUpdateStats(): cannot update statistic counter"
+-#define SKERR_HWI_E022 (SKERR_HWI_E021+1)
+-#define SKERR_HWI_E022MSG "MacStatistic(): illegal statistic base address"
+-#define SKERR_HWI_E023 (SKERR_HWI_E022+1)
+-#define SKERR_HWI_E023MSG "SkGeInitPort(): Transmit Queue Size too small"
+-#define SKERR_HWI_E024 (SKERR_HWI_E023+1)
+-#define SKERR_HWI_E024MSG "FATAL: SkGeStopPort() does not terminate (Rx)"
+-#define SKERR_HWI_E025 (SKERR_HWI_E024+1)
+-#define SKERR_HWI_E025MSG ""
+-
+-/* function prototypes ********************************************************/
+-
+-#ifndef SK_KR_PROTO
+-
+-/*
+- * public functions in skgeinit.c
+- */
+-extern void SkGePollTxD(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port,
+- SK_BOOL PollTxD);
+-
+-extern void SkGeYellowLED(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int State);
+-
+-extern int SkGeCfgSync(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port,
+- SK_U32 IntTime,
+- SK_U32 LimCount,
+- int SyncMode);
+-
+-extern void SkGeLoadLnkSyncCnt(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port,
+- SK_U32 CntVal);
+-
+-extern void SkGeStopPort(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port,
+- int Dir,
+- int RstMode);
+-
+-extern int SkGeInit(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Level);
+-
+-extern void SkGeDeInit(
+- SK_AC *pAC,
+- SK_IOC IoC);
+-
+-extern int SkGeInitPort(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port);
+-
+-extern void SkGeXmitLED(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Led,
+- int Mode);
+-
+-extern int SkGeInitAssignRamToQueues(
+- SK_AC *pAC,
+- int ActivePort,
+- SK_BOOL DualNet);
+-
+-/*
+- * public functions in skxmac2.c
+- */
+-extern void SkMacRxTxDisable(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port);
+-
+-extern void SkMacSoftRst(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port);
+-
+-extern void SkMacHardRst(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port);
+-
+-extern void SkXmInitMac(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port);
+-
+-extern void SkGmInitMac(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port);
+-
+-extern void SkMacInitPhy(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port,
+- SK_BOOL DoLoop);
+-
+-extern void SkMacIrqDisable(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port);
+-
+-extern void SkMacFlushTxFifo(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port);
+-
+-extern void SkMacIrq(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port);
+-
+-extern int SkMacAutoNegDone(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port);
+-
+-extern void SkMacAutoNegLipaPhy(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port,
+- SK_U16 IStatus);
+-
+-extern int SkMacRxTxEnable(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port);
+-
+-extern void SkMacPromiscMode(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port,
+- SK_BOOL Enable);
+-
+-extern void SkMacHashing(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port,
+- SK_BOOL Enable);
+-
+-extern void SkXmPhyRead(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port,
+- int Addr,
+- SK_U16 SK_FAR *pVal);
+-
+-extern void SkXmPhyWrite(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port,
+- int Addr,
+- SK_U16 Val);
+-
+-extern void SkGmPhyRead(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port,
+- int Addr,
+- SK_U16 SK_FAR *pVal);
+-
+-extern void SkGmPhyWrite(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port,
+- int Addr,
+- SK_U16 Val);
+-
+-extern void SkXmClrExactAddr(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port,
+- int StartNum,
+- int StopNum);
+-
+-extern void SkXmAutoNegLipaXmac(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port,
+- SK_U16 IStatus);
+-
+-extern int SkXmUpdateStats(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- unsigned int Port);
+-
+-extern int SkGmUpdateStats(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- unsigned int Port);
+-
+-extern int SkXmMacStatistic(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- unsigned int Port,
+- SK_U16 StatAddr,
+- SK_U32 SK_FAR *pVal);
+-
+-extern int SkGmMacStatistic(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- unsigned int Port,
+- SK_U16 StatAddr,
+- SK_U32 SK_FAR *pVal);
+-
+-extern int SkXmResetCounter(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- unsigned int Port);
+-
+-extern int SkGmResetCounter(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- unsigned int Port);
+-
+-extern int SkXmOverflowStatus(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- unsigned int Port,
+- SK_U16 IStatus,
+- SK_U64 SK_FAR *pStatus);
+-
+-extern int SkGmOverflowStatus(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- unsigned int Port,
+- SK_U16 MacStatus,
+- SK_U64 SK_FAR *pStatus);
+-
+-extern int SkGmCableDiagStatus(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port,
+- SK_BOOL StartTest);
+-
+-#ifdef SK_DIAG
+-extern void SkGePhyRead(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port,
+- int Addr,
+- SK_U16 *pVal);
+-
+-extern void SkGePhyWrite(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port,
+- int Addr,
+- SK_U16 Val);
+-
+-extern void SkMacSetRxCmd(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port,
+- int Mode);
+-extern void SkMacCrcGener(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port,
+- SK_BOOL Enable);
+-extern void SkMacTimeStamp(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port,
+- SK_BOOL Enable);
+-extern void SkXmSendCont(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Port,
+- SK_BOOL Enable);
+-#endif /* SK_DIAG */
+-
+-#else /* SK_KR_PROTO */
+-
+-/*
+- * public functions in skgeinit.c
+- */
+-extern void SkGePollTxD();
+-extern void SkGeYellowLED();
+-extern int SkGeCfgSync();
+-extern void SkGeLoadLnkSyncCnt();
+-extern void SkGeStopPort();
+-extern int SkGeInit();
+-extern void SkGeDeInit();
+-extern int SkGeInitPort();
+-extern void SkGeXmitLED();
+-extern int SkGeInitAssignRamToQueues();
+-
+-/*
+- * public functions in skxmac2.c
+- */
+-extern void SkMacRxTxDisable();
+-extern void SkMacSoftRst();
+-extern void SkMacHardRst();
+-extern void SkMacInitPhy();
+-extern int SkMacRxTxEnable();
+-extern void SkMacPromiscMode();
+-extern void SkMacHashing();
+-extern void SkMacIrqDisable();
+-extern void SkMacFlushTxFifo();
+-extern void SkMacIrq();
+-extern int SkMacAutoNegDone();
+-extern void SkMacAutoNegLipaPhy();
+-extern void SkXmInitMac();
+-extern void SkXmPhyRead();
+-extern void SkXmPhyWrite();
+-extern void SkGmInitMac();
+-extern void SkGmPhyRead();
+-extern void SkGmPhyWrite();
+-extern void SkXmClrExactAddr();
+-extern void SkXmAutoNegLipaXmac();
+-extern int SkXmUpdateStats();
+-extern int SkGmUpdateStats();
+-extern int SkXmMacStatistic();
+-extern int SkGmMacStatistic();
+-extern int SkXmResetCounter();
+-extern int SkGmResetCounter();
+-extern int SkXmOverflowStatus();
+-extern int SkGmOverflowStatus();
+-extern int SkGmCableDiagStatus();
+-
+-#ifdef SK_DIAG
+-extern void SkGePhyRead();
+-extern void SkGePhyWrite();
+-extern void SkMacSetRxCmd();
+-extern void SkMacCrcGener();
+-extern void SkMacTimeStamp();
+-extern void SkXmSendCont();
+-#endif /* SK_DIAG */
+-
+-#endif /* SK_KR_PROTO */
+-
+-#ifdef __cplusplus
+-}
+-#endif /* __cplusplus */
+-
+-#endif /* __INC_SKGEINIT_H_ */
+diff --git a/drivers/net/sk98lin/h/skgepnm2.h b/drivers/net/sk98lin/h/skgepnm2.h
+deleted file mode 100644
+index ddd304f..0000000
+--- a/drivers/net/sk98lin/h/skgepnm2.h
++++ /dev/null
+@@ -1,334 +0,0 @@
+-/*****************************************************************************
+- *
+- * Name: skgepnm2.h
+- * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.36 $
+- * Date: $Date: 2003/05/23 12:45:13 $
+- * Purpose: Defines for Private Network Management Interface
+- *
+- ****************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#ifndef _SKGEPNM2_H_
+-#define _SKGEPNM2_H_
+-
+-/*
+- * General definitions
+- */
+-#define SK_PNMI_CHIPSET_XMAC 1 /* XMAC11800FP */
+-#define SK_PNMI_CHIPSET_YUKON 2 /* YUKON */
+-
+-#define SK_PNMI_BUS_PCI 1 /* PCI bus*/
+-
+-/*
+- * Actions
+- */
+-#define SK_PNMI_ACT_IDLE 1
+-#define SK_PNMI_ACT_RESET 2
+-#define SK_PNMI_ACT_SELFTEST 3
+-#define SK_PNMI_ACT_RESETCNT 4
+-
+-/*
+- * VPD releated defines
+- */
+-
+-#define SK_PNMI_VPD_RW 1
+-#define SK_PNMI_VPD_RO 2
+-
+-#define SK_PNMI_VPD_OK 0
+-#define SK_PNMI_VPD_NOTFOUND 1
+-#define SK_PNMI_VPD_CUT 2
+-#define SK_PNMI_VPD_TIMEOUT 3
+-#define SK_PNMI_VPD_FULL 4
+-#define SK_PNMI_VPD_NOWRITE 5
+-#define SK_PNMI_VPD_FATAL 6
+-
+-#define SK_PNMI_VPD_IGNORE 0
+-#define SK_PNMI_VPD_CREATE 1
+-#define SK_PNMI_VPD_DELETE 2
+-
+-
+-/*
+- * RLMT related defines
+- */
+-#define SK_PNMI_DEF_RLMT_CHG_THRES 240 /* 4 changes per minute */
+-
+-
+-/*
+- * VCT internal status values
+- */
+-#define SK_PNMI_VCT_PENDING 32
+-#define SK_PNMI_VCT_TEST_DONE 64
+-#define SK_PNMI_VCT_LINK 128
+-
+-/*
+- * Internal table definitions
+- */
+-#define SK_PNMI_GET 0
+-#define SK_PNMI_PRESET 1
+-#define SK_PNMI_SET 2
+-
+-#define SK_PNMI_RO 0
+-#define SK_PNMI_RW 1
+-#define SK_PNMI_WO 2
+-
+-typedef struct s_OidTabEntry {
+- SK_U32 Id;
+- SK_U32 InstanceNo;
+- unsigned int StructSize;
+- unsigned int Offset;
+- int Access;
+- int (* Func)(SK_AC *pAc, SK_IOC pIo, int action,
+- SK_U32 Id, char* pBuf, unsigned int* pLen,
+- SK_U32 Instance, unsigned int TableIndex,
+- SK_U32 NetNumber);
+- SK_U16 Param;
+-} SK_PNMI_TAB_ENTRY;
+-
+-
+-/*
+- * Trap lengths
+- */
+-#define SK_PNMI_TRAP_SIMPLE_LEN 17
+-#define SK_PNMI_TRAP_SENSOR_LEN_BASE 46
+-#define SK_PNMI_TRAP_RLMT_CHANGE_LEN 23
+-#define SK_PNMI_TRAP_RLMT_PORT_LEN 23
+-
+-/*
+- * Number of MAC types supported
+- */
+-#define SK_PNMI_MAC_TYPES (SK_MAC_GMAC + 1)
+-
+-/*
+- * MAC statistic data list (overall set for MAC types used)
+- */
+-enum SK_MACSTATS {
+- SK_PNMI_HTX = 0,
+- SK_PNMI_HTX_OCTET,
+- SK_PNMI_HTX_OCTETHIGH = SK_PNMI_HTX_OCTET,
+- SK_PNMI_HTX_OCTETLOW,
+- SK_PNMI_HTX_BROADCAST,
+- SK_PNMI_HTX_MULTICAST,
+- SK_PNMI_HTX_UNICAST,
+- SK_PNMI_HTX_BURST,
+- SK_PNMI_HTX_PMACC,
+- SK_PNMI_HTX_MACC,
+- SK_PNMI_HTX_COL,
+- SK_PNMI_HTX_SINGLE_COL,
+- SK_PNMI_HTX_MULTI_COL,
+- SK_PNMI_HTX_EXCESS_COL,
+- SK_PNMI_HTX_LATE_COL,
+- SK_PNMI_HTX_DEFFERAL,
+- SK_PNMI_HTX_EXCESS_DEF,
+- SK_PNMI_HTX_UNDERRUN,
+- SK_PNMI_HTX_CARRIER,
+- SK_PNMI_HTX_UTILUNDER,
+- SK_PNMI_HTX_UTILOVER,
+- SK_PNMI_HTX_64,
+- SK_PNMI_HTX_127,
+- SK_PNMI_HTX_255,
+- SK_PNMI_HTX_511,
+- SK_PNMI_HTX_1023,
+- SK_PNMI_HTX_MAX,
+- SK_PNMI_HTX_LONGFRAMES,
+- SK_PNMI_HTX_SYNC,
+- SK_PNMI_HTX_SYNC_OCTET,
+- SK_PNMI_HTX_RESERVED,
+-
+- SK_PNMI_HRX,
+- SK_PNMI_HRX_OCTET,
+- SK_PNMI_HRX_OCTETHIGH = SK_PNMI_HRX_OCTET,
+- SK_PNMI_HRX_OCTETLOW,
+- SK_PNMI_HRX_BADOCTET,
+- SK_PNMI_HRX_BADOCTETHIGH = SK_PNMI_HRX_BADOCTET,
+- SK_PNMI_HRX_BADOCTETLOW,
+- SK_PNMI_HRX_BROADCAST,
+- SK_PNMI_HRX_MULTICAST,
+- SK_PNMI_HRX_UNICAST,
+- SK_PNMI_HRX_PMACC,
+- SK_PNMI_HRX_MACC,
+- SK_PNMI_HRX_PMACC_ERR,
+- SK_PNMI_HRX_MACC_UNKWN,
+- SK_PNMI_HRX_BURST,
+- SK_PNMI_HRX_MISSED,
+- SK_PNMI_HRX_FRAMING,
+- SK_PNMI_HRX_UNDERSIZE,
+- SK_PNMI_HRX_OVERFLOW,
+- SK_PNMI_HRX_JABBER,
+- SK_PNMI_HRX_CARRIER,
+- SK_PNMI_HRX_IRLENGTH,
+- SK_PNMI_HRX_SYMBOL,
+- SK_PNMI_HRX_SHORTS,
+- SK_PNMI_HRX_RUNT,
+- SK_PNMI_HRX_TOO_LONG,
+- SK_PNMI_HRX_FCS,
+- SK_PNMI_HRX_CEXT,
+- SK_PNMI_HRX_UTILUNDER,
+- SK_PNMI_HRX_UTILOVER,
+- SK_PNMI_HRX_64,
+- SK_PNMI_HRX_127,
+- SK_PNMI_HRX_255,
+- SK_PNMI_HRX_511,
+- SK_PNMI_HRX_1023,
+- SK_PNMI_HRX_MAX,
+- SK_PNMI_HRX_LONGFRAMES,
+-
+- SK_PNMI_HRX_RESERVED,
+-
+- SK_PNMI_MAX_IDX /* NOTE: Ensure SK_PNMI_CNT_NO is set to this value */
+-};
+-
+-/*
+- * MAC specific data
+- */
+-typedef struct s_PnmiStatAddr {
+- SK_U16 Reg; /* MAC register containing the value */
+- SK_BOOL GetOffset; /* TRUE: Offset managed by PNMI (call GetStatVal())*/
+-} SK_PNMI_STATADDR;
+-
+-
+-/*
+- * SK_PNMI_STRUCT_DATA copy offset evaluation macros
+- */
+-#define SK_PNMI_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_STRUCT_DATA *)0)->e))
+-#define SK_PNMI_MAI_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_STRUCT_DATA *)0)->e))
+-#define SK_PNMI_VPD_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_VPD *)0)->e))
+-#define SK_PNMI_SEN_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_SENSOR *)0)->e))
+-#define SK_PNMI_CHK_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_CHECKSUM *)0)->e))
+-#define SK_PNMI_STA_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_STAT *)0)->e))
+-#define SK_PNMI_CNF_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_CONF *)0)->e))
+-#define SK_PNMI_RLM_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_RLMT *)0)->e))
+-#define SK_PNMI_MON_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_RLMT_MONITOR *)0)->e))
+-#define SK_PNMI_TRP_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_TRAP *)0)->e))
+-
+-#define SK_PNMI_SET_STAT(b,s,o) {SK_U32 Val32; char *pVal; \
+- Val32 = (s); \
+- pVal = (char *)(b) + ((SK_U32)(SK_UPTR) \
+- &(((SK_PNMI_STRUCT_DATA *)0)-> \
+- ReturnStatus.ErrorStatus)); \
+- SK_PNMI_STORE_U32(pVal, Val32); \
+- Val32 = (o); \
+- pVal = (char *)(b) + ((SK_U32)(SK_UPTR) \
+- &(((SK_PNMI_STRUCT_DATA *)0)-> \
+- ReturnStatus.ErrorOffset)); \
+- SK_PNMI_STORE_U32(pVal, Val32);}
+-
+-/*
+- * Time macros
+- */
+-#ifndef SK_PNMI_HUNDREDS_SEC
+-#if SK_TICKS_PER_SEC == 100
+-#define SK_PNMI_HUNDREDS_SEC(t) (t)
+-#else
+-#define SK_PNMI_HUNDREDS_SEC(t) (((t) * 100) / (SK_TICKS_PER_SEC))
+-#endif /* !SK_TICKS_PER_SEC */
+-#endif /* !SK_PNMI_HUNDREDS_SEC */
+-
+-/*
+- * Macros to work around alignment problems
+- */
+-#ifndef SK_PNMI_STORE_U16
+-#define SK_PNMI_STORE_U16(p,v) {*(char *)(p) = *((char *)&(v)); \
+- *((char *)(p) + 1) = \
+- *(((char *)&(v)) + 1);}
+-#endif
+-
+-#ifndef SK_PNMI_STORE_U32
+-#define SK_PNMI_STORE_U32(p,v) {*(char *)(p) = *((char *)&(v)); \
+- *((char *)(p) + 1) = \
+- *(((char *)&(v)) + 1); \
+- *((char *)(p) + 2) = \
+- *(((char *)&(v)) + 2); \
+- *((char *)(p) + 3) = \
+- *(((char *)&(v)) + 3);}
+-#endif
+-
+-#ifndef SK_PNMI_STORE_U64
+-#define SK_PNMI_STORE_U64(p,v) {*(char *)(p) = *((char *)&(v)); \
+- *((char *)(p) + 1) = \
+- *(((char *)&(v)) + 1); \
+- *((char *)(p) + 2) = \
+- *(((char *)&(v)) + 2); \
+- *((char *)(p) + 3) = \
+- *(((char *)&(v)) + 3); \
+- *((char *)(p) + 4) = \
+- *(((char *)&(v)) + 4); \
+- *((char *)(p) + 5) = \
+- *(((char *)&(v)) + 5); \
+- *((char *)(p) + 6) = \
+- *(((char *)&(v)) + 6); \
+- *((char *)(p) + 7) = \
+- *(((char *)&(v)) + 7);}
+-#endif
+-
+-#ifndef SK_PNMI_READ_U16
+-#define SK_PNMI_READ_U16(p,v) {*((char *)&(v)) = *(char *)(p); \
+- *(((char *)&(v)) + 1) = \
+- *((char *)(p) + 1);}
+-#endif
+-
+-#ifndef SK_PNMI_READ_U32
+-#define SK_PNMI_READ_U32(p,v) {*((char *)&(v)) = *(char *)(p); \
+- *(((char *)&(v)) + 1) = \
+- *((char *)(p) + 1); \
+- *(((char *)&(v)) + 2) = \
+- *((char *)(p) + 2); \
+- *(((char *)&(v)) + 3) = \
+- *((char *)(p) + 3);}
+-#endif
+-
+-#ifndef SK_PNMI_READ_U64
+-#define SK_PNMI_READ_U64(p,v) {*((char *)&(v)) = *(char *)(p); \
+- *(((char *)&(v)) + 1) = \
+- *((char *)(p) + 1); \
+- *(((char *)&(v)) + 2) = \
+- *((char *)(p) + 2); \
+- *(((char *)&(v)) + 3) = \
+- *((char *)(p) + 3); \
+- *(((char *)&(v)) + 4) = \
+- *((char *)(p) + 4); \
+- *(((char *)&(v)) + 5) = \
+- *((char *)(p) + 5); \
+- *(((char *)&(v)) + 6) = \
+- *((char *)(p) + 6); \
+- *(((char *)&(v)) + 7) = \
+- *((char *)(p) + 7);}
+-#endif
+-
+-/*
+- * Macros for Debug
+- */
+-#ifdef DEBUG
+-
+-#define SK_PNMI_CHECKFLAGS(vSt) {if (pAC->Pnmi.MacUpdatedFlag > 0 || \
+- pAC->Pnmi.RlmtUpdatedFlag > 0 || \
+- pAC->Pnmi.SirqUpdatedFlag > 0) { \
+- SK_DBG_MSG(pAC, \
+- SK_DBGMOD_PNMI, \
+- SK_DBGCAT_CTRL, \
+- ("PNMI: ERR: %s MacUFlag=%d, RlmtUFlag=%d, SirqUFlag=%d\n", \
+- vSt, \
+- pAC->Pnmi.MacUpdatedFlag, \
+- pAC->Pnmi.RlmtUpdatedFlag, \
+- pAC->Pnmi.SirqUpdatedFlag))}}
+-
+-#else /* !DEBUG */
+-
+-#define SK_PNMI_CHECKFLAGS(vSt) /* Nothing */
+-
+-#endif /* !DEBUG */
+-
+-#endif /* _SKGEPNM2_H_ */
+diff --git a/drivers/net/sk98lin/h/skgepnmi.h b/drivers/net/sk98lin/h/skgepnmi.h
+deleted file mode 100644
+index 1ed214c..0000000
+--- a/drivers/net/sk98lin/h/skgepnmi.h
++++ /dev/null
+@@ -1,962 +0,0 @@
+-/*****************************************************************************
+- *
+- * Name: skgepnmi.h
+- * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.62 $
+- * Date: $Date: 2003/08/15 12:31:52 $
+- * Purpose: Defines for Private Network Management Interface
+- *
+- ****************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#ifndef _SKGEPNMI_H_
+-#define _SKGEPNMI_H_
+-
+-/*
+- * Include dependencies
+- */
+-#include "h/sktypes.h"
+-#include "h/skerror.h"
+-#include "h/sktimer.h"
+-#include "h/ski2c.h"
+-#include "h/skaddr.h"
+-#include "h/skrlmt.h"
+-#include "h/skvpd.h"
+-
+-/*
+- * Management Database Version
+- */
+-#define SK_PNMI_MDB_VERSION 0x00030001 /* 3.1 */
+-
+-
+-/*
+- * Event definitions
+- */
+-#define SK_PNMI_EVT_SIRQ_OVERFLOW 1 /* Counter overflow */
+-#define SK_PNMI_EVT_SEN_WAR_LOW 2 /* Lower war thres exceeded */
+-#define SK_PNMI_EVT_SEN_WAR_UPP 3 /* Upper war thres exceeded */
+-#define SK_PNMI_EVT_SEN_ERR_LOW 4 /* Lower err thres exceeded */
+-#define SK_PNMI_EVT_SEN_ERR_UPP 5 /* Upper err thres exceeded */
+-#define SK_PNMI_EVT_CHG_EST_TIMER 6 /* Timer event for RLMT Chg */
+-#define SK_PNMI_EVT_UTILIZATION_TIMER 7 /* Timer event for Utiliza. */
+-#define SK_PNMI_EVT_CLEAR_COUNTER 8 /* Clear statistic counters */
+-#define SK_PNMI_EVT_XMAC_RESET 9 /* XMAC will be reset */
+-
+-#define SK_PNMI_EVT_RLMT_PORT_UP 10 /* Port came logically up */
+-#define SK_PNMI_EVT_RLMT_PORT_DOWN 11 /* Port went logically down */
+-#define SK_PNMI_EVT_RLMT_SEGMENTATION 13 /* Two SP root bridges found */
+-#define SK_PNMI_EVT_RLMT_ACTIVE_DOWN 14 /* Port went logically down */
+-#define SK_PNMI_EVT_RLMT_ACTIVE_UP 15 /* Port came logically up */
+-#define SK_PNMI_EVT_RLMT_SET_NETS 16 /* 1. Parameter is number of nets
+- 1 = single net; 2 = dual net */
+-#define SK_PNMI_EVT_VCT_RESET 17 /* VCT port reset timer event started with SET. */
+-
+-
+-/*
+- * Return values
+- */
+-#define SK_PNMI_ERR_OK 0
+-#define SK_PNMI_ERR_GENERAL 1
+-#define SK_PNMI_ERR_TOO_SHORT 2
+-#define SK_PNMI_ERR_BAD_VALUE 3
+-#define SK_PNMI_ERR_READ_ONLY 4
+-#define SK_PNMI_ERR_UNKNOWN_OID 5
+-#define SK_PNMI_ERR_UNKNOWN_INST 6
+-#define SK_PNMI_ERR_UNKNOWN_NET 7
+-#define SK_PNMI_ERR_NOT_SUPPORTED 10
+-
+-
+-/*
+- * Return values of driver reset function SK_DRIVER_RESET() and
+- * driver event function SK_DRIVER_EVENT()
+- */
+-#define SK_PNMI_ERR_OK 0
+-#define SK_PNMI_ERR_FAIL 1
+-
+-
+-/*
+- * Return values of driver test function SK_DRIVER_SELFTEST()
+- */
+-#define SK_PNMI_TST_UNKNOWN (1 << 0)
+-#define SK_PNMI_TST_TRANCEIVER (1 << 1)
+-#define SK_PNMI_TST_ASIC (1 << 2)
+-#define SK_PNMI_TST_SENSOR (1 << 3)
+-#define SK_PNMI_TST_POWERMGMT (1 << 4)
+-#define SK_PNMI_TST_PCI (1 << 5)
+-#define SK_PNMI_TST_MAC (1 << 6)
+-
+-
+-/*
+- * RLMT specific definitions
+- */
+-#define SK_PNMI_RLMT_STATUS_STANDBY 1
+-#define SK_PNMI_RLMT_STATUS_ACTIVE 2
+-#define SK_PNMI_RLMT_STATUS_ERROR 3
+-
+-#define SK_PNMI_RLMT_LSTAT_PHY_DOWN 1
+-#define SK_PNMI_RLMT_LSTAT_AUTONEG 2
+-#define SK_PNMI_RLMT_LSTAT_LOG_DOWN 3
+-#define SK_PNMI_RLMT_LSTAT_LOG_UP 4
+-#define SK_PNMI_RLMT_LSTAT_INDETERMINATED 5
+-
+-#define SK_PNMI_RLMT_MODE_CHK_LINK (SK_RLMT_CHECK_LINK)
+-#define SK_PNMI_RLMT_MODE_CHK_RX (SK_RLMT_CHECK_LOC_LINK)
+-#define SK_PNMI_RLMT_MODE_CHK_SPT (SK_RLMT_CHECK_SEG)
+-/* #define SK_PNMI_RLMT_MODE_CHK_EX */
+-
+-/*
+- * OID definition
+- */
+-#ifndef _NDIS_ /* Check, whether NDIS already included OIDs */
+-
+-#define OID_GEN_XMIT_OK 0x00020101
+-#define OID_GEN_RCV_OK 0x00020102
+-#define OID_GEN_XMIT_ERROR 0x00020103
+-#define OID_GEN_RCV_ERROR 0x00020104
+-#define OID_GEN_RCV_NO_BUFFER 0x00020105
+-
+-/* #define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 */
+-#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202
+-/* #define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 */
+-#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204
+-/* #define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 */
+-#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206
+-/* #define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 */
+-#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208
+-/* #define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 */
+-#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A
+-/* #define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B */
+-#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C
+-#define OID_GEN_RCV_CRC_ERROR 0x0002020D
+-#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E
+-
+-#define OID_802_3_PERMANENT_ADDRESS 0x01010101
+-#define OID_802_3_CURRENT_ADDRESS 0x01010102
+-/* #define OID_802_3_MULTICAST_LIST 0x01010103 */
+-/* #define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 */
+-/* #define OID_802_3_MAC_OPTIONS 0x01010105 */
+-
+-#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101
+-#define OID_802_3_XMIT_ONE_COLLISION 0x01020102
+-#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103
+-#define OID_802_3_XMIT_DEFERRED 0x01020201
+-#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202
+-#define OID_802_3_RCV_OVERRUN 0x01020203
+-#define OID_802_3_XMIT_UNDERRUN 0x01020204
+-#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206
+-#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207
+-
+-/*
+- * PnP and PM OIDs
+- */
+-#ifdef SK_POWER_MGMT
+-#define OID_PNP_CAPABILITIES 0xFD010100
+-#define OID_PNP_SET_POWER 0xFD010101
+-#define OID_PNP_QUERY_POWER 0xFD010102
+-#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103
+-#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104
+-#define OID_PNP_ENABLE_WAKE_UP 0xFD010106
+-#endif /* SK_POWER_MGMT */
+-
+-#endif /* _NDIS_ */
+-
+-#define OID_SKGE_MDB_VERSION 0xFF010100
+-#define OID_SKGE_SUPPORTED_LIST 0xFF010101
+-#define OID_SKGE_VPD_FREE_BYTES 0xFF010102
+-#define OID_SKGE_VPD_ENTRIES_LIST 0xFF010103
+-#define OID_SKGE_VPD_ENTRIES_NUMBER 0xFF010104
+-#define OID_SKGE_VPD_KEY 0xFF010105
+-#define OID_SKGE_VPD_VALUE 0xFF010106
+-#define OID_SKGE_VPD_ACCESS 0xFF010107
+-#define OID_SKGE_VPD_ACTION 0xFF010108
+-
+-#define OID_SKGE_PORT_NUMBER 0xFF010110
+-#define OID_SKGE_DEVICE_TYPE 0xFF010111
+-#define OID_SKGE_DRIVER_DESCR 0xFF010112
+-#define OID_SKGE_DRIVER_VERSION 0xFF010113
+-#define OID_SKGE_HW_DESCR 0xFF010114
+-#define OID_SKGE_HW_VERSION 0xFF010115
+-#define OID_SKGE_CHIPSET 0xFF010116
+-#define OID_SKGE_ACTION 0xFF010117
+-#define OID_SKGE_RESULT 0xFF010118
+-#define OID_SKGE_BUS_TYPE 0xFF010119
+-#define OID_SKGE_BUS_SPEED 0xFF01011A
+-#define OID_SKGE_BUS_WIDTH 0xFF01011B
+-/* 0xFF01011C unused */
+-#define OID_SKGE_DIAG_ACTION 0xFF01011D
+-#define OID_SKGE_DIAG_RESULT 0xFF01011E
+-#define OID_SKGE_MTU 0xFF01011F
+-#define OID_SKGE_PHYS_CUR_ADDR 0xFF010120
+-#define OID_SKGE_PHYS_FAC_ADDR 0xFF010121
+-#define OID_SKGE_PMD 0xFF010122
+-#define OID_SKGE_CONNECTOR 0xFF010123
+-#define OID_SKGE_LINK_CAP 0xFF010124
+-#define OID_SKGE_LINK_MODE 0xFF010125
+-#define OID_SKGE_LINK_MODE_STATUS 0xFF010126
+-#define OID_SKGE_LINK_STATUS 0xFF010127
+-#define OID_SKGE_FLOWCTRL_CAP 0xFF010128
+-#define OID_SKGE_FLOWCTRL_MODE 0xFF010129
+-#define OID_SKGE_FLOWCTRL_STATUS 0xFF01012A
+-#define OID_SKGE_PHY_OPERATION_CAP 0xFF01012B
+-#define OID_SKGE_PHY_OPERATION_MODE 0xFF01012C
+-#define OID_SKGE_PHY_OPERATION_STATUS 0xFF01012D
+-#define OID_SKGE_MULTICAST_LIST 0xFF01012E
+-#define OID_SKGE_CURRENT_PACKET_FILTER 0xFF01012F
+-
+-#define OID_SKGE_TRAP 0xFF010130
+-#define OID_SKGE_TRAP_NUMBER 0xFF010131
+-
+-#define OID_SKGE_RLMT_MODE 0xFF010140
+-#define OID_SKGE_RLMT_PORT_NUMBER 0xFF010141
+-#define OID_SKGE_RLMT_PORT_ACTIVE 0xFF010142
+-#define OID_SKGE_RLMT_PORT_PREFERRED 0xFF010143
+-#define OID_SKGE_INTERMEDIATE_SUPPORT 0xFF010160
+-
+-#define OID_SKGE_SPEED_CAP 0xFF010170
+-#define OID_SKGE_SPEED_MODE 0xFF010171
+-#define OID_SKGE_SPEED_STATUS 0xFF010172
+-
+-#define OID_SKGE_BOARDLEVEL 0xFF010180
+-
+-#define OID_SKGE_SENSOR_NUMBER 0xFF020100
+-#define OID_SKGE_SENSOR_INDEX 0xFF020101
+-#define OID_SKGE_SENSOR_DESCR 0xFF020102
+-#define OID_SKGE_SENSOR_TYPE 0xFF020103
+-#define OID_SKGE_SENSOR_VALUE 0xFF020104
+-#define OID_SKGE_SENSOR_WAR_THRES_LOW 0xFF020105
+-#define OID_SKGE_SENSOR_WAR_THRES_UPP 0xFF020106
+-#define OID_SKGE_SENSOR_ERR_THRES_LOW 0xFF020107
+-#define OID_SKGE_SENSOR_ERR_THRES_UPP 0xFF020108
+-#define OID_SKGE_SENSOR_STATUS 0xFF020109
+-#define OID_SKGE_SENSOR_WAR_CTS 0xFF02010A
+-#define OID_SKGE_SENSOR_ERR_CTS 0xFF02010B
+-#define OID_SKGE_SENSOR_WAR_TIME 0xFF02010C
+-#define OID_SKGE_SENSOR_ERR_TIME 0xFF02010D
+-
+-#define OID_SKGE_CHKSM_NUMBER 0xFF020110
+-#define OID_SKGE_CHKSM_RX_OK_CTS 0xFF020111
+-#define OID_SKGE_CHKSM_RX_UNABLE_CTS 0xFF020112
+-#define OID_SKGE_CHKSM_RX_ERR_CTS 0xFF020113
+-#define OID_SKGE_CHKSM_TX_OK_CTS 0xFF020114
+-#define OID_SKGE_CHKSM_TX_UNABLE_CTS 0xFF020115
+-
+-#define OID_SKGE_STAT_TX 0xFF020120
+-#define OID_SKGE_STAT_TX_OCTETS 0xFF020121
+-#define OID_SKGE_STAT_TX_BROADCAST 0xFF020122
+-#define OID_SKGE_STAT_TX_MULTICAST 0xFF020123
+-#define OID_SKGE_STAT_TX_UNICAST 0xFF020124
+-#define OID_SKGE_STAT_TX_LONGFRAMES 0xFF020125
+-#define OID_SKGE_STAT_TX_BURST 0xFF020126
+-#define OID_SKGE_STAT_TX_PFLOWC 0xFF020127
+-#define OID_SKGE_STAT_TX_FLOWC 0xFF020128
+-#define OID_SKGE_STAT_TX_SINGLE_COL 0xFF020129
+-#define OID_SKGE_STAT_TX_MULTI_COL 0xFF02012A
+-#define OID_SKGE_STAT_TX_EXCESS_COL 0xFF02012B
+-#define OID_SKGE_STAT_TX_LATE_COL 0xFF02012C
+-#define OID_SKGE_STAT_TX_DEFFERAL 0xFF02012D
+-#define OID_SKGE_STAT_TX_EXCESS_DEF 0xFF02012E
+-#define OID_SKGE_STAT_TX_UNDERRUN 0xFF02012F
+-#define OID_SKGE_STAT_TX_CARRIER 0xFF020130
+-/* #define OID_SKGE_STAT_TX_UTIL 0xFF020131 */
+-#define OID_SKGE_STAT_TX_64 0xFF020132
+-#define OID_SKGE_STAT_TX_127 0xFF020133
+-#define OID_SKGE_STAT_TX_255 0xFF020134
+-#define OID_SKGE_STAT_TX_511 0xFF020135
+-#define OID_SKGE_STAT_TX_1023 0xFF020136
+-#define OID_SKGE_STAT_TX_MAX 0xFF020137
+-#define OID_SKGE_STAT_TX_SYNC 0xFF020138
+-#define OID_SKGE_STAT_TX_SYNC_OCTETS 0xFF020139
+-#define OID_SKGE_STAT_RX 0xFF02013A
+-#define OID_SKGE_STAT_RX_OCTETS 0xFF02013B
+-#define OID_SKGE_STAT_RX_BROADCAST 0xFF02013C
+-#define OID_SKGE_STAT_RX_MULTICAST 0xFF02013D
+-#define OID_SKGE_STAT_RX_UNICAST 0xFF02013E
+-#define OID_SKGE_STAT_RX_PFLOWC 0xFF02013F
+-#define OID_SKGE_STAT_RX_FLOWC 0xFF020140
+-#define OID_SKGE_STAT_RX_PFLOWC_ERR 0xFF020141
+-#define OID_SKGE_STAT_RX_FLOWC_UNKWN 0xFF020142
+-#define OID_SKGE_STAT_RX_BURST 0xFF020143
+-#define OID_SKGE_STAT_RX_MISSED 0xFF020144
+-#define OID_SKGE_STAT_RX_FRAMING 0xFF020145
+-#define OID_SKGE_STAT_RX_OVERFLOW 0xFF020146
+-#define OID_SKGE_STAT_RX_JABBER 0xFF020147
+-#define OID_SKGE_STAT_RX_CARRIER 0xFF020148
+-#define OID_SKGE_STAT_RX_IR_LENGTH 0xFF020149
+-#define OID_SKGE_STAT_RX_SYMBOL 0xFF02014A
+-#define OID_SKGE_STAT_RX_SHORTS 0xFF02014B
+-#define OID_SKGE_STAT_RX_RUNT 0xFF02014C
+-#define OID_SKGE_STAT_RX_CEXT 0xFF02014D
+-#define OID_SKGE_STAT_RX_TOO_LONG 0xFF02014E
+-#define OID_SKGE_STAT_RX_FCS 0xFF02014F
+-/* #define OID_SKGE_STAT_RX_UTIL 0xFF020150 */
+-#define OID_SKGE_STAT_RX_64 0xFF020151
+-#define OID_SKGE_STAT_RX_127 0xFF020152
+-#define OID_SKGE_STAT_RX_255 0xFF020153
+-#define OID_SKGE_STAT_RX_511 0xFF020154
+-#define OID_SKGE_STAT_RX_1023 0xFF020155
+-#define OID_SKGE_STAT_RX_MAX 0xFF020156
+-#define OID_SKGE_STAT_RX_LONGFRAMES 0xFF020157
+-
+-#define OID_SKGE_RLMT_CHANGE_CTS 0xFF020160
+-#define OID_SKGE_RLMT_CHANGE_TIME 0xFF020161
+-#define OID_SKGE_RLMT_CHANGE_ESTIM 0xFF020162
+-#define OID_SKGE_RLMT_CHANGE_THRES 0xFF020163
+-
+-#define OID_SKGE_RLMT_PORT_INDEX 0xFF020164
+-#define OID_SKGE_RLMT_STATUS 0xFF020165
+-#define OID_SKGE_RLMT_TX_HELLO_CTS 0xFF020166
+-#define OID_SKGE_RLMT_RX_HELLO_CTS 0xFF020167
+-#define OID_SKGE_RLMT_TX_SP_REQ_CTS 0xFF020168
+-#define OID_SKGE_RLMT_RX_SP_CTS 0xFF020169
+-
+-#define OID_SKGE_RLMT_MONITOR_NUMBER 0xFF010150
+-#define OID_SKGE_RLMT_MONITOR_INDEX 0xFF010151
+-#define OID_SKGE_RLMT_MONITOR_ADDR 0xFF010152
+-#define OID_SKGE_RLMT_MONITOR_ERRS 0xFF010153
+-#define OID_SKGE_RLMT_MONITOR_TIMESTAMP 0xFF010154
+-#define OID_SKGE_RLMT_MONITOR_ADMIN 0xFF010155
+-
+-#define OID_SKGE_TX_SW_QUEUE_LEN 0xFF020170
+-#define OID_SKGE_TX_SW_QUEUE_MAX 0xFF020171
+-#define OID_SKGE_TX_RETRY 0xFF020172
+-#define OID_SKGE_RX_INTR_CTS 0xFF020173
+-#define OID_SKGE_TX_INTR_CTS 0xFF020174
+-#define OID_SKGE_RX_NO_BUF_CTS 0xFF020175
+-#define OID_SKGE_TX_NO_BUF_CTS 0xFF020176
+-#define OID_SKGE_TX_USED_DESCR_NO 0xFF020177
+-#define OID_SKGE_RX_DELIVERED_CTS 0xFF020178
+-#define OID_SKGE_RX_OCTETS_DELIV_CTS 0xFF020179
+-#define OID_SKGE_RX_HW_ERROR_CTS 0xFF02017A
+-#define OID_SKGE_TX_HW_ERROR_CTS 0xFF02017B
+-#define OID_SKGE_IN_ERRORS_CTS 0xFF02017C
+-#define OID_SKGE_OUT_ERROR_CTS 0xFF02017D
+-#define OID_SKGE_ERR_RECOVERY_CTS 0xFF02017E
+-#define OID_SKGE_SYSUPTIME 0xFF02017F
+-
+-#define OID_SKGE_ALL_DATA 0xFF020190
+-
+-/* Defines for VCT. */
+-#define OID_SKGE_VCT_GET 0xFF020200
+-#define OID_SKGE_VCT_SET 0xFF020201
+-#define OID_SKGE_VCT_STATUS 0xFF020202
+-
+-#ifdef SK_DIAG_SUPPORT
+-/* Defines for driver DIAG mode. */
+-#define OID_SKGE_DIAG_MODE 0xFF020204
+-#endif /* SK_DIAG_SUPPORT */
+-
+-/* New OIDs */
+-#define OID_SKGE_DRIVER_RELDATE 0xFF020210
+-#define OID_SKGE_DRIVER_FILENAME 0xFF020211
+-#define OID_SKGE_CHIPID 0xFF020212
+-#define OID_SKGE_RAMSIZE 0xFF020213
+-#define OID_SKGE_VAUXAVAIL 0xFF020214
+-#define OID_SKGE_PHY_TYPE 0xFF020215
+-#define OID_SKGE_PHY_LP_MODE 0xFF020216
+-
+-/* VCT struct to store a backup copy of VCT data after a port reset. */
+-typedef struct s_PnmiVct {
+- SK_U8 VctStatus;
+- SK_U8 PCableLen;
+- SK_U32 PMdiPairLen[4];
+- SK_U8 PMdiPairSts[4];
+-} SK_PNMI_VCT;
+-
+-
+-/* VCT status values (to be given to CPA via OID_SKGE_VCT_STATUS). */
+-#define SK_PNMI_VCT_NONE 0
+-#define SK_PNMI_VCT_OLD_VCT_DATA 1
+-#define SK_PNMI_VCT_NEW_VCT_DATA 2
+-#define SK_PNMI_VCT_OLD_DSP_DATA 4
+-#define SK_PNMI_VCT_NEW_DSP_DATA 8
+-#define SK_PNMI_VCT_RUNNING 16
+-
+-
+-/* VCT cable test status. */
+-#define SK_PNMI_VCT_NORMAL_CABLE 0
+-#define SK_PNMI_VCT_SHORT_CABLE 1
+-#define SK_PNMI_VCT_OPEN_CABLE 2
+-#define SK_PNMI_VCT_TEST_FAIL 3
+-#define SK_PNMI_VCT_IMPEDANCE_MISMATCH 4
+-
+-#define OID_SKGE_TRAP_SEN_WAR_LOW 500
+-#define OID_SKGE_TRAP_SEN_WAR_UPP 501
+-#define OID_SKGE_TRAP_SEN_ERR_LOW 502
+-#define OID_SKGE_TRAP_SEN_ERR_UPP 503
+-#define OID_SKGE_TRAP_RLMT_CHANGE_THRES 520
+-#define OID_SKGE_TRAP_RLMT_CHANGE_PORT 521
+-#define OID_SKGE_TRAP_RLMT_PORT_DOWN 522
+-#define OID_SKGE_TRAP_RLMT_PORT_UP 523
+-#define OID_SKGE_TRAP_RLMT_SEGMENTATION 524
+-
+-#ifdef SK_DIAG_SUPPORT
+-/* Defines for driver DIAG mode. */
+-#define SK_DIAG_ATTACHED 2
+-#define SK_DIAG_RUNNING 1
+-#define SK_DIAG_IDLE 0
+-#endif /* SK_DIAG_SUPPORT */
+-
+-/*
+- * Generic PNMI IOCTL subcommand definitions.
+- */
+-#define SK_GET_SINGLE_VAR 1
+-#define SK_SET_SINGLE_VAR 2
+-#define SK_PRESET_SINGLE_VAR 3
+-#define SK_GET_FULL_MIB 4
+-#define SK_SET_FULL_MIB 5
+-#define SK_PRESET_FULL_MIB 6
+-
+-
+-/*
+- * Define error numbers and messages for syslog
+- */
+-#define SK_PNMI_ERR001 (SK_ERRBASE_PNMI + 1)
+-#define SK_PNMI_ERR001MSG "SkPnmiGetStruct: Unknown OID"
+-#define SK_PNMI_ERR002 (SK_ERRBASE_PNMI + 2)
+-#define SK_PNMI_ERR002MSG "SkPnmiGetStruct: Cannot read VPD keys"
+-#define SK_PNMI_ERR003 (SK_ERRBASE_PNMI + 3)
+-#define SK_PNMI_ERR003MSG "OidStruct: Called with wrong OID"
+-#define SK_PNMI_ERR004 (SK_ERRBASE_PNMI + 4)
+-#define SK_PNMI_ERR004MSG "OidStruct: Called with wrong action"
+-#define SK_PNMI_ERR005 (SK_ERRBASE_PNMI + 5)
+-#define SK_PNMI_ERR005MSG "Perform: Cannot reset driver"
+-#define SK_PNMI_ERR006 (SK_ERRBASE_PNMI + 6)
+-#define SK_PNMI_ERR006MSG "Perform: Unknown OID action command"
+-#define SK_PNMI_ERR007 (SK_ERRBASE_PNMI + 7)
+-#define SK_PNMI_ERR007MSG "General: Driver description not initialized"
+-#define SK_PNMI_ERR008 (SK_ERRBASE_PNMI + 8)
+-#define SK_PNMI_ERR008MSG "Addr: Tried to get unknown OID"
+-#define SK_PNMI_ERR009 (SK_ERRBASE_PNMI + 9)
+-#define SK_PNMI_ERR009MSG "Addr: Unknown OID"
+-#define SK_PNMI_ERR010 (SK_ERRBASE_PNMI + 10)
+-#define SK_PNMI_ERR010MSG "CsumStat: Unknown OID"
+-#define SK_PNMI_ERR011 (SK_ERRBASE_PNMI + 11)
+-#define SK_PNMI_ERR011MSG "SensorStat: Sensor descr string too long"
+-#define SK_PNMI_ERR012 (SK_ERRBASE_PNMI + 12)
+-#define SK_PNMI_ERR012MSG "SensorStat: Unknown OID"
+-#define SK_PNMI_ERR013 (SK_ERRBASE_PNMI + 13)
+-#define SK_PNMI_ERR013MSG ""
+-#define SK_PNMI_ERR014 (SK_ERRBASE_PNMI + 14)
+-#define SK_PNMI_ERR014MSG "Vpd: Cannot read VPD keys"
+-#define SK_PNMI_ERR015 (SK_ERRBASE_PNMI + 15)
+-#define SK_PNMI_ERR015MSG "Vpd: Internal array for VPD keys to small"
+-#define SK_PNMI_ERR016 (SK_ERRBASE_PNMI + 16)
+-#define SK_PNMI_ERR016MSG "Vpd: Key string too long"
+-#define SK_PNMI_ERR017 (SK_ERRBASE_PNMI + 17)
+-#define SK_PNMI_ERR017MSG "Vpd: Invalid VPD status pointer"
+-#define SK_PNMI_ERR018 (SK_ERRBASE_PNMI + 18)
+-#define SK_PNMI_ERR018MSG "Vpd: VPD data not valid"
+-#define SK_PNMI_ERR019 (SK_ERRBASE_PNMI + 19)
+-#define SK_PNMI_ERR019MSG "Vpd: VPD entries list string too long"
+-#define SK_PNMI_ERR021 (SK_ERRBASE_PNMI + 21)
+-#define SK_PNMI_ERR021MSG "Vpd: VPD data string too long"
+-#define SK_PNMI_ERR022 (SK_ERRBASE_PNMI + 22)
+-#define SK_PNMI_ERR022MSG "Vpd: VPD data string too long should be errored before"
+-#define SK_PNMI_ERR023 (SK_ERRBASE_PNMI + 23)
+-#define SK_PNMI_ERR023MSG "Vpd: Unknown OID in get action"
+-#define SK_PNMI_ERR024 (SK_ERRBASE_PNMI + 24)
+-#define SK_PNMI_ERR024MSG "Vpd: Unknown OID in preset/set action"
+-#define SK_PNMI_ERR025 (SK_ERRBASE_PNMI + 25)
+-#define SK_PNMI_ERR025MSG "Vpd: Cannot write VPD after modify entry"
+-#define SK_PNMI_ERR026 (SK_ERRBASE_PNMI + 26)
+-#define SK_PNMI_ERR026MSG "Vpd: Cannot update VPD"
+-#define SK_PNMI_ERR027 (SK_ERRBASE_PNMI + 27)
+-#define SK_PNMI_ERR027MSG "Vpd: Cannot delete VPD entry"
+-#define SK_PNMI_ERR028 (SK_ERRBASE_PNMI + 28)
+-#define SK_PNMI_ERR028MSG "Vpd: Cannot update VPD after delete entry"
+-#define SK_PNMI_ERR029 (SK_ERRBASE_PNMI + 29)
+-#define SK_PNMI_ERR029MSG "General: Driver description string too long"
+-#define SK_PNMI_ERR030 (SK_ERRBASE_PNMI + 30)
+-#define SK_PNMI_ERR030MSG "General: Driver version not initialized"
+-#define SK_PNMI_ERR031 (SK_ERRBASE_PNMI + 31)
+-#define SK_PNMI_ERR031MSG "General: Driver version string too long"
+-#define SK_PNMI_ERR032 (SK_ERRBASE_PNMI + 32)
+-#define SK_PNMI_ERR032MSG "General: Cannot read VPD Name for HW descr"
+-#define SK_PNMI_ERR033 (SK_ERRBASE_PNMI + 33)
+-#define SK_PNMI_ERR033MSG "General: HW description string too long"
+-#define SK_PNMI_ERR034 (SK_ERRBASE_PNMI + 34)
+-#define SK_PNMI_ERR034MSG "General: Unknown OID"
+-#define SK_PNMI_ERR035 (SK_ERRBASE_PNMI + 35)
+-#define SK_PNMI_ERR035MSG "Rlmt: Unknown OID"
+-#define SK_PNMI_ERR036 (SK_ERRBASE_PNMI + 36)
+-#define SK_PNMI_ERR036MSG ""
+-#define SK_PNMI_ERR037 (SK_ERRBASE_PNMI + 37)
+-#define SK_PNMI_ERR037MSG "Rlmt: SK_RLMT_MODE_CHANGE event return not 0"
+-#define SK_PNMI_ERR038 (SK_ERRBASE_PNMI + 38)
+-#define SK_PNMI_ERR038MSG "Rlmt: SK_RLMT_PREFPORT_CHANGE event return not 0"
+-#define SK_PNMI_ERR039 (SK_ERRBASE_PNMI + 39)
+-#define SK_PNMI_ERR039MSG "RlmtStat: Unknown OID"
+-#define SK_PNMI_ERR040 (SK_ERRBASE_PNMI + 40)
+-#define SK_PNMI_ERR040MSG "PowerManagement: Unknown OID"
+-#define SK_PNMI_ERR041 (SK_ERRBASE_PNMI + 41)
+-#define SK_PNMI_ERR041MSG "MacPrivateConf: Unknown OID"
+-#define SK_PNMI_ERR042 (SK_ERRBASE_PNMI + 42)
+-#define SK_PNMI_ERR042MSG "MacPrivateConf: SK_HWEV_SET_ROLE returned not 0"
+-#define SK_PNMI_ERR043 (SK_ERRBASE_PNMI + 43)
+-#define SK_PNMI_ERR043MSG "MacPrivateConf: SK_HWEV_SET_LMODE returned not 0"
+-#define SK_PNMI_ERR044 (SK_ERRBASE_PNMI + 44)
+-#define SK_PNMI_ERR044MSG "MacPrivateConf: SK_HWEV_SET_FLOWMODE returned not 0"
+-#define SK_PNMI_ERR045 (SK_ERRBASE_PNMI + 45)
+-#define SK_PNMI_ERR045MSG "MacPrivateConf: SK_HWEV_SET_SPEED returned not 0"
+-#define SK_PNMI_ERR046 (SK_ERRBASE_PNMI + 46)
+-#define SK_PNMI_ERR046MSG "Monitor: Unknown OID"
+-#define SK_PNMI_ERR047 (SK_ERRBASE_PNMI + 47)
+-#define SK_PNMI_ERR047MSG "SirqUpdate: Event function returns not 0"
+-#define SK_PNMI_ERR048 (SK_ERRBASE_PNMI + 48)
+-#define SK_PNMI_ERR048MSG "RlmtUpdate: Event function returns not 0"
+-#define SK_PNMI_ERR049 (SK_ERRBASE_PNMI + 49)
+-#define SK_PNMI_ERR049MSG "SkPnmiInit: Invalid size of 'CounterOffset' struct!!"
+-#define SK_PNMI_ERR050 (SK_ERRBASE_PNMI + 50)
+-#define SK_PNMI_ERR050MSG "SkPnmiInit: Invalid size of 'StatAddr' table!!"
+-#define SK_PNMI_ERR051 (SK_ERRBASE_PNMI + 51)
+-#define SK_PNMI_ERR051MSG "SkPnmiEvent: Port switch suspicious"
+-#define SK_PNMI_ERR052 (SK_ERRBASE_PNMI + 52)
+-#define SK_PNMI_ERR052MSG ""
+-#define SK_PNMI_ERR053 (SK_ERRBASE_PNMI + 53)
+-#define SK_PNMI_ERR053MSG "General: Driver release date not initialized"
+-#define SK_PNMI_ERR054 (SK_ERRBASE_PNMI + 54)
+-#define SK_PNMI_ERR054MSG "General: Driver release date string too long"
+-#define SK_PNMI_ERR055 (SK_ERRBASE_PNMI + 55)
+-#define SK_PNMI_ERR055MSG "General: Driver file name not initialized"
+-#define SK_PNMI_ERR056 (SK_ERRBASE_PNMI + 56)
+-#define SK_PNMI_ERR056MSG "General: Driver file name string too long"
+-
+-/*
+- * Management counter macros called by the driver
+- */
+-#define SK_PNMI_SET_DRIVER_DESCR(pAC,v) ((pAC)->Pnmi.pDriverDescription = \
+- (char *)(v))
+-
+-#define SK_PNMI_SET_DRIVER_VER(pAC,v) ((pAC)->Pnmi.pDriverVersion = \
+- (char *)(v))
+-
+-#define SK_PNMI_SET_DRIVER_RELDATE(pAC,v) ((pAC)->Pnmi.pDriverReleaseDate = \
+- (char *)(v))
+-
+-#define SK_PNMI_SET_DRIVER_FILENAME(pAC,v) ((pAC)->Pnmi.pDriverFileName = \
+- (char *)(v))
+-
+-#define SK_PNMI_CNT_TX_QUEUE_LEN(pAC,v,p) \
+- { \
+- (pAC)->Pnmi.Port[p].TxSwQueueLen = (SK_U64)(v); \
+- if ((pAC)->Pnmi.Port[p].TxSwQueueLen > (pAC)->Pnmi.Port[p].TxSwQueueMax) { \
+- (pAC)->Pnmi.Port[p].TxSwQueueMax = (pAC)->Pnmi.Port[p].TxSwQueueLen; \
+- } \
+- }
+-#define SK_PNMI_CNT_TX_RETRY(pAC,p) (((pAC)->Pnmi.Port[p].TxRetryCts)++)
+-#define SK_PNMI_CNT_RX_INTR(pAC,p) (((pAC)->Pnmi.Port[p].RxIntrCts)++)
+-#define SK_PNMI_CNT_TX_INTR(pAC,p) (((pAC)->Pnmi.Port[p].TxIntrCts)++)
+-#define SK_PNMI_CNT_NO_RX_BUF(pAC,p) (((pAC)->Pnmi.Port[p].RxNoBufCts)++)
+-#define SK_PNMI_CNT_NO_TX_BUF(pAC,p) (((pAC)->Pnmi.Port[p].TxNoBufCts)++)
+-#define SK_PNMI_CNT_USED_TX_DESCR(pAC,v,p) \
+- ((pAC)->Pnmi.Port[p].TxUsedDescrNo=(SK_U64)(v));
+-#define SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,v,p) \
+- { \
+- ((pAC)->Pnmi.Port[p].RxDeliveredCts)++; \
+- (pAC)->Pnmi.Port[p].RxOctetsDeliveredCts += (SK_U64)(v); \
+- }
+-#define SK_PNMI_CNT_ERR_RECOVERY(pAC,p) (((pAC)->Pnmi.Port[p].ErrRecoveryCts)++);
+-
+-#define SK_PNMI_CNT_SYNC_OCTETS(pAC,p,v) \
+- { \
+- if ((p) < SK_MAX_MACS) { \
+- ((pAC)->Pnmi.Port[p].StatSyncCts)++; \
+- (pAC)->Pnmi.Port[p].StatSyncOctetsCts += (SK_U64)(v); \
+- } \
+- }
+-
+-#define SK_PNMI_CNT_RX_LONGFRAMES(pAC,p) \
+- { \
+- if ((p) < SK_MAX_MACS) { \
+- ((pAC)->Pnmi.Port[p].StatRxLongFrameCts++); \
+- } \
+- }
+-
+-#define SK_PNMI_CNT_RX_FRAMETOOLONG(pAC,p) \
+- { \
+- if ((p) < SK_MAX_MACS) { \
+- ((pAC)->Pnmi.Port[p].StatRxFrameTooLongCts++); \
+- } \
+- }
+-
+-#define SK_PNMI_CNT_RX_PMACC_ERR(pAC,p) \
+- { \
+- if ((p) < SK_MAX_MACS) { \
+- ((pAC)->Pnmi.Port[p].StatRxPMaccErr++); \
+- } \
+- }
+-
+-/*
+- * Conversion Macros
+- */
+-#define SK_PNMI_PORT_INST2LOG(i) ((unsigned int)(i) - 1)
+-#define SK_PNMI_PORT_LOG2INST(l) ((unsigned int)(l) + 1)
+-#define SK_PNMI_PORT_PHYS2LOG(p) ((unsigned int)(p) + 1)
+-#define SK_PNMI_PORT_LOG2PHYS(pAC,l) ((unsigned int)(l) - 1)
+-#define SK_PNMI_PORT_PHYS2INST(pAC,p) \
+- (pAC->Pnmi.DualNetActiveFlag ? 2 : ((unsigned int)(p) + 2))
+-#define SK_PNMI_PORT_INST2PHYS(pAC,i) ((unsigned int)(i) - 2)
+-
+-/*
+- * Structure definition for SkPnmiGetStruct and SkPnmiSetStruct
+- */
+-#define SK_PNMI_VPD_KEY_SIZE 5
+-#define SK_PNMI_VPD_BUFSIZE (VPD_SIZE)
+-#define SK_PNMI_VPD_ENTRIES (VPD_SIZE / 4)
+-#define SK_PNMI_VPD_DATALEN 128 /* Number of data bytes */
+-
+-#define SK_PNMI_MULTICAST_LISTLEN 64
+-#define SK_PNMI_SENSOR_ENTRIES (SK_MAX_SENSORS)
+-#define SK_PNMI_CHECKSUM_ENTRIES 3
+-#define SK_PNMI_MAC_ENTRIES (SK_MAX_MACS + 1)
+-#define SK_PNMI_MONITOR_ENTRIES 20
+-#define SK_PNMI_TRAP_ENTRIES 10
+-#define SK_PNMI_TRAPLEN 128
+-#define SK_PNMI_STRINGLEN1 80
+-#define SK_PNMI_STRINGLEN2 25
+-#define SK_PNMI_TRAP_QUEUE_LEN 512
+-
+-typedef struct s_PnmiVpd {
+- char VpdKey[SK_PNMI_VPD_KEY_SIZE];
+- char VpdValue[SK_PNMI_VPD_DATALEN];
+- SK_U8 VpdAccess;
+- SK_U8 VpdAction;
+-} SK_PNMI_VPD;
+-
+-typedef struct s_PnmiSensor {
+- SK_U8 SensorIndex;
+- char SensorDescr[SK_PNMI_STRINGLEN2];
+- SK_U8 SensorType;
+- SK_U32 SensorValue;
+- SK_U32 SensorWarningThresholdLow;
+- SK_U32 SensorWarningThresholdHigh;
+- SK_U32 SensorErrorThresholdLow;
+- SK_U32 SensorErrorThresholdHigh;
+- SK_U8 SensorStatus;
+- SK_U64 SensorWarningCts;
+- SK_U64 SensorErrorCts;
+- SK_U64 SensorWarningTimestamp;
+- SK_U64 SensorErrorTimestamp;
+-} SK_PNMI_SENSOR;
+-
+-typedef struct s_PnmiChecksum {
+- SK_U64 ChecksumRxOkCts;
+- SK_U64 ChecksumRxUnableCts;
+- SK_U64 ChecksumRxErrCts;
+- SK_U64 ChecksumTxOkCts;
+- SK_U64 ChecksumTxUnableCts;
+-} SK_PNMI_CHECKSUM;
+-
+-typedef struct s_PnmiStat {
+- SK_U64 StatTxOkCts;
+- SK_U64 StatTxOctetsOkCts;
+- SK_U64 StatTxBroadcastOkCts;
+- SK_U64 StatTxMulticastOkCts;
+- SK_U64 StatTxUnicastOkCts;
+- SK_U64 StatTxLongFramesCts;
+- SK_U64 StatTxBurstCts;
+- SK_U64 StatTxPauseMacCtrlCts;
+- SK_U64 StatTxMacCtrlCts;
+- SK_U64 StatTxSingleCollisionCts;
+- SK_U64 StatTxMultipleCollisionCts;
+- SK_U64 StatTxExcessiveCollisionCts;
+- SK_U64 StatTxLateCollisionCts;
+- SK_U64 StatTxDeferralCts;
+- SK_U64 StatTxExcessiveDeferralCts;
+- SK_U64 StatTxFifoUnderrunCts;
+- SK_U64 StatTxCarrierCts;
+- SK_U64 Dummy1; /* StatTxUtilization */
+- SK_U64 StatTx64Cts;
+- SK_U64 StatTx127Cts;
+- SK_U64 StatTx255Cts;
+- SK_U64 StatTx511Cts;
+- SK_U64 StatTx1023Cts;
+- SK_U64 StatTxMaxCts;
+- SK_U64 StatTxSyncCts;
+- SK_U64 StatTxSyncOctetsCts;
+- SK_U64 StatRxOkCts;
+- SK_U64 StatRxOctetsOkCts;
+- SK_U64 StatRxBroadcastOkCts;
+- SK_U64 StatRxMulticastOkCts;
+- SK_U64 StatRxUnicastOkCts;
+- SK_U64 StatRxLongFramesCts;
+- SK_U64 StatRxPauseMacCtrlCts;
+- SK_U64 StatRxMacCtrlCts;
+- SK_U64 StatRxPauseMacCtrlErrorCts;
+- SK_U64 StatRxMacCtrlUnknownCts;
+- SK_U64 StatRxBurstCts;
+- SK_U64 StatRxMissedCts;
+- SK_U64 StatRxFramingCts;
+- SK_U64 StatRxFifoOverflowCts;
+- SK_U64 StatRxJabberCts;
+- SK_U64 StatRxCarrierCts;
+- SK_U64 StatRxIRLengthCts;
+- SK_U64 StatRxSymbolCts;
+- SK_U64 StatRxShortsCts;
+- SK_U64 StatRxRuntCts;
+- SK_U64 StatRxCextCts;
+- SK_U64 StatRxTooLongCts;
+- SK_U64 StatRxFcsCts;
+- SK_U64 Dummy2; /* StatRxUtilization */
+- SK_U64 StatRx64Cts;
+- SK_U64 StatRx127Cts;
+- SK_U64 StatRx255Cts;
+- SK_U64 StatRx511Cts;
+- SK_U64 StatRx1023Cts;
+- SK_U64 StatRxMaxCts;
+-} SK_PNMI_STAT;
+-
+-typedef struct s_PnmiConf {
+- char ConfMacCurrentAddr[6];
+- char ConfMacFactoryAddr[6];
+- SK_U8 ConfPMD;
+- SK_U8 ConfConnector;
+- SK_U32 ConfPhyType;
+- SK_U32 ConfPhyMode;
+- SK_U8 ConfLinkCapability;
+- SK_U8 ConfLinkMode;
+- SK_U8 ConfLinkModeStatus;
+- SK_U8 ConfLinkStatus;
+- SK_U8 ConfFlowCtrlCapability;
+- SK_U8 ConfFlowCtrlMode;
+- SK_U8 ConfFlowCtrlStatus;
+- SK_U8 ConfPhyOperationCapability;
+- SK_U8 ConfPhyOperationMode;
+- SK_U8 ConfPhyOperationStatus;
+- SK_U8 ConfSpeedCapability;
+- SK_U8 ConfSpeedMode;
+- SK_U8 ConfSpeedStatus;
+-} SK_PNMI_CONF;
+-
+-typedef struct s_PnmiRlmt {
+- SK_U32 RlmtIndex;
+- SK_U32 RlmtStatus;
+- SK_U64 RlmtTxHelloCts;
+- SK_U64 RlmtRxHelloCts;
+- SK_U64 RlmtTxSpHelloReqCts;
+- SK_U64 RlmtRxSpHelloCts;
+-} SK_PNMI_RLMT;
+-
+-typedef struct s_PnmiRlmtMonitor {
+- SK_U32 RlmtMonitorIndex;
+- char RlmtMonitorAddr[6];
+- SK_U64 RlmtMonitorErrorCts;
+- SK_U64 RlmtMonitorTimestamp;
+- SK_U8 RlmtMonitorAdmin;
+-} SK_PNMI_RLMT_MONITOR;
+-
+-typedef struct s_PnmiRequestStatus {
+- SK_U32 ErrorStatus;
+- SK_U32 ErrorOffset;
+-} SK_PNMI_REQUEST_STATUS;
+-
+-typedef struct s_PnmiStrucData {
+- SK_U32 MgmtDBVersion;
+- SK_PNMI_REQUEST_STATUS ReturnStatus;
+- SK_U32 VpdFreeBytes;
+- char VpdEntriesList[SK_PNMI_VPD_ENTRIES * SK_PNMI_VPD_KEY_SIZE];
+- SK_U32 VpdEntriesNumber;
+- SK_PNMI_VPD Vpd[SK_PNMI_VPD_ENTRIES];
+- SK_U32 PortNumber;
+- SK_U32 DeviceType;
+- char DriverDescr[SK_PNMI_STRINGLEN1];
+- char DriverVersion[SK_PNMI_STRINGLEN2];
+- char DriverReleaseDate[SK_PNMI_STRINGLEN1];
+- char DriverFileName[SK_PNMI_STRINGLEN1];
+- char HwDescr[SK_PNMI_STRINGLEN1];
+- char HwVersion[SK_PNMI_STRINGLEN2];
+- SK_U16 Chipset;
+- SK_U32 ChipId;
+- SK_U8 VauxAvail;
+- SK_U32 RamSize;
+- SK_U32 MtuSize;
+- SK_U32 Action;
+- SK_U32 TestResult;
+- SK_U8 BusType;
+- SK_U8 BusSpeed;
+- SK_U8 BusWidth;
+- SK_U8 SensorNumber;
+- SK_PNMI_SENSOR Sensor[SK_PNMI_SENSOR_ENTRIES];
+- SK_U8 ChecksumNumber;
+- SK_PNMI_CHECKSUM Checksum[SK_PNMI_CHECKSUM_ENTRIES];
+- SK_PNMI_STAT Stat[SK_PNMI_MAC_ENTRIES];
+- SK_PNMI_CONF Conf[SK_PNMI_MAC_ENTRIES];
+- SK_U8 RlmtMode;
+- SK_U32 RlmtPortNumber;
+- SK_U8 RlmtPortActive;
+- SK_U8 RlmtPortPreferred;
+- SK_U64 RlmtChangeCts;
+- SK_U64 RlmtChangeTime;
+- SK_U64 RlmtChangeEstimate;
+- SK_U64 RlmtChangeThreshold;
+- SK_PNMI_RLMT Rlmt[SK_MAX_MACS];
+- SK_U32 RlmtMonitorNumber;
+- SK_PNMI_RLMT_MONITOR RlmtMonitor[SK_PNMI_MONITOR_ENTRIES];
+- SK_U32 TrapNumber;
+- SK_U8 Trap[SK_PNMI_TRAP_QUEUE_LEN];
+- SK_U64 TxSwQueueLen;
+- SK_U64 TxSwQueueMax;
+- SK_U64 TxRetryCts;
+- SK_U64 RxIntrCts;
+- SK_U64 TxIntrCts;
+- SK_U64 RxNoBufCts;
+- SK_U64 TxNoBufCts;
+- SK_U64 TxUsedDescrNo;
+- SK_U64 RxDeliveredCts;
+- SK_U64 RxOctetsDeliveredCts;
+- SK_U64 RxHwErrorsCts;
+- SK_U64 TxHwErrorsCts;
+- SK_U64 InErrorsCts;
+- SK_U64 OutErrorsCts;
+- SK_U64 ErrRecoveryCts;
+- SK_U64 SysUpTime;
+-} SK_PNMI_STRUCT_DATA;
+-
+-#define SK_PNMI_STRUCT_SIZE (sizeof(SK_PNMI_STRUCT_DATA))
+-#define SK_PNMI_MIN_STRUCT_SIZE ((unsigned int)(SK_UPTR)\
+- &(((SK_PNMI_STRUCT_DATA *)0)->VpdFreeBytes))
+- /*
+- * ReturnStatus field
+- * must be located
+- * before VpdFreeBytes
+- */
+-
+-/*
+- * Various definitions
+- */
+-#define SK_PNMI_MAX_PROTOS 3
+-
+-#define SK_PNMI_CNT_NO 66 /* Must have the value of the enum
+- * SK_PNMI_MAX_IDX. Define SK_PNMI_CHECK
+- * for check while init phase 1
+- */
+-
+-/*
+- * Estimate data structure
+- */
+-typedef struct s_PnmiEstimate {
+- unsigned int EstValueIndex;
+- SK_U64 EstValue[7];
+- SK_U64 Estimate;
+- SK_TIMER EstTimer;
+-} SK_PNMI_ESTIMATE;
+-
+-
+-/*
+- * VCT timer data structure
+- */
+-typedef struct s_VctTimer {
+- SK_TIMER VctTimer;
+-} SK_PNMI_VCT_TIMER;
+-
+-
+-/*
+- * PNMI specific adapter context structure
+- */
+-typedef struct s_PnmiPort {
+- SK_U64 StatSyncCts;
+- SK_U64 StatSyncOctetsCts;
+- SK_U64 StatRxLongFrameCts;
+- SK_U64 StatRxFrameTooLongCts;
+- SK_U64 StatRxPMaccErr;
+- SK_U64 TxSwQueueLen;
+- SK_U64 TxSwQueueMax;
+- SK_U64 TxRetryCts;
+- SK_U64 RxIntrCts;
+- SK_U64 TxIntrCts;
+- SK_U64 RxNoBufCts;
+- SK_U64 TxNoBufCts;
+- SK_U64 TxUsedDescrNo;
+- SK_U64 RxDeliveredCts;
+- SK_U64 RxOctetsDeliveredCts;
+- SK_U64 RxHwErrorsCts;
+- SK_U64 TxHwErrorsCts;
+- SK_U64 InErrorsCts;
+- SK_U64 OutErrorsCts;
+- SK_U64 ErrRecoveryCts;
+- SK_U64 RxShortZeroMark;
+- SK_U64 CounterOffset[SK_PNMI_CNT_NO];
+- SK_U32 CounterHigh[SK_PNMI_CNT_NO];
+- SK_BOOL ActiveFlag;
+- SK_U8 Align[3];
+-} SK_PNMI_PORT;
+-
+-
+-typedef struct s_PnmiData {
+- SK_PNMI_PORT Port [SK_MAX_MACS];
+- SK_PNMI_PORT BufPort [SK_MAX_MACS]; /* 2002-09-13 pweber */
+- SK_U64 VirtualCounterOffset[SK_PNMI_CNT_NO];
+- SK_U32 TestResult;
+- char HwVersion[10];
+- SK_U16 Align01;
+-
+- char *pDriverDescription;
+- char *pDriverVersion;
+- char *pDriverReleaseDate;
+- char *pDriverFileName;
+-
+- int MacUpdatedFlag;
+- int RlmtUpdatedFlag;
+- int SirqUpdatedFlag;
+-
+- SK_U64 RlmtChangeCts;
+- SK_U64 RlmtChangeTime;
+- SK_PNMI_ESTIMATE RlmtChangeEstimate;
+- SK_U64 RlmtChangeThreshold;
+-
+- SK_U64 StartUpTime;
+- SK_U32 DeviceType;
+- char PciBusSpeed;
+- char PciBusWidth;
+- char Chipset;
+- char PMD;
+- char Connector;
+- SK_BOOL DualNetActiveFlag;
+- SK_U16 Align02;
+-
+- char TrapBuf[SK_PNMI_TRAP_QUEUE_LEN];
+- unsigned int TrapBufFree;
+- unsigned int TrapQueueBeg;
+- unsigned int TrapQueueEnd;
+- unsigned int TrapBufPad;
+- unsigned int TrapUnique;
+- SK_U8 VctStatus[SK_MAX_MACS];
+- SK_PNMI_VCT VctBackup[SK_MAX_MACS];
+- SK_PNMI_VCT_TIMER VctTimeout[SK_MAX_MACS];
+-#ifdef SK_DIAG_SUPPORT
+- SK_U32 DiagAttached;
+-#endif /* SK_DIAG_SUPPORT */
+-} SK_PNMI;
+-
+-
+-/*
+- * Function prototypes
+- */
+-extern int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int Level);
+-extern int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void* pBuf,
+- unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
+-extern int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
+- unsigned int *pLen, SK_U32 NetIndex);
+-extern int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
+- unsigned int *pLen, SK_U32 NetIndex);
+-extern int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
+- unsigned int *pLen, SK_U32 NetIndex);
+-extern int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event,
+- SK_EVPARA Param);
+-extern int SkPnmiGenIoctl(SK_AC *pAC, SK_IOC IoC, void * pBuf,
+- unsigned int * pLen, SK_U32 NetIndex);
+-
+-#endif
+diff --git a/drivers/net/sk98lin/h/skgesirq.h b/drivers/net/sk98lin/h/skgesirq.h
+deleted file mode 100644
+index 3eec627..0000000
+--- a/drivers/net/sk98lin/h/skgesirq.h
++++ /dev/null
+@@ -1,110 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skgesirq.h
+- * Project: Gigabit Ethernet Adapters, Common Modules
+- * Version: $Revision: 1.30 $
+- * Date: $Date: 2003/07/04 12:34:13 $
+- * Purpose: SK specific Gigabit Ethernet special IRQ functions
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#ifndef _INC_SKGESIRQ_H_
+-#define _INC_SKGESIRQ_H_
+-
+-/* Define return codes of SkGePortCheckUp and CheckShort */
+-#define SK_HW_PS_NONE 0 /* No action needed */
+-#define SK_HW_PS_RESTART 1 /* Restart needed */
+-#define SK_HW_PS_LINK 2 /* Link Up actions needed */
+-
+-/*
+- * Define the Event the special IRQ/INI module can handle
+- */
+-#define SK_HWEV_WATIM 1 /* Timeout for WA Errata #2 XMAC */
+-#define SK_HWEV_PORT_START 2 /* Port Start Event by RLMT */
+-#define SK_HWEV_PORT_STOP 3 /* Port Stop Event by RLMT */
+-#define SK_HWEV_CLEAR_STAT 4 /* Clear Statistics by PNMI */
+-#define SK_HWEV_UPDATE_STAT 5 /* Update Statistics by PNMI */
+-#define SK_HWEV_SET_LMODE 6 /* Set Link Mode by PNMI */
+-#define SK_HWEV_SET_FLOWMODE 7 /* Set Flow Control Mode by PNMI */
+-#define SK_HWEV_SET_ROLE 8 /* Set Master/Slave (Role) by PNMI */
+-#define SK_HWEV_SET_SPEED 9 /* Set Link Speed by PNMI */
+-#define SK_HWEV_HALFDUP_CHK 10 /* Half Duplex Hangup Workaround */
+-
+-#define SK_WA_ACT_TIME (5000000UL) /* 5 sec */
+-#define SK_WA_INA_TIME (100000UL) /* 100 msec */
+-
+-#define SK_HALFDUP_CHK_TIME (10000UL) /* 10 msec */
+-
+-/*
+- * Define the error numbers and messages
+- */
+-#define SKERR_SIRQ_E001 (SK_ERRBASE_SIRQ+0)
+-#define SKERR_SIRQ_E001MSG "Unknown event"
+-#define SKERR_SIRQ_E002 (SKERR_SIRQ_E001+1)
+-#define SKERR_SIRQ_E002MSG "Packet timeout RX1"
+-#define SKERR_SIRQ_E003 (SKERR_SIRQ_E002+1)
+-#define SKERR_SIRQ_E003MSG "Packet timeout RX2"
+-#define SKERR_SIRQ_E004 (SKERR_SIRQ_E003+1)
+-#define SKERR_SIRQ_E004MSG "MAC 1 not correctly initialized"
+-#define SKERR_SIRQ_E005 (SKERR_SIRQ_E004+1)
+-#define SKERR_SIRQ_E005MSG "MAC 2 not correctly initialized"
+-#define SKERR_SIRQ_E006 (SKERR_SIRQ_E005+1)
+-#define SKERR_SIRQ_E006MSG "CHECK failure R1"
+-#define SKERR_SIRQ_E007 (SKERR_SIRQ_E006+1)
+-#define SKERR_SIRQ_E007MSG "CHECK failure R2"
+-#define SKERR_SIRQ_E008 (SKERR_SIRQ_E007+1)
+-#define SKERR_SIRQ_E008MSG "CHECK failure XS1"
+-#define SKERR_SIRQ_E009 (SKERR_SIRQ_E008+1)
+-#define SKERR_SIRQ_E009MSG "CHECK failure XA1"
+-#define SKERR_SIRQ_E010 (SKERR_SIRQ_E009+1)
+-#define SKERR_SIRQ_E010MSG "CHECK failure XS2"
+-#define SKERR_SIRQ_E011 (SKERR_SIRQ_E010+1)
+-#define SKERR_SIRQ_E011MSG "CHECK failure XA2"
+-#define SKERR_SIRQ_E012 (SKERR_SIRQ_E011+1)
+-#define SKERR_SIRQ_E012MSG "unexpected IRQ Master error"
+-#define SKERR_SIRQ_E013 (SKERR_SIRQ_E012+1)
+-#define SKERR_SIRQ_E013MSG "unexpected IRQ Status error"
+-#define SKERR_SIRQ_E014 (SKERR_SIRQ_E013+1)
+-#define SKERR_SIRQ_E014MSG "Parity error on RAM (read)"
+-#define SKERR_SIRQ_E015 (SKERR_SIRQ_E014+1)
+-#define SKERR_SIRQ_E015MSG "Parity error on RAM (write)"
+-#define SKERR_SIRQ_E016 (SKERR_SIRQ_E015+1)
+-#define SKERR_SIRQ_E016MSG "Parity error MAC 1"
+-#define SKERR_SIRQ_E017 (SKERR_SIRQ_E016+1)
+-#define SKERR_SIRQ_E017MSG "Parity error MAC 2"
+-#define SKERR_SIRQ_E018 (SKERR_SIRQ_E017+1)
+-#define SKERR_SIRQ_E018MSG "Parity error RX 1"
+-#define SKERR_SIRQ_E019 (SKERR_SIRQ_E018+1)
+-#define SKERR_SIRQ_E019MSG "Parity error RX 2"
+-#define SKERR_SIRQ_E020 (SKERR_SIRQ_E019+1)
+-#define SKERR_SIRQ_E020MSG "MAC transmit FIFO underrun"
+-#define SKERR_SIRQ_E021 (SKERR_SIRQ_E020+1)
+-#define SKERR_SIRQ_E021MSG "Spurious TWSI interrupt"
+-#define SKERR_SIRQ_E022 (SKERR_SIRQ_E021+1)
+-#define SKERR_SIRQ_E022MSG "Cable pair swap error"
+-#define SKERR_SIRQ_E023 (SKERR_SIRQ_E022+1)
+-#define SKERR_SIRQ_E023MSG "Auto-negotiation error"
+-#define SKERR_SIRQ_E024 (SKERR_SIRQ_E023+1)
+-#define SKERR_SIRQ_E024MSG "FIFO overflow error"
+-#define SKERR_SIRQ_E025 (SKERR_SIRQ_E024+1)
+-#define SKERR_SIRQ_E025MSG "2 Pair Downshift detected"
+-
+-extern void SkGeSirqIsr(SK_AC *pAC, SK_IOC IoC, SK_U32 Istatus);
+-extern int SkGeSirqEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para);
+-extern void SkHWLinkDown(SK_AC *pAC, SK_IOC IoC, int Port);
+-
+-#endif /* _INC_SKGESIRQ_H_ */
+diff --git a/drivers/net/sk98lin/h/ski2c.h b/drivers/net/sk98lin/h/ski2c.h
+deleted file mode 100644
+index 6a63f4a..0000000
+--- a/drivers/net/sk98lin/h/ski2c.h
++++ /dev/null
+@@ -1,174 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: ski2c.h
+- * Project: Gigabit Ethernet Adapters, TWSI-Module
+- * Version: $Revision: 1.35 $
+- * Date: $Date: 2003/10/20 09:06:30 $
+- * Purpose: Defines to access Voltage and Temperature Sensor
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- * SKI2C.H contains all I2C specific defines
+- */
+-
+-#ifndef _SKI2C_H_
+-#define _SKI2C_H_
+-
+-typedef struct s_Sensor SK_SENSOR;
+-
+-#include "h/skgei2c.h"
+-
+-/*
+- * Define the I2C events.
+- */
+-#define SK_I2CEV_IRQ 1 /* IRQ happened Event */
+-#define SK_I2CEV_TIM 2 /* Timeout event */
+-#define SK_I2CEV_CLEAR 3 /* Clear MIB Values */
+-
+-/*
+- * Define READ and WRITE Constants.
+- */
+-#define I2C_READ 0
+-#define I2C_WRITE 1
+-#define I2C_BURST 1
+-#define I2C_SINGLE 0
+-
+-#define SKERR_I2C_E001 (SK_ERRBASE_I2C+0)
+-#define SKERR_I2C_E001MSG "Sensor index unknown"
+-#define SKERR_I2C_E002 (SKERR_I2C_E001+1)
+-#define SKERR_I2C_E002MSG "TWSI: transfer does not complete"
+-#define SKERR_I2C_E003 (SKERR_I2C_E002+1)
+-#define SKERR_I2C_E003MSG "LM80: NAK on device send"
+-#define SKERR_I2C_E004 (SKERR_I2C_E003+1)
+-#define SKERR_I2C_E004MSG "LM80: NAK on register send"
+-#define SKERR_I2C_E005 (SKERR_I2C_E004+1)
+-#define SKERR_I2C_E005MSG "LM80: NAK on device (2) send"
+-#define SKERR_I2C_E006 (SKERR_I2C_E005+1)
+-#define SKERR_I2C_E006MSG "Unknown event"
+-#define SKERR_I2C_E007 (SKERR_I2C_E006+1)
+-#define SKERR_I2C_E007MSG "LM80 read out of state"
+-#define SKERR_I2C_E008 (SKERR_I2C_E007+1)
+-#define SKERR_I2C_E008MSG "Unexpected sensor read completed"
+-#define SKERR_I2C_E009 (SKERR_I2C_E008+1)
+-#define SKERR_I2C_E009MSG "WARNING: temperature sensor out of range"
+-#define SKERR_I2C_E010 (SKERR_I2C_E009+1)
+-#define SKERR_I2C_E010MSG "WARNING: voltage sensor out of range"
+-#define SKERR_I2C_E011 (SKERR_I2C_E010+1)
+-#define SKERR_I2C_E011MSG "ERROR: temperature sensor out of range"
+-#define SKERR_I2C_E012 (SKERR_I2C_E011+1)
+-#define SKERR_I2C_E012MSG "ERROR: voltage sensor out of range"
+-#define SKERR_I2C_E013 (SKERR_I2C_E012+1)
+-#define SKERR_I2C_E013MSG "ERROR: couldn't init sensor"
+-#define SKERR_I2C_E014 (SKERR_I2C_E013+1)
+-#define SKERR_I2C_E014MSG "WARNING: fan sensor out of range"
+-#define SKERR_I2C_E015 (SKERR_I2C_E014+1)
+-#define SKERR_I2C_E015MSG "ERROR: fan sensor out of range"
+-#define SKERR_I2C_E016 (SKERR_I2C_E015+1)
+-#define SKERR_I2C_E016MSG "TWSI: active transfer does not complete"
+-
+-/*
+- * Define Timeout values
+- */
+-#define SK_I2C_TIM_LONG 2000000L /* 2 seconds */
+-#define SK_I2C_TIM_SHORT 100000L /* 100 milliseconds */
+-#define SK_I2C_TIM_WATCH 1000000L /* 1 second */
+-
+-/*
+- * Define trap and error log hold times
+- */
+-#ifndef SK_SEN_ERR_TR_HOLD
+-#define SK_SEN_ERR_TR_HOLD (4*SK_TICKS_PER_SEC)
+-#endif
+-#ifndef SK_SEN_ERR_LOG_HOLD
+-#define SK_SEN_ERR_LOG_HOLD (60*SK_TICKS_PER_SEC)
+-#endif
+-#ifndef SK_SEN_WARN_TR_HOLD
+-#define SK_SEN_WARN_TR_HOLD (15*SK_TICKS_PER_SEC)
+-#endif
+-#ifndef SK_SEN_WARN_LOG_HOLD
+-#define SK_SEN_WARN_LOG_HOLD (15*60*SK_TICKS_PER_SEC)
+-#endif
+-
+-/*
+- * Defines for SenType
+- */
+-#define SK_SEN_UNKNOWN 0
+-#define SK_SEN_TEMP 1
+-#define SK_SEN_VOLT 2
+-#define SK_SEN_FAN 3
+-
+-/*
+- * Define for the SenErrorFlag
+- */
+-#define SK_SEN_ERR_NOT_PRESENT 0 /* Error Flag: Sensor not present */
+-#define SK_SEN_ERR_OK 1 /* Error Flag: O.K. */
+-#define SK_SEN_ERR_WARN 2 /* Error Flag: Warning */
+-#define SK_SEN_ERR_ERR 3 /* Error Flag: Error */
+-#define SK_SEN_ERR_FAULTY 4 /* Error Flag: Faulty */
+-
+-/*
+- * Define the Sensor struct
+- */
+-struct s_Sensor {
+- char *SenDesc; /* Description */
+- int SenType; /* Voltage or Temperature */
+- SK_I32 SenValue; /* Current value of the sensor */
+- SK_I32 SenThreErrHigh; /* High error Threshhold of this sensor */
+- SK_I32 SenThreWarnHigh; /* High warning Threshhold of this sensor */
+- SK_I32 SenThreErrLow; /* Lower error Threshold of the sensor */
+- SK_I32 SenThreWarnLow; /* Lower warning Threshold of the sensor */
+- int SenErrFlag; /* Sensor indicated an error */
+- SK_BOOL SenInit; /* Is sensor initialized ? */
+- SK_U64 SenErrCts; /* Error trap counter */
+- SK_U64 SenWarnCts; /* Warning trap counter */
+- SK_U64 SenBegErrTS; /* Begin error timestamp */
+- SK_U64 SenBegWarnTS; /* Begin warning timestamp */
+- SK_U64 SenLastErrTrapTS; /* Last error trap timestamp */
+- SK_U64 SenLastErrLogTS; /* Last error log timestamp */
+- SK_U64 SenLastWarnTrapTS; /* Last warning trap timestamp */
+- SK_U64 SenLastWarnLogTS; /* Last warning log timestamp */
+- int SenState; /* Sensor State (see HW specific include) */
+- int (*SenRead)(SK_AC *pAC, SK_IOC IoC, struct s_Sensor *pSen);
+- /* Sensors read function */
+- SK_U16 SenReg; /* Register Address for this sensor */
+- SK_U8 SenDev; /* Device Selection for this sensor */
+-};
+-
+-typedef struct s_I2c {
+- SK_SENSOR SenTable[SK_MAX_SENSORS]; /* Sensor Table */
+- int CurrSens; /* Which sensor is currently queried */
+- int MaxSens; /* Max. number of sensors */
+- int TimerMode; /* Use the timer also to watch the state machine */
+- int InitLevel; /* Initialized Level */
+-#ifndef SK_DIAG
+- int DummyReads; /* Number of non-checked dummy reads */
+- SK_TIMER SenTimer; /* Sensors timer */
+-#endif /* !SK_DIAG */
+-} SK_I2C;
+-
+-extern int SkI2cInit(SK_AC *pAC, SK_IOC IoC, int Level);
+-#ifdef SK_DIAG
+-extern SK_U32 SkI2cRead(SK_AC *pAC, SK_IOC IoC, int Dev, int Size, int Reg,
+- int Burst);
+-#else /* !SK_DIAG */
+-extern int SkI2cEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para);
+-extern void SkI2cWaitIrq(SK_AC *pAC, SK_IOC IoC);
+-extern void SkI2cIsr(SK_AC *pAC, SK_IOC IoC);
+-#endif /* !SK_DIAG */
+-#endif /* n_SKI2C_H */
+-
+diff --git a/drivers/net/sk98lin/h/skqueue.h b/drivers/net/sk98lin/h/skqueue.h
+deleted file mode 100644
+index 2ec40d4..0000000
+--- a/drivers/net/sk98lin/h/skqueue.h
++++ /dev/null
+@@ -1,94 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skqueue.h
+- * Project: Gigabit Ethernet Adapters, Event Scheduler Module
+- * Version: $Revision: 1.16 $
+- * Date: $Date: 2003/09/16 12:50:32 $
+- * Purpose: Defines for the Event queue
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- * SKQUEUE.H contains all defines and types for the event queue
+- */
+-
+-#ifndef _SKQUEUE_H_
+-#define _SKQUEUE_H_
+-
+-
+-/*
+- * define the event classes to be served
+- */
+-#define SKGE_DRV 1 /* Driver Event Class */
+-#define SKGE_RLMT 2 /* RLMT Event Class */
+-#define SKGE_I2C 3 /* I2C Event Class */
+-#define SKGE_PNMI 4 /* PNMI Event Class */
+-#define SKGE_CSUM 5 /* Checksum Event Class */
+-#define SKGE_HWAC 6 /* Hardware Access Event Class */
+-
+-#define SKGE_SWT 9 /* Software Timer Event Class */
+-#define SKGE_LACP 10 /* LACP Aggregation Event Class */
+-#define SKGE_RSF 11 /* RSF Aggregation Event Class */
+-#define SKGE_MARKER 12 /* MARKER Aggregation Event Class */
+-#define SKGE_FD 13 /* FD Distributor Event Class */
+-
+-/*
+- * define event queue as circular buffer
+- */
+-#define SK_MAX_EVENT 64
+-
+-/*
+- * Parameter union for the Para stuff
+- */
+-typedef union u_EvPara {
+- void *pParaPtr; /* Parameter Pointer */
+- SK_U64 Para64; /* Parameter 64bit version */
+- SK_U32 Para32[2]; /* Parameter Array of 32bit parameters */
+-} SK_EVPARA;
+-
+-/*
+- * Event Queue
+- * skqueue.c
+- * events are class/value pairs
+- * class is addressee, e.g. RLMT, PNMI etc.
+- * value is command, e.g. line state change, ring op change etc.
+- */
+-typedef struct s_EventElem {
+- SK_U32 Class; /* Event class */
+- SK_U32 Event; /* Event value */
+- SK_EVPARA Para; /* Event parameter */
+-} SK_EVENTELEM;
+-
+-typedef struct s_Queue {
+- SK_EVENTELEM EvQueue[SK_MAX_EVENT];
+- SK_EVENTELEM *EvPut;
+- SK_EVENTELEM *EvGet;
+-} SK_QUEUE;
+-
+-extern void SkEventInit(SK_AC *pAC, SK_IOC Ioc, int Level);
+-extern void SkEventQueue(SK_AC *pAC, SK_U32 Class, SK_U32 Event,
+- SK_EVPARA Para);
+-extern int SkEventDispatcher(SK_AC *pAC, SK_IOC Ioc);
+-
+-
+-/* Define Error Numbers and messages */
+-#define SKERR_Q_E001 (SK_ERRBASE_QUEUE+0)
+-#define SKERR_Q_E001MSG "Event queue overflow"
+-#define SKERR_Q_E002 (SKERR_Q_E001+1)
+-#define SKERR_Q_E002MSG "Undefined event class"
+-#endif /* _SKQUEUE_H_ */
+-
+diff --git a/drivers/net/sk98lin/h/skrlmt.h b/drivers/net/sk98lin/h/skrlmt.h
+deleted file mode 100644
+index ca75dfd..0000000
+--- a/drivers/net/sk98lin/h/skrlmt.h
++++ /dev/null
+@@ -1,438 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skrlmt.h
+- * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.37 $
+- * Date: $Date: 2003/04/15 09:43:43 $
+- * Purpose: Header file for Redundant Link ManagemenT.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * Description:
+- *
+- * This is the header file for Redundant Link ManagemenT.
+- *
+- * Include File Hierarchy:
+- *
+- * "skdrv1st.h"
+- * ...
+- * "sktypes.h"
+- * "skqueue.h"
+- * "skaddr.h"
+- * "skrlmt.h"
+- * ...
+- * "skdrv2nd.h"
+- *
+- ******************************************************************************/
+-
+-#ifndef __INC_SKRLMT_H
+-#define __INC_SKRLMT_H
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif /* cplusplus */
+-
+-/* defines ********************************************************************/
+-
+-#define SK_RLMT_NET_DOWN_TEMP 1 /* NET_DOWN due to last port down. */
+-#define SK_RLMT_NET_DOWN_FINAL 2 /* NET_DOWN due to RLMT_STOP. */
+-
+-/* ----- Default queue sizes - must be multiples of 8 KB ----- */
+-
+-/* Less than 8 KB free in RX queue => pause frames. */
+-#define SK_RLMT_STANDBY_QRXSIZE 128 /* Size of rx standby queue in KB. */
+-#define SK_RLMT_STANDBY_QXASIZE 32 /* Size of async standby queue in KB. */
+-#define SK_RLMT_STANDBY_QXSSIZE 0 /* Size of sync standby queue in KB. */
+-
+-#define SK_RLMT_MAX_TX_BUF_SIZE 60 /* Maximum RLMT transmit size. */
+-
+-/* ----- PORT states ----- */
+-
+-#define SK_RLMT_PS_INIT 0 /* Port state: Init. */
+-#define SK_RLMT_PS_LINK_DOWN 1 /* Port state: Link down. */
+-#define SK_RLMT_PS_DOWN 2 /* Port state: Port down. */
+-#define SK_RLMT_PS_GOING_UP 3 /* Port state: Going up. */
+-#define SK_RLMT_PS_UP 4 /* Port state: Up. */
+-
+-/* ----- RLMT states ----- */
+-
+-#define SK_RLMT_RS_INIT 0 /* RLMT state: Init. */
+-#define SK_RLMT_RS_NET_DOWN 1 /* RLMT state: Net down. */
+-#define SK_RLMT_RS_NET_UP 2 /* RLMT state: Net up. */
+-
+-/* ----- PORT events ----- */
+-
+-#define SK_RLMT_LINK_UP 1001 /* Link came up. */
+-#define SK_RLMT_LINK_DOWN 1002 /* Link went down. */
+-#define SK_RLMT_PORT_ADDR 1003 /* Port address changed. */
+-
+-/* ----- RLMT events ----- */
+-
+-#define SK_RLMT_START 2001 /* Start RLMT. */
+-#define SK_RLMT_STOP 2002 /* Stop RLMT. */
+-#define SK_RLMT_PACKET_RECEIVED 2003 /* Packet was received for RLMT. */
+-#define SK_RLMT_STATS_CLEAR 2004 /* Clear statistics. */
+-#define SK_RLMT_STATS_UPDATE 2005 /* Update statistics. */
+-#define SK_RLMT_PREFPORT_CHANGE 2006 /* Change preferred port. */
+-#define SK_RLMT_MODE_CHANGE 2007 /* New RlmtMode. */
+-#define SK_RLMT_SET_NETS 2008 /* Number of Nets (1 or 2). */
+-
+-/* ----- RLMT mode bits ----- */
+-
+-/*
+- * CAUTION: These defines are private to RLMT.
+- * Please use the RLMT mode defines below.
+- */
+-
+-#define SK_RLMT_CHECK_LINK 1 /* Check Link. */
+-#define SK_RLMT_CHECK_LOC_LINK 2 /* Check other link on same adapter. */
+-#define SK_RLMT_CHECK_SEG 4 /* Check segmentation. */
+-
+-#ifndef RLMT_CHECK_REMOTE
+-#define SK_RLMT_CHECK_OTHERS SK_RLMT_CHECK_LOC_LINK
+-#else /* RLMT_CHECK_REMOTE */
+-#define SK_RLMT_CHECK_REM_LINK 8 /* Check link(s) on other adapter(s). */
+-#define SK_RLMT_MAX_REMOTE_PORTS_CHECKED 3
+-#define SK_RLMT_CHECK_OTHERS \
+- (SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_REM_LINK)
+-#endif /* RLMT_CHECK_REMOTE */
+-
+-#ifndef SK_RLMT_ENABLE_TRANSPARENT
+-#define SK_RLMT_TRANSPARENT 0 /* RLMT transparent - inactive. */
+-#else /* SK_RLMT_ENABLE_TRANSPARENT */
+-#define SK_RLMT_TRANSPARENT 128 /* RLMT transparent. */
+-#endif /* SK_RLMT_ENABLE_TRANSPARENT */
+-
+-/* ----- RLMT modes ----- */
+-
+-/* Check Link State. */
+-#define SK_RLMT_MODE_CLS (SK_RLMT_CHECK_LINK)
+-
+-/* Check Local Ports: check other links on the same adapter. */
+-#define SK_RLMT_MODE_CLP (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK)
+-
+-/* Check Local Ports and Segmentation Status. */
+-#define SK_RLMT_MODE_CLPSS \
+- (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_SEG)
+-
+-#ifdef RLMT_CHECK_REMOTE
+-/* Check Local and Remote Ports: check links (local or remote). */
+- Name of define TBD!
+-#define SK_RLMT_MODE_CRP \
+- (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_REM_LINK)
+-
+-/* Check Local and Remote Ports and Segmentation Status. */
+- Name of define TBD!
+-#define SK_RLMT_MODE_CRPSS \
+- (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | \
+- SK_RLMT_CHECK_REM_LINK | SK_RLMT_CHECK_SEG)
+-#endif /* RLMT_CHECK_REMOTE */
+-
+-/* ----- RLMT lookahead result bits ----- */
+-
+-#define SK_RLMT_RX_RLMT 1 /* Give packet to RLMT. */
+-#define SK_RLMT_RX_PROTOCOL 2 /* Give packet to protocol. */
+-
+-/* Macros */
+-
+-#if 0
+-SK_AC *pAC /* adapter context */
+-SK_U32 PortNum /* receiving port */
+-unsigned PktLen /* received packet's length */
+-SK_BOOL IsBc /* Flag: packet is broadcast */
+-unsigned *pOffset /* offs. of bytes to present to SK_RLMT_LOOKAHEAD */
+-unsigned *pNumBytes /* #Bytes to present to SK_RLMT_LOOKAHEAD */
+-#endif /* 0 */
+-
+-#define SK_RLMT_PRE_LOOKAHEAD(pAC,PortNum,PktLen,IsBc,pOffset,pNumBytes) { \
+- SK_AC *_pAC; \
+- SK_U32 _PortNum; \
+- _pAC = (pAC); \
+- _PortNum = (SK_U32)(PortNum); \
+- /* _pAC->Rlmt.Port[_PortNum].PacketsRx++; */ \
+- _pAC->Rlmt.Port[_PortNum].PacketsPerTimeSlot++; \
+- if (_pAC->Rlmt.RlmtOff) { \
+- *(pNumBytes) = 0; \
+- } \
+- else {\
+- if ((_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_TRANSPARENT) != 0) { \
+- *(pNumBytes) = 0; \
+- } \
+- else if (IsBc) { \
+- if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode != SK_RLMT_MODE_CLS) { \
+- *(pNumBytes) = 6; \
+- *(pOffset) = 6; \
+- } \
+- else { \
+- *(pNumBytes) = 0; \
+- } \
+- } \
+- else { \
+- if ((PktLen) > SK_RLMT_MAX_TX_BUF_SIZE) { \
+- /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
+- *(pNumBytes) = 0; \
+- } \
+- else { \
+- *(pNumBytes) = 6; \
+- *(pOffset) = 0; \
+- } \
+- } \
+- } \
+-}
+-
+-#if 0
+-SK_AC *pAC /* adapter context */
+-SK_U32 PortNum /* receiving port */
+-SK_U8 *pLaPacket, /* received packet's data (points to pOffset) */
+-SK_BOOL IsBc /* Flag: packet is broadcast */
+-SK_BOOL IsMc /* Flag: packet is multicast */
+-unsigned *pForRlmt /* Result: bits SK_RLMT_RX_RLMT, SK_RLMT_RX_PROTOCOL */
+-SK_RLMT_LOOKAHEAD() expects *pNumBytes from
+-packet offset *pOffset (s.a.) at *pLaPacket.
+-
+-If you use SK_RLMT_LOOKAHEAD in a path where you already know if the packet is
+-BC, MC, or UC, you should use constants for IsBc and IsMc, so that your compiler
+-can trash unneeded parts of the if construction.
+-#endif /* 0 */
+-
+-#define SK_RLMT_LOOKAHEAD(pAC,PortNum,pLaPacket,IsBc,IsMc,pForRlmt) { \
+- SK_AC *_pAC; \
+- SK_U32 _PortNum; \
+- SK_U8 *_pLaPacket; \
+- _pAC = (pAC); \
+- _PortNum = (SK_U32)(PortNum); \
+- _pLaPacket = (SK_U8 *)(pLaPacket); \
+- if (IsBc) {\
+- if (!SK_ADDR_EQUAL(_pLaPacket, _pAC->Addr.Net[_pAC->Rlmt.Port[ \
+- _PortNum].Net->NetNumber].CurrentMacAddress.a)) { \
+- _pAC->Rlmt.Port[_PortNum].BcTimeStamp = SkOsGetTime(_pAC); \
+- _pAC->Rlmt.CheckSwitch = SK_TRUE; \
+- } \
+- /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
+- *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
+- } \
+- else if (IsMc) { \
+- if (SK_ADDR_EQUAL(_pLaPacket, BridgeMcAddr.a)) { \
+- _pAC->Rlmt.Port[_PortNum].BpduPacketsPerTimeSlot++; \
+- if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_CHECK_SEG) { \
+- *(pForRlmt) = SK_RLMT_RX_RLMT | SK_RLMT_RX_PROTOCOL; \
+- } \
+- else { \
+- *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
+- } \
+- } \
+- else if (SK_ADDR_EQUAL(_pLaPacket, SkRlmtMcAddr.a)) { \
+- *(pForRlmt) = SK_RLMT_RX_RLMT; \
+- } \
+- else { \
+- /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
+- *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
+- } \
+- } \
+- else { \
+- if (SK_ADDR_EQUAL( \
+- _pLaPacket, \
+- _pAC->Addr.Port[_PortNum].CurrentMacAddress.a)) { \
+- *(pForRlmt) = SK_RLMT_RX_RLMT; \
+- } \
+- else { \
+- /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
+- *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
+- } \
+- } \
+-}
+-
+-#ifdef SK_RLMT_FAST_LOOKAHEAD
+-Error: SK_RLMT_FAST_LOOKAHEAD no longer used. Use new macros for lookahead.
+-#endif /* SK_RLMT_FAST_LOOKAHEAD */
+-#ifdef SK_RLMT_SLOW_LOOKAHEAD
+-Error: SK_RLMT_SLOW_LOOKAHEAD no longer used. Use new macros for lookahead.
+-#endif /* SK_RLMT_SLOW_LOOKAHEAD */
+-
+-/* typedefs *******************************************************************/
+-
+-#ifdef SK_RLMT_MBUF_PRIVATE
+-typedef struct s_RlmtMbuf {
+- some content
+-} SK_RLMT_MBUF;
+-#endif /* SK_RLMT_MBUF_PRIVATE */
+-
+-
+-#ifdef SK_LA_INFO
+-typedef struct s_Rlmt_PacketInfo {
+- unsigned PacketLength; /* Length of packet. */
+- unsigned PacketType; /* Directed/Multicast/Broadcast. */
+-} SK_RLMT_PINFO;
+-#endif /* SK_LA_INFO */
+-
+-
+-typedef struct s_RootId {
+- SK_U8 Id[8]; /* Root Bridge Id. */
+-} SK_RLMT_ROOT_ID;
+-
+-
+-typedef struct s_port {
+- SK_MAC_ADDR CheckAddr;
+- SK_BOOL SuspectTx;
+-} SK_PORT_CHECK;
+-
+-
+-typedef struct s_RlmtNet SK_RLMT_NET;
+-
+-
+-typedef struct s_RlmtPort {
+-
+-/* ----- Public part (read-only) ----- */
+-
+- SK_U8 PortState; /* Current state of this port. */
+-
+- /* For PNMI */
+- SK_BOOL LinkDown;
+- SK_BOOL PortDown;
+- SK_U8 Align01;
+-
+- SK_U32 PortNumber; /* Number of port on adapter. */
+- SK_RLMT_NET * Net; /* Net port belongs to. */
+-
+- SK_U64 TxHelloCts;
+- SK_U64 RxHelloCts;
+- SK_U64 TxSpHelloReqCts;
+- SK_U64 RxSpHelloCts;
+-
+-/* ----- Private part ----- */
+-
+-/* SK_U64 PacketsRx; */ /* Total packets received. */
+- SK_U32 PacketsPerTimeSlot; /* Packets rxed between TOs. */
+-/* SK_U32 DataPacketsPerTimeSlot; */ /* Data packets ... */
+- SK_U32 BpduPacketsPerTimeSlot; /* BPDU packets rxed in TS. */
+- SK_U64 BcTimeStamp; /* Time of last BC receive. */
+- SK_U64 GuTimeStamp; /* Time of entering GOING_UP. */
+-
+- SK_TIMER UpTimer; /* Timer struct Link/Port up. */
+- SK_TIMER DownRxTimer; /* Timer struct down rx. */
+- SK_TIMER DownTxTimer; /* Timer struct down tx. */
+-
+- SK_U32 CheckingState; /* Checking State. */
+-
+- SK_ADDR_PORT * AddrPort;
+-
+- SK_U8 Random[4]; /* Random value. */
+- unsigned PortsChecked; /* #ports checked. */
+- unsigned PortsSuspect; /* #ports checked that are s. */
+- SK_PORT_CHECK PortCheck[1];
+-/* SK_PORT_CHECK PortCheck[SK_MAX_MACS - 1]; */
+-
+- SK_BOOL PortStarted; /* Port is started. */
+- SK_BOOL PortNoRx; /* NoRx for >= 1 time slot. */
+- SK_BOOL RootIdSet;
+- SK_RLMT_ROOT_ID Root; /* Root Bridge Id. */
+-} SK_RLMT_PORT;
+-
+-
+-struct s_RlmtNet {
+-
+-/* ----- Public part (read-only) ----- */
+-
+- SK_U32 NetNumber; /* Number of net. */
+-
+- SK_RLMT_PORT * Port[SK_MAX_MACS]; /* Ports that belong to this net. */
+- SK_U32 NumPorts; /* Number of ports. */
+- SK_U32 PrefPort; /* Preferred port. */
+-
+- /* For PNMI */
+-
+- SK_U32 ChgBcPrio; /* Change Priority of last broadcast received */
+- SK_U32 RlmtMode; /* Check ... */
+- SK_U32 ActivePort; /* Active port. */
+- SK_U32 Preference; /* 0xFFFFFFFF: Automatic. */
+-
+- SK_U8 RlmtState; /* Current RLMT state. */
+-
+-/* ----- Private part ----- */
+- SK_BOOL RootIdSet;
+- SK_U16 Align01;
+-
+- int LinksUp; /* #Links up. */
+- int PortsUp; /* #Ports up. */
+- SK_U32 TimeoutValue; /* RLMT timeout value. */
+-
+- SK_U32 CheckingState; /* Checking State. */
+- SK_RLMT_ROOT_ID Root; /* Root Bridge Id. */
+-
+- SK_TIMER LocTimer; /* Timer struct. */
+- SK_TIMER SegTimer; /* Timer struct. */
+-};
+-
+-
+-typedef struct s_Rlmt {
+-
+-/* ----- Public part (read-only) ----- */
+-
+- SK_U32 NumNets; /* Number of nets. */
+- SK_U32 NetsStarted; /* Number of nets started. */
+- SK_RLMT_NET Net[SK_MAX_NETS]; /* Array of available nets. */
+- SK_RLMT_PORT Port[SK_MAX_MACS]; /* Array of available ports. */
+-
+-/* ----- Private part ----- */
+- SK_BOOL CheckSwitch;
+- SK_BOOL RlmtOff; /* set to zero if the Mac addresses
+- are equal or the second one
+- is zero */
+- SK_U16 Align01;
+-
+-} SK_RLMT;
+-
+-
+-extern SK_MAC_ADDR BridgeMcAddr;
+-extern SK_MAC_ADDR SkRlmtMcAddr;
+-
+-/* function prototypes ********************************************************/
+-
+-
+-#ifndef SK_KR_PROTO
+-
+-/* Functions provided by SkRlmt */
+-
+-/* ANSI/C++ compliant function prototypes */
+-
+-extern void SkRlmtInit(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int Level);
+-
+-extern int SkRlmtEvent(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- SK_U32 Event,
+- SK_EVPARA Para);
+-
+-#else /* defined(SK_KR_PROTO) */
+-
+-/* Non-ANSI/C++ compliant function prototypes */
+-
+-#error KR-style function prototypes are not yet provided.
+-
+-#endif /* defined(SK_KR_PROTO)) */
+-
+-
+-#ifdef __cplusplus
+-}
+-#endif /* __cplusplus */
+-
+-#endif /* __INC_SKRLMT_H */
+diff --git a/drivers/net/sk98lin/h/sktimer.h b/drivers/net/sk98lin/h/sktimer.h
+deleted file mode 100644
+index 04e6d7c..0000000
+--- a/drivers/net/sk98lin/h/sktimer.h
++++ /dev/null
+@@ -1,63 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: sktimer.h
+- * Project: Gigabit Ethernet Adapters, Event Scheduler Module
+- * Version: $Revision: 1.11 $
+- * Date: $Date: 2003/09/16 12:58:18 $
+- * Purpose: Defines for the timer functions
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- * SKTIMER.H contains all defines and types for the timer functions
+- */
+-
+-#ifndef _SKTIMER_H_
+-#define _SKTIMER_H_
+-
+-#include "h/skqueue.h"
+-
+-/*
+- * SK timer
+- * - needed wherever a timer is used. Put this in your data structure
+- * wherever you want.
+- */
+-typedef struct s_Timer SK_TIMER;
+-
+-struct s_Timer {
+- SK_TIMER *TmNext; /* linked list */
+- SK_U32 TmClass; /* Timer Event class */
+- SK_U32 TmEvent; /* Timer Event value */
+- SK_EVPARA TmPara; /* Timer Event parameter */
+- SK_U32 TmDelta; /* delta time */
+- int TmActive; /* flag: active/inactive */
+-};
+-
+-/*
+- * Timer control struct.
+- * - use in Adapters context name pAC->Tim
+- */
+-typedef struct s_TimCtrl {
+- SK_TIMER *StQueue; /* Head of Timer queue */
+-} SK_TIMCTRL;
+-
+-extern void SkTimerInit(SK_AC *pAC, SK_IOC Ioc, int Level);
+-extern void SkTimerStop(SK_AC *pAC, SK_IOC Ioc, SK_TIMER *pTimer);
+-extern void SkTimerStart(SK_AC *pAC, SK_IOC Ioc, SK_TIMER *pTimer,
+- SK_U32 Time, SK_U32 Class, SK_U32 Event, SK_EVPARA Para);
+-extern void SkTimerDone(SK_AC *pAC, SK_IOC Ioc);
+-#endif /* _SKTIMER_H_ */
+diff --git a/drivers/net/sk98lin/h/sktypes.h b/drivers/net/sk98lin/h/sktypes.h
+deleted file mode 100644
+index 40edc96..0000000
+--- a/drivers/net/sk98lin/h/sktypes.h
++++ /dev/null
+@@ -1,69 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: sktypes.h
+- * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.2 $
+- * Date: $Date: 2003/10/07 08:16:51 $
+- * Purpose: Define data types for Linux
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * Description:
+- *
+- * In this file, all data types that are needed by the common modules
+- * are mapped to Linux data types.
+- *
+- *
+- * Include File Hierarchy:
+- *
+- *
+- ******************************************************************************/
+-
+-#ifndef __INC_SKTYPES_H
+-#define __INC_SKTYPES_H
+-
+-
+-/* defines *******************************************************************/
+-
+-/*
+- * Data types with a specific size. 'I' = signed, 'U' = unsigned.
+- */
+-#define SK_I8 s8
+-#define SK_U8 u8
+-#define SK_I16 s16
+-#define SK_U16 u16
+-#define SK_I32 s32
+-#define SK_U32 u32
+-#define SK_I64 s64
+-#define SK_U64 u64
+-
+-#define SK_UPTR ulong /* casting pointer <-> integral */
+-
+-/*
+-* Boolean type.
+-*/
+-#define SK_BOOL SK_U8
+-#define SK_FALSE 0
+-#define SK_TRUE (!SK_FALSE)
+-
+-/* typedefs *******************************************************************/
+-
+-/* function prototypes ********************************************************/
+-
+-#endif /* __INC_SKTYPES_H */
+diff --git a/drivers/net/sk98lin/h/skversion.h b/drivers/net/sk98lin/h/skversion.h
+deleted file mode 100644
+index a1a7294..0000000
+--- a/drivers/net/sk98lin/h/skversion.h
++++ /dev/null
+@@ -1,38 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: version.h
+- * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.5 $
+- * Date: $Date: 2003/10/07 08:16:51 $
+- * Purpose: SK specific Error log support
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#ifdef lint
+-static const char SysKonnectFileId[] = "@(#) (C) SysKonnect GmbH.";
+-static const char SysKonnectBuildNumber[] =
+- "@(#)SK-BUILD: 6.23 PL: 01";
+-#endif /* !defined(lint) */
+-
+-#define BOOT_STRING "sk98lin: Network Device Driver v6.23\n" \
+- "(C)Copyright 1999-2004 Marvell(R)."
+-
+-#define VER_STRING "6.23"
+-#define DRIVER_FILE_NAME "sk98lin"
+-#define DRIVER_REL_DATE "Feb-13-2004"
+-
+-
+diff --git a/drivers/net/sk98lin/h/skvpd.h b/drivers/net/sk98lin/h/skvpd.h
+deleted file mode 100644
+index fdd9e48..0000000
+--- a/drivers/net/sk98lin/h/skvpd.h
++++ /dev/null
+@@ -1,248 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skvpd.h
+- * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.15 $
+- * Date: $Date: 2003/01/13 10:39:38 $
+- * Purpose: Defines and Macros for VPD handling
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2003 SysKonnect GmbH.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- * skvpd.h contains Diagnostic specific defines for VPD handling
+- */
+-
+-#ifndef __INC_SKVPD_H_
+-#define __INC_SKVPD_H_
+-
+-/*
+- * Define Resource Type Identifiers and VPD keywords
+- */
+-#define RES_ID 0x82 /* Resource Type ID String (Product Name) */
+-#define RES_VPD_R 0x90 /* start of VPD read only area */
+-#define RES_VPD_W 0x91 /* start of VPD read/write area */
+-#define RES_END 0x78 /* Resource Type End Tag */
+-
+-#ifndef VPD_NAME
+-#define VPD_NAME "Name" /* Product Name, VPD name of RES_ID */
+-#endif /* VPD_NAME */
+-#define VPD_PN "PN" /* Adapter Part Number */
+-#define VPD_EC "EC" /* Adapter Engineering Level */
+-#define VPD_MN "MN" /* Manufacture ID */
+-#define VPD_SN "SN" /* Serial Number */
+-#define VPD_CP "CP" /* Extended Capability */
+-#define VPD_RV "RV" /* Checksum and Reserved */
+-#define VPD_YA "YA" /* Asset Tag Identifier */
+-#define VPD_VL "VL" /* First Error Log Message (SK specific) */
+-#define VPD_VF "VF" /* Second Error Log Message (SK specific) */
+-#define VPD_RW "RW" /* Remaining Read / Write Area */
+-
+-/* 'type' values for vpd_setup_para() */
+-#define VPD_RO_KEY 1 /* RO keys are "PN", "EC", "MN", "SN", "RV" */
+-#define VPD_RW_KEY 2 /* RW keys are "Yx", "Vx", and "RW" */
+-
+-/* 'op' values for vpd_setup_para() */
+-#define ADD_KEY 1 /* add the key at the pos "RV" or "RW" */
+-#define OWR_KEY 2 /* overwrite key if already exists */
+-
+-/*
+- * Define READ and WRITE Constants.
+- */
+-
+-#define VPD_DEV_ID_GENESIS 0x4300
+-
+-#define VPD_SIZE_YUKON 256
+-#define VPD_SIZE_GENESIS 512
+-#define VPD_SIZE 512
+-#define VPD_READ 0x0000
+-#define VPD_WRITE 0x8000
+-
+-#define VPD_STOP(pAC,IoC) VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG,VPD_WRITE)
+-
+-#define VPD_GET_RES_LEN(p) ((unsigned int) \
+- (* (SK_U8 *)&(p)[1]) |\
+- ((* (SK_U8 *)&(p)[2]) << 8))
+-#define VPD_GET_VPD_LEN(p) ((unsigned int)(* (SK_U8 *)&(p)[2]))
+-#define VPD_GET_VAL(p) ((char *)&(p)[3])
+-
+-#define VPD_MAX_LEN 50
+-
+-/* VPD status */
+- /* bit 7..1 reserved */
+-#define VPD_VALID (1<<0) /* VPD data buffer, vpd_free_ro, */
+- /* and vpd_free_rw valid */
+-
+-/*
+- * VPD structs
+- */
+-typedef struct s_vpd_status {
+- unsigned short Align01; /* Alignment */
+- unsigned short vpd_status; /* VPD status, description see above */
+- int vpd_free_ro; /* unused bytes in read only area */
+- int vpd_free_rw; /* bytes available in read/write area */
+-} SK_VPD_STATUS;
+-
+-typedef struct s_vpd {
+- SK_VPD_STATUS v; /* VPD status structure */
+- char vpd_buf[VPD_SIZE]; /* VPD buffer */
+- int rom_size; /* VPD ROM Size from PCI_OUR_REG_2 */
+- int vpd_size; /* saved VPD-size */
+-} SK_VPD;
+-
+-typedef struct s_vpd_para {
+- unsigned int p_len; /* parameter length */
+- char *p_val; /* points to the value */
+-} SK_VPD_PARA;
+-
+-/*
+- * structure of Large Resource Type Identifiers
+- */
+-
+-/* was removed because of alignment problems */
+-
+-/*
+- * structure of VPD keywords
+- */
+-typedef struct s_vpd_key {
+- char p_key[2]; /* 2 bytes ID string */
+- unsigned char p_len; /* 1 byte length */
+- char p_val; /* start of the value string */
+-} SK_VPD_KEY;
+-
+-
+-/*
+- * System specific VPD macros
+- */
+-#ifndef SKDIAG
+-#ifndef VPD_DO_IO
+-#define VPD_OUT8(pAC,IoC,Addr,Val) (void)SkPciWriteCfgByte(pAC,Addr,Val)
+-#define VPD_OUT16(pAC,IoC,Addr,Val) (void)SkPciWriteCfgWord(pAC,Addr,Val)
+-#define VPD_IN8(pAC,IoC,Addr,pVal) (void)SkPciReadCfgByte(pAC,Addr,pVal)
+-#define VPD_IN16(pAC,IoC,Addr,pVal) (void)SkPciReadCfgWord(pAC,Addr,pVal)
+-#define VPD_IN32(pAC,IoC,Addr,pVal) (void)SkPciReadCfgDWord(pAC,Addr,pVal)
+-#else /* VPD_DO_IO */
+-#define VPD_OUT8(pAC,IoC,Addr,Val) SK_OUT8(IoC,PCI_C(Addr),Val)
+-#define VPD_OUT16(pAC,IoC,Addr,Val) SK_OUT16(IoC,PCI_C(Addr),Val)
+-#define VPD_IN8(pAC,IoC,Addr,pVal) SK_IN8(IoC,PCI_C(Addr),pVal)
+-#define VPD_IN16(pAC,IoC,Addr,pVal) SK_IN16(IoC,PCI_C(Addr),pVal)
+-#define VPD_IN32(pAC,IoC,Addr,pVal) SK_IN32(IoC,PCI_C(Addr),pVal)
+-#endif /* VPD_DO_IO */
+-#else /* SKDIAG */
+-#define VPD_OUT8(pAC,Ioc,Addr,Val) { \
+- if ((pAC)->DgT.DgUseCfgCycle) \
+- SkPciWriteCfgByte(pAC,Addr,Val); \
+- else \
+- SK_OUT8(pAC,PCI_C(Addr),Val); \
+- }
+-#define VPD_OUT16(pAC,Ioc,Addr,Val) { \
+- if ((pAC)->DgT.DgUseCfgCycle) \
+- SkPciWriteCfgWord(pAC,Addr,Val); \
+- else \
+- SK_OUT16(pAC,PCI_C(Addr),Val); \
+- }
+-#define VPD_IN8(pAC,Ioc,Addr,pVal) { \
+- if ((pAC)->DgT.DgUseCfgCycle) \
+- SkPciReadCfgByte(pAC,Addr,pVal); \
+- else \
+- SK_IN8(pAC,PCI_C(Addr),pVal); \
+- }
+-#define VPD_IN16(pAC,Ioc,Addr,pVal) { \
+- if ((pAC)->DgT.DgUseCfgCycle) \
+- SkPciReadCfgWord(pAC,Addr,pVal); \
+- else \
+- SK_IN16(pAC,PCI_C(Addr),pVal); \
+- }
+-#define VPD_IN32(pAC,Ioc,Addr,pVal) { \
+- if ((pAC)->DgT.DgUseCfgCycle) \
+- SkPciReadCfgDWord(pAC,Addr,pVal); \
+- else \
+- SK_IN32(pAC,PCI_C(Addr),pVal); \
+- }
+-#endif /* nSKDIAG */
+-
+-/* function prototypes ********************************************************/
+-
+-#ifndef SK_KR_PROTO
+-#ifdef SKDIAG
+-extern SK_U32 VpdReadDWord(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- int addr);
+-#endif /* SKDIAG */
+-
+-extern SK_VPD_STATUS *VpdStat(
+- SK_AC *pAC,
+- SK_IOC IoC);
+-
+-extern int VpdKeys(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- char *buf,
+- int *len,
+- int *elements);
+-
+-extern int VpdRead(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- const char *key,
+- char *buf,
+- int *len);
+-
+-extern SK_BOOL VpdMayWrite(
+- char *key);
+-
+-extern int VpdWrite(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- const char *key,
+- const char *buf);
+-
+-extern int VpdDelete(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- char *key);
+-
+-extern int VpdUpdate(
+- SK_AC *pAC,
+- SK_IOC IoC);
+-
+-#ifdef SKDIAG
+-extern int VpdReadBlock(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- char *buf,
+- int addr,
+- int len);
+-
+-extern int VpdWriteBlock(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- char *buf,
+- int addr,
+- int len);
+-#endif /* SKDIAG */
+-#else /* SK_KR_PROTO */
+-extern SK_U32 VpdReadDWord();
+-extern SK_VPD_STATUS *VpdStat();
+-extern int VpdKeys();
+-extern int VpdRead();
+-extern SK_BOOL VpdMayWrite();
+-extern int VpdWrite();
+-extern int VpdDelete();
+-extern int VpdUpdate();
+-#endif /* SK_KR_PROTO */
+-
+-#endif /* __INC_SKVPD_H_ */
+diff --git a/drivers/net/sk98lin/h/xmac_ii.h b/drivers/net/sk98lin/h/xmac_ii.h
+deleted file mode 100644
+index 7f8e6d0..0000000
+--- a/drivers/net/sk98lin/h/xmac_ii.h
++++ /dev/null
+@@ -1,1579 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: xmac_ii.h
+- * Project: Gigabit Ethernet Adapters, Common Modules
+- * Version: $Revision: 1.52 $
+- * Date: $Date: 2003/10/02 16:35:50 $
+- * Purpose: Defines and Macros for Gigabit Ethernet Controller
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#ifndef __INC_XMAC_H
+-#define __INC_XMAC_H
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif /* __cplusplus */
+-
+-/* defines ********************************************************************/
+-
+-/*
+- * XMAC II registers
+- *
+- * The XMAC registers are 16 or 32 bits wide.
+- * The XMACs host processor interface is set to 16 bit mode,
+- * therefore ALL registers will be addressed with 16 bit accesses.
+- *
+- * The following macros are provided to access the XMAC registers
+- * XM_IN16(), XM_OUT16, XM_IN32(), XM_OUT32(), XM_INADR(), XM_OUTADR(),
+- * XM_INHASH(), and XM_OUTHASH().
+- * The macros are defined in SkGeHw.h.
+- *
+- * Note: NA reg = Network Address e.g DA, SA etc.
+- *
+- */
+-#define XM_MMU_CMD 0x0000 /* 16 bit r/w MMU Command Register */
+- /* 0x0004: reserved */
+-#define XM_POFF 0x0008 /* 32 bit r/w Packet Offset Register */
+-#define XM_BURST 0x000c /* 32 bit r/w Burst Register for half duplex*/
+-#define XM_1L_VLAN_TAG 0x0010 /* 16 bit r/w One Level VLAN Tag ID */
+-#define XM_2L_VLAN_TAG 0x0014 /* 16 bit r/w Two Level VLAN Tag ID */
+- /* 0x0018 - 0x001e: reserved */
+-#define XM_TX_CMD 0x0020 /* 16 bit r/w Transmit Command Register */
+-#define XM_TX_RT_LIM 0x0024 /* 16 bit r/w Transmit Retry Limit Register */
+-#define XM_TX_STIME 0x0028 /* 16 bit r/w Transmit Slottime Register */
+-#define XM_TX_IPG 0x002c /* 16 bit r/w Transmit Inter Packet Gap */
+-#define XM_RX_CMD 0x0030 /* 16 bit r/w Receive Command Register */
+-#define XM_PHY_ADDR 0x0034 /* 16 bit r/w PHY Address Register */
+-#define XM_PHY_DATA 0x0038 /* 16 bit r/w PHY Data Register */
+- /* 0x003c: reserved */
+-#define XM_GP_PORT 0x0040 /* 32 bit r/w General Purpose Port Register */
+-#define XM_IMSK 0x0044 /* 16 bit r/w Interrupt Mask Register */
+-#define XM_ISRC 0x0048 /* 16 bit r/o Interrupt Status Register */
+-#define XM_HW_CFG 0x004c /* 16 bit r/w Hardware Config Register */
+- /* 0x0050 - 0x005e: reserved */
+-#define XM_TX_LO_WM 0x0060 /* 16 bit r/w Tx FIFO Low Water Mark */
+-#define XM_TX_HI_WM 0x0062 /* 16 bit r/w Tx FIFO High Water Mark */
+-#define XM_TX_THR 0x0064 /* 16 bit r/w Tx Request Threshold */
+-#define XM_HT_THR 0x0066 /* 16 bit r/w Host Request Threshold */
+-#define XM_PAUSE_DA 0x0068 /* NA reg r/w Pause Destination Address */
+- /* 0x006e: reserved */
+-#define XM_CTL_PARA 0x0070 /* 32 bit r/w Control Parameter Register */
+-#define XM_MAC_OPCODE 0x0074 /* 16 bit r/w Opcode for MAC control frames */
+-#define XM_MAC_PTIME 0x0076 /* 16 bit r/w Pause time for MAC ctrl frames*/
+-#define XM_TX_STAT 0x0078 /* 32 bit r/o Tx Status LIFO Register */
+-
+- /* 0x0080 - 0x00fc: 16 NA reg r/w Exact Match Address Registers */
+- /* use the XM_EXM() macro to address */
+-#define XM_EXM_START 0x0080 /* r/w Start Address of the EXM Regs */
+-
+- /*
+- * XM_EXM(Reg)
+- *
+- * returns the XMAC address offset of specified Exact Match Addr Reg
+- *
+- * para: Reg EXM register to addr (0 .. 15)
+- *
+- * usage: XM_INADDR(IoC, MAC_1, XM_EXM(i), &val[i]);
+- */
+-#define XM_EXM(Reg) (XM_EXM_START + ((Reg) << 3))
+-
+-#define XM_SRC_CHK 0x0100 /* NA reg r/w Source Check Address Register */
+-#define XM_SA 0x0108 /* NA reg r/w Station Address Register */
+-#define XM_HSM 0x0110 /* 64 bit r/w Hash Match Address Registers */
+-#define XM_RX_LO_WM 0x0118 /* 16 bit r/w Receive Low Water Mark */
+-#define XM_RX_HI_WM 0x011a /* 16 bit r/w Receive High Water Mark */
+-#define XM_RX_THR 0x011c /* 32 bit r/w Receive Request Threshold */
+-#define XM_DEV_ID 0x0120 /* 32 bit r/o Device ID Register */
+-#define XM_MODE 0x0124 /* 32 bit r/w Mode Register */
+-#define XM_LSA 0x0128 /* NA reg r/o Last Source Register */
+- /* 0x012e: reserved */
+-#define XM_TS_READ 0x0130 /* 32 bit r/o Time Stamp Read Register */
+-#define XM_TS_LOAD 0x0134 /* 32 bit r/o Time Stamp Load Value */
+- /* 0x0138 - 0x01fe: reserved */
+-#define XM_STAT_CMD 0x0200 /* 16 bit r/w Statistics Command Register */
+-#define XM_RX_CNT_EV 0x0204 /* 32 bit r/o Rx Counter Event Register */
+-#define XM_TX_CNT_EV 0x0208 /* 32 bit r/o Tx Counter Event Register */
+-#define XM_RX_EV_MSK 0x020c /* 32 bit r/w Rx Counter Event Mask */
+-#define XM_TX_EV_MSK 0x0210 /* 32 bit r/w Tx Counter Event Mask */
+- /* 0x0204 - 0x027e: reserved */
+-#define XM_TXF_OK 0x0280 /* 32 bit r/o Frames Transmitted OK Conuter */
+-#define XM_TXO_OK_HI 0x0284 /* 32 bit r/o Octets Transmitted OK High Cnt*/
+-#define XM_TXO_OK_LO 0x0288 /* 32 bit r/o Octets Transmitted OK Low Cnt */
+-#define XM_TXF_BC_OK 0x028c /* 32 bit r/o Broadcast Frames Xmitted OK */
+-#define XM_TXF_MC_OK 0x0290 /* 32 bit r/o Multicast Frames Xmitted OK */
+-#define XM_TXF_UC_OK 0x0294 /* 32 bit r/o Unicast Frames Xmitted OK */
+-#define XM_TXF_LONG 0x0298 /* 32 bit r/o Tx Long Frame Counter */
+-#define XM_TXE_BURST 0x029c /* 32 bit r/o Tx Burst Event Counter */
+-#define XM_TXF_MPAUSE 0x02a0 /* 32 bit r/o Tx Pause MAC Ctrl Frame Cnt */
+-#define XM_TXF_MCTRL 0x02a4 /* 32 bit r/o Tx MAC Ctrl Frame Counter */
+-#define XM_TXF_SNG_COL 0x02a8 /* 32 bit r/o Tx Single Collision Counter */
+-#define XM_TXF_MUL_COL 0x02ac /* 32 bit r/o Tx Multiple Collision Counter */
+-#define XM_TXF_ABO_COL 0x02b0 /* 32 bit r/o Tx aborted due to Exces. Col. */
+-#define XM_TXF_LAT_COL 0x02b4 /* 32 bit r/o Tx Late Collision Counter */
+-#define XM_TXF_DEF 0x02b8 /* 32 bit r/o Tx Deferred Frame Counter */
+-#define XM_TXF_EX_DEF 0x02bc /* 32 bit r/o Tx Excessive Deferall Counter */
+-#define XM_TXE_FIFO_UR 0x02c0 /* 32 bit r/o Tx FIFO Underrun Event Cnt */
+-#define XM_TXE_CS_ERR 0x02c4 /* 32 bit r/o Tx Carrier Sense Error Cnt */
+-#define XM_TXP_UTIL 0x02c8 /* 32 bit r/o Tx Utilization in % */
+- /* 0x02cc - 0x02ce: reserved */
+-#define XM_TXF_64B 0x02d0 /* 32 bit r/o 64 Byte Tx Frame Counter */
+-#define XM_TXF_127B 0x02d4 /* 32 bit r/o 65-127 Byte Tx Frame Counter */
+-#define XM_TXF_255B 0x02d8 /* 32 bit r/o 128-255 Byte Tx Frame Counter */
+-#define XM_TXF_511B 0x02dc /* 32 bit r/o 256-511 Byte Tx Frame Counter */
+-#define XM_TXF_1023B 0x02e0 /* 32 bit r/o 512-1023 Byte Tx Frame Counter*/
+-#define XM_TXF_MAX_SZ 0x02e4 /* 32 bit r/o 1024-MaxSize Byte Tx Frame Cnt*/
+- /* 0x02e8 - 0x02fe: reserved */
+-#define XM_RXF_OK 0x0300 /* 32 bit r/o Frames Received OK */
+-#define XM_RXO_OK_HI 0x0304 /* 32 bit r/o Octets Received OK High Cnt */
+-#define XM_RXO_OK_LO 0x0308 /* 32 bit r/o Octets Received OK Low Counter*/
+-#define XM_RXF_BC_OK 0x030c /* 32 bit r/o Broadcast Frames Received OK */
+-#define XM_RXF_MC_OK 0x0310 /* 32 bit r/o Multicast Frames Received OK */
+-#define XM_RXF_UC_OK 0x0314 /* 32 bit r/o Unicast Frames Received OK */
+-#define XM_RXF_MPAUSE 0x0318 /* 32 bit r/o Rx Pause MAC Ctrl Frame Cnt */
+-#define XM_RXF_MCTRL 0x031c /* 32 bit r/o Rx MAC Ctrl Frame Counter */
+-#define XM_RXF_INV_MP 0x0320 /* 32 bit r/o Rx invalid Pause Frame Cnt */
+-#define XM_RXF_INV_MOC 0x0324 /* 32 bit r/o Rx Frames with inv. MAC Opcode*/
+-#define XM_RXE_BURST 0x0328 /* 32 bit r/o Rx Burst Event Counter */
+-#define XM_RXE_FMISS 0x032c /* 32 bit r/o Rx Missed Frames Event Cnt */
+-#define XM_RXF_FRA_ERR 0x0330 /* 32 bit r/o Rx Framing Error Counter */
+-#define XM_RXE_FIFO_OV 0x0334 /* 32 bit r/o Rx FIFO overflow Event Cnt */
+-#define XM_RXF_JAB_PKT 0x0338 /* 32 bit r/o Rx Jabber Packet Frame Cnt */
+-#define XM_RXE_CAR_ERR 0x033c /* 32 bit r/o Rx Carrier Event Error Cnt */
+-#define XM_RXF_LEN_ERR 0x0340 /* 32 bit r/o Rx in Range Length Error */
+-#define XM_RXE_SYM_ERR 0x0344 /* 32 bit r/o Rx Symbol Error Counter */
+-#define XM_RXE_SHT_ERR 0x0348 /* 32 bit r/o Rx Short Event Error Cnt */
+-#define XM_RXE_RUNT 0x034c /* 32 bit r/o Rx Runt Event Counter */
+-#define XM_RXF_LNG_ERR 0x0350 /* 32 bit r/o Rx Frame too Long Error Cnt */
+-#define XM_RXF_FCS_ERR 0x0354 /* 32 bit r/o Rx Frame Check Seq. Error Cnt */
+- /* 0x0358 - 0x035a: reserved */
+-#define XM_RXF_CEX_ERR 0x035c /* 32 bit r/o Rx Carrier Ext Error Frame Cnt*/
+-#define XM_RXP_UTIL 0x0360 /* 32 bit r/o Rx Utilization in % */
+- /* 0x0364 - 0x0366: reserved */
+-#define XM_RXF_64B 0x0368 /* 32 bit r/o 64 Byte Rx Frame Counter */
+-#define XM_RXF_127B 0x036c /* 32 bit r/o 65-127 Byte Rx Frame Counter */
+-#define XM_RXF_255B 0x0370 /* 32 bit r/o 128-255 Byte Rx Frame Counter */
+-#define XM_RXF_511B 0x0374 /* 32 bit r/o 256-511 Byte Rx Frame Counter */
+-#define XM_RXF_1023B 0x0378 /* 32 bit r/o 512-1023 Byte Rx Frame Counter*/
+-#define XM_RXF_MAX_SZ 0x037c /* 32 bit r/o 1024-MaxSize Byte Rx Frame Cnt*/
+- /* 0x02e8 - 0x02fe: reserved */
+-
+-
+-/*----------------------------------------------------------------------------*/
+-/*
+- * XMAC Bit Definitions
+- *
+- * If the bit access behaviour differs from the register access behaviour
+- * (r/w, r/o) this is documented after the bit number.
+- * The following bit access behaviours are used:
+- * (sc) self clearing
+- * (ro) read only
+- */
+-
+-/* XM_MMU_CMD 16 bit r/w MMU Command Register */
+- /* Bit 15..13: reserved */
+-#define XM_MMU_PHY_RDY (1<<12) /* Bit 12: PHY Read Ready */
+-#define XM_MMU_PHY_BUSY (1<<11) /* Bit 11: PHY Busy */
+-#define XM_MMU_IGN_PF (1<<10) /* Bit 10: Ignore Pause Frame */
+-#define XM_MMU_MAC_LB (1<<9) /* Bit 9: Enable MAC Loopback */
+- /* Bit 8: reserved */
+-#define XM_MMU_FRC_COL (1<<7) /* Bit 7: Force Collision */
+-#define XM_MMU_SIM_COL (1<<6) /* Bit 6: Simulate Collision */
+-#define XM_MMU_NO_PRE (1<<5) /* Bit 5: No MDIO Preamble */
+-#define XM_MMU_GMII_FD (1<<4) /* Bit 4: GMII uses Full Duplex */
+-#define XM_MMU_RAT_CTRL (1<<3) /* Bit 3: Enable Rate Control */
+-#define XM_MMU_GMII_LOOP (1<<2) /* Bit 2: PHY is in Loopback Mode */
+-#define XM_MMU_ENA_RX (1<<1) /* Bit 1: Enable Receiver */
+-#define XM_MMU_ENA_TX (1<<0) /* Bit 0: Enable Transmitter */
+-
+-
+-/* XM_TX_CMD 16 bit r/w Transmit Command Register */
+- /* Bit 15..7: reserved */
+-#define XM_TX_BK2BK (1<<6) /* Bit 6: Ignor Carrier Sense (Tx Bk2Bk)*/
+-#define XM_TX_ENC_BYP (1<<5) /* Bit 5: Set Encoder in Bypass Mode */
+-#define XM_TX_SAM_LINE (1<<4) /* Bit 4: (sc) Start utilization calculation */
+-#define XM_TX_NO_GIG_MD (1<<3) /* Bit 3: Disable Carrier Extension */
+-#define XM_TX_NO_PRE (1<<2) /* Bit 2: Disable Preamble Generation */
+-#define XM_TX_NO_CRC (1<<1) /* Bit 1: Disable CRC Generation */
+-#define XM_TX_AUTO_PAD (1<<0) /* Bit 0: Enable Automatic Padding */
+-
+-
+-/* XM_TX_RT_LIM 16 bit r/w Transmit Retry Limit Register */
+- /* Bit 15..5: reserved */
+-#define XM_RT_LIM_MSK 0x1f /* Bit 4..0: Tx Retry Limit */
+-
+-
+-/* XM_TX_STIME 16 bit r/w Transmit Slottime Register */
+- /* Bit 15..7: reserved */
+-#define XM_STIME_MSK 0x7f /* Bit 6..0: Tx Slottime bits */
+-
+-
+-/* XM_TX_IPG 16 bit r/w Transmit Inter Packet Gap */
+- /* Bit 15..8: reserved */
+-#define XM_IPG_MSK 0xff /* Bit 7..0: IPG value bits */
+-
+-
+-/* XM_RX_CMD 16 bit r/w Receive Command Register */
+- /* Bit 15..9: reserved */
+-#define XM_RX_LENERR_OK (1<<8) /* Bit 8 don't set Rx Err bit for */
+- /* inrange error packets */
+-#define XM_RX_BIG_PK_OK (1<<7) /* Bit 7 don't set Rx Err bit for */
+- /* jumbo packets */
+-#define XM_RX_IPG_CAP (1<<6) /* Bit 6 repl. type field with IPG */
+-#define XM_RX_TP_MD (1<<5) /* Bit 5: Enable transparent Mode */
+-#define XM_RX_STRIP_FCS (1<<4) /* Bit 4: Enable FCS Stripping */
+-#define XM_RX_SELF_RX (1<<3) /* Bit 3: Enable Rx of own packets */
+-#define XM_RX_SAM_LINE (1<<2) /* Bit 2: (sc) Start utilization calculation */
+-#define XM_RX_STRIP_PAD (1<<1) /* Bit 1: Strip pad bytes of Rx frames */
+-#define XM_RX_DIS_CEXT (1<<0) /* Bit 0: Disable carrier ext. check */
+-
+-
+-/* XM_PHY_ADDR 16 bit r/w PHY Address Register */
+- /* Bit 15..5: reserved */
+-#define XM_PHY_ADDR_SZ 0x1f /* Bit 4..0: PHY Address bits */
+-
+-
+-/* XM_GP_PORT 32 bit r/w General Purpose Port Register */
+- /* Bit 31..7: reserved */
+-#define XM_GP_ANIP (1L<<6) /* Bit 6: (ro) Auto-Neg. in progress */
+-#define XM_GP_FRC_INT (1L<<5) /* Bit 5: (sc) Force Interrupt */
+- /* Bit 4: reserved */
+-#define XM_GP_RES_MAC (1L<<3) /* Bit 3: (sc) Reset MAC and FIFOs */
+-#define XM_GP_RES_STAT (1L<<2) /* Bit 2: (sc) Reset the statistics module */
+- /* Bit 1: reserved */
+-#define XM_GP_INP_ASS (1L<<0) /* Bit 0: (ro) GP Input Pin asserted */
+-
+-
+-/* XM_IMSK 16 bit r/w Interrupt Mask Register */
+-/* XM_ISRC 16 bit r/o Interrupt Status Register */
+- /* Bit 15: reserved */
+-#define XM_IS_LNK_AE (1<<14) /* Bit 14: Link Asynchronous Event */
+-#define XM_IS_TX_ABORT (1<<13) /* Bit 13: Transmit Abort, late Col. etc */
+-#define XM_IS_FRC_INT (1<<12) /* Bit 12: Force INT bit set in GP */
+-#define XM_IS_INP_ASS (1<<11) /* Bit 11: Input Asserted, GP bit 0 set */
+-#define XM_IS_LIPA_RC (1<<10) /* Bit 10: Link Partner requests config */
+-#define XM_IS_RX_PAGE (1<<9) /* Bit 9: Page Received */
+-#define XM_IS_TX_PAGE (1<<8) /* Bit 8: Next Page Loaded for Transmit */
+-#define XM_IS_AND (1<<7) /* Bit 7: Auto-Negotiation Done */
+-#define XM_IS_TSC_OV (1<<6) /* Bit 6: Time Stamp Counter Overflow */
+-#define XM_IS_RXC_OV (1<<5) /* Bit 5: Rx Counter Event Overflow */
+-#define XM_IS_TXC_OV (1<<4) /* Bit 4: Tx Counter Event Overflow */
+-#define XM_IS_RXF_OV (1<<3) /* Bit 3: Receive FIFO Overflow */
+-#define XM_IS_TXF_UR (1<<2) /* Bit 2: Transmit FIFO Underrun */
+-#define XM_IS_TX_COMP (1<<1) /* Bit 1: Frame Tx Complete */
+-#define XM_IS_RX_COMP (1<<0) /* Bit 0: Frame Rx Complete */
+-
+-#define XM_DEF_MSK (~(XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE |\
+- XM_IS_AND | XM_IS_RXC_OV | XM_IS_TXC_OV | XM_IS_TXF_UR))
+-
+-
+-/* XM_HW_CFG 16 bit r/w Hardware Config Register */
+- /* Bit 15.. 4: reserved */
+-#define XM_HW_GEN_EOP (1<<3) /* Bit 3: generate End of Packet pulse */
+-#define XM_HW_COM4SIG (1<<2) /* Bit 2: use Comma Detect for Sig. Det.*/
+- /* Bit 1: reserved */
+-#define XM_HW_GMII_MD (1<<0) /* Bit 0: GMII Interface selected */
+-
+-
+-/* XM_TX_LO_WM 16 bit r/w Tx FIFO Low Water Mark */
+-/* XM_TX_HI_WM 16 bit r/w Tx FIFO High Water Mark */
+- /* Bit 15..10 reserved */
+-#define XM_TX_WM_MSK 0x01ff /* Bit 9.. 0 Tx FIFO Watermark bits */
+-
+-/* XM_TX_THR 16 bit r/w Tx Request Threshold */
+-/* XM_HT_THR 16 bit r/w Host Request Threshold */
+-/* XM_RX_THR 16 bit r/w Rx Request Threshold */
+- /* Bit 15..11 reserved */
+-#define XM_THR_MSK 0x03ff /* Bit 10.. 0 Rx/Tx Request Threshold bits */
+-
+-
+-/* XM_TX_STAT 32 bit r/o Tx Status LIFO Register */
+-#define XM_ST_VALID (1UL<<31) /* Bit 31: Status Valid */
+-#define XM_ST_BYTE_CNT (0x3fffL<<17) /* Bit 30..17: Tx frame Length */
+-#define XM_ST_RETRY_CNT (0x1fL<<12) /* Bit 16..12: Retry Count */
+-#define XM_ST_EX_COL (1L<<11) /* Bit 11: Excessive Collisions */
+-#define XM_ST_EX_DEF (1L<<10) /* Bit 10: Excessive Deferral */
+-#define XM_ST_BURST (1L<<9) /* Bit 9: p. xmitted in burst md*/
+-#define XM_ST_DEFER (1L<<8) /* Bit 8: packet was defered */
+-#define XM_ST_BC (1L<<7) /* Bit 7: Broadcast packet */
+-#define XM_ST_MC (1L<<6) /* Bit 6: Multicast packet */
+-#define XM_ST_UC (1L<<5) /* Bit 5: Unicast packet */
+-#define XM_ST_TX_UR (1L<<4) /* Bit 4: FIFO Underrun occured */
+-#define XM_ST_CS_ERR (1L<<3) /* Bit 3: Carrier Sense Error */
+-#define XM_ST_LAT_COL (1L<<2) /* Bit 2: Late Collision Error */
+-#define XM_ST_MUL_COL (1L<<1) /* Bit 1: Multiple Collisions */
+-#define XM_ST_SGN_COL (1L<<0) /* Bit 0: Single Collision */
+-
+-/* XM_RX_LO_WM 16 bit r/w Receive Low Water Mark */
+-/* XM_RX_HI_WM 16 bit r/w Receive High Water Mark */
+- /* Bit 15..11: reserved */
+-#define XM_RX_WM_MSK 0x03ff /* Bit 11.. 0: Rx FIFO Watermark bits */
+-
+-
+-/* XM_DEV_ID 32 bit r/o Device ID Register */
+-#define XM_DEV_OUI (0x00ffffffUL<<8) /* Bit 31..8: Device OUI */
+-#define XM_DEV_REV (0x07L << 5) /* Bit 7..5: Chip Rev Num */
+-
+-
+-/* XM_MODE 32 bit r/w Mode Register */
+- /* Bit 31..27: reserved */
+-#define XM_MD_ENA_REJ (1L<<26) /* Bit 26: Enable Frame Reject */
+-#define XM_MD_SPOE_E (1L<<25) /* Bit 25: Send Pause on Edge */
+- /* extern generated */
+-#define XM_MD_TX_REP (1L<<24) /* Bit 24: Transmit Repeater Mode */
+-#define XM_MD_SPOFF_I (1L<<23) /* Bit 23: Send Pause on FIFO full */
+- /* intern generated */
+-#define XM_MD_LE_STW (1L<<22) /* Bit 22: Rx Stat Word in Little Endian */
+-#define XM_MD_TX_CONT (1L<<21) /* Bit 21: Send Continuous */
+-#define XM_MD_TX_PAUSE (1L<<20) /* Bit 20: (sc) Send Pause Frame */
+-#define XM_MD_ATS (1L<<19) /* Bit 19: Append Time Stamp */
+-#define XM_MD_SPOL_I (1L<<18) /* Bit 18: Send Pause on Low */
+- /* intern generated */
+-#define XM_MD_SPOH_I (1L<<17) /* Bit 17: Send Pause on High */
+- /* intern generated */
+-#define XM_MD_CAP (1L<<16) /* Bit 16: Check Address Pair */
+-#define XM_MD_ENA_HASH (1L<<15) /* Bit 15: Enable Hashing */
+-#define XM_MD_CSA (1L<<14) /* Bit 14: Check Station Address */
+-#define XM_MD_CAA (1L<<13) /* Bit 13: Check Address Array */
+-#define XM_MD_RX_MCTRL (1L<<12) /* Bit 12: Rx MAC Control Frame */
+-#define XM_MD_RX_RUNT (1L<<11) /* Bit 11: Rx Runt Frames */
+-#define XM_MD_RX_IRLE (1L<<10) /* Bit 10: Rx in Range Len Err Frame */
+-#define XM_MD_RX_LONG (1L<<9) /* Bit 9: Rx Long Frame */
+-#define XM_MD_RX_CRCE (1L<<8) /* Bit 8: Rx CRC Error Frame */
+-#define XM_MD_RX_ERR (1L<<7) /* Bit 7: Rx Error Frame */
+-#define XM_MD_DIS_UC (1L<<6) /* Bit 6: Disable Rx Unicast */
+-#define XM_MD_DIS_MC (1L<<5) /* Bit 5: Disable Rx Multicast */
+-#define XM_MD_DIS_BC (1L<<4) /* Bit 4: Disable Rx Broadcast */
+-#define XM_MD_ENA_PROM (1L<<3) /* Bit 3: Enable Promiscuous */
+-#define XM_MD_ENA_BE (1L<<2) /* Bit 2: Enable Big Endian */
+-#define XM_MD_FTF (1L<<1) /* Bit 1: (sc) Flush Tx FIFO */
+-#define XM_MD_FRF (1L<<0) /* Bit 0: (sc) Flush Rx FIFO */
+-
+-#define XM_PAUSE_MODE (XM_MD_SPOE_E | XM_MD_SPOL_I | XM_MD_SPOH_I)
+-#define XM_DEF_MODE (XM_MD_RX_RUNT | XM_MD_RX_IRLE | XM_MD_RX_LONG |\
+- XM_MD_RX_CRCE | XM_MD_RX_ERR | XM_MD_CSA | XM_MD_CAA)
+-
+-/* XM_STAT_CMD 16 bit r/w Statistics Command Register */
+- /* Bit 16..6: reserved */
+-#define XM_SC_SNP_RXC (1<<5) /* Bit 5: (sc) Snap Rx Counters */
+-#define XM_SC_SNP_TXC (1<<4) /* Bit 4: (sc) Snap Tx Counters */
+-#define XM_SC_CP_RXC (1<<3) /* Bit 3: Copy Rx Counters Continuously */
+-#define XM_SC_CP_TXC (1<<2) /* Bit 2: Copy Tx Counters Continuously */
+-#define XM_SC_CLR_RXC (1<<1) /* Bit 1: (sc) Clear Rx Counters */
+-#define XM_SC_CLR_TXC (1<<0) /* Bit 0: (sc) Clear Tx Counters */
+-
+-
+-/* XM_RX_CNT_EV 32 bit r/o Rx Counter Event Register */
+-/* XM_RX_EV_MSK 32 bit r/w Rx Counter Event Mask */
+-#define XMR_MAX_SZ_OV (1UL<<31) /* Bit 31: 1024-MaxSize Rx Cnt Ov*/
+-#define XMR_1023B_OV (1L<<30) /* Bit 30: 512-1023Byte Rx Cnt Ov*/
+-#define XMR_511B_OV (1L<<29) /* Bit 29: 256-511 Byte Rx Cnt Ov*/
+-#define XMR_255B_OV (1L<<28) /* Bit 28: 128-255 Byte Rx Cnt Ov*/
+-#define XMR_127B_OV (1L<<27) /* Bit 27: 65-127 Byte Rx Cnt Ov */
+-#define XMR_64B_OV (1L<<26) /* Bit 26: 64 Byte Rx Cnt Ov */
+-#define XMR_UTIL_OV (1L<<25) /* Bit 25: Rx Util Cnt Overflow */
+-#define XMR_UTIL_UR (1L<<24) /* Bit 24: Rx Util Cnt Underrun */
+-#define XMR_CEX_ERR_OV (1L<<23) /* Bit 23: CEXT Err Cnt Ov */
+- /* Bit 22: reserved */
+-#define XMR_FCS_ERR_OV (1L<<21) /* Bit 21: Rx FCS Error Cnt Ov */
+-#define XMR_LNG_ERR_OV (1L<<20) /* Bit 20: Rx too Long Err Cnt Ov*/
+-#define XMR_RUNT_OV (1L<<19) /* Bit 19: Runt Event Cnt Ov */
+-#define XMR_SHT_ERR_OV (1L<<18) /* Bit 18: Rx Short Ev Err Cnt Ov*/
+-#define XMR_SYM_ERR_OV (1L<<17) /* Bit 17: Rx Sym Err Cnt Ov */
+- /* Bit 16: reserved */
+-#define XMR_CAR_ERR_OV (1L<<15) /* Bit 15: Rx Carr Ev Err Cnt Ov */
+-#define XMR_JAB_PKT_OV (1L<<14) /* Bit 14: Rx Jabb Packet Cnt Ov */
+-#define XMR_FIFO_OV (1L<<13) /* Bit 13: Rx FIFO Ov Ev Cnt Ov */
+-#define XMR_FRA_ERR_OV (1L<<12) /* Bit 12: Rx Framing Err Cnt Ov */
+-#define XMR_FMISS_OV (1L<<11) /* Bit 11: Rx Missed Ev Cnt Ov */
+-#define XMR_BURST (1L<<10) /* Bit 10: Rx Burst Event Cnt Ov */
+-#define XMR_INV_MOC (1L<<9) /* Bit 9: Rx with inv. MAC OC Ov*/
+-#define XMR_INV_MP (1L<<8) /* Bit 8: Rx inv Pause Frame Ov */
+-#define XMR_MCTRL_OV (1L<<7) /* Bit 7: Rx MAC Ctrl-F Cnt Ov */
+-#define XMR_MPAUSE_OV (1L<<6) /* Bit 6: Rx Pause MAC Ctrl-F Ov*/
+-#define XMR_UC_OK_OV (1L<<5) /* Bit 5: Rx Unicast Frame CntOv*/
+-#define XMR_MC_OK_OV (1L<<4) /* Bit 4: Rx Multicast Cnt Ov */
+-#define XMR_BC_OK_OV (1L<<3) /* Bit 3: Rx Broadcast Cnt Ov */
+-#define XMR_OK_LO_OV (1L<<2) /* Bit 2: Octets Rx OK Low CntOv*/
+-#define XMR_OK_HI_OV (1L<<1) /* Bit 1: Octets Rx OK Hi Cnt Ov*/
+-#define XMR_OK_OV (1L<<0) /* Bit 0: Frames Received Ok Ov */
+-
+-#define XMR_DEF_MSK (XMR_OK_LO_OV | XMR_OK_HI_OV)
+-
+-/* XM_TX_CNT_EV 32 bit r/o Tx Counter Event Register */
+-/* XM_TX_EV_MSK 32 bit r/w Tx Counter Event Mask */
+- /* Bit 31..26: reserved */
+-#define XMT_MAX_SZ_OV (1L<<25) /* Bit 25: 1024-MaxSize Tx Cnt Ov*/
+-#define XMT_1023B_OV (1L<<24) /* Bit 24: 512-1023Byte Tx Cnt Ov*/
+-#define XMT_511B_OV (1L<<23) /* Bit 23: 256-511 Byte Tx Cnt Ov*/
+-#define XMT_255B_OV (1L<<22) /* Bit 22: 128-255 Byte Tx Cnt Ov*/
+-#define XMT_127B_OV (1L<<21) /* Bit 21: 65-127 Byte Tx Cnt Ov */
+-#define XMT_64B_OV (1L<<20) /* Bit 20: 64 Byte Tx Cnt Ov */
+-#define XMT_UTIL_OV (1L<<19) /* Bit 19: Tx Util Cnt Overflow */
+-#define XMT_UTIL_UR (1L<<18) /* Bit 18: Tx Util Cnt Underrun */
+-#define XMT_CS_ERR_OV (1L<<17) /* Bit 17: Tx Carr Sen Err Cnt Ov*/
+-#define XMT_FIFO_UR_OV (1L<<16) /* Bit 16: Tx FIFO Ur Ev Cnt Ov */
+-#define XMT_EX_DEF_OV (1L<<15) /* Bit 15: Tx Ex Deferall Cnt Ov */
+-#define XMT_DEF (1L<<14) /* Bit 14: Tx Deferred Cnt Ov */
+-#define XMT_LAT_COL_OV (1L<<13) /* Bit 13: Tx Late Col Cnt Ov */
+-#define XMT_ABO_COL_OV (1L<<12) /* Bit 12: Tx abo dueto Ex Col Ov*/
+-#define XMT_MUL_COL_OV (1L<<11) /* Bit 11: Tx Mult Col Cnt Ov */
+-#define XMT_SNG_COL (1L<<10) /* Bit 10: Tx Single Col Cnt Ov */
+-#define XMT_MCTRL_OV (1L<<9) /* Bit 9: Tx MAC Ctrl Counter Ov*/
+-#define XMT_MPAUSE (1L<<8) /* Bit 8: Tx Pause MAC Ctrl-F Ov*/
+-#define XMT_BURST (1L<<7) /* Bit 7: Tx Burst Event Cnt Ov */
+-#define XMT_LONG (1L<<6) /* Bit 6: Tx Long Frame Cnt Ov */
+-#define XMT_UC_OK_OV (1L<<5) /* Bit 5: Tx Unicast Cnt Ov */
+-#define XMT_MC_OK_OV (1L<<4) /* Bit 4: Tx Multicast Cnt Ov */
+-#define XMT_BC_OK_OV (1L<<3) /* Bit 3: Tx Broadcast Cnt Ov */
+-#define XMT_OK_LO_OV (1L<<2) /* Bit 2: Octets Tx OK Low CntOv*/
+-#define XMT_OK_HI_OV (1L<<1) /* Bit 1: Octets Tx OK Hi Cnt Ov*/
+-#define XMT_OK_OV (1L<<0) /* Bit 0: Frames Tx Ok Ov */
+-
+-#define XMT_DEF_MSK (XMT_OK_LO_OV | XMT_OK_HI_OV)
+-
+-/*
+- * Receive Frame Status Encoding
+- */
+-#define XMR_FS_LEN (0x3fffUL<<18) /* Bit 31..18: Rx Frame Length */
+-#define XMR_FS_2L_VLAN (1L<<17) /* Bit 17: tagged wh 2Lev VLAN ID*/
+-#define XMR_FS_1L_VLAN (1L<<16) /* Bit 16: tagged wh 1Lev VLAN ID*/
+-#define XMR_FS_BC (1L<<15) /* Bit 15: Broadcast Frame */
+-#define XMR_FS_MC (1L<<14) /* Bit 14: Multicast Frame */
+-#define XMR_FS_UC (1L<<13) /* Bit 13: Unicast Frame */
+- /* Bit 12: reserved */
+-#define XMR_FS_BURST (1L<<11) /* Bit 11: Burst Mode */
+-#define XMR_FS_CEX_ERR (1L<<10) /* Bit 10: Carrier Ext. Error */
+-#define XMR_FS_802_3 (1L<<9) /* Bit 9: 802.3 Frame */
+-#define XMR_FS_COL_ERR (1L<<8) /* Bit 8: Collision Error */
+-#define XMR_FS_CAR_ERR (1L<<7) /* Bit 7: Carrier Event Error */
+-#define XMR_FS_LEN_ERR (1L<<6) /* Bit 6: In-Range Length Error */
+-#define XMR_FS_FRA_ERR (1L<<5) /* Bit 5: Framing Error */
+-#define XMR_FS_RUNT (1L<<4) /* Bit 4: Runt Frame */
+-#define XMR_FS_LNG_ERR (1L<<3) /* Bit 3: Giant (Jumbo) Frame */
+-#define XMR_FS_FCS_ERR (1L<<2) /* Bit 2: Frame Check Sequ Err */
+-#define XMR_FS_ERR (1L<<1) /* Bit 1: Frame Error */
+-#define XMR_FS_MCTRL (1L<<0) /* Bit 0: MAC Control Packet */
+-
+-/*
+- * XMR_FS_ERR will be set if
+- * XMR_FS_FCS_ERR, XMR_FS_LNG_ERR, XMR_FS_RUNT,
+- * XMR_FS_FRA_ERR, XMR_FS_LEN_ERR, or XMR_FS_CEX_ERR
+- * is set. XMR_FS_LNG_ERR and XMR_FS_LEN_ERR will issue
+- * XMR_FS_ERR unless the corresponding bit in the Receive Command
+- * Register is set.
+- */
+-#define XMR_FS_ANY_ERR XMR_FS_ERR
+-
+-/*----------------------------------------------------------------------------*/
+-/*
+- * XMAC-PHY Registers, indirect addressed over the XMAC
+- */
+-#define PHY_XMAC_CTRL 0x00 /* 16 bit r/w PHY Control Register */
+-#define PHY_XMAC_STAT 0x01 /* 16 bit r/w PHY Status Register */
+-#define PHY_XMAC_ID0 0x02 /* 16 bit r/o PHY ID0 Register */
+-#define PHY_XMAC_ID1 0x03 /* 16 bit r/o PHY ID1 Register */
+-#define PHY_XMAC_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */
+-#define PHY_XMAC_AUNE_LP 0x05 /* 16 bit r/o Link Partner Abi Reg */
+-#define PHY_XMAC_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */
+-#define PHY_XMAC_NEPG 0x07 /* 16 bit r/w Next Page Register */
+-#define PHY_XMAC_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */
+- /* 0x09 - 0x0e: reserved */
+-#define PHY_XMAC_EXT_STAT 0x0f /* 16 bit r/o Ext Status Register */
+-#define PHY_XMAC_RES_ABI 0x10 /* 16 bit r/o PHY Resolved Ability */
+-
+-/*----------------------------------------------------------------------------*/
+-/*
+- * Broadcom-PHY Registers, indirect addressed over XMAC
+- */
+-#define PHY_BCOM_CTRL 0x00 /* 16 bit r/w PHY Control Register */
+-#define PHY_BCOM_STAT 0x01 /* 16 bit r/o PHY Status Register */
+-#define PHY_BCOM_ID0 0x02 /* 16 bit r/o PHY ID0 Register */
+-#define PHY_BCOM_ID1 0x03 /* 16 bit r/o PHY ID1 Register */
+-#define PHY_BCOM_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */
+-#define PHY_BCOM_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */
+-#define PHY_BCOM_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */
+-#define PHY_BCOM_NEPG 0x07 /* 16 bit r/w Next Page Register */
+-#define PHY_BCOM_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */
+- /* Broadcom-specific registers */
+-#define PHY_BCOM_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Ctrl Reg */
+-#define PHY_BCOM_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */
+- /* 0x0b - 0x0e: reserved */
+-#define PHY_BCOM_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */
+-#define PHY_BCOM_P_EXT_CTRL 0x10 /* 16 bit r/w PHY Extended Ctrl Reg */
+-#define PHY_BCOM_P_EXT_STAT 0x11 /* 16 bit r/o PHY Extended Stat Reg */
+-#define PHY_BCOM_RE_CTR 0x12 /* 16 bit r/w Receive Error Counter */
+-#define PHY_BCOM_FC_CTR 0x13 /* 16 bit r/w False Carrier Sense Cnt */
+-#define PHY_BCOM_RNO_CTR 0x14 /* 16 bit r/w Receiver NOT_OK Cnt */
+- /* 0x15 - 0x17: reserved */
+-#define PHY_BCOM_AUX_CTRL 0x18 /* 16 bit r/w Auxiliary Control Reg */
+-#define PHY_BCOM_AUX_STAT 0x19 /* 16 bit r/o Auxiliary Stat Summary */
+-#define PHY_BCOM_INT_STAT 0x1a /* 16 bit r/o Interrupt Status Reg */
+-#define PHY_BCOM_INT_MASK 0x1b /* 16 bit r/w Interrupt Mask Reg */
+- /* 0x1c: reserved */
+- /* 0x1d - 0x1f: test registers */
+-
+-/*----------------------------------------------------------------------------*/
+-/*
+- * Marvel-PHY Registers, indirect addressed over GMAC
+- */
+-#define PHY_MARV_CTRL 0x00 /* 16 bit r/w PHY Control Register */
+-#define PHY_MARV_STAT 0x01 /* 16 bit r/o PHY Status Register */
+-#define PHY_MARV_ID0 0x02 /* 16 bit r/o PHY ID0 Register */
+-#define PHY_MARV_ID1 0x03 /* 16 bit r/o PHY ID1 Register */
+-#define PHY_MARV_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */
+-#define PHY_MARV_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */
+-#define PHY_MARV_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */
+-#define PHY_MARV_NEPG 0x07 /* 16 bit r/w Next Page Register */
+-#define PHY_MARV_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */
+- /* Marvel-specific registers */
+-#define PHY_MARV_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Ctrl Reg */
+-#define PHY_MARV_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */
+- /* 0x0b - 0x0e: reserved */
+-#define PHY_MARV_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */
+-#define PHY_MARV_PHY_CTRL 0x10 /* 16 bit r/w PHY Specific Ctrl Reg */
+-#define PHY_MARV_PHY_STAT 0x11 /* 16 bit r/o PHY Specific Stat Reg */
+-#define PHY_MARV_INT_MASK 0x12 /* 16 bit r/w Interrupt Mask Reg */
+-#define PHY_MARV_INT_STAT 0x13 /* 16 bit r/o Interrupt Status Reg */
+-#define PHY_MARV_EXT_CTRL 0x14 /* 16 bit r/w Ext. PHY Specific Ctrl */
+-#define PHY_MARV_RXE_CNT 0x15 /* 16 bit r/w Receive Error Counter */
+-#define PHY_MARV_EXT_ADR 0x16 /* 16 bit r/w Ext. Ad. for Cable Diag. */
+- /* 0x17: reserved */
+-#define PHY_MARV_LED_CTRL 0x18 /* 16 bit r/w LED Control Reg */
+-#define PHY_MARV_LED_OVER 0x19 /* 16 bit r/w Manual LED Override Reg */
+-#define PHY_MARV_EXT_CTRL_2 0x1a /* 16 bit r/w Ext. PHY Specific Ctrl 2 */
+-#define PHY_MARV_EXT_P_STAT 0x1b /* 16 bit r/w Ext. PHY Spec. Stat Reg */
+-#define PHY_MARV_CABLE_DIAG 0x1c /* 16 bit r/o Cable Diagnostic Reg */
+- /* 0x1d - 0x1f: reserved */
+-
+-/*----------------------------------------------------------------------------*/
+-/*
+- * Level One-PHY Registers, indirect addressed over XMAC
+- */
+-#define PHY_LONE_CTRL 0x00 /* 16 bit r/w PHY Control Register */
+-#define PHY_LONE_STAT 0x01 /* 16 bit r/o PHY Status Register */
+-#define PHY_LONE_ID0 0x02 /* 16 bit r/o PHY ID0 Register */
+-#define PHY_LONE_ID1 0x03 /* 16 bit r/o PHY ID1 Register */
+-#define PHY_LONE_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */
+-#define PHY_LONE_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */
+-#define PHY_LONE_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */
+-#define PHY_LONE_NEPG 0x07 /* 16 bit r/w Next Page Register */
+-#define PHY_LONE_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */
+- /* Level One-specific registers */
+-#define PHY_LONE_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg*/
+-#define PHY_LONE_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */
+- /* 0x0b -0x0e: reserved */
+-#define PHY_LONE_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */
+-#define PHY_LONE_PORT_CFG 0x10 /* 16 bit r/w Port Configuration Reg*/
+-#define PHY_LONE_Q_STAT 0x11 /* 16 bit r/o Quick Status Reg */
+-#define PHY_LONE_INT_ENAB 0x12 /* 16 bit r/w Interrupt Enable Reg */
+-#define PHY_LONE_INT_STAT 0x13 /* 16 bit r/o Interrupt Status Reg */
+-#define PHY_LONE_LED_CFG 0x14 /* 16 bit r/w LED Configuration Reg */
+-#define PHY_LONE_PORT_CTRL 0x15 /* 16 bit r/w Port Control Reg */
+-#define PHY_LONE_CIM 0x16 /* 16 bit r/o CIM Reg */
+- /* 0x17 -0x1c: reserved */
+-
+-/*----------------------------------------------------------------------------*/
+-/*
+- * National-PHY Registers, indirect addressed over XMAC
+- */
+-#define PHY_NAT_CTRL 0x00 /* 16 bit r/w PHY Control Register */
+-#define PHY_NAT_STAT 0x01 /* 16 bit r/w PHY Status Register */
+-#define PHY_NAT_ID0 0x02 /* 16 bit r/o PHY ID0 Register */
+-#define PHY_NAT_ID1 0x03 /* 16 bit r/o PHY ID1 Register */
+-#define PHY_NAT_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */
+-#define PHY_NAT_AUNE_LP 0x05 /* 16 bit r/o Link Partner Ability Reg */
+-#define PHY_NAT_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */
+-#define PHY_NAT_NEPG 0x07 /* 16 bit r/w Next Page Register */
+-#define PHY_NAT_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner Reg */
+- /* National-specific registers */
+-#define PHY_NAT_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg */
+-#define PHY_NAT_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */
+- /* 0x0b -0x0e: reserved */
+-#define PHY_NAT_EXT_STAT 0x0f /* 16 bit r/o Extended Status Register */
+-#define PHY_NAT_EXT_CTRL1 0x10 /* 16 bit r/o Extended Control Reg1 */
+-#define PHY_NAT_Q_STAT1 0x11 /* 16 bit r/o Quick Status Reg1 */
+-#define PHY_NAT_10B_OP 0x12 /* 16 bit r/o 10Base-T Operations Reg */
+-#define PHY_NAT_EXT_CTRL2 0x13 /* 16 bit r/o Extended Control Reg1 */
+-#define PHY_NAT_Q_STAT2 0x14 /* 16 bit r/o Quick Status Reg2 */
+- /* 0x15 -0x18: reserved */
+-#define PHY_NAT_PHY_ADDR 0x19 /* 16 bit r/o PHY Address Register */
+-
+-
+-/*----------------------------------------------------------------------------*/
+-
+-/*
+- * PHY bit definitions
+- * Bits defined as PHY_X_..., PHY_B_..., PHY_L_... or PHY_N_... are
+- * XMAC/Broadcom/LevelOne/National/Marvell-specific.
+- * All other are general.
+- */
+-
+-/***** PHY_XMAC_CTRL 16 bit r/w PHY Control Register *****/
+-/***** PHY_BCOM_CTRL 16 bit r/w PHY Control Register *****/
+-/***** PHY_MARV_CTRL 16 bit r/w PHY Status Register *****/
+-/***** PHY_LONE_CTRL 16 bit r/w PHY Control Register *****/
+-#define PHY_CT_RESET (1<<15) /* Bit 15: (sc) clear all PHY related regs */
+-#define PHY_CT_LOOP (1<<14) /* Bit 14: enable Loopback over PHY */
+-#define PHY_CT_SPS_LSB (1<<13) /* Bit 13: (BC,L1) Speed select, lower bit */
+-#define PHY_CT_ANE (1<<12) /* Bit 12: Auto-Negotiation Enabled */
+-#define PHY_CT_PDOWN (1<<11) /* Bit 11: (BC,L1) Power Down Mode */
+-#define PHY_CT_ISOL (1<<10) /* Bit 10: (BC,L1) Isolate Mode */
+-#define PHY_CT_RE_CFG (1<<9) /* Bit 9: (sc) Restart Auto-Negotiation */
+-#define PHY_CT_DUP_MD (1<<8) /* Bit 8: Duplex Mode */
+-#define PHY_CT_COL_TST (1<<7) /* Bit 7: (BC,L1) Collision Test enabled */
+-#define PHY_CT_SPS_MSB (1<<6) /* Bit 6: (BC,L1) Speed select, upper bit */
+- /* Bit 5..0: reserved */
+-
+-#define PHY_CT_SP1000 PHY_CT_SPS_MSB /* enable speed of 1000 Mbps */
+-#define PHY_CT_SP100 PHY_CT_SPS_LSB /* enable speed of 100 Mbps */
+-#define PHY_CT_SP10 (0) /* enable speed of 10 Mbps */
+-
+-
+-/***** PHY_XMAC_STAT 16 bit r/w PHY Status Register *****/
+-/***** PHY_BCOM_STAT 16 bit r/w PHY Status Register *****/
+-/***** PHY_MARV_STAT 16 bit r/w PHY Status Register *****/
+-/***** PHY_LONE_STAT 16 bit r/w PHY Status Register *****/
+- /* Bit 15..9: reserved */
+- /* (BC/L1) 100/10 Mbps cap bits ignored*/
+-#define PHY_ST_EXT_ST (1<<8) /* Bit 8: Extended Status Present */
+- /* Bit 7: reserved */
+-#define PHY_ST_PRE_SUP (1<<6) /* Bit 6: (BC/L1) preamble suppression */
+-#define PHY_ST_AN_OVER (1<<5) /* Bit 5: Auto-Negotiation Over */
+-#define PHY_ST_REM_FLT (1<<4) /* Bit 4: Remote Fault Condition Occured */
+-#define PHY_ST_AN_CAP (1<<3) /* Bit 3: Auto-Negotiation Capability */
+-#define PHY_ST_LSYNC (1<<2) /* Bit 2: Link Synchronized */
+-#define PHY_ST_JAB_DET (1<<1) /* Bit 1: (BC/L1) Jabber Detected */
+-#define PHY_ST_EXT_REG (1<<0) /* Bit 0: Extended Register available */
+-
+-
+-/***** PHY_XMAC_ID1 16 bit r/o PHY ID1 Register */
+-/***** PHY_BCOM_ID1 16 bit r/o PHY ID1 Register */
+-/***** PHY_MARV_ID1 16 bit r/o PHY ID1 Register */
+-/***** PHY_LONE_ID1 16 bit r/o PHY ID1 Register */
+-#define PHY_I1_OUI_MSK (0x3f<<10) /* Bit 15..10: Organization Unique ID */
+-#define PHY_I1_MOD_NUM (0x3f<<4) /* Bit 9.. 4: Model Number */
+-#define PHY_I1_REV_MSK 0x0f /* Bit 3.. 0: Revision Number */
+-
+-/* different Broadcom PHY Ids */
+-#define PHY_BCOM_ID1_A1 0x6041
+-#define PHY_BCOM_ID1_B2 0x6043
+-#define PHY_BCOM_ID1_C0 0x6044
+-#define PHY_BCOM_ID1_C5 0x6047
+-
+-
+-/***** PHY_XMAC_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/
+-/***** PHY_XMAC_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/
+-#define PHY_AN_NXT_PG (1<<15) /* Bit 15: Request Next Page */
+-#define PHY_X_AN_ACK (1<<14) /* Bit 14: (ro) Acknowledge Received */
+-#define PHY_X_AN_RFB (3<<12) /* Bit 13..12: Remote Fault Bits */
+- /* Bit 11.. 9: reserved */
+-#define PHY_X_AN_PAUSE (3<<7) /* Bit 8.. 7: Pause Bits */
+-#define PHY_X_AN_HD (1<<6) /* Bit 6: Half Duplex */
+-#define PHY_X_AN_FD (1<<5) /* Bit 5: Full Duplex */
+- /* Bit 4.. 0: reserved */
+-
+-/***** PHY_BCOM_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/
+-/***** PHY_BCOM_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/
+-/* PHY_AN_NXT_PG (see XMAC) Bit 15: Request Next Page */
+- /* Bit 14: reserved */
+-#define PHY_B_AN_RF (1<<13) /* Bit 13: Remote Fault */
+- /* Bit 12: reserved */
+-#define PHY_B_AN_ASP (1<<11) /* Bit 11: Asymmetric Pause */
+-#define PHY_B_AN_PC (1<<10) /* Bit 10: Pause Capable */
+- /* Bit 9..5: 100/10 BT cap bits ingnored */
+-#define PHY_B_AN_SEL 0x1f /* Bit 4..0: Selector Field, 00001=Ethernet*/
+-
+-/***** PHY_LONE_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/
+-/***** PHY_LONE_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/
+-/* PHY_AN_NXT_PG (see XMAC) Bit 15: Request Next Page */
+- /* Bit 14: reserved */
+-#define PHY_L_AN_RF (1<<13) /* Bit 13: Remote Fault */
+- /* Bit 12: reserved */
+-#define PHY_L_AN_ASP (1<<11) /* Bit 11: Asymmetric Pause */
+-#define PHY_L_AN_PC (1<<10) /* Bit 10: Pause Capable */
+- /* Bit 9..5: 100/10 BT cap bits ingnored */
+-#define PHY_L_AN_SEL 0x1f /* Bit 4..0: Selector Field, 00001=Ethernet*/
+-
+-/***** PHY_NAT_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/
+-/***** PHY_NAT_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/
+-/* PHY_AN_NXT_PG (see XMAC) Bit 15: Request Next Page */
+- /* Bit 14: reserved */
+-#define PHY_N_AN_RF (1<<13) /* Bit 13: Remote Fault */
+- /* Bit 12: reserved */
+-#define PHY_N_AN_100F (1<<11) /* Bit 11: 100Base-T2 FD Support */
+-#define PHY_N_AN_100H (1<<10) /* Bit 10: 100Base-T2 HD Support */
+- /* Bit 9..5: 100/10 BT cap bits ingnored */
+-#define PHY_N_AN_SEL 0x1f /* Bit 4..0: Selector Field, 00001=Ethernet*/
+-
+-/* field type definition for PHY_x_AN_SEL */
+-#define PHY_SEL_TYPE 0x01 /* 00001 = Ethernet */
+-
+-/***** PHY_XMAC_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/
+- /* Bit 15..4: reserved */
+-#define PHY_ANE_LP_NP (1<<3) /* Bit 3: Link Partner can Next Page */
+-#define PHY_ANE_LOC_NP (1<<2) /* Bit 2: Local PHY can Next Page */
+-#define PHY_ANE_RX_PG (1<<1) /* Bit 1: Page Received */
+- /* Bit 0: reserved */
+-
+-/***** PHY_BCOM_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/
+-/***** PHY_LONE_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/
+-/***** PHY_MARV_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/
+- /* Bit 15..5: reserved */
+-#define PHY_ANE_PAR_DF (1<<4) /* Bit 4: Parallel Detection Fault */
+-/* PHY_ANE_LP_NP (see XMAC) Bit 3: Link Partner can Next Page */
+-/* PHY_ANE_LOC_NP (see XMAC) Bit 2: Local PHY can Next Page */
+-/* PHY_ANE_RX_PG (see XMAC) Bit 1: Page Received */
+-#define PHY_ANE_LP_CAP (1<<0) /* Bit 0: Link Partner Auto-Neg. Cap. */
+-
+-/***** PHY_XMAC_NEPG 16 bit r/w Next Page Register *****/
+-/***** PHY_BCOM_NEPG 16 bit r/w Next Page Register *****/
+-/***** PHY_LONE_NEPG 16 bit r/w Next Page Register *****/
+-/***** PHY_XMAC_NEPG_LP 16 bit r/o Next Page Link Partner *****/
+-/***** PHY_BCOM_NEPG_LP 16 bit r/o Next Page Link Partner *****/
+-/***** PHY_LONE_NEPG_LP 16 bit r/o Next Page Link Partner *****/
+-#define PHY_NP_MORE (1<<15) /* Bit 15: More, Next Pages to follow */
+-#define PHY_NP_ACK1 (1<<14) /* Bit 14: (ro) Ack1, for receiving a message */
+-#define PHY_NP_MSG_VAL (1<<13) /* Bit 13: Message Page valid */
+-#define PHY_NP_ACK2 (1<<12) /* Bit 12: Ack2, comply with msg content */
+-#define PHY_NP_TOG (1<<11) /* Bit 11: Toggle Bit, ensure sync */
+-#define PHY_NP_MSG 0x07ff /* Bit 10..0: Message from/to Link Partner */
+-
+-/*
+- * XMAC-Specific
+- */
+-/***** PHY_XMAC_EXT_STAT 16 bit r/w Extended Status Register *****/
+-#define PHY_X_EX_FD (1<<15) /* Bit 15: Device Supports Full Duplex */
+-#define PHY_X_EX_HD (1<<14) /* Bit 14: Device Supports Half Duplex */
+- /* Bit 13..0: reserved */
+-
+-/***** PHY_XMAC_RES_ABI 16 bit r/o PHY Resolved Ability *****/
+- /* Bit 15..9: reserved */
+-#define PHY_X_RS_PAUSE (3<<7) /* Bit 8..7: selected Pause Mode */
+-#define PHY_X_RS_HD (1<<6) /* Bit 6: Half Duplex Mode selected */
+-#define PHY_X_RS_FD (1<<5) /* Bit 5: Full Duplex Mode selected */
+-#define PHY_X_RS_ABLMIS (1<<4) /* Bit 4: duplex or pause cap mismatch */
+-#define PHY_X_RS_PAUMIS (1<<3) /* Bit 3: pause capability mismatch */
+- /* Bit 2..0: reserved */
+-/*
+- * Remote Fault Bits (PHY_X_AN_RFB) encoding
+- */
+-#define X_RFB_OK (0<<12) /* Bit 13..12 No errors, Link OK */
+-#define X_RFB_LF (1<<12) /* Bit 13..12 Link Failure */
+-#define X_RFB_OFF (2<<12) /* Bit 13..12 Offline */
+-#define X_RFB_AN_ERR (3<<12) /* Bit 13..12 Auto-Negotiation Error */
+-
+-/*
+- * Pause Bits (PHY_X_AN_PAUSE and PHY_X_RS_PAUSE) encoding
+- */
+-#define PHY_X_P_NO_PAUSE (0<<7) /* Bit 8..7: no Pause Mode */
+-#define PHY_X_P_SYM_MD (1<<7) /* Bit 8..7: symmetric Pause Mode */
+-#define PHY_X_P_ASYM_MD (2<<7) /* Bit 8..7: asymmetric Pause Mode */
+-#define PHY_X_P_BOTH_MD (3<<7) /* Bit 8..7: both Pause Mode */
+-
+-
+-/*
+- * Broadcom-Specific
+- */
+-/***** PHY_BCOM_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/
+-#define PHY_B_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */
+-#define PHY_B_1000C_MSE (1<<12) /* Bit 12: Master/Slave Enable */
+-#define PHY_B_1000C_MSC (1<<11) /* Bit 11: M/S Configuration */
+-#define PHY_B_1000C_RD (1<<10) /* Bit 10: Repeater/DTE */
+-#define PHY_B_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */
+-#define PHY_B_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */
+- /* Bit 7..0: reserved */
+-
+-/***** PHY_BCOM_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/
+-/***** PHY_MARV_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/
+-#define PHY_B_1000S_MSF (1<<15) /* Bit 15: Master/Slave Fault */
+-#define PHY_B_1000S_MSR (1<<14) /* Bit 14: Master/Slave Result */
+-#define PHY_B_1000S_LRS (1<<13) /* Bit 13: Local Receiver Status */
+-#define PHY_B_1000S_RRS (1<<12) /* Bit 12: Remote Receiver Status */
+-#define PHY_B_1000S_LP_FD (1<<11) /* Bit 11: Link Partner can FD */
+-#define PHY_B_1000S_LP_HD (1<<10) /* Bit 10: Link Partner can HD */
+- /* Bit 9..8: reserved */
+-#define PHY_B_1000S_IEC 0xff /* Bit 7..0: Idle Error Count */
+-
+-/***** PHY_BCOM_EXT_STAT 16 bit r/o Extended Status Register *****/
+-#define PHY_B_ES_X_FD_CAP (1<<15) /* Bit 15: 1000Base-X FD capable */
+-#define PHY_B_ES_X_HD_CAP (1<<14) /* Bit 14: 1000Base-X HD capable */
+-#define PHY_B_ES_T_FD_CAP (1<<13) /* Bit 13: 1000Base-T FD capable */
+-#define PHY_B_ES_T_HD_CAP (1<<12) /* Bit 12: 1000Base-T HD capable */
+- /* Bit 11..0: reserved */
+-
+-/***** PHY_BCOM_P_EXT_CTRL 16 bit r/w PHY Extended Control Reg *****/
+-#define PHY_B_PEC_MAC_PHY (1<<15) /* Bit 15: 10BIT/GMI-Interface */
+-#define PHY_B_PEC_DIS_CROSS (1<<14) /* Bit 14: Disable MDI Crossover */
+-#define PHY_B_PEC_TX_DIS (1<<13) /* Bit 13: Tx output Disabled */
+-#define PHY_B_PEC_INT_DIS (1<<12) /* Bit 12: Interrupts Disabled */
+-#define PHY_B_PEC_F_INT (1<<11) /* Bit 11: Force Interrupt */
+-#define PHY_B_PEC_BY_45 (1<<10) /* Bit 10: Bypass 4B5B-Decoder */
+-#define PHY_B_PEC_BY_SCR (1<<9) /* Bit 9: Bypass Scrambler */
+-#define PHY_B_PEC_BY_MLT3 (1<<8) /* Bit 8: Bypass MLT3 Encoder */
+-#define PHY_B_PEC_BY_RXA (1<<7) /* Bit 7: Bypass Rx Alignm. */
+-#define PHY_B_PEC_RES_SCR (1<<6) /* Bit 6: Reset Scrambler */
+-#define PHY_B_PEC_EN_LTR (1<<5) /* Bit 5: Ena LED Traffic Mode */
+-#define PHY_B_PEC_LED_ON (1<<4) /* Bit 4: Force LED's on */
+-#define PHY_B_PEC_LED_OFF (1<<3) /* Bit 3: Force LED's off */
+-#define PHY_B_PEC_EX_IPG (1<<2) /* Bit 2: Extend Tx IPG Mode */
+-#define PHY_B_PEC_3_LED (1<<1) /* Bit 1: Three Link LED mode */
+-#define PHY_B_PEC_HIGH_LA (1<<0) /* Bit 0: GMII FIFO Elasticy */
+-
+-/***** PHY_BCOM_P_EXT_STAT 16 bit r/o PHY Extended Status Reg *****/
+- /* Bit 15..14: reserved */
+-#define PHY_B_PES_CROSS_STAT (1<<13) /* Bit 13: MDI Crossover Status */
+-#define PHY_B_PES_INT_STAT (1<<12) /* Bit 12: Interrupt Status */
+-#define PHY_B_PES_RRS (1<<11) /* Bit 11: Remote Receiver Stat. */
+-#define PHY_B_PES_LRS (1<<10) /* Bit 10: Local Receiver Stat. */
+-#define PHY_B_PES_LOCKED (1<<9) /* Bit 9: Locked */
+-#define PHY_B_PES_LS (1<<8) /* Bit 8: Link Status */
+-#define PHY_B_PES_RF (1<<7) /* Bit 7: Remote Fault */
+-#define PHY_B_PES_CE_ER (1<<6) /* Bit 6: Carrier Ext Error */
+-#define PHY_B_PES_BAD_SSD (1<<5) /* Bit 5: Bad SSD */
+-#define PHY_B_PES_BAD_ESD (1<<4) /* Bit 4: Bad ESD */
+-#define PHY_B_PES_RX_ER (1<<3) /* Bit 3: Receive Error */
+-#define PHY_B_PES_TX_ER (1<<2) /* Bit 2: Transmit Error */
+-#define PHY_B_PES_LOCK_ER (1<<1) /* Bit 1: Lock Error */
+-#define PHY_B_PES_MLT3_ER (1<<0) /* Bit 0: MLT3 code Error */
+-
+-/***** PHY_BCOM_FC_CTR 16 bit r/w False Carrier Counter *****/
+- /* Bit 15..8: reserved */
+-#define PHY_B_FC_CTR 0xff /* Bit 7..0: False Carrier Counter */
+-
+-/***** PHY_BCOM_RNO_CTR 16 bit r/w Receive NOT_OK Counter *****/
+-#define PHY_B_RC_LOC_MSK 0xff00 /* Bit 15..8: Local Rx NOT_OK cnt */
+-#define PHY_B_RC_REM_MSK 0x00ff /* Bit 7..0: Remote Rx NOT_OK cnt */
+-
+-/***** PHY_BCOM_AUX_CTRL 16 bit r/w Auxiliary Control Reg *****/
+-#define PHY_B_AC_L_SQE (1<<15) /* Bit 15: Low Squelch */
+-#define PHY_B_AC_LONG_PACK (1<<14) /* Bit 14: Rx Long Packets */
+-#define PHY_B_AC_ER_CTRL (3<<12) /* Bit 13..12: Edgerate Control */
+- /* Bit 11: reserved */
+-#define PHY_B_AC_TX_TST (1<<10) /* Bit 10: Tx test bit, always 1 */
+- /* Bit 9.. 8: reserved */
+-#define PHY_B_AC_DIS_PRF (1<<7) /* Bit 7: dis part resp filter */
+- /* Bit 6: reserved */
+-#define PHY_B_AC_DIS_PM (1<<5) /* Bit 5: dis power management */
+- /* Bit 4: reserved */
+-#define PHY_B_AC_DIAG (1<<3) /* Bit 3: Diagnostic Mode */
+- /* Bit 2.. 0: reserved */
+-
+-/***** PHY_BCOM_AUX_STAT 16 bit r/o Auxiliary Status Reg *****/
+-#define PHY_B_AS_AN_C (1<<15) /* Bit 15: AutoNeg complete */
+-#define PHY_B_AS_AN_CA (1<<14) /* Bit 14: AN Complete Ack */
+-#define PHY_B_AS_ANACK_D (1<<13) /* Bit 13: AN Ack Detect */
+-#define PHY_B_AS_ANAB_D (1<<12) /* Bit 12: AN Ability Detect */
+-#define PHY_B_AS_NPW (1<<11) /* Bit 11: AN Next Page Wait */
+-#define PHY_B_AS_AN_RES_MSK (7<<8) /* Bit 10..8: AN HDC */
+-#define PHY_B_AS_PDF (1<<7) /* Bit 7: Parallel Detect. Fault */
+-#define PHY_B_AS_RF (1<<6) /* Bit 6: Remote Fault */
+-#define PHY_B_AS_ANP_R (1<<5) /* Bit 5: AN Page Received */
+-#define PHY_B_AS_LP_ANAB (1<<4) /* Bit 4: LP AN Ability */
+-#define PHY_B_AS_LP_NPAB (1<<3) /* Bit 3: LP Next Page Ability */
+-#define PHY_B_AS_LS (1<<2) /* Bit 2: Link Status */
+-#define PHY_B_AS_PRR (1<<1) /* Bit 1: Pause Resolution-Rx */
+-#define PHY_B_AS_PRT (1<<0) /* Bit 0: Pause Resolution-Tx */
+-
+-#define PHY_B_AS_PAUSE_MSK (PHY_B_AS_PRR | PHY_B_AS_PRT)
+-
+-/***** PHY_BCOM_INT_STAT 16 bit r/o Interrupt Status Reg *****/
+-/***** PHY_BCOM_INT_MASK 16 bit r/w Interrupt Mask Reg *****/
+- /* Bit 15: reserved */
+-#define PHY_B_IS_PSE (1<<14) /* Bit 14: Pair Swap Error */
+-#define PHY_B_IS_MDXI_SC (1<<13) /* Bit 13: MDIX Status Change */
+-#define PHY_B_IS_HCT (1<<12) /* Bit 12: counter above 32k */
+-#define PHY_B_IS_LCT (1<<11) /* Bit 11: counter above 128 */
+-#define PHY_B_IS_AN_PR (1<<10) /* Bit 10: Page Received */
+-#define PHY_B_IS_NO_HDCL (1<<9) /* Bit 9: No HCD Link */
+-#define PHY_B_IS_NO_HDC (1<<8) /* Bit 8: No HCD */
+-#define PHY_B_IS_NEG_USHDC (1<<7) /* Bit 7: Negotiated Unsup. HCD */
+-#define PHY_B_IS_SCR_S_ER (1<<6) /* Bit 6: Scrambler Sync Error */
+-#define PHY_B_IS_RRS_CHANGE (1<<5) /* Bit 5: Remote Rx Stat Change */
+-#define PHY_B_IS_LRS_CHANGE (1<<4) /* Bit 4: Local Rx Stat Change */
+-#define PHY_B_IS_DUP_CHANGE (1<<3) /* Bit 3: Duplex Mode Change */
+-#define PHY_B_IS_LSP_CHANGE (1<<2) /* Bit 2: Link Speed Change */
+-#define PHY_B_IS_LST_CHANGE (1<<1) /* Bit 1: Link Status Changed */
+-#define PHY_B_IS_CRC_ER (1<<0) /* Bit 0: CRC Error */
+-
+-#define PHY_B_DEF_MSK (~(PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE))
+-
+-/* Pause Bits (PHY_B_AN_ASP and PHY_B_AN_PC) encoding */
+-#define PHY_B_P_NO_PAUSE (0<<10) /* Bit 11..10: no Pause Mode */
+-#define PHY_B_P_SYM_MD (1<<10) /* Bit 11..10: symmetric Pause Mode */
+-#define PHY_B_P_ASYM_MD (2<<10) /* Bit 11..10: asymmetric Pause Mode */
+-#define PHY_B_P_BOTH_MD (3<<10) /* Bit 11..10: both Pause Mode */
+-
+-/*
+- * Resolved Duplex mode and Capabilities (Aux Status Summary Reg)
+- */
+-#define PHY_B_RES_1000FD (7<<8) /* Bit 10..8: 1000Base-T Full Dup. */
+-#define PHY_B_RES_1000HD (6<<8) /* Bit 10..8: 1000Base-T Half Dup. */
+-/* others: 100/10: invalid for us */
+-
+-/*
+- * Level One-Specific
+- */
+-/***** PHY_LONE_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/
+-#define PHY_L_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */
+-#define PHY_L_1000C_MSE (1<<12) /* Bit 12: Master/Slave Enable */
+-#define PHY_L_1000C_MSC (1<<11) /* Bit 11: M/S Configuration */
+-#define PHY_L_1000C_RD (1<<10) /* Bit 10: Repeater/DTE */
+-#define PHY_L_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */
+-#define PHY_L_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */
+- /* Bit 7..0: reserved */
+-
+-/***** PHY_LONE_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/
+-#define PHY_L_1000S_MSF (1<<15) /* Bit 15: Master/Slave Fault */
+-#define PHY_L_1000S_MSR (1<<14) /* Bit 14: Master/Slave Result */
+-#define PHY_L_1000S_LRS (1<<13) /* Bit 13: Local Receiver Status */
+-#define PHY_L_1000S_RRS (1<<12) /* Bit 12: Remote Receiver Status */
+-#define PHY_L_1000S_LP_FD (1<<11) /* Bit 11: Link Partner can FD */
+-#define PHY_L_1000S_LP_HD (1<<10) /* Bit 10: Link Partner can HD */
+- /* Bit 9..8: reserved */
+-#define PHY_B_1000S_IEC 0xff /* Bit 7..0: Idle Error Count */
+-
+-/***** PHY_LONE_EXT_STAT 16 bit r/o Extended Status Register *****/
+-#define PHY_L_ES_X_FD_CAP (1<<15) /* Bit 15: 1000Base-X FD capable */
+-#define PHY_L_ES_X_HD_CAP (1<<14) /* Bit 14: 1000Base-X HD capable */
+-#define PHY_L_ES_T_FD_CAP (1<<13) /* Bit 13: 1000Base-T FD capable */
+-#define PHY_L_ES_T_HD_CAP (1<<12) /* Bit 12: 1000Base-T HD capable */
+- /* Bit 11..0: reserved */
+-
+-/***** PHY_LONE_PORT_CFG 16 bit r/w Port Configuration Reg *****/
+-#define PHY_L_PC_REP_MODE (1<<15) /* Bit 15: Repeater Mode */
+- /* Bit 14: reserved */
+-#define PHY_L_PC_TX_DIS (1<<13) /* Bit 13: Tx output Disabled */
+-#define PHY_L_PC_BY_SCR (1<<12) /* Bit 12: Bypass Scrambler */
+-#define PHY_L_PC_BY_45 (1<<11) /* Bit 11: Bypass 4B5B-Decoder */
+-#define PHY_L_PC_JAB_DIS (1<<10) /* Bit 10: Jabber Disabled */
+-#define PHY_L_PC_SQE (1<<9) /* Bit 9: Enable Heartbeat */
+-#define PHY_L_PC_TP_LOOP (1<<8) /* Bit 8: TP Loopback */
+-#define PHY_L_PC_SSS (1<<7) /* Bit 7: Smart Speed Selection */
+-#define PHY_L_PC_FIFO_SIZE (1<<6) /* Bit 6: FIFO Size */
+-#define PHY_L_PC_PRE_EN (1<<5) /* Bit 5: Preamble Enable */
+-#define PHY_L_PC_CIM (1<<4) /* Bit 4: Carrier Integrity Mon */
+-#define PHY_L_PC_10_SER (1<<3) /* Bit 3: Use Serial Output */
+-#define PHY_L_PC_ANISOL (1<<2) /* Bit 2: Unisolate Port */
+-#define PHY_L_PC_TEN_BIT (1<<1) /* Bit 1: 10bit iface mode on */
+-#define PHY_L_PC_ALTCLOCK (1<<0) /* Bit 0: (ro) ALTCLOCK Mode on */
+-
+-/***** PHY_LONE_Q_STAT 16 bit r/o Quick Status Reg *****/
+-#define PHY_L_QS_D_RATE (3<<14) /* Bit 15..14: Data Rate */
+-#define PHY_L_QS_TX_STAT (1<<13) /* Bit 13: Transmitting */
+-#define PHY_L_QS_RX_STAT (1<<12) /* Bit 12: Receiving */
+-#define PHY_L_QS_COL_STAT (1<<11) /* Bit 11: Collision */
+-#define PHY_L_QS_L_STAT (1<<10) /* Bit 10: Link is up */
+-#define PHY_L_QS_DUP_MOD (1<<9) /* Bit 9: Full/Half Duplex */
+-#define PHY_L_QS_AN (1<<8) /* Bit 8: AutoNeg is On */
+-#define PHY_L_QS_AN_C (1<<7) /* Bit 7: AN is Complete */
+-#define PHY_L_QS_LLE (7<<4) /* Bit 6: Line Length Estim. */
+-#define PHY_L_QS_PAUSE (1<<3) /* Bit 3: LP advertised Pause */
+-#define PHY_L_QS_AS_PAUSE (1<<2) /* Bit 2: LP adv. asym. Pause */
+-#define PHY_L_QS_ISOLATE (1<<1) /* Bit 1: CIM Isolated */
+-#define PHY_L_QS_EVENT (1<<0) /* Bit 0: Event has occurred */
+-
+-/***** PHY_LONE_INT_ENAB 16 bit r/w Interrupt Enable Reg *****/
+-/***** PHY_LONE_INT_STAT 16 bit r/o Interrupt Status Reg *****/
+- /* Bit 15..14: reserved */
+-#define PHY_L_IS_AN_F (1<<13) /* Bit 13: Auto-Negotiation fault */
+- /* Bit 12: not described */
+-#define PHY_L_IS_CROSS (1<<11) /* Bit 11: Crossover used */
+-#define PHY_L_IS_POL (1<<10) /* Bit 10: Polarity correct. used */
+-#define PHY_L_IS_SS (1<<9) /* Bit 9: Smart Speed Downgrade */
+-#define PHY_L_IS_CFULL (1<<8) /* Bit 8: Counter Full */
+-#define PHY_L_IS_AN_C (1<<7) /* Bit 7: AutoNeg Complete */
+-#define PHY_L_IS_SPEED (1<<6) /* Bit 6: Speed Changed */
+-#define PHY_L_IS_DUP (1<<5) /* Bit 5: Duplex Changed */
+-#define PHY_L_IS_LS (1<<4) /* Bit 4: Link Status Changed */
+-#define PHY_L_IS_ISOL (1<<3) /* Bit 3: Isolate Occured */
+-#define PHY_L_IS_MDINT (1<<2) /* Bit 2: (ro) STAT: MII Int Pending */
+-#define PHY_L_IS_INTEN (1<<1) /* Bit 1: ENAB: Enable IRQs */
+-#define PHY_L_IS_FORCE (1<<0) /* Bit 0: ENAB: Force Interrupt */
+-
+-/* int. mask */
+-#define PHY_L_DEF_MSK (PHY_L_IS_LS | PHY_L_IS_ISOL | PHY_L_IS_INTEN)
+-
+-/***** PHY_LONE_LED_CFG 16 bit r/w LED Configuration Reg *****/
+-#define PHY_L_LC_LEDC (3<<14) /* Bit 15..14: Col/Blink/On/Off */
+-#define PHY_L_LC_LEDR (3<<12) /* Bit 13..12: Rx/Blink/On/Off */
+-#define PHY_L_LC_LEDT (3<<10) /* Bit 11..10: Tx/Blink/On/Off */
+-#define PHY_L_LC_LEDG (3<<8) /* Bit 9..8: Giga/Blink/On/Off */
+-#define PHY_L_LC_LEDS (3<<6) /* Bit 7..6: 10-100/Blink/On/Off */
+-#define PHY_L_LC_LEDL (3<<4) /* Bit 5..4: Link/Blink/On/Off */
+-#define PHY_L_LC_LEDF (3<<2) /* Bit 3..2: Duplex/Blink/On/Off */
+-#define PHY_L_LC_PSTRECH (1<<1) /* Bit 1: Strech LED Pulses */
+-#define PHY_L_LC_FREQ (1<<0) /* Bit 0: 30/100 ms */
+-
+-/***** PHY_LONE_PORT_CTRL 16 bit r/w Port Control Reg *****/
+-#define PHY_L_PC_TX_TCLK (1<<15) /* Bit 15: Enable TX_TCLK */
+- /* Bit 14: reserved */
+-#define PHY_L_PC_ALT_NP (1<<13) /* Bit 14: Alternate Next Page */
+-#define PHY_L_PC_GMII_ALT (1<<12) /* Bit 13: Alternate GMII driver */
+- /* Bit 11: reserved */
+-#define PHY_L_PC_TEN_CRS (1<<10) /* Bit 10: Extend CRS*/
+- /* Bit 9..0: not described */
+-
+-/***** PHY_LONE_CIM 16 bit r/o CIM Reg *****/
+-#define PHY_L_CIM_ISOL (255<<8)/* Bit 15..8: Isolate Count */
+-#define PHY_L_CIM_FALSE_CAR (255<<0)/* Bit 7..0: False Carrier Count */
+-
+-
+-/*
+- * Pause Bits (PHY_L_AN_ASP and PHY_L_AN_PC) encoding
+- */
+-#define PHY_L_P_NO_PAUSE (0<<10) /* Bit 11..10: no Pause Mode */
+-#define PHY_L_P_SYM_MD (1<<10) /* Bit 11..10: symmetric Pause Mode */
+-#define PHY_L_P_ASYM_MD (2<<10) /* Bit 11..10: asymmetric Pause Mode */
+-#define PHY_L_P_BOTH_MD (3<<10) /* Bit 11..10: both Pause Mode */
+-
+-
+-/*
+- * National-Specific
+- */
+-/***** PHY_NAT_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/
+-#define PHY_N_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */
+-#define PHY_N_1000C_MSE (1<<12) /* Bit 12: Master/Slave Enable */
+-#define PHY_N_1000C_MSC (1<<11) /* Bit 11: M/S Configuration */
+-#define PHY_N_1000C_RD (1<<10) /* Bit 10: Repeater/DTE */
+-#define PHY_N_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */
+-#define PHY_N_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */
+-#define PHY_N_1000C_APC (1<<7) /* Bit 7: Asymmetric Pause Cap. */
+- /* Bit 6..0: reserved */
+-
+-/***** PHY_NAT_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/
+-#define PHY_N_1000S_MSF (1<<15) /* Bit 15: Master/Slave Fault */
+-#define PHY_N_1000S_MSR (1<<14) /* Bit 14: Master/Slave Result */
+-#define PHY_N_1000S_LRS (1<<13) /* Bit 13: Local Receiver Status */
+-#define PHY_N_1000S_RRS (1<<12) /* Bit 12: Remote Receiver Status*/
+-#define PHY_N_1000S_LP_FD (1<<11) /* Bit 11: Link Partner can FD */
+-#define PHY_N_1000S_LP_HD (1<<10) /* Bit 10: Link Partner can HD */
+-#define PHY_N_1000C_LP_APC (1<<9) /* Bit 9: LP Asym. Pause Cap. */
+- /* Bit 8: reserved */
+-#define PHY_N_1000S_IEC 0xff /* Bit 7..0: Idle Error Count */
+-
+-/***** PHY_NAT_EXT_STAT 16 bit r/o Extended Status Register *****/
+-#define PHY_N_ES_X_FD_CAP (1<<15) /* Bit 15: 1000Base-X FD capable */
+-#define PHY_N_ES_X_HD_CAP (1<<14) /* Bit 14: 1000Base-X HD capable */
+-#define PHY_N_ES_T_FD_CAP (1<<13) /* Bit 13: 1000Base-T FD capable */
+-#define PHY_N_ES_T_HD_CAP (1<<12) /* Bit 12: 1000Base-T HD capable */
+- /* Bit 11..0: reserved */
+-
+-/* todo: those are still missing */
+-/***** PHY_NAT_EXT_CTRL1 16 bit r/o Extended Control Reg1 *****/
+-/***** PHY_NAT_Q_STAT1 16 bit r/o Quick Status Reg1 *****/
+-/***** PHY_NAT_10B_OP 16 bit r/o 10Base-T Operations Reg *****/
+-/***** PHY_NAT_EXT_CTRL2 16 bit r/o Extended Control Reg1 *****/
+-/***** PHY_NAT_Q_STAT2 16 bit r/o Quick Status Reg2 *****/
+-/***** PHY_NAT_PHY_ADDR 16 bit r/o PHY Address Register *****/
+-
+-/*
+- * Marvell-Specific
+- */
+-/***** PHY_MARV_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/
+-/***** PHY_MARV_AUNE_LP 16 bit r/w Link Part Ability Reg *****/
+-#define PHY_M_AN_NXT_PG BIT_15 /* Request Next Page */
+-#define PHY_M_AN_ACK BIT_14 /* (ro) Acknowledge Received */
+-#define PHY_M_AN_RF BIT_13 /* Remote Fault */
+- /* Bit 12: reserved */
+-#define PHY_M_AN_ASP BIT_11 /* Asymmetric Pause */
+-#define PHY_M_AN_PC BIT_10 /* MAC Pause implemented */
+-#define PHY_M_AN_100_FD BIT_8 /* Advertise 100Base-TX Full Duplex */
+-#define PHY_M_AN_100_HD BIT_7 /* Advertise 100Base-TX Half Duplex */
+-#define PHY_M_AN_10_FD BIT_6 /* Advertise 10Base-TX Full Duplex */
+-#define PHY_M_AN_10_HD BIT_5 /* Advertise 10Base-TX Half Duplex */
+-
+-/* special defines for FIBER (88E1011S only) */
+-#define PHY_M_AN_ASP_X BIT_8 /* Asymmetric Pause */
+-#define PHY_M_AN_PC_X BIT_7 /* MAC Pause implemented */
+-#define PHY_M_AN_1000X_AHD BIT_6 /* Advertise 10000Base-X Half Duplex */
+-#define PHY_M_AN_1000X_AFD BIT_5 /* Advertise 10000Base-X Full Duplex */
+-
+-/* Pause Bits (PHY_M_AN_ASP_X and PHY_M_AN_PC_X) encoding */
+-#define PHY_M_P_NO_PAUSE_X (0<<7) /* Bit 8.. 7: no Pause Mode */
+-#define PHY_M_P_SYM_MD_X (1<<7) /* Bit 8.. 7: symmetric Pause Mode */
+-#define PHY_M_P_ASYM_MD_X (2<<7) /* Bit 8.. 7: asymmetric Pause Mode */
+-#define PHY_M_P_BOTH_MD_X (3<<7) /* Bit 8.. 7: both Pause Mode */
+-
+-/***** PHY_MARV_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/
+-#define PHY_M_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */
+-#define PHY_M_1000C_MSE (1<<12) /* Bit 12: Manual Master/Slave Enable */
+-#define PHY_M_1000C_MSC (1<<11) /* Bit 11: M/S Configuration (1=Master) */
+-#define PHY_M_1000C_MPD (1<<10) /* Bit 10: Multi-Port Device */
+-#define PHY_M_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */
+-#define PHY_M_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */
+- /* Bit 7..0: reserved */
+-
+-/***** PHY_MARV_PHY_CTRL 16 bit r/w PHY Specific Ctrl Reg *****/
+-#define PHY_M_PC_TX_FFD_MSK (3<<14) /* Bit 15..14: Tx FIFO Depth Mask */
+-#define PHY_M_PC_RX_FFD_MSK (3<<12) /* Bit 13..12: Rx FIFO Depth Mask */
+-#define PHY_M_PC_ASS_CRS_TX (1<<11) /* Bit 11: Assert CRS on Transmit */
+-#define PHY_M_PC_FL_GOOD (1<<10) /* Bit 10: Force Link Good */
+-#define PHY_M_PC_EN_DET_MSK (3<<8) /* Bit 9.. 8: Energy Detect Mask */
+-#define PHY_M_PC_ENA_EXT_D (1<<7) /* Bit 7: Enable Ext. Distance (10BT) */
+-#define PHY_M_PC_MDIX_MSK (3<<5) /* Bit 6.. 5: MDI/MDIX Config. Mask */
+-#define PHY_M_PC_DIS_125CLK (1<<4) /* Bit 4: Disable 125 CLK */
+-#define PHY_M_PC_MAC_POW_UP (1<<3) /* Bit 3: MAC Power up */
+-#define PHY_M_PC_SQE_T_ENA (1<<2) /* Bit 2: SQE Test Enabled */
+-#define PHY_M_PC_POL_R_DIS (1<<1) /* Bit 1: Polarity Reversal Disabled */
+-#define PHY_M_PC_DIS_JABBER (1<<0) /* Bit 0: Disable Jabber */
+-
+-#define PHY_M_PC_EN_DET SHIFT8(2) /* Energy Detect (Mode 1) */
+-#define PHY_M_PC_EN_DET_PLUS SHIFT8(3) /* Energy Detect Plus (Mode 2) */
+-
+-#define PHY_M_PC_MDI_XMODE(x) SHIFT5(x)
+-#define PHY_M_PC_MAN_MDI 0 /* 00 = Manual MDI configuration */
+-#define PHY_M_PC_MAN_MDIX 1 /* 01 = Manual MDIX configuration */
+-#define PHY_M_PC_ENA_AUTO 3 /* 11 = Enable Automatic Crossover */
+-
+-/***** PHY_MARV_PHY_STAT 16 bit r/o PHY Specific Status Reg *****/
+-#define PHY_M_PS_SPEED_MSK (3<<14) /* Bit 15..14: Speed Mask */
+-#define PHY_M_PS_SPEED_1000 (1<<15) /* 10 = 1000 Mbps */
+-#define PHY_M_PS_SPEED_100 (1<<14) /* 01 = 100 Mbps */
+-#define PHY_M_PS_SPEED_10 0 /* 00 = 10 Mbps */
+-#define PHY_M_PS_FULL_DUP (1<<13) /* Bit 13: Full Duplex */
+-#define PHY_M_PS_PAGE_REC (1<<12) /* Bit 12: Page Received */
+-#define PHY_M_PS_SPDUP_RES (1<<11) /* Bit 11: Speed & Duplex Resolved */
+-#define PHY_M_PS_LINK_UP (1<<10) /* Bit 10: Link Up */
+-#define PHY_M_PS_CABLE_MSK (3<<7) /* Bit 9.. 7: Cable Length Mask */
+-#define PHY_M_PS_MDI_X_STAT (1<<6) /* Bit 6: MDI Crossover Stat (1=MDIX) */
+-#define PHY_M_PS_DOWNS_STAT (1<<5) /* Bit 5: Downshift Status (1=downsh.) */
+-#define PHY_M_PS_ENDET_STAT (1<<4) /* Bit 4: Energy Detect Status (1=act) */
+-#define PHY_M_PS_TX_P_EN (1<<3) /* Bit 3: Tx Pause Enabled */
+-#define PHY_M_PS_RX_P_EN (1<<2) /* Bit 2: Rx Pause Enabled */
+-#define PHY_M_PS_POL_REV (1<<1) /* Bit 1: Polarity Reversed */
+-#define PHY_M_PC_JABBER (1<<0) /* Bit 0: Jabber */
+-
+-#define PHY_M_PS_PAUSE_MSK (PHY_M_PS_TX_P_EN | PHY_M_PS_RX_P_EN)
+-
+-/***** PHY_MARV_INT_MASK 16 bit r/w Interrupt Mask Reg *****/
+-/***** PHY_MARV_INT_STAT 16 bit r/o Interrupt Status Reg *****/
+-#define PHY_M_IS_AN_ERROR (1<<15) /* Bit 15: Auto-Negotiation Error */
+-#define PHY_M_IS_LSP_CHANGE (1<<14) /* Bit 14: Link Speed Changed */
+-#define PHY_M_IS_DUP_CHANGE (1<<13) /* Bit 13: Duplex Mode Changed */
+-#define PHY_M_IS_AN_PR (1<<12) /* Bit 12: Page Received */
+-#define PHY_M_IS_AN_COMPL (1<<11) /* Bit 11: Auto-Negotiation Completed */
+-#define PHY_M_IS_LST_CHANGE (1<<10) /* Bit 10: Link Status Changed */
+-#define PHY_M_IS_SYMB_ERROR (1<<9) /* Bit 9: Symbol Error */
+-#define PHY_M_IS_FALSE_CARR (1<<8) /* Bit 8: False Carrier */
+-#define PHY_M_IS_FIFO_ERROR (1<<7) /* Bit 7: FIFO Overflow/Underrun Error */
+-#define PHY_M_IS_MDI_CHANGE (1<<6) /* Bit 6: MDI Crossover Changed */
+-#define PHY_M_IS_DOWNSH_DET (1<<5) /* Bit 5: Downshift Detected */
+-#define PHY_M_IS_END_CHANGE (1<<4) /* Bit 4: Energy Detect Changed */
+- /* Bit 3..2: reserved */
+-#define PHY_M_IS_POL_CHANGE (1<<1) /* Bit 1: Polarity Changed */
+-#define PHY_M_IS_JABBER (1<<0) /* Bit 0: Jabber */
+-
+-#define PHY_M_DEF_MSK (PHY_M_IS_AN_ERROR | PHY_M_IS_AN_PR | \
+- PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR)
+-
+-/***** PHY_MARV_EXT_CTRL 16 bit r/w Ext. PHY Specific Ctrl *****/
+-#define PHY_M_EC_M_DSC_MSK (3<<10) /* Bit 11..10: Master downshift counter */
+-#define PHY_M_EC_S_DSC_MSK (3<<8) /* Bit 9.. 8: Slave downshift counter */
+-#define PHY_M_EC_MAC_S_MSK (7<<4) /* Bit 6.. 4: Def. MAC interface speed */
+-#define PHY_M_EC_FIB_AN_ENA (1<<3) /* Bit 3: Fiber Auto-Neg. Enable */
+-
+-#define PHY_M_EC_M_DSC(x) SHIFT10(x) /* 00=1x; 01=2x; 10=3x; 11=4x */
+-#define PHY_M_EC_S_DSC(x) SHIFT8(x) /* 00=dis; 01=1x; 10=2x; 11=3x */
+-#define PHY_M_EC_MAC_S(x) SHIFT4(x) /* 01X=0; 110=2.5; 111=25 (MHz) */
+-
+-#define MAC_TX_CLK_0_MHZ 2
+-#define MAC_TX_CLK_2_5_MHZ 6
+-#define MAC_TX_CLK_25_MHZ 7
+-
+-/***** PHY_MARV_LED_CTRL 16 bit r/w LED Control Reg *****/
+-#define PHY_M_LEDC_DIS_LED (1<<15) /* Bit 15: Disable LED */
+-#define PHY_M_LEDC_PULS_MSK (7<<12) /* Bit 14..12: Pulse Stretch Mask */
+-#define PHY_M_LEDC_F_INT (1<<11) /* Bit 11: Force Interrupt */
+-#define PHY_M_LEDC_BL_R_MSK (7<<8) /* Bit 10.. 8: Blink Rate Mask */
+- /* Bit 7.. 5: reserved */
+-#define PHY_M_LEDC_LINK_MSK (3<<3) /* Bit 4.. 3: Link Control Mask */
+-#define PHY_M_LEDC_DP_CTRL (1<<2) /* Bit 2: Duplex Control */
+-#define PHY_M_LEDC_RX_CTRL (1<<1) /* Bit 1: Rx activity / Link */
+-#define PHY_M_LEDC_TX_CTRL (1<<0) /* Bit 0: Tx activity / Link */
+-
+-#define PHY_M_LED_PULS_DUR(x) SHIFT12(x) /* Pulse Stretch Duration */
+-
+-#define PULS_NO_STR 0 /* no pulse stretching */
+-#define PULS_21MS 1 /* 21 ms to 42 ms */
+-#define PULS_42MS 2 /* 42 ms to 84 ms */
+-#define PULS_84MS 3 /* 84 ms to 170 ms */
+-#define PULS_170MS 4 /* 170 ms to 340 ms */
+-#define PULS_340MS 5 /* 340 ms to 670 ms */
+-#define PULS_670MS 6 /* 670 ms to 1.3 s */
+-#define PULS_1300MS 7 /* 1.3 s to 2.7 s */
+-
+-#define PHY_M_LED_BLINK_RT(x) SHIFT8(x) /* Blink Rate */
+-
+-#define BLINK_42MS 0 /* 42 ms */
+-#define BLINK_84MS 1 /* 84 ms */
+-#define BLINK_170MS 2 /* 170 ms */
+-#define BLINK_340MS 3 /* 340 ms */
+-#define BLINK_670MS 4 /* 670 ms */
+- /* values 5 - 7: reserved */
+-
+-/***** PHY_MARV_LED_OVER 16 bit r/w Manual LED Override Reg *****/
+-#define PHY_M_LED_MO_DUP(x) SHIFT10(x) /* Bit 11..10: Duplex */
+-#define PHY_M_LED_MO_10(x) SHIFT8(x) /* Bit 9.. 8: Link 10 */
+-#define PHY_M_LED_MO_100(x) SHIFT6(x) /* Bit 7.. 6: Link 100 */
+-#define PHY_M_LED_MO_1000(x) SHIFT4(x) /* Bit 5.. 4: Link 1000 */
+-#define PHY_M_LED_MO_RX(x) SHIFT2(x) /* Bit 3.. 2: Rx */
+-#define PHY_M_LED_MO_TX(x) SHIFT0(x) /* Bit 1.. 0: Tx */
+-
+-#define MO_LED_NORM 0
+-#define MO_LED_BLINK 1
+-#define MO_LED_OFF 2
+-#define MO_LED_ON 3
+-
+-/***** PHY_MARV_EXT_CTRL_2 16 bit r/w Ext. PHY Specific Ctrl 2 *****/
+- /* Bit 15.. 7: reserved */
+-#define PHY_M_EC2_FI_IMPED (1<<6) /* Bit 6: Fiber Input Impedance */
+-#define PHY_M_EC2_FO_IMPED (1<<5) /* Bit 5: Fiber Output Impedance */
+-#define PHY_M_EC2_FO_M_CLK (1<<4) /* Bit 4: Fiber Mode Clock Enable */
+-#define PHY_M_EC2_FO_BOOST (1<<3) /* Bit 3: Fiber Output Boost */
+-#define PHY_M_EC2_FO_AM_MSK 7 /* Bit 2.. 0: Fiber Output Amplitude */
+-
+-/***** PHY_MARV_EXT_P_STAT 16 bit r/w Ext. PHY Specific Status *****/
+-#define PHY_M_FC_AUTO_SEL (1<<15) /* Bit 15: Fiber/Copper Auto Sel. dis. */
+-#define PHY_M_FC_AN_REG_ACC (1<<14) /* Bit 14: Fiber/Copper Autoneg. reg acc */
+-#define PHY_M_FC_RESULUTION (1<<13) /* Bit 13: Fiber/Copper Resulution */
+-#define PHY_M_SER_IF_AN_BP (1<<12) /* Bit 12: Ser IF autoneg. bypass enable */
+-#define PHY_M_SER_IF_BP_ST (1<<11) /* Bit 11: Ser IF autoneg. bypass status */
+-#define PHY_M_IRQ_POLARITY (1<<10) /* Bit 10: IRQ polarity */
+- /* Bit 9..4: reserved */
+-#define PHY_M_UNDOC1 (1<< 7) /* undocumented bit !! */
+-#define PHY_M_MODE_MASK (0xf<<0)/* Bit 3..0: copy of HWCFG MODE[3:0] */
+-
+-
+-/***** PHY_MARV_CABLE_DIAG 16 bit r/o Cable Diagnostic Reg *****/
+-#define PHY_M_CABD_ENA_TEST (1<<15) /* Bit 15: Enable Test */
+-#define PHY_M_CABD_STAT_MSK (3<<13) /* Bit 14..13: Status */
+- /* Bit 12.. 8: reserved */
+-#define PHY_M_CABD_DIST_MSK 0xff /* Bit 7.. 0: Distance */
+-
+-/* values for Cable Diagnostic Status (11=fail; 00=OK; 10=open; 01=short) */
+-#define CABD_STAT_NORMAL 0
+-#define CABD_STAT_SHORT 1
+-#define CABD_STAT_OPEN 2
+-#define CABD_STAT_FAIL 3
+-
+-
+-/*
+- * GMAC registers
+- *
+- * The GMAC registers are 16 or 32 bits wide.
+- * The GMACs host processor interface is 16 bits wide,
+- * therefore ALL registers will be addressed with 16 bit accesses.
+- *
+- * The following macros are provided to access the GMAC registers
+- * GM_IN16(), GM_OUT16, GM_IN32(), GM_OUT32(), GM_INADR(), GM_OUTADR(),
+- * GM_INHASH(), and GM_OUTHASH().
+- * The macros are defined in SkGeHw.h.
+- *
+- * Note: NA reg = Network Address e.g DA, SA etc.
+- *
+- */
+-
+-/* Port Registers */
+-#define GM_GP_STAT 0x0000 /* 16 bit r/o General Purpose Status */
+-#define GM_GP_CTRL 0x0004 /* 16 bit r/w General Purpose Control */
+-#define GM_TX_CTRL 0x0008 /* 16 bit r/w Transmit Control Reg. */
+-#define GM_RX_CTRL 0x000c /* 16 bit r/w Receive Control Reg. */
+-#define GM_TX_FLOW_CTRL 0x0010 /* 16 bit r/w Transmit Flow-Control */
+-#define GM_TX_PARAM 0x0014 /* 16 bit r/w Transmit Parameter Reg. */
+-#define GM_SERIAL_MODE 0x0018 /* 16 bit r/w Serial Mode Register */
+-
+-/* Source Address Registers */
+-#define GM_SRC_ADDR_1L 0x001c /* 16 bit r/w Source Address 1 (low) */
+-#define GM_SRC_ADDR_1M 0x0020 /* 16 bit r/w Source Address 1 (middle) */
+-#define GM_SRC_ADDR_1H 0x0024 /* 16 bit r/w Source Address 1 (high) */
+-#define GM_SRC_ADDR_2L 0x0028 /* 16 bit r/w Source Address 2 (low) */
+-#define GM_SRC_ADDR_2M 0x002c /* 16 bit r/w Source Address 2 (middle) */
+-#define GM_SRC_ADDR_2H 0x0030 /* 16 bit r/w Source Address 2 (high) */
+-
+-/* Multicast Address Hash Registers */
+-#define GM_MC_ADDR_H1 0x0034 /* 16 bit r/w Multicast Address Hash 1 */
+-#define GM_MC_ADDR_H2 0x0038 /* 16 bit r/w Multicast Address Hash 2 */
+-#define GM_MC_ADDR_H3 0x003c /* 16 bit r/w Multicast Address Hash 3 */
+-#define GM_MC_ADDR_H4 0x0040 /* 16 bit r/w Multicast Address Hash 4 */
+-
+-/* Interrupt Source Registers */
+-#define GM_TX_IRQ_SRC 0x0044 /* 16 bit r/o Tx Overflow IRQ Source */
+-#define GM_RX_IRQ_SRC 0x0048 /* 16 bit r/o Rx Overflow IRQ Source */
+-#define GM_TR_IRQ_SRC 0x004c /* 16 bit r/o Tx/Rx Over. IRQ Source */
+-
+-/* Interrupt Mask Registers */
+-#define GM_TX_IRQ_MSK 0x0050 /* 16 bit r/w Tx Overflow IRQ Mask */
+-#define GM_RX_IRQ_MSK 0x0054 /* 16 bit r/w Rx Overflow IRQ Mask */
+-#define GM_TR_IRQ_MSK 0x0058 /* 16 bit r/w Tx/Rx Over. IRQ Mask */
+-
+-/* Serial Management Interface (SMI) Registers */
+-#define GM_SMI_CTRL 0x0080 /* 16 bit r/w SMI Control Register */
+-#define GM_SMI_DATA 0x0084 /* 16 bit r/w SMI Data Register */
+-#define GM_PHY_ADDR 0x0088 /* 16 bit r/w GPHY Address Register */
+-
+-/* MIB Counters */
+-#define GM_MIB_CNT_BASE 0x0100 /* Base Address of MIB Counters */
+-#define GM_MIB_CNT_SIZE 44 /* Number of MIB Counters */
+-
+-/*
+- * MIB Counters base address definitions (low word) -
+- * use offset 4 for access to high word (32 bit r/o)
+- */
+-#define GM_RXF_UC_OK \
+- (GM_MIB_CNT_BASE + 0) /* Unicast Frames Received OK */
+-#define GM_RXF_BC_OK \
+- (GM_MIB_CNT_BASE + 8) /* Broadcast Frames Received OK */
+-#define GM_RXF_MPAUSE \
+- (GM_MIB_CNT_BASE + 16) /* Pause MAC Ctrl Frames Received */
+-#define GM_RXF_MC_OK \
+- (GM_MIB_CNT_BASE + 24) /* Multicast Frames Received OK */
+-#define GM_RXF_FCS_ERR \
+- (GM_MIB_CNT_BASE + 32) /* Rx Frame Check Seq. Error */
+- /* GM_MIB_CNT_BASE + 40: reserved */
+-#define GM_RXO_OK_LO \
+- (GM_MIB_CNT_BASE + 48) /* Octets Received OK Low */
+-#define GM_RXO_OK_HI \
+- (GM_MIB_CNT_BASE + 56) /* Octets Received OK High */
+-#define GM_RXO_ERR_LO \
+- (GM_MIB_CNT_BASE + 64) /* Octets Received Invalid Low */
+-#define GM_RXO_ERR_HI \
+- (GM_MIB_CNT_BASE + 72) /* Octets Received Invalid High */
+-#define GM_RXF_SHT \
+- (GM_MIB_CNT_BASE + 80) /* Frames <64 Byte Received OK */
+-#define GM_RXE_FRAG \
+- (GM_MIB_CNT_BASE + 88) /* Frames <64 Byte Received with FCS Err */
+-#define GM_RXF_64B \
+- (GM_MIB_CNT_BASE + 96) /* 64 Byte Rx Frame */
+-#define GM_RXF_127B \
+- (GM_MIB_CNT_BASE + 104) /* 65-127 Byte Rx Frame */
+-#define GM_RXF_255B \
+- (GM_MIB_CNT_BASE + 112) /* 128-255 Byte Rx Frame */
+-#define GM_RXF_511B \
+- (GM_MIB_CNT_BASE + 120) /* 256-511 Byte Rx Frame */
+-#define GM_RXF_1023B \
+- (GM_MIB_CNT_BASE + 128) /* 512-1023 Byte Rx Frame */
+-#define GM_RXF_1518B \
+- (GM_MIB_CNT_BASE + 136) /* 1024-1518 Byte Rx Frame */
+-#define GM_RXF_MAX_SZ \
+- (GM_MIB_CNT_BASE + 144) /* 1519-MaxSize Byte Rx Frame */
+-#define GM_RXF_LNG_ERR \
+- (GM_MIB_CNT_BASE + 152) /* Rx Frame too Long Error */
+-#define GM_RXF_JAB_PKT \
+- (GM_MIB_CNT_BASE + 160) /* Rx Jabber Packet Frame */
+- /* GM_MIB_CNT_BASE + 168: reserved */
+-#define GM_RXE_FIFO_OV \
+- (GM_MIB_CNT_BASE + 176) /* Rx FIFO overflow Event */
+- /* GM_MIB_CNT_BASE + 184: reserved */
+-#define GM_TXF_UC_OK \
+- (GM_MIB_CNT_BASE + 192) /* Unicast Frames Xmitted OK */
+-#define GM_TXF_BC_OK \
+- (GM_MIB_CNT_BASE + 200) /* Broadcast Frames Xmitted OK */
+-#define GM_TXF_MPAUSE \
+- (GM_MIB_CNT_BASE + 208) /* Pause MAC Ctrl Frames Xmitted */
+-#define GM_TXF_MC_OK \
+- (GM_MIB_CNT_BASE + 216) /* Multicast Frames Xmitted OK */
+-#define GM_TXO_OK_LO \
+- (GM_MIB_CNT_BASE + 224) /* Octets Transmitted OK Low */
+-#define GM_TXO_OK_HI \
+- (GM_MIB_CNT_BASE + 232) /* Octets Transmitted OK High */
+-#define GM_TXF_64B \
+- (GM_MIB_CNT_BASE + 240) /* 64 Byte Tx Frame */
+-#define GM_TXF_127B \
+- (GM_MIB_CNT_BASE + 248) /* 65-127 Byte Tx Frame */
+-#define GM_TXF_255B \
+- (GM_MIB_CNT_BASE + 256) /* 128-255 Byte Tx Frame */
+-#define GM_TXF_511B \
+- (GM_MIB_CNT_BASE + 264) /* 256-511 Byte Tx Frame */
+-#define GM_TXF_1023B \
+- (GM_MIB_CNT_BASE + 272) /* 512-1023 Byte Tx Frame */
+-#define GM_TXF_1518B \
+- (GM_MIB_CNT_BASE + 280) /* 1024-1518 Byte Tx Frame */
+-#define GM_TXF_MAX_SZ \
+- (GM_MIB_CNT_BASE + 288) /* 1519-MaxSize Byte Tx Frame */
+- /* GM_MIB_CNT_BASE + 296: reserved */
+-#define GM_TXF_COL \
+- (GM_MIB_CNT_BASE + 304) /* Tx Collision */
+-#define GM_TXF_LAT_COL \
+- (GM_MIB_CNT_BASE + 312) /* Tx Late Collision */
+-#define GM_TXF_ABO_COL \
+- (GM_MIB_CNT_BASE + 320) /* Tx aborted due to Exces. Col. */
+-#define GM_TXF_MUL_COL \
+- (GM_MIB_CNT_BASE + 328) /* Tx Multiple Collision */
+-#define GM_TXF_SNG_COL \
+- (GM_MIB_CNT_BASE + 336) /* Tx Single Collision */
+-#define GM_TXE_FIFO_UR \
+- (GM_MIB_CNT_BASE + 344) /* Tx FIFO Underrun Event */
+-
+-/*----------------------------------------------------------------------------*/
+-/*
+- * GMAC Bit Definitions
+- *
+- * If the bit access behaviour differs from the register access behaviour
+- * (r/w, r/o) this is documented after the bit number.
+- * The following bit access behaviours are used:
+- * (sc) self clearing
+- * (r/o) read only
+- */
+-
+-/* GM_GP_STAT 16 bit r/o General Purpose Status Register */
+-#define GM_GPSR_SPEED (1<<15) /* Bit 15: Port Speed (1 = 100 Mbps) */
+-#define GM_GPSR_DUPLEX (1<<14) /* Bit 14: Duplex Mode (1 = Full) */
+-#define GM_GPSR_FC_TX_DIS (1<<13) /* Bit 13: Tx Flow-Control Mode Disabled */
+-#define GM_GPSR_LINK_UP (1<<12) /* Bit 12: Link Up Status */
+-#define GM_GPSR_PAUSE (1<<11) /* Bit 11: Pause State */
+-#define GM_GPSR_TX_ACTIVE (1<<10) /* Bit 10: Tx in Progress */
+-#define GM_GPSR_EXC_COL (1<<9) /* Bit 9: Excessive Collisions Occured */
+-#define GM_GPSR_LAT_COL (1<<8) /* Bit 8: Late Collisions Occured */
+- /* Bit 7..6: reserved */
+-#define GM_GPSR_PHY_ST_CH (1<<5) /* Bit 5: PHY Status Change */
+-#define GM_GPSR_GIG_SPEED (1<<4) /* Bit 4: Gigabit Speed (1 = 1000 Mbps) */
+-#define GM_GPSR_PART_MODE (1<<3) /* Bit 3: Partition mode */
+-#define GM_GPSR_FC_RX_DIS (1<<2) /* Bit 2: Rx Flow-Control Mode Disabled */
+-#define GM_GPSR_PROM_EN (1<<1) /* Bit 1: Promiscuous Mode Enabled */
+- /* Bit 0: reserved */
+-
+-/* GM_GP_CTRL 16 bit r/w General Purpose Control Register */
+- /* Bit 15: reserved */
+-#define GM_GPCR_PROM_ENA (1<<14) /* Bit 14: Enable Promiscuous Mode */
+-#define GM_GPCR_FC_TX_DIS (1<<13) /* Bit 13: Disable Tx Flow-Control Mode */
+-#define GM_GPCR_TX_ENA (1<<12) /* Bit 12: Enable Transmit */
+-#define GM_GPCR_RX_ENA (1<<11) /* Bit 11: Enable Receive */
+-#define GM_GPCR_BURST_ENA (1<<10) /* Bit 10: Enable Burst Mode */
+-#define GM_GPCR_LOOP_ENA (1<<9) /* Bit 9: Enable MAC Loopback Mode */
+-#define GM_GPCR_PART_ENA (1<<8) /* Bit 8: Enable Partition Mode */
+-#define GM_GPCR_GIGS_ENA (1<<7) /* Bit 7: Gigabit Speed (1000 Mbps) */
+-#define GM_GPCR_FL_PASS (1<<6) /* Bit 6: Force Link Pass */
+-#define GM_GPCR_DUP_FULL (1<<5) /* Bit 5: Full Duplex Mode */
+-#define GM_GPCR_FC_RX_DIS (1<<4) /* Bit 4: Disable Rx Flow-Control Mode */
+-#define GM_GPCR_SPEED_100 (1<<3) /* Bit 3: Port Speed 100 Mbps */
+-#define GM_GPCR_AU_DUP_DIS (1<<2) /* Bit 2: Disable Auto-Update Duplex */
+-#define GM_GPCR_AU_FCT_DIS (1<<1) /* Bit 1: Disable Auto-Update Flow-C. */
+-#define GM_GPCR_AU_SPD_DIS (1<<0) /* Bit 0: Disable Auto-Update Speed */
+-
+-#define GM_GPCR_SPEED_1000 (GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100)
+-#define GM_GPCR_AU_ALL_DIS (GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS |\
+- GM_GPCR_AU_SPD_DIS)
+-
+-/* GM_TX_CTRL 16 bit r/w Transmit Control Register */
+-#define GM_TXCR_FORCE_JAM (1<<15) /* Bit 15: Force Jam / Flow-Control */
+-#define GM_TXCR_CRC_DIS (1<<14) /* Bit 14: Disable insertion of CRC */
+-#define GM_TXCR_PAD_DIS (1<<13) /* Bit 13: Disable padding of packets */
+-#define GM_TXCR_COL_THR_MSK (7<<10) /* Bit 12..10: Collision Threshold */
+-
+-#define TX_COL_THR(x) (SHIFT10(x) & GM_TXCR_COL_THR_MSK)
+-
+-#define TX_COL_DEF 0x04
+-
+-/* GM_RX_CTRL 16 bit r/w Receive Control Register */
+-#define GM_RXCR_UCF_ENA (1<<15) /* Bit 15: Enable Unicast filtering */
+-#define GM_RXCR_MCF_ENA (1<<14) /* Bit 14: Enable Multicast filtering */
+-#define GM_RXCR_CRC_DIS (1<<13) /* Bit 13: Remove 4-byte CRC */
+-#define GM_RXCR_PASS_FC (1<<12) /* Bit 12: Pass FC packets to FIFO */
+-
+-/* GM_TX_PARAM 16 bit r/w Transmit Parameter Register */
+-#define GM_TXPA_JAMLEN_MSK (0x03<<14) /* Bit 15..14: Jam Length */
+-#define GM_TXPA_JAMIPG_MSK (0x1f<<9) /* Bit 13..9: Jam IPG */
+-#define GM_TXPA_JAMDAT_MSK (0x1f<<4) /* Bit 8..4: IPG Jam to Data */
+- /* Bit 3..0: reserved */
+-
+-#define TX_JAM_LEN_VAL(x) (SHIFT14(x) & GM_TXPA_JAMLEN_MSK)
+-#define TX_JAM_IPG_VAL(x) (SHIFT9(x) & GM_TXPA_JAMIPG_MSK)
+-#define TX_IPG_JAM_DATA(x) (SHIFT4(x) & GM_TXPA_JAMDAT_MSK)
+-
+-#define TX_JAM_LEN_DEF 0x03
+-#define TX_JAM_IPG_DEF 0x0b
+-#define TX_IPG_JAM_DEF 0x1c
+-
+-/* GM_SERIAL_MODE 16 bit r/w Serial Mode Register */
+-#define GM_SMOD_DATABL_MSK (0x1f<<11) /* Bit 15..11: Data Blinder (r/o) */
+-#define GM_SMOD_LIMIT_4 (1<<10) /* Bit 10: 4 consecutive Tx trials */
+-#define GM_SMOD_VLAN_ENA (1<<9) /* Bit 9: Enable VLAN (Max. Frame Len) */
+-#define GM_SMOD_JUMBO_ENA (1<<8) /* Bit 8: Enable Jumbo (Max. Frame Len) */
+- /* Bit 7..5: reserved */
+-#define GM_SMOD_IPG_MSK 0x1f /* Bit 4..0: Inter-Packet Gap (IPG) */
+-
+-#define DATA_BLIND_VAL(x) (SHIFT11(x) & GM_SMOD_DATABL_MSK)
+-#define DATA_BLIND_DEF 0x04
+-
+-#define IPG_DATA_VAL(x) (x & GM_SMOD_IPG_MSK)
+-#define IPG_DATA_DEF 0x1e
+-
+-/* GM_SMI_CTRL 16 bit r/w SMI Control Register */
+-#define GM_SMI_CT_PHY_A_MSK (0x1f<<11) /* Bit 15..11: PHY Device Address */
+-#define GM_SMI_CT_REG_A_MSK (0x1f<<6) /* Bit 10.. 6: PHY Register Address */
+-#define GM_SMI_CT_OP_RD (1<<5) /* Bit 5: OpCode Read (0=Write)*/
+-#define GM_SMI_CT_RD_VAL (1<<4) /* Bit 4: Read Valid (Read completed) */
+-#define GM_SMI_CT_BUSY (1<<3) /* Bit 3: Busy (Operation in progress) */
+- /* Bit 2..0: reserved */
+-
+-#define GM_SMI_CT_PHY_AD(x) (SHIFT11(x) & GM_SMI_CT_PHY_A_MSK)
+-#define GM_SMI_CT_REG_AD(x) (SHIFT6(x) & GM_SMI_CT_REG_A_MSK)
+-
+- /* GM_PHY_ADDR 16 bit r/w GPHY Address Register */
+- /* Bit 15..6: reserved */
+-#define GM_PAR_MIB_CLR (1<<5) /* Bit 5: Set MIB Clear Counter Mode */
+-#define GM_PAR_MIB_TST (1<<4) /* Bit 4: MIB Load Counter (Test Mode) */
+- /* Bit 3..0: reserved */
+-
+-/* Receive Frame Status Encoding */
+-#define GMR_FS_LEN (0xffffUL<<16) /* Bit 31..16: Rx Frame Length */
+- /* Bit 15..14: reserved */
+-#define GMR_FS_VLAN (1L<<13) /* Bit 13: VLAN Packet */
+-#define GMR_FS_JABBER (1L<<12) /* Bit 12: Jabber Packet */
+-#define GMR_FS_UN_SIZE (1L<<11) /* Bit 11: Undersize Packet */
+-#define GMR_FS_MC (1L<<10) /* Bit 10: Multicast Packet */
+-#define GMR_FS_BC (1L<<9) /* Bit 9: Broadcast Packet */
+-#define GMR_FS_RX_OK (1L<<8) /* Bit 8: Receive OK (Good Packet) */
+-#define GMR_FS_GOOD_FC (1L<<7) /* Bit 7: Good Flow-Control Packet */
+-#define GMR_FS_BAD_FC (1L<<6) /* Bit 6: Bad Flow-Control Packet */
+-#define GMR_FS_MII_ERR (1L<<5) /* Bit 5: MII Error */
+-#define GMR_FS_LONG_ERR (1L<<4) /* Bit 4: Too Long Packet */
+-#define GMR_FS_FRAGMENT (1L<<3) /* Bit 3: Fragment */
+- /* Bit 2: reserved */
+-#define GMR_FS_CRC_ERR (1L<<1) /* Bit 1: CRC Error */
+-#define GMR_FS_RX_FF_OV (1L<<0) /* Bit 0: Rx FIFO Overflow */
+-
+-/*
+- * GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR)
+- */
+-#define GMR_FS_ANY_ERR (GMR_FS_CRC_ERR | \
+- GMR_FS_LONG_ERR | \
+- GMR_FS_MII_ERR | \
+- GMR_FS_BAD_FC | \
+- GMR_FS_GOOD_FC | \
+- GMR_FS_JABBER)
+-
+-/* Rx GMAC FIFO Flush Mask (default) */
+-#define RX_FF_FL_DEF_MSK (GMR_FS_CRC_ERR | \
+- GMR_FS_RX_FF_OV | \
+- GMR_FS_MII_ERR | \
+- GMR_FS_BAD_FC | \
+- GMR_FS_GOOD_FC | \
+- GMR_FS_UN_SIZE | \
+- GMR_FS_JABBER)
+-
+-/* typedefs *******************************************************************/
+-
+-
+-/* function prototypes ********************************************************/
+-
+-#ifdef __cplusplus
+-}
+-#endif /* __cplusplus */
+-
+-#endif /* __INC_XMAC_H */
+diff --git a/drivers/net/sk98lin/skaddr.c b/drivers/net/sk98lin/skaddr.c
+deleted file mode 100644
+index 6e6c56a..0000000
+--- a/drivers/net/sk98lin/skaddr.c
++++ /dev/null
+@@ -1,1788 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skaddr.c
+- * Project: Gigabit Ethernet Adapters, ADDR-Module
+- * Version: $Revision: 1.52 $
+- * Date: $Date: 2003/06/02 13:46:15 $
+- * Purpose: Manage Addresses (Multicast and Unicast) and Promiscuous Mode.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * Description:
+- *
+- * This module is intended to manage multicast addresses, address override,
+- * and promiscuous mode on GEnesis and Yukon adapters.
+- *
+- * Address Layout:
+- * port address: physical MAC address
+- * 1st exact match: logical MAC address (GEnesis only)
+- * 2nd exact match: RLMT multicast (GEnesis only)
+- * exact match 3-13: OS-specific multicasts (GEnesis only)
+- *
+- * Include File Hierarchy:
+- *
+- * "skdrv1st.h"
+- * "skdrv2nd.h"
+- *
+- ******************************************************************************/
+-
+-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+-static const char SysKonnectFileId[] =
+- "@(#) $Id: skaddr.c,v 1.52 2003/06/02 13:46:15 tschilli Exp $ (C) Marvell.";
+-#endif /* DEBUG ||!LINT || !SK_SLIM */
+-
+-#define __SKADDR_C
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif /* cplusplus */
+-
+-#include "h/skdrv1st.h"
+-#include "h/skdrv2nd.h"
+-
+-/* defines ********************************************************************/
+-
+-
+-#define XMAC_POLY 0xEDB88320UL /* CRC32-Poly - XMAC: Little Endian */
+-#define GMAC_POLY 0x04C11DB7L /* CRC16-Poly - GMAC: Little Endian */
+-#define HASH_BITS 6 /* #bits in hash */
+-#define SK_MC_BIT 0x01
+-
+-/* Error numbers and messages. */
+-
+-#define SKERR_ADDR_E001 (SK_ERRBASE_ADDR + 0)
+-#define SKERR_ADDR_E001MSG "Bad Flags."
+-#define SKERR_ADDR_E002 (SKERR_ADDR_E001 + 1)
+-#define SKERR_ADDR_E002MSG "New Error."
+-
+-/* typedefs *******************************************************************/
+-
+-/* None. */
+-
+-/* global variables ***********************************************************/
+-
+-/* 64-bit hash values with all bits set. */
+-
+-static const SK_U16 OnesHash[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
+-
+-/* local variables ************************************************************/
+-
+-#ifdef DEBUG
+-static int Next0[SK_MAX_MACS] = {0};
+-#endif /* DEBUG */
+-
+-static int SkAddrGmacMcAdd(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
+- SK_MAC_ADDR *pMc, int Flags);
+-static int SkAddrGmacMcClear(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
+- int Flags);
+-static int SkAddrGmacMcUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber);
+-static int SkAddrGmacPromiscuousChange(SK_AC *pAC, SK_IOC IoC,
+- SK_U32 PortNumber, int NewPromMode);
+-static int SkAddrXmacMcAdd(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
+- SK_MAC_ADDR *pMc, int Flags);
+-static int SkAddrXmacMcClear(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
+- int Flags);
+-static int SkAddrXmacMcUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber);
+-static int SkAddrXmacPromiscuousChange(SK_AC *pAC, SK_IOC IoC,
+- SK_U32 PortNumber, int NewPromMode);
+-
+-/* functions ******************************************************************/
+-
+-/******************************************************************************
+- *
+- * SkAddrInit - initialize data, set state to init
+- *
+- * Description:
+- *
+- * SK_INIT_DATA
+- * ============
+- *
+- * This routine clears the multicast tables and resets promiscuous mode.
+- * Some entries are reserved for the "logical MAC address", the
+- * SK-RLMT multicast address, and the BPDU multicast address.
+- *
+- *
+- * SK_INIT_IO
+- * ==========
+- *
+- * All permanent MAC addresses are read from EPROM.
+- * If the current MAC addresses are not already set in software,
+- * they are set to the values of the permanent addresses.
+- * The current addresses are written to the corresponding MAC.
+- *
+- *
+- * SK_INIT_RUN
+- * ===========
+- *
+- * Nothing.
+- *
+- * Context:
+- * init, pageable
+- *
+- * Returns:
+- * SK_ADDR_SUCCESS
+- */
+-int SkAddrInit(
+-SK_AC *pAC, /* the adapter context */
+-SK_IOC IoC, /* I/O context */
+-int Level) /* initialization level */
+-{
+- int j;
+- SK_U32 i;
+- SK_U8 *InAddr;
+- SK_U16 *OutAddr;
+- SK_ADDR_PORT *pAPort;
+-
+- switch (Level) {
+- case SK_INIT_DATA:
+- SK_MEMSET((char *) &pAC->Addr, (SK_U8) 0,
+- (SK_U16) sizeof(SK_ADDR));
+-
+- for (i = 0; i < SK_MAX_MACS; i++) {
+- pAPort = &pAC->Addr.Port[i];
+- pAPort->PromMode = SK_PROM_MODE_NONE;
+-
+- pAPort->FirstExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
+- pAPort->FirstExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
+- pAPort->NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
+- pAPort->NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
+- }
+-#ifdef xDEBUG
+- for (i = 0; i < SK_MAX_MACS; i++) {
+- if (pAC->Addr.Port[i].NextExactMatchRlmt <
+- SK_ADDR_FIRST_MATCH_RLMT) {
+- Next0[i] |= 4;
+- }
+- }
+-#endif /* DEBUG */
+- /* pAC->Addr.InitDone = SK_INIT_DATA; */
+- break;
+-
+- case SK_INIT_IO:
+-#ifndef SK_NO_RLMT
+- for (i = 0; i < SK_MAX_NETS; i++) {
+- pAC->Addr.Net[i].ActivePort = pAC->Rlmt.Net[i].ActivePort;
+- }
+-#endif /* !SK_NO_RLMT */
+-#ifdef xDEBUG
+- for (i = 0; i < SK_MAX_MACS; i++) {
+- if (pAC->Addr.Port[i].NextExactMatchRlmt <
+- SK_ADDR_FIRST_MATCH_RLMT) {
+- Next0[i] |= 8;
+- }
+- }
+-#endif /* DEBUG */
+-
+- /* Read permanent logical MAC address from Control Register File. */
+- for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
+- InAddr = (SK_U8 *) &pAC->Addr.Net[0].PermanentMacAddress.a[j];
+- SK_IN8(IoC, B2_MAC_1 + j, InAddr);
+- }
+-
+- if (!pAC->Addr.Net[0].CurrentMacAddressSet) {
+- /* Set the current logical MAC address to the permanent one. */
+- pAC->Addr.Net[0].CurrentMacAddress =
+- pAC->Addr.Net[0].PermanentMacAddress;
+- pAC->Addr.Net[0].CurrentMacAddressSet = SK_TRUE;
+- }
+-
+- /* Set the current logical MAC address. */
+- pAC->Addr.Port[pAC->Addr.Net[0].ActivePort].Exact[0] =
+- pAC->Addr.Net[0].CurrentMacAddress;
+-#if SK_MAX_NETS > 1
+- /* Set logical MAC address for net 2 to (log | 3). */
+- if (!pAC->Addr.Net[1].CurrentMacAddressSet) {
+- pAC->Addr.Net[1].PermanentMacAddress =
+- pAC->Addr.Net[0].PermanentMacAddress;
+- pAC->Addr.Net[1].PermanentMacAddress.a[5] |= 3;
+- /* Set the current logical MAC address to the permanent one. */
+- pAC->Addr.Net[1].CurrentMacAddress =
+- pAC->Addr.Net[1].PermanentMacAddress;
+- pAC->Addr.Net[1].CurrentMacAddressSet = SK_TRUE;
+- }
+-#endif /* SK_MAX_NETS > 1 */
+-
+-#ifdef DEBUG
+- for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
+- ("Permanent MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
+- i,
+- pAC->Addr.Net[i].PermanentMacAddress.a[0],
+- pAC->Addr.Net[i].PermanentMacAddress.a[1],
+- pAC->Addr.Net[i].PermanentMacAddress.a[2],
+- pAC->Addr.Net[i].PermanentMacAddress.a[3],
+- pAC->Addr.Net[i].PermanentMacAddress.a[4],
+- pAC->Addr.Net[i].PermanentMacAddress.a[5]))
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
+- ("Logical MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
+- i,
+- pAC->Addr.Net[i].CurrentMacAddress.a[0],
+- pAC->Addr.Net[i].CurrentMacAddress.a[1],
+- pAC->Addr.Net[i].CurrentMacAddress.a[2],
+- pAC->Addr.Net[i].CurrentMacAddress.a[3],
+- pAC->Addr.Net[i].CurrentMacAddress.a[4],
+- pAC->Addr.Net[i].CurrentMacAddress.a[5]))
+- }
+-#endif /* DEBUG */
+-
+- for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
+- pAPort = &pAC->Addr.Port[i];
+-
+- /* Read permanent port addresses from Control Register File. */
+- for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
+- InAddr = (SK_U8 *) &pAPort->PermanentMacAddress.a[j];
+- SK_IN8(IoC, B2_MAC_2 + 8 * i + j, InAddr);
+- }
+-
+- if (!pAPort->CurrentMacAddressSet) {
+- /*
+- * Set the current and previous physical MAC address
+- * of this port to its permanent MAC address.
+- */
+- pAPort->CurrentMacAddress = pAPort->PermanentMacAddress;
+- pAPort->PreviousMacAddress = pAPort->PermanentMacAddress;
+- pAPort->CurrentMacAddressSet = SK_TRUE;
+- }
+-
+- /* Set port's current physical MAC address. */
+- OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+- XM_OUTADDR(IoC, i, XM_SA, OutAddr);
+- }
+-#endif /* GENESIS */
+-#ifdef YUKON
+- if (!pAC->GIni.GIGenesis) {
+- GM_OUTADDR(IoC, i, GM_SRC_ADDR_1L, OutAddr);
+- }
+-#endif /* YUKON */
+-#ifdef DEBUG
+- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
+- ("SkAddrInit: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
+- pAPort->PermanentMacAddress.a[0],
+- pAPort->PermanentMacAddress.a[1],
+- pAPort->PermanentMacAddress.a[2],
+- pAPort->PermanentMacAddress.a[3],
+- pAPort->PermanentMacAddress.a[4],
+- pAPort->PermanentMacAddress.a[5]))
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
+- ("SkAddrInit: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
+- pAPort->CurrentMacAddress.a[0],
+- pAPort->CurrentMacAddress.a[1],
+- pAPort->CurrentMacAddress.a[2],
+- pAPort->CurrentMacAddress.a[3],
+- pAPort->CurrentMacAddress.a[4],
+- pAPort->CurrentMacAddress.a[5]))
+-#endif /* DEBUG */
+- }
+- /* pAC->Addr.InitDone = SK_INIT_IO; */
+- break;
+-
+- case SK_INIT_RUN:
+-#ifdef xDEBUG
+- for (i = 0; i < SK_MAX_MACS; i++) {
+- if (pAC->Addr.Port[i].NextExactMatchRlmt <
+- SK_ADDR_FIRST_MATCH_RLMT) {
+- Next0[i] |= 16;
+- }
+- }
+-#endif /* DEBUG */
+-
+- /* pAC->Addr.InitDone = SK_INIT_RUN; */
+- break;
+-
+- default: /* error */
+- break;
+- }
+-
+- return (SK_ADDR_SUCCESS);
+-
+-} /* SkAddrInit */
+-
+-#ifndef SK_SLIM
+-
+-/******************************************************************************
+- *
+- * SkAddrMcClear - clear the multicast table
+- *
+- * Description:
+- * This routine clears the multicast table.
+- *
+- * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
+- * immediately.
+- *
+- * It calls either SkAddrXmacMcClear or SkAddrGmacMcClear, according
+- * to the adapter in use. The real work is done there.
+- *
+- * Context:
+- * runtime, pageable
+- * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
+- * may be called after SK_INIT_IO without limitation
+- *
+- * Returns:
+- * SK_ADDR_SUCCESS
+- * SK_ADDR_ILLEGAL_PORT
+- */
+-int SkAddrMcClear(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* I/O context */
+-SK_U32 PortNumber, /* Index of affected port */
+-int Flags) /* permanent/non-perm, sw-only */
+-{
+- int ReturnCode;
+-
+- if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+- return (SK_ADDR_ILLEGAL_PORT);
+- }
+-
+- if (pAC->GIni.GIGenesis) {
+- ReturnCode = SkAddrXmacMcClear(pAC, IoC, PortNumber, Flags);
+- }
+- else {
+- ReturnCode = SkAddrGmacMcClear(pAC, IoC, PortNumber, Flags);
+- }
+-
+- return (ReturnCode);
+-
+-} /* SkAddrMcClear */
+-
+-#endif /* !SK_SLIM */
+-
+-#ifndef SK_SLIM
+-
+-/******************************************************************************
+- *
+- * SkAddrXmacMcClear - clear the multicast table
+- *
+- * Description:
+- * This routine clears the multicast table
+- * (either entry 2 or entries 3-16 and InexactFilter) of the given port.
+- * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
+- * immediately.
+- *
+- * Context:
+- * runtime, pageable
+- * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
+- * may be called after SK_INIT_IO without limitation
+- *
+- * Returns:
+- * SK_ADDR_SUCCESS
+- * SK_ADDR_ILLEGAL_PORT
+- */
+-static int SkAddrXmacMcClear(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* I/O context */
+-SK_U32 PortNumber, /* Index of affected port */
+-int Flags) /* permanent/non-perm, sw-only */
+-{
+- int i;
+-
+- if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
+-
+- /* Clear RLMT multicast addresses. */
+- pAC->Addr.Port[PortNumber].NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
+- }
+- else { /* not permanent => DRV */
+-
+- /* Clear InexactFilter */
+- for (i = 0; i < 8; i++) {
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
+- }
+-
+- /* Clear DRV multicast addresses. */
+-
+- pAC->Addr.Port[PortNumber].NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
+- }
+-
+- if (!(Flags & SK_MC_SW_ONLY)) {
+- (void) SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
+- }
+-
+- return (SK_ADDR_SUCCESS);
+-
+-} /* SkAddrXmacMcClear */
+-
+-#endif /* !SK_SLIM */
+-
+-#ifndef SK_SLIM
+-
+-/******************************************************************************
+- *
+- * SkAddrGmacMcClear - clear the multicast table
+- *
+- * Description:
+- * This routine clears the multicast hashing table (InexactFilter)
+- * (either the RLMT or the driver bits) of the given port.
+- *
+- * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
+- * immediately.
+- *
+- * Context:
+- * runtime, pageable
+- * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
+- * may be called after SK_INIT_IO without limitation
+- *
+- * Returns:
+- * SK_ADDR_SUCCESS
+- * SK_ADDR_ILLEGAL_PORT
+- */
+-static int SkAddrGmacMcClear(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* I/O context */
+-SK_U32 PortNumber, /* Index of affected port */
+-int Flags) /* permanent/non-perm, sw-only */
+-{
+- int i;
+-
+-#ifdef DEBUG
+- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+- ("GMAC InexactFilter (not cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
+-#endif /* DEBUG */
+-
+- /* Clear InexactFilter */
+- for (i = 0; i < 8; i++) {
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
+- }
+-
+- if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
+-
+- /* Copy DRV bits to InexactFilter. */
+- for (i = 0; i < 8; i++) {
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
+- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
+-
+- /* Clear InexactRlmtFilter. */
+- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i] = 0;
+-
+- }
+- }
+- else { /* not permanent => DRV */
+-
+- /* Copy RLMT bits to InexactFilter. */
+- for (i = 0; i < 8; i++) {
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
+- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
+-
+- /* Clear InexactDrvFilter. */
+- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i] = 0;
+- }
+- }
+-
+-#ifdef DEBUG
+- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+- ("GMAC InexactFilter (cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
+-#endif /* DEBUG */
+-
+- if (!(Flags & SK_MC_SW_ONLY)) {
+- (void) SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
+- }
+-
+- return (SK_ADDR_SUCCESS);
+-
+-} /* SkAddrGmacMcClear */
+-
+-#ifndef SK_ADDR_CHEAT
+-
+-/******************************************************************************
+- *
+- * SkXmacMcHash - hash multicast address
+- *
+- * Description:
+- * This routine computes the hash value for a multicast address.
+- * A CRC32 algorithm is used.
+- *
+- * Notes:
+- * The code was adapted from the XaQti data sheet.
+- *
+- * Context:
+- * runtime, pageable
+- *
+- * Returns:
+- * Hash value of multicast address.
+- */
+-static SK_U32 SkXmacMcHash(
+-unsigned char *pMc) /* Multicast address */
+-{
+- SK_U32 Idx;
+- SK_U32 Bit;
+- SK_U32 Data;
+- SK_U32 Crc;
+-
+- Crc = 0xFFFFFFFFUL;
+- for (Idx = 0; Idx < SK_MAC_ADDR_LEN; Idx++) {
+- Data = *pMc++;
+- for (Bit = 0; Bit < 8; Bit++, Data >>= 1) {
+- Crc = (Crc >> 1) ^ (((Crc ^ Data) & 1) ? XMAC_POLY : 0);
+- }
+- }
+-
+- return (Crc & ((1 << HASH_BITS) - 1));
+-
+-} /* SkXmacMcHash */
+-
+-
+-/******************************************************************************
+- *
+- * SkGmacMcHash - hash multicast address
+- *
+- * Description:
+- * This routine computes the hash value for a multicast address.
+- * A CRC16 algorithm is used.
+- *
+- * Notes:
+- *
+- *
+- * Context:
+- * runtime, pageable
+- *
+- * Returns:
+- * Hash value of multicast address.
+- */
+-static SK_U32 SkGmacMcHash(
+-unsigned char *pMc) /* Multicast address */
+-{
+- SK_U32 Data;
+- SK_U32 TmpData;
+- SK_U32 Crc;
+- int Byte;
+- int Bit;
+-
+- Crc = 0xFFFFFFFFUL;
+- for (Byte = 0; Byte < 6; Byte++) {
+- /* Get next byte. */
+- Data = (SK_U32) pMc[Byte];
+-
+- /* Change bit order in byte. */
+- TmpData = Data;
+- for (Bit = 0; Bit < 8; Bit++) {
+- if (TmpData & 1L) {
+- Data |= 1L << (7 - Bit);
+- }
+- else {
+- Data &= ~(1L << (7 - Bit));
+- }
+- TmpData >>= 1;
+- }
+-
+- Crc ^= (Data << 24);
+- for (Bit = 0; Bit < 8; Bit++) {
+- if (Crc & 0x80000000) {
+- Crc = (Crc << 1) ^ GMAC_POLY;
+- }
+- else {
+- Crc <<= 1;
+- }
+- }
+- }
+-
+- return (Crc & ((1 << HASH_BITS) - 1));
+-
+-} /* SkGmacMcHash */
+-
+-#endif /* !SK_ADDR_CHEAT */
+-
+-/******************************************************************************
+- *
+- * SkAddrMcAdd - add a multicast address to a port
+- *
+- * Description:
+- * This routine enables reception for a given address on the given port.
+- *
+- * It calls either SkAddrXmacMcAdd or SkAddrGmacMcAdd, according to the
+- * adapter in use. The real work is done there.
+- *
+- * Notes:
+- * The return code is only valid for SK_PROM_MODE_NONE.
+- *
+- * Context:
+- * runtime, pageable
+- * may be called after SK_INIT_DATA
+- *
+- * Returns:
+- * SK_MC_FILTERING_EXACT
+- * SK_MC_FILTERING_INEXACT
+- * SK_MC_ILLEGAL_ADDRESS
+- * SK_MC_ILLEGAL_PORT
+- * SK_MC_RLMT_OVERFLOW
+- */
+-int SkAddrMcAdd(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* I/O context */
+-SK_U32 PortNumber, /* Port Number */
+-SK_MAC_ADDR *pMc, /* multicast address to be added */
+-int Flags) /* permanent/non-permanent */
+-{
+- int ReturnCode;
+-
+- if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+- return (SK_ADDR_ILLEGAL_PORT);
+- }
+-
+- if (pAC->GIni.GIGenesis) {
+- ReturnCode = SkAddrXmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
+- }
+- else {
+- ReturnCode = SkAddrGmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
+- }
+-
+- return (ReturnCode);
+-
+-} /* SkAddrMcAdd */
+-
+-
+-/******************************************************************************
+- *
+- * SkAddrXmacMcAdd - add a multicast address to a port
+- *
+- * Description:
+- * This routine enables reception for a given address on the given port.
+- *
+- * Notes:
+- * The return code is only valid for SK_PROM_MODE_NONE.
+- *
+- * The multicast bit is only checked if there are no free exact match
+- * entries.
+- *
+- * Context:
+- * runtime, pageable
+- * may be called after SK_INIT_DATA
+- *
+- * Returns:
+- * SK_MC_FILTERING_EXACT
+- * SK_MC_FILTERING_INEXACT
+- * SK_MC_ILLEGAL_ADDRESS
+- * SK_MC_RLMT_OVERFLOW
+- */
+-static int SkAddrXmacMcAdd(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* I/O context */
+-SK_U32 PortNumber, /* Port Number */
+-SK_MAC_ADDR *pMc, /* multicast address to be added */
+-int Flags) /* permanent/non-permanent */
+-{
+- int i;
+- SK_U8 Inexact;
+-#ifndef SK_ADDR_CHEAT
+- SK_U32 HashBit;
+-#endif /* !defined(SK_ADDR_CHEAT) */
+-
+- if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
+-#ifdef xDEBUG
+- if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt <
+- SK_ADDR_FIRST_MATCH_RLMT) {
+- Next0[PortNumber] |= 1;
+- return (SK_MC_RLMT_OVERFLOW);
+- }
+-#endif /* DEBUG */
+-
+- if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt >
+- SK_ADDR_LAST_MATCH_RLMT) {
+- return (SK_MC_RLMT_OVERFLOW);
+- }
+-
+- /* Set a RLMT multicast address. */
+-
+- pAC->Addr.Port[PortNumber].Exact[
+- pAC->Addr.Port[PortNumber].NextExactMatchRlmt++] = *pMc;
+-
+- return (SK_MC_FILTERING_EXACT);
+- }
+-
+-#ifdef xDEBUG
+- if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <
+- SK_ADDR_FIRST_MATCH_DRV) {
+- Next0[PortNumber] |= 2;
+- return (SK_MC_RLMT_OVERFLOW);
+- }
+-#endif /* DEBUG */
+-
+- if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
+-
+- /* Set exact match entry. */
+- pAC->Addr.Port[PortNumber].Exact[
+- pAC->Addr.Port[PortNumber].NextExactMatchDrv++] = *pMc;
+-
+- /* Clear InexactFilter */
+- for (i = 0; i < 8; i++) {
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
+- }
+- }
+- else {
+- if (!(pMc->a[0] & SK_MC_BIT)) {
+- /* Hashing only possible with multicast addresses */
+- return (SK_MC_ILLEGAL_ADDRESS);
+- }
+-#ifndef SK_ADDR_CHEAT
+- /* Compute hash value of address. */
+- HashBit = 63 - SkXmacMcHash(&pMc->a[0]);
+-
+- /* Add bit to InexactFilter. */
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[HashBit / 8] |=
+- 1 << (HashBit % 8);
+-#else /* SK_ADDR_CHEAT */
+- /* Set all bits in InexactFilter. */
+- for (i = 0; i < 8; i++) {
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
+- }
+-#endif /* SK_ADDR_CHEAT */
+- }
+-
+- for (Inexact = 0, i = 0; i < 8; i++) {
+- Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
+- }
+-
+- if (Inexact == 0 && pAC->Addr.Port[PortNumber].PromMode == 0) {
+- return (SK_MC_FILTERING_EXACT);
+- }
+- else {
+- return (SK_MC_FILTERING_INEXACT);
+- }
+-
+-} /* SkAddrXmacMcAdd */
+-
+-
+-/******************************************************************************
+- *
+- * SkAddrGmacMcAdd - add a multicast address to a port
+- *
+- * Description:
+- * This routine enables reception for a given address on the given port.
+- *
+- * Notes:
+- * The return code is only valid for SK_PROM_MODE_NONE.
+- *
+- * Context:
+- * runtime, pageable
+- * may be called after SK_INIT_DATA
+- *
+- * Returns:
+- * SK_MC_FILTERING_INEXACT
+- * SK_MC_ILLEGAL_ADDRESS
+- */
+-static int SkAddrGmacMcAdd(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* I/O context */
+-SK_U32 PortNumber, /* Port Number */
+-SK_MAC_ADDR *pMc, /* multicast address to be added */
+-int Flags) /* permanent/non-permanent */
+-{
+- int i;
+-#ifndef SK_ADDR_CHEAT
+- SK_U32 HashBit;
+-#endif /* !defined(SK_ADDR_CHEAT) */
+-
+- if (!(pMc->a[0] & SK_MC_BIT)) {
+- /* Hashing only possible with multicast addresses */
+- return (SK_MC_ILLEGAL_ADDRESS);
+- }
+-
+-#ifndef SK_ADDR_CHEAT
+-
+- /* Compute hash value of address. */
+- HashBit = SkGmacMcHash(&pMc->a[0]);
+-
+- if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
+-
+- /* Add bit to InexactRlmtFilter. */
+- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[HashBit / 8] |=
+- 1 << (HashBit % 8);
+-
+- /* Copy bit to InexactFilter. */
+- for (i = 0; i < 8; i++) {
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
+- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
+- }
+-#ifdef DEBUG
+- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+- ("GMAC InexactRlmtFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
+- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[0],
+- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[1],
+- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[2],
+- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[3],
+- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[4],
+- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[5],
+- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[6],
+- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[7]))
+-#endif /* DEBUG */
+- }
+- else { /* not permanent => DRV */
+-
+- /* Add bit to InexactDrvFilter. */
+- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[HashBit / 8] |=
+- 1 << (HashBit % 8);
+-
+- /* Copy bit to InexactFilter. */
+- for (i = 0; i < 8; i++) {
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
+- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
+- }
+-#ifdef DEBUG
+- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+- ("GMAC InexactDrvFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
+- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[0],
+- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[1],
+- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[2],
+- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[3],
+- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[4],
+- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[5],
+- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[6],
+- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[7]))
+-#endif /* DEBUG */
+- }
+-
+-#else /* SK_ADDR_CHEAT */
+-
+- /* Set all bits in InexactFilter. */
+- for (i = 0; i < 8; i++) {
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
+- }
+-#endif /* SK_ADDR_CHEAT */
+-
+- return (SK_MC_FILTERING_INEXACT);
+-
+-} /* SkAddrGmacMcAdd */
+-
+-#endif /* !SK_SLIM */
+-
+-/******************************************************************************
+- *
+- * SkAddrMcUpdate - update the HW MC address table and set the MAC address
+- *
+- * Description:
+- * This routine enables reception of the addresses contained in a local
+- * table for a given port.
+- * It also programs the port's current physical MAC address.
+- *
+- * It calls either SkAddrXmacMcUpdate or SkAddrGmacMcUpdate, according
+- * to the adapter in use. The real work is done there.
+- *
+- * Notes:
+- * The return code is only valid for SK_PROM_MODE_NONE.
+- *
+- * Context:
+- * runtime, pageable
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * SK_MC_FILTERING_EXACT
+- * SK_MC_FILTERING_INEXACT
+- * SK_ADDR_ILLEGAL_PORT
+- */
+-int SkAddrMcUpdate(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* I/O context */
+-SK_U32 PortNumber) /* Port Number */
+-{
+- int ReturnCode = 0;
+-#if (!defined(SK_SLIM) || defined(DEBUG))
+- if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+- return (SK_ADDR_ILLEGAL_PORT);
+- }
+-#endif /* !SK_SLIM || DEBUG */
+-
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+- ReturnCode = SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
+- }
+-#endif /* GENESIS */
+-#ifdef YUKON
+- if (!pAC->GIni.GIGenesis) {
+- ReturnCode = SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
+- }
+-#endif /* YUKON */
+- return (ReturnCode);
+-
+-} /* SkAddrMcUpdate */
+-
+-
+-#ifdef GENESIS
+-
+-/******************************************************************************
+- *
+- * SkAddrXmacMcUpdate - update the HW MC address table and set the MAC address
+- *
+- * Description:
+- * This routine enables reception of the addresses contained in a local
+- * table for a given port.
+- * It also programs the port's current physical MAC address.
+- *
+- * Notes:
+- * The return code is only valid for SK_PROM_MODE_NONE.
+- *
+- * Context:
+- * runtime, pageable
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * SK_MC_FILTERING_EXACT
+- * SK_MC_FILTERING_INEXACT
+- * SK_ADDR_ILLEGAL_PORT
+- */
+-static int SkAddrXmacMcUpdate(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* I/O context */
+-SK_U32 PortNumber) /* Port Number */
+-{
+- SK_U32 i;
+- SK_U8 Inexact;
+- SK_U16 *OutAddr;
+- SK_ADDR_PORT *pAPort;
+-
+- SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+- ("SkAddrXmacMcUpdate on Port %u.\n", PortNumber))
+-
+- pAPort = &pAC->Addr.Port[PortNumber];
+-
+-#ifdef DEBUG
+- SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+- ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
+-#endif /* DEBUG */
+-
+- /* Start with 0 to also program the logical MAC address. */
+- for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
+- /* Set exact match address i on XMAC */
+- OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
+- XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
+- }
+-
+- /* Clear other permanent exact match addresses on XMAC */
+- if (pAPort->NextExactMatchRlmt <= SK_ADDR_LAST_MATCH_RLMT) {
+-
+- SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchRlmt,
+- SK_ADDR_LAST_MATCH_RLMT);
+- }
+-
+- for (i = pAPort->FirstExactMatchDrv; i < pAPort->NextExactMatchDrv; i++) {
+- OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
+- XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
+- }
+-
+- /* Clear other non-permanent exact match addresses on XMAC */
+- if (pAPort->NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
+-
+- SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchDrv,
+- SK_ADDR_LAST_MATCH_DRV);
+- }
+-
+- for (Inexact = 0, i = 0; i < 8; i++) {
+- Inexact |= pAPort->InexactFilter.Bytes[i];
+- }
+-
+- if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
+-
+- /* Set all bits in 64-bit hash register. */
+- XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
+-
+- /* Enable Hashing */
+- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+- }
+- else if (Inexact != 0) {
+-
+- /* Set 64-bit hash register to InexactFilter. */
+- XM_OUTHASH(IoC, PortNumber, XM_HSM, &pAPort->InexactFilter.Bytes[0]);
+-
+- /* Enable Hashing */
+- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+- }
+- else {
+- /* Disable Hashing */
+- SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE);
+- }
+-
+- if (pAPort->PromMode != SK_PROM_MODE_NONE) {
+- (void) SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
+- }
+-
+- /* Set port's current physical MAC address. */
+- OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
+-
+- XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
+-
+-#ifdef xDEBUG
+- for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
+- SK_U8 InAddr8[6];
+- SK_U16 *InAddr;
+-
+- /* Get exact match address i from port PortNumber. */
+- InAddr = (SK_U16 *) &InAddr8[0];
+-
+- XM_INADDR(IoC, PortNumber, XM_EXM(i), InAddr);
+-
+- SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+- ("SkAddrXmacMcUpdate: MC address %d on Port %u: ",
+- "%02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x\n",
+- i,
+- PortNumber,
+- InAddr8[0],
+- InAddr8[1],
+- InAddr8[2],
+- InAddr8[3],
+- InAddr8[4],
+- InAddr8[5],
+- pAPort->Exact[i].a[0],
+- pAPort->Exact[i].a[1],
+- pAPort->Exact[i].a[2],
+- pAPort->Exact[i].a[3],
+- pAPort->Exact[i].a[4],
+- pAPort->Exact[i].a[5]))
+- }
+-#endif /* DEBUG */
+-
+- /* Determine return value. */
+- if (Inexact == 0 && pAPort->PromMode == 0) {
+- return (SK_MC_FILTERING_EXACT);
+- }
+- else {
+- return (SK_MC_FILTERING_INEXACT);
+- }
+-
+-} /* SkAddrXmacMcUpdate */
+-
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+-
+-/******************************************************************************
+- *
+- * SkAddrGmacMcUpdate - update the HW MC address table and set the MAC address
+- *
+- * Description:
+- * This routine enables reception of the addresses contained in a local
+- * table for a given port.
+- * It also programs the port's current physical MAC address.
+- *
+- * Notes:
+- * The return code is only valid for SK_PROM_MODE_NONE.
+- *
+- * Context:
+- * runtime, pageable
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * SK_MC_FILTERING_EXACT
+- * SK_MC_FILTERING_INEXACT
+- * SK_ADDR_ILLEGAL_PORT
+- */
+-static int SkAddrGmacMcUpdate(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* I/O context */
+-SK_U32 PortNumber) /* Port Number */
+-{
+-#ifndef SK_SLIM
+- SK_U32 i;
+- SK_U8 Inexact;
+-#endif /* not SK_SLIM */
+- SK_U16 *OutAddr;
+- SK_ADDR_PORT *pAPort;
+-
+- SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+- ("SkAddrGmacMcUpdate on Port %u.\n", PortNumber))
+-
+- pAPort = &pAC->Addr.Port[PortNumber];
+-
+-#ifdef DEBUG
+- SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+- ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
+-#endif /* DEBUG */
+-
+-#ifndef SK_SLIM
+- for (Inexact = 0, i = 0; i < 8; i++) {
+- Inexact |= pAPort->InexactFilter.Bytes[i];
+- }
+-
+- /* Set 64-bit hash register to InexactFilter. */
+- GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
+- &pAPort->InexactFilter.Bytes[0]);
+-
+- if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
+-
+- /* Set all bits in 64-bit hash register. */
+- GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
+-
+- /* Enable Hashing */
+- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+- }
+- else {
+- /* Enable Hashing. */
+- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+- }
+-
+- if (pAPort->PromMode != SK_PROM_MODE_NONE) {
+- (void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
+- }
+-#else /* SK_SLIM */
+-
+- /* Set all bits in 64-bit hash register. */
+- GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
+-
+- /* Enable Hashing */
+- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+-
+- (void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
+-
+-#endif /* SK_SLIM */
+-
+- /* Set port's current physical MAC address. */
+- OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
+- GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
+-
+- /* Set port's current logical MAC address. */
+- OutAddr = (SK_U16 *) &pAPort->Exact[0].a[0];
+- GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_2L, OutAddr);
+-
+-#ifdef DEBUG
+- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+- ("SkAddrGmacMcUpdate: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
+- pAPort->Exact[0].a[0],
+- pAPort->Exact[0].a[1],
+- pAPort->Exact[0].a[2],
+- pAPort->Exact[0].a[3],
+- pAPort->Exact[0].a[4],
+- pAPort->Exact[0].a[5]))
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+- ("SkAddrGmacMcUpdate: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
+- pAPort->CurrentMacAddress.a[0],
+- pAPort->CurrentMacAddress.a[1],
+- pAPort->CurrentMacAddress.a[2],
+- pAPort->CurrentMacAddress.a[3],
+- pAPort->CurrentMacAddress.a[4],
+- pAPort->CurrentMacAddress.a[5]))
+-#endif /* DEBUG */
+-
+-#ifndef SK_SLIM
+- /* Determine return value. */
+- if (Inexact == 0 && pAPort->PromMode == 0) {
+- return (SK_MC_FILTERING_EXACT);
+- }
+- else {
+- return (SK_MC_FILTERING_INEXACT);
+- }
+-#else /* SK_SLIM */
+- return (SK_MC_FILTERING_INEXACT);
+-#endif /* SK_SLIM */
+-
+-} /* SkAddrGmacMcUpdate */
+-
+-#endif /* YUKON */
+-
+-#ifndef SK_NO_MAO
+-
+-/******************************************************************************
+- *
+- * SkAddrOverride - override a port's MAC address
+- *
+- * Description:
+- * This routine overrides the MAC address of one port.
+- *
+- * Context:
+- * runtime, pageable
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * SK_ADDR_SUCCESS if successful.
+- * SK_ADDR_DUPLICATE_ADDRESS if duplicate MAC address.
+- * SK_ADDR_MULTICAST_ADDRESS if multicast or broadcast address.
+- * SK_ADDR_TOO_EARLY if SK_INIT_IO was not executed before.
+- */
+-int SkAddrOverride(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* I/O context */
+-SK_U32 PortNumber, /* Port Number */
+-SK_MAC_ADDR SK_FAR *pNewAddr, /* new MAC address */
+-int Flags) /* logical/physical MAC address */
+-{
+-#ifndef SK_NO_RLMT
+- SK_EVPARA Para;
+-#endif /* !SK_NO_RLMT */
+- SK_U32 NetNumber;
+- SK_U32 i;
+- SK_U16 SK_FAR *OutAddr;
+-
+-#ifndef SK_NO_RLMT
+- NetNumber = pAC->Rlmt.Port[PortNumber].Net->NetNumber;
+-#else
+- NetNumber = 0;
+-#endif /* SK_NO_RLMT */
+-#if (!defined(SK_SLIM) || defined(DEBUG))
+- if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+- return (SK_ADDR_ILLEGAL_PORT);
+- }
+-#endif /* !SK_SLIM || DEBUG */
+- if (pNewAddr != NULL && (pNewAddr->a[0] & SK_MC_BIT) != 0) {
+- return (SK_ADDR_MULTICAST_ADDRESS);
+- }
+-
+- if (!pAC->Addr.Net[NetNumber].CurrentMacAddressSet) {
+- return (SK_ADDR_TOO_EARLY);
+- }
+-
+- if (Flags & SK_ADDR_SET_LOGICAL) { /* Activate logical MAC address. */
+- /* Parameter *pNewAddr is ignored. */
+- for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
+- if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
+- return (SK_ADDR_TOO_EARLY);
+- }
+- }
+-#ifndef SK_NO_RLMT
+- /* Set PortNumber to number of net's active port. */
+- PortNumber = pAC->Rlmt.Net[NetNumber].
+- Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
+-#endif /* !SK_NO_RLMT */
+- pAC->Addr.Port[PortNumber].Exact[0] =
+- pAC->Addr.Net[NetNumber].CurrentMacAddress;
+-
+- /* Write address to first exact match entry of active port. */
+- (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
+- }
+- else if (Flags & SK_ADDR_CLEAR_LOGICAL) {
+- /* Deactivate logical MAC address. */
+- /* Parameter *pNewAddr is ignored. */
+- for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
+- if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
+- return (SK_ADDR_TOO_EARLY);
+- }
+- }
+-#ifndef SK_NO_RLMT
+- /* Set PortNumber to number of net's active port. */
+- PortNumber = pAC->Rlmt.Net[NetNumber].
+- Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
+-#endif /* !SK_NO_RLMT */
+- for (i = 0; i < SK_MAC_ADDR_LEN; i++ ) {
+- pAC->Addr.Port[PortNumber].Exact[0].a[i] = 0;
+- }
+-
+- /* Write address to first exact match entry of active port. */
+- (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
+- }
+- else if (Flags & SK_ADDR_PHYSICAL_ADDRESS) { /* Physical MAC address. */
+- if (SK_ADDR_EQUAL(pNewAddr->a,
+- pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
+- return (SK_ADDR_DUPLICATE_ADDRESS);
+- }
+-
+- for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
+- if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
+- return (SK_ADDR_TOO_EARLY);
+- }
+-
+- if (SK_ADDR_EQUAL(pNewAddr->a,
+- pAC->Addr.Port[i].CurrentMacAddress.a)) {
+- if (i == PortNumber) {
+- return (SK_ADDR_SUCCESS);
+- }
+- else {
+- return (SK_ADDR_DUPLICATE_ADDRESS);
+- }
+- }
+- }
+-
+- pAC->Addr.Port[PortNumber].PreviousMacAddress =
+- pAC->Addr.Port[PortNumber].CurrentMacAddress;
+- pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
+-
+- /* Change port's physical MAC address. */
+- OutAddr = (SK_U16 SK_FAR *) pNewAddr;
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+- XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
+- }
+-#endif /* GENESIS */
+-#ifdef YUKON
+- if (!pAC->GIni.GIGenesis) {
+- GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
+- }
+-#endif /* YUKON */
+-
+-#ifndef SK_NO_RLMT
+- /* Report address change to RLMT. */
+- Para.Para32[0] = PortNumber;
+- Para.Para32[0] = -1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
+-#endif /* !SK_NO_RLMT */
+- }
+- else { /* Logical MAC address. */
+- if (SK_ADDR_EQUAL(pNewAddr->a,
+- pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
+- return (SK_ADDR_SUCCESS);
+- }
+-
+- for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
+- if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
+- return (SK_ADDR_TOO_EARLY);
+- }
+-
+- if (SK_ADDR_EQUAL(pNewAddr->a,
+- pAC->Addr.Port[i].CurrentMacAddress.a)) {
+- return (SK_ADDR_DUPLICATE_ADDRESS);
+- }
+- }
+-
+- /*
+- * In case that the physical and the logical MAC addresses are equal
+- * we must also change the physical MAC address here.
+- * In this case we have an adapter which initially was programmed with
+- * two identical MAC addresses.
+- */
+- if (SK_ADDR_EQUAL(pAC->Addr.Port[PortNumber].CurrentMacAddress.a,
+- pAC->Addr.Port[PortNumber].Exact[0].a)) {
+-
+- pAC->Addr.Port[PortNumber].PreviousMacAddress =
+- pAC->Addr.Port[PortNumber].CurrentMacAddress;
+- pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
+-
+-#ifndef SK_NO_RLMT
+- /* Report address change to RLMT. */
+- Para.Para32[0] = PortNumber;
+- Para.Para32[0] = -1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
+-#endif /* !SK_NO_RLMT */
+- }
+-
+-#ifndef SK_NO_RLMT
+- /* Set PortNumber to number of net's active port. */
+- PortNumber = pAC->Rlmt.Net[NetNumber].
+- Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
+-#endif /* !SK_NO_RLMT */
+- pAC->Addr.Net[NetNumber].CurrentMacAddress = *pNewAddr;
+- pAC->Addr.Port[PortNumber].Exact[0] = *pNewAddr;
+-#ifdef DEBUG
+- SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+- ("SkAddrOverride: Permanent MAC Address: %02X %02X %02X %02X %02X %02X\n",
+- pAC->Addr.Net[NetNumber].PermanentMacAddress.a[0],
+- pAC->Addr.Net[NetNumber].PermanentMacAddress.a[1],
+- pAC->Addr.Net[NetNumber].PermanentMacAddress.a[2],
+- pAC->Addr.Net[NetNumber].PermanentMacAddress.a[3],
+- pAC->Addr.Net[NetNumber].PermanentMacAddress.a[4],
+- pAC->Addr.Net[NetNumber].PermanentMacAddress.a[5]))
+-
+- SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+- ("SkAddrOverride: New logical MAC Address: %02X %02X %02X %02X %02X %02X\n",
+- pAC->Addr.Net[NetNumber].CurrentMacAddress.a[0],
+- pAC->Addr.Net[NetNumber].CurrentMacAddress.a[1],
+- pAC->Addr.Net[NetNumber].CurrentMacAddress.a[2],
+- pAC->Addr.Net[NetNumber].CurrentMacAddress.a[3],
+- pAC->Addr.Net[NetNumber].CurrentMacAddress.a[4],
+- pAC->Addr.Net[NetNumber].CurrentMacAddress.a[5]))
+-#endif /* DEBUG */
+-
+- /* Write address to first exact match entry of active port. */
+- (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
+- }
+-
+- return (SK_ADDR_SUCCESS);
+-
+-} /* SkAddrOverride */
+-
+-
+-#endif /* SK_NO_MAO */
+-
+-/******************************************************************************
+- *
+- * SkAddrPromiscuousChange - set promiscuous mode for given port
+- *
+- * Description:
+- * This routine manages promiscuous mode:
+- * - none
+- * - all LLC frames
+- * - all MC frames
+- *
+- * It calls either SkAddrXmacPromiscuousChange or
+- * SkAddrGmacPromiscuousChange, according to the adapter in use.
+- * The real work is done there.
+- *
+- * Context:
+- * runtime, pageable
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * SK_ADDR_SUCCESS
+- * SK_ADDR_ILLEGAL_PORT
+- */
+-int SkAddrPromiscuousChange(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* I/O context */
+-SK_U32 PortNumber, /* port whose promiscuous mode changes */
+-int NewPromMode) /* new promiscuous mode */
+-{
+- int ReturnCode = 0;
+-#if (!defined(SK_SLIM) || defined(DEBUG))
+- if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+- return (SK_ADDR_ILLEGAL_PORT);
+- }
+-#endif /* !SK_SLIM || DEBUG */
+-
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+- ReturnCode =
+- SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
+- }
+-#endif /* GENESIS */
+-#ifdef YUKON
+- if (!pAC->GIni.GIGenesis) {
+- ReturnCode =
+- SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
+- }
+-#endif /* YUKON */
+-
+- return (ReturnCode);
+-
+-} /* SkAddrPromiscuousChange */
+-
+-#ifdef GENESIS
+-
+-/******************************************************************************
+- *
+- * SkAddrXmacPromiscuousChange - set promiscuous mode for given port
+- *
+- * Description:
+- * This routine manages promiscuous mode:
+- * - none
+- * - all LLC frames
+- * - all MC frames
+- *
+- * Context:
+- * runtime, pageable
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * SK_ADDR_SUCCESS
+- * SK_ADDR_ILLEGAL_PORT
+- */
+-static int SkAddrXmacPromiscuousChange(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* I/O context */
+-SK_U32 PortNumber, /* port whose promiscuous mode changes */
+-int NewPromMode) /* new promiscuous mode */
+-{
+- int i;
+- SK_BOOL InexactModeBit;
+- SK_U8 Inexact;
+- SK_U8 HwInexact;
+- SK_FILTER64 HwInexactFilter;
+- SK_U16 LoMode; /* Lower 16 bits of XMAC Mode Register. */
+- int CurPromMode = SK_PROM_MODE_NONE;
+-
+- /* Read CurPromMode from Hardware. */
+- XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
+-
+- if ((LoMode & XM_MD_ENA_PROM) != 0) {
+- /* Promiscuous mode! */
+- CurPromMode |= SK_PROM_MODE_LLC;
+- }
+-
+- for (Inexact = 0xFF, i = 0; i < 8; i++) {
+- Inexact &= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
+- }
+- if (Inexact == 0xFF) {
+- CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
+- }
+- else {
+- /* Get InexactModeBit (bit XM_MD_ENA_HASH in mode register) */
+- XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
+-
+- InexactModeBit = (LoMode & XM_MD_ENA_HASH) != 0;
+-
+- /* Read 64-bit hash register from XMAC */
+- XM_INHASH(IoC, PortNumber, XM_HSM, &HwInexactFilter.Bytes[0]);
+-
+- for (HwInexact = 0xFF, i = 0; i < 8; i++) {
+- HwInexact &= HwInexactFilter.Bytes[i];
+- }
+-
+- if (InexactModeBit && (HwInexact == 0xFF)) {
+- CurPromMode |= SK_PROM_MODE_ALL_MC;
+- }
+- }
+-
+- pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
+-
+- if (NewPromMode == CurPromMode) {
+- return (SK_ADDR_SUCCESS);
+- }
+-
+- if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
+- !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC. */
+-
+- /* Set all bits in 64-bit hash register. */
+- XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
+-
+- /* Enable Hashing */
+- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+- }
+- else if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
+- !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm MC. */
+- for (Inexact = 0, i = 0; i < 8; i++) {
+- Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
+- }
+- if (Inexact == 0) {
+- /* Disable Hashing */
+- SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE);
+- }
+- else {
+- /* Set 64-bit hash register to InexactFilter. */
+- XM_OUTHASH(IoC, PortNumber, XM_HSM,
+- &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
+-
+- /* Enable Hashing */
+- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+- }
+- }
+-
+- if ((NewPromMode & SK_PROM_MODE_LLC) &&
+- !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */
+- /* Set the MAC in Promiscuous Mode */
+- SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE);
+- }
+- else if ((CurPromMode & SK_PROM_MODE_LLC) &&
+- !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC. */
+- /* Clear Promiscuous Mode */
+- SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE);
+- }
+-
+- return (SK_ADDR_SUCCESS);
+-
+-} /* SkAddrXmacPromiscuousChange */
+-
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+-
+-/******************************************************************************
+- *
+- * SkAddrGmacPromiscuousChange - set promiscuous mode for given port
+- *
+- * Description:
+- * This routine manages promiscuous mode:
+- * - none
+- * - all LLC frames
+- * - all MC frames
+- *
+- * Context:
+- * runtime, pageable
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * SK_ADDR_SUCCESS
+- * SK_ADDR_ILLEGAL_PORT
+- */
+-static int SkAddrGmacPromiscuousChange(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* I/O context */
+-SK_U32 PortNumber, /* port whose promiscuous mode changes */
+-int NewPromMode) /* new promiscuous mode */
+-{
+- SK_U16 ReceiveControl; /* GMAC Receive Control Register */
+- int CurPromMode = SK_PROM_MODE_NONE;
+-
+- /* Read CurPromMode from Hardware. */
+- GM_IN16(IoC, PortNumber, GM_RX_CTRL, &ReceiveControl);
+-
+- if ((ReceiveControl & (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA)) == 0) {
+- /* Promiscuous mode! */
+- CurPromMode |= SK_PROM_MODE_LLC;
+- }
+-
+- if ((ReceiveControl & GM_RXCR_MCF_ENA) == 0) {
+- /* All Multicast mode! */
+- CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
+- }
+-
+- pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
+-
+- if (NewPromMode == CurPromMode) {
+- return (SK_ADDR_SUCCESS);
+- }
+-
+- if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
+- !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC */
+-
+- /* Set all bits in 64-bit hash register. */
+- GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
+-
+- /* Enable Hashing */
+- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+- }
+-
+- if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
+- !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm. MC */
+-
+- /* Set 64-bit hash register to InexactFilter. */
+- GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
+- &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
+-
+- /* Enable Hashing. */
+- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+- }
+-
+- if ((NewPromMode & SK_PROM_MODE_LLC) &&
+- !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */
+-
+- /* Set the MAC to Promiscuous Mode. */
+- SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE);
+- }
+- else if ((CurPromMode & SK_PROM_MODE_LLC) &&
+- !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC */
+-
+- /* Clear Promiscuous Mode. */
+- SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE);
+- }
+-
+- return (SK_ADDR_SUCCESS);
+-
+-} /* SkAddrGmacPromiscuousChange */
+-
+-#endif /* YUKON */
+-
+-#ifndef SK_SLIM
+-
+-/******************************************************************************
+- *
+- * SkAddrSwap - swap address info
+- *
+- * Description:
+- * This routine swaps address info of two ports.
+- *
+- * Context:
+- * runtime, pageable
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * SK_ADDR_SUCCESS
+- * SK_ADDR_ILLEGAL_PORT
+- */
+-int SkAddrSwap(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* I/O context */
+-SK_U32 FromPortNumber, /* Port1 Index */
+-SK_U32 ToPortNumber) /* Port2 Index */
+-{
+- int i;
+- SK_U8 Byte;
+- SK_MAC_ADDR MacAddr;
+- SK_U32 DWord;
+-
+- if (FromPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+- return (SK_ADDR_ILLEGAL_PORT);
+- }
+-
+- if (ToPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+- return (SK_ADDR_ILLEGAL_PORT);
+- }
+-
+- if (pAC->Rlmt.Port[FromPortNumber].Net != pAC->Rlmt.Port[ToPortNumber].Net) {
+- return (SK_ADDR_ILLEGAL_PORT);
+- }
+-
+- /*
+- * Swap:
+- * - Exact Match Entries (GEnesis and Yukon)
+- * Yukon uses first entry for the logical MAC
+- * address (stored in the second GMAC register).
+- * - FirstExactMatchRlmt (GEnesis only)
+- * - NextExactMatchRlmt (GEnesis only)
+- * - FirstExactMatchDrv (GEnesis only)
+- * - NextExactMatchDrv (GEnesis only)
+- * - 64-bit filter (InexactFilter)
+- * - Promiscuous Mode
+- * of ports.
+- */
+-
+- for (i = 0; i < SK_ADDR_EXACT_MATCHES; i++) {
+- MacAddr = pAC->Addr.Port[FromPortNumber].Exact[i];
+- pAC->Addr.Port[FromPortNumber].Exact[i] =
+- pAC->Addr.Port[ToPortNumber].Exact[i];
+- pAC->Addr.Port[ToPortNumber].Exact[i] = MacAddr;
+- }
+-
+- for (i = 0; i < 8; i++) {
+- Byte = pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i];
+- pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i] =
+- pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i];
+- pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i] = Byte;
+- }
+-
+- i = pAC->Addr.Port[FromPortNumber].PromMode;
+- pAC->Addr.Port[FromPortNumber].PromMode = pAC->Addr.Port[ToPortNumber].PromMode;
+- pAC->Addr.Port[ToPortNumber].PromMode = i;
+-
+- if (pAC->GIni.GIGenesis) {
+- DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt;
+- pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt =
+- pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt;
+- pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt = DWord;
+-
+- DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt;
+- pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt =
+- pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt;
+- pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt = DWord;
+-
+- DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv;
+- pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv =
+- pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv;
+- pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv = DWord;
+-
+- DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchDrv;
+- pAC->Addr.Port[FromPortNumber].NextExactMatchDrv =
+- pAC->Addr.Port[ToPortNumber].NextExactMatchDrv;
+- pAC->Addr.Port[ToPortNumber].NextExactMatchDrv = DWord;
+- }
+-
+- /* CAUTION: Solution works if only ports of one adapter are in use. */
+- for (i = 0; (SK_U32) i < pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].
+- Net->NetNumber].NumPorts; i++) {
+- if (pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
+- Port[i]->PortNumber == ToPortNumber) {
+- pAC->Addr.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
+- ActivePort = i;
+- /* 20001207 RA: Was "ToPortNumber;". */
+- }
+- }
+-
+- (void) SkAddrMcUpdate(pAC, IoC, FromPortNumber);
+- (void) SkAddrMcUpdate(pAC, IoC, ToPortNumber);
+-
+- return (SK_ADDR_SUCCESS);
+-
+-} /* SkAddrSwap */
+-
+-#endif /* !SK_SLIM */
+-
+-#ifdef __cplusplus
+-}
+-#endif /* __cplusplus */
+-
+diff --git a/drivers/net/sk98lin/skdim.c b/drivers/net/sk98lin/skdim.c
+deleted file mode 100644
+index 37ce03f..0000000
+--- a/drivers/net/sk98lin/skdim.c
++++ /dev/null
+@@ -1,742 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skdim.c
+- * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.5 $
+- * Date: $Date: 2003/11/28 12:55:40 $
+- * Purpose: All functions to maintain interrupt moderation
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * Description:
+- *
+- * This module is intended to manage the dynamic interrupt moderation on both
+- * GEnesis and Yukon adapters.
+- *
+- * Include File Hierarchy:
+- *
+- * "skdrv1st.h"
+- * "skdrv2nd.h"
+- *
+- ******************************************************************************/
+-
+-#ifndef lint
+-static const char SysKonnectFileId[] =
+- "@(#) $Id: skdim.c,v 1.5 2003/11/28 12:55:40 rroesler Exp $ (C) SysKonnect.";
+-#endif
+-
+-#define __SKADDR_C
+-
+-#ifdef __cplusplus
+-#error C++ is not yet supported.
+-extern "C" {
+-#endif
+-
+-/*******************************************************************************
+-**
+-** Includes
+-**
+-*******************************************************************************/
+-
+-#ifndef __INC_SKDRV1ST_H
+-#include "h/skdrv1st.h"
+-#endif
+-
+-#ifndef __INC_SKDRV2ND_H
+-#include "h/skdrv2nd.h"
+-#endif
+-
+-#include <linux/kernel_stat.h>
+-
+-/*******************************************************************************
+-**
+-** Defines
+-**
+-*******************************************************************************/
+-
+-/*******************************************************************************
+-**
+-** Typedefs
+-**
+-*******************************************************************************/
+-
+-/*******************************************************************************
+-**
+-** Local function prototypes
+-**
+-*******************************************************************************/
+-
+-static unsigned int GetCurrentSystemLoad(SK_AC *pAC);
+-static SK_U64 GetIsrCalls(SK_AC *pAC);
+-static SK_BOOL IsIntModEnabled(SK_AC *pAC);
+-static void SetCurrIntCtr(SK_AC *pAC);
+-static void EnableIntMod(SK_AC *pAC);
+-static void DisableIntMod(SK_AC *pAC);
+-static void ResizeDimTimerDuration(SK_AC *pAC);
+-static void DisplaySelectedModerationType(SK_AC *pAC);
+-static void DisplaySelectedModerationMask(SK_AC *pAC);
+-static void DisplayDescrRatio(SK_AC *pAC);
+-
+-/*******************************************************************************
+-**
+-** Global variables
+-**
+-*******************************************************************************/
+-
+-/*******************************************************************************
+-**
+-** Local variables
+-**
+-*******************************************************************************/
+-
+-/*******************************************************************************
+-**
+-** Global functions
+-**
+-*******************************************************************************/
+-
+-/*******************************************************************************
+-** Function : SkDimModerate
+-** Description : Called in every ISR to check if moderation is to be applied
+-** or not for the current number of interrupts
+-** Programmer : Ralph Roesler
+-** Last Modified: 22-mar-03
+-** Returns : void (!)
+-** Notes : -
+-*******************************************************************************/
+-
+-void
+-SkDimModerate(SK_AC *pAC) {
+- unsigned int CurrSysLoad = 0; /* expressed in percent */
+- unsigned int LoadIncrease = 0; /* expressed in percent */
+- SK_U64 ThresholdInts = 0;
+- SK_U64 IsrCallsPerSec = 0;
+-
+-#define M_DIMINFO pAC->DynIrqModInfo
+-
+- if (!IsIntModEnabled(pAC)) {
+- if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
+- CurrSysLoad = GetCurrentSystemLoad(pAC);
+- if (CurrSysLoad > 75) {
+- /*
+- ** More than 75% total system load! Enable the moderation
+- ** to shield the system against too many interrupts.
+- */
+- EnableIntMod(pAC);
+- } else if (CurrSysLoad > M_DIMINFO.PrevSysLoad) {
+- LoadIncrease = (CurrSysLoad - M_DIMINFO.PrevSysLoad);
+- if (LoadIncrease > ((M_DIMINFO.PrevSysLoad *
+- C_INT_MOD_ENABLE_PERCENTAGE) / 100)) {
+- if (CurrSysLoad > 10) {
+- /*
+- ** More than 50% increase with respect to the
+- ** previous load of the system. Most likely this
+- ** is due to our ISR-proc...
+- */
+- EnableIntMod(pAC);
+- }
+- }
+- } else {
+- /*
+- ** Neither too much system load at all nor too much increase
+- ** with respect to the previous system load. Hence, we can leave
+- ** the ISR-handling like it is without enabling moderation.
+- */
+- }
+- M_DIMINFO.PrevSysLoad = CurrSysLoad;
+- }
+- } else {
+- if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
+- ThresholdInts = ((M_DIMINFO.MaxModIntsPerSec *
+- C_INT_MOD_DISABLE_PERCENTAGE) / 100);
+- IsrCallsPerSec = GetIsrCalls(pAC);
+- if (IsrCallsPerSec <= ThresholdInts) {
+- /*
+- ** The number of interrupts within the last second is
+- ** lower than the disable_percentage of the desried
+- ** maxrate. Therefore we can disable the moderation.
+- */
+- DisableIntMod(pAC);
+- M_DIMINFO.MaxModIntsPerSec =
+- (M_DIMINFO.MaxModIntsPerSecUpperLimit +
+- M_DIMINFO.MaxModIntsPerSecLowerLimit) / 2;
+- } else {
+- /*
+- ** The number of interrupts per sec is the same as expected.
+- ** Evalulate the descriptor-ratio. If it has changed, a resize
+- ** in the moderation timer might be useful
+- */
+- if (M_DIMINFO.AutoSizing) {
+- ResizeDimTimerDuration(pAC);
+- }
+- }
+- }
+- }
+-
+- /*
+- ** Some information to the log...
+- */
+- if (M_DIMINFO.DisplayStats) {
+- DisplaySelectedModerationType(pAC);
+- DisplaySelectedModerationMask(pAC);
+- DisplayDescrRatio(pAC);
+- }
+-
+- M_DIMINFO.NbrProcessedDescr = 0;
+- SetCurrIntCtr(pAC);
+-}
+-
+-/*******************************************************************************
+-** Function : SkDimStartModerationTimer
+-** Description : Starts the audit-timer for the dynamic interrupt moderation
+-** Programmer : Ralph Roesler
+-** Last Modified: 22-mar-03
+-** Returns : void (!)
+-** Notes : -
+-*******************************************************************************/
+-
+-void
+-SkDimStartModerationTimer(SK_AC *pAC) {
+- SK_EVPARA EventParam; /* Event struct for timer event */
+-
+- SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam));
+- EventParam.Para32[0] = SK_DRV_MODERATION_TIMER;
+- SkTimerStart(pAC, pAC->IoBase, &pAC->DynIrqModInfo.ModTimer,
+- SK_DRV_MODERATION_TIMER_LENGTH,
+- SKGE_DRV, SK_DRV_TIMER, EventParam);
+-}
+-
+-/*******************************************************************************
+-** Function : SkDimEnableModerationIfNeeded
+-** Description : Either enables or disables moderation
+-** Programmer : Ralph Roesler
+-** Last Modified: 22-mar-03
+-** Returns : void (!)
+-** Notes : This function is called when a particular adapter is opened
+-** There is no Disable function, because when all interrupts
+-** might be disable, the moderation timer has no meaning at all
+-******************************************************************************/
+-
+-void
+-SkDimEnableModerationIfNeeded(SK_AC *pAC) {
+-
+- if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_STATIC) {
+- EnableIntMod(pAC); /* notification print in this function */
+- } else if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
+- SkDimStartModerationTimer(pAC);
+- if (M_DIMINFO.DisplayStats) {
+- printk("Dynamic moderation has been enabled\n");
+- }
+- } else {
+- if (M_DIMINFO.DisplayStats) {
+- printk("No moderation has been enabled\n");
+- }
+- }
+-}
+-
+-/*******************************************************************************
+-** Function : SkDimDisplayModerationSettings
+-** Description : Displays the current settings regarding interrupt moderation
+-** Programmer : Ralph Roesler
+-** Last Modified: 22-mar-03
+-** Returns : void (!)
+-** Notes : -
+-*******************************************************************************/
+-
+-void
+-SkDimDisplayModerationSettings(SK_AC *pAC) {
+- DisplaySelectedModerationType(pAC);
+- DisplaySelectedModerationMask(pAC);
+-}
+-
+-/*******************************************************************************
+-**
+-** Local functions
+-**
+-*******************************************************************************/
+-
+-/*******************************************************************************
+-** Function : GetCurrentSystemLoad
+-** Description : Retrieves the current system load of the system. This load
+-** is evaluated for all processors within the system.
+-** Programmer : Ralph Roesler
+-** Last Modified: 22-mar-03
+-** Returns : unsigned int: load expressed in percentage
+-** Notes : The possible range being returned is from 0 up to 100.
+-** Whereas 0 means 'no load at all' and 100 'system fully loaded'
+-** It is impossible to determine what actually causes the system
+-** to be in 100%, but maybe that is due to too much interrupts.
+-*******************************************************************************/
+-
+-static unsigned int
+-GetCurrentSystemLoad(SK_AC *pAC) {
+- unsigned long jif = jiffies;
+- unsigned int UserTime = 0;
+- unsigned int SystemTime = 0;
+- unsigned int NiceTime = 0;
+- unsigned int IdleTime = 0;
+- unsigned int TotalTime = 0;
+- unsigned int UsedTime = 0;
+- unsigned int SystemLoad = 0;
+-
+- /* unsigned int NbrCpu = 0; */
+-
+- /*
+- ** The following lines have been commented out, because
+- ** from kernel 2.5.44 onwards, the kernel-owned structure
+- **
+- ** struct kernel_stat kstat
+- **
+- ** is not marked as an exported symbol in the file
+- **
+- ** kernel/ksyms.c
+- **
+- ** As a consequence, using this driver as KLM is not possible
+- ** and any access of the structure kernel_stat via the
+- ** dedicated macros kstat_cpu(i).cpustat.xxx is to be avoided.
+- **
+- ** The kstat-information might be added again in future
+- ** versions of the 2.5.xx kernel, but for the time being,
+- ** number of interrupts will serve as indication how much
+- ** load we currently have...
+- **
+- ** for (NbrCpu = 0; NbrCpu < num_online_cpus(); NbrCpu++) {
+- ** UserTime = UserTime + kstat_cpu(NbrCpu).cpustat.user;
+- ** NiceTime = NiceTime + kstat_cpu(NbrCpu).cpustat.nice;
+- ** SystemTime = SystemTime + kstat_cpu(NbrCpu).cpustat.system;
+- ** }
+- */
+- SK_U64 ThresholdInts = 0;
+- SK_U64 IsrCallsPerSec = 0;
+-
+- ThresholdInts = ((M_DIMINFO.MaxModIntsPerSec *
+- C_INT_MOD_ENABLE_PERCENTAGE) + 100);
+- IsrCallsPerSec = GetIsrCalls(pAC);
+- if (IsrCallsPerSec >= ThresholdInts) {
+- /*
+- ** We do not know how much the real CPU-load is!
+- ** Return 80% as a default in order to activate DIM
+- */
+- SystemLoad = 80;
+- return (SystemLoad);
+- }
+-
+- UsedTime = UserTime + NiceTime + SystemTime;
+-
+- IdleTime = jif * num_online_cpus() - UsedTime;
+- TotalTime = UsedTime + IdleTime;
+-
+- SystemLoad = ( 100 * (UsedTime - M_DIMINFO.PrevUsedTime) ) /
+- (TotalTime - M_DIMINFO.PrevTotalTime);
+-
+- if (M_DIMINFO.DisplayStats) {
+- printk("Current system load is: %u\n", SystemLoad);
+- }
+-
+- M_DIMINFO.PrevTotalTime = TotalTime;
+- M_DIMINFO.PrevUsedTime = UsedTime;
+-
+- return (SystemLoad);
+-}
+-
+-/*******************************************************************************
+-** Function : GetIsrCalls
+-** Description : Depending on the selected moderation mask, this function will
+-** return the number of interrupts handled in the previous time-
+-** frame. This evaluated number is based on the current number
+-** of interrupts stored in PNMI-context and the previous stored
+-** interrupts.
+-** Programmer : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns : int: the number of interrupts being executed in the last
+-** timeframe
+-** Notes : It makes only sense to call this function, when dynamic
+-** interrupt moderation is applied
+-*******************************************************************************/
+-
+-static SK_U64
+-GetIsrCalls(SK_AC *pAC) {
+- SK_U64 RxPort0IntDiff = 0;
+- SK_U64 RxPort1IntDiff = 0;
+- SK_U64 TxPort0IntDiff = 0;
+- SK_U64 TxPort1IntDiff = 0;
+-
+- if (pAC->DynIrqModInfo.MaskIrqModeration == IRQ_MASK_TX_ONLY) {
+- if (pAC->GIni.GIMacsFound == 2) {
+- TxPort1IntDiff = pAC->Pnmi.Port[1].TxIntrCts -
+- pAC->DynIrqModInfo.PrevPort1TxIntrCts;
+- }
+- TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts -
+- pAC->DynIrqModInfo.PrevPort0TxIntrCts;
+- } else if (pAC->DynIrqModInfo.MaskIrqModeration == IRQ_MASK_RX_ONLY) {
+- if (pAC->GIni.GIMacsFound == 2) {
+- RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts -
+- pAC->DynIrqModInfo.PrevPort1RxIntrCts;
+- }
+- RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts -
+- pAC->DynIrqModInfo.PrevPort0RxIntrCts;
+- } else {
+- if (pAC->GIni.GIMacsFound == 2) {
+- RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts -
+- pAC->DynIrqModInfo.PrevPort1RxIntrCts;
+- TxPort1IntDiff = pAC->Pnmi.Port[1].TxIntrCts -
+- pAC->DynIrqModInfo.PrevPort1TxIntrCts;
+- }
+- RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts -
+- pAC->DynIrqModInfo.PrevPort0RxIntrCts;
+- TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts -
+- pAC->DynIrqModInfo.PrevPort0TxIntrCts;
+- }
+-
+- return (RxPort0IntDiff + RxPort1IntDiff + TxPort0IntDiff + TxPort1IntDiff);
+-}
+-
+-/*******************************************************************************
+-** Function : GetRxCalls
+-** Description : This function will return the number of times a receive inter-
+-** rupt was processed. This is needed to evaluate any resizing
+-** factor.
+-** Programmer : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns : SK_U64: the number of RX-ints being processed
+-** Notes : It makes only sense to call this function, when dynamic
+-** interrupt moderation is applied
+-*******************************************************************************/
+-
+-static SK_U64
+-GetRxCalls(SK_AC *pAC) {
+- SK_U64 RxPort0IntDiff = 0;
+- SK_U64 RxPort1IntDiff = 0;
+-
+- if (pAC->GIni.GIMacsFound == 2) {
+- RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts -
+- pAC->DynIrqModInfo.PrevPort1RxIntrCts;
+- }
+- RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts -
+- pAC->DynIrqModInfo.PrevPort0RxIntrCts;
+-
+- return (RxPort0IntDiff + RxPort1IntDiff);
+-}
+-
+-/*******************************************************************************
+-** Function : SetCurrIntCtr
+-** Description : Will store the current number orf occured interrupts in the
+-** adapter context. This is needed to evaluated the number of
+-** interrupts within a current timeframe.
+-** Programmer : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns : void (!)
+-** Notes : -
+-*******************************************************************************/
+-
+-static void
+-SetCurrIntCtr(SK_AC *pAC) {
+- if (pAC->GIni.GIMacsFound == 2) {
+- pAC->DynIrqModInfo.PrevPort1RxIntrCts = pAC->Pnmi.Port[1].RxIntrCts;
+- pAC->DynIrqModInfo.PrevPort1TxIntrCts = pAC->Pnmi.Port[1].TxIntrCts;
+- }
+- pAC->DynIrqModInfo.PrevPort0RxIntrCts = pAC->Pnmi.Port[0].RxIntrCts;
+- pAC->DynIrqModInfo.PrevPort0TxIntrCts = pAC->Pnmi.Port[0].TxIntrCts;
+-}
+-
+-/*******************************************************************************
+-** Function : IsIntModEnabled()
+-** Description : Retrieves the current value of the interrupts moderation
+-** command register. Its content determines whether any
+-** moderation is running or not.
+-** Programmer : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns : SK_TRUE : if mod timer running
+-** SK_FALSE : if no moderation is being performed
+-** Notes : -
+-*******************************************************************************/
+-
+-static SK_BOOL
+-IsIntModEnabled(SK_AC *pAC) {
+- unsigned long CtrCmd;
+-
+- SK_IN32(pAC->IoBase, B2_IRQM_CTRL, &CtrCmd);
+- if ((CtrCmd & TIM_START) == TIM_START) {
+- return SK_TRUE;
+- } else {
+- return SK_FALSE;
+- }
+-}
+-
+-/*******************************************************************************
+-** Function : EnableIntMod()
+-** Description : Enables the interrupt moderation using the values stored in
+-** in the pAC->DynIntMod data structure
+-** Programmer : Ralph Roesler
+-** Last Modified: 22-mar-03
+-** Returns : -
+-** Notes : -
+-*******************************************************************************/
+-
+-static void
+-EnableIntMod(SK_AC *pAC) {
+- unsigned long ModBase;
+-
+- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+- ModBase = C_CLK_FREQ_GENESIS / pAC->DynIrqModInfo.MaxModIntsPerSec;
+- } else {
+- ModBase = C_CLK_FREQ_YUKON / pAC->DynIrqModInfo.MaxModIntsPerSec;
+- }
+-
+- SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase);
+- SK_OUT32(pAC->IoBase, B2_IRQM_MSK, pAC->DynIrqModInfo.MaskIrqModeration);
+- SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START);
+- if (M_DIMINFO.DisplayStats) {
+- printk("Enabled interrupt moderation (%i ints/sec)\n",
+- M_DIMINFO.MaxModIntsPerSec);
+- }
+-}
+-
+-/*******************************************************************************
+-** Function : DisableIntMod()
+-** Description : Disables the interrupt moderation independent of what inter-
+-** rupts are running or not
+-** Programmer : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns : -
+-** Notes : -
+-*******************************************************************************/
+-
+-static void
+-DisableIntMod(SK_AC *pAC) {
+-
+- SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_STOP);
+- if (M_DIMINFO.DisplayStats) {
+- printk("Disabled interrupt moderation\n");
+- }
+-}
+-
+-/*******************************************************************************
+-** Function : ResizeDimTimerDuration();
+-** Description : Checks the current used descriptor ratio and resizes the
+-** duration timer (longer/smaller) if possible.
+-** Programmer : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns : -
+-** Notes : There are both maximum and minimum timer duration value.
+-** This function assumes that interrupt moderation is already
+-** enabled!
+-*******************************************************************************/
+-
+-static void
+-ResizeDimTimerDuration(SK_AC *pAC) {
+- SK_BOOL IncreaseTimerDuration;
+- int TotalMaxNbrDescr;
+- int UsedDescrRatio;
+- int RatioDiffAbs;
+- int RatioDiffRel;
+- int NewMaxModIntsPerSec;
+- int ModAdjValue;
+- long ModBase;
+-
+- /*
+- ** Check first if we are allowed to perform any modification
+- */
+- if (IsIntModEnabled(pAC)) {
+- if (M_DIMINFO.IntModTypeSelect != C_INT_MOD_DYNAMIC) {
+- return;
+- } else {
+- if (M_DIMINFO.ModJustEnabled) {
+- M_DIMINFO.ModJustEnabled = SK_FALSE;
+- return;
+- }
+- }
+- }
+-
+- /*
+- ** If we got until here, we have to evaluate the amount of the
+- ** descriptor ratio change...
+- */
+- TotalMaxNbrDescr = pAC->RxDescrPerRing * GetRxCalls(pAC);
+- UsedDescrRatio = (M_DIMINFO.NbrProcessedDescr * 100) / TotalMaxNbrDescr;
+-
+- if (UsedDescrRatio > M_DIMINFO.PrevUsedDescrRatio) {
+- RatioDiffAbs = (UsedDescrRatio - M_DIMINFO.PrevUsedDescrRatio);
+- RatioDiffRel = (RatioDiffAbs * 100) / UsedDescrRatio;
+- M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
+- IncreaseTimerDuration = SK_FALSE; /* in other words: DECREASE */
+- } else if (UsedDescrRatio < M_DIMINFO.PrevUsedDescrRatio) {
+- RatioDiffAbs = (M_DIMINFO.PrevUsedDescrRatio - UsedDescrRatio);
+- RatioDiffRel = (RatioDiffAbs * 100) / M_DIMINFO.PrevUsedDescrRatio;
+- M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
+- IncreaseTimerDuration = SK_TRUE; /* in other words: INCREASE */
+- } else {
+- RatioDiffAbs = (M_DIMINFO.PrevUsedDescrRatio - UsedDescrRatio);
+- RatioDiffRel = (RatioDiffAbs * 100) / M_DIMINFO.PrevUsedDescrRatio;
+- M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
+- IncreaseTimerDuration = SK_TRUE; /* in other words: INCREASE */
+- }
+-
+- /*
+- ** Now we can determine the change in percent
+- */
+- if ((RatioDiffRel >= 0) && (RatioDiffRel <= 5) ) {
+- ModAdjValue = 1; /* 1% change - maybe some other value in future */
+- } else if ((RatioDiffRel > 5) && (RatioDiffRel <= 10) ) {
+- ModAdjValue = 1; /* 1% change - maybe some other value in future */
+- } else if ((RatioDiffRel > 10) && (RatioDiffRel <= 15) ) {
+- ModAdjValue = 1; /* 1% change - maybe some other value in future */
+- } else {
+- ModAdjValue = 1; /* 1% change - maybe some other value in future */
+- }
+-
+- if (IncreaseTimerDuration) {
+- NewMaxModIntsPerSec = M_DIMINFO.MaxModIntsPerSec +
+- (M_DIMINFO.MaxModIntsPerSec * ModAdjValue) / 100;
+- } else {
+- NewMaxModIntsPerSec = M_DIMINFO.MaxModIntsPerSec -
+- (M_DIMINFO.MaxModIntsPerSec * ModAdjValue) / 100;
+- }
+-
+- /*
+- ** Check if we exceed boundaries...
+- */
+- if ( (NewMaxModIntsPerSec > M_DIMINFO.MaxModIntsPerSecUpperLimit) ||
+- (NewMaxModIntsPerSec < M_DIMINFO.MaxModIntsPerSecLowerLimit)) {
+- if (M_DIMINFO.DisplayStats) {
+- printk("Cannot change ModTim from %i to %i ints/sec\n",
+- M_DIMINFO.MaxModIntsPerSec, NewMaxModIntsPerSec);
+- }
+- return;
+- } else {
+- if (M_DIMINFO.DisplayStats) {
+- printk("Resized ModTim from %i to %i ints/sec\n",
+- M_DIMINFO.MaxModIntsPerSec, NewMaxModIntsPerSec);
+- }
+- }
+-
+- M_DIMINFO.MaxModIntsPerSec = NewMaxModIntsPerSec;
+-
+- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+- ModBase = C_CLK_FREQ_GENESIS / pAC->DynIrqModInfo.MaxModIntsPerSec;
+- } else {
+- ModBase = C_CLK_FREQ_YUKON / pAC->DynIrqModInfo.MaxModIntsPerSec;
+- }
+-
+- /*
+- ** We do not need to touch any other registers
+- */
+- SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase);
+-}
+-
+-/*******************************************************************************
+-** Function : DisplaySelectedModerationType()
+-** Description : Displays what type of moderation we have
+-** Programmer : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns : void!
+-** Notes : -
+-*******************************************************************************/
+-
+-static void
+-DisplaySelectedModerationType(SK_AC *pAC) {
+-
+- if (pAC->DynIrqModInfo.DisplayStats) {
+- if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC) {
+- printk("Static int moderation runs with %i INTS/sec\n",
+- pAC->DynIrqModInfo.MaxModIntsPerSec);
+- } else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
+- if (IsIntModEnabled(pAC)) {
+- printk("Dynamic int moderation runs with %i INTS/sec\n",
+- pAC->DynIrqModInfo.MaxModIntsPerSec);
+- } else {
+- printk("Dynamic int moderation currently not applied\n");
+- }
+- } else {
+- printk("No interrupt moderation selected!\n");
+- }
+- }
+-}
+-
+-/*******************************************************************************
+-** Function : DisplaySelectedModerationMask()
+-** Description : Displays what interrupts are moderated
+-** Programmer : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns : void!
+-** Notes : -
+-*******************************************************************************/
+-
+-static void
+-DisplaySelectedModerationMask(SK_AC *pAC) {
+-
+- if (pAC->DynIrqModInfo.DisplayStats) {
+- if (pAC->DynIrqModInfo.IntModTypeSelect != C_INT_MOD_NONE) {
+- switch (pAC->DynIrqModInfo.MaskIrqModeration) {
+- case IRQ_MASK_TX_ONLY:
+- printk("Only Tx-interrupts are moderated\n");
+- break;
+- case IRQ_MASK_RX_ONLY:
+- printk("Only Rx-interrupts are moderated\n");
+- break;
+- case IRQ_MASK_SP_ONLY:
+- printk("Only special-interrupts are moderated\n");
+- break;
+- case IRQ_MASK_TX_RX:
+- printk("Tx- and Rx-interrupts are moderated\n");
+- break;
+- case IRQ_MASK_SP_RX:
+- printk("Special- and Rx-interrupts are moderated\n");
+- break;
+- case IRQ_MASK_SP_TX:
+- printk("Special- and Tx-interrupts are moderated\n");
+- break;
+- case IRQ_MASK_RX_TX_SP:
+- printk("All Rx-, Tx and special-interrupts are moderated\n");
+- break;
+- default:
+- printk("Don't know what is moderated\n");
+- break;
+- }
+- } else {
+- printk("No specific interrupts masked for moderation\n");
+- }
+- }
+-}
+-
+-/*******************************************************************************
+-** Function : DisplayDescrRatio
+-** Description : Like the name states...
+-** Programmer : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns : void!
+-** Notes : -
+-*******************************************************************************/
+-
+-static void
+-DisplayDescrRatio(SK_AC *pAC) {
+- int TotalMaxNbrDescr = 0;
+-
+- if (pAC->DynIrqModInfo.DisplayStats) {
+- TotalMaxNbrDescr = pAC->RxDescrPerRing * GetRxCalls(pAC);
+- printk("Ratio descriptors: %i/%i\n",
+- M_DIMINFO.NbrProcessedDescr, TotalMaxNbrDescr);
+- }
+-}
+-
+-/*******************************************************************************
+-**
+-** End of file
+-**
+-*******************************************************************************/
+diff --git a/drivers/net/sk98lin/skethtool.c b/drivers/net/sk98lin/skethtool.c
+deleted file mode 100644
+index 5a6da89..0000000
+--- a/drivers/net/sk98lin/skethtool.c
++++ /dev/null
+@@ -1,627 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skethtool.c
+- * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.7 $
+- * Date: $Date: 2004/09/29 13:32:07 $
+- * Purpose: All functions regarding ethtool handling
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2004 Marvell.
+- *
+- * Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet
+- * Server Adapters.
+- *
+- * Author: Ralph Roesler (rroesler at syskonnect.de)
+- * Mirko Lindner (mlindner at syskonnect.de)
+- *
+- * Address all question to: linux at syskonnect.de
+- *
+- * The technical manual for the adapters is available from SysKonnect's
+- * web pages: www.syskonnect.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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- *****************************************************************************/
+-
+-#include "h/skdrv1st.h"
+-#include "h/skdrv2nd.h"
+-#include "h/skversion.h"
+-
+-#include <linux/ethtool.h>
+-#include <linux/timer.h>
+-#include <linux/delay.h>
+-
+-/******************************************************************************
+- *
+- * Defines
+- *
+- *****************************************************************************/
+-
+-#define SUPP_COPPER_ALL (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
+- SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
+- SUPPORTED_1000baseT_Half| SUPPORTED_1000baseT_Full| \
+- SUPPORTED_TP)
+-
+-#define ADV_COPPER_ALL (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \
+- ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
+- ADVERTISED_1000baseT_Half| ADVERTISED_1000baseT_Full| \
+- ADVERTISED_TP)
+-
+-#define SUPP_FIBRE_ALL (SUPPORTED_1000baseT_Full | \
+- SUPPORTED_FIBRE | \
+- SUPPORTED_Autoneg)
+-
+-#define ADV_FIBRE_ALL (ADVERTISED_1000baseT_Full | \
+- ADVERTISED_FIBRE | \
+- ADVERTISED_Autoneg)
+-
+-
+-/******************************************************************************
+- *
+- * Local Functions
+- *
+- *****************************************************************************/
+-
+-/*****************************************************************************
+- *
+- * getSettings - retrieves the current settings of the selected adapter
+- *
+- * Description:
+- * The current configuration of the selected adapter is returned.
+- * This configuration involves a)speed, b)duplex and c)autoneg plus
+- * a number of other variables.
+- *
+- * Returns: always 0
+- *
+- */
+-static int getSettings(struct net_device *dev, struct ethtool_cmd *ecmd)
+-{
+- const DEV_NET *pNet = netdev_priv(dev);
+- int port = pNet->PortNr;
+- const SK_AC *pAC = pNet->pAC;
+- const SK_GEPORT *pPort = &pAC->GIni.GP[port];
+-
+- static int DuplexAutoNegConfMap[9][3]= {
+- { -1 , -1 , -1 },
+- { 0 , -1 , -1 },
+- { SK_LMODE_HALF , DUPLEX_HALF, AUTONEG_DISABLE },
+- { SK_LMODE_FULL , DUPLEX_FULL, AUTONEG_DISABLE },
+- { SK_LMODE_AUTOHALF , DUPLEX_HALF, AUTONEG_ENABLE },
+- { SK_LMODE_AUTOFULL , DUPLEX_FULL, AUTONEG_ENABLE },
+- { SK_LMODE_AUTOBOTH , DUPLEX_FULL, AUTONEG_ENABLE },
+- { SK_LMODE_AUTOSENSE , -1 , -1 },
+- { SK_LMODE_INDETERMINATED, -1 , -1 }
+- };
+- static int SpeedConfMap[6][2] = {
+- { 0 , -1 },
+- { SK_LSPEED_AUTO , -1 },
+- { SK_LSPEED_10MBPS , SPEED_10 },
+- { SK_LSPEED_100MBPS , SPEED_100 },
+- { SK_LSPEED_1000MBPS , SPEED_1000 },
+- { SK_LSPEED_INDETERMINATED, -1 }
+- };
+- static int AdvSpeedMap[6][2] = {
+- { 0 , -1 },
+- { SK_LSPEED_AUTO , -1 },
+- { SK_LSPEED_10MBPS , ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full },
+- { SK_LSPEED_100MBPS , ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full },
+- { SK_LSPEED_1000MBPS , ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full},
+- { SK_LSPEED_INDETERMINATED, -1 }
+- };
+-
+- ecmd->phy_address = port;
+- ecmd->speed = SpeedConfMap[pPort->PLinkSpeedUsed][1];
+- ecmd->duplex = DuplexAutoNegConfMap[pPort->PLinkModeStatus][1];
+- ecmd->autoneg = DuplexAutoNegConfMap[pPort->PLinkModeStatus][2];
+- ecmd->transceiver = XCVR_INTERNAL;
+-
+- if (pAC->GIni.GICopperType) {
+- ecmd->port = PORT_TP;
+- ecmd->supported = (SUPP_COPPER_ALL|SUPPORTED_Autoneg);
+- if (pAC->GIni.GIGenesis) {
+- ecmd->supported &= ~(SUPPORTED_10baseT_Half);
+- ecmd->supported &= ~(SUPPORTED_10baseT_Full);
+- ecmd->supported &= ~(SUPPORTED_100baseT_Half);
+- ecmd->supported &= ~(SUPPORTED_100baseT_Full);
+- } else {
+- if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
+- ecmd->supported &= ~(SUPPORTED_1000baseT_Half);
+- }
+-#ifdef CHIP_ID_YUKON_FE
+- if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) {
+- ecmd->supported &= ~(SUPPORTED_1000baseT_Half);
+- ecmd->supported &= ~(SUPPORTED_1000baseT_Full);
+- }
+-#endif
+- }
+- if (pAC->GIni.GP[0].PLinkSpeed != SK_LSPEED_AUTO) {
+- ecmd->advertising = AdvSpeedMap[pPort->PLinkSpeed][1];
+- if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
+- ecmd->advertising &= ~(SUPPORTED_1000baseT_Half);
+- }
+- } else {
+- ecmd->advertising = ecmd->supported;
+- }
+-
+- if (ecmd->autoneg == AUTONEG_ENABLE)
+- ecmd->advertising |= ADVERTISED_Autoneg;
+- } else {
+- ecmd->port = PORT_FIBRE;
+- ecmd->supported = SUPP_FIBRE_ALL;
+- ecmd->advertising = ADV_FIBRE_ALL;
+- }
+- return 0;
+-}
+-
+-/*
+- * MIB infrastructure uses instance value starting at 1
+- * based on board and port.
+- */
+-static inline u32 pnmiInstance(const DEV_NET *pNet)
+-{
+- return 1 + (pNet->pAC->RlmtNets == 2) + pNet->PortNr;
+-}
+-
+-/*****************************************************************************
+- *
+- * setSettings - configures the settings of a selected adapter
+- *
+- * Description:
+- * Possible settings that may be altered are a)speed, b)duplex or
+- * c)autonegotiation.
+- *
+- * Returns:
+- * 0: everything fine, no error
+- * <0: the return value is the error code of the failure
+- */
+-static int setSettings(struct net_device *dev, struct ethtool_cmd *ecmd)
+-{
+- DEV_NET *pNet = netdev_priv(dev);
+- SK_AC *pAC = pNet->pAC;
+- u32 instance;
+- char buf[4];
+- int len = 1;
+-
+- if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100
+- && ecmd->speed != SPEED_1000)
+- return -EINVAL;
+-
+- if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
+- return -EINVAL;
+-
+- if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE)
+- return -EINVAL;
+-
+- if (ecmd->autoneg == AUTONEG_DISABLE)
+- *buf = (ecmd->duplex == DUPLEX_FULL)
+- ? SK_LMODE_FULL : SK_LMODE_HALF;
+- else
+- *buf = (ecmd->duplex == DUPLEX_FULL)
+- ? SK_LMODE_AUTOFULL : SK_LMODE_AUTOHALF;
+-
+- instance = pnmiInstance(pNet);
+- if (SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_LINK_MODE,
+- &buf, &len, instance, pNet->NetNr) != SK_PNMI_ERR_OK)
+- return -EINVAL;
+-
+- switch(ecmd->speed) {
+- case SPEED_1000:
+- *buf = SK_LSPEED_1000MBPS;
+- break;
+- case SPEED_100:
+- *buf = SK_LSPEED_100MBPS;
+- break;
+- case SPEED_10:
+- *buf = SK_LSPEED_10MBPS;
+- }
+-
+- if (SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE,
+- &buf, &len, instance, pNet->NetNr) != SK_PNMI_ERR_OK)
+- return -EINVAL;
+-
+- return 0;
+-}
+-
+-/*****************************************************************************
+- *
+- * getDriverInfo - returns generic driver and adapter information
+- *
+- * Description:
+- * Generic driver information is returned via this function, such as
+- * the name of the driver, its version and and firmware version.
+- * In addition to this, the location of the selected adapter is
+- * returned as a bus info string (e.g. '01:05.0').
+- *
+- * Returns: N/A
+- *
+- */
+-static void getDriverInfo(struct net_device *dev, struct ethtool_drvinfo *info)
+-{
+- const DEV_NET *pNet = netdev_priv(dev);
+- const SK_AC *pAC = pNet->pAC;
+- char vers[32];
+-
+- snprintf(vers, sizeof(vers)-1, VER_STRING "(v%d.%d)",
+- (pAC->GIni.GIPciHwRev >> 4) & 0xf, pAC->GIni.GIPciHwRev & 0xf);
+-
+- strlcpy(info->driver, DRIVER_FILE_NAME, sizeof(info->driver));
+- strcpy(info->version, vers);
+- strcpy(info->fw_version, "N/A");
+- strlcpy(info->bus_info, pci_name(pAC->PciDev), ETHTOOL_BUSINFO_LEN);
+-}
+-
+-/*
+- * Ethtool statistics support.
+- */
+-static const char StringsStats[][ETH_GSTRING_LEN] = {
+- "rx_packets", "tx_packets",
+- "rx_bytes", "tx_bytes",
+- "rx_errors", "tx_errors",
+- "rx_dropped", "tx_dropped",
+- "multicasts", "collisions",
+- "rx_length_errors", "rx_buffer_overflow_errors",
+- "rx_crc_errors", "rx_frame_errors",
+- "rx_too_short_errors", "rx_too_long_errors",
+- "rx_carrier_extension_errors", "rx_symbol_errors",
+- "rx_llc_mac_size_errors", "rx_carrier_errors",
+- "rx_jabber_errors", "rx_missed_errors",
+- "tx_abort_collision_errors", "tx_carrier_errors",
+- "tx_buffer_underrun_errors", "tx_heartbeat_errors",
+- "tx_window_errors",
+-};
+-
+-static int getStatsCount(struct net_device *dev)
+-{
+- return ARRAY_SIZE(StringsStats);
+-}
+-
+-static void getStrings(struct net_device *dev, u32 stringset, u8 *data)
+-{
+- switch(stringset) {
+- case ETH_SS_STATS:
+- memcpy(data, *StringsStats, sizeof(StringsStats));
+- break;
+- }
+-}
+-
+-static void getEthtoolStats(struct net_device *dev,
+- struct ethtool_stats *stats, u64 *data)
+-{
+- const DEV_NET *pNet = netdev_priv(dev);
+- const SK_AC *pAC = pNet->pAC;
+- const SK_PNMI_STRUCT_DATA *pPnmiStruct = &pAC->PnmiStruct;
+-
+- *data++ = pPnmiStruct->Stat[0].StatRxOkCts;
+- *data++ = pPnmiStruct->Stat[0].StatTxOkCts;
+- *data++ = pPnmiStruct->Stat[0].StatRxOctetsOkCts;
+- *data++ = pPnmiStruct->Stat[0].StatTxOctetsOkCts;
+- *data++ = pPnmiStruct->InErrorsCts;
+- *data++ = pPnmiStruct->Stat[0].StatTxSingleCollisionCts;
+- *data++ = pPnmiStruct->RxNoBufCts;
+- *data++ = pPnmiStruct->TxNoBufCts;
+- *data++ = pPnmiStruct->Stat[0].StatRxMulticastOkCts;
+- *data++ = pPnmiStruct->Stat[0].StatTxSingleCollisionCts;
+- *data++ = pPnmiStruct->Stat[0].StatRxRuntCts;
+- *data++ = pPnmiStruct->Stat[0].StatRxFifoOverflowCts;
+- *data++ = pPnmiStruct->Stat[0].StatRxFcsCts;
+- *data++ = pPnmiStruct->Stat[0].StatRxFramingCts;
+- *data++ = pPnmiStruct->Stat[0].StatRxShortsCts;
+- *data++ = pPnmiStruct->Stat[0].StatRxTooLongCts;
+- *data++ = pPnmiStruct->Stat[0].StatRxCextCts;
+- *data++ = pPnmiStruct->Stat[0].StatRxSymbolCts;
+- *data++ = pPnmiStruct->Stat[0].StatRxIRLengthCts;
+- *data++ = pPnmiStruct->Stat[0].StatRxCarrierCts;
+- *data++ = pPnmiStruct->Stat[0].StatRxJabberCts;
+- *data++ = pPnmiStruct->Stat[0].StatRxMissedCts;
+- *data++ = pAC->stats.tx_aborted_errors;
+- *data++ = pPnmiStruct->Stat[0].StatTxCarrierCts;
+- *data++ = pPnmiStruct->Stat[0].StatTxFifoUnderrunCts;
+- *data++ = pPnmiStruct->Stat[0].StatTxCarrierCts;
+- *data++ = pAC->stats.tx_window_errors;
+-}
+-
+-
+-/*****************************************************************************
+- *
+- * toggleLeds - Changes the LED state of an adapter
+- *
+- * Description:
+- * This function changes the current state of all LEDs of an adapter so
+- * that it can be located by a user.
+- *
+- * Returns: N/A
+- *
+- */
+-static void toggleLeds(DEV_NET *pNet, int on)
+-{
+- SK_AC *pAC = pNet->pAC;
+- int port = pNet->PortNr;
+- void __iomem *io = pAC->IoBase;
+-
+- if (pAC->GIni.GIGenesis) {
+- SK_OUT8(io, MR_ADDR(port,LNK_LED_REG),
+- on ? SK_LNK_ON : SK_LNK_OFF);
+- SkGeYellowLED(pAC, io,
+- on ? (LED_ON >> 1) : (LED_OFF >> 1));
+- SkGeXmitLED(pAC, io, MR_ADDR(port,RX_LED_INI),
+- on ? SK_LED_TST : SK_LED_DIS);
+-
+- if (pAC->GIni.GP[port].PhyType == SK_PHY_BCOM)
+- SkXmPhyWrite(pAC, io, port, PHY_BCOM_P_EXT_CTRL,
+- on ? PHY_B_PEC_LED_ON : PHY_B_PEC_LED_OFF);
+- else if (pAC->GIni.GP[port].PhyType == SK_PHY_LONE)
+- SkXmPhyWrite(pAC, io, port, PHY_LONE_LED_CFG,
+- on ? 0x0800 : PHY_L_LC_LEDT);
+- else
+- SkGeXmitLED(pAC, io, MR_ADDR(port,TX_LED_INI),
+- on ? SK_LED_TST : SK_LED_DIS);
+- } else {
+- const u16 YukLedOn = (PHY_M_LED_MO_DUP(MO_LED_ON) |
+- PHY_M_LED_MO_10(MO_LED_ON) |
+- PHY_M_LED_MO_100(MO_LED_ON) |
+- PHY_M_LED_MO_1000(MO_LED_ON) |
+- PHY_M_LED_MO_RX(MO_LED_ON));
+- const u16 YukLedOff = (PHY_M_LED_MO_DUP(MO_LED_OFF) |
+- PHY_M_LED_MO_10(MO_LED_OFF) |
+- PHY_M_LED_MO_100(MO_LED_OFF) |
+- PHY_M_LED_MO_1000(MO_LED_OFF) |
+- PHY_M_LED_MO_RX(MO_LED_OFF));
+-
+-
+- SkGmPhyWrite(pAC,io,port,PHY_MARV_LED_CTRL,0);
+- SkGmPhyWrite(pAC,io,port,PHY_MARV_LED_OVER,
+- on ? YukLedOn : YukLedOff);
+- }
+-}
+-
+-/*****************************************************************************
+- *
+- * skGeBlinkTimer - Changes the LED state of an adapter
+- *
+- * Description:
+- * This function changes the current state of all LEDs of an adapter so
+- * that it can be located by a user. If the requested time interval for
+- * this test has elapsed, this function cleans up everything that was
+- * temporarily setup during the locate NIC test. This involves of course
+- * also closing or opening any adapter so that the initial board state
+- * is recovered.
+- *
+- * Returns: N/A
+- *
+- */
+-void SkGeBlinkTimer(unsigned long data)
+-{
+- struct net_device *dev = (struct net_device *) data;
+- DEV_NET *pNet = netdev_priv(dev);
+- SK_AC *pAC = pNet->pAC;
+-
+- toggleLeds(pNet, pAC->LedsOn);
+-
+- pAC->LedsOn = !pAC->LedsOn;
+- mod_timer(&pAC->BlinkTimer, jiffies + HZ/4);
+-}
+-
+-/*****************************************************************************
+- *
+- * locateDevice - start the locate NIC feature of the elected adapter
+- *
+- * Description:
+- * This function is used if the user want to locate a particular NIC.
+- * All LEDs are regularly switched on and off, so the NIC can easily
+- * be identified.
+- *
+- * Returns:
+- * ==0: everything fine, no error, locateNIC test was started
+- * !=0: one locateNIC test runs already
+- *
+- */
+-static int locateDevice(struct net_device *dev, u32 data)
+-{
+- DEV_NET *pNet = netdev_priv(dev);
+- SK_AC *pAC = pNet->pAC;
+-
+- if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
+- data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
+-
+- /* start blinking */
+- pAC->LedsOn = 0;
+- mod_timer(&pAC->BlinkTimer, jiffies);
+- msleep_interruptible(data * 1000);
+- del_timer_sync(&pAC->BlinkTimer);
+- toggleLeds(pNet, 0);
+-
+- return 0;
+-}
+-
+-/*****************************************************************************
+- *
+- * getPauseParams - retrieves the pause parameters
+- *
+- * Description:
+- * All current pause parameters of a selected adapter are placed
+- * in the passed ethtool_pauseparam structure and are returned.
+- *
+- * Returns: N/A
+- *
+- */
+-static void getPauseParams(struct net_device *dev, struct ethtool_pauseparam *epause)
+-{
+- DEV_NET *pNet = netdev_priv(dev);
+- SK_AC *pAC = pNet->pAC;
+- SK_GEPORT *pPort = &pAC->GIni.GP[pNet->PortNr];
+-
+- epause->rx_pause = (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC) ||
+- (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM);
+-
+- epause->tx_pause = epause->rx_pause || (pPort->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND);
+- epause->autoneg = epause->rx_pause || epause->tx_pause;
+-}
+-
+-/*****************************************************************************
+- *
+- * setPauseParams - configures the pause parameters of an adapter
+- *
+- * Description:
+- * This function sets the Rx or Tx pause parameters
+- *
+- * Returns:
+- * ==0: everything fine, no error
+- * !=0: the return value is the error code of the failure
+- */
+-static int setPauseParams(struct net_device *dev , struct ethtool_pauseparam *epause)
+-{
+- DEV_NET *pNet = netdev_priv(dev);
+- SK_AC *pAC = pNet->pAC;
+- SK_GEPORT *pPort = &pAC->GIni.GP[pNet->PortNr];
+- u32 instance = pnmiInstance(pNet);
+- struct ethtool_pauseparam old;
+- u8 oldspeed = pPort->PLinkSpeedUsed;
+- char buf[4];
+- int len = 1;
+- int ret;
+-
+- /*
+- ** we have to determine the current settings to see if
+- ** the operator requested any modification of the flow
+- ** control parameters...
+- */
+- getPauseParams(dev, &old);
+-
+- /*
+- ** perform modifications regarding the changes
+- ** requested by the operator
+- */
+- if (epause->autoneg != old.autoneg)
+- *buf = epause->autoneg ? SK_FLOW_MODE_NONE : SK_FLOW_MODE_SYMMETRIC;
+- else {
+- if (epause->rx_pause && epause->tx_pause)
+- *buf = SK_FLOW_MODE_SYMMETRIC;
+- else if (epause->rx_pause && !epause->tx_pause)
+- *buf = SK_FLOW_MODE_SYM_OR_REM;
+- else if (!epause->rx_pause && epause->tx_pause)
+- *buf = SK_FLOW_MODE_LOC_SEND;
+- else
+- *buf = SK_FLOW_MODE_NONE;
+- }
+-
+- ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_FLOWCTRL_MODE,
+- &buf, &len, instance, pNet->NetNr);
+-
+- if (ret != SK_PNMI_ERR_OK) {
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL,
+- ("ethtool (sk98lin): error changing rx/tx pause (%i)\n", ret));
+- goto err;
+- }
+-
+- /*
+- ** It may be that autoneg has been disabled! Therefore
+- ** set the speed to the previously used value...
+- */
+- if (!epause->autoneg) {
+- len = 1;
+- ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE,
+- &oldspeed, &len, instance, pNet->NetNr);
+- if (ret != SK_PNMI_ERR_OK)
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL,
+- ("ethtool (sk98lin): error setting speed (%i)\n", ret));
+- }
+- err:
+- return ret ? -EIO : 0;
+-}
+-
+-/* Only Yukon supports checksum offload. */
+-static int setScatterGather(struct net_device *dev, u32 data)
+-{
+- DEV_NET *pNet = netdev_priv(dev);
+- SK_AC *pAC = pNet->pAC;
+-
+- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
+- return -EOPNOTSUPP;
+- return ethtool_op_set_sg(dev, data);
+-}
+-
+-static int setTxCsum(struct net_device *dev, u32 data)
+-{
+- DEV_NET *pNet = netdev_priv(dev);
+- SK_AC *pAC = pNet->pAC;
+-
+- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
+- return -EOPNOTSUPP;
+-
+- return ethtool_op_set_tx_csum(dev, data);
+-}
+-
+-static u32 getRxCsum(struct net_device *dev)
+-{
+- DEV_NET *pNet = netdev_priv(dev);
+- SK_AC *pAC = pNet->pAC;
+-
+- return pAC->RxPort[pNet->PortNr].RxCsum;
+-}
+-
+-static int setRxCsum(struct net_device *dev, u32 data)
+-{
+- DEV_NET *pNet = netdev_priv(dev);
+- SK_AC *pAC = pNet->pAC;
+-
+- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
+- return -EOPNOTSUPP;
+-
+- pAC->RxPort[pNet->PortNr].RxCsum = data != 0;
+- return 0;
+-}
+-
+-static int getRegsLen(struct net_device *dev)
+-{
+- return 0x4000;
+-}
+-
+-/*
+- * Returns copy of whole control register region
+- * Note: skip RAM address register because accessing it will
+- * cause bus hangs!
+- */
+-static void getRegs(struct net_device *dev, struct ethtool_regs *regs,
+- void *p)
+-{
+- DEV_NET *pNet = netdev_priv(dev);
+- const void __iomem *io = pNet->pAC->IoBase;
+-
+- regs->version = 1;
+- memset(p, 0, regs->len);
+- memcpy_fromio(p, io, B3_RAM_ADDR);
+-
+- memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1,
+- regs->len - B3_RI_WTO_R1);
+-}
+-
+-const struct ethtool_ops SkGeEthtoolOps = {
+- .get_settings = getSettings,
+- .set_settings = setSettings,
+- .get_drvinfo = getDriverInfo,
+- .get_strings = getStrings,
+- .get_stats_count = getStatsCount,
+- .get_ethtool_stats = getEthtoolStats,
+- .phys_id = locateDevice,
+- .get_pauseparam = getPauseParams,
+- .set_pauseparam = setPauseParams,
+- .get_link = ethtool_op_get_link,
+- .get_sg = ethtool_op_get_sg,
+- .set_sg = setScatterGather,
+- .get_tx_csum = ethtool_op_get_tx_csum,
+- .set_tx_csum = setTxCsum,
+- .get_rx_csum = getRxCsum,
+- .set_rx_csum = setRxCsum,
+- .get_regs = getRegs,
+- .get_regs_len = getRegsLen,
+-};
+diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
+deleted file mode 100644
+index 20890e4..0000000
+--- a/drivers/net/sk98lin/skge.c
++++ /dev/null
+@@ -1,5218 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skge.c
+- * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.45 $
+- * Date: $Date: 2004/02/12 14:41:02 $
+- * Purpose: The main driver source module
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * Driver for Marvell Yukon chipset and SysKonnect Gigabit Ethernet
+- * Server Adapters.
+- *
+- * Created 10-Feb-1999, based on Linux' acenic.c, 3c59x.c and
+- * SysKonnects GEnesis Solaris driver
+- * Author: Christoph Goos (cgoos at syskonnect.de)
+- * Mirko Lindner (mlindner at syskonnect.de)
+- *
+- * Address all question to: linux at syskonnect.de
+- *
+- * The technical manual for the adapters is available from SysKonnect's
+- * web pages: www.syskonnect.com
+- * Goto "Support" and search Knowledge Base for "manual".
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * Possible compiler options (#define xxx / -Dxxx):
+- *
+- * debugging can be enable by changing SK_DEBUG_CHKMOD and
+- * SK_DEBUG_CHKCAT in makefile (described there).
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * Description:
+- *
+- * This is the main module of the Linux GE driver.
+- *
+- * All source files except skge.c, skdrv1st.h, skdrv2nd.h and sktypes.h
+- * are part of SysKonnect's COMMON MODULES for the SK-98xx adapters.
+- * Those are used for drivers on multiple OS', so some thing may seem
+- * unnecessary complicated on Linux. Please do not try to 'clean up'
+- * them without VERY good reasons, because this will make it more
+- * difficult to keep the Linux driver in synchronisation with the
+- * other versions.
+- *
+- * Include file hierarchy:
+- *
+- * <linux/module.h>
+- *
+- * "h/skdrv1st.h"
+- * <linux/types.h>
+- * <linux/kernel.h>
+- * <linux/string.h>
+- * <linux/errno.h>
+- * <linux/ioport.h>
+- * <linux/slab.h>
+- * <linux/interrupt.h>
+- * <linux/pci.h>
+- * <linux/bitops.h>
+- * <asm/byteorder.h>
+- * <asm/io.h>
+- * <linux/netdevice.h>
+- * <linux/etherdevice.h>
+- * <linux/skbuff.h>
+- * those three depending on kernel version used:
+- * <linux/bios32.h>
+- * <linux/init.h>
+- * <asm/uaccess.h>
+- * <net/checksum.h>
+- *
+- * "h/skerror.h"
+- * "h/skdebug.h"
+- * "h/sktypes.h"
+- * "h/lm80.h"
+- * "h/xmac_ii.h"
+- *
+- * "h/skdrv2nd.h"
+- * "h/skqueue.h"
+- * "h/skgehwt.h"
+- * "h/sktimer.h"
+- * "h/ski2c.h"
+- * "h/skgepnmi.h"
+- * "h/skvpd.h"
+- * "h/skgehw.h"
+- * "h/skgeinit.h"
+- * "h/skaddr.h"
+- * "h/skgesirq.h"
+- * "h/skrlmt.h"
+- *
+- ******************************************************************************/
+-
+-#include "h/skversion.h"
+-
+-#include <linux/in.h>
+-#include <linux/module.h>
+-#include <linux/moduleparam.h>
+-#include <linux/init.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/ip.h>
+-#include <linux/mii.h>
+-#include <linux/mm.h>
+-
+-#include "h/skdrv1st.h"
+-#include "h/skdrv2nd.h"
+-
+-/*******************************************************************************
+- *
+- * Defines
+- *
+- ******************************************************************************/
+-
+-/* for debuging on x86 only */
+-/* #define BREAKPOINT() asm(" int $3"); */
+-
+-/* use the transmit hw checksum driver functionality */
+-#define USE_SK_TX_CHECKSUM
+-
+-/* use the receive hw checksum driver functionality */
+-#define USE_SK_RX_CHECKSUM
+-
+-/* use the scatter-gather functionality with sendfile() */
+-#define SK_ZEROCOPY
+-
+-/* use of a transmit complete interrupt */
+-#define USE_TX_COMPLETE
+-
+-/*
+- * threshold for copying small receive frames
+- * set to 0 to avoid copying, set to 9001 to copy all frames
+- */
+-#define SK_COPY_THRESHOLD 50
+-
+-/* number of adapters that can be configured via command line params */
+-#define SK_MAX_CARD_PARAM 16
+-
+-
+-
+-/*
+- * use those defines for a compile-in version of the driver instead
+- * of command line parameters
+- */
+-// #define LINK_SPEED_A {"Auto", }
+-// #define LINK_SPEED_B {"Auto", }
+-// #define AUTO_NEG_A {"Sense", }
+-// #define AUTO_NEG_B {"Sense", }
+-// #define DUP_CAP_A {"Both", }
+-// #define DUP_CAP_B {"Both", }
+-// #define FLOW_CTRL_A {"SymOrRem", }
+-// #define FLOW_CTRL_B {"SymOrRem", }
+-// #define ROLE_A {"Auto", }
+-// #define ROLE_B {"Auto", }
+-// #define PREF_PORT {"A", }
+-// #define CON_TYPE {"Auto", }
+-// #define RLMT_MODE {"CheckLinkState", }
+-
+-#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb)
+-#define DEV_KFREE_SKB_IRQ(skb) dev_kfree_skb_irq(skb)
+-#define DEV_KFREE_SKB_ANY(skb) dev_kfree_skb_any(skb)
+-
+-
+-/* Set blink mode*/
+-#define OEM_CONFIG_VALUE ( SK_ACT_LED_BLINK | \
+- SK_DUP_LED_NORMAL | \
+- SK_LED_LINK100_ON)
+-
+-
+-/* Isr return value */
+-#define SkIsrRetVar irqreturn_t
+-#define SkIsrRetNone IRQ_NONE
+-#define SkIsrRetHandled IRQ_HANDLED
+-
+-
+-/*******************************************************************************
+- *
+- * Local Function Prototypes
+- *
+- ******************************************************************************/
+-
+-static void FreeResources(struct SK_NET_DEVICE *dev);
+-static int SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC);
+-static SK_BOOL BoardAllocMem(SK_AC *pAC);
+-static void BoardFreeMem(SK_AC *pAC);
+-static void BoardInitMem(SK_AC *pAC);
+-static void SetupRing(SK_AC*, void*, uintptr_t, RXD**, RXD**, RXD**, int*, SK_BOOL);
+-static SkIsrRetVar SkGeIsr(int irq, void *dev_id);
+-static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id);
+-static int SkGeOpen(struct SK_NET_DEVICE *dev);
+-static int SkGeClose(struct SK_NET_DEVICE *dev);
+-static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev);
+-static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p);
+-static void SkGeSetRxMode(struct SK_NET_DEVICE *dev);
+-static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev);
+-static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd);
+-static void GetConfiguration(SK_AC*);
+-static int XmitFrame(SK_AC*, TX_PORT*, struct sk_buff*);
+-static void FreeTxDescriptors(SK_AC*pAC, TX_PORT*);
+-static void FillRxRing(SK_AC*, RX_PORT*);
+-static SK_BOOL FillRxDescriptor(SK_AC*, RX_PORT*);
+-static void ReceiveIrq(SK_AC*, RX_PORT*, SK_BOOL);
+-static void ClearAndStartRx(SK_AC*, int);
+-static void ClearTxIrq(SK_AC*, int, int);
+-static void ClearRxRing(SK_AC*, RX_PORT*);
+-static void ClearTxRing(SK_AC*, TX_PORT*);
+-static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int new_mtu);
+-static void PortReInitBmu(SK_AC*, int);
+-static int SkGeIocMib(DEV_NET*, unsigned int, int);
+-static int SkGeInitPCI(SK_AC *pAC);
+-static void StartDrvCleanupTimer(SK_AC *pAC);
+-static void StopDrvCleanupTimer(SK_AC *pAC);
+-static int XmitFrameSG(SK_AC*, TX_PORT*, struct sk_buff*);
+-
+-#ifdef SK_DIAG_SUPPORT
+-static SK_U32 ParseDeviceNbrFromSlotName(const char *SlotName);
+-static int SkDrvInitAdapter(SK_AC *pAC, int devNbr);
+-static int SkDrvDeInitAdapter(SK_AC *pAC, int devNbr);
+-#endif
+-
+-/*******************************************************************************
+- *
+- * Extern Function Prototypes
+- *
+- ******************************************************************************/
+-extern void SkDimEnableModerationIfNeeded(SK_AC *pAC);
+-extern void SkDimDisplayModerationSettings(SK_AC *pAC);
+-extern void SkDimStartModerationTimer(SK_AC *pAC);
+-extern void SkDimModerate(SK_AC *pAC);
+-extern void SkGeBlinkTimer(unsigned long data);
+-
+-#ifdef DEBUG
+-static void DumpMsg(struct sk_buff*, char*);
+-static void DumpData(char*, int);
+-static void DumpLong(char*, int);
+-#endif
+-
+-/* global variables *********************************************************/
+-static SK_BOOL DoPrintInterfaceChange = SK_TRUE;
+-extern const struct ethtool_ops SkGeEthtoolOps;
+-
+-/* local variables **********************************************************/
+-static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}};
+-static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480};
+-
+-/*****************************************************************************
+- *
+- * SkPciWriteCfgDWord - write a 32 bit value to pci config space
+- *
+- * Description:
+- * This routine writes a 32 bit value to the pci configuration
+- * space.
+- *
+- * Returns:
+- * 0 - indicate everything worked ok.
+- * != 0 - error indication
+- */
+-static inline int SkPciWriteCfgDWord(
+-SK_AC *pAC, /* Adapter Control structure pointer */
+-int PciAddr, /* PCI register address */
+-SK_U32 Val) /* pointer to store the read value */
+-{
+- pci_write_config_dword(pAC->PciDev, PciAddr, Val);
+- return(0);
+-} /* SkPciWriteCfgDWord */
+-
+-/*****************************************************************************
+- *
+- * SkGeInitPCI - Init the PCI resources
+- *
+- * Description:
+- * This function initialize the PCI resources and IO
+- *
+- * Returns:
+- * 0 - indicate everything worked ok.
+- * != 0 - error indication
+- */
+-static __devinit int SkGeInitPCI(SK_AC *pAC)
+-{
+- struct SK_NET_DEVICE *dev = pAC->dev[0];
+- struct pci_dev *pdev = pAC->PciDev;
+- int retval;
+-
+- dev->mem_start = pci_resource_start (pdev, 0);
+- pci_set_master(pdev);
+-
+- retval = pci_request_regions(pdev, "sk98lin");
+- if (retval)
+- goto out;
+-
+-#ifdef SK_BIG_ENDIAN
+- /*
+- * On big endian machines, we use the adapter's aibility of
+- * reading the descriptors as big endian.
+- */
+- {
+- SK_U32 our2;
+- SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2);
+- our2 |= PCI_REV_DESC;
+- SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2);
+- }
+-#endif
+-
+- /*
+- * Remap the regs into kernel space.
+- */
+- pAC->IoBase = ioremap_nocache(dev->mem_start, 0x4000);
+- if (!pAC->IoBase) {
+- retval = -EIO;
+- goto out_release;
+- }
+-
+- return 0;
+-
+- out_release:
+- pci_release_regions(pdev);
+- out:
+- return retval;
+-}
+-
+-
+-/*****************************************************************************
+- *
+- * FreeResources - release resources allocated for adapter
+- *
+- * Description:
+- * This function releases the IRQ, unmaps the IO and
+- * frees the desriptor ring.
+- *
+- * Returns: N/A
+- *
+- */
+-static void FreeResources(struct SK_NET_DEVICE *dev)
+-{
+-SK_U32 AllocFlag;
+-DEV_NET *pNet;
+-SK_AC *pAC;
+-
+- pNet = netdev_priv(dev);
+- pAC = pNet->pAC;
+- AllocFlag = pAC->AllocFlag;
+- if (pAC->PciDev) {
+- pci_release_regions(pAC->PciDev);
+- }
+- if (AllocFlag & SK_ALLOC_IRQ) {
+- free_irq(dev->irq, dev);
+- }
+- if (pAC->IoBase) {
+- iounmap(pAC->IoBase);
+- }
+- if (pAC->pDescrMem) {
+- BoardFreeMem(pAC);
+- }
+-
+-} /* FreeResources */
+-
+-MODULE_AUTHOR("Mirko Lindner <mlindner at syskonnect.de>");
+-MODULE_DESCRIPTION("SysKonnect SK-NET Gigabit Ethernet SK-98xx driver");
+-MODULE_LICENSE("GPL");
+-
+-#ifdef LINK_SPEED_A
+-static char *Speed_A[SK_MAX_CARD_PARAM] = LINK_SPEED;
+-#else
+-static char *Speed_A[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-#ifdef LINK_SPEED_B
+-static char *Speed_B[SK_MAX_CARD_PARAM] = LINK_SPEED;
+-#else
+-static char *Speed_B[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-#ifdef AUTO_NEG_A
+-static char *AutoNeg_A[SK_MAX_CARD_PARAM] = AUTO_NEG_A;
+-#else
+-static char *AutoNeg_A[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-#ifdef DUP_CAP_A
+-static char *DupCap_A[SK_MAX_CARD_PARAM] = DUP_CAP_A;
+-#else
+-static char *DupCap_A[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-#ifdef FLOW_CTRL_A
+-static char *FlowCtrl_A[SK_MAX_CARD_PARAM] = FLOW_CTRL_A;
+-#else
+-static char *FlowCtrl_A[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-#ifdef ROLE_A
+-static char *Role_A[SK_MAX_CARD_PARAM] = ROLE_A;
+-#else
+-static char *Role_A[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-#ifdef AUTO_NEG_B
+-static char *AutoNeg_B[SK_MAX_CARD_PARAM] = AUTO_NEG_B;
+-#else
+-static char *AutoNeg_B[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-#ifdef DUP_CAP_B
+-static char *DupCap_B[SK_MAX_CARD_PARAM] = DUP_CAP_B;
+-#else
+-static char *DupCap_B[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-#ifdef FLOW_CTRL_B
+-static char *FlowCtrl_B[SK_MAX_CARD_PARAM] = FLOW_CTRL_B;
+-#else
+-static char *FlowCtrl_B[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-#ifdef ROLE_B
+-static char *Role_B[SK_MAX_CARD_PARAM] = ROLE_B;
+-#else
+-static char *Role_B[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-#ifdef CON_TYPE
+-static char *ConType[SK_MAX_CARD_PARAM] = CON_TYPE;
+-#else
+-static char *ConType[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-#ifdef PREF_PORT
+-static char *PrefPort[SK_MAX_CARD_PARAM] = PREF_PORT;
+-#else
+-static char *PrefPort[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-#ifdef RLMT_MODE
+-static char *RlmtMode[SK_MAX_CARD_PARAM] = RLMT_MODE;
+-#else
+-static char *RlmtMode[SK_MAX_CARD_PARAM] = {"", };
+-#endif
+-
+-static int IntsPerSec[SK_MAX_CARD_PARAM];
+-static char *Moderation[SK_MAX_CARD_PARAM];
+-static char *ModerationMask[SK_MAX_CARD_PARAM];
+-static char *AutoSizing[SK_MAX_CARD_PARAM];
+-static char *Stats[SK_MAX_CARD_PARAM];
+-
+-module_param_array(Speed_A, charp, NULL, 0);
+-module_param_array(Speed_B, charp, NULL, 0);
+-module_param_array(AutoNeg_A, charp, NULL, 0);
+-module_param_array(AutoNeg_B, charp, NULL, 0);
+-module_param_array(DupCap_A, charp, NULL, 0);
+-module_param_array(DupCap_B, charp, NULL, 0);
+-module_param_array(FlowCtrl_A, charp, NULL, 0);
+-module_param_array(FlowCtrl_B, charp, NULL, 0);
+-module_param_array(Role_A, charp, NULL, 0);
+-module_param_array(Role_B, charp, NULL, 0);
+-module_param_array(ConType, charp, NULL, 0);
+-module_param_array(PrefPort, charp, NULL, 0);
+-module_param_array(RlmtMode, charp, NULL, 0);
+-/* used for interrupt moderation */
+-module_param_array(IntsPerSec, int, NULL, 0);
+-module_param_array(Moderation, charp, NULL, 0);
+-module_param_array(Stats, charp, NULL, 0);
+-module_param_array(ModerationMask, charp, NULL, 0);
+-module_param_array(AutoSizing, charp, NULL, 0);
+-
+-/*****************************************************************************
+- *
+- * SkGeBoardInit - do level 0 and 1 initialization
+- *
+- * Description:
+- * This function prepares the board hardware for running. The desriptor
+- * ring is set up, the IRQ is allocated and the configuration settings
+- * are examined.
+- *
+- * Returns:
+- * 0, if everything is ok
+- * !=0, on error
+- */
+-static int __devinit SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC)
+-{
+-short i;
+-unsigned long Flags;
+-char *DescrString = "sk98lin: Driver for Linux"; /* this is given to PNMI */
+-char *VerStr = VER_STRING;
+-int Ret; /* return code of request_irq */
+-SK_BOOL DualNet;
+-
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+- ("IoBase: %08lX\n", (unsigned long)pAC->IoBase));
+- for (i=0; i<SK_MAX_MACS; i++) {
+- pAC->TxPort[i][0].HwAddr = pAC->IoBase + TxQueueAddr[i][0];
+- pAC->TxPort[i][0].PortIndex = i;
+- pAC->RxPort[i].HwAddr = pAC->IoBase + RxQueueAddr[i];
+- pAC->RxPort[i].PortIndex = i;
+- }
+-
+- /* Initialize the mutexes */
+- for (i=0; i<SK_MAX_MACS; i++) {
+- spin_lock_init(&pAC->TxPort[i][0].TxDesRingLock);
+- spin_lock_init(&pAC->RxPort[i].RxDesRingLock);
+- }
+- spin_lock_init(&pAC->SlowPathLock);
+-
+- /* setup phy_id blink timer */
+- pAC->BlinkTimer.function = SkGeBlinkTimer;
+- pAC->BlinkTimer.data = (unsigned long) dev;
+- init_timer(&pAC->BlinkTimer);
+-
+- /* level 0 init common modules here */
+-
+- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+- /* Does a RESET on board ...*/
+- if (SkGeInit(pAC, pAC->IoBase, SK_INIT_DATA) != 0) {
+- printk("HWInit (0) failed.\n");
+- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+- return -EIO;
+- }
+- SkI2cInit( pAC, pAC->IoBase, SK_INIT_DATA);
+- SkEventInit(pAC, pAC->IoBase, SK_INIT_DATA);
+- SkPnmiInit( pAC, pAC->IoBase, SK_INIT_DATA);
+- SkAddrInit( pAC, pAC->IoBase, SK_INIT_DATA);
+- SkRlmtInit( pAC, pAC->IoBase, SK_INIT_DATA);
+- SkTimerInit(pAC, pAC->IoBase, SK_INIT_DATA);
+-
+- pAC->BoardLevel = SK_INIT_DATA;
+- pAC->RxBufSize = ETH_BUF_SIZE;
+-
+- SK_PNMI_SET_DRIVER_DESCR(pAC, DescrString);
+- SK_PNMI_SET_DRIVER_VER(pAC, VerStr);
+-
+- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-
+- /* level 1 init common modules here (HW init) */
+- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+- if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) {
+- printk("sk98lin: HWInit (1) failed.\n");
+- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+- return -EIO;
+- }
+- SkI2cInit( pAC, pAC->IoBase, SK_INIT_IO);
+- SkEventInit(pAC, pAC->IoBase, SK_INIT_IO);
+- SkPnmiInit( pAC, pAC->IoBase, SK_INIT_IO);
+- SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO);
+- SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO);
+- SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO);
+-
+- /* Set chipset type support */
+- pAC->ChipsetType = 0;
+- if ((pAC->GIni.GIChipId == CHIP_ID_YUKON) ||
+- (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE)) {
+- pAC->ChipsetType = 1;
+- }
+-
+- GetConfiguration(pAC);
+- if (pAC->RlmtNets == 2) {
+- pAC->GIni.GIPortUsage = SK_MUL_LINK;
+- }
+-
+- pAC->BoardLevel = SK_INIT_IO;
+- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-
+- if (pAC->GIni.GIMacsFound == 2) {
+- Ret = request_irq(dev->irq, SkGeIsr, IRQF_SHARED, "sk98lin", dev);
+- } else if (pAC->GIni.GIMacsFound == 1) {
+- Ret = request_irq(dev->irq, SkGeIsrOnePort, IRQF_SHARED,
+- "sk98lin", dev);
+- } else {
+- printk(KERN_WARNING "sk98lin: Illegal number of ports: %d\n",
+- pAC->GIni.GIMacsFound);
+- return -EIO;
+- }
+-
+- if (Ret) {
+- printk(KERN_WARNING "sk98lin: Requested IRQ %d is busy.\n",
+- dev->irq);
+- return Ret;
+- }
+- pAC->AllocFlag |= SK_ALLOC_IRQ;
+-
+- /* Alloc memory for this board (Mem for RxD/TxD) : */
+- if(!BoardAllocMem(pAC)) {
+- printk("No memory for descriptor rings.\n");
+- return -ENOMEM;
+- }
+-
+- BoardInitMem(pAC);
+- /* tschilling: New common function with minimum size check. */
+- DualNet = SK_FALSE;
+- if (pAC->RlmtNets == 2) {
+- DualNet = SK_TRUE;
+- }
+-
+- if (SkGeInitAssignRamToQueues(
+- pAC,
+- pAC->ActivePort,
+- DualNet)) {
+- BoardFreeMem(pAC);
+- printk("sk98lin: SkGeInitAssignRamToQueues failed.\n");
+- return -EIO;
+- }
+-
+- return (0);
+-} /* SkGeBoardInit */
+-
+-
+-/*****************************************************************************
+- *
+- * BoardAllocMem - allocate the memory for the descriptor rings
+- *
+- * Description:
+- * This function allocates the memory for all descriptor rings.
+- * Each ring is aligned for the desriptor alignment and no ring
+- * has a 4 GByte boundary in it (because the upper 32 bit must
+- * be constant for all descriptiors in one rings).
+- *
+- * Returns:
+- * SK_TRUE, if all memory could be allocated
+- * SK_FALSE, if not
+- */
+-static __devinit SK_BOOL BoardAllocMem(SK_AC *pAC)
+-{
+-caddr_t pDescrMem; /* pointer to descriptor memory area */
+-size_t AllocLength; /* length of complete descriptor area */
+-int i; /* loop counter */
+-unsigned long BusAddr;
+-
+-
+- /* rings plus one for alignment (do not cross 4 GB boundary) */
+- /* RX_RING_SIZE is assumed bigger than TX_RING_SIZE */
+-#if (BITS_PER_LONG == 32)
+- AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8;
+-#else
+- AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
+- + RX_RING_SIZE + 8;
+-#endif
+-
+- pDescrMem = pci_alloc_consistent(pAC->PciDev, AllocLength,
+- &pAC->pDescrMemDMA);
+-
+- if (pDescrMem == NULL) {
+- return (SK_FALSE);
+- }
+- pAC->pDescrMem = pDescrMem;
+- BusAddr = (unsigned long) pAC->pDescrMemDMA;
+-
+- /* Descriptors need 8 byte alignment, and this is ensured
+- * by pci_alloc_consistent.
+- */
+- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+- ("TX%d/A: pDescrMem: %lX, PhysDescrMem: %lX\n",
+- i, (unsigned long) pDescrMem,
+- BusAddr));
+- pAC->TxPort[i][0].pTxDescrRing = pDescrMem;
+- pAC->TxPort[i][0].VTxDescrRing = BusAddr;
+- pDescrMem += TX_RING_SIZE;
+- BusAddr += TX_RING_SIZE;
+-
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+- ("RX%d: pDescrMem: %lX, PhysDescrMem: %lX\n",
+- i, (unsigned long) pDescrMem,
+- (unsigned long)BusAddr));
+- pAC->RxPort[i].pRxDescrRing = pDescrMem;
+- pAC->RxPort[i].VRxDescrRing = BusAddr;
+- pDescrMem += RX_RING_SIZE;
+- BusAddr += RX_RING_SIZE;
+- } /* for */
+-
+- return (SK_TRUE);
+-} /* BoardAllocMem */
+-
+-
+-/****************************************************************************
+- *
+- * BoardFreeMem - reverse of BoardAllocMem
+- *
+- * Description:
+- * Free all memory allocated in BoardAllocMem: adapter context,
+- * descriptor rings, locks.
+- *
+- * Returns: N/A
+- */
+-static void BoardFreeMem(
+-SK_AC *pAC)
+-{
+-size_t AllocLength; /* length of complete descriptor area */
+-
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+- ("BoardFreeMem\n"));
+-#if (BITS_PER_LONG == 32)
+- AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8;
+-#else
+- AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
+- + RX_RING_SIZE + 8;
+-#endif
+-
+- pci_free_consistent(pAC->PciDev, AllocLength,
+- pAC->pDescrMem, pAC->pDescrMemDMA);
+- pAC->pDescrMem = NULL;
+-} /* BoardFreeMem */
+-
+-
+-/*****************************************************************************
+- *
+- * BoardInitMem - initiate the descriptor rings
+- *
+- * Description:
+- * This function sets the descriptor rings up in memory.
+- * The adapter is initialized with the descriptor start addresses.
+- *
+- * Returns: N/A
+- */
+-static __devinit void BoardInitMem(SK_AC *pAC)
+-{
+-int i; /* loop counter */
+-int RxDescrSize; /* the size of a rx descriptor rounded up to alignment*/
+-int TxDescrSize; /* the size of a tx descriptor rounded up to alignment*/
+-
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+- ("BoardInitMem\n"));
+-
+- RxDescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN;
+- pAC->RxDescrPerRing = RX_RING_SIZE / RxDescrSize;
+- TxDescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN;
+- pAC->TxDescrPerRing = TX_RING_SIZE / RxDescrSize;
+-
+- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+- SetupRing(
+- pAC,
+- pAC->TxPort[i][0].pTxDescrRing,
+- pAC->TxPort[i][0].VTxDescrRing,
+- (RXD**)&pAC->TxPort[i][0].pTxdRingHead,
+- (RXD**)&pAC->TxPort[i][0].pTxdRingTail,
+- (RXD**)&pAC->TxPort[i][0].pTxdRingPrev,
+- &pAC->TxPort[i][0].TxdRingFree,
+- SK_TRUE);
+- SetupRing(
+- pAC,
+- pAC->RxPort[i].pRxDescrRing,
+- pAC->RxPort[i].VRxDescrRing,
+- &pAC->RxPort[i].pRxdRingHead,
+- &pAC->RxPort[i].pRxdRingTail,
+- &pAC->RxPort[i].pRxdRingPrev,
+- &pAC->RxPort[i].RxdRingFree,
+- SK_FALSE);
+- }
+-} /* BoardInitMem */
+-
+-
+-/*****************************************************************************
+- *
+- * SetupRing - create one descriptor ring
+- *
+- * Description:
+- * This function creates one descriptor ring in the given memory area.
+- * The head, tail and number of free descriptors in the ring are set.
+- *
+- * Returns:
+- * none
+- */
+-static void SetupRing(
+-SK_AC *pAC,
+-void *pMemArea, /* a pointer to the memory area for the ring */
+-uintptr_t VMemArea, /* the virtual bus address of the memory area */
+-RXD **ppRingHead, /* address where the head should be written */
+-RXD **ppRingTail, /* address where the tail should be written */
+-RXD **ppRingPrev, /* address where the tail should be written */
+-int *pRingFree, /* address where the # of free descr. goes */
+-SK_BOOL IsTx) /* flag: is this a tx ring */
+-{
+-int i; /* loop counter */
+-int DescrSize; /* the size of a descriptor rounded up to alignment*/
+-int DescrNum; /* number of descriptors per ring */
+-RXD *pDescr; /* pointer to a descriptor (receive or transmit) */
+-RXD *pNextDescr; /* pointer to the next descriptor */
+-RXD *pPrevDescr; /* pointer to the previous descriptor */
+-uintptr_t VNextDescr; /* the virtual bus address of the next descriptor */
+-
+- if (IsTx == SK_TRUE) {
+- DescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) *
+- DESCR_ALIGN;
+- DescrNum = TX_RING_SIZE / DescrSize;
+- } else {
+- DescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) *
+- DESCR_ALIGN;
+- DescrNum = RX_RING_SIZE / DescrSize;
+- }
+-
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
+- ("Descriptor size: %d Descriptor Number: %d\n",
+- DescrSize,DescrNum));
+-
+- pDescr = (RXD*) pMemArea;
+- pPrevDescr = NULL;
+- pNextDescr = (RXD*) (((char*)pDescr) + DescrSize);
+- VNextDescr = VMemArea + DescrSize;
+- for(i=0; i<DescrNum; i++) {
+- /* set the pointers right */
+- pDescr->VNextRxd = VNextDescr & 0xffffffffULL;
+- pDescr->pNextRxd = pNextDescr;
+- if (!IsTx) pDescr->TcpSumStarts = ETH_HLEN << 16 | ETH_HLEN;
+-
+- /* advance one step */
+- pPrevDescr = pDescr;
+- pDescr = pNextDescr;
+- pNextDescr = (RXD*) (((char*)pDescr) + DescrSize);
+- VNextDescr += DescrSize;
+- }
+- pPrevDescr->pNextRxd = (RXD*) pMemArea;
+- pPrevDescr->VNextRxd = VMemArea;
+- pDescr = (RXD*) pMemArea;
+- *ppRingHead = (RXD*) pMemArea;
+- *ppRingTail = *ppRingHead;
+- *ppRingPrev = pPrevDescr;
+- *pRingFree = DescrNum;
+-} /* SetupRing */
+-
+-
+-/*****************************************************************************
+- *
+- * PortReInitBmu - re-initiate the descriptor rings for one port
+- *
+- * Description:
+- * This function reinitializes the descriptor rings of one port
+- * in memory. The port must be stopped before.
+- * The HW is initialized with the descriptor start addresses.
+- *
+- * Returns:
+- * none
+- */
+-static void PortReInitBmu(
+-SK_AC *pAC, /* pointer to adapter context */
+-int PortIndex) /* index of the port for which to re-init */
+-{
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+- ("PortReInitBmu "));
+-
+- /* set address of first descriptor of ring in BMU */
+- SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ Q_DA_L,
+- (uint32_t)(((caddr_t)
+- (pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) -
+- pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing +
+- pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) &
+- 0xFFFFFFFF));
+- SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ Q_DA_H,
+- (uint32_t)(((caddr_t)
+- (pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) -
+- pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing +
+- pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) >> 32));
+- SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_L,
+- (uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) -
+- pAC->RxPort[PortIndex].pRxDescrRing +
+- pAC->RxPort[PortIndex].VRxDescrRing) & 0xFFFFFFFF));
+- SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_H,
+- (uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) -
+- pAC->RxPort[PortIndex].pRxDescrRing +
+- pAC->RxPort[PortIndex].VRxDescrRing) >> 32));
+-} /* PortReInitBmu */
+-
+-
+-/****************************************************************************
+- *
+- * SkGeIsr - handle adapter interrupts
+- *
+- * Description:
+- * The interrupt routine is called when the network adapter
+- * generates an interrupt. It may also be called if another device
+- * shares this interrupt vector with the driver.
+- *
+- * Returns: N/A
+- *
+- */
+-static SkIsrRetVar SkGeIsr(int irq, void *dev_id)
+-{
+-struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
+-DEV_NET *pNet;
+-SK_AC *pAC;
+-SK_U32 IntSrc; /* interrupts source register contents */
+-
+- pNet = netdev_priv(dev);
+- pAC = pNet->pAC;
+-
+- /*
+- * Check and process if its our interrupt
+- */
+- SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc);
+- if (IntSrc == 0) {
+- return SkIsrRetNone;
+- }
+-
+- while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {
+-#if 0 /* software irq currently not used */
+- if (IntSrc & IS_IRQ_SW) {
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+- SK_DBGCAT_DRV_INT_SRC,
+- ("Software IRQ\n"));
+- }
+-#endif
+- if (IntSrc & IS_R1_F) {
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+- SK_DBGCAT_DRV_INT_SRC,
+- ("EOF RX1 IRQ\n"));
+- ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
+- SK_PNMI_CNT_RX_INTR(pAC, 0);
+- }
+- if (IntSrc & IS_R2_F) {
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+- SK_DBGCAT_DRV_INT_SRC,
+- ("EOF RX2 IRQ\n"));
+- ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE);
+- SK_PNMI_CNT_RX_INTR(pAC, 1);
+- }
+-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
+- if (IntSrc & IS_XA1_F) {
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+- SK_DBGCAT_DRV_INT_SRC,
+- ("EOF AS TX1 IRQ\n"));
+- SK_PNMI_CNT_TX_INTR(pAC, 0);
+- spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
+- FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
+- spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
+- }
+- if (IntSrc & IS_XA2_F) {
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+- SK_DBGCAT_DRV_INT_SRC,
+- ("EOF AS TX2 IRQ\n"));
+- SK_PNMI_CNT_TX_INTR(pAC, 1);
+- spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
+- FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]);
+- spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
+- }
+-#if 0 /* only if sync. queues used */
+- if (IntSrc & IS_XS1_F) {
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+- SK_DBGCAT_DRV_INT_SRC,
+- ("EOF SY TX1 IRQ\n"));
+- SK_PNMI_CNT_TX_INTR(pAC, 1);
+- spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
+- FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
+- spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
+- ClearTxIrq(pAC, 0, TX_PRIO_HIGH);
+- }
+- if (IntSrc & IS_XS2_F) {
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+- SK_DBGCAT_DRV_INT_SRC,
+- ("EOF SY TX2 IRQ\n"));
+- SK_PNMI_CNT_TX_INTR(pAC, 1);
+- spin_lock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
+- FreeTxDescriptors(pAC, 1, TX_PRIO_HIGH);
+- spin_unlock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
+- ClearTxIrq(pAC, 1, TX_PRIO_HIGH);
+- }
+-#endif
+-#endif
+-
+- /* do all IO at once */
+- if (IntSrc & IS_R1_F)
+- ClearAndStartRx(pAC, 0);
+- if (IntSrc & IS_R2_F)
+- ClearAndStartRx(pAC, 1);
+-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
+- if (IntSrc & IS_XA1_F)
+- ClearTxIrq(pAC, 0, TX_PRIO_LOW);
+- if (IntSrc & IS_XA2_F)
+- ClearTxIrq(pAC, 1, TX_PRIO_LOW);
+-#endif
+- SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc);
+- } /* while (IntSrc & IRQ_MASK != 0) */
+-
+- IntSrc &= pAC->GIni.GIValIrqMask;
+- if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) {
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
+- ("SPECIAL IRQ DP-Cards => %x\n", IntSrc));
+- pAC->CheckQueue = SK_FALSE;
+- spin_lock(&pAC->SlowPathLock);
+- if (IntSrc & SPECIAL_IRQS)
+- SkGeSirqIsr(pAC, pAC->IoBase, IntSrc);
+-
+- SkEventDispatcher(pAC, pAC->IoBase);
+- spin_unlock(&pAC->SlowPathLock);
+- }
+- /*
+- * do it all again is case we cleared an interrupt that
+- * came in after handling the ring (OUTs may be delayed
+- * in hardware buffers, but are through after IN)
+- *
+- * rroesler: has been commented out and shifted to
+- * SkGeDrvEvent(), because it is timer
+- * guarded now
+- *
+- ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
+- ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE);
+- */
+-
+- if (pAC->CheckQueue) {
+- pAC->CheckQueue = SK_FALSE;
+- spin_lock(&pAC->SlowPathLock);
+- SkEventDispatcher(pAC, pAC->IoBase);
+- spin_unlock(&pAC->SlowPathLock);
+- }
+-
+- /* IRQ is processed - Enable IRQs again*/
+- SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
+-
+- return SkIsrRetHandled;
+-} /* SkGeIsr */
+-
+-
+-/****************************************************************************
+- *
+- * SkGeIsrOnePort - handle adapter interrupts for single port adapter
+- *
+- * Description:
+- * The interrupt routine is called when the network adapter
+- * generates an interrupt. It may also be called if another device
+- * shares this interrupt vector with the driver.
+- * This is the same as above, but handles only one port.
+- *
+- * Returns: N/A
+- *
+- */
+-static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id)
+-{
+-struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
+-DEV_NET *pNet;
+-SK_AC *pAC;
+-SK_U32 IntSrc; /* interrupts source register contents */
+-
+- pNet = netdev_priv(dev);
+- pAC = pNet->pAC;
+-
+- /*
+- * Check and process if its our interrupt
+- */
+- SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc);
+- if (IntSrc == 0) {
+- return SkIsrRetNone;
+- }
+-
+- while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {
+-#if 0 /* software irq currently not used */
+- if (IntSrc & IS_IRQ_SW) {
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+- SK_DBGCAT_DRV_INT_SRC,
+- ("Software IRQ\n"));
+- }
+-#endif
+- if (IntSrc & IS_R1_F) {
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+- SK_DBGCAT_DRV_INT_SRC,
+- ("EOF RX1 IRQ\n"));
+- ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
+- SK_PNMI_CNT_RX_INTR(pAC, 0);
+- }
+-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
+- if (IntSrc & IS_XA1_F) {
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+- SK_DBGCAT_DRV_INT_SRC,
+- ("EOF AS TX1 IRQ\n"));
+- SK_PNMI_CNT_TX_INTR(pAC, 0);
+- spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
+- FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
+- spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
+- }
+-#if 0 /* only if sync. queues used */
+- if (IntSrc & IS_XS1_F) {
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+- SK_DBGCAT_DRV_INT_SRC,
+- ("EOF SY TX1 IRQ\n"));
+- SK_PNMI_CNT_TX_INTR(pAC, 0);
+- spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
+- FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
+- spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
+- ClearTxIrq(pAC, 0, TX_PRIO_HIGH);
+- }
+-#endif
+-#endif
+-
+- /* do all IO at once */
+- if (IntSrc & IS_R1_F)
+- ClearAndStartRx(pAC, 0);
+-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
+- if (IntSrc & IS_XA1_F)
+- ClearTxIrq(pAC, 0, TX_PRIO_LOW);
+-#endif
+- SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc);
+- } /* while (IntSrc & IRQ_MASK != 0) */
+-
+- IntSrc &= pAC->GIni.GIValIrqMask;
+- if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) {
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
+- ("SPECIAL IRQ SP-Cards => %x\n", IntSrc));
+- pAC->CheckQueue = SK_FALSE;
+- spin_lock(&pAC->SlowPathLock);
+- if (IntSrc & SPECIAL_IRQS)
+- SkGeSirqIsr(pAC, pAC->IoBase, IntSrc);
+-
+- SkEventDispatcher(pAC, pAC->IoBase);
+- spin_unlock(&pAC->SlowPathLock);
+- }
+- /*
+- * do it all again is case we cleared an interrupt that
+- * came in after handling the ring (OUTs may be delayed
+- * in hardware buffers, but are through after IN)
+- *
+- * rroesler: has been commented out and shifted to
+- * SkGeDrvEvent(), because it is timer
+- * guarded now
+- *
+- ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
+- */
+-
+- /* IRQ is processed - Enable IRQs again*/
+- SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
+-
+- return SkIsrRetHandled;
+-} /* SkGeIsrOnePort */
+-
+-#ifdef CONFIG_NET_POLL_CONTROLLER
+-/****************************************************************************
+- *
+- * SkGePollController - polling receive, for netconsole
+- *
+- * Description:
+- * Polling receive - used by netconsole and other diagnostic tools
+- * to allow network i/o with interrupts disabled.
+- *
+- * Returns: N/A
+- */
+-static void SkGePollController(struct net_device *dev)
+-{
+- disable_irq(dev->irq);
+- SkGeIsr(dev->irq, dev);
+- enable_irq(dev->irq);
+-}
+-#endif
+-
+-/****************************************************************************
+- *
+- * SkGeOpen - handle start of initialized adapter
+- *
+- * Description:
+- * This function starts the initialized adapter.
+- * The board level variable is set and the adapter is
+- * brought to full functionality.
+- * The device flags are set for operation.
+- * Do all necessary level 2 initialization, enable interrupts and
+- * give start command to RLMT.
+- *
+- * Returns:
+- * 0 on success
+- * != 0 on error
+- */
+-static int SkGeOpen(
+-struct SK_NET_DEVICE *dev)
+-{
+- DEV_NET *pNet;
+- SK_AC *pAC;
+- unsigned long Flags; /* for spin lock */
+- int i;
+- SK_EVPARA EvPara; /* an event parameter union */
+-
+- pNet = netdev_priv(dev);
+- pAC = pNet->pAC;
+-
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+- ("SkGeOpen: pAC=0x%lX:\n", (unsigned long)pAC));
+-
+-#ifdef SK_DIAG_SUPPORT
+- if (pAC->DiagModeActive == DIAG_ACTIVE) {
+- if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
+- return (-1); /* still in use by diag; deny actions */
+- }
+- }
+-#endif
+-
+- /* Set blink mode */
+- if ((pAC->PciDev->vendor == 0x1186) || (pAC->PciDev->vendor == 0x11ab ))
+- pAC->GIni.GILedBlinkCtrl = OEM_CONFIG_VALUE;
+-
+- if (pAC->BoardLevel == SK_INIT_DATA) {
+- /* level 1 init common modules here */
+- if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) {
+- printk("%s: HWInit (1) failed.\n", pAC->dev[pNet->PortNr]->name);
+- return (-1);
+- }
+- SkI2cInit (pAC, pAC->IoBase, SK_INIT_IO);
+- SkEventInit (pAC, pAC->IoBase, SK_INIT_IO);
+- SkPnmiInit (pAC, pAC->IoBase, SK_INIT_IO);
+- SkAddrInit (pAC, pAC->IoBase, SK_INIT_IO);
+- SkRlmtInit (pAC, pAC->IoBase, SK_INIT_IO);
+- SkTimerInit (pAC, pAC->IoBase, SK_INIT_IO);
+- pAC->BoardLevel = SK_INIT_IO;
+- }
+-
+- if (pAC->BoardLevel != SK_INIT_RUN) {
+- /* tschilling: Level 2 init modules here, check return value. */
+- if (SkGeInit(pAC, pAC->IoBase, SK_INIT_RUN) != 0) {
+- printk("%s: HWInit (2) failed.\n", pAC->dev[pNet->PortNr]->name);
+- return (-1);
+- }
+- SkI2cInit (pAC, pAC->IoBase, SK_INIT_RUN);
+- SkEventInit (pAC, pAC->IoBase, SK_INIT_RUN);
+- SkPnmiInit (pAC, pAC->IoBase, SK_INIT_RUN);
+- SkAddrInit (pAC, pAC->IoBase, SK_INIT_RUN);
+- SkRlmtInit (pAC, pAC->IoBase, SK_INIT_RUN);
+- SkTimerInit (pAC, pAC->IoBase, SK_INIT_RUN);
+- pAC->BoardLevel = SK_INIT_RUN;
+- }
+-
+- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+- /* Enable transmit descriptor polling. */
+- SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE);
+- FillRxRing(pAC, &pAC->RxPort[i]);
+- }
+- SkGeYellowLED(pAC, pAC->IoBase, 1);
+-
+- StartDrvCleanupTimer(pAC);
+- SkDimEnableModerationIfNeeded(pAC);
+- SkDimDisplayModerationSettings(pAC);
+-
+- pAC->GIni.GIValIrqMask &= IRQ_MASK;
+-
+- /* enable Interrupts */
+- SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
+- SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);
+-
+- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+-
+- if ((pAC->RlmtMode != 0) && (pAC->MaxPorts == 0)) {
+- EvPara.Para32[0] = pAC->RlmtNets;
+- EvPara.Para32[1] = -1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS,
+- EvPara);
+- EvPara.Para32[0] = pAC->RlmtMode;
+- EvPara.Para32[1] = 0;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_MODE_CHANGE,
+- EvPara);
+- }
+-
+- EvPara.Para32[0] = pNet->NetNr;
+- EvPara.Para32[1] = -1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
+- SkEventDispatcher(pAC, pAC->IoBase);
+- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-
+- pAC->MaxPorts++;
+-
+-
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+- ("SkGeOpen suceeded\n"));
+-
+- return (0);
+-} /* SkGeOpen */
+-
+-
+-/****************************************************************************
+- *
+- * SkGeClose - Stop initialized adapter
+- *
+- * Description:
+- * Close initialized adapter.
+- *
+- * Returns:
+- * 0 - on success
+- * error code - on error
+- */
+-static int SkGeClose(
+-struct SK_NET_DEVICE *dev)
+-{
+- DEV_NET *pNet;
+- DEV_NET *newPtrNet;
+- SK_AC *pAC;
+-
+- unsigned long Flags; /* for spin lock */
+- int i;
+- int PortIdx;
+- SK_EVPARA EvPara;
+-
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+- ("SkGeClose: pAC=0x%lX ", (unsigned long)pAC));
+-
+- pNet = netdev_priv(dev);
+- pAC = pNet->pAC;
+-
+-#ifdef SK_DIAG_SUPPORT
+- if (pAC->DiagModeActive == DIAG_ACTIVE) {
+- if (pAC->DiagFlowCtrl == SK_FALSE) {
+- /*
+- ** notify that the interface which has been closed
+- ** by operator interaction must not be started up
+- ** again when the DIAG has finished.
+- */
+- newPtrNet = netdev_priv(pAC->dev[0]);
+- if (newPtrNet == pNet) {
+- pAC->WasIfUp[0] = SK_FALSE;
+- } else {
+- pAC->WasIfUp[1] = SK_FALSE;
+- }
+- return 0; /* return to system everything is fine... */
+- } else {
+- pAC->DiagFlowCtrl = SK_FALSE;
+- }
+- }
+-#endif
+-
+- netif_stop_queue(dev);
+-
+- if (pAC->RlmtNets == 1)
+- PortIdx = pAC->ActivePort;
+- else
+- PortIdx = pNet->NetNr;
+-
+- StopDrvCleanupTimer(pAC);
+-
+- /*
+- * Clear multicast table, promiscuous mode ....
+- */
+- SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0);
+- SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
+- SK_PROM_MODE_NONE);
+-
+- if (pAC->MaxPorts == 1) {
+- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+- /* disable interrupts */
+- SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+- EvPara.Para32[0] = pNet->NetNr;
+- EvPara.Para32[1] = -1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+- SkEventDispatcher(pAC, pAC->IoBase);
+- SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+- /* stop the hardware */
+- SkGeDeInit(pAC, pAC->IoBase);
+- pAC->BoardLevel = SK_INIT_DATA;
+- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+- } else {
+-
+- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+- EvPara.Para32[0] = pNet->NetNr;
+- EvPara.Para32[1] = -1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+- SkPnmiEvent(pAC, pAC->IoBase, SK_PNMI_EVT_XMAC_RESET, EvPara);
+- SkEventDispatcher(pAC, pAC->IoBase);
+- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-
+- /* Stop port */
+- spin_lock_irqsave(&pAC->TxPort[pNet->PortNr]
+- [TX_PRIO_LOW].TxDesRingLock, Flags);
+- SkGeStopPort(pAC, pAC->IoBase, pNet->PortNr,
+- SK_STOP_ALL, SK_HARD_RST);
+- spin_unlock_irqrestore(&pAC->TxPort[pNet->PortNr]
+- [TX_PRIO_LOW].TxDesRingLock, Flags);
+- }
+-
+- if (pAC->RlmtNets == 1) {
+- /* clear all descriptor rings */
+- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+- ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE);
+- ClearRxRing(pAC, &pAC->RxPort[i]);
+- ClearTxRing(pAC, &pAC->TxPort[i][TX_PRIO_LOW]);
+- }
+- } else {
+- /* clear port descriptor rings */
+- ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE);
+- ClearRxRing(pAC, &pAC->RxPort[pNet->PortNr]);
+- ClearTxRing(pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW]);
+- }
+-
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+- ("SkGeClose: done "));
+-
+- SK_MEMSET(&(pAC->PnmiBackup), 0, sizeof(SK_PNMI_STRUCT_DATA));
+- SK_MEMCPY(&(pAC->PnmiBackup), &(pAC->PnmiStruct),
+- sizeof(SK_PNMI_STRUCT_DATA));
+-
+- pAC->MaxPorts--;
+-
+- return (0);
+-} /* SkGeClose */
+-
+-
+-/*****************************************************************************
+- *
+- * SkGeXmit - Linux frame transmit function
+- *
+- * Description:
+- * The system calls this function to send frames onto the wire.
+- * It puts the frame in the tx descriptor ring. If the ring is
+- * full then, the 'tbusy' flag is set.
+- *
+- * Returns:
+- * 0, if everything is ok
+- * !=0, on error
+- * WARNING: returning 1 in 'tbusy' case caused system crashes (double
+- * allocated skb's) !!!
+- */
+-static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev)
+-{
+-DEV_NET *pNet;
+-SK_AC *pAC;
+-int Rc; /* return code of XmitFrame */
+-
+- pNet = netdev_priv(dev);
+- pAC = pNet->pAC;
+-
+- if ((!skb_shinfo(skb)->nr_frags) ||
+- (pAC->GIni.GIChipId == CHIP_ID_GENESIS)) {
+- /* Don't activate scatter-gather and hardware checksum */
+-
+- if (pAC->RlmtNets == 2)
+- Rc = XmitFrame(
+- pAC,
+- &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW],
+- skb);
+- else
+- Rc = XmitFrame(
+- pAC,
+- &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW],
+- skb);
+- } else {
+- /* scatter-gather and hardware TCP checksumming anabled*/
+- if (pAC->RlmtNets == 2)
+- Rc = XmitFrameSG(
+- pAC,
+- &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW],
+- skb);
+- else
+- Rc = XmitFrameSG(
+- pAC,
+- &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW],
+- skb);
+- }
+-
+- /* Transmitter out of resources? */
+- if (Rc <= 0) {
+- netif_stop_queue(dev);
+- }
+-
+- /* If not taken, give buffer ownership back to the
+- * queueing layer.
+- */
+- if (Rc < 0)
+- return (1);
+-
+- dev->trans_start = jiffies;
+- return (0);
+-} /* SkGeXmit */
+-
+-
+-/*****************************************************************************
+- *
+- * XmitFrame - fill one socket buffer into the transmit ring
+- *
+- * Description:
+- * This function puts a message into the transmit descriptor ring
+- * if there is a descriptors left.
+- * Linux skb's consist of only one continuous buffer.
+- * The first step locks the ring. It is held locked
+- * all time to avoid problems with SWITCH_../PORT_RESET.
+- * Then the descriptoris allocated.
+- * The second part is linking the buffer to the descriptor.
+- * At the very last, the Control field of the descriptor
+- * is made valid for the BMU and a start TX command is given
+- * if necessary.
+- *
+- * Returns:
+- * > 0 - on succes: the number of bytes in the message
+- * = 0 - on resource shortage: this frame sent or dropped, now
+- * the ring is full ( -> set tbusy)
+- * < 0 - on failure: other problems ( -> return failure to upper layers)
+- */
+-static int XmitFrame(
+-SK_AC *pAC, /* pointer to adapter context */
+-TX_PORT *pTxPort, /* pointer to struct of port to send to */
+-struct sk_buff *pMessage) /* pointer to send-message */
+-{
+- TXD *pTxd; /* the rxd to fill */
+- TXD *pOldTxd;
+- unsigned long Flags;
+- SK_U64 PhysAddr;
+- int BytesSend = pMessage->len;
+-
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("X"));
+-
+- spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
+-#ifndef USE_TX_COMPLETE
+- FreeTxDescriptors(pAC, pTxPort);
+-#endif
+- if (pTxPort->TxdRingFree == 0) {
+- /*
+- ** no enough free descriptors in ring at the moment.
+- ** Maybe free'ing some old one help?
+- */
+- FreeTxDescriptors(pAC, pTxPort);
+- if (pTxPort->TxdRingFree == 0) {
+- spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+- SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex);
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+- SK_DBGCAT_DRV_TX_PROGRESS,
+- ("XmitFrame failed\n"));
+- /*
+- ** the desired message can not be sent
+- ** Because tbusy seems to be set, the message
+- ** should not be freed here. It will be used
+- ** by the scheduler of the ethernet handler
+- */
+- return (-1);
+- }
+- }
+-
+- /*
+- ** If the passed socket buffer is of smaller MTU-size than 60,
+- ** copy everything into new buffer and fill all bytes between
+- ** the original packet end and the new packet end of 60 with 0x00.
+- ** This is to resolve faulty padding by the HW with 0xaa bytes.
+- */
+- if (BytesSend < C_LEN_ETHERNET_MINSIZE) {
+- if (skb_padto(pMessage, C_LEN_ETHERNET_MINSIZE)) {
+- spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+- return 0;
+- }
+- pMessage->len = C_LEN_ETHERNET_MINSIZE;
+- }
+-
+- /*
+- ** advance head counter behind descriptor needed for this frame,
+- ** so that needed descriptor is reserved from that on. The next
+- ** action will be to add the passed buffer to the TX-descriptor
+- */
+- pTxd = pTxPort->pTxdRingHead;
+- pTxPort->pTxdRingHead = pTxd->pNextTxd;
+- pTxPort->TxdRingFree--;
+-
+-#ifdef SK_DUMP_TX
+- DumpMsg(pMessage, "XmitFrame");
+-#endif
+-
+- /*
+- ** First step is to map the data to be sent via the adapter onto
+- ** the DMA memory. Kernel 2.2 uses virt_to_bus(), but kernels 2.4
+- ** and 2.6 need to use pci_map_page() for that mapping.
+- */
+- PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+- virt_to_page(pMessage->data),
+- ((unsigned long) pMessage->data & ~PAGE_MASK),
+- pMessage->len,
+- PCI_DMA_TODEVICE);
+- pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
+- pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
+- pTxd->pMBuf = pMessage;
+-
+- if (pMessage->ip_summed == CHECKSUM_PARTIAL) {
+- u16 hdrlen = skb_transport_offset(pMessage);
+- u16 offset = hdrlen + pMessage->csum_offset;
+-
+- if ((ipip_hdr(pMessage)->protocol == IPPROTO_UDP) &&
+- (pAC->GIni.GIChipRev == 0) &&
+- (pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
+- pTxd->TBControl = BMU_TCP_CHECK;
+- } else {
+- pTxd->TBControl = BMU_UDP_CHECK;
+- }
+-
+- pTxd->TcpSumOfs = 0;
+- pTxd->TcpSumSt = hdrlen;
+- pTxd->TcpSumWr = offset;
+-
+- pTxd->TBControl |= BMU_OWN | BMU_STF |
+- BMU_SW | BMU_EOF |
+-#ifdef USE_TX_COMPLETE
+- BMU_IRQ_EOF |
+-#endif
+- pMessage->len;
+- } else {
+- pTxd->TBControl = BMU_OWN | BMU_STF | BMU_CHECK |
+- BMU_SW | BMU_EOF |
+-#ifdef USE_TX_COMPLETE
+- BMU_IRQ_EOF |
+-#endif
+- pMessage->len;
+- }
+-
+- /*
+- ** If previous descriptor already done, give TX start cmd
+- */
+- pOldTxd = xchg(&pTxPort->pTxdRingPrev, pTxd);
+- if ((pOldTxd->TBControl & BMU_OWN) == 0) {
+- SK_OUT8(pTxPort->HwAddr, Q_CSR, CSR_START);
+- }
+-
+- /*
+- ** after releasing the lock, the skb may immediately be free'd
+- */
+- spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+- if (pTxPort->TxdRingFree != 0) {
+- return (BytesSend);
+- } else {
+- return (0);
+- }
+-
+-} /* XmitFrame */
+-
+-/*****************************************************************************
+- *
+- * XmitFrameSG - fill one socket buffer into the transmit ring
+- * (use SG and TCP/UDP hardware checksumming)
+- *
+- * Description:
+- * This function puts a message into the transmit descriptor ring
+- * if there is a descriptors left.
+- *
+- * Returns:
+- * > 0 - on succes: the number of bytes in the message
+- * = 0 - on resource shortage: this frame sent or dropped, now
+- * the ring is full ( -> set tbusy)
+- * < 0 - on failure: other problems ( -> return failure to upper layers)
+- */
+-static int XmitFrameSG(
+-SK_AC *pAC, /* pointer to adapter context */
+-TX_PORT *pTxPort, /* pointer to struct of port to send to */
+-struct sk_buff *pMessage) /* pointer to send-message */
+-{
+-
+- TXD *pTxd;
+- TXD *pTxdFst;
+- TXD *pTxdLst;
+- int CurrFrag;
+- int BytesSend;
+- skb_frag_t *sk_frag;
+- SK_U64 PhysAddr;
+- unsigned long Flags;
+- SK_U32 Control;
+-
+- spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
+-#ifndef USE_TX_COMPLETE
+- FreeTxDescriptors(pAC, pTxPort);
+-#endif
+- if ((skb_shinfo(pMessage)->nr_frags +1) > pTxPort->TxdRingFree) {
+- FreeTxDescriptors(pAC, pTxPort);
+- if ((skb_shinfo(pMessage)->nr_frags + 1) > pTxPort->TxdRingFree) {
+- spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+- SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex);
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+- SK_DBGCAT_DRV_TX_PROGRESS,
+- ("XmitFrameSG failed - Ring full\n"));
+- /* this message can not be sent now */
+- return(-1);
+- }
+- }
+-
+- pTxd = pTxPort->pTxdRingHead;
+- pTxdFst = pTxd;
+- pTxdLst = pTxd;
+- BytesSend = 0;
+-
+- /*
+- ** Map the first fragment (header) into the DMA-space
+- */
+- PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+- virt_to_page(pMessage->data),
+- ((unsigned long) pMessage->data & ~PAGE_MASK),
+- skb_headlen(pMessage),
+- PCI_DMA_TODEVICE);
+-
+- pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
+- pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
+-
+- /*
+- ** Does the HW need to evaluate checksum for TCP or UDP packets?
+- */
+- if (pMessage->ip_summed == CHECKSUM_PARTIAL) {
+- u16 hdrlen = skb_transport_offset(pMessage);
+- u16 offset = hdrlen + pMessage->csum_offset;
+-
+- Control = BMU_STFWD;
+-
+- /*
+- ** We have to use the opcode for tcp here, because the
+- ** opcode for udp is not working in the hardware yet
+- ** (Revision 2.0)
+- */
+- if ((ipip_hdr(pMessage)->protocol == IPPROTO_UDP) &&
+- (pAC->GIni.GIChipRev == 0) &&
+- (pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
+- Control |= BMU_TCP_CHECK;
+- } else {
+- Control |= BMU_UDP_CHECK;
+- }
+-
+- pTxd->TcpSumOfs = 0;
+- pTxd->TcpSumSt = hdrlen;
+- pTxd->TcpSumWr = offset;
+- } else
+- Control = BMU_CHECK | BMU_SW;
+-
+- pTxd->TBControl = BMU_STF | Control | skb_headlen(pMessage);
+-
+- pTxd = pTxd->pNextTxd;
+- pTxPort->TxdRingFree--;
+- BytesSend += skb_headlen(pMessage);
+-
+- /*
+- ** Browse over all SG fragments and map each of them into the DMA space
+- */
+- for (CurrFrag = 0; CurrFrag < skb_shinfo(pMessage)->nr_frags; CurrFrag++) {
+- sk_frag = &skb_shinfo(pMessage)->frags[CurrFrag];
+- /*
+- ** we already have the proper value in entry
+- */
+- PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+- sk_frag->page,
+- sk_frag->page_offset,
+- sk_frag->size,
+- PCI_DMA_TODEVICE);
+-
+- pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
+- pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
+- pTxd->pMBuf = pMessage;
+-
+- pTxd->TBControl = Control | BMU_OWN | sk_frag->size;
+-
+- /*
+- ** Do we have the last fragment?
+- */
+- if( (CurrFrag+1) == skb_shinfo(pMessage)->nr_frags ) {
+-#ifdef USE_TX_COMPLETE
+- pTxd->TBControl |= BMU_EOF | BMU_IRQ_EOF;
+-#else
+- pTxd->TBControl |= BMU_EOF;
+-#endif
+- pTxdFst->TBControl |= BMU_OWN | BMU_SW;
+- }
+- pTxdLst = pTxd;
+- pTxd = pTxd->pNextTxd;
+- pTxPort->TxdRingFree--;
+- BytesSend += sk_frag->size;
+- }
+-
+- /*
+- ** If previous descriptor already done, give TX start cmd
+- */
+- if ((pTxPort->pTxdRingPrev->TBControl & BMU_OWN) == 0) {
+- SK_OUT8(pTxPort->HwAddr, Q_CSR, CSR_START);
+- }
+-
+- pTxPort->pTxdRingPrev = pTxdLst;
+- pTxPort->pTxdRingHead = pTxd;
+-
+- spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+-
+- if (pTxPort->TxdRingFree > 0) {
+- return (BytesSend);
+- } else {
+- return (0);
+- }
+-}
+-
+-/*****************************************************************************
+- *
+- * FreeTxDescriptors - release descriptors from the descriptor ring
+- *
+- * Description:
+- * This function releases descriptors from a transmit ring if they
+- * have been sent by the BMU.
+- * If a descriptors is sent, it can be freed and the message can
+- * be freed, too.
+- * The SOFTWARE controllable bit is used to prevent running around a
+- * completely free ring for ever. If this bit is no set in the
+- * frame (by XmitFrame), this frame has never been sent or is
+- * already freed.
+- * The Tx descriptor ring lock must be held while calling this function !!!
+- *
+- * Returns:
+- * none
+- */
+-static void FreeTxDescriptors(
+-SK_AC *pAC, /* pointer to the adapter context */
+-TX_PORT *pTxPort) /* pointer to destination port structure */
+-{
+-TXD *pTxd; /* pointer to the checked descriptor */
+-TXD *pNewTail; /* pointer to 'end' of the ring */
+-SK_U32 Control; /* TBControl field of descriptor */
+-SK_U64 PhysAddr; /* address of DMA mapping */
+-
+- pNewTail = pTxPort->pTxdRingTail;
+- pTxd = pNewTail;
+- /*
+- ** loop forever; exits if BMU_SW bit not set in start frame
+- ** or BMU_OWN bit set in any frame
+- */
+- while (1) {
+- Control = pTxd->TBControl;
+- if ((Control & BMU_SW) == 0) {
+- /*
+- ** software controllable bit is set in first
+- ** fragment when given to BMU. Not set means that
+- ** this fragment was never sent or is already
+- ** freed ( -> ring completely free now).
+- */
+- pTxPort->pTxdRingTail = pTxd;
+- netif_wake_queue(pAC->dev[pTxPort->PortIndex]);
+- return;
+- }
+- if (Control & BMU_OWN) {
+- pTxPort->pTxdRingTail = pTxd;
+- if (pTxPort->TxdRingFree > 0) {
+- netif_wake_queue(pAC->dev[pTxPort->PortIndex]);
+- }
+- return;
+- }
+-
+- /*
+- ** release the DMA mapping, because until not unmapped
+- ** this buffer is considered being under control of the
+- ** adapter card!
+- */
+- PhysAddr = ((SK_U64) pTxd->VDataHigh) << (SK_U64) 32;
+- PhysAddr |= (SK_U64) pTxd->VDataLow;
+- pci_unmap_page(pAC->PciDev, PhysAddr,
+- pTxd->pMBuf->len,
+- PCI_DMA_TODEVICE);
+-
+- if (Control & BMU_EOF)
+- DEV_KFREE_SKB_ANY(pTxd->pMBuf); /* free message */
+-
+- pTxPort->TxdRingFree++;
+- pTxd->TBControl &= ~BMU_SW;
+- pTxd = pTxd->pNextTxd; /* point behind fragment with EOF */
+- } /* while(forever) */
+-} /* FreeTxDescriptors */
+-
+-/*****************************************************************************
+- *
+- * FillRxRing - fill the receive ring with valid descriptors
+- *
+- * Description:
+- * This function fills the receive ring descriptors with data
+- * segments and makes them valid for the BMU.
+- * The active ring is filled completely, if possible.
+- * The non-active ring is filled only partial to save memory.
+- *
+- * Description of rx ring structure:
+- * head - points to the descriptor which will be used next by the BMU
+- * tail - points to the next descriptor to give to the BMU
+- *
+- * Returns: N/A
+- */
+-static void FillRxRing(
+-SK_AC *pAC, /* pointer to the adapter context */
+-RX_PORT *pRxPort) /* ptr to port struct for which the ring
+- should be filled */
+-{
+-unsigned long Flags;
+-
+- spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags);
+- while (pRxPort->RxdRingFree > pRxPort->RxFillLimit) {
+- if(!FillRxDescriptor(pAC, pRxPort))
+- break;
+- }
+- spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags);
+-} /* FillRxRing */
+-
+-
+-/*****************************************************************************
+- *
+- * FillRxDescriptor - fill one buffer into the receive ring
+- *
+- * Description:
+- * The function allocates a new receive buffer and
+- * puts it into the next descriptor.
+- *
+- * Returns:
+- * SK_TRUE - a buffer was added to the ring
+- * SK_FALSE - a buffer could not be added
+- */
+-static SK_BOOL FillRxDescriptor(
+-SK_AC *pAC, /* pointer to the adapter context struct */
+-RX_PORT *pRxPort) /* ptr to port struct of ring to fill */
+-{
+-struct sk_buff *pMsgBlock; /* pointer to a new message block */
+-RXD *pRxd; /* the rxd to fill */
+-SK_U16 Length; /* data fragment length */
+-SK_U64 PhysAddr; /* physical address of a rx buffer */
+-
+- pMsgBlock = alloc_skb(pAC->RxBufSize, GFP_ATOMIC);
+- if (pMsgBlock == NULL) {
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+- SK_DBGCAT_DRV_ENTRY,
+- ("%s: Allocation of rx buffer failed !\n",
+- pAC->dev[pRxPort->PortIndex]->name));
+- SK_PNMI_CNT_NO_RX_BUF(pAC, pRxPort->PortIndex);
+- return(SK_FALSE);
+- }
+- skb_reserve(pMsgBlock, 2); /* to align IP frames */
+- /* skb allocated ok, so add buffer */
+- pRxd = pRxPort->pRxdRingTail;
+- pRxPort->pRxdRingTail = pRxd->pNextRxd;
+- pRxPort->RxdRingFree--;
+- Length = pAC->RxBufSize;
+- PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+- virt_to_page(pMsgBlock->data),
+- ((unsigned long) pMsgBlock->data &
+- ~PAGE_MASK),
+- pAC->RxBufSize - 2,
+- PCI_DMA_FROMDEVICE);
+-
+- pRxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
+- pRxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
+- pRxd->pMBuf = pMsgBlock;
+- pRxd->RBControl = BMU_OWN |
+- BMU_STF |
+- BMU_IRQ_EOF |
+- BMU_TCP_CHECK |
+- Length;
+- return (SK_TRUE);
+-
+-} /* FillRxDescriptor */
+-
+-
+-/*****************************************************************************
+- *
+- * ReQueueRxBuffer - fill one buffer back into the receive ring
+- *
+- * Description:
+- * Fill a given buffer back into the rx ring. The buffer
+- * has been previously allocated and aligned, and its phys.
+- * address calculated, so this is no more necessary.
+- *
+- * Returns: N/A
+- */
+-static void ReQueueRxBuffer(
+-SK_AC *pAC, /* pointer to the adapter context struct */
+-RX_PORT *pRxPort, /* ptr to port struct of ring to fill */
+-struct sk_buff *pMsg, /* pointer to the buffer */
+-SK_U32 PhysHigh, /* phys address high dword */
+-SK_U32 PhysLow) /* phys address low dword */
+-{
+-RXD *pRxd; /* the rxd to fill */
+-SK_U16 Length; /* data fragment length */
+-
+- pRxd = pRxPort->pRxdRingTail;
+- pRxPort->pRxdRingTail = pRxd->pNextRxd;
+- pRxPort->RxdRingFree--;
+- Length = pAC->RxBufSize;
+-
+- pRxd->VDataLow = PhysLow;
+- pRxd->VDataHigh = PhysHigh;
+- pRxd->pMBuf = pMsg;
+- pRxd->RBControl = BMU_OWN |
+- BMU_STF |
+- BMU_IRQ_EOF |
+- BMU_TCP_CHECK |
+- Length;
+- return;
+-} /* ReQueueRxBuffer */
+-
+-/*****************************************************************************
+- *
+- * ReceiveIrq - handle a receive IRQ
+- *
+- * Description:
+- * This function is called when a receive IRQ is set.
+- * It walks the receive descriptor ring and sends up all
+- * frames that are complete.
+- *
+- * Returns: N/A
+- */
+-static void ReceiveIrq(
+- SK_AC *pAC, /* pointer to adapter context */
+- RX_PORT *pRxPort, /* pointer to receive port struct */
+- SK_BOOL SlowPathLock) /* indicates if SlowPathLock is needed */
+-{
+-RXD *pRxd; /* pointer to receive descriptors */
+-SK_U32 Control; /* control field of descriptor */
+-struct sk_buff *pMsg; /* pointer to message holding frame */
+-struct sk_buff *pNewMsg; /* pointer to a new message for copying frame */
+-int FrameLength; /* total length of received frame */
+-SK_MBUF *pRlmtMbuf; /* ptr to a buffer for giving a frame to rlmt */
+-SK_EVPARA EvPara; /* an event parameter union */
+-unsigned long Flags; /* for spin lock */
+-int PortIndex = pRxPort->PortIndex;
+-unsigned int Offset;
+-unsigned int NumBytes;
+-unsigned int ForRlmt;
+-SK_BOOL IsBc;
+-SK_BOOL IsMc;
+-SK_BOOL IsBadFrame; /* Bad frame */
+-
+-SK_U32 FrameStat;
+-SK_U64 PhysAddr;
+-
+-rx_start:
+- /* do forever; exit if BMU_OWN found */
+- for ( pRxd = pRxPort->pRxdRingHead ;
+- pRxPort->RxdRingFree < pAC->RxDescrPerRing ;
+- pRxd = pRxd->pNextRxd,
+- pRxPort->pRxdRingHead = pRxd,
+- pRxPort->RxdRingFree ++) {
+-
+- /*
+- * For a better understanding of this loop
+- * Go through every descriptor beginning at the head
+- * Please note: the ring might be completely received so the OWN bit
+- * set is not a good crirteria to leave that loop.
+- * Therefore the RingFree counter is used.
+- * On entry of this loop pRxd is a pointer to the Rxd that needs
+- * to be checked next.
+- */
+-
+- Control = pRxd->RBControl;
+-
+- /* check if this descriptor is ready */
+- if ((Control & BMU_OWN) != 0) {
+- /* this descriptor is not yet ready */
+- /* This is the usual end of the loop */
+- /* We don't need to start the ring again */
+- FillRxRing(pAC, pRxPort);
+- return;
+- }
+- pAC->DynIrqModInfo.NbrProcessedDescr++;
+-
+- /* get length of frame and check it */
+- FrameLength = Control & BMU_BBC;
+- if (FrameLength > pAC->RxBufSize) {
+- goto rx_failed;
+- }
+-
+- /* check for STF and EOF */
+- if ((Control & (BMU_STF | BMU_EOF)) != (BMU_STF | BMU_EOF)) {
+- goto rx_failed;
+- }
+-
+- /* here we have a complete frame in the ring */
+- pMsg = pRxd->pMBuf;
+-
+- FrameStat = pRxd->FrameStat;
+-
+- /* check for frame length mismatch */
+-#define XMR_FS_LEN_SHIFT 18
+-#define GMR_FS_LEN_SHIFT 16
+- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+- if (FrameLength != (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)) {
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+- SK_DBGCAT_DRV_RX_PROGRESS,
+- ("skge: Frame length mismatch (%u/%u).\n",
+- FrameLength,
+- (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)));
+- goto rx_failed;
+- }
+- }
+- else {
+- if (FrameLength != (SK_U32) (FrameStat >> GMR_FS_LEN_SHIFT)) {
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+- SK_DBGCAT_DRV_RX_PROGRESS,
+- ("skge: Frame length mismatch (%u/%u).\n",
+- FrameLength,
+- (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)));
+- goto rx_failed;
+- }
+- }
+-
+- /* Set Rx Status */
+- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+- IsBc = (FrameStat & XMR_FS_BC) != 0;
+- IsMc = (FrameStat & XMR_FS_MC) != 0;
+- IsBadFrame = (FrameStat &
+- (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0;
+- } else {
+- IsBc = (FrameStat & GMR_FS_BC) != 0;
+- IsMc = (FrameStat & GMR_FS_MC) != 0;
+- IsBadFrame = (((FrameStat & GMR_FS_ANY_ERR) != 0) ||
+- ((FrameStat & GMR_FS_RX_OK) == 0));
+- }
+-
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0,
+- ("Received frame of length %d on port %d\n",
+- FrameLength, PortIndex));
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0,
+- ("Number of free rx descriptors: %d\n",
+- pRxPort->RxdRingFree));
+-/* DumpMsg(pMsg, "Rx"); */
+-
+- if ((Control & BMU_STAT_VAL) != BMU_STAT_VAL || (IsBadFrame)) {
+-#if 0
+- (FrameStat & (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0) {
+-#endif
+- /* there is a receive error in this frame */
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+- SK_DBGCAT_DRV_RX_PROGRESS,
+- ("skge: Error in received frame, dropped!\n"
+- "Control: %x\nRxStat: %x\n",
+- Control, FrameStat));
+-
+- ReQueueRxBuffer(pAC, pRxPort, pMsg,
+- pRxd->VDataHigh, pRxd->VDataLow);
+-
+- continue;
+- }
+-
+- /*
+- * if short frame then copy data to reduce memory waste
+- */
+- if ((FrameLength < SK_COPY_THRESHOLD) &&
+- ((pNewMsg = alloc_skb(FrameLength+2, GFP_ATOMIC)) != NULL)) {
+- /*
+- * Short frame detected and allocation successfull
+- */
+- /* use new skb and copy data */
+- skb_reserve(pNewMsg, 2);
+- skb_put(pNewMsg, FrameLength);
+- PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
+- PhysAddr |= (SK_U64) pRxd->VDataLow;
+-
+- pci_dma_sync_single_for_cpu(pAC->PciDev,
+- (dma_addr_t) PhysAddr,
+- FrameLength,
+- PCI_DMA_FROMDEVICE);
+- skb_copy_to_linear_data(pNewMsg, pMsg, FrameLength);
+-
+- pci_dma_sync_single_for_device(pAC->PciDev,
+- (dma_addr_t) PhysAddr,
+- FrameLength,
+- PCI_DMA_FROMDEVICE);
+- ReQueueRxBuffer(pAC, pRxPort, pMsg,
+- pRxd->VDataHigh, pRxd->VDataLow);
+-
+- pMsg = pNewMsg;
+-
+- }
+- else {
+- /*
+- * if large frame, or SKB allocation failed, pass
+- * the SKB directly to the networking
+- */
+-
+- PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
+- PhysAddr |= (SK_U64) pRxd->VDataLow;
+-
+- /* release the DMA mapping */
+- pci_unmap_single(pAC->PciDev,
+- PhysAddr,
+- pAC->RxBufSize - 2,
+- PCI_DMA_FROMDEVICE);
+-
+- /* set length in message */
+- skb_put(pMsg, FrameLength);
+- } /* frame > SK_COPY_TRESHOLD */
+-
+-#ifdef USE_SK_RX_CHECKSUM
+- pMsg->csum = pRxd->TcpSums & 0xffff;
+- pMsg->ip_summed = CHECKSUM_COMPLETE;
+-#else
+- pMsg->ip_summed = CHECKSUM_NONE;
+-#endif
+-
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("V"));
+- ForRlmt = SK_RLMT_RX_PROTOCOL;
+-#if 0
+- IsBc = (FrameStat & XMR_FS_BC)==XMR_FS_BC;
+-#endif
+- SK_RLMT_PRE_LOOKAHEAD(pAC, PortIndex, FrameLength,
+- IsBc, &Offset, &NumBytes);
+- if (NumBytes != 0) {
+-#if 0
+- IsMc = (FrameStat & XMR_FS_MC)==XMR_FS_MC;
+-#endif
+- SK_RLMT_LOOKAHEAD(pAC, PortIndex,
+- &pMsg->data[Offset],
+- IsBc, IsMc, &ForRlmt);
+- }
+- if (ForRlmt == SK_RLMT_RX_PROTOCOL) {
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("W"));
+- /* send up only frames from active port */
+- if ((PortIndex == pAC->ActivePort) ||
+- (pAC->RlmtNets == 2)) {
+- /* frame for upper layer */
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("U"));
+-#ifdef xDEBUG
+- DumpMsg(pMsg, "Rx");
+-#endif
+- SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,
+- FrameLength, pRxPort->PortIndex);
+-
+- pMsg->protocol = eth_type_trans(pMsg,
+- pAC->dev[pRxPort->PortIndex]);
+- netif_rx(pMsg);
+- pAC->dev[pRxPort->PortIndex]->last_rx = jiffies;
+- }
+- else {
+- /* drop frame */
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+- SK_DBGCAT_DRV_RX_PROGRESS,
+- ("D"));
+- DEV_KFREE_SKB(pMsg);
+- }
+-
+- } /* if not for rlmt */
+- else {
+- /* packet for rlmt */
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+- SK_DBGCAT_DRV_RX_PROGRESS, ("R"));
+- pRlmtMbuf = SkDrvAllocRlmtMbuf(pAC,
+- pAC->IoBase, FrameLength);
+- if (pRlmtMbuf != NULL) {
+- pRlmtMbuf->pNext = NULL;
+- pRlmtMbuf->Length = FrameLength;
+- pRlmtMbuf->PortIdx = PortIndex;
+- EvPara.pParaPtr = pRlmtMbuf;
+- memcpy((char*)(pRlmtMbuf->pData),
+- (char*)(pMsg->data),
+- FrameLength);
+-
+- /* SlowPathLock needed? */
+- if (SlowPathLock == SK_TRUE) {
+- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+- SkEventQueue(pAC, SKGE_RLMT,
+- SK_RLMT_PACKET_RECEIVED,
+- EvPara);
+- pAC->CheckQueue = SK_TRUE;
+- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+- } else {
+- SkEventQueue(pAC, SKGE_RLMT,
+- SK_RLMT_PACKET_RECEIVED,
+- EvPara);
+- pAC->CheckQueue = SK_TRUE;
+- }
+-
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+- SK_DBGCAT_DRV_RX_PROGRESS,
+- ("Q"));
+- }
+- if ((pAC->dev[pRxPort->PortIndex]->flags &
+- (IFF_PROMISC | IFF_ALLMULTI)) != 0 ||
+- (ForRlmt & SK_RLMT_RX_PROTOCOL) ==
+- SK_RLMT_RX_PROTOCOL) {
+- pMsg->protocol = eth_type_trans(pMsg,
+- pAC->dev[pRxPort->PortIndex]);
+- netif_rx(pMsg);
+- pAC->dev[pRxPort->PortIndex]->last_rx = jiffies;
+- }
+- else {
+- DEV_KFREE_SKB(pMsg);
+- }
+-
+- } /* if packet for rlmt */
+- } /* for ... scanning the RXD ring */
+-
+- /* RXD ring is empty -> fill and restart */
+- FillRxRing(pAC, pRxPort);
+- /* do not start if called from Close */
+- if (pAC->BoardLevel > SK_INIT_DATA) {
+- ClearAndStartRx(pAC, PortIndex);
+- }
+- return;
+-
+-rx_failed:
+- /* remove error frame */
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ERROR,
+- ("Schrottdescriptor, length: 0x%x\n", FrameLength));
+-
+- /* release the DMA mapping */
+-
+- PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
+- PhysAddr |= (SK_U64) pRxd->VDataLow;
+- pci_unmap_page(pAC->PciDev,
+- PhysAddr,
+- pAC->RxBufSize - 2,
+- PCI_DMA_FROMDEVICE);
+- DEV_KFREE_SKB_IRQ(pRxd->pMBuf);
+- pRxd->pMBuf = NULL;
+- pRxPort->RxdRingFree++;
+- pRxPort->pRxdRingHead = pRxd->pNextRxd;
+- goto rx_start;
+-
+-} /* ReceiveIrq */
+-
+-
+-/*****************************************************************************
+- *
+- * ClearAndStartRx - give a start receive command to BMU, clear IRQ
+- *
+- * Description:
+- * This function sends a start command and a clear interrupt
+- * command for one receive queue to the BMU.
+- *
+- * Returns: N/A
+- * none
+- */
+-static void ClearAndStartRx(
+-SK_AC *pAC, /* pointer to the adapter context */
+-int PortIndex) /* index of the receive port (XMAC) */
+-{
+- SK_OUT8(pAC->IoBase,
+- RxQueueAddr[PortIndex]+Q_CSR,
+- CSR_START | CSR_IRQ_CL_F);
+-} /* ClearAndStartRx */
+-
+-
+-/*****************************************************************************
+- *
+- * ClearTxIrq - give a clear transmit IRQ command to BMU
+- *
+- * Description:
+- * This function sends a clear tx IRQ command for one
+- * transmit queue to the BMU.
+- *
+- * Returns: N/A
+- */
+-static void ClearTxIrq(
+-SK_AC *pAC, /* pointer to the adapter context */
+-int PortIndex, /* index of the transmit port (XMAC) */
+-int Prio) /* priority or normal queue */
+-{
+- SK_OUT8(pAC->IoBase,
+- TxQueueAddr[PortIndex][Prio]+Q_CSR,
+- CSR_IRQ_CL_F);
+-} /* ClearTxIrq */
+-
+-
+-/*****************************************************************************
+- *
+- * ClearRxRing - remove all buffers from the receive ring
+- *
+- * Description:
+- * This function removes all receive buffers from the ring.
+- * The receive BMU must be stopped before calling this function.
+- *
+- * Returns: N/A
+- */
+-static void ClearRxRing(
+-SK_AC *pAC, /* pointer to adapter context */
+-RX_PORT *pRxPort) /* pointer to rx port struct */
+-{
+-RXD *pRxd; /* pointer to the current descriptor */
+-unsigned long Flags;
+-SK_U64 PhysAddr;
+-
+- if (pRxPort->RxdRingFree == pAC->RxDescrPerRing) {
+- return;
+- }
+- spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags);
+- pRxd = pRxPort->pRxdRingHead;
+- do {
+- if (pRxd->pMBuf != NULL) {
+-
+- PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
+- PhysAddr |= (SK_U64) pRxd->VDataLow;
+- pci_unmap_page(pAC->PciDev,
+- PhysAddr,
+- pAC->RxBufSize - 2,
+- PCI_DMA_FROMDEVICE);
+- DEV_KFREE_SKB(pRxd->pMBuf);
+- pRxd->pMBuf = NULL;
+- }
+- pRxd->RBControl &= BMU_OWN;
+- pRxd = pRxd->pNextRxd;
+- pRxPort->RxdRingFree++;
+- } while (pRxd != pRxPort->pRxdRingTail);
+- pRxPort->pRxdRingTail = pRxPort->pRxdRingHead;
+- spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags);
+-} /* ClearRxRing */
+-
+-/*****************************************************************************
+- *
+- * ClearTxRing - remove all buffers from the transmit ring
+- *
+- * Description:
+- * This function removes all transmit buffers from the ring.
+- * The transmit BMU must be stopped before calling this function
+- * and transmitting at the upper level must be disabled.
+- * The BMU own bit of all descriptors is cleared, the rest is
+- * done by calling FreeTxDescriptors.
+- *
+- * Returns: N/A
+- */
+-static void ClearTxRing(
+-SK_AC *pAC, /* pointer to adapter context */
+-TX_PORT *pTxPort) /* pointer to tx prt struct */
+-{
+-TXD *pTxd; /* pointer to the current descriptor */
+-int i;
+-unsigned long Flags;
+-
+- spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
+- pTxd = pTxPort->pTxdRingHead;
+- for (i=0; i<pAC->TxDescrPerRing; i++) {
+- pTxd->TBControl &= ~BMU_OWN;
+- pTxd = pTxd->pNextTxd;
+- }
+- FreeTxDescriptors(pAC, pTxPort);
+- spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+-} /* ClearTxRing */
+-
+-/*****************************************************************************
+- *
+- * SkGeSetMacAddr - Set the hardware MAC address
+- *
+- * Description:
+- * This function sets the MAC address used by the adapter.
+- *
+- * Returns:
+- * 0, if everything is ok
+- * !=0, on error
+- */
+-static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p)
+-{
+-
+-DEV_NET *pNet = netdev_priv(dev);
+-SK_AC *pAC = pNet->pAC;
+-
+-struct sockaddr *addr = p;
+-unsigned long Flags;
+-
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+- ("SkGeSetMacAddr starts now...\n"));
+- if(netif_running(dev))
+- return -EBUSY;
+-
+- memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
+-
+- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+-
+- if (pAC->RlmtNets == 2)
+- SkAddrOverride(pAC, pAC->IoBase, pNet->NetNr,
+- (SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS);
+- else
+- SkAddrOverride(pAC, pAC->IoBase, pAC->ActivePort,
+- (SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS);
+-
+-
+-
+- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+- return 0;
+-} /* SkGeSetMacAddr */
+-
+-
+-/*****************************************************************************
+- *
+- * SkGeSetRxMode - set receive mode
+- *
+- * Description:
+- * This function sets the receive mode of an adapter. The adapter
+- * supports promiscuous mode, allmulticast mode and a number of
+- * multicast addresses. If more multicast addresses the available
+- * are selected, a hash function in the hardware is used.
+- *
+- * Returns:
+- * 0, if everything is ok
+- * !=0, on error
+- */
+-static void SkGeSetRxMode(struct SK_NET_DEVICE *dev)
+-{
+-
+-DEV_NET *pNet;
+-SK_AC *pAC;
+-
+-struct dev_mc_list *pMcList;
+-int i;
+-int PortIdx;
+-unsigned long Flags;
+-
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+- ("SkGeSetRxMode starts now... "));
+-
+- pNet = netdev_priv(dev);
+- pAC = pNet->pAC;
+- if (pAC->RlmtNets == 1)
+- PortIdx = pAC->ActivePort;
+- else
+- PortIdx = pNet->NetNr;
+-
+- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+- if (dev->flags & IFF_PROMISC) {
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+- ("PROMISCUOUS mode\n"));
+- SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
+- SK_PROM_MODE_LLC);
+- } else if (dev->flags & IFF_ALLMULTI) {
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+- ("ALLMULTI mode\n"));
+- SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
+- SK_PROM_MODE_ALL_MC);
+- } else {
+- SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
+- SK_PROM_MODE_NONE);
+- SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0);
+-
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+- ("Number of MC entries: %d ", dev->mc_count));
+-
+- pMcList = dev->mc_list;
+- for (i=0; i<dev->mc_count; i++, pMcList = pMcList->next) {
+- SkAddrMcAdd(pAC, pAC->IoBase, PortIdx,
+- (SK_MAC_ADDR*)pMcList->dmi_addr, 0);
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MCA,
+- ("%02x:%02x:%02x:%02x:%02x:%02x\n",
+- pMcList->dmi_addr[0],
+- pMcList->dmi_addr[1],
+- pMcList->dmi_addr[2],
+- pMcList->dmi_addr[3],
+- pMcList->dmi_addr[4],
+- pMcList->dmi_addr[5]));
+- }
+- SkAddrMcUpdate(pAC, pAC->IoBase, PortIdx);
+- }
+- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-
+- return;
+-} /* SkGeSetRxMode */
+-
+-
+-/*****************************************************************************
+- *
+- * SkGeChangeMtu - set the MTU to another value
+- *
+- * Description:
+- * This function sets is called whenever the MTU size is changed
+- * (ifconfig mtu xxx dev ethX). If the MTU is bigger than standard
+- * ethernet MTU size, long frame support is activated.
+- *
+- * Returns:
+- * 0, if everything is ok
+- * !=0, on error
+- */
+-static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int NewMtu)
+-{
+-DEV_NET *pNet;
+-struct net_device *pOtherDev;
+-SK_AC *pAC;
+-unsigned long Flags;
+-int i;
+-SK_EVPARA EvPara;
+-
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+- ("SkGeChangeMtu starts now...\n"));
+-
+- pNet = netdev_priv(dev);
+- pAC = pNet->pAC;
+-
+- if ((NewMtu < 68) || (NewMtu > SK_JUMBO_MTU)) {
+- return -EINVAL;
+- }
+-
+- if(pAC->BoardLevel != SK_INIT_RUN) {
+- return -EINVAL;
+- }
+-
+-#ifdef SK_DIAG_SUPPORT
+- if (pAC->DiagModeActive == DIAG_ACTIVE) {
+- if (pAC->DiagFlowCtrl == SK_FALSE) {
+- return -1; /* still in use, deny any actions of MTU */
+- } else {
+- pAC->DiagFlowCtrl = SK_FALSE;
+- }
+- }
+-#endif
+-
+- pOtherDev = pAC->dev[1 - pNet->NetNr];
+-
+- if ( netif_running(pOtherDev) && (pOtherDev->mtu > 1500)
+- && (NewMtu <= 1500))
+- return 0;
+-
+- pAC->RxBufSize = NewMtu + 32;
+- dev->mtu = NewMtu;
+-
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+- ("New MTU: %d\n", NewMtu));
+-
+- /*
+- ** Prevent any reconfiguration while changing the MTU
+- ** by disabling any interrupts
+- */
+- SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+-
+- /*
+- ** Notify RLMT that any ports are to be stopped
+- */
+- EvPara.Para32[0] = 0;
+- EvPara.Para32[1] = -1;
+- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+- EvPara.Para32[0] = 1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+- } else {
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+- }
+-
+- /*
+- ** After calling the SkEventDispatcher(), RLMT is aware about
+- ** the stopped ports -> configuration can take place!
+- */
+- SkEventDispatcher(pAC, pAC->IoBase);
+-
+- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+- spin_lock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock);
+- netif_stop_queue(pAC->dev[i]);
+-
+- }
+-
+- /*
+- ** Depending on the desired MTU size change, a different number of
+- ** RX buffers need to be allocated
+- */
+- if (NewMtu > 1500) {
+- /*
+- ** Use less rx buffers
+- */
+- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+- pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing -
+- (pAC->RxDescrPerRing / 4);
+- } else {
+- if (i == pAC->ActivePort) {
+- pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing -
+- (pAC->RxDescrPerRing / 4);
+- } else {
+- pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing -
+- (pAC->RxDescrPerRing / 10);
+- }
+- }
+- }
+- } else {
+- /*
+- ** Use the normal amount of rx buffers
+- */
+- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+- pAC->RxPort[i].RxFillLimit = 1;
+- } else {
+- if (i == pAC->ActivePort) {
+- pAC->RxPort[i].RxFillLimit = 1;
+- } else {
+- pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing -
+- (pAC->RxDescrPerRing / 4);
+- }
+- }
+- }
+- }
+-
+- SkGeDeInit(pAC, pAC->IoBase);
+-
+- /*
+- ** enable/disable hardware support for long frames
+- */
+- if (NewMtu > 1500) {
+-// pAC->JumboActivated = SK_TRUE; /* is never set back !!! */
+- pAC->GIni.GIPortUsage = SK_JUMBO_LINK;
+- } else {
+- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+- pAC->GIni.GIPortUsage = SK_MUL_LINK;
+- } else {
+- pAC->GIni.GIPortUsage = SK_RED_LINK;
+- }
+- }
+-
+- SkGeInit( pAC, pAC->IoBase, SK_INIT_IO);
+- SkI2cInit( pAC, pAC->IoBase, SK_INIT_IO);
+- SkEventInit(pAC, pAC->IoBase, SK_INIT_IO);
+- SkPnmiInit( pAC, pAC->IoBase, SK_INIT_IO);
+- SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO);
+- SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO);
+- SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO);
+-
+- /*
+- ** tschilling:
+- ** Speed and others are set back to default in level 1 init!
+- */
+- GetConfiguration(pAC);
+-
+- SkGeInit( pAC, pAC->IoBase, SK_INIT_RUN);
+- SkI2cInit( pAC, pAC->IoBase, SK_INIT_RUN);
+- SkEventInit(pAC, pAC->IoBase, SK_INIT_RUN);
+- SkPnmiInit( pAC, pAC->IoBase, SK_INIT_RUN);
+- SkAddrInit( pAC, pAC->IoBase, SK_INIT_RUN);
+- SkRlmtInit( pAC, pAC->IoBase, SK_INIT_RUN);
+- SkTimerInit(pAC, pAC->IoBase, SK_INIT_RUN);
+-
+- /*
+- ** clear and reinit the rx rings here
+- */
+- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+- ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE);
+- ClearRxRing(pAC, &pAC->RxPort[i]);
+- FillRxRing(pAC, &pAC->RxPort[i]);
+-
+- /*
+- ** Enable transmit descriptor polling
+- */
+- SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE);
+- FillRxRing(pAC, &pAC->RxPort[i]);
+- };
+-
+- SkGeYellowLED(pAC, pAC->IoBase, 1);
+- SkDimEnableModerationIfNeeded(pAC);
+- SkDimDisplayModerationSettings(pAC);
+-
+- netif_start_queue(pAC->dev[pNet->PortNr]);
+- for (i=pAC->GIni.GIMacsFound-1; i>=0; i--) {
+- spin_unlock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock);
+- }
+-
+- /*
+- ** Enable Interrupts again
+- */
+- SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
+- SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);
+-
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
+- SkEventDispatcher(pAC, pAC->IoBase);
+-
+- /*
+- ** Notify RLMT about the changing and restarting one (or more) ports
+- */
+- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+- EvPara.Para32[0] = pAC->RlmtNets;
+- EvPara.Para32[1] = -1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS, EvPara);
+- EvPara.Para32[0] = pNet->PortNr;
+- EvPara.Para32[1] = -1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
+-
+- if (netif_running(pOtherDev)) {
+- DEV_NET *pOtherNet = netdev_priv(pOtherDev);
+- EvPara.Para32[0] = pOtherNet->PortNr;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
+- }
+- } else {
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
+- }
+-
+- SkEventDispatcher(pAC, pAC->IoBase);
+- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-
+- /*
+- ** While testing this driver with latest kernel 2.5 (2.5.70), it
+- ** seems as if upper layers have a problem to handle a successful
+- ** return value of '0'. If such a zero is returned, the complete
+- ** system hangs for several minutes (!), which is in acceptable.
+- **
+- ** Currently it is not clear, what the exact reason for this problem
+- ** is. The implemented workaround for 2.5 is to return the desired
+- ** new MTU size if all needed changes for the new MTU size where
+- ** performed. In kernels 2.2 and 2.4, a zero value is returned,
+- ** which indicates the successful change of the mtu-size.
+- */
+- return NewMtu;
+-
+-} /* SkGeChangeMtu */
+-
+-
+-/*****************************************************************************
+- *
+- * SkGeStats - return ethernet device statistics
+- *
+- * Description:
+- * This function return statistic data about the ethernet device
+- * to the operating system.
+- *
+- * Returns:
+- * pointer to the statistic structure.
+- */
+-static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev)
+-{
+-DEV_NET *pNet = netdev_priv(dev);
+-SK_AC *pAC = pNet->pAC;
+-SK_PNMI_STRUCT_DATA *pPnmiStruct; /* structure for all Pnmi-Data */
+-SK_PNMI_STAT *pPnmiStat; /* pointer to virtual XMAC stat. data */
+-SK_PNMI_CONF *pPnmiConf; /* pointer to virtual link config. */
+-unsigned int Size; /* size of pnmi struct */
+-unsigned long Flags; /* for spin lock */
+-
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+- ("SkGeStats starts now...\n"));
+- pPnmiStruct = &pAC->PnmiStruct;
+-
+-#ifdef SK_DIAG_SUPPORT
+- if ((pAC->DiagModeActive == DIAG_NOTACTIVE) &&
+- (pAC->BoardLevel == SK_INIT_RUN)) {
+-#endif
+- SK_MEMSET(pPnmiStruct, 0, sizeof(SK_PNMI_STRUCT_DATA));
+- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+- Size = SK_PNMI_STRUCT_SIZE;
+- SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, pNet->NetNr);
+- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-#ifdef SK_DIAG_SUPPORT
+- }
+-#endif
+-
+- pPnmiStat = &pPnmiStruct->Stat[0];
+- pPnmiConf = &pPnmiStruct->Conf[0];
+-
+- pAC->stats.rx_packets = (SK_U32) pPnmiStruct->RxDeliveredCts & 0xFFFFFFFF;
+- pAC->stats.tx_packets = (SK_U32) pPnmiStat->StatTxOkCts & 0xFFFFFFFF;
+- pAC->stats.rx_bytes = (SK_U32) pPnmiStruct->RxOctetsDeliveredCts;
+- pAC->stats.tx_bytes = (SK_U32) pPnmiStat->StatTxOctetsOkCts;
+-
+- if (dev->mtu <= 1500) {
+- pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF;
+- } else {
+- pAC->stats.rx_errors = (SK_U32) ((pPnmiStruct->InErrorsCts -
+- pPnmiStat->StatRxTooLongCts) & 0xFFFFFFFF);
+- }
+-
+-
+- if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC && pAC->HWRevision < 12)
+- pAC->stats.rx_errors = pAC->stats.rx_errors - pPnmiStat->StatRxShortsCts;
+-
+- pAC->stats.tx_errors = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF;
+- pAC->stats.rx_dropped = (SK_U32) pPnmiStruct->RxNoBufCts & 0xFFFFFFFF;
+- pAC->stats.tx_dropped = (SK_U32) pPnmiStruct->TxNoBufCts & 0xFFFFFFFF;
+- pAC->stats.multicast = (SK_U32) pPnmiStat->StatRxMulticastOkCts & 0xFFFFFFFF;
+- pAC->stats.collisions = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF;
+-
+- /* detailed rx_errors: */
+- pAC->stats.rx_length_errors = (SK_U32) pPnmiStat->StatRxRuntCts & 0xFFFFFFFF;
+- pAC->stats.rx_over_errors = (SK_U32) pPnmiStat->StatRxFifoOverflowCts & 0xFFFFFFFF;
+- pAC->stats.rx_crc_errors = (SK_U32) pPnmiStat->StatRxFcsCts & 0xFFFFFFFF;
+- pAC->stats.rx_frame_errors = (SK_U32) pPnmiStat->StatRxFramingCts & 0xFFFFFFFF;
+- pAC->stats.rx_fifo_errors = (SK_U32) pPnmiStat->StatRxFifoOverflowCts & 0xFFFFFFFF;
+- pAC->stats.rx_missed_errors = (SK_U32) pPnmiStat->StatRxMissedCts & 0xFFFFFFFF;
+-
+- /* detailed tx_errors */
+- pAC->stats.tx_aborted_errors = (SK_U32) 0;
+- pAC->stats.tx_carrier_errors = (SK_U32) pPnmiStat->StatTxCarrierCts & 0xFFFFFFFF;
+- pAC->stats.tx_fifo_errors = (SK_U32) pPnmiStat->StatTxFifoUnderrunCts & 0xFFFFFFFF;
+- pAC->stats.tx_heartbeat_errors = (SK_U32) pPnmiStat->StatTxCarrierCts & 0xFFFFFFFF;
+- pAC->stats.tx_window_errors = (SK_U32) 0;
+-
+- return(&pAC->stats);
+-} /* SkGeStats */
+-
+-/*
+- * Basic MII register access
+- */
+-static int SkGeMiiIoctl(struct net_device *dev,
+- struct mii_ioctl_data *data, int cmd)
+-{
+- DEV_NET *pNet = netdev_priv(dev);
+- SK_AC *pAC = pNet->pAC;
+- SK_IOC IoC = pAC->IoBase;
+- int Port = pNet->PortNr;
+- SK_GEPORT *pPrt = &pAC->GIni.GP[Port];
+- unsigned long Flags;
+- int err = 0;
+- int reg = data->reg_num & 0x1f;
+- SK_U16 val = data->val_in;
+-
+- if (!netif_running(dev))
+- return -ENODEV; /* Phy still in reset */
+-
+- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+- switch(cmd) {
+- case SIOCGMIIPHY:
+- data->phy_id = pPrt->PhyAddr;
+-
+- /* fallthru */
+- case SIOCGMIIREG:
+- if (pAC->GIni.GIGenesis)
+- SkXmPhyRead(pAC, IoC, Port, reg, &val);
+- else
+- SkGmPhyRead(pAC, IoC, Port, reg, &val);
+-
+- data->val_out = val;
+- break;
+-
+- case SIOCSMIIREG:
+- if (!capable(CAP_NET_ADMIN))
+- err = -EPERM;
+-
+- else if (pAC->GIni.GIGenesis)
+- SkXmPhyWrite(pAC, IoC, Port, reg, val);
+- else
+- SkGmPhyWrite(pAC, IoC, Port, reg, val);
+- break;
+- default:
+- err = -EOPNOTSUPP;
+- }
+- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+- return err;
+-}
+-
+-
+-/*****************************************************************************
+- *
+- * SkGeIoctl - IO-control function
+- *
+- * Description:
+- * This function is called if an ioctl is issued on the device.
+- * There are three subfunction for reading, writing and test-writing
+- * the private MIB data structure (useful for SysKonnect-internal tools).
+- *
+- * Returns:
+- * 0, if everything is ok
+- * !=0, on error
+- */
+-static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd)
+-{
+-DEV_NET *pNet;
+-SK_AC *pAC;
+-void *pMemBuf;
+-struct pci_dev *pdev = NULL;
+-SK_GE_IOCTL Ioctl;
+-unsigned int Err = 0;
+-int Size = 0;
+-int Ret = 0;
+-unsigned int Length = 0;
+-int HeaderLength = sizeof(SK_U32) + sizeof(SK_U32);
+-
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+- ("SkGeIoctl starts now...\n"));
+-
+- pNet = netdev_priv(dev);
+- pAC = pNet->pAC;
+-
+- if (cmd == SIOCGMIIPHY || cmd == SIOCSMIIREG || cmd == SIOCGMIIREG)
+- return SkGeMiiIoctl(dev, if_mii(rq), cmd);
+-
+- if(copy_from_user(&Ioctl, rq->ifr_data, sizeof(SK_GE_IOCTL))) {
+- return -EFAULT;
+- }
+-
+- switch(cmd) {
+- case SK_IOCTL_SETMIB:
+- case SK_IOCTL_PRESETMIB:
+- if (!capable(CAP_NET_ADMIN)) return -EPERM;
+- case SK_IOCTL_GETMIB:
+- if(copy_from_user(&pAC->PnmiStruct, Ioctl.pData,
+- Ioctl.Len<sizeof(pAC->PnmiStruct)?
+- Ioctl.Len : sizeof(pAC->PnmiStruct))) {
+- return -EFAULT;
+- }
+- Size = SkGeIocMib(pNet, Ioctl.Len, cmd);
+- if(copy_to_user(Ioctl.pData, &pAC->PnmiStruct,
+- Ioctl.Len<Size? Ioctl.Len : Size)) {
+- return -EFAULT;
+- }
+- Ioctl.Len = Size;
+- if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
+- return -EFAULT;
+- }
+- break;
+- case SK_IOCTL_GEN:
+- if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) {
+- Length = Ioctl.Len;
+- } else {
+- Length = sizeof(pAC->PnmiStruct) + HeaderLength;
+- }
+- if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) {
+- return -ENOMEM;
+- }
+- if(copy_from_user(pMemBuf, Ioctl.pData, Length)) {
+- Err = -EFAULT;
+- goto fault_gen;
+- }
+- if ((Ret = SkPnmiGenIoctl(pAC, pAC->IoBase, pMemBuf, &Length, 0)) < 0) {
+- Err = -EFAULT;
+- goto fault_gen;
+- }
+- if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) {
+- Err = -EFAULT;
+- goto fault_gen;
+- }
+- Ioctl.Len = Length;
+- if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
+- Err = -EFAULT;
+- goto fault_gen;
+- }
+-fault_gen:
+- kfree(pMemBuf); /* cleanup everything */
+- break;
+-#ifdef SK_DIAG_SUPPORT
+- case SK_IOCTL_DIAG:
+- if (!capable(CAP_NET_ADMIN)) return -EPERM;
+- if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) {
+- Length = Ioctl.Len;
+- } else {
+- Length = sizeof(pAC->PnmiStruct) + HeaderLength;
+- }
+- if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) {
+- return -ENOMEM;
+- }
+- if(copy_from_user(pMemBuf, Ioctl.pData, Length)) {
+- Err = -EFAULT;
+- goto fault_diag;
+- }
+- pdev = pAC->PciDev;
+- Length = 3 * sizeof(SK_U32); /* Error, Bus and Device */
+- /*
+- ** While coding this new IOCTL interface, only a few lines of code
+- ** are to to be added. Therefore no dedicated function has been
+- ** added. If more functionality is added, a separate function
+- ** should be used...
+- */
+- * ((SK_U32 *)pMemBuf) = 0;
+- * ((SK_U32 *)pMemBuf + 1) = pdev->bus->number;
+- * ((SK_U32 *)pMemBuf + 2) = ParseDeviceNbrFromSlotName(pci_name(pdev));
+- if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) {
+- Err = -EFAULT;
+- goto fault_diag;
+- }
+- Ioctl.Len = Length;
+- if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
+- Err = -EFAULT;
+- goto fault_diag;
+- }
+-fault_diag:
+- kfree(pMemBuf); /* cleanup everything */
+- break;
+-#endif
+- default:
+- Err = -EOPNOTSUPP;
+- }
+-
+- return(Err);
+-
+-} /* SkGeIoctl */
+-
+-
+-/*****************************************************************************
+- *
+- * SkGeIocMib - handle a GetMib, SetMib- or PresetMib-ioctl message
+- *
+- * Description:
+- * This function reads/writes the MIB data using PNMI (Private Network
+- * Management Interface).
+- * The destination for the data must be provided with the
+- * ioctl call and is given to the driver in the form of
+- * a user space address.
+- * Copying from the user-provided data area into kernel messages
+- * and back is done by copy_from_user and copy_to_user calls in
+- * SkGeIoctl.
+- *
+- * Returns:
+- * returned size from PNMI call
+- */
+-static int SkGeIocMib(
+-DEV_NET *pNet, /* pointer to the adapter context */
+-unsigned int Size, /* length of ioctl data */
+-int mode) /* flag for set/preset */
+-{
+-unsigned long Flags; /* for spin lock */
+-SK_AC *pAC;
+-
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+- ("SkGeIocMib starts now...\n"));
+- pAC = pNet->pAC;
+- /* access MIB */
+- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+- switch(mode) {
+- case SK_IOCTL_GETMIB:
+- SkPnmiGetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size,
+- pNet->NetNr);
+- break;
+- case SK_IOCTL_PRESETMIB:
+- SkPnmiPreSetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size,
+- pNet->NetNr);
+- break;
+- case SK_IOCTL_SETMIB:
+- SkPnmiSetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size,
+- pNet->NetNr);
+- break;
+- default:
+- break;
+- }
+- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+- ("MIB data access succeeded\n"));
+- return (Size);
+-} /* SkGeIocMib */
+-
+-
+-/*****************************************************************************
+- *
+- * GetConfiguration - read configuration information
+- *
+- * Description:
+- * This function reads per-adapter configuration information from
+- * the options provided on the command line.
+- *
+- * Returns:
+- * none
+- */
+-static void GetConfiguration(
+-SK_AC *pAC) /* pointer to the adapter context structure */
+-{
+-SK_I32 Port; /* preferred port */
+-SK_BOOL AutoSet;
+-SK_BOOL DupSet;
+-int LinkSpeed = SK_LSPEED_AUTO; /* Link speed */
+-int AutoNeg = 1; /* autoneg off (0) or on (1) */
+-int DuplexCap = 0; /* 0=both,1=full,2=half */
+-int FlowCtrl = SK_FLOW_MODE_SYM_OR_REM; /* FlowControl */
+-int MSMode = SK_MS_MODE_AUTO; /* master/slave mode */
+-
+-SK_BOOL IsConTypeDefined = SK_TRUE;
+-SK_BOOL IsLinkSpeedDefined = SK_TRUE;
+-SK_BOOL IsFlowCtrlDefined = SK_TRUE;
+-SK_BOOL IsRoleDefined = SK_TRUE;
+-SK_BOOL IsModeDefined = SK_TRUE;
+-/*
+- * The two parameters AutoNeg. and DuplexCap. map to one configuration
+- * parameter. The mapping is described by this table:
+- * DuplexCap -> | both | full | half |
+- * AutoNeg | | | |
+- * -----------------------------------------------------------------
+- * Off | illegal | Full | Half |
+- * -----------------------------------------------------------------
+- * On | AutoBoth | AutoFull | AutoHalf |
+- * -----------------------------------------------------------------
+- * Sense | AutoSense | AutoSense | AutoSense |
+- */
+-int Capabilities[3][3] =
+- { { -1, SK_LMODE_FULL , SK_LMODE_HALF },
+- {SK_LMODE_AUTOBOTH , SK_LMODE_AUTOFULL , SK_LMODE_AUTOHALF },
+- {SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE} };
+-
+-#define DC_BOTH 0
+-#define DC_FULL 1
+-#define DC_HALF 2
+-#define AN_OFF 0
+-#define AN_ON 1
+-#define AN_SENS 2
+-#define M_CurrPort pAC->GIni.GP[Port]
+-
+-
+- /*
+- ** Set the default values first for both ports!
+- */
+- for (Port = 0; Port < SK_MAX_MACS; Port++) {
+- M_CurrPort.PLinkModeConf = Capabilities[AN_ON][DC_BOTH];
+- M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM;
+- M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
+- M_CurrPort.PLinkSpeed = SK_LSPEED_AUTO;
+- }
+-
+- /*
+- ** Check merged parameter ConType. If it has not been used,
+- ** verify any other parameter (e.g. AutoNeg) and use default values.
+- **
+- ** Stating both ConType and other lowlevel link parameters is also
+- ** possible. If this is the case, the passed ConType-parameter is
+- ** overwritten by the lowlevel link parameter.
+- **
+- ** The following settings are used for a merged ConType-parameter:
+- **
+- ** ConType DupCap AutoNeg FlowCtrl Role Speed
+- ** ------- ------ ------- -------- ---------- -----
+- ** Auto Both On SymOrRem Auto Auto
+- ** 100FD Full Off None <ignored> 100
+- ** 100HD Half Off None <ignored> 100
+- ** 10FD Full Off None <ignored> 10
+- ** 10HD Half Off None <ignored> 10
+- **
+- ** This ConType parameter is used for all ports of the adapter!
+- */
+- if ( (ConType != NULL) &&
+- (pAC->Index < SK_MAX_CARD_PARAM) &&
+- (ConType[pAC->Index] != NULL) ) {
+-
+- /* Check chipset family */
+- if ((!pAC->ChipsetType) &&
+- (strcmp(ConType[pAC->Index],"Auto")!=0) &&
+- (strcmp(ConType[pAC->Index],"")!=0)) {
+- /* Set the speed parameter back */
+- printk("sk98lin: Illegal value \"%s\" "
+- "for ConType."
+- " Using Auto.\n",
+- ConType[pAC->Index]);
+-
+- sprintf(ConType[pAC->Index], "Auto");
+- }
+-
+- if (strcmp(ConType[pAC->Index],"")==0) {
+- IsConTypeDefined = SK_FALSE; /* No ConType defined */
+- } else if (strcmp(ConType[pAC->Index],"Auto")==0) {
+- for (Port = 0; Port < SK_MAX_MACS; Port++) {
+- M_CurrPort.PLinkModeConf = Capabilities[AN_ON][DC_BOTH];
+- M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM;
+- M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
+- M_CurrPort.PLinkSpeed = SK_LSPEED_AUTO;
+- }
+- } else if (strcmp(ConType[pAC->Index],"100FD")==0) {
+- for (Port = 0; Port < SK_MAX_MACS; Port++) {
+- M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL];
+- M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+- M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
+- M_CurrPort.PLinkSpeed = SK_LSPEED_100MBPS;
+- }
+- } else if (strcmp(ConType[pAC->Index],"100HD")==0) {
+- for (Port = 0; Port < SK_MAX_MACS; Port++) {
+- M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF];
+- M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+- M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
+- M_CurrPort.PLinkSpeed = SK_LSPEED_100MBPS;
+- }
+- } else if (strcmp(ConType[pAC->Index],"10FD")==0) {
+- for (Port = 0; Port < SK_MAX_MACS; Port++) {
+- M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL];
+- M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+- M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
+- M_CurrPort.PLinkSpeed = SK_LSPEED_10MBPS;
+- }
+- } else if (strcmp(ConType[pAC->Index],"10HD")==0) {
+- for (Port = 0; Port < SK_MAX_MACS; Port++) {
+- M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF];
+- M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+- M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
+- M_CurrPort.PLinkSpeed = SK_LSPEED_10MBPS;
+- }
+- } else {
+- printk("sk98lin: Illegal value \"%s\" for ConType\n",
+- ConType[pAC->Index]);
+- IsConTypeDefined = SK_FALSE; /* Wrong ConType defined */
+- }
+- } else {
+- IsConTypeDefined = SK_FALSE; /* No ConType defined */
+- }
+-
+- /*
+- ** Parse any parameter settings for port A:
+- ** a) any LinkSpeed stated?
+- */
+- if (Speed_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+- Speed_A[pAC->Index] != NULL) {
+- if (strcmp(Speed_A[pAC->Index],"")==0) {
+- IsLinkSpeedDefined = SK_FALSE;
+- } else if (strcmp(Speed_A[pAC->Index],"Auto")==0) {
+- LinkSpeed = SK_LSPEED_AUTO;
+- } else if (strcmp(Speed_A[pAC->Index],"10")==0) {
+- LinkSpeed = SK_LSPEED_10MBPS;
+- } else if (strcmp(Speed_A[pAC->Index],"100")==0) {
+- LinkSpeed = SK_LSPEED_100MBPS;
+- } else if (strcmp(Speed_A[pAC->Index],"1000")==0) {
+- LinkSpeed = SK_LSPEED_1000MBPS;
+- } else {
+- printk("sk98lin: Illegal value \"%s\" for Speed_A\n",
+- Speed_A[pAC->Index]);
+- IsLinkSpeedDefined = SK_FALSE;
+- }
+- } else {
+- IsLinkSpeedDefined = SK_FALSE;
+- }
+-
+- /*
+- ** Check speed parameter:
+- ** Only copper type adapter and GE V2 cards
+- */
+- if (((!pAC->ChipsetType) || (pAC->GIni.GICopperType != SK_TRUE)) &&
+- ((LinkSpeed != SK_LSPEED_AUTO) &&
+- (LinkSpeed != SK_LSPEED_1000MBPS))) {
+- printk("sk98lin: Illegal value for Speed_A. "
+- "Not a copper card or GE V2 card\n Using "
+- "speed 1000\n");
+- LinkSpeed = SK_LSPEED_1000MBPS;
+- }
+-
+- /*
+- ** Decide whether to set new config value if somethig valid has
+- ** been received.
+- */
+- if (IsLinkSpeedDefined) {
+- pAC->GIni.GP[0].PLinkSpeed = LinkSpeed;
+- }
+-
+- /*
+- ** b) Any Autonegotiation and DuplexCapabilities set?
+- ** Please note that both belong together...
+- */
+- AutoNeg = AN_ON; /* tschilling: Default: Autonegotiation on! */
+- AutoSet = SK_FALSE;
+- if (AutoNeg_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+- AutoNeg_A[pAC->Index] != NULL) {
+- AutoSet = SK_TRUE;
+- if (strcmp(AutoNeg_A[pAC->Index],"")==0) {
+- AutoSet = SK_FALSE;
+- } else if (strcmp(AutoNeg_A[pAC->Index],"On")==0) {
+- AutoNeg = AN_ON;
+- } else if (strcmp(AutoNeg_A[pAC->Index],"Off")==0) {
+- AutoNeg = AN_OFF;
+- } else if (strcmp(AutoNeg_A[pAC->Index],"Sense")==0) {
+- AutoNeg = AN_SENS;
+- } else {
+- printk("sk98lin: Illegal value \"%s\" for AutoNeg_A\n",
+- AutoNeg_A[pAC->Index]);
+- }
+- }
+-
+- DuplexCap = DC_BOTH;
+- DupSet = SK_FALSE;
+- if (DupCap_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+- DupCap_A[pAC->Index] != NULL) {
+- DupSet = SK_TRUE;
+- if (strcmp(DupCap_A[pAC->Index],"")==0) {
+- DupSet = SK_FALSE;
+- } else if (strcmp(DupCap_A[pAC->Index],"Both")==0) {
+- DuplexCap = DC_BOTH;
+- } else if (strcmp(DupCap_A[pAC->Index],"Full")==0) {
+- DuplexCap = DC_FULL;
+- } else if (strcmp(DupCap_A[pAC->Index],"Half")==0) {
+- DuplexCap = DC_HALF;
+- } else {
+- printk("sk98lin: Illegal value \"%s\" for DupCap_A\n",
+- DupCap_A[pAC->Index]);
+- }
+- }
+-
+- /*
+- ** Check for illegal combinations
+- */
+- if ((LinkSpeed == SK_LSPEED_1000MBPS) &&
+- ((DuplexCap == SK_LMODE_STAT_AUTOHALF) ||
+- (DuplexCap == SK_LMODE_STAT_HALF)) &&
+- (pAC->ChipsetType)) {
+- printk("sk98lin: Half Duplex not possible with Gigabit speed!\n"
+- " Using Full Duplex.\n");
+- DuplexCap = DC_FULL;
+- }
+-
+- if ( AutoSet && AutoNeg==AN_SENS && DupSet) {
+- printk("sk98lin, Port A: DuplexCapabilities"
+- " ignored using Sense mode\n");
+- }
+-
+- if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){
+- printk("sk98lin: Port A: Illegal combination"
+- " of values AutoNeg. and DuplexCap.\n Using "
+- "Full Duplex\n");
+- DuplexCap = DC_FULL;
+- }
+-
+- if (AutoSet && AutoNeg==AN_OFF && !DupSet) {
+- DuplexCap = DC_FULL;
+- }
+-
+- if (!AutoSet && DupSet) {
+- printk("sk98lin: Port A: Duplex setting not"
+- " possible in\n default AutoNegotiation mode"
+- " (Sense).\n Using AutoNegotiation On\n");
+- AutoNeg = AN_ON;
+- }
+-
+- /*
+- ** set the desired mode
+- */
+- if (AutoSet || DupSet) {
+- pAC->GIni.GP[0].PLinkModeConf = Capabilities[AutoNeg][DuplexCap];
+- }
+-
+- /*
+- ** c) Any Flowcontrol-parameter set?
+- */
+- if (FlowCtrl_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+- FlowCtrl_A[pAC->Index] != NULL) {
+- if (strcmp(FlowCtrl_A[pAC->Index],"") == 0) {
+- IsFlowCtrlDefined = SK_FALSE;
+- } else if (strcmp(FlowCtrl_A[pAC->Index],"SymOrRem") == 0) {
+- FlowCtrl = SK_FLOW_MODE_SYM_OR_REM;
+- } else if (strcmp(FlowCtrl_A[pAC->Index],"Sym")==0) {
+- FlowCtrl = SK_FLOW_MODE_SYMMETRIC;
+- } else if (strcmp(FlowCtrl_A[pAC->Index],"LocSend")==0) {
+- FlowCtrl = SK_FLOW_MODE_LOC_SEND;
+- } else if (strcmp(FlowCtrl_A[pAC->Index],"None")==0) {
+- FlowCtrl = SK_FLOW_MODE_NONE;
+- } else {
+- printk("sk98lin: Illegal value \"%s\" for FlowCtrl_A\n",
+- FlowCtrl_A[pAC->Index]);
+- IsFlowCtrlDefined = SK_FALSE;
+- }
+- } else {
+- IsFlowCtrlDefined = SK_FALSE;
+- }
+-
+- if (IsFlowCtrlDefined) {
+- if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) {
+- printk("sk98lin: Port A: FlowControl"
+- " impossible without AutoNegotiation,"
+- " disabled\n");
+- FlowCtrl = SK_FLOW_MODE_NONE;
+- }
+- pAC->GIni.GP[0].PFlowCtrlMode = FlowCtrl;
+- }
+-
+- /*
+- ** d) What is with the RoleParameter?
+- */
+- if (Role_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+- Role_A[pAC->Index] != NULL) {
+- if (strcmp(Role_A[pAC->Index],"")==0) {
+- IsRoleDefined = SK_FALSE;
+- } else if (strcmp(Role_A[pAC->Index],"Auto")==0) {
+- MSMode = SK_MS_MODE_AUTO;
+- } else if (strcmp(Role_A[pAC->Index],"Master")==0) {
+- MSMode = SK_MS_MODE_MASTER;
+- } else if (strcmp(Role_A[pAC->Index],"Slave")==0) {
+- MSMode = SK_MS_MODE_SLAVE;
+- } else {
+- printk("sk98lin: Illegal value \"%s\" for Role_A\n",
+- Role_A[pAC->Index]);
+- IsRoleDefined = SK_FALSE;
+- }
+- } else {
+- IsRoleDefined = SK_FALSE;
+- }
+-
+- if (IsRoleDefined == SK_TRUE) {
+- pAC->GIni.GP[0].PMSMode = MSMode;
+- }
+-
+-
+-
+- /*
+- ** Parse any parameter settings for port B:
+- ** a) any LinkSpeed stated?
+- */
+- IsConTypeDefined = SK_TRUE;
+- IsLinkSpeedDefined = SK_TRUE;
+- IsFlowCtrlDefined = SK_TRUE;
+- IsModeDefined = SK_TRUE;
+-
+- if (Speed_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+- Speed_B[pAC->Index] != NULL) {
+- if (strcmp(Speed_B[pAC->Index],"")==0) {
+- IsLinkSpeedDefined = SK_FALSE;
+- } else if (strcmp(Speed_B[pAC->Index],"Auto")==0) {
+- LinkSpeed = SK_LSPEED_AUTO;
+- } else if (strcmp(Speed_B[pAC->Index],"10")==0) {
+- LinkSpeed = SK_LSPEED_10MBPS;
+- } else if (strcmp(Speed_B[pAC->Index],"100")==0) {
+- LinkSpeed = SK_LSPEED_100MBPS;
+- } else if (strcmp(Speed_B[pAC->Index],"1000")==0) {
+- LinkSpeed = SK_LSPEED_1000MBPS;
+- } else {
+- printk("sk98lin: Illegal value \"%s\" for Speed_B\n",
+- Speed_B[pAC->Index]);
+- IsLinkSpeedDefined = SK_FALSE;
+- }
+- } else {
+- IsLinkSpeedDefined = SK_FALSE;
+- }
+-
+- /*
+- ** Check speed parameter:
+- ** Only copper type adapter and GE V2 cards
+- */
+- if (((!pAC->ChipsetType) || (pAC->GIni.GICopperType != SK_TRUE)) &&
+- ((LinkSpeed != SK_LSPEED_AUTO) &&
+- (LinkSpeed != SK_LSPEED_1000MBPS))) {
+- printk("sk98lin: Illegal value for Speed_B. "
+- "Not a copper card or GE V2 card\n Using "
+- "speed 1000\n");
+- LinkSpeed = SK_LSPEED_1000MBPS;
+- }
+-
+- /*
+- ** Decide whether to set new config value if somethig valid has
+- ** been received.
+- */
+- if (IsLinkSpeedDefined) {
+- pAC->GIni.GP[1].PLinkSpeed = LinkSpeed;
+- }
+-
+- /*
+- ** b) Any Autonegotiation and DuplexCapabilities set?
+- ** Please note that both belong together...
+- */
+- AutoNeg = AN_SENS; /* default: do auto Sense */
+- AutoSet = SK_FALSE;
+- if (AutoNeg_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+- AutoNeg_B[pAC->Index] != NULL) {
+- AutoSet = SK_TRUE;
+- if (strcmp(AutoNeg_B[pAC->Index],"")==0) {
+- AutoSet = SK_FALSE;
+- } else if (strcmp(AutoNeg_B[pAC->Index],"On")==0) {
+- AutoNeg = AN_ON;
+- } else if (strcmp(AutoNeg_B[pAC->Index],"Off")==0) {
+- AutoNeg = AN_OFF;
+- } else if (strcmp(AutoNeg_B[pAC->Index],"Sense")==0) {
+- AutoNeg = AN_SENS;
+- } else {
+- printk("sk98lin: Illegal value \"%s\" for AutoNeg_B\n",
+- AutoNeg_B[pAC->Index]);
+- }
+- }
+-
+- DuplexCap = DC_BOTH;
+- DupSet = SK_FALSE;
+- if (DupCap_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+- DupCap_B[pAC->Index] != NULL) {
+- DupSet = SK_TRUE;
+- if (strcmp(DupCap_B[pAC->Index],"")==0) {
+- DupSet = SK_FALSE;
+- } else if (strcmp(DupCap_B[pAC->Index],"Both")==0) {
+- DuplexCap = DC_BOTH;
+- } else if (strcmp(DupCap_B[pAC->Index],"Full")==0) {
+- DuplexCap = DC_FULL;
+- } else if (strcmp(DupCap_B[pAC->Index],"Half")==0) {
+- DuplexCap = DC_HALF;
+- } else {
+- printk("sk98lin: Illegal value \"%s\" for DupCap_B\n",
+- DupCap_B[pAC->Index]);
+- }
+- }
+-
+-
+- /*
+- ** Check for illegal combinations
+- */
+- if ((LinkSpeed == SK_LSPEED_1000MBPS) &&
+- ((DuplexCap == SK_LMODE_STAT_AUTOHALF) ||
+- (DuplexCap == SK_LMODE_STAT_HALF)) &&
+- (pAC->ChipsetType)) {
+- printk("sk98lin: Half Duplex not possible with Gigabit speed!\n"
+- " Using Full Duplex.\n");
+- DuplexCap = DC_FULL;
+- }
+-
+- if (AutoSet && AutoNeg==AN_SENS && DupSet) {
+- printk("sk98lin, Port B: DuplexCapabilities"
+- " ignored using Sense mode\n");
+- }
+-
+- if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){
+- printk("sk98lin: Port B: Illegal combination"
+- " of values AutoNeg. and DuplexCap.\n Using "
+- "Full Duplex\n");
+- DuplexCap = DC_FULL;
+- }
+-
+- if (AutoSet && AutoNeg==AN_OFF && !DupSet) {
+- DuplexCap = DC_FULL;
+- }
+-
+- if (!AutoSet && DupSet) {
+- printk("sk98lin: Port B: Duplex setting not"
+- " possible in\n default AutoNegotiation mode"
+- " (Sense).\n Using AutoNegotiation On\n");
+- AutoNeg = AN_ON;
+- }
+-
+- /*
+- ** set the desired mode
+- */
+- if (AutoSet || DupSet) {
+- pAC->GIni.GP[1].PLinkModeConf = Capabilities[AutoNeg][DuplexCap];
+- }
+-
+- /*
+- ** c) Any FlowCtrl parameter set?
+- */
+- if (FlowCtrl_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+- FlowCtrl_B[pAC->Index] != NULL) {
+- if (strcmp(FlowCtrl_B[pAC->Index],"") == 0) {
+- IsFlowCtrlDefined = SK_FALSE;
+- } else if (strcmp(FlowCtrl_B[pAC->Index],"SymOrRem") == 0) {
+- FlowCtrl = SK_FLOW_MODE_SYM_OR_REM;
+- } else if (strcmp(FlowCtrl_B[pAC->Index],"Sym")==0) {
+- FlowCtrl = SK_FLOW_MODE_SYMMETRIC;
+- } else if (strcmp(FlowCtrl_B[pAC->Index],"LocSend")==0) {
+- FlowCtrl = SK_FLOW_MODE_LOC_SEND;
+- } else if (strcmp(FlowCtrl_B[pAC->Index],"None")==0) {
+- FlowCtrl = SK_FLOW_MODE_NONE;
+- } else {
+- printk("sk98lin: Illegal value \"%s\" for FlowCtrl_B\n",
+- FlowCtrl_B[pAC->Index]);
+- IsFlowCtrlDefined = SK_FALSE;
+- }
+- } else {
+- IsFlowCtrlDefined = SK_FALSE;
+- }
+-
+- if (IsFlowCtrlDefined) {
+- if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) {
+- printk("sk98lin: Port B: FlowControl"
+- " impossible without AutoNegotiation,"
+- " disabled\n");
+- FlowCtrl = SK_FLOW_MODE_NONE;
+- }
+- pAC->GIni.GP[1].PFlowCtrlMode = FlowCtrl;
+- }
+-
+- /*
+- ** d) What is the RoleParameter?
+- */
+- if (Role_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+- Role_B[pAC->Index] != NULL) {
+- if (strcmp(Role_B[pAC->Index],"")==0) {
+- IsRoleDefined = SK_FALSE;
+- } else if (strcmp(Role_B[pAC->Index],"Auto")==0) {
+- MSMode = SK_MS_MODE_AUTO;
+- } else if (strcmp(Role_B[pAC->Index],"Master")==0) {
+- MSMode = SK_MS_MODE_MASTER;
+- } else if (strcmp(Role_B[pAC->Index],"Slave")==0) {
+- MSMode = SK_MS_MODE_SLAVE;
+- } else {
+- printk("sk98lin: Illegal value \"%s\" for Role_B\n",
+- Role_B[pAC->Index]);
+- IsRoleDefined = SK_FALSE;
+- }
+- } else {
+- IsRoleDefined = SK_FALSE;
+- }
+-
+- if (IsRoleDefined) {
+- pAC->GIni.GP[1].PMSMode = MSMode;
+- }
+-
+- /*
+- ** Evaluate settings for both ports
+- */
+- pAC->ActivePort = 0;
+- if (PrefPort != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+- PrefPort[pAC->Index] != NULL) {
+- if (strcmp(PrefPort[pAC->Index],"") == 0) { /* Auto */
+- pAC->ActivePort = 0;
+- pAC->Rlmt.Net[0].Preference = -1; /* auto */
+- pAC->Rlmt.Net[0].PrefPort = 0;
+- } else if (strcmp(PrefPort[pAC->Index],"A") == 0) {
+- /*
+- ** do not set ActivePort here, thus a port
+- ** switch is issued after net up.
+- */
+- Port = 0;
+- pAC->Rlmt.Net[0].Preference = Port;
+- pAC->Rlmt.Net[0].PrefPort = Port;
+- } else if (strcmp(PrefPort[pAC->Index],"B") == 0) {
+- /*
+- ** do not set ActivePort here, thus a port
+- ** switch is issued after net up.
+- */
+- if (pAC->GIni.GIMacsFound == 1) {
+- printk("sk98lin: Illegal value \"B\" for PrefPort.\n"
+- " Port B not available on single port adapters.\n");
+-
+- pAC->ActivePort = 0;
+- pAC->Rlmt.Net[0].Preference = -1; /* auto */
+- pAC->Rlmt.Net[0].PrefPort = 0;
+- } else {
+- Port = 1;
+- pAC->Rlmt.Net[0].Preference = Port;
+- pAC->Rlmt.Net[0].PrefPort = Port;
+- }
+- } else {
+- printk("sk98lin: Illegal value \"%s\" for PrefPort\n",
+- PrefPort[pAC->Index]);
+- }
+- }
+-
+- pAC->RlmtNets = 1;
+-
+- if (RlmtMode != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+- RlmtMode[pAC->Index] != NULL) {
+- if (strcmp(RlmtMode[pAC->Index], "") == 0) {
+- pAC->RlmtMode = 0;
+- } else if (strcmp(RlmtMode[pAC->Index], "CheckLinkState") == 0) {
+- pAC->RlmtMode = SK_RLMT_CHECK_LINK;
+- } else if (strcmp(RlmtMode[pAC->Index], "CheckLocalPort") == 0) {
+- pAC->RlmtMode = SK_RLMT_CHECK_LINK |
+- SK_RLMT_CHECK_LOC_LINK;
+- } else if (strcmp(RlmtMode[pAC->Index], "CheckSeg") == 0) {
+- pAC->RlmtMode = SK_RLMT_CHECK_LINK |
+- SK_RLMT_CHECK_LOC_LINK |
+- SK_RLMT_CHECK_SEG;
+- } else if ((strcmp(RlmtMode[pAC->Index], "DualNet") == 0) &&
+- (pAC->GIni.GIMacsFound == 2)) {
+- pAC->RlmtMode = SK_RLMT_CHECK_LINK;
+- pAC->RlmtNets = 2;
+- } else {
+- printk("sk98lin: Illegal value \"%s\" for"
+- " RlmtMode, using default\n",
+- RlmtMode[pAC->Index]);
+- pAC->RlmtMode = 0;
+- }
+- } else {
+- pAC->RlmtMode = 0;
+- }
+-
+- /*
+- ** Check the interrupt moderation parameters
+- */
+- if (Moderation[pAC->Index] != NULL) {
+- if (strcmp(Moderation[pAC->Index], "") == 0) {
+- pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
+- } else if (strcmp(Moderation[pAC->Index], "Static") == 0) {
+- pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_STATIC;
+- } else if (strcmp(Moderation[pAC->Index], "Dynamic") == 0) {
+- pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_DYNAMIC;
+- } else if (strcmp(Moderation[pAC->Index], "None") == 0) {
+- pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
+- } else {
+- printk("sk98lin: Illegal value \"%s\" for Moderation.\n"
+- " Disable interrupt moderation.\n",
+- Moderation[pAC->Index]);
+- pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
+- }
+- } else {
+- pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
+- }
+-
+- if (Stats[pAC->Index] != NULL) {
+- if (strcmp(Stats[pAC->Index], "Yes") == 0) {
+- pAC->DynIrqModInfo.DisplayStats = SK_TRUE;
+- } else {
+- pAC->DynIrqModInfo.DisplayStats = SK_FALSE;
+- }
+- } else {
+- pAC->DynIrqModInfo.DisplayStats = SK_FALSE;
+- }
+-
+- if (ModerationMask[pAC->Index] != NULL) {
+- if (strcmp(ModerationMask[pAC->Index], "Rx") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY;
+- } else if (strcmp(ModerationMask[pAC->Index], "Tx") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_ONLY;
+- } else if (strcmp(ModerationMask[pAC->Index], "Sp") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_ONLY;
+- } else if (strcmp(ModerationMask[pAC->Index], "RxSp") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX;
+- } else if (strcmp(ModerationMask[pAC->Index], "SpRx") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX;
+- } else if (strcmp(ModerationMask[pAC->Index], "RxTx") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
+- } else if (strcmp(ModerationMask[pAC->Index], "TxRx") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
+- } else if (strcmp(ModerationMask[pAC->Index], "TxSp") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX;
+- } else if (strcmp(ModerationMask[pAC->Index], "SpTx") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX;
+- } else if (strcmp(ModerationMask[pAC->Index], "RxTxSp") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+- } else if (strcmp(ModerationMask[pAC->Index], "RxSpTx") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+- } else if (strcmp(ModerationMask[pAC->Index], "TxRxSp") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+- } else if (strcmp(ModerationMask[pAC->Index], "TxSpRx") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+- } else if (strcmp(ModerationMask[pAC->Index], "SpTxRx") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+- } else if (strcmp(ModerationMask[pAC->Index], "SpRxTx") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+- } else { /* some rubbish */
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY;
+- }
+- } else { /* operator has stated nothing */
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
+- }
+-
+- if (AutoSizing[pAC->Index] != NULL) {
+- if (strcmp(AutoSizing[pAC->Index], "On") == 0) {
+- pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
+- } else {
+- pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
+- }
+- } else { /* operator has stated nothing */
+- pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
+- }
+-
+- if (IntsPerSec[pAC->Index] != 0) {
+- if ((IntsPerSec[pAC->Index]< C_INT_MOD_IPS_LOWER_RANGE) ||
+- (IntsPerSec[pAC->Index] > C_INT_MOD_IPS_UPPER_RANGE)) {
+- printk("sk98lin: Illegal value \"%d\" for IntsPerSec. (Range: %d - %d)\n"
+- " Using default value of %i.\n",
+- IntsPerSec[pAC->Index],
+- C_INT_MOD_IPS_LOWER_RANGE,
+- C_INT_MOD_IPS_UPPER_RANGE,
+- C_INTS_PER_SEC_DEFAULT);
+- pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT;
+- } else {
+- pAC->DynIrqModInfo.MaxModIntsPerSec = IntsPerSec[pAC->Index];
+- }
+- } else {
+- pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT;
+- }
+-
+- /*
+- ** Evaluate upper and lower moderation threshold
+- */
+- pAC->DynIrqModInfo.MaxModIntsPerSecUpperLimit =
+- pAC->DynIrqModInfo.MaxModIntsPerSec +
+- (pAC->DynIrqModInfo.MaxModIntsPerSec / 2);
+-
+- pAC->DynIrqModInfo.MaxModIntsPerSecLowerLimit =
+- pAC->DynIrqModInfo.MaxModIntsPerSec -
+- (pAC->DynIrqModInfo.MaxModIntsPerSec / 2);
+-
+- pAC->DynIrqModInfo.PrevTimeVal = jiffies; /* initial value */
+-
+-
+-} /* GetConfiguration */
+-
+-
+-/*****************************************************************************
+- *
+- * ProductStr - return a adapter identification string from vpd
+- *
+- * Description:
+- * This function reads the product name string from the vpd area
+- * and puts it the field pAC->DeviceString.
+- *
+- * Returns: N/A
+- */
+-static inline int ProductStr(
+- SK_AC *pAC, /* pointer to adapter context */
+- char *DeviceStr, /* result string */
+- int StrLen /* length of the string */
+-)
+-{
+-char Keyword[] = VPD_NAME; /* vpd productname identifier */
+-int ReturnCode; /* return code from vpd_read */
+-unsigned long Flags;
+-
+- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+- ReturnCode = VpdRead(pAC, pAC->IoBase, Keyword, DeviceStr, &StrLen);
+- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-
+- return ReturnCode;
+-} /* ProductStr */
+-
+-/*****************************************************************************
+- *
+- * StartDrvCleanupTimer - Start timer to check for descriptors which
+- * might be placed in descriptor ring, but
+- * havent been handled up to now
+- *
+- * Description:
+- * This function requests a HW-timer fo the Yukon card. The actions to
+- * perform when this timer expires, are located in the SkDrvEvent().
+- *
+- * Returns: N/A
+- */
+-static void
+-StartDrvCleanupTimer(SK_AC *pAC) {
+- SK_EVPARA EventParam; /* Event struct for timer event */
+-
+- SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam));
+- EventParam.Para32[0] = SK_DRV_RX_CLEANUP_TIMER;
+- SkTimerStart(pAC, pAC->IoBase, &pAC->DrvCleanupTimer,
+- SK_DRV_RX_CLEANUP_TIMER_LENGTH,
+- SKGE_DRV, SK_DRV_TIMER, EventParam);
+-}
+-
+-/*****************************************************************************
+- *
+- * StopDrvCleanupTimer - Stop timer to check for descriptors
+- *
+- * Description:
+- * This function requests a HW-timer fo the Yukon card. The actions to
+- * perform when this timer expires, are located in the SkDrvEvent().
+- *
+- * Returns: N/A
+- */
+-static void
+-StopDrvCleanupTimer(SK_AC *pAC) {
+- SkTimerStop(pAC, pAC->IoBase, &pAC->DrvCleanupTimer);
+- SK_MEMSET((char *) &pAC->DrvCleanupTimer, 0, sizeof(SK_TIMER));
+-}
+-
+-/****************************************************************************/
+-/* functions for common modules *********************************************/
+-/****************************************************************************/
+-
+-
+-/*****************************************************************************
+- *
+- * SkDrvAllocRlmtMbuf - allocate an RLMT mbuf
+- *
+- * Description:
+- * This routine returns an RLMT mbuf or NULL. The RLMT Mbuf structure
+- * is embedded into a socket buff data area.
+- *
+- * Context:
+- * runtime
+- *
+- * Returns:
+- * NULL or pointer to Mbuf.
+- */
+-SK_MBUF *SkDrvAllocRlmtMbuf(
+-SK_AC *pAC, /* pointer to adapter context */
+-SK_IOC IoC, /* the IO-context */
+-unsigned BufferSize) /* size of the requested buffer */
+-{
+-SK_MBUF *pRlmtMbuf; /* pointer to a new rlmt-mbuf structure */
+-struct sk_buff *pMsgBlock; /* pointer to a new message block */
+-
+- pMsgBlock = alloc_skb(BufferSize + sizeof(SK_MBUF), GFP_ATOMIC);
+- if (pMsgBlock == NULL) {
+- return (NULL);
+- }
+- pRlmtMbuf = (SK_MBUF*) pMsgBlock->data;
+- skb_reserve(pMsgBlock, sizeof(SK_MBUF));
+- pRlmtMbuf->pNext = NULL;
+- pRlmtMbuf->pOs = pMsgBlock;
+- pRlmtMbuf->pData = pMsgBlock->data; /* Data buffer. */
+- pRlmtMbuf->Size = BufferSize; /* Data buffer size. */
+- pRlmtMbuf->Length = 0; /* Length of packet (<= Size). */
+- return (pRlmtMbuf);
+-
+-} /* SkDrvAllocRlmtMbuf */
+-
+-
+-/*****************************************************************************
+- *
+- * SkDrvFreeRlmtMbuf - free an RLMT mbuf
+- *
+- * Description:
+- * This routine frees one or more RLMT mbuf(s).
+- *
+- * Context:
+- * runtime
+- *
+- * Returns:
+- * Nothing
+- */
+-void SkDrvFreeRlmtMbuf(
+-SK_AC *pAC, /* pointer to adapter context */
+-SK_IOC IoC, /* the IO-context */
+-SK_MBUF *pMbuf) /* size of the requested buffer */
+-{
+-SK_MBUF *pFreeMbuf;
+-SK_MBUF *pNextMbuf;
+-
+- pFreeMbuf = pMbuf;
+- do {
+- pNextMbuf = pFreeMbuf->pNext;
+- DEV_KFREE_SKB_ANY(pFreeMbuf->pOs);
+- pFreeMbuf = pNextMbuf;
+- } while ( pFreeMbuf != NULL );
+-} /* SkDrvFreeRlmtMbuf */
+-
+-
+-/*****************************************************************************
+- *
+- * SkOsGetTime - provide a time value
+- *
+- * Description:
+- * This routine provides a time value. The unit is 1/HZ (defined by Linux).
+- * It is not used for absolute time, but only for time differences.
+- *
+- *
+- * Returns:
+- * Time value
+- */
+-SK_U64 SkOsGetTime(SK_AC *pAC)
+-{
+- SK_U64 PrivateJiffies;
+- SkOsGetTimeCurrent(pAC, &PrivateJiffies);
+- return PrivateJiffies;
+-} /* SkOsGetTime */
+-
+-
+-/*****************************************************************************
+- *
+- * SkPciReadCfgDWord - read a 32 bit value from pci config space
+- *
+- * Description:
+- * This routine reads a 32 bit value from the pci configuration
+- * space.
+- *
+- * Returns:
+- * 0 - indicate everything worked ok.
+- * != 0 - error indication
+- */
+-int SkPciReadCfgDWord(
+-SK_AC *pAC, /* Adapter Control structure pointer */
+-int PciAddr, /* PCI register address */
+-SK_U32 *pVal) /* pointer to store the read value */
+-{
+- pci_read_config_dword(pAC->PciDev, PciAddr, pVal);
+- return(0);
+-} /* SkPciReadCfgDWord */
+-
+-
+-/*****************************************************************************
+- *
+- * SkPciReadCfgWord - read a 16 bit value from pci config space
+- *
+- * Description:
+- * This routine reads a 16 bit value from the pci configuration
+- * space.
+- *
+- * Returns:
+- * 0 - indicate everything worked ok.
+- * != 0 - error indication
+- */
+-int SkPciReadCfgWord(
+-SK_AC *pAC, /* Adapter Control structure pointer */
+-int PciAddr, /* PCI register address */
+-SK_U16 *pVal) /* pointer to store the read value */
+-{
+- pci_read_config_word(pAC->PciDev, PciAddr, pVal);
+- return(0);
+-} /* SkPciReadCfgWord */
+-
+-
+-/*****************************************************************************
+- *
+- * SkPciReadCfgByte - read a 8 bit value from pci config space
+- *
+- * Description:
+- * This routine reads a 8 bit value from the pci configuration
+- * space.
+- *
+- * Returns:
+- * 0 - indicate everything worked ok.
+- * != 0 - error indication
+- */
+-int SkPciReadCfgByte(
+-SK_AC *pAC, /* Adapter Control structure pointer */
+-int PciAddr, /* PCI register address */
+-SK_U8 *pVal) /* pointer to store the read value */
+-{
+- pci_read_config_byte(pAC->PciDev, PciAddr, pVal);
+- return(0);
+-} /* SkPciReadCfgByte */
+-
+-
+-/*****************************************************************************
+- *
+- * SkPciWriteCfgWord - write a 16 bit value to pci config space
+- *
+- * Description:
+- * This routine writes a 16 bit value to the pci configuration
+- * space. The flag PciConfigUp indicates whether the config space
+- * is accesible or must be set up first.
+- *
+- * Returns:
+- * 0 - indicate everything worked ok.
+- * != 0 - error indication
+- */
+-int SkPciWriteCfgWord(
+-SK_AC *pAC, /* Adapter Control structure pointer */
+-int PciAddr, /* PCI register address */
+-SK_U16 Val) /* pointer to store the read value */
+-{
+- pci_write_config_word(pAC->PciDev, PciAddr, Val);
+- return(0);
+-} /* SkPciWriteCfgWord */
+-
+-
+-/*****************************************************************************
+- *
+- * SkPciWriteCfgWord - write a 8 bit value to pci config space
+- *
+- * Description:
+- * This routine writes a 8 bit value to the pci configuration
+- * space. The flag PciConfigUp indicates whether the config space
+- * is accesible or must be set up first.
+- *
+- * Returns:
+- * 0 - indicate everything worked ok.
+- * != 0 - error indication
+- */
+-int SkPciWriteCfgByte(
+-SK_AC *pAC, /* Adapter Control structure pointer */
+-int PciAddr, /* PCI register address */
+-SK_U8 Val) /* pointer to store the read value */
+-{
+- pci_write_config_byte(pAC->PciDev, PciAddr, Val);
+- return(0);
+-} /* SkPciWriteCfgByte */
+-
+-
+-/*****************************************************************************
+- *
+- * SkDrvEvent - handle driver events
+- *
+- * Description:
+- * This function handles events from all modules directed to the driver
+- *
+- * Context:
+- * Is called under protection of slow path lock.
+- *
+- * Returns:
+- * 0 if everything ok
+- * < 0 on error
+- *
+- */
+-int SkDrvEvent(
+-SK_AC *pAC, /* pointer to adapter context */
+-SK_IOC IoC, /* io-context */
+-SK_U32 Event, /* event-id */
+-SK_EVPARA Param) /* event-parameter */
+-{
+-SK_MBUF *pRlmtMbuf; /* pointer to a rlmt-mbuf structure */
+-struct sk_buff *pMsg; /* pointer to a message block */
+-int FromPort; /* the port from which we switch away */
+-int ToPort; /* the port we switch to */
+-SK_EVPARA NewPara; /* parameter for further events */
+-int Stat;
+-unsigned long Flags;
+-SK_BOOL DualNet;
+-
+- switch (Event) {
+- case SK_DRV_ADAP_FAIL:
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+- ("ADAPTER FAIL EVENT\n"));
+- printk("%s: Adapter failed.\n", pAC->dev[0]->name);
+- /* disable interrupts */
+- SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+- /* cgoos */
+- break;
+- case SK_DRV_PORT_FAIL:
+- FromPort = Param.Para32[0];
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+- ("PORT FAIL EVENT, Port: %d\n", FromPort));
+- if (FromPort == 0) {
+- printk("%s: Port A failed.\n", pAC->dev[0]->name);
+- } else {
+- printk("%s: Port B failed.\n", pAC->dev[1]->name);
+- }
+- /* cgoos */
+- break;
+- case SK_DRV_PORT_RESET: /* SK_U32 PortIdx */
+- /* action list 4 */
+- FromPort = Param.Para32[0];
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+- ("PORT RESET EVENT, Port: %d ", FromPort));
+- NewPara.Para64 = FromPort;
+- SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara);
+- spin_lock_irqsave(
+- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+- Flags);
+-
+- SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST);
+- netif_carrier_off(pAC->dev[Param.Para32[0]]);
+- spin_unlock_irqrestore(
+- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+- Flags);
+-
+- /* clear rx ring from received frames */
+- ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE);
+-
+- ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
+- spin_lock_irqsave(
+- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+- Flags);
+-
+- /* tschilling: Handling of return value inserted. */
+- if (SkGeInitPort(pAC, IoC, FromPort)) {
+- if (FromPort == 0) {
+- printk("%s: SkGeInitPort A failed.\n", pAC->dev[0]->name);
+- } else {
+- printk("%s: SkGeInitPort B failed.\n", pAC->dev[1]->name);
+- }
+- }
+- SkAddrMcUpdate(pAC,IoC, FromPort);
+- PortReInitBmu(pAC, FromPort);
+- SkGePollTxD(pAC, IoC, FromPort, SK_TRUE);
+- ClearAndStartRx(pAC, FromPort);
+- spin_unlock_irqrestore(
+- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+- Flags);
+- break;
+- case SK_DRV_NET_UP: /* SK_U32 PortIdx */
+- { struct net_device *dev = pAC->dev[Param.Para32[0]];
+- /* action list 5 */
+- FromPort = Param.Para32[0];
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+- ("NET UP EVENT, Port: %d ", Param.Para32[0]));
+- /* Mac update */
+- SkAddrMcUpdate(pAC,IoC, FromPort);
+-
+- if (DoPrintInterfaceChange) {
+- printk("%s: network connection up using"
+- " port %c\n", pAC->dev[Param.Para32[0]]->name, 'A'+Param.Para32[0]);
+-
+- /* tschilling: Values changed according to LinkSpeedUsed. */
+- Stat = pAC->GIni.GP[FromPort].PLinkSpeedUsed;
+- if (Stat == SK_LSPEED_STAT_10MBPS) {
+- printk(" speed: 10\n");
+- } else if (Stat == SK_LSPEED_STAT_100MBPS) {
+- printk(" speed: 100\n");
+- } else if (Stat == SK_LSPEED_STAT_1000MBPS) {
+- printk(" speed: 1000\n");
+- } else {
+- printk(" speed: unknown\n");
+- }
+-
+-
+- Stat = pAC->GIni.GP[FromPort].PLinkModeStatus;
+- if (Stat == SK_LMODE_STAT_AUTOHALF ||
+- Stat == SK_LMODE_STAT_AUTOFULL) {
+- printk(" autonegotiation: yes\n");
+- }
+- else {
+- printk(" autonegotiation: no\n");
+- }
+- if (Stat == SK_LMODE_STAT_AUTOHALF ||
+- Stat == SK_LMODE_STAT_HALF) {
+- printk(" duplex mode: half\n");
+- }
+- else {
+- printk(" duplex mode: full\n");
+- }
+- Stat = pAC->GIni.GP[FromPort].PFlowCtrlStatus;
+- if (Stat == SK_FLOW_STAT_REM_SEND ) {
+- printk(" flowctrl: remote send\n");
+- }
+- else if (Stat == SK_FLOW_STAT_LOC_SEND ){
+- printk(" flowctrl: local send\n");
+- }
+- else if (Stat == SK_FLOW_STAT_SYMMETRIC ){
+- printk(" flowctrl: symmetric\n");
+- }
+- else {
+- printk(" flowctrl: none\n");
+- }
+-
+- /* tschilling: Check against CopperType now. */
+- if ((pAC->GIni.GICopperType == SK_TRUE) &&
+- (pAC->GIni.GP[FromPort].PLinkSpeedUsed ==
+- SK_LSPEED_STAT_1000MBPS)) {
+- Stat = pAC->GIni.GP[FromPort].PMSStatus;
+- if (Stat == SK_MS_STAT_MASTER ) {
+- printk(" role: master\n");
+- }
+- else if (Stat == SK_MS_STAT_SLAVE ) {
+- printk(" role: slave\n");
+- }
+- else {
+- printk(" role: ???\n");
+- }
+- }
+-
+- /*
+- Display dim (dynamic interrupt moderation)
+- informations
+- */
+- if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC)
+- printk(" irq moderation: static (%d ints/sec)\n",
+- pAC->DynIrqModInfo.MaxModIntsPerSec);
+- else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC)
+- printk(" irq moderation: dynamic (%d ints/sec)\n",
+- pAC->DynIrqModInfo.MaxModIntsPerSec);
+- else
+- printk(" irq moderation: disabled\n");
+-
+-
+- printk(" scatter-gather: %s\n",
+- (dev->features & NETIF_F_SG) ? "enabled" : "disabled");
+- printk(" tx-checksum: %s\n",
+- (dev->features & NETIF_F_IP_CSUM) ? "enabled" : "disabled");
+- printk(" rx-checksum: %s\n",
+- pAC->RxPort[Param.Para32[0]].RxCsum ? "enabled" : "disabled");
+-
+- } else {
+- DoPrintInterfaceChange = SK_TRUE;
+- }
+-
+- if ((Param.Para32[0] != pAC->ActivePort) &&
+- (pAC->RlmtNets == 1)) {
+- NewPara.Para32[0] = pAC->ActivePort;
+- NewPara.Para32[1] = Param.Para32[0];
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_INTERN,
+- NewPara);
+- }
+-
+- /* Inform the world that link protocol is up. */
+- netif_carrier_on(dev);
+- break;
+- }
+- case SK_DRV_NET_DOWN: /* SK_U32 Reason */
+- /* action list 7 */
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+- ("NET DOWN EVENT "));
+- if (DoPrintInterfaceChange) {
+- printk("%s: network connection down\n",
+- pAC->dev[Param.Para32[1]]->name);
+- } else {
+- DoPrintInterfaceChange = SK_TRUE;
+- }
+- netif_carrier_off(pAC->dev[Param.Para32[1]]);
+- break;
+- case SK_DRV_SWITCH_HARD: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+- ("PORT SWITCH HARD "));
+- case SK_DRV_SWITCH_SOFT: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
+- /* action list 6 */
+- printk("%s: switching to port %c\n", pAC->dev[0]->name,
+- 'A'+Param.Para32[1]);
+- case SK_DRV_SWITCH_INTERN: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
+- FromPort = Param.Para32[0];
+- ToPort = Param.Para32[1];
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+- ("PORT SWITCH EVENT, From: %d To: %d (Pref %d) ",
+- FromPort, ToPort, pAC->Rlmt.Net[0].PrefPort));
+- NewPara.Para64 = FromPort;
+- SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara);
+- NewPara.Para64 = ToPort;
+- SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara);
+- spin_lock_irqsave(
+- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+- Flags);
+- spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
+- SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST);
+- SkGeStopPort(pAC, IoC, ToPort, SK_STOP_ALL, SK_SOFT_RST);
+- spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
+- spin_unlock_irqrestore(
+- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+- Flags);
+-
+- ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); /* clears rx ring */
+- ReceiveIrq(pAC, &pAC->RxPort[ToPort], SK_FALSE); /* clears rx ring */
+-
+- ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
+- ClearTxRing(pAC, &pAC->TxPort[ToPort][TX_PRIO_LOW]);
+- spin_lock_irqsave(
+- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+- Flags);
+- spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
+- pAC->ActivePort = ToPort;
+-#if 0
+- SetQueueSizes(pAC);
+-#else
+- /* tschilling: New common function with minimum size check. */
+- DualNet = SK_FALSE;
+- if (pAC->RlmtNets == 2) {
+- DualNet = SK_TRUE;
+- }
+-
+- if (SkGeInitAssignRamToQueues(
+- pAC,
+- pAC->ActivePort,
+- DualNet)) {
+- spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
+- spin_unlock_irqrestore(
+- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+- Flags);
+- printk("SkGeInitAssignRamToQueues failed.\n");
+- break;
+- }
+-#endif
+- /* tschilling: Handling of return values inserted. */
+- if (SkGeInitPort(pAC, IoC, FromPort) ||
+- SkGeInitPort(pAC, IoC, ToPort)) {
+- printk("%s: SkGeInitPort failed.\n", pAC->dev[0]->name);
+- }
+- if (Event == SK_DRV_SWITCH_SOFT) {
+- SkMacRxTxEnable(pAC, IoC, FromPort);
+- }
+- SkMacRxTxEnable(pAC, IoC, ToPort);
+- SkAddrSwap(pAC, IoC, FromPort, ToPort);
+- SkAddrMcUpdate(pAC, IoC, FromPort);
+- SkAddrMcUpdate(pAC, IoC, ToPort);
+- PortReInitBmu(pAC, FromPort);
+- PortReInitBmu(pAC, ToPort);
+- SkGePollTxD(pAC, IoC, FromPort, SK_TRUE);
+- SkGePollTxD(pAC, IoC, ToPort, SK_TRUE);
+- ClearAndStartRx(pAC, FromPort);
+- ClearAndStartRx(pAC, ToPort);
+- spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
+- spin_unlock_irqrestore(
+- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+- Flags);
+- break;
+- case SK_DRV_RLMT_SEND: /* SK_MBUF *pMb */
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+- ("RLS "));
+- pRlmtMbuf = (SK_MBUF*) Param.pParaPtr;
+- pMsg = (struct sk_buff*) pRlmtMbuf->pOs;
+- skb_put(pMsg, pRlmtMbuf->Length);
+- if (XmitFrame(pAC, &pAC->TxPort[pRlmtMbuf->PortIdx][TX_PRIO_LOW],
+- pMsg) < 0)
+-
+- DEV_KFREE_SKB_ANY(pMsg);
+- break;
+- case SK_DRV_TIMER:
+- if (Param.Para32[0] == SK_DRV_MODERATION_TIMER) {
+- /*
+- ** expiration of the moderation timer implies that
+- ** dynamic moderation is to be applied
+- */
+- SkDimStartModerationTimer(pAC);
+- SkDimModerate(pAC);
+- if (pAC->DynIrqModInfo.DisplayStats) {
+- SkDimDisplayModerationSettings(pAC);
+- }
+- } else if (Param.Para32[0] == SK_DRV_RX_CLEANUP_TIMER) {
+- /*
+- ** check if we need to check for descriptors which
+- ** haven't been handled the last millisecs
+- */
+- StartDrvCleanupTimer(pAC);
+- if (pAC->GIni.GIMacsFound == 2) {
+- ReceiveIrq(pAC, &pAC->RxPort[1], SK_FALSE);
+- }
+- ReceiveIrq(pAC, &pAC->RxPort[0], SK_FALSE);
+- } else {
+- printk("Expiration of unknown timer\n");
+- }
+- break;
+- default:
+- break;
+- }
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+- ("END EVENT "));
+-
+- return (0);
+-} /* SkDrvEvent */
+-
+-
+-/*****************************************************************************
+- *
+- * SkErrorLog - log errors
+- *
+- * Description:
+- * This function logs errors to the system buffer and to the console
+- *
+- * Returns:
+- * 0 if everything ok
+- * < 0 on error
+- *
+- */
+-void SkErrorLog(
+-SK_AC *pAC,
+-int ErrClass,
+-int ErrNum,
+-char *pErrorMsg)
+-{
+-char ClassStr[80];
+-
+- switch (ErrClass) {
+- case SK_ERRCL_OTHER:
+- strcpy(ClassStr, "Other error");
+- break;
+- case SK_ERRCL_CONFIG:
+- strcpy(ClassStr, "Configuration error");
+- break;
+- case SK_ERRCL_INIT:
+- strcpy(ClassStr, "Initialization error");
+- break;
+- case SK_ERRCL_NORES:
+- strcpy(ClassStr, "Out of resources error");
+- break;
+- case SK_ERRCL_SW:
+- strcpy(ClassStr, "internal Software error");
+- break;
+- case SK_ERRCL_HW:
+- strcpy(ClassStr, "Hardware failure");
+- break;
+- case SK_ERRCL_COMM:
+- strcpy(ClassStr, "Communication error");
+- break;
+- }
+- printk(KERN_INFO "%s: -- ERROR --\n Class: %s\n"
+- " Nr: 0x%x\n Msg: %s\n", pAC->dev[0]->name,
+- ClassStr, ErrNum, pErrorMsg);
+-
+-} /* SkErrorLog */
+-
+-#ifdef SK_DIAG_SUPPORT
+-
+-/*****************************************************************************
+- *
+- * SkDrvEnterDiagMode - handles DIAG attach request
+- *
+- * Description:
+- * Notify the kernel to NOT access the card any longer due to DIAG
+- * Deinitialize the Card
+- *
+- * Returns:
+- * int
+- */
+-int SkDrvEnterDiagMode(
+-SK_AC *pAc) /* pointer to adapter context */
+-{
+- DEV_NET *pNet = netdev_priv(pAc->dev[0]);
+- SK_AC *pAC = pNet->pAC;
+-
+- SK_MEMCPY(&(pAc->PnmiBackup), &(pAc->PnmiStruct),
+- sizeof(SK_PNMI_STRUCT_DATA));
+-
+- pAC->DiagModeActive = DIAG_ACTIVE;
+- if (pAC->BoardLevel > SK_INIT_DATA) {
+- if (netif_running(pAC->dev[0])) {
+- pAC->WasIfUp[0] = SK_TRUE;
+- pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
+- DoPrintInterfaceChange = SK_FALSE;
+- SkDrvDeInitAdapter(pAC, 0); /* performs SkGeClose */
+- } else {
+- pAC->WasIfUp[0] = SK_FALSE;
+- }
+- if (pNet != netdev_priv(pAC->dev[1])) {
+- pNet = netdev_priv(pAC->dev[1]);
+- if (netif_running(pAC->dev[1])) {
+- pAC->WasIfUp[1] = SK_TRUE;
+- pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
+- DoPrintInterfaceChange = SK_FALSE;
+- SkDrvDeInitAdapter(pAC, 1); /* do SkGeClose */
+- } else {
+- pAC->WasIfUp[1] = SK_FALSE;
+- }
+- }
+- pAC->BoardLevel = SK_INIT_DATA;
+- }
+- return(0);
+-}
+-
+-/*****************************************************************************
+- *
+- * SkDrvLeaveDiagMode - handles DIAG detach request
+- *
+- * Description:
+- * Notify the kernel to may access the card again after use by DIAG
+- * Initialize the Card
+- *
+- * Returns:
+- * int
+- */
+-int SkDrvLeaveDiagMode(
+-SK_AC *pAc) /* pointer to adapter control context */
+-{
+- SK_MEMCPY(&(pAc->PnmiStruct), &(pAc->PnmiBackup),
+- sizeof(SK_PNMI_STRUCT_DATA));
+- pAc->DiagModeActive = DIAG_NOTACTIVE;
+- pAc->Pnmi.DiagAttached = SK_DIAG_IDLE;
+- if (pAc->WasIfUp[0] == SK_TRUE) {
+- pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
+- DoPrintInterfaceChange = SK_FALSE;
+- SkDrvInitAdapter(pAc, 0); /* first device */
+- }
+- if (pAc->WasIfUp[1] == SK_TRUE) {
+- pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
+- DoPrintInterfaceChange = SK_FALSE;
+- SkDrvInitAdapter(pAc, 1); /* second device */
+- }
+- return(0);
+-}
+-
+-/*****************************************************************************
+- *
+- * ParseDeviceNbrFromSlotName - Evaluate PCI device number
+- *
+- * Description:
+- * This function parses the PCI slot name information string and will
+- * retrieve the devcie number out of it. The slot_name maintianed by
+- * linux is in the form of '02:0a.0', whereas the first two characters
+- * represent the bus number in hex (in the sample above this is
+- * pci bus 0x02) and the next two characters the device number (0x0a).
+- *
+- * Returns:
+- * SK_U32: The device number from the PCI slot name
+- */
+-
+-static SK_U32 ParseDeviceNbrFromSlotName(
+-const char *SlotName) /* pointer to pci slot name eg. '02:0a.0' */
+-{
+- char *CurrCharPos = (char *) SlotName;
+- int FirstNibble = -1;
+- int SecondNibble = -1;
+- SK_U32 Result = 0;
+-
+- while (*CurrCharPos != '\0') {
+- if (*CurrCharPos == ':') {
+- while (*CurrCharPos != '.') {
+- CurrCharPos++;
+- if ( (*CurrCharPos >= '0') &&
+- (*CurrCharPos <= '9')) {
+- if (FirstNibble == -1) {
+- /* dec. value for '0' */
+- FirstNibble = *CurrCharPos - 48;
+- } else {
+- SecondNibble = *CurrCharPos - 48;
+- }
+- } else if ( (*CurrCharPos >= 'a') &&
+- (*CurrCharPos <= 'f') ) {
+- if (FirstNibble == -1) {
+- FirstNibble = *CurrCharPos - 87;
+- } else {
+- SecondNibble = *CurrCharPos - 87;
+- }
+- } else {
+- Result = 0;
+- }
+- }
+-
+- Result = FirstNibble;
+- Result = Result << 4; /* first nibble is higher one */
+- Result = Result | SecondNibble;
+- }
+- CurrCharPos++; /* next character */
+- }
+- return (Result);
+-}
+-
+-/****************************************************************************
+- *
+- * SkDrvDeInitAdapter - deinitialize adapter (this function is only
+- * called if Diag attaches to that card)
+- *
+- * Description:
+- * Close initialized adapter.
+- *
+- * Returns:
+- * 0 - on success
+- * error code - on error
+- */
+-static int SkDrvDeInitAdapter(
+-SK_AC *pAC, /* pointer to adapter context */
+-int devNbr) /* what device is to be handled */
+-{
+- struct SK_NET_DEVICE *dev;
+-
+- dev = pAC->dev[devNbr];
+-
+- /* On Linux 2.6 the network driver does NOT mess with reference
+- ** counts. The driver MUST be able to be unloaded at any time
+- ** due to the possibility of hotplug.
+- */
+- if (SkGeClose(dev) != 0) {
+- return (-1);
+- }
+- return (0);
+-
+-} /* SkDrvDeInitAdapter() */
+-
+-/****************************************************************************
+- *
+- * SkDrvInitAdapter - Initialize adapter (this function is only
+- * called if Diag deattaches from that card)
+- *
+- * Description:
+- * Close initialized adapter.
+- *
+- * Returns:
+- * 0 - on success
+- * error code - on error
+- */
+-static int SkDrvInitAdapter(
+-SK_AC *pAC, /* pointer to adapter context */
+-int devNbr) /* what device is to be handled */
+-{
+- struct SK_NET_DEVICE *dev;
+-
+- dev = pAC->dev[devNbr];
+-
+- if (SkGeOpen(dev) != 0) {
+- return (-1);
+- }
+-
+- /*
+- ** Use correct MTU size and indicate to kernel TX queue can be started
+- */
+- if (SkGeChangeMtu(dev, dev->mtu) != 0) {
+- return (-1);
+- }
+- return (0);
+-
+-} /* SkDrvInitAdapter */
+-
+-#endif
+-
+-#ifdef DEBUG
+-/****************************************************************************/
+-/* "debug only" section *****************************************************/
+-/****************************************************************************/
+-
+-
+-/*****************************************************************************
+- *
+- * DumpMsg - print a frame
+- *
+- * Description:
+- * This function prints frames to the system logfile/to the console.
+- *
+- * Returns: N/A
+- *
+- */
+-static void DumpMsg(struct sk_buff *skb, char *str)
+-{
+- int msglen;
+-
+- if (skb == NULL) {
+- printk("DumpMsg(): NULL-Message\n");
+- return;
+- }
+-
+- if (skb->data == NULL) {
+- printk("DumpMsg(): Message empty\n");
+- return;
+- }
+-
+- msglen = skb->len;
+- if (msglen > 64)
+- msglen = 64;
+-
+- printk("--- Begin of message from %s , len %d (from %d) ----\n", str, msglen, skb->len);
+-
+- DumpData((char *)skb->data, msglen);
+-
+- printk("------- End of message ---------\n");
+-} /* DumpMsg */
+-
+-
+-
+-/*****************************************************************************
+- *
+- * DumpData - print a data area
+- *
+- * Description:
+- * This function prints a area of data to the system logfile/to the
+- * console.
+- *
+- * Returns: N/A
+- *
+- */
+-static void DumpData(char *p, int size)
+-{
+-register int i;
+-int haddr, addr;
+-char hex_buffer[180];
+-char asc_buffer[180];
+-char HEXCHAR[] = "0123456789ABCDEF";
+-
+- addr = 0;
+- haddr = 0;
+- hex_buffer[0] = 0;
+- asc_buffer[0] = 0;
+- for (i=0; i < size; ) {
+- if (*p >= '0' && *p <='z')
+- asc_buffer[addr] = *p;
+- else
+- asc_buffer[addr] = '.';
+- addr++;
+- asc_buffer[addr] = 0;
+- hex_buffer[haddr] = HEXCHAR[(*p & 0xf0) >> 4];
+- haddr++;
+- hex_buffer[haddr] = HEXCHAR[*p & 0x0f];
+- haddr++;
+- hex_buffer[haddr] = ' ';
+- haddr++;
+- hex_buffer[haddr] = 0;
+- p++;
+- i++;
+- if (i%16 == 0) {
+- printk("%s %s\n", hex_buffer, asc_buffer);
+- addr = 0;
+- haddr = 0;
+- }
+- }
+-} /* DumpData */
+-
+-
+-/*****************************************************************************
+- *
+- * DumpLong - print a data area as long values
+- *
+- * Description:
+- * This function prints a area of data to the system logfile/to the
+- * console.
+- *
+- * Returns: N/A
+- *
+- */
+-static void DumpLong(char *pc, int size)
+-{
+-register int i;
+-int haddr, addr;
+-char hex_buffer[180];
+-char asc_buffer[180];
+-char HEXCHAR[] = "0123456789ABCDEF";
+-long *p;
+-int l;
+-
+- addr = 0;
+- haddr = 0;
+- hex_buffer[0] = 0;
+- asc_buffer[0] = 0;
+- p = (long*) pc;
+- for (i=0; i < size; ) {
+- l = (long) *p;
+- hex_buffer[haddr] = HEXCHAR[(l >> 28) & 0xf];
+- haddr++;
+- hex_buffer[haddr] = HEXCHAR[(l >> 24) & 0xf];
+- haddr++;
+- hex_buffer[haddr] = HEXCHAR[(l >> 20) & 0xf];
+- haddr++;
+- hex_buffer[haddr] = HEXCHAR[(l >> 16) & 0xf];
+- haddr++;
+- hex_buffer[haddr] = HEXCHAR[(l >> 12) & 0xf];
+- haddr++;
+- hex_buffer[haddr] = HEXCHAR[(l >> 8) & 0xf];
+- haddr++;
+- hex_buffer[haddr] = HEXCHAR[(l >> 4) & 0xf];
+- haddr++;
+- hex_buffer[haddr] = HEXCHAR[l & 0x0f];
+- haddr++;
+- hex_buffer[haddr] = ' ';
+- haddr++;
+- hex_buffer[haddr] = 0;
+- p++;
+- i++;
+- if (i%8 == 0) {
+- printk("%4x %s\n", (i-8)*4, hex_buffer);
+- haddr = 0;
+- }
+- }
+- printk("------------------------\n");
+-} /* DumpLong */
+-
+-#endif
+-
+-static int __devinit skge_probe_one(struct pci_dev *pdev,
+- const struct pci_device_id *ent)
+-{
+- SK_AC *pAC;
+- DEV_NET *pNet = NULL;
+- struct net_device *dev = NULL;
+- static int boards_found = 0;
+- int error = -ENODEV;
+- int using_dac = 0;
+- char DeviceStr[80];
+-
+- if (pci_enable_device(pdev))
+- goto out;
+-
+- /* Configure DMA attributes. */
+- if (sizeof(dma_addr_t) > sizeof(u32) &&
+- !(error = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
+- using_dac = 1;
+- error = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+- if (error < 0) {
+- printk(KERN_ERR "sk98lin %s unable to obtain 64 bit DMA "
+- "for consistent allocations\n", pci_name(pdev));
+- goto out_disable_device;
+- }
+- } else {
+- error = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+- if (error) {
+- printk(KERN_ERR "sk98lin %s no usable DMA configuration\n",
+- pci_name(pdev));
+- goto out_disable_device;
+- }
+- }
+-
+- error = -ENOMEM;
+- dev = alloc_etherdev(sizeof(DEV_NET));
+- if (!dev) {
+- printk(KERN_ERR "sk98lin: unable to allocate etherdev "
+- "structure!\n");
+- goto out_disable_device;
+- }
+-
+- pNet = netdev_priv(dev);
+- pNet->pAC = kzalloc(sizeof(SK_AC), GFP_KERNEL);
+- if (!pNet->pAC) {
+- printk(KERN_ERR "sk98lin: unable to allocate adapter "
+- "structure!\n");
+- goto out_free_netdev;
+- }
+-
+- pAC = pNet->pAC;
+- pAC->PciDev = pdev;
+-
+- pAC->dev[0] = dev;
+- pAC->dev[1] = dev;
+- pAC->CheckQueue = SK_FALSE;
+-
+- dev->irq = pdev->irq;
+-
+- error = SkGeInitPCI(pAC);
+- if (error) {
+- printk(KERN_ERR "sk98lin: PCI setup failed: %i\n", error);
+- goto out_free_netdev;
+- }
+-
+- dev->open = &SkGeOpen;
+- dev->stop = &SkGeClose;
+- dev->hard_start_xmit = &SkGeXmit;
+- dev->get_stats = &SkGeStats;
+- dev->set_multicast_list = &SkGeSetRxMode;
+- dev->set_mac_address = &SkGeSetMacAddr;
+- dev->do_ioctl = &SkGeIoctl;
+- dev->change_mtu = &SkGeChangeMtu;
+-#ifdef CONFIG_NET_POLL_CONTROLLER
+- dev->poll_controller = &SkGePollController;
+-#endif
+- SET_NETDEV_DEV(dev, &pdev->dev);
+- SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
+-
+- /* Use only if yukon hardware */
+- if (pAC->ChipsetType) {
+-#ifdef USE_SK_TX_CHECKSUM
+- dev->features |= NETIF_F_IP_CSUM;
+-#endif
+-#ifdef SK_ZEROCOPY
+- dev->features |= NETIF_F_SG;
+-#endif
+-#ifdef USE_SK_RX_CHECKSUM
+- pAC->RxPort[0].RxCsum = 1;
+-#endif
+- }
+-
+- if (using_dac)
+- dev->features |= NETIF_F_HIGHDMA;
+-
+- pAC->Index = boards_found++;
+-
+- error = SkGeBoardInit(dev, pAC);
+- if (error)
+- goto out_free_netdev;
+-
+- /* Read Adapter name from VPD */
+- if (ProductStr(pAC, DeviceStr, sizeof(DeviceStr)) != 0) {
+- error = -EIO;
+- printk(KERN_ERR "sk98lin: Could not read VPD data.\n");
+- goto out_free_resources;
+- }
+-
+- /* Register net device */
+- error = register_netdev(dev);
+- if (error) {
+- printk(KERN_ERR "sk98lin: Could not register device.\n");
+- goto out_free_resources;
+- }
+-
+- /* Print adapter specific string from vpd */
+- printk("%s: %s\n", dev->name, DeviceStr);
+-
+- /* Print configuration settings */
+- printk(" PrefPort:%c RlmtMode:%s\n",
+- 'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber,
+- (pAC->RlmtMode==0) ? "Check Link State" :
+- ((pAC->RlmtMode==1) ? "Check Link State" :
+- ((pAC->RlmtMode==3) ? "Check Local Port" :
+- ((pAC->RlmtMode==7) ? "Check Segmentation" :
+- ((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error")))));
+-
+- SkGeYellowLED(pAC, pAC->IoBase, 1);
+-
+- memcpy(&dev->dev_addr, &pAC->Addr.Net[0].CurrentMacAddress, 6);
+- memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+-
+- pNet->PortNr = 0;
+- pNet->NetNr = 0;
+-
+- boards_found++;
+-
+- pci_set_drvdata(pdev, dev);
+-
+- /* More then one port found */
+- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+- dev = alloc_etherdev(sizeof(DEV_NET));
+- if (!dev) {
+- printk(KERN_ERR "sk98lin: unable to allocate etherdev "
+- "structure!\n");
+- goto single_port;
+- }
+-
+- pNet = netdev_priv(dev);
+- pNet->PortNr = 1;
+- pNet->NetNr = 1;
+- pNet->pAC = pAC;
+-
+- dev->open = &SkGeOpen;
+- dev->stop = &SkGeClose;
+- dev->hard_start_xmit = &SkGeXmit;
+- dev->get_stats = &SkGeStats;
+- dev->set_multicast_list = &SkGeSetRxMode;
+- dev->set_mac_address = &SkGeSetMacAddr;
+- dev->do_ioctl = &SkGeIoctl;
+- dev->change_mtu = &SkGeChangeMtu;
+- SET_NETDEV_DEV(dev, &pdev->dev);
+- SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
+-
+- if (pAC->ChipsetType) {
+-#ifdef USE_SK_TX_CHECKSUM
+- dev->features |= NETIF_F_IP_CSUM;
+-#endif
+-#ifdef SK_ZEROCOPY
+- dev->features |= NETIF_F_SG;
+-#endif
+-#ifdef USE_SK_RX_CHECKSUM
+- pAC->RxPort[1].RxCsum = 1;
+-#endif
+- }
+-
+- if (using_dac)
+- dev->features |= NETIF_F_HIGHDMA;
+-
+- error = register_netdev(dev);
+- if (error) {
+- printk(KERN_ERR "sk98lin: Could not register device"
+- " for second port. (%d)\n", error);
+- free_netdev(dev);
+- goto single_port;
+- }
+-
+- pAC->dev[1] = dev;
+- memcpy(&dev->dev_addr,
+- &pAC->Addr.Net[1].CurrentMacAddress, 6);
+- memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+-
+- printk("%s: %s\n", dev->name, DeviceStr);
+- printk(" PrefPort:B RlmtMode:Dual Check Link State\n");
+- }
+-
+-single_port:
+-
+- /* Save the hardware revision */
+- pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) +
+- (pAC->GIni.GIPciHwRev & 0x0F);
+-
+- /* Set driver globals */
+- pAC->Pnmi.pDriverFileName = DRIVER_FILE_NAME;
+- pAC->Pnmi.pDriverReleaseDate = DRIVER_REL_DATE;
+-
+- memset(&pAC->PnmiBackup, 0, sizeof(SK_PNMI_STRUCT_DATA));
+- memcpy(&pAC->PnmiBackup, &pAC->PnmiStruct, sizeof(SK_PNMI_STRUCT_DATA));
+-
+- return 0;
+-
+- out_free_resources:
+- FreeResources(dev);
+- out_free_netdev:
+- free_netdev(dev);
+- out_disable_device:
+- pci_disable_device(pdev);
+- out:
+- return error;
+-}
+-
+-static void __devexit skge_remove_one(struct pci_dev *pdev)
+-{
+- struct net_device *dev = pci_get_drvdata(pdev);
+- DEV_NET *pNet = netdev_priv(dev);
+- SK_AC *pAC = pNet->pAC;
+- struct net_device *otherdev = pAC->dev[1];
+-
+- unregister_netdev(dev);
+-
+- SkGeYellowLED(pAC, pAC->IoBase, 0);
+-
+- if (pAC->BoardLevel == SK_INIT_RUN) {
+- SK_EVPARA EvPara;
+- unsigned long Flags;
+-
+- /* board is still alive */
+- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+- EvPara.Para32[0] = 0;
+- EvPara.Para32[1] = -1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+- EvPara.Para32[0] = 1;
+- EvPara.Para32[1] = -1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+- SkEventDispatcher(pAC, pAC->IoBase);
+- /* disable interrupts */
+- SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+- SkGeDeInit(pAC, pAC->IoBase);
+- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+- pAC->BoardLevel = SK_INIT_DATA;
+- /* We do NOT check here, if IRQ was pending, of course*/
+- }
+-
+- if (pAC->BoardLevel == SK_INIT_IO) {
+- /* board is still alive */
+- SkGeDeInit(pAC, pAC->IoBase);
+- pAC->BoardLevel = SK_INIT_DATA;
+- }
+-
+- FreeResources(dev);
+- free_netdev(dev);
+- if (otherdev != dev)
+- free_netdev(otherdev);
+- kfree(pAC);
+-}
+-
+-#ifdef CONFIG_PM
+-static int skge_suspend(struct pci_dev *pdev, pm_message_t state)
+-{
+- struct net_device *dev = pci_get_drvdata(pdev);
+- DEV_NET *pNet = netdev_priv(dev);
+- SK_AC *pAC = pNet->pAC;
+- struct net_device *otherdev = pAC->dev[1];
+-
+- if (netif_running(dev)) {
+- netif_carrier_off(dev);
+- DoPrintInterfaceChange = SK_FALSE;
+- SkDrvDeInitAdapter(pAC, 0); /* performs SkGeClose */
+- netif_device_detach(dev);
+- }
+- if (otherdev != dev) {
+- if (netif_running(otherdev)) {
+- netif_carrier_off(otherdev);
+- DoPrintInterfaceChange = SK_FALSE;
+- SkDrvDeInitAdapter(pAC, 1); /* performs SkGeClose */
+- netif_device_detach(otherdev);
+- }
+- }
+-
+- pci_save_state(pdev);
+- pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
+- if (pAC->AllocFlag & SK_ALLOC_IRQ) {
+- free_irq(dev->irq, dev);
+- }
+- pci_disable_device(pdev);
+- pci_set_power_state(pdev, pci_choose_state(pdev, state));
+-
+- return 0;
+-}
+-
+-static int skge_resume(struct pci_dev *pdev)
+-{
+- struct net_device *dev = pci_get_drvdata(pdev);
+- DEV_NET *pNet = netdev_priv(dev);
+- SK_AC *pAC = pNet->pAC;
+- struct net_device *otherdev = pAC->dev[1];
+- int ret;
+-
+- pci_set_power_state(pdev, PCI_D0);
+- pci_restore_state(pdev);
+- ret = pci_enable_device(pdev);
+- if (ret) {
+- printk(KERN_WARNING "sk98lin: unable to enable device %s "
+- "in resume\n", dev->name);
+- goto err_out;
+- }
+- pci_set_master(pdev);
+- if (pAC->GIni.GIMacsFound == 2)
+- ret = request_irq(dev->irq, SkGeIsr, IRQF_SHARED, "sk98lin", dev);
+- else
+- ret = request_irq(dev->irq, SkGeIsrOnePort, IRQF_SHARED, "sk98lin", dev);
+- if (ret) {
+- printk(KERN_WARNING "sk98lin: unable to acquire IRQ %d\n", dev->irq);
+- ret = -EBUSY;
+- goto err_out_disable_pdev;
+- }
+-
+- netif_device_attach(dev);
+- if (netif_running(dev)) {
+- DoPrintInterfaceChange = SK_FALSE;
+- SkDrvInitAdapter(pAC, 0); /* first device */
+- }
+- if (otherdev != dev) {
+- netif_device_attach(otherdev);
+- if (netif_running(otherdev)) {
+- DoPrintInterfaceChange = SK_FALSE;
+- SkDrvInitAdapter(pAC, 1); /* second device */
+- }
+- }
+-
+- return 0;
+-
+-err_out_disable_pdev:
+- pci_disable_device(pdev);
+-err_out:
+- pAC->AllocFlag &= ~SK_ALLOC_IRQ;
+- dev->irq = 0;
+- return ret;
+-}
+-#else
+-#define skge_suspend NULL
+-#define skge_resume NULL
+-#endif
+-
+-static struct pci_device_id skge_pci_tbl[] = {
+-#ifdef SK98LIN_ALL_DEVICES
+- { PCI_VENDOR_ID_3COM, 0x1700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+- { PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+-#endif
+-#ifdef GENESIS
+- /* Generic SysKonnect SK-98xx Gigabit Ethernet Server Adapter */
+- { PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+-#endif
+- /* Generic SysKonnect SK-98xx V2.0 Gigabit Ethernet Adapter */
+- { PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+-#ifdef SK98LIN_ALL_DEVICES
+-/* DLink card does not have valid VPD so this driver gags
+- * { PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+- */
+- { PCI_VENDOR_ID_MARVELL, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+- { PCI_VENDOR_ID_MARVELL, 0x5005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+- { PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+- { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, },
+- { PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+-#endif
+- { 0 }
+-};
+-
+-MODULE_DEVICE_TABLE(pci, skge_pci_tbl);
+-
+-static struct pci_driver skge_driver = {
+- .name = "sk98lin",
+- .id_table = skge_pci_tbl,
+- .probe = skge_probe_one,
+- .remove = __devexit_p(skge_remove_one),
+- .suspend = skge_suspend,
+- .resume = skge_resume,
+-};
+-
+-static int __init skge_init(void)
+-{
+- printk(KERN_NOTICE "sk98lin: driver has been replaced by the skge driver"
+- " and is scheduled for removal\n");
+-
+- return pci_register_driver(&skge_driver);
+-}
+-
+-static void __exit skge_exit(void)
+-{
+- pci_unregister_driver(&skge_driver);
+-}
+-
+-module_init(skge_init);
+-module_exit(skge_exit);
+diff --git a/drivers/net/sk98lin/skgehwt.c b/drivers/net/sk98lin/skgehwt.c
+deleted file mode 100644
+index db67099..0000000
+--- a/drivers/net/sk98lin/skgehwt.c
++++ /dev/null
+@@ -1,171 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skgehwt.c
+- * Project: Gigabit Ethernet Adapters, Event Scheduler Module
+- * Version: $Revision: 1.15 $
+- * Date: $Date: 2003/09/16 13:41:23 $
+- * Purpose: Hardware Timer
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- * Event queue and dispatcher
+- */
+-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+-static const char SysKonnectFileId[] =
+- "@(#) $Id: skgehwt.c,v 1.15 2003/09/16 13:41:23 rschmidt Exp $ (C) Marvell.";
+-#endif
+-
+-#include "h/skdrv1st.h" /* Driver Specific Definitions */
+-#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
+-
+-#ifdef __C2MAN__
+-/*
+- * Hardware Timer function queue management.
+- */
+-intro()
+-{}
+-#endif
+-
+-/*
+- * Prototypes of local functions.
+- */
+-#define SK_HWT_MAX (65000)
+-
+-/* correction factor */
+-#define SK_HWT_FAC (1000 * (SK_U32)pAC->GIni.GIHstClkFact / 100)
+-
+-/*
+- * Initialize hardware timer.
+- *
+- * Must be called during init level 1.
+- */
+-void SkHwtInit(
+-SK_AC *pAC, /* Adapters context */
+-SK_IOC Ioc) /* IoContext */
+-{
+- pAC->Hwt.TStart = 0 ;
+- pAC->Hwt.TStop = 0 ;
+- pAC->Hwt.TActive = SK_FALSE;
+-
+- SkHwtStop(pAC, Ioc);
+-}
+-
+-/*
+- *
+- * Start hardware timer (clock ticks are 16us).
+- *
+- */
+-void SkHwtStart(
+-SK_AC *pAC, /* Adapters context */
+-SK_IOC Ioc, /* IoContext */
+-SK_U32 Time) /* Time in units of 16us to load the timer with. */
+-{
+- SK_U32 Cnt;
+-
+- if (Time > SK_HWT_MAX)
+- Time = SK_HWT_MAX;
+-
+- pAC->Hwt.TStart = Time;
+- pAC->Hwt.TStop = 0L;
+-
+- Cnt = Time;
+-
+- /*
+- * if time < 16 us
+- * time = 16 us
+- */
+- if (!Cnt) {
+- Cnt++;
+- }
+-
+- SK_OUT32(Ioc, B2_TI_INI, Cnt * SK_HWT_FAC);
+-
+- SK_OUT16(Ioc, B2_TI_CTRL, TIM_START); /* Start timer. */
+-
+- pAC->Hwt.TActive = SK_TRUE;
+-}
+-
+-/*
+- * Stop hardware timer.
+- * and clear the timer IRQ
+- */
+-void SkHwtStop(
+-SK_AC *pAC, /* Adapters context */
+-SK_IOC Ioc) /* IoContext */
+-{
+- SK_OUT16(Ioc, B2_TI_CTRL, TIM_STOP);
+-
+- SK_OUT16(Ioc, B2_TI_CTRL, TIM_CLR_IRQ);
+-
+- pAC->Hwt.TActive = SK_FALSE;
+-}
+-
+-
+-/*
+- * Stop hardware timer and read time elapsed since last start.
+- *
+- * returns
+- * The elapsed time since last start in units of 16us.
+- *
+- */
+-SK_U32 SkHwtRead(
+-SK_AC *pAC, /* Adapters context */
+-SK_IOC Ioc) /* IoContext */
+-{
+- SK_U32 TRead;
+- SK_U32 IStatus;
+-
+- if (pAC->Hwt.TActive) {
+-
+- SkHwtStop(pAC, Ioc);
+-
+- SK_IN32(Ioc, B2_TI_VAL, &TRead);
+- TRead /= SK_HWT_FAC;
+-
+- SK_IN32(Ioc, B0_ISRC, &IStatus);
+-
+- /* Check if timer expired (or wraped around) */
+- if ((TRead > pAC->Hwt.TStart) || (IStatus & IS_TIMINT)) {
+-
+- SkHwtStop(pAC, Ioc);
+-
+- pAC->Hwt.TStop = pAC->Hwt.TStart;
+- }
+- else {
+-
+- pAC->Hwt.TStop = pAC->Hwt.TStart - TRead;
+- }
+- }
+- return(pAC->Hwt.TStop);
+-}
+-
+-/*
+- * interrupt source= timer
+- */
+-void SkHwtIsr(
+-SK_AC *pAC, /* Adapters context */
+-SK_IOC Ioc) /* IoContext */
+-{
+- SkHwtStop(pAC, Ioc);
+-
+- pAC->Hwt.TStop = pAC->Hwt.TStart;
+-
+- SkTimerDone(pAC, Ioc);
+-}
+-
+-/* End of file */
+diff --git a/drivers/net/sk98lin/skgeinit.c b/drivers/net/sk98lin/skgeinit.c
+deleted file mode 100644
+index 67f1d6a..0000000
+--- a/drivers/net/sk98lin/skgeinit.c
++++ /dev/null
+@@ -1,2005 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skgeinit.c
+- * Project: Gigabit Ethernet Adapters, Common Modules
+- * Version: $Revision: 1.97 $
+- * Date: $Date: 2003/10/02 16:45:31 $
+- * Purpose: Contains functions to initialize the adapter
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#include "h/skdrv1st.h"
+-#include "h/skdrv2nd.h"
+-
+-/* global variables ***********************************************************/
+-
+-/* local variables ************************************************************/
+-
+-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+-static const char SysKonnectFileId[] =
+- "@(#) $Id: skgeinit.c,v 1.97 2003/10/02 16:45:31 rschmidt Exp $ (C) Marvell.";
+-#endif
+-
+-struct s_QOffTab {
+- int RxQOff; /* Receive Queue Address Offset */
+- int XsQOff; /* Sync Tx Queue Address Offset */
+- int XaQOff; /* Async Tx Queue Address Offset */
+-};
+-static struct s_QOffTab QOffTab[] = {
+- {Q_R1, Q_XS1, Q_XA1}, {Q_R2, Q_XS2, Q_XA2}
+-};
+-
+-struct s_Config {
+- char ScanString[8];
+- SK_U32 Value;
+-};
+-
+-static struct s_Config OemConfig = {
+- {'O','E','M','_','C','o','n','f'},
+-#ifdef SK_OEM_CONFIG
+- OEM_CONFIG_VALUE,
+-#else
+- 0,
+-#endif
+-};
+-
+-/******************************************************************************
+- *
+- * SkGePollTxD() - Enable / Disable Descriptor Polling of TxD Rings
+- *
+- * Description:
+- * Enable or disable the descriptor polling of the transmit descriptor
+- * ring(s) (TxD) for port 'Port'.
+- * The new configuration is *not* saved over any SkGeStopPort() and
+- * SkGeInitPort() calls.
+- *
+- * Returns:
+- * nothing
+- */
+-void SkGePollTxD(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port, /* Port Index (MAC_1 + n) */
+-SK_BOOL PollTxD) /* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */
+-{
+- SK_GEPORT *pPrt;
+- SK_U32 DWord;
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- DWord = (SK_U32)(PollTxD ? CSR_ENA_POL : CSR_DIS_POL);
+-
+- if (pPrt->PXSQSize != 0) {
+- SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), DWord);
+- }
+-
+- if (pPrt->PXAQSize != 0) {
+- SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), DWord);
+- }
+-} /* SkGePollTxD */
+-
+-
+-/******************************************************************************
+- *
+- * SkGeYellowLED() - Switch the yellow LED on or off.
+- *
+- * Description:
+- * Switch the yellow LED on or off.
+- *
+- * Note:
+- * This function may be called any time after SkGeInit(Level 1).
+- *
+- * Returns:
+- * nothing
+- */
+-void SkGeYellowLED(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int State) /* yellow LED state, 0 = OFF, 0 != ON */
+-{
+- if (State == 0) {
+- /* Switch yellow LED OFF */
+- SK_OUT8(IoC, B0_LED, LED_STAT_OFF);
+- }
+- else {
+- /* Switch yellow LED ON */
+- SK_OUT8(IoC, B0_LED, LED_STAT_ON);
+- }
+-} /* SkGeYellowLED */
+-
+-
+-#if (!defined(SK_SLIM) || defined(GENESIS))
+-/******************************************************************************
+- *
+- * SkGeXmitLED() - Modify the Operational Mode of a transmission LED.
+- *
+- * Description:
+- * The Rx or Tx LED which is specified by 'Led' will be
+- * enabled, disabled or switched on in test mode.
+- *
+- * Note:
+- * 'Led' must contain the address offset of the LEDs INI register.
+- *
+- * Usage:
+- * SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA);
+- *
+- * Returns:
+- * nothing
+- */
+-void SkGeXmitLED(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Led, /* offset to the LED Init Value register */
+-int Mode) /* Mode may be SK_LED_DIS, SK_LED_ENA, SK_LED_TST */
+-{
+- SK_U32 LedIni;
+-
+- switch (Mode) {
+- case SK_LED_ENA:
+- LedIni = SK_XMIT_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100;
+- SK_OUT32(IoC, Led + XMIT_LED_INI, LedIni);
+- SK_OUT8(IoC, Led + XMIT_LED_CTRL, LED_START);
+- break;
+- case SK_LED_TST:
+- SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_ON);
+- SK_OUT32(IoC, Led + XMIT_LED_CNT, 100);
+- SK_OUT8(IoC, Led + XMIT_LED_CTRL, LED_START);
+- break;
+- case SK_LED_DIS:
+- default:
+- /*
+- * Do NOT stop the LED Timer here. The LED might be
+- * in on state. But it needs to go off.
+- */
+- SK_OUT32(IoC, Led + XMIT_LED_CNT, 0);
+- SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_OFF);
+- break;
+- }
+-
+- /*
+- * 1000BT: The Transmit LED is driven by the PHY.
+- * But the default LED configuration is used for
+- * Level One and Broadcom PHYs.
+- * (Broadcom: It may be that PHY_B_PEC_EN_LTR has to be set.)
+- * (In this case it has to be added here. But we will see. XXX)
+- */
+-} /* SkGeXmitLED */
+-#endif /* !SK_SLIM || GENESIS */
+-
+-
+-/******************************************************************************
+- *
+- * DoCalcAddr() - Calculates the start and the end address of a queue.
+- *
+- * Description:
+- * This function calculates the start and the end address of a queue.
+- * Afterwards the 'StartVal' is incremented to the next start position.
+- * If the port is already initialized the calculated values
+- * will be checked against the configured values and an
+- * error will be returned, if they are not equal.
+- * If the port is not initialized the values will be written to
+- * *StartAdr and *EndAddr.
+- *
+- * Returns:
+- * 0: success
+- * 1: configuration error
+- */
+-static int DoCalcAddr(
+-SK_AC *pAC, /* adapter context */
+-SK_GEPORT SK_FAR *pPrt, /* port index */
+-int QuSize, /* size of the queue to configure in kB */
+-SK_U32 SK_FAR *StartVal, /* start value for address calculation */
+-SK_U32 SK_FAR *QuStartAddr,/* start addr to calculate */
+-SK_U32 SK_FAR *QuEndAddr) /* end address to calculate */
+-{
+- SK_U32 EndVal;
+- SK_U32 NextStart;
+- int Rtv;
+-
+- Rtv = 0;
+- if (QuSize == 0) {
+- EndVal = *StartVal;
+- NextStart = EndVal;
+- }
+- else {
+- EndVal = *StartVal + ((SK_U32)QuSize * 1024) - 1;
+- NextStart = EndVal + 1;
+- }
+-
+- if (pPrt->PState >= SK_PRT_INIT) {
+- if (*StartVal != *QuStartAddr || EndVal != *QuEndAddr) {
+- Rtv = 1;
+- }
+- }
+- else {
+- *QuStartAddr = *StartVal;
+- *QuEndAddr = EndVal;
+- }
+-
+- *StartVal = NextStart;
+- return(Rtv);
+-} /* DoCalcAddr */
+-
+-/******************************************************************************
+- *
+- * SkGeInitAssignRamToQueues() - allocate default queue sizes
+- *
+- * Description:
+- * This function assigns the memory to the different queues and ports.
+- * When DualNet is set to SK_TRUE all ports get the same amount of memory.
+- * Otherwise the first port gets most of the memory and all the
+- * other ports just the required minimum.
+- * This function can only be called when pAC->GIni.GIRamSize and
+- * pAC->GIni.GIMacsFound have been initialized, usually this happens
+- * at init level 1
+- *
+- * Returns:
+- * 0 - ok
+- * 1 - invalid input values
+- * 2 - not enough memory
+- */
+-
+-int SkGeInitAssignRamToQueues(
+-SK_AC *pAC, /* Adapter context */
+-int ActivePort, /* Active Port in RLMT mode */
+-SK_BOOL DualNet) /* adapter context */
+-{
+- int i;
+- int UsedKilobytes; /* memory already assigned */
+- int ActivePortKilobytes; /* memory available for active port */
+- SK_GEPORT *pGePort;
+-
+- UsedKilobytes = 0;
+-
+- if (ActivePort >= pAC->GIni.GIMacsFound) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+- ("SkGeInitAssignRamToQueues: ActivePort (%d) invalid\n",
+- ActivePort));
+- return(1);
+- }
+- if (((pAC->GIni.GIMacsFound * (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE)) +
+- ((RAM_QUOTA_SYNC == 0) ? 0 : SK_MIN_TXQ_SIZE)) > pAC->GIni.GIRamSize) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+- ("SkGeInitAssignRamToQueues: Not enough memory (%d)\n",
+- pAC->GIni.GIRamSize));
+- return(2);
+- }
+-
+- if (DualNet) {
+- /* every port gets the same amount of memory */
+- ActivePortKilobytes = pAC->GIni.GIRamSize / pAC->GIni.GIMacsFound;
+- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+-
+- pGePort = &pAC->GIni.GP[i];
+-
+- /* take away the minimum memory for active queues */
+- ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE);
+-
+- /* receive queue gets the minimum + 80% of the rest */
+- pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB((
+- ActivePortKilobytes * (unsigned long) RAM_QUOTA_RX) / 100))
+- + SK_MIN_RXQ_SIZE;
+-
+- ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE);
+-
+- /* synchronous transmit queue */
+- pGePort->PXSQSize = 0;
+-
+- /* asynchronous transmit queue */
+- pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes +
+- SK_MIN_TXQ_SIZE);
+- }
+- }
+- else {
+- /* Rlmt Mode or single link adapter */
+-
+- /* Set standby queue size defaults for all standby ports */
+- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+-
+- if (i != ActivePort) {
+- pGePort = &pAC->GIni.GP[i];
+-
+- pGePort->PRxQSize = SK_MIN_RXQ_SIZE;
+- pGePort->PXAQSize = SK_MIN_TXQ_SIZE;
+- pGePort->PXSQSize = 0;
+-
+- /* Count used RAM */
+- UsedKilobytes += pGePort->PRxQSize + pGePort->PXAQSize;
+- }
+- }
+- /* what's left? */
+- ActivePortKilobytes = pAC->GIni.GIRamSize - UsedKilobytes;
+-
+- /* assign it to the active port */
+- /* first take away the minimum memory */
+- ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE);
+- pGePort = &pAC->GIni.GP[ActivePort];
+-
+- /* receive queue get's the minimum + 80% of the rest */
+- pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB((ActivePortKilobytes *
+- (unsigned long) RAM_QUOTA_RX) / 100)) + SK_MIN_RXQ_SIZE;
+-
+- ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE);
+-
+- /* synchronous transmit queue */
+- pGePort->PXSQSize = 0;
+-
+- /* asynchronous transmit queue */
+- pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes) +
+- SK_MIN_TXQ_SIZE;
+- }
+-#ifdef VCPU
+- VCPUprintf(0, "PRxQSize=%u, PXSQSize=%u, PXAQSize=%u\n",
+- pGePort->PRxQSize, pGePort->PXSQSize, pGePort->PXAQSize);
+-#endif /* VCPU */
+-
+- return(0);
+-} /* SkGeInitAssignRamToQueues */
+-
+-/******************************************************************************
+- *
+- * SkGeCheckQSize() - Checks the Adapters Queue Size Configuration
+- *
+- * Description:
+- * This function verifies the Queue Size Configuration specified
+- * in the variables PRxQSize, PXSQSize, and PXAQSize of all
+- * used ports.
+- * This requirements must be fullfilled to have a valid configuration:
+- * - The size of all queues must not exceed GIRamSize.
+- * - The queue sizes must be specified in units of 8 kB.
+- * - The size of Rx queues of available ports must not be
+- * smaller than 16 kB.
+- * - The size of at least one Tx queue (synch. or asynch.)
+- * of available ports must not be smaller than 16 kB
+- * when Jumbo Frames are used.
+- * - The RAM start and end addresses must not be changed
+- * for ports which are already initialized.
+- * Furthermore SkGeCheckQSize() defines the Start and End Addresses
+- * of all ports and stores them into the HWAC port structure.
+- *
+- * Returns:
+- * 0: Queue Size Configuration valid
+- * 1: Queue Size Configuration invalid
+- */
+-static int SkGeCheckQSize(
+-SK_AC *pAC, /* adapter context */
+-int Port) /* port index */
+-{
+- SK_GEPORT *pPrt;
+- int i;
+- int Rtv;
+- int Rtv2;
+- SK_U32 StartAddr;
+-#ifndef SK_SLIM
+- int UsedMem; /* total memory used (max. found ports) */
+-#endif
+-
+- Rtv = 0;
+-
+-#ifndef SK_SLIM
+-
+- UsedMem = 0;
+- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+- pPrt = &pAC->GIni.GP[i];
+-
+- if ((pPrt->PRxQSize & QZ_UNITS) != 0 ||
+- (pPrt->PXSQSize & QZ_UNITS) != 0 ||
+- (pPrt->PXAQSize & QZ_UNITS) != 0) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG);
+- return(1);
+- }
+-
+- if (i == Port && pPrt->PRxQSize < SK_MIN_RXQ_SIZE) {
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E011, SKERR_HWI_E011MSG);
+- return(1);
+- }
+-
+- /*
+- * the size of at least one Tx queue (synch. or asynch.) has to be > 0.
+- * if Jumbo Frames are used, this size has to be >= 16 kB.
+- */
+- if ((i == Port && pPrt->PXSQSize == 0 && pPrt->PXAQSize == 0) ||
+- (pAC->GIni.GIPortUsage == SK_JUMBO_LINK &&
+- ((pPrt->PXSQSize > 0 && pPrt->PXSQSize < SK_MIN_TXQ_SIZE) ||
+- (pPrt->PXAQSize > 0 && pPrt->PXAQSize < SK_MIN_TXQ_SIZE)))) {
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E023, SKERR_HWI_E023MSG);
+- return(1);
+- }
+-
+- UsedMem += pPrt->PRxQSize + pPrt->PXSQSize + pPrt->PXAQSize;
+- }
+-
+- if (UsedMem > pAC->GIni.GIRamSize) {
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG);
+- return(1);
+- }
+-#endif /* !SK_SLIM */
+-
+- /* Now start address calculation */
+- StartAddr = pAC->GIni.GIRamOffs;
+- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+- pPrt = &pAC->GIni.GP[i];
+-
+- /* Calculate/Check values for the receive queue */
+- Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PRxQSize, &StartAddr,
+- &pPrt->PRxQRamStart, &pPrt->PRxQRamEnd);
+- Rtv |= Rtv2;
+-
+- /* Calculate/Check values for the synchronous Tx queue */
+- Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PXSQSize, &StartAddr,
+- &pPrt->PXsQRamStart, &pPrt->PXsQRamEnd);
+- Rtv |= Rtv2;
+-
+- /* Calculate/Check values for the asynchronous Tx queue */
+- Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PXAQSize, &StartAddr,
+- &pPrt->PXaQRamStart, &pPrt->PXaQRamEnd);
+- Rtv |= Rtv2;
+-
+- if (Rtv) {
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E013, SKERR_HWI_E013MSG);
+- return(1);
+- }
+- }
+-
+- return(0);
+-} /* SkGeCheckQSize */
+-
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- * SkGeInitMacArb() - Initialize the MAC Arbiter
+- *
+- * Description:
+- * This function initializes the MAC Arbiter.
+- * It must not be called if there is still an
+- * initialized or active port.
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkGeInitMacArb(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC) /* IO context */
+-{
+- /* release local reset */
+- SK_OUT16(IoC, B3_MA_TO_CTRL, MA_RST_CLR);
+-
+- /* configure timeout values */
+- SK_OUT8(IoC, B3_MA_TOINI_RX1, SK_MAC_TO_53);
+- SK_OUT8(IoC, B3_MA_TOINI_RX2, SK_MAC_TO_53);
+- SK_OUT8(IoC, B3_MA_TOINI_TX1, SK_MAC_TO_53);
+- SK_OUT8(IoC, B3_MA_TOINI_TX2, SK_MAC_TO_53);
+-
+- SK_OUT8(IoC, B3_MA_RCINI_RX1, 0);
+- SK_OUT8(IoC, B3_MA_RCINI_RX2, 0);
+- SK_OUT8(IoC, B3_MA_RCINI_TX1, 0);
+- SK_OUT8(IoC, B3_MA_RCINI_TX2, 0);
+-
+- /* recovery values are needed for XMAC II Rev. B2 only */
+- /* Fast Output Enable Mode was intended to use with Rev. B2, but now? */
+-
+- /*
+- * There is no start or enable button to push, therefore
+- * the MAC arbiter is configured and enabled now.
+- */
+-} /* SkGeInitMacArb */
+-
+-
+-/******************************************************************************
+- *
+- * SkGeInitPktArb() - Initialize the Packet Arbiter
+- *
+- * Description:
+- * This function initializes the Packet Arbiter.
+- * It must not be called if there is still an
+- * initialized or active port.
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkGeInitPktArb(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC) /* IO context */
+-{
+- /* release local reset */
+- SK_OUT16(IoC, B3_PA_CTRL, PA_RST_CLR);
+-
+- /* configure timeout values */
+- SK_OUT16(IoC, B3_PA_TOINI_RX1, SK_PKT_TO_MAX);
+- SK_OUT16(IoC, B3_PA_TOINI_RX2, SK_PKT_TO_MAX);
+- SK_OUT16(IoC, B3_PA_TOINI_TX1, SK_PKT_TO_MAX);
+- SK_OUT16(IoC, B3_PA_TOINI_TX2, SK_PKT_TO_MAX);
+-
+- /*
+- * enable timeout timers if jumbo frames not used
+- * NOTE: the packet arbiter timeout interrupt is needed for
+- * half duplex hangup workaround
+- */
+- if (pAC->GIni.GIPortUsage != SK_JUMBO_LINK) {
+- if (pAC->GIni.GIMacsFound == 1) {
+- SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1);
+- }
+- else {
+- SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1 | PA_ENA_TO_TX2);
+- }
+- }
+-} /* SkGeInitPktArb */
+-#endif /* GENESIS */
+-
+-
+-/******************************************************************************
+- *
+- * SkGeInitMacFifo() - Initialize the MAC FIFOs
+- *
+- * Description:
+- * Initialize all MAC FIFOs of the specified port
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkGeInitMacFifo(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_U16 Word;
+-#ifdef VCPU
+- SK_U32 DWord;
+-#endif /* VCPU */
+- /*
+- * For each FIFO:
+- * - release local reset
+- * - use default value for MAC FIFO size
+- * - setup defaults for the control register
+- * - enable the FIFO
+- */
+-
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+- /* Configure Rx MAC FIFO */
+- SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_CLR);
+- SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_RX_CTRL_DEF);
+- SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_ENA_OP_MD);
+-
+- /* Configure Tx MAC FIFO */
+- SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_CLR);
+- SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF);
+- SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_ENA_OP_MD);
+-
+- /* Enable frame flushing if jumbo frames used */
+- if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
+- SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_FLUSH);
+- }
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIYukon) {
+- /* set Rx GMAC FIFO Flush Mask */
+- SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), (SK_U16)RX_FF_FL_DEF_MSK);
+-
+- Word = (SK_U16)GMF_RX_CTRL_DEF;
+-
+- /* disable Rx GMAC FIFO Flush for YUKON-Lite Rev. A0 only */
+- if (pAC->GIni.GIYukonLite && pAC->GIni.GIChipId == CHIP_ID_YUKON) {
+-
+- Word &= ~GMF_RX_F_FL_ON;
+- }
+-
+- /* Configure Rx MAC FIFO */
+- SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR);
+- SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), Word);
+-
+- /* set Rx GMAC FIFO Flush Threshold (default: 0x0a -> 56 bytes) */
+- SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF);
+-
+- /* Configure Tx MAC FIFO */
+- SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR);
+- SK_OUT16(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U16)GMF_TX_CTRL_DEF);
+-
+-#ifdef VCPU
+- SK_IN32(IoC, MR_ADDR(Port, RX_GMF_AF_THR), &DWord);
+- SK_IN32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), &DWord);
+-#endif /* VCPU */
+-
+- /* set Tx GMAC FIFO Almost Empty Threshold */
+-/* SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), 0); */
+- }
+-#endif /* YUKON */
+-
+-} /* SkGeInitMacFifo */
+-
+-#ifdef SK_LNK_SYNC_CNT
+-/******************************************************************************
+- *
+- * SkGeLoadLnkSyncCnt() - Load the Link Sync Counter and starts counting
+- *
+- * Description:
+- * This function starts the Link Sync Counter of the specified
+- * port and enables the generation of an Link Sync IRQ.
+- * The Link Sync Counter may be used to detect an active link,
+- * if autonegotiation is not used.
+- *
+- * Note:
+- * o To ensure receiving the Link Sync Event the LinkSyncCounter
+- * should be initialized BEFORE clearing the XMAC's reset!
+- * o Enable IS_LNK_SYNC_M1 and IS_LNK_SYNC_M2 after calling this
+- * function.
+- *
+- * Returns:
+- * nothing
+- */
+-void SkGeLoadLnkSyncCnt(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port, /* Port Index (MAC_1 + n) */
+-SK_U32 CntVal) /* Counter value */
+-{
+- SK_U32 OrgIMsk;
+- SK_U32 NewIMsk;
+- SK_U32 ISrc;
+- SK_BOOL IrqPend;
+-
+- /* stop counter */
+- SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_STOP);
+-
+- /*
+- * ASIC problem:
+- * Each time starting the Link Sync Counter an IRQ is generated
+- * by the adapter. See problem report entry from 21.07.98
+- *
+- * Workaround: Disable Link Sync IRQ and clear the unexpeced IRQ
+- * if no IRQ is already pending.
+- */
+- IrqPend = SK_FALSE;
+- SK_IN32(IoC, B0_ISRC, &ISrc);
+- SK_IN32(IoC, B0_IMSK, &OrgIMsk);
+- if (Port == MAC_1) {
+- NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M1;
+- if ((ISrc & IS_LNK_SYNC_M1) != 0) {
+- IrqPend = SK_TRUE;
+- }
+- }
+- else {
+- NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M2;
+- if ((ISrc & IS_LNK_SYNC_M2) != 0) {
+- IrqPend = SK_TRUE;
+- }
+- }
+- if (!IrqPend) {
+- SK_OUT32(IoC, B0_IMSK, NewIMsk);
+- }
+-
+- /* load counter */
+- SK_OUT32(IoC, MR_ADDR(Port, LNK_SYNC_INI), CntVal);
+-
+- /* start counter */
+- SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_START);
+-
+- if (!IrqPend) {
+- /* clear the unexpected IRQ, and restore the interrupt mask */
+- SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_CLR_IRQ);
+- SK_OUT32(IoC, B0_IMSK, OrgIMsk);
+- }
+-} /* SkGeLoadLnkSyncCnt*/
+-#endif /* SK_LNK_SYNC_CNT */
+-
+-#if defined(SK_DIAG) || defined(SK_CFG_SYNC)
+-/******************************************************************************
+- *
+- * SkGeCfgSync() - Configure synchronous bandwidth for this port.
+- *
+- * Description:
+- * This function may be used to configure synchronous bandwidth
+- * to the specified port. This may be done any time after
+- * initializing the port. The configuration values are NOT saved
+- * in the HWAC port structure and will be overwritten any
+- * time when stopping and starting the port.
+- * Any values for the synchronous configuration will be ignored
+- * if the size of the synchronous queue is zero!
+- *
+- * The default configuration for the synchronous service is
+- * TXA_ENA_FSYNC. This means if the size of
+- * the synchronous queue is unequal zero but no specific
+- * synchronous bandwidth is configured, the synchronous queue
+- * will always have the 'unlimited' transmit priority!
+- *
+- * This mode will be restored if the synchronous bandwidth is
+- * deallocated ('IntTime' = 0 and 'LimCount' = 0).
+- *
+- * Returns:
+- * 0: success
+- * 1: parameter configuration error
+- * 2: try to configure quality of service although no
+- * synchronous queue is configured
+- */
+-int SkGeCfgSync(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port, /* Port Index (MAC_1 + n) */
+-SK_U32 IntTime, /* Interval Timer Value in units of 8ns */
+-SK_U32 LimCount, /* Number of bytes to transfer during IntTime */
+-int SyncMode) /* Sync Mode: TXA_ENA_ALLOC | TXA_DIS_ALLOC | 0 */
+-{
+- int Rtv;
+-
+- Rtv = 0;
+-
+- /* check the parameters */
+- if (LimCount > IntTime ||
+- (LimCount == 0 && IntTime != 0) ||
+- (LimCount != 0 && IntTime == 0)) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG);
+- return(1);
+- }
+-
+- if (pAC->GIni.GP[Port].PXSQSize == 0) {
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E009, SKERR_HWI_E009MSG);
+- return(2);
+- }
+-
+- /* calculate register values */
+- IntTime = (IntTime / 2) * pAC->GIni.GIHstClkFact / 100;
+- LimCount = LimCount / 8;
+-
+- if (IntTime > TXA_MAX_VAL || LimCount > TXA_MAX_VAL) {
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG);
+- return(1);
+- }
+-
+- /*
+- * - Enable 'Force Sync' to ensure the synchronous queue
+- * has the priority while configuring the new values.
+- * - Also 'disable alloc' to ensure the settings complies
+- * to the SyncMode parameter.
+- * - Disable 'Rate Control' to configure the new values.
+- * - write IntTime and LimCount
+- * - start 'Rate Control' and disable 'Force Sync'
+- * if Interval Timer or Limit Counter not zero.
+- */
+- SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
+- TXA_ENA_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
+-
+- SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), IntTime);
+- SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), LimCount);
+-
+- SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
+- (SK_U8)(SyncMode & (TXA_ENA_ALLOC | TXA_DIS_ALLOC)));
+-
+- if (IntTime != 0 || LimCount != 0) {
+- SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_DIS_FSYNC | TXA_START_RC);
+- }
+-
+- return(0);
+-} /* SkGeCfgSync */
+-#endif /* SK_DIAG || SK_CFG_SYNC*/
+-
+-
+-/******************************************************************************
+- *
+- * DoInitRamQueue() - Initialize the RAM Buffer Address of a single Queue
+- *
+- * Desccription:
+- * If the queue is used, enable and initialize it.
+- * Make sure the queue is still reset, if it is not used.
+- *
+- * Returns:
+- * nothing
+- */
+-static void DoInitRamQueue(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int QuIoOffs, /* Queue IO Address Offset */
+-SK_U32 QuStartAddr, /* Queue Start Address */
+-SK_U32 QuEndAddr, /* Queue End Address */
+-int QuType) /* Queue Type (SK_RX_SRAM_Q|SK_RX_BRAM_Q|SK_TX_RAM_Q) */
+-{
+- SK_U32 RxUpThresVal;
+- SK_U32 RxLoThresVal;
+-
+- if (QuStartAddr != QuEndAddr) {
+- /* calculate thresholds, assume we have a big Rx queue */
+- RxUpThresVal = (QuEndAddr + 1 - QuStartAddr - SK_RB_ULPP) / 8;
+- RxLoThresVal = (QuEndAddr + 1 - QuStartAddr - SK_RB_LLPP_B)/8;
+-
+- /* build HW address format */
+- QuStartAddr = QuStartAddr / 8;
+- QuEndAddr = QuEndAddr / 8;
+-
+- /* release local reset */
+- SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_RST_CLR);
+-
+- /* configure addresses */
+- SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_START), QuStartAddr);
+- SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_END), QuEndAddr);
+- SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_WP), QuStartAddr);
+- SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RP), QuStartAddr);
+-
+- switch (QuType) {
+- case SK_RX_SRAM_Q:
+- /* configure threshold for small Rx Queue */
+- RxLoThresVal += (SK_RB_LLPP_B - SK_RB_LLPP_S) / 8;
+-
+- /* continue with SK_RX_BRAM_Q */
+- case SK_RX_BRAM_Q:
+- /* write threshold for Rx Queue */
+-
+- SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_UTPP), RxUpThresVal);
+- SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_LTPP), RxLoThresVal);
+-
+- /* the high priority threshold not used */
+- break;
+- case SK_TX_RAM_Q:
+- /*
+- * Do NOT use Store & Forward under normal operation due to
+- * performance optimization (GENESIS only).
+- * But if Jumbo Frames are configured (XMAC Tx FIFO is only 4 kB)
+- * or YUKON is used ((GMAC Tx FIFO is only 1 kB)
+- * we NEED Store & Forward of the RAM buffer.
+- */
+- if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK ||
+- pAC->GIni.GIYukon) {
+- /* enable Store & Forward Mode for the Tx Side */
+- SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_STFWD);
+- }
+- break;
+- }
+-
+- /* set queue operational */
+- SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_OP_MD);
+- }
+- else {
+- /* ensure the queue is still disabled */
+- SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_RST_SET);
+- }
+-} /* DoInitRamQueue */
+-
+-
+-/******************************************************************************
+- *
+- * SkGeInitRamBufs() - Initialize the RAM Buffer Queues
+- *
+- * Description:
+- * Initialize all RAM Buffer Queues of the specified port
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkGeInitRamBufs(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_GEPORT *pPrt;
+- int RxQType;
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- if (pPrt->PRxQSize == SK_MIN_RXQ_SIZE) {
+- RxQType = SK_RX_SRAM_Q; /* small Rx Queue */
+- }
+- else {
+- RxQType = SK_RX_BRAM_Q; /* big Rx Queue */
+- }
+-
+- DoInitRamQueue(pAC, IoC, pPrt->PRxQOff, pPrt->PRxQRamStart,
+- pPrt->PRxQRamEnd, RxQType);
+-
+- DoInitRamQueue(pAC, IoC, pPrt->PXsQOff, pPrt->PXsQRamStart,
+- pPrt->PXsQRamEnd, SK_TX_RAM_Q);
+-
+- DoInitRamQueue(pAC, IoC, pPrt->PXaQOff, pPrt->PXaQRamStart,
+- pPrt->PXaQRamEnd, SK_TX_RAM_Q);
+-
+-} /* SkGeInitRamBufs */
+-
+-
+-/******************************************************************************
+- *
+- * SkGeInitRamIface() - Initialize the RAM Interface
+- *
+- * Description:
+- * This function initializes the Adapters RAM Interface.
+- *
+- * Note:
+- * This function is used in the diagnostics.
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkGeInitRamIface(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC) /* IO context */
+-{
+- /* release local reset */
+- SK_OUT16(IoC, B3_RI_CTRL, RI_RST_CLR);
+-
+- /* configure timeout values */
+- SK_OUT8(IoC, B3_RI_WTO_R1, SK_RI_TO_53);
+- SK_OUT8(IoC, B3_RI_WTO_XA1, SK_RI_TO_53);
+- SK_OUT8(IoC, B3_RI_WTO_XS1, SK_RI_TO_53);
+- SK_OUT8(IoC, B3_RI_RTO_R1, SK_RI_TO_53);
+- SK_OUT8(IoC, B3_RI_RTO_XA1, SK_RI_TO_53);
+- SK_OUT8(IoC, B3_RI_RTO_XS1, SK_RI_TO_53);
+- SK_OUT8(IoC, B3_RI_WTO_R2, SK_RI_TO_53);
+- SK_OUT8(IoC, B3_RI_WTO_XA2, SK_RI_TO_53);
+- SK_OUT8(IoC, B3_RI_WTO_XS2, SK_RI_TO_53);
+- SK_OUT8(IoC, B3_RI_RTO_R2, SK_RI_TO_53);
+- SK_OUT8(IoC, B3_RI_RTO_XA2, SK_RI_TO_53);
+- SK_OUT8(IoC, B3_RI_RTO_XS2, SK_RI_TO_53);
+-
+-} /* SkGeInitRamIface */
+-
+-
+-/******************************************************************************
+- *
+- * SkGeInitBmu() - Initialize the BMU state machines
+- *
+- * Description:
+- * Initialize all BMU state machines of the specified port
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkGeInitBmu(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_GEPORT *pPrt;
+- SK_U32 RxWm;
+- SK_U32 TxWm;
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- RxWm = SK_BMU_RX_WM;
+- TxWm = SK_BMU_TX_WM;
+-
+- if (!pAC->GIni.GIPciSlot64 && !pAC->GIni.GIPciClock66) {
+- /* for better performance */
+- RxWm /= 2;
+- TxWm /= 2;
+- }
+-
+- /* Rx Queue: Release all local resets and set the watermark */
+- SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_CLR_RESET);
+- SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_F), RxWm);
+-
+- /*
+- * Tx Queue: Release all local resets if the queue is used !
+- * set watermark
+- */
+- if (pPrt->PXSQSize != 0) {
+- SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_CLR_RESET);
+- SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_F), TxWm);
+- }
+-
+- if (pPrt->PXAQSize != 0) {
+- SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_CLR_RESET);
+- SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_F), TxWm);
+- }
+- /*
+- * Do NOT enable the descriptor poll timers here, because
+- * the descriptor addresses are not specified yet.
+- */
+-} /* SkGeInitBmu */
+-
+-
+-/******************************************************************************
+- *
+- * TestStopBit() - Test the stop bit of the queue
+- *
+- * Description:
+- * Stopping a queue is not as simple as it seems to be.
+- * If descriptor polling is enabled, it may happen
+- * that RX/TX stop is done and SV idle is NOT set.
+- * In this case we have to issue another stop command.
+- *
+- * Returns:
+- * The queues control status register
+- */
+-static SK_U32 TestStopBit(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* IO Context */
+-int QuIoOffs) /* Queue IO Address Offset */
+-{
+- SK_U32 QuCsr; /* CSR contents */
+-
+- SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr);
+-
+- if ((QuCsr & (CSR_STOP | CSR_SV_IDLE)) == 0) {
+- /* Stop Descriptor overridden by start command */
+- SK_OUT32(IoC, Q_ADDR(QuIoOffs, Q_CSR), CSR_STOP);
+-
+- SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr);
+- }
+-
+- return(QuCsr);
+-} /* TestStopBit */
+-
+-
+-/******************************************************************************
+- *
+- * SkGeStopPort() - Stop the Rx/Tx activity of the port 'Port'.
+- *
+- * Description:
+- * After calling this function the descriptor rings and Rx and Tx
+- * queues of this port may be reconfigured.
+- *
+- * It is possible to stop the receive and transmit path separate or
+- * both together.
+- *
+- * Dir = SK_STOP_TX Stops the transmit path only and resets the MAC.
+- * The receive queue is still active and
+- * the pending Rx frames may be still transferred
+- * into the RxD.
+- * SK_STOP_RX Stop the receive path. The tansmit path
+- * has to be stopped once before.
+- * SK_STOP_ALL SK_STOP_TX + SK_STOP_RX
+- *
+- * RstMode = SK_SOFT_RST Resets the MAC. The PHY is still alive.
+- * SK_HARD_RST Resets the MAC and the PHY.
+- *
+- * Example:
+- * 1) A Link Down event was signaled for a port. Therefore the activity
+- * of this port should be stopped and a hardware reset should be issued
+- * to enable the workaround of XMAC Errata #2. But the received frames
+- * should not be discarded.
+- * ...
+- * SkGeStopPort(pAC, IoC, Port, SK_STOP_TX, SK_HARD_RST);
+- * (transfer all pending Rx frames)
+- * SkGeStopPort(pAC, IoC, Port, SK_STOP_RX, SK_HARD_RST);
+- * ...
+- *
+- * 2) An event was issued which request the driver to switch
+- * the 'virtual active' link to an other already active port
+- * as soon as possible. The frames in the receive queue of this
+- * port may be lost. But the PHY must not be reset during this
+- * event.
+- * ...
+- * SkGeStopPort(pAC, IoC, Port, SK_STOP_ALL, SK_SOFT_RST);
+- * ...
+- *
+- * Extended Description:
+- * If SK_STOP_TX is set,
+- * o disable the MAC's receive and transmitter to prevent
+- * from sending incomplete frames
+- * o stop the port's transmit queues before terminating the
+- * BMUs to prevent from performing incomplete PCI cycles
+- * on the PCI bus
+- * - The network Rx and Tx activity and PCI Tx transfer is
+- * disabled now.
+- * o reset the MAC depending on the RstMode
+- * o Stop Interval Timer and Limit Counter of Tx Arbiter,
+- * also disable Force Sync bit and Enable Alloc bit.
+- * o perform a local reset of the port's Tx path
+- * - reset the PCI FIFO of the async Tx queue
+- * - reset the PCI FIFO of the sync Tx queue
+- * - reset the RAM Buffer async Tx queue
+- * - reset the RAM Buffer sync Tx queue
+- * - reset the MAC Tx FIFO
+- * o switch Link and Tx LED off, stop the LED counters
+- *
+- * If SK_STOP_RX is set,
+- * o stop the port's receive queue
+- * - The path data transfer activity is fully stopped now.
+- * o perform a local reset of the port's Rx path
+- * - reset the PCI FIFO of the Rx queue
+- * - reset the RAM Buffer receive queue
+- * - reset the MAC Rx FIFO
+- * o switch Rx LED off, stop the LED counter
+- *
+- * If all ports are stopped,
+- * o reset the RAM Interface.
+- *
+- * Notes:
+- * o This function may be called during the driver states RESET_PORT and
+- * SWITCH_PORT.
+- */
+-void SkGeStopPort(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* I/O context */
+-int Port, /* port to stop (MAC_1 + n) */
+-int Dir, /* Direction to Stop (SK_STOP_RX, SK_STOP_TX, SK_STOP_ALL) */
+-int RstMode)/* Reset Mode (SK_SOFT_RST, SK_HARD_RST) */
+-{
+-#ifndef SK_DIAG
+- SK_EVPARA Para;
+-#endif /* !SK_DIAG */
+- SK_GEPORT *pPrt;
+- SK_U32 DWord;
+- SK_U32 XsCsr;
+- SK_U32 XaCsr;
+- SK_U64 ToutStart;
+- int i;
+- int ToutCnt;
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- if ((Dir & SK_STOP_TX) != 0) {
+- /* disable receiver and transmitter */
+- SkMacRxTxDisable(pAC, IoC, Port);
+-
+- /* stop both transmit queues */
+- /*
+- * If the BMU is in the reset state CSR_STOP will terminate
+- * immediately.
+- */
+- SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_STOP);
+- SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_STOP);
+-
+- ToutStart = SkOsGetTime(pAC);
+- ToutCnt = 0;
+- do {
+- /*
+- * Clear packet arbiter timeout to make sure
+- * this loop will terminate.
+- */
+- SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ?
+- PA_CLR_TO_TX1 : PA_CLR_TO_TX2));
+-
+- /*
+- * If the transfer stucks at the MAC the STOP command will not
+- * terminate if we don't flush the XMAC's transmit FIFO !
+- */
+- SkMacFlushTxFifo(pAC, IoC, Port);
+-
+- XsCsr = TestStopBit(pAC, IoC, pPrt->PXsQOff);
+- XaCsr = TestStopBit(pAC, IoC, pPrt->PXaQOff);
+-
+- if (SkOsGetTime(pAC) - ToutStart > (SK_TICKS_PER_SEC / 18)) {
+- /*
+- * Timeout of 1/18 second reached.
+- * This needs to be checked at 1/18 sec only.
+- */
+- ToutCnt++;
+- if (ToutCnt > 1) {
+- /* Might be a problem when the driver event handler
+- * calls StopPort again. XXX.
+- */
+-
+- /* Fatal Error, Loop aborted */
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E018,
+- SKERR_HWI_E018MSG);
+-#ifndef SK_DIAG
+- Para.Para64 = Port;
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+-#endif /* !SK_DIAG */
+- return;
+- }
+- /*
+- * Cache incoherency workaround: Assume a start command
+- * has been lost while sending the frame.
+- */
+- ToutStart = SkOsGetTime(pAC);
+-
+- if ((XsCsr & CSR_STOP) != 0) {
+- SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_START);
+- }
+- if ((XaCsr & CSR_STOP) != 0) {
+- SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_START);
+- }
+- }
+-
+- /*
+- * Because of the ASIC problem report entry from 21.08.1998 it is
+- * required to wait until CSR_STOP is reset and CSR_SV_IDLE is set.
+- */
+- } while ((XsCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE ||
+- (XaCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE);
+-
+- /* Reset the MAC depending on the RstMode */
+- if (RstMode == SK_SOFT_RST) {
+- SkMacSoftRst(pAC, IoC, Port);
+- }
+- else {
+- SkMacHardRst(pAC, IoC, Port);
+- }
+-
+- /* Disable Force Sync bit and Enable Alloc bit */
+- SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
+- TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
+-
+- /* Stop Interval Timer and Limit Counter of Tx Arbiter */
+- SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), 0L);
+- SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), 0L);
+-
+- /* Perform a local reset of the port's Tx path */
+-
+- /* Reset the PCI FIFO of the async Tx queue */
+- SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_SET_RESET);
+- /* Reset the PCI FIFO of the sync Tx queue */
+- SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_SET_RESET);
+- /* Reset the RAM Buffer async Tx queue */
+- SK_OUT8(IoC, RB_ADDR(pPrt->PXaQOff, RB_CTRL), RB_RST_SET);
+- /* Reset the RAM Buffer sync Tx queue */
+- SK_OUT8(IoC, RB_ADDR(pPrt->PXsQOff, RB_CTRL), RB_RST_SET);
+-
+- /* Reset Tx MAC FIFO */
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+- /* Note: MFF_RST_SET does NOT reset the XMAC ! */
+- SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_SET);
+-
+- /* switch Link and Tx LED off, stop the LED counters */
+- /* Link LED is switched off by the RLMT and the Diag itself */
+- SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_DIS);
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIYukon) {
+- /* Reset TX MAC FIFO */
+- SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_SET);
+- }
+-#endif /* YUKON */
+- }
+-
+- if ((Dir & SK_STOP_RX) != 0) {
+- /*
+- * The RX Stop Command will not terminate if no buffers
+- * are queued in the RxD ring. But it will always reach
+- * the Idle state. Therefore we can use this feature to
+- * stop the transfer of received packets.
+- */
+- /* stop the port's receive queue */
+- SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_STOP);
+-
+- i = 100;
+- do {
+- /*
+- * Clear packet arbiter timeout to make sure
+- * this loop will terminate
+- */
+- SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ?
+- PA_CLR_TO_RX1 : PA_CLR_TO_RX2));
+-
+- DWord = TestStopBit(pAC, IoC, pPrt->PRxQOff);
+-
+- /* timeout if i==0 (bug fix for #10748) */
+- if (--i == 0) {
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E024,
+- SKERR_HWI_E024MSG);
+- break;
+- }
+- /*
+- * because of the ASIC problem report entry from 21.08.98
+- * it is required to wait until CSR_STOP is reset and
+- * CSR_SV_IDLE is set.
+- */
+- } while ((DWord & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE);
+-
+- /* The path data transfer activity is fully stopped now */
+-
+- /* Perform a local reset of the port's Rx path */
+-
+- /* Reset the PCI FIFO of the Rx queue */
+- SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_SET_RESET);
+- /* Reset the RAM Buffer receive queue */
+- SK_OUT8(IoC, RB_ADDR(pPrt->PRxQOff, RB_CTRL), RB_RST_SET);
+-
+- /* Reset Rx MAC FIFO */
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+-
+- SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_SET);
+-
+- /* switch Rx LED off, stop the LED counter */
+- SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_DIS);
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIYukon) {
+- /* Reset Rx MAC FIFO */
+- SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_SET);
+- }
+-#endif /* YUKON */
+- }
+-} /* SkGeStopPort */
+-
+-
+-/******************************************************************************
+- *
+- * SkGeInit0() - Level 0 Initialization
+- *
+- * Description:
+- * - Initialize the BMU address offsets
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkGeInit0(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC) /* IO context */
+-{
+- int i;
+- SK_GEPORT *pPrt;
+-
+- for (i = 0; i < SK_MAX_MACS; i++) {
+- pPrt = &pAC->GIni.GP[i];
+-
+- pPrt->PState = SK_PRT_RESET;
+- pPrt->PRxQOff = QOffTab[i].RxQOff;
+- pPrt->PXsQOff = QOffTab[i].XsQOff;
+- pPrt->PXaQOff = QOffTab[i].XaQOff;
+- pPrt->PCheckPar = SK_FALSE;
+- pPrt->PIsave = 0;
+- pPrt->PPrevShorts = 0;
+- pPrt->PLinkResCt = 0;
+- pPrt->PAutoNegTOCt = 0;
+- pPrt->PPrevRx = 0;
+- pPrt->PPrevFcs = 0;
+- pPrt->PRxLim = SK_DEF_RX_WA_LIM;
+- pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL;
+- pPrt->PLinkSpeedCap = (SK_U8)SK_LSPEED_CAP_1000MBPS;
+- pPrt->PLinkSpeed = (SK_U8)SK_LSPEED_1000MBPS;
+- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_UNKNOWN;
+- pPrt->PLinkModeConf = (SK_U8)SK_LMODE_AUTOSENSE;
+- pPrt->PFlowCtrlMode = (SK_U8)SK_FLOW_MODE_SYM_OR_REM;
+- pPrt->PLinkCap = (SK_U8)(SK_LMODE_CAP_HALF | SK_LMODE_CAP_FULL |
+- SK_LMODE_CAP_AUTOHALF | SK_LMODE_CAP_AUTOFULL);
+- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
+- pPrt->PFlowCtrlCap = (SK_U8)SK_FLOW_MODE_SYM_OR_REM;
+- pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
+- pPrt->PMSCap = 0;
+- pPrt->PMSMode = (SK_U8)SK_MS_MODE_AUTO;
+- pPrt->PMSStatus = (SK_U8)SK_MS_STAT_UNSET;
+- pPrt->PLipaAutoNeg = (SK_U8)SK_LIPA_UNKNOWN;
+- pPrt->PAutoNegFail = SK_FALSE;
+- pPrt->PHWLinkUp = SK_FALSE;
+- pPrt->PLinkBroken = SK_TRUE; /* See WA code */
+- pPrt->PPhyPowerState = PHY_PM_OPERATIONAL_MODE;
+- pPrt->PMacColThres = TX_COL_DEF;
+- pPrt->PMacJamLen = TX_JAM_LEN_DEF;
+- pPrt->PMacJamIpgVal = TX_JAM_IPG_DEF;
+- pPrt->PMacJamIpgData = TX_IPG_JAM_DEF;
+- pPrt->PMacIpgData = IPG_DATA_DEF;
+- pPrt->PMacLimit4 = SK_FALSE;
+- }
+-
+- pAC->GIni.GIPortUsage = SK_RED_LINK;
+- pAC->GIni.GILedBlinkCtrl = (SK_U16)OemConfig.Value;
+- pAC->GIni.GIValIrqMask = IS_ALL_MSK;
+-
+-} /* SkGeInit0*/
+-
+-
+-/******************************************************************************
+- *
+- * SkGeInit1() - Level 1 Initialization
+- *
+- * Description:
+- * o Do a software reset.
+- * o Clear all reset bits.
+- * o Verify that the detected hardware is present.
+- * Return an error if not.
+- * o Get the hardware configuration
+- * + Read the number of MACs/Ports.
+- * + Read the RAM size.
+- * + Read the PCI Revision Id.
+- * + Find out the adapters host clock speed
+- * + Read and check the PHY type
+- *
+- * Returns:
+- * 0: success
+- * 5: Unexpected PHY type detected
+- * 6: HW self test failed
+- */
+-static int SkGeInit1(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC) /* IO context */
+-{
+- SK_U8 Byte;
+- SK_U16 Word;
+- SK_U16 CtrlStat;
+- SK_U32 DWord;
+- int RetVal;
+- int i;
+-
+- RetVal = 0;
+-
+- /* save CLK_RUN bits (YUKON-Lite) */
+- SK_IN16(IoC, B0_CTST, &CtrlStat);
+-
+- /* do the SW-reset */
+- SK_OUT8(IoC, B0_CTST, CS_RST_SET);
+-
+- /* release the SW-reset */
+- SK_OUT8(IoC, B0_CTST, CS_RST_CLR);
+-
+- /* reset all error bits in the PCI STATUS register */
+- /*
+- * Note: PCI Cfg cycles cannot be used, because they are not
+- * available on some platforms after 'boot time'.
+- */
+- SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
+-
+- SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+- SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
+- SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+-
+- /* release Master Reset */
+- SK_OUT8(IoC, B0_CTST, CS_MRST_CLR);
+-
+-#ifdef CLK_RUN
+- CtrlStat |= CS_CLK_RUN_ENA;
+-#endif /* CLK_RUN */
+-
+- /* restore CLK_RUN bits */
+- SK_OUT16(IoC, B0_CTST, (SK_U16)(CtrlStat &
+- (CS_CLK_RUN_HOT | CS_CLK_RUN_RST | CS_CLK_RUN_ENA)));
+-
+- /* read Chip Identification Number */
+- SK_IN8(IoC, B2_CHIP_ID, &Byte);
+- pAC->GIni.GIChipId = Byte;
+-
+- /* read number of MACs */
+- SK_IN8(IoC, B2_MAC_CFG, &Byte);
+- pAC->GIni.GIMacsFound = (Byte & CFG_SNG_MAC) ? 1 : 2;
+-
+- /* get Chip Revision Number */
+- pAC->GIni.GIChipRev = (SK_U8)((Byte & CFG_CHIP_R_MSK) >> 4);
+-
+- /* get diff. PCI parameters */
+- SK_IN16(IoC, B0_CTST, &CtrlStat);
+-
+- /* read the adapters RAM size */
+- SK_IN8(IoC, B2_E_0, &Byte);
+-
+- pAC->GIni.GIGenesis = SK_FALSE;
+- pAC->GIni.GIYukon = SK_FALSE;
+- pAC->GIni.GIYukonLite = SK_FALSE;
+-
+-#ifdef GENESIS
+- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+-
+- pAC->GIni.GIGenesis = SK_TRUE;
+-
+- if (Byte == (SK_U8)3) {
+- /* special case: 4 x 64k x 36, offset = 0x80000 */
+- pAC->GIni.GIRamSize = 1024;
+- pAC->GIni.GIRamOffs = (SK_U32)512 * 1024;
+- }
+- else {
+- pAC->GIni.GIRamSize = (int)Byte * 512;
+- pAC->GIni.GIRamOffs = 0;
+- }
+- /* all GE adapters work with 53.125 MHz host clock */
+- pAC->GIni.GIHstClkFact = SK_FACT_53;
+-
+- /* set Descr. Poll Timer Init Value to 250 ms */
+- pAC->GIni.GIPollTimerVal =
+- SK_DPOLL_DEF * (SK_U32)pAC->GIni.GIHstClkFact / 100;
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIChipId != CHIP_ID_GENESIS) {
+-
+- pAC->GIni.GIYukon = SK_TRUE;
+-
+- pAC->GIni.GIRamSize = (Byte == (SK_U8)0) ? 128 : (int)Byte * 4;
+-
+- pAC->GIni.GIRamOffs = 0;
+-
+- /* WA for chip Rev. A */
+- pAC->GIni.GIWolOffs = (pAC->GIni.GIChipId == CHIP_ID_YUKON &&
+- pAC->GIni.GIChipRev == 0) ? WOL_REG_OFFS : 0;
+-
+- /* get PM Capabilities of PCI config space */
+- SK_IN16(IoC, PCI_C(PCI_PM_CAP_REG), &Word);
+-
+- /* check if VAUX is available */
+- if (((CtrlStat & CS_VAUX_AVAIL) != 0) &&
+- /* check also if PME from D3cold is set */
+- ((Word & PCI_PME_D3C_SUP) != 0)) {
+- /* set entry in GE init struct */
+- pAC->GIni.GIVauxAvail = SK_TRUE;
+- }
+-
+- if (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) {
+- /* this is Rev. A1 */
+- pAC->GIni.GIYukonLite = SK_TRUE;
+- }
+- else {
+- /* save Flash-Address Register */
+- SK_IN32(IoC, B2_FAR, &DWord);
+-
+- /* test Flash-Address Register */
+- SK_OUT8(IoC, B2_FAR + 3, 0xff);
+- SK_IN8(IoC, B2_FAR + 3, &Byte);
+-
+- if (Byte != 0) {
+- /* this is Rev. A0 */
+- pAC->GIni.GIYukonLite = SK_TRUE;
+-
+- /* restore Flash-Address Register */
+- SK_OUT32(IoC, B2_FAR, DWord);
+- }
+- }
+-
+- /* switch power to VCC (WA for VAUX problem) */
+- SK_OUT8(IoC, B0_POWER_CTRL, (SK_U8)(PC_VAUX_ENA | PC_VCC_ENA |
+- PC_VAUX_OFF | PC_VCC_ON));
+-
+- /* read the Interrupt source */
+- SK_IN32(IoC, B0_ISRC, &DWord);
+-
+- if ((DWord & IS_HW_ERR) != 0) {
+- /* read the HW Error Interrupt source */
+- SK_IN32(IoC, B0_HWE_ISRC, &DWord);
+-
+- if ((DWord & IS_IRQ_SENSOR) != 0) {
+- /* disable HW Error IRQ */
+- pAC->GIni.GIValIrqMask &= ~IS_HW_ERR;
+- }
+- }
+-
+- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+- /* set GMAC Link Control reset */
+- SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_SET);
+-
+- /* clear GMAC Link Control reset */
+- SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
+- }
+- /* all YU chips work with 78.125 MHz host clock */
+- pAC->GIni.GIHstClkFact = SK_FACT_78;
+-
+- pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX; /* 215 ms */
+- }
+-#endif /* YUKON */
+-
+- /* check if 64-bit PCI Slot is present */
+- pAC->GIni.GIPciSlot64 = (SK_BOOL)((CtrlStat & CS_BUS_SLOT_SZ) != 0);
+-
+- /* check if 66 MHz PCI Clock is active */
+- pAC->GIni.GIPciClock66 = (SK_BOOL)((CtrlStat & CS_BUS_CLOCK) != 0);
+-
+- /* read PCI HW Revision Id. */
+- SK_IN8(IoC, PCI_C(PCI_REV_ID), &Byte);
+- pAC->GIni.GIPciHwRev = Byte;
+-
+- /* read the PMD type */
+- SK_IN8(IoC, B2_PMD_TYP, &Byte);
+- pAC->GIni.GICopperType = (SK_U8)(Byte == 'T');
+-
+- /* read the PHY type */
+- SK_IN8(IoC, B2_E_1, &Byte);
+-
+- Byte &= 0x0f; /* the PHY type is stored in the lower nibble */
+- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+-
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+- switch (Byte) {
+- case SK_PHY_XMAC:
+- pAC->GIni.GP[i].PhyAddr = PHY_ADDR_XMAC;
+- break;
+- case SK_PHY_BCOM:
+- pAC->GIni.GP[i].PhyAddr = PHY_ADDR_BCOM;
+- pAC->GIni.GP[i].PMSCap = (SK_U8)(SK_MS_CAP_AUTO |
+- SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE);
+- break;
+-#ifdef OTHER_PHY
+- case SK_PHY_LONE:
+- pAC->GIni.GP[i].PhyAddr = PHY_ADDR_LONE;
+- break;
+- case SK_PHY_NAT:
+- pAC->GIni.GP[i].PhyAddr = PHY_ADDR_NAT;
+- break;
+-#endif /* OTHER_PHY */
+- default:
+- /* ERROR: unexpected PHY type detected */
+- RetVal = 5;
+- break;
+- }
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIYukon) {
+-
+- if (Byte < (SK_U8)SK_PHY_MARV_COPPER) {
+- /* if this field is not initialized */
+- Byte = (SK_U8)SK_PHY_MARV_COPPER;
+-
+- pAC->GIni.GICopperType = SK_TRUE;
+- }
+-
+- pAC->GIni.GP[i].PhyAddr = PHY_ADDR_MARV;
+-
+- if (pAC->GIni.GICopperType) {
+-
+- pAC->GIni.GP[i].PLinkSpeedCap = (SK_U8)(SK_LSPEED_CAP_AUTO |
+- SK_LSPEED_CAP_10MBPS | SK_LSPEED_CAP_100MBPS |
+- SK_LSPEED_CAP_1000MBPS);
+-
+- pAC->GIni.GP[i].PLinkSpeed = (SK_U8)SK_LSPEED_AUTO;
+-
+- pAC->GIni.GP[i].PMSCap = (SK_U8)(SK_MS_CAP_AUTO |
+- SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE);
+- }
+- else {
+- Byte = (SK_U8)SK_PHY_MARV_FIBER;
+- }
+- }
+-#endif /* YUKON */
+-
+- pAC->GIni.GP[i].PhyType = (int)Byte;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+- ("PHY type: %d PHY addr: %04x\n", Byte,
+- pAC->GIni.GP[i].PhyAddr));
+- }
+-
+- /* get MAC Type & set function pointers dependent on */
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+-
+- pAC->GIni.GIMacType = SK_MAC_XMAC;
+-
+- pAC->GIni.GIFunc.pFnMacUpdateStats = SkXmUpdateStats;
+- pAC->GIni.GIFunc.pFnMacStatistic = SkXmMacStatistic;
+- pAC->GIni.GIFunc.pFnMacResetCounter = SkXmResetCounter;
+- pAC->GIni.GIFunc.pFnMacOverflow = SkXmOverflowStatus;
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIYukon) {
+-
+- pAC->GIni.GIMacType = SK_MAC_GMAC;
+-
+- pAC->GIni.GIFunc.pFnMacUpdateStats = SkGmUpdateStats;
+- pAC->GIni.GIFunc.pFnMacStatistic = SkGmMacStatistic;
+- pAC->GIni.GIFunc.pFnMacResetCounter = SkGmResetCounter;
+- pAC->GIni.GIFunc.pFnMacOverflow = SkGmOverflowStatus;
+-
+-#ifdef SPECIAL_HANDLING
+- if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
+- /* check HW self test result */
+- SK_IN8(IoC, B2_E_3, &Byte);
+- if (Byte & B2_E3_RES_MASK) {
+- RetVal = 6;
+- }
+- }
+-#endif
+- }
+-#endif /* YUKON */
+-
+- return(RetVal);
+-} /* SkGeInit1 */
+-
+-
+-/******************************************************************************
+- *
+- * SkGeInit2() - Level 2 Initialization
+- *
+- * Description:
+- * - start the Blink Source Counter
+- * - start the Descriptor Poll Timer
+- * - configure the MAC-Arbiter
+- * - configure the Packet-Arbiter
+- * - enable the Tx Arbiters
+- * - enable the RAM Interface Arbiter
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkGeInit2(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC) /* IO context */
+-{
+-#ifdef GENESIS
+- SK_U32 DWord;
+-#endif /* GENESIS */
+- int i;
+-
+- /* start the Descriptor Poll Timer */
+- if (pAC->GIni.GIPollTimerVal != 0) {
+- if (pAC->GIni.GIPollTimerVal > SK_DPOLL_MAX) {
+- pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX;
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E017, SKERR_HWI_E017MSG);
+- }
+- SK_OUT32(IoC, B28_DPT_INI, pAC->GIni.GIPollTimerVal);
+- SK_OUT8(IoC, B28_DPT_CTRL, DPT_START);
+- }
+-
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+- /* start the Blink Source Counter */
+- DWord = SK_BLK_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100;
+-
+- SK_OUT32(IoC, B2_BSC_INI, DWord);
+- SK_OUT8(IoC, B2_BSC_CTRL, BSC_START);
+-
+- /*
+- * Configure the MAC Arbiter and the Packet Arbiter.
+- * They will be started once and never be stopped.
+- */
+- SkGeInitMacArb(pAC, IoC);
+-
+- SkGeInitPktArb(pAC, IoC);
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIYukon) {
+- /* start Time Stamp Timer */
+- SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_START);
+- }
+-#endif /* YUKON */
+-
+- /* enable the Tx Arbiters */
+- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+- SK_OUT8(IoC, MR_ADDR(i, TXA_CTRL), TXA_ENA_ARB);
+- }
+-
+- /* enable the RAM Interface Arbiter */
+- SkGeInitRamIface(pAC, IoC);
+-
+-} /* SkGeInit2 */
+-
+-/******************************************************************************
+- *
+- * SkGeInit() - Initialize the GE Adapter with the specified level.
+- *
+- * Description:
+- * Level 0: Initialize the Module structures.
+- * Level 1: Generic Hardware Initialization. The IOP/MemBase pointer has
+- * to be set before calling this level.
+- *
+- * o Do a software reset.
+- * o Clear all reset bits.
+- * o Verify that the detected hardware is present.
+- * Return an error if not.
+- * o Get the hardware configuration
+- * + Set GIMacsFound with the number of MACs.
+- * + Store the RAM size in GIRamSize.
+- * + Save the PCI Revision ID in GIPciHwRev.
+- * o return an error
+- * if Number of MACs > SK_MAX_MACS
+- *
+- * After returning from Level 0 the adapter
+- * may be accessed with IO operations.
+- *
+- * Level 2: start the Blink Source Counter
+- *
+- * Returns:
+- * 0: success
+- * 1: Number of MACs exceeds SK_MAX_MACS (after level 1)
+- * 2: Adapter not present or not accessible
+- * 3: Illegal initialization level
+- * 4: Initialization Level 1 Call missing
+- * 5: Unexpected PHY type detected
+- * 6: HW self test failed
+- */
+-int SkGeInit(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Level) /* initialization level */
+-{
+- int RetVal; /* return value */
+- SK_U32 DWord;
+-
+- RetVal = 0;
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+- ("SkGeInit(Level %d)\n", Level));
+-
+- switch (Level) {
+- case SK_INIT_DATA:
+- /* Initialization Level 0 */
+- SkGeInit0(pAC, IoC);
+- pAC->GIni.GILevel = SK_INIT_DATA;
+- break;
+-
+- case SK_INIT_IO:
+- /* Initialization Level 1 */
+- RetVal = SkGeInit1(pAC, IoC);
+- if (RetVal != 0) {
+- break;
+- }
+-
+- /* check if the adapter seems to be accessible */
+- SK_OUT32(IoC, B2_IRQM_INI, SK_TEST_VAL);
+- SK_IN32(IoC, B2_IRQM_INI, &DWord);
+- SK_OUT32(IoC, B2_IRQM_INI, 0L);
+-
+- if (DWord != SK_TEST_VAL) {
+- RetVal = 2;
+- break;
+- }
+-
+- /* check if the number of GIMacsFound matches SK_MAX_MACS */
+- if (pAC->GIni.GIMacsFound > SK_MAX_MACS) {
+- RetVal = 1;
+- break;
+- }
+-
+- /* Level 1 successfully passed */
+- pAC->GIni.GILevel = SK_INIT_IO;
+- break;
+-
+- case SK_INIT_RUN:
+- /* Initialization Level 2 */
+- if (pAC->GIni.GILevel != SK_INIT_IO) {
+-#ifndef SK_DIAG
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E002, SKERR_HWI_E002MSG);
+-#endif /* !SK_DIAG */
+- RetVal = 4;
+- break;
+- }
+- SkGeInit2(pAC, IoC);
+-
+- /* Level 2 successfully passed */
+- pAC->GIni.GILevel = SK_INIT_RUN;
+- break;
+-
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E003, SKERR_HWI_E003MSG);
+- RetVal = 3;
+- break;
+- }
+-
+- return(RetVal);
+-} /* SkGeInit */
+-
+-
+-/******************************************************************************
+- *
+- * SkGeDeInit() - Deinitialize the adapter
+- *
+- * Description:
+- * All ports of the adapter will be stopped if not already done.
+- * Do a software reset and switch off all LEDs.
+- *
+- * Returns:
+- * nothing
+- */
+-void SkGeDeInit(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC) /* IO context */
+-{
+- int i;
+- SK_U16 Word;
+-
+-#if (!defined(SK_SLIM) && !defined(VCPU))
+- /* ensure I2C is ready */
+- SkI2cWaitIrq(pAC, IoC);
+-#endif
+-
+- /* stop all current transfer activity */
+- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+- if (pAC->GIni.GP[i].PState != SK_PRT_STOP &&
+- pAC->GIni.GP[i].PState != SK_PRT_RESET) {
+-
+- SkGeStopPort(pAC, IoC, i, SK_STOP_ALL, SK_HARD_RST);
+- }
+- }
+-
+- /* Reset all bits in the PCI STATUS register */
+- /*
+- * Note: PCI Cfg cycles cannot be used, because they are not
+- * available on some platforms after 'boot time'.
+- */
+- SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
+-
+- SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+- SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
+- SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+-
+- /* do the reset, all LEDs are switched off now */
+- SK_OUT8(IoC, B0_CTST, CS_RST_SET);
+-
+- pAC->GIni.GILevel = SK_INIT_DATA;
+-} /* SkGeDeInit */
+-
+-
+-/******************************************************************************
+- *
+- * SkGeInitPort() Initialize the specified port.
+- *
+- * Description:
+- * PRxQSize, PXSQSize, and PXAQSize has to be
+- * configured for the specified port before calling this function.
+- * The descriptor rings has to be initialized too.
+- *
+- * o (Re)configure queues of the specified port.
+- * o configure the MAC of the specified port.
+- * o put ASIC and MAC(s) in operational mode.
+- * o initialize Rx/Tx and Sync LED
+- * o initialize RAM Buffers and MAC FIFOs
+- *
+- * The port is ready to connect when returning.
+- *
+- * Note:
+- * The MAC's Rx and Tx state machine is still disabled when returning.
+- *
+- * Returns:
+- * 0: success
+- * 1: Queue size initialization error. The configured values
+- * for PRxQSize, PXSQSize, or PXAQSize are invalid for one
+- * or more queues. The specified port was NOT initialized.
+- * An error log entry was generated.
+- * 2: The port has to be stopped before it can be initialized again.
+- */
+-int SkGeInitPort(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port to configure */
+-{
+- SK_GEPORT *pPrt;
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- if (SkGeCheckQSize(pAC, Port) != 0) {
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E004, SKERR_HWI_E004MSG);
+- return(1);
+- }
+-
+- if (pPrt->PState == SK_PRT_INIT || pPrt->PState == SK_PRT_RUN) {
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E005, SKERR_HWI_E005MSG);
+- return(2);
+- }
+-
+- /* configuration ok, initialize the Port now */
+-
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+- /* initialize Rx, Tx and Link LED */
+- /*
+- * If 1000BT Phy needs LED initialization than swap
+- * LED and XMAC initialization order
+- */
+- SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA);
+- SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_ENA);
+- /* The Link LED is initialized by RLMT or Diagnostics itself */
+-
+- SkXmInitMac(pAC, IoC, Port);
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIYukon) {
+-
+- SkGmInitMac(pAC, IoC, Port);
+- }
+-#endif /* YUKON */
+-
+- /* do NOT initialize the Link Sync Counter */
+-
+- SkGeInitMacFifo(pAC, IoC, Port);
+-
+- SkGeInitRamBufs(pAC, IoC, Port);
+-
+- if (pPrt->PXSQSize != 0) {
+- /* enable Force Sync bit if synchronous queue available */
+- SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_ENA_FSYNC);
+- }
+-
+- SkGeInitBmu(pAC, IoC, Port);
+-
+- /* mark port as initialized */
+- pPrt->PState = SK_PRT_INIT;
+-
+- return(0);
+-} /* SkGeInitPort */
+diff --git a/drivers/net/sk98lin/skgemib.c b/drivers/net/sk98lin/skgemib.c
+deleted file mode 100644
+index fde4508..0000000
+--- a/drivers/net/sk98lin/skgemib.c
++++ /dev/null
+@@ -1,1075 +0,0 @@
+-/*****************************************************************************
+- *
+- * Name: skgemib.c
+- * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.11 $
+- * Date: $Date: 2003/09/15 13:38:12 $
+- * Purpose: Private Network Management Interface Management Database
+- *
+- ****************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- * PRIVATE OID handler function prototypes
+- */
+-PNMI_STATIC int Addr(SK_AC *pAC, SK_IOC IoC, int action,
+- SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance,
+- unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int CsumStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+- char *pBuf, unsigned int *pLen, SK_U32 Instance,
+- unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int General(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+- char *pBuf, unsigned int *pLen, SK_U32 Instance,
+- unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int Mac8023Stat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+- char *pBuf, unsigned int *pLen, SK_U32 Instance,
+- unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int MacPrivateConf(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+- char *pBuf, unsigned int *pLen, SK_U32 Instance,
+- unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int MacPrivateStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+- char *pBuf, unsigned int *pLen, SK_U32 Instance,
+- unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int Monitor(SK_AC *pAC, SK_IOC IoC, int action,
+- SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance,
+- unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int OidStruct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+- char *pBuf, unsigned int *pLen, SK_U32 Instance,
+- unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int Perform(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+- char *pBuf, unsigned int* pLen, SK_U32 Instance,
+- unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int Rlmt(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+- char *pBuf, unsigned int *pLen, SK_U32 Instance,
+- unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int RlmtStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+- char *pBuf, unsigned int *pLen, SK_U32 Instance,
+- unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int SensorStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+- char *pBuf, unsigned int *pLen, SK_U32 Instance,
+- unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int Vpd(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+- char *pBuf, unsigned int *pLen, SK_U32 Instance,
+- unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+- char *pBuf, unsigned int *pLen, SK_U32 Instance,
+- unsigned int TableIndex, SK_U32 NetIndex);
+-
+-#ifdef SK_POWER_MGMT
+-PNMI_STATIC int PowerManagement(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+- char *pBuf, unsigned int *pLen, SK_U32 Instance,
+- unsigned int TableIndex, SK_U32 NetIndex);
+-#endif /* SK_POWER_MGMT */
+-
+-#ifdef SK_DIAG_SUPPORT
+-PNMI_STATIC int DiagActions(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
+- char *pBuf, unsigned int *pLen, SK_U32 Instance,
+- unsigned int TableIndex, SK_U32 NetIndex);
+-#endif /* SK_DIAG_SUPPORT */
+-
+-
+-/* defines *******************************************************************/
+-#define ID_TABLE_SIZE ARRAY_SIZE(IdTable)
+-
+-
+-/* global variables **********************************************************/
+-
+-/*
+- * Table to correlate OID with handler function and index to
+- * hardware register stored in StatAddress if applicable.
+- */
+-PNMI_STATIC const SK_PNMI_TAB_ENTRY IdTable[] = {
+- {OID_GEN_XMIT_OK,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX},
+- {OID_GEN_RCV_OK,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX},
+- {OID_GEN_XMIT_ERROR,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, General, 0},
+- {OID_GEN_RCV_ERROR,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, General, 0},
+- {OID_GEN_RCV_NO_BUFFER,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, General, 0},
+- {OID_GEN_DIRECTED_FRAMES_XMIT,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNICAST},
+- {OID_GEN_MULTICAST_FRAMES_XMIT,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTICAST},
+- {OID_GEN_BROADCAST_FRAMES_XMIT,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_BROADCAST},
+- {OID_GEN_DIRECTED_FRAMES_RCV,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_UNICAST},
+- {OID_GEN_MULTICAST_FRAMES_RCV,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_MULTICAST},
+- {OID_GEN_BROADCAST_FRAMES_RCV,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_BROADCAST},
+- {OID_GEN_RCV_CRC_ERROR,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FCS},
+- {OID_GEN_TRANSMIT_QUEUE_LENGTH,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, General, 0},
+- {OID_802_3_PERMANENT_ADDRESS,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, Mac8023Stat, 0},
+- {OID_802_3_CURRENT_ADDRESS,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, Mac8023Stat, 0},
+- {OID_802_3_RCV_ERROR_ALIGNMENT,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FRAMING},
+- {OID_802_3_XMIT_ONE_COLLISION,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_SINGLE_COL},
+- {OID_802_3_XMIT_MORE_COLLISIONS,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTI_COL},
+- {OID_802_3_XMIT_DEFERRED,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_DEFFERAL},
+- {OID_802_3_XMIT_MAX_COLLISIONS,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_EXCESS_COL},
+- {OID_802_3_RCV_OVERRUN,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_OVERFLOW},
+- {OID_802_3_XMIT_UNDERRUN,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNDERRUN},
+- {OID_802_3_XMIT_TIMES_CRS_LOST,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_CARRIER},
+- {OID_802_3_XMIT_LATE_COLLISIONS,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_LATE_COL},
+-#ifdef SK_POWER_MGMT
+- {OID_PNP_CAPABILITIES,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, PowerManagement, 0},
+- {OID_PNP_SET_POWER,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_WO, PowerManagement, 0},
+- {OID_PNP_QUERY_POWER,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, PowerManagement, 0},
+- {OID_PNP_ADD_WAKE_UP_PATTERN,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_WO, PowerManagement, 0},
+- {OID_PNP_REMOVE_WAKE_UP_PATTERN,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_WO, PowerManagement, 0},
+- {OID_PNP_ENABLE_WAKE_UP,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RW, PowerManagement, 0},
+-#endif /* SK_POWER_MGMT */
+-#ifdef SK_DIAG_SUPPORT
+- {OID_SKGE_DIAG_MODE,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RW, DiagActions, 0},
+-#endif /* SK_DIAG_SUPPORT */
+- {OID_SKGE_MDB_VERSION,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(MgmtDBVersion),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_SUPPORTED_LIST,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_ALL_DATA,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RW, OidStruct, 0},
+- {OID_SKGE_VPD_FREE_BYTES,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(VpdFreeBytes),
+- SK_PNMI_RO, Vpd, 0},
+- {OID_SKGE_VPD_ENTRIES_LIST,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(VpdEntriesList),
+- SK_PNMI_RO, Vpd, 0},
+- {OID_SKGE_VPD_ENTRIES_NUMBER,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(VpdEntriesNumber),
+- SK_PNMI_RO, Vpd, 0},
+- {OID_SKGE_VPD_KEY,
+- SK_PNMI_VPD_ENTRIES,
+- sizeof(SK_PNMI_VPD),
+- SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdKey),
+- SK_PNMI_RO, Vpd, 0},
+- {OID_SKGE_VPD_VALUE,
+- SK_PNMI_VPD_ENTRIES,
+- sizeof(SK_PNMI_VPD),
+- SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdValue),
+- SK_PNMI_RO, Vpd, 0},
+- {OID_SKGE_VPD_ACCESS,
+- SK_PNMI_VPD_ENTRIES,
+- sizeof(SK_PNMI_VPD),
+- SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAccess),
+- SK_PNMI_RO, Vpd, 0},
+- {OID_SKGE_VPD_ACTION,
+- SK_PNMI_VPD_ENTRIES,
+- sizeof(SK_PNMI_VPD),
+- SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAction),
+- SK_PNMI_RW, Vpd, 0},
+- {OID_SKGE_PORT_NUMBER,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(PortNumber),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_DEVICE_TYPE,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(DeviceType),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_DRIVER_DESCR,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(DriverDescr),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_DRIVER_VERSION,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(DriverVersion),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_DRIVER_RELDATE,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(DriverReleaseDate),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_DRIVER_FILENAME,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(DriverFileName),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_HW_DESCR,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(HwDescr),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_HW_VERSION,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(HwVersion),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_CHIPSET,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(Chipset),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_CHIPID,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(ChipId),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_RAMSIZE,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(RamSize),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_VAUXAVAIL,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(VauxAvail),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_ACTION,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(Action),
+- SK_PNMI_RW, Perform, 0},
+- {OID_SKGE_RESULT,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(TestResult),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_BUS_TYPE,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(BusType),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_BUS_SPEED,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(BusSpeed),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_BUS_WIDTH,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(BusWidth),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_TX_SW_QUEUE_LEN,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(TxSwQueueLen),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_TX_SW_QUEUE_MAX,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(TxSwQueueMax),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_TX_RETRY,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(TxRetryCts),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_RX_INTR_CTS,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(RxIntrCts),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_TX_INTR_CTS,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(TxIntrCts),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_RX_NO_BUF_CTS,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(RxNoBufCts),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_TX_NO_BUF_CTS,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(TxNoBufCts),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_TX_USED_DESCR_NO,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(TxUsedDescrNo),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_RX_DELIVERED_CTS,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(RxDeliveredCts),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_RX_OCTETS_DELIV_CTS,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(RxOctetsDeliveredCts),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_RX_HW_ERROR_CTS,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(RxHwErrorsCts),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_TX_HW_ERROR_CTS,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(TxHwErrorsCts),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_IN_ERRORS_CTS,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(InErrorsCts),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_OUT_ERROR_CTS,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(OutErrorsCts),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_ERR_RECOVERY_CTS,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(ErrRecoveryCts),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_SYSUPTIME,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(SysUpTime),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_SENSOR_NUMBER,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(SensorNumber),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_SENSOR_INDEX,
+- SK_PNMI_SENSOR_ENTRIES,
+- sizeof(SK_PNMI_SENSOR),
+- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorIndex),
+- SK_PNMI_RO, SensorStat, 0},
+- {OID_SKGE_SENSOR_DESCR,
+- SK_PNMI_SENSOR_ENTRIES,
+- sizeof(SK_PNMI_SENSOR),
+- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorDescr),
+- SK_PNMI_RO, SensorStat, 0},
+- {OID_SKGE_SENSOR_TYPE,
+- SK_PNMI_SENSOR_ENTRIES,
+- sizeof(SK_PNMI_SENSOR),
+- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorType),
+- SK_PNMI_RO, SensorStat, 0},
+- {OID_SKGE_SENSOR_VALUE,
+- SK_PNMI_SENSOR_ENTRIES,
+- sizeof(SK_PNMI_SENSOR),
+- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorValue),
+- SK_PNMI_RO, SensorStat, 0},
+- {OID_SKGE_SENSOR_WAR_THRES_LOW,
+- SK_PNMI_SENSOR_ENTRIES,
+- sizeof(SK_PNMI_SENSOR),
+- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdLow),
+- SK_PNMI_RO, SensorStat, 0},
+- {OID_SKGE_SENSOR_WAR_THRES_UPP,
+- SK_PNMI_SENSOR_ENTRIES,
+- sizeof(SK_PNMI_SENSOR),
+- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdHigh),
+- SK_PNMI_RO, SensorStat, 0},
+- {OID_SKGE_SENSOR_ERR_THRES_LOW,
+- SK_PNMI_SENSOR_ENTRIES,
+- sizeof(SK_PNMI_SENSOR),
+- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdLow),
+- SK_PNMI_RO, SensorStat, 0},
+- {OID_SKGE_SENSOR_ERR_THRES_UPP,
+- SK_PNMI_SENSOR_ENTRIES,
+- sizeof(SK_PNMI_SENSOR),
+- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdHigh),
+- SK_PNMI_RO, SensorStat, 0},
+- {OID_SKGE_SENSOR_STATUS,
+- SK_PNMI_SENSOR_ENTRIES,
+- sizeof(SK_PNMI_SENSOR),
+- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorStatus),
+- SK_PNMI_RO, SensorStat, 0},
+- {OID_SKGE_SENSOR_WAR_CTS,
+- SK_PNMI_SENSOR_ENTRIES,
+- sizeof(SK_PNMI_SENSOR),
+- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningCts),
+- SK_PNMI_RO, SensorStat, 0},
+- {OID_SKGE_SENSOR_ERR_CTS,
+- SK_PNMI_SENSOR_ENTRIES,
+- sizeof(SK_PNMI_SENSOR),
+- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorCts),
+- SK_PNMI_RO, SensorStat, 0},
+- {OID_SKGE_SENSOR_WAR_TIME,
+- SK_PNMI_SENSOR_ENTRIES,
+- sizeof(SK_PNMI_SENSOR),
+- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningTimestamp),
+- SK_PNMI_RO, SensorStat, 0},
+- {OID_SKGE_SENSOR_ERR_TIME,
+- SK_PNMI_SENSOR_ENTRIES,
+- sizeof(SK_PNMI_SENSOR),
+- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorTimestamp),
+- SK_PNMI_RO, SensorStat, 0},
+- {OID_SKGE_CHKSM_NUMBER,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(ChecksumNumber),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_CHKSM_RX_OK_CTS,
+- SKCS_NUM_PROTOCOLS,
+- sizeof(SK_PNMI_CHECKSUM),
+- SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxOkCts),
+- SK_PNMI_RO, CsumStat, 0},
+- {OID_SKGE_CHKSM_RX_UNABLE_CTS,
+- SKCS_NUM_PROTOCOLS,
+- sizeof(SK_PNMI_CHECKSUM),
+- SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxUnableCts),
+- SK_PNMI_RO, CsumStat, 0},
+- {OID_SKGE_CHKSM_RX_ERR_CTS,
+- SKCS_NUM_PROTOCOLS,
+- sizeof(SK_PNMI_CHECKSUM),
+- SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxErrCts),
+- SK_PNMI_RO, CsumStat, 0},
+- {OID_SKGE_CHKSM_TX_OK_CTS,
+- SKCS_NUM_PROTOCOLS,
+- sizeof(SK_PNMI_CHECKSUM),
+- SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxOkCts),
+- SK_PNMI_RO, CsumStat, 0},
+- {OID_SKGE_CHKSM_TX_UNABLE_CTS,
+- SKCS_NUM_PROTOCOLS,
+- sizeof(SK_PNMI_CHECKSUM),
+- SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxUnableCts),
+- SK_PNMI_RO, CsumStat, 0},
+- {OID_SKGE_STAT_TX,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOkCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX},
+- {OID_SKGE_STAT_TX_OCTETS,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOctetsOkCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_OCTET},
+- {OID_SKGE_STAT_TX_BROADCAST,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBroadcastOkCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BROADCAST},
+- {OID_SKGE_STAT_TX_MULTICAST,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMulticastOkCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTICAST},
+- {OID_SKGE_STAT_TX_UNICAST,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUnicastOkCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNICAST},
+- {OID_SKGE_STAT_TX_LONGFRAMES,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLongFramesCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LONGFRAMES},
+- {OID_SKGE_STAT_TX_BURST,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBurstCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BURST},
+- {OID_SKGE_STAT_TX_PFLOWC,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxPauseMacCtrlCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_PMACC},
+- {OID_SKGE_STAT_TX_FLOWC,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMacCtrlCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MACC},
+- {OID_SKGE_STAT_TX_SINGLE_COL,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSingleCollisionCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SINGLE_COL},
+- {OID_SKGE_STAT_TX_MULTI_COL,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMultipleCollisionCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTI_COL},
+- {OID_SKGE_STAT_TX_EXCESS_COL,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveCollisionCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_COL},
+- {OID_SKGE_STAT_TX_LATE_COL,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLateCollisionCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LATE_COL},
+- {OID_SKGE_STAT_TX_DEFFERAL,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxDeferralCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_DEFFERAL},
+- {OID_SKGE_STAT_TX_EXCESS_DEF,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveDeferralCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_DEF},
+- {OID_SKGE_STAT_TX_UNDERRUN,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxFifoUnderrunCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNDERRUN},
+- {OID_SKGE_STAT_TX_CARRIER,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxCarrierCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_CARRIER},
+-/* {OID_SKGE_STAT_TX_UTIL,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUtilization),
+- SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */
+- {OID_SKGE_STAT_TX_64,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx64Cts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_64},
+- {OID_SKGE_STAT_TX_127,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx127Cts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_127},
+- {OID_SKGE_STAT_TX_255,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx255Cts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_255},
+- {OID_SKGE_STAT_TX_511,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx511Cts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_511},
+- {OID_SKGE_STAT_TX_1023,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx1023Cts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_1023},
+- {OID_SKGE_STAT_TX_MAX,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMaxCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MAX},
+- {OID_SKGE_STAT_TX_SYNC,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC},
+- {OID_SKGE_STAT_TX_SYNC_OCTETS,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncOctetsCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC_OCTET},
+- {OID_SKGE_STAT_RX,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOkCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX},
+- {OID_SKGE_STAT_RX_OCTETS,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOctetsOkCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OCTET},
+- {OID_SKGE_STAT_RX_BROADCAST,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBroadcastOkCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BROADCAST},
+- {OID_SKGE_STAT_RX_MULTICAST,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMulticastOkCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MULTICAST},
+- {OID_SKGE_STAT_RX_UNICAST,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUnicastOkCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_UNICAST},
+- {OID_SKGE_STAT_RX_LONGFRAMES,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxLongFramesCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_LONGFRAMES},
+- {OID_SKGE_STAT_RX_PFLOWC,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC},
+- {OID_SKGE_STAT_RX_FLOWC,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC},
+- {OID_SKGE_STAT_RX_PFLOWC_ERR,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlErrorCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC_ERR},
+- {OID_SKGE_STAT_RX_FLOWC_UNKWN,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlUnknownCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC_UNKWN},
+- {OID_SKGE_STAT_RX_BURST,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBurstCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BURST},
+- {OID_SKGE_STAT_RX_MISSED,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMissedCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MISSED},
+- {OID_SKGE_STAT_RX_FRAMING,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFramingCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FRAMING},
+- {OID_SKGE_STAT_RX_OVERFLOW,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFifoOverflowCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OVERFLOW},
+- {OID_SKGE_STAT_RX_JABBER,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxJabberCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_JABBER},
+- {OID_SKGE_STAT_RX_CARRIER,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCarrierCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CARRIER},
+- {OID_SKGE_STAT_RX_IR_LENGTH,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxIRLengthCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_IRLENGTH},
+- {OID_SKGE_STAT_RX_SYMBOL,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxSymbolCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SYMBOL},
+- {OID_SKGE_STAT_RX_SHORTS,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxShortsCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SHORTS},
+- {OID_SKGE_STAT_RX_RUNT,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxRuntCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_RUNT},
+- {OID_SKGE_STAT_RX_CEXT,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCextCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CEXT},
+- {OID_SKGE_STAT_RX_TOO_LONG,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxTooLongCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_TOO_LONG},
+- {OID_SKGE_STAT_RX_FCS,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFcsCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FCS},
+-/* {OID_SKGE_STAT_RX_UTIL,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUtilization),
+- SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */
+- {OID_SKGE_STAT_RX_64,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx64Cts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_64},
+- {OID_SKGE_STAT_RX_127,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx127Cts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_127},
+- {OID_SKGE_STAT_RX_255,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx255Cts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_255},
+- {OID_SKGE_STAT_RX_511,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx511Cts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_511},
+- {OID_SKGE_STAT_RX_1023,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx1023Cts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_1023},
+- {OID_SKGE_STAT_RX_MAX,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_STAT),
+- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMaxCts),
+- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MAX},
+- {OID_SKGE_PHYS_CUR_ADDR,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_CONF),
+- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacCurrentAddr),
+- SK_PNMI_RW, Addr, 0},
+- {OID_SKGE_PHYS_FAC_ADDR,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_CONF),
+- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacFactoryAddr),
+- SK_PNMI_RO, Addr, 0},
+- {OID_SKGE_PMD,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_CONF),
+- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPMD),
+- SK_PNMI_RO, MacPrivateConf, 0},
+- {OID_SKGE_CONNECTOR,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_CONF),
+- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfConnector),
+- SK_PNMI_RO, MacPrivateConf, 0},
+- {OID_SKGE_PHY_TYPE,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_CONF),
+- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyType),
+- SK_PNMI_RO, MacPrivateConf, 0},
+- {OID_SKGE_LINK_CAP,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_CONF),
+- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkCapability),
+- SK_PNMI_RO, MacPrivateConf, 0},
+- {OID_SKGE_LINK_MODE,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_CONF),
+- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkMode),
+- SK_PNMI_RW, MacPrivateConf, 0},
+- {OID_SKGE_LINK_MODE_STATUS,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_CONF),
+- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkModeStatus),
+- SK_PNMI_RO, MacPrivateConf, 0},
+- {OID_SKGE_LINK_STATUS,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_CONF),
+- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkStatus),
+- SK_PNMI_RO, MacPrivateConf, 0},
+- {OID_SKGE_FLOWCTRL_CAP,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_CONF),
+- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlCapability),
+- SK_PNMI_RO, MacPrivateConf, 0},
+- {OID_SKGE_FLOWCTRL_MODE,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_CONF),
+- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlMode),
+- SK_PNMI_RW, MacPrivateConf, 0},
+- {OID_SKGE_FLOWCTRL_STATUS,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_CONF),
+- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlStatus),
+- SK_PNMI_RO, MacPrivateConf, 0},
+- {OID_SKGE_PHY_OPERATION_CAP,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_CONF),
+- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationCapability),
+- SK_PNMI_RO, MacPrivateConf, 0},
+- {OID_SKGE_PHY_OPERATION_MODE,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_CONF),
+- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationMode),
+- SK_PNMI_RW, MacPrivateConf, 0},
+- {OID_SKGE_PHY_OPERATION_STATUS,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_CONF),
+- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationStatus),
+- SK_PNMI_RO, MacPrivateConf, 0},
+- {OID_SKGE_SPEED_CAP,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_CONF),
+- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedCapability),
+- SK_PNMI_RO, MacPrivateConf, 0},
+- {OID_SKGE_SPEED_MODE,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_CONF),
+- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedMode),
+- SK_PNMI_RW, MacPrivateConf, 0},
+- {OID_SKGE_SPEED_STATUS,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_CONF),
+- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedStatus),
+- SK_PNMI_RO, MacPrivateConf, 0},
+- {OID_SKGE_TRAP,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(Trap),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_TRAP_NUMBER,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(TrapNumber),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_RLMT_MODE,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(RlmtMode),
+- SK_PNMI_RW, Rlmt, 0},
+- {OID_SKGE_RLMT_PORT_NUMBER,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(RlmtPortNumber),
+- SK_PNMI_RO, Rlmt, 0},
+- {OID_SKGE_RLMT_PORT_ACTIVE,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(RlmtPortActive),
+- SK_PNMI_RO, Rlmt, 0},
+- {OID_SKGE_RLMT_PORT_PREFERRED,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(RlmtPortPreferred),
+- SK_PNMI_RW, Rlmt, 0},
+- {OID_SKGE_RLMT_CHANGE_CTS,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(RlmtChangeCts),
+- SK_PNMI_RO, Rlmt, 0},
+- {OID_SKGE_RLMT_CHANGE_TIME,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(RlmtChangeTime),
+- SK_PNMI_RO, Rlmt, 0},
+- {OID_SKGE_RLMT_CHANGE_ESTIM,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(RlmtChangeEstimate),
+- SK_PNMI_RO, Rlmt, 0},
+- {OID_SKGE_RLMT_CHANGE_THRES,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(RlmtChangeThreshold),
+- SK_PNMI_RW, Rlmt, 0},
+- {OID_SKGE_RLMT_PORT_INDEX,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_RLMT),
+- SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtIndex),
+- SK_PNMI_RO, RlmtStat, 0},
+- {OID_SKGE_RLMT_STATUS,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_RLMT),
+- SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtStatus),
+- SK_PNMI_RO, RlmtStat, 0},
+- {OID_SKGE_RLMT_TX_HELLO_CTS,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_RLMT),
+- SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxHelloCts),
+- SK_PNMI_RO, RlmtStat, 0},
+- {OID_SKGE_RLMT_RX_HELLO_CTS,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_RLMT),
+- SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxHelloCts),
+- SK_PNMI_RO, RlmtStat, 0},
+- {OID_SKGE_RLMT_TX_SP_REQ_CTS,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_RLMT),
+- SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxSpHelloReqCts),
+- SK_PNMI_RO, RlmtStat, 0},
+- {OID_SKGE_RLMT_RX_SP_CTS,
+- SK_PNMI_MAC_ENTRIES,
+- sizeof(SK_PNMI_RLMT),
+- SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxSpHelloCts),
+- SK_PNMI_RO, RlmtStat, 0},
+- {OID_SKGE_RLMT_MONITOR_NUMBER,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(RlmtMonitorNumber),
+- SK_PNMI_RO, General, 0},
+- {OID_SKGE_RLMT_MONITOR_INDEX,
+- SK_PNMI_MONITOR_ENTRIES,
+- sizeof(SK_PNMI_RLMT_MONITOR),
+- SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorIndex),
+- SK_PNMI_RO, Monitor, 0},
+- {OID_SKGE_RLMT_MONITOR_ADDR,
+- SK_PNMI_MONITOR_ENTRIES,
+- sizeof(SK_PNMI_RLMT_MONITOR),
+- SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAddr),
+- SK_PNMI_RO, Monitor, 0},
+- {OID_SKGE_RLMT_MONITOR_ERRS,
+- SK_PNMI_MONITOR_ENTRIES,
+- sizeof(SK_PNMI_RLMT_MONITOR),
+- SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorErrorCts),
+- SK_PNMI_RO, Monitor, 0},
+- {OID_SKGE_RLMT_MONITOR_TIMESTAMP,
+- SK_PNMI_MONITOR_ENTRIES,
+- sizeof(SK_PNMI_RLMT_MONITOR),
+- SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorTimestamp),
+- SK_PNMI_RO, Monitor, 0},
+- {OID_SKGE_RLMT_MONITOR_ADMIN,
+- SK_PNMI_MONITOR_ENTRIES,
+- sizeof(SK_PNMI_RLMT_MONITOR),
+- SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAdmin),
+- SK_PNMI_RW, Monitor, 0},
+- {OID_SKGE_MTU,
+- 1,
+- 0,
+- SK_PNMI_MAI_OFF(MtuSize),
+- SK_PNMI_RW, MacPrivateConf, 0},
+- {OID_SKGE_VCT_GET,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, Vct, 0},
+- {OID_SKGE_VCT_SET,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_WO, Vct, 0},
+- {OID_SKGE_VCT_STATUS,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, Vct, 0},
+- {OID_SKGE_BOARDLEVEL,
+- 0,
+- 0,
+- 0,
+- SK_PNMI_RO, General, 0},
+-};
+-
+diff --git a/drivers/net/sk98lin/skgepnmi.c b/drivers/net/sk98lin/skgepnmi.c
+deleted file mode 100644
+index 876bb21..0000000
+--- a/drivers/net/sk98lin/skgepnmi.c
++++ /dev/null
+@@ -1,8198 +0,0 @@
+-/*****************************************************************************
+- *
+- * Name: skgepnmi.c
+- * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.111 $
+- * Date: $Date: 2003/09/15 13:35:35 $
+- * Purpose: Private Network Management Interface
+- *
+- ****************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-
+-#ifndef _lint
+-static const char SysKonnectFileId[] =
+- "@(#) $Id: skgepnmi.c,v 1.111 2003/09/15 13:35:35 tschilli Exp $ (C) Marvell.";
+-#endif /* !_lint */
+-
+-#include "h/skdrv1st.h"
+-#include "h/sktypes.h"
+-#include "h/xmac_ii.h"
+-#include "h/skdebug.h"
+-#include "h/skqueue.h"
+-#include "h/skgepnmi.h"
+-#include "h/skgesirq.h"
+-#include "h/skcsum.h"
+-#include "h/skvpd.h"
+-#include "h/skgehw.h"
+-#include "h/skgeinit.h"
+-#include "h/skdrv2nd.h"
+-#include "h/skgepnm2.h"
+-#ifdef SK_POWER_MGMT
+-#include "h/skgepmgt.h"
+-#endif
+-/* defines *******************************************************************/
+-
+-#ifndef DEBUG
+-#define PNMI_STATIC static
+-#else /* DEBUG */
+-#define PNMI_STATIC
+-#endif /* DEBUG */
+-
+-/*
+- * Public Function prototypes
+- */
+-int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int level);
+-int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf,
+- unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
+-int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
+- unsigned int *pLen, SK_U32 NetIndex);
+-int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
+- unsigned int *pLen, SK_U32 NetIndex);
+-int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
+- unsigned int *pLen, SK_U32 NetIndex);
+-int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Param);
+-int SkPnmiGenIoctl(SK_AC *pAC, SK_IOC IoC, void * pBuf,
+- unsigned int * pLen, SK_U32 NetIndex);
+-
+-
+-/*
+- * Private Function prototypes
+- */
+-
+-PNMI_STATIC SK_U8 CalculateLinkModeStatus(SK_AC *pAC, SK_IOC IoC, unsigned int
+- PhysPortIndex);
+-PNMI_STATIC SK_U8 CalculateLinkStatus(SK_AC *pAC, SK_IOC IoC, unsigned int
+- PhysPortIndex);
+-PNMI_STATIC void CopyMac(char *pDst, SK_MAC_ADDR *pMac);
+-PNMI_STATIC void CopyTrapQueue(SK_AC *pAC, char *pDstBuf);
+-PNMI_STATIC SK_U64 GetPhysStatVal(SK_AC *pAC, SK_IOC IoC,
+- unsigned int PhysPortIndex, unsigned int StatIndex);
+-PNMI_STATIC SK_U64 GetStatVal(SK_AC *pAC, SK_IOC IoC, unsigned int LogPortIndex,
+- unsigned int StatIndex, SK_U32 NetIndex);
+-PNMI_STATIC char* GetTrapEntry(SK_AC *pAC, SK_U32 TrapId, unsigned int Size);
+-PNMI_STATIC void GetTrapQueueLen(SK_AC *pAC, unsigned int *pLen,
+- unsigned int *pEntries);
+-PNMI_STATIC int GetVpdKeyArr(SK_AC *pAC, SK_IOC IoC, char *pKeyArr,
+- unsigned int KeyArrLen, unsigned int *pKeyNo);
+-PNMI_STATIC int LookupId(SK_U32 Id);
+-PNMI_STATIC int MacUpdate(SK_AC *pAC, SK_IOC IoC, unsigned int FirstMac,
+- unsigned int LastMac);
+-PNMI_STATIC int PnmiStruct(SK_AC *pAC, SK_IOC IoC, int Action, char *pBuf,
+- unsigned int *pLen, SK_U32 NetIndex);
+-PNMI_STATIC int PnmiVar(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id,
+- char *pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
+-PNMI_STATIC void QueueRlmtNewMacTrap(SK_AC *pAC, unsigned int ActiveMac);
+-PNMI_STATIC void QueueRlmtPortTrap(SK_AC *pAC, SK_U32 TrapId,
+- unsigned int PortIndex);
+-PNMI_STATIC void QueueSensorTrap(SK_AC *pAC, SK_U32 TrapId,
+- unsigned int SensorIndex);
+-PNMI_STATIC void QueueSimpleTrap(SK_AC *pAC, SK_U32 TrapId);
+-PNMI_STATIC void ResetCounter(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex);
+-PNMI_STATIC int RlmtUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex);
+-PNMI_STATIC int SirqUpdate(SK_AC *pAC, SK_IOC IoC);
+-PNMI_STATIC void VirtualConf(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, char *pBuf);
+-PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id, char *pBuf,
+- unsigned int *pLen, SK_U32 Instance, unsigned int TableIndex, SK_U32 NetIndex);
+-PNMI_STATIC void CheckVctStatus(SK_AC *, SK_IOC, char *, SK_U32, SK_U32);
+-
+-/*
+- * Table to correlate OID with handler function and index to
+- * hardware register stored in StatAddress if applicable.
+- */
+-#include "skgemib.c"
+-
+-/* global variables **********************************************************/
+-
+-/*
+- * Overflow status register bit table and corresponding counter
+- * dependent on MAC type - the number relates to the size of overflow
+- * mask returned by the pFnMacOverflow function
+- */
+-PNMI_STATIC const SK_U16 StatOvrflwBit[][SK_PNMI_MAC_TYPES] = {
+-/* Bit0 */ { SK_PNMI_HTX, SK_PNMI_HTX_UNICAST},
+-/* Bit1 */ { SK_PNMI_HTX_OCTETHIGH, SK_PNMI_HTX_BROADCAST},
+-/* Bit2 */ { SK_PNMI_HTX_OCTETLOW, SK_PNMI_HTX_PMACC},
+-/* Bit3 */ { SK_PNMI_HTX_BROADCAST, SK_PNMI_HTX_MULTICAST},
+-/* Bit4 */ { SK_PNMI_HTX_MULTICAST, SK_PNMI_HTX_OCTETLOW},
+-/* Bit5 */ { SK_PNMI_HTX_UNICAST, SK_PNMI_HTX_OCTETHIGH},
+-/* Bit6 */ { SK_PNMI_HTX_LONGFRAMES, SK_PNMI_HTX_64},
+-/* Bit7 */ { SK_PNMI_HTX_BURST, SK_PNMI_HTX_127},
+-/* Bit8 */ { SK_PNMI_HTX_PMACC, SK_PNMI_HTX_255},
+-/* Bit9 */ { SK_PNMI_HTX_MACC, SK_PNMI_HTX_511},
+-/* Bit10 */ { SK_PNMI_HTX_SINGLE_COL, SK_PNMI_HTX_1023},
+-/* Bit11 */ { SK_PNMI_HTX_MULTI_COL, SK_PNMI_HTX_MAX},
+-/* Bit12 */ { SK_PNMI_HTX_EXCESS_COL, SK_PNMI_HTX_LONGFRAMES},
+-/* Bit13 */ { SK_PNMI_HTX_LATE_COL, SK_PNMI_HTX_RESERVED},
+-/* Bit14 */ { SK_PNMI_HTX_DEFFERAL, SK_PNMI_HTX_COL},
+-/* Bit15 */ { SK_PNMI_HTX_EXCESS_DEF, SK_PNMI_HTX_LATE_COL},
+-/* Bit16 */ { SK_PNMI_HTX_UNDERRUN, SK_PNMI_HTX_EXCESS_COL},
+-/* Bit17 */ { SK_PNMI_HTX_CARRIER, SK_PNMI_HTX_MULTI_COL},
+-/* Bit18 */ { SK_PNMI_HTX_UTILUNDER, SK_PNMI_HTX_SINGLE_COL},
+-/* Bit19 */ { SK_PNMI_HTX_UTILOVER, SK_PNMI_HTX_UNDERRUN},
+-/* Bit20 */ { SK_PNMI_HTX_64, SK_PNMI_HTX_RESERVED},
+-/* Bit21 */ { SK_PNMI_HTX_127, SK_PNMI_HTX_RESERVED},
+-/* Bit22 */ { SK_PNMI_HTX_255, SK_PNMI_HTX_RESERVED},
+-/* Bit23 */ { SK_PNMI_HTX_511, SK_PNMI_HTX_RESERVED},
+-/* Bit24 */ { SK_PNMI_HTX_1023, SK_PNMI_HTX_RESERVED},
+-/* Bit25 */ { SK_PNMI_HTX_MAX, SK_PNMI_HTX_RESERVED},
+-/* Bit26 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
+-/* Bit27 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
+-/* Bit28 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
+-/* Bit29 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
+-/* Bit30 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
+-/* Bit31 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
+-/* Bit32 */ { SK_PNMI_HRX, SK_PNMI_HRX_UNICAST},
+-/* Bit33 */ { SK_PNMI_HRX_OCTETHIGH, SK_PNMI_HRX_BROADCAST},
+-/* Bit34 */ { SK_PNMI_HRX_OCTETLOW, SK_PNMI_HRX_PMACC},
+-/* Bit35 */ { SK_PNMI_HRX_BROADCAST, SK_PNMI_HRX_MULTICAST},
+-/* Bit36 */ { SK_PNMI_HRX_MULTICAST, SK_PNMI_HRX_FCS},
+-/* Bit37 */ { SK_PNMI_HRX_UNICAST, SK_PNMI_HRX_RESERVED},
+-/* Bit38 */ { SK_PNMI_HRX_PMACC, SK_PNMI_HRX_OCTETLOW},
+-/* Bit39 */ { SK_PNMI_HRX_MACC, SK_PNMI_HRX_OCTETHIGH},
+-/* Bit40 */ { SK_PNMI_HRX_PMACC_ERR, SK_PNMI_HRX_BADOCTETLOW},
+-/* Bit41 */ { SK_PNMI_HRX_MACC_UNKWN, SK_PNMI_HRX_BADOCTETHIGH},
+-/* Bit42 */ { SK_PNMI_HRX_BURST, SK_PNMI_HRX_UNDERSIZE},
+-/* Bit43 */ { SK_PNMI_HRX_MISSED, SK_PNMI_HRX_RUNT},
+-/* Bit44 */ { SK_PNMI_HRX_FRAMING, SK_PNMI_HRX_64},
+-/* Bit45 */ { SK_PNMI_HRX_OVERFLOW, SK_PNMI_HRX_127},
+-/* Bit46 */ { SK_PNMI_HRX_JABBER, SK_PNMI_HRX_255},
+-/* Bit47 */ { SK_PNMI_HRX_CARRIER, SK_PNMI_HRX_511},
+-/* Bit48 */ { SK_PNMI_HRX_IRLENGTH, SK_PNMI_HRX_1023},
+-/* Bit49 */ { SK_PNMI_HRX_SYMBOL, SK_PNMI_HRX_MAX},
+-/* Bit50 */ { SK_PNMI_HRX_SHORTS, SK_PNMI_HRX_LONGFRAMES},
+-/* Bit51 */ { SK_PNMI_HRX_RUNT, SK_PNMI_HRX_TOO_LONG},
+-/* Bit52 */ { SK_PNMI_HRX_TOO_LONG, SK_PNMI_HRX_JABBER},
+-/* Bit53 */ { SK_PNMI_HRX_FCS, SK_PNMI_HRX_RESERVED},
+-/* Bit54 */ { SK_PNMI_HRX_RESERVED, SK_PNMI_HRX_OVERFLOW},
+-/* Bit55 */ { SK_PNMI_HRX_CEXT, SK_PNMI_HRX_RESERVED},
+-/* Bit56 */ { SK_PNMI_HRX_UTILUNDER, SK_PNMI_HRX_RESERVED},
+-/* Bit57 */ { SK_PNMI_HRX_UTILOVER, SK_PNMI_HRX_RESERVED},
+-/* Bit58 */ { SK_PNMI_HRX_64, SK_PNMI_HRX_RESERVED},
+-/* Bit59 */ { SK_PNMI_HRX_127, SK_PNMI_HRX_RESERVED},
+-/* Bit60 */ { SK_PNMI_HRX_255, SK_PNMI_HRX_RESERVED},
+-/* Bit61 */ { SK_PNMI_HRX_511, SK_PNMI_HRX_RESERVED},
+-/* Bit62 */ { SK_PNMI_HRX_1023, SK_PNMI_HRX_RESERVED},
+-/* Bit63 */ { SK_PNMI_HRX_MAX, SK_PNMI_HRX_RESERVED}
+-};
+-
+-/*
+- * Table for hardware register saving on resets and port switches
+- */
+-PNMI_STATIC const SK_PNMI_STATADDR StatAddr[SK_PNMI_MAX_IDX][SK_PNMI_MAC_TYPES] = {
+- /* SK_PNMI_HTX */
+- {{XM_TXF_OK, SK_TRUE}, {0, SK_FALSE}},
+- /* SK_PNMI_HTX_OCTETHIGH */
+- {{XM_TXO_OK_HI, SK_TRUE}, {GM_TXO_OK_HI, SK_TRUE}},
+- /* SK_PNMI_HTX_OCTETLOW */
+- {{XM_TXO_OK_LO, SK_FALSE}, {GM_TXO_OK_LO, SK_FALSE}},
+- /* SK_PNMI_HTX_BROADCAST */
+- {{XM_TXF_BC_OK, SK_TRUE}, {GM_TXF_BC_OK, SK_TRUE}},
+- /* SK_PNMI_HTX_MULTICAST */
+- {{XM_TXF_MC_OK, SK_TRUE}, {GM_TXF_MC_OK, SK_TRUE}},
+- /* SK_PNMI_HTX_UNICAST */
+- {{XM_TXF_UC_OK, SK_TRUE}, {GM_TXF_UC_OK, SK_TRUE}},
+- /* SK_PNMI_HTX_BURST */
+- {{XM_TXE_BURST, SK_TRUE}, {0, SK_FALSE}},
+- /* SK_PNMI_HTX_PMACC */
+- {{XM_TXF_MPAUSE, SK_TRUE}, {GM_TXF_MPAUSE, SK_TRUE}},
+- /* SK_PNMI_HTX_MACC */
+- {{XM_TXF_MCTRL, SK_TRUE}, {0, SK_FALSE}},
+- /* SK_PNMI_HTX_COL */
+- {{0, SK_FALSE}, {GM_TXF_COL, SK_TRUE}},
+- /* SK_PNMI_HTX_SINGLE_COL */
+- {{XM_TXF_SNG_COL, SK_TRUE}, {GM_TXF_SNG_COL, SK_TRUE}},
+- /* SK_PNMI_HTX_MULTI_COL */
+- {{XM_TXF_MUL_COL, SK_TRUE}, {GM_TXF_MUL_COL, SK_TRUE}},
+- /* SK_PNMI_HTX_EXCESS_COL */
+- {{XM_TXF_ABO_COL, SK_TRUE}, {GM_TXF_ABO_COL, SK_TRUE}},
+- /* SK_PNMI_HTX_LATE_COL */
+- {{XM_TXF_LAT_COL, SK_TRUE}, {GM_TXF_LAT_COL, SK_TRUE}},
+- /* SK_PNMI_HTX_DEFFERAL */
+- {{XM_TXF_DEF, SK_TRUE}, {0, SK_FALSE}},
+- /* SK_PNMI_HTX_EXCESS_DEF */
+- {{XM_TXF_EX_DEF, SK_TRUE}, {0, SK_FALSE}},
+- /* SK_PNMI_HTX_UNDERRUN */
+- {{XM_TXE_FIFO_UR, SK_TRUE}, {GM_TXE_FIFO_UR, SK_TRUE}},
+- /* SK_PNMI_HTX_CARRIER */
+- {{XM_TXE_CS_ERR, SK_TRUE}, {0, SK_FALSE}},
+- /* SK_PNMI_HTX_UTILUNDER */
+- {{0, SK_FALSE}, {0, SK_FALSE}},
+- /* SK_PNMI_HTX_UTILOVER */
+- {{0, SK_FALSE}, {0, SK_FALSE}},
+- /* SK_PNMI_HTX_64 */
+- {{XM_TXF_64B, SK_TRUE}, {GM_TXF_64B, SK_TRUE}},
+- /* SK_PNMI_HTX_127 */
+- {{XM_TXF_127B, SK_TRUE}, {GM_TXF_127B, SK_TRUE}},
+- /* SK_PNMI_HTX_255 */
+- {{XM_TXF_255B, SK_TRUE}, {GM_TXF_255B, SK_TRUE}},
+- /* SK_PNMI_HTX_511 */
+- {{XM_TXF_511B, SK_TRUE}, {GM_TXF_511B, SK_TRUE}},
+- /* SK_PNMI_HTX_1023 */
+- {{XM_TXF_1023B, SK_TRUE}, {GM_TXF_1023B, SK_TRUE}},
+- /* SK_PNMI_HTX_MAX */
+- {{XM_TXF_MAX_SZ, SK_TRUE}, {GM_TXF_1518B, SK_TRUE}},
+- /* SK_PNMI_HTX_LONGFRAMES */
+- {{XM_TXF_LONG, SK_TRUE}, {GM_TXF_MAX_SZ, SK_TRUE}},
+- /* SK_PNMI_HTX_SYNC */
+- {{0, SK_FALSE}, {0, SK_FALSE}},
+- /* SK_PNMI_HTX_SYNC_OCTET */
+- {{0, SK_FALSE}, {0, SK_FALSE}},
+- /* SK_PNMI_HTX_RESERVED */
+- {{0, SK_FALSE}, {0, SK_FALSE}},
+- /* SK_PNMI_HRX */
+- {{XM_RXF_OK, SK_TRUE}, {0, SK_FALSE}},
+- /* SK_PNMI_HRX_OCTETHIGH */
+- {{XM_RXO_OK_HI, SK_TRUE}, {GM_RXO_OK_HI, SK_TRUE}},
+- /* SK_PNMI_HRX_OCTETLOW */
+- {{XM_RXO_OK_LO, SK_FALSE}, {GM_RXO_OK_LO, SK_FALSE}},
+- /* SK_PNMI_HRX_BADOCTETHIGH */
+- {{0, SK_FALSE}, {GM_RXO_ERR_HI, SK_TRUE}},
+- /* SK_PNMI_HRX_BADOCTETLOW */
+- {{0, SK_FALSE}, {GM_RXO_ERR_LO, SK_TRUE}},
+- /* SK_PNMI_HRX_BROADCAST */
+- {{XM_RXF_BC_OK, SK_TRUE}, {GM_RXF_BC_OK, SK_TRUE}},
+- /* SK_PNMI_HRX_MULTICAST */
+- {{XM_RXF_MC_OK, SK_TRUE}, {GM_RXF_MC_OK, SK_TRUE}},
+- /* SK_PNMI_HRX_UNICAST */
+- {{XM_RXF_UC_OK, SK_TRUE}, {GM_RXF_UC_OK, SK_TRUE}},
+- /* SK_PNMI_HRX_PMACC */
+- {{XM_RXF_MPAUSE, SK_TRUE}, {GM_RXF_MPAUSE, SK_TRUE}},
+- /* SK_PNMI_HRX_MACC */
+- {{XM_RXF_MCTRL, SK_TRUE}, {0, SK_FALSE}},
+- /* SK_PNMI_HRX_PMACC_ERR */
+- {{XM_RXF_INV_MP, SK_TRUE}, {0, SK_FALSE}},
+- /* SK_PNMI_HRX_MACC_UNKWN */
+- {{XM_RXF_INV_MOC, SK_TRUE}, {0, SK_FALSE}},
+- /* SK_PNMI_HRX_BURST */
+- {{XM_RXE_BURST, SK_TRUE}, {0, SK_FALSE}},
+- /* SK_PNMI_HRX_MISSED */
+- {{XM_RXE_FMISS, SK_TRUE}, {0, SK_FALSE}},
+- /* SK_PNMI_HRX_FRAMING */
+- {{XM_RXF_FRA_ERR, SK_TRUE}, {0, SK_FALSE}},
+- /* SK_PNMI_HRX_UNDERSIZE */
+- {{0, SK_FALSE}, {GM_RXF_SHT, SK_TRUE}},
+- /* SK_PNMI_HRX_OVERFLOW */
+- {{XM_RXE_FIFO_OV, SK_TRUE}, {GM_RXE_FIFO_OV, SK_TRUE}},
+- /* SK_PNMI_HRX_JABBER */
+- {{XM_RXF_JAB_PKT, SK_TRUE}, {GM_RXF_JAB_PKT, SK_TRUE}},
+- /* SK_PNMI_HRX_CARRIER */
+- {{XM_RXE_CAR_ERR, SK_TRUE}, {0, SK_FALSE}},
+- /* SK_PNMI_HRX_IRLENGTH */
+- {{XM_RXF_LEN_ERR, SK_TRUE}, {0, SK_FALSE}},
+- /* SK_PNMI_HRX_SYMBOL */
+- {{XM_RXE_SYM_ERR, SK_TRUE}, {0, SK_FALSE}},
+- /* SK_PNMI_HRX_SHORTS */
+- {{XM_RXE_SHT_ERR, SK_TRUE}, {0, SK_FALSE}},
+- /* SK_PNMI_HRX_RUNT */
+- {{XM_RXE_RUNT, SK_TRUE}, {GM_RXE_FRAG, SK_TRUE}},
+- /* SK_PNMI_HRX_TOO_LONG */
+- {{XM_RXF_LNG_ERR, SK_TRUE}, {GM_RXF_LNG_ERR, SK_TRUE}},
+- /* SK_PNMI_HRX_FCS */
+- {{XM_RXF_FCS_ERR, SK_TRUE}, {GM_RXF_FCS_ERR, SK_TRUE}},
+- /* SK_PNMI_HRX_CEXT */
+- {{XM_RXF_CEX_ERR, SK_TRUE}, {0, SK_FALSE}},
+- /* SK_PNMI_HRX_UTILUNDER */
+- {{0, SK_FALSE}, {0, SK_FALSE}},
+- /* SK_PNMI_HRX_UTILOVER */
+- {{0, SK_FALSE}, {0, SK_FALSE}},
+- /* SK_PNMI_HRX_64 */
+- {{XM_RXF_64B, SK_TRUE}, {GM_RXF_64B, SK_TRUE}},
+- /* SK_PNMI_HRX_127 */
+- {{XM_RXF_127B, SK_TRUE}, {GM_RXF_127B, SK_TRUE}},
+- /* SK_PNMI_HRX_255 */
+- {{XM_RXF_255B, SK_TRUE}, {GM_RXF_255B, SK_TRUE}},
+- /* SK_PNMI_HRX_511 */
+- {{XM_RXF_511B, SK_TRUE}, {GM_RXF_511B, SK_TRUE}},
+- /* SK_PNMI_HRX_1023 */
+- {{XM_RXF_1023B, SK_TRUE}, {GM_RXF_1023B, SK_TRUE}},
+- /* SK_PNMI_HRX_MAX */
+- {{XM_RXF_MAX_SZ, SK_TRUE}, {GM_RXF_1518B, SK_TRUE}},
+- /* SK_PNMI_HRX_LONGFRAMES */
+- {{0, SK_FALSE}, {GM_RXF_MAX_SZ, SK_TRUE}},
+- /* SK_PNMI_HRX_RESERVED */
+- {{0, SK_FALSE}, {0, SK_FALSE}}
+-};
+-
+-
+-/*****************************************************************************
+- *
+- * Public functions
+- *
+- */
+-
+-/*****************************************************************************
+- *
+- * SkPnmiInit - Init function of PNMI
+- *
+- * Description:
+- * SK_INIT_DATA: Initialises the data structures
+- * SK_INIT_IO: Resets the XMAC statistics, determines the device and
+- * connector type.
+- * SK_INIT_RUN: Starts a timer event for port switch per hour
+- * calculation.
+- *
+- * Returns:
+- * Always 0
+- */
+-int SkPnmiInit(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-int Level) /* Initialization level */
+-{
+- unsigned int PortMax; /* Number of ports */
+- unsigned int PortIndex; /* Current port index in loop */
+- SK_U16 Val16; /* Multiple purpose 16 bit variable */
+- SK_U8 Val8; /* Mulitple purpose 8 bit variable */
+- SK_EVPARA EventParam; /* Event struct for timer event */
+- SK_PNMI_VCT *pVctBackupData;
+-
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+- ("PNMI: SkPnmiInit: Called, level=%d\n", Level));
+-
+- switch (Level) {
+-
+- case SK_INIT_DATA:
+- SK_MEMSET((char *)&pAC->Pnmi, 0, sizeof(pAC->Pnmi));
+- pAC->Pnmi.TrapBufFree = SK_PNMI_TRAP_QUEUE_LEN;
+- pAC->Pnmi.StartUpTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
+- pAC->Pnmi.RlmtChangeThreshold = SK_PNMI_DEF_RLMT_CHG_THRES;
+- for (PortIndex = 0; PortIndex < SK_MAX_MACS; PortIndex ++) {
+-
+- pAC->Pnmi.Port[PortIndex].ActiveFlag = SK_FALSE;
+- pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
+- }
+-
+-#ifdef SK_PNMI_CHECK
+- if (SK_PNMI_MAX_IDX != SK_PNMI_CNT_NO) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR049, SK_PNMI_ERR049MSG);
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL,
+- ("CounterOffset struct size (%d) differs from "
+- "SK_PNMI_MAX_IDX (%d)\n",
+- SK_PNMI_CNT_NO, SK_PNMI_MAX_IDX));
+- }
+-
+-#endif /* SK_PNMI_CHECK */
+- break;
+-
+- case SK_INIT_IO:
+- /*
+- * Reset MAC counters
+- */
+- PortMax = pAC->GIni.GIMacsFound;
+-
+- for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) {
+-
+- pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PortIndex);
+- }
+-
+- /* Initialize DSP variables for Vct() to 0xff => Never written! */
+- for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) {
+- pAC->GIni.GP[PortIndex].PCableLen = 0xff;
+- pVctBackupData = &pAC->Pnmi.VctBackup[PortIndex];
+- pVctBackupData->PCableLen = 0xff;
+- }
+-
+- /*
+- * Get pci bus speed
+- */
+- SK_IN16(IoC, B0_CTST, &Val16);
+- if ((Val16 & CS_BUS_CLOCK) == 0) {
+-
+- pAC->Pnmi.PciBusSpeed = 33;
+- }
+- else {
+- pAC->Pnmi.PciBusSpeed = 66;
+- }
+-
+- /*
+- * Get pci bus width
+- */
+- SK_IN16(IoC, B0_CTST, &Val16);
+- if ((Val16 & CS_BUS_SLOT_SZ) == 0) {
+-
+- pAC->Pnmi.PciBusWidth = 32;
+- }
+- else {
+- pAC->Pnmi.PciBusWidth = 64;
+- }
+-
+- /*
+- * Get chipset
+- */
+- switch (pAC->GIni.GIChipId) {
+- case CHIP_ID_GENESIS:
+- pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_XMAC;
+- break;
+-
+- case CHIP_ID_YUKON:
+- pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON;
+- break;
+-
+- default:
+- break;
+- }
+-
+- /*
+- * Get PMD and DeviceType
+- */
+- SK_IN8(IoC, B2_PMD_TYP, &Val8);
+- switch (Val8) {
+- case 'S':
+- pAC->Pnmi.PMD = 3;
+- if (pAC->GIni.GIMacsFound > 1) {
+-
+- pAC->Pnmi.DeviceType = 0x00020002;
+- }
+- else {
+- pAC->Pnmi.DeviceType = 0x00020001;
+- }
+- break;
+-
+- case 'L':
+- pAC->Pnmi.PMD = 2;
+- if (pAC->GIni.GIMacsFound > 1) {
+-
+- pAC->Pnmi.DeviceType = 0x00020004;
+- }
+- else {
+- pAC->Pnmi.DeviceType = 0x00020003;
+- }
+- break;
+-
+- case 'C':
+- pAC->Pnmi.PMD = 4;
+- if (pAC->GIni.GIMacsFound > 1) {
+-
+- pAC->Pnmi.DeviceType = 0x00020006;
+- }
+- else {
+- pAC->Pnmi.DeviceType = 0x00020005;
+- }
+- break;
+-
+- case 'T':
+- pAC->Pnmi.PMD = 5;
+- if (pAC->GIni.GIMacsFound > 1) {
+-
+- pAC->Pnmi.DeviceType = 0x00020008;
+- }
+- else {
+- pAC->Pnmi.DeviceType = 0x00020007;
+- }
+- break;
+-
+- default :
+- pAC->Pnmi.PMD = 1;
+- pAC->Pnmi.DeviceType = 0;
+- break;
+- }
+-
+- /*
+- * Get connector
+- */
+- SK_IN8(IoC, B2_CONN_TYP, &Val8);
+- switch (Val8) {
+- case 'C':
+- pAC->Pnmi.Connector = 2;
+- break;
+-
+- case 'D':
+- pAC->Pnmi.Connector = 3;
+- break;
+-
+- case 'F':
+- pAC->Pnmi.Connector = 4;
+- break;
+-
+- case 'J':
+- pAC->Pnmi.Connector = 5;
+- break;
+-
+- case 'V':
+- pAC->Pnmi.Connector = 6;
+- break;
+-
+- default:
+- pAC->Pnmi.Connector = 1;
+- break;
+- }
+- break;
+-
+- case SK_INIT_RUN:
+- /*
+- * Start timer for RLMT change counter
+- */
+- SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+- SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
+- 28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
+- EventParam);
+- break;
+-
+- default:
+- break; /* Nothing todo */
+- }
+-
+- return (0);
+-}
+-
+-/*****************************************************************************
+- *
+- * SkPnmiGetVar - Retrieves the value of a single OID
+- *
+- * Description:
+- * Calls a general sub-function for all this stuff. If the instance
+- * -1 is passed, the values of all instances are returned in an
+- * array of values.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK The request was successfully performed
+- * SK_PNMI_ERR_GENERAL A general severe internal error occured
+- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take
+- * the data.
+- * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown
+- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- * exist (e.g. port instance 3 on a two port
+- * adapter.
+- */
+-static int SkPnmiGetVar(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-SK_U32 Id, /* Object ID that is to be processed */
+-void *pBuf, /* Buffer to which the management data will be copied */
+-unsigned int *pLen, /* On call: buffer length. On return: used buffer */
+-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+-{
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+- ("PNMI: SkPnmiGetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
+- Id, *pLen, Instance, NetIndex));
+-
+- return (PnmiVar(pAC, IoC, SK_PNMI_GET, Id, (char *)pBuf, pLen,
+- Instance, NetIndex));
+-}
+-
+-/*****************************************************************************
+- *
+- * SkPnmiPreSetVar - Presets the value of a single OID
+- *
+- * Description:
+- * Calls a general sub-function for all this stuff. The preset does
+- * the same as a set, but returns just before finally setting the
+- * new value. This is useful to check if a set might be successfull.
+- * If the instance -1 is passed, an array of values is supposed and
+- * all instances of the OID will be set.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK The request was successfully performed.
+- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
+- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
+- * the correct data (e.g. a 32bit value is
+- * needed, but a 16 bit value was passed).
+- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
+- * value range.
+- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
+- * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown.
+- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- * exist (e.g. port instance 3 on a two port
+- * adapter.
+- */
+-static int SkPnmiPreSetVar(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-SK_U32 Id, /* Object ID that is to be processed */
+-void *pBuf, /* Buffer to which the management data will be copied */
+-unsigned int *pLen, /* Total length of management data */
+-SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+-{
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+- ("PNMI: SkPnmiPreSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
+- Id, *pLen, Instance, NetIndex));
+-
+-
+- return (PnmiVar(pAC, IoC, SK_PNMI_PRESET, Id, (char *)pBuf, pLen,
+- Instance, NetIndex));
+-}
+-
+-/*****************************************************************************
+- *
+- * SkPnmiSetVar - Sets the value of a single OID
+- *
+- * Description:
+- * Calls a general sub-function for all this stuff. The preset does
+- * the same as a set, but returns just before finally setting the
+- * new value. This is useful to check if a set might be successfull.
+- * If the instance -1 is passed, an array of values is supposed and
+- * all instances of the OID will be set.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK The request was successfully performed.
+- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
+- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
+- * the correct data (e.g. a 32bit value is
+- * needed, but a 16 bit value was passed).
+- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
+- * value range.
+- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
+- * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown.
+- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- * exist (e.g. port instance 3 on a two port
+- * adapter.
+- */
+-int SkPnmiSetVar(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-SK_U32 Id, /* Object ID that is to be processed */
+-void *pBuf, /* Buffer to which the management data will be copied */
+-unsigned int *pLen, /* Total length of management data */
+-SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+-{
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+- ("PNMI: SkPnmiSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
+- Id, *pLen, Instance, NetIndex));
+-
+- return (PnmiVar(pAC, IoC, SK_PNMI_SET, Id, (char *)pBuf, pLen,
+- Instance, NetIndex));
+-}
+-
+-/*****************************************************************************
+- *
+- * SkPnmiGetStruct - Retrieves the management database in SK_PNMI_STRUCT_DATA
+- *
+- * Description:
+- * Runs through the IdTable, queries the single OIDs and stores the
+- * returned data into the management database structure
+- * SK_PNMI_STRUCT_DATA. The offset of the OID in the structure
+- * is stored in the IdTable. The return value of the function will also
+- * be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the
+- * minimum size of SK_PNMI_MIN_STRUCT_SIZE.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK The request was successfully performed
+- * SK_PNMI_ERR_GENERAL A general severe internal error occured
+- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take
+- * the data.
+- * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist
+- */
+-int SkPnmiGetStruct(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-void *pBuf, /* Buffer to which the management data will be copied. */
+-unsigned int *pLen, /* Length of buffer */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+-{
+- int Ret;
+- unsigned int TableIndex;
+- unsigned int DstOffset;
+- unsigned int InstanceNo;
+- unsigned int InstanceCnt;
+- SK_U32 Instance;
+- unsigned int TmpLen;
+- char KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE];
+-
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+- ("PNMI: SkPnmiGetStruct: Called, BufLen=%d, NetIndex=%d\n",
+- *pLen, NetIndex));
+-
+- if (*pLen < SK_PNMI_STRUCT_SIZE) {
+-
+- if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
+-
+- SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT,
+- (SK_U32)(-1));
+- }
+-
+- *pLen = SK_PNMI_STRUCT_SIZE;
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+-
+- /*
+- * Check NetIndex
+- */
+- if (NetIndex >= pAC->Rlmt.NumNets) {
+- return (SK_PNMI_ERR_UNKNOWN_NET);
+- }
+-
+- /* Update statistic */
+- SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On call");
+-
+- if ((Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1)) !=
+- SK_PNMI_ERR_OK) {
+-
+- SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
+- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
+- return (Ret);
+- }
+-
+- if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
+-
+- SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
+- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
+- return (Ret);
+- }
+-
+- if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
+-
+- SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
+- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
+- return (Ret);
+- }
+-
+- /*
+- * Increment semaphores to indicate that an update was
+- * already done
+- */
+- pAC->Pnmi.MacUpdatedFlag ++;
+- pAC->Pnmi.RlmtUpdatedFlag ++;
+- pAC->Pnmi.SirqUpdatedFlag ++;
+-
+- /* Get vpd keys for instance calculation */
+- Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &TmpLen);
+- if (Ret != SK_PNMI_ERR_OK) {
+-
+- pAC->Pnmi.MacUpdatedFlag --;
+- pAC->Pnmi.RlmtUpdatedFlag --;
+- pAC->Pnmi.SirqUpdatedFlag --;
+-
+- SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
+- SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
+- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- /* Retrieve values */
+- SK_MEMSET((char *)pBuf, 0, SK_PNMI_STRUCT_SIZE);
+- for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) {
+-
+- InstanceNo = IdTable[TableIndex].InstanceNo;
+- for (InstanceCnt = 1; InstanceCnt <= InstanceNo;
+- InstanceCnt ++) {
+-
+- DstOffset = IdTable[TableIndex].Offset +
+- (InstanceCnt - 1) *
+- IdTable[TableIndex].StructSize;
+-
+- /*
+- * For the VPD the instance is not an index number
+- * but the key itself. Determin with the instance
+- * counter the VPD key to be used.
+- */
+- if (IdTable[TableIndex].Id == OID_SKGE_VPD_KEY ||
+- IdTable[TableIndex].Id == OID_SKGE_VPD_VALUE ||
+- IdTable[TableIndex].Id == OID_SKGE_VPD_ACCESS ||
+- IdTable[TableIndex].Id == OID_SKGE_VPD_ACTION) {
+-
+- SK_STRNCPY((char *)&Instance, KeyArr[InstanceCnt - 1], 4);
+- }
+- else {
+- Instance = (SK_U32)InstanceCnt;
+- }
+-
+- TmpLen = *pLen - DstOffset;
+- Ret = IdTable[TableIndex].Func(pAC, IoC, SK_PNMI_GET,
+- IdTable[TableIndex].Id, (char *)pBuf +
+- DstOffset, &TmpLen, Instance, TableIndex, NetIndex);
+-
+- /*
+- * An unknown instance error means that we reached
+- * the last instance of that variable. Proceed with
+- * the next OID in the table and ignore the return
+- * code.
+- */
+- if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
+-
+- break;
+- }
+-
+- if (Ret != SK_PNMI_ERR_OK) {
+-
+- pAC->Pnmi.MacUpdatedFlag --;
+- pAC->Pnmi.RlmtUpdatedFlag --;
+- pAC->Pnmi.SirqUpdatedFlag --;
+-
+- SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
+- SK_PNMI_SET_STAT(pBuf, Ret, DstOffset);
+- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
+- return (Ret);
+- }
+- }
+- }
+-
+- pAC->Pnmi.MacUpdatedFlag --;
+- pAC->Pnmi.RlmtUpdatedFlag --;
+- pAC->Pnmi.SirqUpdatedFlag --;
+-
+- *pLen = SK_PNMI_STRUCT_SIZE;
+- SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
+- SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1));
+- return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * SkPnmiPreSetStruct - Presets the management database in SK_PNMI_STRUCT_DATA
+- *
+- * Description:
+- * Calls a general sub-function for all this set stuff. The preset does
+- * the same as a set, but returns just before finally setting the
+- * new value. This is useful to check if a set might be successfull.
+- * The sub-function runs through the IdTable, checks which OIDs are able
+- * to set, and calls the handler function of the OID to perform the
+- * preset. The return value of the function will also be stored in
+- * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
+- * SK_PNMI_MIN_STRUCT_SIZE.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK The request was successfully performed.
+- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
+- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
+- * the correct data (e.g. a 32bit value is
+- * needed, but a 16 bit value was passed).
+- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
+- * value range.
+- */
+-int SkPnmiPreSetStruct(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-void *pBuf, /* Buffer which contains the data to be set */
+-unsigned int *pLen, /* Length of buffer */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+-{
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+- ("PNMI: SkPnmiPreSetStruct: Called, BufLen=%d, NetIndex=%d\n",
+- *pLen, NetIndex));
+-
+- return (PnmiStruct(pAC, IoC, SK_PNMI_PRESET, (char *)pBuf,
+- pLen, NetIndex));
+-}
+-
+-/*****************************************************************************
+- *
+- * SkPnmiSetStruct - Sets the management database in SK_PNMI_STRUCT_DATA
+- *
+- * Description:
+- * Calls a general sub-function for all this set stuff. The return value
+- * of the function will also be stored in SK_PNMI_STRUCT_DATA if the
+- * passed buffer has the minimum size of SK_PNMI_MIN_STRUCT_SIZE.
+- * The sub-function runs through the IdTable, checks which OIDs are able
+- * to set, and calls the handler function of the OID to perform the
+- * set. The return value of the function will also be stored in
+- * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
+- * SK_PNMI_MIN_STRUCT_SIZE.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK The request was successfully performed.
+- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
+- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
+- * the correct data (e.g. a 32bit value is
+- * needed, but a 16 bit value was passed).
+- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
+- * value range.
+- */
+-int SkPnmiSetStruct(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-void *pBuf, /* Buffer which contains the data to be set */
+-unsigned int *pLen, /* Length of buffer */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+-{
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+- ("PNMI: SkPnmiSetStruct: Called, BufLen=%d, NetIndex=%d\n",
+- *pLen, NetIndex));
+-
+- return (PnmiStruct(pAC, IoC, SK_PNMI_SET, (char *)pBuf,
+- pLen, NetIndex));
+-}
+-
+-/*****************************************************************************
+- *
+- * SkPnmiEvent - Event handler
+- *
+- * Description:
+- * Handles the following events:
+- * SK_PNMI_EVT_SIRQ_OVERFLOW When a hardware counter overflows an
+- * interrupt will be generated which is
+- * first handled by SIRQ which generates a
+- * this event. The event increments the
+- * upper 32 bit of the 64 bit counter.
+- * SK_PNMI_EVT_SEN_XXX The event is generated by the I2C module
+- * when a sensor reports a warning or
+- * error. The event will store a trap
+- * message in the trap buffer.
+- * SK_PNMI_EVT_CHG_EST_TIMER The timer event was initiated by this
+- * module and is used to calculate the
+- * port switches per hour.
+- * SK_PNMI_EVT_CLEAR_COUNTER The event clears all counters and
+- * timestamps.
+- * SK_PNMI_EVT_XMAC_RESET The event is generated by the driver
+- * before a hard reset of the XMAC is
+- * performed. All counters will be saved
+- * and added to the hardware counter
+- * values after reset to grant continuous
+- * counter values.
+- * SK_PNMI_EVT_RLMT_PORT_UP Generated by RLMT to notify that a port
+- * went logically up. A trap message will
+- * be stored to the trap buffer.
+- * SK_PNMI_EVT_RLMT_PORT_DOWN Generated by RLMT to notify that a port
+- * went logically down. A trap message will
+- * be stored to the trap buffer.
+- * SK_PNMI_EVT_RLMT_SEGMENTATION Generated by RLMT to notify that two
+- * spanning tree root bridges were
+- * detected. A trap message will be stored
+- * to the trap buffer.
+- * SK_PNMI_EVT_RLMT_ACTIVE_DOWN Notifies PNMI that an active port went
+- * down. PNMI will not further add the
+- * statistic values to the virtual port.
+- * SK_PNMI_EVT_RLMT_ACTIVE_UP Notifies PNMI that a port went up and
+- * is now an active port. PNMI will now
+- * add the statistic data of this port to
+- * the virtual port.
+- * SK_PNMI_EVT_RLMT_SET_NETS Notifies PNMI about the net mode. The first parameter
+- * contains the number of nets. 1 means single net, 2 means
+- * dual net. The second parameter is -1
+- *
+- * Returns:
+- * Always 0
+- */
+-int SkPnmiEvent(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-SK_U32 Event, /* Event-Id */
+-SK_EVPARA Param) /* Event dependent parameter */
+-{
+- unsigned int PhysPortIndex;
+- unsigned int MaxNetNumber;
+- int CounterIndex;
+- int Ret;
+- SK_U16 MacStatus;
+- SK_U64 OverflowStatus;
+- SK_U64 Mask;
+- int MacType;
+- SK_U64 Value;
+- SK_U32 Val32;
+- SK_U16 Register;
+- SK_EVPARA EventParam;
+- SK_U64 NewestValue;
+- SK_U64 OldestValue;
+- SK_U64 Delta;
+- SK_PNMI_ESTIMATE *pEst;
+- SK_U32 NetIndex;
+- SK_GEPORT *pPrt;
+- SK_PNMI_VCT *pVctBackupData;
+- SK_U32 RetCode;
+- int i;
+- SK_U32 CableLength;
+-
+-
+-#ifdef DEBUG
+- if (Event != SK_PNMI_EVT_XMAC_RESET) {
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+- ("PNMI: SkPnmiEvent: Called, Event=0x%x, Param=0x%x\n",
+- (unsigned int)Event, (unsigned int)Param.Para64));
+- }
+-#endif /* DEBUG */
+- SK_PNMI_CHECKFLAGS("SkPnmiEvent: On call");
+-
+- MacType = pAC->GIni.GIMacType;
+-
+- switch (Event) {
+-
+- case SK_PNMI_EVT_SIRQ_OVERFLOW:
+- PhysPortIndex = (int)Param.Para32[0];
+- MacStatus = (SK_U16)Param.Para32[1];
+-#ifdef DEBUG
+- if (PhysPortIndex >= SK_MAX_MACS) {
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SIRQ_OVERFLOW parameter"
+- " wrong, PhysPortIndex=0x%x\n",
+- PhysPortIndex));
+- return (0);
+- }
+-#endif /* DEBUG */
+- OverflowStatus = 0;
+-
+- /*
+- * Check which source caused an overflow interrupt.
+- */
+- if ((pAC->GIni.GIFunc.pFnMacOverflow(pAC, IoC, PhysPortIndex,
+- MacStatus, &OverflowStatus) != 0) ||
+- (OverflowStatus == 0)) {
+-
+- SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
+- return (0);
+- }
+-
+- /*
+- * Check the overflow status register and increment
+- * the upper dword of corresponding counter.
+- */
+- for (CounterIndex = 0; CounterIndex < sizeof(Mask) * 8;
+- CounterIndex ++) {
+-
+- Mask = (SK_U64)1 << CounterIndex;
+- if ((OverflowStatus & Mask) == 0) {
+-
+- continue;
+- }
+-
+- switch (StatOvrflwBit[CounterIndex][MacType]) {
+-
+- case SK_PNMI_HTX_UTILUNDER:
+- case SK_PNMI_HTX_UTILOVER:
+- if (MacType == SK_MAC_XMAC) {
+- XM_IN16(IoC, PhysPortIndex, XM_TX_CMD, &Register);
+- Register |= XM_TX_SAM_LINE;
+- XM_OUT16(IoC, PhysPortIndex, XM_TX_CMD, Register);
+- }
+- break;
+-
+- case SK_PNMI_HRX_UTILUNDER:
+- case SK_PNMI_HRX_UTILOVER:
+- if (MacType == SK_MAC_XMAC) {
+- XM_IN16(IoC, PhysPortIndex, XM_RX_CMD, &Register);
+- Register |= XM_RX_SAM_LINE;
+- XM_OUT16(IoC, PhysPortIndex, XM_RX_CMD, Register);
+- }
+- break;
+-
+- case SK_PNMI_HTX_OCTETHIGH:
+- case SK_PNMI_HTX_OCTETLOW:
+- case SK_PNMI_HTX_RESERVED:
+- case SK_PNMI_HRX_OCTETHIGH:
+- case SK_PNMI_HRX_OCTETLOW:
+- case SK_PNMI_HRX_IRLENGTH:
+- case SK_PNMI_HRX_RESERVED:
+-
+- /*
+- * the following counters aren't be handled (id > 63)
+- */
+- case SK_PNMI_HTX_SYNC:
+- case SK_PNMI_HTX_SYNC_OCTET:
+- break;
+-
+- case SK_PNMI_HRX_LONGFRAMES:
+- if (MacType == SK_MAC_GMAC) {
+- pAC->Pnmi.Port[PhysPortIndex].
+- CounterHigh[CounterIndex] ++;
+- }
+- break;
+-
+- default:
+- pAC->Pnmi.Port[PhysPortIndex].
+- CounterHigh[CounterIndex] ++;
+- }
+- }
+- break;
+-
+- case SK_PNMI_EVT_SEN_WAR_LOW:
+-#ifdef DEBUG
+- if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_LOW parameter wrong, SensorIndex=%d\n",
+- (unsigned int)Param.Para64));
+- return (0);
+- }
+-#endif /* DEBUG */
+-
+- /*
+- * Store a trap message in the trap buffer and generate
+- * an event for user space applications with the
+- * SK_DRIVER_SENDEVENT macro.
+- */
+- QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_LOW,
+- (unsigned int)Param.Para64);
+- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
+- break;
+-
+- case SK_PNMI_EVT_SEN_WAR_UPP:
+-#ifdef DEBUG
+- if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_UPP parameter wrong, SensorIndex=%d\n",
+- (unsigned int)Param.Para64));
+- return (0);
+- }
+-#endif /* DEBUG */
+-
+- /*
+- * Store a trap message in the trap buffer and generate
+- * an event for user space applications with the
+- * SK_DRIVER_SENDEVENT macro.
+- */
+- QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_UPP,
+- (unsigned int)Param.Para64);
+- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
+- break;
+-
+- case SK_PNMI_EVT_SEN_ERR_LOW:
+-#ifdef DEBUG
+- if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_LOW parameter wrong, SensorIndex=%d\n",
+- (unsigned int)Param.Para64));
+- return (0);
+- }
+-#endif /* DEBUG */
+-
+- /*
+- * Store a trap message in the trap buffer and generate
+- * an event for user space applications with the
+- * SK_DRIVER_SENDEVENT macro.
+- */
+- QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_LOW,
+- (unsigned int)Param.Para64);
+- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
+- break;
+-
+- case SK_PNMI_EVT_SEN_ERR_UPP:
+-#ifdef DEBUG
+- if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_UPP parameter wrong, SensorIndex=%d\n",
+- (unsigned int)Param.Para64));
+- return (0);
+- }
+-#endif /* DEBUG */
+-
+- /*
+- * Store a trap message in the trap buffer and generate
+- * an event for user space applications with the
+- * SK_DRIVER_SENDEVENT macro.
+- */
+- QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_UPP,
+- (unsigned int)Param.Para64);
+- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
+- break;
+-
+- case SK_PNMI_EVT_CHG_EST_TIMER:
+- /*
+- * Calculate port switch average on a per hour basis
+- * Time interval for check : 28125 ms
+- * Number of values for average : 8
+- *
+- * Be careful in changing these values, on change check
+- * - typedef of SK_PNMI_ESTIMATE (Size of EstValue
+- * array one less than value number)
+- * - Timer initialization SkTimerStart() in SkPnmiInit
+- * - Delta value below must be multiplicated with
+- * power of 2
+- *
+- */
+- pEst = &pAC->Pnmi.RlmtChangeEstimate;
+- CounterIndex = pEst->EstValueIndex + 1;
+- if (CounterIndex == 7) {
+-
+- CounterIndex = 0;
+- }
+- pEst->EstValueIndex = CounterIndex;
+-
+- NewestValue = pAC->Pnmi.RlmtChangeCts;
+- OldestValue = pEst->EstValue[CounterIndex];
+- pEst->EstValue[CounterIndex] = NewestValue;
+-
+- /*
+- * Calculate average. Delta stores the number of
+- * port switches per 28125 * 8 = 225000 ms
+- */
+- if (NewestValue >= OldestValue) {
+-
+- Delta = NewestValue - OldestValue;
+- }
+- else {
+- /* Overflow situation */
+- Delta = (SK_U64)(0 - OldestValue) + NewestValue;
+- }
+-
+- /*
+- * Extrapolate delta to port switches per hour.
+- * Estimate = Delta * (3600000 / 225000)
+- * = Delta * 16
+- * = Delta << 4
+- */
+- pAC->Pnmi.RlmtChangeEstimate.Estimate = Delta << 4;
+-
+- /*
+- * Check if threshold is exceeded. If the threshold is
+- * permanently exceeded every 28125 ms an event will be
+- * generated to remind the user of this condition.
+- */
+- if ((pAC->Pnmi.RlmtChangeThreshold != 0) &&
+- (pAC->Pnmi.RlmtChangeEstimate.Estimate >=
+- pAC->Pnmi.RlmtChangeThreshold)) {
+-
+- QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_CHANGE_THRES);
+- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
+- }
+-
+- SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+- SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
+- 28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
+- EventParam);
+- break;
+-
+- case SK_PNMI_EVT_CLEAR_COUNTER:
+- /*
+- * Param.Para32[0] contains the NetIndex (0 ..1).
+- * Param.Para32[1] is reserved, contains -1.
+- */
+- NetIndex = (SK_U32)Param.Para32[0];
+-
+-#ifdef DEBUG
+- if (NetIndex >= pAC->Rlmt.NumNets) {
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_CLEAR_COUNTER parameter wrong, NetIndex=%d\n",
+- NetIndex));
+-
+- return (0);
+- }
+-#endif /* DEBUG */
+-
+- /*
+- * Set all counters and timestamps to zero.
+- * The according NetIndex is required as a
+- * parameter of the event.
+- */
+- ResetCounter(pAC, IoC, NetIndex);
+- break;
+-
+- case SK_PNMI_EVT_XMAC_RESET:
+- /*
+- * To grant continuous counter values store the current
+- * XMAC statistic values to the entries 1..n of the
+- * CounterOffset array. XMAC Errata #2
+- */
+-#ifdef DEBUG
+- if ((unsigned int)Param.Para64 >= SK_MAX_MACS) {
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_XMAC_RESET parameter wrong, PhysPortIndex=%d\n",
+- (unsigned int)Param.Para64));
+- return (0);
+- }
+-#endif
+- PhysPortIndex = (unsigned int)Param.Para64;
+-
+- /*
+- * Update XMAC statistic to get fresh values
+- */
+- Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
+- if (Ret != SK_PNMI_ERR_OK) {
+-
+- SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
+- return (0);
+- }
+- /*
+- * Increment semaphore to indicate that an update was
+- * already done
+- */
+- pAC->Pnmi.MacUpdatedFlag ++;
+-
+- for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
+- CounterIndex ++) {
+-
+- if (!StatAddr[CounterIndex][MacType].GetOffset) {
+-
+- continue;
+- }
+-
+- pAC->Pnmi.Port[PhysPortIndex].CounterOffset[CounterIndex] =
+- GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
+-
+- pAC->Pnmi.Port[PhysPortIndex].CounterHigh[CounterIndex] = 0;
+- }
+-
+- pAC->Pnmi.MacUpdatedFlag --;
+- break;
+-
+- case SK_PNMI_EVT_RLMT_PORT_UP:
+- PhysPortIndex = (unsigned int)Param.Para32[0];
+-#ifdef DEBUG
+- if (PhysPortIndex >= SK_MAX_MACS) {
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_UP parameter"
+- " wrong, PhysPortIndex=%d\n", PhysPortIndex));
+-
+- return (0);
+- }
+-#endif /* DEBUG */
+-
+- /*
+- * Store a trap message in the trap buffer and generate an event for
+- * user space applications with the SK_DRIVER_SENDEVENT macro.
+- */
+- QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_UP, PhysPortIndex);
+- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
+-
+- /* Bugfix for XMAC errata (#10620)*/
+- if (MacType == SK_MAC_XMAC) {
+- /* Add incremental difference to offset (#10620)*/
+- (void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- XM_RXE_SHT_ERR, &Val32);
+-
+- Value = (((SK_U64)pAC->Pnmi.Port[PhysPortIndex].
+- CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32);
+- pAC->Pnmi.Port[PhysPortIndex].CounterOffset[SK_PNMI_HRX_SHORTS] +=
+- Value - pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark;
+- }
+-
+- /* Tell VctStatus() that a link was up meanwhile. */
+- pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_LINK;
+- break;
+-
+- case SK_PNMI_EVT_RLMT_PORT_DOWN:
+- PhysPortIndex = (unsigned int)Param.Para32[0];
+-
+-#ifdef DEBUG
+- if (PhysPortIndex >= SK_MAX_MACS) {
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_DOWN parameter"
+- " wrong, PhysPortIndex=%d\n", PhysPortIndex));
+-
+- return (0);
+- }
+-#endif /* DEBUG */
+-
+- /*
+- * Store a trap message in the trap buffer and generate an event for
+- * user space applications with the SK_DRIVER_SENDEVENT macro.
+- */
+- QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_DOWN, PhysPortIndex);
+- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
+-
+- /* Bugfix #10620 - get zero level for incremental difference */
+- if (MacType == SK_MAC_XMAC) {
+-
+- (void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- XM_RXE_SHT_ERR, &Val32);
+-
+- pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark =
+- (((SK_U64)pAC->Pnmi.Port[PhysPortIndex].
+- CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32);
+- }
+- break;
+-
+- case SK_PNMI_EVT_RLMT_ACTIVE_DOWN:
+- PhysPortIndex = (unsigned int)Param.Para32[0];
+- NetIndex = (SK_U32)Param.Para32[1];
+-
+-#ifdef DEBUG
+- if (PhysPortIndex >= SK_MAX_MACS) {
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, PhysPort=%d\n",
+- PhysPortIndex));
+- }
+-
+- if (NetIndex >= pAC->Rlmt.NumNets) {
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, NetIndex=%d\n",
+- NetIndex));
+- }
+-#endif /* DEBUG */
+-
+- /*
+- * For now, ignore event if NetIndex != 0.
+- */
+- if (Param.Para32[1] != 0) {
+-
+- return (0);
+- }
+-
+- /*
+- * Nothing to do if port is already inactive
+- */
+- if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+-
+- return (0);
+- }
+-
+- /*
+- * Update statistic counters to calculate new offset for the virtual
+- * port and increment semaphore to indicate that an update was already
+- * done.
+- */
+- if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
+- SK_PNMI_ERR_OK) {
+-
+- SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
+- return (0);
+- }
+- pAC->Pnmi.MacUpdatedFlag ++;
+-
+- /*
+- * Calculate new counter offset for virtual port to grant continous
+- * counting on port switches. The virtual port consists of all currently
+- * active ports. The port down event indicates that a port is removed
+- * from the virtual port. Therefore add the counter value of the removed
+- * port to the CounterOffset for the virtual port to grant the same
+- * counter value.
+- */
+- for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
+- CounterIndex ++) {
+-
+- if (!StatAddr[CounterIndex][MacType].GetOffset) {
+-
+- continue;
+- }
+-
+- Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
+-
+- pAC->Pnmi.VirtualCounterOffset[CounterIndex] += Value;
+- }
+-
+- /*
+- * Set port to inactive
+- */
+- pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_FALSE;
+-
+- pAC->Pnmi.MacUpdatedFlag --;
+- break;
+-
+- case SK_PNMI_EVT_RLMT_ACTIVE_UP:
+- PhysPortIndex = (unsigned int)Param.Para32[0];
+- NetIndex = (SK_U32)Param.Para32[1];
+-
+-#ifdef DEBUG
+- if (PhysPortIndex >= SK_MAX_MACS) {
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, PhysPort=%d\n",
+- PhysPortIndex));
+- }
+-
+- if (NetIndex >= pAC->Rlmt.NumNets) {
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, NetIndex=%d\n",
+- NetIndex));
+- }
+-#endif /* DEBUG */
+-
+- /*
+- * For now, ignore event if NetIndex != 0.
+- */
+- if (Param.Para32[1] != 0) {
+-
+- return (0);
+- }
+-
+- /*
+- * Nothing to do if port is already active
+- */
+- if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+-
+- return (0);
+- }
+-
+- /*
+- * Statistic maintenance
+- */
+- pAC->Pnmi.RlmtChangeCts ++;
+- pAC->Pnmi.RlmtChangeTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
+-
+- /*
+- * Store a trap message in the trap buffer and generate an event for
+- * user space applications with the SK_DRIVER_SENDEVENT macro.
+- */
+- QueueRlmtNewMacTrap(pAC, PhysPortIndex);
+- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
+-
+- /*
+- * Update statistic counters to calculate new offset for the virtual
+- * port and increment semaphore to indicate that an update was
+- * already done.
+- */
+- if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
+- SK_PNMI_ERR_OK) {
+-
+- SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
+- return (0);
+- }
+- pAC->Pnmi.MacUpdatedFlag ++;
+-
+- /*
+- * Calculate new counter offset for virtual port to grant continous
+- * counting on port switches. A new port is added to the virtual port.
+- * Therefore substract the counter value of the new port from the
+- * CounterOffset for the virtual port to grant the same value.
+- */
+- for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
+- CounterIndex ++) {
+-
+- if (!StatAddr[CounterIndex][MacType].GetOffset) {
+-
+- continue;
+- }
+-
+- Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
+-
+- pAC->Pnmi.VirtualCounterOffset[CounterIndex] -= Value;
+- }
+-
+- /* Set port to active */
+- pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_TRUE;
+-
+- pAC->Pnmi.MacUpdatedFlag --;
+- break;
+-
+- case SK_PNMI_EVT_RLMT_SEGMENTATION:
+- /*
+- * Para.Para32[0] contains the NetIndex.
+- */
+-
+- /*
+- * Store a trap message in the trap buffer and generate an event for
+- * user space applications with the SK_DRIVER_SENDEVENT macro.
+- */
+- QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_SEGMENTATION);
+- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
+- break;
+-
+- case SK_PNMI_EVT_RLMT_SET_NETS:
+- /*
+- * Param.Para32[0] contains the number of Nets.
+- * Param.Para32[1] is reserved, contains -1.
+- */
+- /*
+- * Check number of nets
+- */
+- MaxNetNumber = pAC->GIni.GIMacsFound;
+- if (((unsigned int)Param.Para32[0] < 1)
+- || ((unsigned int)Param.Para32[0] > MaxNetNumber)) {
+- return (SK_PNMI_ERR_UNKNOWN_NET);
+- }
+-
+- if ((unsigned int)Param.Para32[0] == 1) { /* single net mode */
+- pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
+- }
+- else { /* dual net mode */
+- pAC->Pnmi.DualNetActiveFlag = SK_TRUE;
+- }
+- break;
+-
+- case SK_PNMI_EVT_VCT_RESET:
+- PhysPortIndex = Param.Para32[0];
+- pPrt = &pAC->GIni.GP[PhysPortIndex];
+- pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex];
+-
+- if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) {
+- RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE);
+- if (RetCode == 2) {
+- /*
+- * VCT test is still running.
+- * Start VCT timer counter again.
+- */
+- SK_MEMSET((char *) &Param, 0, sizeof(Param));
+- Param.Para32[0] = PhysPortIndex;
+- Param.Para32[1] = -1;
+- SkTimerStart(pAC, IoC,
+- &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer,
+- 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Param);
+- break;
+- }
+- pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING;
+- pAC->Pnmi.VctStatus[PhysPortIndex] |=
+- (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE);
+-
+- /* Copy results for later use to PNMI struct. */
+- for (i = 0; i < 4; i++) {
+- if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) {
+- if ((pPrt->PMdiPairLen[i] > 35) &&
+- (pPrt->PMdiPairLen[i] < 0xff)) {
+- pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH;
+- }
+- }
+- if ((pPrt->PMdiPairLen[i] > 35) &&
+- (pPrt->PMdiPairLen[i] != 0xff)) {
+- CableLength = 1000 *
+- (((175 * pPrt->PMdiPairLen[i]) / 210) - 28);
+- }
+- else {
+- CableLength = 0;
+- }
+- pVctBackupData->PMdiPairLen[i] = CableLength;
+- pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i];
+- }
+-
+- Param.Para32[0] = PhysPortIndex;
+- Param.Para32[1] = -1;
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Param);
+- SkEventDispatcher(pAC, IoC);
+- }
+-
+- break;
+-
+- default:
+- break;
+- }
+-
+- SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
+- return (0);
+-}
+-
+-
+-/******************************************************************************
+- *
+- * Private functions
+- *
+- */
+-
+-/*****************************************************************************
+- *
+- * PnmiVar - Gets, presets, and sets single OIDs
+- *
+- * Description:
+- * Looks up the requested OID, calls the corresponding handler
+- * function, and passes the parameters with the get, preset, or
+- * set command. The function is called by SkGePnmiGetVar,
+- * SkGePnmiPreSetVar, or SkGePnmiSetVar.
+- *
+- * Returns:
+- * SK_PNMI_ERR_XXX. For details have a look at the description of the
+- * calling functions.
+- * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist
+- */
+-PNMI_STATIC int PnmiVar(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-int Action, /* GET/PRESET/SET action */
+-SK_U32 Id, /* Object ID that is to be processed */
+-char *pBuf, /* Buffer used for the management data transfer */
+-unsigned int *pLen, /* Total length of pBuf management data */
+-SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+-{
+- unsigned int TableIndex;
+- int Ret;
+-
+-
+- if ((TableIndex = LookupId(Id)) == (unsigned int)(-1)) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_UNKNOWN_OID);
+- }
+-
+- /* Check NetIndex */
+- if (NetIndex >= pAC->Rlmt.NumNets) {
+- return (SK_PNMI_ERR_UNKNOWN_NET);
+- }
+-
+- SK_PNMI_CHECKFLAGS("PnmiVar: On call");
+-
+- Ret = IdTable[TableIndex].Func(pAC, IoC, Action, Id, pBuf, pLen,
+- Instance, TableIndex, NetIndex);
+-
+- SK_PNMI_CHECKFLAGS("PnmiVar: On return");
+-
+- return (Ret);
+-}
+-
+-/*****************************************************************************
+- *
+- * PnmiStruct - Presets and Sets data in structure SK_PNMI_STRUCT_DATA
+- *
+- * Description:
+- * The return value of the function will also be stored in
+- * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
+- * SK_PNMI_MIN_STRUCT_SIZE. The sub-function runs through the IdTable,
+- * checks which OIDs are able to set, and calls the handler function of
+- * the OID to perform the set. The return value of the function will
+- * also be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the
+- * minimum size of SK_PNMI_MIN_STRUCT_SIZE. The function is called
+- * by SkGePnmiPreSetStruct and SkGePnmiSetStruct.
+- *
+- * Returns:
+- * SK_PNMI_ERR_XXX. The codes are described in the calling functions.
+- * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist
+- */
+-PNMI_STATIC int PnmiStruct(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-int Action, /* PRESET/SET action to be performed */
+-char *pBuf, /* Buffer used for the management data transfer */
+-unsigned int *pLen, /* Length of pBuf management data buffer */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+-{
+- int Ret;
+- unsigned int TableIndex;
+- unsigned int DstOffset;
+- unsigned int Len;
+- unsigned int InstanceNo;
+- unsigned int InstanceCnt;
+- SK_U32 Instance;
+- SK_U32 Id;
+-
+-
+- /* Check if the passed buffer has the right size */
+- if (*pLen < SK_PNMI_STRUCT_SIZE) {
+-
+- /* Check if we can return the error within the buffer */
+- if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
+-
+- SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT,
+- (SK_U32)(-1));
+- }
+-
+- *pLen = SK_PNMI_STRUCT_SIZE;
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+-
+- /* Check NetIndex */
+- if (NetIndex >= pAC->Rlmt.NumNets) {
+- return (SK_PNMI_ERR_UNKNOWN_NET);
+- }
+-
+- SK_PNMI_CHECKFLAGS("PnmiStruct: On call");
+-
+- /*
+- * Update the values of RLMT and SIRQ and increment semaphores to
+- * indicate that an update was already done.
+- */
+- if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
+-
+- SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
+- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
+- return (Ret);
+- }
+-
+- if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
+-
+- SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
+- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
+- return (Ret);
+- }
+-
+- pAC->Pnmi.RlmtUpdatedFlag ++;
+- pAC->Pnmi.SirqUpdatedFlag ++;
+-
+- /* Preset/Set values */
+- for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) {
+-
+- if ((IdTable[TableIndex].Access != SK_PNMI_RW) &&
+- (IdTable[TableIndex].Access != SK_PNMI_WO)) {
+-
+- continue;
+- }
+-
+- InstanceNo = IdTable[TableIndex].InstanceNo;
+- Id = IdTable[TableIndex].Id;
+-
+- for (InstanceCnt = 1; InstanceCnt <= InstanceNo;
+- InstanceCnt ++) {
+-
+- DstOffset = IdTable[TableIndex].Offset +
+- (InstanceCnt - 1) *
+- IdTable[TableIndex].StructSize;
+-
+- /*
+- * Because VPD multiple instance variables are
+- * not setable we do not need to evaluate VPD
+- * instances. Have a look to VPD instance
+- * calculation in SkPnmiGetStruct().
+- */
+- Instance = (SK_U32)InstanceCnt;
+-
+- /*
+- * Evaluate needed buffer length
+- */
+- Len = 0;
+- Ret = IdTable[TableIndex].Func(pAC, IoC,
+- SK_PNMI_GET, IdTable[TableIndex].Id,
+- NULL, &Len, Instance, TableIndex, NetIndex);
+-
+- if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
+-
+- break;
+- }
+- if (Ret != SK_PNMI_ERR_TOO_SHORT) {
+-
+- pAC->Pnmi.RlmtUpdatedFlag --;
+- pAC->Pnmi.SirqUpdatedFlag --;
+-
+- SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
+- SK_PNMI_SET_STAT(pBuf,
+- SK_PNMI_ERR_GENERAL, DstOffset);
+- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- if (Id == OID_SKGE_VPD_ACTION) {
+-
+- switch (*(pBuf + DstOffset)) {
+-
+- case SK_PNMI_VPD_CREATE:
+- Len = 3 + *(pBuf + DstOffset + 3);
+- break;
+-
+- case SK_PNMI_VPD_DELETE:
+- Len = 3;
+- break;
+-
+- default:
+- Len = 1;
+- break;
+- }
+- }
+-
+- /* Call the OID handler function */
+- Ret = IdTable[TableIndex].Func(pAC, IoC, Action,
+- IdTable[TableIndex].Id, pBuf + DstOffset,
+- &Len, Instance, TableIndex, NetIndex);
+-
+- if (Ret != SK_PNMI_ERR_OK) {
+-
+- pAC->Pnmi.RlmtUpdatedFlag --;
+- pAC->Pnmi.SirqUpdatedFlag --;
+-
+- SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
+- SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_BAD_VALUE,
+- DstOffset);
+- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
+- return (SK_PNMI_ERR_BAD_VALUE);
+- }
+- }
+- }
+-
+- pAC->Pnmi.RlmtUpdatedFlag --;
+- pAC->Pnmi.SirqUpdatedFlag --;
+-
+- SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
+- SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1));
+- return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * LookupId - Lookup an OID in the IdTable
+- *
+- * Description:
+- * Scans the IdTable to find the table entry of an OID.
+- *
+- * Returns:
+- * The table index or -1 if not found.
+- */
+-PNMI_STATIC int LookupId(
+-SK_U32 Id) /* Object identifier to be searched */
+-{
+- int i;
+-
+- for (i = 0; i < ID_TABLE_SIZE; i++) {
+-
+- if (IdTable[i].Id == Id) {
+-
+- return i;
+- }
+- }
+-
+- return (-1);
+-}
+-
+-/*****************************************************************************
+- *
+- * OidStruct - Handler of OID_SKGE_ALL_DATA
+- *
+- * Description:
+- * This OID performs a Get/Preset/SetStruct call and returns all data
+- * in a SK_PNMI_STRUCT_DATA structure.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK The request was successfully performed.
+- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
+- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
+- * the correct data (e.g. a 32bit value is
+- * needed, but a 16 bit value was passed).
+- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
+- * value range.
+- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
+- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- * exist (e.g. port instance 3 on a two port
+- * adapter.
+- */
+-PNMI_STATIC int OidStruct(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-int Action, /* GET/PRESET/SET action */
+-SK_U32 Id, /* Object ID that is to be processed */
+-char *pBuf, /* Buffer used for the management data transfer */
+-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+-{
+- if (Id != OID_SKGE_ALL_DATA) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR003,
+- SK_PNMI_ERR003MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- /*
+- * Check instance. We only handle single instance variables
+- */
+- if (Instance != (SK_U32)(-1) && Instance != 1) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_UNKNOWN_INST);
+- }
+-
+- switch (Action) {
+-
+- case SK_PNMI_GET:
+- return (SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex));
+-
+- case SK_PNMI_PRESET:
+- return (SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex));
+-
+- case SK_PNMI_SET:
+- return (SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex));
+- }
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR004, SK_PNMI_ERR004MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+-}
+-
+-/*****************************************************************************
+- *
+- * Perform - OID handler of OID_SKGE_ACTION
+- *
+- * Description:
+- * None.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK The request was successfully performed.
+- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
+- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
+- * the correct data (e.g. a 32bit value is
+- * needed, but a 16 bit value was passed).
+- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
+- * value range.
+- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
+- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- * exist (e.g. port instance 3 on a two port
+- * adapter.
+- */
+-PNMI_STATIC int Perform(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-int Action, /* GET/PRESET/SET action */
+-SK_U32 Id, /* Object ID that is to be processed */
+-char *pBuf, /* Buffer used for the management data transfer */
+-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+-{
+- int Ret;
+- SK_U32 ActionOp;
+-
+-
+- /*
+- * Check instance. We only handle single instance variables
+- */
+- if (Instance != (SK_U32)(-1) && Instance != 1) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_UNKNOWN_INST);
+- }
+-
+- if (*pLen < sizeof(SK_U32)) {
+-
+- *pLen = sizeof(SK_U32);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+-
+- /* Check if a get should be performed */
+- if (Action == SK_PNMI_GET) {
+-
+- /* A get is easy. We always return the same value */
+- ActionOp = (SK_U32)SK_PNMI_ACT_IDLE;
+- SK_PNMI_STORE_U32(pBuf, ActionOp);
+- *pLen = sizeof(SK_U32);
+-
+- return (SK_PNMI_ERR_OK);
+- }
+-
+- /* Continue with PRESET/SET action */
+- if (*pLen > sizeof(SK_U32)) {
+-
+- return (SK_PNMI_ERR_BAD_VALUE);
+- }
+-
+- /* Check if the command is a known one */
+- SK_PNMI_READ_U32(pBuf, ActionOp);
+- if (*pLen > sizeof(SK_U32) ||
+- (ActionOp != SK_PNMI_ACT_IDLE &&
+- ActionOp != SK_PNMI_ACT_RESET &&
+- ActionOp != SK_PNMI_ACT_SELFTEST &&
+- ActionOp != SK_PNMI_ACT_RESETCNT)) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_BAD_VALUE);
+- }
+-
+- /* A preset ends here */
+- if (Action == SK_PNMI_PRESET) {
+-
+- return (SK_PNMI_ERR_OK);
+- }
+-
+- switch (ActionOp) {
+-
+- case SK_PNMI_ACT_IDLE:
+- /* Nothing to do */
+- break;
+-
+- case SK_PNMI_ACT_RESET:
+- /*
+- * Perform a driver reset or something that comes near
+- * to this.
+- */
+- Ret = SK_DRIVER_RESET(pAC, IoC);
+- if (Ret != 0) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR005,
+- SK_PNMI_ERR005MSG);
+-
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- break;
+-
+- case SK_PNMI_ACT_SELFTEST:
+- /*
+- * Perform a driver selftest or something similar to this.
+- * Currently this feature is not used and will probably
+- * implemented in another way.
+- */
+- Ret = SK_DRIVER_SELFTEST(pAC, IoC);
+- pAC->Pnmi.TestResult = Ret;
+- break;
+-
+- case SK_PNMI_ACT_RESETCNT:
+- /* Set all counters and timestamps to zero */
+- ResetCounter(pAC, IoC, NetIndex);
+- break;
+-
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR006,
+- SK_PNMI_ERR006MSG);
+-
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * Mac8023Stat - OID handler of OID_GEN_XXX and OID_802_3_XXX
+- *
+- * Description:
+- * Retrieves the statistic values of the virtual port (logical
+- * index 0). Only special OIDs of NDIS are handled which consist
+- * of a 32 bit instead of a 64 bit value. The OIDs are public
+- * because perhaps some other platform can use them too.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK The request was successfully performed.
+- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
+- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
+- * the correct data (e.g. a 32bit value is
+- * needed, but a 16 bit value was passed).
+- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- * exist (e.g. port instance 3 on a two port
+- * adapter.
+- */
+-PNMI_STATIC int Mac8023Stat(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-int Action, /* GET/PRESET/SET action */
+-SK_U32 Id, /* Object ID that is to be processed */
+-char *pBuf, /* Buffer used for the management data transfer */
+-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+-{
+- int Ret;
+- SK_U64 StatVal;
+- SK_U32 StatVal32;
+- SK_BOOL Is64BitReq = SK_FALSE;
+-
+- /*
+- * Only the active Mac is returned
+- */
+- if (Instance != (SK_U32)(-1) && Instance != 1) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_UNKNOWN_INST);
+- }
+-
+- /*
+- * Check action type
+- */
+- if (Action != SK_PNMI_GET) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_READ_ONLY);
+- }
+-
+- /* Check length */
+- switch (Id) {
+-
+- case OID_802_3_PERMANENT_ADDRESS:
+- case OID_802_3_CURRENT_ADDRESS:
+- if (*pLen < sizeof(SK_MAC_ADDR)) {
+-
+- *pLen = sizeof(SK_MAC_ADDR);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- break;
+-
+- default:
+-#ifndef SK_NDIS_64BIT_CTR
+- if (*pLen < sizeof(SK_U32)) {
+- *pLen = sizeof(SK_U32);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+-
+-#else /* SK_NDIS_64BIT_CTR */
+-
+- /* for compatibility, at least 32bit are required for OID */
+- if (*pLen < sizeof(SK_U32)) {
+- /*
+- * but indicate handling for 64bit values,
+- * if insufficient space is provided
+- */
+- *pLen = sizeof(SK_U64);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+-
+- Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE;
+-#endif /* SK_NDIS_64BIT_CTR */
+- break;
+- }
+-
+- /*
+- * Update all statistics, because we retrieve virtual MAC, which
+- * consists of multiple physical statistics and increment semaphore
+- * to indicate that an update was already done.
+- */
+- Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
+- if ( Ret != SK_PNMI_ERR_OK) {
+-
+- *pLen = 0;
+- return (Ret);
+- }
+- pAC->Pnmi.MacUpdatedFlag ++;
+-
+- /*
+- * Get value (MAC Index 0 identifies the virtual MAC)
+- */
+- switch (Id) {
+-
+- case OID_802_3_PERMANENT_ADDRESS:
+- CopyMac(pBuf, &pAC->Addr.Net[NetIndex].PermanentMacAddress);
+- *pLen = sizeof(SK_MAC_ADDR);
+- break;
+-
+- case OID_802_3_CURRENT_ADDRESS:
+- CopyMac(pBuf, &pAC->Addr.Net[NetIndex].CurrentMacAddress);
+- *pLen = sizeof(SK_MAC_ADDR);
+- break;
+-
+- default:
+- StatVal = GetStatVal(pAC, IoC, 0, IdTable[TableIndex].Param, NetIndex);
+-
+- /* by default 32bit values are evaluated */
+- if (!Is64BitReq) {
+- StatVal32 = (SK_U32)StatVal;
+- SK_PNMI_STORE_U32(pBuf, StatVal32);
+- *pLen = sizeof(SK_U32);
+- }
+- else {
+- SK_PNMI_STORE_U64(pBuf, StatVal);
+- *pLen = sizeof(SK_U64);
+- }
+- break;
+- }
+-
+- pAC->Pnmi.MacUpdatedFlag --;
+-
+- return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * MacPrivateStat - OID handler function of OID_SKGE_STAT_XXX
+- *
+- * Description:
+- * Retrieves the MAC statistic data.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK The request was successfully performed.
+- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
+- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
+- * the correct data (e.g. a 32bit value is
+- * needed, but a 16 bit value was passed).
+- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- * exist (e.g. port instance 3 on a two port
+- * adapter.
+- */
+-PNMI_STATIC int MacPrivateStat(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-int Action, /* GET/PRESET/SET action */
+-SK_U32 Id, /* Object ID that is to be processed */
+-char *pBuf, /* Buffer used for the management data transfer */
+-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+-{
+- unsigned int LogPortMax;
+- unsigned int LogPortIndex;
+- unsigned int PhysPortMax;
+- unsigned int Limit;
+- unsigned int Offset;
+- int MacType;
+- int Ret;
+- SK_U64 StatVal;
+-
+-
+-
+- /* Calculate instance if wished. MAC index 0 is the virtual MAC */
+- PhysPortMax = pAC->GIni.GIMacsFound;
+- LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
+-
+- MacType = pAC->GIni.GIMacType;
+-
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
+- LogPortMax--;
+- }
+-
+- if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
+- /* Check instance range */
+- if ((Instance < 1) || (Instance > LogPortMax)) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_UNKNOWN_INST);
+- }
+- LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
+- Limit = LogPortIndex + 1;
+- }
+-
+- else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
+-
+- LogPortIndex = 0;
+- Limit = LogPortMax;
+- }
+-
+- /* Check action */
+- if (Action != SK_PNMI_GET) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_READ_ONLY);
+- }
+-
+- /* Check length */
+- if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U64)) {
+-
+- *pLen = (Limit - LogPortIndex) * sizeof(SK_U64);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+-
+- /*
+- * Update MAC statistic and increment semaphore to indicate that
+- * an update was already done.
+- */
+- Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
+- if (Ret != SK_PNMI_ERR_OK) {
+-
+- *pLen = 0;
+- return (Ret);
+- }
+- pAC->Pnmi.MacUpdatedFlag ++;
+-
+- /* Get value */
+- Offset = 0;
+- for (; LogPortIndex < Limit; LogPortIndex ++) {
+-
+- switch (Id) {
+-
+-/* XXX not yet implemented due to XMAC problems
+- case OID_SKGE_STAT_TX_UTIL:
+- return (SK_PNMI_ERR_GENERAL);
+-*/
+-/* XXX not yet implemented due to XMAC problems
+- case OID_SKGE_STAT_RX_UTIL:
+- return (SK_PNMI_ERR_GENERAL);
+-*/
+- case OID_SKGE_STAT_RX:
+- if (MacType == SK_MAC_GMAC) {
+- StatVal =
+- GetStatVal(pAC, IoC, LogPortIndex,
+- SK_PNMI_HRX_BROADCAST, NetIndex) +
+- GetStatVal(pAC, IoC, LogPortIndex,
+- SK_PNMI_HRX_MULTICAST, NetIndex) +
+- GetStatVal(pAC, IoC, LogPortIndex,
+- SK_PNMI_HRX_UNICAST, NetIndex) +
+- GetStatVal(pAC, IoC, LogPortIndex,
+- SK_PNMI_HRX_UNDERSIZE, NetIndex);
+- }
+- else {
+- StatVal = GetStatVal(pAC, IoC, LogPortIndex,
+- IdTable[TableIndex].Param, NetIndex);
+- }
+- break;
+-
+- case OID_SKGE_STAT_TX:
+- if (MacType == SK_MAC_GMAC) {
+- StatVal =
+- GetStatVal(pAC, IoC, LogPortIndex,
+- SK_PNMI_HTX_BROADCAST, NetIndex) +
+- GetStatVal(pAC, IoC, LogPortIndex,
+- SK_PNMI_HTX_MULTICAST, NetIndex) +
+- GetStatVal(pAC, IoC, LogPortIndex,
+- SK_PNMI_HTX_UNICAST, NetIndex);
+- }
+- else {
+- StatVal = GetStatVal(pAC, IoC, LogPortIndex,
+- IdTable[TableIndex].Param, NetIndex);
+- }
+- break;
+-
+- default:
+- StatVal = GetStatVal(pAC, IoC, LogPortIndex,
+- IdTable[TableIndex].Param, NetIndex);
+- }
+- SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
+-
+- Offset += sizeof(SK_U64);
+- }
+- *pLen = Offset;
+-
+- pAC->Pnmi.MacUpdatedFlag --;
+-
+- return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * Addr - OID handler function of OID_SKGE_PHYS_CUR_ADDR and _FAC_ADDR
+- *
+- * Description:
+- * Get/Presets/Sets the current and factory MAC address. The MAC
+- * address of the virtual port, which is reported to the OS, may
+- * not be changed, but the physical ones. A set to the virtual port
+- * will be ignored. No error should be reported because otherwise
+- * a multiple instance set (-1) would always fail.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK The request was successfully performed.
+- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
+- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
+- * the correct data (e.g. a 32bit value is
+- * needed, but a 16 bit value was passed).
+- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
+- * value range.
+- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
+- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- * exist (e.g. port instance 3 on a two port
+- * adapter.
+- */
+-PNMI_STATIC int Addr(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-int Action, /* GET/PRESET/SET action */
+-SK_U32 Id, /* Object ID that is to be processed */
+-char *pBuf, /* Buffer used for the management data transfer */
+-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+-{
+- int Ret;
+- unsigned int LogPortMax;
+- unsigned int PhysPortMax;
+- unsigned int LogPortIndex;
+- unsigned int PhysPortIndex;
+- unsigned int Limit;
+- unsigned int Offset = 0;
+-
+- /*
+- * Calculate instance if wished. MAC index 0 is the virtual
+- * MAC.
+- */
+- PhysPortMax = pAC->GIni.GIMacsFound;
+- LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
+-
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
+- LogPortMax--;
+- }
+-
+- if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
+- /* Check instance range */
+- if ((Instance < 1) || (Instance > LogPortMax)) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_UNKNOWN_INST);
+- }
+- LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
+- Limit = LogPortIndex + 1;
+- }
+- else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
+-
+- LogPortIndex = 0;
+- Limit = LogPortMax;
+- }
+-
+- /*
+- * Perform Action
+- */
+- if (Action == SK_PNMI_GET) {
+-
+- /* Check length */
+- if (*pLen < (Limit - LogPortIndex) * 6) {
+-
+- *pLen = (Limit - LogPortIndex) * 6;
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+-
+- /*
+- * Get value
+- */
+- for (; LogPortIndex < Limit; LogPortIndex ++) {
+-
+- switch (Id) {
+-
+- case OID_SKGE_PHYS_CUR_ADDR:
+- if (LogPortIndex == 0) {
+- CopyMac(pBuf + Offset, &pAC->Addr.Net[NetIndex].CurrentMacAddress);
+- }
+- else {
+- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
+-
+- CopyMac(pBuf + Offset,
+- &pAC->Addr.Port[PhysPortIndex].CurrentMacAddress);
+- }
+- Offset += 6;
+- break;
+-
+- case OID_SKGE_PHYS_FAC_ADDR:
+- if (LogPortIndex == 0) {
+- CopyMac(pBuf + Offset,
+- &pAC->Addr.Net[NetIndex].PermanentMacAddress);
+- }
+- else {
+- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
+-
+- CopyMac(pBuf + Offset,
+- &pAC->Addr.Port[PhysPortIndex].PermanentMacAddress);
+- }
+- Offset += 6;
+- break;
+-
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR008,
+- SK_PNMI_ERR008MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- }
+-
+- *pLen = Offset;
+- }
+- else {
+- /*
+- * The logical MAC address may not be changed only
+- * the physical ones
+- */
+- if (Id == OID_SKGE_PHYS_FAC_ADDR) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_READ_ONLY);
+- }
+-
+- /*
+- * Only the current address may be changed
+- */
+- if (Id != OID_SKGE_PHYS_CUR_ADDR) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR009,
+- SK_PNMI_ERR009MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- /* Check length */
+- if (*pLen < (Limit - LogPortIndex) * 6) {
+-
+- *pLen = (Limit - LogPortIndex) * 6;
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- if (*pLen > (Limit - LogPortIndex) * 6) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_BAD_VALUE);
+- }
+-
+- /*
+- * Check Action
+- */
+- if (Action == SK_PNMI_PRESET) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_OK);
+- }
+-
+- /*
+- * Set OID_SKGE_MAC_CUR_ADDR
+- */
+- for (; LogPortIndex < Limit; LogPortIndex ++, Offset += 6) {
+-
+- /*
+- * A set to virtual port and set of broadcast
+- * address will be ignored
+- */
+- if (LogPortIndex == 0 || SK_MEMCMP(pBuf + Offset,
+- "\xff\xff\xff\xff\xff\xff", 6) == 0) {
+-
+- continue;
+- }
+-
+- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC,
+- LogPortIndex);
+-
+- Ret = SkAddrOverride(pAC, IoC, PhysPortIndex,
+- (SK_MAC_ADDR *)(pBuf + Offset),
+- (LogPortIndex == 0 ? SK_ADDR_VIRTUAL_ADDRESS :
+- SK_ADDR_PHYSICAL_ADDRESS));
+- if (Ret != SK_ADDR_OVERRIDE_SUCCESS) {
+-
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- }
+- *pLen = Offset;
+- }
+-
+- return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * CsumStat - OID handler function of OID_SKGE_CHKSM_XXX
+- *
+- * Description:
+- * Retrieves the statistic values of the CSUM module. The CSUM data
+- * structure must be available in the SK_AC even if the CSUM module
+- * is not included, because PNMI reads the statistic data from the
+- * CSUM part of SK_AC directly.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK The request was successfully performed.
+- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
+- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
+- * the correct data (e.g. a 32bit value is
+- * needed, but a 16 bit value was passed).
+- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- * exist (e.g. port instance 3 on a two port
+- * adapter.
+- */
+-PNMI_STATIC int CsumStat(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-int Action, /* GET/PRESET/SET action */
+-SK_U32 Id, /* Object ID that is to be processed */
+-char *pBuf, /* Buffer used for the management data transfer */
+-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+-{
+- unsigned int Index;
+- unsigned int Limit;
+- unsigned int Offset = 0;
+- SK_U64 StatVal;
+-
+-
+- /*
+- * Calculate instance if wished
+- */
+- if (Instance != (SK_U32)(-1)) {
+-
+- if ((Instance < 1) || (Instance > SKCS_NUM_PROTOCOLS)) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_UNKNOWN_INST);
+- }
+- Index = (unsigned int)Instance - 1;
+- Limit = Index + 1;
+- }
+- else {
+- Index = 0;
+- Limit = SKCS_NUM_PROTOCOLS;
+- }
+-
+- /*
+- * Check action
+- */
+- if (Action != SK_PNMI_GET) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_READ_ONLY);
+- }
+-
+- /* Check length */
+- if (*pLen < (Limit - Index) * sizeof(SK_U64)) {
+-
+- *pLen = (Limit - Index) * sizeof(SK_U64);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+-
+- /*
+- * Get value
+- */
+- for (; Index < Limit; Index ++) {
+-
+- switch (Id) {
+-
+- case OID_SKGE_CHKSM_RX_OK_CTS:
+- StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxOkCts;
+- break;
+-
+- case OID_SKGE_CHKSM_RX_UNABLE_CTS:
+- StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxUnableCts;
+- break;
+-
+- case OID_SKGE_CHKSM_RX_ERR_CTS:
+- StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxErrCts;
+- break;
+-
+- case OID_SKGE_CHKSM_TX_OK_CTS:
+- StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxOkCts;
+- break;
+-
+- case OID_SKGE_CHKSM_TX_UNABLE_CTS:
+- StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxUnableCts;
+- break;
+-
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR010,
+- SK_PNMI_ERR010MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
+- Offset += sizeof(SK_U64);
+- }
+-
+- /*
+- * Store used buffer space
+- */
+- *pLen = Offset;
+-
+- return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * SensorStat - OID handler function of OID_SKGE_SENSOR_XXX
+- *
+- * Description:
+- * Retrieves the statistic values of the I2C module, which handles
+- * the temperature and voltage sensors.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK The request was successfully performed.
+- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
+- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
+- * the correct data (e.g. a 32bit value is
+- * needed, but a 16 bit value was passed).
+- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- * exist (e.g. port instance 3 on a two port
+- * adapter.
+- */
+-PNMI_STATIC int SensorStat(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-int Action, /* GET/PRESET/SET action */
+-SK_U32 Id, /* Object ID that is to be processed */
+-char *pBuf, /* Buffer used for the management data transfer */
+-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+-{
+- unsigned int i;
+- unsigned int Index;
+- unsigned int Limit;
+- unsigned int Offset;
+- unsigned int Len;
+- SK_U32 Val32;
+- SK_U64 Val64;
+-
+-
+- /*
+- * Calculate instance if wished
+- */
+- if ((Instance != (SK_U32)(-1))) {
+-
+- if ((Instance < 1) || (Instance > (SK_U32)pAC->I2c.MaxSens)) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_UNKNOWN_INST);
+- }
+-
+- Index = (unsigned int)Instance -1;
+- Limit = (unsigned int)Instance;
+- }
+- else {
+- Index = 0;
+- Limit = (unsigned int) pAC->I2c.MaxSens;
+- }
+-
+- /*
+- * Check action
+- */
+- if (Action != SK_PNMI_GET) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_READ_ONLY);
+- }
+-
+- /* Check length */
+- switch (Id) {
+-
+- case OID_SKGE_SENSOR_VALUE:
+- case OID_SKGE_SENSOR_WAR_THRES_LOW:
+- case OID_SKGE_SENSOR_WAR_THRES_UPP:
+- case OID_SKGE_SENSOR_ERR_THRES_LOW:
+- case OID_SKGE_SENSOR_ERR_THRES_UPP:
+- if (*pLen < (Limit - Index) * sizeof(SK_U32)) {
+-
+- *pLen = (Limit - Index) * sizeof(SK_U32);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- break;
+-
+- case OID_SKGE_SENSOR_DESCR:
+- for (Offset = 0, i = Index; i < Limit; i ++) {
+-
+- Len = (unsigned int)
+- SK_STRLEN(pAC->I2c.SenTable[i].SenDesc) + 1;
+- if (Len >= SK_PNMI_STRINGLEN2) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR011,
+- SK_PNMI_ERR011MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- Offset += Len;
+- }
+- if (*pLen < Offset) {
+-
+- *pLen = Offset;
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- break;
+-
+- case OID_SKGE_SENSOR_INDEX:
+- case OID_SKGE_SENSOR_TYPE:
+- case OID_SKGE_SENSOR_STATUS:
+- if (*pLen < Limit - Index) {
+-
+- *pLen = Limit - Index;
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- break;
+-
+- case OID_SKGE_SENSOR_WAR_CTS:
+- case OID_SKGE_SENSOR_WAR_TIME:
+- case OID_SKGE_SENSOR_ERR_CTS:
+- case OID_SKGE_SENSOR_ERR_TIME:
+- if (*pLen < (Limit - Index) * sizeof(SK_U64)) {
+-
+- *pLen = (Limit - Index) * sizeof(SK_U64);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- break;
+-
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR012,
+- SK_PNMI_ERR012MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+-
+- }
+-
+- /*
+- * Get value
+- */
+- for (Offset = 0; Index < Limit; Index ++) {
+-
+- switch (Id) {
+-
+- case OID_SKGE_SENSOR_INDEX:
+- *(pBuf + Offset) = (char)Index;
+- Offset += sizeof(char);
+- break;
+-
+- case OID_SKGE_SENSOR_DESCR:
+- Len = SK_STRLEN(pAC->I2c.SenTable[Index].SenDesc);
+- SK_MEMCPY(pBuf + Offset + 1,
+- pAC->I2c.SenTable[Index].SenDesc, Len);
+- *(pBuf + Offset) = (char)Len;
+- Offset += Len + 1;
+- break;
+-
+- case OID_SKGE_SENSOR_TYPE:
+- *(pBuf + Offset) =
+- (char)pAC->I2c.SenTable[Index].SenType;
+- Offset += sizeof(char);
+- break;
+-
+- case OID_SKGE_SENSOR_VALUE:
+- Val32 = (SK_U32)pAC->I2c.SenTable[Index].SenValue;
+- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+- Offset += sizeof(SK_U32);
+- break;
+-
+- case OID_SKGE_SENSOR_WAR_THRES_LOW:
+- Val32 = (SK_U32)pAC->I2c.SenTable[Index].
+- SenThreWarnLow;
+- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+- Offset += sizeof(SK_U32);
+- break;
+-
+- case OID_SKGE_SENSOR_WAR_THRES_UPP:
+- Val32 = (SK_U32)pAC->I2c.SenTable[Index].
+- SenThreWarnHigh;
+- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+- Offset += sizeof(SK_U32);
+- break;
+-
+- case OID_SKGE_SENSOR_ERR_THRES_LOW:
+- Val32 = (SK_U32)pAC->I2c.SenTable[Index].
+- SenThreErrLow;
+- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+- Offset += sizeof(SK_U32);
+- break;
+-
+- case OID_SKGE_SENSOR_ERR_THRES_UPP:
+- Val32 = pAC->I2c.SenTable[Index].SenThreErrHigh;
+- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+- Offset += sizeof(SK_U32);
+- break;
+-
+- case OID_SKGE_SENSOR_STATUS:
+- *(pBuf + Offset) =
+- (char)pAC->I2c.SenTable[Index].SenErrFlag;
+- Offset += sizeof(char);
+- break;
+-
+- case OID_SKGE_SENSOR_WAR_CTS:
+- Val64 = pAC->I2c.SenTable[Index].SenWarnCts;
+- SK_PNMI_STORE_U64(pBuf + Offset, Val64);
+- Offset += sizeof(SK_U64);
+- break;
+-
+- case OID_SKGE_SENSOR_ERR_CTS:
+- Val64 = pAC->I2c.SenTable[Index].SenErrCts;
+- SK_PNMI_STORE_U64(pBuf + Offset, Val64);
+- Offset += sizeof(SK_U64);
+- break;
+-
+- case OID_SKGE_SENSOR_WAR_TIME:
+- Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index].
+- SenBegWarnTS);
+- SK_PNMI_STORE_U64(pBuf + Offset, Val64);
+- Offset += sizeof(SK_U64);
+- break;
+-
+- case OID_SKGE_SENSOR_ERR_TIME:
+- Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index].
+- SenBegErrTS);
+- SK_PNMI_STORE_U64(pBuf + Offset, Val64);
+- Offset += sizeof(SK_U64);
+- break;
+-
+- default:
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
+- ("SensorStat: Unknown OID should be handled before"));
+-
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- }
+-
+- /*
+- * Store used buffer space
+- */
+- *pLen = Offset;
+-
+- return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * Vpd - OID handler function of OID_SKGE_VPD_XXX
+- *
+- * Description:
+- * Get/preset/set of VPD data. As instance the name of a VPD key
+- * can be passed. The Instance parameter is a SK_U32 and can be
+- * used as a string buffer for the VPD key, because their maximum
+- * length is 4 byte.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK The request was successfully performed.
+- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
+- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
+- * the correct data (e.g. a 32bit value is
+- * needed, but a 16 bit value was passed).
+- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
+- * value range.
+- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
+- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- * exist (e.g. port instance 3 on a two port
+- * adapter.
+- */
+-PNMI_STATIC int Vpd(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-int Action, /* GET/PRESET/SET action */
+-SK_U32 Id, /* Object ID that is to be processed */
+-char *pBuf, /* Buffer used for the management data transfer */
+-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+-{
+- SK_VPD_STATUS *pVpdStatus;
+- unsigned int BufLen;
+- char Buf[256];
+- char KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE];
+- char KeyStr[SK_PNMI_VPD_KEY_SIZE];
+- unsigned int KeyNo;
+- unsigned int Offset;
+- unsigned int Index;
+- unsigned int FirstIndex;
+- unsigned int LastIndex;
+- unsigned int Len;
+- int Ret;
+- SK_U32 Val32;
+-
+- /*
+- * Get array of all currently stored VPD keys
+- */
+- Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &KeyNo);
+- if (Ret != SK_PNMI_ERR_OK) {
+- *pLen = 0;
+- return (Ret);
+- }
+-
+- /*
+- * If instance is not -1, try to find the requested VPD key for
+- * the multiple instance variables. The other OIDs as for example
+- * OID VPD_ACTION are single instance variables and must be
+- * handled separatly.
+- */
+- FirstIndex = 0;
+- LastIndex = KeyNo;
+-
+- if ((Instance != (SK_U32)(-1))) {
+-
+- if (Id == OID_SKGE_VPD_KEY || Id == OID_SKGE_VPD_VALUE ||
+- Id == OID_SKGE_VPD_ACCESS) {
+-
+- SK_STRNCPY(KeyStr, (char *)&Instance, 4);
+- KeyStr[4] = 0;
+-
+- for (Index = 0; Index < KeyNo; Index ++) {
+-
+- if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) {
+- FirstIndex = Index;
+- LastIndex = Index+1;
+- break;
+- }
+- }
+- if (Index == KeyNo) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_UNKNOWN_INST);
+- }
+- }
+- else if (Instance != 1) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_UNKNOWN_INST);
+- }
+- }
+-
+- /*
+- * Get value, if a query should be performed
+- */
+- if (Action == SK_PNMI_GET) {
+-
+- switch (Id) {
+-
+- case OID_SKGE_VPD_FREE_BYTES:
+- /* Check length of buffer */
+- if (*pLen < sizeof(SK_U32)) {
+-
+- *pLen = sizeof(SK_U32);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- /* Get number of free bytes */
+- pVpdStatus = VpdStat(pAC, IoC);
+- if (pVpdStatus == NULL) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR017,
+- SK_PNMI_ERR017MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- if ((pVpdStatus->vpd_status & VPD_VALID) == 0) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR018,
+- SK_PNMI_ERR018MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- Val32 = (SK_U32)pVpdStatus->vpd_free_rw;
+- SK_PNMI_STORE_U32(pBuf, Val32);
+- *pLen = sizeof(SK_U32);
+- break;
+-
+- case OID_SKGE_VPD_ENTRIES_LIST:
+- /* Check length */
+- for (Len = 0, Index = 0; Index < KeyNo; Index ++) {
+-
+- Len += SK_STRLEN(KeyArr[Index]) + 1;
+- }
+- if (*pLen < Len) {
+-
+- *pLen = Len;
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+-
+- /* Get value */
+- *(pBuf) = (char)Len - 1;
+- for (Offset = 1, Index = 0; Index < KeyNo; Index ++) {
+-
+- Len = SK_STRLEN(KeyArr[Index]);
+- SK_MEMCPY(pBuf + Offset, KeyArr[Index], Len);
+-
+- Offset += Len;
+-
+- if (Index < KeyNo - 1) {
+-
+- *(pBuf + Offset) = ' ';
+- Offset ++;
+- }
+- }
+- *pLen = Offset;
+- break;
+-
+- case OID_SKGE_VPD_ENTRIES_NUMBER:
+- /* Check length */
+- if (*pLen < sizeof(SK_U32)) {
+-
+- *pLen = sizeof(SK_U32);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+-
+- Val32 = (SK_U32)KeyNo;
+- SK_PNMI_STORE_U32(pBuf, Val32);
+- *pLen = sizeof(SK_U32);
+- break;
+-
+- case OID_SKGE_VPD_KEY:
+- /* Check buffer length, if it is large enough */
+- for (Len = 0, Index = FirstIndex;
+- Index < LastIndex; Index ++) {
+-
+- Len += SK_STRLEN(KeyArr[Index]) + 1;
+- }
+- if (*pLen < Len) {
+-
+- *pLen = Len;
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+-
+- /*
+- * Get the key to an intermediate buffer, because
+- * we have to prepend a length byte.
+- */
+- for (Offset = 0, Index = FirstIndex;
+- Index < LastIndex; Index ++) {
+-
+- Len = SK_STRLEN(KeyArr[Index]);
+-
+- *(pBuf + Offset) = (char)Len;
+- SK_MEMCPY(pBuf + Offset + 1, KeyArr[Index],
+- Len);
+- Offset += Len + 1;
+- }
+- *pLen = Offset;
+- break;
+-
+- case OID_SKGE_VPD_VALUE:
+- /* Check the buffer length if it is large enough */
+- for (Offset = 0, Index = FirstIndex;
+- Index < LastIndex; Index ++) {
+-
+- BufLen = 256;
+- if (VpdRead(pAC, IoC, KeyArr[Index], Buf,
+- (int *)&BufLen) > 0 ||
+- BufLen >= SK_PNMI_VPD_DATALEN) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW,
+- SK_PNMI_ERR021,
+- SK_PNMI_ERR021MSG);
+-
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- Offset += BufLen + 1;
+- }
+- if (*pLen < Offset) {
+-
+- *pLen = Offset;
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+-
+- /*
+- * Get the value to an intermediate buffer, because
+- * we have to prepend a length byte.
+- */
+- for (Offset = 0, Index = FirstIndex;
+- Index < LastIndex; Index ++) {
+-
+- BufLen = 256;
+- if (VpdRead(pAC, IoC, KeyArr[Index], Buf,
+- (int *)&BufLen) > 0 ||
+- BufLen >= SK_PNMI_VPD_DATALEN) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW,
+- SK_PNMI_ERR022,
+- SK_PNMI_ERR022MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- *(pBuf + Offset) = (char)BufLen;
+- SK_MEMCPY(pBuf + Offset + 1, Buf, BufLen);
+- Offset += BufLen + 1;
+- }
+- *pLen = Offset;
+- break;
+-
+- case OID_SKGE_VPD_ACCESS:
+- if (*pLen < LastIndex - FirstIndex) {
+-
+- *pLen = LastIndex - FirstIndex;
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+-
+- for (Offset = 0, Index = FirstIndex;
+- Index < LastIndex; Index ++) {
+-
+- if (VpdMayWrite(KeyArr[Index])) {
+-
+- *(pBuf + Offset) = SK_PNMI_VPD_RW;
+- }
+- else {
+- *(pBuf + Offset) = SK_PNMI_VPD_RO;
+- }
+- Offset ++;
+- }
+- *pLen = Offset;
+- break;
+-
+- case OID_SKGE_VPD_ACTION:
+- Offset = LastIndex - FirstIndex;
+- if (*pLen < Offset) {
+-
+- *pLen = Offset;
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- SK_MEMSET(pBuf, 0, Offset);
+- *pLen = Offset;
+- break;
+-
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR023,
+- SK_PNMI_ERR023MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- }
+- else {
+- /* The only OID which can be set is VPD_ACTION */
+- if (Id != OID_SKGE_VPD_ACTION) {
+-
+- if (Id == OID_SKGE_VPD_FREE_BYTES ||
+- Id == OID_SKGE_VPD_ENTRIES_LIST ||
+- Id == OID_SKGE_VPD_ENTRIES_NUMBER ||
+- Id == OID_SKGE_VPD_KEY ||
+- Id == OID_SKGE_VPD_VALUE ||
+- Id == OID_SKGE_VPD_ACCESS) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_READ_ONLY);
+- }
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR024,
+- SK_PNMI_ERR024MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- /*
+- * From this point we handle VPD_ACTION. Check the buffer
+- * length. It should at least have the size of one byte.
+- */
+- if (*pLen < 1) {
+-
+- *pLen = 1;
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+-
+- /*
+- * The first byte contains the VPD action type we should
+- * perform.
+- */
+- switch (*pBuf) {
+-
+- case SK_PNMI_VPD_IGNORE:
+- /* Nothing to do */
+- break;
+-
+- case SK_PNMI_VPD_CREATE:
+- /*
+- * We have to create a new VPD entry or we modify
+- * an existing one. Check first the buffer length.
+- */
+- if (*pLen < 4) {
+-
+- *pLen = 4;
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- KeyStr[0] = pBuf[1];
+- KeyStr[1] = pBuf[2];
+- KeyStr[2] = 0;
+-
+- /*
+- * Is the entry writable or does it belong to the
+- * read-only area?
+- */
+- if (!VpdMayWrite(KeyStr)) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_BAD_VALUE);
+- }
+-
+- Offset = (int)pBuf[3] & 0xFF;
+-
+- SK_MEMCPY(Buf, pBuf + 4, Offset);
+- Buf[Offset] = 0;
+-
+- /* A preset ends here */
+- if (Action == SK_PNMI_PRESET) {
+-
+- return (SK_PNMI_ERR_OK);
+- }
+-
+- /* Write the new entry or modify an existing one */
+- Ret = VpdWrite(pAC, IoC, KeyStr, Buf);
+- if (Ret == SK_PNMI_VPD_NOWRITE ) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_BAD_VALUE);
+- }
+- else if (Ret != SK_PNMI_VPD_OK) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR025,
+- SK_PNMI_ERR025MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- /*
+- * Perform an update of the VPD data. This is
+- * not mandantory, but just to be sure.
+- */
+- Ret = VpdUpdate(pAC, IoC);
+- if (Ret != SK_PNMI_VPD_OK) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR026,
+- SK_PNMI_ERR026MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- break;
+-
+- case SK_PNMI_VPD_DELETE:
+- /* Check if the buffer size is plausible */
+- if (*pLen < 3) {
+-
+- *pLen = 3;
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- if (*pLen > 3) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_BAD_VALUE);
+- }
+- KeyStr[0] = pBuf[1];
+- KeyStr[1] = pBuf[2];
+- KeyStr[2] = 0;
+-
+- /* Find the passed key in the array */
+- for (Index = 0; Index < KeyNo; Index ++) {
+-
+- if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) {
+-
+- break;
+- }
+- }
+- /*
+- * If we cannot find the key it is wrong, so we
+- * return an appropriate error value.
+- */
+- if (Index == KeyNo) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_BAD_VALUE);
+- }
+-
+- if (Action == SK_PNMI_PRESET) {
+-
+- return (SK_PNMI_ERR_OK);
+- }
+-
+- /* Ok, you wanted it and you will get it */
+- Ret = VpdDelete(pAC, IoC, KeyStr);
+- if (Ret != SK_PNMI_VPD_OK) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR027,
+- SK_PNMI_ERR027MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- /*
+- * Perform an update of the VPD data. This is
+- * not mandantory, but just to be sure.
+- */
+- Ret = VpdUpdate(pAC, IoC);
+- if (Ret != SK_PNMI_VPD_OK) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR028,
+- SK_PNMI_ERR028MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- break;
+-
+- default:
+- *pLen = 0;
+- return (SK_PNMI_ERR_BAD_VALUE);
+- }
+- }
+-
+- return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * General - OID handler function of various single instance OIDs
+- *
+- * Description:
+- * The code is simple. No description necessary.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK The request was successfully performed.
+- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
+- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
+- * the correct data (e.g. a 32bit value is
+- * needed, but a 16 bit value was passed).
+- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- * exist (e.g. port instance 3 on a two port
+- * adapter.
+- */
+-PNMI_STATIC int General(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-int Action, /* GET/PRESET/SET action */
+-SK_U32 Id, /* Object ID that is to be processed */
+-char *pBuf, /* Buffer used for the management data transfer */
+-unsigned int *pLen, /* On call: buffer length. On return: used buffer */
+-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+-{
+- int Ret;
+- unsigned int Index;
+- unsigned int Len;
+- unsigned int Offset;
+- unsigned int Val;
+- SK_U8 Val8;
+- SK_U16 Val16;
+- SK_U32 Val32;
+- SK_U64 Val64;
+- SK_U64 Val64RxHwErrs = 0;
+- SK_U64 Val64TxHwErrs = 0;
+- SK_BOOL Is64BitReq = SK_FALSE;
+- char Buf[256];
+- int MacType;
+-
+- /*
+- * Check instance. We only handle single instance variables.
+- */
+- if (Instance != (SK_U32)(-1) && Instance != 1) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_UNKNOWN_INST);
+- }
+-
+- /*
+- * Check action. We only allow get requests.
+- */
+- if (Action != SK_PNMI_GET) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_READ_ONLY);
+- }
+-
+- MacType = pAC->GIni.GIMacType;
+-
+- /*
+- * Check length for the various supported OIDs
+- */
+- switch (Id) {
+-
+- case OID_GEN_XMIT_ERROR:
+- case OID_GEN_RCV_ERROR:
+- case OID_GEN_RCV_NO_BUFFER:
+-#ifndef SK_NDIS_64BIT_CTR
+- if (*pLen < sizeof(SK_U32)) {
+- *pLen = sizeof(SK_U32);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+-
+-#else /* SK_NDIS_64BIT_CTR */
+-
+- /*
+- * for compatibility, at least 32bit are required for oid
+- */
+- if (*pLen < sizeof(SK_U32)) {
+- /*
+- * but indicate handling for 64bit values,
+- * if insufficient space is provided
+- */
+- *pLen = sizeof(SK_U64);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+-
+- Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE;
+-#endif /* SK_NDIS_64BIT_CTR */
+- break;
+-
+- case OID_SKGE_PORT_NUMBER:
+- case OID_SKGE_DEVICE_TYPE:
+- case OID_SKGE_RESULT:
+- case OID_SKGE_RLMT_MONITOR_NUMBER:
+- case OID_GEN_TRANSMIT_QUEUE_LENGTH:
+- case OID_SKGE_TRAP_NUMBER:
+- case OID_SKGE_MDB_VERSION:
+- case OID_SKGE_BOARDLEVEL:
+- case OID_SKGE_CHIPID:
+- case OID_SKGE_RAMSIZE:
+- if (*pLen < sizeof(SK_U32)) {
+-
+- *pLen = sizeof(SK_U32);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- break;
+-
+- case OID_SKGE_CHIPSET:
+- if (*pLen < sizeof(SK_U16)) {
+-
+- *pLen = sizeof(SK_U16);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- break;
+-
+- case OID_SKGE_BUS_TYPE:
+- case OID_SKGE_BUS_SPEED:
+- case OID_SKGE_BUS_WIDTH:
+- case OID_SKGE_SENSOR_NUMBER:
+- case OID_SKGE_CHKSM_NUMBER:
+- case OID_SKGE_VAUXAVAIL:
+- if (*pLen < sizeof(SK_U8)) {
+-
+- *pLen = sizeof(SK_U8);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- break;
+-
+- case OID_SKGE_TX_SW_QUEUE_LEN:
+- case OID_SKGE_TX_SW_QUEUE_MAX:
+- case OID_SKGE_TX_RETRY:
+- case OID_SKGE_RX_INTR_CTS:
+- case OID_SKGE_TX_INTR_CTS:
+- case OID_SKGE_RX_NO_BUF_CTS:
+- case OID_SKGE_TX_NO_BUF_CTS:
+- case OID_SKGE_TX_USED_DESCR_NO:
+- case OID_SKGE_RX_DELIVERED_CTS:
+- case OID_SKGE_RX_OCTETS_DELIV_CTS:
+- case OID_SKGE_RX_HW_ERROR_CTS:
+- case OID_SKGE_TX_HW_ERROR_CTS:
+- case OID_SKGE_IN_ERRORS_CTS:
+- case OID_SKGE_OUT_ERROR_CTS:
+- case OID_SKGE_ERR_RECOVERY_CTS:
+- case OID_SKGE_SYSUPTIME:
+- if (*pLen < sizeof(SK_U64)) {
+-
+- *pLen = sizeof(SK_U64);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- break;
+-
+- default:
+- /* Checked later */
+- break;
+- }
+-
+- /* Update statistic */
+- if (Id == OID_SKGE_RX_HW_ERROR_CTS ||
+- Id == OID_SKGE_TX_HW_ERROR_CTS ||
+- Id == OID_SKGE_IN_ERRORS_CTS ||
+- Id == OID_SKGE_OUT_ERROR_CTS ||
+- Id == OID_GEN_XMIT_ERROR ||
+- Id == OID_GEN_RCV_ERROR) {
+-
+- /* Force the XMAC to update its statistic counters and
+- * Increment semaphore to indicate that an update was
+- * already done.
+- */
+- Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
+- if (Ret != SK_PNMI_ERR_OK) {
+-
+- *pLen = 0;
+- return (Ret);
+- }
+- pAC->Pnmi.MacUpdatedFlag ++;
+-
+- /*
+- * Some OIDs consist of multiple hardware counters. Those
+- * values which are contained in all of them will be added
+- * now.
+- */
+- switch (Id) {
+-
+- case OID_SKGE_RX_HW_ERROR_CTS:
+- case OID_SKGE_IN_ERRORS_CTS:
+- case OID_GEN_RCV_ERROR:
+- Val64RxHwErrs =
+- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_MISSED, NetIndex) +
+- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FRAMING, NetIndex) +
+- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex) +
+- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_JABBER, NetIndex) +
+- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CARRIER, NetIndex) +
+- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_IRLENGTH, NetIndex) +
+- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SYMBOL, NetIndex) +
+- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SHORTS, NetIndex) +
+- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_RUNT, NetIndex) +
+- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_TOO_LONG, NetIndex) +
+- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FCS, NetIndex) +
+- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CEXT, NetIndex);
+- break;
+-
+- case OID_SKGE_TX_HW_ERROR_CTS:
+- case OID_SKGE_OUT_ERROR_CTS:
+- case OID_GEN_XMIT_ERROR:
+- Val64TxHwErrs =
+- GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_EXCESS_COL, NetIndex) +
+- GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_LATE_COL, NetIndex) +
+- GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_UNDERRUN, NetIndex) +
+- GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_CARRIER, NetIndex);
+- break;
+- }
+- }
+-
+- /*
+- * Retrieve value
+- */
+- switch (Id) {
+-
+- case OID_SKGE_SUPPORTED_LIST:
+- Len = ID_TABLE_SIZE * sizeof(SK_U32);
+- if (*pLen < Len) {
+-
+- *pLen = Len;
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- for (Offset = 0, Index = 0; Offset < Len;
+- Offset += sizeof(SK_U32), Index ++) {
+-
+- Val32 = (SK_U32)IdTable[Index].Id;
+- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+- }
+- *pLen = Len;
+- break;
+-
+- case OID_SKGE_BOARDLEVEL:
+- Val32 = (SK_U32)pAC->GIni.GILevel;
+- SK_PNMI_STORE_U32(pBuf, Val32);
+- *pLen = sizeof(SK_U32);
+- break;
+-
+- case OID_SKGE_PORT_NUMBER:
+- Val32 = (SK_U32)pAC->GIni.GIMacsFound;
+- SK_PNMI_STORE_U32(pBuf, Val32);
+- *pLen = sizeof(SK_U32);
+- break;
+-
+- case OID_SKGE_DEVICE_TYPE:
+- Val32 = (SK_U32)pAC->Pnmi.DeviceType;
+- SK_PNMI_STORE_U32(pBuf, Val32);
+- *pLen = sizeof(SK_U32);
+- break;
+-
+- case OID_SKGE_DRIVER_DESCR:
+- if (pAC->Pnmi.pDriverDescription == NULL) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR007,
+- SK_PNMI_ERR007MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- Len = SK_STRLEN(pAC->Pnmi.pDriverDescription) + 1;
+- if (Len > SK_PNMI_STRINGLEN1) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR029,
+- SK_PNMI_ERR029MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- if (*pLen < Len) {
+-
+- *pLen = Len;
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- *pBuf = (char)(Len - 1);
+- SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverDescription, Len - 1);
+- *pLen = Len;
+- break;
+-
+- case OID_SKGE_DRIVER_VERSION:
+- if (pAC->Pnmi.pDriverVersion == NULL) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
+- SK_PNMI_ERR030MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- Len = SK_STRLEN(pAC->Pnmi.pDriverVersion) + 1;
+- if (Len > SK_PNMI_STRINGLEN1) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
+- SK_PNMI_ERR031MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- if (*pLen < Len) {
+-
+- *pLen = Len;
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- *pBuf = (char)(Len - 1);
+- SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverVersion, Len - 1);
+- *pLen = Len;
+- break;
+-
+- case OID_SKGE_DRIVER_RELDATE:
+- if (pAC->Pnmi.pDriverReleaseDate == NULL) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
+- SK_PNMI_ERR053MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- Len = SK_STRLEN(pAC->Pnmi.pDriverReleaseDate) + 1;
+- if (Len > SK_PNMI_STRINGLEN1) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
+- SK_PNMI_ERR054MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- if (*pLen < Len) {
+-
+- *pLen = Len;
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- *pBuf = (char)(Len - 1);
+- SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverReleaseDate, Len - 1);
+- *pLen = Len;
+- break;
+-
+- case OID_SKGE_DRIVER_FILENAME:
+- if (pAC->Pnmi.pDriverFileName == NULL) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
+- SK_PNMI_ERR055MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- Len = SK_STRLEN(pAC->Pnmi.pDriverFileName) + 1;
+- if (Len > SK_PNMI_STRINGLEN1) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
+- SK_PNMI_ERR056MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- if (*pLen < Len) {
+-
+- *pLen = Len;
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- *pBuf = (char)(Len - 1);
+- SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverFileName, Len - 1);
+- *pLen = Len;
+- break;
+-
+- case OID_SKGE_HW_DESCR:
+- /*
+- * The hardware description is located in the VPD. This
+- * query may move to the initialisation routine. But
+- * the VPD data is cached and therefore a call here
+- * will not make much difference.
+- */
+- Len = 256;
+- if (VpdRead(pAC, IoC, VPD_NAME, Buf, (int *)&Len) > 0) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR032,
+- SK_PNMI_ERR032MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- Len ++;
+- if (Len > SK_PNMI_STRINGLEN1) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR033,
+- SK_PNMI_ERR033MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- if (*pLen < Len) {
+-
+- *pLen = Len;
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- *pBuf = (char)(Len - 1);
+- SK_MEMCPY(pBuf + 1, Buf, Len - 1);
+- *pLen = Len;
+- break;
+-
+- case OID_SKGE_HW_VERSION:
+- /* Oh, I love to do some string manipulation */
+- if (*pLen < 5) {
+-
+- *pLen = 5;
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- Val8 = (SK_U8)pAC->GIni.GIPciHwRev;
+- pBuf[0] = 4;
+- pBuf[1] = 'v';
+- pBuf[2] = (char)(0x30 | ((Val8 >> 4) & 0x0F));
+- pBuf[3] = '.';
+- pBuf[4] = (char)(0x30 | (Val8 & 0x0F));
+- *pLen = 5;
+- break;
+-
+- case OID_SKGE_CHIPSET:
+- Val16 = pAC->Pnmi.Chipset;
+- SK_PNMI_STORE_U16(pBuf, Val16);
+- *pLen = sizeof(SK_U16);
+- break;
+-
+- case OID_SKGE_CHIPID:
+- Val32 = pAC->GIni.GIChipId;
+- SK_PNMI_STORE_U32(pBuf, Val32);
+- *pLen = sizeof(SK_U32);
+- break;
+-
+- case OID_SKGE_RAMSIZE:
+- Val32 = pAC->GIni.GIRamSize;
+- SK_PNMI_STORE_U32(pBuf, Val32);
+- *pLen = sizeof(SK_U32);
+- break;
+-
+- case OID_SKGE_VAUXAVAIL:
+- *pBuf = (char) pAC->GIni.GIVauxAvail;
+- *pLen = sizeof(char);
+- break;
+-
+- case OID_SKGE_BUS_TYPE:
+- *pBuf = (char) SK_PNMI_BUS_PCI;
+- *pLen = sizeof(char);
+- break;
+-
+- case OID_SKGE_BUS_SPEED:
+- *pBuf = pAC->Pnmi.PciBusSpeed;
+- *pLen = sizeof(char);
+- break;
+-
+- case OID_SKGE_BUS_WIDTH:
+- *pBuf = pAC->Pnmi.PciBusWidth;
+- *pLen = sizeof(char);
+- break;
+-
+- case OID_SKGE_RESULT:
+- Val32 = pAC->Pnmi.TestResult;
+- SK_PNMI_STORE_U32(pBuf, Val32);
+- *pLen = sizeof(SK_U32);
+- break;
+-
+- case OID_SKGE_SENSOR_NUMBER:
+- *pBuf = (char)pAC->I2c.MaxSens;
+- *pLen = sizeof(char);
+- break;
+-
+- case OID_SKGE_CHKSM_NUMBER:
+- *pBuf = SKCS_NUM_PROTOCOLS;
+- *pLen = sizeof(char);
+- break;
+-
+- case OID_SKGE_TRAP_NUMBER:
+- GetTrapQueueLen(pAC, &Len, &Val);
+- Val32 = (SK_U32)Val;
+- SK_PNMI_STORE_U32(pBuf, Val32);
+- *pLen = sizeof(SK_U32);
+- break;
+-
+- case OID_SKGE_TRAP:
+- GetTrapQueueLen(pAC, &Len, &Val);
+- if (*pLen < Len) {
+-
+- *pLen = Len;
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- CopyTrapQueue(pAC, pBuf);
+- *pLen = Len;
+- break;
+-
+- case OID_SKGE_RLMT_MONITOR_NUMBER:
+-/* XXX Not yet implemented by RLMT therefore we return zero elements */
+- Val32 = 0;
+- SK_PNMI_STORE_U32(pBuf, Val32);
+- *pLen = sizeof(SK_U32);
+- break;
+-
+- case OID_SKGE_TX_SW_QUEUE_LEN:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+- if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueLen;
+- }
+- /* Single net mode */
+- else {
+- Val64 = pAC->Pnmi.BufPort[0].TxSwQueueLen +
+- pAC->Pnmi.BufPort[1].TxSwQueueLen;
+- }
+- }
+- else {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueLen;
+- }
+- /* Single net mode */
+- else {
+- Val64 = pAC->Pnmi.Port[0].TxSwQueueLen +
+- pAC->Pnmi.Port[1].TxSwQueueLen;
+- }
+- }
+- SK_PNMI_STORE_U64(pBuf, Val64);
+- *pLen = sizeof(SK_U64);
+- break;
+-
+-
+- case OID_SKGE_TX_SW_QUEUE_MAX:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+- if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueMax;
+- }
+- /* Single net mode */
+- else {
+- Val64 = pAC->Pnmi.BufPort[0].TxSwQueueMax +
+- pAC->Pnmi.BufPort[1].TxSwQueueMax;
+- }
+- }
+- else {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueMax;
+- }
+- /* Single net mode */
+- else {
+- Val64 = pAC->Pnmi.Port[0].TxSwQueueMax +
+- pAC->Pnmi.Port[1].TxSwQueueMax;
+- }
+- }
+- SK_PNMI_STORE_U64(pBuf, Val64);
+- *pLen = sizeof(SK_U64);
+- break;
+-
+- case OID_SKGE_TX_RETRY:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+- if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = pAC->Pnmi.BufPort[NetIndex].TxRetryCts;
+- }
+- /* Single net mode */
+- else {
+- Val64 = pAC->Pnmi.BufPort[0].TxRetryCts +
+- pAC->Pnmi.BufPort[1].TxRetryCts;
+- }
+- }
+- else {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = pAC->Pnmi.Port[NetIndex].TxRetryCts;
+- }
+- /* Single net mode */
+- else {
+- Val64 = pAC->Pnmi.Port[0].TxRetryCts +
+- pAC->Pnmi.Port[1].TxRetryCts;
+- }
+- }
+- SK_PNMI_STORE_U64(pBuf, Val64);
+- *pLen = sizeof(SK_U64);
+- break;
+-
+- case OID_SKGE_RX_INTR_CTS:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+- if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = pAC->Pnmi.BufPort[NetIndex].RxIntrCts;
+- }
+- /* Single net mode */
+- else {
+- Val64 = pAC->Pnmi.BufPort[0].RxIntrCts +
+- pAC->Pnmi.BufPort[1].RxIntrCts;
+- }
+- }
+- else {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = pAC->Pnmi.Port[NetIndex].RxIntrCts;
+- }
+- /* Single net mode */
+- else {
+- Val64 = pAC->Pnmi.Port[0].RxIntrCts +
+- pAC->Pnmi.Port[1].RxIntrCts;
+- }
+- }
+- SK_PNMI_STORE_U64(pBuf, Val64);
+- *pLen = sizeof(SK_U64);
+- break;
+-
+- case OID_SKGE_TX_INTR_CTS:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+- if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = pAC->Pnmi.BufPort[NetIndex].TxIntrCts;
+- }
+- /* Single net mode */
+- else {
+- Val64 = pAC->Pnmi.BufPort[0].TxIntrCts +
+- pAC->Pnmi.BufPort[1].TxIntrCts;
+- }
+- }
+- else {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = pAC->Pnmi.Port[NetIndex].TxIntrCts;
+- }
+- /* Single net mode */
+- else {
+- Val64 = pAC->Pnmi.Port[0].TxIntrCts +
+- pAC->Pnmi.Port[1].TxIntrCts;
+- }
+- }
+- SK_PNMI_STORE_U64(pBuf, Val64);
+- *pLen = sizeof(SK_U64);
+- break;
+-
+- case OID_SKGE_RX_NO_BUF_CTS:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+- if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
+- }
+- /* Single net mode */
+- else {
+- Val64 = pAC->Pnmi.BufPort[0].RxNoBufCts +
+- pAC->Pnmi.BufPort[1].RxNoBufCts;
+- }
+- }
+- else {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts;
+- }
+- /* Single net mode */
+- else {
+- Val64 = pAC->Pnmi.Port[0].RxNoBufCts +
+- pAC->Pnmi.Port[1].RxNoBufCts;
+- }
+- }
+- SK_PNMI_STORE_U64(pBuf, Val64);
+- *pLen = sizeof(SK_U64);
+- break;
+-
+- case OID_SKGE_TX_NO_BUF_CTS:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+- if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
+- }
+- /* Single net mode */
+- else {
+- Val64 = pAC->Pnmi.BufPort[0].TxNoBufCts +
+- pAC->Pnmi.BufPort[1].TxNoBufCts;
+- }
+- }
+- else {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = pAC->Pnmi.Port[NetIndex].TxNoBufCts;
+- }
+- /* Single net mode */
+- else {
+- Val64 = pAC->Pnmi.Port[0].TxNoBufCts +
+- pAC->Pnmi.Port[1].TxNoBufCts;
+- }
+- }
+- SK_PNMI_STORE_U64(pBuf, Val64);
+- *pLen = sizeof(SK_U64);
+- break;
+-
+- case OID_SKGE_TX_USED_DESCR_NO:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+- if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = pAC->Pnmi.BufPort[NetIndex].TxUsedDescrNo;
+- }
+- /* Single net mode */
+- else {
+- Val64 = pAC->Pnmi.BufPort[0].TxUsedDescrNo +
+- pAC->Pnmi.BufPort[1].TxUsedDescrNo;
+- }
+- }
+- else {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = pAC->Pnmi.Port[NetIndex].TxUsedDescrNo;
+- }
+- /* Single net mode */
+- else {
+- Val64 = pAC->Pnmi.Port[0].TxUsedDescrNo +
+- pAC->Pnmi.Port[1].TxUsedDescrNo;
+- }
+- }
+- SK_PNMI_STORE_U64(pBuf, Val64);
+- *pLen = sizeof(SK_U64);
+- break;
+-
+- case OID_SKGE_RX_DELIVERED_CTS:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+- if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = pAC->Pnmi.BufPort[NetIndex].RxDeliveredCts;
+- }
+- /* Single net mode */
+- else {
+- Val64 = pAC->Pnmi.BufPort[0].RxDeliveredCts +
+- pAC->Pnmi.BufPort[1].RxDeliveredCts;
+- }
+- }
+- else {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = pAC->Pnmi.Port[NetIndex].RxDeliveredCts;
+- }
+- /* Single net mode */
+- else {
+- Val64 = pAC->Pnmi.Port[0].RxDeliveredCts +
+- pAC->Pnmi.Port[1].RxDeliveredCts;
+- }
+- }
+- SK_PNMI_STORE_U64(pBuf, Val64);
+- *pLen = sizeof(SK_U64);
+- break;
+-
+- case OID_SKGE_RX_OCTETS_DELIV_CTS:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+- if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = pAC->Pnmi.BufPort[NetIndex].RxOctetsDeliveredCts;
+- }
+- /* Single net mode */
+- else {
+- Val64 = pAC->Pnmi.BufPort[0].RxOctetsDeliveredCts +
+- pAC->Pnmi.BufPort[1].RxOctetsDeliveredCts;
+- }
+- }
+- else {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts;
+- }
+- /* Single net mode */
+- else {
+- Val64 = pAC->Pnmi.Port[0].RxOctetsDeliveredCts +
+- pAC->Pnmi.Port[1].RxOctetsDeliveredCts;
+- }
+- }
+- SK_PNMI_STORE_U64(pBuf, Val64);
+- *pLen = sizeof(SK_U64);
+- break;
+-
+- case OID_SKGE_RX_HW_ERROR_CTS:
+- SK_PNMI_STORE_U64(pBuf, Val64RxHwErrs);
+- *pLen = sizeof(SK_U64);
+- break;
+-
+- case OID_SKGE_TX_HW_ERROR_CTS:
+- SK_PNMI_STORE_U64(pBuf, Val64TxHwErrs);
+- *pLen = sizeof(SK_U64);
+- break;
+-
+- case OID_SKGE_IN_ERRORS_CTS:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+- if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
+- }
+- /* Single net mode */
+- else {
+- Val64 = Val64RxHwErrs +
+- pAC->Pnmi.BufPort[0].RxNoBufCts +
+- pAC->Pnmi.BufPort[1].RxNoBufCts;
+- }
+- }
+- else {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts;
+- }
+- /* Single net mode */
+- else {
+- Val64 = Val64RxHwErrs +
+- pAC->Pnmi.Port[0].RxNoBufCts +
+- pAC->Pnmi.Port[1].RxNoBufCts;
+- }
+- }
+- SK_PNMI_STORE_U64(pBuf, Val64);
+- *pLen = sizeof(SK_U64);
+- break;
+-
+- case OID_SKGE_OUT_ERROR_CTS:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+- if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
+- }
+- /* Single net mode */
+- else {
+- Val64 = Val64TxHwErrs +
+- pAC->Pnmi.BufPort[0].TxNoBufCts +
+- pAC->Pnmi.BufPort[1].TxNoBufCts;
+- }
+- }
+- else {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts;
+- }
+- /* Single net mode */
+- else {
+- Val64 = Val64TxHwErrs +
+- pAC->Pnmi.Port[0].TxNoBufCts +
+- pAC->Pnmi.Port[1].TxNoBufCts;
+- }
+- }
+- SK_PNMI_STORE_U64(pBuf, Val64);
+- *pLen = sizeof(SK_U64);
+- break;
+-
+- case OID_SKGE_ERR_RECOVERY_CTS:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+- if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = pAC->Pnmi.BufPort[NetIndex].ErrRecoveryCts;
+- }
+- /* Single net mode */
+- else {
+- Val64 = pAC->Pnmi.BufPort[0].ErrRecoveryCts +
+- pAC->Pnmi.BufPort[1].ErrRecoveryCts;
+- }
+- }
+- else {
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- Val64 = pAC->Pnmi.Port[NetIndex].ErrRecoveryCts;
+- }
+- /* Single net mode */
+- else {
+- Val64 = pAC->Pnmi.Port[0].ErrRecoveryCts +
+- pAC->Pnmi.Port[1].ErrRecoveryCts;
+- }
+- }
+- SK_PNMI_STORE_U64(pBuf, Val64);
+- *pLen = sizeof(SK_U64);
+- break;
+-
+- case OID_SKGE_SYSUPTIME:
+- Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
+- Val64 -= pAC->Pnmi.StartUpTime;
+- SK_PNMI_STORE_U64(pBuf, Val64);
+- *pLen = sizeof(SK_U64);
+- break;
+-
+- case OID_SKGE_MDB_VERSION:
+- Val32 = SK_PNMI_MDB_VERSION;
+- SK_PNMI_STORE_U32(pBuf, Val32);
+- *pLen = sizeof(SK_U32);
+- break;
+-
+- case OID_GEN_RCV_ERROR:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+- if (MacType == SK_MAC_XMAC) {
+- Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
+- }
+- else {
+- Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts;
+- }
+-
+- /*
+- * by default 32bit values are evaluated
+- */
+- if (!Is64BitReq) {
+- Val32 = (SK_U32)Val64;
+- SK_PNMI_STORE_U32(pBuf, Val32);
+- *pLen = sizeof(SK_U32);
+- }
+- else {
+- SK_PNMI_STORE_U64(pBuf, Val64);
+- *pLen = sizeof(SK_U64);
+- }
+- break;
+-
+- case OID_GEN_XMIT_ERROR:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+- if (MacType == SK_MAC_XMAC) {
+- Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
+- }
+- else {
+- Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts;
+- }
+-
+- /*
+- * by default 32bit values are evaluated
+- */
+- if (!Is64BitReq) {
+- Val32 = (SK_U32)Val64;
+- SK_PNMI_STORE_U32(pBuf, Val32);
+- *pLen = sizeof(SK_U32);
+- }
+- else {
+- SK_PNMI_STORE_U64(pBuf, Val64);
+- *pLen = sizeof(SK_U64);
+- }
+- break;
+-
+- case OID_GEN_RCV_NO_BUFFER:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+- if (MacType == SK_MAC_XMAC) {
+- Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
+- }
+- else {
+- Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts;
+- }
+-
+- /*
+- * by default 32bit values are evaluated
+- */
+- if (!Is64BitReq) {
+- Val32 = (SK_U32)Val64;
+- SK_PNMI_STORE_U32(pBuf, Val32);
+- *pLen = sizeof(SK_U32);
+- }
+- else {
+- SK_PNMI_STORE_U64(pBuf, Val64);
+- *pLen = sizeof(SK_U64);
+- }
+- break;
+-
+- case OID_GEN_TRANSMIT_QUEUE_LENGTH:
+- Val32 = (SK_U32)pAC->Pnmi.Port[NetIndex].TxSwQueueLen;
+- SK_PNMI_STORE_U32(pBuf, Val32);
+- *pLen = sizeof(SK_U32);
+- break;
+-
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR034,
+- SK_PNMI_ERR034MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- if (Id == OID_SKGE_RX_HW_ERROR_CTS ||
+- Id == OID_SKGE_TX_HW_ERROR_CTS ||
+- Id == OID_SKGE_IN_ERRORS_CTS ||
+- Id == OID_SKGE_OUT_ERROR_CTS ||
+- Id == OID_GEN_XMIT_ERROR ||
+- Id == OID_GEN_RCV_ERROR) {
+-
+- pAC->Pnmi.MacUpdatedFlag --;
+- }
+-
+- return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * Rlmt - OID handler function of OID_SKGE_RLMT_XXX single instance.
+- *
+- * Description:
+- * Get/Presets/Sets the RLMT OIDs.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK The request was successfully performed.
+- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
+- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
+- * the correct data (e.g. a 32bit value is
+- * needed, but a 16 bit value was passed).
+- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
+- * value range.
+- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
+- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- * exist (e.g. port instance 3 on a two port
+- * adapter.
+- */
+-PNMI_STATIC int Rlmt(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-int Action, /* GET/PRESET/SET action */
+-SK_U32 Id, /* Object ID that is to be processed */
+-char *pBuf, /* Buffer used for the management data transfer */
+-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+-{
+- int Ret;
+- unsigned int PhysPortIndex;
+- unsigned int PhysPortMax;
+- SK_EVPARA EventParam;
+- SK_U32 Val32;
+- SK_U64 Val64;
+-
+-
+- /*
+- * Check instance. Only single instance OIDs are allowed here.
+- */
+- if (Instance != (SK_U32)(-1) && Instance != 1) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_UNKNOWN_INST);
+- }
+-
+- /*
+- * Perform the requested action.
+- */
+- if (Action == SK_PNMI_GET) {
+-
+- /*
+- * Check if the buffer length is large enough.
+- */
+-
+- switch (Id) {
+-
+- case OID_SKGE_RLMT_MODE:
+- case OID_SKGE_RLMT_PORT_ACTIVE:
+- case OID_SKGE_RLMT_PORT_PREFERRED:
+- if (*pLen < sizeof(SK_U8)) {
+-
+- *pLen = sizeof(SK_U8);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- break;
+-
+- case OID_SKGE_RLMT_PORT_NUMBER:
+- if (*pLen < sizeof(SK_U32)) {
+-
+- *pLen = sizeof(SK_U32);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- break;
+-
+- case OID_SKGE_RLMT_CHANGE_CTS:
+- case OID_SKGE_RLMT_CHANGE_TIME:
+- case OID_SKGE_RLMT_CHANGE_ESTIM:
+- case OID_SKGE_RLMT_CHANGE_THRES:
+- if (*pLen < sizeof(SK_U64)) {
+-
+- *pLen = sizeof(SK_U64);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- break;
+-
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR035,
+- SK_PNMI_ERR035MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- /*
+- * Update RLMT statistic and increment semaphores to indicate
+- * that an update was already done. Maybe RLMT will hold its
+- * statistic always up to date some time. Then we can
+- * remove this type of call.
+- */
+- if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
+-
+- *pLen = 0;
+- return (Ret);
+- }
+- pAC->Pnmi.RlmtUpdatedFlag ++;
+-
+- /*
+- * Retrieve Value
+- */
+- switch (Id) {
+-
+- case OID_SKGE_RLMT_MODE:
+- *pBuf = (char)pAC->Rlmt.Net[0].RlmtMode;
+- *pLen = sizeof(char);
+- break;
+-
+- case OID_SKGE_RLMT_PORT_NUMBER:
+- Val32 = (SK_U32)pAC->GIni.GIMacsFound;
+- SK_PNMI_STORE_U32(pBuf, Val32);
+- *pLen = sizeof(SK_U32);
+- break;
+-
+- case OID_SKGE_RLMT_PORT_ACTIVE:
+- *pBuf = 0;
+- /*
+- * If multiple ports may become active this OID
+- * doesn't make sense any more. A new variable in
+- * the port structure should be created. However,
+- * for this variable the first active port is
+- * returned.
+- */
+- PhysPortMax = pAC->GIni.GIMacsFound;
+-
+- for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
+- PhysPortIndex ++) {
+-
+- if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+-
+- *pBuf = (char)SK_PNMI_PORT_PHYS2LOG(PhysPortIndex);
+- break;
+- }
+- }
+- *pLen = sizeof(char);
+- break;
+-
+- case OID_SKGE_RLMT_PORT_PREFERRED:
+- *pBuf = (char)SK_PNMI_PORT_PHYS2LOG(pAC->Rlmt.Net[NetIndex].Preference);
+- *pLen = sizeof(char);
+- break;
+-
+- case OID_SKGE_RLMT_CHANGE_CTS:
+- Val64 = pAC->Pnmi.RlmtChangeCts;
+- SK_PNMI_STORE_U64(pBuf, Val64);
+- *pLen = sizeof(SK_U64);
+- break;
+-
+- case OID_SKGE_RLMT_CHANGE_TIME:
+- Val64 = pAC->Pnmi.RlmtChangeTime;
+- SK_PNMI_STORE_U64(pBuf, Val64);
+- *pLen = sizeof(SK_U64);
+- break;
+-
+- case OID_SKGE_RLMT_CHANGE_ESTIM:
+- Val64 = pAC->Pnmi.RlmtChangeEstimate.Estimate;
+- SK_PNMI_STORE_U64(pBuf, Val64);
+- *pLen = sizeof(SK_U64);
+- break;
+-
+- case OID_SKGE_RLMT_CHANGE_THRES:
+- Val64 = pAC->Pnmi.RlmtChangeThreshold;
+- SK_PNMI_STORE_U64(pBuf, Val64);
+- *pLen = sizeof(SK_U64);
+- break;
+-
+- default:
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
+- ("Rlmt: Unknown OID should be handled before"));
+-
+- pAC->Pnmi.RlmtUpdatedFlag --;
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- pAC->Pnmi.RlmtUpdatedFlag --;
+- }
+- else {
+- /* Perform a preset or set */
+- switch (Id) {
+-
+- case OID_SKGE_RLMT_MODE:
+- /* Check if the buffer length is plausible */
+- if (*pLen < sizeof(char)) {
+-
+- *pLen = sizeof(char);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- /* Check if the value range is correct */
+- if (*pLen != sizeof(char) ||
+- (*pBuf & SK_PNMI_RLMT_MODE_CHK_LINK) == 0 ||
+- *(SK_U8 *)pBuf > 15) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_BAD_VALUE);
+- }
+- /* The preset ends here */
+- if (Action == SK_PNMI_PRESET) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_OK);
+- }
+- /* Send an event to RLMT to change the mode */
+- SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+- EventParam.Para32[0] |= (SK_U32)(*pBuf);
+- EventParam.Para32[1] = 0;
+- if (SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE,
+- EventParam) > 0) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR037,
+- SK_PNMI_ERR037MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- break;
+-
+- case OID_SKGE_RLMT_PORT_PREFERRED:
+- /* Check if the buffer length is plausible */
+- if (*pLen < sizeof(char)) {
+-
+- *pLen = sizeof(char);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- /* Check if the value range is correct */
+- if (*pLen != sizeof(char) || *(SK_U8 *)pBuf >
+- (SK_U8)pAC->GIni.GIMacsFound) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_BAD_VALUE);
+- }
+- /* The preset ends here */
+- if (Action == SK_PNMI_PRESET) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_OK);
+- }
+-
+- /*
+- * Send an event to RLMT change the preferred port.
+- * A param of -1 means automatic mode. RLMT will
+- * make the decision which is the preferred port.
+- */
+- SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+- EventParam.Para32[0] = (SK_U32)(*pBuf) - 1;
+- EventParam.Para32[1] = NetIndex;
+- if (SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE,
+- EventParam) > 0) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR038,
+- SK_PNMI_ERR038MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- break;
+-
+- case OID_SKGE_RLMT_CHANGE_THRES:
+- /* Check if the buffer length is plausible */
+- if (*pLen < sizeof(SK_U64)) {
+-
+- *pLen = sizeof(SK_U64);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- /*
+- * There are not many restrictions to the
+- * value range.
+- */
+- if (*pLen != sizeof(SK_U64)) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_BAD_VALUE);
+- }
+- /* A preset ends here */
+- if (Action == SK_PNMI_PRESET) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_OK);
+- }
+- /*
+- * Store the new threshold, which will be taken
+- * on the next timer event.
+- */
+- SK_PNMI_READ_U64(pBuf, Val64);
+- pAC->Pnmi.RlmtChangeThreshold = Val64;
+- break;
+-
+- default:
+- /* The other OIDs are not be able for set */
+- *pLen = 0;
+- return (SK_PNMI_ERR_READ_ONLY);
+- }
+- }
+-
+- return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * RlmtStat - OID handler function of OID_SKGE_RLMT_XXX multiple instance.
+- *
+- * Description:
+- * Performs get requests on multiple instance variables.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK The request was successfully performed.
+- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
+- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
+- * the correct data (e.g. a 32bit value is
+- * needed, but a 16 bit value was passed).
+- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- * exist (e.g. port instance 3 on a two port
+- * adapter.
+- */
+-PNMI_STATIC int RlmtStat(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-int Action, /* GET/PRESET/SET action */
+-SK_U32 Id, /* Object ID that is to be processed */
+-char *pBuf, /* Buffer used for the management data transfer */
+-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+-{
+- unsigned int PhysPortMax;
+- unsigned int PhysPortIndex;
+- unsigned int Limit;
+- unsigned int Offset;
+- int Ret;
+- SK_U32 Val32;
+- SK_U64 Val64;
+-
+- /*
+- * Calculate the port indexes from the instance.
+- */
+- PhysPortMax = pAC->GIni.GIMacsFound;
+-
+- if ((Instance != (SK_U32)(-1))) {
+- /* Check instance range */
+- if ((Instance < 1) || (Instance > PhysPortMax)) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_UNKNOWN_INST);
+- }
+-
+- /* Single net mode */
+- PhysPortIndex = Instance - 1;
+-
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- PhysPortIndex = NetIndex;
+- }
+-
+- /* Both net modes */
+- Limit = PhysPortIndex + 1;
+- }
+- else {
+- /* Single net mode */
+- PhysPortIndex = 0;
+- Limit = PhysPortMax;
+-
+- /* Dual net mode */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- PhysPortIndex = NetIndex;
+- Limit = PhysPortIndex + 1;
+- }
+- }
+-
+- /*
+- * Currently only get requests are allowed.
+- */
+- if (Action != SK_PNMI_GET) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_READ_ONLY);
+- }
+-
+- /*
+- * Check if the buffer length is large enough.
+- */
+- switch (Id) {
+-
+- case OID_SKGE_RLMT_PORT_INDEX:
+- case OID_SKGE_RLMT_STATUS:
+- if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) {
+-
+- *pLen = (Limit - PhysPortIndex) * sizeof(SK_U32);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- break;
+-
+- case OID_SKGE_RLMT_TX_HELLO_CTS:
+- case OID_SKGE_RLMT_RX_HELLO_CTS:
+- case OID_SKGE_RLMT_TX_SP_REQ_CTS:
+- case OID_SKGE_RLMT_RX_SP_CTS:
+- if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U64)) {
+-
+- *pLen = (Limit - PhysPortIndex) * sizeof(SK_U64);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- break;
+-
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR039,
+- SK_PNMI_ERR039MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+-
+- }
+-
+- /*
+- * Update statistic and increment semaphores to indicate that
+- * an update was already done.
+- */
+- if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
+-
+- *pLen = 0;
+- return (Ret);
+- }
+- pAC->Pnmi.RlmtUpdatedFlag ++;
+-
+- /*
+- * Get value
+- */
+- Offset = 0;
+- for (; PhysPortIndex < Limit; PhysPortIndex ++) {
+-
+- switch (Id) {
+-
+- case OID_SKGE_RLMT_PORT_INDEX:
+- Val32 = PhysPortIndex;
+- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+- Offset += sizeof(SK_U32);
+- break;
+-
+- case OID_SKGE_RLMT_STATUS:
+- if (pAC->Rlmt.Port[PhysPortIndex].PortState ==
+- SK_RLMT_PS_INIT ||
+- pAC->Rlmt.Port[PhysPortIndex].PortState ==
+- SK_RLMT_PS_DOWN) {
+-
+- Val32 = SK_PNMI_RLMT_STATUS_ERROR;
+- }
+- else if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+-
+- Val32 = SK_PNMI_RLMT_STATUS_ACTIVE;
+- }
+- else {
+- Val32 = SK_PNMI_RLMT_STATUS_STANDBY;
+- }
+- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+- Offset += sizeof(SK_U32);
+- break;
+-
+- case OID_SKGE_RLMT_TX_HELLO_CTS:
+- Val64 = pAC->Rlmt.Port[PhysPortIndex].TxHelloCts;
+- SK_PNMI_STORE_U64(pBuf + Offset, Val64);
+- Offset += sizeof(SK_U64);
+- break;
+-
+- case OID_SKGE_RLMT_RX_HELLO_CTS:
+- Val64 = pAC->Rlmt.Port[PhysPortIndex].RxHelloCts;
+- SK_PNMI_STORE_U64(pBuf + Offset, Val64);
+- Offset += sizeof(SK_U64);
+- break;
+-
+- case OID_SKGE_RLMT_TX_SP_REQ_CTS:
+- Val64 = pAC->Rlmt.Port[PhysPortIndex].TxSpHelloReqCts;
+- SK_PNMI_STORE_U64(pBuf + Offset, Val64);
+- Offset += sizeof(SK_U64);
+- break;
+-
+- case OID_SKGE_RLMT_RX_SP_CTS:
+- Val64 = pAC->Rlmt.Port[PhysPortIndex].RxSpHelloCts;
+- SK_PNMI_STORE_U64(pBuf + Offset, Val64);
+- Offset += sizeof(SK_U64);
+- break;
+-
+- default:
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
+- ("RlmtStat: Unknown OID should be errored before"));
+-
+- pAC->Pnmi.RlmtUpdatedFlag --;
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- }
+- *pLen = Offset;
+-
+- pAC->Pnmi.RlmtUpdatedFlag --;
+-
+- return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * MacPrivateConf - OID handler function of OIDs concerning the configuration
+- *
+- * Description:
+- * Get/Presets/Sets the OIDs concerning the configuration.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK The request was successfully performed.
+- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
+- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
+- * the correct data (e.g. a 32bit value is
+- * needed, but a 16 bit value was passed).
+- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
+- * value range.
+- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
+- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- * exist (e.g. port instance 3 on a two port
+- * adapter.
+- */
+-PNMI_STATIC int MacPrivateConf(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-int Action, /* GET/PRESET/SET action */
+-SK_U32 Id, /* Object ID that is to be processed */
+-char *pBuf, /* Buffer used for the management data transfer */
+-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+-{
+- unsigned int PhysPortMax;
+- unsigned int PhysPortIndex;
+- unsigned int LogPortMax;
+- unsigned int LogPortIndex;
+- unsigned int Limit;
+- unsigned int Offset;
+- char Val8;
+- char *pBufPtr;
+- int Ret;
+- SK_EVPARA EventParam;
+- SK_U32 Val32;
+-
+- /*
+- * Calculate instance if wished. MAC index 0 is the virtual MAC.
+- */
+- PhysPortMax = pAC->GIni.GIMacsFound;
+- LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
+-
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
+- LogPortMax--;
+- }
+-
+- if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
+- /* Check instance range */
+- if ((Instance < 1) || (Instance > LogPortMax)) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_UNKNOWN_INST);
+- }
+- LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
+- Limit = LogPortIndex + 1;
+- }
+-
+- else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
+-
+- LogPortIndex = 0;
+- Limit = LogPortMax;
+- }
+-
+- /*
+- * Perform action
+- */
+- if (Action == SK_PNMI_GET) {
+-
+- /* Check length */
+- switch (Id) {
+-
+- case OID_SKGE_PMD:
+- case OID_SKGE_CONNECTOR:
+- case OID_SKGE_LINK_CAP:
+- case OID_SKGE_LINK_MODE:
+- case OID_SKGE_LINK_MODE_STATUS:
+- case OID_SKGE_LINK_STATUS:
+- case OID_SKGE_FLOWCTRL_CAP:
+- case OID_SKGE_FLOWCTRL_MODE:
+- case OID_SKGE_FLOWCTRL_STATUS:
+- case OID_SKGE_PHY_OPERATION_CAP:
+- case OID_SKGE_PHY_OPERATION_MODE:
+- case OID_SKGE_PHY_OPERATION_STATUS:
+- case OID_SKGE_SPEED_CAP:
+- case OID_SKGE_SPEED_MODE:
+- case OID_SKGE_SPEED_STATUS:
+- if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U8)) {
+-
+- *pLen = (Limit - LogPortIndex) * sizeof(SK_U8);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- break;
+-
+- case OID_SKGE_MTU:
+- case OID_SKGE_PHY_TYPE:
+- if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U32)) {
+-
+- *pLen = (Limit - LogPortIndex) * sizeof(SK_U32);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- break;
+-
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR041,
+- SK_PNMI_ERR041MSG);
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- /*
+- * Update statistic and increment semaphore to indicate
+- * that an update was already done.
+- */
+- if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
+-
+- *pLen = 0;
+- return (Ret);
+- }
+- pAC->Pnmi.SirqUpdatedFlag ++;
+-
+- /*
+- * Get value
+- */
+- Offset = 0;
+- for (; LogPortIndex < Limit; LogPortIndex ++) {
+-
+- pBufPtr = pBuf + Offset;
+-
+- switch (Id) {
+-
+- case OID_SKGE_PMD:
+- *pBufPtr = pAC->Pnmi.PMD;
+- Offset += sizeof(char);
+- break;
+-
+- case OID_SKGE_CONNECTOR:
+- *pBufPtr = pAC->Pnmi.Connector;
+- Offset += sizeof(char);
+- break;
+-
+- case OID_SKGE_PHY_TYPE:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+- if (LogPortIndex == 0) {
+- continue;
+- }
+- else {
+- /* Get value for physical ports */
+- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
+- Val32 = pAC->GIni.GP[PhysPortIndex].PhyType;
+- SK_PNMI_STORE_U32(pBufPtr, Val32);
+- }
+- }
+- else { /* DualNetMode */
+-
+- Val32 = pAC->GIni.GP[NetIndex].PhyType;
+- SK_PNMI_STORE_U32(pBufPtr, Val32);
+- }
+- Offset += sizeof(SK_U32);
+- break;
+-
+- case OID_SKGE_LINK_CAP:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+- if (LogPortIndex == 0) {
+- /* Get value for virtual port */
+- VirtualConf(pAC, IoC, Id, pBufPtr);
+- }
+- else {
+- /* Get value for physical ports */
+- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
+-
+- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkCap;
+- }
+- }
+- else { /* DualNetMode */
+-
+- *pBufPtr = pAC->GIni.GP[NetIndex].PLinkCap;
+- }
+- Offset += sizeof(char);
+- break;
+-
+- case OID_SKGE_LINK_MODE:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+- if (LogPortIndex == 0) {
+- /* Get value for virtual port */
+- VirtualConf(pAC, IoC, Id, pBufPtr);
+- }
+- else {
+- /* Get value for physical ports */
+- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
+-
+- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkModeConf;
+- }
+- }
+- else { /* DualNetMode */
+-
+- *pBufPtr = pAC->GIni.GP[NetIndex].PLinkModeConf;
+- }
+- Offset += sizeof(char);
+- break;
+-
+- case OID_SKGE_LINK_MODE_STATUS:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+- if (LogPortIndex == 0) {
+- /* Get value for virtual port */
+- VirtualConf(pAC, IoC, Id, pBufPtr);
+- }
+- else {
+- /* Get value for physical port */
+- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
+-
+- *pBufPtr =
+- CalculateLinkModeStatus(pAC, IoC, PhysPortIndex);
+- }
+- }
+- else { /* DualNetMode */
+-
+- *pBufPtr = CalculateLinkModeStatus(pAC, IoC, NetIndex);
+- }
+- Offset += sizeof(char);
+- break;
+-
+- case OID_SKGE_LINK_STATUS:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+- if (LogPortIndex == 0) {
+- /* Get value for virtual port */
+- VirtualConf(pAC, IoC, Id, pBufPtr);
+- }
+- else {
+- /* Get value for physical ports */
+- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
+-
+- *pBufPtr = CalculateLinkStatus(pAC, IoC, PhysPortIndex);
+- }
+- }
+- else { /* DualNetMode */
+-
+- *pBufPtr = CalculateLinkStatus(pAC, IoC, NetIndex);
+- }
+- Offset += sizeof(char);
+- break;
+-
+- case OID_SKGE_FLOWCTRL_CAP:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+- if (LogPortIndex == 0) {
+- /* Get value for virtual port */
+- VirtualConf(pAC, IoC, Id, pBufPtr);
+- }
+- else {
+- /* Get value for physical ports */
+- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
+-
+- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap;
+- }
+- }
+- else { /* DualNetMode */
+-
+- *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlCap;
+- }
+- Offset += sizeof(char);
+- break;
+-
+- case OID_SKGE_FLOWCTRL_MODE:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+- if (LogPortIndex == 0) {
+- /* Get value for virtual port */
+- VirtualConf(pAC, IoC, Id, pBufPtr);
+- }
+- else {
+- /* Get value for physical port */
+- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
+-
+- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlMode;
+- }
+- }
+- else { /* DualNetMode */
+-
+- *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlMode;
+- }
+- Offset += sizeof(char);
+- break;
+-
+- case OID_SKGE_FLOWCTRL_STATUS:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+- if (LogPortIndex == 0) {
+- /* Get value for virtual port */
+- VirtualConf(pAC, IoC, Id, pBufPtr);
+- }
+- else {
+- /* Get value for physical port */
+- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
+-
+- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlStatus;
+- }
+- }
+- else { /* DualNetMode */
+-
+- *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlStatus;
+- }
+- Offset += sizeof(char);
+- break;
+-
+- case OID_SKGE_PHY_OPERATION_CAP:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+- if (LogPortIndex == 0) {
+- /* Get value for virtual port */
+- VirtualConf(pAC, IoC, Id, pBufPtr);
+- }
+- else {
+- /* Get value for physical ports */
+- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
+-
+- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSCap;
+- }
+- }
+- else { /* DualNetMode */
+-
+- *pBufPtr = pAC->GIni.GP[NetIndex].PMSCap;
+- }
+- Offset += sizeof(char);
+- break;
+-
+- case OID_SKGE_PHY_OPERATION_MODE:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+- if (LogPortIndex == 0) {
+- /* Get value for virtual port */
+- VirtualConf(pAC, IoC, Id, pBufPtr);
+- }
+- else {
+- /* Get value for physical port */
+- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
+-
+- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSMode;
+- }
+- }
+- else { /* DualNetMode */
+-
+- *pBufPtr = pAC->GIni.GP[NetIndex].PMSMode;
+- }
+- Offset += sizeof(char);
+- break;
+-
+- case OID_SKGE_PHY_OPERATION_STATUS:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+- if (LogPortIndex == 0) {
+- /* Get value for virtual port */
+- VirtualConf(pAC, IoC, Id, pBufPtr);
+- }
+- else {
+- /* Get value for physical port */
+- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
+-
+- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSStatus;
+- }
+- }
+- else {
+-
+- *pBufPtr = pAC->GIni.GP[NetIndex].PMSStatus;
+- }
+- Offset += sizeof(char);
+- break;
+-
+- case OID_SKGE_SPEED_CAP:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+- if (LogPortIndex == 0) {
+- /* Get value for virtual port */
+- VirtualConf(pAC, IoC, Id, pBufPtr);
+- }
+- else {
+- /* Get value for physical ports */
+- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
+-
+- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedCap;
+- }
+- }
+- else { /* DualNetMode */
+-
+- *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedCap;
+- }
+- Offset += sizeof(char);
+- break;
+-
+- case OID_SKGE_SPEED_MODE:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+- if (LogPortIndex == 0) {
+- /* Get value for virtual port */
+- VirtualConf(pAC, IoC, Id, pBufPtr);
+- }
+- else {
+- /* Get value for physical port */
+- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
+-
+- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeed;
+- }
+- }
+- else { /* DualNetMode */
+-
+- *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeed;
+- }
+- Offset += sizeof(char);
+- break;
+-
+- case OID_SKGE_SPEED_STATUS:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
+- if (LogPortIndex == 0) {
+- /* Get value for virtual port */
+- VirtualConf(pAC, IoC, Id, pBufPtr);
+- }
+- else {
+- /* Get value for physical port */
+- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
+-
+- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed;
+- }
+- }
+- else { /* DualNetMode */
+-
+- *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedUsed;
+- }
+- Offset += sizeof(char);
+- break;
+-
+- case OID_SKGE_MTU:
+- Val32 = SK_DRIVER_GET_MTU(pAC, IoC, NetIndex);
+- SK_PNMI_STORE_U32(pBufPtr, Val32);
+- Offset += sizeof(SK_U32);
+- break;
+-
+- default:
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
+- ("MacPrivateConf: Unknown OID should be handled before"));
+-
+- pAC->Pnmi.SirqUpdatedFlag --;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- }
+- *pLen = Offset;
+- pAC->Pnmi.SirqUpdatedFlag --;
+-
+- return (SK_PNMI_ERR_OK);
+- }
+-
+- /*
+- * From here SET or PRESET action. Check if the passed
+- * buffer length is plausible.
+- */
+- switch (Id) {
+-
+- case OID_SKGE_LINK_MODE:
+- case OID_SKGE_FLOWCTRL_MODE:
+- case OID_SKGE_PHY_OPERATION_MODE:
+- case OID_SKGE_SPEED_MODE:
+- if (*pLen < Limit - LogPortIndex) {
+-
+- *pLen = Limit - LogPortIndex;
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- if (*pLen != Limit - LogPortIndex) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_BAD_VALUE);
+- }
+- break;
+-
+- case OID_SKGE_MTU:
+- if (*pLen < sizeof(SK_U32)) {
+-
+- *pLen = sizeof(SK_U32);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- if (*pLen != sizeof(SK_U32)) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_BAD_VALUE);
+- }
+- break;
+-
+- default:
+- *pLen = 0;
+- return (SK_PNMI_ERR_READ_ONLY);
+- }
+-
+- /*
+- * Perform preset or set
+- */
+- Offset = 0;
+- for (; LogPortIndex < Limit; LogPortIndex ++) {
+-
+- switch (Id) {
+-
+- case OID_SKGE_LINK_MODE:
+- /* Check the value range */
+- Val8 = *(pBuf + Offset);
+- if (Val8 == 0) {
+-
+- Offset += sizeof(char);
+- break;
+- }
+- if (Val8 < SK_LMODE_HALF ||
+- (LogPortIndex != 0 && Val8 > SK_LMODE_AUTOSENSE) ||
+- (LogPortIndex == 0 && Val8 > SK_LMODE_INDETERMINATED)) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_BAD_VALUE);
+- }
+-
+- /* The preset ends here */
+- if (Action == SK_PNMI_PRESET) {
+-
+- return (SK_PNMI_ERR_OK);
+- }
+-
+- if (LogPortIndex == 0) {
+-
+- /*
+- * The virtual port consists of all currently
+- * active ports. Find them and send an event
+- * with the new link mode to SIRQ.
+- */
+- for (PhysPortIndex = 0;
+- PhysPortIndex < PhysPortMax;
+- PhysPortIndex ++) {
+-
+- if (!pAC->Pnmi.Port[PhysPortIndex].
+- ActiveFlag) {
+-
+- continue;
+- }
+-
+- EventParam.Para32[0] = PhysPortIndex;
+- EventParam.Para32[1] = (SK_U32)Val8;
+- if (SkGeSirqEvent(pAC, IoC,
+- SK_HWEV_SET_LMODE,
+- EventParam) > 0) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW,
+- SK_PNMI_ERR043,
+- SK_PNMI_ERR043MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- }
+- }
+- else {
+- /*
+- * Send an event with the new link mode to
+- * the SIRQ module.
+- */
+- EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
+- EventParam.Para32[1] = (SK_U32)Val8;
+- if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE,
+- EventParam) > 0) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW,
+- SK_PNMI_ERR043,
+- SK_PNMI_ERR043MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- }
+- Offset += sizeof(char);
+- break;
+-
+- case OID_SKGE_FLOWCTRL_MODE:
+- /* Check the value range */
+- Val8 = *(pBuf + Offset);
+- if (Val8 == 0) {
+-
+- Offset += sizeof(char);
+- break;
+- }
+- if (Val8 < SK_FLOW_MODE_NONE ||
+- (LogPortIndex != 0 && Val8 > SK_FLOW_MODE_SYM_OR_REM) ||
+- (LogPortIndex == 0 && Val8 > SK_FLOW_MODE_INDETERMINATED)) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_BAD_VALUE);
+- }
+-
+- /* The preset ends here */
+- if (Action == SK_PNMI_PRESET) {
+-
+- return (SK_PNMI_ERR_OK);
+- }
+-
+- if (LogPortIndex == 0) {
+-
+- /*
+- * The virtual port consists of all currently
+- * active ports. Find them and send an event
+- * with the new flow control mode to SIRQ.
+- */
+- for (PhysPortIndex = 0;
+- PhysPortIndex < PhysPortMax;
+- PhysPortIndex ++) {
+-
+- if (!pAC->Pnmi.Port[PhysPortIndex].
+- ActiveFlag) {
+-
+- continue;
+- }
+-
+- EventParam.Para32[0] = PhysPortIndex;
+- EventParam.Para32[1] = (SK_U32)Val8;
+- if (SkGeSirqEvent(pAC, IoC,
+- SK_HWEV_SET_FLOWMODE,
+- EventParam) > 0) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW,
+- SK_PNMI_ERR044,
+- SK_PNMI_ERR044MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- }
+- }
+- else {
+- /*
+- * Send an event with the new flow control
+- * mode to the SIRQ module.
+- */
+- EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
+- EventParam.Para32[1] = (SK_U32)Val8;
+- if (SkGeSirqEvent(pAC, IoC,
+- SK_HWEV_SET_FLOWMODE, EventParam)
+- > 0) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW,
+- SK_PNMI_ERR044,
+- SK_PNMI_ERR044MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- }
+- Offset += sizeof(char);
+- break;
+-
+- case OID_SKGE_PHY_OPERATION_MODE :
+- /* Check the value range */
+- Val8 = *(pBuf + Offset);
+- if (Val8 == 0) {
+- /* mode of this port remains unchanged */
+- Offset += sizeof(char);
+- break;
+- }
+- if (Val8 < SK_MS_MODE_AUTO ||
+- (LogPortIndex != 0 && Val8 > SK_MS_MODE_SLAVE) ||
+- (LogPortIndex == 0 && Val8 > SK_MS_MODE_INDETERMINATED)) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_BAD_VALUE);
+- }
+-
+- /* The preset ends here */
+- if (Action == SK_PNMI_PRESET) {
+-
+- return (SK_PNMI_ERR_OK);
+- }
+-
+- if (LogPortIndex == 0) {
+-
+- /*
+- * The virtual port consists of all currently
+- * active ports. Find them and send an event
+- * with new master/slave (role) mode to SIRQ.
+- */
+- for (PhysPortIndex = 0;
+- PhysPortIndex < PhysPortMax;
+- PhysPortIndex ++) {
+-
+- if (!pAC->Pnmi.Port[PhysPortIndex].
+- ActiveFlag) {
+-
+- continue;
+- }
+-
+- EventParam.Para32[0] = PhysPortIndex;
+- EventParam.Para32[1] = (SK_U32)Val8;
+- if (SkGeSirqEvent(pAC, IoC,
+- SK_HWEV_SET_ROLE,
+- EventParam) > 0) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW,
+- SK_PNMI_ERR042,
+- SK_PNMI_ERR042MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- }
+- }
+- else {
+- /*
+- * Send an event with the new master/slave
+- * (role) mode to the SIRQ module.
+- */
+- EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
+- EventParam.Para32[1] = (SK_U32)Val8;
+- if (SkGeSirqEvent(pAC, IoC,
+- SK_HWEV_SET_ROLE, EventParam) > 0) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW,
+- SK_PNMI_ERR042,
+- SK_PNMI_ERR042MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- }
+-
+- Offset += sizeof(char);
+- break;
+-
+- case OID_SKGE_SPEED_MODE:
+- /* Check the value range */
+- Val8 = *(pBuf + Offset);
+- if (Val8 == 0) {
+-
+- Offset += sizeof(char);
+- break;
+- }
+- if (Val8 < (SK_LSPEED_AUTO) ||
+- (LogPortIndex != 0 && Val8 > (SK_LSPEED_1000MBPS)) ||
+- (LogPortIndex == 0 && Val8 > (SK_LSPEED_INDETERMINATED))) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_BAD_VALUE);
+- }
+-
+- /* The preset ends here */
+- if (Action == SK_PNMI_PRESET) {
+-
+- return (SK_PNMI_ERR_OK);
+- }
+-
+- if (LogPortIndex == 0) {
+-
+- /*
+- * The virtual port consists of all currently
+- * active ports. Find them and send an event
+- * with the new flow control mode to SIRQ.
+- */
+- for (PhysPortIndex = 0;
+- PhysPortIndex < PhysPortMax;
+- PhysPortIndex ++) {
+-
+- if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+-
+- continue;
+- }
+-
+- EventParam.Para32[0] = PhysPortIndex;
+- EventParam.Para32[1] = (SK_U32)Val8;
+- if (SkGeSirqEvent(pAC, IoC,
+- SK_HWEV_SET_SPEED,
+- EventParam) > 0) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW,
+- SK_PNMI_ERR045,
+- SK_PNMI_ERR045MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- }
+- }
+- else {
+- /*
+- * Send an event with the new flow control
+- * mode to the SIRQ module.
+- */
+- EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
+- EventParam.Para32[1] = (SK_U32)Val8;
+- if (SkGeSirqEvent(pAC, IoC,
+- SK_HWEV_SET_SPEED,
+- EventParam) > 0) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW,
+- SK_PNMI_ERR045,
+- SK_PNMI_ERR045MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- }
+- Offset += sizeof(char);
+- break;
+-
+- case OID_SKGE_MTU :
+- /* Check the value range */
+- Val32 = *(SK_U32*)(pBuf + Offset);
+- if (Val32 == 0) {
+- /* mtu of this port remains unchanged */
+- Offset += sizeof(SK_U32);
+- break;
+- }
+- if (SK_DRIVER_PRESET_MTU(pAC, IoC, NetIndex, Val32) != 0) {
+- *pLen = 0;
+- return (SK_PNMI_ERR_BAD_VALUE);
+- }
+-
+- /* The preset ends here */
+- if (Action == SK_PNMI_PRESET) {
+- return (SK_PNMI_ERR_OK);
+- }
+-
+- if (SK_DRIVER_SET_MTU(pAC, IoC, NetIndex, Val32) != 0) {
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- Offset += sizeof(SK_U32);
+- break;
+-
+- default:
+- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
+- ("MacPrivateConf: Unknown OID should be handled before set"));
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- }
+-
+- return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * Monitor - OID handler function for RLMT_MONITOR_XXX
+- *
+- * Description:
+- * Because RLMT currently does not support the monitoring of
+- * remote adapter cards, we return always an empty table.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK The request was successfully performed.
+- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
+- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
+- * the correct data (e.g. a 32bit value is
+- * needed, but a 16 bit value was passed).
+- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
+- * value range.
+- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
+- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- * exist (e.g. port instance 3 on a two port
+- * adapter.
+- */
+-PNMI_STATIC int Monitor(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-int Action, /* GET/PRESET/SET action */
+-SK_U32 Id, /* Object ID that is to be processed */
+-char *pBuf, /* Buffer used for the management data transfer */
+-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+-{
+- unsigned int Index;
+- unsigned int Limit;
+- unsigned int Offset;
+- unsigned int Entries;
+-
+-
+- /*
+- * Calculate instance if wished.
+- */
+- /* XXX Not yet implemented. Return always an empty table. */
+- Entries = 0;
+-
+- if ((Instance != (SK_U32)(-1))) {
+-
+- if ((Instance < 1) || (Instance > Entries)) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_UNKNOWN_INST);
+- }
+-
+- Index = (unsigned int)Instance - 1;
+- Limit = (unsigned int)Instance;
+- }
+- else {
+- Index = 0;
+- Limit = Entries;
+- }
+-
+- /*
+- * Get/Set value
+- */
+- if (Action == SK_PNMI_GET) {
+-
+- for (Offset=0; Index < Limit; Index ++) {
+-
+- switch (Id) {
+-
+- case OID_SKGE_RLMT_MONITOR_INDEX:
+- case OID_SKGE_RLMT_MONITOR_ADDR:
+- case OID_SKGE_RLMT_MONITOR_ERRS:
+- case OID_SKGE_RLMT_MONITOR_TIMESTAMP:
+- case OID_SKGE_RLMT_MONITOR_ADMIN:
+- break;
+-
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR046,
+- SK_PNMI_ERR046MSG);
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- }
+- *pLen = Offset;
+- }
+- else {
+- /* Only MONITOR_ADMIN can be set */
+- if (Id != OID_SKGE_RLMT_MONITOR_ADMIN) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_READ_ONLY);
+- }
+-
+- /* Check if the length is plausible */
+- if (*pLen < (Limit - Index)) {
+-
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- /* Okay, we have a wide value range */
+- if (*pLen != (Limit - Index)) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_BAD_VALUE);
+- }
+-/*
+- for (Offset=0; Index < Limit; Index ++) {
+- }
+-*/
+-/*
+- * XXX Not yet implemented. Return always BAD_VALUE, because the table
+- * is empty.
+- */
+- *pLen = 0;
+- return (SK_PNMI_ERR_BAD_VALUE);
+- }
+-
+- return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * VirtualConf - Calculates the values of configuration OIDs for virtual port
+- *
+- * Description:
+- * We handle here the get of the configuration group OIDs, which are
+- * a little bit complicated. The virtual port consists of all currently
+- * active physical ports. If multiple ports are active and configured
+- * differently we get in some trouble to return a single value. So we
+- * get the value of the first active port and compare it with that of
+- * the other active ports. If they are not the same, we return a value
+- * that indicates that the state is indeterminated.
+- *
+- * Returns:
+- * Nothing
+- */
+-PNMI_STATIC void VirtualConf(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-SK_U32 Id, /* Object ID that is to be processed */
+-char *pBuf) /* Buffer used for the management data transfer */
+-{
+- unsigned int PhysPortMax;
+- unsigned int PhysPortIndex;
+- SK_U8 Val8;
+- SK_U32 Val32;
+- SK_BOOL PortActiveFlag;
+- SK_GEPORT *pPrt;
+-
+- *pBuf = 0;
+- PortActiveFlag = SK_FALSE;
+- PhysPortMax = pAC->GIni.GIMacsFound;
+-
+- for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
+- PhysPortIndex ++) {
+-
+- pPrt = &pAC->GIni.GP[PhysPortIndex];
+-
+- /* Check if the physical port is active */
+- if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+-
+- continue;
+- }
+-
+- PortActiveFlag = SK_TRUE;
+-
+- switch (Id) {
+-
+- case OID_SKGE_PHY_TYPE:
+- /* Check if it is the first active port */
+- if (*pBuf == 0) {
+- Val32 = pPrt->PhyType;
+- SK_PNMI_STORE_U32(pBuf, Val32);
+- continue;
+- }
+-
+- case OID_SKGE_LINK_CAP:
+-
+- /*
+- * Different capabilities should not happen, but
+- * in the case of the cases OR them all together.
+- * From a curious point of view the virtual port
+- * is capable of all found capabilities.
+- */
+- *pBuf |= pPrt->PLinkCap;
+- break;
+-
+- case OID_SKGE_LINK_MODE:
+- /* Check if it is the first active port */
+- if (*pBuf == 0) {
+-
+- *pBuf = pPrt->PLinkModeConf;
+- continue;
+- }
+-
+- /*
+- * If we find an active port with a different link
+- * mode than the first one we return a value that
+- * indicates that the link mode is indeterminated.
+- */
+- if (*pBuf != pPrt->PLinkModeConf) {
+-
+- *pBuf = SK_LMODE_INDETERMINATED;
+- }
+- break;
+-
+- case OID_SKGE_LINK_MODE_STATUS:
+- /* Get the link mode of the physical port */
+- Val8 = CalculateLinkModeStatus(pAC, IoC, PhysPortIndex);
+-
+- /* Check if it is the first active port */
+- if (*pBuf == 0) {
+-
+- *pBuf = Val8;
+- continue;
+- }
+-
+- /*
+- * If we find an active port with a different link
+- * mode status than the first one we return a value
+- * that indicates that the link mode status is
+- * indeterminated.
+- */
+- if (*pBuf != Val8) {
+-
+- *pBuf = SK_LMODE_STAT_INDETERMINATED;
+- }
+- break;
+-
+- case OID_SKGE_LINK_STATUS:
+- /* Get the link status of the physical port */
+- Val8 = CalculateLinkStatus(pAC, IoC, PhysPortIndex);
+-
+- /* Check if it is the first active port */
+- if (*pBuf == 0) {
+-
+- *pBuf = Val8;
+- continue;
+- }
+-
+- /*
+- * If we find an active port with a different link
+- * status than the first one, we return a value
+- * that indicates that the link status is
+- * indeterminated.
+- */
+- if (*pBuf != Val8) {
+-
+- *pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED;
+- }
+- break;
+-
+- case OID_SKGE_FLOWCTRL_CAP:
+- /* Check if it is the first active port */
+- if (*pBuf == 0) {
+-
+- *pBuf = pPrt->PFlowCtrlCap;
+- continue;
+- }
+-
+- /*
+- * From a curious point of view the virtual port
+- * is capable of all found capabilities.
+- */
+- *pBuf |= pPrt->PFlowCtrlCap;
+- break;
+-
+- case OID_SKGE_FLOWCTRL_MODE:
+- /* Check if it is the first active port */
+- if (*pBuf == 0) {
+-
+- *pBuf = pPrt->PFlowCtrlMode;
+- continue;
+- }
+-
+- /*
+- * If we find an active port with a different flow
+- * control mode than the first one, we return a value
+- * that indicates that the mode is indeterminated.
+- */
+- if (*pBuf != pPrt->PFlowCtrlMode) {
+-
+- *pBuf = SK_FLOW_MODE_INDETERMINATED;
+- }
+- break;
+-
+- case OID_SKGE_FLOWCTRL_STATUS:
+- /* Check if it is the first active port */
+- if (*pBuf == 0) {
+-
+- *pBuf = pPrt->PFlowCtrlStatus;
+- continue;
+- }
+-
+- /*
+- * If we find an active port with a different flow
+- * control status than the first one, we return a
+- * value that indicates that the status is
+- * indeterminated.
+- */
+- if (*pBuf != pPrt->PFlowCtrlStatus) {
+-
+- *pBuf = SK_FLOW_STAT_INDETERMINATED;
+- }
+- break;
+-
+- case OID_SKGE_PHY_OPERATION_CAP:
+- /* Check if it is the first active port */
+- if (*pBuf == 0) {
+-
+- *pBuf = pPrt->PMSCap;
+- continue;
+- }
+-
+- /*
+- * From a curious point of view the virtual port
+- * is capable of all found capabilities.
+- */
+- *pBuf |= pPrt->PMSCap;
+- break;
+-
+- case OID_SKGE_PHY_OPERATION_MODE:
+- /* Check if it is the first active port */
+- if (*pBuf == 0) {
+-
+- *pBuf = pPrt->PMSMode;
+- continue;
+- }
+-
+- /*
+- * If we find an active port with a different master/
+- * slave mode than the first one, we return a value
+- * that indicates that the mode is indeterminated.
+- */
+- if (*pBuf != pPrt->PMSMode) {
+-
+- *pBuf = SK_MS_MODE_INDETERMINATED;
+- }
+- break;
+-
+- case OID_SKGE_PHY_OPERATION_STATUS:
+- /* Check if it is the first active port */
+- if (*pBuf == 0) {
+-
+- *pBuf = pPrt->PMSStatus;
+- continue;
+- }
+-
+- /*
+- * If we find an active port with a different master/
+- * slave status than the first one, we return a
+- * value that indicates that the status is
+- * indeterminated.
+- */
+- if (*pBuf != pPrt->PMSStatus) {
+-
+- *pBuf = SK_MS_STAT_INDETERMINATED;
+- }
+- break;
+-
+- case OID_SKGE_SPEED_MODE:
+- /* Check if it is the first active port */
+- if (*pBuf == 0) {
+-
+- *pBuf = pPrt->PLinkSpeed;
+- continue;
+- }
+-
+- /*
+- * If we find an active port with a different flow
+- * control mode than the first one, we return a value
+- * that indicates that the mode is indeterminated.
+- */
+- if (*pBuf != pPrt->PLinkSpeed) {
+-
+- *pBuf = SK_LSPEED_INDETERMINATED;
+- }
+- break;
+-
+- case OID_SKGE_SPEED_STATUS:
+- /* Check if it is the first active port */
+- if (*pBuf == 0) {
+-
+- *pBuf = pPrt->PLinkSpeedUsed;
+- continue;
+- }
+-
+- /*
+- * If we find an active port with a different flow
+- * control status than the first one, we return a
+- * value that indicates that the status is
+- * indeterminated.
+- */
+- if (*pBuf != pPrt->PLinkSpeedUsed) {
+-
+- *pBuf = SK_LSPEED_STAT_INDETERMINATED;
+- }
+- break;
+- }
+- }
+-
+- /*
+- * If no port is active return an indeterminated answer
+- */
+- if (!PortActiveFlag) {
+-
+- switch (Id) {
+-
+- case OID_SKGE_LINK_CAP:
+- *pBuf = SK_LMODE_CAP_INDETERMINATED;
+- break;
+-
+- case OID_SKGE_LINK_MODE:
+- *pBuf = SK_LMODE_INDETERMINATED;
+- break;
+-
+- case OID_SKGE_LINK_MODE_STATUS:
+- *pBuf = SK_LMODE_STAT_INDETERMINATED;
+- break;
+-
+- case OID_SKGE_LINK_STATUS:
+- *pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED;
+- break;
+-
+- case OID_SKGE_FLOWCTRL_CAP:
+- case OID_SKGE_FLOWCTRL_MODE:
+- *pBuf = SK_FLOW_MODE_INDETERMINATED;
+- break;
+-
+- case OID_SKGE_FLOWCTRL_STATUS:
+- *pBuf = SK_FLOW_STAT_INDETERMINATED;
+- break;
+-
+- case OID_SKGE_PHY_OPERATION_CAP:
+- *pBuf = SK_MS_CAP_INDETERMINATED;
+- break;
+-
+- case OID_SKGE_PHY_OPERATION_MODE:
+- *pBuf = SK_MS_MODE_INDETERMINATED;
+- break;
+-
+- case OID_SKGE_PHY_OPERATION_STATUS:
+- *pBuf = SK_MS_STAT_INDETERMINATED;
+- break;
+- case OID_SKGE_SPEED_CAP:
+- *pBuf = SK_LSPEED_CAP_INDETERMINATED;
+- break;
+-
+- case OID_SKGE_SPEED_MODE:
+- *pBuf = SK_LSPEED_INDETERMINATED;
+- break;
+-
+- case OID_SKGE_SPEED_STATUS:
+- *pBuf = SK_LSPEED_STAT_INDETERMINATED;
+- break;
+- }
+- }
+-}
+-
+-/*****************************************************************************
+- *
+- * CalculateLinkStatus - Determins the link status of a physical port
+- *
+- * Description:
+- * Determins the link status the following way:
+- * LSTAT_PHY_DOWN: Link is down
+- * LSTAT_AUTONEG: Auto-negotiation failed
+- * LSTAT_LOG_DOWN: Link is up but RLMT did not yet put the port
+- * logically up.
+- * LSTAT_LOG_UP: RLMT marked the port as up
+- *
+- * Returns:
+- * Link status of physical port
+- */
+-PNMI_STATIC SK_U8 CalculateLinkStatus(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-unsigned int PhysPortIndex) /* Physical port index */
+-{
+- SK_U8 Result;
+-
+- if (!pAC->GIni.GP[PhysPortIndex].PHWLinkUp) {
+-
+- Result = SK_PNMI_RLMT_LSTAT_PHY_DOWN;
+- }
+- else if (pAC->GIni.GP[PhysPortIndex].PAutoNegFail > 0) {
+-
+- Result = SK_PNMI_RLMT_LSTAT_AUTONEG;
+- }
+- else if (!pAC->Rlmt.Port[PhysPortIndex].PortDown) {
+-
+- Result = SK_PNMI_RLMT_LSTAT_LOG_UP;
+- }
+- else {
+- Result = SK_PNMI_RLMT_LSTAT_LOG_DOWN;
+- }
+-
+- return (Result);
+-}
+-
+-/*****************************************************************************
+- *
+- * CalculateLinkModeStatus - Determins the link mode status of a phys. port
+- *
+- * Description:
+- * The COMMON module only tells us if the mode is half or full duplex.
+- * But in the decade of auto sensing it is useful for the user to
+- * know if the mode was negotiated or forced. Therefore we have a
+- * look to the mode, which was last used by the negotiation process.
+- *
+- * Returns:
+- * The link mode status
+- */
+-PNMI_STATIC SK_U8 CalculateLinkModeStatus(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-unsigned int PhysPortIndex) /* Physical port index */
+-{
+- SK_U8 Result;
+-
+- /* Get the current mode, which can be full or half duplex */
+- Result = pAC->GIni.GP[PhysPortIndex].PLinkModeStatus;
+-
+- /* Check if no valid mode could be found (link is down) */
+- if (Result < SK_LMODE_STAT_HALF) {
+-
+- Result = SK_LMODE_STAT_UNKNOWN;
+- }
+- else if (pAC->GIni.GP[PhysPortIndex].PLinkMode >= SK_LMODE_AUTOHALF) {
+-
+- /*
+- * Auto-negotiation was used to bring up the link. Change
+- * the already found duplex status that it indicates
+- * auto-negotiation was involved.
+- */
+- if (Result == SK_LMODE_STAT_HALF) {
+-
+- Result = SK_LMODE_STAT_AUTOHALF;
+- }
+- else if (Result == SK_LMODE_STAT_FULL) {
+-
+- Result = SK_LMODE_STAT_AUTOFULL;
+- }
+- }
+-
+- return (Result);
+-}
+-
+-/*****************************************************************************
+- *
+- * GetVpdKeyArr - Obtain an array of VPD keys
+- *
+- * Description:
+- * Read the VPD keys and build an array of VPD keys, which are
+- * easy to access.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK Task successfully performed.
+- * SK_PNMI_ERR_GENERAL Something went wrong.
+- */
+-PNMI_STATIC int GetVpdKeyArr(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-char *pKeyArr, /* Ptr KeyArray */
+-unsigned int KeyArrLen, /* Length of array in bytes */
+-unsigned int *pKeyNo) /* Number of keys */
+-{
+- unsigned int BufKeysLen = SK_PNMI_VPD_BUFSIZE;
+- char BufKeys[SK_PNMI_VPD_BUFSIZE];
+- unsigned int StartOffset;
+- unsigned int Offset;
+- int Index;
+- int Ret;
+-
+-
+- SK_MEMSET(pKeyArr, 0, KeyArrLen);
+-
+- /*
+- * Get VPD key list
+- */
+- Ret = VpdKeys(pAC, IoC, (char *)&BufKeys, (int *)&BufKeysLen,
+- (int *)pKeyNo);
+- if (Ret > 0) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR014,
+- SK_PNMI_ERR014MSG);
+-
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- /* If no keys are available return now */
+- if (*pKeyNo == 0 || BufKeysLen == 0) {
+-
+- return (SK_PNMI_ERR_OK);
+- }
+- /*
+- * If the key list is too long for us trunc it and give a
+- * errorlog notification. This case should not happen because
+- * the maximum number of keys is limited due to RAM limitations
+- */
+- if (*pKeyNo > SK_PNMI_VPD_ENTRIES) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR015,
+- SK_PNMI_ERR015MSG);
+-
+- *pKeyNo = SK_PNMI_VPD_ENTRIES;
+- }
+-
+- /*
+- * Now build an array of fixed string length size and copy
+- * the keys together.
+- */
+- for (Index = 0, StartOffset = 0, Offset = 0; Offset < BufKeysLen;
+- Offset ++) {
+-
+- if (BufKeys[Offset] != 0) {
+-
+- continue;
+- }
+-
+- if (Offset - StartOffset > SK_PNMI_VPD_KEY_SIZE) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR016,
+- SK_PNMI_ERR016MSG);
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE,
+- &BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE);
+-
+- Index ++;
+- StartOffset = Offset + 1;
+- }
+-
+- /* Last key not zero terminated? Get it anyway */
+- if (StartOffset < Offset) {
+-
+- SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE,
+- &BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE);
+- }
+-
+- return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * SirqUpdate - Let the SIRQ update its internal values
+- *
+- * Description:
+- * Just to be sure that the SIRQ module holds its internal data
+- * structures up to date, we send an update event before we make
+- * any access.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK Task successfully performed.
+- * SK_PNMI_ERR_GENERAL Something went wrong.
+- */
+-PNMI_STATIC int SirqUpdate(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC) /* IO context handle */
+-{
+- SK_EVPARA EventParam;
+-
+-
+- /* Was the module already updated during the current PNMI call? */
+- if (pAC->Pnmi.SirqUpdatedFlag > 0) {
+-
+- return (SK_PNMI_ERR_OK);
+- }
+-
+- /* Send an synchronuous update event to the module */
+- SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+- if (SkGeSirqEvent(pAC, IoC, SK_HWEV_UPDATE_STAT, EventParam) > 0) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR047,
+- SK_PNMI_ERR047MSG);
+-
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * RlmtUpdate - Let the RLMT update its internal values
+- *
+- * Description:
+- * Just to be sure that the RLMT module holds its internal data
+- * structures up to date, we send an update event before we make
+- * any access.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK Task successfully performed.
+- * SK_PNMI_ERR_GENERAL Something went wrong.
+- */
+-PNMI_STATIC int RlmtUpdate(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */
+-{
+- SK_EVPARA EventParam;
+-
+-
+- /* Was the module already updated during the current PNMI call? */
+- if (pAC->Pnmi.RlmtUpdatedFlag > 0) {
+-
+- return (SK_PNMI_ERR_OK);
+- }
+-
+- /* Send an synchronuous update event to the module */
+- SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+- EventParam.Para32[0] = NetIndex;
+- EventParam.Para32[1] = (SK_U32)-1;
+- if (SkRlmtEvent(pAC, IoC, SK_RLMT_STATS_UPDATE, EventParam) > 0) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR048,
+- SK_PNMI_ERR048MSG);
+-
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * MacUpdate - Force the XMAC to output the current statistic
+- *
+- * Description:
+- * The XMAC holds its statistic internally. To obtain the current
+- * values we must send a command so that the statistic data will
+- * be written to a predefined memory area on the adapter.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK Task successfully performed.
+- * SK_PNMI_ERR_GENERAL Something went wrong.
+- */
+-PNMI_STATIC int MacUpdate(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-unsigned int FirstMac, /* Index of the first Mac to be updated */
+-unsigned int LastMac) /* Index of the last Mac to be updated */
+-{
+- unsigned int MacIndex;
+-
+- /*
+- * Were the statistics already updated during the
+- * current PNMI call?
+- */
+- if (pAC->Pnmi.MacUpdatedFlag > 0) {
+-
+- return (SK_PNMI_ERR_OK);
+- }
+-
+- /* Send an update command to all MACs specified */
+- for (MacIndex = FirstMac; MacIndex <= LastMac; MacIndex ++) {
+-
+- /*
+- * 2002-09-13 pweber: Freeze the current SW counters.
+- * (That should be done as close as
+- * possible to the update of the
+- * HW counters)
+- */
+- if (pAC->GIni.GIMacType == SK_MAC_XMAC) {
+- pAC->Pnmi.BufPort[MacIndex] = pAC->Pnmi.Port[MacIndex];
+- }
+-
+- /* 2002-09-13 pweber: Update the HW counter */
+- if (pAC->GIni.GIFunc.pFnMacUpdateStats(pAC, IoC, MacIndex) != 0) {
+-
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- }
+-
+- return (SK_PNMI_ERR_OK);
+-}
+-
+-/*****************************************************************************
+- *
+- * GetStatVal - Retrieve an XMAC statistic counter
+- *
+- * Description:
+- * Retrieves the statistic counter of a virtual or physical port. The
+- * virtual port is identified by the index 0. It consists of all
+- * currently active ports. To obtain the counter value for this port
+- * we must add the statistic counter of all active ports. To grant
+- * continuous counter values for the virtual port even when port
+- * switches occur we must additionally add a delta value, which was
+- * calculated during a SK_PNMI_EVT_RLMT_ACTIVE_UP event.
+- *
+- * Returns:
+- * Requested statistic value
+- */
+-PNMI_STATIC SK_U64 GetStatVal(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-unsigned int LogPortIndex, /* Index of the logical Port to be processed */
+-unsigned int StatIndex, /* Index to statistic value */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */
+-{
+- unsigned int PhysPortIndex;
+- unsigned int PhysPortMax;
+- SK_U64 Val = 0;
+-
+-
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
+-
+- PhysPortIndex = NetIndex;
+-
+- Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
+- }
+- else { /* Single Net mode */
+-
+- if (LogPortIndex == 0) {
+-
+- PhysPortMax = pAC->GIni.GIMacsFound;
+-
+- /* Add counter of all active ports */
+- for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
+- PhysPortIndex ++) {
+-
+- if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+-
+- Val += GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
+- }
+- }
+-
+- /* Correct value because of port switches */
+- Val += pAC->Pnmi.VirtualCounterOffset[StatIndex];
+- }
+- else {
+- /* Get counter value of physical port */
+- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
+-
+- Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
+- }
+- }
+- return (Val);
+-}
+-
+-/*****************************************************************************
+- *
+- * GetPhysStatVal - Get counter value for physical port
+- *
+- * Description:
+- * Builds a 64bit counter value. Except for the octet counters
+- * the lower 32bit are counted in hardware and the upper 32bit
+- * in software by monitoring counter overflow interrupts in the
+- * event handler. To grant continous counter values during XMAC
+- * resets (caused by a workaround) we must add a delta value.
+- * The delta was calculated in the event handler when a
+- * SK_PNMI_EVT_XMAC_RESET was received.
+- *
+- * Returns:
+- * Counter value
+- */
+-PNMI_STATIC SK_U64 GetPhysStatVal(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-unsigned int PhysPortIndex, /* Index of the logical Port to be processed */
+-unsigned int StatIndex) /* Index to statistic value */
+-{
+- SK_U64 Val = 0;
+- SK_U32 LowVal = 0;
+- SK_U32 HighVal = 0;
+- SK_U16 Word;
+- int MacType;
+- unsigned int HelpIndex;
+- SK_GEPORT *pPrt;
+-
+- SK_PNMI_PORT *pPnmiPrt;
+- SK_GEMACFUNC *pFnMac;
+-
+- pPrt = &pAC->GIni.GP[PhysPortIndex];
+-
+- MacType = pAC->GIni.GIMacType;
+-
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
+- if (MacType == SK_MAC_XMAC) {
+- pPnmiPrt = &pAC->Pnmi.BufPort[PhysPortIndex];
+- }
+- else {
+- pPnmiPrt = &pAC->Pnmi.Port[PhysPortIndex];
+- }
+-
+- pFnMac = &pAC->GIni.GIFunc;
+-
+- switch (StatIndex) {
+- case SK_PNMI_HTX:
+- if (MacType == SK_MAC_GMAC) {
+- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- StatAddr[SK_PNMI_HTX_BROADCAST][MacType].Reg,
+- &LowVal);
+- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- StatAddr[SK_PNMI_HTX_MULTICAST][MacType].Reg,
+- &HighVal);
+- LowVal += HighVal;
+- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- StatAddr[SK_PNMI_HTX_UNICAST][MacType].Reg,
+- &HighVal);
+- LowVal += HighVal;
+- }
+- else {
+- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- StatAddr[StatIndex][MacType].Reg,
+- &LowVal);
+- }
+- HighVal = pPnmiPrt->CounterHigh[StatIndex];
+- break;
+-
+- case SK_PNMI_HRX:
+- if (MacType == SK_MAC_GMAC) {
+- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- StatAddr[SK_PNMI_HRX_BROADCAST][MacType].Reg,
+- &LowVal);
+- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- StatAddr[SK_PNMI_HRX_MULTICAST][MacType].Reg,
+- &HighVal);
+- LowVal += HighVal;
+- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- StatAddr[SK_PNMI_HRX_UNICAST][MacType].Reg,
+- &HighVal);
+- LowVal += HighVal;
+- }
+- else {
+- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- StatAddr[StatIndex][MacType].Reg,
+- &LowVal);
+- }
+- HighVal = pPnmiPrt->CounterHigh[StatIndex];
+- break;
+-
+- case SK_PNMI_HTX_OCTET:
+- case SK_PNMI_HRX_OCTET:
+- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- StatAddr[StatIndex][MacType].Reg,
+- &HighVal);
+- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- StatAddr[StatIndex + 1][MacType].Reg,
+- &LowVal);
+- break;
+-
+- case SK_PNMI_HTX_BURST:
+- case SK_PNMI_HTX_EXCESS_DEF:
+- case SK_PNMI_HTX_CARRIER:
+- /* Not supported by GMAC */
+- if (MacType == SK_MAC_GMAC) {
+- return (Val);
+- }
+-
+- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- StatAddr[StatIndex][MacType].Reg,
+- &LowVal);
+- HighVal = pPnmiPrt->CounterHigh[StatIndex];
+- break;
+-
+- case SK_PNMI_HTX_MACC:
+- /* GMAC only supports PAUSE MAC control frames */
+- if (MacType == SK_MAC_GMAC) {
+- HelpIndex = SK_PNMI_HTX_PMACC;
+- }
+- else {
+- HelpIndex = StatIndex;
+- }
+-
+- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- StatAddr[HelpIndex][MacType].Reg,
+- &LowVal);
+-
+- HighVal = pPnmiPrt->CounterHigh[StatIndex];
+- break;
+-
+- case SK_PNMI_HTX_COL:
+- case SK_PNMI_HRX_UNDERSIZE:
+- /* Not supported by XMAC */
+- if (MacType == SK_MAC_XMAC) {
+- return (Val);
+- }
+-
+- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- StatAddr[StatIndex][MacType].Reg,
+- &LowVal);
+- HighVal = pPnmiPrt->CounterHigh[StatIndex];
+- break;
+-
+- case SK_PNMI_HTX_DEFFERAL:
+- /* Not supported by GMAC */
+- if (MacType == SK_MAC_GMAC) {
+- return (Val);
+- }
+-
+- /*
+- * XMAC counts frames with deferred transmission
+- * even in full-duplex mode.
+- *
+- * In full-duplex mode the counter remains constant!
+- */
+- if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) ||
+- (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL)) {
+-
+- LowVal = 0;
+- HighVal = 0;
+- }
+- else {
+- /* Otherwise get contents of hardware register */
+- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- StatAddr[StatIndex][MacType].Reg,
+- &LowVal);
+- HighVal = pPnmiPrt->CounterHigh[StatIndex];
+- }
+- break;
+-
+- case SK_PNMI_HRX_BADOCTET:
+- /* Not supported by XMAC */
+- if (MacType == SK_MAC_XMAC) {
+- return (Val);
+- }
+-
+- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- StatAddr[StatIndex][MacType].Reg,
+- &HighVal);
+- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- StatAddr[StatIndex + 1][MacType].Reg,
+- &LowVal);
+- break;
+-
+- case SK_PNMI_HTX_OCTETLOW:
+- case SK_PNMI_HRX_OCTETLOW:
+- case SK_PNMI_HRX_BADOCTETLOW:
+- return (Val);
+-
+- case SK_PNMI_HRX_LONGFRAMES:
+- /* For XMAC the SW counter is managed by PNMI */
+- if (MacType == SK_MAC_XMAC) {
+- return (pPnmiPrt->StatRxLongFrameCts);
+- }
+-
+- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- StatAddr[StatIndex][MacType].Reg,
+- &LowVal);
+- HighVal = pPnmiPrt->CounterHigh[StatIndex];
+- break;
+-
+- case SK_PNMI_HRX_TOO_LONG:
+- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- StatAddr[StatIndex][MacType].Reg,
+- &LowVal);
+- HighVal = pPnmiPrt->CounterHigh[StatIndex];
+-
+- Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
+-
+- if (MacType == SK_MAC_GMAC) {
+- /* For GMAC the SW counter is additionally managed by PNMI */
+- Val += pPnmiPrt->StatRxFrameTooLongCts;
+- }
+- else {
+- /*
+- * Frames longer than IEEE 802.3 frame max size are counted
+- * by XMAC in frame_too_long counter even reception of long
+- * frames was enabled and the frame was correct.
+- * So correct the value by subtracting RxLongFrame counter.
+- */
+- Val -= pPnmiPrt->StatRxLongFrameCts;
+- }
+-
+- LowVal = (SK_U32)Val;
+- HighVal = (SK_U32)(Val >> 32);
+- break;
+-
+- case SK_PNMI_HRX_SHORTS:
+- /* Not supported by GMAC */
+- if (MacType == SK_MAC_GMAC) {
+- /* GM_RXE_FRAG?? */
+- return (Val);
+- }
+-
+- /*
+- * XMAC counts short frame errors even if link down (#10620)
+- *
+- * If link-down the counter remains constant
+- */
+- if (pPrt->PLinkModeStatus != SK_LMODE_STAT_UNKNOWN) {
+-
+- /* Otherwise get incremental difference */
+- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- StatAddr[StatIndex][MacType].Reg,
+- &LowVal);
+- HighVal = pPnmiPrt->CounterHigh[StatIndex];
+-
+- Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
+- Val -= pPnmiPrt->RxShortZeroMark;
+-
+- LowVal = (SK_U32)Val;
+- HighVal = (SK_U32)(Val >> 32);
+- }
+- break;
+-
+- case SK_PNMI_HRX_MACC:
+- case SK_PNMI_HRX_MACC_UNKWN:
+- case SK_PNMI_HRX_BURST:
+- case SK_PNMI_HRX_MISSED:
+- case SK_PNMI_HRX_FRAMING:
+- case SK_PNMI_HRX_CARRIER:
+- case SK_PNMI_HRX_IRLENGTH:
+- case SK_PNMI_HRX_SYMBOL:
+- case SK_PNMI_HRX_CEXT:
+- /* Not supported by GMAC */
+- if (MacType == SK_MAC_GMAC) {
+- return (Val);
+- }
+-
+- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- StatAddr[StatIndex][MacType].Reg,
+- &LowVal);
+- HighVal = pPnmiPrt->CounterHigh[StatIndex];
+- break;
+-
+- case SK_PNMI_HRX_PMACC_ERR:
+- /* For GMAC the SW counter is managed by PNMI */
+- if (MacType == SK_MAC_GMAC) {
+- return (pPnmiPrt->StatRxPMaccErr);
+- }
+-
+- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- StatAddr[StatIndex][MacType].Reg,
+- &LowVal);
+- HighVal = pPnmiPrt->CounterHigh[StatIndex];
+- break;
+-
+- /* SW counter managed by PNMI */
+- case SK_PNMI_HTX_SYNC:
+- LowVal = (SK_U32)pPnmiPrt->StatSyncCts;
+- HighVal = (SK_U32)(pPnmiPrt->StatSyncCts >> 32);
+- break;
+-
+- /* SW counter managed by PNMI */
+- case SK_PNMI_HTX_SYNC_OCTET:
+- LowVal = (SK_U32)pPnmiPrt->StatSyncOctetsCts;
+- HighVal = (SK_U32)(pPnmiPrt->StatSyncOctetsCts >> 32);
+- break;
+-
+- case SK_PNMI_HRX_FCS:
+- /*
+- * Broadcom filters FCS errors and counts it in
+- * Receive Error Counter register
+- */
+- if (pPrt->PhyType == SK_PHY_BCOM) {
+- /* do not read while not initialized (PHY_READ hangs!)*/
+- if (pPrt->PState != SK_PRT_RESET) {
+- SkXmPhyRead(pAC, IoC, PhysPortIndex, PHY_BCOM_RE_CTR, &Word);
+-
+- LowVal = Word;
+- }
+- HighVal = pPnmiPrt->CounterHigh[StatIndex];
+- }
+- else {
+- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- StatAddr[StatIndex][MacType].Reg,
+- &LowVal);
+- HighVal = pPnmiPrt->CounterHigh[StatIndex];
+- }
+- break;
+-
+- default:
+- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+- StatAddr[StatIndex][MacType].Reg,
+- &LowVal);
+- HighVal = pPnmiPrt->CounterHigh[StatIndex];
+- break;
+- }
+-
+- Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
+-
+- /* Correct value because of possible XMAC reset. XMAC Errata #2 */
+- Val += pPnmiPrt->CounterOffset[StatIndex];
+-
+- return (Val);
+-}
+-
+-/*****************************************************************************
+- *
+- * ResetCounter - Set all counters and timestamps to zero
+- *
+- * Description:
+- * Notifies other common modules which store statistic data to
+- * reset their counters and finally reset our own counters.
+- *
+- * Returns:
+- * Nothing
+- */
+-PNMI_STATIC void ResetCounter(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-SK_U32 NetIndex)
+-{
+- unsigned int PhysPortIndex;
+- SK_EVPARA EventParam;
+-
+-
+- SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+-
+- /* Notify sensor module */
+- SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_CLEAR, EventParam);
+-
+- /* Notify RLMT module */
+- EventParam.Para32[0] = NetIndex;
+- EventParam.Para32[1] = (SK_U32)-1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STATS_CLEAR, EventParam);
+- EventParam.Para32[1] = 0;
+-
+- /* Notify SIRQ module */
+- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_CLEAR_STAT, EventParam);
+-
+- /* Notify CSUM module */
+-#ifdef SK_USE_CSUM
+- EventParam.Para32[0] = NetIndex;
+- EventParam.Para32[1] = (SK_U32)-1;
+- SkEventQueue(pAC, SKGE_CSUM, SK_CSUM_EVENT_CLEAR_PROTO_STATS,
+- EventParam);
+-#endif /* SK_USE_CSUM */
+-
+- /* Clear XMAC statistic */
+- for (PhysPortIndex = 0; PhysPortIndex <
+- (unsigned int)pAC->GIni.GIMacsFound; PhysPortIndex ++) {
+-
+- (void)pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PhysPortIndex);
+-
+- SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].CounterHigh,
+- 0, sizeof(pAC->Pnmi.Port[PhysPortIndex].CounterHigh));
+- SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
+- CounterOffset, 0, sizeof(pAC->Pnmi.Port[
+- PhysPortIndex].CounterOffset));
+- SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].StatSyncCts,
+- 0, sizeof(pAC->Pnmi.Port[PhysPortIndex].StatSyncCts));
+- SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
+- StatSyncOctetsCts, 0, sizeof(pAC->Pnmi.Port[
+- PhysPortIndex].StatSyncOctetsCts));
+- SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
+- StatRxLongFrameCts, 0, sizeof(pAC->Pnmi.Port[
+- PhysPortIndex].StatRxLongFrameCts));
+- SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
+- StatRxFrameTooLongCts, 0, sizeof(pAC->Pnmi.Port[
+- PhysPortIndex].StatRxFrameTooLongCts));
+- SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
+- StatRxPMaccErr, 0, sizeof(pAC->Pnmi.Port[
+- PhysPortIndex].StatRxPMaccErr));
+- }
+-
+- /*
+- * Clear local statistics
+- */
+- SK_MEMSET((char *)&pAC->Pnmi.VirtualCounterOffset, 0,
+- sizeof(pAC->Pnmi.VirtualCounterOffset));
+- pAC->Pnmi.RlmtChangeCts = 0;
+- pAC->Pnmi.RlmtChangeTime = 0;
+- SK_MEMSET((char *)&pAC->Pnmi.RlmtChangeEstimate.EstValue[0], 0,
+- sizeof(pAC->Pnmi.RlmtChangeEstimate.EstValue));
+- pAC->Pnmi.RlmtChangeEstimate.EstValueIndex = 0;
+- pAC->Pnmi.RlmtChangeEstimate.Estimate = 0;
+- pAC->Pnmi.Port[NetIndex].TxSwQueueMax = 0;
+- pAC->Pnmi.Port[NetIndex].TxRetryCts = 0;
+- pAC->Pnmi.Port[NetIndex].RxIntrCts = 0;
+- pAC->Pnmi.Port[NetIndex].TxIntrCts = 0;
+- pAC->Pnmi.Port[NetIndex].RxNoBufCts = 0;
+- pAC->Pnmi.Port[NetIndex].TxNoBufCts = 0;
+- pAC->Pnmi.Port[NetIndex].TxUsedDescrNo = 0;
+- pAC->Pnmi.Port[NetIndex].RxDeliveredCts = 0;
+- pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts = 0;
+- pAC->Pnmi.Port[NetIndex].ErrRecoveryCts = 0;
+-}
+-
+-/*****************************************************************************
+- *
+- * GetTrapEntry - Get an entry in the trap buffer
+- *
+- * Description:
+- * The trap buffer stores various events. A user application somehow
+- * gets notified that an event occured and retrieves the trap buffer
+- * contens (or simply polls the buffer). The buffer is organized as
+- * a ring which stores the newest traps at the beginning. The oldest
+- * traps are overwritten by the newest ones. Each trap entry has a
+- * unique number, so that applications may detect new trap entries.
+- *
+- * Returns:
+- * A pointer to the trap entry
+- */
+-PNMI_STATIC char* GetTrapEntry(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_U32 TrapId, /* SNMP ID of the trap */
+-unsigned int Size) /* Space needed for trap entry */
+-{
+- unsigned int BufPad = pAC->Pnmi.TrapBufPad;
+- unsigned int BufFree = pAC->Pnmi.TrapBufFree;
+- unsigned int Beg = pAC->Pnmi.TrapQueueBeg;
+- unsigned int End = pAC->Pnmi.TrapQueueEnd;
+- char *pBuf = &pAC->Pnmi.TrapBuf[0];
+- int Wrap;
+- unsigned int NeededSpace;
+- unsigned int EntrySize;
+- SK_U32 Val32;
+- SK_U64 Val64;
+-
+-
+- /* Last byte of entry will get a copy of the entry length */
+- Size ++;
+-
+- /*
+- * Calculate needed buffer space */
+- if (Beg >= Size) {
+-
+- NeededSpace = Size;
+- Wrap = SK_FALSE;
+- }
+- else {
+- NeededSpace = Beg + Size;
+- Wrap = SK_TRUE;
+- }
+-
+- /*
+- * Check if enough buffer space is provided. Otherwise
+- * free some entries. Leave one byte space between begin
+- * and end of buffer to make it possible to detect whether
+- * the buffer is full or empty
+- */
+- while (BufFree < NeededSpace + 1) {
+-
+- if (End == 0) {
+-
+- End = SK_PNMI_TRAP_QUEUE_LEN;
+- }
+-
+- EntrySize = (unsigned int)*((unsigned char *)pBuf + End - 1);
+- BufFree += EntrySize;
+- End -= EntrySize;
+-#ifdef DEBUG
+- SK_MEMSET(pBuf + End, (char)(-1), EntrySize);
+-#endif /* DEBUG */
+- if (End == BufPad) {
+-#ifdef DEBUG
+- SK_MEMSET(pBuf, (char)(-1), End);
+-#endif /* DEBUG */
+- BufFree += End;
+- End = 0;
+- BufPad = 0;
+- }
+- }
+-
+- /*
+- * Insert new entry as first entry. Newest entries are
+- * stored at the beginning of the queue.
+- */
+- if (Wrap) {
+-
+- BufPad = Beg;
+- Beg = SK_PNMI_TRAP_QUEUE_LEN - Size;
+- }
+- else {
+- Beg = Beg - Size;
+- }
+- BufFree -= NeededSpace;
+-
+- /* Save the current offsets */
+- pAC->Pnmi.TrapQueueBeg = Beg;
+- pAC->Pnmi.TrapQueueEnd = End;
+- pAC->Pnmi.TrapBufPad = BufPad;
+- pAC->Pnmi.TrapBufFree = BufFree;
+-
+- /* Initialize the trap entry */
+- *(pBuf + Beg + Size - 1) = (char)Size;
+- *(pBuf + Beg) = (char)Size;
+- Val32 = (pAC->Pnmi.TrapUnique) ++;
+- SK_PNMI_STORE_U32(pBuf + Beg + 1, Val32);
+- SK_PNMI_STORE_U32(pBuf + Beg + 1 + sizeof(SK_U32), TrapId);
+- Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
+- SK_PNMI_STORE_U64(pBuf + Beg + 1 + 2 * sizeof(SK_U32), Val64);
+-
+- return (pBuf + Beg);
+-}
+-
+-/*****************************************************************************
+- *
+- * CopyTrapQueue - Copies the trap buffer for the TRAP OID
+- *
+- * Description:
+- * On a query of the TRAP OID the trap buffer contents will be
+- * copied continuously to the request buffer, which must be large
+- * enough. No length check is performed.
+- *
+- * Returns:
+- * Nothing
+- */
+-PNMI_STATIC void CopyTrapQueue(
+-SK_AC *pAC, /* Pointer to adapter context */
+-char *pDstBuf) /* Buffer to which the queued traps will be copied */
+-{
+- unsigned int BufPad = pAC->Pnmi.TrapBufPad;
+- unsigned int Trap = pAC->Pnmi.TrapQueueBeg;
+- unsigned int End = pAC->Pnmi.TrapQueueEnd;
+- char *pBuf = &pAC->Pnmi.TrapBuf[0];
+- unsigned int Len;
+- unsigned int DstOff = 0;
+-
+-
+- while (Trap != End) {
+-
+- Len = (unsigned int)*(pBuf + Trap);
+-
+- /*
+- * Last byte containing a copy of the length will
+- * not be copied.
+- */
+- *(pDstBuf + DstOff) = (char)(Len - 1);
+- SK_MEMCPY(pDstBuf + DstOff + 1, pBuf + Trap + 1, Len - 2);
+- DstOff += Len - 1;
+-
+- Trap += Len;
+- if (Trap == SK_PNMI_TRAP_QUEUE_LEN) {
+-
+- Trap = BufPad;
+- }
+- }
+-}
+-
+-/*****************************************************************************
+- *
+- * GetTrapQueueLen - Get the length of the trap buffer
+- *
+- * Description:
+- * Evaluates the number of currently stored traps and the needed
+- * buffer size to retrieve them.
+- *
+- * Returns:
+- * Nothing
+- */
+-PNMI_STATIC void GetTrapQueueLen(
+-SK_AC *pAC, /* Pointer to adapter context */
+-unsigned int *pLen, /* Length in Bytes of all queued traps */
+-unsigned int *pEntries) /* Returns number of trapes stored in queue */
+-{
+- unsigned int BufPad = pAC->Pnmi.TrapBufPad;
+- unsigned int Trap = pAC->Pnmi.TrapQueueBeg;
+- unsigned int End = pAC->Pnmi.TrapQueueEnd;
+- char *pBuf = &pAC->Pnmi.TrapBuf[0];
+- unsigned int Len;
+- unsigned int Entries = 0;
+- unsigned int TotalLen = 0;
+-
+-
+- while (Trap != End) {
+-
+- Len = (unsigned int)*(pBuf + Trap);
+- TotalLen += Len - 1;
+- Entries ++;
+-
+- Trap += Len;
+- if (Trap == SK_PNMI_TRAP_QUEUE_LEN) {
+-
+- Trap = BufPad;
+- }
+- }
+-
+- *pEntries = Entries;
+- *pLen = TotalLen;
+-}
+-
+-/*****************************************************************************
+- *
+- * QueueSimpleTrap - Store a simple trap to the trap buffer
+- *
+- * Description:
+- * A simple trap is a trap with now additional data. It consists
+- * simply of a trap code.
+- *
+- * Returns:
+- * Nothing
+- */
+-PNMI_STATIC void QueueSimpleTrap(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_U32 TrapId) /* Type of sensor trap */
+-{
+- GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_SIMPLE_LEN);
+-}
+-
+-/*****************************************************************************
+- *
+- * QueueSensorTrap - Stores a sensor trap in the trap buffer
+- *
+- * Description:
+- * Gets an entry in the trap buffer and fills it with sensor related
+- * data.
+- *
+- * Returns:
+- * Nothing
+- */
+-PNMI_STATIC void QueueSensorTrap(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_U32 TrapId, /* Type of sensor trap */
+-unsigned int SensorIndex) /* Index of sensor which caused the trap */
+-{
+- char *pBuf;
+- unsigned int Offset;
+- unsigned int DescrLen;
+- SK_U32 Val32;
+-
+-
+- /* Get trap buffer entry */
+- DescrLen = SK_STRLEN(pAC->I2c.SenTable[SensorIndex].SenDesc);
+- pBuf = GetTrapEntry(pAC, TrapId,
+- SK_PNMI_TRAP_SENSOR_LEN_BASE + DescrLen);
+- Offset = SK_PNMI_TRAP_SIMPLE_LEN;
+-
+- /* Store additionally sensor trap related data */
+- Val32 = OID_SKGE_SENSOR_INDEX;
+- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+- *(pBuf + Offset + 4) = 4;
+- Val32 = (SK_U32)SensorIndex;
+- SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32);
+- Offset += 9;
+-
+- Val32 = (SK_U32)OID_SKGE_SENSOR_DESCR;
+- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+- *(pBuf + Offset + 4) = (char)DescrLen;
+- SK_MEMCPY(pBuf + Offset + 5, pAC->I2c.SenTable[SensorIndex].SenDesc,
+- DescrLen);
+- Offset += DescrLen + 5;
+-
+- Val32 = OID_SKGE_SENSOR_TYPE;
+- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+- *(pBuf + Offset + 4) = 1;
+- *(pBuf + Offset + 5) = (char)pAC->I2c.SenTable[SensorIndex].SenType;
+- Offset += 6;
+-
+- Val32 = OID_SKGE_SENSOR_VALUE;
+- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+- *(pBuf + Offset + 4) = 4;
+- Val32 = (SK_U32)pAC->I2c.SenTable[SensorIndex].SenValue;
+- SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32);
+-}
+-
+-/*****************************************************************************
+- *
+- * QueueRlmtNewMacTrap - Store a port switch trap in the trap buffer
+- *
+- * Description:
+- * Nothing further to explain.
+- *
+- * Returns:
+- * Nothing
+- */
+-PNMI_STATIC void QueueRlmtNewMacTrap(
+-SK_AC *pAC, /* Pointer to adapter context */
+-unsigned int ActiveMac) /* Index (0..n) of the currently active port */
+-{
+- char *pBuf;
+- SK_U32 Val32;
+-
+-
+- pBuf = GetTrapEntry(pAC, OID_SKGE_TRAP_RLMT_CHANGE_PORT,
+- SK_PNMI_TRAP_RLMT_CHANGE_LEN);
+-
+- Val32 = OID_SKGE_RLMT_PORT_ACTIVE;
+- SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32);
+- *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1;
+- *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)ActiveMac;
+-}
+-
+-/*****************************************************************************
+- *
+- * QueueRlmtPortTrap - Store port related RLMT trap to trap buffer
+- *
+- * Description:
+- * Nothing further to explain.
+- *
+- * Returns:
+- * Nothing
+- */
+-PNMI_STATIC void QueueRlmtPortTrap(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_U32 TrapId, /* Type of RLMT port trap */
+-unsigned int PortIndex) /* Index of the port, which changed its state */
+-{
+- char *pBuf;
+- SK_U32 Val32;
+-
+-
+- pBuf = GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_RLMT_PORT_LEN);
+-
+- Val32 = OID_SKGE_RLMT_PORT_INDEX;
+- SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32);
+- *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1;
+- *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)PortIndex;
+-}
+-
+-/*****************************************************************************
+- *
+- * CopyMac - Copies a MAC address
+- *
+- * Description:
+- * Nothing further to explain.
+- *
+- * Returns:
+- * Nothing
+- */
+-PNMI_STATIC void CopyMac(
+-char *pDst, /* Pointer to destination buffer */
+-SK_MAC_ADDR *pMac) /* Pointer of Source */
+-{
+- int i;
+-
+-
+- for (i = 0; i < sizeof(SK_MAC_ADDR); i ++) {
+-
+- *(pDst + i) = pMac->a[i];
+- }
+-}
+-
+-#ifdef SK_POWER_MGMT
+-/*****************************************************************************
+- *
+- * PowerManagement - OID handler function of PowerManagement OIDs
+- *
+- * Description:
+- * The code is simple. No description necessary.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK The request was successfully performed.
+- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
+- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
+- * the correct data (e.g. a 32bit value is
+- * needed, but a 16 bit value was passed).
+- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- * exist (e.g. port instance 3 on a two port
+- * adapter.
+- */
+-
+-PNMI_STATIC int PowerManagement(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-int Action, /* Get/PreSet/Set action */
+-SK_U32 Id, /* Object ID that is to be processed */
+-char *pBuf, /* Buffer to which to mgmt data will be retrieved */
+-unsigned int *pLen, /* On call: buffer length. On return: used buffer */
+-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */
+-{
+-
+- SK_U32 RetCode = SK_PNMI_ERR_GENERAL;
+-
+- /*
+- * Check instance. We only handle single instance variables
+- */
+- if (Instance != (SK_U32)(-1) && Instance != 1) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_UNKNOWN_INST);
+- }
+-
+-
+- /* Check length */
+- switch (Id) {
+-
+- case OID_PNP_CAPABILITIES:
+- if (*pLen < sizeof(SK_PNP_CAPABILITIES)) {
+-
+- *pLen = sizeof(SK_PNP_CAPABILITIES);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- break;
+-
+- case OID_PNP_SET_POWER:
+- case OID_PNP_QUERY_POWER:
+- if (*pLen < sizeof(SK_DEVICE_POWER_STATE))
+- {
+- *pLen = sizeof(SK_DEVICE_POWER_STATE);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- break;
+-
+- case OID_PNP_ADD_WAKE_UP_PATTERN:
+- case OID_PNP_REMOVE_WAKE_UP_PATTERN:
+- if (*pLen < sizeof(SK_PM_PACKET_PATTERN)) {
+-
+- *pLen = sizeof(SK_PM_PACKET_PATTERN);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- break;
+-
+- case OID_PNP_ENABLE_WAKE_UP:
+- if (*pLen < sizeof(SK_U32)) {
+-
+- *pLen = sizeof(SK_U32);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- break;
+- }
+-
+- /*
+- * Perform action
+- */
+- if (Action == SK_PNMI_GET) {
+-
+- /*
+- * Get value
+- */
+- switch (Id) {
+-
+- case OID_PNP_CAPABILITIES:
+- RetCode = SkPowerQueryPnPCapabilities(pAC, IoC, pBuf, pLen);
+- break;
+-
+- case OID_PNP_QUERY_POWER:
+- /* The Windows DDK describes: An OID_PNP_QUERY_POWER requests
+- the miniport to indicate whether it can transition its NIC
+- to the low-power state.
+- A miniport driver must always return NDIS_STATUS_SUCCESS
+- to a query of OID_PNP_QUERY_POWER. */
+- *pLen = sizeof(SK_DEVICE_POWER_STATE);
+- RetCode = SK_PNMI_ERR_OK;
+- break;
+-
+- /* NDIS handles these OIDs as write-only.
+- * So in case of get action the buffer with written length = 0
+- * is returned
+- */
+- case OID_PNP_SET_POWER:
+- case OID_PNP_ADD_WAKE_UP_PATTERN:
+- case OID_PNP_REMOVE_WAKE_UP_PATTERN:
+- *pLen = 0;
+- RetCode = SK_PNMI_ERR_NOT_SUPPORTED;
+- break;
+-
+- case OID_PNP_ENABLE_WAKE_UP:
+- RetCode = SkPowerGetEnableWakeUp(pAC, IoC, pBuf, pLen);
+- break;
+-
+- default:
+- RetCode = SK_PNMI_ERR_GENERAL;
+- break;
+- }
+-
+- return (RetCode);
+- }
+-
+-
+- /*
+- * Perform preset or set
+- */
+-
+- /* POWER module does not support PRESET action */
+- if (Action == SK_PNMI_PRESET) {
+- return (SK_PNMI_ERR_OK);
+- }
+-
+- switch (Id) {
+- case OID_PNP_SET_POWER:
+- RetCode = SkPowerSetPower(pAC, IoC, pBuf, pLen);
+- break;
+-
+- case OID_PNP_ADD_WAKE_UP_PATTERN:
+- RetCode = SkPowerAddWakeUpPattern(pAC, IoC, pBuf, pLen);
+- break;
+-
+- case OID_PNP_REMOVE_WAKE_UP_PATTERN:
+- RetCode = SkPowerRemoveWakeUpPattern(pAC, IoC, pBuf, pLen);
+- break;
+-
+- case OID_PNP_ENABLE_WAKE_UP:
+- RetCode = SkPowerSetEnableWakeUp(pAC, IoC, pBuf, pLen);
+- break;
+-
+- default:
+- RetCode = SK_PNMI_ERR_READ_ONLY;
+- }
+-
+- return (RetCode);
+-}
+-#endif /* SK_POWER_MGMT */
+-
+-#ifdef SK_DIAG_SUPPORT
+-/*****************************************************************************
+- *
+- * DiagActions - OID handler function of Diagnostic driver
+- *
+- * Description:
+- * The code is simple. No description necessary.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK The request was successfully performed.
+- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
+- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
+- * the correct data (e.g. a 32bit value is
+- * needed, but a 16 bit value was passed).
+- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- * exist (e.g. port instance 3 on a two port
+- * adapter.
+- */
+-
+-PNMI_STATIC int DiagActions(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-int Action, /* GET/PRESET/SET action */
+-SK_U32 Id, /* Object ID that is to be processed */
+-char *pBuf, /* Buffer used for the management data transfer */
+-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+-{
+-
+- SK_U32 DiagStatus;
+- SK_U32 RetCode = SK_PNMI_ERR_GENERAL;
+-
+- /*
+- * Check instance. We only handle single instance variables.
+- */
+- if (Instance != (SK_U32)(-1) && Instance != 1) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_UNKNOWN_INST);
+- }
+-
+- /*
+- * Check length.
+- */
+- switch (Id) {
+-
+- case OID_SKGE_DIAG_MODE:
+- if (*pLen < sizeof(SK_U32)) {
+-
+- *pLen = sizeof(SK_U32);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- break;
+-
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR040, SK_PNMI_ERR040MSG);
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- /* Perform action. */
+-
+- /* GET value. */
+- if (Action == SK_PNMI_GET) {
+-
+- switch (Id) {
+-
+- case OID_SKGE_DIAG_MODE:
+- DiagStatus = pAC->Pnmi.DiagAttached;
+- SK_PNMI_STORE_U32(pBuf, DiagStatus);
+- *pLen = sizeof(SK_U32);
+- RetCode = SK_PNMI_ERR_OK;
+- break;
+-
+- default:
+- *pLen = 0;
+- RetCode = SK_PNMI_ERR_GENERAL;
+- break;
+- }
+- return (RetCode);
+- }
+-
+- /* From here SET or PRESET value. */
+-
+- /* PRESET value is not supported. */
+- if (Action == SK_PNMI_PRESET) {
+- return (SK_PNMI_ERR_OK);
+- }
+-
+- /* SET value. */
+- switch (Id) {
+- case OID_SKGE_DIAG_MODE:
+-
+- /* Handle the SET. */
+- switch (*pBuf) {
+-
+- /* Attach the DIAG to this adapter. */
+- case SK_DIAG_ATTACHED:
+- /* Check if we come from running */
+- if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
+-
+- RetCode = SkDrvLeaveDiagMode(pAC);
+-
+- }
+- else if (pAC->Pnmi.DiagAttached == SK_DIAG_IDLE) {
+-
+- RetCode = SK_PNMI_ERR_OK;
+- }
+-
+- else {
+-
+- RetCode = SK_PNMI_ERR_GENERAL;
+-
+- }
+-
+- if (RetCode == SK_PNMI_ERR_OK) {
+-
+- pAC->Pnmi.DiagAttached = SK_DIAG_ATTACHED;
+- }
+- break;
+-
+- /* Enter the DIAG mode in the driver. */
+- case SK_DIAG_RUNNING:
+- RetCode = SK_PNMI_ERR_OK;
+-
+- /*
+- * If DiagAttached is set, we can tell the driver
+- * to enter the DIAG mode.
+- */
+- if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) {
+- /* If DiagMode is not active, we can enter it. */
+- if (!pAC->DiagModeActive) {
+-
+- RetCode = SkDrvEnterDiagMode(pAC);
+- }
+- else {
+-
+- RetCode = SK_PNMI_ERR_GENERAL;
+- }
+- }
+- else {
+-
+- RetCode = SK_PNMI_ERR_GENERAL;
+- }
+-
+- if (RetCode == SK_PNMI_ERR_OK) {
+-
+- pAC->Pnmi.DiagAttached = SK_DIAG_RUNNING;
+- }
+- break;
+-
+- case SK_DIAG_IDLE:
+- /* Check if we come from running */
+- if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
+-
+- RetCode = SkDrvLeaveDiagMode(pAC);
+-
+- }
+- else if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) {
+-
+- RetCode = SK_PNMI_ERR_OK;
+- }
+-
+- else {
+-
+- RetCode = SK_PNMI_ERR_GENERAL;
+-
+- }
+-
+- if (RetCode == SK_PNMI_ERR_OK) {
+-
+- pAC->Pnmi.DiagAttached = SK_DIAG_IDLE;
+- }
+- break;
+-
+- default:
+- RetCode = SK_PNMI_ERR_BAD_VALUE;
+- break;
+- }
+- break;
+-
+- default:
+- RetCode = SK_PNMI_ERR_GENERAL;
+- }
+-
+- if (RetCode == SK_PNMI_ERR_OK) {
+- *pLen = sizeof(SK_U32);
+- }
+- else {
+-
+- *pLen = 0;
+- }
+- return (RetCode);
+-}
+-#endif /* SK_DIAG_SUPPORT */
+-
+-/*****************************************************************************
+- *
+- * Vct - OID handler function of OIDs
+- *
+- * Description:
+- * The code is simple. No description necessary.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK The request was performed successfully.
+- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
+- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
+- * the correct data (e.g. a 32bit value is
+- * needed, but a 16 bit value was passed).
+- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- * exist (e.g. port instance 3 on a two port
+- * adapter).
+- * SK_PNMI_ERR_READ_ONLY Only the Get action is allowed.
+- *
+- */
+-
+-PNMI_STATIC int Vct(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-int Action, /* GET/PRESET/SET action */
+-SK_U32 Id, /* Object ID that is to be processed */
+-char *pBuf, /* Buffer used for the management data transfer */
+-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
+-SK_U32 Instance, /* Instance (-1,2..n) that is to be queried */
+-unsigned int TableIndex, /* Index to the Id table */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+-{
+- SK_GEPORT *pPrt;
+- SK_PNMI_VCT *pVctBackupData;
+- SK_U32 LogPortMax;
+- SK_U32 PhysPortMax;
+- SK_U32 PhysPortIndex;
+- SK_U32 Limit;
+- SK_U32 Offset;
+- SK_BOOL Link;
+- SK_U32 RetCode = SK_PNMI_ERR_GENERAL;
+- int i;
+- SK_EVPARA Para;
+- SK_U32 CableLength;
+-
+- /*
+- * Calculate the port indexes from the instance.
+- */
+- PhysPortMax = pAC->GIni.GIMacsFound;
+- LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
+-
+- /* Dual net mode? */
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- LogPortMax--;
+- }
+-
+- if ((Instance != (SK_U32) (-1))) {
+- /* Check instance range. */
+- if ((Instance < 2) || (Instance > LogPortMax)) {
+- *pLen = 0;
+- return (SK_PNMI_ERR_UNKNOWN_INST);
+- }
+-
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+- PhysPortIndex = NetIndex;
+- }
+- else {
+- PhysPortIndex = Instance - 2;
+- }
+- Limit = PhysPortIndex + 1;
+- }
+- else {
+- /*
+- * Instance == (SK_U32) (-1), get all Instances of that OID.
+- *
+- * Not implemented yet. May be used in future releases.
+- */
+- PhysPortIndex = 0;
+- Limit = PhysPortMax;
+- }
+-
+- pPrt = &pAC->GIni.GP[PhysPortIndex];
+- if (pPrt->PHWLinkUp) {
+- Link = SK_TRUE;
+- }
+- else {
+- Link = SK_FALSE;
+- }
+-
+- /* Check MAC type */
+- if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- /* Initialize backup data pointer. */
+- pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex];
+-
+- /* Check action type */
+- if (Action == SK_PNMI_GET) {
+- /* Check length */
+- switch (Id) {
+-
+- case OID_SKGE_VCT_GET:
+- if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT)) {
+- *pLen = (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- break;
+-
+- case OID_SKGE_VCT_STATUS:
+- if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U8)) {
+- *pLen = (Limit - PhysPortIndex) * sizeof(SK_U8);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- break;
+-
+- default:
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- /* Get value */
+- Offset = 0;
+- for (; PhysPortIndex < Limit; PhysPortIndex++) {
+- switch (Id) {
+-
+- case OID_SKGE_VCT_GET:
+- if ((Link == SK_FALSE) &&
+- (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING)) {
+- RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE);
+- if (RetCode == 0) {
+- pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING;
+- pAC->Pnmi.VctStatus[PhysPortIndex] |=
+- (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE);
+-
+- /* Copy results for later use to PNMI struct. */
+- for (i = 0; i < 4; i++) {
+- if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) {
+- if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] < 0xff)) {
+- pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH;
+- }
+- }
+- if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] != 0xff)) {
+- CableLength = 1000 * (((175 * pPrt->PMdiPairLen[i]) / 210) - 28);
+- }
+- else {
+- CableLength = 0;
+- }
+- pVctBackupData->PMdiPairLen[i] = CableLength;
+- pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i];
+- }
+-
+- Para.Para32[0] = PhysPortIndex;
+- Para.Para32[1] = -1;
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
+- SkEventDispatcher(pAC, IoC);
+- }
+- else {
+- ; /* VCT test is running. */
+- }
+- }
+-
+- /* Get all results. */
+- CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex);
+- Offset += sizeof(SK_U8);
+- *(pBuf + Offset) = pPrt->PCableLen;
+- Offset += sizeof(SK_U8);
+- for (i = 0; i < 4; i++) {
+- SK_PNMI_STORE_U32((pBuf + Offset), pVctBackupData->PMdiPairLen[i]);
+- Offset += sizeof(SK_U32);
+- }
+- for (i = 0; i < 4; i++) {
+- *(pBuf + Offset) = pVctBackupData->PMdiPairSts[i];
+- Offset += sizeof(SK_U8);
+- }
+-
+- RetCode = SK_PNMI_ERR_OK;
+- break;
+-
+- case OID_SKGE_VCT_STATUS:
+- CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex);
+- Offset += sizeof(SK_U8);
+- RetCode = SK_PNMI_ERR_OK;
+- break;
+-
+- default:
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- } /* for */
+- *pLen = Offset;
+- return (RetCode);
+-
+- } /* if SK_PNMI_GET */
+-
+- /*
+- * From here SET or PRESET action. Check if the passed
+- * buffer length is plausible.
+- */
+-
+- /* Check length */
+- switch (Id) {
+- case OID_SKGE_VCT_SET:
+- if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) {
+- *pLen = (Limit - PhysPortIndex) * sizeof(SK_U32);
+- return (SK_PNMI_ERR_TOO_SHORT);
+- }
+- break;
+-
+- default:
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- /*
+- * Perform preset or set.
+- */
+-
+- /* VCT does not support PRESET action. */
+- if (Action == SK_PNMI_PRESET) {
+- return (SK_PNMI_ERR_OK);
+- }
+-
+- Offset = 0;
+- for (; PhysPortIndex < Limit; PhysPortIndex++) {
+- switch (Id) {
+- case OID_SKGE_VCT_SET: /* Start VCT test. */
+- if (Link == SK_FALSE) {
+- SkGeStopPort(pAC, IoC, PhysPortIndex, SK_STOP_ALL, SK_SOFT_RST);
+-
+- RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_TRUE);
+- if (RetCode == 0) { /* RetCode: 0 => Start! */
+- pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_PENDING;
+- pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_NEW_VCT_DATA;
+- pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_LINK;
+-
+- /*
+- * Start VCT timer counter.
+- */
+- SK_MEMSET((char *) &Para, 0, sizeof(Para));
+- Para.Para32[0] = PhysPortIndex;
+- Para.Para32[1] = -1;
+- SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer,
+- 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Para);
+- SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
+- RetCode = SK_PNMI_ERR_OK;
+- }
+- else { /* RetCode: 2 => Running! */
+- SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
+- RetCode = SK_PNMI_ERR_OK;
+- }
+- }
+- else { /* RetCode: 4 => Link! */
+- RetCode = 4;
+- SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
+- RetCode = SK_PNMI_ERR_OK;
+- }
+- Offset += sizeof(SK_U32);
+- break;
+-
+- default:
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- } /* for */
+- *pLen = Offset;
+- return (RetCode);
+-
+-} /* Vct */
+-
+-
+-PNMI_STATIC void CheckVctStatus(
+-SK_AC *pAC,
+-SK_IOC IoC,
+-char *pBuf,
+-SK_U32 Offset,
+-SK_U32 PhysPortIndex)
+-{
+- SK_GEPORT *pPrt;
+- SK_PNMI_VCT *pVctData;
+- SK_U32 RetCode;
+-
+- pPrt = &pAC->GIni.GP[PhysPortIndex];
+-
+- pVctData = (SK_PNMI_VCT *) (pBuf + Offset);
+- pVctData->VctStatus = SK_PNMI_VCT_NONE;
+-
+- if (!pPrt->PHWLinkUp) {
+-
+- /* Was a VCT test ever made before? */
+- if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) {
+- if ((pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_LINK)) {
+- pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA;
+- }
+- else {
+- pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA;
+- }
+- }
+-
+- /* Check VCT test status. */
+- RetCode = SkGmCableDiagStatus(pAC,IoC, PhysPortIndex, SK_FALSE);
+- if (RetCode == 2) { /* VCT test is running. */
+- pVctData->VctStatus |= SK_PNMI_VCT_RUNNING;
+- }
+- else { /* VCT data was copied to pAC here. Check PENDING state. */
+- if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) {
+- pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA;
+- }
+- }
+-
+- if (pPrt->PCableLen != 0xff) { /* Old DSP value. */
+- pVctData->VctStatus |= SK_PNMI_VCT_OLD_DSP_DATA;
+- }
+- }
+- else {
+-
+- /* Was a VCT test ever made before? */
+- if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) {
+- pVctData->VctStatus &= ~SK_PNMI_VCT_NEW_VCT_DATA;
+- pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA;
+- }
+-
+- /* DSP only valid in 100/1000 modes. */
+- if (pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed !=
+- SK_LSPEED_STAT_10MBPS) {
+- pVctData->VctStatus |= SK_PNMI_VCT_NEW_DSP_DATA;
+- }
+- }
+-} /* CheckVctStatus */
+-
+-
+-/*****************************************************************************
+- *
+- * SkPnmiGenIoctl - Handles new generic PNMI IOCTL, calls the needed
+- * PNMI function depending on the subcommand and
+- * returns all data belonging to the complete database
+- * or OID request.
+- *
+- * Description:
+- * Looks up the requested subcommand, calls the corresponding handler
+- * function and passes all required parameters to it.
+- * The function is called by the driver. It is needed to handle the new
+- * generic PNMI IOCTL. This IOCTL is given to the driver and contains both
+- * the OID and a subcommand to decide what kind of request has to be done.
+- *
+- * Returns:
+- * SK_PNMI_ERR_OK The request was successfully performed
+- * SK_PNMI_ERR_GENERAL A general severe internal error occured
+- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take
+- * the data.
+- * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown
+- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
+- * exist (e.g. port instance 3 on a two port
+- * adapter.
+- */
+-int SkPnmiGenIoctl(
+-SK_AC *pAC, /* Pointer to adapter context struct */
+-SK_IOC IoC, /* I/O context */
+-void *pBuf, /* Buffer used for the management data transfer */
+-unsigned int *pLen, /* Length of buffer */
+-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+-{
+-SK_I32 Mode; /* Store value of subcommand. */
+-SK_U32 Oid; /* Store value of OID. */
+-int ReturnCode; /* Store return value to show status of PNMI action. */
+-int HeaderLength; /* Length of desired action plus OID. */
+-
+- ReturnCode = SK_PNMI_ERR_GENERAL;
+-
+- SK_MEMCPY(&Mode, pBuf, sizeof(SK_I32));
+- SK_MEMCPY(&Oid, (char *) pBuf + sizeof(SK_I32), sizeof(SK_U32));
+- HeaderLength = sizeof(SK_I32) + sizeof(SK_U32);
+- *pLen = *pLen - HeaderLength;
+- SK_MEMCPY((char *) pBuf + sizeof(SK_I32), (char *) pBuf + HeaderLength, *pLen);
+-
+- switch(Mode) {
+- case SK_GET_SINGLE_VAR:
+- ReturnCode = SkPnmiGetVar(pAC, IoC, Oid,
+- (char *) pBuf + sizeof(SK_I32), pLen,
+- ((SK_U32) (-1)), NetIndex);
+- SK_PNMI_STORE_U32(pBuf, ReturnCode);
+- *pLen = *pLen + sizeof(SK_I32);
+- break;
+- case SK_PRESET_SINGLE_VAR:
+- ReturnCode = SkPnmiPreSetVar(pAC, IoC, Oid,
+- (char *) pBuf + sizeof(SK_I32), pLen,
+- ((SK_U32) (-1)), NetIndex);
+- SK_PNMI_STORE_U32(pBuf, ReturnCode);
+- *pLen = *pLen + sizeof(SK_I32);
+- break;
+- case SK_SET_SINGLE_VAR:
+- ReturnCode = SkPnmiSetVar(pAC, IoC, Oid,
+- (char *) pBuf + sizeof(SK_I32), pLen,
+- ((SK_U32) (-1)), NetIndex);
+- SK_PNMI_STORE_U32(pBuf, ReturnCode);
+- *pLen = *pLen + sizeof(SK_I32);
+- break;
+- case SK_GET_FULL_MIB:
+- ReturnCode = SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex);
+- break;
+- case SK_PRESET_FULL_MIB:
+- ReturnCode = SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex);
+- break;
+- case SK_SET_FULL_MIB:
+- ReturnCode = SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex);
+- break;
+- default:
+- break;
+- }
+-
+- return (ReturnCode);
+-
+-} /* SkGeIocGen */
+diff --git a/drivers/net/sk98lin/skgesirq.c b/drivers/net/sk98lin/skgesirq.c
+deleted file mode 100644
+index e5ee6d6..0000000
+--- a/drivers/net/sk98lin/skgesirq.c
++++ /dev/null
+@@ -1,2229 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skgesirq.c
+- * Project: Gigabit Ethernet Adapters, Common Modules
+- * Version: $Revision: 1.92 $
+- * Date: $Date: 2003/09/16 14:37:07 $
+- * Purpose: Special IRQ module
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- * Special Interrupt handler
+- *
+- * The following abstract should show how this module is included
+- * in the driver path:
+- *
+- * In the ISR of the driver the bits for frame transmission complete and
+- * for receive complete are checked and handled by the driver itself.
+- * The bits of the slow path mask are checked after that and then the
+- * entry into the so-called "slow path" is prepared. It is an implementors
+- * decision whether this is executed directly or just scheduled by
+- * disabling the mask. In the interrupt service routine some events may be
+- * generated, so it would be a good idea to call the EventDispatcher
+- * right after this ISR.
+- *
+- * The Interrupt source register of the adapter is NOT read by this module.
+- * SO if the drivers implementor needs a while loop around the
+- * slow data paths interrupt bits, he needs to call the SkGeSirqIsr() for
+- * each loop entered.
+- *
+- * However, the MAC Interrupt status registers are read in a while loop.
+- *
+- */
+-
+-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+-static const char SysKonnectFileId[] =
+- "@(#) $Id: skgesirq.c,v 1.92 2003/09/16 14:37:07 rschmidt Exp $ (C) Marvell.";
+-#endif
+-
+-#include "h/skdrv1st.h" /* Driver Specific Definitions */
+-#ifndef SK_SLIM
+-#include "h/skgepnmi.h" /* PNMI Definitions */
+-#include "h/skrlmt.h" /* RLMT Definitions */
+-#endif
+-#include "h/skdrv2nd.h" /* Adapter Control and Driver specific Def. */
+-
+-/* local function prototypes */
+-#ifdef GENESIS
+-static int SkGePortCheckUpXmac(SK_AC*, SK_IOC, int, SK_BOOL);
+-static int SkGePortCheckUpBcom(SK_AC*, SK_IOC, int, SK_BOOL);
+-static void SkPhyIsrBcom(SK_AC*, SK_IOC, int, SK_U16);
+-#endif /* GENESIS */
+-#ifdef YUKON
+-static int SkGePortCheckUpGmac(SK_AC*, SK_IOC, int, SK_BOOL);
+-static void SkPhyIsrGmac(SK_AC*, SK_IOC, int, SK_U16);
+-#endif /* YUKON */
+-#ifdef OTHER_PHY
+-static int SkGePortCheckUpLone(SK_AC*, SK_IOC, int, SK_BOOL);
+-static int SkGePortCheckUpNat(SK_AC*, SK_IOC, int, SK_BOOL);
+-static void SkPhyIsrLone(SK_AC*, SK_IOC, int, SK_U16);
+-#endif /* OTHER_PHY */
+-
+-#ifdef GENESIS
+-/*
+- * array of Rx counter from XMAC which are checked
+- * in AutoSense mode to check whether a link is not able to auto-negotiate.
+- */
+-static const SK_U16 SkGeRxRegs[]= {
+- XM_RXF_64B,
+- XM_RXF_127B,
+- XM_RXF_255B,
+- XM_RXF_511B,
+- XM_RXF_1023B,
+- XM_RXF_MAX_SZ
+-} ;
+-#endif /* GENESIS */
+-
+-#ifdef __C2MAN__
+-/*
+- * Special IRQ function
+- *
+- * General Description:
+- *
+- */
+-intro()
+-{}
+-#endif
+-
+-/******************************************************************************
+- *
+- * SkHWInitDefSense() - Default Autosensing mode initialization
+- *
+- * Description: sets the PLinkMode for HWInit
+- *
+- * Returns: N/A
+- */
+-static void SkHWInitDefSense(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_GEPORT *pPrt; /* GIni Port struct pointer */
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- pPrt->PAutoNegTimeOut = 0;
+-
+- if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) {
+- pPrt->PLinkMode = pPrt->PLinkModeConf;
+- return;
+- }
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("AutoSensing: First mode %d on Port %d\n",
+- (int)SK_LMODE_AUTOFULL, Port));
+-
+- pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL;
+-
+- return;
+-} /* SkHWInitDefSense */
+-
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- * SkHWSenseGetNext() - Get Next Autosensing Mode
+- *
+- * Description: gets the appropriate next mode
+- *
+- * Note:
+- *
+- */
+-static SK_U8 SkHWSenseGetNext(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_GEPORT *pPrt; /* GIni Port struct pointer */
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- pPrt->PAutoNegTimeOut = 0;
+-
+- if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
+- /* Leave all as configured */
+- return(pPrt->PLinkModeConf);
+- }
+-
+- if (pPrt->PLinkMode == (SK_U8)SK_LMODE_AUTOFULL) {
+- /* Return next mode AUTOBOTH */
+- return ((SK_U8)SK_LMODE_AUTOBOTH);
+- }
+-
+- /* Return default autofull */
+- return ((SK_U8)SK_LMODE_AUTOFULL);
+-} /* SkHWSenseGetNext */
+-
+-
+-/******************************************************************************
+- *
+- * SkHWSenseSetNext() - Autosensing Set next mode
+- *
+- * Description: sets the appropriate next mode
+- *
+- * Returns: N/A
+- */
+-static void SkHWSenseSetNext(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port, /* Port Index (MAC_1 + n) */
+-SK_U8 NewMode) /* New Mode to be written in sense mode */
+-{
+- SK_GEPORT *pPrt; /* GIni Port struct pointer */
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- pPrt->PAutoNegTimeOut = 0;
+-
+- if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
+- return;
+- }
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("AutoSensing: next mode %d on Port %d\n",
+- (int)NewMode, Port));
+-
+- pPrt->PLinkMode = NewMode;
+-
+- return;
+-} /* SkHWSenseSetNext */
+-#endif /* GENESIS */
+-
+-
+-/******************************************************************************
+- *
+- * SkHWLinkDown() - Link Down handling
+- *
+- * Description: handles the hardware link down signal
+- *
+- * Returns: N/A
+- */
+-void SkHWLinkDown(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_GEPORT *pPrt; /* GIni Port struct pointer */
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- /* Disable all MAC interrupts */
+- SkMacIrqDisable(pAC, IoC, Port);
+-
+- /* Disable Receiver and Transmitter */
+- SkMacRxTxDisable(pAC, IoC, Port);
+-
+- /* Init default sense mode */
+- SkHWInitDefSense(pAC, IoC, Port);
+-
+- if (pPrt->PHWLinkUp == SK_FALSE) {
+- return;
+- }
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("Link down Port %d\n", Port));
+-
+- /* Set Link to DOWN */
+- pPrt->PHWLinkUp = SK_FALSE;
+-
+- /* Reset Port stati */
+- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
+- pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
+- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_INDETERMINATED;
+-
+- /* Re-init Phy especially when the AutoSense default is set now */
+- SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
+-
+- /* GP0: used for workaround of Rev. C Errata 2 */
+-
+- /* Do NOT signal to RLMT */
+-
+- /* Do NOT start the timer here */
+-} /* SkHWLinkDown */
+-
+-
+-/******************************************************************************
+- *
+- * SkHWLinkUp() - Link Up handling
+- *
+- * Description: handles the hardware link up signal
+- *
+- * Returns: N/A
+- */
+-static void SkHWLinkUp(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_GEPORT *pPrt; /* GIni Port struct pointer */
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- if (pPrt->PHWLinkUp) {
+- /* We do NOT need to proceed on active link */
+- return;
+- }
+-
+- pPrt->PHWLinkUp = SK_TRUE;
+- pPrt->PAutoNegFail = SK_FALSE;
+- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
+-
+- if (pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOHALF &&
+- pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOFULL &&
+- pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOBOTH) {
+- /* Link is up and no Auto-negotiation should be done */
+-
+- /* Link speed should be the configured one */
+- switch (pPrt->PLinkSpeed) {
+- case SK_LSPEED_AUTO:
+- /* default is 1000 Mbps */
+- case SK_LSPEED_1000MBPS:
+- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
+- break;
+- case SK_LSPEED_100MBPS:
+- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
+- break;
+- case SK_LSPEED_10MBPS:
+- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
+- break;
+- }
+-
+- /* Set Link Mode Status */
+- if (pPrt->PLinkMode == SK_LMODE_FULL) {
+- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_FULL;
+- }
+- else {
+- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_HALF;
+- }
+-
+- /* No flow control without auto-negotiation */
+- pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
+-
+- /* enable Rx/Tx */
+- (void)SkMacRxTxEnable(pAC, IoC, Port);
+- }
+-} /* SkHWLinkUp */
+-
+-
+-/******************************************************************************
+- *
+- * SkMacParity() - MAC parity workaround
+- *
+- * Description: handles MAC parity errors correctly
+- *
+- * Returns: N/A
+- */
+-static void SkMacParity(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index of the port failed */
+-{
+- SK_EVPARA Para;
+- SK_GEPORT *pPrt; /* GIni Port struct pointer */
+- SK_U32 TxMax; /* Tx Max Size Counter */
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- /* Clear IRQ Tx Parity Error */
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+-
+- SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_PERR);
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIYukon) {
+- /* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */
+- SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T),
+- (SK_U8)((pAC->GIni.GIChipId == CHIP_ID_YUKON &&
+- pAC->GIni.GIChipRev == 0) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE));
+- }
+-#endif /* YUKON */
+-
+- if (pPrt->PCheckPar) {
+-
+- if (Port == MAC_1) {
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG);
+- }
+- else {
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E017, SKERR_SIRQ_E017MSG);
+- }
+- Para.Para64 = Port;
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+-
+- Para.Para32[0] = Port;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+-
+- return;
+- }
+-
+- /* Check whether frames with a size of 1k were sent */
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+- /* Snap statistic counters */
+- (void)SkXmUpdateStats(pAC, IoC, Port);
+-
+- (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXF_MAX_SZ, &TxMax);
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIYukon) {
+-
+- (void)SkGmMacStatistic(pAC, IoC, Port, GM_TXF_1518B, &TxMax);
+- }
+-#endif /* YUKON */
+-
+- if (TxMax > 0) {
+- /* From now on check the parity */
+- pPrt->PCheckPar = SK_TRUE;
+- }
+-} /* SkMacParity */
+-
+-
+-/******************************************************************************
+- *
+- * SkGeHwErr() - Hardware Error service routine
+- *
+- * Description: handles all HW Error interrupts
+- *
+- * Returns: N/A
+- */
+-static void SkGeHwErr(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-SK_U32 HwStatus) /* Interrupt status word */
+-{
+- SK_EVPARA Para;
+- SK_U16 Word;
+-
+- if ((HwStatus & (IS_IRQ_MST_ERR | IS_IRQ_STAT)) != 0) {
+- /* PCI Errors occured */
+- if ((HwStatus & IS_IRQ_STAT) != 0) {
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG);
+- }
+- else {
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG);
+- }
+-
+- /* Reset all bits in the PCI STATUS register */
+- SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
+-
+- SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+- SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
+- SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+-
+- Para.Para64 = 0;
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
+- }
+-
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+-
+- if ((HwStatus & IS_NO_STAT_M1) != 0) {
+- /* Ignore it */
+- /* This situation is also indicated in the descriptor */
+- SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INSTAT);
+- }
+-
+- if ((HwStatus & IS_NO_STAT_M2) != 0) {
+- /* Ignore it */
+- /* This situation is also indicated in the descriptor */
+- SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INSTAT);
+- }
+-
+- if ((HwStatus & IS_NO_TIST_M1) != 0) {
+- /* Ignore it */
+- /* This situation is also indicated in the descriptor */
+- SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INTIST);
+- }
+-
+- if ((HwStatus & IS_NO_TIST_M2) != 0) {
+- /* Ignore it */
+- /* This situation is also indicated in the descriptor */
+- SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INTIST);
+- }
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIYukon) {
+- /* This is necessary only for Rx timing measurements */
+- if ((HwStatus & IS_IRQ_TIST_OV) != 0) {
+- /* increment Time Stamp Timer counter (high) */
+- pAC->GIni.GITimeStampCnt++;
+-
+- /* Clear Time Stamp Timer IRQ */
+- SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ);
+- }
+-
+- if ((HwStatus & IS_IRQ_SENSOR) != 0) {
+- /* no sensors on 32-bit Yukon */
+- if (pAC->GIni.GIYukon32Bit) {
+- /* disable HW Error IRQ */
+- pAC->GIni.GIValIrqMask &= ~IS_HW_ERR;
+- }
+- }
+- }
+-#endif /* YUKON */
+-
+- if ((HwStatus & IS_RAM_RD_PAR) != 0) {
+- SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_RD_PERR);
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E014, SKERR_SIRQ_E014MSG);
+- Para.Para64 = 0;
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
+- }
+-
+- if ((HwStatus & IS_RAM_WR_PAR) != 0) {
+- SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_WR_PERR);
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E015, SKERR_SIRQ_E015MSG);
+- Para.Para64 = 0;
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
+- }
+-
+- if ((HwStatus & IS_M1_PAR_ERR) != 0) {
+- SkMacParity(pAC, IoC, MAC_1);
+- }
+-
+- if ((HwStatus & IS_M2_PAR_ERR) != 0) {
+- SkMacParity(pAC, IoC, MAC_2);
+- }
+-
+- if ((HwStatus & IS_R1_PAR_ERR) != 0) {
+- /* Clear IRQ */
+- SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_P);
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG);
+- Para.Para64 = MAC_1;
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+-
+- Para.Para32[0] = MAC_1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+- }
+-
+- if ((HwStatus & IS_R2_PAR_ERR) != 0) {
+- /* Clear IRQ */
+- SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_P);
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG);
+- Para.Para64 = MAC_2;
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+-
+- Para.Para32[0] = MAC_2;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+- }
+-} /* SkGeHwErr */
+-
+-
+-/******************************************************************************
+- *
+- * SkGeSirqIsr() - Special Interrupt Service Routine
+- *
+- * Description: handles all non data transfer specific interrupts (slow path)
+- *
+- * Returns: N/A
+- */
+-void SkGeSirqIsr(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-SK_U32 Istatus) /* Interrupt status word */
+-{
+- SK_EVPARA Para;
+- SK_U32 RegVal32; /* Read register value */
+- SK_GEPORT *pPrt; /* GIni Port struct pointer */
+- SK_U16 PhyInt;
+- int i;
+-
+- if (((Istatus & IS_HW_ERR) & pAC->GIni.GIValIrqMask) != 0) {
+- /* read the HW Error Interrupt source */
+- SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
+-
+- SkGeHwErr(pAC, IoC, RegVal32);
+- }
+-
+- /*
+- * Packet Timeout interrupts
+- */
+- /* Check whether MACs are correctly initialized */
+- if (((Istatus & (IS_PA_TO_RX1 | IS_PA_TO_TX1)) != 0) &&
+- pAC->GIni.GP[MAC_1].PState == SK_PRT_RESET) {
+- /* MAC 1 was not initialized but Packet timeout occured */
+- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E004,
+- SKERR_SIRQ_E004MSG);
+- }
+-
+- if (((Istatus & (IS_PA_TO_RX2 | IS_PA_TO_TX2)) != 0) &&
+- pAC->GIni.GP[MAC_2].PState == SK_PRT_RESET) {
+- /* MAC 2 was not initialized but Packet timeout occured */
+- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E005,
+- SKERR_SIRQ_E005MSG);
+- }
+-
+- if ((Istatus & IS_PA_TO_RX1) != 0) {
+- /* Means network is filling us up */
+- SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E002,
+- SKERR_SIRQ_E002MSG);
+- SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX1);
+- }
+-
+- if ((Istatus & IS_PA_TO_RX2) != 0) {
+- /* Means network is filling us up */
+- SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E003,
+- SKERR_SIRQ_E003MSG);
+- SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX2);
+- }
+-
+- if ((Istatus & IS_PA_TO_TX1) != 0) {
+-
+- pPrt = &pAC->GIni.GP[0];
+-
+- /* May be a normal situation in a server with a slow network */
+- SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1);
+-
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+- /*
+- * workaround: if in half duplex mode, check for Tx hangup.
+- * Read number of TX'ed bytes, wait for 10 ms, then compare
+- * the number with current value. If nothing changed, we assume
+- * that Tx is hanging and do a FIFO flush (see event routine).
+- */
+- if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
+- pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
+- !pPrt->HalfDupTimerActive) {
+- /*
+- * many more pack. arb. timeouts may come in between,
+- * we ignore those
+- */
+- pPrt->HalfDupTimerActive = SK_TRUE;
+- /* Snap statistic counters */
+- (void)SkXmUpdateStats(pAC, IoC, 0);
+-
+- (void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_HI, &RegVal32);
+-
+- pPrt->LastOctets = (SK_U64)RegVal32 << 32;
+-
+- (void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_LO, &RegVal32);
+-
+- pPrt->LastOctets += RegVal32;
+-
+- Para.Para32[0] = 0;
+- SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
+- SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
+- }
+- }
+-#endif /* GENESIS */
+- }
+-
+- if ((Istatus & IS_PA_TO_TX2) != 0) {
+-
+- pPrt = &pAC->GIni.GP[1];
+-
+- /* May be a normal situation in a server with a slow network */
+- SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2);
+-
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+- /* workaround: see above */
+- if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
+- pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
+- !pPrt->HalfDupTimerActive) {
+- pPrt->HalfDupTimerActive = SK_TRUE;
+- /* Snap statistic counters */
+- (void)SkXmUpdateStats(pAC, IoC, 1);
+-
+- (void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_HI, &RegVal32);
+-
+- pPrt->LastOctets = (SK_U64)RegVal32 << 32;
+-
+- (void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_LO, &RegVal32);
+-
+- pPrt->LastOctets += RegVal32;
+-
+- Para.Para32[0] = 1;
+- SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
+- SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
+- }
+- }
+-#endif /* GENESIS */
+- }
+-
+- /* Check interrupts of the particular queues */
+- if ((Istatus & IS_R1_C) != 0) {
+- /* Clear IRQ */
+- SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_C);
+- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E006,
+- SKERR_SIRQ_E006MSG);
+- Para.Para64 = MAC_1;
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+- Para.Para32[0] = MAC_1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+- }
+-
+- if ((Istatus & IS_R2_C) != 0) {
+- /* Clear IRQ */
+- SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_C);
+- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E007,
+- SKERR_SIRQ_E007MSG);
+- Para.Para64 = MAC_2;
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+- Para.Para32[0] = MAC_2;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+- }
+-
+- if ((Istatus & IS_XS1_C) != 0) {
+- /* Clear IRQ */
+- SK_OUT32(IoC, B0_XS1_CSR, CSR_IRQ_CL_C);
+- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E008,
+- SKERR_SIRQ_E008MSG);
+- Para.Para64 = MAC_1;
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+- Para.Para32[0] = MAC_1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+- }
+-
+- if ((Istatus & IS_XA1_C) != 0) {
+- /* Clear IRQ */
+- SK_OUT32(IoC, B0_XA1_CSR, CSR_IRQ_CL_C);
+- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E009,
+- SKERR_SIRQ_E009MSG);
+- Para.Para64 = MAC_1;
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+- Para.Para32[0] = MAC_1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+- }
+-
+- if ((Istatus & IS_XS2_C) != 0) {
+- /* Clear IRQ */
+- SK_OUT32(IoC, B0_XS2_CSR, CSR_IRQ_CL_C);
+- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E010,
+- SKERR_SIRQ_E010MSG);
+- Para.Para64 = MAC_2;
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+- Para.Para32[0] = MAC_2;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+- }
+-
+- if ((Istatus & IS_XA2_C) != 0) {
+- /* Clear IRQ */
+- SK_OUT32(IoC, B0_XA2_CSR, CSR_IRQ_CL_C);
+- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E011,
+- SKERR_SIRQ_E011MSG);
+- Para.Para64 = MAC_2;
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+- Para.Para32[0] = MAC_2;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+- }
+-
+- /* External reg interrupt */
+- if ((Istatus & IS_EXT_REG) != 0) {
+- /* Test IRQs from PHY */
+- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+-
+- pPrt = &pAC->GIni.GP[i];
+-
+- if (pPrt->PState == SK_PRT_RESET) {
+- continue;
+- }
+-
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+-
+- switch (pPrt->PhyType) {
+-
+- case SK_PHY_XMAC:
+- break;
+-
+- case SK_PHY_BCOM:
+- SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_STAT, &PhyInt);
+-
+- if ((PhyInt & ~PHY_B_DEF_MSK) != 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("Port %d Bcom Int: 0x%04X\n",
+- i, PhyInt));
+- SkPhyIsrBcom(pAC, IoC, i, PhyInt);
+- }
+- break;
+-#ifdef OTHER_PHY
+- case SK_PHY_LONE:
+- SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_STAT, &PhyInt);
+-
+- if ((PhyInt & PHY_L_DEF_MSK) != 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("Port %d Lone Int: %x\n",
+- i, PhyInt));
+- SkPhyIsrLone(pAC, IoC, i, PhyInt);
+- }
+- break;
+-#endif /* OTHER_PHY */
+- }
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIYukon) {
+- /* Read PHY Interrupt Status */
+- SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_STAT, &PhyInt);
+-
+- if ((PhyInt & PHY_M_DEF_MSK) != 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("Port %d Marv Int: 0x%04X\n",
+- i, PhyInt));
+- SkPhyIsrGmac(pAC, IoC, i, PhyInt);
+- }
+- }
+-#endif /* YUKON */
+- }
+- }
+-
+- /* I2C Ready interrupt */
+- if ((Istatus & IS_I2C_READY) != 0) {
+-#ifdef SK_SLIM
+- SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
+-#else
+- SkI2cIsr(pAC, IoC);
+-#endif
+- }
+-
+- /* SW forced interrupt */
+- if ((Istatus & IS_IRQ_SW) != 0) {
+- /* clear the software IRQ */
+- SK_OUT8(IoC, B0_CTST, CS_CL_SW_IRQ);
+- }
+-
+- if ((Istatus & IS_LNK_SYNC_M1) != 0) {
+- /*
+- * We do NOT need the Link Sync interrupt, because it shows
+- * us only a link going down.
+- */
+- /* clear interrupt */
+- SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LED_CLR_IRQ);
+- }
+-
+- /* Check MAC after link sync counter */
+- if ((Istatus & IS_MAC1) != 0) {
+- /* IRQ from MAC 1 */
+- SkMacIrq(pAC, IoC, MAC_1);
+- }
+-
+- if ((Istatus & IS_LNK_SYNC_M2) != 0) {
+- /*
+- * We do NOT need the Link Sync interrupt, because it shows
+- * us only a link going down.
+- */
+- /* clear interrupt */
+- SK_OUT8(IoC, MR_ADDR(MAC_2, LNK_SYNC_CTRL), LED_CLR_IRQ);
+- }
+-
+- /* Check MAC after link sync counter */
+- if ((Istatus & IS_MAC2) != 0) {
+- /* IRQ from MAC 2 */
+- SkMacIrq(pAC, IoC, MAC_2);
+- }
+-
+- /* Timer interrupt (served last) */
+- if ((Istatus & IS_TIMINT) != 0) {
+- /* check for HW Errors */
+- if (((Istatus & IS_HW_ERR) & ~pAC->GIni.GIValIrqMask) != 0) {
+- /* read the HW Error Interrupt source */
+- SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
+-
+- SkGeHwErr(pAC, IoC, RegVal32);
+- }
+-
+- SkHwtIsr(pAC, IoC);
+- }
+-
+-} /* SkGeSirqIsr */
+-
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- * SkGePortCheckShorts() - Implementing XMAC Workaround Errata # 2
+- *
+- * return:
+- * 0 o.k. nothing needed
+- * 1 Restart needed on this port
+- */
+-static int SkGePortCheckShorts(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* IO Context */
+-int Port) /* Which port should be checked */
+-{
+- SK_U32 Shorts; /* Short Event Counter */
+- SK_U32 CheckShorts; /* Check value for Short Event Counter */
+- SK_U64 RxCts; /* Rx Counter (packets on network) */
+- SK_U32 RxTmp; /* Rx temp. Counter */
+- SK_U32 FcsErrCts; /* FCS Error Counter */
+- SK_GEPORT *pPrt; /* GIni Port struct pointer */
+- int Rtv; /* Return value */
+- int i;
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- /* Default: no action */
+- Rtv = SK_HW_PS_NONE;
+-
+- (void)SkXmUpdateStats(pAC, IoC, Port);
+-
+- /* Extra precaution: check for short Event counter */
+- (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
+-
+- /*
+- * Read Rx counters (packets seen on the network and not necessarily
+- * really received.
+- */
+- RxCts = 0;
+-
+- for (i = 0; i < ARRAY_SIZE(SkGeRxRegs); i++) {
+-
+- (void)SkXmMacStatistic(pAC, IoC, Port, SkGeRxRegs[i], &RxTmp);
+-
+- RxCts += (SK_U64)RxTmp;
+- }
+-
+- /* On default: check shorts against zero */
+- CheckShorts = 0;
+-
+- /* Extra precaution on active links */
+- if (pPrt->PHWLinkUp) {
+- /* Reset Link Restart counter */
+- pPrt->PLinkResCt = 0;
+- pPrt->PAutoNegTOCt = 0;
+-
+- /* If link is up check for 2 */
+- CheckShorts = 2;
+-
+- (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXF_FCS_ERR, &FcsErrCts);
+-
+- if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
+- pPrt->PLipaAutoNeg == SK_LIPA_UNKNOWN &&
+- (pPrt->PLinkMode == SK_LMODE_HALF ||
+- pPrt->PLinkMode == SK_LMODE_FULL)) {
+- /*
+- * This is autosensing and we are in the fallback
+- * manual full/half duplex mode.
+- */
+- if (RxCts == pPrt->PPrevRx) {
+- /* Nothing received, restart link */
+- pPrt->PPrevFcs = FcsErrCts;
+- pPrt->PPrevShorts = Shorts;
+-
+- return(SK_HW_PS_RESTART);
+- }
+- else {
+- pPrt->PLipaAutoNeg = SK_LIPA_MANUAL;
+- }
+- }
+-
+- if (((RxCts - pPrt->PPrevRx) > pPrt->PRxLim) ||
+- (!(FcsErrCts - pPrt->PPrevFcs))) {
+- /*
+- * Note: The compare with zero above has to be done the way shown,
+- * otherwise the Linux driver will have a problem.
+- */
+- /*
+- * We received a bunch of frames or no CRC error occured on the
+- * network -> ok.
+- */
+- pPrt->PPrevRx = RxCts;
+- pPrt->PPrevFcs = FcsErrCts;
+- pPrt->PPrevShorts = Shorts;
+-
+- return(SK_HW_PS_NONE);
+- }
+-
+- pPrt->PPrevFcs = FcsErrCts;
+- }
+-
+-
+- if ((Shorts - pPrt->PPrevShorts) > CheckShorts) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("Short Event Count Restart Port %d \n", Port));
+- Rtv = SK_HW_PS_RESTART;
+- }
+-
+- pPrt->PPrevShorts = Shorts;
+- pPrt->PPrevRx = RxCts;
+-
+- return(Rtv);
+-} /* SkGePortCheckShorts */
+-#endif /* GENESIS */
+-
+-
+-/******************************************************************************
+- *
+- * SkGePortCheckUp() - Check if the link is up
+- *
+- * return:
+- * 0 o.k. nothing needed
+- * 1 Restart needed on this port
+- * 2 Link came up
+- */
+-static int SkGePortCheckUp(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* IO Context */
+-int Port) /* Which port should be checked */
+-{
+- SK_GEPORT *pPrt; /* GIni Port struct pointer */
+- SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */
+- int Rtv; /* Return value */
+-
+- Rtv = SK_HW_PS_NONE;
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
+- AutoNeg = SK_FALSE;
+- }
+- else {
+- AutoNeg = SK_TRUE;
+- }
+-
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+-
+- switch (pPrt->PhyType) {
+-
+- case SK_PHY_XMAC:
+- Rtv = SkGePortCheckUpXmac(pAC, IoC, Port, AutoNeg);
+- break;
+- case SK_PHY_BCOM:
+- Rtv = SkGePortCheckUpBcom(pAC, IoC, Port, AutoNeg);
+- break;
+-#ifdef OTHER_PHY
+- case SK_PHY_LONE:
+- Rtv = SkGePortCheckUpLone(pAC, IoC, Port, AutoNeg);
+- break;
+- case SK_PHY_NAT:
+- Rtv = SkGePortCheckUpNat(pAC, IoC, Port, AutoNeg);
+- break;
+-#endif /* OTHER_PHY */
+- }
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIYukon) {
+-
+- Rtv = SkGePortCheckUpGmac(pAC, IoC, Port, AutoNeg);
+- }
+-#endif /* YUKON */
+-
+- return(Rtv);
+-} /* SkGePortCheckUp */
+-
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- * SkGePortCheckUpXmac() - Implementing of the Workaround Errata # 2
+- *
+- * return:
+- * 0 o.k. nothing needed
+- * 1 Restart needed on this port
+- * 2 Link came up
+- */
+-static int SkGePortCheckUpXmac(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* IO Context */
+-int Port, /* Which port should be checked */
+-SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
+-{
+- SK_U32 Shorts; /* Short Event Counter */
+- SK_GEPORT *pPrt; /* GIni Port struct pointer */
+- int Done;
+- SK_U32 GpReg; /* General Purpose register value */
+- SK_U16 Isrc; /* Interrupt source register */
+- SK_U16 IsrcSum; /* Interrupt source register sum */
+- SK_U16 LpAb; /* Link Partner Ability */
+- SK_U16 ResAb; /* Resolved Ability */
+- SK_U16 ExtStat; /* Extended Status Register */
+- SK_U8 NextMode; /* Next AutoSensing Mode */
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- if (pPrt->PHWLinkUp) {
+- if (pPrt->PhyType != SK_PHY_XMAC) {
+- return(SK_HW_PS_NONE);
+- }
+- else {
+- return(SkGePortCheckShorts(pAC, IoC, Port));
+- }
+- }
+-
+- IsrcSum = pPrt->PIsave;
+- pPrt->PIsave = 0;
+-
+- /* Now wait for each port's link */
+- if (pPrt->PLinkBroken) {
+- /* Link was broken */
+- XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
+-
+- if ((GpReg & XM_GP_INP_ASS) == 0) {
+- /* The Link is in sync */
+- XM_IN16(IoC, Port, XM_ISRC, &Isrc);
+- IsrcSum |= Isrc;
+- SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
+-
+- if ((Isrc & XM_IS_INP_ASS) == 0) {
+- /* It has been in sync since last time */
+- /* Restart the PORT */
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("Link in sync Restart Port %d\n", Port));
+-
+- (void)SkXmUpdateStats(pAC, IoC, Port);
+-
+- /* We now need to reinitialize the PrevShorts counter */
+- (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
+- pPrt->PPrevShorts = Shorts;
+-
+- pPrt->PLinkBroken = SK_FALSE;
+-
+- /*
+- * Link Restart Workaround:
+- * it may be possible that the other Link side
+- * restarts its link as well an we detect
+- * another LinkBroken. To prevent this
+- * happening we check for a maximum number
+- * of consecutive restart. If those happens,
+- * we do NOT restart the active link and
+- * check whether the link is now o.k.
+- */
+- pPrt->PLinkResCt++;
+-
+- pPrt->PAutoNegTimeOut = 0;
+-
+- if (pPrt->PLinkResCt < SK_MAX_LRESTART) {
+- return(SK_HW_PS_RESTART);
+- }
+-
+- pPrt->PLinkResCt = 0;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Do NOT restart on Port %d %x %x\n", Port, Isrc, IsrcSum));
+- }
+- else {
+- pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Save Sync/nosync Port %d %x %x\n", Port, Isrc, IsrcSum));
+-
+- /* Do nothing more if link is broken */
+- return(SK_HW_PS_NONE);
+- }
+- }
+- else {
+- /* Do nothing more if link is broken */
+- return(SK_HW_PS_NONE);
+- }
+-
+- }
+- else {
+- /* Link was not broken, check if it is */
+- XM_IN16(IoC, Port, XM_ISRC, &Isrc);
+- IsrcSum |= Isrc;
+- if ((Isrc & XM_IS_INP_ASS) != 0) {
+- XM_IN16(IoC, Port, XM_ISRC, &Isrc);
+- IsrcSum |= Isrc;
+- if ((Isrc & XM_IS_INP_ASS) != 0) {
+- XM_IN16(IoC, Port, XM_ISRC, &Isrc);
+- IsrcSum |= Isrc;
+- if ((Isrc & XM_IS_INP_ASS) != 0) {
+- pPrt->PLinkBroken = SK_TRUE;
+- /* Re-Init Link partner Autoneg flag */
+- pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("Link broken Port %d\n", Port));
+-
+- /* Cable removed-> reinit sense mode */
+- SkHWInitDefSense(pAC, IoC, Port);
+-
+- return(SK_HW_PS_RESTART);
+- }
+- }
+- }
+- else {
+- SkXmAutoNegLipaXmac(pAC, IoC, Port, Isrc);
+-
+- if (SkGePortCheckShorts(pAC, IoC, Port) == SK_HW_PS_RESTART) {
+- return(SK_HW_PS_RESTART);
+- }
+- }
+- }
+-
+- /*
+- * here we usually can check whether the link is in sync and
+- * auto-negotiation is done.
+- */
+- XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
+- XM_IN16(IoC, Port, XM_ISRC, &Isrc);
+- IsrcSum |= Isrc;
+-
+- SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
+-
+- if ((GpReg & XM_GP_INP_ASS) != 0 || (IsrcSum & XM_IS_INP_ASS) != 0) {
+- if ((GpReg & XM_GP_INP_ASS) == 0) {
+- /* Save Auto-negotiation Done interrupt only if link is in sync */
+- pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
+- }
+-#ifdef DEBUG
+- if ((pPrt->PIsave & XM_IS_AND) != 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("AutoNeg done rescheduled Port %d\n", Port));
+- }
+-#endif /* DEBUG */
+- return(SK_HW_PS_NONE);
+- }
+-
+- if (AutoNeg) {
+- if ((IsrcSum & XM_IS_AND) != 0) {
+- SkHWLinkUp(pAC, IoC, Port);
+- Done = SkMacAutoNegDone(pAC, IoC, Port);
+- if (Done != SK_AND_OK) {
+- /* Get PHY parameters, for debugging only */
+- SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LpAb);
+- SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("AutoNeg FAIL Port %d (LpAb %x, ResAb %x)\n",
+- Port, LpAb, ResAb));
+-
+- /* Try next possible mode */
+- NextMode = SkHWSenseGetNext(pAC, IoC, Port);
+- SkHWLinkDown(pAC, IoC, Port);
+- if (Done == SK_AND_DUP_CAP) {
+- /* GoTo next mode */
+- SkHWSenseSetNext(pAC, IoC, Port, NextMode);
+- }
+-
+- return(SK_HW_PS_RESTART);
+- }
+- /*
+- * Dummy Read extended status to prevent extra link down/ups
+- * (clear Page Received bit if set)
+- */
+- SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_EXP, &ExtStat);
+-
+- return(SK_HW_PS_LINK);
+- }
+-
+- /* AutoNeg not done, but HW link is up. Check for timeouts */
+- pPrt->PAutoNegTimeOut++;
+- if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
+- /* Increase the Timeout counter */
+- pPrt->PAutoNegTOCt++;
+-
+- /* Timeout occured */
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("AutoNeg timeout Port %d\n", Port));
+- if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
+- pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
+- /* Set Link manually up */
+- SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("Set manual full duplex Port %d\n", Port));
+- }
+-
+- if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
+- pPrt->PLipaAutoNeg == SK_LIPA_AUTO &&
+- pPrt->PAutoNegTOCt >= SK_MAX_ANEG_TO) {
+- /*
+- * This is rather complicated.
+- * we need to check here whether the LIPA_AUTO
+- * we saw before is false alert. We saw at one
+- * switch ( SR8800) that on boot time it sends
+- * just one auto-neg packet and does no further
+- * auto-negotiation.
+- * Solution: we restart the autosensing after
+- * a few timeouts.
+- */
+- pPrt->PAutoNegTOCt = 0;
+- pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
+- SkHWInitDefSense(pAC, IoC, Port);
+- }
+-
+- /* Do the restart */
+- return(SK_HW_PS_RESTART);
+- }
+- }
+- else {
+- /* Link is up and we don't need more */
+-#ifdef DEBUG
+- if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("ERROR: Lipa auto detected on port %d\n", Port));
+- }
+-#endif /* DEBUG */
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("Link sync(GP), Port %d\n", Port));
+- SkHWLinkUp(pAC, IoC, Port);
+-
+- /*
+- * Link sync (GP) and so assume a good connection. But if not received
+- * a bunch of frames received in a time slot (maybe broken tx cable)
+- * the port is restart.
+- */
+- return(SK_HW_PS_LINK);
+- }
+-
+- return(SK_HW_PS_NONE);
+-} /* SkGePortCheckUpXmac */
+-
+-
+-/******************************************************************************
+- *
+- * SkGePortCheckUpBcom() - Check if the link is up on Bcom PHY
+- *
+- * return:
+- * 0 o.k. nothing needed
+- * 1 Restart needed on this port
+- * 2 Link came up
+- */
+-static int SkGePortCheckUpBcom(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* IO Context */
+-int Port, /* Which port should be checked */
+-SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
+-{
+- SK_GEPORT *pPrt; /* GIni Port struct pointer */
+- int Done;
+- SK_U16 Isrc; /* Interrupt source register */
+- SK_U16 PhyStat; /* Phy Status Register */
+- SK_U16 ResAb; /* Master/Slave resolution */
+- SK_U16 Ctrl; /* Broadcom control flags */
+-#ifdef DEBUG
+- SK_U16 LpAb;
+- SK_U16 ExtStat;
+-#endif /* DEBUG */
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- /* Check for No HCD Link events (#10523) */
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &Isrc);
+-
+-#ifdef xDEBUG
+- if ((Isrc & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) ==
+- (PHY_B_IS_SCR_S_ER | PHY_B_IS_RRS_CHANGE | PHY_B_IS_LRS_CHANGE)) {
+-
+- SK_U32 Stat1, Stat2, Stat3;
+-
+- Stat1 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
+- CMSMPrintString(
+- pAC->pConfigTable,
+- MSG_TYPE_RUNTIME_INFO,
+- "CheckUp1 - Stat: %x, Mask: %x",
+- (void *)Isrc,
+- (void *)Stat1);
+-
+- Stat1 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
+- Stat2 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &Stat2);
+- Stat1 = Stat1 << 16 | Stat2;
+- Stat2 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
+- Stat3 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
+- Stat2 = Stat2 << 16 | Stat3;
+- CMSMPrintString(
+- pAC->pConfigTable,
+- MSG_TYPE_RUNTIME_INFO,
+- "Ctrl/Stat: %x, AN Adv/LP: %x",
+- (void *)Stat1,
+- (void *)Stat2);
+-
+- Stat1 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
+- Stat2 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
+- Stat1 = Stat1 << 16 | Stat2;
+- Stat2 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
+- Stat3 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &Stat3);
+- Stat2 = Stat2 << 16 | Stat3;
+- CMSMPrintString(
+- pAC->pConfigTable,
+- MSG_TYPE_RUNTIME_INFO,
+- "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
+- (void *)Stat1,
+- (void *)Stat2);
+-
+- Stat1 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
+- Stat2 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
+- Stat1 = Stat1 << 16 | Stat2;
+- Stat2 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
+- Stat3 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
+- Stat2 = Stat2 << 16 | Stat3;
+- CMSMPrintString(
+- pAC->pConfigTable,
+- MSG_TYPE_RUNTIME_INFO,
+- "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
+- (void *)Stat1,
+- (void *)Stat2);
+- }
+-#endif /* DEBUG */
+-
+- if ((Isrc & (PHY_B_IS_NO_HDCL /* | PHY_B_IS_NO_HDC */)) != 0) {
+- /*
+- * Workaround BCom Errata:
+- * enable and disable loopback mode if "NO HCD" occurs.
+- */
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Ctrl);
+- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL,
+- (SK_U16)(Ctrl | PHY_CT_LOOP));
+- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL,
+- (SK_U16)(Ctrl & ~PHY_CT_LOOP));
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("No HCD Link event, Port %d\n", Port));
+-#ifdef xDEBUG
+- CMSMPrintString(
+- pAC->pConfigTable,
+- MSG_TYPE_RUNTIME_INFO,
+- "No HCD link event, port %d.",
+- (void *)Port,
+- (void *)NULL);
+-#endif /* DEBUG */
+- }
+-
+- /* Not obsolete: link status bit is latched to 0 and autoclearing! */
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
+-
+- if (pPrt->PHWLinkUp) {
+- return(SK_HW_PS_NONE);
+- }
+-
+-#ifdef xDEBUG
+- {
+- SK_U32 Stat1, Stat2, Stat3;
+-
+- Stat1 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
+- CMSMPrintString(
+- pAC->pConfigTable,
+- MSG_TYPE_RUNTIME_INFO,
+- "CheckUp1a - Stat: %x, Mask: %x",
+- (void *)Isrc,
+- (void *)Stat1);
+-
+- Stat1 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
+- Stat2 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
+- Stat1 = Stat1 << 16 | PhyStat;
+- Stat2 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
+- Stat3 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
+- Stat2 = Stat2 << 16 | Stat3;
+- CMSMPrintString(
+- pAC->pConfigTable,
+- MSG_TYPE_RUNTIME_INFO,
+- "Ctrl/Stat: %x, AN Adv/LP: %x",
+- (void *)Stat1,
+- (void *)Stat2);
+-
+- Stat1 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
+- Stat2 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
+- Stat1 = Stat1 << 16 | Stat2;
+- Stat2 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
+- Stat3 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
+- Stat2 = Stat2 << 16 | ResAb;
+- CMSMPrintString(
+- pAC->pConfigTable,
+- MSG_TYPE_RUNTIME_INFO,
+- "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
+- (void *)Stat1,
+- (void *)Stat2);
+-
+- Stat1 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
+- Stat2 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
+- Stat1 = Stat1 << 16 | Stat2;
+- Stat2 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
+- Stat3 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
+- Stat2 = Stat2 << 16 | Stat3;
+- CMSMPrintString(
+- pAC->pConfigTable,
+- MSG_TYPE_RUNTIME_INFO,
+- "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
+- (void *)Stat1,
+- (void *)Stat2);
+- }
+-#endif /* DEBUG */
+-
+- /*
+- * Here we usually can check whether the link is in sync and
+- * auto-negotiation is done.
+- */
+-
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
+-
+- SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
+-
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
+-
+- if ((ResAb & PHY_B_1000S_MSF) != 0) {
+- /* Error */
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Master/Slave Fault port %d\n", Port));
+-
+- pPrt->PAutoNegFail = SK_TRUE;
+- pPrt->PMSStatus = SK_MS_STAT_FAULT;
+-
+- return(SK_HW_PS_RESTART);
+- }
+-
+- if ((PhyStat & PHY_ST_LSYNC) == 0) {
+- return(SK_HW_PS_NONE);
+- }
+-
+- pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
+- SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Port %d, ResAb: 0x%04X\n", Port, ResAb));
+-
+- if (AutoNeg) {
+- if ((PhyStat & PHY_ST_AN_OVER) != 0) {
+-
+- SkHWLinkUp(pAC, IoC, Port);
+-
+- Done = SkMacAutoNegDone(pAC, IoC, Port);
+-
+- if (Done != SK_AND_OK) {
+-#ifdef DEBUG
+- /* Get PHY parameters, for debugging only */
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LpAb);
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ExtStat);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
+- Port, LpAb, ExtStat));
+-#endif /* DEBUG */
+- return(SK_HW_PS_RESTART);
+- }
+- else {
+-#ifdef xDEBUG
+- /* Dummy read ISR to prevent extra link downs/ups */
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
+-
+- if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
+- CMSMPrintString(
+- pAC->pConfigTable,
+- MSG_TYPE_RUNTIME_INFO,
+- "CheckUp2 - Stat: %x",
+- (void *)ExtStat,
+- (void *)NULL);
+- }
+-#endif /* DEBUG */
+- return(SK_HW_PS_LINK);
+- }
+- }
+- }
+- else { /* !AutoNeg */
+- /* Link is up and we don't need more. */
+-#ifdef DEBUG
+- if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("ERROR: Lipa auto detected on port %d\n", Port));
+- }
+-#endif /* DEBUG */
+-
+-#ifdef xDEBUG
+- /* Dummy read ISR to prevent extra link downs/ups */
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
+-
+- if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
+- CMSMPrintString(
+- pAC->pConfigTable,
+- MSG_TYPE_RUNTIME_INFO,
+- "CheckUp3 - Stat: %x",
+- (void *)ExtStat,
+- (void *)NULL);
+- }
+-#endif /* DEBUG */
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("Link sync(GP), Port %d\n", Port));
+- SkHWLinkUp(pAC, IoC, Port);
+-
+- return(SK_HW_PS_LINK);
+- }
+-
+- return(SK_HW_PS_NONE);
+-} /* SkGePortCheckUpBcom */
+-#endif /* GENESIS */
+-
+-
+-#ifdef YUKON
+-/******************************************************************************
+- *
+- * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY
+- *
+- * return:
+- * 0 o.k. nothing needed
+- * 1 Restart needed on this port
+- * 2 Link came up
+- */
+-static int SkGePortCheckUpGmac(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* IO Context */
+-int Port, /* Which port should be checked */
+-SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
+-{
+- SK_GEPORT *pPrt; /* GIni Port struct pointer */
+- int Done;
+- SK_U16 PhyIsrc; /* PHY Interrupt source */
+- SK_U16 PhyStat; /* PPY Status */
+- SK_U16 PhySpecStat;/* PHY Specific Status */
+- SK_U16 ResAb; /* Master/Slave resolution */
+- SK_EVPARA Para;
+-#ifdef DEBUG
+- SK_U16 Word; /* I/O helper */
+-#endif /* DEBUG */
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- if (pPrt->PHWLinkUp) {
+- return(SK_HW_PS_NONE);
+- }
+-
+- /* Read PHY Status */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
+-
+- /* Read PHY Interrupt Status */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &PhyIsrc);
+-
+- if ((PhyIsrc & PHY_M_IS_AN_COMPL) != 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Auto-Negotiation Completed, PhyIsrc: 0x%04X\n", PhyIsrc));
+- }
+-
+- if ((PhyIsrc & PHY_M_IS_LSP_CHANGE) != 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Link Speed Changed, PhyIsrc: 0x%04X\n", PhyIsrc));
+- }
+-
+- SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
+-
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
+-
+- if ((ResAb & PHY_B_1000S_MSF) != 0) {
+- /* Error */
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Master/Slave Fault port %d\n", Port));
+-
+- pPrt->PAutoNegFail = SK_TRUE;
+- pPrt->PMSStatus = SK_MS_STAT_FAULT;
+-
+- return(SK_HW_PS_RESTART);
+- }
+-
+- /* Read PHY Specific Status */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Phy1000BT: 0x%04X, PhySpecStat: 0x%04X\n", ResAb, PhySpecStat));
+-
+-#ifdef DEBUG
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_EXP, &Word);
+-
+- if ((PhyIsrc & PHY_M_IS_AN_PR) != 0 || (Word & PHY_ANE_RX_PG) != 0 ||
+- (PhySpecStat & PHY_M_PS_PAGE_REC) != 0) {
+- /* Read PHY Next Page Link Partner */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_NEPG_LP, &Word);
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Page Received, NextPage: 0x%04X\n", Word));
+- }
+-#endif /* DEBUG */
+-
+- if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) {
+- return(SK_HW_PS_NONE);
+- }
+-
+- if ((PhySpecStat & PHY_M_PS_DOWNS_STAT) != 0 ||
+- (PhyIsrc & PHY_M_IS_DOWNSH_DET) != 0) {
+- /* Downshift detected */
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E025, SKERR_SIRQ_E025MSG);
+-
+- Para.Para64 = Port;
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_DOWNSHIFT_DET, Para);
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Downshift detected, PhyIsrc: 0x%04X\n", PhyIsrc));
+- }
+-
+- pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
+- SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
+-
+- pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7);
+-
+- if (AutoNeg) {
+- /* Auto-Negotiation Over ? */
+- if ((PhyStat & PHY_ST_AN_OVER) != 0) {
+-
+- SkHWLinkUp(pAC, IoC, Port);
+-
+- Done = SkMacAutoNegDone(pAC, IoC, Port);
+-
+- if (Done != SK_AND_OK) {
+- return(SK_HW_PS_RESTART);
+- }
+-
+- return(SK_HW_PS_LINK);
+- }
+- }
+- else { /* !AutoNeg */
+- /* Link is up and we don't need more */
+-#ifdef DEBUG
+- if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("ERROR: Lipa auto detected on port %d\n", Port));
+- }
+-#endif /* DEBUG */
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("Link sync, Port %d\n", Port));
+- SkHWLinkUp(pAC, IoC, Port);
+-
+- return(SK_HW_PS_LINK);
+- }
+-
+- return(SK_HW_PS_NONE);
+-} /* SkGePortCheckUpGmac */
+-#endif /* YUKON */
+-
+-
+-#ifdef OTHER_PHY
+-/******************************************************************************
+- *
+- * SkGePortCheckUpLone() - Check if the link is up on Level One PHY
+- *
+- * return:
+- * 0 o.k. nothing needed
+- * 1 Restart needed on this port
+- * 2 Link came up
+- */
+-static int SkGePortCheckUpLone(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* IO Context */
+-int Port, /* Which port should be checked */
+-SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
+-{
+- SK_GEPORT *pPrt; /* GIni Port struct pointer */
+- int Done;
+- SK_U16 Isrc; /* Interrupt source register */
+- SK_U16 LpAb; /* Link Partner Ability */
+- SK_U16 ExtStat; /* Extended Status Register */
+- SK_U16 PhyStat; /* Phy Status Register */
+- SK_U16 StatSum;
+- SK_U8 NextMode; /* Next AutoSensing Mode */
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- if (pPrt->PHWLinkUp) {
+- return(SK_HW_PS_NONE);
+- }
+-
+- StatSum = pPrt->PIsave;
+- pPrt->PIsave = 0;
+-
+- /*
+- * here we usually can check whether the link is in sync and
+- * auto-negotiation is done.
+- */
+- SkXmPhyRead(pAC, IoC, Port, PHY_LONE_STAT, &PhyStat);
+- StatSum |= PhyStat;
+-
+- SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
+-
+- if ((PhyStat & PHY_ST_LSYNC) == 0) {
+- /* Save Auto-negotiation Done bit */
+- pPrt->PIsave = (SK_U16)(StatSum & PHY_ST_AN_OVER);
+-#ifdef DEBUG
+- if ((pPrt->PIsave & PHY_ST_AN_OVER) != 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("AutoNeg done rescheduled Port %d\n", Port));
+- }
+-#endif /* DEBUG */
+- return(SK_HW_PS_NONE);
+- }
+-
+- if (AutoNeg) {
+- if ((StatSum & PHY_ST_AN_OVER) != 0) {
+- SkHWLinkUp(pAC, IoC, Port);
+- Done = SkMacAutoNegDone(pAC, IoC, Port);
+- if (Done != SK_AND_OK) {
+- /* Get PHY parameters, for debugging only */
+- SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LpAb);
+- SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ExtStat);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
+- Port, LpAb, ExtStat));
+-
+- /* Try next possible mode */
+- NextMode = SkHWSenseGetNext(pAC, IoC, Port);
+- SkHWLinkDown(pAC, IoC, Port);
+- if (Done == SK_AND_DUP_CAP) {
+- /* GoTo next mode */
+- SkHWSenseSetNext(pAC, IoC, Port, NextMode);
+- }
+-
+- return(SK_HW_PS_RESTART);
+-
+- }
+- else {
+- /*
+- * Dummy Read interrupt status to prevent
+- * extra link down/ups
+- */
+- SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
+- return(SK_HW_PS_LINK);
+- }
+- }
+-
+- /* AutoNeg not done, but HW link is up. Check for timeouts */
+- pPrt->PAutoNegTimeOut++;
+- if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
+- /* Timeout occured */
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("AutoNeg timeout Port %d\n", Port));
+- if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
+- pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
+- /* Set Link manually up */
+- SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("Set manual full duplex Port %d\n", Port));
+- }
+-
+- /* Do the restart */
+- return(SK_HW_PS_RESTART);
+- }
+- }
+- else {
+- /* Link is up and we don't need more */
+-#ifdef DEBUG
+- if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("ERROR: Lipa auto detected on port %d\n", Port));
+- }
+-#endif /* DEBUG */
+-
+- /*
+- * Dummy Read interrupt status to prevent
+- * extra link down/ups
+- */
+- SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("Link sync(GP), Port %d\n", Port));
+- SkHWLinkUp(pAC, IoC, Port);
+-
+- return(SK_HW_PS_LINK);
+- }
+-
+- return(SK_HW_PS_NONE);
+-} /* SkGePortCheckUpLone */
+-
+-
+-/******************************************************************************
+- *
+- * SkGePortCheckUpNat() - Check if the link is up on National PHY
+- *
+- * return:
+- * 0 o.k. nothing needed
+- * 1 Restart needed on this port
+- * 2 Link came up
+- */
+-static int SkGePortCheckUpNat(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* IO Context */
+-int Port, /* Which port should be checked */
+-SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
+-{
+- /* todo: National */
+- return(SK_HW_PS_NONE);
+-} /* SkGePortCheckUpNat */
+-#endif /* OTHER_PHY */
+-
+-
+-/******************************************************************************
+- *
+- * SkGeSirqEvent() - Event Service Routine
+- *
+- * Description:
+- *
+- * Notes:
+- */
+-int SkGeSirqEvent(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* Io Context */
+-SK_U32 Event, /* Module specific Event */
+-SK_EVPARA Para) /* Event specific Parameter */
+-{
+- SK_GEPORT *pPrt; /* GIni Port struct pointer */
+- SK_U32 Port;
+- SK_U32 Val32;
+- int PortStat;
+- SK_U8 Val8;
+-#ifdef GENESIS
+- SK_U64 Octets;
+-#endif /* GENESIS */
+-
+- Port = Para.Para32[0];
+- pPrt = &pAC->GIni.GP[Port];
+-
+- switch (Event) {
+- case SK_HWEV_WATIM:
+- if (pPrt->PState == SK_PRT_RESET) {
+-
+- PortStat = SK_HW_PS_NONE;
+- }
+- else {
+- /* Check whether port came up */
+- PortStat = SkGePortCheckUp(pAC, IoC, (int)Port);
+- }
+-
+- switch (PortStat) {
+- case SK_HW_PS_RESTART:
+- if (pPrt->PHWLinkUp) {
+- /* Set Link to down */
+- SkHWLinkDown(pAC, IoC, (int)Port);
+-
+- /*
+- * Signal directly to RLMT to ensure correct
+- * sequence of SWITCH and RESET event.
+- */
+- SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
+- }
+-
+- /* Restart needed */
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
+- break;
+-
+- case SK_HW_PS_LINK:
+- /* Signal to RLMT */
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para);
+- break;
+- }
+-
+- /* Start again the check Timer */
+- if (pPrt->PHWLinkUp) {
+- Val32 = SK_WA_ACT_TIME;
+- }
+- else {
+- Val32 = SK_WA_INA_TIME;
+- }
+-
+- /* Todo: still needed for non-XMAC PHYs??? */
+- /* Start workaround Errata #2 timer */
+- SkTimerStart(pAC, IoC, &pPrt->PWaTimer, Val32,
+- SKGE_HWAC, SK_HWEV_WATIM, Para);
+- break;
+-
+- case SK_HWEV_PORT_START:
+- if (pPrt->PHWLinkUp) {
+- /*
+- * Signal directly to RLMT to ensure correct
+- * sequence of SWITCH and RESET event.
+- */
+- SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
+- }
+-
+- SkHWLinkDown(pAC, IoC, (int)Port);
+-
+- /* Schedule Port RESET */
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
+-
+- /* Start workaround Errata #2 timer */
+- SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
+- SKGE_HWAC, SK_HWEV_WATIM, Para);
+- break;
+-
+- case SK_HWEV_PORT_STOP:
+- if (pPrt->PHWLinkUp) {
+- /*
+- * Signal directly to RLMT to ensure correct
+- * sequence of SWITCH and RESET event.
+- */
+- SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
+- }
+-
+- /* Stop Workaround Timer */
+- SkTimerStop(pAC, IoC, &pPrt->PWaTimer);
+-
+- SkHWLinkDown(pAC, IoC, (int)Port);
+- break;
+-
+- case SK_HWEV_UPDATE_STAT:
+- /* We do NOT need to update any statistics */
+- break;
+-
+- case SK_HWEV_CLEAR_STAT:
+- /* We do NOT need to clear any statistics */
+- for (Port = 0; Port < (SK_U32)pAC->GIni.GIMacsFound; Port++) {
+- pPrt->PPrevRx = 0;
+- pPrt->PPrevFcs = 0;
+- pPrt->PPrevShorts = 0;
+- }
+- break;
+-
+- case SK_HWEV_SET_LMODE:
+- Val8 = (SK_U8)Para.Para32[1];
+- if (pPrt->PLinkModeConf != Val8) {
+- /* Set New link mode */
+- pPrt->PLinkModeConf = Val8;
+-
+- /* Restart Port */
+- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
+- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
+- }
+- break;
+-
+- case SK_HWEV_SET_FLOWMODE:
+- Val8 = (SK_U8)Para.Para32[1];
+- if (pPrt->PFlowCtrlMode != Val8) {
+- /* Set New Flow Control mode */
+- pPrt->PFlowCtrlMode = Val8;
+-
+- /* Restart Port */
+- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
+- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
+- }
+- break;
+-
+- case SK_HWEV_SET_ROLE:
+- /* not possible for fiber */
+- if (!pAC->GIni.GICopperType) {
+- break;
+- }
+- Val8 = (SK_U8)Para.Para32[1];
+- if (pPrt->PMSMode != Val8) {
+- /* Set New Role (Master/Slave) mode */
+- pPrt->PMSMode = Val8;
+-
+- /* Restart Port */
+- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
+- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
+- }
+- break;
+-
+- case SK_HWEV_SET_SPEED:
+- if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
+- break;
+- }
+- Val8 = (SK_U8)Para.Para32[1];
+- if (pPrt->PLinkSpeed != Val8) {
+- /* Set New Speed parameter */
+- pPrt->PLinkSpeed = Val8;
+-
+- /* Restart Port */
+- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
+- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
+- }
+- break;
+-
+-#ifdef GENESIS
+- case SK_HWEV_HALFDUP_CHK:
+- if (pAC->GIni.GIGenesis) {
+- /*
+- * half duplex hangup workaround.
+- * See packet arbiter timeout interrupt for description
+- */
+- pPrt->HalfDupTimerActive = SK_FALSE;
+- if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
+- pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) {
+- /* Snap statistic counters */
+- (void)SkXmUpdateStats(pAC, IoC, Port);
+-
+- (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_HI, &Val32);
+-
+- Octets = (SK_U64)Val32 << 32;
+-
+- (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_LO, &Val32);
+-
+- Octets += Val32;
+-
+- if (pPrt->LastOctets == Octets) {
+- /* Tx hanging, a FIFO flush restarts it */
+- SkMacFlushTxFifo(pAC, IoC, Port);
+- }
+- }
+- }
+- break;
+-#endif /* GENESIS */
+-
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG);
+- break;
+- }
+-
+- return(0);
+-} /* SkGeSirqEvent */
+-
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- * SkPhyIsrBcom() - PHY interrupt service routine
+- *
+- * Description: handles all interrupts from BCom PHY
+- *
+- * Returns: N/A
+- */
+-static void SkPhyIsrBcom(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* Io Context */
+-int Port, /* Port Num = PHY Num */
+-SK_U16 IStatus) /* Interrupt Status */
+-{
+- SK_GEPORT *pPrt; /* GIni Port struct pointer */
+- SK_EVPARA Para;
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- if ((IStatus & PHY_B_IS_PSE) != 0) {
+- /* Incorrectable pair swap error */
+- SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E022,
+- SKERR_SIRQ_E022MSG);
+- }
+-
+- if ((IStatus & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) != 0) {
+-
+- SkHWLinkDown(pAC, IoC, Port);
+-
+- Para.Para32[0] = (SK_U32)Port;
+- /* Signal to RLMT */
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+-
+- /* Start workaround Errata #2 timer */
+- SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
+- SKGE_HWAC, SK_HWEV_WATIM, Para);
+- }
+-
+-} /* SkPhyIsrBcom */
+-#endif /* GENESIS */
+-
+-
+-#ifdef YUKON
+-/******************************************************************************
+- *
+- * SkPhyIsrGmac() - PHY interrupt service routine
+- *
+- * Description: handles all interrupts from Marvell PHY
+- *
+- * Returns: N/A
+- */
+-static void SkPhyIsrGmac(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* Io Context */
+-int Port, /* Port Num = PHY Num */
+-SK_U16 IStatus) /* Interrupt Status */
+-{
+- SK_GEPORT *pPrt; /* GIni Port struct pointer */
+- SK_EVPARA Para;
+- SK_U16 Word;
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- if ((IStatus & (PHY_M_IS_AN_PR | PHY_M_IS_LST_CHANGE)) != 0) {
+-
+- SkHWLinkDown(pAC, IoC, Port);
+-
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &Word);
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("AutoNeg.Adv: 0x%04X\n", Word));
+-
+- /* Set Auto-negotiation advertisement */
+- if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) {
+- /* restore Asymmetric Pause bit */
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV,
+- (SK_U16)(Word | PHY_M_AN_ASP));
+- }
+-
+- Para.Para32[0] = (SK_U32)Port;
+- /* Signal to RLMT */
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+- }
+-
+- if ((IStatus & PHY_M_IS_AN_ERROR) != 0) {
+- /* Auto-Negotiation Error */
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E023, SKERR_SIRQ_E023MSG);
+- }
+-
+- if ((IStatus & PHY_M_IS_FIFO_ERROR) != 0) {
+- /* FIFO Overflow/Underrun Error */
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E024, SKERR_SIRQ_E024MSG);
+- }
+-
+-} /* SkPhyIsrGmac */
+-#endif /* YUKON */
+-
+-
+-#ifdef OTHER_PHY
+-/******************************************************************************
+- *
+- * SkPhyIsrLone() - PHY interrupt service routine
+- *
+- * Description: handles all interrupts from LONE PHY
+- *
+- * Returns: N/A
+- */
+-static void SkPhyIsrLone(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* Io Context */
+-int Port, /* Port Num = PHY Num */
+-SK_U16 IStatus) /* Interrupt Status */
+-{
+- SK_EVPARA Para;
+-
+- if (IStatus & (PHY_L_IS_DUP | PHY_L_IS_ISOL)) {
+-
+- SkHWLinkDown(pAC, IoC, Port);
+-
+- Para.Para32[0] = (SK_U32)Port;
+- /* Signal to RLMT */
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+- }
+-
+-} /* SkPhyIsrLone */
+-#endif /* OTHER_PHY */
+-
+-/* End of File */
+diff --git a/drivers/net/sk98lin/ski2c.c b/drivers/net/sk98lin/ski2c.c
+deleted file mode 100644
+index 79bf57c..0000000
+--- a/drivers/net/sk98lin/ski2c.c
++++ /dev/null
+@@ -1,1296 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: ski2c.c
+- * Project: Gigabit Ethernet Adapters, TWSI-Module
+- * Version: $Revision: 1.59 $
+- * Date: $Date: 2003/10/20 09:07:25 $
+- * Purpose: Functions to access Voltage and Temperature Sensor
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- * I2C Protocol
+- */
+-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+-static const char SysKonnectFileId[] =
+- "@(#) $Id: ski2c.c,v 1.59 2003/10/20 09:07:25 rschmidt Exp $ (C) Marvell. ";
+-#endif
+-
+-#include "h/skdrv1st.h" /* Driver Specific Definitions */
+-#include "h/lm80.h"
+-#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
+-
+-#ifdef __C2MAN__
+-/*
+- I2C protocol implementation.
+-
+- General Description:
+-
+- The I2C protocol is used for the temperature sensors and for
+- the serial EEPROM which hold the configuration.
+-
+- This file covers functions that allow to read write and do
+- some bulk requests a specified I2C address.
+-
+- The Genesis has 2 I2C buses. One for the EEPROM which holds
+- the VPD Data and one for temperature and voltage sensor.
+- The following picture shows the I2C buses, I2C devices and
+- their control registers.
+-
+- Note: The VPD functions are in skvpd.c
+-.
+-. PCI Config I2C Bus for VPD Data:
+-.
+-. +------------+
+-. | VPD EEPROM |
+-. +------------+
+-. |
+-. | <-- I2C
+-. |
+-. +-----------+-----------+
+-. | |
+-. +-----------------+ +-----------------+
+-. | PCI_VPD_ADR_REG | | PCI_VPD_DAT_REG |
+-. +-----------------+ +-----------------+
+-.
+-.
+-. I2C Bus for LM80 sensor:
+-.
+-. +-----------------+
+-. | Temperature and |
+-. | Voltage Sensor |
+-. | LM80 |
+-. +-----------------+
+-. |
+-. |
+-. I2C --> |
+-. |
+-. +----+
+-. +-------------->| OR |<--+
+-. | +----+ |
+-. +------+------+ |
+-. | | |
+-. +--------+ +--------+ +----------+
+-. | B2_I2C | | B2_I2C | | B2_I2C |
+-. | _CTRL | | _DATA | | _SW |
+-. +--------+ +--------+ +----------+
+-.
+- The I2C bus may be driven by the B2_I2C_SW or by the B2_I2C_CTRL
+- and B2_I2C_DATA registers.
+- For driver software it is recommended to use the I2C control and
+- data register, because I2C bus timing is done by the ASIC and
+- an interrupt may be received when the I2C request is completed.
+-
+- Clock Rate Timing: MIN MAX generated by
+- VPD EEPROM: 50 kHz 100 kHz HW
+- LM80 over I2C Ctrl/Data reg. 50 kHz 100 kHz HW
+- LM80 over B2_I2C_SW register 0 400 kHz SW
+-
+- Note: The clock generated by the hardware is dependend on the
+- PCI clock. If the PCI bus clock is 33 MHz, the I2C/VPD
+- clock is 50 kHz.
+- */
+-intro()
+-{}
+-#endif
+-
+-#ifdef SK_DIAG
+-/*
+- * I2C Fast Mode timing values used by the LM80.
+- * If new devices are added to the I2C bus the timing values have to be checked.
+- */
+-#ifndef I2C_SLOW_TIMING
+-#define T_CLK_LOW 1300L /* clock low time in ns */
+-#define T_CLK_HIGH 600L /* clock high time in ns */
+-#define T_DATA_IN_SETUP 100L /* data in Set-up Time */
+-#define T_START_HOLD 600L /* start condition hold time */
+-#define T_START_SETUP 600L /* start condition Set-up time */
+-#define T_STOP_SETUP 600L /* stop condition Set-up time */
+-#define T_BUS_IDLE 1300L /* time the bus must free after Tx */
+-#define T_CLK_2_DATA_OUT 900L /* max. clock low to data output valid */
+-#else /* I2C_SLOW_TIMING */
+-/* I2C Standard Mode Timing */
+-#define T_CLK_LOW 4700L /* clock low time in ns */
+-#define T_CLK_HIGH 4000L /* clock high time in ns */
+-#define T_DATA_IN_SETUP 250L /* data in Set-up Time */
+-#define T_START_HOLD 4000L /* start condition hold time */
+-#define T_START_SETUP 4700L /* start condition Set-up time */
+-#define T_STOP_SETUP 4000L /* stop condition Set-up time */
+-#define T_BUS_IDLE 4700L /* time the bus must free after Tx */
+-#endif /* !I2C_SLOW_TIMING */
+-
+-#define NS2BCLK(x) (((x)*125)/10000)
+-
+-/*
+- * I2C Wire Operations
+- *
+- * About I2C_CLK_LOW():
+- *
+- * The Data Direction bit (I2C_DATA_DIR) has to be set to input when setting
+- * clock to low, to prevent the ASIC and the I2C data client from driving the
+- * serial data line simultaneously (ASIC: last bit of a byte = '1', I2C client
+- * send an 'ACK'). See also Concentrator Bugreport No. 10192.
+- */
+-#define I2C_DATA_HIGH(IoC) SK_I2C_SET_BIT(IoC, I2C_DATA)
+-#define I2C_DATA_LOW(IoC) SK_I2C_CLR_BIT(IoC, I2C_DATA)
+-#define I2C_DATA_OUT(IoC) SK_I2C_SET_BIT(IoC, I2C_DATA_DIR)
+-#define I2C_DATA_IN(IoC) SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA)
+-#define I2C_CLK_HIGH(IoC) SK_I2C_SET_BIT(IoC, I2C_CLK)
+-#define I2C_CLK_LOW(IoC) SK_I2C_CLR_BIT(IoC, I2C_CLK | I2C_DATA_DIR)
+-#define I2C_START_COND(IoC) SK_I2C_CLR_BIT(IoC, I2C_CLK)
+-
+-#define NS2CLKT(x) ((x*125L)/10000)
+-
+-/*--------------- I2C Interface Register Functions --------------- */
+-
+-/*
+- * sending one bit
+- */
+-void SkI2cSndBit(
+-SK_IOC IoC, /* I/O Context */
+-SK_U8 Bit) /* Bit to send */
+-{
+- I2C_DATA_OUT(IoC);
+- if (Bit) {
+- I2C_DATA_HIGH(IoC);
+- }
+- else {
+- I2C_DATA_LOW(IoC);
+- }
+- SkDgWaitTime(IoC, NS2BCLK(T_DATA_IN_SETUP));
+- I2C_CLK_HIGH(IoC);
+- SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH));
+- I2C_CLK_LOW(IoC);
+-} /* SkI2cSndBit*/
+-
+-
+-/*
+- * Signal a start to the I2C Bus.
+- *
+- * A start is signaled when data goes to low in a high clock cycle.
+- *
+- * Ends with Clock Low.
+- *
+- * Status: not tested
+- */
+-void SkI2cStart(
+-SK_IOC IoC) /* I/O Context */
+-{
+- /* Init data and Clock to output lines */
+- /* Set Data high */
+- I2C_DATA_OUT(IoC);
+- I2C_DATA_HIGH(IoC);
+- /* Set Clock high */
+- I2C_CLK_HIGH(IoC);
+-
+- SkDgWaitTime(IoC, NS2BCLK(T_START_SETUP));
+-
+- /* Set Data Low */
+- I2C_DATA_LOW(IoC);
+-
+- SkDgWaitTime(IoC, NS2BCLK(T_START_HOLD));
+-
+- /* Clock low without Data to Input */
+- I2C_START_COND(IoC);
+-
+- SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW));
+-} /* SkI2cStart */
+-
+-
+-void SkI2cStop(
+-SK_IOC IoC) /* I/O Context */
+-{
+- /* Init data and Clock to output lines */
+- /* Set Data low */
+- I2C_DATA_OUT(IoC);
+- I2C_DATA_LOW(IoC);
+-
+- SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT));
+-
+- /* Set Clock high */
+- I2C_CLK_HIGH(IoC);
+-
+- SkDgWaitTime(IoC, NS2BCLK(T_STOP_SETUP));
+-
+- /*
+- * Set Data High: Do it by setting the Data Line to Input.
+- * Because of a pull up resistor the Data Line
+- * floods to high.
+- */
+- I2C_DATA_IN(IoC);
+-
+- /*
+- * When I2C activity is stopped
+- * o DATA should be set to input and
+- * o CLOCK should be set to high!
+- */
+- SkDgWaitTime(IoC, NS2BCLK(T_BUS_IDLE));
+-} /* SkI2cStop */
+-
+-
+-/*
+- * Receive just one bit via the I2C bus.
+- *
+- * Note: Clock must be set to LOW before calling this function.
+- *
+- * Returns The received bit.
+- */
+-int SkI2cRcvBit(
+-SK_IOC IoC) /* I/O Context */
+-{
+- int Bit;
+- SK_U8 I2cSwCtrl;
+-
+- /* Init data as input line */
+- I2C_DATA_IN(IoC);
+-
+- SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT));
+-
+- I2C_CLK_HIGH(IoC);
+-
+- SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH));
+-
+- SK_I2C_GET_SW(IoC, &I2cSwCtrl);
+-
+- Bit = (I2cSwCtrl & I2C_DATA) ? 1 : 0;
+-
+- I2C_CLK_LOW(IoC);
+- SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW-T_CLK_2_DATA_OUT));
+-
+- return(Bit);
+-} /* SkI2cRcvBit */
+-
+-
+-/*
+- * Receive an ACK.
+- *
+- * returns 0 If acknowledged
+- * 1 in case of an error
+- */
+-int SkI2cRcvAck(
+-SK_IOC IoC) /* I/O Context */
+-{
+- /*
+- * Received bit must be zero.
+- */
+- return(SkI2cRcvBit(IoC) != 0);
+-} /* SkI2cRcvAck */
+-
+-
+-/*
+- * Send an NACK.
+- */
+-void SkI2cSndNAck(
+-SK_IOC IoC) /* I/O Context */
+-{
+- /*
+- * Received bit must be zero.
+- */
+- SkI2cSndBit(IoC, 1);
+-} /* SkI2cSndNAck */
+-
+-
+-/*
+- * Send an ACK.
+- */
+-void SkI2cSndAck(
+-SK_IOC IoC) /* I/O Context */
+-{
+- /*
+- * Received bit must be zero.
+- */
+- SkI2cSndBit(IoC, 0);
+-} /* SkI2cSndAck */
+-
+-
+-/*
+- * Send one byte to the I2C device and wait for ACK.
+- *
+- * Return acknowleged status.
+- */
+-int SkI2cSndByte(
+-SK_IOC IoC, /* I/O Context */
+-int Byte) /* byte to send */
+-{
+- int i;
+-
+- for (i = 0; i < 8; i++) {
+- if (Byte & (1<<(7-i))) {
+- SkI2cSndBit(IoC, 1);
+- }
+- else {
+- SkI2cSndBit(IoC, 0);
+- }
+- }
+-
+- return(SkI2cRcvAck(IoC));
+-} /* SkI2cSndByte */
+-
+-
+-/*
+- * Receive one byte and ack it.
+- *
+- * Return byte.
+- */
+-int SkI2cRcvByte(
+-SK_IOC IoC, /* I/O Context */
+-int Last) /* Last Byte Flag */
+-{
+- int i;
+- int Byte = 0;
+-
+- for (i = 0; i < 8; i++) {
+- Byte <<= 1;
+- Byte |= SkI2cRcvBit(IoC);
+- }
+-
+- if (Last) {
+- SkI2cSndNAck(IoC);
+- }
+- else {
+- SkI2cSndAck(IoC);
+- }
+-
+- return(Byte);
+-} /* SkI2cRcvByte */
+-
+-
+-/*
+- * Start dialog and send device address
+- *
+- * Return 0 if acknowleged, 1 in case of an error
+- */
+-int SkI2cSndDev(
+-SK_IOC IoC, /* I/O Context */
+-int Addr, /* Device Address */
+-int Rw) /* Read / Write Flag */
+-{
+- SkI2cStart(IoC);
+- Rw = ~Rw;
+- Rw &= I2C_WRITE;
+- return(SkI2cSndByte(IoC, (Addr<<1) | Rw));
+-} /* SkI2cSndDev */
+-
+-#endif /* SK_DIAG */
+-
+-/*----------------- I2C CTRL Register Functions ----------*/
+-
+-/*
+- * waits for a completion of an I2C transfer
+- *
+- * returns 0: success, transfer completes
+- * 1: error, transfer does not complete, I2C transfer
+- * killed, wait loop terminated.
+- */
+-static int SkI2cWait(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-int Event) /* complete event to wait for (I2C_READ or I2C_WRITE) */
+-{
+- SK_U64 StartTime;
+- SK_U64 CurrentTime;
+- SK_U32 I2cCtrl;
+-
+- StartTime = SkOsGetTime(pAC);
+-
+- do {
+- CurrentTime = SkOsGetTime(pAC);
+-
+- if (CurrentTime - StartTime > SK_TICKS_PER_SEC / 8) {
+-
+- SK_I2C_STOP(IoC);
+-#ifndef SK_DIAG
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E002, SKERR_I2C_E002MSG);
+-#endif /* !SK_DIAG */
+- return(1);
+- }
+-
+- SK_I2C_GET_CTL(IoC, &I2cCtrl);
+-
+-#ifdef xYUKON_DBG
+- printf("StartTime=%lu, CurrentTime=%lu\n",
+- StartTime, CurrentTime);
+- if (kbhit()) {
+- return(1);
+- }
+-#endif /* YUKON_DBG */
+-
+- } while ((I2cCtrl & I2C_FLAG) == (SK_U32)Event << 31);
+-
+- return(0);
+-} /* SkI2cWait */
+-
+-
+-/*
+- * waits for a completion of an I2C transfer
+- *
+- * Returns
+- * Nothing
+- */
+-void SkI2cWaitIrq(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC) /* I/O Context */
+-{
+- SK_SENSOR *pSen;
+- SK_U64 StartTime;
+- SK_U32 IrqSrc;
+-
+- pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
+-
+- if (pSen->SenState == SK_SEN_IDLE) {
+- return;
+- }
+-
+- StartTime = SkOsGetTime(pAC);
+-
+- do {
+- if (SkOsGetTime(pAC) - StartTime > SK_TICKS_PER_SEC / 8) {
+-
+- SK_I2C_STOP(IoC);
+-#ifndef SK_DIAG
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E016, SKERR_I2C_E016MSG);
+-#endif /* !SK_DIAG */
+- return;
+- }
+-
+- SK_IN32(IoC, B0_ISRC, &IrqSrc);
+-
+- } while ((IrqSrc & IS_I2C_READY) == 0);
+-
+- pSen->SenState = SK_SEN_IDLE;
+- return;
+-} /* SkI2cWaitIrq */
+-
+-/*
+- * writes a single byte or 4 bytes into the I2C device
+- *
+- * returns 0: success
+- * 1: error
+- */
+-static int SkI2cWrite(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_U32 I2cData, /* I2C Data to write */
+-int I2cDev, /* I2C Device Address */
+-int I2cDevSize, /* I2C Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */
+-int I2cReg, /* I2C Device Register Address */
+-int I2cBurst) /* I2C Burst Flag */
+-{
+- SK_OUT32(IoC, B2_I2C_DATA, I2cData);
+-
+- SK_I2C_CTL(IoC, I2C_WRITE, I2cDev, I2cDevSize, I2cReg, I2cBurst);
+-
+- return(SkI2cWait(pAC, IoC, I2C_WRITE));
+-} /* SkI2cWrite*/
+-
+-
+-#ifdef SK_DIAG
+-/*
+- * reads a single byte or 4 bytes from the I2C device
+- *
+- * returns the word read
+- */
+-SK_U32 SkI2cRead(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-int I2cDev, /* I2C Device Address */
+-int I2cDevSize, /* I2C Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */
+-int I2cReg, /* I2C Device Register Address */
+-int I2cBurst) /* I2C Burst Flag */
+-{
+- SK_U32 Data;
+-
+- SK_OUT32(IoC, B2_I2C_DATA, 0);
+- SK_I2C_CTL(IoC, I2C_READ, I2cDev, I2cDevSize, I2cReg, I2cBurst);
+-
+- if (SkI2cWait(pAC, IoC, I2C_READ) != 0) {
+- w_print("%s\n", SKERR_I2C_E002MSG);
+- }
+-
+- SK_IN32(IoC, B2_I2C_DATA, &Data);
+-
+- return(Data);
+-} /* SkI2cRead */
+-#endif /* SK_DIAG */
+-
+-
+-/*
+- * read a sensor's value
+- *
+- * This function reads a sensor's value from the I2C sensor chip. The sensor
+- * is defined by its index into the sensors database in the struct pAC points
+- * to.
+- * Returns
+- * 1 if the read is completed
+- * 0 if the read must be continued (I2C Bus still allocated)
+- */
+-static int SkI2cReadSensor(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_SENSOR *pSen) /* Sensor to be read */
+-{
+- if (pSen->SenRead != NULL) {
+- return((*pSen->SenRead)(pAC, IoC, pSen));
+- }
+- else {
+- return(0); /* no success */
+- }
+-} /* SkI2cReadSensor */
+-
+-/*
+- * Do the Init state 0 initialization
+- */
+-static int SkI2cInit0(
+-SK_AC *pAC) /* Adapter Context */
+-{
+- int i;
+-
+- /* Begin with first sensor */
+- pAC->I2c.CurrSens = 0;
+-
+- /* Begin with timeout control for state machine */
+- pAC->I2c.TimerMode = SK_TIMER_WATCH_SM;
+-
+- /* Set sensor number to zero */
+- pAC->I2c.MaxSens = 0;
+-
+-#ifndef SK_DIAG
+- /* Initialize Number of Dummy Reads */
+- pAC->I2c.DummyReads = SK_MAX_SENSORS;
+-#endif
+-
+- for (i = 0; i < SK_MAX_SENSORS; i++) {
+- pAC->I2c.SenTable[i].SenDesc = "unknown";
+- pAC->I2c.SenTable[i].SenType = SK_SEN_UNKNOWN;
+- pAC->I2c.SenTable[i].SenThreErrHigh = 0;
+- pAC->I2c.SenTable[i].SenThreErrLow = 0;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = 0;
+- pAC->I2c.SenTable[i].SenThreWarnLow = 0;
+- pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN;
+- pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_NONE;
+- pAC->I2c.SenTable[i].SenValue = 0;
+- pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_NOT_PRESENT;
+- pAC->I2c.SenTable[i].SenErrCts = 0;
+- pAC->I2c.SenTable[i].SenBegErrTS = 0;
+- pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE;
+- pAC->I2c.SenTable[i].SenRead = NULL;
+- pAC->I2c.SenTable[i].SenDev = 0;
+- }
+-
+- /* Now we are "INIT data"ed */
+- pAC->I2c.InitLevel = SK_INIT_DATA;
+- return(0);
+-} /* SkI2cInit0*/
+-
+-
+-/*
+- * Do the init state 1 initialization
+- *
+- * initialize the following register of the LM80:
+- * Configuration register:
+- * - START, noINT, activeLOW, noINT#Clear, noRESET, noCI, noGPO#, noINIT
+- *
+- * Interrupt Mask Register 1:
+- * - all interrupts are Disabled (0xff)
+- *
+- * Interrupt Mask Register 2:
+- * - all interrupts are Disabled (0xff) Interrupt modi doesn't matter.
+- *
+- * Fan Divisor/RST_OUT register:
+- * - Divisors set to 1 (bits 00), all others 0s.
+- *
+- * OS# Configuration/Temperature resolution Register:
+- * - all 0s
+- *
+- */
+-static int SkI2cInit1(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC) /* I/O Context */
+-{
+- int i;
+- SK_U8 I2cSwCtrl;
+- SK_GEPORT *pPrt; /* GIni Port struct pointer */
+-
+- if (pAC->I2c.InitLevel != SK_INIT_DATA) {
+- /* ReInit not needed in I2C module */
+- return(0);
+- }
+-
+- /* Set the Direction of I2C-Data Pin to IN */
+- SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA);
+- /* Check for 32-Bit Yukon with Low at I2C-Data Pin */
+- SK_I2C_GET_SW(IoC, &I2cSwCtrl);
+-
+- if ((I2cSwCtrl & I2C_DATA) == 0) {
+- /* this is a 32-Bit board */
+- pAC->GIni.GIYukon32Bit = SK_TRUE;
+- return(0);
+- }
+-
+- /* Check for 64 Bit Yukon without sensors */
+- if (SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_CFG, 0) != 0) {
+- return(0);
+- }
+-
+- (void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_1, 0);
+-
+- (void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_2, 0);
+-
+- (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_FAN_CTRL, 0);
+-
+- (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_TEMP_CTRL, 0);
+-
+- (void)SkI2cWrite(pAC, IoC, (SK_U32)LM80_CFG_START, LM80_ADDR, I2C_025K_DEV,
+- LM80_CFG, 0);
+-
+- /*
+- * MaxSens has to be updated here, because PhyType is not
+- * set when performing Init Level 0
+- */
+- pAC->I2c.MaxSens = 5;
+-
+- pPrt = &pAC->GIni.GP[0];
+-
+- if (pAC->GIni.GIGenesis) {
+- if (pPrt->PhyType == SK_PHY_BCOM) {
+- if (pAC->GIni.GIMacsFound == 1) {
+- pAC->I2c.MaxSens += 1;
+- }
+- else {
+- pAC->I2c.MaxSens += 3;
+- }
+- }
+- }
+- else {
+- pAC->I2c.MaxSens += 3;
+- }
+-
+- for (i = 0; i < pAC->I2c.MaxSens; i++) {
+- switch (i) {
+- case 0:
+- pAC->I2c.SenTable[i].SenDesc = "Temperature";
+- pAC->I2c.SenTable[i].SenType = SK_SEN_TEMP;
+- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_TEMP_HIGH_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_TEMP_HIGH_WARN;
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_TEMP_LOW_WARN;
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_TEMP_LOW_ERR;
+- pAC->I2c.SenTable[i].SenReg = LM80_TEMP_IN;
+- break;
+- case 1:
+- pAC->I2c.SenTable[i].SenDesc = "Voltage PCI";
+- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
+- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_5V_HIGH_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_5V_HIGH_WARN;
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_5V_LOW_WARN;
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_5V_LOW_ERR;
+- pAC->I2c.SenTable[i].SenReg = LM80_VT0_IN;
+- break;
+- case 2:
+- pAC->I2c.SenTable[i].SenDesc = "Voltage PCI-IO";
+- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
+- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_IO_5V_HIGH_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_IO_5V_HIGH_WARN;
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_IO_3V3_LOW_WARN;
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_IO_3V3_LOW_ERR;
+- pAC->I2c.SenTable[i].SenReg = LM80_VT1_IN;
+- pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_PCI_IO;
+- break;
+- case 3:
+- pAC->I2c.SenTable[i].SenDesc = "Voltage ASIC";
+- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
+- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VDD_HIGH_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VDD_HIGH_WARN;
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VDD_LOW_WARN;
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VDD_LOW_ERR;
+- pAC->I2c.SenTable[i].SenReg = LM80_VT2_IN;
+- break;
+- case 4:
+- if (pAC->GIni.GIGenesis) {
+- if (pPrt->PhyType == SK_PHY_BCOM) {
+- pAC->I2c.SenTable[i].SenDesc = "Voltage PHY A PLL";
+- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
+- }
+- else {
+- pAC->I2c.SenTable[i].SenDesc = "Voltage PMA";
+- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
+- }
+- }
+- else {
+- pAC->I2c.SenTable[i].SenDesc = "Voltage VAUX";
+- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VAUX_3V3_HIGH_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VAUX_3V3_HIGH_WARN;
+- if (pAC->GIni.GIVauxAvail) {
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN;
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR;
+- }
+- else {
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_0V_WARN_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_0V_WARN_ERR;
+- }
+- }
+- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
+- pAC->I2c.SenTable[i].SenReg = LM80_VT3_IN;
+- break;
+- case 5:
+- if (pAC->GIni.GIGenesis) {
+- pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5";
+- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN;
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN;
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR;
+- }
+- else {
+- pAC->I2c.SenTable[i].SenDesc = "Voltage Core 1V5";
+- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_CORE_1V5_HIGH_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_CORE_1V5_HIGH_WARN;
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_CORE_1V5_LOW_WARN;
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_CORE_1V5_LOW_ERR;
+- }
+- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
+- pAC->I2c.SenTable[i].SenReg = LM80_VT4_IN;
+- break;
+- case 6:
+- if (pAC->GIni.GIGenesis) {
+- pAC->I2c.SenTable[i].SenDesc = "Voltage PHY B PLL";
+- }
+- else {
+- pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 3V3";
+- }
+- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
+- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
+- pAC->I2c.SenTable[i].SenReg = LM80_VT5_IN;
+- break;
+- case 7:
+- if (pAC->GIni.GIGenesis) {
+- pAC->I2c.SenTable[i].SenDesc = "Speed Fan";
+- pAC->I2c.SenTable[i].SenType = SK_SEN_FAN;
+- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_FAN_HIGH_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_FAN_HIGH_WARN;
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_FAN_LOW_WARN;
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_FAN_LOW_ERR;
+- pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN;
+- }
+- else {
+- pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5";
+- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
+- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN;
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN;
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR;
+- pAC->I2c.SenTable[i].SenReg = LM80_VT6_IN;
+- }
+- break;
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_INIT | SK_ERRCL_SW,
+- SKERR_I2C_E001, SKERR_I2C_E001MSG);
+- break;
+- }
+-
+- pAC->I2c.SenTable[i].SenValue = 0;
+- pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK;
+- pAC->I2c.SenTable[i].SenErrCts = 0;
+- pAC->I2c.SenTable[i].SenBegErrTS = 0;
+- pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE;
+- pAC->I2c.SenTable[i].SenRead = SkLm80ReadSensor;
+- pAC->I2c.SenTable[i].SenDev = LM80_ADDR;
+- }
+-
+-#ifndef SK_DIAG
+- pAC->I2c.DummyReads = pAC->I2c.MaxSens;
+-#endif /* !SK_DIAG */
+-
+- /* Clear I2C IRQ */
+- SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
+-
+- /* Now we are I/O initialized */
+- pAC->I2c.InitLevel = SK_INIT_IO;
+- return(0);
+-} /* SkI2cInit1 */
+-
+-
+-/*
+- * Init level 2: Start first sensor read.
+- */
+-static int SkI2cInit2(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC) /* I/O Context */
+-{
+- int ReadComplete;
+- SK_SENSOR *pSen;
+-
+- if (pAC->I2c.InitLevel != SK_INIT_IO) {
+- /* ReInit not needed in I2C module */
+- /* Init0 and Init2 not permitted */
+- return(0);
+- }
+-
+- pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
+- ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
+-
+- if (ReadComplete) {
+- SK_ERR_LOG(pAC, SK_ERRCL_INIT, SKERR_I2C_E008, SKERR_I2C_E008MSG);
+- }
+-
+- /* Now we are correctly initialized */
+- pAC->I2c.InitLevel = SK_INIT_RUN;
+-
+- return(0);
+-} /* SkI2cInit2*/
+-
+-
+-/*
+- * Initialize I2C devices
+- *
+- * Get the first voltage value and discard it.
+- * Go into temperature read mode. A default pointer is not set.
+- *
+- * The things to be done depend on the init level in the parameter list:
+- * Level 0:
+- * Initialize only the data structures. Do NOT access hardware.
+- * Level 1:
+- * Initialize hardware through SK_IN / SK_OUT commands. Do NOT use interrupts.
+- * Level 2:
+- * Everything is possible. Interrupts may be used from now on.
+- *
+- * return:
+- * 0 = success
+- * other = error.
+- */
+-int SkI2cInit(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context needed in levels 1 and 2 */
+-int Level) /* Init Level */
+-{
+-
+- switch (Level) {
+- case SK_INIT_DATA:
+- return(SkI2cInit0(pAC));
+- case SK_INIT_IO:
+- return(SkI2cInit1(pAC, IoC));
+- case SK_INIT_RUN:
+- return(SkI2cInit2(pAC, IoC));
+- default:
+- break;
+- }
+-
+- return(0);
+-} /* SkI2cInit */
+-
+-
+-#ifndef SK_DIAG
+-
+-/*
+- * Interrupt service function for the I2C Interface
+- *
+- * Clears the Interrupt source
+- *
+- * Reads the register and check it for sending a trap.
+- *
+- * Starts the timer if necessary.
+- */
+-void SkI2cIsr(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC) /* I/O Context */
+-{
+- SK_EVPARA Para;
+-
+- /* Clear I2C IRQ */
+- SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
+-
+- Para.Para64 = 0;
+- SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_IRQ, Para);
+-} /* SkI2cIsr */
+-
+-
+-/*
+- * Check this sensors Value against the threshold and send events.
+- */
+-static void SkI2cCheckSensor(
+-SK_AC *pAC, /* Adapter Context */
+-SK_SENSOR *pSen)
+-{
+- SK_EVPARA ParaLocal;
+- SK_BOOL TooHigh; /* Is sensor too high? */
+- SK_BOOL TooLow; /* Is sensor too low? */
+- SK_U64 CurrTime; /* Current Time */
+- SK_BOOL DoTrapSend; /* We need to send a trap */
+- SK_BOOL DoErrLog; /* We need to log the error */
+- SK_BOOL IsError; /* We need to log the error */
+-
+- /* Check Dummy Reads first */
+- if (pAC->I2c.DummyReads > 0) {
+- pAC->I2c.DummyReads--;
+- return;
+- }
+-
+- /* Get the current time */
+- CurrTime = SkOsGetTime(pAC);
+-
+- /* Set para to the most useful setting: The current sensor. */
+- ParaLocal.Para64 = (SK_U64)pAC->I2c.CurrSens;
+-
+- /* Check the Value against the thresholds. First: Error Thresholds */
+- TooHigh = (pSen->SenValue > pSen->SenThreErrHigh);
+- TooLow = (pSen->SenValue < pSen->SenThreErrLow);
+-
+- IsError = SK_FALSE;
+- if (TooHigh || TooLow) {
+- /* Error condition is satisfied */
+- DoTrapSend = SK_TRUE;
+- DoErrLog = SK_TRUE;
+-
+- /* Now error condition is satisfied */
+- IsError = SK_TRUE;
+-
+- if (pSen->SenErrFlag == SK_SEN_ERR_ERR) {
+- /* This state is the former one */
+-
+- /* So check first whether we have to send a trap */
+- if (pSen->SenLastErrTrapTS + SK_SEN_ERR_TR_HOLD >
+- CurrTime) {
+- /*
+- * Do NOT send the Trap. The hold back time
+- * has to run out first.
+- */
+- DoTrapSend = SK_FALSE;
+- }
+-
+- /* Check now whether we have to log an Error */
+- if (pSen->SenLastErrLogTS + SK_SEN_ERR_LOG_HOLD >
+- CurrTime) {
+- /*
+- * Do NOT log the error. The hold back time
+- * has to run out first.
+- */
+- DoErrLog = SK_FALSE;
+- }
+- }
+- else {
+- /* We came from a different state -> Set Begin Time Stamp */
+- pSen->SenBegErrTS = CurrTime;
+- pSen->SenErrFlag = SK_SEN_ERR_ERR;
+- }
+-
+- if (DoTrapSend) {
+- /* Set current Time */
+- pSen->SenLastErrTrapTS = CurrTime;
+- pSen->SenErrCts++;
+-
+- /* Queue PNMI Event */
+- SkEventQueue(pAC, SKGE_PNMI, (TooHigh ?
+- SK_PNMI_EVT_SEN_ERR_UPP :
+- SK_PNMI_EVT_SEN_ERR_LOW),
+- ParaLocal);
+- }
+-
+- if (DoErrLog) {
+- /* Set current Time */
+- pSen->SenLastErrLogTS = CurrTime;
+-
+- if (pSen->SenType == SK_SEN_TEMP) {
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E011, SKERR_I2C_E011MSG);
+- }
+- else if (pSen->SenType == SK_SEN_VOLT) {
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E012, SKERR_I2C_E012MSG);
+- }
+- else {
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E015, SKERR_I2C_E015MSG);
+- }
+- }
+- }
+-
+- /* Check the Value against the thresholds */
+- /* 2nd: Warning thresholds */
+- TooHigh = (pSen->SenValue > pSen->SenThreWarnHigh);
+- TooLow = (pSen->SenValue < pSen->SenThreWarnLow);
+-
+- if (!IsError && (TooHigh || TooLow)) {
+- /* Error condition is satisfied */
+- DoTrapSend = SK_TRUE;
+- DoErrLog = SK_TRUE;
+-
+- if (pSen->SenErrFlag == SK_SEN_ERR_WARN) {
+- /* This state is the former one */
+-
+- /* So check first whether we have to send a trap */
+- if (pSen->SenLastWarnTrapTS + SK_SEN_WARN_TR_HOLD > CurrTime) {
+- /*
+- * Do NOT send the Trap. The hold back time
+- * has to run out first.
+- */
+- DoTrapSend = SK_FALSE;
+- }
+-
+- /* Check now whether we have to log an Error */
+- if (pSen->SenLastWarnLogTS + SK_SEN_WARN_LOG_HOLD > CurrTime) {
+- /*
+- * Do NOT log the error. The hold back time
+- * has to run out first.
+- */
+- DoErrLog = SK_FALSE;
+- }
+- }
+- else {
+- /* We came from a different state -> Set Begin Time Stamp */
+- pSen->SenBegWarnTS = CurrTime;
+- pSen->SenErrFlag = SK_SEN_ERR_WARN;
+- }
+-
+- if (DoTrapSend) {
+- /* Set current Time */
+- pSen->SenLastWarnTrapTS = CurrTime;
+- pSen->SenWarnCts++;
+-
+- /* Queue PNMI Event */
+- SkEventQueue(pAC, SKGE_PNMI, (TooHigh ?
+- SK_PNMI_EVT_SEN_WAR_UPP :
+- SK_PNMI_EVT_SEN_WAR_LOW),
+- ParaLocal);
+- }
+-
+- if (DoErrLog) {
+- /* Set current Time */
+- pSen->SenLastWarnLogTS = CurrTime;
+-
+- if (pSen->SenType == SK_SEN_TEMP) {
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E009, SKERR_I2C_E009MSG);
+- }
+- else if (pSen->SenType == SK_SEN_VOLT) {
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E010, SKERR_I2C_E010MSG);
+- }
+- else {
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E014, SKERR_I2C_E014MSG);
+- }
+- }
+- }
+-
+- /* Check for NO error at all */
+- if (!IsError && !TooHigh && !TooLow) {
+- /* Set o.k. Status if no error and no warning condition */
+- pSen->SenErrFlag = SK_SEN_ERR_OK;
+- }
+-
+- /* End of check against the thresholds */
+-
+- /* Bug fix AF: 16.Aug.2001: Correct the init base
+- * of LM80 sensor.
+- */
+- if (pSen->SenInit == SK_SEN_DYN_INIT_PCI_IO) {
+-
+- pSen->SenInit = SK_SEN_DYN_INIT_NONE;
+-
+- if (pSen->SenValue > SK_SEN_PCI_IO_RANGE_LIMITER) {
+- /* 5V PCI-IO Voltage */
+- pSen->SenThreWarnLow = SK_SEN_PCI_IO_5V_LOW_WARN;
+- pSen->SenThreErrLow = SK_SEN_PCI_IO_5V_LOW_ERR;
+- }
+- else {
+- /* 3.3V PCI-IO Voltage */
+- pSen->SenThreWarnHigh = SK_SEN_PCI_IO_3V3_HIGH_WARN;
+- pSen->SenThreErrHigh = SK_SEN_PCI_IO_3V3_HIGH_ERR;
+- }
+- }
+-
+-#ifdef TEST_ONLY
+- /* Dynamic thresholds also for VAUX of LM80 sensor */
+- if (pSen->SenInit == SK_SEN_DYN_INIT_VAUX) {
+-
+- pSen->SenInit = SK_SEN_DYN_INIT_NONE;
+-
+- /* 3.3V VAUX Voltage */
+- if (pSen->SenValue > SK_SEN_VAUX_RANGE_LIMITER) {
+- pSen->SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN;
+- pSen->SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR;
+- }
+- /* 0V VAUX Voltage */
+- else {
+- pSen->SenThreWarnHigh = SK_SEN_VAUX_0V_WARN_ERR;
+- pSen->SenThreErrHigh = SK_SEN_VAUX_0V_WARN_ERR;
+- }
+- }
+-
+- /*
+- * Check initialization state:
+- * The VIO Thresholds need adaption
+- */
+- if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN &&
+- pSen->SenValue > SK_SEN_WARNLOW2C &&
+- pSen->SenValue < SK_SEN_WARNHIGH2) {
+- pSen->SenThreErrLow = SK_SEN_ERRLOW2C;
+- pSen->SenThreWarnLow = SK_SEN_WARNLOW2C;
+- pSen->SenInit = SK_TRUE;
+- }
+-
+- if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN &&
+- pSen->SenValue > SK_SEN_WARNLOW2 &&
+- pSen->SenValue < SK_SEN_WARNHIGH2C) {
+- pSen->SenThreErrHigh = SK_SEN_ERRHIGH2C;
+- pSen->SenThreWarnHigh = SK_SEN_WARNHIGH2C;
+- pSen->SenInit = SK_TRUE;
+- }
+-#endif
+-
+- if (pSen->SenInit != SK_SEN_DYN_INIT_NONE) {
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E013, SKERR_I2C_E013MSG);
+- }
+-} /* SkI2cCheckSensor */
+-
+-
+-/*
+- * The only Event to be served is the timeout event
+- *
+- */
+-int SkI2cEvent(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_U32 Event, /* Module specific Event */
+-SK_EVPARA Para) /* Event specific Parameter */
+-{
+- int ReadComplete;
+- SK_SENSOR *pSen;
+- SK_U32 Time;
+- SK_EVPARA ParaLocal;
+- int i;
+-
+- /* New case: no sensors */
+- if (pAC->I2c.MaxSens == 0) {
+- return(0);
+- }
+-
+- switch (Event) {
+- case SK_I2CEV_IRQ:
+- pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
+- ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
+-
+- if (ReadComplete) {
+- /* Check sensor against defined thresholds */
+- SkI2cCheckSensor(pAC, pSen);
+-
+- /* Increment Current sensor and set appropriate Timeout */
+- pAC->I2c.CurrSens++;
+- if (pAC->I2c.CurrSens >= pAC->I2c.MaxSens) {
+- pAC->I2c.CurrSens = 0;
+- Time = SK_I2C_TIM_LONG;
+- }
+- else {
+- Time = SK_I2C_TIM_SHORT;
+- }
+-
+- /* Start Timer */
+- ParaLocal.Para64 = (SK_U64)0;
+-
+- pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
+-
+- SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
+- SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
+- }
+- else {
+- /* Start Timer */
+- ParaLocal.Para64 = (SK_U64)0;
+-
+- pAC->I2c.TimerMode = SK_TIMER_WATCH_SM;
+-
+- SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, SK_I2C_TIM_WATCH,
+- SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
+- }
+- break;
+- case SK_I2CEV_TIM:
+- if (pAC->I2c.TimerMode == SK_TIMER_NEW_GAUGING) {
+-
+- ParaLocal.Para64 = (SK_U64)0;
+- SkTimerStop(pAC, IoC, &pAC->I2c.SenTimer);
+-
+- pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
+- ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
+-
+- if (ReadComplete) {
+- /* Check sensor against defined thresholds */
+- SkI2cCheckSensor(pAC, pSen);
+-
+- /* Increment Current sensor and set appropriate Timeout */
+- pAC->I2c.CurrSens++;
+- if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) {
+- pAC->I2c.CurrSens = 0;
+- Time = SK_I2C_TIM_LONG;
+- }
+- else {
+- Time = SK_I2C_TIM_SHORT;
+- }
+-
+- /* Start Timer */
+- ParaLocal.Para64 = (SK_U64)0;
+-
+- pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
+-
+- SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
+- SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
+- }
+- }
+- else {
+- pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
+- pSen->SenErrFlag = SK_SEN_ERR_FAULTY;
+- SK_I2C_STOP(IoC);
+-
+- /* Increment Current sensor and set appropriate Timeout */
+- pAC->I2c.CurrSens++;
+- if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) {
+- pAC->I2c.CurrSens = 0;
+- Time = SK_I2C_TIM_LONG;
+- }
+- else {
+- Time = SK_I2C_TIM_SHORT;
+- }
+-
+- /* Start Timer */
+- ParaLocal.Para64 = (SK_U64)0;
+-
+- pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
+-
+- SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
+- SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
+- }
+- break;
+- case SK_I2CEV_CLEAR:
+- for (i = 0; i < SK_MAX_SENSORS; i++) {
+- pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK;
+- pAC->I2c.SenTable[i].SenErrCts = 0;
+- pAC->I2c.SenTable[i].SenWarnCts = 0;
+- pAC->I2c.SenTable[i].SenBegErrTS = 0;
+- pAC->I2c.SenTable[i].SenBegWarnTS = 0;
+- pAC->I2c.SenTable[i].SenLastErrTrapTS = (SK_U64)0;
+- pAC->I2c.SenTable[i].SenLastErrLogTS = (SK_U64)0;
+- pAC->I2c.SenTable[i].SenLastWarnTrapTS = (SK_U64)0;
+- pAC->I2c.SenTable[i].SenLastWarnLogTS = (SK_U64)0;
+- }
+- break;
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E006, SKERR_I2C_E006MSG);
+- }
+-
+- return(0);
+-} /* SkI2cEvent*/
+-
+-#endif /* !SK_DIAG */
+diff --git a/drivers/net/sk98lin/sklm80.c b/drivers/net/sk98lin/sklm80.c
+deleted file mode 100644
+index a204f5b..0000000
+--- a/drivers/net/sk98lin/sklm80.c
++++ /dev/null
+@@ -1,141 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: sklm80.c
+- * Project: Gigabit Ethernet Adapters, TWSI-Module
+- * Version: $Revision: 1.22 $
+- * Date: $Date: 2003/10/20 09:08:21 $
+- * Purpose: Functions to access Voltage and Temperature Sensor (LM80)
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- LM80 functions
+-*/
+-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+-static const char SysKonnectFileId[] =
+- "@(#) $Id: sklm80.c,v 1.22 2003/10/20 09:08:21 rschmidt Exp $ (C) Marvell. ";
+-#endif
+-
+-#include "h/skdrv1st.h" /* Driver Specific Definitions */
+-#include "h/lm80.h"
+-#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
+-
+-#define BREAK_OR_WAIT(pAC,IoC,Event) break
+-
+-/*
+- * read a sensors value (LM80 specific)
+- *
+- * This function reads a sensors value from the I2C sensor chip LM80.
+- * The sensor is defined by its index into the sensors database in the struct
+- * pAC points to.
+- *
+- * Returns 1 if the read is completed
+- * 0 if the read must be continued (I2C Bus still allocated)
+- */
+-int SkLm80ReadSensor(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context needed in level 1 and 2 */
+-SK_SENSOR *pSen) /* Sensor to be read */
+-{
+- SK_I32 Value;
+-
+- switch (pSen->SenState) {
+- case SK_SEN_IDLE:
+- /* Send address to ADDR register */
+- SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, pSen->SenReg, 0);
+-
+- pSen->SenState = SK_SEN_VALUE ;
+- BREAK_OR_WAIT(pAC, IoC, I2C_READ);
+-
+- case SK_SEN_VALUE:
+- /* Read value from data register */
+- SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value));
+-
+- Value &= 0xff; /* only least significant byte is valid */
+-
+- /* Do NOT check the Value against the thresholds */
+- /* Checking is done in the calling instance */
+-
+- if (pSen->SenType == SK_SEN_VOLT) {
+- /* Voltage sensor */
+- pSen->SenValue = Value * SK_LM80_VT_LSB;
+- pSen->SenState = SK_SEN_IDLE ;
+- return(1);
+- }
+-
+- if (pSen->SenType == SK_SEN_FAN) {
+- if (Value != 0 && Value != 0xff) {
+- /* Fan speed counter */
+- pSen->SenValue = SK_LM80_FAN_FAKTOR/Value;
+- }
+- else {
+- /* Indicate Fan error */
+- pSen->SenValue = 0;
+- }
+- pSen->SenState = SK_SEN_IDLE ;
+- return(1);
+- }
+-
+- /* First: correct the value: it might be negative */
+- if ((Value & 0x80) != 0) {
+- /* Value is negative */
+- Value = Value - 256;
+- }
+-
+- /* We have a temperature sensor and need to get the signed extension.
+- * For now we get the extension from the last reading, so in the normal
+- * case we won't see flickering temperatures.
+- */
+- pSen->SenValue = (Value * SK_LM80_TEMP_LSB) +
+- (pSen->SenValue % SK_LM80_TEMP_LSB);
+-
+- /* Send address to ADDR register */
+- SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, LM80_TEMP_CTRL, 0);
+-
+- pSen->SenState = SK_SEN_VALEXT ;
+- BREAK_OR_WAIT(pAC, IoC, I2C_READ);
+-
+- case SK_SEN_VALEXT:
+- /* Read value from data register */
+- SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value));
+- Value &= LM80_TEMP_LSB_9; /* only bit 7 is valid */
+-
+- /* cut the LSB bit */
+- pSen->SenValue = ((pSen->SenValue / SK_LM80_TEMP_LSB) *
+- SK_LM80_TEMP_LSB);
+-
+- if (pSen->SenValue < 0) {
+- /* Value negative: The bit value must be subtracted */
+- pSen->SenValue -= ((Value >> 7) * SK_LM80_TEMPEXT_LSB);
+- }
+- else {
+- /* Value positive: The bit value must be added */
+- pSen->SenValue += ((Value >> 7) * SK_LM80_TEMPEXT_LSB);
+- }
+-
+- pSen->SenState = SK_SEN_IDLE ;
+- return(1);
+-
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E007, SKERR_I2C_E007MSG);
+- return(1);
+- }
+-
+- /* Not completed */
+- return(0);
+-}
+-
+diff --git a/drivers/net/sk98lin/skqueue.c b/drivers/net/sk98lin/skqueue.c
+deleted file mode 100644
+index 0275b4f..0000000
+--- a/drivers/net/sk98lin/skqueue.c
++++ /dev/null
+@@ -1,179 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skqueue.c
+- * Project: Gigabit Ethernet Adapters, Event Scheduler Module
+- * Version: $Revision: 1.20 $
+- * Date: $Date: 2003/09/16 13:44:00 $
+- * Purpose: Management of an event queue.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-
+-/*
+- * Event queue and dispatcher
+- */
+-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+-static const char SysKonnectFileId[] =
+- "@(#) $Id: skqueue.c,v 1.20 2003/09/16 13:44:00 rschmidt Exp $ (C) Marvell.";
+-#endif
+-
+-#include "h/skdrv1st.h" /* Driver Specific Definitions */
+-#include "h/skqueue.h" /* Queue Definitions */
+-#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
+-
+-#ifdef __C2MAN__
+-/*
+- Event queue management.
+-
+- General Description:
+-
+- */
+-intro()
+-{}
+-#endif
+-
+-#define PRINTF(a,b,c)
+-
+-/*
+- * init event queue management
+- *
+- * Must be called during init level 0.
+- */
+-void SkEventInit(
+-SK_AC *pAC, /* Adapter context */
+-SK_IOC Ioc, /* IO context */
+-int Level) /* Init level */
+-{
+- switch (Level) {
+- case SK_INIT_DATA:
+- pAC->Event.EvPut = pAC->Event.EvGet = pAC->Event.EvQueue;
+- break;
+- default:
+- break;
+- }
+-}
+-
+-/*
+- * add event to queue
+- */
+-void SkEventQueue(
+-SK_AC *pAC, /* Adapters context */
+-SK_U32 Class, /* Event Class */
+-SK_U32 Event, /* Event to be queued */
+-SK_EVPARA Para) /* Event parameter */
+-{
+- pAC->Event.EvPut->Class = Class;
+- pAC->Event.EvPut->Event = Event;
+- pAC->Event.EvPut->Para = Para;
+-
+- if (++pAC->Event.EvPut == &pAC->Event.EvQueue[SK_MAX_EVENT])
+- pAC->Event.EvPut = pAC->Event.EvQueue;
+-
+- if (pAC->Event.EvPut == pAC->Event.EvGet) {
+- SK_ERR_LOG(pAC, SK_ERRCL_NORES, SKERR_Q_E001, SKERR_Q_E001MSG);
+- }
+-}
+-
+-/*
+- * event dispatcher
+- * while event queue is not empty
+- * get event from queue
+- * send command to state machine
+- * end
+- * return error reported by individual Event function
+- * 0 if no error occured.
+- */
+-int SkEventDispatcher(
+-SK_AC *pAC, /* Adapters Context */
+-SK_IOC Ioc) /* Io context */
+-{
+- SK_EVENTELEM *pEv; /* pointer into queue */
+- SK_U32 Class;
+- int Rtv;
+-
+- pEv = pAC->Event.EvGet;
+-
+- PRINTF("dispatch get %x put %x\n", pEv, pAC->Event.ev_put);
+-
+- while (pEv != pAC->Event.EvPut) {
+- PRINTF("dispatch Class %d Event %d\n", pEv->Class, pEv->Event);
+-
+- switch (Class = pEv->Class) {
+-#ifndef SK_USE_LAC_EV
+-#ifndef SK_SLIM
+- case SKGE_RLMT: /* RLMT Event */
+- Rtv = SkRlmtEvent(pAC, Ioc, pEv->Event, pEv->Para);
+- break;
+- case SKGE_I2C: /* I2C Event */
+- Rtv = SkI2cEvent(pAC, Ioc, pEv->Event, pEv->Para);
+- break;
+- case SKGE_PNMI: /* PNMI Event */
+- Rtv = SkPnmiEvent(pAC, Ioc, pEv->Event, pEv->Para);
+- break;
+-#endif /* not SK_SLIM */
+-#endif /* not SK_USE_LAC_EV */
+- case SKGE_DRV: /* Driver Event */
+- Rtv = SkDrvEvent(pAC, Ioc, pEv->Event, pEv->Para);
+- break;
+-#ifndef SK_USE_SW_TIMER
+- case SKGE_HWAC:
+- Rtv = SkGeSirqEvent(pAC, Ioc, pEv->Event, pEv->Para);
+- break;
+-#else /* !SK_USE_SW_TIMER */
+- case SKGE_SWT :
+- Rtv = SkSwtEvent(pAC, Ioc, pEv->Event, pEv->Para);
+- break;
+-#endif /* !SK_USE_SW_TIMER */
+-#ifdef SK_USE_LAC_EV
+- case SKGE_LACP :
+- Rtv = SkLacpEvent(pAC, Ioc, pEv->Event, pEv->Para);
+- break;
+- case SKGE_RSF :
+- Rtv = SkRsfEvent(pAC, Ioc, pEv->Event, pEv->Para);
+- break;
+- case SKGE_MARKER :
+- Rtv = SkMarkerEvent(pAC, Ioc, pEv->Event, pEv->Para);
+- break;
+- case SKGE_FD :
+- Rtv = SkFdEvent(pAC, Ioc, pEv->Event, pEv->Para);
+- break;
+-#endif /* SK_USE_LAC_EV */
+-#ifdef SK_USE_CSUM
+- case SKGE_CSUM :
+- Rtv = SkCsEvent(pAC, Ioc, pEv->Event, pEv->Para);
+- break;
+-#endif /* SK_USE_CSUM */
+- default :
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_Q_E002, SKERR_Q_E002MSG);
+- Rtv = 0;
+- }
+-
+- if (Rtv != 0) {
+- return(Rtv);
+- }
+-
+- if (++pEv == &pAC->Event.EvQueue[SK_MAX_EVENT])
+- pEv = pAC->Event.EvQueue;
+-
+- /* Renew get: it is used in queue_events to detect overruns */
+- pAC->Event.EvGet = pEv;
+- }
+-
+- return(0);
+-}
+-
+-/* End of file */
+diff --git a/drivers/net/sk98lin/skrlmt.c b/drivers/net/sk98lin/skrlmt.c
+deleted file mode 100644
+index be8d1cc..0000000
+--- a/drivers/net/sk98lin/skrlmt.c
++++ /dev/null
+@@ -1,3257 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skrlmt.c
+- * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.69 $
+- * Date: $Date: 2003/04/15 09:39:22 $
+- * Purpose: Manage links on SK-NET Adapters, esp. redundant ones.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * Description:
+- *
+- * This module contains code for Link ManagemenT (LMT) of SK-NET Adapters.
+- * It is mainly intended for adapters with more than one link.
+- * For such adapters, this module realizes Redundant Link ManagemenT (RLMT).
+- *
+- * Include File Hierarchy:
+- *
+- * "skdrv1st.h"
+- * "skdrv2nd.h"
+- *
+- ******************************************************************************/
+-
+-#ifndef lint
+-static const char SysKonnectFileId[] =
+- "@(#) $Id: skrlmt.c,v 1.69 2003/04/15 09:39:22 tschilli Exp $ (C) Marvell.";
+-#endif /* !defined(lint) */
+-
+-#define __SKRLMT_C
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif /* cplusplus */
+-
+-#include "h/skdrv1st.h"
+-#include "h/skdrv2nd.h"
+-
+-/* defines ********************************************************************/
+-
+-#ifndef SK_HWAC_LINK_LED
+-#define SK_HWAC_LINK_LED(a,b,c,d)
+-#endif /* !defined(SK_HWAC_LINK_LED) */
+-
+-#ifndef DEBUG
+-#define RLMT_STATIC static
+-#else /* DEBUG */
+-#define RLMT_STATIC
+-
+-#ifndef SK_LITTLE_ENDIAN
+-/* First 32 bits */
+-#define OFFS_LO32 1
+-
+-/* Second 32 bits */
+-#define OFFS_HI32 0
+-#else /* SK_LITTLE_ENDIAN */
+-/* First 32 bits */
+-#define OFFS_LO32 0
+-
+-/* Second 32 bits */
+-#define OFFS_HI32 1
+-#endif /* SK_LITTLE_ENDIAN */
+-
+-#endif /* DEBUG */
+-
+-/* ----- Private timeout values ----- */
+-
+-#define SK_RLMT_MIN_TO_VAL 125000 /* 1/8 sec. */
+-#define SK_RLMT_DEF_TO_VAL 1000000 /* 1 sec. */
+-#define SK_RLMT_PORTDOWN_TIM_VAL 900000 /* another 0.9 sec. */
+-#define SK_RLMT_PORTSTART_TIM_VAL 100000 /* 0.1 sec. */
+-#define SK_RLMT_PORTUP_TIM_VAL 2500000 /* 2.5 sec. */
+-#define SK_RLMT_SEG_TO_VAL 900000000 /* 15 min. */
+-
+-/* Assume tick counter increment is 1 - may be set OS-dependent. */
+-#ifndef SK_TICK_INCR
+-#define SK_TICK_INCR SK_CONSTU64(1)
+-#endif /* !defined(SK_TICK_INCR) */
+-
+-/*
+- * Amount that a time stamp must be later to be recognized as "substantially
+- * later". This is about 1/128 sec, but above 1 tick counter increment.
+- */
+-#define SK_RLMT_BC_DELTA (1 + ((SK_TICKS_PER_SEC >> 7) > SK_TICK_INCR ? \
+- (SK_TICKS_PER_SEC >> 7) : SK_TICK_INCR))
+-
+-/* ----- Private RLMT defaults ----- */
+-
+-#define SK_RLMT_DEF_PREF_PORT 0 /* "Lower" port. */
+-#define SK_RLMT_DEF_MODE SK_RLMT_CHECK_LINK /* Default RLMT Mode. */
+-
+-/* ----- Private RLMT checking states ----- */
+-
+-#define SK_RLMT_RCS_SEG 1 /* RLMT Check State: check seg. */
+-#define SK_RLMT_RCS_START_SEG 2 /* RLMT Check State: start check seg. */
+-#define SK_RLMT_RCS_SEND_SEG 4 /* RLMT Check State: send BPDU packet */
+-#define SK_RLMT_RCS_REPORT_SEG 8 /* RLMT Check State: report seg. */
+-
+-/* ----- Private PORT checking states ----- */
+-
+-#define SK_RLMT_PCS_TX 1 /* Port Check State: check tx. */
+-#define SK_RLMT_PCS_RX 2 /* Port Check State: check rx. */
+-
+-/* ----- Private PORT events ----- */
+-
+-/* Note: Update simulation when changing these. */
+-#define SK_RLMT_PORTSTART_TIM 1100 /* Port start timeout. */
+-#define SK_RLMT_PORTUP_TIM 1101 /* Port can now go up. */
+-#define SK_RLMT_PORTDOWN_RX_TIM 1102 /* Port did not receive once ... */
+-#define SK_RLMT_PORTDOWN 1103 /* Port went down. */
+-#define SK_RLMT_PORTDOWN_TX_TIM 1104 /* Partner did not receive ... */
+-
+-/* ----- Private RLMT events ----- */
+-
+-/* Note: Update simulation when changing these. */
+-#define SK_RLMT_TIM 2100 /* RLMT timeout. */
+-#define SK_RLMT_SEG_TIM 2101 /* RLMT segmentation check timeout. */
+-
+-#define TO_SHORTEN(tim) ((tim) / 2)
+-
+-/* Error numbers and messages. */
+-#define SKERR_RLMT_E001 (SK_ERRBASE_RLMT + 0)
+-#define SKERR_RLMT_E001_MSG "No Packet."
+-#define SKERR_RLMT_E002 (SKERR_RLMT_E001 + 1)
+-#define SKERR_RLMT_E002_MSG "Short Packet."
+-#define SKERR_RLMT_E003 (SKERR_RLMT_E002 + 1)
+-#define SKERR_RLMT_E003_MSG "Unknown RLMT event."
+-#define SKERR_RLMT_E004 (SKERR_RLMT_E003 + 1)
+-#define SKERR_RLMT_E004_MSG "PortsUp incorrect."
+-#define SKERR_RLMT_E005 (SKERR_RLMT_E004 + 1)
+-#define SKERR_RLMT_E005_MSG \
+- "Net seems to be segmented (different root bridges are reported on the ports)."
+-#define SKERR_RLMT_E006 (SKERR_RLMT_E005 + 1)
+-#define SKERR_RLMT_E006_MSG "Duplicate MAC Address detected."
+-#define SKERR_RLMT_E007 (SKERR_RLMT_E006 + 1)
+-#define SKERR_RLMT_E007_MSG "LinksUp incorrect."
+-#define SKERR_RLMT_E008 (SKERR_RLMT_E007 + 1)
+-#define SKERR_RLMT_E008_MSG "Port not started but link came up."
+-#define SKERR_RLMT_E009 (SKERR_RLMT_E008 + 1)
+-#define SKERR_RLMT_E009_MSG "Corrected illegal setting of Preferred Port."
+-#define SKERR_RLMT_E010 (SKERR_RLMT_E009 + 1)
+-#define SKERR_RLMT_E010_MSG "Ignored illegal Preferred Port."
+-
+-/* LLC field values. */
+-#define LLC_COMMAND_RESPONSE_BIT 1
+-#define LLC_TEST_COMMAND 0xE3
+-#define LLC_UI 0x03
+-
+-/* RLMT Packet fields. */
+-#define SK_RLMT_DSAP 0
+-#define SK_RLMT_SSAP 0
+-#define SK_RLMT_CTRL (LLC_TEST_COMMAND)
+-#define SK_RLMT_INDICATOR0 0x53 /* S */
+-#define SK_RLMT_INDICATOR1 0x4B /* K */
+-#define SK_RLMT_INDICATOR2 0x2D /* - */
+-#define SK_RLMT_INDICATOR3 0x52 /* R */
+-#define SK_RLMT_INDICATOR4 0x4C /* L */
+-#define SK_RLMT_INDICATOR5 0x4D /* M */
+-#define SK_RLMT_INDICATOR6 0x54 /* T */
+-#define SK_RLMT_PACKET_VERSION 0
+-
+-/* RLMT SPT Flag values. */
+-#define SK_RLMT_SPT_FLAG_CHANGE 0x01
+-#define SK_RLMT_SPT_FLAG_CHANGE_ACK 0x80
+-
+-/* RLMT SPT Packet fields. */
+-#define SK_RLMT_SPT_DSAP 0x42
+-#define SK_RLMT_SPT_SSAP 0x42
+-#define SK_RLMT_SPT_CTRL (LLC_UI)
+-#define SK_RLMT_SPT_PROTOCOL_ID0 0x00
+-#define SK_RLMT_SPT_PROTOCOL_ID1 0x00
+-#define SK_RLMT_SPT_PROTOCOL_VERSION_ID 0x00
+-#define SK_RLMT_SPT_BPDU_TYPE 0x00
+-#define SK_RLMT_SPT_FLAGS 0x00 /* ?? */
+-#define SK_RLMT_SPT_ROOT_ID0 0xFF /* Lowest possible priority. */
+-#define SK_RLMT_SPT_ROOT_ID1 0xFF /* Lowest possible priority. */
+-
+-/* Remaining 6 bytes will be the current port address. */
+-#define SK_RLMT_SPT_ROOT_PATH_COST0 0x00
+-#define SK_RLMT_SPT_ROOT_PATH_COST1 0x00
+-#define SK_RLMT_SPT_ROOT_PATH_COST2 0x00
+-#define SK_RLMT_SPT_ROOT_PATH_COST3 0x00
+-#define SK_RLMT_SPT_BRIDGE_ID0 0xFF /* Lowest possible priority. */
+-#define SK_RLMT_SPT_BRIDGE_ID1 0xFF /* Lowest possible priority. */
+-
+-/* Remaining 6 bytes will be the current port address. */
+-#define SK_RLMT_SPT_PORT_ID0 0xFF /* Lowest possible priority. */
+-#define SK_RLMT_SPT_PORT_ID1 0xFF /* Lowest possible priority. */
+-#define SK_RLMT_SPT_MSG_AGE0 0x00
+-#define SK_RLMT_SPT_MSG_AGE1 0x00
+-#define SK_RLMT_SPT_MAX_AGE0 0x00
+-#define SK_RLMT_SPT_MAX_AGE1 0xFF
+-#define SK_RLMT_SPT_HELLO_TIME0 0x00
+-#define SK_RLMT_SPT_HELLO_TIME1 0xFF
+-#define SK_RLMT_SPT_FWD_DELAY0 0x00
+-#define SK_RLMT_SPT_FWD_DELAY1 0x40
+-
+-/* Size defines. */
+-#define SK_RLMT_MIN_PACKET_SIZE 34
+-#define SK_RLMT_MAX_PACKET_SIZE (SK_RLMT_MAX_TX_BUF_SIZE)
+-#define SK_PACKET_DATA_LEN (SK_RLMT_MAX_PACKET_SIZE - \
+- SK_RLMT_MIN_PACKET_SIZE)
+-
+-/* ----- RLMT packet types ----- */
+-#define SK_PACKET_ANNOUNCE 1 /* Port announcement. */
+-#define SK_PACKET_ALIVE 2 /* Alive packet to port. */
+-#define SK_PACKET_ADDR_CHANGED 3 /* Port address changed. */
+-#define SK_PACKET_CHECK_TX 4 /* Check your tx line. */
+-
+-#ifdef SK_LITTLE_ENDIAN
+-#define SK_U16_TO_NETWORK_ORDER(Val,Addr) { \
+- SK_U8 *_Addr = (SK_U8*)(Addr); \
+- SK_U16 _Val = (SK_U16)(Val); \
+- *_Addr++ = (SK_U8)(_Val >> 8); \
+- *_Addr = (SK_U8)(_Val & 0xFF); \
+-}
+-#endif /* SK_LITTLE_ENDIAN */
+-
+-#ifdef SK_BIG_ENDIAN
+-#define SK_U16_TO_NETWORK_ORDER(Val,Addr) (*(SK_U16*)(Addr) = (SK_U16)(Val))
+-#endif /* SK_BIG_ENDIAN */
+-
+-#define AUTONEG_FAILED SK_FALSE
+-#define AUTONEG_SUCCESS SK_TRUE
+-
+-
+-/* typedefs *******************************************************************/
+-
+-/* RLMT packet. Length: SK_RLMT_MAX_PACKET_SIZE (60) bytes. */
+-typedef struct s_RlmtPacket {
+- SK_U8 DstAddr[SK_MAC_ADDR_LEN];
+- SK_U8 SrcAddr[SK_MAC_ADDR_LEN];
+- SK_U8 TypeLen[2];
+- SK_U8 DSap;
+- SK_U8 SSap;
+- SK_U8 Ctrl;
+- SK_U8 Indicator[7];
+- SK_U8 RlmtPacketType[2];
+- SK_U8 Align1[2];
+- SK_U8 Random[4]; /* Random value of requesting(!) station. */
+- SK_U8 RlmtPacketVersion[2]; /* RLMT Packet version. */
+- SK_U8 Data[SK_PACKET_DATA_LEN];
+-} SK_RLMT_PACKET;
+-
+-typedef struct s_SpTreeRlmtPacket {
+- SK_U8 DstAddr[SK_MAC_ADDR_LEN];
+- SK_U8 SrcAddr[SK_MAC_ADDR_LEN];
+- SK_U8 TypeLen[2];
+- SK_U8 DSap;
+- SK_U8 SSap;
+- SK_U8 Ctrl;
+- SK_U8 ProtocolId[2];
+- SK_U8 ProtocolVersionId;
+- SK_U8 BpduType;
+- SK_U8 Flags;
+- SK_U8 RootId[8];
+- SK_U8 RootPathCost[4];
+- SK_U8 BridgeId[8];
+- SK_U8 PortId[2];
+- SK_U8 MessageAge[2];
+- SK_U8 MaxAge[2];
+- SK_U8 HelloTime[2];
+- SK_U8 ForwardDelay[2];
+-} SK_SPTREE_PACKET;
+-
+-/* global variables ***********************************************************/
+-
+-SK_MAC_ADDR SkRlmtMcAddr = {{0x01, 0x00, 0x5A, 0x52, 0x4C, 0x4D}};
+-SK_MAC_ADDR BridgeMcAddr = {{0x01, 0x80, 0xC2, 0x00, 0x00, 0x00}};
+-
+-/* local variables ************************************************************/
+-
+-/* None. */
+-
+-/* functions ******************************************************************/
+-
+-RLMT_STATIC void SkRlmtCheckSwitch(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- SK_U32 NetIdx);
+-RLMT_STATIC void SkRlmtCheckSeg(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- SK_U32 NetIdx);
+-RLMT_STATIC void SkRlmtEvtSetNets(
+- SK_AC *pAC,
+- SK_IOC IoC,
+- SK_EVPARA Para);
+-
+-/******************************************************************************
+- *
+- * SkRlmtInit - initialize data, set state to init
+- *
+- * Description:
+- *
+- * SK_INIT_DATA
+- * ============
+- *
+- * This routine initializes all RLMT-related variables to a known state.
+- * The initial state is SK_RLMT_RS_INIT.
+- * All ports are initialized to SK_RLMT_PS_INIT.
+- *
+- *
+- * SK_INIT_IO
+- * ==========
+- *
+- * Nothing.
+- *
+- *
+- * SK_INIT_RUN
+- * ===========
+- *
+- * Determine the adapter's random value.
+- * Set the hw registers, the "logical MAC address", the
+- * RLMT multicast address, and eventually the BPDU multicast address.
+- *
+- * Context:
+- * init, pageable
+- *
+- * Returns:
+- * Nothing.
+- */
+-void SkRlmtInit(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-int Level) /* Initialization Level */
+-{
+- SK_U32 i, j;
+- SK_U64 Random;
+- SK_EVPARA Para;
+- SK_MAC_ADDR VirtualMacAddress;
+- SK_MAC_ADDR PhysicalAMacAddress;
+- SK_BOOL VirtualMacAddressSet;
+- SK_BOOL PhysicalAMacAddressSet;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT,
+- ("RLMT Init level %d.\n", Level))
+-
+- switch (Level) {
+- case SK_INIT_DATA: /* Initialize data structures. */
+- SK_MEMSET((char *)&pAC->Rlmt, 0, sizeof(SK_RLMT));
+-
+- for (i = 0; i < SK_MAX_MACS; i++) {
+- pAC->Rlmt.Port[i].PortState = SK_RLMT_PS_INIT;
+- pAC->Rlmt.Port[i].LinkDown = SK_TRUE;
+- pAC->Rlmt.Port[i].PortDown = SK_TRUE;
+- pAC->Rlmt.Port[i].PortStarted = SK_FALSE;
+- pAC->Rlmt.Port[i].PortNoRx = SK_FALSE;
+- pAC->Rlmt.Port[i].RootIdSet = SK_FALSE;
+- pAC->Rlmt.Port[i].PortNumber = i;
+- pAC->Rlmt.Port[i].Net = &pAC->Rlmt.Net[0];
+- pAC->Rlmt.Port[i].AddrPort = &pAC->Addr.Port[i];
+- }
+-
+- pAC->Rlmt.NumNets = 1;
+- for (i = 0; i < SK_MAX_NETS; i++) {
+- pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT;
+- pAC->Rlmt.Net[i].RootIdSet = SK_FALSE;
+- pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT;
+- pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* Automatic. */
+- /* Just assuming. */
+- pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort;
+- pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE;
+- pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL;
+- pAC->Rlmt.Net[i].NetNumber = i;
+- }
+-
+- pAC->Rlmt.Net[0].Port[0] = &pAC->Rlmt.Port[0];
+- pAC->Rlmt.Net[0].Port[1] = &pAC->Rlmt.Port[1];
+-#if SK_MAX_NETS > 1
+- pAC->Rlmt.Net[1].Port[0] = &pAC->Rlmt.Port[1];
+-#endif /* SK_MAX_NETS > 1 */
+- break;
+-
+- case SK_INIT_IO: /* GIMacsFound first available here. */
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT,
+- ("RLMT: %d MACs were detected.\n", pAC->GIni.GIMacsFound))
+-
+- pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound;
+-
+- /* Initialize HW registers? */
+- if (pAC->GIni.GIMacsFound == 1) {
+- Para.Para32[0] = SK_RLMT_MODE_CLS;
+- Para.Para32[1] = 0;
+- (void)SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE, Para);
+- }
+- break;
+-
+- case SK_INIT_RUN:
+- /* Ensure RLMT is set to one net. */
+- if (pAC->Rlmt.NumNets > 1) {
+- Para.Para32[0] = 1;
+- Para.Para32[1] = -1;
+- SkRlmtEvtSetNets(pAC, IoC, Para);
+- }
+-
+- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+- Random = SkOsGetTime(pAC);
+- *(SK_U32*)&pAC->Rlmt.Port[i].Random = *(SK_U32*)&Random;
+-
+- for (j = 0; j < 4; j++) {
+- pAC->Rlmt.Port[i].Random[j] ^= pAC->Rlmt.Port[i].AddrPort->
+- CurrentMacAddress.a[SK_MAC_ADDR_LEN - 1 - j];
+- }
+-
+- (void)SkAddrMcClear(pAC, IoC, i, SK_ADDR_PERMANENT | SK_MC_SW_ONLY);
+-
+- /* Add RLMT MC address. */
+- (void)SkAddrMcAdd(pAC, IoC, i, &SkRlmtMcAddr, SK_ADDR_PERMANENT);
+-
+- if (pAC->Rlmt.Net[0].RlmtMode & SK_RLMT_CHECK_SEG) {
+- /* Add BPDU MC address. */
+- (void)SkAddrMcAdd(pAC, IoC, i, &BridgeMcAddr, SK_ADDR_PERMANENT);
+- }
+-
+- (void)SkAddrMcUpdate(pAC, IoC, i);
+- }
+-
+- VirtualMacAddressSet = SK_FALSE;
+- /* Read virtual MAC address from Control Register File. */
+- for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
+-
+- SK_IN8(IoC, B2_MAC_1 + j, &VirtualMacAddress.a[j]);
+- VirtualMacAddressSet |= VirtualMacAddress.a[j];
+- }
+-
+- PhysicalAMacAddressSet = SK_FALSE;
+- /* Read physical MAC address for MAC A from Control Register File. */
+- for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
+-
+- SK_IN8(IoC, B2_MAC_2 + j, &PhysicalAMacAddress.a[j]);
+- PhysicalAMacAddressSet |= PhysicalAMacAddress.a[j];
+- }
+-
+- /* check if the two mac addresses contain reasonable values */
+- if (!VirtualMacAddressSet || !PhysicalAMacAddressSet) {
+-
+- pAC->Rlmt.RlmtOff = SK_TRUE;
+- }
+-
+- /* if the two mac addresses are equal switch off the RLMT_PRE_LOOKAHEAD
+- and the RLMT_LOOKAHEAD macros */
+- else if (SK_ADDR_EQUAL(PhysicalAMacAddress.a, VirtualMacAddress.a)) {
+-
+- pAC->Rlmt.RlmtOff = SK_TRUE;
+- }
+- else {
+- pAC->Rlmt.RlmtOff = SK_FALSE;
+- }
+- break;
+-
+- default: /* error */
+- break;
+- }
+- return;
+-} /* SkRlmtInit */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtBuildCheckChain - build the check chain
+- *
+- * Description:
+- * This routine builds the local check chain:
+- * - Each port that is up checks the next port.
+- * - The last port that is up checks the first port that is up.
+- *
+- * Notes:
+- * - Currently only local ports are considered when building the chain.
+- * - Currently the SuspectState is just reset;
+- * it would be better to save it ...
+- *
+- * Context:
+- * runtime, pageable?
+- *
+- * Returns:
+- * Nothing
+- */
+-RLMT_STATIC void SkRlmtBuildCheckChain(
+-SK_AC *pAC, /* Adapter Context */
+-SK_U32 NetIdx) /* Net Number */
+-{
+- SK_U32 i;
+- SK_U32 NumMacsUp;
+- SK_RLMT_PORT * FirstMacUp;
+- SK_RLMT_PORT * PrevMacUp;
+-
+- FirstMacUp = NULL;
+- PrevMacUp = NULL;
+-
+- if (!(pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) {
+- for (i = 0; i < pAC->Rlmt.Net[i].NumPorts; i++) {
+- pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0;
+- }
+- return; /* Done. */
+- }
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SkRlmtBuildCheckChain.\n"))
+-
+- NumMacsUp = 0;
+-
+- for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) {
+- pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0;
+- pAC->Rlmt.Net[NetIdx].Port[i]->PortsSuspect = 0;
+- pAC->Rlmt.Net[NetIdx].Port[i]->CheckingState &=
+- ~(SK_RLMT_PCS_RX | SK_RLMT_PCS_TX);
+-
+- /*
+- * If more than two links are detected we should consider
+- * checking at least two other ports:
+- * 1. the next port that is not LinkDown and
+- * 2. the next port that is not PortDown.
+- */
+- if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) {
+- if (NumMacsUp == 0) {
+- FirstMacUp = pAC->Rlmt.Net[NetIdx].Port[i];
+- }
+- else {
+- PrevMacUp->PortCheck[
+- pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked].CheckAddr =
+- pAC->Rlmt.Net[NetIdx].Port[i]->AddrPort->CurrentMacAddress;
+- PrevMacUp->PortCheck[
+- PrevMacUp->PortsChecked].SuspectTx = SK_FALSE;
+- PrevMacUp->PortsChecked++;
+- }
+- PrevMacUp = pAC->Rlmt.Net[NetIdx].Port[i];
+- NumMacsUp++;
+- }
+- }
+-
+- if (NumMacsUp > 1) {
+- PrevMacUp->PortCheck[PrevMacUp->PortsChecked].CheckAddr =
+- FirstMacUp->AddrPort->CurrentMacAddress;
+- PrevMacUp->PortCheck[PrevMacUp->PortsChecked].SuspectTx =
+- SK_FALSE;
+- PrevMacUp->PortsChecked++;
+- }
+-
+-#ifdef DEBUG
+- for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Port %d checks %d other ports: %2X.\n", i,
+- pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked,
+- pAC->Rlmt.Net[NetIdx].Port[i]->PortCheck[0].CheckAddr.a[5]))
+- }
+-#endif /* DEBUG */
+-
+- return;
+-} /* SkRlmtBuildCheckChain */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtBuildPacket - build an RLMT packet
+- *
+- * Description:
+- * This routine sets up an RLMT packet.
+- *
+- * Context:
+- * runtime, pageable?
+- *
+- * Returns:
+- * NULL or pointer to RLMT mbuf
+- */
+-RLMT_STATIC SK_MBUF *SkRlmtBuildPacket(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_U32 PortNumber, /* Sending port */
+-SK_U16 PacketType, /* RLMT packet type */
+-SK_MAC_ADDR *SrcAddr, /* Source address */
+-SK_MAC_ADDR *DestAddr) /* Destination address */
+-{
+- int i;
+- SK_U16 Length;
+- SK_MBUF *pMb;
+- SK_RLMT_PACKET *pPacket;
+-
+-#ifdef DEBUG
+- SK_U8 CheckSrc = 0;
+- SK_U8 CheckDest = 0;
+-
+- for (i = 0; i < SK_MAC_ADDR_LEN; ++i) {
+- CheckSrc |= SrcAddr->a[i];
+- CheckDest |= DestAddr->a[i];
+- }
+-
+- if ((CheckSrc == 0) || (CheckDest == 0)) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_ERR,
+- ("SkRlmtBuildPacket: Invalid %s%saddr.\n",
+- (CheckSrc == 0 ? "Src" : ""), (CheckDest == 0 ? "Dest" : "")))
+- }
+-#endif
+-
+- if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) != NULL) {
+- pPacket = (SK_RLMT_PACKET*)pMb->pData;
+- for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
+- pPacket->DstAddr[i] = DestAddr->a[i];
+- pPacket->SrcAddr[i] = SrcAddr->a[i];
+- }
+- pPacket->DSap = SK_RLMT_DSAP;
+- pPacket->SSap = SK_RLMT_SSAP;
+- pPacket->Ctrl = SK_RLMT_CTRL;
+- pPacket->Indicator[0] = SK_RLMT_INDICATOR0;
+- pPacket->Indicator[1] = SK_RLMT_INDICATOR1;
+- pPacket->Indicator[2] = SK_RLMT_INDICATOR2;
+- pPacket->Indicator[3] = SK_RLMT_INDICATOR3;
+- pPacket->Indicator[4] = SK_RLMT_INDICATOR4;
+- pPacket->Indicator[5] = SK_RLMT_INDICATOR5;
+- pPacket->Indicator[6] = SK_RLMT_INDICATOR6;
+-
+- SK_U16_TO_NETWORK_ORDER(PacketType, &pPacket->RlmtPacketType[0]);
+-
+- for (i = 0; i < 4; i++) {
+- pPacket->Random[i] = pAC->Rlmt.Port[PortNumber].Random[i];
+- }
+-
+- SK_U16_TO_NETWORK_ORDER(
+- SK_RLMT_PACKET_VERSION, &pPacket->RlmtPacketVersion[0]);
+-
+- for (i = 0; i < SK_PACKET_DATA_LEN; i++) {
+- pPacket->Data[i] = 0x00;
+- }
+-
+- Length = SK_RLMT_MAX_PACKET_SIZE; /* Or smaller. */
+- pMb->Length = Length;
+- pMb->PortIdx = PortNumber;
+- Length -= 14;
+- SK_U16_TO_NETWORK_ORDER(Length, &pPacket->TypeLen[0]);
+-
+- if (PacketType == SK_PACKET_ALIVE) {
+- pAC->Rlmt.Port[PortNumber].TxHelloCts++;
+- }
+- }
+-
+- return (pMb);
+-} /* SkRlmtBuildPacket */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtBuildSpanningTreePacket - build spanning tree check packet
+- *
+- * Description:
+- * This routine sets up a BPDU packet for spanning tree check.
+- *
+- * Context:
+- * runtime, pageable?
+- *
+- * Returns:
+- * NULL or pointer to RLMT mbuf
+- */
+-RLMT_STATIC SK_MBUF *SkRlmtBuildSpanningTreePacket(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_U32 PortNumber) /* Sending port */
+-{
+- unsigned i;
+- SK_U16 Length;
+- SK_MBUF *pMb;
+- SK_SPTREE_PACKET *pSPacket;
+-
+- if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) !=
+- NULL) {
+- pSPacket = (SK_SPTREE_PACKET*)pMb->pData;
+- for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
+- pSPacket->DstAddr[i] = BridgeMcAddr.a[i];
+- pSPacket->SrcAddr[i] =
+- pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i];
+- }
+- pSPacket->DSap = SK_RLMT_SPT_DSAP;
+- pSPacket->SSap = SK_RLMT_SPT_SSAP;
+- pSPacket->Ctrl = SK_RLMT_SPT_CTRL;
+-
+- pSPacket->ProtocolId[0] = SK_RLMT_SPT_PROTOCOL_ID0;
+- pSPacket->ProtocolId[1] = SK_RLMT_SPT_PROTOCOL_ID1;
+- pSPacket->ProtocolVersionId = SK_RLMT_SPT_PROTOCOL_VERSION_ID;
+- pSPacket->BpduType = SK_RLMT_SPT_BPDU_TYPE;
+- pSPacket->Flags = SK_RLMT_SPT_FLAGS;
+- pSPacket->RootId[0] = SK_RLMT_SPT_ROOT_ID0;
+- pSPacket->RootId[1] = SK_RLMT_SPT_ROOT_ID1;
+- pSPacket->RootPathCost[0] = SK_RLMT_SPT_ROOT_PATH_COST0;
+- pSPacket->RootPathCost[1] = SK_RLMT_SPT_ROOT_PATH_COST1;
+- pSPacket->RootPathCost[2] = SK_RLMT_SPT_ROOT_PATH_COST2;
+- pSPacket->RootPathCost[3] = SK_RLMT_SPT_ROOT_PATH_COST3;
+- pSPacket->BridgeId[0] = SK_RLMT_SPT_BRIDGE_ID0;
+- pSPacket->BridgeId[1] = SK_RLMT_SPT_BRIDGE_ID1;
+-
+- /*
+- * Use logical MAC address as bridge ID and filter these packets
+- * on receive.
+- */
+- for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
+- pSPacket->BridgeId[i + 2] = pSPacket->RootId[i + 2] =
+- pAC->Addr.Net[pAC->Rlmt.Port[PortNumber].Net->NetNumber].
+- CurrentMacAddress.a[i];
+- }
+- pSPacket->PortId[0] = SK_RLMT_SPT_PORT_ID0;
+- pSPacket->PortId[1] = SK_RLMT_SPT_PORT_ID1;
+- pSPacket->MessageAge[0] = SK_RLMT_SPT_MSG_AGE0;
+- pSPacket->MessageAge[1] = SK_RLMT_SPT_MSG_AGE1;
+- pSPacket->MaxAge[0] = SK_RLMT_SPT_MAX_AGE0;
+- pSPacket->MaxAge[1] = SK_RLMT_SPT_MAX_AGE1;
+- pSPacket->HelloTime[0] = SK_RLMT_SPT_HELLO_TIME0;
+- pSPacket->HelloTime[1] = SK_RLMT_SPT_HELLO_TIME1;
+- pSPacket->ForwardDelay[0] = SK_RLMT_SPT_FWD_DELAY0;
+- pSPacket->ForwardDelay[1] = SK_RLMT_SPT_FWD_DELAY1;
+-
+- Length = SK_RLMT_MAX_PACKET_SIZE; /* Or smaller. */
+- pMb->Length = Length;
+- pMb->PortIdx = PortNumber;
+- Length -= 14;
+- SK_U16_TO_NETWORK_ORDER(Length, &pSPacket->TypeLen[0]);
+-
+- pAC->Rlmt.Port[PortNumber].TxSpHelloReqCts++;
+- }
+-
+- return (pMb);
+-} /* SkRlmtBuildSpanningTreePacket */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtSend - build and send check packets
+- *
+- * Description:
+- * Depending on the RLMT state and the checking state, several packets
+- * are sent through the indicated port.
+- *
+- * Context:
+- * runtime, pageable?
+- *
+- * Returns:
+- * Nothing.
+- */
+-RLMT_STATIC void SkRlmtSend(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_U32 PortNumber) /* Sending port */
+-{
+- unsigned j;
+- SK_EVPARA Para;
+- SK_RLMT_PORT *pRPort;
+-
+- pRPort = &pAC->Rlmt.Port[PortNumber];
+- if (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) {
+- if (pRPort->CheckingState & (SK_RLMT_PCS_TX | SK_RLMT_PCS_RX)) {
+- /* Port is suspicious. Send the RLMT packet to the RLMT mc addr. */
+- if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber,
+- SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress,
+- &SkRlmtMcAddr)) != NULL) {
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+- }
+- }
+- else {
+- /*
+- * Send a directed RLMT packet to all ports that are
+- * checked by the indicated port.
+- */
+- for (j = 0; j < pRPort->PortsChecked; j++) {
+- if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber,
+- SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress,
+- &pRPort->PortCheck[j].CheckAddr)) != NULL) {
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+- }
+- }
+- }
+- }
+-
+- if ((pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) &&
+- (pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEND_SEG)) {
+- /*
+- * Send a BPDU packet to make a connected switch tell us
+- * the correct root bridge.
+- */
+- if ((Para.pParaPtr =
+- SkRlmtBuildSpanningTreePacket(pAC, IoC, PortNumber)) != NULL) {
+- pAC->Rlmt.Port[PortNumber].Net->CheckingState &= ~SK_RLMT_RCS_SEND_SEG;
+- pRPort->RootIdSet = SK_FALSE;
+-
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_TX,
+- ("SkRlmtSend: BPDU Packet on Port %u.\n", PortNumber))
+- }
+- }
+- return;
+-} /* SkRlmtSend */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtPortReceives - check if port is (going) down and bring it up
+- *
+- * Description:
+- * This routine checks if a port who received a non-BPDU packet
+- * needs to go up or needs to be stopped going down.
+- *
+- * Context:
+- * runtime, pageable?
+- *
+- * Returns:
+- * Nothing.
+- */
+-RLMT_STATIC void SkRlmtPortReceives(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_U32 PortNumber) /* Port to check */
+-{
+- SK_RLMT_PORT *pRPort;
+- SK_EVPARA Para;
+-
+- pRPort = &pAC->Rlmt.Port[PortNumber];
+- pRPort->PortNoRx = SK_FALSE;
+-
+- if ((pRPort->PortState == SK_RLMT_PS_DOWN) &&
+- !(pRPort->CheckingState & SK_RLMT_PCS_TX)) {
+- /*
+- * Port is marked down (rx), but received a non-BPDU packet.
+- * Bring it up.
+- */
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: Received on PortDown.\n"))
+-
+- pRPort->PortState = SK_RLMT_PS_GOING_UP;
+- pRPort->GuTimeStamp = SkOsGetTime(pAC);
+- Para.Para32[0] = PortNumber;
+- Para.Para32[1] = (SK_U32)-1;
+- SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL,
+- SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para);
+- pRPort->CheckingState &= ~SK_RLMT_PCS_RX;
+- /* pAC->Rlmt.CheckSwitch = SK_TRUE; */
+- SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
+- } /* PortDown && !SuspectTx */
+- else if (pRPort->CheckingState & SK_RLMT_PCS_RX) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: Stop bringing port down.\n"))
+- SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
+- pRPort->CheckingState &= ~SK_RLMT_PCS_RX;
+- /* pAC->Rlmt.CheckSwitch = SK_TRUE; */
+- SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
+- } /* PortGoingDown */
+-
+- return;
+-} /* SkRlmtPortReceives */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtPacketReceive - receive a packet for closer examination
+- *
+- * Description:
+- * This routine examines a packet more closely than SK_RLMT_LOOKAHEAD.
+- *
+- * Context:
+- * runtime, pageable?
+- *
+- * Returns:
+- * Nothing.
+- */
+-RLMT_STATIC void SkRlmtPacketReceive(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_MBUF *pMb) /* Received packet */
+-{
+-#ifdef xDEBUG
+- extern void DumpData(char *p, int size);
+-#endif /* DEBUG */
+- int i;
+- unsigned j;
+- SK_U16 PacketType;
+- SK_U32 PortNumber;
+- SK_ADDR_PORT *pAPort;
+- SK_RLMT_PORT *pRPort;
+- SK_RLMT_PACKET *pRPacket;
+- SK_SPTREE_PACKET *pSPacket;
+- SK_EVPARA Para;
+-
+- PortNumber = pMb->PortIdx;
+- pAPort = &pAC->Addr.Port[PortNumber];
+- pRPort = &pAC->Rlmt.Port[PortNumber];
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: PortNumber == %d.\n", PortNumber))
+-
+- pRPacket = (SK_RLMT_PACKET*)pMb->pData;
+- pSPacket = (SK_SPTREE_PACKET*)pRPacket;
+-
+-#ifdef xDEBUG
+- DumpData((char *)pRPacket, 32);
+-#endif /* DEBUG */
+-
+- if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) != 0) {
+- SkRlmtPortReceives(pAC, IoC, PortNumber);
+- }
+-
+- /* Check destination address. */
+-
+- if (!SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->DstAddr) &&
+- !SK_ADDR_EQUAL(SkRlmtMcAddr.a, pRPacket->DstAddr) &&
+- !SK_ADDR_EQUAL(BridgeMcAddr.a, pRPacket->DstAddr)) {
+-
+- /* Not sent to current MAC or registered MC address => Trash it. */
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: Not for me.\n"))
+-
+- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+- return;
+- }
+- else if (SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->SrcAddr)) {
+-
+- /*
+- * Was sent by same port (may happen during port switching
+- * or in case of duplicate MAC addresses).
+- */
+-
+- /*
+- * Check for duplicate address here:
+- * If Packet.Random != My.Random => DupAddr.
+- */
+- for (i = 3; i >= 0; i--) {
+- if (pRPort->Random[i] != pRPacket->Random[i]) {
+- break;
+- }
+- }
+-
+- /*
+- * CAUTION: Do not check for duplicate MAC address in RLMT Alive Reply
+- * packets (they have the LLC_COMMAND_RESPONSE_BIT set in
+- * pRPacket->SSap).
+- */
+- if (i >= 0 && pRPacket->DSap == SK_RLMT_DSAP &&
+- pRPacket->Ctrl == SK_RLMT_CTRL &&
+- pRPacket->SSap == SK_RLMT_SSAP &&
+- pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 &&
+- pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 &&
+- pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 &&
+- pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 &&
+- pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 &&
+- pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 &&
+- pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: Duplicate MAC Address.\n"))
+-
+- /* Error Log entry. */
+- SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E006, SKERR_RLMT_E006_MSG);
+- }
+- else {
+- /* Simply trash it. */
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: Sent by me.\n"))
+- }
+-
+- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+- return;
+- }
+-
+- /* Check SuspectTx entries. */
+- if (pRPort->PortsSuspect > 0) {
+- for (j = 0; j < pRPort->PortsChecked; j++) {
+- if (pRPort->PortCheck[j].SuspectTx &&
+- SK_ADDR_EQUAL(
+- pRPacket->SrcAddr, pRPort->PortCheck[j].CheckAddr.a)) {
+- pRPort->PortCheck[j].SuspectTx = SK_FALSE;
+- pRPort->PortsSuspect--;
+- break;
+- }
+- }
+- }
+-
+- /* Determine type of packet. */
+- if (pRPacket->DSap == SK_RLMT_DSAP &&
+- pRPacket->Ctrl == SK_RLMT_CTRL &&
+- (pRPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SSAP &&
+- pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 &&
+- pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 &&
+- pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 &&
+- pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 &&
+- pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 &&
+- pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 &&
+- pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) {
+-
+- /* It's an RLMT packet. */
+- PacketType = (SK_U16)((pRPacket->RlmtPacketType[0] << 8) |
+- pRPacket->RlmtPacketType[1]);
+-
+- switch (PacketType) {
+- case SK_PACKET_ANNOUNCE: /* Not yet used. */
+-#if 0
+- /* Build the check chain. */
+- SkRlmtBuildCheckChain(pAC);
+-#endif /* 0 */
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: Announce.\n"))
+-
+- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+- break;
+-
+- case SK_PACKET_ALIVE:
+- if (pRPacket->SSap & LLC_COMMAND_RESPONSE_BIT) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: Alive Reply.\n"))
+-
+- if (!(pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_LLC) ||
+- SK_ADDR_EQUAL(
+- pRPacket->DstAddr, pAPort->CurrentMacAddress.a)) {
+- /* Obviously we could send something. */
+- if (pRPort->CheckingState & SK_RLMT_PCS_TX) {
+- pRPort->CheckingState &= ~SK_RLMT_PCS_TX;
+- SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
+- }
+-
+- if ((pRPort->PortState == SK_RLMT_PS_DOWN) &&
+- !(pRPort->CheckingState & SK_RLMT_PCS_RX)) {
+- pRPort->PortState = SK_RLMT_PS_GOING_UP;
+- pRPort->GuTimeStamp = SkOsGetTime(pAC);
+-
+- SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
+-
+- Para.Para32[0] = PortNumber;
+- Para.Para32[1] = (SK_U32)-1;
+- SkTimerStart(pAC, IoC, &pRPort->UpTimer,
+- SK_RLMT_PORTUP_TIM_VAL, SKGE_RLMT,
+- SK_RLMT_PORTUP_TIM, Para);
+- }
+- }
+-
+- /* Mark sending port as alive? */
+- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+- }
+- else { /* Alive Request Packet. */
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: Alive Request.\n"))
+-
+- pRPort->RxHelloCts++;
+-
+- /* Answer. */
+- for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
+- pRPacket->DstAddr[i] = pRPacket->SrcAddr[i];
+- pRPacket->SrcAddr[i] =
+- pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i];
+- }
+- pRPacket->SSap |= LLC_COMMAND_RESPONSE_BIT;
+-
+- Para.pParaPtr = pMb;
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+- }
+- break;
+-
+- case SK_PACKET_CHECK_TX:
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: Check your tx line.\n"))
+-
+- /* A port checking us requests us to check our tx line. */
+- pRPort->CheckingState |= SK_RLMT_PCS_TX;
+-
+- /* Start PortDownTx timer. */
+- Para.Para32[0] = PortNumber;
+- Para.Para32[1] = (SK_U32)-1;
+- SkTimerStart(pAC, IoC, &pRPort->DownTxTimer,
+- SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT,
+- SK_RLMT_PORTDOWN_TX_TIM, Para);
+-
+- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+-
+- if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber,
+- SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress,
+- &SkRlmtMcAddr)) != NULL) {
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+- }
+- break;
+-
+- case SK_PACKET_ADDR_CHANGED:
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: Address Change.\n"))
+-
+- /* Build the check chain. */
+- SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
+- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+- break;
+-
+- default:
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: Unknown RLMT packet.\n"))
+-
+- /* RA;:;: ??? */
+- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+- }
+- }
+- else if (pSPacket->DSap == SK_RLMT_SPT_DSAP &&
+- pSPacket->Ctrl == SK_RLMT_SPT_CTRL &&
+- (pSPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SPT_SSAP) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: BPDU Packet.\n"))
+-
+- /* Spanning Tree packet. */
+- pRPort->RxSpHelloCts++;
+-
+- if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pAC->Addr.Net[pAC->Rlmt.
+- Port[PortNumber].Net->NetNumber].CurrentMacAddress.a[0])) {
+- /*
+- * Check segmentation if a new root bridge is set and
+- * the segmentation check is not currently running.
+- */
+- if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pRPort->Root.Id[2]) &&
+- (pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) &&
+- (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG)
+- != 0 && (pAC->Rlmt.Port[PortNumber].Net->CheckingState &
+- SK_RLMT_RCS_SEG) == 0) {
+- pAC->Rlmt.Port[PortNumber].Net->CheckingState |=
+- SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG;
+- }
+-
+- /* Store tree view of this port. */
+- for (i = 0; i < 8; i++) {
+- pRPort->Root.Id[i] = pSPacket->RootId[i];
+- }
+- pRPort->RootIdSet = SK_TRUE;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP,
+- ("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
+- PortNumber,
+- pRPort->Root.Id[0], pRPort->Root.Id[1],
+- pRPort->Root.Id[2], pRPort->Root.Id[3],
+- pRPort->Root.Id[4], pRPort->Root.Id[5],
+- pRPort->Root.Id[6], pRPort->Root.Id[7]))
+- }
+-
+- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+- if ((pAC->Rlmt.Port[PortNumber].Net->CheckingState &
+- SK_RLMT_RCS_REPORT_SEG) != 0) {
+- SkRlmtCheckSeg(pAC, IoC, pAC->Rlmt.Port[PortNumber].Net->NetNumber);
+- }
+- }
+- else {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: Unknown Packet Type.\n"))
+-
+- /* Unknown packet. */
+- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+- }
+- return;
+-} /* SkRlmtPacketReceive */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtCheckPort - check if a port works
+- *
+- * Description:
+- * This routine checks if a port whose link is up received something
+- * and if it seems to transmit successfully.
+- *
+- * # PortState: PsInit, PsLinkDown, PsDown, PsGoingUp, PsUp
+- * # PortCheckingState (Bitfield): ChkTx, ChkRx, ChkSeg
+- * # RlmtCheckingState (Bitfield): ChkSeg, StartChkSeg, ReportSeg
+- *
+- * if (Rx - RxBpdu == 0) { # No rx.
+- * if (state == PsUp) {
+- * PortCheckingState |= ChkRx
+- * }
+- * if (ModeCheckSeg && (Timeout ==
+- * TO_SHORTEN(RLMT_DEFAULT_TIMEOUT))) {
+- * RlmtCheckingState |= ChkSeg)
+- * PortCheckingState |= ChkSeg
+- * }
+- * NewTimeout = TO_SHORTEN(Timeout)
+- * if (NewTimeout < RLMT_MIN_TIMEOUT) {
+- * NewTimeout = RLMT_MIN_TIMEOUT
+- * PortState = PsDown
+- * ...
+- * }
+- * }
+- * else { # something was received
+- * # Set counter to 0 at LinkDown?
+- * # No - rx may be reported after LinkDown ???
+- * PortCheckingState &= ~ChkRx
+- * NewTimeout = RLMT_DEFAULT_TIMEOUT
+- * if (RxAck == 0) {
+- * possible reasons:
+- * is my tx line bad? --
+- * send RLMT multicast and report
+- * back internally? (only possible
+- * between ports on same adapter)
+- * }
+- * if (RxChk == 0) {
+- * possible reasons:
+- * - tx line of port set to check me
+- * maybe bad
+- * - no other port/adapter available or set
+- * to check me
+- * - adapter checking me has a longer
+- * timeout
+- * ??? anything that can be done here?
+- * }
+- * }
+- *
+- * Context:
+- * runtime, pageable?
+- *
+- * Returns:
+- * New timeout value.
+- */
+-RLMT_STATIC SK_U32 SkRlmtCheckPort(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_U32 PortNumber) /* Port to check */
+-{
+- unsigned i;
+- SK_U32 NewTimeout;
+- SK_RLMT_PORT *pRPort;
+- SK_EVPARA Para;
+-
+- pRPort = &pAC->Rlmt.Port[PortNumber];
+-
+- if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) == 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SkRlmtCheckPort %d: No (%d) receives in last time slot.\n",
+- PortNumber, pRPort->PacketsPerTimeSlot))
+-
+- /*
+- * Check segmentation if there was no receive at least twice
+- * in a row (PortNoRx is already set) and the segmentation
+- * check is not currently running.
+- */
+-
+- if (pRPort->PortNoRx && (pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) &&
+- (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) &&
+- !(pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEG)) {
+- pAC->Rlmt.Port[PortNumber].Net->CheckingState |=
+- SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG;
+- }
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SkRlmtCheckPort: PortsSuspect %d, PcsRx %d.\n",
+- pRPort->PortsSuspect, pRPort->CheckingState & SK_RLMT_PCS_RX))
+-
+- if (pRPort->PortState != SK_RLMT_PS_DOWN) {
+- NewTimeout = TO_SHORTEN(pAC->Rlmt.Port[PortNumber].Net->TimeoutValue);
+- if (NewTimeout < SK_RLMT_MIN_TO_VAL) {
+- NewTimeout = SK_RLMT_MIN_TO_VAL;
+- }
+-
+- if (!(pRPort->CheckingState & SK_RLMT_PCS_RX)) {
+- Para.Para32[0] = PortNumber;
+- pRPort->CheckingState |= SK_RLMT_PCS_RX;
+-
+- /*
+- * What shall we do if the port checked by this one receives
+- * our request frames? What's bad - our rx line or his tx line?
+- */
+- Para.Para32[1] = (SK_U32)-1;
+- SkTimerStart(pAC, IoC, &pRPort->DownRxTimer,
+- SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT,
+- SK_RLMT_PORTDOWN_RX_TIM, Para);
+-
+- for (i = 0; i < pRPort->PortsChecked; i++) {
+- if (pRPort->PortCheck[i].SuspectTx) {
+- continue;
+- }
+- pRPort->PortCheck[i].SuspectTx = SK_TRUE;
+- pRPort->PortsSuspect++;
+- if ((Para.pParaPtr =
+- SkRlmtBuildPacket(pAC, IoC, PortNumber, SK_PACKET_CHECK_TX,
+- &pAC->Addr.Port[PortNumber].CurrentMacAddress,
+- &pRPort->PortCheck[i].CheckAddr)) != NULL) {
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+- }
+- }
+- }
+- }
+- else { /* PortDown -- or all partners suspect. */
+- NewTimeout = SK_RLMT_DEF_TO_VAL;
+- }
+- pRPort->PortNoRx = SK_TRUE;
+- }
+- else { /* A non-BPDU packet was received. */
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SkRlmtCheckPort %d: %d (%d) receives in last time slot.\n",
+- PortNumber,
+- pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot,
+- pRPort->PacketsPerTimeSlot))
+-
+- SkRlmtPortReceives(pAC, IoC, PortNumber);
+- if (pAC->Rlmt.CheckSwitch) {
+- SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
+- }
+-
+- NewTimeout = SK_RLMT_DEF_TO_VAL;
+- }
+-
+- return (NewTimeout);
+-} /* SkRlmtCheckPort */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtSelectBcRx - select new active port, criteria 1 (CLP)
+- *
+- * Description:
+- * This routine selects the port that received a broadcast frame
+- * substantially later than all other ports.
+- *
+- * Context:
+- * runtime, pageable?
+- *
+- * Returns:
+- * SK_BOOL
+- */
+-RLMT_STATIC SK_BOOL SkRlmtSelectBcRx(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_U32 Active, /* Active port */
+-SK_U32 PrefPort, /* Preferred port */
+-SK_U32 *pSelect) /* New active port */
+-{
+- SK_U64 BcTimeStamp;
+- SK_U32 i;
+- SK_BOOL PortFound;
+-
+- BcTimeStamp = 0; /* Not totally necessary, but feeling better. */
+- PortFound = SK_FALSE;
+-
+- /* Select port with the latest TimeStamp. */
+- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("TimeStamp Port %d (Down: %d, NoRx: %d): %08x %08x.\n",
+- i,
+- pAC->Rlmt.Port[i].PortDown, pAC->Rlmt.Port[i].PortNoRx,
+- *((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_HI32),
+- *((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_LO32)))
+-
+- if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx) {
+- if (!PortFound || pAC->Rlmt.Port[i].BcTimeStamp > BcTimeStamp) {
+- BcTimeStamp = pAC->Rlmt.Port[i].BcTimeStamp;
+- *pSelect = i;
+- PortFound = SK_TRUE;
+- }
+- }
+- }
+-
+- if (PortFound) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Port %d received the last broadcast.\n", *pSelect))
+-
+- /* Look if another port's time stamp is similar. */
+- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+- if (i == *pSelect) {
+- continue;
+- }
+- if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx &&
+- (pAC->Rlmt.Port[i].BcTimeStamp >
+- BcTimeStamp - SK_RLMT_BC_DELTA ||
+- pAC->Rlmt.Port[i].BcTimeStamp +
+- SK_RLMT_BC_DELTA > BcTimeStamp)) {
+- PortFound = SK_FALSE;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Port %d received a broadcast at a similar time.\n", i))
+- break;
+- }
+- }
+- }
+-
+-#ifdef DEBUG
+- if (PortFound) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SELECT_BCRX found Port %d receiving the substantially "
+- "latest broadcast (%u).\n",
+- *pSelect,
+- BcTimeStamp - pAC->Rlmt.Port[1 - *pSelect].BcTimeStamp))
+- }
+-#endif /* DEBUG */
+-
+- return (PortFound);
+-} /* SkRlmtSelectBcRx */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtSelectNotSuspect - select new active port, criteria 2 (CLP)
+- *
+- * Description:
+- * This routine selects a good port (it is PortUp && !SuspectRx).
+- *
+- * Context:
+- * runtime, pageable?
+- *
+- * Returns:
+- * SK_BOOL
+- */
+-RLMT_STATIC SK_BOOL SkRlmtSelectNotSuspect(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_U32 Active, /* Active port */
+-SK_U32 PrefPort, /* Preferred port */
+-SK_U32 *pSelect) /* New active port */
+-{
+- SK_U32 i;
+- SK_BOOL PortFound;
+-
+- PortFound = SK_FALSE;
+-
+- /* Select first port that is PortUp && !SuspectRx. */
+- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+- if (!pAC->Rlmt.Port[i].PortDown &&
+- !(pAC->Rlmt.Port[i].CheckingState & SK_RLMT_PCS_RX)) {
+- *pSelect = i;
+- if (!pAC->Rlmt.Port[Active].PortDown &&
+- !(pAC->Rlmt.Port[Active].CheckingState & SK_RLMT_PCS_RX)) {
+- *pSelect = Active;
+- }
+- if (!pAC->Rlmt.Port[PrefPort].PortDown &&
+- !(pAC->Rlmt.Port[PrefPort].CheckingState & SK_RLMT_PCS_RX)) {
+- *pSelect = PrefPort;
+- }
+- PortFound = SK_TRUE;
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SELECT_NOTSUSPECT found Port %d up and not check RX.\n",
+- *pSelect))
+- break;
+- }
+- }
+- return (PortFound);
+-} /* SkRlmtSelectNotSuspect */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtSelectUp - select new active port, criteria 3, 4 (CLP)
+- *
+- * Description:
+- * This routine selects a port that is up.
+- *
+- * Context:
+- * runtime, pageable?
+- *
+- * Returns:
+- * SK_BOOL
+- */
+-RLMT_STATIC SK_BOOL SkRlmtSelectUp(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_U32 Active, /* Active port */
+-SK_U32 PrefPort, /* Preferred port */
+-SK_U32 *pSelect, /* New active port */
+-SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */
+-{
+- SK_U32 i;
+- SK_BOOL PortFound;
+-
+- PortFound = SK_FALSE;
+-
+- /* Select first port that is PortUp. */
+- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+- if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_UP &&
+- pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
+- *pSelect = i;
+- if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_UP &&
+- pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) {
+- *pSelect = Active;
+- }
+- if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_UP &&
+- pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) {
+- *pSelect = PrefPort;
+- }
+- PortFound = SK_TRUE;
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SELECT_UP found Port %d up.\n", *pSelect))
+- break;
+- }
+- }
+- return (PortFound);
+-} /* SkRlmtSelectUp */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtSelectGoingUp - select new active port, criteria 5, 6 (CLP)
+- *
+- * Description:
+- * This routine selects the port that is going up for the longest time.
+- *
+- * Context:
+- * runtime, pageable?
+- *
+- * Returns:
+- * SK_BOOL
+- */
+-RLMT_STATIC SK_BOOL SkRlmtSelectGoingUp(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_U32 Active, /* Active port */
+-SK_U32 PrefPort, /* Preferred port */
+-SK_U32 *pSelect, /* New active port */
+-SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */
+-{
+- SK_U64 GuTimeStamp;
+- SK_U32 i;
+- SK_BOOL PortFound;
+-
+- GuTimeStamp = 0;
+- PortFound = SK_FALSE;
+-
+- /* Select port that is PortGoingUp for the longest time. */
+- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+- if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP &&
+- pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
+- GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp;
+- *pSelect = i;
+- PortFound = SK_TRUE;
+- break;
+- }
+- }
+-
+- if (!PortFound) {
+- return (SK_FALSE);
+- }
+-
+- for (i = *pSelect + 1; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+- if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP &&
+- pAC->Rlmt.Port[i].GuTimeStamp < GuTimeStamp &&
+- pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
+- GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp;
+- *pSelect = i;
+- }
+- }
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SELECT_GOINGUP found Port %d going up.\n", *pSelect))
+- return (SK_TRUE);
+-} /* SkRlmtSelectGoingUp */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtSelectDown - select new active port, criteria 7, 8 (CLP)
+- *
+- * Description:
+- * This routine selects a port that is down.
+- *
+- * Context:
+- * runtime, pageable?
+- *
+- * Returns:
+- * SK_BOOL
+- */
+-RLMT_STATIC SK_BOOL SkRlmtSelectDown(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_U32 Active, /* Active port */
+-SK_U32 PrefPort, /* Preferred port */
+-SK_U32 *pSelect, /* New active port */
+-SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */
+-{
+- SK_U32 i;
+- SK_BOOL PortFound;
+-
+- PortFound = SK_FALSE;
+-
+- /* Select first port that is PortDown. */
+- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+- if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_DOWN &&
+- pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
+- *pSelect = i;
+- if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_DOWN &&
+- pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) {
+- *pSelect = Active;
+- }
+- if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_DOWN &&
+- pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) {
+- *pSelect = PrefPort;
+- }
+- PortFound = SK_TRUE;
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SELECT_DOWN found Port %d down.\n", *pSelect))
+- break;
+- }
+- }
+- return (PortFound);
+-} /* SkRlmtSelectDown */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtCheckSwitch - select new active port and switch to it
+- *
+- * Description:
+- * This routine decides which port should be the active one and queues
+- * port switching if necessary.
+- *
+- * Context:
+- * runtime, pageable?
+- *
+- * Returns:
+- * Nothing.
+- */
+-RLMT_STATIC void SkRlmtCheckSwitch(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_U32 NetIdx) /* Net index */
+-{
+- SK_EVPARA Para;
+- SK_U32 Active;
+- SK_U32 PrefPort;
+- SK_U32 i;
+- SK_BOOL PortFound;
+-
+- Active = pAC->Rlmt.Net[NetIdx].ActivePort; /* Index of active port. */
+- PrefPort = pAC->Rlmt.Net[NetIdx].PrefPort; /* Index of preferred port. */
+- PortFound = SK_FALSE;
+- pAC->Rlmt.CheckSwitch = SK_FALSE;
+-
+-#if 0 /* RW 2001/10/18 - active port becomes always prefered one */
+- if (pAC->Rlmt.Net[NetIdx].Preference == 0xFFFFFFFF) { /* Automatic */
+- /* disable auto-fail back */
+- PrefPort = Active;
+- }
+-#endif
+-
+- if (pAC->Rlmt.Net[NetIdx].LinksUp == 0) {
+- /* Last link went down - shut down the net. */
+- pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_DOWN;
+- Para.Para32[0] = SK_RLMT_NET_DOWN_TEMP;
+- Para.Para32[1] = NetIdx;
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para);
+-
+- Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
+- Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber;
+- Para.Para32[1] = NetIdx;
+- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para);
+- return;
+- } /* pAC->Rlmt.LinksUp == 0 */
+- else if (pAC->Rlmt.Net[NetIdx].LinksUp == 1 &&
+- pAC->Rlmt.Net[NetIdx].RlmtState == SK_RLMT_RS_NET_DOWN) {
+- /* First link came up - get the net up. */
+- pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_UP;
+-
+- /*
+- * If pAC->Rlmt.ActivePort != Para.Para32[0],
+- * the DRV switches to the port that came up.
+- */
+- for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) {
+- if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) {
+- if (!pAC->Rlmt.Net[NetIdx].Port[Active]->LinkDown) {
+- i = Active;
+- }
+- if (!pAC->Rlmt.Net[NetIdx].Port[PrefPort]->LinkDown) {
+- i = PrefPort;
+- }
+- PortFound = SK_TRUE;
+- break;
+- }
+- }
+-
+- if (PortFound) {
+- Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber;
+- Para.Para32[1] = NetIdx;
+- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para);
+-
+- pAC->Rlmt.Net[NetIdx].ActivePort = i;
+- Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber;
+- Para.Para32[1] = NetIdx;
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_UP, Para);
+-
+- if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
+- (Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC,
+- pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber,
+- SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx].
+- CurrentMacAddress, &SkRlmtMcAddr)) != NULL) {
+- /*
+- * Send announce packet to RLMT multicast address to force
+- * switches to learn the new location of the logical MAC address.
+- */
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+- }
+- }
+- else {
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E007, SKERR_RLMT_E007_MSG);
+- }
+-
+- return;
+- } /* LinksUp == 1 && RlmtState == SK_RLMT_RS_NET_DOWN */
+- else { /* Cannot be reached in dual-net mode. */
+- Para.Para32[0] = Active;
+-
+- /*
+- * Preselection:
+- * If RLMT Mode != CheckLinkState
+- * select port that received a broadcast frame substantially later
+- * than all other ports
+- * else select first port that is not SuspectRx
+- * else select first port that is PortUp
+- * else select port that is PortGoingUp for the longest time
+- * else select first port that is PortDown
+- * else stop.
+- *
+- * For the preselected port:
+- * If ActivePort is equal in quality, select ActivePort.
+- *
+- * If PrefPort is equal in quality, select PrefPort.
+- *
+- * If ActivePort != SelectedPort,
+- * If old ActivePort is LinkDown,
+- * SwitchHard
+- * else
+- * SwitchSoft
+- */
+- /* check of ChgBcPrio flag added */
+- if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) &&
+- (!pAC->Rlmt.Net[0].ChgBcPrio)) {
+-
+- if (!PortFound) {
+- PortFound = SkRlmtSelectBcRx(
+- pAC, IoC, Active, PrefPort, &Para.Para32[1]);
+- }
+-
+- if (!PortFound) {
+- PortFound = SkRlmtSelectNotSuspect(
+- pAC, IoC, Active, PrefPort, &Para.Para32[1]);
+- }
+- } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
+-
+- /* with changed priority for last broadcast received */
+- if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) &&
+- (pAC->Rlmt.Net[0].ChgBcPrio)) {
+- if (!PortFound) {
+- PortFound = SkRlmtSelectNotSuspect(
+- pAC, IoC, Active, PrefPort, &Para.Para32[1]);
+- }
+-
+- if (!PortFound) {
+- PortFound = SkRlmtSelectBcRx(
+- pAC, IoC, Active, PrefPort, &Para.Para32[1]);
+- }
+- } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
+-
+- if (!PortFound) {
+- PortFound = SkRlmtSelectUp(
+- pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS);
+- }
+-
+- if (!PortFound) {
+- PortFound = SkRlmtSelectUp(
+- pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED);
+- }
+-
+- if (!PortFound) {
+- PortFound = SkRlmtSelectGoingUp(
+- pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS);
+- }
+-
+- if (!PortFound) {
+- PortFound = SkRlmtSelectGoingUp(
+- pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED);
+- }
+-
+- if (pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) {
+- if (!PortFound) {
+- PortFound = SkRlmtSelectDown(pAC, IoC,
+- Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS);
+- }
+-
+- if (!PortFound) {
+- PortFound = SkRlmtSelectDown(pAC, IoC,
+- Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED);
+- }
+- } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
+-
+- if (PortFound) {
+-
+- if (Para.Para32[1] != Active) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Active: %d, Para1: %d.\n", Active, Para.Para32[1]))
+- pAC->Rlmt.Net[NetIdx].ActivePort = Para.Para32[1];
+- Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
+- Port[Para.Para32[0]]->PortNumber;
+- Para.Para32[1] = pAC->Rlmt.Net[NetIdx].
+- Port[Para.Para32[1]]->PortNumber;
+- SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[1], SK_LED_ACTIVE);
+- if (pAC->Rlmt.Port[Active].LinkDown) {
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_HARD, Para);
+- }
+- else {
+- SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY);
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_SOFT, Para);
+- }
+- Para.Para32[1] = NetIdx;
+- Para.Para32[0] =
+- pAC->Rlmt.Net[NetIdx].Port[Para.Para32[0]]->PortNumber;
+- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para);
+- Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
+- Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber;
+- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para);
+- if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
+- (Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, Para.Para32[0],
+- SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx].CurrentMacAddress,
+- &SkRlmtMcAddr)) != NULL) {
+- /*
+- * Send announce packet to RLMT multicast address to force
+- * switches to learn the new location of the logical
+- * MAC address.
+- */
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+- } /* (Para.pParaPtr = SkRlmtBuildPacket(...)) != NULL */
+- } /* Para.Para32[1] != Active */
+- } /* PortFound */
+- else {
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E004, SKERR_RLMT_E004_MSG);
+- }
+- } /* LinksUp > 1 || LinksUp == 1 && RlmtState != SK_RLMT_RS_NET_DOWN */
+- return;
+-} /* SkRlmtCheckSwitch */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtCheckSeg - Report if segmentation is detected
+- *
+- * Description:
+- * This routine checks if the ports see different root bridges and reports
+- * segmentation in such a case.
+- *
+- * Context:
+- * runtime, pageable?
+- *
+- * Returns:
+- * Nothing.
+- */
+-RLMT_STATIC void SkRlmtCheckSeg(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_U32 NetIdx) /* Net number */
+-{
+- SK_EVPARA Para;
+- SK_RLMT_NET *pNet;
+- SK_U32 i, j;
+- SK_BOOL Equal;
+-
+- pNet = &pAC->Rlmt.Net[NetIdx];
+- pNet->RootIdSet = SK_FALSE;
+- Equal = SK_TRUE;
+-
+- for (i = 0; i < pNet->NumPorts; i++) {
+- if (pNet->Port[i]->LinkDown || !pNet->Port[i]->RootIdSet) {
+- continue;
+- }
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP,
+- ("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n", i,
+- pNet->Port[i]->Root.Id[0], pNet->Port[i]->Root.Id[1],
+- pNet->Port[i]->Root.Id[2], pNet->Port[i]->Root.Id[3],
+- pNet->Port[i]->Root.Id[4], pNet->Port[i]->Root.Id[5],
+- pNet->Port[i]->Root.Id[6], pNet->Port[i]->Root.Id[7]))
+-
+- if (!pNet->RootIdSet) {
+- pNet->Root = pNet->Port[i]->Root;
+- pNet->RootIdSet = SK_TRUE;
+- continue;
+- }
+-
+- for (j = 0; j < 8; j ++) {
+- Equal &= pNet->Port[i]->Root.Id[j] == pNet->Root.Id[j];
+- if (!Equal) {
+- break;
+- }
+- }
+-
+- if (!Equal) {
+- SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E005, SKERR_RLMT_E005_MSG);
+- Para.Para32[0] = NetIdx;
+- Para.Para32[1] = (SK_U32)-1;
+- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SEGMENTATION, Para);
+-
+- pNet->CheckingState &= ~SK_RLMT_RCS_REPORT_SEG;
+-
+- /* 2000-03-06 RA: New. */
+- Para.Para32[0] = NetIdx;
+- Para.Para32[1] = (SK_U32)-1;
+- SkTimerStart(pAC, IoC, &pNet->SegTimer, SK_RLMT_SEG_TO_VAL,
+- SKGE_RLMT, SK_RLMT_SEG_TIM, Para);
+- break;
+- }
+- } /* for (i = 0; i < pNet->NumPorts; i++) */
+-
+- /* 2000-03-06 RA: Moved here. */
+- /* Segmentation check not running anymore. */
+- pNet->CheckingState &= ~SK_RLMT_RCS_SEG;
+-
+-} /* SkRlmtCheckSeg */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtPortStart - initialize port variables and start port
+- *
+- * Description:
+- * This routine initializes a port's variables and issues a PORT_START
+- * to the HWAC module. This handles retries if the start fails or the
+- * link eventually goes down.
+- *
+- * Context:
+- * runtime, pageable?
+- *
+- * Returns:
+- * Nothing
+- */
+-RLMT_STATIC void SkRlmtPortStart(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_U32 PortNumber) /* Port number */
+-{
+- SK_EVPARA Para;
+-
+- pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_LINK_DOWN;
+- pAC->Rlmt.Port[PortNumber].PortStarted = SK_TRUE;
+- pAC->Rlmt.Port[PortNumber].LinkDown = SK_TRUE;
+- pAC->Rlmt.Port[PortNumber].PortDown = SK_TRUE;
+- pAC->Rlmt.Port[PortNumber].CheckingState = 0;
+- pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE;
+- Para.Para32[0] = PortNumber;
+- Para.Para32[1] = (SK_U32)-1;
+- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
+-} /* SkRlmtPortStart */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtEvtPortStartTim - PORT_START_TIM
+- *
+- * Description:
+- * This routine handles PORT_START_TIM events.
+- *
+- * Context:
+- * runtime, pageable?
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * Nothing
+- */
+-RLMT_STATIC void SkRlmtEvtPortStartTim(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */
+-{
+- SK_U32 i;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORTSTART_TIMEOUT Port %d Event BEGIN.\n", Para.Para32[0]))
+-
+- if (Para.Para32[1] != (SK_U32)-1) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad Parameter.\n"))
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORTSTART_TIMEOUT Event EMPTY.\n"))
+- return;
+- }
+-
+- /*
+- * Used to start non-preferred ports if the preferred one
+- * does not come up.
+- * This timeout needs only be set when starting the first
+- * (preferred) port.
+- */
+- if (pAC->Rlmt.Port[Para.Para32[0]].LinkDown) {
+- /* PORT_START failed. */
+- for (i = 0; i < pAC->Rlmt.Port[Para.Para32[0]].Net->NumPorts; i++) {
+- if (!pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortStarted) {
+- SkRlmtPortStart(pAC, IoC,
+- pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortNumber);
+- }
+- }
+- }
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORTSTART_TIMEOUT Event END.\n"))
+-} /* SkRlmtEvtPortStartTim */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtEvtLinkUp - LINK_UP
+- *
+- * Description:
+- * This routine handles LLINK_UP events.
+- *
+- * Context:
+- * runtime, pageable?
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * Nothing
+- */
+-RLMT_STATIC void SkRlmtEvtLinkUp(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 Undefined */
+-{
+- SK_U32 i;
+- SK_RLMT_PORT *pRPort;
+- SK_EVPARA Para2;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_LINK_UP Port %d Event BEGIN.\n", Para.Para32[0]))
+-
+- pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
+- if (!pRPort->PortStarted) {
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E008, SKERR_RLMT_E008_MSG);
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_LINK_UP Event EMPTY.\n"))
+- return;
+- }
+-
+- if (!pRPort->LinkDown) {
+- /* RA;:;: Any better solution? */
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_LINK_UP Event EMPTY.\n"))
+- return;
+- }
+-
+- SkTimerStop(pAC, IoC, &pRPort->UpTimer);
+- SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
+- SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
+-
+- /* Do something if timer already fired? */
+-
+- pRPort->LinkDown = SK_FALSE;
+- pRPort->PortState = SK_RLMT_PS_GOING_UP;
+- pRPort->GuTimeStamp = SkOsGetTime(pAC);
+- pRPort->BcTimeStamp = 0;
+- pRPort->Net->LinksUp++;
+- if (pRPort->Net->LinksUp == 1) {
+- SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_ACTIVE);
+- }
+- else {
+- SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY);
+- }
+-
+- for (i = 0; i < pRPort->Net->NumPorts; i++) {
+- if (!pRPort->Net->Port[i]->PortStarted) {
+- SkRlmtPortStart(pAC, IoC, pRPort->Net->Port[i]->PortNumber);
+- }
+- }
+-
+- SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
+-
+- if (pRPort->Net->LinksUp >= 2) {
+- if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) {
+- /* Build the check chain. */
+- SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
+- }
+- }
+-
+- /* If the first link comes up, start the periodical RLMT timeout. */
+- if (pRPort->Net->NumPorts > 1 && pRPort->Net->LinksUp == 1 &&
+- (pRPort->Net->RlmtMode & SK_RLMT_CHECK_OTHERS) != 0) {
+- Para2.Para32[0] = pRPort->Net->NetNumber;
+- Para2.Para32[1] = (SK_U32)-1;
+- SkTimerStart(pAC, IoC, &pRPort->Net->LocTimer,
+- pRPort->Net->TimeoutValue, SKGE_RLMT, SK_RLMT_TIM, Para2);
+- }
+-
+- Para2 = Para;
+- Para2.Para32[1] = (SK_U32)-1;
+- SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL,
+- SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para2);
+-
+- /* Later: if (pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_LOC_LINK) && */
+- if ((pRPort->Net->RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
+- (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LINK) != 0 &&
+- (Para2.pParaPtr =
+- SkRlmtBuildPacket(pAC, IoC, Para.Para32[0], SK_PACKET_ANNOUNCE,
+- &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress, &SkRlmtMcAddr)
+- ) != NULL) {
+- /* Send "new" packet to RLMT multicast address. */
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
+- }
+-
+- if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_SEG) {
+- if ((Para2.pParaPtr =
+- SkRlmtBuildSpanningTreePacket(pAC, IoC, Para.Para32[0])) != NULL) {
+- pAC->Rlmt.Port[Para.Para32[0]].RootIdSet = SK_FALSE;
+- pRPort->Net->CheckingState |=
+- SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG;
+-
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
+-
+- Para.Para32[1] = (SK_U32)-1;
+- SkTimerStart(pAC, IoC, &pRPort->Net->SegTimer,
+- SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para);
+- }
+- }
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_LINK_UP Event END.\n"))
+-} /* SkRlmtEvtLinkUp */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtEvtPortUpTim - PORT_UP_TIM
+- *
+- * Description:
+- * This routine handles PORT_UP_TIM events.
+- *
+- * Context:
+- * runtime, pageable?
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * Nothing
+- */
+-RLMT_STATIC void SkRlmtEvtPortUpTim(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */
+-{
+- SK_RLMT_PORT *pRPort;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORTUP_TIM Port %d Event BEGIN.\n", Para.Para32[0]))
+-
+- if (Para.Para32[1] != (SK_U32)-1) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad Parameter.\n"))
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORTUP_TIM Event EMPTY.\n"))
+- return;
+- }
+-
+- pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
+- if (pRPort->LinkDown || (pRPort->PortState == SK_RLMT_PS_UP)) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORTUP_TIM Port %d Event EMPTY.\n", Para.Para32[0]))
+- return;
+- }
+-
+- pRPort->PortDown = SK_FALSE;
+- pRPort->PortState = SK_RLMT_PS_UP;
+- pRPort->Net->PortsUp++;
+- if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) {
+- if (pAC->Rlmt.NumNets <= 1) {
+- SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
+- }
+- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_UP, Para);
+- }
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORTUP_TIM Event END.\n"))
+-} /* SkRlmtEvtPortUpTim */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtEvtPortDownTim - PORT_DOWN_*
+- *
+- * Description:
+- * This routine handles PORT_DOWN_* events.
+- *
+- * Context:
+- * runtime, pageable?
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * Nothing
+- */
+-RLMT_STATIC void SkRlmtEvtPortDownX(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_U32 Event, /* Event code */
+-SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */
+-{
+- SK_RLMT_PORT *pRPort;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORTDOWN* Port %d Event (%d) BEGIN.\n",
+- Para.Para32[0], Event))
+-
+- if (Para.Para32[1] != (SK_U32)-1) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad Parameter.\n"))
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORTDOWN* Event EMPTY.\n"))
+- return;
+- }
+-
+- pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
+- if (!pRPort->PortStarted || (Event == SK_RLMT_PORTDOWN_TX_TIM &&
+- !(pRPort->CheckingState & SK_RLMT_PCS_TX))) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORTDOWN* Event (%d) EMPTY.\n", Event))
+- return;
+- }
+-
+- /* Stop port's timers. */
+- SkTimerStop(pAC, IoC, &pRPort->UpTimer);
+- SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
+- SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
+-
+- if (pRPort->PortState != SK_RLMT_PS_LINK_DOWN) {
+- pRPort->PortState = SK_RLMT_PS_DOWN;
+- }
+-
+- if (!pRPort->PortDown) {
+- pRPort->Net->PortsUp--;
+- pRPort->PortDown = SK_TRUE;
+- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_DOWN, Para);
+- }
+-
+- pRPort->PacketsPerTimeSlot = 0;
+- /* pRPort->DataPacketsPerTimeSlot = 0; */
+- pRPort->BpduPacketsPerTimeSlot = 0;
+- pRPort->BcTimeStamp = 0;
+-
+- /*
+- * RA;:;: To be checked:
+- * - actions at RLMT_STOP: We should not switch anymore.
+- */
+- if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) {
+- if (Para.Para32[0] ==
+- pRPort->Net->Port[pRPort->Net->ActivePort]->PortNumber) {
+- /* Active Port went down. */
+- SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
+- }
+- }
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORTDOWN* Event (%d) END.\n", Event))
+-} /* SkRlmtEvtPortDownX */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtEvtLinkDown - LINK_DOWN
+- *
+- * Description:
+- * This routine handles LINK_DOWN events.
+- *
+- * Context:
+- * runtime, pageable?
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * Nothing
+- */
+-RLMT_STATIC void SkRlmtEvtLinkDown(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 Undefined */
+-{
+- SK_RLMT_PORT *pRPort;
+-
+- pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_LINK_DOWN Port %d Event BEGIN.\n", Para.Para32[0]))
+-
+- if (!pAC->Rlmt.Port[Para.Para32[0]].LinkDown) {
+- pRPort->Net->LinksUp--;
+- pRPort->LinkDown = SK_TRUE;
+- pRPort->PortState = SK_RLMT_PS_LINK_DOWN;
+- SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_OFF);
+-
+- if ((pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) != 0) {
+- /* Build the check chain. */
+- SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
+- }
+-
+- /* Ensure that port is marked down. */
+- Para.Para32[1] = -1;
+- (void)SkRlmtEvent(pAC, IoC, SK_RLMT_PORTDOWN, Para);
+- }
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_LINK_DOWN Event END.\n"))
+-} /* SkRlmtEvtLinkDown */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtEvtPortAddr - PORT_ADDR
+- *
+- * Description:
+- * This routine handles PORT_ADDR events.
+- *
+- * Context:
+- * runtime, pageable?
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * Nothing
+- */
+-RLMT_STATIC void SkRlmtEvtPortAddr(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */
+-{
+- SK_U32 i, j;
+- SK_RLMT_PORT *pRPort;
+- SK_MAC_ADDR *pOldMacAddr;
+- SK_MAC_ADDR *pNewMacAddr;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORT_ADDR Port %d Event BEGIN.\n", Para.Para32[0]))
+-
+- if (Para.Para32[1] != (SK_U32)-1) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad Parameter.\n"))
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORT_ADDR Event EMPTY.\n"))
+- return;
+- }
+-
+- /* Port's physical MAC address changed. */
+- pOldMacAddr = &pAC->Addr.Port[Para.Para32[0]].PreviousMacAddress;
+- pNewMacAddr = &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress;
+-
+- /*
+- * NOTE: This is not scalable for solutions where ports are
+- * checked remotely. There, we need to send an RLMT
+- * address change packet - and how do we ensure delivery?
+- */
+- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+- pRPort = &pAC->Rlmt.Port[i];
+- for (j = 0; j < pRPort->PortsChecked; j++) {
+- if (SK_ADDR_EQUAL(
+- pRPort->PortCheck[j].CheckAddr.a, pOldMacAddr->a)) {
+- pRPort->PortCheck[j].CheckAddr = *pNewMacAddr;
+- }
+- }
+- }
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORT_ADDR Event END.\n"))
+-} /* SkRlmtEvtPortAddr */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtEvtStart - START
+- *
+- * Description:
+- * This routine handles START events.
+- *
+- * Context:
+- * runtime, pageable?
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * Nothing
+- */
+-RLMT_STATIC void SkRlmtEvtStart(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */
+-{
+- SK_EVPARA Para2;
+- SK_U32 PortIdx;
+- SK_U32 PortNumber;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_START Net %d Event BEGIN.\n", Para.Para32[0]))
+-
+- if (Para.Para32[1] != (SK_U32)-1) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad Parameter.\n"))
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_START Event EMPTY.\n"))
+- return;
+- }
+-
+- if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad NetNumber %d.\n", Para.Para32[0]))
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_START Event EMPTY.\n"))
+- return;
+- }
+-
+- if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState != SK_RLMT_RS_INIT) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_START Event EMPTY.\n"))
+- return;
+- }
+-
+- if (pAC->Rlmt.NetsStarted >= pAC->Rlmt.NumNets) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("All nets should have been started.\n"))
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_START Event EMPTY.\n"))
+- return;
+- }
+-
+- if (pAC->Rlmt.Net[Para.Para32[0]].PrefPort >=
+- pAC->Rlmt.Net[Para.Para32[0]].NumPorts) {
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E009, SKERR_RLMT_E009_MSG);
+-
+- /* Change PrefPort to internal default. */
+- Para2.Para32[0] = 0xFFFFFFFF;
+- Para2.Para32[1] = Para.Para32[0];
+- (void)SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE, Para2);
+- }
+-
+- PortIdx = pAC->Rlmt.Net[Para.Para32[0]].PrefPort;
+- PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[PortIdx]->PortNumber;
+-
+- pAC->Rlmt.Net[Para.Para32[0]].LinksUp = 0;
+- pAC->Rlmt.Net[Para.Para32[0]].PortsUp = 0;
+- pAC->Rlmt.Net[Para.Para32[0]].CheckingState = 0;
+- pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_NET_DOWN;
+-
+- /* Start preferred port. */
+- SkRlmtPortStart(pAC, IoC, PortNumber);
+-
+- /* Start Timer (for first port only). */
+- Para2.Para32[0] = PortNumber;
+- Para2.Para32[1] = (SK_U32)-1;
+- SkTimerStart(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer,
+- SK_RLMT_PORTSTART_TIM_VAL, SKGE_RLMT, SK_RLMT_PORTSTART_TIM, Para2);
+-
+- pAC->Rlmt.NetsStarted++;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_START Event END.\n"))
+-} /* SkRlmtEvtStart */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtEvtStop - STOP
+- *
+- * Description:
+- * This routine handles STOP events.
+- *
+- * Context:
+- * runtime, pageable?
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * Nothing
+- */
+-RLMT_STATIC void SkRlmtEvtStop(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */
+-{
+- SK_EVPARA Para2;
+- SK_U32 PortNumber;
+- SK_U32 i;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STOP Net %d Event BEGIN.\n", Para.Para32[0]))
+-
+- if (Para.Para32[1] != (SK_U32)-1) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad Parameter.\n"))
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STOP Event EMPTY.\n"))
+- return;
+- }
+-
+- if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad NetNumber %d.\n", Para.Para32[0]))
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STOP Event EMPTY.\n"))
+- return;
+- }
+-
+- if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState == SK_RLMT_RS_INIT) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STOP Event EMPTY.\n"))
+- return;
+- }
+-
+- if (pAC->Rlmt.NetsStarted == 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("All nets are stopped.\n"))
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STOP Event EMPTY.\n"))
+- return;
+- }
+-
+- /* Stop RLMT timers. */
+- SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer);
+- SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer);
+-
+- /* Stop net. */
+- pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_INIT;
+- pAC->Rlmt.Net[Para.Para32[0]].RootIdSet = SK_FALSE;
+- Para2.Para32[0] = SK_RLMT_NET_DOWN_FINAL;
+- Para2.Para32[1] = Para.Para32[0]; /* Net# */
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para2);
+-
+- /* Stop ports. */
+- for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
+- PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber;
+- if (pAC->Rlmt.Port[PortNumber].PortState != SK_RLMT_PS_INIT) {
+- SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer);
+- SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownRxTimer);
+- SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownTxTimer);
+-
+- pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_INIT;
+- pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE;
+- pAC->Rlmt.Port[PortNumber].PortStarted = SK_FALSE;
+- Para2.Para32[0] = PortNumber;
+- Para2.Para32[1] = (SK_U32)-1;
+- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para2);
+- }
+- }
+-
+- pAC->Rlmt.NetsStarted--;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STOP Event END.\n"))
+-} /* SkRlmtEvtStop */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtEvtTim - TIM
+- *
+- * Description:
+- * This routine handles TIM events.
+- *
+- * Context:
+- * runtime, pageable?
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * Nothing
+- */
+-RLMT_STATIC void SkRlmtEvtTim(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */
+-{
+- SK_RLMT_PORT *pRPort;
+- SK_U32 Timeout;
+- SK_U32 NewTimeout;
+- SK_U32 PortNumber;
+- SK_U32 i;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_TIM Event BEGIN.\n"))
+-
+- if (Para.Para32[1] != (SK_U32)-1) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad Parameter.\n"))
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_TIM Event EMPTY.\n"))
+- return;
+- }
+-
+- if ((pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_OTHERS) == 0 ||
+- pAC->Rlmt.Net[Para.Para32[0]].LinksUp == 0) {
+- /* Mode changed or all links down: No more link checking. */
+- return;
+- }
+-
+-#if 0
+- pAC->Rlmt.SwitchCheckCounter--;
+- if (pAC->Rlmt.SwitchCheckCounter == 0) {
+- pAC->Rlmt.SwitchCheckCounter;
+- }
+-#endif /* 0 */
+-
+- NewTimeout = SK_RLMT_DEF_TO_VAL;
+- for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
+- PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber;
+- pRPort = &pAC->Rlmt.Port[PortNumber];
+- if (!pRPort->LinkDown) {
+- Timeout = SkRlmtCheckPort(pAC, IoC, PortNumber);
+- if (Timeout < NewTimeout) {
+- NewTimeout = Timeout;
+- }
+-
+- /*
+- * These counters should be set to 0 for all ports before the
+- * first frame is sent in the next loop.
+- */
+- pRPort->PacketsPerTimeSlot = 0;
+- /* pRPort->DataPacketsPerTimeSlot = 0; */
+- pRPort->BpduPacketsPerTimeSlot = 0;
+- }
+- }
+- pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue = NewTimeout;
+-
+- if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1) {
+- /*
+- * If checking remote ports, also send packets if
+- * (LinksUp == 1) &&
+- * this port checks at least one (remote) port.
+- */
+-
+- /*
+- * Must be new loop, as SkRlmtCheckPort can request to
+- * check segmentation when e.g. checking the last port.
+- */
+- for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
+- if (!pAC->Rlmt.Net[Para.Para32[0]].Port[i]->LinkDown) {
+- SkRlmtSend(pAC, IoC,
+- pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber);
+- }
+- }
+- }
+-
+- SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer,
+- pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue, SKGE_RLMT, SK_RLMT_TIM,
+- Para);
+-
+- if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1 &&
+- (pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_SEG) &&
+- (pAC->Rlmt.Net[Para.Para32[0]].CheckingState & SK_RLMT_RCS_START_SEG)) {
+- SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer,
+- SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para);
+- pAC->Rlmt.Net[Para.Para32[0]].CheckingState &= ~SK_RLMT_RCS_START_SEG;
+- pAC->Rlmt.Net[Para.Para32[0]].CheckingState |=
+- SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG;
+- }
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_TIM Event END.\n"))
+-} /* SkRlmtEvtTim */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtEvtSegTim - SEG_TIM
+- *
+- * Description:
+- * This routine handles SEG_TIM events.
+- *
+- * Context:
+- * runtime, pageable?
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * Nothing
+- */
+-RLMT_STATIC void SkRlmtEvtSegTim(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */
+-{
+-#ifdef xDEBUG
+- int j;
+-#endif /* DEBUG */
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SEG_TIM Event BEGIN.\n"))
+-
+- if (Para.Para32[1] != (SK_U32)-1) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad Parameter.\n"))
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SEG_TIM Event EMPTY.\n"))
+- return;
+- }
+-
+-#ifdef xDEBUG
+- for (j = 0; j < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; j++) {
+- SK_ADDR_PORT *pAPort;
+- SK_U32 k;
+- SK_U16 *InAddr;
+- SK_U8 InAddr8[6];
+-
+- InAddr = (SK_U16 *)&InAddr8[0];
+- pAPort = pAC->Rlmt.Net[Para.Para32[0]].Port[j]->AddrPort;
+- for (k = 0; k < pAPort->NextExactMatchRlmt; k++) {
+- /* Get exact match address k from port j. */
+- XM_INADDR(IoC, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber,
+- XM_EXM(k), InAddr);
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("MC address %d on Port %u: %02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x.\n",
+- k, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber,
+- InAddr8[0], InAddr8[1], InAddr8[2],
+- InAddr8[3], InAddr8[4], InAddr8[5],
+- pAPort->Exact[k].a[0], pAPort->Exact[k].a[1],
+- pAPort->Exact[k].a[2], pAPort->Exact[k].a[3],
+- pAPort->Exact[k].a[4], pAPort->Exact[k].a[5]))
+- }
+- }
+-#endif /* xDEBUG */
+-
+- SkRlmtCheckSeg(pAC, IoC, Para.Para32[0]);
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SEG_TIM Event END.\n"))
+-} /* SkRlmtEvtSegTim */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtEvtPacketRx - PACKET_RECEIVED
+- *
+- * Description:
+- * This routine handles PACKET_RECEIVED events.
+- *
+- * Context:
+- * runtime, pageable?
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * Nothing
+- */
+-RLMT_STATIC void SkRlmtEvtPacketRx(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_EVPARA Para) /* SK_MBUF *pMb */
+-{
+- SK_MBUF *pMb;
+- SK_MBUF *pNextMb;
+- SK_U32 NetNumber;
+-
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PACKET_RECEIVED Event BEGIN.\n"))
+-
+- /* Should we ignore frames during port switching? */
+-
+-#ifdef DEBUG
+- pMb = Para.pParaPtr;
+- if (pMb == NULL) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("No mbuf.\n"))
+- }
+- else if (pMb->pNext != NULL) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("More than one mbuf or pMb->pNext not set.\n"))
+- }
+-#endif /* DEBUG */
+-
+- for (pMb = Para.pParaPtr; pMb != NULL; pMb = pNextMb) {
+- pNextMb = pMb->pNext;
+- pMb->pNext = NULL;
+-
+- NetNumber = pAC->Rlmt.Port[pMb->PortIdx].Net->NetNumber;
+- if (pAC->Rlmt.Net[NetNumber].RlmtState == SK_RLMT_RS_INIT) {
+- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+- }
+- else {
+- SkRlmtPacketReceive(pAC, IoC, pMb);
+- }
+- }
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PACKET_RECEIVED Event END.\n"))
+-} /* SkRlmtEvtPacketRx */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtEvtStatsClear - STATS_CLEAR
+- *
+- * Description:
+- * This routine handles STATS_CLEAR events.
+- *
+- * Context:
+- * runtime, pageable?
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * Nothing
+- */
+-RLMT_STATIC void SkRlmtEvtStatsClear(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */
+-{
+- SK_U32 i;
+- SK_RLMT_PORT *pRPort;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STATS_CLEAR Event BEGIN.\n"))
+-
+- if (Para.Para32[1] != (SK_U32)-1) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad Parameter.\n"))
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STATS_CLEAR Event EMPTY.\n"))
+- return;
+- }
+-
+- if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad NetNumber %d.\n", Para.Para32[0]))
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STATS_CLEAR Event EMPTY.\n"))
+- return;
+- }
+-
+- /* Clear statistics for logical and physical ports. */
+- for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
+- pRPort =
+- &pAC->Rlmt.Port[pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber];
+- pRPort->TxHelloCts = 0;
+- pRPort->RxHelloCts = 0;
+- pRPort->TxSpHelloReqCts = 0;
+- pRPort->RxSpHelloCts = 0;
+- }
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STATS_CLEAR Event END.\n"))
+-} /* SkRlmtEvtStatsClear */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtEvtStatsUpdate - STATS_UPDATE
+- *
+- * Description:
+- * This routine handles STATS_UPDATE events.
+- *
+- * Context:
+- * runtime, pageable?
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * Nothing
+- */
+-RLMT_STATIC void SkRlmtEvtStatsUpdate(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */
+-{
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STATS_UPDATE Event BEGIN.\n"))
+-
+- if (Para.Para32[1] != (SK_U32)-1) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad Parameter.\n"))
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STATS_UPDATE Event EMPTY.\n"))
+- return;
+- }
+-
+- if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad NetNumber %d.\n", Para.Para32[0]))
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STATS_UPDATE Event EMPTY.\n"))
+- return;
+- }
+-
+- /* Update statistics - currently always up-to-date. */
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STATS_UPDATE Event END.\n"))
+-} /* SkRlmtEvtStatsUpdate */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtEvtPrefportChange - PREFPORT_CHANGE
+- *
+- * Description:
+- * This routine handles PREFPORT_CHANGE events.
+- *
+- * Context:
+- * runtime, pageable?
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * Nothing
+- */
+-RLMT_STATIC void SkRlmtEvtPrefportChange(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_EVPARA Para) /* SK_U32 PortIndex; SK_U32 NetNumber */
+-{
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PREFPORT_CHANGE to Port %d Event BEGIN.\n", Para.Para32[0]))
+-
+- if (Para.Para32[1] >= pAC->Rlmt.NumNets) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad NetNumber %d.\n", Para.Para32[1]))
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n"))
+- return;
+- }
+-
+- /* 0xFFFFFFFF == auto-mode. */
+- if (Para.Para32[0] == 0xFFFFFFFF) {
+- pAC->Rlmt.Net[Para.Para32[1]].PrefPort = SK_RLMT_DEF_PREF_PORT;
+- }
+- else {
+- if (Para.Para32[0] >= pAC->Rlmt.Net[Para.Para32[1]].NumPorts) {
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E010, SKERR_RLMT_E010_MSG);
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n"))
+- return;
+- }
+-
+- pAC->Rlmt.Net[Para.Para32[1]].PrefPort = Para.Para32[0];
+- }
+-
+- pAC->Rlmt.Net[Para.Para32[1]].Preference = Para.Para32[0];
+-
+- if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) {
+- SkRlmtCheckSwitch(pAC, IoC, Para.Para32[1]);
+- }
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PREFPORT_CHANGE Event END.\n"))
+-} /* SkRlmtEvtPrefportChange */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtEvtSetNets - SET_NETS
+- *
+- * Description:
+- * This routine handles SET_NETS events.
+- *
+- * Context:
+- * runtime, pageable?
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * Nothing
+- */
+-RLMT_STATIC void SkRlmtEvtSetNets(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_EVPARA Para) /* SK_U32 NumNets; SK_U32 -1 */
+-{
+- int i;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SET_NETS Event BEGIN.\n"))
+-
+- if (Para.Para32[1] != (SK_U32)-1) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad Parameter.\n"))
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SET_NETS Event EMPTY.\n"))
+- return;
+- }
+-
+- if (Para.Para32[0] == 0 || Para.Para32[0] > SK_MAX_NETS ||
+- Para.Para32[0] > (SK_U32)pAC->GIni.GIMacsFound) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad number of nets: %d.\n", Para.Para32[0]))
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SET_NETS Event EMPTY.\n"))
+- return;
+- }
+-
+- if (Para.Para32[0] == pAC->Rlmt.NumNets) { /* No change. */
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SET_NETS Event EMPTY.\n"))
+- return;
+- }
+-
+- /* Entering and leaving dual mode only allowed while nets are stopped. */
+- if (pAC->Rlmt.NetsStarted > 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Changing dual mode only allowed while all nets are stopped.\n"))
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SET_NETS Event EMPTY.\n"))
+- return;
+- }
+-
+- if (Para.Para32[0] == 1) {
+- if (pAC->Rlmt.NumNets > 1) {
+- /* Clear logical MAC addr from second net's active port. */
+- (void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr.
+- Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_CLEAR_LOGICAL);
+- pAC->Rlmt.Net[1].NumPorts = 0;
+- }
+-
+- pAC->Rlmt.NumNets = Para.Para32[0];
+- for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) {
+- pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT;
+- pAC->Rlmt.Net[i].RootIdSet = SK_FALSE;
+- pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* "Automatic" */
+- pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT;
+- /* Just assuming. */
+- pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort;
+- pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE;
+- pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL;
+- pAC->Rlmt.Net[i].NetNumber = i;
+- }
+-
+- pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[0];
+- pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound;
+-
+- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para);
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("RLMT: Changed to one net with two ports.\n"))
+- }
+- else if (Para.Para32[0] == 2) {
+- pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[1];
+- pAC->Rlmt.Net[1].NumPorts = pAC->GIni.GIMacsFound - 1;
+- pAC->Rlmt.Net[0].NumPorts =
+- pAC->GIni.GIMacsFound - pAC->Rlmt.Net[1].NumPorts;
+-
+- pAC->Rlmt.NumNets = Para.Para32[0];
+- for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) {
+- pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT;
+- pAC->Rlmt.Net[i].RootIdSet = SK_FALSE;
+- pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* "Automatic" */
+- pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT;
+- /* Just assuming. */
+- pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort;
+- pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE;
+- pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL;
+-
+- pAC->Rlmt.Net[i].NetNumber = i;
+- }
+-
+- /* Set logical MAC addr on second net's active port. */
+- (void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr.
+- Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_SET_LOGICAL);
+-
+- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para);
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("RLMT: Changed to two nets with one port each.\n"))
+- }
+- else {
+- /* Not implemented for more than two nets. */
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SetNets not implemented for more than two nets.\n"))
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SET_NETS Event EMPTY.\n"))
+- return;
+- }
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SET_NETS Event END.\n"))
+-} /* SkRlmtSetNets */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtEvtModeChange - MODE_CHANGE
+- *
+- * Description:
+- * This routine handles MODE_CHANGE events.
+- *
+- * Context:
+- * runtime, pageable?
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * Nothing
+- */
+-RLMT_STATIC void SkRlmtEvtModeChange(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_EVPARA Para) /* SK_U32 NewMode; SK_U32 NetNumber */
+-{
+- SK_EVPARA Para2;
+- SK_U32 i;
+- SK_U32 PrevRlmtMode;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_MODE_CHANGE Event BEGIN.\n"))
+-
+- if (Para.Para32[1] >= pAC->Rlmt.NumNets) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad NetNumber %d.\n", Para.Para32[1]))
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_MODE_CHANGE Event EMPTY.\n"))
+- return;
+- }
+-
+- Para.Para32[0] |= SK_RLMT_CHECK_LINK;
+-
+- if ((pAC->Rlmt.Net[Para.Para32[1]].NumPorts == 1) &&
+- Para.Para32[0] != SK_RLMT_MODE_CLS) {
+- pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = SK_RLMT_MODE_CLS;
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Forced RLMT mode to CLS on single port net.\n"))
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_MODE_CHANGE Event EMPTY.\n"))
+- return;
+- }
+-
+- /* Update RLMT mode. */
+- PrevRlmtMode = pAC->Rlmt.Net[Para.Para32[1]].RlmtMode;
+- pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = Para.Para32[0];
+-
+- if ((PrevRlmtMode & SK_RLMT_CHECK_LOC_LINK) !=
+- (pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) {
+- /* SK_RLMT_CHECK_LOC_LINK bit changed. */
+- if ((PrevRlmtMode & SK_RLMT_CHECK_OTHERS) == 0 &&
+- pAC->Rlmt.Net[Para.Para32[1]].NumPorts > 1 &&
+- pAC->Rlmt.Net[Para.Para32[1]].PortsUp >= 1) {
+- /* 20001207 RA: Was "PortsUp == 1". */
+- Para2.Para32[0] = Para.Para32[1];
+- Para2.Para32[1] = (SK_U32)-1;
+- SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].LocTimer,
+- pAC->Rlmt.Net[Para.Para32[1]].TimeoutValue,
+- SKGE_RLMT, SK_RLMT_TIM, Para2);
+- }
+- }
+-
+- if ((PrevRlmtMode & SK_RLMT_CHECK_SEG) !=
+- (pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG)) {
+- /* SK_RLMT_CHECK_SEG bit changed. */
+- for (i = 0; i < pAC->Rlmt.Net[Para.Para32[1]].NumPorts; i++) {
+- (void)SkAddrMcClear(pAC, IoC,
+- pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber,
+- SK_ADDR_PERMANENT | SK_MC_SW_ONLY);
+-
+- /* Add RLMT MC address. */
+- (void)SkAddrMcAdd(pAC, IoC,
+- pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber,
+- &SkRlmtMcAddr, SK_ADDR_PERMANENT);
+-
+- if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode &
+- SK_RLMT_CHECK_SEG) != 0) {
+- /* Add BPDU MC address. */
+- (void)SkAddrMcAdd(pAC, IoC,
+- pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber,
+- &BridgeMcAddr, SK_ADDR_PERMANENT);
+-
+- if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) {
+- if (!pAC->Rlmt.Net[Para.Para32[1]].Port[i]->LinkDown &&
+- (Para2.pParaPtr = SkRlmtBuildSpanningTreePacket(
+- pAC, IoC, i)) != NULL) {
+- pAC->Rlmt.Net[Para.Para32[1]].Port[i]->RootIdSet =
+- SK_FALSE;
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
+- }
+- }
+- }
+- (void)SkAddrMcUpdate(pAC, IoC,
+- pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber);
+- } /* for ... */
+-
+- if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG) != 0) {
+- Para2.Para32[0] = Para.Para32[1];
+- Para2.Para32[1] = (SK_U32)-1;
+- SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].SegTimer,
+- SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para2);
+- }
+- } /* SK_RLMT_CHECK_SEG bit changed. */
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_MODE_CHANGE Event END.\n"))
+-} /* SkRlmtEvtModeChange */
+-
+-
+-/******************************************************************************
+- *
+- * SkRlmtEvent - a PORT- or an RLMT-specific event happened
+- *
+- * Description:
+- * This routine calls subroutines to handle PORT- and RLMT-specific events.
+- *
+- * Context:
+- * runtime, pageable?
+- * may be called after SK_INIT_IO
+- *
+- * Returns:
+- * 0
+- */
+-int SkRlmtEvent(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_U32 Event, /* Event code */
+-SK_EVPARA Para) /* Event-specific parameter */
+-{
+- switch (Event) {
+-
+- /* ----- PORT events ----- */
+-
+- case SK_RLMT_PORTSTART_TIM: /* From RLMT via TIME. */
+- SkRlmtEvtPortStartTim(pAC, IoC, Para);
+- break;
+- case SK_RLMT_LINK_UP: /* From SIRQ. */
+- SkRlmtEvtLinkUp(pAC, IoC, Para);
+- break;
+- case SK_RLMT_PORTUP_TIM: /* From RLMT via TIME. */
+- SkRlmtEvtPortUpTim(pAC, IoC, Para);
+- break;
+- case SK_RLMT_PORTDOWN: /* From RLMT. */
+- case SK_RLMT_PORTDOWN_RX_TIM: /* From RLMT via TIME. */
+- case SK_RLMT_PORTDOWN_TX_TIM: /* From RLMT via TIME. */
+- SkRlmtEvtPortDownX(pAC, IoC, Event, Para);
+- break;
+- case SK_RLMT_LINK_DOWN: /* From SIRQ. */
+- SkRlmtEvtLinkDown(pAC, IoC, Para);
+- break;
+- case SK_RLMT_PORT_ADDR: /* From ADDR. */
+- SkRlmtEvtPortAddr(pAC, IoC, Para);
+- break;
+-
+- /* ----- RLMT events ----- */
+-
+- case SK_RLMT_START: /* From DRV. */
+- SkRlmtEvtStart(pAC, IoC, Para);
+- break;
+- case SK_RLMT_STOP: /* From DRV. */
+- SkRlmtEvtStop(pAC, IoC, Para);
+- break;
+- case SK_RLMT_TIM: /* From RLMT via TIME. */
+- SkRlmtEvtTim(pAC, IoC, Para);
+- break;
+- case SK_RLMT_SEG_TIM:
+- SkRlmtEvtSegTim(pAC, IoC, Para);
+- break;
+- case SK_RLMT_PACKET_RECEIVED: /* From DRV. */
+- SkRlmtEvtPacketRx(pAC, IoC, Para);
+- break;
+- case SK_RLMT_STATS_CLEAR: /* From PNMI. */
+- SkRlmtEvtStatsClear(pAC, IoC, Para);
+- break;
+- case SK_RLMT_STATS_UPDATE: /* From PNMI. */
+- SkRlmtEvtStatsUpdate(pAC, IoC, Para);
+- break;
+- case SK_RLMT_PREFPORT_CHANGE: /* From PNMI. */
+- SkRlmtEvtPrefportChange(pAC, IoC, Para);
+- break;
+- case SK_RLMT_MODE_CHANGE: /* From PNMI. */
+- SkRlmtEvtModeChange(pAC, IoC, Para);
+- break;
+- case SK_RLMT_SET_NETS: /* From DRV. */
+- SkRlmtEvtSetNets(pAC, IoC, Para);
+- break;
+-
+- /* ----- Unknown events ----- */
+-
+- default: /* Create error log entry. */
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Unknown RLMT Event %d.\n", Event))
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E003, SKERR_RLMT_E003_MSG);
+- break;
+- } /* switch() */
+-
+- return (0);
+-} /* SkRlmtEvent */
+-
+-#ifdef __cplusplus
+-}
+-#endif /* __cplusplus */
+diff --git a/drivers/net/sk98lin/sktimer.c b/drivers/net/sk98lin/sktimer.c
+deleted file mode 100644
+index 4e46295..0000000
+--- a/drivers/net/sk98lin/sktimer.c
++++ /dev/null
+@@ -1,250 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: sktimer.c
+- * Project: Gigabit Ethernet Adapters, Event Scheduler Module
+- * Version: $Revision: 1.14 $
+- * Date: $Date: 2003/09/16 13:46:51 $
+- * Purpose: High level timer functions.
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-
+-/*
+- * Event queue and dispatcher
+- */
+-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+-static const char SysKonnectFileId[] =
+- "@(#) $Id: sktimer.c,v 1.14 2003/09/16 13:46:51 rschmidt Exp $ (C) Marvell.";
+-#endif
+-
+-#include "h/skdrv1st.h" /* Driver Specific Definitions */
+-#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
+-
+-#ifdef __C2MAN__
+-/*
+- Event queue management.
+-
+- General Description:
+-
+- */
+-intro()
+-{}
+-#endif
+-
+-
+-/* Forward declaration */
+-static void timer_done(SK_AC *pAC,SK_IOC Ioc,int Restart);
+-
+-
+-/*
+- * Inits the software timer
+- *
+- * needs to be called during Init level 1.
+- */
+-void SkTimerInit(
+-SK_AC *pAC, /* Adapters context */
+-SK_IOC Ioc, /* IoContext */
+-int Level) /* Init Level */
+-{
+- switch (Level) {
+- case SK_INIT_DATA:
+- pAC->Tim.StQueue = NULL;
+- break;
+- case SK_INIT_IO:
+- SkHwtInit(pAC, Ioc);
+- SkTimerDone(pAC, Ioc);
+- break;
+- default:
+- break;
+- }
+-}
+-
+-/*
+- * Stops a high level timer
+- * - If a timer is not in the queue the function returns normally, too.
+- */
+-void SkTimerStop(
+-SK_AC *pAC, /* Adapters context */
+-SK_IOC Ioc, /* IoContext */
+-SK_TIMER *pTimer) /* Timer Pointer to be started */
+-{
+- SK_TIMER **ppTimPrev;
+- SK_TIMER *pTm;
+-
+- /*
+- * remove timer from queue
+- */
+- pTimer->TmActive = SK_FALSE;
+-
+- if (pAC->Tim.StQueue == pTimer && !pTimer->TmNext) {
+- SkHwtStop(pAC, Ioc);
+- }
+-
+- for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev);
+- ppTimPrev = &pTm->TmNext ) {
+-
+- if (pTm == pTimer) {
+- /*
+- * Timer found in queue
+- * - dequeue it and
+- * - correct delta of the next timer
+- */
+- *ppTimPrev = pTm->TmNext;
+-
+- if (pTm->TmNext) {
+- /* correct delta of next timer in queue */
+- pTm->TmNext->TmDelta += pTm->TmDelta;
+- }
+- return;
+- }
+- }
+-}
+-
+-/*
+- * Start a high level software timer
+- */
+-void SkTimerStart(
+-SK_AC *pAC, /* Adapters context */
+-SK_IOC Ioc, /* IoContext */
+-SK_TIMER *pTimer, /* Timer Pointer to be started */
+-SK_U32 Time, /* Time value */
+-SK_U32 Class, /* Event Class for this timer */
+-SK_U32 Event, /* Event Value for this timer */
+-SK_EVPARA Para) /* Event Parameter for this timer */
+-{
+- SK_TIMER **ppTimPrev;
+- SK_TIMER *pTm;
+- SK_U32 Delta;
+-
+- Time /= 16; /* input is uS, clock ticks are 16uS */
+-
+- if (!Time)
+- Time = 1;
+-
+- SkTimerStop(pAC, Ioc, pTimer);
+-
+- pTimer->TmClass = Class;
+- pTimer->TmEvent = Event;
+- pTimer->TmPara = Para;
+- pTimer->TmActive = SK_TRUE;
+-
+- if (!pAC->Tim.StQueue) {
+- /* First Timer to be started */
+- pAC->Tim.StQueue = pTimer;
+- pTimer->TmNext = NULL;
+- pTimer->TmDelta = Time;
+-
+- SkHwtStart(pAC, Ioc, Time);
+-
+- return;
+- }
+-
+- /*
+- * timer correction
+- */
+- timer_done(pAC, Ioc, 0);
+-
+- /*
+- * find position in queue
+- */
+- Delta = 0;
+- for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev);
+- ppTimPrev = &pTm->TmNext ) {
+-
+- if (Delta + pTm->TmDelta > Time) {
+- /* Position found */
+- /* Here the timer needs to be inserted. */
+- break;
+- }
+- Delta += pTm->TmDelta;
+- }
+-
+- /* insert in queue */
+- *ppTimPrev = pTimer;
+- pTimer->TmNext = pTm;
+- pTimer->TmDelta = Time - Delta;
+-
+- if (pTm) {
+- /* There is a next timer
+- * -> correct its Delta value.
+- */
+- pTm->TmDelta -= pTimer->TmDelta;
+- }
+-
+- /* restart with first */
+- SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta);
+-}
+-
+-
+-void SkTimerDone(
+-SK_AC *pAC, /* Adapters context */
+-SK_IOC Ioc) /* IoContext */
+-{
+- timer_done(pAC, Ioc, 1);
+-}
+-
+-
+-static void timer_done(
+-SK_AC *pAC, /* Adapters context */
+-SK_IOC Ioc, /* IoContext */
+-int Restart) /* Do we need to restart the Hardware timer ? */
+-{
+- SK_U32 Delta;
+- SK_TIMER *pTm;
+- SK_TIMER *pTComp; /* Timer completed now now */
+- SK_TIMER **ppLast; /* Next field of Last timer to be deq */
+- int Done = 0;
+-
+- Delta = SkHwtRead(pAC, Ioc);
+-
+- ppLast = &pAC->Tim.StQueue;
+- pTm = pAC->Tim.StQueue;
+- while (pTm && !Done) {
+- if (Delta >= pTm->TmDelta) {
+- /* Timer ran out */
+- pTm->TmActive = SK_FALSE;
+- Delta -= pTm->TmDelta;
+- ppLast = &pTm->TmNext;
+- pTm = pTm->TmNext;
+- }
+- else {
+- /* We found the first timer that did not run out */
+- pTm->TmDelta -= Delta;
+- Delta = 0;
+- Done = 1;
+- }
+- }
+- *ppLast = NULL;
+- /*
+- * pTm points to the first Timer that did not run out.
+- * StQueue points to the first Timer that run out.
+- */
+-
+- for ( pTComp = pAC->Tim.StQueue; pTComp; pTComp = pTComp->TmNext) {
+- SkEventQueue(pAC,pTComp->TmClass, pTComp->TmEvent, pTComp->TmPara);
+- }
+-
+- /* Set head of timer queue to the first timer that did not run out */
+- pAC->Tim.StQueue = pTm;
+-
+- if (Restart && pAC->Tim.StQueue) {
+- /* Restart HW timer */
+- SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta);
+- }
+-}
+-
+-/* End of file */
+diff --git a/drivers/net/sk98lin/skvpd.c b/drivers/net/sk98lin/skvpd.c
+deleted file mode 100644
+index 1e662aa..0000000
+--- a/drivers/net/sk98lin/skvpd.c
++++ /dev/null
+@@ -1,1091 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skvpd.c
+- * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.37 $
+- * Date: $Date: 2003/01/13 10:42:45 $
+- * Purpose: Shared software to read and write VPD data
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2003 SysKonnect GmbH.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- Please refer skvpd.txt for information how to include this module
+- */
+-static const char SysKonnectFileId[] =
+- "@(#)$Id: skvpd.c,v 1.37 2003/01/13 10:42:45 rschmidt Exp $ (C) SK";
+-
+-#include "h/skdrv1st.h"
+-#include "h/sktypes.h"
+-#include "h/skdebug.h"
+-#include "h/skdrv2nd.h"
+-
+-/*
+- * Static functions
+- */
+-#ifndef SK_KR_PROTO
+-static SK_VPD_PARA *vpd_find_para(
+- SK_AC *pAC,
+- const char *key,
+- SK_VPD_PARA *p);
+-#else /* SK_KR_PROTO */
+-static SK_VPD_PARA *vpd_find_para();
+-#endif /* SK_KR_PROTO */
+-
+-/*
+- * waits for a completion of a VPD transfer
+- * The VPD transfer must complete within SK_TICKS_PER_SEC/16
+- *
+- * returns 0: success, transfer completes
+- * error exit(9) with a error message
+- */
+-static int VpdWait(
+-SK_AC *pAC, /* Adapters context */
+-SK_IOC IoC, /* IO Context */
+-int event) /* event to wait for (VPD_READ / VPD_write) completion*/
+-{
+- SK_U64 start_time;
+- SK_U16 state;
+-
+- SK_DBG_MSG(pAC,SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+- ("VPD wait for %s\n", event?"Write":"Read"));
+- start_time = SkOsGetTime(pAC);
+- do {
+- if (SkOsGetTime(pAC) - start_time > SK_TICKS_PER_SEC) {
+-
+- /* Bug fix AF: Thu Mar 28 2002
+- * Do not call: VPD_STOP(pAC, IoC);
+- * A pending VPD read cycle can not be aborted by writing
+- * VPD_WRITE to the PCI_VPD_ADR_REG (VPD address register).
+- * Although the write threshold in the OUR-register protects
+- * VPD read only space from being overwritten this does not
+- * protect a VPD read from being `converted` into a VPD write
+- * operation (on the fly). As a consequence the VPD_STOP would
+- * delete VPD read only data. In case of any problems with the
+- * I2C bus we exit the loop here. The I2C read operation can
+- * not be aborted except by a reset (->LR).
+- */
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_FATAL | SK_DBGCAT_ERR,
+- ("ERROR:VPD wait timeout\n"));
+- return(1);
+- }
+-
+- VPD_IN16(pAC, IoC, PCI_VPD_ADR_REG, &state);
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+- ("state = %x, event %x\n",state,event));
+- } while((int)(state & PCI_VPD_FLAG) == event);
+-
+- return(0);
+-}
+-
+-#ifdef SKDIAG
+-
+-/*
+- * Read the dword at address 'addr' from the VPD EEPROM.
+- *
+- * Needed Time: MIN 1,3 ms MAX 2,6 ms
+- *
+- * Note: The DWord is returned in the endianess of the machine the routine
+- * is running on.
+- *
+- * Returns the data read.
+- */
+-SK_U32 VpdReadDWord(
+-SK_AC *pAC, /* Adapters context */
+-SK_IOC IoC, /* IO Context */
+-int addr) /* VPD address */
+-{
+- SK_U32 Rtv;
+-
+- /* start VPD read */
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+- ("VPD read dword at 0x%x\n",addr));
+- addr &= ~VPD_WRITE; /* ensure the R/W bit is set to read */
+-
+- VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, (SK_U16)addr);
+-
+- /* ignore return code here */
+- (void)VpdWait(pAC, IoC, VPD_READ);
+-
+- /* Don't swap here, it's a data stream of bytes */
+- Rtv = 0;
+-
+- VPD_IN32(pAC, IoC, PCI_VPD_DAT_REG, &Rtv);
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+- ("VPD read dword data = 0x%x\n",Rtv));
+- return(Rtv);
+-}
+-
+-#endif /* SKDIAG */
+-
+-/*
+- * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
+- * or to the I2C EEPROM.
+- *
+- * Returns number of bytes read / written.
+- */
+-static int VpdWriteStream(
+-SK_AC *pAC, /* Adapters context */
+-SK_IOC IoC, /* IO Context */
+-char *buf, /* data buffer */
+-int Addr, /* VPD start address */
+-int Len) /* number of bytes to read / to write */
+-{
+- int i;
+- int j;
+- SK_U16 AdrReg;
+- int Rtv;
+- SK_U8 * pComp; /* Compare pointer */
+- SK_U8 Data; /* Input Data for Compare */
+-
+- /* Init Compare Pointer */
+- pComp = (SK_U8 *) buf;
+-
+- for (i = 0; i < Len; i++, buf++) {
+- if ((i%sizeof(SK_U32)) == 0) {
+- /*
+- * At the begin of each cycle read the Data Reg
+- * So it is initialized even if only a few bytes
+- * are written.
+- */
+- AdrReg = (SK_U16) Addr;
+- AdrReg &= ~VPD_WRITE; /* READ operation */
+-
+- VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
+-
+- /* Wait for termination */
+- Rtv = VpdWait(pAC, IoC, VPD_READ);
+- if (Rtv != 0) {
+- return(i);
+- }
+- }
+-
+- /* Write current Byte */
+- VPD_OUT8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)),
+- *(SK_U8*)buf);
+-
+- if (((i%sizeof(SK_U32)) == 3) || (i == (Len - 1))) {
+- /* New Address needs to be written to VPD_ADDR reg */
+- AdrReg = (SK_U16) Addr;
+- Addr += sizeof(SK_U32);
+- AdrReg |= VPD_WRITE; /* WRITE operation */
+-
+- VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
+-
+- /* Wait for termination */
+- Rtv = VpdWait(pAC, IoC, VPD_WRITE);
+- if (Rtv != 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+- ("Write Timed Out\n"));
+- return(i - (i%sizeof(SK_U32)));
+- }
+-
+- /*
+- * Now re-read to verify
+- */
+- AdrReg &= ~VPD_WRITE; /* READ operation */
+-
+- VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
+-
+- /* Wait for termination */
+- Rtv = VpdWait(pAC, IoC, VPD_READ);
+- if (Rtv != 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+- ("Verify Timed Out\n"));
+- return(i - (i%sizeof(SK_U32)));
+- }
+-
+- for (j = 0; j <= (int)(i%sizeof(SK_U32)); j++, pComp++) {
+-
+- VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + j, &Data);
+-
+- if (Data != *pComp) {
+- /* Verify Error */
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+- ("WriteStream Verify Error\n"));
+- return(i - (i%sizeof(SK_U32)) + j);
+- }
+- }
+- }
+- }
+-
+- return(Len);
+-}
+-
+-
+-/*
+- * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
+- * or to the I2C EEPROM.
+- *
+- * Returns number of bytes read / written.
+- */
+-static int VpdReadStream(
+-SK_AC *pAC, /* Adapters context */
+-SK_IOC IoC, /* IO Context */
+-char *buf, /* data buffer */
+-int Addr, /* VPD start address */
+-int Len) /* number of bytes to read / to write */
+-{
+- int i;
+- SK_U16 AdrReg;
+- int Rtv;
+-
+- for (i = 0; i < Len; i++, buf++) {
+- if ((i%sizeof(SK_U32)) == 0) {
+- /* New Address needs to be written to VPD_ADDR reg */
+- AdrReg = (SK_U16) Addr;
+- Addr += sizeof(SK_U32);
+- AdrReg &= ~VPD_WRITE; /* READ operation */
+-
+- VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
+-
+- /* Wait for termination */
+- Rtv = VpdWait(pAC, IoC, VPD_READ);
+- if (Rtv != 0) {
+- return(i);
+- }
+- }
+- VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)),
+- (SK_U8 *)buf);
+- }
+-
+- return(Len);
+-}
+-
+-/*
+- * Read ore writes 'len' bytes of VPD data, starting at 'addr' from
+- * or to the I2C EEPROM.
+- *
+- * Returns number of bytes read / written.
+- */
+-static int VpdTransferBlock(
+-SK_AC *pAC, /* Adapters context */
+-SK_IOC IoC, /* IO Context */
+-char *buf, /* data buffer */
+-int addr, /* VPD start address */
+-int len, /* number of bytes to read / to write */
+-int dir) /* transfer direction may be VPD_READ or VPD_WRITE */
+-{
+- int Rtv; /* Return value */
+- int vpd_rom_size;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+- ("VPD %s block, addr = 0x%x, len = %d\n",
+- dir ? "write" : "read", addr, len));
+-
+- if (len == 0)
+- return(0);
+-
+- vpd_rom_size = pAC->vpd.rom_size;
+-
+- if (addr > vpd_rom_size - 4) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+- ("Address error: 0x%x, exp. < 0x%x\n",
+- addr, vpd_rom_size - 4));
+- return(0);
+- }
+-
+- if (addr + len > vpd_rom_size) {
+- len = vpd_rom_size - addr;
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+- ("Warning: len was cut to %d\n", len));
+- }
+-
+- if (dir == VPD_READ) {
+- Rtv = VpdReadStream(pAC, IoC, buf, addr, len);
+- }
+- else {
+- Rtv = VpdWriteStream(pAC, IoC, buf, addr, len);
+- }
+-
+- return(Rtv);
+-}
+-
+-#ifdef SKDIAG
+-
+-/*
+- * Read 'len' bytes of VPD data, starting at 'addr'.
+- *
+- * Returns number of bytes read.
+- */
+-int VpdReadBlock(
+-SK_AC *pAC, /* pAC pointer */
+-SK_IOC IoC, /* IO Context */
+-char *buf, /* buffer were the data should be stored */
+-int addr, /* start reading at the VPD address */
+-int len) /* number of bytes to read */
+-{
+- return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_READ));
+-}
+-
+-/*
+- * Write 'len' bytes of *but to the VPD EEPROM, starting at 'addr'.
+- *
+- * Returns number of bytes writes.
+- */
+-int VpdWriteBlock(
+-SK_AC *pAC, /* pAC pointer */
+-SK_IOC IoC, /* IO Context */
+-char *buf, /* buffer, holds the data to write */
+-int addr, /* start writing at the VPD address */
+-int len) /* number of bytes to write */
+-{
+- return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_WRITE));
+-}
+-#endif /* SKDIAG */
+-
+-/*
+- * (re)initialize the VPD buffer
+- *
+- * Reads the VPD data from the EEPROM into the VPD buffer.
+- * Get the remaining read only and read / write space.
+- *
+- * return 0: success
+- * 1: fatal VPD error
+- */
+-static int VpdInit(
+-SK_AC *pAC, /* Adapters context */
+-SK_IOC IoC) /* IO Context */
+-{
+- SK_VPD_PARA *r, rp; /* RW or RV */
+- int i;
+- unsigned char x;
+- int vpd_size;
+- SK_U16 dev_id;
+- SK_U32 our_reg2;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, ("VpdInit .. "));
+-
+- VPD_IN16(pAC, IoC, PCI_DEVICE_ID, &dev_id);
+-
+- VPD_IN32(pAC, IoC, PCI_OUR_REG_2, &our_reg2);
+-
+- pAC->vpd.rom_size = 256 << ((our_reg2 & PCI_VPD_ROM_SZ) >> 14);
+-
+- /*
+- * this function might get used before the hardware is initialized
+- * therefore we cannot always trust in GIChipId
+- */
+- if (((pAC->vpd.v.vpd_status & VPD_VALID) == 0 &&
+- dev_id != VPD_DEV_ID_GENESIS) ||
+- ((pAC->vpd.v.vpd_status & VPD_VALID) != 0 &&
+- !pAC->GIni.GIGenesis)) {
+-
+- /* for Yukon the VPD size is always 256 */
+- vpd_size = VPD_SIZE_YUKON;
+- }
+- else {
+- /* Genesis uses the maximum ROM size up to 512 for VPD */
+- if (pAC->vpd.rom_size > VPD_SIZE_GENESIS) {
+- vpd_size = VPD_SIZE_GENESIS;
+- }
+- else {
+- vpd_size = pAC->vpd.rom_size;
+- }
+- }
+-
+- /* read the VPD data into the VPD buffer */
+- if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf, 0, vpd_size, VPD_READ)
+- != vpd_size) {
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+- ("Block Read Error\n"));
+- return(1);
+- }
+-
+- pAC->vpd.vpd_size = vpd_size;
+-
+- /* Asus K8V Se Deluxe bugfix. Correct VPD content */
+- /* MBo April 2004 */
+- if (((unsigned char)pAC->vpd.vpd_buf[0x3f] == 0x38) &&
+- ((unsigned char)pAC->vpd.vpd_buf[0x40] == 0x3c) &&
+- ((unsigned char)pAC->vpd.vpd_buf[0x41] == 0x45)) {
+- printk("sk98lin: Asus mainboard with buggy VPD? "
+- "Correcting data.\n");
+- pAC->vpd.vpd_buf[0x40] = 0x38;
+- }
+-
+-
+- /* find the end tag of the RO area */
+- if (!(r = vpd_find_para(pAC, VPD_RV, &rp))) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+- ("Encoding Error: RV Tag not found\n"));
+- return(1);
+- }
+-
+- if (r->p_val + r->p_len > pAC->vpd.vpd_buf + vpd_size/2) {
+- SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+- ("Encoding Error: Invalid VPD struct size\n"));
+- return(1);
+- }
+- pAC->vpd.v.vpd_free_ro = r->p_len - 1;
+-
+- /* test the checksum */
+- for (i = 0, x = 0; (unsigned)i <= (unsigned)vpd_size/2 - r->p_len; i++) {
+- x += pAC->vpd.vpd_buf[i];
+- }
+-
+- if (x != 0) {
+- /* checksum error */
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+- ("VPD Checksum Error\n"));
+- return(1);
+- }
+-
+- /* find and check the end tag of the RW area */
+- if (!(r = vpd_find_para(pAC, VPD_RW, &rp))) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+- ("Encoding Error: RV Tag not found\n"));
+- return(1);
+- }
+-
+- if (r->p_val < pAC->vpd.vpd_buf + vpd_size/2) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+- ("Encoding Error: Invalid VPD struct size\n"));
+- return(1);
+- }
+- pAC->vpd.v.vpd_free_rw = r->p_len;
+-
+- /* everything seems to be ok */
+- if (pAC->GIni.GIChipId != 0) {
+- pAC->vpd.v.vpd_status |= VPD_VALID;
+- }
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT,
+- ("done. Free RO = %d, Free RW = %d\n",
+- pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw));
+-
+- return(0);
+-}
+-
+-/*
+- * find the Keyword 'key' in the VPD buffer and fills the
+- * parameter struct 'p' with it's values
+- *
+- * returns *p success
+- * 0: parameter was not found or VPD encoding error
+- */
+-static SK_VPD_PARA *vpd_find_para(
+-SK_AC *pAC, /* common data base */
+-const char *key, /* keyword to find (e.g. "MN") */
+-SK_VPD_PARA *p) /* parameter description struct */
+-{
+- char *v ; /* points to VPD buffer */
+- int max; /* Maximum Number of Iterations */
+-
+- v = pAC->vpd.vpd_buf;
+- max = 128;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+- ("VPD find para %s .. ",key));
+-
+- /* check mandatory resource type ID string (Product Name) */
+- if (*v != (char)RES_ID) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+- ("Error: 0x%x missing\n", RES_ID));
+- return NULL;
+- }
+-
+- if (strcmp(key, VPD_NAME) == 0) {
+- p->p_len = VPD_GET_RES_LEN(v);
+- p->p_val = VPD_GET_VAL(v);
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+- ("found, len = %d\n", p->p_len));
+- return(p);
+- }
+-
+- v += 3 + VPD_GET_RES_LEN(v) + 3;
+- for (;; ) {
+- if (SK_MEMCMP(key,v,2) == 0) {
+- p->p_len = VPD_GET_VPD_LEN(v);
+- p->p_val = VPD_GET_VAL(v);
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+- ("found, len = %d\n",p->p_len));
+- return(p);
+- }
+-
+- /* exit when reaching the "RW" Tag or the maximum of itera. */
+- max--;
+- if (SK_MEMCMP(VPD_RW,v,2) == 0 || max == 0) {
+- break;
+- }
+-
+- if (SK_MEMCMP(VPD_RV,v,2) == 0) {
+- v += 3 + VPD_GET_VPD_LEN(v) + 3; /* skip VPD-W */
+- }
+- else {
+- v += 3 + VPD_GET_VPD_LEN(v);
+- }
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+- ("scanning '%c%c' len = %d\n",v[0],v[1],v[2]));
+- }
+-
+-#ifdef DEBUG
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, ("not found\n"));
+- if (max == 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+- ("Key/Len Encoding error\n"));
+- }
+-#endif /* DEBUG */
+- return NULL;
+-}
+-
+-/*
+- * Move 'n' bytes. Begin with the last byte if 'n' is > 0,
+- * Start with the last byte if n is < 0.
+- *
+- * returns nothing
+- */
+-static void vpd_move_para(
+-char *start, /* start of memory block */
+-char *end, /* end of memory block to move */
+-int n) /* number of bytes the memory block has to be moved */
+-{
+- char *p;
+- int i; /* number of byte copied */
+-
+- if (n == 0)
+- return;
+-
+- i = (int) (end - start + 1);
+- if (n < 0) {
+- p = start + n;
+- while (i != 0) {
+- *p++ = *start++;
+- i--;
+- }
+- }
+- else {
+- p = end + n;
+- while (i != 0) {
+- *p-- = *end--;
+- i--;
+- }
+- }
+-}
+-
+-/*
+- * setup the VPD keyword 'key' at 'ip'.
+- *
+- * returns nothing
+- */
+-static void vpd_insert_key(
+-const char *key, /* keyword to insert */
+-const char *buf, /* buffer with the keyword value */
+-int len, /* length of the value string */
+-char *ip) /* inseration point */
+-{
+- SK_VPD_KEY *p;
+-
+- p = (SK_VPD_KEY *) ip;
+- p->p_key[0] = key[0];
+- p->p_key[1] = key[1];
+- p->p_len = (unsigned char) len;
+- SK_MEMCPY(&p->p_val,buf,len);
+-}
+-
+-/*
+- * Setup the VPD end tag "RV" / "RW".
+- * Also correct the remaining space variables vpd_free_ro / vpd_free_rw.
+- *
+- * returns 0: success
+- * 1: encoding error
+- */
+-static int vpd_mod_endtag(
+-SK_AC *pAC, /* common data base */
+-char *etp) /* end pointer input position */
+-{
+- SK_VPD_KEY *p;
+- unsigned char x;
+- int i;
+- int vpd_size;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+- ("VPD modify endtag at 0x%x = '%c%c'\n",etp,etp[0],etp[1]));
+-
+- vpd_size = pAC->vpd.vpd_size;
+-
+- p = (SK_VPD_KEY *) etp;
+-
+- if (p->p_key[0] != 'R' || (p->p_key[1] != 'V' && p->p_key[1] != 'W')) {
+- /* something wrong here, encoding error */
+- SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+- ("Encoding Error: invalid end tag\n"));
+- return(1);
+- }
+- if (etp > pAC->vpd.vpd_buf + vpd_size/2) {
+- /* create "RW" tag */
+- p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size-etp-3-1);
+- pAC->vpd.v.vpd_free_rw = (int) p->p_len;
+- i = pAC->vpd.v.vpd_free_rw;
+- etp += 3;
+- }
+- else {
+- /* create "RV" tag */
+- p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size/2-etp-3);
+- pAC->vpd.v.vpd_free_ro = (int) p->p_len - 1;
+-
+- /* setup checksum */
+- for (i = 0, x = 0; i < vpd_size/2 - p->p_len; i++) {
+- x += pAC->vpd.vpd_buf[i];
+- }
+- p->p_val = (char) 0 - x;
+- i = pAC->vpd.v.vpd_free_ro;
+- etp += 4;
+- }
+- while (i) {
+- *etp++ = 0x00;
+- i--;
+- }
+-
+- return(0);
+-}
+-
+-/*
+- * Insert a VPD keyword into the VPD buffer.
+- *
+- * The keyword 'key' is inserted at the position 'ip' in the
+- * VPD buffer.
+- * The keywords behind the input position will
+- * be moved. The VPD end tag "RV" or "RW" is generated again.
+- *
+- * returns 0: success
+- * 2: value string was cut
+- * 4: VPD full, keyword was not written
+- * 6: fatal VPD error
+- *
+- */
+-static int VpdSetupPara(
+-SK_AC *pAC, /* common data base */
+-const char *key, /* keyword to insert */
+-const char *buf, /* buffer with the keyword value */
+-int len, /* length of the keyword value */
+-int type, /* VPD_RO_KEY or VPD_RW_KEY */
+-int op) /* operation to do: ADD_KEY or OWR_KEY */
+-{
+- SK_VPD_PARA vp;
+- char *etp; /* end tag position */
+- int free; /* remaining space in selected area */
+- char *ip; /* input position inside the VPD buffer */
+- int rtv; /* return code */
+- int head; /* additional haeder bytes to move */
+- int found; /* additinoal bytes if the keyword was found */
+- int vpd_size;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+- ("VPD setup para key = %s, val = %s\n",key,buf));
+-
+- vpd_size = pAC->vpd.vpd_size;
+-
+- rtv = 0;
+- ip = NULL;
+- if (type == VPD_RW_KEY) {
+- /* end tag is "RW" */
+- free = pAC->vpd.v.vpd_free_rw;
+- etp = pAC->vpd.vpd_buf + (vpd_size - free - 1 - 3);
+- }
+- else {
+- /* end tag is "RV" */
+- free = pAC->vpd.v.vpd_free_ro;
+- etp = pAC->vpd.vpd_buf + (vpd_size/2 - free - 4);
+- }
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+- ("Free RO = %d, Free RW = %d\n",
+- pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw));
+-
+- head = 0;
+- found = 0;
+- if (op == OWR_KEY) {
+- if (vpd_find_para(pAC, key, &vp)) {
+- found = 3;
+- ip = vp.p_val - 3;
+- free += vp.p_len + 3;
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+- ("Overwrite Key\n"));
+- }
+- else {
+- op = ADD_KEY;
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+- ("Add Key\n"));
+- }
+- }
+- if (op == ADD_KEY) {
+- ip = etp;
+- vp.p_len = 0;
+- head = 3;
+- }
+-
+- if (len + 3 > free) {
+- if (free < 7) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+- ("VPD Buffer Overflow, keyword not written\n"));
+- return(4);
+- }
+- /* cut it again */
+- len = free - 3;
+- rtv = 2;
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+- ("VPD Buffer Full, Keyword was cut\n"));
+- }
+-
+- vpd_move_para(ip + vp.p_len + found, etp+2, len-vp.p_len+head);
+- vpd_insert_key(key, buf, len, ip);
+- if (vpd_mod_endtag(pAC, etp + len - vp.p_len + head)) {
+- pAC->vpd.v.vpd_status &= ~VPD_VALID;
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+- ("VPD Encoding Error\n"));
+- return(6);
+- }
+-
+- return(rtv);
+-}
+-
+-
+-/*
+- * Read the contents of the VPD EEPROM and copy it to the
+- * VPD buffer if not already done.
+- *
+- * return: A pointer to the vpd_status structure. The structure contains
+- * this fields.
+- */
+-SK_VPD_STATUS *VpdStat(
+-SK_AC *pAC, /* Adapters context */
+-SK_IOC IoC) /* IO Context */
+-{
+- if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
+- (void)VpdInit(pAC, IoC);
+- }
+- return(&pAC->vpd.v);
+-}
+-
+-
+-/*
+- * Read the contents of the VPD EEPROM and copy it to the VPD
+- * buffer if not already done.
+- * Scan the VPD buffer for VPD keywords and create the VPD
+- * keyword list by copying the keywords to 'buf', all after
+- * each other and terminated with a '\0'.
+- *
+- * Exceptions: o The Resource Type ID String (product name) is called "Name"
+- * o The VPD end tags 'RV' and 'RW' are not listed
+- *
+- * The number of copied keywords is counted in 'elements'.
+- *
+- * returns 0: success
+- * 2: buffer overfull, one or more keywords are missing
+- * 6: fatal VPD error
+- *
+- * example values after returning:
+- *
+- * buf = "Name\0PN\0EC\0MN\0SN\0CP\0VF\0VL\0YA\0"
+- * *len = 30
+- * *elements = 9
+- */
+-int VpdKeys(
+-SK_AC *pAC, /* common data base */
+-SK_IOC IoC, /* IO Context */
+-char *buf, /* buffer where to copy the keywords */
+-int *len, /* buffer length */
+-int *elements) /* number of keywords returned */
+-{
+- char *v;
+- int n;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("list VPD keys .. "));
+- *elements = 0;
+- if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
+- if (VpdInit(pAC, IoC) != 0) {
+- *len = 0;
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+- ("VPD Init Error, terminated\n"));
+- return(6);
+- }
+- }
+-
+- if ((signed)strlen(VPD_NAME) + 1 <= *len) {
+- v = pAC->vpd.vpd_buf;
+- strcpy(buf,VPD_NAME);
+- n = strlen(VPD_NAME) + 1;
+- buf += n;
+- *elements = 1;
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
+- ("'%c%c' ",v[0],v[1]));
+- }
+- else {
+- *len = 0;
+- SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
+- ("buffer overflow\n"));
+- return(2);
+- }
+-
+- v += 3 + VPD_GET_RES_LEN(v) + 3;
+- for (;; ) {
+- /* exit when reaching the "RW" Tag */
+- if (SK_MEMCMP(VPD_RW,v,2) == 0) {
+- break;
+- }
+-
+- if (SK_MEMCMP(VPD_RV,v,2) == 0) {
+- v += 3 + VPD_GET_VPD_LEN(v) + 3; /* skip VPD-W */
+- continue;
+- }
+-
+- if (n+3 <= *len) {
+- SK_MEMCPY(buf,v,2);
+- buf += 2;
+- *buf++ = '\0';
+- n += 3;
+- v += 3 + VPD_GET_VPD_LEN(v);
+- *elements += 1;
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
+- ("'%c%c' ",v[0],v[1]));
+- }
+- else {
+- *len = n;
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+- ("buffer overflow\n"));
+- return(2);
+- }
+- }
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("\n"));
+- *len = n;
+- return(0);
+-}
+-
+-
+-/*
+- * Read the contents of the VPD EEPROM and copy it to the
+- * VPD buffer if not already done. Search for the VPD keyword
+- * 'key' and copy its value to 'buf'. Add a terminating '\0'.
+- * If the value does not fit into the buffer cut it after
+- * 'len' - 1 bytes.
+- *
+- * returns 0: success
+- * 1: keyword not found
+- * 2: value string was cut
+- * 3: VPD transfer timeout
+- * 6: fatal VPD error
+- */
+-int VpdRead(
+-SK_AC *pAC, /* common data base */
+-SK_IOC IoC, /* IO Context */
+-const char *key, /* keyword to read (e.g. "MN") */
+-char *buf, /* buffer where to copy the keyword value */
+-int *len) /* buffer length */
+-{
+- SK_VPD_PARA *p, vp;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("VPD read %s .. ", key));
+- if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
+- if (VpdInit(pAC, IoC) != 0) {
+- *len = 0;
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+- ("VPD init error\n"));
+- return(6);
+- }
+- }
+-
+- if ((p = vpd_find_para(pAC, key, &vp)) != NULL) {
+- if (p->p_len > (*(unsigned *)len)-1) {
+- p->p_len = *len - 1;
+- }
+- SK_MEMCPY(buf, p->p_val, p->p_len);
+- buf[p->p_len] = '\0';
+- *len = p->p_len;
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
+- ("%c%c%c%c.., len = %d\n",
+- buf[0],buf[1],buf[2],buf[3],*len));
+- }
+- else {
+- *len = 0;
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("not found\n"));
+- return(1);
+- }
+- return(0);
+-}
+-
+-
+-/*
+- * Check whether a given key may be written
+- *
+- * returns
+- * SK_TRUE Yes it may be written
+- * SK_FALSE No it may be written
+- */
+-SK_BOOL VpdMayWrite(
+-char *key) /* keyword to write (allowed values "Yx", "Vx") */
+-{
+- if ((*key != 'Y' && *key != 'V') ||
+- key[1] < '0' || key[1] > 'Z' ||
+- (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) {
+-
+- return(SK_FALSE);
+- }
+- return(SK_TRUE);
+-}
+-
+-/*
+- * Read the contents of the VPD EEPROM and copy it to the VPD
+- * buffer if not already done. Insert/overwrite the keyword 'key'
+- * in the VPD buffer. Cut the keyword value if it does not fit
+- * into the VPD read / write area.
+- *
+- * returns 0: success
+- * 2: value string was cut
+- * 3: VPD transfer timeout
+- * 4: VPD full, keyword was not written
+- * 5: keyword cannot be written
+- * 6: fatal VPD error
+- */
+-int VpdWrite(
+-SK_AC *pAC, /* common data base */
+-SK_IOC IoC, /* IO Context */
+-const char *key, /* keyword to write (allowed values "Yx", "Vx") */
+-const char *buf) /* buffer where the keyword value can be read from */
+-{
+- int len; /* length of the keyword to write */
+- int rtv; /* return code */
+- int rtv2;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX,
+- ("VPD write %s = %s\n",key,buf));
+-
+- if ((*key != 'Y' && *key != 'V') ||
+- key[1] < '0' || key[1] > 'Z' ||
+- (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) {
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+- ("illegal key tag, keyword not written\n"));
+- return(5);
+- }
+-
+- if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
+- if (VpdInit(pAC, IoC) != 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+- ("VPD init error\n"));
+- return(6);
+- }
+- }
+-
+- rtv = 0;
+- len = strlen(buf);
+- if (len > VPD_MAX_LEN) {
+- /* cut it */
+- len = VPD_MAX_LEN;
+- rtv = 2;
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+- ("keyword too long, cut after %d bytes\n",VPD_MAX_LEN));
+- }
+- if ((rtv2 = VpdSetupPara(pAC, key, buf, len, VPD_RW_KEY, OWR_KEY)) != 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+- ("VPD write error\n"));
+- return(rtv2);
+- }
+-
+- return(rtv);
+-}
+-
+-/*
+- * Read the contents of the VPD EEPROM and copy it to the
+- * VPD buffer if not already done. Remove the VPD keyword
+- * 'key' from the VPD buffer.
+- * Only the keywords in the read/write area can be deleted.
+- * Keywords in the read only area cannot be deleted.
+- *
+- * returns 0: success, keyword was removed
+- * 1: keyword not found
+- * 5: keyword cannot be deleted
+- * 6: fatal VPD error
+- */
+-int VpdDelete(
+-SK_AC *pAC, /* common data base */
+-SK_IOC IoC, /* IO Context */
+-char *key) /* keyword to read (e.g. "MN") */
+-{
+- SK_VPD_PARA *p, vp;
+- char *etp;
+- int vpd_size;
+-
+- vpd_size = pAC->vpd.vpd_size;
+-
+- SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("VPD delete key %s\n",key));
+- if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
+- if (VpdInit(pAC, IoC) != 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+- ("VPD init error\n"));
+- return(6);
+- }
+- }
+-
+- if ((p = vpd_find_para(pAC, key, &vp)) != NULL) {
+- if (p->p_val < pAC->vpd.vpd_buf + vpd_size/2) {
+- /* try to delete read only keyword */
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+- ("cannot delete RO keyword\n"));
+- return(5);
+- }
+-
+- etp = pAC->vpd.vpd_buf + (vpd_size-pAC->vpd.v.vpd_free_rw-1-3);
+-
+- vpd_move_para(vp.p_val+vp.p_len, etp+2,
+- - ((int)(vp.p_len + 3)));
+- if (vpd_mod_endtag(pAC, etp - vp.p_len - 3)) {
+- pAC->vpd.v.vpd_status &= ~VPD_VALID;
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+- ("VPD encoding error\n"));
+- return(6);
+- }
+- }
+- else {
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+- ("keyword not found\n"));
+- return(1);
+- }
+-
+- return(0);
+-}
+-
+-/*
+- * If the VPD buffer contains valid data write the VPD
+- * read/write area back to the VPD EEPROM.
+- *
+- * returns 0: success
+- * 3: VPD transfer timeout
+- */
+-int VpdUpdate(
+-SK_AC *pAC, /* Adapters context */
+-SK_IOC IoC) /* IO Context */
+-{
+- int vpd_size;
+-
+- vpd_size = pAC->vpd.vpd_size;
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("VPD update .. "));
+- if ((pAC->vpd.v.vpd_status & VPD_VALID) != 0) {
+- if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf + vpd_size/2,
+- vpd_size/2, vpd_size/2, VPD_WRITE) != vpd_size/2) {
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+- ("transfer timed out\n"));
+- return(3);
+- }
+- }
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("done\n"));
+- return(0);
+-}
+-
+diff --git a/drivers/net/sk98lin/skxmac2.c b/drivers/net/sk98lin/skxmac2.c
+deleted file mode 100644
+index b4e7502..0000000
+--- a/drivers/net/sk98lin/skxmac2.c
++++ /dev/null
+@@ -1,4160 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skxmac2.c
+- * Project: Gigabit Ethernet Adapters, Common Modules
+- * Version: $Revision: 1.102 $
+- * Date: $Date: 2003/10/02 16:53:58 $
+- * Purpose: Contains functions to initialize the MACs and PHYs
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * 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.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-#include "h/skdrv1st.h"
+-#include "h/skdrv2nd.h"
+-
+-/* typedefs *******************************************************************/
+-
+-/* BCOM PHY magic pattern list */
+-typedef struct s_PhyHack {
+- int PhyReg; /* Phy register */
+- SK_U16 PhyVal; /* Value to write */
+-} BCOM_HACK;
+-
+-/* local variables ************************************************************/
+-
+-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+-static const char SysKonnectFileId[] =
+- "@(#) $Id: skxmac2.c,v 1.102 2003/10/02 16:53:58 rschmidt Exp $ (C) Marvell.";
+-#endif
+-
+-#ifdef GENESIS
+-static BCOM_HACK BcomRegA1Hack[] = {
+- { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 },
+- { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 },
+- { 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 },
+- { 0, 0 }
+-};
+-static BCOM_HACK BcomRegC0Hack[] = {
+- { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, { 0x17, 0x0013 },
+- { 0x15, 0x0A04 }, { 0x18, 0x0420 },
+- { 0, 0 }
+-};
+-#endif
+-
+-/* function prototypes ********************************************************/
+-#ifdef GENESIS
+-static void SkXmInitPhyXmac(SK_AC*, SK_IOC, int, SK_BOOL);
+-static void SkXmInitPhyBcom(SK_AC*, SK_IOC, int, SK_BOOL);
+-static int SkXmAutoNegDoneXmac(SK_AC*, SK_IOC, int);
+-static int SkXmAutoNegDoneBcom(SK_AC*, SK_IOC, int);
+-#endif /* GENESIS */
+-#ifdef YUKON
+-static void SkGmInitPhyMarv(SK_AC*, SK_IOC, int, SK_BOOL);
+-static int SkGmAutoNegDoneMarv(SK_AC*, SK_IOC, int);
+-#endif /* YUKON */
+-#ifdef OTHER_PHY
+-static void SkXmInitPhyLone(SK_AC*, SK_IOC, int, SK_BOOL);
+-static void SkXmInitPhyNat (SK_AC*, SK_IOC, int, SK_BOOL);
+-static int SkXmAutoNegDoneLone(SK_AC*, SK_IOC, int);
+-static int SkXmAutoNegDoneNat (SK_AC*, SK_IOC, int);
+-#endif /* OTHER_PHY */
+-
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- * SkXmPhyRead() - Read from XMAC PHY register
+- *
+- * Description: reads a 16-bit word from XMAC PHY or ext. PHY
+- *
+- * Returns:
+- * nothing
+- */
+-void SkXmPhyRead(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-int Port, /* Port Index (MAC_1 + n) */
+-int PhyReg, /* Register Address (Offset) */
+-SK_U16 SK_FAR *pVal) /* Pointer to Value */
+-{
+- SK_U16 Mmu;
+- SK_GEPORT *pPrt;
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- /* write the PHY register's address */
+- XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
+-
+- /* get the PHY register's value */
+- XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
+-
+- if (pPrt->PhyType != SK_PHY_XMAC) {
+- do {
+- XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
+- /* wait until 'Ready' is set */
+- } while ((Mmu & XM_MMU_PHY_RDY) == 0);
+-
+- /* get the PHY register's value */
+- XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
+- }
+-} /* SkXmPhyRead */
+-
+-
+-/******************************************************************************
+- *
+- * SkXmPhyWrite() - Write to XMAC PHY register
+- *
+- * Description: writes a 16-bit word to XMAC PHY or ext. PHY
+- *
+- * Returns:
+- * nothing
+- */
+-void SkXmPhyWrite(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-int Port, /* Port Index (MAC_1 + n) */
+-int PhyReg, /* Register Address (Offset) */
+-SK_U16 Val) /* Value */
+-{
+- SK_U16 Mmu;
+- SK_GEPORT *pPrt;
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- if (pPrt->PhyType != SK_PHY_XMAC) {
+- do {
+- XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
+- /* wait until 'Busy' is cleared */
+- } while ((Mmu & XM_MMU_PHY_BUSY) != 0);
+- }
+-
+- /* write the PHY register's address */
+- XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
+-
+- /* write the PHY register's value */
+- XM_OUT16(IoC, Port, XM_PHY_DATA, Val);
+-
+- if (pPrt->PhyType != SK_PHY_XMAC) {
+- do {
+- XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
+- /* wait until 'Busy' is cleared */
+- } while ((Mmu & XM_MMU_PHY_BUSY) != 0);
+- }
+-} /* SkXmPhyWrite */
+-#endif /* GENESIS */
+-
+-
+-#ifdef YUKON
+-/******************************************************************************
+- *
+- * SkGmPhyRead() - Read from GPHY register
+- *
+- * Description: reads a 16-bit word from GPHY through MDIO
+- *
+- * Returns:
+- * nothing
+- */
+-void SkGmPhyRead(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-int Port, /* Port Index (MAC_1 + n) */
+-int PhyReg, /* Register Address (Offset) */
+-SK_U16 SK_FAR *pVal) /* Pointer to Value */
+-{
+- SK_U16 Ctrl;
+- SK_GEPORT *pPrt;
+-#ifdef VCPU
+- u_long SimCyle;
+- u_long SimLowTime;
+-
+- VCPUgetTime(&SimCyle, &SimLowTime);
+- VCPUprintf(0, "SkGmPhyRead(%u), SimCyle=%u, SimLowTime=%u\n",
+- PhyReg, SimCyle, SimLowTime);
+-#endif /* VCPU */
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- /* set PHY-Register offset and 'Read' OpCode (= 1) */
+- *pVal = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) |
+- GM_SMI_CT_REG_AD(PhyReg) | GM_SMI_CT_OP_RD);
+-
+- GM_OUT16(IoC, Port, GM_SMI_CTRL, *pVal);
+-
+- GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
+-
+- /* additional check for MDC/MDIO activity */
+- if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
+- *pVal = 0;
+- return;
+- }
+-
+- *pVal |= GM_SMI_CT_BUSY;
+-
+- do {
+-#ifdef VCPU
+- VCPUwaitTime(1000);
+-#endif /* VCPU */
+-
+- GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
+-
+- /* wait until 'ReadValid' is set */
+- } while (Ctrl == *pVal);
+-
+- /* get the PHY register's value */
+- GM_IN16(IoC, Port, GM_SMI_DATA, pVal);
+-
+-#ifdef VCPU
+- VCPUgetTime(&SimCyle, &SimLowTime);
+- VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
+- SimCyle, SimLowTime);
+-#endif /* VCPU */
+-
+-} /* SkGmPhyRead */
+-
+-
+-/******************************************************************************
+- *
+- * SkGmPhyWrite() - Write to GPHY register
+- *
+- * Description: writes a 16-bit word to GPHY through MDIO
+- *
+- * Returns:
+- * nothing
+- */
+-void SkGmPhyWrite(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-int Port, /* Port Index (MAC_1 + n) */
+-int PhyReg, /* Register Address (Offset) */
+-SK_U16 Val) /* Value */
+-{
+- SK_U16 Ctrl;
+- SK_GEPORT *pPrt;
+-#ifdef VCPU
+- SK_U32 DWord;
+- u_long SimCyle;
+- u_long SimLowTime;
+-
+- VCPUgetTime(&SimCyle, &SimLowTime);
+- VCPUprintf(0, "SkGmPhyWrite(Reg=%u, Val=0x%04x), SimCyle=%u, SimLowTime=%u\n",
+- PhyReg, Val, SimCyle, SimLowTime);
+-#endif /* VCPU */
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- /* write the PHY register's value */
+- GM_OUT16(IoC, Port, GM_SMI_DATA, Val);
+-
+- /* set PHY-Register offset and 'Write' OpCode (= 0) */
+- Val = GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | GM_SMI_CT_REG_AD(PhyReg);
+-
+- GM_OUT16(IoC, Port, GM_SMI_CTRL, Val);
+-
+- GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
+-
+- /* additional check for MDC/MDIO activity */
+- if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
+- return;
+- }
+-
+- Val |= GM_SMI_CT_BUSY;
+-
+- do {
+-#ifdef VCPU
+- /* read Timer value */
+- SK_IN32(IoC, B2_TI_VAL, &DWord);
+-
+- VCPUwaitTime(1000);
+-#endif /* VCPU */
+-
+- GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
+-
+- /* wait until 'Busy' is cleared */
+- } while (Ctrl == Val);
+-
+-#ifdef VCPU
+- VCPUgetTime(&SimCyle, &SimLowTime);
+- VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
+- SimCyle, SimLowTime);
+-#endif /* VCPU */
+-
+-} /* SkGmPhyWrite */
+-#endif /* YUKON */
+-
+-
+-#ifdef SK_DIAG
+-/******************************************************************************
+- *
+- * SkGePhyRead() - Read from PHY register
+- *
+- * Description: calls a read PHY routine dep. on board type
+- *
+- * Returns:
+- * nothing
+- */
+-void SkGePhyRead(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-int Port, /* Port Index (MAC_1 + n) */
+-int PhyReg, /* Register Address (Offset) */
+-SK_U16 *pVal) /* Pointer to Value */
+-{
+- void (*r_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 *pVal);
+-
+- if (pAC->GIni.GIGenesis) {
+- r_func = SkXmPhyRead;
+- }
+- else {
+- r_func = SkGmPhyRead;
+- }
+-
+- r_func(pAC, IoC, Port, PhyReg, pVal);
+-} /* SkGePhyRead */
+-
+-
+-/******************************************************************************
+- *
+- * SkGePhyWrite() - Write to PHY register
+- *
+- * Description: calls a write PHY routine dep. on board type
+- *
+- * Returns:
+- * nothing
+- */
+-void SkGePhyWrite(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-int Port, /* Port Index (MAC_1 + n) */
+-int PhyReg, /* Register Address (Offset) */
+-SK_U16 Val) /* Value */
+-{
+- void (*w_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 Val);
+-
+- if (pAC->GIni.GIGenesis) {
+- w_func = SkXmPhyWrite;
+- }
+- else {
+- w_func = SkGmPhyWrite;
+- }
+-
+- w_func(pAC, IoC, Port, PhyReg, Val);
+-} /* SkGePhyWrite */
+-#endif /* SK_DIAG */
+-
+-
+-/******************************************************************************
+- *
+- * SkMacPromiscMode() - Enable / Disable Promiscuous Mode
+- *
+- * Description:
+- * enables / disables promiscuous mode by setting Mode Register (XMAC) or
+- * Receive Control Register (GMAC) dep. on board type
+- *
+- * Returns:
+- * nothing
+- */
+-void SkMacPromiscMode(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port, /* Port Index (MAC_1 + n) */
+-SK_BOOL Enable) /* Enable / Disable */
+-{
+-#ifdef YUKON
+- SK_U16 RcReg;
+-#endif
+-#ifdef GENESIS
+- SK_U32 MdReg;
+-#endif
+-
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+-
+- XM_IN32(IoC, Port, XM_MODE, &MdReg);
+- /* enable or disable promiscuous mode */
+- if (Enable) {
+- MdReg |= XM_MD_ENA_PROM;
+- }
+- else {
+- MdReg &= ~XM_MD_ENA_PROM;
+- }
+- /* setup Mode Register */
+- XM_OUT32(IoC, Port, XM_MODE, MdReg);
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIYukon) {
+-
+- GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
+-
+- /* enable or disable unicast and multicast filtering */
+- if (Enable) {
+- RcReg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
+- }
+- else {
+- RcReg |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
+- }
+- /* setup Receive Control Register */
+- GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
+- }
+-#endif /* YUKON */
+-
+-} /* SkMacPromiscMode*/
+-
+-
+-/******************************************************************************
+- *
+- * SkMacHashing() - Enable / Disable Hashing
+- *
+- * Description:
+- * enables / disables hashing by setting Mode Register (XMAC) or
+- * Receive Control Register (GMAC) dep. on board type
+- *
+- * Returns:
+- * nothing
+- */
+-void SkMacHashing(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port, /* Port Index (MAC_1 + n) */
+-SK_BOOL Enable) /* Enable / Disable */
+-{
+-#ifdef YUKON
+- SK_U16 RcReg;
+-#endif
+-#ifdef GENESIS
+- SK_U32 MdReg;
+-#endif
+-
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+-
+- XM_IN32(IoC, Port, XM_MODE, &MdReg);
+- /* enable or disable hashing */
+- if (Enable) {
+- MdReg |= XM_MD_ENA_HASH;
+- }
+- else {
+- MdReg &= ~XM_MD_ENA_HASH;
+- }
+- /* setup Mode Register */
+- XM_OUT32(IoC, Port, XM_MODE, MdReg);
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIYukon) {
+-
+- GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
+-
+- /* enable or disable multicast filtering */
+- if (Enable) {
+- RcReg |= GM_RXCR_MCF_ENA;
+- }
+- else {
+- RcReg &= ~GM_RXCR_MCF_ENA;
+- }
+- /* setup Receive Control Register */
+- GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
+- }
+-#endif /* YUKON */
+-
+-} /* SkMacHashing*/
+-
+-
+-#ifdef SK_DIAG
+-/******************************************************************************
+- *
+- * SkXmSetRxCmd() - Modify the value of the XMAC's Rx Command Register
+- *
+- * Description:
+- * The features
+- * - FCS stripping, SK_STRIP_FCS_ON/OFF
+- * - pad byte stripping, SK_STRIP_PAD_ON/OFF
+- * - don't set XMR_FS_ERR in status SK_LENERR_OK_ON/OFF
+- * for inrange length error frames
+- * - don't set XMR_FS_ERR in status SK_BIG_PK_OK_ON/OFF
+- * for frames > 1514 bytes
+- * - enable Rx of own packets SK_SELF_RX_ON/OFF
+- *
+- * for incoming packets may be enabled/disabled by this function.
+- * Additional modes may be added later.
+- * Multiple modes can be enabled/disabled at the same time.
+- * The new configuration is written to the Rx Command register immediately.
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkXmSetRxCmd(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port, /* Port Index (MAC_1 + n) */
+-int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
+- SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
+-{
+- SK_U16 OldRxCmd;
+- SK_U16 RxCmd;
+-
+- XM_IN16(IoC, Port, XM_RX_CMD, &OldRxCmd);
+-
+- RxCmd = OldRxCmd;
+-
+- switch (Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) {
+- case SK_STRIP_FCS_ON:
+- RxCmd |= XM_RX_STRIP_FCS;
+- break;
+- case SK_STRIP_FCS_OFF:
+- RxCmd &= ~XM_RX_STRIP_FCS;
+- break;
+- }
+-
+- switch (Mode & (SK_STRIP_PAD_ON | SK_STRIP_PAD_OFF)) {
+- case SK_STRIP_PAD_ON:
+- RxCmd |= XM_RX_STRIP_PAD;
+- break;
+- case SK_STRIP_PAD_OFF:
+- RxCmd &= ~XM_RX_STRIP_PAD;
+- break;
+- }
+-
+- switch (Mode & (SK_LENERR_OK_ON | SK_LENERR_OK_OFF)) {
+- case SK_LENERR_OK_ON:
+- RxCmd |= XM_RX_LENERR_OK;
+- break;
+- case SK_LENERR_OK_OFF:
+- RxCmd &= ~XM_RX_LENERR_OK;
+- break;
+- }
+-
+- switch (Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) {
+- case SK_BIG_PK_OK_ON:
+- RxCmd |= XM_RX_BIG_PK_OK;
+- break;
+- case SK_BIG_PK_OK_OFF:
+- RxCmd &= ~XM_RX_BIG_PK_OK;
+- break;
+- }
+-
+- switch (Mode & (SK_SELF_RX_ON | SK_SELF_RX_OFF)) {
+- case SK_SELF_RX_ON:
+- RxCmd |= XM_RX_SELF_RX;
+- break;
+- case SK_SELF_RX_OFF:
+- RxCmd &= ~XM_RX_SELF_RX;
+- break;
+- }
+-
+- /* Write the new mode to the Rx command register if required */
+- if (OldRxCmd != RxCmd) {
+- XM_OUT16(IoC, Port, XM_RX_CMD, RxCmd);
+- }
+-} /* SkXmSetRxCmd */
+-
+-
+-/******************************************************************************
+- *
+- * SkGmSetRxCmd() - Modify the value of the GMAC's Rx Control Register
+- *
+- * Description:
+- * The features
+- * - FCS (CRC) stripping, SK_STRIP_FCS_ON/OFF
+- * - don't set GMR_FS_LONG_ERR SK_BIG_PK_OK_ON/OFF
+- * for frames > 1514 bytes
+- * - enable Rx of own packets SK_SELF_RX_ON/OFF
+- *
+- * for incoming packets may be enabled/disabled by this function.
+- * Additional modes may be added later.
+- * Multiple modes can be enabled/disabled at the same time.
+- * The new configuration is written to the Rx Command register immediately.
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkGmSetRxCmd(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port, /* Port Index (MAC_1 + n) */
+-int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
+- SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
+-{
+- SK_U16 OldRxCmd;
+- SK_U16 RxCmd;
+-
+- if ((Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) != 0) {
+-
+- GM_IN16(IoC, Port, GM_RX_CTRL, &OldRxCmd);
+-
+- RxCmd = OldRxCmd;
+-
+- if ((Mode & SK_STRIP_FCS_ON) != 0) {
+- RxCmd |= GM_RXCR_CRC_DIS;
+- }
+- else {
+- RxCmd &= ~GM_RXCR_CRC_DIS;
+- }
+- /* Write the new mode to the Rx control register if required */
+- if (OldRxCmd != RxCmd) {
+- GM_OUT16(IoC, Port, GM_RX_CTRL, RxCmd);
+- }
+- }
+-
+- if ((Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) != 0) {
+-
+- GM_IN16(IoC, Port, GM_SERIAL_MODE, &OldRxCmd);
+-
+- RxCmd = OldRxCmd;
+-
+- if ((Mode & SK_BIG_PK_OK_ON) != 0) {
+- RxCmd |= GM_SMOD_JUMBO_ENA;
+- }
+- else {
+- RxCmd &= ~GM_SMOD_JUMBO_ENA;
+- }
+- /* Write the new mode to the Rx control register if required */
+- if (OldRxCmd != RxCmd) {
+- GM_OUT16(IoC, Port, GM_SERIAL_MODE, RxCmd);
+- }
+- }
+-} /* SkGmSetRxCmd */
+-
+-
+-/******************************************************************************
+- *
+- * SkMacSetRxCmd() - Modify the value of the MAC's Rx Control Register
+- *
+- * Description: modifies the MAC's Rx Control reg. dep. on board type
+- *
+- * Returns:
+- * nothing
+- */
+-void SkMacSetRxCmd(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port, /* Port Index (MAC_1 + n) */
+-int Mode) /* Rx Mode */
+-{
+- if (pAC->GIni.GIGenesis) {
+-
+- SkXmSetRxCmd(pAC, IoC, Port, Mode);
+- }
+- else {
+-
+- SkGmSetRxCmd(pAC, IoC, Port, Mode);
+- }
+-
+-} /* SkMacSetRxCmd */
+-
+-
+-/******************************************************************************
+- *
+- * SkMacCrcGener() - Enable / Disable CRC Generation
+- *
+- * Description: enables / disables CRC generation dep. on board type
+- *
+- * Returns:
+- * nothing
+- */
+-void SkMacCrcGener(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port, /* Port Index (MAC_1 + n) */
+-SK_BOOL Enable) /* Enable / Disable */
+-{
+- SK_U16 Word;
+-
+- if (pAC->GIni.GIGenesis) {
+-
+- XM_IN16(IoC, Port, XM_TX_CMD, &Word);
+-
+- if (Enable) {
+- Word &= ~XM_TX_NO_CRC;
+- }
+- else {
+- Word |= XM_TX_NO_CRC;
+- }
+- /* setup Tx Command Register */
+- XM_OUT16(IoC, Port, XM_TX_CMD, Word);
+- }
+- else {
+-
+- GM_IN16(IoC, Port, GM_TX_CTRL, &Word);
+-
+- if (Enable) {
+- Word &= ~GM_TXCR_CRC_DIS;
+- }
+- else {
+- Word |= GM_TXCR_CRC_DIS;
+- }
+- /* setup Tx Control Register */
+- GM_OUT16(IoC, Port, GM_TX_CTRL, Word);
+- }
+-
+-} /* SkMacCrcGener*/
+-
+-#endif /* SK_DIAG */
+-
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- * SkXmClrExactAddr() - Clear Exact Match Address Registers
+- *
+- * Description:
+- * All Exact Match Address registers of the XMAC 'Port' will be
+- * cleared starting with 'StartNum' up to (and including) the
+- * Exact Match address number of 'StopNum'.
+- *
+- * Returns:
+- * nothing
+- */
+-void SkXmClrExactAddr(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port, /* Port Index (MAC_1 + n) */
+-int StartNum, /* Begin with this Address Register Index (0..15) */
+-int StopNum) /* Stop after finished with this Register Idx (0..15) */
+-{
+- int i;
+- SK_U16 ZeroAddr[3] = {0x0000, 0x0000, 0x0000};
+-
+- if ((unsigned)StartNum > 15 || (unsigned)StopNum > 15 ||
+- StartNum > StopNum) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E001, SKERR_HWI_E001MSG);
+- return;
+- }
+-
+- for (i = StartNum; i <= StopNum; i++) {
+- XM_OUTADDR(IoC, Port, XM_EXM(i), &ZeroAddr[0]);
+- }
+-} /* SkXmClrExactAddr */
+-#endif /* GENESIS */
+-
+-
+-/******************************************************************************
+- *
+- * SkMacFlushTxFifo() - Flush the MAC's transmit FIFO
+- *
+- * Description:
+- * Flush the transmit FIFO of the MAC specified by the index 'Port'
+- *
+- * Returns:
+- * nothing
+- */
+-void SkMacFlushTxFifo(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+-#ifdef GENESIS
+- SK_U32 MdReg;
+-
+- if (pAC->GIni.GIGenesis) {
+-
+- XM_IN32(IoC, Port, XM_MODE, &MdReg);
+-
+- XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FTF);
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIYukon) {
+- /* no way to flush the FIFO we have to issue a reset */
+- /* TBD */
+- }
+-#endif /* YUKON */
+-
+-} /* SkMacFlushTxFifo */
+-
+-
+-/******************************************************************************
+- *
+- * SkMacFlushRxFifo() - Flush the MAC's receive FIFO
+- *
+- * Description:
+- * Flush the receive FIFO of the MAC specified by the index 'Port'
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkMacFlushRxFifo(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+-#ifdef GENESIS
+- SK_U32 MdReg;
+-
+- if (pAC->GIni.GIGenesis) {
+-
+- XM_IN32(IoC, Port, XM_MODE, &MdReg);
+-
+- XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FRF);
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIYukon) {
+- /* no way to flush the FIFO we have to issue a reset */
+- /* TBD */
+- }
+-#endif /* YUKON */
+-
+-} /* SkMacFlushRxFifo */
+-
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- * SkXmSoftRst() - Do a XMAC software reset
+- *
+- * Description:
+- * The PHY registers should not be destroyed during this
+- * kind of software reset. Therefore the XMAC Software Reset
+- * (XM_GP_RES_MAC bit in XM_GP_PORT) must not be used!
+- *
+- * The software reset is done by
+- * - disabling the Rx and Tx state machine,
+- * - resetting the statistics module,
+- * - clear all other significant XMAC Mode,
+- * Command, and Control Registers
+- * - clearing the Hash Register and the
+- * Exact Match Address registers, and
+- * - flushing the XMAC's Rx and Tx FIFOs.
+- *
+- * Note:
+- * Another requirement when stopping the XMAC is to
+- * avoid sending corrupted frames on the network.
+- * Disabling the Tx state machine will NOT interrupt
+- * the currently transmitted frame. But we must take care
+- * that the Tx FIFO is cleared AFTER the current frame
+- * is complete sent to the network.
+- *
+- * It takes about 12ns to send a frame with 1538 bytes.
+- * One PCI clock goes at least 15ns (66MHz). Therefore
+- * after reading XM_GP_PORT back, we are sure that the
+- * transmitter is disabled AND idle. And this means
+- * we may flush the transmit FIFO now.
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkXmSoftRst(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_U16 ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000};
+-
+- /* reset the statistics module */
+- XM_OUT32(IoC, Port, XM_GP_PORT, XM_GP_RES_STAT);
+-
+- /* disable all XMAC IRQs */
+- XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
+-
+- XM_OUT32(IoC, Port, XM_MODE, 0); /* clear Mode Reg */
+-
+- XM_OUT16(IoC, Port, XM_TX_CMD, 0); /* reset TX CMD Reg */
+- XM_OUT16(IoC, Port, XM_RX_CMD, 0); /* reset RX CMD Reg */
+-
+- /* disable all PHY IRQs */
+- switch (pAC->GIni.GP[Port].PhyType) {
+- case SK_PHY_BCOM:
+- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
+- break;
+-#ifdef OTHER_PHY
+- case SK_PHY_LONE:
+- SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
+- break;
+- case SK_PHY_NAT:
+- /* todo: National
+- SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
+- break;
+-#endif /* OTHER_PHY */
+- }
+-
+- /* clear the Hash Register */
+- XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr);
+-
+- /* clear the Exact Match Address registers */
+- SkXmClrExactAddr(pAC, IoC, Port, 0, 15);
+-
+- /* clear the Source Check Address registers */
+- XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr);
+-
+-} /* SkXmSoftRst */
+-
+-
+-/******************************************************************************
+- *
+- * SkXmHardRst() - Do a XMAC hardware reset
+- *
+- * Description:
+- * The XMAC of the specified 'Port' and all connected devices
+- * (PHY and SERDES) will receive a reset signal on its *Reset pins.
+- * External PHYs must be reset by clearing a bit in the GPIO register
+- * (Timing requirements: Broadcom: 400ns, Level One: none, National: 80ns).
+- *
+- * ATTENTION:
+- * It is absolutely necessary to reset the SW_RST Bit first
+- * before calling this function.
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkXmHardRst(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_U32 Reg;
+- int i;
+- int TOut;
+- SK_U16 Word;
+-
+- for (i = 0; i < 4; i++) {
+- /* TX_MFF_CTRL1 has 32 bits, but only the lowest 16 bits are used */
+- SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
+-
+- TOut = 0;
+- do {
+- if (TOut++ > 10000) {
+- /*
+- * Adapter seems to be in RESET state.
+- * Registers cannot be written.
+- */
+- return;
+- }
+-
+- SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
+-
+- SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &Word);
+-
+- } while ((Word & MFF_SET_MAC_RST) == 0);
+- }
+-
+- /* For external PHYs there must be special handling */
+- if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
+-
+- SK_IN32(IoC, B2_GP_IO, &Reg);
+-
+- if (Port == 0) {
+- Reg |= GP_DIR_0; /* set to output */
+- Reg &= ~GP_IO_0; /* set PHY reset (active low) */
+- }
+- else {
+- Reg |= GP_DIR_2; /* set to output */
+- Reg &= ~GP_IO_2; /* set PHY reset (active low) */
+- }
+- /* reset external PHY */
+- SK_OUT32(IoC, B2_GP_IO, Reg);
+-
+- /* short delay */
+- SK_IN32(IoC, B2_GP_IO, &Reg);
+- }
+-} /* SkXmHardRst */
+-
+-
+-/******************************************************************************
+- *
+- * SkXmClearRst() - Release the PHY & XMAC reset
+- *
+- * Description:
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkXmClearRst(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_U32 DWord;
+-
+- /* clear HW reset */
+- SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
+-
+- if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
+-
+- SK_IN32(IoC, B2_GP_IO, &DWord);
+-
+- if (Port == 0) {
+- DWord |= (GP_DIR_0 | GP_IO_0); /* set to output */
+- }
+- else {
+- DWord |= (GP_DIR_2 | GP_IO_2); /* set to output */
+- }
+- /* Clear PHY reset */
+- SK_OUT32(IoC, B2_GP_IO, DWord);
+-
+- /* Enable GMII interface */
+- XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD);
+- }
+-} /* SkXmClearRst */
+-#endif /* GENESIS */
+-
+-
+-#ifdef YUKON
+-/******************************************************************************
+- *
+- * SkGmSoftRst() - Do a GMAC software reset
+- *
+- * Description:
+- * The GPHY registers should not be destroyed during this
+- * kind of software reset.
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkGmSoftRst(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_U16 EmptyHash[4] = {0x0000, 0x0000, 0x0000, 0x0000};
+- SK_U16 RxCtrl;
+-
+- /* reset the statistics module */
+-
+- /* disable all GMAC IRQs */
+- SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
+-
+- /* disable all PHY IRQs */
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
+-
+- /* clear the Hash Register */
+- GM_OUTHASH(IoC, Port, GM_MC_ADDR_H1, EmptyHash);
+-
+- /* Enable Unicast and Multicast filtering */
+- GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl);
+-
+- GM_OUT16(IoC, Port, GM_RX_CTRL,
+- (SK_U16)(RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA));
+-
+-} /* SkGmSoftRst */
+-
+-
+-/******************************************************************************
+- *
+- * SkGmHardRst() - Do a GMAC hardware reset
+- *
+- * Description:
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkGmHardRst(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_U32 DWord;
+-
+- /* WA code for COMA mode */
+- if (pAC->GIni.GIYukonLite &&
+- pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
+-
+- SK_IN32(IoC, B2_GP_IO, &DWord);
+-
+- DWord |= (GP_DIR_9 | GP_IO_9);
+-
+- /* set PHY reset */
+- SK_OUT32(IoC, B2_GP_IO, DWord);
+- }
+-
+- /* set GPHY Control reset */
+- SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
+-
+- /* set GMAC Control reset */
+- SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
+-
+-} /* SkGmHardRst */
+-
+-
+-/******************************************************************************
+- *
+- * SkGmClearRst() - Release the GPHY & GMAC reset
+- *
+- * Description:
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkGmClearRst(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_U32 DWord;
+-
+-#ifdef XXX
+- /* clear GMAC Control reset */
+- SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR);
+-
+- /* set GMAC Control reset */
+- SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
+-#endif /* XXX */
+-
+- /* WA code for COMA mode */
+- if (pAC->GIni.GIYukonLite &&
+- pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
+-
+- SK_IN32(IoC, B2_GP_IO, &DWord);
+-
+- DWord |= GP_DIR_9; /* set to output */
+- DWord &= ~GP_IO_9; /* clear PHY reset (active high) */
+-
+- /* clear PHY reset */
+- SK_OUT32(IoC, B2_GP_IO, DWord);
+- }
+-
+- /* set HWCFG_MODE */
+- DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
+- GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE |
+- (pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP :
+- GPC_HWCFG_GMII_FIB);
+-
+- /* set GPHY Control reset */
+- SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET);
+-
+- /* release GPHY Control reset */
+- SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR);
+-
+-#ifdef VCPU
+- VCpuWait(9000);
+-#endif /* VCPU */
+-
+- /* clear GMAC Control reset */
+- SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
+-
+-#ifdef VCPU
+- VCpuWait(2000);
+-
+- SK_IN32(IoC, MR_ADDR(Port, GPHY_CTRL), &DWord);
+-
+- SK_IN32(IoC, B0_ISRC, &DWord);
+-#endif /* VCPU */
+-
+-} /* SkGmClearRst */
+-#endif /* YUKON */
+-
+-
+-/******************************************************************************
+- *
+- * SkMacSoftRst() - Do a MAC software reset
+- *
+- * Description: calls a MAC software reset routine dep. on board type
+- *
+- * Returns:
+- * nothing
+- */
+-void SkMacSoftRst(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_GEPORT *pPrt;
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- /* disable receiver and transmitter */
+- SkMacRxTxDisable(pAC, IoC, Port);
+-
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+-
+- SkXmSoftRst(pAC, IoC, Port);
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIYukon) {
+-
+- SkGmSoftRst(pAC, IoC, Port);
+- }
+-#endif /* YUKON */
+-
+- /* flush the MAC's Rx and Tx FIFOs */
+- SkMacFlushTxFifo(pAC, IoC, Port);
+-
+- SkMacFlushRxFifo(pAC, IoC, Port);
+-
+- pPrt->PState = SK_PRT_STOP;
+-
+-} /* SkMacSoftRst */
+-
+-
+-/******************************************************************************
+- *
+- * SkMacHardRst() - Do a MAC hardware reset
+- *
+- * Description: calls a MAC hardware reset routine dep. on board type
+- *
+- * Returns:
+- * nothing
+- */
+-void SkMacHardRst(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+-
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+-
+- SkXmHardRst(pAC, IoC, Port);
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIYukon) {
+-
+- SkGmHardRst(pAC, IoC, Port);
+- }
+-#endif /* YUKON */
+-
+- pAC->GIni.GP[Port].PState = SK_PRT_RESET;
+-
+-} /* SkMacHardRst */
+-
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- * SkXmInitMac() - Initialize the XMAC II
+- *
+- * Description:
+- * Initialize the XMAC of the specified port.
+- * The XMAC must be reset or stopped before calling this function.
+- *
+- * Note:
+- * The XMAC's Rx and Tx state machine is still disabled when returning.
+- *
+- * Returns:
+- * nothing
+- */
+-void SkXmInitMac(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_GEPORT *pPrt;
+- int i;
+- SK_U16 SWord;
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- if (pPrt->PState == SK_PRT_STOP) {
+- /* Port State: SK_PRT_STOP */
+- /* Verify that the reset bit is cleared */
+- SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);
+-
+- if ((SWord & MFF_SET_MAC_RST) != 0) {
+- /* PState does not match HW state */
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
+- /* Correct it */
+- pPrt->PState = SK_PRT_RESET;
+- }
+- }
+-
+- if (pPrt->PState == SK_PRT_RESET) {
+-
+- SkXmClearRst(pAC, IoC, Port);
+-
+- if (pPrt->PhyType != SK_PHY_XMAC) {
+- /* read Id from external PHY (all have the same address) */
+- SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1);
+-
+- /*
+- * Optimize MDIO transfer by suppressing preamble.
+- * Must be done AFTER first access to BCOM chip.
+- */
+- XM_IN16(IoC, Port, XM_MMU_CMD, &SWord);
+-
+- XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE);
+-
+- if (pPrt->PhyId1 == PHY_BCOM_ID1_C0) {
+- /*
+- * Workaround BCOM Errata for the C0 type.
+- * Write magic patterns to reserved registers.
+- */
+- i = 0;
+- while (BcomRegC0Hack[i].PhyReg != 0) {
+- SkXmPhyWrite(pAC, IoC, Port, BcomRegC0Hack[i].PhyReg,
+- BcomRegC0Hack[i].PhyVal);
+- i++;
+- }
+- }
+- else if (pPrt->PhyId1 == PHY_BCOM_ID1_A1) {
+- /*
+- * Workaround BCOM Errata for the A1 type.
+- * Write magic patterns to reserved registers.
+- */
+- i = 0;
+- while (BcomRegA1Hack[i].PhyReg != 0) {
+- SkXmPhyWrite(pAC, IoC, Port, BcomRegA1Hack[i].PhyReg,
+- BcomRegA1Hack[i].PhyVal);
+- i++;
+- }
+- }
+-
+- /*
+- * Workaround BCOM Errata (#10523) for all BCom PHYs.
+- * Disable Power Management after reset.
+- */
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
+-
+- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
+- (SK_U16)(SWord | PHY_B_AC_DIS_PM));
+-
+- /* PHY LED initialization is done in SkGeXmitLED() */
+- }
+-
+- /* Dummy read the Interrupt source register */
+- XM_IN16(IoC, Port, XM_ISRC, &SWord);
+-
+- /*
+- * The auto-negotiation process starts immediately after
+- * clearing the reset. The auto-negotiation process should be
+- * started by the SIRQ, therefore stop it here immediately.
+- */
+- SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
+-
+-#ifdef TEST_ONLY
+- /* temp. code: enable signal detect */
+- /* WARNING: do not override GMII setting above */
+- XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_COM4SIG);
+-#endif
+- }
+-
+- /*
+- * configure the XMACs Station Address
+- * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A
+- * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B
+- */
+- for (i = 0; i < 3; i++) {
+- /*
+- * The following 2 statements are together endianess
+- * independent. Remember this when changing.
+- */
+- SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
+-
+- XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord);
+- }
+-
+- /* Tx Inter Packet Gap (XM_TX_IPG): use default */
+- /* Tx High Water Mark (XM_TX_HI_WM): use default */
+- /* Tx Low Water Mark (XM_TX_LO_WM): use default */
+- /* Host Request Threshold (XM_HT_THR): use default */
+- /* Rx Request Threshold (XM_RX_THR): use default */
+- /* Rx Low Water Mark (XM_RX_LO_WM): use default */
+-
+- /* configure Rx High Water Mark (XM_RX_HI_WM) */
+- XM_OUT16(IoC, Port, XM_RX_HI_WM, SK_XM_RX_HI_WM);
+-
+- /* Configure Tx Request Threshold */
+- SWord = SK_XM_THR_SL; /* for single port */
+-
+- if (pAC->GIni.GIMacsFound > 1) {
+- switch (pAC->GIni.GIPortUsage) {
+- case SK_RED_LINK:
+- SWord = SK_XM_THR_REDL; /* redundant link */
+- break;
+- case SK_MUL_LINK:
+- SWord = SK_XM_THR_MULL; /* load balancing */
+- break;
+- case SK_JUMBO_LINK:
+- SWord = SK_XM_THR_JUMBO; /* jumbo frames */
+- break;
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014, SKERR_HWI_E014MSG);
+- break;
+- }
+- }
+- XM_OUT16(IoC, Port, XM_TX_THR, SWord);
+-
+- /* setup register defaults for the Tx Command Register */
+- XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD);
+-
+- /* setup register defaults for the Rx Command Register */
+- SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK;
+-
+- if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
+- SWord |= XM_RX_BIG_PK_OK;
+- }
+-
+- if (pPrt->PLinkMode == SK_LMODE_HALF) {
+- /*
+- * If in manual half duplex mode the other side might be in
+- * full duplex mode, so ignore if a carrier extension is not seen
+- * on frames received
+- */
+- SWord |= XM_RX_DIS_CEXT;
+- }
+-
+- XM_OUT16(IoC, Port, XM_RX_CMD, SWord);
+-
+- /*
+- * setup register defaults for the Mode Register
+- * - Don't strip error frames to avoid Store & Forward
+- * on the Rx side.
+- * - Enable 'Check Station Address' bit
+- * - Enable 'Check Address Array' bit
+- */
+- XM_OUT32(IoC, Port, XM_MODE, XM_DEF_MODE);
+-
+- /*
+- * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK)
+- * - Enable all bits excepting 'Octets Rx OK Low CntOv'
+- * and 'Octets Rx OK Hi Cnt Ov'.
+- */
+- XM_OUT32(IoC, Port, XM_RX_EV_MSK, XMR_DEF_MSK);
+-
+- /*
+- * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK)
+- * - Enable all bits excepting 'Octets Tx OK Low CntOv'
+- * and 'Octets Tx OK Hi Cnt Ov'.
+- */
+- XM_OUT32(IoC, Port, XM_TX_EV_MSK, XMT_DEF_MSK);
+-
+- /*
+- * Do NOT init XMAC interrupt mask here.
+- * All interrupts remain disable until link comes up!
+- */
+-
+- /*
+- * Any additional configuration changes may be done now.
+- * The last action is to enable the Rx and Tx state machine.
+- * This should be done after the auto-negotiation process
+- * has been completed successfully.
+- */
+-} /* SkXmInitMac */
+-#endif /* GENESIS */
+-
+-
+-#ifdef YUKON
+-/******************************************************************************
+- *
+- * SkGmInitMac() - Initialize the GMAC
+- *
+- * Description:
+- * Initialize the GMAC of the specified port.
+- * The GMAC must be reset or stopped before calling this function.
+- *
+- * Note:
+- * The GMAC's Rx and Tx state machine is still disabled when returning.
+- *
+- * Returns:
+- * nothing
+- */
+-void SkGmInitMac(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_GEPORT *pPrt;
+- int i;
+- SK_U16 SWord;
+- SK_U32 DWord;
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- if (pPrt->PState == SK_PRT_STOP) {
+- /* Port State: SK_PRT_STOP */
+- /* Verify that the reset bit is cleared */
+- SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord);
+-
+- if ((DWord & GMC_RST_SET) != 0) {
+- /* PState does not match HW state */
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
+- /* Correct it */
+- pPrt->PState = SK_PRT_RESET;
+- }
+- }
+-
+- if (pPrt->PState == SK_PRT_RESET) {
+-
+- SkGmHardRst(pAC, IoC, Port);
+-
+- SkGmClearRst(pAC, IoC, Port);
+-
+- /* Auto-negotiation ? */
+- if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
+- /* Auto-negotiation disabled */
+-
+- /* get General Purpose Control */
+- GM_IN16(IoC, Port, GM_GP_CTRL, &SWord);
+-
+- /* disable auto-update for speed, duplex and flow-control */
+- SWord |= GM_GPCR_AU_ALL_DIS;
+-
+- /* setup General Purpose Control Register */
+- GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
+-
+- SWord = GM_GPCR_AU_ALL_DIS;
+- }
+- else {
+- SWord = 0;
+- }
+-
+- /* speed settings */
+- switch (pPrt->PLinkSpeed) {
+- case SK_LSPEED_AUTO:
+- case SK_LSPEED_1000MBPS:
+- SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100;
+- break;
+- case SK_LSPEED_100MBPS:
+- SWord |= GM_GPCR_SPEED_100;
+- break;
+- case SK_LSPEED_10MBPS:
+- break;
+- }
+-
+- /* duplex settings */
+- if (pPrt->PLinkMode != SK_LMODE_HALF) {
+- /* set full duplex */
+- SWord |= GM_GPCR_DUP_FULL;
+- }
+-
+- /* flow-control settings */
+- switch (pPrt->PFlowCtrlMode) {
+- case SK_FLOW_MODE_NONE:
+- /* set Pause Off */
+- SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_OFF);
+- /* disable Tx & Rx flow-control */
+- SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
+- break;
+- case SK_FLOW_MODE_LOC_SEND:
+- /* disable Rx flow-control */
+- SWord |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
+- break;
+- case SK_FLOW_MODE_SYMMETRIC:
+- case SK_FLOW_MODE_SYM_OR_REM:
+- /* enable Tx & Rx flow-control */
+- break;
+- }
+-
+- /* setup General Purpose Control Register */
+- GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
+-
+- /* dummy read the Interrupt Source Register */
+- SK_IN16(IoC, GMAC_IRQ_SRC, &SWord);
+-
+-#ifndef VCPU
+- /* read Id from PHY */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1);
+-
+- SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
+-#endif /* VCPU */
+- }
+-
+- (void)SkGmResetCounter(pAC, IoC, Port);
+-
+- /* setup Transmit Control Register */
+- GM_OUT16(IoC, Port, GM_TX_CTRL, TX_COL_THR(pPrt->PMacColThres));
+-
+- /* setup Receive Control Register */
+- GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA |
+- GM_RXCR_CRC_DIS);
+-
+- /* setup Transmit Flow Control Register */
+- GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff);
+-
+- /* setup Transmit Parameter Register */
+-#ifdef VCPU
+- GM_IN16(IoC, Port, GM_TX_PARAM, &SWord);
+-#endif /* VCPU */
+-
+- SWord = TX_JAM_LEN_VAL(pPrt->PMacJamLen) |
+- TX_JAM_IPG_VAL(pPrt->PMacJamIpgVal) |
+- TX_IPG_JAM_DATA(pPrt->PMacJamIpgData);
+-
+- GM_OUT16(IoC, Port, GM_TX_PARAM, SWord);
+-
+- /* configure the Serial Mode Register */
+-#ifdef VCPU
+- GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord);
+-#endif /* VCPU */
+-
+- SWord = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(pPrt->PMacIpgData);
+-
+- if (pPrt->PMacLimit4) {
+- /* reset of collision counter after 4 consecutive collisions */
+- SWord |= GM_SMOD_LIMIT_4;
+- }
+-
+- if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
+- /* enable jumbo mode (Max. Frame Length = 9018) */
+- SWord |= GM_SMOD_JUMBO_ENA;
+- }
+-
+- GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord);
+-
+- /*
+- * configure the GMACs Station Addresses
+- * in PROM you can find our addresses at:
+- * B2_MAC_1 = xx xx xx xx xx x0 virtual address
+- * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A
+- * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort
+- */
+-
+- for (i = 0; i < 3; i++) {
+- /*
+- * The following 2 statements are together endianess
+- * independent. Remember this when changing.
+- */
+- /* physical address: will be used for pause frames */
+- SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
+-
+-#ifdef WA_DEV_16
+- /* WA for deviation #16 */
+- if (pAC->GIni.GIChipId == CHIP_ID_YUKON && pAC->GIni.GIChipRev == 0) {
+- /* swap the address bytes */
+- SWord = ((SWord & 0xff00) >> 8) | ((SWord & 0x00ff) << 8);
+-
+- /* write to register in reversed order */
+- GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord);
+- }
+- else {
+- GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
+- }
+-#else
+- GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
+-#endif /* WA_DEV_16 */
+-
+- /* virtual address: will be used for data */
+- SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord);
+-
+- GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord);
+-
+- /* reset Multicast filtering Hash registers 1-3 */
+- GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + 4*i, 0);
+- }
+-
+- /* reset Multicast filtering Hash register 4 */
+- GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0);
+-
+- /* enable interrupt mask for counter overflows */
+- GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0);
+- GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0);
+- GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0);
+-
+-#if defined(SK_DIAG) || defined(DEBUG)
+- /* read General Purpose Status */
+- GM_IN16(IoC, Port, GM_GP_STAT, &SWord);
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("MAC Stat Reg.=0x%04X\n", SWord));
+-#endif /* SK_DIAG || DEBUG */
+-
+-#ifdef SK_DIAG
+- c_print("MAC Stat Reg=0x%04X\n", SWord);
+-#endif /* SK_DIAG */
+-
+-} /* SkGmInitMac */
+-#endif /* YUKON */
+-
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- * SkXmInitDupMd() - Initialize the XMACs Duplex Mode
+- *
+- * Description:
+- * This function initializes the XMACs Duplex Mode.
+- * It should be called after successfully finishing
+- * the Auto-negotiation Process
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkXmInitDupMd(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- switch (pAC->GIni.GP[Port].PLinkModeStatus) {
+- case SK_LMODE_STAT_AUTOHALF:
+- case SK_LMODE_STAT_HALF:
+- /* Configuration Actions for Half Duplex Mode */
+- /*
+- * XM_BURST = default value. We are probable not quick
+- * enough at the 'XMAC' bus to burst 8kB.
+- * The XMAC stops bursting if no transmit frames
+- * are available or the burst limit is exceeded.
+- */
+- /* XM_TX_RT_LIM = default value (15) */
+- /* XM_TX_STIME = default value (0xff = 4096 bit times) */
+- break;
+- case SK_LMODE_STAT_AUTOFULL:
+- case SK_LMODE_STAT_FULL:
+- /* Configuration Actions for Full Duplex Mode */
+- /*
+- * The duplex mode is configured by the PHY,
+- * therefore it seems to be that there is nothing
+- * to do here.
+- */
+- break;
+- case SK_LMODE_STAT_UNKNOWN:
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E007, SKERR_HWI_E007MSG);
+- break;
+- }
+-} /* SkXmInitDupMd */
+-
+-
+-/******************************************************************************
+- *
+- * SkXmInitPauseMd() - initialize the Pause Mode to be used for this port
+- *
+- * Description:
+- * This function initializes the Pause Mode which should
+- * be used for this port.
+- * It should be called after successfully finishing
+- * the Auto-negotiation Process
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkXmInitPauseMd(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_GEPORT *pPrt;
+- SK_U32 DWord;
+- SK_U16 Word;
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
+-
+- if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE ||
+- pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
+-
+- /* Disable Pause Frame Reception */
+- Word |= XM_MMU_IGN_PF;
+- }
+- else {
+- /*
+- * enabling pause frame reception is required for 1000BT
+- * because the XMAC is not reset if the link is going down
+- */
+- /* Enable Pause Frame Reception */
+- Word &= ~XM_MMU_IGN_PF;
+- }
+-
+- XM_OUT16(IoC, Port, XM_MMU_CMD, Word);
+-
+- XM_IN32(IoC, Port, XM_MODE, &DWord);
+-
+- if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC ||
+- pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
+-
+- /*
+- * Configure Pause Frame Generation
+- * Use internal and external Pause Frame Generation.
+- * Sending pause frames is edge triggered.
+- * Send a Pause frame with the maximum pause time if
+- * internal oder external FIFO full condition occurs.
+- * Send a zero pause time frame to re-start transmission.
+- */
+-
+- /* XM_PAUSE_DA = '010000C28001' (default) */
+-
+- /* XM_MAC_PTIME = 0xffff (maximum) */
+- /* remember this value is defined in big endian (!) */
+- XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff);
+-
+- /* Set Pause Mode in Mode Register */
+- DWord |= XM_PAUSE_MODE;
+-
+- /* Set Pause Mode in MAC Rx FIFO */
+- SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE);
+- }
+- else {
+- /*
+- * disable pause frame generation is required for 1000BT
+- * because the XMAC is not reset if the link is going down
+- */
+- /* Disable Pause Mode in Mode Register */
+- DWord &= ~XM_PAUSE_MODE;
+-
+- /* Disable Pause Mode in MAC Rx FIFO */
+- SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE);
+- }
+-
+- XM_OUT32(IoC, Port, XM_MODE, DWord);
+-} /* SkXmInitPauseMd*/
+-
+-
+-/******************************************************************************
+- *
+- * SkXmInitPhyXmac() - Initialize the XMAC Phy registers
+- *
+- * Description: initializes all the XMACs Phy registers
+- *
+- * Note:
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkXmInitPhyXmac(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port, /* Port Index (MAC_1 + n) */
+-SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
+-{
+- SK_GEPORT *pPrt;
+- SK_U16 Ctrl;
+-
+- pPrt = &pAC->GIni.GP[Port];
+- Ctrl = 0;
+-
+- /* Auto-negotiation ? */
+- if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("InitPhyXmac: no auto-negotiation Port %d\n", Port));
+- /* Set DuplexMode in Config register */
+- if (pPrt->PLinkMode == SK_LMODE_FULL) {
+- Ctrl |= PHY_CT_DUP_MD;
+- }
+-
+- /*
+- * Do NOT enable Auto-negotiation here. This would hold
+- * the link down because no IDLEs are transmitted
+- */
+- }
+- else {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("InitPhyXmac: with auto-negotiation Port %d\n", Port));
+- /* Set Auto-negotiation advertisement */
+-
+- /* Set Full/half duplex capabilities */
+- switch (pPrt->PLinkMode) {
+- case SK_LMODE_AUTOHALF:
+- Ctrl |= PHY_X_AN_HD;
+- break;
+- case SK_LMODE_AUTOFULL:
+- Ctrl |= PHY_X_AN_FD;
+- break;
+- case SK_LMODE_AUTOBOTH:
+- Ctrl |= PHY_X_AN_FD | PHY_X_AN_HD;
+- break;
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
+- SKERR_HWI_E015MSG);
+- }
+-
+- /* Set Flow-control capabilities */
+- switch (pPrt->PFlowCtrlMode) {
+- case SK_FLOW_MODE_NONE:
+- Ctrl |= PHY_X_P_NO_PAUSE;
+- break;
+- case SK_FLOW_MODE_LOC_SEND:
+- Ctrl |= PHY_X_P_ASYM_MD;
+- break;
+- case SK_FLOW_MODE_SYMMETRIC:
+- Ctrl |= PHY_X_P_SYM_MD;
+- break;
+- case SK_FLOW_MODE_SYM_OR_REM:
+- Ctrl |= PHY_X_P_BOTH_MD;
+- break;
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
+- SKERR_HWI_E016MSG);
+- }
+-
+- /* Write AutoNeg Advertisement Register */
+- SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_AUNE_ADV, Ctrl);
+-
+- /* Restart Auto-negotiation */
+- Ctrl = PHY_CT_ANE | PHY_CT_RE_CFG;
+- }
+-
+- if (DoLoop) {
+- /* Set the Phy Loopback bit, too */
+- Ctrl |= PHY_CT_LOOP;
+- }
+-
+- /* Write to the Phy control register */
+- SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_CTRL, Ctrl);
+-} /* SkXmInitPhyXmac */
+-
+-
+-/******************************************************************************
+- *
+- * SkXmInitPhyBcom() - Initialize the Broadcom Phy registers
+- *
+- * Description: initializes all the Broadcom Phy registers
+- *
+- * Note:
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkXmInitPhyBcom(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port, /* Port Index (MAC_1 + n) */
+-SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
+-{
+- SK_GEPORT *pPrt;
+- SK_U16 Ctrl1;
+- SK_U16 Ctrl2;
+- SK_U16 Ctrl3;
+- SK_U16 Ctrl4;
+- SK_U16 Ctrl5;
+-
+- Ctrl1 = PHY_CT_SP1000;
+- Ctrl2 = 0;
+- Ctrl3 = PHY_SEL_TYPE;
+- Ctrl4 = PHY_B_PEC_EN_LTR;
+- Ctrl5 = PHY_B_AC_TX_TST;
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- /* manually Master/Slave ? */
+- if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
+- Ctrl2 |= PHY_B_1000C_MSE;
+-
+- if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
+- Ctrl2 |= PHY_B_1000C_MSC;
+- }
+- }
+- /* Auto-negotiation ? */
+- if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("InitPhyBcom: no auto-negotiation Port %d\n", Port));
+- /* Set DuplexMode in Config register */
+- if (pPrt->PLinkMode == SK_LMODE_FULL) {
+- Ctrl1 |= PHY_CT_DUP_MD;
+- }
+-
+- /* Determine Master/Slave manually if not already done */
+- if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
+- Ctrl2 |= PHY_B_1000C_MSE; /* set it to Slave */
+- }
+-
+- /*
+- * Do NOT enable Auto-negotiation here. This would hold
+- * the link down because no IDLES are transmitted
+- */
+- }
+- else {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("InitPhyBcom: with auto-negotiation Port %d\n", Port));
+- /* Set Auto-negotiation advertisement */
+-
+- /*
+- * Workaround BCOM Errata #1 for the C5 type.
+- * 1000Base-T Link Acquisition Failure in Slave Mode
+- * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
+- */
+- Ctrl2 |= PHY_B_1000C_RD;
+-
+- /* Set Full/half duplex capabilities */
+- switch (pPrt->PLinkMode) {
+- case SK_LMODE_AUTOHALF:
+- Ctrl2 |= PHY_B_1000C_AHD;
+- break;
+- case SK_LMODE_AUTOFULL:
+- Ctrl2 |= PHY_B_1000C_AFD;
+- break;
+- case SK_LMODE_AUTOBOTH:
+- Ctrl2 |= PHY_B_1000C_AFD | PHY_B_1000C_AHD;
+- break;
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
+- SKERR_HWI_E015MSG);
+- }
+-
+- /* Set Flow-control capabilities */
+- switch (pPrt->PFlowCtrlMode) {
+- case SK_FLOW_MODE_NONE:
+- Ctrl3 |= PHY_B_P_NO_PAUSE;
+- break;
+- case SK_FLOW_MODE_LOC_SEND:
+- Ctrl3 |= PHY_B_P_ASYM_MD;
+- break;
+- case SK_FLOW_MODE_SYMMETRIC:
+- Ctrl3 |= PHY_B_P_SYM_MD;
+- break;
+- case SK_FLOW_MODE_SYM_OR_REM:
+- Ctrl3 |= PHY_B_P_BOTH_MD;
+- break;
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
+- SKERR_HWI_E016MSG);
+- }
+-
+- /* Restart Auto-negotiation */
+- Ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG;
+- }
+-
+- /* Initialize LED register here? */
+- /* No. Please do it in SkDgXmitLed() (if required) and swap
+- init order of LEDs and XMAC. (MAl) */
+-
+- /* Write 1000Base-T Control Register */
+- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Set 1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
+-
+- /* Write AutoNeg Advertisement Register */
+- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Set Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
+-
+- if (DoLoop) {
+- /* Set the Phy Loopback bit, too */
+- Ctrl1 |= PHY_CT_LOOP;
+- }
+-
+- if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
+- /* configure FIFO to high latency for transmission of ext. packets */
+- Ctrl4 |= PHY_B_PEC_HIGH_LA;
+-
+- /* configure reception of extended packets */
+- Ctrl5 |= PHY_B_AC_LONG_PACK;
+-
+- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, Ctrl5);
+- }
+-
+- /* Configure LED Traffic Mode and Jumbo Frame usage if specified */
+- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4);
+-
+- /* Write to the Phy control register */
+- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, Ctrl1);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("PHY Control Reg=0x%04X\n", Ctrl1));
+-} /* SkXmInitPhyBcom */
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+-/******************************************************************************
+- *
+- * SkGmInitPhyMarv() - Initialize the Marvell Phy registers
+- *
+- * Description: initializes all the Marvell Phy registers
+- *
+- * Note:
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkGmInitPhyMarv(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port, /* Port Index (MAC_1 + n) */
+-SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
+-{
+- SK_GEPORT *pPrt;
+- SK_U16 PhyCtrl;
+- SK_U16 C1000BaseT;
+- SK_U16 AutoNegAdv;
+- SK_U16 ExtPhyCtrl;
+- SK_U16 LedCtrl;
+- SK_BOOL AutoNeg;
+-#if defined(SK_DIAG) || defined(DEBUG)
+- SK_U16 PhyStat;
+- SK_U16 PhyStat1;
+- SK_U16 PhySpecStat;
+-#endif /* SK_DIAG || DEBUG */
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- /* Auto-negotiation ? */
+- if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
+- AutoNeg = SK_FALSE;
+- }
+- else {
+- AutoNeg = SK_TRUE;
+- }
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("InitPhyMarv: Port %d, auto-negotiation %s\n",
+- Port, AutoNeg ? "ON" : "OFF"));
+-
+-#ifdef VCPU
+- VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n",
+- Port, DoLoop);
+-#else /* VCPU */
+- if (DoLoop) {
+- /* Set 'MAC Power up'-bit, set Manual MDI configuration */
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
+- PHY_M_PC_MAC_POW_UP);
+- }
+- else if (AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_AUTO) {
+- /* Read Ext. PHY Specific Control */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
+-
+- ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
+- PHY_M_EC_MAC_S_MSK);
+-
+- ExtPhyCtrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ) |
+- PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1);
+-
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Set Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
+- }
+-
+- /* Read PHY Control */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
+-
+- if (!AutoNeg) {
+- /* Disable Auto-negotiation */
+- PhyCtrl &= ~PHY_CT_ANE;
+- }
+-
+- PhyCtrl |= PHY_CT_RESET;
+- /* Assert software reset */
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
+-#endif /* VCPU */
+-
+- PhyCtrl = 0 /* PHY_CT_COL_TST */;
+- C1000BaseT = 0;
+- AutoNegAdv = PHY_SEL_TYPE;
+-
+- /* manually Master/Slave ? */
+- if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
+- /* enable Manual Master/Slave */
+- C1000BaseT |= PHY_M_1000C_MSE;
+-
+- if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
+- C1000BaseT |= PHY_M_1000C_MSC; /* set it to Master */
+- }
+- }
+-
+- /* Auto-negotiation ? */
+- if (!AutoNeg) {
+-
+- if (pPrt->PLinkMode == SK_LMODE_FULL) {
+- /* Set Full Duplex Mode */
+- PhyCtrl |= PHY_CT_DUP_MD;
+- }
+-
+- /* Set Master/Slave manually if not already done */
+- if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
+- C1000BaseT |= PHY_M_1000C_MSE; /* set it to Slave */
+- }
+-
+- /* Set Speed */
+- switch (pPrt->PLinkSpeed) {
+- case SK_LSPEED_AUTO:
+- case SK_LSPEED_1000MBPS:
+- PhyCtrl |= PHY_CT_SP1000;
+- break;
+- case SK_LSPEED_100MBPS:
+- PhyCtrl |= PHY_CT_SP100;
+- break;
+- case SK_LSPEED_10MBPS:
+- break;
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
+- SKERR_HWI_E019MSG);
+- }
+-
+- if (!DoLoop) {
+- PhyCtrl |= PHY_CT_RESET;
+- }
+- }
+- else {
+- /* Set Auto-negotiation advertisement */
+-
+- if (pAC->GIni.GICopperType) {
+- /* Set Speed capabilities */
+- switch (pPrt->PLinkSpeed) {
+- case SK_LSPEED_AUTO:
+- C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
+- AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
+- PHY_M_AN_10_FD | PHY_M_AN_10_HD;
+- break;
+- case SK_LSPEED_1000MBPS:
+- C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
+- break;
+- case SK_LSPEED_100MBPS:
+- AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
+- /* advertise 10Base-T also */
+- PHY_M_AN_10_FD | PHY_M_AN_10_HD;
+- break;
+- case SK_LSPEED_10MBPS:
+- AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD;
+- break;
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
+- SKERR_HWI_E019MSG);
+- }
+-
+- /* Set Full/half duplex capabilities */
+- switch (pPrt->PLinkMode) {
+- case SK_LMODE_AUTOHALF:
+- C1000BaseT &= ~PHY_M_1000C_AFD;
+- AutoNegAdv &= ~(PHY_M_AN_100_FD | PHY_M_AN_10_FD);
+- break;
+- case SK_LMODE_AUTOFULL:
+- C1000BaseT &= ~PHY_M_1000C_AHD;
+- AutoNegAdv &= ~(PHY_M_AN_100_HD | PHY_M_AN_10_HD);
+- break;
+- case SK_LMODE_AUTOBOTH:
+- break;
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
+- SKERR_HWI_E015MSG);
+- }
+-
+- /* Set Flow-control capabilities */
+- switch (pPrt->PFlowCtrlMode) {
+- case SK_FLOW_MODE_NONE:
+- AutoNegAdv |= PHY_B_P_NO_PAUSE;
+- break;
+- case SK_FLOW_MODE_LOC_SEND:
+- AutoNegAdv |= PHY_B_P_ASYM_MD;
+- break;
+- case SK_FLOW_MODE_SYMMETRIC:
+- AutoNegAdv |= PHY_B_P_SYM_MD;
+- break;
+- case SK_FLOW_MODE_SYM_OR_REM:
+- AutoNegAdv |= PHY_B_P_BOTH_MD;
+- break;
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
+- SKERR_HWI_E016MSG);
+- }
+- }
+- else { /* special defines for FIBER (88E1011S only) */
+-
+- /* Set Full/half duplex capabilities */
+- switch (pPrt->PLinkMode) {
+- case SK_LMODE_AUTOHALF:
+- AutoNegAdv |= PHY_M_AN_1000X_AHD;
+- break;
+- case SK_LMODE_AUTOFULL:
+- AutoNegAdv |= PHY_M_AN_1000X_AFD;
+- break;
+- case SK_LMODE_AUTOBOTH:
+- AutoNegAdv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
+- break;
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
+- SKERR_HWI_E015MSG);
+- }
+-
+- /* Set Flow-control capabilities */
+- switch (pPrt->PFlowCtrlMode) {
+- case SK_FLOW_MODE_NONE:
+- AutoNegAdv |= PHY_M_P_NO_PAUSE_X;
+- break;
+- case SK_FLOW_MODE_LOC_SEND:
+- AutoNegAdv |= PHY_M_P_ASYM_MD_X;
+- break;
+- case SK_FLOW_MODE_SYMMETRIC:
+- AutoNegAdv |= PHY_M_P_SYM_MD_X;
+- break;
+- case SK_FLOW_MODE_SYM_OR_REM:
+- AutoNegAdv |= PHY_M_P_BOTH_MD_X;
+- break;
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
+- SKERR_HWI_E016MSG);
+- }
+- }
+-
+- if (!DoLoop) {
+- /* Restart Auto-negotiation */
+- PhyCtrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
+- }
+- }
+-
+-#ifdef VCPU
+- /*
+- * E-mail from Gu Lin (08-03-2002):
+- */
+-
+- /* Program PHY register 30 as 16'h0708 for simulation speed up */
+- SkGmPhyWrite(pAC, IoC, Port, 30, 0x0700 /* 0x0708 */);
+-
+- VCpuWait(2000);
+-
+-#else /* VCPU */
+-
+- /* Write 1000Base-T Control Register */
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Set 1000B-T Ctrl =0x%04X\n", C1000BaseT));
+-
+- /* Write AutoNeg Advertisement Register */
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Set Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
+-#endif /* VCPU */
+-
+- if (DoLoop) {
+- /* Set the PHY Loopback bit */
+- PhyCtrl |= PHY_CT_LOOP;
+-
+-#ifdef XXX
+- /* Program PHY register 16 as 16'h0400 to force link good */
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_FL_GOOD);
+-#endif /* XXX */
+-
+-#ifndef VCPU
+- if (pPrt->PLinkSpeed != SK_LSPEED_AUTO) {
+- /* Write Ext. PHY Specific Control */
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL,
+- (SK_U16)((pPrt->PLinkSpeed + 2) << 4));
+- }
+-#endif /* VCPU */
+- }
+-#ifdef TEST_ONLY
+- else if (pPrt->PLinkSpeed == SK_LSPEED_10MBPS) {
+- /* Write PHY Specific Control */
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
+- PHY_M_PC_EN_DET_MSK);
+- }
+-#endif
+-
+- /* Write to the PHY Control register */
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Set PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
+-
+-#ifdef VCPU
+- VCpuWait(2000);
+-#else
+-
+- LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS) | PHY_M_LED_BLINK_RT(BLINK_84MS);
+-
+- if ((pAC->GIni.GILedBlinkCtrl & SK_ACT_LED_BLINK) != 0) {
+- LedCtrl |= PHY_M_LEDC_RX_CTRL | PHY_M_LEDC_TX_CTRL;
+- }
+-
+- if ((pAC->GIni.GILedBlinkCtrl & SK_DUP_LED_NORMAL) != 0) {
+- LedCtrl |= PHY_M_LEDC_DP_CTRL;
+- }
+-
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl);
+-
+- if ((pAC->GIni.GILedBlinkCtrl & SK_LED_LINK100_ON) != 0) {
+- /* only in forced 100 Mbps mode */
+- if (!AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_100MBPS) {
+-
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_OVER,
+- PHY_M_LED_MO_100(MO_LED_ON));
+- }
+- }
+-
+-#ifdef SK_DIAG
+- c_print("Set PHY Ctrl=0x%04X\n", PhyCtrl);
+- c_print("Set 1000 B-T=0x%04X\n", C1000BaseT);
+- c_print("Set Auto-Neg=0x%04X\n", AutoNegAdv);
+- c_print("Set Ext Ctrl=0x%04X\n", ExtPhyCtrl);
+-#endif /* SK_DIAG */
+-
+-#if defined(SK_DIAG) || defined(DEBUG)
+- /* Read PHY Control */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
+-
+- /* Read 1000Base-T Control Register */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("1000B-T Ctrl =0x%04X\n", C1000BaseT));
+-
+- /* Read AutoNeg Advertisement Register */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
+-
+- /* Read Ext. PHY Specific Control */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
+-
+- /* Read PHY Status */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("PHY Stat Reg.=0x%04X\n", PhyStat));
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat1);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("PHY Stat Reg.=0x%04X\n", PhyStat1));
+-
+- /* Read PHY Specific Status */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("PHY Spec Stat=0x%04X\n", PhySpecStat));
+-#endif /* SK_DIAG || DEBUG */
+-
+-#ifdef SK_DIAG
+- c_print("PHY Ctrl Reg=0x%04X\n", PhyCtrl);
+- c_print("PHY 1000 Reg=0x%04X\n", C1000BaseT);
+- c_print("PHY AnAd Reg=0x%04X\n", AutoNegAdv);
+- c_print("Ext Ctrl Reg=0x%04X\n", ExtPhyCtrl);
+- c_print("PHY Stat Reg=0x%04X\n", PhyStat);
+- c_print("PHY Stat Reg=0x%04X\n", PhyStat1);
+- c_print("PHY Spec Reg=0x%04X\n", PhySpecStat);
+-#endif /* SK_DIAG */
+-
+-#endif /* VCPU */
+-
+-} /* SkGmInitPhyMarv */
+-#endif /* YUKON */
+-
+-
+-#ifdef OTHER_PHY
+-/******************************************************************************
+- *
+- * SkXmInitPhyLone() - Initialize the Level One Phy registers
+- *
+- * Description: initializes all the Level One Phy registers
+- *
+- * Note:
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkXmInitPhyLone(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port, /* Port Index (MAC_1 + n) */
+-SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
+-{
+- SK_GEPORT *pPrt;
+- SK_U16 Ctrl1;
+- SK_U16 Ctrl2;
+- SK_U16 Ctrl3;
+-
+- Ctrl1 = PHY_CT_SP1000;
+- Ctrl2 = 0;
+- Ctrl3 = PHY_SEL_TYPE;
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- /* manually Master/Slave ? */
+- if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
+- Ctrl2 |= PHY_L_1000C_MSE;
+-
+- if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
+- Ctrl2 |= PHY_L_1000C_MSC;
+- }
+- }
+- /* Auto-negotiation ? */
+- if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
+- /*
+- * level one spec say: "1000 Mbps: manual mode not allowed"
+- * but lets see what happens...
+- */
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("InitPhyLone: no auto-negotiation Port %d\n", Port));
+- /* Set DuplexMode in Config register */
+- if (pPrt->PLinkMode == SK_LMODE_FULL) {
+- Ctrl1 |= PHY_CT_DUP_MD;
+- }
+-
+- /* Determine Master/Slave manually if not already done */
+- if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
+- Ctrl2 |= PHY_L_1000C_MSE; /* set it to Slave */
+- }
+-
+- /*
+- * Do NOT enable Auto-negotiation here. This would hold
+- * the link down because no IDLES are transmitted
+- */
+- }
+- else {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("InitPhyLone: with auto-negotiation Port %d\n", Port));
+- /* Set Auto-negotiation advertisement */
+-
+- /* Set Full/half duplex capabilities */
+- switch (pPrt->PLinkMode) {
+- case SK_LMODE_AUTOHALF:
+- Ctrl2 |= PHY_L_1000C_AHD;
+- break;
+- case SK_LMODE_AUTOFULL:
+- Ctrl2 |= PHY_L_1000C_AFD;
+- break;
+- case SK_LMODE_AUTOBOTH:
+- Ctrl2 |= PHY_L_1000C_AFD | PHY_L_1000C_AHD;
+- break;
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
+- SKERR_HWI_E015MSG);
+- }
+-
+- /* Set Flow-control capabilities */
+- switch (pPrt->PFlowCtrlMode) {
+- case SK_FLOW_MODE_NONE:
+- Ctrl3 |= PHY_L_P_NO_PAUSE;
+- break;
+- case SK_FLOW_MODE_LOC_SEND:
+- Ctrl3 |= PHY_L_P_ASYM_MD;
+- break;
+- case SK_FLOW_MODE_SYMMETRIC:
+- Ctrl3 |= PHY_L_P_SYM_MD;
+- break;
+- case SK_FLOW_MODE_SYM_OR_REM:
+- Ctrl3 |= PHY_L_P_BOTH_MD;
+- break;
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
+- SKERR_HWI_E016MSG);
+- }
+-
+- /* Restart Auto-negotiation */
+- Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG;
+- }
+-
+- /* Write 1000Base-T Control Register */
+- SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_1000T_CTRL, Ctrl2);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
+-
+- /* Write AutoNeg Advertisement Register */
+- SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_AUNE_ADV, Ctrl3);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
+-
+- if (DoLoop) {
+- /* Set the Phy Loopback bit, too */
+- Ctrl1 |= PHY_CT_LOOP;
+- }
+-
+- /* Write to the Phy control register */
+- SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_CTRL, Ctrl1);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("PHY Control Reg=0x%04X\n", Ctrl1));
+-} /* SkXmInitPhyLone */
+-
+-
+-/******************************************************************************
+- *
+- * SkXmInitPhyNat() - Initialize the National Phy registers
+- *
+- * Description: initializes all the National Phy registers
+- *
+- * Note:
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkXmInitPhyNat(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port, /* Port Index (MAC_1 + n) */
+-SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
+-{
+-/* todo: National */
+-} /* SkXmInitPhyNat */
+-#endif /* OTHER_PHY */
+-
+-
+-/******************************************************************************
+- *
+- * SkMacInitPhy() - Initialize the PHY registers
+- *
+- * Description: calls the Init PHY routines dep. on board type
+- *
+- * Note:
+- *
+- * Returns:
+- * nothing
+- */
+-void SkMacInitPhy(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port, /* Port Index (MAC_1 + n) */
+-SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
+-{
+- SK_GEPORT *pPrt;
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+-
+- switch (pPrt->PhyType) {
+- case SK_PHY_XMAC:
+- SkXmInitPhyXmac(pAC, IoC, Port, DoLoop);
+- break;
+- case SK_PHY_BCOM:
+- SkXmInitPhyBcom(pAC, IoC, Port, DoLoop);
+- break;
+-#ifdef OTHER_PHY
+- case SK_PHY_LONE:
+- SkXmInitPhyLone(pAC, IoC, Port, DoLoop);
+- break;
+- case SK_PHY_NAT:
+- SkXmInitPhyNat(pAC, IoC, Port, DoLoop);
+- break;
+-#endif /* OTHER_PHY */
+- }
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIYukon) {
+-
+- SkGmInitPhyMarv(pAC, IoC, Port, DoLoop);
+- }
+-#endif /* YUKON */
+-
+-} /* SkMacInitPhy */
+-
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- * SkXmAutoNegDoneXmac() - Auto-negotiation handling
+- *
+- * Description:
+- * This function handles the auto-negotiation if the Done bit is set.
+- *
+- * Returns:
+- * SK_AND_OK o.k.
+- * SK_AND_DUP_CAP Duplex capability error happened
+- * SK_AND_OTHER Other error happened
+- */
+-static int SkXmAutoNegDoneXmac(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_GEPORT *pPrt;
+- SK_U16 ResAb; /* Resolved Ability */
+- SK_U16 LPAb; /* Link Partner Ability */
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("AutoNegDoneXmac, Port %d\n", Port));
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- /* Get PHY parameters */
+- SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LPAb);
+- SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
+-
+- if ((LPAb & PHY_X_AN_RFB) != 0) {
+- /* At least one of the remote fault bit is set */
+- /* Error */
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("AutoNegFail: Remote fault bit set Port %d\n", Port));
+- pPrt->PAutoNegFail = SK_TRUE;
+- return(SK_AND_OTHER);
+- }
+-
+- /* Check Duplex mismatch */
+- if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) {
+- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
+- }
+- else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) {
+- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
+- }
+- else {
+- /* Error */
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
+- pPrt->PAutoNegFail = SK_TRUE;
+- return(SK_AND_DUP_CAP);
+- }
+-
+- /* Check PAUSE mismatch */
+- /* We are NOT using chapter 4.23 of the Xaqti manual */
+- /* We are using IEEE 802.3z/D5.0 Table 37-4 */
+- if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC ||
+- pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) &&
+- (LPAb & PHY_X_P_SYM_MD) != 0) {
+- /* Symmetric PAUSE */
+- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
+- }
+- else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM &&
+- (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) {
+- /* Enable PAUSE receive, disable PAUSE transmit */
+- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
+- }
+- else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND &&
+- (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) {
+- /* Disable PAUSE receive, enable PAUSE transmit */
+- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
+- }
+- else {
+- /* PAUSE mismatch -> no PAUSE */
+- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
+- }
+- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
+-
+- return(SK_AND_OK);
+-} /* SkXmAutoNegDoneXmac */
+-
+-
+-/******************************************************************************
+- *
+- * SkXmAutoNegDoneBcom() - Auto-negotiation handling
+- *
+- * Description:
+- * This function handles the auto-negotiation if the Done bit is set.
+- *
+- * Returns:
+- * SK_AND_OK o.k.
+- * SK_AND_DUP_CAP Duplex capability error happened
+- * SK_AND_OTHER Other error happened
+- */
+-static int SkXmAutoNegDoneBcom(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_GEPORT *pPrt;
+- SK_U16 LPAb; /* Link Partner Ability */
+- SK_U16 AuxStat; /* Auxiliary Status */
+-
+-#ifdef TEST_ONLY
+-01-Sep-2000 RA;:;:
+- SK_U16 ResAb; /* Resolved Ability */
+-#endif /* 0 */
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("AutoNegDoneBcom, Port %d\n", Port));
+- pPrt = &pAC->GIni.GP[Port];
+-
+- /* Get PHY parameters */
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LPAb);
+-#ifdef TEST_ONLY
+-01-Sep-2000 RA;:;:
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
+-#endif /* 0 */
+-
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat);
+-
+- if ((LPAb & PHY_B_AN_RF) != 0) {
+- /* Remote fault bit is set: Error */
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("AutoNegFail: Remote fault bit set Port %d\n", Port));
+- pPrt->PAutoNegFail = SK_TRUE;
+- return(SK_AND_OTHER);
+- }
+-
+- /* Check Duplex mismatch */
+- if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) {
+- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
+- }
+- else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) {
+- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
+- }
+- else {
+- /* Error */
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
+- pPrt->PAutoNegFail = SK_TRUE;
+- return(SK_AND_DUP_CAP);
+- }
+-
+-#ifdef TEST_ONLY
+-01-Sep-2000 RA;:;:
+- /* Check Master/Slave resolution */
+- if ((ResAb & PHY_B_1000S_MSF) != 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Master/Slave Fault Port %d\n", Port));
+- pPrt->PAutoNegFail = SK_TRUE;
+- pPrt->PMSStatus = SK_MS_STAT_FAULT;
+- return(SK_AND_OTHER);
+- }
+-
+- pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
+- SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
+-#endif /* 0 */
+-
+- /* Check PAUSE mismatch ??? */
+- /* We are using IEEE 802.3z/D5.0 Table 37-4 */
+- if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PAUSE_MSK) {
+- /* Symmetric PAUSE */
+- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
+- }
+- else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) {
+- /* Enable PAUSE receive, disable PAUSE transmit */
+- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
+- }
+- else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRT) {
+- /* Disable PAUSE receive, enable PAUSE transmit */
+- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
+- }
+- else {
+- /* PAUSE mismatch -> no PAUSE */
+- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
+- }
+- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
+-
+- return(SK_AND_OK);
+-} /* SkXmAutoNegDoneBcom */
+-#endif /* GENESIS */
+-
+-
+-#ifdef YUKON
+-/******************************************************************************
+- *
+- * SkGmAutoNegDoneMarv() - Auto-negotiation handling
+- *
+- * Description:
+- * This function handles the auto-negotiation if the Done bit is set.
+- *
+- * Returns:
+- * SK_AND_OK o.k.
+- * SK_AND_DUP_CAP Duplex capability error happened
+- * SK_AND_OTHER Other error happened
+- */
+-static int SkGmAutoNegDoneMarv(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_GEPORT *pPrt;
+- SK_U16 LPAb; /* Link Partner Ability */
+- SK_U16 ResAb; /* Resolved Ability */
+- SK_U16 AuxStat; /* Auxiliary Status */
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("AutoNegDoneMarv, Port %d\n", Port));
+- pPrt = &pAC->GIni.GP[Port];
+-
+- /* Get PHY parameters */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Link P.Abil.=0x%04X\n", LPAb));
+-
+- if ((LPAb & PHY_M_AN_RF) != 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("AutoNegFail: Remote fault bit set Port %d\n", Port));
+- pPrt->PAutoNegFail = SK_TRUE;
+- return(SK_AND_OTHER);
+- }
+-
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
+-
+- /* Check Master/Slave resolution */
+- if ((ResAb & PHY_B_1000S_MSF) != 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Master/Slave Fault Port %d\n", Port));
+- pPrt->PAutoNegFail = SK_TRUE;
+- pPrt->PMSStatus = SK_MS_STAT_FAULT;
+- return(SK_AND_OTHER);
+- }
+-
+- pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
+- (SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE;
+-
+- /* Read PHY Specific Status */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &AuxStat);
+-
+- /* Check Speed & Duplex resolved */
+- if ((AuxStat & PHY_M_PS_SPDUP_RES) == 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("AutoNegFail: Speed & Duplex not resolved, Port %d\n", Port));
+- pPrt->PAutoNegFail = SK_TRUE;
+- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
+- return(SK_AND_DUP_CAP);
+- }
+-
+- if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) {
+- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
+- }
+- else {
+- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
+- }
+-
+- /* Check PAUSE mismatch ??? */
+- /* We are using IEEE 802.3z/D5.0 Table 37-4 */
+- if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_PAUSE_MSK) {
+- /* Symmetric PAUSE */
+- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
+- }
+- else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_RX_P_EN) {
+- /* Enable PAUSE receive, disable PAUSE transmit */
+- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
+- }
+- else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_TX_P_EN) {
+- /* Disable PAUSE receive, enable PAUSE transmit */
+- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
+- }
+- else {
+- /* PAUSE mismatch -> no PAUSE */
+- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
+- }
+-
+- /* set used link speed */
+- switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) {
+- case (unsigned)PHY_M_PS_SPEED_1000:
+- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
+- break;
+- case PHY_M_PS_SPEED_100:
+- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
+- break;
+- default:
+- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
+- }
+-
+- return(SK_AND_OK);
+-} /* SkGmAutoNegDoneMarv */
+-#endif /* YUKON */
+-
+-
+-#ifdef OTHER_PHY
+-/******************************************************************************
+- *
+- * SkXmAutoNegDoneLone() - Auto-negotiation handling
+- *
+- * Description:
+- * This function handles the auto-negotiation if the Done bit is set.
+- *
+- * Returns:
+- * SK_AND_OK o.k.
+- * SK_AND_DUP_CAP Duplex capability error happened
+- * SK_AND_OTHER Other error happened
+- */
+-static int SkXmAutoNegDoneLone(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_GEPORT *pPrt;
+- SK_U16 ResAb; /* Resolved Ability */
+- SK_U16 LPAb; /* Link Partner Ability */
+- SK_U16 QuickStat; /* Auxiliary Status */
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("AutoNegDoneLone, Port %d\n", Port));
+- pPrt = &pAC->GIni.GP[Port];
+-
+- /* Get PHY parameters */
+- SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LPAb);
+- SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ResAb);
+- SkXmPhyRead(pAC, IoC, Port, PHY_LONE_Q_STAT, &QuickStat);
+-
+- if ((LPAb & PHY_L_AN_RF) != 0) {
+- /* Remote fault bit is set */
+- /* Error */
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("AutoNegFail: Remote fault bit set Port %d\n", Port));
+- pPrt->PAutoNegFail = SK_TRUE;
+- return(SK_AND_OTHER);
+- }
+-
+- /* Check Duplex mismatch */
+- if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) {
+- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
+- }
+- else {
+- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
+- }
+-
+- /* Check Master/Slave resolution */
+- if ((ResAb & PHY_L_1000S_MSF) != 0) {
+- /* Error */
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Master/Slave Fault Port %d\n", Port));
+- pPrt->PAutoNegFail = SK_TRUE;
+- pPrt->PMSStatus = SK_MS_STAT_FAULT;
+- return(SK_AND_OTHER);
+- }
+- else if (ResAb & PHY_L_1000S_MSR) {
+- pPrt->PMSStatus = SK_MS_STAT_MASTER;
+- }
+- else {
+- pPrt->PMSStatus = SK_MS_STAT_SLAVE;
+- }
+-
+- /* Check PAUSE mismatch */
+- /* We are using IEEE 802.3z/D5.0 Table 37-4 */
+- /* we must manually resolve the abilities here */
+- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
+-
+- switch (pPrt->PFlowCtrlMode) {
+- case SK_FLOW_MODE_NONE:
+- /* default */
+- break;
+- case SK_FLOW_MODE_LOC_SEND:
+- if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
+- (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) {
+- /* Disable PAUSE receive, enable PAUSE transmit */
+- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
+- }
+- break;
+- case SK_FLOW_MODE_SYMMETRIC:
+- if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
+- /* Symmetric PAUSE */
+- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
+- }
+- break;
+- case SK_FLOW_MODE_SYM_OR_REM:
+- if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
+- PHY_L_QS_AS_PAUSE) {
+- /* Enable PAUSE receive, disable PAUSE transmit */
+- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
+- }
+- else if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
+- /* Symmetric PAUSE */
+- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
+- }
+- break;
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
+- SKERR_HWI_E016MSG);
+- }
+-
+- return(SK_AND_OK);
+-} /* SkXmAutoNegDoneLone */
+-
+-
+-/******************************************************************************
+- *
+- * SkXmAutoNegDoneNat() - Auto-negotiation handling
+- *
+- * Description:
+- * This function handles the auto-negotiation if the Done bit is set.
+- *
+- * Returns:
+- * SK_AND_OK o.k.
+- * SK_AND_DUP_CAP Duplex capability error happened
+- * SK_AND_OTHER Other error happened
+- */
+-static int SkXmAutoNegDoneNat(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+-/* todo: National */
+- return(SK_AND_OK);
+-} /* SkXmAutoNegDoneNat */
+-#endif /* OTHER_PHY */
+-
+-
+-/******************************************************************************
+- *
+- * SkMacAutoNegDone() - Auto-negotiation handling
+- *
+- * Description: calls the auto-negotiation done routines dep. on board type
+- *
+- * Returns:
+- * SK_AND_OK o.k.
+- * SK_AND_DUP_CAP Duplex capability error happened
+- * SK_AND_OTHER Other error happened
+- */
+-int SkMacAutoNegDone(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_GEPORT *pPrt;
+- int Rtv;
+-
+- Rtv = SK_AND_OK;
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+-
+- switch (pPrt->PhyType) {
+-
+- case SK_PHY_XMAC:
+- Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port);
+- break;
+- case SK_PHY_BCOM:
+- Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port);
+- break;
+-#ifdef OTHER_PHY
+- case SK_PHY_LONE:
+- Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port);
+- break;
+- case SK_PHY_NAT:
+- Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port);
+- break;
+-#endif /* OTHER_PHY */
+- default:
+- return(SK_AND_OTHER);
+- }
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIYukon) {
+-
+- Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port);
+- }
+-#endif /* YUKON */
+-
+- if (Rtv != SK_AND_OK) {
+- return(Rtv);
+- }
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("AutoNeg done Port %d\n", Port));
+-
+- /* We checked everything and may now enable the link */
+- pPrt->PAutoNegFail = SK_FALSE;
+-
+- SkMacRxTxEnable(pAC, IoC, Port);
+-
+- return(SK_AND_OK);
+-} /* SkMacAutoNegDone */
+-
+-
+-/******************************************************************************
+- *
+- * SkMacRxTxEnable() - Enable Rx/Tx activity if port is up
+- *
+- * Description: enables Rx/Tx dep. on board type
+- *
+- * Returns:
+- * 0 o.k.
+- * != 0 Error happened
+- */
+-int SkMacRxTxEnable(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_GEPORT *pPrt;
+- SK_U16 Reg; /* 16-bit register value */
+- SK_U16 IntMask; /* MAC interrupt mask */
+-#ifdef GENESIS
+- SK_U16 SWord;
+-#endif
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- if (!pPrt->PHWLinkUp) {
+- /* The Hardware link is NOT up */
+- return(0);
+- }
+-
+- if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF ||
+- pPrt->PLinkMode == SK_LMODE_AUTOFULL ||
+- pPrt->PLinkMode == SK_LMODE_AUTOBOTH) &&
+- pPrt->PAutoNegFail) {
+- /* Auto-negotiation is not done or failed */
+- return(0);
+- }
+-
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+- /* set Duplex Mode and Pause Mode */
+- SkXmInitDupMd(pAC, IoC, Port);
+-
+- SkXmInitPauseMd(pAC, IoC, Port);
+-
+- /*
+- * Initialize the Interrupt Mask Register. Default IRQs are...
+- * - Link Asynchronous Event
+- * - Link Partner requests config
+- * - Auto Negotiation Done
+- * - Rx Counter Event Overflow
+- * - Tx Counter Event Overflow
+- * - Transmit FIFO Underrun
+- */
+- IntMask = XM_DEF_MSK;
+-
+-#ifdef DEBUG
+- /* add IRQ for Receive FIFO Overflow */
+- IntMask &= ~XM_IS_RXF_OV;
+-#endif /* DEBUG */
+-
+- if (pPrt->PhyType != SK_PHY_XMAC) {
+- /* disable GP0 interrupt bit */
+- IntMask |= XM_IS_INP_ASS;
+- }
+- XM_OUT16(IoC, Port, XM_IMSK, IntMask);
+-
+- /* get MMU Command Reg. */
+- XM_IN16(IoC, Port, XM_MMU_CMD, &Reg);
+-
+- if (pPrt->PhyType != SK_PHY_XMAC &&
+- (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
+- pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL)) {
+- /* set to Full Duplex */
+- Reg |= XM_MMU_GMII_FD;
+- }
+-
+- switch (pPrt->PhyType) {
+- case SK_PHY_BCOM:
+- /*
+- * Workaround BCOM Errata (#10523) for all BCom Phys
+- * Enable Power Management after link up
+- */
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
+- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
+- (SK_U16)(SWord & ~PHY_B_AC_DIS_PM));
+- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK,
+- (SK_U16)PHY_B_DEF_MSK);
+- break;
+-#ifdef OTHER_PHY
+- case SK_PHY_LONE:
+- SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, PHY_L_DEF_MSK);
+- break;
+- case SK_PHY_NAT:
+- /* todo National:
+- SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, PHY_N_DEF_MSK); */
+- /* no interrupts possible from National ??? */
+- break;
+-#endif /* OTHER_PHY */
+- }
+-
+- /* enable Rx/Tx */
+- XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIYukon) {
+- /*
+- * Initialize the Interrupt Mask Register. Default IRQs are...
+- * - Rx Counter Event Overflow
+- * - Tx Counter Event Overflow
+- * - Transmit FIFO Underrun
+- */
+- IntMask = GMAC_DEF_MSK;
+-
+-#ifdef DEBUG
+- /* add IRQ for Receive FIFO Overrun */
+- IntMask |= GM_IS_RX_FF_OR;
+-#endif /* DEBUG */
+-
+- SK_OUT8(IoC, GMAC_IRQ_MSK, (SK_U8)IntMask);
+-
+- /* get General Purpose Control */
+- GM_IN16(IoC, Port, GM_GP_CTRL, &Reg);
+-
+- if (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
+- pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) {
+- /* set to Full Duplex */
+- Reg |= GM_GPCR_DUP_FULL;
+- }
+-
+- /* enable Rx/Tx */
+- GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Reg | GM_GPCR_RX_ENA |
+- GM_GPCR_TX_ENA));
+-
+-#ifndef VCPU
+- /* Enable all PHY interrupts */
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK,
+- (SK_U16)PHY_M_DEF_MSK);
+-#endif /* VCPU */
+- }
+-#endif /* YUKON */
+-
+- return(0);
+-
+-} /* SkMacRxTxEnable */
+-
+-
+-/******************************************************************************
+- *
+- * SkMacRxTxDisable() - Disable Receiver and Transmitter
+- *
+- * Description: disables Rx/Tx dep. on board type
+- *
+- * Returns: N/A
+- */
+-void SkMacRxTxDisable(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_U16 Word;
+-
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+-
+- XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
+-
+- XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
+-
+- /* dummy read to ensure writing */
+- XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIYukon) {
+-
+- GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
+-
+- GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Word & ~(GM_GPCR_RX_ENA |
+- GM_GPCR_TX_ENA)));
+-
+- /* dummy read to ensure writing */
+- GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
+- }
+-#endif /* YUKON */
+-
+-} /* SkMacRxTxDisable */
+-
+-
+-/******************************************************************************
+- *
+- * SkMacIrqDisable() - Disable IRQ from MAC
+- *
+- * Description: sets the IRQ-mask to disable IRQ dep. on board type
+- *
+- * Returns: N/A
+- */
+-void SkMacIrqDisable(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_GEPORT *pPrt;
+-#ifdef GENESIS
+- SK_U16 Word;
+-#endif
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+-
+- /* disable all XMAC IRQs */
+- XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
+-
+- /* Disable all PHY interrupts */
+- switch (pPrt->PhyType) {
+- case SK_PHY_BCOM:
+- /* Make sure that PHY is initialized */
+- if (pPrt->PState != SK_PRT_RESET) {
+- /* NOT allowed if BCOM is in RESET state */
+- /* Workaround BCOM Errata (#10523) all BCom */
+- /* Disable Power Management if link is down */
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Word);
+- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
+- (SK_U16)(Word | PHY_B_AC_DIS_PM));
+- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
+- }
+- break;
+-#ifdef OTHER_PHY
+- case SK_PHY_LONE:
+- SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
+- break;
+- case SK_PHY_NAT:
+- /* todo: National
+- SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
+- break;
+-#endif /* OTHER_PHY */
+- }
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIYukon) {
+- /* disable all GMAC IRQs */
+- SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
+-
+-#ifndef VCPU
+- /* Disable all PHY interrupts */
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
+-#endif /* VCPU */
+- }
+-#endif /* YUKON */
+-
+-} /* SkMacIrqDisable */
+-
+-
+-#ifdef SK_DIAG
+-/******************************************************************************
+- *
+- * SkXmSendCont() - Enable / Disable Send Continuous Mode
+- *
+- * Description: enable / disable Send Continuous Mode on XMAC
+- *
+- * Returns:
+- * nothing
+- */
+-void SkXmSendCont(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port, /* Port Index (MAC_1 + n) */
+-SK_BOOL Enable) /* Enable / Disable */
+-{
+- SK_U32 MdReg;
+-
+- XM_IN32(IoC, Port, XM_MODE, &MdReg);
+-
+- if (Enable) {
+- MdReg |= XM_MD_TX_CONT;
+- }
+- else {
+- MdReg &= ~XM_MD_TX_CONT;
+- }
+- /* setup Mode Register */
+- XM_OUT32(IoC, Port, XM_MODE, MdReg);
+-
+-} /* SkXmSendCont */
+-
+-
+-/******************************************************************************
+- *
+- * SkMacTimeStamp() - Enable / Disable Time Stamp
+- *
+- * Description: enable / disable Time Stamp generation for Rx packets
+- *
+- * Returns:
+- * nothing
+- */
+-void SkMacTimeStamp(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port, /* Port Index (MAC_1 + n) */
+-SK_BOOL Enable) /* Enable / Disable */
+-{
+- SK_U32 MdReg;
+- SK_U8 TimeCtrl;
+-
+- if (pAC->GIni.GIGenesis) {
+-
+- XM_IN32(IoC, Port, XM_MODE, &MdReg);
+-
+- if (Enable) {
+- MdReg |= XM_MD_ATS;
+- }
+- else {
+- MdReg &= ~XM_MD_ATS;
+- }
+- /* setup Mode Register */
+- XM_OUT32(IoC, Port, XM_MODE, MdReg);
+- }
+- else {
+- if (Enable) {
+- TimeCtrl = GMT_ST_START | GMT_ST_CLR_IRQ;
+- }
+- else {
+- TimeCtrl = GMT_ST_STOP | GMT_ST_CLR_IRQ;
+- }
+- /* Start/Stop Time Stamp Timer */
+- SK_OUT8(IoC, GMAC_TI_ST_CTRL, TimeCtrl);
+- }
+-
+-} /* SkMacTimeStamp*/
+-
+-#else /* !SK_DIAG */
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- * SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg
+- *
+- * This function analyses the Interrupt status word. If any of the
+- * Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable
+- * is set true.
+- */
+-void SkXmAutoNegLipaXmac(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port, /* Port Index (MAC_1 + n) */
+-SK_U16 IStatus) /* Interrupt Status word to analyse */
+-{
+- SK_GEPORT *pPrt;
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
+- (IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) {
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("AutoNegLipa: AutoNeg detected on Port %d, IStatus=0x%04X\n",
+- Port, IStatus));
+- pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
+- }
+-} /* SkXmAutoNegLipaXmac */
+-#endif /* GENESIS */
+-
+-
+-/******************************************************************************
+- *
+- * SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg
+- *
+- * This function analyses the PHY status word.
+- * If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable
+- * is set true.
+- */
+-void SkMacAutoNegLipaPhy(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port, /* Port Index (MAC_1 + n) */
+-SK_U16 PhyStat) /* PHY Status word to analyse */
+-{
+- SK_GEPORT *pPrt;
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
+- (PhyStat & PHY_ST_AN_OVER) != 0) {
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("AutoNegLipa: AutoNeg detected on Port %d, PhyStat=0x%04X\n",
+- Port, PhyStat));
+- pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
+- }
+-} /* SkMacAutoNegLipaPhy */
+-
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- * SkXmIrq() - Interrupt Service Routine
+- *
+- * Description: services an Interrupt Request of the XMAC
+- *
+- * Note:
+- * With an external PHY, some interrupt bits are not meaningfull any more:
+- * - LinkAsyncEvent (bit #14) XM_IS_LNK_AE
+- * - LinkPartnerReqConfig (bit #10) XM_IS_LIPA_RC
+- * - Page Received (bit #9) XM_IS_RX_PAGE
+- * - NextPageLoadedForXmt (bit #8) XM_IS_TX_PAGE
+- * - AutoNegDone (bit #7) XM_IS_AND
+- * Also probably not valid any more is the GP0 input bit:
+- * - GPRegisterBit0set XM_IS_INP_ASS
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkXmIrq(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_GEPORT *pPrt;
+- SK_EVPARA Para;
+- SK_U16 IStatus; /* Interrupt status read from the XMAC */
+- SK_U16 IStatus2;
+-#ifdef SK_SLIM
+- SK_U64 OverflowStatus;
+-#endif
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- XM_IN16(IoC, Port, XM_ISRC, &IStatus);
+-
+- /* LinkPartner Auto-negable? */
+- if (pPrt->PhyType == SK_PHY_XMAC) {
+- SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus);
+- }
+- else {
+- /* mask bits that are not used with ext. PHY */
+- IStatus &= ~(XM_IS_LNK_AE | XM_IS_LIPA_RC |
+- XM_IS_RX_PAGE | XM_IS_TX_PAGE |
+- XM_IS_AND | XM_IS_INP_ASS);
+- }
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("XmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
+-
+- if (!pPrt->PHWLinkUp) {
+- /* Spurious XMAC interrupt */
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("SkXmIrq: spurious interrupt on Port %d\n", Port));
+- return;
+- }
+-
+- if ((IStatus & XM_IS_INP_ASS) != 0) {
+- /* Reread ISR Register if link is not in sync */
+- XM_IN16(IoC, Port, XM_ISRC, &IStatus2);
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("SkXmIrq: Link async. Double check Port %d 0x%04X 0x%04X\n",
+- Port, IStatus, IStatus2));
+- IStatus &= ~XM_IS_INP_ASS;
+- IStatus |= IStatus2;
+- }
+-
+- if ((IStatus & XM_IS_LNK_AE) != 0) {
+- /* not used, GP0 is used instead */
+- }
+-
+- if ((IStatus & XM_IS_TX_ABORT) != 0) {
+- /* not used */
+- }
+-
+- if ((IStatus & XM_IS_FRC_INT) != 0) {
+- /* not used, use ASIC IRQ instead if needed */
+- }
+-
+- if ((IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) != 0) {
+- SkHWLinkDown(pAC, IoC, Port);
+-
+- /* Signal to RLMT */
+- Para.Para32[0] = (SK_U32)Port;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+-
+- /* Start workaround Errata #2 timer */
+- SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
+- SKGE_HWAC, SK_HWEV_WATIM, Para);
+- }
+-
+- if ((IStatus & XM_IS_RX_PAGE) != 0) {
+- /* not used */
+- }
+-
+- if ((IStatus & XM_IS_TX_PAGE) != 0) {
+- /* not used */
+- }
+-
+- if ((IStatus & XM_IS_AND) != 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("SkXmIrq: AND on link that is up Port %d\n", Port));
+- }
+-
+- if ((IStatus & XM_IS_TSC_OV) != 0) {
+- /* not used */
+- }
+-
+- /* Combined Tx & Rx Counter Overflow SIRQ Event */
+- if ((IStatus & (XM_IS_RXC_OV | XM_IS_TXC_OV)) != 0) {
+-#ifdef SK_SLIM
+- SkXmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
+-#else
+- Para.Para32[0] = (SK_U32)Port;
+- Para.Para32[1] = (SK_U32)IStatus;
+- SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
+-#endif /* SK_SLIM */
+- }
+-
+- if ((IStatus & XM_IS_RXF_OV) != 0) {
+- /* normal situation -> no effect */
+-#ifdef DEBUG
+- pPrt->PRxOverCnt++;
+-#endif /* DEBUG */
+- }
+-
+- if ((IStatus & XM_IS_TXF_UR) != 0) {
+- /* may NOT happen -> error log */
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
+- }
+-
+- if ((IStatus & XM_IS_TX_COMP) != 0) {
+- /* not served here */
+- }
+-
+- if ((IStatus & XM_IS_RX_COMP) != 0) {
+- /* not served here */
+- }
+-} /* SkXmIrq */
+-#endif /* GENESIS */
+-
+-
+-#ifdef YUKON
+-/******************************************************************************
+- *
+- * SkGmIrq() - Interrupt Service Routine
+- *
+- * Description: services an Interrupt Request of the GMAC
+- *
+- * Note:
+- *
+- * Returns:
+- * nothing
+- */
+-static void SkGmIrq(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_GEPORT *pPrt;
+- SK_U8 IStatus; /* Interrupt status */
+-#ifdef SK_SLIM
+- SK_U64 OverflowStatus;
+-#else
+- SK_EVPARA Para;
+-#endif
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- SK_IN8(IoC, GMAC_IRQ_SRC, &IStatus);
+-
+-#ifdef XXX
+- /* LinkPartner Auto-negable? */
+- SkMacAutoNegLipaPhy(pAC, IoC, Port, IStatus);
+-#endif /* XXX */
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("GmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
+-
+- /* Combined Tx & Rx Counter Overflow SIRQ Event */
+- if (IStatus & (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV)) {
+- /* these IRQs will be cleared by reading GMACs register */
+-#ifdef SK_SLIM
+- SkGmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
+-#else
+- Para.Para32[0] = (SK_U32)Port;
+- Para.Para32[1] = (SK_U32)IStatus;
+- SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
+-#endif
+- }
+-
+- if (IStatus & GM_IS_RX_FF_OR) {
+- /* clear GMAC Rx FIFO Overrun IRQ */
+- SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FO);
+-#ifdef DEBUG
+- pPrt->PRxOverCnt++;
+-#endif /* DEBUG */
+- }
+-
+- if (IStatus & GM_IS_TX_FF_UR) {
+- /* clear GMAC Tx FIFO Underrun IRQ */
+- SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FU);
+- /* may NOT happen -> error log */
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
+- }
+-
+- if (IStatus & GM_IS_TX_COMPL) {
+- /* not served here */
+- }
+-
+- if (IStatus & GM_IS_RX_COMPL) {
+- /* not served here */
+- }
+-} /* SkGmIrq */
+-#endif /* YUKON */
+-
+-
+-/******************************************************************************
+- *
+- * SkMacIrq() - Interrupt Service Routine for MAC
+- *
+- * Description: calls the Interrupt Service Routine dep. on board type
+- *
+- * Returns:
+- * nothing
+- */
+-void SkMacIrq(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index (MAC_1 + n) */
+-{
+-#ifdef GENESIS
+- if (pAC->GIni.GIGenesis) {
+- /* IRQ from XMAC */
+- SkXmIrq(pAC, IoC, Port);
+- }
+-#endif /* GENESIS */
+-
+-#ifdef YUKON
+- if (pAC->GIni.GIYukon) {
+- /* IRQ from GMAC */
+- SkGmIrq(pAC, IoC, Port);
+- }
+-#endif /* YUKON */
+-
+-} /* SkMacIrq */
+-
+-#endif /* !SK_DIAG */
+-
+-#ifdef GENESIS
+-/******************************************************************************
+- *
+- * SkXmUpdateStats() - Force the XMAC to output the current statistic
+- *
+- * Description:
+- * The XMAC holds its statistic internally. To obtain the current
+- * values a command must be sent so that the statistic data will
+- * be written to a predefined memory area on the adapter.
+- *
+- * Returns:
+- * 0: success
+- * 1: something went wrong
+- */
+-int SkXmUpdateStats(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-unsigned int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_GEPORT *pPrt;
+- SK_U16 StatReg;
+- int WaitIndex;
+-
+- pPrt = &pAC->GIni.GP[Port];
+- WaitIndex = 0;
+-
+- /* Send an update command to XMAC specified */
+- XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC);
+-
+- /*
+- * It is an auto-clearing register. If the command bits
+- * went to zero again, the statistics are transferred.
+- * Normally the command should be executed immediately.
+- * But just to be sure we execute a loop.
+- */
+- do {
+-
+- XM_IN16(IoC, Port, XM_STAT_CMD, &StatReg);
+-
+- if (++WaitIndex > 10) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E021, SKERR_HWI_E021MSG);
+-
+- return(1);
+- }
+- } while ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) != 0);
+-
+- return(0);
+-} /* SkXmUpdateStats */
+-
+-
+-/******************************************************************************
+- *
+- * SkXmMacStatistic() - Get XMAC counter value
+- *
+- * Description:
+- * Gets the 32bit counter value. Except for the octet counters
+- * the lower 32bit are counted in hardware and the upper 32bit
+- * must be counted in software by monitoring counter overflow interrupts.
+- *
+- * Returns:
+- * 0: success
+- * 1: something went wrong
+- */
+-int SkXmMacStatistic(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-unsigned int Port, /* Port Index (MAC_1 + n) */
+-SK_U16 StatAddr, /* MIB counter base address */
+-SK_U32 SK_FAR *pVal) /* ptr to return statistic value */
+-{
+- if ((StatAddr < XM_TXF_OK) || (StatAddr > XM_RXF_MAX_SZ)) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
+-
+- return(1);
+- }
+-
+- XM_IN32(IoC, Port, StatAddr, pVal);
+-
+- return(0);
+-} /* SkXmMacStatistic */
+-
+-
+-/******************************************************************************
+- *
+- * SkXmResetCounter() - Clear MAC statistic counter
+- *
+- * Description:
+- * Force the XMAC to clear its statistic counter.
+- *
+- * Returns:
+- * 0: success
+- * 1: something went wrong
+- */
+-int SkXmResetCounter(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-unsigned int Port) /* Port Index (MAC_1 + n) */
+-{
+- XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
+- /* Clear two times according to Errata #3 */
+- XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
+-
+- return(0);
+-} /* SkXmResetCounter */
+-
+-
+-/******************************************************************************
+- *
+- * SkXmOverflowStatus() - Gets the status of counter overflow interrupt
+- *
+- * Description:
+- * Checks the source causing an counter overflow interrupt. On success the
+- * resulting counter overflow status is written to <pStatus>, whereas the
+- * upper dword stores the XMAC ReceiveCounterEvent register and the lower
+- * dword the XMAC TransmitCounterEvent register.
+- *
+- * Note:
+- * For XMAC the interrupt source is a self-clearing register, so the source
+- * must be checked only once. SIRQ module does another check to be sure
+- * that no interrupt get lost during process time.
+- *
+- * Returns:
+- * 0: success
+- * 1: something went wrong
+- */
+-int SkXmOverflowStatus(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-unsigned int Port, /* Port Index (MAC_1 + n) */
+-SK_U16 IStatus, /* Interupt Status from MAC */
+-SK_U64 SK_FAR *pStatus) /* ptr for return overflow status value */
+-{
+- SK_U64 Status; /* Overflow status */
+- SK_U32 RegVal;
+-
+- Status = 0;
+-
+- if ((IStatus & XM_IS_RXC_OV) != 0) {
+-
+- XM_IN32(IoC, Port, XM_RX_CNT_EV, &RegVal);
+- Status |= (SK_U64)RegVal << 32;
+- }
+-
+- if ((IStatus & XM_IS_TXC_OV) != 0) {
+-
+- XM_IN32(IoC, Port, XM_TX_CNT_EV, &RegVal);
+- Status |= (SK_U64)RegVal;
+- }
+-
+- *pStatus = Status;
+-
+- return(0);
+-} /* SkXmOverflowStatus */
+-#endif /* GENESIS */
+-
+-
+-#ifdef YUKON
+-/******************************************************************************
+- *
+- * SkGmUpdateStats() - Force the GMAC to output the current statistic
+- *
+- * Description:
+- * Empty function for GMAC. Statistic data is accessible in direct way.
+- *
+- * Returns:
+- * 0: success
+- * 1: something went wrong
+- */
+-int SkGmUpdateStats(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-unsigned int Port) /* Port Index (MAC_1 + n) */
+-{
+- return(0);
+-}
+-
+-
+-/******************************************************************************
+- *
+- * SkGmMacStatistic() - Get GMAC counter value
+- *
+- * Description:
+- * Gets the 32bit counter value. Except for the octet counters
+- * the lower 32bit are counted in hardware and the upper 32bit
+- * must be counted in software by monitoring counter overflow interrupts.
+- *
+- * Returns:
+- * 0: success
+- * 1: something went wrong
+- */
+-int SkGmMacStatistic(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-unsigned int Port, /* Port Index (MAC_1 + n) */
+-SK_U16 StatAddr, /* MIB counter base address */
+-SK_U32 SK_FAR *pVal) /* ptr to return statistic value */
+-{
+-
+- if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) {
+-
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr));
+- return(1);
+- }
+-
+- GM_IN32(IoC, Port, StatAddr, pVal);
+-
+- return(0);
+-} /* SkGmMacStatistic */
+-
+-
+-/******************************************************************************
+- *
+- * SkGmResetCounter() - Clear MAC statistic counter
+- *
+- * Description:
+- * Force GMAC to clear its statistic counter.
+- *
+- * Returns:
+- * 0: success
+- * 1: something went wrong
+- */
+-int SkGmResetCounter(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-unsigned int Port) /* Port Index (MAC_1 + n) */
+-{
+- SK_U16 Reg; /* Phy Address Register */
+- SK_U16 Word;
+- int i;
+-
+- GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg);
+-
+- /* set MIB Clear Counter Mode */
+- GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR);
+-
+- /* read all MIB Counters with Clear Mode set */
+- for (i = 0; i < GM_MIB_CNT_SIZE; i++) {
+- /* the reset is performed only when the lower 16 bits are read */
+- GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word);
+- }
+-
+- /* clear MIB Clear Counter Mode */
+- GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg);
+-
+- return(0);
+-} /* SkGmResetCounter */
+-
+-
+-/******************************************************************************
+- *
+- * SkGmOverflowStatus() - Gets the status of counter overflow interrupt
+- *
+- * Description:
+- * Checks the source causing an counter overflow interrupt. On success the
+- * resulting counter overflow status is written to <pStatus>, whereas the
+- * the following bit coding is used:
+- * 63:56 - unused
+- * 55:48 - TxRx interrupt register bit7:0
+- * 32:47 - Rx interrupt register
+- * 31:24 - unused
+- * 23:16 - TxRx interrupt register bit15:8
+- * 15:0 - Tx interrupt register
+- *
+- * Returns:
+- * 0: success
+- * 1: something went wrong
+- */
+-int SkGmOverflowStatus(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-unsigned int Port, /* Port Index (MAC_1 + n) */
+-SK_U16 IStatus, /* Interupt Status from MAC */
+-SK_U64 SK_FAR *pStatus) /* ptr for return overflow status value */
+-{
+- SK_U64 Status; /* Overflow status */
+- SK_U16 RegVal;
+-
+- Status = 0;
+-
+- if ((IStatus & GM_IS_RX_CO_OV) != 0) {
+- /* this register is self-clearing after read */
+- GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal);
+- Status |= (SK_U64)RegVal << 32;
+- }
+-
+- if ((IStatus & GM_IS_TX_CO_OV) != 0) {
+- /* this register is self-clearing after read */
+- GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal);
+- Status |= (SK_U64)RegVal;
+- }
+-
+- /* this register is self-clearing after read */
+- GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal);
+- /* Rx overflow interrupt register bits (LoByte)*/
+- Status |= (SK_U64)((SK_U8)RegVal) << 48;
+- /* Tx overflow interrupt register bits (HiByte)*/
+- Status |= (SK_U64)(RegVal >> 8) << 16;
+-
+- *pStatus = Status;
+-
+- return(0);
+-} /* SkGmOverflowStatus */
+-
+-
+-#ifndef SK_SLIM
+-/******************************************************************************
+- *
+- * SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test
+- *
+- * Description:
+- * starts the cable diagnostic test if 'StartTest' is true
+- * gets the results if 'StartTest' is true
+- *
+- * NOTE: this test is meaningful only when link is down
+- *
+- * Returns:
+- * 0: success
+- * 1: no YUKON copper
+- * 2: test in progress
+- */
+-int SkGmCableDiagStatus(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port, /* Port Index (MAC_1 + n) */
+-SK_BOOL StartTest) /* flag for start / get result */
+-{
+- int i;
+- SK_U16 RegVal;
+- SK_GEPORT *pPrt;
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+- if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
+-
+- return(1);
+- }
+-
+- if (StartTest) {
+- /* only start the cable test */
+- if ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4) {
+- /* apply TDR workaround from Marvell */
+- SkGmPhyWrite(pAC, IoC, Port, 29, 0x001e);
+-
+- SkGmPhyWrite(pAC, IoC, Port, 30, 0xcc00);
+- SkGmPhyWrite(pAC, IoC, Port, 30, 0xc800);
+- SkGmPhyWrite(pAC, IoC, Port, 30, 0xc400);
+- SkGmPhyWrite(pAC, IoC, Port, 30, 0xc000);
+- SkGmPhyWrite(pAC, IoC, Port, 30, 0xc100);
+- }
+-
+- /* set address to 0 for MDI[0] */
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
+-
+- /* Read Cable Diagnostic Reg */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
+-
+- /* start Cable Diagnostic Test */
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CABLE_DIAG,
+- (SK_U16)(RegVal | PHY_M_CABD_ENA_TEST));
+-
+- return(0);
+- }
+-
+- /* Read Cable Diagnostic Reg */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("PHY Cable Diag.=0x%04X\n", RegVal));
+-
+- if ((RegVal & PHY_M_CABD_ENA_TEST) != 0) {
+- /* test is running */
+- return(2);
+- }
+-
+- /* get the test results */
+- for (i = 0; i < 4; i++) {
+- /* set address to i for MDI[i] */
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i);
+-
+- /* get Cable Diagnostic values */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
+-
+- pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK);
+-
+- pPrt->PMdiPairSts[i] = (SK_U8)((RegVal & PHY_M_CABD_STAT_MSK) >> 13);
+- }
+-
+- return(0);
+-} /* SkGmCableDiagStatus */
+-#endif /* !SK_SLIM */
+-#endif /* YUKON */
+-
+-/* End of file */
+diff --git a/drivers/net/skfp/fplustm.c b/drivers/net/skfp/fplustm.c
+index 76dc8ad..6028bbb 100644
+--- a/drivers/net/skfp/fplustm.c
++++ b/drivers/net/skfp/fplustm.c
+@@ -401,18 +401,18 @@ static void copy_tx_mac(struct s_smc *smc, u_long td, struct fddi_mac *mac,
+ /* int len ; length of the frame including the FC */
+ {
+ int i ;
+- u_int *p ;
++ __le32 *p ;
+
+ CHECK_NPP() ;
+ MARW(off) ; /* set memory address reg for writes */
+
+- p = (u_int *) mac ;
++ p = (__le32 *) mac ;
+ for (i = (len + 3)/4 ; i ; i--) {
+ if (i == 1) {
+ /* last word, set the tag bit */
+ outpw(FM_A(FM_CMDREG2),FM_ISTTB) ;
+ }
+- write_mdr(smc,MDR_REVERSE(*p)) ;
++ write_mdr(smc,le32_to_cpu(*p)) ;
+ p++ ;
+ }
+
+@@ -444,7 +444,7 @@ static void copy_tx_mac(struct s_smc *smc, u_long td, struct fddi_mac *mac,
+ */
+ static void directed_beacon(struct s_smc *smc)
+ {
+- SK_LOC_DECL(u_int,a[2]) ;
++ SK_LOC_DECL(__le32,a[2]) ;
+
+ /*
+ * set UNA in frame
+@@ -458,9 +458,9 @@ static void directed_beacon(struct s_smc *smc)
+ CHECK_NPP() ;
+ /* set memory address reg for writes */
+ MARW(smc->hw.fp.fifo.rbc_ram_start+DBEACON_FRAME_OFF+4) ;
+- write_mdr(smc,MDR_REVERSE(a[0])) ;
++ write_mdr(smc,le32_to_cpu(a[0])) ;
+ outpw(FM_A(FM_CMDREG2),FM_ISTTB) ; /* set the tag bit */
+- write_mdr(smc,MDR_REVERSE(a[1])) ;
++ write_mdr(smc,le32_to_cpu(a[1])) ;
+
+ outpw(FM_A(FM_SABC),smc->hw.fp.fifo.rbc_ram_start + DBEACON_FRAME_OFF) ;
+ }
+diff --git a/drivers/net/skfp/h/fplustm.h b/drivers/net/skfp/h/fplustm.h
+index 98bbf65..6d738e1 100644
+--- a/drivers/net/skfp/h/fplustm.h
++++ b/drivers/net/skfp/h/fplustm.h
+@@ -50,12 +50,12 @@ struct err_st {
+ * Transmit Descriptor struct
+ */
+ struct s_smt_fp_txd {
+- u_int txd_tbctrl ; /* transmit buffer control */
+- u_int txd_txdscr ; /* transmit frame status word */
+- u_int txd_tbadr ; /* physical tx buffer address */
+- u_int txd_ntdadr ; /* physical pointer to the next TxD */
++ __le32 txd_tbctrl ; /* transmit buffer control */
++ __le32 txd_txdscr ; /* transmit frame status word */
++ __le32 txd_tbadr ; /* physical tx buffer address */
++ __le32 txd_ntdadr ; /* physical pointer to the next TxD */
+ #ifdef ENA_64BIT_SUP
+- u_int txd_tbadr_hi ; /* physical tx buffer addr (high dword)*/
++ __le32 txd_tbadr_hi ; /* physical tx buffer addr (high dword)*/
+ #endif
+ char far *txd_virt ; /* virtual pointer to the data frag */
+ /* virt pointer to the next TxD */
+@@ -67,12 +67,12 @@ struct s_smt_fp_txd {
+ * Receive Descriptor struct
+ */
+ struct s_smt_fp_rxd {
+- u_int rxd_rbctrl ; /* receive buffer control */
+- u_int rxd_rfsw ; /* receive frame status word */
+- u_int rxd_rbadr ; /* physical rx buffer address */
+- u_int rxd_nrdadr ; /* physical pointer to the next RxD */
++ __le32 rxd_rbctrl ; /* receive buffer control */
++ __le32 rxd_rfsw ; /* receive frame status word */
++ __le32 rxd_rbadr ; /* physical rx buffer address */
++ __le32 rxd_nrdadr ; /* physical pointer to the next RxD */
+ #ifdef ENA_64BIT_SUP
+- u_int rxd_rbadr_hi ; /* physical tx buffer addr (high dword)*/
++ __le32 rxd_rbadr_hi ; /* physical tx buffer addr (high dword)*/
+ #endif
+ char far *rxd_virt ; /* virtual pointer to the data frag */
+ /* virt pointer to the next RxD */
+diff --git a/drivers/net/skfp/hwmtm.c b/drivers/net/skfp/hwmtm.c
+index 46e3393..4218e97 100644
+--- a/drivers/net/skfp/hwmtm.c
++++ b/drivers/net/skfp/hwmtm.c
+@@ -208,7 +208,7 @@ SMbuf* smt_get_mbuf(struct s_smc *smc);
+ #if defined(NDIS_OS2) || defined(ODI2)
+ #define CR_READ(var) ((var) & 0xffff0000 | ((var) & 0xffff))
+ #else
+-#define CR_READ(var) (u_long)(var)
++#define CR_READ(var) (__le32)(var)
+ #endif
+
+ #define IMASK_SLOW (IS_PLINT1 | IS_PLINT2 | IS_TIMINT | IS_TOKEN | \
+@@ -343,16 +343,16 @@ static u_long init_descr_ring(struct s_smc *smc,
+ for (i=count-1, d1=start; i ; i--) {
+ d2 = d1 ;
+ d1++ ; /* descr is owned by the host */
+- d2->r.rxd_rbctrl = AIX_REVERSE(BMU_CHECK) ;
++ d2->r.rxd_rbctrl = cpu_to_le32(BMU_CHECK) ;
+ d2->r.rxd_next = &d1->r ;
+ phys = mac_drv_virt2phys(smc,(void *)d1) ;
+- d2->r.rxd_nrdadr = AIX_REVERSE(phys) ;
++ d2->r.rxd_nrdadr = cpu_to_le32(phys) ;
+ }
+ DB_GEN("descr ring ends at = %x ",(void *)d1,0,3) ;
+- d1->r.rxd_rbctrl = AIX_REVERSE(BMU_CHECK) ;
++ d1->r.rxd_rbctrl = cpu_to_le32(BMU_CHECK) ;
+ d1->r.rxd_next = &start->r ;
+ phys = mac_drv_virt2phys(smc,(void *)start) ;
+- d1->r.rxd_nrdadr = AIX_REVERSE(phys) ;
++ d1->r.rxd_nrdadr = cpu_to_le32(phys) ;
+
+ for (i=count, d1=start; i ; i--) {
+ DRV_BUF_FLUSH(&d1->r,DDI_DMA_SYNC_FORDEV) ;
+@@ -376,7 +376,7 @@ static void init_txd_ring(struct s_smc *smc)
+ DB_GEN("Init async TxD ring, %d TxDs ",HWM_ASYNC_TXD_COUNT,0,3) ;
+ (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,
+ HWM_ASYNC_TXD_COUNT) ;
+- phys = AIX_REVERSE(ds->txd_ntdadr) ;
++ phys = le32_to_cpu(ds->txd_ntdadr) ;
+ ds++ ;
+ queue->tx_curr_put = queue->tx_curr_get = ds ;
+ ds-- ;
+@@ -390,7 +390,7 @@ static void init_txd_ring(struct s_smc *smc)
+ DB_GEN("Init sync TxD ring, %d TxDs ",HWM_SYNC_TXD_COUNT,0,3) ;
+ (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,
+ HWM_SYNC_TXD_COUNT) ;
+- phys = AIX_REVERSE(ds->txd_ntdadr) ;
++ phys = le32_to_cpu(ds->txd_ntdadr) ;
+ ds++ ;
+ queue->tx_curr_put = queue->tx_curr_get = ds ;
+ queue->tx_free = HWM_SYNC_TXD_COUNT ;
+@@ -412,7 +412,7 @@ static void init_rxd_ring(struct s_smc *smc)
+ DB_GEN("Init RxD ring, %d RxDs ",SMT_R1_RXD_COUNT,0,3) ;
+ (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,
+ SMT_R1_RXD_COUNT) ;
+- phys = AIX_REVERSE(ds->rxd_nrdadr) ;
++ phys = le32_to_cpu(ds->rxd_nrdadr) ;
+ ds++ ;
+ queue->rx_curr_put = queue->rx_curr_get = ds ;
+ queue->rx_free = SMT_R1_RXD_COUNT ;
+@@ -607,12 +607,12 @@ static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue)
+ for (i = tx_used+queue->tx_free-1 ; i ; i-- ) {
+ t = t->txd_next ;
+ }
+- phys = AIX_REVERSE(t->txd_ntdadr) ;
++ phys = le32_to_cpu(t->txd_ntdadr) ;
+
+ t = queue->tx_curr_get ;
+ while (tx_used) {
+ DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORCPU) ;
+- tbctrl = AIX_REVERSE(t->txd_tbctrl) ;
++ tbctrl = le32_to_cpu(t->txd_tbctrl) ;
+
+ if (tbctrl & BMU_OWN) {
+ if (tbctrl & BMU_STF) {
+@@ -622,10 +622,10 @@ static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue)
+ /*
+ * repair the descriptor
+ */
+- t->txd_tbctrl &= AIX_REVERSE(~BMU_OWN) ;
++ t->txd_tbctrl &= ~cpu_to_le32(BMU_OWN) ;
+ }
+ }
+- phys = AIX_REVERSE(t->txd_ntdadr) ;
++ phys = le32_to_cpu(t->txd_ntdadr) ;
+ DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
+ t = t->txd_next ;
+ tx_used-- ;
+@@ -659,12 +659,12 @@ static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue)
+ for (i = SMT_R1_RXD_COUNT-1 ; i ; i-- ) {
+ r = r->rxd_next ;
+ }
+- phys = AIX_REVERSE(r->rxd_nrdadr) ;
++ phys = le32_to_cpu(r->rxd_nrdadr) ;
+
+ r = queue->rx_curr_get ;
+ while (rx_used) {
+ DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+- rbctrl = AIX_REVERSE(r->rxd_rbctrl) ;
++ rbctrl = le32_to_cpu(r->rxd_rbctrl) ;
+
+ if (rbctrl & BMU_OWN) {
+ if (rbctrl & BMU_STF) {
+@@ -674,10 +674,10 @@ static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue)
+ /*
+ * repair the descriptor
+ */
+- r->rxd_rbctrl &= AIX_REVERSE(~BMU_OWN) ;
++ r->rxd_rbctrl &= ~cpu_to_le32(BMU_OWN) ;
+ }
+ }
+- phys = AIX_REVERSE(r->rxd_nrdadr) ;
++ phys = le32_to_cpu(r->rxd_nrdadr) ;
+ DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
+ r = r->rxd_next ;
+ rx_used-- ;
+@@ -1094,8 +1094,7 @@ void process_receive(struct s_smc *smc)
+ do {
+ DB_RX("Check RxD %x for OWN and EOF",(void *)r,0,5) ;
+ DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+- rbctrl = CR_READ(r->rxd_rbctrl) ;
+- rbctrl = AIX_REVERSE(rbctrl) ;
++ rbctrl = le32_to_cpu(CR_READ(r->rxd_rbctrl));
+
+ if (rbctrl & BMU_OWN) {
+ NDD_TRACE("RHxE",r,rfsw,rbctrl) ;
+@@ -1118,7 +1117,7 @@ void process_receive(struct s_smc *smc)
+ smc->os.hwm.detec_count = 0 ;
+ goto rx_end ;
+ }
+- rfsw = AIX_REVERSE(r->rxd_rfsw) ;
++ rfsw = le32_to_cpu(r->rxd_rfsw) ;
+ if ((rbctrl & BMU_STF) != ((rbctrl & BMU_ST_BUF) <<5)) {
+ /*
+ * The BMU_STF bit is deleted, 1 frame is
+@@ -1151,7 +1150,7 @@ void process_receive(struct s_smc *smc)
+ /* may be next 2 DRV_BUF_FLUSH() can be skipped, because */
+ /* BMU_ST_BUF will not be changed by the ASIC */
+ DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+- while (rx_used && !(r->rxd_rbctrl & AIX_REVERSE(BMU_ST_BUF))) {
++ while (rx_used && !(r->rxd_rbctrl & cpu_to_le32(BMU_ST_BUF))) {
+ DB_RX("Check STF bit in %x",(void *)r,0,5) ;
+ r = r->rxd_next ;
+ DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+@@ -1171,7 +1170,7 @@ void process_receive(struct s_smc *smc)
+ /*
+ * ASIC Errata no. 7 (STF - Bit Bug)
+ */
+- rxd->rxd_rbctrl &= AIX_REVERSE(~BMU_STF) ;
++ rxd->rxd_rbctrl &= cpu_to_le32(~BMU_STF) ;
+
+ for (r=rxd, i=frag_count ; i ; r=r->rxd_next, i--){
+ DB_RX("dma_complete for RxD %x",(void *)r,0,5) ;
+@@ -1287,7 +1286,7 @@ void process_receive(struct s_smc *smc)
+ hwm_cpy_rxd2mb(rxd,data,len) ;
+ #else
+ for (r=rxd, i=used_frags ; i ; r=r->rxd_next, i--){
+- n = AIX_REVERSE(r->rxd_rbctrl) & RD_LENGTH ;
++ n = le32_to_cpu(r->rxd_rbctrl) & RD_LENGTH ;
+ DB_RX("cp SMT frame to mb: len = %d",n,0,6) ;
+ memcpy(data,r->rxd_virt,n) ;
+ data += n ;
+@@ -1426,14 +1425,14 @@ void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
+ int frame_status)
+ {
+ struct s_smt_fp_rxd volatile *r ;
+- u_int rbctrl ;
++ __le32 rbctrl;
+
+ NDD_TRACE("RHfB",virt,len,frame_status) ;
+ DB_RX("hwm_rx_frag: len = %d, frame_status = %x\n",len,frame_status,2) ;
+ r = smc->hw.fp.rx_q[QUEUE_R1].rx_curr_put ;
+ r->rxd_virt = virt ;
+- r->rxd_rbadr = AIX_REVERSE(phys) ;
+- rbctrl = AIX_REVERSE( (((u_long)frame_status &
++ r->rxd_rbadr = cpu_to_le32(phys) ;
++ rbctrl = cpu_to_le32( (((__u32)frame_status &
+ (FIRST_FRAG|LAST_FRAG))<<26) |
+ (((u_long) frame_status & FIRST_FRAG) << 21) |
+ BMU_OWN | BMU_CHECK | BMU_EN_IRQ_EOF | len) ;
+@@ -1444,7 +1443,7 @@ void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
+ smc->hw.fp.rx_q[QUEUE_R1].rx_free-- ;
+ smc->hw.fp.rx_q[QUEUE_R1].rx_used++ ;
+ smc->hw.fp.rx_q[QUEUE_R1].rx_curr_put = r->rxd_next ;
+- NDD_TRACE("RHfE",r,AIX_REVERSE(r->rxd_rbadr),0) ;
++ NDD_TRACE("RHfE",r,le32_to_cpu(r->rxd_rbadr),0) ;
+ }
+
+ /*
+@@ -1494,15 +1493,15 @@ void mac_drv_clear_rx_queue(struct s_smc *smc)
+ while (queue->rx_used) {
+ DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+ DB_RX("switch OWN bit of RxD 0x%x ",r,0,5) ;
+- r->rxd_rbctrl &= AIX_REVERSE(~BMU_OWN) ;
++ r->rxd_rbctrl &= ~cpu_to_le32(BMU_OWN) ;
+ frag_count = 1 ;
+ DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
+ r = r->rxd_next ;
+ DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+ while (r != queue->rx_curr_put &&
+- !(r->rxd_rbctrl & AIX_REVERSE(BMU_ST_BUF))) {
++ !(r->rxd_rbctrl & cpu_to_le32(BMU_ST_BUF))) {
+ DB_RX("Check STF bit in %x",(void *)r,0,5) ;
+- r->rxd_rbctrl &= AIX_REVERSE(~BMU_OWN) ;
++ r->rxd_rbctrl &= ~cpu_to_le32(BMU_OWN) ;
+ DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
+ r = r->rxd_next ;
+ DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+@@ -1640,7 +1639,7 @@ void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
+ {
+ struct s_smt_fp_txd volatile *t ;
+ struct s_smt_tx_queue *queue ;
+- u_int tbctrl ;
++ __le32 tbctrl ;
+
+ queue = smc->os.hwm.tx_p ;
+
+@@ -1657,9 +1656,9 @@ void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
+ /* '*t' is already defined */
+ DB_TX("LAN_TX: TxD = %x, virt = %x ",t,virt,3) ;
+ t->txd_virt = virt ;
+- t->txd_txdscr = AIX_REVERSE(smc->os.hwm.tx_descr) ;
+- t->txd_tbadr = AIX_REVERSE(phys) ;
+- tbctrl = AIX_REVERSE((((u_long)frame_status &
++ t->txd_txdscr = cpu_to_le32(smc->os.hwm.tx_descr) ;
++ t->txd_tbadr = cpu_to_le32(phys) ;
++ tbctrl = cpu_to_le32((((__u32)frame_status &
+ (FIRST_FRAG|LAST_FRAG|EN_IRQ_EOF))<< 26) |
+ BMU_OWN|BMU_CHECK |len) ;
+ t->txd_tbctrl = tbctrl ;
+@@ -1826,7 +1825,7 @@ void smt_send_mbuf(struct s_smc *smc, SMbuf *mb, int fc)
+ struct s_smt_tx_queue *queue ;
+ struct s_smt_fp_txd volatile *t ;
+ u_long phys ;
+- u_int tbctrl ;
++ __le32 tbctrl;
+
+ NDD_TRACE("THSB",mb,fc,0) ;
+ DB_TX("smt_send_mbuf: mb = 0x%x, fc = 0x%x",mb,fc,4) ;
+@@ -1894,14 +1893,14 @@ void smt_send_mbuf(struct s_smc *smc, SMbuf *mb, int fc)
+ DB_TX("init TxD = 0x%x",(void *)t,0,5) ;
+ if (i == frag_count-1) {
+ frame_status |= LAST_FRAG ;
+- t->txd_txdscr = AIX_REVERSE(TX_DESCRIPTOR |
+- (((u_long)(mb->sm_len-1)&3) << 27)) ;
++ t->txd_txdscr = cpu_to_le32(TX_DESCRIPTOR |
++ (((__u32)(mb->sm_len-1)&3) << 27)) ;
+ }
+ t->txd_virt = virt[i] ;
+ phys = dma_master(smc, (void far *)virt[i],
+ frag_len[i], DMA_RD|SMT_BUF) ;
+- t->txd_tbadr = AIX_REVERSE(phys) ;
+- tbctrl = AIX_REVERSE((((u_long) frame_status &
++ t->txd_tbadr = cpu_to_le32(phys) ;
++ tbctrl = cpu_to_le32((((__u32)frame_status &
+ (FIRST_FRAG|LAST_FRAG)) << 26) |
+ BMU_OWN | BMU_CHECK | BMU_SMT_TX |frag_len[i]) ;
+ t->txd_tbctrl = tbctrl ;
+@@ -1971,8 +1970,7 @@ static void mac_drv_clear_txd(struct s_smc *smc)
+ do {
+ DRV_BUF_FLUSH(t1,DDI_DMA_SYNC_FORCPU) ;
+ DB_TX("check OWN/EOF bit of TxD 0x%x",t1,0,5) ;
+- tbctrl = CR_READ(t1->txd_tbctrl) ;
+- tbctrl = AIX_REVERSE(tbctrl) ;
++ tbctrl = le32_to_cpu(CR_READ(t1->txd_tbctrl));
+
+ if (tbctrl & BMU_OWN || !queue->tx_used){
+ DB_TX("End of TxDs queue %d",i,0,4) ;
+@@ -1984,7 +1982,7 @@ static void mac_drv_clear_txd(struct s_smc *smc)
+
+ t1 = queue->tx_curr_get ;
+ for (n = frag_count; n; n--) {
+- tbctrl = AIX_REVERSE(t1->txd_tbctrl) ;
++ tbctrl = le32_to_cpu(t1->txd_tbctrl) ;
+ dma_complete(smc,
+ (union s_fp_descr volatile *) t1,
+ (int) (DMA_RD |
+@@ -2064,7 +2062,7 @@ void mac_drv_clear_tx_queue(struct s_smc *smc)
+ while (tx_used) {
+ DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORCPU) ;
+ DB_TX("switch OWN bit of TxD 0x%x ",t,0,5) ;
+- t->txd_tbctrl &= AIX_REVERSE(~BMU_OWN) ;
++ t->txd_tbctrl &= ~cpu_to_le32(BMU_OWN) ;
+ DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
+ t = t->txd_next ;
+ tx_used-- ;
+@@ -2086,10 +2084,10 @@ void mac_drv_clear_tx_queue(struct s_smc *smc)
+ * tx_curr_get and tx_curr_put to this position
+ */
+ if (i == QUEUE_S) {
+- outpd(ADDR(B5_XS_DA),AIX_REVERSE(t->txd_ntdadr)) ;
++ outpd(ADDR(B5_XS_DA),le32_to_cpu(t->txd_ntdadr)) ;
+ }
+ else {
+- outpd(ADDR(B5_XA_DA),AIX_REVERSE(t->txd_ntdadr)) ;
++ outpd(ADDR(B5_XA_DA),le32_to_cpu(t->txd_ntdadr)) ;
+ }
+
+ queue->tx_curr_put = queue->tx_curr_get->txd_next ;
+diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
+index 7cf9b9f..a2b092b 100644
+--- a/drivers/net/skfp/skfddi.c
++++ b/drivers/net/skfp/skfddi.c
+@@ -495,7 +495,7 @@ static int skfp_open(struct net_device *dev)
+
+ PRINTK(KERN_INFO "entering skfp_open\n");
+ /* Register IRQ - support shared interrupts by passing device ptr */
+- err = request_irq(dev->irq, (void *) skfp_interrupt, IRQF_SHARED,
++ err = request_irq(dev->irq, skfp_interrupt, IRQF_SHARED,
+ dev->name, dev);
+ if (err)
+ return err;
+@@ -1644,7 +1644,7 @@ void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
+ // Get RIF length from Routing Control (RC) field.
+ cp = virt + FDDI_MAC_HDR_LEN; // Point behind MAC header.
+
+- ri = ntohs(*((unsigned short *) cp));
++ ri = ntohs(*((__be16 *) cp));
+ RifLength = ri & FDDI_RCF_LEN_MASK;
+ if (len < (int) (FDDI_MAC_HDR_LEN + RifLength)) {
+ printk("fddi: Invalid RIF.\n");
+diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
+index 76cc1d3..4e28002 100644
+--- a/drivers/net/smc911x.c
++++ b/drivers/net/smc911x.c
+@@ -92,6 +92,7 @@ module_param(tx_fifo_kb, int, 0400);
+ MODULE_PARM_DESC(tx_fifo_kb,"transmit FIFO size in KB (1<x<15)(default=8)");
+
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:smc911x");
+
+ /*
+ * The internal workings of the driver. If you are changing anything
+@@ -243,7 +244,7 @@ static void smc911x_reset(struct net_device *dev)
+ do {
+ udelay(10);
+ reg = SMC_GET_PMT_CTRL() & PMT_CTRL_READY_;
+- } while ( timeout-- && !reg);
++ } while (--timeout && !reg);
+ if (timeout == 0) {
+ PRINTK("%s: smc911x_reset timeout waiting for PM restore\n", dev->name);
+ return;
+@@ -267,7 +268,7 @@ static void smc911x_reset(struct net_device *dev)
+ resets++;
+ break;
+ }
+- } while ( timeout-- && (reg & HW_CFG_SRST_));
++ } while (--timeout && (reg & HW_CFG_SRST_));
+ }
+ if (timeout == 0) {
+ PRINTK("%s: smc911x_reset timeout waiting for reset\n", dev->name);
+@@ -413,7 +414,7 @@ static inline void smc911x_drop_pkt(struct net_device *dev)
+ do {
+ udelay(10);
+ reg = SMC_GET_RX_DP_CTRL() & RX_DP_CTRL_FFWD_BUSY_;
+- } while ( timeout-- && reg);
++ } while (--timeout && reg);
+ if (timeout == 0) {
+ PRINTK("%s: timeout waiting for RX fast forward\n", dev->name);
+ }
+@@ -2262,6 +2263,7 @@ static struct platform_driver smc911x_driver = {
+ .resume = smc911x_drv_resume,
+ .driver = {
+ .name = CARDNAME,
++ .owner = THIS_MODULE,
+ },
+ };
+
+diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
+index 63a54e2..a188e33 100644
+--- a/drivers/net/smc91x.c
++++ b/drivers/net/smc91x.c
+@@ -132,6 +132,7 @@ module_param(watchdog, int, 0400);
+ MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
+
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:smc91x");
+
+ /*
+ * The internal workings of the driver. If you are changing anything
+@@ -220,22 +221,22 @@ static void PRINT_PKT(u_char *buf, int length)
+
+
+ /* this enables an interrupt in the interrupt mask register */
+-#define SMC_ENABLE_INT(x) do { \
++#define SMC_ENABLE_INT(lp, x) do { \
+ unsigned char mask; \
+ spin_lock_irq(&lp->lock); \
+- mask = SMC_GET_INT_MASK(); \
++ mask = SMC_GET_INT_MASK(lp); \
+ mask |= (x); \
+- SMC_SET_INT_MASK(mask); \
++ SMC_SET_INT_MASK(lp, mask); \
+ spin_unlock_irq(&lp->lock); \
+ } while (0)
+
+ /* this disables an interrupt from the interrupt mask register */
+-#define SMC_DISABLE_INT(x) do { \
++#define SMC_DISABLE_INT(lp, x) do { \
+ unsigned char mask; \
+ spin_lock_irq(&lp->lock); \
+- mask = SMC_GET_INT_MASK(); \
++ mask = SMC_GET_INT_MASK(lp); \
+ mask &= ~(x); \
+- SMC_SET_INT_MASK(mask); \
++ SMC_SET_INT_MASK(lp, mask); \
+ spin_unlock_irq(&lp->lock); \
+ } while (0)
+
+@@ -244,10 +245,10 @@ static void PRINT_PKT(u_char *buf, int length)
+ * if at all, but let's avoid deadlocking the system if the hardware
+ * decides to go south.
+ */
+-#define SMC_WAIT_MMU_BUSY() do { \
+- if (unlikely(SMC_GET_MMU_CMD() & MC_BUSY)) { \
++#define SMC_WAIT_MMU_BUSY(lp) do { \
++ if (unlikely(SMC_GET_MMU_CMD(lp) & MC_BUSY)) { \
+ unsigned long timeout = jiffies + 2; \
+- while (SMC_GET_MMU_CMD() & MC_BUSY) { \
++ while (SMC_GET_MMU_CMD(lp) & MC_BUSY) { \
+ if (time_after(jiffies, timeout)) { \
+ printk("%s: timeout %s line %d\n", \
+ dev->name, __FILE__, __LINE__); \
+@@ -273,8 +274,8 @@ static void smc_reset(struct net_device *dev)
+
+ /* Disable all interrupts, block TX tasklet */
+ spin_lock_irq(&lp->lock);
+- SMC_SELECT_BANK(2);
+- SMC_SET_INT_MASK(0);
++ SMC_SELECT_BANK(lp, 2);
++ SMC_SET_INT_MASK(lp, 0);
+ pending_skb = lp->pending_tx_skb;
+ lp->pending_tx_skb = NULL;
+ spin_unlock_irq(&lp->lock);
+@@ -290,15 +291,15 @@ static void smc_reset(struct net_device *dev)
+ * This resets the registers mostly to defaults, but doesn't
+ * affect EEPROM. That seems unnecessary
+ */
+- SMC_SELECT_BANK(0);
+- SMC_SET_RCR(RCR_SOFTRST);
++ SMC_SELECT_BANK(lp, 0);
++ SMC_SET_RCR(lp, RCR_SOFTRST);
+
+ /*
+ * Setup the Configuration Register
+ * This is necessary because the CONFIG_REG is not affected
+ * by a soft reset
+ */
+- SMC_SELECT_BANK(1);
++ SMC_SELECT_BANK(lp, 1);
+
+ cfg = CONFIG_DEFAULT;
+
+@@ -316,7 +317,7 @@ static void smc_reset(struct net_device *dev)
+ */
+ cfg |= CONFIG_EPH_POWER_EN;
+
+- SMC_SET_CONFIG(cfg);
++ SMC_SET_CONFIG(lp, cfg);
+
+ /* this should pause enough for the chip to be happy */
+ /*
+@@ -329,12 +330,12 @@ static void smc_reset(struct net_device *dev)
+ udelay(1);
+
+ /* Disable transmit and receive functionality */
+- SMC_SELECT_BANK(0);
+- SMC_SET_RCR(RCR_CLEAR);
+- SMC_SET_TCR(TCR_CLEAR);
++ SMC_SELECT_BANK(lp, 0);
++ SMC_SET_RCR(lp, RCR_CLEAR);
++ SMC_SET_TCR(lp, TCR_CLEAR);
+
+- SMC_SELECT_BANK(1);
+- ctl = SMC_GET_CTL() | CTL_LE_ENABLE;
++ SMC_SELECT_BANK(lp, 1);
++ ctl = SMC_GET_CTL(lp) | CTL_LE_ENABLE;
+
+ /*
+ * Set the control register to automatically release successfully
+@@ -345,12 +346,12 @@ static void smc_reset(struct net_device *dev)
+ ctl |= CTL_AUTO_RELEASE;
+ else
+ ctl &= ~CTL_AUTO_RELEASE;
+- SMC_SET_CTL(ctl);
++ SMC_SET_CTL(lp, ctl);
+
+ /* Reset the MMU */
+- SMC_SELECT_BANK(2);
+- SMC_SET_MMU_CMD(MC_RESET);
+- SMC_WAIT_MMU_BUSY();
++ SMC_SELECT_BANK(lp, 2);
++ SMC_SET_MMU_CMD(lp, MC_RESET);
++ SMC_WAIT_MMU_BUSY(lp);
+ }
+
+ /*
+@@ -365,19 +366,19 @@ static void smc_enable(struct net_device *dev)
+ DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
+
+ /* see the header file for options in TCR/RCR DEFAULT */
+- SMC_SELECT_BANK(0);
+- SMC_SET_TCR(lp->tcr_cur_mode);
+- SMC_SET_RCR(lp->rcr_cur_mode);
++ SMC_SELECT_BANK(lp, 0);
++ SMC_SET_TCR(lp, lp->tcr_cur_mode);
++ SMC_SET_RCR(lp, lp->rcr_cur_mode);
+
+- SMC_SELECT_BANK(1);
+- SMC_SET_MAC_ADDR(dev->dev_addr);
++ SMC_SELECT_BANK(lp, 1);
++ SMC_SET_MAC_ADDR(lp, dev->dev_addr);
+
+ /* now, enable interrupts */
+ mask = IM_EPH_INT|IM_RX_OVRN_INT|IM_RCV_INT;
+ if (lp->version >= (CHIP_91100 << 4))
+ mask |= IM_MDINT;
+- SMC_SELECT_BANK(2);
+- SMC_SET_INT_MASK(mask);
++ SMC_SELECT_BANK(lp, 2);
++ SMC_SET_INT_MASK(lp, mask);
+
+ /*
+ * From this point the register bank must _NOT_ be switched away
+@@ -400,8 +401,8 @@ static void smc_shutdown(struct net_device *dev)
+
+ /* no more interrupts for me */
+ spin_lock_irq(&lp->lock);
+- SMC_SELECT_BANK(2);
+- SMC_SET_INT_MASK(0);
++ SMC_SELECT_BANK(lp, 2);
++ SMC_SET_INT_MASK(lp, 0);
+ pending_skb = lp->pending_tx_skb;
+ lp->pending_tx_skb = NULL;
+ spin_unlock_irq(&lp->lock);
+@@ -409,14 +410,14 @@ static void smc_shutdown(struct net_device *dev)
+ dev_kfree_skb(pending_skb);
+
+ /* and tell the card to stay away from that nasty outside world */
+- SMC_SELECT_BANK(0);
+- SMC_SET_RCR(RCR_CLEAR);
+- SMC_SET_TCR(TCR_CLEAR);
++ SMC_SELECT_BANK(lp, 0);
++ SMC_SET_RCR(lp, RCR_CLEAR);
++ SMC_SET_TCR(lp, TCR_CLEAR);
+
+ #ifdef POWER_DOWN
+ /* finally, shut the chip down */
+- SMC_SELECT_BANK(1);
+- SMC_SET_CONFIG(SMC_GET_CONFIG() & ~CONFIG_EPH_POWER_EN);
++ SMC_SELECT_BANK(lp, 1);
++ SMC_SET_CONFIG(lp, SMC_GET_CONFIG(lp) & ~CONFIG_EPH_POWER_EN);
+ #endif
+ }
+
+@@ -431,17 +432,17 @@ static inline void smc_rcv(struct net_device *dev)
+
+ DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
+
+- packet_number = SMC_GET_RXFIFO();
++ packet_number = SMC_GET_RXFIFO(lp);
+ if (unlikely(packet_number & RXFIFO_REMPTY)) {
+ PRINTK("%s: smc_rcv with nothing on FIFO.\n", dev->name);
+ return;
+ }
+
+ /* read from start of packet */
+- SMC_SET_PTR(PTR_READ | PTR_RCV | PTR_AUTOINC);
++ SMC_SET_PTR(lp, PTR_READ | PTR_RCV | PTR_AUTOINC);
+
+ /* First two words are status and packet length */
+- SMC_GET_PKT_HDR(status, packet_len);
++ SMC_GET_PKT_HDR(lp, status, packet_len);
+ packet_len &= 0x07ff; /* mask off top bits */
+ DBG(2, "%s: RX PNR 0x%x STATUS 0x%04x LENGTH 0x%04x (%d)\n",
+ dev->name, packet_number, status,
+@@ -460,8 +461,8 @@ static inline void smc_rcv(struct net_device *dev)
+ dev->name, packet_len, status);
+ status |= RS_TOOSHORT;
+ }
+- SMC_WAIT_MMU_BUSY();
+- SMC_SET_MMU_CMD(MC_RELEASE);
++ SMC_WAIT_MMU_BUSY(lp);
++ SMC_SET_MMU_CMD(lp, MC_RELEASE);
+ dev->stats.rx_errors++;
+ if (status & RS_ALGNERR)
+ dev->stats.rx_frame_errors++;
+@@ -490,8 +491,8 @@ static inline void smc_rcv(struct net_device *dev)
+ if (unlikely(skb == NULL)) {
+ printk(KERN_NOTICE "%s: Low memory, packet dropped.\n",
+ dev->name);
+- SMC_WAIT_MMU_BUSY();
+- SMC_SET_MMU_CMD(MC_RELEASE);
++ SMC_WAIT_MMU_BUSY(lp);
++ SMC_SET_MMU_CMD(lp, MC_RELEASE);
+ dev->stats.rx_dropped++;
+ return;
+ }
+@@ -510,10 +511,10 @@ static inline void smc_rcv(struct net_device *dev)
+ */
+ data_len = packet_len - ((status & RS_ODDFRAME) ? 5 : 6);
+ data = skb_put(skb, data_len);
+- SMC_PULL_DATA(data, packet_len - 4);
++ SMC_PULL_DATA(lp, data, packet_len - 4);
+
+- SMC_WAIT_MMU_BUSY();
+- SMC_SET_MMU_CMD(MC_RELEASE);
++ SMC_WAIT_MMU_BUSY(lp);
++ SMC_SET_MMU_CMD(lp, MC_RELEASE);
+
+ PRINT_PKT(data, packet_len - 4);
+
+@@ -591,7 +592,7 @@ static void smc_hardware_send_pkt(unsigned long data)
+ }
+ lp->pending_tx_skb = NULL;
+
+- packet_no = SMC_GET_AR();
++ packet_no = SMC_GET_AR(lp);
+ if (unlikely(packet_no & AR_FAILED)) {
+ printk("%s: Memory allocation failed.\n", dev->name);
+ dev->stats.tx_errors++;
+@@ -601,8 +602,8 @@ static void smc_hardware_send_pkt(unsigned long data)
+ }
+
+ /* point to the beginning of the packet */
+- SMC_SET_PN(packet_no);
+- SMC_SET_PTR(PTR_AUTOINC);
++ SMC_SET_PN(lp, packet_no);
++ SMC_SET_PTR(lp, PTR_AUTOINC);
+
+ buf = skb->data;
+ len = skb->len;
+@@ -614,13 +615,13 @@ static void smc_hardware_send_pkt(unsigned long data)
+ * Send the packet length (+6 for status words, length, and ctl.
+ * The card will pad to 64 bytes with zeroes if packet is too small.
+ */
+- SMC_PUT_PKT_HDR(0, len + 6);
++ SMC_PUT_PKT_HDR(lp, 0, len + 6);
+
+ /* send the actual data */
+- SMC_PUSH_DATA(buf, len & ~1);
++ SMC_PUSH_DATA(lp, buf, len & ~1);
+
+ /* Send final ctl word with the last byte if there is one */
+- SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG);
++ SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG(lp));
+
+ /*
+ * If THROTTLE_TX_PKTS is set, we stop the queue here. This will
+@@ -634,14 +635,14 @@ static void smc_hardware_send_pkt(unsigned long data)
+ netif_stop_queue(dev);
+
+ /* queue the packet for TX */
+- SMC_SET_MMU_CMD(MC_ENQUEUE);
++ SMC_SET_MMU_CMD(lp, MC_ENQUEUE);
+ smc_special_unlock(&lp->lock);
+
+ dev->trans_start = jiffies;
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += len;
+
+- SMC_ENABLE_INT(IM_TX_INT | IM_TX_EMPTY_INT);
++ SMC_ENABLE_INT(lp, IM_TX_INT | IM_TX_EMPTY_INT);
+
+ done: if (!THROTTLE_TX_PKTS)
+ netif_wake_queue(dev);
+@@ -688,7 +689,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ smc_special_lock(&lp->lock);
+
+ /* now, try to allocate the memory */
+- SMC_SET_MMU_CMD(MC_ALLOC | numPages);
++ SMC_SET_MMU_CMD(lp, MC_ALLOC | numPages);
+
+ /*
+ * Poll the chip for a short amount of time in case the
+@@ -696,9 +697,9 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ */
+ poll_count = MEMORY_WAIT_TIME;
+ do {
+- status = SMC_GET_INT();
++ status = SMC_GET_INT(lp);
+ if (status & IM_ALLOC_INT) {
+- SMC_ACK_INT(IM_ALLOC_INT);
++ SMC_ACK_INT(lp, IM_ALLOC_INT);
+ break;
+ }
+ } while (--poll_count);
+@@ -710,7 +711,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ /* oh well, wait until the chip finds memory later */
+ netif_stop_queue(dev);
+ DBG(2, "%s: TX memory allocation deferred.\n", dev->name);
+- SMC_ENABLE_INT(IM_ALLOC_INT);
++ SMC_ENABLE_INT(lp, IM_ALLOC_INT);
+ } else {
+ /*
+ * Allocation succeeded: push packet to the chip's own memory
+@@ -736,19 +737,19 @@ static void smc_tx(struct net_device *dev)
+ DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
+
+ /* If the TX FIFO is empty then nothing to do */
+- packet_no = SMC_GET_TXFIFO();
++ packet_no = SMC_GET_TXFIFO(lp);
+ if (unlikely(packet_no & TXFIFO_TEMPTY)) {
+ PRINTK("%s: smc_tx with nothing on FIFO.\n", dev->name);
+ return;
+ }
+
+ /* select packet to read from */
+- saved_packet = SMC_GET_PN();
+- SMC_SET_PN(packet_no);
++ saved_packet = SMC_GET_PN(lp);
++ SMC_SET_PN(lp, packet_no);
+
+ /* read the first word (status word) from this packet */
+- SMC_SET_PTR(PTR_AUTOINC | PTR_READ);
+- SMC_GET_PKT_HDR(tx_status, pkt_len);
++ SMC_SET_PTR(lp, PTR_AUTOINC | PTR_READ);
++ SMC_GET_PKT_HDR(lp, tx_status, pkt_len);
+ DBG(2, "%s: TX STATUS 0x%04x PNR 0x%02x\n",
+ dev->name, tx_status, packet_no);
+
+@@ -771,17 +772,17 @@ static void smc_tx(struct net_device *dev)
+ }
+
+ /* kill the packet */
+- SMC_WAIT_MMU_BUSY();
+- SMC_SET_MMU_CMD(MC_FREEPKT);
++ SMC_WAIT_MMU_BUSY(lp);
++ SMC_SET_MMU_CMD(lp, MC_FREEPKT);
+
+ /* Don't restore Packet Number Reg until busy bit is cleared */
+- SMC_WAIT_MMU_BUSY();
+- SMC_SET_PN(saved_packet);
++ SMC_WAIT_MMU_BUSY(lp);
++ SMC_SET_PN(lp, saved_packet);
+
+ /* re-enable transmit */
+- SMC_SELECT_BANK(0);
+- SMC_SET_TCR(lp->tcr_cur_mode);
+- SMC_SELECT_BANK(2);
++ SMC_SELECT_BANK(lp, 0);
++ SMC_SET_TCR(lp, lp->tcr_cur_mode);
++ SMC_SELECT_BANK(lp, 2);
+ }
+
+
+@@ -793,7 +794,7 @@ static void smc_mii_out(struct net_device *dev, unsigned int val, int bits)
+ void __iomem *ioaddr = lp->base;
+ unsigned int mii_reg, mask;
+
+- mii_reg = SMC_GET_MII() & ~(MII_MCLK | MII_MDOE | MII_MDO);
++ mii_reg = SMC_GET_MII(lp) & ~(MII_MCLK | MII_MDOE | MII_MDO);
+ mii_reg |= MII_MDOE;
+
+ for (mask = 1 << (bits - 1); mask; mask >>= 1) {
+@@ -802,9 +803,9 @@ static void smc_mii_out(struct net_device *dev, unsigned int val, int bits)
+ else
+ mii_reg &= ~MII_MDO;
+
+- SMC_SET_MII(mii_reg);
++ SMC_SET_MII(lp, mii_reg);
+ udelay(MII_DELAY);
+- SMC_SET_MII(mii_reg | MII_MCLK);
++ SMC_SET_MII(lp, mii_reg | MII_MCLK);
+ udelay(MII_DELAY);
+ }
+ }
+@@ -815,16 +816,16 @@ static unsigned int smc_mii_in(struct net_device *dev, int bits)
+ void __iomem *ioaddr = lp->base;
+ unsigned int mii_reg, mask, val;
+
+- mii_reg = SMC_GET_MII() & ~(MII_MCLK | MII_MDOE | MII_MDO);
+- SMC_SET_MII(mii_reg);
++ mii_reg = SMC_GET_MII(lp) & ~(MII_MCLK | MII_MDOE | MII_MDO);
++ SMC_SET_MII(lp, mii_reg);
+
+ for (mask = 1 << (bits - 1), val = 0; mask; mask >>= 1) {
+- if (SMC_GET_MII() & MII_MDI)
++ if (SMC_GET_MII(lp) & MII_MDI)
+ val |= mask;
+
+- SMC_SET_MII(mii_reg);
++ SMC_SET_MII(lp, mii_reg);
+ udelay(MII_DELAY);
+- SMC_SET_MII(mii_reg | MII_MCLK);
++ SMC_SET_MII(lp, mii_reg | MII_MCLK);
+ udelay(MII_DELAY);
+ }
+
+@@ -840,7 +841,7 @@ static int smc_phy_read(struct net_device *dev, int phyaddr, int phyreg)
+ void __iomem *ioaddr = lp->base;
+ unsigned int phydata;
+
+- SMC_SELECT_BANK(3);
++ SMC_SELECT_BANK(lp, 3);
+
+ /* Idle - 32 ones */
+ smc_mii_out(dev, 0xffffffff, 32);
+@@ -852,12 +853,12 @@ static int smc_phy_read(struct net_device *dev, int phyaddr, int phyreg)
+ phydata = smc_mii_in(dev, 18);
+
+ /* Return to idle state */
+- SMC_SET_MII(SMC_GET_MII() & ~(MII_MCLK|MII_MDOE|MII_MDO));
++ SMC_SET_MII(lp, SMC_GET_MII(lp) & ~(MII_MCLK|MII_MDOE|MII_MDO));
+
+ DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
+ __FUNCTION__, phyaddr, phyreg, phydata);
+
+- SMC_SELECT_BANK(2);
++ SMC_SELECT_BANK(lp, 2);
+ return phydata;
+ }
+
+@@ -870,7 +871,7 @@ static void smc_phy_write(struct net_device *dev, int phyaddr, int phyreg,
+ struct smc_local *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
+
+- SMC_SELECT_BANK(3);
++ SMC_SELECT_BANK(lp, 3);
+
+ /* Idle - 32 ones */
+ smc_mii_out(dev, 0xffffffff, 32);
+@@ -879,12 +880,12 @@ static void smc_phy_write(struct net_device *dev, int phyaddr, int phyreg,
+ smc_mii_out(dev, 5 << 28 | phyaddr << 23 | phyreg << 18 | 2 << 16 | phydata, 32);
+
+ /* Return to idle state */
+- SMC_SET_MII(SMC_GET_MII() & ~(MII_MCLK|MII_MDOE|MII_MDO));
++ SMC_SET_MII(lp, SMC_GET_MII(lp) & ~(MII_MCLK|MII_MDOE|MII_MDO));
+
+ DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
+ __FUNCTION__, phyaddr, phyreg, phydata);
+
+- SMC_SELECT_BANK(2);
++ SMC_SELECT_BANK(lp, 2);
+ }
+
+ /*
+@@ -957,9 +958,9 @@ static int smc_phy_fixed(struct net_device *dev)
+ smc_phy_write(dev, phyaddr, MII_BMCR, bmcr);
+
+ /* Re-Configure the Receive/Phy Control register */
+- SMC_SELECT_BANK(0);
+- SMC_SET_RPC(lp->rpc_cur_mode);
+- SMC_SELECT_BANK(2);
++ SMC_SELECT_BANK(lp, 0);
++ SMC_SET_RPC(lp, lp->rpc_cur_mode);
++ SMC_SELECT_BANK(lp, 2);
+
+ return 1;
+ }
+@@ -1050,8 +1051,8 @@ static void smc_phy_check_media(struct net_device *dev, int init)
+ lp->tcr_cur_mode &= ~TCR_SWFDUP;
+ }
+
+- SMC_SELECT_BANK(0);
+- SMC_SET_TCR(lp->tcr_cur_mode);
++ SMC_SELECT_BANK(lp, 0);
++ SMC_SET_TCR(lp, lp->tcr_cur_mode);
+ }
+ }
+
+@@ -1100,8 +1101,8 @@ static void smc_phy_configure(struct work_struct *work)
+ PHY_INT_SPDDET | PHY_INT_DPLXDET);
+
+ /* Configure the Receive/Phy Control register */
+- SMC_SELECT_BANK(0);
+- SMC_SET_RPC(lp->rpc_cur_mode);
++ SMC_SELECT_BANK(lp, 0);
++ SMC_SET_RPC(lp, lp->rpc_cur_mode);
+
+ /* If the user requested no auto neg, then go set his request */
+ if (lp->mii.force_media) {
+@@ -1158,7 +1159,7 @@ static void smc_phy_configure(struct work_struct *work)
+ smc_phy_check_media(dev, 1);
+
+ smc_phy_configure_exit:
+- SMC_SELECT_BANK(2);
++ SMC_SELECT_BANK(lp, 2);
+ spin_unlock_irq(&lp->lock);
+ lp->work_pending = 0;
+ }
+@@ -1200,9 +1201,9 @@ static void smc_10bt_check_media(struct net_device *dev, int init)
+
+ old_carrier = netif_carrier_ok(dev) ? 1 : 0;
+
+- SMC_SELECT_BANK(0);
+- new_carrier = (SMC_GET_EPH_STATUS() & ES_LINK_OK) ? 1 : 0;
+- SMC_SELECT_BANK(2);
++ SMC_SELECT_BANK(lp, 0);
++ new_carrier = (SMC_GET_EPH_STATUS(lp) & ES_LINK_OK) ? 1 : 0;
++ SMC_SELECT_BANK(lp, 2);
+
+ if (init || (old_carrier != new_carrier)) {
+ if (!new_carrier) {
+@@ -1224,11 +1225,11 @@ static void smc_eph_interrupt(struct net_device *dev)
+
+ smc_10bt_check_media(dev, 0);
+
+- SMC_SELECT_BANK(1);
+- ctl = SMC_GET_CTL();
+- SMC_SET_CTL(ctl & ~CTL_LE_ENABLE);
+- SMC_SET_CTL(ctl);
+- SMC_SELECT_BANK(2);
++ SMC_SELECT_BANK(lp, 1);
++ ctl = SMC_GET_CTL(lp);
++ SMC_SET_CTL(lp, ctl & ~CTL_LE_ENABLE);
++ SMC_SET_CTL(lp, ctl);
++ SMC_SELECT_BANK(lp, 2);
+ }
+
+ /*
+@@ -1252,22 +1253,22 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id)
+ * ISR. */
+ SMC_INTERRUPT_PREAMBLE;
+
+- saved_pointer = SMC_GET_PTR();
+- mask = SMC_GET_INT_MASK();
+- SMC_SET_INT_MASK(0);
++ saved_pointer = SMC_GET_PTR(lp);
++ mask = SMC_GET_INT_MASK(lp);
++ SMC_SET_INT_MASK(lp, 0);
+
+ /* set a timeout value, so I don't stay here forever */
+ timeout = MAX_IRQ_LOOPS;
+
+ do {
+- status = SMC_GET_INT();
++ status = SMC_GET_INT(lp);
+
+ DBG(2, "%s: INT 0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x\n",
+ dev->name, status, mask,
+- ({ int meminfo; SMC_SELECT_BANK(0);
+- meminfo = SMC_GET_MIR();
+- SMC_SELECT_BANK(2); meminfo; }),
+- SMC_GET_FIFO());
++ ({ int meminfo; SMC_SELECT_BANK(lp, 0);
++ meminfo = SMC_GET_MIR(lp);
++ SMC_SELECT_BANK(lp, 2); meminfo; }),
++ SMC_GET_FIFO(lp));
+
+ status &= mask;
+ if (!status)
+@@ -1277,7 +1278,7 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id)
+ /* do this before RX as it will free memory quickly */
+ DBG(3, "%s: TX int\n", dev->name);
+ smc_tx(dev);
+- SMC_ACK_INT(IM_TX_INT);
++ SMC_ACK_INT(lp, IM_TX_INT);
+ if (THROTTLE_TX_PKTS)
+ netif_wake_queue(dev);
+ } else if (status & IM_RCV_INT) {
+@@ -1292,9 +1293,9 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id)
+ mask &= ~IM_TX_EMPTY_INT;
+
+ /* update stats */
+- SMC_SELECT_BANK(0);
+- card_stats = SMC_GET_COUNTER();
+- SMC_SELECT_BANK(2);
++ SMC_SELECT_BANK(lp, 0);
++ card_stats = SMC_GET_COUNTER(lp);
++ SMC_SELECT_BANK(lp, 2);
+
+ /* single collisions */
+ dev->stats.collisions += card_stats & 0xF;
+@@ -1304,26 +1305,26 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id)
+ dev->stats.collisions += card_stats & 0xF;
+ } else if (status & IM_RX_OVRN_INT) {
+ DBG(1, "%s: RX overrun (EPH_ST 0x%04x)\n", dev->name,
+- ({ int eph_st; SMC_SELECT_BANK(0);
+- eph_st = SMC_GET_EPH_STATUS();
+- SMC_SELECT_BANK(2); eph_st; }) );
+- SMC_ACK_INT(IM_RX_OVRN_INT);
++ ({ int eph_st; SMC_SELECT_BANK(lp, 0);
++ eph_st = SMC_GET_EPH_STATUS(lp);
++ SMC_SELECT_BANK(lp, 2); eph_st; }));
++ SMC_ACK_INT(lp, IM_RX_OVRN_INT);
+ dev->stats.rx_errors++;
+ dev->stats.rx_fifo_errors++;
+ } else if (status & IM_EPH_INT) {
+ smc_eph_interrupt(dev);
+ } else if (status & IM_MDINT) {
+- SMC_ACK_INT(IM_MDINT);
++ SMC_ACK_INT(lp, IM_MDINT);
+ smc_phy_interrupt(dev);
+ } else if (status & IM_ERCV_INT) {
+- SMC_ACK_INT(IM_ERCV_INT);
++ SMC_ACK_INT(lp, IM_ERCV_INT);
+ PRINTK("%s: UNSUPPORTED: ERCV INTERRUPT \n", dev->name);
+ }
+ } while (--timeout);
+
+ /* restore register states */
+- SMC_SET_PTR(saved_pointer);
+- SMC_SET_INT_MASK(mask);
++ SMC_SET_PTR(lp, saved_pointer);
++ SMC_SET_INT_MASK(lp, mask);
+ spin_unlock(&lp->lock);
+
+ #ifndef CONFIG_NET_POLL_CONTROLLER
+@@ -1368,13 +1369,13 @@ static void smc_timeout(struct net_device *dev)
+ DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
+
+ spin_lock_irq(&lp->lock);
+- status = SMC_GET_INT();
+- mask = SMC_GET_INT_MASK();
+- fifo = SMC_GET_FIFO();
+- SMC_SELECT_BANK(0);
+- eph_st = SMC_GET_EPH_STATUS();
+- meminfo = SMC_GET_MIR();
+- SMC_SELECT_BANK(2);
++ status = SMC_GET_INT(lp);
++ mask = SMC_GET_INT_MASK(lp);
++ fifo = SMC_GET_FIFO(lp);
++ SMC_SELECT_BANK(lp, 0);
++ eph_st = SMC_GET_EPH_STATUS(lp);
++ meminfo = SMC_GET_MIR(lp);
++ SMC_SELECT_BANK(lp, 2);
+ spin_unlock_irq(&lp->lock);
+ PRINTK( "%s: TX timeout (INT 0x%02x INTMASK 0x%02x "
+ "MEM 0x%04x FIFO 0x%04x EPH_ST 0x%04x)\n",
+@@ -1494,13 +1495,13 @@ static void smc_set_multicast_list(struct net_device *dev)
+ }
+
+ spin_lock_irq(&lp->lock);
+- SMC_SELECT_BANK(0);
+- SMC_SET_RCR(lp->rcr_cur_mode);
++ SMC_SELECT_BANK(lp, 0);
++ SMC_SET_RCR(lp, lp->rcr_cur_mode);
+ if (update_multicast) {
+- SMC_SELECT_BANK(3);
+- SMC_SET_MCAST(multicast_table);
++ SMC_SELECT_BANK(lp, 3);
++ SMC_SET_MCAST(lp, multicast_table);
+ }
+- SMC_SELECT_BANK(2);
++ SMC_SELECT_BANK(lp, 2);
+ spin_unlock_irq(&lp->lock);
+ }
+
+@@ -1704,8 +1705,9 @@ static const struct ethtool_ops smc_ethtool_ops = {
+ * I just deleted auto_irq.c, since it was never built...
+ * --jgarzik
+ */
+-static int __init smc_findirq(void __iomem *ioaddr)
++static int __init smc_findirq(struct smc_local *lp)
+ {
++ void __iomem *ioaddr = lp->base;
+ int timeout = 20;
+ unsigned long cookie;
+
+@@ -1719,14 +1721,14 @@ static int __init smc_findirq(void __iomem *ioaddr)
+ * when done.
+ */
+ /* enable ALLOCation interrupts ONLY */
+- SMC_SELECT_BANK(2);
+- SMC_SET_INT_MASK(IM_ALLOC_INT);
++ SMC_SELECT_BANK(lp, 2);
++ SMC_SET_INT_MASK(lp, IM_ALLOC_INT);
+
+ /*
+ * Allocate 512 bytes of memory. Note that the chip was just
+ * reset so all the memory is available
+ */
+- SMC_SET_MMU_CMD(MC_ALLOC | 1);
++ SMC_SET_MMU_CMD(lp, MC_ALLOC | 1);
+
+ /*
+ * Wait until positive that the interrupt has been generated
+@@ -1734,7 +1736,7 @@ static int __init smc_findirq(void __iomem *ioaddr)
+ do {
+ int int_status;
+ udelay(10);
+- int_status = SMC_GET_INT();
++ int_status = SMC_GET_INT(lp);
+ if (int_status & IM_ALLOC_INT)
+ break; /* got the interrupt */
+ } while (--timeout);
+@@ -1747,7 +1749,7 @@ static int __init smc_findirq(void __iomem *ioaddr)
+ */
+
+ /* and disable all interrupts again */
+- SMC_SET_INT_MASK(0);
++ SMC_SET_INT_MASK(lp, 0);
+
+ /* and return what I found */
+ return probe_irq_off(cookie);
+@@ -1790,7 +1792,7 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr,
+ DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);
+
+ /* First, see if the high byte is 0x33 */
+- val = SMC_CURRENT_BANK();
++ val = SMC_CURRENT_BANK(lp);
+ DBG(2, "%s: bank signature probe returned 0x%04x\n", CARDNAME, val);
+ if ((val & 0xFF00) != 0x3300) {
+ if ((val & 0xFF) == 0x33) {
+@@ -1806,8 +1808,8 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr,
+ * The above MIGHT indicate a device, but I need to write to
+ * further test this.
+ */
+- SMC_SELECT_BANK(0);
+- val = SMC_CURRENT_BANK();
++ SMC_SELECT_BANK(lp, 0);
++ val = SMC_CURRENT_BANK(lp);
+ if ((val & 0xFF00) != 0x3300) {
+ retval = -ENODEV;
+ goto err_out;
+@@ -1819,8 +1821,8 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr,
+ * register to bank 1, so I can access the base address
+ * register
+ */
+- SMC_SELECT_BANK(1);
+- val = SMC_GET_BASE();
++ SMC_SELECT_BANK(lp, 1);
++ val = SMC_GET_BASE(lp);
+ val = ((val & 0x1F00) >> 3) << SMC_IO_SHIFT;
+ if (((unsigned int)ioaddr & (0x3e0 << SMC_IO_SHIFT)) != val) {
+ printk("%s: IOADDR %p doesn't match configuration (%x).\n",
+@@ -1832,8 +1834,8 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr,
+ * recognize. These might need to be added to later,
+ * as future revisions could be added.
+ */
+- SMC_SELECT_BANK(3);
+- revision_register = SMC_GET_REV();
++ SMC_SELECT_BANK(lp, 3);
++ revision_register = SMC_GET_REV(lp);
+ DBG(2, "%s: revision = 0x%04x\n", CARDNAME, revision_register);
+ version_string = chip_ids[ (revision_register >> 4) & 0xF];
+ if (!version_string || (revision_register & 0xff00) != 0x3300) {
+@@ -1857,8 +1859,8 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr,
+ spin_lock_init(&lp->lock);
+
+ /* Get the MAC address */
+- SMC_SELECT_BANK(1);
+- SMC_GET_MAC_ADDR(dev->dev_addr);
++ SMC_SELECT_BANK(lp, 1);
++ SMC_GET_MAC_ADDR(lp, dev->dev_addr);
+
+ /* now, reset the chip, and put it into a known state */
+ smc_reset(dev);
+@@ -1883,7 +1885,7 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr,
+
+ trials = 3;
+ while (trials--) {
+- dev->irq = smc_findirq(ioaddr);
++ dev->irq = smc_findirq(lp);
+ if (dev->irq)
+ break;
+ /* kick the card and try again */
+@@ -1998,6 +2000,8 @@ err_out:
+
+ static int smc_enable_device(struct platform_device *pdev)
+ {
++ struct net_device *ndev = platform_get_drvdata(pdev);
++ struct smc_local *lp = netdev_priv(ndev);
+ unsigned long flags;
+ unsigned char ecor, ecsr;
+ void __iomem *addr;
+@@ -2040,7 +2044,7 @@ static int smc_enable_device(struct platform_device *pdev)
+ * Set the appropriate byte/word mode.
+ */
+ ecsr = readb(addr + (ECSR << SMC_IO_SHIFT)) & ~ECSR_IOIS8;
+- if (!SMC_CAN_USE_16BIT)
++ if (!SMC_16BIT(lp))
+ ecsr |= ECSR_IOIS8;
+ writeb(ecsr, addr + (ECSR << SMC_IO_SHIFT));
+ local_irq_restore(flags);
+@@ -2125,10 +2129,11 @@ static void smc_release_datacs(struct platform_device *pdev, struct net_device *
+ */
+ static int smc_drv_probe(struct platform_device *pdev)
+ {
++ struct smc91x_platdata *pd = pdev->dev.platform_data;
++ struct smc_local *lp;
+ struct net_device *ndev;
+ struct resource *res, *ires;
+ unsigned int __iomem *addr;
+- unsigned long irq_flags = SMC_IRQ_FLAGS;
+ int ret;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
+@@ -2153,6 +2158,27 @@ static int smc_drv_probe(struct platform_device *pdev)
+ }
+ SET_NETDEV_DEV(ndev, &pdev->dev);
+
++ /* get configuration from platform data, only allow use of
++ * bus width if both SMC_CAN_USE_xxx and SMC91X_USE_xxx are set.
++ */
++
++ lp = netdev_priv(ndev);
++ lp->cfg.irq_flags = SMC_IRQ_FLAGS;
++
++#ifdef SMC_DYNAMIC_BUS_CONFIG
++ if (pd)
++ memcpy(&lp->cfg, pd, sizeof(lp->cfg));
++ else {
++ lp->cfg.flags = SMC91X_USE_8BIT;
++ lp->cfg.flags |= SMC91X_USE_16BIT;
++ lp->cfg.flags |= SMC91X_USE_32BIT;
++ }
++
++ lp->cfg.flags &= ~(SMC_CAN_USE_8BIT ? 0 : SMC91X_USE_8BIT);
++ lp->cfg.flags &= ~(SMC_CAN_USE_16BIT ? 0 : SMC91X_USE_16BIT);
++ lp->cfg.flags &= ~(SMC_CAN_USE_32BIT ? 0 : SMC91X_USE_32BIT);
++#endif
++
+ ndev->dma = (unsigned char)-1;
+
+ ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+@@ -2163,7 +2189,7 @@ static int smc_drv_probe(struct platform_device *pdev)
+
+ ndev->irq = ires->start;
+ if (SMC_IRQ_FLAGS == -1)
+- irq_flags = ires->flags & IRQF_TRIGGER_MASK;
++ lp->cfg.irq_flags = ires->flags & IRQF_TRIGGER_MASK;
+
+ ret = smc_request_attrib(pdev);
+ if (ret)
+@@ -2171,6 +2197,7 @@ static int smc_drv_probe(struct platform_device *pdev)
+ #if defined(CONFIG_SA1100_ASSABET)
+ NCR_0 |= NCR_ENET_OSC_EN;
+ #endif
++ platform_set_drvdata(pdev, ndev);
+ ret = smc_enable_device(pdev);
+ if (ret)
+ goto out_release_attrib;
+@@ -2189,8 +2216,7 @@ static int smc_drv_probe(struct platform_device *pdev)
+ }
+ #endif
+
+- platform_set_drvdata(pdev, ndev);
+- ret = smc_probe(ndev, addr, irq_flags);
++ ret = smc_probe(ndev, addr, lp->cfg.irq_flags);
+ if (ret != 0)
+ goto out_iounmap;
+
+@@ -2283,6 +2309,7 @@ static struct platform_driver smc_driver = {
+ .resume = smc_drv_resume,
+ .driver = {
+ .name = CARDNAME,
++ .owner = THIS_MODULE,
+ },
+ };
+
+diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
+index 51d4134..69e97a1 100644
+--- a/drivers/net/smc91x.h
++++ b/drivers/net/smc91x.h
+@@ -34,6 +34,7 @@
+ #ifndef _SMC91X_H_
+ #define _SMC91X_H_
+
++#include <linux/smc91x.h>
+
+ /*
+ * Define your architecture specific bus configuration parameters here.
+@@ -291,36 +292,6 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
+ #define SMC_insw(a, r, p, l) insw((a) + (r), p, l)
+ #define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l)
+
+-#elif defined(CONFIG_SUPERH)
+-
+-#ifdef CONFIG_SOLUTION_ENGINE
+-#define SMC_IRQ_FLAGS (0)
+-#define SMC_CAN_USE_8BIT 0
+-#define SMC_CAN_USE_16BIT 1
+-#define SMC_CAN_USE_32BIT 0
+-#define SMC_IO_SHIFT 0
+-#define SMC_NOWAIT 1
+-
+-#define SMC_inw(a, r) inw((a) + (r))
+-#define SMC_outw(v, a, r) outw(v, (a) + (r))
+-#define SMC_insw(a, r, p, l) insw((a) + (r), p, l)
+-#define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l)
+-
+-#else /* BOARDS */
+-
+-#define SMC_CAN_USE_8BIT 1
+-#define SMC_CAN_USE_16BIT 1
+-#define SMC_CAN_USE_32BIT 0
+-
+-#define SMC_inb(a, r) inb((a) + (r))
+-#define SMC_inw(a, r) inw((a) + (r))
+-#define SMC_outb(v, a, r) outb(v, (a) + (r))
+-#define SMC_outw(v, a, r) outw(v, (a) + (r))
+-#define SMC_insw(a, r, p, l) insw((a) + (r), p, l)
+-#define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l)
+-
+-#endif /* BOARDS */
+-
+ #elif defined(CONFIG_M32R)
+
+ #define SMC_CAN_USE_8BIT 0
+@@ -475,12 +446,15 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r,
+ #define SMC_outb(v, a, r) writeb(v, (a) + (r))
+ #define SMC_outw(v, a, r) writew(v, (a) + (r))
+ #define SMC_outl(v, a, r) writel(v, (a) + (r))
++#define SMC_insw(a, r, p, l) readsw((a) + (r), p, l)
++#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l)
+ #define SMC_insl(a, r, p, l) readsl((a) + (r), p, l)
+ #define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l)
+
+ #define RPC_LSA_DEFAULT RPC_LED_100_10
+ #define RPC_LSB_DEFAULT RPC_LED_TX_RX
+
++#define SMC_DYNAMIC_BUS_CONFIG
+ #endif
+
+
+@@ -526,8 +500,19 @@ struct smc_local {
+ #endif
+ void __iomem *base;
+ void __iomem *datacs;
++
++ struct smc91x_platdata cfg;
+ };
+
++#ifdef SMC_DYNAMIC_BUS_CONFIG
++#define SMC_8BIT(p) (((p)->cfg.flags & SMC91X_USE_8BIT) && SMC_CAN_USE_8BIT)
++#define SMC_16BIT(p) (((p)->cfg.flags & SMC91X_USE_16BIT) && SMC_CAN_USE_16BIT)
++#define SMC_32BIT(p) (((p)->cfg.flags & SMC91X_USE_32BIT) && SMC_CAN_USE_32BIT)
++#else
++#define SMC_8BIT(p) SMC_CAN_USE_8BIT
++#define SMC_16BIT(p) SMC_CAN_USE_16BIT
++#define SMC_32BIT(p) SMC_CAN_USE_32BIT
++#endif
+
+ #ifdef SMC_USE_PXA_DMA
+ /*
+@@ -720,7 +705,7 @@ smc_pxa_dma_irq(int dma, void *dummy)
+
+ // Transmit Control Register
+ /* BANK 0 */
+-#define TCR_REG SMC_REG(0x0000, 0)
++#define TCR_REG(lp) SMC_REG(lp, 0x0000, 0)
+ #define TCR_ENABLE 0x0001 // When 1 we can transmit
+ #define TCR_LOOP 0x0002 // Controls output pin LBK
+ #define TCR_FORCOL 0x0004 // When 1 will force a collision
+@@ -739,7 +724,7 @@ smc_pxa_dma_irq(int dma, void *dummy)
+
+ // EPH Status Register
+ /* BANK 0 */
+-#define EPH_STATUS_REG SMC_REG(0x0002, 0)
++#define EPH_STATUS_REG(lp) SMC_REG(lp, 0x0002, 0)
+ #define ES_TX_SUC 0x0001 // Last TX was successful
+ #define ES_SNGL_COL 0x0002 // Single collision detected for last tx
+ #define ES_MUL_COL 0x0004 // Multiple collisions detected for last tx
+@@ -758,7 +743,7 @@ smc_pxa_dma_irq(int dma, void *dummy)
+
+ // Receive Control Register
+ /* BANK 0 */
+-#define RCR_REG SMC_REG(0x0004, 0)
++#define RCR_REG(lp) SMC_REG(lp, 0x0004, 0)
+ #define RCR_RX_ABORT 0x0001 // Set if a rx frame was aborted
+ #define RCR_PRMS 0x0002 // Enable promiscuous mode
+ #define RCR_ALMUL 0x0004 // When set accepts all multicast frames
+@@ -775,17 +760,17 @@ smc_pxa_dma_irq(int dma, void *dummy)
+
+ // Counter Register
+ /* BANK 0 */
+-#define COUNTER_REG SMC_REG(0x0006, 0)
++#define COUNTER_REG(lp) SMC_REG(lp, 0x0006, 0)
+
+
+ // Memory Information Register
+ /* BANK 0 */
+-#define MIR_REG SMC_REG(0x0008, 0)
++#define MIR_REG(lp) SMC_REG(lp, 0x0008, 0)
+
+
+ // Receive/Phy Control Register
+ /* BANK 0 */
+-#define RPC_REG SMC_REG(0x000A, 0)
++#define RPC_REG(lp) SMC_REG(lp, 0x000A, 0)
+ #define RPC_SPEED 0x2000 // When 1 PHY is in 100Mbps mode.
+ #define RPC_DPLX 0x1000 // When 1 PHY is in Full-Duplex Mode
+ #define RPC_ANEG 0x0800 // When 1 PHY is in Auto-Negotiate Mode
+@@ -819,7 +804,7 @@ smc_pxa_dma_irq(int dma, void *dummy)
+
+ // Configuration Reg
+ /* BANK 1 */
+-#define CONFIG_REG SMC_REG(0x0000, 1)
++#define CONFIG_REG(lp) SMC_REG(lp, 0x0000, 1)
+ #define CONFIG_EXT_PHY 0x0200 // 1=external MII, 0=internal Phy
+ #define CONFIG_GPCNTRL 0x0400 // Inverse value drives pin nCNTRL
+ #define CONFIG_NO_WAIT 0x1000 // When 1 no extra wait states on ISA bus
+@@ -831,24 +816,24 @@ smc_pxa_dma_irq(int dma, void *dummy)
+
+ // Base Address Register
+ /* BANK 1 */
+-#define BASE_REG SMC_REG(0x0002, 1)
++#define BASE_REG(lp) SMC_REG(lp, 0x0002, 1)
+
+
+ // Individual Address Registers
+ /* BANK 1 */
+-#define ADDR0_REG SMC_REG(0x0004, 1)
+-#define ADDR1_REG SMC_REG(0x0006, 1)
+-#define ADDR2_REG SMC_REG(0x0008, 1)
++#define ADDR0_REG(lp) SMC_REG(lp, 0x0004, 1)
++#define ADDR1_REG(lp) SMC_REG(lp, 0x0006, 1)
++#define ADDR2_REG(lp) SMC_REG(lp, 0x0008, 1)
+
+
+ // General Purpose Register
+ /* BANK 1 */
+-#define GP_REG SMC_REG(0x000A, 1)
++#define GP_REG(lp) SMC_REG(lp, 0x000A, 1)
+
+
+ // Control Register
+ /* BANK 1 */
+-#define CTL_REG SMC_REG(0x000C, 1)
++#define CTL_REG(lp) SMC_REG(lp, 0x000C, 1)
+ #define CTL_RCV_BAD 0x4000 // When 1 bad CRC packets are received
+ #define CTL_AUTO_RELEASE 0x0800 // When 1 tx pages are released automatically
+ #define CTL_LE_ENABLE 0x0080 // When 1 enables Link Error interrupt
+@@ -861,7 +846,7 @@ smc_pxa_dma_irq(int dma, void *dummy)
+
+ // MMU Command Register
+ /* BANK 2 */
+-#define MMU_CMD_REG SMC_REG(0x0000, 2)
++#define MMU_CMD_REG(lp) SMC_REG(lp, 0x0000, 2)
+ #define MC_BUSY 1 // When 1 the last release has not completed
+ #define MC_NOP (0<<5) // No Op
+ #define MC_ALLOC (1<<5) // OR with number of 256 byte packets
+@@ -875,30 +860,30 @@ smc_pxa_dma_irq(int dma, void *dummy)
+
+ // Packet Number Register
+ /* BANK 2 */
+-#define PN_REG SMC_REG(0x0002, 2)
++#define PN_REG(lp) SMC_REG(lp, 0x0002, 2)
+
+
+ // Allocation Result Register
+ /* BANK 2 */
+-#define AR_REG SMC_REG(0x0003, 2)
++#define AR_REG(lp) SMC_REG(lp, 0x0003, 2)
+ #define AR_FAILED 0x80 // Alocation Failed
+
+
+ // TX FIFO Ports Register
+ /* BANK 2 */
+-#define TXFIFO_REG SMC_REG(0x0004, 2)
++#define TXFIFO_REG(lp) SMC_REG(lp, 0x0004, 2)
+ #define TXFIFO_TEMPTY 0x80 // TX FIFO Empty
+
+ // RX FIFO Ports Register
+ /* BANK 2 */
+-#define RXFIFO_REG SMC_REG(0x0005, 2)
++#define RXFIFO_REG(lp) SMC_REG(lp, 0x0005, 2)
+ #define RXFIFO_REMPTY 0x80 // RX FIFO Empty
+
+-#define FIFO_REG SMC_REG(0x0004, 2)
++#define FIFO_REG(lp) SMC_REG(lp, 0x0004, 2)
+
+ // Pointer Register
+ /* BANK 2 */
+-#define PTR_REG SMC_REG(0x0006, 2)
++#define PTR_REG(lp) SMC_REG(lp, 0x0006, 2)
+ #define PTR_RCV 0x8000 // 1=Receive area, 0=Transmit area
+ #define PTR_AUTOINC 0x4000 // Auto increment the pointer on each access
+ #define PTR_READ 0x2000 // When 1 the operation is a read
+@@ -906,17 +891,17 @@ smc_pxa_dma_irq(int dma, void *dummy)
+
+ // Data Register
+ /* BANK 2 */
+-#define DATA_REG SMC_REG(0x0008, 2)
++#define DATA_REG(lp) SMC_REG(lp, 0x0008, 2)
+
+
+ // Interrupt Status/Acknowledge Register
+ /* BANK 2 */
+-#define INT_REG SMC_REG(0x000C, 2)
++#define INT_REG(lp) SMC_REG(lp, 0x000C, 2)
+
+
+ // Interrupt Mask Register
+ /* BANK 2 */
+-#define IM_REG SMC_REG(0x000D, 2)
++#define IM_REG(lp) SMC_REG(lp, 0x000D, 2)
+ #define IM_MDINT 0x80 // PHY MI Register 18 Interrupt
+ #define IM_ERCV_INT 0x40 // Early Receive Interrupt
+ #define IM_EPH_INT 0x20 // Set by Ethernet Protocol Handler section
+@@ -929,15 +914,15 @@ smc_pxa_dma_irq(int dma, void *dummy)
+
+ // Multicast Table Registers
+ /* BANK 3 */
+-#define MCAST_REG1 SMC_REG(0x0000, 3)
+-#define MCAST_REG2 SMC_REG(0x0002, 3)
+-#define MCAST_REG3 SMC_REG(0x0004, 3)
+-#define MCAST_REG4 SMC_REG(0x0006, 3)
++#define MCAST_REG1(lp) SMC_REG(lp, 0x0000, 3)
++#define MCAST_REG2(lp) SMC_REG(lp, 0x0002, 3)
++#define MCAST_REG3(lp) SMC_REG(lp, 0x0004, 3)
++#define MCAST_REG4(lp) SMC_REG(lp, 0x0006, 3)
+
+
+ // Management Interface Register (MII)
+ /* BANK 3 */
+-#define MII_REG SMC_REG(0x0008, 3)
++#define MII_REG(lp) SMC_REG(lp, 0x0008, 3)
+ #define MII_MSK_CRS100 0x4000 // Disables CRS100 detection during tx half dup
+ #define MII_MDOE 0x0008 // MII Output Enable
+ #define MII_MCLK 0x0004 // MII Clock, pin MDCLK
+@@ -948,20 +933,20 @@ smc_pxa_dma_irq(int dma, void *dummy)
+ // Revision Register
+ /* BANK 3 */
+ /* ( hi: chip id low: rev # ) */
+-#define REV_REG SMC_REG(0x000A, 3)
++#define REV_REG(lp) SMC_REG(lp, 0x000A, 3)
+
+
+ // Early RCV Register
+ /* BANK 3 */
+ /* this is NOT on SMC9192 */
+-#define ERCV_REG SMC_REG(0x000C, 3)
++#define ERCV_REG(lp) SMC_REG(lp, 0x000C, 3)
+ #define ERCV_RCV_DISCRD 0x0080 // When 1 discards a packet being received
+ #define ERCV_THRESHOLD 0x001F // ERCV Threshold Mask
+
+
+ // External Register
+ /* BANK 7 */
+-#define EXT_REG SMC_REG(0x0000, 7)
++#define EXT_REG(lp) SMC_REG(lp, 0x0000, 7)
+
+
+ #define CHIP_9192 3
+@@ -1085,9 +1070,9 @@ static const char * chip_ids[ 16 ] = {
+ */
+
+ #if SMC_DEBUG > 0
+-#define SMC_REG(reg, bank) \
++#define SMC_REG(lp, reg, bank) \
+ ({ \
+- int __b = SMC_CURRENT_BANK(); \
++ int __b = SMC_CURRENT_BANK(lp); \
+ if (unlikely((__b & ~0xf0) != (0x3300 | bank))) { \
+ printk( "%s: bank reg screwed (0x%04x)\n", \
+ CARDNAME, __b ); \
+@@ -1096,7 +1081,7 @@ static const char * chip_ids[ 16 ] = {
+ reg<<SMC_IO_SHIFT; \
+ })
+ #else
+-#define SMC_REG(reg, bank) (reg<<SMC_IO_SHIFT)
++#define SMC_REG(lp, reg, bank) (reg<<SMC_IO_SHIFT)
+ #endif
+
+ /*
+@@ -1108,212 +1093,215 @@ static const char * chip_ids[ 16 ] = {
+ *
+ * Enforce it on any 32-bit capable setup for now.
+ */
+-#define SMC_MUST_ALIGN_WRITE SMC_CAN_USE_32BIT
++#define SMC_MUST_ALIGN_WRITE(lp) SMC_32BIT(lp)
+
+-#define SMC_GET_PN() \
+- ( SMC_CAN_USE_8BIT ? (SMC_inb(ioaddr, PN_REG)) \
+- : (SMC_inw(ioaddr, PN_REG) & 0xFF) )
++#define SMC_GET_PN(lp) \
++ (SMC_8BIT(lp) ? (SMC_inb(ioaddr, PN_REG(lp))) \
++ : (SMC_inw(ioaddr, PN_REG(lp)) & 0xFF))
+
+-#define SMC_SET_PN(x) \
++#define SMC_SET_PN(lp, x) \
+ do { \
+- if (SMC_MUST_ALIGN_WRITE) \
+- SMC_outl((x)<<16, ioaddr, SMC_REG(0, 2)); \
+- else if (SMC_CAN_USE_8BIT) \
+- SMC_outb(x, ioaddr, PN_REG); \
++ if (SMC_MUST_ALIGN_WRITE(lp)) \
++ SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 0, 2)); \
++ else if (SMC_8BIT(lp)) \
++ SMC_outb(x, ioaddr, PN_REG(lp)); \
+ else \
+- SMC_outw(x, ioaddr, PN_REG); \
++ SMC_outw(x, ioaddr, PN_REG(lp)); \
+ } while (0)
+
+-#define SMC_GET_AR() \
+- ( SMC_CAN_USE_8BIT ? (SMC_inb(ioaddr, AR_REG)) \
+- : (SMC_inw(ioaddr, PN_REG) >> 8) )
++#define SMC_GET_AR(lp) \
++ (SMC_8BIT(lp) ? (SMC_inb(ioaddr, AR_REG(lp))) \
++ : (SMC_inw(ioaddr, PN_REG(lp)) >> 8))
+
+-#define SMC_GET_TXFIFO() \
+- ( SMC_CAN_USE_8BIT ? (SMC_inb(ioaddr, TXFIFO_REG)) \
+- : (SMC_inw(ioaddr, TXFIFO_REG) & 0xFF) )
++#define SMC_GET_TXFIFO(lp) \
++ (SMC_8BIT(lp) ? (SMC_inb(ioaddr, TXFIFO_REG(lp))) \
++ : (SMC_inw(ioaddr, TXFIFO_REG(lp)) & 0xFF))
+
+-#define SMC_GET_RXFIFO() \
+- ( SMC_CAN_USE_8BIT ? (SMC_inb(ioaddr, RXFIFO_REG)) \
+- : (SMC_inw(ioaddr, TXFIFO_REG) >> 8) )
++#define SMC_GET_RXFIFO(lp) \
++ (SMC_8BIT(lp) ? (SMC_inb(ioaddr, RXFIFO_REG(lp))) \
++ : (SMC_inw(ioaddr, TXFIFO_REG(lp)) >> 8))
+
+-#define SMC_GET_INT() \
+- ( SMC_CAN_USE_8BIT ? (SMC_inb(ioaddr, INT_REG)) \
+- : (SMC_inw(ioaddr, INT_REG) & 0xFF) )
++#define SMC_GET_INT(lp) \
++ (SMC_8BIT(lp) ? (SMC_inb(ioaddr, INT_REG(lp))) \
++ : (SMC_inw(ioaddr, INT_REG(lp)) & 0xFF))
+
+-#define SMC_ACK_INT(x) \
++#define SMC_ACK_INT(lp, x) \
+ do { \
+- if (SMC_CAN_USE_8BIT) \
+- SMC_outb(x, ioaddr, INT_REG); \
++ if (SMC_8BIT(lp)) \
++ SMC_outb(x, ioaddr, INT_REG(lp)); \
+ else { \
+ unsigned long __flags; \
+ int __mask; \
+ local_irq_save(__flags); \
+- __mask = SMC_inw( ioaddr, INT_REG ) & ~0xff; \
+- SMC_outw( __mask | (x), ioaddr, INT_REG ); \
++ __mask = SMC_inw(ioaddr, INT_REG(lp)) & ~0xff; \
++ SMC_outw(__mask | (x), ioaddr, INT_REG(lp)); \
+ local_irq_restore(__flags); \
+ } \
+ } while (0)
+
+-#define SMC_GET_INT_MASK() \
+- ( SMC_CAN_USE_8BIT ? (SMC_inb(ioaddr, IM_REG)) \
+- : (SMC_inw( ioaddr, INT_REG ) >> 8) )
++#define SMC_GET_INT_MASK(lp) \
++ (SMC_8BIT(lp) ? (SMC_inb(ioaddr, IM_REG(lp))) \
++ : (SMC_inw(ioaddr, INT_REG(lp)) >> 8))
+
+-#define SMC_SET_INT_MASK(x) \
++#define SMC_SET_INT_MASK(lp, x) \
+ do { \
+- if (SMC_CAN_USE_8BIT) \
+- SMC_outb(x, ioaddr, IM_REG); \
++ if (SMC_8BIT(lp)) \
++ SMC_outb(x, ioaddr, IM_REG(lp)); \
+ else \
+- SMC_outw((x) << 8, ioaddr, INT_REG); \
++ SMC_outw((x) << 8, ioaddr, INT_REG(lp)); \
+ } while (0)
+
+-#define SMC_CURRENT_BANK() SMC_inw(ioaddr, BANK_SELECT)
++#define SMC_CURRENT_BANK(lp) SMC_inw(ioaddr, BANK_SELECT)
+
+-#define SMC_SELECT_BANK(x) \
++#define SMC_SELECT_BANK(lp, x) \
+ do { \
+- if (SMC_MUST_ALIGN_WRITE) \
++ if (SMC_MUST_ALIGN_WRITE(lp)) \
+ SMC_outl((x)<<16, ioaddr, 12<<SMC_IO_SHIFT); \
+ else \
+ SMC_outw(x, ioaddr, BANK_SELECT); \
+ } while (0)
+
+-#define SMC_GET_BASE() SMC_inw(ioaddr, BASE_REG)
++#define SMC_GET_BASE(lp) SMC_inw(ioaddr, BASE_REG(lp))
+
+-#define SMC_SET_BASE(x) SMC_outw(x, ioaddr, BASE_REG)
++#define SMC_SET_BASE(lp, x) SMC_outw(x, ioaddr, BASE_REG(lp))
+
+-#define SMC_GET_CONFIG() SMC_inw(ioaddr, CONFIG_REG)
++#define SMC_GET_CONFIG(lp) SMC_inw(ioaddr, CONFIG_REG(lp))
+
+-#define SMC_SET_CONFIG(x) SMC_outw(x, ioaddr, CONFIG_REG)
++#define SMC_SET_CONFIG(lp, x) SMC_outw(x, ioaddr, CONFIG_REG(lp))
+
+-#define SMC_GET_COUNTER() SMC_inw(ioaddr, COUNTER_REG)
++#define SMC_GET_COUNTER(lp) SMC_inw(ioaddr, COUNTER_REG(lp))
+
+-#define SMC_GET_CTL() SMC_inw(ioaddr, CTL_REG)
++#define SMC_GET_CTL(lp) SMC_inw(ioaddr, CTL_REG(lp))
+
+-#define SMC_SET_CTL(x) SMC_outw(x, ioaddr, CTL_REG)
++#define SMC_SET_CTL(lp, x) SMC_outw(x, ioaddr, CTL_REG(lp))
+
+-#define SMC_GET_MII() SMC_inw(ioaddr, MII_REG)
++#define SMC_GET_MII(lp) SMC_inw(ioaddr, MII_REG(lp))
+
+-#define SMC_SET_MII(x) SMC_outw(x, ioaddr, MII_REG)
++#define SMC_SET_MII(lp, x) SMC_outw(x, ioaddr, MII_REG(lp))
+
+-#define SMC_GET_MIR() SMC_inw(ioaddr, MIR_REG)
++#define SMC_GET_MIR(lp) SMC_inw(ioaddr, MIR_REG(lp))
+
+-#define SMC_SET_MIR(x) SMC_outw(x, ioaddr, MIR_REG)
++#define SMC_SET_MIR(lp, x) SMC_outw(x, ioaddr, MIR_REG(lp))
+
+-#define SMC_GET_MMU_CMD() SMC_inw(ioaddr, MMU_CMD_REG)
++#define SMC_GET_MMU_CMD(lp) SMC_inw(ioaddr, MMU_CMD_REG(lp))
+
+-#define SMC_SET_MMU_CMD(x) SMC_outw(x, ioaddr, MMU_CMD_REG)
++#define SMC_SET_MMU_CMD(lp, x) SMC_outw(x, ioaddr, MMU_CMD_REG(lp))
+
+-#define SMC_GET_FIFO() SMC_inw(ioaddr, FIFO_REG)
++#define SMC_GET_FIFO(lp) SMC_inw(ioaddr, FIFO_REG(lp))
+
+-#define SMC_GET_PTR() SMC_inw(ioaddr, PTR_REG)
++#define SMC_GET_PTR(lp) SMC_inw(ioaddr, PTR_REG(lp))
+
+-#define SMC_SET_PTR(x) \
++#define SMC_SET_PTR(lp, x) \
+ do { \
+- if (SMC_MUST_ALIGN_WRITE) \
+- SMC_outl((x)<<16, ioaddr, SMC_REG(4, 2)); \
++ if (SMC_MUST_ALIGN_WRITE(lp)) \
++ SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 4, 2)); \
+ else \
+- SMC_outw(x, ioaddr, PTR_REG); \
++ SMC_outw(x, ioaddr, PTR_REG(lp)); \
+ } while (0)
+
+-#define SMC_GET_EPH_STATUS() SMC_inw(ioaddr, EPH_STATUS_REG)
++#define SMC_GET_EPH_STATUS(lp) SMC_inw(ioaddr, EPH_STATUS_REG(lp))
+
+-#define SMC_GET_RCR() SMC_inw(ioaddr, RCR_REG)
++#define SMC_GET_RCR(lp) SMC_inw(ioaddr, RCR_REG(lp))
+
+-#define SMC_SET_RCR(x) SMC_outw(x, ioaddr, RCR_REG)
++#define SMC_SET_RCR(lp, x) SMC_outw(x, ioaddr, RCR_REG(lp))
+
+-#define SMC_GET_REV() SMC_inw(ioaddr, REV_REG)
++#define SMC_GET_REV(lp) SMC_inw(ioaddr, REV_REG(lp))
+
+-#define SMC_GET_RPC() SMC_inw(ioaddr, RPC_REG)
++#define SMC_GET_RPC(lp) SMC_inw(ioaddr, RPC_REG(lp))
+
+-#define SMC_SET_RPC(x) \
++#define SMC_SET_RPC(lp, x) \
+ do { \
+- if (SMC_MUST_ALIGN_WRITE) \
+- SMC_outl((x)<<16, ioaddr, SMC_REG(8, 0)); \
++ if (SMC_MUST_ALIGN_WRITE(lp)) \
++ SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 8, 0)); \
+ else \
+- SMC_outw(x, ioaddr, RPC_REG); \
++ SMC_outw(x, ioaddr, RPC_REG(lp)); \
+ } while (0)
+
+-#define SMC_GET_TCR() SMC_inw(ioaddr, TCR_REG)
++#define SMC_GET_TCR(lp) SMC_inw(ioaddr, TCR_REG(lp))
+
+-#define SMC_SET_TCR(x) SMC_outw(x, ioaddr, TCR_REG)
++#define SMC_SET_TCR(lp, x) SMC_outw(x, ioaddr, TCR_REG(lp))
+
+ #ifndef SMC_GET_MAC_ADDR
+-#define SMC_GET_MAC_ADDR(addr) \
++#define SMC_GET_MAC_ADDR(lp, addr) \
+ do { \
+ unsigned int __v; \
+- __v = SMC_inw( ioaddr, ADDR0_REG ); \
++ __v = SMC_inw(ioaddr, ADDR0_REG(lp)); \
+ addr[0] = __v; addr[1] = __v >> 8; \
+- __v = SMC_inw( ioaddr, ADDR1_REG ); \
++ __v = SMC_inw(ioaddr, ADDR1_REG(lp)); \
+ addr[2] = __v; addr[3] = __v >> 8; \
+- __v = SMC_inw( ioaddr, ADDR2_REG ); \
++ __v = SMC_inw(ioaddr, ADDR2_REG(lp)); \
+ addr[4] = __v; addr[5] = __v >> 8; \
+ } while (0)
+ #endif
+
+-#define SMC_SET_MAC_ADDR(addr) \
++#define SMC_SET_MAC_ADDR(lp, addr) \
+ do { \
+- SMC_outw( addr[0]|(addr[1] << 8), ioaddr, ADDR0_REG ); \
+- SMC_outw( addr[2]|(addr[3] << 8), ioaddr, ADDR1_REG ); \
+- SMC_outw( addr[4]|(addr[5] << 8), ioaddr, ADDR2_REG ); \
++ SMC_outw(addr[0]|(addr[1] << 8), ioaddr, ADDR0_REG(lp)); \
++ SMC_outw(addr[2]|(addr[3] << 8), ioaddr, ADDR1_REG(lp)); \
++ SMC_outw(addr[4]|(addr[5] << 8), ioaddr, ADDR2_REG(lp)); \
+ } while (0)
+
+-#define SMC_SET_MCAST(x) \
++#define SMC_SET_MCAST(lp, x) \
+ do { \
+ const unsigned char *mt = (x); \
+- SMC_outw( mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1 ); \
+- SMC_outw( mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2 ); \
+- SMC_outw( mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3 ); \
+- SMC_outw( mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4 ); \
++ SMC_outw(mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1(lp)); \
++ SMC_outw(mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2(lp)); \
++ SMC_outw(mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3(lp)); \
++ SMC_outw(mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4(lp)); \
+ } while (0)
+
+-#define SMC_PUT_PKT_HDR(status, length) \
++#define SMC_PUT_PKT_HDR(lp, status, length) \
+ do { \
+- if (SMC_CAN_USE_32BIT) \
+- SMC_outl((status) | (length)<<16, ioaddr, DATA_REG); \
++ if (SMC_32BIT(lp)) \
++ SMC_outl((status) | (length)<<16, ioaddr, \
++ DATA_REG(lp)); \
+ else { \
+- SMC_outw(status, ioaddr, DATA_REG); \
+- SMC_outw(length, ioaddr, DATA_REG); \
++ SMC_outw(status, ioaddr, DATA_REG(lp)); \
++ SMC_outw(length, ioaddr, DATA_REG(lp)); \
+ } \
+ } while (0)
+
+-#define SMC_GET_PKT_HDR(status, length) \
++#define SMC_GET_PKT_HDR(lp, status, length) \
+ do { \
+- if (SMC_CAN_USE_32BIT) { \
+- unsigned int __val = SMC_inl(ioaddr, DATA_REG); \
++ if (SMC_32BIT(lp)) { \
++ unsigned int __val = SMC_inl(ioaddr, DATA_REG(lp)); \
+ (status) = __val & 0xffff; \
+ (length) = __val >> 16; \
+ } else { \
+- (status) = SMC_inw(ioaddr, DATA_REG); \
+- (length) = SMC_inw(ioaddr, DATA_REG); \
++ (status) = SMC_inw(ioaddr, DATA_REG(lp)); \
++ (length) = SMC_inw(ioaddr, DATA_REG(lp)); \
+ } \
+ } while (0)
+
+-#define SMC_PUSH_DATA(p, l) \
++#define SMC_PUSH_DATA(lp, p, l) \
+ do { \
+- if (SMC_CAN_USE_32BIT) { \
++ if (SMC_32BIT(lp)) { \
+ void *__ptr = (p); \
+ int __len = (l); \
+ void __iomem *__ioaddr = ioaddr; \
+ if (__len >= 2 && (unsigned long)__ptr & 2) { \
+ __len -= 2; \
+- SMC_outw(*(u16 *)__ptr, ioaddr, DATA_REG); \
++ SMC_outw(*(u16 *)__ptr, ioaddr, \
++ DATA_REG(lp)); \
+ __ptr += 2; \
+ } \
+ if (SMC_CAN_USE_DATACS && lp->datacs) \
+ __ioaddr = lp->datacs; \
+- SMC_outsl(__ioaddr, DATA_REG, __ptr, __len>>2); \
++ SMC_outsl(__ioaddr, DATA_REG(lp), __ptr, __len>>2); \
+ if (__len & 2) { \
+ __ptr += (__len & ~3); \
+- SMC_outw(*((u16 *)__ptr), ioaddr, DATA_REG); \
++ SMC_outw(*((u16 *)__ptr), ioaddr, \
++ DATA_REG(lp)); \
+ } \
+- } else if (SMC_CAN_USE_16BIT) \
+- SMC_outsw(ioaddr, DATA_REG, p, (l) >> 1); \
+- else if (SMC_CAN_USE_8BIT) \
+- SMC_outsb(ioaddr, DATA_REG, p, l); \
++ } else if (SMC_16BIT(lp)) \
++ SMC_outsw(ioaddr, DATA_REG(lp), p, (l) >> 1); \
++ else if (SMC_8BIT(lp)) \
++ SMC_outsb(ioaddr, DATA_REG(lp), p, l); \
+ } while (0)
+
+-#define SMC_PULL_DATA(p, l) \
++#define SMC_PULL_DATA(lp, p, l) \
+ do { \
+- if (SMC_CAN_USE_32BIT) { \
++ if (SMC_32BIT(lp)) { \
+ void *__ptr = (p); \
+ int __len = (l); \
+ void __iomem *__ioaddr = ioaddr; \
+@@ -1333,16 +1321,17 @@ static const char * chip_ids[ 16 ] = {
+ */ \
+ __ptr -= 2; \
+ __len += 2; \
+- SMC_SET_PTR(2|PTR_READ|PTR_RCV|PTR_AUTOINC); \
++ SMC_SET_PTR(lp, \
++ 2|PTR_READ|PTR_RCV|PTR_AUTOINC); \
+ } \
+ if (SMC_CAN_USE_DATACS && lp->datacs) \
+ __ioaddr = lp->datacs; \
+ __len += 2; \
+- SMC_insl(__ioaddr, DATA_REG, __ptr, __len>>2); \
+- } else if (SMC_CAN_USE_16BIT) \
+- SMC_insw(ioaddr, DATA_REG, p, (l) >> 1); \
+- else if (SMC_CAN_USE_8BIT) \
+- SMC_insb(ioaddr, DATA_REG, p, l); \
++ SMC_insl(__ioaddr, DATA_REG(lp), __ptr, __len>>2); \
++ } else if (SMC_16BIT(lp)) \
++ SMC_insw(ioaddr, DATA_REG(lp), p, (l) >> 1); \
++ else if (SMC_8BIT(lp)) \
++ SMC_insb(ioaddr, DATA_REG(lp), p, l); \
+ } while (0)
+
+ #endif /* _SMC91X_H_ */
+diff --git a/drivers/net/sni_82596.c b/drivers/net/sni_82596.c
+index 2cf6794..854ccf2 100644
+--- a/drivers/net/sni_82596.c
++++ b/drivers/net/sni_82596.c
+@@ -44,6 +44,7 @@ static const char sni_82596_string[] = "snirm_82596";
+ MODULE_AUTHOR("Thomas Bogendoerfer");
+ MODULE_DESCRIPTION("i82596 driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:snirm_82596");
+ module_param(i596_debug, int, 0);
+ MODULE_PARM_DESC(i596_debug, "82596 debug mask");
+
+@@ -166,6 +167,7 @@ static struct platform_driver sni_82596_driver = {
+ .remove = __devexit_p(sni_82596_driver_remove),
+ .driver = {
+ .name = sni_82596_string,
++ .owner = THIS_MODULE,
+ },
+ };
+
+diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
+index bccae7e..4776716 100644
+--- a/drivers/net/spider_net.c
++++ b/drivers/net/spider_net.c
+@@ -1399,6 +1399,8 @@ spider_net_link_reset(struct net_device *netdev)
+ spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0);
+
+ /* reset phy and setup aneg */
++ card->aneg_count = 0;
++ card->medium = BCM54XX_COPPER;
+ spider_net_setup_aneg(card);
+ mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER);
+
+@@ -1413,18 +1415,12 @@ spider_net_link_reset(struct net_device *netdev)
+ * found when an interrupt is presented
+ */
+ static void
+-spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
++spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg,
++ u32 error_reg1, u32 error_reg2)
+ {
+- u32 error_reg1, error_reg2;
+ u32 i;
+ int show_error = 1;
+
+- error_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1STS);
+- error_reg2 = spider_net_read_reg(card, SPIDER_NET_GHIINT2STS);
+-
+- error_reg1 &= SPIDER_NET_INT1_MASK_VALUE;
+- error_reg2 &= SPIDER_NET_INT2_MASK_VALUE;
+-
+ /* check GHIINT0STS ************************************/
+ if (status_reg)
+ for (i = 0; i < 32; i++)
+@@ -1654,12 +1650,15 @@ spider_net_interrupt(int irq, void *ptr)
+ {
+ struct net_device *netdev = ptr;
+ struct spider_net_card *card = netdev_priv(netdev);
+- u32 status_reg;
++ u32 status_reg, error_reg1, error_reg2;
+
+ status_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0STS);
+- status_reg &= SPIDER_NET_INT0_MASK_VALUE;
++ error_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1STS);
++ error_reg2 = spider_net_read_reg(card, SPIDER_NET_GHIINT2STS);
+
+- if (!status_reg)
++ if (!(status_reg & SPIDER_NET_INT0_MASK_VALUE) &&
++ !(error_reg1 & SPIDER_NET_INT1_MASK_VALUE) &&
++ !(error_reg2 & SPIDER_NET_INT2_MASK_VALUE))
+ return IRQ_NONE;
+
+ if (status_reg & SPIDER_NET_RXINT ) {
+@@ -1674,7 +1673,8 @@ spider_net_interrupt(int irq, void *ptr)
+ spider_net_link_reset(netdev);
+
+ if (status_reg & SPIDER_NET_ERRINT )
+- spider_net_handle_error_irq(card, status_reg);
++ spider_net_handle_error_irq(card, status_reg,
++ error_reg1, error_reg2);
+
+ /* clear interrupt sources */
+ spider_net_write_reg(card, SPIDER_NET_GHIINT0STS, status_reg);
+@@ -1982,6 +1982,8 @@ spider_net_open(struct net_device *netdev)
+ goto init_firmware_failed;
+
+ /* start probing with copper */
++ card->aneg_count = 0;
++ card->medium = BCM54XX_COPPER;
+ spider_net_setup_aneg(card);
+ if (card->phy.def->phy_id)
+ mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER);
+@@ -2043,7 +2045,8 @@ static void spider_net_link_phy(unsigned long data)
+ /* if link didn't come up after SPIDER_NET_ANEG_TIMEOUT tries, setup phy again */
+ if (card->aneg_count > SPIDER_NET_ANEG_TIMEOUT) {
+
+- pr_info("%s: link is down trying to bring it up\n", card->netdev->name);
++ pr_debug("%s: link is down trying to bring it up\n",
++ card->netdev->name);
+
+ switch (card->medium) {
+ case BCM54XX_COPPER:
+@@ -2094,9 +2097,10 @@ static void spider_net_link_phy(unsigned long data)
+
+ card->aneg_count = 0;
+
+- pr_debug("Found %s with %i Mbps, %s-duplex %sautoneg.\n",
+- phy->def->name, phy->speed, phy->duplex==1 ? "Full" : "Half",
+- phy->autoneg==1 ? "" : "no ");
++ pr_info("%s: link up, %i Mbps, %s-duplex %sautoneg.\n",
++ card->netdev->name, phy->speed,
++ phy->duplex == 1 ? "Full" : "Half",
++ phy->autoneg == 1 ? "" : "no ");
+
+ return;
+ }
+diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h
+index e1d05c0..05f74cb 100644
+--- a/drivers/net/spider_net.h
++++ b/drivers/net/spider_net.h
+@@ -52,7 +52,7 @@ extern char spider_net_driver_name[];
+
+ #define SPIDER_NET_TX_TIMER (HZ/5)
+ #define SPIDER_NET_ANEG_TIMER (HZ)
+-#define SPIDER_NET_ANEG_TIMEOUT 2
++#define SPIDER_NET_ANEG_TIMEOUT 5
+
+ #define SPIDER_NET_RX_CSUM_DEFAULT 1
+
+@@ -159,9 +159,8 @@ extern char spider_net_driver_name[];
+
+ /** interrupt mask registers */
+ #define SPIDER_NET_INT0_MASK_VALUE 0x3f7fe2c7
+-#define SPIDER_NET_INT1_MASK_VALUE 0xffff7ff7
+-/* no MAC aborts -> auto retransmission */
+-#define SPIDER_NET_INT2_MASK_VALUE 0xffef7ff1
++#define SPIDER_NET_INT1_MASK_VALUE 0x0000fff2
++#define SPIDER_NET_INT2_MASK_VALUE 0x000003f1
+
+ /* we rely on flagged descriptor interrupts */
+ #define SPIDER_NET_FRAMENUM_VALUE 0x00000000
+diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c
+index 370d329..10e4e85 100644
+--- a/drivers/net/tc35815.c
++++ b/drivers/net/tc35815.c
+@@ -23,9 +23,9 @@
+ */
+
+ #ifdef TC35815_NAPI
+-#define DRV_VERSION "1.36-NAPI"
++#define DRV_VERSION "1.37-NAPI"
+ #else
+-#define DRV_VERSION "1.36"
++#define DRV_VERSION "1.37"
+ #endif
+ static const char *version = "tc35815.c:v" DRV_VERSION "\n";
+ #define MODNAME "tc35815"
+@@ -47,8 +47,8 @@ static const char *version = "tc35815.c:v" DRV_VERSION "\n";
+ #include <linux/skbuff.h>
+ #include <linux/delay.h>
+ #include <linux/pci.h>
+-#include <linux/mii.h>
+-#include <linux/ethtool.h>
++#include <linux/phy.h>
++#include <linux/workqueue.h>
+ #include <linux/platform_device.h>
+ #include <asm/io.h>
+ #include <asm/byteorder.h>
+@@ -60,16 +60,16 @@ static const char *version = "tc35815.c:v" DRV_VERSION "\n";
+ #define WORKAROUND_100HALF_PROMISC
+ /* #define TC35815_USE_PACKEDBUFFER */
+
+-typedef enum {
++enum tc35815_chiptype {
+ TC35815CF = 0,
+ TC35815_NWU,
+ TC35815_TX4939,
+-} board_t;
++};
+
+-/* indexed by board_t, above */
++/* indexed by tc35815_chiptype, above */
+ static const struct {
+ const char *name;
+-} board_info[] __devinitdata = {
++} chip_info[] __devinitdata = {
+ { "TOSHIBA TC35815CF 10/100BaseTX" },
+ { "TOSHIBA TC35815 with Wake on LAN" },
+ { "TOSHIBA TC35815/TX4939" },
+@@ -81,209 +81,208 @@ static const struct pci_device_id tc35815_pci_tbl[] = {
+ {PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC35815_TX4939), .driver_data = TC35815_TX4939 },
+ {0,}
+ };
+-MODULE_DEVICE_TABLE (pci, tc35815_pci_tbl);
++MODULE_DEVICE_TABLE(pci, tc35815_pci_tbl);
+
+ /* see MODULE_PARM_DESC */
+ static struct tc35815_options {
+ int speed;
+ int duplex;
+- int doforce;
+ } options;
+
+ /*
+ * Registers
+ */
+ struct tc35815_regs {
+- volatile __u32 DMA_Ctl; /* 0x00 */
+- volatile __u32 TxFrmPtr;
+- volatile __u32 TxThrsh;
+- volatile __u32 TxPollCtr;
+- volatile __u32 BLFrmPtr;
+- volatile __u32 RxFragSize;
+- volatile __u32 Int_En;
+- volatile __u32 FDA_Bas;
+- volatile __u32 FDA_Lim; /* 0x20 */
+- volatile __u32 Int_Src;
+- volatile __u32 unused0[2];
+- volatile __u32 PauseCnt;
+- volatile __u32 RemPauCnt;
+- volatile __u32 TxCtlFrmStat;
+- volatile __u32 unused1;
+- volatile __u32 MAC_Ctl; /* 0x40 */
+- volatile __u32 CAM_Ctl;
+- volatile __u32 Tx_Ctl;
+- volatile __u32 Tx_Stat;
+- volatile __u32 Rx_Ctl;
+- volatile __u32 Rx_Stat;
+- volatile __u32 MD_Data;
+- volatile __u32 MD_CA;
+- volatile __u32 CAM_Adr; /* 0x60 */
+- volatile __u32 CAM_Data;
+- volatile __u32 CAM_Ena;
+- volatile __u32 PROM_Ctl;
+- volatile __u32 PROM_Data;
+- volatile __u32 Algn_Cnt;
+- volatile __u32 CRC_Cnt;
+- volatile __u32 Miss_Cnt;
++ __u32 DMA_Ctl; /* 0x00 */
++ __u32 TxFrmPtr;
++ __u32 TxThrsh;
++ __u32 TxPollCtr;
++ __u32 BLFrmPtr;
++ __u32 RxFragSize;
++ __u32 Int_En;
++ __u32 FDA_Bas;
++ __u32 FDA_Lim; /* 0x20 */
++ __u32 Int_Src;
++ __u32 unused0[2];
++ __u32 PauseCnt;
++ __u32 RemPauCnt;
++ __u32 TxCtlFrmStat;
++ __u32 unused1;
++ __u32 MAC_Ctl; /* 0x40 */
++ __u32 CAM_Ctl;
++ __u32 Tx_Ctl;
++ __u32 Tx_Stat;
++ __u32 Rx_Ctl;
++ __u32 Rx_Stat;
++ __u32 MD_Data;
++ __u32 MD_CA;
++ __u32 CAM_Adr; /* 0x60 */
++ __u32 CAM_Data;
++ __u32 CAM_Ena;
++ __u32 PROM_Ctl;
++ __u32 PROM_Data;
++ __u32 Algn_Cnt;
++ __u32 CRC_Cnt;
++ __u32 Miss_Cnt;
+ };
+
+ /*
+ * Bit assignments
+ */
+ /* DMA_Ctl bit asign ------------------------------------------------------- */
+-#define DMA_RxAlign 0x00c00000 /* 1:Reception Alignment */
+-#define DMA_RxAlign_1 0x00400000
+-#define DMA_RxAlign_2 0x00800000
+-#define DMA_RxAlign_3 0x00c00000
+-#define DMA_M66EnStat 0x00080000 /* 1:66MHz Enable State */
+-#define DMA_IntMask 0x00040000 /* 1:Interupt mask */
+-#define DMA_SWIntReq 0x00020000 /* 1:Software Interrupt request */
+-#define DMA_TxWakeUp 0x00010000 /* 1:Transmit Wake Up */
+-#define DMA_RxBigE 0x00008000 /* 1:Receive Big Endian */
+-#define DMA_TxBigE 0x00004000 /* 1:Transmit Big Endian */
+-#define DMA_TestMode 0x00002000 /* 1:Test Mode */
+-#define DMA_PowrMgmnt 0x00001000 /* 1:Power Management */
+-#define DMA_DmBurst_Mask 0x000001fc /* DMA Burst size */
++#define DMA_RxAlign 0x00c00000 /* 1:Reception Alignment */
++#define DMA_RxAlign_1 0x00400000
++#define DMA_RxAlign_2 0x00800000
++#define DMA_RxAlign_3 0x00c00000
++#define DMA_M66EnStat 0x00080000 /* 1:66MHz Enable State */
++#define DMA_IntMask 0x00040000 /* 1:Interupt mask */
++#define DMA_SWIntReq 0x00020000 /* 1:Software Interrupt request */
++#define DMA_TxWakeUp 0x00010000 /* 1:Transmit Wake Up */
++#define DMA_RxBigE 0x00008000 /* 1:Receive Big Endian */
++#define DMA_TxBigE 0x00004000 /* 1:Transmit Big Endian */
++#define DMA_TestMode 0x00002000 /* 1:Test Mode */
++#define DMA_PowrMgmnt 0x00001000 /* 1:Power Management */
++#define DMA_DmBurst_Mask 0x000001fc /* DMA Burst size */
+
+ /* RxFragSize bit asign ---------------------------------------------------- */
+-#define RxFrag_EnPack 0x00008000 /* 1:Enable Packing */
+-#define RxFrag_MinFragMask 0x00000ffc /* Minimum Fragment */
++#define RxFrag_EnPack 0x00008000 /* 1:Enable Packing */
++#define RxFrag_MinFragMask 0x00000ffc /* Minimum Fragment */
+
+ /* MAC_Ctl bit asign ------------------------------------------------------- */
+-#define MAC_Link10 0x00008000 /* 1:Link Status 10Mbits */
+-#define MAC_EnMissRoll 0x00002000 /* 1:Enable Missed Roll */
+-#define MAC_MissRoll 0x00000400 /* 1:Missed Roll */
+-#define MAC_Loop10 0x00000080 /* 1:Loop 10 Mbps */
+-#define MAC_Conn_Auto 0x00000000 /*00:Connection mode (Automatic) */
+-#define MAC_Conn_10M 0x00000020 /*01: (10Mbps endec)*/
+-#define MAC_Conn_Mll 0x00000040 /*10: (Mll clock) */
+-#define MAC_MacLoop 0x00000010 /* 1:MAC Loopback */
+-#define MAC_FullDup 0x00000008 /* 1:Full Duplex 0:Half Duplex */
+-#define MAC_Reset 0x00000004 /* 1:Software Reset */
+-#define MAC_HaltImm 0x00000002 /* 1:Halt Immediate */
+-#define MAC_HaltReq 0x00000001 /* 1:Halt request */
++#define MAC_Link10 0x00008000 /* 1:Link Status 10Mbits */
++#define MAC_EnMissRoll 0x00002000 /* 1:Enable Missed Roll */
++#define MAC_MissRoll 0x00000400 /* 1:Missed Roll */
++#define MAC_Loop10 0x00000080 /* 1:Loop 10 Mbps */
++#define MAC_Conn_Auto 0x00000000 /*00:Connection mode (Automatic) */
++#define MAC_Conn_10M 0x00000020 /*01: (10Mbps endec)*/
++#define MAC_Conn_Mll 0x00000040 /*10: (Mll clock) */
++#define MAC_MacLoop 0x00000010 /* 1:MAC Loopback */
++#define MAC_FullDup 0x00000008 /* 1:Full Duplex 0:Half Duplex */
++#define MAC_Reset 0x00000004 /* 1:Software Reset */
++#define MAC_HaltImm 0x00000002 /* 1:Halt Immediate */
++#define MAC_HaltReq 0x00000001 /* 1:Halt request */
+
+ /* PROM_Ctl bit asign ------------------------------------------------------ */
+-#define PROM_Busy 0x00008000 /* 1:Busy (Start Operation) */
+-#define PROM_Read 0x00004000 /*10:Read operation */
+-#define PROM_Write 0x00002000 /*01:Write operation */
+-#define PROM_Erase 0x00006000 /*11:Erase operation */
+- /*00:Enable or Disable Writting, */
+- /* as specified in PROM_Addr. */
+-#define PROM_Addr_Ena 0x00000030 /*11xxxx:PROM Write enable */
+- /*00xxxx: disable */
++#define PROM_Busy 0x00008000 /* 1:Busy (Start Operation) */
++#define PROM_Read 0x00004000 /*10:Read operation */
++#define PROM_Write 0x00002000 /*01:Write operation */
++#define PROM_Erase 0x00006000 /*11:Erase operation */
++ /*00:Enable or Disable Writting, */
++ /* as specified in PROM_Addr. */
++#define PROM_Addr_Ena 0x00000030 /*11xxxx:PROM Write enable */
++ /*00xxxx: disable */
+
+ /* CAM_Ctl bit asign ------------------------------------------------------- */
+-#define CAM_CompEn 0x00000010 /* 1:CAM Compare Enable */
+-#define CAM_NegCAM 0x00000008 /* 1:Reject packets CAM recognizes,*/
+- /* accept other */
+-#define CAM_BroadAcc 0x00000004 /* 1:Broadcast assept */
+-#define CAM_GroupAcc 0x00000002 /* 1:Multicast assept */
+-#define CAM_StationAcc 0x00000001 /* 1:unicast accept */
++#define CAM_CompEn 0x00000010 /* 1:CAM Compare Enable */
++#define CAM_NegCAM 0x00000008 /* 1:Reject packets CAM recognizes,*/
++ /* accept other */
++#define CAM_BroadAcc 0x00000004 /* 1:Broadcast assept */
++#define CAM_GroupAcc 0x00000002 /* 1:Multicast assept */
++#define CAM_StationAcc 0x00000001 /* 1:unicast accept */
+
+ /* CAM_Ena bit asign ------------------------------------------------------- */
+-#define CAM_ENTRY_MAX 21 /* CAM Data entry max count */
++#define CAM_ENTRY_MAX 21 /* CAM Data entry max count */
+ #define CAM_Ena_Mask ((1<<CAM_ENTRY_MAX)-1) /* CAM Enable bits (Max 21bits) */
+-#define CAM_Ena_Bit(index) (1<<(index))
++#define CAM_Ena_Bit(index) (1 << (index))
+ #define CAM_ENTRY_DESTINATION 0
+ #define CAM_ENTRY_SOURCE 1
+ #define CAM_ENTRY_MACCTL 20
+
+ /* Tx_Ctl bit asign -------------------------------------------------------- */
+-#define Tx_En 0x00000001 /* 1:Transmit enable */
+-#define Tx_TxHalt 0x00000002 /* 1:Transmit Halt Request */
+-#define Tx_NoPad 0x00000004 /* 1:Suppress Padding */
+-#define Tx_NoCRC 0x00000008 /* 1:Suppress Padding */
+-#define Tx_FBack 0x00000010 /* 1:Fast Back-off */
+-#define Tx_EnUnder 0x00000100 /* 1:Enable Underrun */
+-#define Tx_EnExDefer 0x00000200 /* 1:Enable Excessive Deferral */
+-#define Tx_EnLCarr 0x00000400 /* 1:Enable Lost Carrier */
+-#define Tx_EnExColl 0x00000800 /* 1:Enable Excessive Collision */
+-#define Tx_EnLateColl 0x00001000 /* 1:Enable Late Collision */
+-#define Tx_EnTxPar 0x00002000 /* 1:Enable Transmit Parity */
+-#define Tx_EnComp 0x00004000 /* 1:Enable Completion */
++#define Tx_En 0x00000001 /* 1:Transmit enable */
++#define Tx_TxHalt 0x00000002 /* 1:Transmit Halt Request */
++#define Tx_NoPad 0x00000004 /* 1:Suppress Padding */
++#define Tx_NoCRC 0x00000008 /* 1:Suppress Padding */
++#define Tx_FBack 0x00000010 /* 1:Fast Back-off */
++#define Tx_EnUnder 0x00000100 /* 1:Enable Underrun */
++#define Tx_EnExDefer 0x00000200 /* 1:Enable Excessive Deferral */
++#define Tx_EnLCarr 0x00000400 /* 1:Enable Lost Carrier */
++#define Tx_EnExColl 0x00000800 /* 1:Enable Excessive Collision */
++#define Tx_EnLateColl 0x00001000 /* 1:Enable Late Collision */
++#define Tx_EnTxPar 0x00002000 /* 1:Enable Transmit Parity */
++#define Tx_EnComp 0x00004000 /* 1:Enable Completion */
+
+ /* Tx_Stat bit asign ------------------------------------------------------- */
+-#define Tx_TxColl_MASK 0x0000000F /* Tx Collision Count */
+-#define Tx_ExColl 0x00000010 /* Excessive Collision */
+-#define Tx_TXDefer 0x00000020 /* Transmit Defered */
+-#define Tx_Paused 0x00000040 /* Transmit Paused */
+-#define Tx_IntTx 0x00000080 /* Interrupt on Tx */
+-#define Tx_Under 0x00000100 /* Underrun */
+-#define Tx_Defer 0x00000200 /* Deferral */
+-#define Tx_NCarr 0x00000400 /* No Carrier */
+-#define Tx_10Stat 0x00000800 /* 10Mbps Status */
+-#define Tx_LateColl 0x00001000 /* Late Collision */
+-#define Tx_TxPar 0x00002000 /* Tx Parity Error */
+-#define Tx_Comp 0x00004000 /* Completion */
+-#define Tx_Halted 0x00008000 /* Tx Halted */
+-#define Tx_SQErr 0x00010000 /* Signal Quality Error(SQE) */
++#define Tx_TxColl_MASK 0x0000000F /* Tx Collision Count */
++#define Tx_ExColl 0x00000010 /* Excessive Collision */
++#define Tx_TXDefer 0x00000020 /* Transmit Defered */
++#define Tx_Paused 0x00000040 /* Transmit Paused */
++#define Tx_IntTx 0x00000080 /* Interrupt on Tx */
++#define Tx_Under 0x00000100 /* Underrun */
++#define Tx_Defer 0x00000200 /* Deferral */
++#define Tx_NCarr 0x00000400 /* No Carrier */
++#define Tx_10Stat 0x00000800 /* 10Mbps Status */
++#define Tx_LateColl 0x00001000 /* Late Collision */
++#define Tx_TxPar 0x00002000 /* Tx Parity Error */
++#define Tx_Comp 0x00004000 /* Completion */
++#define Tx_Halted 0x00008000 /* Tx Halted */
++#define Tx_SQErr 0x00010000 /* Signal Quality Error(SQE) */
+
+ /* Rx_Ctl bit asign -------------------------------------------------------- */
+-#define Rx_EnGood 0x00004000 /* 1:Enable Good */
+-#define Rx_EnRxPar 0x00002000 /* 1:Enable Receive Parity */
+-#define Rx_EnLongErr 0x00000800 /* 1:Enable Long Error */
+-#define Rx_EnOver 0x00000400 /* 1:Enable OverFlow */
+-#define Rx_EnCRCErr 0x00000200 /* 1:Enable CRC Error */
+-#define Rx_EnAlign 0x00000100 /* 1:Enable Alignment */
+-#define Rx_IgnoreCRC 0x00000040 /* 1:Ignore CRC Value */
+-#define Rx_StripCRC 0x00000010 /* 1:Strip CRC Value */
+-#define Rx_ShortEn 0x00000008 /* 1:Short Enable */
+-#define Rx_LongEn 0x00000004 /* 1:Long Enable */
+-#define Rx_RxHalt 0x00000002 /* 1:Receive Halt Request */
+-#define Rx_RxEn 0x00000001 /* 1:Receive Intrrupt Enable */
++#define Rx_EnGood 0x00004000 /* 1:Enable Good */
++#define Rx_EnRxPar 0x00002000 /* 1:Enable Receive Parity */
++#define Rx_EnLongErr 0x00000800 /* 1:Enable Long Error */
++#define Rx_EnOver 0x00000400 /* 1:Enable OverFlow */
++#define Rx_EnCRCErr 0x00000200 /* 1:Enable CRC Error */
++#define Rx_EnAlign 0x00000100 /* 1:Enable Alignment */
++#define Rx_IgnoreCRC 0x00000040 /* 1:Ignore CRC Value */
++#define Rx_StripCRC 0x00000010 /* 1:Strip CRC Value */
++#define Rx_ShortEn 0x00000008 /* 1:Short Enable */
++#define Rx_LongEn 0x00000004 /* 1:Long Enable */
++#define Rx_RxHalt 0x00000002 /* 1:Receive Halt Request */
++#define Rx_RxEn 0x00000001 /* 1:Receive Intrrupt Enable */
+
+ /* Rx_Stat bit asign ------------------------------------------------------- */
+-#define Rx_Halted 0x00008000 /* Rx Halted */
+-#define Rx_Good 0x00004000 /* Rx Good */
+-#define Rx_RxPar 0x00002000 /* Rx Parity Error */
+- /* 0x00001000 not use */
+-#define Rx_LongErr 0x00000800 /* Rx Long Error */
+-#define Rx_Over 0x00000400 /* Rx Overflow */
+-#define Rx_CRCErr 0x00000200 /* Rx CRC Error */
+-#define Rx_Align 0x00000100 /* Rx Alignment Error */
+-#define Rx_10Stat 0x00000080 /* Rx 10Mbps Status */
+-#define Rx_IntRx 0x00000040 /* Rx Interrupt */
+-#define Rx_CtlRecd 0x00000020 /* Rx Control Receive */
+-
+-#define Rx_Stat_Mask 0x0000EFC0 /* Rx All Status Mask */
++#define Rx_Halted 0x00008000 /* Rx Halted */
++#define Rx_Good 0x00004000 /* Rx Good */
++#define Rx_RxPar 0x00002000 /* Rx Parity Error */
++ /* 0x00001000 not use */
++#define Rx_LongErr 0x00000800 /* Rx Long Error */
++#define Rx_Over 0x00000400 /* Rx Overflow */
++#define Rx_CRCErr 0x00000200 /* Rx CRC Error */
++#define Rx_Align 0x00000100 /* Rx Alignment Error */
++#define Rx_10Stat 0x00000080 /* Rx 10Mbps Status */
++#define Rx_IntRx 0x00000040 /* Rx Interrupt */
++#define Rx_CtlRecd 0x00000020 /* Rx Control Receive */
++
++#define Rx_Stat_Mask 0x0000EFC0 /* Rx All Status Mask */
+
+ /* Int_En bit asign -------------------------------------------------------- */
+-#define Int_NRAbtEn 0x00000800 /* 1:Non-recoverable Abort Enable */
+-#define Int_TxCtlCmpEn 0x00000400 /* 1:Transmit Control Complete Enable */
+-#define Int_DmParErrEn 0x00000200 /* 1:DMA Parity Error Enable */
+-#define Int_DParDEn 0x00000100 /* 1:Data Parity Error Enable */
+-#define Int_EarNotEn 0x00000080 /* 1:Early Notify Enable */
+-#define Int_DParErrEn 0x00000040 /* 1:Detected Parity Error Enable */
+-#define Int_SSysErrEn 0x00000020 /* 1:Signalled System Error Enable */
+-#define Int_RMasAbtEn 0x00000010 /* 1:Received Master Abort Enable */
+-#define Int_RTargAbtEn 0x00000008 /* 1:Received Target Abort Enable */
+-#define Int_STargAbtEn 0x00000004 /* 1:Signalled Target Abort Enable */
+-#define Int_BLExEn 0x00000002 /* 1:Buffer List Exhausted Enable */
+-#define Int_FDAExEn 0x00000001 /* 1:Free Descriptor Area */
+- /* Exhausted Enable */
++#define Int_NRAbtEn 0x00000800 /* 1:Non-recoverable Abort Enable */
++#define Int_TxCtlCmpEn 0x00000400 /* 1:Transmit Ctl Complete Enable */
++#define Int_DmParErrEn 0x00000200 /* 1:DMA Parity Error Enable */
++#define Int_DParDEn 0x00000100 /* 1:Data Parity Error Enable */
++#define Int_EarNotEn 0x00000080 /* 1:Early Notify Enable */
++#define Int_DParErrEn 0x00000040 /* 1:Detected Parity Error Enable */
++#define Int_SSysErrEn 0x00000020 /* 1:Signalled System Error Enable */
++#define Int_RMasAbtEn 0x00000010 /* 1:Received Master Abort Enable */
++#define Int_RTargAbtEn 0x00000008 /* 1:Received Target Abort Enable */
++#define Int_STargAbtEn 0x00000004 /* 1:Signalled Target Abort Enable */
++#define Int_BLExEn 0x00000002 /* 1:Buffer List Exhausted Enable */
++#define Int_FDAExEn 0x00000001 /* 1:Free Descriptor Area */
++ /* Exhausted Enable */
+
+ /* Int_Src bit asign ------------------------------------------------------- */
+-#define Int_NRabt 0x00004000 /* 1:Non Recoverable error */
+-#define Int_DmParErrStat 0x00002000 /* 1:DMA Parity Error & Clear */
+-#define Int_BLEx 0x00001000 /* 1:Buffer List Empty & Clear */
+-#define Int_FDAEx 0x00000800 /* 1:FDA Empty & Clear */
+-#define Int_IntNRAbt 0x00000400 /* 1:Non Recoverable Abort */
+-#define Int_IntCmp 0x00000200 /* 1:MAC control packet complete */
+-#define Int_IntExBD 0x00000100 /* 1:Interrupt Extra BD & Clear */
+-#define Int_DmParErr 0x00000080 /* 1:DMA Parity Error & Clear */
+-#define Int_IntEarNot 0x00000040 /* 1:Receive Data write & Clear */
+-#define Int_SWInt 0x00000020 /* 1:Software request & Clear */
+-#define Int_IntBLEx 0x00000010 /* 1:Buffer List Empty & Clear */
+-#define Int_IntFDAEx 0x00000008 /* 1:FDA Empty & Clear */
+-#define Int_IntPCI 0x00000004 /* 1:PCI controller & Clear */
+-#define Int_IntMacRx 0x00000002 /* 1:Rx controller & Clear */
+-#define Int_IntMacTx 0x00000001 /* 1:Tx controller & Clear */
++#define Int_NRabt 0x00004000 /* 1:Non Recoverable error */
++#define Int_DmParErrStat 0x00002000 /* 1:DMA Parity Error & Clear */
++#define Int_BLEx 0x00001000 /* 1:Buffer List Empty & Clear */
++#define Int_FDAEx 0x00000800 /* 1:FDA Empty & Clear */
++#define Int_IntNRAbt 0x00000400 /* 1:Non Recoverable Abort */
++#define Int_IntCmp 0x00000200 /* 1:MAC control packet complete */
++#define Int_IntExBD 0x00000100 /* 1:Interrupt Extra BD & Clear */
++#define Int_DmParErr 0x00000080 /* 1:DMA Parity Error & Clear */
++#define Int_IntEarNot 0x00000040 /* 1:Receive Data write & Clear */
++#define Int_SWInt 0x00000020 /* 1:Software request & Clear */
++#define Int_IntBLEx 0x00000010 /* 1:Buffer List Empty & Clear */
++#define Int_IntFDAEx 0x00000008 /* 1:FDA Empty & Clear */
++#define Int_IntPCI 0x00000004 /* 1:PCI controller & Clear */
++#define Int_IntMacRx 0x00000002 /* 1:Rx controller & Clear */
++#define Int_IntMacTx 0x00000001 /* 1:Tx controller & Clear */
+
+ /* MD_CA bit asign --------------------------------------------------------- */
+-#define MD_CA_PreSup 0x00001000 /* 1:Preamble Supress */
+-#define MD_CA_Busy 0x00000800 /* 1:Busy (Start Operation) */
+-#define MD_CA_Wr 0x00000400 /* 1:Write 0:Read */
++#define MD_CA_PreSup 0x00001000 /* 1:Preamble Supress */
++#define MD_CA_Busy 0x00000800 /* 1:Busy (Start Operation) */
++#define MD_CA_Wr 0x00000400 /* 1:Write 0:Read */
+
+
+ /*
+@@ -307,24 +306,24 @@ struct BDesc {
+ #define FD_ALIGN 16
+
+ /* Frame Descripter bit asign ---------------------------------------------- */
+-#define FD_FDLength_MASK 0x0000FFFF /* Length MASK */
+-#define FD_BDCnt_MASK 0x001F0000 /* BD count MASK in FD */
+-#define FD_FrmOpt_MASK 0x7C000000 /* Frame option MASK */
++#define FD_FDLength_MASK 0x0000FFFF /* Length MASK */
++#define FD_BDCnt_MASK 0x001F0000 /* BD count MASK in FD */
++#define FD_FrmOpt_MASK 0x7C000000 /* Frame option MASK */
+ #define FD_FrmOpt_BigEndian 0x40000000 /* Tx/Rx */
+-#define FD_FrmOpt_IntTx 0x20000000 /* Tx only */
+-#define FD_FrmOpt_NoCRC 0x10000000 /* Tx only */
++#define FD_FrmOpt_IntTx 0x20000000 /* Tx only */
++#define FD_FrmOpt_NoCRC 0x10000000 /* Tx only */
+ #define FD_FrmOpt_NoPadding 0x08000000 /* Tx only */
+ #define FD_FrmOpt_Packing 0x04000000 /* Rx only */
+-#define FD_CownsFD 0x80000000 /* FD Controller owner bit */
+-#define FD_Next_EOL 0x00000001 /* FD EOL indicator */
+-#define FD_BDCnt_SHIFT 16
++#define FD_CownsFD 0x80000000 /* FD Controller owner bit */
++#define FD_Next_EOL 0x00000001 /* FD EOL indicator */
++#define FD_BDCnt_SHIFT 16
+
+ /* Buffer Descripter bit asign --------------------------------------------- */
+-#define BD_BuffLength_MASK 0x0000FFFF /* Recieve Data Size */
+-#define BD_RxBDID_MASK 0x00FF0000 /* BD ID Number MASK */
+-#define BD_RxBDSeqN_MASK 0x7F000000 /* Rx BD Sequence Number */
+-#define BD_CownsBD 0x80000000 /* BD Controller owner bit */
+-#define BD_RxBDID_SHIFT 16
++#define BD_BuffLength_MASK 0x0000FFFF /* Recieve Data Size */
++#define BD_RxBDID_MASK 0x00FF0000 /* BD ID Number MASK */
++#define BD_RxBDSeqN_MASK 0x7F000000 /* Rx BD Sequence Number */
++#define BD_CownsBD 0x80000000 /* BD Controller owner bit */
++#define BD_RxBDID_SHIFT 16
+ #define BD_RxBDSeqN_SHIFT 24
+
+
+@@ -348,13 +347,15 @@ struct BDesc {
+ Int_STargAbtEn | \
+ Int_BLExEn | Int_FDAExEn) /* maybe 0xb7f*/
+ #define DMA_CTL_CMD DMA_BURST_SIZE
+-#define HAVE_DMA_RXALIGN(lp) likely((lp)->boardtype != TC35815CF)
++#define HAVE_DMA_RXALIGN(lp) likely((lp)->chiptype != TC35815CF)
+
+ /* Tuning parameters */
+ #define DMA_BURST_SIZE 32
+ #define TX_THRESHOLD 1024
+-#define TX_THRESHOLD_MAX 1536 /* used threshold with packet max byte for low pci transfer ability.*/
+-#define TX_THRESHOLD_KEEP_LIMIT 10 /* setting threshold max value when overrun error occured this count. */
++/* used threshold with packet max byte for low pci transfer ability.*/
++#define TX_THRESHOLD_MAX 1536
++/* setting threshold max value when overrun error occured this count. */
++#define TX_THRESHOLD_KEEP_LIMIT 10
+
+ /* 16 + RX_BUF_NUM * 8 + RX_FD_NUM * 16 + TX_FD_NUM * 32 <= PAGE_SIZE*FD_PAGE_NUM */
+ #ifdef TC35815_USE_PACKEDBUFFER
+@@ -396,21 +397,12 @@ struct FrFD {
+ };
+
+
+-#define tc_readl(addr) readl(addr)
+-#define tc_writel(d, addr) writel(d, addr)
++#define tc_readl(addr) ioread32(addr)
++#define tc_writel(d, addr) iowrite32(d, addr)
+
+ #define TC35815_TX_TIMEOUT msecs_to_jiffies(400)
+
+-/* Timer state engine. */
+-enum tc35815_timer_state {
+- arbwait = 0, /* Waiting for auto negotiation to complete. */
+- lupwait = 1, /* Auto-neg complete, awaiting link-up status. */
+- ltrywait = 2, /* Forcing try of all modes, from fastest to slowest. */
+- asleep = 3, /* Time inactive. */
+- lcheck = 4, /* Check link status. */
+-};
+-
+-/* Information that need to be kept for each board. */
++/* Information that need to be kept for each controller. */
+ struct tc35815_local {
+ struct pci_dev *pci_dev;
+
+@@ -418,12 +410,11 @@ struct tc35815_local {
+ struct napi_struct napi;
+
+ /* statistics */
+- struct net_device_stats stats;
+ struct {
+ int max_tx_qlen;
+ int tx_ints;
+ int rx_ints;
+- int tx_underrun;
++ int tx_underrun;
+ } lstats;
+
+ /* Tx control lock. This protects the transmit buffer ring
+@@ -433,12 +424,12 @@ struct tc35815_local {
+ */
+ spinlock_t lock;
+
+- int phy_addr;
+- int fullduplex;
+- unsigned short saved_lpa;
+- struct timer_list timer;
+- enum tc35815_timer_state timer_state; /* State of auto-neg timer. */
+- unsigned int timer_ticks; /* Number of clicks at each state */
++ struct mii_bus mii_bus;
++ struct phy_device *phy_dev;
++ int duplex;
++ int speed;
++ int link;
++ struct work_struct restart_work;
+
+ /*
+ * Transmitting: Batch Mode.
+@@ -452,7 +443,7 @@ struct tc35815_local {
+ * RX_BUF_NUM BD in Free Buffer FD.
+ * One Free Buffer BD has ETH_FRAME_LEN data buffer.
+ */
+- void * fd_buf; /* for TxFD, RxFD, FrFD */
++ void *fd_buf; /* for TxFD, RxFD, FrFD */
+ dma_addr_t fd_buf_dma;
+ struct TxFD *tfd_base;
+ unsigned int tfd_start;
+@@ -463,7 +454,7 @@ struct tc35815_local {
+ struct FrFD *fbl_ptr;
+ #ifdef TC35815_USE_PACKEDBUFFER
+ unsigned char fbl_curid;
+- void * data_buf[RX_BUF_NUM]; /* packing */
++ void *data_buf[RX_BUF_NUM]; /* packing */
+ dma_addr_t data_buf_dma[RX_BUF_NUM];
+ struct {
+ struct sk_buff *skb;
+@@ -476,10 +467,8 @@ struct tc35815_local {
+ dma_addr_t skb_dma;
+ } tx_skbs[TX_FD_NUM], rx_skbs[RX_BUF_NUM];
+ #endif
+- struct mii_if_info mii;
+- unsigned short mii_id[2];
+ u32 msg_enable;
+- board_t boardtype;
++ enum tc35815_chiptype chiptype;
+ };
+
+ static inline dma_addr_t fd_virt_to_bus(struct tc35815_local *lp, void *virt)
+@@ -506,13 +495,14 @@ static inline void *rxbuf_bus_to_virt(struct tc35815_local *lp, dma_addr_t bus)
+ }
+
+ #define TC35815_DMA_SYNC_ONDEMAND
+-static void* alloc_rxbuf_page(struct pci_dev *hwdev, dma_addr_t *dma_handle)
++static void *alloc_rxbuf_page(struct pci_dev *hwdev, dma_addr_t *dma_handle)
+ {
+ #ifdef TC35815_DMA_SYNC_ONDEMAND
+ void *buf;
+ /* pci_map + pci_dma_sync will be more effective than
+ * pci_alloc_consistent on some archs. */
+- if ((buf = (void *)__get_free_page(GFP_ATOMIC)) == NULL)
++ buf = (void *)__get_free_page(GFP_ATOMIC);
++ if (!buf)
+ return NULL;
+ *dma_handle = pci_map_single(hwdev, buf, PAGE_SIZE,
+ PCI_DMA_FROMDEVICE);
+@@ -577,7 +567,7 @@ static void tc35815_txdone(struct net_device *dev);
+ static int tc35815_close(struct net_device *dev);
+ static struct net_device_stats *tc35815_get_stats(struct net_device *dev);
+ static void tc35815_set_multicast_list(struct net_device *dev);
+-static void tc35815_tx_timeout(struct net_device *dev);
++static void tc35815_tx_timeout(struct net_device *dev);
+ static int tc35815_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+ static void tc35815_poll_controller(struct net_device *dev);
+@@ -585,21 +575,225 @@ static void tc35815_poll_controller(struct net_device *dev);
+ static const struct ethtool_ops tc35815_ethtool_ops;
+
+ /* Example routines you must write ;->. */
+-static void tc35815_chip_reset(struct net_device *dev);
+-static void tc35815_chip_init(struct net_device *dev);
+-static void tc35815_find_phy(struct net_device *dev);
+-static void tc35815_phy_chip_init(struct net_device *dev);
++static void tc35815_chip_reset(struct net_device *dev);
++static void tc35815_chip_init(struct net_device *dev);
+
+ #ifdef DEBUG
+ static void panic_queues(struct net_device *dev);
+ #endif
+
+-static void tc35815_timer(unsigned long data);
+-static void tc35815_start_auto_negotiation(struct net_device *dev,
+- struct ethtool_cmd *ep);
+-static int tc_mdio_read(struct net_device *dev, int phy_id, int location);
+-static void tc_mdio_write(struct net_device *dev, int phy_id, int location,
+- int val);
++static void tc35815_restart_work(struct work_struct *work);
++
++static int tc_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
++{
++ struct net_device *dev = bus->priv;
++ struct tc35815_regs __iomem *tr =
++ (struct tc35815_regs __iomem *)dev->base_addr;
++ unsigned long timeout = jiffies + 10;
++
++ tc_writel(MD_CA_Busy | (mii_id << 5) | (regnum & 0x1f), &tr->MD_CA);
++ while (tc_readl(&tr->MD_CA) & MD_CA_Busy) {
++ if (time_after(jiffies, timeout))
++ return -EIO;
++ cpu_relax();
++ }
++ return tc_readl(&tr->MD_Data) & 0xffff;
++}
++
++static int tc_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 val)
++{
++ struct net_device *dev = bus->priv;
++ struct tc35815_regs __iomem *tr =
++ (struct tc35815_regs __iomem *)dev->base_addr;
++ unsigned long timeout = jiffies + 10;
++
++ tc_writel(val, &tr->MD_Data);
++ tc_writel(MD_CA_Busy | MD_CA_Wr | (mii_id << 5) | (regnum & 0x1f),
++ &tr->MD_CA);
++ while (tc_readl(&tr->MD_CA) & MD_CA_Busy) {
++ if (time_after(jiffies, timeout))
++ return -EIO;
++ cpu_relax();
++ }
++ return 0;
++}
++
++static void tc_handle_link_change(struct net_device *dev)
++{
++ struct tc35815_local *lp = netdev_priv(dev);
++ struct phy_device *phydev = lp->phy_dev;
++ unsigned long flags;
++ int status_change = 0;
++
++ spin_lock_irqsave(&lp->lock, flags);
++ if (phydev->link &&
++ (lp->speed != phydev->speed || lp->duplex != phydev->duplex)) {
++ struct tc35815_regs __iomem *tr =
++ (struct tc35815_regs __iomem *)dev->base_addr;
++ u32 reg;
++
++ reg = tc_readl(&tr->MAC_Ctl);
++ reg |= MAC_HaltReq;
++ tc_writel(reg, &tr->MAC_Ctl);
++ if (phydev->duplex == DUPLEX_FULL)
++ reg |= MAC_FullDup;
++ else
++ reg &= ~MAC_FullDup;
++ tc_writel(reg, &tr->MAC_Ctl);
++ reg &= ~MAC_HaltReq;
++ tc_writel(reg, &tr->MAC_Ctl);
++
++ /*
++ * TX4939 PCFG.SPEEDn bit will be changed on
++ * NETDEV_CHANGE event.
++ */
++
++#if !defined(NO_CHECK_CARRIER) && defined(WORKAROUND_LOSTCAR)
++ /*
++ * WORKAROUND: enable LostCrS only if half duplex
++ * operation.
++ * (TX4939 does not have EnLCarr)
++ */
++ if (phydev->duplex == DUPLEX_HALF &&
++ lp->chiptype != TC35815_TX4939)
++ tc_writel(tc_readl(&tr->Tx_Ctl) | Tx_EnLCarr,
++ &tr->Tx_Ctl);
++#endif
++
++ lp->speed = phydev->speed;
++ lp->duplex = phydev->duplex;
++ status_change = 1;
++ }
++
++ if (phydev->link != lp->link) {
++ if (phydev->link) {
++#ifdef WORKAROUND_100HALF_PROMISC
++ /* delayed promiscuous enabling */
++ if (dev->flags & IFF_PROMISC)
++ tc35815_set_multicast_list(dev);
++#endif
++ netif_schedule(dev);
++ } else {
++ lp->speed = 0;
++ lp->duplex = -1;
++ }
++ lp->link = phydev->link;
++
++ status_change = 1;
++ }
++ spin_unlock_irqrestore(&lp->lock, flags);
++
++ if (status_change && netif_msg_link(lp)) {
++ phy_print_status(phydev);
++#ifdef DEBUG
++ printk(KERN_DEBUG
++ "%s: MII BMCR %04x BMSR %04x LPA %04x\n",
++ dev->name,
++ phy_read(phydev, MII_BMCR),
++ phy_read(phydev, MII_BMSR),
++ phy_read(phydev, MII_LPA));
++#endif
++ }
++}
++
++static int tc_mii_probe(struct net_device *dev)
++{
++ struct tc35815_local *lp = netdev_priv(dev);
++ struct phy_device *phydev = NULL;
++ int phy_addr;
++ u32 dropmask;
++
++ /* find the first phy */
++ for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
++ if (lp->mii_bus.phy_map[phy_addr]) {
++ if (phydev) {
++ printk(KERN_ERR "%s: multiple PHYs found\n",
++ dev->name);
++ return -EINVAL;
++ }
++ phydev = lp->mii_bus.phy_map[phy_addr];
++ break;
++ }
++ }
++
++ if (!phydev) {
++ printk(KERN_ERR "%s: no PHY found\n", dev->name);
++ return -ENODEV;
++ }
++
++ /* attach the mac to the phy */
++ phydev = phy_connect(dev, phydev->dev.bus_id,
++ &tc_handle_link_change, 0,
++ lp->chiptype == TC35815_TX4939 ?
++ PHY_INTERFACE_MODE_RMII : PHY_INTERFACE_MODE_MII);
++ if (IS_ERR(phydev)) {
++ printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
++ return PTR_ERR(phydev);
++ }
++ printk(KERN_INFO "%s: attached PHY driver [%s] "
++ "(mii_bus:phy_addr=%s, id=%x)\n",
++ dev->name, phydev->drv->name, phydev->dev.bus_id,
++ phydev->phy_id);
++
++ /* mask with MAC supported features */
++ phydev->supported &= PHY_BASIC_FEATURES;
++ dropmask = 0;
++ if (options.speed == 10)
++ dropmask |= SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full;
++ else if (options.speed == 100)
++ dropmask |= SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full;
++ if (options.duplex == 1)
++ dropmask |= SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Full;
++ else if (options.duplex == 2)
++ dropmask |= SUPPORTED_10baseT_Half | SUPPORTED_100baseT_Half;
++ phydev->supported &= ~dropmask;
++ phydev->advertising = phydev->supported;
++
++ lp->link = 0;
++ lp->speed = 0;
++ lp->duplex = -1;
++ lp->phy_dev = phydev;
++
++ return 0;
++}
++
++static int tc_mii_init(struct net_device *dev)
++{
++ struct tc35815_local *lp = netdev_priv(dev);
++ int err;
++ int i;
++
++ lp->mii_bus.name = "tc35815_mii_bus";
++ lp->mii_bus.read = tc_mdio_read;
++ lp->mii_bus.write = tc_mdio_write;
++ snprintf(lp->mii_bus.id, MII_BUS_ID_SIZE, "%x",
++ (lp->pci_dev->bus->number << 8) | lp->pci_dev->devfn);
++ lp->mii_bus.priv = dev;
++ lp->mii_bus.dev = &lp->pci_dev->dev;
++ lp->mii_bus.irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
++ if (!lp->mii_bus.irq) {
++ err = -ENOMEM;
++ goto err_out;
++ }
++
++ for (i = 0; i < PHY_MAX_ADDR; i++)
++ lp->mii_bus.irq[i] = PHY_POLL;
++
++ err = mdiobus_register(&lp->mii_bus);
++ if (err)
++ goto err_out_free_mdio_irq;
++ err = tc_mii_probe(dev);
++ if (err)
++ goto err_out_unregister_bus;
++ return 0;
++
++err_out_unregister_bus:
++ mdiobus_unregister(&lp->mii_bus);
++err_out_free_mdio_irq:
++ kfree(lp->mii_bus.irq);
++err_out:
++ return err;
++}
+
+ #ifdef CONFIG_CPU_TX49XX
+ /*
+@@ -617,7 +811,7 @@ static int __devinit tc35815_mac_match(struct device *dev, void *data)
+
+ static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev)
+ {
+- struct tc35815_local *lp = dev->priv;
++ struct tc35815_local *lp = netdev_priv(dev);
+ struct device *pd = bus_find_device(&platform_bus_type, NULL,
+ lp->pci_dev, tc35815_mac_match);
+ if (pd) {
+@@ -635,7 +829,7 @@ static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev)
+ }
+ #endif
+
+-static int __devinit tc35815_init_dev_addr (struct net_device *dev)
++static int __devinit tc35815_init_dev_addr(struct net_device *dev)
+ {
+ struct tc35815_regs __iomem *tr =
+ (struct tc35815_regs __iomem *)dev->base_addr;
+@@ -657,21 +851,21 @@ static int __devinit tc35815_init_dev_addr (struct net_device *dev)
+ return 0;
+ }
+
+-static int __devinit tc35815_init_one (struct pci_dev *pdev,
+- const struct pci_device_id *ent)
++static int __devinit tc35815_init_one(struct pci_dev *pdev,
++ const struct pci_device_id *ent)
+ {
+ void __iomem *ioaddr = NULL;
+ struct net_device *dev;
+ struct tc35815_local *lp;
+ int rc;
+- unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;
++ DECLARE_MAC_BUF(mac);
+
+ static int printed_version;
+ if (!printed_version++) {
+ printk(version);
+ dev_printk(KERN_DEBUG, &pdev->dev,
+- "speed:%d duplex:%d doforce:%d\n",
+- options.speed, options.duplex, options.doforce);
++ "speed:%d duplex:%d\n",
++ options.speed, options.duplex);
+ }
+
+ if (!pdev->irq) {
+@@ -680,55 +874,24 @@ static int __devinit tc35815_init_one (struct pci_dev *pdev,
+ }
+
+ /* dev zeroed in alloc_etherdev */
+- dev = alloc_etherdev (sizeof (*lp));
++ dev = alloc_etherdev(sizeof(*lp));
+ if (dev == NULL) {
+ dev_err(&pdev->dev, "unable to alloc new ethernet\n");
+ return -ENOMEM;
+ }
+ SET_NETDEV_DEV(dev, &pdev->dev);
+- lp = dev->priv;
++ lp = netdev_priv(dev);
+ lp->dev = dev;
+
+ /* enable device (incl. PCI PM wakeup), and bus-mastering */
+- rc = pci_enable_device (pdev);
++ rc = pcim_enable_device(pdev);
+ if (rc)
+ goto err_out;
+-
+- mmio_start = pci_resource_start (pdev, 1);
+- mmio_end = pci_resource_end (pdev, 1);
+- mmio_flags = pci_resource_flags (pdev, 1);
+- mmio_len = pci_resource_len (pdev, 1);
+-
+- /* set this immediately, we need to know before
+- * we talk to the chip directly */
+-
+- /* make sure PCI base addr 1 is MMIO */
+- if (!(mmio_flags & IORESOURCE_MEM)) {
+- dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n");
+- rc = -ENODEV;
+- goto err_out;
+- }
+-
+- /* check for weird/broken PCI region reporting */
+- if ((mmio_len < sizeof(struct tc35815_regs))) {
+- dev_err(&pdev->dev, "Invalid PCI region size(s), aborting\n");
+- rc = -ENODEV;
+- goto err_out;
+- }
+-
+- rc = pci_request_regions (pdev, MODNAME);
++ rc = pcim_iomap_regions(pdev, 1 << 1, MODNAME);
+ if (rc)
+ goto err_out;
+-
+- pci_set_master (pdev);
+-
+- /* ioremap MMIO region */
+- ioaddr = ioremap (mmio_start, mmio_len);
+- if (ioaddr == NULL) {
+- dev_err(&pdev->dev, "cannot remap MMIO, aborting\n");
+- rc = -EIO;
+- goto err_out_free_res;
+- }
++ pci_set_master(pdev);
++ ioaddr = pcim_iomap_table(pdev)[1];
+
+ /* Initialize the device structure. */
+ dev->open = tc35815_open;
+@@ -748,11 +911,12 @@ static int __devinit tc35815_init_one (struct pci_dev *pdev,
+ #endif
+
+ dev->irq = pdev->irq;
+- dev->base_addr = (unsigned long) ioaddr;
++ dev->base_addr = (unsigned long)ioaddr;
+
++ INIT_WORK(&lp->restart_work, tc35815_restart_work);
+ spin_lock_init(&lp->lock);
+ lp->pci_dev = pdev;
+- lp->boardtype = ent->driver_data;
++ lp->chiptype = ent->driver_data;
+
+ lp->msg_enable = NETIF_MSG_TX_ERR | NETIF_MSG_HW | NETIF_MSG_DRV | NETIF_MSG_LINK;
+ pci_set_drvdata(pdev, dev);
+@@ -766,68 +930,49 @@ static int __devinit tc35815_init_one (struct pci_dev *pdev,
+ random_ether_addr(dev->dev_addr);
+ }
+
+- rc = register_netdev (dev);
++ rc = register_netdev(dev);
+ if (rc)
+- goto err_out_unmap;
++ goto err_out;
+
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+- printk(KERN_INFO "%s: %s at 0x%lx, "
+- "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
+- "IRQ %d\n",
++ printk(KERN_INFO "%s: %s at 0x%lx, %s, IRQ %d\n",
+ dev->name,
+- board_info[ent->driver_data].name,
++ chip_info[ent->driver_data].name,
+ dev->base_addr,
+- dev->dev_addr[0], dev->dev_addr[1],
+- dev->dev_addr[2], dev->dev_addr[3],
+- dev->dev_addr[4], dev->dev_addr[5],
++ print_mac(mac, dev->dev_addr),
+ dev->irq);
+
+- setup_timer(&lp->timer, tc35815_timer, (unsigned long) dev);
+- lp->mii.dev = dev;
+- lp->mii.mdio_read = tc_mdio_read;
+- lp->mii.mdio_write = tc_mdio_write;
+- lp->mii.phy_id_mask = 0x1f;
+- lp->mii.reg_num_mask = 0x1f;
+- tc35815_find_phy(dev);
+- lp->mii.phy_id = lp->phy_addr;
+- lp->mii.full_duplex = 0;
+- lp->mii.force_media = 0;
++ rc = tc_mii_init(dev);
++ if (rc)
++ goto err_out_unregister;
+
+ return 0;
+
+-err_out_unmap:
+- iounmap(ioaddr);
+-err_out_free_res:
+- pci_release_regions (pdev);
++err_out_unregister:
++ unregister_netdev(dev);
+ err_out:
+- free_netdev (dev);
++ free_netdev(dev);
+ return rc;
+ }
+
+
+-static void __devexit tc35815_remove_one (struct pci_dev *pdev)
++static void __devexit tc35815_remove_one(struct pci_dev *pdev)
+ {
+- struct net_device *dev = pci_get_drvdata (pdev);
+- unsigned long mmio_addr;
+-
+- mmio_addr = dev->base_addr;
+-
+- unregister_netdev (dev);
+-
+- if (mmio_addr) {
+- iounmap ((void __iomem *)mmio_addr);
+- pci_release_regions (pdev);
+- }
+-
+- free_netdev (dev);
++ struct net_device *dev = pci_get_drvdata(pdev);
++ struct tc35815_local *lp = netdev_priv(dev);
+
+- pci_set_drvdata (pdev, NULL);
++ phy_disconnect(lp->phy_dev);
++ mdiobus_unregister(&lp->mii_bus);
++ kfree(lp->mii_bus.irq);
++ unregister_netdev(dev);
++ free_netdev(dev);
++ pci_set_drvdata(pdev, NULL);
+ }
+
+ static int
+ tc35815_init_queues(struct net_device *dev)
+ {
+- struct tc35815_local *lp = dev->priv;
++ struct tc35815_local *lp = netdev_priv(dev);
+ int i;
+ unsigned long fd_addr;
+
+@@ -838,11 +983,17 @@ tc35815_init_queues(struct net_device *dev)
+ sizeof(struct TxFD) * TX_FD_NUM >
+ PAGE_SIZE * FD_PAGE_NUM);
+
+- if ((lp->fd_buf = pci_alloc_consistent(lp->pci_dev, PAGE_SIZE * FD_PAGE_NUM, &lp->fd_buf_dma)) == 0)
++ lp->fd_buf = pci_alloc_consistent(lp->pci_dev,
++ PAGE_SIZE * FD_PAGE_NUM,
++ &lp->fd_buf_dma);
++ if (!lp->fd_buf)
+ return -ENOMEM;
+ for (i = 0; i < RX_BUF_NUM; i++) {
+ #ifdef TC35815_USE_PACKEDBUFFER
+- if ((lp->data_buf[i] = alloc_rxbuf_page(lp->pci_dev, &lp->data_buf_dma[i])) == NULL) {
++ lp->data_buf[i] =
++ alloc_rxbuf_page(lp->pci_dev,
++ &lp->data_buf_dma[i]);
++ if (!lp->data_buf[i]) {
+ while (--i >= 0) {
+ free_rxbuf_page(lp->pci_dev,
+ lp->data_buf[i],
+@@ -885,18 +1036,17 @@ tc35815_init_queues(struct net_device *dev)
+ #endif
+ printk("\n");
+ } else {
+- for (i = 0; i < FD_PAGE_NUM; i++) {
+- clear_page((void *)((unsigned long)lp->fd_buf + i * PAGE_SIZE));
+- }
++ for (i = 0; i < FD_PAGE_NUM; i++)
++ clear_page((void *)((unsigned long)lp->fd_buf +
++ i * PAGE_SIZE));
+ }
+ fd_addr = (unsigned long)lp->fd_buf;
+
+ /* Free Descriptors (for Receive) */
+ lp->rfd_base = (struct RxFD *)fd_addr;
+ fd_addr += sizeof(struct RxFD) * RX_FD_NUM;
+- for (i = 0; i < RX_FD_NUM; i++) {
++ for (i = 0; i < RX_FD_NUM; i++)
+ lp->rfd_base[i].fd.FDCtl = cpu_to_le32(FD_CownsFD);
+- }
+ lp->rfd_cur = lp->rfd_base;
+ lp->rfd_limit = (struct RxFD *)fd_addr - (RX_FD_RESERVE + 1);
+
+@@ -964,7 +1114,7 @@ tc35815_init_queues(struct net_device *dev)
+ static void
+ tc35815_clear_queues(struct net_device *dev)
+ {
+- struct tc35815_local *lp = dev->priv;
++ struct tc35815_local *lp = netdev_priv(dev);
+ int i;
+
+ for (i = 0; i < TX_FD_NUM; i++) {
+@@ -995,7 +1145,7 @@ tc35815_clear_queues(struct net_device *dev)
+ static void
+ tc35815_free_queues(struct net_device *dev)
+ {
+- struct tc35815_local *lp = dev->priv;
++ struct tc35815_local *lp = netdev_priv(dev);
+ int i;
+
+ if (lp->tfd_base) {
+@@ -1076,7 +1226,7 @@ dump_rxfd(struct RxFD *fd)
+ le32_to_cpu(fd->fd.FDStat),
+ le32_to_cpu(fd->fd.FDCtl));
+ if (le32_to_cpu(fd->fd.FDCtl) & FD_CownsFD)
+- return 0;
++ return 0;
+ printk("BD: ");
+ for (i = 0; i < bd_count; i++)
+ printk(" %08x %08x",
+@@ -1109,7 +1259,7 @@ dump_frfd(struct FrFD *fd)
+ static void
+ panic_queues(struct net_device *dev)
+ {
+- struct tc35815_local *lp = dev->priv;
++ struct tc35815_local *lp = netdev_priv(dev);
+ int i;
+
+ printk("TxFD base %p, start %u, end %u\n",
+@@ -1128,42 +1278,33 @@ panic_queues(struct net_device *dev)
+ }
+ #endif
+
+-static void print_eth(char *add)
++static void print_eth(const u8 *add)
+ {
+- int i;
++ DECLARE_MAC_BUF(mac);
+
+- printk("print_eth(%p)\n", add);
+- for (i = 0; i < 6; i++)
+- printk(" %2.2X", (unsigned char) add[i + 6]);
+- printk(" =>");
+- for (i = 0; i < 6; i++)
+- printk(" %2.2X", (unsigned char) add[i]);
+- printk(" : %2.2X%2.2X\n", (unsigned char) add[12], (unsigned char) add[13]);
++ printk(KERN_DEBUG "print_eth(%p)\n", add);
++ printk(KERN_DEBUG " %s =>", print_mac(mac, add + 6));
++ printk(KERN_CONT " %s : %02x%02x\n",
++ print_mac(mac, add), add[12], add[13]);
+ }
+
+ static int tc35815_tx_full(struct net_device *dev)
+ {
+- struct tc35815_local *lp = dev->priv;
++ struct tc35815_local *lp = netdev_priv(dev);
+ return ((lp->tfd_start + 1) % TX_FD_NUM == lp->tfd_end);
+ }
+
+ static void tc35815_restart(struct net_device *dev)
+ {
+- struct tc35815_local *lp = dev->priv;
+- int pid = lp->phy_addr;
+- int do_phy_reset = 1;
+- del_timer(&lp->timer); /* Kill if running */
+-
+- if (lp->mii_id[0] == 0x0016 && (lp->mii_id[1] & 0xfc00) == 0xf800) {
+- /* Resetting PHY cause problem on some chip... (SEEQ 80221) */
+- do_phy_reset = 0;
+- }
+- if (do_phy_reset) {
++ struct tc35815_local *lp = netdev_priv(dev);
++
++ if (lp->phy_dev) {
+ int timeout;
+- tc_mdio_write(dev, pid, MII_BMCR, BMCR_RESET);
++
++ phy_write(lp->phy_dev, MII_BMCR, BMCR_RESET);
+ timeout = 100;
+ while (--timeout) {
+- if (!(tc_mdio_read(dev, pid, MII_BMCR) & BMCR_RESET))
++ if (!(phy_read(lp->phy_dev, MII_BMCR) & BMCR_RESET))
+ break;
+ udelay(1);
+ }
+@@ -1171,16 +1312,40 @@ static void tc35815_restart(struct net_device *dev)
+ printk(KERN_ERR "%s: BMCR reset failed.\n", dev->name);
+ }
+
++ spin_lock_irq(&lp->lock);
+ tc35815_chip_reset(dev);
+ tc35815_clear_queues(dev);
+ tc35815_chip_init(dev);
+ /* Reconfigure CAM again since tc35815_chip_init() initialize it. */
+ tc35815_set_multicast_list(dev);
++ spin_unlock_irq(&lp->lock);
++
++ netif_wake_queue(dev);
++}
++
++static void tc35815_restart_work(struct work_struct *work)
++{
++ struct tc35815_local *lp =
++ container_of(work, struct tc35815_local, restart_work);
++ struct net_device *dev = lp->dev;
++
++ tc35815_restart(dev);
++}
++
++static void tc35815_schedule_restart(struct net_device *dev)
++{
++ struct tc35815_local *lp = netdev_priv(dev);
++ struct tc35815_regs __iomem *tr =
++ (struct tc35815_regs __iomem *)dev->base_addr;
++
++ /* disable interrupts */
++ tc_writel(0, &tr->Int_En);
++ tc_writel(tc_readl(&tr->DMA_Ctl) | DMA_IntMask, &tr->DMA_Ctl);
++ schedule_work(&lp->restart_work);
+ }
+
+ static void tc35815_tx_timeout(struct net_device *dev)
+ {
+- struct tc35815_local *lp = dev->priv;
+ struct tc35815_regs __iomem *tr =
+ (struct tc35815_regs __iomem *)dev->base_addr;
+
+@@ -1188,28 +1353,12 @@ static void tc35815_tx_timeout(struct net_device *dev)
+ dev->name, tc_readl(&tr->Tx_Stat));
+
+ /* Try to restart the adaptor. */
+- spin_lock_irq(&lp->lock);
+- tc35815_restart(dev);
+- spin_unlock_irq(&lp->lock);
+-
+- lp->stats.tx_errors++;
+-
+- /* If we have space available to accept new transmit
+- * requests, wake up the queueing layer. This would
+- * be the case if the chipset_init() call above just
+- * flushes out the tx queue and empties it.
+- *
+- * If instead, the tx queue is retained then the
+- * netif_wake_queue() call should be placed in the
+- * TX completion interrupt handler of the driver instead
+- * of here.
+- */
+- if (!tc35815_tx_full(dev))
+- netif_wake_queue(dev);
++ tc35815_schedule_restart(dev);
++ dev->stats.tx_errors++;
+ }
+
+ /*
+- * Open/initialize the board. This is called (in the current kernel)
++ * Open/initialize the controller. This is called (in the current kernel)
+ * sometime after booting when the 'ifconfig' program is run.
+ *
+ * This routine should set everything up anew at each open, even
+@@ -1219,17 +1368,16 @@ static void tc35815_tx_timeout(struct net_device *dev)
+ static int
+ tc35815_open(struct net_device *dev)
+ {
+- struct tc35815_local *lp = dev->priv;
++ struct tc35815_local *lp = netdev_priv(dev);
+
+ /*
+ * This is used if the interrupt line can turned off (shared).
+ * See 3c503.c for an example of selecting the IRQ at config-time.
+ */
+- if (request_irq(dev->irq, &tc35815_interrupt, IRQF_SHARED, dev->name, dev)) {
++ if (request_irq(dev->irq, &tc35815_interrupt, IRQF_SHARED,
++ dev->name, dev))
+ return -EAGAIN;
+- }
+
+- del_timer(&lp->timer); /* Kill if running */
+ tc35815_chip_reset(dev);
+
+ if (tc35815_init_queues(dev) != 0) {
+@@ -1246,6 +1394,9 @@ tc35815_open(struct net_device *dev)
+ tc35815_chip_init(dev);
+ spin_unlock_irq(&lp->lock);
+
++ /* schedule a link state check */
++ phy_start(lp->phy_dev);
++
+ /* We are now ready to accept transmit requeusts from
+ * the queueing layer of the networking.
+ */
+@@ -1261,7 +1412,7 @@ tc35815_open(struct net_device *dev)
+ */
+ static int tc35815_send_packet(struct sk_buff *skb, struct net_device *dev)
+ {
+- struct tc35815_local *lp = dev->priv;
++ struct tc35815_local *lp = netdev_priv(dev);
+ struct TxFD *txfd;
+ unsigned long flags;
+
+@@ -1366,7 +1517,7 @@ static void tc35815_fatal_error_interrupt(struct net_device *dev, u32 status)
+ panic("%s: Too many fatal errors.", dev->name);
+ printk(KERN_WARNING "%s: Resetting ...\n", dev->name);
+ /* Try to restart the adaptor. */
+- tc35815_restart(dev);
++ tc35815_schedule_restart(dev);
+ }
+
+ #ifdef TC35815_NAPI
+@@ -1375,7 +1526,7 @@ static int tc35815_do_interrupt(struct net_device *dev, u32 status, int limit)
+ static int tc35815_do_interrupt(struct net_device *dev, u32 status)
+ #endif
+ {
+- struct tc35815_local *lp = dev->priv;
++ struct tc35815_local *lp = netdev_priv(dev);
+ struct tc35815_regs __iomem *tr =
+ (struct tc35815_regs __iomem *)dev->base_addr;
+ int ret = -1;
+@@ -1392,7 +1543,7 @@ static int tc35815_do_interrupt(struct net_device *dev, u32 status)
+ printk(KERN_WARNING
+ "%s: Free Descriptor Area Exhausted (%#x).\n",
+ dev->name, status);
+- lp->stats.rx_dropped++;
++ dev->stats.rx_dropped++;
+ ret = 0;
+ }
+ if (status & Int_IntBLEx) {
+@@ -1401,14 +1552,14 @@ static int tc35815_do_interrupt(struct net_device *dev, u32 status)
+ printk(KERN_WARNING
+ "%s: Buffer List Exhausted (%#x).\n",
+ dev->name, status);
+- lp->stats.rx_dropped++;
++ dev->stats.rx_dropped++;
+ ret = 0;
+ }
+ if (status & Int_IntExBD) {
+ printk(KERN_WARNING
+ "%s: Excessive Buffer Descriptiors (%#x).\n",
+ dev->name, status);
+- lp->stats.rx_length_errors++;
++ dev->stats.rx_length_errors++;
+ ret = 0;
+ }
+
+@@ -1492,7 +1643,7 @@ static void
+ tc35815_rx(struct net_device *dev)
+ #endif
+ {
+- struct tc35815_local *lp = dev->priv;
++ struct tc35815_local *lp = netdev_priv(dev);
+ unsigned int fdctl;
+ int i;
+ int buf_free_count = 0;
+@@ -1532,7 +1683,7 @@ tc35815_rx(struct net_device *dev)
+ if (skb == NULL) {
+ printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",
+ dev->name);
+- lp->stats.rx_dropped++;
++ dev->stats.rx_dropped++;
+ break;
+ }
+ skb_reserve(skb, 2); /* 16 bit alignment */
+@@ -1602,10 +1753,10 @@ tc35815_rx(struct net_device *dev)
+ netif_rx(skb);
+ #endif
+ dev->last_rx = jiffies;
+- lp->stats.rx_packets++;
+- lp->stats.rx_bytes += pkt_len;
++ dev->stats.rx_packets++;
++ dev->stats.rx_bytes += pkt_len;
+ } else {
+- lp->stats.rx_errors++;
++ dev->stats.rx_errors++;
+ printk(KERN_DEBUG "%s: Rx error (status %x)\n",
+ dev->name, status & Rx_Stat_Mask);
+ /* WORKAROUND: LongErr and CRCErr means Overflow. */
+@@ -1613,10 +1764,14 @@ tc35815_rx(struct net_device *dev)
+ status &= ~(Rx_LongErr|Rx_CRCErr);
+ status |= Rx_Over;
+ }
+- if (status & Rx_LongErr) lp->stats.rx_length_errors++;
+- if (status & Rx_Over) lp->stats.rx_fifo_errors++;
+- if (status & Rx_CRCErr) lp->stats.rx_crc_errors++;
+- if (status & Rx_Align) lp->stats.rx_frame_errors++;
++ if (status & Rx_LongErr)
++ dev->stats.rx_length_errors++;
++ if (status & Rx_Over)
++ dev->stats.rx_fifo_errors++;
++ if (status & Rx_CRCErr)
++ dev->stats.rx_crc_errors++;
++ if (status & Rx_Align)
++ dev->stats.rx_frame_errors++;
+ }
+
+ if (bd_count > 0) {
+@@ -1772,40 +1927,39 @@ static int tc35815_poll(struct napi_struct *napi, int budget)
+ static void
+ tc35815_check_tx_stat(struct net_device *dev, int status)
+ {
+- struct tc35815_local *lp = dev->priv;
++ struct tc35815_local *lp = netdev_priv(dev);
+ const char *msg = NULL;
+
+ /* count collisions */
+ if (status & Tx_ExColl)
+- lp->stats.collisions += 16;
++ dev->stats.collisions += 16;
+ if (status & Tx_TxColl_MASK)
+- lp->stats.collisions += status & Tx_TxColl_MASK;
++ dev->stats.collisions += status & Tx_TxColl_MASK;
+
+ #ifndef NO_CHECK_CARRIER
+ /* TX4939 does not have NCarr */
+- if (lp->boardtype == TC35815_TX4939)
++ if (lp->chiptype == TC35815_TX4939)
+ status &= ~Tx_NCarr;
+ #ifdef WORKAROUND_LOSTCAR
+ /* WORKAROUND: ignore LostCrS in full duplex operation */
+- if ((lp->timer_state != asleep && lp->timer_state != lcheck)
+- || lp->fullduplex)
++ if (!lp->link || lp->duplex == DUPLEX_FULL)
+ status &= ~Tx_NCarr;
+ #endif
+ #endif
+
+ if (!(status & TX_STA_ERR)) {
+ /* no error. */
+- lp->stats.tx_packets++;
++ dev->stats.tx_packets++;
+ return;
+ }
+
+- lp->stats.tx_errors++;
++ dev->stats.tx_errors++;
+ if (status & Tx_ExColl) {
+- lp->stats.tx_aborted_errors++;
++ dev->stats.tx_aborted_errors++;
+ msg = "Excessive Collision.";
+ }
+ if (status & Tx_Under) {
+- lp->stats.tx_fifo_errors++;
++ dev->stats.tx_fifo_errors++;
+ msg = "Tx FIFO Underrun.";
+ if (lp->lstats.tx_underrun < TX_THRESHOLD_KEEP_LIMIT) {
+ lp->lstats.tx_underrun++;
+@@ -1818,25 +1972,25 @@ tc35815_check_tx_stat(struct net_device *dev, int status)
+ }
+ }
+ if (status & Tx_Defer) {
+- lp->stats.tx_fifo_errors++;
++ dev->stats.tx_fifo_errors++;
+ msg = "Excessive Deferral.";
+ }
+ #ifndef NO_CHECK_CARRIER
+ if (status & Tx_NCarr) {
+- lp->stats.tx_carrier_errors++;
++ dev->stats.tx_carrier_errors++;
+ msg = "Lost Carrier Sense.";
+ }
+ #endif
+ if (status & Tx_LateColl) {
+- lp->stats.tx_aborted_errors++;
++ dev->stats.tx_aborted_errors++;
+ msg = "Late Collision.";
+ }
+ if (status & Tx_TxPar) {
+- lp->stats.tx_fifo_errors++;
++ dev->stats.tx_fifo_errors++;
+ msg = "Transmit Parity Error.";
+ }
+ if (status & Tx_SQErr) {
+- lp->stats.tx_heartbeat_errors++;
++ dev->stats.tx_heartbeat_errors++;
+ msg = "Signal Quality Error.";
+ }
+ if (msg && netif_msg_tx_err(lp))
+@@ -1849,7 +2003,7 @@ tc35815_check_tx_stat(struct net_device *dev, int status)
+ static void
+ tc35815_txdone(struct net_device *dev)
+ {
+- struct tc35815_local *lp = dev->priv;
++ struct tc35815_local *lp = netdev_priv(dev);
+ struct TxFD *txfd;
+ unsigned int fdctl;
+
+@@ -1878,7 +2032,7 @@ tc35815_txdone(struct net_device *dev)
+ BUG_ON(lp->tx_skbs[lp->tfd_end].skb != skb);
+ #endif
+ if (skb) {
+- lp->stats.tx_bytes += skb->len;
++ dev->stats.tx_bytes += skb->len;
+ pci_unmap_single(lp->pci_dev, lp->tx_skbs[lp->tfd_end].skb_dma, skb->len, PCI_DMA_TODEVICE);
+ lp->tx_skbs[lp->tfd_end].skb = NULL;
+ lp->tx_skbs[lp->tfd_end].skb_dma = 0;
+@@ -1904,7 +2058,7 @@ tc35815_txdone(struct net_device *dev)
+ struct tc35815_regs __iomem *tr =
+ (struct tc35815_regs __iomem *)dev->base_addr;
+ int head = (lp->tfd_start + TX_FD_NUM - 1) % TX_FD_NUM;
+- struct TxFD* txhead = &lp->tfd_base[head];
++ struct TxFD *txhead = &lp->tfd_base[head];
+ int qlen = (lp->tfd_start + TX_FD_NUM
+ - lp->tfd_end) % TX_FD_NUM;
+
+@@ -1939,7 +2093,7 @@ tc35815_txdone(struct net_device *dev)
+ * condition, and space has now been made available,
+ * wake up the queue.
+ */
+- if (netif_queue_stopped(dev) && ! tc35815_tx_full(dev))
++ if (netif_queue_stopped(dev) && !tc35815_tx_full(dev))
+ netif_wake_queue(dev);
+ }
+
+@@ -1947,16 +2101,17 @@ tc35815_txdone(struct net_device *dev)
+ static int
+ tc35815_close(struct net_device *dev)
+ {
+- struct tc35815_local *lp = dev->priv;
++ struct tc35815_local *lp = netdev_priv(dev);
+
+ netif_stop_queue(dev);
+ #ifdef TC35815_NAPI
+ napi_disable(&lp->napi);
+ #endif
++ if (lp->phy_dev)
++ phy_stop(lp->phy_dev);
++ cancel_work_sync(&lp->restart_work);
+
+ /* Flush the Tx and disable Rx here. */
+-
+- del_timer(&lp->timer); /* Kill if running */
+ tc35815_chip_reset(dev);
+ free_irq(dev->irq, dev);
+
+@@ -1972,34 +2127,30 @@ tc35815_close(struct net_device *dev)
+ */
+ static struct net_device_stats *tc35815_get_stats(struct net_device *dev)
+ {
+- struct tc35815_local *lp = dev->priv;
+ struct tc35815_regs __iomem *tr =
+ (struct tc35815_regs __iomem *)dev->base_addr;
+- if (netif_running(dev)) {
++ if (netif_running(dev))
+ /* Update the statistics from the device registers. */
+- lp->stats.rx_missed_errors = tc_readl(&tr->Miss_Cnt);
+- }
++ dev->stats.rx_missed_errors = tc_readl(&tr->Miss_Cnt);
+
+- return &lp->stats;
++ return &dev->stats;
+ }
+
+ static void tc35815_set_cam_entry(struct net_device *dev, int index, unsigned char *addr)
+ {
+- struct tc35815_local *lp = dev->priv;
++ struct tc35815_local *lp = netdev_priv(dev);
+ struct tc35815_regs __iomem *tr =
+ (struct tc35815_regs __iomem *)dev->base_addr;
+ int cam_index = index * 6;
+ u32 cam_data;
+ u32 saved_addr;
++ DECLARE_MAC_BUF(mac);
++
+ saved_addr = tc_readl(&tr->CAM_Adr);
+
+- if (netif_msg_hw(lp)) {
+- int i;
+- printk(KERN_DEBUG "%s: CAM %d:", dev->name, index);
+- for (i = 0; i < 6; i++)
+- printk(" %02x", addr[i]);
+- printk("\n");
+- }
++ if (netif_msg_hw(lp))
++ printk(KERN_DEBUG "%s: CAM %d: %s\n",
++ dev->name, index, print_mac(mac, addr));
+ if (index & 1) {
+ /* read modify write */
+ tc_writel(cam_index - 2, &tr->CAM_Adr);
+@@ -2039,28 +2190,24 @@ tc35815_set_multicast_list(struct net_device *dev)
+ struct tc35815_regs __iomem *tr =
+ (struct tc35815_regs __iomem *)dev->base_addr;
+
+- if (dev->flags&IFF_PROMISC)
+- {
++ if (dev->flags & IFF_PROMISC) {
+ #ifdef WORKAROUND_100HALF_PROMISC
+ /* With some (all?) 100MHalf HUB, controller will hang
+ * if we enabled promiscuous mode before linkup... */
+- struct tc35815_local *lp = dev->priv;
+- int pid = lp->phy_addr;
+- if (!(tc_mdio_read(dev, pid, MII_BMSR) & BMSR_LSTATUS))
++ struct tc35815_local *lp = netdev_priv(dev);
++
++ if (!lp->link)
+ return;
+ #endif
+ /* Enable promiscuous mode */
+ tc_writel(CAM_CompEn | CAM_BroadAcc | CAM_GroupAcc | CAM_StationAcc, &tr->CAM_Ctl);
+- }
+- else if((dev->flags&IFF_ALLMULTI) || dev->mc_count > CAM_ENTRY_MAX - 3)
+- {
++ } else if ((dev->flags & IFF_ALLMULTI) ||
++ dev->mc_count > CAM_ENTRY_MAX - 3) {
+ /* CAM 0, 1, 20 are reserved. */
+ /* Disable promiscuous mode, use normal mode. */
+ tc_writel(CAM_CompEn | CAM_BroadAcc | CAM_GroupAcc, &tr->CAM_Ctl);
+- }
+- else if(dev->mc_count)
+- {
+- struct dev_mc_list* cur_addr = dev->mc_list;
++ } else if (dev->mc_count) {
++ struct dev_mc_list *cur_addr = dev->mc_list;
+ int i;
+ int ena_bits = CAM_Ena_Bit(CAM_ENTRY_SOURCE);
+
+@@ -2075,8 +2222,7 @@ tc35815_set_multicast_list(struct net_device *dev)
+ }
+ tc_writel(ena_bits, &tr->CAM_Ena);
+ tc_writel(CAM_CompEn | CAM_BroadAcc, &tr->CAM_Ctl);
+- }
+- else {
++ } else {
+ tc_writel(CAM_Ena_Bit(CAM_ENTRY_SOURCE), &tr->CAM_Ena);
+ tc_writel(CAM_CompEn | CAM_BroadAcc, &tr->CAM_Ctl);
+ }
+@@ -2084,7 +2230,7 @@ tc35815_set_multicast_list(struct net_device *dev)
+
+ static void tc35815_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+ {
+- struct tc35815_local *lp = dev->priv;
++ struct tc35815_local *lp = netdev_priv(dev);
+ strcpy(info->driver, MODNAME);
+ strcpy(info->version, DRV_VERSION);
+ strcpy(info->bus_info, pci_name(lp->pci_dev));
+@@ -2092,78 +2238,37 @@ static void tc35815_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *
+
+ static int tc35815_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+ {
+- struct tc35815_local *lp = dev->priv;
+- spin_lock_irq(&lp->lock);
+- mii_ethtool_gset(&lp->mii, cmd);
+- spin_unlock_irq(&lp->lock);
+- return 0;
+-}
+-
+-static int tc35815_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+-{
+- struct tc35815_local *lp = dev->priv;
+- int rc;
+-#if 1 /* use our negotiation method... */
+- /* Verify the settings we care about. */
+- if (cmd->autoneg != AUTONEG_ENABLE &&
+- cmd->autoneg != AUTONEG_DISABLE)
+- return -EINVAL;
+- if (cmd->autoneg == AUTONEG_DISABLE &&
+- ((cmd->speed != SPEED_100 &&
+- cmd->speed != SPEED_10) ||
+- (cmd->duplex != DUPLEX_HALF &&
+- cmd->duplex != DUPLEX_FULL)))
+- return -EINVAL;
++ struct tc35815_local *lp = netdev_priv(dev);
+
+- /* Ok, do it to it. */
+- spin_lock_irq(&lp->lock);
+- del_timer(&lp->timer);
+- tc35815_start_auto_negotiation(dev, cmd);
+- spin_unlock_irq(&lp->lock);
+- rc = 0;
+-#else
+- spin_lock_irq(&lp->lock);
+- rc = mii_ethtool_sset(&lp->mii, cmd);
+- spin_unlock_irq(&lp->lock);
+-#endif
+- return rc;
++ if (!lp->phy_dev)
++ return -ENODEV;
++ return phy_ethtool_gset(lp->phy_dev, cmd);
+ }
+
+-static int tc35815_nway_reset(struct net_device *dev)
++static int tc35815_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+ {
+- struct tc35815_local *lp = dev->priv;
+- int rc;
+- spin_lock_irq(&lp->lock);
+- rc = mii_nway_restart(&lp->mii);
+- spin_unlock_irq(&lp->lock);
+- return rc;
+-}
++ struct tc35815_local *lp = netdev_priv(dev);
+
+-static u32 tc35815_get_link(struct net_device *dev)
+-{
+- struct tc35815_local *lp = dev->priv;
+- int rc;
+- spin_lock_irq(&lp->lock);
+- rc = mii_link_ok(&lp->mii);
+- spin_unlock_irq(&lp->lock);
+- return rc;
++ if (!lp->phy_dev)
++ return -ENODEV;
++ return phy_ethtool_sset(lp->phy_dev, cmd);
+ }
+
+ static u32 tc35815_get_msglevel(struct net_device *dev)
+ {
+- struct tc35815_local *lp = dev->priv;
++ struct tc35815_local *lp = netdev_priv(dev);
+ return lp->msg_enable;
+ }
+
+ static void tc35815_set_msglevel(struct net_device *dev, u32 datum)
+ {
+- struct tc35815_local *lp = dev->priv;
++ struct tc35815_local *lp = netdev_priv(dev);
+ lp->msg_enable = datum;
+ }
+
+ static int tc35815_get_sset_count(struct net_device *dev, int sset)
+ {
+- struct tc35815_local *lp = dev->priv;
++ struct tc35815_local *lp = netdev_priv(dev);
+
+ switch (sset) {
+ case ETH_SS_STATS:
+@@ -2175,7 +2280,7 @@ static int tc35815_get_sset_count(struct net_device *dev, int sset)
+
+ static void tc35815_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data)
+ {
+- struct tc35815_local *lp = dev->priv;
++ struct tc35815_local *lp = netdev_priv(dev);
+ data[0] = lp->lstats.max_tx_qlen;
+ data[1] = lp->lstats.tx_ints;
+ data[2] = lp->lstats.rx_ints;
+@@ -2200,8 +2305,7 @@ static const struct ethtool_ops tc35815_ethtool_ops = {
+ .get_drvinfo = tc35815_get_drvinfo,
+ .get_settings = tc35815_get_settings,
+ .set_settings = tc35815_set_settings,
+- .nway_reset = tc35815_nway_reset,
+- .get_link = tc35815_get_link,
++ .get_link = ethtool_op_get_link,
+ .get_msglevel = tc35815_get_msglevel,
+ .set_msglevel = tc35815_set_msglevel,
+ .get_strings = tc35815_get_strings,
+@@ -2211,611 +2315,13 @@ static const struct ethtool_ops tc35815_ethtool_ops = {
+
+ static int tc35815_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+ {
+- struct tc35815_local *lp = dev->priv;
+- int rc;
++ struct tc35815_local *lp = netdev_priv(dev);
+
+ if (!netif_running(dev))
+ return -EINVAL;
+-
+- spin_lock_irq(&lp->lock);
+- rc = generic_mii_ioctl(&lp->mii, if_mii(rq), cmd, NULL);
+- spin_unlock_irq(&lp->lock);
+-
+- return rc;
+-}
+-
+-static int tc_mdio_read(struct net_device *dev, int phy_id, int location)
+-{
+- struct tc35815_regs __iomem *tr =
+- (struct tc35815_regs __iomem *)dev->base_addr;
+- u32 data;
+- tc_writel(MD_CA_Busy | (phy_id << 5) | location, &tr->MD_CA);
+- while (tc_readl(&tr->MD_CA) & MD_CA_Busy)
+- ;
+- data = tc_readl(&tr->MD_Data);
+- return data & 0xffff;
+-}
+-
+-static void tc_mdio_write(struct net_device *dev, int phy_id, int location,
+- int val)
+-{
+- struct tc35815_regs __iomem *tr =
+- (struct tc35815_regs __iomem *)dev->base_addr;
+- tc_writel(val, &tr->MD_Data);
+- tc_writel(MD_CA_Busy | MD_CA_Wr | (phy_id << 5) | location, &tr->MD_CA);
+- while (tc_readl(&tr->MD_CA) & MD_CA_Busy)
+- ;
+-}
+-
+-/* Auto negotiation. The scheme is very simple. We have a timer routine
+- * that keeps watching the auto negotiation process as it progresses.
+- * The DP83840 is first told to start doing it's thing, we set up the time
+- * and place the timer state machine in it's initial state.
+- *
+- * Here the timer peeks at the DP83840 status registers at each click to see
+- * if the auto negotiation has completed, we assume here that the DP83840 PHY
+- * will time out at some point and just tell us what (didn't) happen. For
+- * complete coverage we only allow so many of the ticks at this level to run,
+- * when this has expired we print a warning message and try another strategy.
+- * This "other" strategy is to force the interface into various speed/duplex
+- * configurations and we stop when we see a link-up condition before the
+- * maximum number of "peek" ticks have occurred.
+- *
+- * Once a valid link status has been detected we configure the BigMAC and
+- * the rest of the Happy Meal to speak the most efficient protocol we could
+- * get a clean link for. The priority for link configurations, highest first
+- * is:
+- * 100 Base-T Full Duplex
+- * 100 Base-T Half Duplex
+- * 10 Base-T Full Duplex
+- * 10 Base-T Half Duplex
+- *
+- * We start a new timer now, after a successful auto negotiation status has
+- * been detected. This timer just waits for the link-up bit to get set in
+- * the BMCR of the DP83840. When this occurs we print a kernel log message
+- * describing the link type in use and the fact that it is up.
+- *
+- * If a fatal error of some sort is signalled and detected in the interrupt
+- * service routine, and the chip is reset, or the link is ifconfig'd down
+- * and then back up, this entire process repeats itself all over again.
+- */
+-/* Note: Above comments are come from sunhme driver. */
+-
+-static int tc35815_try_next_permutation(struct net_device *dev)
+-{
+- struct tc35815_local *lp = dev->priv;
+- int pid = lp->phy_addr;
+- unsigned short bmcr;
+-
+- bmcr = tc_mdio_read(dev, pid, MII_BMCR);
+-
+- /* Downgrade from full to half duplex. Only possible via ethtool. */
+- if (bmcr & BMCR_FULLDPLX) {
+- bmcr &= ~BMCR_FULLDPLX;
+- printk(KERN_DEBUG "%s: try next permutation (BMCR %x)\n", dev->name, bmcr);
+- tc_mdio_write(dev, pid, MII_BMCR, bmcr);
+- return 0;
+- }
+-
+- /* Downgrade from 100 to 10. */
+- if (bmcr & BMCR_SPEED100) {
+- bmcr &= ~BMCR_SPEED100;
+- printk(KERN_DEBUG "%s: try next permutation (BMCR %x)\n", dev->name, bmcr);
+- tc_mdio_write(dev, pid, MII_BMCR, bmcr);
+- return 0;
+- }
+-
+- /* We've tried everything. */
+- return -1;
+-}
+-
+-static void
+-tc35815_display_link_mode(struct net_device *dev)
+-{
+- struct tc35815_local *lp = dev->priv;
+- int pid = lp->phy_addr;
+- unsigned short lpa, bmcr;
+- char *speed = "", *duplex = "";
+-
+- lpa = tc_mdio_read(dev, pid, MII_LPA);
+- bmcr = tc_mdio_read(dev, pid, MII_BMCR);
+- if (options.speed ? (bmcr & BMCR_SPEED100) : (lpa & (LPA_100HALF | LPA_100FULL)))
+- speed = "100Mb/s";
+- else
+- speed = "10Mb/s";
+- if (options.duplex ? (bmcr & BMCR_FULLDPLX) : (lpa & (LPA_100FULL | LPA_10FULL)))
+- duplex = "Full Duplex";
+- else
+- duplex = "Half Duplex";
+-
+- if (netif_msg_link(lp))
+- printk(KERN_INFO "%s: Link is up at %s, %s.\n",
+- dev->name, speed, duplex);
+- printk(KERN_DEBUG "%s: MII BMCR %04x BMSR %04x LPA %04x\n",
+- dev->name,
+- bmcr, tc_mdio_read(dev, pid, MII_BMSR), lpa);
+-}
+-
+-static void tc35815_display_forced_link_mode(struct net_device *dev)
+-{
+- struct tc35815_local *lp = dev->priv;
+- int pid = lp->phy_addr;
+- unsigned short bmcr;
+- char *speed = "", *duplex = "";
+-
+- bmcr = tc_mdio_read(dev, pid, MII_BMCR);
+- if (bmcr & BMCR_SPEED100)
+- speed = "100Mb/s";
+- else
+- speed = "10Mb/s";
+- if (bmcr & BMCR_FULLDPLX)
+- duplex = "Full Duplex.\n";
+- else
+- duplex = "Half Duplex.\n";
+-
+- if (netif_msg_link(lp))
+- printk(KERN_INFO "%s: Link has been forced up at %s, %s",
+- dev->name, speed, duplex);
+-}
+-
+-static void tc35815_set_link_modes(struct net_device *dev)
+-{
+- struct tc35815_local *lp = dev->priv;
+- struct tc35815_regs __iomem *tr =
+- (struct tc35815_regs __iomem *)dev->base_addr;
+- int pid = lp->phy_addr;
+- unsigned short bmcr, lpa;
+- int speed;
+-
+- if (lp->timer_state == arbwait) {
+- lpa = tc_mdio_read(dev, pid, MII_LPA);
+- bmcr = tc_mdio_read(dev, pid, MII_BMCR);
+- printk(KERN_DEBUG "%s: MII BMCR %04x BMSR %04x LPA %04x\n",
+- dev->name,
+- bmcr, tc_mdio_read(dev, pid, MII_BMSR), lpa);
+- if (!(lpa & (LPA_10HALF | LPA_10FULL |
+- LPA_100HALF | LPA_100FULL))) {
+- /* fall back to 10HALF */
+- printk(KERN_INFO "%s: bad ability %04x - falling back to 10HD.\n",
+- dev->name, lpa);
+- lpa = LPA_10HALF;
+- }
+- if (options.duplex ? (bmcr & BMCR_FULLDPLX) : (lpa & (LPA_100FULL | LPA_10FULL)))
+- lp->fullduplex = 1;
+- else
+- lp->fullduplex = 0;
+- if (options.speed ? (bmcr & BMCR_SPEED100) : (lpa & (LPA_100HALF | LPA_100FULL)))
+- speed = 100;
+- else
+- speed = 10;
+- } else {
+- /* Forcing a link mode. */
+- bmcr = tc_mdio_read(dev, pid, MII_BMCR);
+- if (bmcr & BMCR_FULLDPLX)
+- lp->fullduplex = 1;
+- else
+- lp->fullduplex = 0;
+- if (bmcr & BMCR_SPEED100)
+- speed = 100;
+- else
+- speed = 10;
+- }
+-
+- tc_writel(tc_readl(&tr->MAC_Ctl) | MAC_HaltReq, &tr->MAC_Ctl);
+- if (lp->fullduplex) {
+- tc_writel(tc_readl(&tr->MAC_Ctl) | MAC_FullDup, &tr->MAC_Ctl);
+- } else {
+- tc_writel(tc_readl(&tr->MAC_Ctl) & ~MAC_FullDup, &tr->MAC_Ctl);
+- }
+- tc_writel(tc_readl(&tr->MAC_Ctl) & ~MAC_HaltReq, &tr->MAC_Ctl);
+-
+- /* TX4939 PCFG.SPEEDn bit will be changed on NETDEV_CHANGE event. */
+-
+-#ifndef NO_CHECK_CARRIER
+- /* TX4939 does not have EnLCarr */
+- if (lp->boardtype != TC35815_TX4939) {
+-#ifdef WORKAROUND_LOSTCAR
+- /* WORKAROUND: enable LostCrS only if half duplex operation */
+- if (!lp->fullduplex && lp->boardtype != TC35815_TX4939)
+- tc_writel(tc_readl(&tr->Tx_Ctl) | Tx_EnLCarr, &tr->Tx_Ctl);
+-#endif
+- }
+-#endif
+- lp->mii.full_duplex = lp->fullduplex;
+-}
+-
+-static void tc35815_timer(unsigned long data)
+-{
+- struct net_device *dev = (struct net_device *)data;
+- struct tc35815_local *lp = dev->priv;
+- int pid = lp->phy_addr;
+- unsigned short bmsr, bmcr, lpa;
+- int restart_timer = 0;
+-
+- spin_lock_irq(&lp->lock);
+-
+- lp->timer_ticks++;
+- switch (lp->timer_state) {
+- case arbwait:
+- /*
+- * Only allow for 5 ticks, thats 10 seconds and much too
+- * long to wait for arbitration to complete.
+- */
+- /* TC35815 need more times... */
+- if (lp->timer_ticks >= 10) {
+- /* Enter force mode. */
+- if (!options.doforce) {
+- printk(KERN_NOTICE "%s: Auto-Negotiation unsuccessful,"
+- " cable probblem?\n", dev->name);
+- /* Try to restart the adaptor. */
+- tc35815_restart(dev);
+- goto out;
+- }
+- printk(KERN_NOTICE "%s: Auto-Negotiation unsuccessful,"
+- " trying force link mode\n", dev->name);
+- printk(KERN_DEBUG "%s: BMCR %x BMSR %x\n", dev->name,
+- tc_mdio_read(dev, pid, MII_BMCR),
+- tc_mdio_read(dev, pid, MII_BMSR));
+- bmcr = BMCR_SPEED100;
+- tc_mdio_write(dev, pid, MII_BMCR, bmcr);
+-
+- /*
+- * OK, seems we need do disable the transceiver
+- * for the first tick to make sure we get an
+- * accurate link state at the second tick.
+- */
+-
+- lp->timer_state = ltrywait;
+- lp->timer_ticks = 0;
+- restart_timer = 1;
+- } else {
+- /* Anything interesting happen? */
+- bmsr = tc_mdio_read(dev, pid, MII_BMSR);
+- if (bmsr & BMSR_ANEGCOMPLETE) {
+- /* Just what we've been waiting for... */
+- tc35815_set_link_modes(dev);
+-
+- /*
+- * Success, at least so far, advance our state
+- * engine.
+- */
+- lp->timer_state = lupwait;
+- restart_timer = 1;
+- } else {
+- restart_timer = 1;
+- }
+- }
+- break;
+-
+- case lupwait:
+- /*
+- * Auto negotiation was successful and we are awaiting a
+- * link up status. I have decided to let this timer run
+- * forever until some sort of error is signalled, reporting
+- * a message to the user at 10 second intervals.
+- */
+- bmsr = tc_mdio_read(dev, pid, MII_BMSR);
+- if (bmsr & BMSR_LSTATUS) {
+- /*
+- * Wheee, it's up, display the link mode in use and put
+- * the timer to sleep.
+- */
+- tc35815_display_link_mode(dev);
+- netif_carrier_on(dev);
+-#ifdef WORKAROUND_100HALF_PROMISC
+- /* delayed promiscuous enabling */
+- if (dev->flags & IFF_PROMISC)
+- tc35815_set_multicast_list(dev);
+-#endif
+-#if 1
+- lp->saved_lpa = tc_mdio_read(dev, pid, MII_LPA);
+- lp->timer_state = lcheck;
+- restart_timer = 1;
+-#else
+- lp->timer_state = asleep;
+- restart_timer = 0;
+-#endif
+- } else {
+- if (lp->timer_ticks >= 10) {
+- printk(KERN_NOTICE "%s: Auto negotiation successful, link still "
+- "not completely up.\n", dev->name);
+- lp->timer_ticks = 0;
+- restart_timer = 1;
+- } else {
+- restart_timer = 1;
+- }
+- }
+- break;
+-
+- case ltrywait:
+- /*
+- * Making the timeout here too long can make it take
+- * annoyingly long to attempt all of the link mode
+- * permutations, but then again this is essentially
+- * error recovery code for the most part.
+- */
+- bmsr = tc_mdio_read(dev, pid, MII_BMSR);
+- bmcr = tc_mdio_read(dev, pid, MII_BMCR);
+- if (lp->timer_ticks == 1) {
+- /*
+- * Re-enable transceiver, we'll re-enable the
+- * transceiver next tick, then check link state
+- * on the following tick.
+- */
+- restart_timer = 1;
+- break;
+- }
+- if (lp->timer_ticks == 2) {
+- restart_timer = 1;
+- break;
+- }
+- if (bmsr & BMSR_LSTATUS) {
+- /* Force mode selection success. */
+- tc35815_display_forced_link_mode(dev);
+- netif_carrier_on(dev);
+- tc35815_set_link_modes(dev);
+-#ifdef WORKAROUND_100HALF_PROMISC
+- /* delayed promiscuous enabling */
+- if (dev->flags & IFF_PROMISC)
+- tc35815_set_multicast_list(dev);
+-#endif
+-#if 1
+- lp->saved_lpa = tc_mdio_read(dev, pid, MII_LPA);
+- lp->timer_state = lcheck;
+- restart_timer = 1;
+-#else
+- lp->timer_state = asleep;
+- restart_timer = 0;
+-#endif
+- } else {
+- if (lp->timer_ticks >= 4) { /* 6 seconds or so... */
+- int ret;
+-
+- ret = tc35815_try_next_permutation(dev);
+- if (ret == -1) {
+- /*
+- * Aieee, tried them all, reset the
+- * chip and try all over again.
+- */
+- printk(KERN_NOTICE "%s: Link down, "
+- "cable problem?\n",
+- dev->name);
+-
+- /* Try to restart the adaptor. */
+- tc35815_restart(dev);
+- goto out;
+- }
+- lp->timer_ticks = 0;
+- restart_timer = 1;
+- } else {
+- restart_timer = 1;
+- }
+- }
+- break;
+-
+- case lcheck:
+- bmcr = tc_mdio_read(dev, pid, MII_BMCR);
+- lpa = tc_mdio_read(dev, pid, MII_LPA);
+- if (bmcr & (BMCR_PDOWN | BMCR_ISOLATE | BMCR_RESET)) {
+- printk(KERN_ERR "%s: PHY down? (BMCR %x)\n", dev->name,
+- bmcr);
+- } else if ((lp->saved_lpa ^ lpa) &
+- (LPA_100FULL|LPA_100HALF|LPA_10FULL|LPA_10HALF)) {
+- printk(KERN_NOTICE "%s: link status changed"
+- " (BMCR %x LPA %x->%x)\n", dev->name,
+- bmcr, lp->saved_lpa, lpa);
+- } else {
+- /* go on */
+- restart_timer = 1;
+- break;
+- }
+- /* Try to restart the adaptor. */
+- tc35815_restart(dev);
+- goto out;
+-
+- case asleep:
+- default:
+- /* Can't happens.... */
+- printk(KERN_ERR "%s: Aieee, link timer is asleep but we got "
+- "one anyways!\n", dev->name);
+- restart_timer = 0;
+- lp->timer_ticks = 0;
+- lp->timer_state = asleep; /* foo on you */
+- break;
+- }
+-
+- if (restart_timer) {
+- lp->timer.expires = jiffies + msecs_to_jiffies(1200);
+- add_timer(&lp->timer);
+- }
+-out:
+- spin_unlock_irq(&lp->lock);
+-}
+-
+-static void tc35815_start_auto_negotiation(struct net_device *dev,
+- struct ethtool_cmd *ep)
+-{
+- struct tc35815_local *lp = dev->priv;
+- int pid = lp->phy_addr;
+- unsigned short bmsr, bmcr, advertize;
+- int timeout;
+-
+- netif_carrier_off(dev);
+- bmsr = tc_mdio_read(dev, pid, MII_BMSR);
+- bmcr = tc_mdio_read(dev, pid, MII_BMCR);
+- advertize = tc_mdio_read(dev, pid, MII_ADVERTISE);
+-
+- if (ep == NULL || ep->autoneg == AUTONEG_ENABLE) {
+- if (options.speed || options.duplex) {
+- /* Advertise only specified configuration. */
+- advertize &= ~(ADVERTISE_10HALF |
+- ADVERTISE_10FULL |
+- ADVERTISE_100HALF |
+- ADVERTISE_100FULL);
+- if (options.speed != 10) {
+- if (options.duplex != 1)
+- advertize |= ADVERTISE_100FULL;
+- if (options.duplex != 2)
+- advertize |= ADVERTISE_100HALF;
+- }
+- if (options.speed != 100) {
+- if (options.duplex != 1)
+- advertize |= ADVERTISE_10FULL;
+- if (options.duplex != 2)
+- advertize |= ADVERTISE_10HALF;
+- }
+- if (options.speed == 100)
+- bmcr |= BMCR_SPEED100;
+- else if (options.speed == 10)
+- bmcr &= ~BMCR_SPEED100;
+- if (options.duplex == 2)
+- bmcr |= BMCR_FULLDPLX;
+- else if (options.duplex == 1)
+- bmcr &= ~BMCR_FULLDPLX;
+- } else {
+- /* Advertise everything we can support. */
+- if (bmsr & BMSR_10HALF)
+- advertize |= ADVERTISE_10HALF;
+- else
+- advertize &= ~ADVERTISE_10HALF;
+- if (bmsr & BMSR_10FULL)
+- advertize |= ADVERTISE_10FULL;
+- else
+- advertize &= ~ADVERTISE_10FULL;
+- if (bmsr & BMSR_100HALF)
+- advertize |= ADVERTISE_100HALF;
+- else
+- advertize &= ~ADVERTISE_100HALF;
+- if (bmsr & BMSR_100FULL)
+- advertize |= ADVERTISE_100FULL;
+- else
+- advertize &= ~ADVERTISE_100FULL;
+- }
+-
+- tc_mdio_write(dev, pid, MII_ADVERTISE, advertize);
+-
+- /* Enable Auto-Negotiation, this is usually on already... */
+- bmcr |= BMCR_ANENABLE;
+- tc_mdio_write(dev, pid, MII_BMCR, bmcr);
+-
+- /* Restart it to make sure it is going. */
+- bmcr |= BMCR_ANRESTART;
+- tc_mdio_write(dev, pid, MII_BMCR, bmcr);
+- printk(KERN_DEBUG "%s: ADVERTISE %x BMCR %x\n", dev->name, advertize, bmcr);
+-
+- /* BMCR_ANRESTART self clears when the process has begun. */
+- timeout = 64; /* More than enough. */
+- while (--timeout) {
+- bmcr = tc_mdio_read(dev, pid, MII_BMCR);
+- if (!(bmcr & BMCR_ANRESTART))
+- break; /* got it. */
+- udelay(10);
+- }
+- if (!timeout) {
+- printk(KERN_ERR "%s: TC35815 would not start auto "
+- "negotiation BMCR=0x%04x\n",
+- dev->name, bmcr);
+- printk(KERN_NOTICE "%s: Performing force link "
+- "detection.\n", dev->name);
+- goto force_link;
+- } else {
+- printk(KERN_DEBUG "%s: auto negotiation started.\n", dev->name);
+- lp->timer_state = arbwait;
+- }
+- } else {
+-force_link:
+- /* Force the link up, trying first a particular mode.
+- * Either we are here at the request of ethtool or
+- * because the Happy Meal would not start to autoneg.
+- */
+-
+- /* Disable auto-negotiation in BMCR, enable the duplex and
+- * speed setting, init the timer state machine, and fire it off.
+- */
+- if (ep == NULL || ep->autoneg == AUTONEG_ENABLE) {
+- bmcr = BMCR_SPEED100;
+- } else {
+- if (ep->speed == SPEED_100)
+- bmcr = BMCR_SPEED100;
+- else
+- bmcr = 0;
+- if (ep->duplex == DUPLEX_FULL)
+- bmcr |= BMCR_FULLDPLX;
+- }
+- tc_mdio_write(dev, pid, MII_BMCR, bmcr);
+-
+- /* OK, seems we need do disable the transceiver for the first
+- * tick to make sure we get an accurate link state at the
+- * second tick.
+- */
+- lp->timer_state = ltrywait;
+- }
+-
+- del_timer(&lp->timer);
+- lp->timer_ticks = 0;
+- lp->timer.expires = jiffies + msecs_to_jiffies(1200);
+- add_timer(&lp->timer);
+-}
+-
+-static void tc35815_find_phy(struct net_device *dev)
+-{
+- struct tc35815_local *lp = dev->priv;
+- int pid = lp->phy_addr;
+- unsigned short id0;
+-
+- /* find MII phy */
+- for (pid = 31; pid >= 0; pid--) {
+- id0 = tc_mdio_read(dev, pid, MII_BMSR);
+- if (id0 != 0xffff && id0 != 0x0000 &&
+- (id0 & BMSR_RESV) != (0xffff & BMSR_RESV) /* paranoia? */
+- ) {
+- lp->phy_addr = pid;
+- break;
+- }
+- }
+- if (pid < 0) {
+- printk(KERN_ERR "%s: No MII Phy found.\n",
+- dev->name);
+- lp->phy_addr = pid = 0;
+- }
+-
+- lp->mii_id[0] = tc_mdio_read(dev, pid, MII_PHYSID1);
+- lp->mii_id[1] = tc_mdio_read(dev, pid, MII_PHYSID2);
+- if (netif_msg_hw(lp))
+- printk(KERN_INFO "%s: PHY(%02x) ID %04x %04x\n", dev->name,
+- pid, lp->mii_id[0], lp->mii_id[1]);
+-}
+-
+-static void tc35815_phy_chip_init(struct net_device *dev)
+-{
+- struct tc35815_local *lp = dev->priv;
+- int pid = lp->phy_addr;
+- unsigned short bmcr;
+- struct ethtool_cmd ecmd, *ep;
+-
+- /* dis-isolate if needed. */
+- bmcr = tc_mdio_read(dev, pid, MII_BMCR);
+- if (bmcr & BMCR_ISOLATE) {
+- int count = 32;
+- printk(KERN_DEBUG "%s: unisolating...", dev->name);
+- tc_mdio_write(dev, pid, MII_BMCR, bmcr & ~BMCR_ISOLATE);
+- while (--count) {
+- if (!(tc_mdio_read(dev, pid, MII_BMCR) & BMCR_ISOLATE))
+- break;
+- udelay(20);
+- }
+- printk(" %s.\n", count ? "done" : "failed");
+- }
+-
+- if (options.speed && options.duplex) {
+- ecmd.autoneg = AUTONEG_DISABLE;
+- ecmd.speed = options.speed == 10 ? SPEED_10 : SPEED_100;
+- ecmd.duplex = options.duplex == 1 ? DUPLEX_HALF : DUPLEX_FULL;
+- ep = &ecmd;
+- } else {
+- ep = NULL;
+- }
+- tc35815_start_auto_negotiation(dev, ep);
++ if (!lp->phy_dev)
++ return -ENODEV;
++ return phy_mii_ioctl(lp->phy_dev, if_mii(rq), cmd);
+ }
+
+ static void tc35815_chip_reset(struct net_device *dev)
+@@ -2862,13 +2368,11 @@ static void tc35815_chip_reset(struct net_device *dev)
+
+ static void tc35815_chip_init(struct net_device *dev)
+ {
+- struct tc35815_local *lp = dev->priv;
++ struct tc35815_local *lp = netdev_priv(dev);
+ struct tc35815_regs __iomem *tr =
+ (struct tc35815_regs __iomem *)dev->base_addr;
+ unsigned long txctl = TX_CTL_CMD;
+
+- tc35815_phy_chip_init(dev);
+-
+ /* load station address to CAM */
+ tc35815_set_cam_entry(dev, CAM_ENTRY_SOURCE, dev->dev_addr);
+
+@@ -2905,12 +2409,11 @@ static void tc35815_chip_init(struct net_device *dev)
+ /* start MAC transmitter */
+ #ifndef NO_CHECK_CARRIER
+ /* TX4939 does not have EnLCarr */
+- if (lp->boardtype == TC35815_TX4939)
++ if (lp->chiptype == TC35815_TX4939)
+ txctl &= ~Tx_EnLCarr;
+ #ifdef WORKAROUND_LOSTCAR
+ /* WORKAROUND: ignore LostCrS in full duplex operation */
+- if ((lp->timer_state != asleep && lp->timer_state != lcheck) ||
+- lp->fullduplex)
++ if (!lp->phy_dev || !lp->link || lp->duplex == DUPLEX_FULL)
+ txctl &= ~Tx_EnLCarr;
+ #endif
+ #endif /* !NO_CHECK_CARRIER */
+@@ -2924,15 +2427,16 @@ static void tc35815_chip_init(struct net_device *dev)
+ static int tc35815_suspend(struct pci_dev *pdev, pm_message_t state)
+ {
+ struct net_device *dev = pci_get_drvdata(pdev);
+- struct tc35815_local *lp = dev->priv;
++ struct tc35815_local *lp = netdev_priv(dev);
+ unsigned long flags;
+
+ pci_save_state(pdev);
+ if (!netif_running(dev))
+ return 0;
+ netif_device_detach(dev);
++ if (lp->phy_dev)
++ phy_stop(lp->phy_dev);
+ spin_lock_irqsave(&lp->lock, flags);
+- del_timer(&lp->timer); /* Kill if running */
+ tc35815_chip_reset(dev);
+ spin_unlock_irqrestore(&lp->lock, flags);
+ pci_set_power_state(pdev, PCI_D3hot);
+@@ -2942,16 +2446,15 @@ static int tc35815_suspend(struct pci_dev *pdev, pm_message_t state)
+ static int tc35815_resume(struct pci_dev *pdev)
+ {
+ struct net_device *dev = pci_get_drvdata(pdev);
+- struct tc35815_local *lp = dev->priv;
+- unsigned long flags;
++ struct tc35815_local *lp = netdev_priv(dev);
+
+ pci_restore_state(pdev);
+ if (!netif_running(dev))
+ return 0;
+ pci_set_power_state(pdev, PCI_D0);
+- spin_lock_irqsave(&lp->lock, flags);
+ tc35815_restart(dev);
+- spin_unlock_irqrestore(&lp->lock, flags);
++ if (lp->phy_dev)
++ phy_start(lp->phy_dev);
+ netif_device_attach(dev);
+ return 0;
+ }
+@@ -2972,8 +2475,6 @@ module_param_named(speed, options.speed, int, 0);
+ MODULE_PARM_DESC(speed, "0:auto, 10:10Mbps, 100:100Mbps");
+ module_param_named(duplex, options.duplex, int, 0);
+ MODULE_PARM_DESC(duplex, "0:auto, 1:half, 2:full");
+-module_param_named(doforce, options.doforce, int, 0);
+-MODULE_PARM_DESC(doforce, "try force link mode if auto-negotiation failed");
+
+ static int __init tc35815_init_module(void)
+ {
+diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c
+index 17585e5..e83b166 100644
+--- a/drivers/net/tehuti.c
++++ b/drivers/net/tehuti.c
+@@ -625,6 +625,12 @@ static void __init bdx_firmware_endianess(void)
+ s_firmLoad[i] = CPU_CHIP_SWAP32(s_firmLoad[i]);
+ }
+
++static int bdx_range_check(struct bdx_priv *priv, u32 offset)
++{
++ return (offset > (u32) (BDX_REGS_SIZE / priv->nic->port_num)) ?
++ -EINVAL : 0;
++}
++
+ static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd)
+ {
+ struct bdx_priv *priv = ndev->priv;
+@@ -643,9 +649,15 @@ static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd)
+ DBG("%d 0x%x 0x%x\n", data[0], data[1], data[2]);
+ }
+
++ if (!capable(CAP_NET_ADMIN))
++ return -EPERM;
++
+ switch (data[0]) {
+
+ case BDX_OP_READ:
++ error = bdx_range_check(priv, data[1]);
++ if (error < 0)
++ return error;
+ data[2] = READ_REG(priv, data[1]);
+ DBG("read_reg(0x%x)=0x%x (dec %d)\n", data[1], data[2],
+ data[2]);
+@@ -655,6 +667,9 @@ static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd)
+ break;
+
+ case BDX_OP_WRITE:
++ error = bdx_range_check(priv, data[1]);
++ if (error < 0)
++ return error;
+ WRITE_REG(priv, data[1], data[2]);
+ DBG("write_reg(0x%x, 0x%x)\n", data[1], data[2]);
+ break;
+diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
+index 96043c5..e3f74c9 100644
+--- a/drivers/net/tg3.c
++++ b/drivers/net/tg3.c
+@@ -64,8 +64,8 @@
+
+ #define DRV_MODULE_NAME "tg3"
+ #define PFX DRV_MODULE_NAME ": "
+-#define DRV_MODULE_VERSION "3.90"
+-#define DRV_MODULE_RELDATE "April 12, 2008"
++#define DRV_MODULE_VERSION "3.91"
++#define DRV_MODULE_RELDATE "April 18, 2008"
+
+ #define TG3_DEF_MAC_MODE 0
+ #define TG3_DEF_RX_MODE 0
+@@ -4017,6 +4017,8 @@ static int tg3_halt(struct tg3 *, int, int);
+ * Invoked with tp->lock held.
+ */
+ static int tg3_restart_hw(struct tg3 *tp, int reset_phy)
++ __releases(tp->lock)
++ __acquires(tp->lock)
+ {
+ int err;
+
+@@ -4135,11 +4137,21 @@ static int tigon3_dma_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
+ u32 last_plus_one, u32 *start,
+ u32 base_flags, u32 mss)
+ {
+- struct sk_buff *new_skb = skb_copy(skb, GFP_ATOMIC);
++ struct sk_buff *new_skb;
+ dma_addr_t new_addr = 0;
+ u32 entry = *start;
+ int i, ret = 0;
+
++ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701)
++ new_skb = skb_copy(skb, GFP_ATOMIC);
++ else {
++ int more_headroom = 4 - ((unsigned long)skb->data & 3);
++
++ new_skb = skb_copy_expand(skb,
++ skb_headroom(skb) + more_headroom,
++ skb_tailroom(skb), GFP_ATOMIC);
++ }
++
+ if (!new_skb) {
+ ret = -1;
+ } else {
+@@ -4462,7 +4474,9 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
+
+ would_hit_hwbug = 0;
+
+- if (tg3_4g_overflow_test(mapping, len))
++ if (tp->tg3_flags3 & TG3_FLG3_5701_DMA_BUG)
++ would_hit_hwbug = 1;
++ else if (tg3_4g_overflow_test(mapping, len))
+ would_hit_hwbug = 1;
+
+ tg3_set_txd(tp, entry, mapping, len, base_flags,
+@@ -11339,6 +11353,38 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
+ }
+ }
+
++ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) {
++ static struct tg3_dev_id {
++ u32 vendor;
++ u32 device;
++ } bridge_chipsets[] = {
++ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_0 },
++ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_1 },
++ { },
++ };
++ struct tg3_dev_id *pci_id = &bridge_chipsets[0];
++ struct pci_dev *bridge = NULL;
++
++ while (pci_id->vendor != 0) {
++ bridge = pci_get_device(pci_id->vendor,
++ pci_id->device,
++ bridge);
++ if (!bridge) {
++ pci_id++;
++ continue;
++ }
++ if (bridge->subordinate &&
++ (bridge->subordinate->number <=
++ tp->pdev->bus->number) &&
++ (bridge->subordinate->subordinate >=
++ tp->pdev->bus->number)) {
++ tp->tg3_flags3 |= TG3_FLG3_5701_DMA_BUG;
++ pci_dev_put(bridge);
++ break;
++ }
++ }
++ }
++
+ /* The EPB bridge inside 5714, 5715, and 5780 cannot support
+ * DMA addresses > 40-bit. This bridge may have other additional
+ * 57xx devices behind it in some 4-port NIC designs for example.
+diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
+index c1075a7..c688c3a 100644
+--- a/drivers/net/tg3.h
++++ b/drivers/net/tg3.h
+@@ -2476,6 +2476,7 @@ struct tg3 {
+ #define TG3_FLG3_NO_NVRAM_ADDR_TRANS 0x00000001
+ #define TG3_FLG3_ENABLE_APE 0x00000002
+ #define TG3_FLG3_5761_5784_AX_FIXES 0x00000004
++#define TG3_FLG3_5701_DMA_BUG 0x00000008
+
+ struct timer_list timer;
+ u16 timer_counter;
+diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c
+index 6f33f84..6017d52 100644
+--- a/drivers/net/tsi108_eth.c
++++ b/drivers/net/tsi108_eth.c
+@@ -162,6 +162,7 @@ static struct platform_driver tsi_eth_driver = {
+ .remove = tsi108_ether_remove,
+ .driver = {
+ .name = "tsi-ethernet",
++ .owner = THIS_MODULE,
+ },
+ };
+
+@@ -1729,3 +1730,4 @@ module_exit(tsi108_ether_exit);
+ MODULE_AUTHOR("Tundra Semiconductor Corporation");
+ MODULE_DESCRIPTION("Tsi108 Gigabit Ethernet driver");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:tsi-ethernet");
+diff --git a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig
+index 20ac150..d913405 100644
+--- a/drivers/net/tulip/Kconfig
++++ b/drivers/net/tulip/Kconfig
+@@ -141,7 +141,7 @@ config ULI526X
+ be called uli526x.
+
+ config PCMCIA_XIRCOM
+- tristate "Xircom CardBus support (new driver)"
++ tristate "Xircom CardBus support"
+ depends on CARDBUS
+ ---help---
+ This driver is for the Digital "Tulip" Ethernet CardBus adapters.
+@@ -152,17 +152,4 @@ config PCMCIA_XIRCOM
+ To compile this driver as a module, choose M here. The module will
+ be called xircom_cb. If unsure, say N.
+
+-config PCMCIA_XIRTULIP
+- tristate "Xircom Tulip-like CardBus support (old driver)"
+- depends on CARDBUS && BROKEN_ON_SMP
+- select CRC32
+- ---help---
+- This driver is for the Digital "Tulip" Ethernet CardBus adapters.
+- It should work with most DEC 21*4*-based chips/ethercards, as well
+- as with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and
+- ASIX.
+-
+- To compile this driver as a module, choose M here. The module will
+- be called xircom_tulip_cb. If unsure, say N.
+-
+ endif # NET_TULIP
+diff --git a/drivers/net/tulip/Makefile b/drivers/net/tulip/Makefile
+index 451090d..200cbf7 100644
+--- a/drivers/net/tulip/Makefile
++++ b/drivers/net/tulip/Makefile
+@@ -2,7 +2,6 @@
+ # Makefile for the Linux "Tulip" family network device drivers.
+ #
+
+-obj-$(CONFIG_PCMCIA_XIRTULIP) += xircom_tulip_cb.o
+ obj-$(CONFIG_PCMCIA_XIRCOM) += xircom_cb.o
+ obj-$(CONFIG_DM9102) += dmfe.o
+ obj-$(CONFIG_WINBOND_840) += winbond-840.o
+diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h
+index 3f69f53..908422f 100644
+--- a/drivers/net/tulip/tulip.h
++++ b/drivers/net/tulip/tulip.h
+@@ -268,7 +268,12 @@ enum t21143_csr6_bits {
+ #define RX_RING_SIZE 128
+ #define MEDIA_MASK 31
+
+-#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer. */
++/* The receiver on the DC21143 rev 65 can fail to close the last
++ * receive descriptor in certain circumstances (see errata) when
++ * using MWI. This can only occur if the receive buffer ends on
++ * a cache line boundary, so the "+ 4" below ensures it doesn't.
++ */
++#define PKT_BUF_SZ (1536 + 4) /* Size of each temporary Rx buffer. */
+
+ #define TULIP_MIN_CACHE_LINE 8 /* in units of 32-bit words */
+
+diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
+index 82f404b..fa1c1c3 100644
+--- a/drivers/net/tulip/tulip_core.c
++++ b/drivers/net/tulip/tulip_core.c
+@@ -1154,18 +1154,13 @@ static void __devinit tulip_mwi_config (struct pci_dev *pdev,
+
+ tp->csr0 = csr0 = 0;
+
+- /* if we have any cache line size at all, we can do MRM */
+- csr0 |= MRM;
++ /* if we have any cache line size at all, we can do MRM and MWI */
++ csr0 |= MRM | MWI;
+
+- /* ...and barring hardware bugs, MWI */
+- if (!(tp->chip_id == DC21143 && tp->revision == 65))
+- csr0 |= MWI;
+-
+- /* set or disable MWI in the standard PCI command bit.
+- * Check for the case where mwi is desired but not available
++ /* Enable MWI in the standard PCI command bit.
++ * Check for the case where MWI is desired but not available
+ */
+- if (csr0 & MWI) pci_try_set_mwi(pdev);
+- else pci_clear_mwi(pdev);
++ pci_try_set_mwi(pdev);
+
+ /* read result from hardware (in case bit refused to enable) */
+ pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
+@@ -1401,10 +1396,6 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
+ #ifdef CONFIG_TULIP_MWI
+ if (!force_csr0 && (tp->flags & HAS_PCI_MWI))
+ tulip_mwi_config (pdev, dev);
+-#else
+- /* MWI is broken for DC21143 rev 65... */
+- if (chip_idx == DC21143 && pdev->revision == 65)
+- tp->csr0 &= ~MWI;
+ #endif
+
+ /* Stop the chip's Tx and Rx processes. */
+diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c
+index 35d0cfc..5006819 100644
+--- a/drivers/net/tulip/winbond-840.c
++++ b/drivers/net/tulip/winbond-840.c
+@@ -107,8 +107,6 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+ /* Time in jiffies before concluding the transmitter is hung. */
+ #define TX_TIMEOUT (2*HZ)
+
+-#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
+-
+ /* Include files, designed to support most kernel versions 2.0.0 and later. */
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+@@ -137,6 +135,9 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+
+ #include "tulip.h"
+
++#undef PKT_BUF_SZ /* tulip.h also defines this */
++#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
++
+ /* These identify the driver base version and may not be removed. */
+ static char version[] =
+ KERN_INFO DRV_NAME ".c:v" DRV_VERSION " (2.4 port) " DRV_RELDATE " Donald Becker <becker at scyld.com>\n"
+diff --git a/drivers/net/tulip/xircom_tulip_cb.c b/drivers/net/tulip/xircom_tulip_cb.c
+deleted file mode 100644
+index c3f8e30..0000000
+--- a/drivers/net/tulip/xircom_tulip_cb.c
++++ /dev/null
+@@ -1,1726 +0,0 @@
+-/* xircom_tulip_cb.c: A Xircom CBE-100 ethernet driver for Linux. */
+-/*
+- Written/copyright 1994-1999 by Donald Becker.
+-
+- This software may be used and distributed according to the terms
+- of the GNU General Public License, incorporated herein by reference.
+-
+- The author may be reached as becker at scyld.com, or C/O
+- Scyld Computing Corporation
+- 410 Severn Ave., Suite 210
+- Annapolis MD 21403
+-
+-*/
+-
+-#define DRV_NAME "xircom_tulip_cb"
+-#define DRV_VERSION "0.92"
+-#define DRV_RELDATE "June 27, 2006"
+-
+-/* A few user-configurable values. */
+-
+-#define xircom_debug debug
+-#ifdef XIRCOM_DEBUG
+-static int xircom_debug = XIRCOM_DEBUG;
+-#else
+-static int xircom_debug = 1;
+-#endif
+-
+-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+-static int max_interrupt_work = 25;
+-
+-#define MAX_UNITS 4
+-/* Used to pass the full-duplex flag, etc. */
+-static int full_duplex[MAX_UNITS];
+-static int options[MAX_UNITS];
+-static int mtu[MAX_UNITS]; /* Jumbo MTU for interfaces. */
+-
+-/* Keep the ring sizes a power of two for efficiency.
+- Making the Tx ring too large decreases the effectiveness of channel
+- bonding and packet priority.
+- There are no ill effects from too-large receive rings. */
+-#define TX_RING_SIZE 16
+-#define RX_RING_SIZE 32
+-
+-/* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */
+-#ifdef __alpha__
+-static int rx_copybreak = 1518;
+-#else
+-static int rx_copybreak = 100;
+-#endif
+-
+-/*
+- Set the bus performance register.
+- Typical: Set 16 longword cache alignment, no burst limit.
+- Cache alignment bits 15:14 Burst length 13:8
+- 0000 No alignment 0x00000000 unlimited 0800 8 longwords
+- 4000 8 longwords 0100 1 longword 1000 16 longwords
+- 8000 16 longwords 0200 2 longwords 2000 32 longwords
+- C000 32 longwords 0400 4 longwords
+- Warning: many older 486 systems are broken and require setting 0x00A04800
+- 8 longword cache alignment, 8 longword burst.
+- ToDo: Non-Intel setting could be better.
+-*/
+-
+-#if defined(__alpha__) || defined(__ia64__) || defined(__x86_64__)
+-static int csr0 = 0x01A00000 | 0xE000;
+-#elif defined(__powerpc__)
+-static int csr0 = 0x01B00000 | 0x8000;
+-#elif defined(CONFIG_SPARC)
+-static int csr0 = 0x01B00080 | 0x8000;
+-#elif defined(__i386__)
+-static int csr0 = 0x01A00000 | 0x8000;
+-#else
+-#warning Processor architecture undefined!
+-static int csr0 = 0x00A00000 | 0x4800;
+-#endif
+-
+-/* Operational parameters that usually are not changed. */
+-/* Time in jiffies before concluding the transmitter is hung. */
+-#define TX_TIMEOUT (4 * HZ)
+-#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
+-#define PKT_SETUP_SZ 192 /* Size of the setup frame */
+-
+-/* PCI registers */
+-#define PCI_POWERMGMT 0x40
+-
+-#include <linux/module.h>
+-#include <linux/moduleparam.h>
+-#include <linux/kernel.h>
+-#include <linux/pci.h>
+-#include <linux/netdevice.h>
+-#include <linux/etherdevice.h>
+-#include <linux/delay.h>
+-#include <linux/init.h>
+-#include <linux/mii.h>
+-#include <linux/ethtool.h>
+-#include <linux/crc32.h>
+-
+-#include <asm/io.h>
+-#include <asm/processor.h> /* Processor type for cache alignment. */
+-#include <asm/uaccess.h>
+-
+-
+-/* These identify the driver base version and may not be removed. */
+-static char version[] __devinitdata =
+-KERN_INFO DRV_NAME ".c derived from tulip.c:v0.91 4/14/99 becker at scyld.com\n"
+-KERN_INFO " unofficial 2.4.x kernel port, version " DRV_VERSION ", " DRV_RELDATE "\n";
+-
+-MODULE_AUTHOR("Donald Becker <becker at scyld.com>");
+-MODULE_DESCRIPTION("Xircom CBE-100 ethernet driver");
+-MODULE_LICENSE("GPL v2");
+-MODULE_VERSION(DRV_VERSION);
+-
+-module_param(debug, int, 0);
+-module_param(max_interrupt_work, int, 0);
+-module_param(rx_copybreak, int, 0);
+-module_param(csr0, int, 0);
+-
+-module_param_array(options, int, NULL, 0);
+-module_param_array(full_duplex, int, NULL, 0);
+-
+-#define RUN_AT(x) (jiffies + (x))
+-
+-/*
+- Theory of Operation
+-
+-I. Board Compatibility
+-
+-This device driver was forked from the driver for the DECchip "Tulip",
+-Digital's single-chip ethernet controllers for PCI. It supports Xircom's
+-almost-Tulip-compatible CBE-100 CardBus adapters.
+-
+-II. Board-specific settings
+-
+-PCI bus devices are configured by the system at boot time, so no jumpers
+-need to be set on the board. The system BIOS preferably should assign the
+-PCI INTA signal to an otherwise unused system IRQ line.
+-
+-III. Driver operation
+-
+-IIIa. Ring buffers
+-
+-The Xircom can use either ring buffers or lists of Tx and Rx descriptors.
+-This driver uses statically allocated rings of Rx and Tx descriptors, set at
+-compile time by RX/TX_RING_SIZE. This version of the driver allocates skbuffs
+-for the Rx ring buffers at open() time and passes the skb->data field to the
+-Xircom as receive data buffers. When an incoming frame is less than
+-RX_COPYBREAK bytes long, a fresh skbuff is allocated and the frame is
+-copied to the new skbuff. When the incoming frame is larger, the skbuff is
+-passed directly up the protocol stack and replaced by a newly allocated
+-skbuff.
+-
+-The RX_COPYBREAK value is chosen to trade-off the memory wasted by
+-using a full-sized skbuff for small frames vs. the copying costs of larger
+-frames. For small frames the copying cost is negligible (esp. considering
+-that we are pre-loading the cache with immediately useful header
+-information). For large frames the copying cost is non-trivial, and the
+-larger copy might flush the cache of useful data. A subtle aspect of this
+-choice is that the Xircom only receives into longword aligned buffers, thus
+-the IP header at offset 14 isn't longword aligned for further processing.
+-Copied frames are put into the new skbuff at an offset of "+2", thus copying
+-has the beneficial effect of aligning the IP header and preloading the
+-cache.
+-
+-IIIC. Synchronization
+-The driver runs as two independent, single-threaded flows of control. One
+-is the send-packet routine, which enforces single-threaded use by the
+-dev->tbusy flag. The other thread is the interrupt handler, which is single
+-threaded by the hardware and other software.
+-
+-The send packet thread has partial control over the Tx ring and 'dev->tbusy'
+-flag. It sets the tbusy flag whenever it's queuing a Tx packet. If the next
+-queue slot is empty, it clears the tbusy flag when finished otherwise it sets
+-the 'tp->tx_full' flag.
+-
+-The interrupt handler has exclusive control over the Rx ring and records stats
+-from the Tx ring. (The Tx-done interrupt can't be selectively turned off, so
+-we can't avoid the interrupt overhead by having the Tx routine reap the Tx
+-stats.) After reaping the stats, it marks the queue entry as empty by setting
+-the 'base' to zero. Iff the 'tp->tx_full' flag is set, it clears both the
+-tx_full and tbusy flags.
+-
+-IV. Notes
+-
+-IVb. References
+-
+-http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
+-http://www.digital.com (search for current 21*4* datasheets and "21X4 SROM")
+-http://www.national.com/pf/DP/DP83840A.html
+-
+-IVc. Errata
+-
+-*/
+-
+-/* A full-duplex map for media types. */
+-enum MediaIs {
+- MediaIsFD = 1, MediaAlwaysFD=2, MediaIsMII=4, MediaIsFx=8,
+- MediaIs100=16};
+-static const char media_cap[] =
+-{0,0,0,16, 3,19,16,24, 27,4,7,5, 0,20,23,20 };
+-
+-/* Offsets to the Command and Status Registers, "CSRs". All accesses
+- must be longword instructions and quadword aligned. */
+-enum xircom_offsets {
+- CSR0=0, CSR1=0x08, CSR2=0x10, CSR3=0x18, CSR4=0x20, CSR5=0x28,
+- CSR6=0x30, CSR7=0x38, CSR8=0x40, CSR9=0x48, CSR10=0x50, CSR11=0x58,
+- CSR12=0x60, CSR13=0x68, CSR14=0x70, CSR15=0x78, CSR16=0x04, };
+-
+-/* The bits in the CSR5 status registers, mostly interrupt sources. */
+-enum status_bits {
+- LinkChange=0x08000000,
+- NormalIntr=0x10000, NormalIntrMask=0x00014045,
+- AbnormalIntr=0x8000, AbnormalIntrMask=0x0a00a5a2,
+- ReservedIntrMask=0xe0001a18,
+- EarlyRxIntr=0x4000, BusErrorIntr=0x2000,
+- EarlyTxIntr=0x400, RxDied=0x100, RxNoBuf=0x80, RxIntr=0x40,
+- TxFIFOUnderflow=0x20, TxNoBuf=0x04, TxDied=0x02, TxIntr=0x01,
+-};
+-
+-enum csr0_control_bits {
+- EnableMWI=0x01000000, EnableMRL=0x00800000,
+- EnableMRM=0x00200000, EqualBusPrio=0x02,
+- SoftwareReset=0x01,
+-};
+-
+-enum csr6_control_bits {
+- ReceiveAllBit=0x40000000, AllMultiBit=0x80, PromiscBit=0x40,
+- HashFilterBit=0x01, FullDuplexBit=0x0200,
+- TxThresh10=0x400000, TxStoreForw=0x200000,
+- TxThreshMask=0xc000, TxThreshShift=14,
+- EnableTx=0x2000, EnableRx=0x02,
+- ReservedZeroMask=0x8d930134, ReservedOneMask=0x320c0000,
+- EnableTxRx=(EnableTx | EnableRx),
+-};
+-
+-
+-enum tbl_flag {
+- HAS_MII=1, HAS_ACPI=2,
+-};
+-static struct xircom_chip_table {
+- char *chip_name;
+- int valid_intrs; /* CSR7 interrupt enable settings */
+- int flags;
+-} xircom_tbl[] = {
+- { "Xircom Cardbus Adapter",
+- LinkChange | NormalIntr | AbnormalIntr | BusErrorIntr |
+- RxDied | RxNoBuf | RxIntr | TxFIFOUnderflow | TxNoBuf | TxDied | TxIntr,
+- HAS_MII | HAS_ACPI, },
+- { NULL, },
+-};
+-/* This matches the table above. */
+-enum chips {
+- X3201_3,
+-};
+-
+-
+-/* The Xircom Rx and Tx buffer descriptors. */
+-struct xircom_rx_desc {
+- s32 status;
+- s32 length;
+- u32 buffer1, buffer2;
+-};
+-
+-struct xircom_tx_desc {
+- s32 status;
+- s32 length;
+- u32 buffer1, buffer2; /* We use only buffer 1. */
+-};
+-
+-enum tx_desc0_status_bits {
+- Tx0DescOwned=0x80000000, Tx0DescError=0x8000, Tx0NoCarrier=0x0800,
+- Tx0LateColl=0x0200, Tx0ManyColl=0x0100, Tx0Underflow=0x02,
+-};
+-enum tx_desc1_status_bits {
+- Tx1ComplIntr=0x80000000, Tx1LastSeg=0x40000000, Tx1FirstSeg=0x20000000,
+- Tx1SetupPkt=0x08000000, Tx1DisableCRC=0x04000000, Tx1RingWrap=0x02000000,
+- Tx1ChainDesc=0x01000000, Tx1NoPad=0x800000, Tx1HashSetup=0x400000,
+- Tx1WholePkt=(Tx1FirstSeg | Tx1LastSeg),
+-};
+-enum rx_desc0_status_bits {
+- Rx0DescOwned=0x80000000, Rx0DescError=0x8000, Rx0NoSpace=0x4000,
+- Rx0Runt=0x0800, Rx0McastPkt=0x0400, Rx0FirstSeg=0x0200, Rx0LastSeg=0x0100,
+- Rx0HugeFrame=0x80, Rx0CRCError=0x02,
+- Rx0WholePkt=(Rx0FirstSeg | Rx0LastSeg),
+-};
+-enum rx_desc1_status_bits {
+- Rx1RingWrap=0x02000000, Rx1ChainDesc=0x01000000,
+-};
+-
+-struct xircom_private {
+- struct xircom_rx_desc rx_ring[RX_RING_SIZE];
+- struct xircom_tx_desc tx_ring[TX_RING_SIZE];
+- /* The saved address of a sent-in-place packet/buffer, for skfree(). */
+- struct sk_buff* tx_skbuff[TX_RING_SIZE];
+-
+- /* The X3201-3 requires 4-byte aligned tx bufs */
+- struct sk_buff* tx_aligned_skbuff[TX_RING_SIZE];
+-
+- /* The addresses of receive-in-place skbuffs. */
+- struct sk_buff* rx_skbuff[RX_RING_SIZE];
+- u16 setup_frame[PKT_SETUP_SZ / sizeof(u16)]; /* Pseudo-Tx frame to init address table. */
+- int chip_id;
+- struct net_device_stats stats;
+- unsigned int cur_rx, cur_tx; /* The next free ring entry */
+- unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
+- unsigned int tx_full:1; /* The Tx queue is full. */
+- unsigned int speed100:1;
+- unsigned int full_duplex:1; /* Full-duplex operation requested. */
+- unsigned int autoneg:1;
+- unsigned int default_port:4; /* Last dev->if_port value. */
+- unsigned int open:1;
+- unsigned int csr0; /* CSR0 setting. */
+- unsigned int csr6; /* Current CSR6 control settings. */
+- u16 to_advertise; /* NWay capabilities advertised. */
+- u16 advertising[4];
+- signed char phys[4], mii_cnt; /* MII device addresses. */
+- int saved_if_port;
+- struct pci_dev *pdev;
+- spinlock_t lock;
+-};
+-
+-static int mdio_read(struct net_device *dev, int phy_id, int location);
+-static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
+-static void xircom_up(struct net_device *dev);
+-static void xircom_down(struct net_device *dev);
+-static int xircom_open(struct net_device *dev);
+-static void xircom_tx_timeout(struct net_device *dev);
+-static void xircom_init_ring(struct net_device *dev);
+-static int xircom_start_xmit(struct sk_buff *skb, struct net_device *dev);
+-static int xircom_rx(struct net_device *dev);
+-static void xircom_media_change(struct net_device *dev);
+-static irqreturn_t xircom_interrupt(int irq, void *dev_instance);
+-static int xircom_close(struct net_device *dev);
+-static struct net_device_stats *xircom_get_stats(struct net_device *dev);
+-static int xircom_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+-static void set_rx_mode(struct net_device *dev);
+-static void check_duplex(struct net_device *dev);
+-static const struct ethtool_ops ops;
+-
+-
+-/* The Xircom cards are picky about when certain bits in CSR6 can be
+- manipulated. Keith Owens <kaos at ocs.com.au>. */
+-static void outl_CSR6(u32 newcsr6, long ioaddr)
+-{
+- const int strict_bits =
+- TxThresh10 | TxStoreForw | TxThreshMask | EnableTxRx | FullDuplexBit;
+- int csr5, csr5_22_20, csr5_19_17, currcsr6, attempts = 200;
+- unsigned long flags;
+- save_flags(flags);
+- cli();
+- /* mask out the reserved bits that always read 0 on the Xircom cards */
+- newcsr6 &= ~ReservedZeroMask;
+- /* or in the reserved bits that always read 1 */
+- newcsr6 |= ReservedOneMask;
+- currcsr6 = inl(ioaddr + CSR6);
+- if (((newcsr6 & strict_bits) == (currcsr6 & strict_bits)) ||
+- ((currcsr6 & ~EnableTxRx) == 0)) {
+- outl(newcsr6, ioaddr + CSR6); /* safe */
+- restore_flags(flags);
+- return;
+- }
+- /* make sure the transmitter and receiver are stopped first */
+- currcsr6 &= ~EnableTxRx;
+- while (1) {
+- csr5 = inl(ioaddr + CSR5);
+- if (csr5 == 0xffffffff)
+- break; /* cannot read csr5, card removed? */
+- csr5_22_20 = csr5 & 0x700000;
+- csr5_19_17 = csr5 & 0x0e0000;
+- if ((csr5_22_20 == 0 || csr5_22_20 == 0x600000) &&
+- (csr5_19_17 == 0 || csr5_19_17 == 0x80000 || csr5_19_17 == 0xc0000))
+- break; /* both are stopped or suspended */
+- if (!--attempts) {
+- printk(KERN_INFO DRV_NAME ": outl_CSR6 too many attempts,"
+- "csr5=0x%08x\n", csr5);
+- outl(newcsr6, ioaddr + CSR6); /* unsafe but do it anyway */
+- restore_flags(flags);
+- return;
+- }
+- outl(currcsr6, ioaddr + CSR6);
+- udelay(1);
+- }
+- /* now it is safe to change csr6 */
+- outl(newcsr6, ioaddr + CSR6);
+- restore_flags(flags);
+-}
+-
+-
+-static void __devinit read_mac_address(struct net_device *dev)
+-{
+- long ioaddr = dev->base_addr;
+- int i, j;
+- unsigned char tuple, link, data_id, data_count;
+-
+- /* Xircom has its address stored in the CIS;
+- * we access it through the boot rom interface for now
+- * this might not work, as the CIS is not parsed but I
+- * (danilo) use the offset I found on my card's CIS !!!
+- *
+- * Doug Ledford: I changed this routine around so that it
+- * walks the CIS memory space, parsing the config items, and
+- * finds the proper lan_node_id tuple and uses the data
+- * stored there.
+- */
+- outl(1 << 12, ioaddr + CSR9); /* enable boot rom access */
+- for (i = 0x100; i < 0x1f7; i += link+2) {
+- outl(i, ioaddr + CSR10);
+- tuple = inl(ioaddr + CSR9) & 0xff;
+- outl(i + 1, ioaddr + CSR10);
+- link = inl(ioaddr + CSR9) & 0xff;
+- outl(i + 2, ioaddr + CSR10);
+- data_id = inl(ioaddr + CSR9) & 0xff;
+- outl(i + 3, ioaddr + CSR10);
+- data_count = inl(ioaddr + CSR9) & 0xff;
+- if ( (tuple == 0x22) &&
+- (data_id == 0x04) && (data_count == 0x06) ) {
+- /*
+- * This is it. We have the data we want.
+- */
+- for (j = 0; j < 6; j++) {
+- outl(i + j + 4, ioaddr + CSR10);
+- dev->dev_addr[j] = inl(ioaddr + CSR9) & 0xff;
+- }
+- break;
+- } else if (link == 0) {
+- break;
+- }
+- }
+-}
+-
+-
+-/*
+- * locate the MII interfaces and initialize them.
+- * we disable full-duplex modes here,
+- * because we don't know how to handle them.
+- */
+-static void find_mii_transceivers(struct net_device *dev)
+-{
+- struct xircom_private *tp = netdev_priv(dev);
+- int phy, phy_idx;
+-
+- if (media_cap[tp->default_port] & MediaIsMII) {
+- u16 media2advert[] = { 0x20, 0x40, 0x03e0, 0x60, 0x80, 0x100, 0x200 };
+- tp->to_advertise = media2advert[tp->default_port - 9];
+- } else
+- tp->to_advertise =
+- /*ADVERTISE_100BASE4 | ADVERTISE_100FULL |*/ ADVERTISE_100HALF |
+- /*ADVERTISE_10FULL |*/ ADVERTISE_10HALF | ADVERTISE_CSMA;
+-
+- /* Find the connected MII xcvrs.
+- Doing this in open() would allow detecting external xcvrs later,
+- but takes much time. */
+- for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) {
+- int mii_status = mdio_read(dev, phy, MII_BMSR);
+- if ((mii_status & (BMSR_100BASE4 | BMSR_100HALF | BMSR_10HALF)) == BMSR_100BASE4 ||
+- ((mii_status & BMSR_100BASE4) == 0 &&
+- (mii_status & (BMSR_100FULL | BMSR_100HALF | BMSR_10FULL | BMSR_10HALF)) != 0)) {
+- int mii_reg0 = mdio_read(dev, phy, MII_BMCR);
+- int mii_advert = mdio_read(dev, phy, MII_ADVERTISE);
+- int reg4 = ((mii_status >> 6) & tp->to_advertise) | ADVERTISE_CSMA;
+- tp->phys[phy_idx] = phy;
+- tp->advertising[phy_idx++] = reg4;
+- printk(KERN_INFO "%s: MII transceiver #%d "
+- "config %4.4x status %4.4x advertising %4.4x.\n",
+- dev->name, phy, mii_reg0, mii_status, mii_advert);
+- }
+- }
+- tp->mii_cnt = phy_idx;
+- if (phy_idx == 0) {
+- printk(KERN_INFO "%s: ***WARNING***: No MII transceiver found!\n",
+- dev->name);
+- tp->phys[0] = 0;
+- }
+-}
+-
+-
+-/*
+- * To quote Arjan van de Ven:
+- * transceiver_voodoo() enables the external UTP plug thingy.
+- * it's called voodoo as I stole this code and cannot cross-reference
+- * it with the specification.
+- * Actually it seems to go like this:
+- * - GPIO2 enables the MII itself so we can talk to it. The MII gets reset
+- * so any prior MII settings are lost.
+- * - GPIO0 enables the TP port so the MII can talk to the network.
+- * - a software reset will reset both GPIO pins.
+- * I also moved the software reset here, because doing it in xircom_up()
+- * required enabling the GPIO pins each time, which reset the MII each time.
+- * Thus we couldn't control the MII -- which sucks because we don't know
+- * how to handle full-duplex modes so we *must* disable them.
+- */
+-static void transceiver_voodoo(struct net_device *dev)
+-{
+- struct xircom_private *tp = netdev_priv(dev);
+- long ioaddr = dev->base_addr;
+-
+- /* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
+- outl(SoftwareReset, ioaddr + CSR0);
+- udelay(2);
+-
+- /* Deassert reset. */
+- outl(tp->csr0, ioaddr + CSR0);
+-
+- /* Reset the xcvr interface and turn on heartbeat. */
+- outl(0x0008, ioaddr + CSR15);
+- udelay(5); /* The delays are Xircom-recommended to give the
+- * chipset time to reset the actual hardware
+- * on the PCMCIA card
+- */
+- outl(0xa8050000, ioaddr + CSR15);
+- udelay(5);
+- outl(0xa00f0000, ioaddr + CSR15);
+- udelay(5);
+-
+- outl_CSR6(0, ioaddr);
+- //outl_CSR6(FullDuplexBit, ioaddr);
+-}
+-
+-
+-static int __devinit xircom_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+-{
+- struct net_device *dev;
+- struct xircom_private *tp;
+- static int board_idx = -1;
+- int chip_idx = id->driver_data;
+- long ioaddr;
+- int i;
+-
+-/* when built into the kernel, we only print version if device is found */
+-#ifndef MODULE
+- static int printed_version;
+- if (!printed_version++)
+- printk(version);
+-#endif
+-
+- //printk(KERN_INFO "xircom_init_one(%s)\n", pci_name(pdev));
+-
+- board_idx++;
+-
+- if (pci_enable_device(pdev))
+- return -ENODEV;
+-
+- pci_set_master(pdev);
+-
+- ioaddr = pci_resource_start(pdev, 0);
+- dev = alloc_etherdev(sizeof(*tp));
+- if (!dev) {
+- printk (KERN_ERR DRV_NAME "%d: cannot alloc etherdev, aborting\n", board_idx);
+- return -ENOMEM;
+- }
+- SET_NETDEV_DEV(dev, &pdev->dev);
+-
+- dev->base_addr = ioaddr;
+- dev->irq = pdev->irq;
+-
+- if (pci_request_regions(pdev, dev->name)) {
+- printk (KERN_ERR DRV_NAME " %d: cannot reserve PCI resources, aborting\n", board_idx);
+- goto err_out_free_netdev;
+- }
+-
+- /* Bring the chip out of sleep mode.
+- Caution: Snooze mode does not work with some boards! */
+- if (xircom_tbl[chip_idx].flags & HAS_ACPI)
+- pci_write_config_dword(pdev, PCI_POWERMGMT, 0);
+-
+- /* Stop the chip's Tx and Rx processes. */
+- outl_CSR6(inl(ioaddr + CSR6) & ~EnableTxRx, ioaddr);
+- /* Clear the missed-packet counter. */
+- (volatile int)inl(ioaddr + CSR8);
+-
+- tp = netdev_priv(dev);
+-
+- spin_lock_init(&tp->lock);
+- tp->pdev = pdev;
+- tp->chip_id = chip_idx;
+- /* BugFixes: The 21143-TD hangs with PCI Write-and-Invalidate cycles. */
+- /* XXX: is this necessary for Xircom? */
+- tp->csr0 = csr0 & ~EnableMWI;
+-
+- pci_set_drvdata(pdev, dev);
+-
+- /* The lower four bits are the media type. */
+- if (board_idx >= 0 && board_idx < MAX_UNITS) {
+- tp->default_port = options[board_idx] & 15;
+- if ((options[board_idx] & 0x90) || full_duplex[board_idx] > 0)
+- tp->full_duplex = 1;
+- if (mtu[board_idx] > 0)
+- dev->mtu = mtu[board_idx];
+- }
+- if (dev->mem_start)
+- tp->default_port = dev->mem_start;
+- if (tp->default_port) {
+- if (media_cap[tp->default_port] & MediaAlwaysFD)
+- tp->full_duplex = 1;
+- }
+- if (tp->full_duplex)
+- tp->autoneg = 0;
+- else
+- tp->autoneg = 1;
+- tp->speed100 = 1;
+-
+- /* The Xircom-specific entries in the device structure. */
+- dev->open = &xircom_open;
+- dev->hard_start_xmit = &xircom_start_xmit;
+- dev->stop = &xircom_close;
+- dev->get_stats = &xircom_get_stats;
+- dev->do_ioctl = &xircom_ioctl;
+-#ifdef HAVE_MULTICAST
+- dev->set_multicast_list = &set_rx_mode;
+-#endif
+- dev->tx_timeout = xircom_tx_timeout;
+- dev->watchdog_timeo = TX_TIMEOUT;
+- SET_ETHTOOL_OPS(dev, &ops);
+-
+- transceiver_voodoo(dev);
+-
+- read_mac_address(dev);
+-
+- if (register_netdev(dev))
+- goto err_out_cleardev;
+-
+- printk(KERN_INFO "%s: %s rev %d at %#3lx,",
+- dev->name, xircom_tbl[chip_idx].chip_name, pdev->revision, ioaddr);
+- for (i = 0; i < 6; i++)
+- printk("%c%2.2X", i ? ':' : ' ', dev->dev_addr[i]);
+- printk(", IRQ %d.\n", dev->irq);
+-
+- if (xircom_tbl[chip_idx].flags & HAS_MII) {
+- find_mii_transceivers(dev);
+- check_duplex(dev);
+- }
+-
+- return 0;
+-
+-err_out_cleardev:
+- pci_set_drvdata(pdev, NULL);
+- pci_release_regions(pdev);
+-err_out_free_netdev:
+- free_netdev(dev);
+- return -ENODEV;
+-}
+-
+-
+-/* MII transceiver control section.
+- Read and write the MII registers using software-generated serial
+- MDIO protocol. See the MII specifications or DP83840A data sheet
+- for details. */
+-
+-/* The maximum data clock rate is 2.5 Mhz. The minimum timing is usually
+- met by back-to-back PCI I/O cycles, but we insert a delay to avoid
+- "overclocking" issues or future 66Mhz PCI. */
+-#define mdio_delay() inl(mdio_addr)
+-
+-/* Read and write the MII registers using software-generated serial
+- MDIO protocol. It is just different enough from the EEPROM protocol
+- to not share code. The maxium data clock rate is 2.5 Mhz. */
+-#define MDIO_SHIFT_CLK 0x10000
+-#define MDIO_DATA_WRITE0 0x00000
+-#define MDIO_DATA_WRITE1 0x20000
+-#define MDIO_ENB 0x00000 /* Ignore the 0x02000 databook setting. */
+-#define MDIO_ENB_IN 0x40000
+-#define MDIO_DATA_READ 0x80000
+-
+-static int mdio_read(struct net_device *dev, int phy_id, int location)
+-{
+- int i;
+- int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
+- int retval = 0;
+- long ioaddr = dev->base_addr;
+- long mdio_addr = ioaddr + CSR9;
+-
+- /* Establish sync by sending at least 32 logic ones. */
+- for (i = 32; i >= 0; i--) {
+- outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
+- mdio_delay();
+- outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
+- mdio_delay();
+- }
+- /* Shift the read command bits out. */
+- for (i = 15; i >= 0; i--) {
+- int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
+-
+- outl(MDIO_ENB | dataval, mdio_addr);
+- mdio_delay();
+- outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
+- mdio_delay();
+- }
+- /* Read the two transition, 16 data, and wire-idle bits. */
+- for (i = 19; i > 0; i--) {
+- outl(MDIO_ENB_IN, mdio_addr);
+- mdio_delay();
+- retval = (retval << 1) | ((inl(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
+- outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
+- mdio_delay();
+- }
+- return (retval>>1) & 0xffff;
+-}
+-
+-
+-static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
+-{
+- int i;
+- int cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
+- long ioaddr = dev->base_addr;
+- long mdio_addr = ioaddr + CSR9;
+-
+- /* Establish sync by sending 32 logic ones. */
+- for (i = 32; i >= 0; i--) {
+- outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
+- mdio_delay();
+- outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
+- mdio_delay();
+- }
+- /* Shift the command bits out. */
+- for (i = 31; i >= 0; i--) {
+- int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
+- outl(MDIO_ENB | dataval, mdio_addr);
+- mdio_delay();
+- outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
+- mdio_delay();
+- }
+- /* Clear out extra bits. */
+- for (i = 2; i > 0; i--) {
+- outl(MDIO_ENB_IN, mdio_addr);
+- mdio_delay();
+- outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
+- mdio_delay();
+- }
+- return;
+-}
+-
+-
+-static void
+-xircom_up(struct net_device *dev)
+-{
+- struct xircom_private *tp = netdev_priv(dev);
+- long ioaddr = dev->base_addr;
+- int i;
+-
+- xircom_init_ring(dev);
+- /* Clear the tx ring */
+- for (i = 0; i < TX_RING_SIZE; i++) {
+- tp->tx_skbuff[i] = NULL;
+- tp->tx_ring[i].status = 0;
+- }
+-
+- if (xircom_debug > 1)
+- printk(KERN_DEBUG "%s: xircom_up() irq %d.\n", dev->name, dev->irq);
+-
+- outl(virt_to_bus(tp->rx_ring), ioaddr + CSR3);
+- outl(virt_to_bus(tp->tx_ring), ioaddr + CSR4);
+-
+- tp->saved_if_port = dev->if_port;
+- if (dev->if_port == 0)
+- dev->if_port = tp->default_port;
+-
+- tp->csr6 = TxThresh10 /*| FullDuplexBit*/; /* XXX: why 10 and not 100? */
+-
+- set_rx_mode(dev);
+-
+- /* Start the chip's Tx to process setup frame. */
+- outl_CSR6(tp->csr6, ioaddr);
+- outl_CSR6(tp->csr6 | EnableTx, ioaddr);
+-
+- /* Acknowledge all outstanding interrupts sources */
+- outl(xircom_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5);
+- /* Enable interrupts by setting the interrupt mask. */
+- outl(xircom_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
+- /* Enable Rx */
+- outl_CSR6(tp->csr6 | EnableTxRx, ioaddr);
+- /* Rx poll demand */
+- outl(0, ioaddr + CSR2);
+-
+- /* Tell the net layer we're ready */
+- netif_start_queue (dev);
+-
+- /* Check current media state */
+- xircom_media_change(dev);
+-
+- if (xircom_debug > 2) {
+- printk(KERN_DEBUG "%s: Done xircom_up(), CSR0 %8.8x, CSR5 %8.8x CSR6 %8.8x.\n",
+- dev->name, inl(ioaddr + CSR0), inl(ioaddr + CSR5),
+- inl(ioaddr + CSR6));
+- }
+-}
+-
+-
+-static int
+-xircom_open(struct net_device *dev)
+-{
+- struct xircom_private *tp = netdev_priv(dev);
+-
+- if (request_irq(dev->irq, &xircom_interrupt, IRQF_SHARED, dev->name, dev))
+- return -EAGAIN;
+-
+- xircom_up(dev);
+- tp->open = 1;
+-
+- return 0;
+-}
+-
+-
+-static void xircom_tx_timeout(struct net_device *dev)
+-{
+- struct xircom_private *tp = netdev_priv(dev);
+- long ioaddr = dev->base_addr;
+-
+- if (media_cap[dev->if_port] & MediaIsMII) {
+- /* Do nothing -- the media monitor should handle this. */
+- if (xircom_debug > 1)
+- printk(KERN_WARNING "%s: Transmit timeout using MII device.\n",
+- dev->name);
+- }
+-
+-#if defined(way_too_many_messages)
+- if (xircom_debug > 3) {
+- int i;
+- for (i = 0; i < RX_RING_SIZE; i++) {
+- u8 *buf = (u8 *)(tp->rx_ring[i].buffer1);
+- int j;
+- printk(KERN_DEBUG "%2d: %8.8x %8.8x %8.8x %8.8x "
+- "%2.2x %2.2x %2.2x.\n",
+- i, (unsigned int)tp->rx_ring[i].status,
+- (unsigned int)tp->rx_ring[i].length,
+- (unsigned int)tp->rx_ring[i].buffer1,
+- (unsigned int)tp->rx_ring[i].buffer2,
+- buf[0], buf[1], buf[2]);
+- for (j = 0; buf[j] != 0xee && j < 1600; j++)
+- if (j < 100) printk(" %2.2x", buf[j]);
+- printk(" j=%d.\n", j);
+- }
+- printk(KERN_DEBUG " Rx ring %8.8x: ", (int)tp->rx_ring);
+- for (i = 0; i < RX_RING_SIZE; i++)
+- printk(" %8.8x", (unsigned int)tp->rx_ring[i].status);
+- printk("\n" KERN_DEBUG " Tx ring %8.8x: ", (int)tp->tx_ring);
+- for (i = 0; i < TX_RING_SIZE; i++)
+- printk(" %8.8x", (unsigned int)tp->tx_ring[i].status);
+- printk("\n");
+- }
+-#endif
+-
+- /* Stop and restart the chip's Tx/Rx processes . */
+- outl_CSR6(tp->csr6 | EnableRx, ioaddr);
+- outl_CSR6(tp->csr6 | EnableTxRx, ioaddr);
+- /* Trigger an immediate transmit demand. */
+- outl(0, ioaddr + CSR1);
+-
+- dev->trans_start = jiffies;
+- netif_wake_queue (dev);
+- tp->stats.tx_errors++;
+-}
+-
+-
+-/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
+-static void xircom_init_ring(struct net_device *dev)
+-{
+- struct xircom_private *tp = netdev_priv(dev);
+- int i;
+-
+- tp->tx_full = 0;
+- tp->cur_rx = tp->cur_tx = 0;
+- tp->dirty_rx = tp->dirty_tx = 0;
+-
+- for (i = 0; i < RX_RING_SIZE; i++) {
+- tp->rx_ring[i].status = 0;
+- tp->rx_ring[i].length = PKT_BUF_SZ;
+- tp->rx_ring[i].buffer2 = virt_to_bus(&tp->rx_ring[i+1]);
+- tp->rx_skbuff[i] = NULL;
+- }
+- /* Mark the last entry as wrapping the ring. */
+- tp->rx_ring[i-1].length = PKT_BUF_SZ | Rx1RingWrap;
+- tp->rx_ring[i-1].buffer2 = virt_to_bus(&tp->rx_ring[0]);
+-
+- for (i = 0; i < RX_RING_SIZE; i++) {
+- /* Note the receive buffer must be longword aligned.
+- dev_alloc_skb() provides 16 byte alignment. But do *not*
+- use skb_reserve() to align the IP header! */
+- struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ);
+- tp->rx_skbuff[i] = skb;
+- if (skb == NULL)
+- break;
+- skb->dev = dev; /* Mark as being used by this device. */
+- tp->rx_ring[i].status = Rx0DescOwned; /* Owned by Xircom chip */
+- tp->rx_ring[i].buffer1 = virt_to_bus(skb->data);
+- }
+- tp->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
+-
+- /* The Tx buffer descriptor is filled in as needed, but we
+- do need to clear the ownership bit. */
+- for (i = 0; i < TX_RING_SIZE; i++) {
+- tp->tx_skbuff[i] = NULL;
+- tp->tx_ring[i].status = 0;
+- tp->tx_ring[i].buffer2 = virt_to_bus(&tp->tx_ring[i+1]);
+- if (tp->chip_id == X3201_3)
+- tp->tx_aligned_skbuff[i] = dev_alloc_skb(PKT_BUF_SZ);
+- }
+- tp->tx_ring[i-1].buffer2 = virt_to_bus(&tp->tx_ring[0]);
+-}
+-
+-
+-static int
+-xircom_start_xmit(struct sk_buff *skb, struct net_device *dev)
+-{
+- struct xircom_private *tp = netdev_priv(dev);
+- int entry;
+- u32 flag;
+-
+- /* Caution: the write order is important here, set the base address
+- with the "ownership" bits last. */
+-
+- /* Calculate the next Tx descriptor entry. */
+- entry = tp->cur_tx % TX_RING_SIZE;
+-
+- tp->tx_skbuff[entry] = skb;
+- if (tp->chip_id == X3201_3) {
+- skb_copy_from_linear_data(skb,
+- tp->tx_aligned_skbuff[entry]->data,
+- skb->len);
+- tp->tx_ring[entry].buffer1 = virt_to_bus(tp->tx_aligned_skbuff[entry]->data);
+- } else
+- tp->tx_ring[entry].buffer1 = virt_to_bus(skb->data);
+-
+- if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE/2) {/* Typical path */
+- flag = Tx1WholePkt; /* No interrupt */
+- } else if (tp->cur_tx - tp->dirty_tx == TX_RING_SIZE/2) {
+- flag = Tx1WholePkt | Tx1ComplIntr; /* Tx-done intr. */
+- } else if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE - 2) {
+- flag = Tx1WholePkt; /* No Tx-done intr. */
+- } else {
+- /* Leave room for set_rx_mode() to fill entries. */
+- flag = Tx1WholePkt | Tx1ComplIntr; /* Tx-done intr. */
+- tp->tx_full = 1;
+- }
+- if (entry == TX_RING_SIZE - 1)
+- flag |= Tx1WholePkt | Tx1ComplIntr | Tx1RingWrap;
+-
+- tp->tx_ring[entry].length = skb->len | flag;
+- tp->tx_ring[entry].status = Tx0DescOwned; /* Pass ownership to the chip. */
+- tp->cur_tx++;
+- if (tp->tx_full)
+- netif_stop_queue (dev);
+- else
+- netif_wake_queue (dev);
+-
+- /* Trigger an immediate transmit demand. */
+- outl(0, dev->base_addr + CSR1);
+-
+- dev->trans_start = jiffies;
+-
+- return 0;
+-}
+-
+-
+-static void xircom_media_change(struct net_device *dev)
+-{
+- struct xircom_private *tp = netdev_priv(dev);
+- long ioaddr = dev->base_addr;
+- u16 reg0, reg1, reg4, reg5;
+- u32 csr6 = inl(ioaddr + CSR6), newcsr6;
+-
+- /* reset status first */
+- mdio_read(dev, tp->phys[0], MII_BMCR);
+- mdio_read(dev, tp->phys[0], MII_BMSR);
+-
+- reg0 = mdio_read(dev, tp->phys[0], MII_BMCR);
+- reg1 = mdio_read(dev, tp->phys[0], MII_BMSR);
+-
+- if (reg1 & BMSR_LSTATUS) {
+- /* link is up */
+- if (reg0 & BMCR_ANENABLE) {
+- /* autonegotiation is enabled */
+- reg4 = mdio_read(dev, tp->phys[0], MII_ADVERTISE);
+- reg5 = mdio_read(dev, tp->phys[0], MII_LPA);
+- if (reg4 & ADVERTISE_100FULL && reg5 & LPA_100FULL) {
+- tp->speed100 = 1;
+- tp->full_duplex = 1;
+- } else if (reg4 & ADVERTISE_100HALF && reg5 & LPA_100HALF) {
+- tp->speed100 = 1;
+- tp->full_duplex = 0;
+- } else if (reg4 & ADVERTISE_10FULL && reg5 & LPA_10FULL) {
+- tp->speed100 = 0;
+- tp->full_duplex = 1;
+- } else {
+- tp->speed100 = 0;
+- tp->full_duplex = 0;
+- }
+- } else {
+- /* autonegotiation is disabled */
+- if (reg0 & BMCR_SPEED100)
+- tp->speed100 = 1;
+- else
+- tp->speed100 = 0;
+- if (reg0 & BMCR_FULLDPLX)
+- tp->full_duplex = 1;
+- else
+- tp->full_duplex = 0;
+- }
+- printk(KERN_DEBUG "%s: Link is up, running at %sMbit %s-duplex\n",
+- dev->name,
+- tp->speed100 ? "100" : "10",
+- tp->full_duplex ? "full" : "half");
+- netif_carrier_on(dev);
+- newcsr6 = csr6 & ~FullDuplexBit;
+- if (tp->full_duplex)
+- newcsr6 |= FullDuplexBit;
+- if (newcsr6 != csr6)
+- outl_CSR6(newcsr6, ioaddr + CSR6);
+- } else {
+- printk(KERN_DEBUG "%s: Link is down\n", dev->name);
+- netif_carrier_off(dev);
+- }
+-}
+-
+-
+-static void check_duplex(struct net_device *dev)
+-{
+- struct xircom_private *tp = netdev_priv(dev);
+- u16 reg0;
+-
+- mdio_write(dev, tp->phys[0], MII_BMCR, BMCR_RESET);
+- udelay(500);
+- while (mdio_read(dev, tp->phys[0], MII_BMCR) & BMCR_RESET);
+-
+- reg0 = mdio_read(dev, tp->phys[0], MII_BMCR);
+- mdio_write(dev, tp->phys[0], MII_ADVERTISE, tp->advertising[0]);
+-
+- if (tp->autoneg) {
+- reg0 &= ~(BMCR_SPEED100 | BMCR_FULLDPLX);
+- reg0 |= BMCR_ANENABLE | BMCR_ANRESTART;
+- } else {
+- reg0 &= ~(BMCR_ANENABLE | BMCR_ANRESTART);
+- if (tp->speed100)
+- reg0 |= BMCR_SPEED100;
+- if (tp->full_duplex)
+- reg0 |= BMCR_FULLDPLX;
+- printk(KERN_DEBUG "%s: Link forced to %sMbit %s-duplex\n",
+- dev->name,
+- tp->speed100 ? "100" : "10",
+- tp->full_duplex ? "full" : "half");
+- }
+- mdio_write(dev, tp->phys[0], MII_BMCR, reg0);
+-}
+-
+-
+-/* The interrupt handler does all of the Rx thread work and cleans up
+- after the Tx thread. */
+-static irqreturn_t xircom_interrupt(int irq, void *dev_instance)
+-{
+- struct net_device *dev = dev_instance;
+- struct xircom_private *tp = netdev_priv(dev);
+- long ioaddr = dev->base_addr;
+- int csr5, work_budget = max_interrupt_work;
+- int handled = 0;
+-
+- spin_lock (&tp->lock);
+-
+- do {
+- csr5 = inl(ioaddr + CSR5);
+- /* Acknowledge all of the current interrupt sources ASAP. */
+- outl(csr5 & 0x0001ffff, ioaddr + CSR5);
+-
+- if (xircom_debug > 4)
+- printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n",
+- dev->name, csr5, inl(dev->base_addr + CSR5));
+-
+- if (csr5 == 0xffffffff)
+- break; /* all bits set, assume PCMCIA card removed */
+-
+- if ((csr5 & (NormalIntr|AbnormalIntr)) == 0)
+- break;
+-
+- handled = 1;
+-
+- if (csr5 & (RxIntr | RxNoBuf))
+- work_budget -= xircom_rx(dev);
+-
+- if (csr5 & (TxNoBuf | TxDied | TxIntr)) {
+- unsigned int dirty_tx;
+-
+- for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0;
+- dirty_tx++) {
+- int entry = dirty_tx % TX_RING_SIZE;
+- int status = tp->tx_ring[entry].status;
+-
+- if (status < 0)
+- break; /* It still hasn't been Txed */
+- /* Check for Rx filter setup frames. */
+- if (tp->tx_skbuff[entry] == NULL)
+- continue;
+-
+- if (status & Tx0DescError) {
+- /* There was an major error, log it. */
+-#ifndef final_version
+- if (xircom_debug > 1)
+- printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n",
+- dev->name, status);
+-#endif
+- tp->stats.tx_errors++;
+- if (status & Tx0ManyColl) {
+- tp->stats.tx_aborted_errors++;
+- }
+- if (status & Tx0NoCarrier) tp->stats.tx_carrier_errors++;
+- if (status & Tx0LateColl) tp->stats.tx_window_errors++;
+- if (status & Tx0Underflow) tp->stats.tx_fifo_errors++;
+- } else {
+- tp->stats.tx_bytes += tp->tx_ring[entry].length & 0x7ff;
+- tp->stats.collisions += (status >> 3) & 15;
+- tp->stats.tx_packets++;
+- }
+-
+- /* Free the original skb. */
+- dev_kfree_skb_irq(tp->tx_skbuff[entry]);
+- tp->tx_skbuff[entry] = NULL;
+- }
+-
+-#ifndef final_version
+- if (tp->cur_tx - dirty_tx > TX_RING_SIZE) {
+- printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
+- dev->name, dirty_tx, tp->cur_tx, tp->tx_full);
+- dirty_tx += TX_RING_SIZE;
+- }
+-#endif
+-
+- if (tp->tx_full &&
+- tp->cur_tx - dirty_tx < TX_RING_SIZE - 2)
+- /* The ring is no longer full */
+- tp->tx_full = 0;
+-
+- if (tp->tx_full)
+- netif_stop_queue (dev);
+- else
+- netif_wake_queue (dev);
+-
+- tp->dirty_tx = dirty_tx;
+- if (csr5 & TxDied) {
+- if (xircom_debug > 2)
+- printk(KERN_WARNING "%s: The transmitter stopped."
+- " CSR5 is %x, CSR6 %x, new CSR6 %x.\n",
+- dev->name, csr5, inl(ioaddr + CSR6), tp->csr6);
+- outl_CSR6(tp->csr6 | EnableRx, ioaddr);
+- outl_CSR6(tp->csr6 | EnableTxRx, ioaddr);
+- }
+- }
+-
+- /* Log errors. */
+- if (csr5 & AbnormalIntr) { /* Abnormal error summary bit. */
+- if (csr5 & LinkChange)
+- xircom_media_change(dev);
+- if (csr5 & TxFIFOUnderflow) {
+- if ((tp->csr6 & TxThreshMask) != TxThreshMask)
+- tp->csr6 += (1 << TxThreshShift); /* Bump up the Tx threshold */
+- else
+- tp->csr6 |= TxStoreForw; /* Store-n-forward. */
+- /* Restart the transmit process. */
+- outl_CSR6(tp->csr6 | EnableRx, ioaddr);
+- outl_CSR6(tp->csr6 | EnableTxRx, ioaddr);
+- }
+- if (csr5 & RxDied) { /* Missed a Rx frame. */
+- tp->stats.rx_errors++;
+- tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
+- outl_CSR6(tp->csr6 | EnableTxRx, ioaddr);
+- }
+- /* Clear all error sources, included undocumented ones! */
+- outl(0x0800f7ba, ioaddr + CSR5);
+- }
+- if (--work_budget < 0) {
+- if (xircom_debug > 1)
+- printk(KERN_WARNING "%s: Too much work during an interrupt, "
+- "csr5=0x%8.8x.\n", dev->name, csr5);
+- /* Acknowledge all interrupt sources. */
+- outl(0x8001ffff, ioaddr + CSR5);
+- break;
+- }
+- } while (1);
+-
+- if (xircom_debug > 3)
+- printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n",
+- dev->name, inl(ioaddr + CSR5));
+-
+- spin_unlock (&tp->lock);
+- return IRQ_RETVAL(handled);
+-}
+-
+-
+-static int
+-xircom_rx(struct net_device *dev)
+-{
+- struct xircom_private *tp = netdev_priv(dev);
+- int entry = tp->cur_rx % RX_RING_SIZE;
+- int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx;
+- int work_done = 0;
+-
+- if (xircom_debug > 4)
+- printk(KERN_DEBUG " In xircom_rx(), entry %d %8.8x.\n", entry,
+- tp->rx_ring[entry].status);
+- /* If we own the next entry, it's a new packet. Send it up. */
+- while (tp->rx_ring[entry].status >= 0) {
+- s32 status = tp->rx_ring[entry].status;
+-
+- if (xircom_debug > 5)
+- printk(KERN_DEBUG " In xircom_rx(), entry %d %8.8x.\n", entry,
+- tp->rx_ring[entry].status);
+- if (--rx_work_limit < 0)
+- break;
+- if ((status & 0x38008300) != 0x0300) {
+- if ((status & 0x38000300) != 0x0300) {
+- /* Ignore earlier buffers. */
+- if ((status & 0xffff) != 0x7fff) {
+- if (xircom_debug > 1)
+- printk(KERN_WARNING "%s: Oversized Ethernet frame "
+- "spanned multiple buffers, status %8.8x!\n",
+- dev->name, status);
+- tp->stats.rx_length_errors++;
+- }
+- } else if (status & Rx0DescError) {
+- /* There was a fatal error. */
+- if (xircom_debug > 2)
+- printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n",
+- dev->name, status);
+- tp->stats.rx_errors++; /* end of a packet.*/
+- if (status & (Rx0Runt | Rx0HugeFrame)) tp->stats.rx_length_errors++;
+- if (status & Rx0CRCError) tp->stats.rx_crc_errors++;
+- }
+- } else {
+- /* Omit the four octet CRC from the length. */
+- short pkt_len = ((status >> 16) & 0x7ff) - 4;
+- struct sk_buff *skb;
+-
+-#ifndef final_version
+- if (pkt_len > 1518) {
+- printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n",
+- dev->name, pkt_len, pkt_len);
+- pkt_len = 1518;
+- tp->stats.rx_length_errors++;
+- }
+-#endif
+- /* Check if the packet is long enough to accept without copying
+- to a minimally-sized skbuff. */
+- if (pkt_len < rx_copybreak
+- && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+- skb_reserve(skb, 2); /* 16 byte align the IP header */
+-#if ! defined(__alpha__)
+- skb_copy_to_linear_data(skb, bus_to_virt(tp->rx_ring[entry].buffer1),
+- pkt_len);
+- skb_put(skb, pkt_len);
+-#else
+- memcpy(skb_put(skb, pkt_len),
+- bus_to_virt(tp->rx_ring[entry].buffer1), pkt_len);
+-#endif
+- work_done++;
+- } else { /* Pass up the skb already on the Rx ring. */
+- skb_put(skb = tp->rx_skbuff[entry], pkt_len);
+- tp->rx_skbuff[entry] = NULL;
+- }
+- skb->protocol = eth_type_trans(skb, dev);
+- netif_rx(skb);
+- dev->last_rx = jiffies;
+- tp->stats.rx_packets++;
+- tp->stats.rx_bytes += pkt_len;
+- }
+- entry = (++tp->cur_rx) % RX_RING_SIZE;
+- }
+-
+- /* Refill the Rx ring buffers. */
+- for (; tp->cur_rx - tp->dirty_rx > 0; tp->dirty_rx++) {
+- entry = tp->dirty_rx % RX_RING_SIZE;
+- if (tp->rx_skbuff[entry] == NULL) {
+- struct sk_buff *skb;
+- skb = tp->rx_skbuff[entry] = dev_alloc_skb(PKT_BUF_SZ);
+- if (skb == NULL)
+- break;
+- skb->dev = dev; /* Mark as being used by this device. */
+- tp->rx_ring[entry].buffer1 = virt_to_bus(skb->data);
+- work_done++;
+- }
+- tp->rx_ring[entry].status = Rx0DescOwned;
+- }
+-
+- return work_done;
+-}
+-
+-
+-static void
+-xircom_down(struct net_device *dev)
+-{
+- long ioaddr = dev->base_addr;
+- struct xircom_private *tp = netdev_priv(dev);
+-
+- /* Disable interrupts by clearing the interrupt mask. */
+- outl(0, ioaddr + CSR7);
+- /* Stop the chip's Tx and Rx processes. */
+- outl_CSR6(inl(ioaddr + CSR6) & ~EnableTxRx, ioaddr);
+-
+- if (inl(ioaddr + CSR6) != 0xffffffff)
+- tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
+-
+- dev->if_port = tp->saved_if_port;
+-}
+-
+-
+-static int
+-xircom_close(struct net_device *dev)
+-{
+- long ioaddr = dev->base_addr;
+- struct xircom_private *tp = netdev_priv(dev);
+- int i;
+-
+- if (xircom_debug > 1)
+- printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
+- dev->name, inl(ioaddr + CSR5));
+-
+- netif_stop_queue(dev);
+-
+- if (netif_device_present(dev))
+- xircom_down(dev);
+-
+- free_irq(dev->irq, dev);
+-
+- /* Free all the skbuffs in the Rx queue. */
+- for (i = 0; i < RX_RING_SIZE; i++) {
+- struct sk_buff *skb = tp->rx_skbuff[i];
+- tp->rx_skbuff[i] = NULL;
+- tp->rx_ring[i].status = 0; /* Not owned by Xircom chip. */
+- tp->rx_ring[i].length = 0;
+- tp->rx_ring[i].buffer1 = 0xBADF00D0; /* An invalid address. */
+- if (skb) {
+- dev_kfree_skb(skb);
+- }
+- }
+- for (i = 0; i < TX_RING_SIZE; i++) {
+- if (tp->tx_skbuff[i])
+- dev_kfree_skb(tp->tx_skbuff[i]);
+- tp->tx_skbuff[i] = NULL;
+- }
+-
+- tp->open = 0;
+- return 0;
+-}
+-
+-
+-static struct net_device_stats *xircom_get_stats(struct net_device *dev)
+-{
+- struct xircom_private *tp = netdev_priv(dev);
+- long ioaddr = dev->base_addr;
+-
+- if (netif_device_present(dev))
+- tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
+-
+- return &tp->stats;
+-}
+-
+-static int xircom_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+-{
+- struct xircom_private *tp = netdev_priv(dev);
+- ecmd->supported =
+- SUPPORTED_10baseT_Half |
+- SUPPORTED_10baseT_Full |
+- SUPPORTED_100baseT_Half |
+- SUPPORTED_100baseT_Full |
+- SUPPORTED_Autoneg |
+- SUPPORTED_MII;
+-
+- ecmd->advertising = ADVERTISED_MII;
+- if (tp->advertising[0] & ADVERTISE_10HALF)
+- ecmd->advertising |= ADVERTISED_10baseT_Half;
+- if (tp->advertising[0] & ADVERTISE_10FULL)
+- ecmd->advertising |= ADVERTISED_10baseT_Full;
+- if (tp->advertising[0] & ADVERTISE_100HALF)
+- ecmd->advertising |= ADVERTISED_100baseT_Half;
+- if (tp->advertising[0] & ADVERTISE_100FULL)
+- ecmd->advertising |= ADVERTISED_100baseT_Full;
+- if (tp->autoneg) {
+- ecmd->advertising |= ADVERTISED_Autoneg;
+- ecmd->autoneg = AUTONEG_ENABLE;
+- } else
+- ecmd->autoneg = AUTONEG_DISABLE;
+-
+- ecmd->port = PORT_MII;
+- ecmd->transceiver = XCVR_INTERNAL;
+- ecmd->phy_address = tp->phys[0];
+- ecmd->speed = tp->speed100 ? SPEED_100 : SPEED_10;
+- ecmd->duplex = tp->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
+- ecmd->maxtxpkt = TX_RING_SIZE / 2;
+- ecmd->maxrxpkt = 0;
+- return 0;
+-}
+-
+-static int xircom_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+-{
+- struct xircom_private *tp = netdev_priv(dev);
+- u16 autoneg, speed100, full_duplex;
+-
+- autoneg = (ecmd->autoneg == AUTONEG_ENABLE);
+- speed100 = (ecmd->speed == SPEED_100);
+- full_duplex = (ecmd->duplex == DUPLEX_FULL);
+-
+- tp->autoneg = autoneg;
+- if (speed100 != tp->speed100 ||
+- full_duplex != tp->full_duplex) {
+- tp->speed100 = speed100;
+- tp->full_duplex = full_duplex;
+- /* change advertising bits */
+- tp->advertising[0] &= ~(ADVERTISE_10HALF |
+- ADVERTISE_10FULL |
+- ADVERTISE_100HALF |
+- ADVERTISE_100FULL |
+- ADVERTISE_100BASE4);
+- if (speed100) {
+- if (full_duplex)
+- tp->advertising[0] |= ADVERTISE_100FULL;
+- else
+- tp->advertising[0] |= ADVERTISE_100HALF;
+- } else {
+- if (full_duplex)
+- tp->advertising[0] |= ADVERTISE_10FULL;
+- else
+- tp->advertising[0] |= ADVERTISE_10HALF;
+- }
+- }
+- check_duplex(dev);
+- return 0;
+-}
+-
+-static void xircom_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+-{
+- struct xircom_private *tp = netdev_priv(dev);
+- strcpy(info->driver, DRV_NAME);
+- strcpy(info->version, DRV_VERSION);
+- strcpy(info->bus_info, pci_name(tp->pdev));
+-}
+-
+-static const struct ethtool_ops ops = {
+- .get_settings = xircom_get_settings,
+- .set_settings = xircom_set_settings,
+- .get_drvinfo = xircom_get_drvinfo,
+-};
+-
+-/* Provide ioctl() calls to examine the MII xcvr state. */
+-static int xircom_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+-{
+- struct xircom_private *tp = netdev_priv(dev);
+- u16 *data = (u16 *)&rq->ifr_ifru;
+- int phy = tp->phys[0] & 0x1f;
+- unsigned long flags;
+-
+- switch(cmd) {
+- /* Legacy mii-diag interface */
+- case SIOCGMIIPHY: /* Get address of MII PHY in use. */
+- if (tp->mii_cnt)
+- data[0] = phy;
+- else
+- return -ENODEV;
+- return 0;
+- case SIOCGMIIREG: /* Read MII PHY register. */
+- save_flags(flags);
+- cli();
+- data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
+- restore_flags(flags);
+- return 0;
+- case SIOCSMIIREG: /* Write MII PHY register. */
+- if (!capable(CAP_NET_ADMIN))
+- return -EPERM;
+- save_flags(flags);
+- cli();
+- if (data[0] == tp->phys[0]) {
+- u16 value = data[2];
+- switch (data[1]) {
+- case 0:
+- if (value & (BMCR_RESET | BMCR_ANENABLE))
+- /* Autonegotiation. */
+- tp->autoneg = 1;
+- else {
+- tp->full_duplex = (value & BMCR_FULLDPLX) ? 1 : 0;
+- tp->autoneg = 0;
+- }
+- break;
+- case 4:
+- tp->advertising[0] = value;
+- break;
+- }
+- check_duplex(dev);
+- }
+- mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+- restore_flags(flags);
+- return 0;
+- default:
+- return -EOPNOTSUPP;
+- }
+-
+- return -EOPNOTSUPP;
+-}
+-
+-/* Set or clear the multicast filter for this adaptor.
+- Note that we only use exclusion around actually queueing the
+- new frame, not around filling tp->setup_frame. This is non-deterministic
+- when re-entered but still correct. */
+-static void set_rx_mode(struct net_device *dev)
+-{
+- struct xircom_private *tp = netdev_priv(dev);
+- struct dev_mc_list *mclist;
+- long ioaddr = dev->base_addr;
+- int csr6 = inl(ioaddr + CSR6);
+- u16 *eaddrs, *setup_frm;
+- u32 tx_flags;
+- int i;
+-
+- tp->csr6 &= ~(AllMultiBit | PromiscBit | HashFilterBit);
+- csr6 &= ~(AllMultiBit | PromiscBit | HashFilterBit);
+- if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
+- tp->csr6 |= PromiscBit;
+- csr6 |= PromiscBit;
+- goto out;
+- }
+-
+- if ((dev->mc_count > 1000) || (dev->flags & IFF_ALLMULTI)) {
+- /* Too many to filter well -- accept all multicasts. */
+- tp->csr6 |= AllMultiBit;
+- csr6 |= AllMultiBit;
+- goto out;
+- }
+-
+- tx_flags = Tx1WholePkt | Tx1SetupPkt | PKT_SETUP_SZ;
+-
+- /* Note that only the low-address shortword of setup_frame is valid! */
+- setup_frm = tp->setup_frame;
+- mclist = dev->mc_list;
+-
+- /* Fill the first entry with our physical address. */
+- eaddrs = (u16 *)dev->dev_addr;
+- *setup_frm = cpu_to_le16(eaddrs[0]); setup_frm += 2;
+- *setup_frm = cpu_to_le16(eaddrs[1]); setup_frm += 2;
+- *setup_frm = cpu_to_le16(eaddrs[2]); setup_frm += 2;
+-
+- if (dev->mc_count > 14) { /* Must use a multicast hash table. */
+- u32 *hash_table = (u32 *)(tp->setup_frame + 4 * 12);
+- u32 hash, hash2;
+-
+- tx_flags |= Tx1HashSetup;
+- tp->csr6 |= HashFilterBit;
+- csr6 |= HashFilterBit;
+-
+- /* Fill the unused 3 entries with the broadcast address.
+- At least one entry *must* contain the broadcast address!!!*/
+- for (i = 0; i < 3; i++) {
+- *setup_frm = 0xffff; setup_frm += 2;
+- *setup_frm = 0xffff; setup_frm += 2;
+- *setup_frm = 0xffff; setup_frm += 2;
+- }
+-
+- /* Truly brain-damaged hash filter layout */
+- /* XXX: not sure if I should take the last or the first 9 bits */
+- for (i = 0; i < dev->mc_count; i++, mclist = mclist->next) {
+- u32 *hptr;
+- hash = ether_crc(ETH_ALEN, mclist->dmi_addr) & 0x1ff;
+- if (hash < 384) {
+- hash2 = hash + ((hash >> 4) << 4) +
+- ((hash >> 5) << 5);
+- } else {
+- hash -= 384;
+- hash2 = 64 + hash + (hash >> 4) * 80;
+- }
+- hptr = &hash_table[hash2 & ~0x1f];
+- *hptr |= cpu_to_le32(1 << (hash2 & 0x1f));
+- }
+- } else {
+- /* We have <= 14 mcast addresses so we can use Xircom's
+- wonderful 16-address perfect filter. */
+- for (i = 0; i < dev->mc_count; i++, mclist = mclist->next) {
+- eaddrs = (u16 *)mclist->dmi_addr;
+- *setup_frm = cpu_to_le16(eaddrs[0]); setup_frm += 2;
+- *setup_frm = cpu_to_le16(eaddrs[1]); setup_frm += 2;
+- *setup_frm = cpu_to_le16(eaddrs[2]); setup_frm += 2;
+- }
+- /* Fill the unused entries with the broadcast address.
+- At least one entry *must* contain the broadcast address!!!*/
+- for (; i < 15; i++) {
+- *setup_frm = 0xffff; setup_frm += 2;
+- *setup_frm = 0xffff; setup_frm += 2;
+- *setup_frm = 0xffff; setup_frm += 2;
+- }
+- }
+-
+- /* Now add this frame to the Tx list. */
+- if (tp->cur_tx - tp->dirty_tx > TX_RING_SIZE - 2) {
+- /* Same setup recently queued, we need not add it. */
+- /* XXX: Huh? All it means is that the Tx list is full...*/
+- } else {
+- unsigned long flags;
+- unsigned int entry;
+- int dummy = -1;
+-
+- save_flags(flags); cli();
+- entry = tp->cur_tx++ % TX_RING_SIZE;
+-
+- if (entry != 0) {
+- /* Avoid a chip errata by prefixing a dummy entry. */
+- tp->tx_skbuff[entry] = NULL;
+- tp->tx_ring[entry].length =
+- (entry == TX_RING_SIZE - 1) ? Tx1RingWrap : 0;
+- tp->tx_ring[entry].buffer1 = 0;
+- /* race with chip, set Tx0DescOwned later */
+- dummy = entry;
+- entry = tp->cur_tx++ % TX_RING_SIZE;
+- }
+-
+- tp->tx_skbuff[entry] = NULL;
+- /* Put the setup frame on the Tx list. */
+- if (entry == TX_RING_SIZE - 1)
+- tx_flags |= Tx1RingWrap; /* Wrap ring. */
+- tp->tx_ring[entry].length = tx_flags;
+- tp->tx_ring[entry].buffer1 = virt_to_bus(tp->setup_frame);
+- tp->tx_ring[entry].status = Tx0DescOwned;
+- if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) {
+- tp->tx_full = 1;
+- netif_stop_queue (dev);
+- }
+- if (dummy >= 0)
+- tp->tx_ring[dummy].status = Tx0DescOwned;
+- restore_flags(flags);
+- /* Trigger an immediate transmit demand. */
+- outl(0, ioaddr + CSR1);
+- }
+-
+-out:
+- outl_CSR6(csr6, ioaddr);
+-}
+-
+-
+-static struct pci_device_id xircom_pci_table[] = {
+- { 0x115D, 0x0003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, X3201_3 },
+- {0},
+-};
+-MODULE_DEVICE_TABLE(pci, xircom_pci_table);
+-
+-
+-#ifdef CONFIG_PM
+-static int xircom_suspend(struct pci_dev *pdev, pm_message_t state)
+-{
+- struct net_device *dev = pci_get_drvdata(pdev);
+- struct xircom_private *tp = netdev_priv(dev);
+- printk(KERN_INFO "xircom_suspend(%s)\n", dev->name);
+- if (tp->open)
+- xircom_down(dev);
+-
+- pci_save_state(pdev);
+- pci_disable_device(pdev);
+- pci_set_power_state(pdev, 3);
+-
+- return 0;
+-}
+-
+-
+-static int xircom_resume(struct pci_dev *pdev)
+-{
+- struct net_device *dev = pci_get_drvdata(pdev);
+- struct xircom_private *tp = netdev_priv(dev);
+- printk(KERN_INFO "xircom_resume(%s)\n", dev->name);
+-
+- pci_set_power_state(pdev,0);
+- pci_enable_device(pdev);
+- pci_restore_state(pdev);
+-
+- /* Bring the chip out of sleep mode.
+- Caution: Snooze mode does not work with some boards! */
+- if (xircom_tbl[tp->chip_id].flags & HAS_ACPI)
+- pci_write_config_dword(tp->pdev, PCI_POWERMGMT, 0);
+-
+- transceiver_voodoo(dev);
+- if (xircom_tbl[tp->chip_id].flags & HAS_MII)
+- check_duplex(dev);
+-
+- if (tp->open)
+- xircom_up(dev);
+- return 0;
+-}
+-#endif /* CONFIG_PM */
+-
+-
+-static void __devexit xircom_remove_one(struct pci_dev *pdev)
+-{
+- struct net_device *dev = pci_get_drvdata(pdev);
+-
+- printk(KERN_INFO "xircom_remove_one(%s)\n", dev->name);
+- unregister_netdev(dev);
+- pci_release_regions(pdev);
+- free_netdev(dev);
+- pci_set_drvdata(pdev, NULL);
+-}
+-
+-
+-static struct pci_driver xircom_driver = {
+- .name = DRV_NAME,
+- .id_table = xircom_pci_table,
+- .probe = xircom_init_one,
+- .remove = __devexit_p(xircom_remove_one),
+-#ifdef CONFIG_PM
+- .suspend = xircom_suspend,
+- .resume = xircom_resume
+-#endif /* CONFIG_PM */
+-};
+-
+-
+-static int __init xircom_init(void)
+-{
+-/* when a module, this is printed whether or not devices are found in probe */
+-#ifdef MODULE
+- printk(version);
+-#endif
+- return pci_register_driver(&xircom_driver);
+-}
+-
+-
+-static void __exit xircom_exit(void)
+-{
+- pci_unregister_driver(&xircom_driver);
+-}
+-
+-module_init(xircom_init)
+-module_exit(xircom_exit)
+-
+-/*
+- * Local variables:
+- * c-indent-level: 4
+- * c-basic-offset: 4
+- * tab-width: 4
+- * End:
+- */
+diff --git a/drivers/net/tun.c b/drivers/net/tun.c
+index 5b5d875..0ce07a3 100644
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -62,7 +62,9 @@
+ #include <linux/if_ether.h>
+ #include <linux/if_tun.h>
+ #include <linux/crc32.h>
++#include <linux/nsproxy.h>
+ #include <net/net_namespace.h>
++#include <net/netns/generic.h>
+
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+@@ -106,7 +108,11 @@ struct tun_struct {
+
+ /* Network device part of the driver */
+
+-static LIST_HEAD(tun_dev_list);
++static unsigned int tun_net_id;
++struct tun_net {
++ struct list_head dev_list;
++};
++
+ static const struct ethtool_ops tun_ethtool_ops;
+
+ /* Net device open. */
+@@ -471,14 +477,15 @@ static void tun_setup(struct net_device *dev)
+ dev->stop = tun_net_close;
+ dev->ethtool_ops = &tun_ethtool_ops;
+ dev->destructor = free_netdev;
++ dev->features |= NETIF_F_NETNS_LOCAL;
+ }
+
+-static struct tun_struct *tun_get_by_name(const char *name)
++static struct tun_struct *tun_get_by_name(struct tun_net *tn, const char *name)
+ {
+ struct tun_struct *tun;
+
+ ASSERT_RTNL();
+- list_for_each_entry(tun, &tun_dev_list, list) {
++ list_for_each_entry(tun, &tn->dev_list, list) {
+ if (!strncmp(tun->dev->name, name, IFNAMSIZ))
+ return tun;
+ }
+@@ -486,13 +493,15 @@ static struct tun_struct *tun_get_by_name(const char *name)
+ return NULL;
+ }
+
+-static int tun_set_iff(struct file *file, struct ifreq *ifr)
++static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
+ {
++ struct tun_net *tn;
+ struct tun_struct *tun;
+ struct net_device *dev;
+ int err;
+
+- tun = tun_get_by_name(ifr->ifr_name);
++ tn = net_generic(net, tun_net_id);
++ tun = tun_get_by_name(tn, ifr->ifr_name);
+ if (tun) {
+ if (tun->attached)
+ return -EBUSY;
+@@ -505,7 +514,7 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr)
+ !capable(CAP_NET_ADMIN))
+ return -EPERM;
+ }
+- else if (__dev_get_by_name(&init_net, ifr->ifr_name))
++ else if (__dev_get_by_name(net, ifr->ifr_name))
+ return -EINVAL;
+ else {
+ char *name;
+@@ -536,6 +545,7 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr)
+ if (!dev)
+ return -ENOMEM;
+
++ dev_net_set(dev, net);
+ tun = netdev_priv(dev);
+ tun->dev = dev;
+ tun->flags = flags;
+@@ -558,7 +568,7 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr)
+ if (err < 0)
+ goto err_free_dev;
+
+- list_add(&tun->list, &tun_dev_list);
++ list_add(&tun->list, &tn->dev_list);
+ }
+
+ DBG(KERN_INFO "%s: tun_set_iff\n", tun->dev->name);
+@@ -575,6 +585,7 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr)
+
+ file->private_data = tun;
+ tun->attached = 1;
++ get_net(dev_net(tun->dev));
+
+ strcpy(ifr->ifr_name, tun->dev->name);
+ return 0;
+@@ -603,7 +614,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
+ ifr.ifr_name[IFNAMSIZ-1] = '\0';
+
+ rtnl_lock();
+- err = tun_set_iff(file, &ifr);
++ err = tun_set_iff(current->nsproxy->net_ns, file, &ifr);
+ rtnl_unlock();
+
+ if (err)
+@@ -657,16 +668,23 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
+ break;
+
+ case TUNSETLINK:
++ {
++ int ret;
++
+ /* Only allow setting the type when the interface is down */
++ rtnl_lock();
+ if (tun->dev->flags & IFF_UP) {
+ DBG(KERN_INFO "%s: Linktype set failed because interface is up\n",
+ tun->dev->name);
+- return -EBUSY;
++ ret = -EBUSY;
+ } else {
+ tun->dev->type = (int) arg;
+ DBG(KERN_INFO "%s: linktype set to %d\n", tun->dev->name, tun->dev->type);
++ ret = 0;
+ }
+- break;
++ rtnl_unlock();
++ return ret;
++ }
+
+ #ifdef TUN_DEBUG
+ case TUNSETDEBUG:
+@@ -723,7 +741,12 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
+ case SIOCADDMULTI:
+ /** Add the specified group to the character device's multicast filter
+ * list. */
++ rtnl_lock();
++ netif_tx_lock_bh(tun->dev);
+ add_multi(tun->chr_filter, ifr.ifr_hwaddr.sa_data);
++ netif_tx_unlock_bh(tun->dev);
++ rtnl_unlock();
++
+ DBG(KERN_DEBUG "%s: add multi: %s\n",
+ tun->dev->name, print_mac(mac, ifr.ifr_hwaddr.sa_data));
+ return 0;
+@@ -731,7 +754,12 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
+ case SIOCDELMULTI:
+ /** Remove the specified group from the character device's multicast
+ * filter list. */
++ rtnl_lock();
++ netif_tx_lock_bh(tun->dev);
+ del_multi(tun->chr_filter, ifr.ifr_hwaddr.sa_data);
++ netif_tx_unlock_bh(tun->dev);
++ rtnl_unlock();
++
+ DBG(KERN_DEBUG "%s: del multi: %s\n",
+ tun->dev->name, print_mac(mac, ifr.ifr_hwaddr.sa_data));
+ return 0;
+@@ -790,6 +818,7 @@ static int tun_chr_close(struct inode *inode, struct file *file)
+ /* Detach from net device */
+ file->private_data = NULL;
+ tun->attached = 0;
++ put_net(dev_net(tun->dev));
+
+ /* Drop read queue */
+ skb_queue_purge(&tun->readq);
+@@ -909,32 +938,76 @@ static const struct ethtool_ops tun_ethtool_ops = {
+ .set_rx_csum = tun_set_rx_csum
+ };
+
+-static int __init tun_init(void)
++static int tun_init_net(struct net *net)
+ {
+- int ret = 0;
++ struct tun_net *tn;
+
+- printk(KERN_INFO "tun: %s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
+- printk(KERN_INFO "tun: %s\n", DRV_COPYRIGHT);
++ tn = kmalloc(sizeof(*tn), GFP_KERNEL);
++ if (tn == NULL)
++ return -ENOMEM;
+
+- ret = misc_register(&tun_miscdev);
+- if (ret)
+- printk(KERN_ERR "tun: Can't register misc device %d\n", TUN_MINOR);
+- return ret;
++ INIT_LIST_HEAD(&tn->dev_list);
++
++ if (net_assign_generic(net, tun_net_id, tn)) {
++ kfree(tn);
++ return -ENOMEM;
++ }
++
++ return 0;
+ }
+
+-static void tun_cleanup(void)
++static void tun_exit_net(struct net *net)
+ {
++ struct tun_net *tn;
+ struct tun_struct *tun, *nxt;
+
+- misc_deregister(&tun_miscdev);
++ tn = net_generic(net, tun_net_id);
+
+ rtnl_lock();
+- list_for_each_entry_safe(tun, nxt, &tun_dev_list, list) {
++ list_for_each_entry_safe(tun, nxt, &tn->dev_list, list) {
+ DBG(KERN_INFO "%s cleaned up\n", tun->dev->name);
+ unregister_netdevice(tun->dev);
+ }
+ rtnl_unlock();
+
++ kfree(tn);
++}
++
++static struct pernet_operations tun_net_ops = {
++ .init = tun_init_net,
++ .exit = tun_exit_net,
++};
++
++static int __init tun_init(void)
++{
++ int ret = 0;
++
++ printk(KERN_INFO "tun: %s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
++ printk(KERN_INFO "tun: %s\n", DRV_COPYRIGHT);
++
++ ret = register_pernet_gen_device(&tun_net_id, &tun_net_ops);
++ if (ret) {
++ printk(KERN_ERR "tun: Can't register pernet ops\n");
++ goto err_pernet;
++ }
++
++ ret = misc_register(&tun_miscdev);
++ if (ret) {
++ printk(KERN_ERR "tun: Can't register misc device %d\n", TUN_MINOR);
++ goto err_misc;
++ }
++ return 0;
++
++err_misc:
++ unregister_pernet_gen_device(tun_net_id, &tun_net_ops);
++err_pernet:
++ return ret;
++}
++
++static void tun_cleanup(void)
++{
++ misc_deregister(&tun_miscdev);
++ unregister_pernet_gen_device(tun_net_id, &tun_net_ops);
+ }
+
+ module_init(tun_init);
+diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
+index 333961b..c0dd25b 100644
+--- a/drivers/net/typhoon.c
++++ b/drivers/net/typhoon.c
+@@ -2183,7 +2183,6 @@ typhoon_resume(struct pci_dev *pdev)
+ }
+
+ netif_device_attach(dev);
+- netif_start_queue(dev);
+ return 0;
+
+ reset:
+diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
+index 0ee4c16..281ce3d 100644
+--- a/drivers/net/ucc_geth.c
++++ b/drivers/net/ucc_geth.c
+@@ -3853,7 +3853,13 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
+
+ ugeth_vdbg("%s: IN", __FUNCTION__);
+
+- prop = of_get_property(np, "device-id", NULL);
++ prop = of_get_property(np, "cell-index", NULL);
++ if (!prop) {
++ prop = of_get_property(np, "device-id", NULL);
++ if (!prop)
++ return -ENODEV;
++ }
++
+ ucc_num = *prop - 1;
+ if ((ucc_num < 0) || (ucc_num > 7))
+ return -ENODEV;
+@@ -3926,7 +3932,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
+ ug_info->uf_info.irq = irq_of_parse_and_map(np, 0);
+ fixed_link = of_get_property(np, "fixed-link", NULL);
+ if (fixed_link) {
+- ug_info->mdio_bus = 0;
++ snprintf(ug_info->mdio_bus, MII_BUS_ID_SIZE, "0");
+ ug_info->phy_address = fixed_link[0];
+ phy = NULL;
+ } else {
+@@ -3954,7 +3960,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
+ if (err)
+ return -1;
+
+- ug_info->mdio_bus = res.start;
++ snprintf(ug_info->mdio_bus, MII_BUS_ID_SIZE, "%x", res.start);
+ }
+
+ /* get the phy interface type, or default to MII */
+diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h
+index 4fb95b3..9f8b758 100644
+--- a/drivers/net/ucc_geth.h
++++ b/drivers/net/ucc_geth.h
+@@ -1156,7 +1156,7 @@ struct ucc_geth_info {
+ u16 pausePeriod;
+ u16 extensionField;
+ u8 phy_address;
+- u32 mdio_bus;
++ char mdio_bus[MII_BUS_ID_SIZE];
+ u8 weightfactor[NUM_TX_QUEUES];
+ u8 interruptcoalescingmaxvalue[NUM_RX_QUEUES];
+ u8 l2qt[UCC_GETH_VLAN_PRIORITY_MAX];
+diff --git a/drivers/net/ucc_geth_mii.c b/drivers/net/ucc_geth_mii.c
+index c69e654..2af4907 100644
+--- a/drivers/net/ucc_geth_mii.c
++++ b/drivers/net/ucc_geth_mii.c
+@@ -157,7 +157,7 @@ static int uec_mdio_probe(struct of_device *ofdev, const struct of_device_id *ma
+ if (err)
+ goto reg_map_fail;
+
+- new_bus->id = res.start;
++ snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", res.start);
+
+ new_bus->irq = kmalloc(32 * sizeof(int), GFP_KERNEL);
+
+@@ -203,9 +203,14 @@ static int uec_mdio_probe(struct of_device *ofdev, const struct of_device_id *ma
+ if ((res.start >= tempres.start) &&
+ (res.end <= tempres.end)) {
+ /* set this UCC to be the MII master */
+- const u32 *id = of_get_property(tempnp, "device-id", NULL);
+- if (id == NULL)
+- goto bus_register_fail;
++ const u32 *id;
++
++ id = of_get_property(tempnp, "cell-index", NULL);
++ if (!id) {
++ id = of_get_property(tempnp, "device-id", NULL);
++ if (!id)
++ goto bus_register_fail;
++ }
+
+ ucc_set_qe_mux_mii_mng(*id - 1);
+
+diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c
+index 01660f6..f7319d3 100644
+--- a/drivers/net/usb/dm9601.c
++++ b/drivers/net/usb/dm9601.c
+@@ -155,7 +155,7 @@ static void dm_write_reg_async(struct usbnet *dev, u8 reg, u8 value)
+ dm_write_async_helper(dev, reg, value, 0, NULL);
+ }
+
+-static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, u16 *value)
++static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 *value)
+ {
+ int ret, i;
+
+@@ -194,7 +194,7 @@ static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, u16 *value)
+ return ret;
+ }
+
+-static int dm_write_shared_word(struct usbnet *dev, int phy, u8 reg, u16 value)
++static int dm_write_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 value)
+ {
+ int ret, i;
+
+@@ -249,7 +249,7 @@ static int dm9601_get_eeprom(struct net_device *net,
+ struct ethtool_eeprom *eeprom, u8 * data)
+ {
+ struct usbnet *dev = netdev_priv(net);
+- u16 *ebuf = (u16 *) data;
++ __le16 *ebuf = (__le16 *) data;
+ int i;
+
+ /* access is 16bit */
+@@ -268,7 +268,7 @@ static int dm9601_mdio_read(struct net_device *netdev, int phy_id, int loc)
+ {
+ struct usbnet *dev = netdev_priv(netdev);
+
+- u16 res;
++ __le16 res;
+
+ if (phy_id) {
+ devdbg(dev, "Only internal phy supported");
+@@ -288,7 +288,7 @@ static void dm9601_mdio_write(struct net_device *netdev, int phy_id, int loc,
+ int val)
+ {
+ struct usbnet *dev = netdev_priv(netdev);
+- u16 res = cpu_to_le16(val);
++ __le16 res = cpu_to_le16(val);
+
+ if (phy_id) {
+ devdbg(dev, "Only internal phy supported");
+diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
+index 569ad8b..0dcfc03 100644
+--- a/drivers/net/usb/kaweth.c
++++ b/drivers/net/usb/kaweth.c
+@@ -58,7 +58,6 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/wait.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #include <asm/byteorder.h>
+
+ #undef DEBUG
+diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c
+index 369c731..21a7785 100644
+--- a/drivers/net/usb/rndis_host.c
++++ b/drivers/net/usb/rndis_host.c
+@@ -218,7 +218,7 @@ EXPORT_SYMBOL_GPL(rndis_command);
+ * ActiveSync 4.1 Windows driver.
+ */
+ static int rndis_query(struct usbnet *dev, struct usb_interface *intf,
+- void *buf, u32 oid, u32 in_len,
++ void *buf, __le32 oid, u32 in_len,
+ void **reply, int *reply_len)
+ {
+ int retval;
+@@ -283,7 +283,8 @@ generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags)
+ struct rndis_set_c *set_c;
+ struct rndis_halt *halt;
+ } u;
+- u32 tmp, phym_unspec, *phym;
++ u32 tmp, phym_unspec;
++ __le32 *phym;
+ int reply_len;
+ unsigned char *bp;
+
+diff --git a/drivers/net/veth.c b/drivers/net/veth.c
+index e2ad98b..31cd817 100644
+--- a/drivers/net/veth.c
++++ b/drivers/net/veth.c
+@@ -375,7 +375,7 @@ static int veth_newlink(struct net_device *dev,
+ else
+ snprintf(ifname, IFNAMSIZ, DRV_NAME "%%d");
+
+- peer = rtnl_create_link(dev->nd_net, ifname, &veth_link_ops, tbp);
++ peer = rtnl_create_link(dev_net(dev), ifname, &veth_link_ops, tbp);
+ if (IS_ERR(peer))
+ return PTR_ERR(peer);
+
+diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
+index cc0addb..6b8d882 100644
+--- a/drivers/net/via-velocity.c
++++ b/drivers/net/via-velocity.c
+@@ -605,7 +605,6 @@ static void __devinit velocity_get_options(struct velocity_opt *opts, int index,
+ static void velocity_init_cam_filter(struct velocity_info *vptr)
+ {
+ struct mac_regs __iomem * regs = vptr->mac_regs;
+- unsigned short vid;
+
+ /* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */
+ WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, ®s->MCFG);
+@@ -617,29 +616,33 @@ static void velocity_init_cam_filter(struct velocity_info *vptr)
+ mac_set_vlan_cam_mask(regs, vptr->vCAMmask);
+ mac_set_cam_mask(regs, vptr->mCAMmask);
+
+- /* Enable first VCAM */
++ /* Enable VCAMs */
+ if (vptr->vlgrp) {
+- for (vid = 0; vid < VLAN_VID_MASK; vid++) {
+- if (vlan_group_get_device(vptr->vlgrp, vid)) {
+- /* If Tagging option is enabled and
+- VLAN ID is not zero, then
+- turn on MCFG_RTGOPT also */
+- if (vid != 0)
+- WORD_REG_BITS_ON(MCFG_RTGOPT, ®s->MCFG);
++ unsigned int vid, i = 0;
++
++ if (!vlan_group_get_device(vptr->vlgrp, 0))
++ WORD_REG_BITS_ON(MCFG_RTGOPT, ®s->MCFG);
+
+- mac_set_vlan_cam(regs, 0, (u8 *) &vid);
++ for (vid = 1; (vid < VLAN_VID_MASK); vid++) {
++ if (vlan_group_get_device(vptr->vlgrp, vid)) {
++ mac_set_vlan_cam(regs, i, (u8 *) &vid);
++ vptr->vCAMmask[i / 8] |= 0x1 << (i % 8);
++ if (++i >= VCAM_SIZE)
++ break;
+ }
+ }
+- vptr->vCAMmask[0] |= 1;
+ mac_set_vlan_cam_mask(regs, vptr->vCAMmask);
+- } else {
+- u16 temp = 0;
+- mac_set_vlan_cam(regs, 0, (u8 *) &temp);
+- temp = 1;
+- mac_set_vlan_cam_mask(regs, (u8 *) &temp);
+ }
+ }
+
++static void velocity_vlan_rx_register(struct net_device *dev,
++ struct vlan_group *grp)
++{
++ struct velocity_info *vptr = netdev_priv(dev);
++
++ vptr->vlgrp = grp;
++}
++
+ static void velocity_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
+ {
+ struct velocity_info *vptr = netdev_priv(dev);
+@@ -959,11 +962,13 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
+
+ dev->vlan_rx_add_vid = velocity_vlan_rx_add_vid;
+ dev->vlan_rx_kill_vid = velocity_vlan_rx_kill_vid;
++ dev->vlan_rx_register = velocity_vlan_rx_register;
+
+ #ifdef VELOCITY_ZERO_COPY_SUPPORT
+ dev->features |= NETIF_F_SG;
+ #endif
+- dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER;
++ dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER |
++ NETIF_F_HW_VLAN_RX;
+
+ if (vptr->flags & VELOCITY_FLAGS_TX_CSUM)
+ dev->features |= NETIF_F_IP_CSUM;
+@@ -1597,8 +1602,13 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
+ skb_put(skb, pkt_len - 4);
+ skb->protocol = eth_type_trans(skb, vptr->dev);
+
++ if (vptr->vlgrp && (rd->rdesc0.RSR & RSR_DETAG)) {
++ vlan_hwaccel_rx(skb, vptr->vlgrp,
++ swab16(le16_to_cpu(rd->rdesc1.PQTAG)));
++ } else
++ netif_rx(skb);
++
+ stats->rx_bytes += pkt_len;
+- netif_rx(skb);
+
+ return 0;
+ }
+@@ -3460,21 +3470,22 @@ static int velocity_resume(struct pci_dev *pdev)
+ static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
+ {
+ struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
++ struct net_device *dev = ifa->ifa_dev->dev;
++ struct velocity_info *vptr;
++ unsigned long flags;
+
+- if (ifa) {
+- struct net_device *dev = ifa->ifa_dev->dev;
+- struct velocity_info *vptr;
+- unsigned long flags;
++ if (dev_net(dev) != &init_net)
++ return NOTIFY_DONE;
+
+- spin_lock_irqsave(&velocity_dev_list_lock, flags);
+- list_for_each_entry(vptr, &velocity_dev_list, list) {
+- if (vptr->dev == dev) {
+- velocity_get_ip(vptr);
+- break;
+- }
++ spin_lock_irqsave(&velocity_dev_list_lock, flags);
++ list_for_each_entry(vptr, &velocity_dev_list, list) {
++ if (vptr->dev == dev) {
++ velocity_get_ip(vptr);
++ break;
+ }
+- spin_unlock_irqrestore(&velocity_dev_list_lock, flags);
+ }
++ spin_unlock_irqrestore(&velocity_dev_list_lock, flags);
++
+ return NOTIFY_DONE;
+ }
+
+diff --git a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c
+index c4c8eab..c2cc42f 100644
+--- a/drivers/net/wan/c101.c
++++ b/drivers/net/wan/c101.c
+@@ -402,7 +402,7 @@ static int __init c101_init(void)
+ #ifdef MODULE
+ printk(KERN_INFO "c101: no card initialized\n");
+ #endif
+- return -ENOSYS; /* no parameters specified, abort */
++ return -EINVAL; /* no parameters specified, abort */
+ }
+
+ printk(KERN_INFO "%s\n", version);
+@@ -420,11 +420,11 @@ static int __init c101_init(void)
+ c101_run(irq, ram);
+
+ if (*hw == '\x0')
+- return first_card ? 0 : -ENOSYS;
++ return first_card ? 0 : -EINVAL;
+ }while(*hw++ == ':');
+
+ printk(KERN_ERR "c101: invalid hardware parameters\n");
+- return first_card ? 0 : -ENOSYS;
++ return first_card ? 0 : -EINVAL;
+ }
+
+
+diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
+index 1d706ea..45ddfc9 100644
+--- a/drivers/net/wan/cosa.c
++++ b/drivers/net/wan/cosa.c
+@@ -90,6 +90,7 @@
+ #include <linux/ioport.h>
+ #include <linux/netdevice.h>
+ #include <linux/spinlock.h>
++#include <linux/mutex.h>
+ #include <linux/device.h>
+
+ #undef COSA_SLOW_IO /* for testing purposes only */
+@@ -127,7 +128,8 @@ struct channel_data {
+ int (*tx_done)(struct channel_data *channel, int size);
+
+ /* Character device parts */
+- struct semaphore rsem, wsem;
++ struct mutex rlock;
++ struct semaphore wsem;
+ char *rxdata;
+ int rxsize;
+ wait_queue_head_t txwaitq, rxwaitq;
+@@ -807,7 +809,7 @@ static struct net_device_stats *cosa_net_stats(struct net_device *dev)
+
+ static void chardev_channel_init(struct channel_data *chan)
+ {
+- init_MUTEX(&chan->rsem);
++ mutex_init(&chan->rlock);
+ init_MUTEX(&chan->wsem);
+ }
+
+@@ -825,12 +827,12 @@ static ssize_t cosa_read(struct file *file,
+ cosa->name, cosa->firmware_status);
+ return -EPERM;
+ }
+- if (down_interruptible(&chan->rsem))
++ if (mutex_lock_interruptible(&chan->rlock))
+ return -ERESTARTSYS;
+
+ if ((chan->rxdata = kmalloc(COSA_MTU, GFP_DMA|GFP_KERNEL)) == NULL) {
+ printk(KERN_INFO "%s: cosa_read() - OOM\n", cosa->name);
+- up(&chan->rsem);
++ mutex_unlock(&chan->rlock);
+ return -ENOMEM;
+ }
+
+@@ -848,7 +850,7 @@ static ssize_t cosa_read(struct file *file,
+ remove_wait_queue(&chan->rxwaitq, &wait);
+ current->state = TASK_RUNNING;
+ spin_unlock_irqrestore(&cosa->lock, flags);
+- up(&chan->rsem);
++ mutex_unlock(&chan->rlock);
+ return -ERESTARTSYS;
+ }
+ }
+@@ -857,7 +859,7 @@ static ssize_t cosa_read(struct file *file,
+ kbuf = chan->rxdata;
+ count = chan->rxsize;
+ spin_unlock_irqrestore(&cosa->lock, flags);
+- up(&chan->rsem);
++ mutex_unlock(&chan->rlock);
+
+ if (copy_to_user(buf, kbuf, count)) {
+ kfree(kbuf);
+diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c
+index 96b2324..b142427 100644
+--- a/drivers/net/wan/dlci.c
++++ b/drivers/net/wan/dlci.c
+@@ -517,7 +517,7 @@ static int dlci_dev_event(struct notifier_block *unused,
+ {
+ struct net_device *dev = (struct net_device *) ptr;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ if (event == NETDEV_UNREGISTER) {
+diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c
+index 39951d0..9a83c9d 100644
+--- a/drivers/net/wan/hdlc.c
++++ b/drivers/net/wan/hdlc.c
+@@ -68,7 +68,7 @@ static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
+ {
+ struct hdlc_device *hdlc = dev_to_hdlc(dev);
+
+- if (dev->nd_net != &init_net) {
++ if (dev_net(dev) != &init_net) {
+ kfree_skb(skb);
+ return 0;
+ }
+@@ -105,7 +105,7 @@ static int hdlc_device_event(struct notifier_block *this, unsigned long event,
+ unsigned long flags;
+ int on;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ if (dev->get_stats != hdlc_get_stats)
+diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
+index c4ab032..520bb0b 100644
+--- a/drivers/net/wan/hdlc_fr.c
++++ b/drivers/net/wan/hdlc_fr.c
+@@ -1090,10 +1090,6 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
+ pvc_device *pvc = NULL;
+ struct net_device *dev;
+ int result, used;
+- char * prefix = "pvc%d";
+-
+- if (type == ARPHRD_ETHER)
+- prefix = "pvceth%d";
+
+ if ((pvc = add_pvc(frad, dlci)) == NULL) {
+ printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n",
+diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
+index 824df3b..b5860b9 100644
+--- a/drivers/net/wan/lapbether.c
++++ b/drivers/net/wan/lapbether.c
+@@ -91,7 +91,7 @@ static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
+ int len, err;
+ struct lapbethdev *lapbeth;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ goto drop;
+
+ if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+@@ -393,7 +393,7 @@ static int lapbeth_device_event(struct notifier_block *this,
+ struct lapbethdev *lapbeth;
+ struct net_device *dev = ptr;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ if (!dev_is_ethdev(dev))
+diff --git a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c
+index 61e24b7..29b4b94 100644
+--- a/drivers/net/wan/syncppp.c
++++ b/drivers/net/wan/syncppp.c
+@@ -1444,7 +1444,7 @@ static void sppp_print_bytes (u_char *p, u16 len)
+
+ static int sppp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *p, struct net_device *orig_dev)
+ {
+- if (dev->nd_net != &init_net) {
++ if (dev_net(dev) != &init_net) {
+ kfree_skb(skb);
+ return 0;
+ }
+diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
+index 714a6ca..fdf5aa8 100644
+--- a/drivers/net/wireless/Kconfig
++++ b/drivers/net/wireless/Kconfig
+@@ -146,12 +146,15 @@ config IPW2100
+ configure your card:
+
+ <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
++
++ It is recommended that you compile this driver as a module (M)
++ rather than built-in (Y). This driver requires firmware at device
++ initialization time, and when built-in this typically happens
++ before the filesystem is accessible (hence firmware will be
++ unavailable and initialization will fail). If you do choose to build
++ this driver into your kernel image, you can avoid this problem by
++ including the firmware and a firmware loader in an initramfs.
+
+- If you want to compile the driver as a module ( = code which can be
+- inserted in and removed from the running kernel whenever you want),
+- say M here and read <file:Documentation/kbuild/modules.txt>.
+- The module will be called ipw2100.ko.
+-
+ config IPW2100_MONITOR
+ bool "Enable promiscuous mode"
+ depends on IPW2100
+@@ -201,11 +204,14 @@ config IPW2200
+ configure your card:
+
+ <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
+-
+- If you want to compile the driver as a module ( = code which can be
+- inserted in and removed from the running kernel whenever you want),
+- say M here and read <file:Documentation/kbuild/modules.txt>.
+- The module will be called ipw2200.ko.
++
++ It is recommended that you compile this driver as a module (M)
++ rather than built-in (Y). This driver requires firmware at device
++ initialization time, and when built-in this typically happens
++ before the filesystem is accessible (hence firmware will be
++ unavailable and initialization will fail). If you do choose to build
++ this driver into your kernel image, you can avoid this problem by
++ including the firmware and a firmware loader in an initramfs.
+
+ config IPW2200_MONITOR
+ bool "Enable promiscuous mode"
+@@ -265,7 +271,6 @@ config LIBERTAS
+ tristate "Marvell 8xxx Libertas WLAN driver support"
+ depends on WLAN_80211
+ select WIRELESS_EXT
+- select IEEE80211
+ select FW_LOADER
+ ---help---
+ A library for Marvell Libertas 8xxx devices.
+@@ -278,7 +283,7 @@ config LIBERTAS_USB
+
+ config LIBERTAS_CS
+ tristate "Marvell Libertas 8385 CompactFlash 802.11b/g cards"
+- depends on LIBERTAS && PCMCIA && EXPERIMENTAL
++ depends on LIBERTAS && PCMCIA
+ select FW_LOADER
+ ---help---
+ A driver for Marvell Libertas 8385 CompactFlash devices.
+@@ -668,90 +673,10 @@ config ADM8211
+
+ Thanks to Infineon-ADMtek for their support of this driver.
+
+-config P54_COMMON
+- tristate "Softmac Prism54 support"
+- depends on MAC80211 && WLAN_80211 && FW_LOADER && EXPERIMENTAL
+- ---help---
+- This is common code for isl38xx based cards.
+- This module does nothing by itself - the USB/PCI frontends
+- also need to be enabled in order to support any devices.
+-
+- These devices require softmac firmware which can be found at
+- http://prism54.org/
+-
+- If you choose to build a module, it'll be called p54common.
+-
+-config P54_USB
+- tristate "Prism54 USB support"
+- depends on P54_COMMON && USB
+- select CRC32
+- ---help---
+- This driver is for USB isl38xx based wireless cards.
+- These are USB based adapters found in devices such as:
+-
+- 3COM 3CRWE254G72
+- SMC 2862W-G
+- Accton 802.11g WN4501 USB
+- Siemens Gigaset USB
+- Netgear WG121
+- Netgear WG111
+- Medion 40900, Roper Europe
+- Shuttle PN15, Airvast WM168g, IOGear GWU513
+- Linksys WUSB54G
+- Linksys WUSB54G Portable
+- DLink DWL-G120 Spinnaker
+- DLink DWL-G122
+- Belkin F5D7050 ver 1000
+- Cohiba Proto board
+- SMC 2862W-G version 2
+- U.S. Robotics U5 802.11g Adapter
+- FUJITSU E-5400 USB D1700
+- Sagem XG703A
+- DLink DWL-G120 Cohiba
+- Spinnaker Proto board
+- Linksys WUSB54AG
+- Inventel UR054G
+- Spinnaker DUT
+-
+- These devices require softmac firmware which can be found at
+- http://prism54.org/
+-
+- If you choose to build a module, it'll be called p54usb.
+-
+-config P54_PCI
+- tristate "Prism54 PCI support"
+- depends on P54_COMMON && PCI
+- ---help---
+- This driver is for PCI isl38xx based wireless cards.
+- This driver supports most devices that are supported by the
+- fullmac prism54 driver plus many devices which are not
+- supported by the fullmac driver/firmware.
+-
+- This driver requires softmac firmware which can be found at
+- http://prism54.org/
+-
+- If you choose to build a module, it'll be called p54pci.
+-
+-config ATH5K
+- tristate "Atheros 5xxx wireless cards support"
+- depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
+- ---help---
+- This module adds support for wireless adapters based on
+- Atheros 5xxx chipset.
+-
+- Currently the following chip versions are supported:
+-
+- MAC: AR5211 AR5212
+- PHY: RF5111/2111 RF5112/2112 RF5413/2413
+-
+- This driver uses the kernel's mac80211 subsystem.
+-
+- If you choose to build a module, it'll be called ath5k. Say M if
+- unsure.
+-
++source "drivers/net/wireless/p54/Kconfig"
++source "drivers/net/wireless/ath5k/Kconfig"
+ source "drivers/net/wireless/iwlwifi/Kconfig"
+ source "drivers/net/wireless/hostap/Kconfig"
+-source "drivers/net/wireless/bcm43xx/Kconfig"
+ source "drivers/net/wireless/b43/Kconfig"
+ source "drivers/net/wireless/b43legacy/Kconfig"
+ source "drivers/net/wireless/zd1211rw/Kconfig"
+diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
+index 091dfe2..c2642bc 100644
+--- a/drivers/net/wireless/Makefile
++++ b/drivers/net/wireless/Makefile
+@@ -35,7 +35,6 @@ obj-$(CONFIG_PCMCIA_ATMEL) += atmel_cs.o
+ obj-$(CONFIG_PRISM54) += prism54/
+
+ obj-$(CONFIG_HOSTAP) += hostap/
+-obj-$(CONFIG_BCM43XX) += bcm43xx/
+ obj-$(CONFIG_B43) += b43/
+ obj-$(CONFIG_B43LEGACY) += b43legacy/
+ obj-$(CONFIG_ZD1211RW) += zd1211rw/
+@@ -57,12 +56,9 @@ obj-$(CONFIG_RTL8187) += rtl8187.o
+
+ obj-$(CONFIG_ADM8211) += adm8211.o
+
+-obj-$(CONFIG_IWL3945) += iwlwifi/
+-obj-$(CONFIG_IWL4965) += iwlwifi/
++obj-$(CONFIG_IWLCORE) += iwlwifi/
+ obj-$(CONFIG_RT2X00) += rt2x00/
+
+-obj-$(CONFIG_P54_COMMON) += p54common.o
+-obj-$(CONFIG_P54_USB) += p54usb.o
+-obj-$(CONFIG_P54_PCI) += p54pci.o
++obj-$(CONFIG_P54_COMMON) += p54/
+
+ obj-$(CONFIG_ATH5K) += ath5k/
+diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
+index 7979618..5c0d2b0 100644
+--- a/drivers/net/wireless/adm8211.c
++++ b/drivers/net/wireless/adm8211.c
+@@ -48,6 +48,32 @@ static struct pci_device_id adm8211_pci_id_table[] __devinitdata = {
+ { 0 }
+ };
+
++static struct ieee80211_rate adm8211_rates[] = {
++ { .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
++ { .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
++ { .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
++ { .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
++ { .bitrate = 220, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, /* XX ?? */
++};
++
++static const struct ieee80211_channel adm8211_channels[] = {
++ { .center_freq = 2412},
++ { .center_freq = 2417},
++ { .center_freq = 2422},
++ { .center_freq = 2427},
++ { .center_freq = 2432},
++ { .center_freq = 2437},
++ { .center_freq = 2442},
++ { .center_freq = 2447},
++ { .center_freq = 2452},
++ { .center_freq = 2457},
++ { .center_freq = 2462},
++ { .center_freq = 2467},
++ { .center_freq = 2472},
++ { .center_freq = 2484},
++};
++
++
+ static void adm8211_eeprom_register_read(struct eeprom_93cx6 *eeprom)
+ {
+ struct adm8211_priv *priv = eeprom->data;
+@@ -155,17 +181,17 @@ static int adm8211_read_eeprom(struct ieee80211_hw *dev)
+ printk(KERN_DEBUG "%s (adm8211): Channel range: %d - %d\n",
+ pci_name(priv->pdev), (int)chan_range.min, (int)chan_range.max);
+
+- priv->modes[0].num_channels = chan_range.max - chan_range.min + 1;
+- priv->modes[0].channels = priv->channels;
++ BUILD_BUG_ON(sizeof(priv->channels) != sizeof(adm8211_channels));
+
+- memcpy(priv->channels, adm8211_channels, sizeof(adm8211_channels));
++ memcpy(priv->channels, adm8211_channels, sizeof(priv->channels));
++ priv->band.channels = priv->channels;
++ priv->band.n_channels = ARRAY_SIZE(adm8211_channels);
++ priv->band.bitrates = adm8211_rates;
++ priv->band.n_bitrates = ARRAY_SIZE(adm8211_rates);
+
+ for (i = 1; i <= ARRAY_SIZE(adm8211_channels); i++)
+- if (i >= chan_range.min && i <= chan_range.max)
+- priv->channels[i - 1].flag =
+- IEEE80211_CHAN_W_SCAN |
+- IEEE80211_CHAN_W_ACTIVE_SCAN |
+- IEEE80211_CHAN_W_IBSS;
++ if (i < chan_range.min || i > chan_range.max)
++ priv->channels[i - 1].flags |= IEEE80211_CHAN_DISABLED;
+
+ switch (priv->eeprom->specific_bbptype) {
+ case ADM8211_BBP_RFMD3000:
+@@ -347,7 +373,6 @@ static void adm8211_interrupt_rci(struct ieee80211_hw *dev)
+ unsigned int pktlen;
+ struct sk_buff *skb, *newskb;
+ unsigned int limit = priv->rx_ring_size;
+- static const u8 rate_tbl[] = {10, 20, 55, 110, 220};
+ u8 rssi, rate;
+
+ while (!(priv->rx_ring[entry].status & cpu_to_le32(RDES0_STATUS_OWN))) {
+@@ -425,12 +450,10 @@ static void adm8211_interrupt_rci(struct ieee80211_hw *dev)
+ else
+ rx_status.ssi = 100 - rssi;
+
+- if (rate <= 4)
+- rx_status.rate = rate_tbl[rate];
++ rx_status.rate_idx = rate;
+
+- rx_status.channel = priv->channel;
+- rx_status.freq = adm8211_channels[priv->channel - 1].freq;
+- rx_status.phymode = MODE_IEEE80211B;
++ rx_status.freq = adm8211_channels[priv->channel - 1].center_freq;
++ rx_status.band = IEEE80211_BAND_2GHZ;
+
+ ieee80211_rx_irqsafe(dev, skb, &rx_status);
+ }
+@@ -465,9 +488,6 @@ do { \
+ if (stsr & ADM8211_STSR_TCI)
+ adm8211_interrupt_tci(dev);
+
+- /*ADM8211_INT(LinkOn);*/
+- /*ADM8211_INT(LinkOff);*/
+-
+ ADM8211_INT(PCF);
+ ADM8211_INT(BCNTC);
+ ADM8211_INT(GPINT);
+@@ -477,7 +497,6 @@ do { \
+ ADM8211_INT(SQL);
+ ADM8211_INT(WEPTD);
+ ADM8211_INT(ATIME);
+- /*ADM8211_INT(TBTT);*/
+ ADM8211_INT(TEIS);
+ ADM8211_INT(FBE);
+ ADM8211_INT(REIS);
+@@ -485,9 +504,6 @@ do { \
+ ADM8211_INT(RPS);
+ ADM8211_INT(RDU);
+ ADM8211_INT(TUF);
+- /*ADM8211_INT(TRT);*/
+- /*ADM8211_INT(TLT);*/
+- /*ADM8211_INT(TDU);*/
+ ADM8211_INT(TPS);
+
+ return IRQ_HANDLED;
+@@ -1054,7 +1070,7 @@ static int adm8211_set_rate(struct ieee80211_hw *dev)
+ if (priv->pdev->revision != ADM8211_REV_BA) {
+ rate_buf[0] = ARRAY_SIZE(adm8211_rates);
+ for (i = 0; i < ARRAY_SIZE(adm8211_rates); i++)
+- rate_buf[i + 1] = (adm8211_rates[i].rate / 5) | 0x80;
++ rate_buf[i + 1] = (adm8211_rates[i].bitrate / 5) | 0x80;
+ } else {
+ /* workaround for rev BA specific bug */
+ rate_buf[0] = 0x04;
+@@ -1086,7 +1102,7 @@ static void adm8211_hw_init(struct ieee80211_hw *dev)
+ u32 reg;
+ u8 cline;
+
+- reg = le32_to_cpu(ADM8211_CSR_READ(PAR));
++ reg = ADM8211_CSR_READ(PAR);
+ reg |= ADM8211_PAR_MRLE | ADM8211_PAR_MRME;
+ reg &= ~(ADM8211_PAR_BAR | ADM8211_PAR_CAL);
+
+@@ -1303,9 +1319,10 @@ static int adm8211_set_ssid(struct ieee80211_hw *dev, u8 *ssid, size_t ssid_len)
+ static int adm8211_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
+ {
+ struct adm8211_priv *priv = dev->priv;
++ int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
+
+- if (conf->channel != priv->channel) {
+- priv->channel = conf->channel;
++ if (channel != priv->channel) {
++ priv->channel = channel;
+ adm8211_rf_set_channel(dev, priv->channel);
+ }
+
+@@ -1678,13 +1695,9 @@ static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
+ int plcp, dur, len, plcp_signal, short_preamble;
+ struct ieee80211_hdr *hdr;
+
+- if (control->tx_rate < 0) {
+- short_preamble = 1;
+- plcp_signal = -control->tx_rate;
+- } else {
+- short_preamble = 0;
+- plcp_signal = control->tx_rate;
+- }
++ short_preamble = !!(control->tx_rate->flags &
++ IEEE80211_TXCTL_SHORT_PREAMBLE);
++ plcp_signal = control->tx_rate->bitrate;
+
+ hdr = (struct ieee80211_hdr *)skb->data;
+ fc = le16_to_cpu(hdr->frame_control) & ~IEEE80211_FCTL_PROTECTED;
+@@ -1880,18 +1893,11 @@ static int __devinit adm8211_probe(struct pci_dev *pdev,
+ SET_IEEE80211_PERM_ADDR(dev, perm_addr);
+
+ dev->extra_tx_headroom = sizeof(struct adm8211_tx_hdr);
+- dev->flags = IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED;
+- /* IEEE80211_HW_RX_INCLUDES_FCS in promisc mode */
++ /* dev->flags = IEEE80211_HW_RX_INCLUDES_FCS in promisc mode */
+
+ dev->channel_change_time = 1000;
+ dev->max_rssi = 100; /* FIXME: find better value */
+
+- priv->modes[0].mode = MODE_IEEE80211B;
+- /* channel info filled in by adm8211_read_eeprom */
+- memcpy(priv->rates, adm8211_rates, sizeof(adm8211_rates));
+- priv->modes[0].num_rates = ARRAY_SIZE(adm8211_rates);
+- priv->modes[0].rates = priv->rates;
+-
+ dev->queues = 1; /* ADM8211C supports more, maybe ADM8211B too */
+
+ priv->retry_limit = 3;
+@@ -1917,14 +1923,9 @@ static int __devinit adm8211_probe(struct pci_dev *pdev,
+ goto err_free_desc;
+ }
+
+- priv->channel = priv->modes[0].channels[0].chan;
++ priv->channel = 1;
+
+- err = ieee80211_register_hwmode(dev, &priv->modes[0]);
+- if (err) {
+- printk(KERN_ERR "%s (adm8211): Can't register hwmode\n",
+- pci_name(pdev));
+- goto err_free_desc;
+- }
++ dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
+
+ err = ieee80211_register_hw(dev);
+ if (err) {
+diff --git a/drivers/net/wireless/adm8211.h b/drivers/net/wireless/adm8211.h
+index ef326fe..8d7c564 100644
+--- a/drivers/net/wireless/adm8211.h
++++ b/drivers/net/wireless/adm8211.h
+@@ -534,61 +534,6 @@ struct adm8211_eeprom {
+ u8 cis_data[0]; /* 0x80, 384 bytes */
+ } __attribute__ ((packed));
+
+-static const struct ieee80211_rate adm8211_rates[] = {
+- { .rate = 10,
+- .val = 10,
+- .val2 = -10,
+- .flags = IEEE80211_RATE_CCK_2 },
+- { .rate = 20,
+- .val = 20,
+- .val2 = -20,
+- .flags = IEEE80211_RATE_CCK_2 },
+- { .rate = 55,
+- .val = 55,
+- .val2 = -55,
+- .flags = IEEE80211_RATE_CCK_2 },
+- { .rate = 110,
+- .val = 110,
+- .val2 = -110,
+- .flags = IEEE80211_RATE_CCK_2 }
+-};
+-
+-struct ieee80211_chan_range {
+- u8 min;
+- u8 max;
+-};
+-
+-static const struct ieee80211_channel adm8211_channels[] = {
+- { .chan = 1,
+- .freq = 2412},
+- { .chan = 2,
+- .freq = 2417},
+- { .chan = 3,
+- .freq = 2422},
+- { .chan = 4,
+- .freq = 2427},
+- { .chan = 5,
+- .freq = 2432},
+- { .chan = 6,
+- .freq = 2437},
+- { .chan = 7,
+- .freq = 2442},
+- { .chan = 8,
+- .freq = 2447},
+- { .chan = 9,
+- .freq = 2452},
+- { .chan = 10,
+- .freq = 2457},
+- { .chan = 11,
+- .freq = 2462},
+- { .chan = 12,
+- .freq = 2467},
+- { .chan = 13,
+- .freq = 2472},
+- { .chan = 14,
+- .freq = 2484},
+-};
+-
+ struct adm8211_priv {
+ struct pci_dev *pdev;
+ spinlock_t lock;
+@@ -603,9 +548,8 @@ struct adm8211_priv {
+ unsigned int cur_tx, dirty_tx, cur_rx;
+
+ struct ieee80211_low_level_stats stats;
+- struct ieee80211_hw_mode modes[1];
+- struct ieee80211_channel channels[ARRAY_SIZE(adm8211_channels)];
+- struct ieee80211_rate rates[ARRAY_SIZE(adm8211_rates)];
++ struct ieee80211_supported_band band;
++ struct ieee80211_channel channels[14];
+ int mode;
+
+ int channel;
+@@ -643,6 +587,11 @@ struct adm8211_priv {
+ } transceiver_type;
+ };
+
++struct ieee80211_chan_range {
++ u8 min;
++ u8 max;
++};
++
+ static const struct ieee80211_chan_range cranges[] = {
+ {1, 11}, /* FCC */
+ {1, 11}, /* IC */
+diff --git a/drivers/net/wireless/ath5k/Kconfig b/drivers/net/wireless/ath5k/Kconfig
+new file mode 100644
+index 0000000..f1f2aea
+--- /dev/null
++++ b/drivers/net/wireless/ath5k/Kconfig
+@@ -0,0 +1,37 @@
++config ATH5K
++ tristate "Atheros 5xxx wireless cards support"
++ depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
++ ---help---
++ This module adds support for wireless adapters based on
++ Atheros 5xxx chipset.
++
++ Currently the following chip versions are supported:
++
++ MAC: AR5211 AR5212
++ PHY: RF5111/2111 RF5112/2112 RF5413/2413
++
++ This driver uses the kernel's mac80211 subsystem.
++
++ If you choose to build a module, it'll be called ath5k. Say M if
++ unsure.
++
++config ATH5K_DEBUG
++ bool "Atheros 5xxx debugging"
++ depends on ATH5K
++ ---help---
++ Atheros 5xxx debugging messages.
++
++ Say Y, if and you will get debug options for ath5k.
++ To use this, you need to mount debugfs:
++
++ mkdir /debug/
++ mount -t debugfs debug /debug/
++
++ You will get access to files under:
++ /debug/ath5k/phy0/
++
++ To enable debug, pass the debug level to the debug module
++ parameter. For example:
++
++ modprobe ath5k debug=0x00000400
++
+diff --git a/drivers/net/wireless/ath5k/Makefile b/drivers/net/wireless/ath5k/Makefile
+index 321641f..564ecd0 100644
+--- a/drivers/net/wireless/ath5k/Makefile
++++ b/drivers/net/wireless/ath5k/Makefile
+@@ -1,2 +1,6 @@
+-ath5k-objs = base.o hw.o regdom.o initvals.o phy.o debug.o
+-obj-$(CONFIG_ATH5K) += ath5k.o
++ath5k-y += base.o
++ath5k-y += hw.o
++ath5k-y += initvals.o
++ath5k-y += phy.o
++ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o
++obj-$(CONFIG_ATH5K) += ath5k.o
+diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h
+index 69dea33..ba35c30 100644
+--- a/drivers/net/wireless/ath5k/ath5k.h
++++ b/drivers/net/wireless/ath5k/ath5k.h
+@@ -30,7 +30,6 @@
+ #include <net/mac80211.h>
+
+ #include "hw.h"
+-#include "regdom.h"
+
+ /* PCI IDs */
+ #define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */
+@@ -141,7 +140,9 @@ enum ath5k_radio {
+ AR5K_RF5110 = 0,
+ AR5K_RF5111 = 1,
+ AR5K_RF5112 = 2,
+- AR5K_RF5413 = 3,
++ AR5K_RF2413 = 3,
++ AR5K_RF5413 = 4,
++ AR5K_RF2425 = 5,
+ };
+
+ /*
+@@ -169,12 +170,15 @@ struct ath5k_srev_name {
+ #define AR5K_SREV_VER_AR5212 0x50
+ #define AR5K_SREV_VER_AR5213 0x55
+ #define AR5K_SREV_VER_AR5213A 0x59
+-#define AR5K_SREV_VER_AR2424 0xa0
+-#define AR5K_SREV_VER_AR5424 0xa3
++#define AR5K_SREV_VER_AR2413 0x78
++#define AR5K_SREV_VER_AR2414 0x79
++#define AR5K_SREV_VER_AR2424 0xa0 /* PCI-E */
++#define AR5K_SREV_VER_AR5424 0xa3 /* PCI-E */
+ #define AR5K_SREV_VER_AR5413 0xa4
+ #define AR5K_SREV_VER_AR5414 0xa5
+-#define AR5K_SREV_VER_AR5416 0xc0 /* ? */
+-#define AR5K_SREV_VER_AR5418 0xca
++#define AR5K_SREV_VER_AR5416 0xc0 /* PCI-E */
++#define AR5K_SREV_VER_AR5418 0xca /* PCI-E */
++#define AR5K_SREV_VER_AR2425 0xe2 /* PCI-E */
+
+ #define AR5K_SREV_RAD_5110 0x00
+ #define AR5K_SREV_RAD_5111 0x10
+@@ -184,8 +188,9 @@ struct ath5k_srev_name {
+ #define AR5K_SREV_RAD_5112A 0x35
+ #define AR5K_SREV_RAD_2112 0x40
+ #define AR5K_SREV_RAD_2112A 0x45
++#define AR5K_SREV_RAD_SC0 0x56 /* Found on 2413/2414 */
+ #define AR5K_SREV_RAD_SC1 0x63 /* Found on 5413/5414 */
+-#define AR5K_SREV_RAD_SC2 0xa2 /* Found on 2424/5424 */
++#define AR5K_SREV_RAD_SC2 0xa2 /* Found on 2424-5/5424 */
+ #define AR5K_SREV_RAD_5133 0xc0 /* MIMO found on 5418 */
+
+ /* IEEE defs */
+@@ -251,26 +256,31 @@ struct ath5k_srev_name {
+ */
+ #define MODULATION_TURBO 0x00000080
+
+-enum ath5k_vendor_mode {
+- MODE_ATHEROS_TURBO = NUM_IEEE80211_MODES+1,
+- MODE_ATHEROS_TURBOG
++enum ath5k_driver_mode {
++ AR5K_MODE_11A = 0,
++ AR5K_MODE_11A_TURBO = 1,
++ AR5K_MODE_11B = 2,
++ AR5K_MODE_11G = 3,
++ AR5K_MODE_11G_TURBO = 4,
++ AR5K_MODE_XR = 0,
++ AR5K_MODE_MAX = 5
+ };
+
+-/* Number of supported mac80211 enum ieee80211_phymode modes by this driver */
+-#define NUM_DRIVER_MODES 3
+-
+ /* adding this flag to rate_code enables short preamble, see ar5212_reg.h */
+ #define AR5K_SET_SHORT_PREAMBLE 0x04
+
+-#define HAS_SHPREAMBLE(_ix) (rt->rates[_ix].modulation == IEEE80211_RATE_CCK_2)
+-#define SHPREAMBLE_FLAG(_ix) (HAS_SHPREAMBLE(_ix) ? AR5K_SET_SHORT_PREAMBLE : 0)
++#define HAS_SHPREAMBLE(_ix) \
++ (rt->rates[_ix].modulation == IEEE80211_RATE_SHORT_PREAMBLE)
++#define SHPREAMBLE_FLAG(_ix) \
++ (HAS_SHPREAMBLE(_ix) ? AR5K_SET_SHORT_PREAMBLE : 0)
++
+
+ /****************\
+ TX DEFINITIONS
+ \****************/
+
+ /*
+- * Tx Descriptor
++ * TX Status
+ */
+ struct ath5k_tx_status {
+ u16 ts_seqnum;
+@@ -418,7 +428,7 @@ enum ath5k_dmasize {
+ \****************/
+
+ /*
+- * Rx Descriptor
++ * RX Status
+ */
+ struct ath5k_rx_status {
+ u16 rs_datalen;
+@@ -440,16 +450,6 @@ struct ath5k_rx_status {
+ #define AR5K_RXKEYIX_INVALID ((u8) - 1)
+ #define AR5K_TXKEYIX_INVALID ((u32) - 1)
+
+-struct ath5k_mib_stats {
+- u32 ackrcv_bad;
+- u32 rts_bad;
+- u32 rts_good;
+- u32 fcs_bad;
+- u32 beacons;
+-};
+-
+-
+-
+
+ /**************************\
+ BEACON TIMERS DEFINITIONS
+@@ -492,29 +492,23 @@ struct ath5k_beacon_state {
+ #define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10)
+
+
+-
+ /********************\
+ COMMON DEFINITIONS
+ \********************/
+
+ /*
+- * Atheros descriptor
++ * Atheros hardware descriptor
++ * This is read and written to by the hardware
+ */
+ struct ath5k_desc {
+- u32 ds_link;
+- u32 ds_data;
+- u32 ds_ctl0;
+- u32 ds_ctl1;
+- u32 ds_hw[4];
++ u32 ds_link; /* physical address of the next descriptor */
++ u32 ds_data; /* physical address of data buffer (skb) */
+
+ union {
+- struct ath5k_rx_status rx;
+- struct ath5k_tx_status tx;
+- } ds_us;
+-
+-#define ds_rxstat ds_us.rx
+-#define ds_txstat ds_us.tx
+-
++ struct ath5k_hw_5210_tx_desc ds_tx5210;
++ struct ath5k_hw_5212_tx_desc ds_tx5212;
++ struct ath5k_hw_all_rx_desc ds_rx;
++ } ud;
+ } __packed;
+
+ #define AR5K_RXDESC_INTREQ 0x0020
+@@ -560,8 +554,8 @@ struct ath5k_desc {
+ * Used internaly in OpenHAL (ar5211.c/ar5212.c
+ * for reset_tx_queue). Also see struct struct ieee80211_channel.
+ */
+-#define IS_CHAN_XR(_c) ((_c.val & CHANNEL_XR) != 0)
+-#define IS_CHAN_B(_c) ((_c.val & CHANNEL_B) != 0)
++#define IS_CHAN_XR(_c) ((_c.hw_value & CHANNEL_XR) != 0)
++#define IS_CHAN_B(_c) ((_c.hw_value & CHANNEL_B) != 0)
+
+ /*
+ * The following structure will be used to map 2GHz channels to
+@@ -584,7 +578,7 @@ struct ath5k_athchan_2ghz {
+
+ /**
+ * struct ath5k_rate - rate structure
+- * @valid: is this a valid rate for the current mode
++ * @valid: is this a valid rate for rate control (remove)
+ * @modulation: respective mac80211 modulation
+ * @rate_kbps: rate in kbit/s
+ * @rate_code: hardware rate value, used in &struct ath5k_desc, on RX on
+@@ -643,47 +637,48 @@ struct ath5k_rate_table {
+
+ /*
+ * Rate tables...
++ * TODO: CLEAN THIS !!!
+ */
+ #define AR5K_RATES_11A { 8, { \
+ 255, 255, 255, 255, 255, 255, 255, 255, 6, 4, 2, 0, \
+ 7, 5, 3, 1, 255, 255, 255, 255, 255, 255, 255, 255, \
+ 255, 255, 255, 255, 255, 255, 255, 255 }, { \
+- { 1, IEEE80211_RATE_OFDM, 6000, 11, 140, 0 }, \
+- { 1, IEEE80211_RATE_OFDM, 9000, 15, 18, 0 }, \
+- { 1, IEEE80211_RATE_OFDM, 12000, 10, 152, 2 }, \
+- { 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 2 }, \
+- { 1, IEEE80211_RATE_OFDM, 24000, 9, 176, 4 }, \
+- { 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 4 }, \
+- { 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 4 }, \
+- { 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 4 } } \
++ { 1, 0, 6000, 11, 140, 0 }, \
++ { 1, 0, 9000, 15, 18, 0 }, \
++ { 1, 0, 12000, 10, 152, 2 }, \
++ { 1, 0, 18000, 14, 36, 2 }, \
++ { 1, 0, 24000, 9, 176, 4 }, \
++ { 1, 0, 36000, 13, 72, 4 }, \
++ { 1, 0, 48000, 8, 96, 4 }, \
++ { 1, 0, 54000, 12, 108, 4 } } \
+ }
+
+ #define AR5K_RATES_11B { 4, { \
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, \
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, \
+ 3, 2, 1, 0, 255, 255, 255, 255 }, { \
+- { 1, IEEE80211_RATE_CCK, 1000, 27, 130, 0 }, \
+- { 1, IEEE80211_RATE_CCK_2, 2000, 26, 132, 1 }, \
+- { 1, IEEE80211_RATE_CCK_2, 5500, 25, 139, 1 }, \
+- { 1, IEEE80211_RATE_CCK_2, 11000, 24, 150, 1 } } \
++ { 1, 0, 1000, 27, 130, 0 }, \
++ { 1, IEEE80211_RATE_SHORT_PREAMBLE, 2000, 26, 132, 1 }, \
++ { 1, IEEE80211_RATE_SHORT_PREAMBLE, 5500, 25, 139, 1 }, \
++ { 1, IEEE80211_RATE_SHORT_PREAMBLE, 11000, 24, 150, 1 } } \
+ }
+
+ #define AR5K_RATES_11G { 12, { \
+ 255, 255, 255, 255, 255, 255, 255, 255, 10, 8, 6, 4, \
+ 11, 9, 7, 5, 255, 255, 255, 255, 255, 255, 255, 255, \
+ 3, 2, 1, 0, 255, 255, 255, 255 }, { \
+- { 1, IEEE80211_RATE_CCK, 1000, 27, 2, 0 }, \
+- { 1, IEEE80211_RATE_CCK_2, 2000, 26, 4, 1 }, \
+- { 1, IEEE80211_RATE_CCK_2, 5500, 25, 11, 1 }, \
+- { 1, IEEE80211_RATE_CCK_2, 11000, 24, 22, 1 }, \
+- { 0, IEEE80211_RATE_OFDM, 6000, 11, 12, 4 }, \
+- { 0, IEEE80211_RATE_OFDM, 9000, 15, 18, 4 }, \
+- { 1, IEEE80211_RATE_OFDM, 12000, 10, 24, 6 }, \
+- { 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 6 }, \
+- { 1, IEEE80211_RATE_OFDM, 24000, 9, 48, 8 }, \
+- { 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 8 }, \
+- { 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 8 }, \
+- { 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 8 } } \
++ { 1, 0, 1000, 27, 2, 0 }, \
++ { 1, IEEE80211_RATE_SHORT_PREAMBLE, 2000, 26, 4, 1 }, \
++ { 1, IEEE80211_RATE_SHORT_PREAMBLE, 5500, 25, 11, 1 }, \
++ { 1, IEEE80211_RATE_SHORT_PREAMBLE, 11000, 24, 22, 1 }, \
++ { 0, 0, 6000, 11, 12, 4 }, \
++ { 0, 0, 9000, 15, 18, 4 }, \
++ { 1, 0, 12000, 10, 24, 6 }, \
++ { 1, 0, 18000, 14, 36, 6 }, \
++ { 1, 0, 24000, 9, 48, 8 }, \
++ { 1, 0, 36000, 13, 72, 8 }, \
++ { 1, 0, 48000, 8, 96, 8 }, \
++ { 1, 0, 54000, 12, 108, 8 } } \
+ }
+
+ #define AR5K_RATES_TURBO { 8, { \
+@@ -708,14 +703,14 @@ struct ath5k_rate_table {
+ { 1, MODULATION_XR, 1000, 2, 139, 1 }, \
+ { 1, MODULATION_XR, 2000, 6, 150, 2 }, \
+ { 1, MODULATION_XR, 3000, 1, 150, 3 }, \
+- { 1, IEEE80211_RATE_OFDM, 6000, 11, 140, 4 }, \
+- { 1, IEEE80211_RATE_OFDM, 9000, 15, 18, 4 }, \
+- { 1, IEEE80211_RATE_OFDM, 12000, 10, 152, 6 }, \
+- { 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 6 }, \
+- { 1, IEEE80211_RATE_OFDM, 24000, 9, 176, 8 }, \
+- { 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 8 }, \
+- { 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 8 }, \
+- { 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 8 } } \
++ { 1, 0, 6000, 11, 140, 4 }, \
++ { 1, 0, 9000, 15, 18, 4 }, \
++ { 1, 0, 12000, 10, 152, 6 }, \
++ { 1, 0, 18000, 14, 36, 6 }, \
++ { 1, 0, 24000, 9, 176, 8 }, \
++ { 1, 0, 36000, 13, 72, 8 }, \
++ { 1, 0, 48000, 8, 96, 8 }, \
++ { 1, 0, 54000, 12, 108, 8 } } \
+ }
+
+ /*
+@@ -890,12 +885,14 @@ enum ath5k_capability_type {
+ AR5K_CAP_RFSILENT = 20, /* Supports RFsilent */
+ };
+
++
++/* XXX: we *may* move cap_range stuff to struct wiphy */
+ struct ath5k_capabilities {
+ /*
+ * Supported PHY modes
+ * (ie. CHANNEL_A, CHANNEL_B, ...)
+ */
+- DECLARE_BITMAP(cap_mode, NUM_DRIVER_MODES);
++ DECLARE_BITMAP(cap_mode, AR5K_MODE_MAX);
+
+ /*
+ * Frequency range (without regulation restrictions)
+@@ -908,14 +905,6 @@ struct ath5k_capabilities {
+ } cap_range;
+
+ /*
+- * Active regulation domain settings
+- */
+- struct {
+- enum ath5k_regdom reg_current;
+- enum ath5k_regdom reg_hw;
+- } cap_regdomain;
+-
+- /*
+ * Values stored in the EEPROM (some of them...)
+ */
+ struct ath5k_eeprom_info cap_eeprom;
+@@ -963,6 +952,7 @@ struct ath5k_hw {
+ u16 ah_phy_revision;
+ u16 ah_radio_5ghz_revision;
+ u16 ah_radio_2ghz_revision;
++ u32 ah_phy_spending;
+
+ enum ath5k_version ah_version;
+ enum ath5k_radio ah_radio;
+@@ -1038,8 +1028,10 @@ struct ath5k_hw {
+ int (*ah_setup_xtx_desc)(struct ath5k_hw *, struct ath5k_desc *,
+ unsigned int, unsigned int, unsigned int, unsigned int,
+ unsigned int, unsigned int);
+- int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *);
+- int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *);
++ int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
++ struct ath5k_tx_status *);
++ int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *,
++ struct ath5k_rx_status *);
+ };
+
+ /*
+@@ -1070,6 +1062,7 @@ extern int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase);
+ extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah);
+ extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask);
+ extern enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask);
++extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_low_level_stats *stats);
+ /* EEPROM access functions */
+ extern int ath5k_hw_set_regdomain(struct ath5k_hw *ah, u16 regdomain);
+ /* Protocol Control Unit Functions */
+@@ -1098,7 +1091,6 @@ extern int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, const struct ath5k_be
+ extern void ath5k_hw_reset_beacon(struct ath5k_hw *ah);
+ extern int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr);
+ #endif
+-extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ath5k_mib_stats *statistics);
+ /* ACK bit rate */
+ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high);
+ /* ACK/CTS Timeouts */
+@@ -1129,8 +1121,6 @@ extern int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio);
+ extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio);
+ extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val);
+ extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level);
+-/* Regulatory Domain/Channels Setup */
+-extern u16 ath5k_get_regdomain(struct ath5k_hw *ah);
+ /* Misc functions */
+ extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result);
+
+diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
+index bef967c..e18305b 100644
+--- a/drivers/net/wireless/ath5k/base.c
++++ b/drivers/net/wireless/ath5k/base.c
+@@ -80,7 +80,7 @@ MODULE_AUTHOR("Nick Kossifidis");
+ MODULE_DESCRIPTION("Support for 5xxx series of Atheros 802.11 wireless LAN cards.");
+ MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards");
+ MODULE_LICENSE("Dual BSD/GPL");
+-MODULE_VERSION("0.1.1 (EXPERIMENTAL)");
++MODULE_VERSION("0.5.0 (EXPERIMENTAL)");
+
+
+ /* Known PCI ids */
+@@ -118,12 +118,15 @@ static struct ath5k_srev_name srev_names[] = {
+ { "5212", AR5K_VERSION_VER, AR5K_SREV_VER_AR5212 },
+ { "5213", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213 },
+ { "5213A", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213A },
++ { "2413", AR5K_VERSION_VER, AR5K_SREV_VER_AR2413 },
++ { "2414", AR5K_VERSION_VER, AR5K_SREV_VER_AR2414 },
+ { "2424", AR5K_VERSION_VER, AR5K_SREV_VER_AR2424 },
+ { "5424", AR5K_VERSION_VER, AR5K_SREV_VER_AR5424 },
+ { "5413", AR5K_VERSION_VER, AR5K_SREV_VER_AR5413 },
+ { "5414", AR5K_VERSION_VER, AR5K_SREV_VER_AR5414 },
+ { "5416", AR5K_VERSION_VER, AR5K_SREV_VER_AR5416 },
+ { "5418", AR5K_VERSION_VER, AR5K_SREV_VER_AR5418 },
++ { "2425", AR5K_VERSION_VER, AR5K_SREV_VER_AR2425 },
+ { "xxxxx", AR5K_VERSION_VER, AR5K_SREV_UNKNOWN },
+ { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 },
+ { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 },
+@@ -132,6 +135,7 @@ static struct ath5k_srev_name srev_names[] = {
+ { "5112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112A },
+ { "2112", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112 },
+ { "2112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112A },
++ { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC0 },
+ { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC1 },
+ { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC2 },
+ { "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 },
+@@ -240,6 +244,8 @@ static int ath5k_chan_set(struct ath5k_softc *sc,
+ static void ath5k_setcurmode(struct ath5k_softc *sc,
+ unsigned int mode);
+ static void ath5k_mode_setup(struct ath5k_softc *sc);
++static void ath5k_set_total_hw_rates(struct ath5k_softc *sc);
++
+ /* Descriptor setup */
+ static int ath5k_desc_alloc(struct ath5k_softc *sc,
+ struct pci_dev *pdev);
+@@ -278,7 +284,8 @@ static int ath5k_rx_start(struct ath5k_softc *sc);
+ static void ath5k_rx_stop(struct ath5k_softc *sc);
+ static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc,
+ struct ath5k_desc *ds,
+- struct sk_buff *skb);
++ struct sk_buff *skb,
++ struct ath5k_rx_status *rs);
+ static void ath5k_tasklet_rx(unsigned long data);
+ /* Tx handling */
+ static void ath5k_tx_processq(struct ath5k_softc *sc,
+@@ -511,35 +518,46 @@ ath5k_pci_probe(struct pci_dev *pdev,
+ sc->ah->ah_mac_srev,
+ sc->ah->ah_phy_revision);
+
+- if(!sc->ah->ah_single_chip){
++ if (!sc->ah->ah_single_chip) {
+ /* Single chip radio (!RF5111) */
+- if(sc->ah->ah_radio_5ghz_revision && !sc->ah->ah_radio_2ghz_revision) {
++ if (sc->ah->ah_radio_5ghz_revision &&
++ !sc->ah->ah_radio_2ghz_revision) {
+ /* No 5GHz support -> report 2GHz radio */
+- if(!test_bit(MODE_IEEE80211A, sc->ah->ah_capabilities.cap_mode)){
++ if (!test_bit(AR5K_MODE_11A,
++ sc->ah->ah_capabilities.cap_mode)) {
+ ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
+- ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision),
+- sc->ah->ah_radio_5ghz_revision);
+- /* No 2GHz support (5110 and some 5Ghz only cards) -> report 5Ghz radio */
+- } else if(!test_bit(MODE_IEEE80211B, sc->ah->ah_capabilities.cap_mode)){
++ ath5k_chip_name(AR5K_VERSION_RAD,
++ sc->ah->ah_radio_5ghz_revision),
++ sc->ah->ah_radio_5ghz_revision);
++ /* No 2GHz support (5110 and some
++ * 5Ghz only cards) -> report 5Ghz radio */
++ } else if (!test_bit(AR5K_MODE_11B,
++ sc->ah->ah_capabilities.cap_mode)) {
+ ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
+- ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision),
+- sc->ah->ah_radio_5ghz_revision);
++ ath5k_chip_name(AR5K_VERSION_RAD,
++ sc->ah->ah_radio_5ghz_revision),
++ sc->ah->ah_radio_5ghz_revision);
+ /* Multiband radio */
+ } else {
+ ATH5K_INFO(sc, "RF%s multiband radio found"
+ " (0x%x)\n",
+- ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision),
+- sc->ah->ah_radio_5ghz_revision);
++ ath5k_chip_name(AR5K_VERSION_RAD,
++ sc->ah->ah_radio_5ghz_revision),
++ sc->ah->ah_radio_5ghz_revision);
+ }
+ }
+- /* Multi chip radio (RF5111 - RF2111) -> report both 2GHz/5GHz radios */
+- else if(sc->ah->ah_radio_5ghz_revision && sc->ah->ah_radio_2ghz_revision){
++ /* Multi chip radio (RF5111 - RF2111) ->
++ * report both 2GHz/5GHz radios */
++ else if (sc->ah->ah_radio_5ghz_revision &&
++ sc->ah->ah_radio_2ghz_revision){
+ ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
+- ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision),
+- sc->ah->ah_radio_5ghz_revision);
++ ath5k_chip_name(AR5K_VERSION_RAD,
++ sc->ah->ah_radio_5ghz_revision),
++ sc->ah->ah_radio_5ghz_revision);
+ ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
+- ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_2ghz_revision),
+- sc->ah->ah_radio_2ghz_revision);
++ ath5k_chip_name(AR5K_VERSION_RAD,
++ sc->ah->ah_radio_2ghz_revision),
++ sc->ah->ah_radio_2ghz_revision);
+ }
+ }
+
+@@ -693,11 +711,14 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
+ goto err;
+ }
+
++ /* Set *_rates so we can map hw rate index */
++ ath5k_set_total_hw_rates(sc);
++
+ /* NB: setup here so ath5k_rate_update is happy */
+- if (test_bit(MODE_IEEE80211A, ah->ah_modes))
+- ath5k_setcurmode(sc, MODE_IEEE80211A);
++ if (test_bit(AR5K_MODE_11A, ah->ah_modes))
++ ath5k_setcurmode(sc, AR5K_MODE_11A);
+ else
+- ath5k_setcurmode(sc, MODE_IEEE80211B);
++ ath5k_setcurmode(sc, AR5K_MODE_11B);
+
+ /*
+ * Allocate tx+rx descriptors and populate the lists.
+@@ -837,12 +858,9 @@ ath5k_copy_rates(struct ieee80211_rate *rates,
+ return 0;
+
+ for (i = 0, count = 0; i < rt->rate_count && max > 0; i++) {
+- if (!rt->rates[i].valid)
+- continue;
+- rates->rate = rt->rates[i].rate_kbps / 100;
+- rates->val = rt->rates[i].rate_code;
+- rates->flags = rt->rates[i].modulation;
+- rates++;
++ rates[count].bitrate = rt->rates[i].rate_kbps / 100;
++ rates[count].hw_value = rt->rates[i].rate_code;
++ rates[count].flags = rt->rates[i].modulation;
+ count++;
+ max--;
+ }
+@@ -856,43 +874,22 @@ ath5k_copy_channels(struct ath5k_hw *ah,
+ unsigned int mode,
+ unsigned int max)
+ {
+- static const struct { unsigned int mode, mask, chan; } map[] = {
+- [MODE_IEEE80211A] = { CHANNEL_OFDM, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_A },
+- [MODE_ATHEROS_TURBO] = { CHANNEL_OFDM|CHANNEL_TURBO, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_T },
+- [MODE_IEEE80211B] = { CHANNEL_CCK, CHANNEL_CCK, CHANNEL_B },
+- [MODE_IEEE80211G] = { CHANNEL_OFDM, CHANNEL_OFDM, CHANNEL_G },
+- [MODE_ATHEROS_TURBOG] = { CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_TG },
+- };
+- static const struct ath5k_regchannel chans_2ghz[] =
+- IEEE80211_CHANNELS_2GHZ;
+- static const struct ath5k_regchannel chans_5ghz[] =
+- IEEE80211_CHANNELS_5GHZ;
+- const struct ath5k_regchannel *chans;
+- enum ath5k_regdom dmn;
+- unsigned int i, count, size, chfreq, all, f, ch;
++ unsigned int i, count, size, chfreq, freq, ch;
+
+ if (!test_bit(mode, ah->ah_modes))
+ return 0;
+
+- all = ah->ah_regdomain == DMN_DEFAULT || CHAN_DEBUG == 1;
+-
+ switch (mode) {
+- case MODE_IEEE80211A:
+- case MODE_ATHEROS_TURBO:
++ case AR5K_MODE_11A:
++ case AR5K_MODE_11A_TURBO:
+ /* 1..220, but 2GHz frequencies are filtered by check_channel */
+- size = all ? 220 : ARRAY_SIZE(chans_5ghz);
+- chans = chans_5ghz;
+- dmn = ath5k_regdom2flag(ah->ah_regdomain,
+- IEEE80211_CHANNELS_5GHZ_MIN);
++ size = 220 ;
+ chfreq = CHANNEL_5GHZ;
+ break;
+- case MODE_IEEE80211B:
+- case MODE_IEEE80211G:
+- case MODE_ATHEROS_TURBOG:
+- size = all ? 26 : ARRAY_SIZE(chans_2ghz);
+- chans = chans_2ghz;
+- dmn = ath5k_regdom2flag(ah->ah_regdomain,
+- IEEE80211_CHANNELS_2GHZ_MIN);
++ case AR5K_MODE_11B:
++ case AR5K_MODE_11G:
++ case AR5K_MODE_11G_TURBO:
++ size = 26;
+ chfreq = CHANNEL_2GHZ;
+ break;
+ default:
+@@ -901,25 +898,31 @@ ath5k_copy_channels(struct ath5k_hw *ah,
+ }
+
+ for (i = 0, count = 0; i < size && max > 0; i++) {
+- ch = all ? i + 1 : chans[i].chan;
+- f = ath5k_ieee2mhz(ch);
+- /* Check if channel is supported by the chipset */
+- if (!ath5k_channel_ok(ah, f, chfreq))
+- continue;
++ ch = i + 1 ;
++ freq = ath5k_ieee2mhz(ch);
+
+- /* Match regulation domain */
+- if (!all && !(IEEE80211_DMN(chans[i].domain) &
+- IEEE80211_DMN(dmn)))
++ /* Check if channel is supported by the chipset */
++ if (!ath5k_channel_ok(ah, freq, chfreq))
+ continue;
+
+- if (!all && (chans[i].mode & map[mode].mask) != map[mode].mode)
+- continue;
++ /* Write channel info and increment counter */
++ channels[count].center_freq = freq;
++ channels[count].band = (chfreq == CHANNEL_2GHZ) ?
++ IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
++ switch (mode) {
++ case AR5K_MODE_11A:
++ case AR5K_MODE_11G:
++ channels[count].hw_value = chfreq | CHANNEL_OFDM;
++ break;
++ case AR5K_MODE_11A_TURBO:
++ case AR5K_MODE_11G_TURBO:
++ channels[count].hw_value = chfreq |
++ CHANNEL_OFDM | CHANNEL_TURBO;
++ break;
++ case AR5K_MODE_11B:
++ channels[count].hw_value = CHANNEL_B;
++ }
+
+- /* Write channel and increment counter */
+- channels->chan = ch;
+- channels->freq = f;
+- channels->val = map[mode].chan;
+- channels++;
+ count++;
+ max--;
+ }
+@@ -927,95 +930,78 @@ ath5k_copy_channels(struct ath5k_hw *ah,
+ return count;
+ }
+
+-/* Only tries to register modes our EEPROM says it can support */
+-#define REGISTER_MODE(m) do { \
+- ret = ath5k_register_mode(hw, m); \
+- if (ret) \
+- return ret; \
+-} while (0) \
+-
+-static inline int
+-ath5k_register_mode(struct ieee80211_hw *hw, u8 m)
+-{
+- struct ath5k_softc *sc = hw->priv;
+- struct ieee80211_hw_mode *modes = sc->modes;
+- unsigned int i;
+- int ret;
+-
+- if (!test_bit(m, sc->ah->ah_capabilities.cap_mode))
+- return 0;
+-
+- for (i = 0; i < NUM_DRIVER_MODES; i++) {
+- if (modes[i].mode != m || !modes[i].num_channels)
+- continue;
+- ret = ieee80211_register_hwmode(hw, &modes[i]);
+- if (ret) {
+- ATH5K_ERR(sc, "can't register hwmode %u\n", m);
+- return ret;
+- }
+- return 0;
+- }
+- BUG();
+-}
+-
+ static int
+ ath5k_getchannels(struct ieee80211_hw *hw)
+ {
+ struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = sc->ah;
+- struct ieee80211_hw_mode *modes = sc->modes;
+- unsigned int i, max_r, max_c;
+- int ret;
++ struct ieee80211_supported_band *sbands = sc->sbands;
++ const struct ath5k_rate_table *hw_rates;
++ unsigned int max_r, max_c, count_r, count_c;
++ int mode2g = AR5K_MODE_11G;
+
+- BUILD_BUG_ON(ARRAY_SIZE(sc->modes) < 3);
+-
+- /* The order here does not matter */
+- modes[0].mode = MODE_IEEE80211G;
+- modes[1].mode = MODE_IEEE80211B;
+- modes[2].mode = MODE_IEEE80211A;
++ BUILD_BUG_ON(ARRAY_SIZE(sc->sbands) < IEEE80211_NUM_BANDS);
+
+ max_r = ARRAY_SIZE(sc->rates);
+ max_c = ARRAY_SIZE(sc->channels);
++ count_r = count_c = 0;
+
+- for (i = 0; i < NUM_DRIVER_MODES; i++) {
+- struct ieee80211_hw_mode *mode = &modes[i];
+- const struct ath5k_rate_table *hw_rates;
++ /* 2GHz band */
++ if (!test_bit(AR5K_MODE_11G, sc->ah->ah_capabilities.cap_mode)) {
++ mode2g = AR5K_MODE_11B;
++ if (!test_bit(AR5K_MODE_11B,
++ sc->ah->ah_capabilities.cap_mode))
++ mode2g = -1;
++ }
+
+- if (i == 0) {
+- modes[0].rates = sc->rates;
+- modes->channels = sc->channels;
+- } else {
+- struct ieee80211_hw_mode *prev_mode = &modes[i-1];
+- int prev_num_r = prev_mode->num_rates;
+- int prev_num_c = prev_mode->num_channels;
+- mode->rates = &prev_mode->rates[prev_num_r];
+- mode->channels = &prev_mode->channels[prev_num_c];
+- }
++ if (mode2g > 0) {
++ struct ieee80211_supported_band *sband =
++ &sbands[IEEE80211_BAND_2GHZ];
++
++ sband->bitrates = sc->rates;
++ sband->channels = sc->channels;
++
++ sband->band = IEEE80211_BAND_2GHZ;
++ sband->n_channels = ath5k_copy_channels(ah, sband->channels,
++ mode2g, max_c);
++
++ hw_rates = ath5k_hw_get_rate_table(ah, mode2g);
++ sband->n_bitrates = ath5k_copy_rates(sband->bitrates,
++ hw_rates, max_r);
++
++ count_c = sband->n_channels;
++ count_r = sband->n_bitrates;
++
++ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband;
++
++ max_r -= count_r;
++ max_c -= count_c;
+
+- hw_rates = ath5k_hw_get_rate_table(ah, mode->mode);
+- mode->num_rates = ath5k_copy_rates(mode->rates, hw_rates,
+- max_r);
+- mode->num_channels = ath5k_copy_channels(ah, mode->channels,
+- mode->mode, max_c);
+- max_r -= mode->num_rates;
+- max_c -= mode->num_channels;
+ }
+
+- /* We try to register all modes this driver supports. We don't bother
+- * with MODE_IEEE80211B for AR5212 as MODE_IEEE80211G already accounts
+- * for that as per mac80211. Then, REGISTER_MODE() will will actually
+- * check the eeprom reading for more reliable capability information.
+- * Order matters here as per mac80211's latest preference. This will
+- * all hopefullly soon go away. */
++ /* 5GHz band */
+
+- REGISTER_MODE(MODE_IEEE80211G);
+- if (ah->ah_version != AR5K_AR5212)
+- REGISTER_MODE(MODE_IEEE80211B);
+- REGISTER_MODE(MODE_IEEE80211A);
++ if (test_bit(AR5K_MODE_11A, sc->ah->ah_capabilities.cap_mode)) {
++ struct ieee80211_supported_band *sband =
++ &sbands[IEEE80211_BAND_5GHZ];
+
+- ath5k_debug_dump_modes(sc, modes);
++ sband->bitrates = &sc->rates[count_r];
++ sband->channels = &sc->channels[count_c];
+
+- return ret;
++ sband->band = IEEE80211_BAND_5GHZ;
++ sband->n_channels = ath5k_copy_channels(ah, sband->channels,
++ AR5K_MODE_11A, max_c);
++
++ hw_rates = ath5k_hw_get_rate_table(ah, AR5K_MODE_11A);
++ sband->n_bitrates = ath5k_copy_rates(sband->bitrates,
++ hw_rates, max_r);
++
++ hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband;
++ }
++
++ ath5k_debug_dump_bands(sc);
++
++ return 0;
+ }
+
+ /*
+@@ -1030,11 +1016,15 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
+ struct ath5k_hw *ah = sc->ah;
+ int ret;
+
+- ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "%u (%u MHz) -> %u (%u MHz)\n",
+- sc->curchan->chan, sc->curchan->freq,
+- chan->chan, chan->freq);
++ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "(%u MHz) -> (%u MHz)\n",
++ sc->curchan->center_freq, chan->center_freq);
++
++ if (chan->center_freq != sc->curchan->center_freq ||
++ chan->hw_value != sc->curchan->hw_value) {
++
++ sc->curchan = chan;
++ sc->curband = &sc->sbands[chan->band];
+
+- if (chan->freq != sc->curchan->freq || chan->val != sc->curchan->val) {
+ /*
+ * To switch channels clear any pending DMA operations;
+ * wait long enough for the RX fifo to drain, reset the
+@@ -1044,13 +1034,13 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
+ ath5k_hw_set_intr(ah, 0); /* disable interrupts */
+ ath5k_txq_cleanup(sc); /* clear pending tx frames */
+ ath5k_rx_stop(sc); /* turn off frame recv */
+- ret = ath5k_hw_reset(ah, sc->opmode, chan, true);
++ ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, true);
+ if (ret) {
+- ATH5K_ERR(sc, "%s: unable to reset channel %u "
+- "(%u Mhz)\n", __func__, chan->chan, chan->freq);
++ ATH5K_ERR(sc, "%s: unable to reset channel "
++ "(%u Mhz)\n", __func__, chan->center_freq);
+ return ret;
+ }
+- sc->curchan = chan;
++
+ ath5k_hw_set_txpower_limit(sc->ah, 0);
+
+ /*
+@@ -1081,6 +1071,9 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
+ return 0;
+ }
+
++/*
++ * TODO: CLEAN THIS !!!
++ */
+ static void
+ ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
+ {
+@@ -1121,10 +1114,6 @@ ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
+ continue;
+ }
+ sc->hwmap[i].txflags = IEEE80211_RADIOTAP_F_DATAPAD;
+- if (SHPREAMBLE_FLAG(ix) || rt->rates[ix].modulation ==
+- IEEE80211_RATE_OFDM)
+- sc->hwmap[i].txflags |=
+- IEEE80211_RADIOTAP_F_SHORTPRE;
+ /* receive frames include FCS */
+ sc->hwmap[i].rxflags = sc->hwmap[i].txflags |
+ IEEE80211_RADIOTAP_F_FCS;
+@@ -1142,6 +1131,12 @@ ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
+ }
+
+ sc->curmode = mode;
++
++ if (mode == AR5K_MODE_11A) {
++ sc->curband = &sc->sbands[IEEE80211_BAND_5GHZ];
++ } else {
++ sc->curband = &sc->sbands[IEEE80211_BAND_2GHZ];
++ }
+ }
+
+ static void
+@@ -1164,6 +1159,72 @@ ath5k_mode_setup(struct ath5k_softc *sc)
+ ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
+ }
+
++/*
++ * Match the hw provided rate index (through descriptors)
++ * to an index for sc->curband->bitrates, so it can be used
++ * by the stack.
++ *
++ * This one is a little bit tricky but i think i'm right
++ * about this...
++ *
++ * We have 4 rate tables in the following order:
++ * XR (4 rates)
++ * 802.11a (8 rates)
++ * 802.11b (4 rates)
++ * 802.11g (12 rates)
++ * that make the hw rate table.
++ *
++ * Lets take a 5211 for example that supports a and b modes only.
++ * First comes the 802.11a table and then 802.11b (total 12 rates).
++ * When hw returns eg. 11 it points to the last 802.11b rate (11Mbit),
++ * if it returns 2 it points to the second 802.11a rate etc.
++ *
++ * Same goes for 5212 who has xr/a/b/g support (total 28 rates).
++ * First comes the XR table, then 802.11a, 802.11b and 802.11g.
++ * When hw returns eg. 27 it points to the last 802.11g rate (54Mbits) etc
++ */
++static void
++ath5k_set_total_hw_rates(struct ath5k_softc *sc) {
++
++ struct ath5k_hw *ah = sc->ah;
++
++ if (test_bit(AR5K_MODE_11A, ah->ah_modes))
++ sc->a_rates = 8;
++
++ if (test_bit(AR5K_MODE_11B, ah->ah_modes))
++ sc->b_rates = 4;
++
++ if (test_bit(AR5K_MODE_11G, ah->ah_modes))
++ sc->g_rates = 12;
++
++ /* XXX: Need to see what what happens when
++ xr disable bits in eeprom are set */
++ if (ah->ah_version >= AR5K_AR5212)
++ sc->xr_rates = 4;
++
++}
++
++static inline int
++ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix) {
++
++ int mac80211_rix;
++
++ if(sc->curband->band == IEEE80211_BAND_2GHZ) {
++ /* We setup a g ratetable for both b/g modes */
++ mac80211_rix =
++ hw_rix - sc->b_rates - sc->a_rates - sc->xr_rates;
++ } else {
++ mac80211_rix = hw_rix - sc->xr_rates;
++ }
++
++ /* Something went wrong, fallback to basic rate for this band */
++ if ((mac80211_rix >= sc->curband->n_bitrates) ||
++ (mac80211_rix <= 0 ))
++ mac80211_rix = 1;
++
++ return mac80211_rix;
++}
++
+
+
+
+@@ -1268,7 +1329,8 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
+
+ ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
+ ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL,
+- (ctl->power_level * 2), ctl->tx_rate, ctl->retry_limit, keyidx, 0, flags, 0, 0);
++ (sc->power_level * 2), ctl->tx_rate->hw_value,
++ ctl->retry_limit, keyidx, 0, flags, 0, 0);
+ if (ret)
+ goto err_unmap;
+
+@@ -1503,8 +1565,7 @@ ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq)
+ */
+ spin_lock_bh(&txq->lock);
+ list_for_each_entry_safe(bf, bf0, &txq->q, list) {
+- ath5k_debug_printtxbuf(sc, bf, !sc->ah->ah_proc_tx_desc(sc->ah,
+- bf->desc));
++ ath5k_debug_printtxbuf(sc, bf);
+
+ ath5k_txbuf_free(sc, bf);
+
+@@ -1629,20 +1690,20 @@ ath5k_rx_stop(struct ath5k_softc *sc)
+
+ static unsigned int
+ ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
+- struct sk_buff *skb)
++ struct sk_buff *skb, struct ath5k_rx_status *rs)
+ {
+ struct ieee80211_hdr *hdr = (void *)skb->data;
+ unsigned int keyix, hlen = ieee80211_get_hdrlen_from_skb(skb);
+
+- if (!(ds->ds_rxstat.rs_status & AR5K_RXERR_DECRYPT) &&
+- ds->ds_rxstat.rs_keyix != AR5K_RXKEYIX_INVALID)
++ if (!(rs->rs_status & AR5K_RXERR_DECRYPT) &&
++ rs->rs_keyix != AR5K_RXKEYIX_INVALID)
+ return RX_FLAG_DECRYPTED;
+
+ /* Apparently when a default key is used to decrypt the packet
+ the hw does not set the index used to decrypt. In such cases
+ get the index from the packet. */
+ if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) &&
+- !(ds->ds_rxstat.rs_status & AR5K_RXERR_DECRYPT) &&
++ !(rs->rs_status & AR5K_RXERR_DECRYPT) &&
+ skb->len >= hlen + 4) {
+ keyix = skb->data[hlen + 3] >> 6;
+
+@@ -1655,28 +1716,62 @@ ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
+
+
+ static void
+-ath5k_check_ibss_hw_merge(struct ath5k_softc *sc, struct sk_buff *skb)
++ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
++ struct ieee80211_rx_status *rxs)
+ {
++ u64 tsf, bc_tstamp;
+ u32 hw_tu;
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
+
+- if ((mgmt->frame_control & IEEE80211_FCTL_FTYPE) ==
++ if ((le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_FTYPE) ==
+ IEEE80211_FTYPE_MGMT &&
+- (mgmt->frame_control & IEEE80211_FCTL_STYPE) ==
++ (le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE) ==
+ IEEE80211_STYPE_BEACON &&
+- mgmt->u.beacon.capab_info & WLAN_CAPABILITY_IBSS &&
++ le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS &&
+ memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) {
+ /*
+- * Received an IBSS beacon with the same BSSID. Hardware might
+- * have updated the TSF, check if we need to update timers.
++ * Received an IBSS beacon with the same BSSID. Hardware *must*
++ * have updated the local TSF. We have to work around various
++ * hardware bugs, though...
+ */
+- hw_tu = TSF_TO_TU(ath5k_hw_get_tsf64(sc->ah));
+- if (hw_tu >= sc->nexttbtt) {
+- ath5k_beacon_update_timers(sc,
+- mgmt->u.beacon.timestamp);
++ tsf = ath5k_hw_get_tsf64(sc->ah);
++ bc_tstamp = le64_to_cpu(mgmt->u.beacon.timestamp);
++ hw_tu = TSF_TO_TU(tsf);
++
++ ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
++ "beacon %llx mactime %llx (diff %lld) tsf now %llx\n",
++ (unsigned long long)bc_tstamp,
++ (unsigned long long)rxs->mactime,
++ (unsigned long long)(rxs->mactime - bc_tstamp),
++ (unsigned long long)tsf);
++
++ /*
++ * Sometimes the HW will give us a wrong tstamp in the rx
++ * status, causing the timestamp extension to go wrong.
++ * (This seems to happen especially with beacon frames bigger
++ * than 78 byte (incl. FCS))
++ * But we know that the receive timestamp must be later than the
++ * timestamp of the beacon since HW must have synced to that.
++ *
++ * NOTE: here we assume mactime to be after the frame was
++ * received, not like mac80211 which defines it at the start.
++ */
++ if (bc_tstamp > rxs->mactime) {
+ ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+- "detected HW merge from received beacon\n");
++ "fixing mactime from %llx to %llx\n",
++ (unsigned long long)rxs->mactime,
++ (unsigned long long)tsf);
++ rxs->mactime = tsf;
+ }
++
++ /*
++ * Local TSF might have moved higher than our beacon timers,
++ * in that case we have to update them to continue sending
++ * beacons. This also takes care of synchronizing beacon sending
++ * times with other stations.
++ */
++ if (hw_tu >= sc->nexttbtt)
++ ath5k_beacon_update_timers(sc, bc_tstamp);
+ }
+ }
+
+@@ -1685,12 +1780,11 @@ static void
+ ath5k_tasklet_rx(unsigned long data)
+ {
+ struct ieee80211_rx_status rxs = {};
++ struct ath5k_rx_status rs = {};
+ struct sk_buff *skb;
+ struct ath5k_softc *sc = (void *)data;
+ struct ath5k_buf *bf;
+ struct ath5k_desc *ds;
+- u16 len;
+- u8 stat;
+ int ret;
+ int hdrlen;
+ int pad;
+@@ -1713,7 +1807,7 @@ ath5k_tasklet_rx(unsigned long data)
+ if (unlikely(ds->ds_link == bf->daddr)) /* this is the end */
+ break;
+
+- ret = sc->ah->ah_proc_rx_desc(sc->ah, ds);
++ ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs);
+ if (unlikely(ret == -EINPROGRESS))
+ break;
+ else if (unlikely(ret)) {
+@@ -1722,16 +1816,15 @@ ath5k_tasklet_rx(unsigned long data)
+ return;
+ }
+
+- if (unlikely(ds->ds_rxstat.rs_more)) {
++ if (unlikely(rs.rs_more)) {
+ ATH5K_WARN(sc, "unsupported jumbo\n");
+ goto next;
+ }
+
+- stat = ds->ds_rxstat.rs_status;
+- if (unlikely(stat)) {
+- if (stat & AR5K_RXERR_PHY)
++ if (unlikely(rs.rs_status)) {
++ if (rs.rs_status & AR5K_RXERR_PHY)
+ goto next;
+- if (stat & AR5K_RXERR_DECRYPT) {
++ if (rs.rs_status & AR5K_RXERR_DECRYPT) {
+ /*
+ * Decrypt error. If the error occurred
+ * because there was no hardware key, then
+@@ -1742,30 +1835,29 @@ ath5k_tasklet_rx(unsigned long data)
+ *
+ * XXX do key cache faulting
+ */
+- if (ds->ds_rxstat.rs_keyix ==
+- AR5K_RXKEYIX_INVALID &&
+- !(stat & AR5K_RXERR_CRC))
++ if (rs.rs_keyix == AR5K_RXKEYIX_INVALID &&
++ !(rs.rs_status & AR5K_RXERR_CRC))
+ goto accept;
+ }
+- if (stat & AR5K_RXERR_MIC) {
++ if (rs.rs_status & AR5K_RXERR_MIC) {
+ rxs.flag |= RX_FLAG_MMIC_ERROR;
+ goto accept;
+ }
+
+ /* let crypto-error packets fall through in MNTR */
+- if ((stat & ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) ||
++ if ((rs.rs_status &
++ ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) ||
+ sc->opmode != IEEE80211_IF_TYPE_MNTR)
+ goto next;
+ }
+ accept:
+- len = ds->ds_rxstat.rs_datalen;
+- pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr, len,
+- PCI_DMA_FROMDEVICE);
++ pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr,
++ rs.rs_datalen, PCI_DMA_FROMDEVICE);
+ pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
+ PCI_DMA_FROMDEVICE);
+ bf->skb = NULL;
+
+- skb_put(skb, len);
++ skb_put(skb, rs.rs_datalen);
+
+ /*
+ * the hardware adds a padding to 4 byte boundaries between
+@@ -1787,13 +1879,23 @@ accept:
+ * 15bit only. that means TSF extension has to be done within
+ * 32768usec (about 32ms). it might be necessary to move this to
+ * the interrupt handler, like it is done in madwifi.
++ *
++ * Unfortunately we don't know when the hardware takes the rx
++ * timestamp (beginning of phy frame, data frame, end of rx?).
++ * The only thing we know is that it is hardware specific...
++ * On AR5213 it seems the rx timestamp is at the end of the
++ * frame, but i'm not sure.
++ *
++ * NOTE: mac80211 defines mactime at the beginning of the first
++ * data symbol. Since we don't have any time references it's
++ * impossible to comply to that. This affects IBSS merge only
++ * right now, so it's not too bad...
+ */
+- rxs.mactime = ath5k_extend_tsf(sc->ah, ds->ds_rxstat.rs_tstamp);
++ rxs.mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp);
+ rxs.flag |= RX_FLAG_TSFT;
+
+- rxs.freq = sc->curchan->freq;
+- rxs.channel = sc->curchan->chan;
+- rxs.phymode = sc->curmode;
++ rxs.freq = sc->curchan->center_freq;
++ rxs.band = sc->curband->band;
+
+ /*
+ * signal quality:
+@@ -1803,25 +1905,25 @@ accept:
+ /* noise floor in dBm, from the last noise calibration */
+ rxs.noise = sc->ah->ah_noise_floor;
+ /* signal level in dBm */
+- rxs.ssi = rxs.noise + ds->ds_rxstat.rs_rssi;
++ rxs.ssi = rxs.noise + rs.rs_rssi;
+ /*
+ * "signal" is actually displayed as Link Quality by iwconfig
+ * we provide a percentage based on rssi (assuming max rssi 64)
+ */
+- rxs.signal = ds->ds_rxstat.rs_rssi * 100 / 64;
++ rxs.signal = rs.rs_rssi * 100 / 64;
+
+- rxs.antenna = ds->ds_rxstat.rs_antenna;
+- rxs.rate = ds->ds_rxstat.rs_rate;
+- rxs.flag |= ath5k_rx_decrypted(sc, ds, skb);
++ rxs.antenna = rs.rs_antenna;
++ rxs.rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
++ rxs.flag |= ath5k_rx_decrypted(sc, ds, skb, &rs);
+
+ ath5k_debug_dump_skb(sc, skb, "RX ", 0);
+
+ /* check beacons in IBSS mode */
+ if (sc->opmode == IEEE80211_IF_TYPE_IBSS)
+- ath5k_check_ibss_hw_merge(sc, skb);
++ ath5k_check_ibss_tsf(sc, skb, &rxs);
+
+ __ieee80211_rx(sc->hw, skb, &rxs);
+- sc->led_rxrate = ds->ds_rxstat.rs_rate;
++ sc->led_rxrate = rs.rs_rate;
+ ath5k_led_event(sc, ATH_LED_RX);
+ next:
+ list_move_tail(&bf->list, &sc->rxbuf);
+@@ -1840,6 +1942,7 @@ static void
+ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
+ {
+ struct ieee80211_tx_status txs = {};
++ struct ath5k_tx_status ts = {};
+ struct ath5k_buf *bf, *bf0;
+ struct ath5k_desc *ds;
+ struct sk_buff *skb;
+@@ -1852,7 +1955,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
+ /* TODO only one segment */
+ pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr,
+ sc->desc_len, PCI_DMA_FROMDEVICE);
+- ret = sc->ah->ah_proc_tx_desc(sc->ah, ds);
++ ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
+ if (unlikely(ret == -EINPROGRESS))
+ break;
+ else if (unlikely(ret)) {
+@@ -1867,17 +1970,16 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
+ PCI_DMA_TODEVICE);
+
+ txs.control = bf->ctl;
+- txs.retry_count = ds->ds_txstat.ts_shortretry +
+- ds->ds_txstat.ts_longretry / 6;
+- if (unlikely(ds->ds_txstat.ts_status)) {
++ txs.retry_count = ts.ts_shortretry + ts.ts_longretry / 6;
++ if (unlikely(ts.ts_status)) {
+ sc->ll_stats.dot11ACKFailureCount++;
+- if (ds->ds_txstat.ts_status & AR5K_TXERR_XRETRY)
++ if (ts.ts_status & AR5K_TXERR_XRETRY)
+ txs.excessive_retries = 1;
+- else if (ds->ds_txstat.ts_status & AR5K_TXERR_FILT)
++ else if (ts.ts_status & AR5K_TXERR_FILT)
+ txs.flags |= IEEE80211_TX_STATUS_TX_FILTERED;
+ } else {
+ txs.flags |= IEEE80211_TX_STATUS_ACK;
+- txs.ack_signal = ds->ds_txstat.ts_rssi;
++ txs.ack_signal = ts.ts_rssi;
+ }
+
+ ieee80211_tx_status(sc->hw, skb, &txs);
+@@ -1958,8 +2060,9 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
+ ds->ds_data = bf->skbaddr;
+ ret = ah->ah_setup_tx_desc(ah, ds, skb->len,
+ ieee80211_get_hdrlen_from_skb(skb),
+- AR5K_PKT_TYPE_BEACON, (ctl->power_level * 2), ctl->tx_rate, 1,
+- AR5K_TXKEYIX_INVALID, antenna, flags, 0, 0);
++ AR5K_PKT_TYPE_BEACON, (sc->power_level * 2),
++ ctl->tx_rate->hw_value, 1, AR5K_TXKEYIX_INVALID,
++ antenna, flags, 0, 0);
+ if (ret)
+ goto err_unmap;
+
+@@ -2050,7 +2153,7 @@ ath5k_beacon_send(struct ath5k_softc *sc)
+ * beacon timer registers.
+ *
+ * This is called in a variety of situations, e.g. when a beacon is received,
+- * when a HW merge has been detected, but also when an new IBSS is created or
++ * when a TSF update has been detected, but also when an new IBSS is created or
+ * when we otherwise know we have to update the timers, but we keep it in this
+ * function to have it all together in one place.
+ */
+@@ -2150,7 +2253,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
+ * another AP to associate with.
+ *
+ * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA
+- * interrupts to detect HW merges only.
++ * interrupts to detect TSF updates only.
+ *
+ * AP mode is missing.
+ */
+@@ -2170,7 +2273,7 @@ ath5k_beacon_config(struct ath5k_softc *sc)
+ * hardware send the beacons automatically. We have to load it
+ * only once here.
+ * We use the SWBA interrupt only to keep track of the beacon
+- * timers in order to detect HW merges (automatic TSF updates).
++ * timers in order to detect automatic TSF updates.
+ */
+ ath5k_beaconq_config(sc);
+
+@@ -2211,7 +2314,8 @@ ath5k_init(struct ath5k_softc *sc)
+ * be followed by initialization of the appropriate bits
+ * and then setup of the interrupt mask.
+ */
+- sc->curchan = sc->hw->conf.chan;
++ sc->curchan = sc->hw->conf.channel;
++ sc->curband = &sc->sbands[sc->curchan->band];
+ ret = ath5k_hw_reset(sc->ah, sc->opmode, sc->curchan, false);
+ if (ret) {
+ ATH5K_ERR(sc, "unable to reset hardware: %d\n", ret);
+@@ -2238,7 +2342,8 @@ ath5k_init(struct ath5k_softc *sc)
+ * Enable interrupts.
+ */
+ sc->imask = AR5K_INT_RX | AR5K_INT_TX | AR5K_INT_RXEOL |
+- AR5K_INT_RXORN | AR5K_INT_FATAL | AR5K_INT_GLOBAL;
++ AR5K_INT_RXORN | AR5K_INT_FATAL | AR5K_INT_GLOBAL |
++ AR5K_INT_MIB;
+
+ ath5k_hw_set_intr(sc->ah, sc->imask);
+ /* Set ack to be sent at low bit-rates */
+@@ -2382,8 +2487,8 @@ ath5k_intr(int irq, void *dev_id)
+ *
+ * In IBSS mode we use this interrupt just to
+ * keep track of the next TBTT (target beacon
+- * transmission time) in order to detect hardware
+- * merges (TSF updates).
++ * transmission time) in order to detect wether
++ * automatic TSF updates happened.
+ */
+ if (sc->opmode == IEEE80211_IF_TYPE_IBSS) {
+ /* XXX: only if VEOL suppported */
+@@ -2418,7 +2523,11 @@ ath5k_intr(int irq, void *dev_id)
+ if (status & AR5K_INT_BMISS) {
+ }
+ if (status & AR5K_INT_MIB) {
+- /* TODO */
++ /*
++ * These stats are also used for ANI i think
++ * so how about updating them more often ?
++ */
++ ath5k_hw_update_mib_counters(ah, &sc->ll_stats);
+ }
+ }
+ } while (ath5k_hw_is_intr_pending(ah) && counter-- > 0);
+@@ -2448,7 +2557,8 @@ ath5k_calibrate(unsigned long data)
+ struct ath5k_hw *ah = sc->ah;
+
+ ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n",
+- sc->curchan->chan, sc->curchan->val);
++ ieee80211_frequency_to_channel(sc->curchan->center_freq),
++ sc->curchan->hw_value);
+
+ if (ath5k_hw_get_rf_gain(ah) == AR5K_RFGAIN_NEED_CHANGE) {
+ /*
+@@ -2460,7 +2570,8 @@ ath5k_calibrate(unsigned long data)
+ }
+ if (ath5k_hw_phy_calibrate(ah, sc->curchan))
+ ATH5K_ERR(sc, "calibration of channel %u failed\n",
+- sc->curchan->chan);
++ ieee80211_frequency_to_channel(
++ sc->curchan->center_freq));
+
+ mod_timer(&sc->calib_tim, round_jiffies(jiffies +
+ msecs_to_jiffies(ath5k_calinterval * 1000)));
+@@ -2558,7 +2669,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ memmove(skb->data, skb->data+pad, hdrlen);
+ }
+
+- sc->led_txrate = ctl->tx_rate;
++ sc->led_txrate = ctl->tx_rate->hw_value;
+
+ spin_lock_irqsave(&sc->txbuflock, flags);
+ if (list_empty(&sc->txbuf)) {
+@@ -2597,11 +2708,6 @@ ath5k_reset(struct ieee80211_hw *hw)
+ int ret;
+
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
+- /*
+- * Convert to a hw channel description with the flags
+- * constrained to reflect the current operating mode.
+- */
+- sc->curchan = hw->conf.chan;
+
+ ath5k_hw_set_intr(ah, 0);
+ ath5k_txq_cleanup(sc);
+@@ -2692,6 +2798,9 @@ end:
+ mutex_unlock(&sc->lock);
+ }
+
++/*
++ * TODO: Phy disable/diversity etc
++ */
+ static int
+ ath5k_config(struct ieee80211_hw *hw,
+ struct ieee80211_conf *conf)
+@@ -2699,9 +2808,9 @@ ath5k_config(struct ieee80211_hw *hw,
+ struct ath5k_softc *sc = hw->priv;
+
+ sc->bintval = conf->beacon_int;
+- ath5k_setcurmode(sc, conf->phymode);
++ sc->power_level = conf->power_level;
+
+- return ath5k_chan_set(sc, conf->chan);
++ return ath5k_chan_set(sc, conf->channel);
+ }
+
+ static int
+@@ -2869,7 +2978,9 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+
+ switch(key->alg) {
+ case ALG_WEP:
+- break;
++ /* XXX: fix hardware encryption, its not working. For now
++ * allow software encryption */
++ /* break; */
+ case ALG_TKIP:
+ case ALG_CCMP:
+ return -EOPNOTSUPP;
+@@ -2909,6 +3020,10 @@ ath5k_get_stats(struct ieee80211_hw *hw,
+ struct ieee80211_low_level_stats *stats)
+ {
+ struct ath5k_softc *sc = hw->priv;
++ struct ath5k_hw *ah = sc->ah;
++
++ /* Force update */
++ ath5k_hw_update_mib_counters(ah, &sc->ll_stats);
+
+ memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats));
+
+diff --git a/drivers/net/wireless/ath5k/base.h b/drivers/net/wireless/ath5k/base.h
+index 8287ae7..3a97558 100644
+--- a/drivers/net/wireless/ath5k/base.h
++++ b/drivers/net/wireless/ath5k/base.h
+@@ -83,7 +83,7 @@ struct ath5k_txq {
+ #if CHAN_DEBUG
+ #define ATH_CHAN_MAX (26+26+26+200+200)
+ #else
+-#define ATH_CHAN_MAX (14+14+14+252+20) /* XXX what's the max? */
++#define ATH_CHAN_MAX (14+14+14+252+20)
+ #endif
+
+ /* Software Carrier, keeps track of the driver state
+@@ -95,15 +95,22 @@ struct ath5k_softc {
+ struct ieee80211_tx_queue_stats tx_stats;
+ struct ieee80211_low_level_stats ll_stats;
+ struct ieee80211_hw *hw; /* IEEE 802.11 common */
+- struct ieee80211_hw_mode modes[NUM_DRIVER_MODES];
++ struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
+ struct ieee80211_channel channels[ATH_CHAN_MAX];
+- struct ieee80211_rate rates[AR5K_MAX_RATES * NUM_DRIVER_MODES];
++ struct ieee80211_rate rates[AR5K_MAX_RATES * IEEE80211_NUM_BANDS];
+ enum ieee80211_if_types opmode;
+ struct ath5k_hw *ah; /* Atheros HW */
+
+-#if ATH5K_DEBUG
++ struct ieee80211_supported_band *curband;
++
++ u8 a_rates;
++ u8 b_rates;
++ u8 g_rates;
++ u8 xr_rates;
++
++#ifdef CONFIG_ATH5K_DEBUG
+ struct ath5k_dbg_info debug; /* debug info */
+-#endif
++#endif /* CONFIG_ATH5K_DEBUG */
+
+ struct ath5k_buf *bufptr; /* allocated buffer ptr */
+ struct ath5k_desc *desc; /* TX/RX descriptors */
+@@ -169,6 +176,7 @@ struct ath5k_softc {
+ unsigned int nexttbtt; /* next beacon time in TU */
+
+ struct timer_list calib_tim; /* calibration timer */
++ int power_level; /* Requested tx power in dbm */
+ };
+
+ #define ath5k_hw_hasbssidmask(_ah) \
+diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c
+index bb581ef..41d5fa3 100644
+--- a/drivers/net/wireless/ath5k/debug.c
++++ b/drivers/net/wireless/ath5k/debug.c
+@@ -65,7 +65,7 @@ static unsigned int ath5k_debug;
+ module_param_named(debug, ath5k_debug, uint, 0);
+
+
+-#if ATH5K_DEBUG
++#ifdef CONFIG_ATH5K_DEBUG
+
+ #include <linux/seq_file.h>
+ #include "reg.h"
+@@ -200,7 +200,8 @@ static ssize_t read_file_tsf(struct file *file, char __user *user_buf,
+ {
+ struct ath5k_softc *sc = file->private_data;
+ char buf[100];
+- snprintf(buf, sizeof(buf), "0x%016llx\n", ath5k_hw_get_tsf64(sc->ah));
++ snprintf(buf, sizeof(buf), "0x%016llx\n",
++ (unsigned long long)ath5k_hw_get_tsf64(sc->ah));
+ return simple_read_from_buffer(user_buf, count, ppos, buf, 19);
+ }
+
+@@ -271,7 +272,8 @@ static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
+
+ tsf = ath5k_hw_get_tsf64(sc->ah);
+ len += snprintf(buf+len, sizeof(buf)-len,
+- "TSF\t\t0x%016llx\tTU: %08x\n", tsf, TSF_TO_TU(tsf));
++ "TSF\t\t0x%016llx\tTU: %08x\n",
++ (unsigned long long)tsf, TSF_TO_TU(tsf));
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ }
+@@ -340,7 +342,7 @@ static struct {
+ { ATH5K_DEBUG_LED, "led", "LED mamagement" },
+ { ATH5K_DEBUG_DUMP_RX, "dumprx", "print received skb content" },
+ { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" },
+- { ATH5K_DEBUG_DUMPMODES, "dumpmodes", "dump modes" },
++ { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" },
+ { ATH5K_DEBUG_TRACE, "trace", "trace function calls" },
+ { ATH5K_DEBUG_ANY, "all", "show all debug levels" },
+ };
+@@ -452,43 +454,63 @@ ath5k_debug_finish_device(struct ath5k_softc *sc)
+ /* functions used in other places */
+
+ void
+-ath5k_debug_dump_modes(struct ath5k_softc *sc, struct ieee80211_hw_mode *modes)
++ath5k_debug_dump_bands(struct ath5k_softc *sc)
+ {
+- unsigned int m, i;
++ unsigned int b, i;
+
+- if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPMODES)))
++ if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPBANDS)))
+ return;
+
+- for (m = 0; m < NUM_DRIVER_MODES; m++) {
+- printk(KERN_DEBUG "Mode %u: channels %d, rates %d\n", m,
+- modes[m].num_channels, modes[m].num_rates);
++ BUG_ON(!sc->sbands);
++
++ for (b = 0; b < IEEE80211_NUM_BANDS; b++) {
++ struct ieee80211_supported_band *band = &sc->sbands[b];
++ char bname[5];
++ switch (band->band) {
++ case IEEE80211_BAND_2GHZ:
++ strcpy(bname, "2 GHz");
++ break;
++ case IEEE80211_BAND_5GHZ:
++ strcpy(bname, "5 GHz");
++ break;
++ default:
++ printk(KERN_DEBUG "Band not supported: %d\n",
++ band->band);
++ return;
++ }
++ printk(KERN_DEBUG "Band %s: channels %d, rates %d\n", bname,
++ band->n_channels, band->n_bitrates);
+ printk(KERN_DEBUG " channels:\n");
+- for (i = 0; i < modes[m].num_channels; i++)
++ for (i = 0; i < band->n_channels; i++)
+ printk(KERN_DEBUG " %3d %d %.4x %.4x\n",
+- modes[m].channels[i].chan,
+- modes[m].channels[i].freq,
+- modes[m].channels[i].val,
+- modes[m].channels[i].flag);
++ ieee80211_frequency_to_channel(
++ band->channels[i].center_freq),
++ band->channels[i].center_freq,
++ band->channels[i].hw_value,
++ band->channels[i].flags);
+ printk(KERN_DEBUG " rates:\n");
+- for (i = 0; i < modes[m].num_rates; i++)
++ for (i = 0; i < band->n_bitrates; i++)
+ printk(KERN_DEBUG " %4d %.4x %.4x %.4x\n",
+- modes[m].rates[i].rate,
+- modes[m].rates[i].val,
+- modes[m].rates[i].flags,
+- modes[m].rates[i].val2);
++ band->bitrates[i].bitrate,
++ band->bitrates[i].hw_value,
++ band->bitrates[i].flags,
++ band->bitrates[i].hw_value_short);
+ }
+ }
+
+ static inline void
+-ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done)
++ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done,
++ struct ath5k_rx_status *rs)
+ {
+ struct ath5k_desc *ds = bf->desc;
++ struct ath5k_hw_all_rx_desc *rd = &ds->ud.ds_rx;
+
+ printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n",
+ ds, (unsigned long long)bf->daddr,
+- ds->ds_link, ds->ds_data, ds->ds_ctl0, ds->ds_ctl1,
+- ds->ds_hw[0], ds->ds_hw[1],
+- !done ? ' ' : (ds->ds_rxstat.rs_status == 0) ? '*' : '!');
++ ds->ds_link, ds->ds_data,
++ rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1,
++ rd->u.rx_stat.rx_status_0, rd->u.rx_stat.rx_status_0,
++ !done ? ' ' : (rs->rs_status == 0) ? '*' : '!');
+ }
+
+ void
+@@ -496,6 +518,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah)
+ {
+ struct ath5k_desc *ds;
+ struct ath5k_buf *bf;
++ struct ath5k_rx_status rs = {};
+ int status;
+
+ if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
+@@ -507,9 +530,9 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah)
+ spin_lock_bh(&sc->rxbuflock);
+ list_for_each_entry(bf, &sc->rxbuf, list) {
+ ds = bf->desc;
+- status = ah->ah_proc_rx_desc(ah, ds);
++ status = ah->ah_proc_rx_desc(ah, ds, &rs);
+ if (!status)
+- ath5k_debug_printrxbuf(bf, status == 0);
++ ath5k_debug_printrxbuf(bf, status == 0, &rs);
+ }
+ spin_unlock_bh(&sc->rxbuflock);
+ }
+@@ -533,19 +556,24 @@ ath5k_debug_dump_skb(struct ath5k_softc *sc,
+ }
+
+ void
+-ath5k_debug_printtxbuf(struct ath5k_softc *sc,
+- struct ath5k_buf *bf, int done)
++ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf)
+ {
+ struct ath5k_desc *ds = bf->desc;
++ struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212;
++ struct ath5k_tx_status ts = {};
++ int done;
+
+ if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
+ return;
+
++ done = sc->ah->ah_proc_tx_desc(sc->ah, bf->desc, &ts);
++
+ printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x "
+ "%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link,
+- ds->ds_data, ds->ds_ctl0, ds->ds_ctl1,
+- ds->ds_hw[0], ds->ds_hw[1], ds->ds_hw[2], ds->ds_hw[3],
+- !done ? ' ' : (ds->ds_txstat.ts_status == 0) ? '*' : '!');
++ ds->ds_data, td->tx_ctl.tx_control_0, td->tx_ctl.tx_control_1,
++ td->tx_ctl.tx_control_2, td->tx_ctl.tx_control_3,
++ td->tx_stat.tx_status_0, td->tx_stat.tx_status_1,
++ done ? ' ' : (ts.ts_status == 0) ? '*' : '!');
+ }
+
+-#endif /* if ATH5K_DEBUG */
++#endif /* ifdef CONFIG_ATH5K_DEBUG */
+diff --git a/drivers/net/wireless/ath5k/debug.h b/drivers/net/wireless/ath5k/debug.h
+index c4fd8c4..2cf8d18 100644
+--- a/drivers/net/wireless/ath5k/debug.h
++++ b/drivers/net/wireless/ath5k/debug.h
+@@ -61,11 +61,6 @@
+ #ifndef _ATH5K_DEBUG_H
+ #define _ATH5K_DEBUG_H
+
+-/* set this to 1 for debugging output */
+-#ifndef ATH5K_DEBUG
+-#define ATH5K_DEBUG 0
+-#endif
+-
+ struct ath5k_softc;
+ struct ath5k_hw;
+ struct ieee80211_hw_mode;
+@@ -96,7 +91,7 @@ struct ath5k_dbg_info {
+ * @ATH5K_DEBUG_LED: led management
+ * @ATH5K_DEBUG_DUMP_RX: print received skb content
+ * @ATH5K_DEBUG_DUMP_TX: print transmit skb content
+- * @ATH5K_DEBUG_DUMPMODES: dump modes
++ * @ATH5K_DEBUG_DUMPBANDS: dump bands
+ * @ATH5K_DEBUG_TRACE: trace function calls
+ * @ATH5K_DEBUG_ANY: show at any debug level
+ *
+@@ -118,12 +113,12 @@ enum ath5k_debug_level {
+ ATH5K_DEBUG_LED = 0x00000080,
+ ATH5K_DEBUG_DUMP_RX = 0x00000100,
+ ATH5K_DEBUG_DUMP_TX = 0x00000200,
+- ATH5K_DEBUG_DUMPMODES = 0x00000400,
++ ATH5K_DEBUG_DUMPBANDS = 0x00000400,
+ ATH5K_DEBUG_TRACE = 0x00001000,
+ ATH5K_DEBUG_ANY = 0xffffffff
+ };
+
+-#if ATH5K_DEBUG
++#ifdef CONFIG_ATH5K_DEBUG
+
+ #define ATH5K_TRACE(_sc) do { \
+ if (unlikely((_sc)->debug.level & ATH5K_DEBUG_TRACE)) \
+@@ -158,20 +153,20 @@ void
+ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah);
+
+ void
+-ath5k_debug_dump_modes(struct ath5k_softc *sc,
+- struct ieee80211_hw_mode *modes);
++ath5k_debug_dump_bands(struct ath5k_softc *sc);
+
+ void
+ ath5k_debug_dump_skb(struct ath5k_softc *sc,
+ struct sk_buff *skb, const char *prefix, int tx);
+
+ void
+-ath5k_debug_printtxbuf(struct ath5k_softc *sc,
+- struct ath5k_buf *bf, int done);
++ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf);
+
+ #else /* no debugging */
+
+-#define ATH5K_TRACE(_sc) /* empty */
++#include <linux/compiler.h>
++
++#define ATH5K_TRACE(_sc) typecheck(struct ath5k_softc *, (_sc))
+
+ static inline void __attribute__ ((format (printf, 3, 4)))
+ ATH5K_DBG(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) {}
+@@ -196,17 +191,15 @@ static inline void
+ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {}
+
+ static inline void
+-ath5k_debug_dump_modes(struct ath5k_softc *sc,
+- struct ieee80211_hw_mode *modes) {}
++ath5k_debug_dump_bands(struct ath5k_softc *sc) {}
+
+ static inline void
+ ath5k_debug_dump_skb(struct ath5k_softc *sc,
+ struct sk_buff *skb, const char *prefix, int tx) {}
+
+ static inline void
+-ath5k_debug_printtxbuf(struct ath5k_softc *sc,
+- struct ath5k_buf *bf, int done) {}
++ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) {}
+
+-#endif /* if ATH5K_DEBUG */
++#endif /* ifdef CONFIG_ATH5K_DEBUG */
+
+ #endif /* ifndef _ATH5K_DEBUG_H */
+diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c
+index 0175743..5fb1ae6 100644
+--- a/drivers/net/wireless/ath5k/hw.c
++++ b/drivers/net/wireless/ath5k/hw.c
+@@ -1,4 +1,4 @@
+- /*
++/*
+ * Copyright (c) 2004-2007 Reyk Floeter <reyk at openbsd.org>
+ * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm at gmail.com>
+ * Copyright (c) 2007 Matthew W. S. Bell <mentor at madwifi.org>
+@@ -48,14 +48,18 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
+ static int ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
+ unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
+ unsigned int);
+-static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *, struct ath5k_desc *);
++static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *, struct ath5k_desc *,
++ struct ath5k_tx_status *);
+ static int ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
+ unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int,
+ unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
+ unsigned int, unsigned int);
+-static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *, struct ath5k_desc *);
+-static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *, struct ath5k_desc *);
+-static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *, struct ath5k_desc *);
++static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *, struct ath5k_desc *,
++ struct ath5k_tx_status *);
++static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *, struct ath5k_desc *,
++ struct ath5k_rx_status *);
++static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *, struct ath5k_desc *,
++ struct ath5k_rx_status *);
+ static int ath5k_hw_get_capabilities(struct ath5k_hw *);
+
+ static int ath5k_eeprom_init(struct ath5k_hw *);
+@@ -81,12 +85,12 @@ static int ath5k_hw_disable_pspoll(struct ath5k_hw *);
+
+ static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo)
+ {
+- return turbo == true ? (usec * 80) : (usec * 40);
++ return turbo ? (usec * 80) : (usec * 40);
+ }
+
+ static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo)
+ {
+- return turbo == true ? (clock / 80) : (clock / 40);
++ return turbo ? (clock / 80) : (clock / 40);
+ }
+
+ /*
+@@ -100,7 +104,7 @@ int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val,
+
+ for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
+ data = ath5k_hw_reg_read(ah, reg);
+- if ((is_set == true) && (data & flag))
++ if (is_set && (data & flag))
+ break;
+ else if ((data & flag) == val)
+ break;
+@@ -116,11 +120,69 @@ int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val,
+ \***************************************/
+
+ /*
++ * Power On Self Test helper function
++ */
++static int ath5k_hw_post(struct ath5k_hw *ah)
++{
++
++ int i, c;
++ u16 cur_reg;
++ u16 regs[2] = {AR5K_STA_ID0, AR5K_PHY(8)};
++ u32 var_pattern;
++ u32 static_pattern[4] = {
++ 0x55555555, 0xaaaaaaaa,
++ 0x66666666, 0x99999999
++ };
++ u32 init_val;
++ u32 cur_val;
++
++ for (c = 0; c < 2; c++) {
++
++ cur_reg = regs[c];
++ init_val = ath5k_hw_reg_read(ah, cur_reg);
++
++ for (i = 0; i < 256; i++) {
++ var_pattern = i << 16 | i;
++ ath5k_hw_reg_write(ah, var_pattern, cur_reg);
++ cur_val = ath5k_hw_reg_read(ah, cur_reg);
++
++ if (cur_val != var_pattern) {
++ ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n");
++ return -EAGAIN;
++ }
++
++ /* Found on ndiswrapper dumps */
++ var_pattern = 0x0039080f;
++ ath5k_hw_reg_write(ah, var_pattern, cur_reg);
++ }
++
++ for (i = 0; i < 4; i++) {
++ var_pattern = static_pattern[i];
++ ath5k_hw_reg_write(ah, var_pattern, cur_reg);
++ cur_val = ath5k_hw_reg_read(ah, cur_reg);
++
++ if (cur_val != var_pattern) {
++ ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n");
++ return -EAGAIN;
++ }
++
++ /* Found on ndiswrapper dumps */
++ var_pattern = 0x003b080f;
++ ath5k_hw_reg_write(ah, var_pattern, cur_reg);
++ }
++ }
++
++ return 0;
++
++}
++
++/*
+ * Check if the device is supported and initialize the needed structs
+ */
+ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
+ {
+ struct ath5k_hw *ah;
++ struct pci_dev *pdev = sc->pdev;
+ u8 mac[ETH_ALEN];
+ int ret;
+ u32 srev;
+@@ -140,9 +202,6 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
+ * HW information
+ */
+
+- /* Get reg domain from eeprom */
+- ath5k_get_regdomain(ah);
+-
+ ah->ah_op_mode = IEEE80211_IF_TYPE_STA;
+ ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
+ ah->ah_turbo = false;
+@@ -177,9 +236,9 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
+ }
+
+ if (ah->ah_version == AR5K_AR5212)
+- ah->ah_proc_rx_desc = ath5k_hw_proc_new_rx_status;
++ ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status;
+ else if (ah->ah_version <= AR5K_AR5211)
+- ah->ah_proc_rx_desc = ath5k_hw_proc_old_rx_status;
++ ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status;
+
+ /* Bring device out of sleep and reset it's units */
+ ret = ath5k_hw_nic_wakeup(ah, AR5K_INIT_MODE, true);
+@@ -203,15 +262,19 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
+ CHANNEL_2GHZ);
+
+ /* Return on unsuported chips (unsupported eeprom etc) */
+- if(srev >= AR5K_SREV_VER_AR5416){
++ if ((srev >= AR5K_SREV_VER_AR5416) &&
++ (srev < AR5K_SREV_VER_AR2425)) {
+ ATH5K_ERR(sc, "Device not yet supported.\n");
+ ret = -ENODEV;
+ goto err_free;
++ } else if (srev == AR5K_SREV_VER_AR2425) {
++ ATH5K_WARN(sc, "Support for RF2425 is under development.\n");
+ }
+
+ /* Identify single chip solutions */
+- if((srev <= AR5K_SREV_VER_AR5414) &&
+- (srev >= AR5K_SREV_VER_AR2424)) {
++ if (((srev <= AR5K_SREV_VER_AR5414) &&
++ (srev >= AR5K_SREV_VER_AR2413)) ||
++ (srev == AR5K_SREV_VER_AR2425)) {
+ ah->ah_single_chip = true;
+ } else {
+ ah->ah_single_chip = false;
+@@ -226,15 +289,87 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
+ ah->ah_radio = AR5K_RF5110;
+ } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112) {
+ ah->ah_radio = AR5K_RF5111;
+- } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) {
++ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5111;
++ } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC0) {
++
+ ah->ah_radio = AR5K_RF5112;
+- } else {
++
++ if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112A) {
++ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112;
++ } else {
++ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A;
++ }
++
++ } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) {
++ ah->ah_radio = AR5K_RF2413;
++ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A;
++ } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC2) {
+ ah->ah_radio = AR5K_RF5413;
++ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A;
++ } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5133) {
++
++ /* AR5424 */
++ if (srev >= AR5K_SREV_VER_AR5424) {
++ ah->ah_radio = AR5K_RF5413;
++ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5424;
++ /* AR2424 */
++ } else {
++ ah->ah_radio = AR5K_RF2413; /* For testing */
++ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A;
++ }
++
++ /*
++ * Register returns 0x4 for radio revision
++ * so ath5k_hw_radio_revision doesn't parse the value
++ * correctly. For now we are based on mac's srev to
++ * identify RF2425 radio.
++ */
++ } else if (srev == AR5K_SREV_VER_AR2425) {
++ ah->ah_radio = AR5K_RF2425;
++ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112;
+ }
+
+ ah->ah_phy = AR5K_PHY(0);
+
+ /*
++ * Identify AR5212-based PCI-E cards
++ * And write some initial settings.
++ *
++ * (doing a "strings" on ndis driver
++ * -ar5211.sys- reveals the following
++ * pci-e related functions:
++ *
++ * pcieClockReq
++ * pcieRxErrNotify
++ * pcieL1SKPEnable
++ * pcieAspm
++ * pcieDisableAspmOnRfWake
++ * pciePowerSaveEnable
++ *
++ * I guess these point to ClockReq but
++ * i'm not sure.)
++ */
++ if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) {
++ ath5k_hw_reg_write(ah, 0x9248fc00, 0x4080);
++ ath5k_hw_reg_write(ah, 0x24924924, 0x4080);
++ ath5k_hw_reg_write(ah, 0x28000039, 0x4080);
++ ath5k_hw_reg_write(ah, 0x53160824, 0x4080);
++ ath5k_hw_reg_write(ah, 0xe5980579, 0x4080);
++ ath5k_hw_reg_write(ah, 0x001defff, 0x4080);
++ ath5k_hw_reg_write(ah, 0x1aaabe40, 0x4080);
++ ath5k_hw_reg_write(ah, 0xbe105554, 0x4080);
++ ath5k_hw_reg_write(ah, 0x000e3007, 0x4080);
++ ath5k_hw_reg_write(ah, 0x00000000, 0x4084);
++ }
++
++ /*
++ * POST
++ */
++ ret = ath5k_hw_post(ah);
++ if (ret)
++ goto err_free;
++
++ /*
+ * Get card capabilities, values, ...
+ */
+
+@@ -280,7 +415,8 @@ err:
+ */
+ static int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
+ {
+- u32 turbo, mode, clock;
++ struct pci_dev *pdev = ah->ah_sc->pdev;
++ u32 turbo, mode, clock, bus_flags;
+ int ret;
+
+ turbo = 0;
+@@ -357,10 +493,16 @@ static int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
+ AR5K_PHY_TURBO);
+ }
+
+- /* ...reset chipset and PCI device */
+- if (ah->ah_single_chip == false && ath5k_hw_nic_reset(ah,
+- AR5K_RESET_CTL_CHIP | AR5K_RESET_CTL_PCI)) {
+- ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip + PCI\n");
++ /* reseting PCI on PCI-E cards results card to hang
++ * and always return 0xffff... so we ingore that flag
++ * for PCI-E cards */
++ bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
++
++ /* Reset chipset */
++ ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
++ AR5K_RESET_CTL_BASEBAND | bus_flags);
++ if (ret) {
++ ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n");
+ return -EIO;
+ }
+
+@@ -405,15 +547,15 @@ const struct ath5k_rate_table *ath5k_hw_get_rate_table(struct ath5k_hw *ah,
+
+ /* Get rate tables */
+ switch (mode) {
+- case MODE_IEEE80211A:
++ case AR5K_MODE_11A:
+ return &ath5k_rt_11a;
+- case MODE_ATHEROS_TURBO:
++ case AR5K_MODE_11A_TURBO:
+ return &ath5k_rt_turbo;
+- case MODE_IEEE80211B:
++ case AR5K_MODE_11B:
+ return &ath5k_rt_11b;
+- case MODE_IEEE80211G:
++ case AR5K_MODE_11G:
+ return &ath5k_rt_11g;
+- case MODE_ATHEROS_TURBOG:
++ case AR5K_MODE_11G_TURBO:
+ return &ath5k_rt_xr;
+ }
+
+@@ -459,15 +601,15 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
+ ds_coef_exp, ds_coef_man, clock;
+
+ if (!(ah->ah_version == AR5K_AR5212) ||
+- !(channel->val & CHANNEL_OFDM))
++ !(channel->hw_value & CHANNEL_OFDM))
+ BUG();
+
+ /* Seems there are two PLLs, one for baseband sampling and one
+ * for tuning. Tuning basebands are 40 MHz or 80MHz when in
+ * turbo. */
+- clock = channel->val & CHANNEL_TURBO ? 80 : 40;
++ clock = channel->hw_value & CHANNEL_TURBO ? 80 : 40;
+ coef_scaled = ((5 * (clock << 24)) / 2) /
+- channel->freq;
++ channel->center_freq;
+
+ for (coef_exp = 31; coef_exp > 0; coef_exp--)
+ if ((coef_scaled >> coef_exp) & 0x1)
+@@ -494,8 +636,7 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
+ * ath5k_hw_write_rate_duration - set rate duration during hw resets
+ *
+ * @ah: the &struct ath5k_hw
+- * @driver_mode: one of enum ieee80211_phymode or our one of our own
+- * vendor modes
++ * @mode: one of enum ath5k_driver_mode
+ *
+ * Write the rate duration table for the current mode upon hw reset. This
+ * is a helper for ath5k_hw_reset(). It seems all this is doing is setting
+@@ -506,19 +647,20 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
+ *
+ */
+ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
+- unsigned int driver_mode)
++ unsigned int mode)
+ {
+ struct ath5k_softc *sc = ah->ah_sc;
+ const struct ath5k_rate_table *rt;
++ struct ieee80211_rate srate = {};
+ unsigned int i;
+
+ /* Get rate table for the current operating mode */
+- rt = ath5k_hw_get_rate_table(ah,
+- driver_mode);
++ rt = ath5k_hw_get_rate_table(ah, mode);
+
+ /* Write rate duration table */
+ for (i = 0; i < rt->rate_count; i++) {
+ const struct ath5k_rate *rate, *control_rate;
++
+ u32 reg;
+ u16 tx_time;
+
+@@ -528,14 +670,16 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
+ /* Set ACK timeout */
+ reg = AR5K_RATE_DUR(rate->rate_code);
+
++ srate.bitrate = control_rate->rate_kbps/100;
++
+ /* An ACK frame consists of 10 bytes. If you add the FCS,
+ * which ieee80211_generic_frame_duration() adds,
+ * its 14 bytes. Note we use the control rate and not the
+ * actual rate for this rate. See mac80211 tx.c
+ * ieee80211_duration() for a brief description of
+ * what rate we should choose to TX ACKs. */
+- tx_time = ieee80211_generic_frame_duration(sc->hw,
+- sc->vif, 10, control_rate->rate_kbps/100);
++ tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw,
++ sc->vif, 10, &srate));
+
+ ath5k_hw_reg_write(ah, tx_time, reg);
+
+@@ -568,8 +712,9 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ struct ieee80211_channel *channel, bool change_channel)
+ {
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+- u32 data, s_seq, s_ant, s_led[3];
+- unsigned int i, mode, freq, ee_mode, ant[2], driver_mode = -1;
++ struct pci_dev *pdev = ah->ah_sc->pdev;
++ u32 data, s_seq, s_ant, s_led[3], dma_size;
++ unsigned int i, mode, freq, ee_mode, ant[2];
+ int ret;
+
+ ATH5K_TRACE(ah->ah_sc);
+@@ -585,7 +730,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ */
+ /*DCU/Antenna selection not available on 5210*/
+ if (ah->ah_version != AR5K_AR5210) {
+- if (change_channel == true) {
++ if (change_channel) {
+ /* Seq number for queue 0 -do this for all queues ? */
+ s_seq = ath5k_hw_reg_read(ah,
+ AR5K_QUEUE_DFS_SEQNUM(0));
+@@ -599,12 +744,12 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR);
+ s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO);
+
+- if (change_channel == true && ah->ah_rf_banks != NULL)
++ if (change_channel && ah->ah_rf_banks != NULL)
+ ath5k_hw_get_rf_gain(ah);
+
+
+ /*Wakeup the device*/
+- ret = ath5k_hw_nic_wakeup(ah, channel->val, false);
++ ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false);
+ if (ret)
+ return ret;
+
+@@ -620,43 +765,40 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ if (ah->ah_version != AR5K_AR5210) {
+ if (ah->ah_radio != AR5K_RF5111 &&
+ ah->ah_radio != AR5K_RF5112 &&
+- ah->ah_radio != AR5K_RF5413) {
++ ah->ah_radio != AR5K_RF5413 &&
++ ah->ah_radio != AR5K_RF2413 &&
++ ah->ah_radio != AR5K_RF2425) {
+ ATH5K_ERR(ah->ah_sc,
+ "invalid phy radio: %u\n", ah->ah_radio);
+ return -EINVAL;
+ }
+
+- switch (channel->val & CHANNEL_MODES) {
++ switch (channel->hw_value & CHANNEL_MODES) {
+ case CHANNEL_A:
+- mode = AR5K_INI_VAL_11A;
++ mode = AR5K_MODE_11A;
+ freq = AR5K_INI_RFGAIN_5GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11A;
+- driver_mode = MODE_IEEE80211A;
+ break;
+ case CHANNEL_G:
+- mode = AR5K_INI_VAL_11G;
++ mode = AR5K_MODE_11G;
+ freq = AR5K_INI_RFGAIN_2GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11G;
+- driver_mode = MODE_IEEE80211G;
+ break;
+ case CHANNEL_B:
+- mode = AR5K_INI_VAL_11B;
++ mode = AR5K_MODE_11B;
+ freq = AR5K_INI_RFGAIN_2GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11B;
+- driver_mode = MODE_IEEE80211B;
+ break;
+ case CHANNEL_T:
+- mode = AR5K_INI_VAL_11A_TURBO;
++ mode = AR5K_MODE_11A_TURBO;
+ freq = AR5K_INI_RFGAIN_5GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11A;
+- driver_mode = MODE_ATHEROS_TURBO;
+ break;
+ /*Is this ok on 5211 too ?*/
+ case CHANNEL_TG:
+- mode = AR5K_INI_VAL_11G_TURBO;
++ mode = AR5K_MODE_11G_TURBO;
+ freq = AR5K_INI_RFGAIN_2GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11G;
+- driver_mode = MODE_ATHEROS_TURBOG;
+ break;
+ case CHANNEL_XR:
+ if (ah->ah_version == AR5K_AR5211) {
+@@ -664,14 +806,13 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ "XR mode not available on 5211");
+ return -EINVAL;
+ }
+- mode = AR5K_INI_VAL_XR;
++ mode = AR5K_MODE_XR;
+ freq = AR5K_INI_RFGAIN_5GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11A;
+- driver_mode = MODE_IEEE80211A;
+ break;
+ default:
+ ATH5K_ERR(ah->ah_sc,
+- "invalid channel: %d\n", channel->freq);
++ "invalid channel: %d\n", channel->center_freq);
+ return -EINVAL;
+ }
+
+@@ -701,15 +842,26 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ /*
+ * Write some more initial register settings
+ */
+- if (ah->ah_version > AR5K_AR5211){ /* found on 5213+ */
++ if (ah->ah_version == AR5K_AR5212) {
+ ath5k_hw_reg_write(ah, 0x0002a002, AR5K_PHY(11));
+
+- if (channel->val == CHANNEL_G)
+- ath5k_hw_reg_write(ah, 0x00f80d80, AR5K_PHY(83)); /* 0x00fc0ec0 */
++ if (channel->hw_value == CHANNEL_G)
++ if (ah->ah_mac_srev < AR5K_SREV_VER_AR2413)
++ ath5k_hw_reg_write(ah, 0x00f80d80,
++ AR5K_PHY(83));
++ else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2424)
++ ath5k_hw_reg_write(ah, 0x00380140,
++ AR5K_PHY(83));
++ else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2425)
++ ath5k_hw_reg_write(ah, 0x00fc0ec0,
++ AR5K_PHY(83));
++ else /* 2425 */
++ ath5k_hw_reg_write(ah, 0x00fc0fc0,
++ AR5K_PHY(83));
+ else
+- ath5k_hw_reg_write(ah, 0x00000000, AR5K_PHY(83));
++ ath5k_hw_reg_write(ah, 0x00000000,
++ AR5K_PHY(83));
+
+- ath5k_hw_reg_write(ah, 0x000001b5, 0xa228); /* 0x000009b5 */
+ ath5k_hw_reg_write(ah, 0x000009b5, 0xa228);
+ ath5k_hw_reg_write(ah, 0x0000000f, 0x8060);
+ ath5k_hw_reg_write(ah, 0x00000000, 0xa254);
+@@ -722,7 +874,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ AR5K_SREV_RAD_5112A) {
+ ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
+ AR5K_PHY_CCKTXCTL);
+- if (channel->val & CHANNEL_5GHZ)
++ if (channel->hw_value & CHANNEL_5GHZ)
+ data = 0xffb81020;
+ else
+ data = 0xffb80d20;
+@@ -742,7 +894,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ * mac80211 are integrated */
+ if (ah->ah_version == AR5K_AR5212 &&
+ ah->ah_sc->vif != NULL)
+- ath5k_hw_write_rate_duration(ah, driver_mode);
++ ath5k_hw_write_rate_duration(ah, mode);
+
+ /*
+ * Write RF registers
+@@ -758,7 +910,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+
+ /* Write OFDM timings on 5212*/
+ if (ah->ah_version == AR5K_AR5212 &&
+- channel->val & CHANNEL_OFDM) {
++ channel->hw_value & CHANNEL_OFDM) {
+ ret = ath5k_hw_write_ofdm_timings(ah, channel);
+ if (ret)
+ return ret;
+@@ -767,7 +919,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ /*Enable/disable 802.11b mode on 5111
+ (enable 2111 frequency converter + CCK)*/
+ if (ah->ah_radio == AR5K_RF5111) {
+- if (driver_mode == MODE_IEEE80211B)
++ if (mode == AR5K_MODE_11B)
+ AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_B_MODE);
+ else
+@@ -885,13 +1037,24 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+
+ /*
+ * Set Rx/Tx DMA Configuration
+- *(passing dma size not available on 5210)
++ *
++ * Set maximum DMA size (512) except for PCI-E cards since
++ * it causes rx overruns and tx errors (tested on 5424 but since
++ * rx overruns also occur on 5416/5418 with madwifi we set 128
++ * for all PCI-E cards to be safe).
++ *
++ * In dumps this is 128 for allchips.
++ *
++ * XXX: need to check 5210 for this
++ * TODO: Check out tx triger level, it's always 64 on dumps but I
++ * guess we can tweak it and see how it goes ;-)
+ */
++ dma_size = (pdev->is_pcie) ? AR5K_DMASIZE_128B : AR5K_DMASIZE_512B;
+ if (ah->ah_version != AR5K_AR5210) {
+- AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_SDMAMR,
+- AR5K_DMASIZE_512B | AR5K_TXCFG_DMASIZE);
+- AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_SDMAMW,
+- AR5K_DMASIZE_512B);
++ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
++ AR5K_TXCFG_SDMAMR, dma_size);
++ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
++ AR5K_RXCFG_SDMAMW, dma_size);
+ }
+
+ /*
+@@ -905,7 +1068,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ if (ah->ah_version != AR5K_AR5210) {
+ data = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
+ AR5K_PHY_RX_DELAY_M;
+- data = (channel->val & CHANNEL_CCK) ?
++ data = (channel->hw_value & CHANNEL_CCK) ?
+ ((data << 2) / 22) : (data / 10);
+
+ udelay(100 + data);
+@@ -922,11 +1085,11 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
+ AR5K_PHY_AGCCTL_CAL, 0, false)) {
+ ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n",
+- channel->freq);
++ channel->center_freq);
+ return -EAGAIN;
+ }
+
+- ret = ath5k_hw_noise_floor_calibration(ah, channel->freq);
++ ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
+ if (ret)
+ return ret;
+
+@@ -934,7 +1097,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+
+ /* A and G modes can use QAM modulation which requires enabling
+ * I and Q calibration. Don't bother in B mode. */
+- if (!(driver_mode == MODE_IEEE80211B)) {
++ if (!(mode == AR5K_MODE_11B)) {
+ ah->ah_calibration = true;
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
+ AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
+@@ -981,6 +1144,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+
+ /*
+ * Set the 32MHz reference clock on 5212 phy clock sleep register
++ *
++ * TODO: Find out how to switch to external 32Khz clock to save power
+ */
+ if (ah->ah_version == AR5K_AR5212) {
+ ath5k_hw_reg_write(ah, AR5K_PHY_SCR_32MHZ, AR5K_PHY_SCR);
+@@ -988,9 +1153,15 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ, AR5K_PHY_SCAL);
+ ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK);
+ ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY);
+- ath5k_hw_reg_write(ah, ah->ah_radio == AR5K_RF5111 ?
+- AR5K_PHY_SPENDING_RF5111 : AR5K_PHY_SPENDING_RF5112,
+- AR5K_PHY_SPENDING);
++ ath5k_hw_reg_write(ah, ah->ah_phy_spending, AR5K_PHY_SPENDING);
++ }
++
++ if (ah->ah_version == AR5K_AR5212) {
++ ath5k_hw_reg_write(ah, 0x000100aa, 0x8118);
++ ath5k_hw_reg_write(ah, 0x00003210, 0x811c);
++ ath5k_hw_reg_write(ah, 0x00000052, 0x8108);
++ if (ah->ah_mac_srev >= AR5K_SREV_VER_AR2413)
++ ath5k_hw_reg_write(ah, 0x00000004, 0x8120);
+ }
+
+ /*
+@@ -1065,7 +1236,7 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
+ staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA;
+ /* fallthrough */
+ case AR5K_PM_NETWORK_SLEEP:
+- if (set_chip == true)
++ if (set_chip)
+ ath5k_hw_reg_write(ah,
+ AR5K_SLEEP_CTL_SLE | sleep_duration,
+ AR5K_SLEEP_CTL);
+@@ -1074,7 +1245,7 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
+ break;
+
+ case AR5K_PM_FULL_SLEEP:
+- if (set_chip == true)
++ if (set_chip)
+ ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP,
+ AR5K_SLEEP_CTL);
+
+@@ -1082,7 +1253,7 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
+ break;
+
+ case AR5K_PM_AWAKE:
+- if (set_chip == false)
++ if (!set_chip)
+ goto commit;
+
+ ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_WAKE,
+@@ -1389,7 +1560,7 @@ int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase)
+ trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG),
+ AR5K_TXCFG_TXFULL);
+
+- if (increase == false) {
++ if (!increase) {
+ if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES)
+ goto done;
+ } else
+@@ -1592,9 +1763,10 @@ static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data)
+ /*
+ * Write to eeprom - currently disabled, use at your own risk
+ */
++#if 0
+ static int ath5k_hw_eeprom_write(struct ath5k_hw *ah, u32 offset, u16 data)
+ {
+-#if 0
++
+ u32 status, timeout;
+
+ ATH5K_TRACE(ah->ah_sc);
+@@ -1636,10 +1808,11 @@ static int ath5k_hw_eeprom_write(struct ath5k_hw *ah, u32 offset, u16 data)
+ }
+ udelay(15);
+ }
+-#endif
++
+ ATH5K_ERR(ah->ah_sc, "EEPROM Write is disabled!");
+ return -EIO;
+ }
++#endif
+
+ /*
+ * Translate binary channel representation in EEPROM to frequency
+@@ -2045,50 +2218,6 @@ static int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
+ }
+
+ /*
+- * Read/Write regulatory domain
+- */
+-static bool ath5k_eeprom_regulation_domain(struct ath5k_hw *ah, bool write,
+- enum ath5k_regdom *regdomain)
+-{
+- u16 ee_regdomain;
+-
+- /* Read current value */
+- if (write != true) {
+- ee_regdomain = ah->ah_capabilities.cap_eeprom.ee_regdomain;
+- *regdomain = ath5k_regdom_to_ieee(ee_regdomain);
+- return true;
+- }
+-
+- ee_regdomain = ath5k_regdom_from_ieee(*regdomain);
+-
+- /* Try to write a new value */
+- if (ah->ah_capabilities.cap_eeprom.ee_protect &
+- AR5K_EEPROM_PROTECT_WR_128_191)
+- return false;
+- if (ath5k_hw_eeprom_write(ah, AR5K_EEPROM_REG_DOMAIN, ee_regdomain)!=0)
+- return false;
+-
+- ah->ah_capabilities.cap_eeprom.ee_regdomain = ee_regdomain;
+-
+- return true;
+-}
+-
+-/*
+- * Use the above to write a new regulatory domain
+- */
+-int ath5k_hw_set_regdomain(struct ath5k_hw *ah, u16 regdomain)
+-{
+- enum ath5k_regdom ieee_regdomain;
+-
+- ieee_regdomain = ath5k_regdom_to_ieee(regdomain);
+-
+- if (ath5k_eeprom_regulation_domain(ah, true, &ieee_regdomain) == true)
+- return 0;
+-
+- return -EIO;
+-}
+-
+-/*
+ * Fill the capabilities struct
+ */
+ static int ath5k_hw_get_capabilities(struct ath5k_hw *ah)
+@@ -2110,8 +2239,8 @@ static int ath5k_hw_get_capabilities(struct ath5k_hw *ah)
+ ah->ah_capabilities.cap_range.range_2ghz_max = 0;
+
+ /* Set supported modes */
+- __set_bit(MODE_IEEE80211A, ah->ah_capabilities.cap_mode);
+- __set_bit(MODE_ATHEROS_TURBO, ah->ah_capabilities.cap_mode);
++ __set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode);
++ __set_bit(AR5K_MODE_11A_TURBO, ah->ah_capabilities.cap_mode);
+ } else {
+ /*
+ * XXX The tranceiver supports frequencies from 4920 to 6100GHz
+@@ -2133,12 +2262,12 @@ static int ath5k_hw_get_capabilities(struct ath5k_hw *ah)
+ ah->ah_capabilities.cap_range.range_5ghz_max = 6100;
+
+ /* Set supported modes */
+- __set_bit(MODE_IEEE80211A,
++ __set_bit(AR5K_MODE_11A,
+ ah->ah_capabilities.cap_mode);
+- __set_bit(MODE_ATHEROS_TURBO,
++ __set_bit(AR5K_MODE_11A_TURBO,
+ ah->ah_capabilities.cap_mode);
+ if (ah->ah_version == AR5K_AR5212)
+- __set_bit(MODE_ATHEROS_TURBOG,
++ __set_bit(AR5K_MODE_11G_TURBO,
+ ah->ah_capabilities.cap_mode);
+ }
+
+@@ -2150,11 +2279,11 @@ static int ath5k_hw_get_capabilities(struct ath5k_hw *ah)
+ ah->ah_capabilities.cap_range.range_2ghz_max = 2732;
+
+ if (AR5K_EEPROM_HDR_11B(ee_header))
+- __set_bit(MODE_IEEE80211B,
++ __set_bit(AR5K_MODE_11B,
+ ah->ah_capabilities.cap_mode);
+
+ if (AR5K_EEPROM_HDR_11G(ee_header))
+- __set_bit(MODE_IEEE80211G,
++ __set_bit(AR5K_MODE_11G,
+ ah->ah_capabilities.cap_mode);
+ }
+ }
+@@ -2279,8 +2408,8 @@ void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id)
+ * Set simple BSSID mask on 5212
+ */
+ if (ah->ah_version == AR5K_AR5212) {
+- ath5k_hw_reg_write(ah, 0xfffffff, AR5K_BSS_IDM0);
+- ath5k_hw_reg_write(ah, 0xfffffff, AR5K_BSS_IDM1);
++ ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM0);
++ ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM1);
+ }
+
+ /*
+@@ -2425,6 +2554,8 @@ void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
+ {
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
++
++ /* TODO: ANI Support */
+ }
+
+ /*
+@@ -2434,6 +2565,8 @@ void ath5k_hw_stop_pcu_recv(struct ath5k_hw *ah)
+ {
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
++
++ /* TODO: ANI Support */
+ }
+
+ /*
+@@ -2828,15 +2961,19 @@ int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr)
+ * Update mib counters (statistics)
+ */
+ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah,
+- struct ath5k_mib_stats *statistics)
++ struct ieee80211_low_level_stats *stats)
+ {
+ ATH5K_TRACE(ah->ah_sc);
++
+ /* Read-And-Clear */
+- statistics->ackrcv_bad += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL);
+- statistics->rts_bad += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL);
+- statistics->rts_good += ath5k_hw_reg_read(ah, AR5K_RTS_OK);
+- statistics->fcs_bad += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL);
+- statistics->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT);
++ stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL);
++ stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL);
++ stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK);
++ stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL);
++
++ /* XXX: Should we use this to track beacon count ?
++ * -we read it anyway to clear the register */
++ ath5k_hw_reg_read(ah, AR5K_BEACON_CNT);
+
+ /* Reset profile count registers on 5212*/
+ if (ah->ah_version == AR5K_AR5212) {
+@@ -2937,8 +3074,16 @@ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
+ for (i = 0; i < AR5K_KEYCACHE_SIZE; i++)
+ ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i));
+
+- /* Set NULL encryption on non-5210*/
+- if (ah->ah_version != AR5K_AR5210)
++ /*
++ * Set NULL encryption on AR5212+
++ *
++ * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5)
++ * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007
++ *
++ * Note2: Windows driver (ndiswrapper) sets this to
++ * 0x00000714 instead of 0x00000007
++ */
++ if (ah->ah_version > AR5K_AR5211)
+ ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
+ AR5K_KEYTABLE_TYPE(entry));
+
+@@ -3186,19 +3331,19 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
+ return 0;
+
+ /* Set Slot time */
+- ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
++ ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME,
+ AR5K_SLOT_TIME);
+ /* Set ACK_CTS timeout */
+- ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
++ ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ AR5K_INIT_ACK_CTS_TIMEOUT_TURBO :
+ AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME);
+ /* Set Transmit Latency */
+- ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
++ ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ AR5K_INIT_TRANSMIT_LATENCY_TURBO :
+ AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210);
+ /* Set IFS0 */
+- if (ah->ah_turbo == true)
++ if (ah->ah_turbo)
+ ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO +
+ (ah->ah_aifs + tq->tqi_aifs) *
+ AR5K_INIT_SLOT_TIME_TURBO) <<
+@@ -3211,16 +3356,16 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
+ AR5K_INIT_SIFS, AR5K_IFS0);
+
+ /* Set IFS1 */
+- ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
++ ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ AR5K_INIT_PROTO_TIME_CNTRL_TURBO :
+ AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1);
+ /* Set PHY register 0x9844 (??) */
+- ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
++ ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ (ath5k_hw_reg_read(ah, AR5K_PHY(17)) & ~0x7F) | 0x38 :
+ (ath5k_hw_reg_read(ah, AR5K_PHY(17)) & ~0x7F) | 0x1C,
+ AR5K_PHY(17));
+ /* Set Frame Control Register */
+- ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
++ ath5k_hw_reg_write(ah, ah->ah_turbo ?
+ (AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE |
+ AR5K_PHY_TURBO_SHORT | 0x2020) :
+ (AR5K_PHY_FRAME_CTL_INI | 0x1020),
+@@ -3259,7 +3404,7 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
+ /*
+ * Calculate and set retry limits
+ */
+- if (ah->ah_software_retry == true) {
++ if (ah->ah_software_retry) {
+ /* XXX Need to test this */
+ retry_lg = ah->ah_limit_tx_retries;
+ retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ?
+@@ -3507,10 +3652,10 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ unsigned int rtscts_rate, unsigned int rtscts_duration)
+ {
+ u32 frame_type;
+- struct ath5k_hw_2w_tx_desc *tx_desc;
++ struct ath5k_hw_2w_tx_ctl *tx_ctl;
+ unsigned int frame_len;
+
+- tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0;
++ tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
+
+ /*
+ * Validate input
+@@ -3529,12 +3674,8 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ return -EINVAL;
+ }
+
+- /* Clear status descriptor */
+- memset(desc->ds_hw, 0, sizeof(struct ath5k_hw_tx_status));
+-
+- /* Initialize control descriptor */
+- tx_desc->tx_control_0 = 0;
+- tx_desc->tx_control_1 = 0;
++ /* Clear descriptor */
++ memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc));
+
+ /* Setup control descriptor */
+
+@@ -3546,7 +3687,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
+ return -EINVAL;
+
+- tx_desc->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
++ tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
+
+ /* Verify and set buffer length */
+
+@@ -3557,7 +3698,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
+ return -EINVAL;
+
+- tx_desc->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
++ tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
+
+ /*
+ * Verify and set header length
+@@ -3566,7 +3707,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ if (ah->ah_version == AR5K_AR5210) {
+ if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN)
+ return -EINVAL;
+- tx_desc->tx_control_0 |=
++ tx_ctl->tx_control_0 |=
+ AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN);
+ }
+
+@@ -3582,19 +3723,19 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ frame_type = type /*<< 2 ?*/;
+ }
+
+- tx_desc->tx_control_0 |=
++ tx_ctl->tx_control_0 |=
+ AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) |
+ AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
+ } else {
+- tx_desc->tx_control_0 |=
++ tx_ctl->tx_control_0 |=
+ AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) |
+ AR5K_REG_SM(antenna_mode, AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT);
+- tx_desc->tx_control_1 |=
++ tx_ctl->tx_control_1 |=
+ AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE);
+ }
+ #define _TX_FLAGS(_c, _flag) \
+ if (flags & AR5K_TXDESC_##_flag) \
+- tx_desc->tx_control_##_c |= \
++ tx_ctl->tx_control_##_c |= \
+ AR5K_2W_TX_DESC_CTL##_c##_##_flag
+
+ _TX_FLAGS(0, CLRDMASK);
+@@ -3609,9 +3750,9 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ * WEP crap
+ */
+ if (key_index != AR5K_TXKEYIX_INVALID) {
+- tx_desc->tx_control_0 |=
++ tx_ctl->tx_control_0 |=
+ AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
+- tx_desc->tx_control_1 |=
++ tx_ctl->tx_control_1 |=
+ AR5K_REG_SM(key_index,
+ AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
+ }
+@@ -3621,7 +3762,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ */
+ if ((ah->ah_version == AR5K_AR5210) &&
+ (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)))
+- tx_desc->tx_control_1 |= rtscts_duration &
++ tx_ctl->tx_control_1 |= rtscts_duration &
+ AR5K_2W_TX_DESC_CTL1_RTS_DURATION;
+
+ return 0;
+@@ -3637,13 +3778,11 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
+ unsigned int antenna_mode, unsigned int flags, unsigned int rtscts_rate,
+ unsigned int rtscts_duration)
+ {
+- struct ath5k_hw_4w_tx_desc *tx_desc;
+- struct ath5k_hw_tx_status *tx_status;
++ struct ath5k_hw_4w_tx_ctl *tx_ctl;
+ unsigned int frame_len;
+
+ ATH5K_TRACE(ah->ah_sc);
+- tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
+- tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[2];
++ tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
+
+ /*
+ * Validate input
+@@ -3662,14 +3801,8 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
+ return -EINVAL;
+ }
+
+- /* Clear status descriptor */
+- memset(tx_status, 0, sizeof(struct ath5k_hw_tx_status));
+-
+- /* Initialize control descriptor */
+- tx_desc->tx_control_0 = 0;
+- tx_desc->tx_control_1 = 0;
+- tx_desc->tx_control_2 = 0;
+- tx_desc->tx_control_3 = 0;
++ /* Clear descriptor */
++ memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));
+
+ /* Setup control descriptor */
+
+@@ -3681,7 +3814,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
+ if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
+ return -EINVAL;
+
+- tx_desc->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
++ tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
+
+ /* Verify and set buffer length */
+
+@@ -3692,20 +3825,20 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
+ if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
+ return -EINVAL;
+
+- tx_desc->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
++ tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
+
+- tx_desc->tx_control_0 |=
++ tx_ctl->tx_control_0 |=
+ AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
+ AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
+- tx_desc->tx_control_1 |= AR5K_REG_SM(type,
++ tx_ctl->tx_control_1 |= AR5K_REG_SM(type,
+ AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
+- tx_desc->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
++ tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
+ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
+- tx_desc->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
++ tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
+
+ #define _TX_FLAGS(_c, _flag) \
+ if (flags & AR5K_TXDESC_##_flag) \
+- tx_desc->tx_control_##_c |= \
++ tx_ctl->tx_control_##_c |= \
+ AR5K_4W_TX_DESC_CTL##_c##_##_flag
+
+ _TX_FLAGS(0, CLRDMASK);
+@@ -3721,8 +3854,8 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
+ * WEP crap
+ */
+ if (key_index != AR5K_TXKEYIX_INVALID) {
+- tx_desc->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
+- tx_desc->tx_control_1 |= AR5K_REG_SM(key_index,
++ tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
++ tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index,
+ AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
+ }
+
+@@ -3733,9 +3866,9 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
+ if ((flags & AR5K_TXDESC_RTSENA) &&
+ (flags & AR5K_TXDESC_CTSENA))
+ return -EINVAL;
+- tx_desc->tx_control_2 |= rtscts_duration &
++ tx_ctl->tx_control_2 |= rtscts_duration &
+ AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
+- tx_desc->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
++ tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
+ AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
+ }
+
+@@ -3750,7 +3883,7 @@ ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, u_int tx_tries2,
+ unsigned int tx_rate3, u_int tx_tries3)
+ {
+- struct ath5k_hw_4w_tx_desc *tx_desc;
++ struct ath5k_hw_4w_tx_ctl *tx_ctl;
+
+ /*
+ * Rates can be 0 as long as the retry count is 0 too.
+@@ -3767,14 +3900,14 @@ ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ }
+
+ if (ah->ah_version == AR5K_AR5212) {
+- tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
++ tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
+
+ #define _XTX_TRIES(_n) \
+ if (tx_tries##_n) { \
+- tx_desc->tx_control_2 |= \
++ tx_ctl->tx_control_2 |= \
+ AR5K_REG_SM(tx_tries##_n, \
+ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n); \
+- tx_desc->tx_control_3 |= \
++ tx_ctl->tx_control_3 |= \
+ AR5K_REG_SM(tx_rate##_n, \
+ AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n); \
+ }
+@@ -3795,13 +3928,15 @@ ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ * Proccess the tx status descriptor on 5210/5211
+ */
+ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
+- struct ath5k_desc *desc)
++ struct ath5k_desc *desc, struct ath5k_tx_status *ts)
+ {
++ struct ath5k_hw_2w_tx_ctl *tx_ctl;
+ struct ath5k_hw_tx_status *tx_status;
+- struct ath5k_hw_2w_tx_desc *tx_desc;
+
+- tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0;
+- tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[0];
++ ATH5K_TRACE(ah->ah_sc);
++
++ tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
++ tx_status = &desc->ud.ds_tx5210.tx_stat;
+
+ /* No frame has been send or error */
+ if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
+@@ -3810,32 +3945,32 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
+ /*
+ * Get descriptor status
+ */
+- desc->ds_us.tx.ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
++ ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
+- desc->ds_us.tx.ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
++ ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
+- desc->ds_us.tx.ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
++ ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
+- /*TODO: desc->ds_us.tx.ts_virtcol + test*/
+- desc->ds_us.tx.ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
++ /*TODO: ts->ts_virtcol + test*/
++ ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_SEQ_NUM);
+- desc->ds_us.tx.ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
++ ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
+- desc->ds_us.tx.ts_antenna = 1;
+- desc->ds_us.tx.ts_status = 0;
+- desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_0,
++ ts->ts_antenna = 1;
++ ts->ts_status = 0;
++ ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_0,
+ AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
+
+ if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){
+ if (tx_status->tx_status_0 &
+ AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
+- desc->ds_us.tx.ts_status |= AR5K_TXERR_XRETRY;
++ ts->ts_status |= AR5K_TXERR_XRETRY;
+
+ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
+- desc->ds_us.tx.ts_status |= AR5K_TXERR_FIFO;
++ ts->ts_status |= AR5K_TXERR_FIFO;
+
+ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
+- desc->ds_us.tx.ts_status |= AR5K_TXERR_FILT;
++ ts->ts_status |= AR5K_TXERR_FILT;
+ }
+
+ return 0;
+@@ -3845,14 +3980,15 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
+ * Proccess a tx descriptor on 5212
+ */
+ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
+- struct ath5k_desc *desc)
++ struct ath5k_desc *desc, struct ath5k_tx_status *ts)
+ {
++ struct ath5k_hw_4w_tx_ctl *tx_ctl;
+ struct ath5k_hw_tx_status *tx_status;
+- struct ath5k_hw_4w_tx_desc *tx_desc;
+
+ ATH5K_TRACE(ah->ah_sc);
+- tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
+- tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[2];
++
++ tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
++ tx_status = &desc->ud.ds_tx5212.tx_stat;
+
+ /* No frame has been send or error */
+ if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
+@@ -3861,42 +3997,42 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
+ /*
+ * Get descriptor status
+ */
+- desc->ds_us.tx.ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
++ ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
+- desc->ds_us.tx.ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
++ ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
+- desc->ds_us.tx.ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
++ ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
+- desc->ds_us.tx.ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
++ ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_SEQ_NUM);
+- desc->ds_us.tx.ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
++ ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
+- desc->ds_us.tx.ts_antenna = (tx_status->tx_status_1 &
++ ts->ts_antenna = (tx_status->tx_status_1 &
+ AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1;
+- desc->ds_us.tx.ts_status = 0;
++ ts->ts_status = 0;
+
+ switch (AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX)) {
+ case 0:
+- desc->ds_us.tx.ts_rate = tx_desc->tx_control_3 &
++ ts->ts_rate = tx_ctl->tx_control_3 &
+ AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
+ break;
+ case 1:
+- desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
++ ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
+ AR5K_4W_TX_DESC_CTL3_XMIT_RATE1);
+- desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
++ ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
+ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
+ break;
+ case 2:
+- desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
++ ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
+ AR5K_4W_TX_DESC_CTL3_XMIT_RATE2);
+- desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
++ ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
+ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
+ break;
+ case 3:
+- desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
++ ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
+ AR5K_4W_TX_DESC_CTL3_XMIT_RATE3);
+- desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
++ ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
+ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3);
+ break;
+ }
+@@ -3904,13 +4040,13 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
+ if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){
+ if (tx_status->tx_status_0 &
+ AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
+- desc->ds_us.tx.ts_status |= AR5K_TXERR_XRETRY;
++ ts->ts_status |= AR5K_TXERR_XRETRY;
+
+ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
+- desc->ds_us.tx.ts_status |= AR5K_TXERR_FIFO;
++ ts->ts_status |= AR5K_TXERR_FIFO;
+
+ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
+- desc->ds_us.tx.ts_status |= AR5K_TXERR_FILT;
++ ts->ts_status |= AR5K_TXERR_FILT;
+ }
+
+ return 0;
+@@ -3926,31 +4062,27 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
+ int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ u32 size, unsigned int flags)
+ {
+- struct ath5k_rx_desc *rx_desc;
++ struct ath5k_hw_rx_ctl *rx_ctl;
+
+ ATH5K_TRACE(ah->ah_sc);
+- rx_desc = (struct ath5k_rx_desc *)&desc->ds_ctl0;
++ rx_ctl = &desc->ud.ds_rx.rx_ctl;
+
+ /*
+- *Clear ds_hw
++ * Clear the descriptor
+ * If we don't clean the status descriptor,
+ * while scanning we get too many results,
+ * most of them virtual, after some secs
+ * of scanning system hangs. M.F.
+ */
+- memset(desc->ds_hw, 0, sizeof(desc->ds_hw));
+-
+- /*Initialize rx descriptor*/
+- rx_desc->rx_control_0 = 0;
+- rx_desc->rx_control_1 = 0;
++ memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc));
+
+ /* Setup descriptor */
+- rx_desc->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
+- if (unlikely(rx_desc->rx_control_1 != size))
++ rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
++ if (unlikely(rx_ctl->rx_control_1 != size))
+ return -EINVAL;
+
+ if (flags & AR5K_RXDESC_INTREQ)
+- rx_desc->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
++ rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
+
+ return 0;
+ }
+@@ -3958,67 +4090,68 @@ int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ /*
+ * Proccess the rx status descriptor on 5210/5211
+ */
+-static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *ah,
+- struct ath5k_desc *desc)
++static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
++ struct ath5k_desc *desc, struct ath5k_rx_status *rs)
+ {
+- struct ath5k_hw_old_rx_status *rx_status;
++ struct ath5k_hw_rx_status *rx_status;
+
+- rx_status = (struct ath5k_hw_old_rx_status *)&desc->ds_hw[0];
++ rx_status = &desc->ud.ds_rx.u.rx_stat;
+
+ /* No frame received / not ready */
+- if (unlikely((rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_DONE)
++ if (unlikely((rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_DONE)
+ == 0))
+ return -EINPROGRESS;
+
+ /*
+ * Frame receive status
+ */
+- desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 &
+- AR5K_OLD_RX_DESC_STATUS0_DATA_LEN;
+- desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
+- AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL);
+- desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
+- AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE);
+- desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 &
+- AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA;
+- desc->ds_us.rx.rs_more = rx_status->rx_status_0 &
+- AR5K_OLD_RX_DESC_STATUS0_MORE;
+- desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
+- AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
+- desc->ds_us.rx.rs_status = 0;
++ rs->rs_datalen = rx_status->rx_status_0 &
++ AR5K_5210_RX_DESC_STATUS0_DATA_LEN;
++ rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
++ AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL);
++ rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
++ AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE);
++ rs->rs_antenna = rx_status->rx_status_0 &
++ AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA;
++ rs->rs_more = rx_status->rx_status_0 &
++ AR5K_5210_RX_DESC_STATUS0_MORE;
++ /* TODO: this timestamp is 13 bit, later on we assume 15 bit */
++ rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
++ AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
++ rs->rs_status = 0;
+
+ /*
+ * Key table status
+ */
+- if (rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_VALID)
+- desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
+- AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX);
++ if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID)
++ rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
++ AR5K_5210_RX_DESC_STATUS1_KEY_INDEX);
+ else
+- desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID;
++ rs->rs_keyix = AR5K_RXKEYIX_INVALID;
+
+ /*
+ * Receive/descriptor errors
+ */
+- if ((rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_FRAME_RECEIVE_OK)
+- == 0) {
+- if (rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_CRC_ERROR)
+- desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC;
++ if ((rx_status->rx_status_1 &
++ AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
++ if (rx_status->rx_status_1 &
++ AR5K_5210_RX_DESC_STATUS1_CRC_ERROR)
++ rs->rs_status |= AR5K_RXERR_CRC;
+
+ if (rx_status->rx_status_1 &
+- AR5K_OLD_RX_DESC_STATUS1_FIFO_OVERRUN)
+- desc->ds_us.rx.rs_status |= AR5K_RXERR_FIFO;
++ AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN)
++ rs->rs_status |= AR5K_RXERR_FIFO;
+
+ if (rx_status->rx_status_1 &
+- AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR) {
+- desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY;
+- desc->ds_us.rx.rs_phyerr =
+- AR5K_REG_MS(rx_status->rx_status_1,
+- AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR);
++ AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) {
++ rs->rs_status |= AR5K_RXERR_PHY;
++ rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1,
++ AR5K_5210_RX_DESC_STATUS1_PHY_ERROR);
+ }
+
+ if (rx_status->rx_status_1 &
+- AR5K_OLD_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
+- desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT;
++ AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
++ rs->rs_status |= AR5K_RXERR_DECRYPT;
+ }
+
+ return 0;
+@@ -4027,71 +4160,72 @@ static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *ah,
+ /*
+ * Proccess the rx status descriptor on 5212
+ */
+-static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *ah,
+- struct ath5k_desc *desc)
++static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
++ struct ath5k_desc *desc, struct ath5k_rx_status *rs)
+ {
+- struct ath5k_hw_new_rx_status *rx_status;
++ struct ath5k_hw_rx_status *rx_status;
+ struct ath5k_hw_rx_error *rx_err;
+
+ ATH5K_TRACE(ah->ah_sc);
+- rx_status = (struct ath5k_hw_new_rx_status *)&desc->ds_hw[0];
++ rx_status = &desc->ud.ds_rx.u.rx_stat;
+
+ /* Overlay on error */
+- rx_err = (struct ath5k_hw_rx_error *)&desc->ds_hw[0];
++ rx_err = &desc->ud.ds_rx.u.rx_err;
+
+ /* No frame received / not ready */
+- if (unlikely((rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_DONE)
++ if (unlikely((rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_DONE)
+ == 0))
+ return -EINPROGRESS;
+
+ /*
+ * Frame receive status
+ */
+- desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 &
+- AR5K_NEW_RX_DESC_STATUS0_DATA_LEN;
+- desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
+- AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL);
+- desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
+- AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE);
+- desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 &
+- AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA;
+- desc->ds_us.rx.rs_more = rx_status->rx_status_0 &
+- AR5K_NEW_RX_DESC_STATUS0_MORE;
+- desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
+- AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
+- desc->ds_us.rx.rs_status = 0;
++ rs->rs_datalen = rx_status->rx_status_0 &
++ AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
++ rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
++ AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
++ rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
++ AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
++ rs->rs_antenna = rx_status->rx_status_0 &
++ AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA;
++ rs->rs_more = rx_status->rx_status_0 &
++ AR5K_5212_RX_DESC_STATUS0_MORE;
++ rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
++ AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
++ rs->rs_status = 0;
+
+ /*
+ * Key table status
+ */
+- if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_VALID)
+- desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
+- AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX);
++ if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
++ rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
++ AR5K_5212_RX_DESC_STATUS1_KEY_INDEX);
+ else
+- desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID;
++ rs->rs_keyix = AR5K_RXKEYIX_INVALID;
+
+ /*
+ * Receive/descriptor errors
+ */
+ if ((rx_status->rx_status_1 &
+- AR5K_NEW_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
+- if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_CRC_ERROR)
+- desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC;
++ AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
++ if (rx_status->rx_status_1 &
++ AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
++ rs->rs_status |= AR5K_RXERR_CRC;
+
+ if (rx_status->rx_status_1 &
+- AR5K_NEW_RX_DESC_STATUS1_PHY_ERROR) {
+- desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY;
+- desc->ds_us.rx.rs_phyerr =
+- AR5K_REG_MS(rx_err->rx_error_1,
+- AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
++ AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
++ rs->rs_status |= AR5K_RXERR_PHY;
++ rs->rs_phyerr = AR5K_REG_MS(rx_err->rx_error_1,
++ AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
+ }
+
+ if (rx_status->rx_status_1 &
+- AR5K_NEW_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
+- desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT;
++ AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
++ rs->rs_status |= AR5K_RXERR_DECRYPT;
+
+- if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_MIC_ERROR)
+- desc->ds_us.rx.rs_status |= AR5K_RXERR_MIC;
++ if (rx_status->rx_status_1 &
++ AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
++ rs->rs_status |= AR5K_RXERR_MIC;
+ }
+
+ return 0;
+@@ -4250,35 +4384,6 @@ void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio,
+ }
+
+
+-/*********************************\
+- Regulatory Domain/Channels Setup
+-\*********************************/
+-
+-u16 ath5k_get_regdomain(struct ath5k_hw *ah)
+-{
+- u16 regdomain;
+- enum ath5k_regdom ieee_regdomain;
+-#ifdef COUNTRYCODE
+- u16 code;
+-#endif
+-
+- ath5k_eeprom_regulation_domain(ah, false, &ieee_regdomain);
+- ah->ah_capabilities.cap_regdomain.reg_hw = ieee_regdomain;
+-
+-#ifdef COUNTRYCODE
+- /*
+- * Get the regulation domain by country code. This will ignore
+- * the settings found in the EEPROM.
+- */
+- code = ieee80211_name2countrycode(COUNTRYCODE);
+- ieee_regdomain = ieee80211_countrycode2regdomain(code);
+-#endif
+-
+- regdomain = ath5k_regdom_from_ieee(ieee_regdomain);
+- ah->ah_capabilities.cap_regdomain.reg_current = regdomain;
+-
+- return regdomain;
+-}
+
+
+ /****************\
+diff --git a/drivers/net/wireless/ath5k/hw.h b/drivers/net/wireless/ath5k/hw.h
+index d9a7c09..64fca8d 100644
+--- a/drivers/net/wireless/ath5k/hw.h
++++ b/drivers/net/wireless/ath5k/hw.h
+@@ -173,7 +173,10 @@ struct ath5k_eeprom_info {
+ * (rX: reserved fields possibily used by future versions of the ar5k chipset)
+ */
+
+-struct ath5k_rx_desc {
++/*
++ * common hardware RX control descriptor
++ */
++struct ath5k_hw_rx_ctl {
+ u32 rx_control_0; /* RX control word 0 */
+
+ #define AR5K_DESC_RX_CTL0 0x00000000
+@@ -185,69 +188,63 @@ struct ath5k_rx_desc {
+ } __packed;
+
+ /*
+- * 5210/5211 rx status descriptor
++ * common hardware RX status descriptor
++ * 5210/11 and 5212 differ only in the flags defined below
+ */
+-struct ath5k_hw_old_rx_status {
++struct ath5k_hw_rx_status {
+ u32 rx_status_0; /* RX status word 0 */
+-
+-#define AR5K_OLD_RX_DESC_STATUS0_DATA_LEN 0x00000fff
+-#define AR5K_OLD_RX_DESC_STATUS0_MORE 0x00001000
+-#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000
+-#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE_S 15
+-#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000
+-#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19
+-#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000
+-#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27
+-
+ u32 rx_status_1; /* RX status word 1 */
+-
+-#define AR5K_OLD_RX_DESC_STATUS1_DONE 0x00000001
+-#define AR5K_OLD_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002
+-#define AR5K_OLD_RX_DESC_STATUS1_CRC_ERROR 0x00000004
+-#define AR5K_OLD_RX_DESC_STATUS1_FIFO_OVERRUN 0x00000008
+-#define AR5K_OLD_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010
+-#define AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR 0x000000e0
+-#define AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR_S 5
+-#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100
+-#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX 0x00007e00
+-#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_S 9
+-#define AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000
+-#define AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15
+-#define AR5K_OLD_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000
+ } __packed;
+
++/* 5210/5211 */
++#define AR5K_5210_RX_DESC_STATUS0_DATA_LEN 0x00000fff
++#define AR5K_5210_RX_DESC_STATUS0_MORE 0x00001000
++#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000
++#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE_S 15
++#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000
++#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19
++#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000
++#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27
++#define AR5K_5210_RX_DESC_STATUS1_DONE 0x00000001
++#define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002
++#define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR 0x00000004
++#define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN 0x00000008
++#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010
++#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR 0x000000e0
++#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S 5
++#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100
++#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX 0x00007e00
++#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S 9
++#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000
++#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15
++#define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000
++
++/* 5212 */
++#define AR5K_5212_RX_DESC_STATUS0_DATA_LEN 0x00000fff
++#define AR5K_5212_RX_DESC_STATUS0_MORE 0x00001000
++#define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000
++#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000
++#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE_S 15
++#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000
++#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20
++#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000
++#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28
++#define AR5K_5212_RX_DESC_STATUS1_DONE 0x00000001
++#define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002
++#define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR 0x00000004
++#define AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008
++#define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR 0x00000010
++#define AR5K_5212_RX_DESC_STATUS1_MIC_ERROR 0x00000020
++#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100
++#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00
++#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_S 9
++#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000
++#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 16
++#define AR5K_5212_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000
++
+ /*
+- * 5212 rx status descriptor
++ * common hardware RX error descriptor
+ */
+-struct ath5k_hw_new_rx_status {
+- u32 rx_status_0; /* RX status word 0 */
+-
+-#define AR5K_NEW_RX_DESC_STATUS0_DATA_LEN 0x00000fff
+-#define AR5K_NEW_RX_DESC_STATUS0_MORE 0x00001000
+-#define AR5K_NEW_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000
+-#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000
+-#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE_S 15
+-#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000
+-#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20
+-#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000
+-#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28
+-
+- u32 rx_status_1; /* RX status word 1 */
+-
+-#define AR5K_NEW_RX_DESC_STATUS1_DONE 0x00000001
+-#define AR5K_NEW_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002
+-#define AR5K_NEW_RX_DESC_STATUS1_CRC_ERROR 0x00000004
+-#define AR5K_NEW_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008
+-#define AR5K_NEW_RX_DESC_STATUS1_PHY_ERROR 0x00000010
+-#define AR5K_NEW_RX_DESC_STATUS1_MIC_ERROR 0x00000020
+-#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100
+-#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00
+-#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_S 9
+-#define AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000
+-#define AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 16
+-#define AR5K_NEW_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000
+-} __packed;
+-
+ struct ath5k_hw_rx_error {
+ u32 rx_error_0; /* RX error word 0 */
+
+@@ -268,7 +265,10 @@ struct ath5k_hw_rx_error {
+ #define AR5K_DESC_RX_PHY_ERROR_SERVICE 0xc0
+ #define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR 0xe0
+
+-struct ath5k_hw_2w_tx_desc {
++/*
++ * 5210/5211 hardware 2-word TX control descriptor
++ */
++struct ath5k_hw_2w_tx_ctl {
+ u32 tx_control_0; /* TX control word 0 */
+
+ #define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff
+@@ -314,9 +314,9 @@ struct ath5k_hw_2w_tx_desc {
+ #define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 0x10
+
+ /*
+- * 5212 4-word tx control descriptor
++ * 5212 hardware 4-word TX control descriptor
+ */
+-struct ath5k_hw_4w_tx_desc {
++struct ath5k_hw_4w_tx_ctl {
+ u32 tx_control_0; /* TX control word 0 */
+
+ #define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff
+@@ -374,7 +374,7 @@ struct ath5k_hw_4w_tx_desc {
+ } __packed;
+
+ /*
+- * Common tx status descriptor
++ * Common TX status descriptor
+ */
+ struct ath5k_hw_tx_status {
+ u32 tx_status_0; /* TX status word 0 */
+@@ -415,6 +415,34 @@ struct ath5k_hw_tx_status {
+
+
+ /*
++ * 5210/5211 hardware TX descriptor
++ */
++struct ath5k_hw_5210_tx_desc {
++ struct ath5k_hw_2w_tx_ctl tx_ctl;
++ struct ath5k_hw_tx_status tx_stat;
++} __packed;
++
++/*
++ * 5212 hardware TX descriptor
++ */
++struct ath5k_hw_5212_tx_desc {
++ struct ath5k_hw_4w_tx_ctl tx_ctl;
++ struct ath5k_hw_tx_status tx_stat;
++} __packed;
++
++/*
++ * common hardware RX descriptor
++ */
++struct ath5k_hw_all_rx_desc {
++ struct ath5k_hw_rx_ctl rx_ctl;
++ union {
++ struct ath5k_hw_rx_status rx_stat;
++ struct ath5k_hw_rx_error rx_err;
++ } u;
++} __packed;
++
++
++/*
+ * AR5K REGISTER ACCESS
+ */
+
+diff --git a/drivers/net/wireless/ath5k/initvals.c b/drivers/net/wireless/ath5k/initvals.c
+index 2c22f1d..04c84e9 100644
+--- a/drivers/net/wireless/ath5k/initvals.c
++++ b/drivers/net/wireless/ath5k/initvals.c
+@@ -678,8 +678,8 @@ static const struct ath5k_ini ar5212_ini[] = {
+ { AR5K_PHY(644), 0x00806333 },
+ { AR5K_PHY(645), 0x00106c10 },
+ { AR5K_PHY(646), 0x009c4060 },
+- /*{ AR5K_PHY(647), 0x1483800a },*/ /* Old value */
+ { AR5K_PHY(647), 0x1483800a },
++ /* { AR5K_PHY(648), 0x018830c6 },*/ /* 2413 */
+ { AR5K_PHY(648), 0x01831061 },
+ { AR5K_PHY(649), 0x00000400 },
+ /*{ AR5K_PHY(650), 0x000001b5 },*/
+@@ -1081,6 +1081,414 @@ static const struct ath5k_ini_mode rf5413_ini_mode_end[] = {
+ { 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0 } },
+ };
+
++/* Initial mode-specific settings for RF2413/2414 (Written after ar5212_ini) */
++/* XXX: No dumps for turbog yet, so turbog is the same with g here with some
++ * minor tweaking based on dumps from other chips */
++static const struct ath5k_ini_mode rf2413_ini_mode_end[] = {
++ { AR5K_TXCFG,
++ /* b g gTurbo */
++ { 0x00000015, 0x00000015, 0x00000015 } },
++ { AR5K_USEC_5211,
++ { 0x04e01395, 0x12e013ab, 0x098813cf } },
++ { AR5K_PHY(10),
++ { 0x05020000, 0x0a020001, 0x0a020001 } },
++ { AR5K_PHY(13),
++ { 0x00000e00, 0x00000e00, 0x00000e00 } },
++ { AR5K_PHY(14),
++ { 0x0000000a, 0x0000000a, 0x0000000a } },
++ { AR5K_PHY(18),
++ { 0x001a6a64, 0x001a6a64, 0x001a6a64 } },
++ { AR5K_PHY(20),
++ { 0x0de8b0da, 0x0c98b0da, 0x0c98b0da } },
++ { AR5K_PHY_SIG,
++ { 0x7ee80d2e, 0x7ec80d2e, 0x7ec80d2e } },
++ { AR5K_PHY_AGCCOARSE,
++ { 0x3137665e, 0x3139605e, 0x3139605e } },
++ { AR5K_PHY(27),
++ { 0x050cb081, 0x050cb081, 0x050cb081 } },
++ { AR5K_PHY_RX_DELAY,
++ { 0x0000044c, 0x00000898, 0x000007d0 } },
++ { AR5K_PHY_FRAME_CTL_5211,
++ { 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
++ { AR5K_PHY_CCKTXCTL,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { AR5K_PHY(642),
++ { 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
++ { AR5K_PHY_GAIN_2GHZ,
++ { 0x0042c140, 0x0042c140, 0x0042c140 } },
++ { 0xa21c,
++ { 0x1863800a, 0x1883800a, 0x1883800a } },
++ { AR5K_DCU_FP,
++ { 0x000003e0, 0x000003e0, 0x000003e0 } },
++ { 0x8060,
++ { 0x0000000f, 0x0000000f, 0x0000000f } },
++ { 0x8118,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 0x811c,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 0x8120,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 0x8124,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 0x8128,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 0x812c,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 0x8130,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 0x8134,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 0x8138,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 0x813c,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 0x8140,
++ { 0x800000a8, 0x800000a8, 0x800000a8 } },
++ { 0x8144,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { AR5K_PHY_AGC,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { AR5K_PHY(11),
++ { 0x0000a000, 0x0000a000, 0x0000a000 } },
++ { AR5K_PHY(15),
++ { 0x00200400, 0x00200400, 0x00200400 } },
++ { AR5K_PHY(19),
++ { 0x1284233c, 0x1284233c, 0x1284233c } },
++ { AR5K_PHY_SCR,
++ { 0x0000001f, 0x0000001f, 0x0000001f } },
++ { AR5K_PHY_SLMT,
++ { 0x00000080, 0x00000080, 0x00000080 } },
++ { AR5K_PHY_SCAL,
++ { 0x0000000e, 0x0000000e, 0x0000000e } },
++ { AR5K_PHY(86),
++ { 0x000000ff, 0x000000ff, 0x000000ff } },
++ { AR5K_PHY(96),
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { AR5K_PHY(97),
++ { 0x02800000, 0x02800000, 0x02800000 } },
++ { AR5K_PHY(104),
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { AR5K_PHY(120),
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { AR5K_PHY(121),
++ { 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa } },
++ { AR5K_PHY(122),
++ { 0x3c466478, 0x3c466478, 0x3c466478 } },
++ { AR5K_PHY(123),
++ { 0x000000aa, 0x000000aa, 0x000000aa } },
++ { AR5K_PHY_SCLOCK,
++ { 0x0000000c, 0x0000000c, 0x0000000c } },
++ { AR5K_PHY_SDELAY,
++ { 0x000000ff, 0x000000ff, 0x000000ff } },
++ { AR5K_PHY_SPENDING,
++ { 0x00000014, 0x00000014, 0x00000014 } },
++ { 0xa228,
++ { 0x000009b5, 0x000009b5, 0x000009b5 } },
++ { 0xa23c,
++ { 0x93c889af, 0x93c889af, 0x93c889af } },
++ { 0xa24c,
++ { 0x00000001, 0x00000001, 0x00000001 } },
++ { 0xa250,
++ { 0x0000a000, 0x0000a000, 0x0000a000 } },
++ { 0xa254,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 0xa258,
++ { 0x0cc75380, 0x0cc75380, 0x0cc75380 } },
++ { 0xa25c,
++ { 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01 } },
++ { 0xa260,
++ { 0x5f690f01, 0x5f690f01, 0x5f690f01 } },
++ { 0xa264,
++ { 0x00418a11, 0x00418a11, 0x00418a11 } },
++ { 0xa268,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 0xa26c,
++ { 0x0c30c16a, 0x0c30c16a, 0x0c30c16a } },
++ { 0xa270,
++ { 0x00820820, 0x00820820, 0x00820820 } },
++ { 0xa274,
++ { 0x001b7caa, 0x001b7caa, 0x001b7caa } },
++ { 0xa278,
++ { 0x1ce739ce, 0x1ce739ce, 0x1ce739ce } },
++ { 0xa27c,
++ { 0x051701ce, 0x051701ce, 0x051701ce } },
++ { 0xa300,
++ { 0x18010000, 0x18010000, 0x18010000 } },
++ { 0xa304,
++ { 0x30032602, 0x30032602, 0x30032602 } },
++ { 0xa308,
++ { 0x48073e06, 0x48073e06, 0x48073e06 } },
++ { 0xa30c,
++ { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } },
++ { 0xa310,
++ { 0x641a600f, 0x641a600f, 0x641a600f } },
++ { 0xa314,
++ { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } },
++ { 0xa318,
++ { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } },
++ { 0xa31c,
++ { 0x8ecf865b, 0x8ecf865b, 0x8ecf865b } },
++ { 0xa320,
++ { 0x9d4f970f, 0x9d4f970f, 0x9d4f970f } },
++ { 0xa324,
++ { 0xa5cfa18f, 0xa5cfa18f, 0xa5cfa18f } },
++ { 0xa328,
++ { 0xb55faf1f, 0xb55faf1f, 0xb55faf1f } },
++ { 0xa32c,
++ { 0xbddfb99f, 0xbddfb99f, 0xbddfb99f } },
++ { 0xa330,
++ { 0xcd7fc73f, 0xcd7fc73f, 0xcd7fc73f } },
++ { 0xa334,
++ { 0xd5ffd1bf, 0xd5ffd1bf, 0xd5ffd1bf } },
++ { 0xa338,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 0xa33c,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 0xa340,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 0xa344,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 0xa348,
++ { 0x3fffffff, 0x3fffffff, 0x3fffffff } },
++ { 0xa34c,
++ { 0x3fffffff, 0x3fffffff, 0x3fffffff } },
++ { 0xa350,
++ { 0x3fffffff, 0x3fffffff, 0x3fffffff } },
++ { 0xa354,
++ { 0x0003ffff, 0x0003ffff, 0x0003ffff } },
++ { 0xa358,
++ { 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f } },
++ { 0xa35c,
++ { 0x066c420f, 0x066c420f, 0x066c420f } },
++ { 0xa360,
++ { 0x0f282207, 0x0f282207, 0x0f282207 } },
++ { 0xa364,
++ { 0x17601685, 0x17601685, 0x17601685 } },
++ { 0xa368,
++ { 0x1f801104, 0x1f801104, 0x1f801104 } },
++ { 0xa36c,
++ { 0x37a00c03, 0x37a00c03, 0x37a00c03 } },
++ { 0xa370,
++ { 0x3fc40883, 0x3fc40883, 0x3fc40883 } },
++ { 0xa374,
++ { 0x57c00803, 0x57c00803, 0x57c00803 } },
++ { 0xa378,
++ { 0x5fd80682, 0x5fd80682, 0x5fd80682 } },
++ { 0xa37c,
++ { 0x7fe00482, 0x7fe00482, 0x7fe00482 } },
++ { 0xa380,
++ { 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba } },
++ { 0xa384,
++ { 0xf3307ff0, 0xf3307ff0, 0xf3307ff0 } },
++};
++
++/* Initial mode-specific settings for RF2425 (Written after ar5212_ini) */
++/* XXX: No dumps for turbog yet, so turbog is the same with g here with some
++ * minor tweaking based on dumps from other chips */
++static const struct ath5k_ini_mode rf2425_ini_mode_end[] = {
++ { AR5K_TXCFG,
++ /* g gTurbo */
++ { 0x00000015, 0x00000015 } },
++ { AR5K_USEC_5211,
++ { 0x12e013ab, 0x098813cf } },
++ { AR5K_PHY_TURBO,
++ { 0x00000000, 0x00000003 } },
++ { AR5K_PHY(10),
++ { 0x0a020001, 0x0a020001 } },
++ { AR5K_PHY(13),
++ { 0x00000e0e, 0x00000e0e } },
++ { AR5K_PHY(14),
++ { 0x0000000b, 0x0000000b } },
++ { AR5K_PHY(17),
++ { 0x13721422, 0x13721422 } },
++ { AR5K_PHY(18),
++ { 0x00199a65, 0x00199a65 } },
++ { AR5K_PHY(20),
++ { 0x0c98b0da, 0x0c98b0da } },
++ { AR5K_PHY_SIG,
++ { 0x7ec80d2e, 0x7ec80d2e } },
++ { AR5K_PHY_AGCCOARSE,
++ { 0x3139605e, 0x3139605e } },
++ { AR5K_PHY(27),
++ { 0x050cb081, 0x050cb081 } },
++ { AR5K_PHY_RX_DELAY,
++ { 0x00000898, 0x000007d0 } },
++ { AR5K_PHY_FRAME_CTL_5211,
++ { 0xf7b81000, 0xf7b81000 } },
++ { AR5K_PHY_CCKTXCTL,
++ { 0x00000000, 0x00000000 } },
++ { AR5K_PHY(642),
++ { 0xd03e6788, 0xd03e6788 } },
++ { AR5K_PHY_GAIN_2GHZ,
++ { 0x0052c140, 0x0052c140 } },
++ { 0xa21c,
++ { 0x1883800a, 0x1883800a } },
++ { 0xa324,
++ { 0xa7cfa7cf, 0xa7cfa7cf } },
++ { 0xa328,
++ { 0xa7cfa7cf, 0xa7cfa7cf } },
++ { 0xa32c,
++ { 0xa7cfa7cf, 0xa7cfa7cf } },
++ { 0xa330,
++ { 0xa7cfa7cf, 0xa7cfa7cf } },
++ { 0xa334,
++ { 0xa7cfa7cf, 0xa7cfa7cf } },
++ { AR5K_DCU_FP,
++ { 0x000003e0, 0x000003e0 } },
++ { 0x8060,
++ { 0x0000000f, 0x0000000f } },
++ { 0x809c,
++ { 0x00000000, 0x00000000 } },
++ { 0x80a0,
++ { 0x00000000, 0x00000000 } },
++ { 0x8118,
++ { 0x00000000, 0x00000000 } },
++ { 0x811c,
++ { 0x00000000, 0x00000000 } },
++ { 0x8120,
++ { 0x00000000, 0x00000000 } },
++ { 0x8124,
++ { 0x00000000, 0x00000000 } },
++ { 0x8128,
++ { 0x00000000, 0x00000000 } },
++ { 0x812c,
++ { 0x00000000, 0x00000000 } },
++ { 0x8130,
++ { 0x00000000, 0x00000000 } },
++ { 0x8134,
++ { 0x00000000, 0x00000000 } },
++ { 0x8138,
++ { 0x00000000, 0x00000000 } },
++ { 0x813c,
++ { 0x00000000, 0x00000000 } },
++ { 0x8140,
++ { 0x800003f9, 0x800003f9 } },
++ { 0x8144,
++ { 0x00000000, 0x00000000 } },
++ { AR5K_PHY_AGC,
++ { 0x00000000, 0x00000000 } },
++ { AR5K_PHY(11),
++ { 0x0000a000, 0x0000a000 } },
++ { AR5K_PHY(15),
++ { 0x00200400, 0x00200400 } },
++ { AR5K_PHY(19),
++ { 0x1284233c, 0x1284233c } },
++ { AR5K_PHY_SCR,
++ { 0x0000001f, 0x0000001f } },
++ { AR5K_PHY_SLMT,
++ { 0x00000080, 0x00000080 } },
++ { AR5K_PHY_SCAL,
++ { 0x0000000e, 0x0000000e } },
++ { AR5K_PHY(86),
++ { 0x00081fff, 0x00081fff } },
++ { AR5K_PHY(96),
++ { 0x00000000, 0x00000000 } },
++ { AR5K_PHY(97),
++ { 0x02800000, 0x02800000 } },
++ { AR5K_PHY(104),
++ { 0x00000000, 0x00000000 } },
++ { AR5K_PHY(119),
++ { 0xfebadbe8, 0xfebadbe8 } },
++ { AR5K_PHY(120),
++ { 0x00000000, 0x00000000 } },
++ { AR5K_PHY(121),
++ { 0xaaaaaaaa, 0xaaaaaaaa } },
++ { AR5K_PHY(122),
++ { 0x3c466478, 0x3c466478 } },
++ { AR5K_PHY(123),
++ { 0x000000aa, 0x000000aa } },
++ { AR5K_PHY_SCLOCK,
++ { 0x0000000c, 0x0000000c } },
++ { AR5K_PHY_SDELAY,
++ { 0x000000ff, 0x000000ff } },
++ { AR5K_PHY_SPENDING,
++ { 0x00000014, 0x00000014 } },
++ { 0xa228,
++ { 0x000009b5, 0x000009b5 } },
++ { AR5K_PHY_TXPOWER_RATE3,
++ { 0x20202020, 0x20202020 } },
++ { AR5K_PHY_TXPOWER_RATE4,
++ { 0x20202020, 0x20202020 } },
++ { 0xa23c,
++ { 0x93c889af, 0x93c889af } },
++ { 0xa24c,
++ { 0x00000001, 0x00000001 } },
++ { 0xa250,
++ { 0x0000a000, 0x0000a000 } },
++ { 0xa254,
++ { 0x00000000, 0x00000000 } },
++ { 0xa258,
++ { 0x0cc75380, 0x0cc75380 } },
++ { 0xa25c,
++ { 0x0f0f0f01, 0x0f0f0f01 } },
++ { 0xa260,
++ { 0x5f690f01, 0x5f690f01 } },
++ { 0xa264,
++ { 0x00418a11, 0x00418a11 } },
++ { 0xa268,
++ { 0x00000000, 0x00000000 } },
++ { 0xa26c,
++ { 0x0c30c166, 0x0c30c166 } },
++ { 0xa270,
++ { 0x00820820, 0x00820820 } },
++ { 0xa274,
++ { 0x081a3caa, 0x081a3caa } },
++ { 0xa278,
++ { 0x1ce739ce, 0x1ce739ce } },
++ { 0xa27c,
++ { 0x051701ce, 0x051701ce } },
++ { 0xa300,
++ { 0x16010000, 0x16010000 } },
++ { 0xa304,
++ { 0x2c032402, 0x2c032402 } },
++ { 0xa308,
++ { 0x48433e42, 0x48433e42 } },
++ { 0xa30c,
++ { 0x5a0f500b, 0x5a0f500b } },
++ { 0xa310,
++ { 0x6c4b624a, 0x6c4b624a } },
++ { 0xa314,
++ { 0x7e8b748a, 0x7e8b748a } },
++ { 0xa318,
++ { 0x96cf8ccb, 0x96cf8ccb } },
++ { 0xa31c,
++ { 0xa34f9d0f, 0xa34f9d0f } },
++ { 0xa320,
++ { 0xa7cfa58f, 0xa7cfa58f } },
++ { 0xa348,
++ { 0x3fffffff, 0x3fffffff } },
++ { 0xa34c,
++ { 0x3fffffff, 0x3fffffff } },
++ { 0xa350,
++ { 0x3fffffff, 0x3fffffff } },
++ { 0xa354,
++ { 0x0003ffff, 0x0003ffff } },
++ { 0xa358,
++ { 0x79a8aa1f, 0x79a8aa1f } },
++ { 0xa35c,
++ { 0x066c420f, 0x066c420f } },
++ { 0xa360,
++ { 0x0f282207, 0x0f282207 } },
++ { 0xa364,
++ { 0x17601685, 0x17601685 } },
++ { 0xa368,
++ { 0x1f801104, 0x1f801104 } },
++ { 0xa36c,
++ { 0x37a00c03, 0x37a00c03 } },
++ { 0xa370,
++ { 0x3fc40883, 0x3fc40883 } },
++ { 0xa374,
++ { 0x57c00803, 0x57c00803 } },
++ { 0xa378,
++ { 0x5fd80682, 0x5fd80682 } },
++ { 0xa37c,
++ { 0x7fe00482, 0x7fe00482 } },
++ { 0xa380,
++ { 0x7f3c7bba, 0x7f3c7bba } },
++ { 0xa384,
++ { 0xf3307ff0, 0xf3307ff0 } },
++};
++
+ /*
+ * Initial BaseBand Gain settings for RF5111/5112 (AR5210 comes with
+ * RF5110 only so initial BB Gain settings are included in AR5K_AR5210_INI)
+@@ -1290,35 +1698,92 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel)
+
+ /* Second set of mode-specific settings */
+ if (ah->ah_radio == AR5K_RF5111){
++
+ ath5k_hw_ini_mode_registers(ah,
+ ARRAY_SIZE(ar5212_rf5111_ini_mode_end),
+ ar5212_rf5111_ini_mode_end, mode);
++
+ /* Baseband gain table */
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf5111_ini_bbgain),
+ rf5111_ini_bbgain, change_channel);
++
+ } else if (ah->ah_radio == AR5K_RF5112){
++
+ ath5k_hw_ini_mode_registers(ah,
+ ARRAY_SIZE(ar5212_rf5112_ini_mode_end),
+ ar5212_rf5112_ini_mode_end, mode);
+- /* Baseband gain table */
++
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf5112_ini_bbgain),
+ rf5112_ini_bbgain, change_channel);
++
+ } else if (ah->ah_radio == AR5K_RF5413){
++
+ ath5k_hw_ini_mode_registers(ah,
+ ARRAY_SIZE(rf5413_ini_mode_end),
+ rf5413_ini_mode_end, mode);
++
++ ath5k_hw_ini_registers(ah,
++ ARRAY_SIZE(rf5112_ini_bbgain),
++ rf5112_ini_bbgain, change_channel);
++
++ } else if (ah->ah_radio == AR5K_RF2413) {
++
++ if (mode < 2) {
++ ATH5K_ERR(ah->ah_sc,
++ "unsupported channel mode: %d\n", mode);
++ return -EINVAL;
++ }
++ mode = mode - 2;
++
++ /* Override a setting from ar5212_ini */
++ ath5k_hw_reg_write(ah, 0x018830c6, AR5K_PHY(648));
++
++ ath5k_hw_ini_mode_registers(ah,
++ ARRAY_SIZE(rf2413_ini_mode_end),
++ rf2413_ini_mode_end, mode);
++
++ /* Baseband gain table */
++ ath5k_hw_ini_registers(ah,
++ ARRAY_SIZE(rf5112_ini_bbgain),
++ rf5112_ini_bbgain, change_channel);
++
++ } else if (ah->ah_radio == AR5K_RF2425) {
++
++ if (mode < 2) {
++ ATH5K_ERR(ah->ah_sc,
++ "unsupported channel mode: %d\n", mode);
++ return -EINVAL;
++ }
++
++ /* Map b to g */
++ if (mode == 2)
++ mode = 0;
++ else
++ mode = mode - 3;
++
++ /* Override a setting from ar5212_ini */
++ ath5k_hw_reg_write(ah, 0x018830c6, AR5K_PHY(648));
++
++ ath5k_hw_ini_mode_registers(ah,
++ ARRAY_SIZE(rf2425_ini_mode_end),
++ rf2425_ini_mode_end, mode);
++
+ /* Baseband gain table */
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf5112_ini_bbgain),
+ rf5112_ini_bbgain, change_channel);
++
+ }
++
+ /* For AR5211 */
+ } else if (ah->ah_version == AR5K_AR5211) {
+
+- if(mode > 2){ /* AR5K_INI_VAL_11B */
+- ATH5K_ERR(ah->ah_sc,"unsupported channel mode: %d\n", mode);
++ /* AR5K_MODE_11B */
++ if (mode > 2) {
++ ATH5K_ERR(ah->ah_sc,
++ "unsupported channel mode: %d\n", mode);
+ return -EINVAL;
+ }
+
+diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c
+index b959417..afd8689 100644
+--- a/drivers/net/wireless/ath5k/phy.c
++++ b/drivers/net/wireless/ath5k/phy.c
+@@ -666,6 +666,153 @@ static const struct ath5k_ini_rf rfregs_5413[] = {
+ { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+ };
+
++/* RF2413/2414 mode-specific init registers */
++static const struct ath5k_ini_rf rfregs_2413[] = {
++ { 1, AR5K_RF_BUFFER_CONTROL_4,
++ /* mode b mode g mode gTurbo */
++ { 0x00000020, 0x00000020, 0x00000020 } },
++ { 2, AR5K_RF_BUFFER_CONTROL_3,
++ { 0x02001408, 0x02001408, 0x02001408 } },
++ { 3, AR5K_RF_BUFFER_CONTROL_6,
++ { 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0xf0000000, 0xf0000000, 0xf0000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x03000000, 0x03000000, 0x03000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x40400000, 0x40400000, 0x40400000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x65050000, 0x65050000, 0x65050000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00420000, 0x00420000, 0x00420000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00b50000, 0x00b50000, 0x00b50000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00030000, 0x00030000, 0x00030000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00f70000, 0x00f70000, 0x00f70000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x009d0000, 0x009d0000, 0x009d0000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00220000, 0x00220000, 0x00220000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x04220000, 0x04220000, 0x04220000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00230018, 0x00230018, 0x00230018 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00280050, 0x00280050, 0x00280050 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x005000c3, 0x005000c3, 0x005000c3 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x0004007f, 0x0004007f, 0x0004007f } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00000458, 0x00000458, 0x00000458 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00000000, 0x00000000, 0x00000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x0000c000, 0x0000c000, 0x0000c000 } },
++ { 6, AR5K_RF_BUFFER_CONTROL_5,
++ { 0x00400230, 0x00400230, 0x00400230 } },
++ { 7, AR5K_RF_BUFFER,
++ { 0x00006400, 0x00006400, 0x00006400 } },
++ { 7, AR5K_RF_BUFFER,
++ { 0x00000800, 0x00000800, 0x00000800 } },
++ { 7, AR5K_RF_BUFFER_CONTROL_2,
++ { 0x0000000e, 0x0000000e, 0x0000000e } },
++};
++
++/* RF2425 mode-specific init registers */
++static const struct ath5k_ini_rf rfregs_2425[] = {
++ { 1, AR5K_RF_BUFFER_CONTROL_4,
++ /* mode g mode gTurbo */
++ { 0x00000020, 0x00000020 } },
++ { 2, AR5K_RF_BUFFER_CONTROL_3,
++ { 0x02001408, 0x02001408 } },
++ { 3, AR5K_RF_BUFFER_CONTROL_6,
++ { 0x00e020c0, 0x00e020c0 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x10000000, 0x10000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00000000, 0x00000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00000000, 0x00000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00000000, 0x00000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00000000, 0x00000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00000000, 0x00000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00000000, 0x00000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00000000, 0x00000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00000000, 0x00000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00000000, 0x00000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00000000, 0x00000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x002a0000, 0x002a0000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00000000, 0x00000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00000000, 0x00000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00100000, 0x00100000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00020000, 0x00020000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00730000, 0x00730000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00f80000, 0x00f80000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00e70000, 0x00e70000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00140000, 0x00140000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00910040, 0x00910040 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x0007001a, 0x0007001a } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00410000, 0x00410000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00810060, 0x00810060 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00020803, 0x00020803 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00000000, 0x00000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00000000, 0x00000000 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00001660, 0x00001660 } },
++ { 6, AR5K_RF_BUFFER,
++ { 0x00001688, 0x00001688 } },
++ { 6, AR5K_RF_BUFFER_CONTROL_1,
++ { 0x00000001, 0x00000001 } },
++ { 7, AR5K_RF_BUFFER,
++ { 0x00006400, 0x00006400 } },
++ { 7, AR5K_RF_BUFFER,
++ { 0x00000800, 0x00000800 } },
++ { 7, AR5K_RF_BUFFER_CONTROL_2,
++ { 0x0000000e, 0x0000000e } },
++};
+
+ /* Initial RF Gain settings for RF5112 */
+ static const struct ath5k_ini_rfgain rfgain_5112[] = {
+@@ -805,6 +952,74 @@ static const struct ath5k_ini_rfgain rfgain_5413[] = {
+ { AR5K_RF_GAIN(63), { 0x000000f9, 0x000000f9 } },
+ };
+
++/* Initial RF Gain settings for RF2413 */
++static const struct ath5k_ini_rfgain rfgain_2413[] = {
++ { AR5K_RF_GAIN(0), { 0x00000000 } },
++ { AR5K_RF_GAIN(1), { 0x00000040 } },
++ { AR5K_RF_GAIN(2), { 0x00000080 } },
++ { AR5K_RF_GAIN(3), { 0x00000181 } },
++ { AR5K_RF_GAIN(4), { 0x000001c1 } },
++ { AR5K_RF_GAIN(5), { 0x00000001 } },
++ { AR5K_RF_GAIN(6), { 0x00000041 } },
++ { AR5K_RF_GAIN(7), { 0x00000081 } },
++ { AR5K_RF_GAIN(8), { 0x00000168 } },
++ { AR5K_RF_GAIN(9), { 0x000001a8 } },
++ { AR5K_RF_GAIN(10), { 0x000001e8 } },
++ { AR5K_RF_GAIN(11), { 0x00000028 } },
++ { AR5K_RF_GAIN(12), { 0x00000068 } },
++ { AR5K_RF_GAIN(13), { 0x00000189 } },
++ { AR5K_RF_GAIN(14), { 0x000001c9 } },
++ { AR5K_RF_GAIN(15), { 0x00000009 } },
++ { AR5K_RF_GAIN(16), { 0x00000049 } },
++ { AR5K_RF_GAIN(17), { 0x00000089 } },
++ { AR5K_RF_GAIN(18), { 0x00000190 } },
++ { AR5K_RF_GAIN(19), { 0x000001d0 } },
++ { AR5K_RF_GAIN(20), { 0x00000010 } },
++ { AR5K_RF_GAIN(21), { 0x00000050 } },
++ { AR5K_RF_GAIN(22), { 0x00000090 } },
++ { AR5K_RF_GAIN(23), { 0x00000191 } },
++ { AR5K_RF_GAIN(24), { 0x000001d1 } },
++ { AR5K_RF_GAIN(25), { 0x00000011 } },
++ { AR5K_RF_GAIN(26), { 0x00000051 } },
++ { AR5K_RF_GAIN(27), { 0x00000091 } },
++ { AR5K_RF_GAIN(28), { 0x00000178 } },
++ { AR5K_RF_GAIN(29), { 0x000001b8 } },
++ { AR5K_RF_GAIN(30), { 0x000001f8 } },
++ { AR5K_RF_GAIN(31), { 0x00000038 } },
++ { AR5K_RF_GAIN(32), { 0x00000078 } },
++ { AR5K_RF_GAIN(33), { 0x00000199 } },
++ { AR5K_RF_GAIN(34), { 0x000001d9 } },
++ { AR5K_RF_GAIN(35), { 0x00000019 } },
++ { AR5K_RF_GAIN(36), { 0x00000059 } },
++ { AR5K_RF_GAIN(37), { 0x00000099 } },
++ { AR5K_RF_GAIN(38), { 0x000000d9 } },
++ { AR5K_RF_GAIN(39), { 0x000000f9 } },
++ { AR5K_RF_GAIN(40), { 0x000000f9 } },
++ { AR5K_RF_GAIN(41), { 0x000000f9 } },
++ { AR5K_RF_GAIN(42), { 0x000000f9 } },
++ { AR5K_RF_GAIN(43), { 0x000000f9 } },
++ { AR5K_RF_GAIN(44), { 0x000000f9 } },
++ { AR5K_RF_GAIN(45), { 0x000000f9 } },
++ { AR5K_RF_GAIN(46), { 0x000000f9 } },
++ { AR5K_RF_GAIN(47), { 0x000000f9 } },
++ { AR5K_RF_GAIN(48), { 0x000000f9 } },
++ { AR5K_RF_GAIN(49), { 0x000000f9 } },
++ { AR5K_RF_GAIN(50), { 0x000000f9 } },
++ { AR5K_RF_GAIN(51), { 0x000000f9 } },
++ { AR5K_RF_GAIN(52), { 0x000000f9 } },
++ { AR5K_RF_GAIN(53), { 0x000000f9 } },
++ { AR5K_RF_GAIN(54), { 0x000000f9 } },
++ { AR5K_RF_GAIN(55), { 0x000000f9 } },
++ { AR5K_RF_GAIN(56), { 0x000000f9 } },
++ { AR5K_RF_GAIN(57), { 0x000000f9 } },
++ { AR5K_RF_GAIN(58), { 0x000000f9 } },
++ { AR5K_RF_GAIN(59), { 0x000000f9 } },
++ { AR5K_RF_GAIN(60), { 0x000000f9 } },
++ { AR5K_RF_GAIN(61), { 0x000000f9 } },
++ { AR5K_RF_GAIN(62), { 0x000000f9 } },
++ { AR5K_RF_GAIN(63), { 0x000000f9 } },
++};
++
+ static const struct ath5k_gain_opt rfgain_opt_5112 = {
+ 1,
+ 8,
+@@ -844,14 +1059,14 @@ static unsigned int ath5k_hw_rfregs_op(u32 *rf, u32 offset, u32 reg, u32 bits,
+ entry = ((first - 1) / 8) + offset;
+ position = (first - 1) % 8;
+
+- if (set == true)
++ if (set)
+ data = ath5k_hw_bitswap(reg, bits);
+
+ for (i = shift = 0, left = bits; left > 0; position = 0, entry++, i++) {
+ last = (position + left > 8) ? 8 : position + left;
+ mask = (((1 << last) - 1) ^ ((1 << position) - 1)) << (col * 8);
+
+- if (set == true) {
++ if (set) {
+ rf[entry] &= ~mask;
+ rf[entry] |= ((data << position) << (col * 8)) & mask;
+ data >>= (8 - position);
+@@ -864,7 +1079,7 @@ static unsigned int ath5k_hw_rfregs_op(u32 *rf, u32 offset, u32 reg, u32 bits,
+ left -= 8 - position;
+ }
+
+- data = set == true ? 1 : ath5k_hw_bitswap(data, bits);
++ data = set ? 1 : ath5k_hw_bitswap(data, bits);
+
+ return data;
+ }
+@@ -955,7 +1170,6 @@ static s32 ath5k_hw_rfregs_gain_adjust(struct ath5k_hw *ah)
+ go = &rfgain_opt_5111;
+ break;
+ case AR5K_RF5112:
+- case AR5K_RF5413: /* ??? */
+ go = &rfgain_opt_5112;
+ break;
+ default:
+@@ -1018,7 +1232,7 @@ static int ath5k_hw_rf5111_rfregs(struct ath5k_hw *ah,
+ int obdb = -1, bank = -1;
+ u32 ee_mode;
+
+- AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
++ AR5K_ASSERT_ENTRY(mode, AR5K_MODE_MAX);
+
+ rf = ah->ah_rf_banks;
+
+@@ -1038,8 +1252,8 @@ static int ath5k_hw_rf5111_rfregs(struct ath5k_hw *ah,
+ }
+
+ /* Modify bank 0 */
+- if (channel->val & CHANNEL_2GHZ) {
+- if (channel->val & CHANNEL_CCK)
++ if (channel->hw_value & CHANNEL_2GHZ) {
++ if (channel->hw_value & CHANNEL_CCK)
+ ee_mode = AR5K_EEPROM_MODE_11B;
+ else
+ ee_mode = AR5K_EEPROM_MODE_11G;
+@@ -1058,10 +1272,10 @@ static int ath5k_hw_rf5111_rfregs(struct ath5k_hw *ah,
+ } else {
+ /* For 11a, Turbo and XR */
+ ee_mode = AR5K_EEPROM_MODE_11A;
+- obdb = channel->freq >= 5725 ? 3 :
+- (channel->freq >= 5500 ? 2 :
+- (channel->freq >= 5260 ? 1 :
+- (channel->freq > 4000 ? 0 : -1)));
++ obdb = channel->center_freq >= 5725 ? 3 :
++ (channel->center_freq >= 5500 ? 2 :
++ (channel->center_freq >= 5260 ? 1 :
++ (channel->center_freq > 4000 ? 0 : -1)));
+
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
+ ee->ee_pwd_84, 1, 51, 3, true))
+@@ -1119,12 +1333,12 @@ static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah,
+ int obdb = -1, bank = -1;
+ u32 ee_mode;
+
+- AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
++ AR5K_ASSERT_ENTRY(mode, AR5K_MODE_MAX);
+
+ rf = ah->ah_rf_banks;
+
+ if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_2112A
+- && !test_bit(MODE_IEEE80211A, ah->ah_capabilities.cap_mode)){
++ && !test_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode)) {
+ rf_ini = rfregs_2112a;
+ rf_size = ARRAY_SIZE(rfregs_5112a);
+ if (mode < 2) {
+@@ -1156,8 +1370,8 @@ static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah,
+ }
+
+ /* Modify bank 6 */
+- if (channel->val & CHANNEL_2GHZ) {
+- if (channel->val & CHANNEL_OFDM)
++ if (channel->hw_value & CHANNEL_2GHZ) {
++ if (channel->hw_value & CHANNEL_OFDM)
+ ee_mode = AR5K_EEPROM_MODE_11G;
+ else
+ ee_mode = AR5K_EEPROM_MODE_11B;
+@@ -1173,10 +1387,13 @@ static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah,
+ } else {
+ /* For 11a, Turbo and XR */
+ ee_mode = AR5K_EEPROM_MODE_11A;
+- obdb = channel->freq >= 5725 ? 3 :
+- (channel->freq >= 5500 ? 2 :
+- (channel->freq >= 5260 ? 1 :
+- (channel->freq > 4000 ? 0 : -1)));
++ obdb = channel->center_freq >= 5725 ? 3 :
++ (channel->center_freq >= 5500 ? 2 :
++ (channel->center_freq >= 5260 ? 1 :
++ (channel->center_freq > 4000 ? 0 : -1)));
++
++ if (obdb == -1)
++ return -EINVAL;
+
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
+ ee->ee_ob[ee_mode][obdb], 3, 279, 0, true))
+@@ -1209,7 +1426,8 @@ static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah,
+ }
+
+ /*
+- * Initialize RF5413/5414
++ * Initialize RF5413/5414 and future chips
++ * (until we come up with a better solution)
+ */
+ static int ath5k_hw_rf5413_rfregs(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel, unsigned int mode)
+@@ -1219,12 +1437,47 @@ static int ath5k_hw_rf5413_rfregs(struct ath5k_hw *ah,
+ unsigned int rf_size, i;
+ int bank = -1;
+
+- AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
++ AR5K_ASSERT_ENTRY(mode, AR5K_MODE_MAX);
+
+ rf = ah->ah_rf_banks;
+
+- rf_ini = rfregs_5413;
+- rf_size = ARRAY_SIZE(rfregs_5413);
++ switch (ah->ah_radio) {
++ case AR5K_RF5413:
++ rf_ini = rfregs_5413;
++ rf_size = ARRAY_SIZE(rfregs_5413);
++ break;
++ case AR5K_RF2413:
++ rf_ini = rfregs_2413;
++ rf_size = ARRAY_SIZE(rfregs_2413);
++
++ if (mode < 2) {
++ ATH5K_ERR(ah->ah_sc,
++ "invalid channel mode: %i\n", mode);
++ return -EINVAL;
++ }
++
++ mode = mode - 2;
++ break;
++ case AR5K_RF2425:
++ rf_ini = rfregs_2425;
++ rf_size = ARRAY_SIZE(rfregs_2425);
++
++ if (mode < 2) {
++ ATH5K_ERR(ah->ah_sc,
++ "invalid channel mode: %i\n", mode);
++ return -EINVAL;
++ }
++
++ /* Map b to g */
++ if (mode == 2)
++ mode = 0;
++ else
++ mode = mode - 3;
++
++ break;
++ default:
++ return -EINVAL;
++ }
+
+ /* Copy values to modify them */
+ for (i = 0; i < rf_size; i++) {
+@@ -1283,6 +1536,14 @@ int ath5k_hw_rfregs(struct ath5k_hw *ah, struct ieee80211_channel *channel,
+ ah->ah_rf_banks_size = sizeof(rfregs_5413);
+ func = ath5k_hw_rf5413_rfregs;
+ break;
++ case AR5K_RF2413:
++ ah->ah_rf_banks_size = sizeof(rfregs_2413);
++ func = ath5k_hw_rf5413_rfregs;
++ break;
++ case AR5K_RF2425:
++ ah->ah_rf_banks_size = sizeof(rfregs_2425);
++ func = ath5k_hw_rf5413_rfregs;
++ break;
+ default:
+ return -EINVAL;
+ }
+@@ -1321,6 +1582,16 @@ int ath5k_hw_rfgain(struct ath5k_hw *ah, unsigned int freq)
+ ath5k_rfg = rfgain_5413;
+ size = ARRAY_SIZE(rfgain_5413);
+ break;
++ case AR5K_RF2413:
++ ath5k_rfg = rfgain_2413;
++ size = ARRAY_SIZE(rfgain_2413);
++ freq = 0; /* only 2Ghz */
++ break;
++ case AR5K_RF2425:
++ ath5k_rfg = rfgain_2413;
++ size = ARRAY_SIZE(rfgain_2413);
++ freq = 0; /* only 2Ghz */
++ break;
+ default:
+ return -EINVAL;
+ }
+@@ -1395,7 +1666,6 @@ int ath5k_hw_set_rfgain_opt(struct ath5k_hw *ah)
+ ah->ah_gain.g_active = 1;
+ break;
+ case AR5K_RF5112:
+- case AR5K_RF5413: /* ??? */
+ ah->ah_gain.g_step_idx = rfgain_opt_5112.go_default;
+ ah->ah_gain.g_step =
+ &rfgain_opt_5112.go_step[ah->ah_gain.g_step_idx];
+@@ -1445,9 +1715,10 @@ static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel)
+ * newer chipsets like the AR5212A who have a completely
+ * different RF/PHY part.
+ */
+- athchan = (ath5k_hw_bitswap((channel->chan - 24) / 2, 5) << 1) |
+- (1 << 6) | 0x1;
+-
++ athchan = (ath5k_hw_bitswap(
++ (ieee80211_frequency_to_channel(
++ channel->center_freq) - 24) / 2, 5)
++ << 1) | (1 << 6) | 0x1;
+ return athchan;
+ }
+
+@@ -1506,7 +1777,8 @@ static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel)
+ {
+ struct ath5k_athchan_2ghz ath5k_channel_2ghz;
+- unsigned int ath5k_channel = channel->chan;
++ unsigned int ath5k_channel =
++ ieee80211_frequency_to_channel(channel->center_freq);
+ u32 data0, data1, clock;
+ int ret;
+
+@@ -1515,10 +1787,11 @@ static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah,
+ */
+ data0 = data1 = 0;
+
+- if (channel->val & CHANNEL_2GHZ) {
++ if (channel->hw_value & CHANNEL_2GHZ) {
+ /* Map 2GHz channel to 5GHz Atheros channel ID */
+- ret = ath5k_hw_rf5111_chan2athchan(channel->chan,
+- &ath5k_channel_2ghz);
++ ret = ath5k_hw_rf5111_chan2athchan(
++ ieee80211_frequency_to_channel(channel->center_freq),
++ &ath5k_channel_2ghz);
+ if (ret)
+ return ret;
+
+@@ -1555,7 +1828,7 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
+ u16 c;
+
+ data = data0 = data1 = data2 = 0;
+- c = channel->freq;
++ c = channel->center_freq;
+
+ /*
+ * Set the channel on the RF5112 or newer
+@@ -1599,19 +1872,17 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
+ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
+ {
+ int ret;
+-
+ /*
+- * Check bounds supported by the PHY
+- * (don't care about regulation restrictions at this point)
+- */
+- if ((channel->freq < ah->ah_capabilities.cap_range.range_2ghz_min ||
+- channel->freq > ah->ah_capabilities.cap_range.range_2ghz_max) &&
+- (channel->freq < ah->ah_capabilities.cap_range.range_5ghz_min ||
+- channel->freq > ah->ah_capabilities.cap_range.range_5ghz_max)) {
++ * Check bounds supported by the PHY (we don't care about regultory
++ * restrictions at this point). Note: hw_value already has the band
++ * (CHANNEL_2GHZ, or CHANNEL_5GHZ) so we inform ath5k_channel_ok()
++ * of the band by that */
++ if (!ath5k_channel_ok(ah, channel->center_freq, channel->hw_value)) {
+ ATH5K_ERR(ah->ah_sc,
+- "channel out of supported range (%u MHz)\n",
+- channel->freq);
+- return -EINVAL;
++ "channel frequency (%u MHz) out of supported "
++ "band range\n",
++ channel->center_freq);
++ return -EINVAL;
+ }
+
+ /*
+@@ -1632,9 +1903,9 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
+ if (ret)
+ return ret;
+
+- ah->ah_current_channel.freq = channel->freq;
+- ah->ah_current_channel.val = channel->val;
+- ah->ah_turbo = channel->val == CHANNEL_T ? true : false;
++ ah->ah_current_channel.center_freq = channel->center_freq;
++ ah->ah_current_channel.hw_value = channel->hw_value;
++ ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false;
+
+ return 0;
+ }
+@@ -1797,11 +2068,11 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
+
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n",
+- channel->freq);
++ channel->center_freq);
+ return ret;
+ }
+
+- ret = ath5k_hw_noise_floor_calibration(ah, channel->freq);
++ ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
+ if (ret)
+ return ret;
+
+@@ -1825,7 +2096,7 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
+ s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd;
+ ATH5K_TRACE(ah->ah_sc);
+
+- if (ah->ah_calibration == false ||
++ if (!ah->ah_calibration ||
+ ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN)
+ goto done;
+
+@@ -1848,10 +2119,10 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
+ ((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S));
+
+ done:
+- ath5k_hw_noise_floor_calibration(ah, channel->freq);
++ ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
+
+ /* Request RF gain */
+- if (channel->val & CHANNEL_5GHZ) {
++ if (channel->hw_value & CHANNEL_5GHZ) {
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_max,
+ AR5K_PHY_PAPD_PROBE_TXPOWER) |
+ AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE);
+@@ -2015,6 +2286,18 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
+ return -EINVAL;
+ }
+
++ /*
++ * RF2413 for some reason can't
++ * transmit anything if we call
++ * this funtion, so we skip it
++ * until we fix txpower.
++ *
++ * XXX: Assume same for RF2425
++ * to be safe.
++ */
++ if ((ah->ah_radio == AR5K_RF2413) || (ah->ah_radio == AR5K_RF2425))
++ return 0;
++
+ /* Reset TX power values */
+ memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));
+ ah->ah_txpower.txp_tpc = tpc;
+@@ -2048,7 +2331,7 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
+ AR5K_TXPOWER_CCK(13, 16) | AR5K_TXPOWER_CCK(12, 8) |
+ AR5K_TXPOWER_CCK(11, 0), AR5K_PHY_TXPOWER_RATE4);
+
+- if (ah->ah_txpower.txp_tpc == true)
++ if (ah->ah_txpower.txp_tpc)
+ ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE |
+ AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX);
+ else
+diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h
+index 2f41c83..30629b3 100644
+--- a/drivers/net/wireless/ath5k/reg.h
++++ b/drivers/net/wireless/ath5k/reg.h
+@@ -1923,7 +1923,9 @@ after DFS is enabled */
+ #define AR5K_PHY_SDELAY_32MHZ 0x000000ff
+ #define AR5K_PHY_SPENDING 0x99f8
+ #define AR5K_PHY_SPENDING_RF5111 0x00000018
+-#define AR5K_PHY_SPENDING_RF5112 0x00000014
++#define AR5K_PHY_SPENDING_RF5112 0x00000014 /* <- i 've only seen this on 2425 dumps ! */
++#define AR5K_PHY_SPENDING_RF5112A 0x0000000e /* but since i only have 5112A-based chips */
++#define AR5K_PHY_SPENDING_RF5424 0x00000012 /* to test it might be also for old 5112. */
+
+ /*
+ * Misc PHY/radio registers [5110 - 5111]
+diff --git a/drivers/net/wireless/ath5k/regdom.c b/drivers/net/wireless/ath5k/regdom.c
+deleted file mode 100644
+index e851957..0000000
+--- a/drivers/net/wireless/ath5k/regdom.c
++++ /dev/null
+@@ -1,121 +0,0 @@
+-/*
+- * Copyright (c) 2004, 2005 Reyk Floeter <reyk at vantronix.net>
+- *
+- * Permission to use, copy, modify, and distribute this software for any
+- * purpose with or without fee is hereby granted, provided that the above
+- * copyright notice and this permission notice appear in all copies.
+- *
+- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+- */
+-
+-/*
+- * Basic regulation domain extensions for the IEEE 802.11 stack
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/string.h>
+-
+-#include "regdom.h"
+-
+-static const struct ath5k_regdommap {
+- enum ath5k_regdom dmn;
+- enum ath5k_regdom dmn5;
+- enum ath5k_regdom dmn2;
+-} r_map[] = {
+- { DMN_DEFAULT, DMN_DEBUG, DMN_DEBUG },
+- { DMN_NULL_WORLD, DMN_NULL, DMN_WORLD },
+- { DMN_NULL_ETSIB, DMN_NULL, DMN_ETSIB },
+- { DMN_NULL_ETSIC, DMN_NULL, DMN_ETSIC },
+- { DMN_FCC1_FCCA, DMN_FCC1, DMN_FCCA },
+- { DMN_FCC1_WORLD, DMN_FCC1, DMN_WORLD },
+- { DMN_FCC2_FCCA, DMN_FCC2, DMN_FCCA },
+- { DMN_FCC2_WORLD, DMN_FCC2, DMN_WORLD },
+- { DMN_FCC2_ETSIC, DMN_FCC2, DMN_ETSIC },
+- { DMN_FRANCE_NULL, DMN_ETSI3, DMN_ETSI3 },
+- { DMN_FCC3_FCCA, DMN_FCC3, DMN_WORLD },
+- { DMN_ETSI1_WORLD, DMN_ETSI1, DMN_WORLD },
+- { DMN_ETSI3_ETSIA, DMN_ETSI3, DMN_WORLD },
+- { DMN_ETSI2_WORLD, DMN_ETSI2, DMN_WORLD },
+- { DMN_ETSI3_WORLD, DMN_ETSI3, DMN_WORLD },
+- { DMN_ETSI4_WORLD, DMN_ETSI4, DMN_WORLD },
+- { DMN_ETSI4_ETSIC, DMN_ETSI4, DMN_ETSIC },
+- { DMN_ETSI5_WORLD, DMN_ETSI5, DMN_WORLD },
+- { DMN_ETSI6_WORLD, DMN_ETSI6, DMN_WORLD },
+- { DMN_ETSI_NULL, DMN_ETSI1, DMN_ETSI1 },
+- { DMN_MKK1_MKKA, DMN_MKK1, DMN_MKKA },
+- { DMN_MKK1_MKKB, DMN_MKK1, DMN_MKKA },
+- { DMN_APL4_WORLD, DMN_APL4, DMN_WORLD },
+- { DMN_MKK2_MKKA, DMN_MKK2, DMN_MKKA },
+- { DMN_APL_NULL, DMN_APL1, DMN_NULL },
+- { DMN_APL2_WORLD, DMN_APL2, DMN_WORLD },
+- { DMN_APL2_APLC, DMN_APL2, DMN_WORLD },
+- { DMN_APL3_WORLD, DMN_APL3, DMN_WORLD },
+- { DMN_MKK1_FCCA, DMN_MKK1, DMN_FCCA },
+- { DMN_APL2_APLD, DMN_APL2, DMN_APLD },
+- { DMN_MKK1_MKKA1, DMN_MKK1, DMN_MKKA },
+- { DMN_MKK1_MKKA2, DMN_MKK1, DMN_MKKA },
+- { DMN_APL1_WORLD, DMN_APL1, DMN_WORLD },
+- { DMN_APL1_FCCA, DMN_APL1, DMN_FCCA },
+- { DMN_APL1_APLA, DMN_APL1, DMN_WORLD },
+- { DMN_APL1_ETSIC, DMN_APL1, DMN_ETSIC },
+- { DMN_APL2_ETSIC, DMN_APL2, DMN_ETSIC },
+- { DMN_APL5_WORLD, DMN_APL5, DMN_WORLD },
+- { DMN_WOR0_WORLD, DMN_WORLD, DMN_WORLD },
+- { DMN_WOR1_WORLD, DMN_WORLD, DMN_WORLD },
+- { DMN_WOR2_WORLD, DMN_WORLD, DMN_WORLD },
+- { DMN_WOR3_WORLD, DMN_WORLD, DMN_WORLD },
+- { DMN_WOR4_WORLD, DMN_WORLD, DMN_WORLD },
+- { DMN_WOR5_ETSIC, DMN_WORLD, DMN_WORLD },
+- { DMN_WOR01_WORLD, DMN_WORLD, DMN_WORLD },
+- { DMN_WOR02_WORLD, DMN_WORLD, DMN_WORLD },
+- { DMN_EU1_WORLD, DMN_ETSI1, DMN_WORLD },
+- { DMN_WOR9_WORLD, DMN_WORLD, DMN_WORLD },
+- { DMN_WORA_WORLD, DMN_WORLD, DMN_WORLD },
+-};
+-
+-enum ath5k_regdom ath5k_regdom2flag(enum ath5k_regdom dmn, u16 mhz)
+-{
+- unsigned int i;
+-
+- for (i = 0; i < ARRAY_SIZE(r_map); i++) {
+- if (r_map[i].dmn == dmn) {
+- if (mhz >= 2000 && mhz <= 3000)
+- return r_map[i].dmn2;
+- if (mhz >= IEEE80211_CHANNELS_5GHZ_MIN &&
+- mhz <= IEEE80211_CHANNELS_5GHZ_MAX)
+- return r_map[i].dmn5;
+- }
+- }
+-
+- return DMN_DEBUG;
+-}
+-
+-u16 ath5k_regdom_from_ieee(enum ath5k_regdom ieee)
+-{
+- u32 regdomain = (u32)ieee;
+-
+- /*
+- * Use the default regulation domain if the value is empty
+- * or not supported by the net80211 regulation code.
+- */
+- if (ath5k_regdom2flag(regdomain, IEEE80211_CHANNELS_5GHZ_MIN) ==
+- DMN_DEBUG)
+- return (u16)AR5K_TUNE_REGDOMAIN;
+-
+- /* It is supported, just return the value */
+- return regdomain;
+-}
+-
+-enum ath5k_regdom ath5k_regdom_to_ieee(u16 regdomain)
+-{
+- enum ath5k_regdom ieee = (enum ath5k_regdom)regdomain;
+-
+- return ieee;
+-}
+-
+diff --git a/drivers/net/wireless/ath5k/regdom.h b/drivers/net/wireless/ath5k/regdom.h
+deleted file mode 100644
+index f7d3c66..0000000
+--- a/drivers/net/wireless/ath5k/regdom.h
++++ /dev/null
+@@ -1,500 +0,0 @@
+-/*
+- * Copyright (c) 2004, 2005 Reyk Floeter <reyk at openbsd.org>
+- *
+- * Permission to use, copy, modify, and distribute this software for any
+- * purpose with or without fee is hereby granted, provided that the above
+- * copyright notice and this permission notice appear in all copies.
+- *
+- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+- */
+-
+-#ifndef _IEEE80211_REGDOMAIN_H_
+-#define _IEEE80211_REGDOMAIN_H_
+-
+-#include <linux/types.h>
+-
+-/* Default regulation domain if stored value EEPROM value is invalid */
+-#define AR5K_TUNE_REGDOMAIN DMN_FCC2_FCCA /* Canada */
+-#define AR5K_TUNE_CTRY CTRY_DEFAULT
+-
+-
+-enum ath5k_regdom {
+- DMN_DEFAULT = 0x00,
+- DMN_NULL_WORLD = 0x03,
+- DMN_NULL_ETSIB = 0x07,
+- DMN_NULL_ETSIC = 0x08,
+- DMN_FCC1_FCCA = 0x10,
+- DMN_FCC1_WORLD = 0x11,
+- DMN_FCC2_FCCA = 0x20,
+- DMN_FCC2_WORLD = 0x21,
+- DMN_FCC2_ETSIC = 0x22,
+- DMN_FRANCE_NULL = 0x31,
+- DMN_FCC3_FCCA = 0x3A,
+- DMN_ETSI1_WORLD = 0x37,
+- DMN_ETSI3_ETSIA = 0x32,
+- DMN_ETSI2_WORLD = 0x35,
+- DMN_ETSI3_WORLD = 0x36,
+- DMN_ETSI4_WORLD = 0x30,
+- DMN_ETSI4_ETSIC = 0x38,
+- DMN_ETSI5_WORLD = 0x39,
+- DMN_ETSI6_WORLD = 0x34,
+- DMN_ETSI_NULL = 0x33,
+- DMN_MKK1_MKKA = 0x40,
+- DMN_MKK1_MKKB = 0x41,
+- DMN_APL4_WORLD = 0x42,
+- DMN_MKK2_MKKA = 0x43,
+- DMN_APL_NULL = 0x44,
+- DMN_APL2_WORLD = 0x45,
+- DMN_APL2_APLC = 0x46,
+- DMN_APL3_WORLD = 0x47,
+- DMN_MKK1_FCCA = 0x48,
+- DMN_APL2_APLD = 0x49,
+- DMN_MKK1_MKKA1 = 0x4A,
+- DMN_MKK1_MKKA2 = 0x4B,
+- DMN_APL1_WORLD = 0x52,
+- DMN_APL1_FCCA = 0x53,
+- DMN_APL1_APLA = 0x54,
+- DMN_APL1_ETSIC = 0x55,
+- DMN_APL2_ETSIC = 0x56,
+- DMN_APL5_WORLD = 0x58,
+- DMN_WOR0_WORLD = 0x60,
+- DMN_WOR1_WORLD = 0x61,
+- DMN_WOR2_WORLD = 0x62,
+- DMN_WOR3_WORLD = 0x63,
+- DMN_WOR4_WORLD = 0x64,
+- DMN_WOR5_ETSIC = 0x65,
+- DMN_WOR01_WORLD = 0x66,
+- DMN_WOR02_WORLD = 0x67,
+- DMN_EU1_WORLD = 0x68,
+- DMN_WOR9_WORLD = 0x69,
+- DMN_WORA_WORLD = 0x6A,
+-
+- DMN_APL1 = 0xf0000001,
+- DMN_APL2 = 0xf0000002,
+- DMN_APL3 = 0xf0000004,
+- DMN_APL4 = 0xf0000008,
+- DMN_APL5 = 0xf0000010,
+- DMN_ETSI1 = 0xf0000020,
+- DMN_ETSI2 = 0xf0000040,
+- DMN_ETSI3 = 0xf0000080,
+- DMN_ETSI4 = 0xf0000100,
+- DMN_ETSI5 = 0xf0000200,
+- DMN_ETSI6 = 0xf0000400,
+- DMN_ETSIA = 0xf0000800,
+- DMN_ETSIB = 0xf0001000,
+- DMN_ETSIC = 0xf0002000,
+- DMN_FCC1 = 0xf0004000,
+- DMN_FCC2 = 0xf0008000,
+- DMN_FCC3 = 0xf0010000,
+- DMN_FCCA = 0xf0020000,
+- DMN_APLD = 0xf0040000,
+- DMN_MKK1 = 0xf0080000,
+- DMN_MKK2 = 0xf0100000,
+- DMN_MKKA = 0xf0200000,
+- DMN_NULL = 0xf0400000,
+- DMN_WORLD = 0xf0800000,
+- DMN_DEBUG = 0xf1000000 /* used for debugging */
+-};
+-
+-#define IEEE80211_DMN(_d) ((_d) & ~0xf0000000)
+-
+-enum ath5k_countrycode {
+- CTRY_DEFAULT = 0, /* Default domain (NA) */
+- CTRY_ALBANIA = 8, /* Albania */
+- CTRY_ALGERIA = 12, /* Algeria */
+- CTRY_ARGENTINA = 32, /* Argentina */
+- CTRY_ARMENIA = 51, /* Armenia */
+- CTRY_AUSTRALIA = 36, /* Australia */
+- CTRY_AUSTRIA = 40, /* Austria */
+- CTRY_AZERBAIJAN = 31, /* Azerbaijan */
+- CTRY_BAHRAIN = 48, /* Bahrain */
+- CTRY_BELARUS = 112, /* Belarus */
+- CTRY_BELGIUM = 56, /* Belgium */
+- CTRY_BELIZE = 84, /* Belize */
+- CTRY_BOLIVIA = 68, /* Bolivia */
+- CTRY_BRAZIL = 76, /* Brazil */
+- CTRY_BRUNEI_DARUSSALAM = 96, /* Brunei Darussalam */
+- CTRY_BULGARIA = 100, /* Bulgaria */
+- CTRY_CANADA = 124, /* Canada */
+- CTRY_CHILE = 152, /* Chile */
+- CTRY_CHINA = 156, /* People's Republic of China */
+- CTRY_COLOMBIA = 170, /* Colombia */
+- CTRY_COSTA_RICA = 188, /* Costa Rica */
+- CTRY_CROATIA = 191, /* Croatia */
+- CTRY_CYPRUS = 196, /* Cyprus */
+- CTRY_CZECH = 203, /* Czech Republic */
+- CTRY_DENMARK = 208, /* Denmark */
+- CTRY_DOMINICAN_REPUBLIC = 214, /* Dominican Republic */
+- CTRY_ECUADOR = 218, /* Ecuador */
+- CTRY_EGYPT = 818, /* Egypt */
+- CTRY_EL_SALVADOR = 222, /* El Salvador */
+- CTRY_ESTONIA = 233, /* Estonia */
+- CTRY_FAEROE_ISLANDS = 234, /* Faeroe Islands */
+- CTRY_FINLAND = 246, /* Finland */
+- CTRY_FRANCE = 250, /* France */
+- CTRY_FRANCE2 = 255, /* France2 */
+- CTRY_GEORGIA = 268, /* Georgia */
+- CTRY_GERMANY = 276, /* Germany */
+- CTRY_GREECE = 300, /* Greece */
+- CTRY_GUATEMALA = 320, /* Guatemala */
+- CTRY_HONDURAS = 340, /* Honduras */
+- CTRY_HONG_KONG = 344, /* Hong Kong S.A.R., P.R.C. */
+- CTRY_HUNGARY = 348, /* Hungary */
+- CTRY_ICELAND = 352, /* Iceland */
+- CTRY_INDIA = 356, /* India */
+- CTRY_INDONESIA = 360, /* Indonesia */
+- CTRY_IRAN = 364, /* Iran */
+- CTRY_IRAQ = 368, /* Iraq */
+- CTRY_IRELAND = 372, /* Ireland */
+- CTRY_ISRAEL = 376, /* Israel */
+- CTRY_ITALY = 380, /* Italy */
+- CTRY_JAMAICA = 388, /* Jamaica */
+- CTRY_JAPAN = 392, /* Japan */
+- CTRY_JAPAN1 = 393, /* Japan (JP1) */
+- CTRY_JAPAN2 = 394, /* Japan (JP0) */
+- CTRY_JAPAN3 = 395, /* Japan (JP1-1) */
+- CTRY_JAPAN4 = 396, /* Japan (JE1) */
+- CTRY_JAPAN5 = 397, /* Japan (JE2) */
+- CTRY_JORDAN = 400, /* Jordan */
+- CTRY_KAZAKHSTAN = 398, /* Kazakhstan */
+- CTRY_KENYA = 404, /* Kenya */
+- CTRY_KOREA_NORTH = 408, /* North Korea */
+- CTRY_KOREA_ROC = 410, /* South Korea */
+- CTRY_KOREA_ROC2 = 411, /* South Korea */
+- CTRY_KUWAIT = 414, /* Kuwait */
+- CTRY_LATVIA = 428, /* Latvia */
+- CTRY_LEBANON = 422, /* Lebanon */
+- CTRY_LIBYA = 434, /* Libya */
+- CTRY_LIECHTENSTEIN = 438, /* Liechtenstein */
+- CTRY_LITHUANIA = 440, /* Lithuania */
+- CTRY_LUXEMBOURG = 442, /* Luxembourg */
+- CTRY_MACAU = 446, /* Macau */
+- CTRY_MACEDONIA = 807, /* Republic of Macedonia */
+- CTRY_MALAYSIA = 458, /* Malaysia */
+- CTRY_MEXICO = 484, /* Mexico */
+- CTRY_MONACO = 492, /* Principality of Monaco */
+- CTRY_MOROCCO = 504, /* Morocco */
+- CTRY_NETHERLANDS = 528, /* Netherlands */
+- CTRY_NEW_ZEALAND = 554, /* New Zealand */
+- CTRY_NICARAGUA = 558, /* Nicaragua */
+- CTRY_NORWAY = 578, /* Norway */
+- CTRY_OMAN = 512, /* Oman */
+- CTRY_PAKISTAN = 586, /* Islamic Republic of Pakistan */
+- CTRY_PANAMA = 591, /* Panama */
+- CTRY_PARAGUAY = 600, /* Paraguay */
+- CTRY_PERU = 604, /* Peru */
+- CTRY_PHILIPPINES = 608, /* Republic of the Philippines */
+- CTRY_POLAND = 616, /* Poland */
+- CTRY_PORTUGAL = 620, /* Portugal */
+- CTRY_PUERTO_RICO = 630, /* Puerto Rico */
+- CTRY_QATAR = 634, /* Qatar */
+- CTRY_ROMANIA = 642, /* Romania */
+- CTRY_RUSSIA = 643, /* Russia */
+- CTRY_SAUDI_ARABIA = 682, /* Saudi Arabia */
+- CTRY_SINGAPORE = 702, /* Singapore */
+- CTRY_SLOVAKIA = 703, /* Slovak Republic */
+- CTRY_SLOVENIA = 705, /* Slovenia */
+- CTRY_SOUTH_AFRICA = 710, /* South Africa */
+- CTRY_SPAIN = 724, /* Spain */
+- CTRY_SRI_LANKA = 728, /* Sri Lanka */
+- CTRY_SWEDEN = 752, /* Sweden */
+- CTRY_SWITZERLAND = 756, /* Switzerland */
+- CTRY_SYRIA = 760, /* Syria */
+- CTRY_TAIWAN = 158, /* Taiwan */
+- CTRY_THAILAND = 764, /* Thailand */
+- CTRY_TRINIDAD_Y_TOBAGO = 780, /* Trinidad y Tobago */
+- CTRY_TUNISIA = 788, /* Tunisia */
+- CTRY_TURKEY = 792, /* Turkey */
+- CTRY_UAE = 784, /* U.A.E. */
+- CTRY_UKRAINE = 804, /* Ukraine */
+- CTRY_UNITED_KINGDOM = 826, /* United Kingdom */
+- CTRY_UNITED_STATES = 840, /* United States */
+- CTRY_URUGUAY = 858, /* Uruguay */
+- CTRY_UZBEKISTAN = 860, /* Uzbekistan */
+- CTRY_VENEZUELA = 862, /* Venezuela */
+- CTRY_VIET_NAM = 704, /* Viet Nam */
+- CTRY_YEMEN = 887, /* Yemen */
+- CTRY_ZIMBABWE = 716, /* Zimbabwe */
+-};
+-
+-#define IEEE80211_CHANNELS_2GHZ_MIN 2412 /* 2GHz channel 1 */
+-#define IEEE80211_CHANNELS_2GHZ_MAX 2732 /* 2GHz channel 26 */
+-#define IEEE80211_CHANNELS_5GHZ_MIN 5005 /* 5GHz channel 1 */
+-#define IEEE80211_CHANNELS_5GHZ_MAX 6100 /* 5GHz channel 220 */
+-
+-struct ath5k_regchannel {
+- u16 chan;
+- enum ath5k_regdom domain;
+- u32 mode;
+-};
+-
+-#define IEEE80211_CHANNELS_2GHZ { \
+-/*2412*/ { 1, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2417*/ { 2, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2422*/ { 3, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2427*/ { 4, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2432*/ { 5, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2437*/ { 6, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2442*/ { 7, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2447*/ { 8, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2452*/ { 9, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2457*/ { 10, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2462*/ { 11, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2467*/ { 12, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2472*/ { 13, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+- \
+-/*2432*/ { 5, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2437*/ { 6, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \
+-/*2442*/ { 7, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM }, \
+- \
+-/*2412*/ { 1, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2417*/ { 2, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2422*/ { 3, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2427*/ { 4, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2432*/ { 5, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2437*/ { 6, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \
+-/*2442*/ { 7, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2447*/ { 8, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2452*/ { 9, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2457*/ { 10, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2462*/ { 11, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2467*/ { 12, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2472*/ { 13, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
+- \
+-/*2412*/ { 1, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2417*/ { 2, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2422*/ { 3, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2427*/ { 4, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2432*/ { 5, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2437*/ { 6, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \
+-/*2442*/ { 7, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2447*/ { 8, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2452*/ { 9, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2457*/ { 10, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2462*/ { 11, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
+- \
+-/*2412*/ { 1, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2417*/ { 2, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2422*/ { 3, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2427*/ { 4, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2432*/ { 5, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2437*/ { 6, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2442*/ { 7, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2447*/ { 8, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2452*/ { 9, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2457*/ { 10, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2462*/ { 11, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2467*/ { 12, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2472*/ { 13, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2484*/ { 14, DMN_MKKA, CHANNEL_CCK }, \
+- \
+-/*2412*/ { 1, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2417*/ { 2, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2422*/ { 3, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2427*/ { 4, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2432*/ { 5, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2437*/ { 6, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \
+-/*2442*/ { 7, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2447*/ { 8, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2452*/ { 9, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2457*/ { 10, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2462*/ { 11, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2467*/ { 12, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+-/*2472*/ { 13, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+-}
+-
+-#define IEEE80211_CHANNELS_5GHZ { \
+-/*5745*/ { 149, DMN_APL1, CHANNEL_OFDM }, \
+-/*5765*/ { 153, DMN_APL1, CHANNEL_OFDM }, \
+-/*5785*/ { 157, DMN_APL1, CHANNEL_OFDM }, \
+-/*5805*/ { 161, DMN_APL1, CHANNEL_OFDM }, \
+-/*5825*/ { 165, DMN_APL1, CHANNEL_OFDM }, \
+- \
+-/*5745*/ { 149, DMN_APL2, CHANNEL_OFDM }, \
+-/*5765*/ { 153, DMN_APL2, CHANNEL_OFDM }, \
+-/*5785*/ { 157, DMN_APL2, CHANNEL_OFDM }, \
+-/*5805*/ { 161, DMN_APL2, CHANNEL_OFDM }, \
+- \
+-/*5280*/ { 56, DMN_APL3, CHANNEL_OFDM }, \
+-/*5300*/ { 60, DMN_APL3, CHANNEL_OFDM }, \
+-/*5320*/ { 64, DMN_APL3, CHANNEL_OFDM }, \
+-/*5745*/ { 149, DMN_APL3, CHANNEL_OFDM }, \
+-/*5765*/ { 153, DMN_APL3, CHANNEL_OFDM }, \
+-/*5785*/ { 157, DMN_APL3, CHANNEL_OFDM }, \
+-/*5805*/ { 161, DMN_APL3, CHANNEL_OFDM }, \
+- \
+-/*5180*/ { 36, DMN_APL4, CHANNEL_OFDM }, \
+-/*5200*/ { 40, DMN_APL4, CHANNEL_OFDM }, \
+-/*5220*/ { 44, DMN_APL4, CHANNEL_OFDM }, \
+-/*5240*/ { 48, DMN_APL4, CHANNEL_OFDM }, \
+-/*5745*/ { 149, DMN_APL4, CHANNEL_OFDM }, \
+-/*5765*/ { 153, DMN_APL4, CHANNEL_OFDM }, \
+-/*5785*/ { 157, DMN_APL4, CHANNEL_OFDM }, \
+-/*5805*/ { 161, DMN_APL4, CHANNEL_OFDM }, \
+-/*5825*/ { 165, DMN_APL4, CHANNEL_OFDM }, \
+- \
+-/*5745*/ { 149, DMN_APL5, CHANNEL_OFDM }, \
+-/*5765*/ { 153, DMN_APL5, CHANNEL_OFDM }, \
+-/*5785*/ { 157, DMN_APL5, CHANNEL_OFDM }, \
+-/*5805*/ { 161, DMN_APL5, CHANNEL_OFDM }, \
+-/*5825*/ { 165, DMN_APL5, CHANNEL_OFDM }, \
+- \
+-/*5180*/ { 36, DMN_ETSI1, CHANNEL_OFDM }, \
+-/*5200*/ { 40, DMN_ETSI1, CHANNEL_OFDM }, \
+-/*5220*/ { 44, DMN_ETSI1, CHANNEL_OFDM }, \
+-/*5240*/ { 48, DMN_ETSI1, CHANNEL_OFDM }, \
+-/*5260*/ { 52, DMN_ETSI1, CHANNEL_OFDM }, \
+-/*5280*/ { 56, DMN_ETSI1, CHANNEL_OFDM }, \
+-/*5300*/ { 60, DMN_ETSI1, CHANNEL_OFDM }, \
+-/*5320*/ { 64, DMN_ETSI1, CHANNEL_OFDM }, \
+-/*5500*/ { 100, DMN_ETSI1, CHANNEL_OFDM }, \
+-/*5520*/ { 104, DMN_ETSI1, CHANNEL_OFDM }, \
+-/*5540*/ { 108, DMN_ETSI1, CHANNEL_OFDM }, \
+-/*5560*/ { 112, DMN_ETSI1, CHANNEL_OFDM }, \
+-/*5580*/ { 116, DMN_ETSI1, CHANNEL_OFDM }, \
+-/*5600*/ { 120, DMN_ETSI1, CHANNEL_OFDM }, \
+-/*5620*/ { 124, DMN_ETSI1, CHANNEL_OFDM }, \
+-/*5640*/ { 128, DMN_ETSI1, CHANNEL_OFDM }, \
+-/*5660*/ { 132, DMN_ETSI1, CHANNEL_OFDM }, \
+-/*5680*/ { 136, DMN_ETSI1, CHANNEL_OFDM }, \
+-/*5700*/ { 140, DMN_ETSI1, CHANNEL_OFDM }, \
+- \
+-/*5180*/ { 36, DMN_ETSI2, CHANNEL_OFDM }, \
+-/*5200*/ { 40, DMN_ETSI2, CHANNEL_OFDM }, \
+-/*5220*/ { 44, DMN_ETSI2, CHANNEL_OFDM }, \
+-/*5240*/ { 48, DMN_ETSI2, CHANNEL_OFDM }, \
+- \
+-/*5180*/ { 36, DMN_ETSI3, CHANNEL_OFDM }, \
+-/*5200*/ { 40, DMN_ETSI3, CHANNEL_OFDM }, \
+-/*5220*/ { 44, DMN_ETSI3, CHANNEL_OFDM }, \
+-/*5240*/ { 48, DMN_ETSI3, CHANNEL_OFDM }, \
+-/*5260*/ { 52, DMN_ETSI3, CHANNEL_OFDM }, \
+-/*5280*/ { 56, DMN_ETSI3, CHANNEL_OFDM }, \
+-/*5300*/ { 60, DMN_ETSI3, CHANNEL_OFDM }, \
+-/*5320*/ { 64, DMN_ETSI3, CHANNEL_OFDM }, \
+- \
+-/*5180*/ { 36, DMN_ETSI4, CHANNEL_OFDM }, \
+-/*5200*/ { 40, DMN_ETSI4, CHANNEL_OFDM }, \
+-/*5220*/ { 44, DMN_ETSI4, CHANNEL_OFDM }, \
+-/*5240*/ { 48, DMN_ETSI4, CHANNEL_OFDM }, \
+-/*5260*/ { 52, DMN_ETSI4, CHANNEL_OFDM }, \
+-/*5280*/ { 56, DMN_ETSI4, CHANNEL_OFDM }, \
+-/*5300*/ { 60, DMN_ETSI4, CHANNEL_OFDM }, \
+-/*5320*/ { 64, DMN_ETSI4, CHANNEL_OFDM }, \
+- \
+-/*5180*/ { 36, DMN_ETSI5, CHANNEL_OFDM }, \
+-/*5200*/ { 40, DMN_ETSI5, CHANNEL_OFDM }, \
+-/*5220*/ { 44, DMN_ETSI5, CHANNEL_OFDM }, \
+-/*5240*/ { 48, DMN_ETSI5, CHANNEL_OFDM }, \
+- \
+-/*5180*/ { 36, DMN_ETSI6, CHANNEL_OFDM }, \
+-/*5200*/ { 40, DMN_ETSI6, CHANNEL_OFDM }, \
+-/*5220*/ { 44, DMN_ETSI6, CHANNEL_OFDM }, \
+-/*5240*/ { 48, DMN_ETSI6, CHANNEL_OFDM }, \
+-/*5260*/ { 52, DMN_ETSI6, CHANNEL_OFDM }, \
+-/*5280*/ { 56, DMN_ETSI6, CHANNEL_OFDM }, \
+-/*5500*/ { 100, DMN_ETSI6, CHANNEL_OFDM }, \
+-/*5520*/ { 104, DMN_ETSI6, CHANNEL_OFDM }, \
+-/*5540*/ { 108, DMN_ETSI6, CHANNEL_OFDM }, \
+-/*5560*/ { 112, DMN_ETSI6, CHANNEL_OFDM }, \
+-/*5580*/ { 116, DMN_ETSI6, CHANNEL_OFDM }, \
+-/*5600*/ { 120, DMN_ETSI6, CHANNEL_OFDM }, \
+-/*5620*/ { 124, DMN_ETSI6, CHANNEL_OFDM }, \
+-/*5640*/ { 128, DMN_ETSI6, CHANNEL_OFDM }, \
+-/*5660*/ { 132, DMN_ETSI6, CHANNEL_OFDM }, \
+-/*5680*/ { 136, DMN_ETSI6, CHANNEL_OFDM }, \
+-/*5700*/ { 140, DMN_ETSI6, CHANNEL_OFDM }, \
+- \
+-/*5180*/ { 36, DMN_FCC1, CHANNEL_OFDM }, \
+-/*5200*/ { 40, DMN_FCC1, CHANNEL_OFDM }, \
+-/*5210*/ { 42, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \
+-/*5220*/ { 44, DMN_FCC1, CHANNEL_OFDM }, \
+-/*5240*/ { 48, DMN_FCC1, CHANNEL_OFDM }, \
+-/*5250*/ { 50, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \
+-/*5260*/ { 52, DMN_FCC1, CHANNEL_OFDM }, \
+-/*5280*/ { 56, DMN_FCC1, CHANNEL_OFDM }, \
+-/*5290*/ { 58, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \
+-/*5300*/ { 60, DMN_FCC1, CHANNEL_OFDM }, \
+-/*5320*/ { 64, DMN_FCC1, CHANNEL_OFDM }, \
+-/*5745*/ { 149, DMN_FCC1, CHANNEL_OFDM }, \
+-/*5760*/ { 152, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \
+-/*5765*/ { 153, DMN_FCC1, CHANNEL_OFDM }, \
+-/*5785*/ { 157, DMN_FCC1, CHANNEL_OFDM }, \
+-/*5800*/ { 160, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \
+-/*5805*/ { 161, DMN_FCC1, CHANNEL_OFDM }, \
+-/*5825*/ { 165, DMN_FCC1, CHANNEL_OFDM }, \
+- \
+-/*5180*/ { 36, DMN_FCC2, CHANNEL_OFDM }, \
+-/*5200*/ { 40, DMN_FCC2, CHANNEL_OFDM }, \
+-/*5220*/ { 44, DMN_FCC2, CHANNEL_OFDM }, \
+-/*5240*/ { 48, DMN_FCC2, CHANNEL_OFDM }, \
+-/*5260*/ { 52, DMN_FCC2, CHANNEL_OFDM }, \
+-/*5280*/ { 56, DMN_FCC2, CHANNEL_OFDM }, \
+-/*5300*/ { 60, DMN_FCC2, CHANNEL_OFDM }, \
+-/*5320*/ { 64, DMN_FCC2, CHANNEL_OFDM }, \
+-/*5745*/ { 149, DMN_FCC2, CHANNEL_OFDM }, \
+-/*5765*/ { 153, DMN_FCC2, CHANNEL_OFDM }, \
+-/*5785*/ { 157, DMN_FCC2, CHANNEL_OFDM }, \
+-/*5805*/ { 161, DMN_FCC2, CHANNEL_OFDM }, \
+-/*5825*/ { 165, DMN_FCC2, CHANNEL_OFDM }, \
+- \
+-/*5180*/ { 36, DMN_FCC3, CHANNEL_OFDM }, \
+-/*5200*/ { 40, DMN_FCC3, CHANNEL_OFDM }, \
+-/*5210*/ { 42, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \
+-/*5220*/ { 44, DMN_FCC3, CHANNEL_OFDM }, \
+-/*5240*/ { 48, DMN_FCC3, CHANNEL_OFDM }, \
+-/*5250*/ { 50, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \
+-/*5260*/ { 52, DMN_FCC3, CHANNEL_OFDM }, \
+-/*5280*/ { 56, DMN_FCC3, CHANNEL_OFDM }, \
+-/*5290*/ { 58, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \
+-/*5300*/ { 60, DMN_FCC3, CHANNEL_OFDM }, \
+-/*5320*/ { 64, DMN_FCC3, CHANNEL_OFDM }, \
+-/*5500*/ { 100, DMN_FCC3, CHANNEL_OFDM }, \
+-/*5520*/ { 104, DMN_FCC3, CHANNEL_OFDM }, \
+-/*5540*/ { 108, DMN_FCC3, CHANNEL_OFDM }, \
+-/*5560*/ { 112, DMN_FCC3, CHANNEL_OFDM }, \
+-/*5580*/ { 116, DMN_FCC3, CHANNEL_OFDM }, \
+-/*5600*/ { 120, DMN_FCC3, CHANNEL_OFDM }, \
+-/*5620*/ { 124, DMN_FCC3, CHANNEL_OFDM }, \
+-/*5640*/ { 128, DMN_FCC3, CHANNEL_OFDM }, \
+-/*5660*/ { 132, DMN_FCC3, CHANNEL_OFDM }, \
+-/*5680*/ { 136, DMN_FCC3, CHANNEL_OFDM }, \
+-/*5700*/ { 140, DMN_FCC3, CHANNEL_OFDM }, \
+-/*5745*/ { 149, DMN_FCC3, CHANNEL_OFDM }, \
+-/*5760*/ { 152, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \
+-/*5765*/ { 153, DMN_FCC3, CHANNEL_OFDM }, \
+-/*5785*/ { 157, DMN_FCC3, CHANNEL_OFDM }, \
+-/*5800*/ { 160, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \
+-/*5805*/ { 161, DMN_FCC3, CHANNEL_OFDM }, \
+-/*5825*/ { 165, DMN_FCC3, CHANNEL_OFDM }, \
+- \
+-/*5170*/ { 34, DMN_MKK1, CHANNEL_OFDM }, \
+-/*5190*/ { 38, DMN_MKK1, CHANNEL_OFDM }, \
+-/*5210*/ { 42, DMN_MKK1, CHANNEL_OFDM }, \
+-/*5230*/ { 46, DMN_MKK1, CHANNEL_OFDM }, \
+- \
+-/*5040*/ { 8, DMN_MKK2, CHANNEL_OFDM }, \
+-/*5060*/ { 12, DMN_MKK2, CHANNEL_OFDM }, \
+-/*5080*/ { 16, DMN_MKK2, CHANNEL_OFDM }, \
+-/*5170*/ { 34, DMN_MKK2, CHANNEL_OFDM }, \
+-/*5190*/ { 38, DMN_MKK2, CHANNEL_OFDM }, \
+-/*5210*/ { 42, DMN_MKK2, CHANNEL_OFDM }, \
+-/*5230*/ { 46, DMN_MKK2, CHANNEL_OFDM }, \
+- \
+-/*5180*/ { 36, DMN_WORLD, CHANNEL_OFDM }, \
+-/*5200*/ { 40, DMN_WORLD, CHANNEL_OFDM }, \
+-/*5220*/ { 44, DMN_WORLD, CHANNEL_OFDM }, \
+-/*5240*/ { 48, DMN_WORLD, CHANNEL_OFDM }, \
+-}
+-
+-enum ath5k_regdom ath5k_regdom2flag(enum ath5k_regdom, u16);
+-u16 ath5k_regdom_from_ieee(enum ath5k_regdom ieee);
+-enum ath5k_regdom ath5k_regdom_to_ieee(u16 regdomain);
+-
+-#endif
+diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
+index 63ec7a7..ef2da40 100644
+--- a/drivers/net/wireless/atmel.c
++++ b/drivers/net/wireless/atmel.c
+@@ -66,6 +66,7 @@
+ #include <linux/device.h>
+ #include <linux/moduleparam.h>
+ #include <linux/firmware.h>
++#include <linux/jiffies.h>
+ #include <net/ieee80211.h>
+ #include "atmel.h"
+
+@@ -516,7 +517,7 @@ struct atmel_private {
+ SITE_SURVEY_IN_PROGRESS,
+ SITE_SURVEY_COMPLETED
+ } site_survey_state;
+- time_t last_survey;
++ unsigned long last_survey;
+
+ int station_was_associated, station_is_associated;
+ int fast_scan;
+@@ -2283,7 +2284,7 @@ static int atmel_set_scan(struct net_device *dev,
+ return -EAGAIN;
+
+ /* Timeout old surveys. */
+- if ((jiffies - priv->last_survey) > (20 * HZ))
++ if (time_after(jiffies, priv->last_survey + 20 * HZ))
+ priv->site_survey_state = SITE_SURVEY_IDLE;
+ priv->last_survey = jiffies;
+
+diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
+index 8bc4bc4..f51b2d9 100644
+--- a/drivers/net/wireless/b43/Kconfig
++++ b/drivers/net/wireless/b43/Kconfig
+@@ -62,6 +62,14 @@ config B43_PCMCIA
+
+ If unsure, say N.
+
++# Data transfers to the device via PIO
++# This is only needed on PCMCIA devices. All others can do DMA properly.
++config B43_PIO
++ bool
++ depends on B43 && (B43_PCMCIA || B43_FORCE_PIO)
++ select SSB_BLOCKIO
++ default y
++
+ config B43_NPHY
+ bool "Pre IEEE 802.11n support (BROKEN)"
+ depends on B43 && EXPERIMENTAL && BROKEN
+@@ -94,3 +102,13 @@ config B43_DEBUG
+
+ Say Y, if you want to find out why the driver does not
+ work for you.
++
++config B43_FORCE_PIO
++ bool "Force usage of PIO instead of DMA"
++ depends on B43 && B43_DEBUG
++ ---help---
++ This will disable DMA and always enable PIO instead.
++
++ Say N!
++ This is only for debugging the PIO engine code. You do
++ _NOT_ want to enable this.
+diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile
+index ac1329d..8c52b0b 100644
+--- a/drivers/net/wireless/b43/Makefile
++++ b/drivers/net/wireless/b43/Makefile
+@@ -1,13 +1,14 @@
+ b43-y += main.o
+ b43-y += tables.o
+-b43-y += tables_nphy.o
++b43-$(CONFIG_B43_NPHY) += tables_nphy.o
+ b43-y += phy.o
+-b43-y += nphy.o
++b43-$(CONFIG_B43_NPHY) += nphy.o
+ b43-y += sysfs.o
+ b43-y += xmit.o
+ b43-y += lo.o
+ b43-y += wa.o
+ b43-y += dma.o
++b43-$(CONFIG_B43_PIO) += pio.o
+ b43-$(CONFIG_B43_RFKILL) += rfkill.o
+ b43-$(CONFIG_B43_LEDS) += leds.o
+ b43-$(CONFIG_B43_PCMCIA) += pcmcia.o
+diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
+index f13346b..eff2a15 100644
+--- a/drivers/net/wireless/b43/b43.h
++++ b/drivers/net/wireless/b43/b43.h
+@@ -75,6 +75,23 @@
+ #define B43_MMIO_DMA64_BASE4 0x300
+ #define B43_MMIO_DMA64_BASE5 0x340
+
++/* PIO on core rev < 11 */
++#define B43_MMIO_PIO_BASE0 0x300
++#define B43_MMIO_PIO_BASE1 0x310
++#define B43_MMIO_PIO_BASE2 0x320
++#define B43_MMIO_PIO_BASE3 0x330
++#define B43_MMIO_PIO_BASE4 0x340
++#define B43_MMIO_PIO_BASE5 0x350
++#define B43_MMIO_PIO_BASE6 0x360
++#define B43_MMIO_PIO_BASE7 0x370
++/* PIO on core rev >= 11 */
++#define B43_MMIO_PIO11_BASE0 0x200
++#define B43_MMIO_PIO11_BASE1 0x240
++#define B43_MMIO_PIO11_BASE2 0x280
++#define B43_MMIO_PIO11_BASE3 0x2C0
++#define B43_MMIO_PIO11_BASE4 0x300
++#define B43_MMIO_PIO11_BASE5 0x340
++
+ #define B43_MMIO_PHY_VER 0x3E0
+ #define B43_MMIO_PHY_RADIO 0x3E2
+ #define B43_MMIO_PHY0 0x3E6
+@@ -94,11 +111,14 @@
+ #define B43_MMIO_GPIO_MASK 0x49E
+ #define B43_MMIO_TSF_CFP_START_LOW 0x604
+ #define B43_MMIO_TSF_CFP_START_HIGH 0x606
++#define B43_MMIO_TSF_CFP_PRETBTT 0x612
+ #define B43_MMIO_TSF_0 0x632 /* core rev < 3 only */
+ #define B43_MMIO_TSF_1 0x634 /* core rev < 3 only */
+ #define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */
+ #define B43_MMIO_TSF_3 0x638 /* core rev < 3 only */
+ #define B43_MMIO_RNG 0x65A
++#define B43_MMIO_IFSCTL 0x688 /* Interframe space control */
++#define B43_MMIO_IFSCTL_USE_EDCF 0x0004
+ #define B43_MMIO_POWERUP_DELAY 0x6A8
+
+ /* SPROM boardflags_lo values */
+@@ -144,7 +164,8 @@ enum {
+ #define B43_SHM_SH_PHYTYPE 0x0052 /* PHY type */
+ #define B43_SHM_SH_ANTSWAP 0x005C /* Antenna swap threshold */
+ #define B43_SHM_SH_HOSTFLO 0x005E /* Hostflags for ucode options (low) */
+-#define B43_SHM_SH_HOSTFHI 0x0060 /* Hostflags for ucode options (high) */
++#define B43_SHM_SH_HOSTFMI 0x0060 /* Hostflags for ucode options (middle) */
++#define B43_SHM_SH_HOSTFHI 0x0062 /* Hostflags for ucode options (high) */
+ #define B43_SHM_SH_RFATT 0x0064 /* Current radio attenuation value */
+ #define B43_SHM_SH_RADAR 0x0066 /* Radar register */
+ #define B43_SHM_SH_PHYTXNOI 0x006E /* PHY noise directly after TX (lower 8bit only) */
+@@ -232,31 +253,41 @@ enum {
+ #define B43_MMIO_RADIO_HWENABLED_LO_MASK (1 << 4)
+
+ /* HostFlags. See b43_hf_read/write() */
+-#define B43_HF_ANTDIVHELP 0x00000001 /* ucode antenna div helper */
+-#define B43_HF_SYMW 0x00000002 /* G-PHY SYM workaround */
+-#define B43_HF_RXPULLW 0x00000004 /* RX pullup workaround */
+-#define B43_HF_CCKBOOST 0x00000008 /* 4dB CCK power boost (exclusive with OFDM boost) */
+-#define B43_HF_BTCOEX 0x00000010 /* Bluetooth coexistance */
+-#define B43_HF_GDCW 0x00000020 /* G-PHY DV canceller filter bw workaround */
+-#define B43_HF_OFDMPABOOST 0x00000040 /* Enable PA gain boost for OFDM */
+-#define B43_HF_ACPR 0x00000080 /* Disable for Japan, channel 14 */
+-#define B43_HF_EDCF 0x00000100 /* on if WME and MAC suspended */
+-#define B43_HF_TSSIRPSMW 0x00000200 /* TSSI reset PSM ucode workaround */
+-#define B43_HF_DSCRQ 0x00000400 /* Disable slow clock request in ucode */
+-#define B43_HF_ACIW 0x00000800 /* ACI workaround: shift bits by 2 on PHY CRS */
+-#define B43_HF_2060W 0x00001000 /* 2060 radio workaround */
+-#define B43_HF_RADARW 0x00002000 /* Radar workaround */
+-#define B43_HF_USEDEFKEYS 0x00004000 /* Enable use of default keys */
+-#define B43_HF_BT4PRIOCOEX 0x00010000 /* Bluetooth 2-priority coexistance */
+-#define B43_HF_FWKUP 0x00020000 /* Fast wake-up ucode */
+-#define B43_HF_VCORECALC 0x00040000 /* Force VCO recalculation when powering up synthpu */
+-#define B43_HF_PCISCW 0x00080000 /* PCI slow clock workaround */
+-#define B43_HF_4318TSSI 0x00200000 /* 4318 TSSI */
+-#define B43_HF_FBCMCFIFO 0x00400000 /* Flush bcast/mcast FIFO immediately */
+-#define B43_HF_HWPCTL 0x00800000 /* Enable hardwarre power control */
+-#define B43_HF_BTCOEXALT 0x01000000 /* Bluetooth coexistance in alternate pins */
+-#define B43_HF_TXBTCHECK 0x02000000 /* Bluetooth check during transmission */
+-#define B43_HF_SKCFPUP 0x04000000 /* Skip CFP update */
++#define B43_HF_ANTDIVHELP 0x000000000001ULL /* ucode antenna div helper */
++#define B43_HF_SYMW 0x000000000002ULL /* G-PHY SYM workaround */
++#define B43_HF_RXPULLW 0x000000000004ULL /* RX pullup workaround */
++#define B43_HF_CCKBOOST 0x000000000008ULL /* 4dB CCK power boost (exclusive with OFDM boost) */
++#define B43_HF_BTCOEX 0x000000000010ULL /* Bluetooth coexistance */
++#define B43_HF_GDCW 0x000000000020ULL /* G-PHY DC canceller filter bw workaround */
++#define B43_HF_OFDMPABOOST 0x000000000040ULL /* Enable PA gain boost for OFDM */
++#define B43_HF_ACPR 0x000000000080ULL /* Disable for Japan, channel 14 */
++#define B43_HF_EDCF 0x000000000100ULL /* on if WME and MAC suspended */
++#define B43_HF_TSSIRPSMW 0x000000000200ULL /* TSSI reset PSM ucode workaround */
++#define B43_HF_20IN40IQW 0x000000000200ULL /* 20 in 40 MHz I/Q workaround (rev >= 13 only) */
++#define B43_HF_DSCRQ 0x000000000400ULL /* Disable slow clock request in ucode */
++#define B43_HF_ACIW 0x000000000800ULL /* ACI workaround: shift bits by 2 on PHY CRS */
++#define B43_HF_2060W 0x000000001000ULL /* 2060 radio workaround */
++#define B43_HF_RADARW 0x000000002000ULL /* Radar workaround */
++#define B43_HF_USEDEFKEYS 0x000000004000ULL /* Enable use of default keys */
++#define B43_HF_AFTERBURNER 0x000000008000ULL /* Afterburner enabled */
++#define B43_HF_BT4PRIOCOEX 0x000000010000ULL /* Bluetooth 4-priority coexistance */
++#define B43_HF_FWKUP 0x000000020000ULL /* Fast wake-up ucode */
++#define B43_HF_VCORECALC 0x000000040000ULL /* Force VCO recalculation when powering up synthpu */
++#define B43_HF_PCISCW 0x000000080000ULL /* PCI slow clock workaround */
++#define B43_HF_4318TSSI 0x000000200000ULL /* 4318 TSSI */
++#define B43_HF_FBCMCFIFO 0x000000400000ULL /* Flush bcast/mcast FIFO immediately */
++#define B43_HF_HWPCTL 0x000000800000ULL /* Enable hardwarre power control */
++#define B43_HF_BTCOEXALT 0x000001000000ULL /* Bluetooth coexistance in alternate pins */
++#define B43_HF_TXBTCHECK 0x000002000000ULL /* Bluetooth check during transmission */
++#define B43_HF_SKCFPUP 0x000004000000ULL /* Skip CFP update */
++#define B43_HF_N40W 0x000008000000ULL /* N PHY 40 MHz workaround (rev >= 13 only) */
++#define B43_HF_ANTSEL 0x000020000000ULL /* Antenna selection (for testing antenna div.) */
++#define B43_HF_BT3COEXT 0x000020000000ULL /* Bluetooth 3-wire coexistence (rev >= 13 only) */
++#define B43_HF_BTCANT 0x000040000000ULL /* Bluetooth coexistence (antenna mode) (rev >= 13 only) */
++#define B43_HF_ANTSELEN 0x000100000000ULL /* Antenna selection enabled (rev >= 13 only) */
++#define B43_HF_ANTSELMODE 0x000200000000ULL /* Antenna selection mode (rev >= 13 only) */
++#define B43_HF_MLADVW 0x001000000000ULL /* N PHY ML ADV workaround (rev >= 13 only) */
++#define B43_HF_PR45960W 0x080000000000ULL /* PR 45960 workaround (rev >= 13 only) */
+
+ /* MacFilter offsets. */
+ #define B43_MACFILTER_SELF 0x0000
+@@ -380,7 +411,6 @@ enum {
+
+ #define B43_IRQ_ALL 0xFFFFFFFF
+ #define B43_IRQ_MASKTEMPLATE (B43_IRQ_MAC_SUSPENDED | \
+- B43_IRQ_BEACON | \
+ B43_IRQ_TBTT_INDI | \
+ B43_IRQ_ATIM_END | \
+ B43_IRQ_PMQ | \
+@@ -429,7 +459,6 @@ enum {
+ };
+
+ struct b43_dmaring;
+-struct b43_pioqueue;
+
+ /* The firmware file header */
+ #define B43_FW_TYPE_UCODE 'u'
+@@ -458,20 +487,13 @@ struct b43_iv {
+ } __attribute__((__packed__));
+
+
+-#define B43_PHYMODE(phytype) (1 << (phytype))
+-#define B43_PHYMODE_A B43_PHYMODE(B43_PHYTYPE_A)
+-#define B43_PHYMODE_B B43_PHYMODE(B43_PHYTYPE_B)
+-#define B43_PHYMODE_G B43_PHYMODE(B43_PHYTYPE_G)
+-
+ struct b43_phy {
+- /* Possible PHYMODEs on this PHY */
+- u8 possible_phymodes;
++ /* Band support flags. */
++ bool supports_2ghz;
++ bool supports_5ghz;
++
+ /* GMODE bit enabled? */
+ bool gmode;
+- /* Possible ieee80211 subsystem hwmodes for this PHY.
+- * Which mode is selected, depends on thr GMODE enabled bit */
+-#define B43_MAX_PHYHWMODES 2
+- struct ieee80211_hw_mode hwmodes[B43_MAX_PHYHWMODES];
+
+ /* Analog Type */
+ u8 analog;
+@@ -583,15 +605,27 @@ struct b43_phy {
+
+ /* Data structures for DMA transmission, per 80211 core. */
+ struct b43_dma {
+- struct b43_dmaring *tx_ring0;
+- struct b43_dmaring *tx_ring1;
+- struct b43_dmaring *tx_ring2;
+- struct b43_dmaring *tx_ring3;
+- struct b43_dmaring *tx_ring4;
+- struct b43_dmaring *tx_ring5;
+-
+- struct b43_dmaring *rx_ring0;
+- struct b43_dmaring *rx_ring3; /* only available on core.rev < 5 */
++ struct b43_dmaring *tx_ring_AC_BK; /* Background */
++ struct b43_dmaring *tx_ring_AC_BE; /* Best Effort */
++ struct b43_dmaring *tx_ring_AC_VI; /* Video */
++ struct b43_dmaring *tx_ring_AC_VO; /* Voice */
++ struct b43_dmaring *tx_ring_mcast; /* Multicast */
++
++ struct b43_dmaring *rx_ring;
++};
++
++struct b43_pio_txqueue;
++struct b43_pio_rxqueue;
++
++/* Data structures for PIO transmission, per 80211 core. */
++struct b43_pio {
++ struct b43_pio_txqueue *tx_queue_AC_BK; /* Background */
++ struct b43_pio_txqueue *tx_queue_AC_BE; /* Best Effort */
++ struct b43_pio_txqueue *tx_queue_AC_VI; /* Video */
++ struct b43_pio_txqueue *tx_queue_AC_VO; /* Voice */
++ struct b43_pio_txqueue *tx_queue_mcast; /* Multicast */
++
++ struct b43_pio_rxqueue *rx_queue;
+ };
+
+ /* Context information for a noise calculation (Link Quality). */
+@@ -617,6 +651,35 @@ struct b43_key {
+ u8 algorithm;
+ };
+
++/* SHM offsets to the QOS data structures for the 4 different queues. */
++#define B43_QOS_PARAMS(queue) (B43_SHM_SH_EDCFQ + \
++ (B43_NR_QOSPARAMS * sizeof(u16) * (queue)))
++#define B43_QOS_BACKGROUND B43_QOS_PARAMS(0)
++#define B43_QOS_BESTEFFORT B43_QOS_PARAMS(1)
++#define B43_QOS_VIDEO B43_QOS_PARAMS(2)
++#define B43_QOS_VOICE B43_QOS_PARAMS(3)
++
++/* QOS parameter hardware data structure offsets. */
++#define B43_NR_QOSPARAMS 22
++enum {
++ B43_QOSPARAM_TXOP = 0,
++ B43_QOSPARAM_CWMIN,
++ B43_QOSPARAM_CWMAX,
++ B43_QOSPARAM_CWCUR,
++ B43_QOSPARAM_AIFS,
++ B43_QOSPARAM_BSLOTS,
++ B43_QOSPARAM_REGGAP,
++ B43_QOSPARAM_STATUS,
++};
++
++/* QOS parameters for a queue. */
++struct b43_qos_params {
++ /* The QOS parameters */
++ struct ieee80211_tx_queue_params p;
++ /* Does this need to get uploaded to hardware? */
++ bool need_hw_update;
++};
++
+ struct b43_wldev;
+
+ /* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */
+@@ -667,8 +730,16 @@ struct b43_wl {
+ /* The beacon we are currently using (AP or IBSS mode).
+ * This beacon stuff is protected by the irq_lock. */
+ struct sk_buff *current_beacon;
++ struct ieee80211_tx_control beacon_txctl;
+ bool beacon0_uploaded;
+ bool beacon1_uploaded;
++ struct work_struct beacon_update_trigger;
++
++ /* The current QOS parameters for the 4 queues.
++ * This is protected by the irq_lock. */
++ struct b43_qos_params qos_params[4];
++ /* Workqueue for updating QOS parameters in hardware. */
++ struct work_struct qos_update_work;
+ };
+
+ /* In-memory representation of a cached microcode file. */
+@@ -727,7 +798,6 @@ struct b43_wldev {
+
+ bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */
+ bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */
+- bool short_preamble; /* TRUE, if short preamble is enabled. */
+ bool short_slot; /* TRUE, if short slot timing is enabled. */
+ bool radio_hw_enable; /* saved state of radio hardware enabled state */
+ bool suspend_in_progress; /* TRUE, if we are in a suspend/resume cycle */
+@@ -735,8 +805,15 @@ struct b43_wldev {
+ /* PHY/Radio device. */
+ struct b43_phy phy;
+
+- /* DMA engines. */
+- struct b43_dma dma;
++ union {
++ /* DMA engines. */
++ struct b43_dma dma;
++ /* PIO engines. */
++ struct b43_pio pio;
++ };
++ /* Use b43_using_pio_transfers() to check whether we are using
++ * DMA or PIO data transfers. */
++ bool __using_pio_transfers;
+
+ /* Various statistics about the physical device. */
+ struct b43_stats stats;
+@@ -820,6 +897,22 @@ static inline void b43_write32(struct b43_wldev *dev, u16 offset, u32 value)
+ ssb_write32(dev->dev, offset, value);
+ }
+
++static inline bool b43_using_pio_transfers(struct b43_wldev *dev)
++{
++#ifdef CONFIG_B43_PIO
++ return dev->__using_pio_transfers;
++#else
++ return 0;
++#endif
++}
++
++#ifdef CONFIG_B43_FORCE_PIO
++# define B43_FORCE_PIO 1
++#else
++# define B43_FORCE_PIO 0
++#endif
++
++
+ /* Message printing */
+ void b43info(struct b43_wl *wl, const char *fmt, ...)
+ __attribute__ ((format(printf, 2, 3)));
+diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
+index 48e9124..6dcbb3c 100644
+--- a/drivers/net/wireless/b43/dma.c
++++ b/drivers/net/wireless/b43/dma.c
+@@ -38,6 +38,7 @@
+ #include <linux/delay.h>
+ #include <linux/skbuff.h>
+ #include <linux/etherdevice.h>
++#include <asm/div64.h>
+
+
+ /* 32bit DMA ops. */
+@@ -291,52 +292,6 @@ static inline int request_slot(struct b43_dmaring *ring)
+ return slot;
+ }
+
+-/* Mac80211-queue to b43-ring mapping */
+-static struct b43_dmaring *priority_to_txring(struct b43_wldev *dev,
+- int queue_priority)
+-{
+- struct b43_dmaring *ring;
+-
+-/*FIXME: For now we always run on TX-ring-1 */
+- return dev->dma.tx_ring1;
+-
+- /* 0 = highest priority */
+- switch (queue_priority) {
+- default:
+- B43_WARN_ON(1);
+- /* fallthrough */
+- case 0:
+- ring = dev->dma.tx_ring3;
+- break;
+- case 1:
+- ring = dev->dma.tx_ring2;
+- break;
+- case 2:
+- ring = dev->dma.tx_ring1;
+- break;
+- case 3:
+- ring = dev->dma.tx_ring0;
+- break;
+- }
+-
+- return ring;
+-}
+-
+-/* b43-ring to mac80211-queue mapping */
+-static inline int txring_to_priority(struct b43_dmaring *ring)
+-{
+- static const u8 idx_to_prio[] = { 3, 2, 1, 0, };
+- unsigned int index;
+-
+-/*FIXME: have only one queue, for now */
+- return 0;
+-
+- index = ring->index;
+- if (B43_WARN_ON(index >= ARRAY_SIZE(idx_to_prio)))
+- index = 0;
+- return idx_to_prio[index];
+-}
+-
+ static u16 b43_dmacontroller_base(enum b43_dmatype type, int controller_idx)
+ {
+ static const u16 map64[] = {
+@@ -596,7 +551,6 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring,
+ struct b43_dmadesc_meta *meta, gfp_t gfp_flags)
+ {
+ struct b43_rxhdr_fw4 *rxhdr;
+- struct b43_hwtxstatus *txstat;
+ dma_addr_t dmaaddr;
+ struct sk_buff *skb;
+
+@@ -632,8 +586,6 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring,
+
+ rxhdr = (struct b43_rxhdr_fw4 *)(skb->data);
+ rxhdr->frame_len = 0;
+- txstat = (struct b43_hwtxstatus *)(skb->data);
+- txstat->cookie = 0;
+
+ return 0;
+ }
+@@ -822,6 +774,18 @@ static u64 supported_dma_mask(struct b43_wldev *dev)
+ return DMA_30BIT_MASK;
+ }
+
++static enum b43_dmatype dma_mask_to_engine_type(u64 dmamask)
++{
++ if (dmamask == DMA_30BIT_MASK)
++ return B43_DMA_30BIT;
++ if (dmamask == DMA_32BIT_MASK)
++ return B43_DMA_32BIT;
++ if (dmamask == DMA_64BIT_MASK)
++ return B43_DMA_64BIT;
++ B43_WARN_ON(1);
++ return B43_DMA_30BIT;
++}
++
+ /* Main initialization function. */
+ static
+ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
+@@ -937,16 +901,52 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
+ goto out;
+ }
+
++#define divide(a, b) ({ \
++ typeof(a) __a = a; \
++ do_div(__a, b); \
++ __a; \
++ })
++
++#define modulo(a, b) ({ \
++ typeof(a) __a = a; \
++ do_div(__a, b); \
++ })
++
+ /* Main cleanup function. */
+-static void b43_destroy_dmaring(struct b43_dmaring *ring)
++static void b43_destroy_dmaring(struct b43_dmaring *ring,
++ const char *ringname)
+ {
+ if (!ring)
+ return;
+
+- b43dbg(ring->dev->wl, "DMA-%u 0x%04X (%s) max used slots: %d/%d\n",
+- (unsigned int)(ring->type),
+- ring->mmio_base,
+- (ring->tx) ? "TX" : "RX", ring->max_used_slots, ring->nr_slots);
++#ifdef CONFIG_B43_DEBUG
++ {
++ /* Print some statistics. */
++ u64 failed_packets = ring->nr_failed_tx_packets;
++ u64 succeed_packets = ring->nr_succeed_tx_packets;
++ u64 nr_packets = failed_packets + succeed_packets;
++ u64 permille_failed = 0, average_tries = 0;
++
++ if (nr_packets)
++ permille_failed = divide(failed_packets * 1000, nr_packets);
++ if (nr_packets)
++ average_tries = divide(ring->nr_total_packet_tries * 100, nr_packets);
++
++ b43dbg(ring->dev->wl, "DMA-%u %s: "
++ "Used slots %d/%d, Failed frames %llu/%llu = %llu.%01llu%%, "
++ "Average tries %llu.%02llu\n",
++ (unsigned int)(ring->type), ringname,
++ ring->max_used_slots,
++ ring->nr_slots,
++ (unsigned long long)failed_packets,
++ (unsigned long long)nr_packets,
++ (unsigned long long)divide(permille_failed, 10),
++ (unsigned long long)modulo(permille_failed, 10),
++ (unsigned long long)divide(average_tries, 100),
++ (unsigned long long)modulo(average_tries, 100));
++ }
++#endif /* DEBUG */
++
+ /* Device IRQs are disabled prior entering this function,
+ * so no need to take care of concurrency with rx handler stuff.
+ */
+@@ -959,139 +959,129 @@ static void b43_destroy_dmaring(struct b43_dmaring *ring)
+ kfree(ring);
+ }
+
++#define destroy_ring(dma, ring) do { \
++ b43_destroy_dmaring((dma)->ring, __stringify(ring)); \
++ (dma)->ring = NULL; \
++ } while (0)
++
+ void b43_dma_free(struct b43_wldev *dev)
+ {
+- struct b43_dma *dma = &dev->dma;
++ struct b43_dma *dma;
+
+- b43_destroy_dmaring(dma->rx_ring3);
+- dma->rx_ring3 = NULL;
+- b43_destroy_dmaring(dma->rx_ring0);
+- dma->rx_ring0 = NULL;
+-
+- b43_destroy_dmaring(dma->tx_ring5);
+- dma->tx_ring5 = NULL;
+- b43_destroy_dmaring(dma->tx_ring4);
+- dma->tx_ring4 = NULL;
+- b43_destroy_dmaring(dma->tx_ring3);
+- dma->tx_ring3 = NULL;
+- b43_destroy_dmaring(dma->tx_ring2);
+- dma->tx_ring2 = NULL;
+- b43_destroy_dmaring(dma->tx_ring1);
+- dma->tx_ring1 = NULL;
+- b43_destroy_dmaring(dma->tx_ring0);
+- dma->tx_ring0 = NULL;
++ if (b43_using_pio_transfers(dev))
++ return;
++ dma = &dev->dma;
++
++ destroy_ring(dma, rx_ring);
++ destroy_ring(dma, tx_ring_AC_BK);
++ destroy_ring(dma, tx_ring_AC_BE);
++ destroy_ring(dma, tx_ring_AC_VI);
++ destroy_ring(dma, tx_ring_AC_VO);
++ destroy_ring(dma, tx_ring_mcast);
++}
++
++static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask)
++{
++ u64 orig_mask = mask;
++ bool fallback = 0;
++ int err;
++
++ /* Try to set the DMA mask. If it fails, try falling back to a
++ * lower mask, as we can always also support a lower one. */
++ while (1) {
++ err = ssb_dma_set_mask(dev->dev, mask);
++ if (!err)
++ break;
++ if (mask == DMA_64BIT_MASK) {
++ mask = DMA_32BIT_MASK;
++ fallback = 1;
++ continue;
++ }
++ if (mask == DMA_32BIT_MASK) {
++ mask = DMA_30BIT_MASK;
++ fallback = 1;
++ continue;
++ }
++ b43err(dev->wl, "The machine/kernel does not support "
++ "the required %u-bit DMA mask\n",
++ (unsigned int)dma_mask_to_engine_type(orig_mask));
++ return -EOPNOTSUPP;
++ }
++ if (fallback) {
++ b43info(dev->wl, "DMA mask fallback from %u-bit to %u-bit\n",
++ (unsigned int)dma_mask_to_engine_type(orig_mask),
++ (unsigned int)dma_mask_to_engine_type(mask));
++ }
++
++ return 0;
+ }
+
+ int b43_dma_init(struct b43_wldev *dev)
+ {
+ struct b43_dma *dma = &dev->dma;
+- struct b43_dmaring *ring;
+ int err;
+ u64 dmamask;
+ enum b43_dmatype type;
+
+ dmamask = supported_dma_mask(dev);
+- switch (dmamask) {
+- default:
+- B43_WARN_ON(1);
+- case DMA_30BIT_MASK:
+- type = B43_DMA_30BIT;
+- break;
+- case DMA_32BIT_MASK:
+- type = B43_DMA_32BIT;
+- break;
+- case DMA_64BIT_MASK:
+- type = B43_DMA_64BIT;
+- break;
+- }
+- err = ssb_dma_set_mask(dev->dev, dmamask);
+- if (err) {
+- b43err(dev->wl, "The machine/kernel does not support "
+- "the required DMA mask (0x%08X%08X)\n",
+- (unsigned int)((dmamask & 0xFFFFFFFF00000000ULL) >> 32),
+- (unsigned int)(dmamask & 0x00000000FFFFFFFFULL));
+- return -EOPNOTSUPP;
+- }
++ type = dma_mask_to_engine_type(dmamask);
++ err = b43_dma_set_mask(dev, dmamask);
++ if (err)
++ return err;
+
+ err = -ENOMEM;
+ /* setup TX DMA channels. */
+- ring = b43_setup_dmaring(dev, 0, 1, type);
+- if (!ring)
++ dma->tx_ring_AC_BK = b43_setup_dmaring(dev, 0, 1, type);
++ if (!dma->tx_ring_AC_BK)
+ goto out;
+- dma->tx_ring0 = ring;
+
+- ring = b43_setup_dmaring(dev, 1, 1, type);
+- if (!ring)
+- goto err_destroy_tx0;
+- dma->tx_ring1 = ring;
++ dma->tx_ring_AC_BE = b43_setup_dmaring(dev, 1, 1, type);
++ if (!dma->tx_ring_AC_BE)
++ goto err_destroy_bk;
+
+- ring = b43_setup_dmaring(dev, 2, 1, type);
+- if (!ring)
+- goto err_destroy_tx1;
+- dma->tx_ring2 = ring;
++ dma->tx_ring_AC_VI = b43_setup_dmaring(dev, 2, 1, type);
++ if (!dma->tx_ring_AC_VI)
++ goto err_destroy_be;
+
+- ring = b43_setup_dmaring(dev, 3, 1, type);
+- if (!ring)
+- goto err_destroy_tx2;
+- dma->tx_ring3 = ring;
++ dma->tx_ring_AC_VO = b43_setup_dmaring(dev, 3, 1, type);
++ if (!dma->tx_ring_AC_VO)
++ goto err_destroy_vi;
+
+- ring = b43_setup_dmaring(dev, 4, 1, type);
+- if (!ring)
+- goto err_destroy_tx3;
+- dma->tx_ring4 = ring;
++ dma->tx_ring_mcast = b43_setup_dmaring(dev, 4, 1, type);
++ if (!dma->tx_ring_mcast)
++ goto err_destroy_vo;
+
+- ring = b43_setup_dmaring(dev, 5, 1, type);
+- if (!ring)
+- goto err_destroy_tx4;
+- dma->tx_ring5 = ring;
++ /* setup RX DMA channel. */
++ dma->rx_ring = b43_setup_dmaring(dev, 0, 0, type);
++ if (!dma->rx_ring)
++ goto err_destroy_mcast;
+
+- /* setup RX DMA channels. */
+- ring = b43_setup_dmaring(dev, 0, 0, type);
+- if (!ring)
+- goto err_destroy_tx5;
+- dma->rx_ring0 = ring;
+-
+- if (dev->dev->id.revision < 5) {
+- ring = b43_setup_dmaring(dev, 3, 0, type);
+- if (!ring)
+- goto err_destroy_rx0;
+- dma->rx_ring3 = ring;
+- }
++ /* No support for the TX status DMA ring. */
++ B43_WARN_ON(dev->dev->id.revision < 5);
+
+ b43dbg(dev->wl, "%u-bit DMA initialized\n",
+ (unsigned int)type);
+ err = 0;
+- out:
++out:
+ return err;
+
+- err_destroy_rx0:
+- b43_destroy_dmaring(dma->rx_ring0);
+- dma->rx_ring0 = NULL;
+- err_destroy_tx5:
+- b43_destroy_dmaring(dma->tx_ring5);
+- dma->tx_ring5 = NULL;
+- err_destroy_tx4:
+- b43_destroy_dmaring(dma->tx_ring4);
+- dma->tx_ring4 = NULL;
+- err_destroy_tx3:
+- b43_destroy_dmaring(dma->tx_ring3);
+- dma->tx_ring3 = NULL;
+- err_destroy_tx2:
+- b43_destroy_dmaring(dma->tx_ring2);
+- dma->tx_ring2 = NULL;
+- err_destroy_tx1:
+- b43_destroy_dmaring(dma->tx_ring1);
+- dma->tx_ring1 = NULL;
+- err_destroy_tx0:
+- b43_destroy_dmaring(dma->tx_ring0);
+- dma->tx_ring0 = NULL;
+- goto out;
++err_destroy_mcast:
++ destroy_ring(dma, tx_ring_mcast);
++err_destroy_vo:
++ destroy_ring(dma, tx_ring_AC_VO);
++err_destroy_vi:
++ destroy_ring(dma, tx_ring_AC_VI);
++err_destroy_be:
++ destroy_ring(dma, tx_ring_AC_BE);
++err_destroy_bk:
++ destroy_ring(dma, tx_ring_AC_BK);
++ return err;
+ }
+
+ /* Generate a cookie for the TX header. */
+ static u16 generate_cookie(struct b43_dmaring *ring, int slot)
+ {
+- u16 cookie = 0x1000;
++ u16 cookie;
+
+ /* Use the upper 4 bits of the cookie as
+ * DMA controller ID and store the slot number
+@@ -1101,30 +1091,9 @@ static u16 generate_cookie(struct b43_dmaring *ring, int slot)
+ * It can also not be 0xFFFF because that is special
+ * for multicast frames.
+ */
+- switch (ring->index) {
+- case 0:
+- cookie = 0x1000;
+- break;
+- case 1:
+- cookie = 0x2000;
+- break;
+- case 2:
+- cookie = 0x3000;
+- break;
+- case 3:
+- cookie = 0x4000;
+- break;
+- case 4:
+- cookie = 0x5000;
+- break;
+- case 5:
+- cookie = 0x6000;
+- break;
+- default:
+- B43_WARN_ON(1);
+- }
++ cookie = (((u16)ring->index + 1) << 12);
+ B43_WARN_ON(slot & ~0x0FFF);
+- cookie |= (u16) slot;
++ cookie |= (u16)slot;
+
+ return cookie;
+ }
+@@ -1138,22 +1107,19 @@ struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot)
+
+ switch (cookie & 0xF000) {
+ case 0x1000:
+- ring = dma->tx_ring0;
++ ring = dma->tx_ring_AC_BK;
+ break;
+ case 0x2000:
+- ring = dma->tx_ring1;
++ ring = dma->tx_ring_AC_BE;
+ break;
+ case 0x3000:
+- ring = dma->tx_ring2;
++ ring = dma->tx_ring_AC_VI;
+ break;
+ case 0x4000:
+- ring = dma->tx_ring3;
++ ring = dma->tx_ring_AC_VO;
+ break;
+ case 0x5000:
+- ring = dma->tx_ring4;
+- break;
+- case 0x6000:
+- ring = dma->tx_ring5;
++ ring = dma->tx_ring_mcast;
+ break;
+ default:
+ B43_WARN_ON(1);
+@@ -1180,7 +1146,6 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
+ size_t hdrsize = b43_txhdr_size(ring->dev);
+
+ #define SLOTS_PER_PACKET 2
+- B43_WARN_ON(skb_shinfo(skb)->nr_frags);
+
+ old_top_slot = ring->current_slot;
+ old_used_slots = ring->used_slots;
+@@ -1285,6 +1250,37 @@ static inline int should_inject_overflow(struct b43_dmaring *ring)
+ return 0;
+ }
+
++/* Static mapping of mac80211's queues (priorities) to b43 DMA rings. */
++static struct b43_dmaring * select_ring_by_priority(struct b43_wldev *dev,
++ u8 queue_prio)
++{
++ struct b43_dmaring *ring;
++
++ if (b43_modparam_qos) {
++ /* 0 = highest priority */
++ switch (queue_prio) {
++ default:
++ B43_WARN_ON(1);
++ /* fallthrough */
++ case 0:
++ ring = dev->dma.tx_ring_AC_VO;
++ break;
++ case 1:
++ ring = dev->dma.tx_ring_AC_VI;
++ break;
++ case 2:
++ ring = dev->dma.tx_ring_AC_BE;
++ break;
++ case 3:
++ ring = dev->dma.tx_ring_AC_BK;
++ break;
++ }
++ } else
++ ring = dev->dma.tx_ring_AC_BE;
++
++ return ring;
++}
++
+ int b43_dma_tx(struct b43_wldev *dev,
+ struct sk_buff *skb, struct ieee80211_tx_control *ctl)
+ {
+@@ -1293,21 +1289,16 @@ int b43_dma_tx(struct b43_wldev *dev,
+ int err = 0;
+ unsigned long flags;
+
+- if (unlikely(skb->len < 2 + 2 + 6)) {
+- /* Too short, this can't be a valid frame. */
+- return -EINVAL;
+- }
+-
+ hdr = (struct ieee80211_hdr *)skb->data;
+ if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) {
+ /* The multicast ring will be sent after the DTIM */
+- ring = dev->dma.tx_ring4;
++ ring = dev->dma.tx_ring_mcast;
+ /* Set the more-data bit. Ucode will clear it on
+ * the last frame for us. */
+ hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+ } else {
+ /* Decide by priority where to put this frame. */
+- ring = priority_to_txring(dev, ctl->queue);
++ ring = select_ring_by_priority(dev, ctl->queue);
+ }
+
+ spin_lock_irqsave(&ring->lock, flags);
+@@ -1322,6 +1313,11 @@ int b43_dma_tx(struct b43_wldev *dev,
+ * That would be a mac80211 bug. */
+ B43_WARN_ON(ring->stopped);
+
++ /* Assign the queue number to the ring (if not already done before)
++ * so TX status handling can use it. The queue to ring mapping is
++ * static, so we don't need to store it per frame. */
++ ring->queue_prio = ctl->queue;
++
+ err = dma_tx_fragment(ring, skb, ctl);
+ if (unlikely(err == -ENOKEY)) {
+ /* Drop this packet, as we don't have the encryption key
+@@ -1338,7 +1334,7 @@ int b43_dma_tx(struct b43_wldev *dev,
+ if ((free_slots(ring) < SLOTS_PER_PACKET) ||
+ should_inject_overflow(ring)) {
+ /* This TX ring is full. */
+- ieee80211_stop_queue(dev->wl->hw, txring_to_priority(ring));
++ ieee80211_stop_queue(dev->wl->hw, ctl->queue);
+ ring->stopped = 1;
+ if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
+ b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index);
+@@ -1359,6 +1355,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
+ struct b43_dmadesc_generic *desc;
+ struct b43_dmadesc_meta *meta;
+ int slot;
++ bool frame_succeed;
+
+ ring = parse_cookie(dev, status->cookie, &slot);
+ if (unlikely(!ring))
+@@ -1385,18 +1382,15 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
+ * status of the transmission.
+ * Some fields of txstat are already filled in dma_tx().
+ */
+- if (status->acked) {
+- meta->txstat.flags |= IEEE80211_TX_STATUS_ACK;
+- } else {
+- if (!(meta->txstat.control.flags
+- & IEEE80211_TXCTL_NO_ACK))
+- meta->txstat.excessive_retries = 1;
+- }
+- if (status->frame_count == 0) {
+- /* The frame was not transmitted at all. */
+- meta->txstat.retry_count = 0;
+- } else
+- meta->txstat.retry_count = status->frame_count - 1;
++ frame_succeed = b43_fill_txstatus_report(
++ &(meta->txstat), status);
++#ifdef CONFIG_B43_DEBUG
++ if (frame_succeed)
++ ring->nr_succeed_tx_packets++;
++ else
++ ring->nr_failed_tx_packets++;
++ ring->nr_total_packet_tries += status->frame_count;
++#endif /* DEBUG */
+ ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb,
+ &(meta->txstat));
+ /* skb is freed by ieee80211_tx_status_irqsafe() */
+@@ -1418,7 +1412,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
+ dev->stats.last_tx = jiffies;
+ if (ring->stopped) {
+ B43_WARN_ON(free_slots(ring) < SLOTS_PER_PACKET);
+- ieee80211_wake_queue(dev->wl->hw, txring_to_priority(ring));
++ ieee80211_wake_queue(dev->wl->hw, ring->queue_prio);
+ ring->stopped = 0;
+ if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
+ b43dbg(dev->wl, "Woke up TX ring %d\n", ring->index);
+@@ -1439,7 +1433,7 @@ void b43_dma_get_tx_stats(struct b43_wldev *dev,
+
+ for (i = 0; i < nr_queues; i++) {
+ data = &(stats->data[i]);
+- ring = priority_to_txring(dev, i);
++ ring = select_ring_by_priority(dev, i);
+
+ spin_lock_irqsave(&ring->lock, flags);
+ data->len = ring->used_slots / SLOTS_PER_PACKET;
+@@ -1465,25 +1459,6 @@ static void dma_rx(struct b43_dmaring *ring, int *slot)
+ sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize);
+ skb = meta->skb;
+
+- if (ring->index == 3) {
+- /* We received an xmit status. */
+- struct b43_hwtxstatus *hw = (struct b43_hwtxstatus *)skb->data;
+- int i = 0;
+-
+- while (hw->cookie == 0) {
+- if (i > 100)
+- break;
+- i++;
+- udelay(2);
+- barrier();
+- }
+- b43_handle_hwtxstatus(ring->dev, hw);
+- /* recycle the descriptor buffer. */
+- sync_descbuffer_for_device(ring, meta->dmaaddr,
+- ring->rx_buffersize);
+-
+- return;
+- }
+ rxhdr = (struct b43_rxhdr_fw4 *)skb->data;
+ len = le16_to_cpu(rxhdr->frame_len);
+ if (len == 0) {
+@@ -1540,7 +1515,7 @@ static void dma_rx(struct b43_dmaring *ring, int *slot)
+ skb_pull(skb, ring->frameoffset);
+
+ b43_rx(ring->dev, skb, rxhdr);
+- drop:
++drop:
+ return;
+ }
+
+@@ -1586,21 +1561,55 @@ static void b43_dma_tx_resume_ring(struct b43_dmaring *ring)
+ void b43_dma_tx_suspend(struct b43_wldev *dev)
+ {
+ b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
+- b43_dma_tx_suspend_ring(dev->dma.tx_ring0);
+- b43_dma_tx_suspend_ring(dev->dma.tx_ring1);
+- b43_dma_tx_suspend_ring(dev->dma.tx_ring2);
+- b43_dma_tx_suspend_ring(dev->dma.tx_ring3);
+- b43_dma_tx_suspend_ring(dev->dma.tx_ring4);
+- b43_dma_tx_suspend_ring(dev->dma.tx_ring5);
++ b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_BK);
++ b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_BE);
++ b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_VI);
++ b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_VO);
++ b43_dma_tx_suspend_ring(dev->dma.tx_ring_mcast);
+ }
+
+ void b43_dma_tx_resume(struct b43_wldev *dev)
+ {
+- b43_dma_tx_resume_ring(dev->dma.tx_ring5);
+- b43_dma_tx_resume_ring(dev->dma.tx_ring4);
+- b43_dma_tx_resume_ring(dev->dma.tx_ring3);
+- b43_dma_tx_resume_ring(dev->dma.tx_ring2);
+- b43_dma_tx_resume_ring(dev->dma.tx_ring1);
+- b43_dma_tx_resume_ring(dev->dma.tx_ring0);
++ b43_dma_tx_resume_ring(dev->dma.tx_ring_mcast);
++ b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_VO);
++ b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_VI);
++ b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_BE);
++ b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_BK);
+ b43_power_saving_ctl_bits(dev, 0);
+ }
++
++#ifdef CONFIG_B43_PIO
++static void direct_fifo_rx(struct b43_wldev *dev, enum b43_dmatype type,
++ u16 mmio_base, bool enable)
++{
++ u32 ctl;
++
++ if (type == B43_DMA_64BIT) {
++ ctl = b43_read32(dev, mmio_base + B43_DMA64_RXCTL);
++ ctl &= ~B43_DMA64_RXDIRECTFIFO;
++ if (enable)
++ ctl |= B43_DMA64_RXDIRECTFIFO;
++ b43_write32(dev, mmio_base + B43_DMA64_RXCTL, ctl);
++ } else {
++ ctl = b43_read32(dev, mmio_base + B43_DMA32_RXCTL);
++ ctl &= ~B43_DMA32_RXDIRECTFIFO;
++ if (enable)
++ ctl |= B43_DMA32_RXDIRECTFIFO;
++ b43_write32(dev, mmio_base + B43_DMA32_RXCTL, ctl);
++ }
++}
++
++/* Enable/Disable Direct FIFO Receive Mode (PIO) on a RX engine.
++ * This is called from PIO code, so DMA structures are not available. */
++void b43_dma_direct_fifo_rx(struct b43_wldev *dev,
++ unsigned int engine_index, bool enable)
++{
++ enum b43_dmatype type;
++ u16 mmio_base;
++
++ type = dma_mask_to_engine_type(supported_dma_mask(dev));
++
++ mmio_base = b43_dmacontroller_base(type, engine_index);
++ direct_fifo_rx(dev, type, mmio_base, enable);
++}
++#endif /* CONFIG_B43_PIO */
+diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h
+index c0d6b69..20acf88 100644
+--- a/drivers/net/wireless/b43/dma.h
++++ b/drivers/net/wireless/b43/dma.h
+@@ -245,6 +245,9 @@ struct b43_dmaring {
+ enum b43_dmatype type;
+ /* Boolean. Is this ring stopped at ieee80211 level? */
+ bool stopped;
++ /* The QOS priority assigned to this ring. Only used for TX rings.
++ * This is the mac80211 "queue" value. */
++ u8 queue_prio;
+ /* Lock, only used for TX. */
+ spinlock_t lock;
+ struct b43_wldev *dev;
+@@ -253,7 +256,13 @@ struct b43_dmaring {
+ int max_used_slots;
+ /* Last time we injected a ring overflow. */
+ unsigned long last_injected_overflow;
+-#endif /* CONFIG_B43_DEBUG */
++ /* Statistics: Number of successfully transmitted packets */
++ u64 nr_succeed_tx_packets;
++ /* Statistics: Number of failed TX packets */
++ u64 nr_failed_tx_packets;
++ /* Statistics: Total number of TX plus all retries. */
++ u64 nr_total_packet_tries;
++#endif /* CONFIG_B43_DEBUG */
+ };
+
+ static inline u32 b43_dma_read(struct b43_dmaring *ring, u16 offset)
+@@ -282,4 +291,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
+
+ void b43_dma_rx(struct b43_dmaring *ring);
+
++void b43_dma_direct_fifo_rx(struct b43_wldev *dev,
++ unsigned int engine_index, bool enable);
++
+ #endif /* B43_DMA_H_ */
+diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c
+index 0aac1ff..36a9c42 100644
+--- a/drivers/net/wireless/b43/leds.c
++++ b/drivers/net/wireless/b43/leds.c
+@@ -116,10 +116,7 @@ static void b43_unregister_led(struct b43_led *led)
+ {
+ if (!led->dev)
+ return;
+- if (led->dev->suspend_in_progress)
+- led_classdev_unregister_suspended(&led->led_dev);
+- else
+- led_classdev_unregister(&led->led_dev);
++ led_classdev_unregister(&led->led_dev);
+ b43_led_turn_off(led->dev, led->index, led->activelow);
+ led->dev = NULL;
+ }
+diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
+index c73a75b..4bf8a99 100644
+--- a/drivers/net/wireless/b43/main.c
++++ b/drivers/net/wireless/b43/main.c
+@@ -46,7 +46,9 @@
+ #include "main.h"
+ #include "debugfs.h"
+ #include "phy.h"
++#include "nphy.h"
+ #include "dma.h"
++#include "pio.h"
+ #include "sysfs.h"
+ #include "xmit.h"
+ #include "lo.h"
+@@ -78,6 +80,15 @@ static int modparam_nohwcrypt;
+ module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
+ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
+
++int b43_modparam_qos = 1;
++module_param_named(qos, b43_modparam_qos, int, 0444);
++MODULE_PARM_DESC(qos, "Enable QOS support (default on)");
++
++static int modparam_btcoex = 1;
++module_param_named(btcoex, modparam_btcoex, int, 0444);
++MODULE_PARM_DESC(btcoex, "Enable Bluetooth coexistance (default on)");
++
++
+ static const struct ssb_device_id b43_ssb_tbl[] = {
+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5),
+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 6),
+@@ -96,25 +107,29 @@ MODULE_DEVICE_TABLE(ssb, b43_ssb_tbl);
+ * data in there. This data is the same for all devices, so we don't
+ * get concurrency issues */
+ #define RATETAB_ENT(_rateid, _flags) \
+- { \
+- .rate = B43_RATE_TO_BASE100KBPS(_rateid), \
+- .val = (_rateid), \
+- .val2 = (_rateid), \
+- .flags = (_flags), \
++ { \
++ .bitrate = B43_RATE_TO_BASE100KBPS(_rateid), \
++ .hw_value = (_rateid), \
++ .flags = (_flags), \
+ }
++
++/*
++ * NOTE: When changing this, sync with xmit.c's
++ * b43_plcp_get_bitrate_idx_* functions!
++ */
+ static struct ieee80211_rate __b43_ratetable[] = {
+- RATETAB_ENT(B43_CCK_RATE_1MB, IEEE80211_RATE_CCK),
+- RATETAB_ENT(B43_CCK_RATE_2MB, IEEE80211_RATE_CCK_2),
+- RATETAB_ENT(B43_CCK_RATE_5MB, IEEE80211_RATE_CCK_2),
+- RATETAB_ENT(B43_CCK_RATE_11MB, IEEE80211_RATE_CCK_2),
+- RATETAB_ENT(B43_OFDM_RATE_6MB, IEEE80211_RATE_OFDM),
+- RATETAB_ENT(B43_OFDM_RATE_9MB, IEEE80211_RATE_OFDM),
+- RATETAB_ENT(B43_OFDM_RATE_12MB, IEEE80211_RATE_OFDM),
+- RATETAB_ENT(B43_OFDM_RATE_18MB, IEEE80211_RATE_OFDM),
+- RATETAB_ENT(B43_OFDM_RATE_24MB, IEEE80211_RATE_OFDM),
+- RATETAB_ENT(B43_OFDM_RATE_36MB, IEEE80211_RATE_OFDM),
+- RATETAB_ENT(B43_OFDM_RATE_48MB, IEEE80211_RATE_OFDM),
+- RATETAB_ENT(B43_OFDM_RATE_54MB, IEEE80211_RATE_OFDM),
++ RATETAB_ENT(B43_CCK_RATE_1MB, 0),
++ RATETAB_ENT(B43_CCK_RATE_2MB, IEEE80211_RATE_SHORT_PREAMBLE),
++ RATETAB_ENT(B43_CCK_RATE_5MB, IEEE80211_RATE_SHORT_PREAMBLE),
++ RATETAB_ENT(B43_CCK_RATE_11MB, IEEE80211_RATE_SHORT_PREAMBLE),
++ RATETAB_ENT(B43_OFDM_RATE_6MB, 0),
++ RATETAB_ENT(B43_OFDM_RATE_9MB, 0),
++ RATETAB_ENT(B43_OFDM_RATE_12MB, 0),
++ RATETAB_ENT(B43_OFDM_RATE_18MB, 0),
++ RATETAB_ENT(B43_OFDM_RATE_24MB, 0),
++ RATETAB_ENT(B43_OFDM_RATE_36MB, 0),
++ RATETAB_ENT(B43_OFDM_RATE_48MB, 0),
++ RATETAB_ENT(B43_OFDM_RATE_54MB, 0),
+ };
+
+ #define b43_a_ratetable (__b43_ratetable + 4)
+@@ -124,53 +139,144 @@ static struct ieee80211_rate __b43_ratetable[] = {
+ #define b43_g_ratetable (__b43_ratetable + 0)
+ #define b43_g_ratetable_size 12
+
+-#define CHANTAB_ENT(_chanid, _freq) \
+- { \
+- .chan = (_chanid), \
+- .freq = (_freq), \
+- .val = (_chanid), \
+- .flag = IEEE80211_CHAN_W_SCAN | \
+- IEEE80211_CHAN_W_ACTIVE_SCAN | \
+- IEEE80211_CHAN_W_IBSS, \
+- .power_level = 0xFF, \
+- .antenna_max = 0xFF, \
+- }
++#define CHAN4G(_channel, _freq, _flags) { \
++ .band = IEEE80211_BAND_2GHZ, \
++ .center_freq = (_freq), \
++ .hw_value = (_channel), \
++ .flags = (_flags), \
++ .max_antenna_gain = 0, \
++ .max_power = 30, \
++}
+ static struct ieee80211_channel b43_2ghz_chantable[] = {
+- CHANTAB_ENT(1, 2412),
+- CHANTAB_ENT(2, 2417),
+- CHANTAB_ENT(3, 2422),
+- CHANTAB_ENT(4, 2427),
+- CHANTAB_ENT(5, 2432),
+- CHANTAB_ENT(6, 2437),
+- CHANTAB_ENT(7, 2442),
+- CHANTAB_ENT(8, 2447),
+- CHANTAB_ENT(9, 2452),
+- CHANTAB_ENT(10, 2457),
+- CHANTAB_ENT(11, 2462),
+- CHANTAB_ENT(12, 2467),
+- CHANTAB_ENT(13, 2472),
+- CHANTAB_ENT(14, 2484),
++ CHAN4G(1, 2412, 0),
++ CHAN4G(2, 2417, 0),
++ CHAN4G(3, 2422, 0),
++ CHAN4G(4, 2427, 0),
++ CHAN4G(5, 2432, 0),
++ CHAN4G(6, 2437, 0),
++ CHAN4G(7, 2442, 0),
++ CHAN4G(8, 2447, 0),
++ CHAN4G(9, 2452, 0),
++ CHAN4G(10, 2457, 0),
++ CHAN4G(11, 2462, 0),
++ CHAN4G(12, 2467, 0),
++ CHAN4G(13, 2472, 0),
++ CHAN4G(14, 2484, 0),
+ };
+-#define b43_2ghz_chantable_size ARRAY_SIZE(b43_2ghz_chantable)
+-
+-#if 0
+-static struct ieee80211_channel b43_5ghz_chantable[] = {
+- CHANTAB_ENT(36, 5180),
+- CHANTAB_ENT(40, 5200),
+- CHANTAB_ENT(44, 5220),
+- CHANTAB_ENT(48, 5240),
+- CHANTAB_ENT(52, 5260),
+- CHANTAB_ENT(56, 5280),
+- CHANTAB_ENT(60, 5300),
+- CHANTAB_ENT(64, 5320),
+- CHANTAB_ENT(149, 5745),
+- CHANTAB_ENT(153, 5765),
+- CHANTAB_ENT(157, 5785),
+- CHANTAB_ENT(161, 5805),
+- CHANTAB_ENT(165, 5825),
++#undef CHAN4G
++
++#define CHAN5G(_channel, _flags) { \
++ .band = IEEE80211_BAND_5GHZ, \
++ .center_freq = 5000 + (5 * (_channel)), \
++ .hw_value = (_channel), \
++ .flags = (_flags), \
++ .max_antenna_gain = 0, \
++ .max_power = 30, \
++}
++static struct ieee80211_channel b43_5ghz_nphy_chantable[] = {
++ CHAN5G(32, 0), CHAN5G(34, 0),
++ CHAN5G(36, 0), CHAN5G(38, 0),
++ CHAN5G(40, 0), CHAN5G(42, 0),
++ CHAN5G(44, 0), CHAN5G(46, 0),
++ CHAN5G(48, 0), CHAN5G(50, 0),
++ CHAN5G(52, 0), CHAN5G(54, 0),
++ CHAN5G(56, 0), CHAN5G(58, 0),
++ CHAN5G(60, 0), CHAN5G(62, 0),
++ CHAN5G(64, 0), CHAN5G(66, 0),
++ CHAN5G(68, 0), CHAN5G(70, 0),
++ CHAN5G(72, 0), CHAN5G(74, 0),
++ CHAN5G(76, 0), CHAN5G(78, 0),
++ CHAN5G(80, 0), CHAN5G(82, 0),
++ CHAN5G(84, 0), CHAN5G(86, 0),
++ CHAN5G(88, 0), CHAN5G(90, 0),
++ CHAN5G(92, 0), CHAN5G(94, 0),
++ CHAN5G(96, 0), CHAN5G(98, 0),
++ CHAN5G(100, 0), CHAN5G(102, 0),
++ CHAN5G(104, 0), CHAN5G(106, 0),
++ CHAN5G(108, 0), CHAN5G(110, 0),
++ CHAN5G(112, 0), CHAN5G(114, 0),
++ CHAN5G(116, 0), CHAN5G(118, 0),
++ CHAN5G(120, 0), CHAN5G(122, 0),
++ CHAN5G(124, 0), CHAN5G(126, 0),
++ CHAN5G(128, 0), CHAN5G(130, 0),
++ CHAN5G(132, 0), CHAN5G(134, 0),
++ CHAN5G(136, 0), CHAN5G(138, 0),
++ CHAN5G(140, 0), CHAN5G(142, 0),
++ CHAN5G(144, 0), CHAN5G(145, 0),
++ CHAN5G(146, 0), CHAN5G(147, 0),
++ CHAN5G(148, 0), CHAN5G(149, 0),
++ CHAN5G(150, 0), CHAN5G(151, 0),
++ CHAN5G(152, 0), CHAN5G(153, 0),
++ CHAN5G(154, 0), CHAN5G(155, 0),
++ CHAN5G(156, 0), CHAN5G(157, 0),
++ CHAN5G(158, 0), CHAN5G(159, 0),
++ CHAN5G(160, 0), CHAN5G(161, 0),
++ CHAN5G(162, 0), CHAN5G(163, 0),
++ CHAN5G(164, 0), CHAN5G(165, 0),
++ CHAN5G(166, 0), CHAN5G(168, 0),
++ CHAN5G(170, 0), CHAN5G(172, 0),
++ CHAN5G(174, 0), CHAN5G(176, 0),
++ CHAN5G(178, 0), CHAN5G(180, 0),
++ CHAN5G(182, 0), CHAN5G(184, 0),
++ CHAN5G(186, 0), CHAN5G(188, 0),
++ CHAN5G(190, 0), CHAN5G(192, 0),
++ CHAN5G(194, 0), CHAN5G(196, 0),
++ CHAN5G(198, 0), CHAN5G(200, 0),
++ CHAN5G(202, 0), CHAN5G(204, 0),
++ CHAN5G(206, 0), CHAN5G(208, 0),
++ CHAN5G(210, 0), CHAN5G(212, 0),
++ CHAN5G(214, 0), CHAN5G(216, 0),
++ CHAN5G(218, 0), CHAN5G(220, 0),
++ CHAN5G(222, 0), CHAN5G(224, 0),
++ CHAN5G(226, 0), CHAN5G(228, 0),
++};
++
++static struct ieee80211_channel b43_5ghz_aphy_chantable[] = {
++ CHAN5G(34, 0), CHAN5G(36, 0),
++ CHAN5G(38, 0), CHAN5G(40, 0),
++ CHAN5G(42, 0), CHAN5G(44, 0),
++ CHAN5G(46, 0), CHAN5G(48, 0),
++ CHAN5G(52, 0), CHAN5G(56, 0),
++ CHAN5G(60, 0), CHAN5G(64, 0),
++ CHAN5G(100, 0), CHAN5G(104, 0),
++ CHAN5G(108, 0), CHAN5G(112, 0),
++ CHAN5G(116, 0), CHAN5G(120, 0),
++ CHAN5G(124, 0), CHAN5G(128, 0),
++ CHAN5G(132, 0), CHAN5G(136, 0),
++ CHAN5G(140, 0), CHAN5G(149, 0),
++ CHAN5G(153, 0), CHAN5G(157, 0),
++ CHAN5G(161, 0), CHAN5G(165, 0),
++ CHAN5G(184, 0), CHAN5G(188, 0),
++ CHAN5G(192, 0), CHAN5G(196, 0),
++ CHAN5G(200, 0), CHAN5G(204, 0),
++ CHAN5G(208, 0), CHAN5G(212, 0),
++ CHAN5G(216, 0),
++};
++#undef CHAN5G
++
++static struct ieee80211_supported_band b43_band_5GHz_nphy = {
++ .band = IEEE80211_BAND_5GHZ,
++ .channels = b43_5ghz_nphy_chantable,
++ .n_channels = ARRAY_SIZE(b43_5ghz_nphy_chantable),
++ .bitrates = b43_a_ratetable,
++ .n_bitrates = b43_a_ratetable_size,
++};
++
++static struct ieee80211_supported_band b43_band_5GHz_aphy = {
++ .band = IEEE80211_BAND_5GHZ,
++ .channels = b43_5ghz_aphy_chantable,
++ .n_channels = ARRAY_SIZE(b43_5ghz_aphy_chantable),
++ .bitrates = b43_a_ratetable,
++ .n_bitrates = b43_a_ratetable_size,
++};
++
++static struct ieee80211_supported_band b43_band_2GHz = {
++ .band = IEEE80211_BAND_2GHZ,
++ .channels = b43_2ghz_chantable,
++ .n_channels = ARRAY_SIZE(b43_2ghz_chantable),
++ .bitrates = b43_g_ratetable,
++ .n_bitrates = b43_g_ratetable_size,
+ };
+-#define b43_5ghz_chantable_size ARRAY_SIZE(b43_5ghz_chantable)
+-#endif
+
+ static void b43_wireless_core_exit(struct b43_wldev *dev);
+ static int b43_wireless_core_init(struct b43_wldev *dev);
+@@ -370,24 +476,30 @@ out:
+ }
+
+ /* Read HostFlags */
+-u32 b43_hf_read(struct b43_wldev * dev)
++u64 b43_hf_read(struct b43_wldev * dev)
+ {
+- u32 ret;
++ u64 ret;
+
+ ret = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI);
+ ret <<= 16;
++ ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFMI);
++ ret <<= 16;
+ ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO);
+
+ return ret;
+ }
+
+ /* Write HostFlags */
+-void b43_hf_write(struct b43_wldev *dev, u32 value)
++void b43_hf_write(struct b43_wldev *dev, u64 value)
+ {
+- b43_shm_write16(dev, B43_SHM_SHARED,
+- B43_SHM_SH_HOSTFLO, (value & 0x0000FFFF));
+- b43_shm_write16(dev, B43_SHM_SHARED,
+- B43_SHM_SH_HOSTFHI, ((value & 0xFFFF0000) >> 16));
++ u16 lo, mi, hi;
++
++ lo = (value & 0x00000000FFFFULL);
++ mi = (value & 0x0000FFFF0000ULL) >> 16;
++ hi = (value & 0xFFFF00000000ULL) >> 32;
++ b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO, lo);
++ b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFMI, mi);
++ b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI, hi);
+ }
+
+ void b43_tsf_read(struct b43_wldev *dev, u64 * tsf)
+@@ -912,7 +1024,18 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags)
+ /* Turn the Analog ON/OFF */
+ static void b43_switch_analog(struct b43_wldev *dev, int on)
+ {
+- b43_write16(dev, B43_MMIO_PHY0, on ? 0 : 0xF4);
++ switch (dev->phy.type) {
++ case B43_PHYTYPE_A:
++ case B43_PHYTYPE_G:
++ b43_write16(dev, B43_MMIO_PHY0, on ? 0 : 0xF4);
++ break;
++ case B43_PHYTYPE_N:
++ b43_phy_write(dev, B43_NPHY_AFECTL_OVER,
++ on ? 0 : 0x7FFF);
++ break;
++ default:
++ B43_WARN_ON(1);
++ }
+ }
+
+ void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags)
+@@ -1162,22 +1285,107 @@ static void b43_write_template_common(struct b43_wldev *dev,
+ size + sizeof(struct b43_plcp_hdr6));
+ }
+
++/* Check if the use of the antenna that ieee80211 told us to
++ * use is possible. This will fall back to DEFAULT.
++ * "antenna_nr" is the antenna identifier we got from ieee80211. */
++u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev,
++ u8 antenna_nr)
++{
++ u8 antenna_mask;
++
++ if (antenna_nr == 0) {
++ /* Zero means "use default antenna". That's always OK. */
++ return 0;
++ }
++
++ /* Get the mask of available antennas. */
++ if (dev->phy.gmode)
++ antenna_mask = dev->dev->bus->sprom.ant_available_bg;
++ else
++ antenna_mask = dev->dev->bus->sprom.ant_available_a;
++
++ if (!(antenna_mask & (1 << (antenna_nr - 1)))) {
++ /* This antenna is not available. Fall back to default. */
++ return 0;
++ }
++
++ return antenna_nr;
++}
++
++static int b43_antenna_from_ieee80211(struct b43_wldev *dev, u8 antenna)
++{
++ antenna = b43_ieee80211_antenna_sanitize(dev, antenna);
++ switch (antenna) {
++ case 0: /* default/diversity */
++ return B43_ANTENNA_DEFAULT;
++ case 1: /* Antenna 0 */
++ return B43_ANTENNA0;
++ case 2: /* Antenna 1 */
++ return B43_ANTENNA1;
++ case 3: /* Antenna 2 */
++ return B43_ANTENNA2;
++ case 4: /* Antenna 3 */
++ return B43_ANTENNA3;
++ default:
++ return B43_ANTENNA_DEFAULT;
++ }
++}
++
++/* Convert a b43 antenna number value to the PHY TX control value. */
++static u16 b43_antenna_to_phyctl(int antenna)
++{
++ switch (antenna) {
++ case B43_ANTENNA0:
++ return B43_TXH_PHY_ANT0;
++ case B43_ANTENNA1:
++ return B43_TXH_PHY_ANT1;
++ case B43_ANTENNA2:
++ return B43_TXH_PHY_ANT2;
++ case B43_ANTENNA3:
++ return B43_TXH_PHY_ANT3;
++ case B43_ANTENNA_AUTO:
++ return B43_TXH_PHY_ANT01AUTO;
++ }
++ B43_WARN_ON(1);
++ return 0;
++}
++
+ static void b43_write_beacon_template(struct b43_wldev *dev,
+ u16 ram_offset,
+- u16 shm_size_offset, u8 rate)
++ u16 shm_size_offset)
+ {
+ unsigned int i, len, variable_len;
+ const struct ieee80211_mgmt *bcn;
+ const u8 *ie;
+ bool tim_found = 0;
++ unsigned int rate;
++ u16 ctl;
++ int antenna;
+
+ bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data);
+ len = min((size_t) dev->wl->current_beacon->len,
+ 0x200 - sizeof(struct b43_plcp_hdr6));
++ rate = dev->wl->beacon_txctl.tx_rate->hw_value;
+
+ b43_write_template_common(dev, (const u8 *)bcn,
+ len, ram_offset, shm_size_offset, rate);
+
++ /* Write the PHY TX control parameters. */
++ antenna = b43_antenna_from_ieee80211(dev,
++ dev->wl->beacon_txctl.antenna_sel_tx);
++ antenna = b43_antenna_to_phyctl(antenna);
++ ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
++ /* We can't send beacons with short preamble. Would get PHY errors. */
++ ctl &= ~B43_TXH_PHY_SHORTPRMBL;
++ ctl &= ~B43_TXH_PHY_ANT;
++ ctl &= ~B43_TXH_PHY_ENC;
++ ctl |= antenna;
++ if (b43_is_cck_rate(rate))
++ ctl |= B43_TXH_PHY_ENC_CCK;
++ else
++ ctl |= B43_TXH_PHY_ENC_OFDM;
++ b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL, ctl);
++
+ /* Find the position of the TIM and the DTIM_period value
+ * and write them to SHM. */
+ ie = bcn->u.beacon.variable;
+@@ -1218,21 +1426,23 @@ static void b43_write_beacon_template(struct b43_wldev *dev,
+ b43warn(dev->wl, "Did not find a valid TIM IE in "
+ "the beacon template packet. AP or IBSS operation "
+ "may be broken.\n");
+- }
++ } else
++ b43dbg(dev->wl, "Updated beacon template\n");
+ }
+
+ static void b43_write_probe_resp_plcp(struct b43_wldev *dev,
+- u16 shm_offset, u16 size, u8 rate)
++ u16 shm_offset, u16 size,
++ struct ieee80211_rate *rate)
+ {
+ struct b43_plcp_hdr4 plcp;
+ u32 tmp;
+ __le16 dur;
+
+ plcp.data = 0;
+- b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
++ b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->hw_value);
+ dur = ieee80211_generic_frame_duration(dev->wl->hw,
+ dev->wl->vif, size,
+- B43_RATE_TO_BASE100KBPS(rate));
++ rate);
+ /* Write PLCP in two parts and timing for packet transfer */
+ tmp = le32_to_cpu(plcp.data);
+ b43_shm_write16(dev, B43_SHM_SHARED, shm_offset, tmp & 0xFFFF);
+@@ -1247,7 +1457,8 @@ static void b43_write_probe_resp_plcp(struct b43_wldev *dev,
+ * 3) Stripping TIM
+ */
+ static const u8 * b43_generate_probe_resp(struct b43_wldev *dev,
+- u16 *dest_size, u8 rate)
++ u16 *dest_size,
++ struct ieee80211_rate *rate)
+ {
+ const u8 *src_data;
+ u8 *dest_data;
+@@ -1292,7 +1503,7 @@ static const u8 * b43_generate_probe_resp(struct b43_wldev *dev,
+ IEEE80211_STYPE_PROBE_RESP);
+ dur = ieee80211_generic_frame_duration(dev->wl->hw,
+ dev->wl->vif, *dest_size,
+- B43_RATE_TO_BASE100KBPS(rate));
++ rate);
+ hdr->duration_id = dur;
+
+ return dest_data;
+@@ -1300,7 +1511,8 @@ static const u8 * b43_generate_probe_resp(struct b43_wldev *dev,
+
+ static void b43_write_probe_resp_template(struct b43_wldev *dev,
+ u16 ram_offset,
+- u16 shm_size_offset, u8 rate)
++ u16 shm_size_offset,
++ struct ieee80211_rate *rate)
+ {
+ const u8 *probe_resp_data;
+ u16 size;
+@@ -1313,20 +1525,89 @@ static void b43_write_probe_resp_template(struct b43_wldev *dev,
+ /* Looks like PLCP headers plus packet timings are stored for
+ * all possible basic rates
+ */
+- b43_write_probe_resp_plcp(dev, 0x31A, size, B43_CCK_RATE_1MB);
+- b43_write_probe_resp_plcp(dev, 0x32C, size, B43_CCK_RATE_2MB);
+- b43_write_probe_resp_plcp(dev, 0x33E, size, B43_CCK_RATE_5MB);
+- b43_write_probe_resp_plcp(dev, 0x350, size, B43_CCK_RATE_11MB);
++ b43_write_probe_resp_plcp(dev, 0x31A, size, &b43_b_ratetable[0]);
++ b43_write_probe_resp_plcp(dev, 0x32C, size, &b43_b_ratetable[1]);
++ b43_write_probe_resp_plcp(dev, 0x33E, size, &b43_b_ratetable[2]);
++ b43_write_probe_resp_plcp(dev, 0x350, size, &b43_b_ratetable[3]);
+
+ size = min((size_t) size, 0x200 - sizeof(struct b43_plcp_hdr6));
+ b43_write_template_common(dev, probe_resp_data,
+- size, ram_offset, shm_size_offset, rate);
++ size, ram_offset, shm_size_offset,
++ rate->hw_value);
+ kfree(probe_resp_data);
+ }
+
++static void handle_irq_beacon(struct b43_wldev *dev)
++{
++ struct b43_wl *wl = dev->wl;
++ u32 cmd, beacon0_valid, beacon1_valid;
++
++ if (!b43_is_mode(wl, IEEE80211_IF_TYPE_AP))
++ return;
++
++ /* This is the bottom half of the asynchronous beacon update. */
++
++ /* Ignore interrupt in the future. */
++ dev->irq_savedstate &= ~B43_IRQ_BEACON;
++
++ cmd = b43_read32(dev, B43_MMIO_MACCMD);
++ beacon0_valid = (cmd & B43_MACCMD_BEACON0_VALID);
++ beacon1_valid = (cmd & B43_MACCMD_BEACON1_VALID);
++
++ /* Schedule interrupt manually, if busy. */
++ if (beacon0_valid && beacon1_valid) {
++ b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_BEACON);
++ dev->irq_savedstate |= B43_IRQ_BEACON;
++ return;
++ }
++
++ if (!beacon0_valid) {
++ if (!wl->beacon0_uploaded) {
++ b43_write_beacon_template(dev, 0x68, 0x18);
++ b43_write_probe_resp_template(dev, 0x268, 0x4A,
++ &__b43_ratetable[3]);
++ wl->beacon0_uploaded = 1;
++ }
++ cmd = b43_read32(dev, B43_MMIO_MACCMD);
++ cmd |= B43_MACCMD_BEACON0_VALID;
++ b43_write32(dev, B43_MMIO_MACCMD, cmd);
++ } else if (!beacon1_valid) {
++ if (!wl->beacon1_uploaded) {
++ b43_write_beacon_template(dev, 0x468, 0x1A);
++ wl->beacon1_uploaded = 1;
++ }
++ cmd = b43_read32(dev, B43_MMIO_MACCMD);
++ cmd |= B43_MACCMD_BEACON1_VALID;
++ b43_write32(dev, B43_MMIO_MACCMD, cmd);
++ }
++}
++
++static void b43_beacon_update_trigger_work(struct work_struct *work)
++{
++ struct b43_wl *wl = container_of(work, struct b43_wl,
++ beacon_update_trigger);
++ struct b43_wldev *dev;
++
++ mutex_lock(&wl->mutex);
++ dev = wl->current_dev;
++ if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
++ spin_lock_irq(&wl->irq_lock);
++ /* update beacon right away or defer to irq */
++ dev->irq_savedstate = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
++ handle_irq_beacon(dev);
++ /* The handler might have updated the IRQ mask. */
++ b43_write32(dev, B43_MMIO_GEN_IRQ_MASK,
++ dev->irq_savedstate);
++ mmiowb();
++ spin_unlock_irq(&wl->irq_lock);
++ }
++ mutex_unlock(&wl->mutex);
++}
++
+ /* Asynchronously update the packet templates in template RAM.
+ * Locking: Requires wl->irq_lock to be locked. */
+-static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon)
++static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon,
++ const struct ieee80211_tx_control *txctl)
+ {
+ /* This is the top half of the ansynchronous beacon update.
+ * The bottom half is the beacon IRQ.
+@@ -1337,8 +1618,10 @@ static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon)
+ if (wl->current_beacon)
+ dev_kfree_skb_any(wl->current_beacon);
+ wl->current_beacon = beacon;
++ memcpy(&wl->beacon_txctl, txctl, sizeof(wl->beacon_txctl));
+ wl->beacon0_uploaded = 0;
+ wl->beacon1_uploaded = 0;
++ queue_work(wl->hw->workqueue, &wl->beacon_update_trigger);
+ }
+
+ static void b43_set_ssid(struct b43_wldev *dev, const u8 * ssid, u8 ssid_len)
+@@ -1364,44 +1647,14 @@ static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)
+ {
+ b43_time_lock(dev);
+ if (dev->dev->id.revision >= 3) {
+- b43_write32(dev, 0x188, (beacon_int << 16));
++ b43_write32(dev, B43_MMIO_TSF_CFP_REP, (beacon_int << 16));
++ b43_write32(dev, B43_MMIO_TSF_CFP_START, (beacon_int << 10));
+ } else {
+ b43_write16(dev, 0x606, (beacon_int >> 6));
+ b43_write16(dev, 0x610, beacon_int);
+ }
+ b43_time_unlock(dev);
+-}
+-
+-static void handle_irq_beacon(struct b43_wldev *dev)
+-{
+- struct b43_wl *wl = dev->wl;
+- u32 cmd;
+-
+- if (!b43_is_mode(wl, IEEE80211_IF_TYPE_AP))
+- return;
+-
+- /* This is the bottom half of the asynchronous beacon update. */
+-
+- cmd = b43_read32(dev, B43_MMIO_MACCMD);
+- if (!(cmd & B43_MACCMD_BEACON0_VALID)) {
+- if (!wl->beacon0_uploaded) {
+- b43_write_beacon_template(dev, 0x68, 0x18,
+- B43_CCK_RATE_1MB);
+- b43_write_probe_resp_template(dev, 0x268, 0x4A,
+- B43_CCK_RATE_11MB);
+- wl->beacon0_uploaded = 1;
+- }
+- cmd |= B43_MACCMD_BEACON0_VALID;
+- }
+- if (!(cmd & B43_MACCMD_BEACON1_VALID)) {
+- if (!wl->beacon1_uploaded) {
+- b43_write_beacon_template(dev, 0x468, 0x1A,
+- B43_CCK_RATE_1MB);
+- wl->beacon1_uploaded = 1;
+- }
+- cmd |= B43_MACCMD_BEACON1_VALID;
+- }
+- b43_write32(dev, B43_MMIO_MACCMD, cmd);
++ b43dbg(dev->wl, "Set beacon interval to %u\n", beacon_int);
+ }
+
+ static void handle_irq_ucode_debug(struct b43_wldev *dev)
+@@ -1483,12 +1736,15 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
+ handle_irq_noise(dev);
+
+ /* Check the DMA reason registers for received data. */
+- if (dma_reason[0] & B43_DMAIRQ_RX_DONE)
+- b43_dma_rx(dev->dma.rx_ring0);
+- if (dma_reason[3] & B43_DMAIRQ_RX_DONE)
+- b43_dma_rx(dev->dma.rx_ring3);
++ if (dma_reason[0] & B43_DMAIRQ_RX_DONE) {
++ if (b43_using_pio_transfers(dev))
++ b43_pio_rx(dev->pio.rx_queue);
++ else
++ b43_dma_rx(dev->dma.rx_ring);
++ }
+ B43_WARN_ON(dma_reason[1] & B43_DMAIRQ_RX_DONE);
+ B43_WARN_ON(dma_reason[2] & B43_DMAIRQ_RX_DONE);
++ B43_WARN_ON(dma_reason[3] & B43_DMAIRQ_RX_DONE);
+ B43_WARN_ON(dma_reason[4] & B43_DMAIRQ_RX_DONE);
+ B43_WARN_ON(dma_reason[5] & B43_DMAIRQ_RX_DONE);
+
+@@ -2045,7 +2301,7 @@ static void b43_gpio_cleanup(struct b43_wldev *dev)
+ }
+
+ /* http://bcm-specs.sipsolutions.net/EnableMac */
+-void b43_mac_enable(struct b43_wldev *dev)
++static void b43_mac_enable(struct b43_wldev *dev)
+ {
+ dev->mac_suspended--;
+ B43_WARN_ON(dev->mac_suspended < 0);
+@@ -2068,7 +2324,7 @@ void b43_mac_enable(struct b43_wldev *dev)
+ }
+
+ /* http://bcm-specs.sipsolutions.net/SuspendMAC */
+-void b43_mac_suspend(struct b43_wldev *dev)
++static void b43_mac_suspend(struct b43_wldev *dev)
+ {
+ int i;
+ u32 tmp;
+@@ -2091,6 +2347,13 @@ void b43_mac_suspend(struct b43_wldev *dev)
+ & ~B43_MACCTL_ENABLED);
+ /* force pci to flush the write */
+ b43_read32(dev, B43_MMIO_MACCTL);
++ for (i = 35; i; i--) {
++ tmp = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
++ if (tmp & B43_IRQ_MAC_SUSPENDED)
++ goto out;
++ udelay(10);
++ }
++ /* Hm, it seems this will take some time. Use msleep(). */
+ for (i = 40; i; i--) {
+ tmp = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
+ if (tmp & B43_IRQ_MAC_SUSPENDED)
+@@ -2196,38 +2459,28 @@ static void b43_rate_memory_init(struct b43_wldev *dev)
+ }
+ }
+
++/* Set the default values for the PHY TX Control Words. */
++static void b43_set_phytxctl_defaults(struct b43_wldev *dev)
++{
++ u16 ctl = 0;
++
++ ctl |= B43_TXH_PHY_ENC_CCK;
++ ctl |= B43_TXH_PHY_ANT01AUTO;
++ ctl |= B43_TXH_PHY_TXPWR;
++
++ b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL, ctl);
++ b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL, ctl);
++ b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL, ctl);
++}
++
+ /* Set the TX-Antenna for management frames sent by firmware. */
+ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna)
+ {
+- u16 ant = 0;
++ u16 ant;
+ u16 tmp;
+
+- switch (antenna) {
+- case B43_ANTENNA0:
+- ant |= B43_TXH_PHY_ANT0;
+- break;
+- case B43_ANTENNA1:
+- ant |= B43_TXH_PHY_ANT1;
+- break;
+- case B43_ANTENNA2:
+- ant |= B43_TXH_PHY_ANT2;
+- break;
+- case B43_ANTENNA3:
+- ant |= B43_TXH_PHY_ANT3;
+- break;
+- case B43_ANTENNA_AUTO:
+- ant |= B43_TXH_PHY_ANT01AUTO;
+- break;
+- default:
+- B43_WARN_ON(1);
+- }
+-
+- /* FIXME We also need to set the other flags of the PHY control field somewhere. */
++ ant = b43_antenna_to_phyctl(antenna);
+
+- /* For Beacons */
+- tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
+- tmp = (tmp & ~B43_TXH_PHY_ANT) | ant;
+- b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL, tmp);
+ /* For ACK/CTS */
+ tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL);
+ tmp = (tmp & ~B43_TXH_PHY_ANT) | ant;
+@@ -2555,10 +2808,10 @@ static int b43_rng_read(struct hwrng *rng, u32 * data)
+ return (sizeof(u16));
+ }
+
+-static void b43_rng_exit(struct b43_wl *wl, bool suspended)
++static void b43_rng_exit(struct b43_wl *wl)
+ {
+ if (wl->rng_initialized)
+- __hwrng_unregister(&wl->rng, suspended);
++ hwrng_unregister(&wl->rng);
+ }
+
+ static int b43_rng_init(struct b43_wl *wl)
+@@ -2589,22 +2842,199 @@ static int b43_op_tx(struct ieee80211_hw *hw,
+ struct b43_wldev *dev = wl->current_dev;
+ int err = -ENODEV;
+
++ if (unlikely(skb->len < 2 + 2 + 6)) {
++ /* Too short, this can't be a valid frame. */
++ return -EINVAL;
++ }
++ B43_WARN_ON(skb_shinfo(skb)->nr_frags);
++
+ if (unlikely(!dev))
+ goto out;
+ if (unlikely(b43_status(dev) < B43_STAT_STARTED))
+ goto out;
+- /* DMA-TX is done without a global lock. */
+- err = b43_dma_tx(dev, skb, ctl);
++ /* TX is done without a global lock. */
++ if (b43_using_pio_transfers(dev))
++ err = b43_pio_tx(dev, skb, ctl);
++ else
++ err = b43_dma_tx(dev, skb, ctl);
+ out:
+ if (unlikely(err))
+ return NETDEV_TX_BUSY;
+ return NETDEV_TX_OK;
+ }
+
++/* Locking: wl->irq_lock */
++static void b43_qos_params_upload(struct b43_wldev *dev,
++ const struct ieee80211_tx_queue_params *p,
++ u16 shm_offset)
++{
++ u16 params[B43_NR_QOSPARAMS];
++ int cw_min, cw_max, aifs, bslots, tmp;
++ unsigned int i;
++
++ const u16 aCWmin = 0x0001;
++ const u16 aCWmax = 0x03FF;
++
++ /* Calculate the default values for the parameters, if needed. */
++ switch (shm_offset) {
++ case B43_QOS_VOICE:
++ aifs = (p->aifs == -1) ? 2 : p->aifs;
++ cw_min = (p->cw_min == 0) ? ((aCWmin + 1) / 4 - 1) : p->cw_min;
++ cw_max = (p->cw_max == 0) ? ((aCWmin + 1) / 2 - 1) : p->cw_max;
++ break;
++ case B43_QOS_VIDEO:
++ aifs = (p->aifs == -1) ? 2 : p->aifs;
++ cw_min = (p->cw_min == 0) ? ((aCWmin + 1) / 2 - 1) : p->cw_min;
++ cw_max = (p->cw_max == 0) ? aCWmin : p->cw_max;
++ break;
++ case B43_QOS_BESTEFFORT:
++ aifs = (p->aifs == -1) ? 3 : p->aifs;
++ cw_min = (p->cw_min == 0) ? aCWmin : p->cw_min;
++ cw_max = (p->cw_max == 0) ? aCWmax : p->cw_max;
++ break;
++ case B43_QOS_BACKGROUND:
++ aifs = (p->aifs == -1) ? 7 : p->aifs;
++ cw_min = (p->cw_min == 0) ? aCWmin : p->cw_min;
++ cw_max = (p->cw_max == 0) ? aCWmax : p->cw_max;
++ break;
++ default:
++ B43_WARN_ON(1);
++ return;
++ }
++ if (cw_min <= 0)
++ cw_min = aCWmin;
++ if (cw_max <= 0)
++ cw_max = aCWmin;
++ bslots = b43_read16(dev, B43_MMIO_RNG) % cw_min;
++
++ memset(¶ms, 0, sizeof(params));
++
++ params[B43_QOSPARAM_TXOP] = p->txop * 32;
++ params[B43_QOSPARAM_CWMIN] = cw_min;
++ params[B43_QOSPARAM_CWMAX] = cw_max;
++ params[B43_QOSPARAM_CWCUR] = cw_min;
++ params[B43_QOSPARAM_AIFS] = aifs;
++ params[B43_QOSPARAM_BSLOTS] = bslots;
++ params[B43_QOSPARAM_REGGAP] = bslots + aifs;
++
++ for (i = 0; i < ARRAY_SIZE(params); i++) {
++ if (i == B43_QOSPARAM_STATUS) {
++ tmp = b43_shm_read16(dev, B43_SHM_SHARED,
++ shm_offset + (i * 2));
++ /* Mark the parameters as updated. */
++ tmp |= 0x100;
++ b43_shm_write16(dev, B43_SHM_SHARED,
++ shm_offset + (i * 2),
++ tmp);
++ } else {
++ b43_shm_write16(dev, B43_SHM_SHARED,
++ shm_offset + (i * 2),
++ params[i]);
++ }
++ }
++}
++
++/* Update the QOS parameters in hardware. */
++static void b43_qos_update(struct b43_wldev *dev)
++{
++ struct b43_wl *wl = dev->wl;
++ struct b43_qos_params *params;
++ unsigned long flags;
++ unsigned int i;
++
++ /* Mapping of mac80211 queues to b43 SHM offsets. */
++ static const u16 qos_shm_offsets[] = {
++ [0] = B43_QOS_VOICE,
++ [1] = B43_QOS_VIDEO,
++ [2] = B43_QOS_BESTEFFORT,
++ [3] = B43_QOS_BACKGROUND,
++ };
++ BUILD_BUG_ON(ARRAY_SIZE(qos_shm_offsets) != ARRAY_SIZE(wl->qos_params));
++
++ b43_mac_suspend(dev);
++ spin_lock_irqsave(&wl->irq_lock, flags);
++
++ for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) {
++ params = &(wl->qos_params[i]);
++ if (params->need_hw_update) {
++ b43_qos_params_upload(dev, &(params->p),
++ qos_shm_offsets[i]);
++ params->need_hw_update = 0;
++ }
++ }
++
++ spin_unlock_irqrestore(&wl->irq_lock, flags);
++ b43_mac_enable(dev);
++}
++
++static void b43_qos_clear(struct b43_wl *wl)
++{
++ struct b43_qos_params *params;
++ unsigned int i;
++
++ for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) {
++ params = &(wl->qos_params[i]);
++
++ memset(&(params->p), 0, sizeof(params->p));
++ params->p.aifs = -1;
++ params->need_hw_update = 1;
++ }
++}
++
++/* Initialize the core's QOS capabilities */
++static void b43_qos_init(struct b43_wldev *dev)
++{
++ struct b43_wl *wl = dev->wl;
++ unsigned int i;
++
++ /* Upload the current QOS parameters. */
++ for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++)
++ wl->qos_params[i].need_hw_update = 1;
++ b43_qos_update(dev);
++
++ /* Enable QOS support. */
++ b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF);
++ b43_write16(dev, B43_MMIO_IFSCTL,
++ b43_read16(dev, B43_MMIO_IFSCTL)
++ | B43_MMIO_IFSCTL_USE_EDCF);
++}
++
++static void b43_qos_update_work(struct work_struct *work)
++{
++ struct b43_wl *wl = container_of(work, struct b43_wl, qos_update_work);
++ struct b43_wldev *dev;
++
++ mutex_lock(&wl->mutex);
++ dev = wl->current_dev;
++ if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED)))
++ b43_qos_update(dev);
++ mutex_unlock(&wl->mutex);
++}
++
+ static int b43_op_conf_tx(struct ieee80211_hw *hw,
+- int queue,
++ int _queue,
+ const struct ieee80211_tx_queue_params *params)
+ {
++ struct b43_wl *wl = hw_to_b43_wl(hw);
++ unsigned long flags;
++ unsigned int queue = (unsigned int)_queue;
++ struct b43_qos_params *p;
++
++ if (queue >= ARRAY_SIZE(wl->qos_params)) {
++ /* Queue not available or don't support setting
++ * params on this queue. Return success to not
++ * confuse mac80211. */
++ return 0;
++ }
++
++ spin_lock_irqsave(&wl->irq_lock, flags);
++ p = &(wl->qos_params[queue]);
++ memcpy(&(p->p), params, sizeof(p->p));
++ p->need_hw_update = 1;
++ spin_unlock_irqrestore(&wl->irq_lock, flags);
++
++ queue_work(hw->workqueue, &wl->qos_update_work);
++
+ return 0;
+ }
+
+@@ -2620,7 +3050,10 @@ static int b43_op_get_tx_stats(struct ieee80211_hw *hw,
+ goto out;
+ spin_lock_irqsave(&wl->irq_lock, flags);
+ if (likely(b43_status(dev) >= B43_STAT_STARTED)) {
+- b43_dma_get_tx_stats(dev, stats);
++ if (b43_using_pio_transfers(dev))
++ b43_pio_get_tx_stats(dev, stats);
++ else
++ b43_dma_get_tx_stats(dev, stats);
+ err = 0;
+ }
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
+@@ -2641,45 +3074,6 @@ static int b43_op_get_stats(struct ieee80211_hw *hw,
+ return 0;
+ }
+
+-static const char *phymode_to_string(unsigned int phymode)
+-{
+- switch (phymode) {
+- case B43_PHYMODE_A:
+- return "A";
+- case B43_PHYMODE_B:
+- return "B";
+- case B43_PHYMODE_G:
+- return "G";
+- default:
+- B43_WARN_ON(1);
+- }
+- return "";
+-}
+-
+-static int find_wldev_for_phymode(struct b43_wl *wl,
+- unsigned int phymode,
+- struct b43_wldev **dev, bool * gmode)
+-{
+- struct b43_wldev *d;
+-
+- list_for_each_entry(d, &wl->devlist, list) {
+- if (d->phy.possible_phymodes & phymode) {
+- /* Ok, this device supports the PHY-mode.
+- * Now figure out how the gmode bit has to be
+- * set to support it. */
+- if (phymode == B43_PHYMODE_A)
+- *gmode = 0;
+- else
+- *gmode = 1;
+- *dev = d;
+-
+- return 0;
+- }
+- }
+-
+- return -ESRCH;
+-}
+-
+ static void b43_put_phy_into_reset(struct b43_wldev *dev)
+ {
+ struct ssb_device *sdev = dev->dev;
+@@ -2699,28 +3093,64 @@ static void b43_put_phy_into_reset(struct b43_wldev *dev)
+ msleep(1);
+ }
+
++static const char * band_to_string(enum ieee80211_band band)
++{
++ switch (band) {
++ case IEEE80211_BAND_5GHZ:
++ return "5";
++ case IEEE80211_BAND_2GHZ:
++ return "2.4";
++ default:
++ break;
++ }
++ B43_WARN_ON(1);
++ return "";
++}
++
+ /* Expects wl->mutex locked */
+-static int b43_switch_phymode(struct b43_wl *wl, unsigned int new_mode)
++static int b43_switch_band(struct b43_wl *wl, struct ieee80211_channel *chan)
+ {
+- struct b43_wldev *up_dev;
++ struct b43_wldev *up_dev = NULL;
+ struct b43_wldev *down_dev;
++ struct b43_wldev *d;
+ int err;
+- bool gmode = 0;
++ bool gmode;
+ int prev_status;
+
+- err = find_wldev_for_phymode(wl, new_mode, &up_dev, &gmode);
+- if (err) {
+- b43err(wl, "Could not find a device for %s-PHY mode\n",
+- phymode_to_string(new_mode));
+- return err;
++ /* Find a device and PHY which supports the band. */
++ list_for_each_entry(d, &wl->devlist, list) {
++ switch (chan->band) {
++ case IEEE80211_BAND_5GHZ:
++ if (d->phy.supports_5ghz) {
++ up_dev = d;
++ gmode = 0;
++ }
++ break;
++ case IEEE80211_BAND_2GHZ:
++ if (d->phy.supports_2ghz) {
++ up_dev = d;
++ gmode = 1;
++ }
++ break;
++ default:
++ B43_WARN_ON(1);
++ return -EINVAL;
++ }
++ if (up_dev)
++ break;
++ }
++ if (!up_dev) {
++ b43err(wl, "Could not find a device for %s-GHz band operation\n",
++ band_to_string(chan->band));
++ return -ENODEV;
+ }
+ if ((up_dev == wl->current_dev) &&
+ (!!wl->current_dev->phy.gmode == !!gmode)) {
+ /* This device is already running. */
+ return 0;
+ }
+- b43dbg(wl, "Reconfiguring PHYmode to %s-PHY\n",
+- phymode_to_string(new_mode));
++ b43dbg(wl, "Switching to %s-GHz band\n",
++ band_to_string(chan->band));
+ down_dev = wl->current_dev;
+
+ prev_status = b43_status(down_dev);
+@@ -2742,8 +3172,8 @@ static int b43_switch_phymode(struct b43_wl *wl, unsigned int new_mode)
+ err = b43_wireless_core_init(up_dev);
+ if (err) {
+ b43err(wl, "Fatal: Could not initialize device for "
+- "newly selected %s-PHY mode\n",
+- phymode_to_string(new_mode));
++ "selected %s-GHz band\n",
++ band_to_string(chan->band));
+ goto init_failure;
+ }
+ }
+@@ -2751,8 +3181,8 @@ static int b43_switch_phymode(struct b43_wl *wl, unsigned int new_mode)
+ err = b43_wireless_core_start(up_dev);
+ if (err) {
+ b43err(wl, "Fatal: Coult not start device for "
+- "newly selected %s-PHY mode\n",
+- phymode_to_string(new_mode));
++ "selected %s-GHz band\n",
++ band_to_string(chan->band));
+ b43_wireless_core_exit(up_dev);
+ goto init_failure;
+ }
+@@ -2762,86 +3192,26 @@ static int b43_switch_phymode(struct b43_wl *wl, unsigned int new_mode)
+ wl->current_dev = up_dev;
+
+ return 0;
+- init_failure:
++init_failure:
+ /* Whoops, failed to init the new core. No core is operating now. */
+ wl->current_dev = NULL;
+ return err;
+ }
+
+-/* Check if the use of the antenna that ieee80211 told us to
+- * use is possible. This will fall back to DEFAULT.
+- * "antenna_nr" is the antenna identifier we got from ieee80211. */
+-u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev,
+- u8 antenna_nr)
+-{
+- u8 antenna_mask;
+-
+- if (antenna_nr == 0) {
+- /* Zero means "use default antenna". That's always OK. */
+- return 0;
+- }
+-
+- /* Get the mask of available antennas. */
+- if (dev->phy.gmode)
+- antenna_mask = dev->dev->bus->sprom.ant_available_bg;
+- else
+- antenna_mask = dev->dev->bus->sprom.ant_available_a;
+-
+- if (!(antenna_mask & (1 << (antenna_nr - 1)))) {
+- /* This antenna is not available. Fall back to default. */
+- return 0;
+- }
+-
+- return antenna_nr;
+-}
+-
+-static int b43_antenna_from_ieee80211(struct b43_wldev *dev, u8 antenna)
+-{
+- antenna = b43_ieee80211_antenna_sanitize(dev, antenna);
+- switch (antenna) {
+- case 0: /* default/diversity */
+- return B43_ANTENNA_DEFAULT;
+- case 1: /* Antenna 0 */
+- return B43_ANTENNA0;
+- case 2: /* Antenna 1 */
+- return B43_ANTENNA1;
+- case 3: /* Antenna 2 */
+- return B43_ANTENNA2;
+- case 4: /* Antenna 3 */
+- return B43_ANTENNA3;
+- default:
+- return B43_ANTENNA_DEFAULT;
+- }
+-}
+-
+ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+ {
+ struct b43_wl *wl = hw_to_b43_wl(hw);
+ struct b43_wldev *dev;
+ struct b43_phy *phy;
+ unsigned long flags;
+- unsigned int new_phymode = 0xFFFF;
+ int antenna;
+ int err = 0;
+ u32 savedirqs;
+
+ mutex_lock(&wl->mutex);
+
+- /* Switch the PHY mode (if necessary). */
+- switch (conf->phymode) {
+- case MODE_IEEE80211A:
+- new_phymode = B43_PHYMODE_A;
+- break;
+- case MODE_IEEE80211B:
+- new_phymode = B43_PHYMODE_B;
+- break;
+- case MODE_IEEE80211G:
+- new_phymode = B43_PHYMODE_G;
+- break;
+- default:
+- B43_WARN_ON(1);
+- }
+- err = b43_switch_phymode(wl, new_phymode);
++ /* Switch the band (if necessary). This might change the active core. */
++ err = b43_switch_band(wl, conf->channel);
+ if (err)
+ goto out_unlock_mutex;
+ dev = wl->current_dev;
+@@ -2861,8 +3231,8 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+
+ /* Switch to the requested channel.
+ * The firmware takes care of races with the TX handler. */
+- if (conf->channel_val != phy->channel)
+- b43_radio_selectchannel(dev, conf->channel_val, 0);
++ if (conf->channel->hw_value != phy->channel)
++ b43_radio_selectchannel(dev, conf->channel->hw_value, 0);
+
+ /* Enable/Disable ShortSlot timing. */
+ if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) !=
+@@ -3075,8 +3445,10 @@ static int b43_op_config_interface(struct ieee80211_hw *hw,
+ if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) {
+ B43_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP);
+ b43_set_ssid(dev, conf->ssid, conf->ssid_len);
+- if (conf->beacon)
+- b43_update_templates(wl, conf->beacon);
++ if (conf->beacon) {
++ b43_update_templates(wl, conf->beacon,
++ conf->beacon_control);
++ }
+ }
+ b43_write_mac_bssid_templates(dev);
+ }
+@@ -3106,6 +3478,7 @@ static void b43_wireless_core_stop(struct b43_wldev *dev)
+
+ b43_set_status(dev, B43_STAT_INITIALIZED);
+
++ b43_pio_stop(dev);
+ mutex_unlock(&wl->mutex);
+ /* Must unlock as it would otherwise deadlock. No races here.
+ * Cancel the possibly running self-rearming periodic work. */
+@@ -3337,8 +3710,10 @@ static void setup_struct_wldev_for_init(struct b43_wldev *dev)
+ static void b43_bluetooth_coext_enable(struct b43_wldev *dev)
+ {
+ struct ssb_sprom *sprom = &dev->dev->bus->sprom;
+- u32 hf;
++ u64 hf;
+
++ if (!modparam_btcoex)
++ return;
+ if (!(sprom->boardflags_lo & B43_BFL_BTCOEXIST))
+ return;
+ if (dev->phy.type != B43_PHYTYPE_B && !dev->phy.gmode)
+@@ -3350,11 +3725,13 @@ static void b43_bluetooth_coext_enable(struct b43_wldev *dev)
+ else
+ hf |= B43_HF_BTCOEX;
+ b43_hf_write(dev, hf);
+- //TODO
+ }
+
+ static void b43_bluetooth_coext_disable(struct b43_wldev *dev)
+-{ //TODO
++{
++ if (!modparam_btcoex)
++ return;
++ //TODO
+ }
+
+ static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev)
+@@ -3400,6 +3777,41 @@ static void b43_set_retry_limits(struct b43_wldev *dev,
+ long_retry);
+ }
+
++static void b43_set_synth_pu_delay(struct b43_wldev *dev, bool idle)
++{
++ u16 pu_delay;
++
++ /* The time value is in microseconds. */
++ if (dev->phy.type == B43_PHYTYPE_A)
++ pu_delay = 3700;
++ else
++ pu_delay = 1050;
++ if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS) || idle)
++ pu_delay = 500;
++ if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8))
++ pu_delay = max(pu_delay, (u16)2400);
++
++ b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_SPUWKUP, pu_delay);
++}
++
++/* Set the TSF CFP pre-TargetBeaconTransmissionTime. */
++static void b43_set_pretbtt(struct b43_wldev *dev)
++{
++ u16 pretbtt;
++
++ /* The time value is in microseconds. */
++ if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS)) {
++ pretbtt = 2;
++ } else {
++ if (dev->phy.type == B43_PHYTYPE_A)
++ pretbtt = 120;
++ else
++ pretbtt = 250;
++ }
++ b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRETBTT, pretbtt);
++ b43_write16(dev, B43_MMIO_TSF_CFP_PRETBTT, pretbtt);
++}
++
+ /* Shutdown a wireless core */
+ /* Locking: wl->mutex */
+ static void b43_wireless_core_exit(struct b43_wldev *dev)
+@@ -3420,9 +3832,10 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
+
+ if (!dev->suspend_in_progress) {
+ b43_leds_exit(dev);
+- b43_rng_exit(dev->wl, false);
++ b43_rng_exit(dev->wl);
+ }
+ b43_dma_free(dev);
++ b43_pio_free(dev);
+ b43_chip_exit(dev);
+ b43_radio_turn_off(dev, 1);
+ b43_switch_analog(dev, 0);
+@@ -3447,7 +3860,8 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
+ struct ssb_sprom *sprom = &bus->sprom;
+ struct b43_phy *phy = &dev->phy;
+ int err;
+- u32 hf, tmp;
++ u64 hf;
++ u32 tmp;
+
+ B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT);
+
+@@ -3510,6 +3924,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
+ b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRMAXTIME, 1);
+
+ b43_rate_memory_init(dev);
++ b43_set_phytxctl_defaults(dev);
+
+ /* Minimum Contention Window */
+ if (phy->type == B43_PHYTYPE_B) {
+@@ -3520,18 +3935,17 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
+ /* Maximum Contention Window */
+ b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF);
+
+- err = b43_dma_init(dev);
++ if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || B43_FORCE_PIO) {
++ dev->__using_pio_transfers = 1;
++ err = b43_pio_init(dev);
++ } else {
++ dev->__using_pio_transfers = 0;
++ err = b43_dma_init(dev);
++ }
+ if (err)
+ goto err_chip_exit;
+ b43_qos_init(dev);
+-
+-//FIXME
+-#if 1
+- b43_write16(dev, 0x0612, 0x0050);
+- b43_shm_write16(dev, B43_SHM_SHARED, 0x0416, 0x0050);
+- b43_shm_write16(dev, B43_SHM_SHARED, 0x0414, 0x01F4);
+-#endif
+-
++ b43_set_synth_pu_delay(dev, 1);
+ b43_bluetooth_coext_enable(dev);
+
+ ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */
+@@ -3591,6 +4005,8 @@ static int b43_op_add_interface(struct ieee80211_hw *hw,
+
+ spin_lock_irqsave(&wl->irq_lock, flags);
+ b43_adjust_opmode(dev);
++ b43_set_pretbtt(dev);
++ b43_set_synth_pu_delay(dev, 0);
+ b43_upload_card_macaddress(dev);
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
+
+@@ -3642,6 +4058,7 @@ static int b43_op_start(struct ieee80211_hw *hw)
+ memset(wl->mac_addr, 0, ETH_ALEN);
+ wl->filter_flags = 0;
+ wl->radiotap_enabled = 0;
++ b43_qos_clear(wl);
+
+ /* First register RFkill.
+ * LEDs that are registered later depend on it. */
+@@ -3683,6 +4100,8 @@ static void b43_op_stop(struct ieee80211_hw *hw)
+ struct b43_wldev *dev = wl->current_dev;
+
+ b43_rfkill_exit(dev);
++ cancel_work_sync(&(wl->qos_update_work));
++ cancel_work_sync(&(wl->beacon_update_trigger));
+
+ mutex_lock(&wl->mutex);
+ if (b43_status(dev) >= B43_STAT_STARTED)
+@@ -3716,16 +4135,17 @@ static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set)
+ struct b43_wl *wl = hw_to_b43_wl(hw);
+ struct sk_buff *beacon;
+ unsigned long flags;
++ struct ieee80211_tx_control txctl;
+
+ /* We could modify the existing beacon and set the aid bit in
+ * the TIM field, but that would probably require resizing and
+ * moving of data within the beacon template.
+ * Simply request a new beacon and let mac80211 do the hard work. */
+- beacon = ieee80211_beacon_get(hw, wl->vif, NULL);
++ beacon = ieee80211_beacon_get(hw, wl->vif, &txctl);
+ if (unlikely(!beacon))
+ return -ENOMEM;
+ spin_lock_irqsave(&wl->irq_lock, flags);
+- b43_update_templates(wl, beacon);
++ b43_update_templates(wl, beacon, &txctl);
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
+
+ return 0;
+@@ -3739,12 +4159,22 @@ static int b43_op_ibss_beacon_update(struct ieee80211_hw *hw,
+ unsigned long flags;
+
+ spin_lock_irqsave(&wl->irq_lock, flags);
+- b43_update_templates(wl, beacon);
++ b43_update_templates(wl, beacon, ctl);
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
+
+ return 0;
+ }
+
++static void b43_op_sta_notify(struct ieee80211_hw *hw,
++ struct ieee80211_vif *vif,
++ enum sta_notify_cmd notify_cmd,
++ const u8 *addr)
++{
++ struct b43_wl *wl = hw_to_b43_wl(hw);
++
++ B43_WARN_ON(!vif || wl->vif != vif);
++}
++
+ static const struct ieee80211_ops b43_hw_ops = {
+ .tx = b43_op_tx,
+ .conf_tx = b43_op_conf_tx,
+@@ -3761,6 +4191,7 @@ static const struct ieee80211_ops b43_hw_ops = {
+ .set_retry_limit = b43_op_set_retry_limit,
+ .set_tim = b43_op_beacon_set_tim,
+ .beacon_update = b43_op_ibss_beacon_update,
++ .sta_notify = b43_op_sta_notify,
+ };
+
+ /* Hard-reset the chip. Do not call this directly.
+@@ -3804,31 +4235,23 @@ static void b43_chip_reset(struct work_struct *work)
+ b43info(wl, "Controller restarted\n");
+ }
+
+-static int b43_setup_modes(struct b43_wldev *dev,
++static int b43_setup_bands(struct b43_wldev *dev,
+ bool have_2ghz_phy, bool have_5ghz_phy)
+ {
+ struct ieee80211_hw *hw = dev->wl->hw;
+- struct ieee80211_hw_mode *mode;
+- struct b43_phy *phy = &dev->phy;
+- int err;
+
+- /* XXX: This function will go away soon, when mac80211
+- * band stuff is rewritten. So this is just a hack.
+- * For now we always claim GPHY mode, as there is no
+- * support for NPHY and APHY in the device, yet.
+- * This assumption is OK, as any B, N or A PHY will already
+- * have died a horrible sanity check death earlier. */
+-
+- mode = &phy->hwmodes[0];
+- mode->mode = MODE_IEEE80211G;
+- mode->num_channels = b43_2ghz_chantable_size;
+- mode->channels = b43_2ghz_chantable;
+- mode->num_rates = b43_g_ratetable_size;
+- mode->rates = b43_g_ratetable;
+- err = ieee80211_register_hwmode(hw, mode);
+- if (err)
+- return err;
+- phy->possible_phymodes |= B43_PHYMODE_G;
++ if (have_2ghz_phy)
++ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &b43_band_2GHz;
++ if (dev->phy.type == B43_PHYTYPE_N) {
++ if (have_5ghz_phy)
++ hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_nphy;
++ } else {
++ if (have_5ghz_phy)
++ hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_aphy;
++ }
++
++ dev->phy.supports_2ghz = have_2ghz_phy;
++ dev->phy.supports_5ghz = have_5ghz_phy;
+
+ return 0;
+ }
+@@ -3910,7 +4333,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
+ err = b43_validate_chipaccess(dev);
+ if (err)
+ goto err_powerdown;
+- err = b43_setup_modes(dev, have_2ghz_phy, have_5ghz_phy);
++ err = b43_setup_bands(dev, have_2ghz_phy, have_5ghz_phy);
+ if (err)
+ goto err_powerdown;
+
+@@ -4000,8 +4423,16 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
+ return err;
+ }
+
++#define IS_PDEV(pdev, _vendor, _device, _subvendor, _subdevice) ( \
++ (pdev->vendor == PCI_VENDOR_ID_##_vendor) && \
++ (pdev->device == _device) && \
++ (pdev->subsystem_vendor == PCI_VENDOR_ID_##_subvendor) && \
++ (pdev->subsystem_device == _subdevice) )
++
+ static void b43_sprom_fixup(struct ssb_bus *bus)
+ {
++ struct pci_dev *pdev;
++
+ /* boardflags workarounds */
+ if (bus->boardinfo.vendor == SSB_BOARDVENDOR_DELL &&
+ bus->chip_id == 0x4301 && bus->boardinfo.rev == 0x74)
+@@ -4009,6 +4440,13 @@ static void b43_sprom_fixup(struct ssb_bus *bus)
+ if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
+ bus->boardinfo.type == 0x4E && bus->boardinfo.rev > 0x40)
+ bus->sprom.boardflags_lo |= B43_BFL_PACTRL;
++ if (bus->bustype == SSB_BUSTYPE_PCI) {
++ pdev = bus->host_pci;
++ if (IS_PDEV(pdev, BROADCOM, 0x4318, ASUSTEK, 0x100F) ||
++ IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0015) ||
++ IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0013))
++ bus->sprom.boardflags_lo &= ~B43_BFL_BTCOEXIST;
++ }
+ }
+
+ static void b43_wireless_exit(struct ssb_device *dev, struct b43_wl *wl)
+@@ -4040,7 +4478,7 @@ static int b43_wireless_init(struct ssb_device *dev)
+ hw->max_signal = 100;
+ hw->max_rssi = -110;
+ hw->max_noise = -110;
+- hw->queues = 1; /* FIXME: hardware has more queues */
++ hw->queues = b43_modparam_qos ? 4 : 1;
+ SET_IEEE80211_DEV(hw, dev->dev);
+ if (is_valid_ether_addr(sprom->et1mac))
+ SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
+@@ -4056,6 +4494,8 @@ static int b43_wireless_init(struct ssb_device *dev)
+ spin_lock_init(&wl->shm_lock);
+ mutex_init(&wl->mutex);
+ INIT_LIST_HEAD(&wl->devlist);
++ INIT_WORK(&wl->qos_update_work, b43_qos_update_work);
++ INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work);
+
+ ssb_set_devtypedata(dev, wl);
+ b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id);
+@@ -4173,7 +4613,7 @@ static int b43_resume(struct ssb_device *dev)
+ err = b43_wireless_core_start(wldev);
+ if (err) {
+ b43_leds_exit(wldev);
+- b43_rng_exit(wldev->wl, true);
++ b43_rng_exit(wldev->wl);
+ b43_wireless_core_exit(wldev);
+ b43err(wl, "Resume failed at core start\n");
+ goto out;
+diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h
+index 2d52d9d..5230aec 100644
+--- a/drivers/net/wireless/b43/main.h
++++ b/drivers/net/wireless/b43/main.h
+@@ -38,6 +38,10 @@
+ /* Magic helper macro to pad structures. Ignore those above. It's magic. */
+ #define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes))
+
++
++extern int b43_modparam_qos;
++
++
+ /* Lightweight function to convert a frequency (in Mhz) to a channel number. */
+ static inline u8 b43_freq_to_channel_5ghz(int freq)
+ {
+@@ -95,16 +99,13 @@ u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset);
+ void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value);
+ void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value);
+
+-u32 b43_hf_read(struct b43_wldev *dev);
+-void b43_hf_write(struct b43_wldev *dev, u32 value);
++u64 b43_hf_read(struct b43_wldev *dev);
++void b43_hf_write(struct b43_wldev *dev, u64 value);
+
+ void b43_dummy_transmission(struct b43_wldev *dev);
+
+ void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags);
+
+-void b43_mac_suspend(struct b43_wldev *dev);
+-void b43_mac_enable(struct b43_wldev *dev);
+-
+ void b43_controller_restart(struct b43_wldev *dev, const char *reason);
+
+ #define B43_PS_ENABLED (1 << 0) /* Force enable hardware power saving */
+diff --git a/drivers/net/wireless/b43/nphy.c b/drivers/net/wireless/b43/nphy.c
+index 705131e..8695eb2 100644
+--- a/drivers/net/wireless/b43/nphy.c
++++ b/drivers/net/wireless/b43/nphy.c
+@@ -240,7 +240,6 @@ static void b43_nphy_workarounds(struct b43_wldev *dev)
+
+ b43_phy_set(dev, B43_NPHY_IQFLIP,
+ B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
+- //FIXME the following condition is different in the specs.
+ if (1 /* FIXME band is 2.4GHz */) {
+ b43_phy_set(dev, B43_NPHY_CLASSCTL,
+ B43_NPHY_CLASSCTL_CCKEN);
+diff --git a/drivers/net/wireless/b43/nphy.h b/drivers/net/wireless/b43/nphy.h
+index 5d95118..faf46b9 100644
+--- a/drivers/net/wireless/b43/nphy.h
++++ b/drivers/net/wireless/b43/nphy.h
+@@ -919,6 +919,10 @@
+
+ struct b43_wldev;
+
++
++#ifdef CONFIG_B43_NPHY
++/* N-PHY support enabled */
++
+ int b43_phy_initn(struct b43_wldev *dev);
+
+ void b43_nphy_radio_turn_on(struct b43_wldev *dev);
+@@ -929,4 +933,40 @@ int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel);
+ void b43_nphy_xmitpower(struct b43_wldev *dev);
+ void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna);
+
++
++#else /* CONFIG_B43_NPHY */
++/* N-PHY support disabled */
++
++
++static inline
++int b43_phy_initn(struct b43_wldev *dev)
++{
++ return -EOPNOTSUPP;
++}
++
++static inline
++void b43_nphy_radio_turn_on(struct b43_wldev *dev)
++{
++}
++static inline
++void b43_nphy_radio_turn_off(struct b43_wldev *dev)
++{
++}
++
++static inline
++int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel)
++{
++ return -ENOSYS;
++}
++
++static inline
++void b43_nphy_xmitpower(struct b43_wldev *dev)
++{
++}
++static inline
++void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
++{
++}
++
++#endif /* CONFIG_B43_NPHY */
+ #endif /* B43_NPHY_H_ */
+diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c
+index 371e4a1..b8aa163 100644
+--- a/drivers/net/wireless/b43/pcmcia.c
++++ b/drivers/net/wireless/b43/pcmcia.c
+@@ -43,14 +43,16 @@ MODULE_DEVICE_TABLE(pcmcia, b43_pcmcia_tbl);
+ #ifdef CONFIG_PM
+ static int b43_pcmcia_suspend(struct pcmcia_device *dev)
+ {
+- //TODO
+- return 0;
++ struct ssb_bus *ssb = dev->priv;
++
++ return ssb_bus_suspend(ssb);
+ }
+
+ static int b43_pcmcia_resume(struct pcmcia_device *dev)
+ {
+- //TODO
+- return 0;
++ struct ssb_bus *ssb = dev->priv;
++
++ return ssb_bus_resume(ssb);
+ }
+ #else /* CONFIG_PM */
+ # define b43_pcmcia_suspend NULL
+diff --git a/drivers/net/wireless/b43/phy.c b/drivers/net/wireless/b43/phy.c
+index 575c543..de024dc 100644
+--- a/drivers/net/wireless/b43/phy.c
++++ b/drivers/net/wireless/b43/phy.c
+@@ -2043,7 +2043,7 @@ int b43_phy_init(struct b43_wldev *dev)
+ void b43_set_rx_antenna(struct b43_wldev *dev, int antenna)
+ {
+ struct b43_phy *phy = &dev->phy;
+- u32 hf;
++ u64 hf;
+ u16 tmp;
+ int autodiv = 0;
+
+diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
+new file mode 100644
+index 0000000..fcacafb
+--- /dev/null
++++ b/drivers/net/wireless/b43/pio.c
+@@ -0,0 +1,842 @@
++/*
++
++ Broadcom B43 wireless driver
++
++ PIO data transfer
++
++ Copyright (c) 2005-2008 Michael Buesch <mb at bu3sch.de>
++
++ 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; see the file COPYING. If not, write to
++ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
++ Boston, MA 02110-1301, USA.
++
++*/
++
++#include "b43.h"
++#include "pio.h"
++#include "dma.h"
++#include "main.h"
++#include "xmit.h"
++
++#include <linux/delay.h>
++
++
++static void b43_pio_rx_work(struct work_struct *work);
++
++
++static u16 generate_cookie(struct b43_pio_txqueue *q,
++ struct b43_pio_txpacket *pack)
++{
++ u16 cookie;
++
++ /* Use the upper 4 bits of the cookie as
++ * PIO controller ID and store the packet index number
++ * in the lower 12 bits.
++ * Note that the cookie must never be 0, as this
++ * is a special value used in RX path.
++ * It can also not be 0xFFFF because that is special
++ * for multicast frames.
++ */
++ cookie = (((u16)q->index + 1) << 12);
++ cookie |= pack->index;
++
++ return cookie;
++}
++
++static
++struct b43_pio_txqueue * parse_cookie(struct b43_wldev *dev,
++ u16 cookie,
++ struct b43_pio_txpacket **pack)
++{
++ struct b43_pio *pio = &dev->pio;
++ struct b43_pio_txqueue *q = NULL;
++ unsigned int pack_index;
++
++ switch (cookie & 0xF000) {
++ case 0x1000:
++ q = pio->tx_queue_AC_BK;
++ break;
++ case 0x2000:
++ q = pio->tx_queue_AC_BE;
++ break;
++ case 0x3000:
++ q = pio->tx_queue_AC_VI;
++ break;
++ case 0x4000:
++ q = pio->tx_queue_AC_VO;
++ break;
++ case 0x5000:
++ q = pio->tx_queue_mcast;
++ break;
++ }
++ if (B43_WARN_ON(!q))
++ return NULL;
++ pack_index = (cookie & 0x0FFF);
++ if (B43_WARN_ON(pack_index >= ARRAY_SIZE(q->packets)))
++ return NULL;
++ *pack = &q->packets[pack_index];
++
++ return q;
++}
++
++static u16 index_to_pioqueue_base(struct b43_wldev *dev,
++ unsigned int index)
++{
++ static const u16 bases[] = {
++ B43_MMIO_PIO_BASE0,
++ B43_MMIO_PIO_BASE1,
++ B43_MMIO_PIO_BASE2,
++ B43_MMIO_PIO_BASE3,
++ B43_MMIO_PIO_BASE4,
++ B43_MMIO_PIO_BASE5,
++ B43_MMIO_PIO_BASE6,
++ B43_MMIO_PIO_BASE7,
++ };
++ static const u16 bases_rev11[] = {
++ B43_MMIO_PIO11_BASE0,
++ B43_MMIO_PIO11_BASE1,
++ B43_MMIO_PIO11_BASE2,
++ B43_MMIO_PIO11_BASE3,
++ B43_MMIO_PIO11_BASE4,
++ B43_MMIO_PIO11_BASE5,
++ };
++
++ if (dev->dev->id.revision >= 11) {
++ B43_WARN_ON(index >= ARRAY_SIZE(bases_rev11));
++ return bases_rev11[index];
++ }
++ B43_WARN_ON(index >= ARRAY_SIZE(bases));
++ return bases[index];
++}
++
++static u16 pio_txqueue_offset(struct b43_wldev *dev)
++{
++ if (dev->dev->id.revision >= 11)
++ return 0x18;
++ return 0;
++}
++
++static u16 pio_rxqueue_offset(struct b43_wldev *dev)
++{
++ if (dev->dev->id.revision >= 11)
++ return 0x38;
++ return 8;
++}
++
++static struct b43_pio_txqueue * b43_setup_pioqueue_tx(struct b43_wldev *dev,
++ unsigned int index)
++{
++ struct b43_pio_txqueue *q;
++ struct b43_pio_txpacket *p;
++ unsigned int i;
++
++ q = kzalloc(sizeof(*q), GFP_KERNEL);
++ if (!q)
++ return NULL;
++ spin_lock_init(&q->lock);
++ q->dev = dev;
++ q->rev = dev->dev->id.revision;
++ q->mmio_base = index_to_pioqueue_base(dev, index) +
++ pio_txqueue_offset(dev);
++ q->index = index;
++
++ q->free_packet_slots = B43_PIO_MAX_NR_TXPACKETS;
++ if (q->rev >= 8) {
++ q->buffer_size = 1920; //FIXME this constant is wrong.
++ } else {
++ q->buffer_size = b43_piotx_read16(q, B43_PIO_TXQBUFSIZE);
++ q->buffer_size -= 80;
++ }
++
++ INIT_LIST_HEAD(&q->packets_list);
++ for (i = 0; i < ARRAY_SIZE(q->packets); i++) {
++ p = &(q->packets[i]);
++ INIT_LIST_HEAD(&p->list);
++ p->index = i;
++ p->queue = q;
++ list_add(&p->list, &q->packets_list);
++ }
++
++ return q;
++}
++
++static struct b43_pio_rxqueue * b43_setup_pioqueue_rx(struct b43_wldev *dev,
++ unsigned int index)
++{
++ struct b43_pio_rxqueue *q;
++
++ q = kzalloc(sizeof(*q), GFP_KERNEL);
++ if (!q)
++ return NULL;
++ spin_lock_init(&q->lock);
++ q->dev = dev;
++ q->rev = dev->dev->id.revision;
++ q->mmio_base = index_to_pioqueue_base(dev, index) +
++ pio_rxqueue_offset(dev);
++ INIT_WORK(&q->rx_work, b43_pio_rx_work);
++
++ /* Enable Direct FIFO RX (PIO) on the engine. */
++ b43_dma_direct_fifo_rx(dev, index, 1);
++
++ return q;
++}
++
++static void b43_pio_cancel_tx_packets(struct b43_pio_txqueue *q)
++{
++ struct b43_pio_txpacket *pack;
++ unsigned int i;
++
++ for (i = 0; i < ARRAY_SIZE(q->packets); i++) {
++ pack = &(q->packets[i]);
++ if (pack->skb) {
++ dev_kfree_skb_any(pack->skb);
++ pack->skb = NULL;
++ }
++ }
++}
++
++static void b43_destroy_pioqueue_tx(struct b43_pio_txqueue *q,
++ const char *name)
++{
++ if (!q)
++ return;
++ b43_pio_cancel_tx_packets(q);
++ kfree(q);
++}
++
++static void b43_destroy_pioqueue_rx(struct b43_pio_rxqueue *q,
++ const char *name)
++{
++ if (!q)
++ return;
++ kfree(q);
++}
++
++#define destroy_queue_tx(pio, queue) do { \
++ b43_destroy_pioqueue_tx((pio)->queue, __stringify(queue)); \
++ (pio)->queue = NULL; \
++ } while (0)
++
++#define destroy_queue_rx(pio, queue) do { \
++ b43_destroy_pioqueue_rx((pio)->queue, __stringify(queue)); \
++ (pio)->queue = NULL; \
++ } while (0)
++
++void b43_pio_free(struct b43_wldev *dev)
++{
++ struct b43_pio *pio;
++
++ if (!b43_using_pio_transfers(dev))
++ return;
++ pio = &dev->pio;
++
++ destroy_queue_rx(pio, rx_queue);
++ destroy_queue_tx(pio, tx_queue_mcast);
++ destroy_queue_tx(pio, tx_queue_AC_VO);
++ destroy_queue_tx(pio, tx_queue_AC_VI);
++ destroy_queue_tx(pio, tx_queue_AC_BE);
++ destroy_queue_tx(pio, tx_queue_AC_BK);
++}
++
++void b43_pio_stop(struct b43_wldev *dev)
++{
++ if (!b43_using_pio_transfers(dev))
++ return;
++ cancel_work_sync(&dev->pio.rx_queue->rx_work);
++}
++
++int b43_pio_init(struct b43_wldev *dev)
++{
++ struct b43_pio *pio = &dev->pio;
++ int err = -ENOMEM;
++
++ b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
++ & ~B43_MACCTL_BE);
++ b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_RXPADOFF, 0);
++
++ pio->tx_queue_AC_BK = b43_setup_pioqueue_tx(dev, 0);
++ if (!pio->tx_queue_AC_BK)
++ goto out;
++
++ pio->tx_queue_AC_BE = b43_setup_pioqueue_tx(dev, 1);
++ if (!pio->tx_queue_AC_BE)
++ goto err_destroy_bk;
++
++ pio->tx_queue_AC_VI = b43_setup_pioqueue_tx(dev, 2);
++ if (!pio->tx_queue_AC_VI)
++ goto err_destroy_be;
++
++ pio->tx_queue_AC_VO = b43_setup_pioqueue_tx(dev, 3);
++ if (!pio->tx_queue_AC_VO)
++ goto err_destroy_vi;
++
++ pio->tx_queue_mcast = b43_setup_pioqueue_tx(dev, 4);
++ if (!pio->tx_queue_mcast)
++ goto err_destroy_vo;
++
++ pio->rx_queue = b43_setup_pioqueue_rx(dev, 0);
++ if (!pio->rx_queue)
++ goto err_destroy_mcast;
++
++ b43dbg(dev->wl, "PIO initialized\n");
++ err = 0;
++out:
++ return err;
++
++err_destroy_mcast:
++ destroy_queue_tx(pio, tx_queue_mcast);
++err_destroy_vo:
++ destroy_queue_tx(pio, tx_queue_AC_VO);
++err_destroy_vi:
++ destroy_queue_tx(pio, tx_queue_AC_VI);
++err_destroy_be:
++ destroy_queue_tx(pio, tx_queue_AC_BE);
++err_destroy_bk:
++ destroy_queue_tx(pio, tx_queue_AC_BK);
++ return err;
++}
++
++/* Static mapping of mac80211's queues (priorities) to b43 PIO queues. */
++static struct b43_pio_txqueue * select_queue_by_priority(struct b43_wldev *dev,
++ u8 queue_prio)
++{
++ struct b43_pio_txqueue *q;
++
++ if (b43_modparam_qos) {
++ /* 0 = highest priority */
++ switch (queue_prio) {
++ default:
++ B43_WARN_ON(1);
++ /* fallthrough */
++ case 0:
++ q = dev->pio.tx_queue_AC_VO;
++ break;
++ case 1:
++ q = dev->pio.tx_queue_AC_VI;
++ break;
++ case 2:
++ q = dev->pio.tx_queue_AC_BE;
++ break;
++ case 3:
++ q = dev->pio.tx_queue_AC_BK;
++ break;
++ }
++ } else
++ q = dev->pio.tx_queue_AC_BE;
++
++ return q;
++}
++
++static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
++ u16 ctl,
++ const void *_data,
++ unsigned int data_len)
++{
++ struct b43_wldev *dev = q->dev;
++ const u8 *data = _data;
++
++ ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI;
++ b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
++
++ ssb_block_write(dev->dev, data, (data_len & ~1),
++ q->mmio_base + B43_PIO_TXDATA,
++ sizeof(u16));
++ if (data_len & 1) {
++ /* Write the last byte. */
++ ctl &= ~B43_PIO_TXCTL_WRITEHI;
++ b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
++ b43_piotx_write16(q, B43_PIO_TXDATA, data[data_len - 1]);
++ }
++
++ return ctl;
++}
++
++static void pio_tx_frame_2byte_queue(struct b43_pio_txpacket *pack,
++ const u8 *hdr, unsigned int hdrlen)
++{
++ struct b43_pio_txqueue *q = pack->queue;
++ const char *frame = pack->skb->data;
++ unsigned int frame_len = pack->skb->len;
++ u16 ctl;
++
++ ctl = b43_piotx_read16(q, B43_PIO_TXCTL);
++ ctl |= B43_PIO_TXCTL_FREADY;
++ ctl &= ~B43_PIO_TXCTL_EOF;
++
++ /* Transfer the header data. */
++ ctl = tx_write_2byte_queue(q, ctl, hdr, hdrlen);
++ /* Transfer the frame data. */
++ ctl = tx_write_2byte_queue(q, ctl, frame, frame_len);
++
++ ctl |= B43_PIO_TXCTL_EOF;
++ b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
++}
++
++static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
++ u32 ctl,
++ const void *_data,
++ unsigned int data_len)
++{
++ struct b43_wldev *dev = q->dev;
++ const u8 *data = _data;
++
++ ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 |
++ B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31;
++ b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
++
++ ssb_block_write(dev->dev, data, (data_len & ~3),
++ q->mmio_base + B43_PIO8_TXDATA,
++ sizeof(u32));
++ if (data_len & 3) {
++ u32 value = 0;
++
++ /* Write the last few bytes. */
++ ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 |
++ B43_PIO8_TXCTL_24_31);
++ data = &(data[data_len - 1]);
++ switch (data_len & 3) {
++ case 3:
++ ctl |= B43_PIO8_TXCTL_16_23;
++ value |= (u32)(*data) << 16;
++ data--;
++ case 2:
++ ctl |= B43_PIO8_TXCTL_8_15;
++ value |= (u32)(*data) << 8;
++ data--;
++ case 1:
++ value |= (u32)(*data);
++ }
++ b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
++ b43_piotx_write32(q, B43_PIO8_TXDATA, value);
++ }
++
++ return ctl;
++}
++
++static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack,
++ const u8 *hdr, unsigned int hdrlen)
++{
++ struct b43_pio_txqueue *q = pack->queue;
++ const char *frame = pack->skb->data;
++ unsigned int frame_len = pack->skb->len;
++ u32 ctl;
++
++ ctl = b43_piotx_read32(q, B43_PIO8_TXCTL);
++ ctl |= B43_PIO8_TXCTL_FREADY;
++ ctl &= ~B43_PIO8_TXCTL_EOF;
++
++ /* Transfer the header data. */
++ ctl = tx_write_4byte_queue(q, ctl, hdr, hdrlen);
++ /* Transfer the frame data. */
++ ctl = tx_write_4byte_queue(q, ctl, frame, frame_len);
++
++ ctl |= B43_PIO8_TXCTL_EOF;
++ b43_piotx_write32(q, B43_PIO_TXCTL, ctl);
++}
++
++static int pio_tx_frame(struct b43_pio_txqueue *q,
++ struct sk_buff *skb,
++ struct ieee80211_tx_control *ctl)
++{
++ struct b43_pio_txpacket *pack;
++ struct b43_txhdr txhdr;
++ u16 cookie;
++ int err;
++ unsigned int hdrlen;
++
++ B43_WARN_ON(list_empty(&q->packets_list));
++ pack = list_entry(q->packets_list.next,
++ struct b43_pio_txpacket, list);
++ memset(&pack->txstat, 0, sizeof(pack->txstat));
++ memcpy(&pack->txstat.control, ctl, sizeof(*ctl));
++
++ cookie = generate_cookie(q, pack);
++ hdrlen = b43_txhdr_size(q->dev);
++ err = b43_generate_txhdr(q->dev, (u8 *)&txhdr, skb->data,
++ skb->len, ctl, cookie);
++ if (err)
++ return err;
++
++ if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) {
++ /* Tell the firmware about the cookie of the last
++ * mcast frame, so it can clear the more-data bit in it. */
++ b43_shm_write16(q->dev, B43_SHM_SHARED,
++ B43_SHM_SH_MCASTCOOKIE, cookie);
++ }
++
++ pack->skb = skb;
++ if (q->rev >= 8)
++ pio_tx_frame_4byte_queue(pack, (const u8 *)&txhdr, hdrlen);
++ else
++ pio_tx_frame_2byte_queue(pack, (const u8 *)&txhdr, hdrlen);
++
++ /* Remove it from the list of available packet slots.
++ * It will be put back when we receive the status report. */
++ list_del(&pack->list);
++
++ /* Update the queue statistics. */
++ q->buffer_used += roundup(skb->len + hdrlen, 4);
++ q->free_packet_slots -= 1;
++
++ return 0;
++}
++
++int b43_pio_tx(struct b43_wldev *dev,
++ struct sk_buff *skb, struct ieee80211_tx_control *ctl)
++{
++ struct b43_pio_txqueue *q;
++ struct ieee80211_hdr *hdr;
++ unsigned long flags;
++ unsigned int hdrlen, total_len;
++ int err = 0;
++
++ hdr = (struct ieee80211_hdr *)skb->data;
++ if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) {
++ /* The multicast queue will be sent after the DTIM. */
++ q = dev->pio.tx_queue_mcast;
++ /* Set the frame More-Data bit. Ucode will clear it
++ * for us on the last frame. */
++ hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
++ } else {
++ /* Decide by priority where to put this frame. */
++ q = select_queue_by_priority(dev, ctl->queue);
++ }
++
++ spin_lock_irqsave(&q->lock, flags);
++
++ hdrlen = b43_txhdr_size(dev);
++ total_len = roundup(skb->len + hdrlen, 4);
++
++ if (unlikely(total_len > q->buffer_size)) {
++ err = -ENOBUFS;
++ b43dbg(dev->wl, "PIO: TX packet longer than queue.\n");
++ goto out_unlock;
++ }
++ if (unlikely(q->free_packet_slots == 0)) {
++ err = -ENOBUFS;
++ b43warn(dev->wl, "PIO: TX packet overflow.\n");
++ goto out_unlock;
++ }
++ B43_WARN_ON(q->buffer_used > q->buffer_size);
++
++ if (total_len > (q->buffer_size - q->buffer_used)) {
++ /* Not enough memory on the queue. */
++ err = -EBUSY;
++ ieee80211_stop_queue(dev->wl->hw, ctl->queue);
++ q->stopped = 1;
++ goto out_unlock;
++ }
++
++ /* Assign the queue number to the ring (if not already done before)
++ * so TX status handling can use it. The mac80211-queue to b43-queue
++ * mapping is static, so we don't need to store it per frame. */
++ q->queue_prio = ctl->queue;
++
++ err = pio_tx_frame(q, skb, ctl);
++ if (unlikely(err == -ENOKEY)) {
++ /* Drop this packet, as we don't have the encryption key
++ * anymore and must not transmit it unencrypted. */
++ dev_kfree_skb_any(skb);
++ err = 0;
++ goto out_unlock;
++ }
++ if (unlikely(err)) {
++ b43err(dev->wl, "PIO transmission failure\n");
++ goto out_unlock;
++ }
++ q->nr_tx_packets++;
++
++ B43_WARN_ON(q->buffer_used > q->buffer_size);
++ if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) ||
++ (q->free_packet_slots == 0)) {
++ /* The queue is full. */
++ ieee80211_stop_queue(dev->wl->hw, ctl->queue);
++ q->stopped = 1;
++ }
++
++out_unlock:
++ spin_unlock_irqrestore(&q->lock, flags);
++
++ return err;
++}
++
++/* Called with IRQs disabled. */
++void b43_pio_handle_txstatus(struct b43_wldev *dev,
++ const struct b43_txstatus *status)
++{
++ struct b43_pio_txqueue *q;
++ struct b43_pio_txpacket *pack = NULL;
++ unsigned int total_len;
++
++ q = parse_cookie(dev, status->cookie, &pack);
++ if (unlikely(!q))
++ return;
++ B43_WARN_ON(!pack);
++
++ spin_lock(&q->lock); /* IRQs are already disabled. */
++
++ b43_fill_txstatus_report(&(pack->txstat), status);
++
++ total_len = pack->skb->len + b43_txhdr_size(dev);
++ total_len = roundup(total_len, 4);
++ q->buffer_used -= total_len;
++ q->free_packet_slots += 1;
++
++ ieee80211_tx_status_irqsafe(dev->wl->hw, pack->skb,
++ &(pack->txstat));
++ pack->skb = NULL;
++ list_add(&pack->list, &q->packets_list);
++
++ if (q->stopped) {
++ ieee80211_wake_queue(dev->wl->hw, q->queue_prio);
++ q->stopped = 0;
++ }
++
++ spin_unlock(&q->lock);
++}
++
++void b43_pio_get_tx_stats(struct b43_wldev *dev,
++ struct ieee80211_tx_queue_stats *stats)
++{
++ const int nr_queues = dev->wl->hw->queues;
++ struct b43_pio_txqueue *q;
++ struct ieee80211_tx_queue_stats_data *data;
++ unsigned long flags;
++ int i;
++
++ for (i = 0; i < nr_queues; i++) {
++ data = &(stats->data[i]);
++ q = select_queue_by_priority(dev, i);
++
++ spin_lock_irqsave(&q->lock, flags);
++ data->len = B43_PIO_MAX_NR_TXPACKETS - q->free_packet_slots;
++ data->limit = B43_PIO_MAX_NR_TXPACKETS;
++ data->count = q->nr_tx_packets;
++ spin_unlock_irqrestore(&q->lock, flags);
++ }
++}
++
++/* Returns whether we should fetch another frame. */
++static bool pio_rx_frame(struct b43_pio_rxqueue *q)
++{
++ struct b43_wldev *dev = q->dev;
++ struct b43_rxhdr_fw4 rxhdr;
++ u16 len;
++ u32 macstat;
++ unsigned int i, padding;
++ struct sk_buff *skb;
++ const char *err_msg = NULL;
++
++ memset(&rxhdr, 0, sizeof(rxhdr));
++
++ /* Check if we have data and wait for it to get ready. */
++ if (q->rev >= 8) {
++ u32 ctl;
++
++ ctl = b43_piorx_read32(q, B43_PIO8_RXCTL);
++ if (!(ctl & B43_PIO8_RXCTL_FRAMERDY))
++ return 0;
++ b43_piorx_write32(q, B43_PIO8_RXCTL,
++ B43_PIO8_RXCTL_FRAMERDY);
++ for (i = 0; i < 10; i++) {
++ ctl = b43_piorx_read32(q, B43_PIO8_RXCTL);
++ if (ctl & B43_PIO8_RXCTL_DATARDY)
++ goto data_ready;
++ udelay(10);
++ }
++ } else {
++ u16 ctl;
++
++ ctl = b43_piorx_read16(q, B43_PIO_RXCTL);
++ if (!(ctl & B43_PIO_RXCTL_FRAMERDY))
++ return 0;
++ b43_piorx_write16(q, B43_PIO_RXCTL,
++ B43_PIO_RXCTL_FRAMERDY);
++ for (i = 0; i < 10; i++) {
++ ctl = b43_piorx_read16(q, B43_PIO_RXCTL);
++ if (ctl & B43_PIO_RXCTL_DATARDY)
++ goto data_ready;
++ udelay(10);
++ }
++ }
++ b43dbg(q->dev->wl, "PIO RX timed out\n");
++ return 1;
++data_ready:
++
++ /* Get the preamble (RX header) */
++ if (q->rev >= 8) {
++ ssb_block_read(dev->dev, &rxhdr, sizeof(rxhdr),
++ q->mmio_base + B43_PIO8_RXDATA,
++ sizeof(u32));
++ } else {
++ ssb_block_read(dev->dev, &rxhdr, sizeof(rxhdr),
++ q->mmio_base + B43_PIO_RXDATA,
++ sizeof(u16));
++ }
++ /* Sanity checks. */
++ len = le16_to_cpu(rxhdr.frame_len);
++ if (unlikely(len > 0x700)) {
++ err_msg = "len > 0x700";
++ goto rx_error;
++ }
++ if (unlikely(len == 0)) {
++ err_msg = "len == 0";
++ goto rx_error;
++ }
++
++ macstat = le32_to_cpu(rxhdr.mac_status);
++ if (macstat & B43_RX_MAC_FCSERR) {
++ if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) {
++ /* Drop frames with failed FCS. */
++ err_msg = "Frame FCS error";
++ goto rx_error;
++ }
++ }
++
++ /* We always pad 2 bytes, as that's what upstream code expects
++ * due to the RX-header being 30 bytes. In case the frame is
++ * unaligned, we pad another 2 bytes. */
++ padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0;
++ skb = dev_alloc_skb(len + padding + 2);
++ if (unlikely(!skb)) {
++ err_msg = "Out of memory";
++ goto rx_error;
++ }
++ skb_reserve(skb, 2);
++ skb_put(skb, len + padding);
++ if (q->rev >= 8) {
++ ssb_block_read(dev->dev, skb->data + padding, (len & ~3),
++ q->mmio_base + B43_PIO8_RXDATA,
++ sizeof(u32));
++ if (len & 3) {
++ u32 value;
++ char *data;
++
++ /* Read the last few bytes. */
++ value = b43_piorx_read32(q, B43_PIO8_RXDATA);
++ data = &(skb->data[len + padding - 1]);
++ switch (len & 3) {
++ case 3:
++ *data = (value >> 16);
++ data--;
++ case 2:
++ *data = (value >> 8);
++ data--;
++ case 1:
++ *data = value;
++ }
++ }
++ } else {
++ ssb_block_read(dev->dev, skb->data + padding, (len & ~1),
++ q->mmio_base + B43_PIO_RXDATA,
++ sizeof(u16));
++ if (len & 1) {
++ u16 value;
++
++ /* Read the last byte. */
++ value = b43_piorx_read16(q, B43_PIO_RXDATA);
++ skb->data[len + padding - 1] = value;
++ }
++ }
++
++ b43_rx(q->dev, skb, &rxhdr);
++
++ return 1;
++
++rx_error:
++ if (err_msg)
++ b43dbg(q->dev->wl, "PIO RX error: %s\n", err_msg);
++ b43_piorx_write16(q, B43_PIO_RXCTL, B43_PIO_RXCTL_DATARDY);
++ return 1;
++}
++
++/* RX workqueue. We can sleep, yay! */
++static void b43_pio_rx_work(struct work_struct *work)
++{
++ struct b43_pio_rxqueue *q = container_of(work, struct b43_pio_rxqueue,
++ rx_work);
++ unsigned int budget = 50;
++ bool stop;
++
++ do {
++ spin_lock_irq(&q->lock);
++ stop = (pio_rx_frame(q) == 0);
++ spin_unlock_irq(&q->lock);
++ cond_resched();
++ if (stop)
++ break;
++ } while (--budget);
++}
++
++/* Called with IRQs disabled. */
++void b43_pio_rx(struct b43_pio_rxqueue *q)
++{
++ /* Due to latency issues we must run the RX path in
++ * a workqueue to be able to schedule between packets. */
++ queue_work(q->dev->wl->hw->workqueue, &q->rx_work);
++}
++
++static void b43_pio_tx_suspend_queue(struct b43_pio_txqueue *q)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&q->lock, flags);
++ if (q->rev >= 8) {
++ b43_piotx_write32(q, B43_PIO8_TXCTL,
++ b43_piotx_read32(q, B43_PIO8_TXCTL)
++ | B43_PIO8_TXCTL_SUSPREQ);
++ } else {
++ b43_piotx_write16(q, B43_PIO_TXCTL,
++ b43_piotx_read16(q, B43_PIO_TXCTL)
++ | B43_PIO_TXCTL_SUSPREQ);
++ }
++ spin_unlock_irqrestore(&q->lock, flags);
++}
++
++static void b43_pio_tx_resume_queue(struct b43_pio_txqueue *q)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&q->lock, flags);
++ if (q->rev >= 8) {
++ b43_piotx_write32(q, B43_PIO8_TXCTL,
++ b43_piotx_read32(q, B43_PIO8_TXCTL)
++ & ~B43_PIO8_TXCTL_SUSPREQ);
++ } else {
++ b43_piotx_write16(q, B43_PIO_TXCTL,
++ b43_piotx_read16(q, B43_PIO_TXCTL)
++ & ~B43_PIO_TXCTL_SUSPREQ);
++ }
++ spin_unlock_irqrestore(&q->lock, flags);
++}
++
++void b43_pio_tx_suspend(struct b43_wldev *dev)
++{
++ b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
++ b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_BK);
++ b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_BE);
++ b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_VI);
++ b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_VO);
++ b43_pio_tx_suspend_queue(dev->pio.tx_queue_mcast);
++}
++
++void b43_pio_tx_resume(struct b43_wldev *dev)
++{
++ b43_pio_tx_resume_queue(dev->pio.tx_queue_mcast);
++ b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_VO);
++ b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_VI);
++ b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_BE);
++ b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_BK);
++ b43_power_saving_ctl_bits(dev, 0);
++}
+diff --git a/drivers/net/wireless/b43/pio.h b/drivers/net/wireless/b43/pio.h
+new file mode 100644
+index 0000000..e2ec676
+--- /dev/null
++++ b/drivers/net/wireless/b43/pio.h
+@@ -0,0 +1,220 @@
++#ifndef B43_PIO_H_
++#define B43_PIO_H_
++
++#include "b43.h"
++
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/list.h>
++#include <linux/skbuff.h>
++
++
++/*** Registers for PIO queues up to revision 7. ***/
++/* TX queue. */
++#define B43_PIO_TXCTL 0x00
++#define B43_PIO_TXCTL_WRITELO 0x0001
++#define B43_PIO_TXCTL_WRITEHI 0x0002
++#define B43_PIO_TXCTL_EOF 0x0004
++#define B43_PIO_TXCTL_FREADY 0x0008
++#define B43_PIO_TXCTL_FLUSHREQ 0x0020
++#define B43_PIO_TXCTL_FLUSHPEND 0x0040
++#define B43_PIO_TXCTL_SUSPREQ 0x0080
++#define B43_PIO_TXCTL_QSUSP 0x0100
++#define B43_PIO_TXCTL_COMMCNT 0xFC00
++#define B43_PIO_TXCTL_COMMCNT_SHIFT 10
++#define B43_PIO_TXDATA 0x02
++#define B43_PIO_TXQBUFSIZE 0x04
++/* RX queue. */
++#define B43_PIO_RXCTL 0x00
++#define B43_PIO_RXCTL_FRAMERDY 0x0001
++#define B43_PIO_RXCTL_DATARDY 0x0002
++#define B43_PIO_RXDATA 0x02
++
++/*** Registers for PIO queues revision 8 and later. ***/
++/* TX queue */
++#define B43_PIO8_TXCTL 0x00
++#define B43_PIO8_TXCTL_0_7 0x00000001
++#define B43_PIO8_TXCTL_8_15 0x00000002
++#define B43_PIO8_TXCTL_16_23 0x00000004
++#define B43_PIO8_TXCTL_24_31 0x00000008
++#define B43_PIO8_TXCTL_EOF 0x00000010
++#define B43_PIO8_TXCTL_FREADY 0x00000080
++#define B43_PIO8_TXCTL_SUSPREQ 0x00000100
++#define B43_PIO8_TXCTL_QSUSP 0x00000200
++#define B43_PIO8_TXCTL_FLUSHREQ 0x00000400
++#define B43_PIO8_TXCTL_FLUSHPEND 0x00000800
++#define B43_PIO8_TXDATA 0x04
++/* RX queue */
++#define B43_PIO8_RXCTL 0x00
++#define B43_PIO8_RXCTL_FRAMERDY 0x00000001
++#define B43_PIO8_RXCTL_DATARDY 0x00000002
++#define B43_PIO8_RXDATA 0x04
++
++
++/* The maximum number of TX-packets the HW can handle. */
++#define B43_PIO_MAX_NR_TXPACKETS 32
++
++
++#ifdef CONFIG_B43_PIO
++
++struct b43_pio_txpacket {
++ /* Pointer to the TX queue we belong to. */
++ struct b43_pio_txqueue *queue;
++ /* The TX data packet. */
++ struct sk_buff *skb;
++ /* The status meta data. */
++ struct ieee80211_tx_status txstat;
++ /* Index in the (struct b43_pio_txqueue)->packets array. */
++ u8 index;
++
++ struct list_head list;
++};
++
++struct b43_pio_txqueue {
++ struct b43_wldev *dev;
++ spinlock_t lock;
++ u16 mmio_base;
++
++ /* The device queue buffer size in bytes. */
++ u16 buffer_size;
++ /* The number of used bytes in the device queue buffer. */
++ u16 buffer_used;
++ /* The number of packets that can still get queued.
++ * This is decremented on queueing a packet and incremented
++ * after receiving the transmit status. */
++ u16 free_packet_slots;
++
++ /* True, if the mac80211 queue was stopped due to overflow at TX. */
++ bool stopped;
++ /* Our b43 queue index number */
++ u8 index;
++ /* The mac80211 QoS queue priority. */
++ u8 queue_prio;
++
++ /* Buffer for TX packet meta data. */
++ struct b43_pio_txpacket packets[B43_PIO_MAX_NR_TXPACKETS];
++ struct list_head packets_list;
++
++ /* Total number of transmitted packets. */
++ unsigned int nr_tx_packets;
++
++ /* Shortcut to the 802.11 core revision. This is to
++ * avoid horrible pointer dereferencing in the fastpaths. */
++ u8 rev;
++};
++
++struct b43_pio_rxqueue {
++ struct b43_wldev *dev;
++ spinlock_t lock;
++ u16 mmio_base;
++
++ /* Work to reduce latency issues on RX. */
++ struct work_struct rx_work;
++
++ /* Shortcut to the 802.11 core revision. This is to
++ * avoid horrible pointer dereferencing in the fastpaths. */
++ u8 rev;
++};
++
++
++static inline u16 b43_piotx_read16(struct b43_pio_txqueue *q, u16 offset)
++{
++ return b43_read16(q->dev, q->mmio_base + offset);
++}
++
++static inline u32 b43_piotx_read32(struct b43_pio_txqueue *q, u16 offset)
++{
++ return b43_read32(q->dev, q->mmio_base + offset);
++}
++
++static inline void b43_piotx_write16(struct b43_pio_txqueue *q,
++ u16 offset, u16 value)
++{
++ b43_write16(q->dev, q->mmio_base + offset, value);
++}
++
++static inline void b43_piotx_write32(struct b43_pio_txqueue *q,
++ u16 offset, u32 value)
++{
++ b43_write32(q->dev, q->mmio_base + offset, value);
++}
++
++
++static inline u16 b43_piorx_read16(struct b43_pio_rxqueue *q, u16 offset)
++{
++ return b43_read16(q->dev, q->mmio_base + offset);
++}
++
++static inline u32 b43_piorx_read32(struct b43_pio_rxqueue *q, u16 offset)
++{
++ return b43_read32(q->dev, q->mmio_base + offset);
++}
++
++static inline void b43_piorx_write16(struct b43_pio_rxqueue *q,
++ u16 offset, u16 value)
++{
++ b43_write16(q->dev, q->mmio_base + offset, value);
++}
++
++static inline void b43_piorx_write32(struct b43_pio_rxqueue *q,
++ u16 offset, u32 value)
++{
++ b43_write32(q->dev, q->mmio_base + offset, value);
++}
++
++
++int b43_pio_init(struct b43_wldev *dev);
++void b43_pio_stop(struct b43_wldev *dev);
++void b43_pio_free(struct b43_wldev *dev);
++
++int b43_pio_tx(struct b43_wldev *dev,
++ struct sk_buff *skb, struct ieee80211_tx_control *ctl);
++void b43_pio_handle_txstatus(struct b43_wldev *dev,
++ const struct b43_txstatus *status);
++void b43_pio_get_tx_stats(struct b43_wldev *dev,
++ struct ieee80211_tx_queue_stats *stats);
++void b43_pio_rx(struct b43_pio_rxqueue *q);
++
++void b43_pio_tx_suspend(struct b43_wldev *dev);
++void b43_pio_tx_resume(struct b43_wldev *dev);
++
++
++#else /* CONFIG_B43_PIO */
++
++
++static inline int b43_pio_init(struct b43_wldev *dev)
++{
++ return 0;
++}
++static inline void b43_pio_free(struct b43_wldev *dev)
++{
++}
++static inline void b43_pio_stop(struct b43_wldev *dev)
++{
++}
++static inline int b43_pio_tx(struct b43_wldev *dev,
++ struct sk_buff *skb,
++ struct ieee80211_tx_control *ctl)
++{
++ return 0;
++}
++static inline void b43_pio_handle_txstatus(struct b43_wldev *dev,
++ const struct b43_txstatus *status)
++{
++}
++static inline void b43_pio_get_tx_stats(struct b43_wldev *dev,
++ struct ieee80211_tx_queue_stats *stats)
++{
++}
++static inline void b43_pio_rx(struct b43_pio_rxqueue *q)
++{
++}
++static inline void b43_pio_tx_suspend(struct b43_wldev *dev)
++{
++}
++static inline void b43_pio_tx_resume(struct b43_wldev *dev)
++{
++}
++
++#endif /* CONFIG_B43_PIO */
++#endif /* B43_PIO_H_ */
+diff --git a/drivers/net/wireless/b43/sysfs.c b/drivers/net/wireless/b43/sysfs.c
+index f4faff6..275095b 100644
+--- a/drivers/net/wireless/b43/sysfs.c
++++ b/drivers/net/wireless/b43/sysfs.c
+@@ -47,29 +47,6 @@ static int get_integer(const char *buf, size_t count)
+ return ret;
+ }
+
+-static int get_boolean(const char *buf, size_t count)
+-{
+- if (count != 0) {
+- if (buf[0] == '1')
+- return 1;
+- if (buf[0] == '0')
+- return 0;
+- if (count >= 4 && memcmp(buf, "true", 4) == 0)
+- return 1;
+- if (count >= 5 && memcmp(buf, "false", 5) == 0)
+- return 0;
+- if (count >= 3 && memcmp(buf, "yes", 3) == 0)
+- return 1;
+- if (count >= 2 && memcmp(buf, "no", 2) == 0)
+- return 0;
+- if (count >= 2 && memcmp(buf, "on", 2) == 0)
+- return 1;
+- if (count >= 3 && memcmp(buf, "off", 3) == 0)
+- return 0;
+- }
+- return -EINVAL;
+-}
+-
+ static ssize_t b43_attr_interfmode_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+@@ -155,82 +132,18 @@ static ssize_t b43_attr_interfmode_store(struct device *dev,
+ static DEVICE_ATTR(interference, 0644,
+ b43_attr_interfmode_show, b43_attr_interfmode_store);
+
+-static ssize_t b43_attr_preamble_show(struct device *dev,
+- struct device_attribute *attr, char *buf)
+-{
+- struct b43_wldev *wldev = dev_to_b43_wldev(dev);
+- ssize_t count;
+-
+- if (!capable(CAP_NET_ADMIN))
+- return -EPERM;
+-
+- mutex_lock(&wldev->wl->mutex);
+-
+- if (wldev->short_preamble)
+- count =
+- snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n");
+- else
+- count =
+- snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n");
+-
+- mutex_unlock(&wldev->wl->mutex);
+-
+- return count;
+-}
+-
+-static ssize_t b43_attr_preamble_store(struct device *dev,
+- struct device_attribute *attr,
+- const char *buf, size_t count)
+-{
+- struct b43_wldev *wldev = dev_to_b43_wldev(dev);
+- unsigned long flags;
+- int value;
+-
+- if (!capable(CAP_NET_ADMIN))
+- return -EPERM;
+-
+- value = get_boolean(buf, count);
+- if (value < 0)
+- return value;
+- mutex_lock(&wldev->wl->mutex);
+- spin_lock_irqsave(&wldev->wl->irq_lock, flags);
+-
+- wldev->short_preamble = !!value;
+-
+- spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
+- mutex_unlock(&wldev->wl->mutex);
+-
+- return count;
+-}
+-
+-static DEVICE_ATTR(shortpreamble, 0644,
+- b43_attr_preamble_show, b43_attr_preamble_store);
+-
+ int b43_sysfs_register(struct b43_wldev *wldev)
+ {
+ struct device *dev = wldev->dev->dev;
+- int err;
+
+ B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED);
+
+- err = device_create_file(dev, &dev_attr_interference);
+- if (err)
+- goto out;
+- err = device_create_file(dev, &dev_attr_shortpreamble);
+- if (err)
+- goto err_remove_interfmode;
+-
+- out:
+- return err;
+- err_remove_interfmode:
+- device_remove_file(dev, &dev_attr_interference);
+- goto out;
++ return device_create_file(dev, &dev_attr_interference);
+ }
+
+ void b43_sysfs_unregister(struct b43_wldev *wldev)
+ {
+ struct device *dev = wldev->dev->dev;
+
+- device_remove_file(dev, &dev_attr_shortpreamble);
+ device_remove_file(dev, &dev_attr_interference);
+ }
+diff --git a/drivers/net/wireless/b43/wa.c b/drivers/net/wireless/b43/wa.c
+index e632125..daa9421 100644
+--- a/drivers/net/wireless/b43/wa.c
++++ b/drivers/net/wireless/b43/wa.c
+@@ -204,42 +204,43 @@ static void b43_wa_rt(struct b43_wldev *dev) /* Rotor table */
+ b43_ofdmtab_write32(dev, B43_OFDMTAB_ROTOR, i, b43_tab_rotor[i]);
+ }
+
++static void b43_write_null_nst(struct b43_wldev *dev)
++{
++ int i;
++
++ for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
++ b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE, i, 0);
++}
++
++static void b43_write_nst(struct b43_wldev *dev, const u16 *nst)
++{
++ int i;
++
++ for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
++ b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE, i, nst[i]);
++}
++
+ static void b43_wa_nst(struct b43_wldev *dev) /* Noise scale table */
+ {
+ struct b43_phy *phy = &dev->phy;
+- int i;
+
+ if (phy->type == B43_PHYTYPE_A) {
+ if (phy->rev <= 1)
+- for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
+- b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
+- i, 0);
++ b43_write_null_nst(dev);
+ else if (phy->rev == 2)
+- for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
+- b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
+- i, b43_tab_noisescalea2[i]);
++ b43_write_nst(dev, b43_tab_noisescalea2);
+ else if (phy->rev == 3)
+- for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
+- b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
+- i, b43_tab_noisescalea3[i]);
++ b43_write_nst(dev, b43_tab_noisescalea3);
+ else
+- for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
+- b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
+- i, b43_tab_noisescaleg3[i]);
++ b43_write_nst(dev, b43_tab_noisescaleg3);
+ } else {
+ if (phy->rev >= 6) {
+ if (b43_phy_read(dev, B43_PHY_ENCORE) & B43_PHY_ENCORE_EN)
+- for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
+- b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
+- i, b43_tab_noisescaleg3[i]);
++ b43_write_nst(dev, b43_tab_noisescaleg3);
+ else
+- for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
+- b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
+- i, b43_tab_noisescaleg2[i]);
++ b43_write_nst(dev, b43_tab_noisescaleg2);
+ } else {
+- for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
+- b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
+- i, b43_tab_noisescaleg1[i]);
++ b43_write_nst(dev, b43_tab_noisescaleg1);
+ }
+ }
+ }
+diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
+index 7caa26e..19aefbf 100644
+--- a/drivers/net/wireless/b43/xmit.c
++++ b/drivers/net/wireless/b43/xmit.c
+@@ -30,48 +30,51 @@
+ #include "xmit.h"
+ #include "phy.h"
+ #include "dma.h"
++#include "pio.h"
+
+
+-/* Extract the bitrate out of a CCK PLCP header. */
+-static u8 b43_plcp_get_bitrate_cck(struct b43_plcp_hdr6 *plcp)
++/* Extract the bitrate index out of a CCK PLCP header. */
++static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp)
+ {
+ switch (plcp->raw[0]) {
+ case 0x0A:
+- return B43_CCK_RATE_1MB;
++ return 0;
+ case 0x14:
+- return B43_CCK_RATE_2MB;
++ return 1;
+ case 0x37:
+- return B43_CCK_RATE_5MB;
++ return 2;
+ case 0x6E:
+- return B43_CCK_RATE_11MB;
++ return 3;
+ }
+ B43_WARN_ON(1);
+- return 0;
++ return -1;
+ }
+
+-/* Extract the bitrate out of an OFDM PLCP header. */
+-static u8 b43_plcp_get_bitrate_ofdm(struct b43_plcp_hdr6 *plcp)
++/* Extract the bitrate index out of an OFDM PLCP header. */
++static u8 b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy)
+ {
++ int base = aphy ? 0 : 4;
++
+ switch (plcp->raw[0] & 0xF) {
+ case 0xB:
+- return B43_OFDM_RATE_6MB;
++ return base + 0;
+ case 0xF:
+- return B43_OFDM_RATE_9MB;
++ return base + 1;
+ case 0xA:
+- return B43_OFDM_RATE_12MB;
++ return base + 2;
+ case 0xE:
+- return B43_OFDM_RATE_18MB;
++ return base + 3;
+ case 0x9:
+- return B43_OFDM_RATE_24MB;
++ return base + 4;
+ case 0xD:
+- return B43_OFDM_RATE_36MB;
++ return base + 5;
+ case 0x8:
+- return B43_OFDM_RATE_48MB;
++ return base + 6;
+ case 0xC:
+- return B43_OFDM_RATE_54MB;
++ return base + 7;
+ }
+ B43_WARN_ON(1);
+- return 0;
++ return -1;
+ }
+
+ u8 b43_plcp_get_ratecode_cck(const u8 bitrate)
+@@ -191,6 +194,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
+ (const struct ieee80211_hdr *)fragment_data;
+ int use_encryption = (!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT));
+ u16 fctl = le16_to_cpu(wlhdr->frame_control);
++ struct ieee80211_rate *fbrate;
+ u8 rate, rate_fb;
+ int rate_ofdm, rate_fb_ofdm;
+ unsigned int plcp_fragment_len;
+@@ -200,9 +204,11 @@ int b43_generate_txhdr(struct b43_wldev *dev,
+
+ memset(txhdr, 0, sizeof(*txhdr));
+
+- rate = txctl->tx_rate;
++ WARN_ON(!txctl->tx_rate);
++ rate = txctl->tx_rate ? txctl->tx_rate->hw_value : B43_CCK_RATE_1MB;
+ rate_ofdm = b43_is_ofdm_rate(rate);
+- rate_fb = (txctl->alt_retry_rate == -1) ? rate : txctl->alt_retry_rate;
++ fbrate = txctl->alt_retry_rate ? : txctl->tx_rate;
++ rate_fb = fbrate->hw_value;
+ rate_fb_ofdm = b43_is_ofdm_rate(rate_fb);
+
+ if (rate_ofdm)
+@@ -221,11 +227,10 @@ int b43_generate_txhdr(struct b43_wldev *dev,
+ * use the original dur_id field. */
+ txhdr->dur_fb = wlhdr->duration_id;
+ } else {
+- int fbrate_base100kbps = B43_RATE_TO_BASE100KBPS(rate_fb);
+ txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw,
+ txctl->vif,
+ fragment_len,
+- fbrate_base100kbps);
++ fbrate);
+ }
+
+ plcp_fragment_len = fragment_len + FCS_LEN;
+@@ -287,7 +292,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
+ phy_ctl |= B43_TXH_PHY_ENC_OFDM;
+ else
+ phy_ctl |= B43_TXH_PHY_ENC_CCK;
+- if (dev->short_preamble)
++ if (txctl->flags & IEEE80211_TXCTL_SHORT_PREAMBLE)
+ phy_ctl |= B43_TXH_PHY_SHORTPRMBL;
+
+ switch (b43_ieee80211_antenna_sanitize(dev, txctl->antenna_sel_tx)) {
+@@ -332,7 +337,8 @@ int b43_generate_txhdr(struct b43_wldev *dev,
+ int rts_rate_ofdm, rts_rate_fb_ofdm;
+ struct b43_plcp_hdr6 *plcp;
+
+- rts_rate = txctl->rts_cts_rate;
++ WARN_ON(!txctl->rts_cts_rate);
++ rts_rate = txctl->rts_cts_rate ? txctl->rts_cts_rate->hw_value : B43_CCK_RATE_1MB;
+ rts_rate_ofdm = b43_is_ofdm_rate(rts_rate);
+ rts_rate_fb = b43_calc_fallback_rate(rts_rate);
+ rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
+@@ -506,7 +512,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
+ u16 phystat0, phystat3, chanstat, mactime;
+ u32 macstat;
+ u16 chanid;
+- u8 jssi;
++ u16 phytype;
+ int padding;
+
+ memset(&status, 0, sizeof(status));
+@@ -514,10 +520,10 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
+ /* Get metadata about the frame from the header. */
+ phystat0 = le16_to_cpu(rxhdr->phy_status0);
+ phystat3 = le16_to_cpu(rxhdr->phy_status3);
+- jssi = rxhdr->jssi;
+ macstat = le32_to_cpu(rxhdr->mac_status);
+ mactime = le16_to_cpu(rxhdr->mac_time);
+ chanstat = le16_to_cpu(rxhdr->channel);
++ phytype = chanstat & B43_RX_CHAN_PHYTYPE;
+
+ if (macstat & B43_RX_MAC_FCSERR)
+ dev->wl->ieee_stats.dot11FCSErrorCount++;
+@@ -567,26 +573,40 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
+ }
+ }
+
+- status.ssi = b43_rssi_postprocess(dev, jssi,
+- (phystat0 & B43_RX_PHYST0_OFDM),
+- (phystat0 & B43_RX_PHYST0_GAINCTL),
+- (phystat3 & B43_RX_PHYST3_TRSTATE));
++ /* Link quality statistics */
+ status.noise = dev->stats.link_noise;
+- /* the next line looks wrong, but is what mac80211 wants */
+- status.signal = (jssi * 100) / B43_RX_MAX_SSI;
++ if ((chanstat & B43_RX_CHAN_PHYTYPE) == B43_PHYTYPE_N) {
++// s8 rssi = max(rxhdr->power0, rxhdr->power1);
++ //TODO: Find out what the rssi value is (dBm or percentage?)
++ // and also find out what the maximum possible value is.
++ // Fill status.ssi and status.signal fields.
++ } else {
++ status.ssi = b43_rssi_postprocess(dev, rxhdr->jssi,
++ (phystat0 & B43_RX_PHYST0_OFDM),
++ (phystat0 & B43_RX_PHYST0_GAINCTL),
++ (phystat3 & B43_RX_PHYST3_TRSTATE));
++ /* the next line looks wrong, but is what mac80211 wants */
++ status.signal = (rxhdr->jssi * 100) / B43_RX_MAX_SSI;
++ }
++
+ if (phystat0 & B43_RX_PHYST0_OFDM)
+- status.rate = b43_plcp_get_bitrate_ofdm(plcp);
++ status.rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp,
++ phytype == B43_PHYTYPE_A);
+ else
+- status.rate = b43_plcp_get_bitrate_cck(plcp);
++ status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp);
+ status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT);
+
+ /*
+- * If monitors are present get full 64-bit timestamp. This
+- * code assumes we get to process the packet within 16 bits
+- * of timestamp, i.e. about 65 milliseconds after the PHY
+- * received the first symbol.
++ * All frames on monitor interfaces and beacons always need a full
++ * 64-bit timestamp. Monitor interfaces need it for diagnostic
++ * purposes and beacons for IBSS merging.
++ * This code assumes we get to process the packet within 16 bits
++ * of timestamp, i.e. about 65 milliseconds after the PHY received
++ * the first symbol.
+ */
+- if (dev->wl->radiotap_enabled) {
++ if (((fctl & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE))
++ == (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON)) ||
++ dev->wl->radiotap_enabled) {
+ u16 low_mactime_now;
+
+ b43_tsf_read(dev, &status.mactime);
+@@ -601,29 +621,28 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
+ chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT;
+ switch (chanstat & B43_RX_CHAN_PHYTYPE) {
+ case B43_PHYTYPE_A:
+- status.phymode = MODE_IEEE80211A;
++ status.band = IEEE80211_BAND_5GHZ;
+ B43_WARN_ON(1);
+ /* FIXME: We don't really know which value the "chanid" contains.
+ * So the following assignment might be wrong. */
+- status.channel = chanid;
+- status.freq = b43_channel_to_freq_5ghz(status.channel);
++ status.freq = b43_channel_to_freq_5ghz(chanid);
+ break;
+ case B43_PHYTYPE_G:
+- status.phymode = MODE_IEEE80211G;
++ status.band = IEEE80211_BAND_2GHZ;
+ /* chanid is the radio channel cookie value as used
+ * to tune the radio. */
+ status.freq = chanid + 2400;
+- status.channel = b43_freq_to_channel_2ghz(status.freq);
+ break;
+ case B43_PHYTYPE_N:
+- status.phymode = 0xDEAD /*FIXME MODE_IEEE80211N*/;
+ /* chanid is the SHM channel cookie. Which is the plain
+ * channel number in b43. */
+- status.channel = chanid;
+- if (chanstat & B43_RX_CHAN_5GHZ)
+- status.freq = b43_freq_to_channel_5ghz(status.freq);
+- else
+- status.freq = b43_freq_to_channel_2ghz(status.freq);
++ if (chanstat & B43_RX_CHAN_5GHZ) {
++ status.band = IEEE80211_BAND_5GHZ;
++ status.freq = b43_freq_to_channel_5ghz(chanid);
++ } else {
++ status.band = IEEE80211_BAND_2GHZ;
++ status.freq = b43_freq_to_channel_2ghz(chanid);
++ }
+ break;
+ default:
+ B43_WARN_ON(1);
+@@ -657,67 +676,54 @@ void b43_handle_txstatus(struct b43_wldev *dev,
+ dev->wl->ieee_stats.dot11RTSSuccessCount++;
+ }
+
+- b43_dma_handle_txstatus(dev, status);
++ if (b43_using_pio_transfers(dev))
++ b43_pio_handle_txstatus(dev, status);
++ else
++ b43_dma_handle_txstatus(dev, status);
+ }
+
+-/* Handle TX status report as received through DMA/PIO queues */
+-void b43_handle_hwtxstatus(struct b43_wldev *dev,
+- const struct b43_hwtxstatus *hw)
++/* Fill out the mac80211 TXstatus report based on the b43-specific
++ * txstatus report data. This returns a boolean whether the frame was
++ * successfully transmitted. */
++bool b43_fill_txstatus_report(struct ieee80211_tx_status *report,
++ const struct b43_txstatus *status)
+ {
+- struct b43_txstatus status;
+- u8 tmp;
+-
+- status.cookie = le16_to_cpu(hw->cookie);
+- status.seq = le16_to_cpu(hw->seq);
+- status.phy_stat = hw->phy_stat;
+- tmp = hw->count;
+- status.frame_count = (tmp >> 4);
+- status.rts_count = (tmp & 0x0F);
+- tmp = hw->flags;
+- status.supp_reason = ((tmp & 0x1C) >> 2);
+- status.pm_indicated = !!(tmp & 0x80);
+- status.intermediate = !!(tmp & 0x40);
+- status.for_ampdu = !!(tmp & 0x20);
+- status.acked = !!(tmp & 0x02);
+-
+- b43_handle_txstatus(dev, &status);
++ bool frame_success = 1;
++
++ if (status->acked) {
++ /* The frame was ACKed. */
++ report->flags |= IEEE80211_TX_STATUS_ACK;
++ } else {
++ /* The frame was not ACKed... */
++ if (!(report->control.flags & IEEE80211_TXCTL_NO_ACK)) {
++ /* ...but we expected an ACK. */
++ frame_success = 0;
++ report->excessive_retries = 1;
++ }
++ }
++ if (status->frame_count == 0) {
++ /* The frame was not transmitted at all. */
++ report->retry_count = 0;
++ } else
++ report->retry_count = status->frame_count - 1;
++
++ return frame_success;
+ }
+
+ /* Stop any TX operation on the device (suspend the hardware queues) */
+ void b43_tx_suspend(struct b43_wldev *dev)
+ {
+- b43_dma_tx_suspend(dev);
++ if (b43_using_pio_transfers(dev))
++ b43_pio_tx_suspend(dev);
++ else
++ b43_dma_tx_suspend(dev);
+ }
+
+ /* Resume any TX operation on the device (resume the hardware queues) */
+ void b43_tx_resume(struct b43_wldev *dev)
+ {
+- b43_dma_tx_resume(dev);
+-}
+-
+-#if 0
+-static void upload_qos_parms(struct b43_wldev *dev,
+- const u16 * parms, u16 offset)
+-{
+- int i;
+-
+- for (i = 0; i < B43_NR_QOSPARMS; i++) {
+- b43_shm_write16(dev, B43_SHM_SHARED,
+- offset + (i * 2), parms[i]);
+- }
+-}
+-#endif
+-
+-/* Initialize the QoS parameters */
+-void b43_qos_init(struct b43_wldev *dev)
+-{
+- /* FIXME: This function must probably be called from the mac80211
+- * config callback. */
+- return;
+-
+- b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF);
+- //FIXME kill magic
+- b43_write16(dev, 0x688, b43_read16(dev, 0x688) | 0x4);
+-
+- /*TODO: We might need some stack support here to get the values. */
++ if (b43_using_pio_transfers(dev))
++ b43_pio_tx_resume(dev);
++ else
++ b43_dma_tx_resume(dev);
+ }
+diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h
+index 4176503..b05f44e 100644
+--- a/drivers/net/wireless/b43/xmit.h
++++ b/drivers/net/wireless/b43/xmit.h
+@@ -207,25 +207,24 @@ enum {
+ B43_TXST_SUPP_ABNACK, /* Afterburner NACK */
+ };
+
+-/* Transmit Status as received through DMA/PIO on old chips */
+-struct b43_hwtxstatus {
+- PAD_BYTES(4);
+- __le16 cookie;
+- u8 flags;
+- u8 count;
+- PAD_BYTES(2);
+- __le16 seq;
+- u8 phy_stat;
+- PAD_BYTES(1);
+-} __attribute__ ((__packed__));
+-
+ /* Receive header for v4 firmware. */
+ struct b43_rxhdr_fw4 {
+ __le16 frame_len; /* Frame length */
+ PAD_BYTES(2);
+ __le16 phy_status0; /* PHY RX Status 0 */
+- __u8 jssi; /* PHY RX Status 1: JSSI */
+- __u8 sig_qual; /* PHY RX Status 1: Signal Quality */
++ union {
++ /* RSSI for A/B/G-PHYs */
++ struct {
++ __u8 jssi; /* PHY RX Status 1: JSSI */
++ __u8 sig_qual; /* PHY RX Status 1: Signal Quality */
++ } __attribute__ ((__packed__));
++
++ /* RSSI for N-PHYs */
++ struct {
++ __s8 power0; /* PHY RX Status 1: Power 0 */
++ __s8 power1; /* PHY RX Status 1: Power 1 */
++ } __attribute__ ((__packed__));
++ } __attribute__ ((__packed__));
+ __le16 phy_status2; /* PHY RX Status 2 */
+ __le16 phy_status3; /* PHY RX Status 3 */
+ __le32 mac_status; /* MAC RX status */
+@@ -295,25 +294,12 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr);
+
+ void b43_handle_txstatus(struct b43_wldev *dev,
+ const struct b43_txstatus *status);
+-
+-void b43_handle_hwtxstatus(struct b43_wldev *dev,
+- const struct b43_hwtxstatus *hw);
++bool b43_fill_txstatus_report(struct ieee80211_tx_status *report,
++ const struct b43_txstatus *status);
+
+ void b43_tx_suspend(struct b43_wldev *dev);
+ void b43_tx_resume(struct b43_wldev *dev);
+
+-#define B43_NR_QOSPARMS 22
+-enum {
+- B43_QOSPARM_TXOP = 0,
+- B43_QOSPARM_CWMIN,
+- B43_QOSPARM_CWMAX,
+- B43_QOSPARM_CWCUR,
+- B43_QOSPARM_AIFS,
+- B43_QOSPARM_BSLOTS,
+- B43_QOSPARM_REGGAP,
+- B43_QOSPARM_STATUS,
+-};
+-void b43_qos_init(struct b43_wldev *dev);
+
+ /* Helper functions for converting the key-table index from "firmware-format"
+ * to "raw-format" and back. The firmware API changed for this at some revision.
+diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h
+index 93d45b7..ded3cd3 100644
+--- a/drivers/net/wireless/b43legacy/b43legacy.h
++++ b/drivers/net/wireless/b43legacy/b43legacy.h
+@@ -97,6 +97,7 @@
+ #define B43legacy_MMIO_RADIO_HWENABLED_LO 0x49A
+ #define B43legacy_MMIO_GPIO_CONTROL 0x49C
+ #define B43legacy_MMIO_GPIO_MASK 0x49E
++#define B43legacy_MMIO_TSF_CFP_PRETBTT 0x612
+ #define B43legacy_MMIO_TSF_0 0x632 /* core rev < 3 only */
+ #define B43legacy_MMIO_TSF_1 0x634 /* core rev < 3 only */
+ #define B43legacy_MMIO_TSF_2 0x636 /* core rev < 3 only */
+@@ -130,19 +131,27 @@
+ #define B43legacy_SHM_SH_HOSTFHI 0x0060 /* Hostflags ucode opts (high) */
+ /* SHM_SHARED crypto engine */
+ #define B43legacy_SHM_SH_KEYIDXBLOCK 0x05D4 /* Key index/algorithm block */
+-/* SHM_SHARED beacon variables */
++/* SHM_SHARED beacon/AP variables */
++#define B43legacy_SHM_SH_DTIMP 0x0012 /* DTIM period */
++#define B43legacy_SHM_SH_BTL0 0x0018 /* Beacon template length 0 */
++#define B43legacy_SHM_SH_BTL1 0x001A /* Beacon template length 1 */
++#define B43legacy_SHM_SH_BTSFOFF 0x001C /* Beacon TSF offset */
++#define B43legacy_SHM_SH_TIMPOS 0x001E /* TIM position in beacon */
+ #define B43legacy_SHM_SH_BEACPHYCTL 0x0054 /* Beacon PHY TX control word */
+ /* SHM_SHARED ACK/CTS control */
+ #define B43legacy_SHM_SH_ACKCTSPHYCTL 0x0022 /* ACK/CTS PHY control word */
+ /* SHM_SHARED probe response variables */
+-#define B43legacy_SHM_SH_PRPHYCTL 0x0188 /* Probe Resp PHY TX control */
++#define B43legacy_SHM_SH_PRTLEN 0x004A /* Probe Response template length */
+ #define B43legacy_SHM_SH_PRMAXTIME 0x0074 /* Probe Response max time */
++#define B43legacy_SHM_SH_PRPHYCTL 0x0188 /* Probe Resp PHY TX control */
+ /* SHM_SHARED rate tables */
+ /* SHM_SHARED microcode soft registers */
+ #define B43legacy_SHM_SH_UCODEREV 0x0000 /* Microcode revision */
+ #define B43legacy_SHM_SH_UCODEPATCH 0x0002 /* Microcode patchlevel */
+ #define B43legacy_SHM_SH_UCODEDATE 0x0004 /* Microcode date */
+ #define B43legacy_SHM_SH_UCODETIME 0x0006 /* Microcode time */
++#define B43legacy_SHM_SH_SPUWKUP 0x0094 /* pre-wakeup for synth PU in us */
++#define B43legacy_SHM_SH_PRETBTT 0x0096 /* pre-TBTT in us */
+
+ #define B43legacy_UCODEFLAGS_OFFSET 0x005E
+
+@@ -199,6 +208,13 @@
+ #define B43legacy_MACCTL_TBTTHOLD 0x10000000 /* TBTT Hold */
+ #define B43legacy_MACCTL_GMODE 0x80000000 /* G Mode */
+
++/* MAC Command bitfield */
++#define B43legacy_MACCMD_BEACON0_VALID 0x00000001 /* Beacon 0 in template RAM is busy/valid */
++#define B43legacy_MACCMD_BEACON1_VALID 0x00000002 /* Beacon 1 in template RAM is busy/valid */
++#define B43legacy_MACCMD_DFQ_VALID 0x00000004 /* Directed frame queue valid (IBSS PS mode, ATIM) */
++#define B43legacy_MACCMD_CCA 0x00000008 /* Clear channel assessment */
++#define B43legacy_MACCMD_BGNOISE 0x00000010 /* Background noise */
++
+ /* 802.11 core specific TM State Low flags */
+ #define B43legacy_TMSLOW_GMODE 0x20000000 /* G Mode Enable */
+ #define B43legacy_TMSLOW_PLLREFSEL 0x00200000 /* PLL Freq Ref Select */
+@@ -317,15 +333,7 @@ enum {
+ # undef assert
+ #endif
+ #ifdef CONFIG_B43LEGACY_DEBUG
+-# define B43legacy_WARN_ON(expr) \
+- do { \
+- if (unlikely((expr))) { \
+- printk(KERN_INFO PFX "Test (%s) failed at:" \
+- " %s:%d:%s()\n", \
+- #expr, __FILE__, \
+- __LINE__, __FUNCTION__); \
+- } \
+- } while (0)
++# define B43legacy_WARN_ON(x) WARN_ON(x)
+ # define B43legacy_BUG_ON(expr) \
+ do { \
+ if (unlikely((expr))) { \
+@@ -336,7 +344,9 @@ enum {
+ } while (0)
+ # define B43legacy_DEBUG 1
+ #else
+-# define B43legacy_WARN_ON(x) do { /* nothing */ } while (0)
++/* This will evaluate the argument even if debugging is disabled. */
++static inline bool __b43legacy_warn_on_dummy(bool x) { return x; }
++# define B43legacy_WARN_ON(x) __b43legacy_warn_on_dummy(unlikely(!!(x)))
+ # define B43legacy_BUG_ON(x) do { /* nothing */ } while (0)
+ # define B43legacy_DEBUG 0
+ #endif
+@@ -392,10 +402,6 @@ struct b43legacy_phy {
+ u8 possible_phymodes;
+ /* GMODE bit enabled in MACCTL? */
+ bool gmode;
+- /* Possible ieee80211 subsystem hwmodes for this PHY.
+- * Which mode is selected, depends on thr GMODE enabled bit */
+-#define B43legacy_MAX_PHYHWMODES 2
+- struct ieee80211_hw_mode hwmodes[B43legacy_MAX_PHYHWMODES];
+
+ /* Analog Type */
+ u8 analog;
+@@ -598,6 +604,12 @@ struct b43legacy_wl {
+ u8 nr_devs;
+
+ bool radiotap_enabled;
++
++ /* The beacon we are currently using (AP or IBSS mode).
++ * This beacon stuff is protected by the irq_lock. */
++ struct sk_buff *current_beacon;
++ bool beacon0_uploaded;
++ bool beacon1_uploaded;
+ };
+
+ /* Pointers to the firmware data and meta information about it. */
+@@ -649,7 +661,7 @@ struct b43legacy_wldev {
+
+ bool __using_pio; /* Using pio rather than dma. */
+ bool bad_frames_preempt;/* Use "Bad Frames Preemption". */
+- bool reg124_set_0x4; /* Variable to keep track of IRQ. */
++ bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM). */
+ bool short_preamble; /* TRUE if using short preamble. */
+ bool short_slot; /* TRUE if using short slot timing. */
+ bool radio_hw_enable; /* State of radio hardware enable bit. */
+@@ -696,9 +708,6 @@ struct b43legacy_wldev {
+ u8 max_nr_keys;
+ struct b43legacy_key key[58];
+
+- /* Cached beacon template while uploading the template. */
+- struct sk_buff *cached_beacon;
+-
+ /* Firmware data */
+ struct b43legacy_firmware fw;
+
+diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
+index 0f7a6e7..ef829ee 100644
+--- a/drivers/net/wireless/b43legacy/main.c
++++ b/drivers/net/wireless/b43legacy/main.c
+@@ -95,28 +95,29 @@ MODULE_DEVICE_TABLE(ssb, b43legacy_ssb_tbl);
+ * data in there. This data is the same for all devices, so we don't
+ * get concurrency issues */
+ #define RATETAB_ENT(_rateid, _flags) \
+- { \
+- .rate = B43legacy_RATE_TO_100KBPS(_rateid), \
+- .val = (_rateid), \
+- .val2 = (_rateid), \
+- .flags = (_flags), \
++ { \
++ .bitrate = B43legacy_RATE_TO_100KBPS(_rateid), \
++ .hw_value = (_rateid), \
++ .flags = (_flags), \
+ }
++/*
++ * NOTE: When changing this, sync with xmit.c's
++ * b43legacy_plcp_get_bitrate_idx_* functions!
++ */
+ static struct ieee80211_rate __b43legacy_ratetable[] = {
+- RATETAB_ENT(B43legacy_CCK_RATE_1MB, IEEE80211_RATE_CCK),
+- RATETAB_ENT(B43legacy_CCK_RATE_2MB, IEEE80211_RATE_CCK_2),
+- RATETAB_ENT(B43legacy_CCK_RATE_5MB, IEEE80211_RATE_CCK_2),
+- RATETAB_ENT(B43legacy_CCK_RATE_11MB, IEEE80211_RATE_CCK_2),
+- RATETAB_ENT(B43legacy_OFDM_RATE_6MB, IEEE80211_RATE_OFDM),
+- RATETAB_ENT(B43legacy_OFDM_RATE_9MB, IEEE80211_RATE_OFDM),
+- RATETAB_ENT(B43legacy_OFDM_RATE_12MB, IEEE80211_RATE_OFDM),
+- RATETAB_ENT(B43legacy_OFDM_RATE_18MB, IEEE80211_RATE_OFDM),
+- RATETAB_ENT(B43legacy_OFDM_RATE_24MB, IEEE80211_RATE_OFDM),
+- RATETAB_ENT(B43legacy_OFDM_RATE_36MB, IEEE80211_RATE_OFDM),
+- RATETAB_ENT(B43legacy_OFDM_RATE_48MB, IEEE80211_RATE_OFDM),
+- RATETAB_ENT(B43legacy_OFDM_RATE_54MB, IEEE80211_RATE_OFDM),
++ RATETAB_ENT(B43legacy_CCK_RATE_1MB, 0),
++ RATETAB_ENT(B43legacy_CCK_RATE_2MB, IEEE80211_RATE_SHORT_PREAMBLE),
++ RATETAB_ENT(B43legacy_CCK_RATE_5MB, IEEE80211_RATE_SHORT_PREAMBLE),
++ RATETAB_ENT(B43legacy_CCK_RATE_11MB, IEEE80211_RATE_SHORT_PREAMBLE),
++ RATETAB_ENT(B43legacy_OFDM_RATE_6MB, 0),
++ RATETAB_ENT(B43legacy_OFDM_RATE_9MB, 0),
++ RATETAB_ENT(B43legacy_OFDM_RATE_12MB, 0),
++ RATETAB_ENT(B43legacy_OFDM_RATE_18MB, 0),
++ RATETAB_ENT(B43legacy_OFDM_RATE_24MB, 0),
++ RATETAB_ENT(B43legacy_OFDM_RATE_36MB, 0),
++ RATETAB_ENT(B43legacy_OFDM_RATE_48MB, 0),
++ RATETAB_ENT(B43legacy_OFDM_RATE_54MB, 0),
+ };
+-#define b43legacy_a_ratetable (__b43legacy_ratetable + 4)
+-#define b43legacy_a_ratetable_size 8
+ #define b43legacy_b_ratetable (__b43legacy_ratetable + 0)
+ #define b43legacy_b_ratetable_size 4
+ #define b43legacy_g_ratetable (__b43legacy_ratetable + 0)
+@@ -124,14 +125,8 @@ static struct ieee80211_rate __b43legacy_ratetable[] = {
+
+ #define CHANTAB_ENT(_chanid, _freq) \
+ { \
+- .chan = (_chanid), \
+- .freq = (_freq), \
+- .val = (_chanid), \
+- .flag = IEEE80211_CHAN_W_SCAN | \
+- IEEE80211_CHAN_W_ACTIVE_SCAN | \
+- IEEE80211_CHAN_W_IBSS, \
+- .power_level = 0x0A, \
+- .antenna_max = 0xFF, \
++ .center_freq = (_freq), \
++ .hw_value = (_chanid), \
+ }
+ static struct ieee80211_channel b43legacy_bg_chantable[] = {
+ CHANTAB_ENT(1, 2412),
+@@ -149,7 +144,20 @@ static struct ieee80211_channel b43legacy_bg_chantable[] = {
+ CHANTAB_ENT(13, 2472),
+ CHANTAB_ENT(14, 2484),
+ };
+-#define b43legacy_bg_chantable_size ARRAY_SIZE(b43legacy_bg_chantable)
++
++static struct ieee80211_supported_band b43legacy_band_2GHz_BPHY = {
++ .channels = b43legacy_bg_chantable,
++ .n_channels = ARRAY_SIZE(b43legacy_bg_chantable),
++ .bitrates = b43legacy_b_ratetable,
++ .n_bitrates = b43legacy_b_ratetable_size,
++};
++
++static struct ieee80211_supported_band b43legacy_band_2GHz_GPHY = {
++ .channels = b43legacy_bg_chantable,
++ .n_channels = ARRAY_SIZE(b43legacy_bg_chantable),
++ .bitrates = b43legacy_g_ratetable,
++ .n_bitrates = b43legacy_g_ratetable_size,
++};
+
+ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev);
+ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev);
+@@ -797,9 +805,8 @@ static void b43legacy_generate_noise_sample(struct b43legacy_wldev *dev)
+ {
+ b43legacy_jssi_write(dev, 0x7F7F7F7F);
+ b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
+- b43legacy_read32(dev,
+- B43legacy_MMIO_MACCMD)
+- | (1 << 4));
++ b43legacy_read32(dev, B43legacy_MMIO_MACCMD)
++ | B43legacy_MACCMD_BGNOISE);
+ B43legacy_WARN_ON(dev->noisecalc.channel_at_start !=
+ dev->phy.channel);
+ }
+@@ -888,18 +895,18 @@ static void handle_irq_tbtt_indication(struct b43legacy_wldev *dev)
+ if (1/*FIXME: the last PSpoll frame was sent successfully */)
+ b43legacy_power_saving_ctl_bits(dev, -1, -1);
+ }
+- dev->reg124_set_0x4 = 0;
+ if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS))
+- dev->reg124_set_0x4 = 1;
++ dev->dfq_valid = 1;
+ }
+
+ static void handle_irq_atim_end(struct b43legacy_wldev *dev)
+ {
+- if (!dev->reg124_set_0x4) /*FIXME rename this variable*/
+- return;
+- b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
+- b43legacy_read32(dev, B43legacy_MMIO_MACCMD)
+- | 0x4);
++ if (dev->dfq_valid) {
++ b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
++ b43legacy_read32(dev, B43legacy_MMIO_MACCMD)
++ | B43legacy_MACCMD_DFQ_VALID);
++ dev->dfq_valid = 0;
++ }
+ }
+
+ static void handle_irq_pmq(struct b43legacy_wldev *dev)
+@@ -955,32 +962,77 @@ static void b43legacy_write_beacon_template(struct b43legacy_wldev *dev,
+ u16 ram_offset,
+ u16 shm_size_offset, u8 rate)
+ {
+- int len;
+- const u8 *data;
+
+- B43legacy_WARN_ON(!dev->cached_beacon);
+- len = min((size_t)dev->cached_beacon->len,
++ unsigned int i, len, variable_len;
++ const struct ieee80211_mgmt *bcn;
++ const u8 *ie;
++ bool tim_found = 0;
++
++ bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data);
++ len = min((size_t)dev->wl->current_beacon->len,
+ 0x200 - sizeof(struct b43legacy_plcp_hdr6));
+- data = (const u8 *)(dev->cached_beacon->data);
+- b43legacy_write_template_common(dev, data,
+- len, ram_offset,
++
++ b43legacy_write_template_common(dev, (const u8 *)bcn, len, ram_offset,
+ shm_size_offset, rate);
++
++ /* Find the position of the TIM and the DTIM_period value
++ * and write them to SHM. */
++ ie = bcn->u.beacon.variable;
++ variable_len = len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
++ for (i = 0; i < variable_len - 2; ) {
++ uint8_t ie_id, ie_len;
++
++ ie_id = ie[i];
++ ie_len = ie[i + 1];
++ if (ie_id == 5) {
++ u16 tim_position;
++ u16 dtim_period;
++ /* This is the TIM Information Element */
++
++ /* Check whether the ie_len is in the beacon data range. */
++ if (variable_len < ie_len + 2 + i)
++ break;
++ /* A valid TIM is at least 4 bytes long. */
++ if (ie_len < 4)
++ break;
++ tim_found = 1;
++
++ tim_position = sizeof(struct b43legacy_plcp_hdr6);
++ tim_position += offsetof(struct ieee80211_mgmt,
++ u.beacon.variable);
++ tim_position += i;
++
++ dtim_period = ie[i + 3];
++
++ b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
++ B43legacy_SHM_SH_TIMPOS, tim_position);
++ b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
++ B43legacy_SHM_SH_DTIMP, dtim_period);
++ break;
++ }
++ i += ie_len + 2;
++ }
++ if (!tim_found) {
++ b43legacywarn(dev->wl, "Did not find a valid TIM IE in the "
++ "beacon template packet. AP or IBSS operation "
++ "may be broken.\n");
++ }
+ }
+
+ static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev,
+ u16 shm_offset, u16 size,
+- u8 rate)
++ struct ieee80211_rate *rate)
+ {
+ struct b43legacy_plcp_hdr4 plcp;
+ u32 tmp;
+ __le16 dur;
+
+ plcp.data = 0;
+- b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
++ b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->bitrate);
+ dur = ieee80211_generic_frame_duration(dev->wl->hw,
+ dev->wl->vif,
+ size,
+- B43legacy_RATE_TO_100KBPS(rate));
++ rate);
+ /* Write PLCP in two parts and timing for packet transfer */
+ tmp = le32_to_cpu(plcp.data);
+ b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, shm_offset,
+@@ -997,45 +1049,44 @@ static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev,
+ * 2) Patching duration field
+ * 3) Stripping TIM
+ */
+-static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
+- u16 *dest_size, u8 rate)
++static const u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
++ u16 *dest_size,
++ struct ieee80211_rate *rate)
+ {
+ const u8 *src_data;
+ u8 *dest_data;
+- u16 src_size;
+- u16 elem_size;
+- u16 src_pos;
+- u16 dest_pos;
++ u16 src_size, elem_size, src_pos, dest_pos;
+ __le16 dur;
+ struct ieee80211_hdr *hdr;
++ size_t ie_start;
++
++ src_size = dev->wl->current_beacon->len;
++ src_data = (const u8 *)dev->wl->current_beacon->data;
+
+- B43legacy_WARN_ON(!dev->cached_beacon);
+- src_size = dev->cached_beacon->len;
+- src_data = (const u8 *)dev->cached_beacon->data;
++ /* Get the start offset of the variable IEs in the packet. */
++ ie_start = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
++ B43legacy_WARN_ON(ie_start != offsetof(struct ieee80211_mgmt,
++ u.beacon.variable));
+
+- if (unlikely(src_size < 0x24)) {
+- b43legacydbg(dev->wl, "b43legacy_generate_probe_resp: "
+- "invalid beacon\n");
++ if (B43legacy_WARN_ON(src_size < ie_start))
+ return NULL;
+- }
+
+ dest_data = kmalloc(src_size, GFP_ATOMIC);
+ if (unlikely(!dest_data))
+ return NULL;
+
+- /* 0x24 is offset of first variable-len Information-Element
+- * in beacon frame.
+- */
+- memcpy(dest_data, src_data, 0x24);
+- src_pos = 0x24;
+- dest_pos = 0x24;
+- for (; src_pos < src_size - 2; src_pos += elem_size) {
++ /* Copy the static data and all Information Elements, except the TIM. */
++ memcpy(dest_data, src_data, ie_start);
++ src_pos = ie_start;
++ dest_pos = ie_start;
++ for ( ; src_pos < src_size - 2; src_pos += elem_size) {
+ elem_size = src_data[src_pos + 1] + 2;
+- if (src_data[src_pos] != 0x05) { /* TIM */
+- memcpy(dest_data + dest_pos, src_data + src_pos,
+- elem_size);
+- dest_pos += elem_size;
++ if (src_data[src_pos] == 5) {
++ /* This is the TIM. */
++ continue;
+ }
++ memcpy(dest_data + dest_pos, src_data + src_pos, elem_size);
++ dest_pos += elem_size;
+ }
+ *dest_size = dest_pos;
+ hdr = (struct ieee80211_hdr *)dest_data;
+@@ -1046,7 +1097,7 @@ static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
+ dur = ieee80211_generic_frame_duration(dev->wl->hw,
+ dev->wl->vif,
+ *dest_size,
+- B43legacy_RATE_TO_100KBPS(rate));
++ rate);
+ hdr->duration_id = dur;
+
+ return dest_data;
+@@ -1054,13 +1105,13 @@ static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
+
+ static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev,
+ u16 ram_offset,
+- u16 shm_size_offset, u8 rate)
++ u16 shm_size_offset,
++ struct ieee80211_rate *rate)
+ {
+- u8 *probe_resp_data;
++ const u8 *probe_resp_data;
+ u16 size;
+
+- B43legacy_WARN_ON(!dev->cached_beacon);
+- size = dev->cached_beacon->len;
++ size = dev->wl->current_beacon->len;
+ probe_resp_data = b43legacy_generate_probe_resp(dev, &size, rate);
+ if (unlikely(!probe_resp_data))
+ return;
+@@ -1069,59 +1120,37 @@ static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev,
+ * all possible basic rates
+ */
+ b43legacy_write_probe_resp_plcp(dev, 0x31A, size,
+- B43legacy_CCK_RATE_1MB);
++ &b43legacy_b_ratetable[0]);
+ b43legacy_write_probe_resp_plcp(dev, 0x32C, size,
+- B43legacy_CCK_RATE_2MB);
++ &b43legacy_b_ratetable[1]);
+ b43legacy_write_probe_resp_plcp(dev, 0x33E, size,
+- B43legacy_CCK_RATE_5MB);
++ &b43legacy_b_ratetable[2]);
+ b43legacy_write_probe_resp_plcp(dev, 0x350, size,
+- B43legacy_CCK_RATE_11MB);
++ &b43legacy_b_ratetable[3]);
+
+ size = min((size_t)size,
+ 0x200 - sizeof(struct b43legacy_plcp_hdr6));
+ b43legacy_write_template_common(dev, probe_resp_data,
+ size, ram_offset,
+- shm_size_offset, rate);
++ shm_size_offset, rate->bitrate);
+ kfree(probe_resp_data);
+ }
+
+-static int b43legacy_refresh_cached_beacon(struct b43legacy_wldev *dev,
+- struct sk_buff *beacon)
++/* Asynchronously update the packet templates in template RAM.
++ * Locking: Requires wl->irq_lock to be locked. */
++static void b43legacy_update_templates(struct b43legacy_wl *wl,
++ struct sk_buff *beacon)
+ {
+- if (dev->cached_beacon)
+- kfree_skb(dev->cached_beacon);
+- dev->cached_beacon = beacon;
++ /* This is the top half of the ansynchronous beacon update. The bottom
++ * half is the beacon IRQ. Beacon update must be asynchronous to avoid
++ * sending an invalid beacon. This can happen for example, if the
++ * firmware transmits a beacon while we are updating it. */
+
+- return 0;
+-}
+-
+-static void b43legacy_update_templates(struct b43legacy_wldev *dev)
+-{
+- u32 status;
+-
+- B43legacy_WARN_ON(!dev->cached_beacon);
+-
+- b43legacy_write_beacon_template(dev, 0x68, 0x18,
+- B43legacy_CCK_RATE_1MB);
+- b43legacy_write_beacon_template(dev, 0x468, 0x1A,
+- B43legacy_CCK_RATE_1MB);
+- b43legacy_write_probe_resp_template(dev, 0x268, 0x4A,
+- B43legacy_CCK_RATE_11MB);
+-
+- status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
+- status |= 0x03;
+- b43legacy_write32(dev, B43legacy_MMIO_MACCMD, status);
+-}
+-
+-static void b43legacy_refresh_templates(struct b43legacy_wldev *dev,
+- struct sk_buff *beacon)
+-{
+- int err;
+-
+- err = b43legacy_refresh_cached_beacon(dev, beacon);
+- if (unlikely(err))
+- return;
+- b43legacy_update_templates(dev);
++ if (wl->current_beacon)
++ dev_kfree_skb_any(wl->current_beacon);
++ wl->current_beacon = beacon;
++ wl->beacon0_uploaded = 0;
++ wl->beacon1_uploaded = 0;
+ }
+
+ static void b43legacy_set_ssid(struct b43legacy_wldev *dev,
+@@ -1162,38 +1191,37 @@ static void b43legacy_set_beacon_int(struct b43legacy_wldev *dev,
+
+ static void handle_irq_beacon(struct b43legacy_wldev *dev)
+ {
+- u32 status;
++ struct b43legacy_wl *wl = dev->wl;
++ u32 cmd;
+
+- if (!b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
++ if (!b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP))
+ return;
+
+- dev->irq_savedstate &= ~B43legacy_IRQ_BEACON;
+- status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
+-
+- if (!dev->cached_beacon || ((status & 0x1) && (status & 0x2))) {
+- /* ACK beacon IRQ. */
+- b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON,
+- B43legacy_IRQ_BEACON);
+- dev->irq_savedstate |= B43legacy_IRQ_BEACON;
+- if (dev->cached_beacon)
+- kfree_skb(dev->cached_beacon);
+- dev->cached_beacon = NULL;
+- return;
+- }
+- if (!(status & 0x1)) {
+- b43legacy_write_beacon_template(dev, 0x68, 0x18,
+- B43legacy_CCK_RATE_1MB);
+- status |= 0x1;
+- b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
+- status);
+- }
+- if (!(status & 0x2)) {
+- b43legacy_write_beacon_template(dev, 0x468, 0x1A,
+- B43legacy_CCK_RATE_1MB);
+- status |= 0x2;
+- b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
+- status);
++ /* This is the bottom half of the asynchronous beacon update. */
++
++ cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
++ if (!(cmd & B43legacy_MACCMD_BEACON0_VALID)) {
++ if (!wl->beacon0_uploaded) {
++ b43legacy_write_beacon_template(dev, 0x68,
++ B43legacy_SHM_SH_BTL0,
++ B43legacy_CCK_RATE_1MB);
++ b43legacy_write_probe_resp_template(dev, 0x268,
++ B43legacy_SHM_SH_PRTLEN,
++ &__b43legacy_ratetable[3]);
++ wl->beacon0_uploaded = 1;
++ }
++ cmd |= B43legacy_MACCMD_BEACON0_VALID;
++ }
++ if (!(cmd & B43legacy_MACCMD_BEACON1_VALID)) {
++ if (!wl->beacon1_uploaded) {
++ b43legacy_write_beacon_template(dev, 0x468,
++ B43legacy_SHM_SH_BTL1,
++ B43legacy_CCK_RATE_1MB);
++ wl->beacon1_uploaded = 1;
++ }
++ cmd |= B43legacy_MACCMD_BEACON1_VALID;
+ }
++ b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd);
+ }
+
+ static void handle_irq_ucode_debug(struct b43legacy_wldev *dev)
+@@ -2552,14 +2580,16 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
+ antenna_rx = b43legacy_antenna_from_ieee80211(conf->antenna_sel_rx);
+
+ mutex_lock(&wl->mutex);
++ dev = wl->current_dev;
++ phy = &dev->phy;
+
+ /* Switch the PHY mode (if necessary). */
+- switch (conf->phymode) {
+- case MODE_IEEE80211B:
+- new_phymode = B43legacy_PHYMODE_B;
+- break;
+- case MODE_IEEE80211G:
+- new_phymode = B43legacy_PHYMODE_G;
++ switch (conf->channel->band) {
++ case IEEE80211_BAND_2GHZ:
++ if (phy->type == B43legacy_PHYTYPE_B)
++ new_phymode = B43legacy_PHYMODE_B;
++ else
++ new_phymode = B43legacy_PHYMODE_G;
+ break;
+ default:
+ B43legacy_WARN_ON(1);
+@@ -2567,8 +2597,6 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
+ err = b43legacy_switch_phymode(wl, new_phymode);
+ if (err)
+ goto out_unlock_mutex;
+- dev = wl->current_dev;
+- phy = &dev->phy;
+
+ /* Disable IRQs while reconfiguring the device.
+ * This makes it possible to drop the spinlock throughout
+@@ -2584,8 +2612,8 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
+
+ /* Switch to the requested channel.
+ * The firmware takes care of races with the TX handler. */
+- if (conf->channel_val != phy->channel)
+- b43legacy_radio_selectchannel(dev, conf->channel_val, 0);
++ if (conf->channel->hw_value != phy->channel)
++ b43legacy_radio_selectchannel(dev, conf->channel->hw_value, 0);
+
+ /* Enable/Disable ShortSlot timing. */
+ if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME))
+@@ -2702,7 +2730,7 @@ static int b43legacy_op_config_interface(struct ieee80211_hw *hw,
+ B43legacy_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP);
+ b43legacy_set_ssid(dev, conf->ssid, conf->ssid_len);
+ if (conf->beacon)
+- b43legacy_refresh_templates(dev, conf->beacon);
++ b43legacy_update_templates(wl, conf->beacon);
+ }
+ b43legacy_write_mac_bssid_templates(dev);
+ }
+@@ -2920,7 +2948,7 @@ static void setup_struct_phy_for_init(struct b43legacy_wldev *dev,
+ static void setup_struct_wldev_for_init(struct b43legacy_wldev *dev)
+ {
+ /* Flags */
+- dev->reg124_set_0x4 = 0;
++ dev->dfq_valid = 0;
+
+ /* Stats */
+ memset(&dev->stats, 0, sizeof(dev->stats));
+@@ -2979,6 +3007,34 @@ static void b43legacy_set_retry_limits(struct b43legacy_wldev *dev,
+ b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0007, long_retry);
+ }
+
++static void b43legacy_set_synth_pu_delay(struct b43legacy_wldev *dev,
++ bool idle) {
++ u16 pu_delay = 1050;
++
++ if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS) || idle)
++ pu_delay = 500;
++ if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8))
++ pu_delay = max(pu_delay, (u16)2400);
++
++ b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
++ B43legacy_SHM_SH_SPUWKUP, pu_delay);
++}
++
++/* Set the TSF CFP pre-TargetBeaconTransmissionTime. */
++static void b43legacy_set_pretbtt(struct b43legacy_wldev *dev)
++{
++ u16 pretbtt;
++
++ /* The time value is in microseconds. */
++ if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS))
++ pretbtt = 2;
++ else
++ pretbtt = 250;
++ b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
++ B43legacy_SHM_SH_PRETBTT, pretbtt);
++ b43legacy_write16(dev, B43legacy_MMIO_TSF_CFP_PRETBTT, pretbtt);
++}
++
+ /* Shutdown a wireless core */
+ /* Locking: wl->mutex */
+ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev)
+@@ -3015,6 +3071,11 @@ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev)
+ kfree(phy->tssi2dbm);
+ kfree(phy->lo_control);
+ phy->lo_control = NULL;
++ if (dev->wl->current_beacon) {
++ dev_kfree_skb_any(dev->wl->current_beacon);
++ dev->wl->current_beacon = NULL;
++ }
++
+ ssb_device_disable(dev->dev, 0);
+ ssb_bus_may_powerdown(dev->dev->bus);
+ }
+@@ -3160,9 +3221,7 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev)
+ if (err)
+ goto err_chip_exit;
+
+- b43legacy_write16(dev, 0x0612, 0x0050);
+- b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0416, 0x0050);
+- b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0414, 0x01F4);
++ b43legacy_set_synth_pu_delay(dev, 1);
+
+ ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */
+ b43legacy_upload_card_macaddress(dev);
+@@ -3218,6 +3277,8 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw,
+
+ spin_lock_irqsave(&wl->irq_lock, flags);
+ b43legacy_adjust_opmode(dev);
++ b43legacy_set_pretbtt(dev);
++ b43legacy_set_synth_pu_delay(dev, 0);
+ b43legacy_upload_card_macaddress(dev);
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
+
+@@ -3339,6 +3400,41 @@ out_unlock:
+ return err;
+ }
+
++static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw,
++ int aid, int set)
++{
++ struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
++ struct sk_buff *beacon;
++ unsigned long flags;
++
++ /* We could modify the existing beacon and set the aid bit in the TIM
++ * field, but that would probably require resizing and moving of data
++ * within the beacon template. Simply request a new beacon and let
++ * mac80211 do the hard work. */
++ beacon = ieee80211_beacon_get(hw, wl->vif, NULL);
++ if (unlikely(!beacon))
++ return -ENOMEM;
++ spin_lock_irqsave(&wl->irq_lock, flags);
++ b43legacy_update_templates(wl, beacon);
++ spin_unlock_irqrestore(&wl->irq_lock, flags);
++
++ return 0;
++}
++
++static int b43legacy_op_ibss_beacon_update(struct ieee80211_hw *hw,
++ struct sk_buff *beacon,
++ struct ieee80211_tx_control *ctl)
++{
++ struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
++ unsigned long flags;
++
++ spin_lock_irqsave(&wl->irq_lock, flags);
++ b43legacy_update_templates(wl, beacon);
++ spin_unlock_irqrestore(&wl->irq_lock, flags);
++
++ return 0;
++}
++
+ static const struct ieee80211_ops b43legacy_hw_ops = {
+ .tx = b43legacy_op_tx,
+ .conf_tx = b43legacy_op_conf_tx,
+@@ -3352,6 +3448,8 @@ static const struct ieee80211_ops b43legacy_hw_ops = {
+ .start = b43legacy_op_start,
+ .stop = b43legacy_op_stop,
+ .set_retry_limit = b43legacy_op_set_retry_limit,
++ .set_tim = b43legacy_op_beacon_set_tim,
++ .beacon_update = b43legacy_op_ibss_beacon_update,
+ };
+
+ /* Hard-reset the chip. Do not call this directly.
+@@ -3400,48 +3498,19 @@ static int b43legacy_setup_modes(struct b43legacy_wldev *dev,
+ int have_gphy)
+ {
+ struct ieee80211_hw *hw = dev->wl->hw;
+- struct ieee80211_hw_mode *mode;
+ struct b43legacy_phy *phy = &dev->phy;
+- int cnt = 0;
+- int err;
+
+ phy->possible_phymodes = 0;
+- for (; 1; cnt++) {
+- if (have_bphy) {
+- B43legacy_WARN_ON(cnt >= B43legacy_MAX_PHYHWMODES);
+- mode = &phy->hwmodes[cnt];
+-
+- mode->mode = MODE_IEEE80211B;
+- mode->num_channels = b43legacy_bg_chantable_size;
+- mode->channels = b43legacy_bg_chantable;
+- mode->num_rates = b43legacy_b_ratetable_size;
+- mode->rates = b43legacy_b_ratetable;
+- err = ieee80211_register_hwmode(hw, mode);
+- if (err)
+- return err;
+-
+- phy->possible_phymodes |= B43legacy_PHYMODE_B;
+- have_bphy = 0;
+- continue;
+- }
+- if (have_gphy) {
+- B43legacy_WARN_ON(cnt >= B43legacy_MAX_PHYHWMODES);
+- mode = &phy->hwmodes[cnt];
+-
+- mode->mode = MODE_IEEE80211G;
+- mode->num_channels = b43legacy_bg_chantable_size;
+- mode->channels = b43legacy_bg_chantable;
+- mode->num_rates = b43legacy_g_ratetable_size;
+- mode->rates = b43legacy_g_ratetable;
+- err = ieee80211_register_hwmode(hw, mode);
+- if (err)
+- return err;
+-
+- phy->possible_phymodes |= B43legacy_PHYMODE_G;
+- have_gphy = 0;
+- continue;
+- }
+- break;
++ if (have_bphy) {
++ hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
++ &b43legacy_band_2GHz_BPHY;
++ phy->possible_phymodes |= B43legacy_PHYMODE_B;
++ }
++
++ if (have_gphy) {
++ hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
++ &b43legacy_band_2GHz_GPHY;
++ phy->possible_phymodes |= B43legacy_PHYMODE_G;
+ }
+
+ return 0;
+diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c
+index d84408a..dcad249 100644
+--- a/drivers/net/wireless/b43legacy/xmit.c
++++ b/drivers/net/wireless/b43legacy/xmit.c
+@@ -37,45 +37,48 @@
+
+
+ /* Extract the bitrate out of a CCK PLCP header. */
+-static u8 b43legacy_plcp_get_bitrate_cck(struct b43legacy_plcp_hdr6 *plcp)
++static u8 b43legacy_plcp_get_bitrate_idx_cck(struct b43legacy_plcp_hdr6 *plcp)
+ {
+ switch (plcp->raw[0]) {
+ case 0x0A:
+- return B43legacy_CCK_RATE_1MB;
++ return 0;
+ case 0x14:
+- return B43legacy_CCK_RATE_2MB;
++ return 1;
+ case 0x37:
+- return B43legacy_CCK_RATE_5MB;
++ return 2;
+ case 0x6E:
+- return B43legacy_CCK_RATE_11MB;
++ return 3;
+ }
+ B43legacy_BUG_ON(1);
+- return 0;
++ return -1;
+ }
+
+ /* Extract the bitrate out of an OFDM PLCP header. */
+-static u8 b43legacy_plcp_get_bitrate_ofdm(struct b43legacy_plcp_hdr6 *plcp)
++static u8 b43legacy_plcp_get_bitrate_idx_ofdm(struct b43legacy_plcp_hdr6 *plcp,
++ bool aphy)
+ {
++ int base = aphy ? 0 : 4;
++
+ switch (plcp->raw[0] & 0xF) {
+ case 0xB:
+- return B43legacy_OFDM_RATE_6MB;
++ return base + 0;
+ case 0xF:
+- return B43legacy_OFDM_RATE_9MB;
++ return base + 1;
+ case 0xA:
+- return B43legacy_OFDM_RATE_12MB;
++ return base + 2;
+ case 0xE:
+- return B43legacy_OFDM_RATE_18MB;
++ return base + 3;
+ case 0x9:
+- return B43legacy_OFDM_RATE_24MB;
++ return base + 4;
+ case 0xD:
+- return B43legacy_OFDM_RATE_36MB;
++ return base + 5;
+ case 0x8:
+- return B43legacy_OFDM_RATE_48MB;
++ return base + 6;
+ case 0xC:
+- return B43legacy_OFDM_RATE_54MB;
++ return base + 7;
+ }
+ B43legacy_BUG_ON(1);
+- return 0;
++ return -1;
+ }
+
+ u8 b43legacy_plcp_get_ratecode_cck(const u8 bitrate)
+@@ -192,7 +195,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
+ int use_encryption = (!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT));
+ u16 fctl;
+ u8 rate;
+- u8 rate_fb;
++ struct ieee80211_rate *rate_fb;
+ int rate_ofdm;
+ int rate_fb_ofdm;
+ unsigned int plcp_fragment_len;
+@@ -204,16 +207,16 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
+
+ memset(txhdr, 0, sizeof(*txhdr));
+
+- rate = txctl->tx_rate;
++ rate = txctl->tx_rate->hw_value;
+ rate_ofdm = b43legacy_is_ofdm_rate(rate);
+- rate_fb = (txctl->alt_retry_rate == -1) ? rate : txctl->alt_retry_rate;
+- rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb);
++ rate_fb = txctl->alt_retry_rate ? : txctl->tx_rate;
++ rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value);
+
+ txhdr->mac_frame_ctl = wlhdr->frame_control;
+ memcpy(txhdr->tx_receiver, wlhdr->addr1, 6);
+
+ /* Calculate duration for fallback rate */
+- if ((rate_fb == rate) ||
++ if ((rate_fb->hw_value == rate) ||
+ (wlhdr->duration_id & cpu_to_le16(0x8000)) ||
+ (wlhdr->duration_id == cpu_to_le16(0))) {
+ /* If the fallback rate equals the normal rate or the
+@@ -221,11 +224,10 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
+ * use the original dur_id field. */
+ txhdr->dur_fb = wlhdr->duration_id;
+ } else {
+- int fbrate_base100kbps = B43legacy_RATE_TO_100KBPS(rate_fb);
+ txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw,
+ txctl->vif,
+ fragment_len,
+- fbrate_base100kbps);
++ rate_fb);
+ }
+
+ plcp_fragment_len = fragment_len + FCS_LEN;
+@@ -266,7 +268,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
+ rate);
+ b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *)
+ (&txhdr->plcp_fb), plcp_fragment_len,
+- rate_fb);
++ rate_fb->hw_value);
+
+ /* PHY TX Control word */
+ if (rate_ofdm)
+@@ -310,7 +312,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
+ int rts_rate_ofdm;
+ int rts_rate_fb_ofdm;
+
+- rts_rate = txctl->rts_cts_rate;
++ rts_rate = txctl->rts_cts_rate->hw_value;
+ rts_rate_ofdm = b43legacy_is_ofdm_rate(rts_rate);
+ rts_rate_fb = b43legacy_calc_fallback_rate(rts_rate);
+ rts_rate_fb_ofdm = b43legacy_is_ofdm_rate(rts_rate_fb);
+@@ -536,19 +538,24 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
+ (phystat3 & B43legacy_RX_PHYST3_TRSTATE));
+ status.noise = dev->stats.link_noise;
+ status.signal = (jssi * 100) / B43legacy_RX_MAX_SSI;
++ /* change to support A PHY */
+ if (phystat0 & B43legacy_RX_PHYST0_OFDM)
+- status.rate = b43legacy_plcp_get_bitrate_ofdm(plcp);
++ status.rate_idx = b43legacy_plcp_get_bitrate_idx_ofdm(plcp, false);
+ else
+- status.rate = b43legacy_plcp_get_bitrate_cck(plcp);
++ status.rate_idx = b43legacy_plcp_get_bitrate_idx_cck(plcp);
+ status.antenna = !!(phystat0 & B43legacy_RX_PHYST0_ANT);
+
+ /*
+- * If monitors are present get full 64-bit timestamp. This
+- * code assumes we get to process the packet within 16 bits
+- * of timestamp, i.e. about 65 milliseconds after the PHY
+- * received the first symbol.
++ * All frames on monitor interfaces and beacons always need a full
++ * 64-bit timestamp. Monitor interfaces need it for diagnostic
++ * purposes and beacons for IBSS merging.
++ * This code assumes we get to process the packet within 16 bits
++ * of timestamp, i.e. about 65 milliseconds after the PHY received
++ * the first symbol.
+ */
+- if (dev->wl->radiotap_enabled) {
++ if (((fctl & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE))
++ == (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON)) ||
++ dev->wl->radiotap_enabled) {
+ u16 low_mactime_now;
+
+ b43legacy_tsf_read(dev, &status.mactime);
+@@ -564,14 +571,9 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
+ B43legacy_RX_CHAN_ID_SHIFT;
+ switch (chanstat & B43legacy_RX_CHAN_PHYTYPE) {
+ case B43legacy_PHYTYPE_B:
+- status.phymode = MODE_IEEE80211B;
+- status.freq = chanid + 2400;
+- status.channel = b43legacy_freq_to_channel_bg(chanid + 2400);
+- break;
+ case B43legacy_PHYTYPE_G:
+- status.phymode = MODE_IEEE80211G;
++ status.band = IEEE80211_BAND_2GHZ;
+ status.freq = chanid + 2400;
+- status.channel = b43legacy_freq_to_channel_bg(chanid + 2400);
+ break;
+ default:
+ b43legacywarn(dev->wl, "Unexpected value for chanstat (0x%X)\n",
+diff --git a/drivers/net/wireless/bcm43xx/Kconfig b/drivers/net/wireless/bcm43xx/Kconfig
+deleted file mode 100644
+index afb8f43..0000000
+--- a/drivers/net/wireless/bcm43xx/Kconfig
++++ /dev/null
+@@ -1,70 +0,0 @@
+-config BCM43XX
+- tristate "Broadcom BCM43xx wireless support (DEPRECATED)"
+- depends on PCI && IEEE80211 && IEEE80211_SOFTMAC && WLAN_80211 && (!SSB_B43_PCI_BRIDGE || SSB != y) && EXPERIMENTAL
+- select WIRELESS_EXT
+- select FW_LOADER
+- select HW_RANDOM
+- ---help---
+- This is an experimental driver for the Broadcom 43xx wireless
+- chip, found in the Apple Airport Extreme and various other
+- devices. This driver is deprecated and will be removed
+- from the kernel in the near future. It has been replaced
+- by the b43 and b43legacy drivers.
+-
+-config BCM43XX_DEBUG
+- bool "Broadcom BCM43xx debugging (RECOMMENDED)"
+- depends on BCM43XX
+- default y
+- ---help---
+- Broadcom 43xx debugging messages.
+- Say Y, because the driver is still very experimental and
+- this will help you get it running.
+-
+-config BCM43XX_DMA
+- bool
+- depends on BCM43XX
+-
+-config BCM43XX_PIO
+- bool
+- depends on BCM43XX
+-
+-choice
+- prompt "BCM43xx data transfer mode"
+- depends on BCM43XX
+- default BCM43XX_DMA_AND_PIO_MODE
+-
+-config BCM43XX_DMA_AND_PIO_MODE
+- bool "DMA + PIO"
+- select BCM43XX_DMA
+- select BCM43XX_PIO
+- ---help---
+- Include both, Direct Memory Access (DMA) and Programmed I/O (PIO)
+- data transfer modes.
+- The actually used mode is selectable through the module
+- parameter "pio". If the module parameter is pio=0, DMA is used.
+- Otherwise PIO is used. DMA is default.
+-
+- If unsure, choose this option.
+-
+-config BCM43XX_DMA_MODE
+- bool "DMA (Direct Memory Access) only"
+- select BCM43XX_DMA
+- ---help---
+- Only include Direct Memory Access (DMA).
+- This reduces the size of the driver module, by omitting the PIO code.
+-
+-config BCM43XX_PIO_MODE
+- bool "PIO (Programmed I/O) only"
+- select BCM43XX_PIO
+- ---help---
+- Only include Programmed I/O (PIO).
+- This reduces the size of the driver module, by omitting the DMA code.
+- Please note that PIO transfers are slow (compared to DMA).
+-
+- Also note that not all devices of the 43xx series support PIO.
+- The 4306 (Apple Airport Extreme and others) supports PIO, while
+- the 4318 is known to _not_ support PIO.
+-
+- Only use PIO, if DMA does not work for you.
+-
+-endchoice
+diff --git a/drivers/net/wireless/bcm43xx/Makefile b/drivers/net/wireless/bcm43xx/Makefile
+deleted file mode 100644
+index bb5220c..0000000
+--- a/drivers/net/wireless/bcm43xx/Makefile
++++ /dev/null
+@@ -1,12 +0,0 @@
+-obj-$(CONFIG_BCM43XX) += bcm43xx.o
+-bcm43xx-obj-$(CONFIG_BCM43XX_DEBUG) += bcm43xx_debugfs.o
+-
+-bcm43xx-obj-$(CONFIG_BCM43XX_DMA) += bcm43xx_dma.o
+-bcm43xx-obj-$(CONFIG_BCM43XX_PIO) += bcm43xx_pio.o
+-
+-bcm43xx-objs := bcm43xx_main.o bcm43xx_ilt.o \
+- bcm43xx_radio.o bcm43xx_phy.o \
+- bcm43xx_power.o bcm43xx_wx.o \
+- bcm43xx_leds.o bcm43xx_ethtool.o \
+- bcm43xx_xmit.o bcm43xx_sysfs.o \
+- $(bcm43xx-obj-y)
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
+deleted file mode 100644
+index 2ebd2ed..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
++++ /dev/null
+@@ -1,997 +0,0 @@
+-#ifndef BCM43xx_H_
+-#define BCM43xx_H_
+-
+-#include <linux/hw_random.h>
+-#include <linux/version.h>
+-#include <linux/kernel.h>
+-#include <linux/spinlock.h>
+-#include <linux/interrupt.h>
+-#include <linux/stringify.h>
+-#include <linux/pci.h>
+-#include <net/ieee80211.h>
+-#include <net/ieee80211softmac.h>
+-#include <asm/atomic.h>
+-#include <asm/io.h>
+-
+-
+-#include "bcm43xx_debugfs.h"
+-#include "bcm43xx_leds.h"
+-
+-
+-#define PFX KBUILD_MODNAME ": "
+-
+-#define BCM43xx_SWITCH_CORE_MAX_RETRIES 50
+-#define BCM43xx_IRQWAIT_MAX_RETRIES 100
+-
+-#define BCM43xx_IO_SIZE 8192
+-
+-/* Active Core PCI Configuration Register. */
+-#define BCM43xx_PCICFG_ACTIVE_CORE 0x80
+-/* SPROM control register. */
+-#define BCM43xx_PCICFG_SPROMCTL 0x88
+-/* Interrupt Control PCI Configuration Register. (Only on PCI cores with rev >= 6) */
+-#define BCM43xx_PCICFG_ICR 0x94
+-
+-/* MMIO offsets */
+-#define BCM43xx_MMIO_DMA0_REASON 0x20
+-#define BCM43xx_MMIO_DMA0_IRQ_MASK 0x24
+-#define BCM43xx_MMIO_DMA1_REASON 0x28
+-#define BCM43xx_MMIO_DMA1_IRQ_MASK 0x2C
+-#define BCM43xx_MMIO_DMA2_REASON 0x30
+-#define BCM43xx_MMIO_DMA2_IRQ_MASK 0x34
+-#define BCM43xx_MMIO_DMA3_REASON 0x38
+-#define BCM43xx_MMIO_DMA3_IRQ_MASK 0x3C
+-#define BCM43xx_MMIO_DMA4_REASON 0x40
+-#define BCM43xx_MMIO_DMA4_IRQ_MASK 0x44
+-#define BCM43xx_MMIO_DMA5_REASON 0x48
+-#define BCM43xx_MMIO_DMA5_IRQ_MASK 0x4C
+-#define BCM43xx_MMIO_STATUS_BITFIELD 0x120
+-#define BCM43xx_MMIO_STATUS2_BITFIELD 0x124
+-#define BCM43xx_MMIO_GEN_IRQ_REASON 0x128
+-#define BCM43xx_MMIO_GEN_IRQ_MASK 0x12C
+-#define BCM43xx_MMIO_RAM_CONTROL 0x130
+-#define BCM43xx_MMIO_RAM_DATA 0x134
+-#define BCM43xx_MMIO_PS_STATUS 0x140
+-#define BCM43xx_MMIO_RADIO_HWENABLED_HI 0x158
+-#define BCM43xx_MMIO_SHM_CONTROL 0x160
+-#define BCM43xx_MMIO_SHM_DATA 0x164
+-#define BCM43xx_MMIO_SHM_DATA_UNALIGNED 0x166
+-#define BCM43xx_MMIO_XMITSTAT_0 0x170
+-#define BCM43xx_MMIO_XMITSTAT_1 0x174
+-#define BCM43xx_MMIO_REV3PLUS_TSF_LOW 0x180 /* core rev >= 3 only */
+-#define BCM43xx_MMIO_REV3PLUS_TSF_HIGH 0x184 /* core rev >= 3 only */
+-
+-/* 32-bit DMA */
+-#define BCM43xx_MMIO_DMA32_BASE0 0x200
+-#define BCM43xx_MMIO_DMA32_BASE1 0x220
+-#define BCM43xx_MMIO_DMA32_BASE2 0x240
+-#define BCM43xx_MMIO_DMA32_BASE3 0x260
+-#define BCM43xx_MMIO_DMA32_BASE4 0x280
+-#define BCM43xx_MMIO_DMA32_BASE5 0x2A0
+-/* 64-bit DMA */
+-#define BCM43xx_MMIO_DMA64_BASE0 0x200
+-#define BCM43xx_MMIO_DMA64_BASE1 0x240
+-#define BCM43xx_MMIO_DMA64_BASE2 0x280
+-#define BCM43xx_MMIO_DMA64_BASE3 0x2C0
+-#define BCM43xx_MMIO_DMA64_BASE4 0x300
+-#define BCM43xx_MMIO_DMA64_BASE5 0x340
+-/* PIO */
+-#define BCM43xx_MMIO_PIO1_BASE 0x300
+-#define BCM43xx_MMIO_PIO2_BASE 0x310
+-#define BCM43xx_MMIO_PIO3_BASE 0x320
+-#define BCM43xx_MMIO_PIO4_BASE 0x330
+-
+-#define BCM43xx_MMIO_PHY_VER 0x3E0
+-#define BCM43xx_MMIO_PHY_RADIO 0x3E2
+-#define BCM43xx_MMIO_ANTENNA 0x3E8
+-#define BCM43xx_MMIO_CHANNEL 0x3F0
+-#define BCM43xx_MMIO_CHANNEL_EXT 0x3F4
+-#define BCM43xx_MMIO_RADIO_CONTROL 0x3F6
+-#define BCM43xx_MMIO_RADIO_DATA_HIGH 0x3F8
+-#define BCM43xx_MMIO_RADIO_DATA_LOW 0x3FA
+-#define BCM43xx_MMIO_PHY_CONTROL 0x3FC
+-#define BCM43xx_MMIO_PHY_DATA 0x3FE
+-#define BCM43xx_MMIO_MACFILTER_CONTROL 0x420
+-#define BCM43xx_MMIO_MACFILTER_DATA 0x422
+-#define BCM43xx_MMIO_RADIO_HWENABLED_LO 0x49A
+-#define BCM43xx_MMIO_GPIO_CONTROL 0x49C
+-#define BCM43xx_MMIO_GPIO_MASK 0x49E
+-#define BCM43xx_MMIO_TSF_0 0x632 /* core rev < 3 only */
+-#define BCM43xx_MMIO_TSF_1 0x634 /* core rev < 3 only */
+-#define BCM43xx_MMIO_TSF_2 0x636 /* core rev < 3 only */
+-#define BCM43xx_MMIO_TSF_3 0x638 /* core rev < 3 only */
+-#define BCM43xx_MMIO_RNG 0x65A
+-#define BCM43xx_MMIO_POWERUP_DELAY 0x6A8
+-
+-/* SPROM offsets. */
+-#define BCM43xx_SPROM_BASE 0x1000
+-#define BCM43xx_SPROM_BOARDFLAGS2 0x1c
+-#define BCM43xx_SPROM_IL0MACADDR 0x24
+-#define BCM43xx_SPROM_ET0MACADDR 0x27
+-#define BCM43xx_SPROM_ET1MACADDR 0x2a
+-#define BCM43xx_SPROM_ETHPHY 0x2d
+-#define BCM43xx_SPROM_BOARDREV 0x2e
+-#define BCM43xx_SPROM_PA0B0 0x2f
+-#define BCM43xx_SPROM_PA0B1 0x30
+-#define BCM43xx_SPROM_PA0B2 0x31
+-#define BCM43xx_SPROM_WL0GPIO0 0x32
+-#define BCM43xx_SPROM_WL0GPIO2 0x33
+-#define BCM43xx_SPROM_MAXPWR 0x34
+-#define BCM43xx_SPROM_PA1B0 0x35
+-#define BCM43xx_SPROM_PA1B1 0x36
+-#define BCM43xx_SPROM_PA1B2 0x37
+-#define BCM43xx_SPROM_IDL_TSSI_TGT 0x38
+-#define BCM43xx_SPROM_BOARDFLAGS 0x39
+-#define BCM43xx_SPROM_ANTENNA_GAIN 0x3a
+-#define BCM43xx_SPROM_VERSION 0x3f
+-
+-/* BCM43xx_SPROM_BOARDFLAGS values */
+-#define BCM43xx_BFL_BTCOEXIST 0x0001 /* implements Bluetooth coexistance */
+-#define BCM43xx_BFL_PACTRL 0x0002 /* GPIO 9 controlling the PA */
+-#define BCM43xx_BFL_AIRLINEMODE 0x0004 /* implements GPIO 13 radio disable indication */
+-#define BCM43xx_BFL_RSSI 0x0008 /* software calculates nrssi slope. */
+-#define BCM43xx_BFL_ENETSPI 0x0010 /* has ephy roboswitch spi */
+-#define BCM43xx_BFL_XTAL_NOSLOW 0x0020 /* no slow clock available */
+-#define BCM43xx_BFL_CCKHIPWR 0x0040 /* can do high power CCK transmission */
+-#define BCM43xx_BFL_ENETADM 0x0080 /* has ADMtek switch */
+-#define BCM43xx_BFL_ENETVLAN 0x0100 /* can do vlan */
+-#define BCM43xx_BFL_AFTERBURNER 0x0200 /* supports Afterburner mode */
+-#define BCM43xx_BFL_NOPCI 0x0400 /* leaves PCI floating */
+-#define BCM43xx_BFL_FEM 0x0800 /* supports the Front End Module */
+-#define BCM43xx_BFL_EXTLNA 0x1000 /* has an external LNA */
+-#define BCM43xx_BFL_HGPA 0x2000 /* had high gain PA */
+-#define BCM43xx_BFL_BTCMOD 0x4000 /* BFL_BTCOEXIST is given in alternate GPIOs */
+-#define BCM43xx_BFL_ALTIQ 0x8000 /* alternate I/Q settings */
+-
+-/* GPIO register offset, in both ChipCommon and PCI core. */
+-#define BCM43xx_GPIO_CONTROL 0x6c
+-
+-/* SHM Routing */
+-#define BCM43xx_SHM_SHARED 0x0001
+-#define BCM43xx_SHM_WIRELESS 0x0002
+-#define BCM43xx_SHM_PCM 0x0003
+-#define BCM43xx_SHM_HWMAC 0x0004
+-#define BCM43xx_SHM_UCODE 0x0300
+-
+-/* MacFilter offsets. */
+-#define BCM43xx_MACFILTER_SELF 0x0000
+-#define BCM43xx_MACFILTER_ASSOC 0x0003
+-
+-/* Chipcommon registers. */
+-#define BCM43xx_CHIPCOMMON_CAPABILITIES 0x04
+-#define BCM43xx_CHIPCOMMON_CTL 0x28
+-#define BCM43xx_CHIPCOMMON_PLLONDELAY 0xB0
+-#define BCM43xx_CHIPCOMMON_FREFSELDELAY 0xB4
+-#define BCM43xx_CHIPCOMMON_SLOWCLKCTL 0xB8
+-#define BCM43xx_CHIPCOMMON_SYSCLKCTL 0xC0
+-
+-/* PCI core specific registers. */
+-#define BCM43xx_PCICORE_BCAST_ADDR 0x50
+-#define BCM43xx_PCICORE_BCAST_DATA 0x54
+-#define BCM43xx_PCICORE_SBTOPCI2 0x108
+-
+-/* SBTOPCI2 values. */
+-#define BCM43xx_SBTOPCI2_PREFETCH 0x4
+-#define BCM43xx_SBTOPCI2_BURST 0x8
+-#define BCM43xx_SBTOPCI2_MEMREAD_MULTI 0x20
+-
+-/* PCI-E core registers. */
+-#define BCM43xx_PCIECORE_REG_ADDR 0x0130
+-#define BCM43xx_PCIECORE_REG_DATA 0x0134
+-#define BCM43xx_PCIECORE_MDIO_CTL 0x0128
+-#define BCM43xx_PCIECORE_MDIO_DATA 0x012C
+-
+-/* PCI-E registers. */
+-#define BCM43xx_PCIE_TLP_WORKAROUND 0x0004
+-#define BCM43xx_PCIE_DLLP_LINKCTL 0x0100
+-
+-/* PCI-E MDIO bits. */
+-#define BCM43xx_PCIE_MDIO_ST 0x40000000
+-#define BCM43xx_PCIE_MDIO_WT 0x10000000
+-#define BCM43xx_PCIE_MDIO_DEV 22
+-#define BCM43xx_PCIE_MDIO_REG 18
+-#define BCM43xx_PCIE_MDIO_TA 0x00020000
+-#define BCM43xx_PCIE_MDIO_TC 0x0100
+-
+-/* MDIO devices. */
+-#define BCM43xx_MDIO_SERDES_RX 0x1F
+-
+-/* SERDES RX registers. */
+-#define BCM43xx_SERDES_RXTIMER 0x2
+-#define BCM43xx_SERDES_CDR 0x6
+-#define BCM43xx_SERDES_CDR_BW 0x7
+-
+-/* Chipcommon capabilities. */
+-#define BCM43xx_CAPABILITIES_PCTL 0x00040000
+-#define BCM43xx_CAPABILITIES_PLLMASK 0x00030000
+-#define BCM43xx_CAPABILITIES_PLLSHIFT 16
+-#define BCM43xx_CAPABILITIES_FLASHMASK 0x00000700
+-#define BCM43xx_CAPABILITIES_FLASHSHIFT 8
+-#define BCM43xx_CAPABILITIES_EXTBUSPRESENT 0x00000040
+-#define BCM43xx_CAPABILITIES_UARTGPIO 0x00000020
+-#define BCM43xx_CAPABILITIES_UARTCLOCKMASK 0x00000018
+-#define BCM43xx_CAPABILITIES_UARTCLOCKSHIFT 3
+-#define BCM43xx_CAPABILITIES_MIPSBIGENDIAN 0x00000004
+-#define BCM43xx_CAPABILITIES_NRUARTSMASK 0x00000003
+-
+-/* PowerControl */
+-#define BCM43xx_PCTL_IN 0xB0
+-#define BCM43xx_PCTL_OUT 0xB4
+-#define BCM43xx_PCTL_OUTENABLE 0xB8
+-#define BCM43xx_PCTL_XTAL_POWERUP 0x40
+-#define BCM43xx_PCTL_PLL_POWERDOWN 0x80
+-
+-/* PowerControl Clock Modes */
+-#define BCM43xx_PCTL_CLK_FAST 0x00
+-#define BCM43xx_PCTL_CLK_SLOW 0x01
+-#define BCM43xx_PCTL_CLK_DYNAMIC 0x02
+-
+-#define BCM43xx_PCTL_FORCE_SLOW 0x0800
+-#define BCM43xx_PCTL_FORCE_PLL 0x1000
+-#define BCM43xx_PCTL_DYN_XTAL 0x2000
+-
+-/* COREIDs */
+-#define BCM43xx_COREID_CHIPCOMMON 0x800
+-#define BCM43xx_COREID_ILINE20 0x801
+-#define BCM43xx_COREID_SDRAM 0x803
+-#define BCM43xx_COREID_PCI 0x804
+-#define BCM43xx_COREID_MIPS 0x805
+-#define BCM43xx_COREID_ETHERNET 0x806
+-#define BCM43xx_COREID_V90 0x807
+-#define BCM43xx_COREID_USB11_HOSTDEV 0x80a
+-#define BCM43xx_COREID_IPSEC 0x80b
+-#define BCM43xx_COREID_PCMCIA 0x80d
+-#define BCM43xx_COREID_EXT_IF 0x80f
+-#define BCM43xx_COREID_80211 0x812
+-#define BCM43xx_COREID_MIPS_3302 0x816
+-#define BCM43xx_COREID_USB11_HOST 0x817
+-#define BCM43xx_COREID_USB11_DEV 0x818
+-#define BCM43xx_COREID_USB20_HOST 0x819
+-#define BCM43xx_COREID_USB20_DEV 0x81a
+-#define BCM43xx_COREID_SDIO_HOST 0x81b
+-#define BCM43xx_COREID_PCIE 0x820
+-
+-/* Core Information Registers */
+-#define BCM43xx_CIR_BASE 0xf00
+-#define BCM43xx_CIR_SBTPSFLAG (BCM43xx_CIR_BASE + 0x18)
+-#define BCM43xx_CIR_SBIMSTATE (BCM43xx_CIR_BASE + 0x90)
+-#define BCM43xx_CIR_SBINTVEC (BCM43xx_CIR_BASE + 0x94)
+-#define BCM43xx_CIR_SBTMSTATELOW (BCM43xx_CIR_BASE + 0x98)
+-#define BCM43xx_CIR_SBTMSTATEHIGH (BCM43xx_CIR_BASE + 0x9c)
+-#define BCM43xx_CIR_SBIMCONFIGLOW (BCM43xx_CIR_BASE + 0xa8)
+-#define BCM43xx_CIR_SB_ID_HI (BCM43xx_CIR_BASE + 0xfc)
+-
+-/* Mask to get the Backplane Flag Number from SBTPSFLAG. */
+-#define BCM43xx_BACKPLANE_FLAG_NR_MASK 0x3f
+-
+-/* SBIMCONFIGLOW values/masks. */
+-#define BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK 0x00000007
+-#define BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT 0
+-#define BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK 0x00000070
+-#define BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT 4
+-#define BCM43xx_SBIMCONFIGLOW_CONNID_MASK 0x00ff0000
+-#define BCM43xx_SBIMCONFIGLOW_CONNID_SHIFT 16
+-
+-/* sbtmstatelow state flags */
+-#define BCM43xx_SBTMSTATELOW_RESET 0x01
+-#define BCM43xx_SBTMSTATELOW_REJECT 0x02
+-#define BCM43xx_SBTMSTATELOW_CLOCK 0x10000
+-#define BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK 0x20000
+-#define BCM43xx_SBTMSTATELOW_G_MODE_ENABLE 0x20000000
+-
+-/* sbtmstatehigh state flags */
+-#define BCM43xx_SBTMSTATEHIGH_SERROR 0x00000001
+-#define BCM43xx_SBTMSTATEHIGH_BUSY 0x00000004
+-#define BCM43xx_SBTMSTATEHIGH_TIMEOUT 0x00000020
+-#define BCM43xx_SBTMSTATEHIGH_G_PHY_AVAIL 0x00010000
+-#define BCM43xx_SBTMSTATEHIGH_A_PHY_AVAIL 0x00020000
+-#define BCM43xx_SBTMSTATEHIGH_COREFLAGS 0x1FFF0000
+-#define BCM43xx_SBTMSTATEHIGH_DMA64BIT 0x10000000
+-#define BCM43xx_SBTMSTATEHIGH_GATEDCLK 0x20000000
+-#define BCM43xx_SBTMSTATEHIGH_BISTFAILED 0x40000000
+-#define BCM43xx_SBTMSTATEHIGH_BISTCOMPLETE 0x80000000
+-
+-/* sbimstate flags */
+-#define BCM43xx_SBIMSTATE_IB_ERROR 0x20000
+-#define BCM43xx_SBIMSTATE_TIMEOUT 0x40000
+-
+-/* PHYVersioning */
+-#define BCM43xx_PHYTYPE_A 0x00
+-#define BCM43xx_PHYTYPE_B 0x01
+-#define BCM43xx_PHYTYPE_G 0x02
+-
+-/* PHYRegisters */
+-#define BCM43xx_PHY_ILT_A_CTRL 0x0072
+-#define BCM43xx_PHY_ILT_A_DATA1 0x0073
+-#define BCM43xx_PHY_ILT_A_DATA2 0x0074
+-#define BCM43xx_PHY_G_LO_CONTROL 0x0810
+-#define BCM43xx_PHY_ILT_G_CTRL 0x0472
+-#define BCM43xx_PHY_ILT_G_DATA1 0x0473
+-#define BCM43xx_PHY_ILT_G_DATA2 0x0474
+-#define BCM43xx_PHY_A_PCTL 0x007B
+-#define BCM43xx_PHY_G_PCTL 0x0029
+-#define BCM43xx_PHY_A_CRS 0x0029
+-#define BCM43xx_PHY_RADIO_BITFIELD 0x0401
+-#define BCM43xx_PHY_G_CRS 0x0429
+-#define BCM43xx_PHY_NRSSILT_CTRL 0x0803
+-#define BCM43xx_PHY_NRSSILT_DATA 0x0804
+-
+-/* RadioRegisters */
+-#define BCM43xx_RADIOCTL_ID 0x01
+-
+-/* StatusBitField */
+-#define BCM43xx_SBF_MAC_ENABLED 0x00000001
+-#define BCM43xx_SBF_2 0x00000002 /*FIXME: fix name*/
+-#define BCM43xx_SBF_CORE_READY 0x00000004
+-#define BCM43xx_SBF_400 0x00000400 /*FIXME: fix name*/
+-#define BCM43xx_SBF_4000 0x00004000 /*FIXME: fix name*/
+-#define BCM43xx_SBF_8000 0x00008000 /*FIXME: fix name*/
+-#define BCM43xx_SBF_XFER_REG_BYTESWAP 0x00010000
+-#define BCM43xx_SBF_MODE_NOTADHOC 0x00020000
+-#define BCM43xx_SBF_MODE_AP 0x00040000
+-#define BCM43xx_SBF_RADIOREG_LOCK 0x00080000
+-#define BCM43xx_SBF_MODE_MONITOR 0x00400000
+-#define BCM43xx_SBF_MODE_PROMISC 0x01000000
+-#define BCM43xx_SBF_PS1 0x02000000
+-#define BCM43xx_SBF_PS2 0x04000000
+-#define BCM43xx_SBF_NO_SSID_BCAST 0x08000000
+-#define BCM43xx_SBF_TIME_UPDATE 0x10000000
+-#define BCM43xx_SBF_MODE_G 0x80000000
+-
+-/* Microcode */
+-#define BCM43xx_UCODE_REVISION 0x0000
+-#define BCM43xx_UCODE_PATCHLEVEL 0x0002
+-#define BCM43xx_UCODE_DATE 0x0004
+-#define BCM43xx_UCODE_TIME 0x0006
+-#define BCM43xx_UCODE_STATUS 0x0040
+-
+-/* MicrocodeFlagsBitfield (addr + lo-word values?)*/
+-#define BCM43xx_UCODEFLAGS_OFFSET 0x005E
+-
+-#define BCM43xx_UCODEFLAG_AUTODIV 0x0001
+-#define BCM43xx_UCODEFLAG_UNKBGPHY 0x0002
+-#define BCM43xx_UCODEFLAG_UNKBPHY 0x0004
+-#define BCM43xx_UCODEFLAG_UNKGPHY 0x0020
+-#define BCM43xx_UCODEFLAG_UNKPACTRL 0x0040
+-#define BCM43xx_UCODEFLAG_JAPAN 0x0080
+-
+-/* Hardware Radio Enable masks */
+-#define BCM43xx_MMIO_RADIO_HWENABLED_HI_MASK (1 << 16)
+-#define BCM43xx_MMIO_RADIO_HWENABLED_LO_MASK (1 << 4)
+-
+-/* Generic-Interrupt reasons. */
+-#define BCM43xx_IRQ_READY (1 << 0)
+-#define BCM43xx_IRQ_BEACON (1 << 1)
+-#define BCM43xx_IRQ_PS (1 << 2)
+-#define BCM43xx_IRQ_REG124 (1 << 5)
+-#define BCM43xx_IRQ_PMQ (1 << 6)
+-#define BCM43xx_IRQ_PIO_WORKAROUND (1 << 8)
+-#define BCM43xx_IRQ_XMIT_ERROR (1 << 11)
+-#define BCM43xx_IRQ_RX (1 << 15)
+-#define BCM43xx_IRQ_SCAN (1 << 16)
+-#define BCM43xx_IRQ_NOISE (1 << 18)
+-#define BCM43xx_IRQ_XMIT_STATUS (1 << 29)
+-
+-#define BCM43xx_IRQ_ALL 0xffffffff
+-#define BCM43xx_IRQ_INITIAL (BCM43xx_IRQ_PS | \
+- BCM43xx_IRQ_REG124 | \
+- BCM43xx_IRQ_PMQ | \
+- BCM43xx_IRQ_XMIT_ERROR | \
+- BCM43xx_IRQ_RX | \
+- BCM43xx_IRQ_SCAN | \
+- BCM43xx_IRQ_NOISE | \
+- BCM43xx_IRQ_XMIT_STATUS)
+-
+-
+-/* Initial default iw_mode */
+-#define BCM43xx_INITIAL_IWMODE IW_MODE_INFRA
+-
+-/* Bus type PCI. */
+-#define BCM43xx_BUSTYPE_PCI 0
+-/* Bus type Silicone Backplane Bus. */
+-#define BCM43xx_BUSTYPE_SB 1
+-/* Bus type PCMCIA. */
+-#define BCM43xx_BUSTYPE_PCMCIA 2
+-
+-/* Threshold values. */
+-#define BCM43xx_MIN_RTS_THRESHOLD 1U
+-#define BCM43xx_MAX_RTS_THRESHOLD 2304U
+-#define BCM43xx_DEFAULT_RTS_THRESHOLD BCM43xx_MAX_RTS_THRESHOLD
+-
+-#define BCM43xx_DEFAULT_SHORT_RETRY_LIMIT 7
+-#define BCM43xx_DEFAULT_LONG_RETRY_LIMIT 4
+-
+-/* FIXME: the next line is a guess as to what the maximum RSSI value might be */
+-#define RX_RSSI_MAX 60
+-
+-/* Max size of a security key */
+-#define BCM43xx_SEC_KEYSIZE 16
+-/* Security algorithms. */
+-enum {
+- BCM43xx_SEC_ALGO_NONE = 0, /* unencrypted, as of TX header. */
+- BCM43xx_SEC_ALGO_WEP,
+- BCM43xx_SEC_ALGO_UNKNOWN,
+- BCM43xx_SEC_ALGO_AES,
+- BCM43xx_SEC_ALGO_WEP104,
+- BCM43xx_SEC_ALGO_TKIP,
+-};
+-
+-#ifdef assert
+-# undef assert
+-#endif
+-#ifdef CONFIG_BCM43XX_DEBUG
+-#define assert(expr) \
+- do { \
+- if (unlikely(!(expr))) { \
+- printk(KERN_ERR PFX "ASSERTION FAILED (%s) at: %s:%d:%s()\n", \
+- #expr, __FILE__, __LINE__, __FUNCTION__); \
+- } \
+- } while (0)
+-#else
+-#define assert(expr) do { /* nothing */ } while (0)
+-#endif
+-
+-/* rate limited printk(). */
+-#ifdef printkl
+-# undef printkl
+-#endif
+-#define printkl(f, x...) do { if (printk_ratelimit()) printk(f ,##x); } while (0)
+-/* rate limited printk() for debugging */
+-#ifdef dprintkl
+-# undef dprintkl
+-#endif
+-#ifdef CONFIG_BCM43XX_DEBUG
+-# define dprintkl printkl
+-#else
+-# define dprintkl(f, x...) do { /* nothing */ } while (0)
+-#endif
+-
+-/* Helper macro for if branches.
+- * An if branch marked with this macro is only taken in DEBUG mode.
+- * Example:
+- * if (DEBUG_ONLY(foo == bar)) {
+- * do something
+- * }
+- * In DEBUG mode, the branch will be taken if (foo == bar).
+- * In non-DEBUG mode, the branch will never be taken.
+- */
+-#ifdef DEBUG_ONLY
+-# undef DEBUG_ONLY
+-#endif
+-#ifdef CONFIG_BCM43XX_DEBUG
+-# define DEBUG_ONLY(x) (x)
+-#else
+-# define DEBUG_ONLY(x) 0
+-#endif
+-
+-/* debugging printk() */
+-#ifdef dprintk
+-# undef dprintk
+-#endif
+-#ifdef CONFIG_BCM43XX_DEBUG
+-# define dprintk(f, x...) do { printk(f ,##x); } while (0)
+-#else
+-# define dprintk(f, x...) do { /* nothing */ } while (0)
+-#endif
+-
+-
+-struct net_device;
+-struct pci_dev;
+-struct bcm43xx_dmaring;
+-struct bcm43xx_pioqueue;
+-
+-struct bcm43xx_initval {
+- __be16 offset;
+- __be16 size;
+- __be32 value;
+-} __attribute__((__packed__));
+-
+-/* Values for bcm430x_sprominfo.locale */
+-enum {
+- BCM43xx_LOCALE_WORLD = 0,
+- BCM43xx_LOCALE_THAILAND,
+- BCM43xx_LOCALE_ISRAEL,
+- BCM43xx_LOCALE_JORDAN,
+- BCM43xx_LOCALE_CHINA,
+- BCM43xx_LOCALE_JAPAN,
+- BCM43xx_LOCALE_USA_CANADA_ANZ,
+- BCM43xx_LOCALE_EUROPE,
+- BCM43xx_LOCALE_USA_LOW,
+- BCM43xx_LOCALE_JAPAN_HIGH,
+- BCM43xx_LOCALE_ALL,
+- BCM43xx_LOCALE_NONE,
+-};
+-
+-#define BCM43xx_SPROM_SIZE 64 /* in 16-bit words. */
+-struct bcm43xx_sprominfo {
+- u16 boardflags2;
+- u8 il0macaddr[6];
+- u8 et0macaddr[6];
+- u8 et1macaddr[6];
+- u8 et0phyaddr:5;
+- u8 et1phyaddr:5;
+- u8 boardrev;
+- u8 locale:4;
+- u8 antennas_aphy:2;
+- u8 antennas_bgphy:2;
+- u16 pa0b0;
+- u16 pa0b1;
+- u16 pa0b2;
+- u8 wl0gpio0;
+- u8 wl0gpio1;
+- u8 wl0gpio2;
+- u8 wl0gpio3;
+- u8 maxpower_aphy;
+- u8 maxpower_bgphy;
+- u16 pa1b0;
+- u16 pa1b1;
+- u16 pa1b2;
+- u8 idle_tssi_tgt_aphy;
+- u8 idle_tssi_tgt_bgphy;
+- u16 boardflags;
+- u16 antennagain_aphy;
+- u16 antennagain_bgphy;
+-};
+-
+-/* Value pair to measure the LocalOscillator. */
+-struct bcm43xx_lopair {
+- s8 low;
+- s8 high;
+- u8 used:1;
+-};
+-#define BCM43xx_LO_COUNT (14*4)
+-
+-struct bcm43xx_phyinfo {
+- /* Hardware Data */
+- u8 analog;
+- u8 type;
+- u8 rev;
+- u16 antenna_diversity;
+- u16 savedpctlreg;
+- u16 minlowsig[2];
+- u16 minlowsigpos[2];
+- u8 connected:1,
+- calibrated:1,
+- is_locked:1, /* used in bcm43xx_phy_{un}lock() */
+- dyn_tssi_tbl:1; /* used in bcm43xx_phy_init_tssi2dbm_table() */
+- /* LO Measurement Data.
+- * Use bcm43xx_get_lopair() to get a value.
+- */
+- struct bcm43xx_lopair *_lo_pairs;
+-
+- /* TSSI to dBm table in use */
+- const s8 *tssi2dbm;
+- /* idle TSSI value */
+- s8 idle_tssi;
+-
+- /* Values from bcm43xx_calc_loopback_gain() */
+- u16 loopback_gain[2];
+-
+- /* PHY lock for core.rev < 3
+- * This lock is only used by bcm43xx_phy_{un}lock()
+- */
+- spinlock_t lock;
+-
+- /* Firmware. */
+- const struct firmware *ucode;
+- const struct firmware *pcm;
+- const struct firmware *initvals0;
+- const struct firmware *initvals1;
+-};
+-
+-
+-struct bcm43xx_radioinfo {
+- u16 manufact;
+- u16 version;
+- u8 revision;
+-
+- /* Desired TX power in dBm Q5.2 */
+- u16 txpower_desired;
+- /* TX Power control values. */
+- union {
+- /* B/G PHY */
+- struct {
+- u16 baseband_atten;
+- u16 radio_atten;
+- u16 txctl1;
+- u16 txctl2;
+- };
+- /* A PHY */
+- struct {
+- u16 txpwr_offset;
+- };
+- };
+-
+- /* Current Interference Mitigation mode */
+- int interfmode;
+- /* Stack of saved values from the Interference Mitigation code.
+- * Each value in the stack is layed out as follows:
+- * bit 0-11: offset
+- * bit 12-15: register ID
+- * bit 16-32: value
+- * register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT
+- */
+-#define BCM43xx_INTERFSTACK_SIZE 26
+- u32 interfstack[BCM43xx_INTERFSTACK_SIZE];
+-
+- /* Saved values from the NRSSI Slope calculation */
+- s16 nrssi[2];
+- s32 nrssislope;
+- /* In memory nrssi lookup table. */
+- s8 nrssi_lt[64];
+-
+- /* current channel */
+- u8 channel;
+- u8 initial_channel;
+-
+- u16 lofcal;
+-
+- u16 initval;
+-
+- u8 enabled:1;
+- /* ACI (adjacent channel interference) flags. */
+- u8 aci_enable:1,
+- aci_wlan_automatic:1,
+- aci_hw_rssi:1;
+-};
+-
+-/* Data structures for DMA transmission, per 80211 core. */
+-struct bcm43xx_dma {
+- struct bcm43xx_dmaring *tx_ring0;
+- struct bcm43xx_dmaring *tx_ring1;
+- struct bcm43xx_dmaring *tx_ring2;
+- struct bcm43xx_dmaring *tx_ring3;
+- struct bcm43xx_dmaring *tx_ring4;
+- struct bcm43xx_dmaring *tx_ring5;
+-
+- struct bcm43xx_dmaring *rx_ring0;
+- struct bcm43xx_dmaring *rx_ring3; /* only available on core.rev < 5 */
+-};
+-
+-/* Data structures for PIO transmission, per 80211 core. */
+-struct bcm43xx_pio {
+- struct bcm43xx_pioqueue *queue0;
+- struct bcm43xx_pioqueue *queue1;
+- struct bcm43xx_pioqueue *queue2;
+- struct bcm43xx_pioqueue *queue3;
+-};
+-
+-#define BCM43xx_MAX_80211_CORES 2
+-
+-/* Generic information about a core. */
+-struct bcm43xx_coreinfo {
+- u8 available:1,
+- enabled:1,
+- initialized:1;
+- /** core_rev revision number */
+- u8 rev;
+- /** Index number for _switch_core() */
+- u8 index;
+- /** core_id ID number */
+- u16 id;
+- /** Core-specific data. */
+- void *priv;
+-};
+-
+-/* Additional information for each 80211 core. */
+-struct bcm43xx_coreinfo_80211 {
+- /* PHY device. */
+- struct bcm43xx_phyinfo phy;
+- /* Radio device. */
+- struct bcm43xx_radioinfo radio;
+- union {
+- /* DMA context. */
+- struct bcm43xx_dma dma;
+- /* PIO context. */
+- struct bcm43xx_pio pio;
+- };
+-};
+-
+-/* Context information for a noise calculation (Link Quality). */
+-struct bcm43xx_noise_calculation {
+- struct bcm43xx_coreinfo *core_at_start;
+- u8 channel_at_start;
+- u8 calculation_running:1;
+- u8 nr_samples;
+- s8 samples[8][4];
+-};
+-
+-struct bcm43xx_stats {
+- u8 noise;
+- struct iw_statistics wstats;
+- /* Store the last TX/RX times here for updating the leds. */
+- unsigned long last_tx;
+- unsigned long last_rx;
+-};
+-
+-struct bcm43xx_key {
+- u8 enabled:1;
+- u8 algorithm;
+-};
+-
+-/* Driver initialization status. */
+-enum {
+- BCM43xx_STAT_UNINIT, /* Uninitialized. */
+- BCM43xx_STAT_INITIALIZING, /* init_board() in progress. */
+- BCM43xx_STAT_INITIALIZED, /* Fully operational. */
+- BCM43xx_STAT_SHUTTINGDOWN, /* free_board() in progress. */
+- BCM43xx_STAT_RESTARTING, /* controller_restart() called. */
+-};
+-#define bcm43xx_status(bcm) atomic_read(&(bcm)->init_status)
+-#define bcm43xx_set_status(bcm, stat) do { \
+- atomic_set(&(bcm)->init_status, (stat)); \
+- smp_wmb(); \
+- } while (0)
+-
+-/* *** THEORY OF LOCKING ***
+- *
+- * We have two different locks in the bcm43xx driver.
+- * => bcm->mutex: General sleeping mutex. Protects struct bcm43xx_private
+- * and the device registers. This mutex does _not_ protect
+- * against concurrency from the IRQ handler.
+- * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency.
+- *
+- * Please note that, if you only take the irq_lock, you are not protected
+- * against concurrency from the periodic work handlers.
+- * Most times you want to take _both_ locks.
+- */
+-
+-struct bcm43xx_private {
+- struct ieee80211_device *ieee;
+- struct ieee80211softmac_device *softmac;
+-
+- struct net_device *net_dev;
+- struct pci_dev *pci_dev;
+- unsigned int irq;
+-
+- void __iomem *mmio_addr;
+-
+- spinlock_t irq_lock;
+- struct mutex mutex;
+-
+- /* Driver initialization status BCM43xx_STAT_*** */
+- atomic_t init_status;
+-
+- u16 was_initialized:1, /* for PCI suspend/resume. */
+- __using_pio:1, /* Internal, use bcm43xx_using_pio(). */
+- bad_frames_preempt:1, /* Use "Bad Frames Preemption" (default off) */
+- reg124_set_0x4:1, /* Some variable to keep track of IRQ stuff. */
+- short_preamble:1, /* TRUE, if short preamble is enabled. */
+- firmware_norelease:1, /* Do not release the firmware. Used on suspend. */
+- radio_hw_enable:1; /* TRUE if radio is hardware enabled */
+-
+- struct bcm43xx_stats stats;
+-
+- /* Bus type we are connected to.
+- * This is currently always BCM43xx_BUSTYPE_PCI
+- */
+- u8 bustype;
+- u64 dma_mask;
+-
+- u16 board_vendor;
+- u16 board_type;
+- u16 board_revision;
+-
+- u16 chip_id;
+- u8 chip_rev;
+- u8 chip_package;
+-
+- struct bcm43xx_sprominfo sprom;
+-#define BCM43xx_NR_LEDS 4
+- struct bcm43xx_led leds[BCM43xx_NR_LEDS];
+- spinlock_t leds_lock;
+-
+- /* The currently active core. */
+- struct bcm43xx_coreinfo *current_core;
+- struct bcm43xx_coreinfo *active_80211_core;
+- /* coreinfo structs for all possible cores follow.
+- * Note that a core might not exist.
+- * So check the coreinfo flags before using it.
+- */
+- struct bcm43xx_coreinfo core_chipcommon;
+- struct bcm43xx_coreinfo core_pci;
+- struct bcm43xx_coreinfo core_80211[ BCM43xx_MAX_80211_CORES ];
+- /* Additional information, specific to the 80211 cores. */
+- struct bcm43xx_coreinfo_80211 core_80211_ext[ BCM43xx_MAX_80211_CORES ];
+- /* Number of available 80211 cores. */
+- int nr_80211_available;
+-
+- u32 chipcommon_capabilities;
+-
+- /* Reason code of the last interrupt. */
+- u32 irq_reason;
+- u32 dma_reason[6];
+- /* saved irq enable/disable state bitfield. */
+- u32 irq_savedstate;
+- /* Link Quality calculation context. */
+- struct bcm43xx_noise_calculation noisecalc;
+- /* if > 0 MAC is suspended. if == 0 MAC is enabled. */
+- int mac_suspended;
+-
+- /* Threshold values. */
+- //TODO: The RTS thr has to be _used_. Currently, it is only set via WX.
+- u32 rts_threshold;
+-
+- /* Interrupt Service Routine tasklet (bottom-half) */
+- struct tasklet_struct isr_tasklet;
+-
+- /* Periodic tasks */
+- struct delayed_work periodic_work;
+- unsigned int periodic_state;
+-
+- struct work_struct restart_work;
+-
+- /* Informational stuff. */
+- char nick[IW_ESSID_MAX_SIZE + 1];
+-
+- /* encryption/decryption */
+- u16 security_offset;
+- struct bcm43xx_key key[54];
+- u8 default_key_idx;
+-
+- /* Random Number Generator. */
+- struct hwrng rng;
+- char rng_name[20 + 1];
+-
+- /* Debugging stuff follows. */
+-#ifdef CONFIG_BCM43XX_DEBUG
+- struct bcm43xx_dfsentry *dfsentry;
+-#endif
+-};
+-
+-
+-static inline
+-struct bcm43xx_private * bcm43xx_priv(struct net_device *dev)
+-{
+- return ieee80211softmac_priv(dev);
+-}
+-
+-struct device;
+-
+-static inline
+-struct bcm43xx_private * dev_to_bcm(struct device *dev)
+-{
+- struct net_device *net_dev;
+- struct bcm43xx_private *bcm;
+-
+- net_dev = dev_get_drvdata(dev);
+- bcm = bcm43xx_priv(net_dev);
+-
+- return bcm;
+-}
+-
+-
+-/* Helper function, which returns a boolean.
+- * TRUE, if PIO is used; FALSE, if DMA is used.
+- */
+-#if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO)
+-static inline
+-int bcm43xx_using_pio(struct bcm43xx_private *bcm)
+-{
+- return bcm->__using_pio;
+-}
+-#elif defined(CONFIG_BCM43XX_DMA)
+-static inline
+-int bcm43xx_using_pio(struct bcm43xx_private *bcm)
+-{
+- return 0;
+-}
+-#elif defined(CONFIG_BCM43XX_PIO)
+-static inline
+-int bcm43xx_using_pio(struct bcm43xx_private *bcm)
+-{
+- return 1;
+-}
+-#else
+-# error "Using neither DMA nor PIO? Confused..."
+-#endif
+-
+-/* Helper functions to access data structures private to the 80211 cores.
+- * Note that we _must_ have an 80211 core mapped when calling
+- * any of these functions.
+- */
+-static inline
+-struct bcm43xx_coreinfo_80211 *
+-bcm43xx_current_80211_priv(struct bcm43xx_private *bcm)
+-{
+- assert(bcm->current_core->id == BCM43xx_COREID_80211);
+- return bcm->current_core->priv;
+-}
+-static inline
+-struct bcm43xx_pio * bcm43xx_current_pio(struct bcm43xx_private *bcm)
+-{
+- assert(bcm43xx_using_pio(bcm));
+- return &(bcm43xx_current_80211_priv(bcm)->pio);
+-}
+-static inline
+-struct bcm43xx_dma * bcm43xx_current_dma(struct bcm43xx_private *bcm)
+-{
+- assert(!bcm43xx_using_pio(bcm));
+- return &(bcm43xx_current_80211_priv(bcm)->dma);
+-}
+-static inline
+-struct bcm43xx_phyinfo * bcm43xx_current_phy(struct bcm43xx_private *bcm)
+-{
+- return &(bcm43xx_current_80211_priv(bcm)->phy);
+-}
+-static inline
+-struct bcm43xx_radioinfo * bcm43xx_current_radio(struct bcm43xx_private *bcm)
+-{
+- return &(bcm43xx_current_80211_priv(bcm)->radio);
+-}
+-
+-
+-static inline
+-struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy,
+- u16 radio_attenuation,
+- u16 baseband_attenuation)
+-{
+- return phy->_lo_pairs + (radio_attenuation + 14 * (baseband_attenuation / 2));
+-}
+-
+-
+-static inline
+-u16 bcm43xx_read16(struct bcm43xx_private *bcm, u16 offset)
+-{
+- return ioread16(bcm->mmio_addr + offset);
+-}
+-
+-static inline
+-void bcm43xx_write16(struct bcm43xx_private *bcm, u16 offset, u16 value)
+-{
+- iowrite16(value, bcm->mmio_addr + offset);
+-}
+-
+-static inline
+-u32 bcm43xx_read32(struct bcm43xx_private *bcm, u16 offset)
+-{
+- return ioread32(bcm->mmio_addr + offset);
+-}
+-
+-static inline
+-void bcm43xx_write32(struct bcm43xx_private *bcm, u16 offset, u32 value)
+-{
+- iowrite32(value, bcm->mmio_addr + offset);
+-}
+-
+-static inline
+-int bcm43xx_pci_read_config16(struct bcm43xx_private *bcm, int offset, u16 *value)
+-{
+- return pci_read_config_word(bcm->pci_dev, offset, value);
+-}
+-
+-static inline
+-int bcm43xx_pci_read_config32(struct bcm43xx_private *bcm, int offset, u32 *value)
+-{
+- return pci_read_config_dword(bcm->pci_dev, offset, value);
+-}
+-
+-static inline
+-int bcm43xx_pci_write_config16(struct bcm43xx_private *bcm, int offset, u16 value)
+-{
+- return pci_write_config_word(bcm->pci_dev, offset, value);
+-}
+-
+-static inline
+-int bcm43xx_pci_write_config32(struct bcm43xx_private *bcm, int offset, u32 value)
+-{
+- return pci_write_config_dword(bcm->pci_dev, offset, value);
+-}
+-
+-/** Limit a value between two limits */
+-#ifdef limit_value
+-# undef limit_value
+-#endif
+-#define limit_value(value, min, max) \
+- ({ \
+- typeof(value) __value = (value); \
+- typeof(value) __min = (min); \
+- typeof(value) __max = (max); \
+- if (__value < __min) \
+- __value = __min; \
+- else if (__value > __max) \
+- __value = __max; \
+- __value; \
+- })
+-
+-#endif /* BCM43xx_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
+deleted file mode 100644
+index 76e9dd8..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
++++ /dev/null
+@@ -1,556 +0,0 @@
+-/*
+-
+- Broadcom BCM43xx wireless driver
+-
+- debugfs driver debugging code
+-
+- Copyright (c) 2005 Michael Buesch <mbuesch at freenet.de>
+-
+- 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; see the file COPYING. If not, write to
+- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+- Boston, MA 02110-1301, USA.
+-
+-*/
+-
+-
+-
+-#include <linux/fs.h>
+-#include <linux/debugfs.h>
+-#include <linux/slab.h>
+-#include <linux/netdevice.h>
+-#include <linux/pci.h>
+-#include <asm/io.h>
+-
+-#include "bcm43xx.h"
+-#include "bcm43xx_main.h"
+-#include "bcm43xx_debugfs.h"
+-#include "bcm43xx_dma.h"
+-#include "bcm43xx_pio.h"
+-#include "bcm43xx_xmit.h"
+-
+-#define REALLY_BIG_BUFFER_SIZE (1024*256)
+-
+-static struct bcm43xx_debugfs fs;
+-static char really_big_buffer[REALLY_BIG_BUFFER_SIZE];
+-static DECLARE_MUTEX(big_buffer_sem);
+-
+-
+-static ssize_t write_file_dummy(struct file *file, const char __user *buf,
+- size_t count, loff_t *ppos)
+-{
+- return count;
+-}
+-
+-static int open_file_generic(struct inode *inode, struct file *file)
+-{
+- file->private_data = inode->i_private;
+- return 0;
+-}
+-
+-#define fappend(fmt, x...) pos += snprintf(buf + pos, len - pos, fmt , ##x)
+-
+-static ssize_t devinfo_read_file(struct file *file, char __user *userbuf,
+- size_t count, loff_t *ppos)
+-{
+- const size_t len = REALLY_BIG_BUFFER_SIZE;
+-
+- struct bcm43xx_private *bcm = file->private_data;
+- char *buf = really_big_buffer;
+- size_t pos = 0;
+- ssize_t res;
+- struct net_device *net_dev;
+- struct pci_dev *pci_dev;
+- unsigned long flags;
+- u16 tmp16;
+- int i;
+-
+- down(&big_buffer_sem);
+-
+- mutex_lock(&bcm->mutex);
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
+- fappend("Board not initialized.\n");
+- goto out;
+- }
+- net_dev = bcm->net_dev;
+- pci_dev = bcm->pci_dev;
+-
+- /* This is where the information is written to the "devinfo" file */
+- fappend("*** %s devinfo ***\n", net_dev->name);
+- fappend("vendor: 0x%04x device: 0x%04x\n",
+- pci_dev->vendor, pci_dev->device);
+- fappend("subsystem_vendor: 0x%04x subsystem_device: 0x%04x\n",
+- pci_dev->subsystem_vendor, pci_dev->subsystem_device);
+- fappend("IRQ: %d\n", bcm->irq);
+- fappend("mmio_addr: 0x%p\n", bcm->mmio_addr);
+- fappend("chip_id: 0x%04x chip_rev: 0x%02x\n", bcm->chip_id, bcm->chip_rev);
+- if ((bcm->core_80211[0].rev >= 3) && (bcm43xx_read32(bcm, 0x0158) & (1 << 16)))
+- fappend("Radio disabled by hardware!\n");
+- if ((bcm->core_80211[0].rev < 3) && !(bcm43xx_read16(bcm, 0x049A) & (1 << 4)))
+- fappend("Radio disabled by hardware!\n");
+- fappend("board_vendor: 0x%04x board_type: 0x%04x\n", bcm->board_vendor,
+- bcm->board_type);
+-
+- fappend("\nCores:\n");
+-#define fappend_core(name, info) fappend("core \"" name "\" %s, %s, id: 0x%04x, " \
+- "rev: 0x%02x, index: 0x%02x\n", \
+- (info).available \
+- ? "available" : "nonavailable", \
+- (info).enabled \
+- ? "enabled" : "disabled", \
+- (info).id, (info).rev, (info).index)
+- fappend_core("CHIPCOMMON", bcm->core_chipcommon);
+- fappend_core("PCI", bcm->core_pci);
+- fappend_core("first 80211", bcm->core_80211[0]);
+- fappend_core("second 80211", bcm->core_80211[1]);
+-#undef fappend_core
+- tmp16 = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
+- fappend("LEDs: ");
+- for (i = 0; i < BCM43xx_NR_LEDS; i++)
+- fappend("%d ", !!(tmp16 & (1 << i)));
+- fappend("\n");
+-
+-out:
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- mutex_unlock(&bcm->mutex);
+- res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+- up(&big_buffer_sem);
+- return res;
+-}
+-
+-static ssize_t drvinfo_read_file(struct file *file, char __user *userbuf,
+- size_t count, loff_t *ppos)
+-{
+- const size_t len = REALLY_BIG_BUFFER_SIZE;
+-
+- char *buf = really_big_buffer;
+- size_t pos = 0;
+- ssize_t res;
+-
+- down(&big_buffer_sem);
+-
+- /* This is where the information is written to the "driver" file */
+- fappend(KBUILD_MODNAME " driver\n");
+- fappend("Compiled at: %s %s\n", __DATE__, __TIME__);
+-
+- res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+- up(&big_buffer_sem);
+- return res;
+-}
+-
+-static ssize_t spromdump_read_file(struct file *file, char __user *userbuf,
+- size_t count, loff_t *ppos)
+-{
+- const size_t len = REALLY_BIG_BUFFER_SIZE;
+-
+- struct bcm43xx_private *bcm = file->private_data;
+- char *buf = really_big_buffer;
+- size_t pos = 0;
+- ssize_t res;
+- unsigned long flags;
+-
+- down(&big_buffer_sem);
+- mutex_lock(&bcm->mutex);
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
+- fappend("Board not initialized.\n");
+- goto out;
+- }
+-
+- /* This is where the information is written to the "sprom_dump" file */
+- fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags);
+-
+-out:
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- mutex_unlock(&bcm->mutex);
+- res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+- up(&big_buffer_sem);
+- return res;
+-}
+-
+-static ssize_t tsf_read_file(struct file *file, char __user *userbuf,
+- size_t count, loff_t *ppos)
+-{
+- const size_t len = REALLY_BIG_BUFFER_SIZE;
+-
+- struct bcm43xx_private *bcm = file->private_data;
+- char *buf = really_big_buffer;
+- size_t pos = 0;
+- ssize_t res;
+- unsigned long flags;
+- u64 tsf;
+-
+- down(&big_buffer_sem);
+- mutex_lock(&bcm->mutex);
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
+- fappend("Board not initialized.\n");
+- goto out;
+- }
+- bcm43xx_tsf_read(bcm, &tsf);
+- fappend("0x%08x%08x\n",
+- (unsigned int)((tsf & 0xFFFFFFFF00000000ULL) >> 32),
+- (unsigned int)(tsf & 0xFFFFFFFFULL));
+-
+-out:
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- mutex_unlock(&bcm->mutex);
+- res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+- up(&big_buffer_sem);
+- return res;
+-}
+-
+-static ssize_t tsf_write_file(struct file *file, const char __user *user_buf,
+- size_t count, loff_t *ppos)
+-{
+- struct bcm43xx_private *bcm = file->private_data;
+- char *buf = really_big_buffer;
+- ssize_t buf_size;
+- ssize_t res;
+- unsigned long flags;
+- unsigned long long tsf;
+-
+- buf_size = min(count, sizeof (really_big_buffer) - 1);
+- down(&big_buffer_sem);
+- if (copy_from_user(buf, user_buf, buf_size)) {
+- res = -EFAULT;
+- goto out_up;
+- }
+- mutex_lock(&bcm->mutex);
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
+- printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
+- res = -EFAULT;
+- goto out_unlock;
+- }
+- if (sscanf(buf, "%lli", &tsf) != 1) {
+- printk(KERN_INFO PFX "debugfs: invalid values for \"tsf\"\n");
+- res = -EINVAL;
+- goto out_unlock;
+- }
+- bcm43xx_tsf_write(bcm, tsf);
+- mmiowb();
+- res = buf_size;
+-
+-out_unlock:
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- mutex_unlock(&bcm->mutex);
+-out_up:
+- up(&big_buffer_sem);
+- return res;
+-}
+-
+-static ssize_t txstat_read_file(struct file *file, char __user *userbuf,
+- size_t count, loff_t *ppos)
+-{
+- const size_t len = REALLY_BIG_BUFFER_SIZE;
+-
+- struct bcm43xx_private *bcm = file->private_data;
+- char *buf = really_big_buffer;
+- size_t pos = 0;
+- ssize_t res;
+- unsigned long flags;
+- struct bcm43xx_dfsentry *e;
+- struct bcm43xx_xmitstatus *status;
+- int i, cnt, j = 0;
+-
+- down(&big_buffer_sem);
+- mutex_lock(&bcm->mutex);
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+-
+- fappend("Last %d logged xmitstatus blobs (Latest first):\n\n",
+- BCM43xx_NR_LOGGED_XMITSTATUS);
+- e = bcm->dfsentry;
+- if (e->xmitstatus_printing == 0) {
+- /* At the beginning, make a copy of all data to avoid
+- * concurrency, as this function is called multiple
+- * times for big logs. Without copying, the data might
+- * change between reads. This would result in total trash.
+- */
+- e->xmitstatus_printing = 1;
+- e->saved_xmitstatus_ptr = e->xmitstatus_ptr;
+- e->saved_xmitstatus_cnt = e->xmitstatus_cnt;
+- memcpy(e->xmitstatus_print_buffer, e->xmitstatus_buffer,
+- BCM43xx_NR_LOGGED_XMITSTATUS * sizeof(*(e->xmitstatus_buffer)));
+- }
+- i = e->saved_xmitstatus_ptr - 1;
+- if (i < 0)
+- i = BCM43xx_NR_LOGGED_XMITSTATUS - 1;
+- cnt = e->saved_xmitstatus_cnt;
+- while (cnt) {
+- status = e->xmitstatus_print_buffer + i;
+- fappend("0x%02x: cookie: 0x%04x, flags: 0x%02x, "
+- "cnt1: 0x%02x, cnt2: 0x%02x, seq: 0x%04x, "
+- "unk: 0x%04x\n", j,
+- status->cookie, status->flags,
+- status->cnt1, status->cnt2, status->seq,
+- status->unknown);
+- j++;
+- cnt--;
+- i--;
+- if (i < 0)
+- i = BCM43xx_NR_LOGGED_XMITSTATUS - 1;
+- }
+-
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- if (*ppos == pos) {
+- /* Done. Drop the copied data. */
+- e->xmitstatus_printing = 0;
+- }
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- mutex_unlock(&bcm->mutex);
+- up(&big_buffer_sem);
+- return res;
+-}
+-
+-static ssize_t restart_write_file(struct file *file, const char __user *user_buf,
+- size_t count, loff_t *ppos)
+-{
+- struct bcm43xx_private *bcm = file->private_data;
+- char *buf = really_big_buffer;
+- ssize_t buf_size;
+- ssize_t res;
+- unsigned long flags;
+-
+- buf_size = min(count, sizeof (really_big_buffer) - 1);
+- down(&big_buffer_sem);
+- if (copy_from_user(buf, user_buf, buf_size)) {
+- res = -EFAULT;
+- goto out_up;
+- }
+- mutex_lock(&(bcm)->mutex);
+- spin_lock_irqsave(&(bcm)->irq_lock, flags);
+- if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
+- printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
+- res = -EFAULT;
+- goto out_unlock;
+- }
+- if (count > 0 && buf[0] == '1') {
+- bcm43xx_controller_restart(bcm, "manually restarted");
+- res = count;
+- } else
+- res = -EINVAL;
+-
+-out_unlock:
+- spin_unlock_irqrestore(&(bcm)->irq_lock, flags);
+- mutex_unlock(&(bcm)->mutex);
+-out_up:
+- up(&big_buffer_sem);
+- return res;
+-}
+-
+-#undef fappend
+-
+-
+-static const struct file_operations devinfo_fops = {
+- .read = devinfo_read_file,
+- .write = write_file_dummy,
+- .open = open_file_generic,
+-};
+-
+-static const struct file_operations spromdump_fops = {
+- .read = spromdump_read_file,
+- .write = write_file_dummy,
+- .open = open_file_generic,
+-};
+-
+-static const struct file_operations drvinfo_fops = {
+- .read = drvinfo_read_file,
+- .write = write_file_dummy,
+- .open = open_file_generic,
+-};
+-
+-static const struct file_operations tsf_fops = {
+- .read = tsf_read_file,
+- .write = tsf_write_file,
+- .open = open_file_generic,
+-};
+-
+-static const struct file_operations txstat_fops = {
+- .read = txstat_read_file,
+- .write = write_file_dummy,
+- .open = open_file_generic,
+-};
+-
+-static const struct file_operations restart_fops = {
+- .write = restart_write_file,
+- .open = open_file_generic,
+-};
+-
+-
+-void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_dfsentry *e;
+- char devdir[IFNAMSIZ];
+-
+- assert(bcm);
+- e = kzalloc(sizeof(*e), GFP_KERNEL);
+- if (!e) {
+- printk(KERN_ERR PFX "out of memory\n");
+- return;
+- }
+- e->bcm = bcm;
+- e->xmitstatus_buffer = kzalloc(BCM43xx_NR_LOGGED_XMITSTATUS
+- * sizeof(*(e->xmitstatus_buffer)),
+- GFP_KERNEL);
+- if (!e->xmitstatus_buffer) {
+- printk(KERN_ERR PFX "out of memory\n");
+- kfree(e);
+- return;
+- }
+- e->xmitstatus_print_buffer = kzalloc(BCM43xx_NR_LOGGED_XMITSTATUS
+- * sizeof(*(e->xmitstatus_buffer)),
+- GFP_KERNEL);
+- if (!e->xmitstatus_print_buffer) {
+- printk(KERN_ERR PFX "out of memory\n");
+- kfree(e);
+- return;
+- }
+-
+-
+- bcm->dfsentry = e;
+-
+- strncpy(devdir, bcm->net_dev->name, ARRAY_SIZE(devdir));
+- e->subdir = debugfs_create_dir(devdir, fs.root);
+- e->dentry_devinfo = debugfs_create_file("devinfo", 0444, e->subdir,
+- bcm, &devinfo_fops);
+- if (!e->dentry_devinfo)
+- printk(KERN_ERR PFX "debugfs: creating \"devinfo\" for \"%s\" failed!\n", devdir);
+- e->dentry_spromdump = debugfs_create_file("sprom_dump", 0444, e->subdir,
+- bcm, &spromdump_fops);
+- if (!e->dentry_spromdump)
+- printk(KERN_ERR PFX "debugfs: creating \"sprom_dump\" for \"%s\" failed!\n", devdir);
+- e->dentry_tsf = debugfs_create_file("tsf", 0666, e->subdir,
+- bcm, &tsf_fops);
+- if (!e->dentry_tsf)
+- printk(KERN_ERR PFX "debugfs: creating \"tsf\" for \"%s\" failed!\n", devdir);
+- e->dentry_txstat = debugfs_create_file("tx_status", 0444, e->subdir,
+- bcm, &txstat_fops);
+- if (!e->dentry_txstat)
+- printk(KERN_ERR PFX "debugfs: creating \"tx_status\" for \"%s\" failed!\n", devdir);
+- e->dentry_restart = debugfs_create_file("restart", 0222, e->subdir,
+- bcm, &restart_fops);
+- if (!e->dentry_restart)
+- printk(KERN_ERR PFX "debugfs: creating \"restart\" for \"%s\" failed!\n", devdir);
+-}
+-
+-void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_dfsentry *e;
+-
+- if (!bcm)
+- return;
+-
+- e = bcm->dfsentry;
+- assert(e);
+- debugfs_remove(e->dentry_spromdump);
+- debugfs_remove(e->dentry_devinfo);
+- debugfs_remove(e->dentry_tsf);
+- debugfs_remove(e->dentry_txstat);
+- debugfs_remove(e->dentry_restart);
+- debugfs_remove(e->subdir);
+- kfree(e->xmitstatus_buffer);
+- kfree(e->xmitstatus_print_buffer);
+- kfree(e);
+-}
+-
+-void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm,
+- struct bcm43xx_xmitstatus *status)
+-{
+- struct bcm43xx_dfsentry *e;
+- struct bcm43xx_xmitstatus *savedstatus;
+-
+- /* This is protected by bcm->_lock */
+- e = bcm->dfsentry;
+- assert(e);
+- savedstatus = e->xmitstatus_buffer + e->xmitstatus_ptr;
+- memcpy(savedstatus, status, sizeof(*status));
+- e->xmitstatus_ptr++;
+- if (e->xmitstatus_ptr >= BCM43xx_NR_LOGGED_XMITSTATUS)
+- e->xmitstatus_ptr = 0;
+- if (e->xmitstatus_cnt < BCM43xx_NR_LOGGED_XMITSTATUS)
+- e->xmitstatus_cnt++;
+-}
+-
+-void bcm43xx_debugfs_init(void)
+-{
+- memset(&fs, 0, sizeof(fs));
+- fs.root = debugfs_create_dir(KBUILD_MODNAME, NULL);
+- if (!fs.root)
+- printk(KERN_ERR PFX "debugfs: creating \"" KBUILD_MODNAME "\" subdir failed!\n");
+- fs.dentry_driverinfo = debugfs_create_file("driver", 0444, fs.root, NULL, &drvinfo_fops);
+- if (!fs.dentry_driverinfo)
+- printk(KERN_ERR PFX "debugfs: creating \"" KBUILD_MODNAME "/driver\" failed!\n");
+-}
+-
+-void bcm43xx_debugfs_exit(void)
+-{
+- debugfs_remove(fs.dentry_driverinfo);
+- debugfs_remove(fs.root);
+-}
+-
+-void bcm43xx_printk_dump(const char *data,
+- size_t size,
+- const char *description)
+-{
+- size_t i;
+- char c;
+-
+- printk(KERN_INFO PFX "Data dump (%s, %zd bytes):",
+- description, size);
+- for (i = 0; i < size; i++) {
+- c = data[i];
+- if (i % 8 == 0)
+- printk("\n" KERN_INFO PFX "0x%08zx: 0x%02x, ", i, c & 0xff);
+- else
+- printk("0x%02x, ", c & 0xff);
+- }
+- printk("\n");
+-}
+-
+-void bcm43xx_printk_bitdump(const unsigned char *data,
+- size_t bytes, int msb_to_lsb,
+- const char *description)
+-{
+- size_t i;
+- int j;
+- const unsigned char *d;
+-
+- printk(KERN_INFO PFX "*** Bitdump (%s, %zd bytes, %s) ***",
+- description, bytes, msb_to_lsb ? "MSB to LSB" : "LSB to MSB");
+- for (i = 0; i < bytes; i++) {
+- d = data + i;
+- if (i % 8 == 0)
+- printk("\n" KERN_INFO PFX "0x%08zx: ", i);
+- if (msb_to_lsb) {
+- for (j = 7; j >= 0; j--) {
+- if (*d & (1 << j))
+- printk("1");
+- else
+- printk("0");
+- }
+- } else {
+- for (j = 0; j < 8; j++) {
+- if (*d & (1 << j))
+- printk("1");
+- else
+- printk("0");
+- }
+- }
+- printk(" ");
+- }
+- printk("\n");
+-}
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h
+deleted file mode 100644
+index a40d1af..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h
++++ /dev/null
+@@ -1,118 +0,0 @@
+-#ifndef BCM43xx_DEBUGFS_H_
+-#define BCM43xx_DEBUGFS_H_
+-
+-struct bcm43xx_private;
+-struct bcm43xx_xmitstatus;
+-
+-#ifdef CONFIG_BCM43XX_DEBUG
+-
+-#include <linux/list.h>
+-#include <asm/semaphore.h>
+-
+-struct dentry;
+-
+-/* limited by the size of the "really_big_buffer" */
+-#define BCM43xx_NR_LOGGED_XMITSTATUS 100
+-
+-struct bcm43xx_dfsentry {
+- struct dentry *subdir;
+- struct dentry *dentry_devinfo;
+- struct dentry *dentry_spromdump;
+- struct dentry *dentry_tsf;
+- struct dentry *dentry_txstat;
+- struct dentry *dentry_restart;
+-
+- struct bcm43xx_private *bcm;
+-
+- /* saved xmitstatus. */
+- struct bcm43xx_xmitstatus *xmitstatus_buffer;
+- int xmitstatus_ptr;
+- int xmitstatus_cnt;
+- /* We need a seperate buffer while printing to avoid
+- * concurrency issues. (New xmitstatus can arrive
+- * while we are printing).
+- */
+- struct bcm43xx_xmitstatus *xmitstatus_print_buffer;
+- int saved_xmitstatus_ptr;
+- int saved_xmitstatus_cnt;
+- int xmitstatus_printing;
+-};
+-
+-struct bcm43xx_debugfs {
+- struct dentry *root;
+- struct dentry *dentry_driverinfo;
+-};
+-
+-void bcm43xx_debugfs_init(void);
+-void bcm43xx_debugfs_exit(void);
+-void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm);
+-void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm);
+-void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm,
+- struct bcm43xx_xmitstatus *status);
+-
+-/* Debug helper: Dump binary data through printk. */
+-void bcm43xx_printk_dump(const char *data,
+- size_t size,
+- const char *description);
+-/* Debug helper: Dump bitwise binary data through printk. */
+-void bcm43xx_printk_bitdump(const unsigned char *data,
+- size_t bytes, int msb_to_lsb,
+- const char *description);
+-#define bcm43xx_printk_bitdumpt(pointer, msb_to_lsb, description) \
+- do { \
+- bcm43xx_printk_bitdump((const unsigned char *)(pointer), \
+- sizeof(*(pointer)), \
+- (msb_to_lsb), \
+- (description)); \
+- } while (0)
+-
+-#else /* CONFIG_BCM43XX_DEBUG*/
+-
+-static inline
+-void bcm43xx_debugfs_init(void) { }
+-static inline
+-void bcm43xx_debugfs_exit(void) { }
+-static inline
+-void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm) { }
+-static inline
+-void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm) { }
+-static inline
+-void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm,
+- struct bcm43xx_xmitstatus *status) { }
+-
+-static inline
+-void bcm43xx_printk_dump(const char *data,
+- size_t size,
+- const char *description)
+-{
+-}
+-static inline
+-void bcm43xx_printk_bitdump(const unsigned char *data,
+- size_t bytes, int msb_to_lsb,
+- const char *description)
+-{
+-}
+-#define bcm43xx_printk_bitdumpt(pointer, msb_to_lsb, description) do { /* nothing */ } while (0)
+-
+-#endif /* CONFIG_BCM43XX_DEBUG*/
+-
+-/* Ugly helper macros to make incomplete code more verbose on runtime */
+-#ifdef TODO
+-# undef TODO
+-#endif
+-#define TODO() \
+- do { \
+- printk(KERN_INFO PFX "TODO: Incomplete code in %s() at %s:%d\n", \
+- __FUNCTION__, __FILE__, __LINE__); \
+- } while (0)
+-
+-#ifdef FIXME
+-# undef FIXME
+-#endif
+-#define FIXME() \
+- do { \
+- printk(KERN_INFO PFX "FIXME: Possibly broken code in %s() at %s:%d\n", \
+- __FUNCTION__, __FILE__, __LINE__); \
+- } while (0)
+-
+-#endif /* BCM43xx_DEBUGFS_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
+deleted file mode 100644
+index 1f7731f..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
++++ /dev/null
+@@ -1,1263 +0,0 @@
+-/*
+-
+- Broadcom BCM43xx wireless driver
+-
+- DMA ringbuffer and descriptor allocation/management
+-
+- Copyright (c) 2005, 2006 Michael Buesch <mbuesch at freenet.de>
+-
+- Some code in this file is derived from the b44.c driver
+- Copyright (C) 2002 David S. Miller
+- Copyright (C) Pekka Pietikainen
+-
+- 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; see the file COPYING. If not, write to
+- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+- Boston, MA 02110-1301, USA.
+-
+-*/
+-
+-#include "bcm43xx.h"
+-#include "bcm43xx_dma.h"
+-#include "bcm43xx_main.h"
+-#include "bcm43xx_debugfs.h"
+-#include "bcm43xx_power.h"
+-#include "bcm43xx_xmit.h"
+-
+-#include <linux/dma-mapping.h>
+-#include <linux/pci.h>
+-#include <linux/delay.h>
+-#include <linux/skbuff.h>
+-
+-
+-static inline int free_slots(struct bcm43xx_dmaring *ring)
+-{
+- return (ring->nr_slots - ring->used_slots);
+-}
+-
+-static inline int next_slot(struct bcm43xx_dmaring *ring, int slot)
+-{
+- assert(slot >= -1 && slot <= ring->nr_slots - 1);
+- if (slot == ring->nr_slots - 1)
+- return 0;
+- return slot + 1;
+-}
+-
+-static inline int prev_slot(struct bcm43xx_dmaring *ring, int slot)
+-{
+- assert(slot >= 0 && slot <= ring->nr_slots - 1);
+- if (slot == 0)
+- return ring->nr_slots - 1;
+- return slot - 1;
+-}
+-
+-/* Request a slot for usage. */
+-static inline
+-int request_slot(struct bcm43xx_dmaring *ring)
+-{
+- int slot;
+-
+- assert(ring->tx);
+- assert(!ring->suspended);
+- assert(free_slots(ring) != 0);
+-
+- slot = next_slot(ring, ring->current_slot);
+- ring->current_slot = slot;
+- ring->used_slots++;
+-
+- /* Check the number of available slots and suspend TX,
+- * if we are running low on free slots.
+- */
+- if (unlikely(free_slots(ring) < ring->suspend_mark)) {
+- netif_stop_queue(ring->bcm->net_dev);
+- ring->suspended = 1;
+- }
+-#ifdef CONFIG_BCM43XX_DEBUG
+- if (ring->used_slots > ring->max_used_slots)
+- ring->max_used_slots = ring->used_slots;
+-#endif /* CONFIG_BCM43XX_DEBUG*/
+-
+- return slot;
+-}
+-
+-/* Return a slot to the free slots. */
+-static inline
+-void return_slot(struct bcm43xx_dmaring *ring, int slot)
+-{
+- assert(ring->tx);
+-
+- ring->used_slots--;
+-
+- /* Check if TX is suspended and check if we have
+- * enough free slots to resume it again.
+- */
+- if (unlikely(ring->suspended)) {
+- if (free_slots(ring) >= ring->resume_mark) {
+- ring->suspended = 0;
+- netif_wake_queue(ring->bcm->net_dev);
+- }
+- }
+-}
+-
+-u16 bcm43xx_dmacontroller_base(int dma64bit, int controller_idx)
+-{
+- static const u16 map64[] = {
+- BCM43xx_MMIO_DMA64_BASE0,
+- BCM43xx_MMIO_DMA64_BASE1,
+- BCM43xx_MMIO_DMA64_BASE2,
+- BCM43xx_MMIO_DMA64_BASE3,
+- BCM43xx_MMIO_DMA64_BASE4,
+- BCM43xx_MMIO_DMA64_BASE5,
+- };
+- static const u16 map32[] = {
+- BCM43xx_MMIO_DMA32_BASE0,
+- BCM43xx_MMIO_DMA32_BASE1,
+- BCM43xx_MMIO_DMA32_BASE2,
+- BCM43xx_MMIO_DMA32_BASE3,
+- BCM43xx_MMIO_DMA32_BASE4,
+- BCM43xx_MMIO_DMA32_BASE5,
+- };
+-
+- if (dma64bit) {
+- assert(controller_idx >= 0 &&
+- controller_idx < ARRAY_SIZE(map64));
+- return map64[controller_idx];
+- }
+- assert(controller_idx >= 0 &&
+- controller_idx < ARRAY_SIZE(map32));
+- return map32[controller_idx];
+-}
+-
+-static inline
+-dma_addr_t map_descbuffer(struct bcm43xx_dmaring *ring,
+- unsigned char *buf,
+- size_t len,
+- int tx)
+-{
+- dma_addr_t dmaaddr;
+- int direction = PCI_DMA_FROMDEVICE;
+-
+- if (tx)
+- direction = PCI_DMA_TODEVICE;
+-
+- dmaaddr = pci_map_single(ring->bcm->pci_dev,
+- buf, len,
+- direction);
+-
+- return dmaaddr;
+-}
+-
+-static inline
+-void unmap_descbuffer(struct bcm43xx_dmaring *ring,
+- dma_addr_t addr,
+- size_t len,
+- int tx)
+-{
+- if (tx) {
+- pci_unmap_single(ring->bcm->pci_dev,
+- addr, len,
+- PCI_DMA_TODEVICE);
+- } else {
+- pci_unmap_single(ring->bcm->pci_dev,
+- addr, len,
+- PCI_DMA_FROMDEVICE);
+- }
+-}
+-
+-static inline
+-void sync_descbuffer_for_cpu(struct bcm43xx_dmaring *ring,
+- dma_addr_t addr,
+- size_t len)
+-{
+- assert(!ring->tx);
+-
+- pci_dma_sync_single_for_cpu(ring->bcm->pci_dev,
+- addr, len, PCI_DMA_FROMDEVICE);
+-}
+-
+-static inline
+-void sync_descbuffer_for_device(struct bcm43xx_dmaring *ring,
+- dma_addr_t addr,
+- size_t len)
+-{
+- assert(!ring->tx);
+-
+- pci_dma_sync_single_for_cpu(ring->bcm->pci_dev,
+- addr, len, PCI_DMA_TODEVICE);
+-}
+-
+-/* Unmap and free a descriptor buffer. */
+-static inline
+-void free_descriptor_buffer(struct bcm43xx_dmaring *ring,
+- struct bcm43xx_dmadesc_meta *meta,
+- int irq_context)
+-{
+- assert(meta->skb);
+- if (irq_context)
+- dev_kfree_skb_irq(meta->skb);
+- else
+- dev_kfree_skb(meta->skb);
+- meta->skb = NULL;
+-}
+-
+-static int alloc_ringmemory(struct bcm43xx_dmaring *ring)
+-{
+- ring->descbase = pci_alloc_consistent(ring->bcm->pci_dev, BCM43xx_DMA_RINGMEMSIZE,
+- &(ring->dmabase));
+- if (!ring->descbase) {
+- /* Allocation may have failed due to pci_alloc_consistent
+- insisting on use of GFP_DMA, which is more restrictive
+- than necessary... */
+- struct dma_desc *rx_ring;
+- dma_addr_t rx_ring_dma;
+-
+- rx_ring = kzalloc(BCM43xx_DMA_RINGMEMSIZE, GFP_KERNEL);
+- if (!rx_ring)
+- goto out_err;
+-
+- rx_ring_dma = pci_map_single(ring->bcm->pci_dev, rx_ring,
+- BCM43xx_DMA_RINGMEMSIZE,
+- PCI_DMA_BIDIRECTIONAL);
+-
+- if (pci_dma_mapping_error(rx_ring_dma) ||
+- rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) {
+- /* Sigh... */
+- if (!pci_dma_mapping_error(rx_ring_dma))
+- pci_unmap_single(ring->bcm->pci_dev,
+- rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE,
+- PCI_DMA_BIDIRECTIONAL);
+- rx_ring_dma = pci_map_single(ring->bcm->pci_dev,
+- rx_ring, BCM43xx_DMA_RINGMEMSIZE,
+- PCI_DMA_BIDIRECTIONAL);
+- if (pci_dma_mapping_error(rx_ring_dma) ||
+- rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) {
+- assert(0);
+- if (!pci_dma_mapping_error(rx_ring_dma))
+- pci_unmap_single(ring->bcm->pci_dev,
+- rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE,
+- PCI_DMA_BIDIRECTIONAL);
+- goto out_err;
+- }
+- }
+-
+- ring->descbase = rx_ring;
+- ring->dmabase = rx_ring_dma;
+- }
+- memset(ring->descbase, 0, BCM43xx_DMA_RINGMEMSIZE);
+-
+- return 0;
+-out_err:
+- printk(KERN_ERR PFX "DMA ringmemory allocation failed\n");
+- return -ENOMEM;
+-}
+-
+-static void free_ringmemory(struct bcm43xx_dmaring *ring)
+-{
+- struct device *dev = &(ring->bcm->pci_dev->dev);
+-
+- dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
+- ring->descbase, ring->dmabase);
+-}
+-
+-/* Reset the RX DMA channel */
+-int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
+- u16 mmio_base, int dma64)
+-{
+- int i;
+- u32 value;
+- u16 offset;
+-
+- offset = dma64 ? BCM43xx_DMA64_RXCTL : BCM43xx_DMA32_RXCTL;
+- bcm43xx_write32(bcm, mmio_base + offset, 0);
+- for (i = 0; i < 1000; i++) {
+- offset = dma64 ? BCM43xx_DMA64_RXSTATUS : BCM43xx_DMA32_RXSTATUS;
+- value = bcm43xx_read32(bcm, mmio_base + offset);
+- if (dma64) {
+- value &= BCM43xx_DMA64_RXSTAT;
+- if (value == BCM43xx_DMA64_RXSTAT_DISABLED) {
+- i = -1;
+- break;
+- }
+- } else {
+- value &= BCM43xx_DMA32_RXSTATE;
+- if (value == BCM43xx_DMA32_RXSTAT_DISABLED) {
+- i = -1;
+- break;
+- }
+- }
+- udelay(10);
+- }
+- if (i != -1) {
+- printk(KERN_ERR PFX "Error: Wait on DMA RX status timed out.\n");
+- return -ENODEV;
+- }
+-
+- return 0;
+-}
+-
+-/* Reset the RX DMA channel */
+-int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
+- u16 mmio_base, int dma64)
+-{
+- int i;
+- u32 value;
+- u16 offset;
+-
+- for (i = 0; i < 1000; i++) {
+- offset = dma64 ? BCM43xx_DMA64_TXSTATUS : BCM43xx_DMA32_TXSTATUS;
+- value = bcm43xx_read32(bcm, mmio_base + offset);
+- if (dma64) {
+- value &= BCM43xx_DMA64_TXSTAT;
+- if (value == BCM43xx_DMA64_TXSTAT_DISABLED ||
+- value == BCM43xx_DMA64_TXSTAT_IDLEWAIT ||
+- value == BCM43xx_DMA64_TXSTAT_STOPPED)
+- break;
+- } else {
+- value &= BCM43xx_DMA32_TXSTATE;
+- if (value == BCM43xx_DMA32_TXSTAT_DISABLED ||
+- value == BCM43xx_DMA32_TXSTAT_IDLEWAIT ||
+- value == BCM43xx_DMA32_TXSTAT_STOPPED)
+- break;
+- }
+- udelay(10);
+- }
+- offset = dma64 ? BCM43xx_DMA64_TXCTL : BCM43xx_DMA32_TXCTL;
+- bcm43xx_write32(bcm, mmio_base + offset, 0);
+- for (i = 0; i < 1000; i++) {
+- offset = dma64 ? BCM43xx_DMA64_TXSTATUS : BCM43xx_DMA32_TXSTATUS;
+- value = bcm43xx_read32(bcm, mmio_base + offset);
+- if (dma64) {
+- value &= BCM43xx_DMA64_TXSTAT;
+- if (value == BCM43xx_DMA64_TXSTAT_DISABLED) {
+- i = -1;
+- break;
+- }
+- } else {
+- value &= BCM43xx_DMA32_TXSTATE;
+- if (value == BCM43xx_DMA32_TXSTAT_DISABLED) {
+- i = -1;
+- break;
+- }
+- }
+- udelay(10);
+- }
+- if (i != -1) {
+- printk(KERN_ERR PFX "Error: Wait on DMA TX status timed out.\n");
+- return -ENODEV;
+- }
+- /* ensure the reset is completed. */
+- udelay(300);
+-
+- return 0;
+-}
+-
+-static void fill_descriptor(struct bcm43xx_dmaring *ring,
+- struct bcm43xx_dmadesc_generic *desc,
+- dma_addr_t dmaaddr,
+- u16 bufsize,
+- int start, int end, int irq)
+-{
+- int slot;
+-
+- slot = bcm43xx_dma_desc2idx(ring, desc);
+- assert(slot >= 0 && slot < ring->nr_slots);
+-
+- if (ring->dma64) {
+- u32 ctl0 = 0, ctl1 = 0;
+- u32 addrlo, addrhi;
+- u32 addrext;
+-
+- addrlo = (u32)(dmaaddr & 0xFFFFFFFF);
+- addrhi = (((u64)dmaaddr >> 32) & ~BCM43xx_DMA64_ROUTING);
+- addrext = (((u64)dmaaddr >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT);
+- addrhi |= ring->routing;
+- if (slot == ring->nr_slots - 1)
+- ctl0 |= BCM43xx_DMA64_DCTL0_DTABLEEND;
+- if (start)
+- ctl0 |= BCM43xx_DMA64_DCTL0_FRAMESTART;
+- if (end)
+- ctl0 |= BCM43xx_DMA64_DCTL0_FRAMEEND;
+- if (irq)
+- ctl0 |= BCM43xx_DMA64_DCTL0_IRQ;
+- ctl1 |= (bufsize - ring->frameoffset)
+- & BCM43xx_DMA64_DCTL1_BYTECNT;
+- ctl1 |= (addrext << BCM43xx_DMA64_DCTL1_ADDREXT_SHIFT)
+- & BCM43xx_DMA64_DCTL1_ADDREXT_MASK;
+-
+- desc->dma64.control0 = cpu_to_le32(ctl0);
+- desc->dma64.control1 = cpu_to_le32(ctl1);
+- desc->dma64.address_low = cpu_to_le32(addrlo);
+- desc->dma64.address_high = cpu_to_le32(addrhi);
+- } else {
+- u32 ctl;
+- u32 addr;
+- u32 addrext;
+-
+- addr = (u32)(dmaaddr & ~BCM43xx_DMA32_ROUTING);
+- addrext = (u32)(dmaaddr & BCM43xx_DMA32_ROUTING)
+- >> BCM43xx_DMA32_ROUTING_SHIFT;
+- addr |= ring->routing;
+- ctl = (bufsize - ring->frameoffset)
+- & BCM43xx_DMA32_DCTL_BYTECNT;
+- if (slot == ring->nr_slots - 1)
+- ctl |= BCM43xx_DMA32_DCTL_DTABLEEND;
+- if (start)
+- ctl |= BCM43xx_DMA32_DCTL_FRAMESTART;
+- if (end)
+- ctl |= BCM43xx_DMA32_DCTL_FRAMEEND;
+- if (irq)
+- ctl |= BCM43xx_DMA32_DCTL_IRQ;
+- ctl |= (addrext << BCM43xx_DMA32_DCTL_ADDREXT_SHIFT)
+- & BCM43xx_DMA32_DCTL_ADDREXT_MASK;
+-
+- desc->dma32.control = cpu_to_le32(ctl);
+- desc->dma32.address = cpu_to_le32(addr);
+- }
+-}
+-
+-static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring,
+- struct bcm43xx_dmadesc_generic *desc,
+- struct bcm43xx_dmadesc_meta *meta,
+- gfp_t gfp_flags)
+-{
+- struct bcm43xx_rxhdr *rxhdr;
+- struct bcm43xx_hwxmitstatus *xmitstat;
+- dma_addr_t dmaaddr;
+- struct sk_buff *skb;
+-
+- assert(!ring->tx);
+-
+- skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags);
+- if (unlikely(!skb))
+- return -ENOMEM;
+- dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0);
+- /* This hardware bug work-around adapted from the b44 driver.
+- The chip may be unable to do PCI DMA to/from anything above 1GB */
+- if (pci_dma_mapping_error(dmaaddr) ||
+- dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) {
+- /* This one has 30-bit addressing... */
+- if (!pci_dma_mapping_error(dmaaddr))
+- pci_unmap_single(ring->bcm->pci_dev,
+- dmaaddr, ring->rx_buffersize,
+- PCI_DMA_FROMDEVICE);
+- dev_kfree_skb_any(skb);
+- skb = __dev_alloc_skb(ring->rx_buffersize,GFP_DMA);
+- if (skb == NULL)
+- return -ENOMEM;
+- dmaaddr = pci_map_single(ring->bcm->pci_dev,
+- skb->data, ring->rx_buffersize,
+- PCI_DMA_FROMDEVICE);
+- if (pci_dma_mapping_error(dmaaddr) ||
+- dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) {
+- assert(0);
+- dev_kfree_skb_any(skb);
+- return -ENOMEM;
+- }
+- }
+- meta->skb = skb;
+- meta->dmaaddr = dmaaddr;
+- skb->dev = ring->bcm->net_dev;
+-
+- fill_descriptor(ring, desc, dmaaddr,
+- ring->rx_buffersize, 0, 0, 0);
+-
+- rxhdr = (struct bcm43xx_rxhdr *)(skb->data);
+- rxhdr->frame_length = 0;
+- rxhdr->flags1 = 0;
+- xmitstat = (struct bcm43xx_hwxmitstatus *)(skb->data);
+- xmitstat->cookie = 0;
+-
+- return 0;
+-}
+-
+-/* Allocate the initial descbuffers.
+- * This is used for an RX ring only.
+- */
+-static int alloc_initial_descbuffers(struct bcm43xx_dmaring *ring)
+-{
+- int i, err = -ENOMEM;
+- struct bcm43xx_dmadesc_generic *desc;
+- struct bcm43xx_dmadesc_meta *meta;
+-
+- for (i = 0; i < ring->nr_slots; i++) {
+- desc = bcm43xx_dma_idx2desc(ring, i, &meta);
+-
+- err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL);
+- if (err)
+- goto err_unwind;
+- }
+- mb();
+- ring->used_slots = ring->nr_slots;
+- err = 0;
+-out:
+- return err;
+-
+-err_unwind:
+- for (i--; i >= 0; i--) {
+- desc = bcm43xx_dma_idx2desc(ring, i, &meta);
+-
+- unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0);
+- dev_kfree_skb(meta->skb);
+- }
+- goto out;
+-}
+-
+-/* Do initial setup of the DMA controller.
+- * Reset the controller, write the ring busaddress
+- * and switch the "enable" bit on.
+- */
+-static int dmacontroller_setup(struct bcm43xx_dmaring *ring)
+-{
+- int err = 0;
+- u32 value;
+- u32 addrext;
+-
+- if (ring->tx) {
+- if (ring->dma64) {
+- u64 ringbase = (u64)(ring->dmabase);
+-
+- addrext = ((ringbase >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT);
+- value = BCM43xx_DMA64_TXENABLE;
+- value |= (addrext << BCM43xx_DMA64_TXADDREXT_SHIFT)
+- & BCM43xx_DMA64_TXADDREXT_MASK;
+- bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL, value);
+- bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGLO,
+- (ringbase & 0xFFFFFFFF));
+- bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGHI,
+- ((ringbase >> 32) & ~BCM43xx_DMA64_ROUTING)
+- | ring->routing);
+- } else {
+- u32 ringbase = (u32)(ring->dmabase);
+-
+- addrext = (ringbase >> BCM43xx_DMA32_ROUTING_SHIFT);
+- value = BCM43xx_DMA32_TXENABLE;
+- value |= (addrext << BCM43xx_DMA32_TXADDREXT_SHIFT)
+- & BCM43xx_DMA32_TXADDREXT_MASK;
+- bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL, value);
+- bcm43xx_dma_write(ring, BCM43xx_DMA32_TXRING,
+- (ringbase & ~BCM43xx_DMA32_ROUTING)
+- | ring->routing);
+- }
+- } else {
+- err = alloc_initial_descbuffers(ring);
+- if (err)
+- goto out;
+- if (ring->dma64) {
+- u64 ringbase = (u64)(ring->dmabase);
+-
+- addrext = ((ringbase >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT);
+- value = (ring->frameoffset << BCM43xx_DMA64_RXFROFF_SHIFT);
+- value |= BCM43xx_DMA64_RXENABLE;
+- value |= (addrext << BCM43xx_DMA64_RXADDREXT_SHIFT)
+- & BCM43xx_DMA64_RXADDREXT_MASK;
+- bcm43xx_dma_write(ring, BCM43xx_DMA64_RXCTL, value);
+- bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGLO,
+- (ringbase & 0xFFFFFFFF));
+- bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGHI,
+- ((ringbase >> 32) & ~BCM43xx_DMA64_ROUTING)
+- | ring->routing);
+- bcm43xx_dma_write(ring, BCM43xx_DMA64_RXINDEX, 200);
+- } else {
+- u32 ringbase = (u32)(ring->dmabase);
+-
+- addrext = (ringbase >> BCM43xx_DMA32_ROUTING_SHIFT);
+- value = (ring->frameoffset << BCM43xx_DMA32_RXFROFF_SHIFT);
+- value |= BCM43xx_DMA32_RXENABLE;
+- value |= (addrext << BCM43xx_DMA32_RXADDREXT_SHIFT)
+- & BCM43xx_DMA32_RXADDREXT_MASK;
+- bcm43xx_dma_write(ring, BCM43xx_DMA32_RXCTL, value);
+- bcm43xx_dma_write(ring, BCM43xx_DMA32_RXRING,
+- (ringbase & ~BCM43xx_DMA32_ROUTING)
+- | ring->routing);
+- bcm43xx_dma_write(ring, BCM43xx_DMA32_RXINDEX, 200);
+- }
+- }
+-
+-out:
+- return err;
+-}
+-
+-/* Shutdown the DMA controller. */
+-static void dmacontroller_cleanup(struct bcm43xx_dmaring *ring)
+-{
+- if (ring->tx) {
+- bcm43xx_dmacontroller_tx_reset(ring->bcm, ring->mmio_base, ring->dma64);
+- if (ring->dma64) {
+- bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGLO, 0);
+- bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGHI, 0);
+- } else
+- bcm43xx_dma_write(ring, BCM43xx_DMA32_TXRING, 0);
+- } else {
+- bcm43xx_dmacontroller_rx_reset(ring->bcm, ring->mmio_base, ring->dma64);
+- if (ring->dma64) {
+- bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGLO, 0);
+- bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGHI, 0);
+- } else
+- bcm43xx_dma_write(ring, BCM43xx_DMA32_RXRING, 0);
+- }
+-}
+-
+-static void free_all_descbuffers(struct bcm43xx_dmaring *ring)
+-{
+- struct bcm43xx_dmadesc_generic *desc;
+- struct bcm43xx_dmadesc_meta *meta;
+- int i;
+-
+- if (!ring->used_slots)
+- return;
+- for (i = 0; i < ring->nr_slots; i++) {
+- desc = bcm43xx_dma_idx2desc(ring, i, &meta);
+-
+- if (!meta->skb) {
+- assert(ring->tx);
+- continue;
+- }
+- if (ring->tx) {
+- unmap_descbuffer(ring, meta->dmaaddr,
+- meta->skb->len, 1);
+- } else {
+- unmap_descbuffer(ring, meta->dmaaddr,
+- ring->rx_buffersize, 0);
+- }
+- free_descriptor_buffer(ring, meta, 0);
+- }
+-}
+-
+-/* Main initialization function. */
+-static
+-struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm,
+- int controller_index,
+- int for_tx,
+- int dma64)
+-{
+- struct bcm43xx_dmaring *ring;
+- int err;
+- int nr_slots;
+-
+- ring = kzalloc(sizeof(*ring), GFP_KERNEL);
+- if (!ring)
+- goto out;
+-
+- nr_slots = BCM43xx_RXRING_SLOTS;
+- if (for_tx)
+- nr_slots = BCM43xx_TXRING_SLOTS;
+-
+- ring->meta = kcalloc(nr_slots, sizeof(struct bcm43xx_dmadesc_meta),
+- GFP_KERNEL);
+- if (!ring->meta)
+- goto err_kfree_ring;
+-
+- ring->routing = BCM43xx_DMA32_CLIENTTRANS;
+- if (dma64)
+- ring->routing = BCM43xx_DMA64_CLIENTTRANS;
+-
+- ring->bcm = bcm;
+- ring->nr_slots = nr_slots;
+- ring->suspend_mark = ring->nr_slots * BCM43xx_TXSUSPEND_PERCENT / 100;
+- ring->resume_mark = ring->nr_slots * BCM43xx_TXRESUME_PERCENT / 100;
+- assert(ring->suspend_mark < ring->resume_mark);
+- ring->mmio_base = bcm43xx_dmacontroller_base(dma64, controller_index);
+- ring->index = controller_index;
+- ring->dma64 = !!dma64;
+- if (for_tx) {
+- ring->tx = 1;
+- ring->current_slot = -1;
+- } else {
+- if (ring->index == 0) {
+- ring->rx_buffersize = BCM43xx_DMA0_RX_BUFFERSIZE;
+- ring->frameoffset = BCM43xx_DMA0_RX_FRAMEOFFSET;
+- } else if (ring->index == 3) {
+- ring->rx_buffersize = BCM43xx_DMA3_RX_BUFFERSIZE;
+- ring->frameoffset = BCM43xx_DMA3_RX_FRAMEOFFSET;
+- } else
+- assert(0);
+- }
+-
+- err = alloc_ringmemory(ring);
+- if (err)
+- goto err_kfree_meta;
+- err = dmacontroller_setup(ring);
+- if (err)
+- goto err_free_ringmemory;
+- return ring;
+-
+-out:
+- printk(KERN_ERR PFX "Error in bcm43xx_setup_dmaring\n");
+- return ring;
+-
+-err_free_ringmemory:
+- free_ringmemory(ring);
+-err_kfree_meta:
+- kfree(ring->meta);
+-err_kfree_ring:
+- kfree(ring);
+- ring = NULL;
+- goto out;
+-}
+-
+-/* Main cleanup function. */
+-static void bcm43xx_destroy_dmaring(struct bcm43xx_dmaring *ring)
+-{
+- if (!ring)
+- return;
+-
+- dprintk(KERN_INFO PFX "DMA-%s 0x%04X (%s) max used slots: %d/%d\n",
+- (ring->dma64) ? "64" : "32",
+- ring->mmio_base,
+- (ring->tx) ? "TX" : "RX",
+- ring->max_used_slots, ring->nr_slots);
+- /* Device IRQs are disabled prior entering this function,
+- * so no need to take care of concurrency with rx handler stuff.
+- */
+- dmacontroller_cleanup(ring);
+- free_all_descbuffers(ring);
+- free_ringmemory(ring);
+-
+- kfree(ring->meta);
+- kfree(ring);
+-}
+-
+-void bcm43xx_dma_free(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_dma *dma;
+-
+- if (bcm43xx_using_pio(bcm))
+- return;
+- dma = bcm43xx_current_dma(bcm);
+-
+- bcm43xx_destroy_dmaring(dma->rx_ring3);
+- dma->rx_ring3 = NULL;
+- bcm43xx_destroy_dmaring(dma->rx_ring0);
+- dma->rx_ring0 = NULL;
+-
+- bcm43xx_destroy_dmaring(dma->tx_ring5);
+- dma->tx_ring5 = NULL;
+- bcm43xx_destroy_dmaring(dma->tx_ring4);
+- dma->tx_ring4 = NULL;
+- bcm43xx_destroy_dmaring(dma->tx_ring3);
+- dma->tx_ring3 = NULL;
+- bcm43xx_destroy_dmaring(dma->tx_ring2);
+- dma->tx_ring2 = NULL;
+- bcm43xx_destroy_dmaring(dma->tx_ring1);
+- dma->tx_ring1 = NULL;
+- bcm43xx_destroy_dmaring(dma->tx_ring0);
+- dma->tx_ring0 = NULL;
+-}
+-
+-int bcm43xx_dma_init(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm);
+- struct bcm43xx_dmaring *ring;
+- int err = -ENOMEM;
+- int dma64 = 0;
+-
+- bcm->dma_mask = bcm43xx_get_supported_dma_mask(bcm);
+- if (bcm->dma_mask == DMA_64BIT_MASK)
+- dma64 = 1;
+- err = pci_set_dma_mask(bcm->pci_dev, bcm->dma_mask);
+- if (err)
+- goto no_dma;
+- err = pci_set_consistent_dma_mask(bcm->pci_dev, bcm->dma_mask);
+- if (err)
+- goto no_dma;
+-
+- /* setup TX DMA channels. */
+- ring = bcm43xx_setup_dmaring(bcm, 0, 1, dma64);
+- if (!ring)
+- goto out;
+- dma->tx_ring0 = ring;
+-
+- ring = bcm43xx_setup_dmaring(bcm, 1, 1, dma64);
+- if (!ring)
+- goto err_destroy_tx0;
+- dma->tx_ring1 = ring;
+-
+- ring = bcm43xx_setup_dmaring(bcm, 2, 1, dma64);
+- if (!ring)
+- goto err_destroy_tx1;
+- dma->tx_ring2 = ring;
+-
+- ring = bcm43xx_setup_dmaring(bcm, 3, 1, dma64);
+- if (!ring)
+- goto err_destroy_tx2;
+- dma->tx_ring3 = ring;
+-
+- ring = bcm43xx_setup_dmaring(bcm, 4, 1, dma64);
+- if (!ring)
+- goto err_destroy_tx3;
+- dma->tx_ring4 = ring;
+-
+- ring = bcm43xx_setup_dmaring(bcm, 5, 1, dma64);
+- if (!ring)
+- goto err_destroy_tx4;
+- dma->tx_ring5 = ring;
+-
+- /* setup RX DMA channels. */
+- ring = bcm43xx_setup_dmaring(bcm, 0, 0, dma64);
+- if (!ring)
+- goto err_destroy_tx5;
+- dma->rx_ring0 = ring;
+-
+- if (bcm->current_core->rev < 5) {
+- ring = bcm43xx_setup_dmaring(bcm, 3, 0, dma64);
+- if (!ring)
+- goto err_destroy_rx0;
+- dma->rx_ring3 = ring;
+- }
+-
+- dprintk(KERN_INFO PFX "%d-bit DMA initialized\n",
+- (bcm->dma_mask == DMA_64BIT_MASK) ? 64 :
+- (bcm->dma_mask == DMA_32BIT_MASK) ? 32 : 30);
+- err = 0;
+-out:
+- return err;
+-
+-err_destroy_rx0:
+- bcm43xx_destroy_dmaring(dma->rx_ring0);
+- dma->rx_ring0 = NULL;
+-err_destroy_tx5:
+- bcm43xx_destroy_dmaring(dma->tx_ring5);
+- dma->tx_ring5 = NULL;
+-err_destroy_tx4:
+- bcm43xx_destroy_dmaring(dma->tx_ring4);
+- dma->tx_ring4 = NULL;
+-err_destroy_tx3:
+- bcm43xx_destroy_dmaring(dma->tx_ring3);
+- dma->tx_ring3 = NULL;
+-err_destroy_tx2:
+- bcm43xx_destroy_dmaring(dma->tx_ring2);
+- dma->tx_ring2 = NULL;
+-err_destroy_tx1:
+- bcm43xx_destroy_dmaring(dma->tx_ring1);
+- dma->tx_ring1 = NULL;
+-err_destroy_tx0:
+- bcm43xx_destroy_dmaring(dma->tx_ring0);
+- dma->tx_ring0 = NULL;
+-no_dma:
+-#ifdef CONFIG_BCM43XX_PIO
+- printk(KERN_WARNING PFX "DMA not supported on this device."
+- " Falling back to PIO.\n");
+- bcm->__using_pio = 1;
+- return -ENOSYS;
+-#else
+- printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
+- "Please recompile the driver with PIO support.\n");
+- return -ENODEV;
+-#endif /* CONFIG_BCM43XX_PIO */
+-}
+-
+-/* Generate a cookie for the TX header. */
+-static u16 generate_cookie(struct bcm43xx_dmaring *ring,
+- int slot)
+-{
+- u16 cookie = 0x1000;
+-
+- /* Use the upper 4 bits of the cookie as
+- * DMA controller ID and store the slot number
+- * in the lower 12 bits.
+- * Note that the cookie must never be 0, as this
+- * is a special value used in RX path.
+- */
+- switch (ring->index) {
+- case 0:
+- cookie = 0xA000;
+- break;
+- case 1:
+- cookie = 0xB000;
+- break;
+- case 2:
+- cookie = 0xC000;
+- break;
+- case 3:
+- cookie = 0xD000;
+- break;
+- case 4:
+- cookie = 0xE000;
+- break;
+- case 5:
+- cookie = 0xF000;
+- break;
+- }
+- assert(((u16)slot & 0xF000) == 0x0000);
+- cookie |= (u16)slot;
+-
+- return cookie;
+-}
+-
+-/* Inspect a cookie and find out to which controller/slot it belongs. */
+-static
+-struct bcm43xx_dmaring * parse_cookie(struct bcm43xx_private *bcm,
+- u16 cookie, int *slot)
+-{
+- struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm);
+- struct bcm43xx_dmaring *ring = NULL;
+-
+- switch (cookie & 0xF000) {
+- case 0xA000:
+- ring = dma->tx_ring0;
+- break;
+- case 0xB000:
+- ring = dma->tx_ring1;
+- break;
+- case 0xC000:
+- ring = dma->tx_ring2;
+- break;
+- case 0xD000:
+- ring = dma->tx_ring3;
+- break;
+- case 0xE000:
+- ring = dma->tx_ring4;
+- break;
+- case 0xF000:
+- ring = dma->tx_ring5;
+- break;
+- default:
+- assert(0);
+- }
+- *slot = (cookie & 0x0FFF);
+- assert(*slot >= 0 && *slot < ring->nr_slots);
+-
+- return ring;
+-}
+-
+-static void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring,
+- int slot)
+-{
+- u16 offset;
+- int descsize;
+-
+- /* Everything is ready to start. Buffers are DMA mapped and
+- * associated with slots.
+- * "slot" is the last slot of the new frame we want to transmit.
+- * Close your seat belts now, please.
+- */
+- wmb();
+- slot = next_slot(ring, slot);
+- offset = (ring->dma64) ? BCM43xx_DMA64_TXINDEX : BCM43xx_DMA32_TXINDEX;
+- descsize = (ring->dma64) ? sizeof(struct bcm43xx_dmadesc64)
+- : sizeof(struct bcm43xx_dmadesc32);
+- bcm43xx_dma_write(ring, offset,
+- (u32)(slot * descsize));
+-}
+-
+-static void dma_tx_fragment(struct bcm43xx_dmaring *ring,
+- struct sk_buff *skb,
+- u8 cur_frag)
+-{
+- int slot;
+- struct bcm43xx_dmadesc_generic *desc;
+- struct bcm43xx_dmadesc_meta *meta;
+- dma_addr_t dmaaddr;
+- struct sk_buff *bounce_skb;
+-
+- assert(skb_shinfo(skb)->nr_frags == 0);
+-
+- slot = request_slot(ring);
+- desc = bcm43xx_dma_idx2desc(ring, slot, &meta);
+-
+- /* Add a device specific TX header. */
+- assert(skb_headroom(skb) >= sizeof(struct bcm43xx_txhdr));
+- /* Reserve enough headroom for the device tx header. */
+- __skb_push(skb, sizeof(struct bcm43xx_txhdr));
+- /* Now calculate and add the tx header.
+- * The tx header includes the PLCP header.
+- */
+- bcm43xx_generate_txhdr(ring->bcm,
+- (struct bcm43xx_txhdr *)skb->data,
+- skb->data + sizeof(struct bcm43xx_txhdr),
+- skb->len - sizeof(struct bcm43xx_txhdr),
+- (cur_frag == 0),
+- generate_cookie(ring, slot));
+- dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
+- if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) {
+- /* chip cannot handle DMA to/from > 1GB, use bounce buffer (copied from b44 driver) */
+- if (!dma_mapping_error(dmaaddr))
+- unmap_descbuffer(ring, dmaaddr, skb->len, 1);
+- bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC|GFP_DMA);
+- if (!bounce_skb)
+- return;
+- dmaaddr = map_descbuffer(ring, bounce_skb->data, bounce_skb->len, 1);
+- if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) {
+- if (!dma_mapping_error(dmaaddr))
+- unmap_descbuffer(ring, dmaaddr, skb->len, 1);
+- dev_kfree_skb_any(bounce_skb);
+- assert(0);
+- return;
+- }
+- skb_copy_from_linear_data(skb, skb_put(bounce_skb, skb->len),
+- skb->len);
+- dev_kfree_skb_any(skb);
+- skb = bounce_skb;
+- }
+-
+- meta->skb = skb;
+- meta->dmaaddr = dmaaddr;
+-
+- fill_descriptor(ring, desc, dmaaddr,
+- skb->len, 1, 1, 1);
+-
+- /* Now transfer the whole frame. */
+- dmacontroller_poke_tx(ring, slot);
+-}
+-
+-int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
+- struct ieee80211_txb *txb)
+-{
+- /* We just received a packet from the kernel network subsystem.
+- * Add headers and DMA map the memory. Poke
+- * the device to send the stuff.
+- * Note that this is called from atomic context.
+- */
+- struct bcm43xx_dmaring *ring = bcm43xx_current_dma(bcm)->tx_ring1;
+- u8 i;
+- struct sk_buff *skb;
+-
+- assert(ring->tx);
+- if (unlikely(free_slots(ring) < txb->nr_frags)) {
+- /* The queue should be stopped,
+- * if we are low on free slots.
+- * If this ever triggers, we have to lower the suspend_mark.
+- */
+- dprintkl(KERN_ERR PFX "Out of DMA descriptor slots!\n");
+- return -ENOMEM;
+- }
+-
+- for (i = 0; i < txb->nr_frags; i++) {
+- skb = txb->fragments[i];
+- /* Take skb from ieee80211_txb_free */
+- txb->fragments[i] = NULL;
+- dma_tx_fragment(ring, skb, i);
+- }
+- ieee80211_txb_free(txb);
+-
+- return 0;
+-}
+-
+-void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm,
+- struct bcm43xx_xmitstatus *status)
+-{
+- struct bcm43xx_dmaring *ring;
+- struct bcm43xx_dmadesc_generic *desc;
+- struct bcm43xx_dmadesc_meta *meta;
+- int is_last_fragment;
+- int slot;
+- u32 tmp;
+-
+- ring = parse_cookie(bcm, status->cookie, &slot);
+- assert(ring);
+- assert(ring->tx);
+- while (1) {
+- assert(slot >= 0 && slot < ring->nr_slots);
+- desc = bcm43xx_dma_idx2desc(ring, slot, &meta);
+-
+- if (ring->dma64) {
+- tmp = le32_to_cpu(desc->dma64.control0);
+- is_last_fragment = !!(tmp & BCM43xx_DMA64_DCTL0_FRAMEEND);
+- } else {
+- tmp = le32_to_cpu(desc->dma32.control);
+- is_last_fragment = !!(tmp & BCM43xx_DMA32_DCTL_FRAMEEND);
+- }
+- unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1);
+- free_descriptor_buffer(ring, meta, 1);
+- /* Everything belonging to the slot is unmapped
+- * and freed, so we can return it.
+- */
+- return_slot(ring, slot);
+-
+- if (is_last_fragment)
+- break;
+- slot = next_slot(ring, slot);
+- }
+- bcm->stats.last_tx = jiffies;
+-}
+-
+-static void dma_rx(struct bcm43xx_dmaring *ring,
+- int *slot)
+-{
+- struct bcm43xx_dmadesc_generic *desc;
+- struct bcm43xx_dmadesc_meta *meta;
+- struct bcm43xx_rxhdr *rxhdr;
+- struct sk_buff *skb;
+- u16 len;
+- int err;
+- dma_addr_t dmaaddr;
+-
+- desc = bcm43xx_dma_idx2desc(ring, *slot, &meta);
+-
+- sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize);
+- skb = meta->skb;
+-
+- if (ring->index == 3) {
+- /* We received an xmit status. */
+- struct bcm43xx_hwxmitstatus *hw = (struct bcm43xx_hwxmitstatus *)skb->data;
+- struct bcm43xx_xmitstatus stat;
+- int i = 0;
+-
+- stat.cookie = le16_to_cpu(hw->cookie);
+- while (stat.cookie == 0) {
+- if (unlikely(++i >= 10000)) {
+- assert(0);
+- break;
+- }
+- udelay(2);
+- barrier();
+- stat.cookie = le16_to_cpu(hw->cookie);
+- }
+- stat.flags = hw->flags;
+- stat.cnt1 = hw->cnt1;
+- stat.cnt2 = hw->cnt2;
+- stat.seq = le16_to_cpu(hw->seq);
+- stat.unknown = le16_to_cpu(hw->unknown);
+-
+- bcm43xx_debugfs_log_txstat(ring->bcm, &stat);
+- bcm43xx_dma_handle_xmitstatus(ring->bcm, &stat);
+- /* recycle the descriptor buffer. */
+- sync_descbuffer_for_device(ring, meta->dmaaddr, ring->rx_buffersize);
+-
+- return;
+- }
+- rxhdr = (struct bcm43xx_rxhdr *)skb->data;
+- len = le16_to_cpu(rxhdr->frame_length);
+- if (len == 0) {
+- int i = 0;
+-
+- do {
+- udelay(2);
+- barrier();
+- len = le16_to_cpu(rxhdr->frame_length);
+- } while (len == 0 && i++ < 5);
+- if (unlikely(len == 0)) {
+- /* recycle the descriptor buffer. */
+- sync_descbuffer_for_device(ring, meta->dmaaddr,
+- ring->rx_buffersize);
+- goto drop;
+- }
+- }
+- if (unlikely(len > ring->rx_buffersize)) {
+- /* The data did not fit into one descriptor buffer
+- * and is split over multiple buffers.
+- * This should never happen, as we try to allocate buffers
+- * big enough. So simply ignore this packet.
+- */
+- int cnt = 0;
+- s32 tmp = len;
+-
+- while (1) {
+- desc = bcm43xx_dma_idx2desc(ring, *slot, &meta);
+- /* recycle the descriptor buffer. */
+- sync_descbuffer_for_device(ring, meta->dmaaddr,
+- ring->rx_buffersize);
+- *slot = next_slot(ring, *slot);
+- cnt++;
+- tmp -= ring->rx_buffersize;
+- if (tmp <= 0)
+- break;
+- }
+- printkl(KERN_ERR PFX "DMA RX buffer too small "
+- "(len: %u, buffer: %u, nr-dropped: %d)\n",
+- len, ring->rx_buffersize, cnt);
+- goto drop;
+- }
+- len -= IEEE80211_FCS_LEN;
+-
+- dmaaddr = meta->dmaaddr;
+- err = setup_rx_descbuffer(ring, desc, meta, GFP_ATOMIC);
+- if (unlikely(err)) {
+- dprintkl(KERN_ERR PFX "DMA RX: setup_rx_descbuffer() failed\n");
+- sync_descbuffer_for_device(ring, dmaaddr,
+- ring->rx_buffersize);
+- goto drop;
+- }
+-
+- unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0);
+- skb_put(skb, len + ring->frameoffset);
+- skb_pull(skb, ring->frameoffset);
+-
+- err = bcm43xx_rx(ring->bcm, skb, rxhdr);
+- if (err) {
+- dev_kfree_skb_irq(skb);
+- goto drop;
+- }
+-
+-drop:
+- return;
+-}
+-
+-void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)
+-{
+- u32 status;
+- u16 descptr;
+- int slot, current_slot;
+-#ifdef CONFIG_BCM43XX_DEBUG
+- int used_slots = 0;
+-#endif
+-
+- assert(!ring->tx);
+- if (ring->dma64) {
+- status = bcm43xx_dma_read(ring, BCM43xx_DMA64_RXSTATUS);
+- descptr = (status & BCM43xx_DMA64_RXSTATDPTR);
+- current_slot = descptr / sizeof(struct bcm43xx_dmadesc64);
+- } else {
+- status = bcm43xx_dma_read(ring, BCM43xx_DMA32_RXSTATUS);
+- descptr = (status & BCM43xx_DMA32_RXDPTR);
+- current_slot = descptr / sizeof(struct bcm43xx_dmadesc32);
+- }
+- assert(current_slot >= 0 && current_slot < ring->nr_slots);
+-
+- slot = ring->current_slot;
+- for ( ; slot != current_slot; slot = next_slot(ring, slot)) {
+- dma_rx(ring, &slot);
+-#ifdef CONFIG_BCM43XX_DEBUG
+- if (++used_slots > ring->max_used_slots)
+- ring->max_used_slots = used_slots;
+-#endif
+- }
+- if (ring->dma64) {
+- bcm43xx_dma_write(ring, BCM43xx_DMA64_RXINDEX,
+- (u32)(slot * sizeof(struct bcm43xx_dmadesc64)));
+- } else {
+- bcm43xx_dma_write(ring, BCM43xx_DMA32_RXINDEX,
+- (u32)(slot * sizeof(struct bcm43xx_dmadesc32)));
+- }
+- ring->current_slot = slot;
+-}
+-
+-void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring)
+-{
+- assert(ring->tx);
+- bcm43xx_power_saving_ctl_bits(ring->bcm, -1, 1);
+- if (ring->dma64) {
+- bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL,
+- bcm43xx_dma_read(ring, BCM43xx_DMA64_TXCTL)
+- | BCM43xx_DMA64_TXSUSPEND);
+- } else {
+- bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL,
+- bcm43xx_dma_read(ring, BCM43xx_DMA32_TXCTL)
+- | BCM43xx_DMA32_TXSUSPEND);
+- }
+-}
+-
+-void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring)
+-{
+- assert(ring->tx);
+- if (ring->dma64) {
+- bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL,
+- bcm43xx_dma_read(ring, BCM43xx_DMA64_TXCTL)
+- & ~BCM43xx_DMA64_TXSUSPEND);
+- } else {
+- bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL,
+- bcm43xx_dma_read(ring, BCM43xx_DMA32_TXCTL)
+- & ~BCM43xx_DMA32_TXSUSPEND);
+- }
+- bcm43xx_power_saving_ctl_bits(ring->bcm, -1, -1);
+-}
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
+deleted file mode 100644
+index d1105e5..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
++++ /dev/null
+@@ -1,386 +0,0 @@
+-#ifndef BCM43xx_DMA_H_
+-#define BCM43xx_DMA_H_
+-
+-#include <linux/list.h>
+-#include <linux/spinlock.h>
+-#include <linux/workqueue.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/linkage.h>
+-#include <asm/atomic.h>
+-
+-
+-/* DMA-Interrupt reasons. */
+-#define BCM43xx_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \
+- | (1 << 14) | (1 << 15))
+-#define BCM43xx_DMAIRQ_NONFATALMASK (1 << 13)
+-#define BCM43xx_DMAIRQ_RX_DONE (1 << 16)
+-
+-
+-/*** 32-bit DMA Engine. ***/
+-
+-/* 32-bit DMA controller registers. */
+-#define BCM43xx_DMA32_TXCTL 0x00
+-#define BCM43xx_DMA32_TXENABLE 0x00000001
+-#define BCM43xx_DMA32_TXSUSPEND 0x00000002
+-#define BCM43xx_DMA32_TXLOOPBACK 0x00000004
+-#define BCM43xx_DMA32_TXFLUSH 0x00000010
+-#define BCM43xx_DMA32_TXADDREXT_MASK 0x00030000
+-#define BCM43xx_DMA32_TXADDREXT_SHIFT 16
+-#define BCM43xx_DMA32_TXRING 0x04
+-#define BCM43xx_DMA32_TXINDEX 0x08
+-#define BCM43xx_DMA32_TXSTATUS 0x0C
+-#define BCM43xx_DMA32_TXDPTR 0x00000FFF
+-#define BCM43xx_DMA32_TXSTATE 0x0000F000
+-#define BCM43xx_DMA32_TXSTAT_DISABLED 0x00000000
+-#define BCM43xx_DMA32_TXSTAT_ACTIVE 0x00001000
+-#define BCM43xx_DMA32_TXSTAT_IDLEWAIT 0x00002000
+-#define BCM43xx_DMA32_TXSTAT_STOPPED 0x00003000
+-#define BCM43xx_DMA32_TXSTAT_SUSP 0x00004000
+-#define BCM43xx_DMA32_TXERROR 0x000F0000
+-#define BCM43xx_DMA32_TXERR_NOERR 0x00000000
+-#define BCM43xx_DMA32_TXERR_PROT 0x00010000
+-#define BCM43xx_DMA32_TXERR_UNDERRUN 0x00020000
+-#define BCM43xx_DMA32_TXERR_BUFREAD 0x00030000
+-#define BCM43xx_DMA32_TXERR_DESCREAD 0x00040000
+-#define BCM43xx_DMA32_TXACTIVE 0xFFF00000
+-#define BCM43xx_DMA32_RXCTL 0x10
+-#define BCM43xx_DMA32_RXENABLE 0x00000001
+-#define BCM43xx_DMA32_RXFROFF_MASK 0x000000FE
+-#define BCM43xx_DMA32_RXFROFF_SHIFT 1
+-#define BCM43xx_DMA32_RXDIRECTFIFO 0x00000100
+-#define BCM43xx_DMA32_RXADDREXT_MASK 0x00030000
+-#define BCM43xx_DMA32_RXADDREXT_SHIFT 16
+-#define BCM43xx_DMA32_RXRING 0x14
+-#define BCM43xx_DMA32_RXINDEX 0x18
+-#define BCM43xx_DMA32_RXSTATUS 0x1C
+-#define BCM43xx_DMA32_RXDPTR 0x00000FFF
+-#define BCM43xx_DMA32_RXSTATE 0x0000F000
+-#define BCM43xx_DMA32_RXSTAT_DISABLED 0x00000000
+-#define BCM43xx_DMA32_RXSTAT_ACTIVE 0x00001000
+-#define BCM43xx_DMA32_RXSTAT_IDLEWAIT 0x00002000
+-#define BCM43xx_DMA32_RXSTAT_STOPPED 0x00003000
+-#define BCM43xx_DMA32_RXERROR 0x000F0000
+-#define BCM43xx_DMA32_RXERR_NOERR 0x00000000
+-#define BCM43xx_DMA32_RXERR_PROT 0x00010000
+-#define BCM43xx_DMA32_RXERR_OVERFLOW 0x00020000
+-#define BCM43xx_DMA32_RXERR_BUFWRITE 0x00030000
+-#define BCM43xx_DMA32_RXERR_DESCREAD 0x00040000
+-#define BCM43xx_DMA32_RXACTIVE 0xFFF00000
+-
+-/* 32-bit DMA descriptor. */
+-struct bcm43xx_dmadesc32 {
+- __le32 control;
+- __le32 address;
+-} __attribute__((__packed__));
+-#define BCM43xx_DMA32_DCTL_BYTECNT 0x00001FFF
+-#define BCM43xx_DMA32_DCTL_ADDREXT_MASK 0x00030000
+-#define BCM43xx_DMA32_DCTL_ADDREXT_SHIFT 16
+-#define BCM43xx_DMA32_DCTL_DTABLEEND 0x10000000
+-#define BCM43xx_DMA32_DCTL_IRQ 0x20000000
+-#define BCM43xx_DMA32_DCTL_FRAMEEND 0x40000000
+-#define BCM43xx_DMA32_DCTL_FRAMESTART 0x80000000
+-
+-/* Address field Routing value. */
+-#define BCM43xx_DMA32_ROUTING 0xC0000000
+-#define BCM43xx_DMA32_ROUTING_SHIFT 30
+-#define BCM43xx_DMA32_NOTRANS 0x00000000
+-#define BCM43xx_DMA32_CLIENTTRANS 0x40000000
+-
+-
+-
+-/*** 64-bit DMA Engine. ***/
+-
+-/* 64-bit DMA controller registers. */
+-#define BCM43xx_DMA64_TXCTL 0x00
+-#define BCM43xx_DMA64_TXENABLE 0x00000001
+-#define BCM43xx_DMA64_TXSUSPEND 0x00000002
+-#define BCM43xx_DMA64_TXLOOPBACK 0x00000004
+-#define BCM43xx_DMA64_TXFLUSH 0x00000010
+-#define BCM43xx_DMA64_TXADDREXT_MASK 0x00030000
+-#define BCM43xx_DMA64_TXADDREXT_SHIFT 16
+-#define BCM43xx_DMA64_TXINDEX 0x04
+-#define BCM43xx_DMA64_TXRINGLO 0x08
+-#define BCM43xx_DMA64_TXRINGHI 0x0C
+-#define BCM43xx_DMA64_TXSTATUS 0x10
+-#define BCM43xx_DMA64_TXSTATDPTR 0x00001FFF
+-#define BCM43xx_DMA64_TXSTAT 0xF0000000
+-#define BCM43xx_DMA64_TXSTAT_DISABLED 0x00000000
+-#define BCM43xx_DMA64_TXSTAT_ACTIVE 0x10000000
+-#define BCM43xx_DMA64_TXSTAT_IDLEWAIT 0x20000000
+-#define BCM43xx_DMA64_TXSTAT_STOPPED 0x30000000
+-#define BCM43xx_DMA64_TXSTAT_SUSP 0x40000000
+-#define BCM43xx_DMA64_TXERROR 0x14
+-#define BCM43xx_DMA64_TXERRDPTR 0x0001FFFF
+-#define BCM43xx_DMA64_TXERR 0xF0000000
+-#define BCM43xx_DMA64_TXERR_NOERR 0x00000000
+-#define BCM43xx_DMA64_TXERR_PROT 0x10000000
+-#define BCM43xx_DMA64_TXERR_UNDERRUN 0x20000000
+-#define BCM43xx_DMA64_TXERR_TRANSFER 0x30000000
+-#define BCM43xx_DMA64_TXERR_DESCREAD 0x40000000
+-#define BCM43xx_DMA64_TXERR_CORE 0x50000000
+-#define BCM43xx_DMA64_RXCTL 0x20
+-#define BCM43xx_DMA64_RXENABLE 0x00000001
+-#define BCM43xx_DMA64_RXFROFF_MASK 0x000000FE
+-#define BCM43xx_DMA64_RXFROFF_SHIFT 1
+-#define BCM43xx_DMA64_RXDIRECTFIFO 0x00000100
+-#define BCM43xx_DMA64_RXADDREXT_MASK 0x00030000
+-#define BCM43xx_DMA64_RXADDREXT_SHIFT 16
+-#define BCM43xx_DMA64_RXINDEX 0x24
+-#define BCM43xx_DMA64_RXRINGLO 0x28
+-#define BCM43xx_DMA64_RXRINGHI 0x2C
+-#define BCM43xx_DMA64_RXSTATUS 0x30
+-#define BCM43xx_DMA64_RXSTATDPTR 0x00001FFF
+-#define BCM43xx_DMA64_RXSTAT 0xF0000000
+-#define BCM43xx_DMA64_RXSTAT_DISABLED 0x00000000
+-#define BCM43xx_DMA64_RXSTAT_ACTIVE 0x10000000
+-#define BCM43xx_DMA64_RXSTAT_IDLEWAIT 0x20000000
+-#define BCM43xx_DMA64_RXSTAT_STOPPED 0x30000000
+-#define BCM43xx_DMA64_RXSTAT_SUSP 0x40000000
+-#define BCM43xx_DMA64_RXERROR 0x34
+-#define BCM43xx_DMA64_RXERRDPTR 0x0001FFFF
+-#define BCM43xx_DMA64_RXERR 0xF0000000
+-#define BCM43xx_DMA64_RXERR_NOERR 0x00000000
+-#define BCM43xx_DMA64_RXERR_PROT 0x10000000
+-#define BCM43xx_DMA64_RXERR_UNDERRUN 0x20000000
+-#define BCM43xx_DMA64_RXERR_TRANSFER 0x30000000
+-#define BCM43xx_DMA64_RXERR_DESCREAD 0x40000000
+-#define BCM43xx_DMA64_RXERR_CORE 0x50000000
+-
+-/* 64-bit DMA descriptor. */
+-struct bcm43xx_dmadesc64 {
+- __le32 control0;
+- __le32 control1;
+- __le32 address_low;
+- __le32 address_high;
+-} __attribute__((__packed__));
+-#define BCM43xx_DMA64_DCTL0_DTABLEEND 0x10000000
+-#define BCM43xx_DMA64_DCTL0_IRQ 0x20000000
+-#define BCM43xx_DMA64_DCTL0_FRAMEEND 0x40000000
+-#define BCM43xx_DMA64_DCTL0_FRAMESTART 0x80000000
+-#define BCM43xx_DMA64_DCTL1_BYTECNT 0x00001FFF
+-#define BCM43xx_DMA64_DCTL1_ADDREXT_MASK 0x00030000
+-#define BCM43xx_DMA64_DCTL1_ADDREXT_SHIFT 16
+-
+-/* Address field Routing value. */
+-#define BCM43xx_DMA64_ROUTING 0xC0000000
+-#define BCM43xx_DMA64_ROUTING_SHIFT 30
+-#define BCM43xx_DMA64_NOTRANS 0x00000000
+-#define BCM43xx_DMA64_CLIENTTRANS 0x80000000
+-
+-
+-
+-struct bcm43xx_dmadesc_generic {
+- union {
+- struct bcm43xx_dmadesc32 dma32;
+- struct bcm43xx_dmadesc64 dma64;
+- } __attribute__((__packed__));
+-} __attribute__((__packed__));
+-
+-
+-/* Misc DMA constants */
+-#define BCM43xx_DMA_RINGMEMSIZE PAGE_SIZE
+-#define BCM43xx_DMA0_RX_FRAMEOFFSET 30
+-#define BCM43xx_DMA3_RX_FRAMEOFFSET 0
+-
+-
+-/* DMA engine tuning knobs */
+-#define BCM43xx_TXRING_SLOTS 512
+-#define BCM43xx_RXRING_SLOTS 64
+-#define BCM43xx_DMA0_RX_BUFFERSIZE (2304 + 100)
+-#define BCM43xx_DMA3_RX_BUFFERSIZE 16
+-/* Suspend the tx queue, if less than this percent slots are free. */
+-#define BCM43xx_TXSUSPEND_PERCENT 20
+-/* Resume the tx queue, if more than this percent slots are free. */
+-#define BCM43xx_TXRESUME_PERCENT 50
+-
+-
+-
+-#ifdef CONFIG_BCM43XX_DMA
+-
+-
+-struct sk_buff;
+-struct bcm43xx_private;
+-struct bcm43xx_xmitstatus;
+-
+-
+-struct bcm43xx_dmadesc_meta {
+- /* The kernel DMA-able buffer. */
+- struct sk_buff *skb;
+- /* DMA base bus-address of the descriptor buffer. */
+- dma_addr_t dmaaddr;
+-};
+-
+-struct bcm43xx_dmaring {
+- /* Kernel virtual base address of the ring memory. */
+- void *descbase;
+- /* Meta data about all descriptors. */
+- struct bcm43xx_dmadesc_meta *meta;
+- /* DMA Routing value. */
+- u32 routing;
+- /* (Unadjusted) DMA base bus-address of the ring memory. */
+- dma_addr_t dmabase;
+- /* Number of descriptor slots in the ring. */
+- int nr_slots;
+- /* Number of used descriptor slots. */
+- int used_slots;
+- /* Currently used slot in the ring. */
+- int current_slot;
+- /* Marks to suspend/resume the queue. */
+- int suspend_mark;
+- int resume_mark;
+- /* Frameoffset in octets. */
+- u32 frameoffset;
+- /* Descriptor buffer size. */
+- u16 rx_buffersize;
+- /* The MMIO base register of the DMA controller. */
+- u16 mmio_base;
+- /* DMA controller index number (0-5). */
+- int index;
+- /* Boolean. Is this a TX ring? */
+- u8 tx;
+- /* Boolean. 64bit DMA if true, 32bit DMA otherwise. */
+- u8 dma64;
+- /* Boolean. Are transfers suspended on this ring? */
+- u8 suspended;
+- struct bcm43xx_private *bcm;
+-#ifdef CONFIG_BCM43XX_DEBUG
+- /* Maximum number of used slots. */
+- int max_used_slots;
+-#endif /* CONFIG_BCM43XX_DEBUG*/
+-};
+-
+-
+-static inline
+-int bcm43xx_dma_desc2idx(struct bcm43xx_dmaring *ring,
+- struct bcm43xx_dmadesc_generic *desc)
+-{
+- if (ring->dma64) {
+- struct bcm43xx_dmadesc64 *dd64 = ring->descbase;
+- return (int)(&(desc->dma64) - dd64);
+- } else {
+- struct bcm43xx_dmadesc32 *dd32 = ring->descbase;
+- return (int)(&(desc->dma32) - dd32);
+- }
+-}
+-
+-static inline
+-struct bcm43xx_dmadesc_generic * bcm43xx_dma_idx2desc(struct bcm43xx_dmaring *ring,
+- int slot,
+- struct bcm43xx_dmadesc_meta **meta)
+-{
+- *meta = &(ring->meta[slot]);
+- if (ring->dma64) {
+- struct bcm43xx_dmadesc64 *dd64 = ring->descbase;
+- return (struct bcm43xx_dmadesc_generic *)(&(dd64[slot]));
+- } else {
+- struct bcm43xx_dmadesc32 *dd32 = ring->descbase;
+- return (struct bcm43xx_dmadesc_generic *)(&(dd32[slot]));
+- }
+-}
+-
+-static inline
+-u32 bcm43xx_dma_read(struct bcm43xx_dmaring *ring,
+- u16 offset)
+-{
+- return bcm43xx_read32(ring->bcm, ring->mmio_base + offset);
+-}
+-
+-static inline
+-void bcm43xx_dma_write(struct bcm43xx_dmaring *ring,
+- u16 offset, u32 value)
+-{
+- bcm43xx_write32(ring->bcm, ring->mmio_base + offset, value);
+-}
+-
+-
+-int bcm43xx_dma_init(struct bcm43xx_private *bcm);
+-void bcm43xx_dma_free(struct bcm43xx_private *bcm);
+-
+-int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
+- u16 dmacontroller_mmio_base,
+- int dma64);
+-int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
+- u16 dmacontroller_mmio_base,
+- int dma64);
+-
+-u16 bcm43xx_dmacontroller_base(int dma64bit, int dmacontroller_idx);
+-
+-void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring);
+-void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring);
+-
+-void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm,
+- struct bcm43xx_xmitstatus *status);
+-
+-int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
+- struct ieee80211_txb *txb);
+-void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring);
+-
+-/* Helper function that returns the dma mask for this device. */
+-static inline
+-u64 bcm43xx_get_supported_dma_mask(struct bcm43xx_private *bcm)
+-{
+- int dma64 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH) &
+- BCM43xx_SBTMSTATEHIGH_DMA64BIT;
+- u16 mmio_base = bcm43xx_dmacontroller_base(dma64, 0);
+- u32 mask = BCM43xx_DMA32_TXADDREXT_MASK;
+-
+- if (dma64)
+- return DMA_64BIT_MASK;
+- bcm43xx_write32(bcm, mmio_base + BCM43xx_DMA32_TXCTL, mask);
+- if (bcm43xx_read32(bcm, mmio_base + BCM43xx_DMA32_TXCTL) & mask)
+- return DMA_32BIT_MASK;
+- return DMA_30BIT_MASK;
+-}
+-
+-#else /* CONFIG_BCM43XX_DMA */
+-
+-
+-static inline
+-int bcm43xx_dma_init(struct bcm43xx_private *bcm)
+-{
+- return 0;
+-}
+-static inline
+-void bcm43xx_dma_free(struct bcm43xx_private *bcm)
+-{
+-}
+-static inline
+-int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
+- u16 dmacontroller_mmio_base,
+- int dma64)
+-{
+- return 0;
+-}
+-static inline
+-int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
+- u16 dmacontroller_mmio_base,
+- int dma64)
+-{
+- return 0;
+-}
+-static inline
+-int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
+- struct ieee80211_txb *txb)
+-{
+- return 0;
+-}
+-static inline
+-void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm,
+- struct bcm43xx_xmitstatus *status)
+-{
+-}
+-static inline
+-void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)
+-{
+-}
+-static inline
+-void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring)
+-{
+-}
+-static inline
+-void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring)
+-{
+-}
+-
+-#endif /* CONFIG_BCM43XX_DMA */
+-#endif /* BCM43xx_DMA_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c
+deleted file mode 100644
+index d2df6a0..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c
++++ /dev/null
+@@ -1,50 +0,0 @@
+-/*
+-
+- Broadcom BCM43xx wireless driver
+-
+- ethtool support
+-
+- Copyright (c) 2006 Jason Lunz <lunz at falooley.org>
+-
+- Some code in this file is derived from the 8139too.c driver
+- Copyright (C) 2002 Jeff Garzik
+-
+- 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; see the file COPYING. If not, write to
+- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+- Boston, MA 02110-1301, USA.
+-
+-*/
+-
+-#include "bcm43xx.h"
+-#include "bcm43xx_ethtool.h"
+-
+-#include <linux/netdevice.h>
+-#include <linux/pci.h>
+-#include <linux/string.h>
+-#include <linux/utsname.h>
+-
+-
+-static void bcm43xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(dev);
+-
+- strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
+- strncpy(info->version, utsname()->release, sizeof(info->version));
+- strncpy(info->bus_info, pci_name(bcm->pci_dev), ETHTOOL_BUSINFO_LEN);
+-}
+-
+-const struct ethtool_ops bcm43xx_ethtool_ops = {
+- .get_drvinfo = bcm43xx_get_drvinfo,
+- .get_link = ethtool_op_get_link,
+-};
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h
+deleted file mode 100644
+index 6f8d42d..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h
++++ /dev/null
+@@ -1,8 +0,0 @@
+-#ifndef BCM43xx_ETHTOOL_H_
+-#define BCM43xx_ETHTOOL_H_
+-
+-#include <linux/ethtool.h>
+-
+-extern const struct ethtool_ops bcm43xx_ethtool_ops;
+-
+-#endif /* BCM43xx_ETHTOOL_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c
+deleted file mode 100644
+index f2b8dba..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c
++++ /dev/null
+@@ -1,352 +0,0 @@
+-/*
+-
+- Broadcom BCM43xx wireless driver
+-
+- Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+- Stefano Brivio <st3 at riseup.net>
+- Michael Buesch <mbuesch at freenet.de>
+- Danny van Dyk <kugelfang at gentoo.org>
+- Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+- 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; see the file COPYING. If not, write to
+- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+- Boston, MA 02110-1301, USA.
+-
+-*/
+-
+-#include "bcm43xx.h"
+-#include "bcm43xx_ilt.h"
+-#include "bcm43xx_phy.h"
+-
+-
+-/**** Initial Internal Lookup Tables ****/
+-
+-const u32 bcm43xx_ilt_rotor[BCM43xx_ILT_ROTOR_SIZE] = {
+- 0xFEB93FFD, 0xFEC63FFD, /* 0 */
+- 0xFED23FFD, 0xFEDF3FFD,
+- 0xFEEC3FFE, 0xFEF83FFE,
+- 0xFF053FFE, 0xFF113FFE,
+- 0xFF1E3FFE, 0xFF2A3FFF, /* 8 */
+- 0xFF373FFF, 0xFF443FFF,
+- 0xFF503FFF, 0xFF5D3FFF,
+- 0xFF693FFF, 0xFF763FFF,
+- 0xFF824000, 0xFF8F4000, /* 16 */
+- 0xFF9B4000, 0xFFA84000,
+- 0xFFB54000, 0xFFC14000,
+- 0xFFCE4000, 0xFFDA4000,
+- 0xFFE74000, 0xFFF34000, /* 24 */
+- 0x00004000, 0x000D4000,
+- 0x00194000, 0x00264000,
+- 0x00324000, 0x003F4000,
+- 0x004B4000, 0x00584000, /* 32 */
+- 0x00654000, 0x00714000,
+- 0x007E4000, 0x008A3FFF,
+- 0x00973FFF, 0x00A33FFF,
+- 0x00B03FFF, 0x00BC3FFF, /* 40 */
+- 0x00C93FFF, 0x00D63FFF,
+- 0x00E23FFE, 0x00EF3FFE,
+- 0x00FB3FFE, 0x01083FFE,
+- 0x01143FFE, 0x01213FFD, /* 48 */
+- 0x012E3FFD, 0x013A3FFD,
+- 0x01473FFD,
+-};
+-
+-const u32 bcm43xx_ilt_retard[BCM43xx_ILT_RETARD_SIZE] = {
+- 0xDB93CB87, 0xD666CF64, /* 0 */
+- 0xD1FDD358, 0xCDA6D826,
+- 0xCA38DD9F, 0xC729E2B4,
+- 0xC469E88E, 0xC26AEE2B,
+- 0xC0DEF46C, 0xC073FA62, /* 8 */
+- 0xC01D00D5, 0xC0760743,
+- 0xC1560D1E, 0xC2E51369,
+- 0xC4ED18FF, 0xC7AC1ED7,
+- 0xCB2823B2, 0xCEFA28D9, /* 16 */
+- 0xD2F62D3F, 0xD7BB3197,
+- 0xDCE53568, 0xE1FE3875,
+- 0xE7D13B35, 0xED663D35,
+- 0xF39B3EC4, 0xF98E3FA7, /* 24 */
+- 0x00004000, 0x06723FA7,
+- 0x0C653EC4, 0x129A3D35,
+- 0x182F3B35, 0x1E023875,
+- 0x231B3568, 0x28453197, /* 32 */
+- 0x2D0A2D3F, 0x310628D9,
+- 0x34D823B2, 0x38541ED7,
+- 0x3B1318FF, 0x3D1B1369,
+- 0x3EAA0D1E, 0x3F8A0743, /* 40 */
+- 0x3FE300D5, 0x3F8DFA62,
+- 0x3F22F46C, 0x3D96EE2B,
+- 0x3B97E88E, 0x38D7E2B4,
+- 0x35C8DD9F, 0x325AD826, /* 48 */
+- 0x2E03D358, 0x299ACF64,
+- 0x246DCB87,
+-};
+-
+-const u16 bcm43xx_ilt_finefreqa[BCM43xx_ILT_FINEFREQA_SIZE] = {
+- 0x0082, 0x0082, 0x0102, 0x0182, /* 0 */
+- 0x0202, 0x0282, 0x0302, 0x0382,
+- 0x0402, 0x0482, 0x0502, 0x0582,
+- 0x05E2, 0x0662, 0x06E2, 0x0762,
+- 0x07E2, 0x0842, 0x08C2, 0x0942, /* 16 */
+- 0x09C2, 0x0A22, 0x0AA2, 0x0B02,
+- 0x0B82, 0x0BE2, 0x0C62, 0x0CC2,
+- 0x0D42, 0x0DA2, 0x0E02, 0x0E62,
+- 0x0EE2, 0x0F42, 0x0FA2, 0x1002, /* 32 */
+- 0x1062, 0x10C2, 0x1122, 0x1182,
+- 0x11E2, 0x1242, 0x12A2, 0x12E2,
+- 0x1342, 0x13A2, 0x1402, 0x1442,
+- 0x14A2, 0x14E2, 0x1542, 0x1582, /* 48 */
+- 0x15E2, 0x1622, 0x1662, 0x16C1,
+- 0x1701, 0x1741, 0x1781, 0x17E1,
+- 0x1821, 0x1861, 0x18A1, 0x18E1,
+- 0x1921, 0x1961, 0x19A1, 0x19E1, /* 64 */
+- 0x1A21, 0x1A61, 0x1AA1, 0x1AC1,
+- 0x1B01, 0x1B41, 0x1B81, 0x1BA1,
+- 0x1BE1, 0x1C21, 0x1C41, 0x1C81,
+- 0x1CA1, 0x1CE1, 0x1D01, 0x1D41, /* 80 */
+- 0x1D61, 0x1DA1, 0x1DC1, 0x1E01,
+- 0x1E21, 0x1E61, 0x1E81, 0x1EA1,
+- 0x1EE1, 0x1F01, 0x1F21, 0x1F41,
+- 0x1F81, 0x1FA1, 0x1FC1, 0x1FE1, /* 96 */
+- 0x2001, 0x2041, 0x2061, 0x2081,
+- 0x20A1, 0x20C1, 0x20E1, 0x2101,
+- 0x2121, 0x2141, 0x2161, 0x2181,
+- 0x21A1, 0x21C1, 0x21E1, 0x2201, /* 112 */
+- 0x2221, 0x2241, 0x2261, 0x2281,
+- 0x22A1, 0x22C1, 0x22C1, 0x22E1,
+- 0x2301, 0x2321, 0x2341, 0x2361,
+- 0x2361, 0x2381, 0x23A1, 0x23C1, /* 128 */
+- 0x23E1, 0x23E1, 0x2401, 0x2421,
+- 0x2441, 0x2441, 0x2461, 0x2481,
+- 0x2481, 0x24A1, 0x24C1, 0x24C1,
+- 0x24E1, 0x2501, 0x2501, 0x2521, /* 144 */
+- 0x2541, 0x2541, 0x2561, 0x2561,
+- 0x2581, 0x25A1, 0x25A1, 0x25C1,
+- 0x25C1, 0x25E1, 0x2601, 0x2601,
+- 0x2621, 0x2621, 0x2641, 0x2641, /* 160 */
+- 0x2661, 0x2661, 0x2681, 0x2681,
+- 0x26A1, 0x26A1, 0x26C1, 0x26C1,
+- 0x26E1, 0x26E1, 0x2701, 0x2701,
+- 0x2721, 0x2721, 0x2740, 0x2740, /* 176 */
+- 0x2760, 0x2760, 0x2780, 0x2780,
+- 0x2780, 0x27A0, 0x27A0, 0x27C0,
+- 0x27C0, 0x27E0, 0x27E0, 0x27E0,
+- 0x2800, 0x2800, 0x2820, 0x2820, /* 192 */
+- 0x2820, 0x2840, 0x2840, 0x2840,
+- 0x2860, 0x2860, 0x2880, 0x2880,
+- 0x2880, 0x28A0, 0x28A0, 0x28A0,
+- 0x28C0, 0x28C0, 0x28C0, 0x28E0, /* 208 */
+- 0x28E0, 0x28E0, 0x2900, 0x2900,
+- 0x2900, 0x2920, 0x2920, 0x2920,
+- 0x2940, 0x2940, 0x2940, 0x2960,
+- 0x2960, 0x2960, 0x2960, 0x2980, /* 224 */
+- 0x2980, 0x2980, 0x29A0, 0x29A0,
+- 0x29A0, 0x29A0, 0x29C0, 0x29C0,
+- 0x29C0, 0x29E0, 0x29E0, 0x29E0,
+- 0x29E0, 0x2A00, 0x2A00, 0x2A00, /* 240 */
+- 0x2A00, 0x2A20, 0x2A20, 0x2A20,
+- 0x2A20, 0x2A40, 0x2A40, 0x2A40,
+- 0x2A40, 0x2A60, 0x2A60, 0x2A60,
+-};
+-
+-const u16 bcm43xx_ilt_finefreqg[BCM43xx_ILT_FINEFREQG_SIZE] = {
+- 0x0089, 0x02E9, 0x0409, 0x04E9, /* 0 */
+- 0x05A9, 0x0669, 0x0709, 0x0789,
+- 0x0829, 0x08A9, 0x0929, 0x0989,
+- 0x0A09, 0x0A69, 0x0AC9, 0x0B29,
+- 0x0BA9, 0x0BE9, 0x0C49, 0x0CA9, /* 16 */
+- 0x0D09, 0x0D69, 0x0DA9, 0x0E09,
+- 0x0E69, 0x0EA9, 0x0F09, 0x0F49,
+- 0x0FA9, 0x0FE9, 0x1029, 0x1089,
+- 0x10C9, 0x1109, 0x1169, 0x11A9, /* 32 */
+- 0x11E9, 0x1229, 0x1289, 0x12C9,
+- 0x1309, 0x1349, 0x1389, 0x13C9,
+- 0x1409, 0x1449, 0x14A9, 0x14E9,
+- 0x1529, 0x1569, 0x15A9, 0x15E9, /* 48 */
+- 0x1629, 0x1669, 0x16A9, 0x16E8,
+- 0x1728, 0x1768, 0x17A8, 0x17E8,
+- 0x1828, 0x1868, 0x18A8, 0x18E8,
+- 0x1928, 0x1968, 0x19A8, 0x19E8, /* 64 */
+- 0x1A28, 0x1A68, 0x1AA8, 0x1AE8,
+- 0x1B28, 0x1B68, 0x1BA8, 0x1BE8,
+- 0x1C28, 0x1C68, 0x1CA8, 0x1CE8,
+- 0x1D28, 0x1D68, 0x1DC8, 0x1E08, /* 80 */
+- 0x1E48, 0x1E88, 0x1EC8, 0x1F08,
+- 0x1F48, 0x1F88, 0x1FE8, 0x2028,
+- 0x2068, 0x20A8, 0x2108, 0x2148,
+- 0x2188, 0x21C8, 0x2228, 0x2268, /* 96 */
+- 0x22C8, 0x2308, 0x2348, 0x23A8,
+- 0x23E8, 0x2448, 0x24A8, 0x24E8,
+- 0x2548, 0x25A8, 0x2608, 0x2668,
+- 0x26C8, 0x2728, 0x2787, 0x27E7, /* 112 */
+- 0x2847, 0x28C7, 0x2947, 0x29A7,
+- 0x2A27, 0x2AC7, 0x2B47, 0x2BE7,
+- 0x2CA7, 0x2D67, 0x2E47, 0x2F67,
+- 0x3247, 0x3526, 0x3646, 0x3726, /* 128 */
+- 0x3806, 0x38A6, 0x3946, 0x39E6,
+- 0x3A66, 0x3AE6, 0x3B66, 0x3BC6,
+- 0x3C45, 0x3CA5, 0x3D05, 0x3D85,
+- 0x3DE5, 0x3E45, 0x3EA5, 0x3EE5, /* 144 */
+- 0x3F45, 0x3FA5, 0x4005, 0x4045,
+- 0x40A5, 0x40E5, 0x4145, 0x4185,
+- 0x41E5, 0x4225, 0x4265, 0x42C5,
+- 0x4305, 0x4345, 0x43A5, 0x43E5, /* 160 */
+- 0x4424, 0x4464, 0x44C4, 0x4504,
+- 0x4544, 0x4584, 0x45C4, 0x4604,
+- 0x4644, 0x46A4, 0x46E4, 0x4724,
+- 0x4764, 0x47A4, 0x47E4, 0x4824, /* 176 */
+- 0x4864, 0x48A4, 0x48E4, 0x4924,
+- 0x4964, 0x49A4, 0x49E4, 0x4A24,
+- 0x4A64, 0x4AA4, 0x4AE4, 0x4B23,
+- 0x4B63, 0x4BA3, 0x4BE3, 0x4C23, /* 192 */
+- 0x4C63, 0x4CA3, 0x4CE3, 0x4D23,
+- 0x4D63, 0x4DA3, 0x4DE3, 0x4E23,
+- 0x4E63, 0x4EA3, 0x4EE3, 0x4F23,
+- 0x4F63, 0x4FC3, 0x5003, 0x5043, /* 208 */
+- 0x5083, 0x50C3, 0x5103, 0x5143,
+- 0x5183, 0x51E2, 0x5222, 0x5262,
+- 0x52A2, 0x52E2, 0x5342, 0x5382,
+- 0x53C2, 0x5402, 0x5462, 0x54A2, /* 224 */
+- 0x5502, 0x5542, 0x55A2, 0x55E2,
+- 0x5642, 0x5682, 0x56E2, 0x5722,
+- 0x5782, 0x57E1, 0x5841, 0x58A1,
+- 0x5901, 0x5961, 0x59C1, 0x5A21, /* 240 */
+- 0x5AA1, 0x5B01, 0x5B81, 0x5BE1,
+- 0x5C61, 0x5D01, 0x5D80, 0x5E20,
+- 0x5EE0, 0x5FA0, 0x6080, 0x61C0,
+-};
+-
+-const u16 bcm43xx_ilt_noisea2[BCM43xx_ILT_NOISEA2_SIZE] = {
+- 0x0001, 0x0001, 0x0001, 0xFFFE,
+- 0xFFFE, 0x3FFF, 0x1000, 0x0393,
+-};
+-
+-const u16 bcm43xx_ilt_noisea3[BCM43xx_ILT_NOISEA3_SIZE] = {
+- 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36,
+- 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36,
+-};
+-
+-const u16 bcm43xx_ilt_noiseg1[BCM43xx_ILT_NOISEG1_SIZE] = {
+- 0x013C, 0x01F5, 0x031A, 0x0631,
+- 0x0001, 0x0001, 0x0001, 0x0001,
+-};
+-
+-const u16 bcm43xx_ilt_noiseg2[BCM43xx_ILT_NOISEG2_SIZE] = {
+- 0x5484, 0x3C40, 0x0000, 0x0000,
+- 0x0000, 0x0000, 0x0000, 0x0000,
+-};
+-
+-const u16 bcm43xx_ilt_noisescaleg1[BCM43xx_ILT_NOISESCALEG_SIZE] = {
+- 0x6C77, 0x5162, 0x3B40, 0x3335, /* 0 */
+- 0x2F2D, 0x2A2A, 0x2527, 0x1F21,
+- 0x1A1D, 0x1719, 0x1616, 0x1414,
+- 0x1414, 0x1400, 0x1414, 0x1614,
+- 0x1716, 0x1A19, 0x1F1D, 0x2521, /* 16 */
+- 0x2A27, 0x2F2A, 0x332D, 0x3B35,
+- 0x5140, 0x6C62, 0x0077,
+-};
+-
+-const u16 bcm43xx_ilt_noisescaleg2[BCM43xx_ILT_NOISESCALEG_SIZE] = {
+- 0xD8DD, 0xCBD4, 0xBCC0, 0XB6B7, /* 0 */
+- 0xB2B0, 0xADAD, 0xA7A9, 0x9FA1,
+- 0x969B, 0x9195, 0x8F8F, 0x8A8A,
+- 0x8A8A, 0x8A00, 0x8A8A, 0x8F8A,
+- 0x918F, 0x9695, 0x9F9B, 0xA7A1, /* 16 */
+- 0xADA9, 0xB2AD, 0xB6B0, 0xBCB7,
+- 0xCBC0, 0xD8D4, 0x00DD,
+-};
+-
+-const u16 bcm43xx_ilt_noisescaleg3[BCM43xx_ILT_NOISESCALEG_SIZE] = {
+- 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 0 */
+- 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
+- 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
+- 0xA4A4, 0xA400, 0xA4A4, 0xA4A4,
+- 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 16 */
+- 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
+- 0xA4A4, 0xA4A4, 0x00A4,
+-};
+-
+-const u16 bcm43xx_ilt_sigmasqr1[BCM43xx_ILT_SIGMASQR_SIZE] = {
+- 0x007A, 0x0075, 0x0071, 0x006C, /* 0 */
+- 0x0067, 0x0063, 0x005E, 0x0059,
+- 0x0054, 0x0050, 0x004B, 0x0046,
+- 0x0042, 0x003D, 0x003D, 0x003D,
+- 0x003D, 0x003D, 0x003D, 0x003D, /* 16 */
+- 0x003D, 0x003D, 0x003D, 0x003D,
+- 0x003D, 0x003D, 0x0000, 0x003D,
+- 0x003D, 0x003D, 0x003D, 0x003D,
+- 0x003D, 0x003D, 0x003D, 0x003D, /* 32 */
+- 0x003D, 0x003D, 0x003D, 0x003D,
+- 0x0042, 0x0046, 0x004B, 0x0050,
+- 0x0054, 0x0059, 0x005E, 0x0063,
+- 0x0067, 0x006C, 0x0071, 0x0075, /* 48 */
+- 0x007A,
+-};
+-
+-const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE] = {
+- 0x00DE, 0x00DC, 0x00DA, 0x00D8, /* 0 */
+- 0x00D6, 0x00D4, 0x00D2, 0x00CF,
+- 0x00CD, 0x00CA, 0x00C7, 0x00C4,
+- 0x00C1, 0x00BE, 0x00BE, 0x00BE,
+- 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 16 */
+- 0x00BE, 0x00BE, 0x00BE, 0x00BE,
+- 0x00BE, 0x00BE, 0x0000, 0x00BE,
+- 0x00BE, 0x00BE, 0x00BE, 0x00BE,
+- 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 32 */
+- 0x00BE, 0x00BE, 0x00BE, 0x00BE,
+- 0x00C1, 0x00C4, 0x00C7, 0x00CA,
+- 0x00CD, 0x00CF, 0x00D2, 0x00D4,
+- 0x00D6, 0x00D8, 0x00DA, 0x00DC, /* 48 */
+- 0x00DE,
+-};
+-
+-/**** Helper functions to access the device Internal Lookup Tables ****/
+-
+-void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val)
+-{
+- if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) {
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset);
+- mmiowb();
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val);
+- } else {
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset);
+- mmiowb();
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, val);
+- }
+-}
+-
+-void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val)
+-{
+- if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) {
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset);
+- mmiowb();
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA2, (val & 0xFFFF0000) >> 16);
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val & 0x0000FFFF);
+- } else {
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset);
+- mmiowb();
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA2, (val & 0xFFFF0000) >> 16);
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, val & 0x0000FFFF);
+- }
+-}
+-
+-u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset)
+-{
+- if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) {
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset);
+- return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_A_DATA1);
+- } else {
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset);
+- return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_G_DATA1);
+- }
+-}
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h
+deleted file mode 100644
+index d7eaf5f..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h
++++ /dev/null
+@@ -1,33 +0,0 @@
+-#ifndef BCM43xx_ILT_H_
+-#define BCM43xx_ILT_H_
+-
+-#define BCM43xx_ILT_ROTOR_SIZE 53
+-extern const u32 bcm43xx_ilt_rotor[BCM43xx_ILT_ROTOR_SIZE];
+-#define BCM43xx_ILT_RETARD_SIZE 53
+-extern const u32 bcm43xx_ilt_retard[BCM43xx_ILT_RETARD_SIZE];
+-#define BCM43xx_ILT_FINEFREQA_SIZE 256
+-extern const u16 bcm43xx_ilt_finefreqa[BCM43xx_ILT_FINEFREQA_SIZE];
+-#define BCM43xx_ILT_FINEFREQG_SIZE 256
+-extern const u16 bcm43xx_ilt_finefreqg[BCM43xx_ILT_FINEFREQG_SIZE];
+-#define BCM43xx_ILT_NOISEA2_SIZE 8
+-extern const u16 bcm43xx_ilt_noisea2[BCM43xx_ILT_NOISEA2_SIZE];
+-#define BCM43xx_ILT_NOISEA3_SIZE 8
+-extern const u16 bcm43xx_ilt_noisea3[BCM43xx_ILT_NOISEA3_SIZE];
+-#define BCM43xx_ILT_NOISEG1_SIZE 8
+-extern const u16 bcm43xx_ilt_noiseg1[BCM43xx_ILT_NOISEG1_SIZE];
+-#define BCM43xx_ILT_NOISEG2_SIZE 8
+-extern const u16 bcm43xx_ilt_noiseg2[BCM43xx_ILT_NOISEG2_SIZE];
+-#define BCM43xx_ILT_NOISESCALEG_SIZE 27
+-extern const u16 bcm43xx_ilt_noisescaleg1[BCM43xx_ILT_NOISESCALEG_SIZE];
+-extern const u16 bcm43xx_ilt_noisescaleg2[BCM43xx_ILT_NOISESCALEG_SIZE];
+-extern const u16 bcm43xx_ilt_noisescaleg3[BCM43xx_ILT_NOISESCALEG_SIZE];
+-#define BCM43xx_ILT_SIGMASQR_SIZE 53
+-extern const u16 bcm43xx_ilt_sigmasqr1[BCM43xx_ILT_SIGMASQR_SIZE];
+-extern const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE];
+-
+-
+-void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val);
+-void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val);
+-u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset);
+-
+-#endif /* BCM43xx_ILT_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
+deleted file mode 100644
+index cb51dc5..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
++++ /dev/null
+@@ -1,307 +0,0 @@
+-/*
+-
+- Broadcom BCM43xx wireless driver
+-
+- Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+- Stefano Brivio <st3 at riseup.net>
+- Michael Buesch <mbuesch at freenet.de>
+- Danny van Dyk <kugelfang at gentoo.org>
+- Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+- 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; see the file COPYING. If not, write to
+- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+- Boston, MA 02110-1301, USA.
+-
+-*/
+-
+-#include "bcm43xx_leds.h"
+-#include "bcm43xx_radio.h"
+-#include "bcm43xx.h"
+-
+-#include <linux/bitops.h>
+-
+-
+-static void bcm43xx_led_changestate(struct bcm43xx_led *led)
+-{
+- struct bcm43xx_private *bcm = led->bcm;
+- const int index = bcm43xx_led_index(led);
+- const u16 mask = (1 << index);
+- u16 ledctl;
+-
+- assert(index >= 0 && index < BCM43xx_NR_LEDS);
+- assert(led->blink_interval);
+- ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
+- ledctl = (ledctl & mask) ? (ledctl & ~mask) : (ledctl | mask);
+- bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
+-}
+-
+-static void bcm43xx_led_blink(unsigned long d)
+-{
+- struct bcm43xx_led *led = (struct bcm43xx_led *)d;
+- struct bcm43xx_private *bcm = led->bcm;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&bcm->leds_lock, flags);
+- if (led->blink_interval) {
+- bcm43xx_led_changestate(led);
+- mod_timer(&led->blink_timer, jiffies + led->blink_interval);
+- }
+- spin_unlock_irqrestore(&bcm->leds_lock, flags);
+-}
+-
+-static void bcm43xx_led_blink_start(struct bcm43xx_led *led,
+- unsigned long interval)
+-{
+- if (led->blink_interval)
+- return;
+- led->blink_interval = interval;
+- bcm43xx_led_changestate(led);
+- led->blink_timer.expires = jiffies + interval;
+- add_timer(&led->blink_timer);
+-}
+-
+-static void bcm43xx_led_blink_stop(struct bcm43xx_led *led, int sync)
+-{
+- struct bcm43xx_private *bcm = led->bcm;
+- const int index = bcm43xx_led_index(led);
+- u16 ledctl;
+-
+- if (!led->blink_interval)
+- return;
+- if (unlikely(sync))
+- del_timer_sync(&led->blink_timer);
+- else
+- del_timer(&led->blink_timer);
+- led->blink_interval = 0;
+-
+- /* Make sure the LED is turned off. */
+- assert(index >= 0 && index < BCM43xx_NR_LEDS);
+- ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
+- if (led->activelow)
+- ledctl |= (1 << index);
+- else
+- ledctl &= ~(1 << index);
+- bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
+-}
+-
+-static void bcm43xx_led_init_hardcoded(struct bcm43xx_private *bcm,
+- struct bcm43xx_led *led,
+- int led_index)
+-{
+- /* This function is called, if the behaviour (and activelow)
+- * information for a LED is missing in the SPROM.
+- * We hardcode the behaviour values for various devices here.
+- * Note that the BCM43xx_LED_TEST_XXX behaviour values can
+- * be used to figure out which led is mapped to which index.
+- */
+-
+- switch (led_index) {
+- case 0:
+- led->behaviour = BCM43xx_LED_ACTIVITY;
+- led->activelow = 1;
+- if (bcm->board_vendor == PCI_VENDOR_ID_COMPAQ)
+- led->behaviour = BCM43xx_LED_RADIO_ALL;
+- break;
+- case 1:
+- led->behaviour = BCM43xx_LED_RADIO_B;
+- if (bcm->board_vendor == PCI_VENDOR_ID_ASUSTEK)
+- led->behaviour = BCM43xx_LED_ASSOC;
+- break;
+- case 2:
+- led->behaviour = BCM43xx_LED_RADIO_A;
+- break;
+- case 3:
+- led->behaviour = BCM43xx_LED_OFF;
+- break;
+- default:
+- assert(0);
+- }
+-}
+-
+-int bcm43xx_leds_init(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_led *led;
+- u8 sprom[4];
+- int i;
+-
+- sprom[0] = bcm->sprom.wl0gpio0;
+- sprom[1] = bcm->sprom.wl0gpio1;
+- sprom[2] = bcm->sprom.wl0gpio2;
+- sprom[3] = bcm->sprom.wl0gpio3;
+-
+- for (i = 0; i < BCM43xx_NR_LEDS; i++) {
+- led = &(bcm->leds[i]);
+- led->bcm = bcm;
+- setup_timer(&led->blink_timer,
+- bcm43xx_led_blink,
+- (unsigned long)led);
+-
+- if (sprom[i] == 0xFF) {
+- bcm43xx_led_init_hardcoded(bcm, led, i);
+- } else {
+- led->behaviour = sprom[i] & BCM43xx_LED_BEHAVIOUR;
+- led->activelow = !!(sprom[i] & BCM43xx_LED_ACTIVELOW);
+- }
+- }
+-
+- return 0;
+-}
+-
+-void bcm43xx_leds_exit(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_led *led;
+- int i;
+-
+- for (i = 0; i < BCM43xx_NR_LEDS; i++) {
+- led = &(bcm->leds[i]);
+- bcm43xx_led_blink_stop(led, 1);
+- }
+- bcm43xx_leds_switch_all(bcm, 0);
+-}
+-
+-void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity)
+-{
+- struct bcm43xx_led *led;
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- const int transferring = (jiffies - bcm->stats.last_tx) < BCM43xx_LED_XFER_THRES;
+- int i, turn_on;
+- unsigned long interval = 0;
+- u16 ledctl;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&bcm->leds_lock, flags);
+- ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
+- for (i = 0; i < BCM43xx_NR_LEDS; i++) {
+- led = &(bcm->leds[i]);
+-
+- turn_on = 0;
+- switch (led->behaviour) {
+- case BCM43xx_LED_INACTIVE:
+- continue;
+- case BCM43xx_LED_OFF:
+- case BCM43xx_LED_BCM4303_3:
+- break;
+- case BCM43xx_LED_ON:
+- turn_on = 1;
+- break;
+- case BCM43xx_LED_ACTIVITY:
+- case BCM43xx_LED_BCM4303_0:
+- turn_on = activity;
+- break;
+- case BCM43xx_LED_RADIO_ALL:
+- turn_on = radio->enabled && bcm43xx_is_hw_radio_enabled(bcm);
+- break;
+- case BCM43xx_LED_RADIO_A:
+- case BCM43xx_LED_BCM4303_2:
+- turn_on = (radio->enabled && bcm43xx_is_hw_radio_enabled(bcm) &&
+- phy->type == BCM43xx_PHYTYPE_A);
+- break;
+- case BCM43xx_LED_RADIO_B:
+- case BCM43xx_LED_BCM4303_1:
+- turn_on = (radio->enabled && bcm43xx_is_hw_radio_enabled(bcm) &&
+- (phy->type == BCM43xx_PHYTYPE_B ||
+- phy->type == BCM43xx_PHYTYPE_G));
+- break;
+- case BCM43xx_LED_MODE_BG:
+- if (phy->type == BCM43xx_PHYTYPE_G && bcm43xx_is_hw_radio_enabled(bcm) &&
+- 1/*FIXME: using G rates.*/)
+- turn_on = 1;
+- break;
+- case BCM43xx_LED_TRANSFER:
+- if (transferring)
+- bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_MEDIUM);
+- else
+- bcm43xx_led_blink_stop(led, 0);
+- continue;
+- case BCM43xx_LED_APTRANSFER:
+- if (bcm->ieee->iw_mode == IW_MODE_MASTER) {
+- if (transferring) {
+- interval = BCM43xx_LEDBLINK_FAST;
+- turn_on = 1;
+- }
+- } else {
+- turn_on = 1;
+- if (0/*TODO: not assoc*/)
+- interval = BCM43xx_LEDBLINK_SLOW;
+- else if (transferring)
+- interval = BCM43xx_LEDBLINK_FAST;
+- else
+- turn_on = 0;
+- }
+- if (turn_on)
+- bcm43xx_led_blink_start(led, interval);
+- else
+- bcm43xx_led_blink_stop(led, 0);
+- continue;
+- case BCM43xx_LED_WEIRD:
+- //TODO
+- break;
+- case BCM43xx_LED_ASSOC:
+- if (bcm->softmac->associnfo.associated)
+- turn_on = 1;
+- break;
+-#ifdef CONFIG_BCM43XX_DEBUG
+- case BCM43xx_LED_TEST_BLINKSLOW:
+- bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_SLOW);
+- continue;
+- case BCM43xx_LED_TEST_BLINKMEDIUM:
+- bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_MEDIUM);
+- continue;
+- case BCM43xx_LED_TEST_BLINKFAST:
+- bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_FAST);
+- continue;
+-#endif /* CONFIG_BCM43XX_DEBUG */
+- default:
+- dprintkl(KERN_INFO PFX "Bad value in leds_update,"
+- " led->behaviour: 0x%x\n", led->behaviour);
+- };
+-
+- if (led->activelow)
+- turn_on = !turn_on;
+- if (turn_on)
+- ledctl |= (1 << i);
+- else
+- ledctl &= ~(1 << i);
+- }
+- bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
+- spin_unlock_irqrestore(&bcm->leds_lock, flags);
+-}
+-
+-void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on)
+-{
+- struct bcm43xx_led *led;
+- u16 ledctl;
+- int i;
+- int bit_on;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&bcm->leds_lock, flags);
+- ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
+- for (i = 0; i < BCM43xx_NR_LEDS; i++) {
+- led = &(bcm->leds[i]);
+- if (led->behaviour == BCM43xx_LED_INACTIVE)
+- continue;
+- if (on)
+- bit_on = led->activelow ? 0 : 1;
+- else
+- bit_on = led->activelow ? 1 : 0;
+- if (bit_on)
+- ledctl |= (1 << i);
+- else
+- ledctl &= ~(1 << i);
+- }
+- bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
+- spin_unlock_irqrestore(&bcm->leds_lock, flags);
+-}
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h
+deleted file mode 100644
+index 811e14a..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h
++++ /dev/null
+@@ -1,62 +0,0 @@
+-#ifndef BCM43xx_LEDS_H_
+-#define BCM43xx_LEDS_H_
+-
+-#include <linux/types.h>
+-#include <linux/timer.h>
+-
+-
+-struct bcm43xx_led {
+- u8 behaviour:7;
+- u8 activelow:1;
+-
+- struct bcm43xx_private *bcm;
+- struct timer_list blink_timer;
+- unsigned long blink_interval;
+-};
+-#define bcm43xx_led_index(led) ((int)((led) - (led)->bcm->leds))
+-
+-/* Delay between state changes when blinking in jiffies */
+-#define BCM43xx_LEDBLINK_SLOW (HZ / 1)
+-#define BCM43xx_LEDBLINK_MEDIUM (HZ / 4)
+-#define BCM43xx_LEDBLINK_FAST (HZ / 8)
+-
+-#define BCM43xx_LED_XFER_THRES (HZ / 100)
+-
+-#define BCM43xx_LED_BEHAVIOUR 0x7F
+-#define BCM43xx_LED_ACTIVELOW 0x80
+-enum { /* LED behaviour values */
+- BCM43xx_LED_OFF,
+- BCM43xx_LED_ON,
+- BCM43xx_LED_ACTIVITY,
+- BCM43xx_LED_RADIO_ALL,
+- BCM43xx_LED_RADIO_A,
+- BCM43xx_LED_RADIO_B,
+- BCM43xx_LED_MODE_BG,
+- BCM43xx_LED_TRANSFER,
+- BCM43xx_LED_APTRANSFER,
+- BCM43xx_LED_WEIRD,//FIXME
+- BCM43xx_LED_ASSOC,
+- BCM43xx_LED_INACTIVE,
+-
+- /* Behaviour values for testing.
+- * With these values it is easier to figure out
+- * the real behaviour of leds, in case the SPROM
+- * is missing information.
+- */
+- BCM43xx_LED_TEST_BLINKSLOW,
+- BCM43xx_LED_TEST_BLINKMEDIUM,
+- BCM43xx_LED_TEST_BLINKFAST,
+-
+- /* Misc values for BCM4303 */
+- BCM43xx_LED_BCM4303_0 = 0x2B,
+- BCM43xx_LED_BCM4303_1 = 0x78,
+- BCM43xx_LED_BCM4303_2 = 0x2E,
+- BCM43xx_LED_BCM4303_3 = 0x19,
+-};
+-
+-int bcm43xx_leds_init(struct bcm43xx_private *bcm);
+-void bcm43xx_leds_exit(struct bcm43xx_private *bcm);
+-void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity);
+-void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on);
+-
+-#endif /* BCM43xx_LEDS_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+deleted file mode 100644
+index b96a325..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
++++ /dev/null
+@@ -1,4281 +0,0 @@
+-/*
+-
+- Broadcom BCM43xx wireless driver
+-
+- Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+- Stefano Brivio <st3 at riseup.net>
+- Michael Buesch <mbuesch at freenet.de>
+- Danny van Dyk <kugelfang at gentoo.org>
+- Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+- Some parts of the code in this file are derived from the ipw2200
+- driver Copyright(c) 2003 - 2004 Intel Corporation.
+-
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; 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; see the file COPYING. If not, write to
+- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+- Boston, MA 02110-1301, USA.
+-
+-*/
+-
+-#include <linux/delay.h>
+-#include <linux/init.h>
+-#include <linux/moduleparam.h>
+-#include <linux/if_arp.h>
+-#include <linux/etherdevice.h>
+-#include <linux/version.h>
+-#include <linux/firmware.h>
+-#include <linux/wireless.h>
+-#include <linux/workqueue.h>
+-#include <linux/skbuff.h>
+-#include <linux/dma-mapping.h>
+-#include <net/iw_handler.h>
+-
+-#include "bcm43xx.h"
+-#include "bcm43xx_main.h"
+-#include "bcm43xx_debugfs.h"
+-#include "bcm43xx_radio.h"
+-#include "bcm43xx_phy.h"
+-#include "bcm43xx_dma.h"
+-#include "bcm43xx_pio.h"
+-#include "bcm43xx_power.h"
+-#include "bcm43xx_wx.h"
+-#include "bcm43xx_ethtool.h"
+-#include "bcm43xx_xmit.h"
+-#include "bcm43xx_sysfs.h"
+-
+-
+-MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver");
+-MODULE_AUTHOR("Martin Langer");
+-MODULE_AUTHOR("Stefano Brivio");
+-MODULE_AUTHOR("Michael Buesch");
+-MODULE_LICENSE("GPL");
+-
+-#if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO)
+-static int modparam_pio;
+-module_param_named(pio, modparam_pio, int, 0444);
+-MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode");
+-#elif defined(CONFIG_BCM43XX_DMA)
+-# define modparam_pio 0
+-#elif defined(CONFIG_BCM43XX_PIO)
+-# define modparam_pio 1
+-#endif
+-
+-static int modparam_bad_frames_preempt;
+-module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
+-MODULE_PARM_DESC(bad_frames_preempt, "enable(1) / disable(0) Bad Frames Preemption");
+-
+-static int modparam_short_retry = BCM43xx_DEFAULT_SHORT_RETRY_LIMIT;
+-module_param_named(short_retry, modparam_short_retry, int, 0444);
+-MODULE_PARM_DESC(short_retry, "Short-Retry-Limit (0 - 15)");
+-
+-static int modparam_long_retry = BCM43xx_DEFAULT_LONG_RETRY_LIMIT;
+-module_param_named(long_retry, modparam_long_retry, int, 0444);
+-MODULE_PARM_DESC(long_retry, "Long-Retry-Limit (0 - 15)");
+-
+-static int modparam_locale = -1;
+-module_param_named(locale, modparam_locale, int, 0444);
+-MODULE_PARM_DESC(country, "Select LocaleCode 0-11 (For travelers)");
+-
+-static int modparam_noleds;
+-module_param_named(noleds, modparam_noleds, int, 0444);
+-MODULE_PARM_DESC(noleds, "Turn off all LED activity");
+-
+-static char modparam_fwpostfix[64];
+-module_param_string(fwpostfix, modparam_fwpostfix, 64, 0444);
+-MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for using multiple firmware image versions.");
+-
+-
+-/* If you want to debug with just a single device, enable this,
+- * where the string is the pci device ID (as given by the kernel's
+- * pci_name function) of the device to be used.
+- */
+-//#define DEBUG_SINGLE_DEVICE_ONLY "0001:11:00.0"
+-
+-/* If you want to enable printing of each MMIO access, enable this. */
+-//#define DEBUG_ENABLE_MMIO_PRINT
+-
+-/* If you want to enable printing of MMIO access within
+- * ucode/pcm upload, initvals write, enable this.
+- */
+-//#define DEBUG_ENABLE_UCODE_MMIO_PRINT
+-
+-/* If you want to enable printing of PCI Config Space access, enable this */
+-//#define DEBUG_ENABLE_PCILOG
+-
+-
+-/* Detailed list maintained at:
+- * http://openfacts.berlios.de/index-en.phtml?title=Bcm43xxDevices
+- */
+- static struct pci_device_id bcm43xx_pci_tbl[] = {
+- /* Broadcom 4303 802.11b */
+- { PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+- /* Broadcom 4307 802.11b */
+- { PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+- /* Broadcom 4311 802.11(a)/b/g */
+- { PCI_VENDOR_ID_BROADCOM, 0x4311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+- /* Broadcom 4312 802.11a/b/g */
+- { PCI_VENDOR_ID_BROADCOM, 0x4312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+- /* Broadcom 4318 802.11b/g */
+- { PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+- /* Broadcom 4319 802.11a/b/g */
+- { PCI_VENDOR_ID_BROADCOM, 0x4319, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+- /* Broadcom 4306 802.11b/g */
+- { PCI_VENDOR_ID_BROADCOM, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+- /* Broadcom 4306 802.11a */
+-// { PCI_VENDOR_ID_BROADCOM, 0x4321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+- /* Broadcom 4309 802.11a/b/g */
+- { PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+- /* Broadcom 43XG 802.11b/g */
+- { PCI_VENDOR_ID_BROADCOM, 0x4325, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+- { 0 },
+-};
+-MODULE_DEVICE_TABLE(pci, bcm43xx_pci_tbl);
+-
+-static void bcm43xx_ram_write(struct bcm43xx_private *bcm, u16 offset, u32 val)
+-{
+- u32 status;
+-
+- status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+- if (!(status & BCM43xx_SBF_XFER_REG_BYTESWAP))
+- val = swab32(val);
+-
+- bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_CONTROL, offset);
+- mmiowb();
+- bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_DATA, val);
+-}
+-
+-static inline
+-void bcm43xx_shm_control_word(struct bcm43xx_private *bcm,
+- u16 routing, u16 offset)
+-{
+- u32 control;
+-
+- /* "offset" is the WORD offset. */
+-
+- control = routing;
+- control <<= 16;
+- control |= offset;
+- bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_CONTROL, control);
+-}
+-
+-u32 bcm43xx_shm_read32(struct bcm43xx_private *bcm,
+- u16 routing, u16 offset)
+-{
+- u32 ret;
+-
+- if (routing == BCM43xx_SHM_SHARED) {
+- if (offset & 0x0003) {
+- /* Unaligned access */
+- bcm43xx_shm_control_word(bcm, routing, offset >> 2);
+- ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED);
+- ret <<= 16;
+- bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1);
+- ret |= bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA);
+-
+- return ret;
+- }
+- offset >>= 2;
+- }
+- bcm43xx_shm_control_word(bcm, routing, offset);
+- ret = bcm43xx_read32(bcm, BCM43xx_MMIO_SHM_DATA);
+-
+- return ret;
+-}
+-
+-u16 bcm43xx_shm_read16(struct bcm43xx_private *bcm,
+- u16 routing, u16 offset)
+-{
+- u16 ret;
+-
+- if (routing == BCM43xx_SHM_SHARED) {
+- if (offset & 0x0003) {
+- /* Unaligned access */
+- bcm43xx_shm_control_word(bcm, routing, offset >> 2);
+- ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED);
+-
+- return ret;
+- }
+- offset >>= 2;
+- }
+- bcm43xx_shm_control_word(bcm, routing, offset);
+- ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA);
+-
+- return ret;
+-}
+-
+-void bcm43xx_shm_write32(struct bcm43xx_private *bcm,
+- u16 routing, u16 offset,
+- u32 value)
+-{
+- if (routing == BCM43xx_SHM_SHARED) {
+- if (offset & 0x0003) {
+- /* Unaligned access */
+- bcm43xx_shm_control_word(bcm, routing, offset >> 2);
+- mmiowb();
+- bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED,
+- (value >> 16) & 0xffff);
+- mmiowb();
+- bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1);
+- mmiowb();
+- bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA,
+- value & 0xffff);
+- return;
+- }
+- offset >>= 2;
+- }
+- bcm43xx_shm_control_word(bcm, routing, offset);
+- mmiowb();
+- bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, value);
+-}
+-
+-void bcm43xx_shm_write16(struct bcm43xx_private *bcm,
+- u16 routing, u16 offset,
+- u16 value)
+-{
+- if (routing == BCM43xx_SHM_SHARED) {
+- if (offset & 0x0003) {
+- /* Unaligned access */
+- bcm43xx_shm_control_word(bcm, routing, offset >> 2);
+- mmiowb();
+- bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED,
+- value);
+- return;
+- }
+- offset >>= 2;
+- }
+- bcm43xx_shm_control_word(bcm, routing, offset);
+- mmiowb();
+- bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA, value);
+-}
+-
+-void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf)
+-{
+- /* We need to be careful. As we read the TSF from multiple
+- * registers, we should take care of register overflows.
+- * In theory, the whole tsf read process should be atomic.
+- * We try to be atomic here, by restaring the read process,
+- * if any of the high registers changed (overflew).
+- */
+- if (bcm->current_core->rev >= 3) {
+- u32 low, high, high2;
+-
+- do {
+- high = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH);
+- low = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW);
+- high2 = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH);
+- } while (unlikely(high != high2));
+-
+- *tsf = high;
+- *tsf <<= 32;
+- *tsf |= low;
+- } else {
+- u64 tmp;
+- u16 v0, v1, v2, v3;
+- u16 test1, test2, test3;
+-
+- do {
+- v3 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_3);
+- v2 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_2);
+- v1 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_1);
+- v0 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_0);
+-
+- test3 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_3);
+- test2 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_2);
+- test1 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_1);
+- } while (v3 != test3 || v2 != test2 || v1 != test1);
+-
+- *tsf = v3;
+- *tsf <<= 48;
+- tmp = v2;
+- tmp <<= 32;
+- *tsf |= tmp;
+- tmp = v1;
+- tmp <<= 16;
+- *tsf |= tmp;
+- *tsf |= v0;
+- }
+-}
+-
+-void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf)
+-{
+- u32 status;
+-
+- status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+- status |= BCM43xx_SBF_TIME_UPDATE;
+- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+- mmiowb();
+-
+- /* Be careful with the in-progress timer.
+- * First zero out the low register, so we have a full
+- * register-overflow duration to complete the operation.
+- */
+- if (bcm->current_core->rev >= 3) {
+- u32 lo = (tsf & 0x00000000FFFFFFFFULL);
+- u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32;
+-
+- bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, 0);
+- mmiowb();
+- bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH, hi);
+- mmiowb();
+- bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, lo);
+- } else {
+- u16 v0 = (tsf & 0x000000000000FFFFULL);
+- u16 v1 = (tsf & 0x00000000FFFF0000ULL) >> 16;
+- u16 v2 = (tsf & 0x0000FFFF00000000ULL) >> 32;
+- u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48;
+-
+- bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, 0);
+- mmiowb();
+- bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_3, v3);
+- mmiowb();
+- bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_2, v2);
+- mmiowb();
+- bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_1, v1);
+- mmiowb();
+- bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, v0);
+- }
+-
+- status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+- status &= ~BCM43xx_SBF_TIME_UPDATE;
+- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+-}
+-
+-static
+-void bcm43xx_macfilter_set(struct bcm43xx_private *bcm,
+- u16 offset,
+- const u8 *mac)
+-{
+- u16 data;
+-
+- offset |= 0x0020;
+- bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_CONTROL, offset);
+-
+- data = mac[0];
+- data |= mac[1] << 8;
+- bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data);
+- data = mac[2];
+- data |= mac[3] << 8;
+- bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data);
+- data = mac[4];
+- data |= mac[5] << 8;
+- bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data);
+-}
+-
+-static void bcm43xx_macfilter_clear(struct bcm43xx_private *bcm,
+- u16 offset)
+-{
+- const u8 zero_addr[ETH_ALEN] = { 0 };
+-
+- bcm43xx_macfilter_set(bcm, offset, zero_addr);
+-}
+-
+-static void bcm43xx_write_mac_bssid_templates(struct bcm43xx_private *bcm)
+-{
+- const u8 *mac = (const u8 *)(bcm->net_dev->dev_addr);
+- const u8 *bssid = (const u8 *)(bcm->ieee->bssid);
+- u8 mac_bssid[ETH_ALEN * 2];
+- int i;
+-
+- memcpy(mac_bssid, mac, ETH_ALEN);
+- memcpy(mac_bssid + ETH_ALEN, bssid, ETH_ALEN);
+-
+- /* Write our MAC address and BSSID to template ram */
+- for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
+- bcm43xx_ram_write(bcm, 0x20 + i, *((u32 *)(mac_bssid + i)));
+- for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
+- bcm43xx_ram_write(bcm, 0x78 + i, *((u32 *)(mac_bssid + i)));
+- for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
+- bcm43xx_ram_write(bcm, 0x478 + i, *((u32 *)(mac_bssid + i)));
+-}
+-
+-//FIXME: Well, we should probably call them from somewhere.
+-#if 0
+-static void bcm43xx_set_slot_time(struct bcm43xx_private *bcm, u16 slot_time)
+-{
+- /* slot_time is in usec. */
+- if (bcm43xx_current_phy(bcm)->type != BCM43xx_PHYTYPE_G)
+- return;
+- bcm43xx_write16(bcm, 0x684, 510 + slot_time);
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0010, slot_time);
+-}
+-
+-static void bcm43xx_short_slot_timing_enable(struct bcm43xx_private *bcm)
+-{
+- bcm43xx_set_slot_time(bcm, 9);
+-}
+-
+-static void bcm43xx_short_slot_timing_disable(struct bcm43xx_private *bcm)
+-{
+- bcm43xx_set_slot_time(bcm, 20);
+-}
+-#endif
+-
+-/* FIXME: To get the MAC-filter working, we need to implement the
+- * following functions (and rename them :)
+- */
+-#if 0
+-static void bcm43xx_disassociate(struct bcm43xx_private *bcm)
+-{
+- bcm43xx_mac_suspend(bcm);
+- bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
+-
+- bcm43xx_ram_write(bcm, 0x0026, 0x0000);
+- bcm43xx_ram_write(bcm, 0x0028, 0x0000);
+- bcm43xx_ram_write(bcm, 0x007E, 0x0000);
+- bcm43xx_ram_write(bcm, 0x0080, 0x0000);
+- bcm43xx_ram_write(bcm, 0x047E, 0x0000);
+- bcm43xx_ram_write(bcm, 0x0480, 0x0000);
+-
+- if (bcm->current_core->rev < 3) {
+- bcm43xx_write16(bcm, 0x0610, 0x8000);
+- bcm43xx_write16(bcm, 0x060E, 0x0000);
+- } else
+- bcm43xx_write32(bcm, 0x0188, 0x80000000);
+-
+- bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff);
+-
+- if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_G &&
+- ieee80211_is_ofdm_rate(bcm->softmac->txrates.default_rate))
+- bcm43xx_short_slot_timing_enable(bcm);
+-
+- bcm43xx_mac_enable(bcm);
+-}
+-
+-static void bcm43xx_associate(struct bcm43xx_private *bcm,
+- const u8 *mac)
+-{
+- memcpy(bcm->ieee->bssid, mac, ETH_ALEN);
+-
+- bcm43xx_mac_suspend(bcm);
+- bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_ASSOC, mac);
+- bcm43xx_write_mac_bssid_templates(bcm);
+- bcm43xx_mac_enable(bcm);
+-}
+-#endif
+-
+-/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable.
+- * Returns the _previously_ enabled IRQ mask.
+- */
+-static inline u32 bcm43xx_interrupt_enable(struct bcm43xx_private *bcm, u32 mask)
+-{
+- u32 old_mask;
+-
+- old_mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK);
+- bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK, old_mask | mask);
+-
+- return old_mask;
+-}
+-
+-/* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable.
+- * Returns the _previously_ enabled IRQ mask.
+- */
+-static inline u32 bcm43xx_interrupt_disable(struct bcm43xx_private *bcm, u32 mask)
+-{
+- u32 old_mask;
+-
+- old_mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK);
+- bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK, old_mask & ~mask);
+-
+- return old_mask;
+-}
+-
+-/* Synchronize IRQ top- and bottom-half.
+- * IRQs must be masked before calling this.
+- * This must not be called with the irq_lock held.
+- */
+-static void bcm43xx_synchronize_irq(struct bcm43xx_private *bcm)
+-{
+- synchronize_irq(bcm->irq);
+- tasklet_disable(&bcm->isr_tasklet);
+-}
+-
+-/* Make sure we don't receive more data from the device. */
+-static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) {
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- return -EBUSY;
+- }
+- bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+- bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); /* flush */
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- bcm43xx_synchronize_irq(bcm);
+-
+- return 0;
+-}
+-
+-static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- u32 radio_id;
+- u16 manufact;
+- u16 version;
+- u8 revision;
+-
+- if (bcm->chip_id == 0x4317) {
+- if (bcm->chip_rev == 0x00)
+- radio_id = 0x3205017F;
+- else if (bcm->chip_rev == 0x01)
+- radio_id = 0x4205017F;
+- else
+- radio_id = 0x5205017F;
+- } else {
+- bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, BCM43xx_RADIOCTL_ID);
+- radio_id = bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_HIGH);
+- radio_id <<= 16;
+- bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, BCM43xx_RADIOCTL_ID);
+- radio_id |= bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW);
+- }
+-
+- manufact = (radio_id & 0x00000FFF);
+- version = (radio_id & 0x0FFFF000) >> 12;
+- revision = (radio_id & 0xF0000000) >> 28;
+-
+- dprintk(KERN_INFO PFX "Detected Radio: ID: %x (Manuf: %x Ver: %x Rev: %x)\n",
+- radio_id, manufact, version, revision);
+-
+- switch (phy->type) {
+- case BCM43xx_PHYTYPE_A:
+- if ((version != 0x2060) || (revision != 1) || (manufact != 0x17f))
+- goto err_unsupported_radio;
+- break;
+- case BCM43xx_PHYTYPE_B:
+- if ((version & 0xFFF0) != 0x2050)
+- goto err_unsupported_radio;
+- break;
+- case BCM43xx_PHYTYPE_G:
+- if (version != 0x2050)
+- goto err_unsupported_radio;
+- break;
+- }
+-
+- radio->manufact = manufact;
+- radio->version = version;
+- radio->revision = revision;
+-
+- if (phy->type == BCM43xx_PHYTYPE_A)
+- radio->txpower_desired = bcm->sprom.maxpower_aphy;
+- else
+- radio->txpower_desired = bcm->sprom.maxpower_bgphy;
+-
+- return 0;
+-
+-err_unsupported_radio:
+- printk(KERN_ERR PFX "Unsupported Radio connected to the PHY!\n");
+- return -ENODEV;
+-}
+-
+-static const char * bcm43xx_locale_iso(u8 locale)
+-{
+- /* ISO 3166-1 country codes.
+- * Note that there aren't ISO 3166-1 codes for
+- * all or locales. (Not all locales are countries)
+- */
+- switch (locale) {
+- case BCM43xx_LOCALE_WORLD:
+- case BCM43xx_LOCALE_ALL:
+- return "XX";
+- case BCM43xx_LOCALE_THAILAND:
+- return "TH";
+- case BCM43xx_LOCALE_ISRAEL:
+- return "IL";
+- case BCM43xx_LOCALE_JORDAN:
+- return "JO";
+- case BCM43xx_LOCALE_CHINA:
+- return "CN";
+- case BCM43xx_LOCALE_JAPAN:
+- case BCM43xx_LOCALE_JAPAN_HIGH:
+- return "JP";
+- case BCM43xx_LOCALE_USA_CANADA_ANZ:
+- case BCM43xx_LOCALE_USA_LOW:
+- return "US";
+- case BCM43xx_LOCALE_EUROPE:
+- return "EU";
+- case BCM43xx_LOCALE_NONE:
+- return " ";
+- }
+- assert(0);
+- return " ";
+-}
+-
+-static const char * bcm43xx_locale_string(u8 locale)
+-{
+- switch (locale) {
+- case BCM43xx_LOCALE_WORLD:
+- return "World";
+- case BCM43xx_LOCALE_THAILAND:
+- return "Thailand";
+- case BCM43xx_LOCALE_ISRAEL:
+- return "Israel";
+- case BCM43xx_LOCALE_JORDAN:
+- return "Jordan";
+- case BCM43xx_LOCALE_CHINA:
+- return "China";
+- case BCM43xx_LOCALE_JAPAN:
+- return "Japan";
+- case BCM43xx_LOCALE_USA_CANADA_ANZ:
+- return "USA/Canada/ANZ";
+- case BCM43xx_LOCALE_EUROPE:
+- return "Europe";
+- case BCM43xx_LOCALE_USA_LOW:
+- return "USAlow";
+- case BCM43xx_LOCALE_JAPAN_HIGH:
+- return "JapanHigh";
+- case BCM43xx_LOCALE_ALL:
+- return "All";
+- case BCM43xx_LOCALE_NONE:
+- return "None";
+- }
+- assert(0);
+- return "";
+-}
+-
+-static inline u8 bcm43xx_crc8(u8 crc, u8 data)
+-{
+- static const u8 t[] = {
+- 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
+- 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
+- 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
+- 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
+- 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
+- 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
+- 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
+- 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
+- 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
+- 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
+- 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
+- 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
+- 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
+- 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
+- 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
+- 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
+- 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
+- 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
+- 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
+- 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
+- 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
+- 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
+- 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
+- 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
+- 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
+- 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
+- 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
+- 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
+- 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
+- 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
+- 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
+- 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
+- };
+- return t[crc ^ data];
+-}
+-
+-static u8 bcm43xx_sprom_crc(const u16 *sprom)
+-{
+- int word;
+- u8 crc = 0xFF;
+-
+- for (word = 0; word < BCM43xx_SPROM_SIZE - 1; word++) {
+- crc = bcm43xx_crc8(crc, sprom[word] & 0x00FF);
+- crc = bcm43xx_crc8(crc, (sprom[word] & 0xFF00) >> 8);
+- }
+- crc = bcm43xx_crc8(crc, sprom[BCM43xx_SPROM_VERSION] & 0x00FF);
+- crc ^= 0xFF;
+-
+- return crc;
+-}
+-
+-int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom)
+-{
+- int i;
+- u8 crc, expected_crc;
+-
+- for (i = 0; i < BCM43xx_SPROM_SIZE; i++)
+- sprom[i] = bcm43xx_read16(bcm, BCM43xx_SPROM_BASE + (i * 2));
+- /* CRC-8 check. */
+- crc = bcm43xx_sprom_crc(sprom);
+- expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8;
+- if (crc != expected_crc) {
+- printk(KERN_WARNING PFX "WARNING: Invalid SPROM checksum "
+- "(0x%02X, expected: 0x%02X)\n",
+- crc, expected_crc);
+- return -EINVAL;
+- }
+-
+- return 0;
+-}
+-
+-int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom)
+-{
+- int i, err;
+- u8 crc, expected_crc;
+- u32 spromctl;
+-
+- /* CRC-8 validation of the input data. */
+- crc = bcm43xx_sprom_crc(sprom);
+- expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8;
+- if (crc != expected_crc) {
+- printk(KERN_ERR PFX "SPROM input data: Invalid CRC\n");
+- return -EINVAL;
+- }
+-
+- printk(KERN_INFO PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
+- err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_SPROMCTL, &spromctl);
+- if (err)
+- goto err_ctlreg;
+- spromctl |= 0x10; /* SPROM WRITE enable. */
+- err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl);
+- if (err)
+- goto err_ctlreg;
+- /* We must burn lots of CPU cycles here, but that does not
+- * really matter as one does not write the SPROM every other minute...
+- */
+- printk(KERN_INFO PFX "[ 0%%");
+- mdelay(500);
+- for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
+- if (i == 16)
+- printk("25%%");
+- else if (i == 32)
+- printk("50%%");
+- else if (i == 48)
+- printk("75%%");
+- else if (i % 2)
+- printk(".");
+- bcm43xx_write16(bcm, BCM43xx_SPROM_BASE + (i * 2), sprom[i]);
+- mmiowb();
+- mdelay(20);
+- }
+- spromctl &= ~0x10; /* SPROM WRITE enable. */
+- err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl);
+- if (err)
+- goto err_ctlreg;
+- mdelay(500);
+- printk("100%% ]\n");
+- printk(KERN_INFO PFX "SPROM written.\n");
+- bcm43xx_controller_restart(bcm, "SPROM update");
+-
+- return 0;
+-err_ctlreg:
+- printk(KERN_ERR PFX "Could not access SPROM control register.\n");
+- return -ENODEV;
+-}
+-
+-static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm)
+-{
+- u16 value;
+- u16 *sprom;
+-
+- sprom = kzalloc(BCM43xx_SPROM_SIZE * sizeof(u16),
+- GFP_KERNEL);
+- if (!sprom) {
+- printk(KERN_ERR PFX "sprom_extract OOM\n");
+- return -ENOMEM;
+- }
+- bcm43xx_sprom_read(bcm, sprom);
+-
+- /* boardflags2 */
+- value = sprom[BCM43xx_SPROM_BOARDFLAGS2];
+- bcm->sprom.boardflags2 = value;
+-
+- /* il0macaddr */
+- value = sprom[BCM43xx_SPROM_IL0MACADDR + 0];
+- *(((__be16 *)bcm->sprom.il0macaddr) + 0) = cpu_to_be16(value);
+- value = sprom[BCM43xx_SPROM_IL0MACADDR + 1];
+- *(((__be16 *)bcm->sprom.il0macaddr) + 1) = cpu_to_be16(value);
+- value = sprom[BCM43xx_SPROM_IL0MACADDR + 2];
+- *(((__be16 *)bcm->sprom.il0macaddr) + 2) = cpu_to_be16(value);
+-
+- /* et0macaddr */
+- value = sprom[BCM43xx_SPROM_ET0MACADDR + 0];
+- *(((__be16 *)bcm->sprom.et0macaddr) + 0) = cpu_to_be16(value);
+- value = sprom[BCM43xx_SPROM_ET0MACADDR + 1];
+- *(((__be16 *)bcm->sprom.et0macaddr) + 1) = cpu_to_be16(value);
+- value = sprom[BCM43xx_SPROM_ET0MACADDR + 2];
+- *(((__be16 *)bcm->sprom.et0macaddr) + 2) = cpu_to_be16(value);
+-
+- /* et1macaddr */
+- value = sprom[BCM43xx_SPROM_ET1MACADDR + 0];
+- *(((__be16 *)bcm->sprom.et1macaddr) + 0) = cpu_to_be16(value);
+- value = sprom[BCM43xx_SPROM_ET1MACADDR + 1];
+- *(((__be16 *)bcm->sprom.et1macaddr) + 1) = cpu_to_be16(value);
+- value = sprom[BCM43xx_SPROM_ET1MACADDR + 2];
+- *(((__be16 *)bcm->sprom.et1macaddr) + 2) = cpu_to_be16(value);
+-
+- /* ethernet phy settings */
+- value = sprom[BCM43xx_SPROM_ETHPHY];
+- bcm->sprom.et0phyaddr = (value & 0x001F);
+- bcm->sprom.et1phyaddr = (value & 0x03E0) >> 5;
+-
+- /* boardrev, antennas, locale */
+- value = sprom[BCM43xx_SPROM_BOARDREV];
+- bcm->sprom.boardrev = (value & 0x00FF);
+- bcm->sprom.locale = (value & 0x0F00) >> 8;
+- bcm->sprom.antennas_aphy = (value & 0x3000) >> 12;
+- bcm->sprom.antennas_bgphy = (value & 0xC000) >> 14;
+- if (modparam_locale != -1) {
+- if (modparam_locale >= 0 && modparam_locale <= 11) {
+- bcm->sprom.locale = modparam_locale;
+- printk(KERN_WARNING PFX "Operating with modified "
+- "LocaleCode %u (%s)\n",
+- bcm->sprom.locale,
+- bcm43xx_locale_string(bcm->sprom.locale));
+- } else {
+- printk(KERN_WARNING PFX "Module parameter \"locale\" "
+- "invalid value. (0 - 11)\n");
+- }
+- }
+-
+- /* pa0b* */
+- value = sprom[BCM43xx_SPROM_PA0B0];
+- bcm->sprom.pa0b0 = value;
+- value = sprom[BCM43xx_SPROM_PA0B1];
+- bcm->sprom.pa0b1 = value;
+- value = sprom[BCM43xx_SPROM_PA0B2];
+- bcm->sprom.pa0b2 = value;
+-
+- /* wl0gpio* */
+- value = sprom[BCM43xx_SPROM_WL0GPIO0];
+- if (value == 0x0000)
+- value = 0xFFFF;
+- bcm->sprom.wl0gpio0 = value & 0x00FF;
+- bcm->sprom.wl0gpio1 = (value & 0xFF00) >> 8;
+- value = sprom[BCM43xx_SPROM_WL0GPIO2];
+- if (value == 0x0000)
+- value = 0xFFFF;
+- bcm->sprom.wl0gpio2 = value & 0x00FF;
+- bcm->sprom.wl0gpio3 = (value & 0xFF00) >> 8;
+-
+- /* maxpower */
+- value = sprom[BCM43xx_SPROM_MAXPWR];
+- bcm->sprom.maxpower_aphy = (value & 0xFF00) >> 8;
+- bcm->sprom.maxpower_bgphy = value & 0x00FF;
+-
+- /* pa1b* */
+- value = sprom[BCM43xx_SPROM_PA1B0];
+- bcm->sprom.pa1b0 = value;
+- value = sprom[BCM43xx_SPROM_PA1B1];
+- bcm->sprom.pa1b1 = value;
+- value = sprom[BCM43xx_SPROM_PA1B2];
+- bcm->sprom.pa1b2 = value;
+-
+- /* idle tssi target */
+- value = sprom[BCM43xx_SPROM_IDL_TSSI_TGT];
+- bcm->sprom.idle_tssi_tgt_aphy = value & 0x00FF;
+- bcm->sprom.idle_tssi_tgt_bgphy = (value & 0xFF00) >> 8;
+-
+- /* boardflags */
+- value = sprom[BCM43xx_SPROM_BOARDFLAGS];
+- if (value == 0xFFFF)
+- value = 0x0000;
+- bcm->sprom.boardflags = value;
+- /* boardflags workarounds */
+- if (bcm->board_vendor == PCI_VENDOR_ID_DELL &&
+- bcm->chip_id == 0x4301 &&
+- bcm->board_revision == 0x74)
+- bcm->sprom.boardflags |= BCM43xx_BFL_BTCOEXIST;
+- if (bcm->board_vendor == PCI_VENDOR_ID_APPLE &&
+- bcm->board_type == 0x4E &&
+- bcm->board_revision > 0x40)
+- bcm->sprom.boardflags |= BCM43xx_BFL_PACTRL;
+-
+- /* antenna gain */
+- value = sprom[BCM43xx_SPROM_ANTENNA_GAIN];
+- if (value == 0x0000 || value == 0xFFFF)
+- value = 0x0202;
+- /* convert values to Q5.2 */
+- bcm->sprom.antennagain_aphy = ((value & 0xFF00) >> 8) * 4;
+- bcm->sprom.antennagain_bgphy = (value & 0x00FF) * 4;
+-
+- kfree(sprom);
+-
+- return 0;
+-}
+-
+-static int bcm43xx_geo_init(struct bcm43xx_private *bcm)
+-{
+- struct ieee80211_geo *geo;
+- struct ieee80211_channel *chan;
+- int have_a = 0, have_bg = 0;
+- int i;
+- u8 channel;
+- struct bcm43xx_phyinfo *phy;
+- const char *iso_country;
+- u8 max_bg_channel;
+-
+- geo = kzalloc(sizeof(*geo), GFP_KERNEL);
+- if (!geo)
+- return -ENOMEM;
+-
+- for (i = 0; i < bcm->nr_80211_available; i++) {
+- phy = &(bcm->core_80211_ext[i].phy);
+- switch (phy->type) {
+- case BCM43xx_PHYTYPE_B:
+- case BCM43xx_PHYTYPE_G:
+- have_bg = 1;
+- break;
+- case BCM43xx_PHYTYPE_A:
+- have_a = 1;
+- break;
+- default:
+- assert(0);
+- }
+- }
+- iso_country = bcm43xx_locale_iso(bcm->sprom.locale);
+-
+-/* set the maximum channel based on locale set in sprom or witle locale option */
+- switch (bcm->sprom.locale) {
+- case BCM43xx_LOCALE_THAILAND:
+- case BCM43xx_LOCALE_ISRAEL:
+- case BCM43xx_LOCALE_JORDAN:
+- case BCM43xx_LOCALE_USA_CANADA_ANZ:
+- case BCM43xx_LOCALE_USA_LOW:
+- max_bg_channel = 11;
+- break;
+- case BCM43xx_LOCALE_JAPAN:
+- case BCM43xx_LOCALE_JAPAN_HIGH:
+- max_bg_channel = 14;
+- break;
+- default:
+- max_bg_channel = 13;
+- }
+-
+- if (have_a) {
+- for (i = 0, channel = IEEE80211_52GHZ_MIN_CHANNEL;
+- channel <= IEEE80211_52GHZ_MAX_CHANNEL; channel++) {
+- chan = &geo->a[i++];
+- chan->freq = bcm43xx_channel_to_freq_a(channel);
+- chan->channel = channel;
+- }
+- geo->a_channels = i;
+- }
+- if (have_bg) {
+- for (i = 0, channel = IEEE80211_24GHZ_MIN_CHANNEL;
+- channel <= max_bg_channel; channel++) {
+- chan = &geo->bg[i++];
+- chan->freq = bcm43xx_channel_to_freq_bg(channel);
+- chan->channel = channel;
+- }
+- geo->bg_channels = i;
+- }
+- memcpy(geo->name, iso_country, 2);
+- if (0 /*TODO: Outdoor use only */)
+- geo->name[2] = 'O';
+- else if (0 /*TODO: Indoor use only */)
+- geo->name[2] = 'I';
+- else
+- geo->name[2] = ' ';
+- geo->name[3] = '\0';
+-
+- ieee80211_set_geo(bcm->ieee, geo);
+- kfree(geo);
+-
+- return 0;
+-}
+-
+-/* DummyTransmission function, as documented on
+- * http://bcm-specs.sipsolutions.net/DummyTransmission
+- */
+-void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- unsigned int i, max_loop;
+- u16 value = 0;
+- u32 buffer[5] = {
+- 0x00000000,
+- 0x0000D400,
+- 0x00000000,
+- 0x00000001,
+- 0x00000000,
+- };
+-
+- switch (phy->type) {
+- case BCM43xx_PHYTYPE_A:
+- max_loop = 0x1E;
+- buffer[0] = 0xCC010200;
+- break;
+- case BCM43xx_PHYTYPE_B:
+- case BCM43xx_PHYTYPE_G:
+- max_loop = 0xFA;
+- buffer[0] = 0x6E840B00;
+- break;
+- default:
+- assert(0);
+- return;
+- }
+-
+- for (i = 0; i < 5; i++)
+- bcm43xx_ram_write(bcm, i * 4, buffer[i]);
+-
+- bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
+-
+- bcm43xx_write16(bcm, 0x0568, 0x0000);
+- bcm43xx_write16(bcm, 0x07C0, 0x0000);
+- bcm43xx_write16(bcm, 0x050C, ((phy->type == BCM43xx_PHYTYPE_A) ? 1 : 0));
+- bcm43xx_write16(bcm, 0x0508, 0x0000);
+- bcm43xx_write16(bcm, 0x050A, 0x0000);
+- bcm43xx_write16(bcm, 0x054C, 0x0000);
+- bcm43xx_write16(bcm, 0x056A, 0x0014);
+- bcm43xx_write16(bcm, 0x0568, 0x0826);
+- bcm43xx_write16(bcm, 0x0500, 0x0000);
+- bcm43xx_write16(bcm, 0x0502, 0x0030);
+-
+- if (radio->version == 0x2050 && radio->revision <= 0x5)
+- bcm43xx_radio_write16(bcm, 0x0051, 0x0017);
+- for (i = 0x00; i < max_loop; i++) {
+- value = bcm43xx_read16(bcm, 0x050E);
+- if (value & 0x0080)
+- break;
+- udelay(10);
+- }
+- for (i = 0x00; i < 0x0A; i++) {
+- value = bcm43xx_read16(bcm, 0x050E);
+- if (value & 0x0400)
+- break;
+- udelay(10);
+- }
+- for (i = 0x00; i < 0x0A; i++) {
+- value = bcm43xx_read16(bcm, 0x0690);
+- if (!(value & 0x0100))
+- break;
+- udelay(10);
+- }
+- if (radio->version == 0x2050 && radio->revision <= 0x5)
+- bcm43xx_radio_write16(bcm, 0x0051, 0x0037);
+-}
+-
+-static void key_write(struct bcm43xx_private *bcm,
+- u8 index, u8 algorithm, const __le16 *key)
+-{
+- unsigned int i, basic_wep = 0;
+- u32 offset;
+- u16 value;
+-
+- /* Write associated key information */
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x100 + (index * 2),
+- ((index << 4) | (algorithm & 0x0F)));
+-
+- /* The first 4 WEP keys need extra love */
+- if (((algorithm == BCM43xx_SEC_ALGO_WEP) ||
+- (algorithm == BCM43xx_SEC_ALGO_WEP104)) && (index < 4))
+- basic_wep = 1;
+-
+- /* Write key payload, 8 little endian words */
+- offset = bcm->security_offset + (index * BCM43xx_SEC_KEYSIZE);
+- for (i = 0; i < (BCM43xx_SEC_KEYSIZE / sizeof(u16)); i++) {
+- value = le16_to_cpu(key[i]);
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
+- offset + (i * 2), value);
+-
+- if (!basic_wep)
+- continue;
+-
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
+- offset + (i * 2) + 4 * BCM43xx_SEC_KEYSIZE,
+- value);
+- }
+-}
+-
+-static void keymac_write(struct bcm43xx_private *bcm,
+- u8 index, const __be32 *addr)
+-{
+- /* for keys 0-3 there is no associated mac address */
+- if (index < 4)
+- return;
+-
+- index -= 4;
+- if (bcm->current_core->rev >= 5) {
+- bcm43xx_shm_write32(bcm,
+- BCM43xx_SHM_HWMAC,
+- index * 2,
+- be32_to_cpu(*addr));
+- bcm43xx_shm_write16(bcm,
+- BCM43xx_SHM_HWMAC,
+- (index * 2) + 1,
+- be16_to_cpu(*((__be16 *)(addr + 1))));
+- } else {
+- if (index < 8) {
+- TODO(); /* Put them in the macaddress filter */
+- } else {
+- TODO();
+- /* Put them BCM43xx_SHM_SHARED, stating index 0x0120.
+- Keep in mind to update the count of keymacs in 0x003E as well! */
+- }
+- }
+-}
+-
+-static int bcm43xx_key_write(struct bcm43xx_private *bcm,
+- u8 index, u8 algorithm,
+- const u8 *_key, int key_len,
+- const u8 *mac_addr)
+-{
+- u8 key[BCM43xx_SEC_KEYSIZE] = { 0 };
+-
+- if (index >= ARRAY_SIZE(bcm->key))
+- return -EINVAL;
+- if (key_len > ARRAY_SIZE(key))
+- return -EINVAL;
+- if (algorithm < 1 || algorithm > 5)
+- return -EINVAL;
+-
+- memcpy(key, _key, key_len);
+- key_write(bcm, index, algorithm, (const __le16 *)key);
+- keymac_write(bcm, index, (const __be32 *)mac_addr);
+-
+- bcm->key[index].algorithm = algorithm;
+-
+- return 0;
+-}
+-
+-static void bcm43xx_clear_keys(struct bcm43xx_private *bcm)
+-{
+- static const __be32 zero_mac[2] = { 0 };
+- unsigned int i,j, nr_keys = 54;
+- u16 offset;
+-
+- if (bcm->current_core->rev < 5)
+- nr_keys = 16;
+- assert(nr_keys <= ARRAY_SIZE(bcm->key));
+-
+- for (i = 0; i < nr_keys; i++) {
+- bcm->key[i].enabled = 0;
+- /* returns for i < 4 immediately */
+- keymac_write(bcm, i, zero_mac);
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
+- 0x100 + (i * 2), 0x0000);
+- for (j = 0; j < 8; j++) {
+- offset = bcm->security_offset + (j * 4) + (i * BCM43xx_SEC_KEYSIZE);
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
+- offset, 0x0000);
+- }
+- }
+- dprintk(KERN_INFO PFX "Keys cleared\n");
+-}
+-
+-/* Lowlevel core-switch function. This is only to be used in
+- * bcm43xx_switch_core() and bcm43xx_probe_cores()
+- */
+-static int _switch_core(struct bcm43xx_private *bcm, int core)
+-{
+- int err;
+- int attempts = 0;
+- u32 current_core;
+-
+- assert(core >= 0);
+- while (1) {
+- err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ACTIVE_CORE,
+- (core * 0x1000) + 0x18000000);
+- if (unlikely(err))
+- goto error;
+- err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ACTIVE_CORE,
+- ¤t_core);
+- if (unlikely(err))
+- goto error;
+- current_core = (current_core - 0x18000000) / 0x1000;
+- if (current_core == core)
+- break;
+-
+- if (unlikely(attempts++ > BCM43xx_SWITCH_CORE_MAX_RETRIES))
+- goto error;
+- udelay(10);
+- }
+-
+- return 0;
+-error:
+- printk(KERN_ERR PFX "Failed to switch to core %d\n", core);
+- return -ENODEV;
+-}
+-
+-int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core)
+-{
+- int err;
+-
+- if (unlikely(!new_core))
+- return 0;
+- if (!new_core->available)
+- return -ENODEV;
+- if (bcm->current_core == new_core)
+- return 0;
+- err = _switch_core(bcm, new_core->index);
+- if (unlikely(err))
+- goto out;
+-
+- bcm->current_core = new_core;
+-out:
+- return err;
+-}
+-
+-static int bcm43xx_core_enabled(struct bcm43xx_private *bcm)
+-{
+- u32 value;
+-
+- value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+- value &= BCM43xx_SBTMSTATELOW_CLOCK | BCM43xx_SBTMSTATELOW_RESET
+- | BCM43xx_SBTMSTATELOW_REJECT;
+-
+- return (value == BCM43xx_SBTMSTATELOW_CLOCK);
+-}
+-
+-/* disable current core */
+-static int bcm43xx_core_disable(struct bcm43xx_private *bcm, u32 core_flags)
+-{
+- u32 sbtmstatelow;
+- u32 sbtmstatehigh;
+- int i;
+-
+- /* fetch sbtmstatelow from core information registers */
+- sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+-
+- /* core is already in reset */
+- if (sbtmstatelow & BCM43xx_SBTMSTATELOW_RESET)
+- goto out;
+-
+- if (sbtmstatelow & BCM43xx_SBTMSTATELOW_CLOCK) {
+- sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
+- BCM43xx_SBTMSTATELOW_REJECT;
+- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+-
+- for (i = 0; i < 1000; i++) {
+- sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+- if (sbtmstatelow & BCM43xx_SBTMSTATELOW_REJECT) {
+- i = -1;
+- break;
+- }
+- udelay(10);
+- }
+- if (i != -1) {
+- printk(KERN_ERR PFX "Error: core_disable() REJECT timeout!\n");
+- return -EBUSY;
+- }
+-
+- for (i = 0; i < 1000; i++) {
+- sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
+- if (!(sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_BUSY)) {
+- i = -1;
+- break;
+- }
+- udelay(10);
+- }
+- if (i != -1) {
+- printk(KERN_ERR PFX "Error: core_disable() BUSY timeout!\n");
+- return -EBUSY;
+- }
+-
+- sbtmstatelow = BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
+- BCM43xx_SBTMSTATELOW_REJECT |
+- BCM43xx_SBTMSTATELOW_RESET |
+- BCM43xx_SBTMSTATELOW_CLOCK |
+- core_flags;
+- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+- udelay(10);
+- }
+-
+- sbtmstatelow = BCM43xx_SBTMSTATELOW_RESET |
+- BCM43xx_SBTMSTATELOW_REJECT |
+- core_flags;
+- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+-
+-out:
+- bcm->current_core->enabled = 0;
+-
+- return 0;
+-}
+-
+-/* enable (reset) current core */
+-static int bcm43xx_core_enable(struct bcm43xx_private *bcm, u32 core_flags)
+-{
+- u32 sbtmstatelow;
+- u32 sbtmstatehigh;
+- u32 sbimstate;
+- int err;
+-
+- err = bcm43xx_core_disable(bcm, core_flags);
+- if (err)
+- goto out;
+-
+- sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
+- BCM43xx_SBTMSTATELOW_RESET |
+- BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
+- core_flags;
+- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+- udelay(1);
+-
+- sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
+- if (sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_SERROR) {
+- sbtmstatehigh = 0x00000000;
+- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATEHIGH, sbtmstatehigh);
+- }
+-
+- sbimstate = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMSTATE);
+- if (sbimstate & (BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT)) {
+- sbimstate &= ~(BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT);
+- bcm43xx_write32(bcm, BCM43xx_CIR_SBIMSTATE, sbimstate);
+- }
+-
+- sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
+- BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
+- core_flags;
+- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+- udelay(1);
+-
+- sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | core_flags;
+- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+- udelay(1);
+-
+- bcm->current_core->enabled = 1;
+- assert(err == 0);
+-out:
+- return err;
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/80211CoreReset */
+-void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy)
+-{
+- u32 flags = 0x00040000;
+-
+- if ((bcm43xx_core_enabled(bcm)) &&
+- !bcm43xx_using_pio(bcm)) {
+- }
+- if (bcm43xx_status(bcm) == BCM43xx_STAT_SHUTTINGDOWN) {
+- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+- bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+- & ~(BCM43xx_SBF_MAC_ENABLED | 0x00000002));
+- } else {
+- if (connect_phy)
+- flags |= BCM43xx_SBTMSTATELOW_G_MODE_ENABLE;
+- bcm43xx_phy_connect(bcm, connect_phy);
+- bcm43xx_core_enable(bcm, flags);
+- bcm43xx_write16(bcm, 0x03E6, 0x0000);
+- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+- bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+- | BCM43xx_SBF_400);
+- }
+-}
+-
+-static void bcm43xx_wireless_core_disable(struct bcm43xx_private *bcm)
+-{
+- bcm43xx_radio_turn_off(bcm);
+- bcm43xx_write16(bcm, 0x03E6, 0x00F4);
+- bcm43xx_core_disable(bcm, 0);
+-}
+-
+-/* Mark the current 80211 core inactive. */
+-static void bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm)
+-{
+- u32 sbtmstatelow;
+-
+- bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+- bcm43xx_radio_turn_off(bcm);
+- sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+- sbtmstatelow &= 0xDFF5FFFF;
+- sbtmstatelow |= 0x000A0000;
+- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+- udelay(1);
+- sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+- sbtmstatelow &= 0xFFF5FFFF;
+- sbtmstatelow |= 0x00080000;
+- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+- udelay(1);
+-}
+-
+-static void handle_irq_transmit_status(struct bcm43xx_private *bcm)
+-{
+- u32 v0, v1;
+- u16 tmp;
+- struct bcm43xx_xmitstatus stat;
+-
+- while (1) {
+- v0 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_0);
+- if (!v0)
+- break;
+- v1 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_1);
+-
+- stat.cookie = (v0 >> 16) & 0x0000FFFF;
+- tmp = (u16)((v0 & 0xFFF0) | ((v0 & 0xF) >> 1));
+- stat.flags = tmp & 0xFF;
+- stat.cnt1 = (tmp & 0x0F00) >> 8;
+- stat.cnt2 = (tmp & 0xF000) >> 12;
+- stat.seq = (u16)(v1 & 0xFFFF);
+- stat.unknown = (u16)((v1 >> 16) & 0xFF);
+-
+- bcm43xx_debugfs_log_txstat(bcm, &stat);
+-
+- if (stat.flags & BCM43xx_TXSTAT_FLAG_AMPDU)
+- continue;
+- if (stat.flags & BCM43xx_TXSTAT_FLAG_INTER)
+- continue;
+-
+- if (bcm43xx_using_pio(bcm))
+- bcm43xx_pio_handle_xmitstatus(bcm, &stat);
+- else
+- bcm43xx_dma_handle_xmitstatus(bcm, &stat);
+- }
+-}
+-
+-static void drain_txstatus_queue(struct bcm43xx_private *bcm)
+-{
+- u32 dummy;
+-
+- if (bcm->current_core->rev < 5)
+- return;
+- /* Read all entries from the microcode TXstatus FIFO
+- * and throw them away.
+- */
+- while (1) {
+- dummy = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_0);
+- if (!dummy)
+- break;
+- dummy = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_1);
+- }
+-}
+-
+-static void bcm43xx_generate_noise_sample(struct bcm43xx_private *bcm)
+-{
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x408, 0x7F7F);
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x40A, 0x7F7F);
+- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD,
+- bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD) | (1 << 4));
+- assert(bcm->noisecalc.core_at_start == bcm->current_core);
+- assert(bcm->noisecalc.channel_at_start == bcm43xx_current_radio(bcm)->channel);
+-}
+-
+-static void bcm43xx_calculate_link_quality(struct bcm43xx_private *bcm)
+-{
+- /* Top half of Link Quality calculation. */
+-
+- if (bcm->noisecalc.calculation_running)
+- return;
+- bcm->noisecalc.core_at_start = bcm->current_core;
+- bcm->noisecalc.channel_at_start = bcm43xx_current_radio(bcm)->channel;
+- bcm->noisecalc.calculation_running = 1;
+- bcm->noisecalc.nr_samples = 0;
+-
+- bcm43xx_generate_noise_sample(bcm);
+-}
+-
+-static void handle_irq_noise(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- u16 tmp;
+- u8 noise[4];
+- u8 i, j;
+- s32 average;
+-
+- /* Bottom half of Link Quality calculation. */
+-
+- assert(bcm->noisecalc.calculation_running);
+- if (bcm->noisecalc.core_at_start != bcm->current_core ||
+- bcm->noisecalc.channel_at_start != radio->channel)
+- goto drop_calculation;
+- tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x408);
+- noise[0] = (tmp & 0x00FF);
+- noise[1] = (tmp & 0xFF00) >> 8;
+- tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40A);
+- noise[2] = (tmp & 0x00FF);
+- noise[3] = (tmp & 0xFF00) >> 8;
+- if (noise[0] == 0x7F || noise[1] == 0x7F ||
+- noise[2] == 0x7F || noise[3] == 0x7F)
+- goto generate_new;
+-
+- /* Get the noise samples. */
+- assert(bcm->noisecalc.nr_samples < 8);
+- i = bcm->noisecalc.nr_samples;
+- noise[0] = limit_value(noise[0], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
+- noise[1] = limit_value(noise[1], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
+- noise[2] = limit_value(noise[2], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
+- noise[3] = limit_value(noise[3], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
+- bcm->noisecalc.samples[i][0] = radio->nrssi_lt[noise[0]];
+- bcm->noisecalc.samples[i][1] = radio->nrssi_lt[noise[1]];
+- bcm->noisecalc.samples[i][2] = radio->nrssi_lt[noise[2]];
+- bcm->noisecalc.samples[i][3] = radio->nrssi_lt[noise[3]];
+- bcm->noisecalc.nr_samples++;
+- if (bcm->noisecalc.nr_samples == 8) {
+- /* Calculate the Link Quality by the noise samples. */
+- average = 0;
+- for (i = 0; i < 8; i++) {
+- for (j = 0; j < 4; j++)
+- average += bcm->noisecalc.samples[i][j];
+- }
+- average /= (8 * 4);
+- average *= 125;
+- average += 64;
+- average /= 128;
+-
+- tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40C);
+- tmp = (tmp / 128) & 0x1F;
+- if (tmp >= 8)
+- average += 2;
+- else
+- average -= 25;
+- if (tmp == 8)
+- average -= 72;
+- else
+- average -= 48;
+-
+- bcm->stats.noise = average;
+-drop_calculation:
+- bcm->noisecalc.calculation_running = 0;
+- return;
+- }
+-generate_new:
+- bcm43xx_generate_noise_sample(bcm);
+-}
+-
+-static void handle_irq_ps(struct bcm43xx_private *bcm)
+-{
+- if (bcm->ieee->iw_mode == IW_MODE_MASTER) {
+- ///TODO: PS TBTT
+- } else {
+- if (1/*FIXME: the last PSpoll frame was sent successfully */)
+- bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
+- }
+- if (bcm->ieee->iw_mode == IW_MODE_ADHOC)
+- bcm->reg124_set_0x4 = 1;
+- //FIXME else set to false?
+-}
+-
+-static void handle_irq_reg124(struct bcm43xx_private *bcm)
+-{
+- if (!bcm->reg124_set_0x4)
+- return;
+- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD,
+- bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD)
+- | 0x4);
+- //FIXME: reset reg124_set_0x4 to false?
+-}
+-
+-static void handle_irq_pmq(struct bcm43xx_private *bcm)
+-{
+- u32 tmp;
+-
+- //TODO: AP mode.
+-
+- while (1) {
+- tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_PS_STATUS);
+- if (!(tmp & 0x00000008))
+- break;
+- }
+- /* 16bit write is odd, but correct. */
+- bcm43xx_write16(bcm, BCM43xx_MMIO_PS_STATUS, 0x0002);
+-}
+-
+-static void bcm43xx_generate_beacon_template(struct bcm43xx_private *bcm,
+- u16 ram_offset, u16 shm_size_offset)
+-{
+- u32 value;
+- u16 size = 0;
+-
+- /* Timestamp. */
+- //FIXME: assumption: The chip sets the timestamp
+- value = 0;
+- bcm43xx_ram_write(bcm, ram_offset++, value);
+- bcm43xx_ram_write(bcm, ram_offset++, value);
+- size += 8;
+-
+- /* Beacon Interval / Capability Information */
+- value = 0x0000;//FIXME: Which interval?
+- value |= (1 << 0) << 16; /* ESS */
+- value |= (1 << 2) << 16; /* CF Pollable */ //FIXME?
+- value |= (1 << 3) << 16; /* CF Poll Request */ //FIXME?
+- if (!bcm->ieee->open_wep)
+- value |= (1 << 4) << 16; /* Privacy */
+- bcm43xx_ram_write(bcm, ram_offset++, value);
+- size += 4;
+-
+- /* SSID */
+- //TODO
+-
+- /* FH Parameter Set */
+- //TODO
+-
+- /* DS Parameter Set */
+- //TODO
+-
+- /* CF Parameter Set */
+- //TODO
+-
+- /* TIM */
+- //TODO
+-
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, shm_size_offset, size);
+-}
+-
+-static void handle_irq_beacon(struct bcm43xx_private *bcm)
+-{
+- u32 status;
+-
+- bcm->irq_savedstate &= ~BCM43xx_IRQ_BEACON;
+- status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD);
+-
+- if ((status & 0x1) && (status & 0x2)) {
+- /* ACK beacon IRQ. */
+- bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON,
+- BCM43xx_IRQ_BEACON);
+- bcm->irq_savedstate |= BCM43xx_IRQ_BEACON;
+- return;
+- }
+- if (!(status & 0x1)) {
+- bcm43xx_generate_beacon_template(bcm, 0x68, 0x18);
+- status |= 0x1;
+- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status);
+- }
+- if (!(status & 0x2)) {
+- bcm43xx_generate_beacon_template(bcm, 0x468, 0x1A);
+- status |= 0x2;
+- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status);
+- }
+-}
+-
+-/* Interrupt handler bottom-half */
+-static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm)
+-{
+- u32 reason;
+- u32 dma_reason[6];
+- u32 merged_dma_reason = 0;
+- int i, activity = 0;
+- unsigned long flags;
+-
+-#ifdef CONFIG_BCM43XX_DEBUG
+- u32 _handled = 0x00000000;
+-# define bcmirq_handled(irq) do { _handled |= (irq); } while (0)
+-#else
+-# define bcmirq_handled(irq) do { /* nothing */ } while (0)
+-#endif /* CONFIG_BCM43XX_DEBUG*/
+-
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- reason = bcm->irq_reason;
+- for (i = 5; i >= 0; i--) {
+- dma_reason[i] = bcm->dma_reason[i];
+- merged_dma_reason |= dma_reason[i];
+- }
+-
+- if (unlikely(reason & BCM43xx_IRQ_XMIT_ERROR)) {
+- /* TX error. We get this when Template Ram is written in wrong endianess
+- * in dummy_tx(). We also get this if something is wrong with the TX header
+- * on DMA or PIO queues.
+- * Maybe we get this in other error conditions, too.
+- */
+- printkl(KERN_ERR PFX "FATAL ERROR: BCM43xx_IRQ_XMIT_ERROR\n");
+- bcmirq_handled(BCM43xx_IRQ_XMIT_ERROR);
+- }
+- if (unlikely(merged_dma_reason & BCM43xx_DMAIRQ_FATALMASK)) {
+- printkl(KERN_ERR PFX "FATAL ERROR: Fatal DMA error: "
+- "0x%08X, 0x%08X, 0x%08X, "
+- "0x%08X, 0x%08X, 0x%08X\n",
+- dma_reason[0], dma_reason[1],
+- dma_reason[2], dma_reason[3],
+- dma_reason[4], dma_reason[5]);
+- bcm43xx_controller_restart(bcm, "DMA error");
+- mmiowb();
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- return;
+- }
+- if (unlikely(merged_dma_reason & BCM43xx_DMAIRQ_NONFATALMASK)) {
+- printkl(KERN_ERR PFX "DMA error: "
+- "0x%08X, 0x%08X, 0x%08X, "
+- "0x%08X, 0x%08X, 0x%08X\n",
+- dma_reason[0], dma_reason[1],
+- dma_reason[2], dma_reason[3],
+- dma_reason[4], dma_reason[5]);
+- }
+-
+- if (reason & BCM43xx_IRQ_PS) {
+- handle_irq_ps(bcm);
+- bcmirq_handled(BCM43xx_IRQ_PS);
+- }
+-
+- if (reason & BCM43xx_IRQ_REG124) {
+- handle_irq_reg124(bcm);
+- bcmirq_handled(BCM43xx_IRQ_REG124);
+- }
+-
+- if (reason & BCM43xx_IRQ_BEACON) {
+- if (bcm->ieee->iw_mode == IW_MODE_MASTER)
+- handle_irq_beacon(bcm);
+- bcmirq_handled(BCM43xx_IRQ_BEACON);
+- }
+-
+- if (reason & BCM43xx_IRQ_PMQ) {
+- handle_irq_pmq(bcm);
+- bcmirq_handled(BCM43xx_IRQ_PMQ);
+- }
+-
+- if (reason & BCM43xx_IRQ_SCAN) {
+- /*TODO*/
+- //bcmirq_handled(BCM43xx_IRQ_SCAN);
+- }
+-
+- if (reason & BCM43xx_IRQ_NOISE) {
+- handle_irq_noise(bcm);
+- bcmirq_handled(BCM43xx_IRQ_NOISE);
+- }
+-
+- /* Check the DMA reason registers for received data. */
+- if (dma_reason[0] & BCM43xx_DMAIRQ_RX_DONE) {
+- if (bcm43xx_using_pio(bcm))
+- bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue0);
+- else
+- bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring0);
+- /* We intentionally don't set "activity" to 1, here. */
+- }
+- assert(!(dma_reason[1] & BCM43xx_DMAIRQ_RX_DONE));
+- assert(!(dma_reason[2] & BCM43xx_DMAIRQ_RX_DONE));
+- if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) {
+- if (bcm43xx_using_pio(bcm))
+- bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue3);
+- else
+- bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring3);
+- activity = 1;
+- }
+- assert(!(dma_reason[4] & BCM43xx_DMAIRQ_RX_DONE));
+- assert(!(dma_reason[5] & BCM43xx_DMAIRQ_RX_DONE));
+- bcmirq_handled(BCM43xx_IRQ_RX);
+-
+- if (reason & BCM43xx_IRQ_XMIT_STATUS) {
+- handle_irq_transmit_status(bcm);
+- activity = 1;
+- //TODO: In AP mode, this also causes sending of powersave responses.
+- bcmirq_handled(BCM43xx_IRQ_XMIT_STATUS);
+- }
+-
+- /* IRQ_PIO_WORKAROUND is handled in the top-half. */
+- bcmirq_handled(BCM43xx_IRQ_PIO_WORKAROUND);
+-#ifdef CONFIG_BCM43XX_DEBUG
+- if (unlikely(reason & ~_handled)) {
+- printkl(KERN_WARNING PFX
+- "Unhandled IRQ! Reason: 0x%08x, Unhandled: 0x%08x, "
+- "DMA: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
+- reason, (reason & ~_handled),
+- dma_reason[0], dma_reason[1],
+- dma_reason[2], dma_reason[3]);
+- }
+-#endif
+-#undef bcmirq_handled
+-
+- if (!modparam_noleds)
+- bcm43xx_leds_update(bcm, activity);
+- bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
+- mmiowb();
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-}
+-
+-static void pio_irq_workaround(struct bcm43xx_private *bcm,
+- u16 base, int queueidx)
+-{
+- u16 rxctl;
+-
+- rxctl = bcm43xx_read16(bcm, base + BCM43xx_PIO_RXCTL);
+- if (rxctl & BCM43xx_PIO_RXCTL_DATAAVAILABLE)
+- bcm->dma_reason[queueidx] |= BCM43xx_DMAIRQ_RX_DONE;
+- else
+- bcm->dma_reason[queueidx] &= ~BCM43xx_DMAIRQ_RX_DONE;
+-}
+-
+-static void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, u32 reason)
+-{
+- if (bcm43xx_using_pio(bcm) &&
+- (bcm->current_core->rev < 3) &&
+- (!(reason & BCM43xx_IRQ_PIO_WORKAROUND))) {
+- /* Apply a PIO specific workaround to the dma_reasons */
+- pio_irq_workaround(bcm, BCM43xx_MMIO_PIO1_BASE, 0);
+- pio_irq_workaround(bcm, BCM43xx_MMIO_PIO2_BASE, 1);
+- pio_irq_workaround(bcm, BCM43xx_MMIO_PIO3_BASE, 2);
+- pio_irq_workaround(bcm, BCM43xx_MMIO_PIO4_BASE, 3);
+- }
+-
+- bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, reason);
+-
+- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA0_REASON,
+- bcm->dma_reason[0]);
+- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_REASON,
+- bcm->dma_reason[1]);
+- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_REASON,
+- bcm->dma_reason[2]);
+- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_REASON,
+- bcm->dma_reason[3]);
+- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_REASON,
+- bcm->dma_reason[4]);
+- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA5_REASON,
+- bcm->dma_reason[5]);
+-}
+-
+-/* Interrupt handler top-half */
+-static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id)
+-{
+- irqreturn_t ret = IRQ_HANDLED;
+- struct bcm43xx_private *bcm = dev_id;
+- u32 reason;
+-
+- if (!bcm)
+- return IRQ_NONE;
+-
+- spin_lock(&bcm->irq_lock);
+-
+- reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
+- if (reason == 0xffffffff) {
+- /* irq not for us (shared irq) */
+- ret = IRQ_NONE;
+- goto out;
+- }
+- reason &= bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK);
+- if (!reason)
+- goto out;
+-
+- assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
+- assert(bcm->current_core->id == BCM43xx_COREID_80211);
+-
+- bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA0_REASON)
+- & 0x0001DC00;
+- bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON)
+- & 0x0000DC00;
+- bcm->dma_reason[2] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_REASON)
+- & 0x0000DC00;
+- bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_REASON)
+- & 0x0001DC00;
+- bcm->dma_reason[4] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON)
+- & 0x0000DC00;
+- bcm->dma_reason[5] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA5_REASON)
+- & 0x0000DC00;
+-
+- bcm43xx_interrupt_ack(bcm, reason);
+-
+- /* disable all IRQs. They are enabled again in the bottom half. */
+- bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+- /* save the reason code and call our bottom half. */
+- bcm->irq_reason = reason;
+- tasklet_schedule(&bcm->isr_tasklet);
+-
+-out:
+- mmiowb();
+- spin_unlock(&bcm->irq_lock);
+-
+- return ret;
+-}
+-
+-static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-
+- if (bcm->firmware_norelease && !force)
+- return; /* Suspending or controller reset. */
+- release_firmware(phy->ucode);
+- phy->ucode = NULL;
+- release_firmware(phy->pcm);
+- phy->pcm = NULL;
+- release_firmware(phy->initvals0);
+- phy->initvals0 = NULL;
+- release_firmware(phy->initvals1);
+- phy->initvals1 = NULL;
+-}
+-
+-static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- u8 rev = bcm->current_core->rev;
+- int err = 0;
+- int nr;
+- char buf[22 + sizeof(modparam_fwpostfix) - 1] = { 0 };
+-
+- if (!phy->ucode) {
+- snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_microcode%d%s.fw",
+- (rev >= 5 ? 5 : rev),
+- modparam_fwpostfix);
+- err = request_firmware(&phy->ucode, buf, &bcm->pci_dev->dev);
+- if (err) {
+- printk(KERN_ERR PFX
+- "Error: Microcode \"%s\" not available or load failed.\n",
+- buf);
+- goto error;
+- }
+- }
+-
+- if (!phy->pcm) {
+- snprintf(buf, ARRAY_SIZE(buf),
+- "bcm43xx_pcm%d%s.fw",
+- (rev < 5 ? 4 : 5),
+- modparam_fwpostfix);
+- err = request_firmware(&phy->pcm, buf, &bcm->pci_dev->dev);
+- if (err) {
+- printk(KERN_ERR PFX
+- "Error: PCM \"%s\" not available or load failed.\n",
+- buf);
+- goto error;
+- }
+- }
+-
+- if (!phy->initvals0) {
+- if (rev == 2 || rev == 4) {
+- switch (phy->type) {
+- case BCM43xx_PHYTYPE_A:
+- nr = 3;
+- break;
+- case BCM43xx_PHYTYPE_B:
+- case BCM43xx_PHYTYPE_G:
+- nr = 1;
+- break;
+- default:
+- goto err_noinitval;
+- }
+-
+- } else if (rev >= 5) {
+- switch (phy->type) {
+- case BCM43xx_PHYTYPE_A:
+- nr = 7;
+- break;
+- case BCM43xx_PHYTYPE_B:
+- case BCM43xx_PHYTYPE_G:
+- nr = 5;
+- break;
+- default:
+- goto err_noinitval;
+- }
+- } else
+- goto err_noinitval;
+- snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
+- nr, modparam_fwpostfix);
+-
+- err = request_firmware(&phy->initvals0, buf, &bcm->pci_dev->dev);
+- if (err) {
+- printk(KERN_ERR PFX
+- "Error: InitVals \"%s\" not available or load failed.\n",
+- buf);
+- goto error;
+- }
+- if (phy->initvals0->size % sizeof(struct bcm43xx_initval)) {
+- printk(KERN_ERR PFX "InitVals fileformat error.\n");
+- goto error;
+- }
+- }
+-
+- if (!phy->initvals1) {
+- if (rev >= 5) {
+- u32 sbtmstatehigh;
+-
+- switch (phy->type) {
+- case BCM43xx_PHYTYPE_A:
+- sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
+- if (sbtmstatehigh & 0x00010000)
+- nr = 9;
+- else
+- nr = 10;
+- break;
+- case BCM43xx_PHYTYPE_B:
+- case BCM43xx_PHYTYPE_G:
+- nr = 6;
+- break;
+- default:
+- goto err_noinitval;
+- }
+- snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
+- nr, modparam_fwpostfix);
+-
+- err = request_firmware(&phy->initvals1, buf, &bcm->pci_dev->dev);
+- if (err) {
+- printk(KERN_ERR PFX
+- "Error: InitVals \"%s\" not available or load failed.\n",
+- buf);
+- goto error;
+- }
+- if (phy->initvals1->size % sizeof(struct bcm43xx_initval)) {
+- printk(KERN_ERR PFX "InitVals fileformat error.\n");
+- goto error;
+- }
+- }
+- }
+-
+-out:
+- return err;
+-error:
+- bcm43xx_release_firmware(bcm, 1);
+- goto out;
+-err_noinitval:
+- printk(KERN_ERR PFX "Error: No InitVals available!\n");
+- err = -ENOENT;
+- goto error;
+-}
+-
+-static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- const __be32 *data;
+- unsigned int i, len;
+-
+- /* Upload Microcode. */
+- data = (__be32 *)(phy->ucode->data);
+- len = phy->ucode->size / sizeof(u32);
+- bcm43xx_shm_control_word(bcm, BCM43xx_SHM_UCODE, 0x0000);
+- for (i = 0; i < len; i++) {
+- bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA,
+- be32_to_cpu(data[i]));
+- udelay(10);
+- }
+-
+- /* Upload PCM data. */
+- data = (__be32 *)(phy->pcm->data);
+- len = phy->pcm->size / sizeof(u32);
+- bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01ea);
+- bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, 0x00004000);
+- bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01eb);
+- for (i = 0; i < len; i++) {
+- bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA,
+- be32_to_cpu(data[i]));
+- udelay(10);
+- }
+-}
+-
+-static int bcm43xx_write_initvals(struct bcm43xx_private *bcm,
+- const struct bcm43xx_initval *data,
+- const unsigned int len)
+-{
+- u16 offset, size;
+- u32 value;
+- unsigned int i;
+-
+- for (i = 0; i < len; i++) {
+- offset = be16_to_cpu(data[i].offset);
+- size = be16_to_cpu(data[i].size);
+- value = be32_to_cpu(data[i].value);
+-
+- if (unlikely(offset >= 0x1000))
+- goto err_format;
+- if (size == 2) {
+- if (unlikely(value & 0xFFFF0000))
+- goto err_format;
+- bcm43xx_write16(bcm, offset, (u16)value);
+- } else if (size == 4) {
+- bcm43xx_write32(bcm, offset, value);
+- } else
+- goto err_format;
+- }
+-
+- return 0;
+-
+-err_format:
+- printk(KERN_ERR PFX "InitVals (bcm43xx_initvalXX.fw) file-format error. "
+- "Please fix your bcm43xx firmware files.\n");
+- return -EPROTO;
+-}
+-
+-static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- int err;
+-
+- err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)phy->initvals0->data,
+- phy->initvals0->size / sizeof(struct bcm43xx_initval));
+- if (err)
+- goto out;
+- if (phy->initvals1) {
+- err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)phy->initvals1->data,
+- phy->initvals1->size / sizeof(struct bcm43xx_initval));
+- if (err)
+- goto out;
+- }
+-out:
+- return err;
+-}
+-
+-static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm)
+-{
+- int err;
+-
+- bcm->irq = bcm->pci_dev->irq;
+- err = request_irq(bcm->irq, bcm43xx_interrupt_handler,
+- IRQF_SHARED, KBUILD_MODNAME, bcm);
+- if (err)
+- printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq);
+-
+- return err;
+-}
+-
+-/* Switch to the core used to write the GPIO register.
+- * This is either the ChipCommon, or the PCI core.
+- */
+-static int switch_to_gpio_core(struct bcm43xx_private *bcm)
+-{
+- int err;
+-
+- /* Where to find the GPIO register depends on the chipset.
+- * If it has a ChipCommon, its register at offset 0x6c is the GPIO
+- * control register. Otherwise the register at offset 0x6c in the
+- * PCI core is the GPIO control register.
+- */
+- err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+- if (err == -ENODEV) {
+- err = bcm43xx_switch_core(bcm, &bcm->core_pci);
+- if (unlikely(err == -ENODEV)) {
+- printk(KERN_ERR PFX "gpio error: "
+- "Neither ChipCommon nor PCI core available!\n");
+- }
+- }
+-
+- return err;
+-}
+-
+-/* Initialize the GPIOs
+- * http://bcm-specs.sipsolutions.net/GPIO
+- */
+-static int bcm43xx_gpio_init(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_coreinfo *old_core;
+- int err;
+- u32 mask, set;
+-
+- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+- bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+- & 0xFFFF3FFF);
+-
+- bcm43xx_leds_switch_all(bcm, 0);
+- bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK,
+- bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK) | 0x000F);
+-
+- mask = 0x0000001F;
+- set = 0x0000000F;
+- if (bcm->chip_id == 0x4301) {
+- mask |= 0x0060;
+- set |= 0x0060;
+- }
+- if (0 /* FIXME: conditional unknown */) {
+- bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK,
+- bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK)
+- | 0x0100);
+- mask |= 0x0180;
+- set |= 0x0180;
+- }
+- if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) {
+- bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK,
+- bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK)
+- | 0x0200);
+- mask |= 0x0200;
+- set |= 0x0200;
+- }
+- if (bcm->current_core->rev >= 2)
+- mask |= 0x0010; /* FIXME: This is redundant. */
+-
+- old_core = bcm->current_core;
+- err = switch_to_gpio_core(bcm);
+- if (err)
+- goto out;
+- bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL,
+- (bcm43xx_read32(bcm, BCM43xx_GPIO_CONTROL) & mask) | set);
+- err = bcm43xx_switch_core(bcm, old_core);
+-out:
+- return err;
+-}
+-
+-/* Turn off all GPIO stuff. Call this on module unload, for example. */
+-static int bcm43xx_gpio_cleanup(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_coreinfo *old_core;
+- int err;
+-
+- old_core = bcm->current_core;
+- err = switch_to_gpio_core(bcm);
+- if (err)
+- return err;
+- bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL, 0x00000000);
+- err = bcm43xx_switch_core(bcm, old_core);
+- assert(err == 0);
+-
+- return 0;
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/EnableMac */
+-void bcm43xx_mac_enable(struct bcm43xx_private *bcm)
+-{
+- bcm->mac_suspended--;
+- assert(bcm->mac_suspended >= 0);
+- if (bcm->mac_suspended == 0) {
+- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+- bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+- | BCM43xx_SBF_MAC_ENABLED);
+- bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY);
+- bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
+- bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
+- bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
+- }
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/SuspendMAC */
+-void bcm43xx_mac_suspend(struct bcm43xx_private *bcm)
+-{
+- int i;
+- u32 tmp;
+-
+- assert(bcm->mac_suspended >= 0);
+- if (bcm->mac_suspended == 0) {
+- bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
+- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+- bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+- & ~BCM43xx_SBF_MAC_ENABLED);
+- bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
+- for (i = 10000; i; i--) {
+- tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
+- if (tmp & BCM43xx_IRQ_READY)
+- goto out;
+- udelay(1);
+- }
+- printkl(KERN_ERR PFX "MAC suspend failed\n");
+- }
+-out:
+- bcm->mac_suspended++;
+-}
+-
+-void bcm43xx_set_iwmode(struct bcm43xx_private *bcm,
+- int iw_mode)
+-{
+- unsigned long flags;
+- struct net_device *net_dev = bcm->net_dev;
+- u32 status;
+- u16 value;
+-
+- spin_lock_irqsave(&bcm->ieee->lock, flags);
+- bcm->ieee->iw_mode = iw_mode;
+- spin_unlock_irqrestore(&bcm->ieee->lock, flags);
+- if (iw_mode == IW_MODE_MONITOR)
+- net_dev->type = ARPHRD_IEEE80211;
+- else
+- net_dev->type = ARPHRD_ETHER;
+-
+- status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+- /* Reset status to infrastructured mode */
+- status &= ~(BCM43xx_SBF_MODE_AP | BCM43xx_SBF_MODE_MONITOR);
+- status &= ~BCM43xx_SBF_MODE_PROMISC;
+- status |= BCM43xx_SBF_MODE_NOTADHOC;
+-
+-/* FIXME: Always enable promisc mode, until we get the MAC filters working correctly. */
+-status |= BCM43xx_SBF_MODE_PROMISC;
+-
+- switch (iw_mode) {
+- case IW_MODE_MONITOR:
+- status |= BCM43xx_SBF_MODE_MONITOR;
+- status |= BCM43xx_SBF_MODE_PROMISC;
+- break;
+- case IW_MODE_ADHOC:
+- status &= ~BCM43xx_SBF_MODE_NOTADHOC;
+- break;
+- case IW_MODE_MASTER:
+- status |= BCM43xx_SBF_MODE_AP;
+- break;
+- case IW_MODE_SECOND:
+- case IW_MODE_REPEAT:
+- TODO(); /* TODO */
+- break;
+- case IW_MODE_INFRA:
+- /* nothing to be done here... */
+- break;
+- default:
+- dprintk(KERN_ERR PFX "Unknown mode in set_iwmode: %d\n", iw_mode);
+- }
+- if (net_dev->flags & IFF_PROMISC)
+- status |= BCM43xx_SBF_MODE_PROMISC;
+- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+-
+- value = 0x0002;
+- if (iw_mode != IW_MODE_ADHOC && iw_mode != IW_MODE_MASTER) {
+- if (bcm->chip_id == 0x4306 && bcm->chip_rev == 3)
+- value = 0x0064;
+- else
+- value = 0x0032;
+- }
+- bcm43xx_write16(bcm, 0x0612, value);
+-}
+-
+-/* This is the opposite of bcm43xx_chip_init() */
+-static void bcm43xx_chip_cleanup(struct bcm43xx_private *bcm)
+-{
+- bcm43xx_radio_turn_off(bcm);
+- if (!modparam_noleds)
+- bcm43xx_leds_exit(bcm);
+- bcm43xx_gpio_cleanup(bcm);
+- bcm43xx_release_firmware(bcm, 0);
+-}
+-
+-/* Initialize the chip
+- * http://bcm-specs.sipsolutions.net/ChipInit
+- */
+-static int bcm43xx_chip_init(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- int err;
+- int i, tmp;
+- u32 value32;
+- u16 value16;
+-
+- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+- BCM43xx_SBF_CORE_READY
+- | BCM43xx_SBF_400);
+-
+- err = bcm43xx_request_firmware(bcm);
+- if (err)
+- goto out;
+- bcm43xx_upload_microcode(bcm);
+-
+- bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xFFFFFFFF);
+- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402);
+- i = 0;
+- while (1) {
+- value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
+- if (value32 == BCM43xx_IRQ_READY)
+- break;
+- i++;
+- if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) {
+- printk(KERN_ERR PFX "IRQ_READY timeout\n");
+- err = -ENODEV;
+- goto err_release_fw;
+- }
+- udelay(10);
+- }
+- bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
+-
+- value16 = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODE_REVISION);
+-
+- dprintk(KERN_INFO PFX "Microcode rev 0x%x, pl 0x%x "
+- "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", value16,
+- bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODE_PATCHLEVEL),
+- (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODE_DATE) >> 12) & 0xf,
+- (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODE_DATE) >> 8) & 0xf,
+- bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODE_DATE) & 0xff,
+- (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODE_TIME) >> 11) & 0x1f,
+- (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODE_TIME) >> 5) & 0x3f,
+- bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODE_TIME) & 0x1f);
+-
+- if ( value16 > 0x128 ) {
+- printk(KERN_ERR PFX
+- "Firmware: no support for microcode extracted "
+- "from version 4.x binary drivers.\n");
+- err = -EOPNOTSUPP;
+- goto err_release_fw;
+- }
+-
+- err = bcm43xx_gpio_init(bcm);
+- if (err)
+- goto err_release_fw;
+-
+- err = bcm43xx_upload_initvals(bcm);
+- if (err)
+- goto err_gpio_cleanup;
+- bcm43xx_radio_turn_on(bcm);
+- bcm->radio_hw_enable = bcm43xx_is_hw_radio_enabled(bcm);
+- printk(KERN_INFO PFX "Radio %s by hardware\n",
+- (bcm->radio_hw_enable == 0) ? "disabled" : "enabled");
+-
+- bcm43xx_write16(bcm, 0x03E6, 0x0000);
+- err = bcm43xx_phy_init(bcm);
+- if (err)
+- goto err_radio_off;
+-
+- /* Select initial Interference Mitigation. */
+- tmp = radio->interfmode;
+- radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE;
+- bcm43xx_radio_set_interference_mitigation(bcm, tmp);
+-
+- bcm43xx_phy_set_antenna_diversity(bcm);
+- bcm43xx_radio_set_txantenna(bcm, BCM43xx_RADIO_TXANTENNA_DEFAULT);
+- if (phy->type == BCM43xx_PHYTYPE_B) {
+- value16 = bcm43xx_read16(bcm, 0x005E);
+- value16 |= 0x0004;
+- bcm43xx_write16(bcm, 0x005E, value16);
+- }
+- bcm43xx_write32(bcm, 0x0100, 0x01000000);
+- if (bcm->current_core->rev < 5)
+- bcm43xx_write32(bcm, 0x010C, 0x01000000);
+-
+- value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+- value32 &= ~ BCM43xx_SBF_MODE_NOTADHOC;
+- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
+- value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+- value32 |= BCM43xx_SBF_MODE_NOTADHOC;
+- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
+-
+- value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+- value32 |= 0x100000;
+- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
+-
+- if (bcm43xx_using_pio(bcm)) {
+- bcm43xx_write32(bcm, 0x0210, 0x00000100);
+- bcm43xx_write32(bcm, 0x0230, 0x00000100);
+- bcm43xx_write32(bcm, 0x0250, 0x00000100);
+- bcm43xx_write32(bcm, 0x0270, 0x00000100);
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0034, 0x0000);
+- }
+-
+- /* Probe Response Timeout value */
+- /* FIXME: Default to 0, has to be set by ioctl probably... :-/ */
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0074, 0x0000);
+-
+- /* Initially set the wireless operation mode. */
+- bcm43xx_set_iwmode(bcm, bcm->ieee->iw_mode);
+-
+- if (bcm->current_core->rev < 3) {
+- bcm43xx_write16(bcm, 0x060E, 0x0000);
+- bcm43xx_write16(bcm, 0x0610, 0x8000);
+- bcm43xx_write16(bcm, 0x0604, 0x0000);
+- bcm43xx_write16(bcm, 0x0606, 0x0200);
+- } else {
+- bcm43xx_write32(bcm, 0x0188, 0x80000000);
+- bcm43xx_write32(bcm, 0x018C, 0x02000000);
+- }
+- bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0x00004000);
+- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA0_IRQ_MASK, 0x0001DC00);
+- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_IRQ_MASK, 0x0000DC00);
+- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_IRQ_MASK, 0x0000DC00);
+- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_IRQ_MASK, 0x0001DC00);
+- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_IRQ_MASK, 0x0000DC00);
+- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA5_IRQ_MASK, 0x0000DC00);
+-
+- value32 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+- value32 |= 0x00100000;
+- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, value32);
+-
+- bcm43xx_write16(bcm, BCM43xx_MMIO_POWERUP_DELAY, bcm43xx_pctl_powerup_delay(bcm));
+-
+- assert(err == 0);
+- dprintk(KERN_INFO PFX "Chip initialized\n");
+-out:
+- return err;
+-
+-err_radio_off:
+- bcm43xx_radio_turn_off(bcm);
+-err_gpio_cleanup:
+- bcm43xx_gpio_cleanup(bcm);
+-err_release_fw:
+- bcm43xx_release_firmware(bcm, 1);
+- goto out;
+-}
+-
+-/* Validate chip access
+- * http://bcm-specs.sipsolutions.net/ValidateChipAccess */
+-static int bcm43xx_validate_chip(struct bcm43xx_private *bcm)
+-{
+- u32 value;
+- u32 shm_backup;
+-
+- shm_backup = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000);
+- bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0xAA5555AA);
+- if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0xAA5555AA)
+- goto error;
+- bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0x55AAAA55);
+- if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0x55AAAA55)
+- goto error;
+- bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, shm_backup);
+-
+- value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+- if ((value | 0x80000000) != 0x80000400)
+- goto error;
+-
+- value = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
+- if (value != 0x00000000)
+- goto error;
+-
+- return 0;
+-error:
+- printk(KERN_ERR PFX "Failed to validate the chipaccess\n");
+- return -ENODEV;
+-}
+-
+-static void bcm43xx_init_struct_phyinfo(struct bcm43xx_phyinfo *phy)
+-{
+- /* Initialize a "phyinfo" structure. The structure is already
+- * zeroed out.
+- * This is called on insmod time to initialize members.
+- */
+- phy->savedpctlreg = 0xFFFF;
+- spin_lock_init(&phy->lock);
+-}
+-
+-static void bcm43xx_init_struct_radioinfo(struct bcm43xx_radioinfo *radio)
+-{
+- /* Initialize a "radioinfo" structure. The structure is already
+- * zeroed out.
+- * This is called on insmod time to initialize members.
+- */
+- radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE;
+- radio->channel = 0xFF;
+- radio->initial_channel = 0xFF;
+-}
+-
+-static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
+-{
+- int err, i;
+- int current_core;
+- u32 core_vendor, core_id, core_rev;
+- u32 sb_id_hi, chip_id_32 = 0;
+- u16 pci_device, chip_id_16;
+- u8 core_count;
+-
+- memset(&bcm->core_chipcommon, 0, sizeof(struct bcm43xx_coreinfo));
+- memset(&bcm->core_pci, 0, sizeof(struct bcm43xx_coreinfo));
+- memset(&bcm->core_80211, 0, sizeof(struct bcm43xx_coreinfo)
+- * BCM43xx_MAX_80211_CORES);
+- memset(&bcm->core_80211_ext, 0, sizeof(struct bcm43xx_coreinfo_80211)
+- * BCM43xx_MAX_80211_CORES);
+- bcm->nr_80211_available = 0;
+- bcm->current_core = NULL;
+- bcm->active_80211_core = NULL;
+-
+- /* map core 0 */
+- err = _switch_core(bcm, 0);
+- if (err)
+- goto out;
+-
+- /* fetch sb_id_hi from core information registers */
+- sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
+-
+- core_id = (sb_id_hi & 0x8FF0) >> 4;
+- core_rev = (sb_id_hi & 0x7000) >> 8;
+- core_rev |= (sb_id_hi & 0xF);
+- core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
+-
+- /* if present, chipcommon is always core 0; read the chipid from it */
+- if (core_id == BCM43xx_COREID_CHIPCOMMON) {
+- chip_id_32 = bcm43xx_read32(bcm, 0);
+- chip_id_16 = chip_id_32 & 0xFFFF;
+- bcm->core_chipcommon.available = 1;
+- bcm->core_chipcommon.id = core_id;
+- bcm->core_chipcommon.rev = core_rev;
+- bcm->core_chipcommon.index = 0;
+- /* While we are at it, also read the capabilities. */
+- bcm->chipcommon_capabilities = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_CAPABILITIES);
+- } else {
+- /* without a chipCommon, use a hard coded table. */
+- pci_device = bcm->pci_dev->device;
+- if (pci_device == 0x4301)
+- chip_id_16 = 0x4301;
+- else if ((pci_device >= 0x4305) && (pci_device <= 0x4307))
+- chip_id_16 = 0x4307;
+- else if ((pci_device >= 0x4402) && (pci_device <= 0x4403))
+- chip_id_16 = 0x4402;
+- else if ((pci_device >= 0x4610) && (pci_device <= 0x4615))
+- chip_id_16 = 0x4610;
+- else if ((pci_device >= 0x4710) && (pci_device <= 0x4715))
+- chip_id_16 = 0x4710;
+- else {
+- printk(KERN_ERR PFX "Could not determine Chip ID\n");
+- return -ENODEV;
+- }
+- }
+-
+- /* ChipCommon with Core Rev >=4 encodes number of cores,
+- * otherwise consult hardcoded table */
+- if ((core_id == BCM43xx_COREID_CHIPCOMMON) && (core_rev >= 4)) {
+- core_count = (chip_id_32 & 0x0F000000) >> 24;
+- } else {
+- switch (chip_id_16) {
+- case 0x4610:
+- case 0x4704:
+- case 0x4710:
+- core_count = 9;
+- break;
+- case 0x4310:
+- core_count = 8;
+- break;
+- case 0x5365:
+- core_count = 7;
+- break;
+- case 0x4306:
+- core_count = 6;
+- break;
+- case 0x4301:
+- case 0x4307:
+- core_count = 5;
+- break;
+- case 0x4402:
+- core_count = 3;
+- break;
+- default:
+- /* SOL if we get here */
+- assert(0);
+- core_count = 1;
+- }
+- }
+-
+- bcm->chip_id = chip_id_16;
+- bcm->chip_rev = (chip_id_32 & 0x000F0000) >> 16;
+- bcm->chip_package = (chip_id_32 & 0x00F00000) >> 20;
+-
+- dprintk(KERN_INFO PFX "Chip ID 0x%x, rev 0x%x\n",
+- bcm->chip_id, bcm->chip_rev);
+- dprintk(KERN_INFO PFX "Number of cores: %d\n", core_count);
+- if (bcm->core_chipcommon.available) {
+- dprintk(KERN_INFO PFX "Core 0: ID 0x%x, rev 0x%x, vendor 0x%x\n",
+- core_id, core_rev, core_vendor);
+- current_core = 1;
+- } else
+- current_core = 0;
+- for ( ; current_core < core_count; current_core++) {
+- struct bcm43xx_coreinfo *core;
+- struct bcm43xx_coreinfo_80211 *ext_80211;
+-
+- err = _switch_core(bcm, current_core);
+- if (err)
+- goto out;
+- /* Gather information */
+- /* fetch sb_id_hi from core information registers */
+- sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
+-
+- /* extract core_id, core_rev, core_vendor */
+- core_id = (sb_id_hi & 0x8FF0) >> 4;
+- core_rev = ((sb_id_hi & 0xF) | ((sb_id_hi & 0x7000) >> 8));
+- core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
+-
+- dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x\n",
+- current_core, core_id, core_rev, core_vendor);
+-
+- core = NULL;
+- switch (core_id) {
+- case BCM43xx_COREID_PCI:
+- case BCM43xx_COREID_PCIE:
+- core = &bcm->core_pci;
+- if (core->available) {
+- printk(KERN_WARNING PFX "Multiple PCI cores found.\n");
+- continue;
+- }
+- break;
+- case BCM43xx_COREID_80211:
+- for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
+- core = &(bcm->core_80211[i]);
+- ext_80211 = &(bcm->core_80211_ext[i]);
+- if (!core->available)
+- break;
+- core = NULL;
+- }
+- if (!core) {
+- printk(KERN_WARNING PFX "More than %d cores of type 802.11 found.\n",
+- BCM43xx_MAX_80211_CORES);
+- continue;
+- }
+- if (i != 0) {
+- /* More than one 80211 core is only supported
+- * by special chips.
+- * There are chips with two 80211 cores, but with
+- * dangling pins on the second core. Be careful
+- * and ignore these cores here.
+- */
+- if (1 /*bcm->pci_dev->device != 0x4324*/ ) {
+- /* TODO: A PHY */
+- dprintk(KERN_INFO PFX "Ignoring additional 802.11a core.\n");
+- continue;
+- }
+- }
+- switch (core_rev) {
+- case 2:
+- case 4:
+- case 5:
+- case 6:
+- case 7:
+- case 9:
+- case 10:
+- break;
+- default:
+- printk(KERN_WARNING PFX
+- "Unsupported 80211 core revision %u\n",
+- core_rev);
+- }
+- bcm->nr_80211_available++;
+- core->priv = ext_80211;
+- bcm43xx_init_struct_phyinfo(&ext_80211->phy);
+- bcm43xx_init_struct_radioinfo(&ext_80211->radio);
+- break;
+- case BCM43xx_COREID_CHIPCOMMON:
+- printk(KERN_WARNING PFX "Multiple CHIPCOMMON cores found.\n");
+- break;
+- }
+- if (core) {
+- core->available = 1;
+- core->id = core_id;
+- core->rev = core_rev;
+- core->index = current_core;
+- }
+- }
+-
+- if (!bcm->core_80211[0].available) {
+- printk(KERN_ERR PFX "Error: No 80211 core found!\n");
+- err = -ENODEV;
+- goto out;
+- }
+-
+- err = bcm43xx_switch_core(bcm, &bcm->core_80211[0]);
+-
+- assert(err == 0);
+-out:
+- return err;
+-}
+-
+-static void bcm43xx_gen_bssid(struct bcm43xx_private *bcm)
+-{
+- const u8 *mac = (const u8*)(bcm->net_dev->dev_addr);
+- u8 *bssid = bcm->ieee->bssid;
+-
+- switch (bcm->ieee->iw_mode) {
+- case IW_MODE_ADHOC:
+- random_ether_addr(bssid);
+- break;
+- case IW_MODE_MASTER:
+- case IW_MODE_INFRA:
+- case IW_MODE_REPEAT:
+- case IW_MODE_SECOND:
+- case IW_MODE_MONITOR:
+- memcpy(bssid, mac, ETH_ALEN);
+- break;
+- default:
+- assert(0);
+- }
+-}
+-
+-static void bcm43xx_rate_memory_write(struct bcm43xx_private *bcm,
+- u16 rate,
+- int is_ofdm)
+-{
+- u16 offset;
+-
+- if (is_ofdm) {
+- offset = 0x480;
+- offset += (bcm43xx_plcp_get_ratecode_ofdm(rate) & 0x000F) * 2;
+- }
+- else {
+- offset = 0x4C0;
+- offset += (bcm43xx_plcp_get_ratecode_cck(rate) & 0x000F) * 2;
+- }
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, offset + 0x20,
+- bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, offset));
+-}
+-
+-static void bcm43xx_rate_memory_init(struct bcm43xx_private *bcm)
+-{
+- switch (bcm43xx_current_phy(bcm)->type) {
+- case BCM43xx_PHYTYPE_A:
+- case BCM43xx_PHYTYPE_G:
+- bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_6MB, 1);
+- bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_12MB, 1);
+- bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_18MB, 1);
+- bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_24MB, 1);
+- bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_36MB, 1);
+- bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_48MB, 1);
+- bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_54MB, 1);
+- case BCM43xx_PHYTYPE_B:
+- bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_1MB, 0);
+- bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_2MB, 0);
+- bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_5MB, 0);
+- bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_11MB, 0);
+- break;
+- default:
+- assert(0);
+- }
+-}
+-
+-static void bcm43xx_wireless_core_cleanup(struct bcm43xx_private *bcm)
+-{
+- bcm43xx_chip_cleanup(bcm);
+- bcm43xx_pio_free(bcm);
+- bcm43xx_dma_free(bcm);
+-
+- bcm->current_core->initialized = 0;
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/80211Init */
+-static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm,
+- int active_wlcore)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- u32 ucodeflags;
+- int err;
+- u32 sbimconfiglow;
+- u8 limit;
+-
+- if (bcm->core_pci.rev <= 5 && bcm->core_pci.id != BCM43xx_COREID_PCIE) {
+- sbimconfiglow = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
+- sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
+- sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
+- if (bcm->bustype == BCM43xx_BUSTYPE_PCI)
+- sbimconfiglow |= 0x32;
+- else
+- sbimconfiglow |= 0x53;
+- bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, sbimconfiglow);
+- }
+-
+- bcm43xx_phy_calibrate(bcm);
+- err = bcm43xx_chip_init(bcm);
+- if (err)
+- goto out;
+-
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0016, bcm->current_core->rev);
+- ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, BCM43xx_UCODEFLAGS_OFFSET);
+-
+- if (0 /*FIXME: which condition has to be used here? */)
+- ucodeflags |= 0x00000010;
+-
+- /* HW decryption needs to be set now */
+- ucodeflags |= 0x40000000;
+-
+- if (phy->type == BCM43xx_PHYTYPE_G) {
+- ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY;
+- if (phy->rev == 1)
+- ucodeflags |= BCM43xx_UCODEFLAG_UNKGPHY;
+- if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
+- ucodeflags |= BCM43xx_UCODEFLAG_UNKPACTRL;
+- } else if (phy->type == BCM43xx_PHYTYPE_B) {
+- ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY;
+- if (phy->rev >= 2 && radio->version == 0x2050)
+- ucodeflags &= ~BCM43xx_UCODEFLAG_UNKGPHY;
+- }
+-
+- if (ucodeflags != bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODEFLAGS_OFFSET)) {
+- bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODEFLAGS_OFFSET, ucodeflags);
+- }
+-
+- /* Short/Long Retry Limit.
+- * The retry-limit is a 4-bit counter. Enforce this to avoid overflowing
+- * the chip-internal counter.
+- */
+- limit = limit_value(modparam_short_retry, 0, 0xF);
+- bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0006, limit);
+- limit = limit_value(modparam_long_retry, 0, 0xF);
+- bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0007, limit);
+-
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0044, 3);
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0046, 2);
+-
+- bcm43xx_rate_memory_init(bcm);
+-
+- /* Minimum Contention Window */
+- if (phy->type == BCM43xx_PHYTYPE_B)
+- bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000001f);
+- else
+- bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000000f);
+- /* Maximum Contention Window */
+- bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff);
+-
+- bcm43xx_gen_bssid(bcm);
+- bcm43xx_write_mac_bssid_templates(bcm);
+-
+- if (bcm->current_core->rev >= 5)
+- bcm43xx_write16(bcm, 0x043C, 0x000C);
+-
+- if (active_wlcore) {
+- if (bcm43xx_using_pio(bcm)) {
+- err = bcm43xx_pio_init(bcm);
+- } else {
+- err = bcm43xx_dma_init(bcm);
+- if (err == -ENOSYS)
+- err = bcm43xx_pio_init(bcm);
+- }
+- if (err)
+- goto err_chip_cleanup;
+- }
+- bcm43xx_write16(bcm, 0x0612, 0x0050);
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050);
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4);
+-
+- if (active_wlcore) {
+- if (radio->initial_channel != 0xFF)
+- bcm43xx_radio_selectchannel(bcm, radio->initial_channel, 0);
+- }
+-
+- /* Don't enable MAC/IRQ here, as it will race with the IRQ handler.
+- * We enable it later.
+- */
+- bcm->current_core->initialized = 1;
+-out:
+- return err;
+-
+-err_chip_cleanup:
+- bcm43xx_chip_cleanup(bcm);
+- goto out;
+-}
+-
+-static int bcm43xx_chipset_attach(struct bcm43xx_private *bcm)
+-{
+- int err;
+- u16 pci_status;
+-
+- err = bcm43xx_pctl_set_crystal(bcm, 1);
+- if (err)
+- goto out;
+- err = bcm43xx_pci_read_config16(bcm, PCI_STATUS, &pci_status);
+- if (err)
+- goto out;
+- err = bcm43xx_pci_write_config16(bcm, PCI_STATUS, pci_status & ~PCI_STATUS_SIG_TARGET_ABORT);
+-
+-out:
+- return err;
+-}
+-
+-static void bcm43xx_chipset_detach(struct bcm43xx_private *bcm)
+-{
+- bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW);
+- bcm43xx_pctl_set_crystal(bcm, 0);
+-}
+-
+-static void bcm43xx_pcicore_broadcast_value(struct bcm43xx_private *bcm,
+- u32 address,
+- u32 data)
+-{
+- bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_ADDR, address);
+- bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_DATA, data);
+-}
+-
+-static int bcm43xx_pcicore_commit_settings(struct bcm43xx_private *bcm)
+-{
+- int err = 0;
+-
+- bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+-
+- if (bcm->core_chipcommon.available) {
+- err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+- if (err)
+- goto out;
+-
+- bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
+-
+- /* this function is always called when a PCI core is mapped */
+- err = bcm43xx_switch_core(bcm, &bcm->core_pci);
+- if (err)
+- goto out;
+- } else
+- bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
+-
+- bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
+-
+-out:
+- return err;
+-}
+-
+-static u32 bcm43xx_pcie_reg_read(struct bcm43xx_private *bcm, u32 address)
+-{
+- bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address);
+- return bcm43xx_read32(bcm, BCM43xx_PCIECORE_REG_DATA);
+-}
+-
+-static void bcm43xx_pcie_reg_write(struct bcm43xx_private *bcm, u32 address,
+- u32 data)
+-{
+- bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address);
+- bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_DATA, data);
+-}
+-
+-static void bcm43xx_pcie_mdio_write(struct bcm43xx_private *bcm, u8 dev, u8 reg,
+- u16 data)
+-{
+- int i;
+-
+- bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0x0082);
+- bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_DATA, BCM43xx_PCIE_MDIO_ST |
+- BCM43xx_PCIE_MDIO_WT | (dev << BCM43xx_PCIE_MDIO_DEV) |
+- (reg << BCM43xx_PCIE_MDIO_REG) | BCM43xx_PCIE_MDIO_TA |
+- data);
+- udelay(10);
+-
+- for (i = 0; i < 10; i++) {
+- if (bcm43xx_read32(bcm, BCM43xx_PCIECORE_MDIO_CTL) &
+- BCM43xx_PCIE_MDIO_TC)
+- break;
+- msleep(1);
+- }
+- bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0);
+-}
+-
+-/* Make an I/O Core usable. "core_mask" is the bitmask of the cores to enable.
+- * To enable core 0, pass a core_mask of 1<<0
+- */
+-static int bcm43xx_setup_backplane_pci_connection(struct bcm43xx_private *bcm,
+- u32 core_mask)
+-{
+- u32 backplane_flag_nr;
+- u32 value;
+- struct bcm43xx_coreinfo *old_core;
+- int err = 0;
+-
+- value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTPSFLAG);
+- backplane_flag_nr = value & BCM43xx_BACKPLANE_FLAG_NR_MASK;
+-
+- old_core = bcm->current_core;
+- err = bcm43xx_switch_core(bcm, &bcm->core_pci);
+- if (err)
+- goto out;
+-
+- if (bcm->current_core->rev < 6 &&
+- bcm->current_core->id == BCM43xx_COREID_PCI) {
+- value = bcm43xx_read32(bcm, BCM43xx_CIR_SBINTVEC);
+- value |= (1 << backplane_flag_nr);
+- bcm43xx_write32(bcm, BCM43xx_CIR_SBINTVEC, value);
+- } else {
+- err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ICR, &value);
+- if (err) {
+- printk(KERN_ERR PFX "Error: ICR setup failure!\n");
+- goto out_switch_back;
+- }
+- value |= core_mask << 8;
+- err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ICR, value);
+- if (err) {
+- printk(KERN_ERR PFX "Error: ICR setup failure!\n");
+- goto out_switch_back;
+- }
+- }
+-
+- if (bcm->current_core->id == BCM43xx_COREID_PCI) {
+- value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
+- value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST;
+- bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
+-
+- if (bcm->current_core->rev < 5) {
+- value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
+- value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT)
+- & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
+- value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT)
+- & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
+- bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value);
+- err = bcm43xx_pcicore_commit_settings(bcm);
+- assert(err == 0);
+- } else if (bcm->current_core->rev >= 11) {
+- value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
+- value |= BCM43xx_SBTOPCI2_MEMREAD_MULTI;
+- bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
+- }
+- } else {
+- if (bcm->current_core->rev == 0 || bcm->current_core->rev == 1) {
+- value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_TLP_WORKAROUND);
+- value |= 0x8;
+- bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_TLP_WORKAROUND,
+- value);
+- }
+- if (bcm->current_core->rev == 0) {
+- bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX,
+- BCM43xx_SERDES_RXTIMER, 0x8128);
+- bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX,
+- BCM43xx_SERDES_CDR, 0x0100);
+- bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX,
+- BCM43xx_SERDES_CDR_BW, 0x1466);
+- } else if (bcm->current_core->rev == 1) {
+- value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_DLLP_LINKCTL);
+- value |= 0x40;
+- bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_DLLP_LINKCTL,
+- value);
+- }
+- }
+-out_switch_back:
+- err = bcm43xx_switch_core(bcm, old_core);
+-out:
+- return err;
+-}
+-
+-static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-
+- if (phy->type != BCM43xx_PHYTYPE_G || phy->rev < 2)
+- return;
+-
+- bcm43xx_mac_suspend(bcm);
+- bcm43xx_phy_lo_g_measure(bcm);
+- bcm43xx_mac_enable(bcm);
+-}
+-
+-static void bcm43xx_periodic_every60sec(struct bcm43xx_private *bcm)
+-{
+- bcm43xx_phy_lo_mark_all_unused(bcm);
+- if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
+- bcm43xx_mac_suspend(bcm);
+- bcm43xx_calc_nrssi_slope(bcm);
+- bcm43xx_mac_enable(bcm);
+- }
+-}
+-
+-static void bcm43xx_periodic_every30sec(struct bcm43xx_private *bcm)
+-{
+- /* Update device statistics. */
+- bcm43xx_calculate_link_quality(bcm);
+-}
+-
+-static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm)
+-{
+- bcm43xx_phy_xmitpower(bcm); //FIXME: unless scanning?
+- //TODO for APHY (temperature?)
+-}
+-
+-static void bcm43xx_periodic_every1sec(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- int radio_hw_enable;
+-
+- /* check if radio hardware enabled status changed */
+- radio_hw_enable = bcm43xx_is_hw_radio_enabled(bcm);
+- if (unlikely(bcm->radio_hw_enable != radio_hw_enable)) {
+- bcm->radio_hw_enable = radio_hw_enable;
+- printk(KERN_INFO PFX "Radio hardware status changed to %s\n",
+- (radio_hw_enable == 0) ? "disabled" : "enabled");
+- bcm43xx_leds_update(bcm, 0);
+- }
+- if (phy->type == BCM43xx_PHYTYPE_G) {
+- //TODO: update_aci_moving_average
+- if (radio->aci_enable && radio->aci_wlan_automatic) {
+- bcm43xx_mac_suspend(bcm);
+- if (!radio->aci_enable && 1 /*TODO: not scanning? */) {
+- if (0 /*TODO: bunch of conditions*/) {
+- bcm43xx_radio_set_interference_mitigation(bcm,
+- BCM43xx_RADIO_INTERFMODE_MANUALWLAN);
+- }
+- } else if (1/*TODO*/) {
+- /*
+- if ((aci_average > 1000) && !(bcm43xx_radio_aci_scan(bcm))) {
+- bcm43xx_radio_set_interference_mitigation(bcm,
+- BCM43xx_RADIO_INTERFMODE_NONE);
+- }
+- */
+- }
+- bcm43xx_mac_enable(bcm);
+- } else if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN &&
+- phy->rev == 1) {
+- //TODO: implement rev1 workaround
+- }
+- }
+-}
+-
+-static void do_periodic_work(struct bcm43xx_private *bcm)
+-{
+- if (bcm->periodic_state % 120 == 0)
+- bcm43xx_periodic_every120sec(bcm);
+- if (bcm->periodic_state % 60 == 0)
+- bcm43xx_periodic_every60sec(bcm);
+- if (bcm->periodic_state % 30 == 0)
+- bcm43xx_periodic_every30sec(bcm);
+- if (bcm->periodic_state % 15 == 0)
+- bcm43xx_periodic_every15sec(bcm);
+- bcm43xx_periodic_every1sec(bcm);
+-
+- schedule_delayed_work(&bcm->periodic_work, HZ);
+-}
+-
+-static void bcm43xx_periodic_work_handler(struct work_struct *work)
+-{
+- struct bcm43xx_private *bcm =
+- container_of(work, struct bcm43xx_private, periodic_work.work);
+- struct net_device *net_dev = bcm->net_dev;
+- unsigned long flags;
+- u32 savedirqs = 0;
+- unsigned long orig_trans_start = 0;
+-
+- mutex_lock(&bcm->mutex);
+- /* keep from doing and rearming periodic work if shutting down */
+- if (bcm43xx_status(bcm) == BCM43xx_STAT_UNINIT)
+- goto unlock_mutex;
+- if (unlikely(bcm->periodic_state % 60 == 0)) {
+- /* Periodic work will take a long time, so we want it to
+- * be preemtible.
+- */
+-
+- netif_tx_lock_bh(net_dev);
+- /* We must fake a started transmission here, as we are going to
+- * disable TX. If we wouldn't fake a TX, it would be possible to
+- * trigger the netdev watchdog, if the last real TX is already
+- * some time on the past (slightly less than 5secs)
+- */
+- orig_trans_start = net_dev->trans_start;
+- net_dev->trans_start = jiffies;
+- netif_stop_queue(net_dev);
+- netif_tx_unlock_bh(net_dev);
+-
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- bcm43xx_mac_suspend(bcm);
+- if (bcm43xx_using_pio(bcm))
+- bcm43xx_pio_freeze_txqueues(bcm);
+- savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- bcm43xx_synchronize_irq(bcm);
+- } else {
+- /* Periodic work should take short time, so we want low
+- * locking overhead.
+- */
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- }
+-
+- do_periodic_work(bcm);
+-
+- if (unlikely(bcm->periodic_state % 60 == 0)) {
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- tasklet_enable(&bcm->isr_tasklet);
+- bcm43xx_interrupt_enable(bcm, savedirqs);
+- if (bcm43xx_using_pio(bcm))
+- bcm43xx_pio_thaw_txqueues(bcm);
+- bcm43xx_mac_enable(bcm);
+- netif_wake_queue(bcm->net_dev);
+- net_dev->trans_start = orig_trans_start;
+- }
+- mmiowb();
+- bcm->periodic_state++;
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-unlock_mutex:
+- mutex_unlock(&bcm->mutex);
+-}
+-
+-void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
+-{
+- struct delayed_work *work = &bcm->periodic_work;
+-
+- assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
+- INIT_DELAYED_WORK(work, bcm43xx_periodic_work_handler);
+- schedule_delayed_work(work, 0);
+-}
+-
+-static void bcm43xx_security_init(struct bcm43xx_private *bcm)
+-{
+- bcm->security_offset = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+- 0x0056) * 2;
+- bcm43xx_clear_keys(bcm);
+-}
+-
+-static int bcm43xx_rng_read(struct hwrng *rng, u32 *data)
+-{
+- struct bcm43xx_private *bcm = (struct bcm43xx_private *)rng->priv;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&(bcm)->irq_lock, flags);
+- *data = bcm43xx_read16(bcm, BCM43xx_MMIO_RNG);
+- spin_unlock_irqrestore(&(bcm)->irq_lock, flags);
+-
+- return (sizeof(u16));
+-}
+-
+-static void bcm43xx_rng_exit(struct bcm43xx_private *bcm)
+-{
+- hwrng_unregister(&bcm->rng);
+-}
+-
+-static int bcm43xx_rng_init(struct bcm43xx_private *bcm)
+-{
+- int err;
+-
+- snprintf(bcm->rng_name, ARRAY_SIZE(bcm->rng_name),
+- "%s_%s", KBUILD_MODNAME, bcm->net_dev->name);
+- bcm->rng.name = bcm->rng_name;
+- bcm->rng.data_read = bcm43xx_rng_read;
+- bcm->rng.priv = (unsigned long)bcm;
+- err = hwrng_register(&bcm->rng);
+- if (err)
+- printk(KERN_ERR PFX "RNG init failed (%d)\n", err);
+-
+- return err;
+-}
+-
+-void bcm43xx_cancel_work(struct bcm43xx_private *bcm)
+-{
+- /* The system must be unlocked when this routine is entered.
+- * If not, the next 2 steps may deadlock */
+- cancel_work_sync(&bcm->restart_work);
+- cancel_delayed_work_sync(&bcm->periodic_work);
+-}
+-
+-static int bcm43xx_shutdown_all_wireless_cores(struct bcm43xx_private *bcm)
+-{
+- int ret = 0;
+- int i, err;
+- struct bcm43xx_coreinfo *core;
+-
+- bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN);
+- for (i = 0; i < bcm->nr_80211_available; i++) {
+- core = &(bcm->core_80211[i]);
+- assert(core->available);
+- if (!core->initialized)
+- continue;
+- err = bcm43xx_switch_core(bcm, core);
+- if (err) {
+- dprintk(KERN_ERR PFX "shutdown_all_wireless_cores "
+- "switch_core failed (%d)\n", err);
+- ret = err;
+- continue;
+- }
+- bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+- bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
+- bcm43xx_wireless_core_cleanup(bcm);
+- if (core == bcm->active_80211_core)
+- bcm->active_80211_core = NULL;
+- }
+- free_irq(bcm->irq, bcm);
+- bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
+-
+- return ret;
+-}
+-
+-/* This is the opposite of bcm43xx_init_board() */
+-static void bcm43xx_free_board(struct bcm43xx_private *bcm)
+-{
+- bcm43xx_rng_exit(bcm);
+- bcm43xx_sysfs_unregister(bcm);
+-
+- mutex_lock(&(bcm)->mutex);
+- bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
+- mutex_unlock(&(bcm)->mutex);
+-
+- bcm43xx_cancel_work(bcm);
+-
+- mutex_lock(&(bcm)->mutex);
+- bcm43xx_shutdown_all_wireless_cores(bcm);
+- bcm43xx_pctl_set_crystal(bcm, 0);
+- mutex_unlock(&(bcm)->mutex);
+-}
+-
+-static void prepare_phydata_for_init(struct bcm43xx_phyinfo *phy)
+-{
+- phy->antenna_diversity = 0xFFFF;
+- memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig));
+- memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos));
+-
+- /* Flags */
+- phy->calibrated = 0;
+- phy->is_locked = 0;
+-
+- if (phy->_lo_pairs) {
+- memset(phy->_lo_pairs, 0,
+- sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT);
+- }
+- memset(phy->loopback_gain, 0, sizeof(phy->loopback_gain));
+-}
+-
+-static void prepare_radiodata_for_init(struct bcm43xx_private *bcm,
+- struct bcm43xx_radioinfo *radio)
+-{
+- int i;
+-
+- /* Set default attenuation values. */
+- radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm);
+- radio->radio_atten = bcm43xx_default_radio_attenuation(bcm);
+- radio->txctl1 = bcm43xx_default_txctl1(bcm);
+- radio->txctl2 = 0xFFFF;
+- radio->txpwr_offset = 0;
+-
+- /* NRSSI */
+- radio->nrssislope = 0;
+- for (i = 0; i < ARRAY_SIZE(radio->nrssi); i++)
+- radio->nrssi[i] = -1000;
+- for (i = 0; i < ARRAY_SIZE(radio->nrssi_lt); i++)
+- radio->nrssi_lt[i] = i;
+-
+- radio->lofcal = 0xFFFF;
+- radio->initval = 0xFFFF;
+-
+- radio->aci_enable = 0;
+- radio->aci_wlan_automatic = 0;
+- radio->aci_hw_rssi = 0;
+-}
+-
+-static void prepare_priv_for_init(struct bcm43xx_private *bcm)
+-{
+- int i;
+- struct bcm43xx_coreinfo *core;
+- struct bcm43xx_coreinfo_80211 *wlext;
+-
+- assert(!bcm->active_80211_core);
+-
+- bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING);
+-
+- /* Flags */
+- bcm->was_initialized = 0;
+- bcm->reg124_set_0x4 = 0;
+-
+- /* Stats */
+- memset(&bcm->stats, 0, sizeof(bcm->stats));
+-
+- /* Wireless core data */
+- for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
+- core = &(bcm->core_80211[i]);
+- wlext = core->priv;
+-
+- if (!core->available)
+- continue;
+- assert(wlext == &(bcm->core_80211_ext[i]));
+-
+- prepare_phydata_for_init(&wlext->phy);
+- prepare_radiodata_for_init(bcm, &wlext->radio);
+- }
+-
+- /* IRQ related flags */
+- bcm->irq_reason = 0;
+- memset(bcm->dma_reason, 0, sizeof(bcm->dma_reason));
+- bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
+-
+- bcm->mac_suspended = 1;
+-
+- /* Noise calculation context */
+- memset(&bcm->noisecalc, 0, sizeof(bcm->noisecalc));
+-
+- /* Periodic work context */
+- bcm->periodic_state = 0;
+-}
+-
+-static int wireless_core_up(struct bcm43xx_private *bcm,
+- int active_wlcore)
+-{
+- int err;
+-
+- if (!bcm43xx_core_enabled(bcm))
+- bcm43xx_wireless_core_reset(bcm, 1);
+- if (!active_wlcore)
+- bcm43xx_wireless_core_mark_inactive(bcm);
+- err = bcm43xx_wireless_core_init(bcm, active_wlcore);
+- if (err)
+- goto out;
+- if (!active_wlcore)
+- bcm43xx_radio_turn_off(bcm);
+-out:
+- return err;
+-}
+-
+-/* Select and enable the "to be used" wireless core.
+- * Locking: bcm->mutex must be aquired before calling this.
+- * bcm->irq_lock must not be aquired.
+- */
+-int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm,
+- int phytype)
+-{
+- int i, err;
+- struct bcm43xx_coreinfo *active_core = NULL;
+- struct bcm43xx_coreinfo_80211 *active_wlext = NULL;
+- struct bcm43xx_coreinfo *core;
+- struct bcm43xx_coreinfo_80211 *wlext;
+- int adjust_active_sbtmstatelow = 0;
+-
+- might_sleep();
+-
+- if (phytype < 0) {
+- /* If no phytype is requested, select the first core. */
+- assert(bcm->core_80211[0].available);
+- wlext = bcm->core_80211[0].priv;
+- phytype = wlext->phy.type;
+- }
+- /* Find the requested core. */
+- for (i = 0; i < bcm->nr_80211_available; i++) {
+- core = &(bcm->core_80211[i]);
+- wlext = core->priv;
+- if (wlext->phy.type == phytype) {
+- active_core = core;
+- active_wlext = wlext;
+- break;
+- }
+- }
+- if (!active_core)
+- return -ESRCH; /* No such PHYTYPE on this board. */
+-
+- if (bcm->active_80211_core) {
+- /* We already selected a wl core in the past.
+- * So first clean up everything.
+- */
+- dprintk(KERN_INFO PFX "select_wireless_core: cleanup\n");
+- ieee80211softmac_stop(bcm->net_dev);
+- bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED);
+- err = bcm43xx_disable_interrupts_sync(bcm);
+- assert(!err);
+- tasklet_enable(&bcm->isr_tasklet);
+- err = bcm43xx_shutdown_all_wireless_cores(bcm);
+- if (err)
+- goto error;
+- /* Ok, everything down, continue to re-initialize. */
+- bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING);
+- }
+-
+- /* Reset all data structures. */
+- prepare_priv_for_init(bcm);
+-
+- err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_FAST);
+- if (err)
+- goto error;
+-
+- /* Mark all unused cores "inactive". */
+- for (i = 0; i < bcm->nr_80211_available; i++) {
+- core = &(bcm->core_80211[i]);
+- wlext = core->priv;
+-
+- if (core == active_core)
+- continue;
+- err = bcm43xx_switch_core(bcm, core);
+- if (err) {
+- dprintk(KERN_ERR PFX "Could not switch to inactive "
+- "802.11 core (%d)\n", err);
+- goto error;
+- }
+- err = wireless_core_up(bcm, 0);
+- if (err) {
+- dprintk(KERN_ERR PFX "core_up for inactive 802.11 core "
+- "failed (%d)\n", err);
+- goto error;
+- }
+- adjust_active_sbtmstatelow = 1;
+- }
+-
+- /* Now initialize the active 802.11 core. */
+- err = bcm43xx_switch_core(bcm, active_core);
+- if (err) {
+- dprintk(KERN_ERR PFX "Could not switch to active "
+- "802.11 core (%d)\n", err);
+- goto error;
+- }
+- if (adjust_active_sbtmstatelow &&
+- active_wlext->phy.type == BCM43xx_PHYTYPE_G) {
+- u32 sbtmstatelow;
+-
+- sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+- sbtmstatelow |= BCM43xx_SBTMSTATELOW_G_MODE_ENABLE;
+- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+- }
+- err = wireless_core_up(bcm, 1);
+- if (err) {
+- dprintk(KERN_ERR PFX "core_up for active 802.11 core "
+- "failed (%d)\n", err);
+- goto error;
+- }
+- err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC);
+- if (err)
+- goto error;
+- bcm->active_80211_core = active_core;
+-
+- bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
+- bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr));
+- bcm43xx_security_init(bcm);
+- drain_txstatus_queue(bcm);
+- ieee80211softmac_start(bcm->net_dev);
+-
+- /* Let's go! Be careful after enabling the IRQs.
+- * Don't switch cores, for example.
+- */
+- bcm43xx_mac_enable(bcm);
+- bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED);
+- err = bcm43xx_initialize_irq(bcm);
+- if (err)
+- goto error;
+- bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
+-
+- dprintk(KERN_INFO PFX "Selected 802.11 core (phytype %d)\n",
+- active_wlext->phy.type);
+-
+- return 0;
+-
+-error:
+- bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
+- bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW);
+- return err;
+-}
+-
+-static int bcm43xx_init_board(struct bcm43xx_private *bcm)
+-{
+- int err;
+-
+- mutex_lock(&(bcm)->mutex);
+-
+- tasklet_enable(&bcm->isr_tasklet);
+- err = bcm43xx_pctl_set_crystal(bcm, 1);
+- if (err)
+- goto err_tasklet;
+- err = bcm43xx_pctl_init(bcm);
+- if (err)
+- goto err_crystal_off;
+- err = bcm43xx_select_wireless_core(bcm, -1);
+- if (err)
+- goto err_crystal_off;
+- err = bcm43xx_sysfs_register(bcm);
+- if (err)
+- goto err_wlshutdown;
+- err = bcm43xx_rng_init(bcm);
+- if (err)
+- goto err_sysfs_unreg;
+- bcm43xx_periodic_tasks_setup(bcm);
+-
+- /*FIXME: This should be handled by softmac instead. */
+- schedule_delayed_work(&bcm->softmac->associnfo.work, 0);
+-
+-out:
+- mutex_unlock(&(bcm)->mutex);
+-
+- return err;
+-
+-err_sysfs_unreg:
+- bcm43xx_sysfs_unregister(bcm);
+-err_wlshutdown:
+- bcm43xx_shutdown_all_wireless_cores(bcm);
+-err_crystal_off:
+- bcm43xx_pctl_set_crystal(bcm, 0);
+-err_tasklet:
+- tasklet_disable(&bcm->isr_tasklet);
+- goto out;
+-}
+-
+-static void bcm43xx_detach_board(struct bcm43xx_private *bcm)
+-{
+- struct pci_dev *pci_dev = bcm->pci_dev;
+- int i;
+-
+- bcm43xx_chipset_detach(bcm);
+- /* Do _not_ access the chip, after it is detached. */
+- pci_iounmap(pci_dev, bcm->mmio_addr);
+- pci_release_regions(pci_dev);
+- pci_disable_device(pci_dev);
+-
+- /* Free allocated structures/fields */
+- for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
+- kfree(bcm->core_80211_ext[i].phy._lo_pairs);
+- if (bcm->core_80211_ext[i].phy.dyn_tssi_tbl)
+- kfree(bcm->core_80211_ext[i].phy.tssi2dbm);
+- }
+-}
+-
+-static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- u16 value;
+- u8 phy_analog;
+- u8 phy_type;
+- u8 phy_rev;
+- int phy_rev_ok = 1;
+- void *p;
+-
+- value = bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER);
+-
+- phy_analog = (value & 0xF000) >> 12;
+- phy_type = (value & 0x0F00) >> 8;
+- phy_rev = (value & 0x000F);
+-
+- dprintk(KERN_INFO PFX "Detected PHY: Analog: %x, Type %x, Revision %x\n",
+- phy_analog, phy_type, phy_rev);
+-
+- switch (phy_type) {
+- case BCM43xx_PHYTYPE_A:
+- if (phy_rev >= 4)
+- phy_rev_ok = 0;
+- /*FIXME: We need to switch the ieee->modulation, etc.. flags,
+- * if we switch 80211 cores after init is done.
+- * As we do not implement on the fly switching between
+- * wireless cores, I will leave this as a future task.
+- */
+- bcm->ieee->modulation = IEEE80211_OFDM_MODULATION;
+- bcm->ieee->mode = IEEE_A;
+- bcm->ieee->freq_band = IEEE80211_52GHZ_BAND |
+- IEEE80211_24GHZ_BAND;
+- break;
+- case BCM43xx_PHYTYPE_B:
+- if (phy_rev != 2 && phy_rev != 4 && phy_rev != 6 && phy_rev != 7)
+- phy_rev_ok = 0;
+- bcm->ieee->modulation = IEEE80211_CCK_MODULATION;
+- bcm->ieee->mode = IEEE_B;
+- bcm->ieee->freq_band = IEEE80211_24GHZ_BAND;
+- break;
+- case BCM43xx_PHYTYPE_G:
+- if (phy_rev > 8)
+- phy_rev_ok = 0;
+- bcm->ieee->modulation = IEEE80211_OFDM_MODULATION |
+- IEEE80211_CCK_MODULATION;
+- bcm->ieee->mode = IEEE_G;
+- bcm->ieee->freq_band = IEEE80211_24GHZ_BAND;
+- break;
+- default:
+- printk(KERN_ERR PFX "Error: Unknown PHY Type %x\n",
+- phy_type);
+- return -ENODEV;
+- };
+- bcm->ieee->perfect_rssi = RX_RSSI_MAX;
+- bcm->ieee->worst_rssi = 0;
+- if (!phy_rev_ok) {
+- printk(KERN_WARNING PFX "Invalid PHY Revision %x\n",
+- phy_rev);
+- }
+-
+- phy->analog = phy_analog;
+- phy->type = phy_type;
+- phy->rev = phy_rev;
+- if ((phy_type == BCM43xx_PHYTYPE_B) || (phy_type == BCM43xx_PHYTYPE_G)) {
+- p = kzalloc(sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT,
+- GFP_KERNEL);
+- if (!p)
+- return -ENOMEM;
+- phy->_lo_pairs = p;
+- }
+-
+- return 0;
+-}
+-
+-static int bcm43xx_attach_board(struct bcm43xx_private *bcm)
+-{
+- struct pci_dev *pci_dev = bcm->pci_dev;
+- struct net_device *net_dev = bcm->net_dev;
+- int err;
+- int i;
+- u32 coremask;
+-
+- err = pci_enable_device(pci_dev);
+- if (err) {
+- printk(KERN_ERR PFX "pci_enable_device() failed\n");
+- goto out;
+- }
+- err = pci_request_regions(pci_dev, KBUILD_MODNAME);
+- if (err) {
+- printk(KERN_ERR PFX "pci_request_regions() failed\n");
+- goto err_pci_disable;
+- }
+- /* enable PCI bus-mastering */
+- pci_set_master(pci_dev);
+- bcm->mmio_addr = pci_iomap(pci_dev, 0, ~0UL);
+- if (!bcm->mmio_addr) {
+- printk(KERN_ERR PFX "pci_iomap() failed\n");
+- err = -EIO;
+- goto err_pci_release;
+- }
+- net_dev->base_addr = (unsigned long)bcm->mmio_addr;
+-
+- err = bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID,
+- &bcm->board_vendor);
+- if (err)
+- goto err_iounmap;
+- err = bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_ID,
+- &bcm->board_type);
+- if (err)
+- goto err_iounmap;
+-
+- bcm->board_revision = bcm->pci_dev->revision;
+-
+- err = bcm43xx_chipset_attach(bcm);
+- if (err)
+- goto err_iounmap;
+- err = bcm43xx_pctl_init(bcm);
+- if (err)
+- goto err_chipset_detach;
+- err = bcm43xx_probe_cores(bcm);
+- if (err)
+- goto err_chipset_detach;
+-
+- /* Attach all IO cores to the backplane. */
+- coremask = 0;
+- for (i = 0; i < bcm->nr_80211_available; i++)
+- coremask |= (1 << bcm->core_80211[i].index);
+- //FIXME: Also attach some non80211 cores?
+- err = bcm43xx_setup_backplane_pci_connection(bcm, coremask);
+- if (err) {
+- printk(KERN_ERR PFX "Backplane->PCI connection failed!\n");
+- goto err_chipset_detach;
+- }
+-
+- err = bcm43xx_sprom_extract(bcm);
+- if (err)
+- goto err_chipset_detach;
+- err = bcm43xx_leds_init(bcm);
+- if (err)
+- goto err_chipset_detach;
+-
+- for (i = 0; i < bcm->nr_80211_available; i++) {
+- err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]);
+- assert(err != -ENODEV);
+- if (err)
+- goto err_80211_unwind;
+-
+- /* Enable the selected wireless core.
+- * Connect PHY only on the first core.
+- */
+- bcm43xx_wireless_core_reset(bcm, (i == 0));
+-
+- err = bcm43xx_read_phyinfo(bcm);
+- if (err && (i == 0))
+- goto err_80211_unwind;
+-
+- err = bcm43xx_read_radioinfo(bcm);
+- if (err && (i == 0))
+- goto err_80211_unwind;
+-
+- err = bcm43xx_validate_chip(bcm);
+- if (err && (i == 0))
+- goto err_80211_unwind;
+-
+- bcm43xx_radio_turn_off(bcm);
+- err = bcm43xx_phy_init_tssi2dbm_table(bcm);
+- if (err)
+- goto err_80211_unwind;
+- bcm43xx_wireless_core_disable(bcm);
+- }
+- err = bcm43xx_geo_init(bcm);
+- if (err)
+- goto err_80211_unwind;
+- bcm43xx_pctl_set_crystal(bcm, 0);
+-
+- /* Set the MAC address in the networking subsystem */
+- if (is_valid_ether_addr(bcm->sprom.et1macaddr))
+- memcpy(bcm->net_dev->dev_addr, bcm->sprom.et1macaddr, 6);
+- else
+- memcpy(bcm->net_dev->dev_addr, bcm->sprom.il0macaddr, 6);
+-
+- snprintf(bcm->nick, IW_ESSID_MAX_SIZE,
+- "Broadcom %04X", bcm->chip_id);
+-
+- assert(err == 0);
+-out:
+- return err;
+-
+-err_80211_unwind:
+- for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
+- kfree(bcm->core_80211_ext[i].phy._lo_pairs);
+- if (bcm->core_80211_ext[i].phy.dyn_tssi_tbl)
+- kfree(bcm->core_80211_ext[i].phy.tssi2dbm);
+- }
+-err_chipset_detach:
+- bcm43xx_chipset_detach(bcm);
+-err_iounmap:
+- pci_iounmap(pci_dev, bcm->mmio_addr);
+-err_pci_release:
+- pci_release_regions(pci_dev);
+-err_pci_disable:
+- pci_disable_device(pci_dev);
+- printk(KERN_ERR PFX "Unable to attach board\n");
+- goto out;
+-}
+-
+-/* Do the Hardware IO operations to send the txb */
+-static inline int bcm43xx_tx(struct bcm43xx_private *bcm,
+- struct ieee80211_txb *txb)
+-{
+- int err = -ENODEV;
+-
+- if (bcm43xx_using_pio(bcm))
+- err = bcm43xx_pio_tx(bcm, txb);
+- else
+- err = bcm43xx_dma_tx(bcm, txb);
+- bcm->net_dev->trans_start = jiffies;
+-
+- return err;
+-}
+-
+-static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev,
+- u8 channel)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- struct bcm43xx_radioinfo *radio;
+- unsigned long flags;
+-
+- mutex_lock(&bcm->mutex);
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
+- bcm43xx_mac_suspend(bcm);
+- bcm43xx_radio_selectchannel(bcm, channel, 0);
+- bcm43xx_mac_enable(bcm);
+- } else {
+- radio = bcm43xx_current_radio(bcm);
+- radio->initial_channel = channel;
+- }
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- mutex_unlock(&bcm->mutex);
+-}
+-
+-/* set_security() callback in struct ieee80211_device */
+-static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
+- struct ieee80211_security *sec)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- struct ieee80211_security *secinfo = &bcm->ieee->sec;
+- unsigned long flags;
+- int keyidx;
+-
+- dprintk(KERN_INFO PFX "set security called");
+-
+- mutex_lock(&bcm->mutex);
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+-
+- for (keyidx = 0; keyidx<WEP_KEYS; keyidx++)
+- if (sec->flags & (1<<keyidx)) {
+- secinfo->encode_alg[keyidx] = sec->encode_alg[keyidx];
+- secinfo->key_sizes[keyidx] = sec->key_sizes[keyidx];
+- memcpy(secinfo->keys[keyidx], sec->keys[keyidx], SCM_KEY_LEN);
+- }
+-
+- if (sec->flags & SEC_ACTIVE_KEY) {
+- secinfo->active_key = sec->active_key;
+- dprintk(", .active_key = %d", sec->active_key);
+- }
+- if (sec->flags & SEC_UNICAST_GROUP) {
+- secinfo->unicast_uses_group = sec->unicast_uses_group;
+- dprintk(", .unicast_uses_group = %d", sec->unicast_uses_group);
+- }
+- if (sec->flags & SEC_LEVEL) {
+- secinfo->level = sec->level;
+- dprintk(", .level = %d", sec->level);
+- }
+- if (sec->flags & SEC_ENABLED) {
+- secinfo->enabled = sec->enabled;
+- dprintk(", .enabled = %d", sec->enabled);
+- }
+- if (sec->flags & SEC_ENCRYPT) {
+- secinfo->encrypt = sec->encrypt;
+- dprintk(", .encrypt = %d", sec->encrypt);
+- }
+- if (sec->flags & SEC_AUTH_MODE) {
+- secinfo->auth_mode = sec->auth_mode;
+- dprintk(", .auth_mode = %d", sec->auth_mode);
+- }
+- dprintk("\n");
+- if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED &&
+- !bcm->ieee->host_encrypt) {
+- if (secinfo->enabled) {
+- /* upload WEP keys to hardware */
+- char null_address[6] = { 0 };
+- u8 algorithm = 0;
+- for (keyidx = 0; keyidx<WEP_KEYS; keyidx++) {
+- if (!(sec->flags & (1<<keyidx)))
+- continue;
+- switch (sec->encode_alg[keyidx]) {
+- case SEC_ALG_NONE: algorithm = BCM43xx_SEC_ALGO_NONE; break;
+- case SEC_ALG_WEP:
+- algorithm = BCM43xx_SEC_ALGO_WEP;
+- if (secinfo->key_sizes[keyidx] == 13)
+- algorithm = BCM43xx_SEC_ALGO_WEP104;
+- break;
+- case SEC_ALG_TKIP:
+- FIXME();
+- algorithm = BCM43xx_SEC_ALGO_TKIP;
+- break;
+- case SEC_ALG_CCMP:
+- FIXME();
+- algorithm = BCM43xx_SEC_ALGO_AES;
+- break;
+- default:
+- assert(0);
+- break;
+- }
+- bcm43xx_key_write(bcm, keyidx, algorithm, sec->keys[keyidx], secinfo->key_sizes[keyidx], &null_address[0]);
+- bcm->key[keyidx].enabled = 1;
+- bcm->key[keyidx].algorithm = algorithm;
+- }
+- } else
+- bcm43xx_clear_keys(bcm);
+- }
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- mutex_unlock(&bcm->mutex);
+-}
+-
+-/* hard_start_xmit() callback in struct ieee80211_device */
+-static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb,
+- struct net_device *net_dev,
+- int pri)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- int err = -ENODEV;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED))
+- err = bcm43xx_tx(bcm, txb);
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-
+- if (unlikely(err))
+- return NETDEV_TX_BUSY;
+- return NETDEV_TX_OK;
+-}
+-
+-static void bcm43xx_net_tx_timeout(struct net_device *net_dev)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- unsigned long flags;
+-
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- bcm43xx_controller_restart(bcm, "TX timeout");
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-}
+-
+-#ifdef CONFIG_NET_POLL_CONTROLLER
+-static void bcm43xx_net_poll_controller(struct net_device *net_dev)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- unsigned long flags;
+-
+- local_irq_save(flags);
+- if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
+- bcm43xx_interrupt_handler(bcm->irq, bcm);
+- local_irq_restore(flags);
+-}
+-#endif /* CONFIG_NET_POLL_CONTROLLER */
+-
+-static int bcm43xx_net_open(struct net_device *net_dev)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-
+- return bcm43xx_init_board(bcm);
+-}
+-
+-static int bcm43xx_net_stop(struct net_device *net_dev)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- int err;
+-
+- ieee80211softmac_stop(net_dev);
+- err = bcm43xx_disable_interrupts_sync(bcm);
+- assert(!err);
+- bcm43xx_free_board(bcm);
+- bcm43xx_cancel_work(bcm);
+-
+- return 0;
+-}
+-
+-static int bcm43xx_init_private(struct bcm43xx_private *bcm,
+- struct net_device *net_dev,
+- struct pci_dev *pci_dev)
+-{
+- bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
+- bcm->ieee = netdev_priv(net_dev);
+- bcm->softmac = ieee80211_priv(net_dev);
+- bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan;
+-
+- bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
+- bcm->mac_suspended = 1;
+- bcm->pci_dev = pci_dev;
+- bcm->net_dev = net_dev;
+- bcm->bad_frames_preempt = modparam_bad_frames_preempt;
+- spin_lock_init(&bcm->irq_lock);
+- spin_lock_init(&bcm->leds_lock);
+- mutex_init(&bcm->mutex);
+- tasklet_init(&bcm->isr_tasklet,
+- (void (*)(unsigned long))bcm43xx_interrupt_tasklet,
+- (unsigned long)bcm);
+- tasklet_disable_nosync(&bcm->isr_tasklet);
+- if (modparam_pio)
+- bcm->__using_pio = 1;
+- bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD;
+-
+- /* default to sw encryption for now */
+- bcm->ieee->host_build_iv = 0;
+- bcm->ieee->host_encrypt = 1;
+- bcm->ieee->host_decrypt = 1;
+-
+- bcm->ieee->iw_mode = BCM43xx_INITIAL_IWMODE;
+- bcm->ieee->tx_headroom = sizeof(struct bcm43xx_txhdr);
+- bcm->ieee->set_security = bcm43xx_ieee80211_set_security;
+- bcm->ieee->hard_start_xmit = bcm43xx_ieee80211_hard_start_xmit;
+-
+- return 0;
+-}
+-
+-static int __devinit bcm43xx_init_one(struct pci_dev *pdev,
+- const struct pci_device_id *ent)
+-{
+- struct net_device *net_dev;
+- struct bcm43xx_private *bcm;
+- int err;
+-
+-#ifdef DEBUG_SINGLE_DEVICE_ONLY
+- if (strcmp(pci_name(pdev), DEBUG_SINGLE_DEVICE_ONLY))
+- return -ENODEV;
+-#endif
+-
+- net_dev = alloc_ieee80211softmac(sizeof(*bcm));
+- if (!net_dev) {
+- printk(KERN_ERR PFX
+- "could not allocate ieee80211 device %s\n",
+- pci_name(pdev));
+- err = -ENOMEM;
+- goto out;
+- }
+- /* initialize the net_device struct */
+- SET_NETDEV_DEV(net_dev, &pdev->dev);
+-
+- net_dev->open = bcm43xx_net_open;
+- net_dev->stop = bcm43xx_net_stop;
+- net_dev->tx_timeout = bcm43xx_net_tx_timeout;
+-#ifdef CONFIG_NET_POLL_CONTROLLER
+- net_dev->poll_controller = bcm43xx_net_poll_controller;
+-#endif
+- net_dev->wireless_handlers = &bcm43xx_wx_handlers_def;
+- net_dev->irq = pdev->irq;
+- SET_ETHTOOL_OPS(net_dev, &bcm43xx_ethtool_ops);
+-
+- /* initialize the bcm43xx_private struct */
+- bcm = bcm43xx_priv(net_dev);
+- memset(bcm, 0, sizeof(*bcm));
+- err = bcm43xx_init_private(bcm, net_dev, pdev);
+- if (err)
+- goto err_free_netdev;
+-
+- pci_set_drvdata(pdev, net_dev);
+-
+- err = bcm43xx_attach_board(bcm);
+- if (err)
+- goto err_free_netdev;
+-
+- err = register_netdev(net_dev);
+- if (err) {
+- printk(KERN_ERR PFX "Cannot register net device, "
+- "aborting.\n");
+- err = -ENOMEM;
+- goto err_detach_board;
+- }
+-
+- bcm43xx_debugfs_add_device(bcm);
+-
+- assert(err == 0);
+-out:
+- return err;
+-
+-err_detach_board:
+- bcm43xx_detach_board(bcm);
+-err_free_netdev:
+- free_ieee80211softmac(net_dev);
+- goto out;
+-}
+-
+-static void __devexit bcm43xx_remove_one(struct pci_dev *pdev)
+-{
+- struct net_device *net_dev = pci_get_drvdata(pdev);
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-
+- bcm43xx_debugfs_remove_device(bcm);
+- unregister_netdev(net_dev);
+- bcm43xx_detach_board(bcm);
+- free_ieee80211softmac(net_dev);
+-}
+-
+-/* Hard-reset the chip. Do not call this directly.
+- * Use bcm43xx_controller_restart()
+- */
+-static void bcm43xx_chip_reset(struct work_struct *work)
+-{
+- struct bcm43xx_private *bcm =
+- container_of(work, struct bcm43xx_private, restart_work);
+- struct bcm43xx_phyinfo *phy;
+- int err = -ENODEV;
+-
+- bcm43xx_cancel_work(bcm);
+- mutex_lock(&(bcm)->mutex);
+- if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
+- phy = bcm43xx_current_phy(bcm);
+- err = bcm43xx_select_wireless_core(bcm, phy->type);
+- if (!err)
+- bcm43xx_periodic_tasks_setup(bcm);
+- }
+- mutex_unlock(&(bcm)->mutex);
+-
+- printk(KERN_ERR PFX "Controller restart%s\n",
+- (err == 0) ? "ed" : " failed");
+-}
+-
+-/* Hard-reset the chip.
+- * This can be called from interrupt or process context.
+- * bcm->irq_lock must be locked.
+- */
+-void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason)
+-{
+- if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
+- return;
+- printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason);
+- INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset);
+- schedule_work(&bcm->restart_work);
+-}
+-
+-#ifdef CONFIG_PM
+-
+-static int bcm43xx_suspend(struct pci_dev *pdev, pm_message_t state)
+-{
+- struct net_device *net_dev = pci_get_drvdata(pdev);
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- int err;
+-
+- dprintk(KERN_INFO PFX "Suspending...\n");
+-
+- netif_device_detach(net_dev);
+- bcm->was_initialized = 0;
+- if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
+- bcm->was_initialized = 1;
+- ieee80211softmac_stop(net_dev);
+- err = bcm43xx_disable_interrupts_sync(bcm);
+- if (unlikely(err)) {
+- dprintk(KERN_ERR PFX "Suspend failed.\n");
+- return -EAGAIN;
+- }
+- bcm->firmware_norelease = 1;
+- bcm43xx_free_board(bcm);
+- bcm->firmware_norelease = 0;
+- }
+- bcm43xx_chipset_detach(bcm);
+-
+- pci_save_state(pdev);
+- pci_disable_device(pdev);
+- pci_set_power_state(pdev, pci_choose_state(pdev, state));
+-
+- dprintk(KERN_INFO PFX "Device suspended.\n");
+-
+- return 0;
+-}
+-
+-static int bcm43xx_resume(struct pci_dev *pdev)
+-{
+- struct net_device *net_dev = pci_get_drvdata(pdev);
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- int err = 0;
+-
+- dprintk(KERN_INFO PFX "Resuming...\n");
+-
+- pci_set_power_state(pdev, 0);
+- err = pci_enable_device(pdev);
+- if (err) {
+- printk(KERN_ERR PFX "Failure with pci_enable_device!\n");
+- return err;
+- }
+- pci_restore_state(pdev);
+-
+- bcm43xx_chipset_attach(bcm);
+- if (bcm->was_initialized)
+- err = bcm43xx_init_board(bcm);
+- if (err) {
+- printk(KERN_ERR PFX "Resume failed!\n");
+- return err;
+- }
+- netif_device_attach(net_dev);
+-
+- dprintk(KERN_INFO PFX "Device resumed.\n");
+-
+- return 0;
+-}
+-
+-#endif /* CONFIG_PM */
+-
+-static struct pci_driver bcm43xx_pci_driver = {
+- .name = KBUILD_MODNAME,
+- .id_table = bcm43xx_pci_tbl,
+- .probe = bcm43xx_init_one,
+- .remove = __devexit_p(bcm43xx_remove_one),
+-#ifdef CONFIG_PM
+- .suspend = bcm43xx_suspend,
+- .resume = bcm43xx_resume,
+-#endif /* CONFIG_PM */
+-};
+-
+-static int __init bcm43xx_init(void)
+-{
+- printk(KERN_INFO KBUILD_MODNAME " driver\n");
+- bcm43xx_debugfs_init();
+- return pci_register_driver(&bcm43xx_pci_driver);
+-}
+-
+-static void __exit bcm43xx_exit(void)
+-{
+- pci_unregister_driver(&bcm43xx_pci_driver);
+- bcm43xx_debugfs_exit();
+-}
+-
+-module_init(bcm43xx_init)
+-module_exit(bcm43xx_exit)
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
+deleted file mode 100644
+index 14cfbeb..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h
++++ /dev/null
+@@ -1,133 +0,0 @@
+-/*
+-
+- Broadcom BCM43xx wireless driver
+-
+- Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+- Stefano Brivio <st3 at riseup.net>
+- Michael Buesch <mbuesch at freenet.de>
+- Danny van Dyk <kugelfang at gentoo.org>
+- Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+- Some parts of the code in this file are derived from the ipw2200
+- driver Copyright(c) 2003 - 2004 Intel Corporation.
+-
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; 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; see the file COPYING. If not, write to
+- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+- Boston, MA 02110-1301, USA.
+-
+-*/
+-
+-#ifndef BCM43xx_MAIN_H_
+-#define BCM43xx_MAIN_H_
+-
+-#include "bcm43xx.h"
+-
+-#define P4D_BYT3S(magic, nr_bytes) u8 __p4dding##magic[nr_bytes]
+-#define P4D_BYTES(line, nr_bytes) P4D_BYT3S(line, nr_bytes)
+-/* Magic helper macro to pad structures. Ignore those above. It's magic. */
+-#define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes))
+-
+-
+-/* Lightweight function to convert a frequency (in Mhz) to a channel number. */
+-static inline
+-u8 bcm43xx_freq_to_channel_a(int freq)
+-{
+- return ((freq - 5000) / 5);
+-}
+-static inline
+-u8 bcm43xx_freq_to_channel_bg(int freq)
+-{
+- u8 channel;
+-
+- if (freq == 2484)
+- channel = 14;
+- else
+- channel = (freq - 2407) / 5;
+-
+- return channel;
+-}
+-static inline
+-u8 bcm43xx_freq_to_channel(struct bcm43xx_private *bcm,
+- int freq)
+-{
+- if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A)
+- return bcm43xx_freq_to_channel_a(freq);
+- return bcm43xx_freq_to_channel_bg(freq);
+-}
+-
+-/* Lightweight function to convert a channel number to a frequency (in Mhz). */
+-static inline
+-int bcm43xx_channel_to_freq_a(u8 channel)
+-{
+- return (5000 + (5 * channel));
+-}
+-static inline
+-int bcm43xx_channel_to_freq_bg(u8 channel)
+-{
+- int freq;
+-
+- if (channel == 14)
+- freq = 2484;
+- else
+- freq = 2407 + (5 * channel);
+-
+- return freq;
+-}
+-static inline
+-int bcm43xx_channel_to_freq(struct bcm43xx_private *bcm,
+- u8 channel)
+-{
+- if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A)
+- return bcm43xx_channel_to_freq_a(channel);
+- return bcm43xx_channel_to_freq_bg(channel);
+-}
+-
+-void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf);
+-void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf);
+-
+-void bcm43xx_set_iwmode(struct bcm43xx_private *bcm,
+- int iw_mode);
+-
+-u32 bcm43xx_shm_read32(struct bcm43xx_private *bcm,
+- u16 routing, u16 offset);
+-u16 bcm43xx_shm_read16(struct bcm43xx_private *bcm,
+- u16 routing, u16 offset);
+-void bcm43xx_shm_write32(struct bcm43xx_private *bcm,
+- u16 routing, u16 offset,
+- u32 value);
+-void bcm43xx_shm_write16(struct bcm43xx_private *bcm,
+- u16 routing, u16 offset,
+- u16 value);
+-
+-void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm);
+-
+-int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core);
+-
+-int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm,
+- int phytype);
+-
+-void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy);
+-
+-void bcm43xx_mac_suspend(struct bcm43xx_private *bcm);
+-void bcm43xx_mac_enable(struct bcm43xx_private *bcm);
+-
+-void bcm43xx_cancel_work(struct bcm43xx_private *bcm);
+-void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm);
+-
+-void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason);
+-
+-int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom);
+-int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom);
+-
+-#endif /* BCM43xx_MAIN_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
+deleted file mode 100644
+index af3de33..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
++++ /dev/null
+@@ -1,2346 +0,0 @@
+-/*
+-
+- Broadcom BCM43xx wireless driver
+-
+- Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+- Stefano Brivio <st3 at riseup.net>
+- Michael Buesch <mbuesch at freenet.de>
+- Danny van Dyk <kugelfang at gentoo.org>
+- Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+- Some parts of the code in this file are derived from the ipw2200
+- driver Copyright(c) 2003 - 2004 Intel Corporation.
+-
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; 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; see the file COPYING. If not, write to
+- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+- Boston, MA 02110-1301, USA.
+-
+-*/
+-
+-#include <linux/delay.h>
+-#include <linux/pci.h>
+-#include <linux/types.h>
+-
+-#include "bcm43xx.h"
+-#include "bcm43xx_phy.h"
+-#include "bcm43xx_main.h"
+-#include "bcm43xx_radio.h"
+-#include "bcm43xx_ilt.h"
+-#include "bcm43xx_power.h"
+-
+-
+-static const s8 bcm43xx_tssi2dbm_b_table[] = {
+- 0x4D, 0x4C, 0x4B, 0x4A,
+- 0x4A, 0x49, 0x48, 0x47,
+- 0x47, 0x46, 0x45, 0x45,
+- 0x44, 0x43, 0x42, 0x42,
+- 0x41, 0x40, 0x3F, 0x3E,
+- 0x3D, 0x3C, 0x3B, 0x3A,
+- 0x39, 0x38, 0x37, 0x36,
+- 0x35, 0x34, 0x32, 0x31,
+- 0x30, 0x2F, 0x2D, 0x2C,
+- 0x2B, 0x29, 0x28, 0x26,
+- 0x25, 0x23, 0x21, 0x1F,
+- 0x1D, 0x1A, 0x17, 0x14,
+- 0x10, 0x0C, 0x06, 0x00,
+- -7, -7, -7, -7,
+- -7, -7, -7, -7,
+- -7, -7, -7, -7,
+-};
+-
+-static const s8 bcm43xx_tssi2dbm_g_table[] = {
+- 77, 77, 77, 76,
+- 76, 76, 75, 75,
+- 74, 74, 73, 73,
+- 73, 72, 72, 71,
+- 71, 70, 70, 69,
+- 68, 68, 67, 67,
+- 66, 65, 65, 64,
+- 63, 63, 62, 61,
+- 60, 59, 58, 57,
+- 56, 55, 54, 53,
+- 52, 50, 49, 47,
+- 45, 43, 40, 37,
+- 33, 28, 22, 14,
+- 5, -7, -20, -20,
+- -20, -20, -20, -20,
+- -20, -20, -20, -20,
+-};
+-
+-static void bcm43xx_phy_initg(struct bcm43xx_private *bcm);
+-
+-
+-static inline
+-void bcm43xx_voluntary_preempt(void)
+-{
+- assert(!in_atomic() && !in_irq() &&
+- !in_interrupt() && !irqs_disabled());
+-#ifndef CONFIG_PREEMPT
+- cond_resched();
+-#endif /* CONFIG_PREEMPT */
+-}
+-
+-void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-
+- assert(irqs_disabled());
+- if (bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) == 0x00000000) {
+- phy->is_locked = 0;
+- return;
+- }
+- if (bcm->current_core->rev < 3) {
+- bcm43xx_mac_suspend(bcm);
+- spin_lock(&phy->lock);
+- } else {
+- if (bcm->ieee->iw_mode != IW_MODE_MASTER)
+- bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
+- }
+- phy->is_locked = 1;
+-}
+-
+-void bcm43xx_raw_phy_unlock(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-
+- assert(irqs_disabled());
+- if (bcm->current_core->rev < 3) {
+- if (phy->is_locked) {
+- spin_unlock(&phy->lock);
+- bcm43xx_mac_enable(bcm);
+- }
+- } else {
+- if (bcm->ieee->iw_mode != IW_MODE_MASTER)
+- bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
+- }
+- phy->is_locked = 0;
+-}
+-
+-u16 bcm43xx_phy_read(struct bcm43xx_private *bcm, u16 offset)
+-{
+- bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_CONTROL, offset);
+- return bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_DATA);
+-}
+-
+-void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val)
+-{
+- bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_CONTROL, offset);
+- mmiowb();
+- bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_DATA, val);
+-}
+-
+-void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-
+- bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */
+- if (phy->calibrated)
+- return;
+- if (phy->type == BCM43xx_PHYTYPE_G && phy->rev == 1) {
+- bcm43xx_wireless_core_reset(bcm, 0);
+- bcm43xx_phy_initg(bcm);
+- bcm43xx_wireless_core_reset(bcm, 1);
+- }
+- phy->calibrated = 1;
+-}
+-
+-/* Connect the PHY
+- * http://bcm-specs.sipsolutions.net/SetPHY
+- */
+-int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- u32 flags;
+-
+- if (bcm->current_core->rev < 5)
+- goto out;
+-
+- flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
+- if (connect) {
+- if (!(flags & BCM43xx_SBTMSTATEHIGH_G_PHY_AVAIL))
+- return -ENODEV;
+- flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+- flags |= BCM43xx_SBTMSTATELOW_G_MODE_ENABLE;
+- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags);
+- } else {
+- if (!(flags & BCM43xx_SBTMSTATEHIGH_A_PHY_AVAIL))
+- return -ENODEV;
+- flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+- flags &= ~BCM43xx_SBTMSTATELOW_G_MODE_ENABLE;
+- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags);
+- }
+-out:
+- phy->connected = connect;
+- if (connect)
+- dprintk(KERN_INFO PFX "PHY connected\n");
+- else
+- dprintk(KERN_INFO PFX "PHY disconnected\n");
+-
+- return 0;
+-}
+-
+-/* intialize B PHY power control
+- * as described in http://bcm-specs.sipsolutions.net/InitPowerControl
+- */
+-static void bcm43xx_phy_init_pctl(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- u16 saved_batt = 0, saved_ratt = 0, saved_txctl1 = 0;
+- int must_reset_txpower = 0;
+-
+- assert(phy->type != BCM43xx_PHYTYPE_A);
+- if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) &&
+- (bcm->board_type == 0x0416))
+- return;
+-
+- bcm43xx_phy_write(bcm, 0x0028, 0x8018);
+- bcm43xx_write16(bcm, 0x03E6, bcm43xx_read16(bcm, 0x03E6) & 0xFFDF);
+-
+- if (phy->type == BCM43xx_PHYTYPE_G) {
+- if (!phy->connected)
+- return;
+- bcm43xx_phy_write(bcm, 0x047A, 0xC111);
+- }
+- if (phy->savedpctlreg != 0xFFFF)
+- return;
+-
+- if (phy->type == BCM43xx_PHYTYPE_B &&
+- phy->rev >= 2 &&
+- radio->version == 0x2050) {
+- bcm43xx_radio_write16(bcm, 0x0076,
+- bcm43xx_radio_read16(bcm, 0x0076) | 0x0084);
+- } else {
+- saved_batt = radio->baseband_atten;
+- saved_ratt = radio->radio_atten;
+- saved_txctl1 = radio->txctl1;
+- if ((radio->revision >= 6) && (radio->revision <= 8)
+- && /*FIXME: incomplete specs for 5 < revision < 9 */ 0)
+- bcm43xx_radio_set_txpower_bg(bcm, 0xB, 0x1F, 0);
+- else
+- bcm43xx_radio_set_txpower_bg(bcm, 0xB, 9, 0);
+- must_reset_txpower = 1;
+- }
+- bcm43xx_dummy_transmission(bcm);
+-
+- phy->savedpctlreg = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_PCTL);
+-
+- if (must_reset_txpower)
+- bcm43xx_radio_set_txpower_bg(bcm, saved_batt, saved_ratt, saved_txctl1);
+- else
+- bcm43xx_radio_write16(bcm, 0x0076, bcm43xx_radio_read16(bcm, 0x0076) & 0xFF7B);
+- bcm43xx_radio_clear_tssi(bcm);
+-}
+-
+-static void bcm43xx_phy_agcsetup(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- u16 offset = 0x0000;
+-
+- if (phy->rev == 1)
+- offset = 0x4C00;
+-
+- bcm43xx_ilt_write(bcm, offset, 0x00FE);
+- bcm43xx_ilt_write(bcm, offset + 1, 0x000D);
+- bcm43xx_ilt_write(bcm, offset + 2, 0x0013);
+- bcm43xx_ilt_write(bcm, offset + 3, 0x0019);
+-
+- if (phy->rev == 1) {
+- bcm43xx_ilt_write(bcm, 0x1800, 0x2710);
+- bcm43xx_ilt_write(bcm, 0x1801, 0x9B83);
+- bcm43xx_ilt_write(bcm, 0x1802, 0x9B83);
+- bcm43xx_ilt_write(bcm, 0x1803, 0x0F8D);
+- bcm43xx_phy_write(bcm, 0x0455, 0x0004);
+- }
+-
+- bcm43xx_phy_write(bcm, 0x04A5, (bcm43xx_phy_read(bcm, 0x04A5) & 0x00FF) | 0x5700);
+- bcm43xx_phy_write(bcm, 0x041A, (bcm43xx_phy_read(bcm, 0x041A) & 0xFF80) | 0x000F);
+- bcm43xx_phy_write(bcm, 0x041A, (bcm43xx_phy_read(bcm, 0x041A) & 0xC07F) | 0x2B80);
+- bcm43xx_phy_write(bcm, 0x048C, (bcm43xx_phy_read(bcm, 0x048C) & 0xF0FF) | 0x0300);
+-
+- bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0008);
+-
+- bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xFFF0) | 0x0008);
+- bcm43xx_phy_write(bcm, 0x04A1, (bcm43xx_phy_read(bcm, 0x04A1) & 0xF0FF) | 0x0600);
+- bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xF0FF) | 0x0700);
+- bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xF0FF) | 0x0100);
+-
+- if (phy->rev == 1)
+- bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xFFF0) | 0x0007);
+-
+- bcm43xx_phy_write(bcm, 0x0488, (bcm43xx_phy_read(bcm, 0x0488) & 0xFF00) | 0x001C);
+- bcm43xx_phy_write(bcm, 0x0488, (bcm43xx_phy_read(bcm, 0x0488) & 0xC0FF) | 0x0200);
+- bcm43xx_phy_write(bcm, 0x0496, (bcm43xx_phy_read(bcm, 0x0496) & 0xFF00) | 0x001C);
+- bcm43xx_phy_write(bcm, 0x0489, (bcm43xx_phy_read(bcm, 0x0489) & 0xFF00) | 0x0020);
+- bcm43xx_phy_write(bcm, 0x0489, (bcm43xx_phy_read(bcm, 0x0489) & 0xC0FF) | 0x0200);
+- bcm43xx_phy_write(bcm, 0x0482, (bcm43xx_phy_read(bcm, 0x0482) & 0xFF00) | 0x002E);
+- bcm43xx_phy_write(bcm, 0x0496, (bcm43xx_phy_read(bcm, 0x0496) & 0x00FF) | 0x1A00);
+- bcm43xx_phy_write(bcm, 0x0481, (bcm43xx_phy_read(bcm, 0x0481) & 0xFF00) | 0x0028);
+- bcm43xx_phy_write(bcm, 0x0481, (bcm43xx_phy_read(bcm, 0x0481) & 0x00FF) | 0x2C00);
+-
+- if (phy->rev == 1) {
+- bcm43xx_phy_write(bcm, 0x0430, 0x092B);
+- bcm43xx_phy_write(bcm, 0x041B, (bcm43xx_phy_read(bcm, 0x041B) & 0xFFE1) | 0x0002);
+- } else {
+- bcm43xx_phy_write(bcm, 0x041B, bcm43xx_phy_read(bcm, 0x041B) & 0xFFE1);
+- bcm43xx_phy_write(bcm, 0x041F, 0x287A);
+- bcm43xx_phy_write(bcm, 0x0420, (bcm43xx_phy_read(bcm, 0x0420) & 0xFFF0) | 0x0004);
+- }
+-
+- if (phy->rev > 2) {
+- bcm43xx_phy_write(bcm, 0x0422, 0x287A);
+- bcm43xx_phy_write(bcm, 0x0420, (bcm43xx_phy_read(bcm, 0x0420)
+- & 0x0FFF) | 0x3000);
+- }
+-
+- bcm43xx_phy_write(bcm, 0x04A8, (bcm43xx_phy_read(bcm, 0x04A8) & 0x8080)
+- | 0x7874);
+- bcm43xx_phy_write(bcm, 0x048E, 0x1C00);
+-
+- if (phy->rev == 1) {
+- bcm43xx_phy_write(bcm, 0x04AB, (bcm43xx_phy_read(bcm, 0x04AB)
+- & 0xF0FF) | 0x0600);
+- bcm43xx_phy_write(bcm, 0x048B, 0x005E);
+- bcm43xx_phy_write(bcm, 0x048C, (bcm43xx_phy_read(bcm, 0x048C)
+- & 0xFF00) | 0x001E);
+- bcm43xx_phy_write(bcm, 0x048D, 0x0002);
+- }
+-
+- bcm43xx_ilt_write(bcm, offset + 0x0800, 0);
+- bcm43xx_ilt_write(bcm, offset + 0x0801, 7);
+- bcm43xx_ilt_write(bcm, offset + 0x0802, 16);
+- bcm43xx_ilt_write(bcm, offset + 0x0803, 28);
+-
+- if (phy->rev >= 6) {
+- bcm43xx_phy_write(bcm, 0x0426, (bcm43xx_phy_read(bcm, 0x0426)
+- & 0xFFFC));
+- bcm43xx_phy_write(bcm, 0x0426, (bcm43xx_phy_read(bcm, 0x0426)
+- & 0xEFFF));
+- }
+-}
+-
+-static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- u16 i;
+-
+- assert(phy->type == BCM43xx_PHYTYPE_G);
+- if (phy->rev == 1) {
+- bcm43xx_phy_write(bcm, 0x0406, 0x4F19);
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+- (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS)
+- & 0xFC3F) | 0x0340);
+- bcm43xx_phy_write(bcm, 0x042C, 0x005A);
+- bcm43xx_phy_write(bcm, 0x0427, 0x001A);
+-
+- for (i = 0; i < BCM43xx_ILT_FINEFREQG_SIZE; i++)
+- bcm43xx_ilt_write(bcm, 0x5800 + i, bcm43xx_ilt_finefreqg[i]);
+- for (i = 0; i < BCM43xx_ILT_NOISEG1_SIZE; i++)
+- bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg1[i]);
+- for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++)
+- bcm43xx_ilt_write32(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
+- } else {
+- /* nrssi values are signed 6-bit values. Not sure why we write 0x7654 here... */
+- bcm43xx_nrssi_hw_write(bcm, 0xBA98, (s16)0x7654);
+-
+- if (phy->rev == 2) {
+- bcm43xx_phy_write(bcm, 0x04C0, 0x1861);
+- bcm43xx_phy_write(bcm, 0x04C1, 0x0271);
+- } else if (phy->rev > 2) {
+- bcm43xx_phy_write(bcm, 0x04C0, 0x0098);
+- bcm43xx_phy_write(bcm, 0x04C1, 0x0070);
+- bcm43xx_phy_write(bcm, 0x04C9, 0x0080);
+- }
+- bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x800);
+-
+- for (i = 0; i < 64; i++)
+- bcm43xx_ilt_write(bcm, 0x4000 + i, i);
+- for (i = 0; i < BCM43xx_ILT_NOISEG2_SIZE; i++)
+- bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg2[i]);
+- }
+-
+- if (phy->rev <= 2)
+- for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
+- bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg1[i]);
+- else if ((phy->rev >= 7) && (bcm43xx_phy_read(bcm, 0x0449) & 0x0200))
+- for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
+- bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg3[i]);
+- else
+- for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
+- bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg2[i]);
+-
+- if (phy->rev == 2)
+- for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
+- bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]);
+- else if ((phy->rev > 2) && (phy->rev <= 8))
+- for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
+- bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr2[i]);
+-
+- if (phy->rev == 1) {
+- for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++)
+- bcm43xx_ilt_write32(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
+- for (i = 0; i < 4; i++) {
+- bcm43xx_ilt_write(bcm, 0x5404 + i, 0x0020);
+- bcm43xx_ilt_write(bcm, 0x5408 + i, 0x0020);
+- bcm43xx_ilt_write(bcm, 0x540C + i, 0x0020);
+- bcm43xx_ilt_write(bcm, 0x5410 + i, 0x0020);
+- }
+- bcm43xx_phy_agcsetup(bcm);
+-
+- if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) &&
+- (bcm->board_type == 0x0416) &&
+- (bcm->board_revision == 0x0017))
+- return;
+-
+- bcm43xx_ilt_write(bcm, 0x5001, 0x0002);
+- bcm43xx_ilt_write(bcm, 0x5002, 0x0001);
+- } else {
+- for (i = 0; i <= 0x2F; i++)
+- bcm43xx_ilt_write(bcm, 0x1000 + i, 0x0820);
+- bcm43xx_phy_agcsetup(bcm);
+- bcm43xx_phy_read(bcm, 0x0400); /* dummy read */
+- bcm43xx_phy_write(bcm, 0x0403, 0x1000);
+- bcm43xx_ilt_write(bcm, 0x3C02, 0x000F);
+- bcm43xx_ilt_write(bcm, 0x3C03, 0x0014);
+-
+- if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) &&
+- (bcm->board_type == 0x0416) &&
+- (bcm->board_revision == 0x0017))
+- return;
+-
+- bcm43xx_ilt_write(bcm, 0x0401, 0x0002);
+- bcm43xx_ilt_write(bcm, 0x0402, 0x0001);
+- }
+-}
+-
+-/* Initialize the noisescaletable for APHY */
+-static void bcm43xx_phy_init_noisescaletbl(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- int i;
+-
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, 0x1400);
+- for (i = 0; i < 12; i++) {
+- if (phy->rev == 2)
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6767);
+- else
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2323);
+- }
+- if (phy->rev == 2)
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6700);
+- else
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2300);
+- for (i = 0; i < 11; i++) {
+- if (phy->rev == 2)
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6767);
+- else
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2323);
+- }
+- if (phy->rev == 2)
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x0067);
+- else
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x0023);
+-}
+-
+-static void bcm43xx_phy_setupa(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- u16 i;
+-
+- assert(phy->type == BCM43xx_PHYTYPE_A);
+- switch (phy->rev) {
+- case 2:
+- bcm43xx_phy_write(bcm, 0x008E, 0x3800);
+- bcm43xx_phy_write(bcm, 0x0035, 0x03FF);
+- bcm43xx_phy_write(bcm, 0x0036, 0x0400);
+-
+- bcm43xx_ilt_write(bcm, 0x3807, 0x0051);
+-
+- bcm43xx_phy_write(bcm, 0x001C, 0x0FF9);
+- bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F);
+- bcm43xx_ilt_write(bcm, 0x3C0C, 0x07BF);
+- bcm43xx_radio_write16(bcm, 0x0002, 0x07BF);
+-
+- bcm43xx_phy_write(bcm, 0x0024, 0x4680);
+- bcm43xx_phy_write(bcm, 0x0020, 0x0003);
+- bcm43xx_phy_write(bcm, 0x001D, 0x0F40);
+- bcm43xx_phy_write(bcm, 0x001F, 0x1C00);
+-
+- bcm43xx_phy_write(bcm, 0x002A, (bcm43xx_phy_read(bcm, 0x002A) & 0x00FF) | 0x0400);
+- bcm43xx_phy_write(bcm, 0x002B, bcm43xx_phy_read(bcm, 0x002B) & 0xFBFF);
+- bcm43xx_phy_write(bcm, 0x008E, 0x58C1);
+-
+- bcm43xx_ilt_write(bcm, 0x0803, 0x000F);
+- bcm43xx_ilt_write(bcm, 0x0804, 0x001F);
+- bcm43xx_ilt_write(bcm, 0x0805, 0x002A);
+- bcm43xx_ilt_write(bcm, 0x0805, 0x0030);
+- bcm43xx_ilt_write(bcm, 0x0807, 0x003A);
+-
+- bcm43xx_ilt_write(bcm, 0x0000, 0x0013);
+- bcm43xx_ilt_write(bcm, 0x0001, 0x0013);
+- bcm43xx_ilt_write(bcm, 0x0002, 0x0013);
+- bcm43xx_ilt_write(bcm, 0x0003, 0x0013);
+- bcm43xx_ilt_write(bcm, 0x0004, 0x0015);
+- bcm43xx_ilt_write(bcm, 0x0005, 0x0015);
+- bcm43xx_ilt_write(bcm, 0x0006, 0x0019);
+-
+- bcm43xx_ilt_write(bcm, 0x0404, 0x0003);
+- bcm43xx_ilt_write(bcm, 0x0405, 0x0003);
+- bcm43xx_ilt_write(bcm, 0x0406, 0x0007);
+-
+- for (i = 0; i < 16; i++)
+- bcm43xx_ilt_write(bcm, 0x4000 + i, (0x8 + i) & 0x000F);
+-
+- bcm43xx_ilt_write(bcm, 0x3003, 0x1044);
+- bcm43xx_ilt_write(bcm, 0x3004, 0x7201);
+- bcm43xx_ilt_write(bcm, 0x3006, 0x0040);
+- bcm43xx_ilt_write(bcm, 0x3001, (bcm43xx_ilt_read(bcm, 0x3001) & 0x0010) | 0x0008);
+-
+- for (i = 0; i < BCM43xx_ILT_FINEFREQA_SIZE; i++)
+- bcm43xx_ilt_write(bcm, 0x5800 + i, bcm43xx_ilt_finefreqa[i]);
+- for (i = 0; i < BCM43xx_ILT_NOISEA2_SIZE; i++)
+- bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea2[i]);
+- for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++)
+- bcm43xx_ilt_write32(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
+- bcm43xx_phy_init_noisescaletbl(bcm);
+- for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++)
+- bcm43xx_ilt_write32(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
+- break;
+- case 3:
+- for (i = 0; i < 64; i++)
+- bcm43xx_ilt_write(bcm, 0x4000 + i, i);
+-
+- bcm43xx_ilt_write(bcm, 0x3807, 0x0051);
+-
+- bcm43xx_phy_write(bcm, 0x001C, 0x0FF9);
+- bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F);
+- bcm43xx_radio_write16(bcm, 0x0002, 0x07BF);
+-
+- bcm43xx_phy_write(bcm, 0x0024, 0x4680);
+- bcm43xx_phy_write(bcm, 0x0020, 0x0003);
+- bcm43xx_phy_write(bcm, 0x001D, 0x0F40);
+- bcm43xx_phy_write(bcm, 0x001F, 0x1C00);
+- bcm43xx_phy_write(bcm, 0x002A, (bcm43xx_phy_read(bcm, 0x002A) & 0x00FF) | 0x0400);
+-
+- bcm43xx_ilt_write(bcm, 0x3001, (bcm43xx_ilt_read(bcm, 0x3001) & 0x0010) | 0x0008);
+- for (i = 0; i < BCM43xx_ILT_NOISEA3_SIZE; i++)
+- bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea3[i]);
+- bcm43xx_phy_init_noisescaletbl(bcm);
+- for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
+- bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]);
+-
+- bcm43xx_phy_write(bcm, 0x0003, 0x1808);
+-
+- bcm43xx_ilt_write(bcm, 0x0803, 0x000F);
+- bcm43xx_ilt_write(bcm, 0x0804, 0x001F);
+- bcm43xx_ilt_write(bcm, 0x0805, 0x002A);
+- bcm43xx_ilt_write(bcm, 0x0805, 0x0030);
+- bcm43xx_ilt_write(bcm, 0x0807, 0x003A);
+-
+- bcm43xx_ilt_write(bcm, 0x0000, 0x0013);
+- bcm43xx_ilt_write(bcm, 0x0001, 0x0013);
+- bcm43xx_ilt_write(bcm, 0x0002, 0x0013);
+- bcm43xx_ilt_write(bcm, 0x0003, 0x0013);
+- bcm43xx_ilt_write(bcm, 0x0004, 0x0015);
+- bcm43xx_ilt_write(bcm, 0x0005, 0x0015);
+- bcm43xx_ilt_write(bcm, 0x0006, 0x0019);
+-
+- bcm43xx_ilt_write(bcm, 0x0404, 0x0003);
+- bcm43xx_ilt_write(bcm, 0x0405, 0x0003);
+- bcm43xx_ilt_write(bcm, 0x0406, 0x0007);
+-
+- bcm43xx_ilt_write(bcm, 0x3C02, 0x000F);
+- bcm43xx_ilt_write(bcm, 0x3C03, 0x0014);
+- break;
+- default:
+- assert(0);
+- }
+-}
+-
+-/* Initialize APHY. This is also called for the GPHY in some cases. */
+-static void bcm43xx_phy_inita(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- u16 tval;
+-
+- if (phy->type == BCM43xx_PHYTYPE_A) {
+- bcm43xx_phy_setupa(bcm);
+- } else {
+- bcm43xx_phy_setupg(bcm);
+- if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
+- bcm43xx_phy_write(bcm, 0x046E, 0x03CF);
+- return;
+- }
+-
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_A_CRS,
+- (bcm43xx_phy_read(bcm, BCM43xx_PHY_A_CRS) & 0xF83C) | 0x0340);
+- bcm43xx_phy_write(bcm, 0x0034, 0x0001);
+-
+- TODO();//TODO: RSSI AGC
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_A_CRS,
+- bcm43xx_phy_read(bcm, BCM43xx_PHY_A_CRS) | (1 << 14));
+- bcm43xx_radio_init2060(bcm);
+-
+- if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM)
+- && ((bcm->board_type == 0x0416) || (bcm->board_type == 0x040A))) {
+- if (radio->lofcal == 0xFFFF) {
+- TODO();//TODO: LOF Cal
+- bcm43xx_radio_set_tx_iq(bcm);
+- } else
+- bcm43xx_radio_write16(bcm, 0x001E, radio->lofcal);
+- }
+-
+- bcm43xx_phy_write(bcm, 0x007A, 0xF111);
+-
+- if (phy->savedpctlreg == 0xFFFF) {
+- bcm43xx_radio_write16(bcm, 0x0019, 0x0000);
+- bcm43xx_radio_write16(bcm, 0x0017, 0x0020);
+-
+- tval = bcm43xx_ilt_read(bcm, 0x3001);
+- if (phy->rev == 1) {
+- bcm43xx_ilt_write(bcm, 0x3001,
+- (bcm43xx_ilt_read(bcm, 0x3001) & 0xFF87)
+- | 0x0058);
+- } else {
+- bcm43xx_ilt_write(bcm, 0x3001,
+- (bcm43xx_ilt_read(bcm, 0x3001) & 0xFFC3)
+- | 0x002C);
+- }
+- bcm43xx_dummy_transmission(bcm);
+- phy->savedpctlreg = bcm43xx_phy_read(bcm, BCM43xx_PHY_A_PCTL);
+- bcm43xx_ilt_write(bcm, 0x3001, tval);
+-
+- bcm43xx_radio_set_txpower_a(bcm, 0x0018);
+- }
+- bcm43xx_radio_clear_tssi(bcm);
+-}
+-
+-static void bcm43xx_phy_initb2(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- u16 offset, val;
+-
+- bcm43xx_write16(bcm, 0x03EC, 0x3F22);
+- bcm43xx_phy_write(bcm, 0x0020, 0x301C);
+- bcm43xx_phy_write(bcm, 0x0026, 0x0000);
+- bcm43xx_phy_write(bcm, 0x0030, 0x00C6);
+- bcm43xx_phy_write(bcm, 0x0088, 0x3E00);
+- val = 0x3C3D;
+- for (offset = 0x0089; offset < 0x00A7; offset++) {
+- bcm43xx_phy_write(bcm, offset, val);
+- val -= 0x0202;
+- }
+- bcm43xx_phy_write(bcm, 0x03E4, 0x3000);
+- if (radio->channel == 0xFF)
+- bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
+- else
+- bcm43xx_radio_selectchannel(bcm, radio->channel, 0);
+- if (radio->version != 0x2050) {
+- bcm43xx_radio_write16(bcm, 0x0075, 0x0080);
+- bcm43xx_radio_write16(bcm, 0x0079, 0x0081);
+- }
+- bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+- bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
+- if (radio->version == 0x2050) {
+- bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+- bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
+- bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
+- bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
+- bcm43xx_radio_write16(bcm, 0x007A, 0x000F);
+- bcm43xx_phy_write(bcm, 0x0038, 0x0677);
+- bcm43xx_radio_init2050(bcm);
+- }
+- bcm43xx_phy_write(bcm, 0x0014, 0x0080);
+- bcm43xx_phy_write(bcm, 0x0032, 0x00CA);
+- bcm43xx_phy_write(bcm, 0x0032, 0x00CC);
+- bcm43xx_phy_write(bcm, 0x0035, 0x07C2);
+- bcm43xx_phy_lo_b_measure(bcm);
+- bcm43xx_phy_write(bcm, 0x0026, 0xCC00);
+- if (radio->version != 0x2050)
+- bcm43xx_phy_write(bcm, 0x0026, 0xCE00);
+- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x1000);
+- bcm43xx_phy_write(bcm, 0x002A, 0x88A3);
+- if (radio->version != 0x2050)
+- bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
+- bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
+- bcm43xx_phy_init_pctl(bcm);
+-}
+-
+-static void bcm43xx_phy_initb4(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- u16 offset, val;
+-
+- bcm43xx_write16(bcm, 0x03EC, 0x3F22);
+- bcm43xx_phy_write(bcm, 0x0020, 0x301C);
+- bcm43xx_phy_write(bcm, 0x0026, 0x0000);
+- bcm43xx_phy_write(bcm, 0x0030, 0x00C6);
+- bcm43xx_phy_write(bcm, 0x0088, 0x3E00);
+- val = 0x3C3D;
+- for (offset = 0x0089; offset < 0x00A7; offset++) {
+- bcm43xx_phy_write(bcm, offset, val);
+- val -= 0x0202;
+- }
+- bcm43xx_phy_write(bcm, 0x03E4, 0x3000);
+- if (radio->channel == 0xFF)
+- bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
+- else
+- bcm43xx_radio_selectchannel(bcm, radio->channel, 0);
+- if (radio->version != 0x2050) {
+- bcm43xx_radio_write16(bcm, 0x0075, 0x0080);
+- bcm43xx_radio_write16(bcm, 0x0079, 0x0081);
+- }
+- bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+- bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
+- if (radio->version == 0x2050) {
+- bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+- bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
+- bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
+- bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
+- bcm43xx_radio_write16(bcm, 0x007A, 0x000F);
+- bcm43xx_phy_write(bcm, 0x0038, 0x0677);
+- bcm43xx_radio_init2050(bcm);
+- }
+- bcm43xx_phy_write(bcm, 0x0014, 0x0080);
+- bcm43xx_phy_write(bcm, 0x0032, 0x00CA);
+- if (radio->version == 0x2050)
+- bcm43xx_phy_write(bcm, 0x0032, 0x00E0);
+- bcm43xx_phy_write(bcm, 0x0035, 0x07C2);
+-
+- bcm43xx_phy_lo_b_measure(bcm);
+-
+- bcm43xx_phy_write(bcm, 0x0026, 0xCC00);
+- if (radio->version == 0x2050)
+- bcm43xx_phy_write(bcm, 0x0026, 0xCE00);
+- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x1100);
+- bcm43xx_phy_write(bcm, 0x002A, 0x88A3);
+- if (radio->version == 0x2050)
+- bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
+- bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
+- if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
+- bcm43xx_calc_nrssi_slope(bcm);
+- bcm43xx_calc_nrssi_threshold(bcm);
+- }
+- bcm43xx_phy_init_pctl(bcm);
+-}
+-
+-static void bcm43xx_phy_initb5(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- u16 offset;
+- u16 value;
+- u8 old_channel;
+-
+- if (phy->analog == 1)
+- bcm43xx_radio_write16(bcm, 0x007A,
+- bcm43xx_radio_read16(bcm, 0x007A)
+- | 0x0050);
+- if ((bcm->board_vendor != PCI_VENDOR_ID_BROADCOM) &&
+- (bcm->board_type != 0x0416)) {
+- value = 0x2120;
+- for (offset = 0x00A8 ; offset < 0x00C7; offset++) {
+- bcm43xx_phy_write(bcm, offset, value);
+- value += 0x0202;
+- }
+- }
+- bcm43xx_phy_write(bcm, 0x0035,
+- (bcm43xx_phy_read(bcm, 0x0035) & 0xF0FF)
+- | 0x0700);
+- if (radio->version == 0x2050)
+- bcm43xx_phy_write(bcm, 0x0038, 0x0667);
+-
+- if (phy->connected) {
+- if (radio->version == 0x2050) {
+- bcm43xx_radio_write16(bcm, 0x007A,
+- bcm43xx_radio_read16(bcm, 0x007A)
+- | 0x0020);
+- bcm43xx_radio_write16(bcm, 0x0051,
+- bcm43xx_radio_read16(bcm, 0x0051)
+- | 0x0004);
+- }
+- bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, 0x0000);
+-
+- bcm43xx_phy_write(bcm, 0x0802, bcm43xx_phy_read(bcm, 0x0802) | 0x0100);
+- bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x2000);
+-
+- bcm43xx_phy_write(bcm, 0x001C, 0x186A);
+-
+- bcm43xx_phy_write(bcm, 0x0013, (bcm43xx_phy_read(bcm, 0x0013) & 0x00FF) | 0x1900);
+- bcm43xx_phy_write(bcm, 0x0035, (bcm43xx_phy_read(bcm, 0x0035) & 0xFFC0) | 0x0064);
+- bcm43xx_phy_write(bcm, 0x005D, (bcm43xx_phy_read(bcm, 0x005D) & 0xFF80) | 0x000A);
+- }
+-
+- if (bcm->bad_frames_preempt) {
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
+- bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | (1 << 11));
+- }
+-
+- if (phy->analog == 1) {
+- bcm43xx_phy_write(bcm, 0x0026, 0xCE00);
+- bcm43xx_phy_write(bcm, 0x0021, 0x3763);
+- bcm43xx_phy_write(bcm, 0x0022, 0x1BC3);
+- bcm43xx_phy_write(bcm, 0x0023, 0x06F9);
+- bcm43xx_phy_write(bcm, 0x0024, 0x037E);
+- } else
+- bcm43xx_phy_write(bcm, 0x0026, 0xCC00);
+- bcm43xx_phy_write(bcm, 0x0030, 0x00C6);
+- bcm43xx_write16(bcm, 0x03EC, 0x3F22);
+-
+- if (phy->analog == 1)
+- bcm43xx_phy_write(bcm, 0x0020, 0x3E1C);
+- else
+- bcm43xx_phy_write(bcm, 0x0020, 0x301C);
+-
+- if (phy->analog == 0)
+- bcm43xx_write16(bcm, 0x03E4, 0x3000);
+-
+- old_channel = radio->channel;
+- /* Force to channel 7, even if not supported. */
+- bcm43xx_radio_selectchannel(bcm, 7, 0);
+-
+- if (radio->version != 0x2050) {
+- bcm43xx_radio_write16(bcm, 0x0075, 0x0080);
+- bcm43xx_radio_write16(bcm, 0x0079, 0x0081);
+- }
+-
+- bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+- bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
+-
+- if (radio->version == 0x2050) {
+- bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+- bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
+- }
+-
+- bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
+- bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
+-
+- bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0007);
+-
+- bcm43xx_radio_selectchannel(bcm, old_channel, 0);
+-
+- bcm43xx_phy_write(bcm, 0x0014, 0x0080);
+- bcm43xx_phy_write(bcm, 0x0032, 0x00CA);
+- bcm43xx_phy_write(bcm, 0x002A, 0x88A3);
+-
+- bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
+-
+- if (radio->version == 0x2050)
+- bcm43xx_radio_write16(bcm, 0x005D, 0x000D);
+-
+- bcm43xx_write16(bcm, 0x03E4, (bcm43xx_read16(bcm, 0x03E4) & 0xFFC0) | 0x0004);
+-}
+-
+-static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- u16 offset, val;
+- u8 old_channel;
+-
+- bcm43xx_phy_write(bcm, 0x003E, 0x817A);
+- bcm43xx_radio_write16(bcm, 0x007A,
+- (bcm43xx_radio_read16(bcm, 0x007A) | 0x0058));
+- if (radio->revision == 4 ||
+- radio->revision == 5) {
+- bcm43xx_radio_write16(bcm, 0x0051, 0x0037);
+- bcm43xx_radio_write16(bcm, 0x0052, 0x0070);
+- bcm43xx_radio_write16(bcm, 0x0053, 0x00B3);
+- bcm43xx_radio_write16(bcm, 0x0054, 0x009B);
+- bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
+- bcm43xx_radio_write16(bcm, 0x005B, 0x0088);
+- bcm43xx_radio_write16(bcm, 0x005D, 0x0088);
+- bcm43xx_radio_write16(bcm, 0x005E, 0x0088);
+- bcm43xx_radio_write16(bcm, 0x007D, 0x0088);
+- bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODEFLAGS_OFFSET,
+- (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODEFLAGS_OFFSET)
+- | 0x00000200));
+- }
+- if (radio->revision == 8) {
+- bcm43xx_radio_write16(bcm, 0x0051, 0x0000);
+- bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
+- bcm43xx_radio_write16(bcm, 0x0053, 0x00B7);
+- bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
+- bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
+- bcm43xx_radio_write16(bcm, 0x005B, 0x006B);
+- bcm43xx_radio_write16(bcm, 0x005C, 0x000F);
+- if (bcm->sprom.boardflags & 0x8000) {
+- bcm43xx_radio_write16(bcm, 0x005D, 0x00FA);
+- bcm43xx_radio_write16(bcm, 0x005E, 0x00D8);
+- } else {
+- bcm43xx_radio_write16(bcm, 0x005D, 0x00F5);
+- bcm43xx_radio_write16(bcm, 0x005E, 0x00B8);
+- }
+- bcm43xx_radio_write16(bcm, 0x0073, 0x0003);
+- bcm43xx_radio_write16(bcm, 0x007D, 0x00A8);
+- bcm43xx_radio_write16(bcm, 0x007C, 0x0001);
+- bcm43xx_radio_write16(bcm, 0x007E, 0x0008);
+- }
+- val = 0x1E1F;
+- for (offset = 0x0088; offset < 0x0098; offset++) {
+- bcm43xx_phy_write(bcm, offset, val);
+- val -= 0x0202;
+- }
+- val = 0x3E3F;
+- for (offset = 0x0098; offset < 0x00A8; offset++) {
+- bcm43xx_phy_write(bcm, offset, val);
+- val -= 0x0202;
+- }
+- val = 0x2120;
+- for (offset = 0x00A8; offset < 0x00C8; offset++) {
+- bcm43xx_phy_write(bcm, offset, (val & 0x3F3F));
+- val += 0x0202;
+- }
+- if (phy->type == BCM43xx_PHYTYPE_G) {
+- bcm43xx_radio_write16(bcm, 0x007A,
+- bcm43xx_radio_read16(bcm, 0x007A) | 0x0020);
+- bcm43xx_radio_write16(bcm, 0x0051,
+- bcm43xx_radio_read16(bcm, 0x0051) | 0x0004);
+- bcm43xx_phy_write(bcm, 0x0802,
+- bcm43xx_phy_read(bcm, 0x0802) | 0x0100);
+- bcm43xx_phy_write(bcm, 0x042B,
+- bcm43xx_phy_read(bcm, 0x042B) | 0x2000);
+- bcm43xx_phy_write(bcm, 0x5B, 0x0000);
+- bcm43xx_phy_write(bcm, 0x5C, 0x0000);
+- }
+-
+- old_channel = radio->channel;
+- if (old_channel >= 8)
+- bcm43xx_radio_selectchannel(bcm, 1, 0);
+- else
+- bcm43xx_radio_selectchannel(bcm, 13, 0);
+-
+- bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+- bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
+- udelay(40);
+- if (radio->revision < 6 || radio-> revision == 8) {
+- bcm43xx_radio_write16(bcm, 0x007C, (bcm43xx_radio_read16(bcm, 0x007C)
+- | 0x0002));
+- bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
+- }
+- if (radio->revision <= 2) {
+- bcm43xx_radio_write16(bcm, 0x007C, 0x0020);
+- bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
+- bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
+- bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
+- }
+- bcm43xx_radio_write16(bcm, 0x007A,
+- (bcm43xx_radio_read16(bcm, 0x007A) & 0x00F8) | 0x0007);
+-
+- bcm43xx_radio_selectchannel(bcm, old_channel, 0);
+-
+- bcm43xx_phy_write(bcm, 0x0014, 0x0200);
+- if (radio->revision >= 6)
+- bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
+- else
+- bcm43xx_phy_write(bcm, 0x002A, 0x8AC0);
+- bcm43xx_phy_write(bcm, 0x0038, 0x0668);
+- bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
+- if (radio->revision <= 5)
+- bcm43xx_phy_write(bcm, 0x005D, (bcm43xx_phy_read(bcm, 0x005D)
+- & 0xFF80) | 0x0003);
+- if (radio->revision <= 2)
+- bcm43xx_radio_write16(bcm, 0x005D, 0x000D);
+-
+- if (phy->analog == 4){
+- bcm43xx_write16(bcm, 0x03E4, 0x0009);
+- bcm43xx_phy_write(bcm, 0x61, bcm43xx_phy_read(bcm, 0x61) & 0xFFF);
+- } else {
+- bcm43xx_phy_write(bcm, 0x0002, (bcm43xx_phy_read(bcm, 0x0002) & 0xFFC0) | 0x0004);
+- }
+- if (phy->type == BCM43xx_PHYTYPE_G)
+- bcm43xx_write16(bcm, 0x03E6, 0x0);
+- if (phy->type == BCM43xx_PHYTYPE_B) {
+- bcm43xx_write16(bcm, 0x03E6, 0x8140);
+- bcm43xx_phy_write(bcm, 0x0016, 0x0410);
+- bcm43xx_phy_write(bcm, 0x0017, 0x0820);
+- bcm43xx_phy_write(bcm, 0x0062, 0x0007);
+- bcm43xx_radio_init2050(bcm);
+- bcm43xx_phy_lo_g_measure(bcm);
+- if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
+- bcm43xx_calc_nrssi_slope(bcm);
+- bcm43xx_calc_nrssi_threshold(bcm);
+- }
+- bcm43xx_phy_init_pctl(bcm);
+- }
+-}
+-
+-static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- u16 backup_phy[15] = {0};
+- u16 backup_radio[3];
+- u16 backup_bband;
+- u16 i;
+- u16 loop1_cnt, loop1_done, loop1_omitted;
+- u16 loop2_done;
+-
+- backup_phy[0] = bcm43xx_phy_read(bcm, 0x0429);
+- backup_phy[1] = bcm43xx_phy_read(bcm, 0x0001);
+- backup_phy[2] = bcm43xx_phy_read(bcm, 0x0811);
+- backup_phy[3] = bcm43xx_phy_read(bcm, 0x0812);
+- if (phy->rev != 1) {
+- backup_phy[4] = bcm43xx_phy_read(bcm, 0x0814);
+- backup_phy[5] = bcm43xx_phy_read(bcm, 0x0815);
+- }
+- backup_phy[6] = bcm43xx_phy_read(bcm, 0x005A);
+- backup_phy[7] = bcm43xx_phy_read(bcm, 0x0059);
+- backup_phy[8] = bcm43xx_phy_read(bcm, 0x0058);
+- backup_phy[9] = bcm43xx_phy_read(bcm, 0x000A);
+- backup_phy[10] = bcm43xx_phy_read(bcm, 0x0003);
+- backup_phy[11] = bcm43xx_phy_read(bcm, 0x080F);
+- backup_phy[12] = bcm43xx_phy_read(bcm, 0x0810);
+- backup_phy[13] = bcm43xx_phy_read(bcm, 0x002B);
+- backup_phy[14] = bcm43xx_phy_read(bcm, 0x0015);
+- bcm43xx_phy_read(bcm, 0x002D); /* dummy read */
+- backup_bband = radio->baseband_atten;
+- backup_radio[0] = bcm43xx_radio_read16(bcm, 0x0052);
+- backup_radio[1] = bcm43xx_radio_read16(bcm, 0x0043);
+- backup_radio[2] = bcm43xx_radio_read16(bcm, 0x007A);
+-
+- bcm43xx_phy_write(bcm, 0x0429,
+- bcm43xx_phy_read(bcm, 0x0429) & 0x3FFF);
+- bcm43xx_phy_write(bcm, 0x0001,
+- bcm43xx_phy_read(bcm, 0x0001) & 0x8000);
+- bcm43xx_phy_write(bcm, 0x0811,
+- bcm43xx_phy_read(bcm, 0x0811) | 0x0002);
+- bcm43xx_phy_write(bcm, 0x0812,
+- bcm43xx_phy_read(bcm, 0x0812) & 0xFFFD);
+- bcm43xx_phy_write(bcm, 0x0811,
+- bcm43xx_phy_read(bcm, 0x0811) | 0x0001);
+- bcm43xx_phy_write(bcm, 0x0812,
+- bcm43xx_phy_read(bcm, 0x0812) & 0xFFFE);
+- if (phy->rev != 1) {
+- bcm43xx_phy_write(bcm, 0x0814,
+- bcm43xx_phy_read(bcm, 0x0814) | 0x0001);
+- bcm43xx_phy_write(bcm, 0x0815,
+- bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE);
+- bcm43xx_phy_write(bcm, 0x0814,
+- bcm43xx_phy_read(bcm, 0x0814) | 0x0002);
+- bcm43xx_phy_write(bcm, 0x0815,
+- bcm43xx_phy_read(bcm, 0x0815) & 0xFFFD);
+- }
+- bcm43xx_phy_write(bcm, 0x0811,
+- bcm43xx_phy_read(bcm, 0x0811) | 0x000C);
+- bcm43xx_phy_write(bcm, 0x0812,
+- bcm43xx_phy_read(bcm, 0x0812) | 0x000C);
+-
+- bcm43xx_phy_write(bcm, 0x0811,
+- (bcm43xx_phy_read(bcm, 0x0811)
+- & 0xFFCF) | 0x0030);
+- bcm43xx_phy_write(bcm, 0x0812,
+- (bcm43xx_phy_read(bcm, 0x0812)
+- & 0xFFCF) | 0x0010);
+-
+- bcm43xx_phy_write(bcm, 0x005A, 0x0780);
+- bcm43xx_phy_write(bcm, 0x0059, 0xC810);
+- bcm43xx_phy_write(bcm, 0x0058, 0x000D);
+- if (phy->analog == 0) {
+- bcm43xx_phy_write(bcm, 0x0003, 0x0122);
+- } else {
+- bcm43xx_phy_write(bcm, 0x000A,
+- bcm43xx_phy_read(bcm, 0x000A)
+- | 0x2000);
+- }
+- if (phy->rev != 1) {
+- bcm43xx_phy_write(bcm, 0x0814,
+- bcm43xx_phy_read(bcm, 0x0814) | 0x0004);
+- bcm43xx_phy_write(bcm, 0x0815,
+- bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB);
+- }
+- bcm43xx_phy_write(bcm, 0x0003,
+- (bcm43xx_phy_read(bcm, 0x0003)
+- & 0xFF9F) | 0x0040);
+- if (radio->version == 0x2050 && radio->revision == 2) {
+- bcm43xx_radio_write16(bcm, 0x0052, 0x0000);
+- bcm43xx_radio_write16(bcm, 0x0043,
+- (bcm43xx_radio_read16(bcm, 0x0043)
+- & 0xFFF0) | 0x0009);
+- loop1_cnt = 9;
+- } else if (radio->revision == 8) {
+- bcm43xx_radio_write16(bcm, 0x0043, 0x000F);
+- loop1_cnt = 15;
+- } else
+- loop1_cnt = 0;
+-
+- bcm43xx_phy_set_baseband_attenuation(bcm, 11);
+-
+- if (phy->rev >= 3)
+- bcm43xx_phy_write(bcm, 0x080F, 0xC020);
+- else
+- bcm43xx_phy_write(bcm, 0x080F, 0x8020);
+- bcm43xx_phy_write(bcm, 0x0810, 0x0000);
+-
+- bcm43xx_phy_write(bcm, 0x002B,
+- (bcm43xx_phy_read(bcm, 0x002B)
+- & 0xFFC0) | 0x0001);
+- bcm43xx_phy_write(bcm, 0x002B,
+- (bcm43xx_phy_read(bcm, 0x002B)
+- & 0xC0FF) | 0x0800);
+- bcm43xx_phy_write(bcm, 0x0811,
+- bcm43xx_phy_read(bcm, 0x0811) | 0x0100);
+- bcm43xx_phy_write(bcm, 0x0812,
+- bcm43xx_phy_read(bcm, 0x0812) & 0xCFFF);
+- if (bcm->sprom.boardflags & BCM43xx_BFL_EXTLNA) {
+- if (phy->rev >= 7) {
+- bcm43xx_phy_write(bcm, 0x0811,
+- bcm43xx_phy_read(bcm, 0x0811)
+- | 0x0800);
+- bcm43xx_phy_write(bcm, 0x0812,
+- bcm43xx_phy_read(bcm, 0x0812)
+- | 0x8000);
+- }
+- }
+- bcm43xx_radio_write16(bcm, 0x007A,
+- bcm43xx_radio_read16(bcm, 0x007A)
+- & 0x00F7);
+-
+- for (i = 0; i < loop1_cnt; i++) {
+- bcm43xx_radio_write16(bcm, 0x0043, loop1_cnt);
+- bcm43xx_phy_write(bcm, 0x0812,
+- (bcm43xx_phy_read(bcm, 0x0812)
+- & 0xF0FF) | (i << 8));
+- bcm43xx_phy_write(bcm, 0x0015,
+- (bcm43xx_phy_read(bcm, 0x0015)
+- & 0x0FFF) | 0xA000);
+- bcm43xx_phy_write(bcm, 0x0015,
+- (bcm43xx_phy_read(bcm, 0x0015)
+- & 0x0FFF) | 0xF000);
+- udelay(20);
+- if (bcm43xx_phy_read(bcm, 0x002D) >= 0x0DFC)
+- break;
+- }
+- loop1_done = i;
+- loop1_omitted = loop1_cnt - loop1_done;
+-
+- loop2_done = 0;
+- if (loop1_done >= 8) {
+- bcm43xx_phy_write(bcm, 0x0812,
+- bcm43xx_phy_read(bcm, 0x0812)
+- | 0x0030);
+- for (i = loop1_done - 8; i < 16; i++) {
+- bcm43xx_phy_write(bcm, 0x0812,
+- (bcm43xx_phy_read(bcm, 0x0812)
+- & 0xF0FF) | (i << 8));
+- bcm43xx_phy_write(bcm, 0x0015,
+- (bcm43xx_phy_read(bcm, 0x0015)
+- & 0x0FFF) | 0xA000);
+- bcm43xx_phy_write(bcm, 0x0015,
+- (bcm43xx_phy_read(bcm, 0x0015)
+- & 0x0FFF) | 0xF000);
+- udelay(20);
+- if (bcm43xx_phy_read(bcm, 0x002D) >= 0x0DFC)
+- break;
+- }
+- }
+-
+- if (phy->rev != 1) {
+- bcm43xx_phy_write(bcm, 0x0814, backup_phy[4]);
+- bcm43xx_phy_write(bcm, 0x0815, backup_phy[5]);
+- }
+- bcm43xx_phy_write(bcm, 0x005A, backup_phy[6]);
+- bcm43xx_phy_write(bcm, 0x0059, backup_phy[7]);
+- bcm43xx_phy_write(bcm, 0x0058, backup_phy[8]);
+- bcm43xx_phy_write(bcm, 0x000A, backup_phy[9]);
+- bcm43xx_phy_write(bcm, 0x0003, backup_phy[10]);
+- bcm43xx_phy_write(bcm, 0x080F, backup_phy[11]);
+- bcm43xx_phy_write(bcm, 0x0810, backup_phy[12]);
+- bcm43xx_phy_write(bcm, 0x002B, backup_phy[13]);
+- bcm43xx_phy_write(bcm, 0x0015, backup_phy[14]);
+-
+- bcm43xx_phy_set_baseband_attenuation(bcm, backup_bband);
+-
+- bcm43xx_radio_write16(bcm, 0x0052, backup_radio[0]);
+- bcm43xx_radio_write16(bcm, 0x0043, backup_radio[1]);
+- bcm43xx_radio_write16(bcm, 0x007A, backup_radio[2]);
+-
+- bcm43xx_phy_write(bcm, 0x0811, backup_phy[2] | 0x0003);
+- udelay(10);
+- bcm43xx_phy_write(bcm, 0x0811, backup_phy[2]);
+- bcm43xx_phy_write(bcm, 0x0812, backup_phy[3]);
+- bcm43xx_phy_write(bcm, 0x0429, backup_phy[0]);
+- bcm43xx_phy_write(bcm, 0x0001, backup_phy[1]);
+-
+- phy->loopback_gain[0] = ((loop1_done * 6) - (loop1_omitted * 4)) - 11;
+- phy->loopback_gain[1] = (24 - (3 * loop2_done)) * 2;
+-}
+-
+-static void bcm43xx_phy_initg(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- u16 tmp;
+-
+- if (phy->rev == 1)
+- bcm43xx_phy_initb5(bcm);
+- else
+- bcm43xx_phy_initb6(bcm);
+- if (phy->rev >= 2 || phy->connected)
+- bcm43xx_phy_inita(bcm);
+-
+- if (phy->rev >= 2) {
+- bcm43xx_phy_write(bcm, 0x0814, 0x0000);
+- bcm43xx_phy_write(bcm, 0x0815, 0x0000);
+- }
+- if (phy->rev == 2) {
+- bcm43xx_phy_write(bcm, 0x0811, 0x0000);
+- bcm43xx_phy_write(bcm, 0x0015, 0x00C0);
+- }
+- if (phy->rev > 5) {
+- bcm43xx_phy_write(bcm, 0x0811, 0x0400);
+- bcm43xx_phy_write(bcm, 0x0015, 0x00C0);
+- }
+- if (phy->rev >= 2 && phy->connected) {
+- tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF;
+- if (tmp ==3 || tmp == 5) {
+- bcm43xx_phy_write(bcm, 0x04C2, 0x1816);
+- bcm43xx_phy_write(bcm, 0x04C3, 0x8006);
+- if (tmp == 5) {
+- bcm43xx_phy_write(bcm, 0x04CC,
+- (bcm43xx_phy_read(bcm, 0x04CC)
+- & 0x00FF) | 0x1F00);
+- }
+- }
+- bcm43xx_phy_write(bcm, 0x047E, 0x0078);
+- }
+- if (radio->revision == 8) {
+- bcm43xx_phy_write(bcm, 0x0801, bcm43xx_phy_read(bcm, 0x0801) | 0x0080);
+- bcm43xx_phy_write(bcm, 0x043E, bcm43xx_phy_read(bcm, 0x043E) | 0x0004);
+- }
+- if (phy->rev >= 2 && phy->connected)
+- bcm43xx_calc_loopback_gain(bcm);
+- if (radio->revision != 8) {
+- if (radio->initval == 0xFFFF)
+- radio->initval = bcm43xx_radio_init2050(bcm);
+- else
+- bcm43xx_radio_write16(bcm, 0x0078, radio->initval);
+- }
+- if (radio->txctl2 == 0xFFFF) {
+- bcm43xx_phy_lo_g_measure(bcm);
+- } else {
+- if (radio->version == 0x2050 && radio->revision == 8) {
+- bcm43xx_radio_write16(bcm, 0x0052,
+- (radio->txctl1 << 4) | radio->txctl2);
+- } else {
+- bcm43xx_radio_write16(bcm, 0x0052,
+- (bcm43xx_radio_read16(bcm, 0x0052)
+- & 0xFFF0) | radio->txctl1);
+- }
+- if (phy->rev >= 6) {
+- bcm43xx_phy_write(bcm, 0x0036,
+- (bcm43xx_phy_read(bcm, 0x0036)
+- & 0x0FFF) | (radio->txctl2 << 12));
+- }
+- if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
+- bcm43xx_phy_write(bcm, 0x002E, 0x8075);
+- else
+- bcm43xx_phy_write(bcm, 0x002E, 0x807F);
+- if (phy->rev < 2)
+- bcm43xx_phy_write(bcm, 0x002F, 0x0101);
+- else
+- bcm43xx_phy_write(bcm, 0x002F, 0x0202);
+- }
+- if (phy->connected || phy->rev >= 2) {
+- bcm43xx_phy_lo_adjust(bcm, 0);
+- bcm43xx_phy_write(bcm, 0x080F, 0x8078);
+- }
+-
+- if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) {
+- /* The specs state to update the NRSSI LT with
+- * the value 0x7FFFFFFF here. I think that is some weird
+- * compiler optimization in the original driver.
+- * Essentially, what we do here is resetting all NRSSI LT
+- * entries to -32 (see the limit_value() in nrssi_hw_update())
+- */
+- bcm43xx_nrssi_hw_update(bcm, 0xFFFF);
+- bcm43xx_calc_nrssi_threshold(bcm);
+- } else if (phy->connected || phy->rev >= 2) {
+- if (radio->nrssi[0] == -1000) {
+- assert(radio->nrssi[1] == -1000);
+- bcm43xx_calc_nrssi_slope(bcm);
+- } else {
+- assert(radio->nrssi[1] != -1000);
+- bcm43xx_calc_nrssi_threshold(bcm);
+- }
+- }
+- if (radio->revision == 8)
+- bcm43xx_phy_write(bcm, 0x0805, 0x3230);
+- bcm43xx_phy_init_pctl(bcm);
+- if (bcm->chip_id == 0x4306 && bcm->chip_package == 2) {
+- bcm43xx_phy_write(bcm, 0x0429,
+- bcm43xx_phy_read(bcm, 0x0429) & 0xBFFF);
+- bcm43xx_phy_write(bcm, 0x04C3,
+- bcm43xx_phy_read(bcm, 0x04C3) & 0x7FFF);
+- }
+-}
+-
+-static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm)
+-{
+- int i;
+- u16 ret = 0;
+- unsigned long flags;
+-
+- local_irq_save(flags);
+- for (i = 0; i < 10; i++){
+- bcm43xx_phy_write(bcm, 0x0015, 0xAFA0);
+- udelay(1);
+- bcm43xx_phy_write(bcm, 0x0015, 0xEFA0);
+- udelay(10);
+- bcm43xx_phy_write(bcm, 0x0015, 0xFFA0);
+- udelay(40);
+- ret += bcm43xx_phy_read(bcm, 0x002C);
+- }
+- local_irq_restore(flags);
+- bcm43xx_voluntary_preempt();
+-
+- return ret;
+-}
+-
+-void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- u16 regstack[12] = { 0 };
+- u16 mls;
+- u16 fval;
+- int i, j;
+-
+- regstack[0] = bcm43xx_phy_read(bcm, 0x0015);
+- regstack[1] = bcm43xx_radio_read16(bcm, 0x0052) & 0xFFF0;
+-
+- if (radio->version == 0x2053) {
+- regstack[2] = bcm43xx_phy_read(bcm, 0x000A);
+- regstack[3] = bcm43xx_phy_read(bcm, 0x002A);
+- regstack[4] = bcm43xx_phy_read(bcm, 0x0035);
+- regstack[5] = bcm43xx_phy_read(bcm, 0x0003);
+- regstack[6] = bcm43xx_phy_read(bcm, 0x0001);
+- regstack[7] = bcm43xx_phy_read(bcm, 0x0030);
+-
+- regstack[8] = bcm43xx_radio_read16(bcm, 0x0043);
+- regstack[9] = bcm43xx_radio_read16(bcm, 0x007A);
+- regstack[10] = bcm43xx_read16(bcm, 0x03EC);
+- regstack[11] = bcm43xx_radio_read16(bcm, 0x0052) & 0x00F0;
+-
+- bcm43xx_phy_write(bcm, 0x0030, 0x00FF);
+- bcm43xx_write16(bcm, 0x03EC, 0x3F3F);
+- bcm43xx_phy_write(bcm, 0x0035, regstack[4] & 0xFF7F);
+- bcm43xx_radio_write16(bcm, 0x007A, regstack[9] & 0xFFF0);
+- }
+- bcm43xx_phy_write(bcm, 0x0015, 0xB000);
+- bcm43xx_phy_write(bcm, 0x002B, 0x0004);
+-
+- if (radio->version == 0x2053) {
+- bcm43xx_phy_write(bcm, 0x002B, 0x0203);
+- bcm43xx_phy_write(bcm, 0x002A, 0x08A3);
+- }
+-
+- phy->minlowsig[0] = 0xFFFF;
+-
+- for (i = 0; i < 4; i++) {
+- bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | i);
+- bcm43xx_phy_lo_b_r15_loop(bcm);
+- }
+- for (i = 0; i < 10; i++) {
+- bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | i);
+- mls = bcm43xx_phy_lo_b_r15_loop(bcm) / 10;
+- if (mls < phy->minlowsig[0]) {
+- phy->minlowsig[0] = mls;
+- phy->minlowsigpos[0] = i;
+- }
+- }
+- bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | phy->minlowsigpos[0]);
+-
+- phy->minlowsig[1] = 0xFFFF;
+-
+- for (i = -4; i < 5; i += 2) {
+- for (j = -4; j < 5; j += 2) {
+- if (j < 0)
+- fval = (0x0100 * i) + j + 0x0100;
+- else
+- fval = (0x0100 * i) + j;
+- bcm43xx_phy_write(bcm, 0x002F, fval);
+- mls = bcm43xx_phy_lo_b_r15_loop(bcm) / 10;
+- if (mls < phy->minlowsig[1]) {
+- phy->minlowsig[1] = mls;
+- phy->minlowsigpos[1] = fval;
+- }
+- }
+- }
+- phy->minlowsigpos[1] += 0x0101;
+-
+- bcm43xx_phy_write(bcm, 0x002F, phy->minlowsigpos[1]);
+- if (radio->version == 0x2053) {
+- bcm43xx_phy_write(bcm, 0x000A, regstack[2]);
+- bcm43xx_phy_write(bcm, 0x002A, regstack[3]);
+- bcm43xx_phy_write(bcm, 0x0035, regstack[4]);
+- bcm43xx_phy_write(bcm, 0x0003, regstack[5]);
+- bcm43xx_phy_write(bcm, 0x0001, regstack[6]);
+- bcm43xx_phy_write(bcm, 0x0030, regstack[7]);
+-
+- bcm43xx_radio_write16(bcm, 0x0043, regstack[8]);
+- bcm43xx_radio_write16(bcm, 0x007A, regstack[9]);
+-
+- bcm43xx_radio_write16(bcm, 0x0052,
+- (bcm43xx_radio_read16(bcm, 0x0052) & 0x000F)
+- | regstack[11]);
+-
+- bcm43xx_write16(bcm, 0x03EC, regstack[10]);
+- }
+- bcm43xx_phy_write(bcm, 0x0015, regstack[0]);
+-}
+-
+-static inline
+-u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- u16 ret;
+- unsigned long flags;
+-
+- local_irq_save(flags);
+- if (phy->connected) {
+- bcm43xx_phy_write(bcm, 0x15, 0xE300);
+- control <<= 8;
+- bcm43xx_phy_write(bcm, 0x0812, control | 0x00B0);
+- udelay(5);
+- bcm43xx_phy_write(bcm, 0x0812, control | 0x00B2);
+- udelay(2);
+- bcm43xx_phy_write(bcm, 0x0812, control | 0x00B3);
+- udelay(4);
+- bcm43xx_phy_write(bcm, 0x0015, 0xF300);
+- udelay(8);
+- } else {
+- bcm43xx_phy_write(bcm, 0x0015, control | 0xEFA0);
+- udelay(2);
+- bcm43xx_phy_write(bcm, 0x0015, control | 0xEFE0);
+- udelay(4);
+- bcm43xx_phy_write(bcm, 0x0015, control | 0xFFE0);
+- udelay(8);
+- }
+- ret = bcm43xx_phy_read(bcm, 0x002D);
+- local_irq_restore(flags);
+- bcm43xx_voluntary_preempt();
+-
+- return ret;
+-}
+-
+-static u32 bcm43xx_phy_lo_g_singledeviation(struct bcm43xx_private *bcm, u16 control)
+-{
+- int i;
+- u32 ret = 0;
+-
+- for (i = 0; i < 8; i++)
+- ret += bcm43xx_phy_lo_g_deviation_subval(bcm, control);
+-
+- return ret;
+-}
+-
+-/* Write the LocalOscillator CONTROL */
+-static inline
+-void bcm43xx_lo_write(struct bcm43xx_private *bcm,
+- struct bcm43xx_lopair *pair)
+-{
+- u16 value;
+-
+- value = (u8)(pair->low);
+- value |= ((u8)(pair->high)) << 8;
+-
+-#ifdef CONFIG_BCM43XX_DEBUG
+- /* Sanity check. */
+- if (pair->low < -8 || pair->low > 8 ||
+- pair->high < -8 || pair->high > 8) {
+- printk(KERN_WARNING PFX
+- "WARNING: Writing invalid LOpair "
+- "(low: %d, high: %d, index: %lu)\n",
+- pair->low, pair->high,
+- (unsigned long)(pair - bcm43xx_current_phy(bcm)->_lo_pairs));
+- dump_stack();
+- }
+-#endif
+-
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, value);
+-}
+-
+-static inline
+-struct bcm43xx_lopair * bcm43xx_find_lopair(struct bcm43xx_private *bcm,
+- u16 baseband_attenuation,
+- u16 radio_attenuation,
+- u16 tx)
+-{
+- static const u8 dict[10] = { 11, 10, 11, 12, 13, 12, 13, 12, 13, 12 };
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-
+- if (baseband_attenuation > 6)
+- baseband_attenuation = 6;
+- assert(radio_attenuation < 10);
+-
+- if (tx == 3) {
+- return bcm43xx_get_lopair(phy,
+- radio_attenuation,
+- baseband_attenuation);
+- }
+- return bcm43xx_get_lopair(phy, dict[radio_attenuation], baseband_attenuation);
+-}
+-
+-static inline
+-struct bcm43xx_lopair * bcm43xx_current_lopair(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-
+- return bcm43xx_find_lopair(bcm,
+- radio->baseband_atten,
+- radio->radio_atten,
+- radio->txctl1);
+-}
+-
+-/* Adjust B/G LO */
+-void bcm43xx_phy_lo_adjust(struct bcm43xx_private *bcm, int fixed)
+-{
+- struct bcm43xx_lopair *pair;
+-
+- if (fixed) {
+- /* Use fixed values. Only for initialization. */
+- pair = bcm43xx_find_lopair(bcm, 2, 3, 0);
+- } else
+- pair = bcm43xx_current_lopair(bcm);
+- bcm43xx_lo_write(bcm, pair);
+-}
+-
+-static void bcm43xx_phy_lo_g_measure_txctl2(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- u16 txctl2 = 0, i;
+- u32 smallest, tmp;
+-
+- bcm43xx_radio_write16(bcm, 0x0052, 0x0000);
+- udelay(10);
+- smallest = bcm43xx_phy_lo_g_singledeviation(bcm, 0);
+- for (i = 0; i < 16; i++) {
+- bcm43xx_radio_write16(bcm, 0x0052, i);
+- udelay(10);
+- tmp = bcm43xx_phy_lo_g_singledeviation(bcm, 0);
+- if (tmp < smallest) {
+- smallest = tmp;
+- txctl2 = i;
+- }
+- }
+- radio->txctl2 = txctl2;
+-}
+-
+-static
+-void bcm43xx_phy_lo_g_state(struct bcm43xx_private *bcm,
+- const struct bcm43xx_lopair *in_pair,
+- struct bcm43xx_lopair *out_pair,
+- u16 r27)
+-{
+- static const struct bcm43xx_lopair transitions[8] = {
+- { .high = 1, .low = 1, },
+- { .high = 1, .low = 0, },
+- { .high = 1, .low = -1, },
+- { .high = 0, .low = -1, },
+- { .high = -1, .low = -1, },
+- { .high = -1, .low = 0, },
+- { .high = -1, .low = 1, },
+- { .high = 0, .low = 1, },
+- };
+- struct bcm43xx_lopair lowest_transition = {
+- .high = in_pair->high,
+- .low = in_pair->low,
+- };
+- struct bcm43xx_lopair tmp_pair;
+- struct bcm43xx_lopair transition;
+- int i = 12;
+- int state = 0;
+- int found_lower;
+- int j, begin, end;
+- u32 lowest_deviation;
+- u32 tmp;
+-
+- /* Note that in_pair and out_pair can point to the same pair. Be careful. */
+-
+- bcm43xx_lo_write(bcm, &lowest_transition);
+- lowest_deviation = bcm43xx_phy_lo_g_singledeviation(bcm, r27);
+- do {
+- found_lower = 0;
+- assert(state >= 0 && state <= 8);
+- if (state == 0) {
+- begin = 1;
+- end = 8;
+- } else if (state % 2 == 0) {
+- begin = state - 1;
+- end = state + 1;
+- } else {
+- begin = state - 2;
+- end = state + 2;
+- }
+- if (begin < 1)
+- begin += 8;
+- if (end > 8)
+- end -= 8;
+-
+- j = begin;
+- tmp_pair.high = lowest_transition.high;
+- tmp_pair.low = lowest_transition.low;
+- while (1) {
+- assert(j >= 1 && j <= 8);
+- transition.high = tmp_pair.high + transitions[j - 1].high;
+- transition.low = tmp_pair.low + transitions[j - 1].low;
+- if ((abs(transition.low) < 9) && (abs(transition.high) < 9)) {
+- bcm43xx_lo_write(bcm, &transition);
+- tmp = bcm43xx_phy_lo_g_singledeviation(bcm, r27);
+- if (tmp < lowest_deviation) {
+- lowest_deviation = tmp;
+- state = j;
+- found_lower = 1;
+-
+- lowest_transition.high = transition.high;
+- lowest_transition.low = transition.low;
+- }
+- }
+- if (j == end)
+- break;
+- if (j == 8)
+- j = 1;
+- else
+- j++;
+- }
+- } while (i-- && found_lower);
+-
+- out_pair->high = lowest_transition.high;
+- out_pair->low = lowest_transition.low;
+-}
+-
+-/* Set the baseband attenuation value on chip. */
+-void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm,
+- u16 baseband_attenuation)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- u16 value;
+-
+- if (phy->analog == 0) {
+- value = (bcm43xx_read16(bcm, 0x03E6) & 0xFFF0);
+- value |= (baseband_attenuation & 0x000F);
+- bcm43xx_write16(bcm, 0x03E6, value);
+- return;
+- }
+-
+- if (phy->analog > 1) {
+- value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C;
+- value |= (baseband_attenuation << 2) & 0x003C;
+- } else {
+- value = bcm43xx_phy_read(bcm, 0x0060) & ~0x0078;
+- value |= (baseband_attenuation << 3) & 0x0078;
+- }
+- bcm43xx_phy_write(bcm, 0x0060, value);
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/LocalOscillator/Measure */
+-void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
+-{
+- static const u8 pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 };
+- const int is_initializing = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZING);
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- u16 h, i, oldi = 0, j;
+- struct bcm43xx_lopair control;
+- struct bcm43xx_lopair *tmp_control;
+- u16 tmp;
+- u16 regstack[16] = { 0 };
+- u8 oldchannel;
+-
+- //XXX: What are these?
+- u8 r27 = 0, r31;
+-
+- oldchannel = radio->channel;
+- /* Setup */
+- if (phy->connected) {
+- regstack[0] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS);
+- regstack[1] = bcm43xx_phy_read(bcm, 0x0802);
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0] & 0x7FFF);
+- bcm43xx_phy_write(bcm, 0x0802, regstack[1] & 0xFFFC);
+- }
+- regstack[3] = bcm43xx_read16(bcm, 0x03E2);
+- bcm43xx_write16(bcm, 0x03E2, regstack[3] | 0x8000);
+- regstack[4] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
+- regstack[5] = bcm43xx_phy_read(bcm, 0x15);
+- regstack[6] = bcm43xx_phy_read(bcm, 0x2A);
+- regstack[7] = bcm43xx_phy_read(bcm, 0x35);
+- regstack[8] = bcm43xx_phy_read(bcm, 0x60);
+- regstack[9] = bcm43xx_radio_read16(bcm, 0x43);
+- regstack[10] = bcm43xx_radio_read16(bcm, 0x7A);
+- regstack[11] = bcm43xx_radio_read16(bcm, 0x52);
+- if (phy->connected) {
+- regstack[12] = bcm43xx_phy_read(bcm, 0x0811);
+- regstack[13] = bcm43xx_phy_read(bcm, 0x0812);
+- regstack[14] = bcm43xx_phy_read(bcm, 0x0814);
+- regstack[15] = bcm43xx_phy_read(bcm, 0x0815);
+- }
+- bcm43xx_radio_selectchannel(bcm, 6, 0);
+- if (phy->connected) {
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0] & 0x7FFF);
+- bcm43xx_phy_write(bcm, 0x0802, regstack[1] & 0xFFFC);
+- bcm43xx_dummy_transmission(bcm);
+- }
+- bcm43xx_radio_write16(bcm, 0x0043, 0x0006);
+-
+- bcm43xx_phy_set_baseband_attenuation(bcm, 2);
+-
+- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x0000);
+- bcm43xx_phy_write(bcm, 0x002E, 0x007F);
+- bcm43xx_phy_write(bcm, 0x080F, 0x0078);
+- bcm43xx_phy_write(bcm, 0x0035, regstack[7] & ~(1 << 7));
+- bcm43xx_radio_write16(bcm, 0x007A, regstack[10] & 0xFFF0);
+- bcm43xx_phy_write(bcm, 0x002B, 0x0203);
+- bcm43xx_phy_write(bcm, 0x002A, 0x08A3);
+- if (phy->connected) {
+- bcm43xx_phy_write(bcm, 0x0814, regstack[14] | 0x0003);
+- bcm43xx_phy_write(bcm, 0x0815, regstack[15] & 0xFFFC);
+- bcm43xx_phy_write(bcm, 0x0811, 0x01B3);
+- bcm43xx_phy_write(bcm, 0x0812, 0x00B2);
+- }
+- if (is_initializing)
+- bcm43xx_phy_lo_g_measure_txctl2(bcm);
+- bcm43xx_phy_write(bcm, 0x080F, 0x8078);
+-
+- /* Measure */
+- control.low = 0;
+- control.high = 0;
+- for (h = 0; h < 10; h++) {
+- /* Loop over each possible RadioAttenuation (0-9) */
+- i = pairorder[h];
+- if (is_initializing) {
+- if (i == 3) {
+- control.low = 0;
+- control.high = 0;
+- } else if (((i % 2 == 1) && (oldi % 2 == 1)) ||
+- ((i % 2 == 0) && (oldi % 2 == 0))) {
+- tmp_control = bcm43xx_get_lopair(phy, oldi, 0);
+- memcpy(&control, tmp_control, sizeof(control));
+- } else {
+- tmp_control = bcm43xx_get_lopair(phy, 3, 0);
+- memcpy(&control, tmp_control, sizeof(control));
+- }
+- }
+- /* Loop over each possible BasebandAttenuation/2 */
+- for (j = 0; j < 4; j++) {
+- if (is_initializing) {
+- tmp = i * 2 + j;
+- r27 = 0;
+- r31 = 0;
+- if (tmp > 14) {
+- r31 = 1;
+- if (tmp > 17)
+- r27 = 1;
+- if (tmp > 19)
+- r27 = 2;
+- }
+- } else {
+- tmp_control = bcm43xx_get_lopair(phy, i, j * 2);
+- if (!tmp_control->used)
+- continue;
+- memcpy(&control, tmp_control, sizeof(control));
+- r27 = 3;
+- r31 = 0;
+- }
+- bcm43xx_radio_write16(bcm, 0x43, i);
+- bcm43xx_radio_write16(bcm, 0x52, radio->txctl2);
+- udelay(10);
+- bcm43xx_voluntary_preempt();
+-
+- bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
+-
+- tmp = (regstack[10] & 0xFFF0);
+- if (r31)
+- tmp |= 0x0008;
+- bcm43xx_radio_write16(bcm, 0x007A, tmp);
+-
+- tmp_control = bcm43xx_get_lopair(phy, i, j * 2);
+- bcm43xx_phy_lo_g_state(bcm, &control, tmp_control, r27);
+- }
+- oldi = i;
+- }
+- /* Loop over each possible RadioAttenuation (10-13) */
+- for (i = 10; i < 14; i++) {
+- /* Loop over each possible BasebandAttenuation/2 */
+- for (j = 0; j < 4; j++) {
+- if (is_initializing) {
+- tmp_control = bcm43xx_get_lopair(phy, i - 9, j * 2);
+- memcpy(&control, tmp_control, sizeof(control));
+- tmp = (i - 9) * 2 + j - 5;//FIXME: This is wrong, as the following if statement can never trigger.
+- r27 = 0;
+- r31 = 0;
+- if (tmp > 14) {
+- r31 = 1;
+- if (tmp > 17)
+- r27 = 1;
+- if (tmp > 19)
+- r27 = 2;
+- }
+- } else {
+- tmp_control = bcm43xx_get_lopair(phy, i - 9, j * 2);
+- if (!tmp_control->used)
+- continue;
+- memcpy(&control, tmp_control, sizeof(control));
+- r27 = 3;
+- r31 = 0;
+- }
+- bcm43xx_radio_write16(bcm, 0x43, i - 9);
+- bcm43xx_radio_write16(bcm, 0x52,
+- radio->txctl2
+- | (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above?
+- udelay(10);
+- bcm43xx_voluntary_preempt();
+-
+- bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
+-
+- tmp = (regstack[10] & 0xFFF0);
+- if (r31)
+- tmp |= 0x0008;
+- bcm43xx_radio_write16(bcm, 0x7A, tmp);
+-
+- tmp_control = bcm43xx_get_lopair(phy, i, j * 2);
+- bcm43xx_phy_lo_g_state(bcm, &control, tmp_control, r27);
+- }
+- }
+-
+- /* Restoration */
+- if (phy->connected) {
+- bcm43xx_phy_write(bcm, 0x0015, 0xE300);
+- bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA0);
+- udelay(5);
+- bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA2);
+- udelay(2);
+- bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA3);
+- bcm43xx_voluntary_preempt();
+- } else
+- bcm43xx_phy_write(bcm, 0x0015, r27 | 0xEFA0);
+- bcm43xx_phy_lo_adjust(bcm, is_initializing);
+- bcm43xx_phy_write(bcm, 0x002E, 0x807F);
+- if (phy->connected)
+- bcm43xx_phy_write(bcm, 0x002F, 0x0202);
+- else
+- bcm43xx_phy_write(bcm, 0x002F, 0x0101);
+- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, regstack[4]);
+- bcm43xx_phy_write(bcm, 0x0015, regstack[5]);
+- bcm43xx_phy_write(bcm, 0x002A, regstack[6]);
+- bcm43xx_phy_write(bcm, 0x0035, regstack[7]);
+- bcm43xx_phy_write(bcm, 0x0060, regstack[8]);
+- bcm43xx_radio_write16(bcm, 0x0043, regstack[9]);
+- bcm43xx_radio_write16(bcm, 0x007A, regstack[10]);
+- regstack[11] &= 0x00F0;
+- regstack[11] |= (bcm43xx_radio_read16(bcm, 0x52) & 0x000F);
+- bcm43xx_radio_write16(bcm, 0x52, regstack[11]);
+- bcm43xx_write16(bcm, 0x03E2, regstack[3]);
+- if (phy->connected) {
+- bcm43xx_phy_write(bcm, 0x0811, regstack[12]);
+- bcm43xx_phy_write(bcm, 0x0812, regstack[13]);
+- bcm43xx_phy_write(bcm, 0x0814, regstack[14]);
+- bcm43xx_phy_write(bcm, 0x0815, regstack[15]);
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0]);
+- bcm43xx_phy_write(bcm, 0x0802, regstack[1]);
+- }
+- bcm43xx_radio_selectchannel(bcm, oldchannel, 1);
+-
+-#ifdef CONFIG_BCM43XX_DEBUG
+- {
+- /* Sanity check for all lopairs. */
+- for (i = 0; i < BCM43xx_LO_COUNT; i++) {
+- tmp_control = phy->_lo_pairs + i;
+- if (tmp_control->low < -8 || tmp_control->low > 8 ||
+- tmp_control->high < -8 || tmp_control->high > 8) {
+- printk(KERN_WARNING PFX
+- "WARNING: Invalid LOpair (low: %d, high: %d, index: %d)\n",
+- tmp_control->low, tmp_control->high, i);
+- }
+- }
+- }
+-#endif /* CONFIG_BCM43XX_DEBUG */
+-}
+-
+-static
+-void bcm43xx_phy_lo_mark_current_used(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_lopair *pair;
+-
+- pair = bcm43xx_current_lopair(bcm);
+- pair->used = 1;
+-}
+-
+-void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_lopair *pair;
+- int i;
+-
+- for (i = 0; i < BCM43xx_LO_COUNT; i++) {
+- pair = phy->_lo_pairs + i;
+- pair->used = 0;
+- }
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/EstimatePowerOut
+- * This function converts a TSSI value to dBm in Q5.2
+- */
+-static s8 bcm43xx_phy_estimate_power_out(struct bcm43xx_private *bcm, s8 tssi)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- s8 dbm = 0;
+- s32 tmp;
+-
+- tmp = phy->idle_tssi;
+- tmp += tssi;
+- tmp -= phy->savedpctlreg;
+-
+- switch (phy->type) {
+- case BCM43xx_PHYTYPE_A:
+- tmp += 0x80;
+- tmp = limit_value(tmp, 0x00, 0xFF);
+- dbm = phy->tssi2dbm[tmp];
+- TODO(); //TODO: There's a FIXME on the specs
+- break;
+- case BCM43xx_PHYTYPE_B:
+- case BCM43xx_PHYTYPE_G:
+- tmp = limit_value(tmp, 0x00, 0x3F);
+- dbm = phy->tssi2dbm[tmp];
+- break;
+- default:
+- assert(0);
+- }
+-
+- return dbm;
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower */
+-void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-
+- if (phy->savedpctlreg == 0xFFFF)
+- return;
+- if ((bcm->board_type == 0x0416) &&
+- (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM))
+- return;
+-
+- switch (phy->type) {
+- case BCM43xx_PHYTYPE_A: {
+-
+- TODO(); //TODO: Nothing for A PHYs yet :-/
+-
+- break;
+- }
+- case BCM43xx_PHYTYPE_B:
+- case BCM43xx_PHYTYPE_G: {
+- u16 tmp;
+- u16 txpower;
+- s8 v0, v1, v2, v3;
+- s8 average;
+- u8 max_pwr;
+- s16 desired_pwr, estimated_pwr, pwr_adjust;
+- s16 radio_att_delta, baseband_att_delta;
+- s16 radio_attenuation, baseband_attenuation;
+- unsigned long phylock_flags;
+-
+- tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0058);
+- v0 = (s8)(tmp & 0x00FF);
+- v1 = (s8)((tmp & 0xFF00) >> 8);
+- tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x005A);
+- v2 = (s8)(tmp & 0x00FF);
+- v3 = (s8)((tmp & 0xFF00) >> 8);
+- tmp = 0;
+-
+- if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F) {
+- tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0070);
+- v0 = (s8)(tmp & 0x00FF);
+- v1 = (s8)((tmp & 0xFF00) >> 8);
+- tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0072);
+- v2 = (s8)(tmp & 0x00FF);
+- v3 = (s8)((tmp & 0xFF00) >> 8);
+- if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F)
+- return;
+- v0 = (v0 + 0x20) & 0x3F;
+- v1 = (v1 + 0x20) & 0x3F;
+- v2 = (v2 + 0x20) & 0x3F;
+- v3 = (v3 + 0x20) & 0x3F;
+- tmp = 1;
+- }
+- bcm43xx_radio_clear_tssi(bcm);
+-
+- average = (v0 + v1 + v2 + v3 + 2) / 4;
+-
+- if (tmp && (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x005E) & 0x8))
+- average -= 13;
+-
+- estimated_pwr = bcm43xx_phy_estimate_power_out(bcm, average);
+-
+- max_pwr = bcm->sprom.maxpower_bgphy;
+-
+- if ((bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) &&
+- (phy->type == BCM43xx_PHYTYPE_G))
+- max_pwr -= 0x3;
+-
+- /*TODO:
+- max_pwr = min(REG - bcm->sprom.antennagain_bgphy - 0x6, max_pwr)
+- where REG is the max power as per the regulatory domain
+- */
+-
+- desired_pwr = limit_value(radio->txpower_desired, 0, max_pwr);
+- /* Check if we need to adjust the current power. */
+- pwr_adjust = desired_pwr - estimated_pwr;
+- radio_att_delta = -(pwr_adjust + 7) >> 3;
+- baseband_att_delta = -(pwr_adjust >> 1) - (4 * radio_att_delta);
+- if ((radio_att_delta == 0) && (baseband_att_delta == 0)) {
+- bcm43xx_phy_lo_mark_current_used(bcm);
+- return;
+- }
+-
+- /* Calculate the new attenuation values. */
+- baseband_attenuation = radio->baseband_atten;
+- baseband_attenuation += baseband_att_delta;
+- radio_attenuation = radio->radio_atten;
+- radio_attenuation += radio_att_delta;
+-
+- /* Get baseband and radio attenuation values into their permitted ranges.
+- * baseband 0-11, radio 0-9.
+- * Radio attenuation affects power level 4 times as much as baseband.
+- */
+- if (radio_attenuation < 0) {
+- baseband_attenuation -= (4 * -radio_attenuation);
+- radio_attenuation = 0;
+- } else if (radio_attenuation > 9) {
+- baseband_attenuation += (4 * (radio_attenuation - 9));
+- radio_attenuation = 9;
+- } else {
+- while (baseband_attenuation < 0 && radio_attenuation > 0) {
+- baseband_attenuation += 4;
+- radio_attenuation--;
+- }
+- while (baseband_attenuation > 11 && radio_attenuation < 9) {
+- baseband_attenuation -= 4;
+- radio_attenuation++;
+- }
+- }
+- baseband_attenuation = limit_value(baseband_attenuation, 0, 11);
+-
+- txpower = radio->txctl1;
+- if ((radio->version == 0x2050) && (radio->revision == 2)) {
+- if (radio_attenuation <= 1) {
+- if (txpower == 0) {
+- txpower = 3;
+- radio_attenuation += 2;
+- baseband_attenuation += 2;
+- } else if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) {
+- baseband_attenuation += 4 * (radio_attenuation - 2);
+- radio_attenuation = 2;
+- }
+- } else if (radio_attenuation > 4 && txpower != 0) {
+- txpower = 0;
+- if (baseband_attenuation < 3) {
+- radio_attenuation -= 3;
+- baseband_attenuation += 2;
+- } else {
+- radio_attenuation -= 2;
+- baseband_attenuation -= 2;
+- }
+- }
+- }
+- radio->txctl1 = txpower;
+- baseband_attenuation = limit_value(baseband_attenuation, 0, 11);
+- radio_attenuation = limit_value(radio_attenuation, 0, 9);
+-
+- bcm43xx_phy_lock(bcm, phylock_flags);
+- bcm43xx_radio_lock(bcm);
+- bcm43xx_radio_set_txpower_bg(bcm, baseband_attenuation,
+- radio_attenuation, txpower);
+- bcm43xx_phy_lo_mark_current_used(bcm);
+- bcm43xx_radio_unlock(bcm);
+- bcm43xx_phy_unlock(bcm, phylock_flags);
+- break;
+- }
+- default:
+- assert(0);
+- }
+-}
+-
+-static inline
+-s32 bcm43xx_tssi2dbm_ad(s32 num, s32 den)
+-{
+- if (num < 0)
+- return num/den;
+- else
+- return (num+den/2)/den;
+-}
+-
+-static inline
+-s8 bcm43xx_tssi2dbm_entry(s8 entry [], u8 index, s16 pab0, s16 pab1, s16 pab2)
+-{
+- s32 m1, m2, f = 256, q, delta;
+- s8 i = 0;
+-
+- m1 = bcm43xx_tssi2dbm_ad(16 * pab0 + index * pab1, 32);
+- m2 = max(bcm43xx_tssi2dbm_ad(32768 + index * pab2, 256), 1);
+- do {
+- if (i > 15)
+- return -EINVAL;
+- q = bcm43xx_tssi2dbm_ad(f * 4096 -
+- bcm43xx_tssi2dbm_ad(m2 * f, 16) * f, 2048);
+- delta = abs(q - f);
+- f = q;
+- i++;
+- } while (delta >= 2);
+- entry[index] = limit_value(bcm43xx_tssi2dbm_ad(m1 * f, 8192), -127, 128);
+- return 0;
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table */
+-int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- s16 pab0, pab1, pab2;
+- u8 idx;
+- s8 *dyn_tssi2dbm;
+-
+- if (phy->type == BCM43xx_PHYTYPE_A) {
+- pab0 = (s16)(bcm->sprom.pa1b0);
+- pab1 = (s16)(bcm->sprom.pa1b1);
+- pab2 = (s16)(bcm->sprom.pa1b2);
+- } else {
+- pab0 = (s16)(bcm->sprom.pa0b0);
+- pab1 = (s16)(bcm->sprom.pa0b1);
+- pab2 = (s16)(bcm->sprom.pa0b2);
+- }
+-
+- if ((bcm->chip_id == 0x4301) && (radio->version != 0x2050)) {
+- phy->idle_tssi = 0x34;
+- phy->tssi2dbm = bcm43xx_tssi2dbm_b_table;
+- return 0;
+- }
+-
+- if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
+- pab0 != -1 && pab1 != -1 && pab2 != -1) {
+- /* The pabX values are set in SPROM. Use them. */
+- if (phy->type == BCM43xx_PHYTYPE_A) {
+- if ((s8)bcm->sprom.idle_tssi_tgt_aphy != 0 &&
+- (s8)bcm->sprom.idle_tssi_tgt_aphy != -1)
+- phy->idle_tssi = (s8)(bcm->sprom.idle_tssi_tgt_aphy);
+- else
+- phy->idle_tssi = 62;
+- } else {
+- if ((s8)bcm->sprom.idle_tssi_tgt_bgphy != 0 &&
+- (s8)bcm->sprom.idle_tssi_tgt_bgphy != -1)
+- phy->idle_tssi = (s8)(bcm->sprom.idle_tssi_tgt_bgphy);
+- else
+- phy->idle_tssi = 62;
+- }
+- dyn_tssi2dbm = kmalloc(64, GFP_KERNEL);
+- if (dyn_tssi2dbm == NULL) {
+- printk(KERN_ERR PFX "Could not allocate memory "
+- "for tssi2dbm table\n");
+- return -ENOMEM;
+- }
+- for (idx = 0; idx < 64; idx++)
+- if (bcm43xx_tssi2dbm_entry(dyn_tssi2dbm, idx, pab0, pab1, pab2)) {
+- phy->tssi2dbm = NULL;
+- printk(KERN_ERR PFX "Could not generate "
+- "tssi2dBm table\n");
+- kfree(dyn_tssi2dbm);
+- return -ENODEV;
+- }
+- phy->tssi2dbm = dyn_tssi2dbm;
+- phy->dyn_tssi_tbl = 1;
+- } else {
+- /* pabX values not set in SPROM. */
+- switch (phy->type) {
+- case BCM43xx_PHYTYPE_A:
+- /* APHY needs a generated table. */
+- phy->tssi2dbm = NULL;
+- printk(KERN_ERR PFX "Could not generate tssi2dBm "
+- "table (wrong SPROM info)!\n");
+- return -ENODEV;
+- case BCM43xx_PHYTYPE_B:
+- phy->idle_tssi = 0x34;
+- phy->tssi2dbm = bcm43xx_tssi2dbm_b_table;
+- break;
+- case BCM43xx_PHYTYPE_G:
+- phy->idle_tssi = 0x34;
+- phy->tssi2dbm = bcm43xx_tssi2dbm_g_table;
+- break;
+- }
+- }
+-
+- return 0;
+-}
+-
+-int bcm43xx_phy_init(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- int err = -ENODEV;
+-
+- switch (phy->type) {
+- case BCM43xx_PHYTYPE_A:
+- if (phy->rev == 2 || phy->rev == 3) {
+- bcm43xx_phy_inita(bcm);
+- err = 0;
+- }
+- break;
+- case BCM43xx_PHYTYPE_B:
+- switch (phy->rev) {
+- case 2:
+- bcm43xx_phy_initb2(bcm);
+- err = 0;
+- break;
+- case 4:
+- bcm43xx_phy_initb4(bcm);
+- err = 0;
+- break;
+- case 5:
+- bcm43xx_phy_initb5(bcm);
+- err = 0;
+- break;
+- case 6:
+- bcm43xx_phy_initb6(bcm);
+- err = 0;
+- break;
+- }
+- break;
+- case BCM43xx_PHYTYPE_G:
+- bcm43xx_phy_initg(bcm);
+- err = 0;
+- break;
+- }
+- if (err)
+- printk(KERN_WARNING PFX "Unknown PHYTYPE found!\n");
+-
+- return err;
+-}
+-
+-void bcm43xx_phy_set_antenna_diversity(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- u16 antennadiv;
+- u16 offset;
+- u16 value;
+- u32 ucodeflags;
+-
+- antennadiv = phy->antenna_diversity;
+-
+- if (antennadiv == 0xFFFF)
+- antennadiv = 3;
+- assert(antennadiv <= 3);
+-
+- ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODEFLAGS_OFFSET);
+- bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODEFLAGS_OFFSET,
+- ucodeflags & ~BCM43xx_UCODEFLAG_AUTODIV);
+-
+- switch (phy->type) {
+- case BCM43xx_PHYTYPE_A:
+- case BCM43xx_PHYTYPE_G:
+- if (phy->type == BCM43xx_PHYTYPE_A)
+- offset = 0x0000;
+- else
+- offset = 0x0400;
+-
+- if (antennadiv == 2)
+- value = (3/*automatic*/ << 7);
+- else
+- value = (antennadiv << 7);
+- bcm43xx_phy_write(bcm, offset + 1,
+- (bcm43xx_phy_read(bcm, offset + 1)
+- & 0x7E7F) | value);
+-
+- if (antennadiv >= 2) {
+- if (antennadiv == 2)
+- value = (antennadiv << 7);
+- else
+- value = (0/*force0*/ << 7);
+- bcm43xx_phy_write(bcm, offset + 0x2B,
+- (bcm43xx_phy_read(bcm, offset + 0x2B)
+- & 0xFEFF) | value);
+- }
+-
+- if (phy->type == BCM43xx_PHYTYPE_G) {
+- if (antennadiv >= 2)
+- bcm43xx_phy_write(bcm, 0x048C,
+- bcm43xx_phy_read(bcm, 0x048C)
+- | 0x2000);
+- else
+- bcm43xx_phy_write(bcm, 0x048C,
+- bcm43xx_phy_read(bcm, 0x048C)
+- & ~0x2000);
+- if (phy->rev >= 2) {
+- bcm43xx_phy_write(bcm, 0x0461,
+- bcm43xx_phy_read(bcm, 0x0461)
+- | 0x0010);
+- bcm43xx_phy_write(bcm, 0x04AD,
+- (bcm43xx_phy_read(bcm, 0x04AD)
+- & 0x00FF) | 0x0015);
+- if (phy->rev == 2)
+- bcm43xx_phy_write(bcm, 0x0427, 0x0008);
+- else
+- bcm43xx_phy_write(bcm, 0x0427,
+- (bcm43xx_phy_read(bcm, 0x0427)
+- & 0x00FF) | 0x0008);
+- }
+- else if (phy->rev >= 6)
+- bcm43xx_phy_write(bcm, 0x049B, 0x00DC);
+- } else {
+- if (phy->rev < 3)
+- bcm43xx_phy_write(bcm, 0x002B,
+- (bcm43xx_phy_read(bcm, 0x002B)
+- & 0x00FF) | 0x0024);
+- else {
+- bcm43xx_phy_write(bcm, 0x0061,
+- bcm43xx_phy_read(bcm, 0x0061)
+- | 0x0010);
+- if (phy->rev == 3) {
+- bcm43xx_phy_write(bcm, 0x0093, 0x001D);
+- bcm43xx_phy_write(bcm, 0x0027, 0x0008);
+- } else {
+- bcm43xx_phy_write(bcm, 0x0093, 0x003A);
+- bcm43xx_phy_write(bcm, 0x0027,
+- (bcm43xx_phy_read(bcm, 0x0027)
+- & 0x00FF) | 0x0008);
+- }
+- }
+- }
+- break;
+- case BCM43xx_PHYTYPE_B:
+- if (bcm->current_core->rev == 2)
+- value = (3/*automatic*/ << 7);
+- else
+- value = (antennadiv << 7);
+- bcm43xx_phy_write(bcm, 0x03E2,
+- (bcm43xx_phy_read(bcm, 0x03E2)
+- & 0xFE7F) | value);
+- break;
+- default:
+- assert(0);
+- }
+-
+- if (antennadiv >= 2) {
+- ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODEFLAGS_OFFSET);
+- bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODEFLAGS_OFFSET,
+- ucodeflags | BCM43xx_UCODEFLAG_AUTODIV);
+- }
+-
+- phy->antenna_diversity = antennadiv;
+-}
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.h b/drivers/net/wireless/bcm43xx/bcm43xx_phy.h
+deleted file mode 100644
+index 7311836..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.h
++++ /dev/null
+@@ -1,78 +0,0 @@
+-/*
+-
+- Broadcom BCM43xx wireless driver
+-
+- Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+- Stefano Brivio <st3 at riseup.net>
+- Michael Buesch <mbuesch at freenet.de>
+- Danny van Dyk <kugelfang at gentoo.org>
+- Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+- Some parts of the code in this file are derived from the ipw2200
+- driver Copyright(c) 2003 - 2004 Intel Corporation.
+-
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; 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; see the file COPYING. If not, write to
+- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+- Boston, MA 02110-1301, USA.
+-
+-*/
+-
+-#ifndef BCM43xx_PHY_H_
+-#define BCM43xx_PHY_H_
+-
+-#include <linux/types.h>
+-
+-struct bcm43xx_private;
+-
+-void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm);
+-#define bcm43xx_phy_lock(bcm, flags) \
+- do { \
+- local_irq_save(flags); \
+- bcm43xx_raw_phy_lock(bcm); \
+- } while (0)
+-void bcm43xx_raw_phy_unlock(struct bcm43xx_private *bcm);
+-#define bcm43xx_phy_unlock(bcm, flags) \
+- do { \
+- bcm43xx_raw_phy_unlock(bcm); \
+- local_irq_restore(flags); \
+- } while (0)
+-
+-/* Card uses the loopback gain stuff */
+-#define has_loopback_gain(phy) \
+- (((phy)->rev > 1) || ((phy)->connected))
+-
+-u16 bcm43xx_phy_read(struct bcm43xx_private *bcm, u16 offset);
+-void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val);
+-
+-int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm);
+-int bcm43xx_phy_init(struct bcm43xx_private *bcm);
+-
+-void bcm43xx_phy_set_antenna_diversity(struct bcm43xx_private *bcm);
+-void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm);
+-int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect);
+-
+-void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm);
+-void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm);
+-void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm);
+-
+-/* Adjust the LocalOscillator to the saved values.
+- * "fixed" is only set to 1 once in initialization. Set to 0 otherwise.
+- */
+-void bcm43xx_phy_lo_adjust(struct bcm43xx_private *bcm, int fixed);
+-void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm);
+-
+-void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm,
+- u16 baseband_attenuation);
+-
+-#endif /* BCM43xx_PHY_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
+deleted file mode 100644
+index 76ab109..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
++++ /dev/null
+@@ -1,674 +0,0 @@
+-/*
+-
+- Broadcom BCM43xx wireless driver
+-
+- PIO Transmission
+-
+- Copyright (c) 2005 Michael Buesch <mbuesch at freenet.de>
+-
+- 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; see the file COPYING. If not, write to
+- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+- Boston, MA 02110-1301, USA.
+-
+-*/
+-
+-#include "bcm43xx.h"
+-#include "bcm43xx_pio.h"
+-#include "bcm43xx_main.h"
+-#include "bcm43xx_xmit.h"
+-#include "bcm43xx_power.h"
+-
+-#include <linux/delay.h>
+-
+-
+-static void tx_start(struct bcm43xx_pioqueue *queue)
+-{
+- bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+- BCM43xx_PIO_TXCTL_INIT);
+-}
+-
+-static void tx_octet(struct bcm43xx_pioqueue *queue,
+- u8 octet)
+-{
+- if (queue->need_workarounds) {
+- bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
+- octet);
+- bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+- BCM43xx_PIO_TXCTL_WRITELO);
+- } else {
+- bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+- BCM43xx_PIO_TXCTL_WRITELO);
+- bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
+- octet);
+- }
+-}
+-
+-static u16 tx_get_next_word(struct bcm43xx_txhdr *txhdr,
+- const u8 *packet,
+- unsigned int *pos)
+-{
+- const u8 *source;
+- unsigned int i = *pos;
+- u16 ret;
+-
+- if (i < sizeof(*txhdr)) {
+- source = (const u8 *)txhdr;
+- } else {
+- source = packet;
+- i -= sizeof(*txhdr);
+- }
+- ret = le16_to_cpu( *((__le16 *)(source + i)) );
+- *pos += 2;
+-
+- return ret;
+-}
+-
+-static void tx_data(struct bcm43xx_pioqueue *queue,
+- struct bcm43xx_txhdr *txhdr,
+- const u8 *packet,
+- unsigned int octets)
+-{
+- u16 data;
+- unsigned int i = 0;
+-
+- if (queue->need_workarounds) {
+- data = tx_get_next_word(txhdr, packet, &i);
+- bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data);
+- }
+- bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+- BCM43xx_PIO_TXCTL_WRITELO |
+- BCM43xx_PIO_TXCTL_WRITEHI);
+- while (i < octets - 1) {
+- data = tx_get_next_word(txhdr, packet, &i);
+- bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data);
+- }
+- if (octets % 2)
+- tx_octet(queue, packet[octets - sizeof(*txhdr) - 1]);
+-}
+-
+-static void tx_complete(struct bcm43xx_pioqueue *queue,
+- struct sk_buff *skb)
+-{
+- if (queue->need_workarounds) {
+- bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
+- skb->data[skb->len - 1]);
+- bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+- BCM43xx_PIO_TXCTL_WRITELO |
+- BCM43xx_PIO_TXCTL_COMPLETE);
+- } else {
+- bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+- BCM43xx_PIO_TXCTL_COMPLETE);
+- }
+-}
+-
+-static u16 generate_cookie(struct bcm43xx_pioqueue *queue,
+- struct bcm43xx_pio_txpacket *packet)
+-{
+- u16 cookie = 0x0000;
+- int packetindex;
+-
+- /* We use the upper 4 bits for the PIO
+- * controller ID and the lower 12 bits
+- * for the packet index (in the cache).
+- */
+- switch (queue->mmio_base) {
+- case BCM43xx_MMIO_PIO1_BASE:
+- break;
+- case BCM43xx_MMIO_PIO2_BASE:
+- cookie = 0x1000;
+- break;
+- case BCM43xx_MMIO_PIO3_BASE:
+- cookie = 0x2000;
+- break;
+- case BCM43xx_MMIO_PIO4_BASE:
+- cookie = 0x3000;
+- break;
+- default:
+- assert(0);
+- }
+- packetindex = pio_txpacket_getindex(packet);
+- assert(((u16)packetindex & 0xF000) == 0x0000);
+- cookie |= (u16)packetindex;
+-
+- return cookie;
+-}
+-
+-static
+-struct bcm43xx_pioqueue * parse_cookie(struct bcm43xx_private *bcm,
+- u16 cookie,
+- struct bcm43xx_pio_txpacket **packet)
+-{
+- struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm);
+- struct bcm43xx_pioqueue *queue = NULL;
+- int packetindex;
+-
+- switch (cookie & 0xF000) {
+- case 0x0000:
+- queue = pio->queue0;
+- break;
+- case 0x1000:
+- queue = pio->queue1;
+- break;
+- case 0x2000:
+- queue = pio->queue2;
+- break;
+- case 0x3000:
+- queue = pio->queue3;
+- break;
+- default:
+- assert(0);
+- }
+- packetindex = (cookie & 0x0FFF);
+- assert(packetindex >= 0 && packetindex < BCM43xx_PIO_MAXTXPACKETS);
+- *packet = &(queue->tx_packets_cache[packetindex]);
+-
+- return queue;
+-}
+-
+-static void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue,
+- struct sk_buff *skb,
+- struct bcm43xx_pio_txpacket *packet)
+-{
+- struct bcm43xx_txhdr txhdr;
+- unsigned int octets;
+-
+- assert(skb_shinfo(skb)->nr_frags == 0);
+- bcm43xx_generate_txhdr(queue->bcm,
+- &txhdr, skb->data, skb->len,
+- (packet->xmitted_frags == 0),
+- generate_cookie(queue, packet));
+-
+- tx_start(queue);
+- octets = skb->len + sizeof(txhdr);
+- if (queue->need_workarounds)
+- octets--;
+- tx_data(queue, &txhdr, (u8 *)skb->data, octets);
+- tx_complete(queue, skb);
+-}
+-
+-static void free_txpacket(struct bcm43xx_pio_txpacket *packet,
+- int irq_context)
+-{
+- struct bcm43xx_pioqueue *queue = packet->queue;
+-
+- ieee80211_txb_free(packet->txb);
+- list_move(&packet->list, &queue->txfree);
+- queue->nr_txfree++;
+-
+- assert(queue->tx_devq_used >= packet->xmitted_octets);
+- assert(queue->tx_devq_packets >= packet->xmitted_frags);
+- queue->tx_devq_used -= packet->xmitted_octets;
+- queue->tx_devq_packets -= packet->xmitted_frags;
+-}
+-
+-static int pio_tx_packet(struct bcm43xx_pio_txpacket *packet)
+-{
+- struct bcm43xx_pioqueue *queue = packet->queue;
+- struct ieee80211_txb *txb = packet->txb;
+- struct sk_buff *skb;
+- u16 octets;
+- int i;
+-
+- for (i = packet->xmitted_frags; i < txb->nr_frags; i++) {
+- skb = txb->fragments[i];
+-
+- octets = (u16)skb->len + sizeof(struct bcm43xx_txhdr);
+- assert(queue->tx_devq_size >= octets);
+- assert(queue->tx_devq_packets <= BCM43xx_PIO_MAXTXDEVQPACKETS);
+- assert(queue->tx_devq_used <= queue->tx_devq_size);
+- /* Check if there is sufficient free space on the device
+- * TX queue. If not, return and let the TX tasklet
+- * retry later.
+- */
+- if (queue->tx_devq_packets == BCM43xx_PIO_MAXTXDEVQPACKETS)
+- return -EBUSY;
+- if (queue->tx_devq_used + octets > queue->tx_devq_size)
+- return -EBUSY;
+- /* Now poke the device. */
+- pio_tx_write_fragment(queue, skb, packet);
+-
+- /* Account for the packet size.
+- * (We must not overflow the device TX queue)
+- */
+- queue->tx_devq_packets++;
+- queue->tx_devq_used += octets;
+-
+- assert(packet->xmitted_frags < packet->txb->nr_frags);
+- packet->xmitted_frags++;
+- packet->xmitted_octets += octets;
+- }
+- list_move_tail(&packet->list, &queue->txrunning);
+-
+- return 0;
+-}
+-
+-static void tx_tasklet(unsigned long d)
+-{
+- struct bcm43xx_pioqueue *queue = (struct bcm43xx_pioqueue *)d;
+- struct bcm43xx_private *bcm = queue->bcm;
+- unsigned long flags;
+- struct bcm43xx_pio_txpacket *packet, *tmp_packet;
+- int err;
+- u16 txctl;
+-
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+-
+- if (queue->tx_frozen)
+- goto out_unlock;
+- txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL);
+- if (txctl & BCM43xx_PIO_TXCTL_SUSPEND)
+- goto out_unlock;
+-
+- list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) {
+- assert(packet->xmitted_frags < packet->txb->nr_frags);
+- if (packet->xmitted_frags == 0) {
+- int i;
+- struct sk_buff *skb;
+-
+- /* Check if the device queue is big
+- * enough for every fragment. If not, drop the
+- * whole packet.
+- */
+- for (i = 0; i < packet->txb->nr_frags; i++) {
+- skb = packet->txb->fragments[i];
+- if (unlikely(skb->len > queue->tx_devq_size)) {
+- dprintkl(KERN_ERR PFX "PIO TX device queue too small. "
+- "Dropping packet.\n");
+- free_txpacket(packet, 1);
+- goto next_packet;
+- }
+- }
+- }
+- /* Try to transmit the packet.
+- * This may not completely succeed.
+- */
+- err = pio_tx_packet(packet);
+- if (err)
+- break;
+- next_packet:
+- continue;
+- }
+-out_unlock:
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+-}
+-
+-static void setup_txqueues(struct bcm43xx_pioqueue *queue)
+-{
+- struct bcm43xx_pio_txpacket *packet;
+- int i;
+-
+- queue->nr_txfree = BCM43xx_PIO_MAXTXPACKETS;
+- for (i = 0; i < BCM43xx_PIO_MAXTXPACKETS; i++) {
+- packet = &(queue->tx_packets_cache[i]);
+-
+- packet->queue = queue;
+- INIT_LIST_HEAD(&packet->list);
+-
+- list_add(&packet->list, &queue->txfree);
+- }
+-}
+-
+-static
+-struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm,
+- u16 pio_mmio_base)
+-{
+- struct bcm43xx_pioqueue *queue;
+- u32 value;
+- u16 qsize;
+-
+- queue = kzalloc(sizeof(*queue), GFP_KERNEL);
+- if (!queue)
+- goto out;
+-
+- queue->bcm = bcm;
+- queue->mmio_base = pio_mmio_base;
+- queue->need_workarounds = (bcm->current_core->rev < 3);
+-
+- INIT_LIST_HEAD(&queue->txfree);
+- INIT_LIST_HEAD(&queue->txqueue);
+- INIT_LIST_HEAD(&queue->txrunning);
+- tasklet_init(&queue->txtask, tx_tasklet,
+- (unsigned long)queue);
+-
+- value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+- value &= ~BCM43xx_SBF_XFER_REG_BYTESWAP;
+- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value);
+-
+- qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE);
+- if (qsize == 0) {
+- printk(KERN_ERR PFX "ERROR: This card does not support PIO "
+- "operation mode. Please use DMA mode "
+- "(module parameter pio=0).\n");
+- goto err_freequeue;
+- }
+- if (qsize <= BCM43xx_PIO_TXQADJUST) {
+- printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n",
+- qsize);
+- goto err_freequeue;
+- }
+- qsize -= BCM43xx_PIO_TXQADJUST;
+- queue->tx_devq_size = qsize;
+-
+- setup_txqueues(queue);
+-
+-out:
+- return queue;
+-
+-err_freequeue:
+- kfree(queue);
+- queue = NULL;
+- goto out;
+-}
+-
+-static void cancel_transfers(struct bcm43xx_pioqueue *queue)
+-{
+- struct bcm43xx_pio_txpacket *packet, *tmp_packet;
+-
+- netif_tx_disable(queue->bcm->net_dev);
+- tasklet_disable(&queue->txtask);
+-
+- list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list)
+- free_txpacket(packet, 0);
+- list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list)
+- free_txpacket(packet, 0);
+-}
+-
+-static void bcm43xx_destroy_pioqueue(struct bcm43xx_pioqueue *queue)
+-{
+- if (!queue)
+- return;
+-
+- cancel_transfers(queue);
+- kfree(queue);
+-}
+-
+-void bcm43xx_pio_free(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_pio *pio;
+-
+- if (!bcm43xx_using_pio(bcm))
+- return;
+- pio = bcm43xx_current_pio(bcm);
+-
+- bcm43xx_destroy_pioqueue(pio->queue3);
+- pio->queue3 = NULL;
+- bcm43xx_destroy_pioqueue(pio->queue2);
+- pio->queue2 = NULL;
+- bcm43xx_destroy_pioqueue(pio->queue1);
+- pio->queue1 = NULL;
+- bcm43xx_destroy_pioqueue(pio->queue0);
+- pio->queue0 = NULL;
+-}
+-
+-int bcm43xx_pio_init(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm);
+- struct bcm43xx_pioqueue *queue;
+- int err = -ENOMEM;
+-
+- queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO1_BASE);
+- if (!queue)
+- goto out;
+- pio->queue0 = queue;
+-
+- queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO2_BASE);
+- if (!queue)
+- goto err_destroy0;
+- pio->queue1 = queue;
+-
+- queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO3_BASE);
+- if (!queue)
+- goto err_destroy1;
+- pio->queue2 = queue;
+-
+- queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO4_BASE);
+- if (!queue)
+- goto err_destroy2;
+- pio->queue3 = queue;
+-
+- if (bcm->current_core->rev < 3)
+- bcm->irq_savedstate |= BCM43xx_IRQ_PIO_WORKAROUND;
+-
+- dprintk(KERN_INFO PFX "PIO initialized\n");
+- err = 0;
+-out:
+- return err;
+-
+-err_destroy2:
+- bcm43xx_destroy_pioqueue(pio->queue2);
+- pio->queue2 = NULL;
+-err_destroy1:
+- bcm43xx_destroy_pioqueue(pio->queue1);
+- pio->queue1 = NULL;
+-err_destroy0:
+- bcm43xx_destroy_pioqueue(pio->queue0);
+- pio->queue0 = NULL;
+- goto out;
+-}
+-
+-int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
+- struct ieee80211_txb *txb)
+-{
+- struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1;
+- struct bcm43xx_pio_txpacket *packet;
+-
+- assert(!queue->tx_suspended);
+- assert(!list_empty(&queue->txfree));
+-
+- packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list);
+- packet->txb = txb;
+- packet->xmitted_frags = 0;
+- packet->xmitted_octets = 0;
+- list_move_tail(&packet->list, &queue->txqueue);
+- queue->nr_txfree--;
+- assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS);
+-
+- /* Suspend TX, if we are out of packets in the "free" queue. */
+- if (list_empty(&queue->txfree)) {
+- netif_stop_queue(queue->bcm->net_dev);
+- queue->tx_suspended = 1;
+- }
+-
+- tasklet_schedule(&queue->txtask);
+-
+- return 0;
+-}
+-
+-void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
+- struct bcm43xx_xmitstatus *status)
+-{
+- struct bcm43xx_pioqueue *queue;
+- struct bcm43xx_pio_txpacket *packet;
+-
+- queue = parse_cookie(bcm, status->cookie, &packet);
+- assert(queue);
+-
+- free_txpacket(packet, 1);
+- if (queue->tx_suspended) {
+- queue->tx_suspended = 0;
+- netif_wake_queue(queue->bcm->net_dev);
+- }
+- /* If there are packets on the txqueue, poke the tasklet
+- * to transmit them.
+- */
+- if (!list_empty(&queue->txqueue))
+- tasklet_schedule(&queue->txtask);
+-}
+-
+-static void pio_rx_error(struct bcm43xx_pioqueue *queue,
+- int clear_buffers,
+- const char *error)
+-{
+- int i;
+-
+- printkl("PIO RX error: %s\n", error);
+- bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL,
+- BCM43xx_PIO_RXCTL_READY);
+- if (clear_buffers) {
+- assert(queue->mmio_base == BCM43xx_MMIO_PIO1_BASE);
+- for (i = 0; i < 15; i++) {
+- /* Dummy read. */
+- bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
+- }
+- }
+-}
+-
+-void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
+-{
+- __le16 preamble[21] = { 0 };
+- struct bcm43xx_rxhdr *rxhdr;
+- u16 tmp, len, rxflags2;
+- int i, preamble_readwords;
+- struct sk_buff *skb;
+-
+- tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL);
+- if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE))
+- return;
+- bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL,
+- BCM43xx_PIO_RXCTL_DATAAVAILABLE);
+-
+- for (i = 0; i < 10; i++) {
+- tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL);
+- if (tmp & BCM43xx_PIO_RXCTL_READY)
+- goto data_ready;
+- udelay(10);
+- }
+- dprintkl(KERN_ERR PFX "PIO RX timed out\n");
+- return;
+-data_ready:
+-
+- len = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
+- if (unlikely(len > 0x700)) {
+- pio_rx_error(queue, 0, "len > 0x700");
+- return;
+- }
+- if (unlikely(len == 0 && queue->mmio_base != BCM43xx_MMIO_PIO4_BASE)) {
+- pio_rx_error(queue, 0, "len == 0");
+- return;
+- }
+- preamble[0] = cpu_to_le16(len);
+- if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE)
+- preamble_readwords = 14 / sizeof(u16);
+- else
+- preamble_readwords = 18 / sizeof(u16);
+- for (i = 0; i < preamble_readwords; i++) {
+- tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
+- preamble[i + 1] = cpu_to_le16(tmp);
+- }
+- rxhdr = (struct bcm43xx_rxhdr *)preamble;
+- rxflags2 = le16_to_cpu(rxhdr->flags2);
+- if (unlikely(rxflags2 & BCM43xx_RXHDR_FLAGS2_INVALIDFRAME)) {
+- pio_rx_error(queue,
+- (queue->mmio_base == BCM43xx_MMIO_PIO1_BASE),
+- "invalid frame");
+- return;
+- }
+- if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE) {
+- /* We received an xmit status. */
+- struct bcm43xx_hwxmitstatus *hw;
+- struct bcm43xx_xmitstatus stat;
+-
+- hw = (struct bcm43xx_hwxmitstatus *)(preamble + 1);
+- stat.cookie = le16_to_cpu(hw->cookie);
+- stat.flags = hw->flags;
+- stat.cnt1 = hw->cnt1;
+- stat.cnt2 = hw->cnt2;
+- stat.seq = le16_to_cpu(hw->seq);
+- stat.unknown = le16_to_cpu(hw->unknown);
+-
+- bcm43xx_debugfs_log_txstat(queue->bcm, &stat);
+- bcm43xx_pio_handle_xmitstatus(queue->bcm, &stat);
+-
+- return;
+- }
+-
+- skb = dev_alloc_skb(len);
+- if (unlikely(!skb)) {
+- pio_rx_error(queue, 1, "OOM");
+- return;
+- }
+- skb_put(skb, len);
+- for (i = 0; i < len - 1; i += 2) {
+- tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
+- *((__le16 *)(skb->data + i)) = cpu_to_le16(tmp);
+- }
+- if (len % 2) {
+- tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
+- skb->data[len - 1] = (tmp & 0x00FF);
+-/* The specs say the following is required, but
+- * it is wrong and corrupts the PLCP. If we don't do
+- * this, the PLCP seems to be correct. So ifdef it out for now.
+- */
+-#if 0
+- if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME)
+- skb->data[2] = (tmp & 0xFF00) >> 8;
+- else
+- skb->data[0] = (tmp & 0xFF00) >> 8;
+-#endif
+- }
+- skb_trim(skb, len - IEEE80211_FCS_LEN);
+- bcm43xx_rx(queue->bcm, skb, rxhdr);
+-}
+-
+-void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue)
+-{
+- bcm43xx_power_saving_ctl_bits(queue->bcm, -1, 1);
+- bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+- bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL)
+- | BCM43xx_PIO_TXCTL_SUSPEND);
+-}
+-
+-void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue)
+-{
+- bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+- bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL)
+- & ~BCM43xx_PIO_TXCTL_SUSPEND);
+- bcm43xx_power_saving_ctl_bits(queue->bcm, -1, -1);
+- if (!list_empty(&queue->txqueue))
+- tasklet_schedule(&queue->txtask);
+-}
+-
+-void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_pio *pio;
+-
+- assert(bcm43xx_using_pio(bcm));
+- pio = bcm43xx_current_pio(bcm);
+- pio->queue0->tx_frozen = 1;
+- pio->queue1->tx_frozen = 1;
+- pio->queue2->tx_frozen = 1;
+- pio->queue3->tx_frozen = 1;
+-}
+-
+-void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_pio *pio;
+-
+- assert(bcm43xx_using_pio(bcm));
+- pio = bcm43xx_current_pio(bcm);
+- pio->queue0->tx_frozen = 0;
+- pio->queue1->tx_frozen = 0;
+- pio->queue2->tx_frozen = 0;
+- pio->queue3->tx_frozen = 0;
+- if (!list_empty(&pio->queue0->txqueue))
+- tasklet_schedule(&pio->queue0->txtask);
+- if (!list_empty(&pio->queue1->txqueue))
+- tasklet_schedule(&pio->queue1->txtask);
+- if (!list_empty(&pio->queue2->txqueue))
+- tasklet_schedule(&pio->queue2->txtask);
+- if (!list_empty(&pio->queue3->txqueue))
+- tasklet_schedule(&pio->queue3->txtask);
+-}
+-
+-
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
+deleted file mode 100644
+index bc78a3c..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
++++ /dev/null
+@@ -1,163 +0,0 @@
+-#ifndef BCM43xx_PIO_H_
+-#define BCM43xx_PIO_H_
+-
+-#include "bcm43xx.h"
+-
+-#include <linux/interrupt.h>
+-#include <linux/list.h>
+-#include <linux/skbuff.h>
+-
+-
+-#define BCM43xx_PIO_TXCTL 0x00
+-#define BCM43xx_PIO_TXDATA 0x02
+-#define BCM43xx_PIO_TXQBUFSIZE 0x04
+-#define BCM43xx_PIO_RXCTL 0x08
+-#define BCM43xx_PIO_RXDATA 0x0A
+-
+-#define BCM43xx_PIO_TXCTL_WRITELO (1 << 0)
+-#define BCM43xx_PIO_TXCTL_WRITEHI (1 << 1)
+-#define BCM43xx_PIO_TXCTL_COMPLETE (1 << 2)
+-#define BCM43xx_PIO_TXCTL_INIT (1 << 3)
+-#define BCM43xx_PIO_TXCTL_SUSPEND (1 << 7)
+-
+-#define BCM43xx_PIO_RXCTL_DATAAVAILABLE (1 << 0)
+-#define BCM43xx_PIO_RXCTL_READY (1 << 1)
+-
+-/* PIO constants */
+-#define BCM43xx_PIO_MAXTXDEVQPACKETS 31
+-#define BCM43xx_PIO_TXQADJUST 80
+-
+-/* PIO tuning knobs */
+-#define BCM43xx_PIO_MAXTXPACKETS 256
+-
+-
+-
+-#ifdef CONFIG_BCM43XX_PIO
+-
+-
+-struct bcm43xx_pioqueue;
+-struct bcm43xx_xmitstatus;
+-
+-struct bcm43xx_pio_txpacket {
+- struct bcm43xx_pioqueue *queue;
+- struct ieee80211_txb *txb;
+- struct list_head list;
+-
+- u8 xmitted_frags;
+- u16 xmitted_octets;
+-};
+-
+-#define pio_txpacket_getindex(packet) ((int)((packet) - (packet)->queue->tx_packets_cache))
+-
+-struct bcm43xx_pioqueue {
+- struct bcm43xx_private *bcm;
+- u16 mmio_base;
+-
+- u8 tx_suspended:1,
+- tx_frozen:1,
+- need_workarounds:1; /* Workarounds needed for core.rev < 3 */
+-
+- /* Adjusted size of the device internal TX buffer. */
+- u16 tx_devq_size;
+- /* Used octets of the device internal TX buffer. */
+- u16 tx_devq_used;
+- /* Used packet slots in the device internal TX buffer. */
+- u8 tx_devq_packets;
+- /* Packets from the txfree list can
+- * be taken on incoming TX requests.
+- */
+- struct list_head txfree;
+- unsigned int nr_txfree;
+- /* Packets on the txqueue are queued,
+- * but not completely written to the chip, yet.
+- */
+- struct list_head txqueue;
+- /* Packets on the txrunning queue are completely
+- * posted to the device. We are waiting for the txstatus.
+- */
+- struct list_head txrunning;
+- /* Total number or packets sent.
+- * (This counter can obviously wrap).
+- */
+- unsigned int nr_tx_packets;
+- struct tasklet_struct txtask;
+- struct bcm43xx_pio_txpacket tx_packets_cache[BCM43xx_PIO_MAXTXPACKETS];
+-};
+-
+-static inline
+-u16 bcm43xx_pio_read(struct bcm43xx_pioqueue *queue,
+- u16 offset)
+-{
+- return bcm43xx_read16(queue->bcm, queue->mmio_base + offset);
+-}
+-
+-static inline
+-void bcm43xx_pio_write(struct bcm43xx_pioqueue *queue,
+- u16 offset, u16 value)
+-{
+- bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value);
+- mmiowb();
+-}
+-
+-
+-int bcm43xx_pio_init(struct bcm43xx_private *bcm);
+-void bcm43xx_pio_free(struct bcm43xx_private *bcm);
+-
+-int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
+- struct ieee80211_txb *txb);
+-void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
+- struct bcm43xx_xmitstatus *status);
+-void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue);
+-
+-/* Suspend a TX queue on hardware level. */
+-void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue);
+-void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue);
+-/* Suspend (freeze) the TX tasklet (software level). */
+-void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm);
+-void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm);
+-
+-#else /* CONFIG_BCM43XX_PIO */
+-
+-static inline
+-int bcm43xx_pio_init(struct bcm43xx_private *bcm)
+-{
+- return 0;
+-}
+-static inline
+-void bcm43xx_pio_free(struct bcm43xx_private *bcm)
+-{
+-}
+-static inline
+-int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
+- struct ieee80211_txb *txb)
+-{
+- return 0;
+-}
+-static inline
+-void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
+- struct bcm43xx_xmitstatus *status)
+-{
+-}
+-static inline
+-void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
+-{
+-}
+-static inline
+-void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue)
+-{
+-}
+-static inline
+-void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue)
+-{
+-}
+-static inline
+-void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm)
+-{
+-}
+-static inline
+-void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm)
+-{
+-}
+-
+-#endif /* CONFIG_BCM43XX_PIO */
+-#endif /* BCM43xx_PIO_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.c b/drivers/net/wireless/bcm43xx/bcm43xx_power.c
+deleted file mode 100644
+index 7e774f4..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_power.c
++++ /dev/null
+@@ -1,393 +0,0 @@
+-/*
+-
+- Broadcom BCM43xx wireless driver
+-
+- Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+- Stefano Brivio <st3 at riseup.net>
+- Michael Buesch <mbuesch at freenet.de>
+- Danny van Dyk <kugelfang at gentoo.org>
+- Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+- Some parts of the code in this file are derived from the ipw2200
+- driver Copyright(c) 2003 - 2004 Intel Corporation.
+-
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; 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; see the file COPYING. If not, write to
+- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+- Boston, MA 02110-1301, USA.
+-
+-*/
+-
+-#include <linux/delay.h>
+-
+-#include "bcm43xx.h"
+-#include "bcm43xx_power.h"
+-#include "bcm43xx_main.h"
+-
+-
+-/* Get the Slow Clock Source */
+-static int bcm43xx_pctl_get_slowclksrc(struct bcm43xx_private *bcm)
+-{
+- u32 tmp;
+- int err;
+-
+- assert(bcm->current_core == &bcm->core_chipcommon);
+- if (bcm->current_core->rev < 6) {
+- if (bcm->bustype == BCM43xx_BUSTYPE_PCMCIA ||
+- bcm->bustype == BCM43xx_BUSTYPE_SB)
+- return BCM43xx_PCTL_CLKSRC_XTALOS;
+- if (bcm->bustype == BCM43xx_BUSTYPE_PCI) {
+- err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp);
+- assert(!err);
+- if (tmp & 0x10)
+- return BCM43xx_PCTL_CLKSRC_PCI;
+- return BCM43xx_PCTL_CLKSRC_XTALOS;
+- }
+- }
+- if (bcm->current_core->rev < 10) {
+- tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+- tmp &= 0x7;
+- if (tmp == 0)
+- return BCM43xx_PCTL_CLKSRC_LOPWROS;
+- if (tmp == 1)
+- return BCM43xx_PCTL_CLKSRC_XTALOS;
+- if (tmp == 2)
+- return BCM43xx_PCTL_CLKSRC_PCI;
+- }
+-
+- return BCM43xx_PCTL_CLKSRC_XTALOS;
+-}
+-
+-/* Get max/min slowclock frequency
+- * as described in http://bcm-specs.sipsolutions.net/PowerControl
+- */
+-static int bcm43xx_pctl_clockfreqlimit(struct bcm43xx_private *bcm,
+- int get_max)
+-{
+- int limit;
+- int clocksrc;
+- int divisor;
+- u32 tmp;
+-
+- assert(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL);
+- assert(bcm->current_core == &bcm->core_chipcommon);
+-
+- clocksrc = bcm43xx_pctl_get_slowclksrc(bcm);
+- if (bcm->current_core->rev < 6) {
+- switch (clocksrc) {
+- case BCM43xx_PCTL_CLKSRC_PCI:
+- divisor = 64;
+- break;
+- case BCM43xx_PCTL_CLKSRC_XTALOS:
+- divisor = 32;
+- break;
+- default:
+- assert(0);
+- divisor = 1;
+- }
+- } else if (bcm->current_core->rev < 10) {
+- switch (clocksrc) {
+- case BCM43xx_PCTL_CLKSRC_LOPWROS:
+- divisor = 1;
+- break;
+- case BCM43xx_PCTL_CLKSRC_XTALOS:
+- case BCM43xx_PCTL_CLKSRC_PCI:
+- tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+- divisor = ((tmp & 0xFFFF0000) >> 16) + 1;
+- divisor *= 4;
+- break;
+- default:
+- assert(0);
+- divisor = 1;
+- }
+- } else {
+- tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL);
+- divisor = ((tmp & 0xFFFF0000) >> 16) + 1;
+- divisor *= 4;
+- }
+-
+- switch (clocksrc) {
+- case BCM43xx_PCTL_CLKSRC_LOPWROS:
+- if (get_max)
+- limit = 43000;
+- else
+- limit = 25000;
+- break;
+- case BCM43xx_PCTL_CLKSRC_XTALOS:
+- if (get_max)
+- limit = 20200000;
+- else
+- limit = 19800000;
+- break;
+- case BCM43xx_PCTL_CLKSRC_PCI:
+- if (get_max)
+- limit = 34000000;
+- else
+- limit = 25000000;
+- break;
+- default:
+- assert(0);
+- limit = 0;
+- }
+- limit /= divisor;
+-
+- return limit;
+-}
+-
+-
+-/* init power control
+- * as described in http://bcm-specs.sipsolutions.net/PowerControl
+- */
+-int bcm43xx_pctl_init(struct bcm43xx_private *bcm)
+-{
+- int err, maxfreq;
+- struct bcm43xx_coreinfo *old_core;
+-
+- old_core = bcm->current_core;
+- err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+- if (err == -ENODEV)
+- return 0;
+- if (err)
+- goto out;
+-
+- if (bcm->chip_id == 0x4321) {
+- if (bcm->chip_rev == 0)
+- bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_CTL, 0x03A4);
+- if (bcm->chip_rev == 1)
+- bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_CTL, 0x00A4);
+- }
+-
+- if (bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL) {
+- if (bcm->current_core->rev >= 10) {
+- /* Set Idle Power clock rate to 1Mhz */
+- bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL,
+- (bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL)
+- & 0x0000FFFF) | 0x40000);
+- } else {
+- maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
+- bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY,
+- (maxfreq * 150 + 999999) / 1000000);
+- bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_FREFSELDELAY,
+- (maxfreq * 15 + 999999) / 1000000);
+- }
+- }
+-
+- err = bcm43xx_switch_core(bcm, old_core);
+- assert(err == 0);
+-
+-out:
+- return err;
+-}
+-
+-u16 bcm43xx_pctl_powerup_delay(struct bcm43xx_private *bcm)
+-{
+- u16 delay = 0;
+- int err;
+- u32 pll_on_delay;
+- struct bcm43xx_coreinfo *old_core;
+- int minfreq;
+-
+- if (bcm->bustype != BCM43xx_BUSTYPE_PCI)
+- goto out;
+- if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL))
+- goto out;
+- old_core = bcm->current_core;
+- err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+- if (err == -ENODEV)
+- goto out;
+-
+- minfreq = bcm43xx_pctl_clockfreqlimit(bcm, 0);
+- pll_on_delay = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY);
+- delay = (((pll_on_delay + 2) * 1000000) + (minfreq - 1)) / minfreq;
+-
+- err = bcm43xx_switch_core(bcm, old_core);
+- assert(err == 0);
+-
+-out:
+- return delay;
+-}
+-
+-/* set the powercontrol clock
+- * as described in http://bcm-specs.sipsolutions.net/PowerControl
+- */
+-int bcm43xx_pctl_set_clock(struct bcm43xx_private *bcm, u16 mode)
+-{
+- int err;
+- struct bcm43xx_coreinfo *old_core;
+- u32 tmp;
+-
+- old_core = bcm->current_core;
+- err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+- if (err == -ENODEV)
+- return 0;
+- if (err)
+- goto out;
+-
+- if (bcm->core_chipcommon.rev < 6) {
+- if (mode == BCM43xx_PCTL_CLK_FAST) {
+- err = bcm43xx_pctl_set_crystal(bcm, 1);
+- if (err)
+- goto out;
+- }
+- } else {
+- if ((bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL) &&
+- (bcm->core_chipcommon.rev < 10)) {
+- switch (mode) {
+- case BCM43xx_PCTL_CLK_FAST:
+- tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+- tmp = (tmp & ~BCM43xx_PCTL_FORCE_SLOW) | BCM43xx_PCTL_FORCE_PLL;
+- bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp);
+- break;
+- case BCM43xx_PCTL_CLK_SLOW:
+- tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+- tmp |= BCM43xx_PCTL_FORCE_SLOW;
+- bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp);
+- break;
+- case BCM43xx_PCTL_CLK_DYNAMIC:
+- tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+- tmp &= ~BCM43xx_PCTL_FORCE_SLOW;
+- tmp |= BCM43xx_PCTL_FORCE_PLL;
+- tmp &= ~BCM43xx_PCTL_DYN_XTAL;
+- bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp);
+- }
+- }
+- }
+-
+- err = bcm43xx_switch_core(bcm, old_core);
+- assert(err == 0);
+-
+-out:
+- return err;
+-}
+-
+-int bcm43xx_pctl_set_crystal(struct bcm43xx_private *bcm, int on)
+-{
+- int err;
+- u32 in, out, outenable;
+-
+- err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_IN, &in);
+- if (err)
+- goto err_pci;
+- err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &out);
+- if (err)
+- goto err_pci;
+- err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUTENABLE, &outenable);
+- if (err)
+- goto err_pci;
+-
+- outenable |= (BCM43xx_PCTL_XTAL_POWERUP | BCM43xx_PCTL_PLL_POWERDOWN);
+-
+- if (on) {
+- if (in & 0x40)
+- return 0;
+-
+- out |= (BCM43xx_PCTL_XTAL_POWERUP | BCM43xx_PCTL_PLL_POWERDOWN);
+-
+- err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out);
+- if (err)
+- goto err_pci;
+- err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUTENABLE, outenable);
+- if (err)
+- goto err_pci;
+- udelay(1000);
+-
+- out &= ~BCM43xx_PCTL_PLL_POWERDOWN;
+- err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out);
+- if (err)
+- goto err_pci;
+- udelay(5000);
+- } else {
+- if (bcm->current_core->rev < 5)
+- return 0;
+- if (bcm->sprom.boardflags & BCM43xx_BFL_XTAL_NOSLOW)
+- return 0;
+-
+-/* XXX: Why BCM43xx_MMIO_RADIO_HWENABLED_xx can't be read at this time?
+- * err = bcm43xx_switch_core(bcm, bcm->active_80211_core);
+- * if (err)
+- * return err;
+- * if (((bcm->current_core->rev >= 3) &&
+- * (bcm43xx_read32(bcm, BCM43xx_MMIO_RADIO_HWENABLED_HI) & (1 << 16))) ||
+- * ((bcm->current_core->rev < 3) &&
+- * !(bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_HWENABLED_LO) & (1 << 4))))
+- * return 0;
+- * err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
+- * if (err)
+- * return err;
+- */
+-
+- err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW);
+- if (err)
+- goto out;
+- out &= ~BCM43xx_PCTL_XTAL_POWERUP;
+- out |= BCM43xx_PCTL_PLL_POWERDOWN;
+- err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out);
+- if (err)
+- goto err_pci;
+- err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUTENABLE, outenable);
+- if (err)
+- goto err_pci;
+- }
+-
+-out:
+- return err;
+-
+-err_pci:
+- printk(KERN_ERR PFX "Error: pctl_set_clock() could not access PCI config space!\n");
+- err = -EBUSY;
+- goto out;
+-}
+-
+-/* Set the PowerSavingControlBits.
+- * Bitvalues:
+- * 0 => unset the bit
+- * 1 => set the bit
+- * -1 => calculate the bit
+- */
+-void bcm43xx_power_saving_ctl_bits(struct bcm43xx_private *bcm,
+- int bit25, int bit26)
+-{
+- int i;
+- u32 status;
+-
+-//FIXME: Force 25 to off and 26 to on for now:
+-bit25 = 0;
+-bit26 = 1;
+-
+- if (bit25 == -1) {
+- //TODO: If powersave is not off and FIXME is not set and we are not in adhoc
+- // and thus is not an AP and we are associated, set bit 25
+- }
+- if (bit26 == -1) {
+- //TODO: If the device is awake or this is an AP, or we are scanning, or FIXME,
+- // or we are associated, or FIXME, or the latest PS-Poll packet sent was
+- // successful, set bit26
+- }
+- status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+- if (bit25)
+- status |= BCM43xx_SBF_PS1;
+- else
+- status &= ~BCM43xx_SBF_PS1;
+- if (bit26)
+- status |= BCM43xx_SBF_PS2;
+- else
+- status &= ~BCM43xx_SBF_PS2;
+- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+- if (bit26 && bcm->current_core->rev >= 5) {
+- for (i = 0; i < 100; i++) {
+- if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0040) != 4)
+- break;
+- udelay(10);
+- }
+- }
+-}
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.h b/drivers/net/wireless/bcm43xx/bcm43xx_power.h
+deleted file mode 100644
+index c966ab3..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_power.h
++++ /dev/null
+@@ -1,56 +0,0 @@
+-/*
+-
+- Broadcom BCM43xx wireless driver
+-
+- Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+- Stefano Brivio <st3 at riseup.net>
+- Michael Buesch <mbuesch at freenet.de>
+- Danny van Dyk <kugelfang at gentoo.org>
+- Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+- Some parts of the code in this file are derived from the ipw2200
+- driver Copyright(c) 2003 - 2004 Intel Corporation.
+-
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; 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; see the file COPYING. If not, write to
+- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+- Boston, MA 02110-1301, USA.
+-
+-*/
+-
+-#ifndef BCM43xx_POWER_H_
+-#define BCM43xx_POWER_H_
+-
+-#include <linux/types.h>
+-
+-/* Clock sources */
+-enum {
+- /* PCI clock */
+- BCM43xx_PCTL_CLKSRC_PCI,
+- /* Crystal slow clock oscillator */
+- BCM43xx_PCTL_CLKSRC_XTALOS,
+- /* Low power oscillator */
+- BCM43xx_PCTL_CLKSRC_LOPWROS,
+-};
+-
+-struct bcm43xx_private;
+-
+-int bcm43xx_pctl_init(struct bcm43xx_private *bcm);
+-int bcm43xx_pctl_set_clock(struct bcm43xx_private *bcm, u16 mode);
+-int bcm43xx_pctl_set_crystal(struct bcm43xx_private *bcm, int on);
+-u16 bcm43xx_pctl_powerup_delay(struct bcm43xx_private *bcm);
+-
+-void bcm43xx_power_saving_ctl_bits(struct bcm43xx_private *bcm,
+- int bit25, int bit26);
+-
+-#endif /* BCM43xx_POWER_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
+deleted file mode 100644
+index c605099..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
++++ /dev/null
+@@ -1,2170 +0,0 @@
+-/*
+-
+- Broadcom BCM43xx wireless driver
+-
+- Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+- Stefano Brivio <st3 at riseup.net>
+- Michael Buesch <mbuesch at freenet.de>
+- Danny van Dyk <kugelfang at gentoo.org>
+- Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+- Some parts of the code in this file are derived from the ipw2200
+- driver Copyright(c) 2003 - 2004 Intel Corporation.
+-
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; 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; see the file COPYING. If not, write to
+- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+- Boston, MA 02110-1301, USA.
+-
+-*/
+-
+-#include <linux/delay.h>
+-
+-#include "bcm43xx.h"
+-#include "bcm43xx_main.h"
+-#include "bcm43xx_phy.h"
+-#include "bcm43xx_radio.h"
+-#include "bcm43xx_ilt.h"
+-
+-
+-/* Table for bcm43xx_radio_calibrationvalue() */
+-static const u16 rcc_table[16] = {
+- 0x0002, 0x0003, 0x0001, 0x000F,
+- 0x0006, 0x0007, 0x0005, 0x000F,
+- 0x000A, 0x000B, 0x0009, 0x000F,
+- 0x000E, 0x000F, 0x000D, 0x000F,
+-};
+-
+-/* Reverse the bits of a 4bit value.
+- * Example: 1101 is flipped 1011
+- */
+-static u16 flip_4bit(u16 value)
+-{
+- u16 flipped = 0x0000;
+-
+- assert((value & ~0x000F) == 0x0000);
+-
+- flipped |= (value & 0x0001) << 3;
+- flipped |= (value & 0x0002) << 1;
+- flipped |= (value & 0x0004) >> 1;
+- flipped |= (value & 0x0008) >> 3;
+-
+- return flipped;
+-}
+-
+-/* Get the freq, as it has to be written to the device. */
+-static inline
+-u16 channel2freq_bg(u8 channel)
+-{
+- /* Frequencies are given as frequencies_bg[index] + 2.4GHz
+- * Starting with channel 1
+- */
+- static const u16 frequencies_bg[14] = {
+- 12, 17, 22, 27,
+- 32, 37, 42, 47,
+- 52, 57, 62, 67,
+- 72, 84,
+- };
+-
+- assert(channel >= 1 && channel <= 14);
+-
+- return frequencies_bg[channel - 1];
+-}
+-
+-/* Get the freq, as it has to be written to the device. */
+-static inline
+-u16 channel2freq_a(u8 channel)
+-{
+- assert(channel <= 200);
+-
+- return (5000 + 5 * channel);
+-}
+-
+-void bcm43xx_radio_lock(struct bcm43xx_private *bcm)
+-{
+- u32 status;
+-
+- status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+- status |= BCM43xx_SBF_RADIOREG_LOCK;
+- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+- mmiowb();
+- udelay(10);
+-}
+-
+-void bcm43xx_radio_unlock(struct bcm43xx_private *bcm)
+-{
+- u32 status;
+-
+- bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER); /* dummy read */
+- status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
+- status &= ~BCM43xx_SBF_RADIOREG_LOCK;
+- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
+- mmiowb();
+-}
+-
+-u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-
+- switch (phy->type) {
+- case BCM43xx_PHYTYPE_A:
+- offset |= 0x0040;
+- break;
+- case BCM43xx_PHYTYPE_B:
+- if (radio->version == 0x2053) {
+- if (offset < 0x70)
+- offset += 0x80;
+- else if (offset < 0x80)
+- offset += 0x70;
+- } else if (radio->version == 0x2050) {
+- offset |= 0x80;
+- } else
+- assert(0);
+- break;
+- case BCM43xx_PHYTYPE_G:
+- offset |= 0x80;
+- break;
+- }
+-
+- bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, offset);
+- return bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW);
+-}
+-
+-void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val)
+-{
+- bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, offset);
+- mmiowb();
+- bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW, val);
+-}
+-
+-static void bcm43xx_set_all_gains(struct bcm43xx_private *bcm,
+- s16 first, s16 second, s16 third)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- u16 i;
+- u16 start = 0x08, end = 0x18;
+- u16 offset = 0x0400;
+- u16 tmp;
+-
+- if (phy->rev <= 1) {
+- offset = 0x5000;
+- start = 0x10;
+- end = 0x20;
+- }
+-
+- for (i = 0; i < 4; i++)
+- bcm43xx_ilt_write(bcm, offset + i, first);
+-
+- for (i = start; i < end; i++)
+- bcm43xx_ilt_write(bcm, offset + i, second);
+-
+- if (third != -1) {
+- tmp = ((u16)third << 14) | ((u16)third << 6);
+- bcm43xx_phy_write(bcm, 0x04A0,
+- (bcm43xx_phy_read(bcm, 0x04A0) & 0xBFBF) | tmp);
+- bcm43xx_phy_write(bcm, 0x04A1,
+- (bcm43xx_phy_read(bcm, 0x04A1) & 0xBFBF) | tmp);
+- bcm43xx_phy_write(bcm, 0x04A2,
+- (bcm43xx_phy_read(bcm, 0x04A2) & 0xBFBF) | tmp);
+- }
+- bcm43xx_dummy_transmission(bcm);
+-}
+-
+-static void bcm43xx_set_original_gains(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- u16 i, tmp;
+- u16 offset = 0x0400;
+- u16 start = 0x0008, end = 0x0018;
+-
+- if (phy->rev <= 1) {
+- offset = 0x5000;
+- start = 0x0010;
+- end = 0x0020;
+- }
+-
+- for (i = 0; i < 4; i++) {
+- tmp = (i & 0xFFFC);
+- tmp |= (i & 0x0001) << 1;
+- tmp |= (i & 0x0002) >> 1;
+-
+- bcm43xx_ilt_write(bcm, offset + i, tmp);
+- }
+-
+- for (i = start; i < end; i++)
+- bcm43xx_ilt_write(bcm, offset + i, i - start);
+-
+- bcm43xx_phy_write(bcm, 0x04A0,
+- (bcm43xx_phy_read(bcm, 0x04A0) & 0xBFBF) | 0x4040);
+- bcm43xx_phy_write(bcm, 0x04A1,
+- (bcm43xx_phy_read(bcm, 0x04A1) & 0xBFBF) | 0x4040);
+- bcm43xx_phy_write(bcm, 0x04A2,
+- (bcm43xx_phy_read(bcm, 0x04A2) & 0xBFBF) | 0x4000);
+- bcm43xx_dummy_transmission(bcm);
+-}
+-
+-/* Synthetic PU workaround */
+-static void bcm43xx_synth_pu_workaround(struct bcm43xx_private *bcm, u8 channel)
+-{
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-
+- if (radio->version != 0x2050 || radio->revision >= 6) {
+- /* We do not need the workaround. */
+- return;
+- }
+-
+- if (channel <= 10) {
+- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
+- channel2freq_bg(channel + 4));
+- } else {
+- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
+- channel2freq_bg(1));
+- }
+- udelay(100);
+- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
+- channel2freq_bg(channel));
+-}
+-
+-u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel)
+-{
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- u8 ret = 0;
+- u16 saved, rssi, temp;
+- int i, j = 0;
+-
+- saved = bcm43xx_phy_read(bcm, 0x0403);
+- bcm43xx_radio_selectchannel(bcm, channel, 0);
+- bcm43xx_phy_write(bcm, 0x0403, (saved & 0xFFF8) | 5);
+- if (radio->aci_hw_rssi)
+- rssi = bcm43xx_phy_read(bcm, 0x048A) & 0x3F;
+- else
+- rssi = saved & 0x3F;
+- /* clamp temp to signed 5bit */
+- if (rssi > 32)
+- rssi -= 64;
+- for (i = 0;i < 100; i++) {
+- temp = (bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x3F;
+- if (temp > 32)
+- temp -= 64;
+- if (temp < rssi)
+- j++;
+- if (j >= 20)
+- ret = 1;
+- }
+- bcm43xx_phy_write(bcm, 0x0403, saved);
+-
+- return ret;
+-}
+-
+-u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- u8 ret[13];
+- unsigned int channel = radio->channel;
+- unsigned int i, j, start, end;
+- unsigned long phylock_flags;
+-
+- if (!((phy->type == BCM43xx_PHYTYPE_G) && (phy->rev > 0)))
+- return 0;
+-
+- bcm43xx_phy_lock(bcm, phylock_flags);
+- bcm43xx_radio_lock(bcm);
+- bcm43xx_phy_write(bcm, 0x0802,
+- bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC);
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+- bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF);
+- bcm43xx_set_all_gains(bcm, 3, 8, 1);
+-
+- start = (channel - 5 > 0) ? channel - 5 : 1;
+- end = (channel + 5 < 14) ? channel + 5 : 13;
+-
+- for (i = start; i <= end; i++) {
+- if (abs(channel - i) > 2)
+- ret[i-1] = bcm43xx_radio_aci_detect(bcm, i);
+- }
+- bcm43xx_radio_selectchannel(bcm, channel, 0);
+- bcm43xx_phy_write(bcm, 0x0802,
+- (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC) | 0x0003);
+- bcm43xx_phy_write(bcm, 0x0403,
+- bcm43xx_phy_read(bcm, 0x0403) & 0xFFF8);
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+- bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x8000);
+- bcm43xx_set_original_gains(bcm);
+- for (i = 0; i < 13; i++) {
+- if (!ret[i])
+- continue;
+- end = (i + 5 < 13) ? i + 5 : 13;
+- for (j = i; j < end; j++)
+- ret[j] = 1;
+- }
+- bcm43xx_radio_unlock(bcm);
+- bcm43xx_phy_unlock(bcm, phylock_flags);
+-
+- return ret[channel - 1];
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
+-void bcm43xx_nrssi_hw_write(struct bcm43xx_private *bcm, u16 offset, s16 val)
+-{
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_CTRL, offset);
+- mmiowb();
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_DATA, (u16)val);
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
+-s16 bcm43xx_nrssi_hw_read(struct bcm43xx_private *bcm, u16 offset)
+-{
+- u16 val;
+-
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_CTRL, offset);
+- val = bcm43xx_phy_read(bcm, BCM43xx_PHY_NRSSILT_DATA);
+-
+- return (s16)val;
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
+-void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val)
+-{
+- u16 i;
+- s16 tmp;
+-
+- for (i = 0; i < 64; i++) {
+- tmp = bcm43xx_nrssi_hw_read(bcm, i);
+- tmp -= val;
+- tmp = limit_value(tmp, -32, 31);
+- bcm43xx_nrssi_hw_write(bcm, i, tmp);
+- }
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
+-void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- s16 i, delta;
+- s32 tmp;
+-
+- delta = 0x1F - radio->nrssi[0];
+- for (i = 0; i < 64; i++) {
+- tmp = (i - delta) * radio->nrssislope;
+- tmp /= 0x10000;
+- tmp += 0x3A;
+- tmp = limit_value(tmp, 0, 0x3F);
+- radio->nrssi_lt[i] = tmp;
+- }
+-}
+-
+-static void bcm43xx_calc_nrssi_offset(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- u16 backup[20] = { 0 };
+- s16 v47F;
+- u16 i;
+- u16 saved = 0xFFFF;
+-
+- backup[0] = bcm43xx_phy_read(bcm, 0x0001);
+- backup[1] = bcm43xx_phy_read(bcm, 0x0811);
+- backup[2] = bcm43xx_phy_read(bcm, 0x0812);
+- backup[3] = bcm43xx_phy_read(bcm, 0x0814);
+- backup[4] = bcm43xx_phy_read(bcm, 0x0815);
+- backup[5] = bcm43xx_phy_read(bcm, 0x005A);
+- backup[6] = bcm43xx_phy_read(bcm, 0x0059);
+- backup[7] = bcm43xx_phy_read(bcm, 0x0058);
+- backup[8] = bcm43xx_phy_read(bcm, 0x000A);
+- backup[9] = bcm43xx_phy_read(bcm, 0x0003);
+- backup[10] = bcm43xx_radio_read16(bcm, 0x007A);
+- backup[11] = bcm43xx_radio_read16(bcm, 0x0043);
+-
+- bcm43xx_phy_write(bcm, 0x0429,
+- bcm43xx_phy_read(bcm, 0x0429) & 0x7FFF);
+- bcm43xx_phy_write(bcm, 0x0001,
+- (bcm43xx_phy_read(bcm, 0x0001) & 0x3FFF) | 0x4000);
+- bcm43xx_phy_write(bcm, 0x0811,
+- bcm43xx_phy_read(bcm, 0x0811) | 0x000C);
+- bcm43xx_phy_write(bcm, 0x0812,
+- (bcm43xx_phy_read(bcm, 0x0812) & 0xFFF3) | 0x0004);
+- bcm43xx_phy_write(bcm, 0x0802,
+- bcm43xx_phy_read(bcm, 0x0802) & ~(0x1 | 0x2));
+- if (phy->rev >= 6) {
+- backup[12] = bcm43xx_phy_read(bcm, 0x002E);
+- backup[13] = bcm43xx_phy_read(bcm, 0x002F);
+- backup[14] = bcm43xx_phy_read(bcm, 0x080F);
+- backup[15] = bcm43xx_phy_read(bcm, 0x0810);
+- backup[16] = bcm43xx_phy_read(bcm, 0x0801);
+- backup[17] = bcm43xx_phy_read(bcm, 0x0060);
+- backup[18] = bcm43xx_phy_read(bcm, 0x0014);
+- backup[19] = bcm43xx_phy_read(bcm, 0x0478);
+-
+- bcm43xx_phy_write(bcm, 0x002E, 0);
+- bcm43xx_phy_write(bcm, 0x002F, 0);
+- bcm43xx_phy_write(bcm, 0x080F, 0);
+- bcm43xx_phy_write(bcm, 0x0810, 0);
+- bcm43xx_phy_write(bcm, 0x0478,
+- bcm43xx_phy_read(bcm, 0x0478) | 0x0100);
+- bcm43xx_phy_write(bcm, 0x0801,
+- bcm43xx_phy_read(bcm, 0x0801) | 0x0040);
+- bcm43xx_phy_write(bcm, 0x0060,
+- bcm43xx_phy_read(bcm, 0x0060) | 0x0040);
+- bcm43xx_phy_write(bcm, 0x0014,
+- bcm43xx_phy_read(bcm, 0x0014) | 0x0200);
+- }
+- bcm43xx_radio_write16(bcm, 0x007A,
+- bcm43xx_radio_read16(bcm, 0x007A) | 0x0070);
+- bcm43xx_radio_write16(bcm, 0x007A,
+- bcm43xx_radio_read16(bcm, 0x007A) | 0x0080);
+- udelay(30);
+-
+- v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
+- if (v47F >= 0x20)
+- v47F -= 0x40;
+- if (v47F == 31) {
+- for (i = 7; i >= 4; i--) {
+- bcm43xx_radio_write16(bcm, 0x007B, i);
+- udelay(20);
+- v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
+- if (v47F >= 0x20)
+- v47F -= 0x40;
+- if (v47F < 31 && saved == 0xFFFF)
+- saved = i;
+- }
+- if (saved == 0xFFFF)
+- saved = 4;
+- } else {
+- bcm43xx_radio_write16(bcm, 0x007A,
+- bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);
+- bcm43xx_phy_write(bcm, 0x0814,
+- bcm43xx_phy_read(bcm, 0x0814) | 0x0001);
+- bcm43xx_phy_write(bcm, 0x0815,
+- bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE);
+- bcm43xx_phy_write(bcm, 0x0811,
+- bcm43xx_phy_read(bcm, 0x0811) | 0x000C);
+- bcm43xx_phy_write(bcm, 0x0812,
+- bcm43xx_phy_read(bcm, 0x0812) | 0x000C);
+- bcm43xx_phy_write(bcm, 0x0811,
+- bcm43xx_phy_read(bcm, 0x0811) | 0x0030);
+- bcm43xx_phy_write(bcm, 0x0812,
+- bcm43xx_phy_read(bcm, 0x0812) | 0x0030);
+- bcm43xx_phy_write(bcm, 0x005A, 0x0480);
+- bcm43xx_phy_write(bcm, 0x0059, 0x0810);
+- bcm43xx_phy_write(bcm, 0x0058, 0x000D);
+- if (phy->analog == 0) {
+- bcm43xx_phy_write(bcm, 0x0003, 0x0122);
+- } else {
+- bcm43xx_phy_write(bcm, 0x000A,
+- bcm43xx_phy_read(bcm, 0x000A)
+- | 0x2000);
+- }
+- bcm43xx_phy_write(bcm, 0x0814,
+- bcm43xx_phy_read(bcm, 0x0814) | 0x0004);
+- bcm43xx_phy_write(bcm, 0x0815,
+- bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB);
+- bcm43xx_phy_write(bcm, 0x0003,
+- (bcm43xx_phy_read(bcm, 0x0003) & 0xFF9F)
+- | 0x0040);
+- bcm43xx_radio_write16(bcm, 0x007A,
+- bcm43xx_radio_read16(bcm, 0x007A) | 0x000F);
+- bcm43xx_set_all_gains(bcm, 3, 0, 1);
+- bcm43xx_radio_write16(bcm, 0x0043,
+- (bcm43xx_radio_read16(bcm, 0x0043)
+- & 0x00F0) | 0x000F);
+- udelay(30);
+- v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
+- if (v47F >= 0x20)
+- v47F -= 0x40;
+- if (v47F == -32) {
+- for (i = 0; i < 4; i++) {
+- bcm43xx_radio_write16(bcm, 0x007B, i);
+- udelay(20);
+- v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
+- if (v47F >= 0x20)
+- v47F -= 0x40;
+- if (v47F > -31 && saved == 0xFFFF)
+- saved = i;
+- }
+- if (saved == 0xFFFF)
+- saved = 3;
+- } else
+- saved = 0;
+- }
+- bcm43xx_radio_write16(bcm, 0x007B, saved);
+-
+- if (phy->rev >= 6) {
+- bcm43xx_phy_write(bcm, 0x002E, backup[12]);
+- bcm43xx_phy_write(bcm, 0x002F, backup[13]);
+- bcm43xx_phy_write(bcm, 0x080F, backup[14]);
+- bcm43xx_phy_write(bcm, 0x0810, backup[15]);
+- }
+- bcm43xx_phy_write(bcm, 0x0814, backup[3]);
+- bcm43xx_phy_write(bcm, 0x0815, backup[4]);
+- bcm43xx_phy_write(bcm, 0x005A, backup[5]);
+- bcm43xx_phy_write(bcm, 0x0059, backup[6]);
+- bcm43xx_phy_write(bcm, 0x0058, backup[7]);
+- bcm43xx_phy_write(bcm, 0x000A, backup[8]);
+- bcm43xx_phy_write(bcm, 0x0003, backup[9]);
+- bcm43xx_radio_write16(bcm, 0x0043, backup[11]);
+- bcm43xx_radio_write16(bcm, 0x007A, backup[10]);
+- bcm43xx_phy_write(bcm, 0x0802,
+- bcm43xx_phy_read(bcm, 0x0802) | 0x1 | 0x2);
+- bcm43xx_phy_write(bcm, 0x0429,
+- bcm43xx_phy_read(bcm, 0x0429) | 0x8000);
+- bcm43xx_set_original_gains(bcm);
+- if (phy->rev >= 6) {
+- bcm43xx_phy_write(bcm, 0x0801, backup[16]);
+- bcm43xx_phy_write(bcm, 0x0060, backup[17]);
+- bcm43xx_phy_write(bcm, 0x0014, backup[18]);
+- bcm43xx_phy_write(bcm, 0x0478, backup[19]);
+- }
+- bcm43xx_phy_write(bcm, 0x0001, backup[0]);
+- bcm43xx_phy_write(bcm, 0x0812, backup[2]);
+- bcm43xx_phy_write(bcm, 0x0811, backup[1]);
+-}
+-
+-void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- u16 backup[18] = { 0 };
+- u16 tmp;
+- s16 nrssi0, nrssi1;
+-
+- switch (phy->type) {
+- case BCM43xx_PHYTYPE_B:
+- backup[0] = bcm43xx_radio_read16(bcm, 0x007A);
+- backup[1] = bcm43xx_radio_read16(bcm, 0x0052);
+- backup[2] = bcm43xx_radio_read16(bcm, 0x0043);
+- backup[3] = bcm43xx_phy_read(bcm, 0x0030);
+- backup[4] = bcm43xx_phy_read(bcm, 0x0026);
+- backup[5] = bcm43xx_phy_read(bcm, 0x0015);
+- backup[6] = bcm43xx_phy_read(bcm, 0x002A);
+- backup[7] = bcm43xx_phy_read(bcm, 0x0020);
+- backup[8] = bcm43xx_phy_read(bcm, 0x005A);
+- backup[9] = bcm43xx_phy_read(bcm, 0x0059);
+- backup[10] = bcm43xx_phy_read(bcm, 0x0058);
+- backup[11] = bcm43xx_read16(bcm, 0x03E2);
+- backup[12] = bcm43xx_read16(bcm, 0x03E6);
+- backup[13] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
+-
+- tmp = bcm43xx_radio_read16(bcm, 0x007A);
+- tmp &= (phy->rev >= 5) ? 0x007F : 0x000F;
+- bcm43xx_radio_write16(bcm, 0x007A, tmp);
+- bcm43xx_phy_write(bcm, 0x0030, 0x00FF);
+- bcm43xx_write16(bcm, 0x03EC, 0x7F7F);
+- bcm43xx_phy_write(bcm, 0x0026, 0x0000);
+- bcm43xx_phy_write(bcm, 0x0015,
+- bcm43xx_phy_read(bcm, 0x0015) | 0x0020);
+- bcm43xx_phy_write(bcm, 0x002A, 0x08A3);
+- bcm43xx_radio_write16(bcm, 0x007A,
+- bcm43xx_radio_read16(bcm, 0x007A) | 0x0080);
+-
+- nrssi0 = (s16)bcm43xx_phy_read(bcm, 0x0027);
+- bcm43xx_radio_write16(bcm, 0x007A,
+- bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);
+- if (phy->analog >= 2) {
+- bcm43xx_write16(bcm, 0x03E6, 0x0040);
+- } else if (phy->analog == 0) {
+- bcm43xx_write16(bcm, 0x03E6, 0x0122);
+- } else {
+- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
+- bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) & 0x2000);
+- }
+- bcm43xx_phy_write(bcm, 0x0020, 0x3F3F);
+- bcm43xx_phy_write(bcm, 0x0015, 0xF330);
+- bcm43xx_radio_write16(bcm, 0x005A, 0x0060);
+- bcm43xx_radio_write16(bcm, 0x0043,
+- bcm43xx_radio_read16(bcm, 0x0043) & 0x00F0);
+- bcm43xx_phy_write(bcm, 0x005A, 0x0480);
+- bcm43xx_phy_write(bcm, 0x0059, 0x0810);
+- bcm43xx_phy_write(bcm, 0x0058, 0x000D);
+- udelay(20);
+-
+- nrssi1 = (s16)bcm43xx_phy_read(bcm, 0x0027);
+- bcm43xx_phy_write(bcm, 0x0030, backup[3]);
+- bcm43xx_radio_write16(bcm, 0x007A, backup[0]);
+- bcm43xx_write16(bcm, 0x03E2, backup[11]);
+- bcm43xx_phy_write(bcm, 0x0026, backup[4]);
+- bcm43xx_phy_write(bcm, 0x0015, backup[5]);
+- bcm43xx_phy_write(bcm, 0x002A, backup[6]);
+- bcm43xx_synth_pu_workaround(bcm, radio->channel);
+- if (phy->analog != 0)
+- bcm43xx_write16(bcm, 0x03F4, backup[13]);
+-
+- bcm43xx_phy_write(bcm, 0x0020, backup[7]);
+- bcm43xx_phy_write(bcm, 0x005A, backup[8]);
+- bcm43xx_phy_write(bcm, 0x0059, backup[9]);
+- bcm43xx_phy_write(bcm, 0x0058, backup[10]);
+- bcm43xx_radio_write16(bcm, 0x0052, backup[1]);
+- bcm43xx_radio_write16(bcm, 0x0043, backup[2]);
+-
+- if (nrssi0 == nrssi1)
+- radio->nrssislope = 0x00010000;
+- else
+- radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
+-
+- if (nrssi0 <= -4) {
+- radio->nrssi[0] = nrssi0;
+- radio->nrssi[1] = nrssi1;
+- }
+- break;
+- case BCM43xx_PHYTYPE_G:
+- if (radio->revision >= 9)
+- return;
+- if (radio->revision == 8)
+- bcm43xx_calc_nrssi_offset(bcm);
+-
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+- bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF);
+- bcm43xx_phy_write(bcm, 0x0802,
+- bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC);
+- backup[7] = bcm43xx_read16(bcm, 0x03E2);
+- bcm43xx_write16(bcm, 0x03E2,
+- bcm43xx_read16(bcm, 0x03E2) | 0x8000);
+- backup[0] = bcm43xx_radio_read16(bcm, 0x007A);
+- backup[1] = bcm43xx_radio_read16(bcm, 0x0052);
+- backup[2] = bcm43xx_radio_read16(bcm, 0x0043);
+- backup[3] = bcm43xx_phy_read(bcm, 0x0015);
+- backup[4] = bcm43xx_phy_read(bcm, 0x005A);
+- backup[5] = bcm43xx_phy_read(bcm, 0x0059);
+- backup[6] = bcm43xx_phy_read(bcm, 0x0058);
+- backup[8] = bcm43xx_read16(bcm, 0x03E6);
+- backup[9] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
+- if (phy->rev >= 3) {
+- backup[10] = bcm43xx_phy_read(bcm, 0x002E);
+- backup[11] = bcm43xx_phy_read(bcm, 0x002F);
+- backup[12] = bcm43xx_phy_read(bcm, 0x080F);
+- backup[13] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_LO_CONTROL);
+- backup[14] = bcm43xx_phy_read(bcm, 0x0801);
+- backup[15] = bcm43xx_phy_read(bcm, 0x0060);
+- backup[16] = bcm43xx_phy_read(bcm, 0x0014);
+- backup[17] = bcm43xx_phy_read(bcm, 0x0478);
+- bcm43xx_phy_write(bcm, 0x002E, 0);
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, 0);
+- switch (phy->rev) {
+- case 4: case 6: case 7:
+- bcm43xx_phy_write(bcm, 0x0478,
+- bcm43xx_phy_read(bcm, 0x0478)
+- | 0x0100);
+- bcm43xx_phy_write(bcm, 0x0801,
+- bcm43xx_phy_read(bcm, 0x0801)
+- | 0x0040);
+- break;
+- case 3: case 5:
+- bcm43xx_phy_write(bcm, 0x0801,
+- bcm43xx_phy_read(bcm, 0x0801)
+- & 0xFFBF);
+- break;
+- }
+- bcm43xx_phy_write(bcm, 0x0060,
+- bcm43xx_phy_read(bcm, 0x0060)
+- | 0x0040);
+- bcm43xx_phy_write(bcm, 0x0014,
+- bcm43xx_phy_read(bcm, 0x0014)
+- | 0x0200);
+- }
+- bcm43xx_radio_write16(bcm, 0x007A,
+- bcm43xx_radio_read16(bcm, 0x007A) | 0x0070);
+- bcm43xx_set_all_gains(bcm, 0, 8, 0);
+- bcm43xx_radio_write16(bcm, 0x007A,
+- bcm43xx_radio_read16(bcm, 0x007A) & 0x00F7);
+- if (phy->rev >= 2) {
+- bcm43xx_phy_write(bcm, 0x0811,
+- (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0030);
+- bcm43xx_phy_write(bcm, 0x0812,
+- (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0010);
+- }
+- bcm43xx_radio_write16(bcm, 0x007A,
+- bcm43xx_radio_read16(bcm, 0x007A) | 0x0080);
+- udelay(20);
+-
+- nrssi0 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
+- if (nrssi0 >= 0x0020)
+- nrssi0 -= 0x0040;
+-
+- bcm43xx_radio_write16(bcm, 0x007A,
+- bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);
+- if (phy->analog >= 2) {
+- bcm43xx_phy_write(bcm, 0x0003,
+- (bcm43xx_phy_read(bcm, 0x0003)
+- & 0xFF9F) | 0x0040);
+- }
+-
+- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
+- bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
+- | 0x2000);
+- bcm43xx_radio_write16(bcm, 0x007A,
+- bcm43xx_radio_read16(bcm, 0x007A) | 0x000F);
+- bcm43xx_phy_write(bcm, 0x0015, 0xF330);
+- if (phy->rev >= 2) {
+- bcm43xx_phy_write(bcm, 0x0812,
+- (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0020);
+- bcm43xx_phy_write(bcm, 0x0811,
+- (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0020);
+- }
+-
+- bcm43xx_set_all_gains(bcm, 3, 0, 1);
+- if (radio->revision == 8) {
+- bcm43xx_radio_write16(bcm, 0x0043, 0x001F);
+- } else {
+- tmp = bcm43xx_radio_read16(bcm, 0x0052) & 0xFF0F;
+- bcm43xx_radio_write16(bcm, 0x0052, tmp | 0x0060);
+- tmp = bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0;
+- bcm43xx_radio_write16(bcm, 0x0043, tmp | 0x0009);
+- }
+- bcm43xx_phy_write(bcm, 0x005A, 0x0480);
+- bcm43xx_phy_write(bcm, 0x0059, 0x0810);
+- bcm43xx_phy_write(bcm, 0x0058, 0x000D);
+- udelay(20);
+- nrssi1 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
+- if (nrssi1 >= 0x0020)
+- nrssi1 -= 0x0040;
+- if (nrssi0 == nrssi1)
+- radio->nrssislope = 0x00010000;
+- else
+- radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
+- if (nrssi0 >= -4) {
+- radio->nrssi[0] = nrssi1;
+- radio->nrssi[1] = nrssi0;
+- }
+- if (phy->rev >= 3) {
+- bcm43xx_phy_write(bcm, 0x002E, backup[10]);
+- bcm43xx_phy_write(bcm, 0x002F, backup[11]);
+- bcm43xx_phy_write(bcm, 0x080F, backup[12]);
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, backup[13]);
+- }
+- if (phy->rev >= 2) {
+- bcm43xx_phy_write(bcm, 0x0812,
+- bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF);
+- bcm43xx_phy_write(bcm, 0x0811,
+- bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF);
+- }
+-
+- bcm43xx_radio_write16(bcm, 0x007A, backup[0]);
+- bcm43xx_radio_write16(bcm, 0x0052, backup[1]);
+- bcm43xx_radio_write16(bcm, 0x0043, backup[2]);
+- bcm43xx_write16(bcm, 0x03E2, backup[7]);
+- bcm43xx_write16(bcm, 0x03E6, backup[8]);
+- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[9]);
+- bcm43xx_phy_write(bcm, 0x0015, backup[3]);
+- bcm43xx_phy_write(bcm, 0x005A, backup[4]);
+- bcm43xx_phy_write(bcm, 0x0059, backup[5]);
+- bcm43xx_phy_write(bcm, 0x0058, backup[6]);
+- bcm43xx_synth_pu_workaround(bcm, radio->channel);
+- bcm43xx_phy_write(bcm, 0x0802,
+- bcm43xx_phy_read(bcm, 0x0802) | (0x0001 | 0x0002));
+- bcm43xx_set_original_gains(bcm);
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+- bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x8000);
+- if (phy->rev >= 3) {
+- bcm43xx_phy_write(bcm, 0x0801, backup[14]);
+- bcm43xx_phy_write(bcm, 0x0060, backup[15]);
+- bcm43xx_phy_write(bcm, 0x0014, backup[16]);
+- bcm43xx_phy_write(bcm, 0x0478, backup[17]);
+- }
+- bcm43xx_nrssi_mem_update(bcm);
+- bcm43xx_calc_nrssi_threshold(bcm);
+- break;
+- default:
+- assert(0);
+- }
+-}
+-
+-void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- s32 threshold;
+- s32 a, b;
+- s16 tmp16;
+- u16 tmp_u16;
+-
+- switch (phy->type) {
+- case BCM43xx_PHYTYPE_B: {
+- if (radio->version != 0x2050)
+- return;
+- if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI))
+- return;
+-
+- if (radio->revision >= 6) {
+- threshold = (radio->nrssi[1] - radio->nrssi[0]) * 32;
+- threshold += 20 * (radio->nrssi[0] + 1);
+- threshold /= 40;
+- } else
+- threshold = radio->nrssi[1] - 5;
+-
+- threshold = limit_value(threshold, 0, 0x3E);
+- bcm43xx_phy_read(bcm, 0x0020); /* dummy read */
+- bcm43xx_phy_write(bcm, 0x0020, (((u16)threshold) << 8) | 0x001C);
+-
+- if (radio->revision >= 6) {
+- bcm43xx_phy_write(bcm, 0x0087, 0x0E0D);
+- bcm43xx_phy_write(bcm, 0x0086, 0x0C0B);
+- bcm43xx_phy_write(bcm, 0x0085, 0x0A09);
+- bcm43xx_phy_write(bcm, 0x0084, 0x0808);
+- bcm43xx_phy_write(bcm, 0x0083, 0x0808);
+- bcm43xx_phy_write(bcm, 0x0082, 0x0604);
+- bcm43xx_phy_write(bcm, 0x0081, 0x0302);
+- bcm43xx_phy_write(bcm, 0x0080, 0x0100);
+- }
+- break;
+- }
+- case BCM43xx_PHYTYPE_G:
+- if (!phy->connected ||
+- !(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) {
+- tmp16 = bcm43xx_nrssi_hw_read(bcm, 0x20);
+- if (tmp16 >= 0x20)
+- tmp16 -= 0x40;
+- if (tmp16 < 3) {
+- bcm43xx_phy_write(bcm, 0x048A,
+- (bcm43xx_phy_read(bcm, 0x048A)
+- & 0xF000) | 0x09EB);
+- } else {
+- bcm43xx_phy_write(bcm, 0x048A,
+- (bcm43xx_phy_read(bcm, 0x048A)
+- & 0xF000) | 0x0AED);
+- }
+- } else {
+- if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN) {
+- a = 0xE;
+- b = 0xA;
+- } else if (!radio->aci_wlan_automatic && radio->aci_enable) {
+- a = 0x13;
+- b = 0x12;
+- } else {
+- a = 0xE;
+- b = 0x11;
+- }
+-
+- a = a * (radio->nrssi[1] - radio->nrssi[0]);
+- a += (radio->nrssi[0] << 6);
+- if (a < 32)
+- a += 31;
+- else
+- a += 32;
+- a = a >> 6;
+- a = limit_value(a, -31, 31);
+-
+- b = b * (radio->nrssi[1] - radio->nrssi[0]);
+- b += (radio->nrssi[0] << 6);
+- if (b < 32)
+- b += 31;
+- else
+- b += 32;
+- b = b >> 6;
+- b = limit_value(b, -31, 31);
+-
+- tmp_u16 = bcm43xx_phy_read(bcm, 0x048A) & 0xF000;
+- tmp_u16 |= ((u32)b & 0x0000003F);
+- tmp_u16 |= (((u32)a & 0x0000003F) << 6);
+- bcm43xx_phy_write(bcm, 0x048A, tmp_u16);
+- }
+- break;
+- default:
+- assert(0);
+- }
+-}
+-
+-/* Stack implementation to save/restore values from the
+- * interference mitigation code.
+- * It is save to restore values in random order.
+- */
+-static void _stack_save(u32 *_stackptr, size_t *stackidx,
+- u8 id, u16 offset, u16 value)
+-{
+- u32 *stackptr = &(_stackptr[*stackidx]);
+-
+- assert((offset & 0xE000) == 0x0000);
+- assert((id & 0xF8) == 0x00);
+- *stackptr = offset;
+- *stackptr |= ((u32)id) << 13;
+- *stackptr |= ((u32)value) << 16;
+- (*stackidx)++;
+- assert(*stackidx < BCM43xx_INTERFSTACK_SIZE);
+-}
+-
+-static u16 _stack_restore(u32 *stackptr,
+- u8 id, u16 offset)
+-{
+- size_t i;
+-
+- assert((offset & 0xE000) == 0x0000);
+- assert((id & 0xF8) == 0x00);
+- for (i = 0; i < BCM43xx_INTERFSTACK_SIZE; i++, stackptr++) {
+- if ((*stackptr & 0x00001FFF) != offset)
+- continue;
+- if (((*stackptr & 0x00007000) >> 13) != id)
+- continue;
+- return ((*stackptr & 0xFFFF0000) >> 16);
+- }
+- assert(0);
+-
+- return 0;
+-}
+-
+-#define phy_stacksave(offset) \
+- do { \
+- _stack_save(stack, &stackidx, 0x1, (offset), \
+- bcm43xx_phy_read(bcm, (offset))); \
+- } while (0)
+-#define phy_stackrestore(offset) \
+- do { \
+- bcm43xx_phy_write(bcm, (offset), \
+- _stack_restore(stack, 0x1, \
+- (offset))); \
+- } while (0)
+-#define radio_stacksave(offset) \
+- do { \
+- _stack_save(stack, &stackidx, 0x2, (offset), \
+- bcm43xx_radio_read16(bcm, (offset))); \
+- } while (0)
+-#define radio_stackrestore(offset) \
+- do { \
+- bcm43xx_radio_write16(bcm, (offset), \
+- _stack_restore(stack, 0x2, \
+- (offset))); \
+- } while (0)
+-#define ilt_stacksave(offset) \
+- do { \
+- _stack_save(stack, &stackidx, 0x3, (offset), \
+- bcm43xx_ilt_read(bcm, (offset))); \
+- } while (0)
+-#define ilt_stackrestore(offset) \
+- do { \
+- bcm43xx_ilt_write(bcm, (offset), \
+- _stack_restore(stack, 0x3, \
+- (offset))); \
+- } while (0)
+-
+-static void
+-bcm43xx_radio_interference_mitigation_enable(struct bcm43xx_private *bcm,
+- int mode)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- u16 tmp, flipped;
+- u32 tmp32;
+- size_t stackidx = 0;
+- u32 *stack = radio->interfstack;
+-
+- switch (mode) {
+- case BCM43xx_RADIO_INTERFMODE_NONWLAN:
+- if (phy->rev != 1) {
+- bcm43xx_phy_write(bcm, 0x042B,
+- bcm43xx_phy_read(bcm, 0x042B) | 0x0800);
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+- bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & ~0x4000);
+- break;
+- }
+- radio_stacksave(0x0078);
+- tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E);
+- flipped = flip_4bit(tmp);
+- if (flipped < 10 && flipped >= 8)
+- flipped = 7;
+- else if (flipped >= 10)
+- flipped -= 3;
+- flipped = flip_4bit(flipped);
+- flipped = (flipped << 1) | 0x0020;
+- bcm43xx_radio_write16(bcm, 0x0078, flipped);
+-
+- bcm43xx_calc_nrssi_threshold(bcm);
+-
+- phy_stacksave(0x0406);
+- bcm43xx_phy_write(bcm, 0x0406, 0x7E28);
+-
+- bcm43xx_phy_write(bcm, 0x042B,
+- bcm43xx_phy_read(bcm, 0x042B) | 0x0800);
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
+- bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | 0x1000);
+-
+- phy_stacksave(0x04A0);
+- bcm43xx_phy_write(bcm, 0x04A0,
+- (bcm43xx_phy_read(bcm, 0x04A0) & 0xC0C0) | 0x0008);
+- phy_stacksave(0x04A1);
+- bcm43xx_phy_write(bcm, 0x04A1,
+- (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0C0) | 0x0605);
+- phy_stacksave(0x04A2);
+- bcm43xx_phy_write(bcm, 0x04A2,
+- (bcm43xx_phy_read(bcm, 0x04A2) & 0xC0C0) | 0x0204);
+- phy_stacksave(0x04A8);
+- bcm43xx_phy_write(bcm, 0x04A8,
+- (bcm43xx_phy_read(bcm, 0x04A8) & 0xC0C0) | 0x0803);
+- phy_stacksave(0x04AB);
+- bcm43xx_phy_write(bcm, 0x04AB,
+- (bcm43xx_phy_read(bcm, 0x04AB) & 0xC0C0) | 0x0605);
+-
+- phy_stacksave(0x04A7);
+- bcm43xx_phy_write(bcm, 0x04A7, 0x0002);
+- phy_stacksave(0x04A3);
+- bcm43xx_phy_write(bcm, 0x04A3, 0x287A);
+- phy_stacksave(0x04A9);
+- bcm43xx_phy_write(bcm, 0x04A9, 0x2027);
+- phy_stacksave(0x0493);
+- bcm43xx_phy_write(bcm, 0x0493, 0x32F5);
+- phy_stacksave(0x04AA);
+- bcm43xx_phy_write(bcm, 0x04AA, 0x2027);
+- phy_stacksave(0x04AC);
+- bcm43xx_phy_write(bcm, 0x04AC, 0x32F5);
+- break;
+- case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
+- if (bcm43xx_phy_read(bcm, 0x0033) & 0x0800)
+- break;
+-
+- radio->aci_enable = 1;
+-
+- phy_stacksave(BCM43xx_PHY_RADIO_BITFIELD);
+- phy_stacksave(BCM43xx_PHY_G_CRS);
+- if (phy->rev < 2) {
+- phy_stacksave(0x0406);
+- } else {
+- phy_stacksave(0x04C0);
+- phy_stacksave(0x04C1);
+- }
+- phy_stacksave(0x0033);
+- phy_stacksave(0x04A7);
+- phy_stacksave(0x04A3);
+- phy_stacksave(0x04A9);
+- phy_stacksave(0x04AA);
+- phy_stacksave(0x04AC);
+- phy_stacksave(0x0493);
+- phy_stacksave(0x04A1);
+- phy_stacksave(0x04A0);
+- phy_stacksave(0x04A2);
+- phy_stacksave(0x048A);
+- phy_stacksave(0x04A8);
+- phy_stacksave(0x04AB);
+- if (phy->rev == 2) {
+- phy_stacksave(0x04AD);
+- phy_stacksave(0x04AE);
+- } else if (phy->rev >= 3) {
+- phy_stacksave(0x04AD);
+- phy_stacksave(0x0415);
+- phy_stacksave(0x0416);
+- phy_stacksave(0x0417);
+- ilt_stacksave(0x1A00 + 0x2);
+- ilt_stacksave(0x1A00 + 0x3);
+- }
+- phy_stacksave(0x042B);
+- phy_stacksave(0x048C);
+-
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
+- bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD)
+- & ~0x1000);
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+- (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS)
+- & 0xFFFC) | 0x0002);
+-
+- bcm43xx_phy_write(bcm, 0x0033, 0x0800);
+- bcm43xx_phy_write(bcm, 0x04A3, 0x2027);
+- bcm43xx_phy_write(bcm, 0x04A9, 0x1CA8);
+- bcm43xx_phy_write(bcm, 0x0493, 0x287A);
+- bcm43xx_phy_write(bcm, 0x04AA, 0x1CA8);
+- bcm43xx_phy_write(bcm, 0x04AC, 0x287A);
+-
+- bcm43xx_phy_write(bcm, 0x04A0,
+- (bcm43xx_phy_read(bcm, 0x04A0)
+- & 0xFFC0) | 0x001A);
+- bcm43xx_phy_write(bcm, 0x04A7, 0x000D);
+-
+- if (phy->rev < 2) {
+- bcm43xx_phy_write(bcm, 0x0406, 0xFF0D);
+- } else if (phy->rev == 2) {
+- bcm43xx_phy_write(bcm, 0x04C0, 0xFFFF);
+- bcm43xx_phy_write(bcm, 0x04C1, 0x00A9);
+- } else {
+- bcm43xx_phy_write(bcm, 0x04C0, 0x00C1);
+- bcm43xx_phy_write(bcm, 0x04C1, 0x0059);
+- }
+-
+- bcm43xx_phy_write(bcm, 0x04A1,
+- (bcm43xx_phy_read(bcm, 0x04A1)
+- & 0xC0FF) | 0x1800);
+- bcm43xx_phy_write(bcm, 0x04A1,
+- (bcm43xx_phy_read(bcm, 0x04A1)
+- & 0xFFC0) | 0x0015);
+- bcm43xx_phy_write(bcm, 0x04A8,
+- (bcm43xx_phy_read(bcm, 0x04A8)
+- & 0xCFFF) | 0x1000);
+- bcm43xx_phy_write(bcm, 0x04A8,
+- (bcm43xx_phy_read(bcm, 0x04A8)
+- & 0xF0FF) | 0x0A00);
+- bcm43xx_phy_write(bcm, 0x04AB,
+- (bcm43xx_phy_read(bcm, 0x04AB)
+- & 0xCFFF) | 0x1000);
+- bcm43xx_phy_write(bcm, 0x04AB,
+- (bcm43xx_phy_read(bcm, 0x04AB)
+- & 0xF0FF) | 0x0800);
+- bcm43xx_phy_write(bcm, 0x04AB,
+- (bcm43xx_phy_read(bcm, 0x04AB)
+- & 0xFFCF) | 0x0010);
+- bcm43xx_phy_write(bcm, 0x04AB,
+- (bcm43xx_phy_read(bcm, 0x04AB)
+- & 0xFFF0) | 0x0005);
+- bcm43xx_phy_write(bcm, 0x04A8,
+- (bcm43xx_phy_read(bcm, 0x04A8)
+- & 0xFFCF) | 0x0010);
+- bcm43xx_phy_write(bcm, 0x04A8,
+- (bcm43xx_phy_read(bcm, 0x04A8)
+- & 0xFFF0) | 0x0006);
+- bcm43xx_phy_write(bcm, 0x04A2,
+- (bcm43xx_phy_read(bcm, 0x04A2)
+- & 0xF0FF) | 0x0800);
+- bcm43xx_phy_write(bcm, 0x04A0,
+- (bcm43xx_phy_read(bcm, 0x04A0)
+- & 0xF0FF) | 0x0500);
+- bcm43xx_phy_write(bcm, 0x04A2,
+- (bcm43xx_phy_read(bcm, 0x04A2)
+- & 0xFFF0) | 0x000B);
+-
+- if (phy->rev >= 3) {
+- bcm43xx_phy_write(bcm, 0x048A,
+- bcm43xx_phy_read(bcm, 0x048A)
+- & ~0x8000);
+- bcm43xx_phy_write(bcm, 0x0415,
+- (bcm43xx_phy_read(bcm, 0x0415)
+- & 0x8000) | 0x36D8);
+- bcm43xx_phy_write(bcm, 0x0416,
+- (bcm43xx_phy_read(bcm, 0x0416)
+- & 0x8000) | 0x36D8);
+- bcm43xx_phy_write(bcm, 0x0417,
+- (bcm43xx_phy_read(bcm, 0x0417)
+- & 0xFE00) | 0x016D);
+- } else {
+- bcm43xx_phy_write(bcm, 0x048A,
+- bcm43xx_phy_read(bcm, 0x048A)
+- | 0x1000);
+- bcm43xx_phy_write(bcm, 0x048A,
+- (bcm43xx_phy_read(bcm, 0x048A)
+- & 0x9FFF) | 0x2000);
+- tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODEFLAGS_OFFSET);
+- if (!(tmp32 & 0x800)) {
+- tmp32 |= 0x800;
+- bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODEFLAGS_OFFSET,
+- tmp32);
+- }
+- }
+- if (phy->rev >= 2) {
+- bcm43xx_phy_write(bcm, 0x042B,
+- bcm43xx_phy_read(bcm, 0x042B)
+- | 0x0800);
+- }
+- bcm43xx_phy_write(bcm, 0x048C,
+- (bcm43xx_phy_read(bcm, 0x048C)
+- & 0xF0FF) | 0x0200);
+- if (phy->rev == 2) {
+- bcm43xx_phy_write(bcm, 0x04AE,
+- (bcm43xx_phy_read(bcm, 0x04AE)
+- & 0xFF00) | 0x007F);
+- bcm43xx_phy_write(bcm, 0x04AD,
+- (bcm43xx_phy_read(bcm, 0x04AD)
+- & 0x00FF) | 0x1300);
+- } else if (phy->rev >= 6) {
+- bcm43xx_ilt_write(bcm, 0x1A00 + 0x3, 0x007F);
+- bcm43xx_ilt_write(bcm, 0x1A00 + 0x2, 0x007F);
+- bcm43xx_phy_write(bcm, 0x04AD,
+- bcm43xx_phy_read(bcm, 0x04AD)
+- & 0x00FF);
+- }
+- bcm43xx_calc_nrssi_slope(bcm);
+- break;
+- default:
+- assert(0);
+- }
+-}
+-
+-static void
+-bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm,
+- int mode)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- u32 tmp32;
+- u32 *stack = radio->interfstack;
+-
+- switch (mode) {
+- case BCM43xx_RADIO_INTERFMODE_NONWLAN:
+- if (phy->rev != 1) {
+- bcm43xx_phy_write(bcm, 0x042B,
+- bcm43xx_phy_read(bcm, 0x042B) & ~0x0800);
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+- bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000);
+- break;
+- }
+- phy_stackrestore(0x0078);
+- bcm43xx_calc_nrssi_threshold(bcm);
+- phy_stackrestore(0x0406);
+- bcm43xx_phy_write(bcm, 0x042B,
+- bcm43xx_phy_read(bcm, 0x042B) & ~0x0800);
+- if (!bcm->bad_frames_preempt) {
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
+- bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD)
+- & ~(1 << 11));
+- }
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+- bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000);
+- phy_stackrestore(0x04A0);
+- phy_stackrestore(0x04A1);
+- phy_stackrestore(0x04A2);
+- phy_stackrestore(0x04A8);
+- phy_stackrestore(0x04AB);
+- phy_stackrestore(0x04A7);
+- phy_stackrestore(0x04A3);
+- phy_stackrestore(0x04A9);
+- phy_stackrestore(0x0493);
+- phy_stackrestore(0x04AA);
+- phy_stackrestore(0x04AC);
+- break;
+- case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
+- if (!(bcm43xx_phy_read(bcm, 0x0033) & 0x0800))
+- break;
+-
+- radio->aci_enable = 0;
+-
+- phy_stackrestore(BCM43xx_PHY_RADIO_BITFIELD);
+- phy_stackrestore(BCM43xx_PHY_G_CRS);
+- phy_stackrestore(0x0033);
+- phy_stackrestore(0x04A3);
+- phy_stackrestore(0x04A9);
+- phy_stackrestore(0x0493);
+- phy_stackrestore(0x04AA);
+- phy_stackrestore(0x04AC);
+- phy_stackrestore(0x04A0);
+- phy_stackrestore(0x04A7);
+- if (phy->rev >= 2) {
+- phy_stackrestore(0x04C0);
+- phy_stackrestore(0x04C1);
+- } else
+- phy_stackrestore(0x0406);
+- phy_stackrestore(0x04A1);
+- phy_stackrestore(0x04AB);
+- phy_stackrestore(0x04A8);
+- if (phy->rev == 2) {
+- phy_stackrestore(0x04AD);
+- phy_stackrestore(0x04AE);
+- } else if (phy->rev >= 3) {
+- phy_stackrestore(0x04AD);
+- phy_stackrestore(0x0415);
+- phy_stackrestore(0x0416);
+- phy_stackrestore(0x0417);
+- ilt_stackrestore(0x1A00 + 0x2);
+- ilt_stackrestore(0x1A00 + 0x3);
+- }
+- phy_stackrestore(0x04A2);
+- phy_stackrestore(0x04A8);
+- phy_stackrestore(0x042B);
+- phy_stackrestore(0x048C);
+- tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODEFLAGS_OFFSET);
+- if (tmp32 & 0x800) {
+- tmp32 &= ~0x800;
+- bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODEFLAGS_OFFSET,
+- tmp32);
+- }
+- bcm43xx_calc_nrssi_slope(bcm);
+- break;
+- default:
+- assert(0);
+- }
+-}
+-
+-#undef phy_stacksave
+-#undef phy_stackrestore
+-#undef radio_stacksave
+-#undef radio_stackrestore
+-#undef ilt_stacksave
+-#undef ilt_stackrestore
+-
+-int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm,
+- int mode)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- int currentmode;
+-
+- if ((phy->type != BCM43xx_PHYTYPE_G) ||
+- (phy->rev == 0) ||
+- (!phy->connected))
+- return -ENODEV;
+-
+- radio->aci_wlan_automatic = 0;
+- switch (mode) {
+- case BCM43xx_RADIO_INTERFMODE_AUTOWLAN:
+- radio->aci_wlan_automatic = 1;
+- if (radio->aci_enable)
+- mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
+- else
+- mode = BCM43xx_RADIO_INTERFMODE_NONE;
+- break;
+- case BCM43xx_RADIO_INTERFMODE_NONE:
+- case BCM43xx_RADIO_INTERFMODE_NONWLAN:
+- case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
+- break;
+- default:
+- return -EINVAL;
+- }
+-
+- currentmode = radio->interfmode;
+- if (currentmode == mode)
+- return 0;
+- if (currentmode != BCM43xx_RADIO_INTERFMODE_NONE)
+- bcm43xx_radio_interference_mitigation_disable(bcm, currentmode);
+-
+- if (mode == BCM43xx_RADIO_INTERFMODE_NONE) {
+- radio->aci_enable = 0;
+- radio->aci_hw_rssi = 0;
+- } else
+- bcm43xx_radio_interference_mitigation_enable(bcm, mode);
+- radio->interfmode = mode;
+-
+- return 0;
+-}
+-
+-u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm)
+-{
+- u16 reg, index, ret;
+-
+- reg = bcm43xx_radio_read16(bcm, 0x0060);
+- index = (reg & 0x001E) >> 1;
+- ret = rcc_table[index] << 1;
+- ret |= (reg & 0x0001);
+- ret |= 0x0020;
+-
+- return ret;
+-}
+-
+-#define LPD(L, P, D) (((L) << 2) | ((P) << 1) | ((D) << 0))
+-static u16 bcm43xx_get_812_value(struct bcm43xx_private *bcm, u8 lpd)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- u16 loop_or = 0;
+- u16 adj_loopback_gain = phy->loopback_gain[0];
+- u8 loop;
+- u16 extern_lna_control;
+-
+- if (!phy->connected)
+- return 0;
+- if (!has_loopback_gain(phy)) {
+- if (phy->rev < 7 || !(bcm->sprom.boardflags
+- & BCM43xx_BFL_EXTLNA)) {
+- switch (lpd) {
+- case LPD(0, 1, 1):
+- return 0x0FB2;
+- case LPD(0, 0, 1):
+- return 0x00B2;
+- case LPD(1, 0, 1):
+- return 0x30B2;
+- case LPD(1, 0, 0):
+- return 0x30B3;
+- default:
+- assert(0);
+- }
+- } else {
+- switch (lpd) {
+- case LPD(0, 1, 1):
+- return 0x8FB2;
+- case LPD(0, 0, 1):
+- return 0x80B2;
+- case LPD(1, 0, 1):
+- return 0x20B2;
+- case LPD(1, 0, 0):
+- return 0x20B3;
+- default:
+- assert(0);
+- }
+- }
+- } else {
+- if (radio->revision == 8)
+- adj_loopback_gain += 0x003E;
+- else
+- adj_loopback_gain += 0x0026;
+- if (adj_loopback_gain >= 0x46) {
+- adj_loopback_gain -= 0x46;
+- extern_lna_control = 0x3000;
+- } else if (adj_loopback_gain >= 0x3A) {
+- adj_loopback_gain -= 0x3A;
+- extern_lna_control = 0x2000;
+- } else if (adj_loopback_gain >= 0x2E) {
+- adj_loopback_gain -= 0x2E;
+- extern_lna_control = 0x1000;
+- } else {
+- adj_loopback_gain -= 0x10;
+- extern_lna_control = 0x0000;
+- }
+- for (loop = 0; loop < 16; loop++) {
+- u16 tmp = adj_loopback_gain - 6 * loop;
+- if (tmp < 6)
+- break;
+- }
+-
+- loop_or = (loop << 8) | extern_lna_control;
+- if (phy->rev >= 7 && bcm->sprom.boardflags
+- & BCM43xx_BFL_EXTLNA) {
+- if (extern_lna_control)
+- loop_or |= 0x8000;
+- switch (lpd) {
+- case LPD(0, 1, 1):
+- return 0x8F92;
+- case LPD(0, 0, 1):
+- return (0x8092 | loop_or);
+- case LPD(1, 0, 1):
+- return (0x2092 | loop_or);
+- case LPD(1, 0, 0):
+- return (0x2093 | loop_or);
+- default:
+- assert(0);
+- }
+- } else {
+- switch (lpd) {
+- case LPD(0, 1, 1):
+- return 0x0F92;
+- case LPD(0, 0, 1):
+- case LPD(1, 0, 1):
+- return (0x0092 | loop_or);
+- case LPD(1, 0, 0):
+- return (0x0093 | loop_or);
+- default:
+- assert(0);
+- }
+- }
+- }
+- return 0;
+-}
+-
+-u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- u16 backup[21] = { 0 };
+- u16 ret;
+- u16 i, j;
+- u32 tmp1 = 0, tmp2 = 0;
+-
+- backup[0] = bcm43xx_radio_read16(bcm, 0x0043);
+- backup[14] = bcm43xx_radio_read16(bcm, 0x0051);
+- backup[15] = bcm43xx_radio_read16(bcm, 0x0052);
+- backup[1] = bcm43xx_phy_read(bcm, 0x0015);
+- backup[16] = bcm43xx_phy_read(bcm, 0x005A);
+- backup[17] = bcm43xx_phy_read(bcm, 0x0059);
+- backup[18] = bcm43xx_phy_read(bcm, 0x0058);
+- if (phy->type == BCM43xx_PHYTYPE_B) {
+- backup[2] = bcm43xx_phy_read(bcm, 0x0030);
+- backup[3] = bcm43xx_read16(bcm, 0x03EC);
+- bcm43xx_phy_write(bcm, 0x0030, 0x00FF);
+- bcm43xx_write16(bcm, 0x03EC, 0x3F3F);
+- } else {
+- if (phy->connected) {
+- backup[4] = bcm43xx_phy_read(bcm, 0x0811);
+- backup[5] = bcm43xx_phy_read(bcm, 0x0812);
+- backup[6] = bcm43xx_phy_read(bcm, 0x0814);
+- backup[7] = bcm43xx_phy_read(bcm, 0x0815);
+- backup[8] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS);
+- backup[9] = bcm43xx_phy_read(bcm, 0x0802);
+- bcm43xx_phy_write(bcm, 0x0814,
+- (bcm43xx_phy_read(bcm, 0x0814)
+- | 0x0003));
+- bcm43xx_phy_write(bcm, 0x0815,
+- (bcm43xx_phy_read(bcm, 0x0815)
+- & 0xFFFC));
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
+- (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS)
+- & 0x7FFF));
+- bcm43xx_phy_write(bcm, 0x0802,
+- (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC));
+- if (phy->rev > 1) { /* loopback gain enabled */
+- backup[19] = bcm43xx_phy_read(bcm, 0x080F);
+- backup[20] = bcm43xx_phy_read(bcm, 0x0810);
+- if (phy->rev >= 3)
+- bcm43xx_phy_write(bcm, 0x080F, 0xC020);
+- else
+- bcm43xx_phy_write(bcm, 0x080F, 0x8020);
+- bcm43xx_phy_write(bcm, 0x0810, 0x0000);
+- }
+- bcm43xx_phy_write(bcm, 0x0812,
+- bcm43xx_get_812_value(bcm, LPD(0, 1, 1)));
+- if (phy->rev < 7 || !(bcm->sprom.boardflags
+- & BCM43xx_BFL_EXTLNA))
+- bcm43xx_phy_write(bcm, 0x0811, 0x01B3);
+- else
+- bcm43xx_phy_write(bcm, 0x0811, 0x09B3);
+- }
+- }
+- bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO,
+- (bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) | 0x8000));
+- backup[10] = bcm43xx_phy_read(bcm, 0x0035);
+- bcm43xx_phy_write(bcm, 0x0035,
+- (bcm43xx_phy_read(bcm, 0x0035) & 0xFF7F));
+- backup[11] = bcm43xx_read16(bcm, 0x03E6);
+- backup[12] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
+-
+- // Initialization
+- if (phy->analog == 0) {
+- bcm43xx_write16(bcm, 0x03E6, 0x0122);
+- } else {
+- if (phy->analog >= 2)
+- bcm43xx_phy_write(bcm, 0x0003,
+- (bcm43xx_phy_read(bcm, 0x0003)
+- & 0xFFBF) | 0x0040);
+- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
+- (bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
+- | 0x2000));
+- }
+-
+- ret = bcm43xx_radio_calibrationvalue(bcm);
+-
+- if (phy->type == BCM43xx_PHYTYPE_B)
+- bcm43xx_radio_write16(bcm, 0x0078, 0x0026);
+-
+- if (phy->connected)
+- bcm43xx_phy_write(bcm, 0x0812,
+- bcm43xx_get_812_value(bcm, LPD(0, 1, 1)));
+- bcm43xx_phy_write(bcm, 0x0015, 0xBFAF);
+- bcm43xx_phy_write(bcm, 0x002B, 0x1403);
+- if (phy->connected)
+- bcm43xx_phy_write(bcm, 0x0812,
+- bcm43xx_get_812_value(bcm, LPD(0, 0, 1)));
+- bcm43xx_phy_write(bcm, 0x0015, 0xBFA0);
+- bcm43xx_radio_write16(bcm, 0x0051,
+- (bcm43xx_radio_read16(bcm, 0x0051) | 0x0004));
+- if (radio->revision == 8)
+- bcm43xx_radio_write16(bcm, 0x0043, 0x001F);
+- else {
+- bcm43xx_radio_write16(bcm, 0x0052, 0x0000);
+- bcm43xx_radio_write16(bcm, 0x0043,
+- (bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0)
+- | 0x0009);
+- }
+- bcm43xx_phy_write(bcm, 0x0058, 0x0000);
+-
+- for (i = 0; i < 16; i++) {
+- bcm43xx_phy_write(bcm, 0x005A, 0x0480);
+- bcm43xx_phy_write(bcm, 0x0059, 0xC810);
+- bcm43xx_phy_write(bcm, 0x0058, 0x000D);
+- if (phy->connected)
+- bcm43xx_phy_write(bcm, 0x0812,
+- bcm43xx_get_812_value(bcm, LPD(1, 0, 1)));
+- bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
+- udelay(10);
+- if (phy->connected)
+- bcm43xx_phy_write(bcm, 0x0812,
+- bcm43xx_get_812_value(bcm, LPD(1, 0, 1)));
+- bcm43xx_phy_write(bcm, 0x0015, 0xEFB0);
+- udelay(10);
+- if (phy->connected)
+- bcm43xx_phy_write(bcm, 0x0812,
+- bcm43xx_get_812_value(bcm, LPD(1, 0, 0)));
+- bcm43xx_phy_write(bcm, 0x0015, 0xFFF0);
+- udelay(20);
+- tmp1 += bcm43xx_phy_read(bcm, 0x002D);
+- bcm43xx_phy_write(bcm, 0x0058, 0x0000);
+- if (phy->connected)
+- bcm43xx_phy_write(bcm, 0x0812,
+- bcm43xx_get_812_value(bcm, LPD(1, 0, 1)));
+- bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
+- }
+-
+- tmp1++;
+- tmp1 >>= 9;
+- udelay(10);
+- bcm43xx_phy_write(bcm, 0x0058, 0x0000);
+-
+- for (i = 0; i < 16; i++) {
+- bcm43xx_radio_write16(bcm, 0x0078, (flip_4bit(i) << 1) | 0x0020);
+- backup[13] = bcm43xx_radio_read16(bcm, 0x0078);
+- udelay(10);
+- for (j = 0; j < 16; j++) {
+- bcm43xx_phy_write(bcm, 0x005A, 0x0D80);
+- bcm43xx_phy_write(bcm, 0x0059, 0xC810);
+- bcm43xx_phy_write(bcm, 0x0058, 0x000D);
+- if (phy->connected)
+- bcm43xx_phy_write(bcm, 0x0812,
+- bcm43xx_get_812_value(bcm,
+- LPD(1, 0, 1)));
+- bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
+- udelay(10);
+- if (phy->connected)
+- bcm43xx_phy_write(bcm, 0x0812,
+- bcm43xx_get_812_value(bcm,
+- LPD(1, 0, 1)));
+- bcm43xx_phy_write(bcm, 0x0015, 0xEFB0);
+- udelay(10);
+- if (phy->connected)
+- bcm43xx_phy_write(bcm, 0x0812,
+- bcm43xx_get_812_value(bcm,
+- LPD(1, 0, 0)));
+- bcm43xx_phy_write(bcm, 0x0015, 0xFFF0);
+- udelay(10);
+- tmp2 += bcm43xx_phy_read(bcm, 0x002D);
+- bcm43xx_phy_write(bcm, 0x0058, 0x0000);
+- if (phy->connected)
+- bcm43xx_phy_write(bcm, 0x0812,
+- bcm43xx_get_812_value(bcm,
+- LPD(1, 0, 1)));
+- bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
+- }
+- tmp2++;
+- tmp2 >>= 8;
+- if (tmp1 < tmp2)
+- break;
+- }
+-
+- /* Restore the registers */
+- bcm43xx_phy_write(bcm, 0x0015, backup[1]);
+- bcm43xx_radio_write16(bcm, 0x0051, backup[14]);
+- bcm43xx_radio_write16(bcm, 0x0052, backup[15]);
+- bcm43xx_radio_write16(bcm, 0x0043, backup[0]);
+- bcm43xx_phy_write(bcm, 0x005A, backup[16]);
+- bcm43xx_phy_write(bcm, 0x0059, backup[17]);
+- bcm43xx_phy_write(bcm, 0x0058, backup[18]);
+- bcm43xx_write16(bcm, 0x03E6, backup[11]);
+- if (phy->analog != 0)
+- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[12]);
+- bcm43xx_phy_write(bcm, 0x0035, backup[10]);
+- bcm43xx_radio_selectchannel(bcm, radio->channel, 1);
+- if (phy->type == BCM43xx_PHYTYPE_B) {
+- bcm43xx_phy_write(bcm, 0x0030, backup[2]);
+- bcm43xx_write16(bcm, 0x03EC, backup[3]);
+- } else {
+- if (phy->connected) {
+- bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO,
+- (bcm43xx_read16(bcm,
+- BCM43xx_MMIO_PHY_RADIO) & 0x7FFF));
+- bcm43xx_phy_write(bcm, 0x0811, backup[4]);
+- bcm43xx_phy_write(bcm, 0x0812, backup[5]);
+- bcm43xx_phy_write(bcm, 0x0814, backup[6]);
+- bcm43xx_phy_write(bcm, 0x0815, backup[7]);
+- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, backup[8]);
+- bcm43xx_phy_write(bcm, 0x0802, backup[9]);
+- if (phy->rev > 1) {
+- bcm43xx_phy_write(bcm, 0x080F, backup[19]);
+- bcm43xx_phy_write(bcm, 0x0810, backup[20]);
+- }
+- }
+- }
+- if (i >= 15)
+- ret = backup[13];
+-
+- return ret;
+-}
+-
+-void bcm43xx_radio_init2060(struct bcm43xx_private *bcm)
+-{
+- int err;
+-
+- bcm43xx_radio_write16(bcm, 0x0004, 0x00C0);
+- bcm43xx_radio_write16(bcm, 0x0005, 0x0008);
+- bcm43xx_radio_write16(bcm, 0x0009, 0x0040);
+- bcm43xx_radio_write16(bcm, 0x0005, 0x00AA);
+- bcm43xx_radio_write16(bcm, 0x0032, 0x008F);
+- bcm43xx_radio_write16(bcm, 0x0006, 0x008F);
+- bcm43xx_radio_write16(bcm, 0x0034, 0x008F);
+- bcm43xx_radio_write16(bcm, 0x002C, 0x0007);
+- bcm43xx_radio_write16(bcm, 0x0082, 0x0080);
+- bcm43xx_radio_write16(bcm, 0x0080, 0x0000);
+- bcm43xx_radio_write16(bcm, 0x003F, 0x00DA);
+- bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008);
+- bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0010);
+- bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020);
+- bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020);
+- udelay(400);
+-
+- bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020) | 0x0010);
+- udelay(400);
+-
+- bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008) | 0x0008);
+- bcm43xx_radio_write16(bcm, 0x0085, bcm43xx_radio_read16(bcm, 0x0085) & ~0x0010);
+- bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008);
+- bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040);
+- bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040) | 0x0040);
+- bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0008) | 0x0008);
+- bcm43xx_phy_write(bcm, 0x0063, 0xDDC6);
+- bcm43xx_phy_write(bcm, 0x0069, 0x07BE);
+- bcm43xx_phy_write(bcm, 0x006A, 0x0000);
+-
+- err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_A, 0);
+- assert(err == 0);
+- udelay(1000);
+-}
+-
+-static inline
+-u16 freq_r3A_value(u16 frequency)
+-{
+- u16 value;
+-
+- if (frequency < 5091)
+- value = 0x0040;
+- else if (frequency < 5321)
+- value = 0x0000;
+- else if (frequency < 5806)
+- value = 0x0080;
+- else
+- value = 0x0040;
+-
+- return value;
+-}
+-
+-void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm)
+-{
+- static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 };
+- static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A };
+- u16 tmp = bcm43xx_radio_read16(bcm, 0x001E);
+- int i, j;
+-
+- for (i = 0; i < 5; i++) {
+- for (j = 0; j < 5; j++) {
+- if (tmp == (data_high[i] | data_low[j])) {
+- bcm43xx_phy_write(bcm, 0x0069, (i - j) << 8 | 0x00C0);
+- return;
+- }
+- }
+- }
+-}
+-
+-int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm,
+- u8 channel,
+- int synthetic_pu_workaround)
+-{
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- u16 r8, tmp;
+- u16 freq;
+-
+- if (!ieee80211_is_valid_channel(bcm->ieee, channel))
+- return -EINVAL;
+- if ((radio->manufact == 0x17F) &&
+- (radio->version == 0x2060) &&
+- (radio->revision == 1)) {
+- freq = channel2freq_a(channel);
+-
+- r8 = bcm43xx_radio_read16(bcm, 0x0008);
+- bcm43xx_write16(bcm, 0x03F0, freq);
+- bcm43xx_radio_write16(bcm, 0x0008, r8);
+-
+- TODO();//TODO: write max channel TX power? to Radio 0x2D
+- tmp = bcm43xx_radio_read16(bcm, 0x002E);
+- tmp &= 0x0080;
+- TODO();//TODO: OR tmp with the Power out estimation for this channel?
+- bcm43xx_radio_write16(bcm, 0x002E, tmp);
+-
+- if (freq >= 4920 && freq <= 5500) {
+- /*
+- * r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0F;
+- * = (freq * 0.025862069
+- */
+- r8 = 3 * freq / 116; /* is equal to r8 = freq * 0.025862 */
+- }
+- bcm43xx_radio_write16(bcm, 0x0007, (r8 << 4) | r8);
+- bcm43xx_radio_write16(bcm, 0x0020, (r8 << 4) | r8);
+- bcm43xx_radio_write16(bcm, 0x0021, (r8 << 4) | r8);
+- bcm43xx_radio_write16(bcm, 0x0022,
+- (bcm43xx_radio_read16(bcm, 0x0022)
+- & 0x000F) | (r8 << 4));
+- bcm43xx_radio_write16(bcm, 0x002A, (r8 << 4));
+- bcm43xx_radio_write16(bcm, 0x002B, (r8 << 4));
+- bcm43xx_radio_write16(bcm, 0x0008,
+- (bcm43xx_radio_read16(bcm, 0x0008)
+- & 0x00F0) | (r8 << 4));
+- bcm43xx_radio_write16(bcm, 0x0029,
+- (bcm43xx_radio_read16(bcm, 0x0029)
+- & 0xFF0F) | 0x00B0);
+- bcm43xx_radio_write16(bcm, 0x0035, 0x00AA);
+- bcm43xx_radio_write16(bcm, 0x0036, 0x0085);
+- bcm43xx_radio_write16(bcm, 0x003A,
+- (bcm43xx_radio_read16(bcm, 0x003A)
+- & 0xFF20) | freq_r3A_value(freq));
+- bcm43xx_radio_write16(bcm, 0x003D,
+- bcm43xx_radio_read16(bcm, 0x003D) & 0x00FF);
+- bcm43xx_radio_write16(bcm, 0x0081,
+- (bcm43xx_radio_read16(bcm, 0x0081)
+- & 0xFF7F) | 0x0080);
+- bcm43xx_radio_write16(bcm, 0x0035,
+- bcm43xx_radio_read16(bcm, 0x0035) & 0xFFEF);
+- bcm43xx_radio_write16(bcm, 0x0035,
+- (bcm43xx_radio_read16(bcm, 0x0035)
+- & 0xFFEF) | 0x0010);
+- bcm43xx_radio_set_tx_iq(bcm);
+- TODO(); //TODO: TSSI2dbm workaround
+- bcm43xx_phy_xmitpower(bcm);//FIXME correct?
+- } else {
+- if (synthetic_pu_workaround)
+- bcm43xx_synth_pu_workaround(bcm, channel);
+-
+- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
+- channel2freq_bg(channel));
+-
+- if (channel == 14) {
+- if (bcm->sprom.locale == BCM43xx_LOCALE_JAPAN) {
+- bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODEFLAGS_OFFSET,
+- bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODEFLAGS_OFFSET)
+- & ~(1 << 7));
+- } else {
+- bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODEFLAGS_OFFSET,
+- bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODEFLAGS_OFFSET)
+- | (1 << 7));
+- }
+- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
+- bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
+- | (1 << 11));
+- } else {
+- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
+- bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
+- & 0xF7BF);
+- }
+- }
+-
+- radio->channel = channel;
+- //XXX: Using the longer of 2 timeouts (8000 vs 2000 usecs). Specs states
+- // that 2000 usecs might suffice.
+- udelay(8000);
+-
+- return 0;
+-}
+-
+-void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val)
+-{
+- u16 tmp;
+-
+- val <<= 8;
+- tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0022) & 0xFCFF;
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0022, tmp | val);
+- tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x03A8) & 0xFCFF;
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x03A8, tmp | val);
+- tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0054) & 0xFCFF;
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0054, tmp | val);
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/TX_Gain_Base_Band */
+-static u16 bcm43xx_get_txgain_base_band(u16 txpower)
+-{
+- u16 ret;
+-
+- assert(txpower <= 63);
+-
+- if (txpower >= 54)
+- ret = 2;
+- else if (txpower >= 49)
+- ret = 4;
+- else if (txpower >= 44)
+- ret = 5;
+- else
+- ret = 6;
+-
+- return ret;
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/TX_Gain_Radio_Frequency_Power_Amplifier */
+-static u16 bcm43xx_get_txgain_freq_power_amp(u16 txpower)
+-{
+- u16 ret;
+-
+- assert(txpower <= 63);
+-
+- if (txpower >= 32)
+- ret = 0;
+- else if (txpower >= 25)
+- ret = 1;
+- else if (txpower >= 20)
+- ret = 2;
+- else if (txpower >= 12)
+- ret = 3;
+- else
+- ret = 4;
+-
+- return ret;
+-}
+-
+-/* http://bcm-specs.sipsolutions.net/TX_Gain_Digital_Analog_Converter */
+-static u16 bcm43xx_get_txgain_dac(u16 txpower)
+-{
+- u16 ret;
+-
+- assert(txpower <= 63);
+-
+- if (txpower >= 54)
+- ret = txpower - 53;
+- else if (txpower >= 49)
+- ret = txpower - 42;
+- else if (txpower >= 44)
+- ret = txpower - 37;
+- else if (txpower >= 32)
+- ret = txpower - 32;
+- else if (txpower >= 25)
+- ret = txpower - 20;
+- else if (txpower >= 20)
+- ret = txpower - 13;
+- else if (txpower >= 12)
+- ret = txpower - 8;
+- else
+- ret = txpower;
+-
+- return ret;
+-}
+-
+-void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower)
+-{
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- u16 pamp, base, dac, ilt;
+-
+- txpower = limit_value(txpower, 0, 63);
+-
+- pamp = bcm43xx_get_txgain_freq_power_amp(txpower);
+- pamp <<= 5;
+- pamp &= 0x00E0;
+- bcm43xx_phy_write(bcm, 0x0019, pamp);
+-
+- base = bcm43xx_get_txgain_base_band(txpower);
+- base &= 0x000F;
+- bcm43xx_phy_write(bcm, 0x0017, base | 0x0020);
+-
+- ilt = bcm43xx_ilt_read(bcm, 0x3001);
+- ilt &= 0x0007;
+-
+- dac = bcm43xx_get_txgain_dac(txpower);
+- dac <<= 3;
+- dac |= ilt;
+-
+- bcm43xx_ilt_write(bcm, 0x3001, dac);
+-
+- radio->txpwr_offset = txpower;
+-
+- TODO();
+- //TODO: FuncPlaceholder (Adjust BB loft cancel)
+-}
+-
+-void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm,
+- u16 baseband_attenuation, u16 radio_attenuation,
+- u16 txpower)
+-{
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-
+- if (baseband_attenuation == 0xFFFF)
+- baseband_attenuation = radio->baseband_atten;
+- if (radio_attenuation == 0xFFFF)
+- radio_attenuation = radio->radio_atten;
+- if (txpower == 0xFFFF)
+- txpower = radio->txctl1;
+- radio->baseband_atten = baseband_attenuation;
+- radio->radio_atten = radio_attenuation;
+- radio->txctl1 = txpower;
+-
+- assert(/*baseband_attenuation >= 0 &&*/ baseband_attenuation <= 11);
+- if (radio->revision < 6)
+- assert(/*radio_attenuation >= 0 &&*/ radio_attenuation <= 9);
+- else
+- assert(/* radio_attenuation >= 0 &&*/ radio_attenuation <= 31);
+- assert(/*txpower >= 0 &&*/ txpower <= 7);
+-
+- bcm43xx_phy_set_baseband_attenuation(bcm, baseband_attenuation);
+- bcm43xx_radio_write16(bcm, 0x0043, radio_attenuation);
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0064, radio_attenuation);
+- if (radio->version == 0x2050) {
+- bcm43xx_radio_write16(bcm, 0x0052,
+- (bcm43xx_radio_read16(bcm, 0x0052) & ~0x0070)
+- | ((txpower << 4) & 0x0070));
+- }
+- //FIXME: The spec is very weird and unclear here.
+- if (phy->type == BCM43xx_PHYTYPE_G)
+- bcm43xx_phy_lo_adjust(bcm, 0);
+-}
+-
+-u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-
+- if (radio->version == 0x2050 && radio->revision < 6)
+- return 0;
+- return 2;
+-}
+-
+-u16 bcm43xx_default_radio_attenuation(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- u16 att = 0xFFFF;
+-
+- if (phy->type == BCM43xx_PHYTYPE_A)
+- return 0x60;
+-
+- switch (radio->version) {
+- case 0x2053:
+- switch (radio->revision) {
+- case 1:
+- att = 6;
+- break;
+- }
+- break;
+- case 0x2050:
+- switch (radio->revision) {
+- case 0:
+- att = 5;
+- break;
+- case 1:
+- if (phy->type == BCM43xx_PHYTYPE_G) {
+- if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+- bcm->board_type == 0x421 &&
+- bcm->board_revision >= 30)
+- att = 3;
+- else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+- bcm->board_type == 0x416)
+- att = 3;
+- else
+- att = 1;
+- } else {
+- if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+- bcm->board_type == 0x421 &&
+- bcm->board_revision >= 30)
+- att = 7;
+- else
+- att = 6;
+- }
+- break;
+- case 2:
+- if (phy->type == BCM43xx_PHYTYPE_G) {
+- if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+- bcm->board_type == 0x421 &&
+- bcm->board_revision >= 30)
+- att = 3;
+- else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+- bcm->board_type == 0x416)
+- att = 5;
+- else if (bcm->chip_id == 0x4320)
+- att = 4;
+- else
+- att = 3;
+- } else
+- att = 6;
+- break;
+- case 3:
+- att = 5;
+- break;
+- case 4:
+- case 5:
+- att = 1;
+- break;
+- case 6:
+- case 7:
+- att = 5;
+- break;
+- case 8:
+- att = 0x1A;
+- break;
+- case 9:
+- default:
+- att = 5;
+- }
+- }
+- if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
+- bcm->board_type == 0x421) {
+- if (bcm->board_revision < 0x43)
+- att = 2;
+- else if (bcm->board_revision < 0x51)
+- att = 3;
+- }
+- if (att == 0xFFFF)
+- att = 5;
+-
+- return att;
+-}
+-
+-u16 bcm43xx_default_txctl1(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-
+- if (radio->version != 0x2050)
+- return 0;
+- if (radio->revision == 1)
+- return 3;
+- if (radio->revision < 6)
+- return 2;
+- if (radio->revision == 8)
+- return 1;
+- return 0;
+-}
+-
+-void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- int err;
+-
+- if (radio->enabled)
+- return;
+-
+- switch (phy->type) {
+- case BCM43xx_PHYTYPE_A:
+- bcm43xx_radio_write16(bcm, 0x0004, 0x00C0);
+- bcm43xx_radio_write16(bcm, 0x0005, 0x0008);
+- bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) & 0xFFF7);
+- bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) & 0xFFF7);
+- bcm43xx_radio_init2060(bcm);
+- break;
+- case BCM43xx_PHYTYPE_B:
+- case BCM43xx_PHYTYPE_G:
+- bcm43xx_phy_write(bcm, 0x0015, 0x8000);
+- bcm43xx_phy_write(bcm, 0x0015, 0xCC00);
+- bcm43xx_phy_write(bcm, 0x0015, (phy->connected ? 0x00C0 : 0x0000));
+- err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 1);
+- assert(err == 0);
+- break;
+- default:
+- assert(0);
+- }
+- radio->enabled = 1;
+- dprintk(KERN_INFO PFX "Radio turned on\n");
+- bcm43xx_leds_update(bcm, 0);
+-}
+-
+-void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+-
+- if (phy->type == BCM43xx_PHYTYPE_A) {
+- bcm43xx_radio_write16(bcm, 0x0004, 0x00FF);
+- bcm43xx_radio_write16(bcm, 0x0005, 0x00FB);
+- bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) | 0x0008);
+- bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) | 0x0008);
+- }
+- if (phy->type == BCM43xx_PHYTYPE_G && bcm->current_core->rev >= 5) {
+- bcm43xx_phy_write(bcm, 0x0811, bcm43xx_phy_read(bcm, 0x0811) | 0x008C);
+- bcm43xx_phy_write(bcm, 0x0812, bcm43xx_phy_read(bcm, 0x0812) & 0xFF73);
+- } else
+- bcm43xx_phy_write(bcm, 0x0015, 0xAA00);
+- radio->enabled = 0;
+- dprintk(KERN_INFO PFX "Radio initialized\n");
+- bcm43xx_leds_update(bcm, 0);
+-}
+-
+-void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+-
+- switch (phy->type) {
+- case BCM43xx_PHYTYPE_A:
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0068, 0x7F7F);
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x006a, 0x7F7F);
+- break;
+- case BCM43xx_PHYTYPE_B:
+- case BCM43xx_PHYTYPE_G:
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0058, 0x7F7F);
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x005a, 0x7F7F);
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0070, 0x7F7F);
+- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0072, 0x7F7F);
+- break;
+- }
+-}
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h
+deleted file mode 100644
+index 77a98a5..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h
++++ /dev/null
+@@ -1,115 +0,0 @@
+-/*
+-
+- Broadcom BCM43xx wireless driver
+-
+- Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+- Stefano Brivio <st3 at riseup.net>
+- Michael Buesch <mbuesch at freenet.de>
+- Danny van Dyk <kugelfang at gentoo.org>
+- Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+- Some parts of the code in this file are derived from the ipw2200
+- driver Copyright(c) 2003 - 2004 Intel Corporation.
+-
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; 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; see the file COPYING. If not, write to
+- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+- Boston, MA 02110-1301, USA.
+-
+-*/
+-
+-#ifndef BCM43xx_RADIO_H_
+-#define BCM43xx_RADIO_H_
+-
+-#include "bcm43xx.h"
+-
+-
+-#define BCM43xx_RADIO_DEFAULT_CHANNEL_A 36
+-#define BCM43xx_RADIO_DEFAULT_CHANNEL_BG 6
+-
+-/* Force antenna 0. */
+-#define BCM43xx_RADIO_TXANTENNA_0 0
+-/* Force antenna 1. */
+-#define BCM43xx_RADIO_TXANTENNA_1 1
+-/* Use the RX antenna, that was selected for the most recently
+- * received good PLCP header.
+- */
+-#define BCM43xx_RADIO_TXANTENNA_LASTPLCP 3
+-#define BCM43xx_RADIO_TXANTENNA_DEFAULT BCM43xx_RADIO_TXANTENNA_LASTPLCP
+-
+-#define BCM43xx_RADIO_INTERFMODE_NONE 0
+-#define BCM43xx_RADIO_INTERFMODE_NONWLAN 1
+-#define BCM43xx_RADIO_INTERFMODE_MANUALWLAN 2
+-#define BCM43xx_RADIO_INTERFMODE_AUTOWLAN 3
+-
+-
+-void bcm43xx_radio_lock(struct bcm43xx_private *bcm);
+-void bcm43xx_radio_unlock(struct bcm43xx_private *bcm);
+-
+-u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset);
+-void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val);
+-
+-u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm);
+-void bcm43xx_radio_init2060(struct bcm43xx_private *bcm);
+-
+-void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm);
+-void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm);
+-
+-static inline
+-int bcm43xx_is_hw_radio_enabled(struct bcm43xx_private *bcm)
+-{
+- /* function to return state of hardware enable of radio
+- * returns 0 if radio disabled, 1 if radio enabled
+- */
+- if (bcm->current_core->rev >= 3)
+- return ((bcm43xx_read32(bcm, BCM43xx_MMIO_RADIO_HWENABLED_HI)
+- & BCM43xx_MMIO_RADIO_HWENABLED_HI_MASK)
+- == 0) ? 1 : 0;
+- else
+- return ((bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_HWENABLED_LO)
+- & BCM43xx_MMIO_RADIO_HWENABLED_LO_MASK)
+- == 0) ? 0 : 1;
+-}
+-
+-int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm, u8 channel,
+- int synthetic_pu_workaround);
+-
+-void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower);
+-void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm,
+- u16 baseband_attenuation, u16 attenuation,
+- u16 txpower);
+-
+-u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_private *bcm);
+-u16 bcm43xx_default_radio_attenuation(struct bcm43xx_private *bcm);
+-u16 bcm43xx_default_txctl1(struct bcm43xx_private *bcm);
+-
+-void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val);
+-
+-void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm);
+-
+-u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel);
+-u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm);
+-
+-int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm, int mode);
+-
+-void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm);
+-void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm);
+-s16 bcm43xx_nrssi_hw_read(struct bcm43xx_private *bcm, u16 offset);
+-void bcm43xx_nrssi_hw_write(struct bcm43xx_private *bcm, u16 offset, s16 val);
+-void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val);
+-void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm);
+-
+-void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm);
+-u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm);
+-
+-#endif /* BCM43xx_RADIO_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
+deleted file mode 100644
+index 8ab5f93..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
++++ /dev/null
+@@ -1,471 +0,0 @@
+-/*
+-
+- Broadcom BCM43xx wireless driver
+-
+- SYSFS support routines
+-
+- Copyright (c) 2006 Michael Buesch <mbuesch at freenet.de>
+-
+- 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; see the file COPYING. If not, write to
+- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+- Boston, MA 02110-1301, USA.
+-
+-*/
+-
+-#include "bcm43xx_sysfs.h"
+-#include "bcm43xx.h"
+-#include "bcm43xx_main.h"
+-#include "bcm43xx_radio.h"
+-
+-#include <linux/capability.h>
+-
+-
+-#define GENERIC_FILESIZE 64
+-
+-
+-static int get_integer(const char *buf, size_t count)
+-{
+- char tmp[10 + 1] = { 0 };
+- int ret = -EINVAL;
+-
+- if (count == 0)
+- goto out;
+- count = min(count, (size_t)10);
+- memcpy(tmp, buf, count);
+- ret = simple_strtol(tmp, NULL, 10);
+-out:
+- return ret;
+-}
+-
+-static int get_boolean(const char *buf, size_t count)
+-{
+- if (count != 0) {
+- if (buf[0] == '1')
+- return 1;
+- if (buf[0] == '0')
+- return 0;
+- if (count >= 4 && memcmp(buf, "true", 4) == 0)
+- return 1;
+- if (count >= 5 && memcmp(buf, "false", 5) == 0)
+- return 0;
+- if (count >= 3 && memcmp(buf, "yes", 3) == 0)
+- return 1;
+- if (count >= 2 && memcmp(buf, "no", 2) == 0)
+- return 0;
+- if (count >= 2 && memcmp(buf, "on", 2) == 0)
+- return 1;
+- if (count >= 3 && memcmp(buf, "off", 3) == 0)
+- return 0;
+- }
+- return -EINVAL;
+-}
+-
+-static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len)
+-{
+- int i, pos = 0;
+-
+- for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
+- pos += snprintf(buf + pos, buf_len - pos - 1,
+- "%04X", swab16(sprom[i]) & 0xFFFF);
+- }
+- pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
+-
+- return pos + 1;
+-}
+-
+-static int hex2sprom(u16 *sprom, const char *dump, size_t len)
+-{
+- char tmp[5] = { 0 };
+- int cnt = 0;
+- unsigned long parsed;
+-
+- if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2)
+- return -EINVAL;
+-
+- while (cnt < BCM43xx_SPROM_SIZE) {
+- memcpy(tmp, dump, 4);
+- dump += 4;
+- parsed = simple_strtoul(tmp, NULL, 16);
+- sprom[cnt++] = swab16((u16)parsed);
+- }
+-
+- return 0;
+-}
+-
+-static ssize_t bcm43xx_attr_sprom_show(struct device *dev,
+- struct device_attribute *attr,
+- char *buf)
+-{
+- struct bcm43xx_private *bcm = dev_to_bcm(dev);
+- u16 *sprom;
+- unsigned long flags;
+- int err;
+-
+- if (!capable(CAP_NET_ADMIN))
+- return -EPERM;
+-
+- assert(BCM43xx_SPROM_SIZE * sizeof(u16) <= PAGE_SIZE);
+- sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
+- GFP_KERNEL);
+- if (!sprom)
+- return -ENOMEM;
+- mutex_lock(&bcm->mutex);
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- err = bcm43xx_sprom_read(bcm, sprom);
+- if (!err)
+- err = sprom2hex(sprom, buf, PAGE_SIZE);
+- mmiowb();
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- mutex_unlock(&bcm->mutex);
+- kfree(sprom);
+-
+- return err;
+-}
+-
+-static ssize_t bcm43xx_attr_sprom_store(struct device *dev,
+- struct device_attribute *attr,
+- const char *buf, size_t count)
+-{
+- struct bcm43xx_private *bcm = dev_to_bcm(dev);
+- u16 *sprom;
+- unsigned long flags;
+- int err;
+-
+- if (!capable(CAP_NET_ADMIN))
+- return -EPERM;
+-
+- sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
+- GFP_KERNEL);
+- if (!sprom)
+- return -ENOMEM;
+- err = hex2sprom(sprom, buf, count);
+- if (err)
+- goto out_kfree;
+- mutex_lock(&bcm->mutex);
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- spin_lock(&bcm->leds_lock);
+- err = bcm43xx_sprom_write(bcm, sprom);
+- mmiowb();
+- spin_unlock(&bcm->leds_lock);
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- mutex_unlock(&bcm->mutex);
+-out_kfree:
+- kfree(sprom);
+-
+- return err ? err : count;
+-
+-}
+-
+-static DEVICE_ATTR(sprom, 0600,
+- bcm43xx_attr_sprom_show,
+- bcm43xx_attr_sprom_store);
+-
+-static ssize_t bcm43xx_attr_interfmode_show(struct device *dev,
+- struct device_attribute *attr,
+- char *buf)
+-{
+- struct bcm43xx_private *bcm = dev_to_bcm(dev);
+- ssize_t count = 0;
+-
+- if (!capable(CAP_NET_ADMIN))
+- return -EPERM;
+-
+- mutex_lock(&bcm->mutex);
+-
+- switch (bcm43xx_current_radio(bcm)->interfmode) {
+- case BCM43xx_RADIO_INTERFMODE_NONE:
+- count = snprintf(buf, PAGE_SIZE, "0 (No Interference Mitigation)\n");
+- break;
+- case BCM43xx_RADIO_INTERFMODE_NONWLAN:
+- count = snprintf(buf, PAGE_SIZE, "1 (Non-WLAN Interference Mitigation)\n");
+- break;
+- case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
+- count = snprintf(buf, PAGE_SIZE, "2 (WLAN Interference Mitigation)\n");
+- break;
+- default:
+- assert(0);
+- }
+-
+- mutex_unlock(&bcm->mutex);
+-
+- return count;
+-
+-}
+-
+-static ssize_t bcm43xx_attr_interfmode_store(struct device *dev,
+- struct device_attribute *attr,
+- const char *buf, size_t count)
+-{
+- struct bcm43xx_private *bcm = dev_to_bcm(dev);
+- unsigned long flags;
+- int err;
+- int mode;
+-
+- if (!capable(CAP_NET_ADMIN))
+- return -EPERM;
+-
+- mode = get_integer(buf, count);
+- switch (mode) {
+- case 0:
+- mode = BCM43xx_RADIO_INTERFMODE_NONE;
+- break;
+- case 1:
+- mode = BCM43xx_RADIO_INTERFMODE_NONWLAN;
+- break;
+- case 2:
+- mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
+- break;
+- case 3:
+- mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN;
+- break;
+- default:
+- return -EINVAL;
+- }
+-
+- mutex_lock(&bcm->mutex);
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+-
+- err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
+- if (err) {
+- printk(KERN_ERR PFX "Interference Mitigation not "
+- "supported by device\n");
+- }
+- mmiowb();
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- mutex_unlock(&bcm->mutex);
+-
+- return err ? err : count;
+-}
+-
+-static DEVICE_ATTR(interference, 0644,
+- bcm43xx_attr_interfmode_show,
+- bcm43xx_attr_interfmode_store);
+-
+-static ssize_t bcm43xx_attr_preamble_show(struct device *dev,
+- struct device_attribute *attr,
+- char *buf)
+-{
+- struct bcm43xx_private *bcm = dev_to_bcm(dev);
+- ssize_t count;
+-
+- if (!capable(CAP_NET_ADMIN))
+- return -EPERM;
+-
+- mutex_lock(&bcm->mutex);
+-
+- if (bcm->short_preamble)
+- count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n");
+- else
+- count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n");
+-
+- mutex_unlock(&bcm->mutex);
+-
+- return count;
+-}
+-
+-static ssize_t bcm43xx_attr_preamble_store(struct device *dev,
+- struct device_attribute *attr,
+- const char *buf, size_t count)
+-{
+- struct bcm43xx_private *bcm = dev_to_bcm(dev);
+- unsigned long flags;
+- int value;
+-
+- if (!capable(CAP_NET_ADMIN))
+- return -EPERM;
+-
+- value = get_boolean(buf, count);
+- if (value < 0)
+- return value;
+- mutex_lock(&bcm->mutex);
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+-
+- bcm->short_preamble = !!value;
+-
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- mutex_unlock(&bcm->mutex);
+-
+- return count;
+-}
+-
+-static DEVICE_ATTR(shortpreamble, 0644,
+- bcm43xx_attr_preamble_show,
+- bcm43xx_attr_preamble_store);
+-
+-static ssize_t bcm43xx_attr_phymode_store(struct device *dev,
+- struct device_attribute *attr,
+- const char *buf, size_t count)
+-{
+- struct bcm43xx_private *bcm = dev_to_bcm(dev);
+- int phytype;
+- int err = -EINVAL;
+-
+- if (count < 1)
+- goto out;
+- switch (buf[0]) {
+- case 'a': case 'A':
+- phytype = BCM43xx_PHYTYPE_A;
+- break;
+- case 'b': case 'B':
+- phytype = BCM43xx_PHYTYPE_B;
+- break;
+- case 'g': case 'G':
+- phytype = BCM43xx_PHYTYPE_G;
+- break;
+- default:
+- goto out;
+- }
+-
+- bcm43xx_cancel_work(bcm);
+- mutex_lock(&(bcm)->mutex);
+- err = bcm43xx_select_wireless_core(bcm, phytype);
+- if (!err)
+- bcm43xx_periodic_tasks_setup(bcm);
+- mutex_unlock(&(bcm)->mutex);
+- if (err == -ESRCH)
+- err = -ENODEV;
+-
+-out:
+- return err ? err : count;
+-}
+-
+-static ssize_t bcm43xx_attr_phymode_show(struct device *dev,
+- struct device_attribute *attr,
+- char *buf)
+-{
+- struct bcm43xx_private *bcm = dev_to_bcm(dev);
+- ssize_t count = 0;
+-
+- mutex_lock(&(bcm)->mutex);
+- switch (bcm43xx_current_phy(bcm)->type) {
+- case BCM43xx_PHYTYPE_A:
+- snprintf(buf, PAGE_SIZE, "A");
+- break;
+- case BCM43xx_PHYTYPE_B:
+- snprintf(buf, PAGE_SIZE, "B");
+- break;
+- case BCM43xx_PHYTYPE_G:
+- snprintf(buf, PAGE_SIZE, "G");
+- break;
+- default:
+- assert(0);
+- }
+- mutex_unlock(&(bcm)->mutex);
+-
+- return count;
+-}
+-
+-static DEVICE_ATTR(phymode, 0644,
+- bcm43xx_attr_phymode_show,
+- bcm43xx_attr_phymode_store);
+-
+-static ssize_t bcm43xx_attr_microcode_show(struct device *dev,
+- struct device_attribute *attr,
+- char *buf)
+-{
+- unsigned long flags;
+- struct bcm43xx_private *bcm = dev_to_bcm(dev);
+- ssize_t count = 0;
+- u16 status;
+-
+- if (!capable(CAP_NET_ADMIN))
+- return -EPERM;
+-
+- mutex_lock(&(bcm)->mutex);
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- status = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+- BCM43xx_UCODE_STATUS);
+-
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- mutex_unlock(&(bcm)->mutex);
+- switch (status) {
+- case 0x0000:
+- count = snprintf(buf, PAGE_SIZE, "0x%.4x (invalid)\n",
+- status);
+- break;
+- case 0x0001:
+- count = snprintf(buf, PAGE_SIZE, "0x%.4x (init)\n",
+- status);
+- break;
+- case 0x0002:
+- count = snprintf(buf, PAGE_SIZE, "0x%.4x (active)\n",
+- status);
+- break;
+- case 0x0003:
+- count = snprintf(buf, PAGE_SIZE, "0x%.4x (suspended)\n",
+- status);
+- break;
+- case 0x0004:
+- count = snprintf(buf, PAGE_SIZE, "0x%.4x (asleep)\n",
+- status);
+- break;
+- default:
+- count = snprintf(buf, PAGE_SIZE, "0x%.4x (unknown)\n",
+- status);
+- break;
+- }
+-
+- return count;
+-}
+-
+-static DEVICE_ATTR(microcodestatus, 0444,
+- bcm43xx_attr_microcode_show,
+- NULL);
+-
+-int bcm43xx_sysfs_register(struct bcm43xx_private *bcm)
+-{
+- struct device *dev = &bcm->pci_dev->dev;
+- int err;
+-
+- assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
+-
+- err = device_create_file(dev, &dev_attr_sprom);
+- if (err)
+- goto out;
+- err = device_create_file(dev, &dev_attr_interference);
+- if (err)
+- goto err_remove_sprom;
+- err = device_create_file(dev, &dev_attr_shortpreamble);
+- if (err)
+- goto err_remove_interfmode;
+- err = device_create_file(dev, &dev_attr_phymode);
+- if (err)
+- goto err_remove_shortpreamble;
+- err = device_create_file(dev, &dev_attr_microcodestatus);
+- if (err)
+- goto err_remove_phymode;
+-
+-out:
+- return err;
+-err_remove_phymode:
+- device_remove_file(dev, &dev_attr_phymode);
+-err_remove_shortpreamble:
+- device_remove_file(dev, &dev_attr_shortpreamble);
+-err_remove_interfmode:
+- device_remove_file(dev, &dev_attr_interference);
+-err_remove_sprom:
+- device_remove_file(dev, &dev_attr_sprom);
+- goto out;
+-}
+-
+-void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm)
+-{
+- struct device *dev = &bcm->pci_dev->dev;
+-
+- device_remove_file(dev, &dev_attr_microcodestatus);
+- device_remove_file(dev, &dev_attr_phymode);
+- device_remove_file(dev, &dev_attr_shortpreamble);
+- device_remove_file(dev, &dev_attr_interference);
+- device_remove_file(dev, &dev_attr_sprom);
+-}
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h
+deleted file mode 100644
+index cc701df..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h
++++ /dev/null
+@@ -1,9 +0,0 @@
+-#ifndef BCM43xx_SYSFS_H_
+-#define BCM43xx_SYSFS_H_
+-
+-struct bcm43xx_private;
+-
+-int bcm43xx_sysfs_register(struct bcm43xx_private *bcm);
+-void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm);
+-
+-#endif /* BCM43xx_SYSFS_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
+deleted file mode 100644
+index 6acfdc4..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
++++ /dev/null
+@@ -1,1035 +0,0 @@
+-/*
+-
+- Broadcom BCM43xx wireless driver
+-
+- Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+- Stefano Brivio <st3 at riseup.net>
+- Michael Buesch <mbuesch at freenet.de>
+- Danny van Dyk <kugelfang at gentoo.org>
+- Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+- Some parts of the code in this file are derived from the ipw2200
+- driver Copyright(c) 2003 - 2004 Intel Corporation.
+-
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; 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; see the file COPYING. If not, write to
+- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+- Boston, MA 02110-1301, USA.
+-
+-*/
+-
+-#include <linux/wireless.h>
+-#include <net/iw_handler.h>
+-#include <net/ieee80211softmac.h>
+-#include <net/ieee80211softmac_wx.h>
+-#include <linux/capability.h>
+-#include <linux/delay.h>
+-
+-#include "bcm43xx.h"
+-#include "bcm43xx_wx.h"
+-#include "bcm43xx_main.h"
+-#include "bcm43xx_radio.h"
+-#include "bcm43xx_phy.h"
+-
+-
+-/* The WIRELESS_EXT version, which is implemented by this driver. */
+-#define BCM43xx_WX_VERSION 18
+-
+-#define MAX_WX_STRING 80
+-
+-static int bcm43xx_wx_get_name(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- int i;
+- struct bcm43xx_phyinfo *phy;
+- char suffix[7] = { 0 };
+- int have_a = 0, have_b = 0, have_g = 0;
+-
+- mutex_lock(&bcm->mutex);
+- for (i = 0; i < bcm->nr_80211_available; i++) {
+- phy = &(bcm->core_80211_ext[i].phy);
+- switch (phy->type) {
+- case BCM43xx_PHYTYPE_A:
+- have_a = 1;
+- break;
+- case BCM43xx_PHYTYPE_G:
+- have_g = 1;
+- case BCM43xx_PHYTYPE_B:
+- have_b = 1;
+- break;
+- default:
+- assert(0);
+- }
+- }
+- mutex_unlock(&bcm->mutex);
+-
+- i = 0;
+- if (have_a) {
+- suffix[i++] = 'a';
+- suffix[i++] = '/';
+- }
+- if (have_b) {
+- suffix[i++] = 'b';
+- suffix[i++] = '/';
+- }
+- if (have_g) {
+- suffix[i++] = 'g';
+- suffix[i++] = '/';
+- }
+- if (i != 0)
+- suffix[i - 1] = '\0';
+-
+- snprintf(data->name, IFNAMSIZ, "IEEE 802.11%s", suffix);
+-
+- return 0;
+-}
+-
+-static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- unsigned long flags;
+- u8 channel;
+- s8 expon;
+- int freq;
+- int err = -EINVAL;
+-
+- mutex_lock(&bcm->mutex);
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+-
+- if ((data->freq.e == 0) &&
+- (data->freq.m >= 0) && (data->freq.m <= 1000)) {
+- channel = data->freq.m;
+- freq = bcm43xx_channel_to_freq(bcm, channel);
+- } else {
+- freq = data->freq.m;
+- expon = 6 - data->freq.e;
+- while (--expon >= 0) /* scale down the frequency to MHz */
+- freq /= 10;
+- assert(freq > 1000);
+- channel = bcm43xx_freq_to_channel(bcm, freq);
+- }
+- if (!ieee80211_is_valid_channel(bcm->ieee, channel))
+- goto out_unlock;
+- if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
+- //ieee80211softmac_disassoc(softmac, $REASON);
+- bcm43xx_mac_suspend(bcm);
+- err = bcm43xx_radio_selectchannel(bcm, channel, 0);
+- bcm43xx_mac_enable(bcm);
+- } else {
+- bcm43xx_current_radio(bcm)->initial_channel = channel;
+- err = 0;
+- }
+-out_unlock:
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- mutex_unlock(&bcm->mutex);
+-
+- return err;
+-}
+-
+-static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- struct bcm43xx_radioinfo *radio;
+- int err = -ENODEV;
+- u16 channel;
+-
+- mutex_lock(&bcm->mutex);
+- radio = bcm43xx_current_radio(bcm);
+- channel = radio->channel;
+- if (channel == 0xFF) {
+- channel = radio->initial_channel;
+- if (channel == 0xFF)
+- goto out_unlock;
+- }
+- assert(channel > 0 && channel <= 1000);
+- data->freq.e = 1;
+- data->freq.m = bcm43xx_channel_to_freq(bcm, channel) * 100000;
+- data->freq.flags = 1;
+-
+- err = 0;
+-out_unlock:
+- mutex_unlock(&bcm->mutex);
+-
+- return err;
+-}
+-
+-static int bcm43xx_wx_set_mode(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- unsigned long flags;
+- int mode;
+-
+- mode = data->mode;
+- if (mode == IW_MODE_AUTO)
+- mode = BCM43xx_INITIAL_IWMODE;
+-
+- mutex_lock(&bcm->mutex);
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
+- if (bcm->ieee->iw_mode != mode)
+- bcm43xx_set_iwmode(bcm, mode);
+- } else
+- bcm->ieee->iw_mode = mode;
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- mutex_unlock(&bcm->mutex);
+-
+- return 0;
+-}
+-
+-static int bcm43xx_wx_get_mode(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-
+- mutex_lock(&bcm->mutex);
+- data->mode = bcm->ieee->iw_mode;
+- mutex_unlock(&bcm->mutex);
+-
+- return 0;
+-}
+-
+-static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- struct iw_range *range = (struct iw_range *)extra;
+- const struct ieee80211_geo *geo;
+- int i, j;
+- struct bcm43xx_phyinfo *phy;
+-
+- data->data.length = sizeof(*range);
+- memset(range, 0, sizeof(*range));
+-
+- //TODO: What about 802.11b?
+- /* 54Mb/s == ~27Mb/s payload throughput (802.11g) */
+- range->throughput = 27 * 1000 * 1000;
+-
+- range->max_qual.qual = 100;
+- range->max_qual.level = 146; /* set floor at -110 dBm (146 - 256) */
+- range->max_qual.noise = 146;
+- range->max_qual.updated = IW_QUAL_ALL_UPDATED;
+-
+- range->avg_qual.qual = 50;
+- range->avg_qual.level = 0;
+- range->avg_qual.noise = 0;
+- range->avg_qual.updated = IW_QUAL_ALL_UPDATED;
+-
+- range->min_rts = BCM43xx_MIN_RTS_THRESHOLD;
+- range->max_rts = BCM43xx_MAX_RTS_THRESHOLD;
+- range->min_frag = MIN_FRAG_THRESHOLD;
+- range->max_frag = MAX_FRAG_THRESHOLD;
+-
+- range->encoding_size[0] = 5;
+- range->encoding_size[1] = 13;
+- range->num_encoding_sizes = 2;
+- range->max_encoding_tokens = WEP_KEYS;
+-
+- range->we_version_compiled = WIRELESS_EXT;
+- range->we_version_source = BCM43xx_WX_VERSION;
+-
+- range->enc_capa = IW_ENC_CAPA_WPA |
+- IW_ENC_CAPA_WPA2 |
+- IW_ENC_CAPA_CIPHER_TKIP |
+- IW_ENC_CAPA_CIPHER_CCMP;
+-
+- mutex_lock(&bcm->mutex);
+- phy = bcm43xx_current_phy(bcm);
+-
+- range->num_bitrates = 0;
+- i = 0;
+- if (phy->type == BCM43xx_PHYTYPE_A ||
+- phy->type == BCM43xx_PHYTYPE_G) {
+- range->num_bitrates = 8;
+- range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB * 500000;
+- range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB * 500000;
+- range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB * 500000;
+- range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB * 500000;
+- range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB * 500000;
+- range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB * 500000;
+- range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB * 500000;
+- range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB * 500000;
+- }
+- if (phy->type == BCM43xx_PHYTYPE_B ||
+- phy->type == BCM43xx_PHYTYPE_G) {
+- range->num_bitrates += 4;
+- range->bitrate[i++] = IEEE80211_CCK_RATE_1MB * 500000;
+- range->bitrate[i++] = IEEE80211_CCK_RATE_2MB * 500000;
+- range->bitrate[i++] = IEEE80211_CCK_RATE_5MB * 500000;
+- range->bitrate[i++] = IEEE80211_CCK_RATE_11MB * 500000;
+- }
+-
+- geo = ieee80211_get_geo(bcm->ieee);
+- range->num_channels = geo->a_channels + geo->bg_channels;
+- j = 0;
+- for (i = 0; i < geo->a_channels; i++) {
+- if (j == IW_MAX_FREQUENCIES)
+- break;
+- range->freq[j].i = j + 1;
+- range->freq[j].m = geo->a[i].freq * 100000;
+- range->freq[j].e = 1;
+- j++;
+- }
+- for (i = 0; i < geo->bg_channels; i++) {
+- if (j == IW_MAX_FREQUENCIES)
+- break;
+- range->freq[j].i = j + 1;
+- range->freq[j].m = geo->bg[i].freq * 100000;
+- range->freq[j].e = 1;
+- j++;
+- }
+- range->num_frequency = j;
+-
+- mutex_unlock(&bcm->mutex);
+-
+- return 0;
+-}
+-
+-static int bcm43xx_wx_set_nick(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- size_t len;
+-
+- mutex_lock(&bcm->mutex);
+- len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE);
+- memcpy(bcm->nick, extra, len);
+- bcm->nick[len] = '\0';
+- mutex_unlock(&bcm->mutex);
+-
+- return 0;
+-}
+-
+-static int bcm43xx_wx_get_nick(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- size_t len;
+-
+- mutex_lock(&bcm->mutex);
+- len = strlen(bcm->nick);
+- memcpy(extra, bcm->nick, len);
+- data->data.length = (__u16)len;
+- data->data.flags = 1;
+- mutex_unlock(&bcm->mutex);
+-
+- return 0;
+-}
+-
+-static int bcm43xx_wx_set_rts(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- unsigned long flags;
+- int err = -EINVAL;
+-
+- mutex_lock(&bcm->mutex);
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- if (data->rts.disabled) {
+- bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD;
+- err = 0;
+- } else {
+- if (data->rts.value >= BCM43xx_MIN_RTS_THRESHOLD &&
+- data->rts.value <= BCM43xx_MAX_RTS_THRESHOLD) {
+- bcm->rts_threshold = data->rts.value;
+- err = 0;
+- }
+- }
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- mutex_unlock(&bcm->mutex);
+-
+- return err;
+-}
+-
+-static int bcm43xx_wx_get_rts(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-
+- mutex_lock(&bcm->mutex);
+- data->rts.value = bcm->rts_threshold;
+- data->rts.fixed = 0;
+- data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD);
+- mutex_unlock(&bcm->mutex);
+-
+- return 0;
+-}
+-
+-static int bcm43xx_wx_set_frag(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- unsigned long flags;
+- int err = -EINVAL;
+-
+- mutex_lock(&bcm->mutex);
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- if (data->frag.disabled) {
+- bcm->ieee->fts = MAX_FRAG_THRESHOLD;
+- err = 0;
+- } else {
+- if (data->frag.value >= MIN_FRAG_THRESHOLD &&
+- data->frag.value <= MAX_FRAG_THRESHOLD) {
+- bcm->ieee->fts = data->frag.value & ~0x1;
+- err = 0;
+- }
+- }
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- mutex_unlock(&bcm->mutex);
+-
+- return err;
+-}
+-
+-static int bcm43xx_wx_get_frag(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+-
+- mutex_lock(&bcm->mutex);
+- data->frag.value = bcm->ieee->fts;
+- data->frag.fixed = 0;
+- data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD);
+- mutex_unlock(&bcm->mutex);
+-
+- return 0;
+-}
+-
+-static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- struct bcm43xx_radioinfo *radio;
+- struct bcm43xx_phyinfo *phy;
+- unsigned long flags;
+- int err = -ENODEV;
+- u16 maxpower;
+-
+- if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) {
+- printk(KERN_ERR PFX "TX power not in dBm.\n");
+- return -EOPNOTSUPP;
+- }
+-
+- mutex_lock(&bcm->mutex);
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
+- goto out_unlock;
+- radio = bcm43xx_current_radio(bcm);
+- phy = bcm43xx_current_phy(bcm);
+- if (data->txpower.disabled != (!(radio->enabled))) {
+- if (data->txpower.disabled)
+- bcm43xx_radio_turn_off(bcm);
+- else
+- bcm43xx_radio_turn_on(bcm);
+- }
+- if (data->txpower.value > 0) {
+- /* desired and maxpower dBm values are in Q5.2 */
+- if (phy->type == BCM43xx_PHYTYPE_A)
+- maxpower = bcm->sprom.maxpower_aphy;
+- else
+- maxpower = bcm->sprom.maxpower_bgphy;
+- radio->txpower_desired = limit_value(data->txpower.value << 2,
+- 0, maxpower);
+- bcm43xx_phy_xmitpower(bcm);
+- }
+- err = 0;
+-
+-out_unlock:
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- mutex_unlock(&bcm->mutex);
+-
+- return err;
+-}
+-
+-static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- struct bcm43xx_radioinfo *radio;
+- int err = -ENODEV;
+-
+- mutex_lock(&bcm->mutex);
+- if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
+- goto out_unlock;
+- radio = bcm43xx_current_radio(bcm);
+- /* desired dBm value is in Q5.2 */
+- data->txpower.value = radio->txpower_desired >> 2;
+- data->txpower.fixed = 1;
+- data->txpower.flags = IW_TXPOW_DBM;
+- data->txpower.disabled = !(radio->enabled);
+-
+- err = 0;
+-out_unlock:
+- mutex_unlock(&bcm->mutex);
+-
+- return err;
+-}
+-
+-static int bcm43xx_wx_set_encoding(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- int err;
+-
+- err = ieee80211_wx_set_encode(bcm->ieee, info, data, extra);
+-
+- return err;
+-}
+-
+-static int bcm43xx_wx_set_encodingext(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- int err;
+-
+- err = ieee80211_wx_set_encodeext(bcm->ieee, info, data, extra);
+-
+- return err;
+-}
+-
+-static int bcm43xx_wx_get_encoding(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- int err;
+-
+- err = ieee80211_wx_get_encode(bcm->ieee, info, data, extra);
+-
+- return err;
+-}
+-
+-static int bcm43xx_wx_get_encodingext(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- int err;
+-
+- err = ieee80211_wx_get_encodeext(bcm->ieee, info, data, extra);
+-
+- return err;
+-}
+-
+-static int bcm43xx_wx_set_interfmode(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- unsigned long flags;
+- int mode, err = 0;
+-
+- mode = *((int *)extra);
+- switch (mode) {
+- case 0:
+- mode = BCM43xx_RADIO_INTERFMODE_NONE;
+- break;
+- case 1:
+- mode = BCM43xx_RADIO_INTERFMODE_NONWLAN;
+- break;
+- case 2:
+- mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
+- break;
+- case 3:
+- mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN;
+- break;
+- default:
+- printk(KERN_ERR PFX "set_interfmode allowed parameters are: "
+- "0 => None, 1 => Non-WLAN, 2 => WLAN, "
+- "3 => Auto-WLAN\n");
+- return -EINVAL;
+- }
+-
+- mutex_lock(&bcm->mutex);
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
+- err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
+- if (err) {
+- printk(KERN_ERR PFX "Interference Mitigation not "
+- "supported by device\n");
+- }
+- } else {
+- if (mode == BCM43xx_RADIO_INTERFMODE_AUTOWLAN) {
+- printk(KERN_ERR PFX "Interference Mitigation mode Auto-WLAN "
+- "not supported while the interface is down.\n");
+- err = -ENODEV;
+- } else
+- bcm43xx_current_radio(bcm)->interfmode = mode;
+- }
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- mutex_unlock(&bcm->mutex);
+-
+- return err;
+-}
+-
+-static int bcm43xx_wx_get_interfmode(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- int mode;
+-
+- mutex_lock(&bcm->mutex);
+- mode = bcm43xx_current_radio(bcm)->interfmode;
+- mutex_unlock(&bcm->mutex);
+-
+- switch (mode) {
+- case BCM43xx_RADIO_INTERFMODE_NONE:
+- strncpy(extra, "0 (No Interference Mitigation)", MAX_WX_STRING);
+- break;
+- case BCM43xx_RADIO_INTERFMODE_NONWLAN:
+- strncpy(extra, "1 (Non-WLAN Interference Mitigation)", MAX_WX_STRING);
+- break;
+- case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
+- strncpy(extra, "2 (WLAN Interference Mitigation)", MAX_WX_STRING);
+- break;
+- default:
+- assert(0);
+- }
+- data->data.length = strlen(extra) + 1;
+-
+- return 0;
+-}
+-
+-static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- unsigned long flags;
+- int on;
+-
+- on = *((int *)extra);
+- mutex_lock(&bcm->mutex);
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- bcm->short_preamble = !!on;
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- mutex_unlock(&bcm->mutex);
+-
+- return 0;
+-}
+-
+-static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- int on;
+-
+- mutex_lock(&bcm->mutex);
+- on = bcm->short_preamble;
+- mutex_unlock(&bcm->mutex);
+-
+- if (on)
+- strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING);
+- else
+- strncpy(extra, "0 (Short Preamble disabled)", MAX_WX_STRING);
+- data->data.length = strlen(extra) + 1;
+-
+- return 0;
+-}
+-
+-static int bcm43xx_wx_set_swencryption(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- unsigned long flags;
+- int on;
+-
+- on = *((int *)extra);
+-
+- mutex_lock(&bcm->mutex);
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- bcm->ieee->host_encrypt = !!on;
+- bcm->ieee->host_decrypt = !!on;
+- bcm->ieee->host_build_iv = !on;
+- bcm->ieee->host_strip_iv_icv = !on;
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- mutex_unlock(&bcm->mutex);
+-
+- return 0;
+-}
+-
+-static int bcm43xx_wx_get_swencryption(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- int on;
+-
+- mutex_lock(&bcm->mutex);
+- on = bcm->ieee->host_encrypt;
+- mutex_unlock(&bcm->mutex);
+-
+- if (on)
+- strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING);
+- else
+- strncpy(extra, "0 (SW encryption disabled) ", MAX_WX_STRING);
+- data->data.length = strlen(extra + 1);
+-
+- return 0;
+-}
+-
+-/* Enough buffer to hold a hexdump of the sprom data. */
+-#define SPROM_BUFFERSIZE 512
+-
+-static int sprom2hex(const u16 *sprom, char *dump)
+-{
+- int i, pos = 0;
+-
+- for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
+- pos += snprintf(dump + pos, SPROM_BUFFERSIZE - pos - 1,
+- "%04X", swab16(sprom[i]) & 0xFFFF);
+- }
+-
+- return pos + 1;
+-}
+-
+-static int hex2sprom(u16 *sprom, const char *dump, unsigned int len)
+-{
+- char tmp[5] = { 0 };
+- int cnt = 0;
+- unsigned long parsed;
+-
+- if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2)
+- return -EINVAL;
+- while (cnt < BCM43xx_SPROM_SIZE) {
+- memcpy(tmp, dump, 4);
+- dump += 4;
+- parsed = simple_strtoul(tmp, NULL, 16);
+- sprom[cnt++] = swab16((u16)parsed);
+- }
+-
+- return 0;
+-}
+-
+-static int bcm43xx_wx_sprom_read(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- int err = -EPERM;
+- u16 *sprom;
+- unsigned long flags;
+-
+- if (!capable(CAP_SYS_RAWIO))
+- goto out;
+-
+- err = -ENOMEM;
+- sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
+- GFP_KERNEL);
+- if (!sprom)
+- goto out;
+-
+- mutex_lock(&bcm->mutex);
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- err = -ENODEV;
+- if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
+- err = bcm43xx_sprom_read(bcm, sprom);
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- mutex_unlock(&bcm->mutex);
+- if (!err)
+- data->data.length = sprom2hex(sprom, extra);
+- kfree(sprom);
+-out:
+- return err;
+-}
+-
+-static int bcm43xx_wx_sprom_write(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- int err = -EPERM;
+- u16 *sprom;
+- unsigned long flags;
+- char *input;
+- unsigned int len;
+-
+- if (!capable(CAP_SYS_RAWIO))
+- goto out;
+-
+- err = -ENOMEM;
+- sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
+- GFP_KERNEL);
+- if (!sprom)
+- goto out;
+-
+- len = data->data.length;
+- extra[len - 1] = '\0';
+- input = strchr(extra, ':');
+- if (input) {
+- input++;
+- len -= input - extra;
+- } else
+- input = extra;
+- err = hex2sprom(sprom, input, len);
+- if (err)
+- goto out_kfree;
+-
+- mutex_lock(&bcm->mutex);
+- spin_lock_irqsave(&bcm->irq_lock, flags);
+- spin_lock(&bcm->leds_lock);
+- err = -ENODEV;
+- if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
+- err = bcm43xx_sprom_write(bcm, sprom);
+- spin_unlock(&bcm->leds_lock);
+- spin_unlock_irqrestore(&bcm->irq_lock, flags);
+- mutex_unlock(&bcm->mutex);
+-out_kfree:
+- kfree(sprom);
+-out:
+- return err;
+-}
+-
+-/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
+-
+-static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_dev)
+-{
+- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+- struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
+- struct iw_statistics *wstats;
+- struct ieee80211_network *network = NULL;
+- static int tmp_level = 0;
+- static int tmp_qual = 0;
+- unsigned long flags;
+-
+- wstats = &bcm->stats.wstats;
+- if (!mac->associnfo.associated) {
+- wstats->miss.beacon = 0;
+-// bcm->ieee->ieee_stats.tx_retry_limit_exceeded = 0; // FIXME: should this be cleared here?
+- wstats->discard.retries = 0;
+-// bcm->ieee->ieee_stats.tx_discards_wrong_sa = 0; // FIXME: same question
+- wstats->discard.nwid = 0;
+-// bcm->ieee->ieee_stats.rx_discards_undecryptable = 0; // FIXME: ditto
+- wstats->discard.code = 0;
+-// bcm->ieee->ieee_stats.rx_fragments = 0; // FIXME: same here
+- wstats->discard.fragment = 0;
+- wstats->discard.misc = 0;
+- wstats->qual.qual = 0;
+- wstats->qual.level = 0;
+- wstats->qual.noise = 0;
+- wstats->qual.updated = 7;
+- wstats->qual.updated |= IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+- return wstats;
+- }
+- /* fill in the real statistics when iface associated */
+- spin_lock_irqsave(&mac->ieee->lock, flags);
+- list_for_each_entry(network, &mac->ieee->network_list, list) {
+- if (!memcmp(mac->associnfo.bssid, network->bssid, ETH_ALEN)) {
+- if (!tmp_level) { /* get initial values */
+- tmp_level = network->stats.signal;
+- tmp_qual = network->stats.rssi;
+- } else { /* smooth results */
+- tmp_level = (15 * tmp_level + network->stats.signal)/16;
+- tmp_qual = (15 * tmp_qual + network->stats.rssi)/16;
+- }
+- break;
+- }
+- }
+- spin_unlock_irqrestore(&mac->ieee->lock, flags);
+- wstats->qual.level = tmp_level;
+- wstats->qual.qual = 100 * tmp_qual / RX_RSSI_MAX;
+- wstats->qual.noise = bcm->stats.noise;
+- wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+- wstats->discard.code = bcm->ieee->ieee_stats.rx_discards_undecryptable;
+- wstats->discard.retries = bcm->ieee->ieee_stats.tx_retry_limit_exceeded;
+- wstats->discard.nwid = bcm->ieee->ieee_stats.tx_discards_wrong_sa;
+- wstats->discard.fragment = bcm->ieee->ieee_stats.rx_fragments;
+- wstats->discard.misc = 0; // FIXME
+- wstats->miss.beacon = 0; // FIXME
+- return wstats;
+-}
+-
+-
+-#ifdef WX
+-# undef WX
+-#endif
+-#define WX(ioctl) [(ioctl) - SIOCSIWCOMMIT]
+-static const iw_handler bcm43xx_wx_handlers[] = {
+- /* Wireless Identification */
+- WX(SIOCGIWNAME) = bcm43xx_wx_get_name,
+- /* Basic operations */
+- WX(SIOCSIWFREQ) = bcm43xx_wx_set_channelfreq,
+- WX(SIOCGIWFREQ) = bcm43xx_wx_get_channelfreq,
+- WX(SIOCSIWMODE) = bcm43xx_wx_set_mode,
+- WX(SIOCGIWMODE) = bcm43xx_wx_get_mode,
+- /* Informative stuff */
+- WX(SIOCGIWRANGE) = bcm43xx_wx_get_rangeparams,
+- /* Access Point manipulation */
+- WX(SIOCSIWAP) = ieee80211softmac_wx_set_wap,
+- WX(SIOCGIWAP) = ieee80211softmac_wx_get_wap,
+- WX(SIOCSIWSCAN) = ieee80211softmac_wx_trigger_scan,
+- WX(SIOCGIWSCAN) = ieee80211softmac_wx_get_scan_results,
+- /* 802.11 specific support */
+- WX(SIOCSIWESSID) = ieee80211softmac_wx_set_essid,
+- WX(SIOCGIWESSID) = ieee80211softmac_wx_get_essid,
+- WX(SIOCSIWNICKN) = bcm43xx_wx_set_nick,
+- WX(SIOCGIWNICKN) = bcm43xx_wx_get_nick,
+- /* Other parameters */
+- WX(SIOCSIWRATE) = ieee80211softmac_wx_set_rate,
+- WX(SIOCGIWRATE) = ieee80211softmac_wx_get_rate,
+- WX(SIOCSIWRTS) = bcm43xx_wx_set_rts,
+- WX(SIOCGIWRTS) = bcm43xx_wx_get_rts,
+- WX(SIOCSIWFRAG) = bcm43xx_wx_set_frag,
+- WX(SIOCGIWFRAG) = bcm43xx_wx_get_frag,
+- WX(SIOCSIWTXPOW) = bcm43xx_wx_set_xmitpower,
+- WX(SIOCGIWTXPOW) = bcm43xx_wx_get_xmitpower,
+-//TODO WX(SIOCSIWRETRY) = bcm43xx_wx_set_retry,
+-//TODO WX(SIOCGIWRETRY) = bcm43xx_wx_get_retry,
+- /* Encoding */
+- WX(SIOCSIWENCODE) = bcm43xx_wx_set_encoding,
+- WX(SIOCGIWENCODE) = bcm43xx_wx_get_encoding,
+- WX(SIOCSIWENCODEEXT) = bcm43xx_wx_set_encodingext,
+- WX(SIOCGIWENCODEEXT) = bcm43xx_wx_get_encodingext,
+- /* Power saving */
+-//TODO WX(SIOCSIWPOWER) = bcm43xx_wx_set_power,
+-//TODO WX(SIOCGIWPOWER) = bcm43xx_wx_get_power,
+- WX(SIOCSIWGENIE) = ieee80211softmac_wx_set_genie,
+- WX(SIOCGIWGENIE) = ieee80211softmac_wx_get_genie,
+- WX(SIOCSIWAUTH) = ieee80211_wx_set_auth,
+- WX(SIOCGIWAUTH) = ieee80211_wx_get_auth,
+-};
+-#undef WX
+-
+-static const iw_handler bcm43xx_priv_wx_handlers[] = {
+- /* Set Interference Mitigation Mode. */
+- bcm43xx_wx_set_interfmode,
+- /* Get Interference Mitigation Mode. */
+- bcm43xx_wx_get_interfmode,
+- /* Enable/Disable Short Preamble mode. */
+- bcm43xx_wx_set_shortpreamble,
+- /* Get Short Preamble mode. */
+- bcm43xx_wx_get_shortpreamble,
+- /* Enable/Disable Software Encryption mode */
+- bcm43xx_wx_set_swencryption,
+- /* Get Software Encryption mode */
+- bcm43xx_wx_get_swencryption,
+- /* Write SRPROM data. */
+- bcm43xx_wx_sprom_write,
+- /* Read SPROM data. */
+- bcm43xx_wx_sprom_read,
+-};
+-
+-#define PRIV_WX_SET_INTERFMODE (SIOCIWFIRSTPRIV + 0)
+-#define PRIV_WX_GET_INTERFMODE (SIOCIWFIRSTPRIV + 1)
+-#define PRIV_WX_SET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 2)
+-#define PRIV_WX_GET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 3)
+-#define PRIV_WX_SET_SWENCRYPTION (SIOCIWFIRSTPRIV + 4)
+-#define PRIV_WX_GET_SWENCRYPTION (SIOCIWFIRSTPRIV + 5)
+-#define PRIV_WX_SPROM_WRITE (SIOCIWFIRSTPRIV + 6)
+-#define PRIV_WX_SPROM_READ (SIOCIWFIRSTPRIV + 7)
+-
+-#define PRIV_WX_DUMMY(ioctl) \
+- { \
+- .cmd = (ioctl), \
+- .name = "__unused" \
+- }
+-
+-static const struct iw_priv_args bcm43xx_priv_wx_args[] = {
+- {
+- .cmd = PRIV_WX_SET_INTERFMODE,
+- .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+- .name = "set_interfmode",
+- },
+- {
+- .cmd = PRIV_WX_GET_INTERFMODE,
+- .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
+- .name = "get_interfmode",
+- },
+- {
+- .cmd = PRIV_WX_SET_SHORTPREAMBLE,
+- .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+- .name = "set_shortpreamb",
+- },
+- {
+- .cmd = PRIV_WX_GET_SHORTPREAMBLE,
+- .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
+- .name = "get_shortpreamb",
+- },
+- {
+- .cmd = PRIV_WX_SET_SWENCRYPTION,
+- .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+- .name = "set_swencrypt",
+- },
+- {
+- .cmd = PRIV_WX_GET_SWENCRYPTION,
+- .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
+- .name = "get_swencrypt",
+- },
+- {
+- .cmd = PRIV_WX_SPROM_WRITE,
+- .set_args = IW_PRIV_TYPE_CHAR | SPROM_BUFFERSIZE,
+- .name = "write_sprom",
+- },
+- {
+- .cmd = PRIV_WX_SPROM_READ,
+- .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | SPROM_BUFFERSIZE,
+- .name = "read_sprom",
+- },
+-};
+-
+-const struct iw_handler_def bcm43xx_wx_handlers_def = {
+- .standard = bcm43xx_wx_handlers,
+- .num_standard = ARRAY_SIZE(bcm43xx_wx_handlers),
+- .num_private = ARRAY_SIZE(bcm43xx_priv_wx_handlers),
+- .num_private_args = ARRAY_SIZE(bcm43xx_priv_wx_args),
+- .private = bcm43xx_priv_wx_handlers,
+- .private_args = bcm43xx_priv_wx_args,
+- .get_wireless_stats = bcm43xx_get_wireless_stats,
+-};
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.h b/drivers/net/wireless/bcm43xx/bcm43xx_wx.h
+deleted file mode 100644
+index 1f29ff3..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.h
++++ /dev/null
+@@ -1,36 +0,0 @@
+-/*
+-
+- Broadcom BCM43xx wireless driver
+-
+- Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+- Stefano Brivio <st3 at riseup.net>
+- Michael Buesch <mbuesch at freenet.de>
+- Danny van Dyk <kugelfang at gentoo.org>
+- Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+- Some parts of the code in this file are derived from the ipw2200
+- driver Copyright(c) 2003 - 2004 Intel Corporation.
+-
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; 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; see the file COPYING. If not, write to
+- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+- Boston, MA 02110-1301, USA.
+-
+-*/
+-
+-#ifndef BCM43xx_WX_H_
+-#define BCM43xx_WX_H_
+-
+-extern const struct iw_handler_def bcm43xx_wx_handlers_def;
+-
+-#endif /* BCM43xx_WX_H_ */
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
+deleted file mode 100644
+index f79fe11..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
++++ /dev/null
+@@ -1,565 +0,0 @@
+-/*
+-
+- Broadcom BCM43xx wireless driver
+-
+- Transmission (TX/RX) related functions.
+-
+- Copyright (c) 2005 Martin Langer <martin-langer at gmx.de>,
+- Stefano Brivio <st3 at riseup.net>
+- Michael Buesch <mbuesch at freenet.de>
+- Danny van Dyk <kugelfang at gentoo.org>
+- Andreas Jaggi <andreas.jaggi at waterwave.ch>
+-
+- 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; see the file COPYING. If not, write to
+- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+- Boston, MA 02110-1301, USA.
+-
+-*/
+-
+-#include "bcm43xx_xmit.h"
+-
+-#include <linux/etherdevice.h>
+-
+-
+-/* Extract the bitrate out of a CCK PLCP header. */
+-static u8 bcm43xx_plcp_get_bitrate_cck(struct bcm43xx_plcp_hdr4 *plcp)
+-{
+- switch (plcp->raw[0]) {
+- case 0x0A:
+- return IEEE80211_CCK_RATE_1MB;
+- case 0x14:
+- return IEEE80211_CCK_RATE_2MB;
+- case 0x37:
+- return IEEE80211_CCK_RATE_5MB;
+- case 0x6E:
+- return IEEE80211_CCK_RATE_11MB;
+- }
+- assert(0);
+- return 0;
+-}
+-
+-/* Extract the bitrate out of an OFDM PLCP header. */
+-static u8 bcm43xx_plcp_get_bitrate_ofdm(struct bcm43xx_plcp_hdr4 *plcp)
+-{
+- switch (plcp->raw[0] & 0xF) {
+- case 0xB:
+- return IEEE80211_OFDM_RATE_6MB;
+- case 0xF:
+- return IEEE80211_OFDM_RATE_9MB;
+- case 0xA:
+- return IEEE80211_OFDM_RATE_12MB;
+- case 0xE:
+- return IEEE80211_OFDM_RATE_18MB;
+- case 0x9:
+- return IEEE80211_OFDM_RATE_24MB;
+- case 0xD:
+- return IEEE80211_OFDM_RATE_36MB;
+- case 0x8:
+- return IEEE80211_OFDM_RATE_48MB;
+- case 0xC:
+- return IEEE80211_OFDM_RATE_54MB;
+- }
+- assert(0);
+- return 0;
+-}
+-
+-u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate)
+-{
+- switch (bitrate) {
+- case IEEE80211_CCK_RATE_1MB:
+- return 0x0A;
+- case IEEE80211_CCK_RATE_2MB:
+- return 0x14;
+- case IEEE80211_CCK_RATE_5MB:
+- return 0x37;
+- case IEEE80211_CCK_RATE_11MB:
+- return 0x6E;
+- }
+- assert(0);
+- return 0;
+-}
+-
+-u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate)
+-{
+- switch (bitrate) {
+- case IEEE80211_OFDM_RATE_6MB:
+- return 0xB;
+- case IEEE80211_OFDM_RATE_9MB:
+- return 0xF;
+- case IEEE80211_OFDM_RATE_12MB:
+- return 0xA;
+- case IEEE80211_OFDM_RATE_18MB:
+- return 0xE;
+- case IEEE80211_OFDM_RATE_24MB:
+- return 0x9;
+- case IEEE80211_OFDM_RATE_36MB:
+- return 0xD;
+- case IEEE80211_OFDM_RATE_48MB:
+- return 0x8;
+- case IEEE80211_OFDM_RATE_54MB:
+- return 0xC;
+- }
+- assert(0);
+- return 0;
+-}
+-
+-static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp,
+- const u16 octets, const u8 bitrate,
+- const int ofdm_modulation)
+-{
+- __le32 *data = &(plcp->data);
+- __u8 *raw = plcp->raw;
+-
+- if (ofdm_modulation) {
+- u32 val = bcm43xx_plcp_get_ratecode_ofdm(bitrate);
+- assert(!(octets & 0xF000));
+- val |= (octets << 5);
+- *data = cpu_to_le32(val);
+- } else {
+- u32 plen;
+-
+- plen = octets * 16 / bitrate;
+- if ((octets * 16 % bitrate) > 0) {
+- plen++;
+- if ((bitrate == IEEE80211_CCK_RATE_11MB)
+- && ((octets * 8 % 11) < 4)) {
+- raw[1] = 0x84;
+- } else
+- raw[1] = 0x04;
+- } else
+- raw[1] = 0x04;
+- *data |= cpu_to_le32(plen << 16);
+- raw[0] = bcm43xx_plcp_get_ratecode_cck(bitrate);
+- }
+-}
+-
+-static u8 bcm43xx_calc_fallback_rate(u8 bitrate)
+-{
+- switch (bitrate) {
+- case IEEE80211_CCK_RATE_1MB:
+- return IEEE80211_CCK_RATE_1MB;
+- case IEEE80211_CCK_RATE_2MB:
+- return IEEE80211_CCK_RATE_1MB;
+- case IEEE80211_CCK_RATE_5MB:
+- return IEEE80211_CCK_RATE_2MB;
+- case IEEE80211_CCK_RATE_11MB:
+- return IEEE80211_CCK_RATE_5MB;
+- case IEEE80211_OFDM_RATE_6MB:
+- return IEEE80211_CCK_RATE_5MB;
+- case IEEE80211_OFDM_RATE_9MB:
+- return IEEE80211_OFDM_RATE_6MB;
+- case IEEE80211_OFDM_RATE_12MB:
+- return IEEE80211_OFDM_RATE_9MB;
+- case IEEE80211_OFDM_RATE_18MB:
+- return IEEE80211_OFDM_RATE_12MB;
+- case IEEE80211_OFDM_RATE_24MB:
+- return IEEE80211_OFDM_RATE_18MB;
+- case IEEE80211_OFDM_RATE_36MB:
+- return IEEE80211_OFDM_RATE_24MB;
+- case IEEE80211_OFDM_RATE_48MB:
+- return IEEE80211_OFDM_RATE_36MB;
+- case IEEE80211_OFDM_RATE_54MB:
+- return IEEE80211_OFDM_RATE_48MB;
+- }
+- assert(0);
+- return 0;
+-}
+-
+-static
+-__le16 bcm43xx_calc_duration_id(const struct ieee80211_hdr *wireless_header,
+- u8 bitrate)
+-{
+- const u16 frame_ctl = le16_to_cpu(wireless_header->frame_ctl);
+- __le16 duration_id = wireless_header->duration_id;
+-
+- switch (WLAN_FC_GET_TYPE(frame_ctl)) {
+- case IEEE80211_FTYPE_DATA:
+- case IEEE80211_FTYPE_MGMT:
+- //TODO: Steal the code from ieee80211, once it is completed there.
+- break;
+- case IEEE80211_FTYPE_CTL:
+- /* Use the original duration/id. */
+- break;
+- default:
+- assert(0);
+- }
+-
+- return duration_id;
+-}
+-
+-static inline
+-u16 ceiling_div(u16 dividend, u16 divisor)
+-{
+- return ((dividend + divisor - 1) / divisor);
+-}
+-
+-static void bcm43xx_generate_rts(const struct bcm43xx_phyinfo *phy,
+- struct bcm43xx_txhdr *txhdr,
+- u16 *flags,
+- u8 bitrate,
+- const struct ieee80211_hdr_4addr *wlhdr)
+-{
+- u16 fctl;
+- u16 dur;
+- u8 fallback_bitrate;
+- int ofdm_modulation;
+- int fallback_ofdm_modulation;
+-// u8 *sa, *da;
+- u16 flen;
+-
+-//FIXME sa = ieee80211_get_SA((struct ieee80211_hdr *)wlhdr);
+-//FIXME da = ieee80211_get_DA((struct ieee80211_hdr *)wlhdr);
+- fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate);
+- ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
+- fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));
+-
+- flen = sizeof(u16) + sizeof(u16) + ETH_ALEN + ETH_ALEN + IEEE80211_FCS_LEN,
+- bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_plcp),
+- flen, bitrate,
+- !ieee80211_is_cck_rate(bitrate));
+- bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_fallback_plcp),
+- flen, fallback_bitrate,
+- !ieee80211_is_cck_rate(fallback_bitrate));
+- fctl = IEEE80211_FTYPE_CTL;
+- fctl |= IEEE80211_STYPE_RTS;
+- dur = le16_to_cpu(wlhdr->duration_id);
+-/*FIXME: should we test for dur==0 here and let it unmodified in this case?
+- * The following assert checks for this case...
+- */
+-assert(dur);
+-/*FIXME: The duration calculation is not really correct.
+- * I am not 100% sure which bitrate to use. We use the RTS rate here,
+- * but this is likely to be wrong.
+- */
+- if (phy->type == BCM43xx_PHYTYPE_A) {
+- /* Three times SIFS */
+- dur += 16 * 3;
+- /* Add ACK duration. */
+- dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10,
+- bitrate * 4);
+- /* Add CTS duration. */
+- dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10,
+- bitrate * 4);
+- } else {
+- /* Three times SIFS */
+- dur += 10 * 3;
+- /* Add ACK duration. */
+- dur += ceiling_div(8 * (14 /*bytes*/) * 10,
+- bitrate);
+- /* Add CTS duration. */
+- dur += ceiling_div(8 * (14 /*bytes*/) * 10,
+- bitrate);
+- }
+-
+- txhdr->rts_cts_frame_control = cpu_to_le16(fctl);
+- txhdr->rts_cts_dur = cpu_to_le16(dur);
+-//printk(BCM43xx_MACFMT " " BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(wlhdr->addr1), BCM43xx_MACARG(wlhdr->addr2), BCM43xx_MACARG(wlhdr->addr3));
+-//printk(BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(sa), BCM43xx_MACARG(da));
+- memcpy(txhdr->rts_cts_mac1, wlhdr->addr1, ETH_ALEN);//FIXME!
+-// memcpy(txhdr->rts_cts_mac2, sa, ETH_ALEN);
+-
+- *flags |= BCM43xx_TXHDRFLAG_RTSCTS;
+- *flags |= BCM43xx_TXHDRFLAG_RTS;
+- if (ofdm_modulation)
+- *flags |= BCM43xx_TXHDRFLAG_RTSCTS_OFDM;
+- if (fallback_ofdm_modulation)
+- *flags |= BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM;
+-}
+-
+-void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
+- struct bcm43xx_txhdr *txhdr,
+- const unsigned char *fragment_data,
+- const unsigned int fragment_len,
+- const int is_first_fragment,
+- const u16 cookie)
+-{
+- const struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- const struct ieee80211_hdr_4addr *wireless_header = (const struct ieee80211_hdr_4addr *)fragment_data;
+- const struct ieee80211_security *secinfo = &bcm->ieee->sec;
+- u8 bitrate;
+- u8 fallback_bitrate;
+- int ofdm_modulation;
+- int fallback_ofdm_modulation;
+- u16 plcp_fragment_len = fragment_len;
+- u16 flags = 0;
+- u16 control = 0;
+- u16 wsec_rate = 0;
+- u16 encrypt_frame;
+- const u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(wireless_header->frame_ctl));
+- const int is_mgt = (ftype == IEEE80211_FTYPE_MGMT);
+-
+- /* Now construct the TX header. */
+- memset(txhdr, 0, sizeof(*txhdr));
+-
+- bitrate = ieee80211softmac_suggest_txrate(bcm->softmac,
+- is_multicast_ether_addr(wireless_header->addr1), is_mgt);
+- ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
+- fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate);
+- fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));
+-
+- /* Set Frame Control from 80211 header. */
+- txhdr->frame_control = wireless_header->frame_ctl;
+- /* Copy address1 from 80211 header. */
+- memcpy(txhdr->mac1, wireless_header->addr1, 6);
+- /* Set the fallback duration ID. */
+- txhdr->fallback_dur_id = bcm43xx_calc_duration_id((const struct ieee80211_hdr *)wireless_header,
+- fallback_bitrate);
+- /* Set the cookie (used as driver internal ID for the frame) */
+- txhdr->cookie = cpu_to_le16(cookie);
+-
+- /* Hardware appends FCS. */
+- plcp_fragment_len += IEEE80211_FCS_LEN;
+-
+- /* Hardware encryption. */
+- encrypt_frame = le16_to_cpup(&wireless_header->frame_ctl) & IEEE80211_FCTL_PROTECTED;
+- if (encrypt_frame && !bcm->ieee->host_encrypt) {
+- const struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)wireless_header;
+- memcpy(txhdr->wep_iv, hdr->payload, 4);
+- /* Hardware appends ICV. */
+- plcp_fragment_len += 4;
+-
+- wsec_rate |= (bcm->key[secinfo->active_key].algorithm << BCM43xx_TXHDR_WSEC_ALGO_SHIFT)
+- & BCM43xx_TXHDR_WSEC_ALGO_MASK;
+- wsec_rate |= (secinfo->active_key << BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT)
+- & BCM43xx_TXHDR_WSEC_KEYINDEX_MASK;
+- }
+-
+- /* Generate the PLCP header and the fallback PLCP header. */
+- bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp),
+- plcp_fragment_len,
+- bitrate, ofdm_modulation);
+- bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, plcp_fragment_len,
+- fallback_bitrate, fallback_ofdm_modulation);
+-
+- /* Set the CONTROL field */
+- if (ofdm_modulation)
+- control |= BCM43xx_TXHDRCTL_OFDM;
+- if (bcm->short_preamble) //FIXME: could be the other way around, please test
+- control |= BCM43xx_TXHDRCTL_SHORT_PREAMBLE;
+- control |= (phy->antenna_diversity << BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT)
+- & BCM43xx_TXHDRCTL_ANTENNADIV_MASK;
+-
+- /* Set the FLAGS field */
+- if (!is_multicast_ether_addr(wireless_header->addr1) &&
+- !is_broadcast_ether_addr(wireless_header->addr1))
+- flags |= BCM43xx_TXHDRFLAG_EXPECTACK;
+- if (1 /* FIXME: PS poll?? */)
+- flags |= 0x10; // FIXME: unknown meaning.
+- if (fallback_ofdm_modulation)
+- flags |= BCM43xx_TXHDRFLAG_FALLBACKOFDM;
+- if (is_first_fragment)
+- flags |= BCM43xx_TXHDRFLAG_FIRSTFRAGMENT;
+-
+- /* Set WSEC/RATE field */
+- wsec_rate |= (txhdr->plcp.raw[0] << BCM43xx_TXHDR_RATE_SHIFT)
+- & BCM43xx_TXHDR_RATE_MASK;
+-
+- /* Generate the RTS/CTS packet, if required. */
+- /* FIXME: We should first try with CTS-to-self,
+- * if we are on 80211g. If we get too many
+- * failures (hidden nodes), we should switch back to RTS/CTS.
+- */
+- if (0/*FIXME txctl->use_rts_cts*/) {
+- bcm43xx_generate_rts(phy, txhdr, &flags,
+- 0/*FIXME txctl->rts_cts_rate*/,
+- wireless_header);
+- }
+-
+- txhdr->flags = cpu_to_le16(flags);
+- txhdr->control = cpu_to_le16(control);
+- txhdr->wsec_rate = cpu_to_le16(wsec_rate);
+-}
+-
+-static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm,
+- u8 in_rssi, int ofdm,
+- int adjust_2053, int adjust_2050)
+-{
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- s32 tmp;
+-
+- switch (radio->version) {
+- case 0x2050:
+- if (ofdm) {
+- tmp = in_rssi;
+- if (tmp > 127)
+- tmp -= 256;
+- tmp *= 73;
+- tmp /= 64;
+- if (adjust_2050)
+- tmp += 25;
+- else
+- tmp -= 3;
+- } else {
+- if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
+- if (in_rssi > 63)
+- in_rssi = 63;
+- tmp = radio->nrssi_lt[in_rssi];
+- tmp = 31 - tmp;
+- tmp *= -131;
+- tmp /= 128;
+- tmp -= 57;
+- } else {
+- tmp = in_rssi;
+- tmp = 31 - tmp;
+- tmp *= -149;
+- tmp /= 128;
+- tmp -= 68;
+- }
+- if (phy->type == BCM43xx_PHYTYPE_G &&
+- adjust_2050)
+- tmp += 25;
+- }
+- break;
+- case 0x2060:
+- if (in_rssi > 127)
+- tmp = in_rssi - 256;
+- else
+- tmp = in_rssi;
+- break;
+- default:
+- tmp = in_rssi;
+- tmp -= 11;
+- tmp *= 103;
+- tmp /= 64;
+- if (adjust_2053)
+- tmp -= 109;
+- else
+- tmp -= 83;
+- }
+-
+- return (s8)tmp;
+-}
+-
+-//TODO
+-#if 0
+-static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm,
+- u8 in_rssi)
+-{
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- s8 ret;
+-
+- if (phy->type == BCM43xx_PHYTYPE_A) {
+- //TODO: Incomplete specs.
+- ret = 0;
+- } else
+- ret = bcm43xx_rssi_postprocess(bcm, in_rssi, 0, 1, 1);
+-
+- return ret;
+-}
+-#endif
+-
+-int bcm43xx_rx(struct bcm43xx_private *bcm,
+- struct sk_buff *skb,
+- struct bcm43xx_rxhdr *rxhdr)
+-{
+- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
+- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+- struct bcm43xx_plcp_hdr4 *plcp;
+- struct ieee80211_rx_stats stats;
+- struct ieee80211_hdr_4addr *wlhdr;
+- u16 frame_ctl;
+- int is_packet_for_us = 0;
+- int err = -EINVAL;
+- const u16 rxflags1 = le16_to_cpu(rxhdr->flags1);
+- const u16 rxflags2 = le16_to_cpu(rxhdr->flags2);
+- const u16 rxflags3 = le16_to_cpu(rxhdr->flags3);
+- const int is_ofdm = !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_OFDM);
+-
+- if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) {
+- plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data + 2);
+- /* Skip two unknown bytes and the PLCP header. */
+- skb_pull(skb, 2 + sizeof(struct bcm43xx_plcp_hdr6));
+- } else {
+- plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data);
+- /* Skip the PLCP header. */
+- skb_pull(skb, sizeof(struct bcm43xx_plcp_hdr6));
+- }
+- /* The SKB contains the PAYLOAD (wireless header + data)
+- * at this point. The FCS at the end is stripped.
+- */
+-
+- memset(&stats, 0, sizeof(stats));
+- stats.mac_time = le16_to_cpu(rxhdr->mactime);
+- stats.rssi = rxhdr->rssi;
+- stats.signal = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
+- !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ),
+- !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ));
+- stats.noise = bcm->stats.noise;
+- if (is_ofdm)
+- stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp);
+- else
+- stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp);
+- stats.received_channel = radio->channel;
+- stats.mask = IEEE80211_STATMASK_SIGNAL |
+- IEEE80211_STATMASK_NOISE |
+- IEEE80211_STATMASK_RATE |
+- IEEE80211_STATMASK_RSSI;
+- if (phy->type == BCM43xx_PHYTYPE_A)
+- stats.freq = IEEE80211_52GHZ_BAND;
+- else
+- stats.freq = IEEE80211_24GHZ_BAND;
+- stats.len = skb->len;
+-
+- bcm->stats.last_rx = jiffies;
+- if (bcm->ieee->iw_mode == IW_MODE_MONITOR) {
+- err = ieee80211_rx(bcm->ieee, skb, &stats);
+- return (err == 0) ? -EINVAL : 0;
+- }
+-
+- wlhdr = (struct ieee80211_hdr_4addr *)(skb->data);
+-
+- switch (bcm->ieee->iw_mode) {
+- case IW_MODE_ADHOC:
+- if (memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
+- memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
+- is_broadcast_ether_addr(wlhdr->addr1) ||
+- is_multicast_ether_addr(wlhdr->addr1) ||
+- bcm->net_dev->flags & IFF_PROMISC)
+- is_packet_for_us = 1;
+- break;
+- case IW_MODE_INFRA:
+- default:
+- /* When receiving multicast or broadcast packets, filter out
+- the packets we send ourself; we shouldn't see those */
+- if (memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
+- memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
+- (memcmp(wlhdr->addr3, bcm->net_dev->dev_addr, ETH_ALEN) &&
+- (is_broadcast_ether_addr(wlhdr->addr1) ||
+- is_multicast_ether_addr(wlhdr->addr1) ||
+- bcm->net_dev->flags & IFF_PROMISC)))
+- is_packet_for_us = 1;
+- break;
+- }
+-
+- frame_ctl = le16_to_cpu(wlhdr->frame_ctl);
+- switch (WLAN_FC_GET_TYPE(frame_ctl)) {
+- case IEEE80211_FTYPE_MGMT:
+- ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats);
+- break;
+- case IEEE80211_FTYPE_DATA:
+- if (is_packet_for_us) {
+- err = ieee80211_rx(bcm->ieee, skb, &stats);
+- err = (err == 0) ? -EINVAL : 0;
+- }
+- break;
+- case IEEE80211_FTYPE_CTL:
+- break;
+- default:
+- assert(0);
+- return -EINVAL;
+- }
+-
+- return err;
+-}
+diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
+deleted file mode 100644
+index 47c135a..0000000
+--- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
++++ /dev/null
+@@ -1,150 +0,0 @@
+-#ifndef BCM43xx_XMIT_H_
+-#define BCM43xx_XMIT_H_
+-
+-#include "bcm43xx_main.h"
+-
+-
+-#define _bcm43xx_declare_plcp_hdr(size) \
+- struct bcm43xx_plcp_hdr##size { \
+- union { \
+- __le32 data; \
+- __u8 raw[size]; \
+- } __attribute__((__packed__)); \
+- } __attribute__((__packed__))
+-
+-/* struct bcm43xx_plcp_hdr4 */
+-_bcm43xx_declare_plcp_hdr(4);
+-/* struct bcm43xx_plcp_hdr6 */
+-_bcm43xx_declare_plcp_hdr(6);
+-
+-#undef _bcm43xx_declare_plcp_hdr
+-
+-/* Device specific TX header. To be prepended to TX frames. */
+-struct bcm43xx_txhdr {
+- union {
+- struct {
+- __le16 flags;
+- __le16 wsec_rate;
+- __le16 frame_control;
+- u16 unknown_zeroed_0;
+- __le16 control;
+- u8 wep_iv[10];
+- u8 unknown_wsec_tkip_data[3]; //FIXME
+- PAD_BYTES(3);
+- u8 mac1[6];
+- u16 unknown_zeroed_1;
+- struct bcm43xx_plcp_hdr4 rts_cts_fallback_plcp;
+- __le16 rts_cts_dur_fallback;
+- struct bcm43xx_plcp_hdr4 fallback_plcp;
+- __le16 fallback_dur_id;
+- PAD_BYTES(2);
+- __le16 cookie;
+- __le16 unknown_scb_stuff; //FIXME
+- struct bcm43xx_plcp_hdr6 rts_cts_plcp;
+- __le16 rts_cts_frame_control;
+- __le16 rts_cts_dur;
+- u8 rts_cts_mac1[6];
+- u8 rts_cts_mac2[6];
+- PAD_BYTES(2);
+- struct bcm43xx_plcp_hdr6 plcp;
+- } __attribute__((__packed__));
+- u8 raw[82];
+- } __attribute__((__packed__));
+-} __attribute__((__packed__));
+-
+-/* Values/Masks for the device TX header */
+-#define BCM43xx_TXHDRFLAG_EXPECTACK 0x0001
+-#define BCM43xx_TXHDRFLAG_RTSCTS 0x0002
+-#define BCM43xx_TXHDRFLAG_RTS 0x0004
+-#define BCM43xx_TXHDRFLAG_FIRSTFRAGMENT 0x0008
+-#define BCM43xx_TXHDRFLAG_DESTPSMODE 0x0020
+-#define BCM43xx_TXHDRFLAG_RTSCTS_OFDM 0x0080
+-#define BCM43xx_TXHDRFLAG_FALLBACKOFDM 0x0100
+-#define BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM 0x0200
+-#define BCM43xx_TXHDRFLAG_CTS 0x0400
+-#define BCM43xx_TXHDRFLAG_FRAMEBURST 0x0800
+-
+-#define BCM43xx_TXHDRCTL_OFDM 0x0001
+-#define BCM43xx_TXHDRCTL_SHORT_PREAMBLE 0x0010
+-#define BCM43xx_TXHDRCTL_ANTENNADIV_MASK 0x0030
+-#define BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT 8
+-
+-#define BCM43xx_TXHDR_RATE_MASK 0x0F00
+-#define BCM43xx_TXHDR_RATE_SHIFT 8
+-#define BCM43xx_TXHDR_RTSRATE_MASK 0xF000
+-#define BCM43xx_TXHDR_RTSRATE_SHIFT 12
+-#define BCM43xx_TXHDR_WSEC_KEYINDEX_MASK 0x00F0
+-#define BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT 4
+-#define BCM43xx_TXHDR_WSEC_ALGO_MASK 0x0003
+-#define BCM43xx_TXHDR_WSEC_ALGO_SHIFT 0
+-
+-void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
+- struct bcm43xx_txhdr *txhdr,
+- const unsigned char *fragment_data,
+- const unsigned int fragment_len,
+- const int is_first_fragment,
+- const u16 cookie);
+-
+-/* RX header as received from the hardware. */
+-struct bcm43xx_rxhdr {
+- /* Frame Length. Must be generated explicitly in PIO mode. */
+- __le16 frame_length;
+- PAD_BYTES(2);
+- /* Flags field 1 */
+- __le16 flags1;
+- u8 rssi;
+- u8 signal_quality;
+- PAD_BYTES(2);
+- /* Flags field 3 */
+- __le16 flags3;
+- /* Flags field 2 */
+- __le16 flags2;
+- /* Lower 16bits of the TSF at the time the frame started. */
+- __le16 mactime;
+- PAD_BYTES(14);
+-} __attribute__((__packed__));
+-
+-#define BCM43xx_RXHDR_FLAGS1_OFDM (1 << 0)
+-/*#define BCM43xx_RXHDR_FLAGS1_SIGNAL??? (1 << 3) FIXME */
+-#define BCM43xx_RXHDR_FLAGS1_SHORTPREAMBLE (1 << 7)
+-#define BCM43xx_RXHDR_FLAGS1_2053RSSIADJ (1 << 14)
+-
+-#define BCM43xx_RXHDR_FLAGS2_INVALIDFRAME (1 << 0)
+-#define BCM43xx_RXHDR_FLAGS2_TYPE2FRAME (1 << 2)
+-/*FIXME: WEP related flags */
+-
+-#define BCM43xx_RXHDR_FLAGS3_2050RSSIADJ (1 << 10)
+-
+-/* Transmit Status as received from the hardware. */
+-struct bcm43xx_hwxmitstatus {
+- PAD_BYTES(4);
+- __le16 cookie;
+- u8 flags;
+- u8 cnt1:4,
+- cnt2:4;
+- PAD_BYTES(2);
+- __le16 seq;
+- __le16 unknown; //FIXME
+-} __attribute__((__packed__));
+-
+-/* Transmit Status in CPU byteorder. */
+-struct bcm43xx_xmitstatus {
+- u16 cookie;
+- u8 flags;
+- u8 cnt1:4,
+- cnt2:4;
+- u16 seq;
+- u16 unknown; //FIXME
+-};
+-
+-#define BCM43xx_TXSTAT_FLAG_AMPDU 0x10
+-#define BCM43xx_TXSTAT_FLAG_INTER 0x20
+-
+-u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate);
+-u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate);
+-
+-int bcm43xx_rx(struct bcm43xx_private *bcm,
+- struct sk_buff *skb,
+- struct bcm43xx_rxhdr *rxhdr);
+-
+-#endif /* BCM43xx_XMIT_H_ */
+diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
+index 98d6ff6..fa87c5c 100644
+--- a/drivers/net/wireless/ipw2200.c
++++ b/drivers/net/wireless/ipw2200.c
+@@ -4495,9 +4495,9 @@ static void ipw_rx_notification(struct ipw_priv *priv,
+ priv->
+ essid_len),
+ print_mac(mac, priv->bssid),
+- ntohs(auth->status),
++ le16_to_cpu(auth->status),
+ ipw_get_status_code
+- (ntohs
++ (le16_to_cpu
+ (auth->status)));
+
+ priv->status &=
+@@ -4532,9 +4532,9 @@ static void ipw_rx_notification(struct ipw_priv *priv,
+ IPW_DL_STATE |
+ IPW_DL_ASSOC,
+ "association failed (0x%04X): %s\n",
+- ntohs(resp->status),
++ le16_to_cpu(resp->status),
+ ipw_get_status_code
+- (ntohs
++ (le16_to_cpu
+ (resp->status)));
+ }
+
+@@ -4591,8 +4591,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
+ IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
+ IPW_DL_ASSOC,
+ "authentication failed (0x%04X): %s\n",
+- ntohs(auth->status),
+- ipw_get_status_code(ntohs
++ le16_to_cpu(auth->status),
++ ipw_get_status_code(le16_to_cpu
+ (auth->
+ status)));
+ }
+@@ -10350,9 +10350,7 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
+ remaining_bytes,
+ PCI_DMA_TODEVICE));
+
+- tfd->u.data.num_chunks =
+- cpu_to_le32(le32_to_cpu(tfd->u.data.num_chunks) +
+- 1);
++ le32_add_cpu(&tfd->u.data.num_chunks, 1);
+ }
+ }
+
+diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h
+index fdc187e..cd3295b 100644
+--- a/drivers/net/wireless/ipw2200.h
++++ b/drivers/net/wireless/ipw2200.h
+@@ -385,73 +385,73 @@ struct clx2_queue {
+ dma_addr_t dma_addr; /**< physical addr for BD's */
+ int low_mark; /**< low watermark, resume queue if free space more than this */
+ int high_mark; /**< high watermark, stop queue if free space less than this */
+-} __attribute__ ((packed));
++} __attribute__ ((packed)); /* XXX */
+
+ struct machdr32 {
+ __le16 frame_ctl;
+- u16 duration; // watch out for endians!
++ __le16 duration; // watch out for endians!
+ u8 addr1[MACADRR_BYTE_LEN];
+ u8 addr2[MACADRR_BYTE_LEN];
+ u8 addr3[MACADRR_BYTE_LEN];
+- u16 seq_ctrl; // more endians!
++ __le16 seq_ctrl; // more endians!
+ u8 addr4[MACADRR_BYTE_LEN];
+ __le16 qos_ctrl;
+ } __attribute__ ((packed));
+
+ struct machdr30 {
+ __le16 frame_ctl;
+- u16 duration; // watch out for endians!
++ __le16 duration; // watch out for endians!
+ u8 addr1[MACADRR_BYTE_LEN];
+ u8 addr2[MACADRR_BYTE_LEN];
+ u8 addr3[MACADRR_BYTE_LEN];
+- u16 seq_ctrl; // more endians!
++ __le16 seq_ctrl; // more endians!
+ u8 addr4[MACADRR_BYTE_LEN];
+ } __attribute__ ((packed));
+
+ struct machdr26 {
+ __le16 frame_ctl;
+- u16 duration; // watch out for endians!
++ __le16 duration; // watch out for endians!
+ u8 addr1[MACADRR_BYTE_LEN];
+ u8 addr2[MACADRR_BYTE_LEN];
+ u8 addr3[MACADRR_BYTE_LEN];
+- u16 seq_ctrl; // more endians!
++ __le16 seq_ctrl; // more endians!
+ __le16 qos_ctrl;
+ } __attribute__ ((packed));
+
+ struct machdr24 {
+ __le16 frame_ctl;
+- u16 duration; // watch out for endians!
++ __le16 duration; // watch out for endians!
+ u8 addr1[MACADRR_BYTE_LEN];
+ u8 addr2[MACADRR_BYTE_LEN];
+ u8 addr3[MACADRR_BYTE_LEN];
+- u16 seq_ctrl; // more endians!
++ __le16 seq_ctrl; // more endians!
+ } __attribute__ ((packed));
+
+ // TX TFD with 32 byte MAC Header
+ struct tx_tfd_32 {
+ struct machdr32 mchdr; // 32
+- u32 uivplaceholder[2]; // 8
++ __le32 uivplaceholder[2]; // 8
+ } __attribute__ ((packed));
+
+ // TX TFD with 30 byte MAC Header
+ struct tx_tfd_30 {
+ struct machdr30 mchdr; // 30
+ u8 reserved[2]; // 2
+- u32 uivplaceholder[2]; // 8
++ __le32 uivplaceholder[2]; // 8
+ } __attribute__ ((packed));
+
+ // tx tfd with 26 byte mac header
+ struct tx_tfd_26 {
+ struct machdr26 mchdr; // 26
+ u8 reserved1[2]; // 2
+- u32 uivplaceholder[2]; // 8
++ __le32 uivplaceholder[2]; // 8
+ u8 reserved2[4]; // 4
+ } __attribute__ ((packed));
+
+ // tx tfd with 24 byte mac header
+ struct tx_tfd_24 {
+ struct machdr24 mchdr; // 24
+- u32 uivplaceholder[2]; // 8
++ __le32 uivplaceholder[2]; // 8
+ u8 reserved[8]; // 8
+ } __attribute__ ((packed));
+
+@@ -460,7 +460,7 @@ struct tx_tfd_24 {
+ struct tfd_command {
+ u8 index;
+ u8 length;
+- u16 reserved;
++ __le16 reserved;
+ u8 payload[0];
+ } __attribute__ ((packed));
+
+@@ -562,27 +562,27 @@ struct rate_histogram {
+ struct ipw_cmd_stats {
+ u8 cmd_id;
+ u8 seq_num;
+- u16 good_sfd;
+- u16 bad_plcp;
+- u16 wrong_bssid;
+- u16 valid_mpdu;
+- u16 bad_mac_header;
+- u16 reserved_frame_types;
+- u16 rx_ina;
+- u16 bad_crc32;
+- u16 invalid_cts;
+- u16 invalid_acks;
+- u16 long_distance_ina_fina;
+- u16 dsp_silence_unreachable;
+- u16 accumulated_rssi;
+- u16 rx_ovfl_frame_tossed;
+- u16 rssi_silence_threshold;
+- u16 rx_ovfl_frame_supplied;
+- u16 last_rx_frame_signal;
+- u16 last_rx_frame_noise;
+- u16 rx_autodetec_no_ofdm;
+- u16 rx_autodetec_no_barker;
+- u16 reserved;
++ __le16 good_sfd;
++ __le16 bad_plcp;
++ __le16 wrong_bssid;
++ __le16 valid_mpdu;
++ __le16 bad_mac_header;
++ __le16 reserved_frame_types;
++ __le16 rx_ina;
++ __le16 bad_crc32;
++ __le16 invalid_cts;
++ __le16 invalid_acks;
++ __le16 long_distance_ina_fina;
++ __le16 dsp_silence_unreachable;
++ __le16 accumulated_rssi;
++ __le16 rx_ovfl_frame_tossed;
++ __le16 rssi_silence_threshold;
++ __le16 rx_ovfl_frame_supplied;
++ __le16 last_rx_frame_signal;
++ __le16 last_rx_frame_noise;
++ __le16 rx_autodetec_no_ofdm;
++ __le16 rx_autodetec_no_barker;
++ __le16 reserved;
+ } __attribute__ ((packed));
+
+ struct notif_channel_result {
+@@ -637,7 +637,7 @@ struct notif_association {
+ struct notif_authenticate {
+ u8 state;
+ struct machdr24 addr;
+- u16 status;
++ __le16 status;
+ } __attribute__ ((packed));
+
+ struct notif_calibration {
+@@ -732,14 +732,14 @@ struct ipw_rx_queue {
+ struct alive_command_responce {
+ u8 alive_command;
+ u8 sequence_number;
+- u16 software_revision;
++ __le16 software_revision;
+ u8 device_identifier;
+ u8 reserved1[5];
+- u16 reserved2;
+- u16 reserved3;
+- u16 clock_settle_time;
+- u16 powerup_settle_time;
+- u16 reserved4;
++ __le16 reserved2;
++ __le16 reserved3;
++ __le16 clock_settle_time;
++ __le16 powerup_settle_time;
++ __le16 reserved4;
+ u8 time_stamp[5]; /* month, day, year, hours, minutes */
+ u8 ucode_valid;
+ } __attribute__ ((packed));
+@@ -878,7 +878,11 @@ static inline void ipw_set_scan_type(struct ipw_scan_request_ext *scan,
+
+ struct ipw_associate {
+ u8 channel;
++#ifdef __LITTLE_ENDIAN_BITFIELD
+ u8 auth_type:4, auth_key:4;
++#else
++ u8 auth_key:4, auth_type:4;
++#endif
+ u8 assoc_type;
+ u8 reserved;
+ __le16 policy_support;
+@@ -918,12 +922,12 @@ struct ipw_frag_threshold {
+ struct ipw_retry_limit {
+ u8 short_retry_limit;
+ u8 long_retry_limit;
+- u16 reserved;
++ __le16 reserved;
+ } __attribute__ ((packed));
+
+ struct ipw_dino_config {
+- u32 dino_config_addr;
+- u16 dino_config_size;
++ __le32 dino_config_addr;
++ __le16 dino_config_size;
+ u8 dino_response;
+ u8 reserved;
+ } __attribute__ ((packed));
+@@ -998,7 +1002,7 @@ struct ipw_sensitivity_calib {
+ * - \a status contains status;
+ * - \a param filled with status parameters.
+ */
+-struct ipw_cmd {
++struct ipw_cmd { /* XXX */
+ u32 cmd; /**< Host command */
+ u32 status;/**< Status */
+ u32 status_len;
+@@ -1092,7 +1096,7 @@ struct ipw_ibss_seq {
+ struct list_head list;
+ };
+
+-struct ipw_error_elem {
++struct ipw_error_elem { /* XXX */
+ u32 desc;
+ u32 time;
+ u32 blink1;
+@@ -1102,13 +1106,13 @@ struct ipw_error_elem {
+ u32 data;
+ };
+
+-struct ipw_event {
++struct ipw_event { /* XXX */
+ u32 event;
+ u32 time;
+ u32 data;
+ } __attribute__ ((packed));
+
+-struct ipw_fw_error {
++struct ipw_fw_error { /* XXX */
+ unsigned long jiffies;
+ u32 status;
+ u32 config;
+@@ -1153,7 +1157,7 @@ struct ipw_prom_priv {
+ */
+ struct ipw_rt_hdr {
+ struct ieee80211_radiotap_header rt_hdr;
+- u64 rt_tsf; /* TSF */
++ u64 rt_tsf; /* TSF */ /* XXX */
+ u8 rt_flags; /* radiotap packet flags */
+ u8 rt_rate; /* rate in 500kb/s */
+ __le16 rt_channel; /* channel in mhz */
+@@ -1940,8 +1944,8 @@ enum {
+ #define IPW_MEM_FIXED_OVERRIDE (IPW_SHARED_LOWER_BOUND + 0x41C)
+
+ struct ipw_fixed_rate {
+- u16 tx_rates;
+- u16 reserved;
++ __le16 tx_rates;
++ __le16 reserved;
+ } __attribute__ ((packed));
+
+ #define IPW_INDIRECT_ADDR_MASK (~0x3ul)
+@@ -1951,12 +1955,12 @@ struct host_cmd {
+ u8 len;
+ u16 reserved;
+ u32 *param;
+-} __attribute__ ((packed));
++} __attribute__ ((packed)); /* XXX */
+
+ struct cmdlog_host_cmd {
+ u8 cmd;
+ u8 len;
+- u16 reserved;
++ __le16 reserved;
+ char param[124];
+ } __attribute__ ((packed));
+
+diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
+index b54ff71..c4e631d 100644
+--- a/drivers/net/wireless/iwlwifi/Kconfig
++++ b/drivers/net/wireless/iwlwifi/Kconfig
+@@ -1,7 +1,22 @@
++config IWLCORE
++ tristate "Intel Wireless Wifi Core"
++ depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
++
++config IWLWIFI_LEDS
++ bool
++ default n
++
++config IWLWIFI_RFKILL
++ boolean "IWLWIFI RF kill support"
++ depends on IWLCORE
++ select RFKILL
++ select RFKILL_INPUT
++
+ config IWL4965
+ tristate "Intel Wireless WiFi 4965AGN"
+ depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
+ select FW_LOADER
++ select IWLCORE
+ ---help---
+ Select to build the driver supporting the:
+
+@@ -24,21 +39,24 @@ config IWL4965
+ say M here and read <file:Documentation/kbuild/modules.txt>. The
+ module will be called iwl4965.ko.
+
+-config IWL4965_QOS
+- bool "Enable Wireless QoS in iwl4965 driver"
+- depends on IWL4965
+- ---help---
+- This option will enable wireless quality of service (QoS) for the
+- iwl4965 driver.
+-
+ config IWL4965_HT
+ bool "Enable 802.11n HT features in iwl4965 driver"
+ depends on EXPERIMENTAL
+- depends on IWL4965 && IWL4965_QOS
++ depends on IWL4965
+ ---help---
+ This option enables IEEE 802.11n High Throughput features
+ for the iwl4965 driver.
+
++config IWL4965_LEDS
++ bool "Enable LEDS features in iwl4965 driver"
++ depends on IWL4965
++ select MAC80211_LEDS
++ select LEDS_CLASS
++ select IWLWIFI_LEDS
++ ---help---
++ This option enables LEDS for the iwlwifi drivers
++
++
+ config IWL4965_SPECTRUM_MEASUREMENT
+ bool "Enable Spectrum Measurement in iwl4965 driver"
+ depends on IWL4965
+@@ -52,7 +70,7 @@ config IWL4965_SENSITIVITY
+ This option will enable sensitivity calibration for the iwl4965
+ driver.
+
+-config IWL4965_DEBUG
++config IWLWIFI_DEBUG
+ bool "Enable full debugging output in iwl4965 driver"
+ depends on IWL4965
+ ---help---
+@@ -78,6 +96,12 @@ config IWL4965_DEBUG
+ as the debug information can assist others in helping you resolve
+ any problems you may encounter.
+
++config IWLWIFI_DEBUGFS
++ bool "Iwlwifi debugfs support"
++ depends on IWLCORE && IWLWIFI_DEBUG && MAC80211_DEBUGFS
++ ---help---
++ Enable creation of debugfs files for the iwlwifi drivers.
++
+ config IWL3945
+ tristate "Intel PRO/Wireless 3945ABG/BG Network Connection"
+ depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
+@@ -104,19 +128,20 @@ config IWL3945
+ say M here and read <file:Documentation/kbuild/modules.txt>. The
+ module will be called iwl3945.ko.
+
+-config IWL3945_QOS
+- bool "Enable Wireless QoS in iwl3945 driver"
+- depends on IWL3945
+- ---help---
+- This option will enable wireless quality of service (QoS) for the
+- iwl3945 driver.
+-
+ config IWL3945_SPECTRUM_MEASUREMENT
+ bool "Enable Spectrum Measurement in iwl3945 drivers"
+ depends on IWL3945
+ ---help---
+ This option will enable spectrum measurement for the iwl3945 driver.
+
++config IWL3945_LEDS
++ bool "Enable LEDS features in iwl3945 driver"
++ depends on IWL3945
++ select MAC80211_LEDS
++ select LEDS_CLASS
++ ---help---
++ This option enables LEDS for the iwl3945 driver.
++
+ config IWL3945_DEBUG
+ bool "Enable full debugging output in iwl3945 driver"
+ depends on IWL3945
+diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
+index 3bbd383..ec6187b 100644
+--- a/drivers/net/wireless/iwlwifi/Makefile
++++ b/drivers/net/wireless/iwlwifi/Makefile
+@@ -1,5 +1,13 @@
++obj-$(CONFIG_IWLCORE) += iwlcore.o
++iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o
++iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
++iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o
++iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o
++
+ obj-$(CONFIG_IWL3945) += iwl3945.o
+-iwl3945-objs = iwl3945-base.o iwl-3945.o iwl-3945-rs.o
++iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o
++iwl3945-$(CONFIG_IWL3945_LEDS) += iwl-3945-led.o
+
+ obj-$(CONFIG_IWL4965) += iwl4965.o
+-iwl4965-objs = iwl4965-base.o iwl-4965.o iwl-4965-rs.o
++iwl4965-objs := iwl4965-base.o iwl-4965.o iwl-4965-rs.o iwl-sta.o
++
+diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h
+index 46bb2c7..817ece7 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h
++++ b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h
+@@ -5,7 +5,7 @@
+ *
+ * GPL LICENSE SUMMARY
+ *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+@@ -30,7 +30,7 @@
+ *
+ * BSD LICENSE
+ *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -515,14 +515,20 @@ struct iwl3945_qosparam_cmd {
+ #define STA_CONTROL_MODIFY_MSK 0x01
+
+ /* key flags __le16*/
+-#define STA_KEY_FLG_ENCRYPT_MSK __constant_cpu_to_le16(0x7)
+-#define STA_KEY_FLG_NO_ENC __constant_cpu_to_le16(0x0)
+-#define STA_KEY_FLG_WEP __constant_cpu_to_le16(0x1)
+-#define STA_KEY_FLG_CCMP __constant_cpu_to_le16(0x2)
+-#define STA_KEY_FLG_TKIP __constant_cpu_to_le16(0x3)
++#define STA_KEY_FLG_ENCRYPT_MSK __constant_cpu_to_le16(0x0007)
++#define STA_KEY_FLG_NO_ENC __constant_cpu_to_le16(0x0000)
++#define STA_KEY_FLG_WEP __constant_cpu_to_le16(0x0001)
++#define STA_KEY_FLG_CCMP __constant_cpu_to_le16(0x0002)
++#define STA_KEY_FLG_TKIP __constant_cpu_to_le16(0x0003)
+
+ #define STA_KEY_FLG_KEYID_POS 8
+ #define STA_KEY_FLG_INVALID __constant_cpu_to_le16(0x0800)
++/* wep key is either from global key (0) or from station info array (1) */
++#define STA_KEY_FLG_WEP_KEY_MAP_MSK __constant_cpu_to_le16(0x0008)
++
++/* wep key in STA: 5-bytes (0) or 13-bytes (1) */
++#define STA_KEY_FLG_KEY_SIZE_MSK __constant_cpu_to_le16(0x1000)
++#define STA_KEY_MULTICAST_MSK __constant_cpu_to_le16(0x4000)
+
+ /* Flags indicate whether to modify vs. don't change various station params */
+ #define STA_MODIFY_KEY_MASK 0x01
+@@ -546,7 +552,8 @@ struct iwl3945_keyinfo {
+ u8 tkip_rx_tsc_byte2; /* TSC[2] for key mix ph1 detection */
+ u8 reserved1;
+ __le16 tkip_rx_ttak[5]; /* 10-byte unicast TKIP TTAK */
+- __le16 reserved2;
++ u8 key_offset;
++ u8 reserved2;
+ u8 key[16]; /* 16-byte unicast decryption key */
+ } __attribute__ ((packed));
+
+@@ -659,26 +666,26 @@ struct iwl3945_rx_frame_hdr {
+ u8 payload[0];
+ } __attribute__ ((packed));
+
+-#define RX_RES_STATUS_NO_CRC32_ERROR __constant_cpu_to_le32(1 << 0)
+-#define RX_RES_STATUS_NO_RXE_OVERFLOW __constant_cpu_to_le32(1 << 1)
++#define RX_RES_STATUS_NO_CRC32_ERROR __constant_cpu_to_le32(1 << 0)
++#define RX_RES_STATUS_NO_RXE_OVERFLOW __constant_cpu_to_le32(1 << 1)
+
+-#define RX_RES_PHY_FLAGS_BAND_24_MSK __constant_cpu_to_le16(1 << 0)
+-#define RX_RES_PHY_FLAGS_MOD_CCK_MSK __constant_cpu_to_le16(1 << 1)
+-#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK __constant_cpu_to_le16(1 << 2)
+-#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK __constant_cpu_to_le16(1 << 3)
+-#define RX_RES_PHY_FLAGS_ANTENNA_MSK __constant_cpu_to_le16(0xf0)
++#define RX_RES_PHY_FLAGS_BAND_24_MSK __constant_cpu_to_le16(1 << 0)
++#define RX_RES_PHY_FLAGS_MOD_CCK_MSK __constant_cpu_to_le16(1 << 1)
++#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK __constant_cpu_to_le16(1 << 2)
++#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK __constant_cpu_to_le16(1 << 3)
++#define RX_RES_PHY_FLAGS_ANTENNA_MSK __constant_cpu_to_le16(0xf0)
+
+-#define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8)
+-#define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8)
+-#define RX_RES_STATUS_SEC_TYPE_WEP (0x1 << 8)
+-#define RX_RES_STATUS_SEC_TYPE_CCMP (0x2 << 8)
+-#define RX_RES_STATUS_SEC_TYPE_TKIP (0x3 << 8)
++#define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8)
++#define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8)
++#define RX_RES_STATUS_SEC_TYPE_WEP (0x1 << 8)
++#define RX_RES_STATUS_SEC_TYPE_CCMP (0x2 << 8)
++#define RX_RES_STATUS_SEC_TYPE_TKIP (0x3 << 8)
+
+-#define RX_RES_STATUS_DECRYPT_TYPE_MSK (0x3 << 11)
+-#define RX_RES_STATUS_NOT_DECRYPT (0x0 << 11)
+-#define RX_RES_STATUS_DECRYPT_OK (0x3 << 11)
+-#define RX_RES_STATUS_BAD_ICV_MIC (0x1 << 11)
+-#define RX_RES_STATUS_BAD_KEY_TTAK (0x2 << 11)
++#define RX_RES_STATUS_DECRYPT_TYPE_MSK (0x3 << 11)
++#define RX_RES_STATUS_NOT_DECRYPT (0x0 << 11)
++#define RX_RES_STATUS_DECRYPT_OK (0x3 << 11)
++#define RX_RES_STATUS_BAD_ICV_MIC (0x1 << 11)
++#define RX_RES_STATUS_BAD_KEY_TTAK (0x2 << 11)
+
+ struct iwl3945_rx_frame_end {
+ __le32 status;
+@@ -700,45 +707,6 @@ struct iwl3945_rx_frame {
+ struct iwl3945_rx_frame_end end;
+ } __attribute__ ((packed));
+
+-/* Fixed (non-configurable) rx data from phy */
+-#define RX_PHY_FLAGS_ANTENNAE_OFFSET (4)
+-#define RX_PHY_FLAGS_ANTENNAE_MASK (0x70)
+-#define IWL_AGC_DB_MASK (0x3f80) /* MASK(7,13) */
+-#define IWL_AGC_DB_POS (7)
+-struct iwl4965_rx_non_cfg_phy {
+- __le16 ant_selection; /* ant A bit 4, ant B bit 5, ant C bit 6 */
+- __le16 agc_info; /* agc code 0:6, agc dB 7:13, reserved 14:15 */
+- u8 rssi_info[6]; /* we use even entries, 0/2/4 for A/B/C rssi */
+- u8 pad[0];
+-} __attribute__ ((packed));
+-
+-/*
+- * REPLY_4965_RX = 0xc3 (response only, not a command)
+- * Used only for legacy (non 11n) frames.
+- */
+-#define RX_RES_PHY_CNT 14
+-struct iwl4965_rx_phy_res {
+- u8 non_cfg_phy_cnt; /* non configurable DSP phy data byte count */
+- u8 cfg_phy_cnt; /* configurable DSP phy data byte count */
+- u8 stat_id; /* configurable DSP phy data set ID */
+- u8 reserved1;
+- __le64 timestamp; /* TSF at on air rise */
+- __le32 beacon_time_stamp; /* beacon at on-air rise */
+- __le16 phy_flags; /* general phy flags: band, modulation, ... */
+- __le16 channel; /* channel number */
+- __le16 non_cfg_phy[RX_RES_PHY_CNT]; /* upto 14 phy entries */
+- __le32 reserved2;
+- __le32 rate_n_flags;
+- __le16 byte_count; /* frame's byte-count */
+- __le16 reserved3;
+-} __attribute__ ((packed));
+-
+-struct iwl4965_rx_mpdu_res_start {
+- __le16 byte_count;
+- __le16 reserved;
+-} __attribute__ ((packed));
+-
+-
+ /******************************************************************************
+ * (5)
+ * Tx Commands & Responses:
+diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-core.h b/drivers/net/wireless/iwlwifi/iwl-3945-core.h
+new file mode 100644
+index 0000000..bc12f97
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-3945-core.h
+@@ -0,0 +1,80 @@
++/******************************************************************************
++ *
++ * This file is provided under a dual BSD/GPLv2 license. When using or
++ * redistributing this file, you may do so under either license.
++ *
++ * GPL LICENSE SUMMARY
++ *
++ * Copyright(c) 2008 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
++ * USA
++ *
++ * The full GNU General Public License is included in this distribution
++ * in the file called LICENSE.GPL.
++ *
++ * Contact Information:
++ * Tomas Winkler <tomas.winkler at intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ * BSD LICENSE
++ *
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * * Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ * * Neither the name Intel Corporation nor the names of its
++ * contributors may be used to endorse or promote products derived
++ * from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *****************************************************************************/
++
++#ifndef __iwl_3945_dev_h__
++#define __iwl_3945_dev_h__
++
++#define IWL_PCI_DEVICE(dev, subdev, cfg) \
++ .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \
++ .subvendor = PCI_ANY_ID, .subdevice = (subdev), \
++ .driver_data = (kernel_ulong_t)&(cfg)
++
++#define IWL_SKU_G 0x1
++#define IWL_SKU_A 0x2
++
++struct iwl_3945_cfg {
++ const char *name;
++ const char *fw_name;
++ unsigned int sku;
++};
++
++#endif /* __iwl_dev_h__ */
+diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-debug.h b/drivers/net/wireless/iwlwifi/iwl-3945-debug.h
+index f853c6b..f1d002f 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-3945-debug.h
++++ b/drivers/net/wireless/iwlwifi/iwl-3945-debug.h
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+ *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project.
+ *
+@@ -40,6 +40,15 @@ do { if (iwl3945_debug_level & (level)) \
+ do { if ((iwl3945_debug_level & (level)) && net_ratelimit()) \
+ printk(KERN_ERR DRV_NAME": %c %s " fmt, \
+ in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
++
++static inline void iwl3945_print_hex_dump(int level, void *p, u32 len)
++{
++ if (!(iwl3945_debug_level & level))
++ return;
++
++ print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1,
++ p, len, 1);
++}
+ #else
+ static inline void IWL_DEBUG(int level, const char *fmt, ...)
+ {
+@@ -47,7 +56,12 @@ static inline void IWL_DEBUG(int level, const char *fmt, ...)
+ static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...)
+ {
+ }
+-#endif /* CONFIG_IWL3945_DEBUG */
++static inline void iwl3945_print_hex_dump(int level, void *p, u32 len)
++{
++}
++#endif /* CONFIG_IWL3945_DEBUG */
++
++
+
+ /*
+ * To use the debug system;
+@@ -143,6 +157,7 @@ static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...)
+ IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
+ #define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a)
+ #define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a)
++#define IWL_DEBUG_STATS_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_STATS, f, ## a)
+ #define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a)
+ #define IWL_DEBUG_QOS(f, a...) IWL_DEBUG(IWL_DL_QOS, f, ## a)
+ #define IWL_DEBUG_RADIO(f, a...) IWL_DEBUG(IWL_DL_RADIO, f, ## a)
+diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
+index 571815d..ad612a8 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
++++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
+@@ -5,7 +5,7 @@
+ *
+ * GPL LICENSE SUMMARY
+ *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+@@ -30,7 +30,7 @@
+ *
+ * BSD LICENSE
+ *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -198,43 +198,27 @@ struct iwl3945_eeprom_temperature_corr {
+ */
+ struct iwl3945_eeprom {
+ u8 reserved0[16];
+-#define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */
+ u16 device_id; /* abs.ofs: 16 */
+ u8 reserved1[2];
+-#define EEPROM_PMC (2*0x0A) /* 2 bytes */
+ u16 pmc; /* abs.ofs: 20 */
+ u8 reserved2[20];
+-#define EEPROM_MAC_ADDRESS (2*0x15) /* 6 bytes */
+ u8 mac_address[6]; /* abs.ofs: 42 */
+ u8 reserved3[58];
+-#define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */
+ u16 board_revision; /* abs.ofs: 106 */
+ u8 reserved4[11];
+-#define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */
+ u8 board_pba_number[9]; /* abs.ofs: 119 */
+ u8 reserved5[8];
+-#define EEPROM_VERSION (2*0x44) /* 2 bytes */
+ u16 version; /* abs.ofs: 136 */
+-#define EEPROM_SKU_CAP (2*0x45) /* 1 bytes */
+ u8 sku_cap; /* abs.ofs: 138 */
+-#define EEPROM_LEDS_MODE (2*0x45+1) /* 1 bytes */
+ u8 leds_mode; /* abs.ofs: 139 */
+-#define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */
+ u16 oem_mode;
+-#define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */
+ u16 wowlan_mode; /* abs.ofs: 142 */
+-#define EEPROM_LEDS_TIME_INTERVAL (2*0x48) /* 2 bytes */
+ u16 leds_time_interval; /* abs.ofs: 144 */
+-#define EEPROM_LEDS_OFF_TIME (2*0x49) /* 1 bytes */
+ u8 leds_off_time; /* abs.ofs: 146 */
+-#define EEPROM_LEDS_ON_TIME (2*0x49+1) /* 1 bytes */
+ u8 leds_on_time; /* abs.ofs: 147 */
+-#define EEPROM_ALMGOR_M_VERSION (2*0x4A) /* 1 bytes */
+ u8 almgor_m_version; /* abs.ofs: 148 */
+-#define EEPROM_ANTENNA_SWITCH_TYPE (2*0x4A+1) /* 1 bytes */
+ u8 antenna_switch_type; /* abs.ofs: 149 */
+ u8 reserved6[42];
+-#define EEPROM_REGULATORY_SKU_ID (2*0x60) /* 4 bytes */
+ u8 sku_id[4]; /* abs.ofs: 192 */
+
+ /*
+@@ -249,9 +233,7 @@ struct iwl3945_eeprom {
+ *
+ * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
+ */
+-#define EEPROM_REGULATORY_BAND_1 (2*0x62) /* 2 bytes */
+ u16 band_1_count; /* abs.ofs: 196 */
+-#define EEPROM_REGULATORY_BAND_1_CHANNELS (2*0x63) /* 28 bytes */
+ struct iwl3945_eeprom_channel band_1_channels[14]; /* abs.ofs: 196 */
+
+ /*
+@@ -259,36 +241,28 @@ struct iwl3945_eeprom {
+ * 5.0 GHz channels 7, 8, 11, 12, 16
+ * (4915-5080MHz) (none of these is ever supported)
+ */
+-#define EEPROM_REGULATORY_BAND_2 (2*0x71) /* 2 bytes */
+ u16 band_2_count; /* abs.ofs: 226 */
+-#define EEPROM_REGULATORY_BAND_2_CHANNELS (2*0x72) /* 26 bytes */
+ struct iwl3945_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */
+
+ /*
+ * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
+ * (5170-5320MHz)
+ */
+-#define EEPROM_REGULATORY_BAND_3 (2*0x7F) /* 2 bytes */
+ u16 band_3_count; /* abs.ofs: 254 */
+-#define EEPROM_REGULATORY_BAND_3_CHANNELS (2*0x80) /* 24 bytes */
+ struct iwl3945_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */
+
+ /*
+ * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
+ * (5500-5700MHz)
+ */
+-#define EEPROM_REGULATORY_BAND_4 (2*0x8C) /* 2 bytes */
+ u16 band_4_count; /* abs.ofs: 280 */
+-#define EEPROM_REGULATORY_BAND_4_CHANNELS (2*0x8D) /* 22 bytes */
+ struct iwl3945_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */
+
+ /*
+ * 5.7 GHz channels 145, 149, 153, 157, 161, 165
+ * (5725-5825MHz)
+ */
+-#define EEPROM_REGULATORY_BAND_5 (2*0x98) /* 2 bytes */
+ u16 band_5_count; /* abs.ofs: 304 */
+-#define EEPROM_REGULATORY_BAND_5_CHANNELS (2*0x99) /* 12 bytes */
+ struct iwl3945_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */
+
+ u8 reserved9[194];
+@@ -296,15 +270,9 @@ struct iwl3945_eeprom {
+ /*
+ * 3945 Txpower calibration data.
+ */
+-#define EEPROM_TXPOWER_CALIB_GROUP0 0x200
+-#define EEPROM_TXPOWER_CALIB_GROUP1 0x240
+-#define EEPROM_TXPOWER_CALIB_GROUP2 0x280
+-#define EEPROM_TXPOWER_CALIB_GROUP3 0x2c0
+-#define EEPROM_TXPOWER_CALIB_GROUP4 0x300
+ #define IWL_NUM_TX_CALIB_GROUPS 5
+ struct iwl3945_eeprom_txpower_group groups[IWL_NUM_TX_CALIB_GROUPS];
+ /* abs.ofs: 512 */
+-#define EEPROM_CALIB_TEMPERATURE_CORRECT 0x340
+ struct iwl3945_eeprom_temperature_corr corrections; /* abs.ofs: 832 */
+ u8 reserved16[172]; /* fill out to full 1024 byte block */
+ } __attribute__ ((packed));
+@@ -321,181 +289,6 @@ struct iwl3945_eeprom {
+ #define PCI_REG_WUM8 0x0E8
+ #define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT (0x80000000)
+
+-/*=== CSR (control and status registers) ===*/
+-#define CSR_BASE (0x000)
+-
+-#define CSR_SW_VER (CSR_BASE+0x000)
+-#define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */
+-#define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */
+-#define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */
+-#define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */
+-#define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/
+-#define CSR_GPIO_IN (CSR_BASE+0x018) /* read external chip pins */
+-#define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/
+-#define CSR_GP_CNTRL (CSR_BASE+0x024)
+-
+-/*
+- * Hardware revision info
+- * Bit fields:
+- * 31-8: Reserved
+- * 7-4: Type of device: 0x0 = 4965, 0xd = 3945
+- * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D
+- * 1-0: "Dash" value, as in A-1, etc.
+- */
+-#define CSR_HW_REV (CSR_BASE+0x028)
+-
+-/* EEPROM reads */
+-#define CSR_EEPROM_REG (CSR_BASE+0x02c)
+-#define CSR_EEPROM_GP (CSR_BASE+0x030)
+-#define CSR_GP_UCODE (CSR_BASE+0x044)
+-#define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054)
+-#define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058)
+-#define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c)
+-#define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060)
+-#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)
+-
+-/* Analog phase-lock-loop configuration (3945 only)
+- * Set bit 24. */
+-#define CSR_ANA_PLL_CFG (CSR_BASE+0x20c)
+-
+-/* Bits for CSR_HW_IF_CONFIG_REG */
+-#define CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MB (0x00000100)
+-#define CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MM (0x00000200)
+-#define CSR_HW_IF_CONFIG_REG_BIT_SKU_MRC (0x00000400)
+-#define CSR_HW_IF_CONFIG_REG_BIT_BOARD_TYPE (0x00000800)
+-#define CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A (0x00000000)
+-#define CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B (0x00001000)
+-#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000)
+-
+-/* interrupt flags in INTA, set by uCode or hardware (e.g. dma),
+- * acknowledged (reset) by host writing "1" to flagged bits. */
+-#define CSR_INT_BIT_FH_RX (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */
+-#define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */
+-#define CSR_INT_BIT_DNLD (1 << 28) /* uCode Download */
+-#define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */
+-#define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */
+-#define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */
+-#define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */
+-#define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */
+-#define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses, 3945 */
+-#define CSR_INT_BIT_WAKEUP (1 << 1) /* NIC controller waking up (pwr mgmt) */
+-#define CSR_INT_BIT_ALIVE (1 << 0) /* uCode interrupts once it initializes */
+-
+-#define CSR_INI_SET_MASK (CSR_INT_BIT_FH_RX | \
+- CSR_INT_BIT_HW_ERR | \
+- CSR_INT_BIT_FH_TX | \
+- CSR_INT_BIT_SW_ERR | \
+- CSR_INT_BIT_RF_KILL | \
+- CSR_INT_BIT_SW_RX | \
+- CSR_INT_BIT_WAKEUP | \
+- CSR_INT_BIT_ALIVE)
+-
+-/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */
+-#define CSR_FH_INT_BIT_ERR (1 << 31) /* Error */
+-#define CSR_FH_INT_BIT_HI_PRIOR (1 << 30) /* High priority Rx, bypass coalescing */
+-#define CSR_FH_INT_BIT_RX_CHNL2 (1 << 18) /* Rx channel 2 (3945 only) */
+-#define CSR_FH_INT_BIT_RX_CHNL1 (1 << 17) /* Rx channel 1 */
+-#define CSR_FH_INT_BIT_RX_CHNL0 (1 << 16) /* Rx channel 0 */
+-#define CSR_FH_INT_BIT_TX_CHNL6 (1 << 6) /* Tx channel 6 (3945 only) */
+-#define CSR_FH_INT_BIT_TX_CHNL1 (1 << 1) /* Tx channel 1 */
+-#define CSR_FH_INT_BIT_TX_CHNL0 (1 << 0) /* Tx channel 0 */
+-
+-#define CSR_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \
+- CSR_FH_INT_BIT_RX_CHNL2 | \
+- CSR_FH_INT_BIT_RX_CHNL1 | \
+- CSR_FH_INT_BIT_RX_CHNL0)
+-
+-#define CSR_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL6 | \
+- CSR_FH_INT_BIT_TX_CHNL1 | \
+- CSR_FH_INT_BIT_TX_CHNL0)
+-
+-
+-/* RESET */
+-#define CSR_RESET_REG_FLAG_NEVO_RESET (0x00000001)
+-#define CSR_RESET_REG_FLAG_FORCE_NMI (0x00000002)
+-#define CSR_RESET_REG_FLAG_SW_RESET (0x00000080)
+-#define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100)
+-#define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200)
+-
+-/* GP (general purpose) CONTROL */
+-#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001)
+-#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004)
+-#define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008)
+-#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010)
+-
+-#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001)
+-
+-#define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE (0x07000000)
+-#define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE (0x04000000)
+-#define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW (0x08000000)
+-
+-
+-/* EEPROM REG */
+-#define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001)
+-#define CSR_EEPROM_REG_BIT_CMD (0x00000002)
+-
+-/* EEPROM GP */
+-#define CSR_EEPROM_GP_VALID_MSK (0x00000006)
+-#define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000)
+-#define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180)
+-
+-/* UCODE DRV GP */
+-#define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP (0x00000001)
+-#define CSR_UCODE_SW_BIT_RFKILL (0x00000002)
+-#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004)
+-#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008)
+-
+-/* GPIO */
+-#define CSR_GPIO_IN_BIT_AUX_POWER (0x00000200)
+-#define CSR_GPIO_IN_VAL_VAUX_PWR_SRC (0x00000000)
+-#define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC CSR_GPIO_IN_BIT_AUX_POWER
+-
+-/* GI Chicken Bits */
+-#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000)
+-#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000)
+-
+-/* CSR_ANA_PLL_CFG */
+-#define CSR_ANA_PLL_CFG_SH (0x00880300)
+-
+-/*=== HBUS (Host-side Bus) ===*/
+-#define HBUS_BASE (0x400)
+-
+-/*
+- * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM
+- * structures, error log, event log, verifying uCode load).
+- * First write to address register, then read from or write to data register
+- * to complete the job. Once the address register is set up, accesses to
+- * data registers auto-increment the address by one dword.
+- * Bit usage for address registers (read or write):
+- * 0-31: memory address within device
+- */
+-#define HBUS_TARG_MEM_RADDR (HBUS_BASE+0x00c)
+-#define HBUS_TARG_MEM_WADDR (HBUS_BASE+0x010)
+-#define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018)
+-#define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c)
+-
+-/*
+- * Registers for accessing device's internal peripheral registers
+- * (e.g. SCD, BSM, etc.). First write to address register,
+- * then read from or write to data register to complete the job.
+- * Bit usage for address registers (read or write):
+- * 0-15: register address (offset) within device
+- * 24-25: (# bytes - 1) to read or write (e.g. 3 for dword)
+- */
+-#define HBUS_TARG_PRPH_WADDR (HBUS_BASE+0x044)
+-#define HBUS_TARG_PRPH_RADDR (HBUS_BASE+0x048)
+-#define HBUS_TARG_PRPH_WDAT (HBUS_BASE+0x04c)
+-#define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050)
+-
+-/*
+- * Per-Tx-queue write pointer (index, really!) (3945 and 4965).
+- * Indicates index to next TFD that driver will fill (1 past latest filled).
+- * Bit usage:
+- * 0-7: queue write index
+- * 11-8: queue selector
+- */
+-#define HBUS_TARG_WRPTR (HBUS_BASE+0x060)
+-
+ /* SCD (3945 Tx Frame Scheduler) */
+ #define SCD_BASE (CSR_BASE + 0x2E00)
+
+@@ -663,7 +456,7 @@ struct iwl3945_eeprom {
+ /* Size of uCode instruction memory in bootstrap state machine */
+ #define IWL_MAX_BSM_SIZE ALM_RTC_INST_SIZE
+
+-#define IWL_MAX_NUM_QUEUES 8
++#define IWL39_MAX_NUM_QUEUES 8
+
+ static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr)
+ {
+diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-io.h b/drivers/net/wireless/iwlwifi/iwl-3945-io.h
+index 75e20d0..0b94751 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-3945-io.h
++++ b/drivers/net/wireless/iwlwifi/iwl-3945-io.h
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+ *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project.
+ *
+@@ -59,28 +59,28 @@
+ *
+ */
+
+-#define _iwl3945_write32(iwl, ofs, val) writel((val), (iwl)->hw_base + (ofs))
++#define _iwl3945_write32(priv, ofs, val) writel((val), (priv)->hw_base + (ofs))
+ #ifdef CONFIG_IWL3945_DEBUG
+-static inline void __iwl3945_write32(const char *f, u32 l, struct iwl3945_priv *iwl,
++static inline void __iwl3945_write32(const char *f, u32 l, struct iwl3945_priv *priv,
+ u32 ofs, u32 val)
+ {
+ IWL_DEBUG_IO("write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l);
+- _iwl3945_write32(iwl, ofs, val);
++ _iwl3945_write32(priv, ofs, val);
+ }
+-#define iwl3945_write32(iwl, ofs, val) \
+- __iwl3945_write32(__FILE__, __LINE__, iwl, ofs, val)
++#define iwl3945_write32(priv, ofs, val) \
++ __iwl3945_write32(__FILE__, __LINE__, priv, ofs, val)
+ #else
+-#define iwl3945_write32(iwl, ofs, val) _iwl3945_write32(iwl, ofs, val)
++#define iwl3945_write32(priv, ofs, val) _iwl3945_write32(priv, ofs, val)
+ #endif
+
+-#define _iwl3945_read32(iwl, ofs) readl((iwl)->hw_base + (ofs))
++#define _iwl3945_read32(priv, ofs) readl((priv)->hw_base + (ofs))
+ #ifdef CONFIG_IWL3945_DEBUG
+-static inline u32 __iwl3945_read32(char *f, u32 l, struct iwl3945_priv *iwl, u32 ofs)
++static inline u32 __iwl3945_read32(char *f, u32 l, struct iwl3945_priv *priv, u32 ofs)
+ {
+ IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l);
+- return _iwl3945_read32(iwl, ofs);
++ return _iwl3945_read32(priv, ofs);
+ }
+-#define iwl3945_read32(iwl, ofs) __iwl3945_read32(__FILE__, __LINE__, iwl, ofs)
++#define iwl3945_read32(priv, ofs) __iwl3945_read32(__FILE__, __LINE__, priv, ofs)
+ #else
+ #define iwl3945_read32(p, o) _iwl3945_read32(p, o)
+ #endif
+@@ -105,18 +105,13 @@ static inline int __iwl3945_poll_bit(const char *f, u32 l,
+ u32 bits, u32 mask, int timeout)
+ {
+ int ret = _iwl3945_poll_bit(priv, addr, bits, mask, timeout);
+- if (unlikely(ret == -ETIMEDOUT))
+- IWL_DEBUG_IO
+- ("poll_bit(0x%08X, 0x%08X, 0x%08X) - timedout - %s %d\n",
+- addr, bits, mask, f, l);
+- else
+- IWL_DEBUG_IO
+- ("poll_bit(0x%08X, 0x%08X, 0x%08X) = 0x%08X - %s %d\n",
+- addr, bits, mask, ret, f, l);
++ IWL_DEBUG_IO("poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n",
++ addr, bits, mask,
++ unlikely(ret == -ETIMEDOUT)?"timeout":"", f, l);
+ return ret;
+ }
+-#define iwl3945_poll_bit(iwl, addr, bits, mask, timeout) \
+- __iwl3945_poll_bit(__FILE__, __LINE__, iwl, addr, bits, mask, timeout)
++#define iwl3945_poll_bit(priv, addr, bits, mask, timeout) \
++ __iwl3945_poll_bit(__FILE__, __LINE__, priv, addr, bits, mask, timeout)
+ #else
+ #define iwl3945_poll_bit(p, a, b, m, t) _iwl3945_poll_bit(p, a, b, m, t)
+ #endif
+@@ -321,8 +316,8 @@ static inline int __iwl3945_poll_direct_bit(const char *f, u32 l,
+ "- %s %d\n", addr, mask, ret, f, l);
+ return ret;
+ }
+-#define iwl3945_poll_direct_bit(iwl, addr, mask, timeout) \
+- __iwl3945_poll_direct_bit(__FILE__, __LINE__, iwl, addr, mask, timeout)
++#define iwl3945_poll_direct_bit(priv, addr, mask, timeout) \
++ __iwl3945_poll_direct_bit(__FILE__, __LINE__, priv, addr, mask, timeout)
+ #else
+ #define iwl3945_poll_direct_bit _iwl3945_poll_direct_bit
+ #endif
+diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c
+new file mode 100644
+index 0000000..d200d08
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c
+@@ -0,0 +1,433 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called LICENSE.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ *****************************************************************************/
++
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/init.h>
++#include <linux/pci.h>
++#include <linux/dma-mapping.h>
++#include <linux/delay.h>
++#include <linux/skbuff.h>
++#include <linux/netdevice.h>
++#include <linux/wireless.h>
++#include <net/mac80211.h>
++#include <linux/etherdevice.h>
++#include <asm/unaligned.h>
++
++#include "iwl-3945.h"
++#include "iwl-helpers.h"
++
++#define IWL_1MB_RATE (128 * 1024)
++#define IWL_LED_THRESHOLD (16)
++#define IWL_MAX_BLINK_TBL (10)
++
++static const struct {
++ u16 brightness;
++ u8 on_time;
++ u8 of_time;
++} blink_tbl[] =
++{
++ {300, 25, 25},
++ {200, 40, 40},
++ {100, 55, 55},
++ {70, 65, 65},
++ {50, 75, 75},
++ {20, 85, 85},
++ {15, 95, 95 },
++ {10, 110, 110},
++ {5, 130, 130},
++ {0, 167, 167}
++};
++
++static int iwl3945_led_cmd_callback(struct iwl3945_priv *priv,
++ struct iwl3945_cmd *cmd,
++ struct sk_buff *skb)
++{
++ return 1;
++}
++
++
++/* Send led command */
++static int iwl_send_led_cmd(struct iwl3945_priv *priv,
++ struct iwl3945_led_cmd *led_cmd)
++{
++ struct iwl3945_host_cmd cmd = {
++ .id = REPLY_LEDS_CMD,
++ .len = sizeof(struct iwl3945_led_cmd),
++ .data = led_cmd,
++ .meta.flags = CMD_ASYNC,
++ .meta.u.callback = iwl3945_led_cmd_callback
++ };
++
++ return iwl3945_send_cmd(priv, &cmd);
++}
++
++
++/* Set led on command */
++static int iwl3945_led_on(struct iwl3945_priv *priv, int led_id)
++{
++ struct iwl3945_led_cmd led_cmd = {
++ .id = led_id,
++ .on = IWL_LED_SOLID,
++ .off = 0,
++ .interval = IWL_DEF_LED_INTRVL
++ };
++ return iwl_send_led_cmd(priv, &led_cmd);
++}
++
++/* Set led on command */
++static int iwl3945_led_pattern(struct iwl3945_priv *priv, int led_id,
++ enum led_brightness brightness)
++{
++ struct iwl3945_led_cmd led_cmd = {
++ .id = led_id,
++ .on = brightness,
++ .off = brightness,
++ .interval = IWL_DEF_LED_INTRVL
++ };
++ if (brightness == LED_FULL) {
++ led_cmd.on = IWL_LED_SOLID;
++ led_cmd.off = 0;
++ }
++ return iwl_send_led_cmd(priv, &led_cmd);
++}
++
++/* Set led register off */
++static int iwl3945_led_on_reg(struct iwl3945_priv *priv, int led_id)
++{
++ IWL_DEBUG_LED("led on %d\n", led_id);
++ return iwl3945_led_on(priv, led_id);
++}
++
++/* Set led off command */
++static int iwl3945_led_off(struct iwl3945_priv *priv, int led_id)
++{
++ struct iwl3945_led_cmd led_cmd = {
++ .id = led_id,
++ .on = 0,
++ .off = 0,
++ .interval = IWL_DEF_LED_INTRVL
++ };
++ IWL_DEBUG_LED("led off %d\n", led_id);
++ return iwl_send_led_cmd(priv, &led_cmd);
++}
++
++/* Set led register off */
++static int iwl3945_led_off_reg(struct iwl3945_priv *priv, int led_id)
++{
++ iwl3945_led_off(priv, led_id);
++ return 0;
++}
++
++/* Set led blink command */
++static int iwl3945_led_not_solid(struct iwl3945_priv *priv, int led_id,
++ u8 brightness)
++{
++ struct iwl3945_led_cmd led_cmd = {
++ .id = led_id,
++ .on = brightness,
++ .off = brightness,
++ .interval = IWL_DEF_LED_INTRVL
++ };
++
++ return iwl_send_led_cmd(priv, &led_cmd);
++}
++
++
++/*
++ * brightness call back function for Tx/Rx LED
++ */
++static int iwl3945_led_associated(struct iwl3945_priv *priv, int led_id)
++{
++ if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
++ !test_bit(STATUS_READY, &priv->status))
++ return 0;
++
++
++ /* start counting Tx/Rx bytes */
++ if (!priv->last_blink_time && priv->allow_blinking)
++ priv->last_blink_time = jiffies;
++ return 0;
++}
++
++/*
++ * brightness call back for association and radio
++ */
++static void iwl3945_led_brightness_set(struct led_classdev *led_cdev,
++ enum led_brightness brightness)
++{
++ struct iwl3945_led *led = container_of(led_cdev,
++ struct iwl3945_led, led_dev);
++ struct iwl3945_priv *priv = led->priv;
++
++ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++ return;
++
++ switch (brightness) {
++ case LED_FULL:
++ if (led->type == IWL_LED_TRG_ASSOC) {
++ priv->allow_blinking = 1;
++ IWL_DEBUG_LED("MAC is associated\n");
++ }
++ if (led->led_on)
++ led->led_on(priv, IWL_LED_LINK);
++ break;
++ case LED_OFF:
++ if (led->type == IWL_LED_TRG_ASSOC) {
++ priv->allow_blinking = 0;
++ IWL_DEBUG_LED("MAC is disassociated\n");
++ }
++ if (led->led_off)
++ led->led_off(priv, IWL_LED_LINK);
++ break;
++ default:
++ if (led->led_pattern)
++ led->led_pattern(priv, IWL_LED_LINK, brightness);
++ break;
++ }
++}
++
++
++
++/*
++ * Register led class with the system
++ */
++static int iwl3945_led_register_led(struct iwl3945_priv *priv,
++ struct iwl3945_led *led,
++ enum led_type type, u8 set_led,
++ const char *name, char *trigger)
++{
++ struct device *device = wiphy_dev(priv->hw->wiphy);
++ int ret;
++
++ led->led_dev.name = name;
++ led->led_dev.brightness_set = iwl3945_led_brightness_set;
++ led->led_dev.default_trigger = trigger;
++
++ ret = led_classdev_register(device, &led->led_dev);
++ if (ret) {
++ IWL_ERROR("Error: failed to register led handler.\n");
++ return ret;
++ }
++
++ led->priv = priv;
++ led->type = type;
++ led->registered = 1;
++
++ if (set_led && led->led_on)
++ led->led_on(priv, IWL_LED_LINK);
++ return 0;
++}
++
++
++/*
++ * calculate blink rate according to last 2 sec Tx/Rx activities
++ */
++static inline u8 get_blink_rate(struct iwl3945_priv *priv)
++{
++ int index;
++ u8 blink_rate;
++
++ if (priv->rxtxpackets < IWL_LED_THRESHOLD)
++ index = 10;
++ else {
++ for (index = 0; index < IWL_MAX_BLINK_TBL; index++) {
++ if (priv->rxtxpackets > (blink_tbl[index].brightness *
++ IWL_1MB_RATE))
++ break;
++ }
++ }
++ /* if 0 frame is transfered */
++ if ((index == IWL_MAX_BLINK_TBL) || !priv->allow_blinking)
++ blink_rate = IWL_LED_SOLID;
++ else
++ blink_rate = blink_tbl[index].on_time;
++
++ return blink_rate;
++}
++
++static inline int is_rf_kill(struct iwl3945_priv *priv)
++{
++ return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
++ test_bit(STATUS_RF_KILL_SW, &priv->status);
++}
++
++/*
++ * this function called from handler. Since setting Led command can
++ * happen very frequent we postpone led command to be called from
++ * REPLY handler so we know ucode is up
++ */
++void iwl3945_led_background(struct iwl3945_priv *priv)
++{
++ u8 blink_rate;
++
++ if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
++ priv->last_blink_time = 0;
++ return;
++ }
++ if (is_rf_kill(priv)) {
++ priv->last_blink_time = 0;
++ return;
++ }
++
++ if (!priv->allow_blinking) {
++ priv->last_blink_time = 0;
++ if (priv->last_blink_rate != IWL_LED_SOLID) {
++ priv->last_blink_rate = IWL_LED_SOLID;
++ iwl3945_led_on(priv, IWL_LED_LINK);
++ }
++ return;
++ }
++ if (!priv->last_blink_time ||
++ !time_after(jiffies, priv->last_blink_time +
++ msecs_to_jiffies(1000)))
++ return;
++
++ blink_rate = get_blink_rate(priv);
++
++ /* call only if blink rate change */
++ if (blink_rate != priv->last_blink_rate) {
++ if (blink_rate != IWL_LED_SOLID) {
++ priv->last_blink_time = jiffies +
++ msecs_to_jiffies(1000);
++ iwl3945_led_not_solid(priv, IWL_LED_LINK, blink_rate);
++ } else {
++ priv->last_blink_time = 0;
++ iwl3945_led_on(priv, IWL_LED_LINK);
++ }
++ }
++
++ priv->last_blink_rate = blink_rate;
++ priv->rxtxpackets = 0;
++}
++
++
++/* Register all led handler */
++int iwl3945_led_register(struct iwl3945_priv *priv)
++{
++ char *trigger;
++ char name[32];
++ int ret;
++
++ priv->last_blink_rate = 0;
++ priv->rxtxpackets = 0;
++ priv->last_blink_time = 0;
++ priv->allow_blinking = 0;
++
++ trigger = ieee80211_get_radio_led_name(priv->hw);
++ snprintf(name, sizeof(name), "iwl-%s:radio",
++ wiphy_name(priv->hw->wiphy));
++
++ priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on_reg;
++ priv->led[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off_reg;
++ priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL;
++
++ ret = iwl3945_led_register_led(priv,
++ &priv->led[IWL_LED_TRG_RADIO],
++ IWL_LED_TRG_RADIO, 1,
++ name, trigger);
++ if (ret)
++ goto exit_fail;
++
++ trigger = ieee80211_get_assoc_led_name(priv->hw);
++ snprintf(name, sizeof(name), "iwl-%s:assoc",
++ wiphy_name(priv->hw->wiphy));
++
++ ret = iwl3945_led_register_led(priv,
++ &priv->led[IWL_LED_TRG_ASSOC],
++ IWL_LED_TRG_ASSOC, 0,
++ name, trigger);
++ /* for assoc always turn led on */
++ priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on_reg;
++ priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on_reg;
++ priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL;
++
++ if (ret)
++ goto exit_fail;
++
++ trigger = ieee80211_get_rx_led_name(priv->hw);
++ snprintf(name, sizeof(name), "iwl-%s:RX",
++ wiphy_name(priv->hw->wiphy));
++
++
++ ret = iwl3945_led_register_led(priv,
++ &priv->led[IWL_LED_TRG_RX],
++ IWL_LED_TRG_RX, 0,
++ name, trigger);
++
++ priv->led[IWL_LED_TRG_RX].led_on = iwl3945_led_associated;
++ priv->led[IWL_LED_TRG_RX].led_off = iwl3945_led_associated;
++ priv->led[IWL_LED_TRG_RX].led_pattern = iwl3945_led_pattern;
++
++ if (ret)
++ goto exit_fail;
++
++ trigger = ieee80211_get_tx_led_name(priv->hw);
++ snprintf(name, sizeof(name), "iwl-%s:TX",
++ wiphy_name(priv->hw->wiphy));
++ ret = iwl3945_led_register_led(priv,
++ &priv->led[IWL_LED_TRG_TX],
++ IWL_LED_TRG_TX, 0,
++ name, trigger);
++ priv->led[IWL_LED_TRG_TX].led_on = iwl3945_led_associated;
++ priv->led[IWL_LED_TRG_TX].led_off = iwl3945_led_associated;
++ priv->led[IWL_LED_TRG_TX].led_pattern = iwl3945_led_pattern;
++
++ if (ret)
++ goto exit_fail;
++
++ return 0;
++
++exit_fail:
++ iwl3945_led_unregister(priv);
++ return ret;
++}
++
++
++/* unregister led class */
++static void iwl3945_led_unregister_led(struct iwl3945_led *led, u8 set_led)
++{
++ if (!led->registered)
++ return;
++
++ led_classdev_unregister(&led->led_dev);
++
++ if (set_led)
++ led->led_dev.brightness_set(&led->led_dev, LED_OFF);
++ led->registered = 0;
++}
++
++/* Unregister all led handlers */
++void iwl3945_led_unregister(struct iwl3945_priv *priv)
++{
++ iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_ASSOC], 0);
++ iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_RX], 0);
++ iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_TX], 0);
++ iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_RADIO], 1);
++}
++
+diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.h b/drivers/net/wireless/iwlwifi/iwl-3945-led.h
+new file mode 100644
+index 0000000..b1d2f6b
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.h
+@@ -0,0 +1,73 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called LICENSE.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ *****************************************************************************/
++
++#ifndef IWL3945_LEDS_H
++#define IWL3945_LEDS_H
++
++struct iwl3945_priv;
++
++#ifdef CONFIG_IWL3945_LEDS
++#define IWL_LED_SOLID 11
++#define IWL_LED_NAME_LEN 31
++#define IWL_DEF_LED_INTRVL __constant_cpu_to_le32(1000)
++
++#define IWL_LED_ACTIVITY (0<<1)
++#define IWL_LED_LINK (1<<1)
++
++enum led_type {
++ IWL_LED_TRG_TX,
++ IWL_LED_TRG_RX,
++ IWL_LED_TRG_ASSOC,
++ IWL_LED_TRG_RADIO,
++ IWL_LED_TRG_MAX,
++};
++
++#include <linux/leds.h>
++
++struct iwl3945_led {
++ struct iwl3945_priv *priv;
++ struct led_classdev led_dev;
++
++ int (*led_on) (struct iwl3945_priv *priv, int led_id);
++ int (*led_off) (struct iwl3945_priv *priv, int led_id);
++ int (*led_pattern) (struct iwl3945_priv *priv, int led_id,
++ enum led_brightness brightness);
++
++ enum led_type type;
++ unsigned int registered;
++};
++
++extern int iwl3945_led_register(struct iwl3945_priv *priv);
++extern void iwl3945_led_unregister(struct iwl3945_priv *priv);
++extern void iwl3945_led_background(struct iwl3945_priv *priv);
++
++#else
++static inline int iwl3945_led_register(struct iwl3945_priv *priv) { return 0; }
++static inline void iwl3945_led_unregister(struct iwl3945_priv *priv) {}
++static inline void iwl3945_led_background(struct iwl3945_priv *priv) {}
++#endif /* CONFIG_IWL3945_LEDS */
++
++#endif /* IWL3945_LEDS_H */
+diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+index 80d31ae..85c2264 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
++++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+ *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+@@ -37,7 +37,7 @@
+
+ #include <linux/workqueue.h>
+
+-#include "../net/mac80211/ieee80211_rate.h"
++#include "../net/mac80211/rate.h"
+
+ #include "iwl-3945.h"
+
+@@ -100,14 +100,6 @@ static struct iwl3945_tpt_entry iwl3945_tpt_table_a[] = {
+ {-89, IWL_RATE_6M_INDEX}
+ };
+
+-static struct iwl3945_tpt_entry iwl3945_tpt_table_b[] = {
+- {-86, IWL_RATE_11M_INDEX},
+- {-88, IWL_RATE_5M_INDEX},
+- {-90, IWL_RATE_2M_INDEX},
+- {-92, IWL_RATE_1M_INDEX}
+-
+-};
+-
+ static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = {
+ {-60, IWL_RATE_54M_INDEX},
+ {-64, IWL_RATE_48M_INDEX},
+@@ -129,7 +121,7 @@ static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = {
+ #define IWL_RATE_MIN_SUCCESS_TH 8
+ #define IWL_RATE_DECREASE_TH 1920
+
+-static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, u8 mode)
++static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band)
+ {
+ u32 index = 0;
+ u32 table_size = 0;
+@@ -138,21 +130,19 @@ static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, u8 mode)
+ if ((rssi < IWL_MIN_RSSI_VAL) || (rssi > IWL_MAX_RSSI_VAL))
+ rssi = IWL_MIN_RSSI_VAL;
+
+- switch (mode) {
+- case MODE_IEEE80211G:
++ switch (band) {
++ case IEEE80211_BAND_2GHZ:
+ tpt_table = iwl3945_tpt_table_g;
+ table_size = ARRAY_SIZE(iwl3945_tpt_table_g);
+ break;
+
+- case MODE_IEEE80211A:
++ case IEEE80211_BAND_5GHZ:
+ tpt_table = iwl3945_tpt_table_a;
+ table_size = ARRAY_SIZE(iwl3945_tpt_table_a);
+ break;
+
+ default:
+- case MODE_IEEE80211B:
+- tpt_table = iwl3945_tpt_table_b;
+- table_size = ARRAY_SIZE(iwl3945_tpt_table_b);
++ BUG();
+ break;
+ }
+
+@@ -168,9 +158,9 @@ static void iwl3945_clear_window(struct iwl3945_rate_scale_data *window)
+ {
+ window->data = 0;
+ window->success_counter = 0;
+- window->success_ratio = IWL_INVALID_VALUE;
++ window->success_ratio = -1;
+ window->counter = 0;
+- window->average_tpt = IWL_INVALID_VALUE;
++ window->average_tpt = IWL_INV_TPT;
+ window->stamp = 0;
+ }
+
+@@ -340,17 +330,17 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
+ * after assoc.. */
+
+ for (i = IWL_RATE_COUNT - 1; i >= 0; i--) {
+- if (sta->supp_rates & (1 << i)) {
+- sta->txrate = i;
++ if (sta->supp_rates[local->hw.conf.channel->band] & (1 << i)) {
++ sta->txrate_idx = i;
+ break;
+ }
+ }
+
+- sta->last_txrate = sta->txrate;
++ sta->last_txrate_idx = sta->txrate_idx;
+
+- /* For MODE_IEEE80211A mode it start at IWL_FIRST_OFDM_RATE */
+- if (local->hw.conf.phymode == MODE_IEEE80211A)
+- sta->last_txrate += IWL_FIRST_OFDM_RATE;
++ /* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */
++ if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ)
++ sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
+
+ IWL_DEBUG_RATE("leave\n");
+ }
+@@ -429,17 +419,19 @@ static int rs_adjust_next_rate(struct iwl3945_priv *priv, int rate)
+ {
+ int next_rate = iwl3945_get_prev_ieee_rate(rate);
+
+- switch (priv->phymode) {
+- case MODE_IEEE80211A:
++ switch (priv->band) {
++ case IEEE80211_BAND_5GHZ:
+ if (rate == IWL_RATE_12M_INDEX)
+ next_rate = IWL_RATE_9M_INDEX;
+ else if (rate == IWL_RATE_6M_INDEX)
+ next_rate = IWL_RATE_6M_INDEX;
+ break;
++/* XXX cannot be invoked in current mac80211 so not a regression
+ case MODE_IEEE80211B:
+ if (rate == IWL_RATE_11M_INDEX_TABLE)
+ next_rate = IWL_RATE_5M_INDEX_TABLE;
+ break;
++ */
+ default:
+ break;
+ }
+@@ -465,22 +457,25 @@ static void rs_tx_status(void *priv_rate,
+ struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate;
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct iwl3945_rs_sta *rs_sta;
++ struct ieee80211_supported_band *sband;
+
+ IWL_DEBUG_RATE("enter\n");
+
+- retries = tx_resp->retry_count;
++ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+
+- first_index = tx_resp->control.tx_rate;
++
++ retries = tx_resp->retry_count;
++ first_index = tx_resp->control.tx_rate->hw_value;
+ if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) {
+- IWL_DEBUG_RATE("leave: Rate out of bounds: %0x for %d\n",
+- tx_resp->control.tx_rate, first_index);
++ IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index);
+ return;
+ }
+
++ rcu_read_lock();
++
+ sta = sta_info_get(local, hdr->addr1);
+ if (!sta || !sta->rate_ctrl_priv) {
+- if (sta)
+- sta_info_put(sta);
++ rcu_read_unlock();
+ IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
+ return;
+ }
+@@ -553,7 +548,7 @@ static void rs_tx_status(void *priv_rate,
+
+ spin_unlock_irqrestore(&rs_sta->lock, flags);
+
+- sta_info_put(sta);
++ rcu_read_unlock();
+
+ IWL_DEBUG_RATE("leave\n");
+
+@@ -561,14 +556,14 @@ static void rs_tx_status(void *priv_rate,
+ }
+
+ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
+- u8 index, u16 rate_mask, int phymode)
++ u8 index, u16 rate_mask, enum ieee80211_band band)
+ {
+ u8 high = IWL_RATE_INVALID;
+ u8 low = IWL_RATE_INVALID;
+
+ /* 802.11A walks to the next literal adjacent rate in
+ * the rate table */
+- if (unlikely(phymode == MODE_IEEE80211A)) {
++ if (unlikely(band == IEEE80211_BAND_5GHZ)) {
+ int i;
+ u32 mask;
+
+@@ -639,7 +634,8 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
+ *
+ */
+ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+- struct ieee80211_hw_mode *mode, struct sk_buff *skb,
++ struct ieee80211_supported_band *sband,
++ struct sk_buff *skb,
+ struct rate_selection *sel)
+ {
+ u8 low = IWL_RATE_INVALID;
+@@ -648,9 +644,9 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+ int index;
+ struct iwl3945_rs_sta *rs_sta;
+ struct iwl3945_rate_scale_data *window = NULL;
+- int current_tpt = IWL_INVALID_VALUE;
+- int low_tpt = IWL_INVALID_VALUE;
+- int high_tpt = IWL_INVALID_VALUE;
++ int current_tpt = IWL_INV_TPT;
++ int low_tpt = IWL_INV_TPT;
++ int high_tpt = IWL_INV_TPT;
+ u32 fail_count;
+ s8 scale_action = 0;
+ unsigned long flags;
+@@ -663,6 +659,8 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+
+ IWL_DEBUG_RATE("enter\n");
+
++ rcu_read_lock();
++
+ sta = sta_info_get(local, hdr->addr1);
+
+ /* Send management frames and broadcast/multicast data using lowest
+@@ -672,16 +670,15 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+ is_multicast_ether_addr(hdr->addr1) ||
+ !sta || !sta->rate_ctrl_priv) {
+ IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
+- sel->rate = rate_lowest(local, local->oper_hw_mode, sta);
+- if (sta)
+- sta_info_put(sta);
++ sel->rate = rate_lowest(local, sband, sta);
++ rcu_read_unlock();
+ return;
+ }
+
+- rate_mask = sta->supp_rates;
+- index = min(sta->last_txrate & 0xffff, IWL_RATE_COUNT - 1);
++ rate_mask = sta->supp_rates[sband->band];
++ index = min(sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1);
+
+- if (priv->phymode == (u8) MODE_IEEE80211A)
++ if (sband->band == IEEE80211_BAND_5GHZ)
+ rate_mask = rate_mask << IWL_FIRST_OFDM_RATE;
+
+ rs_sta = (void *)sta->rate_ctrl_priv;
+@@ -713,7 +710,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+
+ if (((fail_count <= IWL_RATE_MIN_FAILURE_TH) &&
+ (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) {
+- window->average_tpt = IWL_INVALID_VALUE;
++ window->average_tpt = IWL_INV_TPT;
+ spin_unlock_irqrestore(&rs_sta->lock, flags);
+
+ IWL_DEBUG_RATE("Invalid average_tpt on rate %d: "
+@@ -732,7 +729,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+ current_tpt = window->average_tpt;
+
+ high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask,
+- local->hw.conf.phymode);
++ sband->band);
+ low = high_low & 0xff;
+ high = (high_low >> 8) & 0xff;
+
+@@ -749,19 +746,16 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+ if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) {
+ IWL_DEBUG_RATE("decrease rate because of low success_ratio\n");
+ scale_action = -1;
+- } else if ((low_tpt == IWL_INVALID_VALUE) &&
+- (high_tpt == IWL_INVALID_VALUE))
++ } else if ((low_tpt == IWL_INV_TPT) && (high_tpt == IWL_INV_TPT))
+ scale_action = 1;
+- else if ((low_tpt != IWL_INVALID_VALUE) &&
+- (high_tpt != IWL_INVALID_VALUE)
+- && (low_tpt < current_tpt)
+- && (high_tpt < current_tpt)) {
++ else if ((low_tpt != IWL_INV_TPT) && (high_tpt != IWL_INV_TPT) &&
++ (low_tpt < current_tpt) && (high_tpt < current_tpt)) {
+ IWL_DEBUG_RATE("No action -- low [%d] & high [%d] < "
+ "current_tpt [%d]\n",
+ low_tpt, high_tpt, current_tpt);
+ scale_action = 0;
+ } else {
+- if (high_tpt != IWL_INVALID_VALUE) {
++ if (high_tpt != IWL_INV_TPT) {
+ if (high_tpt > current_tpt)
+ scale_action = 1;
+ else {
+@@ -769,7 +763,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+ ("decrease rate because of high tpt\n");
+ scale_action = -1;
+ }
+- } else if (low_tpt != IWL_INVALID_VALUE) {
++ } else if (low_tpt != IWL_INV_TPT) {
+ if (low_tpt > current_tpt) {
+ IWL_DEBUG_RATE
+ ("decrease rate because of low tpt\n");
+@@ -810,17 +804,17 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+
+ out:
+
+- sta->last_txrate = index;
+- if (priv->phymode == (u8) MODE_IEEE80211A)
+- sta->txrate = sta->last_txrate - IWL_FIRST_OFDM_RATE;
++ sta->last_txrate_idx = index;
++ if (sband->band == IEEE80211_BAND_5GHZ)
++ sta->txrate_idx = sta->last_txrate_idx - IWL_FIRST_OFDM_RATE;
+ else
+- sta->txrate = sta->last_txrate;
++ sta->txrate_idx = sta->last_txrate_idx;
+
+- sta_info_put(sta);
++ rcu_read_unlock();
+
+ IWL_DEBUG_RATE("leave: %d\n", index);
+
+- sel->rate = &priv->ieee_rates[index];
++ sel->rate = &sband->bitrates[sta->txrate_idx];
+ }
+
+ static struct rate_control_ops rs_ops = {
+@@ -848,13 +842,15 @@ int iwl3945_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
+ unsigned long now = jiffies;
+ u32 max_time = 0;
+
++ rcu_read_lock();
++
+ sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr);
+ if (!sta || !sta->rate_ctrl_priv) {
+- if (sta) {
+- sta_info_put(sta);
++ if (sta)
+ IWL_DEBUG_RATE("leave - no private rate data!\n");
+- } else
++ else
+ IWL_DEBUG_RATE("leave - no station!\n");
++ rcu_read_unlock();
+ return sprintf(buf, "station %d not found\n", sta_id);
+ }
+
+@@ -895,7 +891,7 @@ int iwl3945_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
+ i = j;
+ }
+ spin_unlock_irqrestore(&rs_sta->lock, flags);
+- sta_info_put(sta);
++ rcu_read_unlock();
+
+ /* Display the average rate of all samples taken.
+ *
+@@ -932,11 +928,12 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
+ return;
+ }
+
++ rcu_read_lock();
++
+ sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr);
+ if (!sta || !sta->rate_ctrl_priv) {
+- if (sta)
+- sta_info_put(sta);
+ IWL_DEBUG_RATE("leave - no private rate data!\n");
++ rcu_read_unlock();
+ return;
+ }
+
+@@ -945,8 +942,9 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
+ spin_lock_irqsave(&rs_sta->lock, flags);
+
+ rs_sta->tgg = 0;
+- switch (priv->phymode) {
+- case MODE_IEEE80211G:
++ switch (priv->band) {
++ case IEEE80211_BAND_2GHZ:
++ /* TODO: this always does G, not a regression */
+ if (priv->active_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) {
+ rs_sta->tgg = 1;
+ rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot;
+@@ -954,18 +952,15 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
+ rs_sta->expected_tpt = iwl3945_expected_tpt_g;
+ break;
+
+- case MODE_IEEE80211A:
++ case IEEE80211_BAND_5GHZ:
+ rs_sta->expected_tpt = iwl3945_expected_tpt_a;
+ break;
+-
+- default:
+- IWL_WARNING("Invalid phymode. Defaulting to 802.11b\n");
+- case MODE_IEEE80211B:
+- rs_sta->expected_tpt = iwl3945_expected_tpt_b;
++ case IEEE80211_NUM_BANDS:
++ BUG();
+ break;
+ }
+
+- sta_info_put(sta);
++ rcu_read_unlock();
+ spin_unlock_irqrestore(&rs_sta->lock, flags);
+
+ rssi = priv->last_rx_rssi;
+@@ -974,20 +969,19 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
+
+ IWL_DEBUG(IWL_DL_INFO | IWL_DL_RATE, "Network RSSI: %d\n", rssi);
+
+- rs_sta->start_rate =
+- iwl3945_get_rate_index_by_rssi(rssi, priv->phymode);
++ rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band);
+
+ IWL_DEBUG_RATE("leave: rssi %d assign rate index: "
+ "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate,
+ iwl3945_rates[rs_sta->start_rate].plcp);
+ }
+
+-void iwl3945_rate_control_register(struct ieee80211_hw *hw)
++int iwl3945_rate_control_register(void)
+ {
+- ieee80211_rate_control_register(&rs_ops);
++ return ieee80211_rate_control_register(&rs_ops);
+ }
+
+-void iwl3945_rate_control_unregister(struct ieee80211_hw *hw)
++void iwl3945_rate_control_unregister(void)
+ {
+ ieee80211_rate_control_unregister(&rs_ops);
+ }
+diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h
+index d5e9220..f085d33 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h
++++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+ *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+@@ -36,8 +36,8 @@ struct iwl3945_rate_info {
+ u8 next_rs; /* next rate used in rs algo */
+ u8 prev_rs_tgg; /* previous rate used in TGG rs algo */
+ u8 next_rs_tgg; /* next rate used in TGG rs algo */
+- u8 table_rs_index; /* index in rate scale table cmd */
+- u8 prev_table_rs; /* prev in rate table cmd */
++ u8 table_rs_index; /* index in rate scale table cmd */
++ u8 prev_table_rs; /* prev in rate table cmd */
+ };
+
+ /*
+@@ -159,7 +159,7 @@ enum {
+
+ #define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1)
+
+-#define IWL_INVALID_VALUE -1
++#define IWL_INV_TPT -1
+
+ #define IWL_MIN_RSSI_VAL -100
+ #define IWL_MAX_RSSI_VAL 0
+@@ -202,7 +202,7 @@ extern void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id);
+ * ieee80211_register_hw
+ *
+ */
+-extern void iwl3945_rate_control_register(struct ieee80211_hw *hw);
++extern int iwl3945_rate_control_register(void);
+
+ /**
+ * iwl3945_rate_control_unregister - Unregister the rate control callbacks
+@@ -210,6 +210,6 @@ extern void iwl3945_rate_control_register(struct ieee80211_hw *hw);
+ * This should be called after calling ieee80211_unregister_hw, but before
+ * the driver is unloaded.
+ */
+-extern void iwl3945_rate_control_unregister(struct ieee80211_hw *hw);
++extern void iwl3945_rate_control_unregister(void);
+
+ #endif
+diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
+index 8d4d91d..598e4ee 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
++++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+ *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+@@ -39,6 +39,7 @@
+ #include <asm/unaligned.h>
+ #include <net/mac80211.h>
+
++#include "iwl-3945-core.h"
+ #include "iwl-3945.h"
+ #include "iwl-helpers.h"
+ #include "iwl-3945-rs.h"
+@@ -183,6 +184,16 @@ void iwl3945_disable_events(struct iwl3945_priv *priv)
+
+ }
+
++static int iwl3945_hwrate_to_plcp_idx(u8 plcp)
++{
++ int idx;
++
++ for (idx = 0; idx < IWL_RATE_COUNT; idx++)
++ if (iwl3945_rates[idx].plcp == plcp)
++ return idx;
++ return -1;
++}
++
+ /**
+ * iwl3945_get_antenna_flags - Get antenna flags for RXON command
+ * @priv: eeprom and antenna fields are used to determine antenna flags
+@@ -216,14 +227,126 @@ __le32 iwl3945_get_antenna_flags(const struct iwl3945_priv *priv)
+ return 0; /* "diversity" is default if error */
+ }
+
++#ifdef CONFIG_IWL3945_DEBUG
++#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
++
++static const char *iwl3945_get_tx_fail_reason(u32 status)
++{
++ switch (status & TX_STATUS_MSK) {
++ case TX_STATUS_SUCCESS:
++ return "SUCCESS";
++ TX_STATUS_ENTRY(SHORT_LIMIT);
++ TX_STATUS_ENTRY(LONG_LIMIT);
++ TX_STATUS_ENTRY(FIFO_UNDERRUN);
++ TX_STATUS_ENTRY(MGMNT_ABORT);
++ TX_STATUS_ENTRY(NEXT_FRAG);
++ TX_STATUS_ENTRY(LIFE_EXPIRE);
++ TX_STATUS_ENTRY(DEST_PS);
++ TX_STATUS_ENTRY(ABORTED);
++ TX_STATUS_ENTRY(BT_RETRY);
++ TX_STATUS_ENTRY(STA_INVALID);
++ TX_STATUS_ENTRY(FRAG_DROPPED);
++ TX_STATUS_ENTRY(TID_DISABLE);
++ TX_STATUS_ENTRY(FRAME_FLUSHED);
++ TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL);
++ TX_STATUS_ENTRY(TX_LOCKED);
++ TX_STATUS_ENTRY(NO_BEACON_ON_RADAR);
++ }
++
++ return "UNKNOWN";
++}
++#else
++static inline const char *iwl3945_get_tx_fail_reason(u32 status)
++{
++ return "";
++}
++#endif
++
++
++/**
++ * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
++ *
++ * When FW advances 'R' index, all entries between old and new 'R' index
++ * need to be reclaimed. As result, some free space forms. If there is
++ * enough free space (> low mark), wake the stack that feeds us.
++ */
++static void iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv,
++ int txq_id, int index)
++{
++ struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
++ struct iwl3945_queue *q = &txq->q;
++ struct iwl3945_tx_info *tx_info;
++
++ BUG_ON(txq_id == IWL_CMD_QUEUE_NUM);
++
++ for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index;
++ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
++
++ tx_info = &txq->txb[txq->q.read_ptr];
++ ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0],
++ &tx_info->status);
++ tx_info->skb[0] = NULL;
++ iwl3945_hw_txq_free_tfd(priv, txq);
++ }
++
++ if (iwl3945_queue_space(q) > q->low_mark && (txq_id >= 0) &&
++ (txq_id != IWL_CMD_QUEUE_NUM) &&
++ priv->mac80211_registered)
++ ieee80211_wake_queue(priv->hw, txq_id);
++}
++
++/**
++ * iwl3945_rx_reply_tx - Handle Tx response
++ */
++static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv,
++ struct iwl3945_rx_mem_buffer *rxb)
++{
++ struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
++ u16 sequence = le16_to_cpu(pkt->hdr.sequence);
++ int txq_id = SEQ_TO_QUEUE(sequence);
++ int index = SEQ_TO_INDEX(sequence);
++ struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
++ struct ieee80211_tx_status *tx_status;
++ struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
++ u32 status = le32_to_cpu(tx_resp->status);
++ int rate_idx;
++
++ if ((index >= txq->q.n_bd) || (iwl3945_x2_queue_used(&txq->q, index) == 0)) {
++ IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
++ "is out of range [0-%d] %d %d\n", txq_id,
++ index, txq->q.n_bd, txq->q.write_ptr,
++ txq->q.read_ptr);
++ return;
++ }
++
++ tx_status = &(txq->txb[txq->q.read_ptr].status);
++
++ tx_status->retry_count = tx_resp->failure_frame;
++ /* tx_status->rts_retry_count = tx_resp->failure_rts; */
++ tx_status->flags = ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ?
++ IEEE80211_TX_STATUS_ACK : 0;
++
++ IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n",
++ txq_id, iwl3945_get_tx_fail_reason(status), status,
++ tx_resp->rate, tx_resp->failure_frame);
++
++ rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate);
++ tx_status->control.tx_rate = &priv->ieee_rates[rate_idx];
++ IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
++ iwl3945_tx_queue_reclaim(priv, txq_id, index);
++
++ if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
++ IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n");
++}
++
++
++
+ /*****************************************************************************
+ *
+ * Intel PRO/Wireless 3945ABG/BG Network Connection
+ *
+ * RX handler implementations
+ *
+- * Used by iwl-base.c
+- *
+ *****************************************************************************/
+
+ void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb)
+@@ -235,9 +358,161 @@ void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl3945_rx_mem_b
+
+ memcpy(&priv->statistics, pkt->u.raw, sizeof(priv->statistics));
+
++ iwl3945_led_background(priv);
++
+ priv->last_statistics_time = jiffies;
+ }
+
++/******************************************************************************
++ *
++ * Misc. internal state and helper functions
++ *
++ ******************************************************************************/
++#ifdef CONFIG_IWL3945_DEBUG
++
++/**
++ * iwl3945_report_frame - dump frame to syslog during debug sessions
++ *
++ * You may hack this function to show different aspects of received frames,
++ * including selective frame dumps.
++ * group100 parameter selects whether to show 1 out of 100 good frames.
++ */
++static void iwl3945_dbg_report_frame(struct iwl3945_priv *priv,
++ struct iwl3945_rx_packet *pkt,
++ struct ieee80211_hdr *header, int group100)
++{
++ u32 to_us;
++ u32 print_summary = 0;
++ u32 print_dump = 0; /* set to 1 to dump all frames' contents */
++ u32 hundred = 0;
++ u32 dataframe = 0;
++ u16 fc;
++ u16 seq_ctl;
++ u16 channel;
++ u16 phy_flags;
++ u16 length;
++ u16 status;
++ u16 bcn_tmr;
++ u32 tsf_low;
++ u64 tsf;
++ u8 rssi;
++ u8 agc;
++ u16 sig_avg;
++ u16 noise_diff;
++ struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
++ struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
++ struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
++ u8 *data = IWL_RX_DATA(pkt);
++
++ /* MAC header */
++ fc = le16_to_cpu(header->frame_control);
++ seq_ctl = le16_to_cpu(header->seq_ctrl);
++
++ /* metadata */
++ channel = le16_to_cpu(rx_hdr->channel);
++ phy_flags = le16_to_cpu(rx_hdr->phy_flags);
++ length = le16_to_cpu(rx_hdr->len);
++
++ /* end-of-frame status and timestamp */
++ status = le32_to_cpu(rx_end->status);
++ bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp);
++ tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff;
++ tsf = le64_to_cpu(rx_end->timestamp);
++
++ /* signal statistics */
++ rssi = rx_stats->rssi;
++ agc = rx_stats->agc;
++ sig_avg = le16_to_cpu(rx_stats->sig_avg);
++ noise_diff = le16_to_cpu(rx_stats->noise_diff);
++
++ to_us = !compare_ether_addr(header->addr1, priv->mac_addr);
++
++ /* if data frame is to us and all is good,
++ * (optionally) print summary for only 1 out of every 100 */
++ if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) ==
++ (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) {
++ dataframe = 1;
++ if (!group100)
++ print_summary = 1; /* print each frame */
++ else if (priv->framecnt_to_us < 100) {
++ priv->framecnt_to_us++;
++ print_summary = 0;
++ } else {
++ priv->framecnt_to_us = 0;
++ print_summary = 1;
++ hundred = 1;
++ }
++ } else {
++ /* print summary for all other frames */
++ print_summary = 1;
++ }
++
++ if (print_summary) {
++ char *title;
++ u32 rate;
++
++ if (hundred)
++ title = "100Frames";
++ else if (fc & IEEE80211_FCTL_RETRY)
++ title = "Retry";
++ else if (ieee80211_is_assoc_response(fc))
++ title = "AscRsp";
++ else if (ieee80211_is_reassoc_response(fc))
++ title = "RasRsp";
++ else if (ieee80211_is_probe_response(fc)) {
++ title = "PrbRsp";
++ print_dump = 1; /* dump frame contents */
++ } else if (ieee80211_is_beacon(fc)) {
++ title = "Beacon";
++ print_dump = 1; /* dump frame contents */
++ } else if (ieee80211_is_atim(fc))
++ title = "ATIM";
++ else if (ieee80211_is_auth(fc))
++ title = "Auth";
++ else if (ieee80211_is_deauth(fc))
++ title = "DeAuth";
++ else if (ieee80211_is_disassoc(fc))
++ title = "DisAssoc";
++ else
++ title = "Frame";
++
++ rate = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate);
++ if (rate == -1)
++ rate = 0;
++ else
++ rate = iwl3945_rates[rate].ieee / 2;
++
++ /* print frame summary.
++ * MAC addresses show just the last byte (for brevity),
++ * but you can hack it to show more, if you'd like to. */
++ if (dataframe)
++ IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, "
++ "len=%u, rssi=%d, chnl=%d, rate=%u, \n",
++ title, fc, header->addr1[5],
++ length, rssi, channel, rate);
++ else {
++ /* src/dst addresses assume managed mode */
++ IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, "
++ "src=0x%02x, rssi=%u, tim=%lu usec, "
++ "phy=0x%02x, chnl=%d\n",
++ title, fc, header->addr1[5],
++ header->addr3[5], rssi,
++ tsf_low - priv->scan_start_tsf,
++ phy_flags, channel);
++ }
++ }
++ if (print_dump)
++ iwl3945_print_hex_dump(IWL_DL_RX, data, length);
++}
++#else
++static inline void iwl3945_dbg_report_frame(struct iwl3945_priv *priv,
++ struct iwl3945_rx_packet *pkt,
++ struct ieee80211_hdr *header, int group100)
++{
++}
++#endif
++
++
+ static void iwl3945_add_radiotap(struct iwl3945_priv *priv,
+ struct sk_buff *skb,
+ struct iwl3945_rx_frame_hdr *rx_hdr,
+@@ -247,9 +522,9 @@ static void iwl3945_add_radiotap(struct iwl3945_priv *priv,
+ * the information provided in the skb from the hardware */
+ s8 signal = stats->ssi;
+ s8 noise = 0;
+- int rate = stats->rate;
++ int rate = stats->rate_idx;
+ u64 tsf = stats->mactime;
+- __le16 phy_flags_hw = rx_hdr->phy_flags;
++ __le16 phy_flags_hw = rx_hdr->phy_flags, antenna;
+
+ struct iwl3945_rt_rx_hdr {
+ struct ieee80211_radiotap_header rt_hdr;
+@@ -315,15 +590,14 @@ static void iwl3945_add_radiotap(struct iwl3945_priv *priv,
+ IEEE80211_CHAN_2GHZ),
+ &iwl3945_rt->rt_chbitmask);
+
+- rate = iwl3945_rate_index_from_plcp(rate);
+ if (rate == -1)
+ iwl3945_rt->rt_rate = 0;
+ else
+ iwl3945_rt->rt_rate = iwl3945_rates[rate].ieee;
+
+ /* antenna number */
+- iwl3945_rt->rt_antenna =
+- le16_to_cpu(phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
++ antenna = phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK;
++ iwl3945_rt->rt_antenna = le16_to_cpu(antenna) >> 4;
+
+ /* set the preamble flag if we have it */
+ if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
+@@ -368,6 +642,10 @@ static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data,
+ if (priv->add_radiotap)
+ iwl3945_add_radiotap(priv, rxb->skb, rx_hdr, stats);
+
++#ifdef CONFIG_IWL3945_LEDS
++ if (is_data)
++ priv->rxtxpackets += len;
++#endif
+ ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats);
+ rxb->skb = NULL;
+ }
+@@ -377,25 +655,28 @@ static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data,
+ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
+ struct iwl3945_rx_mem_buffer *rxb)
+ {
++ struct ieee80211_hdr *header;
++ struct ieee80211_rx_status rx_status;
+ struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
+ struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
+ struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
+- struct ieee80211_hdr *header;
++ int snr;
+ u16 rx_stats_sig_avg = le16_to_cpu(rx_stats->sig_avg);
+ u16 rx_stats_noise_diff = le16_to_cpu(rx_stats->noise_diff);
+- struct ieee80211_rx_status stats = {
+- .mactime = le64_to_cpu(rx_end->timestamp),
+- .freq = ieee80211chan2mhz(le16_to_cpu(rx_hdr->channel)),
+- .channel = le16_to_cpu(rx_hdr->channel),
+- .phymode = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
+- MODE_IEEE80211G : MODE_IEEE80211A,
+- .antenna = 0,
+- .rate = rx_hdr->rate,
+- .flag = 0,
+- };
+ u8 network_packet;
+- int snr;
++
++ rx_status.antenna = 0;
++ rx_status.flag = 0;
++ rx_status.mactime = le64_to_cpu(rx_end->timestamp);
++ rx_status.freq =
++ ieee80211_frequency_to_channel(le16_to_cpu(rx_hdr->channel));
++ rx_status.band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
++ IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
++
++ rx_status.rate_idx = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate);
++ if (rx_status.band == IEEE80211_BAND_5GHZ)
++ rx_status.rate_idx -= IWL_FIRST_OFDM_RATE;
+
+ if ((unlikely(rx_stats->phy_count > 20))) {
+ IWL_DEBUG_DROP
+@@ -411,12 +692,12 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
+ }
+
+ if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
+- iwl3945_handle_data_packet(priv, 1, rxb, &stats);
++ iwl3945_handle_data_packet(priv, 1, rxb, &rx_status);
+ return;
+ }
+
+ /* Convert 3945's rssi indicator to dBm */
+- stats.ssi = rx_stats->rssi - IWL_RSSI_OFFSET;
++ rx_status.ssi = rx_stats->rssi - IWL_RSSI_OFFSET;
+
+ /* Set default noise value to -127 */
+ if (priv->last_rx_noise == 0)
+@@ -432,51 +713,47 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
+ * signal-to-noise ratio (SNR) is (sig_avg / noise_diff).
+ * Convert linear SNR to dB SNR, then subtract that from rssi dBm
+ * to obtain noise level in dBm.
+- * Calculate stats.signal (quality indicator in %) based on SNR. */
++ * Calculate rx_status.signal (quality indicator in %) based on SNR. */
+ if (rx_stats_noise_diff) {
+ snr = rx_stats_sig_avg / rx_stats_noise_diff;
+- stats.noise = stats.ssi - iwl3945_calc_db_from_ratio(snr);
+- stats.signal = iwl3945_calc_sig_qual(stats.ssi, stats.noise);
++ rx_status.noise = rx_status.ssi -
++ iwl3945_calc_db_from_ratio(snr);
++ rx_status.signal = iwl3945_calc_sig_qual(rx_status.ssi,
++ rx_status.noise);
+
+ /* If noise info not available, calculate signal quality indicator (%)
+ * using just the dBm signal level. */
+ } else {
+- stats.noise = priv->last_rx_noise;
+- stats.signal = iwl3945_calc_sig_qual(stats.ssi, 0);
++ rx_status.noise = priv->last_rx_noise;
++ rx_status.signal = iwl3945_calc_sig_qual(rx_status.ssi, 0);
+ }
+
+
+ IWL_DEBUG_STATS("Rssi %d noise %d qual %d sig_avg %d noise_diff %d\n",
+- stats.ssi, stats.noise, stats.signal,
++ rx_status.ssi, rx_status.noise, rx_status.signal,
+ rx_stats_sig_avg, rx_stats_noise_diff);
+
+- stats.freq = ieee80211chan2mhz(stats.channel);
+-
+- /* can be covered by iwl3945_report_frame() in most cases */
+-/* IWL_DEBUG_RX("RX status: 0x%08X\n", rx_end->status); */
+-
+ header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
+
+ network_packet = iwl3945_is_network_packet(priv, header);
+
+-#ifdef CONFIG_IWL3945_DEBUG
+- if (iwl3945_debug_level & IWL_DL_STATS && net_ratelimit())
+- IWL_DEBUG_STATS
+- ("[%c] %d RSSI: %d Signal: %u, Noise: %u, Rate: %u\n",
+- network_packet ? '*' : ' ',
+- stats.channel, stats.ssi, stats.ssi,
+- stats.ssi, stats.rate);
++ IWL_DEBUG_STATS_LIMIT("[%c] %d RSSI:%d Signal:%u, Noise:%u, Rate:%u\n",
++ network_packet ? '*' : ' ',
++ le16_to_cpu(rx_hdr->channel),
++ rx_status.ssi, rx_status.ssi,
++ rx_status.ssi, rx_status.rate_idx);
+
++#ifdef CONFIG_IWL3945_DEBUG
+ if (iwl3945_debug_level & (IWL_DL_RX))
+ /* Set "1" to report good data frames in groups of 100 */
+- iwl3945_report_frame(priv, pkt, header, 1);
++ iwl3945_dbg_report_frame(priv, pkt, header, 1);
+ #endif
+
+ if (network_packet) {
+ priv->last_beacon_time = le32_to_cpu(rx_end->beacon_timestamp);
+ priv->last_tsf = le64_to_cpu(rx_end->timestamp);
+- priv->last_rx_rssi = stats.ssi;
+- priv->last_rx_noise = stats.noise;
++ priv->last_rx_rssi = rx_status.ssi;
++ priv->last_rx_noise = rx_status.noise;
+ }
+
+ switch (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FTYPE) {
+@@ -563,7 +840,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
+ }
+ }
+
+- iwl3945_handle_data_packet(priv, 0, rxb, &stats);
++ iwl3945_handle_data_packet(priv, 0, rxb, &rx_status);
+ break;
+
+ case IEEE80211_FTYPE_CTL:
+@@ -580,7 +857,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
+ print_mac(mac2, header->addr2),
+ print_mac(mac3, header->addr3));
+ else
+- iwl3945_handle_data_packet(priv, 1, rxb, &stats);
++ iwl3945_handle_data_packet(priv, 1, rxb, &rx_status);
+ break;
+ }
+ }
+@@ -689,7 +966,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv,
+ struct ieee80211_hdr *hdr, int sta_id, int tx_id)
+ {
+ unsigned long flags;
+- u16 rate_index = min(ctrl->tx_rate & 0xffff, IWL_RATE_COUNT - 1);
++ u16 rate_index = min(ctrl->tx_rate->hw_value & 0xffff, IWL_RATE_COUNT - 1);
+ u16 rate_mask;
+ int rate;
+ u8 rts_retry_limit;
+@@ -709,7 +986,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv,
+ priv->stations[sta_id].current_rate.rate_n_flags = rate;
+
+ if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
+- (sta_id != IWL3945_BROADCAST_ID) &&
++ (sta_id != priv->hw_setting.bcast_sta_id) &&
+ (sta_id != IWL_MULTICAST_ID))
+ priv->stations[IWL_STA_ID].current_rate.rate_n_flags = rate;
+
+@@ -996,19 +1273,19 @@ int iwl3945_hw_nic_init(struct iwl3945_priv *priv)
+ if (rev_id & PCI_CFG_REV_ID_BIT_RTP)
+ IWL_DEBUG_INFO("RTP type \n");
+ else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) {
+- IWL_DEBUG_INFO("ALM-MB type\n");
++ IWL_DEBUG_INFO("3945 RADIO-MB type\n");
+ iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+- CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MB);
++ CSR39_HW_IF_CONFIG_REG_BIT_3945_MB);
+ } else {
+- IWL_DEBUG_INFO("ALM-MM type\n");
++ IWL_DEBUG_INFO("3945 RADIO-MM type\n");
+ iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+- CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MM);
++ CSR39_HW_IF_CONFIG_REG_BIT_3945_MM);
+ }
+
+ if (EEPROM_SKU_CAP_OP_MODE_MRC == priv->eeprom.sku_cap) {
+ IWL_DEBUG_INFO("SKU OP mode is mrc\n");
+ iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+- CSR_HW_IF_CONFIG_REG_BIT_SKU_MRC);
++ CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC);
+ } else
+ IWL_DEBUG_INFO("SKU OP mode is basic\n");
+
+@@ -1016,24 +1293,24 @@ int iwl3945_hw_nic_init(struct iwl3945_priv *priv)
+ IWL_DEBUG_INFO("3945ABG revision is 0x%X\n",
+ priv->eeprom.board_revision);
+ iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+- CSR_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
++ CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
+ } else {
+ IWL_DEBUG_INFO("3945ABG revision is 0x%X\n",
+ priv->eeprom.board_revision);
+ iwl3945_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
+- CSR_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
++ CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
+ }
+
+ if (priv->eeprom.almgor_m_version <= 1) {
+ iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+- CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A);
++ CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A);
+ IWL_DEBUG_INFO("Card M type A version is 0x%X\n",
+ priv->eeprom.almgor_m_version);
+ } else {
+ IWL_DEBUG_INFO("Card M type B version is 0x%X\n",
+ priv->eeprom.almgor_m_version);
+ iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+- CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B);
++ CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B);
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+@@ -1552,14 +1829,14 @@ int iwl3945_hw_reg_send_txpower(struct iwl3945_priv *priv)
+ .channel = priv->active_rxon.channel,
+ };
+
+- txpower.band = (priv->phymode == MODE_IEEE80211A) ? 0 : 1;
++ txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1;
+ ch_info = iwl3945_get_channel_info(priv,
+- priv->phymode,
++ priv->band,
+ le16_to_cpu(priv->active_rxon.channel));
+ if (!ch_info) {
+ IWL_ERROR
+ ("Failed to get channel info for channel %d [%d]\n",
+- le16_to_cpu(priv->active_rxon.channel), priv->phymode);
++ le16_to_cpu(priv->active_rxon.channel), priv->band);
+ return -EINVAL;
+ }
+
+@@ -2241,8 +2518,8 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv)
+ table[index].next_rate_index = iwl3945_rates[prev_index].table_rs_index;
+ }
+
+- switch (priv->phymode) {
+- case MODE_IEEE80211A:
++ switch (priv->band) {
++ case IEEE80211_BAND_5GHZ:
+ IWL_DEBUG_RATE("Select A mode rate scale\n");
+ /* If one of the following CCK rates is used,
+ * have it fall back to the 6M OFDM rate */
+@@ -2257,8 +2534,8 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv)
+ iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
+ break;
+
+- case MODE_IEEE80211B:
+- IWL_DEBUG_RATE("Select B mode rate scale\n");
++ case IEEE80211_BAND_2GHZ:
++ IWL_DEBUG_RATE("Select B/G mode rate scale\n");
+ /* If an OFDM rate is used, have it fall back to the
+ * 1M CCK rates */
+ for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE; i++)
+@@ -2269,7 +2546,7 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv)
+ break;
+
+ default:
+- IWL_DEBUG_RATE("Select G mode rate scale\n");
++ WARN_ON(1);
+ break;
+ }
+
+@@ -2303,7 +2580,6 @@ int iwl3945_hw_set_hw_setting(struct iwl3945_priv *priv)
+ return -ENOMEM;
+ }
+
+- priv->hw_setting.ac_queue_count = AC_NUM;
+ priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE;
+ priv->hw_setting.max_pkt_size = 2342;
+ priv->hw_setting.tx_cmd_len = sizeof(struct iwl3945_tx_cmd);
+@@ -2311,6 +2587,8 @@ int iwl3945_hw_set_hw_setting(struct iwl3945_priv *priv)
+ priv->hw_setting.max_rxq_log = RX_QUEUE_SIZE_LOG;
+ priv->hw_setting.max_stations = IWL3945_STATION_COUNT;
+ priv->hw_setting.bcast_sta_id = IWL3945_BROADCAST_ID;
++
++ priv->hw_setting.tx_ant_num = 2;
+ return 0;
+ }
+
+@@ -2323,7 +2601,7 @@ unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv,
+ tx_beacon_cmd = (struct iwl3945_tx_beacon_cmd *)&frame->u;
+ memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
+
+- tx_beacon_cmd->tx.sta_id = IWL3945_BROADCAST_ID;
++ tx_beacon_cmd->tx.sta_id = priv->hw_setting.bcast_sta_id;
+ tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+
+ frame_size = iwl3945_fill_beacon_frame(priv,
+@@ -2350,6 +2628,7 @@ unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv,
+
+ void iwl3945_hw_rx_handler_setup(struct iwl3945_priv *priv)
+ {
++ priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx;
+ priv->rx_handlers[REPLY_3945_RX] = iwl3945_rx_reply_rx;
+ }
+
+@@ -2364,9 +2643,25 @@ void iwl3945_hw_cancel_deferred_work(struct iwl3945_priv *priv)
+ cancel_delayed_work(&priv->thermal_periodic);
+ }
+
++static struct iwl_3945_cfg iwl3945_bg_cfg = {
++ .name = "3945BG",
++ .fw_name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode",
++ .sku = IWL_SKU_G,
++};
++
++static struct iwl_3945_cfg iwl3945_abg_cfg = {
++ .name = "3945ABG",
++ .fw_name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode",
++ .sku = IWL_SKU_A|IWL_SKU_G,
++};
++
+ struct pci_device_id iwl3945_hw_card_ids[] = {
+- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4222)},
+- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4227)},
++ {IWL_PCI_DEVICE(0x4222, 0x1005, iwl3945_bg_cfg)},
++ {IWL_PCI_DEVICE(0x4222, 0x1034, iwl3945_bg_cfg)},
++ {IWL_PCI_DEVICE(0x4222, 0x1044, iwl3945_bg_cfg)},
++ {IWL_PCI_DEVICE(0x4227, 0x1014, iwl3945_bg_cfg)},
++ {IWL_PCI_DEVICE(0x4222, PCI_ANY_ID, iwl3945_abg_cfg)},
++ {IWL_PCI_DEVICE(0x4227, PCI_ANY_ID, iwl3945_abg_cfg)},
+ {0}
+ };
+
+diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
+index 1da14f9..45c1c55 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
++++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+ *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+@@ -40,9 +40,17 @@
+ extern struct pci_device_id iwl3945_hw_card_ids[];
+
+ #define DRV_NAME "iwl3945"
+-#include "iwl-3945-hw.h"
++#include "iwl-csr.h"
+ #include "iwl-prph.h"
++#include "iwl-3945-hw.h"
+ #include "iwl-3945-debug.h"
++#include "iwl-3945-led.h"
++
++/* Change firmware file name, using "-" and incrementing number,
++ * *only* when uCode interface or architecture changes so that it
++ * is not compatible with earlier drivers.
++ * This number will also appear in << 8 position of 1st dword of uCode file */
++#define IWL3945_UCODE_API "-1"
+
+ /* Default noise level to report when noise measurement is not available.
+ * This may be because we're:
+@@ -109,6 +117,9 @@ struct iwl3945_queue {
+ * space less than this */
+ } __attribute__ ((packed));
+
++int iwl3945_queue_space(const struct iwl3945_queue *q);
++int iwl3945_x2_queue_used(const struct iwl3945_queue *q, int i);
++
+ #define MAX_NUM_OF_TBS (20)
+
+ /* One for each TFD */
+@@ -195,7 +206,7 @@ struct iwl3945_channel_info {
+
+ u8 group_index; /* 0-4, maps channel to group1/2/3/4/5 */
+ u8 band_index; /* 0-4, maps channel to band1/2/3/4/5 */
+- u8 phymode; /* MODE_IEEE80211{A,B,G} */
++ enum ieee80211_band band;
+
+ /* Radio/DSP gain settings for each "normal" data Tx rate.
+ * These include, in addition to RF and DSP gain, a few fields for
+@@ -269,8 +280,8 @@ struct iwl3945_frame {
+
+ #define SEQ_TO_QUEUE(x) ((x >> 8) & 0xbf)
+ #define QUEUE_TO_SEQ(x) ((x & 0xbf) << 8)
+-#define SEQ_TO_INDEX(x) (x & 0xff)
+-#define INDEX_TO_SEQ(x) (x & 0xff)
++#define SEQ_TO_INDEX(x) ((u8)(x & 0xff))
++#define INDEX_TO_SEQ(x) ((u8)(x & 0xff))
+ #define SEQ_HUGE_FRAME (0x4000)
+ #define SEQ_RX_FRAME __constant_cpu_to_le16(0x8000)
+ #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
+@@ -390,23 +401,24 @@ struct iwl3945_rx_queue {
+ #define MIN_B_CHANNELS 1
+
+ #define STATUS_HCMD_ACTIVE 0 /* host command in progress */
+-#define STATUS_INT_ENABLED 1
+-#define STATUS_RF_KILL_HW 2
+-#define STATUS_RF_KILL_SW 3
+-#define STATUS_INIT 4
+-#define STATUS_ALIVE 5
+-#define STATUS_READY 6
+-#define STATUS_TEMPERATURE 7
+-#define STATUS_GEO_CONFIGURED 8
+-#define STATUS_EXIT_PENDING 9
+-#define STATUS_IN_SUSPEND 10
+-#define STATUS_STATISTICS 11
+-#define STATUS_SCANNING 12
+-#define STATUS_SCAN_ABORTING 13
+-#define STATUS_SCAN_HW 14
+-#define STATUS_POWER_PMI 15
+-#define STATUS_FW_ERROR 16
+-#define STATUS_CONF_PENDING 17
++#define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */
++#define STATUS_INT_ENABLED 2
++#define STATUS_RF_KILL_HW 3
++#define STATUS_RF_KILL_SW 4
++#define STATUS_INIT 5
++#define STATUS_ALIVE 6
++#define STATUS_READY 7
++#define STATUS_TEMPERATURE 8
++#define STATUS_GEO_CONFIGURED 9
++#define STATUS_EXIT_PENDING 10
++#define STATUS_IN_SUSPEND 11
++#define STATUS_STATISTICS 12
++#define STATUS_SCANNING 13
++#define STATUS_SCAN_ABORTING 14
++#define STATUS_SCAN_HW 15
++#define STATUS_POWER_PMI 16
++#define STATUS_FW_ERROR 17
++#define STATUS_CONF_PENDING 18
+
+ #define MAX_TID_COUNT 9
+
+@@ -431,8 +443,6 @@ union iwl3945_ht_rate_supp {
+ };
+ };
+
+-#ifdef CONFIG_IWL3945_QOS
+-
+ union iwl3945_qos_capabity {
+ struct {
+ u8 edca_count:4; /* bit 0-3 */
+@@ -460,7 +470,6 @@ struct iwl3945_qos_info {
+ union iwl3945_qos_capabity qos_cap;
+ struct iwl3945_qosparam_cmd def_qos_parm;
+ };
+-#endif /*CONFIG_IWL3945_QOS */
+
+ #define STA_PS_STATUS_WAKE 0
+ #define STA_PS_STATUS_SLEEP 1
+@@ -511,8 +520,8 @@ struct iwl3945_ibss_seq {
+ /**
+ * struct iwl3945_driver_hw_info
+ * @max_txq_num: Max # Tx queues supported
+- * @ac_queue_count: # Tx queues for EDCA Access Categories (AC)
+ * @tx_cmd_len: Size of Tx command (but not including frame itself)
++ * @tx_ant_num: Number of TX antennas
+ * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
+ * @rx_buf_size:
+ * @max_pkt_size:
+@@ -524,8 +533,8 @@ struct iwl3945_ibss_seq {
+ */
+ struct iwl3945_driver_hw_info {
+ u16 max_txq_num;
+- u16 ac_queue_count;
+ u16 tx_cmd_len;
++ u16 tx_ant_num;
+ u16 max_rxq_size;
+ u32 rx_buf_size;
+ u32 max_pkt_size;
+@@ -561,16 +570,6 @@ extern int iwl3945_is_network_packet(struct iwl3945_priv *priv,
+ struct ieee80211_hdr *header);
+ extern int iwl3945_power_init_handle(struct iwl3945_priv *priv);
+ extern int iwl3945_eeprom_init(struct iwl3945_priv *priv);
+-#ifdef CONFIG_IWL3945_DEBUG
+-extern void iwl3945_report_frame(struct iwl3945_priv *priv,
+- struct iwl3945_rx_packet *pkt,
+- struct ieee80211_hdr *header, int group100);
+-#else
+-static inline void iwl3945_report_frame(struct iwl3945_priv *priv,
+- struct iwl3945_rx_packet *pkt,
+- struct ieee80211_hdr *header,
+- int group100) {}
+-#endif
+ extern void iwl3945_handle_data_packet_monitor(struct iwl3945_priv *priv,
+ struct iwl3945_rx_mem_buffer *rxb,
+ void *data, short len,
+@@ -688,25 +687,28 @@ enum {
+
+ #endif
+
++#define IWL_MAX_NUM_QUEUES IWL39_MAX_NUM_QUEUES
++
+ struct iwl3945_priv {
+
+ /* ieee device used by generic ieee processing code */
+ struct ieee80211_hw *hw;
+ struct ieee80211_channel *ieee_channels;
+ struct ieee80211_rate *ieee_rates;
++ struct iwl_3945_cfg *cfg; /* device configuration */
+
+ /* temporary frame storage list */
+ struct list_head free_frames;
+ int frames_count;
+
+- u8 phymode;
++ enum ieee80211_band band;
+ int alloc_rxb_skb;
+ bool add_radiotap;
+
+ void (*rx_handlers[REPLY_MAX])(struct iwl3945_priv *priv,
+ struct iwl3945_rx_mem_buffer *rxb);
+
+- const struct ieee80211_hw_mode *modes;
++ struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
+
+ #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
+ /* spectrum measurement report caching */
+@@ -779,13 +781,15 @@ struct iwl3945_priv {
+ struct iwl3945_init_alive_resp card_alive_init;
+ struct iwl3945_alive_resp card_alive;
+
+-#ifdef LED
+- /* LED related variables */
+- struct iwl3945_activity_blink activity;
+- unsigned long led_packets;
+- int led_state;
++#ifdef CONFIG_IWL3945_LEDS
++ struct iwl3945_led led[IWL_LED_TRG_MAX];
++ unsigned long last_blink_time;
++ u8 last_blink_rate;
++ u8 allow_blinking;
++ unsigned int rxtxpackets;
+ #endif
+
++
+ u16 active_rate;
+ u16 active_rate_basic;
+
+@@ -803,7 +807,6 @@ struct iwl3945_priv {
+ struct iwl3945_tx_queue txq[IWL_MAX_NUM_QUEUES];
+
+ unsigned long status;
+- u32 config;
+
+ int last_rx_rssi; /* From Rx packet statisitics */
+ int last_rx_noise; /* From beacon statistics */
+@@ -830,10 +833,9 @@ struct iwl3945_priv {
+ struct iwl3945_station_entry stations[IWL_STATION_COUNT];
+
+ /* Indication if ieee80211_ops->open has been called */
+- int is_open;
++ u8 is_open;
+
+ u8 mac80211_registered;
+- int is_abg;
+
+ u32 notif_missed_beacons;
+
+@@ -852,7 +854,7 @@ struct iwl3945_priv {
+ /* eeprom */
+ struct iwl3945_eeprom eeprom;
+
+- int iw_mode;
++ enum ieee80211_if_types iw_mode;
+
+ struct sk_buff *ibss_beacon;
+
+@@ -869,9 +871,7 @@ struct iwl3945_priv {
+ u16 assoc_capability;
+ u8 ps_mode;
+
+-#ifdef CONFIG_IWL3945_QOS
+ struct iwl3945_qos_info qos_data;
+-#endif /*CONFIG_IWL3945_QOS */
+
+ struct workqueue_struct *workqueue;
+
+@@ -937,13 +937,12 @@ static inline int is_channel_radar(const struct iwl3945_channel_info *ch_info)
+
+ static inline u8 is_channel_a_band(const struct iwl3945_channel_info *ch_info)
+ {
+- return ch_info->phymode == MODE_IEEE80211A;
++ return ch_info->band == IEEE80211_BAND_5GHZ;
+ }
+
+ static inline u8 is_channel_bg_band(const struct iwl3945_channel_info *ch_info)
+ {
+- return ((ch_info->phymode == MODE_IEEE80211B) ||
+- (ch_info->phymode == MODE_IEEE80211G));
++ return ch_info->band == IEEE80211_BAND_2GHZ;
+ }
+
+ static inline int is_channel_passive(const struct iwl3945_channel_info *ch)
+@@ -956,18 +955,8 @@ static inline int is_channel_ibss(const struct iwl3945_channel_info *ch)
+ return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0;
+ }
+
+-static inline int iwl3945_rate_index_from_plcp(int plcp)
+-{
+- int i;
+-
+- for (i = 0; i < IWL_RATE_COUNT; i++)
+- if (iwl3945_rates[i].plcp == plcp)
+- return i;
+- return -1;
+-}
+-
+ extern const struct iwl3945_channel_info *iwl3945_get_channel_info(
+- const struct iwl3945_priv *priv, int phymode, u16 channel);
++ const struct iwl3945_priv *priv, enum ieee80211_band band, u16 channel);
+
+ /* Requires full declaration of iwl3945_priv before including */
+ #include "iwl-3945-io.h"
+diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h
+index f3470c8..3bcd107 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h
++++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h
+@@ -5,7 +5,7 @@
+ *
+ * GPL LICENSE SUMMARY
+ *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+@@ -30,7 +30,7 @@
+ *
+ * BSD LICENSE
+ *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -84,6 +84,9 @@ enum {
+ REPLY_REMOVE_STA = 0x19, /* not used */
+ REPLY_REMOVE_ALL_STA = 0x1a, /* not used */
+
++ /* Security */
++ REPLY_WEPKEY = 0x20,
++
+ /* RX, TX, LEDs */
+ REPLY_TX = 0x1c,
+ REPLY_RATE_SCALE = 0x47, /* 3945 only */
+@@ -139,7 +142,7 @@ enum {
+ REPLY_PHY_CALIBRATION_CMD = 0xb0,
+ REPLY_RX_PHY_CMD = 0xc0,
+ REPLY_RX_MPDU_CMD = 0xc1,
+- REPLY_4965_RX = 0xc3,
++ REPLY_RX = 0xc3,
+ REPLY_COMPRESSED_BA = 0xc5,
+ REPLY_MAX = 0xff
+ };
+@@ -151,16 +154,16 @@ enum {
+ *
+ *****************************************************************************/
+
+-/* iwl4965_cmd_header flags value */
++/* iwl_cmd_header flags value */
+ #define IWL_CMD_FAILED_MSK 0x40
+
+ /**
+- * struct iwl4965_cmd_header
++ * struct iwl_cmd_header
+ *
+ * This header format appears in the beginning of each command sent from the
+ * driver, and each response/notification received from uCode.
+ */
+-struct iwl4965_cmd_header {
++struct iwl_cmd_header {
+ u8 cmd; /* Command ID: REPLY_RXON, etc. */
+ u8 flags; /* IWL_CMD_* */
+ /*
+@@ -194,7 +197,7 @@ struct iwl4965_cmd_header {
+ * 4965 rate_n_flags bit fields
+ *
+ * rate_n_flags format is used in following 4965 commands:
+- * REPLY_4965_RX (response only)
++ * REPLY_RX (response only)
+ * REPLY_TX (both command and response)
+ * REPLY_TX_LINK_QUALITY_CMD
+ *
+@@ -266,11 +269,10 @@ struct iwl4965_cmd_header {
+ * 10 B active, A inactive
+ * 11 Both active
+ */
+-#define RATE_MCS_ANT_A_POS 14
+-#define RATE_MCS_ANT_B_POS 15
+-#define RATE_MCS_ANT_A_MSK 0x4000
+-#define RATE_MCS_ANT_B_MSK 0x8000
+-#define RATE_MCS_ANT_AB_MSK 0xc000
++#define RATE_MCS_ANT_POS 14
++#define RATE_MCS_ANT_A_MSK 0x04000
++#define RATE_MCS_ANT_B_MSK 0x08000
++#define RATE_MCS_ANT_AB_MSK 0x0C000
+
+
+ /**
+@@ -727,14 +729,21 @@ struct iwl4965_qosparam_cmd {
+ #define STA_CONTROL_MODIFY_MSK 0x01
+
+ /* key flags __le16*/
+-#define STA_KEY_FLG_ENCRYPT_MSK __constant_cpu_to_le16(0x7)
+-#define STA_KEY_FLG_NO_ENC __constant_cpu_to_le16(0x0)
+-#define STA_KEY_FLG_WEP __constant_cpu_to_le16(0x1)
+-#define STA_KEY_FLG_CCMP __constant_cpu_to_le16(0x2)
+-#define STA_KEY_FLG_TKIP __constant_cpu_to_le16(0x3)
++#define STA_KEY_FLG_ENCRYPT_MSK __constant_cpu_to_le16(0x0007)
++#define STA_KEY_FLG_NO_ENC __constant_cpu_to_le16(0x0000)
++#define STA_KEY_FLG_WEP __constant_cpu_to_le16(0x0001)
++#define STA_KEY_FLG_CCMP __constant_cpu_to_le16(0x0002)
++#define STA_KEY_FLG_TKIP __constant_cpu_to_le16(0x0003)
+
+ #define STA_KEY_FLG_KEYID_POS 8
+ #define STA_KEY_FLG_INVALID __constant_cpu_to_le16(0x0800)
++/* wep key is either from global key (0) or from station info array (1) */
++#define STA_KEY_FLG_MAP_KEY_MSK __constant_cpu_to_le16(0x0008)
++
++/* wep key in STA: 5-bytes (0) or 13-bytes (1) */
++#define STA_KEY_FLG_KEY_SIZE_MSK __constant_cpu_to_le16(0x1000)
++#define STA_KEY_MULTICAST_MSK __constant_cpu_to_le16(0x4000)
++#define STA_KEY_MAX_NUM 8
+
+ /* Flags indicate whether to modify vs. don't change various station params */
+ #define STA_MODIFY_KEY_MASK 0x01
+@@ -752,7 +761,8 @@ struct iwl4965_keyinfo {
+ u8 tkip_rx_tsc_byte2; /* TSC[2] for key mix ph1 detection */
+ u8 reserved1;
+ __le16 tkip_rx_ttak[5]; /* 10-byte unicast TKIP TTAK */
+- __le16 reserved2;
++ u8 key_offset;
++ u8 reserved2;
+ u8 key[16]; /* 16-byte unicast decryption key */
+ } __attribute__ ((packed));
+
+@@ -842,6 +852,30 @@ struct iwl4965_add_sta_resp {
+ u8 status; /* ADD_STA_* */
+ } __attribute__ ((packed));
+
++/*
++ * REPLY_WEP_KEY = 0x20
++ */
++struct iwl_wep_key {
++ u8 key_index;
++ u8 key_offset;
++ u8 reserved1[2];
++ u8 key_size;
++ u8 reserved2[3];
++ u8 key[16];
++} __attribute__ ((packed));
++
++struct iwl_wep_cmd {
++ u8 num_keys;
++ u8 global_key_type;
++ u8 flags;
++ u8 reserved;
++ struct iwl_wep_key key[0];
++} __attribute__ ((packed));
++
++#define WEP_KEY_WEP_TYPE 1
++#define WEP_KEYS_MAX 4
++#define WEP_INVALID_OFFSET 0xff
++#define WEP_KEY_LEN_128 13
+
+ /******************************************************************************
+ * (4)
+@@ -868,26 +902,35 @@ struct iwl4965_rx_frame_hdr {
+ u8 payload[0];
+ } __attribute__ ((packed));
+
+-#define RX_RES_STATUS_NO_CRC32_ERROR __constant_cpu_to_le32(1 << 0)
+-#define RX_RES_STATUS_NO_RXE_OVERFLOW __constant_cpu_to_le32(1 << 1)
++#define RX_RES_STATUS_NO_CRC32_ERROR __constant_cpu_to_le32(1 << 0)
++#define RX_RES_STATUS_NO_RXE_OVERFLOW __constant_cpu_to_le32(1 << 1)
++
++#define RX_RES_PHY_FLAGS_BAND_24_MSK __constant_cpu_to_le16(1 << 0)
++#define RX_RES_PHY_FLAGS_MOD_CCK_MSK __constant_cpu_to_le16(1 << 1)
++#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK __constant_cpu_to_le16(1 << 2)
++#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK __constant_cpu_to_le16(1 << 3)
++#define RX_RES_PHY_FLAGS_ANTENNA_MSK __constant_cpu_to_le16(0xf0)
++
++#define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8)
++#define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8)
++#define RX_RES_STATUS_SEC_TYPE_WEP (0x1 << 8)
++#define RX_RES_STATUS_SEC_TYPE_CCMP (0x2 << 8)
++#define RX_RES_STATUS_SEC_TYPE_TKIP (0x3 << 8)
++#define RX_RES_STATUS_SEC_TYPE_ERR (0x7 << 8)
+
+-#define RX_RES_PHY_FLAGS_BAND_24_MSK __constant_cpu_to_le16(1 << 0)
+-#define RX_RES_PHY_FLAGS_MOD_CCK_MSK __constant_cpu_to_le16(1 << 1)
+-#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK __constant_cpu_to_le16(1 << 2)
+-#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK __constant_cpu_to_le16(1 << 3)
+-#define RX_RES_PHY_FLAGS_ANTENNA_MSK __constant_cpu_to_le16(0xf0)
++#define RX_RES_STATUS_STATION_FOUND (1<<6)
++#define RX_RES_STATUS_NO_STATION_INFO_MISMATCH (1<<7)
+
+-#define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8)
+-#define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8)
+-#define RX_RES_STATUS_SEC_TYPE_WEP (0x1 << 8)
+-#define RX_RES_STATUS_SEC_TYPE_CCMP (0x2 << 8)
+-#define RX_RES_STATUS_SEC_TYPE_TKIP (0x3 << 8)
++#define RX_RES_STATUS_DECRYPT_TYPE_MSK (0x3 << 11)
++#define RX_RES_STATUS_NOT_DECRYPT (0x0 << 11)
++#define RX_RES_STATUS_DECRYPT_OK (0x3 << 11)
++#define RX_RES_STATUS_BAD_ICV_MIC (0x1 << 11)
++#define RX_RES_STATUS_BAD_KEY_TTAK (0x2 << 11)
+
+-#define RX_RES_STATUS_DECRYPT_TYPE_MSK (0x3 << 11)
+-#define RX_RES_STATUS_NOT_DECRYPT (0x0 << 11)
+-#define RX_RES_STATUS_DECRYPT_OK (0x3 << 11)
+-#define RX_RES_STATUS_BAD_ICV_MIC (0x1 << 11)
+-#define RX_RES_STATUS_BAD_KEY_TTAK (0x2 << 11)
++#define RX_MPDU_RES_STATUS_ICV_OK (0x20)
++#define RX_MPDU_RES_STATUS_MIC_OK (0x40)
++#define RX_MPDU_RES_STATUS_TTAK_OK (1 << 7)
++#define RX_MPDU_RES_STATUS_DEC_DONE_MSK (0x800)
+
+ struct iwl4965_rx_frame_end {
+ __le32 status;
+@@ -922,7 +965,7 @@ struct iwl4965_rx_non_cfg_phy {
+ } __attribute__ ((packed));
+
+ /*
+- * REPLY_4965_RX = 0xc3 (response only, not a command)
++ * REPLY_RX = 0xc3 (response only, not a command)
+ * Used only for legacy (non 11n) frames.
+ */
+ #define RX_RES_PHY_CNT 14
+@@ -1038,6 +1081,10 @@ struct iwl4965_rx_mpdu_res_start {
+ * MAC header) to DWORD boundary. */
+ #define TX_CMD_FLG_MH_PAD_MSK __constant_cpu_to_le32(1 << 20)
+
++/* accelerate aggregation support
++ * 0 - no CCMP encryption; 1 - CCMP encryption */
++#define TX_CMD_FLG_AGG_CCMP_MSK __constant_cpu_to_le32(1 << 22)
++
+ /* HCCA-AP - disable duration overwriting. */
+ #define TX_CMD_FLG_DUR_MSK __constant_cpu_to_le32(1 << 25)
+
+@@ -1300,6 +1347,25 @@ struct iwl4965_tx_resp {
+ __le32 status; /* TX status (for aggregation status of 1st frame) */
+ } __attribute__ ((packed));
+
++struct agg_tx_status {
++ __le16 status;
++ __le16 sequence;
++} __attribute__ ((packed));
++
++struct iwl4965_tx_resp_agg {
++ u8 frame_count; /* 1 no aggregation, >1 aggregation */
++ u8 reserved1;
++ u8 failure_rts;
++ u8 failure_frame;
++ __le32 rate_n_flags;
++ __le16 wireless_media_time;
++ __le16 reserved3;
++ __le32 pa_power1;
++ __le32 pa_power2;
++ struct agg_tx_status status; /* TX status (for aggregation status */
++ /* of 1st frame) */
++} __attribute__ ((packed));
++
+ /*
+ * REPLY_COMPRESSED_BA = 0xc5 (response only, not a command)
+ *
+@@ -1313,9 +1379,8 @@ struct iwl4965_compressed_ba_resp {
+ /* Index of recipient (BA-sending) station in uCode's station table */
+ u8 sta_id;
+ u8 tid;
+- __le16 ba_seq_ctl;
+- __le32 ba_bitmap0;
+- __le32 ba_bitmap1;
++ __le16 seq_ctl;
++ __le64 bitmap;
+ __le16 scd_flow;
+ __le16 scd_ssn;
+ } __attribute__ ((packed));
+@@ -1348,11 +1413,11 @@ struct iwl4965_txpowertable_cmd {
+
+
+ /**
+- * struct iwl4965_link_qual_general_params
++ * struct iwl_link_qual_general_params
+ *
+ * Used in REPLY_TX_LINK_QUALITY_CMD
+ */
+-struct iwl4965_link_qual_general_params {
++struct iwl_link_qual_general_params {
+ u8 flags;
+
+ /* No entries at or above this (driver chosen) index contain MIMO */
+@@ -1379,11 +1444,11 @@ struct iwl4965_link_qual_general_params {
+ } __attribute__ ((packed));
+
+ /**
+- * struct iwl4965_link_qual_agg_params
++ * struct iwl_link_qual_agg_params
+ *
+ * Used in REPLY_TX_LINK_QUALITY_CMD
+ */
+-struct iwl4965_link_qual_agg_params {
++struct iwl_link_qual_agg_params {
+
+ /* Maximum number of uSec in aggregation.
+ * Driver should set this to 4000 (4 milliseconds). */
+@@ -1593,14 +1658,14 @@ struct iwl4965_link_qual_agg_params {
+ * legacy), and then repeat the search process.
+ *
+ */
+-struct iwl4965_link_quality_cmd {
++struct iwl_link_quality_cmd {
+
+ /* Index of destination/recipient station in uCode's station table */
+ u8 sta_id;
+ u8 reserved1;
+ __le16 control; /* not used */
+- struct iwl4965_link_qual_general_params general_params;
+- struct iwl4965_link_qual_agg_params agg_params;
++ struct iwl_link_qual_general_params general_params;
++ struct iwl_link_qual_agg_params agg_params;
+
+ /*
+ * Rate info; when using rate-scaling, Tx command's initial_rate_index
+@@ -2625,7 +2690,7 @@ struct iwl4965_led_cmd {
+
+ struct iwl4965_rx_packet {
+ __le32 len;
+- struct iwl4965_cmd_header hdr;
++ struct iwl_cmd_header hdr;
+ union {
+ struct iwl4965_alive_resp alive_frame;
+ struct iwl4965_rx_frame rx_frame;
+diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-debug.h b/drivers/net/wireless/iwlwifi/iwl-4965-debug.h
+deleted file mode 100644
+index 36696bb..0000000
+--- a/drivers/net/wireless/iwlwifi/iwl-4965-debug.h
++++ /dev/null
+@@ -1,152 +0,0 @@
+-/******************************************************************************
+- *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
+- *
+- * Portions of this file are derived from the ipw3945 project.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of version 2 of the GNU General Public License as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License along with
+- * this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+- *
+- * The full GNU General Public License is included in this distribution in the
+- * file called LICENSE.
+- *
+- * Contact Information:
+- * James P. Ketrenos <ipw2100-admin at linux.intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+- *****************************************************************************/
+-
+-#ifndef __iwl4965_debug_h__
+-#define __iwl4965_debug_h__
+-
+-#ifdef CONFIG_IWL4965_DEBUG
+-extern u32 iwl4965_debug_level;
+-#define IWL_DEBUG(level, fmt, args...) \
+-do { if (iwl4965_debug_level & (level)) \
+- printk(KERN_ERR DRV_NAME": %c %s " fmt, \
+- in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
+-
+-#define IWL_DEBUG_LIMIT(level, fmt, args...) \
+-do { if ((iwl4965_debug_level & (level)) && net_ratelimit()) \
+- printk(KERN_ERR DRV_NAME": %c %s " fmt, \
+- in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
+-#else
+-static inline void IWL_DEBUG(int level, const char *fmt, ...)
+-{
+-}
+-static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...)
+-{
+-}
+-#endif /* CONFIG_IWL4965_DEBUG */
+-
+-/*
+- * To use the debug system;
+- *
+- * If you are defining a new debug classification, simply add it to the #define
+- * list here in the form of:
+- *
+- * #define IWL_DL_xxxx VALUE
+- *
+- * shifting value to the left one bit from the previous entry. xxxx should be
+- * the name of the classification (for example, WEP)
+- *
+- * You then need to either add a IWL_xxxx_DEBUG() macro definition for your
+- * classification, or use IWL_DEBUG(IWL_DL_xxxx, ...) whenever you want
+- * to send output to that classification.
+- *
+- * To add your debug level to the list of levels seen when you perform
+- *
+- * % cat /proc/net/iwl/debug_level
+- *
+- * you simply need to add your entry to the iwl4965_debug_levels array.
+- *
+- * If you do not see debug_level in /proc/net/iwl then you do not have
+- * CONFIG_IWL4965_DEBUG defined in your kernel configuration
+- *
+- */
+-
+-#define IWL_DL_INFO (1 << 0)
+-#define IWL_DL_MAC80211 (1 << 1)
+-#define IWL_DL_HOST_COMMAND (1 << 2)
+-#define IWL_DL_STATE (1 << 3)
+-
+-#define IWL_DL_RADIO (1 << 7)
+-#define IWL_DL_POWER (1 << 8)
+-#define IWL_DL_TEMP (1 << 9)
+-
+-#define IWL_DL_NOTIF (1 << 10)
+-#define IWL_DL_SCAN (1 << 11)
+-#define IWL_DL_ASSOC (1 << 12)
+-#define IWL_DL_DROP (1 << 13)
+-
+-#define IWL_DL_TXPOWER (1 << 14)
+-
+-#define IWL_DL_AP (1 << 15)
+-
+-#define IWL_DL_FW (1 << 16)
+-#define IWL_DL_RF_KILL (1 << 17)
+-#define IWL_DL_FW_ERRORS (1 << 18)
+-
+-#define IWL_DL_LED (1 << 19)
+-
+-#define IWL_DL_RATE (1 << 20)
+-
+-#define IWL_DL_CALIB (1 << 21)
+-#define IWL_DL_WEP (1 << 22)
+-#define IWL_DL_TX (1 << 23)
+-#define IWL_DL_RX (1 << 24)
+-#define IWL_DL_ISR (1 << 25)
+-#define IWL_DL_HT (1 << 26)
+-#define IWL_DL_IO (1 << 27)
+-#define IWL_DL_11H (1 << 28)
+-
+-#define IWL_DL_STATS (1 << 29)
+-#define IWL_DL_TX_REPLY (1 << 30)
+-#define IWL_DL_QOS (1 << 31)
+-
+-#define IWL_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a)
+-#define IWL_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a)
+-#define IWL_DEBUG_INFO(f, a...) IWL_DEBUG(IWL_DL_INFO, f, ## a)
+-
+-#define IWL_DEBUG_MAC80211(f, a...) IWL_DEBUG(IWL_DL_MAC80211, f, ## a)
+-#define IWL_DEBUG_TEMP(f, a...) IWL_DEBUG(IWL_DL_TEMP, f, ## a)
+-#define IWL_DEBUG_SCAN(f, a...) IWL_DEBUG(IWL_DL_SCAN, f, ## a)
+-#define IWL_DEBUG_RX(f, a...) IWL_DEBUG(IWL_DL_RX, f, ## a)
+-#define IWL_DEBUG_TX(f, a...) IWL_DEBUG(IWL_DL_TX, f, ## a)
+-#define IWL_DEBUG_ISR(f, a...) IWL_DEBUG(IWL_DL_ISR, f, ## a)
+-#define IWL_DEBUG_LED(f, a...) IWL_DEBUG(IWL_DL_LED, f, ## a)
+-#define IWL_DEBUG_WEP(f, a...) IWL_DEBUG(IWL_DL_WEP, f, ## a)
+-#define IWL_DEBUG_HC(f, a...) IWL_DEBUG(IWL_DL_HOST_COMMAND, f, ## a)
+-#define IWL_DEBUG_CALIB(f, a...) IWL_DEBUG(IWL_DL_CALIB, f, ## a)
+-#define IWL_DEBUG_FW(f, a...) IWL_DEBUG(IWL_DL_FW, f, ## a)
+-#define IWL_DEBUG_RF_KILL(f, a...) IWL_DEBUG(IWL_DL_RF_KILL, f, ## a)
+-#define IWL_DEBUG_DROP(f, a...) IWL_DEBUG(IWL_DL_DROP, f, ## a)
+-#define IWL_DEBUG_DROP_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_DROP, f, ## a)
+-#define IWL_DEBUG_AP(f, a...) IWL_DEBUG(IWL_DL_AP, f, ## a)
+-#define IWL_DEBUG_TXPOWER(f, a...) IWL_DEBUG(IWL_DL_TXPOWER, f, ## a)
+-#define IWL_DEBUG_IO(f, a...) IWL_DEBUG(IWL_DL_IO, f, ## a)
+-#define IWL_DEBUG_RATE(f, a...) IWL_DEBUG(IWL_DL_RATE, f, ## a)
+-#define IWL_DEBUG_RATE_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_RATE, f, ## a)
+-#define IWL_DEBUG_NOTIF(f, a...) IWL_DEBUG(IWL_DL_NOTIF, f, ## a)
+-#define IWL_DEBUG_ASSOC(f, a...) IWL_DEBUG(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
+-#define IWL_DEBUG_ASSOC_LIMIT(f, a...) \
+- IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
+-#define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a)
+-#define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a)
+-#define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a)
+-#define IWL_DEBUG_QOS(f, a...) IWL_DEBUG(IWL_DL_QOS, f, ## a)
+-#define IWL_DEBUG_RADIO(f, a...) IWL_DEBUG(IWL_DL_RADIO, f, ## a)
+-#define IWL_DEBUG_POWER(f, a...) IWL_DEBUG(IWL_DL_POWER, f, ## a)
+-#define IWL_DEBUG_11H(f, a...) IWL_DEBUG(IWL_DL_11H, f, ## a)
+-
+-#endif
+diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
+index ffe1e9d..1a66b50 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
++++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
+@@ -5,7 +5,7 @@
+ *
+ * GPL LICENSE SUMMARY
+ *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+@@ -30,7 +30,7 @@
+ *
+ * BSD LICENSE
+ *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -92,316 +92,6 @@
+ /* RSSI to dBm */
+ #define IWL_RSSI_OFFSET 44
+
+-/*
+- * EEPROM related constants, enums, and structures.
+- */
+-
+-/*
+- * EEPROM access time values:
+- *
+- * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG,
+- * then clearing (with subsequent read/modify/write) CSR_EEPROM_REG bit
+- * CSR_EEPROM_REG_BIT_CMD (0x2).
+- * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1).
+- * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec.
+- * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG.
+- */
+-#define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */
+-#define IWL_EEPROM_ACCESS_DELAY 10 /* uSec */
+-
+-/*
+- * Regulatory channel usage flags in EEPROM struct iwl4965_eeprom_channel.flags.
+- *
+- * IBSS and/or AP operation is allowed *only* on those channels with
+- * (VALID && IBSS && ACTIVE && !RADAR). This restriction is in place because
+- * RADAR detection is not supported by the 4965 driver, but is a
+- * requirement for establishing a new network for legal operation on channels
+- * requiring RADAR detection or restricting ACTIVE scanning.
+- *
+- * NOTE: "WIDE" flag does not indicate anything about "FAT" 40 MHz channels.
+- * It only indicates that 20 MHz channel use is supported; FAT channel
+- * usage is indicated by a separate set of regulatory flags for each
+- * FAT channel pair.
+- *
+- * NOTE: Using a channel inappropriately will result in a uCode error!
+- */
+-enum {
+- EEPROM_CHANNEL_VALID = (1 << 0), /* usable for this SKU/geo */
+- EEPROM_CHANNEL_IBSS = (1 << 1), /* usable as an IBSS channel */
+- /* Bit 2 Reserved */
+- EEPROM_CHANNEL_ACTIVE = (1 << 3), /* active scanning allowed */
+- EEPROM_CHANNEL_RADAR = (1 << 4), /* radar detection required */
+- EEPROM_CHANNEL_WIDE = (1 << 5), /* 20 MHz channel okay */
+- EEPROM_CHANNEL_NARROW = (1 << 6), /* 10 MHz channel (not used) */
+- EEPROM_CHANNEL_DFS = (1 << 7), /* dynamic freq selection candidate */
+-};
+-
+-/* SKU Capabilities */
+-#define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE (1 << 0)
+-#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE (1 << 1)
+-
+-/* *regulatory* channel data format in eeprom, one for each channel.
+- * There are separate entries for FAT (40 MHz) vs. normal (20 MHz) channels. */
+-struct iwl4965_eeprom_channel {
+- u8 flags; /* EEPROM_CHANNEL_* flags copied from EEPROM */
+- s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */
+-} __attribute__ ((packed));
+-
+-/* 4965 has two radio transmitters (and 3 radio receivers) */
+-#define EEPROM_TX_POWER_TX_CHAINS (2)
+-
+-/* 4965 has room for up to 8 sets of txpower calibration data */
+-#define EEPROM_TX_POWER_BANDS (8)
+-
+-/* 4965 factory calibration measures txpower gain settings for
+- * each of 3 target output levels */
+-#define EEPROM_TX_POWER_MEASUREMENTS (3)
+-
+-/* 4965 driver does not work with txpower calibration version < 5.
+- * Look for this in calib_version member of struct iwl4965_eeprom. */
+-#define EEPROM_TX_POWER_VERSION_NEW (5)
+-
+-
+-/*
+- * 4965 factory calibration data for one txpower level, on one channel,
+- * measured on one of the 2 tx chains (radio transmitter and associated
+- * antenna). EEPROM contains:
+- *
+- * 1) Temperature (degrees Celsius) of device when measurement was made.
+- *
+- * 2) Gain table index used to achieve the target measurement power.
+- * This refers to the "well-known" gain tables (see iwl-4965-hw.h).
+- *
+- * 3) Actual measured output power, in half-dBm ("34" = 17 dBm).
+- *
+- * 4) RF power amplifier detector level measurement (not used).
+- */
+-struct iwl4965_eeprom_calib_measure {
+- u8 temperature; /* Device temperature (Celsius) */
+- u8 gain_idx; /* Index into gain table */
+- u8 actual_pow; /* Measured RF output power, half-dBm */
+- s8 pa_det; /* Power amp detector level (not used) */
+-} __attribute__ ((packed));
+-
+-
+-/*
+- * 4965 measurement set for one channel. EEPROM contains:
+- *
+- * 1) Channel number measured
+- *
+- * 2) Measurements for each of 3 power levels for each of 2 radio transmitters
+- * (a.k.a. "tx chains") (6 measurements altogether)
+- */
+-struct iwl4965_eeprom_calib_ch_info {
+- u8 ch_num;
+- struct iwl4965_eeprom_calib_measure measurements[EEPROM_TX_POWER_TX_CHAINS]
+- [EEPROM_TX_POWER_MEASUREMENTS];
+-} __attribute__ ((packed));
+-
+-/*
+- * 4965 txpower subband info.
+- *
+- * For each frequency subband, EEPROM contains the following:
+- *
+- * 1) First and last channels within range of the subband. "0" values
+- * indicate that this sample set is not being used.
+- *
+- * 2) Sample measurement sets for 2 channels close to the range endpoints.
+- */
+-struct iwl4965_eeprom_calib_subband_info {
+- u8 ch_from; /* channel number of lowest channel in subband */
+- u8 ch_to; /* channel number of highest channel in subband */
+- struct iwl4965_eeprom_calib_ch_info ch1;
+- struct iwl4965_eeprom_calib_ch_info ch2;
+-} __attribute__ ((packed));
+-
+-
+-/*
+- * 4965 txpower calibration info. EEPROM contains:
+- *
+- * 1) Factory-measured saturation power levels (maximum levels at which
+- * tx power amplifier can output a signal without too much distortion).
+- * There is one level for 2.4 GHz band and one for 5 GHz band. These
+- * values apply to all channels within each of the bands.
+- *
+- * 2) Factory-measured power supply voltage level. This is assumed to be
+- * constant (i.e. same value applies to all channels/bands) while the
+- * factory measurements are being made.
+- *
+- * 3) Up to 8 sets of factory-measured txpower calibration values.
+- * These are for different frequency ranges, since txpower gain
+- * characteristics of the analog radio circuitry vary with frequency.
+- *
+- * Not all sets need to be filled with data;
+- * struct iwl4965_eeprom_calib_subband_info contains range of channels
+- * (0 if unused) for each set of data.
+- */
+-struct iwl4965_eeprom_calib_info {
+- u8 saturation_power24; /* half-dBm (e.g. "34" = 17 dBm) */
+- u8 saturation_power52; /* half-dBm */
+- s16 voltage; /* signed */
+- struct iwl4965_eeprom_calib_subband_info band_info[EEPROM_TX_POWER_BANDS];
+-} __attribute__ ((packed));
+-
+-
+-/*
+- * 4965 EEPROM map
+- */
+-struct iwl4965_eeprom {
+- u8 reserved0[16];
+-#define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */
+- u16 device_id; /* abs.ofs: 16 */
+- u8 reserved1[2];
+-#define EEPROM_PMC (2*0x0A) /* 2 bytes */
+- u16 pmc; /* abs.ofs: 20 */
+- u8 reserved2[20];
+-#define EEPROM_MAC_ADDRESS (2*0x15) /* 6 bytes */
+- u8 mac_address[6]; /* abs.ofs: 42 */
+- u8 reserved3[58];
+-#define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */
+- u16 board_revision; /* abs.ofs: 106 */
+- u8 reserved4[11];
+-#define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */
+- u8 board_pba_number[9]; /* abs.ofs: 119 */
+- u8 reserved5[8];
+-#define EEPROM_VERSION (2*0x44) /* 2 bytes */
+- u16 version; /* abs.ofs: 136 */
+-#define EEPROM_SKU_CAP (2*0x45) /* 1 bytes */
+- u8 sku_cap; /* abs.ofs: 138 */
+-#define EEPROM_LEDS_MODE (2*0x45+1) /* 1 bytes */
+- u8 leds_mode; /* abs.ofs: 139 */
+-#define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */
+- u16 oem_mode;
+-#define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */
+- u16 wowlan_mode; /* abs.ofs: 142 */
+-#define EEPROM_LEDS_TIME_INTERVAL (2*0x48) /* 2 bytes */
+- u16 leds_time_interval; /* abs.ofs: 144 */
+-#define EEPROM_LEDS_OFF_TIME (2*0x49) /* 1 bytes */
+- u8 leds_off_time; /* abs.ofs: 146 */
+-#define EEPROM_LEDS_ON_TIME (2*0x49+1) /* 1 bytes */
+- u8 leds_on_time; /* abs.ofs: 147 */
+-#define EEPROM_ALMGOR_M_VERSION (2*0x4A) /* 1 bytes */
+- u8 almgor_m_version; /* abs.ofs: 148 */
+-#define EEPROM_ANTENNA_SWITCH_TYPE (2*0x4A+1) /* 1 bytes */
+- u8 antenna_switch_type; /* abs.ofs: 149 */
+- u8 reserved6[8];
+-#define EEPROM_4965_BOARD_REVISION (2*0x4F) /* 2 bytes */
+- u16 board_revision_4965; /* abs.ofs: 158 */
+- u8 reserved7[13];
+-#define EEPROM_4965_BOARD_PBA (2*0x56+1) /* 9 bytes */
+- u8 board_pba_number_4965[9]; /* abs.ofs: 173 */
+- u8 reserved8[10];
+-#define EEPROM_REGULATORY_SKU_ID (2*0x60) /* 4 bytes */
+- u8 sku_id[4]; /* abs.ofs: 192 */
+-
+-/*
+- * Per-channel regulatory data.
+- *
+- * Each channel that *might* be supported by 3945 or 4965 has a fixed location
+- * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
+- * txpower (MSB).
+- *
+- * Entries immediately below are for 20 MHz channel width. FAT (40 MHz)
+- * channels (only for 4965, not supported by 3945) appear later in the EEPROM.
+- *
+- * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
+- */
+-#define EEPROM_REGULATORY_BAND_1 (2*0x62) /* 2 bytes */
+- u16 band_1_count; /* abs.ofs: 196 */
+-#define EEPROM_REGULATORY_BAND_1_CHANNELS (2*0x63) /* 28 bytes */
+- struct iwl4965_eeprom_channel band_1_channels[14]; /* abs.ofs: 196 */
+-
+-/*
+- * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196,
+- * 5.0 GHz channels 7, 8, 11, 12, 16
+- * (4915-5080MHz) (none of these is ever supported)
+- */
+-#define EEPROM_REGULATORY_BAND_2 (2*0x71) /* 2 bytes */
+- u16 band_2_count; /* abs.ofs: 226 */
+-#define EEPROM_REGULATORY_BAND_2_CHANNELS (2*0x72) /* 26 bytes */
+- struct iwl4965_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */
+-
+-/*
+- * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
+- * (5170-5320MHz)
+- */
+-#define EEPROM_REGULATORY_BAND_3 (2*0x7F) /* 2 bytes */
+- u16 band_3_count; /* abs.ofs: 254 */
+-#define EEPROM_REGULATORY_BAND_3_CHANNELS (2*0x80) /* 24 bytes */
+- struct iwl4965_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */
+-
+-/*
+- * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
+- * (5500-5700MHz)
+- */
+-#define EEPROM_REGULATORY_BAND_4 (2*0x8C) /* 2 bytes */
+- u16 band_4_count; /* abs.ofs: 280 */
+-#define EEPROM_REGULATORY_BAND_4_CHANNELS (2*0x8D) /* 22 bytes */
+- struct iwl4965_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */
+-
+-/*
+- * 5.7 GHz channels 145, 149, 153, 157, 161, 165
+- * (5725-5825MHz)
+- */
+-#define EEPROM_REGULATORY_BAND_5 (2*0x98) /* 2 bytes */
+- u16 band_5_count; /* abs.ofs: 304 */
+-#define EEPROM_REGULATORY_BAND_5_CHANNELS (2*0x99) /* 12 bytes */
+- struct iwl4965_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */
+-
+- u8 reserved10[2];
+-
+-
+-/*
+- * 2.4 GHz FAT channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11)
+- *
+- * The channel listed is the center of the lower 20 MHz half of the channel.
+- * The overall center frequency is actually 2 channels (10 MHz) above that,
+- * and the upper half of each FAT channel is centered 4 channels (20 MHz) away
+- * from the lower half; e.g. the upper half of FAT channel 1 is channel 5,
+- * and the overall FAT channel width centers on channel 3.
+- *
+- * NOTE: The RXON command uses 20 MHz channel numbers to specify the
+- * control channel to which to tune. RXON also specifies whether the
+- * control channel is the upper or lower half of a FAT channel.
+- *
+- * NOTE: 4965 does not support FAT channels on 2.4 GHz.
+- */
+-#define EEPROM_REGULATORY_BAND_24_FAT_CHANNELS (2*0xA0) /* 14 bytes */
+- struct iwl4965_eeprom_channel band_24_channels[7]; /* abs.ofs: 320 */
+- u8 reserved11[2];
+-
+-/*
+- * 5.2 GHz FAT channels 36 (40), 44 (48), 52 (56), 60 (64),
+- * 100 (104), 108 (112), 116 (120), 124 (128), 132 (136), 149 (153), 157 (161)
+- */
+-#define EEPROM_REGULATORY_BAND_52_FAT_CHANNELS (2*0xA8) /* 22 bytes */
+- struct iwl4965_eeprom_channel band_52_channels[11]; /* abs.ofs: 336 */
+- u8 reserved12[6];
+-
+-/*
+- * 4965 driver requires txpower calibration format version 5 or greater.
+- * Driver does not work with txpower calibration version < 5.
+- * This value is simply a 16-bit number, no major/minor versions here.
+- */
+-#define EEPROM_CALIB_VERSION_OFFSET (2*0xB6) /* 2 bytes */
+- u16 calib_version; /* abs.ofs: 364 */
+- u8 reserved13[2];
+- u8 reserved14[96]; /* abs.ofs: 368 */
+-
+-/*
+- * 4965 Txpower calibration data.
+- */
+-#define EEPROM_IWL_CALIB_TXPOWER_OFFSET (2*0xE8) /* 48 bytes */
+- struct iwl4965_eeprom_calib_info calib_info; /* abs.ofs: 464 */
+-
+- u8 reserved16[140]; /* fill out to full 1024 byte block */
+-
+-
+-} __attribute__ ((packed));
+-
+-#define IWL_EEPROM_IMAGE_SIZE 1024
+-
+-/* End of EEPROM */
+
+ #include "iwl-4965-commands.h"
+
+@@ -410,182 +100,6 @@ struct iwl4965_eeprom {
+ #define PCI_REG_WUM8 0x0E8
+ #define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT (0x80000000)
+
+-/*=== CSR (control and status registers) ===*/
+-#define CSR_BASE (0x000)
+-
+-#define CSR_SW_VER (CSR_BASE+0x000)
+-#define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */
+-#define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */
+-#define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */
+-#define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */
+-#define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/
+-#define CSR_GPIO_IN (CSR_BASE+0x018) /* read external chip pins */
+-#define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/
+-#define CSR_GP_CNTRL (CSR_BASE+0x024)
+-
+-/*
+- * Hardware revision info
+- * Bit fields:
+- * 31-8: Reserved
+- * 7-4: Type of device: 0x0 = 4965, 0xd = 3945
+- * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D
+- * 1-0: "Dash" value, as in A-1, etc.
+- *
+- * NOTE: Revision step affects calculation of CCK txpower for 4965.
+- */
+-#define CSR_HW_REV (CSR_BASE+0x028)
+-
+-/* EEPROM reads */
+-#define CSR_EEPROM_REG (CSR_BASE+0x02c)
+-#define CSR_EEPROM_GP (CSR_BASE+0x030)
+-#define CSR_GP_UCODE (CSR_BASE+0x044)
+-#define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054)
+-#define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058)
+-#define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c)
+-#define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060)
+-#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)
+-
+-/*
+- * Indicates hardware rev, to determine CCK backoff for txpower calculation.
+- * Bit fields:
+- * 3-2: 0 = A, 1 = B, 2 = C, 3 = D step
+- */
+-#define CSR_HW_REV_WA_REG (CSR_BASE+0x22C)
+-
+-/* Hardware interface configuration bits */
+-#define CSR_HW_IF_CONFIG_REG_BIT_KEDRON_R (0x00000010)
+-#define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x00000C00)
+-#define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100)
+-#define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200)
+-#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000)
+-
+-/* interrupt flags in INTA, set by uCode or hardware (e.g. dma),
+- * acknowledged (reset) by host writing "1" to flagged bits. */
+-#define CSR_INT_BIT_FH_RX (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */
+-#define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */
+-#define CSR_INT_BIT_DNLD (1 << 28) /* uCode Download */
+-#define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */
+-#define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */
+-#define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */
+-#define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */
+-#define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */
+-#define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses, 3945 */
+-#define CSR_INT_BIT_WAKEUP (1 << 1) /* NIC controller waking up (pwr mgmt) */
+-#define CSR_INT_BIT_ALIVE (1 << 0) /* uCode interrupts once it initializes */
+-
+-#define CSR_INI_SET_MASK (CSR_INT_BIT_FH_RX | \
+- CSR_INT_BIT_HW_ERR | \
+- CSR_INT_BIT_FH_TX | \
+- CSR_INT_BIT_SW_ERR | \
+- CSR_INT_BIT_RF_KILL | \
+- CSR_INT_BIT_SW_RX | \
+- CSR_INT_BIT_WAKEUP | \
+- CSR_INT_BIT_ALIVE)
+-
+-/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */
+-#define CSR_FH_INT_BIT_ERR (1 << 31) /* Error */
+-#define CSR_FH_INT_BIT_HI_PRIOR (1 << 30) /* High priority Rx, bypass coalescing */
+-#define CSR_FH_INT_BIT_RX_CHNL1 (1 << 17) /* Rx channel 1 */
+-#define CSR_FH_INT_BIT_RX_CHNL0 (1 << 16) /* Rx channel 0 */
+-#define CSR_FH_INT_BIT_TX_CHNL1 (1 << 1) /* Tx channel 1 */
+-#define CSR_FH_INT_BIT_TX_CHNL0 (1 << 0) /* Tx channel 0 */
+-
+-#define CSR_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \
+- CSR_FH_INT_BIT_RX_CHNL1 | \
+- CSR_FH_INT_BIT_RX_CHNL0)
+-
+-#define CSR_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL1 | \
+- CSR_FH_INT_BIT_TX_CHNL0)
+-
+-
+-/* RESET */
+-#define CSR_RESET_REG_FLAG_NEVO_RESET (0x00000001)
+-#define CSR_RESET_REG_FLAG_FORCE_NMI (0x00000002)
+-#define CSR_RESET_REG_FLAG_SW_RESET (0x00000080)
+-#define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100)
+-#define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200)
+-
+-/* GP (general purpose) CONTROL */
+-#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001)
+-#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004)
+-#define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008)
+-#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010)
+-
+-#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001)
+-
+-#define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE (0x07000000)
+-#define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE (0x04000000)
+-#define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW (0x08000000)
+-
+-
+-/* EEPROM REG */
+-#define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001)
+-#define CSR_EEPROM_REG_BIT_CMD (0x00000002)
+-
+-/* EEPROM GP */
+-#define CSR_EEPROM_GP_VALID_MSK (0x00000006)
+-#define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000)
+-#define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180)
+-
+-/* UCODE DRV GP */
+-#define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP (0x00000001)
+-#define CSR_UCODE_SW_BIT_RFKILL (0x00000002)
+-#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004)
+-#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008)
+-
+-/* GPIO */
+-#define CSR_GPIO_IN_BIT_AUX_POWER (0x00000200)
+-#define CSR_GPIO_IN_VAL_VAUX_PWR_SRC (0x00000000)
+-#define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC CSR_GPIO_IN_BIT_AUX_POWER
+-
+-/* GI Chicken Bits */
+-#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000)
+-#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000)
+-
+-/*=== HBUS (Host-side Bus) ===*/
+-#define HBUS_BASE (0x400)
+-
+-/*
+- * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM
+- * structures, error log, event log, verifying uCode load).
+- * First write to address register, then read from or write to data register
+- * to complete the job. Once the address register is set up, accesses to
+- * data registers auto-increment the address by one dword.
+- * Bit usage for address registers (read or write):
+- * 0-31: memory address within device
+- */
+-#define HBUS_TARG_MEM_RADDR (HBUS_BASE+0x00c)
+-#define HBUS_TARG_MEM_WADDR (HBUS_BASE+0x010)
+-#define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018)
+-#define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c)
+-
+-/*
+- * Registers for accessing device's internal peripheral registers
+- * (e.g. SCD, BSM, etc.). First write to address register,
+- * then read from or write to data register to complete the job.
+- * Bit usage for address registers (read or write):
+- * 0-15: register address (offset) within device
+- * 24-25: (# bytes - 1) to read or write (e.g. 3 for dword)
+- */
+-#define HBUS_TARG_PRPH_WADDR (HBUS_BASE+0x044)
+-#define HBUS_TARG_PRPH_RADDR (HBUS_BASE+0x048)
+-#define HBUS_TARG_PRPH_WDAT (HBUS_BASE+0x04c)
+-#define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050)
+-
+-/*
+- * Per-Tx-queue write pointer (index, really!) (3945 and 4965).
+- * Driver sets this to indicate index to next TFD that driver will fill
+- * (1 past latest filled).
+- * Bit usage:
+- * 0-7: queue write index (0-255)
+- * 11-8: queue selector (0-15)
+- */
+-#define HBUS_TARG_WRPTR (HBUS_BASE+0x060)
+-
+-#define HBUS_TARG_MBX_C (HBUS_BASE+0x030)
+-
+-#define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED (0x00000004)
+-
+ #define TFD_QUEUE_SIZE_MAX (256)
+
+ #define IWL_NUM_SCAN_RATES (2)
+@@ -599,9 +113,6 @@ struct iwl4965_eeprom {
+ #define TFD_TX_CMD_SLOTS 256
+ #define TFD_CMD_SLOTS 32
+
+-#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl4965_cmd) - \
+- sizeof(struct iwl4965_cmd_meta))
+-
+ /*
+ * RX related structures and functions
+ */
+@@ -615,16 +126,18 @@ struct iwl4965_eeprom {
+ /* Sizes and addresses for instruction and data memory (SRAM) in
+ * 4965's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */
+ #define RTC_INST_LOWER_BOUND (0x000000)
+-#define KDR_RTC_INST_UPPER_BOUND (0x018000)
++#define IWL49_RTC_INST_UPPER_BOUND (0x018000)
+
+ #define RTC_DATA_LOWER_BOUND (0x800000)
+-#define KDR_RTC_DATA_UPPER_BOUND (0x80A000)
++#define IWL49_RTC_DATA_UPPER_BOUND (0x80A000)
+
+-#define KDR_RTC_INST_SIZE (KDR_RTC_INST_UPPER_BOUND - RTC_INST_LOWER_BOUND)
+-#define KDR_RTC_DATA_SIZE (KDR_RTC_DATA_UPPER_BOUND - RTC_DATA_LOWER_BOUND)
++#define IWL49_RTC_INST_SIZE \
++ (IWL49_RTC_INST_UPPER_BOUND - RTC_INST_LOWER_BOUND)
++#define IWL49_RTC_DATA_SIZE \
++ (IWL49_RTC_DATA_UPPER_BOUND - RTC_DATA_LOWER_BOUND)
+
+-#define IWL_MAX_INST_SIZE KDR_RTC_INST_SIZE
+-#define IWL_MAX_DATA_SIZE KDR_RTC_DATA_SIZE
++#define IWL_MAX_INST_SIZE IWL49_RTC_INST_SIZE
++#define IWL_MAX_DATA_SIZE IWL49_RTC_DATA_SIZE
+
+ /* Size of uCode instruction memory in bootstrap state machine */
+ #define IWL_MAX_BSM_SIZE BSM_SRAM_SIZE
+@@ -632,7 +145,7 @@ struct iwl4965_eeprom {
+ static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr)
+ {
+ return (addr >= RTC_DATA_LOWER_BOUND) &&
+- (addr < KDR_RTC_DATA_UPPER_BOUND);
++ (addr < IWL49_RTC_DATA_UPPER_BOUND);
+ }
+
+ /********************* START TEMPERATURE *************************************/
+@@ -1872,10 +1385,10 @@ static inline __le32 iwl4965_hw_set_rate_n_flags(u8 rate, u16 flags)
+ * up to 7 DMA channels (FIFOs). Each Tx queue is supported by a circular array
+ * in DRAM containing 256 Transmit Frame Descriptors (TFDs).
+ */
+-#define IWL4965_MAX_WIN_SIZE 64
+-#define IWL4965_QUEUE_SIZE 256
+-#define IWL4965_NUM_FIFOS 7
+-#define IWL_MAX_NUM_QUEUES 16
++#define IWL4965_MAX_WIN_SIZE 64
++#define IWL4965_QUEUE_SIZE 256
++#define IWL4965_NUM_FIFOS 7
++#define IWL4965_MAX_NUM_QUEUES 16
+
+
+ /**
+@@ -2040,30 +1553,30 @@ struct iwl4965_sched_queue_byte_cnt_tbl {
+ */
+ struct iwl4965_shared {
+ struct iwl4965_sched_queue_byte_cnt_tbl
+- queues_byte_cnt_tbls[IWL_MAX_NUM_QUEUES];
+- __le32 val0;
++ queues_byte_cnt_tbls[IWL4965_MAX_NUM_QUEUES];
++ __le32 rb_closed;
+
+ /* __le32 rb_closed_stts_rb_num:12; */
+ #define IWL_rb_closed_stts_rb_num_POS 0
+ #define IWL_rb_closed_stts_rb_num_LEN 12
+-#define IWL_rb_closed_stts_rb_num_SYM val0
++#define IWL_rb_closed_stts_rb_num_SYM rb_closed
+ /* __le32 rsrv1:4; */
+ /* __le32 rb_closed_stts_rx_frame_num:12; */
+ #define IWL_rb_closed_stts_rx_frame_num_POS 16
+ #define IWL_rb_closed_stts_rx_frame_num_LEN 12
+-#define IWL_rb_closed_stts_rx_frame_num_SYM val0
++#define IWL_rb_closed_stts_rx_frame_num_SYM rb_closed
+ /* __le32 rsrv2:4; */
+
+- __le32 val1;
++ __le32 frm_finished;
+ /* __le32 frame_finished_stts_rb_num:12; */
+ #define IWL_frame_finished_stts_rb_num_POS 0
+ #define IWL_frame_finished_stts_rb_num_LEN 12
+-#define IWL_frame_finished_stts_rb_num_SYM val1
++#define IWL_frame_finished_stts_rb_num_SYM frm_finished
+ /* __le32 rsrv3:4; */
+ /* __le32 frame_finished_stts_rx_frame_num:12; */
+ #define IWL_frame_finished_stts_rx_frame_num_POS 16
+ #define IWL_frame_finished_stts_rx_frame_num_LEN 12
+-#define IWL_frame_finished_stts_rx_frame_num_SYM val1
++#define IWL_frame_finished_stts_rx_frame_num_SYM frm_finished
+ /* __le32 rsrv4:4; */
+
+ __le32 padding1; /* so that allocation will be aligned to 16B */
+diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-io.h b/drivers/net/wireless/iwlwifi/iwl-4965-io.h
+deleted file mode 100644
+index 34a0b57..0000000
+--- a/drivers/net/wireless/iwlwifi/iwl-4965-io.h
++++ /dev/null
+@@ -1,431 +0,0 @@
+-/******************************************************************************
+- *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
+- *
+- * Portions of this file are derived from the ipw3945 project.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of version 2 of the GNU General Public License as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License along with
+- * this program; if not, write to the Free Software Foundation, Inc.,
+- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+- *
+- * The full GNU General Public License is included in this distribution in the
+- * file called LICENSE.
+- *
+- * Contact Information:
+- * James P. Ketrenos <ipw2100-admin at linux.intel.com>
+- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+- *
+- *****************************************************************************/
+-
+-#ifndef __iwl4965_io_h__
+-#define __iwl4965_io_h__
+-
+-#include <linux/io.h>
+-
+-#include "iwl-4965-debug.h"
+-
+-/*
+- * IO, register, and NIC memory access functions
+- *
+- * NOTE on naming convention and macro usage for these
+- *
+- * A single _ prefix before a an access function means that no state
+- * check or debug information is printed when that function is called.
+- *
+- * A double __ prefix before an access function means that state is checked
+- * and the current line number is printed in addition to any other debug output.
+- *
+- * The non-prefixed name is the #define that maps the caller into a
+- * #define that provides the caller's __LINE__ to the double prefix version.
+- *
+- * If you wish to call the function without any debug or state checking,
+- * you should use the single _ prefix version (as is used by dependent IO
+- * routines, for example _iwl4965_read_direct32 calls the non-check version of
+- * _iwl4965_read32.)
+- *
+- * These declarations are *extremely* useful in quickly isolating code deltas
+- * which result in misconfiguring of the hardware I/O. In combination with
+- * git-bisect and the IO debug level you can quickly determine the specific
+- * commit which breaks the IO sequence to the hardware.
+- *
+- */
+-
+-#define _iwl4965_write32(iwl, ofs, val) writel((val), (iwl)->hw_base + (ofs))
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline void __iwl4965_write32(const char *f, u32 l, struct iwl4965_priv *iwl,
+- u32 ofs, u32 val)
+-{
+- IWL_DEBUG_IO("write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l);
+- _iwl4965_write32(iwl, ofs, val);
+-}
+-#define iwl4965_write32(iwl, ofs, val) \
+- __iwl4965_write32(__FILE__, __LINE__, iwl, ofs, val)
+-#else
+-#define iwl4965_write32(iwl, ofs, val) _iwl4965_write32(iwl, ofs, val)
+-#endif
+-
+-#define _iwl4965_read32(iwl, ofs) readl((iwl)->hw_base + (ofs))
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline u32 __iwl4965_read32(char *f, u32 l, struct iwl4965_priv *iwl, u32 ofs)
+-{
+- IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l);
+- return _iwl4965_read32(iwl, ofs);
+-}
+-#define iwl4965_read32(iwl, ofs) __iwl4965_read32(__FILE__, __LINE__, iwl, ofs)
+-#else
+-#define iwl4965_read32(p, o) _iwl4965_read32(p, o)
+-#endif
+-
+-static inline int _iwl4965_poll_bit(struct iwl4965_priv *priv, u32 addr,
+- u32 bits, u32 mask, int timeout)
+-{
+- int i = 0;
+-
+- do {
+- if ((_iwl4965_read32(priv, addr) & mask) == (bits & mask))
+- return i;
+- mdelay(10);
+- i += 10;
+- } while (i < timeout);
+-
+- return -ETIMEDOUT;
+-}
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline int __iwl4965_poll_bit(const char *f, u32 l,
+- struct iwl4965_priv *priv, u32 addr,
+- u32 bits, u32 mask, int timeout)
+-{
+- int ret = _iwl4965_poll_bit(priv, addr, bits, mask, timeout);
+- if (unlikely(ret == -ETIMEDOUT))
+- IWL_DEBUG_IO
+- ("poll_bit(0x%08X, 0x%08X, 0x%08X) - timedout - %s %d\n",
+- addr, bits, mask, f, l);
+- else
+- IWL_DEBUG_IO
+- ("poll_bit(0x%08X, 0x%08X, 0x%08X) = 0x%08X - %s %d\n",
+- addr, bits, mask, ret, f, l);
+- return ret;
+-}
+-#define iwl4965_poll_bit(iwl, addr, bits, mask, timeout) \
+- __iwl4965_poll_bit(__FILE__, __LINE__, iwl, addr, bits, mask, timeout)
+-#else
+-#define iwl4965_poll_bit(p, a, b, m, t) _iwl4965_poll_bit(p, a, b, m, t)
+-#endif
+-
+-static inline void _iwl4965_set_bit(struct iwl4965_priv *priv, u32 reg, u32 mask)
+-{
+- _iwl4965_write32(priv, reg, _iwl4965_read32(priv, reg) | mask);
+-}
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline void __iwl4965_set_bit(const char *f, u32 l,
+- struct iwl4965_priv *priv, u32 reg, u32 mask)
+-{
+- u32 val = _iwl4965_read32(priv, reg) | mask;
+- IWL_DEBUG_IO("set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
+- _iwl4965_write32(priv, reg, val);
+-}
+-#define iwl4965_set_bit(p, r, m) __iwl4965_set_bit(__FILE__, __LINE__, p, r, m)
+-#else
+-#define iwl4965_set_bit(p, r, m) _iwl4965_set_bit(p, r, m)
+-#endif
+-
+-static inline void _iwl4965_clear_bit(struct iwl4965_priv *priv, u32 reg, u32 mask)
+-{
+- _iwl4965_write32(priv, reg, _iwl4965_read32(priv, reg) & ~mask);
+-}
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline void __iwl4965_clear_bit(const char *f, u32 l,
+- struct iwl4965_priv *priv, u32 reg, u32 mask)
+-{
+- u32 val = _iwl4965_read32(priv, reg) & ~mask;
+- IWL_DEBUG_IO("clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
+- _iwl4965_write32(priv, reg, val);
+-}
+-#define iwl4965_clear_bit(p, r, m) __iwl4965_clear_bit(__FILE__, __LINE__, p, r, m)
+-#else
+-#define iwl4965_clear_bit(p, r, m) _iwl4965_clear_bit(p, r, m)
+-#endif
+-
+-static inline int _iwl4965_grab_nic_access(struct iwl4965_priv *priv)
+-{
+- int ret;
+- u32 gp_ctl;
+-
+-#ifdef CONFIG_IWL4965_DEBUG
+- if (atomic_read(&priv->restrict_refcnt))
+- return 0;
+-#endif
+- if (test_bit(STATUS_RF_KILL_HW, &priv->status) ||
+- test_bit(STATUS_RF_KILL_SW, &priv->status)) {
+- IWL_WARNING("WARNING: Requesting MAC access during RFKILL "
+- "wakes up NIC\n");
+-
+- /* 10 msec allows time for NIC to complete its data save */
+- gp_ctl = _iwl4965_read32(priv, CSR_GP_CNTRL);
+- if (gp_ctl & CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY) {
+- IWL_DEBUG_RF_KILL("Wait for complete power-down, "
+- "gpctl = 0x%08x\n", gp_ctl);
+- mdelay(10);
+- } else
+- IWL_DEBUG_RF_KILL("power-down complete, "
+- "gpctl = 0x%08x\n", gp_ctl);
+- }
+-
+- /* this bit wakes up the NIC */
+- _iwl4965_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+- ret = _iwl4965_poll_bit(priv, CSR_GP_CNTRL,
+- CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
+- (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
+- CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 50);
+- if (ret < 0) {
+- IWL_ERROR("MAC is in deep sleep!\n");
+- return -EIO;
+- }
+-
+-#ifdef CONFIG_IWL4965_DEBUG
+- atomic_inc(&priv->restrict_refcnt);
+-#endif
+- return 0;
+-}
+-
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline int __iwl4965_grab_nic_access(const char *f, u32 l,
+- struct iwl4965_priv *priv)
+-{
+- if (atomic_read(&priv->restrict_refcnt))
+- IWL_DEBUG_INFO("Grabbing access while already held at "
+- "line %d.\n", l);
+-
+- IWL_DEBUG_IO("grabbing nic access - %s %d\n", f, l);
+- return _iwl4965_grab_nic_access(priv);
+-}
+-#define iwl4965_grab_nic_access(priv) \
+- __iwl4965_grab_nic_access(__FILE__, __LINE__, priv)
+-#else
+-#define iwl4965_grab_nic_access(priv) \
+- _iwl4965_grab_nic_access(priv)
+-#endif
+-
+-static inline void _iwl4965_release_nic_access(struct iwl4965_priv *priv)
+-{
+-#ifdef CONFIG_IWL4965_DEBUG
+- if (atomic_dec_and_test(&priv->restrict_refcnt))
+-#endif
+- _iwl4965_clear_bit(priv, CSR_GP_CNTRL,
+- CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+-}
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline void __iwl4965_release_nic_access(const char *f, u32 l,
+- struct iwl4965_priv *priv)
+-{
+- if (atomic_read(&priv->restrict_refcnt) <= 0)
+- IWL_ERROR("Release unheld nic access at line %d.\n", l);
+-
+- IWL_DEBUG_IO("releasing nic access - %s %d\n", f, l);
+- _iwl4965_release_nic_access(priv);
+-}
+-#define iwl4965_release_nic_access(priv) \
+- __iwl4965_release_nic_access(__FILE__, __LINE__, priv)
+-#else
+-#define iwl4965_release_nic_access(priv) \
+- _iwl4965_release_nic_access(priv)
+-#endif
+-
+-static inline u32 _iwl4965_read_direct32(struct iwl4965_priv *priv, u32 reg)
+-{
+- return _iwl4965_read32(priv, reg);
+-}
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline u32 __iwl4965_read_direct32(const char *f, u32 l,
+- struct iwl4965_priv *priv, u32 reg)
+-{
+- u32 value = _iwl4965_read_direct32(priv, reg);
+- if (!atomic_read(&priv->restrict_refcnt))
+- IWL_ERROR("Nic access not held from %s %d\n", f, l);
+- IWL_DEBUG_IO("read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value,
+- f, l);
+- return value;
+-}
+-#define iwl4965_read_direct32(priv, reg) \
+- __iwl4965_read_direct32(__FILE__, __LINE__, priv, reg)
+-#else
+-#define iwl4965_read_direct32 _iwl4965_read_direct32
+-#endif
+-
+-static inline void _iwl4965_write_direct32(struct iwl4965_priv *priv,
+- u32 reg, u32 value)
+-{
+- _iwl4965_write32(priv, reg, value);
+-}
+-#ifdef CONFIG_IWL4965_DEBUG
+-static void __iwl4965_write_direct32(u32 line,
+- struct iwl4965_priv *priv, u32 reg, u32 value)
+-{
+- if (!atomic_read(&priv->restrict_refcnt))
+- IWL_ERROR("Nic access not held from line %d\n", line);
+- _iwl4965_write_direct32(priv, reg, value);
+-}
+-#define iwl4965_write_direct32(priv, reg, value) \
+- __iwl4965_write_direct32(__LINE__, priv, reg, value)
+-#else
+-#define iwl4965_write_direct32 _iwl4965_write_direct32
+-#endif
+-
+-static inline void iwl4965_write_reg_buf(struct iwl4965_priv *priv,
+- u32 reg, u32 len, u32 *values)
+-{
+- u32 count = sizeof(u32);
+-
+- if ((priv != NULL) && (values != NULL)) {
+- for (; 0 < len; len -= count, reg += count, values++)
+- _iwl4965_write_direct32(priv, reg, *values);
+- }
+-}
+-
+-static inline int _iwl4965_poll_direct_bit(struct iwl4965_priv *priv,
+- u32 addr, u32 mask, int timeout)
+-{
+- int i = 0;
+-
+- do {
+- if ((_iwl4965_read_direct32(priv, addr) & mask) == mask)
+- return i;
+- mdelay(10);
+- i += 10;
+- } while (i < timeout);
+-
+- return -ETIMEDOUT;
+-}
+-
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline int __iwl4965_poll_direct_bit(const char *f, u32 l,
+- struct iwl4965_priv *priv,
+- u32 addr, u32 mask, int timeout)
+-{
+- int ret = _iwl4965_poll_direct_bit(priv, addr, mask, timeout);
+-
+- if (unlikely(ret == -ETIMEDOUT))
+- IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) - "
+- "timedout - %s %d\n", addr, mask, f, l);
+- else
+- IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) = 0x%08X "
+- "- %s %d\n", addr, mask, ret, f, l);
+- return ret;
+-}
+-#define iwl4965_poll_direct_bit(iwl, addr, mask, timeout) \
+- __iwl4965_poll_direct_bit(__FILE__, __LINE__, iwl, addr, mask, timeout)
+-#else
+-#define iwl4965_poll_direct_bit _iwl4965_poll_direct_bit
+-#endif
+-
+-static inline u32 _iwl4965_read_prph(struct iwl4965_priv *priv, u32 reg)
+-{
+- _iwl4965_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
+- return _iwl4965_read_direct32(priv, HBUS_TARG_PRPH_RDAT);
+-}
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline u32 __iwl4965_read_prph(u32 line, struct iwl4965_priv *priv, u32 reg)
+-{
+- if (!atomic_read(&priv->restrict_refcnt))
+- IWL_ERROR("Nic access not held from line %d\n", line);
+- return _iwl4965_read_prph(priv, reg);
+-}
+-
+-#define iwl4965_read_prph(priv, reg) \
+- __iwl4965_read_prph(__LINE__, priv, reg)
+-#else
+-#define iwl4965_read_prph _iwl4965_read_prph
+-#endif
+-
+-static inline void _iwl4965_write_prph(struct iwl4965_priv *priv,
+- u32 addr, u32 val)
+-{
+- _iwl4965_write_direct32(priv, HBUS_TARG_PRPH_WADDR,
+- ((addr & 0x0000FFFF) | (3 << 24)));
+- _iwl4965_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val);
+-}
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline void __iwl4965_write_prph(u32 line, struct iwl4965_priv *priv,
+- u32 addr, u32 val)
+-{
+- if (!atomic_read(&priv->restrict_refcnt))
+- IWL_ERROR("Nic access from line %d\n", line);
+- _iwl4965_write_prph(priv, addr, val);
+-}
+-
+-#define iwl4965_write_prph(priv, addr, val) \
+- __iwl4965_write_prph(__LINE__, priv, addr, val);
+-#else
+-#define iwl4965_write_prph _iwl4965_write_prph
+-#endif
+-
+-#define _iwl4965_set_bits_prph(priv, reg, mask) \
+- _iwl4965_write_prph(priv, reg, (_iwl4965_read_prph(priv, reg) | mask))
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline void __iwl4965_set_bits_prph(u32 line, struct iwl4965_priv *priv,
+- u32 reg, u32 mask)
+-{
+- if (!atomic_read(&priv->restrict_refcnt))
+- IWL_ERROR("Nic access not held from line %d\n", line);
+-
+- _iwl4965_set_bits_prph(priv, reg, mask);
+-}
+-#define iwl4965_set_bits_prph(priv, reg, mask) \
+- __iwl4965_set_bits_prph(__LINE__, priv, reg, mask)
+-#else
+-#define iwl4965_set_bits_prph _iwl4965_set_bits_prph
+-#endif
+-
+-#define _iwl4965_set_bits_mask_prph(priv, reg, bits, mask) \
+- _iwl4965_write_prph(priv, reg, ((_iwl4965_read_prph(priv, reg) & mask) | bits))
+-
+-#ifdef CONFIG_IWL4965_DEBUG
+-static inline void __iwl4965_set_bits_mask_prph(u32 line,
+- struct iwl4965_priv *priv, u32 reg, u32 bits, u32 mask)
+-{
+- if (!atomic_read(&priv->restrict_refcnt))
+- IWL_ERROR("Nic access not held from line %d\n", line);
+- _iwl4965_set_bits_mask_prph(priv, reg, bits, mask);
+-}
+-#define iwl4965_set_bits_mask_prph(priv, reg, bits, mask) \
+- __iwl4965_set_bits_mask_prph(__LINE__, priv, reg, bits, mask)
+-#else
+-#define iwl4965_set_bits_mask_prph _iwl4965_set_bits_mask_prph
+-#endif
+-
+-static inline void iwl4965_clear_bits_prph(struct iwl4965_priv
+- *priv, u32 reg, u32 mask)
+-{
+- u32 val = _iwl4965_read_prph(priv, reg);
+- _iwl4965_write_prph(priv, reg, (val & ~mask));
+-}
+-
+-static inline u32 iwl4965_read_targ_mem(struct iwl4965_priv *priv, u32 addr)
+-{
+- iwl4965_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr);
+- return iwl4965_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+-}
+-
+-static inline void iwl4965_write_targ_mem(struct iwl4965_priv *priv, u32 addr, u32 val)
+-{
+- iwl4965_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
+- iwl4965_write_direct32(priv, HBUS_TARG_MEM_WDAT, val);
+-}
+-
+-static inline void iwl4965_write_targ_mem_buf(struct iwl4965_priv *priv, u32 addr,
+- u32 len, u32 *values)
+-{
+- iwl4965_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
+- for (; 0 < len; len -= sizeof(u32), values++)
+- iwl4965_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values);
+-}
+-#endif
+diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
+index d064622..b608e1c 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
++++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+ *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+@@ -36,9 +36,10 @@
+
+ #include <linux/workqueue.h>
+
+-#include "../net/mac80211/ieee80211_rate.h"
++#include "../net/mac80211/rate.h"
+
+ #include "iwl-4965.h"
++#include "iwl-core.h"
+ #include "iwl-helpers.h"
+
+ #define RS_NAME "iwl-4965-rs"
+@@ -83,7 +84,7 @@ struct iwl4965_rate_scale_data {
+ /**
+ * struct iwl4965_scale_tbl_info -- tx params and success history for all rates
+ *
+- * There are two of these in struct iwl_rate_scale_priv,
++ * There are two of these in struct iwl4965_lq_sta,
+ * one for "active", and one for "search".
+ */
+ struct iwl4965_scale_tbl_info {
+@@ -98,8 +99,23 @@ struct iwl4965_scale_tbl_info {
+ struct iwl4965_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */
+ };
+
++#ifdef CONFIG_IWL4965_HT
++
++struct iwl4965_traffic_load {
++ unsigned long time_stamp; /* age of the oldest statistics */
++ u32 packet_count[TID_QUEUE_MAX_SIZE]; /* packet count in this time
++ * slice */
++ u32 total; /* total num of packets during the
++ * last TID_MAX_TIME_DIFF */
++ u8 queue_count; /* number of queues that has
++ * been used since the last cleanup */
++ u8 head; /* start of the circular buffer */
++};
++
++#endif /* CONFIG_IWL4965_HT */
++
+ /**
+- * struct iwl_rate_scale_priv -- driver's rate scaling private structure
++ * struct iwl4965_lq_sta -- driver's rate scaling private structure
+ *
+ * Pointer to this gets passed back and forth between driver and mac80211.
+ */
+@@ -124,7 +140,7 @@ struct iwl4965_lq_sta {
+ u8 valid_antenna;
+ u8 is_green;
+ u8 is_dup;
+- u8 phymode;
++ enum ieee80211_band band;
+ u8 ibss_sta_added;
+
+ /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
+@@ -134,23 +150,30 @@ struct iwl4965_lq_sta {
+ u16 active_mimo_rate;
+ u16 active_rate_basic;
+
+- struct iwl4965_link_quality_cmd lq;
++ struct iwl_link_quality_cmd lq;
+ struct iwl4965_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */
++#ifdef CONFIG_IWL4965_HT
++ struct iwl4965_traffic_load load[TID_MAX_LOAD_COUNT];
++ u8 tx_agg_tid_en;
++#endif
+ #ifdef CONFIG_MAC80211_DEBUGFS
+ struct dentry *rs_sta_dbgfs_scale_table_file;
+ struct dentry *rs_sta_dbgfs_stats_table_file;
++#ifdef CONFIG_IWL4965_HT
++ struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file;
++#endif
+ struct iwl4965_rate dbg_fixed;
+- struct iwl4965_priv *drv;
++ struct iwl_priv *drv;
+ #endif
+ };
+
+-static void rs_rate_scale_perform(struct iwl4965_priv *priv,
++static void rs_rate_scale_perform(struct iwl_priv *priv,
+ struct net_device *dev,
+ struct ieee80211_hdr *hdr,
+ struct sta_info *sta);
+ static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta,
+ struct iwl4965_rate *tx_mcs,
+- struct iwl4965_link_quality_cmd *tbl);
++ struct iwl_link_quality_cmd *tbl);
+
+
+ #ifdef CONFIG_MAC80211_DEBUGFS
+@@ -207,68 +230,150 @@ static s32 expected_tpt_mimo40MHzSGI[IWL_RATE_COUNT] = {
+ 0, 0, 0, 0, 131, 131, 191, 222, 242, 270, 284, 289, 293
+ };
+
+-static int iwl4965_lq_sync_callback(struct iwl4965_priv *priv,
+- struct iwl4965_cmd *cmd, struct sk_buff *skb)
++static inline u8 iwl4965_rate_get_rate(u32 rate_n_flags)
+ {
+- /*We didn't cache the SKB; let the caller free it */
+- return 1;
++ return (u8)(rate_n_flags & 0xFF);
+ }
+
+-static inline u8 iwl4965_rate_get_rate(u32 rate_n_flags)
++static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window)
+ {
+- return (u8)(rate_n_flags & 0xFF);
++ window->data = 0;
++ window->success_counter = 0;
++ window->success_ratio = IWL_INVALID_VALUE;
++ window->counter = 0;
++ window->average_tpt = IWL_INVALID_VALUE;
++ window->stamp = 0;
+ }
+
+-static int rs_send_lq_cmd(struct iwl4965_priv *priv,
+- struct iwl4965_link_quality_cmd *lq, u8 flags)
++#ifdef CONFIG_IWL4965_HT
++/*
++ * removes the old data from the statistics. All data that is older than
++ * TID_MAX_TIME_DIFF, will be deleted.
++ */
++static void rs_tl_rm_old_stats(struct iwl4965_traffic_load *tl, u32 curr_time)
+ {
+-#ifdef CONFIG_IWL4965_DEBUG
+- int i;
+-#endif
+- struct iwl4965_host_cmd cmd = {
+- .id = REPLY_TX_LINK_QUALITY_CMD,
+- .len = sizeof(struct iwl4965_link_quality_cmd),
+- .meta.flags = flags,
+- .data = lq,
+- };
+-
+- if ((lq->sta_id == 0xFF) &&
+- (priv->iw_mode == IEEE80211_IF_TYPE_IBSS))
+- return -EINVAL;
++ /* The oldest age we want to keep */
++ u32 oldest_time = curr_time - TID_MAX_TIME_DIFF;
++
++ while (tl->queue_count &&
++ (tl->time_stamp < oldest_time)) {
++ tl->total -= tl->packet_count[tl->head];
++ tl->packet_count[tl->head] = 0;
++ tl->time_stamp += TID_QUEUE_CELL_SPACING;
++ tl->queue_count--;
++ tl->head++;
++ if (tl->head >= TID_QUEUE_MAX_SIZE)
++ tl->head = 0;
++ }
++}
++
++/*
++ * increment traffic load value for tid and also remove
++ * any old values if passed the certain time period
++ */
++static void rs_tl_add_packet(struct iwl4965_lq_sta *lq_data, u8 tid)
++{
++ u32 curr_time = jiffies_to_msecs(jiffies);
++ u32 time_diff;
++ s32 index;
++ struct iwl4965_traffic_load *tl = NULL;
+
+- if (lq->sta_id == 0xFF)
+- lq->sta_id = IWL_AP_ID;
++ if (tid >= TID_MAX_LOAD_COUNT)
++ return;
+
+- IWL_DEBUG_RATE("lq station id 0x%x\n", lq->sta_id);
+- IWL_DEBUG_RATE("lq dta 0x%X 0x%X\n",
+- lq->general_params.single_stream_ant_msk,
+- lq->general_params.dual_stream_ant_msk);
+-#ifdef CONFIG_IWL4965_DEBUG
+- for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
+- IWL_DEBUG_RATE("lq index %d 0x%X\n",
+- i, lq->rs_table[i].rate_n_flags);
+-#endif
++ tl = &lq_data->load[tid];
+
+- if (flags & CMD_ASYNC)
+- cmd.meta.u.callback = iwl4965_lq_sync_callback;
++ curr_time -= curr_time % TID_ROUND_VALUE;
+
+- if (iwl4965_is_associated(priv) && priv->assoc_station_added &&
+- priv->lq_mngr.lq_ready)
+- return iwl4965_send_cmd(priv, &cmd);
++ /* Happens only for the first packet. Initialize the data */
++ if (!(tl->queue_count)) {
++ tl->total = 1;
++ tl->time_stamp = curr_time;
++ tl->queue_count = 1;
++ tl->head = 0;
++ tl->packet_count[0] = 1;
++ return;
++ }
+
+- return 0;
++ time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time);
++ index = time_diff / TID_QUEUE_CELL_SPACING;
++
++ /* The history is too long: remove data that is older than */
++ /* TID_MAX_TIME_DIFF */
++ if (index >= TID_QUEUE_MAX_SIZE)
++ rs_tl_rm_old_stats(tl, curr_time);
++
++ index = (tl->head + index) % TID_QUEUE_MAX_SIZE;
++ tl->packet_count[index] = tl->packet_count[index] + 1;
++ tl->total = tl->total + 1;
++
++ if ((index + 1) > tl->queue_count)
++ tl->queue_count = index + 1;
+ }
+
+-static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window)
++/*
++ get the traffic load value for tid
++*/
++static u32 rs_tl_get_load(struct iwl4965_lq_sta *lq_data, u8 tid)
+ {
+- window->data = 0;
+- window->success_counter = 0;
+- window->success_ratio = IWL_INVALID_VALUE;
+- window->counter = 0;
+- window->average_tpt = IWL_INVALID_VALUE;
+- window->stamp = 0;
++ u32 curr_time = jiffies_to_msecs(jiffies);
++ u32 time_diff;
++ s32 index;
++ struct iwl4965_traffic_load *tl = NULL;
++
++ if (tid >= TID_MAX_LOAD_COUNT)
++ return 0;
++
++ tl = &(lq_data->load[tid]);
++
++ curr_time -= curr_time % TID_ROUND_VALUE;
++
++ if (!(tl->queue_count))
++ return 0;
++
++ time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time);
++ index = time_diff / TID_QUEUE_CELL_SPACING;
++
++ /* The history is too long: remove data that is older than */
++ /* TID_MAX_TIME_DIFF */
++ if (index >= TID_QUEUE_MAX_SIZE)
++ rs_tl_rm_old_stats(tl, curr_time);
++
++ return tl->total;
++}
++
++static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
++ struct iwl4965_lq_sta *lq_data, u8 tid,
++ struct sta_info *sta)
++{
++ unsigned long state;
++ DECLARE_MAC_BUF(mac);
++
++ spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
++ state = sta->ampdu_mlme.tid_state_tx[tid];
++ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++
++ if (state == HT_AGG_STATE_IDLE &&
++ rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
++ IWL_DEBUG_HT("Starting Tx agg: STA: %s tid: %d\n",
++ print_mac(mac, sta->addr), tid);
++ ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid);
++ }
++}
++
++static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid,
++ struct iwl4965_lq_sta *lq_data,
++ struct sta_info *sta)
++{
++ if ((tid < TID_MAX_LOAD_COUNT))
++ rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
++ else if (tid == IWL_AGG_ALL_TID)
++ for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++)
++ rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
+ }
+
++#endif /* CONFIG_IWLWIFI_HT */
++
+ /**
+ * rs_collect_tx_data - Update the success/failure sliding window
+ *
+@@ -277,7 +382,8 @@ static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window)
+ * packets.
+ */
+ static int rs_collect_tx_data(struct iwl4965_rate_scale_data *windows,
+- int scale_index, s32 tpt, u32 status)
++ int scale_index, s32 tpt, int retries,
++ int successes)
+ {
+ struct iwl4965_rate_scale_data *window = NULL;
+ u64 mask;
+@@ -298,26 +404,33 @@ static int rs_collect_tx_data(struct iwl4965_rate_scale_data *windows,
+ * subtract "1" from the success counter (this is the main reason
+ * we keep these bitmaps!).
+ */
+- if (window->counter >= win_size) {
+- window->counter = win_size - 1;
+- mask = 1;
+- mask = (mask << (win_size - 1));
+- if ((window->data & mask)) {
+- window->data &= ~mask;
+- window->success_counter = window->success_counter - 1;
++ while (retries > 0) {
++ if (window->counter >= win_size) {
++ window->counter = win_size - 1;
++ mask = 1;
++ mask = (mask << (win_size - 1));
++ if (window->data & mask) {
++ window->data &= ~mask;
++ window->success_counter =
++ window->success_counter - 1;
++ }
+ }
+- }
+
+- /* Increment frames-attempted counter */
+- window->counter = window->counter + 1;
++ /* Increment frames-attempted counter */
++ window->counter++;
++
++ /* Shift bitmap by one frame (throw away oldest history),
++ * OR in "1", and increment "success" if this
++ * frame was successful. */
++ mask = window->data;
++ window->data = (mask << 1);
++ if (successes > 0) {
++ window->success_counter = window->success_counter + 1;
++ window->data |= 0x1;
++ successes--;
++ }
+
+- /* Shift bitmap by one frame (throw away oldest history),
+- * OR in "1", and increment "success" if this frame was successful. */
+- mask = window->data;
+- window->data = (mask << 1);
+- if (status != 0) {
+- window->success_counter = window->success_counter + 1;
+- window->data |= 0x1;
++ retries--;
+ }
+
+ /* Calculate current success ratio, avoid divide-by-0! */
+@@ -404,13 +517,14 @@ static void rs_mcs_from_tbl(struct iwl4965_rate *mcs_rate,
+ * fill "search" or "active" tx mode table.
+ */
+ static int rs_get_tbl_info_from_mcs(const struct iwl4965_rate *mcs_rate,
+- int phymode, struct iwl4965_scale_tbl_info *tbl,
++ enum ieee80211_band band,
++ struct iwl4965_scale_tbl_info *tbl,
+ int *rate_idx)
+ {
+ int index;
+ u32 ant_msk;
+
+- index = iwl4965_rate_index_from_plcp(mcs_rate->rate_n_flags);
++ index = iwl4965_hwrate_to_plcp_idx(mcs_rate->rate_n_flags);
+
+ if (index == IWL_RATE_INVALID) {
+ *rate_idx = -1;
+@@ -429,7 +543,7 @@ static int rs_get_tbl_info_from_mcs(const struct iwl4965_rate *mcs_rate,
+ tbl->lq_type = LQ_NONE;
+ else {
+
+- if (phymode == MODE_IEEE80211A)
++ if (band == IEEE80211_BAND_5GHZ)
+ tbl->lq_type = LQ_A;
+ else
+ tbl->lq_type = LQ_G;
+@@ -498,7 +612,7 @@ static inline void rs_toggle_antenna(struct iwl4965_rate *new_rate,
+ }
+ }
+
+-static inline u8 rs_use_green(struct iwl4965_priv *priv,
++static inline u8 rs_use_green(struct iwl_priv *priv,
+ struct ieee80211_conf *conf)
+ {
+ #ifdef CONFIG_IWL4965_HT
+@@ -607,7 +721,7 @@ static void rs_get_lower_rate(struct iwl4965_lq_sta *lq_sta,
+ if (!is_legacy(tbl->lq_type) && (!ht_possible || !scale_index)) {
+ switch_to_legacy = 1;
+ scale_index = rs_ht_to_legacy[scale_index];
+- if (lq_sta->phymode == MODE_IEEE80211A)
++ if (lq_sta->band == IEEE80211_BAND_5GHZ)
+ tbl->lq_type = LQ_A;
+ else
+ tbl->lq_type = LQ_G;
+@@ -625,7 +739,7 @@ static void rs_get_lower_rate(struct iwl4965_lq_sta *lq_sta,
+ /* Mask with station rate restriction */
+ if (is_legacy(tbl->lq_type)) {
+ /* supp_rates has no CCK bits in A mode */
+- if (lq_sta->phymode == (u8) MODE_IEEE80211A)
++ if (lq_sta->band == IEEE80211_BAND_5GHZ)
+ rate_mask = (u16)(rate_mask &
+ (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE));
+ else
+@@ -658,11 +772,12 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
+ u8 retries;
+ int rs_index, index = 0;
+ struct iwl4965_lq_sta *lq_sta;
+- struct iwl4965_link_quality_cmd *table;
++ struct iwl_link_quality_cmd *table;
+ struct sta_info *sta;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+- struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate;
++ struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_hw *hw = local_to_hw(local);
+ struct iwl4965_rate_scale_data *window = NULL;
+ struct iwl4965_rate_scale_data *search_win = NULL;
+ struct iwl4965_rate tx_mcs;
+@@ -677,28 +792,32 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
+ if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1))
+ return;
+
++ /* This packet was aggregated but doesn't carry rate scale info */
++ if ((tx_resp->control.flags & IEEE80211_TXCTL_AMPDU) &&
++ !(tx_resp->flags & IEEE80211_TX_STATUS_AMPDU))
++ return;
++
+ retries = tx_resp->retry_count;
+
+ if (retries > 15)
+ retries = 15;
+
++ rcu_read_lock();
+
+ sta = sta_info_get(local, hdr->addr1);
+
+- if (!sta || !sta->rate_ctrl_priv) {
+- if (sta)
+- sta_info_put(sta);
+- return;
+- }
++ if (!sta || !sta->rate_ctrl_priv)
++ goto out;
++
+
+ lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv;
+
+ if (!priv->lq_mngr.lq_ready)
+- return;
++ goto out;
+
+ if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
+ !lq_sta->ibss_sta_added)
+- return;
++ goto out;
+
+ table = &lq_sta->lq;
+ active_index = lq_sta->active_tbl;
+@@ -719,17 +838,6 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
+ search_win = (struct iwl4965_rate_scale_data *)
+ &(search_tbl->win[0]);
+
+- tx_mcs.rate_n_flags = tx_resp->control.tx_rate;
+-
+- rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode,
+- &tbl_type, &rs_index);
+- if ((rs_index < 0) || (rs_index >= IWL_RATE_COUNT)) {
+- IWL_DEBUG_RATE("bad rate index at: %d rate 0x%X\n",
+- rs_index, tx_mcs.rate_n_flags);
+- sta_info_put(sta);
+- return;
+- }
+-
+ /*
+ * Ignore this Tx frame response if its initial rate doesn't match
+ * that of latest Link Quality command. There may be stragglers
+@@ -738,14 +846,29 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
+ * to check "search" mode, or a prior "search" mode after we've moved
+ * to a new "search" mode (which might become the new "active" mode).
+ */
+- if (retries &&
+- (tx_mcs.rate_n_flags !=
+- le32_to_cpu(table->rs_table[0].rate_n_flags))) {
+- IWL_DEBUG_RATE("initial rate does not match 0x%x 0x%x\n",
+- tx_mcs.rate_n_flags,
+- le32_to_cpu(table->rs_table[0].rate_n_flags));
+- sta_info_put(sta);
+- return;
++ tx_mcs.rate_n_flags = le32_to_cpu(table->rs_table[0].rate_n_flags);
++ rs_get_tbl_info_from_mcs(&tx_mcs, priv->band, &tbl_type, &rs_index);
++ if (priv->band == IEEE80211_BAND_5GHZ)
++ rs_index -= IWL_FIRST_OFDM_RATE;
++
++ if ((tx_resp->control.tx_rate == NULL) ||
++ (tbl_type.is_SGI ^
++ !!(tx_resp->control.flags & IEEE80211_TXCTL_SHORT_GI)) ||
++ (tbl_type.is_fat ^
++ !!(tx_resp->control.flags & IEEE80211_TXCTL_40_MHZ_WIDTH)) ||
++ (tbl_type.is_dup ^
++ !!(tx_resp->control.flags & IEEE80211_TXCTL_DUP_DATA)) ||
++ (tbl_type.antenna_type ^
++ tx_resp->control.antenna_sel_tx) ||
++ (!!(tx_mcs.rate_n_flags & RATE_MCS_HT_MSK) ^
++ !!(tx_resp->control.flags & IEEE80211_TXCTL_OFDM_HT)) ||
++ (!!(tx_mcs.rate_n_flags & RATE_MCS_GF_MSK) ^
++ !!(tx_resp->control.flags & IEEE80211_TXCTL_GREEN_FIELD)) ||
++ (hw->wiphy->bands[priv->band]->bitrates[rs_index].bitrate !=
++ tx_resp->control.tx_rate->bitrate)) {
++ IWL_DEBUG_RATE("initial rate does not match 0x%x\n",
++ tx_mcs.rate_n_flags);
++ goto out;
+ }
+
+ /* Update frame history window with "failure" for each Tx retry. */
+@@ -754,7 +877,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
+ * Each tx attempt steps one entry deeper in the rate table. */
+ tx_mcs.rate_n_flags =
+ le32_to_cpu(table->rs_table[index].rate_n_flags);
+- rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode,
++ rs_get_tbl_info_from_mcs(&tx_mcs, priv->band,
+ &tbl_type, &rs_index);
+
+ /* If type matches "search" table,
+@@ -766,7 +889,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
+ tpt = search_tbl->expected_tpt[rs_index];
+ else
+ tpt = 0;
+- rs_collect_tx_data(search_win, rs_index, tpt, 0);
++ rs_collect_tx_data(search_win, rs_index, tpt, 1, 0);
+
+ /* Else if type matches "current/active" table,
+ * add failure to "current/active" history */
+@@ -777,7 +900,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
+ tpt = curr_tbl->expected_tpt[rs_index];
+ else
+ tpt = 0;
+- rs_collect_tx_data(window, rs_index, tpt, 0);
++ rs_collect_tx_data(window, rs_index, tpt, 1, 0);
+ }
+
+ /* If not searching for a new mode, increment failed counter
+@@ -794,14 +917,8 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
+ * if Tx was successful first try, use original rate,
+ * else look up the rate that was, finally, successful.
+ */
+- if (!tx_resp->retry_count)
+- tx_mcs.rate_n_flags = tx_resp->control.tx_rate;
+- else
+- tx_mcs.rate_n_flags =
+- le32_to_cpu(table->rs_table[index].rate_n_flags);
+-
+- rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode,
+- &tbl_type, &rs_index);
++ tx_mcs.rate_n_flags = le32_to_cpu(table->rs_table[index].rate_n_flags);
++ rs_get_tbl_info_from_mcs(&tx_mcs, priv->band, &tbl_type, &rs_index);
+
+ /* Update frame history window with "success" if Tx got ACKed ... */
+ if (tx_resp->flags & IEEE80211_TX_STATUS_ACK)
+@@ -818,9 +935,13 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
+ tpt = search_tbl->expected_tpt[rs_index];
+ else
+ tpt = 0;
+- rs_collect_tx_data(search_win,
+- rs_index, tpt, status);
+-
++ if (tx_resp->control.flags & IEEE80211_TXCTL_AMPDU)
++ rs_collect_tx_data(search_win, rs_index, tpt,
++ tx_resp->ampdu_ack_len,
++ tx_resp->ampdu_ack_map);
++ else
++ rs_collect_tx_data(search_win, rs_index, tpt,
++ 1, status);
+ /* Else if type matches "current/active" table,
+ * add final tx status to "current/active" history */
+ } else if ((tbl_type.lq_type == curr_tbl->lq_type) &&
+@@ -830,21 +951,34 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
+ tpt = curr_tbl->expected_tpt[rs_index];
+ else
+ tpt = 0;
+- rs_collect_tx_data(window, rs_index, tpt, status);
++ if (tx_resp->control.flags & IEEE80211_TXCTL_AMPDU)
++ rs_collect_tx_data(window, rs_index, tpt,
++ tx_resp->ampdu_ack_len,
++ tx_resp->ampdu_ack_map);
++ else
++ rs_collect_tx_data(window, rs_index, tpt,
++ 1, status);
+ }
+
+ /* If not searching for new mode, increment success/failed counter
+ * ... these help determine when to start searching again */
+ if (lq_sta->stay_in_tbl) {
+- if (status)
+- lq_sta->total_success++;
+- else
+- lq_sta->total_failed++;
++ if (tx_resp->control.flags & IEEE80211_TXCTL_AMPDU) {
++ lq_sta->total_success += tx_resp->ampdu_ack_map;
++ lq_sta->total_failed +=
++ (tx_resp->ampdu_ack_len - tx_resp->ampdu_ack_map);
++ } else {
++ if (status)
++ lq_sta->total_success++;
++ else
++ lq_sta->total_failed++;
++ }
+ }
+
+ /* See if there's a better rate or modulation mode to try. */
+ rs_rate_scale_perform(priv, dev, hdr, sta);
+- sta_info_put(sta);
++out:
++ rcu_read_unlock();
+ return;
+ }
+
+@@ -948,7 +1082,7 @@ static void rs_get_expected_tpt_table(struct iwl4965_lq_sta *lq_sta,
+ * to decrease to match "active" throughput. When moving from MIMO to SISO,
+ * bit rate will typically need to increase, but not if performance was bad.
+ */
+-static s32 rs_get_best_rate(struct iwl4965_priv *priv,
++static s32 rs_get_best_rate(struct iwl_priv *priv,
+ struct iwl4965_lq_sta *lq_sta,
+ struct iwl4965_scale_tbl_info *tbl, /* "search" */
+ u16 rate_mask, s8 index, s8 rate)
+@@ -1046,7 +1180,7 @@ static inline u8 rs_is_both_ant_supp(u8 valid_antenna)
+ /*
+ * Set up search table for MIMO
+ */
+-static int rs_switch_to_mimo(struct iwl4965_priv *priv,
++static int rs_switch_to_mimo(struct iwl_priv *priv,
+ struct iwl4965_lq_sta *lq_sta,
+ struct ieee80211_conf *conf,
+ struct sta_info *sta,
+@@ -1105,13 +1239,13 @@ static int rs_switch_to_mimo(struct iwl4965_priv *priv,
+ return 0;
+ #else
+ return -1;
+-#endif /*CONFIG_IWL4965_HT */
++#endif /*CONFIG_IWL4965_HT */
+ }
+
+ /*
+ * Set up search table for SISO
+ */
+-static int rs_switch_to_siso(struct iwl4965_priv *priv,
++static int rs_switch_to_siso(struct iwl_priv *priv,
+ struct iwl4965_lq_sta *lq_sta,
+ struct ieee80211_conf *conf,
+ struct sta_info *sta,
+@@ -1168,13 +1302,13 @@ static int rs_switch_to_siso(struct iwl4965_priv *priv,
+ #else
+ return -1;
+
+-#endif /*CONFIG_IWL4965_HT */
++#endif /*CONFIG_IWL4965_HT */
+ }
+
+ /*
+ * Try to switch to new modulation mode from legacy
+ */
+-static int rs_move_legacy_other(struct iwl4965_priv *priv,
++static int rs_move_legacy_other(struct iwl_priv *priv,
+ struct iwl4965_lq_sta *lq_sta,
+ struct ieee80211_conf *conf,
+ struct sta_info *sta,
+@@ -1272,7 +1406,7 @@ static int rs_move_legacy_other(struct iwl4965_priv *priv,
+ /*
+ * Try to switch to new modulation mode from SISO
+ */
+-static int rs_move_siso_to_other(struct iwl4965_priv *priv,
++static int rs_move_siso_to_other(struct iwl_priv *priv,
+ struct iwl4965_lq_sta *lq_sta,
+ struct ieee80211_conf *conf,
+ struct sta_info *sta,
+@@ -1325,6 +1459,7 @@ static int rs_move_siso_to_other(struct iwl4965_priv *priv,
+ break;
+ case IWL_SISO_SWITCH_GI:
+ IWL_DEBUG_HT("LQ: SISO SWITCH TO GI\n");
++
+ memcpy(search_tbl, tbl, sz);
+ search_tbl->action = 0;
+ if (search_tbl->is_SGI)
+@@ -1367,7 +1502,7 @@ static int rs_move_siso_to_other(struct iwl4965_priv *priv,
+ /*
+ * Try to switch to new modulation mode from MIMO
+ */
+-static int rs_move_mimo_to_other(struct iwl4965_priv *priv,
++static int rs_move_mimo_to_other(struct iwl_priv *priv,
+ struct iwl4965_lq_sta *lq_sta,
+ struct ieee80211_conf *conf,
+ struct sta_info *sta,
+@@ -1390,6 +1525,7 @@ static int rs_move_mimo_to_other(struct iwl4965_priv *priv,
+ case IWL_MIMO_SWITCH_ANTENNA_B:
+ IWL_DEBUG_HT("LQ: MIMO SWITCH TO SISO\n");
+
++
+ /* Set up new search table for SISO */
+ memcpy(search_tbl, tbl, sz);
+ search_tbl->lq_type = LQ_SISO;
+@@ -1546,7 +1682,7 @@ static void rs_stay_in_table(struct iwl4965_lq_sta *lq_sta)
+ /*
+ * Do rate scaling and search for new modulation mode.
+ */
+-static void rs_rate_scale_perform(struct iwl4965_priv *priv,
++static void rs_rate_scale_perform(struct iwl_priv *priv,
+ struct net_device *dev,
+ struct ieee80211_hdr *hdr,
+ struct sta_info *sta)
+@@ -1574,6 +1710,10 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
+ u8 active_tbl = 0;
+ u8 done_search = 0;
+ u16 high_low;
++#ifdef CONFIG_IWL4965_HT
++ u8 tid = MAX_TID_COUNT;
++ __le16 *qc;
++#endif
+
+ IWL_DEBUG_RATE("rate scale calculate new rate for skb\n");
+
+@@ -1594,6 +1734,13 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
+ }
+ lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv;
+
++#ifdef CONFIG_IWL4965_HT
++ qc = ieee80211_get_qos_ctrl(hdr);
++ if (qc) {
++ tid = (u8)(le16_to_cpu(*qc) & 0xf);
++ rs_tl_add_packet(lq_sta, tid);
++ }
++#endif
+ /*
+ * Select rate-scale / modulation-mode table to work with in
+ * the rest of this function: "search" if searching for better
+@@ -1608,7 +1755,7 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
+ is_green = lq_sta->is_green;
+
+ /* current tx rate */
+- index = sta->last_txrate;
++ index = sta->last_txrate_idx;
+
+ IWL_DEBUG_RATE("Rate scale index %d for type %d\n", index,
+ tbl->lq_type);
+@@ -1621,7 +1768,7 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
+
+ /* mask with station rate restriction */
+ if (is_legacy(tbl->lq_type)) {
+- if (lq_sta->phymode == (u8) MODE_IEEE80211A)
++ if (lq_sta->band == IEEE80211_BAND_5GHZ)
+ /* supp_rates has no CCK bits in A mode */
+ rate_scale_index_msk = (u16) (rate_mask &
+ (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE));
+@@ -1685,7 +1832,7 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
+ if (update_lq) {
+ rs_mcs_from_tbl(&mcs_rate, tbl, index, is_green);
+ rs_fill_link_cmd(lq_sta, &mcs_rate, &lq_sta->lq);
+- rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
++ iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
+ }
+ goto out;
+
+@@ -1727,7 +1874,7 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
+ tbl = &(lq_sta->lq_info[active_tbl]);
+
+ /* Revert to "active" rate and throughput info */
+- index = iwl4965_rate_index_from_plcp(
++ index = iwl4965_hwrate_to_plcp_idx(
+ tbl->current_rate.rate_n_flags);
+ current_tpt = lq_sta->last_tpt;
+
+@@ -1850,7 +1997,7 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
+ if (update_lq) {
+ rs_mcs_from_tbl(&mcs_rate, tbl, index, is_green);
+ rs_fill_link_cmd(lq_sta, &mcs_rate, &lq_sta->lq);
+- rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
++ iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
+ }
+
+ /* Should we stay with this modulation mode, or search for a new one? */
+@@ -1883,14 +2030,14 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
+ rs_rate_scale_clear_window(&(tbl->win[i]));
+
+ /* Use new "search" start rate */
+- index = iwl4965_rate_index_from_plcp(
++ index = iwl4965_hwrate_to_plcp_idx(
+ tbl->current_rate.rate_n_flags);
+
+ IWL_DEBUG_HT("Switch current mcs: %X index: %d\n",
+ tbl->current_rate.rate_n_flags, index);
+ rs_fill_link_cmd(lq_sta, &tbl->current_rate,
+ &lq_sta->lq);
+- rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
++ iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
+ }
+
+ /* If the "active" (non-search) mode was legacy,
+@@ -1914,15 +2061,14 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
+ * mode for a while before next round of mode comparisons. */
+ if (lq_sta->enable_counter &&
+ (lq_sta->action_counter >= IWL_ACTION_LIMIT)) {
+-#ifdef CONFIG_IWL4965_HT_AGG
+- /* If appropriate, set up aggregation! */
+- if ((lq_sta->last_tpt > TID_AGG_TPT_THREHOLD) &&
+- (priv->lq_mngr.agg_ctrl.auto_agg)) {
+- priv->lq_mngr.agg_ctrl.tid_retry =
+- TID_ALL_SPECIFIED;
+- schedule_work(&priv->agg_work);
++#ifdef CONFIG_IWL4965_HT
++ if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) &&
++ (lq_sta->tx_agg_tid_en & (1 << tid)) &&
++ (tid != MAX_TID_COUNT)) {
++ IWL_DEBUG_HT("try to aggregate tid %d\n", tid);
++ rs_tl_turn_on_agg(priv, tid, lq_sta, sta);
+ }
+-#endif /*CONFIG_IWL4965_HT_AGG */
++#endif /*CONFIG_IWL4965_HT */
+ lq_sta->action_counter = 0;
+ rs_set_stay_in_table(0, lq_sta);
+ }
+@@ -1942,21 +2088,21 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv,
+ out:
+ rs_mcs_from_tbl(&tbl->current_rate, tbl, index, is_green);
+ i = index;
+- sta->last_txrate = i;
++ sta->last_txrate_idx = i;
+
+- /* sta->txrate is an index to A mode rates which start
++ /* sta->txrate_idx is an index to A mode rates which start
+ * at IWL_FIRST_OFDM_RATE
+ */
+- if (lq_sta->phymode == (u8) MODE_IEEE80211A)
+- sta->txrate = i - IWL_FIRST_OFDM_RATE;
++ if (lq_sta->band == IEEE80211_BAND_5GHZ)
++ sta->txrate_idx = i - IWL_FIRST_OFDM_RATE;
+ else
+- sta->txrate = i;
++ sta->txrate_idx = i;
+
+ return;
+ }
+
+
+-static void rs_initialize_lq(struct iwl4965_priv *priv,
++static void rs_initialize_lq(struct iwl_priv *priv,
+ struct ieee80211_conf *conf,
+ struct sta_info *sta)
+ {
+@@ -1972,7 +2118,7 @@ static void rs_initialize_lq(struct iwl4965_priv *priv,
+ goto out;
+
+ lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv;
+- i = sta->last_txrate;
++ i = sta->last_txrate_idx;
+
+ if ((lq_sta->lq.sta_id == 0xff) &&
+ (priv->iw_mode == IEEE80211_IF_TYPE_IBSS))
+@@ -1996,7 +2142,7 @@ static void rs_initialize_lq(struct iwl4965_priv *priv,
+ mcs_rate.rate_n_flags |= RATE_MCS_CCK_MSK;
+
+ tbl->antenna_type = ANT_AUX;
+- rs_get_tbl_info_from_mcs(&mcs_rate, priv->phymode, tbl, &rate_idx);
++ rs_get_tbl_info_from_mcs(&mcs_rate, priv->band, tbl, &rate_idx);
+ if (!rs_is_ant_connected(priv->valid_antenna, tbl->antenna_type))
+ rs_toggle_antenna(&mcs_rate, tbl);
+
+@@ -2004,13 +2150,14 @@ static void rs_initialize_lq(struct iwl4965_priv *priv,
+ tbl->current_rate.rate_n_flags = mcs_rate.rate_n_flags;
+ rs_get_expected_tpt_table(lq_sta, tbl);
+ rs_fill_link_cmd(lq_sta, &mcs_rate, &lq_sta->lq);
+- rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
++ iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
+ out:
+ return;
+ }
+
+ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+- struct ieee80211_hw_mode *mode, struct sk_buff *skb,
++ struct ieee80211_supported_band *sband,
++ struct sk_buff *skb,
+ struct rate_selection *sel)
+ {
+
+@@ -2020,11 +2167,13 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct sta_info *sta;
+ u16 fc;
+- struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate;
++ struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
+ struct iwl4965_lq_sta *lq_sta;
+
+ IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n");
+
++ rcu_read_lock();
++
+ sta = sta_info_get(local, hdr->addr1);
+
+ /* Send management frames and broadcast/multicast data using lowest
+@@ -2032,14 +2181,12 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+ fc = le16_to_cpu(hdr->frame_control);
+ if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) ||
+ !sta || !sta->rate_ctrl_priv) {
+- sel->rate = rate_lowest(local, local->oper_hw_mode, sta);
+- if (sta)
+- sta_info_put(sta);
+- return;
++ sel->rate = rate_lowest(local, sband, sta);
++ goto out;
+ }
+
+ lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv;
+- i = sta->last_txrate;
++ i = sta->last_txrate_idx;
+
+ if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
+ !lq_sta->ibss_sta_added) {
+@@ -2062,14 +2209,15 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
+ goto done;
+ }
+
+- done:
++done:
+ if ((i < 0) || (i > IWL_RATE_COUNT)) {
+- sel->rate = rate_lowest(local, local->oper_hw_mode, sta);
+- return;
++ sel->rate = rate_lowest(local, sband, sta);
++ goto out;
+ }
+- sta_info_put(sta);
+
+ sel->rate = &priv->ieee_rates[i];
++out:
++ rcu_read_unlock();
+ }
+
+ static void *rs_alloc_sta(void *priv, gfp_t gfp)
+@@ -2099,13 +2247,15 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
+ {
+ int i, j;
+ struct ieee80211_conf *conf = &local->hw.conf;
+- struct ieee80211_hw_mode *mode = local->oper_hw_mode;
+- struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate;
++ struct ieee80211_supported_band *sband;
++ struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
+ struct iwl4965_lq_sta *lq_sta = priv_sta;
+
++ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++
+ lq_sta->flush_timer = 0;
+- lq_sta->supp_rates = sta->supp_rates;
+- sta->txrate = 3;
++ lq_sta->supp_rates = sta->supp_rates[sband->band];
++ sta->txrate_idx = 3;
+ for (j = 0; j < LQ_SIZE; j++)
+ for (i = 0; i < IWL_RATE_COUNT; i++)
+ rs_rate_scale_clear_window(&(lq_sta->lq_info[j].win[i]));
+@@ -2140,15 +2290,15 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
+ }
+
+ /* Find highest tx rate supported by hardware and destination station */
+- for (i = 0; i < mode->num_rates; i++) {
+- if ((sta->supp_rates & BIT(i)) &&
+- (mode->rates[i].flags & IEEE80211_RATE_SUPPORTED))
+- sta->txrate = i;
+- }
+- sta->last_txrate = sta->txrate;
++ for (i = 0; i < sband->n_bitrates; i++)
++ if (sta->supp_rates[sband->band] & BIT(i))
++ sta->txrate_idx = i;
++
++ sta->last_txrate_idx = sta->txrate_idx;
++ /* WTF is with this bogus comment? A doesn't have cck rates */
+ /* For MODE_IEEE80211A, cck rates are at end of rate table */
+- if (local->hw.conf.phymode == MODE_IEEE80211A)
+- sta->last_txrate += IWL_FIRST_OFDM_RATE;
++ if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ)
++ sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
+
+ lq_sta->is_dup = 0;
+ lq_sta->valid_antenna = priv->valid_antenna;
+@@ -2157,7 +2307,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
+ lq_sta->active_rate = priv->active_rate;
+ lq_sta->active_rate &= ~(0x1000);
+ lq_sta->active_rate_basic = priv->active_rate_basic;
+- lq_sta->phymode = priv->phymode;
++ lq_sta->band = priv->band;
+ #ifdef CONFIG_IWL4965_HT
+ /*
+ * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3),
+@@ -2180,6 +2330,8 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
+ IWL_DEBUG_HT("SISO RATE 0x%X MIMO RATE 0x%X\n",
+ lq_sta->active_siso_rate,
+ lq_sta->active_mimo_rate);
++ /* as default allow aggregation for all tids */
++ lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID;
+ #endif /*CONFIG_IWL4965_HT*/
+ #ifdef CONFIG_MAC80211_DEBUGFS
+ lq_sta->drv = priv;
+@@ -2193,7 +2345,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
+
+ static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta,
+ struct iwl4965_rate *tx_mcs,
+- struct iwl4965_link_quality_cmd *lq_cmd)
++ struct iwl_link_quality_cmd *lq_cmd)
+ {
+ int index = 0;
+ int rate_idx;
+@@ -2207,7 +2359,7 @@ static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta,
+ rs_dbgfs_set_mcs(lq_sta, tx_mcs, index);
+
+ /* Interpret rate_n_flags */
+- rs_get_tbl_info_from_mcs(tx_mcs, lq_sta->phymode,
++ rs_get_tbl_info_from_mcs(tx_mcs, lq_sta->band,
+ &tbl_type, &rate_idx);
+
+ /* How many times should we repeat the initial rate? */
+@@ -2261,7 +2413,7 @@ static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta,
+ index++;
+ }
+
+- rs_get_tbl_info_from_mcs(&new_rate, lq_sta->phymode, &tbl_type,
++ rs_get_tbl_info_from_mcs(&new_rate, lq_sta->band, &tbl_type,
+ &rate_idx);
+
+ /* Indicate to uCode which entries might be MIMO.
+@@ -2318,17 +2470,11 @@ static void rs_free(void *priv_rate)
+
+ static void rs_clear(void *priv_rate)
+ {
+- struct iwl4965_priv *priv = (struct iwl4965_priv *) priv_rate;
++ struct iwl_priv *priv = (struct iwl_priv *) priv_rate;
+
+ IWL_DEBUG_RATE("enter\n");
+
+ priv->lq_mngr.lq_ready = 0;
+-#ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
+- if (priv->lq_mngr.agg_ctrl.granted_ba)
+- iwl4965_turn_off_agg(priv, TID_ALL_SPECIFIED);
+-#endif /*CONFIG_IWL4965_HT_AGG */
+-#endif /* CONFIG_IWL4965_HT */
+
+ IWL_DEBUG_RATE("leave\n");
+ }
+@@ -2354,7 +2500,7 @@ static void rs_dbgfs_set_mcs(struct iwl4965_lq_sta *lq_sta,
+ {
+ u32 base_rate;
+
+- if (lq_sta->phymode == (u8) MODE_IEEE80211A)
++ if (lq_sta->band == IEEE80211_BAND_5GHZ)
+ base_rate = 0x800D;
+ else
+ base_rate = 0x820A;
+@@ -2398,7 +2544,7 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
+
+ if (lq_sta->dbg_fixed.rate_n_flags) {
+ rs_fill_link_cmd(lq_sta, &lq_sta->dbg_fixed, &lq_sta->lq);
+- rs_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC);
++ iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC);
+ }
+
+ return count;
+@@ -2495,6 +2641,12 @@ static void rs_add_debugfs(void *priv, void *priv_sta,
+ lq_sta->rs_sta_dbgfs_stats_table_file =
+ debugfs_create_file("rate_stats_table", 0600, dir,
+ lq_sta, &rs_sta_dbgfs_stats_table_ops);
++#ifdef CONFIG_IWL4965_HT
++ lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file =
++ debugfs_create_u8("tx_agg_tid_enable", 0600, dir,
++ &lq_sta->tx_agg_tid_en);
++#endif
++
+ }
+
+ static void rs_remove_debugfs(void *priv, void *priv_sta)
+@@ -2502,6 +2654,9 @@ static void rs_remove_debugfs(void *priv, void *priv_sta)
+ struct iwl4965_lq_sta *lq_sta = priv_sta;
+ debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file);
+ debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file);
++#ifdef CONFIG_IWL4965_HT
++ debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file);
++#endif
+ }
+ #endif
+
+@@ -2525,7 +2680,7 @@ static struct rate_control_ops rs_ops = {
+ int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
+ {
+ struct ieee80211_local *local = hw_to_local(hw);
+- struct iwl4965_priv *priv = hw->priv;
++ struct iwl_priv *priv = hw->priv;
+ struct iwl4965_lq_sta *lq_sta;
+ struct sta_info *sta;
+ int cnt = 0, i;
+@@ -2534,13 +2689,15 @@ int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
+ u32 max_time = 0;
+ u8 lq_type, antenna;
+
++ rcu_read_lock();
++
+ sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr);
+ if (!sta || !sta->rate_ctrl_priv) {
+- if (sta) {
+- sta_info_put(sta);
++ if (sta)
+ IWL_DEBUG_RATE("leave - no private rate data!\n");
+- } else
++ else
+ IWL_DEBUG_RATE("leave - no station!\n");
++ rcu_read_unlock();
+ return sprintf(buf, "station %d not found\n", sta_id);
+ }
+
+@@ -2605,25 +2762,25 @@ int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
+
+ cnt += sprintf(&buf[cnt], "\nrate scale type %d antenna %d "
+ "active_search %d rate index %d\n", lq_type, antenna,
+- lq_sta->search_better_tbl, sta->last_txrate);
++ lq_sta->search_better_tbl, sta->last_txrate_idx);
+
+- sta_info_put(sta);
++ rcu_read_unlock();
+ return cnt;
+ }
+
+ void iwl4965_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
+ {
+- struct iwl4965_priv *priv = hw->priv;
++ struct iwl_priv *priv = hw->priv;
+
+ priv->lq_mngr.lq_ready = 1;
+ }
+
+-void iwl4965_rate_control_register(struct ieee80211_hw *hw)
++int iwl4965_rate_control_register(void)
+ {
+- ieee80211_rate_control_register(&rs_ops);
++ return ieee80211_rate_control_register(&rs_ops);
+ }
+
+-void iwl4965_rate_control_unregister(struct ieee80211_hw *hw)
++void iwl4965_rate_control_unregister(void)
+ {
+ ieee80211_rate_control_unregister(&rs_ops);
+ }
+diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h
+index 55f7073..866e378 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h
++++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+ *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+@@ -212,6 +212,18 @@ enum {
+
+ #define LQ_SIZE 2 /* 2 mode tables: "Active" and "Search" */
+
++/* load per tid defines for A-MPDU activation */
++#define IWL_AGG_TPT_THREHOLD 0
++#define IWL_AGG_LOAD_THRESHOLD 10
++#define IWL_AGG_ALL_TID 0xff
++#define TID_QUEUE_CELL_SPACING 50 /*mS */
++#define TID_QUEUE_MAX_SIZE 20
++#define TID_ROUND_VALUE 5 /* mS */
++#define TID_MAX_LOAD_COUNT 8
++
++#define TID_MAX_TIME_DIFF ((TID_QUEUE_MAX_SIZE - 1) * TID_QUEUE_CELL_SPACING)
++#define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y))
++
+ extern const struct iwl4965_rate_info iwl4965_rates[IWL_RATE_COUNT];
+
+ enum iwl4965_table_type {
+@@ -247,7 +259,7 @@ static inline u8 iwl4965_get_prev_ieee_rate(u8 rate_index)
+ return rate;
+ }
+
+-extern int iwl4965_rate_index_from_plcp(int plcp);
++extern int iwl4965_hwrate_to_plcp_idx(u32 rate_n_flags);
+
+ /**
+ * iwl4965_fill_rs_info - Fill an output text buffer with the rate representation
+@@ -276,7 +288,7 @@ extern void iwl4965_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id);
+ * ieee80211_register_hw
+ *
+ */
+-extern void iwl4965_rate_control_register(struct ieee80211_hw *hw);
++extern int iwl4965_rate_control_register(void);
+
+ /**
+ * iwl4965_rate_control_unregister - Unregister the rate control callbacks
+@@ -284,6 +296,6 @@ extern void iwl4965_rate_control_register(struct ieee80211_hw *hw);
+ * This should be called after calling ieee80211_unregister_hw, but before
+ * the driver is unloaded.
+ */
+-extern void iwl4965_rate_control_unregister(struct ieee80211_hw *hw);
++extern void iwl4965_rate_control_unregister(void);
+
+ #endif
+diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
+index 6576757..17f629f 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
++++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+ *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+@@ -38,10 +38,21 @@
+ #include <linux/etherdevice.h>
+ #include <asm/unaligned.h>
+
++#include "iwl-eeprom.h"
+ #include "iwl-4965.h"
++#include "iwl-core.h"
++#include "iwl-io.h"
+ #include "iwl-helpers.h"
+
+-static void iwl4965_hw_card_show_info(struct iwl4965_priv *priv);
++/* module parameters */
++static struct iwl_mod_params iwl4965_mod_params = {
++ .num_of_queues = IWL4965_MAX_NUM_QUEUES,
++ .enable_qos = 1,
++ .amsdu_size_8K = 1,
++ /* the rest are 0 by default */
++};
++
++static void iwl4965_hw_card_show_info(struct iwl_priv *priv);
+
+ #define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np) \
+ [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \
+@@ -79,13 +90,277 @@ const struct iwl4965_rate_info iwl4965_rates[IWL_RATE_COUNT] = {
+ IWL_DECLARE_RATE_INFO(60, 60, 48, INV, 48, INV, 48, INV),/* 60mbps */
+ };
+
++#ifdef CONFIG_IWL4965_HT
++
++static const u16 default_tid_to_tx_fifo[] = {
++ IWL_TX_FIFO_AC1,
++ IWL_TX_FIFO_AC0,
++ IWL_TX_FIFO_AC0,
++ IWL_TX_FIFO_AC1,
++ IWL_TX_FIFO_AC2,
++ IWL_TX_FIFO_AC2,
++ IWL_TX_FIFO_AC3,
++ IWL_TX_FIFO_AC3,
++ IWL_TX_FIFO_NONE,
++ IWL_TX_FIFO_NONE,
++ IWL_TX_FIFO_NONE,
++ IWL_TX_FIFO_NONE,
++ IWL_TX_FIFO_NONE,
++ IWL_TX_FIFO_NONE,
++ IWL_TX_FIFO_NONE,
++ IWL_TX_FIFO_NONE,
++ IWL_TX_FIFO_AC3
++};
++
++#endif /*CONFIG_IWL4965_HT */
++
++/* check contents of special bootstrap uCode SRAM */
++static int iwl4965_verify_bsm(struct iwl_priv *priv)
++{
++ __le32 *image = priv->ucode_boot.v_addr;
++ u32 len = priv->ucode_boot.len;
++ u32 reg;
++ u32 val;
++
++ IWL_DEBUG_INFO("Begin verify bsm\n");
++
++ /* verify BSM SRAM contents */
++ val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG);
++ for (reg = BSM_SRAM_LOWER_BOUND;
++ reg < BSM_SRAM_LOWER_BOUND + len;
++ reg += sizeof(u32), image++) {
++ val = iwl_read_prph(priv, reg);
++ if (val != le32_to_cpu(*image)) {
++ IWL_ERROR("BSM uCode verification failed at "
++ "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
++ BSM_SRAM_LOWER_BOUND,
++ reg - BSM_SRAM_LOWER_BOUND, len,
++ val, le32_to_cpu(*image));
++ return -EIO;
++ }
++ }
++
++ IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n");
++
++ return 0;
++}
++
++/**
++ * iwl4965_load_bsm - Load bootstrap instructions
++ *
++ * BSM operation:
++ *
++ * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
++ * in special SRAM that does not power down during RFKILL. When powering back
++ * up after power-saving sleeps (or during initial uCode load), the BSM loads
++ * the bootstrap program into the on-board processor, and starts it.
++ *
++ * The bootstrap program loads (via DMA) instructions and data for a new
++ * program from host DRAM locations indicated by the host driver in the
++ * BSM_DRAM_* registers. Once the new program is loaded, it starts
++ * automatically.
++ *
++ * When initializing the NIC, the host driver points the BSM to the
++ * "initialize" uCode image. This uCode sets up some internal data, then
++ * notifies host via "initialize alive" that it is complete.
++ *
++ * The host then replaces the BSM_DRAM_* pointer values to point to the
++ * normal runtime uCode instructions and a backup uCode data cache buffer
++ * (filled initially with starting data values for the on-board processor),
++ * then triggers the "initialize" uCode to load and launch the runtime uCode,
++ * which begins normal operation.
++ *
++ * When doing a power-save shutdown, runtime uCode saves data SRAM into
++ * the backup data cache in DRAM before SRAM is powered down.
++ *
++ * When powering back up, the BSM loads the bootstrap program. This reloads
++ * the runtime uCode instructions and the backup data cache into SRAM,
++ * and re-launches the runtime uCode from where it left off.
++ */
++static int iwl4965_load_bsm(struct iwl_priv *priv)
++{
++ __le32 *image = priv->ucode_boot.v_addr;
++ u32 len = priv->ucode_boot.len;
++ dma_addr_t pinst;
++ dma_addr_t pdata;
++ u32 inst_len;
++ u32 data_len;
++ int i;
++ u32 done;
++ u32 reg_offset;
++ int ret;
++
++ IWL_DEBUG_INFO("Begin load bsm\n");
++
++ /* make sure bootstrap program is no larger than BSM's SRAM size */
++ if (len > IWL_MAX_BSM_SIZE)
++ return -EINVAL;
++
++ /* Tell bootstrap uCode where to find the "Initialize" uCode
++ * in host DRAM ... host DRAM physical address bits 35:4 for 4965.
++ * NOTE: iwl4965_initialize_alive_start() will replace these values,
++ * after the "initialize" uCode has run, to point to
++ * runtime/protocol instructions and backup data cache. */
++ pinst = priv->ucode_init.p_addr >> 4;
++ pdata = priv->ucode_init_data.p_addr >> 4;
++ inst_len = priv->ucode_init.len;
++ data_len = priv->ucode_init_data.len;
++
++ ret = iwl_grab_nic_access(priv);
++ if (ret)
++ return ret;
++
++ iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
++ iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
++ iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
++ iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
++
++ /* Fill BSM memory with bootstrap instructions */
++ for (reg_offset = BSM_SRAM_LOWER_BOUND;
++ reg_offset < BSM_SRAM_LOWER_BOUND + len;
++ reg_offset += sizeof(u32), image++)
++ _iwl_write_prph(priv, reg_offset, le32_to_cpu(*image));
++
++ ret = iwl4965_verify_bsm(priv);
++ if (ret) {
++ iwl_release_nic_access(priv);
++ return ret;
++ }
++
++ /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
++ iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
++ iwl_write_prph(priv, BSM_WR_MEM_DST_REG, RTC_INST_LOWER_BOUND);
++ iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
++
++ /* Load bootstrap code into instruction SRAM now,
++ * to prepare to load "initialize" uCode */
++ iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START);
++
++ /* Wait for load of bootstrap uCode to finish */
++ for (i = 0; i < 100; i++) {
++ done = iwl_read_prph(priv, BSM_WR_CTRL_REG);
++ if (!(done & BSM_WR_CTRL_REG_BIT_START))
++ break;
++ udelay(10);
++ }
++ if (i < 100)
++ IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i);
++ else {
++ IWL_ERROR("BSM write did not complete!\n");
++ return -EIO;
++ }
++
++ /* Enable future boot loads whenever power management unit triggers it
++ * (e.g. when powering back up after power-save shutdown) */
++ iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN);
++
++ iwl_release_nic_access(priv);
++
++ return 0;
++}
++
++static int iwl4965_init_drv(struct iwl_priv *priv)
++{
++ int ret;
++ int i;
++
++ priv->antenna = (enum iwl4965_antenna)priv->cfg->mod_params->antenna;
++ priv->retry_rate = 1;
++ priv->ibss_beacon = NULL;
++
++ spin_lock_init(&priv->lock);
++ spin_lock_init(&priv->power_data.lock);
++ spin_lock_init(&priv->sta_lock);
++ spin_lock_init(&priv->hcmd_lock);
++ spin_lock_init(&priv->lq_mngr.lock);
++
++ priv->shared_virt = pci_alloc_consistent(priv->pci_dev,
++ sizeof(struct iwl4965_shared),
++ &priv->shared_phys);
++
++ if (!priv->shared_virt) {
++ ret = -ENOMEM;
++ goto err;
++ }
++
++ memset(priv->shared_virt, 0, sizeof(struct iwl4965_shared));
++
++
++ for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++)
++ INIT_LIST_HEAD(&priv->ibss_mac_hash[i]);
++
++ INIT_LIST_HEAD(&priv->free_frames);
++
++ mutex_init(&priv->mutex);
++
++ /* Clear the driver's (not device's) station table */
++ iwlcore_clear_stations_table(priv);
++
++ priv->data_retry_limit = -1;
++ priv->ieee_channels = NULL;
++ priv->ieee_rates = NULL;
++ priv->band = IEEE80211_BAND_2GHZ;
++
++ priv->iw_mode = IEEE80211_IF_TYPE_STA;
++
++ priv->use_ant_b_for_management_frame = 1; /* start with ant B */
++ priv->valid_antenna = 0x7; /* assume all 3 connected */
++ priv->ps_mode = IWL_MIMO_PS_NONE;
++
++ /* Choose which receivers/antennas to use */
++ iwl4965_set_rxon_chain(priv);
++
++ iwlcore_reset_qos(priv);
++
++ priv->qos_data.qos_active = 0;
++ priv->qos_data.qos_cap.val = 0;
++
++ iwlcore_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6);
++
++ priv->rates_mask = IWL_RATES_MASK;
++ /* If power management is turned on, default to AC mode */
++ priv->power_mode = IWL_POWER_AC;
++ priv->user_txpower_limit = IWL_DEFAULT_TX_POWER;
++
++ ret = iwl_init_channel_map(priv);
++ if (ret) {
++ IWL_ERROR("initializing regulatory failed: %d\n", ret);
++ goto err;
++ }
++
++ ret = iwl4965_init_geos(priv);
++ if (ret) {
++ IWL_ERROR("initializing geos failed: %d\n", ret);
++ goto err_free_channel_map;
++ }
++
++ ret = ieee80211_register_hw(priv->hw);
++ if (ret) {
++ IWL_ERROR("Failed to register network device (error %d)\n",
++ ret);
++ goto err_free_geos;
++ }
++
++ priv->hw->conf.beacon_int = 100;
++ priv->mac80211_registered = 1;
++
++ return 0;
++
++err_free_geos:
++ iwl4965_free_geos(priv);
++err_free_channel_map:
++ iwl_free_channel_map(priv);
++err:
++ return ret;
++}
++
+ static int is_fat_channel(__le32 rxon_flags)
+ {
+ return (rxon_flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK) ||
+ (rxon_flags & RXON_FLG_CHANNEL_MODE_MIXED_MSK);
+ }
+
+-static u8 is_single_stream(struct iwl4965_priv *priv)
++static u8 is_single_stream(struct iwl_priv *priv)
+ {
+ #ifdef CONFIG_IWL4965_HT
+ if (!priv->current_ht_config.is_ht ||
+@@ -98,13 +373,71 @@ static u8 is_single_stream(struct iwl4965_priv *priv)
+ return 0;
+ }
+
++int iwl4965_hwrate_to_plcp_idx(u32 rate_n_flags)
++{
++ int idx = 0;
++
++ /* 4965 HT rate format */
++ if (rate_n_flags & RATE_MCS_HT_MSK) {
++ idx = (rate_n_flags & 0xff);
++
++ if (idx >= IWL_RATE_MIMO_6M_PLCP)
++ idx = idx - IWL_RATE_MIMO_6M_PLCP;
++
++ idx += IWL_FIRST_OFDM_RATE;
++ /* skip 9M not supported in ht*/
++ if (idx >= IWL_RATE_9M_INDEX)
++ idx += 1;
++ if ((idx >= IWL_FIRST_OFDM_RATE) && (idx <= IWL_LAST_OFDM_RATE))
++ return idx;
++
++ /* 4965 legacy rate format, search for match in table */
++ } else {
++ for (idx = 0; idx < ARRAY_SIZE(iwl4965_rates); idx++)
++ if (iwl4965_rates[idx].plcp == (rate_n_flags & 0xFF))
++ return idx;
++ }
++
++ return -1;
++}
++
++/**
++ * translate ucode response to mac80211 tx status control values
++ */
++void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
++ struct ieee80211_tx_control *control)
++{
++ int rate_index;
++
++ control->antenna_sel_tx =
++ ((rate_n_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS);
++ if (rate_n_flags & RATE_MCS_HT_MSK)
++ control->flags |= IEEE80211_TXCTL_OFDM_HT;
++ if (rate_n_flags & RATE_MCS_GF_MSK)
++ control->flags |= IEEE80211_TXCTL_GREEN_FIELD;
++ if (rate_n_flags & RATE_MCS_FAT_MSK)
++ control->flags |= IEEE80211_TXCTL_40_MHZ_WIDTH;
++ if (rate_n_flags & RATE_MCS_DUP_MSK)
++ control->flags |= IEEE80211_TXCTL_DUP_DATA;
++ if (rate_n_flags & RATE_MCS_SGI_MSK)
++ control->flags |= IEEE80211_TXCTL_SHORT_GI;
++ /* since iwl4965_hwrate_to_plcp_idx is band indifferent, we always use
++ * IEEE80211_BAND_2GHZ band as it contains all the rates */
++ rate_index = iwl4965_hwrate_to_plcp_idx(rate_n_flags);
++ if (rate_index == -1)
++ control->tx_rate = NULL;
++ else
++ control->tx_rate =
++ &priv->bands[IEEE80211_BAND_2GHZ].bitrates[rate_index];
++}
++
+ /*
+ * Determine how many receiver/antenna chains to use.
+ * More provides better reception via diversity. Fewer saves power.
+ * MIMO (dual stream) requires at least 2, but works better with 3.
+ * This does not determine *which* chains to use, just how many.
+ */
+-static int iwl4965_get_rx_chain_counter(struct iwl4965_priv *priv,
++static int iwl4965_get_rx_chain_counter(struct iwl_priv *priv,
+ u8 *idle_state, u8 *rx_state)
+ {
+ u8 is_single = is_single_stream(priv);
+@@ -133,32 +466,32 @@ static int iwl4965_get_rx_chain_counter(struct iwl4965_priv *priv,
+ return 0;
+ }
+
+-int iwl4965_hw_rxq_stop(struct iwl4965_priv *priv)
++int iwl4965_hw_rxq_stop(struct iwl_priv *priv)
+ {
+ int rc;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+- rc = iwl4965_grab_nic_access(priv);
++ rc = iwl_grab_nic_access(priv);
+ if (rc) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return rc;
+ }
+
+ /* stop Rx DMA */
+- iwl4965_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+- rc = iwl4965_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
++ iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
++ rc = iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
+ (1 << 24), 1000);
+ if (rc < 0)
+ IWL_ERROR("Can't stop Rx DMA.\n");
+
+- iwl4965_release_nic_access(priv);
++ iwl_release_nic_access(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+ }
+
+-u8 iwl4965_hw_find_station(struct iwl4965_priv *priv, const u8 *addr)
++u8 iwl4965_hw_find_station(struct iwl_priv *priv, const u8 *addr)
+ {
+ int i;
+ int start = 0;
+@@ -171,10 +504,10 @@ u8 iwl4965_hw_find_station(struct iwl4965_priv *priv, const u8 *addr)
+ start = IWL_STA_ID;
+
+ if (is_broadcast_ether_addr(addr))
+- return IWL4965_BROADCAST_ID;
++ return priv->hw_params.bcast_sta_id;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+- for (i = start; i < priv->hw_setting.max_stations; i++)
++ for (i = start; i < priv->hw_params.max_stations; i++)
+ if ((priv->stations[i].used) &&
+ (!compare_ether_addr
+ (priv->stations[i].sta.sta.addr, addr))) {
+@@ -190,13 +523,13 @@ u8 iwl4965_hw_find_station(struct iwl4965_priv *priv, const u8 *addr)
+ return ret;
+ }
+
+-static int iwl4965_nic_set_pwr_src(struct iwl4965_priv *priv, int pwr_max)
++static int iwl4965_nic_set_pwr_src(struct iwl_priv *priv, int pwr_max)
+ {
+ int ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+- ret = iwl4965_grab_nic_access(priv);
++ ret = iwl_grab_nic_access(priv);
+ if (ret) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return ret;
+@@ -209,92 +542,92 @@ static int iwl4965_nic_set_pwr_src(struct iwl4965_priv *priv, int pwr_max)
+ &val);
+
+ if (val & PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT)
+- iwl4965_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
++ iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
+ APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
+ ~APMG_PS_CTRL_MSK_PWR_SRC);
+ } else
+- iwl4965_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
++ iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
+ APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
+ ~APMG_PS_CTRL_MSK_PWR_SRC);
+
+- iwl4965_release_nic_access(priv);
++ iwl_release_nic_access(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return ret;
+ }
+
+-static int iwl4965_rx_init(struct iwl4965_priv *priv, struct iwl4965_rx_queue *rxq)
++static int iwl4965_rx_init(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq)
+ {
+- int rc;
++ int ret;
+ unsigned long flags;
+ unsigned int rb_size;
+
+ spin_lock_irqsave(&priv->lock, flags);
+- rc = iwl4965_grab_nic_access(priv);
+- if (rc) {
++ ret = iwl_grab_nic_access(priv);
++ if (ret) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+- return rc;
++ return ret;
+ }
+
+- if (iwl4965_param_amsdu_size_8K)
++ if (priv->cfg->mod_params->amsdu_size_8K)
+ rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
+ else
+ rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
+
+ /* Stop Rx DMA */
+- iwl4965_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
++ iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+
+ /* Reset driver's Rx queue write index */
+- iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
++ iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
+
+ /* Tell device where to find RBD circular buffer in DRAM */
+- iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
+- rxq->dma_addr >> 8);
++ iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
++ rxq->dma_addr >> 8);
+
+ /* Tell device where in DRAM to update its Rx status */
+- iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG,
+- (priv->hw_setting.shared_phys +
+- offsetof(struct iwl4965_shared, val0)) >> 4);
++ iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG,
++ (priv->shared_phys +
++ offsetof(struct iwl4965_shared, rb_closed)) >> 4);
+
+ /* Enable Rx DMA, enable host interrupt, Rx buffer size 4k, 256 RBDs */
+- iwl4965_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG,
+- FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
+- FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
+- rb_size |
+- /*0x10 << 4 | */
+- (RX_QUEUE_SIZE_LOG <<
++ iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG,
++ FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
++ FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
++ rb_size |
++ /* 0x10 << 4 | */
++ (RX_QUEUE_SIZE_LOG <<
+ FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT));
+
+ /*
+- * iwl4965_write32(priv,CSR_INT_COAL_REG,0);
++ * iwl_write32(priv,CSR_INT_COAL_REG,0);
+ */
+
+- iwl4965_release_nic_access(priv);
++ iwl_release_nic_access(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+ }
+
+ /* Tell 4965 where to find the "keep warm" buffer */
+-static int iwl4965_kw_init(struct iwl4965_priv *priv)
++static int iwl4965_kw_init(struct iwl_priv *priv)
+ {
+ unsigned long flags;
+ int rc;
+
+ spin_lock_irqsave(&priv->lock, flags);
+- rc = iwl4965_grab_nic_access(priv);
++ rc = iwl_grab_nic_access(priv);
+ if (rc)
+ goto out;
+
+- iwl4965_write_direct32(priv, IWL_FH_KW_MEM_ADDR_REG,
++ iwl_write_direct32(priv, IWL_FH_KW_MEM_ADDR_REG,
+ priv->kw.dma_addr >> 4);
+- iwl4965_release_nic_access(priv);
++ iwl_release_nic_access(priv);
+ out:
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return rc;
+ }
+
+-static int iwl4965_kw_alloc(struct iwl4965_priv *priv)
++static int iwl4965_kw_alloc(struct iwl_priv *priv)
+ {
+ struct pci_dev *dev = priv->pci_dev;
+ struct iwl4965_kw *kw = &priv->kw;
+@@ -307,58 +640,10 @@ static int iwl4965_kw_alloc(struct iwl4965_priv *priv)
+ return 0;
+ }
+
+-#define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \
+- ? # x " " : "")
+-
+-/**
+- * iwl4965_set_fat_chan_info - Copy fat channel info into driver's priv.
+- *
+- * Does not set up a command, or touch hardware.
+- */
+-int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, int phymode, u16 channel,
+- const struct iwl4965_eeprom_channel *eeprom_ch,
+- u8 fat_extension_channel)
+-{
+- struct iwl4965_channel_info *ch_info;
+-
+- ch_info = (struct iwl4965_channel_info *)
+- iwl4965_get_channel_info(priv, phymode, channel);
+-
+- if (!is_channel_valid(ch_info))
+- return -1;
+-
+- IWL_DEBUG_INFO("FAT Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x"
+- " %ddBm): Ad-Hoc %ssupported\n",
+- ch_info->channel,
+- is_channel_a_band(ch_info) ?
+- "5.2" : "2.4",
+- CHECK_AND_PRINT(IBSS),
+- CHECK_AND_PRINT(ACTIVE),
+- CHECK_AND_PRINT(RADAR),
+- CHECK_AND_PRINT(WIDE),
+- CHECK_AND_PRINT(NARROW),
+- CHECK_AND_PRINT(DFS),
+- eeprom_ch->flags,
+- eeprom_ch->max_power_avg,
+- ((eeprom_ch->flags & EEPROM_CHANNEL_IBSS)
+- && !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ?
+- "" : "not ");
+-
+- ch_info->fat_eeprom = *eeprom_ch;
+- ch_info->fat_max_power_avg = eeprom_ch->max_power_avg;
+- ch_info->fat_curr_txpow = eeprom_ch->max_power_avg;
+- ch_info->fat_min_power = 0;
+- ch_info->fat_scan_power = eeprom_ch->max_power_avg;
+- ch_info->fat_flags = eeprom_ch->flags;
+- ch_info->fat_extension_channel = fat_extension_channel;
+-
+- return 0;
+-}
+-
+ /**
+ * iwl4965_kw_free - Free the "keep warm" buffer
+ */
+-static void iwl4965_kw_free(struct iwl4965_priv *priv)
++static void iwl4965_kw_free(struct iwl_priv *priv)
+ {
+ struct pci_dev *dev = priv->pci_dev;
+ struct iwl4965_kw *kw = &priv->kw;
+@@ -376,7 +661,7 @@ static void iwl4965_kw_free(struct iwl4965_priv *priv)
+ * @param priv
+ * @return error code
+ */
+-static int iwl4965_txq_ctx_reset(struct iwl4965_priv *priv)
++static int iwl4965_txq_ctx_reset(struct iwl_priv *priv)
+ {
+ int rc = 0;
+ int txq_id, slots_num;
+@@ -396,7 +681,7 @@ static int iwl4965_txq_ctx_reset(struct iwl4965_priv *priv)
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+- rc = iwl4965_grab_nic_access(priv);
++ rc = iwl_grab_nic_access(priv);
+ if (unlikely(rc)) {
+ IWL_ERROR("TX reset failed");
+ spin_unlock_irqrestore(&priv->lock, flags);
+@@ -404,8 +689,8 @@ static int iwl4965_txq_ctx_reset(struct iwl4965_priv *priv)
+ }
+
+ /* Turn off all Tx DMA channels */
+- iwl4965_write_prph(priv, KDR_SCD_TXFACT, 0);
+- iwl4965_release_nic_access(priv);
++ iwl_write_prph(priv, IWL49_SCD_TXFACT, 0);
++ iwl_release_nic_access(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ /* Tell 4965 where to find the keep-warm buffer */
+@@ -417,7 +702,7 @@ static int iwl4965_txq_ctx_reset(struct iwl4965_priv *priv)
+
+ /* Alloc and init all (default 16) Tx queues,
+ * including the command queue (#4) */
+- for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) {
++ for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
+ slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
+ TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
+ rc = iwl4965_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
+@@ -438,7 +723,7 @@ static int iwl4965_txq_ctx_reset(struct iwl4965_priv *priv)
+ return rc;
+ }
+
+-int iwl4965_hw_nic_init(struct iwl4965_priv *priv)
++int iwl4965_hw_nic_init(struct iwl_priv *priv)
+ {
+ int rc;
+ unsigned long flags;
+@@ -452,11 +737,11 @@ int iwl4965_hw_nic_init(struct iwl4965_priv *priv)
+ /* nic_init */
+ spin_lock_irqsave(&priv->lock, flags);
+
+- iwl4965_set_bit(priv, CSR_GIO_CHICKEN_BITS,
++ iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
+ CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
+
+- iwl4965_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+- rc = iwl4965_poll_bit(priv, CSR_GP_CNTRL,
++ iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
++ rc = iwl_poll_bit(priv, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
+ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
+ if (rc < 0) {
+@@ -465,26 +750,25 @@ int iwl4965_hw_nic_init(struct iwl4965_priv *priv)
+ return rc;
+ }
+
+- rc = iwl4965_grab_nic_access(priv);
++ rc = iwl_grab_nic_access(priv);
+ if (rc) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return rc;
+ }
+
+- iwl4965_read_prph(priv, APMG_CLK_CTRL_REG);
++ iwl_read_prph(priv, APMG_CLK_CTRL_REG);
+
+- iwl4965_write_prph(priv, APMG_CLK_CTRL_REG,
+- APMG_CLK_VAL_DMA_CLK_RQT |
+- APMG_CLK_VAL_BSM_CLK_RQT);
+- iwl4965_read_prph(priv, APMG_CLK_CTRL_REG);
++ iwl_write_prph(priv, APMG_CLK_CTRL_REG,
++ APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT);
++ iwl_read_prph(priv, APMG_CLK_CTRL_REG);
+
+ udelay(20);
+
+- iwl4965_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
+- APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
++ iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
++ APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
+
+- iwl4965_release_nic_access(priv);
+- iwl4965_write32(priv, CSR_INT_COALESCING, 512 / 32);
++ iwl_release_nic_access(priv);
++ iwl_write32(priv, CSR_INT_COALESCING, 512 / 32);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ /* Determine HW type */
+@@ -520,25 +804,24 @@ int iwl4965_hw_nic_init(struct iwl4965_priv *priv)
+
+ /* set CSR_HW_CONFIG_REG for uCode use */
+
+- iwl4965_set_bit(priv, CSR_SW_VER, CSR_HW_IF_CONFIG_REG_BIT_KEDRON_R |
+- CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
+- CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
++ iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
++ CSR49_HW_IF_CONFIG_REG_BIT_4965_R |
++ CSR49_HW_IF_CONFIG_REG_BIT_RADIO_SI |
++ CSR49_HW_IF_CONFIG_REG_BIT_MAC_SI);
+
+- rc = iwl4965_grab_nic_access(priv);
++ rc = iwl_grab_nic_access(priv);
+ if (rc < 0) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ IWL_DEBUG_INFO("Failed to init the card\n");
+ return rc;
+ }
+
+- iwl4965_read_prph(priv, APMG_PS_CTRL_REG);
+- iwl4965_set_bits_prph(priv, APMG_PS_CTRL_REG,
+- APMG_PS_CTRL_VAL_RESET_REQ);
++ iwl_read_prph(priv, APMG_PS_CTRL_REG);
++ iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ);
+ udelay(5);
+- iwl4965_clear_bits_prph(priv, APMG_PS_CTRL_REG,
+- APMG_PS_CTRL_VAL_RESET_REQ);
++ iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ);
+
+- iwl4965_release_nic_access(priv);
++ iwl_release_nic_access(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ iwl4965_hw_card_show_info(priv);
+@@ -582,7 +865,7 @@ int iwl4965_hw_nic_init(struct iwl4965_priv *priv)
+ return 0;
+ }
+
+-int iwl4965_hw_nic_stop_master(struct iwl4965_priv *priv)
++int iwl4965_hw_nic_stop_master(struct iwl_priv *priv)
+ {
+ int rc = 0;
+ u32 reg_val;
+@@ -591,16 +874,16 @@ int iwl4965_hw_nic_stop_master(struct iwl4965_priv *priv)
+ spin_lock_irqsave(&priv->lock, flags);
+
+ /* set stop master bit */
+- iwl4965_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
++ iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
+
+- reg_val = iwl4965_read32(priv, CSR_GP_CNTRL);
++ reg_val = iwl_read32(priv, CSR_GP_CNTRL);
+
+ if (CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE ==
+ (reg_val & CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE))
+ IWL_DEBUG_INFO("Card in power save, master is already "
+ "stopped\n");
+ else {
+- rc = iwl4965_poll_bit(priv, CSR_RESET,
++ rc = iwl_poll_bit(priv, CSR_RESET,
+ CSR_RESET_REG_FLAG_MASTER_DISABLED,
+ CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
+ if (rc < 0) {
+@@ -618,27 +901,26 @@ int iwl4965_hw_nic_stop_master(struct iwl4965_priv *priv)
+ /**
+ * iwl4965_hw_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory
+ */
+-void iwl4965_hw_txq_ctx_stop(struct iwl4965_priv *priv)
++void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv)
+ {
+
+ int txq_id;
+ unsigned long flags;
+
+ /* Stop each Tx DMA channel, and wait for it to be idle */
+- for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) {
++ for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
+ spin_lock_irqsave(&priv->lock, flags);
+- if (iwl4965_grab_nic_access(priv)) {
++ if (iwl_grab_nic_access(priv)) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ continue;
+ }
+
+- iwl4965_write_direct32(priv,
+- IWL_FH_TCSR_CHNL_TX_CONFIG_REG(txq_id),
+- 0x0);
+- iwl4965_poll_direct_bit(priv, IWL_FH_TSSR_TX_STATUS_REG,
+- IWL_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE
+- (txq_id), 200);
+- iwl4965_release_nic_access(priv);
++ iwl_write_direct32(priv,
++ IWL_FH_TCSR_CHNL_TX_CONFIG_REG(txq_id), 0x0);
++ iwl_poll_direct_bit(priv, IWL_FH_TSSR_TX_STATUS_REG,
++ IWL_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE
++ (txq_id), 200);
++ iwl_release_nic_access(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+
+@@ -646,7 +928,7 @@ void iwl4965_hw_txq_ctx_stop(struct iwl4965_priv *priv)
+ iwl4965_hw_txq_ctx_free(priv);
+ }
+
+-int iwl4965_hw_nic_reset(struct iwl4965_priv *priv)
++int iwl4965_hw_nic_reset(struct iwl_priv *priv)
+ {
+ int rc = 0;
+ unsigned long flags;
+@@ -655,29 +937,29 @@ int iwl4965_hw_nic_reset(struct iwl4965_priv *priv)
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+- iwl4965_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
++ iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+
+ udelay(10);
+
+- iwl4965_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+- rc = iwl4965_poll_bit(priv, CSR_RESET,
++ iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
++ rc = iwl_poll_bit(priv, CSR_RESET,
+ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
+ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25);
+
+ udelay(10);
+
+- rc = iwl4965_grab_nic_access(priv);
++ rc = iwl_grab_nic_access(priv);
+ if (!rc) {
+- iwl4965_write_prph(priv, APMG_CLK_EN_REG,
+- APMG_CLK_VAL_DMA_CLK_RQT |
+- APMG_CLK_VAL_BSM_CLK_RQT);
++ iwl_write_prph(priv, APMG_CLK_EN_REG,
++ APMG_CLK_VAL_DMA_CLK_RQT |
++ APMG_CLK_VAL_BSM_CLK_RQT);
+
+ udelay(10);
+
+- iwl4965_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
+- APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
++ iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
++ APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
+
+- iwl4965_release_nic_access(priv);
++ iwl_release_nic_access(priv);
+ }
+
+ clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
+@@ -694,56 +976,37 @@ int iwl4965_hw_nic_reset(struct iwl4965_priv *priv)
+ /**
+ * iwl4965_bg_statistics_periodic - Timer callback to queue statistics
+ *
+- * This callback is provided in order to queue the statistics_work
+- * in work_queue context (v. softirq)
++ * This callback is provided in order to send a statistics request.
+ *
+ * This timer function is continually reset to execute within
+ * REG_RECALIB_PERIOD seconds since the last STATISTICS_NOTIFICATION
+ * was received. We need to ensure we receive the statistics in order
+- * to update the temperature used for calibrating the TXPOWER. However,
+- * we can't send the statistics command from softirq context (which
+- * is the context which timers run at) so we have to queue off the
+- * statistics_work to actually send the command to the hardware.
++ * to update the temperature used for calibrating the TXPOWER.
+ */
+ static void iwl4965_bg_statistics_periodic(unsigned long data)
+ {
+- struct iwl4965_priv *priv = (struct iwl4965_priv *)data;
+-
+- queue_work(priv->workqueue, &priv->statistics_work);
+-}
+-
+-/**
+- * iwl4965_bg_statistics_work - Send the statistics request to the hardware.
+- *
+- * This is queued by iwl4965_bg_statistics_periodic.
+- */
+-static void iwl4965_bg_statistics_work(struct work_struct *work)
+-{
+- struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv,
+- statistics_work);
++ struct iwl_priv *priv = (struct iwl_priv *)data;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+- mutex_lock(&priv->mutex);
+- iwl4965_send_statistics_request(priv);
+- mutex_unlock(&priv->mutex);
++ iwl_send_statistics_request(priv, CMD_ASYNC);
+ }
+
+ #define CT_LIMIT_CONST 259
+ #define TM_CT_KILL_THRESHOLD 110
+
+-void iwl4965_rf_kill_ct_config(struct iwl4965_priv *priv)
++void iwl4965_rf_kill_ct_config(struct iwl_priv *priv)
+ {
+ struct iwl4965_ct_kill_config cmd;
+ u32 R1, R2, R3;
+ u32 temp_th;
+ u32 crit_temperature;
+ unsigned long flags;
+- int rc = 0;
++ int ret = 0;
+
+ spin_lock_irqsave(&priv->lock, flags);
+- iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR,
++ iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+ CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+@@ -761,9 +1024,9 @@ void iwl4965_rf_kill_ct_config(struct iwl4965_priv *priv)
+
+ crit_temperature = ((temp_th * (R3-R1))/CT_LIMIT_CONST) + R2;
+ cmd.critical_temperature_R = cpu_to_le32(crit_temperature);
+- rc = iwl4965_send_cmd_pdu(priv,
+- REPLY_CT_KILL_CONFIG_CMD, sizeof(cmd), &cmd);
+- if (rc)
++ ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
++ sizeof(cmd), &cmd);
++ if (ret)
+ IWL_ERROR("REPLY_CT_KILL_CONFIG_CMD failed\n");
+ else
+ IWL_DEBUG_INFO("REPLY_CT_KILL_CONFIG_CMD succeeded\n");
+@@ -779,7 +1042,7 @@ void iwl4965_rf_kill_ct_config(struct iwl4965_priv *priv)
+ * enough to receive all of our own network traffic, but not so
+ * high that our DSP gets too busy trying to lock onto non-network
+ * activity/noise. */
+-static int iwl4965_sens_energy_cck(struct iwl4965_priv *priv,
++static int iwl4965_sens_energy_cck(struct iwl_priv *priv,
+ u32 norm_fa,
+ u32 rx_enable_time,
+ struct statistics_general_data *rx_info)
+@@ -970,7 +1233,7 @@ static int iwl4965_sens_energy_cck(struct iwl4965_priv *priv,
+ }
+
+
+-static int iwl4965_sens_auto_corr_ofdm(struct iwl4965_priv *priv,
++static int iwl4965_sens_auto_corr_ofdm(struct iwl_priv *priv,
+ u32 norm_fa,
+ u32 rx_enable_time)
+ {
+@@ -1035,25 +1298,25 @@ static int iwl4965_sens_auto_corr_ofdm(struct iwl4965_priv *priv,
+ return 0;
+ }
+
+-static int iwl4965_sensitivity_callback(struct iwl4965_priv *priv,
+- struct iwl4965_cmd *cmd, struct sk_buff *skb)
++static int iwl4965_sensitivity_callback(struct iwl_priv *priv,
++ struct iwl_cmd *cmd, struct sk_buff *skb)
+ {
+ /* We didn't cache the SKB; let the caller free it */
+ return 1;
+ }
+
+ /* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */
+-static int iwl4965_sensitivity_write(struct iwl4965_priv *priv, u8 flags)
++static int iwl4965_sensitivity_write(struct iwl_priv *priv, u8 flags)
+ {
+- int rc = 0;
+ struct iwl4965_sensitivity_cmd cmd ;
+ struct iwl4965_sensitivity_data *data = NULL;
+- struct iwl4965_host_cmd cmd_out = {
++ struct iwl_host_cmd cmd_out = {
+ .id = SENSITIVITY_CMD,
+ .len = sizeof(struct iwl4965_sensitivity_cmd),
+ .meta.flags = flags,
+ .data = &cmd,
+ };
++ int ret;
+
+ data = &(priv->sensitivity_data);
+
+@@ -1111,20 +1374,18 @@ static int iwl4965_sensitivity_write(struct iwl4965_priv *priv, u8 flags)
+ memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]),
+ sizeof(u16)*HD_TABLE_SIZE);
+
+- rc = iwl4965_send_cmd(priv, &cmd_out);
+- if (!rc) {
+- IWL_DEBUG_CALIB("SENSITIVITY_CMD succeeded\n");
+- return rc;
+- }
++ ret = iwl_send_cmd(priv, &cmd_out);
++ if (ret)
++ IWL_ERROR("SENSITIVITY_CMD failed\n");
+
+- return 0;
++ return ret;
+ }
+
+-void iwl4965_init_sensitivity(struct iwl4965_priv *priv, u8 flags, u8 force)
++void iwl4965_init_sensitivity(struct iwl_priv *priv, u8 flags, u8 force)
+ {
+- int rc = 0;
+- int i;
+ struct iwl4965_sensitivity_data *data = NULL;
++ int i;
++ int ret = 0;
+
+ IWL_DEBUG_CALIB("Start iwl4965_init_sensitivity\n");
+
+@@ -1168,8 +1429,8 @@ void iwl4965_init_sensitivity(struct iwl4965_priv *priv, u8 flags, u8 force)
+ memset(&(priv->sensitivity_tbl[0]), 0,
+ sizeof(u16)*HD_TABLE_SIZE);
+
+- rc |= iwl4965_sensitivity_write(priv, flags);
+- IWL_DEBUG_CALIB("<<return 0x%X\n", rc);
++ ret |= iwl4965_sensitivity_write(priv, flags);
++ IWL_DEBUG_CALIB("<<return 0x%X\n", ret);
+
+ return;
+ }
+@@ -1178,13 +1439,12 @@ void iwl4965_init_sensitivity(struct iwl4965_priv *priv, u8 flags, u8 force)
+ /* Reset differential Rx gains in NIC to prepare for chain noise calibration.
+ * Called after every association, but this runs only once!
+ * ... once chain noise is calibrated the first time, it's good forever. */
+-void iwl4965_chain_noise_reset(struct iwl4965_priv *priv)
++void iwl4965_chain_noise_reset(struct iwl_priv *priv)
+ {
+ struct iwl4965_chain_noise_data *data = NULL;
+- int rc = 0;
+
+ data = &(priv->chain_noise_data);
+- if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl4965_is_associated(priv)) {
++ if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) {
+ struct iwl4965_calibration_cmd cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+@@ -1192,8 +1452,8 @@ void iwl4965_chain_noise_reset(struct iwl4965_priv *priv)
+ cmd.diff_gain_a = 0;
+ cmd.diff_gain_b = 0;
+ cmd.diff_gain_c = 0;
+- rc = iwl4965_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
+- sizeof(cmd), &cmd);
++ iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD,
++ sizeof(cmd), &cmd, NULL);
+ msleep(4);
+ data->state = IWL_CHAIN_NOISE_ACCUMULATE;
+ IWL_DEBUG_CALIB("Run chain_noise_calibrate\n");
+@@ -1207,11 +1467,11 @@ void iwl4965_chain_noise_reset(struct iwl4965_priv *priv)
+ * 1) Which antennas are connected.
+ * 2) Differential rx gain settings to balance the 3 receivers.
+ */
+-static void iwl4965_noise_calibration(struct iwl4965_priv *priv,
++static void iwl4965_noise_calibration(struct iwl_priv *priv,
+ struct iwl4965_notif_statistics *stat_resp)
+ {
+ struct iwl4965_chain_noise_data *data = NULL;
+- int rc = 0;
++ int ret = 0;
+
+ u32 chain_noise_a;
+ u32 chain_noise_b;
+@@ -1417,9 +1677,9 @@ static void iwl4965_noise_calibration(struct iwl4965_priv *priv,
+ cmd.diff_gain_a = data->delta_gain_code[0];
+ cmd.diff_gain_b = data->delta_gain_code[1];
+ cmd.diff_gain_c = data->delta_gain_code[2];
+- rc = iwl4965_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
++ ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
+ sizeof(cmd), &cmd);
+- if (rc)
++ if (ret)
+ IWL_DEBUG_CALIB("fail sending cmd "
+ "REPLY_PHY_CALIBRATION_CMD \n");
+
+@@ -1440,10 +1700,9 @@ static void iwl4965_noise_calibration(struct iwl4965_priv *priv,
+ return;
+ }
+
+-static void iwl4965_sensitivity_calibration(struct iwl4965_priv *priv,
++static void iwl4965_sensitivity_calibration(struct iwl_priv *priv,
+ struct iwl4965_notif_statistics *resp)
+ {
+- int rc = 0;
+ u32 rx_enable_time;
+ u32 fa_cck;
+ u32 fa_ofdm;
+@@ -1456,10 +1715,11 @@ static void iwl4965_sensitivity_calibration(struct iwl4965_priv *priv,
+ struct statistics_rx *statistics = &(resp->rx);
+ unsigned long flags;
+ struct statistics_general_data statis;
++ int ret;
+
+ data = &(priv->sensitivity_data);
+
+- if (!iwl4965_is_associated(priv)) {
++ if (!iwl_is_associated(priv)) {
+ IWL_DEBUG_CALIB("<< - not associated\n");
+ return;
+ }
+@@ -1540,14 +1800,14 @@ static void iwl4965_sensitivity_calibration(struct iwl4965_priv *priv,
+
+ iwl4965_sens_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time);
+ iwl4965_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis);
+- rc |= iwl4965_sensitivity_write(priv, CMD_ASYNC);
++ ret = iwl4965_sensitivity_write(priv, CMD_ASYNC);
+
+ return;
+ }
+
+ static void iwl4965_bg_sensitivity_work(struct work_struct *work)
+ {
+- struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv,
++ struct iwl_priv *priv = container_of(work, struct iwl_priv,
+ sensitivity_work);
+
+ mutex_lock(&priv->mutex);
+@@ -1577,7 +1837,7 @@ static void iwl4965_bg_sensitivity_work(struct work_struct *work)
+
+ static void iwl4965_bg_txpower_work(struct work_struct *work)
+ {
+- struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv,
++ struct iwl_priv *priv = container_of(work, struct iwl_priv,
+ txpower_work);
+
+ /* If a scan happened to start before we got here
+@@ -1605,11 +1865,11 @@ static void iwl4965_bg_txpower_work(struct work_struct *work)
+ /*
+ * Acquire priv->lock before calling this function !
+ */
+-static void iwl4965_set_wr_ptrs(struct iwl4965_priv *priv, int txq_id, u32 index)
++static void iwl4965_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index)
+ {
+- iwl4965_write_direct32(priv, HBUS_TARG_WRPTR,
++ iwl_write_direct32(priv, HBUS_TARG_WRPTR,
+ (index & 0xff) | (txq_id << 8));
+- iwl4965_write_prph(priv, KDR_SCD_QUEUE_RDPTR(txq_id), index);
++ iwl_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(txq_id), index);
+ }
+
+ /**
+@@ -1619,7 +1879,7 @@ static void iwl4965_set_wr_ptrs(struct iwl4965_priv *priv, int txq_id, u32 index
+ *
+ * NOTE: Acquire priv->lock before calling this function !
+ */
+-static void iwl4965_tx_queue_set_status(struct iwl4965_priv *priv,
++static void iwl4965_tx_queue_set_status(struct iwl_priv *priv,
+ struct iwl4965_tx_queue *txq,
+ int tx_fifo_id, int scd_retry)
+ {
+@@ -1629,7 +1889,7 @@ static void iwl4965_tx_queue_set_status(struct iwl4965_priv *priv,
+ int active = test_bit(txq_id, &priv->txq_ctx_active_msk)?1:0;
+
+ /* Set up and activate */
+- iwl4965_write_prph(priv, KDR_SCD_QUEUE_STATUS_BITS(txq_id),
++ iwl_write_prph(priv, IWL49_SCD_QUEUE_STATUS_BITS(txq_id),
+ (active << SCD_QUEUE_STTS_REG_POS_ACTIVE) |
+ (tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) |
+ (scd_retry << SCD_QUEUE_STTS_REG_POS_WSL) |
+@@ -1653,22 +1913,22 @@ static const u16 default_queue_to_tx_fifo[] = {
+ IWL_TX_FIFO_HCCA_2
+ };
+
+-static inline void iwl4965_txq_ctx_activate(struct iwl4965_priv *priv, int txq_id)
++static inline void iwl4965_txq_ctx_activate(struct iwl_priv *priv, int txq_id)
+ {
+ set_bit(txq_id, &priv->txq_ctx_active_msk);
+ }
+
+-static inline void iwl4965_txq_ctx_deactivate(struct iwl4965_priv *priv, int txq_id)
++static inline void iwl4965_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id)
+ {
+ clear_bit(txq_id, &priv->txq_ctx_active_msk);
+ }
+
+-int iwl4965_alive_notify(struct iwl4965_priv *priv)
++int iwl4965_alive_notify(struct iwl_priv *priv)
+ {
+ u32 a;
+ int i = 0;
+ unsigned long flags;
+- int rc;
++ int ret;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+@@ -1681,46 +1941,46 @@ int iwl4965_alive_notify(struct iwl4965_priv *priv)
+ priv->chain_noise_data.delta_gain_code[i] =
+ CHAIN_NOISE_DELTA_GAIN_INIT_VAL;
+ #endif /* CONFIG_IWL4965_SENSITIVITY*/
+- rc = iwl4965_grab_nic_access(priv);
+- if (rc) {
++ ret = iwl_grab_nic_access(priv);
++ if (ret) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+- return rc;
++ return ret;
+ }
+
+ /* Clear 4965's internal Tx Scheduler data base */
+- priv->scd_base_addr = iwl4965_read_prph(priv, KDR_SCD_SRAM_BASE_ADDR);
++ priv->scd_base_addr = iwl_read_prph(priv, IWL49_SCD_SRAM_BASE_ADDR);
+ a = priv->scd_base_addr + SCD_CONTEXT_DATA_OFFSET;
+ for (; a < priv->scd_base_addr + SCD_TX_STTS_BITMAP_OFFSET; a += 4)
+- iwl4965_write_targ_mem(priv, a, 0);
++ iwl_write_targ_mem(priv, a, 0);
+ for (; a < priv->scd_base_addr + SCD_TRANSLATE_TBL_OFFSET; a += 4)
+- iwl4965_write_targ_mem(priv, a, 0);
+- for (; a < sizeof(u16) * priv->hw_setting.max_txq_num; a += 4)
+- iwl4965_write_targ_mem(priv, a, 0);
++ iwl_write_targ_mem(priv, a, 0);
++ for (; a < sizeof(u16) * priv->hw_params.max_txq_num; a += 4)
++ iwl_write_targ_mem(priv, a, 0);
+
+ /* Tel 4965 where to find Tx byte count tables */
+- iwl4965_write_prph(priv, KDR_SCD_DRAM_BASE_ADDR,
+- (priv->hw_setting.shared_phys +
++ iwl_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR,
++ (priv->shared_phys +
+ offsetof(struct iwl4965_shared, queues_byte_cnt_tbls)) >> 10);
+
+ /* Disable chain mode for all queues */
+- iwl4965_write_prph(priv, KDR_SCD_QUEUECHAIN_SEL, 0);
++ iwl_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0);
+
+ /* Initialize each Tx queue (including the command queue) */
+- for (i = 0; i < priv->hw_setting.max_txq_num; i++) {
++ for (i = 0; i < priv->hw_params.max_txq_num; i++) {
+
+ /* TFD circular buffer read/write indexes */
+- iwl4965_write_prph(priv, KDR_SCD_QUEUE_RDPTR(i), 0);
+- iwl4965_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8));
++ iwl_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(i), 0);
++ iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8));
+
+ /* Max Tx Window size for Scheduler-ACK mode */
+- iwl4965_write_targ_mem(priv, priv->scd_base_addr +
++ iwl_write_targ_mem(priv, priv->scd_base_addr +
+ SCD_CONTEXT_QUEUE_OFFSET(i),
+ (SCD_WIN_SIZE <<
+ SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) &
+ SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
+
+ /* Frame limit */
+- iwl4965_write_targ_mem(priv, priv->scd_base_addr +
++ iwl_write_targ_mem(priv, priv->scd_base_addr +
+ SCD_CONTEXT_QUEUE_OFFSET(i) +
+ sizeof(u32),
+ (SCD_FRAME_LIMIT <<
+@@ -1728,11 +1988,11 @@ int iwl4965_alive_notify(struct iwl4965_priv *priv)
+ SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
+
+ }
+- iwl4965_write_prph(priv, KDR_SCD_INTERRUPT_MASK,
+- (1 << priv->hw_setting.max_txq_num) - 1);
++ iwl_write_prph(priv, IWL49_SCD_INTERRUPT_MASK,
++ (1 << priv->hw_params.max_txq_num) - 1);
+
+ /* Activate all Tx DMA/FIFO channels */
+- iwl4965_write_prph(priv, KDR_SCD_TXFACT,
++ iwl_write_prph(priv, IWL49_SCD_TXFACT,
+ SCD_TXFACT_REG_TXFIFO_MASK(0, 7));
+
+ iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
+@@ -1744,42 +2004,47 @@ int iwl4965_alive_notify(struct iwl4965_priv *priv)
+ iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0);
+ }
+
+- iwl4965_release_nic_access(priv);
++ iwl_release_nic_access(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+- return 0;
++ /* Ask for statistics now, the uCode will send statistics notification
++ * periodically after association */
++ iwl_send_statistics_request(priv, CMD_ASYNC);
++ return ret;
+ }
+
+ /**
+- * iwl4965_hw_set_hw_setting
++ * iwl4965_hw_set_hw_params
+ *
+ * Called when initializing driver
+ */
+-int iwl4965_hw_set_hw_setting(struct iwl4965_priv *priv)
++int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
+ {
+- /* Allocate area for Tx byte count tables and Rx queue status */
+- priv->hw_setting.shared_virt =
+- pci_alloc_consistent(priv->pci_dev,
+- sizeof(struct iwl4965_shared),
+- &priv->hw_setting.shared_phys);
+-
+- if (!priv->hw_setting.shared_virt)
+- return -1;
+
+- memset(priv->hw_setting.shared_virt, 0, sizeof(struct iwl4965_shared));
++ if ((priv->cfg->mod_params->num_of_queues > IWL4965_MAX_NUM_QUEUES) ||
++ (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) {
++ IWL_ERROR("invalid queues_num, should be between %d and %d\n",
++ IWL_MIN_NUM_QUEUES, IWL4965_MAX_NUM_QUEUES);
++ return -EINVAL;
++ }
+
+- priv->hw_setting.max_txq_num = iwl4965_param_queues_num;
+- priv->hw_setting.ac_queue_count = AC_NUM;
+- priv->hw_setting.tx_cmd_len = sizeof(struct iwl4965_tx_cmd);
+- priv->hw_setting.max_rxq_size = RX_QUEUE_SIZE;
+- priv->hw_setting.max_rxq_log = RX_QUEUE_SIZE_LOG;
+- if (iwl4965_param_amsdu_size_8K)
+- priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE_8K;
++ priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues;
++ priv->hw_params.tx_cmd_len = sizeof(struct iwl4965_tx_cmd);
++ priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
++ priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
++ if (priv->cfg->mod_params->amsdu_size_8K)
++ priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_8K;
+ else
+- priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE_4K;
+- priv->hw_setting.max_pkt_size = priv->hw_setting.rx_buf_size - 256;
+- priv->hw_setting.max_stations = IWL4965_STATION_COUNT;
+- priv->hw_setting.bcast_sta_id = IWL4965_BROADCAST_ID;
++ priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_4K;
++ priv->hw_params.max_pkt_size = priv->hw_params.rx_buf_size - 256;
++ priv->hw_params.max_stations = IWL4965_STATION_COUNT;
++ priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID;
++
++ priv->hw_params.tx_chains_num = 2;
++ priv->hw_params.rx_chains_num = 2;
++ priv->hw_params.valid_tx_ant = (IWL_ANTENNA_MAIN | IWL_ANTENNA_AUX);
++ priv->hw_params.valid_rx_ant = (IWL_ANTENNA_MAIN | IWL_ANTENNA_AUX);
++
+ return 0;
+ }
+
+@@ -1788,12 +2053,12 @@ int iwl4965_hw_set_hw_setting(struct iwl4965_priv *priv)
+ *
+ * Destroy all TX DMA queues and structures
+ */
+-void iwl4965_hw_txq_ctx_free(struct iwl4965_priv *priv)
++void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv)
+ {
+ int txq_id;
+
+ /* Tx queues */
+- for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++)
++ for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
+ iwl4965_tx_queue_free(priv, &priv->txq[txq_id]);
+
+ /* Keep-warm buffer */
+@@ -1806,7 +2071,7 @@ void iwl4965_hw_txq_ctx_free(struct iwl4965_priv *priv)
+ * Does NOT advance any TFD circular buffer read/write indexes
+ * Does NOT free the TFD itself (which is within circular buffer)
+ */
+-int iwl4965_hw_txq_free_tfd(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq)
++int iwl4965_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl4965_tx_queue *txq)
+ {
+ struct iwl4965_tfd_frame *bd_tmp = (struct iwl4965_tfd_frame *)&txq->bd[0];
+ struct iwl4965_tfd_frame *bd = &bd_tmp[txq->q.read_ptr];
+@@ -1859,7 +2124,7 @@ int iwl4965_hw_txq_free_tfd(struct iwl4965_priv *priv, struct iwl4965_tx_queue *
+ return 0;
+ }
+
+-int iwl4965_hw_reg_set_txpower(struct iwl4965_priv *priv, s8 power)
++int iwl4965_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)
+ {
+ IWL_ERROR("TODO: Implement iwl4965_hw_reg_set_txpower!\n");
+ return -EINVAL;
+@@ -1914,12 +2179,13 @@ static s32 iwl4965_get_voltage_compensation(s32 eeprom_voltage,
+ return comp;
+ }
+
+-static const struct iwl4965_channel_info *
+-iwl4965_get_channel_txpower_info(struct iwl4965_priv *priv, u8 phymode, u16 channel)
++static const struct iwl_channel_info *
++iwl4965_get_channel_txpower_info(struct iwl_priv *priv,
++ enum ieee80211_band band, u16 channel)
+ {
+- const struct iwl4965_channel_info *ch_info;
++ const struct iwl_channel_info *ch_info;
+
+- ch_info = iwl4965_get_channel_info(priv, phymode, channel);
++ ch_info = iwl_get_channel_info(priv, band, channel);
+
+ if (!is_channel_valid(ch_info))
+ return NULL;
+@@ -1953,7 +2219,7 @@ static s32 iwl4965_get_tx_atten_grp(u16 channel)
+ return -1;
+ }
+
+-static u32 iwl4965_get_sub_band(const struct iwl4965_priv *priv, u32 channel)
++static u32 iwl4965_get_sub_band(const struct iwl_priv *priv, u32 channel)
+ {
+ s32 b = -1;
+
+@@ -1989,7 +2255,7 @@ static s32 iwl4965_interpolate_value(s32 x, s32 x1, s32 y1, s32 x2, s32 y2)
+ * differences in channel frequencies, which is proportional to differences
+ * in channel number.
+ */
+-static int iwl4965_interpolate_chan(struct iwl4965_priv *priv, u32 channel,
++static int iwl4965_interpolate_chan(struct iwl_priv *priv, u32 channel,
+ struct iwl4965_eeprom_calib_ch_info *chan_info)
+ {
+ s32 s = -1;
+@@ -2322,7 +2588,7 @@ static const struct gain_entry gain_table[2][108] = {
+ }
+ };
+
+-static int iwl4965_fill_txpower_tbl(struct iwl4965_priv *priv, u8 band, u16 channel,
++static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
+ u8 is_fat, u8 ctrl_chan_high,
+ struct iwl4965_tx_power_db *tx_power_tbl)
+ {
+@@ -2336,7 +2602,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl4965_priv *priv, u8 band, u16 chan
+ s32 txatten_grp = CALIB_CH_GROUP_MAX;
+ int i;
+ int c;
+- const struct iwl4965_channel_info *ch_info = NULL;
++ const struct iwl_channel_info *ch_info = NULL;
+ struct iwl4965_eeprom_calib_ch_info ch_eeprom_info;
+ const struct iwl4965_eeprom_calib_measure *measurement;
+ s16 voltage;
+@@ -2368,7 +2634,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl4965_priv *priv, u8 band, u16 chan
+
+ /* Get current (RXON) channel, band, width */
+ ch_info =
+- iwl4965_get_channel_txpower_info(priv, priv->phymode, channel);
++ iwl4965_get_channel_txpower_info(priv, priv->band, channel);
+
+ IWL_DEBUG_TXPOWER("chan %d band %d is_fat %d\n", channel, band,
+ is_fat);
+@@ -2579,10 +2845,10 @@ static int iwl4965_fill_txpower_tbl(struct iwl4965_priv *priv, u8 band, u16 chan
+ * Uses the active RXON for channel, band, and characteristics (fat, high)
+ * The power limit is taken from priv->user_txpower_limit.
+ */
+-int iwl4965_hw_reg_send_txpower(struct iwl4965_priv *priv)
++int iwl4965_hw_reg_send_txpower(struct iwl_priv *priv)
+ {
+ struct iwl4965_txpowertable_cmd cmd = { 0 };
+- int rc = 0;
++ int ret;
+ u8 band = 0;
+ u8 is_fat = 0;
+ u8 ctrl_chan_high = 0;
+@@ -2595,8 +2861,7 @@ int iwl4965_hw_reg_send_txpower(struct iwl4965_priv *priv)
+ return -EAGAIN;
+ }
+
+- band = ((priv->phymode == MODE_IEEE80211B) ||
+- (priv->phymode == MODE_IEEE80211G));
++ band = priv->band == IEEE80211_BAND_2GHZ;
+
+ is_fat = is_fat_channel(priv->active_rxon.flags);
+
+@@ -2607,29 +2872,70 @@ int iwl4965_hw_reg_send_txpower(struct iwl4965_priv *priv)
+ cmd.band = band;
+ cmd.channel = priv->active_rxon.channel;
+
+- rc = iwl4965_fill_txpower_tbl(priv, band,
++ ret = iwl4965_fill_txpower_tbl(priv, band,
+ le16_to_cpu(priv->active_rxon.channel),
+ is_fat, ctrl_chan_high, &cmd.tx_power);
+- if (rc)
+- return rc;
++ if (ret)
++ goto out;
+
+- rc = iwl4965_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD, sizeof(cmd), &cmd);
+- return rc;
++ ret = iwl_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD, sizeof(cmd), &cmd);
++
++out:
++ return ret;
+ }
+
+-int iwl4965_hw_channel_switch(struct iwl4965_priv *priv, u16 channel)
++static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
++{
++ int ret = 0;
++ struct iwl4965_rxon_assoc_cmd rxon_assoc;
++ const struct iwl4965_rxon_cmd *rxon1 = &priv->staging_rxon;
++ const struct iwl4965_rxon_cmd *rxon2 = &priv->active_rxon;
++
++ if ((rxon1->flags == rxon2->flags) &&
++ (rxon1->filter_flags == rxon2->filter_flags) &&
++ (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
++ (rxon1->ofdm_ht_single_stream_basic_rates ==
++ rxon2->ofdm_ht_single_stream_basic_rates) &&
++ (rxon1->ofdm_ht_dual_stream_basic_rates ==
++ rxon2->ofdm_ht_dual_stream_basic_rates) &&
++ (rxon1->rx_chain == rxon2->rx_chain) &&
++ (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
++ IWL_DEBUG_INFO("Using current RXON_ASSOC. Not resending.\n");
++ return 0;
++ }
++
++ rxon_assoc.flags = priv->staging_rxon.flags;
++ rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
++ rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
++ rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
++ rxon_assoc.reserved = 0;
++ rxon_assoc.ofdm_ht_single_stream_basic_rates =
++ priv->staging_rxon.ofdm_ht_single_stream_basic_rates;
++ rxon_assoc.ofdm_ht_dual_stream_basic_rates =
++ priv->staging_rxon.ofdm_ht_dual_stream_basic_rates;
++ rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain;
++
++ ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC,
++ sizeof(rxon_assoc), &rxon_assoc, NULL);
++ if (ret)
++ return ret;
++
++ return ret;
++}
++
++
++int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
+ {
+ int rc;
+ u8 band = 0;
+ u8 is_fat = 0;
+ u8 ctrl_chan_high = 0;
+ struct iwl4965_channel_switch_cmd cmd = { 0 };
+- const struct iwl4965_channel_info *ch_info;
++ const struct iwl_channel_info *ch_info;
+
+- band = ((priv->phymode == MODE_IEEE80211B) ||
+- (priv->phymode == MODE_IEEE80211G));
++ band = priv->band == IEEE80211_BAND_2GHZ;
+
+- ch_info = iwl4965_get_channel_info(priv, priv->phymode, channel);
++ ch_info = iwl_get_channel_info(priv, priv->band, channel);
+
+ is_fat = is_fat_channel(priv->staging_rxon.flags);
+
+@@ -2655,15 +2961,15 @@ int iwl4965_hw_channel_switch(struct iwl4965_priv *priv, u16 channel)
+ return rc;
+ }
+
+- rc = iwl4965_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
++ rc = iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
+ return rc;
+ }
+
+ #define RTS_HCCA_RETRY_LIMIT 3
+ #define RTS_DFAULT_RETRY_LIMIT 60
+
+-void iwl4965_hw_build_tx_cmd_rate(struct iwl4965_priv *priv,
+- struct iwl4965_cmd *cmd,
++void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv,
++ struct iwl_cmd *cmd,
+ struct ieee80211_tx_control *ctrl,
+ struct ieee80211_hdr *hdr, int sta_id,
+ int is_hcca)
+@@ -2674,7 +2980,7 @@ void iwl4965_hw_build_tx_cmd_rate(struct iwl4965_priv *priv,
+ u16 fc = le16_to_cpu(hdr->frame_control);
+ u8 rate_plcp;
+ u16 rate_flags = 0;
+- int rate_idx = min(ctrl->tx_rate & 0xffff, IWL_RATE_COUNT - 1);
++ int rate_idx = min(ctrl->tx_rate->hw_value & 0xffff, IWL_RATE_COUNT - 1);
+
+ rate_plcp = iwl4965_rates[rate_idx].plcp;
+
+@@ -2729,19 +3035,18 @@ void iwl4965_hw_build_tx_cmd_rate(struct iwl4965_priv *priv,
+ tx->rate_n_flags = iwl4965_hw_set_rate_n_flags(rate_plcp, rate_flags);
+ }
+
+-int iwl4965_hw_get_rx_read(struct iwl4965_priv *priv)
++int iwl4965_hw_get_rx_read(struct iwl_priv *priv)
+ {
+- struct iwl4965_shared *shared_data = priv->hw_setting.shared_virt;
+-
+- return IWL_GET_BITS(*shared_data, rb_closed_stts_rb_num);
++ struct iwl4965_shared *s = priv->shared_virt;
++ return le32_to_cpu(s->rb_closed) & 0xFFF;
+ }
+
+-int iwl4965_hw_get_temperature(struct iwl4965_priv *priv)
++int iwl4965_hw_get_temperature(struct iwl_priv *priv)
+ {
+ return priv->temperature;
+ }
+
+-unsigned int iwl4965_hw_get_beacon_cmd(struct iwl4965_priv *priv,
++unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
+ struct iwl4965_frame *frame, u8 rate)
+ {
+ struct iwl4965_tx_beacon_cmd *tx_beacon_cmd;
+@@ -2750,7 +3055,7 @@ unsigned int iwl4965_hw_get_beacon_cmd(struct iwl4965_priv *priv,
+ tx_beacon_cmd = &frame->u.beacon;
+ memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
+
+- tx_beacon_cmd->tx.sta_id = IWL4965_BROADCAST_ID;
++ tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id;
+ tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+
+ frame_size = iwl4965_fill_beacon_frame(priv,
+@@ -2780,35 +3085,35 @@ unsigned int iwl4965_hw_get_beacon_cmd(struct iwl4965_priv *priv,
+ * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
+ * channels supported in hardware.
+ */
+-int iwl4965_hw_tx_queue_init(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq)
++int iwl4965_hw_tx_queue_init(struct iwl_priv *priv, struct iwl4965_tx_queue *txq)
+ {
+ int rc;
+ unsigned long flags;
+ int txq_id = txq->q.id;
+
+ spin_lock_irqsave(&priv->lock, flags);
+- rc = iwl4965_grab_nic_access(priv);
++ rc = iwl_grab_nic_access(priv);
+ if (rc) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return rc;
+ }
+
+ /* Circular buffer (TFD queue in DRAM) physical base address */
+- iwl4965_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
++ iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
+ txq->q.dma_addr >> 8);
+
+ /* Enable DMA channel, using same id as for TFD queue */
+- iwl4965_write_direct32(
++ iwl_write_direct32(
+ priv, IWL_FH_TCSR_CHNL_TX_CONFIG_REG(txq_id),
+ IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
+ IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL);
+- iwl4965_release_nic_access(priv);
++ iwl_release_nic_access(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+ }
+
+-int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl4965_priv *priv, void *ptr,
++int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr,
+ dma_addr_t addr, u16 len)
+ {
+ int index, is_odd;
+@@ -2842,7 +3147,7 @@ int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl4965_priv *priv, void *ptr,
+ return 0;
+ }
+
+-static void iwl4965_hw_card_show_info(struct iwl4965_priv *priv)
++static void iwl4965_hw_card_show_info(struct iwl_priv *priv)
+ {
+ u16 hw_version = priv->eeprom.board_revision_4965;
+
+@@ -2858,17 +3163,15 @@ static void iwl4965_hw_card_show_info(struct iwl4965_priv *priv)
+ #define IWL_TX_DELIMITER_SIZE 4
+
+ /**
+- * iwl4965_tx_queue_update_wr_ptr - Set up entry in Tx byte-count array
++ * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
+ */
+-int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv,
+- struct iwl4965_tx_queue *txq, u16 byte_cnt)
++static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
++ struct iwl4965_tx_queue *txq,
++ u16 byte_cnt)
+ {
+ int len;
+ int txq_id = txq->q.id;
+- struct iwl4965_shared *shared_data = priv->hw_setting.shared_virt;
+-
+- if (txq->need_update == 0)
+- return 0;
++ struct iwl4965_shared *shared_data = priv->shared_virt;
+
+ len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
+
+@@ -2881,8 +3184,6 @@ int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv,
+ IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id].
+ tfd_offset[IWL4965_QUEUE_SIZE + txq->q.write_ptr],
+ byte_cnt, len);
+-
+- return 0;
+ }
+
+ /**
+@@ -2891,7 +3192,7 @@ int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv,
+ * Selects how many and which Rx receivers/antennas/chains to use.
+ * This should not be used for scan command ... it puts data in wrong place.
+ */
+-void iwl4965_set_rxon_chain(struct iwl4965_priv *priv)
++void iwl4965_set_rxon_chain(struct iwl_priv *priv)
+ {
+ u8 is_single = is_single_stream(priv);
+ u8 idle_state, rx_state;
+@@ -2922,378 +3223,6 @@ void iwl4965_set_rxon_chain(struct iwl4965_priv *priv)
+ IWL_DEBUG_ASSOC("rx chain %X\n", priv->staging_rxon.rx_chain);
+ }
+
+-#ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
+-/*
+- get the traffic load value for tid
+-*/
+-static u32 iwl4965_tl_get_load(struct iwl4965_priv *priv, u8 tid)
+-{
+- u32 load = 0;
+- u32 current_time = jiffies_to_msecs(jiffies);
+- u32 time_diff;
+- s32 index;
+- unsigned long flags;
+- struct iwl4965_traffic_load *tid_ptr = NULL;
+-
+- if (tid >= TID_MAX_LOAD_COUNT)
+- return 0;
+-
+- tid_ptr = &(priv->lq_mngr.agg_ctrl.traffic_load[tid]);
+-
+- current_time -= current_time % TID_ROUND_VALUE;
+-
+- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+- if (!(tid_ptr->queue_count))
+- goto out;
+-
+- time_diff = TIME_WRAP_AROUND(tid_ptr->time_stamp, current_time);
+- index = time_diff / TID_QUEUE_CELL_SPACING;
+-
+- if (index >= TID_QUEUE_MAX_SIZE) {
+- u32 oldest_time = current_time - TID_MAX_TIME_DIFF;
+-
+- while (tid_ptr->queue_count &&
+- (tid_ptr->time_stamp < oldest_time)) {
+- tid_ptr->total -= tid_ptr->packet_count[tid_ptr->head];
+- tid_ptr->packet_count[tid_ptr->head] = 0;
+- tid_ptr->time_stamp += TID_QUEUE_CELL_SPACING;
+- tid_ptr->queue_count--;
+- tid_ptr->head++;
+- if (tid_ptr->head >= TID_QUEUE_MAX_SIZE)
+- tid_ptr->head = 0;
+- }
+- }
+- load = tid_ptr->total;
+-
+- out:
+- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+- return load;
+-}
+-
+-/*
+- increment traffic load value for tid and also remove
+- any old values if passed the certian time period
+-*/
+-static void iwl4965_tl_add_packet(struct iwl4965_priv *priv, u8 tid)
+-{
+- u32 current_time = jiffies_to_msecs(jiffies);
+- u32 time_diff;
+- s32 index;
+- unsigned long flags;
+- struct iwl4965_traffic_load *tid_ptr = NULL;
+-
+- if (tid >= TID_MAX_LOAD_COUNT)
+- return;
+-
+- tid_ptr = &(priv->lq_mngr.agg_ctrl.traffic_load[tid]);
+-
+- current_time -= current_time % TID_ROUND_VALUE;
+-
+- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+- if (!(tid_ptr->queue_count)) {
+- tid_ptr->total = 1;
+- tid_ptr->time_stamp = current_time;
+- tid_ptr->queue_count = 1;
+- tid_ptr->head = 0;
+- tid_ptr->packet_count[0] = 1;
+- goto out;
+- }
+-
+- time_diff = TIME_WRAP_AROUND(tid_ptr->time_stamp, current_time);
+- index = time_diff / TID_QUEUE_CELL_SPACING;
+-
+- if (index >= TID_QUEUE_MAX_SIZE) {
+- u32 oldest_time = current_time - TID_MAX_TIME_DIFF;
+-
+- while (tid_ptr->queue_count &&
+- (tid_ptr->time_stamp < oldest_time)) {
+- tid_ptr->total -= tid_ptr->packet_count[tid_ptr->head];
+- tid_ptr->packet_count[tid_ptr->head] = 0;
+- tid_ptr->time_stamp += TID_QUEUE_CELL_SPACING;
+- tid_ptr->queue_count--;
+- tid_ptr->head++;
+- if (tid_ptr->head >= TID_QUEUE_MAX_SIZE)
+- tid_ptr->head = 0;
+- }
+- }
+-
+- index = (tid_ptr->head + index) % TID_QUEUE_MAX_SIZE;
+- tid_ptr->packet_count[index] = tid_ptr->packet_count[index] + 1;
+- tid_ptr->total = tid_ptr->total + 1;
+-
+- if ((index + 1) > tid_ptr->queue_count)
+- tid_ptr->queue_count = index + 1;
+- out:
+- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+-
+-}
+-
+-#define MMAC_SCHED_MAX_NUMBER_OF_HT_BACK_FLOWS 7
+-enum HT_STATUS {
+- BA_STATUS_FAILURE = 0,
+- BA_STATUS_INITIATOR_DELBA,
+- BA_STATUS_RECIPIENT_DELBA,
+- BA_STATUS_RENEW_ADDBA_REQUEST,
+- BA_STATUS_ACTIVE,
+-};
+-
+-/**
+- * iwl4964_tl_ba_avail - Find out if an unused aggregation queue is available
+- */
+-static u8 iwl4964_tl_ba_avail(struct iwl4965_priv *priv)
+-{
+- int i;
+- struct iwl4965_lq_mngr *lq;
+- u8 count = 0;
+- u16 msk;
+-
+- lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr);
+-
+- /* Find out how many agg queues are in use */
+- for (i = 0; i < TID_MAX_LOAD_COUNT ; i++) {
+- msk = 1 << i;
+- if ((lq->agg_ctrl.granted_ba & msk) ||
+- (lq->agg_ctrl.wait_for_agg_status & msk))
+- count++;
+- }
+-
+- if (count < MMAC_SCHED_MAX_NUMBER_OF_HT_BACK_FLOWS)
+- return 1;
+-
+- return 0;
+-}
+-
+-static void iwl4965_ba_status(struct iwl4965_priv *priv,
+- u8 tid, enum HT_STATUS status);
+-
+-static int iwl4965_perform_addba(struct iwl4965_priv *priv, u8 tid, u32 length,
+- u32 ba_timeout)
+-{
+- int rc;
+-
+- rc = ieee80211_start_BA_session(priv->hw, priv->bssid, tid);
+- if (rc)
+- iwl4965_ba_status(priv, tid, BA_STATUS_FAILURE);
+-
+- return rc;
+-}
+-
+-static int iwl4965_perform_delba(struct iwl4965_priv *priv, u8 tid)
+-{
+- int rc;
+-
+- rc = ieee80211_stop_BA_session(priv->hw, priv->bssid, tid);
+- if (rc)
+- iwl4965_ba_status(priv, tid, BA_STATUS_FAILURE);
+-
+- return rc;
+-}
+-
+-static void iwl4965_turn_on_agg_for_tid(struct iwl4965_priv *priv,
+- struct iwl4965_lq_mngr *lq,
+- u8 auto_agg, u8 tid)
+-{
+- u32 tid_msk = (1 << tid);
+- unsigned long flags;
+-
+- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+-/*
+- if ((auto_agg) && (!lq->enable_counter)){
+- lq->agg_ctrl.next_retry = 0;
+- lq->agg_ctrl.tid_retry = 0;
+- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+- return;
+- }
+-*/
+- if (!(lq->agg_ctrl.granted_ba & tid_msk) &&
+- (lq->agg_ctrl.requested_ba & tid_msk)) {
+- u8 available_queues;
+- u32 load;
+-
+- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+- available_queues = iwl4964_tl_ba_avail(priv);
+- load = iwl4965_tl_get_load(priv, tid);
+-
+- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+- if (!available_queues) {
+- if (auto_agg)
+- lq->agg_ctrl.tid_retry |= tid_msk;
+- else {
+- lq->agg_ctrl.requested_ba &= ~tid_msk;
+- lq->agg_ctrl.wait_for_agg_status &= ~tid_msk;
+- }
+- } else if ((auto_agg) &&
+- ((load <= lq->agg_ctrl.tid_traffic_load_threshold) ||
+- ((lq->agg_ctrl.wait_for_agg_status & tid_msk))))
+- lq->agg_ctrl.tid_retry |= tid_msk;
+- else {
+- lq->agg_ctrl.wait_for_agg_status |= tid_msk;
+- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+- iwl4965_perform_addba(priv, tid, 0x40,
+- lq->agg_ctrl.ba_timeout);
+- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+- }
+- }
+- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+-}
+-
+-static void iwl4965_turn_on_agg(struct iwl4965_priv *priv, u8 tid)
+-{
+- struct iwl4965_lq_mngr *lq;
+- unsigned long flags;
+-
+- lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr);
+-
+- if ((tid < TID_MAX_LOAD_COUNT))
+- iwl4965_turn_on_agg_for_tid(priv, lq, lq->agg_ctrl.auto_agg,
+- tid);
+- else if (tid == TID_ALL_SPECIFIED) {
+- if (lq->agg_ctrl.requested_ba) {
+- for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++)
+- iwl4965_turn_on_agg_for_tid(priv, lq,
+- lq->agg_ctrl.auto_agg, tid);
+- } else {
+- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+- lq->agg_ctrl.tid_retry = 0;
+- lq->agg_ctrl.next_retry = 0;
+- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+- }
+- }
+-
+-}
+-
+-void iwl4965_turn_off_agg(struct iwl4965_priv *priv, u8 tid)
+-{
+- u32 tid_msk;
+- struct iwl4965_lq_mngr *lq;
+- unsigned long flags;
+-
+- lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr);
+-
+- if ((tid < TID_MAX_LOAD_COUNT)) {
+- tid_msk = 1 << tid;
+- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+- lq->agg_ctrl.wait_for_agg_status |= tid_msk;
+- lq->agg_ctrl.requested_ba &= ~tid_msk;
+- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+- iwl4965_perform_delba(priv, tid);
+- } else if (tid == TID_ALL_SPECIFIED) {
+- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+- for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++) {
+- tid_msk = 1 << tid;
+- lq->agg_ctrl.wait_for_agg_status |= tid_msk;
+- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+- iwl4965_perform_delba(priv, tid);
+- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+- }
+- lq->agg_ctrl.requested_ba = 0;
+- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+- }
+-}
+-
+-/**
+- * iwl4965_ba_status - Update driver's link quality mgr with tid's HT status
+- */
+-static void iwl4965_ba_status(struct iwl4965_priv *priv,
+- u8 tid, enum HT_STATUS status)
+-{
+- struct iwl4965_lq_mngr *lq;
+- u32 tid_msk = (1 << tid);
+- unsigned long flags;
+-
+- lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr);
+-
+- if ((tid >= TID_MAX_LOAD_COUNT))
+- goto out;
+-
+- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+- switch (status) {
+- case BA_STATUS_ACTIVE:
+- if (!(lq->agg_ctrl.granted_ba & tid_msk))
+- lq->agg_ctrl.granted_ba |= tid_msk;
+- break;
+- default:
+- if ((lq->agg_ctrl.granted_ba & tid_msk))
+- lq->agg_ctrl.granted_ba &= ~tid_msk;
+- break;
+- }
+-
+- lq->agg_ctrl.wait_for_agg_status &= ~tid_msk;
+- if (status != BA_STATUS_ACTIVE) {
+- if (lq->agg_ctrl.auto_agg) {
+- lq->agg_ctrl.tid_retry |= tid_msk;
+- lq->agg_ctrl.next_retry =
+- jiffies + msecs_to_jiffies(500);
+- } else
+- lq->agg_ctrl.requested_ba &= ~tid_msk;
+- }
+- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+- out:
+- return;
+-}
+-
+-static void iwl4965_bg_agg_work(struct work_struct *work)
+-{
+- struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv,
+- agg_work);
+-
+- u32 tid;
+- u32 retry_tid;
+- u32 tid_msk;
+- unsigned long flags;
+- struct iwl4965_lq_mngr *lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr);
+-
+- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+- retry_tid = lq->agg_ctrl.tid_retry;
+- lq->agg_ctrl.tid_retry = 0;
+- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+-
+- if (retry_tid == TID_ALL_SPECIFIED)
+- iwl4965_turn_on_agg(priv, TID_ALL_SPECIFIED);
+- else {
+- for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++) {
+- tid_msk = (1 << tid);
+- if (retry_tid & tid_msk)
+- iwl4965_turn_on_agg(priv, tid);
+- }
+- }
+-
+- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+- if (lq->agg_ctrl.tid_retry)
+- lq->agg_ctrl.next_retry = jiffies + msecs_to_jiffies(500);
+- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+- return;
+-}
+-
+-/* TODO: move this functionality to rate scaling */
+-void iwl4965_tl_get_stats(struct iwl4965_priv *priv,
+- struct ieee80211_hdr *hdr)
+-{
+- __le16 *qc = ieee80211_get_qos_ctrl(hdr);
+-
+- if (qc &&
+- (priv->iw_mode != IEEE80211_IF_TYPE_IBSS)) {
+- u8 tid = 0;
+- tid = (u8) (le16_to_cpu(*qc) & 0xF);
+- if (tid < TID_MAX_LOAD_COUNT)
+- iwl4965_tl_add_packet(priv, tid);
+- }
+-
+- if (priv->lq_mngr.agg_ctrl.next_retry &&
+- (time_after(priv->lq_mngr.agg_ctrl.next_retry, jiffies))) {
+- unsigned long flags;
+-
+- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
+- priv->lq_mngr.agg_ctrl.next_retry = 0;
+- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
+- schedule_work(&priv->agg_work);
+- }
+-}
+-
+-#endif /*CONFIG_IWL4965_HT_AGG */
+-#endif /* CONFIG_IWL4965_HT */
+-
+ /**
+ * sign_extend - Sign extend a value using specified bit as sign-bit
+ *
+@@ -3316,7 +3245,7 @@ static s32 sign_extend(u32 oper, int index)
+ *
+ * A return of <0 indicates bogus data in the statistics
+ */
+-int iwl4965_get_temperature(const struct iwl4965_priv *priv)
++int iwl4965_get_temperature(const struct iwl_priv *priv)
+ {
+ s32 temperature;
+ s32 vt;
+@@ -3384,7 +3313,7 @@ int iwl4965_get_temperature(const struct iwl4965_priv *priv)
+ * Assumes caller will replace priv->last_temperature once calibration
+ * executed.
+ */
+-static int iwl4965_is_temp_calib_needed(struct iwl4965_priv *priv)
++static int iwl4965_is_temp_calib_needed(struct iwl_priv *priv)
+ {
+ int temp_diff;
+
+@@ -3417,7 +3346,7 @@ static int iwl4965_is_temp_calib_needed(struct iwl4965_priv *priv)
+ /* Calculate noise level, based on measurements during network silence just
+ * before arriving beacon. This measurement can be done only if we know
+ * exactly when to expect beacons, therefore only when we're associated. */
+-static void iwl4965_rx_calc_noise(struct iwl4965_priv *priv)
++static void iwl4965_rx_calc_noise(struct iwl_priv *priv)
+ {
+ struct statistics_rx_non_phy *rx_info
+ = &(priv->statistics.rx.general);
+@@ -3454,7 +3383,7 @@ static void iwl4965_rx_calc_noise(struct iwl4965_priv *priv)
+ priv->last_rx_noise);
+ }
+
+-void iwl4965_hw_rx_statistics(struct iwl4965_priv *priv, struct iwl4965_rx_mem_buffer *rxb)
++void iwl4965_hw_rx_statistics(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb)
+ {
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ int change;
+@@ -3488,6 +3417,8 @@ void iwl4965_hw_rx_statistics(struct iwl4965_priv *priv, struct iwl4965_rx_mem_b
+ #endif
+ }
+
++ iwl_leds_background(priv);
++
+ /* If the hardware hasn't reported a change in
+ * temperature then don't bother computing a
+ * calibrated temperature value */
+@@ -3518,7 +3449,7 @@ void iwl4965_hw_rx_statistics(struct iwl4965_priv *priv, struct iwl4965_rx_mem_b
+ queue_work(priv->workqueue, &priv->txpower_work);
+ }
+
+-static void iwl4965_add_radiotap(struct iwl4965_priv *priv,
++static void iwl4965_add_radiotap(struct iwl_priv *priv,
+ struct sk_buff *skb,
+ struct iwl4965_rx_phy_res *rx_start,
+ struct ieee80211_rx_status *stats,
+@@ -3526,8 +3457,9 @@ static void iwl4965_add_radiotap(struct iwl4965_priv *priv,
+ {
+ s8 signal = stats->ssi;
+ s8 noise = 0;
+- int rate = stats->rate;
++ int rate = stats->rate_idx;
+ u64 tsf = stats->mactime;
++ __le16 antenna;
+ __le16 phy_flags_hw = rx_start->phy_flags;
+ struct iwl4965_rt_rx_hdr {
+ struct ieee80211_radiotap_header rt_hdr;
+@@ -3594,7 +3526,6 @@ static void iwl4965_add_radiotap(struct iwl4965_priv *priv,
+ IEEE80211_CHAN_2GHZ),
+ &iwl4965_rt->rt_chbitmask);
+
+- rate = iwl4965_rate_index_from_plcp(rate);
+ if (rate == -1)
+ iwl4965_rt->rt_rate = 0;
+ else
+@@ -3613,8 +3544,8 @@ static void iwl4965_add_radiotap(struct iwl4965_priv *priv,
+ * new 802.11n radiotap field "RX chains" that is defined
+ * as a bitmask.
+ */
+- iwl4965_rt->rt_antenna =
+- le16_to_cpu(phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
++ antenna = phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK;
++ iwl4965_rt->rt_antenna = le16_to_cpu(antenna) >> 4;
+
+ /* set the preamble flag if appropriate */
+ if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
+@@ -3623,7 +3554,74 @@ static void iwl4965_add_radiotap(struct iwl4965_priv *priv,
+ stats->flag |= RX_FLAG_RADIOTAP;
+ }
+
+-static void iwl4965_handle_data_packet(struct iwl4965_priv *priv, int is_data,
++static void iwl_update_rx_stats(struct iwl_priv *priv, u16 fc, u16 len)
++{
++ /* 0 - mgmt, 1 - cnt, 2 - data */
++ int idx = (fc & IEEE80211_FCTL_FTYPE) >> 2;
++ priv->rx_stats[idx].cnt++;
++ priv->rx_stats[idx].bytes += len;
++}
++
++static u32 iwl4965_translate_rx_status(u32 decrypt_in)
++{
++ u32 decrypt_out = 0;
++
++ if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) ==
++ RX_RES_STATUS_STATION_FOUND)
++ decrypt_out |= (RX_RES_STATUS_STATION_FOUND |
++ RX_RES_STATUS_NO_STATION_INFO_MISMATCH);
++
++ decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK);
++
++ /* packet was not encrypted */
++ if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
++ RX_RES_STATUS_SEC_TYPE_NONE)
++ return decrypt_out;
++
++ /* packet was encrypted with unknown alg */
++ if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
++ RX_RES_STATUS_SEC_TYPE_ERR)
++ return decrypt_out;
++
++ /* decryption was not done in HW */
++ if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) !=
++ RX_MPDU_RES_STATUS_DEC_DONE_MSK)
++ return decrypt_out;
++
++ switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) {
++
++ case RX_RES_STATUS_SEC_TYPE_CCMP:
++ /* alg is CCM: check MIC only */
++ if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK))
++ /* Bad MIC */
++ decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
++ else
++ decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
++
++ break;
++
++ case RX_RES_STATUS_SEC_TYPE_TKIP:
++ if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) {
++ /* Bad TTAK */
++ decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK;
++ break;
++ }
++ /* fall through if TTAK OK */
++ default:
++ if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK))
++ decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
++ else
++ decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
++ break;
++ };
++
++ IWL_DEBUG_RX("decrypt_in:0x%x decrypt_out = 0x%x\n",
++ decrypt_in, decrypt_out);
++
++ return decrypt_out;
++}
++
++static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data,
+ int include_phy,
+ struct iwl4965_rx_mem_buffer *rxb,
+ struct ieee80211_rx_status *stats)
+@@ -3636,6 +3634,7 @@ static void iwl4965_handle_data_packet(struct iwl4965_priv *priv, int is_data,
+ __le32 *rx_end;
+ unsigned int skblen;
+ u32 ampdu_status;
++ u32 ampdu_status_legacy;
+
+ if (!include_phy && priv->last_phy_res[0])
+ rx_start = (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1];
+@@ -3664,7 +3663,7 @@ static void iwl4965_handle_data_packet(struct iwl4965_priv *priv, int is_data,
+ rx_start->byte_count = amsdu->byte_count;
+ rx_end = (__le32 *) (((u8 *) hdr) + len);
+ }
+- if (len > priv->hw_setting.max_pkt_size || len < 16) {
++ if (len > priv->hw_params.max_pkt_size || len < 16) {
+ IWL_WARNING("byte count out of range [16,4K] : %d\n", len);
+ return;
+ }
+@@ -3672,6 +3671,12 @@ static void iwl4965_handle_data_packet(struct iwl4965_priv *priv, int is_data,
+ ampdu_status = le32_to_cpu(*rx_end);
+ skblen = ((u8 *) rx_end - (u8 *) & pkt->u.raw[0]) + sizeof(u32);
+
++ if (!include_phy) {
++ /* New status scheme, need to translate */
++ ampdu_status_legacy = ampdu_status;
++ ampdu_status = iwl4965_translate_rx_status(ampdu_status);
++ }
++
+ /* start from MAC */
+ skb_reserve(rxb->skb, (void *)hdr - (void *)pkt);
+ skb_put(rxb->skb, len); /* end where data ends */
+@@ -3686,19 +3691,16 @@ static void iwl4965_handle_data_packet(struct iwl4965_priv *priv, int is_data,
+ stats->flag = 0;
+ hdr = (struct ieee80211_hdr *)rxb->skb->data;
+
+- if (iwl4965_param_hwcrypto)
++ if (!priv->cfg->mod_params->sw_crypto)
+ iwl4965_set_decrypted_flag(priv, rxb->skb, ampdu_status, stats);
+
+ if (priv->add_radiotap)
+ iwl4965_add_radiotap(priv, rxb->skb, rx_start, stats, ampdu_status);
+
++ iwl_update_rx_stats(priv, le16_to_cpu(hdr->frame_control), len);
+ ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats);
+ priv->alloc_rxb_skb--;
+ rxb->skb = NULL;
+-#ifdef LED
+- priv->led_packets += len;
+- iwl4965_setup_activity_timer(priv);
+-#endif
+ }
+
+ /* Calc max signal level (dBm) among 3 possible receivers */
+@@ -3737,85 +3739,16 @@ static int iwl4965_calc_rssi(struct iwl4965_rx_phy_res *rx_resp)
+
+ #ifdef CONFIG_IWL4965_HT
+
+-/* Parsed Information Elements */
+-struct ieee802_11_elems {
+- u8 *ds_params;
+- u8 ds_params_len;
+- u8 *tim;
+- u8 tim_len;
+- u8 *ibss_params;
+- u8 ibss_params_len;
+- u8 *erp_info;
+- u8 erp_info_len;
+- u8 *ht_cap_param;
+- u8 ht_cap_param_len;
+- u8 *ht_extra_param;
+- u8 ht_extra_param_len;
+-};
+-
+-static int parse_elems(u8 *start, size_t len, struct ieee802_11_elems *elems)
+-{
+- size_t left = len;
+- u8 *pos = start;
+- int unknown = 0;
+-
+- memset(elems, 0, sizeof(*elems));
+-
+- while (left >= 2) {
+- u8 id, elen;
+-
+- id = *pos++;
+- elen = *pos++;
+- left -= 2;
+-
+- if (elen > left)
+- return -1;
+-
+- switch (id) {
+- case WLAN_EID_DS_PARAMS:
+- elems->ds_params = pos;
+- elems->ds_params_len = elen;
+- break;
+- case WLAN_EID_TIM:
+- elems->tim = pos;
+- elems->tim_len = elen;
+- break;
+- case WLAN_EID_IBSS_PARAMS:
+- elems->ibss_params = pos;
+- elems->ibss_params_len = elen;
+- break;
+- case WLAN_EID_ERP_INFO:
+- elems->erp_info = pos;
+- elems->erp_info_len = elen;
+- break;
+- case WLAN_EID_HT_CAPABILITY:
+- elems->ht_cap_param = pos;
+- elems->ht_cap_param_len = elen;
+- break;
+- case WLAN_EID_HT_EXTRA_INFO:
+- elems->ht_extra_param = pos;
+- elems->ht_extra_param_len = elen;
+- break;
+- default:
+- unknown++;
+- break;
+- }
+-
+- left -= elen;
+- pos += elen;
+- }
+-
+- return 0;
+-}
+-
+-void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, int mode)
++void iwl4965_init_ht_hw_capab(struct iwl_priv *priv,
++ struct ieee80211_ht_info *ht_info,
++ enum ieee80211_band band)
+ {
+ ht_info->cap = 0;
+ memset(ht_info->supp_mcs_set, 0, 16);
+
+ ht_info->ht_supported = 1;
+
+- if (mode == MODE_IEEE80211A) {
++ if (band == IEEE80211_BAND_5GHZ) {
+ ht_info->cap |= (u16)IEEE80211_HT_CAP_SUP_WIDTH;
+ ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_40;
+ ht_info->supp_mcs_set[4] = 0x01;
+@@ -3824,10 +3757,9 @@ void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, int mode)
+ ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_20;
+ ht_info->cap |= (u16)(IEEE80211_HT_CAP_MIMO_PS &
+ (IWL_MIMO_PS_NONE << 2));
+- if (iwl4965_param_amsdu_size_8K) {
+- printk(KERN_DEBUG "iwl4965 in A-MSDU 8K support mode\n");
++
++ if (priv->cfg->mod_params->amsdu_size_8K)
+ ht_info->cap |= (u16)IEEE80211_HT_CAP_MAX_AMSDU;
+- }
+
+ ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
+ ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF;
+@@ -3837,7 +3769,7 @@ void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, int mode)
+ }
+ #endif /* CONFIG_IWL4965_HT */
+
+-static void iwl4965_sta_modify_ps_wake(struct iwl4965_priv *priv, int sta_id)
++static void iwl4965_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
+ {
+ unsigned long flags;
+
+@@ -3851,7 +3783,7 @@ static void iwl4965_sta_modify_ps_wake(struct iwl4965_priv *priv, int sta_id)
+ iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+ }
+
+-static void iwl4965_update_ps_mode(struct iwl4965_priv *priv, u16 ps_bit, u8 *addr)
++static void iwl4965_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr)
+ {
+ /* FIXME: need locking over ps_status ??? */
+ u8 sta_id = iwl4965_hw_find_station(priv, addr);
+@@ -3868,44 +3800,201 @@ static void iwl4965_update_ps_mode(struct iwl4965_priv *priv, u16 ps_bit, u8 *ad
+ }
+ }
+ }
++#ifdef CONFIG_IWLWIFI_DEBUG
+
+-#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
++/**
++ * iwl4965_dbg_report_frame - dump frame to syslog during debug sessions
++ *
++ * You may hack this function to show different aspects of received frames,
++ * including selective frame dumps.
++ * group100 parameter selects whether to show 1 out of 100 good frames.
++ *
++ * TODO: This was originally written for 3945, need to audit for
++ * proper operation with 4965.
++ */
++static void iwl4965_dbg_report_frame(struct iwl_priv *priv,
++ struct iwl4965_rx_packet *pkt,
++ struct ieee80211_hdr *header, int group100)
++{
++ u32 to_us;
++ u32 print_summary = 0;
++ u32 print_dump = 0; /* set to 1 to dump all frames' contents */
++ u32 hundred = 0;
++ u32 dataframe = 0;
++ u16 fc;
++ u16 seq_ctl;
++ u16 channel;
++ u16 phy_flags;
++ int rate_sym;
++ u16 length;
++ u16 status;
++ u16 bcn_tmr;
++ u32 tsf_low;
++ u64 tsf;
++ u8 rssi;
++ u8 agc;
++ u16 sig_avg;
++ u16 noise_diff;
++ struct iwl4965_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
++ struct iwl4965_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
++ struct iwl4965_rx_frame_end *rx_end = IWL_RX_END(pkt);
++ u8 *data = IWL_RX_DATA(pkt);
++
++ if (likely(!(iwl_debug_level & IWL_DL_RX)))
++ return;
+
+-/* Called for REPLY_4965_RX (legacy ABG frames), or
++ /* MAC header */
++ fc = le16_to_cpu(header->frame_control);
++ seq_ctl = le16_to_cpu(header->seq_ctrl);
++
++ /* metadata */
++ channel = le16_to_cpu(rx_hdr->channel);
++ phy_flags = le16_to_cpu(rx_hdr->phy_flags);
++ rate_sym = rx_hdr->rate;
++ length = le16_to_cpu(rx_hdr->len);
++
++ /* end-of-frame status and timestamp */
++ status = le32_to_cpu(rx_end->status);
++ bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp);
++ tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff;
++ tsf = le64_to_cpu(rx_end->timestamp);
++
++ /* signal statistics */
++ rssi = rx_stats->rssi;
++ agc = rx_stats->agc;
++ sig_avg = le16_to_cpu(rx_stats->sig_avg);
++ noise_diff = le16_to_cpu(rx_stats->noise_diff);
++
++ to_us = !compare_ether_addr(header->addr1, priv->mac_addr);
++
++ /* if data frame is to us and all is good,
++ * (optionally) print summary for only 1 out of every 100 */
++ if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) ==
++ (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) {
++ dataframe = 1;
++ if (!group100)
++ print_summary = 1; /* print each frame */
++ else if (priv->framecnt_to_us < 100) {
++ priv->framecnt_to_us++;
++ print_summary = 0;
++ } else {
++ priv->framecnt_to_us = 0;
++ print_summary = 1;
++ hundred = 1;
++ }
++ } else {
++ /* print summary for all other frames */
++ print_summary = 1;
++ }
++
++ if (print_summary) {
++ char *title;
++ int rate_idx;
++ u32 bitrate;
++
++ if (hundred)
++ title = "100Frames";
++ else if (fc & IEEE80211_FCTL_RETRY)
++ title = "Retry";
++ else if (ieee80211_is_assoc_response(fc))
++ title = "AscRsp";
++ else if (ieee80211_is_reassoc_response(fc))
++ title = "RasRsp";
++ else if (ieee80211_is_probe_response(fc)) {
++ title = "PrbRsp";
++ print_dump = 1; /* dump frame contents */
++ } else if (ieee80211_is_beacon(fc)) {
++ title = "Beacon";
++ print_dump = 1; /* dump frame contents */
++ } else if (ieee80211_is_atim(fc))
++ title = "ATIM";
++ else if (ieee80211_is_auth(fc))
++ title = "Auth";
++ else if (ieee80211_is_deauth(fc))
++ title = "DeAuth";
++ else if (ieee80211_is_disassoc(fc))
++ title = "DisAssoc";
++ else
++ title = "Frame";
++
++ rate_idx = iwl4965_hwrate_to_plcp_idx(rate_sym);
++ if (unlikely(rate_idx == -1))
++ bitrate = 0;
++ else
++ bitrate = iwl4965_rates[rate_idx].ieee / 2;
++
++ /* print frame summary.
++ * MAC addresses show just the last byte (for brevity),
++ * but you can hack it to show more, if you'd like to. */
++ if (dataframe)
++ IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, "
++ "len=%u, rssi=%d, chnl=%d, rate=%u, \n",
++ title, fc, header->addr1[5],
++ length, rssi, channel, bitrate);
++ else {
++ /* src/dst addresses assume managed mode */
++ IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, "
++ "src=0x%02x, rssi=%u, tim=%lu usec, "
++ "phy=0x%02x, chnl=%d\n",
++ title, fc, header->addr1[5],
++ header->addr3[5], rssi,
++ tsf_low - priv->scan_start_tsf,
++ phy_flags, channel);
++ }
++ }
++ if (print_dump)
++ iwl_print_hex_dump(IWL_DL_RX, data, length);
++}
++#else
++static inline void iwl4965_dbg_report_frame(struct iwl_priv *priv,
++ struct iwl4965_rx_packet *pkt,
++ struct ieee80211_hdr *header,
++ int group100)
++{
++}
++#endif
++
++
++
++/* Called for REPLY_RX (legacy ABG frames), or
+ * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
+-static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
++static void iwl4965_rx_reply_rx(struct iwl_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
+ {
++ struct ieee80211_hdr *header;
++ struct ieee80211_rx_status rx_status;
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ /* Use phy data (Rx signal strength, etc.) contained within
+ * this rx packet for legacy frames,
+ * or phy data cached from REPLY_RX_PHY_CMD for HT frames. */
+- int include_phy = (pkt->hdr.cmd == REPLY_4965_RX);
++ int include_phy = (pkt->hdr.cmd == REPLY_RX);
+ struct iwl4965_rx_phy_res *rx_start = (include_phy) ?
+ (struct iwl4965_rx_phy_res *)&(pkt->u.raw[0]) :
+ (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1];
+ __le32 *rx_end;
+ unsigned int len = 0;
+- struct ieee80211_hdr *header;
+ u16 fc;
+- struct ieee80211_rx_status stats = {
+- .mactime = le64_to_cpu(rx_start->timestamp),
+- .channel = le16_to_cpu(rx_start->channel),
+- .phymode =
+- (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
+- MODE_IEEE80211G : MODE_IEEE80211A,
+- .antenna = 0,
+- .rate = iwl4965_hw_get_rate(rx_start->rate_n_flags),
+- .flag = 0,
+- };
+ u8 network_packet;
+
++ rx_status.mactime = le64_to_cpu(rx_start->timestamp);
++ rx_status.freq =
++ ieee80211_frequency_to_channel(le16_to_cpu(rx_start->channel));
++ rx_status.band = (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
++ IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
++ rx_status.rate_idx =
++ iwl4965_hwrate_to_plcp_idx(le32_to_cpu(rx_start->rate_n_flags));
++ if (rx_status.band == IEEE80211_BAND_5GHZ)
++ rx_status.rate_idx -= IWL_FIRST_OFDM_RATE;
++
++ rx_status.antenna = 0;
++ rx_status.flag = 0;
++
+ if ((unlikely(rx_start->cfg_phy_cnt > 20))) {
+- IWL_DEBUG_DROP
+- ("dsp size out of range [0,20]: "
+- "%d/n", rx_start->cfg_phy_cnt);
++ IWL_DEBUG_DROP("dsp size out of range [0,20]: %d/n",
++ rx_start->cfg_phy_cnt);
+ return;
+ }
++
+ if (!include_phy) {
+ if (priv->last_phy_res[0])
+ rx_start = (struct iwl4965_rx_phy_res *)
+@@ -3924,7 +4013,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
+ + rx_start->cfg_phy_cnt);
+
+ len = le16_to_cpu(rx_start->byte_count);
+- rx_end = (__le32 *) (pkt->u.raw + rx_start->cfg_phy_cnt +
++ rx_end = (__le32 *)(pkt->u.raw + rx_start->cfg_phy_cnt +
+ sizeof(struct iwl4965_rx_phy_res) + len);
+ } else {
+ struct iwl4965_rx_mpdu_res_start *amsdu =
+@@ -3946,43 +4035,38 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
+
+ priv->ucode_beacon_time = le32_to_cpu(rx_start->beacon_time_stamp);
+
+- stats.freq = ieee80211chan2mhz(stats.channel);
+-
+ /* Find max signal strength (dBm) among 3 antenna/receiver chains */
+- stats.ssi = iwl4965_calc_rssi(rx_start);
++ rx_status.ssi = iwl4965_calc_rssi(rx_start);
+
+ /* Meaningful noise values are available only from beacon statistics,
+ * which are gathered only when associated, and indicate noise
+ * only for the associated network channel ...
+ * Ignore these noise values while scanning (other channels) */
+- if (iwl4965_is_associated(priv) &&
++ if (iwl_is_associated(priv) &&
+ !test_bit(STATUS_SCANNING, &priv->status)) {
+- stats.noise = priv->last_rx_noise;
+- stats.signal = iwl4965_calc_sig_qual(stats.ssi, stats.noise);
++ rx_status.noise = priv->last_rx_noise;
++ rx_status.signal = iwl4965_calc_sig_qual(rx_status.ssi,
++ rx_status.noise);
+ } else {
+- stats.noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
+- stats.signal = iwl4965_calc_sig_qual(stats.ssi, 0);
++ rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
++ rx_status.signal = iwl4965_calc_sig_qual(rx_status.ssi, 0);
+ }
+
+ /* Reset beacon noise level if not associated. */
+- if (!iwl4965_is_associated(priv))
++ if (!iwl_is_associated(priv))
+ priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
+
+-#ifdef CONFIG_IWL4965_DEBUG
+- /* TODO: Parts of iwl4965_report_frame are broken for 4965 */
+- if (iwl4965_debug_level & (IWL_DL_RX))
+- /* Set "1" to report good data frames in groups of 100 */
+- iwl4965_report_frame(priv, pkt, header, 1);
++ /* Set "1" to report good data frames in groups of 100 */
++ /* FIXME: need to optimze the call: */
++ iwl4965_dbg_report_frame(priv, pkt, header, 1);
+
+- if (iwl4965_debug_level & (IWL_DL_RX | IWL_DL_STATS))
+- IWL_DEBUG_RX("Rssi %d, noise %d, qual %d, TSF %lu\n",
+- stats.ssi, stats.noise, stats.signal,
+- (long unsigned int)le64_to_cpu(rx_start->timestamp));
+-#endif
++ IWL_DEBUG_STATS_LIMIT("Rssi %d, noise %d, qual %d, TSF %llu\n",
++ rx_status.ssi, rx_status.noise, rx_status.signal,
++ (unsigned long long)rx_status.mactime);
+
+ network_packet = iwl4965_is_network_packet(priv, header);
+ if (network_packet) {
+- priv->last_rx_rssi = stats.ssi;
++ priv->last_rx_rssi = rx_status.ssi;
+ priv->last_beacon_time = priv->ucode_beacon_time;
+ priv->last_tsf = le64_to_cpu(rx_start->timestamp);
+ }
+@@ -3990,102 +4074,10 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
+ fc = le16_to_cpu(header->frame_control);
+ switch (fc & IEEE80211_FCTL_FTYPE) {
+ case IEEE80211_FTYPE_MGMT:
+-
+ if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
+ iwl4965_update_ps_mode(priv, fc & IEEE80211_FCTL_PM,
+ header->addr2);
+- switch (fc & IEEE80211_FCTL_STYPE) {
+- case IEEE80211_STYPE_PROBE_RESP:
+- case IEEE80211_STYPE_BEACON:
+- if ((priv->iw_mode == IEEE80211_IF_TYPE_STA &&
+- !compare_ether_addr(header->addr2, priv->bssid)) ||
+- (priv->iw_mode == IEEE80211_IF_TYPE_IBSS &&
+- !compare_ether_addr(header->addr3, priv->bssid))) {
+- struct ieee80211_mgmt *mgmt =
+- (struct ieee80211_mgmt *)header;
+- u64 timestamp =
+- le64_to_cpu(mgmt->u.beacon.timestamp);
+-
+- priv->timestamp0 = timestamp & 0xFFFFFFFF;
+- priv->timestamp1 =
+- (timestamp >> 32) & 0xFFFFFFFF;
+- priv->beacon_int = le16_to_cpu(
+- mgmt->u.beacon.beacon_int);
+- if (priv->call_post_assoc_from_beacon &&
+- (priv->iw_mode == IEEE80211_IF_TYPE_STA)) {
+- priv->call_post_assoc_from_beacon = 0;
+- queue_work(priv->workqueue,
+- &priv->post_associate.work);
+- }
+- }
+- break;
+-
+- case IEEE80211_STYPE_ACTION:
+- break;
+-
+- /*
+- * TODO: Use the new callback function from
+- * mac80211 instead of sniffing these packets.
+- */
+- case IEEE80211_STYPE_ASSOC_RESP:
+- case IEEE80211_STYPE_REASSOC_RESP:
+- if (network_packet) {
+-#ifdef CONFIG_IWL4965_HT
+- u8 *pos = NULL;
+- struct ieee802_11_elems elems;
+-#endif /*CONFIG_IWL4965_HT */
+- struct ieee80211_mgmt *mgnt =
+- (struct ieee80211_mgmt *)header;
+-
+- /* We have just associated, give some
+- * time for the 4-way handshake if
+- * any. Don't start scan too early. */
+- priv->next_scan_jiffies = jiffies +
+- IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
+-
+- priv->assoc_id = (~((1 << 15) | (1 << 14))
+- & le16_to_cpu(mgnt->u.assoc_resp.aid));
+- priv->assoc_capability =
+- le16_to_cpu(
+- mgnt->u.assoc_resp.capab_info);
+-#ifdef CONFIG_IWL4965_HT
+- pos = mgnt->u.assoc_resp.variable;
+- if (!parse_elems(pos,
+- len - (pos - (u8 *) mgnt),
+- &elems)) {
+- if (elems.ht_extra_param &&
+- elems.ht_cap_param)
+- break;
+- }
+-#endif /*CONFIG_IWL4965_HT */
+- /* assoc_id is 0 no association */
+- if (!priv->assoc_id)
+- break;
+- if (priv->beacon_int)
+- queue_work(priv->workqueue,
+- &priv->post_associate.work);
+- else
+- priv->call_post_assoc_from_beacon = 1;
+- }
+-
+- break;
+-
+- case IEEE80211_STYPE_PROBE_REQ:
+- if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
+- !iwl4965_is_associated(priv)) {
+- DECLARE_MAC_BUF(mac1);
+- DECLARE_MAC_BUF(mac2);
+- DECLARE_MAC_BUF(mac3);
+-
+- IWL_DEBUG_DROP("Dropping (non network): "
+- "%s, %s, %s\n",
+- print_mac(mac1, header->addr1),
+- print_mac(mac2, header->addr2),
+- print_mac(mac3, header->addr3));
+- return;
+- }
+- }
+- iwl4965_handle_data_packet(priv, 0, include_phy, rxb, &stats);
++ iwl4965_handle_data_packet(priv, 0, include_phy, rxb, &rx_status);
+ break;
+
+ case IEEE80211_FTYPE_CTL:
+@@ -4094,7 +4086,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
+ case IEEE80211_STYPE_BACK_REQ:
+ IWL_DEBUG_HT("IEEE80211_STYPE_BACK_REQ arrived\n");
+ iwl4965_handle_data_packet(priv, 0, include_phy,
+- rxb, &stats);
++ rxb, &rx_status);
+ break;
+ default:
+ break;
+@@ -4124,7 +4116,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
+ print_mac(mac3, header->addr3));
+ else
+ iwl4965_handle_data_packet(priv, 1, include_phy, rxb,
+- &stats);
++ &rx_status);
+ break;
+ }
+ default:
+@@ -4135,7 +4127,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
+
+ /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
+ * This will be used later in iwl4965_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
+-static void iwl4965_rx_reply_rx_phy(struct iwl4965_priv *priv,
++static void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
+ {
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+@@ -4143,8 +4135,7 @@ static void iwl4965_rx_reply_rx_phy(struct iwl4965_priv *priv,
+ memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]),
+ sizeof(struct iwl4965_rx_phy_res));
+ }
+-
+-static void iwl4965_rx_missed_beacon_notif(struct iwl4965_priv *priv,
++static void iwl4965_rx_missed_beacon_notif(struct iwl_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
+
+ {
+@@ -4165,31 +4156,12 @@ static void iwl4965_rx_missed_beacon_notif(struct iwl4965_priv *priv,
+ }
+ #endif /*CONFIG_IWL4965_SENSITIVITY*/
+ }
+-
+ #ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
+-
+-/**
+- * iwl4965_set_tx_status - Update driver's record of one Tx frame's status
+- *
+- * This will get sent to mac80211.
+- */
+-static void iwl4965_set_tx_status(struct iwl4965_priv *priv, int txq_id, int idx,
+- u32 status, u32 retry_count, u32 rate)
+-{
+- struct ieee80211_tx_status *tx_status =
+- &(priv->txq[txq_id].txb[idx].status);
+-
+- tx_status->flags = status ? IEEE80211_TX_STATUS_ACK : 0;
+- tx_status->retry_count += retry_count;
+- tx_status->control.tx_rate = rate;
+-}
+-
+
+ /**
+ * iwl4965_sta_modify_enable_tid_tx - Enable Tx for this TID in station table
+ */
+-static void iwl4965_sta_modify_enable_tid_tx(struct iwl4965_priv *priv,
++static void iwl4965_sta_modify_enable_tid_tx(struct iwl_priv *priv,
+ int sta_id, int tid)
+ {
+ unsigned long flags;
+@@ -4204,24 +4176,24 @@ static void iwl4965_sta_modify_enable_tid_tx(struct iwl4965_priv *priv,
+ iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+ }
+
+-
+ /**
+ * iwl4965_tx_status_reply_compressed_ba - Update tx status from block-ack
+ *
+ * Go through block-ack's bitmap of ACK'd frames, update driver's record of
+ * ACK vs. not. This gets sent to mac80211, then to rate scaling algo.
+ */
+-static int iwl4965_tx_status_reply_compressed_ba(struct iwl4965_priv *priv,
++static int iwl4965_tx_status_reply_compressed_ba(struct iwl_priv *priv,
+ struct iwl4965_ht_agg *agg,
+ struct iwl4965_compressed_ba_resp*
+ ba_resp)
+
+ {
+ int i, sh, ack;
+- u16 ba_seq_ctl = le16_to_cpu(ba_resp->ba_seq_ctl);
+- u32 bitmap0, bitmap1;
+- u32 resp_bitmap0 = le32_to_cpu(ba_resp->ba_bitmap0);
+- u32 resp_bitmap1 = le32_to_cpu(ba_resp->ba_bitmap1);
++ u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl);
++ u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
++ u64 bitmap;
++ int successes = 0;
++ struct ieee80211_tx_status *tx_status;
+
+ if (unlikely(!agg->wait_for_ba)) {
+ IWL_ERROR("Received BA when not expected\n");
+@@ -4230,17 +4202,15 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl4965_priv *priv,
+
+ /* Mark that the expected block-ack response arrived */
+ agg->wait_for_ba = 0;
+- IWL_DEBUG_TX_REPLY("BA %d %d\n", agg->start_idx, ba_resp->ba_seq_ctl);
++ IWL_DEBUG_TX_REPLY("BA %d %d\n", agg->start_idx, ba_resp->seq_ctl);
+
+ /* Calculate shift to align block-ack bits with our Tx window bits */
+- sh = agg->start_idx - SEQ_TO_INDEX(ba_seq_ctl >> 4);
++ sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl>>4);
+ if (sh < 0) /* tbw something is wrong with indices */
+ sh += 0x100;
+
+ /* don't use 64-bit values for now */
+- bitmap0 = resp_bitmap0 >> sh;
+- bitmap1 = resp_bitmap1 >> sh;
+- bitmap0 |= (resp_bitmap1 & ((1 << sh) | ((1 << sh) - 1))) << (32 - sh);
++ bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
+
+ if (agg->frame_count > (64 - sh)) {
+ IWL_DEBUG_TX_REPLY("more frames than bitmap size");
+@@ -4249,23 +4219,113 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl4965_priv *priv,
+
+ /* check for success or failure according to the
+ * transmitted bitmap and block-ack bitmap */
+- bitmap0 &= agg->bitmap0;
+- bitmap1 &= agg->bitmap1;
++ bitmap &= agg->bitmap;
+
+ /* For each frame attempted in aggregation,
+ * update driver's record of tx frame's status. */
+ for (i = 0; i < agg->frame_count ; i++) {
+- int idx = (agg->start_idx + i) & 0xff;
+- ack = bitmap0 & (1 << i);
++ ack = bitmap & (1 << i);
++ successes += !!ack;
+ IWL_DEBUG_TX_REPLY("%s ON i=%d idx=%d raw=%d\n",
+- ack? "ACK":"NACK", i, idx, agg->start_idx + i);
+- iwl4965_set_tx_status(priv, agg->txq_id, idx, ack, 0,
+- agg->rate_n_flags);
++ ack? "ACK":"NACK", i, (agg->start_idx + i) & 0xff,
++ agg->start_idx + i);
++ }
++
++ tx_status = &priv->txq[scd_flow].txb[agg->start_idx].status;
++ tx_status->flags = IEEE80211_TX_STATUS_ACK;
++ tx_status->flags |= IEEE80211_TX_STATUS_AMPDU;
++ tx_status->ampdu_ack_map = successes;
++ tx_status->ampdu_ack_len = agg->frame_count;
++ iwl4965_hwrate_to_tx_control(priv, agg->rate_n_flags,
++ &tx_status->control);
++
++ IWL_DEBUG_TX_REPLY("Bitmap %llx\n", (unsigned long long)bitmap);
+
++ return 0;
++}
++
++/**
++ * iwl4965_tx_queue_stop_scheduler - Stop queue, but keep configuration
++ */
++static void iwl4965_tx_queue_stop_scheduler(struct iwl_priv *priv,
++ u16 txq_id)
++{
++ /* Simply stop the queue, but don't change any configuration;
++ * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
++ iwl_write_prph(priv,
++ IWL49_SCD_QUEUE_STATUS_BITS(txq_id),
++ (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)|
++ (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
++}
++
++/**
++ * txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID
++ * priv->lock must be held by the caller
++ */
++static int iwl4965_tx_queue_agg_disable(struct iwl_priv *priv, u16 txq_id,
++ u16 ssn_idx, u8 tx_fifo)
++{
++ int ret = 0;
++
++ if (IWL_BACK_QUEUE_FIRST_ID > txq_id) {
++ IWL_WARNING("queue number too small: %d, must be > %d\n",
++ txq_id, IWL_BACK_QUEUE_FIRST_ID);
++ return -EINVAL;
+ }
+
+- IWL_DEBUG_TX_REPLY("Bitmap %x%x\n", bitmap0, bitmap1);
++ ret = iwl_grab_nic_access(priv);
++ if (ret)
++ return ret;
++
++ iwl4965_tx_queue_stop_scheduler(priv, txq_id);
+
++ iwl_clear_bits_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
++
++ priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
++ priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
++ /* supposes that ssn_idx is valid (!= 0xFFF) */
++ iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx);
++
++ iwl_clear_bits_prph(priv, IWL49_SCD_INTERRUPT_MASK, (1 << txq_id));
++ iwl4965_txq_ctx_deactivate(priv, txq_id);
++ iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0);
++
++ iwl_release_nic_access(priv);
++
++ return 0;
++}
++
++int iwl4965_check_empty_hw_queue(struct iwl_priv *priv, int sta_id,
++ u8 tid, int txq_id)
++{
++ struct iwl4965_queue *q = &priv->txq[txq_id].q;
++ u8 *addr = priv->stations[sta_id].sta.sta.addr;
++ struct iwl4965_tid_data *tid_data = &priv->stations[sta_id].tid[tid];
++
++ switch (priv->stations[sta_id].tid[tid].agg.state) {
++ case IWL_EMPTYING_HW_QUEUE_DELBA:
++ /* We are reclaiming the last packet of the */
++ /* aggregated HW queue */
++ if (txq_id == tid_data->agg.txq_id &&
++ q->read_ptr == q->write_ptr) {
++ u16 ssn = SEQ_TO_SN(tid_data->seq_number);
++ int tx_fifo = default_tid_to_tx_fifo[tid];
++ IWL_DEBUG_HT("HW queue empty: continue DELBA flow\n");
++ iwl4965_tx_queue_agg_disable(priv, txq_id,
++ ssn, tx_fifo);
++ tid_data->agg.state = IWL_AGG_OFF;
++ ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, addr, tid);
++ }
++ break;
++ case IWL_EMPTYING_HW_QUEUE_ADDBA:
++ /* We are reclaiming the last packet of the queue */
++ if (tid_data->tfds_in_queue == 0) {
++ IWL_DEBUG_HT("HW queue empty: continue ADDBA flow\n");
++ tid_data->agg.state = IWL_AGG_ON;
++ ieee80211_start_tx_ba_cb_irqsafe(priv->hw, addr, tid);
++ }
++ break;
++ }
+ return 0;
+ }
+
+@@ -4285,7 +4345,7 @@ static inline int iwl4965_queue_dec_wrap(int index, int n_bd)
+ * Handles block-acknowledge notification from device, which reports success
+ * of frames sent via aggregation.
+ */
+-static void iwl4965_rx_reply_compressed_ba(struct iwl4965_priv *priv,
++static void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
+ {
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+@@ -4293,48 +4353,43 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl4965_priv *priv,
+ int index;
+ struct iwl4965_tx_queue *txq = NULL;
+ struct iwl4965_ht_agg *agg;
++ DECLARE_MAC_BUF(mac);
+
+ /* "flow" corresponds to Tx queue */
+- u16 ba_resp_scd_flow = le16_to_cpu(ba_resp->scd_flow);
++ u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
+
+ /* "ssn" is start of block-ack Tx window, corresponds to index
+ * (in Tx queue's circular buffer) of first TFD/frame in window */
+ u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
+
+- if (ba_resp_scd_flow >= ARRAY_SIZE(priv->txq)) {
++ if (scd_flow >= priv->hw_params.max_txq_num) {
+ IWL_ERROR("BUG_ON scd_flow is bigger than number of queues");
+ return;
+ }
+
+- txq = &priv->txq[ba_resp_scd_flow];
++ txq = &priv->txq[scd_flow];
+ agg = &priv->stations[ba_resp->sta_id].tid[ba_resp->tid].agg;
+
+ /* Find index just before block-ack window */
+ index = iwl4965_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
+
+ /* TODO: Need to get this copy more safely - now good for debug */
+-/*
+- {
+- DECLARE_MAC_BUF(mac);
++
+ IWL_DEBUG_TX_REPLY("REPLY_COMPRESSED_BA [%d]Received from %s, "
+ "sta_id = %d\n",
+ agg->wait_for_ba,
+ print_mac(mac, (u8*) &ba_resp->sta_addr_lo32),
+ ba_resp->sta_id);
+- IWL_DEBUG_TX_REPLY("TID = %d, SeqCtl = %d, bitmap = 0x%X%X, scd_flow = "
++ IWL_DEBUG_TX_REPLY("TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = "
+ "%d, scd_ssn = %d\n",
+ ba_resp->tid,
+- ba_resp->ba_seq_ctl,
+- ba_resp->ba_bitmap1,
+- ba_resp->ba_bitmap0,
++ ba_resp->seq_ctl,
++ (unsigned long long)le64_to_cpu(ba_resp->bitmap),
+ ba_resp->scd_flow,
+ ba_resp->scd_ssn);
+- IWL_DEBUG_TX_REPLY("DAT start_idx = %d, bitmap = 0x%X%X \n",
++ IWL_DEBUG_TX_REPLY("DAT start_idx = %d, bitmap = 0x%llx \n",
+ agg->start_idx,
+- agg->bitmap1,
+- agg->bitmap0);
+- }
+-*/
++ (unsigned long long)agg->bitmap);
+
+ /* Update driver's record of ACK vs. not for each frame in window */
+ iwl4965_tx_status_reply_compressed_ba(priv, agg, ba_resp);
+@@ -4342,29 +4397,23 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl4965_priv *priv,
+ /* Release all TFDs before the SSN, i.e. all TFDs in front of
+ * block-ack window (we assume that they've been successfully
+ * transmitted ... if not, it's too late anyway). */
+- if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff))
+- iwl4965_tx_queue_reclaim(priv, ba_resp_scd_flow, index);
+-
+-}
+-
+-
+-/**
+- * iwl4965_tx_queue_stop_scheduler - Stop queue, but keep configuration
+- */
+-static void iwl4965_tx_queue_stop_scheduler(struct iwl4965_priv *priv, u16 txq_id)
+-{
+- /* Simply stop the queue, but don't change any configuration;
+- * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
+- iwl4965_write_prph(priv,
+- KDR_SCD_QUEUE_STATUS_BITS(txq_id),
+- (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)|
+- (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
++ if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) {
++ int freed = iwl4965_tx_queue_reclaim(priv, scd_flow, index);
++ priv->stations[ba_resp->sta_id].
++ tid[ba_resp->tid].tfds_in_queue -= freed;
++ if (iwl4965_queue_space(&txq->q) > txq->q.low_mark &&
++ priv->mac80211_registered &&
++ agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)
++ ieee80211_wake_queue(priv->hw, scd_flow);
++ iwl4965_check_empty_hw_queue(priv, ba_resp->sta_id,
++ ba_resp->tid, scd_flow);
++ }
+ }
+
+ /**
+ * iwl4965_tx_queue_set_q2ratid - Map unique receiver/tid combination to a queue
+ */
+-static int iwl4965_tx_queue_set_q2ratid(struct iwl4965_priv *priv, u16 ra_tid,
++static int iwl4965_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid,
+ u16 txq_id)
+ {
+ u32 tbl_dw_addr;
+@@ -4376,25 +4425,26 @@ static int iwl4965_tx_queue_set_q2ratid(struct iwl4965_priv *priv, u16 ra_tid,
+ tbl_dw_addr = priv->scd_base_addr +
+ SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id);
+
+- tbl_dw = iwl4965_read_targ_mem(priv, tbl_dw_addr);
++ tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr);
+
+ if (txq_id & 0x1)
+ tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF);
+ else
+ tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000);
+
+- iwl4965_write_targ_mem(priv, tbl_dw_addr, tbl_dw);
++ iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw);
+
+ return 0;
+ }
+
++
+ /**
+ * iwl4965_tx_queue_agg_enable - Set up & enable aggregation for selected queue
+ *
+ * NOTE: txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID,
+ * i.e. it must be one of the higher queues used for aggregation
+ */
+-static int iwl4965_tx_queue_agg_enable(struct iwl4965_priv *priv, int txq_id,
++static int iwl4965_tx_queue_agg_enable(struct iwl_priv *priv, int txq_id,
+ int tx_fifo, int sta_id, int tid,
+ u16 ssn_idx)
+ {
+@@ -4412,7 +4462,7 @@ static int iwl4965_tx_queue_agg_enable(struct iwl4965_priv *priv, int txq_id,
+ iwl4965_sta_modify_enable_tid_tx(priv, sta_id, tid);
+
+ spin_lock_irqsave(&priv->lock, flags);
+- rc = iwl4965_grab_nic_access(priv);
++ rc = iwl_grab_nic_access(priv);
+ if (rc) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return rc;
+@@ -4425,7 +4475,7 @@ static int iwl4965_tx_queue_agg_enable(struct iwl4965_priv *priv, int txq_id,
+ iwl4965_tx_queue_set_q2ratid(priv, ra_tid, txq_id);
+
+ /* Set this queue as a chain-building queue */
+- iwl4965_set_bits_prph(priv, KDR_SCD_QUEUECHAIN_SEL, (1 << txq_id));
++ iwl_set_bits_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
+
+ /* Place first TFD at index corresponding to start sequence number.
+ * Assumes that ssn_idx is valid (!= 0xFFF) */
+@@ -4434,69 +4484,27 @@ static int iwl4965_tx_queue_agg_enable(struct iwl4965_priv *priv, int txq_id,
+ iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx);
+
+ /* Set up Tx window size and frame limit for this queue */
+- iwl4965_write_targ_mem(priv,
++ iwl_write_targ_mem(priv,
+ priv->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(txq_id),
+ (SCD_WIN_SIZE << SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) &
+ SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
+
+- iwl4965_write_targ_mem(priv, priv->scd_base_addr +
++ iwl_write_targ_mem(priv, priv->scd_base_addr +
+ SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32),
+ (SCD_FRAME_LIMIT << SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS)
+ & SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
+
+- iwl4965_set_bits_prph(priv, KDR_SCD_INTERRUPT_MASK, (1 << txq_id));
++ iwl_set_bits_prph(priv, IWL49_SCD_INTERRUPT_MASK, (1 << txq_id));
+
+ /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
+ iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1);
+
+- iwl4965_release_nic_access(priv);
+- spin_unlock_irqrestore(&priv->lock, flags);
+-
+- return 0;
+-}
+-
+-/**
+- * txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID
+- */
+-static int iwl4965_tx_queue_agg_disable(struct iwl4965_priv *priv, u16 txq_id,
+- u16 ssn_idx, u8 tx_fifo)
+-{
+- unsigned long flags;
+- int rc;
+-
+- if (IWL_BACK_QUEUE_FIRST_ID > txq_id) {
+- IWL_WARNING("queue number too small: %d, must be > %d\n",
+- txq_id, IWL_BACK_QUEUE_FIRST_ID);
+- return -EINVAL;
+- }
+-
+- spin_lock_irqsave(&priv->lock, flags);
+- rc = iwl4965_grab_nic_access(priv);
+- if (rc) {
+- spin_unlock_irqrestore(&priv->lock, flags);
+- return rc;
+- }
+-
+- iwl4965_tx_queue_stop_scheduler(priv, txq_id);
+-
+- iwl4965_clear_bits_prph(priv, KDR_SCD_QUEUECHAIN_SEL, (1 << txq_id));
+-
+- priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
+- priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
+- /* supposes that ssn_idx is valid (!= 0xFFF) */
+- iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx);
+-
+- iwl4965_clear_bits_prph(priv, KDR_SCD_INTERRUPT_MASK, (1 << txq_id));
+- iwl4965_txq_ctx_deactivate(priv, txq_id);
+- iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0);
+-
+- iwl4965_release_nic_access(priv);
++ iwl_release_nic_access(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+ }
+
+-#endif/* CONFIG_IWL4965_HT_AGG */
+ #endif /* CONFIG_IWL4965_HT */
+
+ /**
+@@ -4513,10 +4521,10 @@ static int iwl4965_tx_queue_agg_disable(struct iwl4965_priv *priv, u16 txq_id,
+ * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD,
+ * which requires station table entry to exist).
+ */
+-void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap)
++void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
+ {
+ int i, r;
+- struct iwl4965_link_quality_cmd link_cmd = {
++ struct iwl_link_quality_cmd link_cmd = {
+ .reserved1 = 0,
+ };
+ u16 rate_flags;
+@@ -4525,7 +4533,7 @@ void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap)
+ * all the way down to 1M in IEEE order, and then spin on 1M */
+ if (is_ap)
+ r = IWL_RATE_54M_INDEX;
+- else if (priv->phymode == MODE_IEEE80211A)
++ else if (priv->band == IEEE80211_BAND_5GHZ)
+ r = IWL_RATE_6M_INDEX;
+ else
+ r = IWL_RATE_1M_INDEX;
+@@ -4550,24 +4558,25 @@ void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap)
+ link_cmd.agg_params.agg_time_limit = cpu_to_le16(4000);
+
+ /* Update the rate scaling for control frame Tx to AP */
+- link_cmd.sta_id = is_ap ? IWL_AP_ID : IWL4965_BROADCAST_ID;
++ link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id;
+
+- iwl4965_send_cmd_pdu(priv, REPLY_TX_LINK_QUALITY_CMD, sizeof(link_cmd),
+- &link_cmd);
++ iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD,
++ sizeof(link_cmd), &link_cmd, NULL);
+ }
+
+ #ifdef CONFIG_IWL4965_HT
+
+-static u8 iwl4965_is_channel_extension(struct iwl4965_priv *priv, int phymode,
+- u16 channel, u8 extension_chan_offset)
++static u8 iwl4965_is_channel_extension(struct iwl_priv *priv,
++ enum ieee80211_band band,
++ u16 channel, u8 extension_chan_offset)
+ {
+- const struct iwl4965_channel_info *ch_info;
++ const struct iwl_channel_info *ch_info;
+
+- ch_info = iwl4965_get_channel_info(priv, phymode, channel);
++ ch_info = iwl_get_channel_info(priv, band, channel);
+ if (!is_channel_valid(ch_info))
+ return 0;
+
+- if (extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_AUTO)
++ if (extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_NONE)
+ return 0;
+
+ if ((ch_info->fat_extension_channel == extension_chan_offset) ||
+@@ -4577,14 +4586,14 @@ static u8 iwl4965_is_channel_extension(struct iwl4965_priv *priv, int phymode,
+ return 0;
+ }
+
+-static u8 iwl4965_is_fat_tx_allowed(struct iwl4965_priv *priv,
++static u8 iwl4965_is_fat_tx_allowed(struct iwl_priv *priv,
+ struct ieee80211_ht_info *sta_ht_inf)
+ {
+ struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config;
+
+ if ((!iwl_ht_conf->is_ht) ||
+ (iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ) ||
+- (iwl_ht_conf->extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_AUTO))
++ (iwl_ht_conf->extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_NONE))
+ return 0;
+
+ if (sta_ht_inf) {
+@@ -4593,12 +4602,12 @@ static u8 iwl4965_is_fat_tx_allowed(struct iwl4965_priv *priv,
+ return 0;
+ }
+
+- return (iwl4965_is_channel_extension(priv, priv->phymode,
++ return (iwl4965_is_channel_extension(priv, priv->band,
+ iwl_ht_conf->control_channel,
+ iwl_ht_conf->extension_chan_offset));
+ }
+
+-void iwl4965_set_rxon_ht(struct iwl4965_priv *priv, struct iwl_ht_info *ht_info)
++void iwl4965_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
+ {
+ struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon;
+ u32 val;
+@@ -4629,9 +4638,7 @@ void iwl4965_set_rxon_ht(struct iwl4965_priv *priv, struct iwl_ht_info *ht_info)
+ case IWL_EXT_CHANNEL_OFFSET_BELOW:
+ rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
+ break;
+- case IWL_EXT_CHANNEL_OFFSET_AUTO:
+- rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK;
+- break;
++ case IWL_EXT_CHANNEL_OFFSET_NONE:
+ default:
+ rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK;
+ break;
+@@ -4654,7 +4661,7 @@ void iwl4965_set_rxon_ht(struct iwl4965_priv *priv, struct iwl_ht_info *ht_info)
+ return;
+ }
+
+-void iwl4965_set_ht_add_station(struct iwl4965_priv *priv, u8 index,
++void iwl4965_set_ht_add_station(struct iwl_priv *priv, u8 index,
+ struct ieee80211_ht_info *sta_ht_inf)
+ {
+ __le32 sta_flags;
+@@ -4699,7 +4706,7 @@ void iwl4965_set_ht_add_station(struct iwl4965_priv *priv, u8 index,
+ return;
+ }
+
+-static void iwl4965_sta_modify_add_ba_tid(struct iwl4965_priv *priv,
++static void iwl4965_sta_modify_add_ba_tid(struct iwl_priv *priv,
+ int sta_id, int tid, u16 ssn)
+ {
+ unsigned long flags;
+@@ -4715,7 +4722,7 @@ static void iwl4965_sta_modify_add_ba_tid(struct iwl4965_priv *priv,
+ iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+ }
+
+-static void iwl4965_sta_modify_del_ba_tid(struct iwl4965_priv *priv,
++static void iwl4965_sta_modify_del_ba_tid(struct iwl_priv *priv,
+ int sta_id, int tid)
+ {
+ unsigned long flags;
+@@ -4730,136 +4737,94 @@ static void iwl4965_sta_modify_del_ba_tid(struct iwl4965_priv *priv,
+ iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+ }
+
+-int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
+- enum ieee80211_ampdu_mlme_action action,
+- const u8 *addr, u16 tid, u16 ssn)
+-{
+- struct iwl4965_priv *priv = hw->priv;
+- int sta_id;
+- DECLARE_MAC_BUF(mac);
+-
+- IWL_DEBUG_HT("A-MPDU action on da=%s tid=%d ",
+- print_mac(mac, addr), tid);
+- sta_id = iwl4965_hw_find_station(priv, addr);
+- switch (action) {
+- case IEEE80211_AMPDU_RX_START:
+- IWL_DEBUG_HT("start Rx\n");
+- iwl4965_sta_modify_add_ba_tid(priv, sta_id, tid, ssn);
+- break;
+- case IEEE80211_AMPDU_RX_STOP:
+- IWL_DEBUG_HT("stop Rx\n");
+- iwl4965_sta_modify_del_ba_tid(priv, sta_id, tid);
+- break;
+- default:
+- IWL_DEBUG_HT("unknown\n");
+- return -EINVAL;
+- break;
+- }
+- return 0;
+-}
+-
+-#ifdef CONFIG_IWL4965_HT_AGG
+-
+-static const u16 default_tid_to_tx_fifo[] = {
+- IWL_TX_FIFO_AC1,
+- IWL_TX_FIFO_AC0,
+- IWL_TX_FIFO_AC0,
+- IWL_TX_FIFO_AC1,
+- IWL_TX_FIFO_AC2,
+- IWL_TX_FIFO_AC2,
+- IWL_TX_FIFO_AC3,
+- IWL_TX_FIFO_AC3,
+- IWL_TX_FIFO_NONE,
+- IWL_TX_FIFO_NONE,
+- IWL_TX_FIFO_NONE,
+- IWL_TX_FIFO_NONE,
+- IWL_TX_FIFO_NONE,
+- IWL_TX_FIFO_NONE,
+- IWL_TX_FIFO_NONE,
+- IWL_TX_FIFO_NONE,
+- IWL_TX_FIFO_AC3
+-};
+-
+ /*
+ * Find first available (lowest unused) Tx Queue, mark it "active".
+ * Called only when finding queue for aggregation.
+ * Should never return anything < 7, because they should already
+ * be in use as EDCA AC (0-3), Command (4), HCCA (5, 6).
+ */
+-static int iwl4965_txq_ctx_activate_free(struct iwl4965_priv *priv)
++static int iwl4965_txq_ctx_activate_free(struct iwl_priv *priv)
+ {
+ int txq_id;
+
+- for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++)
++ for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
+ if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk))
+ return txq_id;
+ return -1;
+ }
+
+-int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, u8 *da, u16 tid,
+- u16 *start_seq_num)
++static int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, const u8 *da,
++ u16 tid, u16 *start_seq_num)
+ {
+-
+- struct iwl4965_priv *priv = hw->priv;
++ struct iwl_priv *priv = hw->priv;
+ int sta_id;
+ int tx_fifo;
+ int txq_id;
+ int ssn = -1;
++ int ret = 0;
+ unsigned long flags;
+ struct iwl4965_tid_data *tid_data;
+ DECLARE_MAC_BUF(mac);
+
+- /* Determine Tx DMA/FIFO channel for this Traffic ID */
+ if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo)))
+ tx_fifo = default_tid_to_tx_fifo[tid];
+ else
+ return -EINVAL;
+
+- IWL_WARNING("iwl-AGG iwl4965_mac_ht_tx_agg_start on da=%s"
+- " tid=%d\n", print_mac(mac, da), tid);
++ IWL_WARNING("%s on da = %s tid = %d\n",
++ __func__, print_mac(mac, da), tid);
+
+- /* Get index into station table */
+ sta_id = iwl4965_hw_find_station(priv, da);
+ if (sta_id == IWL_INVALID_STATION)
+ return -ENXIO;
+
+- /* Find available Tx queue for aggregation */
++ if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) {
++ IWL_ERROR("Start AGG when state is not IWL_AGG_OFF !\n");
++ return -ENXIO;
++ }
++
+ txq_id = iwl4965_txq_ctx_activate_free(priv);
+ if (txq_id == -1)
+ return -ENXIO;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ tid_data = &priv->stations[sta_id].tid[tid];
+-
+- /* Get starting sequence number for 1st frame in block ack window.
+- * We'll use least signif byte as 1st frame's index into Tx queue. */
+ ssn = SEQ_TO_SN(tid_data->seq_number);
+ tid_data->agg.txq_id = txq_id;
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ *start_seq_num = ssn;
++ ret = iwl4965_tx_queue_agg_enable(priv, txq_id, tx_fifo,
++ sta_id, tid, ssn);
++ if (ret)
++ return ret;
+
+- /* Update driver's link quality manager */
+- iwl4965_ba_status(priv, tid, BA_STATUS_ACTIVE);
+-
+- /* Set up and enable aggregation for selected Tx queue and FIFO */
+- return iwl4965_tx_queue_agg_enable(priv, txq_id, tx_fifo,
+- sta_id, tid, ssn);
++ ret = 0;
++ if (tid_data->tfds_in_queue == 0) {
++ printk(KERN_ERR "HW queue is empty\n");
++ tid_data->agg.state = IWL_AGG_ON;
++ ieee80211_start_tx_ba_cb_irqsafe(hw, da, tid);
++ } else {
++ IWL_DEBUG_HT("HW queue is NOT empty: %d packets in HW queue\n",
++ tid_data->tfds_in_queue);
++ tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA;
++ }
++ return ret;
+ }
+
+-
+-int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da, u16 tid,
+- int generator)
++static int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, const u8 *da,
++ u16 tid)
+ {
+
+- struct iwl4965_priv *priv = hw->priv;
++ struct iwl_priv *priv = hw->priv;
+ int tx_fifo_id, txq_id, sta_id, ssn = -1;
+ struct iwl4965_tid_data *tid_data;
+- int rc;
++ int ret, write_ptr, read_ptr;
++ unsigned long flags;
+ DECLARE_MAC_BUF(mac);
+
+ if (!da) {
+- IWL_ERROR("%s: da = NULL\n", __func__);
++ IWL_ERROR("da = NULL\n");
+ return -EINVAL;
+ }
+
+@@ -4873,31 +4838,82 @@ int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da, u16 tid,
+ if (sta_id == IWL_INVALID_STATION)
+ return -ENXIO;
+
++ if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_ON)
++ IWL_WARNING("Stopping AGG while state not IWL_AGG_ON\n");
++
+ tid_data = &priv->stations[sta_id].tid[tid];
+ ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4;
+ txq_id = tid_data->agg.txq_id;
++ write_ptr = priv->txq[txq_id].q.write_ptr;
++ read_ptr = priv->txq[txq_id].q.read_ptr;
++
++ /* The queue is not empty */
++ if (write_ptr != read_ptr) {
++ IWL_DEBUG_HT("Stopping a non empty AGG HW QUEUE\n");
++ priv->stations[sta_id].tid[tid].agg.state =
++ IWL_EMPTYING_HW_QUEUE_DELBA;
++ return 0;
++ }
+
+- rc = iwl4965_tx_queue_agg_disable(priv, txq_id, ssn, tx_fifo_id);
+- /* FIXME: need more safe way to handle error condition */
+- if (rc)
+- return rc;
++ IWL_DEBUG_HT("HW queue empty\n");;
++ priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ ret = iwl4965_tx_queue_agg_disable(priv, txq_id, ssn, tx_fifo_id);
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ if (ret)
++ return ret;
++
++ ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, da, tid);
+
+- iwl4965_ba_status(priv, tid, BA_STATUS_INITIATOR_DELBA);
+ IWL_DEBUG_INFO("iwl4965_mac_ht_tx_agg_stop on da=%s tid=%d\n",
+- print_mac(mac, da), tid);
++ print_mac(mac, da), tid);
+
+ return 0;
+ }
+
++int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
++ enum ieee80211_ampdu_mlme_action action,
++ const u8 *addr, u16 tid, u16 *ssn)
++{
++ struct iwl_priv *priv = hw->priv;
++ int sta_id;
++ DECLARE_MAC_BUF(mac);
++
++ IWL_DEBUG_HT("A-MPDU action on da=%s tid=%d ",
++ print_mac(mac, addr), tid);
++ sta_id = iwl4965_hw_find_station(priv, addr);
++ switch (action) {
++ case IEEE80211_AMPDU_RX_START:
++ IWL_DEBUG_HT("start Rx\n");
++ iwl4965_sta_modify_add_ba_tid(priv, sta_id, tid, *ssn);
++ break;
++ case IEEE80211_AMPDU_RX_STOP:
++ IWL_DEBUG_HT("stop Rx\n");
++ iwl4965_sta_modify_del_ba_tid(priv, sta_id, tid);
++ break;
++ case IEEE80211_AMPDU_TX_START:
++ IWL_DEBUG_HT("start Tx\n");
++ return iwl4965_mac_ht_tx_agg_start(hw, addr, tid, ssn);
++ case IEEE80211_AMPDU_TX_STOP:
++ IWL_DEBUG_HT("stop Tx\n");
++ return iwl4965_mac_ht_tx_agg_stop(hw, addr, tid);
++ default:
++ IWL_DEBUG_HT("unknown\n");
++ return -EINVAL;
++ break;
++ }
++ return 0;
++}
+
+-#endif /* CONFIG_IWL4965_HT_AGG */
+ #endif /* CONFIG_IWL4965_HT */
+
+ /* Set up 4965-specific Rx frame reply handlers */
+-void iwl4965_hw_rx_handler_setup(struct iwl4965_priv *priv)
++void iwl4965_hw_rx_handler_setup(struct iwl_priv *priv)
+ {
+ /* Legacy Rx frames */
+- priv->rx_handlers[REPLY_4965_RX] = iwl4965_rx_reply_rx;
++ priv->rx_handlers[REPLY_RX] = iwl4965_rx_reply_rx;
+
+ /* High-throughput (HT) Rx frames */
+ priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl4965_rx_reply_rx_phy;
+@@ -4907,71 +4923,85 @@ void iwl4965_hw_rx_handler_setup(struct iwl4965_priv *priv)
+ iwl4965_rx_missed_beacon_notif;
+
+ #ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
+ priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl4965_rx_reply_compressed_ba;
+-#endif /* CONFIG_IWL4965_HT_AGG */
+ #endif /* CONFIG_IWL4965_HT */
+ }
+
+-void iwl4965_hw_setup_deferred_work(struct iwl4965_priv *priv)
++void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv)
+ {
+ INIT_WORK(&priv->txpower_work, iwl4965_bg_txpower_work);
+- INIT_WORK(&priv->statistics_work, iwl4965_bg_statistics_work);
+ #ifdef CONFIG_IWL4965_SENSITIVITY
+ INIT_WORK(&priv->sensitivity_work, iwl4965_bg_sensitivity_work);
+ #endif
+-#ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
+- INIT_WORK(&priv->agg_work, iwl4965_bg_agg_work);
+-#endif /* CONFIG_IWL4965_HT_AGG */
+-#endif /* CONFIG_IWL4965_HT */
+ init_timer(&priv->statistics_periodic);
+ priv->statistics_periodic.data = (unsigned long)priv;
+ priv->statistics_periodic.function = iwl4965_bg_statistics_periodic;
+ }
+
+-void iwl4965_hw_cancel_deferred_work(struct iwl4965_priv *priv)
++void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv)
+ {
+ del_timer_sync(&priv->statistics_periodic);
+
+ cancel_delayed_work(&priv->init_alive_start);
+ }
+
+-struct pci_device_id iwl4965_hw_card_ids[] = {
+- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4229)},
+- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4230)},
+- {0}
++
++static struct iwl_hcmd_ops iwl4965_hcmd = {
++ .rxon_assoc = iwl4965_send_rxon_assoc,
+ };
+
+-/*
+- * The device's EEPROM semaphore prevents conflicts between driver and uCode
+- * when accessing the EEPROM; each access is a series of pulses to/from the
+- * EEPROM chip, not a single event, so even reads could conflict if they
+- * weren't arbitrated by the semaphore.
+- */
+-int iwl4965_eeprom_acquire_semaphore(struct iwl4965_priv *priv)
+-{
+- u16 count;
+- int rc;
++static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
++ .enqueue_hcmd = iwl4965_enqueue_hcmd,
++};
+
+- for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) {
+- /* Request semaphore */
+- iwl4965_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+- CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
+-
+- /* See if we got it */
+- rc = iwl4965_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
+- CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
+- CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
+- EEPROM_SEM_TIMEOUT);
+- if (rc >= 0) {
+- IWL_DEBUG_IO("Acquired semaphore after %d tries.\n",
+- count+1);
+- return rc;
+- }
+- }
++static struct iwl_lib_ops iwl4965_lib = {
++ .init_drv = iwl4965_init_drv,
++ .set_hw_params = iwl4965_hw_set_hw_params,
++ .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl,
++ .hw_nic_init = iwl4965_hw_nic_init,
++ .is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr,
++ .alive_notify = iwl4965_alive_notify,
++ .load_ucode = iwl4965_load_bsm,
++ .eeprom_ops = {
++ .verify_signature = iwlcore_eeprom_verify_signature,
++ .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
++ .release_semaphore = iwlcore_eeprom_release_semaphore,
++ },
++ .radio_kill_sw = iwl4965_radio_kill_sw,
++};
+
+- return rc;
+-}
++static struct iwl_ops iwl4965_ops = {
++ .lib = &iwl4965_lib,
++ .hcmd = &iwl4965_hcmd,
++ .utils = &iwl4965_hcmd_utils,
++};
++
++struct iwl_cfg iwl4965_agn_cfg = {
++ .name = "4965AGN",
++ .fw_name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode",
++ .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
++ .ops = &iwl4965_ops,
++ .mod_params = &iwl4965_mod_params,
++};
++
++module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444);
++MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
++module_param_named(disable, iwl4965_mod_params.disable, int, 0444);
++MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
++module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444);
++MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])\n");
++module_param_named(debug, iwl4965_mod_params.debug, int, 0444);
++MODULE_PARM_DESC(debug, "debug output mask");
++module_param_named(
++ disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, 0444);
++MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
++
++module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, 0444);
++MODULE_PARM_DESC(queues_num, "number of hw queues.");
++
++/* QoS */
++module_param_named(qos_enable, iwl4965_mod_params.enable_qos, int, 0444);
++MODULE_PARM_DESC(qos_enable, "enable all QoS functionality");
++module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K, int, 0444);
++MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size");
+
+-MODULE_DEVICE_TABLE(pci, iwl4965_hw_card_ids);
+diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h
+index 9cb82be..9ed13cb 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-4965.h
++++ b/drivers/net/wireless/iwlwifi/iwl-4965.h
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+ *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+@@ -36,13 +36,24 @@
+ #include <linux/kernel.h>
+ #include <net/ieee80211_radiotap.h>
+
+-/* Hardware specific file defines the PCI IDs table for that hardware module */
+-extern struct pci_device_id iwl4965_hw_card_ids[];
+-
+ #define DRV_NAME "iwl4965"
++#include "iwl-rfkill.h"
++#include "iwl-eeprom.h"
+ #include "iwl-4965-hw.h"
++#include "iwl-csr.h"
+ #include "iwl-prph.h"
+-#include "iwl-4965-debug.h"
++#include "iwl-debug.h"
++#include "iwl-led.h"
++
++/* configuration for the iwl4965 */
++extern struct iwl_cfg iwl4965_agn_cfg;
++
++/* Change firmware file name, using "-" and incrementing number,
++ * *only* when uCode interface or architecture changes so that it
++ * is not compatible with earlier drivers.
++ * This number will also appear in << 8 position of 1st dword of uCode file */
++#define IWL4965_UCODE_API "-1"
++
+
+ /* Default noise level to report when noise measurement is not available.
+ * This may be because we're:
+@@ -57,11 +68,6 @@ extern struct pci_device_id iwl4965_hw_card_ids[];
+ * averages within an s8's (used in some apps) range of negative values. */
+ #define IWL_NOISE_MEAS_NOT_AVAILABLE (-127)
+
+-/* Module parameters accessible from iwl-*.c */
+-extern int iwl4965_param_hwcrypto;
+-extern int iwl4965_param_queues_num;
+-extern int iwl4965_param_amsdu_size_8K;
+-
+ enum iwl4965_antenna {
+ IWL_ANTENNA_DIVERSITY,
+ IWL_ANTENNA_MAIN,
+@@ -133,7 +139,7 @@ struct iwl4965_tx_info {
+ struct iwl4965_tx_queue {
+ struct iwl4965_queue q;
+ struct iwl4965_tfd_frame *bd;
+- struct iwl4965_cmd *cmd;
++ struct iwl_cmd *cmd;
+ dma_addr_t dma_addr_cmd;
+ struct iwl4965_tx_info *txb;
+ int need_update;
+@@ -190,7 +196,7 @@ enum {
+ */
+ #define IWL4965_MAX_RATE (33)
+
+-struct iwl4965_channel_info {
++struct iwl_channel_info {
+ struct iwl4965_channel_tgd_info tgd;
+ struct iwl4965_channel_tgh_info tgh;
+ struct iwl4965_eeprom_channel eeprom; /* EEPROM regulatory limit */
+@@ -206,7 +212,7 @@ struct iwl4965_channel_info {
+
+ u8 group_index; /* 0-4, maps channel to group1/2/3/4/5 */
+ u8 band_index; /* 0-4, maps channel to band1/2/3/4/5 */
+- u8 phymode; /* MODE_IEEE80211{A,B,G} */
++ enum ieee80211_band band;
+
+ /* Radio/DSP gain settings for each "normal" data Tx rate.
+ * These include, in addition to RF and DSP gain, a few fields for
+@@ -288,8 +294,8 @@ struct iwl4965_frame {
+
+ #define SEQ_TO_QUEUE(x) ((x >> 8) & 0xbf)
+ #define QUEUE_TO_SEQ(x) ((x & 0xbf) << 8)
+-#define SEQ_TO_INDEX(x) (x & 0xff)
+-#define INDEX_TO_SEQ(x) (x & 0xff)
++#define SEQ_TO_INDEX(x) ((u8)(x & 0xff))
++#define INDEX_TO_SEQ(x) ((u8)(x & 0xff))
+ #define SEQ_HUGE_FRAME (0x4000)
+ #define SEQ_RX_FRAME __constant_cpu_to_le16(0x8000)
+ #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
+@@ -305,15 +311,15 @@ enum {
+ CMD_WANT_SKB = (1 << 2),
+ };
+
+-struct iwl4965_cmd;
+-struct iwl4965_priv;
++struct iwl_cmd;
++struct iwl_priv;
+
+-struct iwl4965_cmd_meta {
+- struct iwl4965_cmd_meta *source;
++struct iwl_cmd_meta {
++ struct iwl_cmd_meta *source;
+ union {
+ struct sk_buff *skb;
+- int (*callback)(struct iwl4965_priv *priv,
+- struct iwl4965_cmd *cmd, struct sk_buff *skb);
++ int (*callback)(struct iwl_priv *priv,
++ struct iwl_cmd *cmd, struct sk_buff *skb);
+ } __attribute__ ((packed)) u;
+
+ /* The CMD_SIZE_HUGE flag bit indicates that the command
+@@ -323,15 +329,15 @@ struct iwl4965_cmd_meta {
+ } __attribute__ ((packed));
+
+ /**
+- * struct iwl4965_cmd
++ * struct iwl_cmd
+ *
+ * For allocation of the command and tx queues, this establishes the overall
+ * size of the largest command we send to uCode, except for a scan command
+ * (which is relatively huge; space is allocated separately).
+ */
+-struct iwl4965_cmd {
+- struct iwl4965_cmd_meta meta; /* driver data */
+- struct iwl4965_cmd_header hdr; /* uCode API */
++struct iwl_cmd {
++ struct iwl_cmd_meta meta; /* driver data */
++ struct iwl_cmd_header hdr; /* uCode API */
+ union {
+ struct iwl4965_addsta_cmd addsta;
+ struct iwl4965_led_cmd led;
+@@ -351,15 +357,15 @@ struct iwl4965_cmd {
+ } __attribute__ ((packed)) cmd;
+ } __attribute__ ((packed));
+
+-struct iwl4965_host_cmd {
++struct iwl_host_cmd {
+ u8 id;
+ u16 len;
+- struct iwl4965_cmd_meta meta;
++ struct iwl_cmd_meta meta;
+ const void *data;
+ };
+
+-#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl4965_cmd) - \
+- sizeof(struct iwl4965_cmd_meta))
++#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_cmd) - \
++ sizeof(struct iwl_cmd_meta))
+
+ /*
+ * RX related structures and functions
+@@ -408,32 +414,12 @@ struct iwl4965_rx_queue {
+ #define MAX_B_CHANNELS 14
+ #define MIN_B_CHANNELS 1
+
+-#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
+-#define STATUS_INT_ENABLED 1
+-#define STATUS_RF_KILL_HW 2
+-#define STATUS_RF_KILL_SW 3
+-#define STATUS_INIT 4
+-#define STATUS_ALIVE 5
+-#define STATUS_READY 6
+-#define STATUS_TEMPERATURE 7
+-#define STATUS_GEO_CONFIGURED 8
+-#define STATUS_EXIT_PENDING 9
+-#define STATUS_IN_SUSPEND 10
+-#define STATUS_STATISTICS 11
+-#define STATUS_SCANNING 12
+-#define STATUS_SCAN_ABORTING 13
+-#define STATUS_SCAN_HW 14
+-#define STATUS_POWER_PMI 15
+-#define STATUS_FW_ERROR 16
+-#define STATUS_CONF_PENDING 17
+-
+ #define MAX_TID_COUNT 9
+
+ #define IWL_INVALID_RATE 0xFF
+ #define IWL_INVALID_VALUE -1
+
+ #ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
+ /**
+ * struct iwl4965_ht_agg -- aggregation status while waiting for block-ack
+ * @txq_id: Tx queue used for Tx attempt
+@@ -453,25 +439,30 @@ struct iwl4965_ht_agg {
+ u16 frame_count;
+ u16 wait_for_ba;
+ u16 start_idx;
+- u32 bitmap0;
+- u32 bitmap1;
++ u64 bitmap;
+ u32 rate_n_flags;
++#define IWL_AGG_OFF 0
++#define IWL_AGG_ON 1
++#define IWL_EMPTYING_HW_QUEUE_ADDBA 2
++#define IWL_EMPTYING_HW_QUEUE_DELBA 3
++ u8 state;
+ };
+-#endif /* CONFIG_IWL4965_HT_AGG */
++
+ #endif /* CONFIG_IWL4965_HT */
+
+ struct iwl4965_tid_data {
+ u16 seq_number;
++ u16 tfds_in_queue;
+ #ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
+ struct iwl4965_ht_agg agg;
+-#endif /* CONFIG_IWL4965_HT_AGG */
+ #endif /* CONFIG_IWL4965_HT */
+ };
+
+ struct iwl4965_hw_key {
+ enum ieee80211_key_alg alg;
+ int keylen;
++ u8 keyidx;
++ struct ieee80211_key_conf *conf;
+ u8 key[32];
+ };
+
+@@ -508,8 +499,6 @@ struct iwl_ht_info {
+ };
+ #endif /*CONFIG_IWL4965_HT */
+
+-#ifdef CONFIG_IWL4965_QOS
+-
+ union iwl4965_qos_capabity {
+ struct {
+ u8 edca_count:4; /* bit 0-3 */
+@@ -537,7 +526,6 @@ struct iwl4965_qos_info {
+ union iwl4965_qos_capabity qos_cap;
+ struct iwl4965_qosparam_cmd def_qos_parm;
+ };
+-#endif /*CONFIG_IWL4965_QOS */
+
+ #define STA_PS_STATUS_WAKE 0
+ #define STA_PS_STATUS_SLEEP 1
+@@ -579,30 +567,29 @@ struct iwl4965_ibss_seq {
+ };
+
+ /**
+- * struct iwl4965_driver_hw_info
++ * struct iwl_hw_params
+ * @max_txq_num: Max # Tx queues supported
+- * @ac_queue_count: # Tx queues for EDCA Access Categories (AC)
+ * @tx_cmd_len: Size of Tx command (but not including frame itself)
++ * @tx_ant_num: Number of TX antennas
+ * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
+ * @rx_buffer_size:
+ * @max_rxq_log: Log-base-2 of max_rxq_size
+ * @max_stations:
+ * @bcast_sta_id:
+- * @shared_virt: Pointer to driver/uCode shared Tx Byte Counts and Rx status
+- * @shared_phys: Physical Pointer to Tx Byte Counts and Rx status
+ */
+-struct iwl4965_driver_hw_info {
++struct iwl_hw_params {
+ u16 max_txq_num;
+- u16 ac_queue_count;
+ u16 tx_cmd_len;
++ u8 tx_chains_num;
++ u8 rx_chains_num;
++ u8 valid_tx_ant;
++ u8 valid_rx_ant;
+ u16 max_rxq_size;
++ u16 max_rxq_log;
+ u32 rx_buf_size;
+ u32 max_pkt_size;
+- u16 max_rxq_log;
+ u8 max_stations;
+ u8 bcast_sta_id;
+- void *shared_virt;
+- dma_addr_t shared_phys;
+ };
+
+ #define HT_SHORT_GI_20MHZ_ONLY (1 << 0)
+@@ -626,62 +613,49 @@ struct iwl4965_driver_hw_info {
+ *
+ *****************************************************************************/
+ struct iwl4965_addsta_cmd;
+-extern int iwl4965_send_add_station(struct iwl4965_priv *priv,
++extern int iwl4965_send_add_station(struct iwl_priv *priv,
+ struct iwl4965_addsta_cmd *sta, u8 flags);
+-extern u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr,
++extern u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr,
+ int is_ap, u8 flags, void *ht_data);
+-extern int iwl4965_is_network_packet(struct iwl4965_priv *priv,
++extern int iwl4965_is_network_packet(struct iwl_priv *priv,
+ struct ieee80211_hdr *header);
+-extern int iwl4965_power_init_handle(struct iwl4965_priv *priv);
+-extern int iwl4965_eeprom_init(struct iwl4965_priv *priv);
+-#ifdef CONFIG_IWL4965_DEBUG
+-extern void iwl4965_report_frame(struct iwl4965_priv *priv,
+- struct iwl4965_rx_packet *pkt,
+- struct ieee80211_hdr *header, int group100);
+-#else
+-static inline void iwl4965_report_frame(struct iwl4965_priv *priv,
+- struct iwl4965_rx_packet *pkt,
+- struct ieee80211_hdr *header,
+- int group100) {}
+-#endif
+-extern void iwl4965_handle_data_packet_monitor(struct iwl4965_priv *priv,
++extern int iwl4965_power_init_handle(struct iwl_priv *priv);
++extern void iwl4965_handle_data_packet_monitor(struct iwl_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb,
+ void *data, short len,
+ struct ieee80211_rx_status *stats,
+ u16 phy_flags);
+-extern int iwl4965_is_duplicate_packet(struct iwl4965_priv *priv,
++extern int iwl4965_is_duplicate_packet(struct iwl_priv *priv,
+ struct ieee80211_hdr *header);
+-extern int iwl4965_rx_queue_alloc(struct iwl4965_priv *priv);
+-extern void iwl4965_rx_queue_reset(struct iwl4965_priv *priv,
++extern int iwl4965_rx_queue_alloc(struct iwl_priv *priv);
++extern void iwl4965_rx_queue_reset(struct iwl_priv *priv,
+ struct iwl4965_rx_queue *rxq);
+ extern int iwl4965_calc_db_from_ratio(int sig_ratio);
+ extern int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm);
+-extern int iwl4965_tx_queue_init(struct iwl4965_priv *priv,
++extern int iwl4965_tx_queue_init(struct iwl_priv *priv,
+ struct iwl4965_tx_queue *txq, int count, u32 id);
+ extern void iwl4965_rx_replenish(void *data);
+-extern void iwl4965_tx_queue_free(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq);
+-extern int iwl4965_send_cmd_pdu(struct iwl4965_priv *priv, u8 id, u16 len,
+- const void *data);
+-extern int __must_check iwl4965_send_cmd(struct iwl4965_priv *priv,
+- struct iwl4965_host_cmd *cmd);
+-extern unsigned int iwl4965_fill_beacon_frame(struct iwl4965_priv *priv,
++extern void iwl4965_tx_queue_free(struct iwl_priv *priv, struct iwl4965_tx_queue *txq);
++extern unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv,
+ struct ieee80211_hdr *hdr,
+ const u8 *dest, int left);
+-extern int iwl4965_rx_queue_update_write_ptr(struct iwl4965_priv *priv,
++extern int iwl4965_rx_queue_update_write_ptr(struct iwl_priv *priv,
+ struct iwl4965_rx_queue *q);
+-extern int iwl4965_send_statistics_request(struct iwl4965_priv *priv);
+-extern void iwl4965_set_decrypted_flag(struct iwl4965_priv *priv, struct sk_buff *skb,
++extern void iwl4965_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb,
+ u32 decrypt_res,
+ struct ieee80211_rx_status *stats);
+ extern __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr);
++int iwl4965_init_geos(struct iwl_priv *priv);
++void iwl4965_free_geos(struct iwl_priv *priv);
+
+ extern const u8 iwl4965_broadcast_addr[ETH_ALEN];
++int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
+
+ /*
+ * Currently used by iwl-3945-rs... look at restructuring so that it doesn't
+ * call this... todo... fix that.
+ */
+-extern u8 iwl4965_sync_station(struct iwl4965_priv *priv, int sta_id,
++extern u8 iwl4965_sync_station(struct iwl_priv *priv, int sta_id,
+ u16 tx_rate, u8 flags);
+
+ /******************************************************************************
+@@ -700,36 +674,36 @@ extern u8 iwl4965_sync_station(struct iwl4965_priv *priv, int sta_id,
+ * iwl4965_mac_ <-- mac80211 callback
+ *
+ ****************************************************************************/
+-extern void iwl4965_hw_rx_handler_setup(struct iwl4965_priv *priv);
+-extern void iwl4965_hw_setup_deferred_work(struct iwl4965_priv *priv);
+-extern void iwl4965_hw_cancel_deferred_work(struct iwl4965_priv *priv);
+-extern int iwl4965_hw_rxq_stop(struct iwl4965_priv *priv);
+-extern int iwl4965_hw_set_hw_setting(struct iwl4965_priv *priv);
+-extern int iwl4965_hw_nic_init(struct iwl4965_priv *priv);
+-extern int iwl4965_hw_nic_stop_master(struct iwl4965_priv *priv);
+-extern void iwl4965_hw_txq_ctx_free(struct iwl4965_priv *priv);
+-extern void iwl4965_hw_txq_ctx_stop(struct iwl4965_priv *priv);
+-extern int iwl4965_hw_nic_reset(struct iwl4965_priv *priv);
+-extern int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl4965_priv *priv, void *tfd,
++extern void iwl4965_hw_rx_handler_setup(struct iwl_priv *priv);
++extern void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv);
++extern void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv);
++extern int iwl4965_hw_rxq_stop(struct iwl_priv *priv);
++extern int iwl4965_hw_set_hw_params(struct iwl_priv *priv);
++extern int iwl4965_hw_nic_init(struct iwl_priv *priv);
++extern int iwl4965_hw_nic_stop_master(struct iwl_priv *priv);
++extern void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv);
++extern void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv);
++extern int iwl4965_hw_nic_reset(struct iwl_priv *priv);
++extern int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *tfd,
+ dma_addr_t addr, u16 len);
+-extern int iwl4965_hw_txq_free_tfd(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq);
+-extern int iwl4965_hw_get_temperature(struct iwl4965_priv *priv);
+-extern int iwl4965_hw_tx_queue_init(struct iwl4965_priv *priv,
++extern int iwl4965_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl4965_tx_queue *txq);
++extern int iwl4965_hw_get_temperature(struct iwl_priv *priv);
++extern int iwl4965_hw_tx_queue_init(struct iwl_priv *priv,
+ struct iwl4965_tx_queue *txq);
+-extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl4965_priv *priv,
++extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
+ struct iwl4965_frame *frame, u8 rate);
+-extern int iwl4965_hw_get_rx_read(struct iwl4965_priv *priv);
+-extern void iwl4965_hw_build_tx_cmd_rate(struct iwl4965_priv *priv,
+- struct iwl4965_cmd *cmd,
++extern int iwl4965_hw_get_rx_read(struct iwl_priv *priv);
++extern void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv,
++ struct iwl_cmd *cmd,
+ struct ieee80211_tx_control *ctrl,
+ struct ieee80211_hdr *hdr,
+ int sta_id, int tx_id);
+-extern int iwl4965_hw_reg_send_txpower(struct iwl4965_priv *priv);
+-extern int iwl4965_hw_reg_set_txpower(struct iwl4965_priv *priv, s8 power);
+-extern void iwl4965_hw_rx_statistics(struct iwl4965_priv *priv,
++extern int iwl4965_hw_reg_send_txpower(struct iwl_priv *priv);
++extern int iwl4965_hw_reg_set_txpower(struct iwl_priv *priv, s8 power);
++extern void iwl4965_hw_rx_statistics(struct iwl_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb);
+-extern void iwl4965_disable_events(struct iwl4965_priv *priv);
+-extern int iwl4965_get_temperature(const struct iwl4965_priv *priv);
++extern void iwl4965_disable_events(struct iwl_priv *priv);
++extern int iwl4965_get_temperature(const struct iwl_priv *priv);
+
+ /**
+ * iwl4965_hw_find_station - Find station id for a given BSSID
+@@ -739,54 +713,51 @@ extern int iwl4965_get_temperature(const struct iwl4965_priv *priv);
+ * not yet been merged into a single common layer for managing the
+ * station tables.
+ */
+-extern u8 iwl4965_hw_find_station(struct iwl4965_priv *priv, const u8 *bssid);
++extern u8 iwl4965_hw_find_station(struct iwl_priv *priv, const u8 *bssid);
+
+-extern int iwl4965_hw_channel_switch(struct iwl4965_priv *priv, u16 channel);
+-extern int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index);
+-
+-struct iwl4965_priv;
++extern int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel);
++extern int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index);
++extern int iwl4965_queue_space(const struct iwl4965_queue *q);
++struct iwl_priv;
+
++extern void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio);
+ /*
+ * Forward declare iwl-4965.c functions for iwl-base.c
+ */
+-extern int iwl4965_eeprom_acquire_semaphore(struct iwl4965_priv *priv);
+-
+-extern int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv,
++extern int iwl4965_tx_queue_update_wr_ptr(struct iwl_priv *priv,
+ struct iwl4965_tx_queue *txq,
+ u16 byte_cnt);
+-extern void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr,
++extern void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr,
+ int is_ap);
+-extern void iwl4965_set_rxon_chain(struct iwl4965_priv *priv);
+-extern int iwl4965_alive_notify(struct iwl4965_priv *priv);
+-extern void iwl4965_update_rate_scaling(struct iwl4965_priv *priv, u8 mode);
+-extern void iwl4965_chain_noise_reset(struct iwl4965_priv *priv);
+-extern void iwl4965_init_sensitivity(struct iwl4965_priv *priv, u8 flags,
++extern void iwl4965_set_rxon_chain(struct iwl_priv *priv);
++extern int iwl4965_alive_notify(struct iwl_priv *priv);
++extern void iwl4965_update_rate_scaling(struct iwl_priv *priv, u8 mode);
++extern void iwl4965_chain_noise_reset(struct iwl_priv *priv);
++extern void iwl4965_init_sensitivity(struct iwl_priv *priv, u8 flags,
+ u8 force);
+-extern int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, int phymode,
+- u16 channel,
+- const struct iwl4965_eeprom_channel *eeprom_ch,
+- u8 fat_extension_channel);
+-extern void iwl4965_rf_kill_ct_config(struct iwl4965_priv *priv);
++extern void iwl4965_rf_kill_ct_config(struct iwl_priv *priv);
++extern void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv,
++ u32 rate_n_flags,
++ struct ieee80211_tx_control *control);
+
+ #ifdef CONFIG_IWL4965_HT
+-extern void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info,
+- int mode);
+-extern void iwl4965_set_rxon_ht(struct iwl4965_priv *priv,
+- struct iwl_ht_info *ht_info);
+-extern void iwl4965_set_ht_add_station(struct iwl4965_priv *priv, u8 index,
++void iwl4965_init_ht_hw_capab(struct iwl_priv *priv,
++ struct ieee80211_ht_info *ht_info,
++ enum ieee80211_band band);
++void iwl4965_set_rxon_ht(struct iwl_priv *priv,
++ struct iwl_ht_info *ht_info);
++void iwl4965_set_ht_add_station(struct iwl_priv *priv, u8 index,
+ struct ieee80211_ht_info *sta_ht_inf);
+-extern int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
++int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
+ enum ieee80211_ampdu_mlme_action action,
+- const u8 *addr, u16 tid, u16 ssn);
+-#ifdef CONFIG_IWL4965_HT_AGG
+-extern int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, u8 *da,
+- u16 tid, u16 *start_seq_num);
+-extern int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da,
+- u16 tid, int generator);
+-extern void iwl4965_turn_off_agg(struct iwl4965_priv *priv, u8 tid);
+-extern void iwl4965_tl_get_stats(struct iwl4965_priv *priv,
+- struct ieee80211_hdr *hdr);
+-#endif /* CONFIG_IWL4965_HT_AGG */
++ const u8 *addr, u16 tid, u16 *ssn);
++int iwl4965_check_empty_hw_queue(struct iwl_priv *priv, int sta_id,
++ u8 tid, int txq_id);
++#else
++static inline void iwl4965_init_ht_hw_capab(struct iwl_priv *priv,
++ struct ieee80211_ht_info *ht_info,
++ enum ieee80211_band band) {}
++
+ #endif /*CONFIG_IWL4965_HT */
+ /* Structures, enum, and defines specific to the 4965 */
+
+@@ -798,18 +769,6 @@ struct iwl4965_kw {
+ size_t size;
+ };
+
+-#define TID_QUEUE_CELL_SPACING 50 /*mS */
+-#define TID_QUEUE_MAX_SIZE 20
+-#define TID_ROUND_VALUE 5 /* mS */
+-#define TID_MAX_LOAD_COUNT 8
+-
+-#define TID_MAX_TIME_DIFF ((TID_QUEUE_MAX_SIZE - 1) * TID_QUEUE_CELL_SPACING)
+-#define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y))
+-
+-#define TID_ALL_ENABLED 0x7f
+-#define TID_ALL_SPECIFIED 0xff
+-#define TID_AGG_TPT_THREHOLD 0x0
+-
+ #define IWL_CHANNEL_WIDTH_20MHZ 0
+ #define IWL_CHANNEL_WIDTH_40MHZ 1
+
+@@ -823,48 +782,17 @@ struct iwl4965_kw {
+ #define IWL_OPERATION_MODE_MIXED 2
+ #define IWL_OPERATION_MODE_20MHZ 3
+
+-#define IWL_EXT_CHANNEL_OFFSET_AUTO 0
+-#define IWL_EXT_CHANNEL_OFFSET_ABOVE 1
+-#define IWL_EXT_CHANNEL_OFFSET_ 2
+-#define IWL_EXT_CHANNEL_OFFSET_BELOW 3
+-#define IWL_EXT_CHANNEL_OFFSET_MAX 4
++#define IWL_EXT_CHANNEL_OFFSET_NONE 0
++#define IWL_EXT_CHANNEL_OFFSET_ABOVE 1
++#define IWL_EXT_CHANNEL_OFFSET_RESERVE1 2
++#define IWL_EXT_CHANNEL_OFFSET_BELOW 3
+
+ #define NRG_NUM_PREV_STAT_L 20
+ #define NUM_RX_CHAINS (3)
+
+ #define TX_POWER_IWL_ILLEGAL_VOLTAGE -10000
+
+-struct iwl4965_traffic_load {
+- unsigned long time_stamp;
+- u32 packet_count[TID_QUEUE_MAX_SIZE];
+- u8 queue_count;
+- u8 head;
+- u32 total;
+-};
+-
+-#ifdef CONFIG_IWL4965_HT_AGG
+-/**
+- * struct iwl4965_agg_control
+- * @requested_ba: bit map of tids requesting aggregation/block-ack
+- * @granted_ba: bit map of tids granted aggregation/block-ack
+- */
+-struct iwl4965_agg_control {
+- unsigned long next_retry;
+- u32 wait_for_agg_status;
+- u32 tid_retry;
+- u32 requested_ba;
+- u32 granted_ba;
+- u8 auto_agg;
+- u32 tid_traffic_load_threshold;
+- u32 ba_timeout;
+- struct iwl4965_traffic_load traffic_load[TID_MAX_LOAD_COUNT];
+-};
+-#endif /*CONFIG_IWL4965_HT_AGG */
+-
+ struct iwl4965_lq_mngr {
+-#ifdef CONFIG_IWL4965_HT_AGG
+- struct iwl4965_agg_control agg_ctrl;
+-#endif
+ spinlock_t lock;
+ s32 max_window_size;
+ s32 *expected_tpt;
+@@ -877,7 +805,6 @@ struct iwl4965_lq_mngr {
+ u8 lq_ready;
+ };
+
+-
+ /* Sensitivity and chain noise calibration */
+ #define INTERFERENCE_DATA_AVAILABLE __constant_cpu_to_le32(1)
+ #define INITIALIZATION_VALUE 0xFFFF
+@@ -1014,25 +941,28 @@ enum {
+
+ #endif
+
+-struct iwl4965_priv {
++#define IWL_MAX_NUM_QUEUES 20 /* FIXME: do dynamic allocation */
++
++struct iwl_priv {
+
+ /* ieee device used by generic ieee processing code */
+ struct ieee80211_hw *hw;
+ struct ieee80211_channel *ieee_channels;
+ struct ieee80211_rate *ieee_rates;
++ struct iwl_cfg *cfg;
+
+ /* temporary frame storage list */
+ struct list_head free_frames;
+ int frames_count;
+
+- u8 phymode;
++ enum ieee80211_band band;
+ int alloc_rxb_skb;
+ bool add_radiotap;
+
+- void (*rx_handlers[REPLY_MAX])(struct iwl4965_priv *priv,
++ void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb);
+
+- const struct ieee80211_hw_mode *modes;
++ struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
+
+ #ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
+ /* spectrum measurement report caching */
+@@ -1044,7 +974,7 @@ struct iwl4965_priv {
+
+ /* we allocate array of iwl4965_channel_info for NIC's valid channels.
+ * Access via channel # using indirect index array */
+- struct iwl4965_channel_info *channel_info; /* channel info array */
++ struct iwl_channel_info *channel_info; /* channel info array */
+ u8 channel_count; /* # of channels */
+
+ /* each calibration channel group in the EEPROM has a derived
+@@ -1104,18 +1034,21 @@ struct iwl4965_priv {
+ * 4965's initialize alive response contains some calibration data. */
+ struct iwl4965_init_alive_resp card_alive_init;
+ struct iwl4965_alive_resp card_alive;
++#ifdef CONFIG_IWLWIFI_RFKILL
++ struct iwl_rfkill_mngr rfkill_mngr;
++#endif
+
+-#ifdef LED
+- /* LED related variables */
+- struct iwl4965_activity_blink activity;
+- unsigned long led_packets;
+- int led_state;
++#ifdef CONFIG_IWLWIFI_LEDS
++ struct iwl4965_led led[IWL_LED_TRG_MAX];
++ unsigned long last_blink_time;
++ u8 last_blink_rate;
++ u8 allow_blinking;
++ u64 led_tpt;
+ #endif
+
+ u16 active_rate;
+ u16 active_rate_basic;
+
+- u8 call_post_assoc_from_beacon;
+ u8 assoc_station_added;
+ u8 use_ant_b_for_management_frame; /* Tx antenna selection */
+ u8 valid_antenna; /* Bit mask of antennas actually connected */
+@@ -1150,11 +1083,16 @@ struct iwl4965_priv {
+ u32 scd_base_addr; /* scheduler sram base address */
+
+ unsigned long status;
+- u32 config;
+
+ int last_rx_rssi; /* From Rx packet statisitics */
+ int last_rx_noise; /* From beacon statistics */
+
++ /* counts mgmt, ctl, and data packets */
++ struct traffic_stats {
++ u32 cnt;
++ u64 bytes;
++ } tx_stats[3], rx_stats[3];
++
+ struct iwl4965_power_mgr power_data;
+
+ struct iwl4965_notif_statistics statistics;
+@@ -1175,12 +1113,15 @@ struct iwl4965_priv {
+ spinlock_t sta_lock;
+ int num_stations;
+ struct iwl4965_station_entry stations[IWL_STATION_COUNT];
++ struct iwl_wep_key wep_keys[WEP_KEYS_MAX];
++ u8 default_wep_key;
++ u8 key_mapping_key;
++ unsigned long ucode_key_table;
+
+ /* Indication if ieee80211_ops->open has been called */
+- int is_open;
++ u8 is_open;
+
+ u8 mac80211_registered;
+- int is_abg;
+
+ u32 notif_missed_beacons;
+
+@@ -1199,26 +1140,28 @@ struct iwl4965_priv {
+ /* eeprom */
+ struct iwl4965_eeprom eeprom;
+
+- int iw_mode;
++ enum ieee80211_if_types iw_mode;
+
+ struct sk_buff *ibss_beacon;
+
+ /* Last Rx'd beacon timestamp */
+- u32 timestamp0;
+- u32 timestamp1;
++ u64 timestamp;
+ u16 beacon_int;
+- struct iwl4965_driver_hw_info hw_setting;
+ struct ieee80211_vif *vif;
+
++ struct iwl_hw_params hw_params;
++ /* driver/uCode shared Tx Byte Counts and Rx status */
++ void *shared_virt;
++ /* Physical Pointer to Tx Byte Counts and Rx status */
++ dma_addr_t shared_phys;
++
+ /* Current association information needed to configure the
+ * hardware */
+ u16 assoc_id;
+ u16 assoc_capability;
+ u8 ps_mode;
+
+-#ifdef CONFIG_IWL4965_QOS
+ struct iwl4965_qos_info qos_data;
+-#endif /*CONFIG_IWL4965_QOS */
+
+ struct workqueue_struct *workqueue;
+
+@@ -1253,71 +1196,68 @@ struct iwl4965_priv {
+ u32 pm_state[16];
+ #endif
+
+-#ifdef CONFIG_IWL4965_DEBUG
++#ifdef CONFIG_IWLWIFI_DEBUG
+ /* debugging info */
+ u32 framecnt_to_us;
+ atomic_t restrict_refcnt;
+-#endif
++#ifdef CONFIG_IWLWIFI_DEBUGFS
++ /* debugfs */
++ struct iwl_debugfs *dbgfs;
++#endif /* CONFIG_IWLWIFI_DEBUGFS */
++#endif /* CONFIG_IWLWIFI_DEBUG */
+
+ struct work_struct txpower_work;
+ #ifdef CONFIG_IWL4965_SENSITIVITY
+ struct work_struct sensitivity_work;
+ #endif
+- struct work_struct statistics_work;
+ struct timer_list statistics_periodic;
++}; /*iwl_priv */
+
+-#ifdef CONFIG_IWL4965_HT_AGG
+- struct work_struct agg_work;
+-#endif
+-}; /*iwl4965_priv */
+-
+-static inline int iwl4965_is_associated(struct iwl4965_priv *priv)
++static inline int iwl_is_associated(struct iwl_priv *priv)
+ {
+ return (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
+ }
+
+-static inline int is_channel_valid(const struct iwl4965_channel_info *ch_info)
++static inline int is_channel_valid(const struct iwl_channel_info *ch_info)
+ {
+ if (ch_info == NULL)
+ return 0;
+ return (ch_info->flags & EEPROM_CHANNEL_VALID) ? 1 : 0;
+ }
+
+-static inline int is_channel_narrow(const struct iwl4965_channel_info *ch_info)
++static inline int is_channel_narrow(const struct iwl_channel_info *ch_info)
+ {
+ return (ch_info->flags & EEPROM_CHANNEL_NARROW) ? 1 : 0;
+ }
+
+-static inline int is_channel_radar(const struct iwl4965_channel_info *ch_info)
++static inline int is_channel_radar(const struct iwl_channel_info *ch_info)
+ {
+ return (ch_info->flags & EEPROM_CHANNEL_RADAR) ? 1 : 0;
+ }
+
+-static inline u8 is_channel_a_band(const struct iwl4965_channel_info *ch_info)
++static inline u8 is_channel_a_band(const struct iwl_channel_info *ch_info)
+ {
+- return ch_info->phymode == MODE_IEEE80211A;
++ return ch_info->band == IEEE80211_BAND_5GHZ;
+ }
+
+-static inline u8 is_channel_bg_band(const struct iwl4965_channel_info *ch_info)
++static inline u8 is_channel_bg_band(const struct iwl_channel_info *ch_info)
+ {
+- return ((ch_info->phymode == MODE_IEEE80211B) ||
+- (ch_info->phymode == MODE_IEEE80211G));
++ return ch_info->band == IEEE80211_BAND_2GHZ;
+ }
+
+-static inline int is_channel_passive(const struct iwl4965_channel_info *ch)
++static inline int is_channel_passive(const struct iwl_channel_info *ch)
+ {
+ return (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) ? 1 : 0;
+ }
+
+-static inline int is_channel_ibss(const struct iwl4965_channel_info *ch)
++static inline int is_channel_ibss(const struct iwl_channel_info *ch)
+ {
+ return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0;
+ }
+
+-extern const struct iwl4965_channel_info *iwl4965_get_channel_info(
+- const struct iwl4965_priv *priv, int phymode, u16 channel);
++extern const struct iwl_channel_info *iwl_get_channel_info(
++ const struct iwl_priv *priv, enum ieee80211_band band, u16 channel);
+
+-/* Requires full declaration of iwl4965_priv before including */
+-#include "iwl-4965-io.h"
++/* Requires full declaration of iwl_priv before including */
+
+ #endif /* __iwl4965_4965_h__ */
+diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
+new file mode 100644
+index 0000000..2dfd982
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-core.c
+@@ -0,0 +1,292 @@
++/******************************************************************************
++ *
++ * GPL LICENSE SUMMARY
++ *
++ * Copyright(c) 2008 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
++ * USA
++ *
++ * The full GNU General Public License is included in this distribution
++ * in the file called LICENSE.GPL.
++ *
++ * Contact Information:
++ * Tomas Winkler <tomas.winkler at intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *****************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/version.h>
++#include <net/mac80211.h>
++
++struct iwl_priv; /* FIXME: remove */
++#include "iwl-debug.h"
++#include "iwl-eeprom.h"
++#include "iwl-4965.h" /* FIXME: remove */
++#include "iwl-core.h"
++#include "iwl-rfkill.h"
++
++
++MODULE_DESCRIPTION("iwl core");
++MODULE_VERSION(IWLWIFI_VERSION);
++MODULE_AUTHOR(DRV_COPYRIGHT);
++MODULE_LICENSE("GPL");
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++u32 iwl_debug_level;
++EXPORT_SYMBOL(iwl_debug_level);
++#endif
++
++/* This function both allocates and initializes hw and priv. */
++struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
++ struct ieee80211_ops *hw_ops)
++{
++ struct iwl_priv *priv;
++
++ /* mac80211 allocates memory for this device instance, including
++ * space for this driver's private structure */
++ struct ieee80211_hw *hw =
++ ieee80211_alloc_hw(sizeof(struct iwl_priv), hw_ops);
++ if (hw == NULL) {
++ IWL_ERROR("Can not allocate network device\n");
++ goto out;
++ }
++
++ priv = hw->priv;
++ priv->hw = hw;
++
++out:
++ return hw;
++}
++EXPORT_SYMBOL(iwl_alloc_all);
++
++/**
++ * iwlcore_clear_stations_table - Clear the driver's station table
++ *
++ * NOTE: This does not clear or otherwise alter the device's station table.
++ */
++void iwlcore_clear_stations_table(struct iwl_priv *priv)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&priv->sta_lock, flags);
++
++ priv->num_stations = 0;
++ memset(priv->stations, 0, sizeof(priv->stations));
++
++ spin_unlock_irqrestore(&priv->sta_lock, flags);
++}
++EXPORT_SYMBOL(iwlcore_clear_stations_table);
++
++void iwlcore_reset_qos(struct iwl_priv *priv)
++{
++ u16 cw_min = 15;
++ u16 cw_max = 1023;
++ u8 aifs = 2;
++ u8 is_legacy = 0;
++ unsigned long flags;
++ int i;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ priv->qos_data.qos_active = 0;
++
++ if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) {
++ if (priv->qos_data.qos_enable)
++ priv->qos_data.qos_active = 1;
++ if (!(priv->active_rate & 0xfff0)) {
++ cw_min = 31;
++ is_legacy = 1;
++ }
++ } else if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
++ if (priv->qos_data.qos_enable)
++ priv->qos_data.qos_active = 1;
++ } else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) {
++ cw_min = 31;
++ is_legacy = 1;
++ }
++
++ if (priv->qos_data.qos_active)
++ aifs = 3;
++
++ priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min);
++ priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max);
++ priv->qos_data.def_qos_parm.ac[0].aifsn = aifs;
++ priv->qos_data.def_qos_parm.ac[0].edca_txop = 0;
++ priv->qos_data.def_qos_parm.ac[0].reserved1 = 0;
++
++ if (priv->qos_data.qos_active) {
++ i = 1;
++ priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min);
++ priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max);
++ priv->qos_data.def_qos_parm.ac[i].aifsn = 7;
++ priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
++ priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
++
++ i = 2;
++ priv->qos_data.def_qos_parm.ac[i].cw_min =
++ cpu_to_le16((cw_min + 1) / 2 - 1);
++ priv->qos_data.def_qos_parm.ac[i].cw_max =
++ cpu_to_le16(cw_max);
++ priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
++ if (is_legacy)
++ priv->qos_data.def_qos_parm.ac[i].edca_txop =
++ cpu_to_le16(6016);
++ else
++ priv->qos_data.def_qos_parm.ac[i].edca_txop =
++ cpu_to_le16(3008);
++ priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
++
++ i = 3;
++ priv->qos_data.def_qos_parm.ac[i].cw_min =
++ cpu_to_le16((cw_min + 1) / 4 - 1);
++ priv->qos_data.def_qos_parm.ac[i].cw_max =
++ cpu_to_le16((cw_max + 1) / 2 - 1);
++ priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
++ priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
++ if (is_legacy)
++ priv->qos_data.def_qos_parm.ac[i].edca_txop =
++ cpu_to_le16(3264);
++ else
++ priv->qos_data.def_qos_parm.ac[i].edca_txop =
++ cpu_to_le16(1504);
++ } else {
++ for (i = 1; i < 4; i++) {
++ priv->qos_data.def_qos_parm.ac[i].cw_min =
++ cpu_to_le16(cw_min);
++ priv->qos_data.def_qos_parm.ac[i].cw_max =
++ cpu_to_le16(cw_max);
++ priv->qos_data.def_qos_parm.ac[i].aifsn = aifs;
++ priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
++ priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
++ }
++ }
++ IWL_DEBUG_QOS("set QoS to default \n");
++
++ spin_unlock_irqrestore(&priv->lock, flags);
++}
++EXPORT_SYMBOL(iwlcore_reset_qos);
++
++/**
++ * iwlcore_set_rxon_channel - Set the phymode and channel values in staging RXON
++ * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
++ * @channel: Any channel valid for the requested phymode
++
++ * In addition to setting the staging RXON, priv->phymode is also set.
++ *
++ * NOTE: Does not commit to the hardware; it sets appropriate bit fields
++ * in the staging RXON flag structure based on the phymode
++ */
++int iwlcore_set_rxon_channel(struct iwl_priv *priv,
++ enum ieee80211_band band,
++ u16 channel)
++{
++ if (!iwl_get_channel_info(priv, band, channel)) {
++ IWL_DEBUG_INFO("Could not set channel to %d [%d]\n",
++ channel, band);
++ return -EINVAL;
++ }
++
++ if ((le16_to_cpu(priv->staging_rxon.channel) == channel) &&
++ (priv->band == band))
++ return 0;
++
++ priv->staging_rxon.channel = cpu_to_le16(channel);
++ if (band == IEEE80211_BAND_5GHZ)
++ priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK;
++ else
++ priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
++
++ priv->band = band;
++
++ IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, band);
++
++ return 0;
++}
++EXPORT_SYMBOL(iwlcore_set_rxon_channel);
++
++static void iwlcore_init_hw(struct iwl_priv *priv)
++{
++ struct ieee80211_hw *hw = priv->hw;
++ hw->rate_control_algorithm = "iwl-4965-rs";
++
++ /* Tell mac80211 and its clients (e.g. Wireless Extensions)
++ * the range of signal quality values that we'll provide.
++ * Negative values for level/noise indicate that we'll provide dBm.
++ * For WE, at least, non-0 values here *enable* display of values
++ * in app (iwconfig). */
++ hw->max_rssi = -20; /* signal level, negative indicates dBm */
++ hw->max_noise = -20; /* noise level, negative indicates dBm */
++ hw->max_signal = 100; /* link quality indication (%) */
++
++ /* Tell mac80211 our Tx characteristics */
++ hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
++
++ /* Default value; 4 EDCA QOS priorities */
++ hw->queues = 4;
++#ifdef CONFIG_IWL4965_HT
++ /* Enhanced value; more queues, to support 11n aggregation */
++ hw->queues = 16;
++#endif /* CONFIG_IWL4965_HT */
++}
++
++int iwl_setup(struct iwl_priv *priv)
++{
++ int ret = 0;
++ iwlcore_init_hw(priv);
++ ret = priv->cfg->ops->lib->init_drv(priv);
++ return ret;
++}
++EXPORT_SYMBOL(iwl_setup);
++
++/* Low level driver call this function to update iwlcore with
++ * driver status.
++ */
++int iwlcore_low_level_notify(struct iwl_priv *priv,
++ enum iwlcore_card_notify notify)
++{
++ int ret;
++ switch (notify) {
++ case IWLCORE_INIT_EVT:
++ ret = iwl_rfkill_init(priv);
++ if (ret)
++ IWL_ERROR("Unable to initialize RFKILL system. "
++ "Ignoring error: %d\n", ret);
++ break;
++ case IWLCORE_START_EVT:
++ break;
++ case IWLCORE_STOP_EVT:
++ break;
++ case IWLCORE_REMOVE_EVT:
++ iwl_rfkill_unregister(priv);
++ break;
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL(iwlcore_low_level_notify);
++
++int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags)
++{
++ u32 stat_flags = 0;
++ struct iwl_host_cmd cmd = {
++ .id = REPLY_STATISTICS_CMD,
++ .meta.flags = flags,
++ .len = sizeof(stat_flags),
++ .data = (u8 *) &stat_flags,
++ };
++ return iwl_send_cmd(priv, &cmd);
++}
++EXPORT_SYMBOL(iwl_send_statistics_request);
++
+diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
+new file mode 100644
+index 0000000..7193d97
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-core.h
+@@ -0,0 +1,246 @@
++/******************************************************************************
++ *
++ * This file is provided under a dual BSD/GPLv2 license. When using or
++ * redistributing this file, you may do so under either license.
++ *
++ * GPL LICENSE SUMMARY
++ *
++ * Copyright(c) 2008 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
++ * USA
++ *
++ * The full GNU General Public License is included in this distribution
++ * in the file called LICENSE.GPL.
++ *
++ * Contact Information:
++ * Tomas Winkler <tomas.winkler at intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ * BSD LICENSE
++ *
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * * Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ * * Neither the name Intel Corporation nor the names of its
++ * contributors may be used to endorse or promote products derived
++ * from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *****************************************************************************/
++
++#ifndef __iwl_core_h__
++#define __iwl_core_h__
++
++/************************
++ * forward declarations *
++ ************************/
++struct iwl_host_cmd;
++struct iwl_cmd;
++
++
++#define IWLWIFI_VERSION "1.2.26k"
++#define DRV_COPYRIGHT "Copyright(c) 2003-2008 Intel Corporation"
++
++#define IWL_PCI_DEVICE(dev, subdev, cfg) \
++ .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \
++ .subvendor = PCI_ANY_ID, .subdevice = (subdev), \
++ .driver_data = (kernel_ulong_t)&(cfg)
++
++#define IWL_SKU_G 0x1
++#define IWL_SKU_A 0x2
++#define IWL_SKU_N 0x8
++
++struct iwl_hcmd_ops {
++ int (*rxon_assoc)(struct iwl_priv *priv);
++};
++struct iwl_hcmd_utils_ops {
++ int (*enqueue_hcmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
++};
++
++struct iwl_lib_ops {
++ /* iwlwifi driver (priv) init */
++ int (*init_drv)(struct iwl_priv *priv);
++ /* set hw dependant perameters */
++ int (*set_hw_params)(struct iwl_priv *priv);
++
++ void (*txq_update_byte_cnt_tbl)(struct iwl_priv *priv,
++ struct iwl4965_tx_queue *txq,
++ u16 byte_cnt);
++ /* nic init */
++ int (*hw_nic_init)(struct iwl_priv *priv);
++ /* alive notification */
++ int (*alive_notify)(struct iwl_priv *priv);
++ /* check validity of rtc data address */
++ int (*is_valid_rtc_data_addr)(u32 addr);
++ /* 1st ucode load */
++ int (*load_ucode)(struct iwl_priv *priv);
++ /* rfkill */
++ void (*radio_kill_sw)(struct iwl_priv *priv, int disable_radio);
++ /* eeprom operations (as defined in iwl-eeprom.h) */
++ struct iwl_eeprom_ops eeprom_ops;
++};
++
++struct iwl_ops {
++ const struct iwl_lib_ops *lib;
++ const struct iwl_hcmd_ops *hcmd;
++ const struct iwl_hcmd_utils_ops *utils;
++};
++
++struct iwl_mod_params {
++ int disable; /* def: 0 = enable radio */
++ int sw_crypto; /* def: 0 = using hardware encryption */
++ int debug; /* def: 0 = minimal debug log messages */
++ int disable_hw_scan; /* def: 0 = use h/w scan */
++ int num_of_queues; /* def: HW dependent */
++ int enable_qos; /* def: 1 = use quality of service */
++ int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */
++ int antenna; /* def: 0 = both antennas (use diversity) */
++};
++
++struct iwl_cfg {
++ const char *name;
++ const char *fw_name;
++ unsigned int sku;
++ const struct iwl_ops *ops;
++ const struct iwl_mod_params *mod_params;
++};
++
++/***************************
++ * L i b *
++ ***************************/
++
++struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
++ struct ieee80211_ops *hw_ops);
++
++void iwlcore_clear_stations_table(struct iwl_priv *priv);
++void iwlcore_reset_qos(struct iwl_priv *priv);
++int iwlcore_set_rxon_channel(struct iwl_priv *priv,
++ enum ieee80211_band band,
++ u16 channel);
++
++int iwl_setup(struct iwl_priv *priv);
++
++/*****************************************************
++ * S e n d i n g H o s t C o m m a n d s *
++ *****************************************************/
++
++const char *get_cmd_string(u8 cmd);
++int __must_check iwl_send_cmd_sync(struct iwl_priv *priv,
++ struct iwl_host_cmd *cmd);
++int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
++int __must_check iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id,
++ u16 len, const void *data);
++int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,
++ const void *data,
++ int (*callback)(struct iwl_priv *priv,
++ struct iwl_cmd *cmd,
++ struct sk_buff *skb));
++/*************** DRIVER STATUS FUNCTIONS *****/
++
++#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
++#define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */
++#define STATUS_INT_ENABLED 2
++#define STATUS_RF_KILL_HW 3
++#define STATUS_RF_KILL_SW 4
++#define STATUS_INIT 5
++#define STATUS_ALIVE 6
++#define STATUS_READY 7
++#define STATUS_TEMPERATURE 8
++#define STATUS_GEO_CONFIGURED 9
++#define STATUS_EXIT_PENDING 10
++#define STATUS_IN_SUSPEND 11
++#define STATUS_STATISTICS 12
++#define STATUS_SCANNING 13
++#define STATUS_SCAN_ABORTING 14
++#define STATUS_SCAN_HW 15
++#define STATUS_POWER_PMI 16
++#define STATUS_FW_ERROR 17
++#define STATUS_CONF_PENDING 18
++
++
++static inline int iwl_is_ready(struct iwl_priv *priv)
++{
++ /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
++ * set but EXIT_PENDING is not */
++ return test_bit(STATUS_READY, &priv->status) &&
++ test_bit(STATUS_GEO_CONFIGURED, &priv->status) &&
++ !test_bit(STATUS_EXIT_PENDING, &priv->status);
++}
++
++static inline int iwl_is_alive(struct iwl_priv *priv)
++{
++ return test_bit(STATUS_ALIVE, &priv->status);
++}
++
++static inline int iwl_is_init(struct iwl_priv *priv)
++{
++ return test_bit(STATUS_INIT, &priv->status);
++}
++
++static inline int iwl_is_rfkill(struct iwl_priv *priv)
++{
++ return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
++ test_bit(STATUS_RF_KILL_SW, &priv->status);
++}
++
++static inline int iwl_is_ready_rf(struct iwl_priv *priv)
++{
++
++ if (iwl_is_rfkill(priv))
++ return 0;
++
++ return iwl_is_ready(priv);
++}
++
++
++enum iwlcore_card_notify {
++ IWLCORE_INIT_EVT = 0,
++ IWLCORE_START_EVT = 1,
++ IWLCORE_STOP_EVT = 2,
++ IWLCORE_REMOVE_EVT = 3,
++};
++
++int iwlcore_low_level_notify(struct iwl_priv *priv,
++ enum iwlcore_card_notify notify);
++extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags);
++int iwl_send_lq_cmd(struct iwl_priv *priv,
++ struct iwl_link_quality_cmd *lq, u8 flags);
++
++static inline int iwl_send_rxon_assoc(struct iwl_priv *priv)
++{
++ return priv->cfg->ops->hcmd->rxon_assoc(priv);
++}
++
++#endif /* __iwl_core_h__ */
+diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
+new file mode 100644
+index 0000000..1272579
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
+@@ -0,0 +1,265 @@
++/******************************************************************************
++ *
++ * This file is provided under a dual BSD/GPLv2 license. When using or
++ * redistributing this file, you may do so under either license.
++ *
++ * GPL LICENSE SUMMARY
++ *
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
++ * USA
++ *
++ * The full GNU General Public License is included in this distribution
++ * in the file called LICENSE.GPL.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ * BSD LICENSE
++ *
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * * Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ * * Neither the name Intel Corporation nor the names of its
++ * contributors may be used to endorse or promote products derived
++ * from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ *****************************************************************************/
++/*=== CSR (control and status registers) ===*/
++#define CSR_BASE (0x000)
++
++#define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */
++#define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */
++#define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */
++#define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */
++#define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/
++#define CSR_GPIO_IN (CSR_BASE+0x018) /* read external chip pins */
++#define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/
++#define CSR_GP_CNTRL (CSR_BASE+0x024)
++
++/*
++ * Hardware revision info
++ * Bit fields:
++ * 31-8: Reserved
++ * 7-4: Type of device: 0x0 = 4965, 0xd = 3945
++ * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D
++ * 1-0: "Dash" value, as in A-1, etc.
++ *
++ * NOTE: Revision step affects calculation of CCK txpower for 4965.
++ */
++#define CSR_HW_REV (CSR_BASE+0x028)
++
++/* EEPROM reads */
++#define CSR_EEPROM_REG (CSR_BASE+0x02c)
++#define CSR_EEPROM_GP (CSR_BASE+0x030)
++#define CSR_GP_UCODE (CSR_BASE+0x044)
++#define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054)
++#define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058)
++#define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c)
++#define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060)
++#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)
++#define CSR_LED_REG (CSR_BASE+0x094)
++
++/* Analog phase-lock-loop configuration (3945 only)
++ * Set bit 24. */
++#define CSR_ANA_PLL_CFG (CSR_BASE+0x20c)
++/*
++ * Indicates hardware rev, to determine CCK backoff for txpower calculation.
++ * Bit fields:
++ * 3-2: 0 = A, 1 = B, 2 = C, 3 = D step
++ */
++#define CSR_HW_REV_WA_REG (CSR_BASE+0x22C)
++
++/* Bits for CSR_HW_IF_CONFIG_REG */
++#define CSR49_HW_IF_CONFIG_REG_BIT_4965_R (0x00000010)
++#define CSR49_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x00000C00)
++#define CSR49_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100)
++#define CSR49_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200)
++
++#define CSR39_HW_IF_CONFIG_REG_BIT_3945_MB (0x00000100)
++#define CSR39_HW_IF_CONFIG_REG_BIT_3945_MM (0x00000200)
++#define CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC (0x00000400)
++#define CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE (0x00000800)
++#define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A (0x00000000)
++#define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B (0x00001000)
++
++#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000)
++
++/* interrupt flags in INTA, set by uCode or hardware (e.g. dma),
++ * acknowledged (reset) by host writing "1" to flagged bits. */
++#define CSR_INT_BIT_FH_RX (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */
++#define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */
++#define CSR_INT_BIT_DNLD (1 << 28) /* uCode Download */
++#define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */
++#define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */
++#define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */
++#define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */
++#define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */
++#define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses, 3945 */
++#define CSR_INT_BIT_WAKEUP (1 << 1) /* NIC controller waking up (pwr mgmt) */
++#define CSR_INT_BIT_ALIVE (1 << 0) /* uCode interrupts once it initializes */
++
++#define CSR_INI_SET_MASK (CSR_INT_BIT_FH_RX | \
++ CSR_INT_BIT_HW_ERR | \
++ CSR_INT_BIT_FH_TX | \
++ CSR_INT_BIT_SW_ERR | \
++ CSR_INT_BIT_RF_KILL | \
++ CSR_INT_BIT_SW_RX | \
++ CSR_INT_BIT_WAKEUP | \
++ CSR_INT_BIT_ALIVE)
++
++/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */
++#define CSR_FH_INT_BIT_ERR (1 << 31) /* Error */
++#define CSR_FH_INT_BIT_HI_PRIOR (1 << 30) /* High priority Rx, bypass coalescing */
++#define CSR39_FH_INT_BIT_RX_CHNL2 (1 << 18) /* Rx channel 2 (3945 only) */
++#define CSR_FH_INT_BIT_RX_CHNL1 (1 << 17) /* Rx channel 1 */
++#define CSR_FH_INT_BIT_RX_CHNL0 (1 << 16) /* Rx channel 0 */
++#define CSR39_FH_INT_BIT_TX_CHNL6 (1 << 6) /* Tx channel 6 (3945 only) */
++#define CSR_FH_INT_BIT_TX_CHNL1 (1 << 1) /* Tx channel 1 */
++#define CSR_FH_INT_BIT_TX_CHNL0 (1 << 0) /* Tx channel 0 */
++
++#define CSR39_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \
++ CSR39_FH_INT_BIT_RX_CHNL2 | \
++ CSR_FH_INT_BIT_RX_CHNL1 | \
++ CSR_FH_INT_BIT_RX_CHNL0)
++
++
++#define CSR39_FH_INT_TX_MASK (CSR39_FH_INT_BIT_TX_CHNL6 | \
++ CSR_FH_INT_BIT_TX_CHNL1 | \
++ CSR_FH_INT_BIT_TX_CHNL0)
++
++#define CSR49_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \
++ CSR_FH_INT_BIT_RX_CHNL1 | \
++ CSR_FH_INT_BIT_RX_CHNL0)
++
++#define CSR49_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL1 | \
++ CSR_FH_INT_BIT_TX_CHNL0)
++
++
++/* RESET */
++#define CSR_RESET_REG_FLAG_NEVO_RESET (0x00000001)
++#define CSR_RESET_REG_FLAG_FORCE_NMI (0x00000002)
++#define CSR_RESET_REG_FLAG_SW_RESET (0x00000080)
++#define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100)
++#define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200)
++
++/* GP (general purpose) CONTROL */
++#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001)
++#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004)
++#define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008)
++#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010)
++
++#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001)
++
++#define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE (0x07000000)
++#define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE (0x04000000)
++#define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW (0x08000000)
++
++
++/* EEPROM REG */
++#define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001)
++#define CSR_EEPROM_REG_BIT_CMD (0x00000002)
++
++/* EEPROM GP */
++#define CSR_EEPROM_GP_VALID_MSK (0x00000006)
++#define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000)
++#define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180)
++
++/* UCODE DRV GP */
++#define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP (0x00000001)
++#define CSR_UCODE_SW_BIT_RFKILL (0x00000002)
++#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004)
++#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008)
++
++/* GPIO */
++#define CSR_GPIO_IN_BIT_AUX_POWER (0x00000200)
++#define CSR_GPIO_IN_VAL_VAUX_PWR_SRC (0x00000000)
++#define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC CSR_GPIO_IN_BIT_AUX_POWER
++
++/* GI Chicken Bits */
++#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000)
++#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000)
++
++/* LED */
++#define CSR_LED_BSM_CTRL_MSK (0xFFFFFFDF)
++#define CSR_LED_REG_TRUN_ON (0x78)
++#define CSR_LED_REG_TRUN_OFF (0x38)
++
++/*=== HBUS (Host-side Bus) ===*/
++#define HBUS_BASE (0x400)
++/*
++ * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM
++ * structures, error log, event log, verifying uCode load).
++ * First write to address register, then read from or write to data register
++ * to complete the job. Once the address register is set up, accesses to
++ * data registers auto-increment the address by one dword.
++ * Bit usage for address registers (read or write):
++ * 0-31: memory address within device
++ */
++#define HBUS_TARG_MEM_RADDR (HBUS_BASE+0x00c)
++#define HBUS_TARG_MEM_WADDR (HBUS_BASE+0x010)
++#define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018)
++#define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c)
++
++/*
++ * Registers for accessing device's internal peripheral registers
++ * (e.g. SCD, BSM, etc.). First write to address register,
++ * then read from or write to data register to complete the job.
++ * Bit usage for address registers (read or write):
++ * 0-15: register address (offset) within device
++ * 24-25: (# bytes - 1) to read or write (e.g. 3 for dword)
++ */
++#define HBUS_TARG_PRPH_WADDR (HBUS_BASE+0x044)
++#define HBUS_TARG_PRPH_RADDR (HBUS_BASE+0x048)
++#define HBUS_TARG_PRPH_WDAT (HBUS_BASE+0x04c)
++#define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050)
++
++/*
++ * Per-Tx-queue write pointer (index, really!) (3945 and 4965).
++ * Indicates index to next TFD that driver will fill (1 past latest filled).
++ * Bit usage:
++ * 0-7: queue write index
++ * 11-8: queue selector
++ */
++#define HBUS_TARG_WRPTR (HBUS_BASE+0x060)
++#define HBUS_TARG_MBX_C (HBUS_BASE+0x030)
++
++#define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED (0x00000004)
++
++
++
+diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
+new file mode 100644
+index 0000000..c60724c
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
+@@ -0,0 +1,197 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
++ *
++ * Portions of this file are derived from the ipw3945 project.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called LICENSE.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ *****************************************************************************/
++
++#ifndef __iwl_debug_h__
++#define __iwl_debug_h__
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++extern u32 iwl_debug_level;
++#define IWL_DEBUG(level, fmt, args...) \
++do { if (iwl_debug_level & (level)) \
++ printk(KERN_ERR DRV_NAME": %c %s " fmt, \
++ in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
++
++#define IWL_DEBUG_LIMIT(level, fmt, args...) \
++do { if ((iwl_debug_level & (level)) && net_ratelimit()) \
++ printk(KERN_ERR DRV_NAME": %c %s " fmt, \
++ in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
++
++static inline void iwl_print_hex_dump(int level, void *p, u32 len)
++{
++ if (!(iwl_debug_level & level))
++ return;
++
++ print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1,
++ p, len, 1);
++}
++
++#ifdef CONFIG_IWLWIFI_DEBUGFS
++struct iwl_debugfs {
++ const char *name;
++ struct dentry *dir_drv;
++ struct dentry *dir_data;
++ struct dir_data_files{
++ struct dentry *file_sram;
++ struct dentry *file_stations;
++ struct dentry *file_rx_statistics;
++ struct dentry *file_tx_statistics;
++ } dbgfs_data_files;
++ u32 sram_offset;
++ u32 sram_len;
++};
++
++int iwl_dbgfs_register(struct iwl_priv *priv, const char *name);
++void iwl_dbgfs_unregister(struct iwl_priv *priv);
++#endif
++
++#else
++static inline void IWL_DEBUG(int level, const char *fmt, ...)
++{
++}
++static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...)
++{
++}
++static inline void iwl_print_hex_dump(int level, void *p, u32 len)
++{
++}
++#endif /* CONFIG_IWLWIFI_DEBUG */
++
++
++
++#ifndef CONFIG_IWLWIFI_DEBUGFS
++static inline int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
++{
++ return 0;
++}
++static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
++{
++}
++#endif /* CONFIG_IWLWIFI_DEBUGFS */
++
++/*
++ * To use the debug system;
++ *
++ * If you are defining a new debug classification, simply add it to the #define
++ * list here in the form of:
++ *
++ * #define IWL_DL_xxxx VALUE
++ *
++ * shifting value to the left one bit from the previous entry. xxxx should be
++ * the name of the classification (for example, WEP)
++ *
++ * You then need to either add a IWL_xxxx_DEBUG() macro definition for your
++ * classification, or use IWL_DEBUG(IWL_DL_xxxx, ...) whenever you want
++ * to send output to that classification.
++ *
++ * To add your debug level to the list of levels seen when you perform
++ *
++ * % cat /proc/net/iwl/debug_level
++ *
++ * you simply need to add your entry to the iwl_debug_levels array.
++ *
++ * If you do not see debug_level in /proc/net/iwl then you do not have
++ * CONFIG_IWLWIFI_DEBUG defined in your kernel configuration
++ *
++ */
++
++#define IWL_DL_INFO (1 << 0)
++#define IWL_DL_MAC80211 (1 << 1)
++#define IWL_DL_HOST_COMMAND (1 << 2)
++#define IWL_DL_STATE (1 << 3)
++
++#define IWL_DL_RADIO (1 << 7)
++#define IWL_DL_POWER (1 << 8)
++#define IWL_DL_TEMP (1 << 9)
++
++#define IWL_DL_NOTIF (1 << 10)
++#define IWL_DL_SCAN (1 << 11)
++#define IWL_DL_ASSOC (1 << 12)
++#define IWL_DL_DROP (1 << 13)
++
++#define IWL_DL_TXPOWER (1 << 14)
++
++#define IWL_DL_AP (1 << 15)
++
++#define IWL_DL_FW (1 << 16)
++#define IWL_DL_RF_KILL (1 << 17)
++#define IWL_DL_FW_ERRORS (1 << 18)
++
++#define IWL_DL_LED (1 << 19)
++
++#define IWL_DL_RATE (1 << 20)
++
++#define IWL_DL_CALIB (1 << 21)
++#define IWL_DL_WEP (1 << 22)
++#define IWL_DL_TX (1 << 23)
++#define IWL_DL_RX (1 << 24)
++#define IWL_DL_ISR (1 << 25)
++#define IWL_DL_HT (1 << 26)
++#define IWL_DL_IO (1 << 27)
++#define IWL_DL_11H (1 << 28)
++
++#define IWL_DL_STATS (1 << 29)
++#define IWL_DL_TX_REPLY (1 << 30)
++#define IWL_DL_QOS (1 << 31)
++
++#define IWL_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a)
++#define IWL_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a)
++#define IWL_DEBUG_INFO(f, a...) IWL_DEBUG(IWL_DL_INFO, f, ## a)
++
++#define IWL_DEBUG_MAC80211(f, a...) IWL_DEBUG(IWL_DL_MAC80211, f, ## a)
++#define IWL_DEBUG_TEMP(f, a...) IWL_DEBUG(IWL_DL_TEMP, f, ## a)
++#define IWL_DEBUG_SCAN(f, a...) IWL_DEBUG(IWL_DL_SCAN, f, ## a)
++#define IWL_DEBUG_RX(f, a...) IWL_DEBUG(IWL_DL_RX, f, ## a)
++#define IWL_DEBUG_TX(f, a...) IWL_DEBUG(IWL_DL_TX, f, ## a)
++#define IWL_DEBUG_ISR(f, a...) IWL_DEBUG(IWL_DL_ISR, f, ## a)
++#define IWL_DEBUG_LED(f, a...) IWL_DEBUG(IWL_DL_LED, f, ## a)
++#define IWL_DEBUG_WEP(f, a...) IWL_DEBUG(IWL_DL_WEP, f, ## a)
++#define IWL_DEBUG_HC(f, a...) IWL_DEBUG(IWL_DL_HOST_COMMAND, f, ## a)
++#define IWL_DEBUG_CALIB(f, a...) IWL_DEBUG(IWL_DL_CALIB, f, ## a)
++#define IWL_DEBUG_FW(f, a...) IWL_DEBUG(IWL_DL_FW, f, ## a)
++#define IWL_DEBUG_RF_KILL(f, a...) IWL_DEBUG(IWL_DL_RF_KILL, f, ## a)
++#define IWL_DEBUG_DROP(f, a...) IWL_DEBUG(IWL_DL_DROP, f, ## a)
++#define IWL_DEBUG_DROP_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_DROP, f, ## a)
++#define IWL_DEBUG_AP(f, a...) IWL_DEBUG(IWL_DL_AP, f, ## a)
++#define IWL_DEBUG_TXPOWER(f, a...) IWL_DEBUG(IWL_DL_TXPOWER, f, ## a)
++#define IWL_DEBUG_IO(f, a...) IWL_DEBUG(IWL_DL_IO, f, ## a)
++#define IWL_DEBUG_RATE(f, a...) IWL_DEBUG(IWL_DL_RATE, f, ## a)
++#define IWL_DEBUG_RATE_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_RATE, f, ## a)
++#define IWL_DEBUG_NOTIF(f, a...) IWL_DEBUG(IWL_DL_NOTIF, f, ## a)
++#define IWL_DEBUG_ASSOC(f, a...) IWL_DEBUG(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
++#define IWL_DEBUG_ASSOC_LIMIT(f, a...) \
++ IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
++#define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a)
++#define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a)
++#define IWL_DEBUG_STATS_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_STATS, f, ## a)
++#define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a)
++#define IWL_DEBUG_QOS(f, a...) IWL_DEBUG(IWL_DL_QOS, f, ## a)
++#define IWL_DEBUG_RADIO(f, a...) IWL_DEBUG(IWL_DL_RADIO, f, ## a)
++#define IWL_DEBUG_POWER(f, a...) IWL_DEBUG(IWL_DL_POWER, f, ## a)
++#define IWL_DEBUG_11H(f, a...) IWL_DEBUG(IWL_DL_11H, f, ## a)
++
++#endif
+diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+new file mode 100644
+index 0000000..9a30e1d
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+@@ -0,0 +1,341 @@
++/******************************************************************************
++ *
++ * GPL LICENSE SUMMARY
++ *
++ * Copyright(c) 2008 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
++ * USA
++ *
++ * The full GNU General Public License is included in this distribution
++ * in the file called LICENSE.GPL.
++ *
++ * Contact Information:
++ * Tomas Winkler <tomas.winkler at intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *****************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/debugfs.h>
++
++#include <linux/ieee80211.h>
++#include <net/mac80211.h>
++
++
++#include "iwl-4965.h"
++#include "iwl-debug.h"
++#include "iwl-core.h"
++#include "iwl-io.h"
++
++
++/* create and remove of files */
++#define DEBUGFS_ADD_DIR(name, parent) do { \
++ dbgfs->dir_##name = debugfs_create_dir(#name, parent); \
++ if (!(dbgfs->dir_##name)) \
++ goto err; \
++} while (0)
++
++#define DEBUGFS_ADD_FILE(name, parent) do { \
++ dbgfs->dbgfs_##parent##_files.file_##name = \
++ debugfs_create_file(#name, 0644, dbgfs->dir_##parent, priv, \
++ &iwl_dbgfs_##name##_ops); \
++ if (!(dbgfs->dbgfs_##parent##_files.file_##name)) \
++ goto err; \
++} while (0)
++
++#define DEBUGFS_REMOVE(name) do { \
++ debugfs_remove(name); \
++ name = NULL; \
++} while (0);
++
++/* file operation */
++#define DEBUGFS_READ_FUNC(name) \
++static ssize_t iwl_dbgfs_##name##_read(struct file *file, \
++ char __user *user_buf, \
++ size_t count, loff_t *ppos);
++
++#define DEBUGFS_WRITE_FUNC(name) \
++static ssize_t iwl_dbgfs_##name##_write(struct file *file, \
++ const char __user *user_buf, \
++ size_t count, loff_t *ppos);
++
++
++static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file)
++{
++ file->private_data = inode->i_private;
++ return 0;
++}
++
++#define DEBUGFS_READ_FILE_OPS(name) \
++ DEBUGFS_READ_FUNC(name); \
++static const struct file_operations iwl_dbgfs_##name##_ops = { \
++ .read = iwl_dbgfs_##name##_read, \
++ .open = iwl_dbgfs_open_file_generic, \
++};
++
++#define DEBUGFS_READ_WRITE_FILE_OPS(name) \
++ DEBUGFS_READ_FUNC(name); \
++ DEBUGFS_WRITE_FUNC(name); \
++static const struct file_operations iwl_dbgfs_##name##_ops = { \
++ .write = iwl_dbgfs_##name##_write, \
++ .read = iwl_dbgfs_##name##_read, \
++ .open = iwl_dbgfs_open_file_generic, \
++};
++
++
++static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file,
++ char __user *user_buf,
++ size_t count, loff_t *ppos) {
++
++ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
++ char buf[256];
++ int pos = 0;
++ const size_t bufsz = sizeof(buf);
++
++ pos += scnprintf(buf + pos, bufsz - pos, "mgmt: %u\n",
++ priv->tx_stats[0].cnt);
++ pos += scnprintf(buf + pos, bufsz - pos, "ctrl: %u\n",
++ priv->tx_stats[1].cnt);
++ pos += scnprintf(buf + pos, bufsz - pos, "data: %u\n",
++ priv->tx_stats[2].cnt);
++
++ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
++}
++
++static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file,
++ char __user *user_buf,
++ size_t count, loff_t *ppos) {
++
++ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
++ char buf[256];
++ int pos = 0;
++ const size_t bufsz = sizeof(buf);
++
++ pos += scnprintf(buf + pos, bufsz - pos, "mgmt: %u\n",
++ priv->rx_stats[0].cnt);
++ pos += scnprintf(buf + pos, bufsz - pos, "ctrl: %u\n",
++ priv->rx_stats[1].cnt);
++ pos += scnprintf(buf + pos, bufsz - pos, "data: %u\n",
++ priv->rx_stats[2].cnt);
++
++ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
++}
++
++#define BYTE1_MASK 0x000000ff;
++#define BYTE2_MASK 0x0000ffff;
++#define BYTE3_MASK 0x00ffffff;
++static ssize_t iwl_dbgfs_sram_read(struct file *file,
++ char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ u32 val;
++ char buf[1024];
++ ssize_t ret;
++ int i;
++ int pos = 0;
++ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
++ const size_t bufsz = sizeof(buf);
++
++ printk(KERN_DEBUG "offset is: 0x%x\tlen is: 0x%x\n",
++ priv->dbgfs->sram_offset, priv->dbgfs->sram_len);
++
++ iwl_grab_nic_access(priv);
++ for (i = priv->dbgfs->sram_len; i > 0; i -= 4) {
++ val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \
++ priv->dbgfs->sram_len - i);
++ if (i < 4) {
++ switch (i) {
++ case 1:
++ val &= BYTE1_MASK;
++ break;
++ case 2:
++ val &= BYTE2_MASK;
++ break;
++ case 3:
++ val &= BYTE3_MASK;
++ break;
++ }
++ }
++ pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
++ }
++ pos += scnprintf(buf + pos, bufsz - pos, "\n");
++ iwl_release_nic_access(priv);
++
++ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
++ return ret;
++}
++
++static ssize_t iwl_dbgfs_sram_write(struct file *file,
++ const char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct iwl_priv *priv = file->private_data;
++ char buf[64];
++ int buf_size;
++ u32 offset, len;
++
++ memset(buf, 0, sizeof(buf));
++ buf_size = min(count, sizeof(buf) - 1);
++ if (copy_from_user(buf, user_buf, buf_size))
++ return -EFAULT;
++
++ if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
++ priv->dbgfs->sram_offset = offset;
++ priv->dbgfs->sram_len = len;
++ } else {
++ priv->dbgfs->sram_offset = 0;
++ priv->dbgfs->sram_len = 0;
++ }
++
++ return count;
++}
++
++static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
++ struct iwl4965_station_entry *station;
++ int max_sta = priv->hw_params.max_stations;
++ char *buf;
++ int i, j, pos = 0;
++ ssize_t ret;
++ /* Add 30 for initial string */
++ const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations);
++ DECLARE_MAC_BUF(mac);
++
++ buf = kmalloc(bufsz, GFP_KERNEL);
++ if(!buf)
++ return -ENOMEM;
++
++ pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
++ priv->num_stations);
++
++ for (i = 0; i < max_sta; i++) {
++ station = &priv->stations[i];
++ if (station->used) {
++ pos += scnprintf(buf + pos, bufsz - pos,
++ "station %d:\ngeneral data:\n", i+1);
++ print_mac(mac, station->sta.sta.addr);
++ pos += scnprintf(buf + pos, bufsz - pos, "id: %u\n",
++ station->sta.sta.sta_id);
++ pos += scnprintf(buf + pos, bufsz - pos, "mode: %u\n",
++ station->sta.mode);
++ pos += scnprintf(buf + pos, bufsz - pos,
++ "flags: 0x%x\n",
++ station->sta.station_flags_msk);
++ pos += scnprintf(buf + pos, bufsz - pos,
++ "ps_status: %u\n", station->ps_status);
++ pos += scnprintf(buf + pos, bufsz - pos, "tid data:\n");
++ pos += scnprintf(buf + pos, bufsz - pos,
++ "seq_num\t\ttxq_id");
++#ifdef CONFIG_IWL4965_HT
++ pos += scnprintf(buf + pos, bufsz - pos,
++ "\tframe_count\twait_for_ba\t");
++ pos += scnprintf(buf + pos, bufsz - pos,
++ "start_idx\tbitmap0\t");
++ pos += scnprintf(buf + pos, bufsz - pos,
++ "bitmap1\trate_n_flags");
++#endif
++ pos += scnprintf(buf + pos, bufsz - pos, "\n");
++
++ for (j = 0; j < MAX_TID_COUNT; j++) {
++ pos += scnprintf(buf + pos, bufsz - pos,
++ "[%d]:\t\t%u", j,
++ station->tid[j].seq_number);
++#ifdef CONFIG_IWL4965_HT
++ pos += scnprintf(buf + pos, bufsz - pos,
++ "\t%u\t\t%u\t\t%u\t\t",
++ station->tid[j].agg.txq_id,
++ station->tid[j].agg.frame_count,
++ station->tid[j].agg.wait_for_ba);
++ pos += scnprintf(buf + pos, bufsz - pos,
++ "%u\t%llu\t%u",
++ station->tid[j].agg.start_idx,
++ (unsigned long long)station->tid[j].agg.bitmap,
++ station->tid[j].agg.rate_n_flags);
++#endif
++ pos += scnprintf(buf + pos, bufsz - pos, "\n");
++ }
++ pos += scnprintf(buf + pos, bufsz - pos, "\n");
++ }
++ }
++
++ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
++ kfree(buf);
++ return ret;
++}
++
++
++DEBUGFS_READ_WRITE_FILE_OPS(sram);
++DEBUGFS_READ_FILE_OPS(stations);
++DEBUGFS_READ_FILE_OPS(rx_statistics);
++DEBUGFS_READ_FILE_OPS(tx_statistics);
++
++/*
++ * Create the debugfs files and directories
++ *
++ */
++int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
++{
++ struct iwl_debugfs *dbgfs;
++
++ dbgfs = kzalloc(sizeof(struct iwl_debugfs), GFP_KERNEL);
++ if (!dbgfs) {
++ goto err;
++ }
++
++ priv->dbgfs = dbgfs;
++ dbgfs->name = name;
++ dbgfs->dir_drv = debugfs_create_dir(name, NULL);
++ if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)){
++ goto err;
++ }
++
++ DEBUGFS_ADD_DIR(data, dbgfs->dir_drv);
++ DEBUGFS_ADD_FILE(sram, data);
++ DEBUGFS_ADD_FILE(stations, data);
++ DEBUGFS_ADD_FILE(rx_statistics, data);
++ DEBUGFS_ADD_FILE(tx_statistics, data);
++
++ return 0;
++
++err:
++ IWL_ERROR("Can't open the debugfs directory\n");
++ iwl_dbgfs_unregister(priv);
++ return -ENOENT;
++}
++EXPORT_SYMBOL(iwl_dbgfs_register);
++
++/**
++ * Remove the debugfs files and directories
++ *
++ */
++void iwl_dbgfs_unregister(struct iwl_priv *priv)
++{
++ if (!(priv->dbgfs))
++ return;
++
++ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_rx_statistics);
++ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_tx_statistics);
++ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
++ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations);
++ DEBUGFS_REMOVE(priv->dbgfs->dir_data);
++ DEBUGFS_REMOVE(priv->dbgfs->dir_drv);
++ kfree(priv->dbgfs);
++ priv->dbgfs = NULL;
++}
++EXPORT_SYMBOL(iwl_dbgfs_unregister);
++
++
+diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+new file mode 100644
+index 0000000..a07d5dc
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+@@ -0,0 +1,561 @@
++/******************************************************************************
++ *
++ * This file is provided under a dual BSD/GPLv2 license. When using or
++ * redistributing this file, you may do so under either license.
++ *
++ * GPL LICENSE SUMMARY
++ *
++ * Copyright(c) 2008 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
++ * USA
++ *
++ * The full GNU General Public License is included in this distribution
++ * in the file called LICENSE.GPL.
++ *
++ * Contact Information:
++ * Tomas Winkler <tomas.winkler at intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ * BSD LICENSE
++ *
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * * Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ * * Neither the name Intel Corporation nor the names of its
++ * contributors may be used to endorse or promote products derived
++ * from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *****************************************************************************/
++
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/init.h>
++
++#include <net/mac80211.h>
++
++#include "iwl-4965-commands.h"
++#include "iwl-4965.h"
++#include "iwl-core.h"
++#include "iwl-debug.h"
++#include "iwl-eeprom.h"
++#include "iwl-io.h"
++
++/************************** EEPROM BANDS ****************************
++ *
++ * The iwl_eeprom_band definitions below provide the mapping from the
++ * EEPROM contents to the specific channel number supported for each
++ * band.
++ *
++ * For example, iwl_priv->eeprom.band_3_channels[4] from the band_3
++ * definition below maps to physical channel 42 in the 5.2GHz spectrum.
++ * The specific geography and calibration information for that channel
++ * is contained in the eeprom map itself.
++ *
++ * During init, we copy the eeprom information and channel map
++ * information into priv->channel_info_24/52 and priv->channel_map_24/52
++ *
++ * channel_map_24/52 provides the index in the channel_info array for a
++ * given channel. We have to have two separate maps as there is channel
++ * overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and
++ * band_2
++ *
++ * A value of 0xff stored in the channel_map indicates that the channel
++ * is not supported by the hardware at all.
++ *
++ * A value of 0xfe in the channel_map indicates that the channel is not
++ * valid for Tx with the current hardware. This means that
++ * while the system can tune and receive on a given channel, it may not
++ * be able to associate or transmit any frames on that
++ * channel. There is no corresponding channel information for that
++ * entry.
++ *
++ *********************************************************************/
++
++/* 2.4 GHz */
++const u8 iwl_eeprom_band_1[14] = {
++ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
++};
++
++/* 5.2 GHz bands */
++static const u8 iwl_eeprom_band_2[] = { /* 4915-5080MHz */
++ 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16
++};
++
++static const u8 iwl_eeprom_band_3[] = { /* 5170-5320MHz */
++ 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
++};
++
++static const u8 iwl_eeprom_band_4[] = { /* 5500-5700MHz */
++ 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
++};
++
++static const u8 iwl_eeprom_band_5[] = { /* 5725-5825MHz */
++ 145, 149, 153, 157, 161, 165
++};
++
++static const u8 iwl_eeprom_band_6[] = { /* 2.4 FAT channel */
++ 1, 2, 3, 4, 5, 6, 7
++};
++
++static const u8 iwl_eeprom_band_7[] = { /* 5.2 FAT channel */
++ 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
++};
++
++/******************************************************************************
++ *
++ * EEPROM related functions
++ *
++******************************************************************************/
++
++int iwlcore_eeprom_verify_signature(struct iwl_priv *priv)
++{
++ u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
++ if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) {
++ IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp);
++ return -ENOENT;
++ }
++ return 0;
++}
++EXPORT_SYMBOL(iwlcore_eeprom_verify_signature);
++
++/*
++ * The device's EEPROM semaphore prevents conflicts between driver and uCode
++ * when accessing the EEPROM; each access is a series of pulses to/from the
++ * EEPROM chip, not a single event, so even reads could conflict if they
++ * weren't arbitrated by the semaphore.
++ */
++int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv)
++{
++ u16 count;
++ int ret;
++
++ for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) {
++ /* Request semaphore */
++ iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
++ CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
++
++ /* See if we got it */
++ ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
++ CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
++ CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
++ EEPROM_SEM_TIMEOUT);
++ if (ret >= 0) {
++ IWL_DEBUG_IO("Acquired semaphore after %d tries.\n",
++ count+1);
++ return ret;
++ }
++ }
++
++ return ret;
++}
++EXPORT_SYMBOL(iwlcore_eeprom_acquire_semaphore);
++
++void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv)
++{
++ iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
++ CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
++
++}
++EXPORT_SYMBOL(iwlcore_eeprom_release_semaphore);
++
++
++/**
++ * iwl_eeprom_init - read EEPROM contents
++ *
++ * Load the EEPROM contents from adapter into priv->eeprom
++ *
++ * NOTE: This routine uses the non-debug IO access functions.
++ */
++int iwl_eeprom_init(struct iwl_priv *priv)
++{
++ u16 *e = (u16 *)&priv->eeprom;
++ u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
++ u32 r;
++ int sz = sizeof(priv->eeprom);
++ int ret;
++ int i;
++ u16 addr;
++
++ /* The EEPROM structure has several padding buffers within it
++ * and when adding new EEPROM maps is subject to programmer errors
++ * which may be very difficult to identify without explicitly
++ * checking the resulting size of the eeprom map. */
++ BUILD_BUG_ON(sizeof(priv->eeprom) != IWL_EEPROM_IMAGE_SIZE);
++
++ if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) {
++ IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp);
++ return -ENOENT;
++ }
++
++ /* Make sure driver (instead of uCode) is allowed to read EEPROM */
++ ret = priv->cfg->ops->lib->eeprom_ops.acquire_semaphore(priv);
++ if (ret < 0) {
++ IWL_ERROR("Failed to acquire EEPROM semaphore.\n");
++ return -ENOENT;
++ }
++
++ /* eeprom is an array of 16bit values */
++ for (addr = 0; addr < sz; addr += sizeof(u16)) {
++ _iwl_write32(priv, CSR_EEPROM_REG, addr << 1);
++ _iwl_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD);
++
++ for (i = 0; i < IWL_EEPROM_ACCESS_TIMEOUT;
++ i += IWL_EEPROM_ACCESS_DELAY) {
++ r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
++ if (r & CSR_EEPROM_REG_READ_VALID_MSK)
++ break;
++ udelay(IWL_EEPROM_ACCESS_DELAY);
++ }
++
++ if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) {
++ IWL_ERROR("Time out reading EEPROM[%d]", addr);
++ ret = -ETIMEDOUT;
++ goto done;
++ }
++ e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
++ }
++ ret = 0;
++
++done:
++ priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv);
++ return ret;
++}
++EXPORT_SYMBOL(iwl_eeprom_init);
++
++
++void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
++{
++ memcpy(mac, priv->eeprom.mac_address, 6);
++}
++EXPORT_SYMBOL(iwl_eeprom_get_mac);
++
++static void iwl_init_band_reference(const struct iwl_priv *priv,
++ int band,
++ int *eeprom_ch_count,
++ const struct iwl4965_eeprom_channel
++ **eeprom_ch_info,
++ const u8 **eeprom_ch_index)
++{
++ switch (band) {
++ case 1: /* 2.4GHz band */
++ *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1);
++ *eeprom_ch_info = priv->eeprom.band_1_channels;
++ *eeprom_ch_index = iwl_eeprom_band_1;
++ break;
++ case 2: /* 4.9GHz band */
++ *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2);
++ *eeprom_ch_info = priv->eeprom.band_2_channels;
++ *eeprom_ch_index = iwl_eeprom_band_2;
++ break;
++ case 3: /* 5.2GHz band */
++ *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3);
++ *eeprom_ch_info = priv->eeprom.band_3_channels;
++ *eeprom_ch_index = iwl_eeprom_band_3;
++ break;
++ case 4: /* 5.5GHz band */
++ *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4);
++ *eeprom_ch_info = priv->eeprom.band_4_channels;
++ *eeprom_ch_index = iwl_eeprom_band_4;
++ break;
++ case 5: /* 5.7GHz band */
++ *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5);
++ *eeprom_ch_info = priv->eeprom.band_5_channels;
++ *eeprom_ch_index = iwl_eeprom_band_5;
++ break;
++ case 6: /* 2.4GHz FAT channels */
++ *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6);
++ *eeprom_ch_info = priv->eeprom.band_24_channels;
++ *eeprom_ch_index = iwl_eeprom_band_6;
++ break;
++ case 7: /* 5 GHz FAT channels */
++ *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7);
++ *eeprom_ch_info = priv->eeprom.band_52_channels;
++ *eeprom_ch_index = iwl_eeprom_band_7;
++ break;
++ default:
++ BUG();
++ return;
++ }
++}
++
++#define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \
++ ? # x " " : "")
++
++/**
++ * iwl4965_set_fat_chan_info - Copy fat channel info into driver's priv.
++ *
++ * Does not set up a command, or touch hardware.
++ */
++static int iwl4965_set_fat_chan_info(struct iwl_priv *priv,
++ enum ieee80211_band band, u16 channel,
++ const struct iwl4965_eeprom_channel *eeprom_ch,
++ u8 fat_extension_channel)
++{
++ struct iwl_channel_info *ch_info;
++
++ ch_info = (struct iwl_channel_info *)
++ iwl_get_channel_info(priv, band, channel);
++
++ if (!is_channel_valid(ch_info))
++ return -1;
++
++ IWL_DEBUG_INFO("FAT Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x"
++ " %ddBm): Ad-Hoc %ssupported\n",
++ ch_info->channel,
++ is_channel_a_band(ch_info) ?
++ "5.2" : "2.4",
++ CHECK_AND_PRINT(IBSS),
++ CHECK_AND_PRINT(ACTIVE),
++ CHECK_AND_PRINT(RADAR),
++ CHECK_AND_PRINT(WIDE),
++ CHECK_AND_PRINT(NARROW),
++ CHECK_AND_PRINT(DFS),
++ eeprom_ch->flags,
++ eeprom_ch->max_power_avg,
++ ((eeprom_ch->flags & EEPROM_CHANNEL_IBSS)
++ && !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ?
++ "" : "not ");
++
++ ch_info->fat_eeprom = *eeprom_ch;
++ ch_info->fat_max_power_avg = eeprom_ch->max_power_avg;
++ ch_info->fat_curr_txpow = eeprom_ch->max_power_avg;
++ ch_info->fat_min_power = 0;
++ ch_info->fat_scan_power = eeprom_ch->max_power_avg;
++ ch_info->fat_flags = eeprom_ch->flags;
++ ch_info->fat_extension_channel = fat_extension_channel;
++
++ return 0;
++}
++
++#define CHECK_AND_PRINT_I(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \
++ ? # x " " : "")
++
++/**
++ * iwl_init_channel_map - Set up driver's info for all possible channels
++ */
++int iwl_init_channel_map(struct iwl_priv *priv)
++{
++ int eeprom_ch_count = 0;
++ const u8 *eeprom_ch_index = NULL;
++ const struct iwl4965_eeprom_channel *eeprom_ch_info = NULL;
++ int band, ch;
++ struct iwl_channel_info *ch_info;
++
++ if (priv->channel_count) {
++ IWL_DEBUG_INFO("Channel map already initialized.\n");
++ return 0;
++ }
++
++ if (priv->eeprom.version < 0x2f) {
++ IWL_WARNING("Unsupported EEPROM version: 0x%04X\n",
++ priv->eeprom.version);
++ return -EINVAL;
++ }
++
++ IWL_DEBUG_INFO("Initializing regulatory info from EEPROM\n");
++
++ priv->channel_count =
++ ARRAY_SIZE(iwl_eeprom_band_1) +
++ ARRAY_SIZE(iwl_eeprom_band_2) +
++ ARRAY_SIZE(iwl_eeprom_band_3) +
++ ARRAY_SIZE(iwl_eeprom_band_4) +
++ ARRAY_SIZE(iwl_eeprom_band_5);
++
++ IWL_DEBUG_INFO("Parsing data for %d channels.\n", priv->channel_count);
++
++ priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) *
++ priv->channel_count, GFP_KERNEL);
++ if (!priv->channel_info) {
++ IWL_ERROR("Could not allocate channel_info\n");
++ priv->channel_count = 0;
++ return -ENOMEM;
++ }
++
++ ch_info = priv->channel_info;
++
++ /* Loop through the 5 EEPROM bands adding them in order to the
++ * channel map we maintain (that contains additional information than
++ * what just in the EEPROM) */
++ for (band = 1; band <= 5; band++) {
++
++ iwl_init_band_reference(priv, band, &eeprom_ch_count,
++ &eeprom_ch_info, &eeprom_ch_index);
++
++ /* Loop through each band adding each of the channels */
++ for (ch = 0; ch < eeprom_ch_count; ch++) {
++ ch_info->channel = eeprom_ch_index[ch];
++ ch_info->band = (band == 1) ? IEEE80211_BAND_2GHZ :
++ IEEE80211_BAND_5GHZ;
++
++ /* permanently store EEPROM's channel regulatory flags
++ * and max power in channel info database. */
++ ch_info->eeprom = eeprom_ch_info[ch];
++
++ /* Copy the run-time flags so they are there even on
++ * invalid channels */
++ ch_info->flags = eeprom_ch_info[ch].flags;
++
++ if (!(is_channel_valid(ch_info))) {
++ IWL_DEBUG_INFO("Ch. %d Flags %x [%sGHz] - "
++ "No traffic\n",
++ ch_info->channel,
++ ch_info->flags,
++ is_channel_a_band(ch_info) ?
++ "5.2" : "2.4");
++ ch_info++;
++ continue;
++ }
++
++ /* Initialize regulatory-based run-time data */
++ ch_info->max_power_avg = ch_info->curr_txpow =
++ eeprom_ch_info[ch].max_power_avg;
++ ch_info->scan_power = eeprom_ch_info[ch].max_power_avg;
++ ch_info->min_power = 0;
++
++ IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s%s(0x%02x"
++ " %ddBm): Ad-Hoc %ssupported\n",
++ ch_info->channel,
++ is_channel_a_band(ch_info) ?
++ "5.2" : "2.4",
++ CHECK_AND_PRINT_I(VALID),
++ CHECK_AND_PRINT_I(IBSS),
++ CHECK_AND_PRINT_I(ACTIVE),
++ CHECK_AND_PRINT_I(RADAR),
++ CHECK_AND_PRINT_I(WIDE),
++ CHECK_AND_PRINT_I(NARROW),
++ CHECK_AND_PRINT_I(DFS),
++ eeprom_ch_info[ch].flags,
++ eeprom_ch_info[ch].max_power_avg,
++ ((eeprom_ch_info[ch].
++ flags & EEPROM_CHANNEL_IBSS)
++ && !(eeprom_ch_info[ch].
++ flags & EEPROM_CHANNEL_RADAR))
++ ? "" : "not ");
++
++ /* Set the user_txpower_limit to the highest power
++ * supported by any channel */
++ if (eeprom_ch_info[ch].max_power_avg >
++ priv->user_txpower_limit)
++ priv->user_txpower_limit =
++ eeprom_ch_info[ch].max_power_avg;
++
++ ch_info++;
++ }
++ }
++
++ /* Two additional EEPROM bands for 2.4 and 5 GHz FAT channels */
++ for (band = 6; band <= 7; band++) {
++ enum ieee80211_band ieeeband;
++ u8 fat_extension_chan;
++
++ iwl_init_band_reference(priv, band, &eeprom_ch_count,
++ &eeprom_ch_info, &eeprom_ch_index);
++
++ /* EEPROM band 6 is 2.4, band 7 is 5 GHz */
++ ieeeband =
++ (band == 6) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
++
++ /* Loop through each band adding each of the channels */
++ for (ch = 0; ch < eeprom_ch_count; ch++) {
++
++ if ((band == 6) &&
++ ((eeprom_ch_index[ch] == 5) ||
++ (eeprom_ch_index[ch] == 6) ||
++ (eeprom_ch_index[ch] == 7)))
++ fat_extension_chan = HT_IE_EXT_CHANNEL_MAX;
++ else
++ fat_extension_chan = HT_IE_EXT_CHANNEL_ABOVE;
++
++ /* Set up driver's info for lower half */
++ iwl4965_set_fat_chan_info(priv, ieeeband,
++ eeprom_ch_index[ch],
++ &(eeprom_ch_info[ch]),
++ fat_extension_chan);
++
++ /* Set up driver's info for upper half */
++ iwl4965_set_fat_chan_info(priv, ieeeband,
++ (eeprom_ch_index[ch] + 4),
++ &(eeprom_ch_info[ch]),
++ HT_IE_EXT_CHANNEL_BELOW);
++ }
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL(iwl_init_channel_map);
++
++/*
++ * iwl_free_channel_map - undo allocations in iwl4965_init_channel_map
++ */
++void iwl_free_channel_map(struct iwl_priv *priv)
++{
++ kfree(priv->channel_info);
++ priv->channel_count = 0;
++}
++EXPORT_SYMBOL(iwl_free_channel_map);
++
++/**
++ * iwl_get_channel_info - Find driver's private channel info
++ *
++ * Based on band and channel number.
++ */
++const struct iwl_channel_info *iwl_get_channel_info(
++ const struct iwl_priv *priv,
++ enum ieee80211_band band, u16 channel)
++{
++ int i;
++
++ switch (band) {
++ case IEEE80211_BAND_5GHZ:
++ for (i = 14; i < priv->channel_count; i++) {
++ if (priv->channel_info[i].channel == channel)
++ return &priv->channel_info[i];
++ }
++ break;
++ case IEEE80211_BAND_2GHZ:
++ if (channel >= 1 && channel <= 14)
++ return &priv->channel_info[channel - 1];
++ break;
++ default:
++ BUG();
++ }
++
++ return NULL;
++}
++EXPORT_SYMBOL(iwl_get_channel_info);
++
+diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+new file mode 100644
+index 0000000..bd0a042
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+@@ -0,0 +1,375 @@
++/******************************************************************************
++ *
++ * This file is provided under a dual BSD/GPLv2 license. When using or
++ * redistributing this file, you may do so under either license.
++ *
++ * GPL LICENSE SUMMARY
++ *
++ * Copyright(c) 2008 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
++ * USA
++ *
++ * The full GNU General Public License is included in this distribution
++ * in the file called LICENSE.GPL.
++ *
++ * Contact Information:
++ * Tomas Winkler <tomas.winkler at intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ * BSD LICENSE
++ *
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * * Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ * * Neither the name Intel Corporation nor the names of its
++ * contributors may be used to endorse or promote products derived
++ * from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *****************************************************************************/
++
++#ifndef __iwl_eeprom_h__
++#define __iwl_eeprom_h__
++
++struct iwl_priv;
++
++/*
++ * EEPROM access time values:
++ *
++ * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG,
++ * then clearing (with subsequent read/modify/write) CSR_EEPROM_REG bit
++ * CSR_EEPROM_REG_BIT_CMD (0x2).
++ * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1).
++ * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec.
++ * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG.
++ */
++#define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */
++#define IWL_EEPROM_ACCESS_DELAY 10 /* uSec */
++
++#define IWL_EEPROM_SEM_TIMEOUT 10 /* milliseconds */
++#define IWL_EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */
++
++
++/*
++ * Regulatory channel usage flags in EEPROM struct iwl4965_eeprom_channel.flags.
++ *
++ * IBSS and/or AP operation is allowed *only* on those channels with
++ * (VALID && IBSS && ACTIVE && !RADAR). This restriction is in place because
++ * RADAR detection is not supported by the 4965 driver, but is a
++ * requirement for establishing a new network for legal operation on channels
++ * requiring RADAR detection or restricting ACTIVE scanning.
++ *
++ * NOTE: "WIDE" flag does not indicate anything about "FAT" 40 MHz channels.
++ * It only indicates that 20 MHz channel use is supported; FAT channel
++ * usage is indicated by a separate set of regulatory flags for each
++ * FAT channel pair.
++ *
++ * NOTE: Using a channel inappropriately will result in a uCode error!
++ */
++#define IWL_NUM_TX_CALIB_GROUPS 5
++enum {
++ EEPROM_CHANNEL_VALID = (1 << 0), /* usable for this SKU/geo */
++ EEPROM_CHANNEL_IBSS = (1 << 1), /* usable as an IBSS channel */
++ /* Bit 2 Reserved */
++ EEPROM_CHANNEL_ACTIVE = (1 << 3), /* active scanning allowed */
++ EEPROM_CHANNEL_RADAR = (1 << 4), /* radar detection required */
++ EEPROM_CHANNEL_WIDE = (1 << 5), /* 20 MHz channel okay */
++ EEPROM_CHANNEL_NARROW = (1 << 6), /* 10 MHz channel (not used) */
++ EEPROM_CHANNEL_DFS = (1 << 7), /* dynamic freq selection candidate */
++};
++
++/* SKU Capabilities */
++#define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE (1 << 0)
++#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE (1 << 1)
++
++/* *regulatory* channel data format in eeprom, one for each channel.
++ * There are separate entries for FAT (40 MHz) vs. normal (20 MHz) channels. */
++struct iwl4965_eeprom_channel {
++ u8 flags; /* EEPROM_CHANNEL_* flags copied from EEPROM */
++ s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */
++} __attribute__ ((packed));
++
++/* 4965 has two radio transmitters (and 3 radio receivers) */
++#define EEPROM_TX_POWER_TX_CHAINS (2)
++
++/* 4965 has room for up to 8 sets of txpower calibration data */
++#define EEPROM_TX_POWER_BANDS (8)
++
++/* 4965 factory calibration measures txpower gain settings for
++ * each of 3 target output levels */
++#define EEPROM_TX_POWER_MEASUREMENTS (3)
++
++#define EEPROM_4965_TX_POWER_VERSION (2)
++
++/* 4965 driver does not work with txpower calibration version < 5.
++ * Look for this in calib_version member of struct iwl4965_eeprom. */
++#define EEPROM_TX_POWER_VERSION_NEW (5)
++
++/* 2.4 GHz */
++extern const u8 iwl_eeprom_band_1[14];
++
++/*
++ * 4965 factory calibration data for one txpower level, on one channel,
++ * measured on one of the 2 tx chains (radio transmitter and associated
++ * antenna). EEPROM contains:
++ *
++ * 1) Temperature (degrees Celsius) of device when measurement was made.
++ *
++ * 2) Gain table index used to achieve the target measurement power.
++ * This refers to the "well-known" gain tables (see iwl-4965-hw.h).
++ *
++ * 3) Actual measured output power, in half-dBm ("34" = 17 dBm).
++ *
++ * 4) RF power amplifier detector level measurement (not used).
++ */
++struct iwl4965_eeprom_calib_measure {
++ u8 temperature; /* Device temperature (Celsius) */
++ u8 gain_idx; /* Index into gain table */
++ u8 actual_pow; /* Measured RF output power, half-dBm */
++ s8 pa_det; /* Power amp detector level (not used) */
++} __attribute__ ((packed));
++
++
++/*
++ * 4965 measurement set for one channel. EEPROM contains:
++ *
++ * 1) Channel number measured
++ *
++ * 2) Measurements for each of 3 power levels for each of 2 radio transmitters
++ * (a.k.a. "tx chains") (6 measurements altogether)
++ */
++struct iwl4965_eeprom_calib_ch_info {
++ u8 ch_num;
++ struct iwl4965_eeprom_calib_measure
++ measurements[EEPROM_TX_POWER_TX_CHAINS]
++ [EEPROM_TX_POWER_MEASUREMENTS];
++} __attribute__ ((packed));
++
++/*
++ * 4965 txpower subband info.
++ *
++ * For each frequency subband, EEPROM contains the following:
++ *
++ * 1) First and last channels within range of the subband. "0" values
++ * indicate that this sample set is not being used.
++ *
++ * 2) Sample measurement sets for 2 channels close to the range endpoints.
++ */
++struct iwl4965_eeprom_calib_subband_info {
++ u8 ch_from; /* channel number of lowest channel in subband */
++ u8 ch_to; /* channel number of highest channel in subband */
++ struct iwl4965_eeprom_calib_ch_info ch1;
++ struct iwl4965_eeprom_calib_ch_info ch2;
++} __attribute__ ((packed));
++
++
++/*
++ * 4965 txpower calibration info. EEPROM contains:
++ *
++ * 1) Factory-measured saturation power levels (maximum levels at which
++ * tx power amplifier can output a signal without too much distortion).
++ * There is one level for 2.4 GHz band and one for 5 GHz band. These
++ * values apply to all channels within each of the bands.
++ *
++ * 2) Factory-measured power supply voltage level. This is assumed to be
++ * constant (i.e. same value applies to all channels/bands) while the
++ * factory measurements are being made.
++ *
++ * 3) Up to 8 sets of factory-measured txpower calibration values.
++ * These are for different frequency ranges, since txpower gain
++ * characteristics of the analog radio circuitry vary with frequency.
++ *
++ * Not all sets need to be filled with data;
++ * struct iwl4965_eeprom_calib_subband_info contains range of channels
++ * (0 if unused) for each set of data.
++ */
++struct iwl4965_eeprom_calib_info {
++ u8 saturation_power24; /* half-dBm (e.g. "34" = 17 dBm) */
++ u8 saturation_power52; /* half-dBm */
++ s16 voltage; /* signed */
++ struct iwl4965_eeprom_calib_subband_info
++ band_info[EEPROM_TX_POWER_BANDS];
++} __attribute__ ((packed));
++
++
++
++/*
++ * 4965 EEPROM map
++ */
++struct iwl4965_eeprom {
++ u8 reserved0[16];
++ u16 device_id; /* abs.ofs: 16 */
++ u8 reserved1[2];
++ u16 pmc; /* abs.ofs: 20 */
++ u8 reserved2[20];
++ u8 mac_address[6]; /* abs.ofs: 42 */
++ u8 reserved3[58];
++ u16 board_revision; /* abs.ofs: 106 */
++ u8 reserved4[11];
++ u8 board_pba_number[9]; /* abs.ofs: 119 */
++ u8 reserved5[8];
++ u16 version; /* abs.ofs: 136 */
++ u8 sku_cap; /* abs.ofs: 138 */
++ u8 leds_mode; /* abs.ofs: 139 */
++ u16 oem_mode;
++ u16 wowlan_mode; /* abs.ofs: 142 */
++ u16 leds_time_interval; /* abs.ofs: 144 */
++ u8 leds_off_time; /* abs.ofs: 146 */
++ u8 leds_on_time; /* abs.ofs: 147 */
++ u8 almgor_m_version; /* abs.ofs: 148 */
++ u8 antenna_switch_type; /* abs.ofs: 149 */
++ u8 reserved6[8];
++ u16 board_revision_4965; /* abs.ofs: 158 */
++ u8 reserved7[13];
++ u8 board_pba_number_4965[9]; /* abs.ofs: 173 */
++ u8 reserved8[10];
++ u8 sku_id[4]; /* abs.ofs: 192 */
++
++/*
++ * Per-channel regulatory data.
++ *
++ * Each channel that *might* be supported by 3945 or 4965 has a fixed location
++ * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
++ * txpower (MSB).
++ *
++ * Entries immediately below are for 20 MHz channel width. FAT (40 MHz)
++ * channels (only for 4965, not supported by 3945) appear later in the EEPROM.
++ *
++ * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
++ */
++ u16 band_1_count; /* abs.ofs: 196 */
++ struct iwl4965_eeprom_channel band_1_channels[14]; /* abs.ofs: 196 */
++
++/*
++ * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196,
++ * 5.0 GHz channels 7, 8, 11, 12, 16
++ * (4915-5080MHz) (none of these is ever supported)
++ */
++ u16 band_2_count; /* abs.ofs: 226 */
++ struct iwl4965_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */
++
++/*
++ * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
++ * (5170-5320MHz)
++ */
++ u16 band_3_count; /* abs.ofs: 254 */
++ struct iwl4965_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */
++
++/*
++ * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
++ * (5500-5700MHz)
++ */
++ u16 band_4_count; /* abs.ofs: 280 */
++ struct iwl4965_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */
++
++/*
++ * 5.7 GHz channels 145, 149, 153, 157, 161, 165
++ * (5725-5825MHz)
++ */
++ u16 band_5_count; /* abs.ofs: 304 */
++ struct iwl4965_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */
++
++ u8 reserved10[2];
++
++
++/*
++ * 2.4 GHz FAT channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11)
++ *
++ * The channel listed is the center of the lower 20 MHz half of the channel.
++ * The overall center frequency is actually 2 channels (10 MHz) above that,
++ * and the upper half of each FAT channel is centered 4 channels (20 MHz) away
++ * from the lower half; e.g. the upper half of FAT channel 1 is channel 5,
++ * and the overall FAT channel width centers on channel 3.
++ *
++ * NOTE: The RXON command uses 20 MHz channel numbers to specify the
++ * control channel to which to tune. RXON also specifies whether the
++ * control channel is the upper or lower half of a FAT channel.
++ *
++ * NOTE: 4965 does not support FAT channels on 2.4 GHz.
++ */
++ struct iwl4965_eeprom_channel band_24_channels[7]; /* abs.ofs: 320 */
++ u8 reserved11[2];
++
++/*
++ * 5.2 GHz FAT channels 36 (40), 44 (48), 52 (56), 60 (64),
++ * 100 (104), 108 (112), 116 (120), 124 (128), 132 (136), 149 (153), 157 (161)
++ */
++ struct iwl4965_eeprom_channel band_52_channels[11]; /* abs.ofs: 336 */
++ u8 reserved12[6];
++
++/*
++ * 4965 driver requires txpower calibration format version 5 or greater.
++ * Driver does not work with txpower calibration version < 5.
++ * This value is simply a 16-bit number, no major/minor versions here.
++ */
++ u16 calib_version; /* abs.ofs: 364 */
++ u8 reserved13[2];
++ u8 reserved14[96]; /* abs.ofs: 368 */
++
++/*
++ * 4965 Txpower calibration data.
++ */
++ struct iwl4965_eeprom_calib_info calib_info; /* abs.ofs: 464 */
++
++ u8 reserved16[140]; /* fill out to full 1024 byte block */
++
++
++} __attribute__ ((packed));
++
++#define IWL_EEPROM_IMAGE_SIZE 1024
++
++/* End of EEPROM */
++
++struct iwl_eeprom_ops {
++ int (*verify_signature) (struct iwl_priv *priv);
++ int (*acquire_semaphore) (struct iwl_priv *priv);
++ void (*release_semaphore) (struct iwl_priv *priv);
++};
++
++
++void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac);
++int iwl_eeprom_init(struct iwl_priv *priv);
++
++int iwlcore_eeprom_verify_signature(struct iwl_priv *priv);
++int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv);
++void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv);
++
++int iwl_init_channel_map(struct iwl_priv *priv);
++void iwl_free_channel_map(struct iwl_priv *priv);
++const struct iwl_channel_info *iwl_get_channel_info(
++ const struct iwl_priv *priv,
++ enum ieee80211_band band, u16 channel);
++
++#endif /* __iwl_eeprom_h__ */
+diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+new file mode 100644
+index 0000000..fdb27f1
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+@@ -0,0 +1,278 @@
++/******************************************************************************
++ *
++ * GPL LICENSE SUMMARY
++ *
++ * Copyright(c) 2008 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
++ * USA
++ *
++ * The full GNU General Public License is included in this distribution
++ * in the file called LICENSE.GPL.
++ *
++ * Contact Information:
++ * Tomas Winkler <tomas.winkler at intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *****************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/version.h>
++#include <net/mac80211.h>
++
++#include "iwl-4965.h" /* FIXME: remove */
++#include "iwl-debug.h"
++#include "iwl-eeprom.h"
++#include "iwl-core.h"
++
++
++#define IWL_CMD(x) case x : return #x
++
++const char *get_cmd_string(u8 cmd)
++{
++ switch (cmd) {
++ IWL_CMD(REPLY_ALIVE);
++ IWL_CMD(REPLY_ERROR);
++ IWL_CMD(REPLY_RXON);
++ IWL_CMD(REPLY_RXON_ASSOC);
++ IWL_CMD(REPLY_QOS_PARAM);
++ IWL_CMD(REPLY_RXON_TIMING);
++ IWL_CMD(REPLY_ADD_STA);
++ IWL_CMD(REPLY_REMOVE_STA);
++ IWL_CMD(REPLY_REMOVE_ALL_STA);
++ IWL_CMD(REPLY_WEPKEY);
++ IWL_CMD(REPLY_TX);
++ IWL_CMD(REPLY_RATE_SCALE);
++ IWL_CMD(REPLY_LEDS_CMD);
++ IWL_CMD(REPLY_TX_LINK_QUALITY_CMD);
++ IWL_CMD(RADAR_NOTIFICATION);
++ IWL_CMD(REPLY_QUIET_CMD);
++ IWL_CMD(REPLY_CHANNEL_SWITCH);
++ IWL_CMD(CHANNEL_SWITCH_NOTIFICATION);
++ IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD);
++ IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION);
++ IWL_CMD(POWER_TABLE_CMD);
++ IWL_CMD(PM_SLEEP_NOTIFICATION);
++ IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC);
++ IWL_CMD(REPLY_SCAN_CMD);
++ IWL_CMD(REPLY_SCAN_ABORT_CMD);
++ IWL_CMD(SCAN_START_NOTIFICATION);
++ IWL_CMD(SCAN_RESULTS_NOTIFICATION);
++ IWL_CMD(SCAN_COMPLETE_NOTIFICATION);
++ IWL_CMD(BEACON_NOTIFICATION);
++ IWL_CMD(REPLY_TX_BEACON);
++ IWL_CMD(WHO_IS_AWAKE_NOTIFICATION);
++ IWL_CMD(QUIET_NOTIFICATION);
++ IWL_CMD(REPLY_TX_PWR_TABLE_CMD);
++ IWL_CMD(MEASURE_ABORT_NOTIFICATION);
++ IWL_CMD(REPLY_BT_CONFIG);
++ IWL_CMD(REPLY_STATISTICS_CMD);
++ IWL_CMD(STATISTICS_NOTIFICATION);
++ IWL_CMD(REPLY_CARD_STATE_CMD);
++ IWL_CMD(CARD_STATE_NOTIFICATION);
++ IWL_CMD(MISSED_BEACONS_NOTIFICATION);
++ IWL_CMD(REPLY_CT_KILL_CONFIG_CMD);
++ IWL_CMD(SENSITIVITY_CMD);
++ IWL_CMD(REPLY_PHY_CALIBRATION_CMD);
++ IWL_CMD(REPLY_RX_PHY_CMD);
++ IWL_CMD(REPLY_RX_MPDU_CMD);
++ IWL_CMD(REPLY_RX);
++ IWL_CMD(REPLY_COMPRESSED_BA);
++ default:
++ return "UNKNOWN";
++
++ }
++}
++EXPORT_SYMBOL(get_cmd_string);
++
++#define HOST_COMPLETE_TIMEOUT (HZ / 2)
++
++static int iwl_generic_cmd_callback(struct iwl_priv *priv,
++ struct iwl_cmd *cmd, struct sk_buff *skb)
++{
++ struct iwl4965_rx_packet *pkt = NULL;
++
++ if (!skb) {
++ IWL_ERROR("Error: Response NULL in %s.\n",
++ get_cmd_string(cmd->hdr.cmd));
++ return 1;
++ }
++
++ pkt = (struct iwl4965_rx_packet *)skb->data;
++ if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
++ IWL_ERROR("Bad return from %s (0x%08X)\n",
++ get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
++ return 1;
++ }
++
++ IWL_DEBUG_HC("back from %s (0x%08X)\n",
++ get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
++
++ /* Let iwl_tx_complete free the response skb */
++ return 1;
++}
++
++static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
++{
++ int ret;
++
++ BUG_ON(!(cmd->meta.flags & CMD_ASYNC));
++
++ /* An asynchronous command can not expect an SKB to be set. */
++ BUG_ON(cmd->meta.flags & CMD_WANT_SKB);
++
++ /* Assign a generic callback if one is not provided */
++ if (!cmd->meta.u.callback)
++ cmd->meta.u.callback = iwl_generic_cmd_callback;
++
++ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++ return -EBUSY;
++
++ ret = priv->cfg->ops->utils->enqueue_hcmd(priv, cmd);
++ if (ret < 0) {
++ IWL_ERROR("Error sending %s: enqueue_hcmd failed: %d\n",
++ get_cmd_string(cmd->id), ret);
++ return ret;
++ }
++ return 0;
++}
++
++int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
++{
++ int cmd_idx;
++ int ret;
++
++ BUG_ON(cmd->meta.flags & CMD_ASYNC);
++
++ /* A synchronous command can not have a callback set. */
++ BUG_ON(cmd->meta.u.callback != NULL);
++
++ if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) {
++ IWL_ERROR("Error sending %s: Already sending a host command\n",
++ get_cmd_string(cmd->id));
++ ret = -EBUSY;
++ goto out;
++ }
++
++ set_bit(STATUS_HCMD_ACTIVE, &priv->status);
++
++ if (cmd->meta.flags & CMD_WANT_SKB)
++ cmd->meta.source = &cmd->meta;
++
++ cmd_idx = priv->cfg->ops->utils->enqueue_hcmd(priv, cmd);
++ if (cmd_idx < 0) {
++ ret = cmd_idx;
++ IWL_ERROR("Error sending %s: enqueue_hcmd failed: %d\n",
++ get_cmd_string(cmd->id), ret);
++ goto out;
++ }
++
++ ret = wait_event_interruptible_timeout(priv->wait_command_queue,
++ !test_bit(STATUS_HCMD_ACTIVE, &priv->status),
++ HOST_COMPLETE_TIMEOUT);
++ if (!ret) {
++ if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) {
++ IWL_ERROR("Error sending %s: time out after %dms.\n",
++ get_cmd_string(cmd->id),
++ jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
++
++ clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
++ ret = -ETIMEDOUT;
++ goto cancel;
++ }
++ }
++
++ if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
++ IWL_DEBUG_INFO("Command %s aborted: RF KILL Switch\n",
++ get_cmd_string(cmd->id));
++ ret = -ECANCELED;
++ goto fail;
++ }
++ if (test_bit(STATUS_FW_ERROR, &priv->status)) {
++ IWL_DEBUG_INFO("Command %s failed: FW Error\n",
++ get_cmd_string(cmd->id));
++ ret = -EIO;
++ goto fail;
++ }
++ if ((cmd->meta.flags & CMD_WANT_SKB) && !cmd->meta.u.skb) {
++ IWL_ERROR("Error: Response NULL in '%s'\n",
++ get_cmd_string(cmd->id));
++ ret = -EIO;
++ goto out;
++ }
++
++ ret = 0;
++ goto out;
++
++cancel:
++ if (cmd->meta.flags & CMD_WANT_SKB) {
++ struct iwl_cmd *qcmd;
++
++ /* Cancel the CMD_WANT_SKB flag for the cmd in the
++ * TX cmd queue. Otherwise in case the cmd comes
++ * in later, it will possibly set an invalid
++ * address (cmd->meta.source). */
++ qcmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx];
++ qcmd->meta.flags &= ~CMD_WANT_SKB;
++ }
++fail:
++ if (cmd->meta.u.skb) {
++ dev_kfree_skb_any(cmd->meta.u.skb);
++ cmd->meta.u.skb = NULL;
++ }
++out:
++ clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status);
++ return ret;
++}
++EXPORT_SYMBOL(iwl_send_cmd_sync);
++
++int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
++{
++ if (cmd->meta.flags & CMD_ASYNC)
++ return iwl_send_cmd_async(priv, cmd);
++
++ return iwl_send_cmd_sync(priv, cmd);
++}
++EXPORT_SYMBOL(iwl_send_cmd);
++
++int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data)
++{
++ struct iwl_host_cmd cmd = {
++ .id = id,
++ .len = len,
++ .data = data,
++ };
++
++ return iwl_send_cmd_sync(priv, &cmd);
++}
++EXPORT_SYMBOL(iwl_send_cmd_pdu);
++
++int iwl_send_cmd_pdu_async(struct iwl_priv *priv,
++ u8 id, u16 len, const void *data,
++ int (*callback)(struct iwl_priv *priv,
++ struct iwl_cmd *cmd,
++ struct sk_buff *skb))
++{
++ struct iwl_host_cmd cmd = {
++ .id = id,
++ .len = len,
++ .data = data,
++ };
++
++ cmd.meta.flags |= CMD_ASYNC;
++ cmd.meta.u.callback = callback;
++
++ return iwl_send_cmd_async(priv, &cmd);
++}
++EXPORT_SYMBOL(iwl_send_cmd_pdu_async);
+diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h
+index 8993cca..a443472 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-helpers.h
++++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+ *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+@@ -254,6 +254,26 @@ static inline u8 iwl_get_dma_hi_address(dma_addr_t addr)
+ return sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0;
+ }
+
++/**
++ * iwl_queue_inc_wrap - increment queue index, wrap back to beginning
++ * @index -- current index
++ * @n_bd -- total number of entries in queue (must be power of 2)
++ */
++static inline int iwl_queue_inc_wrap(int index, int n_bd)
++{
++ return ++index & (n_bd - 1);
++}
++
++/**
++ * iwl_queue_dec_wrap - decrement queue index, wrap back to end
++ * @index -- current index
++ * @n_bd -- total number of entries in queue (must be power of 2)
++ */
++static inline int iwl_queue_dec_wrap(int index, int n_bd)
++{
++ return --index & (n_bd - 1);
++}
++
+ /* TODO: Move fw_desc functions to iwl-pci.ko */
+ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev,
+ struct fw_desc *desc)
+diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h
+new file mode 100644
+index 0000000..5bc3df4
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-io.h
+@@ -0,0 +1,429 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
++ *
++ * Portions of this file are derived from the ipw3945 project.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called LICENSE.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ *****************************************************************************/
++
++#ifndef __iwl_io_h__
++#define __iwl_io_h__
++
++#include <linux/io.h>
++
++#include "iwl-debug.h"
++
++/*
++ * IO, register, and NIC memory access functions
++ *
++ * NOTE on naming convention and macro usage for these
++ *
++ * A single _ prefix before a an access function means that no state
++ * check or debug information is printed when that function is called.
++ *
++ * A double __ prefix before an access function means that state is checked
++ * and the current line number and caller function name are printed in addition
++ * to any other debug output.
++ *
++ * The non-prefixed name is the #define that maps the caller into a
++ * #define that provides the caller's name and __LINE__ to the double
++ * prefix version.
++ *
++ * If you wish to call the function without any debug or state checking,
++ * you should use the single _ prefix version (as is used by dependent IO
++ * routines, for example _iwl_read_direct32 calls the non-check version of
++ * _iwl_read32.)
++ *
++ * These declarations are *extremely* useful in quickly isolating code deltas
++ * which result in misconfiguring of the hardware I/O. In combination with
++ * git-bisect and the IO debug level you can quickly determine the specific
++ * commit which breaks the IO sequence to the hardware.
++ *
++ */
++
++#define _iwl_write32(priv, ofs, val) writel((val), (priv)->hw_base + (ofs))
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *priv,
++ u32 ofs, u32 val)
++{
++ IWL_DEBUG_IO("write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l);
++ _iwl_write32(priv, ofs, val);
++}
++#define iwl_write32(priv, ofs, val) \
++ __iwl_write32(__FILE__, __LINE__, priv, ofs, val)
++#else
++#define iwl_write32(priv, ofs, val) _iwl_write32(priv, ofs, val)
++#endif
++
++#define _iwl_read32(priv, ofs) readl((priv)->hw_base + (ofs))
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline u32 __iwl_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs)
++{
++ IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l);
++ return _iwl_read32(priv, ofs);
++}
++#define iwl_read32(priv, ofs) __iwl_read32(__FILE__, __LINE__, priv, ofs)
++#else
++#define iwl_read32(p, o) _iwl_read32(p, o)
++#endif
++
++static inline int _iwl_poll_bit(struct iwl_priv *priv, u32 addr,
++ u32 bits, u32 mask, int timeout)
++{
++ int i = 0;
++
++ do {
++ if ((_iwl_read32(priv, addr) & mask) == (bits & mask))
++ return i;
++ mdelay(10);
++ i += 10;
++ } while (i < timeout);
++
++ return -ETIMEDOUT;
++}
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline int __iwl_poll_bit(const char *f, u32 l,
++ struct iwl_priv *priv, u32 addr,
++ u32 bits, u32 mask, int timeout)
++{
++ int ret = _iwl_poll_bit(priv, addr, bits, mask, timeout);
++ IWL_DEBUG_IO("poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n",
++ addr, bits, mask,
++ unlikely(ret == -ETIMEDOUT)?"timeout":"", f, l);
++ return ret;
++}
++#define iwl_poll_bit(priv, addr, bits, mask, timeout) \
++ __iwl_poll_bit(__FILE__, __LINE__, priv, addr, bits, mask, timeout)
++#else
++#define iwl_poll_bit(p, a, b, m, t) _iwl_poll_bit(p, a, b, m, t)
++#endif
++
++static inline void _iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask)
++{
++ _iwl_write32(priv, reg, _iwl_read32(priv, reg) | mask);
++}
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline void __iwl_set_bit(const char *f, u32 l,
++ struct iwl_priv *priv, u32 reg, u32 mask)
++{
++ u32 val = _iwl_read32(priv, reg) | mask;
++ IWL_DEBUG_IO("set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
++ _iwl_write32(priv, reg, val);
++}
++#define iwl_set_bit(p, r, m) __iwl_set_bit(__FILE__, __LINE__, p, r, m)
++#else
++#define iwl_set_bit(p, r, m) _iwl_set_bit(p, r, m)
++#endif
++
++static inline void _iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask)
++{
++ _iwl_write32(priv, reg, _iwl_read32(priv, reg) & ~mask);
++}
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline void __iwl_clear_bit(const char *f, u32 l,
++ struct iwl_priv *priv, u32 reg, u32 mask)
++{
++ u32 val = _iwl_read32(priv, reg) & ~mask;
++ IWL_DEBUG_IO("clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
++ _iwl_write32(priv, reg, val);
++}
++#define iwl_clear_bit(p, r, m) __iwl_clear_bit(__FILE__, __LINE__, p, r, m)
++#else
++#define iwl_clear_bit(p, r, m) _iwl_clear_bit(p, r, m)
++#endif
++
++static inline int _iwl_grab_nic_access(struct iwl_priv *priv)
++{
++ int ret;
++ u32 gp_ctl;
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++ if (atomic_read(&priv->restrict_refcnt))
++ return 0;
++#endif
++ if (test_bit(STATUS_RF_KILL_HW, &priv->status) ||
++ test_bit(STATUS_RF_KILL_SW, &priv->status)) {
++ IWL_WARNING("WARNING: Requesting MAC access during RFKILL "
++ "wakes up NIC\n");
++
++ /* 10 msec allows time for NIC to complete its data save */
++ gp_ctl = _iwl_read32(priv, CSR_GP_CNTRL);
++ if (gp_ctl & CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY) {
++ IWL_DEBUG_RF_KILL("Wait for complete power-down, "
++ "gpctl = 0x%08x\n", gp_ctl);
++ mdelay(10);
++ } else
++ IWL_DEBUG_RF_KILL("power-down complete, "
++ "gpctl = 0x%08x\n", gp_ctl);
++ }
++
++ /* this bit wakes up the NIC */
++ _iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
++ ret = _iwl_poll_bit(priv, CSR_GP_CNTRL,
++ CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
++ (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
++ CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 50);
++ if (ret < 0) {
++ IWL_ERROR("MAC is in deep sleep!\n");
++ return -EIO;
++ }
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++ atomic_inc(&priv->restrict_refcnt);
++#endif
++ return 0;
++}
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline int __iwl_grab_nic_access(const char *f, u32 l,
++ struct iwl_priv *priv)
++{
++ if (atomic_read(&priv->restrict_refcnt))
++ IWL_ERROR("Grabbing access while already held %s %d.\n", f, l);
++
++ IWL_DEBUG_IO("grabbing nic access - %s %d\n", f, l);
++ return _iwl_grab_nic_access(priv);
++}
++#define iwl_grab_nic_access(priv) \
++ __iwl_grab_nic_access(__FILE__, __LINE__, priv)
++#else
++#define iwl_grab_nic_access(priv) \
++ _iwl_grab_nic_access(priv)
++#endif
++
++static inline void _iwl_release_nic_access(struct iwl_priv *priv)
++{
++#ifdef CONFIG_IWLWIFI_DEBUG
++ if (atomic_dec_and_test(&priv->restrict_refcnt))
++#endif
++ _iwl_clear_bit(priv, CSR_GP_CNTRL,
++ CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
++}
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline void __iwl_release_nic_access(const char *f, u32 l,
++ struct iwl_priv *priv)
++{
++ if (atomic_read(&priv->restrict_refcnt) <= 0)
++ IWL_ERROR("Release unheld nic access at line %s %d.\n", f, l);
++
++ IWL_DEBUG_IO("releasing nic access - %s %d\n", f, l);
++ _iwl_release_nic_access(priv);
++}
++#define iwl_release_nic_access(priv) \
++ __iwl_release_nic_access(__FILE__, __LINE__, priv)
++#else
++#define iwl_release_nic_access(priv) \
++ _iwl_release_nic_access(priv)
++#endif
++
++static inline u32 _iwl_read_direct32(struct iwl_priv *priv, u32 reg)
++{
++ return _iwl_read32(priv, reg);
++}
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline u32 __iwl_read_direct32(const char *f, u32 l,
++ struct iwl_priv *priv, u32 reg)
++{
++ u32 value = _iwl_read_direct32(priv, reg);
++ if (!atomic_read(&priv->restrict_refcnt))
++ IWL_ERROR("Nic access not held from %s %d\n", f, l);
++ IWL_DEBUG_IO("read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value,
++ f, l);
++ return value;
++}
++#define iwl_read_direct32(priv, reg) \
++ __iwl_read_direct32(__FILE__, __LINE__, priv, reg)
++#else
++#define iwl_read_direct32 _iwl_read_direct32
++#endif
++
++static inline void _iwl_write_direct32(struct iwl_priv *priv,
++ u32 reg, u32 value)
++{
++ _iwl_write32(priv, reg, value);
++}
++#ifdef CONFIG_IWLWIFI_DEBUG
++static void __iwl_write_direct32(const char *f , u32 line,
++ struct iwl_priv *priv, u32 reg, u32 value)
++{
++ if (!atomic_read(&priv->restrict_refcnt))
++ IWL_ERROR("Nic access not held from %s line %d\n", f, line);
++ _iwl_write_direct32(priv, reg, value);
++}
++#define iwl_write_direct32(priv, reg, value) \
++ __iwl_write_direct32(__func__, __LINE__, priv, reg, value)
++#else
++#define iwl_write_direct32 _iwl_write_direct32
++#endif
++
++static inline void iwl_write_reg_buf(struct iwl_priv *priv,
++ u32 reg, u32 len, u32 *values)
++{
++ u32 count = sizeof(u32);
++
++ if ((priv != NULL) && (values != NULL)) {
++ for (; 0 < len; len -= count, reg += count, values++)
++ _iwl_write_direct32(priv, reg, *values);
++ }
++}
++
++static inline int _iwl_poll_direct_bit(struct iwl_priv *priv,
++ u32 addr, u32 mask, int timeout)
++{
++ int i = 0;
++
++ do {
++ if ((_iwl_read_direct32(priv, addr) & mask) == mask)
++ return i;
++ mdelay(10);
++ i += 10;
++ } while (i < timeout);
++
++ return -ETIMEDOUT;
++}
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline int __iwl_poll_direct_bit(const char *f, u32 l,
++ struct iwl_priv *priv,
++ u32 addr, u32 mask, int timeout)
++{
++ int ret = _iwl_poll_direct_bit(priv, addr, mask, timeout);
++
++ if (unlikely(ret == -ETIMEDOUT))
++ IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) - "
++ "timedout - %s %d\n", addr, mask, f, l);
++ else
++ IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) = 0x%08X "
++ "- %s %d\n", addr, mask, ret, f, l);
++ return ret;
++}
++#define iwl_poll_direct_bit(priv, addr, mask, timeout) \
++ __iwl_poll_direct_bit(__FILE__, __LINE__, priv, addr, mask, timeout)
++#else
++#define iwl_poll_direct_bit _iwl_poll_direct_bit
++#endif
++
++static inline u32 _iwl_read_prph(struct iwl_priv *priv, u32 reg)
++{
++ _iwl_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
++ return _iwl_read_direct32(priv, HBUS_TARG_PRPH_RDAT);
++}
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline u32 __iwl_read_prph(const char *f, u32 line,
++ struct iwl_priv *priv, u32 reg)
++{
++ if (!atomic_read(&priv->restrict_refcnt))
++ IWL_ERROR("Nic access not held from %s line %d\n", f, line);
++ return _iwl_read_prph(priv, reg);
++}
++
++#define iwl_read_prph(priv, reg) \
++ __iwl_read_prph(__func__, __LINE__, priv, reg)
++#else
++#define iwl_read_prph _iwl_read_prph
++#endif
++
++static inline void _iwl_write_prph(struct iwl_priv *priv,
++ u32 addr, u32 val)
++{
++ _iwl_write_direct32(priv, HBUS_TARG_PRPH_WADDR,
++ ((addr & 0x0000FFFF) | (3 << 24)));
++ _iwl_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val);
++}
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline void __iwl_write_prph(const char *f, u32 line,
++ struct iwl_priv *priv, u32 addr, u32 val)
++{
++ if (!atomic_read(&priv->restrict_refcnt))
++ IWL_ERROR("Nic access not held from %s line %d\n", f, line);
++ _iwl_write_prph(priv, addr, val);
++}
++
++#define iwl_write_prph(priv, addr, val) \
++ __iwl_write_prph(__func__, __LINE__, priv, addr, val);
++#else
++#define iwl_write_prph _iwl_write_prph
++#endif
++
++#define _iwl_set_bits_prph(priv, reg, mask) \
++ _iwl_write_prph(priv, reg, (_iwl_read_prph(priv, reg) | mask))
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline void __iwl_set_bits_prph(const char *f, u32 line,
++ struct iwl_priv *priv,
++ u32 reg, u32 mask)
++{
++ if (!atomic_read(&priv->restrict_refcnt))
++ IWL_ERROR("Nic access not held from %s line %d\n", f, line);
++
++ _iwl_set_bits_prph(priv, reg, mask);
++}
++#define iwl_set_bits_prph(priv, reg, mask) \
++ __iwl_set_bits_prph(__func__, __LINE__, priv, reg, mask)
++#else
++#define iwl_set_bits_prph _iwl_set_bits_prph
++#endif
++
++#define _iwl_set_bits_mask_prph(priv, reg, bits, mask) \
++ _iwl_write_prph(priv, reg, ((_iwl_read_prph(priv, reg) & mask) | bits))
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++static inline void __iwl_set_bits_mask_prph(const char *f, u32 line,
++ struct iwl_priv *priv, u32 reg, u32 bits, u32 mask)
++{
++ if (!atomic_read(&priv->restrict_refcnt))
++ IWL_ERROR("Nic access not held from %s line %d\n", f, line);
++ _iwl_set_bits_mask_prph(priv, reg, bits, mask);
++}
++#define iwl_set_bits_mask_prph(priv, reg, bits, mask) \
++ __iwl_set_bits_mask_prph(__func__, __LINE__, priv, reg, bits, mask)
++#else
++#define iwl_set_bits_mask_prph _iwl_set_bits_mask_prph
++#endif
++
++static inline void iwl_clear_bits_prph(struct iwl_priv
++ *priv, u32 reg, u32 mask)
++{
++ u32 val = _iwl_read_prph(priv, reg);
++ _iwl_write_prph(priv, reg, (val & ~mask));
++}
++
++static inline u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr)
++{
++ iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr);
++ return iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
++}
++
++static inline void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val)
++{
++ iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
++ iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, val);
++}
++
++static inline void iwl_write_targ_mem_buf(struct iwl_priv *priv, u32 addr,
++ u32 len, u32 *values)
++{
++ iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
++ for (; 0 < len; len -= sizeof(u32), values++)
++ iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values);
++}
++#endif
+diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c
+new file mode 100644
+index 0000000..03fdf5b
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-led.c
+@@ -0,0 +1,449 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called LICENSE.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ *****************************************************************************/
++
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/init.h>
++#include <linux/pci.h>
++#include <linux/dma-mapping.h>
++#include <linux/delay.h>
++#include <linux/skbuff.h>
++#include <linux/netdevice.h>
++#include <linux/wireless.h>
++#include <net/mac80211.h>
++#include <linux/etherdevice.h>
++#include <asm/unaligned.h>
++
++#include "iwl-4965.h"
++#include "iwl-core.h"
++#include "iwl-io.h"
++#include "iwl-helpers.h"
++
++#define IWL_1MB_RATE (128 * 1024)
++#define IWL_LED_THRESHOLD (16)
++#define IWL_MAX_BLINK_TBL (10)
++
++static const struct {
++ u16 tpt;
++ u8 on_time;
++ u8 of_time;
++} blink_tbl[] =
++{
++ {300, 25, 25},
++ {200, 40, 40},
++ {100, 55, 55},
++ {70, 65, 65},
++ {50, 75, 75},
++ {20, 85, 85},
++ {15, 95, 95 },
++ {10, 110, 110},
++ {5, 130, 130},
++ {0, 167, 167}
++};
++
++static int iwl_led_cmd_callback(struct iwl_priv *priv,
++ struct iwl_cmd *cmd, struct sk_buff *skb)
++{
++ return 1;
++}
++
++
++/* Send led command */
++static int iwl_send_led_cmd(struct iwl_priv *priv,
++ struct iwl4965_led_cmd *led_cmd)
++{
++ struct iwl_host_cmd cmd = {
++ .id = REPLY_LEDS_CMD,
++ .len = sizeof(struct iwl4965_led_cmd),
++ .data = led_cmd,
++ .meta.flags = CMD_ASYNC,
++ .meta.u.callback = iwl_led_cmd_callback
++ };
++ u32 reg;
++
++ reg = iwl_read32(priv, CSR_LED_REG);
++ if (reg != (reg & CSR_LED_BSM_CTRL_MSK))
++ iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK);
++
++ return iwl_send_cmd(priv, &cmd);
++}
++
++
++/* Set led on command */
++static int iwl4965_led_on(struct iwl_priv *priv, int led_id)
++{
++ struct iwl4965_led_cmd led_cmd = {
++ .id = led_id,
++ .on = IWL_LED_SOLID,
++ .off = 0,
++ .interval = IWL_DEF_LED_INTRVL
++ };
++ return iwl_send_led_cmd(priv, &led_cmd);
++}
++
++/* Set led on command */
++static int iwl4965_led_pattern(struct iwl_priv *priv, int led_id,
++ enum led_brightness brightness)
++{
++ struct iwl4965_led_cmd led_cmd = {
++ .id = led_id,
++ .on = brightness,
++ .off = brightness,
++ .interval = IWL_DEF_LED_INTRVL
++ };
++ if (brightness == LED_FULL) {
++ led_cmd.on = IWL_LED_SOLID;
++ led_cmd.off = 0;
++ }
++ return iwl_send_led_cmd(priv, &led_cmd);
++}
++
++/* Set led register off */
++static int iwl4965_led_on_reg(struct iwl_priv *priv, int led_id)
++{
++ IWL_DEBUG_LED("led on %d\n", led_id);
++ iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON);
++ return 0;
++}
++
++#if 0
++/* Set led off command */
++int iwl4965_led_off(struct iwl_priv *priv, int led_id)
++{
++ struct iwl4965_led_cmd led_cmd = {
++ .id = led_id,
++ .on = 0,
++ .off = 0,
++ .interval = IWL_DEF_LED_INTRVL
++ };
++ IWL_DEBUG_LED("led off %d\n", led_id);
++ return iwl_send_led_cmd(priv, &led_cmd);
++}
++#endif
++
++
++/* Set led register off */
++static int iwl4965_led_off_reg(struct iwl_priv *priv, int led_id)
++{
++ IWL_DEBUG_LED("radio off\n");
++ iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF);
++ return 0;
++}
++
++/* Set led blink command */
++static int iwl4965_led_not_solid(struct iwl_priv *priv, int led_id,
++ u8 brightness)
++{
++ struct iwl4965_led_cmd led_cmd = {
++ .id = led_id,
++ .on = brightness,
++ .off = brightness,
++ .interval = IWL_DEF_LED_INTRVL
++ };
++
++ return iwl_send_led_cmd(priv, &led_cmd);
++}
++
++
++/*
++ * brightness call back function for Tx/Rx LED
++ */
++static int iwl4965_led_associated(struct iwl_priv *priv, int led_id)
++{
++ if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
++ !test_bit(STATUS_READY, &priv->status))
++ return 0;
++
++
++ /* start counting Tx/Rx bytes */
++ if (!priv->last_blink_time && priv->allow_blinking)
++ priv->last_blink_time = jiffies;
++ return 0;
++}
++
++/*
++ * brightness call back for association and radio
++ */
++static void iwl4965_led_brightness_set(struct led_classdev *led_cdev,
++ enum led_brightness brightness)
++{
++ struct iwl4965_led *led = container_of(led_cdev,
++ struct iwl4965_led, led_dev);
++ struct iwl_priv *priv = led->priv;
++
++ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++ return;
++
++ switch (brightness) {
++ case LED_FULL:
++ if (led->type == IWL_LED_TRG_ASSOC)
++ priv->allow_blinking = 1;
++
++ if (led->led_on)
++ led->led_on(priv, IWL_LED_LINK);
++ break;
++ case LED_OFF:
++ if (led->type == IWL_LED_TRG_ASSOC)
++ priv->allow_blinking = 0;
++
++ if (led->led_off)
++ led->led_off(priv, IWL_LED_LINK);
++ break;
++ default:
++ if (led->led_pattern)
++ led->led_pattern(priv, IWL_LED_LINK, brightness);
++ break;
++ }
++}
++
++
++
++/*
++ * Register led class with the system
++ */
++static int iwl_leds_register_led(struct iwl_priv *priv,
++ struct iwl4965_led *led,
++ enum led_type type, u8 set_led,
++ const char *name, char *trigger)
++{
++ struct device *device = wiphy_dev(priv->hw->wiphy);
++ int ret;
++
++ led->led_dev.name = name;
++ led->led_dev.brightness_set = iwl4965_led_brightness_set;
++ led->led_dev.default_trigger = trigger;
++
++ led->priv = priv;
++ led->type = type;
++
++ ret = led_classdev_register(device, &led->led_dev);
++ if (ret) {
++ IWL_ERROR("Error: failed to register led handler.\n");
++ return ret;
++ }
++
++ led->registered = 1;
++
++ if (set_led && led->led_on)
++ led->led_on(priv, IWL_LED_LINK);
++
++ return 0;
++}
++
++
++/*
++ * calculate blink rate according to last 2 sec Tx/Rx activities
++ */
++static inline u8 get_blink_rate(struct iwl_priv *priv)
++{
++ int i;
++ u8 blink_rate;
++ u64 current_tpt = priv->tx_stats[2].bytes + priv->rx_stats[2].bytes;
++ s64 tpt = current_tpt - priv->led_tpt;
++
++ if (tpt < 0) /* wrapparound */
++ tpt = -tpt;
++
++ priv->led_tpt = current_tpt;
++
++ if (tpt < IWL_LED_THRESHOLD) {
++ i = IWL_MAX_BLINK_TBL;
++ } else {
++ for (i = 0; i < IWL_MAX_BLINK_TBL; i++)
++ if (tpt > (blink_tbl[i].tpt * IWL_1MB_RATE))
++ break;
++ }
++ /* if 0 frame is transfered */
++ if ((i == IWL_MAX_BLINK_TBL) || !priv->allow_blinking)
++ blink_rate = IWL_LED_SOLID;
++ else
++ blink_rate = blink_tbl[i].on_time;
++
++ return blink_rate;
++}
++
++static inline int is_rf_kill(struct iwl_priv *priv)
++{
++ return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
++ test_bit(STATUS_RF_KILL_SW, &priv->status);
++}
++
++/*
++ * this function called from handler. Since setting Led command can
++ * happen very frequent we postpone led command to be called from
++ * REPLY handler so we know ucode is up
++ */
++void iwl_leds_background(struct iwl_priv *priv)
++{
++ u8 blink_rate;
++
++ if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
++ priv->last_blink_time = 0;
++ return;
++ }
++ if (is_rf_kill(priv)) {
++ priv->last_blink_time = 0;
++ return;
++ }
++
++ if (!priv->allow_blinking) {
++ priv->last_blink_time = 0;
++ if (priv->last_blink_rate != IWL_LED_SOLID) {
++ priv->last_blink_rate = IWL_LED_SOLID;
++ iwl4965_led_on(priv, IWL_LED_LINK);
++ }
++ return;
++ }
++ if (!priv->last_blink_time ||
++ !time_after(jiffies, priv->last_blink_time +
++ msecs_to_jiffies(1000)))
++ return;
++
++ blink_rate = get_blink_rate(priv);
++
++ /* call only if blink rate change */
++ if (blink_rate != priv->last_blink_rate) {
++ if (blink_rate != IWL_LED_SOLID) {
++ priv->last_blink_time = jiffies +
++ msecs_to_jiffies(1000);
++ iwl4965_led_not_solid(priv, IWL_LED_LINK, blink_rate);
++ } else {
++ priv->last_blink_time = 0;
++ iwl4965_led_on(priv, IWL_LED_LINK);
++ }
++ }
++
++ priv->last_blink_rate = blink_rate;
++}
++EXPORT_SYMBOL(iwl_leds_background);
++
++/* Register all led handler */
++int iwl_leds_register(struct iwl_priv *priv)
++{
++ char *trigger;
++ char name[32];
++ int ret;
++
++ priv->last_blink_rate = 0;
++ priv->led_tpt = 0;
++ priv->last_blink_time = 0;
++ priv->allow_blinking = 0;
++
++ trigger = ieee80211_get_radio_led_name(priv->hw);
++ snprintf(name, sizeof(name), "iwl-%s:radio",
++ wiphy_name(priv->hw->wiphy));
++
++ priv->led[IWL_LED_TRG_RADIO].led_on = iwl4965_led_on_reg;
++ priv->led[IWL_LED_TRG_RADIO].led_off = iwl4965_led_off_reg;
++ priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL;
++
++ ret = iwl_leds_register_led(priv,
++ &priv->led[IWL_LED_TRG_RADIO],
++ IWL_LED_TRG_RADIO, 1,
++ name, trigger);
++ if (ret)
++ goto exit_fail;
++
++ trigger = ieee80211_get_assoc_led_name(priv->hw);
++ snprintf(name, sizeof(name), "iwl-%s:assoc",
++ wiphy_name(priv->hw->wiphy));
++
++ ret = iwl_leds_register_led(priv,
++ &priv->led[IWL_LED_TRG_ASSOC],
++ IWL_LED_TRG_ASSOC, 0,
++ name, trigger);
++ /* for assoc always turn led on */
++ priv->led[IWL_LED_TRG_ASSOC].led_on = iwl4965_led_on_reg;
++ priv->led[IWL_LED_TRG_ASSOC].led_off = iwl4965_led_on_reg;
++ priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL;
++
++ if (ret)
++ goto exit_fail;
++
++ trigger = ieee80211_get_rx_led_name(priv->hw);
++ snprintf(name, sizeof(name), "iwl-%s:RX",
++ wiphy_name(priv->hw->wiphy));
++
++
++ ret = iwl_leds_register_led(priv,
++ &priv->led[IWL_LED_TRG_RX],
++ IWL_LED_TRG_RX, 0,
++ name, trigger);
++
++ priv->led[IWL_LED_TRG_RX].led_on = iwl4965_led_associated;
++ priv->led[IWL_LED_TRG_RX].led_off = iwl4965_led_associated;
++ priv->led[IWL_LED_TRG_RX].led_pattern = iwl4965_led_pattern;
++
++ if (ret)
++ goto exit_fail;
++
++ trigger = ieee80211_get_tx_led_name(priv->hw);
++ snprintf(name, sizeof(name), "iwl-%s:TX",
++ wiphy_name(priv->hw->wiphy));
++ ret = iwl_leds_register_led(priv,
++ &priv->led[IWL_LED_TRG_TX],
++ IWL_LED_TRG_TX, 0,
++ name, trigger);
++ priv->led[IWL_LED_TRG_TX].led_on = iwl4965_led_associated;
++ priv->led[IWL_LED_TRG_TX].led_off = iwl4965_led_associated;
++ priv->led[IWL_LED_TRG_TX].led_pattern = iwl4965_led_pattern;
++
++ if (ret)
++ goto exit_fail;
++
++ return 0;
++
++exit_fail:
++ iwl_leds_unregister(priv);
++ return ret;
++}
++EXPORT_SYMBOL(iwl_leds_register);
++
++/* unregister led class */
++static void iwl_leds_unregister_led(struct iwl4965_led *led, u8 set_led)
++{
++ if (!led->registered)
++ return;
++
++ led_classdev_unregister(&led->led_dev);
++
++ if (set_led)
++ led->led_dev.brightness_set(&led->led_dev, LED_OFF);
++ led->registered = 0;
++}
++
++/* Unregister all led handlers */
++void iwl_leds_unregister(struct iwl_priv *priv)
++{
++ iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_ASSOC], 0);
++ iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_RX], 0);
++ iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_TX], 0);
++ iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_RADIO], 1);
++}
++EXPORT_SYMBOL(iwl_leds_unregister);
++
+diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h
+new file mode 100644
+index 0000000..5bb0412
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-led.h
+@@ -0,0 +1,82 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called LICENSE.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ *****************************************************************************/
++
++#ifndef __iwl_leds_h__
++#define __iwl_leds_h__
++
++
++struct iwl_priv;
++
++#ifdef CONFIG_IWLWIFI_LEDS
++#include <linux/leds.h>
++
++#define IWL_LED_SOLID 11
++#define IWL_LED_NAME_LEN 31
++#define IWL_DEF_LED_INTRVL __constant_cpu_to_le32(1000)
++
++#define IWL_LED_ACTIVITY (0<<1)
++#define IWL_LED_LINK (1<<1)
++
++enum led_type {
++ IWL_LED_TRG_TX,
++ IWL_LED_TRG_RX,
++ IWL_LED_TRG_ASSOC,
++ IWL_LED_TRG_RADIO,
++ IWL_LED_TRG_MAX,
++};
++
++
++struct iwl4965_led {
++ struct iwl_priv *priv;
++ struct led_classdev led_dev;
++
++ int (*led_on) (struct iwl_priv *priv, int led_id);
++ int (*led_off) (struct iwl_priv *priv, int led_id);
++ int (*led_pattern) (struct iwl_priv *priv, int led_id,
++ enum led_brightness brightness);
++
++ enum led_type type;
++ unsigned int registered;
++};
++
++int iwl_leds_register(struct iwl_priv *priv);
++void iwl_leds_unregister(struct iwl_priv *priv);
++void iwl_leds_background(struct iwl_priv *priv);
++
++#else
++static inline int iwl_leds_register(struct iwl_priv *priv)
++{
++ return 0;
++}
++static inline void iwl_leds_unregister(struct iwl_priv *priv)
++{
++}
++static inline void iwl_leds_background(struct iwl_priv *priv)
++{
++}
++
++#endif /* CONFIG_IWLWIFI_LEDS */
++#endif /* __iwl_leds_h__ */
+diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
+index 4ba1216..c9cf8ee 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
++++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
+@@ -5,7 +5,7 @@
+ *
+ * GPL LICENSE SUMMARY
+ *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+@@ -30,7 +30,7 @@
+ *
+ * BSD LICENSE
+ *
+- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -243,44 +243,48 @@
+ * 4965 Tx Scheduler registers.
+ * Details are documented in iwl-4965-hw.h
+ */
+-#define KDR_SCD_BASE (PRPH_BASE + 0xa02c00)
++#define IWL49_SCD_BASE (PRPH_BASE + 0xa02c00)
+
+-#define KDR_SCD_SRAM_BASE_ADDR (KDR_SCD_BASE + 0x0)
+-#define KDR_SCD_EMPTY_BITS (KDR_SCD_BASE + 0x4)
+-#define KDR_SCD_DRAM_BASE_ADDR (KDR_SCD_BASE + 0x10)
+-#define KDR_SCD_AIT (KDR_SCD_BASE + 0x18)
+-#define KDR_SCD_TXFACT (KDR_SCD_BASE + 0x1c)
+-#define KDR_SCD_QUEUE_WRPTR(x) (KDR_SCD_BASE + 0x24 + (x) * 4)
+-#define KDR_SCD_QUEUE_RDPTR(x) (KDR_SCD_BASE + 0x64 + (x) * 4)
+-#define KDR_SCD_SETQUEUENUM (KDR_SCD_BASE + 0xa4)
+-#define KDR_SCD_SET_TXSTAT_TXED (KDR_SCD_BASE + 0xa8)
+-#define KDR_SCD_SET_TXSTAT_DONE (KDR_SCD_BASE + 0xac)
+-#define KDR_SCD_SET_TXSTAT_NOT_SCHD (KDR_SCD_BASE + 0xb0)
+-#define KDR_SCD_DECREASE_CREDIT (KDR_SCD_BASE + 0xb4)
+-#define KDR_SCD_DECREASE_SCREDIT (KDR_SCD_BASE + 0xb8)
+-#define KDR_SCD_LOAD_CREDIT (KDR_SCD_BASE + 0xbc)
+-#define KDR_SCD_LOAD_SCREDIT (KDR_SCD_BASE + 0xc0)
+-#define KDR_SCD_BAR (KDR_SCD_BASE + 0xc4)
+-#define KDR_SCD_BAR_DW0 (KDR_SCD_BASE + 0xc8)
+-#define KDR_SCD_BAR_DW1 (KDR_SCD_BASE + 0xcc)
+-#define KDR_SCD_QUEUECHAIN_SEL (KDR_SCD_BASE + 0xd0)
+-#define KDR_SCD_QUERY_REQ (KDR_SCD_BASE + 0xd8)
+-#define KDR_SCD_QUERY_RES (KDR_SCD_BASE + 0xdc)
+-#define KDR_SCD_PENDING_FRAMES (KDR_SCD_BASE + 0xe0)
+-#define KDR_SCD_INTERRUPT_MASK (KDR_SCD_BASE + 0xe4)
+-#define KDR_SCD_INTERRUPT_THRESHOLD (KDR_SCD_BASE + 0xe8)
+-#define KDR_SCD_QUERY_MIN_FRAME_SIZE (KDR_SCD_BASE + 0x100)
+-#define KDR_SCD_QUEUE_STATUS_BITS(x) (KDR_SCD_BASE + 0x104 + (x) * 4)
++#define IWL49_SCD_SRAM_BASE_ADDR (IWL49_SCD_BASE + 0x0)
++#define IWL49_SCD_EMPTY_BITS (IWL49_SCD_BASE + 0x4)
++#define IWL49_SCD_DRAM_BASE_ADDR (IWL49_SCD_BASE + 0x10)
++#define IWL49_SCD_AIT (IWL49_SCD_BASE + 0x18)
++#define IWL49_SCD_TXFACT (IWL49_SCD_BASE + 0x1c)
++#define IWL49_SCD_QUEUE_WRPTR(x) (IWL49_SCD_BASE + 0x24 + (x) * 4)
++#define IWL49_SCD_QUEUE_RDPTR(x) (IWL49_SCD_BASE + 0x64 + (x) * 4)
++#define IWL49_SCD_SETQUEUENUM (IWL49_SCD_BASE + 0xa4)
++#define IWL49_SCD_SET_TXSTAT_TXED (IWL49_SCD_BASE + 0xa8)
++#define IWL49_SCD_SET_TXSTAT_DONE (IWL49_SCD_BASE + 0xac)
++#define IWL49_SCD_SET_TXSTAT_NOT_SCHD (IWL49_SCD_BASE + 0xb0)
++#define IWL49_SCD_DECREASE_CREDIT (IWL49_SCD_BASE + 0xb4)
++#define IWL49_SCD_DECREASE_SCREDIT (IWL49_SCD_BASE + 0xb8)
++#define IWL49_SCD_LOAD_CREDIT (IWL49_SCD_BASE + 0xbc)
++#define IWL49_SCD_LOAD_SCREDIT (IWL49_SCD_BASE + 0xc0)
++#define IWL49_SCD_BAR (IWL49_SCD_BASE + 0xc4)
++#define IWL49_SCD_BAR_DW0 (IWL49_SCD_BASE + 0xc8)
++#define IWL49_SCD_BAR_DW1 (IWL49_SCD_BASE + 0xcc)
++#define IWL49_SCD_QUEUECHAIN_SEL (IWL49_SCD_BASE + 0xd0)
++#define IWL49_SCD_QUERY_REQ (IWL49_SCD_BASE + 0xd8)
++#define IWL49_SCD_QUERY_RES (IWL49_SCD_BASE + 0xdc)
++#define IWL49_SCD_PENDING_FRAMES (IWL49_SCD_BASE + 0xe0)
++#define IWL49_SCD_INTERRUPT_MASK (IWL49_SCD_BASE + 0xe4)
++#define IWL49_SCD_INTERRUPT_THRESHOLD (IWL49_SCD_BASE + 0xe8)
++#define IWL49_SCD_QUERY_MIN_FRAME_SIZE (IWL49_SCD_BASE + 0x100)
++#define IWL49_SCD_QUEUE_STATUS_BITS(x) (IWL49_SCD_BASE + 0x104 + (x) * 4)
+
+ /* SP SCD */
+-#define SHL_SCD_BASE (PRPH_BASE + 0xa02c00)
++#define IWL50_SCD_BASE (PRPH_BASE + 0xa02c00)
+
+-#define SHL_SCD_AIT (SHL_SCD_BASE + 0x0c)
+-#define SHL_SCD_TXFACT (SHL_SCD_BASE + 0x10)
+-#define SHL_SCD_QUEUE_WRPTR(x) (SHL_SCD_BASE + 0x18 + (x) * 4)
+-#define SHL_SCD_QUEUE_RDPTR(x) (SHL_SCD_BASE + 0x68 + (x) * 4)
+-#define SHL_SCD_QUEUECHAIN_SEL (SHL_SCD_BASE + 0xe8)
+-#define SHL_SCD_AGGR_SEL (SHL_SCD_BASE + 0x248)
+-#define SHL_SCD_INTERRUPT_MASK (SHL_SCD_BASE + 0x108)
++#define IWL50_SCD_SRAM_BASE_ADDR (IWL50_SCD_BASE + 0x0)
++#define IWL50_SCD_DRAM_BASE_ADDR (IWL50_SCD_BASE + 0x8)
++#define IWL50_SCD_AIT (IWL50_SCD_BASE + 0x0c)
++#define IWL50_SCD_TXFACT (IWL50_SCD_BASE + 0x10)
++#define IWL50_SCD_ACTIVE (IWL50_SCD_BASE + 0x14)
++#define IWL50_SCD_QUEUE_WRPTR(x) (IWL50_SCD_BASE + 0x18 + (x) * 4)
++#define IWL50_SCD_QUEUE_RDPTR(x) (IWL50_SCD_BASE + 0x68 + (x) * 4)
++#define IWL50_SCD_QUEUECHAIN_SEL (IWL50_SCD_BASE + 0xe8)
++#define IWL50_SCD_AGGR_SEL (IWL50_SCD_BASE + 0x248)
++#define IWL50_SCD_INTERRUPT_MASK (IWL50_SCD_BASE + 0x108)
++#define IWL50_SCD_QUEUE_STATUS_BITS(x) (IWL50_SCD_BASE + 0x10c + (x) * 4)
+
+ #endif /* __iwl_prph_h__ */
+diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
+new file mode 100644
+index 0000000..5980a56
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
+@@ -0,0 +1,173 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
++ *
++ * Portions of this file are derived from the ipw3945 project, as well
++ * as portions of the ieee80211 subsystem header files.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called LICENSE.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *****************************************************************************/
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/init.h>
++
++#include <net/mac80211.h>
++
++#include "iwl-eeprom.h"
++#include "iwl-4965.h"
++#include "iwl-core.h"
++#include "iwl-helpers.h"
++
++
++/* software rf-kill from user */
++static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
++{
++ struct iwl_priv *priv = data;
++ int err = 0;
++
++ if (!priv->rfkill_mngr.rfkill)
++ return 0;
++
++ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
++ return 0;
++
++ IWL_DEBUG_RF_KILL("we recieved soft RFKILL set to state %d\n", state);
++ mutex_lock(&priv->mutex);
++
++ switch (state) {
++ case RFKILL_STATE_ON:
++ priv->cfg->ops->lib->radio_kill_sw(priv, 0);
++ /* if HW rf-kill is set dont allow ON state */
++ if (iwl_is_rfkill(priv))
++ err = -EBUSY;
++ break;
++ case RFKILL_STATE_OFF:
++ priv->cfg->ops->lib->radio_kill_sw(priv, 1);
++ if (!iwl_is_rfkill(priv))
++ err = -EBUSY;
++ break;
++ }
++ mutex_unlock(&priv->mutex);
++
++ return err;
++}
++
++int iwl_rfkill_init(struct iwl_priv *priv)
++{
++ struct device *device = wiphy_dev(priv->hw->wiphy);
++ int ret = 0;
++
++ BUG_ON(device == NULL);
++
++ IWL_DEBUG_RF_KILL("Initializing RFKILL.\n");
++ priv->rfkill_mngr.rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN);
++ if (!priv->rfkill_mngr.rfkill) {
++ IWL_ERROR("Unable to allocate rfkill device.\n");
++ ret = -ENOMEM;
++ goto error;
++ }
++
++ priv->rfkill_mngr.rfkill->name = priv->cfg->name;
++ priv->rfkill_mngr.rfkill->data = priv;
++ priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON;
++ priv->rfkill_mngr.rfkill->toggle_radio = iwl_rfkill_soft_rf_kill;
++ priv->rfkill_mngr.rfkill->user_claim_unsupported = 1;
++
++ priv->rfkill_mngr.rfkill->dev.class->suspend = NULL;
++ priv->rfkill_mngr.rfkill->dev.class->resume = NULL;
++
++ priv->rfkill_mngr.input_dev = input_allocate_device();
++ if (!priv->rfkill_mngr.input_dev) {
++ IWL_ERROR("Unable to allocate rfkill input device.\n");
++ ret = -ENOMEM;
++ goto freed_rfkill;
++ }
++
++ priv->rfkill_mngr.input_dev->name = priv->cfg->name;
++ priv->rfkill_mngr.input_dev->phys = wiphy_name(priv->hw->wiphy);
++ priv->rfkill_mngr.input_dev->id.bustype = BUS_HOST;
++ priv->rfkill_mngr.input_dev->id.vendor = priv->pci_dev->vendor;
++ priv->rfkill_mngr.input_dev->dev.parent = device;
++ priv->rfkill_mngr.input_dev->evbit[0] = BIT(EV_KEY);
++ set_bit(KEY_WLAN, priv->rfkill_mngr.input_dev->keybit);
++
++ ret = rfkill_register(priv->rfkill_mngr.rfkill);
++ if (ret) {
++ IWL_ERROR("Unable to register rfkill: %d\n", ret);
++ goto free_input_dev;
++ }
++
++ ret = input_register_device(priv->rfkill_mngr.input_dev);
++ if (ret) {
++ IWL_ERROR("Unable to register rfkill input device: %d\n", ret);
++ goto unregister_rfkill;
++ }
++
++ IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
++ return ret;
++
++unregister_rfkill:
++ rfkill_unregister(priv->rfkill_mngr.rfkill);
++ priv->rfkill_mngr.rfkill = NULL;
++
++free_input_dev:
++ input_free_device(priv->rfkill_mngr.input_dev);
++ priv->rfkill_mngr.input_dev = NULL;
++
++freed_rfkill:
++ if (priv->rfkill_mngr.rfkill != NULL)
++ rfkill_free(priv->rfkill_mngr.rfkill);
++ priv->rfkill_mngr.rfkill = NULL;
++
++error:
++ IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
++ return ret;
++}
++EXPORT_SYMBOL(iwl_rfkill_init);
++
++void iwl_rfkill_unregister(struct iwl_priv *priv)
++{
++
++ if (priv->rfkill_mngr.input_dev)
++ input_unregister_device(priv->rfkill_mngr.input_dev);
++
++ if (priv->rfkill_mngr.rfkill)
++ rfkill_unregister(priv->rfkill_mngr.rfkill);
++
++ priv->rfkill_mngr.input_dev = NULL;
++ priv->rfkill_mngr.rfkill = NULL;
++}
++EXPORT_SYMBOL(iwl_rfkill_unregister);
++
++/* set rf-kill to the right state. */
++void iwl_rfkill_set_hw_state(struct iwl_priv *priv)
++{
++
++ if (!priv->rfkill_mngr.rfkill)
++ return;
++
++ if (!iwl_is_rfkill(priv))
++ priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON;
++ else
++ priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF;
++}
++EXPORT_SYMBOL(iwl_rfkill_set_hw_state);
+diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.h b/drivers/net/wireless/iwlwifi/iwl-rfkill.h
+new file mode 100644
+index 0000000..a7f04b8
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.h
+@@ -0,0 +1,54 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
++ *
++ * Portions of this file are derived from the ipw3945 project, as well
++ * as portions of the ieee80211 subsystem header files.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called LICENSE.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *****************************************************************************/
++#ifndef __iwl_rf_kill_h__
++#define __iwl_rf_kill_h__
++
++struct iwl_priv;
++
++#include <linux/rfkill.h>
++#include <linux/input.h>
++
++
++#ifdef CONFIG_IWLWIFI_RFKILL
++struct iwl_rfkill_mngr {
++ struct rfkill *rfkill;
++ struct input_dev *input_dev;
++};
++
++void iwl_rfkill_set_hw_state(struct iwl_priv *priv);
++void iwl_rfkill_unregister(struct iwl_priv *priv);
++int iwl_rfkill_init(struct iwl_priv *priv);
++#else
++static inline void iwl_rfkill_set_hw_state(struct iwl_priv *priv) {}
++static inline void iwl_rfkill_unregister(struct iwl_priv *priv) {}
++static inline int iwl_rfkill_init(struct iwl_priv *priv) { return 0; }
++#endif
++
++
++
++#endif /* __iwl_rf_kill_h__ */
+diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.h b/drivers/net/wireless/iwlwifi/iwl-spectrum.h
+index b576ff2..a40a217 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-spectrum.h
++++ b/drivers/net/wireless/iwlwifi/iwl-spectrum.h
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+ *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ieee80211 subsystem header files.
+ *
+diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
+new file mode 100644
+index 0000000..e4fdfaa
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
+@@ -0,0 +1,355 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
++ *
++ * Portions of this file are derived from the ipw3945 project, as well
++ * as portions of the ieee80211 subsystem header files.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called LICENSE.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ *****************************************************************************/
++
++#include <net/mac80211.h>
++
++#include "iwl-eeprom.h"
++#include "iwl-4965.h"
++#include "iwl-core.h"
++#include "iwl-sta.h"
++#include "iwl-io.h"
++#include "iwl-helpers.h"
++#include "iwl-4965.h"
++#include "iwl-sta.h"
++
++int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
++{
++ int i;
++
++ for (i = 0; i < STA_KEY_MAX_NUM; i++)
++ if (!test_and_set_bit(i, &priv->ucode_key_table))
++ return i;
++
++ return -1;
++}
++
++int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
++{
++ int i, not_empty = 0;
++ u8 buff[sizeof(struct iwl_wep_cmd) +
++ sizeof(struct iwl_wep_key) * WEP_KEYS_MAX];
++ struct iwl_wep_cmd *wep_cmd = (struct iwl_wep_cmd *)buff;
++ size_t cmd_size = sizeof(struct iwl_wep_cmd);
++ struct iwl_host_cmd cmd = {
++ .id = REPLY_WEPKEY,
++ .data = wep_cmd,
++ .meta.flags = CMD_ASYNC,
++ };
++
++ memset(wep_cmd, 0, cmd_size +
++ (sizeof(struct iwl_wep_key) * WEP_KEYS_MAX));
++
++ for (i = 0; i < WEP_KEYS_MAX ; i++) {
++ wep_cmd->key[i].key_index = i;
++ if (priv->wep_keys[i].key_size) {
++ wep_cmd->key[i].key_offset = i;
++ not_empty = 1;
++ } else {
++ wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET;
++ }
++
++ wep_cmd->key[i].key_size = priv->wep_keys[i].key_size;
++ memcpy(&wep_cmd->key[i].key[3], priv->wep_keys[i].key,
++ priv->wep_keys[i].key_size);
++ }
++
++ wep_cmd->global_key_type = WEP_KEY_WEP_TYPE;
++ wep_cmd->num_keys = WEP_KEYS_MAX;
++
++ cmd_size += sizeof(struct iwl_wep_key) * WEP_KEYS_MAX;
++
++ cmd.len = cmd_size;
++
++ if (not_empty || send_if_empty)
++ return iwl_send_cmd(priv, &cmd);
++ else
++ return 0;
++}
++
++int iwl_remove_default_wep_key(struct iwl_priv *priv,
++ struct ieee80211_key_conf *keyconf)
++{
++ int ret;
++ unsigned long flags;
++
++ spin_lock_irqsave(&priv->sta_lock, flags);
++
++ if (!test_and_clear_bit(keyconf->keyidx, &priv->ucode_key_table))
++ IWL_ERROR("index %d not used in uCode key table.\n",
++ keyconf->keyidx);
++
++ priv->default_wep_key--;
++ memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0]));
++ ret = iwl_send_static_wepkey_cmd(priv, 1);
++ spin_unlock_irqrestore(&priv->sta_lock, flags);
++
++ return ret;
++}
++
++int iwl_set_default_wep_key(struct iwl_priv *priv,
++ struct ieee80211_key_conf *keyconf)
++{
++ int ret;
++ unsigned long flags;
++
++ keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
++ keyconf->hw_key_idx = keyconf->keyidx;
++ priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP;
++
++ spin_lock_irqsave(&priv->sta_lock, flags);
++ priv->default_wep_key++;
++
++ if (test_and_set_bit(keyconf->keyidx, &priv->ucode_key_table))
++ IWL_ERROR("index %d already used in uCode key table.\n",
++ keyconf->keyidx);
++
++ priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
++ memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key,
++ keyconf->keylen);
++
++ ret = iwl_send_static_wepkey_cmd(priv, 0);
++ spin_unlock_irqrestore(&priv->sta_lock, flags);
++
++ return ret;
++}
++
++static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
++ struct ieee80211_key_conf *keyconf,
++ u8 sta_id)
++{
++ unsigned long flags;
++ __le16 key_flags = 0;
++ int ret;
++
++ keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
++ keyconf->hw_key_idx = keyconf->keyidx;
++
++ key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK);
++ key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
++ key_flags &= ~STA_KEY_FLG_INVALID;
++
++ if (keyconf->keylen == WEP_KEY_LEN_128)
++ key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
++
++ if (sta_id == priv->hw_params.bcast_sta_id)
++ key_flags |= STA_KEY_MULTICAST_MSK;
++
++ spin_lock_irqsave(&priv->sta_lock, flags);
++
++ priv->stations[sta_id].keyinfo.alg = keyconf->alg;
++ priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
++ priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx;
++
++ memcpy(priv->stations[sta_id].keyinfo.key,
++ keyconf->key, keyconf->keylen);
++
++ memcpy(&priv->stations[sta_id].sta.key.key[3],
++ keyconf->key, keyconf->keylen);
++
++ priv->stations[sta_id].sta.key.key_offset =
++ iwl_get_free_ucode_key_index(priv);
++ priv->stations[sta_id].sta.key.key_flags = key_flags;
++
++ priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
++ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
++
++ ret = iwl4965_send_add_station(priv,
++ &priv->stations[sta_id].sta, CMD_ASYNC);
++
++ spin_unlock_irqrestore(&priv->sta_lock, flags);
++
++ return ret;
++}
++
++static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
++ struct ieee80211_key_conf *keyconf,
++ u8 sta_id)
++{
++ unsigned long flags;
++ __le16 key_flags = 0;
++
++ key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
++ key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
++ key_flags &= ~STA_KEY_FLG_INVALID;
++
++ if (sta_id == priv->hw_params.bcast_sta_id)
++ key_flags |= STA_KEY_MULTICAST_MSK;
++
++ keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
++ keyconf->hw_key_idx = keyconf->keyidx;
++
++ spin_lock_irqsave(&priv->sta_lock, flags);
++ priv->stations[sta_id].keyinfo.alg = keyconf->alg;
++ priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
++
++ memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
++ keyconf->keylen);
++
++ memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
++ keyconf->keylen);
++
++ priv->stations[sta_id].sta.key.key_offset =
++ iwl_get_free_ucode_key_index(priv);
++ priv->stations[sta_id].sta.key.key_flags = key_flags;
++ priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
++ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
++
++ spin_unlock_irqrestore(&priv->sta_lock, flags);
++
++ IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n");
++ return iwl4965_send_add_station(priv,
++ &priv->stations[sta_id].sta, CMD_ASYNC);
++}
++
++static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
++ struct ieee80211_key_conf *keyconf,
++ u8 sta_id)
++{
++ unsigned long flags;
++ int ret = 0;
++
++ keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
++ keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
++ keyconf->hw_key_idx = keyconf->keyidx;
++
++ spin_lock_irqsave(&priv->sta_lock, flags);
++
++ priv->stations[sta_id].keyinfo.alg = keyconf->alg;
++ priv->stations[sta_id].keyinfo.conf = keyconf;
++ priv->stations[sta_id].keyinfo.keylen = 16;
++ priv->stations[sta_id].sta.key.key_offset =
++ iwl_get_free_ucode_key_index(priv);
++
++ /* This copy is acutally not needed: we get the key with each TX */
++ memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16);
++
++ memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16);
++
++ spin_unlock_irqrestore(&priv->sta_lock, flags);
++
++ return ret;
++}
++
++int iwl_remove_dynamic_key(struct iwl_priv *priv, u8 sta_id)
++{
++ unsigned long flags;
++
++ priv->key_mapping_key = 0;
++
++ spin_lock_irqsave(&priv->sta_lock, flags);
++ if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset,
++ &priv->ucode_key_table))
++ IWL_ERROR("index %d not used in uCode key table.\n",
++ priv->stations[sta_id].sta.key.key_offset);
++ memset(&priv->stations[sta_id].keyinfo, 0,
++ sizeof(struct iwl4965_hw_key));
++ memset(&priv->stations[sta_id].sta.key, 0,
++ sizeof(struct iwl4965_keyinfo));
++ priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
++ priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
++ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
++ spin_unlock_irqrestore(&priv->sta_lock, flags);
++
++ IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n");
++ return iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0);
++}
++
++int iwl_set_dynamic_key(struct iwl_priv *priv,
++ struct ieee80211_key_conf *key, u8 sta_id)
++{
++ int ret;
++
++ priv->key_mapping_key = 1;
++
++ switch (key->alg) {
++ case ALG_CCMP:
++ ret = iwl_set_ccmp_dynamic_key_info(priv, key, sta_id);
++ break;
++ case ALG_TKIP:
++ ret = iwl_set_tkip_dynamic_key_info(priv, key, sta_id);
++ break;
++ case ALG_WEP:
++ ret = iwl_set_wep_dynamic_key_info(priv, key, sta_id);
++ break;
++ default:
++ IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, key->alg);
++ ret = -EINVAL;
++ }
++
++ return ret;
++}
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++static void iwl_dump_lq_cmd(struct iwl_priv *priv,
++ struct iwl_link_quality_cmd *lq)
++{
++ int i;
++ IWL_DEBUG_RATE("lq station id 0x%x\n", lq->sta_id);
++ IWL_DEBUG_RATE("lq dta 0x%X 0x%X\n",
++ lq->general_params.single_stream_ant_msk,
++ lq->general_params.dual_stream_ant_msk);
++
++ for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
++ IWL_DEBUG_RATE("lq index %d 0x%X\n",
++ i, lq->rs_table[i].rate_n_flags);
++}
++#else
++static inline void iwl_dump_lq_cmd(struct iwl_priv *priv,
++ struct iwl_link_quality_cmd *lq)
++{
++}
++#endif
++
++int iwl_send_lq_cmd(struct iwl_priv *priv,
++ struct iwl_link_quality_cmd *lq, u8 flags)
++{
++ struct iwl_host_cmd cmd = {
++ .id = REPLY_TX_LINK_QUALITY_CMD,
++ .len = sizeof(struct iwl_link_quality_cmd),
++ .meta.flags = flags,
++ .data = lq,
++ };
++
++ if ((lq->sta_id == 0xFF) &&
++ (priv->iw_mode == IEEE80211_IF_TYPE_IBSS))
++ return -EINVAL;
++
++ if (lq->sta_id == 0xFF)
++ lq->sta_id = IWL_AP_ID;
++
++ iwl_dump_lq_cmd(priv,lq);
++
++ if (iwl_is_associated(priv) && priv->assoc_station_added &&
++ priv->lq_mngr.lq_ready)
++ return iwl_send_cmd(priv, &cmd);
++
++ return 0;
++}
++EXPORT_SYMBOL(iwl_send_lq_cmd);
++
+diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
+new file mode 100644
+index 0000000..44f272e
+--- /dev/null
++++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
+@@ -0,0 +1,49 @@
++/******************************************************************************
++ *
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
++ *
++ * Portions of this file are derived from the ipw3945 project, as well
++ * as portions of the ieee80211 subsystem header files.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
++ *
++ * The full GNU General Public License is included in this distribution in the
++ * file called LICENSE.
++ *
++ * Contact Information:
++ * James P. Ketrenos <ipw2100-admin at linux.intel.com>
++ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++ *
++ *****************************************************************************/
++#ifndef __iwl_sta_h__
++#define __iwl_sta_h__
++
++#include <net/mac80211.h>
++
++#include "iwl-eeprom.h"
++#include "iwl-core.h"
++#include "iwl-4965.h"
++#include "iwl-io.h"
++#include "iwl-helpers.h"
++
++int iwl_get_free_ucode_key_index(struct iwl_priv *priv);
++int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty);
++int iwl_remove_default_wep_key(struct iwl_priv *priv,
++ struct ieee80211_key_conf *key);
++int iwl_set_default_wep_key(struct iwl_priv *priv,
++ struct ieee80211_key_conf *key);
++int iwl_remove_dynamic_key(struct iwl_priv *priv, u8 sta_id);
++int iwl_set_dynamic_key(struct iwl_priv *priv,
++ struct ieee80211_key_conf *key, u8 sta_id);
++#endif /* __iwl_sta_h__ */
+diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
+index cbaeaf1..a1a0b3c 100644
+--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
++++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+ *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+@@ -46,6 +46,7 @@
+
+ #include <asm/div64.h>
+
++#include "iwl-3945-core.h"
+ #include "iwl-3945.h"
+ #include "iwl-helpers.h"
+
+@@ -69,7 +70,7 @@ static int iwl3945_param_disable; /* def: 0 = enable radio */
+ static int iwl3945_param_antenna; /* def: 0 = both antennas (use diversity) */
+ int iwl3945_param_hwcrypto; /* def: 0 = use software encryption */
+ static int iwl3945_param_qos_enable = 1; /* def: 1 = use quality of service */
+-int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 8 Tx queues */
++int iwl3945_param_queues_num = IWL39_MAX_NUM_QUEUES; /* def: 8 Tx queues */
+
+ /*
+ * module name, copyright, version, etc.
+@@ -91,15 +92,10 @@ int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 8 Tx queues */
+ #define VS
+ #endif
+
+-#define IWLWIFI_VERSION "1.2.23k" VD VS
+-#define DRV_COPYRIGHT "Copyright(c) 2003-2007 Intel Corporation"
++#define IWLWIFI_VERSION "1.2.26k" VD VS
++#define DRV_COPYRIGHT "Copyright(c) 2003-2008 Intel Corporation"
+ #define DRV_VERSION IWLWIFI_VERSION
+
+-/* Change firmware file name, using "-" and incrementing number,
+- * *only* when uCode interface or architecture changes so that it
+- * is not compatible with earlier drivers.
+- * This number will also appear in << 8 position of 1st dword of uCode file */
+-#define IWL3945_UCODE_API "-1"
+
+ MODULE_DESCRIPTION(DRV_DESCRIPTION);
+ MODULE_VERSION(DRV_VERSION);
+@@ -116,16 +112,10 @@ static __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr)
+ return NULL;
+ }
+
+-static const struct ieee80211_hw_mode *iwl3945_get_hw_mode(
+- struct iwl3945_priv *priv, int mode)
++static const struct ieee80211_supported_band *iwl3945_get_band(
++ struct iwl3945_priv *priv, enum ieee80211_band band)
+ {
+- int i;
+-
+- for (i = 0; i < 3; i++)
+- if (priv->modes[i].mode == mode)
+- return &priv->modes[i];
+-
+- return NULL;
++ return priv->hw->wiphy->bands[band];
+ }
+
+ static int iwl3945_is_empty_essid(const char *essid, int essid_len)
+@@ -168,17 +158,6 @@ static const char *iwl3945_escape_essid(const char *essid, u8 essid_len)
+ return escaped;
+ }
+
+-static void iwl3945_print_hex_dump(int level, void *p, u32 len)
+-{
+-#ifdef CONFIG_IWL3945_DEBUG
+- if (!(iwl3945_debug_level & level))
+- return;
+-
+- print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1,
+- p, len, 1);
+-#endif
+-}
+-
+ /*************** DMA-QUEUE-GENERAL-FUNCTIONS *****
+ * DMA services
+ *
+@@ -204,7 +183,7 @@ static void iwl3945_print_hex_dump(int level, void *p, u32 len)
+ * (#0-3) for data tx via EDCA. An additional 2 HCCA queues are unused.
+ ***************************************************/
+
+-static int iwl3945_queue_space(const struct iwl3945_queue *q)
++int iwl3945_queue_space(const struct iwl3945_queue *q)
+ {
+ int s = q->read_ptr - q->write_ptr;
+
+@@ -220,33 +199,14 @@ static int iwl3945_queue_space(const struct iwl3945_queue *q)
+ return s;
+ }
+
+-/**
+- * iwl3945_queue_inc_wrap - increment queue index, wrap back to beginning
+- * @index -- current index
+- * @n_bd -- total number of entries in queue (must be power of 2)
+- */
+-static inline int iwl3945_queue_inc_wrap(int index, int n_bd)
+-{
+- return ++index & (n_bd - 1);
+-}
+-
+-/**
+- * iwl3945_queue_dec_wrap - increment queue index, wrap back to end
+- * @index -- current index
+- * @n_bd -- total number of entries in queue (must be power of 2)
+- */
+-static inline int iwl3945_queue_dec_wrap(int index, int n_bd)
+-{
+- return --index & (n_bd - 1);
+-}
+-
+-static inline int x2_queue_used(const struct iwl3945_queue *q, int i)
++int iwl3945_x2_queue_used(const struct iwl3945_queue *q, int i)
+ {
+ return q->write_ptr > q->read_ptr ?
+ (i >= q->read_ptr && i < q->write_ptr) :
+ !(i < q->read_ptr && i >= q->write_ptr);
+ }
+
++
+ static inline u8 get_cmd_index(struct iwl3945_queue *q, u32 index, int is_huge)
+ {
+ /* This is for scan command, the big buffer at end of command array */
+@@ -267,8 +227,8 @@ static int iwl3945_queue_init(struct iwl3945_priv *priv, struct iwl3945_queue *q
+ q->n_window = slots_num;
+ q->id = id;
+
+- /* count must be power-of-two size, otherwise iwl3945_queue_inc_wrap
+- * and iwl3945_queue_dec_wrap are broken. */
++ /* count must be power-of-two size, otherwise iwl_queue_inc_wrap
++ * and iwl_queue_dec_wrap are broken. */
+ BUG_ON(!is_power_of_2(count));
+
+ /* slots_num must be power-of-two size, otherwise
+@@ -368,7 +328,7 @@ int iwl3945_tx_queue_init(struct iwl3945_priv *priv,
+ txq->need_update = 0;
+
+ /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
+- * iwl3945_queue_inc_wrap and iwl3945_queue_dec_wrap are broken. */
++ * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
+ BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
+
+ /* Initialize queue high/low-water, head/tail indexes */
+@@ -399,7 +359,7 @@ void iwl3945_tx_queue_free(struct iwl3945_priv *priv, struct iwl3945_tx_queue *t
+
+ /* first, empty all BD's */
+ for (; q->write_ptr != q->read_ptr;
+- q->read_ptr = iwl3945_queue_inc_wrap(q->read_ptr, q->n_bd))
++ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd))
+ iwl3945_hw_txq_free_tfd(priv, txq);
+
+ len = sizeof(struct iwl3945_cmd) * q->n_window;
+@@ -547,7 +507,7 @@ u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8
+ station->sta.sta.sta_id = index;
+ station->sta.station_flags = 0;
+
+- if (priv->phymode == MODE_IEEE80211A)
++ if (priv->band == IEEE80211_BAND_5GHZ)
+ rate = IWL_RATE_6M_PLCP;
+ else
+ rate = IWL_RATE_1M_PLCP;
+@@ -738,7 +698,7 @@ static int iwl3945_enqueue_hcmd(struct iwl3945_priv *priv, struct iwl3945_host_c
+ txq->need_update = 1;
+
+ /* Increment and update queue's write index */
+- q->write_ptr = iwl3945_queue_inc_wrap(q->write_ptr, q->n_bd);
++ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
+ ret = iwl3945_tx_queue_update_write_ptr(priv, txq);
+
+ spin_unlock_irqrestore(&priv->hcmd_lock, flags);
+@@ -773,17 +733,17 @@ static int iwl3945_send_cmd_sync(struct iwl3945_priv *priv, struct iwl3945_host_
+ {
+ int cmd_idx;
+ int ret;
+- static atomic_t entry = ATOMIC_INIT(0); /* reentrance protection */
+
+ BUG_ON(cmd->meta.flags & CMD_ASYNC);
+
+ /* A synchronous command can not have a callback set. */
+ BUG_ON(cmd->meta.u.callback != NULL);
+
+- if (atomic_xchg(&entry, 1)) {
++ if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) {
+ IWL_ERROR("Error sending %s: Already sending a host command\n",
+ get_cmd_string(cmd->id));
+- return -EBUSY;
++ ret = -EBUSY;
++ goto out;
+ }
+
+ set_bit(STATUS_HCMD_ACTIVE, &priv->status);
+@@ -853,7 +813,7 @@ fail:
+ cmd->meta.u.skb = NULL;
+ }
+ out:
+- atomic_set(&entry, 0);
++ clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status);
+ return ret;
+ }
+
+@@ -894,35 +854,37 @@ int iwl3945_send_statistics_request(struct iwl3945_priv *priv)
+
+ /**
+ * iwl3945_set_rxon_channel - Set the phymode and channel values in staging RXON
+- * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
+- * @channel: Any channel valid for the requested phymode
++ * @band: 2.4 or 5 GHz band
++ * @channel: Any channel valid for the requested band
+
+- * In addition to setting the staging RXON, priv->phymode is also set.
++ * In addition to setting the staging RXON, priv->band is also set.
+ *
+ * NOTE: Does not commit to the hardware; it sets appropriate bit fields
+- * in the staging RXON flag structure based on the phymode
++ * in the staging RXON flag structure based on the band
+ */
+-static int iwl3945_set_rxon_channel(struct iwl3945_priv *priv, u8 phymode, u16 channel)
++static int iwl3945_set_rxon_channel(struct iwl3945_priv *priv,
++ enum ieee80211_band band,
++ u16 channel)
+ {
+- if (!iwl3945_get_channel_info(priv, phymode, channel)) {
++ if (!iwl3945_get_channel_info(priv, band, channel)) {
+ IWL_DEBUG_INFO("Could not set channel to %d [%d]\n",
+- channel, phymode);
++ channel, band);
+ return -EINVAL;
+ }
+
+ if ((le16_to_cpu(priv->staging_rxon.channel) == channel) &&
+- (priv->phymode == phymode))
++ (priv->band == band))
+ return 0;
+
+ priv->staging_rxon.channel = cpu_to_le16(channel);
+- if (phymode == MODE_IEEE80211A)
++ if (band == IEEE80211_BAND_5GHZ)
+ priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK;
+ else
+ priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
+
+- priv->phymode = phymode;
++ priv->band = band;
+
+- IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, phymode);
++ IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, band);
+
+ return 0;
+ }
+@@ -1210,8 +1172,7 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv)
+ return -EIO;
+ }
+
+- /* Init the hardware's rate fallback order based on the
+- * phymode */
++ /* Init the hardware's rate fallback order based on the band */
+ rc = iwl3945_init_hw_rate_table(priv);
+ if (rc) {
+ IWL_ERROR("Error setting HW rate table: %02X\n", rc);
+@@ -1635,151 +1596,6 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv)
+ return 0;
+ }
+
+-/******************************************************************************
+- *
+- * Misc. internal state and helper functions
+- *
+- ******************************************************************************/
+-#ifdef CONFIG_IWL3945_DEBUG
+-
+-/**
+- * iwl3945_report_frame - dump frame to syslog during debug sessions
+- *
+- * You may hack this function to show different aspects of received frames,
+- * including selective frame dumps.
+- * group100 parameter selects whether to show 1 out of 100 good frames.
+- */
+-void iwl3945_report_frame(struct iwl3945_priv *priv,
+- struct iwl3945_rx_packet *pkt,
+- struct ieee80211_hdr *header, int group100)
+-{
+- u32 to_us;
+- u32 print_summary = 0;
+- u32 print_dump = 0; /* set to 1 to dump all frames' contents */
+- u32 hundred = 0;
+- u32 dataframe = 0;
+- u16 fc;
+- u16 seq_ctl;
+- u16 channel;
+- u16 phy_flags;
+- int rate_sym;
+- u16 length;
+- u16 status;
+- u16 bcn_tmr;
+- u32 tsf_low;
+- u64 tsf;
+- u8 rssi;
+- u8 agc;
+- u16 sig_avg;
+- u16 noise_diff;
+- struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
+- struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
+- struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
+- u8 *data = IWL_RX_DATA(pkt);
+-
+- /* MAC header */
+- fc = le16_to_cpu(header->frame_control);
+- seq_ctl = le16_to_cpu(header->seq_ctrl);
+-
+- /* metadata */
+- channel = le16_to_cpu(rx_hdr->channel);
+- phy_flags = le16_to_cpu(rx_hdr->phy_flags);
+- rate_sym = rx_hdr->rate;
+- length = le16_to_cpu(rx_hdr->len);
+-
+- /* end-of-frame status and timestamp */
+- status = le32_to_cpu(rx_end->status);
+- bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp);
+- tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff;
+- tsf = le64_to_cpu(rx_end->timestamp);
+-
+- /* signal statistics */
+- rssi = rx_stats->rssi;
+- agc = rx_stats->agc;
+- sig_avg = le16_to_cpu(rx_stats->sig_avg);
+- noise_diff = le16_to_cpu(rx_stats->noise_diff);
+-
+- to_us = !compare_ether_addr(header->addr1, priv->mac_addr);
+-
+- /* if data frame is to us and all is good,
+- * (optionally) print summary for only 1 out of every 100 */
+- if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) ==
+- (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) {
+- dataframe = 1;
+- if (!group100)
+- print_summary = 1; /* print each frame */
+- else if (priv->framecnt_to_us < 100) {
+- priv->framecnt_to_us++;
+- print_summary = 0;
+- } else {
+- priv->framecnt_to_us = 0;
+- print_summary = 1;
+- hundred = 1;
+- }
+- } else {
+- /* print summary for all other frames */
+- print_summary = 1;
+- }
+-
+- if (print_summary) {
+- char *title;
+- u32 rate;
+-
+- if (hundred)
+- title = "100Frames";
+- else if (fc & IEEE80211_FCTL_RETRY)
+- title = "Retry";
+- else if (ieee80211_is_assoc_response(fc))
+- title = "AscRsp";
+- else if (ieee80211_is_reassoc_response(fc))
+- title = "RasRsp";
+- else if (ieee80211_is_probe_response(fc)) {
+- title = "PrbRsp";
+- print_dump = 1; /* dump frame contents */
+- } else if (ieee80211_is_beacon(fc)) {
+- title = "Beacon";
+- print_dump = 1; /* dump frame contents */
+- } else if (ieee80211_is_atim(fc))
+- title = "ATIM";
+- else if (ieee80211_is_auth(fc))
+- title = "Auth";
+- else if (ieee80211_is_deauth(fc))
+- title = "DeAuth";
+- else if (ieee80211_is_disassoc(fc))
+- title = "DisAssoc";
+- else
+- title = "Frame";
+-
+- rate = iwl3945_rate_index_from_plcp(rate_sym);
+- if (rate == -1)
+- rate = 0;
+- else
+- rate = iwl3945_rates[rate].ieee / 2;
+-
+- /* print frame summary.
+- * MAC addresses show just the last byte (for brevity),
+- * but you can hack it to show more, if you'd like to. */
+- if (dataframe)
+- IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, "
+- "len=%u, rssi=%d, chnl=%d, rate=%u, \n",
+- title, fc, header->addr1[5],
+- length, rssi, channel, rate);
+- else {
+- /* src/dst addresses assume managed mode */
+- IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, "
+- "src=0x%02x, rssi=%u, tim=%lu usec, "
+- "phy=0x%02x, chnl=%d\n",
+- title, fc, header->addr1[5],
+- header->addr3[5], rssi,
+- tsf_low - priv->scan_start_tsf,
+- phy_flags, channel);
+- }
+- }
+- if (print_dump)
+- iwl3945_print_hex_dump(IWL_DL_RX, data, length);
+-}
+-#endif
+-
+ static void iwl3945_unset_hw_setting(struct iwl3945_priv *priv)
+ {
+ if (priv->hw_setting.shared_virt)
+@@ -1915,7 +1731,6 @@ static u16 iwl3945_fill_probe_req(struct iwl3945_priv *priv,
+ /*
+ * QoS support
+ */
+-#ifdef CONFIG_IWL3945_QOS
+ static int iwl3945_send_qos_params_command(struct iwl3945_priv *priv,
+ struct iwl3945_qosparam_cmd *qos)
+ {
+@@ -2044,7 +1859,6 @@ static void iwl3945_activate_qos(struct iwl3945_priv *priv, u8 force)
+ }
+ }
+
+-#endif /* CONFIG_IWL3945_QOS */
+ /*
+ * Power management (not Tx power!) functions
+ */
+@@ -2244,39 +2058,13 @@ int iwl3945_is_network_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *h
+ return !compare_ether_addr(header->addr2, priv->bssid);
+ /* packets to our adapter go through */
+ return !compare_ether_addr(header->addr1, priv->mac_addr);
++ default:
++ return 1;
+ }
+
+ return 1;
+ }
+
+-#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
+-
+-static const char *iwl3945_get_tx_fail_reason(u32 status)
+-{
+- switch (status & TX_STATUS_MSK) {
+- case TX_STATUS_SUCCESS:
+- return "SUCCESS";
+- TX_STATUS_ENTRY(SHORT_LIMIT);
+- TX_STATUS_ENTRY(LONG_LIMIT);
+- TX_STATUS_ENTRY(FIFO_UNDERRUN);
+- TX_STATUS_ENTRY(MGMNT_ABORT);
+- TX_STATUS_ENTRY(NEXT_FRAG);
+- TX_STATUS_ENTRY(LIFE_EXPIRE);
+- TX_STATUS_ENTRY(DEST_PS);
+- TX_STATUS_ENTRY(ABORTED);
+- TX_STATUS_ENTRY(BT_RETRY);
+- TX_STATUS_ENTRY(STA_INVALID);
+- TX_STATUS_ENTRY(FRAG_DROPPED);
+- TX_STATUS_ENTRY(TID_DISABLE);
+- TX_STATUS_ENTRY(FRAME_FLUSHED);
+- TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL);
+- TX_STATUS_ENTRY(TX_LOCKED);
+- TX_STATUS_ENTRY(NO_BEACON_ON_RADAR);
+- }
+-
+- return "UNKNOWN";
+-}
+-
+ /**
+ * iwl3945_scan_cancel - Cancel any currently executing HW scan
+ *
+@@ -2461,9 +2249,10 @@ static int iwl3945_set_rxon_hwcrypto(struct iwl3945_priv *priv, int hw_decrypt)
+ return 0;
+ }
+
+-static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, u8 phymode)
++static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv,
++ enum ieee80211_band band)
+ {
+- if (phymode == MODE_IEEE80211A) {
++ if (band == IEEE80211_BAND_5GHZ) {
+ priv->staging_rxon.flags &=
+ ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
+ | RXON_FLG_CCK_MSK);
+@@ -2515,6 +2304,9 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
+ priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK |
+ RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
+ break;
++ default:
++ IWL_ERROR("Unsupported interface type %d\n", priv->iw_mode);
++ break;
+ }
+
+ #if 0
+@@ -2526,7 +2318,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
+ priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+ #endif
+
+- ch_info = iwl3945_get_channel_info(priv, priv->phymode,
++ ch_info = iwl3945_get_channel_info(priv, priv->band,
+ le16_to_cpu(priv->staging_rxon.channel));
+
+ if (!ch_info)
+@@ -2542,11 +2334,11 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
+
+ priv->staging_rxon.channel = cpu_to_le16(ch_info->channel);
+ if (is_channel_a_band(ch_info))
+- priv->phymode = MODE_IEEE80211A;
++ priv->band = IEEE80211_BAND_5GHZ;
+ else
+- priv->phymode = MODE_IEEE80211G;
++ priv->band = IEEE80211_BAND_2GHZ;
+
+- iwl3945_set_flags_for_phymode(priv, priv->phymode);
++ iwl3945_set_flags_for_phymode(priv, priv->band);
+
+ priv->staging_rxon.ofdm_basic_rates =
+ (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
+@@ -2560,7 +2352,7 @@ static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode)
+ const struct iwl3945_channel_info *ch_info;
+
+ ch_info = iwl3945_get_channel_info(priv,
+- priv->phymode,
++ priv->band,
+ le16_to_cpu(priv->staging_rxon.channel));
+
+ if (!ch_info || !is_channel_ibss(ch_info)) {
+@@ -2694,8 +2486,12 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv,
+ cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(3);
+ else
+ cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(2);
+- } else
++ } else {
+ cmd->cmd.tx.timeout.pm_frame_timeout = 0;
++#ifdef CONFIG_IWL3945_LEDS
++ priv->rxtxpackets += le16_to_cpu(cmd->cmd.tx.len);
++#endif
++ }
+
+ cmd->cmd.tx.driver_txop = 0;
+ cmd->cmd.tx.tx_flags = tx_flags;
+@@ -2792,7 +2588,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
+ goto drop_unlock;
+ }
+
+- if ((ctl->tx_rate & 0xFF) == IWL_INVALID_RATE) {
++ if ((ctl->tx_rate->hw_value & 0xFF) == IWL_INVALID_RATE) {
+ IWL_ERROR("ERROR: No TX rate available.\n");
+ goto drop_unlock;
+ }
+@@ -2963,7 +2759,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
+ ieee80211_get_hdrlen(fc));
+
+ /* Tell device the write index *just past* this latest filled TFD */
+- q->write_ptr = iwl3945_queue_inc_wrap(q->write_ptr, q->n_bd);
++ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
+ rc = iwl3945_tx_queue_update_write_ptr(priv, txq);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+@@ -2992,12 +2788,12 @@ drop:
+
+ static void iwl3945_set_rate(struct iwl3945_priv *priv)
+ {
+- const struct ieee80211_hw_mode *hw = NULL;
++ const struct ieee80211_supported_band *sband = NULL;
+ struct ieee80211_rate *rate;
+ int i;
+
+- hw = iwl3945_get_hw_mode(priv, priv->phymode);
+- if (!hw) {
++ sband = iwl3945_get_band(priv, priv->band);
++ if (!sband) {
+ IWL_ERROR("Failed to set rate: unable to get hw mode\n");
+ return;
+ }
+@@ -3005,24 +2801,17 @@ static void iwl3945_set_rate(struct iwl3945_priv *priv)
+ priv->active_rate = 0;
+ priv->active_rate_basic = 0;
+
+- IWL_DEBUG_RATE("Setting rates for 802.11%c\n",
+- hw->mode == MODE_IEEE80211A ?
+- 'a' : ((hw->mode == MODE_IEEE80211B) ? 'b' : 'g'));
+-
+- for (i = 0; i < hw->num_rates; i++) {
+- rate = &(hw->rates[i]);
+- if ((rate->val < IWL_RATE_COUNT) &&
+- (rate->flags & IEEE80211_RATE_SUPPORTED)) {
+- IWL_DEBUG_RATE("Adding rate index %d (plcp %d)%s\n",
+- rate->val, iwl3945_rates[rate->val].plcp,
+- (rate->flags & IEEE80211_RATE_BASIC) ?
+- "*" : "");
+- priv->active_rate |= (1 << rate->val);
+- if (rate->flags & IEEE80211_RATE_BASIC)
+- priv->active_rate_basic |= (1 << rate->val);
+- } else
+- IWL_DEBUG_RATE("Not adding rate %d (plcp %d)\n",
+- rate->val, iwl3945_rates[rate->val].plcp);
++ IWL_DEBUG_RATE("Setting rates for %s GHz\n",
++ sband->band == IEEE80211_BAND_2GHZ ? "2.4" : "5");
++
++ for (i = 0; i < sband->n_bitrates; i++) {
++ rate = &sband->bitrates[i];
++ if ((rate->hw_value < IWL_RATE_COUNT) &&
++ !(rate->flags & IEEE80211_CHAN_DISABLED)) {
++ IWL_DEBUG_RATE("Adding rate index %d (plcp %d)\n",
++ rate->hw_value, iwl3945_rates[rate->hw_value].plcp);
++ priv->active_rate |= (1 << rate->hw_value);
++ }
+ }
+
+ IWL_DEBUG_RATE("Set active_rate = %0x, active_rate_basic = %0x\n",
+@@ -3330,127 +3119,6 @@ static int iwl3945_get_measurement(struct iwl3945_priv *priv,
+ }
+ #endif
+
+-static void iwl3945_txstatus_to_ieee(struct iwl3945_priv *priv,
+- struct iwl3945_tx_info *tx_sta)
+-{
+-
+- tx_sta->status.ack_signal = 0;
+- tx_sta->status.excessive_retries = 0;
+- tx_sta->status.queue_length = 0;
+- tx_sta->status.queue_number = 0;
+-
+- if (in_interrupt())
+- ieee80211_tx_status_irqsafe(priv->hw,
+- tx_sta->skb[0], &(tx_sta->status));
+- else
+- ieee80211_tx_status(priv->hw,
+- tx_sta->skb[0], &(tx_sta->status));
+-
+- tx_sta->skb[0] = NULL;
+-}
+-
+-/**
+- * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
+- *
+- * When FW advances 'R' index, all entries between old and new 'R' index
+- * need to be reclaimed. As result, some free space forms. If there is
+- * enough free space (> low mark), wake the stack that feeds us.
+- */
+-static int iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv, int txq_id, int index)
+-{
+- struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
+- struct iwl3945_queue *q = &txq->q;
+- int nfreed = 0;
+-
+- if ((index >= q->n_bd) || (x2_queue_used(q, index) == 0)) {
+- IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
+- "is out of range [0-%d] %d %d.\n", txq_id,
+- index, q->n_bd, q->write_ptr, q->read_ptr);
+- return 0;
+- }
+-
+- for (index = iwl3945_queue_inc_wrap(index, q->n_bd);
+- q->read_ptr != index;
+- q->read_ptr = iwl3945_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+- if (txq_id != IWL_CMD_QUEUE_NUM) {
+- iwl3945_txstatus_to_ieee(priv,
+- &(txq->txb[txq->q.read_ptr]));
+- iwl3945_hw_txq_free_tfd(priv, txq);
+- } else if (nfreed > 1) {
+- IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
+- q->write_ptr, q->read_ptr);
+- queue_work(priv->workqueue, &priv->restart);
+- }
+- nfreed++;
+- }
+-
+- if (iwl3945_queue_space(q) > q->low_mark && (txq_id >= 0) &&
+- (txq_id != IWL_CMD_QUEUE_NUM) &&
+- priv->mac80211_registered)
+- ieee80211_wake_queue(priv->hw, txq_id);
+-
+-
+- return nfreed;
+-}
+-
+-static int iwl3945_is_tx_success(u32 status)
+-{
+- return (status & 0xFF) == 0x1;
+-}
+-
+-/******************************************************************************
+- *
+- * Generic RX handler implementations
+- *
+- ******************************************************************************/
+-/**
+- * iwl3945_rx_reply_tx - Handle Tx response
+- */
+-static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv,
+- struct iwl3945_rx_mem_buffer *rxb)
+-{
+- struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
+- u16 sequence = le16_to_cpu(pkt->hdr.sequence);
+- int txq_id = SEQ_TO_QUEUE(sequence);
+- int index = SEQ_TO_INDEX(sequence);
+- struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
+- struct ieee80211_tx_status *tx_status;
+- struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
+- u32 status = le32_to_cpu(tx_resp->status);
+-
+- if ((index >= txq->q.n_bd) || (x2_queue_used(&txq->q, index) == 0)) {
+- IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
+- "is out of range [0-%d] %d %d\n", txq_id,
+- index, txq->q.n_bd, txq->q.write_ptr,
+- txq->q.read_ptr);
+- return;
+- }
+-
+- tx_status = &(txq->txb[txq->q.read_ptr].status);
+-
+- tx_status->retry_count = tx_resp->failure_frame;
+- tx_status->queue_number = status;
+- tx_status->queue_length = tx_resp->bt_kill_count;
+- tx_status->queue_length |= tx_resp->failure_rts;
+-
+- tx_status->flags =
+- iwl3945_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
+-
+- tx_status->control.tx_rate = iwl3945_rate_index_from_plcp(tx_resp->rate);
+-
+- IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n",
+- txq_id, iwl3945_get_tx_fail_reason(status), status,
+- tx_resp->rate, tx_resp->failure_frame);
+-
+- IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
+- if (index != -1)
+- iwl3945_tx_queue_reclaim(priv, txq_id, index);
+-
+- if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
+- IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n");
+-}
+-
+-
+ static void iwl3945_rx_reply_alive(struct iwl3945_priv *priv,
+ struct iwl3945_rx_mem_buffer *rxb)
+ {
+@@ -3797,13 +3465,44 @@ static void iwl3945_setup_rx_handlers(struct iwl3945_priv *priv)
+ priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] =
+ iwl3945_rx_scan_complete_notif;
+ priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif;
+- priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx;
+
+ /* Set up hardware specific Rx handlers */
+ iwl3945_hw_rx_handler_setup(priv);
+ }
+
+ /**
++ * iwl3945_cmd_queue_reclaim - Reclaim CMD queue entries
++ * When FW advances 'R' index, all entries between old and new 'R' index
++ * need to be reclaimed.
++ */
++static void iwl3945_cmd_queue_reclaim(struct iwl3945_priv *priv,
++ int txq_id, int index)
++{
++ struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
++ struct iwl3945_queue *q = &txq->q;
++ int nfreed = 0;
++
++ if ((index >= q->n_bd) || (iwl3945_x2_queue_used(q, index) == 0)) {
++ IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
++ "is out of range [0-%d] %d %d.\n", txq_id,
++ index, q->n_bd, q->write_ptr, q->read_ptr);
++ return;
++ }
++
++ for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index;
++ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
++ if (nfreed > 1) {
++ IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
++ q->write_ptr, q->read_ptr);
++ queue_work(priv->workqueue, &priv->restart);
++ break;
++ }
++ nfreed++;
++ }
++}
++
++
++/**
+ * iwl3945_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
+ * @rxb: Rx buffer to reclaim
+ *
+@@ -3822,12 +3521,6 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv,
+ int cmd_index;
+ struct iwl3945_cmd *cmd;
+
+- /* If a Tx command is being handled and it isn't in the actual
+- * command queue then there a command routing bug has been introduced
+- * in the queue management code. */
+- if (txq_id != IWL_CMD_QUEUE_NUM)
+- IWL_ERROR("Error wrong command queue %d command id 0x%X\n",
+- txq_id, pkt->hdr.cmd);
+ BUG_ON(txq_id != IWL_CMD_QUEUE_NUM);
+
+ cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge);
+@@ -3841,7 +3534,7 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv,
+ !cmd->meta.u.callback(priv, cmd, rxb->skb))
+ rxb->skb = NULL;
+
+- iwl3945_tx_queue_reclaim(priv, txq_id, index);
++ iwl3945_cmd_queue_reclaim(priv, txq_id, index);
+
+ if (!(cmd->meta.flags & CMD_ASYNC)) {
+ clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
+@@ -4460,6 +4153,16 @@ static void iwl3945_enable_interrupts(struct iwl3945_priv *priv)
+ iwl3945_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
+ }
+
++
++/* call this function to flush any scheduled tasklet */
++static inline void iwl_synchronize_irq(struct iwl3945_priv *priv)
++{
++ /* wait to make sure we flush pedding tasklet*/
++ synchronize_irq(priv->pci_dev->irq);
++ tasklet_kill(&priv->irq_tasklet);
++}
++
++
+ static inline void iwl3945_disable_interrupts(struct iwl3945_priv *priv)
+ {
+ clear_bit(STATUS_INT_ENABLED, &priv->status);
+@@ -4521,8 +4224,7 @@ static void iwl3945_dump_nic_error_log(struct iwl3945_priv *priv)
+
+ if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
+ IWL_ERROR("Start IWL Error Log Dump:\n");
+- IWL_ERROR("Status: 0x%08lX, Config: %08X count: %d\n",
+- priv->status, priv->config, count);
++ IWL_ERROR("Status: 0x%08lX, count: %d\n", priv->status, count);
+ }
+
+ IWL_ERROR("Desc Time asrtPC blink2 "
+@@ -4742,9 +4444,9 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv)
+ * atomic, make sure that inta covers all the interrupts that
+ * we've discovered, even if FH interrupt came in just after
+ * reading CSR_INT. */
+- if (inta_fh & CSR_FH_INT_RX_MASK)
++ if (inta_fh & CSR39_FH_INT_RX_MASK)
+ inta |= CSR_INT_BIT_FH_RX;
+- if (inta_fh & CSR_FH_INT_TX_MASK)
++ if (inta_fh & CSR39_FH_INT_TX_MASK)
+ inta |= CSR_INT_BIT_FH_TX;
+
+ /* Now service all interrupt bits discovered above. */
+@@ -4792,7 +4494,7 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv)
+ /* Queue restart only if RF_KILL switch was set to "kill"
+ * when we loaded driver, and is now set to "enable".
+ * After we're Alive, RF_KILL gets handled by
+- * iwl_rx_card_state_notif() */
++ * iwl3945_rx_card_state_notif() */
+ if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) {
+ clear_bit(STATUS_RF_KILL_HW, &priv->status);
+ queue_work(priv->workqueue, &priv->restart);
+@@ -4860,7 +4562,9 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv)
+ }
+
+ /* Re-enable all interrupts */
+- iwl3945_enable_interrupts(priv);
++ /* only Re-enable if disabled by irq */
++ if (test_bit(STATUS_INT_ENABLED, &priv->status))
++ iwl3945_enable_interrupts(priv);
+
+ #ifdef CONFIG_IWL3945_DEBUG
+ if (iwl3945_debug_level & (IWL_DL_ISR)) {
+@@ -4924,7 +4628,9 @@ unplugged:
+
+ none:
+ /* re-enable interrupts here since we don't have anything to service. */
+- iwl3945_enable_interrupts(priv);
++ /* only Re-enable if disabled by irq */
++ if (test_bit(STATUS_INT_ENABLED, &priv->status))
++ iwl3945_enable_interrupts(priv);
+ spin_unlock(&priv->lock);
+ return IRQ_NONE;
+ }
+@@ -5026,24 +4732,24 @@ static void iwl3945_init_band_reference(const struct iwl3945_priv *priv, int ban
+ * Based on band and channel number.
+ */
+ const struct iwl3945_channel_info *iwl3945_get_channel_info(const struct iwl3945_priv *priv,
+- int phymode, u16 channel)
++ enum ieee80211_band band, u16 channel)
+ {
+ int i;
+
+- switch (phymode) {
+- case MODE_IEEE80211A:
++ switch (band) {
++ case IEEE80211_BAND_5GHZ:
+ for (i = 14; i < priv->channel_count; i++) {
+ if (priv->channel_info[i].channel == channel)
+ return &priv->channel_info[i];
+ }
+ break;
+
+- case MODE_IEEE80211B:
+- case MODE_IEEE80211G:
++ case IEEE80211_BAND_2GHZ:
+ if (channel >= 1 && channel <= 14)
+ return &priv->channel_info[channel - 1];
+ break;
+-
++ case IEEE80211_NUM_BANDS:
++ WARN_ON(1);
+ }
+
+ return NULL;
+@@ -5106,8 +4812,8 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv)
+ /* Loop through each band adding each of the channels */
+ for (ch = 0; ch < eeprom_ch_count; ch++) {
+ ch_info->channel = eeprom_ch_index[ch];
+- ch_info->phymode = (band == 1) ? MODE_IEEE80211B :
+- MODE_IEEE80211A;
++ ch_info->band = (band == 1) ? IEEE80211_BAND_2GHZ :
++ IEEE80211_BAND_5GHZ;
+
+ /* permanently store EEPROM's channel regulatory flags
+ * and max power in channel info database. */
+@@ -5134,11 +4840,12 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv)
+ ch_info->scan_power = eeprom_ch_info[ch].max_power_avg;
+ ch_info->min_power = 0;
+
+- IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x"
++ IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s%s(0x%02x"
+ " %ddBm): Ad-Hoc %ssupported\n",
+ ch_info->channel,
+ is_channel_a_band(ch_info) ?
+ "5.2" : "2.4",
++ CHECK_AND_PRINT(VALID),
+ CHECK_AND_PRINT(IBSS),
+ CHECK_AND_PRINT(ACTIVE),
+ CHECK_AND_PRINT(RADAR),
+@@ -5203,18 +4910,20 @@ static void iwl3945_free_channel_map(struct iwl3945_priv *priv)
+ #define IWL_PASSIVE_DWELL_BASE (100)
+ #define IWL_CHANNEL_TUNE_TIME 5
+
+-static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv, int phymode)
++static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv,
++ enum ieee80211_band band)
+ {
+- if (phymode == MODE_IEEE80211A)
++ if (band == IEEE80211_BAND_5GHZ)
+ return IWL_ACTIVE_DWELL_TIME_52;
+ else
+ return IWL_ACTIVE_DWELL_TIME_24;
+ }
+
+-static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv, int phymode)
++static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv,
++ enum ieee80211_band band)
+ {
+- u16 active = iwl3945_get_active_dwell_time(priv, phymode);
+- u16 passive = (phymode != MODE_IEEE80211A) ?
++ u16 active = iwl3945_get_active_dwell_time(priv, band);
++ u16 passive = (band == IEEE80211_BAND_2GHZ) ?
+ IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
+ IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
+
+@@ -5234,28 +4943,32 @@ static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv, int phymode
+ return passive;
+ }
+
+-static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode,
++static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv,
++ enum ieee80211_band band,
+ u8 is_active, u8 direct_mask,
+ struct iwl3945_scan_channel *scan_ch)
+ {
+ const struct ieee80211_channel *channels = NULL;
+- const struct ieee80211_hw_mode *hw_mode;
++ const struct ieee80211_supported_band *sband;
+ const struct iwl3945_channel_info *ch_info;
+ u16 passive_dwell = 0;
+ u16 active_dwell = 0;
+ int added, i;
+
+- hw_mode = iwl3945_get_hw_mode(priv, phymode);
+- if (!hw_mode)
++ sband = iwl3945_get_band(priv, band);
++ if (!sband)
+ return 0;
+
+- channels = hw_mode->channels;
++ channels = sband->channels;
+
+- active_dwell = iwl3945_get_active_dwell_time(priv, phymode);
+- passive_dwell = iwl3945_get_passive_dwell_time(priv, phymode);
++ active_dwell = iwl3945_get_active_dwell_time(priv, band);
++ passive_dwell = iwl3945_get_passive_dwell_time(priv, band);
+
+- for (i = 0, added = 0; i < hw_mode->num_channels; i++) {
+- if (channels[i].chan ==
++ for (i = 0, added = 0; i < sband->n_channels; i++) {
++ if (channels[i].flags & IEEE80211_CHAN_DISABLED)
++ continue;
++
++ if (channels[i].hw_value ==
+ le16_to_cpu(priv->active_rxon.channel)) {
+ if (iwl3945_is_associated(priv)) {
+ IWL_DEBUG_SCAN
+@@ -5266,9 +4979,9 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode,
+ } else if (priv->only_active_channel)
+ continue;
+
+- scan_ch->channel = channels[i].chan;
++ scan_ch->channel = channels[i].hw_value;
+
+- ch_info = iwl3945_get_channel_info(priv, phymode, scan_ch->channel);
++ ch_info = iwl3945_get_channel_info(priv, band, scan_ch->channel);
+ if (!is_channel_valid(ch_info)) {
+ IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n",
+ scan_ch->channel);
+@@ -5276,7 +4989,7 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode,
+ }
+
+ if (!is_active || is_channel_passive(ch_info) ||
+- !(channels[i].flag & IEEE80211_CHAN_W_ACTIVE_SCAN))
++ (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN))
+ scan_ch->type = 0; /* passive */
+ else
+ scan_ch->type = 1; /* active */
+@@ -5295,7 +5008,7 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode,
+ /* scan_pwr_info->tpc.dsp_atten; */
+
+ /*scan_pwr_info->tpc.tx_gain; */
+- if (phymode == MODE_IEEE80211A)
++ if (band == IEEE80211_BAND_5GHZ)
+ scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
+ else {
+ scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
+@@ -5319,41 +5032,23 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode,
+ return added;
+ }
+
+-static void iwl3945_reset_channel_flag(struct iwl3945_priv *priv)
+-{
+- int i, j;
+- for (i = 0; i < 3; i++) {
+- struct ieee80211_hw_mode *hw_mode = (void *)&priv->modes[i];
+- for (j = 0; j < hw_mode->num_channels; j++)
+- hw_mode->channels[j].flag = hw_mode->channels[j].val;
+- }
+-}
+-
+ static void iwl3945_init_hw_rates(struct iwl3945_priv *priv,
+ struct ieee80211_rate *rates)
+ {
+ int i;
+
+ for (i = 0; i < IWL_RATE_COUNT; i++) {
+- rates[i].rate = iwl3945_rates[i].ieee * 5;
+- rates[i].val = i; /* Rate scaling will work on indexes */
+- rates[i].val2 = i;
+- rates[i].flags = IEEE80211_RATE_SUPPORTED;
+- /* Only OFDM have the bits-per-symbol set */
+- if ((i <= IWL_LAST_OFDM_RATE) && (i >= IWL_FIRST_OFDM_RATE))
+- rates[i].flags |= IEEE80211_RATE_OFDM;
+- else {
++ rates[i].bitrate = iwl3945_rates[i].ieee * 5;
++ rates[i].hw_value = i; /* Rate scaling will work on indexes */
++ rates[i].hw_value_short = i;
++ rates[i].flags = 0;
++ if ((i > IWL_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) {
+ /*
+- * If CCK 1M then set rate flag to CCK else CCK_2
+- * which is CCK | PREAMBLE2
++ * If CCK != 1M then set short preamble rate flag.
+ */
+ rates[i].flags |= (iwl3945_rates[i].plcp == 10) ?
+- IEEE80211_RATE_CCK : IEEE80211_RATE_CCK_2;
++ 0 : IEEE80211_RATE_SHORT_PREAMBLE;
+ }
+-
+- /* Set up which ones are basic rates... */
+- if (IWL_BASIC_RATES_MASK & (1 << i))
+- rates[i].flags |= IEEE80211_RATE_BASIC;
+ }
+ }
+
+@@ -5363,143 +5058,117 @@ static void iwl3945_init_hw_rates(struct iwl3945_priv *priv,
+ static int iwl3945_init_geos(struct iwl3945_priv *priv)
+ {
+ struct iwl3945_channel_info *ch;
+- struct ieee80211_hw_mode *modes;
++ struct ieee80211_supported_band *sband;
+ struct ieee80211_channel *channels;
+ struct ieee80211_channel *geo_ch;
+ struct ieee80211_rate *rates;
+ int i = 0;
+- enum {
+- A = 0,
+- B = 1,
+- G = 2,
+- };
+- int mode_count = 3;
+
+- if (priv->modes) {
++ if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
++ priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
+ IWL_DEBUG_INFO("Geography modes already initialized.\n");
+ set_bit(STATUS_GEO_CONFIGURED, &priv->status);
+ return 0;
+ }
+
+- modes = kzalloc(sizeof(struct ieee80211_hw_mode) * mode_count,
+- GFP_KERNEL);
+- if (!modes)
+- return -ENOMEM;
+-
+ channels = kzalloc(sizeof(struct ieee80211_channel) *
+ priv->channel_count, GFP_KERNEL);
+- if (!channels) {
+- kfree(modes);
++ if (!channels)
+ return -ENOMEM;
+- }
+
+- rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_MAX_RATES + 1)),
++ rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_RATE_COUNT + 1)),
+ GFP_KERNEL);
+ if (!rates) {
+- kfree(modes);
+ kfree(channels);
+ return -ENOMEM;
+ }
+
+- /* 0 = 802.11a
+- * 1 = 802.11b
+- * 2 = 802.11g
+- */
+-
+ /* 5.2GHz channels start after the 2.4GHz channels */
+- modes[A].mode = MODE_IEEE80211A;
+- modes[A].channels = &channels[ARRAY_SIZE(iwl3945_eeprom_band_1)];
+- modes[A].rates = &rates[4];
+- modes[A].num_rates = 8; /* just OFDM */
+- modes[A].num_channels = 0;
+-
+- modes[B].mode = MODE_IEEE80211B;
+- modes[B].channels = channels;
+- modes[B].rates = rates;
+- modes[B].num_rates = 4; /* just CCK */
+- modes[B].num_channels = 0;
+-
+- modes[G].mode = MODE_IEEE80211G;
+- modes[G].channels = channels;
+- modes[G].rates = rates;
+- modes[G].num_rates = 12; /* OFDM & CCK */
+- modes[G].num_channels = 0;
++ sband = &priv->bands[IEEE80211_BAND_5GHZ];
++ sband->channels = &channels[ARRAY_SIZE(iwl3945_eeprom_band_1)];
++ /* just OFDM */
++ sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
++ sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE;
++
++ sband = &priv->bands[IEEE80211_BAND_2GHZ];
++ sband->channels = channels;
++ /* OFDM & CCK */
++ sband->bitrates = rates;
++ sband->n_bitrates = IWL_RATE_COUNT;
+
+ priv->ieee_channels = channels;
+ priv->ieee_rates = rates;
+
+ iwl3945_init_hw_rates(priv, rates);
+
+- for (i = 0, geo_ch = channels; i < priv->channel_count; i++) {
++ for (i = 0; i < priv->channel_count; i++) {
+ ch = &priv->channel_info[i];
+
+- if (!is_channel_valid(ch)) {
+- IWL_DEBUG_INFO("Channel %d [%sGHz] is restricted -- "
+- "skipping.\n",
+- ch->channel, is_channel_a_band(ch) ?
+- "5.2" : "2.4");
++ /* FIXME: might be removed if scan is OK*/
++ if (!is_channel_valid(ch))
+ continue;
+- }
+
+ if (is_channel_a_band(ch))
+- geo_ch = &modes[A].channels[modes[A].num_channels++];
+- else {
+- geo_ch = &modes[B].channels[modes[B].num_channels++];
+- modes[G].num_channels++;
+- }
++ sband = &priv->bands[IEEE80211_BAND_5GHZ];
++ else
++ sband = &priv->bands[IEEE80211_BAND_2GHZ];
+
+- geo_ch->freq = ieee80211chan2mhz(ch->channel);
+- geo_ch->chan = ch->channel;
+- geo_ch->power_level = ch->max_power_avg;
+- geo_ch->antenna_max = 0xff;
++ geo_ch = &sband->channels[sband->n_channels++];
++
++ geo_ch->center_freq = ieee80211_channel_to_frequency(ch->channel);
++ geo_ch->max_power = ch->max_power_avg;
++ geo_ch->max_antenna_gain = 0xff;
++ geo_ch->hw_value = ch->channel;
+
+ if (is_channel_valid(ch)) {
+- geo_ch->flag = IEEE80211_CHAN_W_SCAN;
+- if (ch->flags & EEPROM_CHANNEL_IBSS)
+- geo_ch->flag |= IEEE80211_CHAN_W_IBSS;
++ if (!(ch->flags & EEPROM_CHANNEL_IBSS))
++ geo_ch->flags |= IEEE80211_CHAN_NO_IBSS;
+
+- if (ch->flags & EEPROM_CHANNEL_ACTIVE)
+- geo_ch->flag |= IEEE80211_CHAN_W_ACTIVE_SCAN;
++ if (!(ch->flags & EEPROM_CHANNEL_ACTIVE))
++ geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
+
+ if (ch->flags & EEPROM_CHANNEL_RADAR)
+- geo_ch->flag |= IEEE80211_CHAN_W_RADAR_DETECT;
++ geo_ch->flags |= IEEE80211_CHAN_RADAR;
+
+ if (ch->max_power_avg > priv->max_channel_txpower_limit)
+ priv->max_channel_txpower_limit =
+ ch->max_power_avg;
++ } else {
++ geo_ch->flags |= IEEE80211_CHAN_DISABLED;
+ }
+
+- geo_ch->val = geo_ch->flag;
++ /* Save flags for reg domain usage */
++ geo_ch->orig_flags = geo_ch->flags;
++
++ IWL_DEBUG_INFO("Channel %d Freq=%d[%sGHz] %s flag=0%X\n",
++ ch->channel, geo_ch->center_freq,
++ is_channel_a_band(ch) ? "5.2" : "2.4",
++ geo_ch->flags & IEEE80211_CHAN_DISABLED ?
++ "restricted" : "valid",
++ geo_ch->flags);
+ }
+
+- if ((modes[A].num_channels == 0) && priv->is_abg) {
++ if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
++ priv->cfg->sku & IWL_SKU_A) {
+ printk(KERN_INFO DRV_NAME
+ ": Incorrectly detected BG card as ABG. Please send "
+ "your PCI ID 0x%04X:0x%04X to maintainer.\n",
+ priv->pci_dev->device, priv->pci_dev->subsystem_device);
+- priv->is_abg = 0;
++ priv->cfg->sku &= ~IWL_SKU_A;
+ }
+
+ printk(KERN_INFO DRV_NAME
+ ": Tunable channels: %d 802.11bg, %d 802.11a channels\n",
+- modes[G].num_channels, modes[A].num_channels);
++ priv->bands[IEEE80211_BAND_2GHZ].n_channels,
++ priv->bands[IEEE80211_BAND_5GHZ].n_channels);
+
+- /*
+- * NOTE: We register these in preference of order -- the
+- * stack doesn't currently (as of 7.0.6 / Apr 24 '07) pick
+- * a phymode based on rates or AP capabilities but seems to
+- * configure it purely on if the channel being configured
+- * is supported by a mode -- and the first match is taken
+- */
++ if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
++ priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
++ &priv->bands[IEEE80211_BAND_2GHZ];
++ if (priv->bands[IEEE80211_BAND_5GHZ].n_channels)
++ priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
++ &priv->bands[IEEE80211_BAND_5GHZ];
+
+- if (modes[G].num_channels)
+- ieee80211_register_hwmode(priv->hw, &modes[G]);
+- if (modes[B].num_channels)
+- ieee80211_register_hwmode(priv->hw, &modes[B]);
+- if (modes[A].num_channels)
+- ieee80211_register_hwmode(priv->hw, &modes[A]);
+-
+- priv->modes = modes;
+ set_bit(STATUS_GEO_CONFIGURED, &priv->status);
+
+ return 0;
+@@ -5510,7 +5179,6 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv)
+ */
+ static void iwl3945_free_geos(struct iwl3945_priv *priv)
+ {
+- kfree(priv->modes);
+ kfree(priv->ieee_channels);
+ kfree(priv->ieee_rates);
+ clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
+@@ -5837,7 +5505,7 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv)
+ int ret = 0;
+ const struct firmware *ucode_raw;
+ /* firmware file name contains uCode/driver compatibility version */
+- const char *name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode";
++ const char *name = priv->cfg->fw_name;
+ u8 *src;
+ size_t len;
+ u32 ver, inst_size, data_size, init_size, init_data_size, boot_size;
+@@ -6209,6 +5877,8 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
+
+ iwl3945_reg_txpower_periodic(priv);
+
++ iwl3945_led_register(priv);
++
+ IWL_DEBUG_INFO("ALIVE processing complete.\n");
+ set_bit(STATUS_READY, &priv->status);
+ wake_up_interruptible(&priv->wait_command_queue);
+@@ -6216,6 +5886,7 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
+ if (priv->error_recovering)
+ iwl3945_error_recovery(priv);
+
++ ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC);
+ return;
+
+ restart:
+@@ -6237,6 +5908,7 @@ static void __iwl3945_down(struct iwl3945_priv *priv)
+ if (!exit_pending)
+ set_bit(STATUS_EXIT_PENDING, &priv->status);
+
++ iwl3945_led_unregister(priv);
+ iwl3945_clear_stations_table(priv);
+
+ /* Unblock any waiting calls */
+@@ -6251,7 +5923,10 @@ static void __iwl3945_down(struct iwl3945_priv *priv)
+ iwl3945_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+
+ /* tell the device to stop sending interrupts */
++ spin_lock_irqsave(&priv->lock, flags);
+ iwl3945_disable_interrupts(priv);
++ spin_unlock_irqrestore(&priv->lock, flags);
++ iwl_synchronize_irq(priv);
+
+ if (priv->mac80211_registered)
+ ieee80211_stop_queues(priv->hw);
+@@ -6519,7 +6194,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
+ struct iwl3945_scan_cmd *scan;
+ struct ieee80211_conf *conf = NULL;
+ u8 direct_mask;
+- int phymode;
++ enum ieee80211_band band;
+
+ conf = ieee80211_get_hw_conf(priv->hw);
+
+@@ -6651,13 +6326,13 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
+ scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
+ scan->tx_cmd.rate = IWL_RATE_1M_PLCP;
+ scan->good_CRC_th = 0;
+- phymode = MODE_IEEE80211G;
++ band = IEEE80211_BAND_2GHZ;
+ break;
+
+ case 1:
+ scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
+ scan->good_CRC_th = IWL_GOOD_CRC_TH;
+- phymode = MODE_IEEE80211A;
++ band = IEEE80211_BAND_5GHZ;
+ break;
+
+ default:
+@@ -6671,18 +6346,23 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
+ if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR)
+ scan->filter_flags = RXON_FILTER_PROMISC_MSK;
+
+- if (direct_mask)
++ if (direct_mask) {
+ IWL_DEBUG_SCAN
+ ("Initiating direct scan for %s.\n",
+ iwl3945_escape_essid(priv->essid, priv->essid_len));
+- else
++ scan->channel_count =
++ iwl3945_get_channels_for_scan(
++ priv, band, 1, /* active */
++ direct_mask,
++ (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
++ } else {
+ IWL_DEBUG_SCAN("Initiating indirect scan.\n");
+-
+- scan->channel_count =
+- iwl3945_get_channels_for_scan(
+- priv, phymode, 1, /* active */
+- direct_mask,
+- (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
++ scan->channel_count =
++ iwl3945_get_channels_for_scan(
++ priv, band, 0, /* passive */
++ direct_mask,
++ (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
++ }
+
+ cmd.len += le16_to_cpu(scan->tx_cmd.len) +
+ scan->channel_count * sizeof(struct iwl3945_scan_channel);
+@@ -6825,7 +6505,7 @@ static void iwl3945_bg_post_associate(struct work_struct *data)
+ iwl3945_add_station(priv, iwl3945_broadcast_addr, 0, 0);
+ iwl3945_add_station(priv, priv->bssid, 0, 0);
+ iwl3945_sync_sta(priv, IWL_STA_ID,
+- (priv->phymode == MODE_IEEE80211A)?
++ (priv->band == IEEE80211_BAND_5GHZ) ?
+ IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP,
+ CMD_ASYNC);
+ iwl3945_rate_scale_init(priv->hw, IWL_STA_ID);
+@@ -6841,9 +6521,8 @@ static void iwl3945_bg_post_associate(struct work_struct *data)
+
+ iwl3945_sequence_reset(priv);
+
+-#ifdef CONFIG_IWL3945_QOS
+ iwl3945_activate_qos(priv, 0);
+-#endif /* CONFIG_IWL3945_QOS */
++
+ /* we have just associated, don't start scan too early */
+ priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
+ mutex_unlock(&priv->mutex);
+@@ -7020,7 +6699,7 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ }
+
+ IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
+- ctl->tx_rate);
++ ctl->tx_rate->bitrate);
+
+ if (iwl3945_tx_skb(priv, skb, ctl))
+ dev_kfree_skb_any(skb);
+@@ -7079,7 +6758,7 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
+ int ret = 0;
+
+ mutex_lock(&priv->mutex);
+- IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel);
++ IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value);
+
+ priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
+
+@@ -7099,19 +6778,20 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+- ch_info = iwl3945_get_channel_info(priv, conf->phymode, conf->channel);
++ ch_info = iwl3945_get_channel_info(priv, conf->channel->band,
++ conf->channel->hw_value);
+ if (!is_channel_valid(ch_info)) {
+ IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this SKU.\n",
+- conf->channel, conf->phymode);
++ conf->channel->hw_value, conf->channel->band);
+ IWL_DEBUG_MAC80211("leave - invalid channel\n");
+ spin_unlock_irqrestore(&priv->lock, flags);
+ ret = -EINVAL;
+ goto out;
+ }
+
+- iwl3945_set_rxon_channel(priv, conf->phymode, conf->channel);
++ iwl3945_set_rxon_channel(priv, conf->channel->band, conf->channel->hw_value);
+
+- iwl3945_set_flags_for_phymode(priv, conf->phymode);
++ iwl3945_set_flags_for_phymode(priv, conf->channel->band);
+
+ /* The list of supported rates and rate mask can be different
+ * for each phymode; since the phymode may have changed, reset
+@@ -7225,6 +6905,11 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
+ if (conf == NULL)
+ return -EIO;
+
++ if (priv->vif != vif) {
++ IWL_DEBUG_MAC80211("leave - priv->vif != vif\n");
++ return 0;
++ }
++
+ /* XXX: this MUST use conf->mac_addr */
+
+ if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
+@@ -7249,17 +6934,6 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
+ if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) &&
+ !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) {
+ */
+- if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
+- IWL_DEBUG_MAC80211("leave - scanning\n");
+- mutex_unlock(&priv->mutex);
+- return 0;
+- }
+-
+- if (priv->vif != vif) {
+- IWL_DEBUG_MAC80211("leave - priv->vif != vif\n");
+- mutex_unlock(&priv->mutex);
+- return 0;
+- }
+
+ if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
+ if (!conf->bssid) {
+@@ -7487,10 +7161,8 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue,
+ const struct ieee80211_tx_queue_params *params)
+ {
+ struct iwl3945_priv *priv = hw->priv;
+-#ifdef CONFIG_IWL3945_QOS
+ unsigned long flags;
+ int q;
+-#endif /* CONFIG_IWL3945_QOS */
+
+ IWL_DEBUG_MAC80211("enter\n");
+
+@@ -7504,7 +7176,6 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue,
+ return 0;
+ }
+
+-#ifdef CONFIG_IWL3945_QOS
+ if (!priv->qos_data.qos_enable) {
+ priv->qos_data.qos_active = 0;
+ IWL_DEBUG_MAC80211("leave - qos not enabled\n");
+@@ -7518,7 +7189,7 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue,
+ priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max);
+ priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
+ priv->qos_data.def_qos_parm.ac[q].edca_txop =
+- cpu_to_le16((params->burst_time * 100));
++ cpu_to_le16((params->txop * 32));
+
+ priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
+ priv->qos_data.qos_active = 1;
+@@ -7533,8 +7204,6 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue,
+
+ mutex_unlock(&priv->mutex);
+
+-#endif /*CONFIG_IWL3945_QOS */
+-
+ IWL_DEBUG_MAC80211("leave\n");
+ return 0;
+ }
+@@ -7599,9 +7268,8 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
+ mutex_lock(&priv->mutex);
+ IWL_DEBUG_MAC80211("enter\n");
+
+-#ifdef CONFIG_IWL3945_QOS
+ iwl3945_reset_qos(priv);
+-#endif
++
+ cancel_delayed_work(&priv->post_associate);
+
+ spin_lock_irqsave(&priv->lock, flags);
+@@ -7689,9 +7357,7 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
+ IWL_DEBUG_MAC80211("leave\n");
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+-#ifdef CONFIG_IWL3945_QOS
+ iwl3945_reset_qos(priv);
+-#endif
+
+ queue_work(priv->workqueue, &priv->post_associate.work);
+
+@@ -7892,65 +7558,6 @@ static ssize_t store_filter_flags(struct device *d,
+ static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
+ store_filter_flags);
+
+-static ssize_t show_tune(struct device *d,
+- struct device_attribute *attr, char *buf)
+-{
+- struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
+-
+- return sprintf(buf, "0x%04X\n",
+- (priv->phymode << 8) |
+- le16_to_cpu(priv->active_rxon.channel));
+-}
+-
+-static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, u8 phymode);
+-
+-static ssize_t store_tune(struct device *d,
+- struct device_attribute *attr,
+- const char *buf, size_t count)
+-{
+- struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
+- char *p = (char *)buf;
+- u16 tune = simple_strtoul(p, &p, 0);
+- u8 phymode = (tune >> 8) & 0xff;
+- u16 channel = tune & 0xff;
+-
+- IWL_DEBUG_INFO("Tune request to:%d channel:%d\n", phymode, channel);
+-
+- mutex_lock(&priv->mutex);
+- if ((le16_to_cpu(priv->staging_rxon.channel) != channel) ||
+- (priv->phymode != phymode)) {
+- const struct iwl3945_channel_info *ch_info;
+-
+- ch_info = iwl3945_get_channel_info(priv, phymode, channel);
+- if (!ch_info) {
+- IWL_WARNING("Requested invalid phymode/channel "
+- "combination: %d %d\n", phymode, channel);
+- mutex_unlock(&priv->mutex);
+- return -EINVAL;
+- }
+-
+- /* Cancel any currently running scans... */
+- if (iwl3945_scan_cancel_timeout(priv, 100))
+- IWL_WARNING("Could not cancel scan.\n");
+- else {
+- IWL_DEBUG_INFO("Committing phymode and "
+- "rxon.channel = %d %d\n",
+- phymode, channel);
+-
+- iwl3945_set_rxon_channel(priv, phymode, channel);
+- iwl3945_set_flags_for_phymode(priv, phymode);
+-
+- iwl3945_set_rate(priv);
+- iwl3945_commit_rxon(priv);
+- }
+- }
+- mutex_unlock(&priv->mutex);
+-
+- return count;
+-}
+-
+-static DEVICE_ATTR(tune, S_IWUSR | S_IRUGO, show_tune, store_tune);
+-
+ #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
+
+ static ssize_t show_measurement(struct device *d,
+@@ -8024,31 +7631,6 @@ static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR,
+ show_measurement, store_measurement);
+ #endif /* CONFIG_IWL3945_SPECTRUM_MEASUREMENT */
+
+-static ssize_t show_rate(struct device *d,
+- struct device_attribute *attr, char *buf)
+-{
+- struct iwl3945_priv *priv = dev_get_drvdata(d);
+- unsigned long flags;
+- int i;
+-
+- spin_lock_irqsave(&priv->sta_lock, flags);
+- if (priv->iw_mode == IEEE80211_IF_TYPE_STA)
+- i = priv->stations[IWL_AP_ID].current_rate.s.rate;
+- else
+- i = priv->stations[IWL_STA_ID].current_rate.s.rate;
+- spin_unlock_irqrestore(&priv->sta_lock, flags);
+-
+- i = iwl3945_rate_index_from_plcp(i);
+- if (i == -1)
+- return sprintf(buf, "0\n");
+-
+- return sprintf(buf, "%d%s\n",
+- (iwl3945_rates[i].ieee >> 1),
+- (iwl3945_rates[i].ieee & 0x1) ? ".5" : "");
+-}
+-
+-static DEVICE_ATTR(rate, S_IRUSR, show_rate, NULL);
+-
+ static ssize_t store_retry_rate(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+@@ -8165,73 +7747,8 @@ static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level,
+ static ssize_t show_channels(struct device *d,
+ struct device_attribute *attr, char *buf)
+ {
+- struct iwl3945_priv *priv = dev_get_drvdata(d);
+- int len = 0, i;
+- struct ieee80211_channel *channels = NULL;
+- const struct ieee80211_hw_mode *hw_mode = NULL;
+- int count = 0;
+-
+- if (!iwl3945_is_ready(priv))
+- return -EAGAIN;
+-
+- hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211G);
+- if (!hw_mode)
+- hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211B);
+- if (hw_mode) {
+- channels = hw_mode->channels;
+- count = hw_mode->num_channels;
+- }
+-
+- len +=
+- sprintf(&buf[len],
+- "Displaying %d channels in 2.4GHz band "
+- "(802.11bg):\n", count);
+-
+- for (i = 0; i < count; i++)
+- len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
+- channels[i].chan,
+- channels[i].power_level,
+- channels[i].
+- flag & IEEE80211_CHAN_W_RADAR_DETECT ?
+- " (IEEE 802.11h required)" : "",
+- (!(channels[i].flag & IEEE80211_CHAN_W_IBSS)
+- || (channels[i].
+- flag &
+- IEEE80211_CHAN_W_RADAR_DETECT)) ? "" :
+- ", IBSS",
+- channels[i].
+- flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
+- "active/passive" : "passive only");
+-
+- hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211A);
+- if (hw_mode) {
+- channels = hw_mode->channels;
+- count = hw_mode->num_channels;
+- } else {
+- channels = NULL;
+- count = 0;
+- }
+-
+- len += sprintf(&buf[len], "Displaying %d channels in 5.2GHz band "
+- "(802.11a):\n", count);
+-
+- for (i = 0; i < count; i++)
+- len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
+- channels[i].chan,
+- channels[i].power_level,
+- channels[i].
+- flag & IEEE80211_CHAN_W_RADAR_DETECT ?
+- " (IEEE 802.11h required)" : "",
+- (!(channels[i].flag & IEEE80211_CHAN_W_IBSS)
+- || (channels[i].
+- flag &
+- IEEE80211_CHAN_W_RADAR_DETECT)) ? "" :
+- ", IBSS",
+- channels[i].
+- flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
+- "active/passive" : "passive only");
+-
+- return len;
++ /* all this shit doesn't belong into sysfs anyway */
++ return 0;
+ }
+
+ static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
+@@ -8404,14 +7921,12 @@ static struct attribute *iwl3945_sysfs_entries[] = {
+ &dev_attr_measurement.attr,
+ #endif
+ &dev_attr_power_level.attr,
+- &dev_attr_rate.attr,
+ &dev_attr_retry_rate.attr,
+ &dev_attr_rf_kill.attr,
+ &dev_attr_rs_window.attr,
+ &dev_attr_statistics.attr,
+ &dev_attr_status.attr,
+ &dev_attr_temperature.attr,
+- &dev_attr_tune.attr,
+ &dev_attr_tx_power.attr,
+
+ NULL
+@@ -8444,10 +7959,11 @@ static struct ieee80211_ops iwl3945_hw_ops = {
+ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ int err = 0;
+- u32 pci_id;
+ struct iwl3945_priv *priv;
+ struct ieee80211_hw *hw;
++ struct iwl_3945_cfg *cfg = (struct iwl_3945_cfg *)(ent->driver_data);
+ int i;
++ unsigned long flags;
+ DECLARE_MAC_BUF(mac);
+
+ /* Disabling hardware scan means that mac80211 will perform scans
+@@ -8457,10 +7973,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+ iwl3945_hw_ops.hw_scan = NULL;
+ }
+
+- if ((iwl3945_param_queues_num > IWL_MAX_NUM_QUEUES) ||
++ if ((iwl3945_param_queues_num > IWL39_MAX_NUM_QUEUES) ||
+ (iwl3945_param_queues_num < IWL_MIN_NUM_QUEUES)) {
+ IWL_ERROR("invalid queues_num, should be between %d and %d\n",
+- IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES);
++ IWL_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES);
+ err = -EINVAL;
+ goto out;
+ }
+@@ -8482,6 +7998,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+ priv->hw = hw;
+
+ priv->pci_dev = pdev;
++ priv->cfg = cfg;
+
+ /* Select antenna (may be helpful if only one antenna is connected) */
+ priv->antenna = (enum iwl3945_antenna)iwl3945_param_antenna;
+@@ -8532,7 +8049,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+ priv->data_retry_limit = -1;
+ priv->ieee_channels = NULL;
+ priv->ieee_rates = NULL;
+- priv->phymode = -1;
++ priv->band = IEEE80211_BAND_2GHZ;
+
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (!err)
+@@ -8571,32 +8088,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+
+ priv->iw_mode = IEEE80211_IF_TYPE_STA;
+
+- pci_id =
+- (priv->pci_dev->device << 16) | priv->pci_dev->subsystem_device;
+-
+- switch (pci_id) {
+- case 0x42221005: /* 0x4222 0x8086 0x1005 is BG SKU */
+- case 0x42221034: /* 0x4222 0x8086 0x1034 is BG SKU */
+- case 0x42271014: /* 0x4227 0x8086 0x1014 is BG SKU */
+- case 0x42221044: /* 0x4222 0x8086 0x1044 is BG SKU */
+- priv->is_abg = 0;
+- break;
+-
+- /*
+- * Rest are assumed ABG SKU -- if this is not the
+- * case then the card will get the wrong 'Detected'
+- * line in the kernel log however the code that
+- * initializes the GEO table will detect no A-band
+- * channels and remove the is_abg mask.
+- */
+- default:
+- priv->is_abg = 1;
+- break;
+- }
+-
+ printk(KERN_INFO DRV_NAME
+- ": Detected Intel PRO/Wireless 3945%sBG Network Connection\n",
+- priv->is_abg ? "A" : "");
++ ": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name);
+
+ /* Device-specific setup */
+ if (iwl3945_hw_set_hw_setting(priv)) {
+@@ -8604,7 +8097,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+ goto out_iounmap;
+ }
+
+-#ifdef CONFIG_IWL3945_QOS
+ if (iwl3945_param_qos_enable)
+ priv->qos_data.qos_enable = 1;
+
+@@ -8612,9 +8104,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+
+ priv->qos_data.qos_active = 0;
+ priv->qos_data.qos_cap.val = 0;
+-#endif /* CONFIG_IWL3945_QOS */
+
+- iwl3945_set_rxon_channel(priv, MODE_IEEE80211G, 6);
++ iwl3945_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6);
+ iwl3945_setup_deferred_work(priv);
+ iwl3945_setup_rx_handlers(priv);
+
+@@ -8623,7 +8114,9 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+ priv->power_mode = IWL_POWER_AC;
+ priv->user_txpower_limit = IWL_DEFAULT_TX_POWER;
+
++ spin_lock_irqsave(&priv->lock, flags);
+ iwl3945_disable_interrupts(priv);
++ spin_unlock_irqrestore(&priv->lock, flags);
+
+ err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group);
+ if (err) {
+@@ -8665,9 +8158,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+ IWL_ERROR("initializing geos failed: %d\n", err);
+ goto out_free_channel_map;
+ }
+- iwl3945_reset_channel_flag(priv);
+
+- iwl3945_rate_control_register(priv->hw);
+ err = ieee80211_register_hw(priv->hw);
+ if (err) {
+ IWL_ERROR("Failed to register network device (error %d)\n", err);
+@@ -8711,6 +8202,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
+ struct iwl3945_priv *priv = pci_get_drvdata(pdev);
+ struct list_head *p, *q;
+ int i;
++ unsigned long flags;
+
+ if (!priv)
+ return;
+@@ -8721,6 +8213,15 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
+
+ iwl3945_down(priv);
+
++ /* make sure we flush any pending irq or
++ * tasklet for the driver
++ */
++ spin_lock_irqsave(&priv->lock, flags);
++ iwl3945_disable_interrupts(priv);
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ iwl_synchronize_irq(priv);
++
+ /* Free MAC hash list for ADHOC */
+ for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) {
+ list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) {
+@@ -8742,7 +8243,6 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
+
+ if (priv->mac80211_registered) {
+ ieee80211_unregister_hw(priv->hw);
+- iwl3945_rate_control_unregister(priv->hw);
+ }
+
+ /*netif_stop_queue(dev); */
+@@ -8823,21 +8323,35 @@ static int __init iwl3945_init(void)
+ int ret;
+ printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
+ printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
++
++ ret = iwl3945_rate_control_register();
++ if (ret) {
++ IWL_ERROR("Unable to register rate control algorithm: %d\n", ret);
++ return ret;
++ }
++
+ ret = pci_register_driver(&iwl3945_driver);
+ if (ret) {
+ IWL_ERROR("Unable to initialize PCI module\n");
+- return ret;
++ goto error_register;
+ }
+ #ifdef CONFIG_IWL3945_DEBUG
+ ret = driver_create_file(&iwl3945_driver.driver, &driver_attr_debug_level);
+ if (ret) {
+ IWL_ERROR("Unable to create driver sysfs file\n");
+- pci_unregister_driver(&iwl3945_driver);
+- return ret;
++ goto error_debug;
+ }
+ #endif
+
+ return ret;
++
++#ifdef CONFIG_IWL3945_DEBUG
++error_debug:
++ pci_unregister_driver(&iwl3945_driver);
++#endif
++error_register:
++ iwl3945_rate_control_unregister();
++ return ret;
+ }
+
+ static void __exit iwl3945_exit(void)
+@@ -8846,6 +8360,7 @@ static void __exit iwl3945_exit(void)
+ driver_remove_file(&iwl3945_driver.driver, &driver_attr_debug_level);
+ #endif
+ pci_unregister_driver(&iwl3945_driver);
++ iwl3945_rate_control_unregister();
+ }
+
+ module_param_named(antenna, iwl3945_param_antenna, int, 0444);
+diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
+index 60ec29e..d0bbcaa 100644
+--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
++++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
+@@ -1,6 +1,6 @@
+ /******************************************************************************
+ *
+- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
++ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+@@ -45,14 +45,14 @@
+
+ #include <asm/div64.h>
+
++#include "iwl-eeprom.h"
+ #include "iwl-4965.h"
++#include "iwl-core.h"
++#include "iwl-io.h"
+ #include "iwl-helpers.h"
++#include "iwl-sta.h"
+
+-#ifdef CONFIG_IWL4965_DEBUG
+-u32 iwl4965_debug_level;
+-#endif
+-
+-static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv,
++static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv,
+ struct iwl4965_tx_queue *txq);
+
+ /******************************************************************************
+@@ -61,16 +61,6 @@ static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv,
+ *
+ ******************************************************************************/
+
+-/* module parameters */
+-static int iwl4965_param_disable_hw_scan; /* def: 0 = use 4965's h/w scan */
+-static int iwl4965_param_debug; /* def: 0 = minimal debug log messages */
+-static int iwl4965_param_disable; /* def: enable radio */
+-static int iwl4965_param_antenna; /* def: 0 = both antennas (use diversity) */
+-int iwl4965_param_hwcrypto; /* def: using software encryption */
+-static int iwl4965_param_qos_enable = 1; /* def: 1 = use quality of service */
+-int iwl4965_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 16 Tx queues */
+-int iwl4965_param_amsdu_size_8K; /* def: enable 8K amsdu size */
+-
+ /*
+ * module name, copyright, version, etc.
+ * NOTE: DRV_NAME is defined in iwlwifi.h for use by iwl-debug.h and printk
+@@ -78,7 +68,7 @@ int iwl4965_param_amsdu_size_8K; /* def: enable 8K amsdu size */
+
+ #define DRV_DESCRIPTION "Intel(R) Wireless WiFi Link 4965AGN driver for Linux"
+
+-#ifdef CONFIG_IWL4965_DEBUG
++#ifdef CONFIG_IWLWIFI_DEBUG
+ #define VD "d"
+ #else
+ #define VD
+@@ -90,15 +80,8 @@ int iwl4965_param_amsdu_size_8K; /* def: enable 8K amsdu size */
+ #define VS
+ #endif
+
+-#define IWLWIFI_VERSION "1.2.23k" VD VS
+-#define DRV_COPYRIGHT "Copyright(c) 2003-2007 Intel Corporation"
+-#define DRV_VERSION IWLWIFI_VERSION
++#define DRV_VERSION IWLWIFI_VERSION VD VS
+
+-/* Change firmware file name, using "-" and incrementing number,
+- * *only* when uCode interface or architecture changes so that it
+- * is not compatible with earlier drivers.
+- * This number will also appear in << 8 position of 1st dword of uCode file */
+-#define IWL4965_UCODE_API "-1"
+
+ MODULE_DESCRIPTION(DRV_DESCRIPTION);
+ MODULE_VERSION(DRV_VERSION);
+@@ -115,16 +98,10 @@ __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr)
+ return NULL;
+ }
+
+-static const struct ieee80211_hw_mode *iwl4965_get_hw_mode(
+- struct iwl4965_priv *priv, int mode)
++static const struct ieee80211_supported_band *iwl4965_get_hw_mode(
++ struct iwl_priv *priv, enum ieee80211_band band)
+ {
+- int i;
+-
+- for (i = 0; i < 3; i++)
+- if (priv->modes[i].mode == mode)
+- return &priv->modes[i];
+-
+- return NULL;
++ return priv->hw->wiphy->bands[band];
+ }
+
+ static int iwl4965_is_empty_essid(const char *essid, int essid_len)
+@@ -167,17 +144,6 @@ static const char *iwl4965_escape_essid(const char *essid, u8 essid_len)
+ return escaped;
+ }
+
+-static void iwl4965_print_hex_dump(int level, void *p, u32 len)
+-{
+-#ifdef CONFIG_IWL4965_DEBUG
+- if (!(iwl4965_debug_level & level))
+- return;
+-
+- print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1,
+- p, len, 1);
+-#endif
+-}
+-
+ /*************** DMA-QUEUE-GENERAL-FUNCTIONS *****
+ * DMA services
+ *
+@@ -205,7 +171,7 @@ static void iwl4965_print_hex_dump(int level, void *p, u32 len)
+ * See more detailed info in iwl-4965-hw.h.
+ ***************************************************/
+
+-static int iwl4965_queue_space(const struct iwl4965_queue *q)
++int iwl4965_queue_space(const struct iwl4965_queue *q)
+ {
+ int s = q->read_ptr - q->write_ptr;
+
+@@ -221,25 +187,6 @@ static int iwl4965_queue_space(const struct iwl4965_queue *q)
+ return s;
+ }
+
+-/**
+- * iwl4965_queue_inc_wrap - increment queue index, wrap back to beginning
+- * @index -- current index
+- * @n_bd -- total number of entries in queue (must be power of 2)
+- */
+-static inline int iwl4965_queue_inc_wrap(int index, int n_bd)
+-{
+- return ++index & (n_bd - 1);
+-}
+-
+-/**
+- * iwl4965_queue_dec_wrap - decrement queue index, wrap back to end
+- * @index -- current index
+- * @n_bd -- total number of entries in queue (must be power of 2)
+- */
+-static inline int iwl4965_queue_dec_wrap(int index, int n_bd)
+-{
+- return --index & (n_bd - 1);
+-}
+
+ static inline int x2_queue_used(const struct iwl4965_queue *q, int i)
+ {
+@@ -261,15 +208,15 @@ static inline u8 get_cmd_index(struct iwl4965_queue *q, u32 index, int is_huge)
+ /**
+ * iwl4965_queue_init - Initialize queue's high/low-water and read/write indexes
+ */
+-static int iwl4965_queue_init(struct iwl4965_priv *priv, struct iwl4965_queue *q,
++static int iwl4965_queue_init(struct iwl_priv *priv, struct iwl4965_queue *q,
+ int count, int slots_num, u32 id)
+ {
+ q->n_bd = count;
+ q->n_window = slots_num;
+ q->id = id;
+
+- /* count must be power-of-two size, otherwise iwl4965_queue_inc_wrap
+- * and iwl4965_queue_dec_wrap are broken. */
++ /* count must be power-of-two size, otherwise iwl_queue_inc_wrap
++ * and iwl_queue_dec_wrap are broken. */
+ BUG_ON(!is_power_of_2(count));
+
+ /* slots_num must be power-of-two size, otherwise
+@@ -292,7 +239,7 @@ static int iwl4965_queue_init(struct iwl4965_priv *priv, struct iwl4965_queue *q
+ /**
+ * iwl4965_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue
+ */
+-static int iwl4965_tx_queue_alloc(struct iwl4965_priv *priv,
++static int iwl4965_tx_queue_alloc(struct iwl_priv *priv,
+ struct iwl4965_tx_queue *txq, u32 id)
+ {
+ struct pci_dev *dev = priv->pci_dev;
+@@ -337,7 +284,7 @@ static int iwl4965_tx_queue_alloc(struct iwl4965_priv *priv,
+ /**
+ * iwl4965_tx_queue_init - Allocate and initialize one tx/cmd queue
+ */
+-int iwl4965_tx_queue_init(struct iwl4965_priv *priv,
++int iwl4965_tx_queue_init(struct iwl_priv *priv,
+ struct iwl4965_tx_queue *txq, int slots_num, u32 txq_id)
+ {
+ struct pci_dev *dev = priv->pci_dev;
+@@ -352,7 +299,7 @@ int iwl4965_tx_queue_init(struct iwl4965_priv *priv,
+ * For normal Tx queues (all other queues), no super-size command
+ * space is needed.
+ */
+- len = sizeof(struct iwl4965_cmd) * slots_num;
++ len = sizeof(struct iwl_cmd) * slots_num;
+ if (txq_id == IWL_CMD_QUEUE_NUM)
+ len += IWL_MAX_SCAN_SIZE;
+ txq->cmd = pci_alloc_consistent(dev, len, &txq->dma_addr_cmd);
+@@ -369,7 +316,7 @@ int iwl4965_tx_queue_init(struct iwl4965_priv *priv,
+ txq->need_update = 0;
+
+ /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
+- * iwl4965_queue_inc_wrap and iwl4965_queue_dec_wrap are broken. */
++ * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
+ BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
+
+ /* Initialize queue's high/low-water marks, and head/tail indexes */
+@@ -389,7 +336,7 @@ int iwl4965_tx_queue_init(struct iwl4965_priv *priv,
+ * Free all buffers.
+ * 0-fill, but do not free "txq" descriptor structure.
+ */
+-void iwl4965_tx_queue_free(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq)
++void iwl4965_tx_queue_free(struct iwl_priv *priv, struct iwl4965_tx_queue *txq)
+ {
+ struct iwl4965_queue *q = &txq->q;
+ struct pci_dev *dev = priv->pci_dev;
+@@ -400,10 +347,10 @@ void iwl4965_tx_queue_free(struct iwl4965_priv *priv, struct iwl4965_tx_queue *t
+
+ /* first, empty all BD's */
+ for (; q->write_ptr != q->read_ptr;
+- q->read_ptr = iwl4965_queue_inc_wrap(q->read_ptr, q->n_bd))
++ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd))
+ iwl4965_hw_txq_free_tfd(priv, txq);
+
+- len = sizeof(struct iwl4965_cmd) * q->n_window;
++ len = sizeof(struct iwl_cmd) * q->n_window;
+ if (q->id == IWL_CMD_QUEUE_NUM)
+ len += IWL_MAX_SCAN_SIZE;
+
+@@ -440,7 +387,7 @@ const u8 iwl4965_broadcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+ *
+ * NOTE: This does not remove station from device's station table.
+ */
+-static u8 iwl4965_remove_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap)
++static u8 iwl4965_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
+ {
+ int index = IWL_INVALID_STATION;
+ int i;
+@@ -451,9 +398,9 @@ static u8 iwl4965_remove_station(struct iwl4965_priv *priv, const u8 *addr, int
+ if (is_ap)
+ index = IWL_AP_ID;
+ else if (is_broadcast_ether_addr(addr))
+- index = priv->hw_setting.bcast_sta_id;
++ index = priv->hw_params.bcast_sta_id;
+ else
+- for (i = IWL_STA_ID; i < priv->hw_setting.max_stations; i++)
++ for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++)
+ if (priv->stations[i].used &&
+ !compare_ether_addr(priv->stations[i].sta.sta.addr,
+ addr)) {
+@@ -478,26 +425,9 @@ out:
+ #endif
+
+ /**
+- * iwl4965_clear_stations_table - Clear the driver's station table
+- *
+- * NOTE: This does not clear or otherwise alter the device's station table.
+- */
+-static void iwl4965_clear_stations_table(struct iwl4965_priv *priv)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&priv->sta_lock, flags);
+-
+- priv->num_stations = 0;
+- memset(priv->stations, 0, sizeof(priv->stations));
+-
+- spin_unlock_irqrestore(&priv->sta_lock, flags);
+-}
+-
+-/**
+ * iwl4965_add_station_flags - Add station to tables in driver and device
+ */
+-u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr,
++u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr,
+ int is_ap, u8 flags, void *ht_data)
+ {
+ int i;
+@@ -510,9 +440,9 @@ u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr,
+ if (is_ap)
+ index = IWL_AP_ID;
+ else if (is_broadcast_ether_addr(addr))
+- index = priv->hw_setting.bcast_sta_id;
++ index = priv->hw_params.bcast_sta_id;
+ else
+- for (i = IWL_STA_ID; i < priv->hw_setting.max_stations; i++) {
++ for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) {
+ if (!compare_ether_addr(priv->stations[i].sta.sta.addr,
+ addr)) {
+ index = i;
+@@ -553,7 +483,7 @@ u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr,
+
+ #ifdef CONFIG_IWL4965_HT
+ /* BCAST station and IBSS stations do not work in HT mode */
+- if (index != priv->hw_setting.bcast_sta_id &&
++ if (index != priv->hw_params.bcast_sta_id &&
+ priv->iw_mode != IEEE80211_IF_TYPE_IBSS)
+ iwl4965_set_ht_add_station(priv, index,
+ (struct ieee80211_ht_info *) ht_data);
+@@ -567,103 +497,10 @@ u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr,
+
+ }
+
+-/*************** DRIVER STATUS FUNCTIONS *****/
+-
+-static inline int iwl4965_is_ready(struct iwl4965_priv *priv)
+-{
+- /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
+- * set but EXIT_PENDING is not */
+- return test_bit(STATUS_READY, &priv->status) &&
+- test_bit(STATUS_GEO_CONFIGURED, &priv->status) &&
+- !test_bit(STATUS_EXIT_PENDING, &priv->status);
+-}
+-
+-static inline int iwl4965_is_alive(struct iwl4965_priv *priv)
+-{
+- return test_bit(STATUS_ALIVE, &priv->status);
+-}
+-
+-static inline int iwl4965_is_init(struct iwl4965_priv *priv)
+-{
+- return test_bit(STATUS_INIT, &priv->status);
+-}
+-
+-static inline int iwl4965_is_rfkill(struct iwl4965_priv *priv)
+-{
+- return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
+- test_bit(STATUS_RF_KILL_SW, &priv->status);
+-}
+-
+-static inline int iwl4965_is_ready_rf(struct iwl4965_priv *priv)
+-{
+-
+- if (iwl4965_is_rfkill(priv))
+- return 0;
+
+- return iwl4965_is_ready(priv);
+-}
+
+ /*************** HOST COMMAND QUEUE FUNCTIONS *****/
+
+-#define IWL_CMD(x) case x : return #x
+-
+-static const char *get_cmd_string(u8 cmd)
+-{
+- switch (cmd) {
+- IWL_CMD(REPLY_ALIVE);
+- IWL_CMD(REPLY_ERROR);
+- IWL_CMD(REPLY_RXON);
+- IWL_CMD(REPLY_RXON_ASSOC);
+- IWL_CMD(REPLY_QOS_PARAM);
+- IWL_CMD(REPLY_RXON_TIMING);
+- IWL_CMD(REPLY_ADD_STA);
+- IWL_CMD(REPLY_REMOVE_STA);
+- IWL_CMD(REPLY_REMOVE_ALL_STA);
+- IWL_CMD(REPLY_TX);
+- IWL_CMD(REPLY_RATE_SCALE);
+- IWL_CMD(REPLY_LEDS_CMD);
+- IWL_CMD(REPLY_TX_LINK_QUALITY_CMD);
+- IWL_CMD(RADAR_NOTIFICATION);
+- IWL_CMD(REPLY_QUIET_CMD);
+- IWL_CMD(REPLY_CHANNEL_SWITCH);
+- IWL_CMD(CHANNEL_SWITCH_NOTIFICATION);
+- IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD);
+- IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION);
+- IWL_CMD(POWER_TABLE_CMD);
+- IWL_CMD(PM_SLEEP_NOTIFICATION);
+- IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC);
+- IWL_CMD(REPLY_SCAN_CMD);
+- IWL_CMD(REPLY_SCAN_ABORT_CMD);
+- IWL_CMD(SCAN_START_NOTIFICATION);
+- IWL_CMD(SCAN_RESULTS_NOTIFICATION);
+- IWL_CMD(SCAN_COMPLETE_NOTIFICATION);
+- IWL_CMD(BEACON_NOTIFICATION);
+- IWL_CMD(REPLY_TX_BEACON);
+- IWL_CMD(WHO_IS_AWAKE_NOTIFICATION);
+- IWL_CMD(QUIET_NOTIFICATION);
+- IWL_CMD(REPLY_TX_PWR_TABLE_CMD);
+- IWL_CMD(MEASURE_ABORT_NOTIFICATION);
+- IWL_CMD(REPLY_BT_CONFIG);
+- IWL_CMD(REPLY_STATISTICS_CMD);
+- IWL_CMD(STATISTICS_NOTIFICATION);
+- IWL_CMD(REPLY_CARD_STATE_CMD);
+- IWL_CMD(CARD_STATE_NOTIFICATION);
+- IWL_CMD(MISSED_BEACONS_NOTIFICATION);
+- IWL_CMD(REPLY_CT_KILL_CONFIG_CMD);
+- IWL_CMD(SENSITIVITY_CMD);
+- IWL_CMD(REPLY_PHY_CALIBRATION_CMD);
+- IWL_CMD(REPLY_RX_PHY_CMD);
+- IWL_CMD(REPLY_RX_MPDU_CMD);
+- IWL_CMD(REPLY_4965_RX);
+- IWL_CMD(REPLY_COMPRESSED_BA);
+- default:
+- return "UNKNOWN";
+-
+- }
+-}
+-
+-#define HOST_COMPLETE_TIMEOUT (HZ / 2)
+-
+ /**
+ * iwl4965_enqueue_hcmd - enqueue a uCode command
+ * @priv: device private data point
+@@ -673,13 +510,13 @@ static const char *get_cmd_string(u8 cmd)
+ * failed. On success, it turns the index (> 0) of command in the
+ * command queue.
+ */
+-static int iwl4965_enqueue_hcmd(struct iwl4965_priv *priv, struct iwl4965_host_cmd *cmd)
++int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+ {
+ struct iwl4965_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
+ struct iwl4965_queue *q = &txq->q;
+ struct iwl4965_tfd_frame *tfd;
+ u32 *control_flags;
+- struct iwl4965_cmd *out_cmd;
++ struct iwl_cmd *out_cmd;
+ u32 idx;
+ u16 fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));
+ dma_addr_t phys_addr;
+@@ -692,7 +529,7 @@ static int iwl4965_enqueue_hcmd(struct iwl4965_priv *priv, struct iwl4965_host_c
+ BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
+ !(cmd->meta.flags & CMD_SIZE_HUGE));
+
+- if (iwl4965_is_rfkill(priv)) {
++ if (iwl_is_rfkill(priv)) {
+ IWL_DEBUG_INFO("Not sending command - RF KILL");
+ return -EIO;
+ }
+@@ -726,7 +563,7 @@ static int iwl4965_enqueue_hcmd(struct iwl4965_priv *priv, struct iwl4965_host_c
+ out_cmd->hdr.sequence |= cpu_to_le16(SEQ_HUGE_FRAME);
+
+ phys_addr = txq->dma_addr_cmd + sizeof(txq->cmd[0]) * idx +
+- offsetof(struct iwl4965_cmd, hdr);
++ offsetof(struct iwl_cmd, hdr);
+ iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size);
+
+ IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, "
+@@ -738,161 +575,25 @@ static int iwl4965_enqueue_hcmd(struct iwl4965_priv *priv, struct iwl4965_host_c
+ txq->need_update = 1;
+
+ /* Set up entry in queue's byte count circular buffer */
+- ret = iwl4965_tx_queue_update_wr_ptr(priv, txq, 0);
++ priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, 0);
+
+ /* Increment and update queue's write index */
+- q->write_ptr = iwl4965_queue_inc_wrap(q->write_ptr, q->n_bd);
+- iwl4965_tx_queue_update_write_ptr(priv, txq);
++ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
++ ret = iwl4965_tx_queue_update_write_ptr(priv, txq);
+
+ spin_unlock_irqrestore(&priv->hcmd_lock, flags);
+ return ret ? ret : idx;
+ }
+
+-static int iwl4965_send_cmd_async(struct iwl4965_priv *priv, struct iwl4965_host_cmd *cmd)
++static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
+ {
+- int ret;
+-
+- BUG_ON(!(cmd->meta.flags & CMD_ASYNC));
+-
+- /* An asynchronous command can not expect an SKB to be set. */
+- BUG_ON(cmd->meta.flags & CMD_WANT_SKB);
+-
+- /* An asynchronous command MUST have a callback. */
+- BUG_ON(!cmd->meta.u.callback);
+-
+- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+- return -EBUSY;
+-
+- ret = iwl4965_enqueue_hcmd(priv, cmd);
+- if (ret < 0) {
+- IWL_ERROR("Error sending %s: iwl4965_enqueue_hcmd failed: %d\n",
+- get_cmd_string(cmd->id), ret);
+- return ret;
+- }
+- return 0;
+-}
+-
+-static int iwl4965_send_cmd_sync(struct iwl4965_priv *priv, struct iwl4965_host_cmd *cmd)
+-{
+- int cmd_idx;
+- int ret;
+- static atomic_t entry = ATOMIC_INIT(0); /* reentrance protection */
+-
+- BUG_ON(cmd->meta.flags & CMD_ASYNC);
+-
+- /* A synchronous command can not have a callback set. */
+- BUG_ON(cmd->meta.u.callback != NULL);
+-
+- if (atomic_xchg(&entry, 1)) {
+- IWL_ERROR("Error sending %s: Already sending a host command\n",
+- get_cmd_string(cmd->id));
+- return -EBUSY;
+- }
+-
+- set_bit(STATUS_HCMD_ACTIVE, &priv->status);
+-
+- if (cmd->meta.flags & CMD_WANT_SKB)
+- cmd->meta.source = &cmd->meta;
+-
+- cmd_idx = iwl4965_enqueue_hcmd(priv, cmd);
+- if (cmd_idx < 0) {
+- ret = cmd_idx;
+- IWL_ERROR("Error sending %s: iwl4965_enqueue_hcmd failed: %d\n",
+- get_cmd_string(cmd->id), ret);
+- goto out;
+- }
+-
+- ret = wait_event_interruptible_timeout(priv->wait_command_queue,
+- !test_bit(STATUS_HCMD_ACTIVE, &priv->status),
+- HOST_COMPLETE_TIMEOUT);
+- if (!ret) {
+- if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) {
+- IWL_ERROR("Error sending %s: time out after %dms.\n",
+- get_cmd_string(cmd->id),
+- jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
+-
+- clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
+- ret = -ETIMEDOUT;
+- goto cancel;
+- }
+- }
+-
+- if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
+- IWL_DEBUG_INFO("Command %s aborted: RF KILL Switch\n",
+- get_cmd_string(cmd->id));
+- ret = -ECANCELED;
+- goto fail;
+- }
+- if (test_bit(STATUS_FW_ERROR, &priv->status)) {
+- IWL_DEBUG_INFO("Command %s failed: FW Error\n",
+- get_cmd_string(cmd->id));
+- ret = -EIO;
+- goto fail;
+- }
+- if ((cmd->meta.flags & CMD_WANT_SKB) && !cmd->meta.u.skb) {
+- IWL_ERROR("Error: Response NULL in '%s'\n",
+- get_cmd_string(cmd->id));
+- ret = -EIO;
+- goto out;
+- }
+-
+- ret = 0;
+- goto out;
+-
+-cancel:
+- if (cmd->meta.flags & CMD_WANT_SKB) {
+- struct iwl4965_cmd *qcmd;
+-
+- /* Cancel the CMD_WANT_SKB flag for the cmd in the
+- * TX cmd queue. Otherwise in case the cmd comes
+- * in later, it will possibly set an invalid
+- * address (cmd->meta.source). */
+- qcmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx];
+- qcmd->meta.flags &= ~CMD_WANT_SKB;
+- }
+-fail:
+- if (cmd->meta.u.skb) {
+- dev_kfree_skb_any(cmd->meta.u.skb);
+- cmd->meta.u.skb = NULL;
+- }
+-out:
+- atomic_set(&entry, 0);
+- return ret;
+-}
+-
+-int iwl4965_send_cmd(struct iwl4965_priv *priv, struct iwl4965_host_cmd *cmd)
+-{
+- if (cmd->meta.flags & CMD_ASYNC)
+- return iwl4965_send_cmd_async(priv, cmd);
+-
+- return iwl4965_send_cmd_sync(priv, cmd);
+-}
+-
+-int iwl4965_send_cmd_pdu(struct iwl4965_priv *priv, u8 id, u16 len, const void *data)
+-{
+- struct iwl4965_host_cmd cmd = {
+- .id = id,
+- .len = len,
+- .data = data,
+- };
+-
+- return iwl4965_send_cmd_sync(priv, &cmd);
+-}
+-
+-static int __must_check iwl4965_send_cmd_u32(struct iwl4965_priv *priv, u8 id, u32 val)
+-{
+- struct iwl4965_host_cmd cmd = {
+- .id = id,
+- .len = sizeof(val),
+- .data = &val,
+- };
++ struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon;
+
+- return iwl4965_send_cmd_sync(priv, &cmd);
+-}
++ if (hw_decrypt)
++ rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK;
++ else
++ rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK;
+
+-int iwl4965_send_statistics_request(struct iwl4965_priv *priv)
+-{
+- return iwl4965_send_cmd_u32(priv, REPLY_STATISTICS_CMD, 0);
+ }
+
+ /**
+@@ -901,7 +602,7 @@ int iwl4965_send_statistics_request(struct iwl4965_priv *priv)
+ * there is only one AP station with id= IWL_AP_ID
+ * NOTE: mutex must be held before calling this fnction
+ */
+-static int iwl4965_rxon_add_station(struct iwl4965_priv *priv,
++static int iwl4965_rxon_add_station(struct iwl_priv *priv,
+ const u8 *addr, int is_ap)
+ {
+ u8 sta_id;
+@@ -928,42 +629,6 @@ static int iwl4965_rxon_add_station(struct iwl4965_priv *priv,
+ }
+
+ /**
+- * iwl4965_set_rxon_channel - Set the phymode and channel values in staging RXON
+- * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
+- * @channel: Any channel valid for the requested phymode
+-
+- * In addition to setting the staging RXON, priv->phymode is also set.
+- *
+- * NOTE: Does not commit to the hardware; it sets appropriate bit fields
+- * in the staging RXON flag structure based on the phymode
+- */
+-static int iwl4965_set_rxon_channel(struct iwl4965_priv *priv, u8 phymode,
+- u16 channel)
+-{
+- if (!iwl4965_get_channel_info(priv, phymode, channel)) {
+- IWL_DEBUG_INFO("Could not set channel to %d [%d]\n",
+- channel, phymode);
+- return -EINVAL;
+- }
+-
+- if ((le16_to_cpu(priv->staging_rxon.channel) == channel) &&
+- (priv->phymode == phymode))
+- return 0;
+-
+- priv->staging_rxon.channel = cpu_to_le16(channel);
+- if (phymode == MODE_IEEE80211A)
+- priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK;
+- else
+- priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
+-
+- priv->phymode = phymode;
+-
+- IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, phymode);
+-
+- return 0;
+-}
+-
+-/**
+ * iwl4965_check_rxon_cmd - validate RXON structure is valid
+ *
+ * NOTE: This is really only useful during development and can eventually
+@@ -1044,7 +709,7 @@ static int iwl4965_check_rxon_cmd(struct iwl4965_rxon_cmd *rxon)
+ * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that
+ * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required.
+ */
+-static int iwl4965_full_rxon_required(struct iwl4965_priv *priv)
++static int iwl4965_full_rxon_required(struct iwl_priv *priv)
+ {
+
+ /* These items are only settable from the full RXON command */
+@@ -1084,60 +749,6 @@ static int iwl4965_full_rxon_required(struct iwl4965_priv *priv)
+ return 0;
+ }
+
+-static int iwl4965_send_rxon_assoc(struct iwl4965_priv *priv)
+-{
+- int rc = 0;
+- struct iwl4965_rx_packet *res = NULL;
+- struct iwl4965_rxon_assoc_cmd rxon_assoc;
+- struct iwl4965_host_cmd cmd = {
+- .id = REPLY_RXON_ASSOC,
+- .len = sizeof(rxon_assoc),
+- .meta.flags = CMD_WANT_SKB,
+- .data = &rxon_assoc,
+- };
+- const struct iwl4965_rxon_cmd *rxon1 = &priv->staging_rxon;
+- const struct iwl4965_rxon_cmd *rxon2 = &priv->active_rxon;
+-
+- if ((rxon1->flags == rxon2->flags) &&
+- (rxon1->filter_flags == rxon2->filter_flags) &&
+- (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
+- (rxon1->ofdm_ht_single_stream_basic_rates ==
+- rxon2->ofdm_ht_single_stream_basic_rates) &&
+- (rxon1->ofdm_ht_dual_stream_basic_rates ==
+- rxon2->ofdm_ht_dual_stream_basic_rates) &&
+- (rxon1->rx_chain == rxon2->rx_chain) &&
+- (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
+- IWL_DEBUG_INFO("Using current RXON_ASSOC. Not resending.\n");
+- return 0;
+- }
+-
+- rxon_assoc.flags = priv->staging_rxon.flags;
+- rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
+- rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
+- rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
+- rxon_assoc.reserved = 0;
+- rxon_assoc.ofdm_ht_single_stream_basic_rates =
+- priv->staging_rxon.ofdm_ht_single_stream_basic_rates;
+- rxon_assoc.ofdm_ht_dual_stream_basic_rates =
+- priv->staging_rxon.ofdm_ht_dual_stream_basic_rates;
+- rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain;
+-
+- rc = iwl4965_send_cmd_sync(priv, &cmd);
+- if (rc)
+- return rc;
+-
+- res = (struct iwl4965_rx_packet *)cmd.meta.u.skb->data;
+- if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
+- IWL_ERROR("Bad return from REPLY_RXON_ASSOC command\n");
+- rc = -EIO;
+- }
+-
+- priv->alloc_rxb_skb--;
+- dev_kfree_skb_any(cmd.meta.u.skb);
+-
+- return rc;
+-}
+-
+ /**
+ * iwl4965_commit_rxon - commit staging_rxon to hardware
+ *
+@@ -1146,14 +757,14 @@ static int iwl4965_send_rxon_assoc(struct iwl4965_priv *priv)
+ * function correctly transitions out of the RXON_ASSOC_MSK state if
+ * a HW tune is required based on the RXON structure changes.
+ */
+-static int iwl4965_commit_rxon(struct iwl4965_priv *priv)
++static int iwl4965_commit_rxon(struct iwl_priv *priv)
+ {
+ /* cast away the const for active_rxon in this function */
+ struct iwl4965_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
+ DECLARE_MAC_BUF(mac);
+ int rc = 0;
+
+- if (!iwl4965_is_alive(priv))
++ if (!iwl_is_alive(priv))
+ return -1;
+
+ /* always get timestamp with Rx frame */
+@@ -1169,7 +780,7 @@ static int iwl4965_commit_rxon(struct iwl4965_priv *priv)
+ * iwl4965_rxon_assoc_cmd which is used to reconfigure filter
+ * and other flags for the current radio configuration. */
+ if (!iwl4965_full_rxon_required(priv)) {
+- rc = iwl4965_send_rxon_assoc(priv);
++ rc = iwl_send_rxon_assoc(priv);
+ if (rc) {
+ IWL_ERROR("Error setting RXON_ASSOC "
+ "configuration (%d).\n", rc);
+@@ -1196,12 +807,12 @@ static int iwl4965_commit_rxon(struct iwl4965_priv *priv)
+ * an RXON_ASSOC and the new config wants the associated mask enabled,
+ * we must clear the associated from the active configuration
+ * before we apply the new config */
+- if (iwl4965_is_associated(priv) &&
++ if (iwl_is_associated(priv) &&
+ (priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) {
+ IWL_DEBUG_INFO("Toggling associated bit on current RXON\n");
+ active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+
+- rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON,
++ rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
+ sizeof(struct iwl4965_rxon_cmd),
+ &priv->active_rxon);
+
+@@ -1224,15 +835,16 @@ static int iwl4965_commit_rxon(struct iwl4965_priv *priv)
+ le16_to_cpu(priv->staging_rxon.channel),
+ print_mac(mac, priv->staging_rxon.bssid_addr));
+
++ iwl4965_set_rxon_hwcrypto(priv, !priv->cfg->mod_params->sw_crypto);
+ /* Apply the new configuration */
+- rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON,
++ rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
+ sizeof(struct iwl4965_rxon_cmd), &priv->staging_rxon);
+ if (rc) {
+ IWL_ERROR("Error setting new configuration (%d).\n", rc);
+ return rc;
+ }
+
+- iwl4965_clear_stations_table(priv);
++ iwlcore_clear_stations_table(priv);
+
+ #ifdef CONFIG_IWL4965_SENSITIVITY
+ if (!priv->error_recovering)
+@@ -1261,7 +873,7 @@ static int iwl4965_commit_rxon(struct iwl4965_priv *priv)
+
+ /* If we have set the ASSOC_MSK and we are in BSS mode then
+ * add the IWL_AP_ID to the station rate table */
+- if (iwl4965_is_associated(priv) &&
++ if (iwl_is_associated(priv) &&
+ (priv->iw_mode == IEEE80211_IF_TYPE_STA)) {
+ if (iwl4965_rxon_add_station(priv, priv->active_rxon.bssid_addr, 1)
+ == IWL_INVALID_STATION) {
+@@ -1269,12 +881,15 @@ static int iwl4965_commit_rxon(struct iwl4965_priv *priv)
+ return -EIO;
+ }
+ priv->assoc_station_added = 1;
++ if (priv->default_wep_key &&
++ iwl_send_static_wepkey_cmd(priv, 0))
++ IWL_ERROR("Could not send WEP static key.\n");
+ }
+
+ return 0;
+ }
+
+-static int iwl4965_send_bt_config(struct iwl4965_priv *priv)
++static int iwl4965_send_bt_config(struct iwl_priv *priv)
+ {
+ struct iwl4965_bt_cmd bt_cmd = {
+ .flags = 3,
+@@ -1284,15 +899,15 @@ static int iwl4965_send_bt_config(struct iwl4965_priv *priv)
+ .kill_cts_mask = 0,
+ };
+
+- return iwl4965_send_cmd_pdu(priv, REPLY_BT_CONFIG,
++ return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
+ sizeof(struct iwl4965_bt_cmd), &bt_cmd);
+ }
+
+-static int iwl4965_send_scan_abort(struct iwl4965_priv *priv)
++static int iwl4965_send_scan_abort(struct iwl_priv *priv)
+ {
+ int rc = 0;
+ struct iwl4965_rx_packet *res;
+- struct iwl4965_host_cmd cmd = {
++ struct iwl_host_cmd cmd = {
+ .id = REPLY_SCAN_ABORT_CMD,
+ .meta.flags = CMD_WANT_SKB,
+ };
+@@ -1305,7 +920,7 @@ static int iwl4965_send_scan_abort(struct iwl4965_priv *priv)
+ return 0;
+ }
+
+- rc = iwl4965_send_cmd_sync(priv, &cmd);
++ rc = iwl_send_cmd_sync(priv, &cmd);
+ if (rc) {
+ clear_bit(STATUS_SCAN_ABORTING, &priv->status);
+ return rc;
+@@ -1329,8 +944,8 @@ static int iwl4965_send_scan_abort(struct iwl4965_priv *priv)
+ return rc;
+ }
+
+-static int iwl4965_card_state_sync_callback(struct iwl4965_priv *priv,
+- struct iwl4965_cmd *cmd,
++static int iwl4965_card_state_sync_callback(struct iwl_priv *priv,
++ struct iwl_cmd *cmd,
+ struct sk_buff *skb)
+ {
+ return 1;
+@@ -1346,9 +961,9 @@ static int iwl4965_card_state_sync_callback(struct iwl4965_priv *priv,
+ * When in the 'halt' state, the card is shut down and must be fully
+ * restarted to come back on.
+ */
+-static int iwl4965_send_card_state(struct iwl4965_priv *priv, u32 flags, u8 meta_flag)
++static int iwl4965_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
+ {
+- struct iwl4965_host_cmd cmd = {
++ struct iwl_host_cmd cmd = {
+ .id = REPLY_CARD_STATE_CMD,
+ .len = sizeof(u32),
+ .data = &flags,
+@@ -1358,11 +973,11 @@ static int iwl4965_send_card_state(struct iwl4965_priv *priv, u32 flags, u8 meta
+ if (meta_flag & CMD_ASYNC)
+ cmd.meta.u.callback = iwl4965_card_state_sync_callback;
+
+- return iwl4965_send_cmd(priv, &cmd);
++ return iwl_send_cmd(priv, &cmd);
+ }
+
+-static int iwl4965_add_sta_sync_callback(struct iwl4965_priv *priv,
+- struct iwl4965_cmd *cmd, struct sk_buff *skb)
++static int iwl4965_add_sta_sync_callback(struct iwl_priv *priv,
++ struct iwl_cmd *cmd, struct sk_buff *skb)
+ {
+ struct iwl4965_rx_packet *res = NULL;
+
+@@ -1389,12 +1004,12 @@ static int iwl4965_add_sta_sync_callback(struct iwl4965_priv *priv,
+ return 1;
+ }
+
+-int iwl4965_send_add_station(struct iwl4965_priv *priv,
++int iwl4965_send_add_station(struct iwl_priv *priv,
+ struct iwl4965_addsta_cmd *sta, u8 flags)
+ {
+ struct iwl4965_rx_packet *res = NULL;
+ int rc = 0;
+- struct iwl4965_host_cmd cmd = {
++ struct iwl_host_cmd cmd = {
+ .id = REPLY_ADD_STA,
+ .len = sizeof(struct iwl4965_addsta_cmd),
+ .meta.flags = flags,
+@@ -1406,7 +1021,7 @@ int iwl4965_send_add_station(struct iwl4965_priv *priv,
+ else
+ cmd.meta.flags |= CMD_WANT_SKB;
+
+- rc = iwl4965_send_cmd(priv, &cmd);
++ rc = iwl_send_cmd(priv, &cmd);
+
+ if (rc || (flags & CMD_ASYNC))
+ return rc;
+@@ -1436,62 +1051,7 @@ int iwl4965_send_add_station(struct iwl4965_priv *priv,
+ return rc;
+ }
+
+-static int iwl4965_update_sta_key_info(struct iwl4965_priv *priv,
+- struct ieee80211_key_conf *keyconf,
+- u8 sta_id)
+-{
+- unsigned long flags;
+- __le16 key_flags = 0;
+-
+- switch (keyconf->alg) {
+- case ALG_CCMP:
+- key_flags |= STA_KEY_FLG_CCMP;
+- key_flags |= cpu_to_le16(
+- keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+- key_flags &= ~STA_KEY_FLG_INVALID;
+- break;
+- case ALG_TKIP:
+- case ALG_WEP:
+- default:
+- return -EINVAL;
+- }
+- spin_lock_irqsave(&priv->sta_lock, flags);
+- priv->stations[sta_id].keyinfo.alg = keyconf->alg;
+- priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
+- memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
+- keyconf->keylen);
+-
+- memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
+- keyconf->keylen);
+- priv->stations[sta_id].sta.key.key_flags = key_flags;
+- priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+-
+- spin_unlock_irqrestore(&priv->sta_lock, flags);
+-
+- IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n");
+- iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0);
+- return 0;
+-}
+-
+-static int iwl4965_clear_sta_key_info(struct iwl4965_priv *priv, u8 sta_id)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&priv->sta_lock, flags);
+- memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl4965_hw_key));
+- memset(&priv->stations[sta_id].sta.key, 0, sizeof(struct iwl4965_keyinfo));
+- priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
+- priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+- spin_unlock_irqrestore(&priv->sta_lock, flags);
+-
+- IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n");
+- iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0);
+- return 0;
+-}
+-
+-static void iwl4965_clear_free_frames(struct iwl4965_priv *priv)
++static void iwl4965_clear_free_frames(struct iwl_priv *priv)
+ {
+ struct list_head *element;
+
+@@ -1512,7 +1072,7 @@ static void iwl4965_clear_free_frames(struct iwl4965_priv *priv)
+ }
+ }
+
+-static struct iwl4965_frame *iwl4965_get_free_frame(struct iwl4965_priv *priv)
++static struct iwl4965_frame *iwl4965_get_free_frame(struct iwl_priv *priv)
+ {
+ struct iwl4965_frame *frame;
+ struct list_head *element;
+@@ -1532,18 +1092,18 @@ static struct iwl4965_frame *iwl4965_get_free_frame(struct iwl4965_priv *priv)
+ return list_entry(element, struct iwl4965_frame, list);
+ }
+
+-static void iwl4965_free_frame(struct iwl4965_priv *priv, struct iwl4965_frame *frame)
++static void iwl4965_free_frame(struct iwl_priv *priv, struct iwl4965_frame *frame)
+ {
+ memset(frame, 0, sizeof(*frame));
+ list_add(&frame->list, &priv->free_frames);
+ }
+
+-unsigned int iwl4965_fill_beacon_frame(struct iwl4965_priv *priv,
++unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv,
+ struct ieee80211_hdr *hdr,
+ const u8 *dest, int left)
+ {
+
+- if (!iwl4965_is_associated(priv) || !priv->ibss_beacon ||
++ if (!iwl_is_associated(priv) || !priv->ibss_beacon ||
+ ((priv->iw_mode != IEEE80211_IF_TYPE_IBSS) &&
+ (priv->iw_mode != IEEE80211_IF_TYPE_AP)))
+ return 0;
+@@ -1556,34 +1116,6 @@ unsigned int iwl4965_fill_beacon_frame(struct iwl4965_priv *priv,
+ return priv->ibss_beacon->len;
+ }
+
+-int iwl4965_rate_index_from_plcp(int plcp)
+-{
+- int i = 0;
+-
+- /* 4965 HT rate format */
+- if (plcp & RATE_MCS_HT_MSK) {
+- i = (plcp & 0xff);
+-
+- if (i >= IWL_RATE_MIMO_6M_PLCP)
+- i = i - IWL_RATE_MIMO_6M_PLCP;
+-
+- i += IWL_FIRST_OFDM_RATE;
+- /* skip 9M not supported in ht*/
+- if (i >= IWL_RATE_9M_INDEX)
+- i += 1;
+- if ((i >= IWL_FIRST_OFDM_RATE) &&
+- (i <= IWL_LAST_OFDM_RATE))
+- return i;
+-
+- /* 4965 legacy rate format, search for match in table */
+- } else {
+- for (i = 0; i < ARRAY_SIZE(iwl4965_rates); i++)
+- if (iwl4965_rates[i].plcp == (plcp &0xFF))
+- return i;
+- }
+- return -1;
+-}
+-
+ static u8 iwl4965_rate_get_lowest_plcp(int rate_mask)
+ {
+ u8 i;
+@@ -1597,7 +1129,7 @@ static u8 iwl4965_rate_get_lowest_plcp(int rate_mask)
+ return IWL_RATE_INVALID;
+ }
+
+-static int iwl4965_send_beacon_cmd(struct iwl4965_priv *priv)
++static int iwl4965_send_beacon_cmd(struct iwl_priv *priv)
+ {
+ struct iwl4965_frame *frame;
+ unsigned int frame_size;
+@@ -1625,7 +1157,7 @@ static int iwl4965_send_beacon_cmd(struct iwl4965_priv *priv)
+
+ frame_size = iwl4965_hw_get_beacon_cmd(priv, frame, rate);
+
+- rc = iwl4965_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
++ rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
+ &frame->u.cmd[0]);
+
+ iwl4965_free_frame(priv, frame);
+@@ -1635,238 +1167,17 @@ static int iwl4965_send_beacon_cmd(struct iwl4965_priv *priv)
+
+ /******************************************************************************
+ *
+- * EEPROM related functions
+- *
+- ******************************************************************************/
+-
+-static void get_eeprom_mac(struct iwl4965_priv *priv, u8 *mac)
+-{
+- memcpy(mac, priv->eeprom.mac_address, 6);
+-}
+-
+-static inline void iwl4965_eeprom_release_semaphore(struct iwl4965_priv *priv)
+-{
+- iwl4965_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
+- CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
+-}
+-
+-/**
+- * iwl4965_eeprom_init - read EEPROM contents
+- *
+- * Load the EEPROM contents from adapter into priv->eeprom
+- *
+- * NOTE: This routine uses the non-debug IO access functions.
+- */
+-int iwl4965_eeprom_init(struct iwl4965_priv *priv)
+-{
+- u16 *e = (u16 *)&priv->eeprom;
+- u32 gp = iwl4965_read32(priv, CSR_EEPROM_GP);
+- u32 r;
+- int sz = sizeof(priv->eeprom);
+- int rc;
+- int i;
+- u16 addr;
+-
+- /* The EEPROM structure has several padding buffers within it
+- * and when adding new EEPROM maps is subject to programmer errors
+- * which may be very difficult to identify without explicitly
+- * checking the resulting size of the eeprom map. */
+- BUILD_BUG_ON(sizeof(priv->eeprom) != IWL_EEPROM_IMAGE_SIZE);
+-
+- if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) {
+- IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp);
+- return -ENOENT;
+- }
+-
+- /* Make sure driver (instead of uCode) is allowed to read EEPROM */
+- rc = iwl4965_eeprom_acquire_semaphore(priv);
+- if (rc < 0) {
+- IWL_ERROR("Failed to acquire EEPROM semaphore.\n");
+- return -ENOENT;
+- }
+-
+- /* eeprom is an array of 16bit values */
+- for (addr = 0; addr < sz; addr += sizeof(u16)) {
+- _iwl4965_write32(priv, CSR_EEPROM_REG, addr << 1);
+- _iwl4965_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD);
+-
+- for (i = 0; i < IWL_EEPROM_ACCESS_TIMEOUT;
+- i += IWL_EEPROM_ACCESS_DELAY) {
+- r = _iwl4965_read_direct32(priv, CSR_EEPROM_REG);
+- if (r & CSR_EEPROM_REG_READ_VALID_MSK)
+- break;
+- udelay(IWL_EEPROM_ACCESS_DELAY);
+- }
+-
+- if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) {
+- IWL_ERROR("Time out reading EEPROM[%d]", addr);
+- rc = -ETIMEDOUT;
+- goto done;
+- }
+- e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
+- }
+- rc = 0;
+-
+-done:
+- iwl4965_eeprom_release_semaphore(priv);
+- return rc;
+-}
+-
+-/******************************************************************************
+- *
+ * Misc. internal state and helper functions
+ *
+ ******************************************************************************/
+-#ifdef CONFIG_IWL4965_DEBUG
+-
+-/**
+- * iwl4965_report_frame - dump frame to syslog during debug sessions
+- *
+- * You may hack this function to show different aspects of received frames,
+- * including selective frame dumps.
+- * group100 parameter selects whether to show 1 out of 100 good frames.
+- *
+- * TODO: This was originally written for 3945, need to audit for
+- * proper operation with 4965.
+- */
+-void iwl4965_report_frame(struct iwl4965_priv *priv,
+- struct iwl4965_rx_packet *pkt,
+- struct ieee80211_hdr *header, int group100)
+-{
+- u32 to_us;
+- u32 print_summary = 0;
+- u32 print_dump = 0; /* set to 1 to dump all frames' contents */
+- u32 hundred = 0;
+- u32 dataframe = 0;
+- u16 fc;
+- u16 seq_ctl;
+- u16 channel;
+- u16 phy_flags;
+- int rate_sym;
+- u16 length;
+- u16 status;
+- u16 bcn_tmr;
+- u32 tsf_low;
+- u64 tsf;
+- u8 rssi;
+- u8 agc;
+- u16 sig_avg;
+- u16 noise_diff;
+- struct iwl4965_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
+- struct iwl4965_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
+- struct iwl4965_rx_frame_end *rx_end = IWL_RX_END(pkt);
+- u8 *data = IWL_RX_DATA(pkt);
+-
+- /* MAC header */
+- fc = le16_to_cpu(header->frame_control);
+- seq_ctl = le16_to_cpu(header->seq_ctrl);
+-
+- /* metadata */
+- channel = le16_to_cpu(rx_hdr->channel);
+- phy_flags = le16_to_cpu(rx_hdr->phy_flags);
+- rate_sym = rx_hdr->rate;
+- length = le16_to_cpu(rx_hdr->len);
+-
+- /* end-of-frame status and timestamp */
+- status = le32_to_cpu(rx_end->status);
+- bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp);
+- tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff;
+- tsf = le64_to_cpu(rx_end->timestamp);
+-
+- /* signal statistics */
+- rssi = rx_stats->rssi;
+- agc = rx_stats->agc;
+- sig_avg = le16_to_cpu(rx_stats->sig_avg);
+- noise_diff = le16_to_cpu(rx_stats->noise_diff);
+-
+- to_us = !compare_ether_addr(header->addr1, priv->mac_addr);
+-
+- /* if data frame is to us and all is good,
+- * (optionally) print summary for only 1 out of every 100 */
+- if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) ==
+- (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) {
+- dataframe = 1;
+- if (!group100)
+- print_summary = 1; /* print each frame */
+- else if (priv->framecnt_to_us < 100) {
+- priv->framecnt_to_us++;
+- print_summary = 0;
+- } else {
+- priv->framecnt_to_us = 0;
+- print_summary = 1;
+- hundred = 1;
+- }
+- } else {
+- /* print summary for all other frames */
+- print_summary = 1;
+- }
+-
+- if (print_summary) {
+- char *title;
+- u32 rate;
+-
+- if (hundred)
+- title = "100Frames";
+- else if (fc & IEEE80211_FCTL_RETRY)
+- title = "Retry";
+- else if (ieee80211_is_assoc_response(fc))
+- title = "AscRsp";
+- else if (ieee80211_is_reassoc_response(fc))
+- title = "RasRsp";
+- else if (ieee80211_is_probe_response(fc)) {
+- title = "PrbRsp";
+- print_dump = 1; /* dump frame contents */
+- } else if (ieee80211_is_beacon(fc)) {
+- title = "Beacon";
+- print_dump = 1; /* dump frame contents */
+- } else if (ieee80211_is_atim(fc))
+- title = "ATIM";
+- else if (ieee80211_is_auth(fc))
+- title = "Auth";
+- else if (ieee80211_is_deauth(fc))
+- title = "DeAuth";
+- else if (ieee80211_is_disassoc(fc))
+- title = "DisAssoc";
+- else
+- title = "Frame";
+
+- rate = iwl4965_rate_index_from_plcp(rate_sym);
+- if (rate == -1)
+- rate = 0;
+- else
+- rate = iwl4965_rates[rate].ieee / 2;
+-
+- /* print frame summary.
+- * MAC addresses show just the last byte (for brevity),
+- * but you can hack it to show more, if you'd like to. */
+- if (dataframe)
+- IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, "
+- "len=%u, rssi=%d, chnl=%d, rate=%u, \n",
+- title, fc, header->addr1[5],
+- length, rssi, channel, rate);
+- else {
+- /* src/dst addresses assume managed mode */
+- IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, "
+- "src=0x%02x, rssi=%u, tim=%lu usec, "
+- "phy=0x%02x, chnl=%d\n",
+- title, fc, header->addr1[5],
+- header->addr3[5], rssi,
+- tsf_low - priv->scan_start_tsf,
+- phy_flags, channel);
+- }
+- }
+- if (print_dump)
+- iwl4965_print_hex_dump(IWL_DL_RX, data, length);
+-}
+-#endif
+-
+-static void iwl4965_unset_hw_setting(struct iwl4965_priv *priv)
++static void iwl4965_unset_hw_params(struct iwl_priv *priv)
+ {
+- if (priv->hw_setting.shared_virt)
++ if (priv->shared_virt)
+ pci_free_consistent(priv->pci_dev,
+ sizeof(struct iwl4965_shared),
+- priv->hw_setting.shared_virt,
+- priv->hw_setting.shared_phys);
++ priv->shared_virt,
++ priv->shared_phys);
+ }
+
+ /**
+@@ -1898,24 +1209,20 @@ static u16 iwl4965_supported_rate_to_ie(u8 *ie, u16 supported_rate,
+ return ret_rates;
+ }
+
+-#ifdef CONFIG_IWL4965_HT
+-void static iwl4965_set_ht_capab(struct ieee80211_hw *hw,
+- struct ieee80211_ht_cap *ht_cap,
+- u8 use_current_config);
+-#endif
+-
+ /**
+ * iwl4965_fill_probe_req - fill in all required fields and IE for probe request
+ */
+-static u16 iwl4965_fill_probe_req(struct iwl4965_priv *priv,
+- struct ieee80211_mgmt *frame,
+- int left, int is_direct)
++static u16 iwl4965_fill_probe_req(struct iwl_priv *priv,
++ enum ieee80211_band band,
++ struct ieee80211_mgmt *frame,
++ int left, int is_direct)
+ {
+ int len = 0;
+ u8 *pos = NULL;
+ u16 active_rates, ret_rates, cck_rates, active_rate_basic;
+ #ifdef CONFIG_IWL4965_HT
+- struct ieee80211_hw_mode *mode;
++ const struct ieee80211_supported_band *sband =
++ iwl4965_get_hw_mode(priv, band);
+ #endif /* CONFIG_IWL4965_HT */
+
+ /* Make sure there is enough space for the probe request,
+@@ -2000,13 +1307,18 @@ static u16 iwl4965_fill_probe_req(struct iwl4965_priv *priv,
+ len += 2 + *pos;
+
+ #ifdef CONFIG_IWL4965_HT
+- mode = priv->hw->conf.mode;
+- if (mode->ht_info.ht_supported) {
++ if (sband && sband->ht_info.ht_supported) {
++ struct ieee80211_ht_cap *ht_cap;
+ pos += (*pos) + 1;
+ *pos++ = WLAN_EID_HT_CAPABILITY;
+ *pos++ = sizeof(struct ieee80211_ht_cap);
+- iwl4965_set_ht_capab(priv->hw,
+- (struct ieee80211_ht_cap *)pos, 0);
++ ht_cap = (struct ieee80211_ht_cap *)pos;
++ ht_cap->cap_info = cpu_to_le16(sband->ht_info.cap);
++ memcpy(ht_cap->supp_mcs_set, sband->ht_info.supp_mcs_set, 16);
++ ht_cap->ampdu_params_info =(sband->ht_info.ampdu_factor &
++ IEEE80211_HT_CAP_AMPDU_FACTOR) |
++ ((sband->ht_info.ampdu_density << 2) &
++ IEEE80211_HT_CAP_AMPDU_DENSITY);
+ len += 2 + sizeof(struct ieee80211_ht_cap);
+ }
+ #endif /*CONFIG_IWL4965_HT */
+@@ -2018,103 +1330,15 @@ static u16 iwl4965_fill_probe_req(struct iwl4965_priv *priv,
+ /*
+ * QoS support
+ */
+-#ifdef CONFIG_IWL4965_QOS
+-static int iwl4965_send_qos_params_command(struct iwl4965_priv *priv,
++static int iwl4965_send_qos_params_command(struct iwl_priv *priv,
+ struct iwl4965_qosparam_cmd *qos)
+ {
+
+- return iwl4965_send_cmd_pdu(priv, REPLY_QOS_PARAM,
++ return iwl_send_cmd_pdu(priv, REPLY_QOS_PARAM,
+ sizeof(struct iwl4965_qosparam_cmd), qos);
+ }
+
+-static void iwl4965_reset_qos(struct iwl4965_priv *priv)
+-{
+- u16 cw_min = 15;
+- u16 cw_max = 1023;
+- u8 aifs = 2;
+- u8 is_legacy = 0;
+- unsigned long flags;
+- int i;
+-
+- spin_lock_irqsave(&priv->lock, flags);
+- priv->qos_data.qos_active = 0;
+-
+- if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) {
+- if (priv->qos_data.qos_enable)
+- priv->qos_data.qos_active = 1;
+- if (!(priv->active_rate & 0xfff0)) {
+- cw_min = 31;
+- is_legacy = 1;
+- }
+- } else if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
+- if (priv->qos_data.qos_enable)
+- priv->qos_data.qos_active = 1;
+- } else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) {
+- cw_min = 31;
+- is_legacy = 1;
+- }
+-
+- if (priv->qos_data.qos_active)
+- aifs = 3;
+-
+- priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min);
+- priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max);
+- priv->qos_data.def_qos_parm.ac[0].aifsn = aifs;
+- priv->qos_data.def_qos_parm.ac[0].edca_txop = 0;
+- priv->qos_data.def_qos_parm.ac[0].reserved1 = 0;
+-
+- if (priv->qos_data.qos_active) {
+- i = 1;
+- priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min);
+- priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max);
+- priv->qos_data.def_qos_parm.ac[i].aifsn = 7;
+- priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
+- priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
+-
+- i = 2;
+- priv->qos_data.def_qos_parm.ac[i].cw_min =
+- cpu_to_le16((cw_min + 1) / 2 - 1);
+- priv->qos_data.def_qos_parm.ac[i].cw_max =
+- cpu_to_le16(cw_max);
+- priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
+- if (is_legacy)
+- priv->qos_data.def_qos_parm.ac[i].edca_txop =
+- cpu_to_le16(6016);
+- else
+- priv->qos_data.def_qos_parm.ac[i].edca_txop =
+- cpu_to_le16(3008);
+- priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
+-
+- i = 3;
+- priv->qos_data.def_qos_parm.ac[i].cw_min =
+- cpu_to_le16((cw_min + 1) / 4 - 1);
+- priv->qos_data.def_qos_parm.ac[i].cw_max =
+- cpu_to_le16((cw_max + 1) / 2 - 1);
+- priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
+- priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
+- if (is_legacy)
+- priv->qos_data.def_qos_parm.ac[i].edca_txop =
+- cpu_to_le16(3264);
+- else
+- priv->qos_data.def_qos_parm.ac[i].edca_txop =
+- cpu_to_le16(1504);
+- } else {
+- for (i = 1; i < 4; i++) {
+- priv->qos_data.def_qos_parm.ac[i].cw_min =
+- cpu_to_le16(cw_min);
+- priv->qos_data.def_qos_parm.ac[i].cw_max =
+- cpu_to_le16(cw_max);
+- priv->qos_data.def_qos_parm.ac[i].aifsn = aifs;
+- priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
+- priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
+- }
+- }
+- IWL_DEBUG_QOS("set QoS to default \n");
+-
+- spin_unlock_irqrestore(&priv->lock, flags);
+-}
+-
+-static void iwl4965_activate_qos(struct iwl4965_priv *priv, u8 force)
++static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force)
+ {
+ unsigned long flags;
+
+@@ -2142,7 +1366,7 @@ static void iwl4965_activate_qos(struct iwl4965_priv *priv, u8 force)
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+- if (force || iwl4965_is_associated(priv)) {
++ if (force || iwl_is_associated(priv)) {
+ IWL_DEBUG_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n",
+ priv->qos_data.qos_active,
+ priv->qos_data.def_qos_parm.qos_flags);
+@@ -2152,7 +1376,6 @@ static void iwl4965_activate_qos(struct iwl4965_priv *priv, u8 force)
+ }
+ }
+
+-#endif /* CONFIG_IWL4965_QOS */
+ /*
+ * Power management (not Tx power!) functions
+ */
+@@ -2193,7 +1416,7 @@ static struct iwl4965_power_vec_entry range_1[IWL_POWER_AC] = {
+ SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
+ };
+
+-int iwl4965_power_init_handle(struct iwl4965_priv *priv)
++int iwl4965_power_init_handle(struct iwl_priv *priv)
+ {
+ int rc = 0, i;
+ struct iwl4965_power_mgr *pow_data;
+@@ -2232,7 +1455,7 @@ int iwl4965_power_init_handle(struct iwl4965_priv *priv)
+ return rc;
+ }
+
+-static int iwl4965_update_power_cmd(struct iwl4965_priv *priv,
++static int iwl4965_update_power_cmd(struct iwl_priv *priv,
+ struct iwl4965_powertable_cmd *cmd, u32 mode)
+ {
+ int rc = 0, i;
+@@ -2296,7 +1519,7 @@ static int iwl4965_update_power_cmd(struct iwl4965_priv *priv,
+ return rc;
+ }
+
+-static int iwl4965_send_power_mode(struct iwl4965_priv *priv, u32 mode)
++static int iwl4965_send_power_mode(struct iwl_priv *priv, u32 mode)
+ {
+ u32 uninitialized_var(final_mode);
+ int rc;
+@@ -2321,7 +1544,7 @@ static int iwl4965_send_power_mode(struct iwl4965_priv *priv, u32 mode)
+
+ iwl4965_update_power_cmd(priv, &cmd, final_mode);
+
+- rc = iwl4965_send_cmd_pdu(priv, POWER_TABLE_CMD, sizeof(cmd), &cmd);
++ rc = iwl_send_cmd_pdu(priv, POWER_TABLE_CMD, sizeof(cmd), &cmd);
+
+ if (final_mode == IWL_POWER_MODE_CAM)
+ clear_bit(STATUS_POWER_PMI, &priv->status);
+@@ -2331,7 +1554,7 @@ static int iwl4965_send_power_mode(struct iwl4965_priv *priv, u32 mode)
+ return rc;
+ }
+
+-int iwl4965_is_network_packet(struct iwl4965_priv *priv, struct ieee80211_hdr *header)
++int iwl4965_is_network_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
+ {
+ /* Filter incoming packets to determine if they are targeted toward
+ * this network, discarding packets coming from ourselves */
+@@ -2354,6 +1577,8 @@ int iwl4965_is_network_packet(struct iwl4965_priv *priv, struct ieee80211_hdr *h
+ return !compare_ether_addr(header->addr2, priv->bssid);
+ /* packets to our adapter go through */
+ return !compare_ether_addr(header->addr1, priv->mac_addr);
++ default:
++ break;
+ }
+
+ return 1;
+@@ -2392,7 +1617,7 @@ static const char *iwl4965_get_tx_fail_reason(u32 status)
+ *
+ * NOTE: priv->mutex is not required before calling this function
+ */
+-static int iwl4965_scan_cancel(struct iwl4965_priv *priv)
++static int iwl4965_scan_cancel(struct iwl_priv *priv)
+ {
+ if (!test_bit(STATUS_SCAN_HW, &priv->status)) {
+ clear_bit(STATUS_SCANNING, &priv->status);
+@@ -2420,7 +1645,7 @@ static int iwl4965_scan_cancel(struct iwl4965_priv *priv)
+ *
+ * NOTE: priv->mutex must be held before calling this function
+ */
+-static int iwl4965_scan_cancel_timeout(struct iwl4965_priv *priv, unsigned long ms)
++static int iwl4965_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
+ {
+ unsigned long now = jiffies;
+ int ret;
+@@ -2439,7 +1664,7 @@ static int iwl4965_scan_cancel_timeout(struct iwl4965_priv *priv, unsigned long
+ return ret;
+ }
+
+-static void iwl4965_sequence_reset(struct iwl4965_priv *priv)
++static void iwl4965_sequence_reset(struct iwl_priv *priv)
+ {
+ /* Reset ieee stats */
+
+@@ -2469,7 +1694,7 @@ static __le16 iwl4965_adjust_beacon_interval(u16 beacon_val)
+ return cpu_to_le16(new_val);
+ }
+
+-static void iwl4965_setup_rxon_timing(struct iwl4965_priv *priv)
++static void iwl4965_setup_rxon_timing(struct iwl_priv *priv)
+ {
+ u64 interval_tm_unit;
+ u64 tsf, result;
+@@ -2480,13 +1705,13 @@ static void iwl4965_setup_rxon_timing(struct iwl4965_priv *priv)
+ conf = ieee80211_get_hw_conf(priv->hw);
+
+ spin_lock_irqsave(&priv->lock, flags);
+- priv->rxon_timing.timestamp.dw[1] = cpu_to_le32(priv->timestamp1);
+- priv->rxon_timing.timestamp.dw[0] = cpu_to_le32(priv->timestamp0);
++ priv->rxon_timing.timestamp.dw[1] = cpu_to_le32(priv->timestamp >> 32);
++ priv->rxon_timing.timestamp.dw[0] =
++ cpu_to_le32(priv->timestamp & 0xFFFFFFFF);
+
+ priv->rxon_timing.listen_interval = INTEL_CONN_LISTEN_INTERVAL;
+
+- tsf = priv->timestamp1;
+- tsf = ((tsf << 32) | priv->timestamp0);
++ tsf = priv->timestamp;
+
+ beacon_int = priv->beacon_int;
+ spin_unlock_irqrestore(&priv->lock, flags);
+@@ -2525,14 +1750,14 @@ static void iwl4965_setup_rxon_timing(struct iwl4965_priv *priv)
+ le16_to_cpu(priv->rxon_timing.atim_window));
+ }
+
+-static int iwl4965_scan_initiate(struct iwl4965_priv *priv)
++static int iwl4965_scan_initiate(struct iwl_priv *priv)
+ {
+ if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
+ IWL_ERROR("APs don't scan.\n");
+ return 0;
+ }
+
+- if (!iwl4965_is_ready_rf(priv)) {
++ if (!iwl_is_ready_rf(priv)) {
+ IWL_DEBUG_SCAN("Aborting scan due to not ready.\n");
+ return -EIO;
+ }
+@@ -2559,27 +1784,17 @@ static int iwl4965_scan_initiate(struct iwl4965_priv *priv)
+ return 0;
+ }
+
+-static int iwl4965_set_rxon_hwcrypto(struct iwl4965_priv *priv, int hw_decrypt)
+-{
+- struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon;
+
+- if (hw_decrypt)
+- rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK;
+- else
+- rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK;
+-
+- return 0;
+-}
+-
+-static void iwl4965_set_flags_for_phymode(struct iwl4965_priv *priv, u8 phymode)
++static void iwl4965_set_flags_for_phymode(struct iwl_priv *priv,
++ enum ieee80211_band band)
+ {
+- if (phymode == MODE_IEEE80211A) {
++ if (band == IEEE80211_BAND_5GHZ) {
+ priv->staging_rxon.flags &=
+ ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
+ | RXON_FLG_CCK_MSK);
+ priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
+ } else {
+- /* Copied from iwl4965_bg_post_associate() */
++ /* Copied from iwl4965_post_associate() */
+ if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
+ priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
+ else
+@@ -2597,9 +1812,9 @@ static void iwl4965_set_flags_for_phymode(struct iwl4965_priv *priv, u8 phymode)
+ /*
+ * initialize rxon structure with default values from eeprom
+ */
+-static void iwl4965_connection_init_rx_config(struct iwl4965_priv *priv)
++static void iwl4965_connection_init_rx_config(struct iwl_priv *priv)
+ {
+- const struct iwl4965_channel_info *ch_info;
++ const struct iwl_channel_info *ch_info;
+
+ memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
+
+@@ -2625,6 +1840,9 @@ static void iwl4965_connection_init_rx_config(struct iwl4965_priv *priv)
+ priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK |
+ RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
+ break;
++ default:
++ IWL_ERROR("Unsupported interface type %d\n", priv->iw_mode);
++ break;
+ }
+
+ #if 0
+@@ -2636,7 +1854,7 @@ static void iwl4965_connection_init_rx_config(struct iwl4965_priv *priv)
+ priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+ #endif
+
+- ch_info = iwl4965_get_channel_info(priv, priv->phymode,
++ ch_info = iwl_get_channel_info(priv, priv->band,
+ le16_to_cpu(priv->staging_rxon.channel));
+
+ if (!ch_info)
+@@ -2651,12 +1869,9 @@ static void iwl4965_connection_init_rx_config(struct iwl4965_priv *priv)
+ ch_info = &priv->channel_info[0];
+
+ priv->staging_rxon.channel = cpu_to_le16(ch_info->channel);
+- if (is_channel_a_band(ch_info))
+- priv->phymode = MODE_IEEE80211A;
+- else
+- priv->phymode = MODE_IEEE80211G;
++ priv->band = ch_info->band;
+
+- iwl4965_set_flags_for_phymode(priv, priv->phymode);
++ iwl4965_set_flags_for_phymode(priv, priv->band);
+
+ priv->staging_rxon.ofdm_basic_rates =
+ (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
+@@ -2672,13 +1887,13 @@ static void iwl4965_connection_init_rx_config(struct iwl4965_priv *priv)
+ iwl4965_set_rxon_chain(priv);
+ }
+
+-static int iwl4965_set_mode(struct iwl4965_priv *priv, int mode)
++static int iwl4965_set_mode(struct iwl_priv *priv, int mode)
+ {
+ if (mode == IEEE80211_IF_TYPE_IBSS) {
+- const struct iwl4965_channel_info *ch_info;
++ const struct iwl_channel_info *ch_info;
+
+- ch_info = iwl4965_get_channel_info(priv,
+- priv->phymode,
++ ch_info = iwl_get_channel_info(priv,
++ priv->band,
+ le16_to_cpu(priv->staging_rxon.channel));
+
+ if (!ch_info || !is_channel_ibss(ch_info)) {
+@@ -2693,10 +1908,10 @@ static int iwl4965_set_mode(struct iwl4965_priv *priv, int mode)
+ iwl4965_connection_init_rx_config(priv);
+ memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
+
+- iwl4965_clear_stations_table(priv);
++ iwlcore_clear_stations_table(priv);
+
+ /* dont commit rxon if rf-kill is on*/
+- if (!iwl4965_is_ready_rf(priv))
++ if (!iwl_is_ready_rf(priv))
+ return -EAGAIN;
+
+ cancel_delayed_work(&priv->scan_check);
+@@ -2711,44 +1926,58 @@ static int iwl4965_set_mode(struct iwl4965_priv *priv, int mode)
+ return 0;
+ }
+
+-static void iwl4965_build_tx_cmd_hwcrypto(struct iwl4965_priv *priv,
++static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
+ struct ieee80211_tx_control *ctl,
+- struct iwl4965_cmd *cmd,
++ struct iwl_cmd *cmd,
+ struct sk_buff *skb_frag,
+- int last_frag)
++ int sta_id)
+ {
+- struct iwl4965_hw_key *keyinfo = &priv->stations[ctl->key_idx].keyinfo;
++ struct iwl4965_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
++ struct iwl_wep_key *wepkey;
++ int keyidx = 0;
++
++ BUG_ON(ctl->key_idx > 3);
+
+ switch (keyinfo->alg) {
+ case ALG_CCMP:
+ cmd->cmd.tx.sec_ctl = TX_CMD_SEC_CCM;
+ memcpy(cmd->cmd.tx.key, keyinfo->key, keyinfo->keylen);
++ if (ctl->flags & IEEE80211_TXCTL_AMPDU)
++ cmd->cmd.tx.tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK;
+ IWL_DEBUG_TX("tx_cmd with aes hwcrypto\n");
+ break;
+
+ case ALG_TKIP:
+-#if 0
+ cmd->cmd.tx.sec_ctl = TX_CMD_SEC_TKIP;
+-
+- if (last_frag)
+- memcpy(cmd->cmd.tx.tkip_mic.byte, skb_frag->tail - 8,
+- 8);
+- else
+- memset(cmd->cmd.tx.tkip_mic.byte, 0, 8);
+-#endif
++ ieee80211_get_tkip_key(keyinfo->conf, skb_frag,
++ IEEE80211_TKIP_P2_KEY, cmd->cmd.tx.key);
++ IWL_DEBUG_TX("tx_cmd with tkip hwcrypto\n");
+ break;
+
+ case ALG_WEP:
+- cmd->cmd.tx.sec_ctl = TX_CMD_SEC_WEP |
+- (ctl->key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT;
+-
+- if (keyinfo->keylen == 13)
+- cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
++ wepkey = &priv->wep_keys[ctl->key_idx];
++ cmd->cmd.tx.sec_ctl = 0;
++ if (priv->default_wep_key) {
++ /* the WEP key was sent as static */
++ keyidx = ctl->key_idx;
++ memcpy(&cmd->cmd.tx.key[3], wepkey->key,
++ wepkey->key_size);
++ if (wepkey->key_size == WEP_KEY_LEN_128)
++ cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
++ } else {
++ /* the WEP key was sent as dynamic */
++ keyidx = keyinfo->keyidx;
++ memcpy(&cmd->cmd.tx.key[3], keyinfo->key,
++ keyinfo->keylen);
++ if (keyinfo->keylen == WEP_KEY_LEN_128)
++ cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
++ }
+
+- memcpy(&cmd->cmd.tx.key[3], keyinfo->key, keyinfo->keylen);
++ cmd->cmd.tx.sec_ctl |= (TX_CMD_SEC_WEP |
++ (keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT);
+
+ IWL_DEBUG_TX("Configuring packet for WEP encryption "
+- "with key %d\n", ctl->key_idx);
++ "with key %d\n", keyidx);
+ break;
+
+ default:
+@@ -2760,8 +1989,8 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl4965_priv *priv,
+ /*
+ * handle build REPLY_TX command notification.
+ */
+-static void iwl4965_build_tx_cmd_basic(struct iwl4965_priv *priv,
+- struct iwl4965_cmd *cmd,
++static void iwl4965_build_tx_cmd_basic(struct iwl_priv *priv,
++ struct iwl_cmd *cmd,
+ struct ieee80211_tx_control *ctrl,
+ struct ieee80211_hdr *hdr,
+ int is_unicast, u8 std_id)
+@@ -2816,20 +2045,27 @@ static void iwl4965_build_tx_cmd_basic(struct iwl4965_priv *priv,
+ cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(3);
+ else
+ cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(2);
+- } else
++ } else {
+ cmd->cmd.tx.timeout.pm_frame_timeout = 0;
++ }
+
+ cmd->cmd.tx.driver_txop = 0;
+ cmd->cmd.tx.tx_flags = tx_flags;
+ cmd->cmd.tx.next_frame_len = 0;
+ }
+-
++static void iwl_update_tx_stats(struct iwl_priv *priv, u16 fc, u16 len)
++{
++ /* 0 - mgmt, 1 - cnt, 2 - data */
++ int idx = (fc & IEEE80211_FCTL_FTYPE) >> 2;
++ priv->tx_stats[idx].cnt++;
++ priv->tx_stats[idx].bytes += len;
++}
+ /**
+ * iwl4965_get_sta_id - Find station's index within station table
+ *
+ * If new IBSS station, create new entry in station table
+ */
+-static int iwl4965_get_sta_id(struct iwl4965_priv *priv,
++static int iwl4965_get_sta_id(struct iwl_priv *priv,
+ struct ieee80211_hdr *hdr)
+ {
+ int sta_id;
+@@ -2839,7 +2075,7 @@ static int iwl4965_get_sta_id(struct iwl4965_priv *priv,
+ /* If this frame is broadcast or management, use broadcast station id */
+ if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) ||
+ is_multicast_ether_addr(hdr->addr1))
+- return priv->hw_setting.bcast_sta_id;
++ return priv->hw_params.bcast_sta_id;
+
+ switch (priv->iw_mode) {
+
+@@ -2853,7 +2089,7 @@ static int iwl4965_get_sta_id(struct iwl4965_priv *priv,
+ sta_id = iwl4965_hw_find_station(priv, hdr->addr1);
+ if (sta_id != IWL_INVALID_STATION)
+ return sta_id;
+- return priv->hw_setting.bcast_sta_id;
++ return priv->hw_params.bcast_sta_id;
+
+ /* If this frame is going out to an IBSS network, find the station,
+ * or create a new station table entry */
+@@ -2872,19 +2108,19 @@ static int iwl4965_get_sta_id(struct iwl4965_priv *priv,
+ IWL_DEBUG_DROP("Station %s not in station map. "
+ "Defaulting to broadcast...\n",
+ print_mac(mac, hdr->addr1));
+- iwl4965_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
+- return priv->hw_setting.bcast_sta_id;
++ iwl_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
++ return priv->hw_params.bcast_sta_id;
+
+ default:
+ IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode);
+- return priv->hw_setting.bcast_sta_id;
++ return priv->hw_params.bcast_sta_id;
+ }
+ }
+
+ /*
+ * start REPLY_TX command process
+ */
+-static int iwl4965_tx_skb(struct iwl4965_priv *priv,
++static int iwl4965_tx_skb(struct iwl_priv *priv,
+ struct sk_buff *skb, struct ieee80211_tx_control *ctl)
+ {
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+@@ -2896,7 +2132,7 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv,
+ dma_addr_t phys_addr;
+ dma_addr_t txcmd_phys;
+ dma_addr_t scratch_phys;
+- struct iwl4965_cmd *out_cmd = NULL;
++ struct iwl_cmd *out_cmd = NULL;
+ u16 len, idx, len_org;
+ u8 id, hdr_len, unicast;
+ u8 sta_id;
+@@ -2908,7 +2144,7 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv,
+ int rc;
+
+ spin_lock_irqsave(&priv->lock, flags);
+- if (iwl4965_is_rfkill(priv)) {
++ if (iwl_is_rfkill(priv)) {
+ IWL_DEBUG_DROP("Dropping - RF KILL\n");
+ goto drop_unlock;
+ }
+@@ -2918,7 +2154,7 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv,
+ goto drop_unlock;
+ }
+
+- if ((ctl->tx_rate & 0xFF) == IWL_INVALID_RATE) {
++ if ((ctl->tx_rate->hw_value & 0xFF) == IWL_INVALID_RATE) {
+ IWL_ERROR("ERROR: No TX rate available.\n");
+ goto drop_unlock;
+ }
+@@ -2928,7 +2164,7 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv,
+
+ fc = le16_to_cpu(hdr->frame_control);
+
+-#ifdef CONFIG_IWL4965_DEBUG
++#ifdef CONFIG_IWLWIFI_DEBUG
+ if (ieee80211_is_auth(fc))
+ IWL_DEBUG_TX("Sending AUTH frame\n");
+ else if (ieee80211_is_assoc_request(fc))
+@@ -2939,10 +2175,10 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv,
+
+ /* drop all data frame if we are not associated */
+ if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
+- (!iwl4965_is_associated(priv) ||
++ (!iwl_is_associated(priv) ||
+ ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id) ||
+ !priv->assoc_station_added)) {
+- IWL_DEBUG_DROP("Dropping - !iwl4965_is_associated\n");
++ IWL_DEBUG_DROP("Dropping - !iwl_is_associated\n");
+ goto drop_unlock;
+ }
+
+@@ -2972,11 +2208,10 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv,
+ __constant_cpu_to_le16(IEEE80211_SCTL_FRAG));
+ seq_number += 0x10;
+ #ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
+ /* aggregation is on for this <sta,tid> */
+- if (ctl->flags & IEEE80211_TXCTL_HT_MPDU_AGG)
++ if (ctl->flags & IEEE80211_TXCTL_AMPDU)
+ txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
+-#endif /* CONFIG_IWL4965_HT_AGG */
++ priv->stations[sta_id].tid[tid].tfds_in_queue++;
+ #endif /* CONFIG_IWL4965_HT */
+ }
+
+@@ -3025,8 +2260,8 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv,
+ * of the MAC header (device reads on dword boundaries).
+ * We'll tell device about this padding later.
+ */
+- len = priv->hw_setting.tx_cmd_len +
+- sizeof(struct iwl4965_cmd_header) + hdr_len;
++ len = priv->hw_params.tx_cmd_len +
++ sizeof(struct iwl_cmd_header) + hdr_len;
+
+ len_org = len;
+ len = (len + 3) & ~3;
+@@ -3038,15 +2273,15 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv,
+
+ /* Physical address of this Tx command's header (not MAC header!),
+ * within command buffer array. */
+- txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl4965_cmd) * idx +
+- offsetof(struct iwl4965_cmd, hdr);
++ txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl_cmd) * idx +
++ offsetof(struct iwl_cmd, hdr);
+
+ /* Add buffer containing Tx command and MAC(!) header to TFD's
+ * first entry */
+ iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len);
+
+ if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
+- iwl4965_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, 0);
++ iwl4965_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, sta_id);
+
+ /* Set up TFD's 2nd entry to point directly to remainder of skb,
+ * if any (802.11 null frames have no payload). */
+@@ -3071,19 +2306,13 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv,
+ /* set is_hcca to 0; it probably will never be implemented */
+ iwl4965_hw_build_tx_cmd_rate(priv, out_cmd, ctl, hdr, sta_id, 0);
+
+- scratch_phys = txcmd_phys + sizeof(struct iwl4965_cmd_header) +
++ iwl_update_tx_stats(priv, fc, len);
++
++ scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
+ offsetof(struct iwl4965_tx_cmd, scratch);
+ out_cmd->cmd.tx.dram_lsb_ptr = cpu_to_le32(scratch_phys);
+ out_cmd->cmd.tx.dram_msb_ptr = iwl_get_dma_hi_address(scratch_phys);
+
+-#ifdef CONFIG_IWL4965_HT_AGG
+-#ifdef CONFIG_IWL4965_HT
+- /* TODO: move this functionality to rate scaling */
+- iwl4965_tl_get_stats(priv, hdr);
+-#endif /* CONFIG_IWL4965_HT_AGG */
+-#endif /*CONFIG_IWL4965_HT */
+-
+-
+ if (!ieee80211_get_morefrag(hdr)) {
+ txq->need_update = 1;
+ if (qc) {
+@@ -3095,17 +2324,17 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv,
+ txq->need_update = 0;
+ }
+
+- iwl4965_print_hex_dump(IWL_DL_TX, out_cmd->cmd.payload,
++ iwl_print_hex_dump(IWL_DL_TX, out_cmd->cmd.payload,
+ sizeof(out_cmd->cmd.tx));
+
+- iwl4965_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr,
++ iwl_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr,
+ ieee80211_get_hdrlen(fc));
+
+ /* Set up entry for this TFD in Tx byte-count array */
+- iwl4965_tx_queue_update_wr_ptr(priv, txq, len);
++ priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, len);
+
+ /* Tell device the write index *just past* this latest filled TFD */
+- q->write_ptr = iwl4965_queue_inc_wrap(q->write_ptr, q->n_bd);
++ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
+ rc = iwl4965_tx_queue_update_write_ptr(priv, txq);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+@@ -3132,13 +2361,13 @@ drop:
+ return -1;
+ }
+
+-static void iwl4965_set_rate(struct iwl4965_priv *priv)
++static void iwl4965_set_rate(struct iwl_priv *priv)
+ {
+- const struct ieee80211_hw_mode *hw = NULL;
++ const struct ieee80211_supported_band *hw = NULL;
+ struct ieee80211_rate *rate;
+ int i;
+
+- hw = iwl4965_get_hw_mode(priv, priv->phymode);
++ hw = iwl4965_get_hw_mode(priv, priv->band);
+ if (!hw) {
+ IWL_ERROR("Failed to set rate: unable to get hw mode\n");
+ return;
+@@ -3147,24 +2376,10 @@ static void iwl4965_set_rate(struct iwl4965_priv *priv)
+ priv->active_rate = 0;
+ priv->active_rate_basic = 0;
+
+- IWL_DEBUG_RATE("Setting rates for 802.11%c\n",
+- hw->mode == MODE_IEEE80211A ?
+- 'a' : ((hw->mode == MODE_IEEE80211B) ? 'b' : 'g'));
+-
+- for (i = 0; i < hw->num_rates; i++) {
+- rate = &(hw->rates[i]);
+- if ((rate->val < IWL_RATE_COUNT) &&
+- (rate->flags & IEEE80211_RATE_SUPPORTED)) {
+- IWL_DEBUG_RATE("Adding rate index %d (plcp %d)%s\n",
+- rate->val, iwl4965_rates[rate->val].plcp,
+- (rate->flags & IEEE80211_RATE_BASIC) ?
+- "*" : "");
+- priv->active_rate |= (1 << rate->val);
+- if (rate->flags & IEEE80211_RATE_BASIC)
+- priv->active_rate_basic |= (1 << rate->val);
+- } else
+- IWL_DEBUG_RATE("Not adding rate %d (plcp %d)\n",
+- rate->val, iwl4965_rates[rate->val].plcp);
++ for (i = 0; i < hw->n_bitrates; i++) {
++ rate = &(hw->bitrates[i]);
++ if (rate->hw_value < IWL_RATE_COUNT)
++ priv->active_rate |= (1 << rate->hw_value);
+ }
+
+ IWL_DEBUG_RATE("Set active_rate = %0x, active_rate_basic = %0x\n",
+@@ -3193,7 +2408,7 @@ static void iwl4965_set_rate(struct iwl4965_priv *priv)
+ (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
+ }
+
+-static void iwl4965_radio_kill_sw(struct iwl4965_priv *priv, int disable_radio)
++void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio)
+ {
+ unsigned long flags;
+
+@@ -3208,17 +2423,26 @@ static void iwl4965_radio_kill_sw(struct iwl4965_priv *priv, int disable_radio)
+ /* FIXME: This is a workaround for AP */
+ if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
+ spin_lock_irqsave(&priv->lock, flags);
+- iwl4965_write32(priv, CSR_UCODE_DRV_GP1_SET,
++ iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+ CSR_UCODE_SW_BIT_RFKILL);
+ spin_unlock_irqrestore(&priv->lock, flags);
+- iwl4965_send_card_state(priv, CARD_STATE_CMD_DISABLE, 0);
++ /* call the host command only if no hw rf-kill set */
++ if (!test_bit(STATUS_RF_KILL_HW, &priv->status) &&
++ iwl_is_ready(priv))
++ iwl4965_send_card_state(priv,
++ CARD_STATE_CMD_DISABLE,
++ 0);
+ set_bit(STATUS_RF_KILL_SW, &priv->status);
++
++ /* make sure mac80211 stop sending Tx frame */
++ if (priv->mac80211_registered)
++ ieee80211_stop_queues(priv->hw);
+ }
+ return;
+ }
+
+ spin_lock_irqsave(&priv->lock, flags);
+- iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
++ iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+
+ clear_bit(STATUS_RF_KILL_SW, &priv->status);
+ spin_unlock_irqrestore(&priv->lock, flags);
+@@ -3227,9 +2451,9 @@ static void iwl4965_radio_kill_sw(struct iwl4965_priv *priv, int disable_radio)
+ msleep(10);
+
+ spin_lock_irqsave(&priv->lock, flags);
+- iwl4965_read32(priv, CSR_UCODE_DRV_GP1);
+- if (!iwl4965_grab_nic_access(priv))
+- iwl4965_release_nic_access(priv);
++ iwl_read32(priv, CSR_UCODE_DRV_GP1);
++ if (!iwl_grab_nic_access(priv))
++ iwl_release_nic_access(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
+@@ -3242,7 +2466,7 @@ static void iwl4965_radio_kill_sw(struct iwl4965_priv *priv, int disable_radio)
+ return;
+ }
+
+-void iwl4965_set_decrypted_flag(struct iwl4965_priv *priv, struct sk_buff *skb,
++void iwl4965_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb,
+ u32 decrypt_res, struct ieee80211_rx_status *stats)
+ {
+ u16 fc =
+@@ -3257,6 +2481,12 @@ void iwl4965_set_decrypted_flag(struct iwl4965_priv *priv, struct sk_buff *skb,
+ IWL_DEBUG_RX("decrypt_res:0x%x\n", decrypt_res);
+ switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) {
+ case RX_RES_STATUS_SEC_TYPE_TKIP:
++ /* The uCode has got a bad phase 1 Key, pushes the packet.
++ * Decryption will be done in SW. */
++ if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
++ RX_RES_STATUS_BAD_KEY_TTAK)
++ break;
++
+ if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
+ RX_RES_STATUS_BAD_ICV_MIC)
+ stats->flag |= RX_FLAG_MMIC_ERROR;
+@@ -3277,7 +2507,7 @@ void iwl4965_set_decrypted_flag(struct iwl4965_priv *priv, struct sk_buff *skb,
+
+ #define IWL_PACKET_RETRY_TIME HZ
+
+-int iwl4965_is_duplicate_packet(struct iwl4965_priv *priv, struct ieee80211_hdr *header)
++int iwl4965_is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
+ {
+ u16 sc = le16_to_cpu(header->seq_ctrl);
+ u16 seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
+@@ -3394,13 +2624,13 @@ static __le32 iwl4965_add_beacon_time(u32 base, u32 addon, u32 beacon_interval)
+ return cpu_to_le32(res);
+ }
+
+-static int iwl4965_get_measurement(struct iwl4965_priv *priv,
++static int iwl4965_get_measurement(struct iwl_priv *priv,
+ struct ieee80211_measurement_params *params,
+ u8 type)
+ {
+ struct iwl4965_spectrum_cmd spectrum;
+ struct iwl4965_rx_packet *res;
+- struct iwl4965_host_cmd cmd = {
++ struct iwl_host_cmd cmd = {
+ .id = REPLY_SPECTRUM_MEASUREMENT_CMD,
+ .data = (void *)&spectrum,
+ .meta.flags = CMD_WANT_SKB,
+@@ -3410,7 +2640,7 @@ static int iwl4965_get_measurement(struct iwl4965_priv *priv,
+ int spectrum_resp_status;
+ int duration = le16_to_cpu(params->duration);
+
+- if (iwl4965_is_associated(priv))
++ if (iwl_is_associated(priv))
+ add_time =
+ iwl4965_usecs_to_beacons(
+ le64_to_cpu(params->start_time) - priv->last_tsf,
+@@ -3425,7 +2655,7 @@ static int iwl4965_get_measurement(struct iwl4965_priv *priv,
+ cmd.len = sizeof(spectrum);
+ spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len));
+
+- if (iwl4965_is_associated(priv))
++ if (iwl_is_associated(priv))
+ spectrum.start_time =
+ iwl4965_add_beacon_time(priv->last_beacon_time,
+ add_time,
+@@ -3440,7 +2670,7 @@ static int iwl4965_get_measurement(struct iwl4965_priv *priv,
+ spectrum.flags |= RXON_FLG_BAND_24G_MSK |
+ RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK;
+
+- rc = iwl4965_send_cmd_sync(priv, &cmd);
++ rc = iwl_send_cmd_sync(priv, &cmd);
+ if (rc)
+ return rc;
+
+@@ -3474,7 +2704,7 @@ static int iwl4965_get_measurement(struct iwl4965_priv *priv,
+ }
+ #endif
+
+-static void iwl4965_txstatus_to_ieee(struct iwl4965_priv *priv,
++static void iwl4965_txstatus_to_ieee(struct iwl_priv *priv,
+ struct iwl4965_tx_info *tx_sta)
+ {
+
+@@ -3500,7 +2730,7 @@ static void iwl4965_txstatus_to_ieee(struct iwl4965_priv *priv,
+ * need to be reclaimed. As result, some free space forms. If there is
+ * enough free space (> low mark), wake the stack that feeds us.
+ */
+-int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index)
++int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
+ {
+ struct iwl4965_tx_queue *txq = &priv->txq[txq_id];
+ struct iwl4965_queue *q = &txq->q;
+@@ -3513,9 +2743,9 @@ int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index)
+ return 0;
+ }
+
+- for (index = iwl4965_queue_inc_wrap(index, q->n_bd);
++ for (index = iwl_queue_inc_wrap(index, q->n_bd);
+ q->read_ptr != index;
+- q->read_ptr = iwl4965_queue_inc_wrap(q->read_ptr, q->n_bd)) {
++ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+ if (txq_id != IWL_CMD_QUEUE_NUM) {
+ iwl4965_txstatus_to_ieee(priv,
+ &(txq->txb[txq->q.read_ptr]));
+@@ -3528,10 +2758,10 @@ int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index)
+ nfreed++;
+ }
+
+- if (iwl4965_queue_space(q) > q->low_mark && (txq_id >= 0) &&
++/* if (iwl4965_queue_space(q) > q->low_mark && (txq_id >= 0) &&
+ (txq_id != IWL_CMD_QUEUE_NUM) &&
+ priv->mac80211_registered)
+- ieee80211_wake_queue(priv->hw, txq_id);
++ ieee80211_wake_queue(priv->hw, txq_id); */
+
+
+ return nfreed;
+@@ -3550,9 +2780,8 @@ static int iwl4965_is_tx_success(u32 status)
+ *
+ ******************************************************************************/
+ #ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
+
+-static inline int iwl4965_get_ra_sta_id(struct iwl4965_priv *priv,
++static inline int iwl4965_get_ra_sta_id(struct iwl_priv *priv,
+ struct ieee80211_hdr *hdr)
+ {
+ if (priv->iw_mode == IEEE80211_IF_TYPE_STA)
+@@ -3564,7 +2793,7 @@ static inline int iwl4965_get_ra_sta_id(struct iwl4965_priv *priv,
+ }
+
+ static struct ieee80211_hdr *iwl4965_tx_queue_get_hdr(
+- struct iwl4965_priv *priv, int txq_id, int idx)
++ struct iwl_priv *priv, int txq_id, int idx)
+ {
+ if (priv->txq[txq_id].txb[idx].skb[0])
+ return (struct ieee80211_hdr *)priv->txq[txq_id].
+@@ -3583,13 +2812,13 @@ static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp)
+ /**
+ * iwl4965_tx_status_reply_tx - Handle Tx rspnse for frames in aggregation queue
+ */
+-static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv,
++static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
+ struct iwl4965_ht_agg *agg,
+- struct iwl4965_tx_resp *tx_resp,
++ struct iwl4965_tx_resp_agg *tx_resp,
+ u16 start_idx)
+ {
+- u32 status;
+- __le32 *frame_status = &tx_resp->status;
++ u16 status;
++ struct agg_tx_status *frame_status = &tx_resp->status;
+ struct ieee80211_tx_status *tx_status = NULL;
+ struct ieee80211_hdr *hdr = NULL;
+ int i, sh;
+@@ -3602,30 +2831,30 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv,
+ agg->frame_count = tx_resp->frame_count;
+ agg->start_idx = start_idx;
+ agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
+- agg->bitmap0 = agg->bitmap1 = 0;
++ agg->bitmap = 0;
+
+ /* # frames attempted by Tx command */
+ if (agg->frame_count == 1) {
+ /* Only one frame was attempted; no block-ack will arrive */
+- struct iwl4965_tx_queue *txq ;
+- status = le32_to_cpu(frame_status[0]);
++ status = le16_to_cpu(frame_status[0].status);
++ seq = le16_to_cpu(frame_status[0].sequence);
++ idx = SEQ_TO_INDEX(seq);
++ txq_id = SEQ_TO_QUEUE(seq);
+
+- txq_id = agg->txq_id;
+- txq = &priv->txq[txq_id];
+ /* FIXME: code repetition */
+- IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d \n",
+- agg->frame_count, agg->start_idx);
++ IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d idx=%d\n",
++ agg->frame_count, agg->start_idx, idx);
+
+- tx_status = &(priv->txq[txq_id].txb[txq->q.read_ptr].status);
++ tx_status = &(priv->txq[txq_id].txb[idx].status);
+ tx_status->retry_count = tx_resp->failure_frame;
+ tx_status->queue_number = status & 0xff;
+- tx_status->queue_length = tx_resp->bt_kill_count;
+- tx_status->queue_length |= tx_resp->failure_rts;
+-
++ tx_status->queue_length = tx_resp->failure_rts;
++ tx_status->control.flags &= ~IEEE80211_TXCTL_AMPDU;
+ tx_status->flags = iwl4965_is_tx_success(status)?
+ IEEE80211_TX_STATUS_ACK : 0;
+- tx_status->control.tx_rate =
+- iwl4965_hw_get_rate_n_flags(tx_resp->rate_n_flags);
++ iwl4965_hwrate_to_tx_control(priv,
++ le32_to_cpu(tx_resp->rate_n_flags),
++ &tx_status->control);
+ /* FIXME: code repetition end */
+
+ IWL_DEBUG_TX_REPLY("1 Frame 0x%x failure :%d\n",
+@@ -3642,8 +2871,8 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv,
+ /* Construct bit-map of pending frames within Tx window */
+ for (i = 0; i < agg->frame_count; i++) {
+ u16 sc;
+- status = le32_to_cpu(frame_status[i]);
+- seq = status >> 16;
++ status = le16_to_cpu(frame_status[i].status);
++ seq = le16_to_cpu(frame_status[i].sequence);
+ idx = SEQ_TO_INDEX(seq);
+ txq_id = SEQ_TO_QUEUE(seq);
+
+@@ -3687,13 +2916,12 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv,
+ start, (u32)(bitmap & 0xFFFFFFFF));
+ }
+
+- agg->bitmap0 = bitmap & 0xFFFFFFFF;
+- agg->bitmap1 = bitmap >> 32;
++ agg->bitmap = bitmap;
+ agg->start_idx = start;
+ agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
+- IWL_DEBUG_TX_REPLY("Frames %d start_idx=%d bitmap=0x%x\n",
++ IWL_DEBUG_TX_REPLY("Frames %d start_idx=%d bitmap=0x%llx\n",
+ agg->frame_count, agg->start_idx,
+- agg->bitmap0);
++ (unsigned long long)agg->bitmap);
+
+ if (bitmap)
+ agg->wait_for_ba = 1;
+@@ -3701,12 +2929,11 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv,
+ return 0;
+ }
+ #endif
+-#endif
+
+ /**
+ * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response
+ */
+-static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv,
++static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
+ {
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+@@ -3718,9 +2945,9 @@ static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv,
+ struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
+ u32 status = le32_to_cpu(tx_resp->status);
+ #ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
+- int tid, sta_id;
+-#endif
++ int tid = MAX_TID_COUNT, sta_id = IWL_INVALID_STATION;
++ struct ieee80211_hdr *hdr;
++ __le16 *qc;
+ #endif
+
+ if ((index >= txq->q.n_bd) || (x2_queue_used(&txq->q, index) == 0)) {
+@@ -3732,44 +2959,51 @@ static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv,
+ }
+
+ #ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
++ hdr = iwl4965_tx_queue_get_hdr(priv, txq_id, index);
++ qc = ieee80211_get_qos_ctrl(hdr);
++
++ if (qc)
++ tid = le16_to_cpu(*qc) & 0xf;
++
++ sta_id = iwl4965_get_ra_sta_id(priv, hdr);
++ if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) {
++ IWL_ERROR("Station not known\n");
++ return;
++ }
++
+ if (txq->sched_retry) {
+ const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
+- struct ieee80211_hdr *hdr =
+- iwl4965_tx_queue_get_hdr(priv, txq_id, index);
+ struct iwl4965_ht_agg *agg = NULL;
+- __le16 *qc = ieee80211_get_qos_ctrl(hdr);
+
+- if (qc == NULL) {
+- IWL_ERROR("BUG_ON qc is null!!!!\n");
++ if (!qc)
+ return;
+- }
+-
+- tid = le16_to_cpu(*qc) & 0xf;
+-
+- sta_id = iwl4965_get_ra_sta_id(priv, hdr);
+- if (unlikely(sta_id == IWL_INVALID_STATION)) {
+- IWL_ERROR("Station not known for\n");
+- return;
+- }
+
+ agg = &priv->stations[sta_id].tid[tid].agg;
+
+- iwl4965_tx_status_reply_tx(priv, agg, tx_resp, index);
++ iwl4965_tx_status_reply_tx(priv, agg,
++ (struct iwl4965_tx_resp_agg *)tx_resp, index);
+
+ if ((tx_resp->frame_count == 1) &&
+ !iwl4965_is_tx_success(status)) {
+ /* TODO: send BAR */
+ }
+
+- if ((txq->q.read_ptr != (scd_ssn & 0xff))) {
+- index = iwl4965_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
++ if (txq->q.read_ptr != (scd_ssn & 0xff)) {
++ int freed;
++ index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
+ IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn "
+ "%d index %d\n", scd_ssn , index);
+- iwl4965_tx_queue_reclaim(priv, txq_id, index);
++ freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
++ priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
++
++ if (iwl4965_queue_space(&txq->q) > txq->q.low_mark &&
++ txq_id >= 0 && priv->mac80211_registered &&
++ agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)
++ ieee80211_wake_queue(priv->hw, txq_id);
++
++ iwl4965_check_empty_hw_queue(priv, sta_id, tid, txq_id);
+ }
+ } else {
+-#endif /* CONFIG_IWL4965_HT_AGG */
+ #endif /* CONFIG_IWL4965_HT */
+ tx_status = &(txq->txb[txq->q.read_ptr].status);
+
+@@ -3777,12 +3011,10 @@ static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv,
+ tx_status->queue_number = status;
+ tx_status->queue_length = tx_resp->bt_kill_count;
+ tx_status->queue_length |= tx_resp->failure_rts;
+-
+ tx_status->flags =
+ iwl4965_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
+-
+- tx_status->control.tx_rate =
+- iwl4965_hw_get_rate_n_flags(tx_resp->rate_n_flags);
++ iwl4965_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags),
++ &tx_status->control);
+
+ IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags 0x%x "
+ "retries %d\n", txq_id, iwl4965_get_tx_fail_reason(status),
+@@ -3790,12 +3022,21 @@ static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv,
+ tx_resp->failure_frame);
+
+ IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
+- if (index != -1)
+- iwl4965_tx_queue_reclaim(priv, txq_id, index);
++ if (index != -1) {
++ int freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
++#ifdef CONFIG_IWL4965_HT
++ if (tid != MAX_TID_COUNT)
++ priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
++ if (iwl4965_queue_space(&txq->q) > txq->q.low_mark &&
++ (txq_id >= 0) &&
++ priv->mac80211_registered)
++ ieee80211_wake_queue(priv->hw, txq_id);
++ if (tid != MAX_TID_COUNT)
++ iwl4965_check_empty_hw_queue(priv, sta_id, tid, txq_id);
++#endif
++ }
+ #ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
+ }
+-#endif /* CONFIG_IWL4965_HT_AGG */
+ #endif /* CONFIG_IWL4965_HT */
+
+ if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
+@@ -3803,7 +3044,7 @@ static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv,
+ }
+
+
+-static void iwl4965_rx_reply_alive(struct iwl4965_priv *priv,
++static void iwl4965_rx_reply_alive(struct iwl_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
+ {
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+@@ -3839,7 +3080,7 @@ static void iwl4965_rx_reply_alive(struct iwl4965_priv *priv,
+ IWL_WARNING("uCode did not respond OK.\n");
+ }
+
+-static void iwl4965_rx_reply_add_sta(struct iwl4965_priv *priv,
++static void iwl4965_rx_reply_add_sta(struct iwl_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
+ {
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+@@ -3848,7 +3089,7 @@ static void iwl4965_rx_reply_add_sta(struct iwl4965_priv *priv,
+ return;
+ }
+
+-static void iwl4965_rx_reply_error(struct iwl4965_priv *priv,
++static void iwl4965_rx_reply_error(struct iwl_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
+ {
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+@@ -3864,7 +3105,7 @@ static void iwl4965_rx_reply_error(struct iwl4965_priv *priv,
+
+ #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
+
+-static void iwl4965_rx_csa(struct iwl4965_priv *priv, struct iwl4965_rx_mem_buffer *rxb)
++static void iwl4965_rx_csa(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb)
+ {
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl4965_rxon_cmd *rxon = (void *)&priv->active_rxon;
+@@ -3875,7 +3116,7 @@ static void iwl4965_rx_csa(struct iwl4965_priv *priv, struct iwl4965_rx_mem_buff
+ priv->staging_rxon.channel = csa->channel;
+ }
+
+-static void iwl4965_rx_spectrum_measure_notif(struct iwl4965_priv *priv,
++static void iwl4965_rx_spectrum_measure_notif(struct iwl_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
+ {
+ #ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
+@@ -3893,10 +3134,10 @@ static void iwl4965_rx_spectrum_measure_notif(struct iwl4965_priv *priv,
+ #endif
+ }
+
+-static void iwl4965_rx_pm_sleep_notif(struct iwl4965_priv *priv,
++static void iwl4965_rx_pm_sleep_notif(struct iwl_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
+ {
+-#ifdef CONFIG_IWL4965_DEBUG
++#ifdef CONFIG_IWLWIFI_DEBUG
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl4965_sleep_notification *sleep = &(pkt->u.sleep_notif);
+ IWL_DEBUG_RX("sleep mode: %d, src: %d\n",
+@@ -3904,20 +3145,20 @@ static void iwl4965_rx_pm_sleep_notif(struct iwl4965_priv *priv,
+ #endif
+ }
+
+-static void iwl4965_rx_pm_debug_statistics_notif(struct iwl4965_priv *priv,
++static void iwl4965_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
+ {
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ IWL_DEBUG_RADIO("Dumping %d bytes of unhandled "
+ "notification for %s:\n",
+ le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
+- iwl4965_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
++ iwl_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
+ }
+
+ static void iwl4965_bg_beacon_update(struct work_struct *work)
+ {
+- struct iwl4965_priv *priv =
+- container_of(work, struct iwl4965_priv, beacon_update);
++ struct iwl_priv *priv =
++ container_of(work, struct iwl_priv, beacon_update);
+ struct sk_buff *beacon;
+
+ /* Pull updated AP beacon from mac80211. will fail if not in AP mode */
+@@ -3939,10 +3180,10 @@ static void iwl4965_bg_beacon_update(struct work_struct *work)
+ iwl4965_send_beacon_cmd(priv);
+ }
+
+-static void iwl4965_rx_beacon_notif(struct iwl4965_priv *priv,
++static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
+ {
+-#ifdef CONFIG_IWL4965_DEBUG
++#ifdef CONFIG_IWLWIFI_DEBUG
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl4965_beacon_notif *beacon = &(pkt->u.beacon_status);
+ u8 rate = iwl4965_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
+@@ -3962,10 +3203,10 @@ static void iwl4965_rx_beacon_notif(struct iwl4965_priv *priv,
+ }
+
+ /* Service response to REPLY_SCAN_CMD (0x80) */
+-static void iwl4965_rx_reply_scan(struct iwl4965_priv *priv,
++static void iwl4965_rx_reply_scan(struct iwl_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
+ {
+-#ifdef CONFIG_IWL4965_DEBUG
++#ifdef CONFIG_IWLWIFI_DEBUG
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl4965_scanreq_notification *notif =
+ (struct iwl4965_scanreq_notification *)pkt->u.raw;
+@@ -3975,7 +3216,7 @@ static void iwl4965_rx_reply_scan(struct iwl4965_priv *priv,
+ }
+
+ /* Service SCAN_START_NOTIFICATION (0x82) */
+-static void iwl4965_rx_scan_start_notif(struct iwl4965_priv *priv,
++static void iwl4965_rx_scan_start_notif(struct iwl_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
+ {
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+@@ -3992,7 +3233,7 @@ static void iwl4965_rx_scan_start_notif(struct iwl4965_priv *priv,
+ }
+
+ /* Service SCAN_RESULTS_NOTIFICATION (0x83) */
+-static void iwl4965_rx_scan_results_notif(struct iwl4965_priv *priv,
++static void iwl4965_rx_scan_results_notif(struct iwl_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
+ {
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+@@ -4017,7 +3258,7 @@ static void iwl4965_rx_scan_results_notif(struct iwl4965_priv *priv,
+ }
+
+ /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
+-static void iwl4965_rx_scan_complete_notif(struct iwl4965_priv *priv,
++static void iwl4965_rx_scan_complete_notif(struct iwl_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
+ {
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+@@ -4075,7 +3316,7 @@ reschedule:
+
+ /* Handle notification from uCode that card's power state is changing
+ * due to software, hardware, or critical temperature RFKILL */
+-static void iwl4965_rx_card_state_notif(struct iwl4965_priv *priv,
++static void iwl4965_rx_card_state_notif(struct iwl_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
+ {
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+@@ -4089,35 +3330,35 @@ static void iwl4965_rx_card_state_notif(struct iwl4965_priv *priv,
+ if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED |
+ RF_CARD_DISABLED)) {
+
+- iwl4965_write32(priv, CSR_UCODE_DRV_GP1_SET,
++ iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+ CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+
+- if (!iwl4965_grab_nic_access(priv)) {
+- iwl4965_write_direct32(
++ if (!iwl_grab_nic_access(priv)) {
++ iwl_write_direct32(
+ priv, HBUS_TARG_MBX_C,
+ HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
+
+- iwl4965_release_nic_access(priv);
++ iwl_release_nic_access(priv);
+ }
+
+ if (!(flags & RXON_CARD_DISABLED)) {
+- iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR,
++ iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+ CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+- if (!iwl4965_grab_nic_access(priv)) {
+- iwl4965_write_direct32(
++ if (!iwl_grab_nic_access(priv)) {
++ iwl_write_direct32(
+ priv, HBUS_TARG_MBX_C,
+ HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
+
+- iwl4965_release_nic_access(priv);
++ iwl_release_nic_access(priv);
+ }
+ }
+
+ if (flags & RF_CARD_DISABLED) {
+- iwl4965_write32(priv, CSR_UCODE_DRV_GP1_SET,
++ iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+ CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
+- iwl4965_read32(priv, CSR_UCODE_DRV_GP1);
+- if (!iwl4965_grab_nic_access(priv))
+- iwl4965_release_nic_access(priv);
++ iwl_read32(priv, CSR_UCODE_DRV_GP1);
++ if (!iwl_grab_nic_access(priv))
++ iwl_release_nic_access(priv);
+ }
+ }
+
+@@ -4153,7 +3394,7 @@ static void iwl4965_rx_card_state_notif(struct iwl4965_priv *priv,
+ * This function chains into the hardware specific files for them to setup
+ * any hardware specific handlers as well.
+ */
+-static void iwl4965_setup_rx_handlers(struct iwl4965_priv *priv)
++static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
+ {
+ priv->rx_handlers[REPLY_ALIVE] = iwl4965_rx_reply_alive;
+ priv->rx_handlers[REPLY_ADD_STA] = iwl4965_rx_reply_add_sta;
+@@ -4195,7 +3436,7 @@ static void iwl4965_setup_rx_handlers(struct iwl4965_priv *priv)
+ * will be executed. The attached skb (if present) will only be freed
+ * if the callback returns 1
+ */
+-static void iwl4965_tx_cmd_complete(struct iwl4965_priv *priv,
++static void iwl4965_tx_cmd_complete(struct iwl_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
+ {
+ struct iwl4965_rx_packet *pkt = (struct iwl4965_rx_packet *)rxb->skb->data;
+@@ -4204,7 +3445,7 @@ static void iwl4965_tx_cmd_complete(struct iwl4965_priv *priv,
+ int index = SEQ_TO_INDEX(sequence);
+ int huge = sequence & SEQ_HUGE_FRAME;
+ int cmd_index;
+- struct iwl4965_cmd *cmd;
++ struct iwl_cmd *cmd;
+
+ /* If a Tx command is being handled and it isn't in the actual
+ * command queue then there a command routing bug has been introduced
+@@ -4318,7 +3559,7 @@ static int iwl4965_rx_queue_space(const struct iwl4965_rx_queue *q)
+ /**
+ * iwl4965_rx_queue_update_write_ptr - Update the write pointer for the RX queue
+ */
+-int iwl4965_rx_queue_update_write_ptr(struct iwl4965_priv *priv, struct iwl4965_rx_queue *q)
++int iwl4965_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl4965_rx_queue *q)
+ {
+ u32 reg = 0;
+ int rc = 0;
+@@ -4331,27 +3572,27 @@ int iwl4965_rx_queue_update_write_ptr(struct iwl4965_priv *priv, struct iwl4965_
+
+ /* If power-saving is in use, make sure device is awake */
+ if (test_bit(STATUS_POWER_PMI, &priv->status)) {
+- reg = iwl4965_read32(priv, CSR_UCODE_DRV_GP1);
++ reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
+
+ if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
+- iwl4965_set_bit(priv, CSR_GP_CNTRL,
++ iwl_set_bit(priv, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+ goto exit_unlock;
+ }
+
+- rc = iwl4965_grab_nic_access(priv);
++ rc = iwl_grab_nic_access(priv);
+ if (rc)
+ goto exit_unlock;
+
+ /* Device expects a multiple of 8 */
+- iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,
++ iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,
+ q->write & ~0x7);
+- iwl4965_release_nic_access(priv);
++ iwl_release_nic_access(priv);
+
+ /* Else device is assumed to be awake */
+ } else
+ /* Device expects a multiple of 8 */
+- iwl4965_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7);
++ iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7);
+
+
+ q->need_update = 0;
+@@ -4364,7 +3605,7 @@ int iwl4965_rx_queue_update_write_ptr(struct iwl4965_priv *priv, struct iwl4965_
+ /**
+ * iwl4965_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
+ */
+-static inline __le32 iwl4965_dma_addr2rbd_ptr(struct iwl4965_priv *priv,
++static inline __le32 iwl4965_dma_addr2rbd_ptr(struct iwl_priv *priv,
+ dma_addr_t dma_addr)
+ {
+ return cpu_to_le32((u32)(dma_addr >> 8));
+@@ -4382,7 +3623,7 @@ static inline __le32 iwl4965_dma_addr2rbd_ptr(struct iwl4965_priv *priv,
+ * also updates the memory address in the firmware to reference the new
+ * target buffer.
+ */
+-static int iwl4965_rx_queue_restock(struct iwl4965_priv *priv)
++static int iwl4965_rx_queue_restock(struct iwl_priv *priv)
+ {
+ struct iwl4965_rx_queue *rxq = &priv->rxq;
+ struct list_head *element;
+@@ -4434,7 +3675,7 @@ static int iwl4965_rx_queue_restock(struct iwl4965_priv *priv)
+ * Also restock the Rx queue via iwl4965_rx_queue_restock.
+ * This is called as a scheduled work item (except for during initialization)
+ */
+-static void iwl4965_rx_allocate(struct iwl4965_priv *priv)
++static void iwl4965_rx_allocate(struct iwl_priv *priv)
+ {
+ struct iwl4965_rx_queue *rxq = &priv->rxq;
+ struct list_head *element;
+@@ -4447,7 +3688,7 @@ static void iwl4965_rx_allocate(struct iwl4965_priv *priv)
+
+ /* Alloc a new receive buffer */
+ rxb->skb =
+- alloc_skb(priv->hw_setting.rx_buf_size,
++ alloc_skb(priv->hw_params.rx_buf_size,
+ __GFP_NOWARN | GFP_ATOMIC);
+ if (!rxb->skb) {
+ if (net_ratelimit())
+@@ -4464,7 +3705,7 @@ static void iwl4965_rx_allocate(struct iwl4965_priv *priv)
+ /* Get physical address of RB/SKB */
+ rxb->dma_addr =
+ pci_map_single(priv->pci_dev, rxb->skb->data,
+- priv->hw_setting.rx_buf_size, PCI_DMA_FROMDEVICE);
++ priv->hw_params.rx_buf_size, PCI_DMA_FROMDEVICE);
+ list_add_tail(&rxb->list, &rxq->rx_free);
+ rxq->free_count++;
+ }
+@@ -4476,7 +3717,7 @@ static void iwl4965_rx_allocate(struct iwl4965_priv *priv)
+ */
+ static void __iwl4965_rx_replenish(void *data)
+ {
+- struct iwl4965_priv *priv = data;
++ struct iwl_priv *priv = data;
+
+ iwl4965_rx_allocate(priv);
+ iwl4965_rx_queue_restock(priv);
+@@ -4485,7 +3726,7 @@ static void __iwl4965_rx_replenish(void *data)
+
+ void iwl4965_rx_replenish(void *data)
+ {
+- struct iwl4965_priv *priv = data;
++ struct iwl_priv *priv = data;
+ unsigned long flags;
+
+ iwl4965_rx_allocate(priv);
+@@ -4500,14 +3741,14 @@ void iwl4965_rx_replenish(void *data)
+ * This free routine walks the list of POOL entries and if SKB is set to
+ * non NULL it is unmapped and freed
+ */
+-static void iwl4965_rx_queue_free(struct iwl4965_priv *priv, struct iwl4965_rx_queue *rxq)
++static void iwl4965_rx_queue_free(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq)
+ {
+ int i;
+ for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
+ if (rxq->pool[i].skb != NULL) {
+ pci_unmap_single(priv->pci_dev,
+ rxq->pool[i].dma_addr,
+- priv->hw_setting.rx_buf_size,
++ priv->hw_params.rx_buf_size,
+ PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(rxq->pool[i].skb);
+ }
+@@ -4518,7 +3759,7 @@ static void iwl4965_rx_queue_free(struct iwl4965_priv *priv, struct iwl4965_rx_q
+ rxq->bd = NULL;
+ }
+
+-int iwl4965_rx_queue_alloc(struct iwl4965_priv *priv)
++int iwl4965_rx_queue_alloc(struct iwl_priv *priv)
+ {
+ struct iwl4965_rx_queue *rxq = &priv->rxq;
+ struct pci_dev *dev = priv->pci_dev;
+@@ -4545,7 +3786,7 @@ int iwl4965_rx_queue_alloc(struct iwl4965_priv *priv)
+ return 0;
+ }
+
+-void iwl4965_rx_queue_reset(struct iwl4965_priv *priv, struct iwl4965_rx_queue *rxq)
++void iwl4965_rx_queue_reset(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq)
+ {
+ unsigned long flags;
+ int i;
+@@ -4559,7 +3800,7 @@ void iwl4965_rx_queue_reset(struct iwl4965_priv *priv, struct iwl4965_rx_queue *
+ if (rxq->pool[i].skb != NULL) {
+ pci_unmap_single(priv->pci_dev,
+ rxq->pool[i].dma_addr,
+- priv->hw_setting.rx_buf_size,
++ priv->hw_params.rx_buf_size,
+ PCI_DMA_FROMDEVICE);
+ priv->alloc_rxb_skb--;
+ dev_kfree_skb(rxq->pool[i].skb);
+@@ -4660,7 +3901,7 @@ int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm)
+ * the appropriate handlers, including command responses,
+ * frame-received notifications, and other notifications.
+ */
+-static void iwl4965_rx_handle(struct iwl4965_priv *priv)
++static void iwl4965_rx_handle(struct iwl_priv *priv)
+ {
+ struct iwl4965_rx_mem_buffer *rxb;
+ struct iwl4965_rx_packet *pkt;
+@@ -4694,7 +3935,7 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv)
+ rxq->queue[i] = NULL;
+
+ pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr,
+- priv->hw_setting.rx_buf_size,
++ priv->hw_params.rx_buf_size,
+ PCI_DMA_FROMDEVICE);
+ pkt = (struct iwl4965_rx_packet *)rxb->skb->data;
+
+@@ -4706,7 +3947,7 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv)
+ * but apparently a few don't get set; catch them here. */
+ reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
+ (pkt->hdr.cmd != REPLY_RX_PHY_CMD) &&
+- (pkt->hdr.cmd != REPLY_4965_RX) &&
++ (pkt->hdr.cmd != REPLY_RX) &&
+ (pkt->hdr.cmd != REPLY_COMPRESSED_BA) &&
+ (pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
+ (pkt->hdr.cmd != REPLY_TX);
+@@ -4729,7 +3970,7 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv)
+
+ if (reclaim) {
+ /* Invoke any callbacks, transfer the skb to caller, and
+- * fire off the (possibly) blocking iwl4965_send_cmd()
++ * fire off the (possibly) blocking iwl_send_cmd()
+ * as we reclaim the driver command queue */
+ if (rxb && rxb->skb)
+ iwl4965_tx_cmd_complete(priv, rxb);
+@@ -4747,7 +3988,7 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv)
+ }
+
+ pci_unmap_single(priv->pci_dev, rxb->dma_addr,
+- priv->hw_setting.rx_buf_size,
++ priv->hw_params.rx_buf_size,
+ PCI_DMA_FROMDEVICE);
+ spin_lock_irqsave(&rxq->lock, flags);
+ list_add_tail(&rxb->list, &priv->rxq.rx_used);
+@@ -4773,7 +4014,7 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv)
+ /**
+ * iwl4965_tx_queue_update_write_ptr - Send new write index to hardware
+ */
+-static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv,
++static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv,
+ struct iwl4965_tx_queue *txq)
+ {
+ u32 reg = 0;
+@@ -4788,27 +4029,27 @@ static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv,
+ /* wake up nic if it's powered down ...
+ * uCode will wake up, and interrupt us again, so next
+ * time we'll skip this part. */
+- reg = iwl4965_read32(priv, CSR_UCODE_DRV_GP1);
++ reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
+
+ if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
+ IWL_DEBUG_INFO("Requesting wakeup, GP1 = 0x%x\n", reg);
+- iwl4965_set_bit(priv, CSR_GP_CNTRL,
++ iwl_set_bit(priv, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+ return rc;
+ }
+
+ /* restore this queue's parameters in nic hardware. */
+- rc = iwl4965_grab_nic_access(priv);
++ rc = iwl_grab_nic_access(priv);
+ if (rc)
+ return rc;
+- iwl4965_write_direct32(priv, HBUS_TARG_WRPTR,
++ iwl_write_direct32(priv, HBUS_TARG_WRPTR,
+ txq->q.write_ptr | (txq_id << 8));
+- iwl4965_release_nic_access(priv);
++ iwl_release_nic_access(priv);
+
+ /* else not in power-save mode, uCode will never sleep when we're
+ * trying to tx (during RFKILL, we're not trying to tx). */
+ } else
+- iwl4965_write32(priv, HBUS_TARG_WRPTR,
++ iwl_write32(priv, HBUS_TARG_WRPTR,
+ txq->q.write_ptr | (txq_id << 8));
+
+ txq->need_update = 0;
+@@ -4816,13 +4057,13 @@ static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv,
+ return rc;
+ }
+
+-#ifdef CONFIG_IWL4965_DEBUG
++#ifdef CONFIG_IWLWIFI_DEBUG
+ static void iwl4965_print_rx_config_cmd(struct iwl4965_rxon_cmd *rxon)
+ {
+ DECLARE_MAC_BUF(mac);
+
+ IWL_DEBUG_RADIO("RX CONFIG:\n");
+- iwl4965_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
++ iwl_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
+ IWL_DEBUG_RADIO("u16 channel: 0x%x\n", le16_to_cpu(rxon->channel));
+ IWL_DEBUG_RADIO("u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags));
+ IWL_DEBUG_RADIO("u32 filter_flags: 0x%08x\n",
+@@ -4839,24 +4080,32 @@ static void iwl4965_print_rx_config_cmd(struct iwl4965_rxon_cmd *rxon)
+ }
+ #endif
+
+-static void iwl4965_enable_interrupts(struct iwl4965_priv *priv)
++static void iwl4965_enable_interrupts(struct iwl_priv *priv)
+ {
+ IWL_DEBUG_ISR("Enabling interrupts\n");
+ set_bit(STATUS_INT_ENABLED, &priv->status);
+- iwl4965_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
++ iwl_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
++}
++
++/* call this function to flush any scheduled tasklet */
++static inline void iwl_synchronize_irq(struct iwl_priv *priv)
++{
++ /* wait to make sure we flush pedding tasklet*/
++ synchronize_irq(priv->pci_dev->irq);
++ tasklet_kill(&priv->irq_tasklet);
+ }
+
+-static inline void iwl4965_disable_interrupts(struct iwl4965_priv *priv)
++static inline void iwl4965_disable_interrupts(struct iwl_priv *priv)
+ {
+ clear_bit(STATUS_INT_ENABLED, &priv->status);
+
+ /* disable interrupts from uCode/NIC to host */
+- iwl4965_write32(priv, CSR_INT_MASK, 0x00000000);
++ iwl_write32(priv, CSR_INT_MASK, 0x00000000);
+
+ /* acknowledge/clear/reset any interrupts still pending
+ * from uCode or flow handler (Rx/Tx DMA) */
+- iwl4965_write32(priv, CSR_INT, 0xffffffff);
+- iwl4965_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
++ iwl_write32(priv, CSR_INT, 0xffffffff);
++ iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
+ IWL_DEBUG_ISR("Disabled interrupts\n");
+ }
+
+@@ -4883,7 +4132,7 @@ static const char *desc_lookup(int i)
+ #define ERROR_START_OFFSET (1 * sizeof(u32))
+ #define ERROR_ELEM_SIZE (7 * sizeof(u32))
+
+-static void iwl4965_dump_nic_error_log(struct iwl4965_priv *priv)
++static void iwl4965_dump_nic_error_log(struct iwl_priv *priv)
+ {
+ u32 data2, line;
+ u32 desc, time, count, base, data1;
+@@ -4892,34 +4141,33 @@ static void iwl4965_dump_nic_error_log(struct iwl4965_priv *priv)
+
+ base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
+
+- if (!iwl4965_hw_valid_rtc_data_addr(base)) {
++ if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+ IWL_ERROR("Not valid error log pointer 0x%08X\n", base);
+ return;
+ }
+
+- rc = iwl4965_grab_nic_access(priv);
++ rc = iwl_grab_nic_access(priv);
+ if (rc) {
+ IWL_WARNING("Can not read from adapter at this time.\n");
+ return;
+ }
+
+- count = iwl4965_read_targ_mem(priv, base);
++ count = iwl_read_targ_mem(priv, base);
+
+ if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
+ IWL_ERROR("Start IWL Error Log Dump:\n");
+- IWL_ERROR("Status: 0x%08lX, Config: %08X count: %d\n",
+- priv->status, priv->config, count);
++ IWL_ERROR("Status: 0x%08lX, count: %d\n", priv->status, count);
+ }
+
+- desc = iwl4965_read_targ_mem(priv, base + 1 * sizeof(u32));
+- blink1 = iwl4965_read_targ_mem(priv, base + 3 * sizeof(u32));
+- blink2 = iwl4965_read_targ_mem(priv, base + 4 * sizeof(u32));
+- ilink1 = iwl4965_read_targ_mem(priv, base + 5 * sizeof(u32));
+- ilink2 = iwl4965_read_targ_mem(priv, base + 6 * sizeof(u32));
+- data1 = iwl4965_read_targ_mem(priv, base + 7 * sizeof(u32));
+- data2 = iwl4965_read_targ_mem(priv, base + 8 * sizeof(u32));
+- line = iwl4965_read_targ_mem(priv, base + 9 * sizeof(u32));
+- time = iwl4965_read_targ_mem(priv, base + 11 * sizeof(u32));
++ desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32));
++ blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32));
++ blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32));
++ ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32));
++ ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32));
++ data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32));
++ data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32));
++ line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32));
++ time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32));
+
+ IWL_ERROR("Desc Time "
+ "data1 data2 line\n");
+@@ -4929,7 +4177,7 @@ static void iwl4965_dump_nic_error_log(struct iwl4965_priv *priv)
+ IWL_ERROR("0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
+ ilink1, ilink2);
+
+- iwl4965_release_nic_access(priv);
++ iwl_release_nic_access(priv);
+ }
+
+ #define EVENT_START_OFFSET (4 * sizeof(u32))
+@@ -4937,9 +4185,9 @@ static void iwl4965_dump_nic_error_log(struct iwl4965_priv *priv)
+ /**
+ * iwl4965_print_event_log - Dump error event log to syslog
+ *
+- * NOTE: Must be called with iwl4965_grab_nic_access() already obtained!
++ * NOTE: Must be called with iwl_grab_nic_access() already obtained!
+ */
+-static void iwl4965_print_event_log(struct iwl4965_priv *priv, u32 start_idx,
++static void iwl4965_print_event_log(struct iwl_priv *priv, u32 start_idx,
+ u32 num_events, u32 mode)
+ {
+ u32 i;
+@@ -4963,21 +4211,21 @@ static void iwl4965_print_event_log(struct iwl4965_priv *priv, u32 start_idx,
+ /* "time" is actually "data" for mode 0 (no timestamp).
+ * place event id # at far right for easier visual parsing. */
+ for (i = 0; i < num_events; i++) {
+- ev = iwl4965_read_targ_mem(priv, ptr);
++ ev = iwl_read_targ_mem(priv, ptr);
+ ptr += sizeof(u32);
+- time = iwl4965_read_targ_mem(priv, ptr);
++ time = iwl_read_targ_mem(priv, ptr);
+ ptr += sizeof(u32);
+ if (mode == 0)
+ IWL_ERROR("0x%08x\t%04u\n", time, ev); /* data, ev */
+ else {
+- data = iwl4965_read_targ_mem(priv, ptr);
++ data = iwl_read_targ_mem(priv, ptr);
+ ptr += sizeof(u32);
+ IWL_ERROR("%010u\t0x%08x\t%04u\n", time, data, ev);
+ }
+ }
+ }
+
+-static void iwl4965_dump_nic_event_log(struct iwl4965_priv *priv)
++static void iwl4965_dump_nic_event_log(struct iwl_priv *priv)
+ {
+ int rc;
+ u32 base; /* SRAM byte address of event log header */
+@@ -4988,29 +4236,29 @@ static void iwl4965_dump_nic_event_log(struct iwl4965_priv *priv)
+ u32 size; /* # entries that we'll print */
+
+ base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+- if (!iwl4965_hw_valid_rtc_data_addr(base)) {
++ if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+ IWL_ERROR("Invalid event log pointer 0x%08X\n", base);
+ return;
+ }
+
+- rc = iwl4965_grab_nic_access(priv);
++ rc = iwl_grab_nic_access(priv);
+ if (rc) {
+ IWL_WARNING("Can not read from adapter at this time.\n");
+ return;
+ }
+
+ /* event log header */
+- capacity = iwl4965_read_targ_mem(priv, base);
+- mode = iwl4965_read_targ_mem(priv, base + (1 * sizeof(u32)));
+- num_wraps = iwl4965_read_targ_mem(priv, base + (2 * sizeof(u32)));
+- next_entry = iwl4965_read_targ_mem(priv, base + (3 * sizeof(u32)));
++ capacity = iwl_read_targ_mem(priv, base);
++ mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
++ num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
++ next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
+
+ size = num_wraps ? capacity : next_entry;
+
+ /* bail out if nothing in log */
+ if (size == 0) {
+ IWL_ERROR("Start IWL Event Log Dump: nothing in log\n");
+- iwl4965_release_nic_access(priv);
++ iwl_release_nic_access(priv);
+ return;
+ }
+
+@@ -5026,13 +4274,13 @@ static void iwl4965_dump_nic_event_log(struct iwl4965_priv *priv)
+ /* (then/else) start at top of log */
+ iwl4965_print_event_log(priv, 0, next_entry, mode);
+
+- iwl4965_release_nic_access(priv);
++ iwl_release_nic_access(priv);
+ }
+
+ /**
+ * iwl4965_irq_handle_error - called for HW or SW error interrupt from card
+ */
+-static void iwl4965_irq_handle_error(struct iwl4965_priv *priv)
++static void iwl4965_irq_handle_error(struct iwl_priv *priv)
+ {
+ /* Set the FW error flag -- cleared on iwl4965_down */
+ set_bit(STATUS_FW_ERROR, &priv->status);
+@@ -5040,8 +4288,8 @@ static void iwl4965_irq_handle_error(struct iwl4965_priv *priv)
+ /* Cancel currently queued command. */
+ clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
+
+-#ifdef CONFIG_IWL4965_DEBUG
+- if (iwl4965_debug_level & IWL_DL_FW_ERRORS) {
++#ifdef CONFIG_IWLWIFI_DEBUG
++ if (iwl_debug_level & IWL_DL_FW_ERRORS) {
+ iwl4965_dump_nic_error_log(priv);
+ iwl4965_dump_nic_event_log(priv);
+ iwl4965_print_rx_config_cmd(&priv->staging_rxon);
+@@ -5058,7 +4306,7 @@ static void iwl4965_irq_handle_error(struct iwl4965_priv *priv)
+ IWL_DEBUG(IWL_DL_INFO | IWL_DL_FW_ERRORS,
+ "Restarting adapter due to uCode error.\n");
+
+- if (iwl4965_is_associated(priv)) {
++ if (iwl_is_associated(priv)) {
+ memcpy(&priv->recovery_rxon, &priv->active_rxon,
+ sizeof(priv->recovery_rxon));
+ priv->error_recovering = 1;
+@@ -5067,7 +4315,7 @@ static void iwl4965_irq_handle_error(struct iwl4965_priv *priv)
+ }
+ }
+
+-static void iwl4965_error_recovery(struct iwl4965_priv *priv)
++static void iwl4965_error_recovery(struct iwl_priv *priv)
+ {
+ unsigned long flags;
+
+@@ -5084,12 +4332,12 @@ static void iwl4965_error_recovery(struct iwl4965_priv *priv)
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+
+-static void iwl4965_irq_tasklet(struct iwl4965_priv *priv)
++static void iwl4965_irq_tasklet(struct iwl_priv *priv)
+ {
+ u32 inta, handled = 0;
+ u32 inta_fh;
+ unsigned long flags;
+-#ifdef CONFIG_IWL4965_DEBUG
++#ifdef CONFIG_IWLWIFI_DEBUG
+ u32 inta_mask;
+ #endif
+
+@@ -5098,19 +4346,19 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv)
+ /* Ack/clear/reset pending uCode interrupts.
+ * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
+ * and will clear only when CSR_FH_INT_STATUS gets cleared. */
+- inta = iwl4965_read32(priv, CSR_INT);
+- iwl4965_write32(priv, CSR_INT, inta);
++ inta = iwl_read32(priv, CSR_INT);
++ iwl_write32(priv, CSR_INT, inta);
+
+ /* Ack/clear/reset pending flow-handler (DMA) interrupts.
+ * Any new interrupts that happen after this, either while we're
+ * in this tasklet, or later, will show up in next ISR/tasklet. */
+- inta_fh = iwl4965_read32(priv, CSR_FH_INT_STATUS);
+- iwl4965_write32(priv, CSR_FH_INT_STATUS, inta_fh);
++ inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
++ iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
+
+-#ifdef CONFIG_IWL4965_DEBUG
+- if (iwl4965_debug_level & IWL_DL_ISR) {
++#ifdef CONFIG_IWLWIFI_DEBUG
++ if (iwl_debug_level & IWL_DL_ISR) {
+ /* just for debug */
+- inta_mask = iwl4965_read32(priv, CSR_INT_MASK);
++ inta_mask = iwl_read32(priv, CSR_INT_MASK);
+ IWL_DEBUG_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
+ inta, inta_mask, inta_fh);
+ }
+@@ -5120,9 +4368,9 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv)
+ * atomic, make sure that inta covers all the interrupts that
+ * we've discovered, even if FH interrupt came in just after
+ * reading CSR_INT. */
+- if (inta_fh & CSR_FH_INT_RX_MASK)
++ if (inta_fh & CSR49_FH_INT_RX_MASK)
+ inta |= CSR_INT_BIT_FH_RX;
+- if (inta_fh & CSR_FH_INT_TX_MASK)
++ if (inta_fh & CSR49_FH_INT_TX_MASK)
+ inta |= CSR_INT_BIT_FH_TX;
+
+ /* Now service all interrupt bits discovered above. */
+@@ -5141,8 +4389,8 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv)
+ return;
+ }
+
+-#ifdef CONFIG_IWL4965_DEBUG
+- if (iwl4965_debug_level & (IWL_DL_ISR)) {
++#ifdef CONFIG_IWLWIFI_DEBUG
++ if (iwl_debug_level & (IWL_DL_ISR)) {
+ /* NIC fires this, but we don't use it, redundant with WAKEUP */
+ if (inta & CSR_INT_BIT_SCD)
+ IWL_DEBUG_ISR("Scheduler finished to transmit "
+@@ -5159,7 +4407,7 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv)
+ /* HW RF KILL switch toggled */
+ if (inta & CSR_INT_BIT_RF_KILL) {
+ int hw_rf_kill = 0;
+- if (!(iwl4965_read32(priv, CSR_GP_CNTRL) &
++ if (!(iwl_read32(priv, CSR_GP_CNTRL) &
+ CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
+ hw_rf_kill = 1;
+
+@@ -5170,7 +4418,7 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv)
+ /* Queue restart only if RF_KILL switch was set to "kill"
+ * when we loaded driver, and is now set to "enable".
+ * After we're Alive, RF_KILL gets handled by
+- * iwl_rx_card_state_notif() */
++ * iwl4965_rx_card_state_notif() */
+ if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) {
+ clear_bit(STATUS_RF_KILL_HW, &priv->status);
+ queue_work(priv->workqueue, &priv->restart);
+@@ -5230,13 +4478,15 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv)
+ }
+
+ /* Re-enable all interrupts */
+- iwl4965_enable_interrupts(priv);
+-
+-#ifdef CONFIG_IWL4965_DEBUG
+- if (iwl4965_debug_level & (IWL_DL_ISR)) {
+- inta = iwl4965_read32(priv, CSR_INT);
+- inta_mask = iwl4965_read32(priv, CSR_INT_MASK);
+- inta_fh = iwl4965_read32(priv, CSR_FH_INT_STATUS);
++ /* only Re-enable if diabled by irq */
++ if (test_bit(STATUS_INT_ENABLED, &priv->status))
++ iwl4965_enable_interrupts(priv);
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++ if (iwl_debug_level & (IWL_DL_ISR)) {
++ inta = iwl_read32(priv, CSR_INT);
++ inta_mask = iwl_read32(priv, CSR_INT_MASK);
++ inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+ IWL_DEBUG_ISR("End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
+ "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
+ }
+@@ -5246,7 +4496,7 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv)
+
+ static irqreturn_t iwl4965_isr(int irq, void *data)
+ {
+- struct iwl4965_priv *priv = data;
++ struct iwl_priv *priv = data;
+ u32 inta, inta_mask;
+ u32 inta_fh;
+ if (!priv)
+@@ -5258,12 +4508,12 @@ static irqreturn_t iwl4965_isr(int irq, void *data)
+ * back-to-back ISRs and sporadic interrupts from our NIC.
+ * If we have something to service, the tasklet will re-enable ints.
+ * If we *don't* have something, we'll re-enable before leaving here. */
+- inta_mask = iwl4965_read32(priv, CSR_INT_MASK); /* just for debug */
+- iwl4965_write32(priv, CSR_INT_MASK, 0x00000000);
++ inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
++ iwl_write32(priv, CSR_INT_MASK, 0x00000000);
+
+ /* Discover which interrupts are active/pending */
+- inta = iwl4965_read32(priv, CSR_INT);
+- inta_fh = iwl4965_read32(priv, CSR_FH_INT_STATUS);
++ inta = iwl_read32(priv, CSR_INT);
++ inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+
+ /* Ignore interrupt if there's nothing in NIC to service.
+ * This may be due to IRQ shared with another device,
+@@ -5295,313 +4545,13 @@ static irqreturn_t iwl4965_isr(int irq, void *data)
+
+ none:
+ /* re-enable interrupts here since we don't have anything to service. */
+- iwl4965_enable_interrupts(priv);
++ /* only Re-enable if diabled by irq */
++ if (test_bit(STATUS_INT_ENABLED, &priv->status))
++ iwl4965_enable_interrupts(priv);
+ spin_unlock(&priv->lock);
+ return IRQ_NONE;
+ }
+
+-/************************** EEPROM BANDS ****************************
+- *
+- * The iwl4965_eeprom_band definitions below provide the mapping from the
+- * EEPROM contents to the specific channel number supported for each
+- * band.
+- *
+- * For example, iwl4965_priv->eeprom.band_3_channels[4] from the band_3
+- * definition below maps to physical channel 42 in the 5.2GHz spectrum.
+- * The specific geography and calibration information for that channel
+- * is contained in the eeprom map itself.
+- *
+- * During init, we copy the eeprom information and channel map
+- * information into priv->channel_info_24/52 and priv->channel_map_24/52
+- *
+- * channel_map_24/52 provides the index in the channel_info array for a
+- * given channel. We have to have two separate maps as there is channel
+- * overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and
+- * band_2
+- *
+- * A value of 0xff stored in the channel_map indicates that the channel
+- * is not supported by the hardware at all.
+- *
+- * A value of 0xfe in the channel_map indicates that the channel is not
+- * valid for Tx with the current hardware. This means that
+- * while the system can tune and receive on a given channel, it may not
+- * be able to associate or transmit any frames on that
+- * channel. There is no corresponding channel information for that
+- * entry.
+- *
+- *********************************************************************/
+-
+-/* 2.4 GHz */
+-static const u8 iwl4965_eeprom_band_1[14] = {
+- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
+-};
+-
+-/* 5.2 GHz bands */
+-static const u8 iwl4965_eeprom_band_2[] = { /* 4915-5080MHz */
+- 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16
+-};
+-
+-static const u8 iwl4965_eeprom_band_3[] = { /* 5170-5320MHz */
+- 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
+-};
+-
+-static const u8 iwl4965_eeprom_band_4[] = { /* 5500-5700MHz */
+- 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
+-};
+-
+-static const u8 iwl4965_eeprom_band_5[] = { /* 5725-5825MHz */
+- 145, 149, 153, 157, 161, 165
+-};
+-
+-static u8 iwl4965_eeprom_band_6[] = { /* 2.4 FAT channel */
+- 1, 2, 3, 4, 5, 6, 7
+-};
+-
+-static u8 iwl4965_eeprom_band_7[] = { /* 5.2 FAT channel */
+- 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
+-};
+-
+-static void iwl4965_init_band_reference(const struct iwl4965_priv *priv,
+- int band,
+- int *eeprom_ch_count,
+- const struct iwl4965_eeprom_channel
+- **eeprom_ch_info,
+- const u8 **eeprom_ch_index)
+-{
+- switch (band) {
+- case 1: /* 2.4GHz band */
+- *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_1);
+- *eeprom_ch_info = priv->eeprom.band_1_channels;
+- *eeprom_ch_index = iwl4965_eeprom_band_1;
+- break;
+- case 2: /* 4.9GHz band */
+- *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_2);
+- *eeprom_ch_info = priv->eeprom.band_2_channels;
+- *eeprom_ch_index = iwl4965_eeprom_band_2;
+- break;
+- case 3: /* 5.2GHz band */
+- *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_3);
+- *eeprom_ch_info = priv->eeprom.band_3_channels;
+- *eeprom_ch_index = iwl4965_eeprom_band_3;
+- break;
+- case 4: /* 5.5GHz band */
+- *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_4);
+- *eeprom_ch_info = priv->eeprom.band_4_channels;
+- *eeprom_ch_index = iwl4965_eeprom_band_4;
+- break;
+- case 5: /* 5.7GHz band */
+- *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_5);
+- *eeprom_ch_info = priv->eeprom.band_5_channels;
+- *eeprom_ch_index = iwl4965_eeprom_band_5;
+- break;
+- case 6: /* 2.4GHz FAT channels */
+- *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_6);
+- *eeprom_ch_info = priv->eeprom.band_24_channels;
+- *eeprom_ch_index = iwl4965_eeprom_band_6;
+- break;
+- case 7: /* 5 GHz FAT channels */
+- *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_7);
+- *eeprom_ch_info = priv->eeprom.band_52_channels;
+- *eeprom_ch_index = iwl4965_eeprom_band_7;
+- break;
+- default:
+- BUG();
+- return;
+- }
+-}
+-
+-/**
+- * iwl4965_get_channel_info - Find driver's private channel info
+- *
+- * Based on band and channel number.
+- */
+-const struct iwl4965_channel_info *iwl4965_get_channel_info(const struct iwl4965_priv *priv,
+- int phymode, u16 channel)
+-{
+- int i;
+-
+- switch (phymode) {
+- case MODE_IEEE80211A:
+- for (i = 14; i < priv->channel_count; i++) {
+- if (priv->channel_info[i].channel == channel)
+- return &priv->channel_info[i];
+- }
+- break;
+-
+- case MODE_IEEE80211B:
+- case MODE_IEEE80211G:
+- if (channel >= 1 && channel <= 14)
+- return &priv->channel_info[channel - 1];
+- break;
+-
+- }
+-
+- return NULL;
+-}
+-
+-#define CHECK_AND_PRINT(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \
+- ? # x " " : "")
+-
+-/**
+- * iwl4965_init_channel_map - Set up driver's info for all possible channels
+- */
+-static int iwl4965_init_channel_map(struct iwl4965_priv *priv)
+-{
+- int eeprom_ch_count = 0;
+- const u8 *eeprom_ch_index = NULL;
+- const struct iwl4965_eeprom_channel *eeprom_ch_info = NULL;
+- int band, ch;
+- struct iwl4965_channel_info *ch_info;
+-
+- if (priv->channel_count) {
+- IWL_DEBUG_INFO("Channel map already initialized.\n");
+- return 0;
+- }
+-
+- if (priv->eeprom.version < 0x2f) {
+- IWL_WARNING("Unsupported EEPROM version: 0x%04X\n",
+- priv->eeprom.version);
+- return -EINVAL;
+- }
+-
+- IWL_DEBUG_INFO("Initializing regulatory info from EEPROM\n");
+-
+- priv->channel_count =
+- ARRAY_SIZE(iwl4965_eeprom_band_1) +
+- ARRAY_SIZE(iwl4965_eeprom_band_2) +
+- ARRAY_SIZE(iwl4965_eeprom_band_3) +
+- ARRAY_SIZE(iwl4965_eeprom_band_4) +
+- ARRAY_SIZE(iwl4965_eeprom_band_5);
+-
+- IWL_DEBUG_INFO("Parsing data for %d channels.\n", priv->channel_count);
+-
+- priv->channel_info = kzalloc(sizeof(struct iwl4965_channel_info) *
+- priv->channel_count, GFP_KERNEL);
+- if (!priv->channel_info) {
+- IWL_ERROR("Could not allocate channel_info\n");
+- priv->channel_count = 0;
+- return -ENOMEM;
+- }
+-
+- ch_info = priv->channel_info;
+-
+- /* Loop through the 5 EEPROM bands adding them in order to the
+- * channel map we maintain (that contains additional information than
+- * what just in the EEPROM) */
+- for (band = 1; band <= 5; band++) {
+-
+- iwl4965_init_band_reference(priv, band, &eeprom_ch_count,
+- &eeprom_ch_info, &eeprom_ch_index);
+-
+- /* Loop through each band adding each of the channels */
+- for (ch = 0; ch < eeprom_ch_count; ch++) {
+- ch_info->channel = eeprom_ch_index[ch];
+- ch_info->phymode = (band == 1) ? MODE_IEEE80211B :
+- MODE_IEEE80211A;
+-
+- /* permanently store EEPROM's channel regulatory flags
+- * and max power in channel info database. */
+- ch_info->eeprom = eeprom_ch_info[ch];
+-
+- /* Copy the run-time flags so they are there even on
+- * invalid channels */
+- ch_info->flags = eeprom_ch_info[ch].flags;
+-
+- if (!(is_channel_valid(ch_info))) {
+- IWL_DEBUG_INFO("Ch. %d Flags %x [%sGHz] - "
+- "No traffic\n",
+- ch_info->channel,
+- ch_info->flags,
+- is_channel_a_band(ch_info) ?
+- "5.2" : "2.4");
+- ch_info++;
+- continue;
+- }
+-
+- /* Initialize regulatory-based run-time data */
+- ch_info->max_power_avg = ch_info->curr_txpow =
+- eeprom_ch_info[ch].max_power_avg;
+- ch_info->scan_power = eeprom_ch_info[ch].max_power_avg;
+- ch_info->min_power = 0;
+-
+- IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x"
+- " %ddBm): Ad-Hoc %ssupported\n",
+- ch_info->channel,
+- is_channel_a_band(ch_info) ?
+- "5.2" : "2.4",
+- CHECK_AND_PRINT(IBSS),
+- CHECK_AND_PRINT(ACTIVE),
+- CHECK_AND_PRINT(RADAR),
+- CHECK_AND_PRINT(WIDE),
+- CHECK_AND_PRINT(NARROW),
+- CHECK_AND_PRINT(DFS),
+- eeprom_ch_info[ch].flags,
+- eeprom_ch_info[ch].max_power_avg,
+- ((eeprom_ch_info[ch].
+- flags & EEPROM_CHANNEL_IBSS)
+- && !(eeprom_ch_info[ch].
+- flags & EEPROM_CHANNEL_RADAR))
+- ? "" : "not ");
+-
+- /* Set the user_txpower_limit to the highest power
+- * supported by any channel */
+- if (eeprom_ch_info[ch].max_power_avg >
+- priv->user_txpower_limit)
+- priv->user_txpower_limit =
+- eeprom_ch_info[ch].max_power_avg;
+-
+- ch_info++;
+- }
+- }
+-
+- /* Two additional EEPROM bands for 2.4 and 5 GHz FAT channels */
+- for (band = 6; band <= 7; band++) {
+- int phymode;
+- u8 fat_extension_chan;
+-
+- iwl4965_init_band_reference(priv, band, &eeprom_ch_count,
+- &eeprom_ch_info, &eeprom_ch_index);
+-
+- /* EEPROM band 6 is 2.4, band 7 is 5 GHz */
+- phymode = (band == 6) ? MODE_IEEE80211B : MODE_IEEE80211A;
+-
+- /* Loop through each band adding each of the channels */
+- for (ch = 0; ch < eeprom_ch_count; ch++) {
+-
+- if ((band == 6) &&
+- ((eeprom_ch_index[ch] == 5) ||
+- (eeprom_ch_index[ch] == 6) ||
+- (eeprom_ch_index[ch] == 7)))
+- fat_extension_chan = HT_IE_EXT_CHANNEL_MAX;
+- else
+- fat_extension_chan = HT_IE_EXT_CHANNEL_ABOVE;
+-
+- /* Set up driver's info for lower half */
+- iwl4965_set_fat_chan_info(priv, phymode,
+- eeprom_ch_index[ch],
+- &(eeprom_ch_info[ch]),
+- fat_extension_chan);
+-
+- /* Set up driver's info for upper half */
+- iwl4965_set_fat_chan_info(priv, phymode,
+- (eeprom_ch_index[ch] + 4),
+- &(eeprom_ch_info[ch]),
+- HT_IE_EXT_CHANNEL_BELOW);
+- }
+- }
+-
+- return 0;
+-}
+-
+-/*
+- * iwl4965_free_channel_map - undo allocations in iwl4965_init_channel_map
+- */
+-static void iwl4965_free_channel_map(struct iwl4965_priv *priv)
+-{
+- kfree(priv->channel_info);
+- priv->channel_count = 0;
+-}
+-
+ /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
+ * sending probe req. This should be set long enough to hear probe responses
+ * from more than one AP. */
+@@ -5625,22 +4575,24 @@ static void iwl4965_free_channel_map(struct iwl4965_priv *priv)
+ #define IWL_PASSIVE_DWELL_BASE (100)
+ #define IWL_CHANNEL_TUNE_TIME 5
+
+-static inline u16 iwl4965_get_active_dwell_time(struct iwl4965_priv *priv, int phymode)
++static inline u16 iwl4965_get_active_dwell_time(struct iwl_priv *priv,
++ enum ieee80211_band band)
+ {
+- if (phymode == MODE_IEEE80211A)
++ if (band == IEEE80211_BAND_5GHZ)
+ return IWL_ACTIVE_DWELL_TIME_52;
+ else
+ return IWL_ACTIVE_DWELL_TIME_24;
+ }
+
+-static u16 iwl4965_get_passive_dwell_time(struct iwl4965_priv *priv, int phymode)
++static u16 iwl4965_get_passive_dwell_time(struct iwl_priv *priv,
++ enum ieee80211_band band)
+ {
+- u16 active = iwl4965_get_active_dwell_time(priv, phymode);
+- u16 passive = (phymode != MODE_IEEE80211A) ?
++ u16 active = iwl4965_get_active_dwell_time(priv, band);
++ u16 passive = (band != IEEE80211_BAND_5GHZ) ?
+ IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
+ IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
+
+- if (iwl4965_is_associated(priv)) {
++ if (iwl_is_associated(priv)) {
+ /* If we're associated, we clamp the maximum passive
+ * dwell time to be 98% of the beacon interval (minus
+ * 2 * channel tune time) */
+@@ -5656,30 +4608,34 @@ static u16 iwl4965_get_passive_dwell_time(struct iwl4965_priv *priv, int phymode
+ return passive;
+ }
+
+-static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode,
++static int iwl4965_get_channels_for_scan(struct iwl_priv *priv,
++ enum ieee80211_band band,
+ u8 is_active, u8 direct_mask,
+ struct iwl4965_scan_channel *scan_ch)
+ {
+ const struct ieee80211_channel *channels = NULL;
+- const struct ieee80211_hw_mode *hw_mode;
+- const struct iwl4965_channel_info *ch_info;
++ const struct ieee80211_supported_band *sband;
++ const struct iwl_channel_info *ch_info;
+ u16 passive_dwell = 0;
+ u16 active_dwell = 0;
+ int added, i;
+
+- hw_mode = iwl4965_get_hw_mode(priv, phymode);
+- if (!hw_mode)
++ sband = iwl4965_get_hw_mode(priv, band);
++ if (!sband)
+ return 0;
+
+- channels = hw_mode->channels;
++ channels = sband->channels;
++
++ active_dwell = iwl4965_get_active_dwell_time(priv, band);
++ passive_dwell = iwl4965_get_passive_dwell_time(priv, band);
+
+- active_dwell = iwl4965_get_active_dwell_time(priv, phymode);
+- passive_dwell = iwl4965_get_passive_dwell_time(priv, phymode);
++ for (i = 0, added = 0; i < sband->n_channels; i++) {
++ if (channels[i].flags & IEEE80211_CHAN_DISABLED)
++ continue;
+
+- for (i = 0, added = 0; i < hw_mode->num_channels; i++) {
+- if (channels[i].chan ==
++ if (ieee80211_frequency_to_channel(channels[i].center_freq) ==
+ le16_to_cpu(priv->active_rxon.channel)) {
+- if (iwl4965_is_associated(priv)) {
++ if (iwl_is_associated(priv)) {
+ IWL_DEBUG_SCAN
+ ("Skipping current channel %d\n",
+ le16_to_cpu(priv->active_rxon.channel));
+@@ -5688,9 +4644,9 @@ static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode,
+ } else if (priv->only_active_channel)
+ continue;
+
+- scan_ch->channel = channels[i].chan;
++ scan_ch->channel = ieee80211_frequency_to_channel(channels[i].center_freq);
+
+- ch_info = iwl4965_get_channel_info(priv, phymode,
++ ch_info = iwl_get_channel_info(priv, band,
+ scan_ch->channel);
+ if (!is_channel_valid(ch_info)) {
+ IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n",
+@@ -5699,7 +4655,7 @@ static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode,
+ }
+
+ if (!is_active || is_channel_passive(ch_info) ||
+- !(channels[i].flag & IEEE80211_CHAN_W_ACTIVE_SCAN))
++ (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN))
+ scan_ch->type = 0; /* passive */
+ else
+ scan_ch->type = 1; /* active */
+@@ -5718,7 +4674,7 @@ static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode,
+ /* scan_pwr_info->tpc.dsp_atten; */
+
+ /*scan_pwr_info->tpc.tx_gain; */
+- if (phymode == MODE_IEEE80211A)
++ if (band == IEEE80211_BAND_5GHZ)
+ scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
+ else {
+ scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
+@@ -5742,194 +4698,148 @@ static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode,
+ return added;
+ }
+
+-static void iwl4965_reset_channel_flag(struct iwl4965_priv *priv)
+-{
+- int i, j;
+- for (i = 0; i < 3; i++) {
+- struct ieee80211_hw_mode *hw_mode = (void *)&priv->modes[i];
+- for (j = 0; j < hw_mode->num_channels; j++)
+- hw_mode->channels[j].flag = hw_mode->channels[j].val;
+- }
+-}
+-
+-static void iwl4965_init_hw_rates(struct iwl4965_priv *priv,
++static void iwl4965_init_hw_rates(struct iwl_priv *priv,
+ struct ieee80211_rate *rates)
+ {
+ int i;
+
+ for (i = 0; i < IWL_RATE_COUNT; i++) {
+- rates[i].rate = iwl4965_rates[i].ieee * 5;
+- rates[i].val = i; /* Rate scaling will work on indexes */
+- rates[i].val2 = i;
+- rates[i].flags = IEEE80211_RATE_SUPPORTED;
+- /* Only OFDM have the bits-per-symbol set */
+- if ((i <= IWL_LAST_OFDM_RATE) && (i >= IWL_FIRST_OFDM_RATE))
+- rates[i].flags |= IEEE80211_RATE_OFDM;
+- else {
++ rates[i].bitrate = iwl4965_rates[i].ieee * 5;
++ rates[i].hw_value = i; /* Rate scaling will work on indexes */
++ rates[i].hw_value_short = i;
++ rates[i].flags = 0;
++ if ((i > IWL_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) {
+ /*
+- * If CCK 1M then set rate flag to CCK else CCK_2
+- * which is CCK | PREAMBLE2
++ * If CCK != 1M then set short preamble rate flag.
+ */
+- rates[i].flags |= (iwl4965_rates[i].plcp == 10) ?
+- IEEE80211_RATE_CCK : IEEE80211_RATE_CCK_2;
++ rates[i].flags |=
++ (iwl4965_rates[i].plcp == IWL_RATE_1M_PLCP) ?
++ 0 : IEEE80211_RATE_SHORT_PREAMBLE;
+ }
+-
+- /* Set up which ones are basic rates... */
+- if (IWL_BASIC_RATES_MASK & (1 << i))
+- rates[i].flags |= IEEE80211_RATE_BASIC;
+ }
+ }
+
+ /**
+ * iwl4965_init_geos - Initialize mac80211's geo/channel info based from eeprom
+ */
+-static int iwl4965_init_geos(struct iwl4965_priv *priv)
++int iwl4965_init_geos(struct iwl_priv *priv)
+ {
+- struct iwl4965_channel_info *ch;
+- struct ieee80211_hw_mode *modes;
++ struct iwl_channel_info *ch;
++ struct ieee80211_supported_band *sband;
+ struct ieee80211_channel *channels;
+ struct ieee80211_channel *geo_ch;
+ struct ieee80211_rate *rates;
+ int i = 0;
+- enum {
+- A = 0,
+- B = 1,
+- G = 2,
+- };
+- int mode_count = 3;
+
+- if (priv->modes) {
++ if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
++ priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
+ IWL_DEBUG_INFO("Geography modes already initialized.\n");
+ set_bit(STATUS_GEO_CONFIGURED, &priv->status);
+ return 0;
+ }
+
+- modes = kzalloc(sizeof(struct ieee80211_hw_mode) * mode_count,
+- GFP_KERNEL);
+- if (!modes)
+- return -ENOMEM;
+-
+ channels = kzalloc(sizeof(struct ieee80211_channel) *
+ priv->channel_count, GFP_KERNEL);
+- if (!channels) {
+- kfree(modes);
++ if (!channels)
+ return -ENOMEM;
+- }
+
+- rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_MAX_RATES + 1)),
++ rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_RATE_COUNT + 1)),
+ GFP_KERNEL);
+ if (!rates) {
+- kfree(modes);
+ kfree(channels);
+ return -ENOMEM;
+ }
+
+- /* 0 = 802.11a
+- * 1 = 802.11b
+- * 2 = 802.11g
+- */
+-
+ /* 5.2GHz channels start after the 2.4GHz channels */
+- modes[A].mode = MODE_IEEE80211A;
+- modes[A].channels = &channels[ARRAY_SIZE(iwl4965_eeprom_band_1)];
+- modes[A].rates = rates;
+- modes[A].num_rates = 8; /* just OFDM */
+- modes[A].rates = &rates[4];
+- modes[A].num_channels = 0;
+-#ifdef CONFIG_IWL4965_HT
+- iwl4965_init_ht_hw_capab(&modes[A].ht_info, MODE_IEEE80211A);
+-#endif
++ sband = &priv->bands[IEEE80211_BAND_5GHZ];
++ sband->channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)];
++ /* just OFDM */
++ sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
++ sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE;
+
+- modes[B].mode = MODE_IEEE80211B;
+- modes[B].channels = channels;
+- modes[B].rates = rates;
+- modes[B].num_rates = 4; /* just CCK */
+- modes[B].num_channels = 0;
+-
+- modes[G].mode = MODE_IEEE80211G;
+- modes[G].channels = channels;
+- modes[G].rates = rates;
+- modes[G].num_rates = 12; /* OFDM & CCK */
+- modes[G].num_channels = 0;
+-#ifdef CONFIG_IWL4965_HT
+- iwl4965_init_ht_hw_capab(&modes[G].ht_info, MODE_IEEE80211G);
+-#endif
++ iwl4965_init_ht_hw_capab(priv, &sband->ht_info, IEEE80211_BAND_5GHZ);
++
++ sband = &priv->bands[IEEE80211_BAND_2GHZ];
++ sband->channels = channels;
++ /* OFDM & CCK */
++ sband->bitrates = rates;
++ sband->n_bitrates = IWL_RATE_COUNT;
++
++ iwl4965_init_ht_hw_capab(priv, &sband->ht_info, IEEE80211_BAND_2GHZ);
+
+ priv->ieee_channels = channels;
+ priv->ieee_rates = rates;
+
+ iwl4965_init_hw_rates(priv, rates);
+
+- for (i = 0, geo_ch = channels; i < priv->channel_count; i++) {
++ for (i = 0; i < priv->channel_count; i++) {
+ ch = &priv->channel_info[i];
+
+- if (!is_channel_valid(ch)) {
+- IWL_DEBUG_INFO("Channel %d [%sGHz] is restricted -- "
+- "skipping.\n",
+- ch->channel, is_channel_a_band(ch) ?
+- "5.2" : "2.4");
++ /* FIXME: might be removed if scan is OK */
++ if (!is_channel_valid(ch))
+ continue;
+- }
+
+- if (is_channel_a_band(ch)) {
+- geo_ch = &modes[A].channels[modes[A].num_channels++];
+- } else {
+- geo_ch = &modes[B].channels[modes[B].num_channels++];
+- modes[G].num_channels++;
+- }
++ if (is_channel_a_band(ch))
++ sband = &priv->bands[IEEE80211_BAND_5GHZ];
++ else
++ sband = &priv->bands[IEEE80211_BAND_2GHZ];
+
+- geo_ch->freq = ieee80211chan2mhz(ch->channel);
+- geo_ch->chan = ch->channel;
+- geo_ch->power_level = ch->max_power_avg;
+- geo_ch->antenna_max = 0xff;
++ geo_ch = &sband->channels[sband->n_channels++];
++
++ geo_ch->center_freq = ieee80211_channel_to_frequency(ch->channel);
++ geo_ch->max_power = ch->max_power_avg;
++ geo_ch->max_antenna_gain = 0xff;
++ geo_ch->hw_value = ch->channel;
+
+ if (is_channel_valid(ch)) {
+- geo_ch->flag = IEEE80211_CHAN_W_SCAN;
+- if (ch->flags & EEPROM_CHANNEL_IBSS)
+- geo_ch->flag |= IEEE80211_CHAN_W_IBSS;
++ if (!(ch->flags & EEPROM_CHANNEL_IBSS))
++ geo_ch->flags |= IEEE80211_CHAN_NO_IBSS;
+
+- if (ch->flags & EEPROM_CHANNEL_ACTIVE)
+- geo_ch->flag |= IEEE80211_CHAN_W_ACTIVE_SCAN;
++ if (!(ch->flags & EEPROM_CHANNEL_ACTIVE))
++ geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
+
+ if (ch->flags & EEPROM_CHANNEL_RADAR)
+- geo_ch->flag |= IEEE80211_CHAN_W_RADAR_DETECT;
++ geo_ch->flags |= IEEE80211_CHAN_RADAR;
+
+ if (ch->max_power_avg > priv->max_channel_txpower_limit)
+ priv->max_channel_txpower_limit =
+ ch->max_power_avg;
++ } else {
++ geo_ch->flags |= IEEE80211_CHAN_DISABLED;
+ }
+
+- geo_ch->val = geo_ch->flag;
++ /* Save flags for reg domain usage */
++ geo_ch->orig_flags = geo_ch->flags;
++
++ IWL_DEBUG_INFO("Channel %d Freq=%d[%sGHz] %s flag=0%X\n",
++ ch->channel, geo_ch->center_freq,
++ is_channel_a_band(ch) ? "5.2" : "2.4",
++ geo_ch->flags & IEEE80211_CHAN_DISABLED ?
++ "restricted" : "valid",
++ geo_ch->flags);
+ }
+
+- if ((modes[A].num_channels == 0) && priv->is_abg) {
++ if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
++ priv->cfg->sku & IWL_SKU_A) {
+ printk(KERN_INFO DRV_NAME
+ ": Incorrectly detected BG card as ABG. Please send "
+ "your PCI ID 0x%04X:0x%04X to maintainer.\n",
+ priv->pci_dev->device, priv->pci_dev->subsystem_device);
+- priv->is_abg = 0;
++ priv->cfg->sku &= ~IWL_SKU_A;
+ }
+
+ printk(KERN_INFO DRV_NAME
+ ": Tunable channels: %d 802.11bg, %d 802.11a channels\n",
+- modes[G].num_channels, modes[A].num_channels);
++ priv->bands[IEEE80211_BAND_2GHZ].n_channels,
++ priv->bands[IEEE80211_BAND_5GHZ].n_channels);
+
+- /*
+- * NOTE: We register these in preference of order -- the
+- * stack doesn't currently (as of 7.0.6 / Apr 24 '07) pick
+- * a phymode based on rates or AP capabilities but seems to
+- * configure it purely on if the channel being configured
+- * is supported by a mode -- and the first match is taken
+- */
++ if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
++ priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
++ &priv->bands[IEEE80211_BAND_2GHZ];
++ if (priv->bands[IEEE80211_BAND_5GHZ].n_channels)
++ priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
++ &priv->bands[IEEE80211_BAND_5GHZ];
+
+- if (modes[G].num_channels)
+- ieee80211_register_hwmode(priv->hw, &modes[G]);
+- if (modes[B].num_channels)
+- ieee80211_register_hwmode(priv->hw, &modes[B]);
+- if (modes[A].num_channels)
+- ieee80211_register_hwmode(priv->hw, &modes[A]);
+-
+- priv->modes = modes;
+ set_bit(STATUS_GEO_CONFIGURED, &priv->status);
+
+ return 0;
+@@ -5938,9 +4848,8 @@ static int iwl4965_init_geos(struct iwl4965_priv *priv)
+ /*
+ * iwl4965_free_geos - undo allocations in iwl4965_init_geos
+ */
+-static void iwl4965_free_geos(struct iwl4965_priv *priv)
++void iwl4965_free_geos(struct iwl_priv *priv)
+ {
+- kfree(priv->modes);
+ kfree(priv->ieee_channels);
+ kfree(priv->ieee_rates);
+ clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
+@@ -5952,7 +4861,7 @@ static void iwl4965_free_geos(struct iwl4965_priv *priv)
+ *
+ ******************************************************************************/
+
+-static void iwl4965_dealloc_ucode_pci(struct iwl4965_priv *priv)
++static void iwl4965_dealloc_ucode_pci(struct iwl_priv *priv)
+ {
+ iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code);
+ iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data);
+@@ -5966,7 +4875,7 @@ static void iwl4965_dealloc_ucode_pci(struct iwl4965_priv *priv)
+ * iwl4965_verify_inst_full - verify runtime uCode image in card vs. host,
+ * looking at all data.
+ */
+-static int iwl4965_verify_inst_full(struct iwl4965_priv *priv, __le32 *image,
++static int iwl4965_verify_inst_full(struct iwl_priv *priv, __le32 *image,
+ u32 len)
+ {
+ u32 val;
+@@ -5976,18 +4885,18 @@ static int iwl4965_verify_inst_full(struct iwl4965_priv *priv, __le32 *image,
+
+ IWL_DEBUG_INFO("ucode inst image size is %u\n", len);
+
+- rc = iwl4965_grab_nic_access(priv);
++ rc = iwl_grab_nic_access(priv);
+ if (rc)
+ return rc;
+
+- iwl4965_write_direct32(priv, HBUS_TARG_MEM_RADDR, RTC_INST_LOWER_BOUND);
++ iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, RTC_INST_LOWER_BOUND);
+
+ errcnt = 0;
+ for (; len > 0; len -= sizeof(u32), image++) {
+ /* read data comes through single port, auto-incr addr */
+ /* NOTE: Use the debugless read so we don't flood kernel log
+ * if IWL_DL_IO is set */
+- val = _iwl4965_read_direct32(priv, HBUS_TARG_MEM_RDAT);
++ val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+ if (val != le32_to_cpu(*image)) {
+ IWL_ERROR("uCode INST section is invalid at "
+ "offset 0x%x, is 0x%x, s/b 0x%x\n",
+@@ -5999,7 +4908,7 @@ static int iwl4965_verify_inst_full(struct iwl4965_priv *priv, __le32 *image,
+ }
+ }
+
+- iwl4965_release_nic_access(priv);
++ iwl_release_nic_access(priv);
+
+ if (!errcnt)
+ IWL_DEBUG_INFO
+@@ -6014,7 +4923,7 @@ static int iwl4965_verify_inst_full(struct iwl4965_priv *priv, __le32 *image,
+ * using sample data 100 bytes apart. If these sample points are good,
+ * it's a pretty good bet that everything between them is good, too.
+ */
+-static int iwl4965_verify_inst_sparse(struct iwl4965_priv *priv, __le32 *image, u32 len)
++static int iwl4965_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
+ {
+ u32 val;
+ int rc = 0;
+@@ -6023,7 +4932,7 @@ static int iwl4965_verify_inst_sparse(struct iwl4965_priv *priv, __le32 *image,
+
+ IWL_DEBUG_INFO("ucode inst image size is %u\n", len);
+
+- rc = iwl4965_grab_nic_access(priv);
++ rc = iwl_grab_nic_access(priv);
+ if (rc)
+ return rc;
+
+@@ -6031,9 +4940,9 @@ static int iwl4965_verify_inst_sparse(struct iwl4965_priv *priv, __le32 *image,
+ /* read data comes through single port, auto-incr addr */
+ /* NOTE: Use the debugless read so we don't flood kernel log
+ * if IWL_DL_IO is set */
+- iwl4965_write_direct32(priv, HBUS_TARG_MEM_RADDR,
++ iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
+ i + RTC_INST_LOWER_BOUND);
+- val = _iwl4965_read_direct32(priv, HBUS_TARG_MEM_RDAT);
++ val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+ if (val != le32_to_cpu(*image)) {
+ #if 0 /* Enable this if you want to see details */
+ IWL_ERROR("uCode INST section is invalid at "
+@@ -6047,7 +4956,7 @@ static int iwl4965_verify_inst_sparse(struct iwl4965_priv *priv, __le32 *image,
+ }
+ }
+
+- iwl4965_release_nic_access(priv);
++ iwl_release_nic_access(priv);
+
+ return rc;
+ }
+@@ -6057,7 +4966,7 @@ static int iwl4965_verify_inst_sparse(struct iwl4965_priv *priv, __le32 *image,
+ * iwl4965_verify_ucode - determine which instruction image is in SRAM,
+ * and verify its contents
+ */
+-static int iwl4965_verify_ucode(struct iwl4965_priv *priv)
++static int iwl4965_verify_ucode(struct iwl_priv *priv)
+ {
+ __le32 *image;
+ u32 len;
+@@ -6102,160 +5011,10 @@ static int iwl4965_verify_ucode(struct iwl4965_priv *priv)
+ return rc;
+ }
+
+-
+-/* check contents of special bootstrap uCode SRAM */
+-static int iwl4965_verify_bsm(struct iwl4965_priv *priv)
+-{
+- __le32 *image = priv->ucode_boot.v_addr;
+- u32 len = priv->ucode_boot.len;
+- u32 reg;
+- u32 val;
+-
+- IWL_DEBUG_INFO("Begin verify bsm\n");
+-
+- /* verify BSM SRAM contents */
+- val = iwl4965_read_prph(priv, BSM_WR_DWCOUNT_REG);
+- for (reg = BSM_SRAM_LOWER_BOUND;
+- reg < BSM_SRAM_LOWER_BOUND + len;
+- reg += sizeof(u32), image ++) {
+- val = iwl4965_read_prph(priv, reg);
+- if (val != le32_to_cpu(*image)) {
+- IWL_ERROR("BSM uCode verification failed at "
+- "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
+- BSM_SRAM_LOWER_BOUND,
+- reg - BSM_SRAM_LOWER_BOUND, len,
+- val, le32_to_cpu(*image));
+- return -EIO;
+- }
+- }
+-
+- IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n");
+-
+- return 0;
+-}
+-
+-/**
+- * iwl4965_load_bsm - Load bootstrap instructions
+- *
+- * BSM operation:
+- *
+- * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
+- * in special SRAM that does not power down during RFKILL. When powering back
+- * up after power-saving sleeps (or during initial uCode load), the BSM loads
+- * the bootstrap program into the on-board processor, and starts it.
+- *
+- * The bootstrap program loads (via DMA) instructions and data for a new
+- * program from host DRAM locations indicated by the host driver in the
+- * BSM_DRAM_* registers. Once the new program is loaded, it starts
+- * automatically.
+- *
+- * When initializing the NIC, the host driver points the BSM to the
+- * "initialize" uCode image. This uCode sets up some internal data, then
+- * notifies host via "initialize alive" that it is complete.
+- *
+- * The host then replaces the BSM_DRAM_* pointer values to point to the
+- * normal runtime uCode instructions and a backup uCode data cache buffer
+- * (filled initially with starting data values for the on-board processor),
+- * then triggers the "initialize" uCode to load and launch the runtime uCode,
+- * which begins normal operation.
+- *
+- * When doing a power-save shutdown, runtime uCode saves data SRAM into
+- * the backup data cache in DRAM before SRAM is powered down.
+- *
+- * When powering back up, the BSM loads the bootstrap program. This reloads
+- * the runtime uCode instructions and the backup data cache into SRAM,
+- * and re-launches the runtime uCode from where it left off.
+- */
+-static int iwl4965_load_bsm(struct iwl4965_priv *priv)
+-{
+- __le32 *image = priv->ucode_boot.v_addr;
+- u32 len = priv->ucode_boot.len;
+- dma_addr_t pinst;
+- dma_addr_t pdata;
+- u32 inst_len;
+- u32 data_len;
+- int rc;
+- int i;
+- u32 done;
+- u32 reg_offset;
+-
+- IWL_DEBUG_INFO("Begin load bsm\n");
+-
+- /* make sure bootstrap program is no larger than BSM's SRAM size */
+- if (len > IWL_MAX_BSM_SIZE)
+- return -EINVAL;
+-
+- /* Tell bootstrap uCode where to find the "Initialize" uCode
+- * in host DRAM ... host DRAM physical address bits 35:4 for 4965.
+- * NOTE: iwl4965_initialize_alive_start() will replace these values,
+- * after the "initialize" uCode has run, to point to
+- * runtime/protocol instructions and backup data cache. */
+- pinst = priv->ucode_init.p_addr >> 4;
+- pdata = priv->ucode_init_data.p_addr >> 4;
+- inst_len = priv->ucode_init.len;
+- data_len = priv->ucode_init_data.len;
+-
+- rc = iwl4965_grab_nic_access(priv);
+- if (rc)
+- return rc;
+-
+- iwl4965_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
+- iwl4965_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
+- iwl4965_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
+- iwl4965_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
+-
+- /* Fill BSM memory with bootstrap instructions */
+- for (reg_offset = BSM_SRAM_LOWER_BOUND;
+- reg_offset < BSM_SRAM_LOWER_BOUND + len;
+- reg_offset += sizeof(u32), image++)
+- _iwl4965_write_prph(priv, reg_offset,
+- le32_to_cpu(*image));
+-
+- rc = iwl4965_verify_bsm(priv);
+- if (rc) {
+- iwl4965_release_nic_access(priv);
+- return rc;
+- }
+-
+- /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
+- iwl4965_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
+- iwl4965_write_prph(priv, BSM_WR_MEM_DST_REG,
+- RTC_INST_LOWER_BOUND);
+- iwl4965_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
+-
+- /* Load bootstrap code into instruction SRAM now,
+- * to prepare to load "initialize" uCode */
+- iwl4965_write_prph(priv, BSM_WR_CTRL_REG,
+- BSM_WR_CTRL_REG_BIT_START);
+-
+- /* Wait for load of bootstrap uCode to finish */
+- for (i = 0; i < 100; i++) {
+- done = iwl4965_read_prph(priv, BSM_WR_CTRL_REG);
+- if (!(done & BSM_WR_CTRL_REG_BIT_START))
+- break;
+- udelay(10);
+- }
+- if (i < 100)
+- IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i);
+- else {
+- IWL_ERROR("BSM write did not complete!\n");
+- return -EIO;
+- }
+-
+- /* Enable future boot loads whenever power management unit triggers it
+- * (e.g. when powering back up after power-save shutdown) */
+- iwl4965_write_prph(priv, BSM_WR_CTRL_REG,
+- BSM_WR_CTRL_REG_BIT_START_EN);
+-
+- iwl4965_release_nic_access(priv);
+-
+- return 0;
+-}
+-
+-static void iwl4965_nic_start(struct iwl4965_priv *priv)
++static void iwl4965_nic_start(struct iwl_priv *priv)
+ {
+ /* Remove all resets to allow NIC to operate */
+- iwl4965_write32(priv, CSR_RESET, 0);
++ iwl_write32(priv, CSR_RESET, 0);
+ }
+
+
+@@ -6264,12 +5023,12 @@ static void iwl4965_nic_start(struct iwl4965_priv *priv)
+ *
+ * Copy into buffers for card to fetch via bus-mastering
+ */
+-static int iwl4965_read_ucode(struct iwl4965_priv *priv)
++static int iwl4965_read_ucode(struct iwl_priv *priv)
+ {
+ struct iwl4965_ucode *ucode;
+ int ret;
+ const struct firmware *ucode_raw;
+- const char *name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode";
++ const char *name = priv->cfg->fw_name;
+ u8 *src;
+ size_t len;
+ u32 ver, inst_size, data_size, init_size, init_data_size, boot_size;
+@@ -6465,7 +5224,7 @@ static int iwl4965_read_ucode(struct iwl4965_priv *priv)
+ * We need to replace them to load runtime uCode inst and data,
+ * and to save runtime data when powering down.
+ */
+-static int iwl4965_set_ucode_ptrs(struct iwl4965_priv *priv)
++static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv)
+ {
+ dma_addr_t pinst;
+ dma_addr_t pdata;
+@@ -6477,24 +5236,24 @@ static int iwl4965_set_ucode_ptrs(struct iwl4965_priv *priv)
+ pdata = priv->ucode_data_backup.p_addr >> 4;
+
+ spin_lock_irqsave(&priv->lock, flags);
+- rc = iwl4965_grab_nic_access(priv);
++ rc = iwl_grab_nic_access(priv);
+ if (rc) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return rc;
+ }
+
+ /* Tell bootstrap uCode where to find image to load */
+- iwl4965_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
+- iwl4965_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
+- iwl4965_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
++ iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
++ iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
++ iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
+ priv->ucode_data.len);
+
+ /* Inst bytecount must be last to set up, bit 31 signals uCode
+ * that all new ptr/size info is in place */
+- iwl4965_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
++ iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
+ priv->ucode_code.len | BSM_DRAM_INST_LOAD);
+
+- iwl4965_release_nic_access(priv);
++ iwl_release_nic_access(priv);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+@@ -6514,7 +5273,7 @@ static int iwl4965_set_ucode_ptrs(struct iwl4965_priv *priv)
+ *
+ * Tell "initialize" uCode to go ahead and load the runtime uCode.
+ */
+-static void iwl4965_init_alive_start(struct iwl4965_priv *priv)
++static void iwl4965_init_alive_start(struct iwl_priv *priv)
+ {
+ /* Check alive response for "valid" sign from uCode */
+ if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
+@@ -6559,9 +5318,9 @@ static void iwl4965_init_alive_start(struct iwl4965_priv *priv)
+ * from protocol/runtime uCode (initialization uCode's
+ * Alive gets handled by iwl4965_init_alive_start()).
+ */
+-static void iwl4965_alive_start(struct iwl4965_priv *priv)
++static void iwl4965_alive_start(struct iwl_priv *priv)
+ {
+- int rc = 0;
++ int ret = 0;
+
+ IWL_DEBUG_INFO("Runtime Alive received.\n");
+
+@@ -6582,12 +5341,12 @@ static void iwl4965_alive_start(struct iwl4965_priv *priv)
+ goto restart;
+ }
+
+- iwl4965_clear_stations_table(priv);
++ iwlcore_clear_stations_table(priv);
+
+- rc = iwl4965_alive_notify(priv);
+- if (rc) {
++ ret = priv->cfg->ops->lib->alive_notify(priv);
++ if (ret) {
+ IWL_WARNING("Could not complete ALIVE transition [ntf]: %d\n",
+- rc);
++ ret);
+ goto restart;
+ }
+
+@@ -6597,7 +5356,7 @@ static void iwl4965_alive_start(struct iwl4965_priv *priv)
+ /* Clear out the uCode error bit if it is set */
+ clear_bit(STATUS_FW_ERROR, &priv->status);
+
+- if (iwl4965_is_rfkill(priv))
++ if (iwl_is_rfkill(priv))
+ return;
+
+ ieee80211_start_queues(priv->hw);
+@@ -6607,7 +5366,7 @@ static void iwl4965_alive_start(struct iwl4965_priv *priv)
+
+ iwl4965_send_power_mode(priv, IWL_POWER_LEVEL(priv->power_mode));
+
+- if (iwl4965_is_associated(priv)) {
++ if (iwl_is_associated(priv)) {
+ struct iwl4965_rxon_cmd *active_rxon =
+ (struct iwl4965_rxon_cmd *)(&priv->active_rxon);
+
+@@ -6631,6 +5390,8 @@ static void iwl4965_alive_start(struct iwl4965_priv *priv)
+
+ iwl4965_rf_kill_ct_config(priv);
+
++ iwl_leds_register(priv);
++
+ IWL_DEBUG_INFO("ALIVE processing complete.\n");
+ set_bit(STATUS_READY, &priv->status);
+ wake_up_interruptible(&priv->wait_command_queue);
+@@ -6638,15 +5399,17 @@ static void iwl4965_alive_start(struct iwl4965_priv *priv)
+ if (priv->error_recovering)
+ iwl4965_error_recovery(priv);
+
++ iwlcore_low_level_notify(priv, IWLCORE_START_EVT);
++ ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC);
+ return;
+
+ restart:
+ queue_work(priv->workqueue, &priv->restart);
+ }
+
+-static void iwl4965_cancel_deferred_work(struct iwl4965_priv *priv);
++static void iwl4965_cancel_deferred_work(struct iwl_priv *priv);
+
+-static void __iwl4965_down(struct iwl4965_priv *priv)
++static void __iwl4965_down(struct iwl_priv *priv)
+ {
+ unsigned long flags;
+ int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status);
+@@ -6659,7 +5422,11 @@ static void __iwl4965_down(struct iwl4965_priv *priv)
+ if (!exit_pending)
+ set_bit(STATUS_EXIT_PENDING, &priv->status);
+
+- iwl4965_clear_stations_table(priv);
++ iwl_leds_unregister(priv);
++
++ iwlcore_low_level_notify(priv, IWLCORE_STOP_EVT);
++
++ iwlcore_clear_stations_table(priv);
+
+ /* Unblock any waiting calls */
+ wake_up_interruptible_all(&priv->wait_command_queue);
+@@ -6670,17 +5437,20 @@ static void __iwl4965_down(struct iwl4965_priv *priv)
+ clear_bit(STATUS_EXIT_PENDING, &priv->status);
+
+ /* stop and reset the on-board processor */
+- iwl4965_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
++ iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+
+ /* tell the device to stop sending interrupts */
++ spin_lock_irqsave(&priv->lock, flags);
+ iwl4965_disable_interrupts(priv);
++ spin_unlock_irqrestore(&priv->lock, flags);
++ iwl_synchronize_irq(priv);
+
+ if (priv->mac80211_registered)
+ ieee80211_stop_queues(priv->hw);
+
+ /* If we have not previously called iwl4965_init() then
+ * clear all bits but the RF Kill and SUSPEND bits and return */
+- if (!iwl4965_is_init(priv)) {
++ if (!iwl_is_init(priv)) {
+ priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
+ STATUS_RF_KILL_HW |
+ test_bit(STATUS_RF_KILL_SW, &priv->status) <<
+@@ -6706,7 +5476,7 @@ static void __iwl4965_down(struct iwl4965_priv *priv)
+ STATUS_FW_ERROR;
+
+ spin_lock_irqsave(&priv->lock, flags);
+- iwl4965_clear_bit(priv, CSR_GP_CNTRL,
++ iwl_clear_bit(priv, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+@@ -6714,17 +5484,17 @@ static void __iwl4965_down(struct iwl4965_priv *priv)
+ iwl4965_hw_rxq_stop(priv);
+
+ spin_lock_irqsave(&priv->lock, flags);
+- if (!iwl4965_grab_nic_access(priv)) {
+- iwl4965_write_prph(priv, APMG_CLK_DIS_REG,
++ if (!iwl_grab_nic_access(priv)) {
++ iwl_write_prph(priv, APMG_CLK_DIS_REG,
+ APMG_CLK_VAL_DMA_CLK_RQT);
+- iwl4965_release_nic_access(priv);
++ iwl_release_nic_access(priv);
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ udelay(5);
+
+ iwl4965_hw_nic_stop_master(priv);
+- iwl4965_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
++ iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+ iwl4965_hw_nic_reset(priv);
+
+ exit:
+@@ -6738,7 +5508,7 @@ static void __iwl4965_down(struct iwl4965_priv *priv)
+ iwl4965_clear_free_frames(priv);
+ }
+
+-static void iwl4965_down(struct iwl4965_priv *priv)
++static void iwl4965_down(struct iwl_priv *priv)
+ {
+ mutex_lock(&priv->mutex);
+ __iwl4965_down(priv);
+@@ -6749,9 +5519,10 @@ static void iwl4965_down(struct iwl4965_priv *priv)
+
+ #define MAX_HW_RESTARTS 5
+
+-static int __iwl4965_up(struct iwl4965_priv *priv)
++static int __iwl4965_up(struct iwl_priv *priv)
+ {
+- int rc, i;
++ int i;
++ int ret;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
+ IWL_WARNING("Exit pending; will not bring the NIC up\n");
+@@ -6761,6 +5532,7 @@ static int __iwl4965_up(struct iwl4965_priv *priv)
+ if (test_bit(STATUS_RF_KILL_SW, &priv->status)) {
+ IWL_WARNING("Radio disabled by SW RF kill (module "
+ "parameter)\n");
++ iwl_rfkill_set_hw_state(priv);
+ return -ENODEV;
+ }
+
+@@ -6770,37 +5542,39 @@ static int __iwl4965_up(struct iwl4965_priv *priv)
+ }
+
+ /* If platform's RF_KILL switch is NOT set to KILL */
+- if (iwl4965_read32(priv, CSR_GP_CNTRL) &
++ if (iwl_read32(priv, CSR_GP_CNTRL) &
+ CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
+ clear_bit(STATUS_RF_KILL_HW, &priv->status);
+ else {
+ set_bit(STATUS_RF_KILL_HW, &priv->status);
+ if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) {
++ iwl_rfkill_set_hw_state(priv);
+ IWL_WARNING("Radio disabled by HW RF Kill switch\n");
+ return -ENODEV;
+ }
+ }
+
+- iwl4965_write32(priv, CSR_INT, 0xFFFFFFFF);
++ iwl_rfkill_set_hw_state(priv);
++ iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
+
+- rc = iwl4965_hw_nic_init(priv);
+- if (rc) {
+- IWL_ERROR("Unable to int nic\n");
+- return rc;
++ ret = priv->cfg->ops->lib->hw_nic_init(priv);
++ if (ret) {
++ IWL_ERROR("Unable to init nic\n");
++ return ret;
+ }
+
+ /* make sure rfkill handshake bits are cleared */
+- iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+- iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR,
++ iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
++ iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+ CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+
+ /* clear (again), then enable host interrupts */
+- iwl4965_write32(priv, CSR_INT, 0xFFFFFFFF);
++ iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
+ iwl4965_enable_interrupts(priv);
+
+ /* really make sure rfkill handshake bits are cleared */
+- iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+- iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
++ iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
++ iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+
+ /* Copy original ucode data image from disk into backup cache.
+ * This will be used to initialize the on-board processor's
+@@ -6814,15 +5588,15 @@ static int __iwl4965_up(struct iwl4965_priv *priv)
+
+ for (i = 0; i < MAX_HW_RESTARTS; i++) {
+
+- iwl4965_clear_stations_table(priv);
++ iwlcore_clear_stations_table(priv);
+
+ /* load bootstrap state machine,
+ * load bootstrap program into processor's memory,
+ * prepare to load the "initialize" uCode */
+- rc = iwl4965_load_bsm(priv);
++ ret = priv->cfg->ops->lib->load_ucode(priv);
+
+- if (rc) {
+- IWL_ERROR("Unable to set up bootstrap uCode: %d\n", rc);
++ if (ret) {
++ IWL_ERROR("Unable to set up bootstrap uCode: %d\n", ret);
+ continue;
+ }
+
+@@ -6852,8 +5626,8 @@ static int __iwl4965_up(struct iwl4965_priv *priv)
+
+ static void iwl4965_bg_init_alive_start(struct work_struct *data)
+ {
+- struct iwl4965_priv *priv =
+- container_of(data, struct iwl4965_priv, init_alive_start.work);
++ struct iwl_priv *priv =
++ container_of(data, struct iwl_priv, init_alive_start.work);
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+@@ -6865,8 +5639,8 @@ static void iwl4965_bg_init_alive_start(struct work_struct *data)
+
+ static void iwl4965_bg_alive_start(struct work_struct *data)
+ {
+- struct iwl4965_priv *priv =
+- container_of(data, struct iwl4965_priv, alive_start.work);
++ struct iwl_priv *priv =
++ container_of(data, struct iwl_priv, alive_start.work);
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+@@ -6878,7 +5652,7 @@ static void iwl4965_bg_alive_start(struct work_struct *data)
+
+ static void iwl4965_bg_rf_kill(struct work_struct *work)
+ {
+- struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv, rf_kill);
++ struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
+
+ wake_up_interruptible(&priv->wait_command_queue);
+
+@@ -6887,13 +5661,16 @@ static void iwl4965_bg_rf_kill(struct work_struct *work)
+
+ mutex_lock(&priv->mutex);
+
+- if (!iwl4965_is_rfkill(priv)) {
++ if (!iwl_is_rfkill(priv)) {
+ IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL,
+ "HW and/or SW RF Kill no longer active, restarting "
+ "device\n");
+ if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
+ queue_work(priv->workqueue, &priv->restart);
+ } else {
++ /* make sure mac80211 stop sending Tx frame */
++ if (priv->mac80211_registered)
++ ieee80211_stop_queues(priv->hw);
+
+ if (!test_bit(STATUS_RF_KILL_HW, &priv->status))
+ IWL_DEBUG_RF_KILL("Can not turn radio back on - "
+@@ -6903,6 +5680,8 @@ static void iwl4965_bg_rf_kill(struct work_struct *work)
+ "Kill switch must be turned off for "
+ "wireless networking to work.\n");
+ }
++ iwl_rfkill_set_hw_state(priv);
++
+ mutex_unlock(&priv->mutex);
+ }
+
+@@ -6910,8 +5689,8 @@ static void iwl4965_bg_rf_kill(struct work_struct *work)
+
+ static void iwl4965_bg_scan_check(struct work_struct *data)
+ {
+- struct iwl4965_priv *priv =
+- container_of(data, struct iwl4965_priv, scan_check.work);
++ struct iwl_priv *priv =
++ container_of(data, struct iwl_priv, scan_check.work);
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+@@ -6931,24 +5710,25 @@ static void iwl4965_bg_scan_check(struct work_struct *data)
+
+ static void iwl4965_bg_request_scan(struct work_struct *data)
+ {
+- struct iwl4965_priv *priv =
+- container_of(data, struct iwl4965_priv, request_scan);
+- struct iwl4965_host_cmd cmd = {
++ struct iwl_priv *priv =
++ container_of(data, struct iwl_priv, request_scan);
++ struct iwl_host_cmd cmd = {
+ .id = REPLY_SCAN_CMD,
+ .len = sizeof(struct iwl4965_scan_cmd),
+ .meta.flags = CMD_SIZE_HUGE,
+ };
+- int rc = 0;
+ struct iwl4965_scan_cmd *scan;
+ struct ieee80211_conf *conf = NULL;
++ u16 cmd_len;
++ enum ieee80211_band band;
+ u8 direct_mask;
+- int phymode;
++ int ret = 0;
+
+ conf = ieee80211_get_hw_conf(priv->hw);
+
+ mutex_lock(&priv->mutex);
+
+- if (!iwl4965_is_ready(priv)) {
++ if (!iwl_is_ready(priv)) {
+ IWL_WARNING("request scan called when driver not ready.\n");
+ goto done;
+ }
+@@ -6963,7 +5743,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
+ if (test_bit(STATUS_SCAN_HW, &priv->status)) {
+ IWL_DEBUG_INFO("Multiple concurrent scan requests in parallel. "
+ "Ignoring second request.\n");
+- rc = -EIO;
++ ret = -EIO;
+ goto done;
+ }
+
+@@ -6977,7 +5757,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
+ goto done;
+ }
+
+- if (iwl4965_is_rfkill(priv)) {
++ if (iwl_is_rfkill(priv)) {
+ IWL_DEBUG_HC("Aborting scan due to RF Kill activation\n");
+ goto done;
+ }
+@@ -6996,7 +5776,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
+ priv->scan = kmalloc(sizeof(struct iwl4965_scan_cmd) +
+ IWL_MAX_SCAN_SIZE, GFP_KERNEL);
+ if (!priv->scan) {
+- rc = -ENOMEM;
++ ret = -ENOMEM;
+ goto done;
+ }
+ }
+@@ -7006,7 +5786,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
+ scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
+ scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
+
+- if (iwl4965_is_associated(priv)) {
++ if (iwl_is_associated(priv)) {
+ u16 interval = 0;
+ u32 extra;
+ u32 suspend_time = 100;
+@@ -7043,26 +5823,19 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
+ memcpy(scan->direct_scan[0].ssid,
+ priv->direct_ssid, priv->direct_ssid_len);
+ direct_mask = 1;
+- } else if (!iwl4965_is_associated(priv) && priv->essid_len) {
++ } else if (!iwl_is_associated(priv) && priv->essid_len) {
+ scan->direct_scan[0].id = WLAN_EID_SSID;
+ scan->direct_scan[0].len = priv->essid_len;
+ memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len);
+ direct_mask = 1;
+- } else
++ } else {
+ direct_mask = 0;
++ }
+
+- /* We don't build a direct scan probe request; the uCode will do
+- * that based on the direct_mask added to each channel entry */
+- scan->tx_cmd.len = cpu_to_le16(
+- iwl4965_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data,
+- IWL_MAX_SCAN_SIZE - sizeof(*scan), 0));
+ scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
+- scan->tx_cmd.sta_id = priv->hw_setting.bcast_sta_id;
++ scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id;
+ scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+
+- /* flags + rate selection */
+-
+- scan->tx_cmd.tx_flags |= cpu_to_le32(0x200);
+
+ switch (priv->scan_bands) {
+ case 2:
+@@ -7072,7 +5845,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
+ RATE_MCS_ANT_B_MSK|RATE_MCS_CCK_MSK);
+
+ scan->good_CRC_th = 0;
+- phymode = MODE_IEEE80211G;
++ band = IEEE80211_BAND_2GHZ;
+ break;
+
+ case 1:
+@@ -7080,7 +5853,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
+ iwl4965_hw_set_rate_n_flags(IWL_RATE_6M_PLCP,
+ RATE_MCS_ANT_B_MSK);
+ scan->good_CRC_th = IWL_GOOD_CRC_TH;
+- phymode = MODE_IEEE80211A;
++ band = IEEE80211_BAND_5GHZ;
+ break;
+
+ default:
+@@ -7088,6 +5861,13 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
+ goto done;
+ }
+
++ /* We don't build a direct scan probe request; the uCode will do
++ * that based on the direct_mask added to each channel entry */
++ cmd_len = iwl4965_fill_probe_req(priv, band,
++ (struct ieee80211_mgmt *)scan->data,
++ IWL_MAX_SCAN_SIZE - sizeof(*scan), 0);
++
++ scan->tx_cmd.len = cpu_to_le16(cmd_len);
+ /* select Rx chains */
+
+ /* Force use of chains B and C (0x6) for scan Rx.
+@@ -7101,18 +5881,23 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
+ if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR)
+ scan->filter_flags = RXON_FILTER_PROMISC_MSK;
+
+- if (direct_mask)
++ if (direct_mask) {
+ IWL_DEBUG_SCAN
+ ("Initiating direct scan for %s.\n",
+ iwl4965_escape_essid(priv->essid, priv->essid_len));
+- else
++ scan->channel_count =
++ iwl4965_get_channels_for_scan(
++ priv, band, 1, /* active */
++ direct_mask,
++ (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
++ } else {
+ IWL_DEBUG_SCAN("Initiating indirect scan.\n");
+-
+- scan->channel_count =
+- iwl4965_get_channels_for_scan(
+- priv, phymode, 1, /* active */
+- direct_mask,
+- (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
++ scan->channel_count =
++ iwl4965_get_channels_for_scan(
++ priv, band, 0, /* passive */
++ direct_mask,
++ (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
++ }
+
+ cmd.len += le16_to_cpu(scan->tx_cmd.len) +
+ scan->channel_count * sizeof(struct iwl4965_scan_channel);
+@@ -7120,8 +5905,8 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
+ scan->len = cpu_to_le16(cmd.len);
+
+ set_bit(STATUS_SCAN_HW, &priv->status);
+- rc = iwl4965_send_cmd_sync(priv, &cmd);
+- if (rc)
++ ret = iwl_send_cmd_sync(priv, &cmd);
++ if (ret)
+ goto done;
+
+ queue_delayed_work(priv->workqueue, &priv->scan_check,
+@@ -7138,7 +5923,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
+
+ static void iwl4965_bg_up(struct work_struct *data)
+ {
+- struct iwl4965_priv *priv = container_of(data, struct iwl4965_priv, up);
++ struct iwl_priv *priv = container_of(data, struct iwl_priv, up);
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+@@ -7150,7 +5935,7 @@ static void iwl4965_bg_up(struct work_struct *data)
+
+ static void iwl4965_bg_restart(struct work_struct *data)
+ {
+- struct iwl4965_priv *priv = container_of(data, struct iwl4965_priv, restart);
++ struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+@@ -7161,8 +5946,8 @@ static void iwl4965_bg_restart(struct work_struct *data)
+
+ static void iwl4965_bg_rx_replenish(struct work_struct *data)
+ {
+- struct iwl4965_priv *priv =
+- container_of(data, struct iwl4965_priv, rx_replenish);
++ struct iwl_priv *priv =
++ container_of(data, struct iwl_priv, rx_replenish);
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+@@ -7174,13 +5959,10 @@ static void iwl4965_bg_rx_replenish(struct work_struct *data)
+
+ #define IWL_DELAY_NEXT_SCAN (HZ*2)
+
+-static void iwl4965_bg_post_associate(struct work_struct *data)
++static void iwl4965_post_associate(struct iwl_priv *priv)
+ {
+- struct iwl4965_priv *priv = container_of(data, struct iwl4965_priv,
+- post_associate.work);
+-
+- int rc = 0;
+ struct ieee80211_conf *conf = NULL;
++ int ret = 0;
+ DECLARE_MAC_BUF(mac);
+
+ if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
+@@ -7196,12 +5978,10 @@ static void iwl4965_bg_post_associate(struct work_struct *data)
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+- mutex_lock(&priv->mutex);
+
+- if (!priv->vif || !priv->is_open) {
+- mutex_unlock(&priv->mutex);
++ if (!priv->vif || !priv->is_open)
+ return;
+- }
++
+ iwl4965_scan_cancel_timeout(priv, 200);
+
+ conf = ieee80211_get_hw_conf(priv->hw);
+@@ -7211,9 +5991,9 @@ static void iwl4965_bg_post_associate(struct work_struct *data)
+
+ memset(&priv->rxon_timing, 0, sizeof(struct iwl4965_rxon_time_cmd));
+ iwl4965_setup_rxon_timing(priv);
+- rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON_TIMING,
++ ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
+ sizeof(priv->rxon_timing), &priv->rxon_timing);
+- if (rc)
++ if (ret)
+ IWL_WARNING("REPLY_RXON_TIMING failed - "
+ "Attempting to continue.\n");
+
+@@ -7255,7 +6035,7 @@ static void iwl4965_bg_post_associate(struct work_struct *data)
+ case IEEE80211_IF_TYPE_IBSS:
+
+ /* clear out the station table */
+- iwl4965_clear_stations_table(priv);
++ iwlcore_clear_stations_table(priv);
+
+ iwl4965_rxon_add_station(priv, iwl4965_broadcast_addr, 0);
+ iwl4965_rxon_add_station(priv, priv->bssid, 0);
+@@ -7281,19 +6061,29 @@ static void iwl4965_bg_post_associate(struct work_struct *data)
+ if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
+ priv->assoc_station_added = 1;
+
+-#ifdef CONFIG_IWL4965_QOS
+ iwl4965_activate_qos(priv, 0);
+-#endif /* CONFIG_IWL4965_QOS */
++
+ /* we have just associated, don't start scan too early */
+ priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
++}
++
++
++static void iwl4965_bg_post_associate(struct work_struct *data)
++{
++ struct iwl_priv *priv = container_of(data, struct iwl_priv,
++ post_associate.work);
++
++ mutex_lock(&priv->mutex);
++ iwl4965_post_associate(priv);
+ mutex_unlock(&priv->mutex);
++
+ }
+
+ static void iwl4965_bg_abort_scan(struct work_struct *work)
+ {
+- struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv, abort_scan);
++ struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan);
+
+- if (!iwl4965_is_ready(priv))
++ if (!iwl_is_ready(priv))
+ return;
+
+ mutex_lock(&priv->mutex);
+@@ -7308,8 +6098,8 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
+
+ static void iwl4965_bg_scan_completed(struct work_struct *work)
+ {
+- struct iwl4965_priv *priv =
+- container_of(work, struct iwl4965_priv, scan_completed);
++ struct iwl_priv *priv =
++ container_of(work, struct iwl_priv, scan_completed);
+
+ IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN, "SCAN complete scan\n");
+
+@@ -7338,7 +6128,7 @@ static void iwl4965_bg_scan_completed(struct work_struct *work)
+
+ static int iwl4965_mac_start(struct ieee80211_hw *hw)
+ {
+- struct iwl4965_priv *priv = hw->priv;
++ struct iwl_priv *priv = hw->priv;
+ int ret;
+
+ IWL_DEBUG_MAC80211("enter\n");
+@@ -7415,7 +6205,7 @@ out_disable_msi:
+
+ static void iwl4965_mac_stop(struct ieee80211_hw *hw)
+ {
+- struct iwl4965_priv *priv = hw->priv;
++ struct iwl_priv *priv = hw->priv;
+
+ IWL_DEBUG_MAC80211("enter\n");
+
+@@ -7426,7 +6216,7 @@ static void iwl4965_mac_stop(struct ieee80211_hw *hw)
+
+ priv->is_open = 0;
+
+- if (iwl4965_is_ready_rf(priv)) {
++ if (iwl_is_ready_rf(priv)) {
+ /* stop mac, cancel any scan request and clear
+ * RXON_FILTER_ASSOC_MSK BIT
+ */
+@@ -7450,7 +6240,7 @@ static void iwl4965_mac_stop(struct ieee80211_hw *hw)
+ static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct ieee80211_tx_control *ctl)
+ {
+- struct iwl4965_priv *priv = hw->priv;
++ struct iwl_priv *priv = hw->priv;
+
+ IWL_DEBUG_MAC80211("enter\n");
+
+@@ -7460,7 +6250,7 @@ static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ }
+
+ IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
+- ctl->tx_rate);
++ ctl->tx_rate->bitrate);
+
+ if (iwl4965_tx_skb(priv, skb, ctl))
+ dev_kfree_skb_any(skb);
+@@ -7472,7 +6262,7 @@ static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ static int iwl4965_mac_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_init_conf *conf)
+ {
+- struct iwl4965_priv *priv = hw->priv;
++ struct iwl_priv *priv = hw->priv;
+ unsigned long flags;
+ DECLARE_MAC_BUF(mac);
+
+@@ -7495,7 +6285,7 @@ static int iwl4965_mac_add_interface(struct ieee80211_hw *hw,
+ memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
+ }
+
+- if (iwl4965_is_ready(priv))
++ if (iwl_is_ready(priv))
+ iwl4965_set_mode(priv, conf->type);
+
+ mutex_unlock(&priv->mutex);
+@@ -7513,23 +6303,23 @@ static int iwl4965_mac_add_interface(struct ieee80211_hw *hw,
+ */
+ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+ {
+- struct iwl4965_priv *priv = hw->priv;
+- const struct iwl4965_channel_info *ch_info;
++ struct iwl_priv *priv = hw->priv;
++ const struct iwl_channel_info *ch_info;
+ unsigned long flags;
+ int ret = 0;
+
+ mutex_lock(&priv->mutex);
+- IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel);
++ IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value);
+
+ priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
+
+- if (!iwl4965_is_ready(priv)) {
++ if (!iwl_is_ready(priv)) {
+ IWL_DEBUG_MAC80211("leave - not ready\n");
+ ret = -EIO;
+ goto out;
+ }
+
+- if (unlikely(!iwl4965_param_disable_hw_scan &&
++ if (unlikely(!priv->cfg->mod_params->disable_hw_scan &&
+ test_bit(STATUS_SCANNING, &priv->status))) {
+ IWL_DEBUG_MAC80211("leave - scanning\n");
+ set_bit(STATUS_CONF_PENDING, &priv->status);
+@@ -7539,10 +6329,9 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+- ch_info = iwl4965_get_channel_info(priv, conf->phymode, conf->channel);
++ ch_info = iwl_get_channel_info(priv, conf->channel->band,
++ ieee80211_frequency_to_channel(conf->channel->center_freq));
+ if (!is_channel_valid(ch_info)) {
+- IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this SKU.\n",
+- conf->channel, conf->phymode);
+ IWL_DEBUG_MAC80211("leave - invalid channel\n");
+ spin_unlock_irqrestore(&priv->lock, flags);
+ ret = -EINVAL;
+@@ -7550,10 +6339,10 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
+ }
+
+ #ifdef CONFIG_IWL4965_HT
+- /* if we are switching fron ht to 2.4 clear flags
++ /* if we are switching from ht to 2.4 clear flags
+ * from any ht related info since 2.4 does not
+ * support ht */
+- if ((le16_to_cpu(priv->staging_rxon.channel) != conf->channel)
++ if ((le16_to_cpu(priv->staging_rxon.channel) != conf->channel->hw_value)
+ #ifdef IEEE80211_CONF_CHANNEL_SWITCH
+ && !(conf->flags & IEEE80211_CONF_CHANNEL_SWITCH)
+ #endif
+@@ -7561,12 +6350,13 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
+ priv->staging_rxon.flags = 0;
+ #endif /* CONFIG_IWL4965_HT */
+
+- iwl4965_set_rxon_channel(priv, conf->phymode, conf->channel);
++ iwlcore_set_rxon_channel(priv, conf->channel->band,
++ ieee80211_frequency_to_channel(conf->channel->center_freq));
+
+- iwl4965_set_flags_for_phymode(priv, conf->phymode);
++ iwl4965_set_flags_for_phymode(priv, conf->channel->band);
+
+ /* The list of supported rates and rate mask can be different
+- * for each phymode; since the phymode may have changed, reset
++ * for each band; since the band may have changed, reset
+ * the rate mask to what mac80211 lists */
+ iwl4965_set_rate(priv);
+
+@@ -7579,14 +6369,15 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
+ }
+ #endif
+
+- iwl4965_radio_kill_sw(priv, !conf->radio_enabled);
++ if (priv->cfg->ops->lib->radio_kill_sw)
++ priv->cfg->ops->lib->radio_kill_sw(priv, !conf->radio_enabled);
+
+ if (!conf->radio_enabled) {
+ IWL_DEBUG_MAC80211("leave - radio disabled\n");
+ goto out;
+ }
+
+- if (iwl4965_is_rfkill(priv)) {
++ if (iwl_is_rfkill(priv)) {
+ IWL_DEBUG_MAC80211("leave - RF kill\n");
+ ret = -EIO;
+ goto out;
+@@ -7608,9 +6399,9 @@ out:
+ return ret;
+ }
+
+-static void iwl4965_config_ap(struct iwl4965_priv *priv)
++static void iwl4965_config_ap(struct iwl_priv *priv)
+ {
+- int rc = 0;
++ int ret = 0;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+@@ -7625,9 +6416,9 @@ static void iwl4965_config_ap(struct iwl4965_priv *priv)
+ /* RXON Timing */
+ memset(&priv->rxon_timing, 0, sizeof(struct iwl4965_rxon_time_cmd));
+ iwl4965_setup_rxon_timing(priv);
+- rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON_TIMING,
++ ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
+ sizeof(priv->rxon_timing), &priv->rxon_timing);
+- if (rc)
++ if (ret)
+ IWL_WARNING("REPLY_RXON_TIMING failed - "
+ "Attempting to continue.\n");
+
+@@ -7658,9 +6449,7 @@ static void iwl4965_config_ap(struct iwl4965_priv *priv)
+ /* restore RXON assoc */
+ priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
+ iwl4965_commit_rxon(priv);
+-#ifdef CONFIG_IWL4965_QOS
+ iwl4965_activate_qos(priv, 1);
+-#endif
+ iwl4965_rxon_add_station(priv, iwl4965_broadcast_addr, 0);
+ }
+ iwl4965_send_beacon_cmd(priv);
+@@ -7674,7 +6463,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_if_conf *conf)
+ {
+- struct iwl4965_priv *priv = hw->priv;
++ struct iwl_priv *priv = hw->priv;
+ DECLARE_MAC_BUF(mac);
+ unsigned long flags;
+ int rc;
+@@ -7682,6 +6471,11 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
+ if (conf == NULL)
+ return -EIO;
+
++ if (priv->vif != vif) {
++ IWL_DEBUG_MAC80211("leave - priv->vif != vif\n");
++ return 0;
++ }
++
+ if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
+ (!conf->beacon || !conf->ssid_len)) {
+ IWL_DEBUG_MAC80211
+@@ -7689,7 +6483,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
+ return 0;
+ }
+
+- if (!iwl4965_is_alive(priv))
++ if (!iwl_is_alive(priv))
+ return -EAGAIN;
+
+ mutex_lock(&priv->mutex);
+@@ -7704,17 +6498,6 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
+ if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) &&
+ !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) {
+ */
+- if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
+- IWL_DEBUG_MAC80211("leave - scanning\n");
+- mutex_unlock(&priv->mutex);
+- return 0;
+- }
+-
+- if (priv->vif != vif) {
+- IWL_DEBUG_MAC80211("leave - priv->vif != vif\n");
+- mutex_unlock(&priv->mutex);
+- return 0;
+- }
+
+ if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
+ if (!conf->bssid) {
+@@ -7729,7 +6512,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
+ priv->ibss_beacon = conf->beacon;
+ }
+
+- if (iwl4965_is_rfkill(priv))
++ if (iwl_is_rfkill(priv))
+ goto done;
+
+ if (conf->bssid && !is_zero_ether_addr(conf->bssid) &&
+@@ -7797,13 +6580,13 @@ static void iwl4965_configure_filter(struct ieee80211_hw *hw,
+ static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_init_conf *conf)
+ {
+- struct iwl4965_priv *priv = hw->priv;
++ struct iwl_priv *priv = hw->priv;
+
+ IWL_DEBUG_MAC80211("enter\n");
+
+ mutex_lock(&priv->mutex);
+
+- if (iwl4965_is_ready_rf(priv)) {
++ if (iwl_is_ready_rf(priv)) {
+ iwl4965_scan_cancel_timeout(priv, 100);
+ cancel_delayed_work(&priv->post_associate);
+ priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+@@ -7821,14 +6604,77 @@ static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw,
+
+ }
+
++
++#ifdef CONFIG_IWL4965_HT
++static void iwl4965_ht_conf(struct iwl_priv *priv,
++ struct ieee80211_bss_conf *bss_conf)
++{
++ struct ieee80211_ht_info *ht_conf = bss_conf->ht_conf;
++ struct ieee80211_ht_bss_info *ht_bss_conf = bss_conf->ht_bss_conf;
++ struct iwl_ht_info *iwl_conf = &priv->current_ht_config;
++
++ IWL_DEBUG_MAC80211("enter: \n");
++
++ iwl_conf->is_ht = bss_conf->assoc_ht;
++
++ if (!iwl_conf->is_ht)
++ return;
++
++ priv->ps_mode = (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2);
++
++ if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20)
++ iwl_conf->sgf |= 0x1;
++ if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40)
++ iwl_conf->sgf |= 0x2;
++
++ iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD);
++ iwl_conf->max_amsdu_size =
++ !!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU);
++
++ iwl_conf->supported_chan_width =
++ !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH);
++ iwl_conf->extension_chan_offset =
++ ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_SEC_OFFSET;
++ /* If no above or below channel supplied disable FAT channel */
++ if (iwl_conf->extension_chan_offset != IWL_EXT_CHANNEL_OFFSET_ABOVE &&
++ iwl_conf->extension_chan_offset != IWL_EXT_CHANNEL_OFFSET_BELOW)
++ iwl_conf->supported_chan_width = 0;
++
++ iwl_conf->tx_mimo_ps_mode =
++ (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2);
++ memcpy(iwl_conf->supp_mcs_set, ht_conf->supp_mcs_set, 16);
++
++ iwl_conf->control_channel = ht_bss_conf->primary_channel;
++ iwl_conf->tx_chan_width =
++ !!(ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_WIDTH);
++ iwl_conf->ht_protection =
++ ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_HT_PROTECTION;
++ iwl_conf->non_GF_STA_present =
++ !!(ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_NON_GF_STA_PRSNT);
++
++ IWL_DEBUG_MAC80211("control channel %d\n", iwl_conf->control_channel);
++ IWL_DEBUG_MAC80211("leave\n");
++}
++#else
++static inline void iwl4965_ht_conf(struct iwl_priv *priv,
++ struct ieee80211_bss_conf *bss_conf)
++{
++}
++#endif
++
++#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
+ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *bss_conf,
+ u32 changes)
+ {
+- struct iwl4965_priv *priv = hw->priv;
++ struct iwl_priv *priv = hw->priv;
++
++ IWL_DEBUG_MAC80211("changes = 0x%X\n", changes);
+
+ if (changes & BSS_CHANGED_ERP_PREAMBLE) {
++ IWL_DEBUG_MAC80211("ERP_PREAMBLE %d\n",
++ bss_conf->use_short_preamble);
+ if (bss_conf->use_short_preamble)
+ priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+ else
+@@ -7836,35 +6682,58 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw,
+ }
+
+ if (changes & BSS_CHANGED_ERP_CTS_PROT) {
+- if (bss_conf->use_cts_prot && (priv->phymode != MODE_IEEE80211A))
++ IWL_DEBUG_MAC80211("ERP_CTS %d\n", bss_conf->use_cts_prot);
++ if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
+ priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK;
+ else
+ priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
+ }
+
++ if (changes & BSS_CHANGED_HT) {
++ IWL_DEBUG_MAC80211("HT %d\n", bss_conf->assoc_ht);
++ iwl4965_ht_conf(priv, bss_conf);
++ iwl4965_set_rxon_chain(priv);
++ }
++
+ if (changes & BSS_CHANGED_ASSOC) {
+- /*
+- * TODO:
+- * do stuff instead of sniffing assoc resp
+- */
++ IWL_DEBUG_MAC80211("ASSOC %d\n", bss_conf->assoc);
++ /* This should never happen as this function should
++ * never be called from interrupt context. */
++ if (WARN_ON_ONCE(in_interrupt()))
++ return;
++ if (bss_conf->assoc) {
++ priv->assoc_id = bss_conf->aid;
++ priv->beacon_int = bss_conf->beacon_int;
++ priv->timestamp = bss_conf->timestamp;
++ priv->assoc_capability = bss_conf->assoc_capability;
++ priv->next_scan_jiffies = jiffies +
++ IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
++ mutex_lock(&priv->mutex);
++ iwl4965_post_associate(priv);
++ mutex_unlock(&priv->mutex);
++ } else {
++ priv->assoc_id = 0;
++ IWL_DEBUG_MAC80211("DISASSOC %d\n", bss_conf->assoc);
++ }
++ } else if (changes && iwl_is_associated(priv) && priv->assoc_id) {
++ IWL_DEBUG_MAC80211("Associated Changes %d\n", changes);
++ iwl_send_rxon_assoc(priv);
+ }
+
+- if (iwl4965_is_associated(priv))
+- iwl4965_send_rxon_assoc(priv);
+ }
+
+ static int iwl4965_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
+ {
+ int rc = 0;
+ unsigned long flags;
+- struct iwl4965_priv *priv = hw->priv;
++ struct iwl_priv *priv = hw->priv;
+
+ IWL_DEBUG_MAC80211("enter\n");
+
+ mutex_lock(&priv->mutex);
+ spin_lock_irqsave(&priv->lock, flags);
+
+- if (!iwl4965_is_ready_rf(priv)) {
++ if (!iwl_is_ready_rf(priv)) {
+ rc = -EIO;
+ IWL_DEBUG_MAC80211("leave - not ready or exit pending\n");
+ goto out_unlock;
+@@ -7910,18 +6779,67 @@ out_unlock:
+ return rc;
+ }
+
++static void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw,
++ struct ieee80211_key_conf *keyconf, const u8 *addr,
++ u32 iv32, u16 *phase1key)
++{
++ struct iwl_priv *priv = hw->priv;
++ u8 sta_id = IWL_INVALID_STATION;
++ unsigned long flags;
++ __le16 key_flags = 0;
++ int i;
++ DECLARE_MAC_BUF(mac);
++
++ IWL_DEBUG_MAC80211("enter\n");
++
++ sta_id = iwl4965_hw_find_station(priv, addr);
++ if (sta_id == IWL_INVALID_STATION) {
++ IWL_DEBUG_MAC80211("leave - %s not in station map.\n",
++ print_mac(mac, addr));
++ return;
++ }
++
++ iwl4965_scan_cancel_timeout(priv, 100);
++
++ key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
++ key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
++ key_flags &= ~STA_KEY_FLG_INVALID;
++
++ if (sta_id == priv->hw_params.bcast_sta_id)
++ key_flags |= STA_KEY_MULTICAST_MSK;
++
++ spin_lock_irqsave(&priv->sta_lock, flags);
++
++ priv->stations[sta_id].sta.key.key_flags = key_flags;
++ priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
++
++ for (i = 0; i < 5; i++)
++ priv->stations[sta_id].sta.key.tkip_rx_ttak[i] =
++ cpu_to_le16(phase1key[i]);
++
++ priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
++ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
++
++ iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
++
++ spin_unlock_irqrestore(&priv->sta_lock, flags);
++
++ IWL_DEBUG_MAC80211("leave\n");
++}
++
+ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ const u8 *local_addr, const u8 *addr,
+ struct ieee80211_key_conf *key)
+ {
+- struct iwl4965_priv *priv = hw->priv;
++ struct iwl_priv *priv = hw->priv;
+ DECLARE_MAC_BUF(mac);
+- int rc = 0;
+- u8 sta_id;
++ int ret = 0;
++ u8 sta_id = IWL_INVALID_STATION;
++ u8 is_default_wep_key = 0;
+
+ IWL_DEBUG_MAC80211("enter\n");
+
+- if (!iwl4965_param_hwcrypto) {
++ if (priv->cfg->mod_params->sw_crypto) {
+ IWL_DEBUG_MAC80211("leave - hwcrypto disabled\n");
+ return -EOPNOTSUPP;
+ }
+@@ -7935,53 +6853,61 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ IWL_DEBUG_MAC80211("leave - %s not in station map.\n",
+ print_mac(mac, addr));
+ return -EINVAL;
++
+ }
+
+ mutex_lock(&priv->mutex);
+-
+ iwl4965_scan_cancel_timeout(priv, 100);
++ mutex_unlock(&priv->mutex);
++
++ /* If we are getting WEP group key and we didn't receive any key mapping
++ * so far, we are in legacy wep mode (group key only), otherwise we are
++ * in 1X mode.
++ * In legacy wep mode, we use another host command to the uCode */
++ if (key->alg == ALG_WEP && sta_id == priv->hw_params.bcast_sta_id &&
++ priv->iw_mode != IEEE80211_IF_TYPE_AP) {
++ if (cmd == SET_KEY)
++ is_default_wep_key = !priv->key_mapping_key;
++ else
++ is_default_wep_key = priv->default_wep_key;
++ }
+
+ switch (cmd) {
+- case SET_KEY:
+- rc = iwl4965_update_sta_key_info(priv, key, sta_id);
+- if (!rc) {
+- iwl4965_set_rxon_hwcrypto(priv, 1);
+- iwl4965_commit_rxon(priv);
+- key->hw_key_idx = sta_id;
+- IWL_DEBUG_MAC80211("set_key success, using hwcrypto\n");
+- key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+- }
++ case SET_KEY:
++ if (is_default_wep_key)
++ ret = iwl_set_default_wep_key(priv, key);
++ else
++ ret = iwl_set_dynamic_key(priv, key, sta_id);
++
++ IWL_DEBUG_MAC80211("enable hwcrypto key\n");
+ break;
+ case DISABLE_KEY:
+- rc = iwl4965_clear_sta_key_info(priv, sta_id);
+- if (!rc) {
+- iwl4965_set_rxon_hwcrypto(priv, 0);
+- iwl4965_commit_rxon(priv);
+- IWL_DEBUG_MAC80211("disable hwcrypto key\n");
+- }
++ if (is_default_wep_key)
++ ret = iwl_remove_default_wep_key(priv, key);
++ else
++ ret = iwl_remove_dynamic_key(priv, sta_id);
++
++ IWL_DEBUG_MAC80211("disable hwcrypto key\n");
+ break;
+ default:
+- rc = -EINVAL;
++ ret = -EINVAL;
+ }
+
+ IWL_DEBUG_MAC80211("leave\n");
+- mutex_unlock(&priv->mutex);
+
+- return rc;
++ return ret;
+ }
+
+ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue,
+ const struct ieee80211_tx_queue_params *params)
+ {
+- struct iwl4965_priv *priv = hw->priv;
+-#ifdef CONFIG_IWL4965_QOS
++ struct iwl_priv *priv = hw->priv;
+ unsigned long flags;
+ int q;
+-#endif /* CONFIG_IWL4965_QOS */
+
+ IWL_DEBUG_MAC80211("enter\n");
+
+- if (!iwl4965_is_ready_rf(priv)) {
++ if (!iwl_is_ready_rf(priv)) {
+ IWL_DEBUG_MAC80211("leave - RF not ready\n");
+ return -EIO;
+ }
+@@ -7991,7 +6917,6 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue,
+ return 0;
+ }
+
+-#ifdef CONFIG_IWL4965_QOS
+ if (!priv->qos_data.qos_enable) {
+ priv->qos_data.qos_active = 0;
+ IWL_DEBUG_MAC80211("leave - qos not enabled\n");
+@@ -8005,7 +6930,7 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue,
+ priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max);
+ priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
+ priv->qos_data.def_qos_parm.ac[q].edca_txop =
+- cpu_to_le16((params->burst_time * 100));
++ cpu_to_le16((params->txop * 32));
+
+ priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
+ priv->qos_data.qos_active = 1;
+@@ -8015,13 +6940,11 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue,
+ mutex_lock(&priv->mutex);
+ if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
+ iwl4965_activate_qos(priv, 1);
+- else if (priv->assoc_id && iwl4965_is_associated(priv))
++ else if (priv->assoc_id && iwl_is_associated(priv))
+ iwl4965_activate_qos(priv, 0);
+
+ mutex_unlock(&priv->mutex);
+
+-#endif /*CONFIG_IWL4965_QOS */
+-
+ IWL_DEBUG_MAC80211("leave\n");
+ return 0;
+ }
+@@ -8029,7 +6952,7 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue,
+ static int iwl4965_mac_get_tx_stats(struct ieee80211_hw *hw,
+ struct ieee80211_tx_queue_stats *stats)
+ {
+- struct iwl4965_priv *priv = hw->priv;
++ struct iwl_priv *priv = hw->priv;
+ int i, avail;
+ struct iwl4965_tx_queue *txq;
+ struct iwl4965_queue *q;
+@@ -8037,7 +6960,7 @@ static int iwl4965_mac_get_tx_stats(struct ieee80211_hw *hw,
+
+ IWL_DEBUG_MAC80211("enter\n");
+
+- if (!iwl4965_is_ready_rf(priv)) {
++ if (!iwl_is_ready_rf(priv)) {
+ IWL_DEBUG_MAC80211("leave - RF not ready\n");
+ return -EIO;
+ }
+@@ -8080,7 +7003,7 @@ static u64 iwl4965_mac_get_tsf(struct ieee80211_hw *hw)
+
+ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
+ {
+- struct iwl4965_priv *priv = hw->priv;
++ struct iwl_priv *priv = hw->priv;
+ unsigned long flags;
+
+ mutex_lock(&priv->mutex);
+@@ -8091,30 +7014,15 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
+ spin_lock_irqsave(&priv->lock, flags);
+ memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info));
+ spin_unlock_irqrestore(&priv->lock, flags);
+-#ifdef CONFIG_IWL4965_HT_AGG
+-/* if (priv->lq_mngr.agg_ctrl.granted_ba)
+- iwl4965_turn_off_agg(priv, TID_ALL_SPECIFIED);*/
+-
+- memset(&(priv->lq_mngr.agg_ctrl), 0, sizeof(struct iwl4965_agg_control));
+- priv->lq_mngr.agg_ctrl.tid_traffic_load_threshold = 10;
+- priv->lq_mngr.agg_ctrl.ba_timeout = 5000;
+- priv->lq_mngr.agg_ctrl.auto_agg = 1;
+-
+- if (priv->lq_mngr.agg_ctrl.auto_agg)
+- priv->lq_mngr.agg_ctrl.requested_ba = TID_ALL_ENABLED;
+-#endif /*CONFIG_IWL4965_HT_AGG */
+ #endif /* CONFIG_IWL4965_HT */
+
+-#ifdef CONFIG_IWL4965_QOS
+- iwl4965_reset_qos(priv);
+-#endif
++ iwlcore_reset_qos(priv);
+
+ cancel_delayed_work(&priv->post_associate);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->assoc_id = 0;
+ priv->assoc_capability = 0;
+- priv->call_post_assoc_from_beacon = 0;
+ priv->assoc_station_added = 0;
+
+ /* new association get rid of ibss beacon skb */
+@@ -8124,14 +7032,13 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
+ priv->ibss_beacon = NULL;
+
+ priv->beacon_int = priv->hw->conf.beacon_int;
+- priv->timestamp1 = 0;
+- priv->timestamp0 = 0;
++ priv->timestamp = 0;
+ if ((priv->iw_mode == IEEE80211_IF_TYPE_STA))
+ priv->beacon_int = 0;
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+- if (!iwl4965_is_ready_rf(priv)) {
++ if (!iwl_is_ready_rf(priv)) {
+ IWL_DEBUG_MAC80211("leave - not ready\n");
+ mutex_unlock(&priv->mutex);
+ return;
+@@ -8166,13 +7073,13 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
+ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct ieee80211_tx_control *control)
+ {
+- struct iwl4965_priv *priv = hw->priv;
++ struct iwl_priv *priv = hw->priv;
+ unsigned long flags;
+
+ mutex_lock(&priv->mutex);
+ IWL_DEBUG_MAC80211("enter\n");
+
+- if (!iwl4965_is_ready_rf(priv)) {
++ if (!iwl_is_ready_rf(priv)) {
+ IWL_DEBUG_MAC80211("leave - RF not ready\n");
+ mutex_unlock(&priv->mutex);
+ return -EIO;
+@@ -8196,9 +7103,7 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
+ IWL_DEBUG_MAC80211("leave\n");
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+-#ifdef CONFIG_IWL4965_QOS
+- iwl4965_reset_qos(priv);
+-#endif
++ iwlcore_reset_qos(priv);
+
+ queue_work(priv->workqueue, &priv->post_associate.work);
+
+@@ -8207,111 +7112,13 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
+ return 0;
+ }
+
+-#ifdef CONFIG_IWL4965_HT
+-
+-static void iwl4965_ht_info_fill(struct ieee80211_conf *conf,
+- struct iwl4965_priv *priv)
+-{
+- struct iwl_ht_info *iwl_conf = &priv->current_ht_config;
+- struct ieee80211_ht_info *ht_conf = &conf->ht_conf;
+- struct ieee80211_ht_bss_info *ht_bss_conf = &conf->ht_bss_conf;
+-
+- IWL_DEBUG_MAC80211("enter: \n");
+-
+- if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) {
+- iwl_conf->is_ht = 0;
+- return;
+- }
+-
+- iwl_conf->is_ht = 1;
+- priv->ps_mode = (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2);
+-
+- if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20)
+- iwl_conf->sgf |= 0x1;
+- if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40)
+- iwl_conf->sgf |= 0x2;
+-
+- iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD);
+- iwl_conf->max_amsdu_size =
+- !!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU);
+- iwl_conf->supported_chan_width =
+- !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH);
+- iwl_conf->tx_mimo_ps_mode =
+- (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2);
+- memcpy(iwl_conf->supp_mcs_set, ht_conf->supp_mcs_set, 16);
+-
+- iwl_conf->control_channel = ht_bss_conf->primary_channel;
+- iwl_conf->extension_chan_offset =
+- ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_SEC_OFFSET;
+- iwl_conf->tx_chan_width =
+- !!(ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_WIDTH);
+- iwl_conf->ht_protection =
+- ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_HT_PROTECTION;
+- iwl_conf->non_GF_STA_present =
+- !!(ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_NON_GF_STA_PRSNT);
+-
+- IWL_DEBUG_MAC80211("control channel %d\n",
+- iwl_conf->control_channel);
+- IWL_DEBUG_MAC80211("leave\n");
+-}
+-
+-static int iwl4965_mac_conf_ht(struct ieee80211_hw *hw,
+- struct ieee80211_conf *conf)
+-{
+- struct iwl4965_priv *priv = hw->priv;
+-
+- IWL_DEBUG_MAC80211("enter: \n");
+-
+- iwl4965_ht_info_fill(conf, priv);
+- iwl4965_set_rxon_chain(priv);
+-
+- if (priv && priv->assoc_id &&
+- (priv->iw_mode == IEEE80211_IF_TYPE_STA)) {
+- unsigned long flags;
+-
+- spin_lock_irqsave(&priv->lock, flags);
+- if (priv->beacon_int)
+- queue_work(priv->workqueue, &priv->post_associate.work);
+- else
+- priv->call_post_assoc_from_beacon = 1;
+- spin_unlock_irqrestore(&priv->lock, flags);
+- }
+-
+- IWL_DEBUG_MAC80211("leave:\n");
+- return 0;
+-}
+-
+-static void iwl4965_set_ht_capab(struct ieee80211_hw *hw,
+- struct ieee80211_ht_cap *ht_cap,
+- u8 use_current_config)
+-{
+- struct ieee80211_conf *conf = &hw->conf;
+- struct ieee80211_hw_mode *mode = conf->mode;
+-
+- if (use_current_config) {
+- ht_cap->cap_info = cpu_to_le16(conf->ht_conf.cap);
+- memcpy(ht_cap->supp_mcs_set,
+- conf->ht_conf.supp_mcs_set, 16);
+- } else {
+- ht_cap->cap_info = cpu_to_le16(mode->ht_info.cap);
+- memcpy(ht_cap->supp_mcs_set,
+- mode->ht_info.supp_mcs_set, 16);
+- }
+- ht_cap->ampdu_params_info =
+- (mode->ht_info.ampdu_factor & IEEE80211_HT_CAP_AMPDU_FACTOR) |
+- ((mode->ht_info.ampdu_density << 2) &
+- IEEE80211_HT_CAP_AMPDU_DENSITY);
+-}
+-
+-#endif /*CONFIG_IWL4965_HT*/
+-
+ /*****************************************************************************
+ *
+ * sysfs attributes
+ *
+ *****************************************************************************/
+
+-#ifdef CONFIG_IWL4965_DEBUG
++#ifdef CONFIG_IWLWIFI_DEBUG
+
+ /*
+ * The following adds a new attribute to the sysfs representation
+@@ -8323,7 +7130,7 @@ static void iwl4965_set_ht_capab(struct ieee80211_hw *hw,
+
+ static ssize_t show_debug_level(struct device_driver *d, char *buf)
+ {
+- return sprintf(buf, "0x%08X\n", iwl4965_debug_level);
++ return sprintf(buf, "0x%08X\n", iwl_debug_level);
+ }
+ static ssize_t store_debug_level(struct device_driver *d,
+ const char *buf, size_t count)
+@@ -8336,7 +7143,7 @@ static ssize_t store_debug_level(struct device_driver *d,
+ printk(KERN_INFO DRV_NAME
+ ": %s is not in hex or decimal form.\n", buf);
+ else
+- iwl4965_debug_level = val;
++ iwl_debug_level = val;
+
+ return strnlen(buf, count);
+ }
+@@ -8344,45 +7151,15 @@ static ssize_t store_debug_level(struct device_driver *d,
+ static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
+ show_debug_level, store_debug_level);
+
+-#endif /* CONFIG_IWL4965_DEBUG */
+-
+-static ssize_t show_rf_kill(struct device *d,
+- struct device_attribute *attr, char *buf)
+-{
+- /*
+- * 0 - RF kill not enabled
+- * 1 - SW based RF kill active (sysfs)
+- * 2 - HW based RF kill active
+- * 3 - Both HW and SW based RF kill active
+- */
+- struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
+- int val = (test_bit(STATUS_RF_KILL_SW, &priv->status) ? 0x1 : 0x0) |
+- (test_bit(STATUS_RF_KILL_HW, &priv->status) ? 0x2 : 0x0);
+-
+- return sprintf(buf, "%i\n", val);
+-}
+-
+-static ssize_t store_rf_kill(struct device *d,
+- struct device_attribute *attr,
+- const char *buf, size_t count)
+-{
+- struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
++#endif /* CONFIG_IWLWIFI_DEBUG */
+
+- mutex_lock(&priv->mutex);
+- iwl4965_radio_kill_sw(priv, buf[0] == '1');
+- mutex_unlock(&priv->mutex);
+-
+- return count;
+-}
+-
+-static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill);
+
+ static ssize_t show_temperature(struct device *d,
+ struct device_attribute *attr, char *buf)
+ {
+- struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
++ struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+
+- if (!iwl4965_is_alive(priv))
++ if (!iwl_is_alive(priv))
+ return -EAGAIN;
+
+ return sprintf(buf, "%d\n", iwl4965_hw_get_temperature(priv));
+@@ -8394,7 +7171,7 @@ static ssize_t show_rs_window(struct device *d,
+ struct device_attribute *attr,
+ char *buf)
+ {
+- struct iwl4965_priv *priv = d->driver_data;
++ struct iwl_priv *priv = d->driver_data;
+ return iwl4965_fill_rs_info(priv->hw, buf, IWL_AP_ID);
+ }
+ static DEVICE_ATTR(rs_window, S_IRUGO, show_rs_window, NULL);
+@@ -8402,7 +7179,7 @@ static DEVICE_ATTR(rs_window, S_IRUGO, show_rs_window, NULL);
+ static ssize_t show_tx_power(struct device *d,
+ struct device_attribute *attr, char *buf)
+ {
+- struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
++ struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ return sprintf(buf, "%d\n", priv->user_txpower_limit);
+ }
+
+@@ -8410,7 +7187,7 @@ static ssize_t store_tx_power(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+ {
+- struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
++ struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ char *p = (char *)buf;
+ u32 val;
+
+@@ -8429,7 +7206,7 @@ static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
+ static ssize_t show_flags(struct device *d,
+ struct device_attribute *attr, char *buf)
+ {
+- struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
++ struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+
+ return sprintf(buf, "0x%04X\n", priv->active_rxon.flags);
+ }
+@@ -8438,7 +7215,7 @@ static ssize_t store_flags(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+ {
+- struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
++ struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ u32 flags = simple_strtoul(buf, NULL, 0);
+
+ mutex_lock(&priv->mutex);
+@@ -8463,7 +7240,7 @@ static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags);
+ static ssize_t show_filter_flags(struct device *d,
+ struct device_attribute *attr, char *buf)
+ {
+- struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
++ struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+
+ return sprintf(buf, "0x%04X\n",
+ le32_to_cpu(priv->active_rxon.filter_flags));
+@@ -8473,7 +7250,7 @@ static ssize_t store_filter_flags(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+ {
+- struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
++ struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ u32 filter_flags = simple_strtoul(buf, NULL, 0);
+
+ mutex_lock(&priv->mutex);
+@@ -8497,71 +7274,12 @@ static ssize_t store_filter_flags(struct device *d,
+ static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
+ store_filter_flags);
+
+-static ssize_t show_tune(struct device *d,
+- struct device_attribute *attr, char *buf)
+-{
+- struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
+-
+- return sprintf(buf, "0x%04X\n",
+- (priv->phymode << 8) |
+- le16_to_cpu(priv->active_rxon.channel));
+-}
+-
+-static void iwl4965_set_flags_for_phymode(struct iwl4965_priv *priv, u8 phymode);
+-
+-static ssize_t store_tune(struct device *d,
+- struct device_attribute *attr,
+- const char *buf, size_t count)
+-{
+- struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
+- char *p = (char *)buf;
+- u16 tune = simple_strtoul(p, &p, 0);
+- u8 phymode = (tune >> 8) & 0xff;
+- u16 channel = tune & 0xff;
+-
+- IWL_DEBUG_INFO("Tune request to:%d channel:%d\n", phymode, channel);
+-
+- mutex_lock(&priv->mutex);
+- if ((le16_to_cpu(priv->staging_rxon.channel) != channel) ||
+- (priv->phymode != phymode)) {
+- const struct iwl4965_channel_info *ch_info;
+-
+- ch_info = iwl4965_get_channel_info(priv, phymode, channel);
+- if (!ch_info) {
+- IWL_WARNING("Requested invalid phymode/channel "
+- "combination: %d %d\n", phymode, channel);
+- mutex_unlock(&priv->mutex);
+- return -EINVAL;
+- }
+-
+- /* Cancel any currently running scans... */
+- if (iwl4965_scan_cancel_timeout(priv, 100))
+- IWL_WARNING("Could not cancel scan.\n");
+- else {
+- IWL_DEBUG_INFO("Committing phymode and "
+- "rxon.channel = %d %d\n",
+- phymode, channel);
+-
+- iwl4965_set_rxon_channel(priv, phymode, channel);
+- iwl4965_set_flags_for_phymode(priv, phymode);
+-
+- iwl4965_set_rate(priv);
+- iwl4965_commit_rxon(priv);
+- }
+- }
+- mutex_unlock(&priv->mutex);
+-
+- return count;
+-}
+-
+-static DEVICE_ATTR(tune, S_IWUSR | S_IRUGO, show_tune, store_tune);
+-
+ #ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
+
+ static ssize_t show_measurement(struct device *d,
+ struct device_attribute *attr, char *buf)
+ {
+- struct iwl4965_priv *priv = dev_get_drvdata(d);
++ struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl4965_spectrum_notification measure_report;
+ u32 size = sizeof(measure_report), len = 0, ofs = 0;
+ u8 *data = (u8 *) & measure_report;
+@@ -8594,7 +7312,7 @@ static ssize_t store_measurement(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+ {
+- struct iwl4965_priv *priv = dev_get_drvdata(d);
++ struct iwl_priv *priv = dev_get_drvdata(d);
+ struct ieee80211_measurement_params params = {
+ .channel = le16_to_cpu(priv->active_rxon.channel),
+ .start_time = cpu_to_le64(priv->last_tsf),
+@@ -8633,7 +7351,7 @@ static ssize_t store_retry_rate(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+ {
+- struct iwl4965_priv *priv = dev_get_drvdata(d);
++ struct iwl_priv *priv = dev_get_drvdata(d);
+
+ priv->retry_rate = simple_strtoul(buf, NULL, 0);
+ if (priv->retry_rate <= 0)
+@@ -8645,7 +7363,7 @@ static ssize_t store_retry_rate(struct device *d,
+ static ssize_t show_retry_rate(struct device *d,
+ struct device_attribute *attr, char *buf)
+ {
+- struct iwl4965_priv *priv = dev_get_drvdata(d);
++ struct iwl_priv *priv = dev_get_drvdata(d);
+ return sprintf(buf, "%d", priv->retry_rate);
+ }
+
+@@ -8656,14 +7374,14 @@ static ssize_t store_power_level(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+ {
+- struct iwl4965_priv *priv = dev_get_drvdata(d);
++ struct iwl_priv *priv = dev_get_drvdata(d);
+ int rc;
+ int mode;
+
+ mode = simple_strtoul(buf, NULL, 0);
+ mutex_lock(&priv->mutex);
+
+- if (!iwl4965_is_ready(priv)) {
++ if (!iwl_is_ready(priv)) {
+ rc = -EAGAIN;
+ goto out;
+ }
+@@ -8710,7 +7428,7 @@ static const s32 period_duration[] = {
+ static ssize_t show_power_level(struct device *d,
+ struct device_attribute *attr, char *buf)
+ {
+- struct iwl4965_priv *priv = dev_get_drvdata(d);
++ struct iwl_priv *priv = dev_get_drvdata(d);
+ int level = IWL_POWER_LEVEL(priv->power_mode);
+ char *p = buf;
+
+@@ -8745,73 +7463,8 @@ static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level,
+ static ssize_t show_channels(struct device *d,
+ struct device_attribute *attr, char *buf)
+ {
+- struct iwl4965_priv *priv = dev_get_drvdata(d);
+- int len = 0, i;
+- struct ieee80211_channel *channels = NULL;
+- const struct ieee80211_hw_mode *hw_mode = NULL;
+- int count = 0;
+-
+- if (!iwl4965_is_ready(priv))
+- return -EAGAIN;
+-
+- hw_mode = iwl4965_get_hw_mode(priv, MODE_IEEE80211G);
+- if (!hw_mode)
+- hw_mode = iwl4965_get_hw_mode(priv, MODE_IEEE80211B);
+- if (hw_mode) {
+- channels = hw_mode->channels;
+- count = hw_mode->num_channels;
+- }
+-
+- len +=
+- sprintf(&buf[len],
+- "Displaying %d channels in 2.4GHz band "
+- "(802.11bg):\n", count);
+-
+- for (i = 0; i < count; i++)
+- len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
+- channels[i].chan,
+- channels[i].power_level,
+- channels[i].
+- flag & IEEE80211_CHAN_W_RADAR_DETECT ?
+- " (IEEE 802.11h required)" : "",
+- (!(channels[i].flag & IEEE80211_CHAN_W_IBSS)
+- || (channels[i].
+- flag &
+- IEEE80211_CHAN_W_RADAR_DETECT)) ? "" :
+- ", IBSS",
+- channels[i].
+- flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
+- "active/passive" : "passive only");
+-
+- hw_mode = iwl4965_get_hw_mode(priv, MODE_IEEE80211A);
+- if (hw_mode) {
+- channels = hw_mode->channels;
+- count = hw_mode->num_channels;
+- } else {
+- channels = NULL;
+- count = 0;
+- }
+-
+- len += sprintf(&buf[len], "Displaying %d channels in 5.2GHz band "
+- "(802.11a):\n", count);
+-
+- for (i = 0; i < count; i++)
+- len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
+- channels[i].chan,
+- channels[i].power_level,
+- channels[i].
+- flag & IEEE80211_CHAN_W_RADAR_DETECT ?
+- " (IEEE 802.11h required)" : "",
+- (!(channels[i].flag & IEEE80211_CHAN_W_IBSS)
+- || (channels[i].
+- flag &
+- IEEE80211_CHAN_W_RADAR_DETECT)) ? "" :
+- ", IBSS",
+- channels[i].
+- flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
+- "active/passive" : "passive only");
+-
+- return len;
++ /* all this shit doesn't belong into sysfs anyway */
++ return 0;
+ }
+
+ static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
+@@ -8819,17 +7472,17 @@ static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
+ static ssize_t show_statistics(struct device *d,
+ struct device_attribute *attr, char *buf)
+ {
+- struct iwl4965_priv *priv = dev_get_drvdata(d);
++ struct iwl_priv *priv = dev_get_drvdata(d);
+ u32 size = sizeof(struct iwl4965_notif_statistics);
+ u32 len = 0, ofs = 0;
+ u8 *data = (u8 *) & priv->statistics;
+ int rc = 0;
+
+- if (!iwl4965_is_alive(priv))
++ if (!iwl_is_alive(priv))
+ return -EAGAIN;
+
+ mutex_lock(&priv->mutex);
+- rc = iwl4965_send_statistics_request(priv);
++ rc = iwl_send_statistics_request(priv, 0);
+ mutex_unlock(&priv->mutex);
+
+ if (rc) {
+@@ -8857,9 +7510,9 @@ static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL);
+ static ssize_t show_antenna(struct device *d,
+ struct device_attribute *attr, char *buf)
+ {
+- struct iwl4965_priv *priv = dev_get_drvdata(d);
++ struct iwl_priv *priv = dev_get_drvdata(d);
+
+- if (!iwl4965_is_alive(priv))
++ if (!iwl_is_alive(priv))
+ return -EAGAIN;
+
+ return sprintf(buf, "%d\n", priv->antenna);
+@@ -8870,7 +7523,7 @@ static ssize_t store_antenna(struct device *d,
+ const char *buf, size_t count)
+ {
+ int ant;
+- struct iwl4965_priv *priv = dev_get_drvdata(d);
++ struct iwl_priv *priv = dev_get_drvdata(d);
+
+ if (count == 0)
+ return 0;
+@@ -8895,8 +7548,8 @@ static DEVICE_ATTR(antenna, S_IWUSR | S_IRUGO, show_antenna, store_antenna);
+ static ssize_t show_status(struct device *d,
+ struct device_attribute *attr, char *buf)
+ {
+- struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
+- if (!iwl4965_is_alive(priv))
++ struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
++ if (!iwl_is_alive(priv))
+ return -EAGAIN;
+ return sprintf(buf, "0x%08x\n", (int)priv->status);
+ }
+@@ -8910,7 +7563,7 @@ static ssize_t dump_error_log(struct device *d,
+ char *p = (char *)buf;
+
+ if (p[0] == '1')
+- iwl4965_dump_nic_error_log((struct iwl4965_priv *)d->driver_data);
++ iwl4965_dump_nic_error_log((struct iwl_priv *)d->driver_data);
+
+ return strnlen(buf, count);
+ }
+@@ -8924,7 +7577,7 @@ static ssize_t dump_event_log(struct device *d,
+ char *p = (char *)buf;
+
+ if (p[0] == '1')
+- iwl4965_dump_nic_event_log((struct iwl4965_priv *)d->driver_data);
++ iwl4965_dump_nic_event_log((struct iwl_priv *)d->driver_data);
+
+ return strnlen(buf, count);
+ }
+@@ -8937,7 +7590,7 @@ static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log);
+ *
+ *****************************************************************************/
+
+-static void iwl4965_setup_deferred_work(struct iwl4965_priv *priv)
++static void iwl4965_setup_deferred_work(struct iwl_priv *priv)
+ {
+ priv->workqueue = create_workqueue(DRV_NAME);
+
+@@ -8962,7 +7615,7 @@ static void iwl4965_setup_deferred_work(struct iwl4965_priv *priv)
+ iwl4965_irq_tasklet, (unsigned long)priv);
+ }
+
+-static void iwl4965_cancel_deferred_work(struct iwl4965_priv *priv)
++static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
+ {
+ iwl4965_hw_cancel_deferred_work(priv);
+
+@@ -8985,12 +7638,10 @@ static struct attribute *iwl4965_sysfs_entries[] = {
+ #endif
+ &dev_attr_power_level.attr,
+ &dev_attr_retry_rate.attr,
+- &dev_attr_rf_kill.attr,
+ &dev_attr_rs_window.attr,
+ &dev_attr_statistics.attr,
+ &dev_attr_status.attr,
+ &dev_attr_temperature.attr,
+- &dev_attr_tune.attr,
+ &dev_attr_tx_power.attr,
+
+ NULL
+@@ -9011,6 +7662,7 @@ static struct ieee80211_ops iwl4965_hw_ops = {
+ .config_interface = iwl4965_mac_config_interface,
+ .configure_filter = iwl4965_configure_filter,
+ .set_key = iwl4965_mac_set_key,
++ .update_tkip_key = iwl4965_mac_update_tkip_key,
+ .get_stats = iwl4965_mac_get_stats,
+ .get_tx_stats = iwl4965_mac_get_tx_stats,
+ .conf_tx = iwl4965_mac_conf_tx,
+@@ -9019,12 +7671,7 @@ static struct ieee80211_ops iwl4965_hw_ops = {
+ .beacon_update = iwl4965_mac_beacon_update,
+ .bss_info_changed = iwl4965_bss_info_changed,
+ #ifdef CONFIG_IWL4965_HT
+- .conf_ht = iwl4965_mac_conf_ht,
+ .ampdu_action = iwl4965_mac_ampdu_action,
+-#ifdef CONFIG_IWL4965_HT_AGG
+- .ht_tx_agg_start = iwl4965_mac_ht_tx_agg_start,
+- .ht_tx_agg_stop = iwl4965_mac_ht_tx_agg_stop,
+-#endif /* CONFIG_IWL4965_HT_AGG */
+ #endif /* CONFIG_IWL4965_HT */
+ .hw_scan = iwl4965_mac_hw_scan
+ };
+@@ -9032,85 +7679,45 @@ static struct ieee80211_ops iwl4965_hw_ops = {
+ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
+ int err = 0;
+- struct iwl4965_priv *priv;
++ struct iwl_priv *priv;
+ struct ieee80211_hw *hw;
+- int i;
++ struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
++ unsigned long flags;
+ DECLARE_MAC_BUF(mac);
+
++ /************************
++ * 1. Allocating HW data
++ ************************/
++
+ /* Disabling hardware scan means that mac80211 will perform scans
+ * "the hard way", rather than using device's scan. */
+- if (iwl4965_param_disable_hw_scan) {
++ if (cfg->mod_params->disable_hw_scan) {
+ IWL_DEBUG_INFO("Disabling hw_scan\n");
+ iwl4965_hw_ops.hw_scan = NULL;
+ }
+
+- if ((iwl4965_param_queues_num > IWL_MAX_NUM_QUEUES) ||
+- (iwl4965_param_queues_num < IWL_MIN_NUM_QUEUES)) {
+- IWL_ERROR("invalid queues_num, should be between %d and %d\n",
+- IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES);
+- err = -EINVAL;
+- goto out;
+- }
+-
+- /* mac80211 allocates memory for this device instance, including
+- * space for this driver's private structure */
+- hw = ieee80211_alloc_hw(sizeof(struct iwl4965_priv), &iwl4965_hw_ops);
+- if (hw == NULL) {
+- IWL_ERROR("Can not allocate network device\n");
++ hw = iwl_alloc_all(cfg, &iwl4965_hw_ops);
++ if (!hw) {
+ err = -ENOMEM;
+ goto out;
+ }
+- SET_IEEE80211_DEV(hw, &pdev->dev);
++ priv = hw->priv;
++ /* At this point both hw and priv are allocated. */
+
+- hw->rate_control_algorithm = "iwl-4965-rs";
++ SET_IEEE80211_DEV(hw, &pdev->dev);
+
+ IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
+- priv = hw->priv;
+- priv->hw = hw;
+-
++ priv->cfg = cfg;
+ priv->pci_dev = pdev;
+- priv->antenna = (enum iwl4965_antenna)iwl4965_param_antenna;
+-#ifdef CONFIG_IWL4965_DEBUG
+- iwl4965_debug_level = iwl4965_param_debug;
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++ iwl_debug_level = priv->cfg->mod_params->debug;
+ atomic_set(&priv->restrict_refcnt, 0);
+ #endif
+- priv->retry_rate = 1;
+-
+- priv->ibss_beacon = NULL;
+-
+- /* Tell mac80211 and its clients (e.g. Wireless Extensions)
+- * the range of signal quality values that we'll provide.
+- * Negative values for level/noise indicate that we'll provide dBm.
+- * For WE, at least, non-0 values here *enable* display of values
+- * in app (iwconfig). */
+- hw->max_rssi = -20; /* signal level, negative indicates dBm */
+- hw->max_noise = -20; /* noise level, negative indicates dBm */
+- hw->max_signal = 100; /* link quality indication (%) */
+
+- /* Tell mac80211 our Tx characteristics */
+- hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
+-
+- /* Default value; 4 EDCA QOS priorities */
+- hw->queues = 4;
+-#ifdef CONFIG_IWL4965_HT
+-#ifdef CONFIG_IWL4965_HT_AGG
+- /* Enhanced value; more queues, to support 11n aggregation */
+- hw->queues = 16;
+-#endif /* CONFIG_IWL4965_HT_AGG */
+-#endif /* CONFIG_IWL4965_HT */
+-
+- spin_lock_init(&priv->lock);
+- spin_lock_init(&priv->power_data.lock);
+- spin_lock_init(&priv->sta_lock);
+- spin_lock_init(&priv->hcmd_lock);
+- spin_lock_init(&priv->lq_mngr.lock);
+-
+- for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++)
+- INIT_LIST_HEAD(&priv->ibss_mac_hash[i]);
+-
+- INIT_LIST_HEAD(&priv->free_frames);
+-
+- mutex_init(&priv->mutex);
++ /**************************
++ * 2. Initializing PCI bus
++ **************************/
+ if (pci_enable_device(pdev)) {
+ err = -ENODEV;
+ goto out_ieee80211_free_hw;
+@@ -9118,31 +7725,28 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+
+ pci_set_master(pdev);
+
+- /* Clear the driver's (not device's) station table */
+- iwl4965_clear_stations_table(priv);
+-
+- priv->data_retry_limit = -1;
+- priv->ieee_channels = NULL;
+- priv->ieee_rates = NULL;
+- priv->phymode = -1;
+-
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (!err)
+ err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+- if (err) {
+- printk(KERN_WARNING DRV_NAME ": No suitable DMA available.\n");
+- goto out_pci_disable_device;
++ if (err) {
++ printk(KERN_WARNING DRV_NAME
++ ": No suitable DMA available.\n");
++ goto out_pci_disable_device;
+ }
+
+- pci_set_drvdata(pdev, priv);
+ err = pci_request_regions(pdev, DRV_NAME);
+ if (err)
+ goto out_pci_disable_device;
+
++ pci_set_drvdata(pdev, priv);
++
+ /* We disable the RETRY_TIMEOUT register (0x41) to keep
+ * PCI Tx retries from interfering with C3 CPU state */
+ pci_write_config_byte(pdev, 0x41, 0x00);
+
++ /***********************
++ * 3. Read REV register
++ ***********************/
+ priv->hw_base = pci_iomap(pdev, 0, 0);
+ if (!priv->hw_base) {
+ err = -ENODEV;
+@@ -9150,132 +7754,112 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+ }
+
+ IWL_DEBUG_INFO("pci_resource_len = 0x%08llx\n",
+- (unsigned long long) pci_resource_len(pdev, 0));
++ (unsigned long long) pci_resource_len(pdev, 0));
+ IWL_DEBUG_INFO("pci_resource_base = %p\n", priv->hw_base);
+
+- /* Initialize module parameter values here */
++ printk(KERN_INFO DRV_NAME
++ ": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name);
+
+- /* Disable radio (SW RF KILL) via parameter when loading driver */
+- if (iwl4965_param_disable) {
+- set_bit(STATUS_RF_KILL_SW, &priv->status);
+- IWL_DEBUG_INFO("Radio disabled.\n");
++ /*****************
++ * 4. Read EEPROM
++ *****************/
++ /* nic init */
++ iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
++ CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
++
++ iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
++ err = iwl_poll_bit(priv, CSR_GP_CNTRL,
++ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
++ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
++ if (err < 0) {
++ IWL_DEBUG_INFO("Failed to init the card\n");
++ goto out_iounmap;
+ }
++ /* Read the EEPROM */
++ err = iwl_eeprom_init(priv);
++ if (err) {
++ IWL_ERROR("Unable to init EEPROM\n");
++ goto out_iounmap;
++ }
++ /* MAC Address location in EEPROM same for 3945/4965 */
++ iwl_eeprom_get_mac(priv, priv->mac_addr);
++ IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
++ SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
+
+- priv->iw_mode = IEEE80211_IF_TYPE_STA;
+-
+- priv->ps_mode = 0;
+- priv->use_ant_b_for_management_frame = 1; /* start with ant B */
+- priv->valid_antenna = 0x7; /* assume all 3 connected */
+- priv->ps_mode = IWL_MIMO_PS_NONE;
+-
+- /* Choose which receivers/antennas to use */
+- iwl4965_set_rxon_chain(priv);
+-
+- printk(KERN_INFO DRV_NAME
+- ": Detected Intel Wireless WiFi Link 4965AGN\n");
+-
++ /************************
++ * 5. Setup HW constants
++ ************************/
+ /* Device-specific setup */
+- if (iwl4965_hw_set_hw_setting(priv)) {
+- IWL_ERROR("failed to set hw settings\n");
++ if (priv->cfg->ops->lib->set_hw_params(priv)) {
++ IWL_ERROR("failed to set hw parameters\n");
+ goto out_iounmap;
+ }
+
+-#ifdef CONFIG_IWL4965_QOS
+- if (iwl4965_param_qos_enable)
+- priv->qos_data.qos_enable = 1;
++ /*******************
++ * 6. Setup hw/priv
++ *******************/
+
+- iwl4965_reset_qos(priv);
++ err = iwl_setup(priv);
++ if (err)
++ goto out_unset_hw_params;
++ /* At this point both hw and priv are initialized. */
+
+- priv->qos_data.qos_active = 0;
+- priv->qos_data.qos_cap.val = 0;
+-#endif /* CONFIG_IWL4965_QOS */
++ /**********************************
++ * 7. Initialize module parameters
++ **********************************/
+
+- iwl4965_set_rxon_channel(priv, MODE_IEEE80211G, 6);
+- iwl4965_setup_deferred_work(priv);
+- iwl4965_setup_rx_handlers(priv);
++ /* Disable radio (SW RF KILL) via parameter when loading driver */
++ if (priv->cfg->mod_params->disable) {
++ set_bit(STATUS_RF_KILL_SW, &priv->status);
++ IWL_DEBUG_INFO("Radio disabled.\n");
++ }
+
+- priv->rates_mask = IWL_RATES_MASK;
+- /* If power management is turned on, default to AC mode */
+- priv->power_mode = IWL_POWER_AC;
+- priv->user_txpower_limit = IWL_DEFAULT_TX_POWER;
++ if (priv->cfg->mod_params->enable_qos)
++ priv->qos_data.qos_enable = 1;
+
++ /********************
++ * 8. Setup services
++ ********************/
++ spin_lock_irqsave(&priv->lock, flags);
+ iwl4965_disable_interrupts(priv);
++ spin_unlock_irqrestore(&priv->lock, flags);
+
+ err = sysfs_create_group(&pdev->dev.kobj, &iwl4965_attribute_group);
+ if (err) {
+ IWL_ERROR("failed to create sysfs device attributes\n");
+- goto out_release_irq;
+- }
+-
+- /* nic init */
+- iwl4965_set_bit(priv, CSR_GIO_CHICKEN_BITS,
+- CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
+-
+- iwl4965_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+- err = iwl4965_poll_bit(priv, CSR_GP_CNTRL,
+- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
+- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
+- if (err < 0) {
+- IWL_DEBUG_INFO("Failed to init the card\n");
+- goto out_remove_sysfs;
+- }
+- /* Read the EEPROM */
+- err = iwl4965_eeprom_init(priv);
+- if (err) {
+- IWL_ERROR("Unable to init EEPROM\n");
+- goto out_remove_sysfs;
++ goto out_unset_hw_params;
+ }
+- /* MAC Address location in EEPROM same for 3945/4965 */
+- get_eeprom_mac(priv, priv->mac_addr);
+- IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
+- SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
+
+- err = iwl4965_init_channel_map(priv);
++ err = iwl_dbgfs_register(priv, DRV_NAME);
+ if (err) {
+- IWL_ERROR("initializing regulatory failed: %d\n", err);
++ IWL_ERROR("failed to create debugfs files\n");
+ goto out_remove_sysfs;
+ }
+
+- err = iwl4965_init_geos(priv);
+- if (err) {
+- IWL_ERROR("initializing geos failed: %d\n", err);
+- goto out_free_channel_map;
+- }
+- iwl4965_reset_channel_flag(priv);
+-
+- iwl4965_rate_control_register(priv->hw);
+- err = ieee80211_register_hw(priv->hw);
+- if (err) {
+- IWL_ERROR("Failed to register network device (error %d)\n", err);
+- goto out_free_geos;
+- }
++ iwl4965_setup_deferred_work(priv);
++ iwl4965_setup_rx_handlers(priv);
+
+- priv->hw->conf.beacon_int = 100;
+- priv->mac80211_registered = 1;
++ /********************
++ * 9. Conclude
++ ********************/
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+
++ /* notify iwlcore to init */
++ iwlcore_low_level_notify(priv, IWLCORE_INIT_EVT);
+ return 0;
+
+- out_free_geos:
+- iwl4965_free_geos(priv);
+- out_free_channel_map:
+- iwl4965_free_channel_map(priv);
+ out_remove_sysfs:
+ sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
+-
+- out_release_irq:
+- destroy_workqueue(priv->workqueue);
+- priv->workqueue = NULL;
+- iwl4965_unset_hw_setting(priv);
+-
++ out_unset_hw_params:
++ iwl4965_unset_hw_params(priv);
+ out_iounmap:
+ pci_iounmap(pdev, priv->hw_base);
+ out_pci_release_regions:
+ pci_release_regions(pdev);
++ pci_set_drvdata(pdev, NULL);
+ out_pci_disable_device:
+ pci_disable_device(pdev);
+- pci_set_drvdata(pdev, NULL);
+ out_ieee80211_free_hw:
+ ieee80211_free_hw(priv->hw);
+ out:
+@@ -9284,19 +7868,34 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+
+ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
+ {
+- struct iwl4965_priv *priv = pci_get_drvdata(pdev);
++ struct iwl_priv *priv = pci_get_drvdata(pdev);
+ struct list_head *p, *q;
+ int i;
++ unsigned long flags;
+
+ if (!priv)
+ return;
+
+ IWL_DEBUG_INFO("*** UNLOAD DRIVER ***\n");
+
++ if (priv->mac80211_registered) {
++ ieee80211_unregister_hw(priv->hw);
++ priv->mac80211_registered = 0;
++ }
++
+ set_bit(STATUS_EXIT_PENDING, &priv->status);
+
+ iwl4965_down(priv);
+
++ /* make sure we flush any pending irq or
++ * tasklet for the driver
++ */
++ spin_lock_irqsave(&priv->lock, flags);
++ iwl4965_disable_interrupts(priv);
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ iwl_synchronize_irq(priv);
++
+ /* Free MAC hash list for ADHOC */
+ for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) {
+ list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) {
+@@ -9305,6 +7904,8 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
+ }
+ }
+
++ iwlcore_low_level_notify(priv, IWLCORE_REMOVE_EVT);
++ iwl_dbgfs_unregister(priv);
+ sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
+
+ iwl4965_dealloc_ucode_pci(priv);
+@@ -9313,13 +7914,9 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
+ iwl4965_rx_queue_free(priv, &priv->rxq);
+ iwl4965_hw_txq_ctx_free(priv);
+
+- iwl4965_unset_hw_setting(priv);
+- iwl4965_clear_stations_table(priv);
++ iwl4965_unset_hw_params(priv);
++ iwlcore_clear_stations_table(priv);
+
+- if (priv->mac80211_registered) {
+- ieee80211_unregister_hw(priv->hw);
+- iwl4965_rate_control_unregister(priv->hw);
+- }
+
+ /*netif_stop_queue(dev); */
+ flush_workqueue(priv->workqueue);
+@@ -9335,7 +7932,7 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+
+- iwl4965_free_channel_map(priv);
++ iwl_free_channel_map(priv);
+ iwl4965_free_geos(priv);
+
+ if (priv->ibss_beacon)
+@@ -9348,7 +7945,7 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
+
+ static int iwl4965_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+ {
+- struct iwl4965_priv *priv = pci_get_drvdata(pdev);
++ struct iwl_priv *priv = pci_get_drvdata(pdev);
+
+ if (priv->is_open) {
+ set_bit(STATUS_IN_SUSPEND, &priv->status);
+@@ -9363,7 +7960,7 @@ static int iwl4965_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+
+ static int iwl4965_pci_resume(struct pci_dev *pdev)
+ {
+- struct iwl4965_priv *priv = pci_get_drvdata(pdev);
++ struct iwl_priv *priv = pci_get_drvdata(pdev);
+
+ pci_set_power_state(pdev, PCI_D0);
+
+@@ -9382,9 +7979,17 @@ static int iwl4965_pci_resume(struct pci_dev *pdev)
+ *
+ *****************************************************************************/
+
+-static struct pci_driver iwl4965_driver = {
++/* Hardware specific file defines the PCI IDs table for that hardware module */
++static struct pci_device_id iwl_hw_card_ids[] = {
++ {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)},
++ {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)},
++ {0}
++};
++MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
++
++static struct pci_driver iwl_driver = {
+ .name = DRV_NAME,
+- .id_table = iwl4965_hw_card_ids,
++ .id_table = iwl_hw_card_ids,
+ .probe = iwl4965_pci_probe,
+ .remove = __devexit_p(iwl4965_pci_remove),
+ #ifdef CONFIG_PM
+@@ -9399,51 +8004,45 @@ static int __init iwl4965_init(void)
+ int ret;
+ printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
+ printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
+- ret = pci_register_driver(&iwl4965_driver);
++
++ ret = iwl4965_rate_control_register();
+ if (ret) {
+- IWL_ERROR("Unable to initialize PCI module\n");
++ IWL_ERROR("Unable to register rate control algorithm: %d\n", ret);
+ return ret;
+ }
+-#ifdef CONFIG_IWL4965_DEBUG
+- ret = driver_create_file(&iwl4965_driver.driver, &driver_attr_debug_level);
++
++ ret = pci_register_driver(&iwl_driver);
++ if (ret) {
++ IWL_ERROR("Unable to initialize PCI module\n");
++ goto error_register;
++ }
++#ifdef CONFIG_IWLWIFI_DEBUG
++ ret = driver_create_file(&iwl_driver.driver, &driver_attr_debug_level);
+ if (ret) {
+ IWL_ERROR("Unable to create driver sysfs file\n");
+- pci_unregister_driver(&iwl4965_driver);
+- return ret;
++ goto error_debug;
+ }
+ #endif
+
+ return ret;
++
++#ifdef CONFIG_IWLWIFI_DEBUG
++error_debug:
++ pci_unregister_driver(&iwl_driver);
++#endif
++error_register:
++ iwl4965_rate_control_unregister();
++ return ret;
+ }
+
+ static void __exit iwl4965_exit(void)
+ {
+-#ifdef CONFIG_IWL4965_DEBUG
+- driver_remove_file(&iwl4965_driver.driver, &driver_attr_debug_level);
++#ifdef CONFIG_IWLWIFI_DEBUG
++ driver_remove_file(&iwl_driver.driver, &driver_attr_debug_level);
+ #endif
+- pci_unregister_driver(&iwl4965_driver);
+-}
+-
+-module_param_named(antenna, iwl4965_param_antenna, int, 0444);
+-MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
+-module_param_named(disable, iwl4965_param_disable, int, 0444);
+-MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
+-module_param_named(hwcrypto, iwl4965_param_hwcrypto, int, 0444);
+-MODULE_PARM_DESC(hwcrypto,
+- "using hardware crypto engine (default 0 [software])\n");
+-module_param_named(debug, iwl4965_param_debug, int, 0444);
+-MODULE_PARM_DESC(debug, "debug output mask");
+-module_param_named(disable_hw_scan, iwl4965_param_disable_hw_scan, int, 0444);
+-MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
+-
+-module_param_named(queues_num, iwl4965_param_queues_num, int, 0444);
+-MODULE_PARM_DESC(queues_num, "number of hw queues.");
+-
+-/* QoS */
+-module_param_named(qos_enable, iwl4965_param_qos_enable, int, 0444);
+-MODULE_PARM_DESC(qos_enable, "enable all QoS functionality");
+-module_param_named(amsdu_size_8K, iwl4965_param_amsdu_size_8K, int, 0444);
+-MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size");
++ pci_unregister_driver(&iwl_driver);
++ iwl4965_rate_control_unregister();
++}
+
+ module_exit(iwl4965_exit);
+ module_init(iwl4965_init);
+diff --git a/drivers/net/wireless/libertas/11d.c b/drivers/net/wireless/libertas/11d.c
+index 5e10ce0..4bc46a6 100644
+--- a/drivers/net/wireless/libertas/11d.c
++++ b/drivers/net/wireless/libertas/11d.c
+@@ -79,7 +79,7 @@ static u8 *lbs_code_2_region(u8 code)
+ * @param nrchan number of channels
+ * @return the nrchan-th chan number
+ */
+-static u8 lbs_get_chan_11d(u8 band, u8 firstchan, u8 nrchan, u8 *chan)
++static u8 lbs_get_chan_11d(u8 firstchan, u8 nrchan, u8 *chan)
+ /*find the nrchan-th chan after the firstchan*/
+ {
+ u8 i;
+@@ -134,7 +134,7 @@ static u8 lbs_channel_known_11d(u8 chan,
+ return 0;
+ }
+
+-u32 lbs_chan_2_freq(u8 chan, u8 band)
++u32 lbs_chan_2_freq(u8 chan)
+ {
+ struct chan_freq_power *cf;
+ u16 i;
+@@ -264,7 +264,7 @@ static void lbs_generate_parsed_region_chan_11d(struct region_channel *region_ch
+ * @param chan chan
+ * @return TRUE;FALSE
+ */
+-static u8 lbs_region_chan_supported_11d(u8 region, u8 band, u8 chan)
++static u8 lbs_region_chan_supported_11d(u8 region, u8 chan)
+ {
+ struct chan_freq_power *cfp;
+ int cfp_no;
+@@ -273,7 +273,7 @@ static u8 lbs_region_chan_supported_11d(u8 region, u8 band, u8 chan)
+
+ lbs_deb_enter(LBS_DEB_11D);
+
+- cfp = lbs_get_region_cfp_table(region, band, &cfp_no);
++ cfp = lbs_get_region_cfp_table(region, &cfp_no);
+ if (cfp == NULL)
+ return 0;
+
+@@ -367,7 +367,7 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset*
+ for (i = 0; idx < MAX_NO_OF_CHAN && i < nrchan; i++) {
+ /*step4: channel is supported? */
+
+- if (!lbs_get_chan_11d(band, firstchan, i, &curchan)) {
++ if (!lbs_get_chan_11d(firstchan, i, &curchan)) {
+ /* Chan is not found in UN table */
+ lbs_deb_11d("chan is not supported: %d \n", i);
+ break;
+@@ -375,8 +375,7 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset*
+
+ lastchan = curchan;
+
+- if (lbs_region_chan_supported_11d
+- (region, band, curchan)) {
++ if (lbs_region_chan_supported_11d(region, curchan)) {
+ /*step5: Check if curchan is supported by mrvl in region */
+ parsed_region_chan->chanpwr[idx].chan = curchan;
+ parsed_region_chan->chanpwr[idx].pwr =
+@@ -554,8 +553,7 @@ done:
+ * @param resp pointer to command response buffer
+ * @return 0; -1
+ */
+-int lbs_ret_802_11d_domain_info(struct lbs_private *priv,
+- struct cmd_ds_command *resp)
++int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp)
+ {
+ struct cmd_ds_802_11d_domain_info *domaininfo = &resp->params.domaininforesp;
+ struct mrvlietypes_domainparamset *domain = &domaininfo->domain;
+diff --git a/drivers/net/wireless/libertas/11d.h b/drivers/net/wireless/libertas/11d.h
+index 811eea2..4f4f47f 100644
+--- a/drivers/net/wireless/libertas/11d.h
++++ b/drivers/net/wireless/libertas/11d.h
+@@ -83,7 +83,7 @@ struct lbs_private;
+ u8 lbs_get_scan_type_11d(u8 chan,
+ struct parsed_region_chan_11d *parsed_region_chan);
+
+-u32 lbs_chan_2_freq(u8 chan, u8 band);
++u32 lbs_chan_2_freq(u8 chan);
+
+ void lbs_init_11d(struct lbs_private *priv);
+
+@@ -93,8 +93,7 @@ int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
+ struct cmd_ds_command *cmd, u16 cmdno,
+ u16 cmdOption);
+
+-int lbs_ret_802_11d_domain_info(struct lbs_private *priv,
+- struct cmd_ds_command *resp);
++int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp);
+
+ struct bss_descriptor;
+ int lbs_parse_dnld_countryinfo_11d(struct lbs_private *priv,
+diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile
+index 0e27876..f0724e3 100644
+--- a/drivers/net/wireless/libertas/Makefile
++++ b/drivers/net/wireless/libertas/Makefile
+@@ -1,7 +1,7 @@
+ libertas-objs := main.o wext.o \
+ rx.o tx.o cmd.o \
+ cmdresp.o scan.o \
+- join.o 11d.o \
++ 11d.o \
+ debugfs.o \
+ ethtool.o assoc.o
+
+diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
+index 6a24ed6..c9c3640 100644
+--- a/drivers/net/wireless/libertas/assoc.c
++++ b/drivers/net/wireless/libertas/assoc.c
+@@ -1,14 +1,11 @@
+ /* Copyright (C) 2006, Red Hat, Inc. */
+
+-#include <linux/bitops.h>
+-#include <net/ieee80211.h>
+ #include <linux/etherdevice.h>
+
+ #include "assoc.h"
+-#include "join.h"
+ #include "decl.h"
+-#include "hostcmd.h"
+ #include "host.h"
++#include "scan.h"
+ #include "cmd.h"
+
+
+@@ -17,6 +14,428 @@ static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) =
+ static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) =
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
++/* The firmware needs certain bits masked out of the beacon-derviced capability
++ * field when associating/joining to BSSs.
++ */
++#define CAPINFO_MASK (~(0xda00))
++
++
++
++/**
++ * @brief Associate to a specific BSS discovered in a scan
++ *
++ * @param priv A pointer to struct lbs_private structure
++ * @param pbssdesc Pointer to the BSS descriptor to associate with.
++ *
++ * @return 0-success, otherwise fail
++ */
++static int lbs_associate(struct lbs_private *priv,
++ struct assoc_request *assoc_req)
++{
++ int ret;
++
++ lbs_deb_enter(LBS_DEB_ASSOC);
++
++ ret = lbs_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE,
++ 0, CMD_OPTION_WAITFORRSP,
++ 0, assoc_req->bss.bssid);
++
++ if (ret)
++ goto done;
++
++ /* set preamble to firmware */
++ if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
++ (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE))
++ priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
++ else
++ priv->preamble = CMD_TYPE_LONG_PREAMBLE;
++
++ lbs_set_radio_control(priv);
++
++ ret = lbs_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE,
++ 0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
++
++done:
++ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
++ return ret;
++}
++
++/**
++ * @brief Join an adhoc network found in a previous scan
++ *
++ * @param priv A pointer to struct lbs_private structure
++ * @param pbssdesc Pointer to a BSS descriptor found in a previous scan
++ * to attempt to join
++ *
++ * @return 0--success, -1--fail
++ */
++static int lbs_join_adhoc_network(struct lbs_private *priv,
++ struct assoc_request *assoc_req)
++{
++ struct bss_descriptor *bss = &assoc_req->bss;
++ int ret = 0;
++
++ lbs_deb_join("current SSID '%s', ssid length %u\n",
++ escape_essid(priv->curbssparams.ssid,
++ priv->curbssparams.ssid_len),
++ priv->curbssparams.ssid_len);
++ lbs_deb_join("requested ssid '%s', ssid length %u\n",
++ escape_essid(bss->ssid, bss->ssid_len),
++ bss->ssid_len);
++
++ /* check if the requested SSID is already joined */
++ if (priv->curbssparams.ssid_len &&
++ !lbs_ssid_cmp(priv->curbssparams.ssid,
++ priv->curbssparams.ssid_len,
++ bss->ssid, bss->ssid_len) &&
++ (priv->mode == IW_MODE_ADHOC) &&
++ (priv->connect_status == LBS_CONNECTED)) {
++ union iwreq_data wrqu;
++
++ lbs_deb_join("ADHOC_J_CMD: New ad-hoc SSID is the same as "
++ "current, not attempting to re-join");
++
++ /* Send the re-association event though, because the association
++ * request really was successful, even if just a null-op.
++ */
++ memset(&wrqu, 0, sizeof(wrqu));
++ memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid,
++ ETH_ALEN);
++ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
++ wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
++ goto out;
++ }
++
++ /* Use shortpreamble only when both creator and card supports
++ short preamble */
++ if (!(bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) ||
++ !(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
++ lbs_deb_join("AdhocJoin: Long preamble\n");
++ priv->preamble = CMD_TYPE_LONG_PREAMBLE;
++ } else {
++ lbs_deb_join("AdhocJoin: Short preamble\n");
++ priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
++ }
++
++ lbs_set_radio_control(priv);
++
++ lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel);
++ lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);
++
++ priv->adhoccreate = 0;
++
++ ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_JOIN,
++ 0, CMD_OPTION_WAITFORRSP,
++ OID_802_11_SSID, assoc_req);
++
++out:
++ return ret;
++}
++
++/**
++ * @brief Start an Adhoc Network
++ *
++ * @param priv A pointer to struct lbs_private structure
++ * @param adhocssid The ssid of the Adhoc Network
++ * @return 0--success, -1--fail
++ */
++static int lbs_start_adhoc_network(struct lbs_private *priv,
++ struct assoc_request *assoc_req)
++{
++ int ret = 0;
++
++ priv->adhoccreate = 1;
++
++ if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
++ lbs_deb_join("AdhocStart: Short preamble\n");
++ priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
++ } else {
++ lbs_deb_join("AdhocStart: Long preamble\n");
++ priv->preamble = CMD_TYPE_LONG_PREAMBLE;
++ }
++
++ lbs_set_radio_control(priv);
++
++ lbs_deb_join("AdhocStart: channel = %d\n", assoc_req->channel);
++ lbs_deb_join("AdhocStart: band = %d\n", assoc_req->band);
++
++ ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_START,
++ 0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
++
++ return ret;
++}
++
++int lbs_stop_adhoc_network(struct lbs_private *priv)
++{
++ return lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_STOP,
++ 0, CMD_OPTION_WAITFORRSP, 0, NULL);
++}
++
++static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
++ struct bss_descriptor *match_bss)
++{
++ if (!secinfo->wep_enabled && !secinfo->WPAenabled
++ && !secinfo->WPA2enabled
++ && match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC
++ && match_bss->rsn_ie[0] != MFIE_TYPE_RSN
++ && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY))
++ return 1;
++ else
++ return 0;
++}
++
++static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo,
++ struct bss_descriptor *match_bss)
++{
++ if (secinfo->wep_enabled && !secinfo->WPAenabled
++ && !secinfo->WPA2enabled
++ && (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
++ return 1;
++ else
++ return 0;
++}
++
++static inline int match_bss_wpa(struct lbs_802_11_security *secinfo,
++ struct bss_descriptor *match_bss)
++{
++ if (!secinfo->wep_enabled && secinfo->WPAenabled
++ && (match_bss->wpa_ie[0] == MFIE_TYPE_GENERIC)
++ /* privacy bit may NOT be set in some APs like LinkSys WRT54G
++ && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
++ )
++ return 1;
++ else
++ return 0;
++}
++
++static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo,
++ struct bss_descriptor *match_bss)
++{
++ if (!secinfo->wep_enabled && secinfo->WPA2enabled &&
++ (match_bss->rsn_ie[0] == MFIE_TYPE_RSN)
++ /* privacy bit may NOT be set in some APs like LinkSys WRT54G
++ (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
++ )
++ return 1;
++ else
++ return 0;
++}
++
++static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo,
++ struct bss_descriptor *match_bss)
++{
++ if (!secinfo->wep_enabled && !secinfo->WPAenabled
++ && !secinfo->WPA2enabled
++ && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC)
++ && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN)
++ && (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
++ return 1;
++ else
++ return 0;
++}
++
++/**
++ * @brief Check if a scanned network compatible with the driver settings
++ *
++ * WEP WPA WPA2 ad-hoc encrypt Network
++ * enabled enabled enabled AES mode privacy WPA WPA2 Compatible
++ * 0 0 0 0 NONE 0 0 0 yes No security
++ * 1 0 0 0 NONE 1 0 0 yes Static WEP
++ * 0 1 0 0 x 1x 1 x yes WPA
++ * 0 0 1 0 x 1x x 1 yes WPA2
++ * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES
++ * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP
++ *
++ *
++ * @param priv A pointer to struct lbs_private
++ * @param index Index in scantable to check against current driver settings
++ * @param mode Network mode: Infrastructure or IBSS
++ *
++ * @return Index in scantable, or error code if negative
++ */
++static int is_network_compatible(struct lbs_private *priv,
++ struct bss_descriptor *bss, uint8_t mode)
++{
++ int matched = 0;
++
++ lbs_deb_enter(LBS_DEB_SCAN);
++
++ if (bss->mode != mode)
++ goto done;
++
++ matched = match_bss_no_security(&priv->secinfo, bss);
++ if (matched)
++ goto done;
++ matched = match_bss_static_wep(&priv->secinfo, bss);
++ if (matched)
++ goto done;
++ matched = match_bss_wpa(&priv->secinfo, bss);
++ if (matched) {
++ lbs_deb_scan("is_network_compatible() WPA: wpa_ie 0x%x "
++ "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
++ "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
++ priv->secinfo.wep_enabled ? "e" : "d",
++ priv->secinfo.WPAenabled ? "e" : "d",
++ priv->secinfo.WPA2enabled ? "e" : "d",
++ (bss->capability & WLAN_CAPABILITY_PRIVACY));
++ goto done;
++ }
++ matched = match_bss_wpa2(&priv->secinfo, bss);
++ if (matched) {
++ lbs_deb_scan("is_network_compatible() WPA2: wpa_ie 0x%x "
++ "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
++ "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
++ priv->secinfo.wep_enabled ? "e" : "d",
++ priv->secinfo.WPAenabled ? "e" : "d",
++ priv->secinfo.WPA2enabled ? "e" : "d",
++ (bss->capability & WLAN_CAPABILITY_PRIVACY));
++ goto done;
++ }
++ matched = match_bss_dynamic_wep(&priv->secinfo, bss);
++ if (matched) {
++ lbs_deb_scan("is_network_compatible() dynamic WEP: "
++ "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n",
++ bss->wpa_ie[0], bss->rsn_ie[0],
++ (bss->capability & WLAN_CAPABILITY_PRIVACY));
++ goto done;
++ }
++
++ /* bss security settings don't match those configured on card */
++ lbs_deb_scan("is_network_compatible() FAILED: wpa_ie 0x%x "
++ "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n",
++ bss->wpa_ie[0], bss->rsn_ie[0],
++ priv->secinfo.wep_enabled ? "e" : "d",
++ priv->secinfo.WPAenabled ? "e" : "d",
++ priv->secinfo.WPA2enabled ? "e" : "d",
++ (bss->capability & WLAN_CAPABILITY_PRIVACY));
++
++done:
++ lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched);
++ return matched;
++}
++
++/**
++ * @brief This function finds a specific compatible BSSID in the scan list
++ *
++ * Used in association code
++ *
++ * @param priv A pointer to struct lbs_private
++ * @param bssid BSSID to find in the scan list
++ * @param mode Network mode: Infrastructure or IBSS
++ *
++ * @return index in BSSID list, or error return code (< 0)
++ */
++static struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv,
++ uint8_t *bssid, uint8_t mode)
++{
++ struct bss_descriptor *iter_bss;
++ struct bss_descriptor *found_bss = NULL;
++
++ lbs_deb_enter(LBS_DEB_SCAN);
++
++ if (!bssid)
++ goto out;
++
++ lbs_deb_hex(LBS_DEB_SCAN, "looking for", bssid, ETH_ALEN);
++
++ /* Look through the scan table for a compatible match. The loop will
++ * continue past a matched bssid that is not compatible in case there
++ * is an AP with multiple SSIDs assigned to the same BSSID
++ */
++ mutex_lock(&priv->lock);
++ list_for_each_entry(iter_bss, &priv->network_list, list) {
++ if (compare_ether_addr(iter_bss->bssid, bssid))
++ continue; /* bssid doesn't match */
++ switch (mode) {
++ case IW_MODE_INFRA:
++ case IW_MODE_ADHOC:
++ if (!is_network_compatible(priv, iter_bss, mode))
++ break;
++ found_bss = iter_bss;
++ break;
++ default:
++ found_bss = iter_bss;
++ break;
++ }
++ }
++ mutex_unlock(&priv->lock);
++
++out:
++ lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
++ return found_bss;
++}
++
++/**
++ * @brief This function finds ssid in ssid list.
++ *
++ * Used in association code
++ *
++ * @param priv A pointer to struct lbs_private
++ * @param ssid SSID to find in the list
++ * @param bssid BSSID to qualify the SSID selection (if provided)
++ * @param mode Network mode: Infrastructure or IBSS
++ *
++ * @return index in BSSID list
++ */
++static struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv,
++ uint8_t *ssid, uint8_t ssid_len,
++ uint8_t *bssid, uint8_t mode,
++ int channel)
++{
++ u32 bestrssi = 0;
++ struct bss_descriptor *iter_bss = NULL;
++ struct bss_descriptor *found_bss = NULL;
++ struct bss_descriptor *tmp_oldest = NULL;
++
++ lbs_deb_enter(LBS_DEB_SCAN);
++
++ mutex_lock(&priv->lock);
++
++ list_for_each_entry(iter_bss, &priv->network_list, list) {
++ if (!tmp_oldest ||
++ (iter_bss->last_scanned < tmp_oldest->last_scanned))
++ tmp_oldest = iter_bss;
++
++ if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len,
++ ssid, ssid_len) != 0)
++ continue; /* ssid doesn't match */
++ if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0)
++ continue; /* bssid doesn't match */
++ if ((channel > 0) && (iter_bss->channel != channel))
++ continue; /* channel doesn't match */
++
++ switch (mode) {
++ case IW_MODE_INFRA:
++ case IW_MODE_ADHOC:
++ if (!is_network_compatible(priv, iter_bss, mode))
++ break;
++
++ if (bssid) {
++ /* Found requested BSSID */
++ found_bss = iter_bss;
++ goto out;
++ }
++
++ if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
++ bestrssi = SCAN_RSSI(iter_bss->rssi);
++ found_bss = iter_bss;
++ }
++ break;
++ case IW_MODE_AUTO:
++ default:
++ if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
++ bestrssi = SCAN_RSSI(iter_bss->rssi);
++ found_bss = iter_bss;
++ }
++ break;
++ }
++ }
++
++out:
++ mutex_unlock(&priv->lock);
++ lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
++ return found_bss;
++}
+
+ static int assoc_helper_essid(struct lbs_private *priv,
+ struct assoc_request * assoc_req)
+@@ -38,7 +457,7 @@ static int assoc_helper_essid(struct lbs_private *priv,
+ escape_essid(assoc_req->ssid, assoc_req->ssid_len));
+ if (assoc_req->mode == IW_MODE_INFRA) {
+ lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
+- assoc_req->ssid_len, 0);
++ assoc_req->ssid_len);
+
+ bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
+ assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel);
+@@ -53,7 +472,7 @@ static int assoc_helper_essid(struct lbs_private *priv,
+ * scan data will cause us to join a non-existant adhoc network
+ */
+ lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
+- assoc_req->ssid_len, 1);
++ assoc_req->ssid_len);
+
+ /* Search for the requested SSID in the scan table */
+ bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
+@@ -164,34 +583,6 @@ done:
+ return ret;
+ }
+
+-
+-int lbs_update_channel(struct lbs_private *priv)
+-{
+- int ret;
+-
+- /* the channel in f/w could be out of sync; get the current channel */
+- lbs_deb_enter(LBS_DEB_ASSOC);
+-
+- ret = lbs_get_channel(priv);
+- if (ret > 0) {
+- priv->curbssparams.channel = ret;
+- ret = 0;
+- }
+- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
+- return ret;
+-}
+-
+-void lbs_sync_channel(struct work_struct *work)
+-{
+- struct lbs_private *priv = container_of(work, struct lbs_private,
+- sync_channel);
+-
+- lbs_deb_enter(LBS_DEB_ASSOC);
+- if (lbs_update_channel(priv))
+- lbs_pr_info("Channel synchronization failed.");
+- lbs_deb_leave(LBS_DEB_ASSOC);
+-}
+-
+ static int assoc_helper_channel(struct lbs_private *priv,
+ struct assoc_request * assoc_req)
+ {
+@@ -279,13 +670,11 @@ static int assoc_helper_wep_keys(struct lbs_private *priv,
+
+ /* enable/disable the MAC's WEP packet filter */
+ if (assoc_req->secinfo.wep_enabled)
+- priv->currentpacketfilter |= CMD_ACT_MAC_WEP_ENABLE;
++ priv->mac_control |= CMD_ACT_MAC_WEP_ENABLE;
+ else
+- priv->currentpacketfilter &= ~CMD_ACT_MAC_WEP_ENABLE;
++ priv->mac_control &= ~CMD_ACT_MAC_WEP_ENABLE;
+
+- ret = lbs_set_mac_packet_filter(priv);
+- if (ret)
+- goto out;
++ lbs_set_mac_control(priv);
+
+ mutex_lock(&priv->lock);
+
+@@ -315,9 +704,7 @@ static int assoc_helper_secinfo(struct lbs_private *priv,
+ memcpy(&priv->secinfo, &assoc_req->secinfo,
+ sizeof(struct lbs_802_11_security));
+
+- ret = lbs_set_mac_packet_filter(priv);
+- if (ret)
+- goto out;
++ lbs_set_mac_control(priv);
+
+ /* If RSN is already enabled, don't try to enable it again, since
+ * ENABLE_RSN resets internal state machines and will clobber the
+@@ -360,11 +747,7 @@ static int assoc_helper_wpa_keys(struct lbs_private *priv,
+
+ if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
+ clear_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
+- ret = lbs_prepare_and_send_command(priv,
+- CMD_802_11_KEY_MATERIAL,
+- CMD_ACT_SET,
+- CMD_OPTION_WAITFORRSP,
+- 0, assoc_req);
++ ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req);
+ assoc_req->flags = flags;
+ }
+
+@@ -374,11 +757,7 @@ static int assoc_helper_wpa_keys(struct lbs_private *priv,
+ if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
+ clear_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
+
+- ret = lbs_prepare_and_send_command(priv,
+- CMD_802_11_KEY_MATERIAL,
+- CMD_ACT_SET,
+- CMD_OPTION_WAITFORRSP,
+- 0, assoc_req);
++ ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req);
+ assoc_req->flags = flags;
+ }
+
+@@ -413,11 +792,10 @@ static int should_deauth_infrastructure(struct lbs_private *priv,
+ {
+ int ret = 0;
+
+- lbs_deb_enter(LBS_DEB_ASSOC);
+-
+ if (priv->connect_status != LBS_CONNECTED)
+ return 0;
+
++ lbs_deb_enter(LBS_DEB_ASSOC);
+ if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
+ lbs_deb_assoc("Deauthenticating due to new SSID\n");
+ ret = 1;
+@@ -456,7 +834,7 @@ static int should_deauth_infrastructure(struct lbs_private *priv,
+
+ out:
+ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
+- return 0;
++ return ret;
+ }
+
+
+@@ -489,6 +867,91 @@ static int should_stop_adhoc(struct lbs_private *priv,
+ }
+
+
++/**
++ * @brief This function finds the best SSID in the Scan List
++ *
++ * Search the scan table for the best SSID that also matches the current
++ * adapter network preference (infrastructure or adhoc)
++ *
++ * @param priv A pointer to struct lbs_private
++ *
++ * @return index in BSSID list
++ */
++static struct bss_descriptor *lbs_find_best_ssid_in_list(
++ struct lbs_private *priv, uint8_t mode)
++{
++ uint8_t bestrssi = 0;
++ struct bss_descriptor *iter_bss;
++ struct bss_descriptor *best_bss = NULL;
++
++ lbs_deb_enter(LBS_DEB_SCAN);
++
++ mutex_lock(&priv->lock);
++
++ list_for_each_entry(iter_bss, &priv->network_list, list) {
++ switch (mode) {
++ case IW_MODE_INFRA:
++ case IW_MODE_ADHOC:
++ if (!is_network_compatible(priv, iter_bss, mode))
++ break;
++ if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
++ break;
++ bestrssi = SCAN_RSSI(iter_bss->rssi);
++ best_bss = iter_bss;
++ break;
++ case IW_MODE_AUTO:
++ default:
++ if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
++ break;
++ bestrssi = SCAN_RSSI(iter_bss->rssi);
++ best_bss = iter_bss;
++ break;
++ }
++ }
++
++ mutex_unlock(&priv->lock);
++ lbs_deb_leave_args(LBS_DEB_SCAN, "best_bss %p", best_bss);
++ return best_bss;
++}
++
++/**
++ * @brief Find the best AP
++ *
++ * Used from association worker.
++ *
++ * @param priv A pointer to struct lbs_private structure
++ * @param pSSID A pointer to AP's ssid
++ *
++ * @return 0--success, otherwise--fail
++ */
++static int lbs_find_best_network_ssid(struct lbs_private *priv,
++ uint8_t *out_ssid, uint8_t *out_ssid_len, uint8_t preferred_mode,
++ uint8_t *out_mode)
++{
++ int ret = -1;
++ struct bss_descriptor *found;
++
++ lbs_deb_enter(LBS_DEB_SCAN);
++
++ priv->scan_ssid_len = 0;
++ lbs_scan_networks(priv, 1);
++ if (priv->surpriseremoved)
++ goto out;
++
++ found = lbs_find_best_ssid_in_list(priv, preferred_mode);
++ if (found && (found->ssid_len > 0)) {
++ memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE);
++ *out_ssid_len = found->ssid_len;
++ *out_mode = found->mode;
++ ret = 0;
++ }
++
++out:
++ lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
++ return ret;
++}
++
++
+ void lbs_association_worker(struct work_struct *work)
+ {
+ struct lbs_private *priv = container_of(work, struct lbs_private,
+@@ -643,17 +1106,11 @@ void lbs_association_worker(struct work_struct *work)
+ }
+
+ if (success) {
+- lbs_deb_assoc("ASSOC: associated to '%s', %s\n",
+- escape_essid(priv->curbssparams.ssid,
+- priv->curbssparams.ssid_len),
++ lbs_deb_assoc("associated to %s\n",
+ print_mac(mac, priv->curbssparams.bssid));
+ lbs_prepare_and_send_command(priv,
+ CMD_802_11_RSSI,
+ 0, CMD_OPTION_WAITFORRSP, 0, NULL);
+-
+- lbs_prepare_and_send_command(priv,
+- CMD_802_11_GET_LOG,
+- 0, CMD_OPTION_WAITFORRSP, 0, NULL);
+ } else {
+ ret = -1;
+ }
+@@ -752,3 +1209,705 @@ struct assoc_request *lbs_get_association_request(struct lbs_private *priv)
+ lbs_deb_leave(LBS_DEB_ASSOC);
+ return assoc_req;
+ }
++
++
++/**
++ * @brief This function finds common rates between rate1 and card rates.
++ *
++ * It will fill common rates in rate1 as output if found.
++ *
++ * NOTE: Setting the MSB of the basic rates need to be taken
++ * care, either before or after calling this function
++ *
++ * @param priv A pointer to struct lbs_private structure
++ * @param rate1 the buffer which keeps input and output
++ * @param rate1_size the size of rate1 buffer; new size of buffer on return
++ *
++ * @return 0 or -1
++ */
++static int get_common_rates(struct lbs_private *priv,
++ u8 *rates,
++ u16 *rates_size)
++{
++ u8 *card_rates = lbs_bg_rates;
++ size_t num_card_rates = sizeof(lbs_bg_rates);
++ int ret = 0, i, j;
++ u8 tmp[30];
++ size_t tmp_size = 0;
++
++ /* For each rate in card_rates that exists in rate1, copy to tmp */
++ for (i = 0; card_rates[i] && (i < num_card_rates); i++) {
++ for (j = 0; rates[j] && (j < *rates_size); j++) {
++ if (rates[j] == card_rates[i])
++ tmp[tmp_size++] = card_rates[i];
++ }
++ }
++
++ lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size);
++ lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, num_card_rates);
++ lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size);
++ lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
++
++ if (!priv->auto_rate) {
++ for (i = 0; i < tmp_size; i++) {
++ if (tmp[i] == priv->cur_rate)
++ goto done;
++ }
++ lbs_pr_alert("Previously set fixed data rate %#x isn't "
++ "compatible with the network.\n", priv->cur_rate);
++ ret = -1;
++ goto done;
++ }
++ ret = 0;
++
++done:
++ memset(rates, 0, *rates_size);
++ *rates_size = min_t(int, tmp_size, *rates_size);
++ memcpy(rates, tmp, *rates_size);
++ return ret;
++}
++
++
++/**
++ * @brief Sets the MSB on basic rates as the firmware requires
++ *
++ * Scan through an array and set the MSB for basic data rates.
++ *
++ * @param rates buffer of data rates
++ * @param len size of buffer
++ */
++static void lbs_set_basic_rate_flags(u8 *rates, size_t len)
++{
++ int i;
++
++ for (i = 0; i < len; i++) {
++ if (rates[i] == 0x02 || rates[i] == 0x04 ||
++ rates[i] == 0x0b || rates[i] == 0x16)
++ rates[i] |= 0x80;
++ }
++}
++
++/**
++ * @brief Send Deauthentication Request
++ *
++ * @param priv A pointer to struct lbs_private structure
++ * @return 0--success, -1--fail
++ */
++int lbs_send_deauthentication(struct lbs_private *priv)
++{
++ return lbs_prepare_and_send_command(priv, CMD_802_11_DEAUTHENTICATE,
++ 0, CMD_OPTION_WAITFORRSP, 0, NULL);
++}
++
++/**
++ * @brief This function prepares command of authenticate.
++ *
++ * @param priv A pointer to struct lbs_private structure
++ * @param cmd A pointer to cmd_ds_command structure
++ * @param pdata_buf Void cast of pointer to a BSSID to authenticate with
++ *
++ * @return 0 or -1
++ */
++int lbs_cmd_80211_authenticate(struct lbs_private *priv,
++ struct cmd_ds_command *cmd,
++ void *pdata_buf)
++{
++ struct cmd_ds_802_11_authenticate *pauthenticate = &cmd->params.auth;
++ int ret = -1;
++ u8 *bssid = pdata_buf;
++ DECLARE_MAC_BUF(mac);
++
++ lbs_deb_enter(LBS_DEB_JOIN);
++
++ cmd->command = cpu_to_le16(CMD_802_11_AUTHENTICATE);
++ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate)
++ + S_DS_GEN);
++
++ /* translate auth mode to 802.11 defined wire value */
++ switch (priv->secinfo.auth_mode) {
++ case IW_AUTH_ALG_OPEN_SYSTEM:
++ pauthenticate->authtype = 0x00;
++ break;
++ case IW_AUTH_ALG_SHARED_KEY:
++ pauthenticate->authtype = 0x01;
++ break;
++ case IW_AUTH_ALG_LEAP:
++ pauthenticate->authtype = 0x80;
++ break;
++ default:
++ lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n",
++ priv->secinfo.auth_mode);
++ goto out;
++ }
++
++ memcpy(pauthenticate->macaddr, bssid, ETH_ALEN);
++
++ lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n",
++ print_mac(mac, bssid), pauthenticate->authtype);
++ ret = 0;
++
++out:
++ lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
++ return ret;
++}
++
++int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
++ struct cmd_ds_command *cmd)
++{
++ struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth;
++
++ lbs_deb_enter(LBS_DEB_JOIN);
++
++ cmd->command = cpu_to_le16(CMD_802_11_DEAUTHENTICATE);
++ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) +
++ S_DS_GEN);
++
++ /* set AP MAC address */
++ memmove(dauth->macaddr, priv->curbssparams.bssid, ETH_ALEN);
++
++ /* Reason code 3 = Station is leaving */
++#define REASON_CODE_STA_LEAVING 3
++ dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING);
++
++ lbs_deb_leave(LBS_DEB_JOIN);
++ return 0;
++}
++
++int lbs_cmd_80211_associate(struct lbs_private *priv,
++ struct cmd_ds_command *cmd, void *pdata_buf)
++{
++ struct cmd_ds_802_11_associate *passo = &cmd->params.associate;
++ int ret = 0;
++ struct assoc_request *assoc_req = pdata_buf;
++ struct bss_descriptor *bss = &assoc_req->bss;
++ u8 *pos;
++ u16 tmpcap, tmplen;
++ struct mrvlietypes_ssidparamset *ssid;
++ struct mrvlietypes_phyparamset *phy;
++ struct mrvlietypes_ssparamset *ss;
++ struct mrvlietypes_ratesparamset *rates;
++ struct mrvlietypes_rsnparamset *rsn;
++
++ lbs_deb_enter(LBS_DEB_ASSOC);
++
++ pos = (u8 *) passo;
++
++ if (!priv) {
++ ret = -1;
++ goto done;
++ }
++
++ cmd->command = cpu_to_le16(CMD_802_11_ASSOCIATE);
++
++ memcpy(passo->peerstaaddr, bss->bssid, sizeof(passo->peerstaaddr));
++ pos += sizeof(passo->peerstaaddr);
++
++ /* set the listen interval */
++ passo->listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL);
++
++ pos += sizeof(passo->capability);
++ pos += sizeof(passo->listeninterval);
++ pos += sizeof(passo->bcnperiod);
++ pos += sizeof(passo->dtimperiod);
++
++ ssid = (struct mrvlietypes_ssidparamset *) pos;
++ ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
++ tmplen = bss->ssid_len;
++ ssid->header.len = cpu_to_le16(tmplen);
++ memcpy(ssid->ssid, bss->ssid, tmplen);
++ pos += sizeof(ssid->header) + tmplen;
++
++ phy = (struct mrvlietypes_phyparamset *) pos;
++ phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
++ tmplen = sizeof(phy->fh_ds.dsparamset);
++ phy->header.len = cpu_to_le16(tmplen);
++ memcpy(&phy->fh_ds.dsparamset,
++ &bss->phyparamset.dsparamset.currentchan,
++ tmplen);
++ pos += sizeof(phy->header) + tmplen;
++
++ ss = (struct mrvlietypes_ssparamset *) pos;
++ ss->header.type = cpu_to_le16(TLV_TYPE_CF);
++ tmplen = sizeof(ss->cf_ibss.cfparamset);
++ ss->header.len = cpu_to_le16(tmplen);
++ pos += sizeof(ss->header) + tmplen;
++
++ rates = (struct mrvlietypes_ratesparamset *) pos;
++ rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
++ memcpy(&rates->rates, &bss->rates, MAX_RATES);
++ tmplen = MAX_RATES;
++ if (get_common_rates(priv, rates->rates, &tmplen)) {
++ ret = -1;
++ goto done;
++ }
++ pos += sizeof(rates->header) + tmplen;
++ rates->header.len = cpu_to_le16(tmplen);
++ lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen);
++
++ /* Copy the infra. association rates into Current BSS state structure */
++ memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
++ memcpy(&priv->curbssparams.rates, &rates->rates, tmplen);
++
++ /* Set MSB on basic rates as the firmware requires, but _after_
++ * copying to current bss rates.
++ */
++ lbs_set_basic_rate_flags(rates->rates, tmplen);
++
++ if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
++ rsn = (struct mrvlietypes_rsnparamset *) pos;
++ /* WPA_IE or WPA2_IE */
++ rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]);
++ tmplen = (u16) assoc_req->wpa_ie[1];
++ rsn->header.len = cpu_to_le16(tmplen);
++ memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen);
++ lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: RSN IE", (u8 *) rsn,
++ sizeof(rsn->header) + tmplen);
++ pos += sizeof(rsn->header) + tmplen;
++ }
++
++ /* update curbssparams */
++ priv->curbssparams.channel = bss->phyparamset.dsparamset.currentchan;
++
++ if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
++ ret = -1;
++ goto done;
++ }
++
++ cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN);
++
++ /* set the capability info */
++ tmpcap = (bss->capability & CAPINFO_MASK);
++ if (bss->mode == IW_MODE_INFRA)
++ tmpcap |= WLAN_CAPABILITY_ESS;
++ passo->capability = cpu_to_le16(tmpcap);
++ lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap);
++
++done:
++ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
++ return ret;
++}
++
++int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
++ struct cmd_ds_command *cmd, void *pdata_buf)
++{
++ struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads;
++ int ret = 0;
++ int cmdappendsize = 0;
++ struct assoc_request *assoc_req = pdata_buf;
++ u16 tmpcap = 0;
++ size_t ratesize = 0;
++
++ lbs_deb_enter(LBS_DEB_JOIN);
++
++ if (!priv) {
++ ret = -1;
++ goto done;
++ }
++
++ cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_START);
++
++ /*
++ * Fill in the parameters for 2 data structures:
++ * 1. cmd_ds_802_11_ad_hoc_start command
++ * 2. priv->scantable[i]
++ *
++ * Driver will fill up SSID, bsstype,IBSS param, Physical Param,
++ * probe delay, and cap info.
++ *
++ * Firmware will fill up beacon period, DTIM, Basic rates
++ * and operational rates.
++ */
++
++ memset(adhs->ssid, 0, IW_ESSID_MAX_SIZE);
++ memcpy(adhs->ssid, assoc_req->ssid, assoc_req->ssid_len);
++
++ lbs_deb_join("ADHOC_S_CMD: SSID '%s', ssid length %u\n",
++ escape_essid(assoc_req->ssid, assoc_req->ssid_len),
++ assoc_req->ssid_len);
++
++ /* set the BSS type */
++ adhs->bsstype = CMD_BSS_TYPE_IBSS;
++ priv->mode = IW_MODE_ADHOC;
++ if (priv->beacon_period == 0)
++ priv->beacon_period = MRVDRV_BEACON_INTERVAL;
++ adhs->beaconperiod = cpu_to_le16(priv->beacon_period);
++
++ /* set Physical param set */
++#define DS_PARA_IE_ID 3
++#define DS_PARA_IE_LEN 1
++
++ adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID;
++ adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN;
++
++ WARN_ON(!assoc_req->channel);
++
++ lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
++ assoc_req->channel);
++
++ adhs->phyparamset.dsparamset.currentchan = assoc_req->channel;
++
++ /* set IBSS param set */
++#define IBSS_PARA_IE_ID 6
++#define IBSS_PARA_IE_LEN 2
++
++ adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID;
++ adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN;
++ adhs->ssparamset.ibssparamset.atimwindow = 0;
++
++ /* set capability info */
++ tmpcap = WLAN_CAPABILITY_IBSS;
++ if (assoc_req->secinfo.wep_enabled) {
++ lbs_deb_join("ADHOC_S_CMD: WEP enabled, "
++ "setting privacy on\n");
++ tmpcap |= WLAN_CAPABILITY_PRIVACY;
++ } else {
++ lbs_deb_join("ADHOC_S_CMD: WEP disabled, "
++ "setting privacy off\n");
++ }
++ adhs->capability = cpu_to_le16(tmpcap);
++
++ /* probedelay */
++ adhs->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
++
++ memset(adhs->rates, 0, sizeof(adhs->rates));
++ ratesize = min(sizeof(adhs->rates), sizeof(lbs_bg_rates));
++ memcpy(adhs->rates, lbs_bg_rates, ratesize);
++
++ /* Copy the ad-hoc creating rates into Current BSS state structure */
++ memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
++ memcpy(&priv->curbssparams.rates, &adhs->rates, ratesize);
++
++ /* Set MSB on basic rates as the firmware requires, but _after_
++ * copying to current bss rates.
++ */
++ lbs_set_basic_rate_flags(adhs->rates, ratesize);
++
++ lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
++ adhs->rates[0], adhs->rates[1], adhs->rates[2], adhs->rates[3]);
++
++ lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n");
++
++ if (lbs_create_dnld_countryinfo_11d(priv)) {
++ lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
++ ret = -1;
++ goto done;
++ }
++
++ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start) +
++ S_DS_GEN + cmdappendsize);
++
++ ret = 0;
++done:
++ lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
++ return ret;
++}
++
++int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd)
++{
++ cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_STOP);
++ cmd->size = cpu_to_le16(S_DS_GEN);
++
++ return 0;
++}
++
++int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
++ struct cmd_ds_command *cmd, void *pdata_buf)
++{
++ struct cmd_ds_802_11_ad_hoc_join *join_cmd = &cmd->params.adj;
++ struct assoc_request *assoc_req = pdata_buf;
++ struct bss_descriptor *bss = &assoc_req->bss;
++ int cmdappendsize = 0;
++ int ret = 0;
++ u16 ratesize = 0;
++ DECLARE_MAC_BUF(mac);
++
++ lbs_deb_enter(LBS_DEB_JOIN);
++
++ cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_JOIN);
++
++ join_cmd->bss.type = CMD_BSS_TYPE_IBSS;
++ join_cmd->bss.beaconperiod = cpu_to_le16(bss->beaconperiod);
++
++ memcpy(&join_cmd->bss.bssid, &bss->bssid, ETH_ALEN);
++ memcpy(&join_cmd->bss.ssid, &bss->ssid, bss->ssid_len);
++
++ memcpy(&join_cmd->bss.phyparamset, &bss->phyparamset,
++ sizeof(union ieeetypes_phyparamset));
++
++ memcpy(&join_cmd->bss.ssparamset, &bss->ssparamset,
++ sizeof(union IEEEtypes_ssparamset));
++
++ join_cmd->bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK);
++ lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
++ bss->capability, CAPINFO_MASK);
++
++ /* information on BSSID descriptor passed to FW */
++ lbs_deb_join(
++ "ADHOC_J_CMD: BSSID = %s, SSID = '%s'\n",
++ print_mac(mac, join_cmd->bss.bssid),
++ join_cmd->bss.ssid);
++
++ /* failtimeout */
++ join_cmd->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
++
++ /* probedelay */
++ join_cmd->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
++
++ priv->curbssparams.channel = bss->channel;
++
++ /* Copy Data rates from the rates recorded in scan response */
++ memset(join_cmd->bss.rates, 0, sizeof(join_cmd->bss.rates));
++ ratesize = min_t(u16, sizeof(join_cmd->bss.rates), MAX_RATES);
++ memcpy(join_cmd->bss.rates, bss->rates, ratesize);
++ if (get_common_rates(priv, join_cmd->bss.rates, &ratesize)) {
++ lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n");
++ ret = -1;
++ goto done;
++ }
++
++ /* Copy the ad-hoc creating rates into Current BSS state structure */
++ memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
++ memcpy(&priv->curbssparams.rates, join_cmd->bss.rates, ratesize);
++
++ /* Set MSB on basic rates as the firmware requires, but _after_
++ * copying to current bss rates.
++ */
++ lbs_set_basic_rate_flags(join_cmd->bss.rates, ratesize);
++
++ join_cmd->bss.ssparamset.ibssparamset.atimwindow =
++ cpu_to_le16(bss->atimwindow);
++
++ if (assoc_req->secinfo.wep_enabled) {
++ u16 tmp = le16_to_cpu(join_cmd->bss.capability);
++ tmp |= WLAN_CAPABILITY_PRIVACY;
++ join_cmd->bss.capability = cpu_to_le16(tmp);
++ }
++
++ if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
++ /* wake up first */
++ __le32 Localpsmode;
++
++ Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM);
++ ret = lbs_prepare_and_send_command(priv,
++ CMD_802_11_PS_MODE,
++ CMD_ACT_SET,
++ 0, 0, &Localpsmode);
++
++ if (ret) {
++ ret = -1;
++ goto done;
++ }
++ }
++
++ if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
++ ret = -1;
++ goto done;
++ }
++
++ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join) +
++ S_DS_GEN + cmdappendsize);
++
++done:
++ lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
++ return ret;
++}
++
++int lbs_ret_80211_associate(struct lbs_private *priv,
++ struct cmd_ds_command *resp)
++{
++ int ret = 0;
++ union iwreq_data wrqu;
++ struct ieeetypes_assocrsp *passocrsp;
++ struct bss_descriptor *bss;
++ u16 status_code;
++
++ lbs_deb_enter(LBS_DEB_ASSOC);
++
++ if (!priv->in_progress_assoc_req) {
++ lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n");
++ ret = -1;
++ goto done;
++ }
++ bss = &priv->in_progress_assoc_req->bss;
++
++ passocrsp = (struct ieeetypes_assocrsp *) &resp->params;
++
++ /*
++ * Older FW versions map the IEEE 802.11 Status Code in the association
++ * response to the following values returned in passocrsp->statuscode:
++ *
++ * IEEE Status Code Marvell Status Code
++ * 0 -> 0x0000 ASSOC_RESULT_SUCCESS
++ * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
++ * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
++ * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
++ * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
++ * others -> 0x0003 ASSOC_RESULT_REFUSED
++ *
++ * Other response codes:
++ * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused)
++ * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for
++ * association response from the AP)
++ */
++
++ status_code = le16_to_cpu(passocrsp->statuscode);
++ switch (status_code) {
++ case 0x00:
++ break;
++ case 0x01:
++ lbs_deb_assoc("ASSOC_RESP: invalid parameters\n");
++ break;
++ case 0x02:
++ lbs_deb_assoc("ASSOC_RESP: internal timer "
++ "expired while waiting for the AP\n");
++ break;
++ case 0x03:
++ lbs_deb_assoc("ASSOC_RESP: association "
++ "refused by AP\n");
++ break;
++ case 0x04:
++ lbs_deb_assoc("ASSOC_RESP: authentication "
++ "refused by AP\n");
++ break;
++ default:
++ lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x "
++ " unknown\n", status_code);
++ break;
++ }
++
++ if (status_code) {
++ lbs_mac_event_disconnected(priv);
++ ret = -1;
++ goto done;
++ }
++
++ lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP", (void *)&resp->params,
++ le16_to_cpu(resp->size) - S_DS_GEN);
++
++ /* Send a Media Connected event, according to the Spec */
++ priv->connect_status = LBS_CONNECTED;
++
++ /* Update current SSID and BSSID */
++ memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
++ priv->curbssparams.ssid_len = bss->ssid_len;
++ memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
++
++ priv->SNR[TYPE_RXPD][TYPE_AVG] = 0;
++ priv->NF[TYPE_RXPD][TYPE_AVG] = 0;
++
++ memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
++ memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
++ priv->nextSNRNF = 0;
++ priv->numSNRNF = 0;
++
++ netif_carrier_on(priv->dev);
++ if (!priv->tx_pending_len)
++ netif_wake_queue(priv->dev);
++
++ memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
++ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
++ wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
++
++done:
++ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
++ return ret;
++}
++
++int lbs_ret_80211_disassociate(struct lbs_private *priv)
++{
++ lbs_deb_enter(LBS_DEB_JOIN);
++
++ lbs_mac_event_disconnected(priv);
++
++ lbs_deb_leave(LBS_DEB_JOIN);
++ return 0;
++}
++
++int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
++ struct cmd_ds_command *resp)
++{
++ int ret = 0;
++ u16 command = le16_to_cpu(resp->command);
++ u16 result = le16_to_cpu(resp->result);
++ struct cmd_ds_802_11_ad_hoc_result *padhocresult;
++ union iwreq_data wrqu;
++ struct bss_descriptor *bss;
++ DECLARE_MAC_BUF(mac);
++
++ lbs_deb_enter(LBS_DEB_JOIN);
++
++ padhocresult = &resp->params.result;
++
++ lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp->size));
++ lbs_deb_join("ADHOC_RESP: command = %x\n", command);
++ lbs_deb_join("ADHOC_RESP: result = %x\n", result);
++
++ if (!priv->in_progress_assoc_req) {
++ lbs_deb_join("ADHOC_RESP: no in-progress association "
++ "request\n");
++ ret = -1;
++ goto done;
++ }
++ bss = &priv->in_progress_assoc_req->bss;
++
++ /*
++ * Join result code 0 --> SUCCESS
++ */
++ if (result) {
++ lbs_deb_join("ADHOC_RESP: failed\n");
++ if (priv->connect_status == LBS_CONNECTED)
++ lbs_mac_event_disconnected(priv);
++ ret = -1;
++ goto done;
++ }
++
++ /*
++ * Now the join cmd should be successful
++ * If BSSID has changed use SSID to compare instead of BSSID
++ */
++ lbs_deb_join("ADHOC_RESP: associated to '%s'\n",
++ escape_essid(bss->ssid, bss->ssid_len));
++
++ /* Send a Media Connected event, according to the Spec */
++ priv->connect_status = LBS_CONNECTED;
++
++ if (command == CMD_RET(CMD_802_11_AD_HOC_START)) {
++ /* Update the created network descriptor with the new BSSID */
++ memcpy(bss->bssid, padhocresult->bssid, ETH_ALEN);
++ }
++
++ /* Set the BSSID from the joined/started descriptor */
++ memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
++
++ /* Set the new SSID to current SSID */
++ memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
++ priv->curbssparams.ssid_len = bss->ssid_len;
++
++ netif_carrier_on(priv->dev);
++ if (!priv->tx_pending_len)
++ netif_wake_queue(priv->dev);
++
++ memset(&wrqu, 0, sizeof(wrqu));
++ memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
++ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
++ wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
++
++ lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n");
++ lbs_deb_join("ADHOC_RESP: channel = %d\n", priv->curbssparams.channel);
++ lbs_deb_join("ADHOC_RESP: BSSID = %s\n",
++ print_mac(mac, padhocresult->bssid));
++
++done:
++ lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
++ return ret;
++}
++
++int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv)
++{
++ lbs_deb_enter(LBS_DEB_JOIN);
++
++ lbs_mac_event_disconnected(priv);
++
++ lbs_deb_leave(LBS_DEB_JOIN);
++ return 0;
++}
+diff --git a/drivers/net/wireless/libertas/assoc.h b/drivers/net/wireless/libertas/assoc.h
+index 08372bb..c516fbe 100644
+--- a/drivers/net/wireless/libertas/assoc.h
++++ b/drivers/net/wireless/libertas/assoc.h
+@@ -7,6 +7,33 @@
+
+ void lbs_association_worker(struct work_struct *work);
+ struct assoc_request *lbs_get_association_request(struct lbs_private *priv);
+-void lbs_sync_channel(struct work_struct *work);
++
++struct cmd_ds_command;
++int lbs_cmd_80211_authenticate(struct lbs_private *priv,
++ struct cmd_ds_command *cmd,
++ void *pdata_buf);
++int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
++ struct cmd_ds_command *cmd,
++ void *pdata_buf);
++int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd);
++int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
++ struct cmd_ds_command *cmd,
++ void *pdata_buf);
++int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
++ struct cmd_ds_command *cmd);
++int lbs_cmd_80211_associate(struct lbs_private *priv,
++ struct cmd_ds_command *cmd,
++ void *pdata_buf);
++
++int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
++ struct cmd_ds_command *resp);
++int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv);
++int lbs_ret_80211_disassociate(struct lbs_private *priv);
++int lbs_ret_80211_associate(struct lbs_private *priv,
++ struct cmd_ds_command *resp);
++
++int lbs_stop_adhoc_network(struct lbs_private *priv);
++
++int lbs_send_deauthentication(struct lbs_private *priv);
+
+ #endif /* _LBS_ASSOC_H */
+diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
+index b3c1acb..6328b95 100644
+--- a/drivers/net/wireless/libertas/cmd.c
++++ b/drivers/net/wireless/libertas/cmd.c
+@@ -4,19 +4,57 @@
+ */
+
+ #include <net/iw_handler.h>
++#include <linux/kfifo.h>
+ #include "host.h"
+ #include "hostcmd.h"
+ #include "decl.h"
+ #include "defs.h"
+ #include "dev.h"
+-#include "join.h"
++#include "assoc.h"
+ #include "wext.h"
+ #include "cmd.h"
+
+ static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv);
+-static void lbs_set_cmd_ctrl_node(struct lbs_private *priv,
+- struct cmd_ctrl_node *ptempnode,
+- void *pdata_buf);
++
++
++/**
++ * @brief Simple callback that copies response back into command
++ *
++ * @param priv A pointer to struct lbs_private structure
++ * @param extra A pointer to the original command structure for which
++ * 'resp' is a response
++ * @param resp A pointer to the command response
++ *
++ * @return 0 on success, error on failure
++ */
++int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
++ struct cmd_header *resp)
++{
++ struct cmd_header *buf = (void *)extra;
++ uint16_t copy_len;
++
++ copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size));
++ memcpy(buf, resp, copy_len);
++ return 0;
++}
++EXPORT_SYMBOL_GPL(lbs_cmd_copyback);
++
++/**
++ * @brief Simple callback that ignores the result. Use this if
++ * you just want to send a command to the hardware, but don't
++ * care for the result.
++ *
++ * @param priv ignored
++ * @param extra ignored
++ * @param resp ignored
++ *
++ * @return 0 for success
++ */
++static int lbs_cmd_async_callback(struct lbs_private *priv, unsigned long extra,
++ struct cmd_header *resp)
++{
++ return 0;
++}
+
+
+ /**
+@@ -143,8 +181,7 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria)
+ }
+ EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg);
+
+-static int lbs_cmd_802_11_ps_mode(struct lbs_private *priv,
+- struct cmd_ds_command *cmd,
++static int lbs_cmd_802_11_ps_mode(struct cmd_ds_command *cmd,
+ u16 cmd_action)
+ {
+ struct cmd_ds_802_11_ps_mode *psm = &cmd->params.psmode;
+@@ -259,6 +296,7 @@ int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
+
+ lbs_deb_enter(LBS_DEB_CMD);
+
++ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP);
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+
+@@ -322,7 +360,9 @@ int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(cmd_action);
+
+- if (cmd_action == CMD_ACT_SET) {
++ if (cmd_action == CMD_ACT_GET)
++ cmd.enable = 0;
++ else {
+ if (*enable)
+ cmd.enable = cpu_to_le16(CMD_ENABLE_RSN);
+ else
+@@ -338,81 +378,108 @@ int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
+ return ret;
+ }
+
+-static void set_one_wpa_key(struct MrvlIEtype_keyParamSet * pkeyparamset,
+- struct enc_key * pkey)
++static void set_one_wpa_key(struct MrvlIEtype_keyParamSet *keyparam,
++ struct enc_key *key)
+ {
+ lbs_deb_enter(LBS_DEB_CMD);
+
+- if (pkey->flags & KEY_INFO_WPA_ENABLED) {
+- pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
+- }
+- if (pkey->flags & KEY_INFO_WPA_UNICAST) {
+- pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
+- }
+- if (pkey->flags & KEY_INFO_WPA_MCAST) {
+- pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
+- }
++ if (key->flags & KEY_INFO_WPA_ENABLED)
++ keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
++ if (key->flags & KEY_INFO_WPA_UNICAST)
++ keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
++ if (key->flags & KEY_INFO_WPA_MCAST)
++ keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
+
+- pkeyparamset->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
+- pkeyparamset->keytypeid = cpu_to_le16(pkey->type);
+- pkeyparamset->keylen = cpu_to_le16(pkey->len);
+- memcpy(pkeyparamset->key, pkey->key, pkey->len);
+- pkeyparamset->length = cpu_to_le16( sizeof(pkeyparamset->keytypeid)
+- + sizeof(pkeyparamset->keyinfo)
+- + sizeof(pkeyparamset->keylen)
+- + sizeof(pkeyparamset->key));
++ keyparam->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
++ keyparam->keytypeid = cpu_to_le16(key->type);
++ keyparam->keylen = cpu_to_le16(key->len);
++ memcpy(keyparam->key, key->key, key->len);
++
++ /* Length field doesn't include the {type,length} header */
++ keyparam->length = cpu_to_le16(sizeof(*keyparam) - 4);
+ lbs_deb_leave(LBS_DEB_CMD);
+ }
+
+-static int lbs_cmd_802_11_key_material(struct lbs_private *priv,
+- struct cmd_ds_command *cmd,
+- u16 cmd_action,
+- u32 cmd_oid, void *pdata_buf)
++int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
++ struct assoc_request *assoc)
+ {
+- struct cmd_ds_802_11_key_material *pkeymaterial =
+- &cmd->params.keymaterial;
+- struct assoc_request * assoc_req = pdata_buf;
++ struct cmd_ds_802_11_key_material cmd;
+ int ret = 0;
+ int index = 0;
+
+ lbs_deb_enter(LBS_DEB_CMD);
+
+- cmd->command = cpu_to_le16(CMD_802_11_KEY_MATERIAL);
+- pkeymaterial->action = cpu_to_le16(cmd_action);
++ cmd.action = cpu_to_le16(cmd_action);
++ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+
+ if (cmd_action == CMD_ACT_GET) {
+- cmd->size = cpu_to_le16(S_DS_GEN + sizeof (pkeymaterial->action));
+- ret = 0;
+- goto done;
+- }
++ cmd.hdr.size = cpu_to_le16(S_DS_GEN + 2);
++ } else {
++ memset(cmd.keyParamSet, 0, sizeof(cmd.keyParamSet));
+
+- memset(&pkeymaterial->keyParamSet, 0, sizeof(pkeymaterial->keyParamSet));
++ if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc->flags)) {
++ set_one_wpa_key(&cmd.keyParamSet[index],
++ &assoc->wpa_unicast_key);
++ index++;
++ }
+
+- if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
+- set_one_wpa_key(&pkeymaterial->keyParamSet[index],
+- &assoc_req->wpa_unicast_key);
+- index++;
+- }
++ if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) {
++ set_one_wpa_key(&cmd.keyParamSet[index],
++ &assoc->wpa_mcast_key);
++ index++;
++ }
+
+- if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
+- set_one_wpa_key(&pkeymaterial->keyParamSet[index],
+- &assoc_req->wpa_mcast_key);
+- index++;
++ /* The common header and as many keys as we included */
++ cmd.hdr.size = cpu_to_le16(offsetof(typeof(cmd),
++ keyParamSet[index]));
+ }
++ ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd);
++ /* Copy the returned key to driver private data */
++ if (!ret && cmd_action == CMD_ACT_GET) {
++ void *buf_ptr = cmd.keyParamSet;
++ void *resp_end = &(&cmd)[1];
++
++ while (buf_ptr < resp_end) {
++ struct MrvlIEtype_keyParamSet *keyparam = buf_ptr;
++ struct enc_key *key;
++ uint16_t param_set_len = le16_to_cpu(keyparam->length);
++ uint16_t key_len = le16_to_cpu(keyparam->keylen);
++ uint16_t key_flags = le16_to_cpu(keyparam->keyinfo);
++ uint16_t key_type = le16_to_cpu(keyparam->keytypeid);
++ void *end;
++
++ end = (void *)keyparam + sizeof(keyparam->type)
++ + sizeof(keyparam->length) + param_set_len;
++
++ /* Make sure we don't access past the end of the IEs */
++ if (end > resp_end)
++ break;
++
++ if (key_flags & KEY_INFO_WPA_UNICAST)
++ key = &priv->wpa_unicast_key;
++ else if (key_flags & KEY_INFO_WPA_MCAST)
++ key = &priv->wpa_mcast_key;
++ else
++ break;
+
+- cmd->size = cpu_to_le16( S_DS_GEN
+- + sizeof (pkeymaterial->action)
+- + (index * sizeof(struct MrvlIEtype_keyParamSet)));
++ /* Copy returned key into driver */
++ memset(key, 0, sizeof(struct enc_key));
++ if (key_len > sizeof(key->key))
++ break;
++ key->type = key_type;
++ key->flags = key_flags;
++ key->len = key_len;
++ memcpy(key->key, keyparam->key, key->len);
+
+- ret = 0;
++ buf_ptr = end + 1;
++ }
++ }
+
+-done:
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+ return ret;
+ }
+
+-static int lbs_cmd_802_11_reset(struct lbs_private *priv,
+- struct cmd_ds_command *cmd, int cmd_action)
++static int lbs_cmd_802_11_reset(struct cmd_ds_command *cmd, int cmd_action)
+ {
+ struct cmd_ds_802_11_reset *reset = &cmd->params.reset;
+
+@@ -426,30 +493,6 @@ static int lbs_cmd_802_11_reset(struct lbs_private *priv,
+ return 0;
+ }
+
+-static int lbs_cmd_802_11_get_log(struct lbs_private *priv,
+- struct cmd_ds_command *cmd)
+-{
+- lbs_deb_enter(LBS_DEB_CMD);
+- cmd->command = cpu_to_le16(CMD_802_11_GET_LOG);
+- cmd->size =
+- cpu_to_le16(sizeof(struct cmd_ds_802_11_get_log) + S_DS_GEN);
+-
+- lbs_deb_leave(LBS_DEB_CMD);
+- return 0;
+-}
+-
+-static int lbs_cmd_802_11_get_stat(struct lbs_private *priv,
+- struct cmd_ds_command *cmd)
+-{
+- lbs_deb_enter(LBS_DEB_CMD);
+- cmd->command = cpu_to_le16(CMD_802_11_GET_STAT);
+- cmd->size =
+- cpu_to_le16(sizeof(struct cmd_ds_802_11_get_stat) + S_DS_GEN);
+-
+- lbs_deb_leave(LBS_DEB_CMD);
+- return 0;
+-}
+-
+ static int lbs_cmd_802_11_snmp_mib(struct lbs_private *priv,
+ struct cmd_ds_command *cmd,
+ int cmd_action,
+@@ -570,8 +613,7 @@ static int lbs_cmd_802_11_snmp_mib(struct lbs_private *priv,
+ return 0;
+ }
+
+-static int lbs_cmd_802_11_rf_tx_power(struct lbs_private *priv,
+- struct cmd_ds_command *cmd,
++static int lbs_cmd_802_11_rf_tx_power(struct cmd_ds_command *cmd,
+ u16 cmd_action, void *pdata_buf)
+ {
+
+@@ -614,8 +656,7 @@ static int lbs_cmd_802_11_rf_tx_power(struct lbs_private *priv,
+ return 0;
+ }
+
+-static int lbs_cmd_802_11_monitor_mode(struct lbs_private *priv,
+- struct cmd_ds_command *cmd,
++static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd,
+ u16 cmd_action, void *pdata_buf)
+ {
+ struct cmd_ds_802_11_monitor_mode *monitor = &cmd->params.monitor;
+@@ -773,6 +814,7 @@ int lbs_get_channel(struct lbs_private *priv)
+
+ lbs_deb_enter(LBS_DEB_CMD);
+
++ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_GET);
+
+@@ -788,6 +830,22 @@ out:
+ return ret;
+ }
+
++int lbs_update_channel(struct lbs_private *priv)
++{
++ int ret;
++
++ /* the channel in f/w could be out of sync; get the current channel */
++ lbs_deb_enter(LBS_DEB_ASSOC);
++
++ ret = lbs_get_channel(priv);
++ if (ret > 0) {
++ priv->curbssparams.channel = ret;
++ ret = 0;
++ }
++ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
++ return ret;
++}
++
+ /**
+ * @brief Set the radio channel
+ *
+@@ -804,6 +862,7 @@ int lbs_set_channel(struct lbs_private *priv, u8 channel)
+
+ lbs_deb_enter(LBS_DEB_CMD);
+
++ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET);
+ cmd.channel = cpu_to_le16(channel);
+@@ -842,8 +901,7 @@ static int lbs_cmd_802_11_rssi(struct lbs_private *priv,
+ return 0;
+ }
+
+-static int lbs_cmd_reg_access(struct lbs_private *priv,
+- struct cmd_ds_command *cmdptr,
++static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr,
+ u8 cmd_action, void *pdata_buf)
+ {
+ struct lbs_offset_value *offval;
+@@ -917,53 +975,7 @@ static int lbs_cmd_reg_access(struct lbs_private *priv,
+ return 0;
+ }
+
+-static int lbs_cmd_802_11_mac_address(struct lbs_private *priv,
+- struct cmd_ds_command *cmd,
+- u16 cmd_action)
+-{
+-
+- lbs_deb_enter(LBS_DEB_CMD);
+- cmd->command = cpu_to_le16(CMD_802_11_MAC_ADDRESS);
+- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_mac_address) +
+- S_DS_GEN);
+- cmd->result = 0;
+-
+- cmd->params.macadd.action = cpu_to_le16(cmd_action);
+-
+- if (cmd_action == CMD_ACT_SET) {
+- memcpy(cmd->params.macadd.macadd,
+- priv->current_addr, ETH_ALEN);
+- lbs_deb_hex(LBS_DEB_CMD, "SET_CMD: MAC addr", priv->current_addr, 6);
+- }
+-
+- lbs_deb_leave(LBS_DEB_CMD);
+- return 0;
+-}
+-
+-static int lbs_cmd_802_11_eeprom_access(struct lbs_private *priv,
+- struct cmd_ds_command *cmd,
+- int cmd_action, void *pdata_buf)
+-{
+- struct lbs_ioctl_regrdwr *ea = pdata_buf;
+-
+- lbs_deb_enter(LBS_DEB_CMD);
+-
+- cmd->command = cpu_to_le16(CMD_802_11_EEPROM_ACCESS);
+- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) +
+- S_DS_GEN);
+- cmd->result = 0;
+-
+- cmd->params.rdeeprom.action = cpu_to_le16(ea->action);
+- cmd->params.rdeeprom.offset = cpu_to_le16(ea->offset);
+- cmd->params.rdeeprom.bytecount = cpu_to_le16(ea->NOB);
+- cmd->params.rdeeprom.value = 0;
+-
+- lbs_deb_leave(LBS_DEB_CMD);
+- return 0;
+-}
+-
+-static int lbs_cmd_bt_access(struct lbs_private *priv,
+- struct cmd_ds_command *cmd,
++static int lbs_cmd_bt_access(struct cmd_ds_command *cmd,
+ u16 cmd_action, void *pdata_buf)
+ {
+ struct cmd_ds_bt_access *bt_access = &cmd->params.bt;
+@@ -1000,8 +1012,7 @@ static int lbs_cmd_bt_access(struct lbs_private *priv,
+ return 0;
+ }
+
+-static int lbs_cmd_fwt_access(struct lbs_private *priv,
+- struct cmd_ds_command *cmd,
++static int lbs_cmd_fwt_access(struct cmd_ds_command *cmd,
+ u16 cmd_action, void *pdata_buf)
+ {
+ struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt;
+@@ -1153,9 +1164,9 @@ static void lbs_submit_command(struct lbs_private *priv,
+ command == CMD_802_11_AUTHENTICATE)
+ timeo = 10 * HZ;
+
+- lbs_deb_host("DNLD_CMD: command 0x%04x, seq %d, size %d, jiffies %lu\n",
+- command, le16_to_cpu(cmd->seqnum), cmdsize, jiffies);
+- lbs_deb_hex(LBS_DEB_HOST, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
++ lbs_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n",
++ command, le16_to_cpu(cmd->seqnum), cmdsize);
++ lbs_deb_hex(LBS_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
+
+ ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize);
+
+@@ -1164,9 +1175,7 @@ static void lbs_submit_command(struct lbs_private *priv,
+ /* Let the timer kick in and retry, and potentially reset
+ the whole thing if the condition persists */
+ timeo = HZ;
+- } else
+- lbs_deb_cmd("DNLD_CMD: sent command 0x%04x, jiffies %lu\n",
+- command, jiffies);
++ }
+
+ /* Setup the timer after transmit command */
+ mod_timer(&priv->command_timer, jiffies + timeo);
+@@ -1174,24 +1183,6 @@ static void lbs_submit_command(struct lbs_private *priv,
+ lbs_deb_leave(LBS_DEB_HOST);
+ }
+
+-static int lbs_cmd_mac_control(struct lbs_private *priv,
+- struct cmd_ds_command *cmd)
+-{
+- struct cmd_ds_mac_control *mac = &cmd->params.macctrl;
+-
+- lbs_deb_enter(LBS_DEB_CMD);
+-
+- cmd->command = cpu_to_le16(CMD_MAC_CONTROL);
+- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_control) + S_DS_GEN);
+- mac->action = cpu_to_le16(priv->currentpacketfilter);
+-
+- lbs_deb_cmd("MAC_CONTROL: action 0x%x, size %d\n",
+- le16_to_cpu(mac->action), le16_to_cpu(cmd->size));
+-
+- lbs_deb_leave(LBS_DEB_CMD);
+- return 0;
+-}
+-
+ /**
+ * This function inserts command node to cmdfreeq
+ * after cleans it. Requires priv->driver_lock held.
+@@ -1234,7 +1225,7 @@ void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
+ cmd->cmdwaitqwoken = 1;
+ wake_up_interruptible(&cmd->cmdwait_q);
+
+- if (!cmd->callback)
++ if (!cmd->callback || cmd->callback == lbs_cmd_async_callback)
+ __lbs_cleanup_and_insert_cmd(priv, cmd);
+ priv->cur_cmd = NULL;
+ }
+@@ -1278,18 +1269,20 @@ int lbs_set_radio_control(struct lbs_private *priv)
+ return ret;
+ }
+
+-int lbs_set_mac_packet_filter(struct lbs_private *priv)
++void lbs_set_mac_control(struct lbs_private *priv)
+ {
+- int ret = 0;
++ struct cmd_ds_mac_control cmd;
+
+ lbs_deb_enter(LBS_DEB_CMD);
+
+- /* Send MAC control command to station */
+- ret = lbs_prepare_and_send_command(priv,
+- CMD_MAC_CONTROL, 0, 0, 0, NULL);
++ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
++ cmd.action = cpu_to_le16(priv->mac_control);
++ cmd.reserved = 0;
+
+- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+- return ret;
++ lbs_cmd_async(priv, CMD_MAC_CONTROL,
++ &cmd.hdr, sizeof(cmd));
++
++ lbs_deb_leave(LBS_DEB_CMD);
+ }
+
+ /**
+@@ -1338,7 +1331,8 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
+ goto done;
+ }
+
+- lbs_set_cmd_ctrl_node(priv, cmdnode, pdata_buf);
++ cmdnode->callback = NULL;
++ cmdnode->callback_arg = (unsigned long)pdata_buf;
+
+ cmdptr = (struct cmd_ds_command *)cmdnode->cmdbuf;
+
+@@ -1353,15 +1347,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
+
+ switch (cmd_no) {
+ case CMD_802_11_PS_MODE:
+- ret = lbs_cmd_802_11_ps_mode(priv, cmdptr, cmd_action);
+- break;
+-
+- case CMD_802_11_SCAN:
+- ret = lbs_cmd_80211_scan(priv, cmdptr, pdata_buf);
+- break;
+-
+- case CMD_MAC_CONTROL:
+- ret = lbs_cmd_mac_control(priv, cmdptr);
++ ret = lbs_cmd_802_11_ps_mode(cmdptr, cmd_action);
+ break;
+
+ case CMD_802_11_ASSOCIATE:
+@@ -1376,25 +1362,15 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
+ case CMD_802_11_AD_HOC_START:
+ ret = lbs_cmd_80211_ad_hoc_start(priv, cmdptr, pdata_buf);
+ break;
+- case CMD_CODE_DNLD:
+- break;
+
+ case CMD_802_11_RESET:
+- ret = lbs_cmd_802_11_reset(priv, cmdptr, cmd_action);
+- break;
+-
+- case CMD_802_11_GET_LOG:
+- ret = lbs_cmd_802_11_get_log(priv, cmdptr);
++ ret = lbs_cmd_802_11_reset(cmdptr, cmd_action);
+ break;
+
+ case CMD_802_11_AUTHENTICATE:
+ ret = lbs_cmd_80211_authenticate(priv, cmdptr, pdata_buf);
+ break;
+
+- case CMD_802_11_GET_STAT:
+- ret = lbs_cmd_802_11_get_stat(priv, cmdptr);
+- break;
+-
+ case CMD_802_11_SNMP_MIB:
+ ret = lbs_cmd_802_11_snmp_mib(priv, cmdptr,
+ cmd_action, cmd_oid, pdata_buf);
+@@ -1403,12 +1379,12 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
+ case CMD_MAC_REG_ACCESS:
+ case CMD_BBP_REG_ACCESS:
+ case CMD_RF_REG_ACCESS:
+- ret = lbs_cmd_reg_access(priv, cmdptr, cmd_action, pdata_buf);
++ ret = lbs_cmd_reg_access(cmdptr, cmd_action, pdata_buf);
+ break;
+
+ case CMD_802_11_RF_TX_POWER:
+- ret = lbs_cmd_802_11_rf_tx_power(priv, cmdptr,
+- cmd_action, pdata_buf);
++ ret = lbs_cmd_802_11_rf_tx_power(cmdptr,
++ cmd_action, pdata_buf);
+ break;
+
+ case CMD_802_11_RATE_ADAPT_RATESET:
+@@ -1421,7 +1397,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
+ break;
+
+ case CMD_802_11_MONITOR_MODE:
+- ret = lbs_cmd_802_11_monitor_mode(priv, cmdptr,
++ ret = lbs_cmd_802_11_monitor_mode(cmdptr,
+ cmd_action, pdata_buf);
+ break;
+
+@@ -1434,26 +1410,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
+ break;
+
+ case CMD_802_11_AD_HOC_STOP:
+- ret = lbs_cmd_80211_ad_hoc_stop(priv, cmdptr);
+- break;
+-
+- case CMD_802_11_KEY_MATERIAL:
+- ret = lbs_cmd_802_11_key_material(priv, cmdptr, cmd_action,
+- cmd_oid, pdata_buf);
+- break;
+-
+- case CMD_802_11_PAIRWISE_TSC:
+- break;
+- case CMD_802_11_GROUP_TSC:
+- break;
+-
+- case CMD_802_11_MAC_ADDRESS:
+- ret = lbs_cmd_802_11_mac_address(priv, cmdptr, cmd_action);
+- break;
+-
+- case CMD_802_11_EEPROM_ACCESS:
+- ret = lbs_cmd_802_11_eeprom_access(priv, cmdptr,
+- cmd_action, pdata_buf);
++ ret = lbs_cmd_80211_ad_hoc_stop(cmdptr);
+ break;
+
+ case CMD_802_11_SET_AFC:
+@@ -1509,22 +1466,12 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
+ break;
+ }
+
+- case CMD_802_11_PWR_CFG:
+- cmdptr->command = cpu_to_le16(CMD_802_11_PWR_CFG);
+- cmdptr->size =
+- cpu_to_le16(sizeof(struct cmd_ds_802_11_pwr_cfg) +
+- S_DS_GEN);
+- memmove(&cmdptr->params.pwrcfg, pdata_buf,
+- sizeof(struct cmd_ds_802_11_pwr_cfg));
+-
+- ret = 0;
+- break;
+ case CMD_BT_ACCESS:
+- ret = lbs_cmd_bt_access(priv, cmdptr, cmd_action, pdata_buf);
++ ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf);
+ break;
+
+ case CMD_FWT_ACCESS:
+- ret = lbs_cmd_fwt_access(priv, cmdptr, cmd_action, pdata_buf);
++ ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf);
+ break;
+
+ case CMD_GET_TSF:
+@@ -1697,36 +1644,6 @@ static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv)
+ }
+
+ /**
+- * @brief This function cleans command node.
+- *
+- * @param ptempnode A pointer to cmdCtrlNode structure
+- * @return n/a
+- */
+-
+-/**
+- * @brief This function initializes the command node.
+- *
+- * @param priv A pointer to struct lbs_private structure
+- * @param ptempnode A pointer to cmd_ctrl_node structure
+- * @param pdata_buf A pointer to informaion buffer
+- * @return 0 or -1
+- */
+-static void lbs_set_cmd_ctrl_node(struct lbs_private *priv,
+- struct cmd_ctrl_node *ptempnode,
+- void *pdata_buf)
+-{
+- lbs_deb_enter(LBS_DEB_HOST);
+-
+- if (!ptempnode)
+- return;
+-
+- ptempnode->callback = NULL;
+- ptempnode->callback_arg = (unsigned long)pdata_buf;
+-
+- lbs_deb_leave(LBS_DEB_HOST);
+-}
+-
+-/**
+ * @brief This function executes next command in command
+ * pending queue. It will put fimware back to PS mode
+ * if applicable.
+@@ -1741,9 +1658,9 @@ int lbs_execute_next_command(struct lbs_private *priv)
+ unsigned long flags;
+ int ret = 0;
+
+- // Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
+- // only caller to us is lbs_thread() and we get even when a
+- // data packet is received
++ /* Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
++ * only caller to us is lbs_thread() and we get even when a
++ * data packet is received */
+ lbs_deb_enter(LBS_DEB_THREAD);
+
+ spin_lock_irqsave(&priv->driver_lock, flags);
+@@ -1907,44 +1824,32 @@ void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str)
+ lbs_deb_leave(LBS_DEB_WEXT);
+ }
+
+-static int sendconfirmsleep(struct lbs_private *priv, u8 *cmdptr, u16 size)
++static void lbs_send_confirmsleep(struct lbs_private *priv)
+ {
+ unsigned long flags;
+- int ret = 0;
++ int ret;
+
+ lbs_deb_enter(LBS_DEB_HOST);
++ lbs_deb_hex(LBS_DEB_HOST, "sleep confirm", (u8 *) &confirm_sleep,
++ sizeof(confirm_sleep));
+
+- lbs_deb_host("SEND_SLEEPC_CMD: before download, cmd size %d\n",
+- size);
+-
+- lbs_deb_hex(LBS_DEB_HOST, "sleep confirm command", cmdptr, size);
+-
+- ret = priv->hw_host_to_card(priv, MVMS_CMD, cmdptr, size);
++ ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &confirm_sleep,
++ sizeof(confirm_sleep));
++ if (ret) {
++ lbs_pr_alert("confirm_sleep failed\n");
++ goto out;
++ }
+
+ spin_lock_irqsave(&priv->driver_lock, flags);
+- if (priv->intcounter || priv->currenttxskb)
+- lbs_deb_host("SEND_SLEEPC_CMD: intcounter %d, currenttxskb %p\n",
+- priv->intcounter, priv->currenttxskb);
+- spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+- if (ret) {
+- lbs_pr_alert(
+- "SEND_SLEEPC_CMD: Host to Card failed for Confirm Sleep\n");
+- } else {
+- spin_lock_irqsave(&priv->driver_lock, flags);
+- if (!priv->intcounter) {
+- priv->psstate = PS_STATE_SLEEP;
+- } else {
+- lbs_deb_host("SEND_SLEEPC_CMD: after sent, intcounter %d\n",
+- priv->intcounter);
+- }
+- spin_unlock_irqrestore(&priv->driver_lock, flags);
++ /* If nothing to do, go back to sleep (?) */
++ if (!__kfifo_len(priv->event_fifo) && !priv->resp_len[priv->resp_idx])
++ priv->psstate = PS_STATE_SLEEP;
+
+- lbs_deb_host("SEND_SLEEPC_CMD: sent confirm sleep\n");
+- }
++ spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+- lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
+- return ret;
++out:
++ lbs_deb_leave(LBS_DEB_HOST);
+ }
+
+ void lbs_ps_sleep(struct lbs_private *priv, int wait_option)
+@@ -1992,10 +1897,10 @@ void lbs_ps_wakeup(struct lbs_private *priv, int wait_option)
+ * @param psmode Power Saving mode
+ * @return n/a
+ */
+-void lbs_ps_confirm_sleep(struct lbs_private *priv, u16 psmode)
++void lbs_ps_confirm_sleep(struct lbs_private *priv)
+ {
+ unsigned long flags =0;
+- u8 allowed = 1;
++ int allowed = 1;
+
+ lbs_deb_enter(LBS_DEB_HOST);
+
+@@ -2005,20 +1910,22 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv, u16 psmode)
+ }
+
+ spin_lock_irqsave(&priv->driver_lock, flags);
++ /* In-progress command? */
+ if (priv->cur_cmd) {
+ allowed = 0;
+ lbs_deb_host("cur_cmd was set\n");
+ }
+- if (priv->intcounter > 0) {
++
++ /* Pending events or command responses? */
++ if (__kfifo_len(priv->event_fifo) || priv->resp_len[priv->resp_idx]) {
+ allowed = 0;
+- lbs_deb_host("intcounter %d\n", priv->intcounter);
++ lbs_deb_host("pending events or command responses\n");
+ }
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+ if (allowed) {
+ lbs_deb_host("sending lbs_ps_confirm_sleep\n");
+- sendconfirmsleep(priv, (u8 *) & priv->lbs_ps_confirm_sleep,
+- sizeof(struct PS_CMD_ConfirmSleep));
++ lbs_send_confirmsleep(priv);
+ } else {
+ lbs_deb_host("sleep confirm has been delayed\n");
+ }
+@@ -2027,39 +1934,10 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv, u16 psmode)
+ }
+
+
+-/**
+- * @brief Simple callback that copies response back into command
+- *
+- * @param priv A pointer to struct lbs_private structure
+- * @param extra A pointer to the original command structure for which
+- * 'resp' is a response
+- * @param resp A pointer to the command response
+- *
+- * @return 0 on success, error on failure
+- */
+-int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
+- struct cmd_header *resp)
+-{
+- struct cmd_header *buf = (void *)extra;
+- uint16_t copy_len;
+-
+- lbs_deb_enter(LBS_DEB_CMD);
+-
+- copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size));
+- lbs_deb_cmd("Copying back %u bytes; command response was %u bytes, "
+- "copy back buffer was %u bytes\n", copy_len,
+- le16_to_cpu(resp->size), le16_to_cpu(buf->size));
+- memcpy(buf, resp, copy_len);
+-
+- lbs_deb_leave(LBS_DEB_CMD);
+- return 0;
+-}
+-EXPORT_SYMBOL_GPL(lbs_cmd_copyback);
+-
+-struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, uint16_t command,
+- struct cmd_header *in_cmd, int in_cmd_size,
+- int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
+- unsigned long callback_arg)
++static struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
++ uint16_t command, struct cmd_header *in_cmd, int in_cmd_size,
++ int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
++ unsigned long callback_arg)
+ {
+ struct cmd_ctrl_node *cmdnode;
+
+@@ -2096,9 +1974,6 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, uint16_t command
+
+ lbs_deb_host("PREP_CMD: command 0x%04x\n", command);
+
+- /* here was the big old switch() statement, which is now obsolete,
+- * because the caller of lbs_cmd() sets up all of *cmd for us. */
+-
+ cmdnode->cmdwaitqwoken = 0;
+ lbs_queue_cmd(priv, cmdnode);
+ wake_up_interruptible(&priv->waitq);
+@@ -2108,6 +1983,15 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, uint16_t command
+ return cmdnode;
+ }
+
++void lbs_cmd_async(struct lbs_private *priv, uint16_t command,
++ struct cmd_header *in_cmd, int in_cmd_size)
++{
++ lbs_deb_enter(LBS_DEB_CMD);
++ __lbs_cmd_async(priv, command, in_cmd, in_cmd_size,
++ lbs_cmd_async_callback, 0);
++ lbs_deb_leave(LBS_DEB_CMD);
++}
++
+ int __lbs_cmd(struct lbs_private *priv, uint16_t command,
+ struct cmd_header *in_cmd, int in_cmd_size,
+ int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
+diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h
+index b9ab85c..3dfc2d4 100644
+--- a/drivers/net/wireless/libertas/cmd.h
++++ b/drivers/net/wireless/libertas/cmd.h
+@@ -18,12 +18,9 @@
+ #define lbs_cmd_with_response(priv, cmdnr, cmd) \
+ lbs_cmd(priv, cmdnr, cmd, lbs_cmd_copyback, (unsigned long) (cmd))
+
+-/* __lbs_cmd() will free the cmdnode and return success/failure.
+- __lbs_cmd_async() requires that the callback free the cmdnode */
+-struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, uint16_t command,
+- struct cmd_header *in_cmd, int in_cmd_size,
+- int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
+- unsigned long callback_arg);
++void lbs_cmd_async(struct lbs_private *priv, uint16_t command,
++ struct cmd_header *in_cmd, int in_cmd_size);
++
+ int __lbs_cmd(struct lbs_private *priv, uint16_t command,
+ struct cmd_header *in_cmd, int in_cmd_size,
+ int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
+@@ -57,5 +54,7 @@ int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
+ struct assoc_request *assoc);
+ int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
+ uint16_t *enable);
++int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
++ struct assoc_request *assoc);
+
+ #endif /* _LBS_CMD_H */
+diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
+index f0ef708..5abecb7 100644
+--- a/drivers/net/wireless/libertas/cmdresp.c
++++ b/drivers/net/wireless/libertas/cmdresp.c
+@@ -12,7 +12,7 @@
+ #include "decl.h"
+ #include "defs.h"
+ #include "dev.h"
+-#include "join.h"
++#include "assoc.h"
+ #include "wext.h"
+
+ /**
+@@ -74,7 +74,7 @@ void lbs_mac_event_disconnected(struct lbs_private *priv)
+ lbs_deb_cmd("disconnected, so exit PS mode\n");
+ lbs_ps_wakeup(priv, 0);
+ }
+- lbs_deb_leave(LBS_DEB_CMD);
++ lbs_deb_leave(LBS_DEB_ASSOC);
+ }
+
+ /**
+@@ -146,22 +146,6 @@ static int lbs_ret_reg_access(struct lbs_private *priv,
+ return ret;
+ }
+
+-static int lbs_ret_802_11_stat(struct lbs_private *priv,
+- struct cmd_ds_command *resp)
+-{
+- lbs_deb_enter(LBS_DEB_CMD);
+-/* currently priv->wlan802_11Stat is unused
+-
+- struct cmd_ds_802_11_get_stat *p11Stat = &resp->params.gstat;
+-
+- // TODO Convert it to Big endian befor copy
+- memcpy(&priv->wlan802_11Stat,
+- p11Stat, sizeof(struct cmd_ds_802_11_get_stat));
+-*/
+- lbs_deb_leave(LBS_DEB_CMD);
+- return 0;
+-}
+-
+ static int lbs_ret_802_11_snmp_mib(struct lbs_private *priv,
+ struct cmd_ds_command *resp)
+ {
+@@ -204,74 +188,6 @@ static int lbs_ret_802_11_snmp_mib(struct lbs_private *priv,
+ return 0;
+ }
+
+-static int lbs_ret_802_11_key_material(struct lbs_private *priv,
+- struct cmd_ds_command *resp)
+-{
+- struct cmd_ds_802_11_key_material *pkeymaterial =
+- &resp->params.keymaterial;
+- u16 action = le16_to_cpu(pkeymaterial->action);
+-
+- lbs_deb_enter(LBS_DEB_CMD);
+-
+- /* Copy the returned key to driver private data */
+- if (action == CMD_ACT_GET) {
+- u8 * buf_ptr = (u8 *) &pkeymaterial->keyParamSet;
+- u8 * resp_end = (u8 *) (resp + le16_to_cpu(resp->size));
+-
+- while (buf_ptr < resp_end) {
+- struct MrvlIEtype_keyParamSet * pkeyparamset =
+- (struct MrvlIEtype_keyParamSet *) buf_ptr;
+- struct enc_key * pkey;
+- u16 param_set_len = le16_to_cpu(pkeyparamset->length);
+- u16 key_len = le16_to_cpu(pkeyparamset->keylen);
+- u16 key_flags = le16_to_cpu(pkeyparamset->keyinfo);
+- u16 key_type = le16_to_cpu(pkeyparamset->keytypeid);
+- u8 * end;
+-
+- end = (u8 *) pkeyparamset + sizeof (pkeyparamset->type)
+- + sizeof (pkeyparamset->length)
+- + param_set_len;
+- /* Make sure we don't access past the end of the IEs */
+- if (end > resp_end)
+- break;
+-
+- if (key_flags & KEY_INFO_WPA_UNICAST)
+- pkey = &priv->wpa_unicast_key;
+- else if (key_flags & KEY_INFO_WPA_MCAST)
+- pkey = &priv->wpa_mcast_key;
+- else
+- break;
+-
+- /* Copy returned key into driver */
+- memset(pkey, 0, sizeof(struct enc_key));
+- if (key_len > sizeof(pkey->key))
+- break;
+- pkey->type = key_type;
+- pkey->flags = key_flags;
+- pkey->len = key_len;
+- memcpy(pkey->key, pkeyparamset->key, pkey->len);
+-
+- buf_ptr = end + 1;
+- }
+- }
+-
+- lbs_deb_enter(LBS_DEB_CMD);
+- return 0;
+-}
+-
+-static int lbs_ret_802_11_mac_address(struct lbs_private *priv,
+- struct cmd_ds_command *resp)
+-{
+- struct cmd_ds_802_11_mac_address *macadd = &resp->params.macadd;
+-
+- lbs_deb_enter(LBS_DEB_CMD);
+-
+- memcpy(priv->current_addr, macadd->macadd, ETH_ALEN);
+-
+- lbs_deb_enter(LBS_DEB_CMD);
+- return 0;
+-}
+-
+ static int lbs_ret_802_11_rf_tx_power(struct lbs_private *priv,
+ struct cmd_ds_command *resp)
+ {
+@@ -333,45 +249,6 @@ static int lbs_ret_802_11_rssi(struct lbs_private *priv,
+ return 0;
+ }
+
+-static int lbs_ret_802_11_eeprom_access(struct lbs_private *priv,
+- struct cmd_ds_command *resp)
+-{
+- struct lbs_ioctl_regrdwr *pbuf;
+- pbuf = (struct lbs_ioctl_regrdwr *) priv->prdeeprom;
+-
+- lbs_deb_enter_args(LBS_DEB_CMD, "len %d",
+- le16_to_cpu(resp->params.rdeeprom.bytecount));
+- if (pbuf->NOB < le16_to_cpu(resp->params.rdeeprom.bytecount)) {
+- pbuf->NOB = 0;
+- lbs_deb_cmd("EEPROM read length too big\n");
+- return -1;
+- }
+- pbuf->NOB = le16_to_cpu(resp->params.rdeeprom.bytecount);
+- if (pbuf->NOB > 0) {
+-
+- memcpy(&pbuf->value, (u8 *) & resp->params.rdeeprom.value,
+- le16_to_cpu(resp->params.rdeeprom.bytecount));
+- lbs_deb_hex(LBS_DEB_CMD, "EEPROM", (char *)&pbuf->value,
+- le16_to_cpu(resp->params.rdeeprom.bytecount));
+- }
+- lbs_deb_leave(LBS_DEB_CMD);
+- return 0;
+-}
+-
+-static int lbs_ret_get_log(struct lbs_private *priv,
+- struct cmd_ds_command *resp)
+-{
+- struct cmd_ds_802_11_get_log *logmessage = &resp->params.glog;
+-
+- lbs_deb_enter(LBS_DEB_CMD);
+-
+- /* Stored little-endian */
+- memcpy(&priv->logmsg, logmessage, sizeof(struct cmd_ds_802_11_get_log));
+-
+- lbs_deb_leave(LBS_DEB_CMD);
+- return 0;
+-}
+-
+ static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv,
+ struct cmd_ds_command *resp)
+ {
+@@ -390,7 +267,6 @@ static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv,
+ }
+
+ static inline int handle_cmd_response(struct lbs_private *priv,
+- unsigned long dummy,
+ struct cmd_header *cmd_response)
+ {
+ struct cmd_ds_command *resp = (struct cmd_ds_command *) cmd_response;
+@@ -407,14 +283,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
+ ret = lbs_ret_reg_access(priv, respcmd, resp);
+ break;
+
+- case CMD_RET(CMD_802_11_SCAN):
+- ret = lbs_ret_80211_scan(priv, resp);
+- break;
+-
+- case CMD_RET(CMD_802_11_GET_LOG):
+- ret = lbs_ret_get_log(priv, resp);
+- break;
+-
+ case CMD_RET_802_11_ASSOCIATE:
+ case CMD_RET(CMD_802_11_ASSOCIATE):
+ case CMD_RET(CMD_802_11_REASSOCIATE):
+@@ -423,7 +291,7 @@ static inline int handle_cmd_response(struct lbs_private *priv,
+
+ case CMD_RET(CMD_802_11_DISASSOCIATE):
+ case CMD_RET(CMD_802_11_DEAUTHENTICATE):
+- ret = lbs_ret_80211_disassociate(priv, resp);
++ ret = lbs_ret_80211_disassociate(priv);
+ break;
+
+ case CMD_RET(CMD_802_11_AD_HOC_START):
+@@ -431,10 +299,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
+ ret = lbs_ret_80211_ad_hoc_start(priv, resp);
+ break;
+
+- case CMD_RET(CMD_802_11_GET_STAT):
+- ret = lbs_ret_802_11_stat(priv, resp);
+- break;
+-
+ case CMD_RET(CMD_802_11_SNMP_MIB):
+ ret = lbs_ret_802_11_snmp_mib(priv, resp);
+ break;
+@@ -453,7 +317,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
+ break;
+
+ case CMD_RET(CMD_MAC_MULTICAST_ADR):
+- case CMD_RET(CMD_MAC_CONTROL):
+ case CMD_RET(CMD_802_11_RESET):
+ case CMD_RET(CMD_802_11_AUTHENTICATE):
+ case CMD_RET(CMD_802_11_BEACON_STOP):
+@@ -467,24 +330,12 @@ static inline int handle_cmd_response(struct lbs_private *priv,
+ ret = lbs_ret_802_11_rssi(priv, resp);
+ break;
+
+- case CMD_RET(CMD_802_11_MAC_ADDRESS):
+- ret = lbs_ret_802_11_mac_address(priv, resp);
+- break;
+-
+ case CMD_RET(CMD_802_11_AD_HOC_STOP):
+- ret = lbs_ret_80211_ad_hoc_stop(priv, resp);
+- break;
+-
+- case CMD_RET(CMD_802_11_KEY_MATERIAL):
+- ret = lbs_ret_802_11_key_material(priv, resp);
+- break;
+-
+- case CMD_RET(CMD_802_11_EEPROM_ACCESS):
+- ret = lbs_ret_802_11_eeprom_access(priv, resp);
++ ret = lbs_ret_80211_ad_hoc_stop(priv);
+ break;
+
+ case CMD_RET(CMD_802_11D_DOMAIN_INFO):
+- ret = lbs_ret_802_11d_domain_info(priv, resp);
++ ret = lbs_ret_802_11d_domain_info(resp);
+ break;
+
+ case CMD_RET(CMD_802_11_TPC_CFG):
+@@ -500,14 +351,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+ break;
+
+- case CMD_RET(CMD_802_11_PWR_CFG):
+- spin_lock_irqsave(&priv->driver_lock, flags);
+- memmove((void *)priv->cur_cmd->callback_arg, &resp->params.pwrcfg,
+- sizeof(struct cmd_ds_802_11_pwr_cfg));
+- spin_unlock_irqrestore(&priv->driver_lock, flags);
+-
+- break;
+-
+ case CMD_RET(CMD_GET_TSF):
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ memcpy((void *)priv->cur_cmd->callback_arg,
+@@ -541,7 +384,7 @@ static inline int handle_cmd_response(struct lbs_private *priv,
+ return ret;
+ }
+
+-int lbs_process_rx_command(struct lbs_private *priv)
++int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
+ {
+ uint16_t respcmd, curcmd;
+ struct cmd_header *resp;
+@@ -561,14 +404,14 @@ int lbs_process_rx_command(struct lbs_private *priv)
+ goto done;
+ }
+
+- resp = (void *)priv->upld_buf;
++ resp = (void *)data;
+ curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command);
+ respcmd = le16_to_cpu(resp->command);
+ result = le16_to_cpu(resp->result);
+
+- lbs_deb_host("CMD_RESP: response 0x%04x, seq %d, size %d, jiffies %lu\n",
+- respcmd, le16_to_cpu(resp->seqnum), priv->upld_len, jiffies);
+- lbs_deb_hex(LBS_DEB_HOST, "CMD_RESP", (void *) resp, priv->upld_len);
++ lbs_deb_cmd("CMD_RESP: response 0x%04x, seq %d, size %d\n",
++ respcmd, le16_to_cpu(resp->seqnum), len);
++ lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, len);
+
+ if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) {
+ lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n",
+@@ -687,7 +530,7 @@ int lbs_process_rx_command(struct lbs_private *priv)
+ ret = priv->cur_cmd->callback(priv, priv->cur_cmd->callback_arg,
+ resp);
+ } else
+- ret = handle_cmd_response(priv, 0, resp);
++ ret = handle_cmd_response(priv, resp);
+
+ spin_lock_irqsave(&priv->driver_lock, flags);
+
+@@ -705,21 +548,20 @@ done:
+
+ static int lbs_send_confirmwake(struct lbs_private *priv)
+ {
+- struct cmd_header *cmd = &priv->lbs_ps_confirm_wake;
++ struct cmd_header cmd;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_HOST);
+
+- cmd->command = cpu_to_le16(CMD_802_11_WAKEUP_CONFIRM);
+- cmd->size = cpu_to_le16(sizeof(*cmd));
+- cmd->seqnum = cpu_to_le16(++priv->seqnum);
+- cmd->result = 0;
+-
+- lbs_deb_host("SEND_WAKEC_CMD: before download\n");
++ cmd.command = cpu_to_le16(CMD_802_11_WAKEUP_CONFIRM);
++ cmd.size = cpu_to_le16(sizeof(cmd));
++ cmd.seqnum = cpu_to_le16(++priv->seqnum);
++ cmd.result = 0;
+
+- lbs_deb_hex(LBS_DEB_HOST, "wake confirm command", (void *)cmd, sizeof(*cmd));
++ lbs_deb_hex(LBS_DEB_HOST, "wake confirm", (u8 *) &cmd,
++ sizeof(cmd));
+
+- ret = priv->hw_host_to_card(priv, MVMS_CMD, (void *)cmd, sizeof(*cmd));
++ ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &cmd, sizeof(cmd));
+ if (ret)
+ lbs_pr_alert("SEND_WAKEC_CMD: Host to Card failed for Confirm Wake\n");
+
+@@ -727,22 +569,15 @@ static int lbs_send_confirmwake(struct lbs_private *priv)
+ return ret;
+ }
+
+-int lbs_process_event(struct lbs_private *priv)
++int lbs_process_event(struct lbs_private *priv, u32 event)
+ {
+ int ret = 0;
+- u32 eventcause;
+
+ lbs_deb_enter(LBS_DEB_CMD);
+
+- spin_lock_irq(&priv->driver_lock);
+- eventcause = priv->eventcause >> SBI_EVENT_CAUSE_SHIFT;
+- spin_unlock_irq(&priv->driver_lock);
+-
+- lbs_deb_cmd("event cause %d\n", eventcause);
+-
+- switch (eventcause) {
++ switch (event) {
+ case MACREG_INT_CODE_LINK_SENSED:
+- lbs_deb_cmd("EVENT: MACREG_INT_CODE_LINK_SENSED\n");
++ lbs_deb_cmd("EVENT: link sensed\n");
+ break;
+
+ case MACREG_INT_CODE_DEAUTHENTICATED:
+@@ -761,7 +596,7 @@ int lbs_process_event(struct lbs_private *priv)
+ break;
+
+ case MACREG_INT_CODE_PS_SLEEP:
+- lbs_deb_cmd("EVENT: sleep\n");
++ lbs_deb_cmd("EVENT: ps sleep\n");
+
+ /* handle unexpected PS SLEEP event */
+ if (priv->psstate == PS_STATE_FULL_POWER) {
+@@ -771,17 +606,17 @@ int lbs_process_event(struct lbs_private *priv)
+ }
+ priv->psstate = PS_STATE_PRE_SLEEP;
+
+- lbs_ps_confirm_sleep(priv, (u16) priv->psmode);
++ lbs_ps_confirm_sleep(priv);
+
+ break;
+
+ case MACREG_INT_CODE_HOST_AWAKE:
+- lbs_deb_cmd("EVENT: HOST_AWAKE\n");
++ lbs_deb_cmd("EVENT: host awake\n");
+ lbs_send_confirmwake(priv);
+ break;
+
+ case MACREG_INT_CODE_PS_AWAKE:
+- lbs_deb_cmd("EVENT: awake\n");
++ lbs_deb_cmd("EVENT: ps awake\n");
+ /* handle unexpected PS AWAKE event */
+ if (priv->psstate == PS_STATE_FULL_POWER) {
+ lbs_deb_cmd(
+@@ -812,14 +647,16 @@ int lbs_process_event(struct lbs_private *priv)
+ lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n");
+ handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST);
+ break;
++
+ case MACREG_INT_CODE_MIB_CHANGED:
++ lbs_deb_cmd("EVENT: MIB CHANGED\n");
++ break;
+ case MACREG_INT_CODE_INIT_DONE:
++ lbs_deb_cmd("EVENT: INIT DONE\n");
+ break;
+-
+ case MACREG_INT_CODE_ADHOC_BCN_LOST:
+ lbs_deb_cmd("EVENT: ADHOC beacon lost\n");
+ break;
+-
+ case MACREG_INT_CODE_RSSI_LOW:
+ lbs_pr_alert("EVENT: rssi low\n");
+ break;
+@@ -854,14 +691,10 @@ int lbs_process_event(struct lbs_private *priv)
+ break;
+
+ default:
+- lbs_pr_alert("EVENT: unknown event id %d\n", eventcause);
++ lbs_pr_alert("EVENT: unknown event id %d\n", event);
+ break;
+ }
+
+- spin_lock_irq(&priv->driver_lock);
+- priv->eventcause = 0;
+- spin_unlock_irq(&priv->driver_lock);
+-
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+ return ret;
+ }
+diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
+index fd67b77..ad2fabc 100644
+--- a/drivers/net/wireless/libertas/debugfs.c
++++ b/drivers/net/wireless/libertas/debugfs.c
+@@ -19,7 +19,7 @@ static char *szStates[] = {
+ };
+
+ #ifdef PROC_DEBUG
+-static void lbs_debug_init(struct lbs_private *priv, struct net_device *dev);
++static void lbs_debug_init(struct lbs_private *priv);
+ #endif
+
+ static int open_file_generic(struct inode *inode, struct file *file)
+@@ -78,7 +78,7 @@ static ssize_t lbs_getscantable(struct file *file, char __user *userbuf,
+ u16 spectrum_mgmt = (iter_bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT);
+
+ pos += snprintf(buf+pos, len-pos,
+- "%02u| %03d | %04ld | %s |",
++ "%02u| %03d | %04d | %s |",
+ numscansdone, iter_bss->channel, iter_bss->rssi,
+ print_mac(mac, iter_bss->bssid));
+ pos += snprintf(buf+pos, len-pos, " %04x-", iter_bss->capability);
+@@ -164,173 +164,6 @@ out_unlock:
+ return ret;
+ }
+
+-static ssize_t lbs_extscan(struct file *file, const char __user *userbuf,
+- size_t count, loff_t *ppos)
+-{
+- struct lbs_private *priv = file->private_data;
+- ssize_t res, buf_size;
+- union iwreq_data wrqu;
+- unsigned long addr = get_zeroed_page(GFP_KERNEL);
+- char *buf = (char *)addr;
+-
+- buf_size = min(count, len - 1);
+- if (copy_from_user(buf, userbuf, buf_size)) {
+- res = -EFAULT;
+- goto out_unlock;
+- }
+-
+- lbs_send_specific_ssid_scan(priv, buf, strlen(buf)-1, 0);
+-
+- memset(&wrqu, 0, sizeof(union iwreq_data));
+- wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
+-
+-out_unlock:
+- free_page(addr);
+- return count;
+-}
+-
+-static void lbs_parse_bssid(char *buf, size_t count,
+- struct lbs_ioctl_user_scan_cfg *scan_cfg)
+-{
+- char *hold;
+- unsigned int mac[ETH_ALEN];
+-
+- hold = strstr(buf, "bssid=");
+- if (!hold)
+- return;
+- hold += 6;
+- sscanf(hold, "%02x:%02x:%02x:%02x:%02x:%02x",
+- mac, mac+1, mac+2, mac+3, mac+4, mac+5);
+- memcpy(scan_cfg->bssid, mac, ETH_ALEN);
+-}
+-
+-static void lbs_parse_ssid(char *buf, size_t count,
+- struct lbs_ioctl_user_scan_cfg *scan_cfg)
+-{
+- char *hold, *end;
+- ssize_t size;
+-
+- hold = strstr(buf, "ssid=");
+- if (!hold)
+- return;
+- hold += 5;
+- end = strchr(hold, ' ');
+- if (!end)
+- end = buf + count - 1;
+-
+- size = min((size_t)IW_ESSID_MAX_SIZE, (size_t) (end - hold));
+- strncpy(scan_cfg->ssid, hold, size);
+-
+- return;
+-}
+-
+-static int lbs_parse_clear(char *buf, size_t count, const char *tag)
+-{
+- char *hold;
+- int val;
+-
+- hold = strstr(buf, tag);
+- if (!hold)
+- return 0;
+- hold += strlen(tag);
+- sscanf(hold, "%d", &val);
+-
+- if (val != 0)
+- val = 1;
+-
+- return val;
+-}
+-
+-static int lbs_parse_dur(char *buf, size_t count,
+- struct lbs_ioctl_user_scan_cfg *scan_cfg)
+-{
+- char *hold;
+- int val;
+-
+- hold = strstr(buf, "dur=");
+- if (!hold)
+- return 0;
+- hold += 4;
+- sscanf(hold, "%d", &val);
+-
+- return val;
+-}
+-
+-static void lbs_parse_type(char *buf, size_t count,
+- struct lbs_ioctl_user_scan_cfg *scan_cfg)
+-{
+- char *hold;
+- int val;
+-
+- hold = strstr(buf, "type=");
+- if (!hold)
+- return;
+- hold += 5;
+- sscanf(hold, "%d", &val);
+-
+- /* type=1,2 or 3 */
+- if (val < 1 || val > 3)
+- return;
+-
+- scan_cfg->bsstype = val;
+-
+- return;
+-}
+-
+-static ssize_t lbs_setuserscan(struct file *file,
+- const char __user *userbuf,
+- size_t count, loff_t *ppos)
+-{
+- struct lbs_private *priv = file->private_data;
+- ssize_t res, buf_size;
+- struct lbs_ioctl_user_scan_cfg *scan_cfg;
+- union iwreq_data wrqu;
+- int dur;
+- char *buf = (char *)get_zeroed_page(GFP_KERNEL);
+-
+- if (!buf)
+- return -ENOMEM;
+-
+- buf_size = min(count, len - 1);
+- if (copy_from_user(buf, userbuf, buf_size)) {
+- res = -EFAULT;
+- goto out_buf;
+- }
+-
+- scan_cfg = kzalloc(sizeof(struct lbs_ioctl_user_scan_cfg), GFP_KERNEL);
+- if (!scan_cfg) {
+- res = -ENOMEM;
+- goto out_buf;
+- }
+- res = count;
+-
+- scan_cfg->bsstype = LBS_SCAN_BSS_TYPE_ANY;
+-
+- dur = lbs_parse_dur(buf, count, scan_cfg);
+- lbs_parse_bssid(buf, count, scan_cfg);
+- scan_cfg->clear_bssid = lbs_parse_clear(buf, count, "clear_bssid=");
+- lbs_parse_ssid(buf, count, scan_cfg);
+- scan_cfg->clear_ssid = lbs_parse_clear(buf, count, "clear_ssid=");
+- lbs_parse_type(buf, count, scan_cfg);
+-
+- lbs_scan_networks(priv, scan_cfg, 1);
+- wait_event_interruptible(priv->cmd_pending,
+- priv->surpriseremoved || !priv->last_scanned_channel);
+-
+- if (priv->surpriseremoved)
+- goto out_scan_cfg;
+-
+- memset(&wrqu, 0x00, sizeof(union iwreq_data));
+- wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
+-
+- out_scan_cfg:
+- kfree(scan_cfg);
+- out_buf:
+- free_page((unsigned long)buf);
+- return res;
+-}
+-
+-
+ /*
+ * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might
+ * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the
+@@ -857,8 +690,6 @@ static struct lbs_debugfs_files debugfs_files[] = {
+ write_file_dummy), },
+ { "sleepparams", 0644, FOPS(lbs_sleepparams_read,
+ lbs_sleepparams_write), },
+- { "extscan", 0600, FOPS(NULL, lbs_extscan), },
+- { "setuserscan", 0600, FOPS(NULL, lbs_setuserscan), },
+ };
+
+ static struct lbs_debugfs_files debugfs_events_files[] = {
+@@ -947,7 +778,7 @@ void lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev)
+ }
+
+ #ifdef PROC_DEBUG
+- lbs_debug_init(priv, dev);
++ lbs_debug_init(priv);
+ #endif
+ exit:
+ return;
+@@ -993,7 +824,6 @@ struct debug_data {
+ /* To debug any member of struct lbs_private, simply add one line here.
+ */
+ static struct debug_data items[] = {
+- {"intcounter", item_size(intcounter), item_addr(intcounter)},
+ {"psmode", item_size(psmode), item_addr(psmode)},
+ {"psstate", item_size(psstate), item_addr(psstate)},
+ };
+@@ -1121,7 +951,7 @@ static struct file_operations lbs_debug_fops = {
+ * @param dev pointer net_device
+ * @return N/A
+ */
+-static void lbs_debug_init(struct lbs_private *priv, struct net_device *dev)
++static void lbs_debug_init(struct lbs_private *priv)
+ {
+ int i;
+
+diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
+index 4e22341..b652fa3 100644
+--- a/drivers/net/wireless/libertas/decl.h
++++ b/drivers/net/wireless/libertas/decl.h
+@@ -17,9 +17,9 @@ struct net_device;
+ struct cmd_ctrl_node;
+ struct cmd_ds_command;
+
+-int lbs_set_mac_packet_filter(struct lbs_private *priv);
++void lbs_set_mac_control(struct lbs_private *priv);
+
+-void lbs_send_tx_feedback(struct lbs_private *priv);
++void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count);
+
+ int lbs_free_cmd_buffer(struct lbs_private *priv);
+
+@@ -30,17 +30,16 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
+
+ int lbs_allocate_cmd_buffer(struct lbs_private *priv);
+ int lbs_execute_next_command(struct lbs_private *priv);
+-int lbs_process_event(struct lbs_private *priv);
+-void lbs_interrupt(struct lbs_private *priv);
++int lbs_process_event(struct lbs_private *priv, u32 event);
++void lbs_queue_event(struct lbs_private *priv, u32 event);
++void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
++
+ int lbs_set_radio_control(struct lbs_private *priv);
+ u32 lbs_fw_index_to_data_rate(u8 index);
+ u8 lbs_data_rate_to_fw_index(u32 rate);
+-void lbs_get_fwversion(struct lbs_private *priv,
+- char *fwversion,
+- int maxlen);
+
+ /** The proc fs interface */
+-int lbs_process_rx_command(struct lbs_private *priv);
++int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len);
+ void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
+ int result);
+ int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev);
+@@ -49,7 +48,7 @@ int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band);
+ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *);
+
+ void lbs_ps_sleep(struct lbs_private *priv, int wait_option);
+-void lbs_ps_confirm_sleep(struct lbs_private *priv, u16 psmode);
++void lbs_ps_confirm_sleep(struct lbs_private *priv);
+ void lbs_ps_wakeup(struct lbs_private *priv, int wait_option);
+
+ struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
+@@ -63,7 +62,6 @@ void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str);
+
+ /* main.c */
+ struct chan_freq_power *lbs_get_region_cfp_table(u8 region,
+- u8 band,
+ int *cfp_no);
+ struct lbs_private *lbs_add_card(void *card, struct device *dmdev);
+ int lbs_remove_card(struct lbs_private *priv);
+@@ -72,4 +70,9 @@ int lbs_stop_card(struct lbs_private *priv);
+ void lbs_host_to_card_done(struct lbs_private *priv);
+
+ int lbs_update_channel(struct lbs_private *priv);
++
++#ifndef CONFIG_IEEE80211
++const char *escape_essid(const char *essid, u8 essid_len);
++#endif
++
+ #endif
+diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
+index 3053cc2..d395201 100644
+--- a/drivers/net/wireless/libertas/defs.h
++++ b/drivers/net/wireless/libertas/defs.h
+@@ -53,14 +53,14 @@ do { if ((lbs_debug & (grp)) == (grp)) \
+ #endif
+
+ #define lbs_deb_enter(grp) \
+- LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s():%d\n", __FUNCTION__, __LINE__);
++ LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s()\n", __func__);
+ #define lbs_deb_enter_args(grp, fmt, args...) \
+- LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s(" fmt "):%d\n", __FUNCTION__, ## args, __LINE__);
++ LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s(" fmt ")\n", __func__, ## args);
+ #define lbs_deb_leave(grp) \
+- LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s():%d\n", __FUNCTION__, __LINE__);
++ LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s()\n", __func__);
+ #define lbs_deb_leave_args(grp, fmt, args...) \
+- LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s():%d, " fmt "\n", \
+- __FUNCTION__, __LINE__, ##args);
++ LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s(), " fmt "\n", \
++ __func__, ##args);
+ #define lbs_deb_main(fmt, args...) LBS_DEB_LL(LBS_DEB_MAIN, " main", fmt, ##args)
+ #define lbs_deb_net(fmt, args...) LBS_DEB_LL(LBS_DEB_NET, " net", fmt, ##args)
+ #define lbs_deb_mesh(fmt, args...) LBS_DEB_LL(LBS_DEB_MESH, " mesh", fmt, ##args)
+@@ -177,8 +177,6 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
+ #define MRVDRV_CMD_UPLD_RDY 0x0008
+ #define MRVDRV_CARDEVENT 0x0010
+
+-#define SBI_EVENT_CAUSE_SHIFT 3
+-
+ /** TxPD status */
+
+ /* Station firmware use TxPD status field to report final Tx transmit
+diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
+index 5a69f2b..0d9edb9 100644
+--- a/drivers/net/wireless/libertas/dev.h
++++ b/drivers/net/wireless/libertas/dev.h
+@@ -10,9 +10,10 @@
+ #include <linux/wireless.h>
+ #include <linux/ethtool.h>
+ #include <linux/debugfs.h>
++#include <net/ieee80211.h>
+
+ #include "defs.h"
+-#include "scan.h"
++#include "hostcmd.h"
+
+ extern struct ethtool_ops lbs_ethtool_ops;
+
+@@ -128,10 +129,6 @@ struct lbs_private {
+ u32 bbp_offset;
+ u32 rf_offset;
+
+- /** Upload length */
+- u32 upld_len;
+- /* Upload buffer */
+- u8 upld_buf[LBS_UPLD_SIZE];
+ /* Download sent:
+ bit0 1/0=data_sent/data_tx_done,
+ bit1 1/0=cmd_sent/cmd_tx_done,
+@@ -143,27 +140,27 @@ struct lbs_private {
+ wait_queue_head_t waitq;
+ struct workqueue_struct *work_thread;
+
++ /** Scanning */
+ struct delayed_work scan_work;
+ struct delayed_work assoc_work;
+ struct work_struct sync_channel;
++ /* remember which channel was scanned last, != 0 if currently scanning */
++ int scan_channel;
++ u8 scan_ssid[IW_ESSID_MAX_SIZE + 1];
++ u8 scan_ssid_len;
+
+ /** Hardware access */
+ int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
+- int (*hw_get_int_status) (struct lbs_private *priv, u8 *);
+- int (*hw_read_event_cause) (struct lbs_private *);
+
+ /* Wake On LAN */
+ uint32_t wol_criteria;
+ uint8_t wol_gpio;
+ uint8_t wol_gap;
+
+- /* was struct lbs_adapter from here... */
+-
+ /** Wlan adapter data structure*/
+ /** STATUS variables */
+ u32 fwrelease;
+ u32 fwcapinfo;
+- /* protected with big lock */
+
+ struct mutex lock;
+
+@@ -175,7 +172,6 @@ struct lbs_private {
+
+ /** command-related variables */
+ u16 seqnum;
+- /* protected by big lock */
+
+ struct cmd_ctrl_node *cmd_array;
+ /** Current command */
+@@ -188,12 +184,17 @@ struct lbs_private {
+ struct list_head cmdpendingq;
+
+ wait_queue_head_t cmd_pending;
+- /* command related variables protected by priv->driver_lock */
+
+- /** Async and Sync Event variables */
+- u32 intcounter;
+- u32 eventcause;
+- u8 nodename[16]; /* nickname */
++ /* Command responses sent from the hardware to the driver */
++ u8 resp_idx;
++ u8 resp_buf[2][LBS_UPLD_SIZE];
++ u32 resp_len[2];
++
++ /* Events sent from hardware to driver */
++ struct kfifo *event_fifo;
++
++ /* nickname */
++ u8 nodename[16];
+
+ /** spin locks */
+ spinlock_t driver_lock;
+@@ -203,8 +204,6 @@ struct lbs_private {
+ int nr_retries;
+ int cmd_timed_out;
+
+- u8 hisregcpy;
+-
+ /** current ssid/bssid related parameters*/
+ struct current_bss_params curbssparams;
+
+@@ -247,7 +246,7 @@ struct lbs_private {
+ struct sk_buff *currenttxskb;
+
+ /** NIC Operation characteristics */
+- u16 currentpacketfilter;
++ u16 mac_control;
+ u32 connect_status;
+ u32 mesh_connect_status;
+ u16 regioncode;
+@@ -262,9 +261,6 @@ struct lbs_private {
+ char ps_supported;
+ u8 needtowakeup;
+
+- struct PS_CMD_ConfirmSleep lbs_ps_confirm_sleep;
+- struct cmd_header lbs_ps_confirm_wake;
+-
+ struct assoc_request * pending_assoc_req;
+ struct assoc_request * in_progress_assoc_req;
+
+@@ -315,16 +311,52 @@ struct lbs_private {
+ u32 enable11d;
+
+ /** MISCELLANEOUS */
+- u8 *prdeeprom;
+ struct lbs_offset_value offsetvalue;
+
+- struct cmd_ds_802_11_get_log logmsg;
+-
+ u32 monitormode;
+- int last_scanned_channel;
+ u8 fw_ready;
+ };
+
++extern struct cmd_confirm_sleep confirm_sleep;
++
++/**
++ * @brief Structure used to store information for each beacon/probe response
++ */
++struct bss_descriptor {
++ u8 bssid[ETH_ALEN];
++
++ u8 ssid[IW_ESSID_MAX_SIZE + 1];
++ u8 ssid_len;
++
++ u16 capability;
++ u32 rssi;
++ u32 channel;
++ u16 beaconperiod;
++ u32 atimwindow;
++
++ /* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */
++ u8 mode;
++
++ /* zero-terminated array of supported data rates */
++ u8 rates[MAX_RATES + 1];
++
++ unsigned long last_scanned;
++
++ union ieeetypes_phyparamset phyparamset;
++ union IEEEtypes_ssparamset ssparamset;
++
++ struct ieeetypes_countryinfofullset countryinfo;
++
++ u8 wpa_ie[MAX_WPA_IE_LEN];
++ size_t wpa_ie_len;
++ u8 rsn_ie[MAX_WPA_IE_LEN];
++ size_t rsn_ie_len;
++
++ u8 mesh;
++
++ struct list_head list;
++};
++
+ /** Association request
+ *
+ * Encapsulates all the options that describe a specific assocation request
+diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c
+index 21e6f98..dcfdb40 100644
+--- a/drivers/net/wireless/libertas/ethtool.c
++++ b/drivers/net/wireless/libertas/ethtool.c
+@@ -6,7 +6,6 @@
+ #include "decl.h"
+ #include "defs.h"
+ #include "dev.h"
+-#include "join.h"
+ #include "wext.h"
+ #include "cmd.h"
+
+@@ -25,13 +24,14 @@ static void lbs_ethtool_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+ {
+ struct lbs_private *priv = (struct lbs_private *) dev->priv;
+- char fwver[32];
+-
+- lbs_get_fwversion(priv, fwver, sizeof(fwver) - 1);
+
++ snprintf(info->fw_version, 32, "%u.%u.%u.p%u",
++ priv->fwrelease >> 24 & 0xff,
++ priv->fwrelease >> 16 & 0xff,
++ priv->fwrelease >> 8 & 0xff,
++ priv->fwrelease & 0xff);
+ strcpy(info->driver, "libertas");
+ strcpy(info->version, lbs_driver_version);
+- strcpy(info->fw_version, fwver);
+ }
+
+ /* All 8388 parts have 16KiB EEPROM size at the time of writing.
+@@ -48,61 +48,28 @@ static int lbs_ethtool_get_eeprom(struct net_device *dev,
+ struct ethtool_eeprom *eeprom, u8 * bytes)
+ {
+ struct lbs_private *priv = (struct lbs_private *) dev->priv;
+- struct lbs_ioctl_regrdwr regctrl;
+- char *ptr;
++ struct cmd_ds_802_11_eeprom_access cmd;
+ int ret;
+
+- regctrl.action = 0;
+- regctrl.offset = eeprom->offset;
+- regctrl.NOB = eeprom->len;
+-
+- if (eeprom->offset + eeprom->len > LBS_EEPROM_LEN)
+- return -EINVAL;
+-
+-// mutex_lock(&priv->mutex);
+-
+- priv->prdeeprom = kmalloc(eeprom->len+sizeof(regctrl), GFP_KERNEL);
+- if (!priv->prdeeprom)
+- return -ENOMEM;
+- memcpy(priv->prdeeprom, ®ctrl, sizeof(regctrl));
+-
+- /* +14 is for action, offset, and NOB in
+- * response */
+- lbs_deb_ethtool("action:%d offset: %x NOB: %02x\n",
+- regctrl.action, regctrl.offset, regctrl.NOB);
++ lbs_deb_enter(LBS_DEB_ETHTOOL);
+
+- ret = lbs_prepare_and_send_command(priv,
+- CMD_802_11_EEPROM_ACCESS,
+- regctrl.action,
+- CMD_OPTION_WAITFORRSP, 0,
+- ®ctrl);
+-
+- if (ret) {
+- if (priv->prdeeprom)
+- kfree(priv->prdeeprom);
+- goto done;
++ if (eeprom->offset + eeprom->len > LBS_EEPROM_LEN ||
++ eeprom->len > LBS_EEPROM_READ_LEN) {
++ ret = -EINVAL;
++ goto out;
+ }
+
+- mdelay(10);
+-
+- ptr = (char *)priv->prdeeprom;
+-
+- /* skip the command header, but include the "value" u32 variable */
+- ptr = ptr + sizeof(struct lbs_ioctl_regrdwr) - 4;
+-
+- /*
+- * Return the result back to the user
+- */
+- memcpy(bytes, ptr, eeprom->len);
+-
+- if (priv->prdeeprom)
+- kfree(priv->prdeeprom);
+-// mutex_unlock(&priv->mutex);
+-
+- ret = 0;
+-
+-done:
+- lbs_deb_enter_args(LBS_DEB_ETHTOOL, "ret %d", ret);
++ cmd.hdr.size = cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) -
++ LBS_EEPROM_READ_LEN + eeprom->len);
++ cmd.action = cpu_to_le16(CMD_ACT_GET);
++ cmd.offset = cpu_to_le16(eeprom->offset);
++ cmd.len = cpu_to_le16(eeprom->len);
++ ret = lbs_cmd_with_response(priv, CMD_802_11_EEPROM_ACCESS, &cmd);
++ if (!ret)
++ memcpy(bytes, cmd.value, eeprom->len);
++
++out:
++ lbs_deb_leave_args(LBS_DEB_ETHTOOL, "ret %d", ret);
+ return ret;
+ }
+
+diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
+index 1aa0407..3915c31 100644
+--- a/drivers/net/wireless/libertas/host.h
++++ b/drivers/net/wireless/libertas/host.h
+@@ -33,7 +33,6 @@
+ #define CMD_RET_802_11_ASSOCIATE 0x8012
+
+ /* Command codes */
+-#define CMD_CODE_DNLD 0x0002
+ #define CMD_GET_HW_SPEC 0x0003
+ #define CMD_EEPROM_UPDATE 0x0004
+ #define CMD_802_11_RESET 0x0005
+@@ -68,8 +67,6 @@
+ #define CMD_802_11_AD_HOC_JOIN 0x002c
+ #define CMD_802_11_QUERY_TKIP_REPLY_CNTRS 0x002e
+ #define CMD_802_11_ENABLE_RSN 0x002f
+-#define CMD_802_11_PAIRWISE_TSC 0x0036
+-#define CMD_802_11_GROUP_TSC 0x0037
+ #define CMD_802_11_SET_AFC 0x003c
+ #define CMD_802_11_GET_AFC 0x003d
+ #define CMD_802_11_AD_HOC_STOP 0x0040
+@@ -87,7 +84,6 @@
+ #define CMD_802_11_INACTIVITY_TIMEOUT 0x0067
+ #define CMD_802_11_SLEEP_PERIOD 0x0068
+ #define CMD_802_11_TPC_CFG 0x0072
+-#define CMD_802_11_PWR_CFG 0x0073
+ #define CMD_802_11_FW_WAKE_METHOD 0x0074
+ #define CMD_802_11_SUBSCRIBE_EVENT 0x0075
+ #define CMD_802_11_RATE_ADAPT_RATESET 0x0076
+diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
+index d35b015..f29bc5b 100644
+--- a/drivers/net/wireless/libertas/hostcmd.h
++++ b/drivers/net/wireless/libertas/hostcmd.h
+@@ -174,9 +174,11 @@ struct cmd_ds_802_11_subscribe_event {
+ * Define data structure for CMD_802_11_SCAN
+ */
+ struct cmd_ds_802_11_scan {
+- u8 bsstype;
+- u8 bssid[ETH_ALEN];
+- u8 tlvbuffer[1];
++ struct cmd_header hdr;
++
++ uint8_t bsstype;
++ uint8_t bssid[ETH_ALEN];
++ uint8_t tlvbuffer[0];
+ #if 0
+ mrvlietypes_ssidparamset_t ssidParamSet;
+ mrvlietypes_chanlistparamset_t ChanListParamSet;
+@@ -185,12 +187,16 @@ struct cmd_ds_802_11_scan {
+ };
+
+ struct cmd_ds_802_11_scan_rsp {
++ struct cmd_header hdr;
++
+ __le16 bssdescriptsize;
+- u8 nr_sets;
+- u8 bssdesc_and_tlvbuffer[1];
++ uint8_t nr_sets;
++ uint8_t bssdesc_and_tlvbuffer[0];
+ };
+
+ struct cmd_ds_802_11_get_log {
++ struct cmd_header hdr;
++
+ __le32 mcasttxframe;
+ __le32 failed;
+ __le32 retry;
+@@ -207,8 +213,9 @@ struct cmd_ds_802_11_get_log {
+ };
+
+ struct cmd_ds_mac_control {
++ struct cmd_header hdr;
+ __le16 action;
+- __le16 reserved;
++ u16 reserved;
+ };
+
+ struct cmd_ds_mac_multicast_adr {
+@@ -420,6 +427,8 @@ struct cmd_ds_802_11_rssi_rsp {
+ };
+
+ struct cmd_ds_802_11_mac_address {
++ struct cmd_header hdr;
++
+ __le16 action;
+ u8 macadd[ETH_ALEN];
+ };
+@@ -471,14 +480,11 @@ struct cmd_ds_802_11_ps_mode {
+ __le16 locallisteninterval;
+ };
+
+-struct PS_CMD_ConfirmSleep {
+- __le16 command;
+- __le16 size;
+- __le16 seqnum;
+- __le16 result;
++struct cmd_confirm_sleep {
++ struct cmd_header hdr;
+
+ __le16 action;
+- __le16 reserved1;
++ __le16 nullpktinterval;
+ __le16 multipledtim;
+ __le16 reserved;
+ __le16 locallisteninterval;
+@@ -572,17 +578,20 @@ struct cmd_ds_host_sleep {
+ } __attribute__ ((packed));
+
+ struct cmd_ds_802_11_key_material {
++ struct cmd_header hdr;
++
+ __le16 action;
+ struct MrvlIEtype_keyParamSet keyParamSet[2];
+ } __attribute__ ((packed));
+
+ struct cmd_ds_802_11_eeprom_access {
++ struct cmd_header hdr;
+ __le16 action;
+-
+- /* multiple 4 */
+ __le16 offset;
+- __le16 bytecount;
+- u8 value;
++ __le16 len;
++ /* firmware says it returns a maximum of 20 bytes */
++#define LBS_EEPROM_READ_LEN 20
++ u8 value[LBS_EEPROM_READ_LEN];
+ } __attribute__ ((packed));
+
+ struct cmd_ds_802_11_tpc_cfg {
+@@ -600,14 +609,6 @@ struct cmd_ds_802_11_led_ctrl {
+ u8 data[256];
+ } __attribute__ ((packed));
+
+-struct cmd_ds_802_11_pwr_cfg {
+- __le16 action;
+- u8 enable;
+- s8 PA_P0;
+- s8 PA_P1;
+- s8 PA_P2;
+-} __attribute__ ((packed));
+-
+ struct cmd_ds_802_11_afc {
+ __le16 afc_auto;
+ union {
+@@ -689,15 +690,11 @@ struct cmd_ds_command {
+ /* command Body */
+ union {
+ struct cmd_ds_802_11_ps_mode psmode;
+- struct cmd_ds_802_11_scan scan;
+- struct cmd_ds_802_11_scan_rsp scanresp;
+- struct cmd_ds_mac_control macctrl;
+ struct cmd_ds_802_11_associate associate;
+ struct cmd_ds_802_11_deauthenticate deauth;
+ struct cmd_ds_802_11_ad_hoc_start ads;
+ struct cmd_ds_802_11_reset reset;
+ struct cmd_ds_802_11_ad_hoc_result result;
+- struct cmd_ds_802_11_get_log glog;
+ struct cmd_ds_802_11_authenticate auth;
+ struct cmd_ds_802_11_get_stat gstat;
+ struct cmd_ds_802_3_get_stat gstat_8023;
+@@ -711,18 +708,14 @@ struct cmd_ds_command {
+ struct cmd_ds_802_11_rssi rssi;
+ struct cmd_ds_802_11_rssi_rsp rssirsp;
+ struct cmd_ds_802_11_disassociate dassociate;
+- struct cmd_ds_802_11_mac_address macadd;
+- struct cmd_ds_802_11_key_material keymaterial;
+ struct cmd_ds_mac_reg_access macreg;
+ struct cmd_ds_bbp_reg_access bbpreg;
+ struct cmd_ds_rf_reg_access rfreg;
+- struct cmd_ds_802_11_eeprom_access rdeeprom;
+
+ struct cmd_ds_802_11d_domain_info domaininfo;
+ struct cmd_ds_802_11d_domain_info domaininforesp;
+
+ struct cmd_ds_802_11_tpc_cfg tpccfg;
+- struct cmd_ds_802_11_pwr_cfg pwrcfg;
+ struct cmd_ds_802_11_afc afc;
+ struct cmd_ds_802_11_led_ctrl ledgpio;
+
+diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
+index 038c66a..54280e2 100644
+--- a/drivers/net/wireless/libertas/if_cs.c
++++ b/drivers/net/wireless/libertas/if_cs.c
+@@ -83,14 +83,14 @@ static inline unsigned int if_cs_read8(struct if_cs_card *card, uint reg)
+ {
+ unsigned int val = ioread8(card->iobase + reg);
+ if (debug_output)
+- printk(KERN_INFO "##inb %08x<%02x\n", reg, val);
++ printk(KERN_INFO "inb %08x<%02x\n", reg, val);
+ return val;
+ }
+ static inline unsigned int if_cs_read16(struct if_cs_card *card, uint reg)
+ {
+ unsigned int val = ioread16(card->iobase + reg);
+ if (debug_output)
+- printk(KERN_INFO "##inw %08x<%04x\n", reg, val);
++ printk(KERN_INFO "inw %08x<%04x\n", reg, val);
+ return val;
+ }
+ static inline void if_cs_read16_rep(
+@@ -100,7 +100,7 @@ static inline void if_cs_read16_rep(
+ unsigned long count)
+ {
+ if (debug_output)
+- printk(KERN_INFO "##insw %08x<(0x%lx words)\n",
++ printk(KERN_INFO "insw %08x<(0x%lx words)\n",
+ reg, count);
+ ioread16_rep(card->iobase + reg, buf, count);
+ }
+@@ -108,14 +108,14 @@ static inline void if_cs_read16_rep(
+ static inline void if_cs_write8(struct if_cs_card *card, uint reg, u8 val)
+ {
+ if (debug_output)
+- printk(KERN_INFO "##outb %08x>%02x\n", reg, val);
++ printk(KERN_INFO "outb %08x>%02x\n", reg, val);
+ iowrite8(val, card->iobase + reg);
+ }
+
+ static inline void if_cs_write16(struct if_cs_card *card, uint reg, u16 val)
+ {
+ if (debug_output)
+- printk(KERN_INFO "##outw %08x>%04x\n", reg, val);
++ printk(KERN_INFO "outw %08x>%04x\n", reg, val);
+ iowrite16(val, card->iobase + reg);
+ }
+
+@@ -126,7 +126,7 @@ static inline void if_cs_write16_rep(
+ unsigned long count)
+ {
+ if (debug_output)
+- printk(KERN_INFO "##outsw %08x>(0x%lx words)\n",
++ printk(KERN_INFO "outsw %08x>(0x%lx words)\n",
+ reg, count);
+ iowrite16_rep(card->iobase + reg, buf, count);
+ }
+@@ -199,17 +199,6 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r
+ #define IF_CS_C_S_CARDEVENT 0x0010
+ #define IF_CS_C_S_MASK 0x001f
+ #define IF_CS_C_S_STATUS_MASK 0x7f00
+-/* The following definitions should be the same as the MRVDRV_ ones */
+-
+-#if MRVDRV_CMD_DNLD_RDY != IF_CS_C_S_CMD_DNLD_RDY
+-#error MRVDRV_CMD_DNLD_RDY and IF_CS_C_S_CMD_DNLD_RDY not in sync
+-#endif
+-#if MRVDRV_CMD_UPLD_RDY != IF_CS_C_S_CMD_UPLD_RDY
+-#error MRVDRV_CMD_UPLD_RDY and IF_CS_C_S_CMD_UPLD_RDY not in sync
+-#endif
+-#if MRVDRV_CARDEVENT != IF_CS_C_S_CARDEVENT
+-#error MRVDRV_CARDEVENT and IF_CS_C_S_CARDEVENT not in sync
+-#endif
+
+ #define IF_CS_C_INT_CAUSE 0x00000022
+ #define IF_CS_C_IC_MASK 0x001f
+@@ -226,55 +215,6 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r
+
+
+ /********************************************************************/
+-/* Interrupts */
+-/********************************************************************/
+-
+-static inline void if_cs_enable_ints(struct if_cs_card *card)
+-{
+- lbs_deb_enter(LBS_DEB_CS);
+- if_cs_write16(card, IF_CS_H_INT_MASK, 0);
+-}
+-
+-static inline void if_cs_disable_ints(struct if_cs_card *card)
+-{
+- lbs_deb_enter(LBS_DEB_CS);
+- if_cs_write16(card, IF_CS_H_INT_MASK, IF_CS_H_IM_MASK);
+-}
+-
+-static irqreturn_t if_cs_interrupt(int irq, void *data)
+-{
+- struct if_cs_card *card = data;
+- u16 int_cause;
+-
+- lbs_deb_enter(LBS_DEB_CS);
+-
+- int_cause = if_cs_read16(card, IF_CS_C_INT_CAUSE);
+- if (int_cause == 0x0) {
+- /* Not for us */
+- return IRQ_NONE;
+-
+- } else if (int_cause == 0xffff) {
+- /* Read in junk, the card has probably been removed */
+- card->priv->surpriseremoved = 1;
+- return IRQ_HANDLED;
+- } else {
+- if (int_cause & IF_CS_H_IC_TX_OVER)
+- lbs_host_to_card_done(card->priv);
+-
+- /* clear interrupt */
+- if_cs_write16(card, IF_CS_C_INT_CAUSE, int_cause & IF_CS_C_IC_MASK);
+- }
+- spin_lock(&card->priv->driver_lock);
+- lbs_interrupt(card->priv);
+- spin_unlock(&card->priv->driver_lock);
+-
+- return IRQ_HANDLED;
+-}
+-
+-
+-
+-
+-/********************************************************************/
+ /* I/O */
+ /********************************************************************/
+
+@@ -351,6 +291,7 @@ static void if_cs_send_data(struct lbs_private *priv, u8 *buf, u16 nb)
+ */
+ static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len)
+ {
++ unsigned long flags;
+ int ret = -1;
+ u16 val;
+
+@@ -378,6 +319,12 @@ static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len)
+ * bytes */
+ *len -= 8;
+ ret = 0;
++
++ /* Clear this flag again */
++ spin_lock_irqsave(&priv->driver_lock, flags);
++ priv->dnld_sent = DNLD_RES_RECEIVED;
++ spin_unlock_irqrestore(&priv->driver_lock, flags);
++
+ out:
+ lbs_deb_leave_args(LBS_DEB_CS, "ret %d, len %d", ret, *len);
+ return ret;
+@@ -396,11 +343,9 @@ static struct sk_buff *if_cs_receive_data(struct lbs_private *priv)
+ if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) {
+ lbs_pr_err("card data buffer has invalid # of bytes (%d)\n", len);
+ priv->stats.rx_dropped++;
+- printk(KERN_INFO "##HS %s:%d TODO\n", __FUNCTION__, __LINE__);
+ goto dat_err;
+ }
+
+- //TODO: skb = dev_alloc_skb(len+ETH_FRAME_LEN+MRVDRV_SNAP_HEADER_LEN+EXTRA_LEN);
+ skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + 2);
+ if (!skb)
+ goto out;
+@@ -425,6 +370,96 @@ out:
+
+
+ /********************************************************************/
++/* Interrupts */
++/********************************************************************/
++
++static inline void if_cs_enable_ints(struct if_cs_card *card)
++{
++ lbs_deb_enter(LBS_DEB_CS);
++ if_cs_write16(card, IF_CS_H_INT_MASK, 0);
++}
++
++static inline void if_cs_disable_ints(struct if_cs_card *card)
++{
++ lbs_deb_enter(LBS_DEB_CS);
++ if_cs_write16(card, IF_CS_H_INT_MASK, IF_CS_H_IM_MASK);
++}
++
++
++static irqreturn_t if_cs_interrupt(int irq, void *data)
++{
++ struct if_cs_card *card = data;
++ struct lbs_private *priv = card->priv;
++ u16 cause;
++
++ lbs_deb_enter(LBS_DEB_CS);
++
++ cause = if_cs_read16(card, IF_CS_C_INT_CAUSE);
++ if_cs_write16(card, IF_CS_C_INT_CAUSE, cause & IF_CS_C_IC_MASK);
++
++ lbs_deb_cs("cause 0x%04x\n", cause);
++ if (cause == 0) {
++ /* Not for us */
++ return IRQ_NONE;
++ }
++
++ if (cause == 0xffff) {
++ /* Read in junk, the card has probably been removed */
++ card->priv->surpriseremoved = 1;
++ return IRQ_HANDLED;
++ }
++
++ /* TODO: I'm not sure what the best ordering is */
++
++ cause = if_cs_read16(card, IF_CS_C_STATUS) & IF_CS_C_S_MASK;
++
++ if (cause & IF_CS_C_S_RX_UPLD_RDY) {
++ struct sk_buff *skb;
++ lbs_deb_cs("rx packet\n");
++ skb = if_cs_receive_data(priv);
++ if (skb)
++ lbs_process_rxed_packet(priv, skb);
++ }
++
++ if (cause & IF_CS_H_IC_TX_OVER) {
++ lbs_deb_cs("tx over\n");
++ lbs_host_to_card_done(priv);
++ }
++
++ if (cause & IF_CS_C_S_CMD_UPLD_RDY) {
++ unsigned long flags;
++ u8 i;
++
++ lbs_deb_cs("cmd upload ready\n");
++ spin_lock_irqsave(&priv->driver_lock, flags);
++ i = (priv->resp_idx == 0) ? 1 : 0;
++ spin_unlock_irqrestore(&priv->driver_lock, flags);
++
++ BUG_ON(priv->resp_len[i]);
++ if_cs_receive_cmdres(priv, priv->resp_buf[i],
++ &priv->resp_len[i]);
++
++ spin_lock_irqsave(&priv->driver_lock, flags);
++ lbs_notify_command_response(priv, i);
++ spin_unlock_irqrestore(&priv->driver_lock, flags);
++ }
++
++ if (cause & IF_CS_H_IC_HOST_EVENT) {
++ u16 event = if_cs_read16(priv->card, IF_CS_C_STATUS)
++ & IF_CS_C_S_STATUS_MASK;
++ if_cs_write16(priv->card, IF_CS_H_INT_CAUSE,
++ IF_CS_H_IC_HOST_EVENT);
++ lbs_deb_cs("eventcause 0x%04x\n", event);
++ lbs_queue_event(priv, event >> 8 & 0xff);
++ }
++
++ return IRQ_HANDLED;
++}
++
++
++
++
++/********************************************************************/
+ /* Firmware */
+ /********************************************************************/
+
+@@ -476,8 +511,6 @@ static int if_cs_prog_helper(struct if_cs_card *card)
+
+ if (remain < count)
+ count = remain;
+- /* printk(KERN_INFO "//HS %d loading %d of %d bytes\n",
+- __LINE__, sent, fw->size); */
+
+ /* "write the number of bytes to be sent to the I/O Command
+ * write length register" */
+@@ -544,18 +577,12 @@ static int if_cs_prog_real(struct if_cs_card *card)
+
+ ret = if_cs_poll_while_fw_download(card, IF_CS_C_SQ_READ_LOW, IF_CS_C_SQ_HELPER_OK);
+ if (ret < 0) {
+- int i;
+ lbs_pr_err("helper firmware doesn't answer\n");
+- for (i = 0; i < 0x50; i += 2)
+- printk(KERN_INFO "## HS %02x: %04x\n",
+- i, if_cs_read16(card, i));
+ goto err_release;
+ }
+
+ for (sent = 0; sent < fw->size; sent += len) {
+ len = if_cs_read16(card, IF_CS_C_SQ_READ_LOW);
+- /* printk(KERN_INFO "//HS %d loading %d of %d bytes\n",
+- __LINE__, sent, fw->size); */
+ if (len & 1) {
+ retry++;
+ lbs_pr_info("odd, need to retry this firmware block\n");
+@@ -642,64 +669,6 @@ static int if_cs_host_to_card(struct lbs_private *priv,
+ }
+
+
+-static int if_cs_get_int_status(struct lbs_private *priv, u8 *ireg)
+-{
+- struct if_cs_card *card = (struct if_cs_card *)priv->card;
+- int ret = 0;
+- u16 int_cause;
+- *ireg = 0;
+-
+- lbs_deb_enter(LBS_DEB_CS);
+-
+- if (priv->surpriseremoved)
+- goto out;
+-
+- int_cause = if_cs_read16(card, IF_CS_C_INT_CAUSE) & IF_CS_C_IC_MASK;
+- if_cs_write16(card, IF_CS_C_INT_CAUSE, int_cause);
+-
+- *ireg = if_cs_read16(card, IF_CS_C_STATUS) & IF_CS_C_S_MASK;
+-
+- if (!*ireg)
+- goto sbi_get_int_status_exit;
+-
+-sbi_get_int_status_exit:
+-
+- /* is there a data packet for us? */
+- if (*ireg & IF_CS_C_S_RX_UPLD_RDY) {
+- struct sk_buff *skb = if_cs_receive_data(priv);
+- lbs_process_rxed_packet(priv, skb);
+- *ireg &= ~IF_CS_C_S_RX_UPLD_RDY;
+- }
+-
+- if (*ireg & IF_CS_C_S_TX_DNLD_RDY) {
+- priv->dnld_sent = DNLD_RES_RECEIVED;
+- }
+-
+- /* Card has a command result for us */
+- if (*ireg & IF_CS_C_S_CMD_UPLD_RDY) {
+- ret = if_cs_receive_cmdres(priv, priv->upld_buf, &priv->upld_len);
+- if (ret < 0)
+- lbs_pr_err("could not receive cmd from card\n");
+- }
+-
+-out:
+- lbs_deb_leave_args(LBS_DEB_CS, "ret %d, ireg 0x%x, hisregcpy 0x%x", ret, *ireg, priv->hisregcpy);
+- return ret;
+-}
+-
+-
+-static int if_cs_read_event_cause(struct lbs_private *priv)
+-{
+- lbs_deb_enter(LBS_DEB_CS);
+-
+- priv->eventcause = (if_cs_read16(priv->card, IF_CS_C_STATUS) & IF_CS_C_S_STATUS_MASK) >> 5;
+- if_cs_write16(priv->card, IF_CS_H_INT_CAUSE, IF_CS_H_IC_HOST_EVENT);
+-
+- return 0;
+-}
+-
+-
+-
+ /********************************************************************/
+ /* Card Services */
+ /********************************************************************/
+@@ -852,13 +821,10 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
+ goto out2;
+ }
+
+- /* Store pointers to our call-back functions */
++ /* Finish setting up fields in lbs_private */
+ card->priv = priv;
+ priv->card = card;
+- priv->hw_host_to_card = if_cs_host_to_card;
+- priv->hw_get_int_status = if_cs_get_int_status;
+- priv->hw_read_event_cause = if_cs_read_event_cause;
+-
++ priv->hw_host_to_card = if_cs_host_to_card;
+ priv->fw_ready = 1;
+
+ /* Now actually get the IRQ */
+@@ -880,6 +846,9 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
+ goto out3;
+ }
+
++ /* The firmware for the CF card supports powersave */
++ priv->ps_supported = 1;
++
+ ret = 0;
+ goto out;
+
+diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
+index eed7320..51f664b 100644
+--- a/drivers/net/wireless/libertas/if_sdio.c
++++ b/drivers/net/wireless/libertas/if_sdio.c
+@@ -91,8 +91,6 @@ struct if_sdio_card {
+ const char *firmware;
+
+ u8 buffer[65536];
+- u8 int_cause;
+- u32 event;
+
+ spinlock_t lock;
+ struct if_sdio_packet *packets;
+@@ -129,13 +127,13 @@ static u16 if_sdio_read_scratch(struct if_sdio_card *card, int *err)
+ static int if_sdio_handle_cmd(struct if_sdio_card *card,
+ u8 *buffer, unsigned size)
+ {
++ struct lbs_private *priv = card->priv;
+ int ret;
+ unsigned long flags;
++ u8 i;
+
+ lbs_deb_enter(LBS_DEB_SDIO);
+
+- spin_lock_irqsave(&card->priv->driver_lock, flags);
+-
+ if (size > LBS_CMD_BUFFER_SIZE) {
+ lbs_deb_sdio("response packet too large (%d bytes)\n",
+ (int)size);
+@@ -143,20 +141,20 @@ static int if_sdio_handle_cmd(struct if_sdio_card *card,
+ goto out;
+ }
+
+- memcpy(card->priv->upld_buf, buffer, size);
+- card->priv->upld_len = size;
++ spin_lock_irqsave(&priv->driver_lock, flags);
+
+- card->int_cause |= MRVDRV_CMD_UPLD_RDY;
++ i = (priv->resp_idx == 0) ? 1 : 0;
++ BUG_ON(priv->resp_len[i]);
++ priv->resp_len[i] = size;
++ memcpy(priv->resp_buf[i], buffer, size);
++ lbs_notify_command_response(priv, i);
+
+- lbs_interrupt(card->priv);
++ spin_unlock_irqrestore(&card->priv->driver_lock, flags);
+
+ ret = 0;
+
+ out:
+- spin_unlock_irqrestore(&card->priv->driver_lock, flags);
+-
+ lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
+-
+ return ret;
+ }
+
+@@ -202,7 +200,6 @@ static int if_sdio_handle_event(struct if_sdio_card *card,
+ u8 *buffer, unsigned size)
+ {
+ int ret;
+- unsigned long flags;
+ u32 event;
+
+ lbs_deb_enter(LBS_DEB_SDIO);
+@@ -222,18 +219,9 @@ static int if_sdio_handle_event(struct if_sdio_card *card,
+ event |= buffer[2] << 16;
+ event |= buffer[1] << 8;
+ event |= buffer[0] << 0;
+- event <<= SBI_EVENT_CAUSE_SHIFT;
+ }
+
+- spin_lock_irqsave(&card->priv->driver_lock, flags);
+-
+- card->event = event;
+- card->int_cause |= MRVDRV_CARDEVENT;
+-
+- lbs_interrupt(card->priv);
+-
+- spin_unlock_irqrestore(&card->priv->driver_lock, flags);
+-
++ lbs_queue_event(card->priv, event & 0xFF);
+ ret = 0;
+
+ out:
+@@ -770,37 +758,6 @@ out:
+ return ret;
+ }
+
+-static int if_sdio_get_int_status(struct lbs_private *priv, u8 *ireg)
+-{
+- struct if_sdio_card *card;
+-
+- lbs_deb_enter(LBS_DEB_SDIO);
+-
+- card = priv->card;
+-
+- *ireg = card->int_cause;
+- card->int_cause = 0;
+-
+- lbs_deb_leave(LBS_DEB_SDIO);
+-
+- return 0;
+-}
+-
+-static int if_sdio_read_event_cause(struct lbs_private *priv)
+-{
+- struct if_sdio_card *card;
+-
+- lbs_deb_enter(LBS_DEB_SDIO);
+-
+- card = priv->card;
+-
+- priv->eventcause = card->event;
+-
+- lbs_deb_leave(LBS_DEB_SDIO);
+-
+- return 0;
+-}
+-
+ /*******************************************************************/
+ /* SDIO callbacks */
+ /*******************************************************************/
+@@ -953,8 +910,6 @@ static int if_sdio_probe(struct sdio_func *func,
+
+ priv->card = card;
+ priv->hw_host_to_card = if_sdio_host_to_card;
+- priv->hw_get_int_status = if_sdio_get_int_status;
+- priv->hw_read_event_cause = if_sdio_read_event_cause;
+
+ priv->fw_ready = 1;
+
+diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
+index 75aed9d..8032df7 100644
+--- a/drivers/net/wireless/libertas/if_usb.c
++++ b/drivers/net/wireless/libertas/if_usb.c
+@@ -38,8 +38,6 @@ static void if_usb_receive_fwload(struct urb *urb);
+ static int if_usb_prog_firmware(struct if_usb_card *cardp);
+ static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type,
+ uint8_t *payload, uint16_t nb);
+-static int if_usb_get_int_status(struct lbs_private *priv, uint8_t *);
+-static int if_usb_read_event_cause(struct lbs_private *);
+ static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
+ uint16_t nb);
+ static void if_usb_free(struct if_usb_card *cardp);
+@@ -233,8 +231,6 @@ static int if_usb_probe(struct usb_interface *intf,
+ cardp->priv->fw_ready = 1;
+
+ priv->hw_host_to_card = if_usb_host_to_card;
+- priv->hw_get_int_status = if_usb_get_int_status;
+- priv->hw_read_event_cause = if_usb_read_event_cause;
+ cardp->boot2_version = udev->descriptor.bcdDevice;
+
+ if_usb_submit_rx_urb(cardp);
+@@ -582,7 +578,6 @@ static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb,
+ skb_pull(skb, MESSAGE_HEADER_LEN);
+
+ lbs_process_rxed_packet(priv, skb);
+- priv->upld_len = (recvlength - MESSAGE_HEADER_LEN);
+ }
+
+ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
+@@ -590,6 +585,8 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
+ struct if_usb_card *cardp,
+ struct lbs_private *priv)
+ {
++ u8 i;
++
+ if (recvlength > LBS_CMD_BUFFER_SIZE) {
+ lbs_deb_usbd(&cardp->udev->dev,
+ "The receive buffer is too large\n");
+@@ -601,12 +598,15 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
+ BUG();
+
+ spin_lock(&priv->driver_lock);
+- cardp->usb_int_cause |= MRVDRV_CMD_UPLD_RDY;
+- priv->upld_len = (recvlength - MESSAGE_HEADER_LEN);
+- memcpy(priv->upld_buf, recvbuff + MESSAGE_HEADER_LEN, priv->upld_len);
+
++ i = (priv->resp_idx == 0) ? 1 : 0;
++ BUG_ON(priv->resp_len[i]);
++ priv->resp_len[i] = (recvlength - MESSAGE_HEADER_LEN);
++ memcpy(priv->resp_buf[i], recvbuff + MESSAGE_HEADER_LEN,
++ priv->resp_len[i]);
+ kfree_skb(skb);
+- lbs_interrupt(priv);
++ lbs_notify_command_response(priv, i);
++
+ spin_unlock(&priv->driver_lock);
+
+ lbs_deb_usbd(&cardp->udev->dev,
+@@ -629,6 +629,7 @@ static void if_usb_receive(struct urb *urb)
+ uint8_t *recvbuff = NULL;
+ uint32_t recvtype = 0;
+ __le32 *pkt = (__le32 *)(skb->data + IPFIELD_ALIGN_OFFSET);
++ uint32_t event;
+
+ lbs_deb_enter(LBS_DEB_USB);
+
+@@ -660,26 +661,20 @@ static void if_usb_receive(struct urb *urb)
+ break;
+
+ case CMD_TYPE_INDICATION:
+- /* Event cause handling */
+- spin_lock(&priv->driver_lock);
++ /* Event handling */
++ event = le32_to_cpu(pkt[1]);
++ lbs_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", event);
++ kfree_skb(skb);
+
+- cardp->usb_event_cause = le32_to_cpu(pkt[1]);
++ /* Icky undocumented magic special case */
++ if (event & 0xffff0000) {
++ u32 trycount = (event & 0xffff0000) >> 16;
+
+- lbs_deb_usbd(&cardp->udev->dev,"**EVENT** 0x%X\n",
+- cardp->usb_event_cause);
++ lbs_send_tx_feedback(priv, trycount);
++ } else
++ lbs_queue_event(priv, event & 0xFF);
++ break;
+
+- /* Icky undocumented magic special case */
+- if (cardp->usb_event_cause & 0xffff0000) {
+- lbs_send_tx_feedback(priv);
+- spin_unlock(&priv->driver_lock);
+- break;
+- }
+- cardp->usb_event_cause <<= 3;
+- cardp->usb_int_cause |= MRVDRV_CARDEVENT;
+- kfree_skb(skb);
+- lbs_interrupt(priv);
+- spin_unlock(&priv->driver_lock);
+- goto rx_exit;
+ default:
+ lbs_deb_usbd(&cardp->udev->dev, "Unknown command type 0x%X\n",
+ recvtype);
+@@ -722,30 +717,6 @@ static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type,
+ return usb_tx_block(cardp, cardp->ep_out_buf, nb + MESSAGE_HEADER_LEN);
+ }
+
+-/* called with priv->driver_lock held */
+-static int if_usb_get_int_status(struct lbs_private *priv, uint8_t *ireg)
+-{
+- struct if_usb_card *cardp = priv->card;
+-
+- *ireg = cardp->usb_int_cause;
+- cardp->usb_int_cause = 0;
+-
+- lbs_deb_usbd(&cardp->udev->dev, "Int cause is 0x%X\n", *ireg);
+-
+- return 0;
+-}
+-
+-static int if_usb_read_event_cause(struct lbs_private *priv)
+-{
+- struct if_usb_card *cardp = priv->card;
+-
+- priv->eventcause = cardp->usb_event_cause;
+- /* Re-submit rx urb here to avoid event lost issue */
+- if_usb_submit_rx_urb(cardp);
+-
+- return 0;
+-}
+-
+ /**
+ * @brief This function issues Boot command to the Boot2 code
+ * @param ivalue 1:Boot from FW by USB-Download
+diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h
+index e4829a3..5771a83 100644
+--- a/drivers/net/wireless/libertas/if_usb.h
++++ b/drivers/net/wireless/libertas/if_usb.h
+@@ -46,8 +46,6 @@ struct if_usb_card {
+ struct lbs_private *priv;
+
+ struct sk_buff *rx_skb;
+- uint32_t usb_event_cause;
+- uint8_t usb_int_cause;
+
+ uint8_t ep_in;
+ uint8_t ep_out;
+diff --git a/drivers/net/wireless/libertas/join.c b/drivers/net/wireless/libertas/join.c
+deleted file mode 100644
+index 2d45080..0000000
+--- a/drivers/net/wireless/libertas/join.c
++++ /dev/null
+@@ -1,895 +0,0 @@
+-/**
+- * Functions implementing wlan infrastructure and adhoc join routines,
+- * IOCTL handlers as well as command preperation and response routines
+- * for sending adhoc start, adhoc join, and association commands
+- * to the firmware.
+- */
+-#include <linux/netdevice.h>
+-#include <linux/if_arp.h>
+-#include <linux/wireless.h>
+-#include <linux/etherdevice.h>
+-
+-#include <net/iw_handler.h>
+-
+-#include "host.h"
+-#include "decl.h"
+-#include "join.h"
+-#include "dev.h"
+-#include "assoc.h"
+-
+-/* The firmware needs certain bits masked out of the beacon-derviced capability
+- * field when associating/joining to BSSs.
+- */
+-#define CAPINFO_MASK (~(0xda00))
+-
+-/**
+- * @brief This function finds common rates between rate1 and card rates.
+- *
+- * It will fill common rates in rate1 as output if found.
+- *
+- * NOTE: Setting the MSB of the basic rates need to be taken
+- * care, either before or after calling this function
+- *
+- * @param priv A pointer to struct lbs_private structure
+- * @param rate1 the buffer which keeps input and output
+- * @param rate1_size the size of rate1 buffer; new size of buffer on return
+- *
+- * @return 0 or -1
+- */
+-static int get_common_rates(struct lbs_private *priv,
+- u8 *rates,
+- u16 *rates_size)
+-{
+- u8 *card_rates = lbs_bg_rates;
+- size_t num_card_rates = sizeof(lbs_bg_rates);
+- int ret = 0, i, j;
+- u8 tmp[30];
+- size_t tmp_size = 0;
+-
+- /* For each rate in card_rates that exists in rate1, copy to tmp */
+- for (i = 0; card_rates[i] && (i < num_card_rates); i++) {
+- for (j = 0; rates[j] && (j < *rates_size); j++) {
+- if (rates[j] == card_rates[i])
+- tmp[tmp_size++] = card_rates[i];
+- }
+- }
+-
+- lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size);
+- lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, num_card_rates);
+- lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size);
+- lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
+-
+- if (!priv->auto_rate) {
+- for (i = 0; i < tmp_size; i++) {
+- if (tmp[i] == priv->cur_rate)
+- goto done;
+- }
+- lbs_pr_alert("Previously set fixed data rate %#x isn't "
+- "compatible with the network.\n", priv->cur_rate);
+- ret = -1;
+- goto done;
+- }
+- ret = 0;
+-
+-done:
+- memset(rates, 0, *rates_size);
+- *rates_size = min_t(int, tmp_size, *rates_size);
+- memcpy(rates, tmp, *rates_size);
+- return ret;
+-}
+-
+-
+-/**
+- * @brief Sets the MSB on basic rates as the firmware requires
+- *
+- * Scan through an array and set the MSB for basic data rates.
+- *
+- * @param rates buffer of data rates
+- * @param len size of buffer
+- */
+-static void lbs_set_basic_rate_flags(u8 *rates, size_t len)
+-{
+- int i;
+-
+- for (i = 0; i < len; i++) {
+- if (rates[i] == 0x02 || rates[i] == 0x04 ||
+- rates[i] == 0x0b || rates[i] == 0x16)
+- rates[i] |= 0x80;
+- }
+-}
+-
+-/**
+- * @brief Unsets the MSB on basic rates
+- *
+- * Scan through an array and unset the MSB for basic data rates.
+- *
+- * @param rates buffer of data rates
+- * @param len size of buffer
+- */
+-void lbs_unset_basic_rate_flags(u8 *rates, size_t len)
+-{
+- int i;
+-
+- for (i = 0; i < len; i++)
+- rates[i] &= 0x7f;
+-}
+-
+-
+-/**
+- * @brief Associate to a specific BSS discovered in a scan
+- *
+- * @param priv A pointer to struct lbs_private structure
+- * @param pbssdesc Pointer to the BSS descriptor to associate with.
+- *
+- * @return 0-success, otherwise fail
+- */
+-int lbs_associate(struct lbs_private *priv, struct assoc_request *assoc_req)
+-{
+- int ret;
+-
+- lbs_deb_enter(LBS_DEB_ASSOC);
+-
+- ret = lbs_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE,
+- 0, CMD_OPTION_WAITFORRSP,
+- 0, assoc_req->bss.bssid);
+-
+- if (ret)
+- goto done;
+-
+- /* set preamble to firmware */
+- if ( (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
+- && (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE))
+- priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
+- else
+- priv->preamble = CMD_TYPE_LONG_PREAMBLE;
+-
+- lbs_set_radio_control(priv);
+-
+- ret = lbs_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE,
+- 0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
+-
+-done:
+- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
+- return ret;
+-}
+-
+-/**
+- * @brief Start an Adhoc Network
+- *
+- * @param priv A pointer to struct lbs_private structure
+- * @param adhocssid The ssid of the Adhoc Network
+- * @return 0--success, -1--fail
+- */
+-int lbs_start_adhoc_network(struct lbs_private *priv,
+- struct assoc_request *assoc_req)
+-{
+- int ret = 0;
+-
+- priv->adhoccreate = 1;
+-
+- if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
+- lbs_deb_join("AdhocStart: Short preamble\n");
+- priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
+- } else {
+- lbs_deb_join("AdhocStart: Long preamble\n");
+- priv->preamble = CMD_TYPE_LONG_PREAMBLE;
+- }
+-
+- lbs_set_radio_control(priv);
+-
+- lbs_deb_join("AdhocStart: channel = %d\n", assoc_req->channel);
+- lbs_deb_join("AdhocStart: band = %d\n", assoc_req->band);
+-
+- ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_START,
+- 0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
+-
+- return ret;
+-}
+-
+-/**
+- * @brief Join an adhoc network found in a previous scan
+- *
+- * @param priv A pointer to struct lbs_private structure
+- * @param pbssdesc Pointer to a BSS descriptor found in a previous scan
+- * to attempt to join
+- *
+- * @return 0--success, -1--fail
+- */
+-int lbs_join_adhoc_network(struct lbs_private *priv,
+- struct assoc_request *assoc_req)
+-{
+- struct bss_descriptor * bss = &assoc_req->bss;
+- int ret = 0;
+-
+- lbs_deb_join("%s: Current SSID '%s', ssid length %u\n",
+- __func__,
+- escape_essid(priv->curbssparams.ssid,
+- priv->curbssparams.ssid_len),
+- priv->curbssparams.ssid_len);
+- lbs_deb_join("%s: requested ssid '%s', ssid length %u\n",
+- __func__, escape_essid(bss->ssid, bss->ssid_len),
+- bss->ssid_len);
+-
+- /* check if the requested SSID is already joined */
+- if ( priv->curbssparams.ssid_len
+- && !lbs_ssid_cmp(priv->curbssparams.ssid,
+- priv->curbssparams.ssid_len,
+- bss->ssid, bss->ssid_len)
+- && (priv->mode == IW_MODE_ADHOC)
+- && (priv->connect_status == LBS_CONNECTED)) {
+- union iwreq_data wrqu;
+-
+- lbs_deb_join("ADHOC_J_CMD: New ad-hoc SSID is the same as "
+- "current, not attempting to re-join");
+-
+- /* Send the re-association event though, because the association
+- * request really was successful, even if just a null-op.
+- */
+- memset(&wrqu, 0, sizeof(wrqu));
+- memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid,
+- ETH_ALEN);
+- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+- wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
+- goto out;
+- }
+-
+- /* Use shortpreamble only when both creator and card supports
+- short preamble */
+- if ( !(bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
+- || !(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
+- lbs_deb_join("AdhocJoin: Long preamble\n");
+- priv->preamble = CMD_TYPE_LONG_PREAMBLE;
+- } else {
+- lbs_deb_join("AdhocJoin: Short preamble\n");
+- priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
+- }
+-
+- lbs_set_radio_control(priv);
+-
+- lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel);
+- lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);
+-
+- priv->adhoccreate = 0;
+-
+- ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_JOIN,
+- 0, CMD_OPTION_WAITFORRSP,
+- OID_802_11_SSID, assoc_req);
+-
+-out:
+- return ret;
+-}
+-
+-int lbs_stop_adhoc_network(struct lbs_private *priv)
+-{
+- return lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_STOP,
+- 0, CMD_OPTION_WAITFORRSP, 0, NULL);
+-}
+-
+-/**
+- * @brief Send Deauthentication Request
+- *
+- * @param priv A pointer to struct lbs_private structure
+- * @return 0--success, -1--fail
+- */
+-int lbs_send_deauthentication(struct lbs_private *priv)
+-{
+- return lbs_prepare_and_send_command(priv, CMD_802_11_DEAUTHENTICATE,
+- 0, CMD_OPTION_WAITFORRSP, 0, NULL);
+-}
+-
+-/**
+- * @brief This function prepares command of authenticate.
+- *
+- * @param priv A pointer to struct lbs_private structure
+- * @param cmd A pointer to cmd_ds_command structure
+- * @param pdata_buf Void cast of pointer to a BSSID to authenticate with
+- *
+- * @return 0 or -1
+- */
+-int lbs_cmd_80211_authenticate(struct lbs_private *priv,
+- struct cmd_ds_command *cmd,
+- void *pdata_buf)
+-{
+- struct cmd_ds_802_11_authenticate *pauthenticate = &cmd->params.auth;
+- int ret = -1;
+- u8 *bssid = pdata_buf;
+- DECLARE_MAC_BUF(mac);
+-
+- lbs_deb_enter(LBS_DEB_JOIN);
+-
+- cmd->command = cpu_to_le16(CMD_802_11_AUTHENTICATE);
+- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate)
+- + S_DS_GEN);
+-
+- /* translate auth mode to 802.11 defined wire value */
+- switch (priv->secinfo.auth_mode) {
+- case IW_AUTH_ALG_OPEN_SYSTEM:
+- pauthenticate->authtype = 0x00;
+- break;
+- case IW_AUTH_ALG_SHARED_KEY:
+- pauthenticate->authtype = 0x01;
+- break;
+- case IW_AUTH_ALG_LEAP:
+- pauthenticate->authtype = 0x80;
+- break;
+- default:
+- lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n",
+- priv->secinfo.auth_mode);
+- goto out;
+- }
+-
+- memcpy(pauthenticate->macaddr, bssid, ETH_ALEN);
+-
+- lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n",
+- print_mac(mac, bssid), pauthenticate->authtype);
+- ret = 0;
+-
+-out:
+- lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
+- return ret;
+-}
+-
+-int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
+- struct cmd_ds_command *cmd)
+-{
+- struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth;
+-
+- lbs_deb_enter(LBS_DEB_JOIN);
+-
+- cmd->command = cpu_to_le16(CMD_802_11_DEAUTHENTICATE);
+- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) +
+- S_DS_GEN);
+-
+- /* set AP MAC address */
+- memmove(dauth->macaddr, priv->curbssparams.bssid, ETH_ALEN);
+-
+- /* Reason code 3 = Station is leaving */
+-#define REASON_CODE_STA_LEAVING 3
+- dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING);
+-
+- lbs_deb_leave(LBS_DEB_JOIN);
+- return 0;
+-}
+-
+-int lbs_cmd_80211_associate(struct lbs_private *priv,
+- struct cmd_ds_command *cmd, void *pdata_buf)
+-{
+- struct cmd_ds_802_11_associate *passo = &cmd->params.associate;
+- int ret = 0;
+- struct assoc_request * assoc_req = pdata_buf;
+- struct bss_descriptor * bss = &assoc_req->bss;
+- u8 *pos;
+- u16 tmpcap, tmplen;
+- struct mrvlietypes_ssidparamset *ssid;
+- struct mrvlietypes_phyparamset *phy;
+- struct mrvlietypes_ssparamset *ss;
+- struct mrvlietypes_ratesparamset *rates;
+- struct mrvlietypes_rsnparamset *rsn;
+-
+- lbs_deb_enter(LBS_DEB_ASSOC);
+-
+- pos = (u8 *) passo;
+-
+- if (!priv) {
+- ret = -1;
+- goto done;
+- }
+-
+- cmd->command = cpu_to_le16(CMD_802_11_ASSOCIATE);
+-
+- memcpy(passo->peerstaaddr, bss->bssid, sizeof(passo->peerstaaddr));
+- pos += sizeof(passo->peerstaaddr);
+-
+- /* set the listen interval */
+- passo->listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL);
+-
+- pos += sizeof(passo->capability);
+- pos += sizeof(passo->listeninterval);
+- pos += sizeof(passo->bcnperiod);
+- pos += sizeof(passo->dtimperiod);
+-
+- ssid = (struct mrvlietypes_ssidparamset *) pos;
+- ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
+- tmplen = bss->ssid_len;
+- ssid->header.len = cpu_to_le16(tmplen);
+- memcpy(ssid->ssid, bss->ssid, tmplen);
+- pos += sizeof(ssid->header) + tmplen;
+-
+- phy = (struct mrvlietypes_phyparamset *) pos;
+- phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
+- tmplen = sizeof(phy->fh_ds.dsparamset);
+- phy->header.len = cpu_to_le16(tmplen);
+- memcpy(&phy->fh_ds.dsparamset,
+- &bss->phyparamset.dsparamset.currentchan,
+- tmplen);
+- pos += sizeof(phy->header) + tmplen;
+-
+- ss = (struct mrvlietypes_ssparamset *) pos;
+- ss->header.type = cpu_to_le16(TLV_TYPE_CF);
+- tmplen = sizeof(ss->cf_ibss.cfparamset);
+- ss->header.len = cpu_to_le16(tmplen);
+- pos += sizeof(ss->header) + tmplen;
+-
+- rates = (struct mrvlietypes_ratesparamset *) pos;
+- rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
+- memcpy(&rates->rates, &bss->rates, MAX_RATES);
+- tmplen = MAX_RATES;
+- if (get_common_rates(priv, rates->rates, &tmplen)) {
+- ret = -1;
+- goto done;
+- }
+- pos += sizeof(rates->header) + tmplen;
+- rates->header.len = cpu_to_le16(tmplen);
+- lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen);
+-
+- /* Copy the infra. association rates into Current BSS state structure */
+- memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
+- memcpy(&priv->curbssparams.rates, &rates->rates, tmplen);
+-
+- /* Set MSB on basic rates as the firmware requires, but _after_
+- * copying to current bss rates.
+- */
+- lbs_set_basic_rate_flags(rates->rates, tmplen);
+-
+- if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
+- rsn = (struct mrvlietypes_rsnparamset *) pos;
+- /* WPA_IE or WPA2_IE */
+- rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]);
+- tmplen = (u16) assoc_req->wpa_ie[1];
+- rsn->header.len = cpu_to_le16(tmplen);
+- memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen);
+- lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: RSN IE", (u8 *) rsn,
+- sizeof(rsn->header) + tmplen);
+- pos += sizeof(rsn->header) + tmplen;
+- }
+-
+- /* update curbssparams */
+- priv->curbssparams.channel = bss->phyparamset.dsparamset.currentchan;
+-
+- if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
+- ret = -1;
+- goto done;
+- }
+-
+- cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN);
+-
+- /* set the capability info */
+- tmpcap = (bss->capability & CAPINFO_MASK);
+- if (bss->mode == IW_MODE_INFRA)
+- tmpcap |= WLAN_CAPABILITY_ESS;
+- passo->capability = cpu_to_le16(tmpcap);
+- lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap);
+-
+-done:
+- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
+- return ret;
+-}
+-
+-int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
+- struct cmd_ds_command *cmd, void *pdata_buf)
+-{
+- struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads;
+- int ret = 0;
+- int cmdappendsize = 0;
+- struct assoc_request * assoc_req = pdata_buf;
+- u16 tmpcap = 0;
+- size_t ratesize = 0;
+-
+- lbs_deb_enter(LBS_DEB_JOIN);
+-
+- if (!priv) {
+- ret = -1;
+- goto done;
+- }
+-
+- cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_START);
+-
+- /*
+- * Fill in the parameters for 2 data structures:
+- * 1. cmd_ds_802_11_ad_hoc_start command
+- * 2. priv->scantable[i]
+- *
+- * Driver will fill up SSID, bsstype,IBSS param, Physical Param,
+- * probe delay, and cap info.
+- *
+- * Firmware will fill up beacon period, DTIM, Basic rates
+- * and operational rates.
+- */
+-
+- memset(adhs->ssid, 0, IW_ESSID_MAX_SIZE);
+- memcpy(adhs->ssid, assoc_req->ssid, assoc_req->ssid_len);
+-
+- lbs_deb_join("ADHOC_S_CMD: SSID '%s', ssid length %u\n",
+- escape_essid(assoc_req->ssid, assoc_req->ssid_len),
+- assoc_req->ssid_len);
+-
+- /* set the BSS type */
+- adhs->bsstype = CMD_BSS_TYPE_IBSS;
+- priv->mode = IW_MODE_ADHOC;
+- if (priv->beacon_period == 0)
+- priv->beacon_period = MRVDRV_BEACON_INTERVAL;
+- adhs->beaconperiod = cpu_to_le16(priv->beacon_period);
+-
+- /* set Physical param set */
+-#define DS_PARA_IE_ID 3
+-#define DS_PARA_IE_LEN 1
+-
+- adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID;
+- adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN;
+-
+- WARN_ON(!assoc_req->channel);
+-
+- lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
+- assoc_req->channel);
+-
+- adhs->phyparamset.dsparamset.currentchan = assoc_req->channel;
+-
+- /* set IBSS param set */
+-#define IBSS_PARA_IE_ID 6
+-#define IBSS_PARA_IE_LEN 2
+-
+- adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID;
+- adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN;
+- adhs->ssparamset.ibssparamset.atimwindow = 0;
+-
+- /* set capability info */
+- tmpcap = WLAN_CAPABILITY_IBSS;
+- if (assoc_req->secinfo.wep_enabled) {
+- lbs_deb_join("ADHOC_S_CMD: WEP enabled, setting privacy on\n");
+- tmpcap |= WLAN_CAPABILITY_PRIVACY;
+- } else {
+- lbs_deb_join("ADHOC_S_CMD: WEP disabled, setting privacy off\n");
+- }
+- adhs->capability = cpu_to_le16(tmpcap);
+-
+- /* probedelay */
+- adhs->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
+-
+- memset(adhs->rates, 0, sizeof(adhs->rates));
+- ratesize = min(sizeof(adhs->rates), sizeof(lbs_bg_rates));
+- memcpy(adhs->rates, lbs_bg_rates, ratesize);
+-
+- /* Copy the ad-hoc creating rates into Current BSS state structure */
+- memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
+- memcpy(&priv->curbssparams.rates, &adhs->rates, ratesize);
+-
+- /* Set MSB on basic rates as the firmware requires, but _after_
+- * copying to current bss rates.
+- */
+- lbs_set_basic_rate_flags(adhs->rates, ratesize);
+-
+- lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
+- adhs->rates[0], adhs->rates[1], adhs->rates[2], adhs->rates[3]);
+-
+- lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n");
+-
+- if (lbs_create_dnld_countryinfo_11d(priv)) {
+- lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
+- ret = -1;
+- goto done;
+- }
+-
+- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start) +
+- S_DS_GEN + cmdappendsize);
+-
+- ret = 0;
+-done:
+- lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
+- return ret;
+-}
+-
+-int lbs_cmd_80211_ad_hoc_stop(struct lbs_private *priv,
+- struct cmd_ds_command *cmd)
+-{
+- cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_STOP);
+- cmd->size = cpu_to_le16(S_DS_GEN);
+-
+- return 0;
+-}
+-
+-int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
+- struct cmd_ds_command *cmd, void *pdata_buf)
+-{
+- struct cmd_ds_802_11_ad_hoc_join *join_cmd = &cmd->params.adj;
+- struct assoc_request * assoc_req = pdata_buf;
+- struct bss_descriptor *bss = &assoc_req->bss;
+- int cmdappendsize = 0;
+- int ret = 0;
+- u16 ratesize = 0;
+- DECLARE_MAC_BUF(mac);
+-
+- lbs_deb_enter(LBS_DEB_JOIN);
+-
+- cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_JOIN);
+-
+- join_cmd->bss.type = CMD_BSS_TYPE_IBSS;
+- join_cmd->bss.beaconperiod = cpu_to_le16(bss->beaconperiod);
+-
+- memcpy(&join_cmd->bss.bssid, &bss->bssid, ETH_ALEN);
+- memcpy(&join_cmd->bss.ssid, &bss->ssid, bss->ssid_len);
+-
+- memcpy(&join_cmd->bss.phyparamset, &bss->phyparamset,
+- sizeof(union ieeetypes_phyparamset));
+-
+- memcpy(&join_cmd->bss.ssparamset, &bss->ssparamset,
+- sizeof(union IEEEtypes_ssparamset));
+-
+- join_cmd->bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK);
+- lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
+- bss->capability, CAPINFO_MASK);
+-
+- /* information on BSSID descriptor passed to FW */
+- lbs_deb_join(
+- "ADHOC_J_CMD: BSSID = %s, SSID = '%s'\n",
+- print_mac(mac, join_cmd->bss.bssid),
+- join_cmd->bss.ssid);
+-
+- /* failtimeout */
+- join_cmd->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
+-
+- /* probedelay */
+- join_cmd->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
+-
+- priv->curbssparams.channel = bss->channel;
+-
+- /* Copy Data rates from the rates recorded in scan response */
+- memset(join_cmd->bss.rates, 0, sizeof(join_cmd->bss.rates));
+- ratesize = min_t(u16, sizeof(join_cmd->bss.rates), MAX_RATES);
+- memcpy(join_cmd->bss.rates, bss->rates, ratesize);
+- if (get_common_rates(priv, join_cmd->bss.rates, &ratesize)) {
+- lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n");
+- ret = -1;
+- goto done;
+- }
+-
+- /* Copy the ad-hoc creating rates into Current BSS state structure */
+- memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
+- memcpy(&priv->curbssparams.rates, join_cmd->bss.rates, ratesize);
+-
+- /* Set MSB on basic rates as the firmware requires, but _after_
+- * copying to current bss rates.
+- */
+- lbs_set_basic_rate_flags(join_cmd->bss.rates, ratesize);
+-
+- join_cmd->bss.ssparamset.ibssparamset.atimwindow =
+- cpu_to_le16(bss->atimwindow);
+-
+- if (assoc_req->secinfo.wep_enabled) {
+- u16 tmp = le16_to_cpu(join_cmd->bss.capability);
+- tmp |= WLAN_CAPABILITY_PRIVACY;
+- join_cmd->bss.capability = cpu_to_le16(tmp);
+- }
+-
+- if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
+- /* wake up first */
+- __le32 Localpsmode;
+-
+- Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM);
+- ret = lbs_prepare_and_send_command(priv,
+- CMD_802_11_PS_MODE,
+- CMD_ACT_SET,
+- 0, 0, &Localpsmode);
+-
+- if (ret) {
+- ret = -1;
+- goto done;
+- }
+- }
+-
+- if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
+- ret = -1;
+- goto done;
+- }
+-
+- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join) +
+- S_DS_GEN + cmdappendsize);
+-
+-done:
+- lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
+- return ret;
+-}
+-
+-int lbs_ret_80211_associate(struct lbs_private *priv,
+- struct cmd_ds_command *resp)
+-{
+- int ret = 0;
+- union iwreq_data wrqu;
+- struct ieeetypes_assocrsp *passocrsp;
+- struct bss_descriptor * bss;
+- u16 status_code;
+-
+- lbs_deb_enter(LBS_DEB_ASSOC);
+-
+- if (!priv->in_progress_assoc_req) {
+- lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n");
+- ret = -1;
+- goto done;
+- }
+- bss = &priv->in_progress_assoc_req->bss;
+-
+- passocrsp = (struct ieeetypes_assocrsp *) & resp->params;
+-
+- /*
+- * Older FW versions map the IEEE 802.11 Status Code in the association
+- * response to the following values returned in passocrsp->statuscode:
+- *
+- * IEEE Status Code Marvell Status Code
+- * 0 -> 0x0000 ASSOC_RESULT_SUCCESS
+- * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
+- * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
+- * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
+- * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
+- * others -> 0x0003 ASSOC_RESULT_REFUSED
+- *
+- * Other response codes:
+- * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused)
+- * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for
+- * association response from the AP)
+- */
+-
+- status_code = le16_to_cpu(passocrsp->statuscode);
+- switch (status_code) {
+- case 0x00:
+- break;
+- case 0x01:
+- lbs_deb_assoc("ASSOC_RESP: invalid parameters\n");
+- break;
+- case 0x02:
+- lbs_deb_assoc("ASSOC_RESP: internal timer "
+- "expired while waiting for the AP\n");
+- break;
+- case 0x03:
+- lbs_deb_assoc("ASSOC_RESP: association "
+- "refused by AP\n");
+- break;
+- case 0x04:
+- lbs_deb_assoc("ASSOC_RESP: authentication "
+- "refused by AP\n");
+- break;
+- default:
+- lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x "
+- " unknown\n", status_code);
+- break;
+- }
+-
+- if (status_code) {
+- lbs_mac_event_disconnected(priv);
+- ret = -1;
+- goto done;
+- }
+-
+- lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP", (void *)&resp->params,
+- le16_to_cpu(resp->size) - S_DS_GEN);
+-
+- /* Send a Media Connected event, according to the Spec */
+- priv->connect_status = LBS_CONNECTED;
+-
+- /* Update current SSID and BSSID */
+- memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
+- priv->curbssparams.ssid_len = bss->ssid_len;
+- memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
+-
+- lbs_deb_assoc("ASSOC_RESP: currentpacketfilter is 0x%x\n",
+- priv->currentpacketfilter);
+-
+- priv->SNR[TYPE_RXPD][TYPE_AVG] = 0;
+- priv->NF[TYPE_RXPD][TYPE_AVG] = 0;
+-
+- memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
+- memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
+- priv->nextSNRNF = 0;
+- priv->numSNRNF = 0;
+-
+- netif_carrier_on(priv->dev);
+- if (!priv->tx_pending_len)
+- netif_wake_queue(priv->dev);
+-
+- memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
+- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+- wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
+-
+-done:
+- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
+- return ret;
+-}
+-
+-int lbs_ret_80211_disassociate(struct lbs_private *priv,
+- struct cmd_ds_command *resp)
+-{
+- lbs_deb_enter(LBS_DEB_JOIN);
+-
+- lbs_mac_event_disconnected(priv);
+-
+- lbs_deb_leave(LBS_DEB_JOIN);
+- return 0;
+-}
+-
+-int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
+- struct cmd_ds_command *resp)
+-{
+- int ret = 0;
+- u16 command = le16_to_cpu(resp->command);
+- u16 result = le16_to_cpu(resp->result);
+- struct cmd_ds_802_11_ad_hoc_result *padhocresult;
+- union iwreq_data wrqu;
+- struct bss_descriptor *bss;
+- DECLARE_MAC_BUF(mac);
+-
+- lbs_deb_enter(LBS_DEB_JOIN);
+-
+- padhocresult = &resp->params.result;
+-
+- lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp->size));
+- lbs_deb_join("ADHOC_RESP: command = %x\n", command);
+- lbs_deb_join("ADHOC_RESP: result = %x\n", result);
+-
+- if (!priv->in_progress_assoc_req) {
+- lbs_deb_join("ADHOC_RESP: no in-progress association request\n");
+- ret = -1;
+- goto done;
+- }
+- bss = &priv->in_progress_assoc_req->bss;
+-
+- /*
+- * Join result code 0 --> SUCCESS
+- */
+- if (result) {
+- lbs_deb_join("ADHOC_RESP: failed\n");
+- if (priv->connect_status == LBS_CONNECTED) {
+- lbs_mac_event_disconnected(priv);
+- }
+- ret = -1;
+- goto done;
+- }
+-
+- /*
+- * Now the join cmd should be successful
+- * If BSSID has changed use SSID to compare instead of BSSID
+- */
+- lbs_deb_join("ADHOC_RESP: associated to '%s'\n",
+- escape_essid(bss->ssid, bss->ssid_len));
+-
+- /* Send a Media Connected event, according to the Spec */
+- priv->connect_status = LBS_CONNECTED;
+-
+- if (command == CMD_RET(CMD_802_11_AD_HOC_START)) {
+- /* Update the created network descriptor with the new BSSID */
+- memcpy(bss->bssid, padhocresult->bssid, ETH_ALEN);
+- }
+-
+- /* Set the BSSID from the joined/started descriptor */
+- memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
+-
+- /* Set the new SSID to current SSID */
+- memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
+- priv->curbssparams.ssid_len = bss->ssid_len;
+-
+- netif_carrier_on(priv->dev);
+- if (!priv->tx_pending_len)
+- netif_wake_queue(priv->dev);
+-
+- memset(&wrqu, 0, sizeof(wrqu));
+- memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
+- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+- wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
+-
+- lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n");
+- lbs_deb_join("ADHOC_RESP: channel = %d\n", priv->curbssparams.channel);
+- lbs_deb_join("ADHOC_RESP: BSSID = %s\n",
+- print_mac(mac, padhocresult->bssid));
+-
+-done:
+- lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
+- return ret;
+-}
+-
+-int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv,
+- struct cmd_ds_command *resp)
+-{
+- lbs_deb_enter(LBS_DEB_JOIN);
+-
+- lbs_mac_event_disconnected(priv);
+-
+- lbs_deb_leave(LBS_DEB_JOIN);
+- return 0;
+-}
+diff --git a/drivers/net/wireless/libertas/join.h b/drivers/net/wireless/libertas/join.h
+deleted file mode 100644
+index c617d07..0000000
+--- a/drivers/net/wireless/libertas/join.h
++++ /dev/null
+@@ -1,53 +0,0 @@
+-/**
+- * Interface for the wlan infrastructure and adhoc join routines
+- *
+- * Driver interface functions and type declarations for the join module
+- * implemented in join.c. Process all start/join requests for
+- * both adhoc and infrastructure networks
+- */
+-#ifndef _LBS_JOIN_H
+-#define _LBS_JOIN_H
+-
+-#include "defs.h"
+-#include "dev.h"
+-
+-struct cmd_ds_command;
+-int lbs_cmd_80211_authenticate(struct lbs_private *priv,
+- struct cmd_ds_command *cmd,
+- void *pdata_buf);
+-int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
+- struct cmd_ds_command *cmd,
+- void *pdata_buf);
+-int lbs_cmd_80211_ad_hoc_stop(struct lbs_private *priv,
+- struct cmd_ds_command *cmd);
+-int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
+- struct cmd_ds_command *cmd,
+- void *pdata_buf);
+-int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
+- struct cmd_ds_command *cmd);
+-int lbs_cmd_80211_associate(struct lbs_private *priv,
+- struct cmd_ds_command *cmd,
+- void *pdata_buf);
+-
+-int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
+- struct cmd_ds_command *resp);
+-int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv,
+- struct cmd_ds_command *resp);
+-int lbs_ret_80211_disassociate(struct lbs_private *priv,
+- struct cmd_ds_command *resp);
+-int lbs_ret_80211_associate(struct lbs_private *priv,
+- struct cmd_ds_command *resp);
+-
+-int lbs_start_adhoc_network(struct lbs_private *priv,
+- struct assoc_request * assoc_req);
+-int lbs_join_adhoc_network(struct lbs_private *priv,
+- struct assoc_request * assoc_req);
+-int lbs_stop_adhoc_network(struct lbs_private *priv);
+-
+-int lbs_send_deauthentication(struct lbs_private *priv);
+-
+-int lbs_associate(struct lbs_private *priv, struct assoc_request *assoc_req);
+-
+-void lbs_unset_basic_rate_flags(u8 *rates, size_t len);
+-
+-#endif
+diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
+index 4d4e2f3..406f54d 100644
+--- a/drivers/net/wireless/libertas/main.c
++++ b/drivers/net/wireless/libertas/main.c
+@@ -10,6 +10,7 @@
+ #include <linux/netdevice.h>
+ #include <linux/if_arp.h>
+ #include <linux/kthread.h>
++#include <linux/kfifo.h>
+
+ #include <net/iw_handler.h>
+ #include <net/ieee80211.h>
+@@ -19,8 +20,8 @@
+ #include "dev.h"
+ #include "wext.h"
+ #include "debugfs.h"
++#include "scan.h"
+ #include "assoc.h"
+-#include "join.h"
+ #include "cmd.h"
+
+ #define DRIVER_RELEASE_VERSION "323.p0"
+@@ -37,6 +38,11 @@ EXPORT_SYMBOL_GPL(lbs_debug);
+ module_param_named(libertas_debug, lbs_debug, int, 0644);
+
+
++/* This global structure is used to send the confirm_sleep command as
++ * fast as possible down to the firmware. */
++struct cmd_confirm_sleep confirm_sleep;
++
++
+ #define LBS_TX_PWR_DEFAULT 20 /*100mW */
+ #define LBS_TX_PWR_US_DEFAULT 20 /*100mW */
+ #define LBS_TX_PWR_JP_DEFAULT 16 /*50mW */
+@@ -277,10 +283,10 @@ static ssize_t lbs_rtap_set(struct device *dev,
+ struct lbs_private *priv = to_net_dev(dev)->priv;
+
+ sscanf(buf, "%x", &monitor_mode);
+- if (monitor_mode != LBS_MONITOR_OFF) {
+- if(priv->monitormode == monitor_mode)
++ if (monitor_mode) {
++ if (priv->monitormode == monitor_mode)
+ return strlen(buf);
+- if (priv->monitormode == LBS_MONITOR_OFF) {
++ if (!priv->monitormode) {
+ if (priv->infra_open || priv->mesh_open)
+ return -EBUSY;
+ if (priv->mode == IW_MODE_INFRA)
+@@ -293,9 +299,9 @@ static ssize_t lbs_rtap_set(struct device *dev,
+ }
+
+ else {
+- if (priv->monitormode == LBS_MONITOR_OFF)
++ if (!priv->monitormode)
+ return strlen(buf);
+- priv->monitormode = LBS_MONITOR_OFF;
++ priv->monitormode = 0;
+ lbs_remove_rtap(priv);
+
+ if (priv->currenttxskb) {
+@@ -392,7 +398,7 @@ static int lbs_dev_open(struct net_device *dev)
+
+ spin_lock_irq(&priv->driver_lock);
+
+- if (priv->monitormode != LBS_MONITOR_OFF) {
++ if (priv->monitormode) {
+ ret = -EBUSY;
+ goto out;
+ }
+@@ -475,10 +481,9 @@ static void lbs_tx_timeout(struct net_device *dev)
+
+ dev->trans_start = jiffies;
+
+- if (priv->currenttxskb) {
+- priv->eventcause = 0x01000000;
+- lbs_send_tx_feedback(priv);
+- }
++ if (priv->currenttxskb)
++ lbs_send_tx_feedback(priv, 0);
++
+ /* XX: Shouldn't we also call into the hw-specific driver
+ to kick it somehow? */
+ lbs_host_to_card_done(priv);
+@@ -531,34 +536,27 @@ static int lbs_set_mac_address(struct net_device *dev, void *addr)
+ int ret = 0;
+ struct lbs_private *priv = (struct lbs_private *) dev->priv;
+ struct sockaddr *phwaddr = addr;
++ struct cmd_ds_802_11_mac_address cmd;
+
+ lbs_deb_enter(LBS_DEB_NET);
+
+ /* In case it was called from the mesh device */
+- dev = priv->dev ;
+-
+- memset(priv->current_addr, 0, ETH_ALEN);
+-
+- /* dev->dev_addr is 8 bytes */
+- lbs_deb_hex(LBS_DEB_NET, "dev->dev_addr", dev->dev_addr, ETH_ALEN);
+-
+- lbs_deb_hex(LBS_DEB_NET, "addr", phwaddr->sa_data, ETH_ALEN);
+- memcpy(priv->current_addr, phwaddr->sa_data, ETH_ALEN);
++ dev = priv->dev;
+
+- ret = lbs_prepare_and_send_command(priv, CMD_802_11_MAC_ADDRESS,
+- CMD_ACT_SET,
+- CMD_OPTION_WAITFORRSP, 0, NULL);
++ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
++ cmd.action = cpu_to_le16(CMD_ACT_SET);
++ memcpy(cmd.macadd, phwaddr->sa_data, ETH_ALEN);
+
++ ret = lbs_cmd_with_response(priv, CMD_802_11_MAC_ADDRESS, &cmd);
+ if (ret) {
+ lbs_deb_net("set MAC address failed\n");
+- ret = -1;
+ goto done;
+ }
+
+- lbs_deb_hex(LBS_DEB_NET, "priv->macaddr", priv->current_addr, ETH_ALEN);
+- memcpy(dev->dev_addr, priv->current_addr, ETH_ALEN);
++ memcpy(priv->current_addr, phwaddr->sa_data, ETH_ALEN);
++ memcpy(dev->dev_addr, phwaddr->sa_data, ETH_ALEN);
+ if (priv->mesh_dev)
+- memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN);
++ memcpy(priv->mesh_dev->dev_addr, phwaddr->sa_data, ETH_ALEN);
+
+ done:
+ lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
+@@ -581,45 +579,45 @@ static int lbs_copy_multicast_address(struct lbs_private *priv,
+ static void lbs_set_multicast_list(struct net_device *dev)
+ {
+ struct lbs_private *priv = dev->priv;
+- int oldpacketfilter;
++ int old_mac_control;
+ DECLARE_MAC_BUF(mac);
+
+ lbs_deb_enter(LBS_DEB_NET);
+
+- oldpacketfilter = priv->currentpacketfilter;
++ old_mac_control = priv->mac_control;
+
+ if (dev->flags & IFF_PROMISC) {
+ lbs_deb_net("enable promiscuous mode\n");
+- priv->currentpacketfilter |=
++ priv->mac_control |=
+ CMD_ACT_MAC_PROMISCUOUS_ENABLE;
+- priv->currentpacketfilter &=
++ priv->mac_control &=
+ ~(CMD_ACT_MAC_ALL_MULTICAST_ENABLE |
+ CMD_ACT_MAC_MULTICAST_ENABLE);
+ } else {
+ /* Multicast */
+- priv->currentpacketfilter &=
++ priv->mac_control &=
+ ~CMD_ACT_MAC_PROMISCUOUS_ENABLE;
+
+ if (dev->flags & IFF_ALLMULTI || dev->mc_count >
+ MRVDRV_MAX_MULTICAST_LIST_SIZE) {
+ lbs_deb_net( "enabling all multicast\n");
+- priv->currentpacketfilter |=
++ priv->mac_control |=
+ CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
+- priv->currentpacketfilter &=
++ priv->mac_control &=
+ ~CMD_ACT_MAC_MULTICAST_ENABLE;
+ } else {
+- priv->currentpacketfilter &=
++ priv->mac_control &=
+ ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
+
+ if (!dev->mc_count) {
+ lbs_deb_net("no multicast addresses, "
+ "disabling multicast\n");
+- priv->currentpacketfilter &=
++ priv->mac_control &=
+ ~CMD_ACT_MAC_MULTICAST_ENABLE;
+ } else {
+ int i;
+
+- priv->currentpacketfilter |=
++ priv->mac_control |=
+ CMD_ACT_MAC_MULTICAST_ENABLE;
+
+ priv->nr_of_multicastmacaddr =
+@@ -642,9 +640,8 @@ static void lbs_set_multicast_list(struct net_device *dev)
+ }
+ }
+
+- if (priv->currentpacketfilter != oldpacketfilter) {
+- lbs_set_mac_packet_filter(priv);
+- }
++ if (priv->mac_control != old_mac_control)
++ lbs_set_mac_control(priv);
+
+ lbs_deb_leave(LBS_DEB_NET);
+ }
+@@ -662,7 +659,6 @@ static int lbs_thread(void *data)
+ struct net_device *dev = data;
+ struct lbs_private *priv = dev->priv;
+ wait_queue_t wait;
+- u8 ireg = 0;
+
+ lbs_deb_enter(LBS_DEB_THREAD);
+
+@@ -670,9 +666,10 @@ static int lbs_thread(void *data)
+
+ for (;;) {
+ int shouldsleep;
++ u8 resp_idx;
+
+- lbs_deb_thread( "main-thread 111: intcounter=%d currenttxskb=%p dnld_sent=%d\n",
+- priv->intcounter, priv->currenttxskb, priv->dnld_sent);
++ lbs_deb_thread("1: currenttxskb %p, dnld_sent %d\n",
++ priv->currenttxskb, priv->dnld_sent);
+
+ add_wait_queue(&priv->waitq, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+@@ -684,8 +681,6 @@ static int lbs_thread(void *data)
+ shouldsleep = 1; /* We need to wait until we're _told_ to die */
+ else if (priv->psstate == PS_STATE_SLEEP)
+ shouldsleep = 1; /* Sleep mode. Nothing we can do till it wakes */
+- else if (priv->intcounter)
+- shouldsleep = 0; /* Interrupt pending. Deal with it now */
+ else if (priv->cmd_timed_out)
+ shouldsleep = 0; /* Command timed out. Recover */
+ else if (!priv->fw_ready)
+@@ -698,29 +693,34 @@ static int lbs_thread(void *data)
+ shouldsleep = 1; /* Can't send a command; one already running */
+ else if (!list_empty(&priv->cmdpendingq))
+ shouldsleep = 0; /* We have a command to send */
++ else if (__kfifo_len(priv->event_fifo))
++ shouldsleep = 0; /* We have an event to process */
++ else if (priv->resp_len[priv->resp_idx])
++ shouldsleep = 0; /* We have a command response */
+ else
+ shouldsleep = 1; /* No command */
+
+ if (shouldsleep) {
+- lbs_deb_thread("main-thread sleeping... Conn=%d IntC=%d PS_mode=%d PS_State=%d\n",
+- priv->connect_status, priv->intcounter,
+- priv->psmode, priv->psstate);
++ lbs_deb_thread("sleeping, connect_status %d, "
++ "ps_mode %d, ps_state %d\n",
++ priv->connect_status,
++ priv->psmode, priv->psstate);
+ spin_unlock_irq(&priv->driver_lock);
+ schedule();
+ } else
+ spin_unlock_irq(&priv->driver_lock);
+
+- lbs_deb_thread("main-thread 222 (waking up): intcounter=%d currenttxskb=%p dnld_sent=%d\n",
+- priv->intcounter, priv->currenttxskb, priv->dnld_sent);
++ lbs_deb_thread("2: currenttxskb %p, dnld_send %d\n",
++ priv->currenttxskb, priv->dnld_sent);
+
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&priv->waitq, &wait);
+
+- lbs_deb_thread("main-thread 333: intcounter=%d currenttxskb=%p dnld_sent=%d\n",
+- priv->intcounter, priv->currenttxskb, priv->dnld_sent);
++ lbs_deb_thread("3: currenttxskb %p, dnld_sent %d\n",
++ priv->currenttxskb, priv->dnld_sent);
+
+ if (kthread_should_stop()) {
+- lbs_deb_thread("main-thread: break from main thread\n");
++ lbs_deb_thread("break from main thread\n");
+ break;
+ }
+
+@@ -729,35 +729,23 @@ static int lbs_thread(void *data)
+ continue;
+ }
+
+- spin_lock_irq(&priv->driver_lock);
+-
+- if (priv->intcounter) {
+- u8 int_status;
+-
+- priv->intcounter = 0;
+- int_status = priv->hw_get_int_status(priv, &ireg);
+-
+- if (int_status) {
+- lbs_deb_thread("main-thread: reading HOST_INT_STATUS_REG failed\n");
+- spin_unlock_irq(&priv->driver_lock);
+- continue;
+- }
+- priv->hisregcpy |= ireg;
+- }
+-
+- lbs_deb_thread("main-thread 444: intcounter=%d currenttxskb=%p dnld_sent=%d\n",
+- priv->intcounter, priv->currenttxskb, priv->dnld_sent);
++ lbs_deb_thread("4: currenttxskb %p, dnld_sent %d\n",
++ priv->currenttxskb, priv->dnld_sent);
+
+- /* command response? */
+- if (priv->hisregcpy & MRVDRV_CMD_UPLD_RDY) {
+- lbs_deb_thread("main-thread: cmd response ready\n");
+-
+- priv->hisregcpy &= ~MRVDRV_CMD_UPLD_RDY;
++ spin_lock_irq(&priv->driver_lock);
++ /* Process any pending command response */
++ resp_idx = priv->resp_idx;
++ if (priv->resp_len[resp_idx]) {
+ spin_unlock_irq(&priv->driver_lock);
+- lbs_process_rx_command(priv);
++ lbs_process_command_response(priv,
++ priv->resp_buf[resp_idx],
++ priv->resp_len[resp_idx]);
+ spin_lock_irq(&priv->driver_lock);
++ priv->resp_len[resp_idx] = 0;
+ }
++ spin_unlock_irq(&priv->driver_lock);
+
++ /* command timeout stuff */
+ if (priv->cmd_timed_out && priv->cur_cmd) {
+ struct cmd_ctrl_node *cmdnode = priv->cur_cmd;
+
+@@ -778,21 +766,18 @@ static int lbs_thread(void *data)
+ }
+ priv->cmd_timed_out = 0;
+
+- /* Any Card Event */
+- if (priv->hisregcpy & MRVDRV_CARDEVENT) {
+- lbs_deb_thread("main-thread: Card Event Activity\n");
+-
+- priv->hisregcpy &= ~MRVDRV_CARDEVENT;
++ /* Process hardware events, e.g. card removed, link lost */
++ spin_lock_irq(&priv->driver_lock);
++ while (__kfifo_len(priv->event_fifo)) {
++ u32 event;
+
+- if (priv->hw_read_event_cause(priv)) {
+- lbs_pr_alert("main-thread: hw_read_event_cause failed\n");
+- spin_unlock_irq(&priv->driver_lock);
+- continue;
+- }
+- spin_unlock_irq(&priv->driver_lock);
+- lbs_process_event(priv);
+- } else
++ __kfifo_get(priv->event_fifo, (unsigned char *) &event,
++ sizeof(event));
+ spin_unlock_irq(&priv->driver_lock);
++ lbs_process_event(priv, event);
++ spin_lock_irq(&priv->driver_lock);
++ }
++ spin_unlock_irq(&priv->driver_lock);
+
+ if (!priv->fw_ready)
+ continue;
+@@ -801,10 +786,12 @@ static int lbs_thread(void *data)
+ if (priv->psstate == PS_STATE_PRE_SLEEP &&
+ !priv->dnld_sent && !priv->cur_cmd) {
+ if (priv->connect_status == LBS_CONNECTED) {
+- lbs_deb_thread("main_thread: PRE_SLEEP--intcounter=%d currenttxskb=%p dnld_sent=%d cur_cmd=%p, confirm now\n",
+- priv->intcounter, priv->currenttxskb, priv->dnld_sent, priv->cur_cmd);
++ lbs_deb_thread("pre-sleep, currenttxskb %p, "
++ "dnld_sent %d, cur_cmd %p\n",
++ priv->currenttxskb, priv->dnld_sent,
++ priv->cur_cmd);
+
+- lbs_ps_confirm_sleep(priv, (u16) priv->psmode);
++ lbs_ps_confirm_sleep(priv);
+ } else {
+ /* workaround for firmware sending
+ * deauth/linkloss event immediately
+@@ -812,7 +799,8 @@ static int lbs_thread(void *data)
+ * after firmware fixes it
+ */
+ priv->psstate = PS_STATE_AWAKE;
+- lbs_pr_alert("main-thread: ignore PS_SleepConfirm in non-connected state\n");
++ lbs_pr_alert("ignore PS_SleepConfirm in "
++ "non-connected state\n");
+ }
+ }
+
+@@ -945,7 +933,7 @@ static int lbs_setup_firmware(struct lbs_private *priv)
+ goto done;
+ }
+
+- lbs_set_mac_packet_filter(priv);
++ lbs_set_mac_control(priv);
+
+ ret = lbs_get_data_rate(priv);
+ if (ret < 0) {
+@@ -985,6 +973,18 @@ out:
+ lbs_deb_leave(LBS_DEB_CMD);
+ }
+
++static void lbs_sync_channel_worker(struct work_struct *work)
++{
++ struct lbs_private *priv = container_of(work, struct lbs_private,
++ sync_channel);
++
++ lbs_deb_enter(LBS_DEB_MAIN);
++ if (lbs_update_channel(priv))
++ lbs_pr_info("Channel synchronization failed.");
++ lbs_deb_leave(LBS_DEB_MAIN);
++}
++
++
+ static int lbs_init_adapter(struct lbs_private *priv)
+ {
+ size_t bufsize;
+@@ -1009,14 +1009,6 @@ static int lbs_init_adapter(struct lbs_private *priv)
+ &priv->network_free_list);
+ }
+
+- priv->lbs_ps_confirm_sleep.seqnum = cpu_to_le16(++priv->seqnum);
+- priv->lbs_ps_confirm_sleep.command =
+- cpu_to_le16(CMD_802_11_PS_MODE);
+- priv->lbs_ps_confirm_sleep.size =
+- cpu_to_le16(sizeof(struct PS_CMD_ConfirmSleep));
+- priv->lbs_ps_confirm_sleep.action =
+- cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED);
+-
+ memset(priv->current_addr, 0xff, ETH_ALEN);
+
+ priv->connect_status = LBS_DISCONNECTED;
+@@ -1024,7 +1016,7 @@ static int lbs_init_adapter(struct lbs_private *priv)
+ priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
+ priv->mode = IW_MODE_INFRA;
+ priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL;
+- priv->currentpacketfilter = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
++ priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
+ priv->radioon = RADIO_ON;
+ priv->auto_rate = 1;
+ priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
+@@ -1045,7 +1037,18 @@ static int lbs_init_adapter(struct lbs_private *priv)
+ /* Allocate the command buffers */
+ if (lbs_allocate_cmd_buffer(priv)) {
+ lbs_pr_err("Out of memory allocating command buffers\n");
+- ret = -1;
++ ret = -ENOMEM;
++ goto out;
++ }
++ priv->resp_idx = 0;
++ priv->resp_len[0] = priv->resp_len[1] = 0;
++
++ /* Create the event FIFO */
++ priv->event_fifo = kfifo_alloc(sizeof(u32) * 16, GFP_KERNEL, NULL);
++ if (IS_ERR(priv->event_fifo)) {
++ lbs_pr_err("Out of memory allocating event FIFO buffer\n");
++ ret = -ENOMEM;
++ goto out;
+ }
+
+ out:
+@@ -1059,6 +1062,8 @@ static void lbs_free_adapter(struct lbs_private *priv)
+ lbs_deb_enter(LBS_DEB_MAIN);
+
+ lbs_free_cmd_buffer(priv);
++ if (priv->event_fifo)
++ kfifo_free(priv->event_fifo);
+ del_timer(&priv->command_timer);
+ kfree(priv->networks);
+ priv->networks = NULL;
+@@ -1128,7 +1133,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
+ priv->work_thread = create_singlethread_workqueue("lbs_worker");
+ INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker);
+ INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker);
+- INIT_WORK(&priv->sync_channel, lbs_sync_channel);
++ INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker);
+
+ sprintf(priv->mesh_ssid, "mesh");
+ priv->mesh_ssid_len = 4;
+@@ -1380,7 +1385,7 @@ static void lbs_remove_mesh(struct lbs_private *priv)
+ * @param cfp_no A pointer to CFP number
+ * @return A pointer to CFP
+ */
+-struct chan_freq_power *lbs_get_region_cfp_table(u8 region, u8 band, int *cfp_no)
++struct chan_freq_power *lbs_get_region_cfp_table(u8 region, int *cfp_no)
+ {
+ int i, end;
+
+@@ -1414,7 +1419,7 @@ int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band)
+
+ memset(priv->region_channel, 0, sizeof(priv->region_channel));
+
+- cfp = lbs_get_region_cfp_table(region, band, &cfp_no);
++ cfp = lbs_get_region_cfp_table(region, &cfp_no);
+ if (cfp != NULL) {
+ priv->region_channel[i].nrcfp = cfp_no;
+ priv->region_channel[i].CFP = cfp;
+@@ -1433,31 +1438,49 @@ out:
+ return ret;
+ }
+
+-/**
+- * @brief This function handles the interrupt. it will change PS
+- * state if applicable. it will wake up main_thread to handle
+- * the interrupt event as well.
+- *
+- * @param dev A pointer to net_device structure
+- * @return n/a
+- */
+-void lbs_interrupt(struct lbs_private *priv)
++void lbs_queue_event(struct lbs_private *priv, u32 event)
++{
++ unsigned long flags;
++
++ lbs_deb_enter(LBS_DEB_THREAD);
++ spin_lock_irqsave(&priv->driver_lock, flags);
++
++ if (priv->psstate == PS_STATE_SLEEP)
++ priv->psstate = PS_STATE_AWAKE;
++
++ __kfifo_put(priv->event_fifo, (unsigned char *) &event, sizeof(u32));
++
++ wake_up_interruptible(&priv->waitq);
++
++ spin_unlock_irqrestore(&priv->driver_lock, flags);
++ lbs_deb_leave(LBS_DEB_THREAD);
++}
++EXPORT_SYMBOL_GPL(lbs_queue_event);
++
++void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx)
+ {
+ lbs_deb_enter(LBS_DEB_THREAD);
+
+- lbs_deb_thread("lbs_interrupt: intcounter=%d\n", priv->intcounter);
+- priv->intcounter++;
+ if (priv->psstate == PS_STATE_SLEEP)
+ priv->psstate = PS_STATE_AWAKE;
++
++ /* Swap buffers by flipping the response index */
++ BUG_ON(resp_idx > 1);
++ priv->resp_idx = resp_idx;
++
+ wake_up_interruptible(&priv->waitq);
+
+ lbs_deb_leave(LBS_DEB_THREAD);
+ }
+-EXPORT_SYMBOL_GPL(lbs_interrupt);
++EXPORT_SYMBOL_GPL(lbs_notify_command_response);
+
+ static int __init lbs_init_module(void)
+ {
+ lbs_deb_enter(LBS_DEB_MAIN);
++ memset(&confirm_sleep, 0, sizeof(confirm_sleep));
++ confirm_sleep.hdr.command = cpu_to_le16(CMD_802_11_PS_MODE);
++ confirm_sleep.hdr.size = cpu_to_le16(sizeof(confirm_sleep));
++ confirm_sleep.action = cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED);
+ lbs_debugfs_init();
+ lbs_deb_leave(LBS_DEB_MAIN);
+ return 0;
+@@ -1554,6 +1577,32 @@ out:
+ return ret;
+ }
+
++#ifndef CONFIG_IEEE80211
++const char *escape_essid(const char *essid, u8 essid_len)
++{
++ static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
++ const char *s = essid;
++ char *d = escaped;
++
++ if (ieee80211_is_empty_essid(essid, essid_len)) {
++ memcpy(escaped, "<hidden>", sizeof("<hidden>"));
++ return escaped;
++ }
++
++ essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
++ while (essid_len--) {
++ if (*s == '\0') {
++ *d++ = '\\';
++ *d++ = '0';
++ s++;
++ } else {
++ *d++ = *s++;
++ }
++ }
++ *d = '\0';
++ return escaped;
++}
++#endif
+
+ module_init(lbs_init_module);
+ module_exit(lbs_exit_module);
+diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
+index 149557a..05af731 100644
+--- a/drivers/net/wireless/libertas/rx.c
++++ b/drivers/net/wireless/libertas/rx.c
+@@ -145,17 +145,17 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
+ struct net_device *dev = priv->dev;
+ struct rxpackethdr *p_rx_pkt;
+ struct rxpd *p_rx_pd;
+-
+ int hdrchop;
+ struct ethhdr *p_ethhdr;
+-
+ const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
+
+ lbs_deb_enter(LBS_DEB_RX);
+
++ BUG_ON(!skb);
++
+ skb->ip_summed = CHECKSUM_NONE;
+
+- if (priv->monitormode != LBS_MONITOR_OFF)
++ if (priv->monitormode)
+ return process_rxed_802_11_packet(priv, skb);
+
+ p_rx_pkt = (struct rxpackethdr *) skb->data;
+diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
+index 69f94c9..e72c97a 100644
+--- a/drivers/net/wireless/libertas/scan.c
++++ b/drivers/net/wireless/libertas/scan.c
+@@ -4,22 +4,14 @@
+ * IOCTL handlers as well as command preperation and response routines
+ * for sending scan commands to the firmware.
+ */
+-#include <linux/ctype.h>
+-#include <linux/if.h>
+-#include <linux/netdevice.h>
+-#include <linux/wireless.h>
+ #include <linux/etherdevice.h>
+-
+-#include <net/ieee80211.h>
+-#include <net/iw_handler.h>
+-
+ #include <asm/unaligned.h>
+
+ #include "host.h"
+ #include "decl.h"
+ #include "dev.h"
+ #include "scan.h"
+-#include "join.h"
++#include "cmd.h"
+
+ //! Approximate amount of data needed to pass a scan result back to iwlist
+ #define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \
+@@ -39,10 +31,9 @@
+ //! Memory needed to store a max number/size SSID TLV for a firmware scan
+ #define SSID_TLV_MAX_SIZE (1 * sizeof(struct mrvlietypes_ssidparamset))
+
+-//! Maximum memory needed for a lbs_scan_cmd_config with all TLVs at max
+-#define MAX_SCAN_CFG_ALLOC (sizeof(struct lbs_scan_cmd_config) \
+- + CHAN_TLV_MAX_SIZE \
+- + SSID_TLV_MAX_SIZE)
++//! Maximum memory needed for a cmd_ds_802_11_scan with all TLVs at max
++#define MAX_SCAN_CFG_ALLOC (sizeof(struct cmd_ds_802_11_scan) \
++ + CHAN_TLV_MAX_SIZE + SSID_TLV_MAX_SIZE)
+
+ //! The maximum number of channels the firmware can scan per command
+ #define MRVDRV_MAX_CHANNELS_PER_SCAN 14
+@@ -61,11 +52,8 @@
+ //! Scan time specified in the channel TLV for each channel for active scans
+ #define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100
+
+-static const u8 zeromac[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+-static const u8 bcastmac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+-
+-
+-
++static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
++ struct cmd_header *resp);
+
+ /*********************************************************************/
+ /* */
+@@ -73,7 +61,24 @@ static const u8 bcastmac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+ /* */
+ /*********************************************************************/
+
+-static inline void clear_bss_descriptor (struct bss_descriptor * bss)
++/**
++ * @brief Unsets the MSB on basic rates
++ *
++ * Scan through an array and unset the MSB for basic data rates.
++ *
++ * @param rates buffer of data rates
++ * @param len size of buffer
++ */
++static void lbs_unset_basic_rate_flags(u8 *rates, size_t len)
++{
++ int i;
++
++ for (i = 0; i < len; i++)
++ rates[i] &= 0x7f;
++}
++
++
++static inline void clear_bss_descriptor(struct bss_descriptor *bss)
+ {
+ /* Don't blow away ->list, just BSS data */
+ memset(bss, 0, offsetof(struct bss_descriptor, list));
+@@ -87,7 +92,8 @@ static inline void clear_bss_descriptor (struct bss_descriptor * bss)
+ *
+ * @return 0: ssid is same, otherwise is different
+ */
+-int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len)
++int lbs_ssid_cmp(uint8_t *ssid1, uint8_t ssid1_len, uint8_t *ssid2,
++ uint8_t ssid2_len)
+ {
+ if (ssid1_len != ssid2_len)
+ return -1;
+@@ -95,76 +101,6 @@ int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len)
+ return memcmp(ssid1, ssid2, ssid1_len);
+ }
+
+-static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
+- struct bss_descriptor * match_bss)
+-{
+- if ( !secinfo->wep_enabled
+- && !secinfo->WPAenabled
+- && !secinfo->WPA2enabled
+- && match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC
+- && match_bss->rsn_ie[0] != MFIE_TYPE_RSN
+- && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
+- return 1;
+- }
+- return 0;
+-}
+-
+-static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo,
+- struct bss_descriptor * match_bss)
+-{
+- if ( secinfo->wep_enabled
+- && !secinfo->WPAenabled
+- && !secinfo->WPA2enabled
+- && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
+- return 1;
+- }
+- return 0;
+-}
+-
+-static inline int match_bss_wpa(struct lbs_802_11_security *secinfo,
+- struct bss_descriptor * match_bss)
+-{
+- if ( !secinfo->wep_enabled
+- && secinfo->WPAenabled
+- && (match_bss->wpa_ie[0] == MFIE_TYPE_GENERIC)
+- /* privacy bit may NOT be set in some APs like LinkSys WRT54G
+- && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
+- */
+- ) {
+- return 1;
+- }
+- return 0;
+-}
+-
+-static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo,
+- struct bss_descriptor * match_bss)
+-{
+- if ( !secinfo->wep_enabled
+- && secinfo->WPA2enabled
+- && (match_bss->rsn_ie[0] == MFIE_TYPE_RSN)
+- /* privacy bit may NOT be set in some APs like LinkSys WRT54G
+- && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
+- */
+- ) {
+- return 1;
+- }
+- return 0;
+-}
+-
+-static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo,
+- struct bss_descriptor * match_bss)
+-{
+- if ( !secinfo->wep_enabled
+- && !secinfo->WPAenabled
+- && !secinfo->WPA2enabled
+- && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC)
+- && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN)
+- && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
+- return 1;
+- }
+- return 0;
+-}
+-
+ static inline int is_same_network(struct bss_descriptor *src,
+ struct bss_descriptor *dst)
+ {
+@@ -177,83 +113,6 @@ static inline int is_same_network(struct bss_descriptor *src,
+ !memcmp(src->ssid, dst->ssid, src->ssid_len));
+ }
+
+-/**
+- * @brief Check if a scanned network compatible with the driver settings
+- *
+- * WEP WPA WPA2 ad-hoc encrypt Network
+- * enabled enabled enabled AES mode privacy WPA WPA2 Compatible
+- * 0 0 0 0 NONE 0 0 0 yes No security
+- * 1 0 0 0 NONE 1 0 0 yes Static WEP
+- * 0 1 0 0 x 1x 1 x yes WPA
+- * 0 0 1 0 x 1x x 1 yes WPA2
+- * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES
+- * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP
+- *
+- *
+- * @param priv A pointer to struct lbs_private
+- * @param index Index in scantable to check against current driver settings
+- * @param mode Network mode: Infrastructure or IBSS
+- *
+- * @return Index in scantable, or error code if negative
+- */
+-static int is_network_compatible(struct lbs_private *priv,
+- struct bss_descriptor * bss, u8 mode)
+-{
+- int matched = 0;
+-
+- lbs_deb_enter(LBS_DEB_SCAN);
+-
+- if (bss->mode != mode)
+- goto done;
+-
+- if ((matched = match_bss_no_security(&priv->secinfo, bss))) {
+- goto done;
+- } else if ((matched = match_bss_static_wep(&priv->secinfo, bss))) {
+- goto done;
+- } else if ((matched = match_bss_wpa(&priv->secinfo, bss))) {
+- lbs_deb_scan(
+- "is_network_compatible() WPA: wpa_ie 0x%x "
+- "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
+- "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
+- priv->secinfo.wep_enabled ? "e" : "d",
+- priv->secinfo.WPAenabled ? "e" : "d",
+- priv->secinfo.WPA2enabled ? "e" : "d",
+- (bss->capability & WLAN_CAPABILITY_PRIVACY));
+- goto done;
+- } else if ((matched = match_bss_wpa2(&priv->secinfo, bss))) {
+- lbs_deb_scan(
+- "is_network_compatible() WPA2: wpa_ie 0x%x "
+- "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
+- "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
+- priv->secinfo.wep_enabled ? "e" : "d",
+- priv->secinfo.WPAenabled ? "e" : "d",
+- priv->secinfo.WPA2enabled ? "e" : "d",
+- (bss->capability & WLAN_CAPABILITY_PRIVACY));
+- goto done;
+- } else if ((matched = match_bss_dynamic_wep(&priv->secinfo, bss))) {
+- lbs_deb_scan(
+- "is_network_compatible() dynamic WEP: "
+- "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n",
+- bss->wpa_ie[0], bss->rsn_ie[0],
+- (bss->capability & WLAN_CAPABILITY_PRIVACY));
+- goto done;
+- }
+-
+- /* bss security settings don't match those configured on card */
+- lbs_deb_scan(
+- "is_network_compatible() FAILED: wpa_ie 0x%x "
+- "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n",
+- bss->wpa_ie[0], bss->rsn_ie[0],
+- priv->secinfo.wep_enabled ? "e" : "d",
+- priv->secinfo.WPAenabled ? "e" : "d",
+- priv->secinfo.WPA2enabled ? "e" : "d",
+- (bss->capability & WLAN_CAPABILITY_PRIVACY));
+-
+-done:
+- lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched);
+- return matched;
+-}
+-
+
+
+
+@@ -263,17 +122,6 @@ done:
+ /* */
+ /*********************************************************************/
+
+-void lbs_scan_worker(struct work_struct *work)
+-{
+- struct lbs_private *priv =
+- container_of(work, struct lbs_private, scan_work.work);
+-
+- lbs_deb_enter(LBS_DEB_SCAN);
+- lbs_scan_networks(priv, NULL, 0);
+- lbs_deb_leave(LBS_DEB_SCAN);
+-}
+-
+-
+ /**
+ * @brief Create a channel list for the driver to scan based on region info
+ *
+@@ -285,25 +133,18 @@ void lbs_scan_worker(struct work_struct *work)
+ *
+ * @param priv A pointer to struct lbs_private structure
+ * @param scanchanlist Output parameter: resulting channel list to scan
+- * @param filteredscan Flag indicating whether or not a BSSID or SSID filter
+- * is being sent in the command to firmware. Used to
+- * increase the number of channels sent in a scan
+- * command and to disable the firmware channel scan
+- * filter.
+ *
+ * @return void
+ */
+ static int lbs_scan_create_channel_list(struct lbs_private *priv,
+- struct chanscanparamset * scanchanlist,
+- u8 filteredscan)
++ struct chanscanparamset *scanchanlist)
+ {
+-
+ struct region_channel *scanregion;
+ struct chan_freq_power *cfp;
+ int rgnidx;
+ int chanidx;
+ int nextchan;
+- u8 scantype;
++ uint8_t scantype;
+
+ chanidx = 0;
+
+@@ -314,9 +155,8 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv,
+ scantype = CMD_SCAN_TYPE_ACTIVE;
+
+ for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) {
+- if (priv->enable11d &&
+- (priv->connect_status != LBS_CONNECTED) &&
+- (priv->mesh_connect_status != LBS_CONNECTED)) {
++ if (priv->enable11d && (priv->connect_status != LBS_CONNECTED)
++ && (priv->mesh_connect_status != LBS_CONNECTED)) {
+ /* Scan all the supported chan for the first scan */
+ if (!priv->universal_channel[rgnidx].valid)
+ continue;
+@@ -331,51 +171,32 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv,
+ scanregion = &priv->region_channel[rgnidx];
+ }
+
+- for (nextchan = 0;
+- nextchan < scanregion->nrcfp; nextchan++, chanidx++) {
++ for (nextchan = 0; nextchan < scanregion->nrcfp; nextchan++, chanidx++) {
++ struct chanscanparamset *chan = &scanchanlist[chanidx];
+
+ cfp = scanregion->CFP + nextchan;
+
+- if (priv->enable11d) {
+- scantype =
+- lbs_get_scan_type_11d(cfp->channel,
+- &priv->
+- parsed_region_chan);
+- }
++ if (priv->enable11d)
++ scantype = lbs_get_scan_type_11d(cfp->channel,
++ &priv->parsed_region_chan);
+
+- switch (scanregion->band) {
+- case BAND_B:
+- case BAND_G:
+- default:
+- scanchanlist[chanidx].radiotype =
+- CMD_SCAN_RADIO_TYPE_BG;
+- break;
+- }
++ if (scanregion->band == BAND_B || scanregion->band == BAND_G)
++ chan->radiotype = CMD_SCAN_RADIO_TYPE_BG;
+
+ if (scantype == CMD_SCAN_TYPE_PASSIVE) {
+- scanchanlist[chanidx].maxscantime =
+- cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME);
+- scanchanlist[chanidx].chanscanmode.passivescan =
+- 1;
++ chan->maxscantime = cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME);
++ chan->chanscanmode.passivescan = 1;
+ } else {
+- scanchanlist[chanidx].maxscantime =
+- cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME);
+- scanchanlist[chanidx].chanscanmode.passivescan =
+- 0;
++ chan->maxscantime = cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME);
++ chan->chanscanmode.passivescan = 0;
+ }
+
+- scanchanlist[chanidx].channumber = cfp->channel;
+-
+- if (filteredscan) {
+- scanchanlist[chanidx].chanscanmode.
+- disablechanfilt = 1;
+- }
++ chan->channumber = cfp->channel;
+ }
+ }
+ return chanidx;
+ }
+
+-
+ /*
+ * Add SSID TLV of the form:
+ *
+@@ -383,18 +204,16 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv,
+ * length 06 00
+ * ssid 4d 4e 54 45 53 54
+ */
+-static int lbs_scan_add_ssid_tlv(u8 *tlv,
+- const struct lbs_ioctl_user_scan_cfg *user_cfg)
++static int lbs_scan_add_ssid_tlv(struct lbs_private *priv, u8 *tlv)
+ {
+- struct mrvlietypes_ssidparamset *ssid_tlv =
+- (struct mrvlietypes_ssidparamset *)tlv;
++ struct mrvlietypes_ssidparamset *ssid_tlv = (void *)tlv;
++
+ ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID);
+- ssid_tlv->header.len = cpu_to_le16(user_cfg->ssid_len);
+- memcpy(ssid_tlv->ssid, user_cfg->ssid, user_cfg->ssid_len);
+- return sizeof(ssid_tlv->header) + user_cfg->ssid_len;
++ ssid_tlv->header.len = cpu_to_le16(priv->scan_ssid_len);
++ memcpy(ssid_tlv->ssid, priv->scan_ssid, priv->scan_ssid_len);
++ return sizeof(ssid_tlv->header) + priv->scan_ssid_len;
+ }
+
+-
+ /*
+ * Add CHANLIST TLV of the form
+ *
+@@ -420,13 +239,12 @@ static int lbs_scan_add_ssid_tlv(u8 *tlv,
+ * channel 13 00 0d 00 00 00 64 00
+ *
+ */
+-static int lbs_scan_add_chanlist_tlv(u8 *tlv,
+- struct chanscanparamset *chan_list,
+- int chan_count)
++static int lbs_scan_add_chanlist_tlv(uint8_t *tlv,
++ struct chanscanparamset *chan_list,
++ int chan_count)
+ {
+- size_t size = sizeof(struct chanscanparamset) * chan_count;
+- struct mrvlietypes_chanlistparamset *chan_tlv =
+- (struct mrvlietypes_chanlistparamset *) tlv;
++ size_t size = sizeof(struct chanscanparamset) *chan_count;
++ struct mrvlietypes_chanlistparamset *chan_tlv = (void *)tlv;
+
+ chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
+ memcpy(chan_tlv->chanscanparam, chan_list, size);
+@@ -434,7 +252,6 @@ static int lbs_scan_add_chanlist_tlv(u8 *tlv,
+ return sizeof(chan_tlv->header) + size;
+ }
+
+-
+ /*
+ * Add RATES TLV of the form
+ *
+@@ -445,11 +262,10 @@ static int lbs_scan_add_chanlist_tlv(u8 *tlv,
+ * The rates are in lbs_bg_rates[], but for the 802.11b
+ * rates the high bit isn't set.
+ */
+-static int lbs_scan_add_rates_tlv(u8 *tlv)
++static int lbs_scan_add_rates_tlv(uint8_t *tlv)
+ {
+ int i;
+- struct mrvlietypes_ratesparamset *rate_tlv =
+- (struct mrvlietypes_ratesparamset *) tlv;
++ struct mrvlietypes_ratesparamset *rate_tlv = (void *)tlv;
+
+ rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES);
+ tlv += sizeof(rate_tlv->header);
+@@ -470,82 +286,74 @@ static int lbs_scan_add_rates_tlv(u8 *tlv)
+ return sizeof(rate_tlv->header) + i;
+ }
+
+-
+ /*
+ * Generate the CMD_802_11_SCAN command with the proper tlv
+ * for a bunch of channels.
+ */
+-static int lbs_do_scan(struct lbs_private *priv,
+- u8 bsstype,
+- struct chanscanparamset *chan_list,
+- int chan_count,
+- const struct lbs_ioctl_user_scan_cfg *user_cfg)
++static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype,
++ struct chanscanparamset *chan_list, int chan_count)
+ {
+ int ret = -ENOMEM;
+- struct lbs_scan_cmd_config *scan_cmd;
+- u8 *tlv; /* pointer into our current, growing TLV storage area */
++ struct cmd_ds_802_11_scan *scan_cmd;
++ uint8_t *tlv; /* pointer into our current, growing TLV storage area */
+
+- lbs_deb_enter_args(LBS_DEB_SCAN, "bsstype %d, chanlist[].chan %d, "
+- "chan_count %d",
+- bsstype, chan_list[0].channumber, chan_count);
++ lbs_deb_enter_args(LBS_DEB_SCAN, "bsstype %d, chanlist[].chan %d, chan_count %d",
++ bsstype, chan_list[0].channumber, chan_count);
+
+ /* create the fixed part for scan command */
+ scan_cmd = kzalloc(MAX_SCAN_CFG_ALLOC, GFP_KERNEL);
+ if (scan_cmd == NULL)
+ goto out;
++
+ tlv = scan_cmd->tlvbuffer;
+- if (user_cfg)
+- memcpy(scan_cmd->bssid, user_cfg->bssid, ETH_ALEN);
++ /* TODO: do we need to scan for a specific BSSID?
++ memcpy(scan_cmd->bssid, priv->scan_bssid, ETH_ALEN); */
+ scan_cmd->bsstype = bsstype;
+
+ /* add TLVs */
+- if (user_cfg && user_cfg->ssid_len)
+- tlv += lbs_scan_add_ssid_tlv(tlv, user_cfg);
++ if (priv->scan_ssid_len)
++ tlv += lbs_scan_add_ssid_tlv(priv, tlv);
+ if (chan_list && chan_count)
+ tlv += lbs_scan_add_chanlist_tlv(tlv, chan_list, chan_count);
+ tlv += lbs_scan_add_rates_tlv(tlv);
+
+ /* This is the final data we are about to send */
+- scan_cmd->tlvbufferlen = tlv - scan_cmd->tlvbuffer;
+- lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd, 1+6);
++ scan_cmd->hdr.size = cpu_to_le16(tlv - (uint8_t *)scan_cmd);
++ lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd,
++ sizeof(*scan_cmd));
+ lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TLV", scan_cmd->tlvbuffer,
+- scan_cmd->tlvbufferlen);
++ tlv - scan_cmd->tlvbuffer);
++
++ ret = __lbs_cmd(priv, CMD_802_11_SCAN, &scan_cmd->hdr,
++ le16_to_cpu(scan_cmd->hdr.size),
++ lbs_ret_80211_scan, 0);
+
+- ret = lbs_prepare_and_send_command(priv, CMD_802_11_SCAN, 0,
+- CMD_OPTION_WAITFORRSP, 0, scan_cmd);
+ out:
+ kfree(scan_cmd);
+ lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
+ return ret;
+ }
+
+-
+ /**
+ * @brief Internal function used to start a scan based on an input config
+ *
+- * Also used from debugfs
+- *
+ * Use the input user scan configuration information when provided in
+ * order to send the appropriate scan commands to firmware to populate or
+ * update the internal driver scan table
+ *
+ * @param priv A pointer to struct lbs_private structure
+- * @param puserscanin Pointer to the input configuration for the requested
+- * scan.
++ * @param full_scan Do a full-scan (blocking)
+ *
+ * @return 0 or < 0 if error
+ */
+-int lbs_scan_networks(struct lbs_private *priv,
+- const struct lbs_ioctl_user_scan_cfg *user_cfg,
+- int full_scan)
++int lbs_scan_networks(struct lbs_private *priv, int full_scan)
+ {
+ int ret = -ENOMEM;
+ struct chanscanparamset *chan_list;
+ struct chanscanparamset *curr_chans;
+ int chan_count;
+- u8 bsstype = CMD_BSS_TYPE_ANY;
++ uint8_t bsstype = CMD_BSS_TYPE_ANY;
+ int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD;
+- int filteredscan = 0;
+ union iwreq_data wrqu;
+ #ifdef CONFIG_LIBERTAS_DEBUG
+ struct bss_descriptor *iter;
+@@ -553,8 +361,7 @@ int lbs_scan_networks(struct lbs_private *priv,
+ DECLARE_MAC_BUF(mac);
+ #endif
+
+- lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d",
+- full_scan);
++ lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", full_scan);
+
+ /* Cancel any partial outstanding partial scans if this scan
+ * is a full scan.
+@@ -562,30 +369,27 @@ int lbs_scan_networks(struct lbs_private *priv,
+ if (full_scan && delayed_work_pending(&priv->scan_work))
+ cancel_delayed_work(&priv->scan_work);
+
+- /* Determine same scan parameters */
++ /* User-specified bsstype or channel list
++ TODO: this can be implemented if some user-space application
++ need the feature. Formerly, it was accessible from debugfs,
++ but then nowhere used.
+ if (user_cfg) {
+ if (user_cfg->bsstype)
+- bsstype = user_cfg->bsstype;
+- if (compare_ether_addr(user_cfg->bssid, &zeromac[0]) != 0) {
+- numchannels = MRVDRV_MAX_CHANNELS_PER_SCAN;
+- filteredscan = 1;
+- }
+- }
+- lbs_deb_scan("numchannels %d, bsstype %d, "
+- "filteredscan %d\n",
+- numchannels, bsstype, filteredscan);
++ bsstype = user_cfg->bsstype;
++ } */
++
++ lbs_deb_scan("numchannels %d, bsstype %d\n", numchannels, bsstype);
+
+ /* Create list of channels to scan */
+ chan_list = kzalloc(sizeof(struct chanscanparamset) *
+- LBS_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL);
++ LBS_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL);
+ if (!chan_list) {
+ lbs_pr_alert("SCAN: chan_list empty\n");
+ goto out;
+ }
+
+ /* We want to scan all channels */
+- chan_count = lbs_scan_create_channel_list(priv, chan_list,
+- filteredscan);
++ chan_count = lbs_scan_create_channel_list(priv, chan_list);
+
+ netif_stop_queue(priv->dev);
+ netif_carrier_off(priv->dev);
+@@ -595,13 +399,13 @@ int lbs_scan_networks(struct lbs_private *priv,
+ }
+
+ /* Prepare to continue an interrupted scan */
+- lbs_deb_scan("chan_count %d, last_scanned_channel %d\n",
+- chan_count, priv->last_scanned_channel);
++ lbs_deb_scan("chan_count %d, scan_channel %d\n",
++ chan_count, priv->scan_channel);
+ curr_chans = chan_list;
+ /* advance channel list by already-scanned-channels */
+- if (priv->last_scanned_channel > 0) {
+- curr_chans += priv->last_scanned_channel;
+- chan_count -= priv->last_scanned_channel;
++ if (priv->scan_channel > 0) {
++ curr_chans += priv->scan_channel;
++ chan_count -= priv->scan_channel;
+ }
+
+ /* Send scan command(s)
+@@ -612,9 +416,9 @@ int lbs_scan_networks(struct lbs_private *priv,
+ while (chan_count) {
+ int to_scan = min(numchannels, chan_count);
+ lbs_deb_scan("scanning %d of %d channels\n",
+- to_scan, chan_count);
++ to_scan, chan_count);
+ ret = lbs_do_scan(priv, bsstype, curr_chans,
+- to_scan, user_cfg);
++ to_scan);
+ if (ret) {
+ lbs_pr_err("SCAN_CMD failed\n");
+ goto out2;
+@@ -623,17 +427,16 @@ int lbs_scan_networks(struct lbs_private *priv,
+ chan_count -= to_scan;
+
+ /* somehow schedule the next part of the scan */
+- if (chan_count &&
+- !full_scan &&
++ if (chan_count && !full_scan &&
+ !priv->surpriseremoved) {
+ /* -1 marks just that we're currently scanning */
+- if (priv->last_scanned_channel < 0)
+- priv->last_scanned_channel = to_scan;
++ if (priv->scan_channel < 0)
++ priv->scan_channel = to_scan;
+ else
+- priv->last_scanned_channel += to_scan;
++ priv->scan_channel += to_scan;
+ cancel_delayed_work(&priv->scan_work);
+ queue_delayed_work(priv->work_thread, &priv->scan_work,
+- msecs_to_jiffies(300));
++ msecs_to_jiffies(300));
+ /* skip over GIWSCAN event */
+ goto out;
+ }
+@@ -648,13 +451,13 @@ int lbs_scan_networks(struct lbs_private *priv,
+ lbs_deb_scan("scan table:\n");
+ list_for_each_entry(iter, &priv->network_list, list)
+ lbs_deb_scan("%02d: BSSID %s, RSSI %d, SSID '%s'\n",
+- i++, print_mac(mac, iter->bssid), (s32) iter->rssi,
+- escape_essid(iter->ssid, iter->ssid_len));
++ i++, print_mac(mac, iter->bssid), iter->rssi,
++ escape_essid(iter->ssid, iter->ssid_len));
+ mutex_unlock(&priv->lock);
+ #endif
+
+ out2:
+- priv->last_scanned_channel = 0;
++ priv->scan_channel = 0;
+
+ out:
+ if (priv->connect_status == LBS_CONNECTED) {
+@@ -673,7 +476,15 @@ out:
+ return ret;
+ }
+
++void lbs_scan_worker(struct work_struct *work)
++{
++ struct lbs_private *priv =
++ container_of(work, struct lbs_private, scan_work.work);
+
++ lbs_deb_enter(LBS_DEB_SCAN);
++ lbs_scan_networks(priv, 0);
++ lbs_deb_leave(LBS_DEB_SCAN);
++}
+
+
+ /*********************************************************************/
+@@ -694,7 +505,7 @@ out:
+ * @return 0 or -1
+ */
+ static int lbs_process_bss(struct bss_descriptor *bss,
+- u8 ** pbeaconinfo, int *bytesleft)
++ uint8_t **pbeaconinfo, int *bytesleft)
+ {
+ struct ieeetypes_fhparamset *pFH;
+ struct ieeetypes_dsparamset *pDS;
+@@ -702,9 +513,9 @@ static int lbs_process_bss(struct bss_descriptor *bss,
+ struct ieeetypes_ibssparamset *pibss;
+ DECLARE_MAC_BUF(mac);
+ struct ieeetypes_countryinfoset *pcountryinfo;
+- u8 *pos, *end, *p;
+- u8 n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0;
+- u16 beaconsize = 0;
++ uint8_t *pos, *end, *p;
++ uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0;
++ uint16_t beaconsize = 0;
+ int ret;
+
+ lbs_deb_enter(LBS_DEB_SCAN);
+@@ -776,12 +587,11 @@ static int lbs_process_bss(struct bss_descriptor *bss,
+
+ /* process variable IE */
+ while (pos <= end - 2) {
+- struct ieee80211_info_element * elem =
+- (struct ieee80211_info_element *) pos;
++ struct ieee80211_info_element * elem = (void *)pos;
+
+ if (pos + elem->len > end) {
+ lbs_deb_scan("process_bss: error in processing IE, "
+- "bytes left < IE length\n");
++ "bytes left < IE length\n");
+ break;
+ }
+
+@@ -795,7 +605,7 @@ static int lbs_process_bss(struct bss_descriptor *bss,
+ break;
+
+ case MFIE_TYPE_RATES:
+- n_basic_rates = min_t(u8, MAX_RATES, elem->len);
++ n_basic_rates = min_t(uint8_t, MAX_RATES, elem->len);
+ memcpy(bss->rates, elem->data, n_basic_rates);
+ got_basic_rates = 1;
+ lbs_deb_scan("got RATES IE\n");
+@@ -836,19 +646,16 @@ static int lbs_process_bss(struct bss_descriptor *bss,
+ lbs_deb_scan("got COUNTRY IE\n");
+ if (pcountryinfo->len < sizeof(pcountryinfo->countrycode)
+ || pcountryinfo->len > 254) {
+- lbs_deb_scan("process_bss: 11D- Err "
+- "CountryInfo len %d, min %zd, max 254\n",
+- pcountryinfo->len,
+- sizeof(pcountryinfo->countrycode));
++ lbs_deb_scan("process_bss: 11D- Err CountryInfo len %d, min %zd, max 254\n",
++ pcountryinfo->len, sizeof(pcountryinfo->countrycode));
+ ret = -1;
+ goto done;
+ }
+
+- memcpy(&bss->countryinfo,
+- pcountryinfo, pcountryinfo->len + 2);
++ memcpy(&bss->countryinfo, pcountryinfo, pcountryinfo->len + 2);
+ lbs_deb_hex(LBS_DEB_SCAN, "process_bss: 11d countryinfo",
+- (u8 *) pcountryinfo,
+- (u32) (pcountryinfo->len + 2));
++ (uint8_t *) pcountryinfo,
++ (int) (pcountryinfo->len + 2));
+ break;
+
+ case MFIE_TYPE_RATES_EX:
+@@ -872,26 +679,19 @@ static int lbs_process_bss(struct bss_descriptor *bss,
+
+ case MFIE_TYPE_GENERIC:
+ if (elem->len >= 4 &&
+- elem->data[0] == 0x00 &&
+- elem->data[1] == 0x50 &&
+- elem->data[2] == 0xf2 &&
+- elem->data[3] == 0x01) {
+- bss->wpa_ie_len = min(elem->len + 2,
+- MAX_WPA_IE_LEN);
++ elem->data[0] == 0x00 && elem->data[1] == 0x50 &&
++ elem->data[2] == 0xf2 && elem->data[3] == 0x01) {
++ bss->wpa_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN);
+ memcpy(bss->wpa_ie, elem, bss->wpa_ie_len);
+ lbs_deb_scan("got WPA IE\n");
+- lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie,
+- elem->len);
++ lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie, elem->len);
+ } else if (elem->len >= MARVELL_MESH_IE_LENGTH &&
+- elem->data[0] == 0x00 &&
+- elem->data[1] == 0x50 &&
+- elem->data[2] == 0x43 &&
+- elem->data[3] == 0x04) {
++ elem->data[0] == 0x00 && elem->data[1] == 0x50 &&
++ elem->data[2] == 0x43 && elem->data[3] == 0x04) {
+ lbs_deb_scan("got mesh IE\n");
+ bss->mesh = 1;
+ } else {
+- lbs_deb_scan("got generiec IE: "
+- "%02x:%02x:%02x:%02x, len %d\n",
++ lbs_deb_scan("got generic IE: %02x:%02x:%02x:%02x, len %d\n",
+ elem->data[0], elem->data[1],
+ elem->data[2], elem->data[3],
+ elem->len);
+@@ -903,12 +703,12 @@ static int lbs_process_bss(struct bss_descriptor *bss,
+ bss->rsn_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN);
+ memcpy(bss->rsn_ie, elem, bss->rsn_ie_len);
+ lbs_deb_hex(LBS_DEB_SCAN, "process_bss: RSN_IE",
+- bss->rsn_ie, elem->len);
++ bss->rsn_ie, elem->len);
+ break;
+
+ default:
+ lbs_deb_scan("got IE 0x%04x, len %d\n",
+- elem->id, elem->len);
++ elem->id, elem->len);
+ break;
+ }
+
+@@ -927,213 +727,6 @@ done:
+ }
+
+ /**
+- * @brief This function finds a specific compatible BSSID in the scan list
+- *
+- * Used in association code
+- *
+- * @param priv A pointer to struct lbs_private
+- * @param bssid BSSID to find in the scan list
+- * @param mode Network mode: Infrastructure or IBSS
+- *
+- * @return index in BSSID list, or error return code (< 0)
+- */
+-struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv,
+- u8 * bssid, u8 mode)
+-{
+- struct bss_descriptor * iter_bss;
+- struct bss_descriptor * found_bss = NULL;
+-
+- lbs_deb_enter(LBS_DEB_SCAN);
+-
+- if (!bssid)
+- goto out;
+-
+- lbs_deb_hex(LBS_DEB_SCAN, "looking for",
+- bssid, ETH_ALEN);
+-
+- /* Look through the scan table for a compatible match. The loop will
+- * continue past a matched bssid that is not compatible in case there
+- * is an AP with multiple SSIDs assigned to the same BSSID
+- */
+- mutex_lock(&priv->lock);
+- list_for_each_entry (iter_bss, &priv->network_list, list) {
+- if (compare_ether_addr(iter_bss->bssid, bssid))
+- continue; /* bssid doesn't match */
+- switch (mode) {
+- case IW_MODE_INFRA:
+- case IW_MODE_ADHOC:
+- if (!is_network_compatible(priv, iter_bss, mode))
+- break;
+- found_bss = iter_bss;
+- break;
+- default:
+- found_bss = iter_bss;
+- break;
+- }
+- }
+- mutex_unlock(&priv->lock);
+-
+-out:
+- lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
+- return found_bss;
+-}
+-
+-/**
+- * @brief This function finds ssid in ssid list.
+- *
+- * Used in association code
+- *
+- * @param priv A pointer to struct lbs_private
+- * @param ssid SSID to find in the list
+- * @param bssid BSSID to qualify the SSID selection (if provided)
+- * @param mode Network mode: Infrastructure or IBSS
+- *
+- * @return index in BSSID list
+- */
+-struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv,
+- u8 *ssid, u8 ssid_len, u8 * bssid, u8 mode,
+- int channel)
+-{
+- u8 bestrssi = 0;
+- struct bss_descriptor * iter_bss = NULL;
+- struct bss_descriptor * found_bss = NULL;
+- struct bss_descriptor * tmp_oldest = NULL;
+-
+- lbs_deb_enter(LBS_DEB_SCAN);
+-
+- mutex_lock(&priv->lock);
+-
+- list_for_each_entry (iter_bss, &priv->network_list, list) {
+- if ( !tmp_oldest
+- || (iter_bss->last_scanned < tmp_oldest->last_scanned))
+- tmp_oldest = iter_bss;
+-
+- if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len,
+- ssid, ssid_len) != 0)
+- continue; /* ssid doesn't match */
+- if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0)
+- continue; /* bssid doesn't match */
+- if ((channel > 0) && (iter_bss->channel != channel))
+- continue; /* channel doesn't match */
+-
+- switch (mode) {
+- case IW_MODE_INFRA:
+- case IW_MODE_ADHOC:
+- if (!is_network_compatible(priv, iter_bss, mode))
+- break;
+-
+- if (bssid) {
+- /* Found requested BSSID */
+- found_bss = iter_bss;
+- goto out;
+- }
+-
+- if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
+- bestrssi = SCAN_RSSI(iter_bss->rssi);
+- found_bss = iter_bss;
+- }
+- break;
+- case IW_MODE_AUTO:
+- default:
+- if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
+- bestrssi = SCAN_RSSI(iter_bss->rssi);
+- found_bss = iter_bss;
+- }
+- break;
+- }
+- }
+-
+-out:
+- mutex_unlock(&priv->lock);
+- lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
+- return found_bss;
+-}
+-
+-/**
+- * @brief This function finds the best SSID in the Scan List
+- *
+- * Search the scan table for the best SSID that also matches the current
+- * adapter network preference (infrastructure or adhoc)
+- *
+- * @param priv A pointer to struct lbs_private
+- *
+- * @return index in BSSID list
+- */
+-static struct bss_descriptor *lbs_find_best_ssid_in_list(
+- struct lbs_private *priv,
+- u8 mode)
+-{
+- u8 bestrssi = 0;
+- struct bss_descriptor * iter_bss;
+- struct bss_descriptor * best_bss = NULL;
+-
+- lbs_deb_enter(LBS_DEB_SCAN);
+-
+- mutex_lock(&priv->lock);
+-
+- list_for_each_entry (iter_bss, &priv->network_list, list) {
+- switch (mode) {
+- case IW_MODE_INFRA:
+- case IW_MODE_ADHOC:
+- if (!is_network_compatible(priv, iter_bss, mode))
+- break;
+- if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
+- break;
+- bestrssi = SCAN_RSSI(iter_bss->rssi);
+- best_bss = iter_bss;
+- break;
+- case IW_MODE_AUTO:
+- default:
+- if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
+- break;
+- bestrssi = SCAN_RSSI(iter_bss->rssi);
+- best_bss = iter_bss;
+- break;
+- }
+- }
+-
+- mutex_unlock(&priv->lock);
+- lbs_deb_leave_args(LBS_DEB_SCAN, "best_bss %p", best_bss);
+- return best_bss;
+-}
+-
+-/**
+- * @brief Find the AP with specific ssid in the scan list
+- *
+- * Used from association worker.
+- *
+- * @param priv A pointer to struct lbs_private structure
+- * @param pSSID A pointer to AP's ssid
+- *
+- * @return 0--success, otherwise--fail
+- */
+-int lbs_find_best_network_ssid(struct lbs_private *priv,
+- u8 *out_ssid, u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode)
+-{
+- int ret = -1;
+- struct bss_descriptor * found;
+-
+- lbs_deb_enter(LBS_DEB_SCAN);
+-
+- lbs_scan_networks(priv, NULL, 1);
+- if (priv->surpriseremoved)
+- goto out;
+-
+- found = lbs_find_best_ssid_in_list(priv, preferred_mode);
+- if (found && (found->ssid_len > 0)) {
+- memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE);
+- *out_ssid_len = found->ssid_len;
+- *out_mode = found->mode;
+- ret = 0;
+- }
+-
+-out:
+- lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
+- return ret;
+-}
+-
+-
+-/**
+ * @brief Send a scan command for all available channels filtered on a spec
+ *
+ * Used in association code and from debugfs
+@@ -1141,29 +734,24 @@ out:
+ * @param priv A pointer to struct lbs_private structure
+ * @param ssid A pointer to the SSID to scan for
+ * @param ssid_len Length of the SSID
+- * @param clear_ssid Should existing scan results with this SSID
+- * be cleared?
+ *
+ * @return 0-success, otherwise fail
+ */
+-int lbs_send_specific_ssid_scan(struct lbs_private *priv,
+- u8 *ssid, u8 ssid_len, u8 clear_ssid)
++int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid,
++ uint8_t ssid_len)
+ {
+- struct lbs_ioctl_user_scan_cfg scancfg;
+ int ret = 0;
+
+- lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s', clear %d",
+- escape_essid(ssid, ssid_len), clear_ssid);
++ lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s'\n",
++ escape_essid(ssid, ssid_len));
+
+ if (!ssid_len)
+ goto out;
+
+- memset(&scancfg, 0x00, sizeof(scancfg));
+- memcpy(scancfg.ssid, ssid, ssid_len);
+- scancfg.ssid_len = ssid_len;
+- scancfg.clear_ssid = clear_ssid;
++ memcpy(priv->scan_ssid, ssid, ssid_len);
++ priv->scan_ssid_len = ssid_len;
+
+- lbs_scan_networks(priv, &scancfg, 1);
++ lbs_scan_networks(priv, 1);
+ if (priv->surpriseremoved) {
+ ret = -1;
+ goto out;
+@@ -1187,17 +775,17 @@ out:
+ #define MAX_CUSTOM_LEN 64
+
+ static inline char *lbs_translate_scan(struct lbs_private *priv,
+- char *start, char *stop,
+- struct bss_descriptor *bss)
++ char *start, char *stop,
++ struct bss_descriptor *bss)
+ {
+ struct chan_freq_power *cfp;
+ char *current_val; /* For rates */
+ struct iw_event iwe; /* Temporary buffer */
+ int j;
+-#define PERFECT_RSSI ((u8)50)
+-#define WORST_RSSI ((u8)0)
+-#define RSSI_DIFF ((u8)(PERFECT_RSSI - WORST_RSSI))
+- u8 rssi;
++#define PERFECT_RSSI ((uint8_t)50)
++#define WORST_RSSI ((uint8_t)0)
++#define RSSI_DIFF ((uint8_t)(PERFECT_RSSI - WORST_RSSI))
++ uint8_t rssi;
+
+ lbs_deb_enter(LBS_DEB_SCAN);
+
+@@ -1217,7 +805,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv,
+ /* SSID */
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.flags = 1;
+- iwe.u.data.length = min((u32) bss->ssid_len, (u32) IW_ESSID_MAX_SIZE);
++ iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IW_ESSID_MAX_SIZE);
+ start = iwe_stream_add_point(start, stop, &iwe, bss->ssid);
+
+ /* Mode */
+@@ -1238,28 +826,26 @@ static inline char *lbs_translate_scan(struct lbs_private *priv,
+
+ rssi = iwe.u.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE;
+ iwe.u.qual.qual =
+- (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) *
+- (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) /
+- (RSSI_DIFF * RSSI_DIFF);
++ (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) *
++ (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) /
++ (RSSI_DIFF * RSSI_DIFF);
+ if (iwe.u.qual.qual > 100)
+ iwe.u.qual.qual = 100;
+
+ if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
+ iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
+ } else {
+- iwe.u.qual.noise =
+- CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]);
++ iwe.u.qual.noise = CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]);
+ }
+
+ /* Locally created ad-hoc BSSs won't have beacons if this is the
+ * only station in the adhoc network; so get signal strength
+ * from receive statistics.
+ */
+- if ((priv->mode == IW_MODE_ADHOC)
+- && priv->adhoccreate
++ if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate
+ && !lbs_ssid_cmp(priv->curbssparams.ssid,
+- priv->curbssparams.ssid_len,
+- bss->ssid, bss->ssid_len)) {
++ priv->curbssparams.ssid_len,
++ bss->ssid, bss->ssid_len)) {
+ int snr, nf;
+ snr = priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
+ nf = priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
+@@ -1290,14 +876,13 @@ static inline char *lbs_translate_scan(struct lbs_private *priv,
+ current_val = iwe_stream_add_value(start, current_val,
+ stop, &iwe, IW_EV_PARAM_LEN);
+ }
+- if ((bss->mode == IW_MODE_ADHOC)
++ if ((bss->mode == IW_MODE_ADHOC) && priv->adhoccreate
+ && !lbs_ssid_cmp(priv->curbssparams.ssid,
+- priv->curbssparams.ssid_len,
+- bss->ssid, bss->ssid_len)
+- && priv->adhoccreate) {
++ priv->curbssparams.ssid_len,
++ bss->ssid, bss->ssid_len)) {
+ iwe.u.bitrate.value = 22 * 500000;
+ current_val = iwe_stream_add_value(start, current_val,
+- stop, &iwe, IW_EV_PARAM_LEN);
++ stop, &iwe, IW_EV_PARAM_LEN);
+ }
+ /* Check if we added any event */
+ if((current_val - start) > IW_EV_LCP_LEN)
+@@ -1326,8 +911,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv,
+ char *p = custom;
+
+ iwe.cmd = IWEVCUSTOM;
+- p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
+- "mesh-type: olpc");
++ p += snprintf(p, MAX_CUSTOM_LEN, "mesh-type: olpc");
+ iwe.u.data.length = p - custom;
+ if (iwe.u.data.length)
+ start = iwe_stream_add_point(start, stop, &iwe, custom);
+@@ -1350,39 +934,49 @@ out:
+ * @return 0 --success, otherwise fail
+ */
+ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
+- struct iw_param *wrqu, char *extra)
++ union iwreq_data *wrqu, char *extra)
+ {
+ struct lbs_private *priv = dev->priv;
++ int ret = 0;
+
+- lbs_deb_enter(LBS_DEB_SCAN);
++ lbs_deb_enter(LBS_DEB_WEXT);
+
+- if (!netif_running(dev))
+- return -ENETDOWN;
++ if (!netif_running(dev)) {
++ ret = -ENETDOWN;
++ goto out;
++ }
+
+ /* mac80211 does this:
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- if (sdata->type != IEEE80211_IF_TYPE_xxx)
+- return -EOPNOTSUPP;
++ if (sdata->type != IEEE80211_IF_TYPE_xxx) {
++ ret = -EOPNOTSUPP;
++ goto out;
++ }
++ */
+
+ if (wrqu->data.length == sizeof(struct iw_scan_req) &&
+ wrqu->data.flags & IW_SCAN_THIS_ESSID) {
+- req = (struct iw_scan_req *)extra;
+- ssid = req->essid;
+- ssid_len = req->essid_len;
++ struct iw_scan_req *req = (struct iw_scan_req *)extra;
++ priv->scan_ssid_len = req->essid_len;
++ memcpy(priv->scan_ssid, req->essid, priv->scan_ssid_len);
++ lbs_deb_wext("set_scan, essid '%s'\n",
++ escape_essid(priv->scan_ssid, priv->scan_ssid_len));
++ } else {
++ priv->scan_ssid_len = 0;
+ }
+- */
+
+ if (!delayed_work_pending(&priv->scan_work))
+ queue_delayed_work(priv->work_thread, &priv->scan_work,
+- msecs_to_jiffies(50));
++ msecs_to_jiffies(50));
+ /* set marker that currently a scan is taking place */
+- priv->last_scanned_channel = -1;
++ priv->scan_channel = -1;
+
+ if (priv->surpriseremoved)
+- return -EIO;
++ ret = -EIO;
+
+- lbs_deb_leave(LBS_DEB_SCAN);
+- return 0;
++out:
++ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
++ return ret;
+ }
+
+
+@@ -1397,31 +991,30 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
+ * @return 0 --success, otherwise fail
+ */
+ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
+- struct iw_point *dwrq, char *extra)
++ struct iw_point *dwrq, char *extra)
+ {
+ #define SCAN_ITEM_SIZE 128
+ struct lbs_private *priv = dev->priv;
+ int err = 0;
+ char *ev = extra;
+ char *stop = ev + dwrq->length;
+- struct bss_descriptor * iter_bss;
+- struct bss_descriptor * safe;
++ struct bss_descriptor *iter_bss;
++ struct bss_descriptor *safe;
+
+- lbs_deb_enter(LBS_DEB_SCAN);
++ lbs_deb_enter(LBS_DEB_WEXT);
+
+ /* iwlist should wait until the current scan is finished */
+- if (priv->last_scanned_channel)
++ if (priv->scan_channel)
+ return -EAGAIN;
+
+ /* Update RSSI if current BSS is a locally created ad-hoc BSS */
+- if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) {
++ if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate)
+ lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
+- CMD_OPTION_WAITFORRSP, 0, NULL);
+- }
++ CMD_OPTION_WAITFORRSP, 0, NULL);
+
+ mutex_lock(&priv->lock);
+ list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) {
+- char * next_ev;
++ char *next_ev;
+ unsigned long stale_time;
+
+ if (stop - ev < SCAN_ITEM_SIZE) {
+@@ -1436,8 +1029,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
+ /* Prune old an old scan result */
+ stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE;
+ if (time_after(jiffies, stale_time)) {
+- list_move_tail (&iter_bss->list,
+- &priv->network_free_list);
++ list_move_tail(&iter_bss->list, &priv->network_free_list);
+ clear_bss_descriptor(iter_bss);
+ continue;
+ }
+@@ -1453,7 +1045,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
+ dwrq->length = (ev - extra);
+ dwrq->flags = 0;
+
+- lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", err);
++ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err);
+ return err;
+ }
+
+@@ -1468,44 +1060,6 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
+
+
+ /**
+- * @brief Prepare a scan command to be sent to the firmware
+- *
+- * Called via lbs_prepare_and_send_command(priv, CMD_802_11_SCAN, ...)
+- * from cmd.c
+- *
+- * Sends a fixed length data part (specifying the BSS type and BSSID filters)
+- * as well as a variable number/length of TLVs to the firmware.
+- *
+- * @param priv A pointer to struct lbs_private structure
+- * @param cmd A pointer to cmd_ds_command structure to be sent to
+- * firmware with the cmd_DS_801_11_SCAN structure
+- * @param pdata_buf Void pointer cast of a lbs_scan_cmd_config struct used
+- * to set the fields/TLVs for the command sent to firmware
+- *
+- * @return 0 or -1
+- */
+-int lbs_cmd_80211_scan(struct lbs_private *priv,
+- struct cmd_ds_command *cmd, void *pdata_buf)
+-{
+- struct cmd_ds_802_11_scan *pscan = &cmd->params.scan;
+- struct lbs_scan_cmd_config *pscancfg = pdata_buf;
+-
+- lbs_deb_enter(LBS_DEB_SCAN);
+-
+- /* Set fixed field variables in scan command */
+- pscan->bsstype = pscancfg->bsstype;
+- memcpy(pscan->bssid, pscancfg->bssid, ETH_ALEN);
+- memcpy(pscan->tlvbuffer, pscancfg->tlvbuffer, pscancfg->tlvbufferlen);
+-
+- /* size is equal to the sizeof(fixed portions) + the TLV len + header */
+- cmd->size = cpu_to_le16(sizeof(pscan->bsstype) + ETH_ALEN
+- + pscancfg->tlvbufferlen + S_DS_GEN);
+-
+- lbs_deb_leave(LBS_DEB_SCAN);
+- return 0;
+-}
+-
+-/**
+ * @brief This function handles the command response of scan
+ *
+ * Called from handle_cmd_response() in cmdrespc.
+@@ -1531,13 +1085,14 @@ int lbs_cmd_80211_scan(struct lbs_private *priv,
+ *
+ * @return 0 or -1
+ */
+-int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp)
++static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
++ struct cmd_header *resp)
+ {
+- struct cmd_ds_802_11_scan_rsp *pscan;
+- struct bss_descriptor * iter_bss;
+- struct bss_descriptor * safe;
+- u8 *pbssinfo;
+- u16 scanrespsize;
++ struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp;
++ struct bss_descriptor *iter_bss;
++ struct bss_descriptor *safe;
++ uint8_t *bssinfo;
++ uint16_t scanrespsize;
+ int bytesleft;
+ int idx;
+ int tlvbufsize;
+@@ -1554,48 +1109,45 @@ int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp)
+ clear_bss_descriptor(iter_bss);
+ }
+
+- pscan = &resp->params.scanresp;
+-
+- if (pscan->nr_sets > MAX_NETWORK_COUNT) {
+- lbs_deb_scan(
+- "SCAN_RESP: too many scan results (%d, max %d)!!\n",
+- pscan->nr_sets, MAX_NETWORK_COUNT);
++ if (scanresp->nr_sets > MAX_NETWORK_COUNT) {
++ lbs_deb_scan("SCAN_RESP: too many scan results (%d, max %d)\n",
++ scanresp->nr_sets, MAX_NETWORK_COUNT);
+ ret = -1;
+ goto done;
+ }
+
+- bytesleft = le16_to_cpu(pscan->bssdescriptsize);
++ bytesleft = le16_to_cpu(scanresp->bssdescriptsize);
+ lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft);
+
+ scanrespsize = le16_to_cpu(resp->size);
+- lbs_deb_scan("SCAN_RESP: scan results %d\n", pscan->nr_sets);
++ lbs_deb_scan("SCAN_RESP: scan results %d\n", scanresp->nr_sets);
+
+- pbssinfo = pscan->bssdesc_and_tlvbuffer;
++ bssinfo = scanresp->bssdesc_and_tlvbuffer;
+
+ /* The size of the TLV buffer is equal to the entire command response
+ * size (scanrespsize) minus the fixed fields (sizeof()'s), the
+ * BSS Descriptions (bssdescriptsize as bytesLef) and the command
+ * response header (S_DS_GEN)
+ */
+- tlvbufsize = scanrespsize - (bytesleft + sizeof(pscan->bssdescriptsize)
+- + sizeof(pscan->nr_sets)
++ tlvbufsize = scanrespsize - (bytesleft + sizeof(scanresp->bssdescriptsize)
++ + sizeof(scanresp->nr_sets)
+ + S_DS_GEN);
+
+ /*
+- * Process each scan response returned (pscan->nr_sets). Save
++ * Process each scan response returned (scanresp->nr_sets). Save
+ * the information in the newbssentry and then insert into the
+ * driver scan table either as an update to an existing entry
+ * or as an addition at the end of the table
+ */
+- for (idx = 0; idx < pscan->nr_sets && bytesleft; idx++) {
++ for (idx = 0; idx < scanresp->nr_sets && bytesleft; idx++) {
+ struct bss_descriptor new;
+- struct bss_descriptor * found = NULL;
+- struct bss_descriptor * oldest = NULL;
++ struct bss_descriptor *found = NULL;
++ struct bss_descriptor *oldest = NULL;
+ DECLARE_MAC_BUF(mac);
+
+ /* Process the data fields and IEs returned for this BSS */
+ memset(&new, 0, sizeof (struct bss_descriptor));
+- if (lbs_process_bss(&new, &pbssinfo, &bytesleft) != 0) {
++ if (lbs_process_bss(&new, &bssinfo, &bytesleft) != 0) {
+ /* error parsing the scan response, skipped */
+ lbs_deb_scan("SCAN_RESP: process_bss returned ERROR\n");
+ continue;
+@@ -1630,8 +1182,7 @@ int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp)
+ continue;
+ }
+
+- lbs_deb_scan("SCAN_RESP: BSSID %s\n",
+- print_mac(mac, new.bssid));
++ lbs_deb_scan("SCAN_RESP: BSSID %s\n", print_mac(mac, new.bssid));
+
+ /* Copy the locally created newbssentry to the scan table */
+ memcpy(found, &new, offsetof(struct bss_descriptor, list));
+diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h
+index 319f70d..9e07b04 100644
+--- a/drivers/net/wireless/libertas/scan.h
++++ b/drivers/net/wireless/libertas/scan.h
+@@ -7,198 +7,22 @@
+ #ifndef _LBS_SCAN_H
+ #define _LBS_SCAN_H
+
+-#include <net/ieee80211.h>
+-#include "hostcmd.h"
+-
+ /**
+ * @brief Maximum number of channels that can be sent in a setuserscan ioctl
+- *
+- * @sa lbs_ioctl_user_scan_cfg
+ */
+ #define LBS_IOCTL_USER_SCAN_CHAN_MAX 50
+
+-//! Infrastructure BSS scan type in lbs_scan_cmd_config
+-#define LBS_SCAN_BSS_TYPE_BSS 1
+-
+-//! Adhoc BSS scan type in lbs_scan_cmd_config
+-#define LBS_SCAN_BSS_TYPE_IBSS 2
+-
+-//! Adhoc or Infrastructure BSS scan type in lbs_scan_cmd_config, no filter
+-#define LBS_SCAN_BSS_TYPE_ANY 3
+-
+-/**
+- * @brief Structure used internally in the wlan driver to configure a scan.
+- *
+- * Sent to the command processing module to configure the firmware
+- * scan command prepared by lbs_cmd_80211_scan.
+- *
+- * @sa lbs_scan_networks
+- *
+- */
+-struct lbs_scan_cmd_config {
+- /**
+- * @brief BSS type to be sent in the firmware command
+- *
+- * Field can be used to restrict the types of networks returned in the
+- * scan. valid settings are:
+- *
+- * - LBS_SCAN_BSS_TYPE_BSS (infrastructure)
+- * - LBS_SCAN_BSS_TYPE_IBSS (adhoc)
+- * - LBS_SCAN_BSS_TYPE_ANY (unrestricted, adhoc and infrastructure)
+- */
+- u8 bsstype;
+-
+- /**
+- * @brief Specific BSSID used to filter scan results in the firmware
+- */
+- u8 bssid[ETH_ALEN];
+-
+- /**
+- * @brief length of TLVs sent in command starting at tlvBuffer
+- */
+- int tlvbufferlen;
+-
+- /**
+- * @brief SSID TLV(s) and ChanList TLVs to be sent in the firmware command
+- *
+- * @sa TLV_TYPE_CHANLIST, mrvlietypes_chanlistparamset_t
+- * @sa TLV_TYPE_SSID, mrvlietypes_ssidparamset_t
+- */
+- u8 tlvbuffer[1]; //!< SSID TLV(s) and ChanList TLVs are stored here
+-};
+-
+-/**
+- * @brief IOCTL channel sub-structure sent in lbs_ioctl_user_scan_cfg
+- *
+- * Multiple instances of this structure are included in the IOCTL command
+- * to configure a instance of a scan on the specific channel.
+- */
+-struct lbs_ioctl_user_scan_chan {
+- u8 channumber; //!< channel Number to scan
+- u8 radiotype; //!< Radio type: 'B/G' band = 0, 'A' band = 1
+- u8 scantype; //!< Scan type: Active = 0, Passive = 1
+- u16 scantime; //!< Scan duration in milliseconds; if 0 default used
+-};
+-
+-/**
+- * @brief IOCTL input structure to configure an immediate scan cmd to firmware
+- *
+- * Used in the setuserscan (LBS_SET_USER_SCAN) private ioctl. Specifies
+- * a number of parameters to be used in general for the scan as well
+- * as a channel list (lbs_ioctl_user_scan_chan) for each scan period
+- * desired.
+- *
+- * @sa lbs_set_user_scan_ioctl
+- */
+-struct lbs_ioctl_user_scan_cfg {
+- /**
+- * @brief BSS type to be sent in the firmware command
+- *
+- * Field can be used to restrict the types of networks returned in the
+- * scan. valid settings are:
+- *
+- * - LBS_SCAN_BSS_TYPE_BSS (infrastructure)
+- * - LBS_SCAN_BSS_TYPE_IBSS (adhoc)
+- * - LBS_SCAN_BSS_TYPE_ANY (unrestricted, adhoc and infrastructure)
+- */
+- u8 bsstype;
+-
+- /**
+- * @brief BSSID filter sent in the firmware command to limit the results
+- */
+- u8 bssid[ETH_ALEN];
+-
+- /* Clear existing scan results matching this BSSID */
+- u8 clear_bssid;
+-
+- /**
+- * @brief SSID filter sent in the firmware command to limit the results
+- */
+- char ssid[IW_ESSID_MAX_SIZE];
+- u8 ssid_len;
+-
+- /* Clear existing scan results matching this SSID */
+- u8 clear_ssid;
+-};
+-
+-/**
+- * @brief Structure used to store information for each beacon/probe response
+- */
+-struct bss_descriptor {
+- u8 bssid[ETH_ALEN];
+-
+- u8 ssid[IW_ESSID_MAX_SIZE + 1];
+- u8 ssid_len;
+-
+- u16 capability;
+-
+- /* receive signal strength in dBm */
+- long rssi;
+-
+- u32 channel;
+-
+- u16 beaconperiod;
+-
+- u32 atimwindow;
+-
+- /* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */
+- u8 mode;
+-
+- /* zero-terminated array of supported data rates */
+- u8 rates[MAX_RATES + 1];
+-
+- unsigned long last_scanned;
+-
+- union ieeetypes_phyparamset phyparamset;
+- union IEEEtypes_ssparamset ssparamset;
+-
+- struct ieeetypes_countryinfofullset countryinfo;
+-
+- u8 wpa_ie[MAX_WPA_IE_LEN];
+- size_t wpa_ie_len;
+- u8 rsn_ie[MAX_WPA_IE_LEN];
+- size_t rsn_ie_len;
+-
+- u8 mesh;
+-
+- struct list_head list;
+-};
+-
+ int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len);
+
+-struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv,
+- u8 *ssid, u8 ssid_len, u8 *bssid, u8 mode,
+- int channel);
+-
+-struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv,
+- u8 *bssid, u8 mode);
+-
+-int lbs_find_best_network_ssid(struct lbs_private *priv, u8 *out_ssid,
+- u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode);
+-
+ int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid,
+- u8 ssid_len, u8 clear_ssid);
++ u8 ssid_len);
+
+-int lbs_cmd_80211_scan(struct lbs_private *priv,
+- struct cmd_ds_command *cmd,
+- void *pdata_buf);
+-
+-int lbs_ret_80211_scan(struct lbs_private *priv,
+- struct cmd_ds_command *resp);
+-
+-int lbs_scan_networks(struct lbs_private *priv,
+- const struct lbs_ioctl_user_scan_cfg *puserscanin,
+- int full_scan);
+-
+-struct ifreq;
+-
+-struct iw_point;
+-struct iw_param;
+-struct iw_request_info;
+ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *dwrq, char *extra);
+ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
+- struct iw_param *vwrq, char *extra);
++ union iwreq_data *wrqu, char *extra);
++
++int lbs_scan_networks(struct lbs_private *priv, int full_scan);
+
+ void lbs_scan_worker(struct work_struct *work);
+
+diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
+index 00d95f7..a4972fe 100644
+--- a/drivers/net/wireless/libertas/tx.c
++++ b/drivers/net/wireless/libertas/tx.c
+@@ -151,7 +151,7 @@ int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+
+ dev->trans_start = jiffies;
+
+- if (priv->monitormode != LBS_MONITOR_OFF) {
++ if (priv->monitormode) {
+ /* Keep the skb to echo it back once Tx feedback is
+ received from FW */
+ skb_orphan(skb);
+@@ -179,32 +179,17 @@ int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ *
+ * @returns void
+ */
+-void lbs_send_tx_feedback(struct lbs_private *priv)
++void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count)
+ {
+ struct tx_radiotap_hdr *radiotap_hdr;
+- u32 status = priv->eventcause;
+- int txfail;
+- int try_count;
+
+- if (priv->monitormode == LBS_MONITOR_OFF ||
+- priv->currenttxskb == NULL)
++ if (!priv->monitormode || priv->currenttxskb == NULL)
+ return;
+
+ radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data;
+
+- txfail = (status >> 24);
+-
+-#if 0
+- /* The version of roofnet that we've tested does not use this yet
+- * But it may be used in the future.
+- */
+- if (txfail)
+- radiotap_hdr->flags &= IEEE80211_RADIOTAP_F_TX_FAIL;
+-#endif
+- try_count = (status >> 16) & 0xff;
+- radiotap_hdr->data_retries = (try_count) ?
+- (1 + priv->txretrycount - try_count) : 0;
+-
++ radiotap_hdr->data_retries = try_count ?
++ (1 + priv->txretrycount - try_count) : 0;
+
+ priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb,
+ priv->rtap_net_dev);
+diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h
+index f0d5795..4031be4 100644
+--- a/drivers/net/wireless/libertas/types.h
++++ b/drivers/net/wireless/libertas/types.h
+@@ -239,4 +239,17 @@ struct mrvlietypes_ledgpio {
+ struct led_pin ledpin[1];
+ } __attribute__ ((packed));
+
++struct led_bhv {
++ uint8_t firmwarestate;
++ uint8_t led;
++ uint8_t ledstate;
++ uint8_t ledarg;
++} __attribute__ ((packed));
++
++
++struct mrvlietypes_ledbhv {
++ struct mrvlietypesheader header;
++ struct led_bhv ledbhv[1];
++} __attribute__ ((packed));
++
+ #endif
+diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
+index e8bfc26..0973d01 100644
+--- a/drivers/net/wireless/libertas/wext.c
++++ b/drivers/net/wireless/libertas/wext.c
+@@ -16,8 +16,8 @@
+ #include "decl.h"
+ #include "defs.h"
+ #include "dev.h"
+-#include "join.h"
+ #include "wext.h"
++#include "scan.h"
+ #include "assoc.h"
+ #include "cmd.h"
+
+@@ -579,6 +579,9 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
+ range->num_bitrates);
+
+ range->num_frequency = 0;
++
++ range->scan_capa = IW_SCAN_CAPA_ESSID;
++
+ if (priv->enable11d &&
+ (priv->connect_status == LBS_CONNECTED ||
+ priv->mesh_connect_status == LBS_CONNECTED)) {
+@@ -602,7 +605,7 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
+ lbs_deb_wext("chan_no %d\n", chan_no);
+ range->freq[range->num_frequency].i = (long)chan_no;
+ range->freq[range->num_frequency].m =
+- (long)lbs_chan_2_freq(chan_no, band) * 100000;
++ (long)lbs_chan_2_freq(chan_no) * 100000;
+ range->freq[range->num_frequency].e = 1;
+ range->num_frequency++;
+ }
+@@ -653,13 +656,10 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
+ range->num_encoding_sizes = 2;
+ range->max_encoding_tokens = 4;
+
+- range->min_pmp = 1000000;
+- range->max_pmp = 120000000;
+- range->min_pmt = 1000;
+- range->max_pmt = 1000000;
+- range->pmp_flags = IW_POWER_PERIOD;
+- range->pmt_flags = IW_POWER_TIMEOUT;
+- range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
++ /*
++ * Right now we support only "iwconfig ethX power on|off"
++ */
++ range->pm_capa = IW_POWER_ON;
+
+ /*
+ * Minimum version we recommend
+@@ -781,21 +781,14 @@ static int lbs_get_power(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *vwrq, char *extra)
+ {
+ struct lbs_private *priv = dev->priv;
+- int mode;
+
+ lbs_deb_enter(LBS_DEB_WEXT);
+
+- mode = priv->psmode;
+-
+- if ((vwrq->disabled = (mode == LBS802_11POWERMODECAM))
+- || priv->connect_status == LBS_DISCONNECTED)
+- {
+- goto out;
+- }
+-
+ vwrq->value = 0;
++ vwrq->flags = 0;
++ vwrq->disabled = priv->psmode == LBS802_11POWERMODECAM
++ || priv->connect_status == LBS_DISCONNECTED;
+
+-out:
+ lbs_deb_leave(LBS_DEB_WEXT);
+ return 0;
+ }
+@@ -817,6 +810,7 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
+ int stats_valid = 0;
+ u8 rssi;
+ u32 tx_retries;
++ struct cmd_ds_802_11_get_log log;
+
+ lbs_deb_enter(LBS_DEB_WEXT);
+
+@@ -860,7 +854,11 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
+ /* Quality by TX errors */
+ priv->wstats.discard.retries = priv->stats.tx_errors;
+
+- tx_retries = le32_to_cpu(priv->logmsg.retry);
++ memset(&log, 0, sizeof(log));
++ log.hdr.size = cpu_to_le16(sizeof(log));
++ lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log);
++
++ tx_retries = le32_to_cpu(log.retry);
+
+ if (tx_retries > 75)
+ tx_qual = (90 - tx_retries) * POOR / 15;
+@@ -876,10 +874,9 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
+ (PERFECT - VERY_GOOD) / 50 + VERY_GOOD;
+ quality = min(quality, tx_qual);
+
+- priv->wstats.discard.code = le32_to_cpu(priv->logmsg.wepundecryptable);
+- priv->wstats.discard.fragment = le32_to_cpu(priv->logmsg.rxfrag);
++ priv->wstats.discard.code = le32_to_cpu(log.wepundecryptable);
+ priv->wstats.discard.retries = tx_retries;
+- priv->wstats.discard.misc = le32_to_cpu(priv->logmsg.ackfailure);
++ priv->wstats.discard.misc = le32_to_cpu(log.ackfailure);
+
+ /* Calculate quality */
+ priv->wstats.qual.qual = min_t(u8, quality, 100);
+@@ -889,8 +886,6 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
+ /* update stats asynchronously for future calls */
+ lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
+ 0, 0, NULL);
+- lbs_prepare_and_send_command(priv, CMD_802_11_GET_LOG, 0,
+- 0, 0, NULL);
+ out:
+ if (!stats_valid) {
+ priv->wstats.miss.beacon = 0;
+@@ -2065,23 +2060,6 @@ static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info,
+ return ret;
+ }
+
+-void lbs_get_fwversion(struct lbs_private *priv, char *fwversion, int maxlen)
+-{
+- char fwver[32];
+-
+- mutex_lock(&priv->lock);
+-
+- sprintf(fwver, "%u.%u.%u.p%u",
+- priv->fwrelease >> 24 & 0xff,
+- priv->fwrelease >> 16 & 0xff,
+- priv->fwrelease >> 8 & 0xff,
+- priv->fwrelease & 0xff);
+-
+- mutex_unlock(&priv->lock);
+- snprintf(fwversion, maxlen, fwver);
+-}
+-
+-
+ /*
+ * iwconfig settable callbacks
+ */
+diff --git a/drivers/net/wireless/libertas/wext.h b/drivers/net/wireless/libertas/wext.h
+index a563d9a..4c08db4 100644
+--- a/drivers/net/wireless/libertas/wext.h
++++ b/drivers/net/wireless/libertas/wext.h
+@@ -4,19 +4,6 @@
+ #ifndef _LBS_WEXT_H_
+ #define _LBS_WEXT_H_
+
+-/** lbs_ioctl_regrdwr */
+-struct lbs_ioctl_regrdwr {
+- /** Which register to access */
+- u16 whichreg;
+- /** Read or Write */
+- u16 action;
+- u32 offset;
+- u16 NOB;
+- u32 value;
+-};
+-
+-#define LBS_MONITOR_OFF 0
+-
+ extern struct iw_handler_def lbs_handler_def;
+ extern struct iw_handler_def mesh_handler_def;
+
+diff --git a/drivers/net/wireless/net2280.h b/drivers/net/wireless/net2280.h
+deleted file mode 100644
+index 120eb83..0000000
+--- a/drivers/net/wireless/net2280.h
++++ /dev/null
+@@ -1,452 +0,0 @@
+-#ifndef NET2280_H
+-#define NET2280_H
+-/*
+- * NetChip 2280 high/full speed USB device controller.
+- * Unlike many such controllers, this one talks PCI.
+- */
+-
+-/*
+- * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
+- * Copyright (C) 2003 David Brownell
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * 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
+- */
+-
+-/*-------------------------------------------------------------------------*/
+-
+-/* NET2280 MEMORY MAPPED REGISTERS
+- *
+- * The register layout came from the chip documentation, and the bit
+- * number definitions were extracted from chip specification.
+- *
+- * Use the shift operator ('<<') to build bit masks, with readl/writel
+- * to access the registers through PCI.
+- */
+-
+-/* main registers, BAR0 + 0x0000 */
+-struct net2280_regs {
+- // offset 0x0000
+- __le32 devinit;
+-#define LOCAL_CLOCK_FREQUENCY 8
+-#define FORCE_PCI_RESET 7
+-#define PCI_ID 6
+-#define PCI_ENABLE 5
+-#define FIFO_SOFT_RESET 4
+-#define CFG_SOFT_RESET 3
+-#define PCI_SOFT_RESET 2
+-#define USB_SOFT_RESET 1
+-#define M8051_RESET 0
+- __le32 eectl;
+-#define EEPROM_ADDRESS_WIDTH 23
+-#define EEPROM_CHIP_SELECT_ACTIVE 22
+-#define EEPROM_PRESENT 21
+-#define EEPROM_VALID 20
+-#define EEPROM_BUSY 19
+-#define EEPROM_CHIP_SELECT_ENABLE 18
+-#define EEPROM_BYTE_READ_START 17
+-#define EEPROM_BYTE_WRITE_START 16
+-#define EEPROM_READ_DATA 8
+-#define EEPROM_WRITE_DATA 0
+- __le32 eeclkfreq;
+- u32 _unused0;
+- // offset 0x0010
+-
+- __le32 pciirqenb0; /* interrupt PCI master ... */
+-#define SETUP_PACKET_INTERRUPT_ENABLE 7
+-#define ENDPOINT_F_INTERRUPT_ENABLE 6
+-#define ENDPOINT_E_INTERRUPT_ENABLE 5
+-#define ENDPOINT_D_INTERRUPT_ENABLE 4
+-#define ENDPOINT_C_INTERRUPT_ENABLE 3
+-#define ENDPOINT_B_INTERRUPT_ENABLE 2
+-#define ENDPOINT_A_INTERRUPT_ENABLE 1
+-#define ENDPOINT_0_INTERRUPT_ENABLE 0
+- __le32 pciirqenb1;
+-#define PCI_INTERRUPT_ENABLE 31
+-#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
+-#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
+-#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
+-#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
+-#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
+-#define PCI_TARGET_ABORT_ASSERTED_INTERRUPT_ENABLE 18
+-#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
+-#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
+-#define GPIO_INTERRUPT_ENABLE 13
+-#define DMA_D_INTERRUPT_ENABLE 12
+-#define DMA_C_INTERRUPT_ENABLE 11
+-#define DMA_B_INTERRUPT_ENABLE 10
+-#define DMA_A_INTERRUPT_ENABLE 9
+-#define EEPROM_DONE_INTERRUPT_ENABLE 8
+-#define VBUS_INTERRUPT_ENABLE 7
+-#define CONTROL_STATUS_INTERRUPT_ENABLE 6
+-#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
+-#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
+-#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
+-#define RESUME_INTERRUPT_ENABLE 1
+-#define SOF_INTERRUPT_ENABLE 0
+- __le32 cpu_irqenb0; /* ... or onboard 8051 */
+-#define SETUP_PACKET_INTERRUPT_ENABLE 7
+-#define ENDPOINT_F_INTERRUPT_ENABLE 6
+-#define ENDPOINT_E_INTERRUPT_ENABLE 5
+-#define ENDPOINT_D_INTERRUPT_ENABLE 4
+-#define ENDPOINT_C_INTERRUPT_ENABLE 3
+-#define ENDPOINT_B_INTERRUPT_ENABLE 2
+-#define ENDPOINT_A_INTERRUPT_ENABLE 1
+-#define ENDPOINT_0_INTERRUPT_ENABLE 0
+- __le32 cpu_irqenb1;
+-#define CPU_INTERRUPT_ENABLE 31
+-#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
+-#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
+-#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
+-#define PCI_INTA_INTERRUPT_ENABLE 24
+-#define PCI_PME_INTERRUPT_ENABLE 23
+-#define PCI_SERR_INTERRUPT_ENABLE 22
+-#define PCI_PERR_INTERRUPT_ENABLE 21
+-#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
+-#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
+-#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
+-#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
+-#define GPIO_INTERRUPT_ENABLE 13
+-#define DMA_D_INTERRUPT_ENABLE 12
+-#define DMA_C_INTERRUPT_ENABLE 11
+-#define DMA_B_INTERRUPT_ENABLE 10
+-#define DMA_A_INTERRUPT_ENABLE 9
+-#define EEPROM_DONE_INTERRUPT_ENABLE 8
+-#define VBUS_INTERRUPT_ENABLE 7
+-#define CONTROL_STATUS_INTERRUPT_ENABLE 6
+-#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
+-#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
+-#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
+-#define RESUME_INTERRUPT_ENABLE 1
+-#define SOF_INTERRUPT_ENABLE 0
+-
+- // offset 0x0020
+- u32 _unused1;
+- __le32 usbirqenb1;
+-#define USB_INTERRUPT_ENABLE 31
+-#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
+-#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
+-#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
+-#define PCI_INTA_INTERRUPT_ENABLE 24
+-#define PCI_PME_INTERRUPT_ENABLE 23
+-#define PCI_SERR_INTERRUPT_ENABLE 22
+-#define PCI_PERR_INTERRUPT_ENABLE 21
+-#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
+-#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
+-#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
+-#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
+-#define GPIO_INTERRUPT_ENABLE 13
+-#define DMA_D_INTERRUPT_ENABLE 12
+-#define DMA_C_INTERRUPT_ENABLE 11
+-#define DMA_B_INTERRUPT_ENABLE 10
+-#define DMA_A_INTERRUPT_ENABLE 9
+-#define EEPROM_DONE_INTERRUPT_ENABLE 8
+-#define VBUS_INTERRUPT_ENABLE 7
+-#define CONTROL_STATUS_INTERRUPT_ENABLE 6
+-#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
+-#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
+-#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
+-#define RESUME_INTERRUPT_ENABLE 1
+-#define SOF_INTERRUPT_ENABLE 0
+- __le32 irqstat0;
+-#define INTA_ASSERTED 12
+-#define SETUP_PACKET_INTERRUPT 7
+-#define ENDPOINT_F_INTERRUPT 6
+-#define ENDPOINT_E_INTERRUPT 5
+-#define ENDPOINT_D_INTERRUPT 4
+-#define ENDPOINT_C_INTERRUPT 3
+-#define ENDPOINT_B_INTERRUPT 2
+-#define ENDPOINT_A_INTERRUPT 1
+-#define ENDPOINT_0_INTERRUPT 0
+- __le32 irqstat1;
+-#define POWER_STATE_CHANGE_INTERRUPT 27
+-#define PCI_ARBITER_TIMEOUT_INTERRUPT 26
+-#define PCI_PARITY_ERROR_INTERRUPT 25
+-#define PCI_INTA_INTERRUPT 24
+-#define PCI_PME_INTERRUPT 23
+-#define PCI_SERR_INTERRUPT 22
+-#define PCI_PERR_INTERRUPT 21
+-#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT 20
+-#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT 19
+-#define PCI_RETRY_ABORT_INTERRUPT 17
+-#define PCI_MASTER_CYCLE_DONE_INTERRUPT 16
+-#define GPIO_INTERRUPT 13
+-#define DMA_D_INTERRUPT 12
+-#define DMA_C_INTERRUPT 11
+-#define DMA_B_INTERRUPT 10
+-#define DMA_A_INTERRUPT 9
+-#define EEPROM_DONE_INTERRUPT 8
+-#define VBUS_INTERRUPT 7
+-#define CONTROL_STATUS_INTERRUPT 6
+-#define ROOT_PORT_RESET_INTERRUPT 4
+-#define SUSPEND_REQUEST_INTERRUPT 3
+-#define SUSPEND_REQUEST_CHANGE_INTERRUPT 2
+-#define RESUME_INTERRUPT 1
+-#define SOF_INTERRUPT 0
+- // offset 0x0030
+- __le32 idxaddr;
+- __le32 idxdata;
+- __le32 fifoctl;
+-#define PCI_BASE2_RANGE 16
+-#define IGNORE_FIFO_AVAILABILITY 3
+-#define PCI_BASE2_SELECT 2
+-#define FIFO_CONFIGURATION_SELECT 0
+- u32 _unused2;
+- // offset 0x0040
+- __le32 memaddr;
+-#define START 28
+-#define DIRECTION 27
+-#define FIFO_DIAGNOSTIC_SELECT 24
+-#define MEMORY_ADDRESS 0
+- __le32 memdata0;
+- __le32 memdata1;
+- u32 _unused3;
+- // offset 0x0050
+- __le32 gpioctl;
+-#define GPIO3_LED_SELECT 12
+-#define GPIO3_INTERRUPT_ENABLE 11
+-#define GPIO2_INTERRUPT_ENABLE 10
+-#define GPIO1_INTERRUPT_ENABLE 9
+-#define GPIO0_INTERRUPT_ENABLE 8
+-#define GPIO3_OUTPUT_ENABLE 7
+-#define GPIO2_OUTPUT_ENABLE 6
+-#define GPIO1_OUTPUT_ENABLE 5
+-#define GPIO0_OUTPUT_ENABLE 4
+-#define GPIO3_DATA 3
+-#define GPIO2_DATA 2
+-#define GPIO1_DATA 1
+-#define GPIO0_DATA 0
+- __le32 gpiostat;
+-#define GPIO3_INTERRUPT 3
+-#define GPIO2_INTERRUPT 2
+-#define GPIO1_INTERRUPT 1
+-#define GPIO0_INTERRUPT 0
+-} __attribute__ ((packed));
+-
+-/* usb control, BAR0 + 0x0080 */
+-struct net2280_usb_regs {
+- // offset 0x0080
+- __le32 stdrsp;
+-#define STALL_UNSUPPORTED_REQUESTS 31
+-#define SET_TEST_MODE 16
+-#define GET_OTHER_SPEED_CONFIGURATION 15
+-#define GET_DEVICE_QUALIFIER 14
+-#define SET_ADDRESS 13
+-#define ENDPOINT_SET_CLEAR_HALT 12
+-#define DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP 11
+-#define GET_STRING_DESCRIPTOR_2 10
+-#define GET_STRING_DESCRIPTOR_1 9
+-#define GET_STRING_DESCRIPTOR_0 8
+-#define GET_SET_INTERFACE 6
+-#define GET_SET_CONFIGURATION 5
+-#define GET_CONFIGURATION_DESCRIPTOR 4
+-#define GET_DEVICE_DESCRIPTOR 3
+-#define GET_ENDPOINT_STATUS 2
+-#define GET_INTERFACE_STATUS 1
+-#define GET_DEVICE_STATUS 0
+- __le32 prodvendid;
+-#define PRODUCT_ID 16
+-#define VENDOR_ID 0
+- __le32 relnum;
+- __le32 usbctl;
+-#define SERIAL_NUMBER_INDEX 16
+-#define PRODUCT_ID_STRING_ENABLE 13
+-#define VENDOR_ID_STRING_ENABLE 12
+-#define USB_ROOT_PORT_WAKEUP_ENABLE 11
+-#define VBUS_PIN 10
+-#define TIMED_DISCONNECT 9
+-#define SUSPEND_IMMEDIATELY 7
+-#define SELF_POWERED_USB_DEVICE 6
+-#define REMOTE_WAKEUP_SUPPORT 5
+-#define PME_POLARITY 4
+-#define USB_DETECT_ENABLE 3
+-#define PME_WAKEUP_ENABLE 2
+-#define DEVICE_REMOTE_WAKEUP_ENABLE 1
+-#define SELF_POWERED_STATUS 0
+- // offset 0x0090
+- __le32 usbstat;
+-#define HIGH_SPEED 7
+-#define FULL_SPEED 6
+-#define GENERATE_RESUME 5
+-#define GENERATE_DEVICE_REMOTE_WAKEUP 4
+- __le32 xcvrdiag;
+-#define FORCE_HIGH_SPEED_MODE 31
+-#define FORCE_FULL_SPEED_MODE 30
+-#define USB_TEST_MODE 24
+-#define LINE_STATE 16
+-#define TRANSCEIVER_OPERATION_MODE 2
+-#define TRANSCEIVER_SELECT 1
+-#define TERMINATION_SELECT 0
+- __le32 setup0123;
+- __le32 setup4567;
+- // offset 0x0090
+- u32 _unused0;
+- __le32 ouraddr;
+-#define FORCE_IMMEDIATE 7
+-#define OUR_USB_ADDRESS 0
+- __le32 ourconfig;
+-} __attribute__ ((packed));
+-
+-/* pci control, BAR0 + 0x0100 */
+-struct net2280_pci_regs {
+- // offset 0x0100
+- __le32 pcimstctl;
+-#define PCI_ARBITER_PARK_SELECT 13
+-#define PCI_MULTI LEVEL_ARBITER 12
+-#define PCI_RETRY_ABORT_ENABLE 11
+-#define DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE 10
+-#define DMA_READ_MULTIPLE_ENABLE 9
+-#define DMA_READ_LINE_ENABLE 8
+-#define PCI_MASTER_COMMAND_SELECT 6
+-#define MEM_READ_OR_WRITE 0
+-#define IO_READ_OR_WRITE 1
+-#define CFG_READ_OR_WRITE 2
+-#define PCI_MASTER_START 5
+-#define PCI_MASTER_READ_WRITE 4
+-#define PCI_MASTER_WRITE 0
+-#define PCI_MASTER_READ 1
+-#define PCI_MASTER_BYTE_WRITE_ENABLES 0
+- __le32 pcimstaddr;
+- __le32 pcimstdata;
+- __le32 pcimststat;
+-#define PCI_ARBITER_CLEAR 2
+-#define PCI_EXTERNAL_ARBITER 1
+-#define PCI_HOST_MODE 0
+-} __attribute__ ((packed));
+-
+-/* dma control, BAR0 + 0x0180 ... array of four structs like this,
+- * for channels 0..3. see also struct net2280_dma: descriptor
+- * that can be loaded into some of these registers.
+- */
+-struct net2280_dma_regs { /* [11.7] */
+- // offset 0x0180, 0x01a0, 0x01c0, 0x01e0,
+- __le32 dmactl;
+-#define DMA_SCATTER_GATHER_DONE_INTERRUPT_ENABLE 25
+-#define DMA_CLEAR_COUNT_ENABLE 21
+-#define DESCRIPTOR_POLLING_RATE 19
+-#define POLL_CONTINUOUS 0
+-#define POLL_1_USEC 1
+-#define POLL_100_USEC 2
+-#define POLL_1_MSEC 3
+-#define DMA_VALID_BIT_POLLING_ENABLE 18
+-#define DMA_VALID_BIT_ENABLE 17
+-#define DMA_SCATTER_GATHER_ENABLE 16
+-#define DMA_OUT_AUTO_START_ENABLE 4
+-#define DMA_PREEMPT_ENABLE 3
+-#define DMA_FIFO_VALIDATE 2
+-#define DMA_ENABLE 1
+-#define DMA_ADDRESS_HOLD 0
+- __le32 dmastat;
+-#define DMA_SCATTER_GATHER_DONE_INTERRUPT 25
+-#define DMA_TRANSACTION_DONE_INTERRUPT 24
+-#define DMA_ABORT 1
+-#define DMA_START 0
+- u32 _unused0[2];
+- // offset 0x0190, 0x01b0, 0x01d0, 0x01f0,
+- __le32 dmacount;
+-#define VALID_BIT 31
+-#define DMA_DIRECTION 30
+-#define DMA_DONE_INTERRUPT_ENABLE 29
+-#define END_OF_CHAIN 28
+-#define DMA_BYTE_COUNT_MASK ((1<<24)-1)
+-#define DMA_BYTE_COUNT 0
+- __le32 dmaaddr;
+- __le32 dmadesc;
+- u32 _unused1;
+-} __attribute__ ((packed));
+-
+-/* dedicated endpoint registers, BAR0 + 0x0200 */
+-
+-struct net2280_dep_regs { /* [11.8] */
+- // offset 0x0200, 0x0210, 0x220, 0x230, 0x240
+- __le32 dep_cfg;
+- // offset 0x0204, 0x0214, 0x224, 0x234, 0x244
+- __le32 dep_rsp;
+- u32 _unused[2];
+-} __attribute__ ((packed));
+-
+-/* configurable endpoint registers, BAR0 + 0x0300 ... array of seven structs
+- * like this, for ep0 then the configurable endpoints A..F
+- * ep0 reserved for control; E and F have only 64 bytes of fifo
+- */
+-struct net2280_ep_regs { /* [11.9] */
+- // offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0
+- __le32 ep_cfg;
+-#define ENDPOINT_BYTE_COUNT 16
+-#define ENDPOINT_ENABLE 10
+-#define ENDPOINT_TYPE 8
+-#define ENDPOINT_DIRECTION 7
+-#define ENDPOINT_NUMBER 0
+- __le32 ep_rsp;
+-#define SET_NAK_OUT_PACKETS 15
+-#define SET_EP_HIDE_STATUS_PHASE 14
+-#define SET_EP_FORCE_CRC_ERROR 13
+-#define SET_INTERRUPT_MODE 12
+-#define SET_CONTROL_STATUS_PHASE_HANDSHAKE 11
+-#define SET_NAK_OUT_PACKETS_MODE 10
+-#define SET_ENDPOINT_TOGGLE 9
+-#define SET_ENDPOINT_HALT 8
+-#define CLEAR_NAK_OUT_PACKETS 7
+-#define CLEAR_EP_HIDE_STATUS_PHASE 6
+-#define CLEAR_EP_FORCE_CRC_ERROR 5
+-#define CLEAR_INTERRUPT_MODE 4
+-#define CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE 3
+-#define CLEAR_NAK_OUT_PACKETS_MODE 2
+-#define CLEAR_ENDPOINT_TOGGLE 1
+-#define CLEAR_ENDPOINT_HALT 0
+- __le32 ep_irqenb;
+-#define SHORT_PACKET_OUT_DONE_INTERRUPT_ENABLE 6
+-#define SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE 5
+-#define DATA_PACKET_RECEIVED_INTERRUPT_ENABLE 3
+-#define DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE 2
+-#define DATA_OUT_PING_TOKEN_INTERRUPT_ENABLE 1
+-#define DATA_IN_TOKEN_INTERRUPT_ENABLE 0
+- __le32 ep_stat;
+-#define FIFO_VALID_COUNT 24
+-#define HIGH_BANDWIDTH_OUT_TRANSACTION_PID 22
+-#define TIMEOUT 21
+-#define USB_STALL_SENT 20
+-#define USB_IN_NAK_SENT 19
+-#define USB_IN_ACK_RCVD 18
+-#define USB_OUT_PING_NAK_SENT 17
+-#define USB_OUT_ACK_SENT 16
+-#define FIFO_OVERFLOW 13
+-#define FIFO_UNDERFLOW 12
+-#define FIFO_FULL 11
+-#define FIFO_EMPTY 10
+-#define FIFO_FLUSH 9
+-#define SHORT_PACKET_OUT_DONE_INTERRUPT 6
+-#define SHORT_PACKET_TRANSFERRED_INTERRUPT 5
+-#define NAK_OUT_PACKETS 4
+-#define DATA_PACKET_RECEIVED_INTERRUPT 3
+-#define DATA_PACKET_TRANSMITTED_INTERRUPT 2
+-#define DATA_OUT_PING_TOKEN_INTERRUPT 1
+-#define DATA_IN_TOKEN_INTERRUPT 0
+- // offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0
+- __le32 ep_avail;
+- __le32 ep_data;
+- u32 _unused0[2];
+-} __attribute__ ((packed));
+-
+-struct net2280_reg_write {
+- __le16 port;
+- __le32 addr;
+- __le32 val;
+-} __attribute__ ((packed));
+-
+-struct net2280_reg_read {
+- __le16 port;
+- __le32 addr;
+-} __attribute__ ((packed));
+-#endif /* NET2280_H */
+diff --git a/drivers/net/wireless/p54.h b/drivers/net/wireless/p54.h
+deleted file mode 100644
+index 744c866..0000000
+--- a/drivers/net/wireless/p54.h
++++ /dev/null
+@@ -1,81 +0,0 @@
+-#ifndef PRISM54_H
+-#define PRISM54_H
+-
+-/*
+- * Shared defines for all mac80211 Prism54 code
+- *
+- * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
+- *
+- * Based on the islsm (softmac prism54) driver, which is:
+- * Copyright 2004-2006 Jean-Baptiste Note <jbnote at gmail.com>, et al.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-enum control_frame_types {
+- P54_CONTROL_TYPE_FILTER_SET = 0,
+- P54_CONTROL_TYPE_CHANNEL_CHANGE,
+- P54_CONTROL_TYPE_FREQDONE,
+- P54_CONTROL_TYPE_DCFINIT,
+- P54_CONTROL_TYPE_FREEQUEUE = 7,
+- P54_CONTROL_TYPE_TXDONE,
+- P54_CONTROL_TYPE_PING,
+- P54_CONTROL_TYPE_STAT_READBACK,
+- P54_CONTROL_TYPE_BBP,
+- P54_CONTROL_TYPE_EEPROM_READBACK,
+- P54_CONTROL_TYPE_LED
+-};
+-
+-struct p54_control_hdr {
+- __le16 magic1;
+- __le16 len;
+- __le32 req_id;
+- __le16 type; /* enum control_frame_types */
+- u8 retry1;
+- u8 retry2;
+- u8 data[0];
+-} __attribute__ ((packed));
+-
+-#define EEPROM_READBACK_LEN (sizeof(struct p54_control_hdr) + 4 /* p54_eeprom_lm86 */)
+-#define MAX_RX_SIZE (IEEE80211_MAX_RTS_THRESHOLD + sizeof(struct p54_control_hdr) + 20 /* length of struct p54_rx_hdr */ + 16 )
+-
+-#define ISL38XX_DEV_FIRMWARE_ADDR 0x20000
+-
+-struct p54_common {
+- u32 rx_start;
+- u32 rx_end;
+- struct sk_buff_head tx_queue;
+- void (*tx)(struct ieee80211_hw *dev, struct p54_control_hdr *data,
+- size_t len, int free_on_tx);
+- int (*open)(struct ieee80211_hw *dev);
+- void (*stop)(struct ieee80211_hw *dev);
+- int mode;
+- u8 mac_addr[ETH_ALEN];
+- u8 bssid[ETH_ALEN];
+- struct pda_iq_autocal_entry *iq_autocal;
+- unsigned int iq_autocal_len;
+- struct pda_channel_output_limit *output_limit;
+- unsigned int output_limit_len;
+- struct pda_pa_curve_data *curve_data;
+- __le16 rxhw;
+- u8 version;
+- unsigned int tx_hdr_len;
+- void *cached_vdcf;
+- unsigned int fw_var;
+- /* FIXME: this channels/modes/rates stuff sucks */
+- struct ieee80211_channel channels[14];
+- struct ieee80211_rate rates[12];
+- struct ieee80211_hw_mode modes[2];
+- struct ieee80211_tx_queue_stats tx_stats;
+-};
+-
+-int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb);
+-void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw);
+-int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len);
+-void p54_fill_eeprom_readback(struct p54_control_hdr *hdr);
+-struct ieee80211_hw *p54_init_common(size_t priv_data_len);
+-void p54_free_common(struct ieee80211_hw *dev);
+-
+-#endif /* PRISM54_H */
+diff --git a/drivers/net/wireless/p54/Kconfig b/drivers/net/wireless/p54/Kconfig
+new file mode 100644
+index 0000000..d3469d0
+--- /dev/null
++++ b/drivers/net/wireless/p54/Kconfig
+@@ -0,0 +1,63 @@
++config P54_COMMON
++ tristate "Softmac Prism54 support"
++ depends on MAC80211 && WLAN_80211 && FW_LOADER && EXPERIMENTAL
++ ---help---
++ This is common code for isl38xx based cards.
++ This module does nothing by itself - the USB/PCI frontends
++ also need to be enabled in order to support any devices.
++
++ These devices require softmac firmware which can be found at
++ http://prism54.org/
++
++ If you choose to build a module, it'll be called p54common.
++
++config P54_USB
++ tristate "Prism54 USB support"
++ depends on P54_COMMON && USB
++ select CRC32
++ ---help---
++ This driver is for USB isl38xx based wireless cards.
++ These are USB based adapters found in devices such as:
++
++ 3COM 3CRWE254G72
++ SMC 2862W-G
++ Accton 802.11g WN4501 USB
++ Siemens Gigaset USB
++ Netgear WG121
++ Netgear WG111
++ Medion 40900, Roper Europe
++ Shuttle PN15, Airvast WM168g, IOGear GWU513
++ Linksys WUSB54G
++ Linksys WUSB54G Portable
++ DLink DWL-G120 Spinnaker
++ DLink DWL-G122
++ Belkin F5D7050 ver 1000
++ Cohiba Proto board
++ SMC 2862W-G version 2
++ U.S. Robotics U5 802.11g Adapter
++ FUJITSU E-5400 USB D1700
++ Sagem XG703A
++ DLink DWL-G120 Cohiba
++ Spinnaker Proto board
++ Linksys WUSB54AG
++ Inventel UR054G
++ Spinnaker DUT
++
++ These devices require softmac firmware which can be found at
++ http://prism54.org/
++
++ If you choose to build a module, it'll be called p54usb.
++
++config P54_PCI
++ tristate "Prism54 PCI support"
++ depends on P54_COMMON && PCI
++ ---help---
++ This driver is for PCI isl38xx based wireless cards.
++ This driver supports most devices that are supported by the
++ fullmac prism54 driver plus many devices which are not
++ supported by the fullmac driver/firmware.
++
++ This driver requires softmac firmware which can be found at
++ http://prism54.org/
++
++ If you choose to build a module, it'll be called p54pci.
+diff --git a/drivers/net/wireless/p54/Makefile b/drivers/net/wireless/p54/Makefile
+new file mode 100644
+index 0000000..4fa9ce7
+--- /dev/null
++++ b/drivers/net/wireless/p54/Makefile
+@@ -0,0 +1,3 @@
++obj-$(CONFIG_P54_COMMON) += p54common.o
++obj-$(CONFIG_P54_USB) += p54usb.o
++obj-$(CONFIG_P54_PCI) += p54pci.o
+diff --git a/drivers/net/wireless/p54/net2280.h b/drivers/net/wireless/p54/net2280.h
+new file mode 100644
+index 0000000..4915d9d
+--- /dev/null
++++ b/drivers/net/wireless/p54/net2280.h
+@@ -0,0 +1,452 @@
++#ifndef NET2280_H
++#define NET2280_H
++/*
++ * NetChip 2280 high/full speed USB device controller.
++ * Unlike many such controllers, this one talks PCI.
++ */
++
++/*
++ * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
++ * Copyright (C) 2003 David Brownell
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * 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
++ */
++
++/*-------------------------------------------------------------------------*/
++
++/* NET2280 MEMORY MAPPED REGISTERS
++ *
++ * The register layout came from the chip documentation, and the bit
++ * number definitions were extracted from chip specification.
++ *
++ * Use the shift operator ('<<') to build bit masks, with readl/writel
++ * to access the registers through PCI.
++ */
++
++/* main registers, BAR0 + 0x0000 */
++struct net2280_regs {
++ /* offset 0x0000 */
++ __le32 devinit;
++#define LOCAL_CLOCK_FREQUENCY 8
++#define FORCE_PCI_RESET 7
++#define PCI_ID 6
++#define PCI_ENABLE 5
++#define FIFO_SOFT_RESET 4
++#define CFG_SOFT_RESET 3
++#define PCI_SOFT_RESET 2
++#define USB_SOFT_RESET 1
++#define M8051_RESET 0
++ __le32 eectl;
++#define EEPROM_ADDRESS_WIDTH 23
++#define EEPROM_CHIP_SELECT_ACTIVE 22
++#define EEPROM_PRESENT 21
++#define EEPROM_VALID 20
++#define EEPROM_BUSY 19
++#define EEPROM_CHIP_SELECT_ENABLE 18
++#define EEPROM_BYTE_READ_START 17
++#define EEPROM_BYTE_WRITE_START 16
++#define EEPROM_READ_DATA 8
++#define EEPROM_WRITE_DATA 0
++ __le32 eeclkfreq;
++ u32 _unused0;
++ /* offset 0x0010 */
++
++ __le32 pciirqenb0; /* interrupt PCI master ... */
++#define SETUP_PACKET_INTERRUPT_ENABLE 7
++#define ENDPOINT_F_INTERRUPT_ENABLE 6
++#define ENDPOINT_E_INTERRUPT_ENABLE 5
++#define ENDPOINT_D_INTERRUPT_ENABLE 4
++#define ENDPOINT_C_INTERRUPT_ENABLE 3
++#define ENDPOINT_B_INTERRUPT_ENABLE 2
++#define ENDPOINT_A_INTERRUPT_ENABLE 1
++#define ENDPOINT_0_INTERRUPT_ENABLE 0
++ __le32 pciirqenb1;
++#define PCI_INTERRUPT_ENABLE 31
++#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
++#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
++#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
++#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
++#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
++#define PCI_TARGET_ABORT_ASSERTED_INTERRUPT_ENABLE 18
++#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
++#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
++#define GPIO_INTERRUPT_ENABLE 13
++#define DMA_D_INTERRUPT_ENABLE 12
++#define DMA_C_INTERRUPT_ENABLE 11
++#define DMA_B_INTERRUPT_ENABLE 10
++#define DMA_A_INTERRUPT_ENABLE 9
++#define EEPROM_DONE_INTERRUPT_ENABLE 8
++#define VBUS_INTERRUPT_ENABLE 7
++#define CONTROL_STATUS_INTERRUPT_ENABLE 6
++#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
++#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
++#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
++#define RESUME_INTERRUPT_ENABLE 1
++#define SOF_INTERRUPT_ENABLE 0
++ __le32 cpu_irqenb0; /* ... or onboard 8051 */
++#define SETUP_PACKET_INTERRUPT_ENABLE 7
++#define ENDPOINT_F_INTERRUPT_ENABLE 6
++#define ENDPOINT_E_INTERRUPT_ENABLE 5
++#define ENDPOINT_D_INTERRUPT_ENABLE 4
++#define ENDPOINT_C_INTERRUPT_ENABLE 3
++#define ENDPOINT_B_INTERRUPT_ENABLE 2
++#define ENDPOINT_A_INTERRUPT_ENABLE 1
++#define ENDPOINT_0_INTERRUPT_ENABLE 0
++ __le32 cpu_irqenb1;
++#define CPU_INTERRUPT_ENABLE 31
++#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
++#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
++#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
++#define PCI_INTA_INTERRUPT_ENABLE 24
++#define PCI_PME_INTERRUPT_ENABLE 23
++#define PCI_SERR_INTERRUPT_ENABLE 22
++#define PCI_PERR_INTERRUPT_ENABLE 21
++#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
++#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
++#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
++#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
++#define GPIO_INTERRUPT_ENABLE 13
++#define DMA_D_INTERRUPT_ENABLE 12
++#define DMA_C_INTERRUPT_ENABLE 11
++#define DMA_B_INTERRUPT_ENABLE 10
++#define DMA_A_INTERRUPT_ENABLE 9
++#define EEPROM_DONE_INTERRUPT_ENABLE 8
++#define VBUS_INTERRUPT_ENABLE 7
++#define CONTROL_STATUS_INTERRUPT_ENABLE 6
++#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
++#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
++#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
++#define RESUME_INTERRUPT_ENABLE 1
++#define SOF_INTERRUPT_ENABLE 0
++
++ /* offset 0x0020 */
++ u32 _unused1;
++ __le32 usbirqenb1;
++#define USB_INTERRUPT_ENABLE 31
++#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
++#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
++#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
++#define PCI_INTA_INTERRUPT_ENABLE 24
++#define PCI_PME_INTERRUPT_ENABLE 23
++#define PCI_SERR_INTERRUPT_ENABLE 22
++#define PCI_PERR_INTERRUPT_ENABLE 21
++#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
++#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
++#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
++#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
++#define GPIO_INTERRUPT_ENABLE 13
++#define DMA_D_INTERRUPT_ENABLE 12
++#define DMA_C_INTERRUPT_ENABLE 11
++#define DMA_B_INTERRUPT_ENABLE 10
++#define DMA_A_INTERRUPT_ENABLE 9
++#define EEPROM_DONE_INTERRUPT_ENABLE 8
++#define VBUS_INTERRUPT_ENABLE 7
++#define CONTROL_STATUS_INTERRUPT_ENABLE 6
++#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
++#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
++#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
++#define RESUME_INTERRUPT_ENABLE 1
++#define SOF_INTERRUPT_ENABLE 0
++ __le32 irqstat0;
++#define INTA_ASSERTED 12
++#define SETUP_PACKET_INTERRUPT 7
++#define ENDPOINT_F_INTERRUPT 6
++#define ENDPOINT_E_INTERRUPT 5
++#define ENDPOINT_D_INTERRUPT 4
++#define ENDPOINT_C_INTERRUPT 3
++#define ENDPOINT_B_INTERRUPT 2
++#define ENDPOINT_A_INTERRUPT 1
++#define ENDPOINT_0_INTERRUPT 0
++ __le32 irqstat1;
++#define POWER_STATE_CHANGE_INTERRUPT 27
++#define PCI_ARBITER_TIMEOUT_INTERRUPT 26
++#define PCI_PARITY_ERROR_INTERRUPT 25
++#define PCI_INTA_INTERRUPT 24
++#define PCI_PME_INTERRUPT 23
++#define PCI_SERR_INTERRUPT 22
++#define PCI_PERR_INTERRUPT 21
++#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT 20
++#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT 19
++#define PCI_RETRY_ABORT_INTERRUPT 17
++#define PCI_MASTER_CYCLE_DONE_INTERRUPT 16
++#define GPIO_INTERRUPT 13
++#define DMA_D_INTERRUPT 12
++#define DMA_C_INTERRUPT 11
++#define DMA_B_INTERRUPT 10
++#define DMA_A_INTERRUPT 9
++#define EEPROM_DONE_INTERRUPT 8
++#define VBUS_INTERRUPT 7
++#define CONTROL_STATUS_INTERRUPT 6
++#define ROOT_PORT_RESET_INTERRUPT 4
++#define SUSPEND_REQUEST_INTERRUPT 3
++#define SUSPEND_REQUEST_CHANGE_INTERRUPT 2
++#define RESUME_INTERRUPT 1
++#define SOF_INTERRUPT 0
++ /* offset 0x0030 */
++ __le32 idxaddr;
++ __le32 idxdata;
++ __le32 fifoctl;
++#define PCI_BASE2_RANGE 16
++#define IGNORE_FIFO_AVAILABILITY 3
++#define PCI_BASE2_SELECT 2
++#define FIFO_CONFIGURATION_SELECT 0
++ u32 _unused2;
++ /* offset 0x0040 */
++ __le32 memaddr;
++#define START 28
++#define DIRECTION 27
++#define FIFO_DIAGNOSTIC_SELECT 24
++#define MEMORY_ADDRESS 0
++ __le32 memdata0;
++ __le32 memdata1;
++ u32 _unused3;
++ /* offset 0x0050 */
++ __le32 gpioctl;
++#define GPIO3_LED_SELECT 12
++#define GPIO3_INTERRUPT_ENABLE 11
++#define GPIO2_INTERRUPT_ENABLE 10
++#define GPIO1_INTERRUPT_ENABLE 9
++#define GPIO0_INTERRUPT_ENABLE 8
++#define GPIO3_OUTPUT_ENABLE 7
++#define GPIO2_OUTPUT_ENABLE 6
++#define GPIO1_OUTPUT_ENABLE 5
++#define GPIO0_OUTPUT_ENABLE 4
++#define GPIO3_DATA 3
++#define GPIO2_DATA 2
++#define GPIO1_DATA 1
++#define GPIO0_DATA 0
++ __le32 gpiostat;
++#define GPIO3_INTERRUPT 3
++#define GPIO2_INTERRUPT 2
++#define GPIO1_INTERRUPT 1
++#define GPIO0_INTERRUPT 0
++} __attribute__ ((packed));
++
++/* usb control, BAR0 + 0x0080 */
++struct net2280_usb_regs {
++ /* offset 0x0080 */
++ __le32 stdrsp;
++#define STALL_UNSUPPORTED_REQUESTS 31
++#define SET_TEST_MODE 16
++#define GET_OTHER_SPEED_CONFIGURATION 15
++#define GET_DEVICE_QUALIFIER 14
++#define SET_ADDRESS 13
++#define ENDPOINT_SET_CLEAR_HALT 12
++#define DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP 11
++#define GET_STRING_DESCRIPTOR_2 10
++#define GET_STRING_DESCRIPTOR_1 9
++#define GET_STRING_DESCRIPTOR_0 8
++#define GET_SET_INTERFACE 6
++#define GET_SET_CONFIGURATION 5
++#define GET_CONFIGURATION_DESCRIPTOR 4
++#define GET_DEVICE_DESCRIPTOR 3
++#define GET_ENDPOINT_STATUS 2
++#define GET_INTERFACE_STATUS 1
++#define GET_DEVICE_STATUS 0
++ __le32 prodvendid;
++#define PRODUCT_ID 16
++#define VENDOR_ID 0
++ __le32 relnum;
++ __le32 usbctl;
++#define SERIAL_NUMBER_INDEX 16
++#define PRODUCT_ID_STRING_ENABLE 13
++#define VENDOR_ID_STRING_ENABLE 12
++#define USB_ROOT_PORT_WAKEUP_ENABLE 11
++#define VBUS_PIN 10
++#define TIMED_DISCONNECT 9
++#define SUSPEND_IMMEDIATELY 7
++#define SELF_POWERED_USB_DEVICE 6
++#define REMOTE_WAKEUP_SUPPORT 5
++#define PME_POLARITY 4
++#define USB_DETECT_ENABLE 3
++#define PME_WAKEUP_ENABLE 2
++#define DEVICE_REMOTE_WAKEUP_ENABLE 1
++#define SELF_POWERED_STATUS 0
++ /* offset 0x0090 */
++ __le32 usbstat;
++#define HIGH_SPEED 7
++#define FULL_SPEED 6
++#define GENERATE_RESUME 5
++#define GENERATE_DEVICE_REMOTE_WAKEUP 4
++ __le32 xcvrdiag;
++#define FORCE_HIGH_SPEED_MODE 31
++#define FORCE_FULL_SPEED_MODE 30
++#define USB_TEST_MODE 24
++#define LINE_STATE 16
++#define TRANSCEIVER_OPERATION_MODE 2
++#define TRANSCEIVER_SELECT 1
++#define TERMINATION_SELECT 0
++ __le32 setup0123;
++ __le32 setup4567;
++ /* offset 0x0090 */
++ u32 _unused0;
++ __le32 ouraddr;
++#define FORCE_IMMEDIATE 7
++#define OUR_USB_ADDRESS 0
++ __le32 ourconfig;
++} __attribute__ ((packed));
++
++/* pci control, BAR0 + 0x0100 */
++struct net2280_pci_regs {
++ /* offset 0x0100 */
++ __le32 pcimstctl;
++#define PCI_ARBITER_PARK_SELECT 13
++#define PCI_MULTI LEVEL_ARBITER 12
++#define PCI_RETRY_ABORT_ENABLE 11
++#define DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE 10
++#define DMA_READ_MULTIPLE_ENABLE 9
++#define DMA_READ_LINE_ENABLE 8
++#define PCI_MASTER_COMMAND_SELECT 6
++#define MEM_READ_OR_WRITE 0
++#define IO_READ_OR_WRITE 1
++#define CFG_READ_OR_WRITE 2
++#define PCI_MASTER_START 5
++#define PCI_MASTER_READ_WRITE 4
++#define PCI_MASTER_WRITE 0
++#define PCI_MASTER_READ 1
++#define PCI_MASTER_BYTE_WRITE_ENABLES 0
++ __le32 pcimstaddr;
++ __le32 pcimstdata;
++ __le32 pcimststat;
++#define PCI_ARBITER_CLEAR 2
++#define PCI_EXTERNAL_ARBITER 1
++#define PCI_HOST_MODE 0
++} __attribute__ ((packed));
++
++/* dma control, BAR0 + 0x0180 ... array of four structs like this,
++ * for channels 0..3. see also struct net2280_dma: descriptor
++ * that can be loaded into some of these registers.
++ */
++struct net2280_dma_regs { /* [11.7] */
++ /* offset 0x0180, 0x01a0, 0x01c0, 0x01e0, */
++ __le32 dmactl;
++#define DMA_SCATTER_GATHER_DONE_INTERRUPT_ENABLE 25
++#define DMA_CLEAR_COUNT_ENABLE 21
++#define DESCRIPTOR_POLLING_RATE 19
++#define POLL_CONTINUOUS 0
++#define POLL_1_USEC 1
++#define POLL_100_USEC 2
++#define POLL_1_MSEC 3
++#define DMA_VALID_BIT_POLLING_ENABLE 18
++#define DMA_VALID_BIT_ENABLE 17
++#define DMA_SCATTER_GATHER_ENABLE 16
++#define DMA_OUT_AUTO_START_ENABLE 4
++#define DMA_PREEMPT_ENABLE 3
++#define DMA_FIFO_VALIDATE 2
++#define DMA_ENABLE 1
++#define DMA_ADDRESS_HOLD 0
++ __le32 dmastat;
++#define DMA_SCATTER_GATHER_DONE_INTERRUPT 25
++#define DMA_TRANSACTION_DONE_INTERRUPT 24
++#define DMA_ABORT 1
++#define DMA_START 0
++ u32 _unused0[2];
++ /* offset 0x0190, 0x01b0, 0x01d0, 0x01f0, */
++ __le32 dmacount;
++#define VALID_BIT 31
++#define DMA_DIRECTION 30
++#define DMA_DONE_INTERRUPT_ENABLE 29
++#define END_OF_CHAIN 28
++#define DMA_BYTE_COUNT_MASK ((1<<24)-1)
++#define DMA_BYTE_COUNT 0
++ __le32 dmaaddr;
++ __le32 dmadesc;
++ u32 _unused1;
++} __attribute__ ((packed));
++
++/* dedicated endpoint registers, BAR0 + 0x0200 */
++
++struct net2280_dep_regs { /* [11.8] */
++ /* offset 0x0200, 0x0210, 0x220, 0x230, 0x240 */
++ __le32 dep_cfg;
++ /* offset 0x0204, 0x0214, 0x224, 0x234, 0x244 */
++ __le32 dep_rsp;
++ u32 _unused[2];
++} __attribute__ ((packed));
++
++/* configurable endpoint registers, BAR0 + 0x0300 ... array of seven structs
++ * like this, for ep0 then the configurable endpoints A..F
++ * ep0 reserved for control; E and F have only 64 bytes of fifo
++ */
++struct net2280_ep_regs { /* [11.9] */
++ /* offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0 */
++ __le32 ep_cfg;
++#define ENDPOINT_BYTE_COUNT 16
++#define ENDPOINT_ENABLE 10
++#define ENDPOINT_TYPE 8
++#define ENDPOINT_DIRECTION 7
++#define ENDPOINT_NUMBER 0
++ __le32 ep_rsp;
++#define SET_NAK_OUT_PACKETS 15
++#define SET_EP_HIDE_STATUS_PHASE 14
++#define SET_EP_FORCE_CRC_ERROR 13
++#define SET_INTERRUPT_MODE 12
++#define SET_CONTROL_STATUS_PHASE_HANDSHAKE 11
++#define SET_NAK_OUT_PACKETS_MODE 10
++#define SET_ENDPOINT_TOGGLE 9
++#define SET_ENDPOINT_HALT 8
++#define CLEAR_NAK_OUT_PACKETS 7
++#define CLEAR_EP_HIDE_STATUS_PHASE 6
++#define CLEAR_EP_FORCE_CRC_ERROR 5
++#define CLEAR_INTERRUPT_MODE 4
++#define CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE 3
++#define CLEAR_NAK_OUT_PACKETS_MODE 2
++#define CLEAR_ENDPOINT_TOGGLE 1
++#define CLEAR_ENDPOINT_HALT 0
++ __le32 ep_irqenb;
++#define SHORT_PACKET_OUT_DONE_INTERRUPT_ENABLE 6
++#define SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE 5
++#define DATA_PACKET_RECEIVED_INTERRUPT_ENABLE 3
++#define DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE 2
++#define DATA_OUT_PING_TOKEN_INTERRUPT_ENABLE 1
++#define DATA_IN_TOKEN_INTERRUPT_ENABLE 0
++ __le32 ep_stat;
++#define FIFO_VALID_COUNT 24
++#define HIGH_BANDWIDTH_OUT_TRANSACTION_PID 22
++#define TIMEOUT 21
++#define USB_STALL_SENT 20
++#define USB_IN_NAK_SENT 19
++#define USB_IN_ACK_RCVD 18
++#define USB_OUT_PING_NAK_SENT 17
++#define USB_OUT_ACK_SENT 16
++#define FIFO_OVERFLOW 13
++#define FIFO_UNDERFLOW 12
++#define FIFO_FULL 11
++#define FIFO_EMPTY 10
++#define FIFO_FLUSH 9
++#define SHORT_PACKET_OUT_DONE_INTERRUPT 6
++#define SHORT_PACKET_TRANSFERRED_INTERRUPT 5
++#define NAK_OUT_PACKETS 4
++#define DATA_PACKET_RECEIVED_INTERRUPT 3
++#define DATA_PACKET_TRANSMITTED_INTERRUPT 2
++#define DATA_OUT_PING_TOKEN_INTERRUPT 1
++#define DATA_IN_TOKEN_INTERRUPT 0
++ /* offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0 */
++ __le32 ep_avail;
++ __le32 ep_data;
++ u32 _unused0[2];
++} __attribute__ ((packed));
++
++struct net2280_reg_write {
++ __le16 port;
++ __le32 addr;
++ __le32 val;
++} __attribute__ ((packed));
++
++struct net2280_reg_read {
++ __le16 port;
++ __le32 addr;
++} __attribute__ ((packed));
++#endif /* NET2280_H */
+diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h
+new file mode 100644
+index 0000000..06d2c67
+--- /dev/null
++++ b/drivers/net/wireless/p54/p54.h
+@@ -0,0 +1,77 @@
++#ifndef PRISM54_H
++#define PRISM54_H
++
++/*
++ * Shared defines for all mac80211 Prism54 code
++ *
++ * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
++ *
++ * Based on the islsm (softmac prism54) driver, which is:
++ * Copyright 2004-2006 Jean-Baptiste Note <jbnote at gmail.com>, et al.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++enum control_frame_types {
++ P54_CONTROL_TYPE_FILTER_SET = 0,
++ P54_CONTROL_TYPE_CHANNEL_CHANGE,
++ P54_CONTROL_TYPE_FREQDONE,
++ P54_CONTROL_TYPE_DCFINIT,
++ P54_CONTROL_TYPE_FREEQUEUE = 7,
++ P54_CONTROL_TYPE_TXDONE,
++ P54_CONTROL_TYPE_PING,
++ P54_CONTROL_TYPE_STAT_READBACK,
++ P54_CONTROL_TYPE_BBP,
++ P54_CONTROL_TYPE_EEPROM_READBACK,
++ P54_CONTROL_TYPE_LED
++};
++
++struct p54_control_hdr {
++ __le16 magic1;
++ __le16 len;
++ __le32 req_id;
++ __le16 type; /* enum control_frame_types */
++ u8 retry1;
++ u8 retry2;
++ u8 data[0];
++} __attribute__ ((packed));
++
++#define EEPROM_READBACK_LEN (sizeof(struct p54_control_hdr) + 4 /* p54_eeprom_lm86 */)
++#define MAX_RX_SIZE (IEEE80211_MAX_RTS_THRESHOLD + sizeof(struct p54_control_hdr) + 20 /* length of struct p54_rx_hdr */ + 16 )
++
++#define ISL38XX_DEV_FIRMWARE_ADDR 0x20000
++
++struct p54_common {
++ u32 rx_start;
++ u32 rx_end;
++ struct sk_buff_head tx_queue;
++ void (*tx)(struct ieee80211_hw *dev, struct p54_control_hdr *data,
++ size_t len, int free_on_tx);
++ int (*open)(struct ieee80211_hw *dev);
++ void (*stop)(struct ieee80211_hw *dev);
++ int mode;
++ u8 mac_addr[ETH_ALEN];
++ u8 bssid[ETH_ALEN];
++ struct pda_iq_autocal_entry *iq_autocal;
++ unsigned int iq_autocal_len;
++ struct pda_channel_output_limit *output_limit;
++ unsigned int output_limit_len;
++ struct pda_pa_curve_data *curve_data;
++ __le16 rxhw;
++ u8 version;
++ unsigned int tx_hdr_len;
++ void *cached_vdcf;
++ unsigned int fw_var;
++ struct ieee80211_tx_queue_stats tx_stats;
++};
++
++int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb);
++void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw);
++int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len);
++void p54_fill_eeprom_readback(struct p54_control_hdr *hdr);
++struct ieee80211_hw *p54_init_common(size_t priv_data_len);
++void p54_free_common(struct ieee80211_hw *dev);
++
++#endif /* PRISM54_H */
+diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c
+new file mode 100644
+index 0000000..63f9bad
+--- /dev/null
++++ b/drivers/net/wireless/p54/p54common.c
+@@ -0,0 +1,1051 @@
++
++/*
++ * Common code for mac80211 Prism54 drivers
++ *
++ * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
++ * Copyright (c) 2007, Christian Lamparter <chunkeey at web.de>
++ *
++ * Based on the islsm (softmac prism54) driver, which is:
++ * Copyright 2004-2006 Jean-Baptiste Note <jbnote at gmail.com>, et al.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/init.h>
++#include <linux/firmware.h>
++#include <linux/etherdevice.h>
++
++#include <net/mac80211.h>
++
++#include "p54.h"
++#include "p54common.h"
++
++MODULE_AUTHOR("Michael Wu <flamingice at sourmilk.net>");
++MODULE_DESCRIPTION("Softmac Prism54 common code");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("prism54common");
++
++static struct ieee80211_rate p54_rates[] = {
++ { .bitrate = 10, .hw_value = 0, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
++ { .bitrate = 20, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
++ { .bitrate = 55, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
++ { .bitrate = 110, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
++ { .bitrate = 60, .hw_value = 4, },
++ { .bitrate = 90, .hw_value = 5, },
++ { .bitrate = 120, .hw_value = 6, },
++ { .bitrate = 180, .hw_value = 7, },
++ { .bitrate = 240, .hw_value = 8, },
++ { .bitrate = 360, .hw_value = 9, },
++ { .bitrate = 480, .hw_value = 10, },
++ { .bitrate = 540, .hw_value = 11, },
++};
++
++static struct ieee80211_channel p54_channels[] = {
++ { .center_freq = 2412, .hw_value = 1, },
++ { .center_freq = 2417, .hw_value = 2, },
++ { .center_freq = 2422, .hw_value = 3, },
++ { .center_freq = 2427, .hw_value = 4, },
++ { .center_freq = 2432, .hw_value = 5, },
++ { .center_freq = 2437, .hw_value = 6, },
++ { .center_freq = 2442, .hw_value = 7, },
++ { .center_freq = 2447, .hw_value = 8, },
++ { .center_freq = 2452, .hw_value = 9, },
++ { .center_freq = 2457, .hw_value = 10, },
++ { .center_freq = 2462, .hw_value = 11, },
++ { .center_freq = 2467, .hw_value = 12, },
++ { .center_freq = 2472, .hw_value = 13, },
++ { .center_freq = 2484, .hw_value = 14, },
++};
++
++static struct ieee80211_supported_band band_2GHz = {
++ .channels = p54_channels,
++ .n_channels = ARRAY_SIZE(p54_channels),
++ .bitrates = p54_rates,
++ .n_bitrates = ARRAY_SIZE(p54_rates),
++};
++
++
++void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
++{
++ struct p54_common *priv = dev->priv;
++ struct bootrec_exp_if *exp_if;
++ struct bootrec *bootrec;
++ u32 *data = (u32 *)fw->data;
++ u32 *end_data = (u32 *)fw->data + (fw->size >> 2);
++ u8 *fw_version = NULL;
++ size_t len;
++ int i;
++
++ if (priv->rx_start)
++ return;
++
++ while (data < end_data && *data)
++ data++;
++
++ while (data < end_data && !*data)
++ data++;
++
++ bootrec = (struct bootrec *) data;
++
++ while (bootrec->data <= end_data &&
++ (bootrec->data + (len = le32_to_cpu(bootrec->len))) <= end_data) {
++ u32 code = le32_to_cpu(bootrec->code);
++ switch (code) {
++ case BR_CODE_COMPONENT_ID:
++ switch (be32_to_cpu(*(__be32 *)bootrec->data)) {
++ case FW_FMAC:
++ printk(KERN_INFO "p54: FreeMAC firmware\n");
++ break;
++ case FW_LM20:
++ printk(KERN_INFO "p54: LM20 firmware\n");
++ break;
++ case FW_LM86:
++ printk(KERN_INFO "p54: LM86 firmware\n");
++ break;
++ case FW_LM87:
++ printk(KERN_INFO "p54: LM87 firmware - not supported yet!\n");
++ break;
++ default:
++ printk(KERN_INFO "p54: unknown firmware\n");
++ break;
++ }
++ break;
++ case BR_CODE_COMPONENT_VERSION:
++ /* 24 bytes should be enough for all firmwares */
++ if (strnlen((unsigned char*)bootrec->data, 24) < 24)
++ fw_version = (unsigned char*)bootrec->data;
++ break;
++ case BR_CODE_DESCR:
++ priv->rx_start = le32_to_cpu(((__le32 *)bootrec->data)[1]);
++ /* FIXME add sanity checking */
++ priv->rx_end = le32_to_cpu(((__le32 *)bootrec->data)[2]) - 0x3500;
++ break;
++ case BR_CODE_EXPOSED_IF:
++ exp_if = (struct bootrec_exp_if *) bootrec->data;
++ for (i = 0; i < (len * sizeof(*exp_if) / 4); i++)
++ if (exp_if[i].if_id == cpu_to_le16(0x1a))
++ priv->fw_var = le16_to_cpu(exp_if[i].variant);
++ break;
++ case BR_CODE_DEPENDENT_IF:
++ break;
++ case BR_CODE_END_OF_BRA:
++ case LEGACY_BR_CODE_END_OF_BRA:
++ end_data = NULL;
++ break;
++ default:
++ break;
++ }
++ bootrec = (struct bootrec *)&bootrec->data[len];
++ }
++
++ if (fw_version)
++ printk(KERN_INFO "p54: FW rev %s - Softmac protocol %x.%x\n",
++ fw_version, priv->fw_var >> 8, priv->fw_var & 0xff);
++
++ if (priv->fw_var >= 0x300) {
++ /* Firmware supports QoS, use it! */
++ priv->tx_stats.data[0].limit = 3;
++ priv->tx_stats.data[1].limit = 4;
++ priv->tx_stats.data[2].limit = 3;
++ priv->tx_stats.data[3].limit = 1;
++ dev->queues = 4;
++ }
++}
++EXPORT_SYMBOL_GPL(p54_parse_firmware);
++
++static int p54_convert_rev0_to_rev1(struct ieee80211_hw *dev,
++ struct pda_pa_curve_data *curve_data)
++{
++ struct p54_common *priv = dev->priv;
++ struct pda_pa_curve_data_sample_rev1 *rev1;
++ struct pda_pa_curve_data_sample_rev0 *rev0;
++ size_t cd_len = sizeof(*curve_data) +
++ (curve_data->points_per_channel*sizeof(*rev1) + 2) *
++ curve_data->channels;
++ unsigned int i, j;
++ void *source, *target;
++
++ priv->curve_data = kmalloc(cd_len, GFP_KERNEL);
++ if (!priv->curve_data)
++ return -ENOMEM;
++
++ memcpy(priv->curve_data, curve_data, sizeof(*curve_data));
++ source = curve_data->data;
++ target = priv->curve_data->data;
++ for (i = 0; i < curve_data->channels; i++) {
++ __le16 *freq = source;
++ source += sizeof(__le16);
++ *((__le16 *)target) = *freq;
++ target += sizeof(__le16);
++ for (j = 0; j < curve_data->points_per_channel; j++) {
++ rev1 = target;
++ rev0 = source;
++
++ rev1->rf_power = rev0->rf_power;
++ rev1->pa_detector = rev0->pa_detector;
++ rev1->data_64qam = rev0->pcv;
++ /* "invent" the points for the other modulations */
++#define SUB(x,y) (u8)((x) - (y)) > (x) ? 0 : (x) - (y)
++ rev1->data_16qam = SUB(rev0->pcv, 12);
++ rev1->data_qpsk = SUB(rev1->data_16qam, 12);
++ rev1->data_bpsk = SUB(rev1->data_qpsk, 12);
++ rev1->data_barker= SUB(rev1->data_bpsk, 14);
++#undef SUB
++ target += sizeof(*rev1);
++ source += sizeof(*rev0);
++ }
++ }
++
++ return 0;
++}
++
++int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
++{
++ struct p54_common *priv = dev->priv;
++ struct eeprom_pda_wrap *wrap = NULL;
++ struct pda_entry *entry;
++ unsigned int data_len, entry_len;
++ void *tmp;
++ int err;
++ u8 *end = (u8 *)eeprom + len;
++
++ wrap = (struct eeprom_pda_wrap *) eeprom;
++ entry = (void *)wrap->data + le16_to_cpu(wrap->len);
++
++ /* verify that at least the entry length/code fits */
++ while ((u8 *)entry <= end - sizeof(*entry)) {
++ entry_len = le16_to_cpu(entry->len);
++ data_len = ((entry_len - 1) << 1);
++
++ /* abort if entry exceeds whole structure */
++ if ((u8 *)entry + sizeof(*entry) + data_len > end)
++ break;
++
++ switch (le16_to_cpu(entry->code)) {
++ case PDR_MAC_ADDRESS:
++ SET_IEEE80211_PERM_ADDR(dev, entry->data);
++ break;
++ case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS:
++ if (data_len < 2) {
++ err = -EINVAL;
++ goto err;
++ }
++
++ if (2 + entry->data[1]*sizeof(*priv->output_limit) > data_len) {
++ err = -EINVAL;
++ goto err;
++ }
++
++ priv->output_limit = kmalloc(entry->data[1] *
++ sizeof(*priv->output_limit), GFP_KERNEL);
++
++ if (!priv->output_limit) {
++ err = -ENOMEM;
++ goto err;
++ }
++
++ memcpy(priv->output_limit, &entry->data[2],
++ entry->data[1]*sizeof(*priv->output_limit));
++ priv->output_limit_len = entry->data[1];
++ break;
++ case PDR_PRISM_PA_CAL_CURVE_DATA:
++ if (data_len < sizeof(struct pda_pa_curve_data)) {
++ err = -EINVAL;
++ goto err;
++ }
++
++ if (((struct pda_pa_curve_data *)entry->data)->cal_method_rev) {
++ priv->curve_data = kmalloc(data_len, GFP_KERNEL);
++ if (!priv->curve_data) {
++ err = -ENOMEM;
++ goto err;
++ }
++
++ memcpy(priv->curve_data, entry->data, data_len);
++ } else {
++ err = p54_convert_rev0_to_rev1(dev, (struct pda_pa_curve_data *)entry->data);
++ if (err)
++ goto err;
++ }
++
++ break;
++ case PDR_PRISM_ZIF_TX_IQ_CALIBRATION:
++ priv->iq_autocal = kmalloc(data_len, GFP_KERNEL);
++ if (!priv->iq_autocal) {
++ err = -ENOMEM;
++ goto err;
++ }
++
++ memcpy(priv->iq_autocal, entry->data, data_len);
++ priv->iq_autocal_len = data_len / sizeof(struct pda_iq_autocal_entry);
++ break;
++ case PDR_INTERFACE_LIST:
++ tmp = entry->data;
++ while ((u8 *)tmp < entry->data + data_len) {
++ struct bootrec_exp_if *exp_if = tmp;
++ if (le16_to_cpu(exp_if->if_id) == 0xF)
++ priv->rxhw = exp_if->variant & cpu_to_le16(0x07);
++ tmp += sizeof(struct bootrec_exp_if);
++ }
++ break;
++ case PDR_HARDWARE_PLATFORM_COMPONENT_ID:
++ priv->version = *(u8 *)(entry->data + 1);
++ break;
++ case PDR_END:
++ /* make it overrun */
++ entry_len = len;
++ break;
++ default:
++ printk(KERN_INFO "p54: unknown eeprom code : 0x%x\n",
++ le16_to_cpu(entry->code));
++ break;
++ }
++
++ entry = (void *)entry + (entry_len + 1)*2;
++ }
++
++ if (!priv->iq_autocal || !priv->output_limit || !priv->curve_data) {
++ printk(KERN_ERR "p54: not all required entries found in eeprom!\n");
++ err = -EINVAL;
++ goto err;
++ }
++
++ return 0;
++
++ err:
++ if (priv->iq_autocal) {
++ kfree(priv->iq_autocal);
++ priv->iq_autocal = NULL;
++ }
++
++ if (priv->output_limit) {
++ kfree(priv->output_limit);
++ priv->output_limit = NULL;
++ }
++
++ if (priv->curve_data) {
++ kfree(priv->curve_data);
++ priv->curve_data = NULL;
++ }
++
++ printk(KERN_ERR "p54: eeprom parse failed!\n");
++ return err;
++}
++EXPORT_SYMBOL_GPL(p54_parse_eeprom);
++
++void p54_fill_eeprom_readback(struct p54_control_hdr *hdr)
++{
++ struct p54_eeprom_lm86 *eeprom_hdr;
++
++ hdr->magic1 = cpu_to_le16(0x8000);
++ hdr->len = cpu_to_le16(sizeof(*eeprom_hdr) + 0x2000);
++ hdr->type = cpu_to_le16(P54_CONTROL_TYPE_EEPROM_READBACK);
++ hdr->retry1 = hdr->retry2 = 0;
++ eeprom_hdr = (struct p54_eeprom_lm86 *) hdr->data;
++ eeprom_hdr->offset = 0x0;
++ eeprom_hdr->len = cpu_to_le16(0x2000);
++}
++EXPORT_SYMBOL_GPL(p54_fill_eeprom_readback);
++
++static void p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
++{
++ struct p54_rx_hdr *hdr = (struct p54_rx_hdr *) skb->data;
++ struct ieee80211_rx_status rx_status = {0};
++ u16 freq = le16_to_cpu(hdr->freq);
++
++ rx_status.ssi = hdr->rssi;
++ /* XX correct? */
++ rx_status.rate_idx = hdr->rate & 0xf;
++ rx_status.freq = freq;
++ rx_status.band = IEEE80211_BAND_2GHZ;
++ rx_status.antenna = hdr->antenna;
++ rx_status.mactime = le64_to_cpu(hdr->timestamp);
++ rx_status.flag |= RX_FLAG_TSFT;
++
++ skb_pull(skb, sizeof(*hdr));
++ skb_trim(skb, le16_to_cpu(hdr->len));
++
++ ieee80211_rx_irqsafe(dev, skb, &rx_status);
++}
++
++static void inline p54_wake_free_queues(struct ieee80211_hw *dev)
++{
++ struct p54_common *priv = dev->priv;
++ int i;
++
++ /* ieee80211_start_queues is great if all queues are really empty.
++ * But, what if some are full? */
++
++ for (i = 0; i < dev->queues; i++)
++ if (priv->tx_stats.data[i].len < priv->tx_stats.data[i].limit)
++ ieee80211_wake_queue(dev, i);
++}
++
++static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
++{
++ struct p54_common *priv = dev->priv;
++ struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
++ struct p54_frame_sent_hdr *payload = (struct p54_frame_sent_hdr *) hdr->data;
++ struct sk_buff *entry = (struct sk_buff *) priv->tx_queue.next;
++ u32 addr = le32_to_cpu(hdr->req_id) - 0x70;
++ struct memrecord *range = NULL;
++ u32 freed = 0;
++ u32 last_addr = priv->rx_start;
++
++ while (entry != (struct sk_buff *)&priv->tx_queue) {
++ range = (struct memrecord *)&entry->cb;
++ if (range->start_addr == addr) {
++ struct ieee80211_tx_status status;
++ struct p54_control_hdr *entry_hdr;
++ struct p54_tx_control_allocdata *entry_data;
++ int pad = 0;
++
++ if (entry->next != (struct sk_buff *)&priv->tx_queue)
++ freed = ((struct memrecord *)&entry->next->cb)->start_addr - last_addr;
++ else
++ freed = priv->rx_end - last_addr;
++
++ last_addr = range->end_addr;
++ __skb_unlink(entry, &priv->tx_queue);
++ if (!range->control) {
++ kfree_skb(entry);
++ break;
++ }
++ memset(&status, 0, sizeof(status));
++ memcpy(&status.control, range->control,
++ sizeof(status.control));
++ kfree(range->control);
++ priv->tx_stats.data[status.control.queue].len--;
++
++ entry_hdr = (struct p54_control_hdr *) entry->data;
++ entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data;
++ if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0)
++ pad = entry_data->align[0];
++
++ if (!(status.control.flags & IEEE80211_TXCTL_NO_ACK)) {
++ if (!(payload->status & 0x01))
++ status.flags |= IEEE80211_TX_STATUS_ACK;
++ else
++ status.excessive_retries = 1;
++ }
++ status.retry_count = payload->retries - 1;
++ status.ack_signal = le16_to_cpu(payload->ack_rssi);
++ skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data));
++ ieee80211_tx_status_irqsafe(dev, entry, &status);
++ break;
++ } else
++ last_addr = range->end_addr;
++ entry = entry->next;
++ }
++
++ if (freed >= IEEE80211_MAX_RTS_THRESHOLD + 0x170 +
++ sizeof(struct p54_control_hdr))
++ p54_wake_free_queues(dev);
++}
++
++static void p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb)
++{
++ struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
++
++ switch (le16_to_cpu(hdr->type)) {
++ case P54_CONTROL_TYPE_TXDONE:
++ p54_rx_frame_sent(dev, skb);
++ break;
++ case P54_CONTROL_TYPE_BBP:
++ break;
++ default:
++ printk(KERN_DEBUG "%s: not handling 0x%02x type control frame\n",
++ wiphy_name(dev->wiphy), le16_to_cpu(hdr->type));
++ break;
++ }
++}
++
++/* returns zero if skb can be reused */
++int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb)
++{
++ u8 type = le16_to_cpu(*((__le16 *)skb->data)) >> 8;
++ switch (type) {
++ case 0x00:
++ case 0x01:
++ p54_rx_data(dev, skb);
++ return -1;
++ case 0x4d:
++ /* TODO: do something better... but then again, I've never seen this happen */
++ printk(KERN_ERR "%s: Received fault. Probably need to restart hardware now..\n",
++ wiphy_name(dev->wiphy));
++ break;
++ case 0x80:
++ p54_rx_control(dev, skb);
++ break;
++ default:
++ printk(KERN_ERR "%s: unknown frame RXed (0x%02x)\n",
++ wiphy_name(dev->wiphy), type);
++ break;
++ }
++ return 0;
++}
++EXPORT_SYMBOL_GPL(p54_rx);
++
++/*
++ * So, the firmware is somewhat stupid and doesn't know what places in its
++ * memory incoming data should go to. By poking around in the firmware, we
++ * can find some unused memory to upload our packets to. However, data that we
++ * want the card to TX needs to stay intact until the card has told us that
++ * it is done with it. This function finds empty places we can upload to and
++ * marks allocated areas as reserved if necessary. p54_rx_frame_sent frees
++ * allocated areas.
++ */
++static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
++ struct p54_control_hdr *data, u32 len,
++ struct ieee80211_tx_control *control)
++{
++ struct p54_common *priv = dev->priv;
++ struct sk_buff *entry = priv->tx_queue.next;
++ struct sk_buff *target_skb = NULL;
++ struct memrecord *range;
++ u32 last_addr = priv->rx_start;
++ u32 largest_hole = 0;
++ u32 target_addr = priv->rx_start;
++ unsigned long flags;
++ unsigned int left;
++ len = (len + 0x170 + 3) & ~0x3; /* 0x70 headroom, 0x100 tailroom */
++
++ spin_lock_irqsave(&priv->tx_queue.lock, flags);
++ left = skb_queue_len(&priv->tx_queue);
++ while (left--) {
++ u32 hole_size;
++ range = (struct memrecord *)&entry->cb;
++ hole_size = range->start_addr - last_addr;
++ if (!target_skb && hole_size >= len) {
++ target_skb = entry->prev;
++ hole_size -= len;
++ target_addr = last_addr;
++ }
++ largest_hole = max(largest_hole, hole_size);
++ last_addr = range->end_addr;
++ entry = entry->next;
++ }
++ if (!target_skb && priv->rx_end - last_addr >= len) {
++ target_skb = priv->tx_queue.prev;
++ largest_hole = max(largest_hole, priv->rx_end - last_addr - len);
++ if (!skb_queue_empty(&priv->tx_queue)) {
++ range = (struct memrecord *)&target_skb->cb;
++ target_addr = range->end_addr;
++ }
++ } else
++ largest_hole = max(largest_hole, priv->rx_end - last_addr);
++
++ if (skb) {
++ range = (struct memrecord *)&skb->cb;
++ range->start_addr = target_addr;
++ range->end_addr = target_addr + len;
++ range->control = control;
++ __skb_queue_after(&priv->tx_queue, target_skb, skb);
++ if (largest_hole < IEEE80211_MAX_RTS_THRESHOLD + 0x170 +
++ sizeof(struct p54_control_hdr))
++ ieee80211_stop_queues(dev);
++ }
++ spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
++
++ data->req_id = cpu_to_le32(target_addr + 0x70);
++}
++
++static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
++ struct ieee80211_tx_control *control)
++{
++ struct ieee80211_tx_queue_stats_data *current_queue;
++ struct p54_common *priv = dev->priv;
++ struct p54_control_hdr *hdr;
++ struct p54_tx_control_allocdata *txhdr;
++ struct ieee80211_tx_control *control_copy;
++ size_t padding, len;
++ u8 rate;
++
++ current_queue = &priv->tx_stats.data[control->queue];
++ if (unlikely(current_queue->len > current_queue->limit))
++ return NETDEV_TX_BUSY;
++ current_queue->len++;
++ current_queue->count++;
++ if (current_queue->len == current_queue->limit)
++ ieee80211_stop_queue(dev, control->queue);
++
++ padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3;
++ len = skb->len;
++
++ control_copy = kmalloc(sizeof(*control), GFP_ATOMIC);
++ if (control_copy)
++ memcpy(control_copy, control, sizeof(*control));
++
++ txhdr = (struct p54_tx_control_allocdata *)
++ skb_push(skb, sizeof(*txhdr) + padding);
++ hdr = (struct p54_control_hdr *) skb_push(skb, sizeof(*hdr));
++
++ if (padding)
++ hdr->magic1 = cpu_to_le16(0x4010);
++ else
++ hdr->magic1 = cpu_to_le16(0x0010);
++ hdr->len = cpu_to_le16(len);
++ hdr->type = (control->flags & IEEE80211_TXCTL_NO_ACK) ? 0 : cpu_to_le16(1);
++ hdr->retry1 = hdr->retry2 = control->retry_limit;
++ p54_assign_address(dev, skb, hdr, skb->len, control_copy);
++
++ memset(txhdr->wep_key, 0x0, 16);
++ txhdr->padding = 0;
++ txhdr->padding2 = 0;
++
++ /* TODO: add support for alternate retry TX rates */
++ rate = control->tx_rate->hw_value;
++ if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE)
++ rate |= 0x10;
++ if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
++ rate |= 0x40;
++ else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
++ rate |= 0x20;
++ memset(txhdr->rateset, rate, 8);
++ txhdr->wep_key_present = 0;
++ txhdr->wep_key_len = 0;
++ txhdr->frame_type = cpu_to_le32(control->queue + 4);
++ txhdr->magic4 = 0;
++ txhdr->antenna = (control->antenna_sel_tx == 0) ?
++ 2 : control->antenna_sel_tx - 1;
++ txhdr->output_power = 0x7f; // HW Maximum
++ txhdr->magic5 = (control->flags & IEEE80211_TXCTL_NO_ACK) ?
++ 0 : ((rate > 0x3) ? cpu_to_le32(0x33) : cpu_to_le32(0x23));
++ if (padding)
++ txhdr->align[0] = padding;
++
++ priv->tx(dev, hdr, skb->len, 0);
++ return 0;
++}
++
++static int p54_set_filter(struct ieee80211_hw *dev, u16 filter_type,
++ const u8 *dst, const u8 *src, u8 antenna,
++ u32 magic3, u32 magic8, u32 magic9)
++{
++ struct p54_common *priv = dev->priv;
++ struct p54_control_hdr *hdr;
++ struct p54_tx_control_filter *filter;
++
++ hdr = kzalloc(sizeof(*hdr) + sizeof(*filter) +
++ priv->tx_hdr_len, GFP_ATOMIC);
++ if (!hdr)
++ return -ENOMEM;
++
++ hdr = (void *)hdr + priv->tx_hdr_len;
++
++ filter = (struct p54_tx_control_filter *) hdr->data;
++ hdr->magic1 = cpu_to_le16(0x8001);
++ hdr->len = cpu_to_le16(sizeof(*filter));
++ p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*filter), NULL);
++ hdr->type = cpu_to_le16(P54_CONTROL_TYPE_FILTER_SET);
++
++ filter->filter_type = cpu_to_le16(filter_type);
++ memcpy(filter->dst, dst, ETH_ALEN);
++ if (!src)
++ memset(filter->src, ~0, ETH_ALEN);
++ else
++ memcpy(filter->src, src, ETH_ALEN);
++ filter->antenna = antenna;
++ filter->magic3 = cpu_to_le32(magic3);
++ filter->rx_addr = cpu_to_le32(priv->rx_end);
++ filter->max_rx = cpu_to_le16(0x0620); /* FIXME: for usb ver 1.. maybe */
++ filter->rxhw = priv->rxhw;
++ filter->magic8 = cpu_to_le16(magic8);
++ filter->magic9 = cpu_to_le16(magic9);
++
++ priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*filter), 1);
++ return 0;
++}
++
++static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq)
++{
++ struct p54_common *priv = dev->priv;
++ struct p54_control_hdr *hdr;
++ struct p54_tx_control_channel *chan;
++ unsigned int i;
++ size_t payload_len = sizeof(*chan) + sizeof(u32)*2 +
++ sizeof(*chan->curve_data) *
++ priv->curve_data->points_per_channel;
++ void *entry;
++
++ hdr = kzalloc(sizeof(*hdr) + payload_len +
++ priv->tx_hdr_len, GFP_KERNEL);
++ if (!hdr)
++ return -ENOMEM;
++
++ hdr = (void *)hdr + priv->tx_hdr_len;
++
++ chan = (struct p54_tx_control_channel *) hdr->data;
++
++ hdr->magic1 = cpu_to_le16(0x8001);
++ hdr->len = cpu_to_le16(sizeof(*chan));
++ hdr->type = cpu_to_le16(P54_CONTROL_TYPE_CHANNEL_CHANGE);
++ p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + payload_len, NULL);
++
++ chan->magic1 = cpu_to_le16(0x1);
++ chan->magic2 = cpu_to_le16(0x0);
++
++ for (i = 0; i < priv->iq_autocal_len; i++) {
++ if (priv->iq_autocal[i].freq != freq)
++ continue;
++
++ memcpy(&chan->iq_autocal, &priv->iq_autocal[i],
++ sizeof(*priv->iq_autocal));
++ break;
++ }
++ if (i == priv->iq_autocal_len)
++ goto err;
++
++ for (i = 0; i < priv->output_limit_len; i++) {
++ if (priv->output_limit[i].freq != freq)
++ continue;
++
++ chan->val_barker = 0x38;
++ chan->val_bpsk = priv->output_limit[i].val_bpsk;
++ chan->val_qpsk = priv->output_limit[i].val_qpsk;
++ chan->val_16qam = priv->output_limit[i].val_16qam;
++ chan->val_64qam = priv->output_limit[i].val_64qam;
++ break;
++ }
++ if (i == priv->output_limit_len)
++ goto err;
++
++ chan->pa_points_per_curve = priv->curve_data->points_per_channel;
++
++ entry = priv->curve_data->data;
++ for (i = 0; i < priv->curve_data->channels; i++) {
++ if (*((__le16 *)entry) != freq) {
++ entry += sizeof(__le16);
++ entry += sizeof(struct pda_pa_curve_data_sample_rev1) *
++ chan->pa_points_per_curve;
++ continue;
++ }
++
++ entry += sizeof(__le16);
++ memcpy(chan->curve_data, entry, sizeof(*chan->curve_data) *
++ chan->pa_points_per_curve);
++ break;
++ }
++
++ memcpy(hdr->data + payload_len - 4, &chan->val_bpsk, 4);
++
++ priv->tx(dev, hdr, sizeof(*hdr) + payload_len, 1);
++ return 0;
++
++ err:
++ printk(KERN_ERR "%s: frequency change failed\n", wiphy_name(dev->wiphy));
++ kfree(hdr);
++ return -EINVAL;
++}
++
++static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act)
++{
++ struct p54_common *priv = dev->priv;
++ struct p54_control_hdr *hdr;
++ struct p54_tx_control_led *led;
++
++ hdr = kzalloc(sizeof(*hdr) + sizeof(*led) +
++ priv->tx_hdr_len, GFP_KERNEL);
++ if (!hdr)
++ return -ENOMEM;
++
++ hdr = (void *)hdr + priv->tx_hdr_len;
++ hdr->magic1 = cpu_to_le16(0x8001);
++ hdr->len = cpu_to_le16(sizeof(*led));
++ hdr->type = cpu_to_le16(P54_CONTROL_TYPE_LED);
++ p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*led), NULL);
++
++ led = (struct p54_tx_control_led *) hdr->data;
++ led->mode = cpu_to_le16(mode);
++ led->led_permanent = cpu_to_le16(link);
++ led->led_temporary = cpu_to_le16(act);
++ led->duration = cpu_to_le16(1000);
++
++ priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*led), 1);
++
++ return 0;
++}
++
++#define P54_SET_QUEUE(queue, ai_fs, cw_min, cw_max, _txop) \
++do { \
++ queue.aifs = cpu_to_le16(ai_fs); \
++ queue.cwmin = cpu_to_le16(cw_min); \
++ queue.cwmax = cpu_to_le16(cw_max); \
++ queue.txop = cpu_to_le16(_txop); \
++} while(0)
++
++static void p54_init_vdcf(struct ieee80211_hw *dev)
++{
++ struct p54_common *priv = dev->priv;
++ struct p54_control_hdr *hdr;
++ struct p54_tx_control_vdcf *vdcf;
++
++ /* all USB V1 adapters need a extra headroom */
++ hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len;
++ hdr->magic1 = cpu_to_le16(0x8001);
++ hdr->len = cpu_to_le16(sizeof(*vdcf));
++ hdr->type = cpu_to_le16(P54_CONTROL_TYPE_DCFINIT);
++ hdr->req_id = cpu_to_le32(priv->rx_start);
++
++ vdcf = (struct p54_tx_control_vdcf *) hdr->data;
++
++ P54_SET_QUEUE(vdcf->queue[0], 0x0002, 0x0003, 0x0007, 47);
++ P54_SET_QUEUE(vdcf->queue[1], 0x0002, 0x0007, 0x000f, 94);
++ P54_SET_QUEUE(vdcf->queue[2], 0x0003, 0x000f, 0x03ff, 0);
++ P54_SET_QUEUE(vdcf->queue[3], 0x0007, 0x000f, 0x03ff, 0);
++}
++
++static void p54_set_vdcf(struct ieee80211_hw *dev)
++{
++ struct p54_common *priv = dev->priv;
++ struct p54_control_hdr *hdr;
++ struct p54_tx_control_vdcf *vdcf;
++
++ hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len;
++
++ p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*vdcf), NULL);
++
++ vdcf = (struct p54_tx_control_vdcf *) hdr->data;
++
++ if (dev->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
++ vdcf->slottime = 9;
++ vdcf->magic1 = 0x00;
++ vdcf->magic2 = 0x10;
++ } else {
++ vdcf->slottime = 20;
++ vdcf->magic1 = 0x0a;
++ vdcf->magic2 = 0x06;
++ }
++
++ /* (see prism54/isl_oid.h for further details) */
++ vdcf->frameburst = cpu_to_le16(0);
++
++ priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*vdcf), 0);
++}
++
++static int p54_start(struct ieee80211_hw *dev)
++{
++ struct p54_common *priv = dev->priv;
++ int err;
++
++ err = priv->open(dev);
++ if (!err)
++ priv->mode = IEEE80211_IF_TYPE_MNTR;
++
++ return err;
++}
++
++static void p54_stop(struct ieee80211_hw *dev)
++{
++ struct p54_common *priv = dev->priv;
++ struct sk_buff *skb;
++ while ((skb = skb_dequeue(&priv->tx_queue))) {
++ struct memrecord *range = (struct memrecord *)&skb->cb;
++ if (range->control)
++ kfree(range->control);
++ kfree_skb(skb);
++ }
++ priv->stop(dev);
++ priv->mode = IEEE80211_IF_TYPE_INVALID;
++}
++
++static int p54_add_interface(struct ieee80211_hw *dev,
++ struct ieee80211_if_init_conf *conf)
++{
++ struct p54_common *priv = dev->priv;
++
++ if (priv->mode != IEEE80211_IF_TYPE_MNTR)
++ return -EOPNOTSUPP;
++
++ switch (conf->type) {
++ case IEEE80211_IF_TYPE_STA:
++ priv->mode = conf->type;
++ break;
++ default:
++ return -EOPNOTSUPP;
++ }
++
++ memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
++
++ p54_set_filter(dev, 0, priv->mac_addr, NULL, 0, 1, 0, 0xF642);
++ p54_set_filter(dev, 0, priv->mac_addr, NULL, 1, 0, 0, 0xF642);
++
++ switch (conf->type) {
++ case IEEE80211_IF_TYPE_STA:
++ p54_set_filter(dev, 1, priv->mac_addr, NULL, 0, 0x15F, 0x1F4, 0);
++ break;
++ default:
++ BUG(); /* impossible */
++ break;
++ }
++
++ p54_set_leds(dev, 1, 0, 0);
++
++ return 0;
++}
++
++static void p54_remove_interface(struct ieee80211_hw *dev,
++ struct ieee80211_if_init_conf *conf)
++{
++ struct p54_common *priv = dev->priv;
++ priv->mode = IEEE80211_IF_TYPE_MNTR;
++ memset(priv->mac_addr, 0, ETH_ALEN);
++ p54_set_filter(dev, 0, priv->mac_addr, NULL, 2, 0, 0, 0);
++}
++
++static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
++{
++ int ret;
++
++ ret = p54_set_freq(dev, cpu_to_le16(conf->channel->center_freq));
++ p54_set_vdcf(dev);
++ return ret;
++}
++
++static int p54_config_interface(struct ieee80211_hw *dev,
++ struct ieee80211_vif *vif,
++ struct ieee80211_if_conf *conf)
++{
++ struct p54_common *priv = dev->priv;
++
++ p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 0, 1, 0, 0xF642);
++ p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 2, 0, 0, 0);
++ p54_set_leds(dev, 1, !is_multicast_ether_addr(conf->bssid), 0);
++ memcpy(priv->bssid, conf->bssid, ETH_ALEN);
++ return 0;
++}
++
++static void p54_configure_filter(struct ieee80211_hw *dev,
++ unsigned int changed_flags,
++ unsigned int *total_flags,
++ int mc_count, struct dev_mc_list *mclist)
++{
++ struct p54_common *priv = dev->priv;
++
++ *total_flags &= FIF_BCN_PRBRESP_PROMISC;
++
++ if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
++ if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
++ p54_set_filter(dev, 0, priv->mac_addr,
++ NULL, 2, 0, 0, 0);
++ else
++ p54_set_filter(dev, 0, priv->mac_addr,
++ priv->bssid, 2, 0, 0, 0);
++ }
++}
++
++static int p54_conf_tx(struct ieee80211_hw *dev, int queue,
++ const struct ieee80211_tx_queue_params *params)
++{
++ struct p54_common *priv = dev->priv;
++ struct p54_tx_control_vdcf *vdcf;
++
++ vdcf = (struct p54_tx_control_vdcf *)(((struct p54_control_hdr *)
++ ((void *)priv->cached_vdcf + priv->tx_hdr_len))->data);
++
++ if ((params) && !((queue < 0) || (queue > 4))) {
++ P54_SET_QUEUE(vdcf->queue[queue], params->aifs,
++ params->cw_min, params->cw_max, params->txop);
++ } else
++ return -EINVAL;
++
++ p54_set_vdcf(dev);
++
++ return 0;
++}
++
++static int p54_get_stats(struct ieee80211_hw *dev,
++ struct ieee80211_low_level_stats *stats)
++{
++ /* TODO */
++ return 0;
++}
++
++static int p54_get_tx_stats(struct ieee80211_hw *dev,
++ struct ieee80211_tx_queue_stats *stats)
++{
++ struct p54_common *priv = dev->priv;
++ unsigned int i;
++
++ for (i = 0; i < dev->queues; i++)
++ memcpy(&stats->data[i], &priv->tx_stats.data[i],
++ sizeof(stats->data[i]));
++
++ return 0;
++}
++
++static const struct ieee80211_ops p54_ops = {
++ .tx = p54_tx,
++ .start = p54_start,
++ .stop = p54_stop,
++ .add_interface = p54_add_interface,
++ .remove_interface = p54_remove_interface,
++ .config = p54_config,
++ .config_interface = p54_config_interface,
++ .configure_filter = p54_configure_filter,
++ .conf_tx = p54_conf_tx,
++ .get_stats = p54_get_stats,
++ .get_tx_stats = p54_get_tx_stats
++};
++
++struct ieee80211_hw *p54_init_common(size_t priv_data_len)
++{
++ struct ieee80211_hw *dev;
++ struct p54_common *priv;
++
++ dev = ieee80211_alloc_hw(priv_data_len, &p54_ops);
++ if (!dev)
++ return NULL;
++
++ priv = dev->priv;
++ priv->mode = IEEE80211_IF_TYPE_INVALID;
++ skb_queue_head_init(&priv->tx_queue);
++ dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz;
++ dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */
++ IEEE80211_HW_RX_INCLUDES_FCS;
++ dev->channel_change_time = 1000; /* TODO: find actual value */
++ dev->max_rssi = 127;
++
++ priv->tx_stats.data[0].limit = 5;
++ dev->queues = 1;
++
++ dev->extra_tx_headroom = sizeof(struct p54_control_hdr) + 4 +
++ sizeof(struct p54_tx_control_allocdata);
++
++ priv->cached_vdcf = kzalloc(sizeof(struct p54_tx_control_vdcf) +
++ priv->tx_hdr_len + sizeof(struct p54_control_hdr), GFP_KERNEL);
++
++ if (!priv->cached_vdcf) {
++ ieee80211_free_hw(dev);
++ return NULL;
++ }
++
++ p54_init_vdcf(dev);
++
++ return dev;
++}
++EXPORT_SYMBOL_GPL(p54_init_common);
++
++void p54_free_common(struct ieee80211_hw *dev)
++{
++ struct p54_common *priv = dev->priv;
++ kfree(priv->iq_autocal);
++ kfree(priv->output_limit);
++ kfree(priv->curve_data);
++ kfree(priv->cached_vdcf);
++}
++EXPORT_SYMBOL_GPL(p54_free_common);
++
++static int __init p54_init(void)
++{
++ return 0;
++}
++
++static void __exit p54_exit(void)
++{
++}
++
++module_init(p54_init);
++module_exit(p54_exit);
+diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h
+new file mode 100644
+index 0000000..c15b56e
+--- /dev/null
++++ b/drivers/net/wireless/p54/p54common.h
+@@ -0,0 +1,254 @@
++#ifndef PRISM54COMMON_H
++#define PRISM54COMMON_H
++
++/*
++ * Common code specific definitions for mac80211 Prism54 drivers
++ *
++ * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
++ * Copyright (c) 2007, Christian Lamparter <chunkeey at web.de>
++ *
++ * Based on the islsm (softmac prism54) driver, which is:
++ * Copyright 2004-2006 Jean-Baptiste Note <jbnote at gmail.com>, et al.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++struct bootrec {
++ __le32 code;
++ __le32 len;
++ u32 data[0];
++} __attribute__((packed));
++
++struct bootrec_exp_if {
++ __le16 role;
++ __le16 if_id;
++ __le16 variant;
++ __le16 btm_compat;
++ __le16 top_compat;
++} __attribute__((packed));
++
++#define BR_CODE_MIN 0x80000000
++#define BR_CODE_COMPONENT_ID 0x80000001
++#define BR_CODE_COMPONENT_VERSION 0x80000002
++#define BR_CODE_DEPENDENT_IF 0x80000003
++#define BR_CODE_EXPOSED_IF 0x80000004
++#define BR_CODE_DESCR 0x80000101
++#define BR_CODE_MAX 0x8FFFFFFF
++#define BR_CODE_END_OF_BRA 0xFF0000FF
++#define LEGACY_BR_CODE_END_OF_BRA 0xFFFFFFFF
++
++#define FW_FMAC 0x464d4143
++#define FW_LM86 0x4c4d3836
++#define FW_LM87 0x4c4d3837
++#define FW_LM20 0x4c4d3230
++
++/* PDA defines are Copyright (C) 2005 Nokia Corporation (taken from islsm_pda.h) */
++
++struct pda_entry {
++ __le16 len; /* includes both code and data */
++ __le16 code;
++ u8 data[0];
++} __attribute__ ((packed));
++
++struct eeprom_pda_wrap {
++ __le32 magic;
++ __le16 pad;
++ __le16 len;
++ __le32 arm_opcode;
++ u8 data[0];
++} __attribute__ ((packed));
++
++struct pda_iq_autocal_entry {
++ __le16 freq;
++ __le16 iq_param[4];
++} __attribute__ ((packed));
++
++struct pda_channel_output_limit {
++ __le16 freq;
++ u8 val_bpsk;
++ u8 val_qpsk;
++ u8 val_16qam;
++ u8 val_64qam;
++ u8 rate_set_mask;
++ u8 rate_set_size;
++} __attribute__ ((packed));
++
++struct pda_pa_curve_data_sample_rev0 {
++ u8 rf_power;
++ u8 pa_detector;
++ u8 pcv;
++} __attribute__ ((packed));
++
++struct pda_pa_curve_data_sample_rev1 {
++ u8 rf_power;
++ u8 pa_detector;
++ u8 data_barker;
++ u8 data_bpsk;
++ u8 data_qpsk;
++ u8 data_16qam;
++ u8 data_64qam;
++ u8 padding;
++} __attribute__ ((packed));
++
++struct pda_pa_curve_data {
++ u8 cal_method_rev;
++ u8 channels;
++ u8 points_per_channel;
++ u8 padding;
++ u8 data[0];
++} __attribute__ ((packed));
++
++/*
++ * this defines the PDR codes used to build PDAs as defined in document
++ * number 553155. The current implementation mirrors version 1.1 of the
++ * document and lists only PDRs supported by the ARM platform.
++ */
++
++/* common and choice range (0x0000 - 0x0fff) */
++#define PDR_END 0x0000
++#define PDR_MANUFACTURING_PART_NUMBER 0x0001
++#define PDR_PDA_VERSION 0x0002
++#define PDR_NIC_SERIAL_NUMBER 0x0003
++
++#define PDR_MAC_ADDRESS 0x0101
++#define PDR_REGULATORY_DOMAIN_LIST 0x0103
++#define PDR_TEMPERATURE_TYPE 0x0107
++
++#define PDR_PRISM_PCI_IDENTIFIER 0x0402
++
++/* ARM range (0x1000 - 0x1fff) */
++#define PDR_COUNTRY_INFORMATION 0x1000
++#define PDR_INTERFACE_LIST 0x1001
++#define PDR_HARDWARE_PLATFORM_COMPONENT_ID 0x1002
++#define PDR_OEM_NAME 0x1003
++#define PDR_PRODUCT_NAME 0x1004
++#define PDR_UTF8_OEM_NAME 0x1005
++#define PDR_UTF8_PRODUCT_NAME 0x1006
++#define PDR_COUNTRY_LIST 0x1007
++#define PDR_DEFAULT_COUNTRY 0x1008
++
++#define PDR_ANTENNA_GAIN 0x1100
++
++#define PDR_PRISM_INDIGO_PA_CALIBRATION_DATA 0x1901
++#define PDR_RSSI_LINEAR_APPROXIMATION 0x1902
++#define PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS 0x1903
++#define PDR_PRISM_PA_CAL_CURVE_DATA 0x1904
++#define PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND 0x1905
++#define PDR_PRISM_ZIF_TX_IQ_CALIBRATION 0x1906
++#define PDR_REGULATORY_POWER_LIMITS 0x1907
++#define PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED 0x1908
++#define PDR_RADIATED_TRANSMISSION_CORRECTION 0x1909
++#define PDR_PRISM_TX_IQ_CALIBRATION 0x190a
++
++/* reserved range (0x2000 - 0x7fff) */
++
++/* customer range (0x8000 - 0xffff) */
++#define PDR_BASEBAND_REGISTERS 0x8000
++#define PDR_PER_CHANNEL_BASEBAND_REGISTERS 0x8001
++
++/* stored in skb->cb */
++struct memrecord {
++ u32 start_addr;
++ u32 end_addr;
++ struct ieee80211_tx_control *control;
++};
++
++struct p54_eeprom_lm86 {
++ __le16 offset;
++ __le16 len;
++ u8 data[0];
++} __attribute__ ((packed));
++
++struct p54_rx_hdr {
++ __le16 magic;
++ __le16 len;
++ __le16 freq;
++ u8 antenna;
++ u8 rate;
++ u8 rssi;
++ u8 quality;
++ u16 unknown2;
++ __le64 timestamp;
++ u8 data[0];
++} __attribute__ ((packed));
++
++struct p54_frame_sent_hdr {
++ u8 status;
++ u8 retries;
++ __le16 ack_rssi;
++ __le16 seq;
++ u16 rate;
++} __attribute__ ((packed));
++
++struct p54_tx_control_allocdata {
++ u8 rateset[8];
++ u16 padding;
++ u8 wep_key_present;
++ u8 wep_key_len;
++ u8 wep_key[16];
++ __le32 frame_type;
++ u32 padding2;
++ __le16 magic4;
++ u8 antenna;
++ u8 output_power;
++ __le32 magic5;
++ u8 align[0];
++} __attribute__ ((packed));
++
++struct p54_tx_control_filter {
++ __le16 filter_type;
++ u8 dst[ETH_ALEN];
++ u8 src[ETH_ALEN];
++ u8 antenna;
++ u8 debug;
++ __le32 magic3;
++ u8 rates[8]; // FIXME: what's this for?
++ __le32 rx_addr;
++ __le16 max_rx;
++ __le16 rxhw;
++ __le16 magic8;
++ __le16 magic9;
++} __attribute__ ((packed));
++
++struct p54_tx_control_channel {
++ __le16 magic1;
++ __le16 magic2;
++ u8 padding1[20];
++ struct pda_iq_autocal_entry iq_autocal;
++ u8 pa_points_per_curve;
++ u8 val_barker;
++ u8 val_bpsk;
++ u8 val_qpsk;
++ u8 val_16qam;
++ u8 val_64qam;
++ struct pda_pa_curve_data_sample_rev1 curve_data[0];
++ /* additional padding/data after curve_data */
++} __attribute__ ((packed));
++
++struct p54_tx_control_led {
++ __le16 mode;
++ __le16 led_temporary;
++ __le16 led_permanent;
++ __le16 duration;
++} __attribute__ ((packed));
++
++struct p54_tx_vdcf_queues {
++ __le16 aifs;
++ __le16 cwmin;
++ __le16 cwmax;
++ __le16 txop;
++} __attribute__ ((packed));
++
++struct p54_tx_control_vdcf {
++ u8 padding;
++ u8 slottime;
++ u8 magic1;
++ u8 magic2;
++ struct p54_tx_vdcf_queues queue[8];
++ u8 pad2[4];
++ __le16 frameburst;
++} __attribute__ ((packed));
++
++#endif /* PRISM54COMMON_H */
+diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c
+new file mode 100644
+index 0000000..fa52772
+--- /dev/null
++++ b/drivers/net/wireless/p54/p54pci.c
+@@ -0,0 +1,697 @@
++
++/*
++ * Linux device driver for PCI based Prism54
++ *
++ * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
++ *
++ * Based on the islsm (softmac prism54) driver, which is:
++ * Copyright 2004-2006 Jean-Baptiste Note <jean-baptiste.note at m4x.org>, et al.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/init.h>
++#include <linux/pci.h>
++#include <linux/firmware.h>
++#include <linux/etherdevice.h>
++#include <linux/delay.h>
++#include <linux/completion.h>
++#include <net/mac80211.h>
++
++#include "p54.h"
++#include "p54pci.h"
++
++MODULE_AUTHOR("Michael Wu <flamingice at sourmilk.net>");
++MODULE_DESCRIPTION("Prism54 PCI wireless driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("prism54pci");
++
++static struct pci_device_id p54p_table[] __devinitdata = {
++ /* Intersil PRISM Duette/Prism GT Wireless LAN adapter */
++ { PCI_DEVICE(0x1260, 0x3890) },
++ /* 3COM 3CRWE154G72 Wireless LAN adapter */
++ { PCI_DEVICE(0x10b7, 0x6001) },
++ /* Intersil PRISM Indigo Wireless LAN adapter */
++ { PCI_DEVICE(0x1260, 0x3877) },
++ /* Intersil PRISM Javelin/Xbow Wireless LAN adapter */
++ { PCI_DEVICE(0x1260, 0x3886) },
++ { },
++};
++
++MODULE_DEVICE_TABLE(pci, p54p_table);
++
++static int p54p_upload_firmware(struct ieee80211_hw *dev)
++{
++ struct p54p_priv *priv = dev->priv;
++ const struct firmware *fw_entry = NULL;
++ __le32 reg;
++ int err;
++ __le32 *data;
++ u32 remains, left, device_addr;
++
++ P54P_WRITE(int_enable, cpu_to_le32(0));
++ P54P_READ(int_enable);
++ udelay(10);
++
++ reg = P54P_READ(ctrl_stat);
++ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
++ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT);
++ P54P_WRITE(ctrl_stat, reg);
++ P54P_READ(ctrl_stat);
++ udelay(10);
++
++ reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
++ P54P_WRITE(ctrl_stat, reg);
++ wmb();
++ udelay(10);
++
++ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
++ P54P_WRITE(ctrl_stat, reg);
++ wmb();
++
++ mdelay(50);
++
++ err = request_firmware(&fw_entry, "isl3886", &priv->pdev->dev);
++ if (err) {
++ printk(KERN_ERR "%s (prism54pci): cannot find firmware "
++ "(isl3886)\n", pci_name(priv->pdev));
++ return err;
++ }
++
++ p54_parse_firmware(dev, fw_entry);
++
++ data = (__le32 *) fw_entry->data;
++ remains = fw_entry->size;
++ device_addr = ISL38XX_DEV_FIRMWARE_ADDR;
++ while (remains) {
++ u32 i = 0;
++ left = min((u32)0x1000, remains);
++ P54P_WRITE(direct_mem_base, cpu_to_le32(device_addr));
++ P54P_READ(int_enable);
++
++ device_addr += 0x1000;
++ while (i < left) {
++ P54P_WRITE(direct_mem_win[i], *data++);
++ i += sizeof(u32);
++ }
++
++ remains -= left;
++ P54P_READ(int_enable);
++ }
++
++ release_firmware(fw_entry);
++
++ reg = P54P_READ(ctrl_stat);
++ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
++ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
++ reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT);
++ P54P_WRITE(ctrl_stat, reg);
++ P54P_READ(ctrl_stat);
++ udelay(10);
++
++ reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
++ P54P_WRITE(ctrl_stat, reg);
++ wmb();
++ udelay(10);
++
++ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
++ P54P_WRITE(ctrl_stat, reg);
++ wmb();
++ udelay(10);
++
++ return 0;
++}
++
++static irqreturn_t p54p_simple_interrupt(int irq, void *dev_id)
++{
++ struct p54p_priv *priv = (struct p54p_priv *) dev_id;
++ __le32 reg;
++
++ reg = P54P_READ(int_ident);
++ P54P_WRITE(int_ack, reg);
++
++ if (reg & P54P_READ(int_enable))
++ complete(&priv->boot_comp);
++
++ return IRQ_HANDLED;
++}
++
++static int p54p_read_eeprom(struct ieee80211_hw *dev)
++{
++ struct p54p_priv *priv = dev->priv;
++ struct p54p_ring_control *ring_control = priv->ring_control;
++ int err;
++ struct p54_control_hdr *hdr;
++ void *eeprom;
++ dma_addr_t rx_mapping, tx_mapping;
++ u16 alen;
++
++ init_completion(&priv->boot_comp);
++ err = request_irq(priv->pdev->irq, &p54p_simple_interrupt,
++ IRQF_SHARED, "prism54pci", priv);
++ if (err) {
++ printk(KERN_ERR "%s (prism54pci): failed to register IRQ handler\n",
++ pci_name(priv->pdev));
++ return err;
++ }
++
++ eeprom = kmalloc(0x2010 + EEPROM_READBACK_LEN, GFP_KERNEL);
++ if (!eeprom) {
++ printk(KERN_ERR "%s (prism54pci): no memory for eeprom!\n",
++ pci_name(priv->pdev));
++ err = -ENOMEM;
++ goto out;
++ }
++
++ memset(ring_control, 0, sizeof(*ring_control));
++ P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma));
++ P54P_READ(ring_control_base);
++ udelay(10);
++
++ P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_INIT));
++ P54P_READ(int_enable);
++ udelay(10);
++
++ P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
++
++ if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) {
++ printk(KERN_ERR "%s (prism54pci): Cannot boot firmware!\n",
++ pci_name(priv->pdev));
++ err = -EINVAL;
++ goto out;
++ }
++
++ P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_UPDATE));
++ P54P_READ(int_enable);
++
++ hdr = eeprom + 0x2010;
++ p54_fill_eeprom_readback(hdr);
++ hdr->req_id = cpu_to_le32(priv->common.rx_start);
++
++ rx_mapping = pci_map_single(priv->pdev, eeprom,
++ 0x2010, PCI_DMA_FROMDEVICE);
++ tx_mapping = pci_map_single(priv->pdev, (void *)hdr,
++ EEPROM_READBACK_LEN, PCI_DMA_TODEVICE);
++
++ ring_control->rx_mgmt[0].host_addr = cpu_to_le32(rx_mapping);
++ ring_control->rx_mgmt[0].len = cpu_to_le16(0x2010);
++ ring_control->tx_data[0].host_addr = cpu_to_le32(tx_mapping);
++ ring_control->tx_data[0].device_addr = hdr->req_id;
++ ring_control->tx_data[0].len = cpu_to_le16(EEPROM_READBACK_LEN);
++
++ ring_control->host_idx[2] = cpu_to_le32(1);
++ ring_control->host_idx[1] = cpu_to_le32(1);
++
++ wmb();
++ mdelay(100);
++ P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
++
++ wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ);
++ wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ);
++
++ pci_unmap_single(priv->pdev, tx_mapping,
++ EEPROM_READBACK_LEN, PCI_DMA_TODEVICE);
++ pci_unmap_single(priv->pdev, rx_mapping,
++ 0x2010, PCI_DMA_FROMDEVICE);
++
++ alen = le16_to_cpu(ring_control->rx_mgmt[0].len);
++ if (le32_to_cpu(ring_control->device_idx[2]) != 1 ||
++ alen < 0x10) {
++ printk(KERN_ERR "%s (prism54pci): Cannot read eeprom!\n",
++ pci_name(priv->pdev));
++ err = -EINVAL;
++ goto out;
++ }
++
++ p54_parse_eeprom(dev, (u8 *)eeprom + 0x10, alen - 0x10);
++
++ out:
++ kfree(eeprom);
++ P54P_WRITE(int_enable, cpu_to_le32(0));
++ P54P_READ(int_enable);
++ udelay(10);
++ free_irq(priv->pdev->irq, priv);
++ P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
++ return err;
++}
++
++static void p54p_refill_rx_ring(struct ieee80211_hw *dev)
++{
++ struct p54p_priv *priv = dev->priv;
++ struct p54p_ring_control *ring_control = priv->ring_control;
++ u32 limit, host_idx, idx;
++
++ host_idx = le32_to_cpu(ring_control->host_idx[0]);
++ limit = host_idx;
++ limit -= le32_to_cpu(ring_control->device_idx[0]);
++ limit = ARRAY_SIZE(ring_control->rx_data) - limit;
++
++ idx = host_idx % ARRAY_SIZE(ring_control->rx_data);
++ while (limit-- > 1) {
++ struct p54p_desc *desc = &ring_control->rx_data[idx];
++
++ if (!desc->host_addr) {
++ struct sk_buff *skb;
++ dma_addr_t mapping;
++ skb = dev_alloc_skb(MAX_RX_SIZE);
++ if (!skb)
++ break;
++
++ mapping = pci_map_single(priv->pdev,
++ skb_tail_pointer(skb),
++ MAX_RX_SIZE,
++ PCI_DMA_FROMDEVICE);
++ desc->host_addr = cpu_to_le32(mapping);
++ desc->device_addr = 0; // FIXME: necessary?
++ desc->len = cpu_to_le16(MAX_RX_SIZE);
++ desc->flags = 0;
++ priv->rx_buf[idx] = skb;
++ }
++
++ idx++;
++ host_idx++;
++ idx %= ARRAY_SIZE(ring_control->rx_data);
++ }
++
++ wmb();
++ ring_control->host_idx[0] = cpu_to_le32(host_idx);
++}
++
++static irqreturn_t p54p_interrupt(int irq, void *dev_id)
++{
++ struct ieee80211_hw *dev = dev_id;
++ struct p54p_priv *priv = dev->priv;
++ struct p54p_ring_control *ring_control = priv->ring_control;
++ __le32 reg;
++
++ spin_lock(&priv->lock);
++ reg = P54P_READ(int_ident);
++ if (unlikely(reg == cpu_to_le32(0xFFFFFFFF))) {
++ spin_unlock(&priv->lock);
++ return IRQ_HANDLED;
++ }
++
++ P54P_WRITE(int_ack, reg);
++
++ reg &= P54P_READ(int_enable);
++
++ if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)) {
++ struct p54p_desc *desc;
++ u32 idx, i;
++ i = priv->tx_idx;
++ i %= ARRAY_SIZE(ring_control->tx_data);
++ priv->tx_idx = idx = le32_to_cpu(ring_control->device_idx[1]);
++ idx %= ARRAY_SIZE(ring_control->tx_data);
++
++ while (i != idx) {
++ desc = &ring_control->tx_data[i];
++ if (priv->tx_buf[i]) {
++ kfree(priv->tx_buf[i]);
++ priv->tx_buf[i] = NULL;
++ }
++
++ pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
++ le16_to_cpu(desc->len), PCI_DMA_TODEVICE);
++
++ desc->host_addr = 0;
++ desc->device_addr = 0;
++ desc->len = 0;
++ desc->flags = 0;
++
++ i++;
++ i %= ARRAY_SIZE(ring_control->tx_data);
++ }
++
++ i = priv->rx_idx;
++ i %= ARRAY_SIZE(ring_control->rx_data);
++ priv->rx_idx = idx = le32_to_cpu(ring_control->device_idx[0]);
++ idx %= ARRAY_SIZE(ring_control->rx_data);
++ while (i != idx) {
++ u16 len;
++ struct sk_buff *skb;
++ desc = &ring_control->rx_data[i];
++ len = le16_to_cpu(desc->len);
++ skb = priv->rx_buf[i];
++
++ skb_put(skb, len);
++
++ if (p54_rx(dev, skb)) {
++ pci_unmap_single(priv->pdev,
++ le32_to_cpu(desc->host_addr),
++ MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
++
++ priv->rx_buf[i] = NULL;
++ desc->host_addr = 0;
++ } else {
++ skb_trim(skb, 0);
++ desc->len = cpu_to_le16(MAX_RX_SIZE);
++ }
++
++ i++;
++ i %= ARRAY_SIZE(ring_control->rx_data);
++ }
++
++ p54p_refill_rx_ring(dev);
++
++ wmb();
++ P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
++ } else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT))
++ complete(&priv->boot_comp);
++
++ spin_unlock(&priv->lock);
++
++ return reg ? IRQ_HANDLED : IRQ_NONE;
++}
++
++static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data,
++ size_t len, int free_on_tx)
++{
++ struct p54p_priv *priv = dev->priv;
++ struct p54p_ring_control *ring_control = priv->ring_control;
++ unsigned long flags;
++ struct p54p_desc *desc;
++ dma_addr_t mapping;
++ u32 device_idx, idx, i;
++
++ spin_lock_irqsave(&priv->lock, flags);
++
++ device_idx = le32_to_cpu(ring_control->device_idx[1]);
++ idx = le32_to_cpu(ring_control->host_idx[1]);
++ i = idx % ARRAY_SIZE(ring_control->tx_data);
++
++ mapping = pci_map_single(priv->pdev, data, len, PCI_DMA_TODEVICE);
++ desc = &ring_control->tx_data[i];
++ desc->host_addr = cpu_to_le32(mapping);
++ desc->device_addr = data->req_id;
++ desc->len = cpu_to_le16(len);
++ desc->flags = 0;
++
++ wmb();
++ ring_control->host_idx[1] = cpu_to_le32(idx + 1);
++
++ if (free_on_tx)
++ priv->tx_buf[i] = data;
++
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
++ P54P_READ(dev_int);
++
++ /* FIXME: unlikely to happen because the device usually runs out of
++ memory before we fill the ring up, but we can make it impossible */
++ if (idx - device_idx > ARRAY_SIZE(ring_control->tx_data) - 2)
++ printk(KERN_INFO "%s: tx overflow.\n", wiphy_name(dev->wiphy));
++}
++
++static int p54p_open(struct ieee80211_hw *dev)
++{
++ struct p54p_priv *priv = dev->priv;
++ int err;
++
++ init_completion(&priv->boot_comp);
++ err = request_irq(priv->pdev->irq, &p54p_interrupt,
++ IRQF_SHARED, "prism54pci", dev);
++ if (err) {
++ printk(KERN_ERR "%s: failed to register IRQ handler\n",
++ wiphy_name(dev->wiphy));
++ return err;
++ }
++
++ memset(priv->ring_control, 0, sizeof(*priv->ring_control));
++ priv->rx_idx = priv->tx_idx = 0;
++ p54p_refill_rx_ring(dev);
++
++ p54p_upload_firmware(dev);
++
++ P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma));
++ P54P_READ(ring_control_base);
++ wmb();
++ udelay(10);
++
++ P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_INIT));
++ P54P_READ(int_enable);
++ wmb();
++ udelay(10);
++
++ P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
++ P54P_READ(dev_int);
++
++ if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) {
++ printk(KERN_ERR "%s: Cannot boot firmware!\n",
++ wiphy_name(dev->wiphy));
++ free_irq(priv->pdev->irq, dev);
++ return -ETIMEDOUT;
++ }
++
++ P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_UPDATE));
++ P54P_READ(int_enable);
++ wmb();
++ udelay(10);
++
++ P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
++ P54P_READ(dev_int);
++ wmb();
++ udelay(10);
++
++ return 0;
++}
++
++static void p54p_stop(struct ieee80211_hw *dev)
++{
++ struct p54p_priv *priv = dev->priv;
++ struct p54p_ring_control *ring_control = priv->ring_control;
++ unsigned int i;
++ struct p54p_desc *desc;
++
++ P54P_WRITE(int_enable, cpu_to_le32(0));
++ P54P_READ(int_enable);
++ udelay(10);
++
++ free_irq(priv->pdev->irq, dev);
++
++ P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
++
++ for (i = 0; i < ARRAY_SIZE(priv->rx_buf); i++) {
++ desc = &ring_control->rx_data[i];
++ if (desc->host_addr)
++ pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
++ MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
++ kfree_skb(priv->rx_buf[i]);
++ priv->rx_buf[i] = NULL;
++ }
++
++ for (i = 0; i < ARRAY_SIZE(priv->tx_buf); i++) {
++ desc = &ring_control->tx_data[i];
++ if (desc->host_addr)
++ pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
++ le16_to_cpu(desc->len), PCI_DMA_TODEVICE);
++
++ kfree(priv->tx_buf[i]);
++ priv->tx_buf[i] = NULL;
++ }
++
++ memset(ring_control, 0, sizeof(ring_control));
++}
++
++static int __devinit p54p_probe(struct pci_dev *pdev,
++ const struct pci_device_id *id)
++{
++ struct p54p_priv *priv;
++ struct ieee80211_hw *dev;
++ unsigned long mem_addr, mem_len;
++ int err;
++ DECLARE_MAC_BUF(mac);
++
++ err = pci_enable_device(pdev);
++ if (err) {
++ printk(KERN_ERR "%s (prism54pci): Cannot enable new PCI device\n",
++ pci_name(pdev));
++ return err;
++ }
++
++ mem_addr = pci_resource_start(pdev, 0);
++ mem_len = pci_resource_len(pdev, 0);
++ if (mem_len < sizeof(struct p54p_csr)) {
++ printk(KERN_ERR "%s (prism54pci): Too short PCI resources\n",
++ pci_name(pdev));
++ pci_disable_device(pdev);
++ return err;
++ }
++
++ err = pci_request_regions(pdev, "prism54pci");
++ if (err) {
++ printk(KERN_ERR "%s (prism54pci): Cannot obtain PCI resources\n",
++ pci_name(pdev));
++ return err;
++ }
++
++ if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) ||
++ pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
++ printk(KERN_ERR "%s (prism54pci): No suitable DMA available\n",
++ pci_name(pdev));
++ goto err_free_reg;
++ }
++
++ pci_set_master(pdev);
++ pci_try_set_mwi(pdev);
++
++ pci_write_config_byte(pdev, 0x40, 0);
++ pci_write_config_byte(pdev, 0x41, 0);
++
++ dev = p54_init_common(sizeof(*priv));
++ if (!dev) {
++ printk(KERN_ERR "%s (prism54pci): ieee80211 alloc failed\n",
++ pci_name(pdev));
++ err = -ENOMEM;
++ goto err_free_reg;
++ }
++
++ priv = dev->priv;
++ priv->pdev = pdev;
++
++ SET_IEEE80211_DEV(dev, &pdev->dev);
++ pci_set_drvdata(pdev, dev);
++
++ priv->map = ioremap(mem_addr, mem_len);
++ if (!priv->map) {
++ printk(KERN_ERR "%s (prism54pci): Cannot map device memory\n",
++ pci_name(pdev));
++ err = -EINVAL; // TODO: use a better error code?
++ goto err_free_dev;
++ }
++
++ priv->ring_control = pci_alloc_consistent(pdev, sizeof(*priv->ring_control),
++ &priv->ring_control_dma);
++ if (!priv->ring_control) {
++ printk(KERN_ERR "%s (prism54pci): Cannot allocate rings\n",
++ pci_name(pdev));
++ err = -ENOMEM;
++ goto err_iounmap;
++ }
++ memset(priv->ring_control, 0, sizeof(*priv->ring_control));
++
++ err = p54p_upload_firmware(dev);
++ if (err)
++ goto err_free_desc;
++
++ err = p54p_read_eeprom(dev);
++ if (err)
++ goto err_free_desc;
++
++ priv->common.open = p54p_open;
++ priv->common.stop = p54p_stop;
++ priv->common.tx = p54p_tx;
++
++ spin_lock_init(&priv->lock);
++
++ err = ieee80211_register_hw(dev);
++ if (err) {
++ printk(KERN_ERR "%s (prism54pci): Cannot register netdevice\n",
++ pci_name(pdev));
++ goto err_free_common;
++ }
++
++ printk(KERN_INFO "%s: hwaddr %s, isl38%02x\n",
++ wiphy_name(dev->wiphy),
++ print_mac(mac, dev->wiphy->perm_addr),
++ priv->common.version);
++
++ return 0;
++
++ err_free_common:
++ p54_free_common(dev);
++
++ err_free_desc:
++ pci_free_consistent(pdev, sizeof(*priv->ring_control),
++ priv->ring_control, priv->ring_control_dma);
++
++ err_iounmap:
++ iounmap(priv->map);
++
++ err_free_dev:
++ pci_set_drvdata(pdev, NULL);
++ ieee80211_free_hw(dev);
++
++ err_free_reg:
++ pci_release_regions(pdev);
++ pci_disable_device(pdev);
++ return err;
++}
++
++static void __devexit p54p_remove(struct pci_dev *pdev)
++{
++ struct ieee80211_hw *dev = pci_get_drvdata(pdev);
++ struct p54p_priv *priv;
++
++ if (!dev)
++ return;
++
++ ieee80211_unregister_hw(dev);
++ priv = dev->priv;
++ pci_free_consistent(pdev, sizeof(*priv->ring_control),
++ priv->ring_control, priv->ring_control_dma);
++ p54_free_common(dev);
++ iounmap(priv->map);
++ pci_release_regions(pdev);
++ pci_disable_device(pdev);
++ ieee80211_free_hw(dev);
++}
++
++#ifdef CONFIG_PM
++static int p54p_suspend(struct pci_dev *pdev, pm_message_t state)
++{
++ struct ieee80211_hw *dev = pci_get_drvdata(pdev);
++ struct p54p_priv *priv = dev->priv;
++
++ if (priv->common.mode != IEEE80211_IF_TYPE_INVALID) {
++ ieee80211_stop_queues(dev);
++ p54p_stop(dev);
++ }
++
++ pci_save_state(pdev);
++ pci_set_power_state(pdev, pci_choose_state(pdev, state));
++ return 0;
++}
++
++static int p54p_resume(struct pci_dev *pdev)
++{
++ struct ieee80211_hw *dev = pci_get_drvdata(pdev);
++ struct p54p_priv *priv = dev->priv;
++
++ pci_set_power_state(pdev, PCI_D0);
++ pci_restore_state(pdev);
++
++ if (priv->common.mode != IEEE80211_IF_TYPE_INVALID) {
++ p54p_open(dev);
++ ieee80211_start_queues(dev);
++ }
++
++ return 0;
++}
++#endif /* CONFIG_PM */
++
++static struct pci_driver p54p_driver = {
++ .name = "prism54pci",
++ .id_table = p54p_table,
++ .probe = p54p_probe,
++ .remove = __devexit_p(p54p_remove),
++#ifdef CONFIG_PM
++ .suspend = p54p_suspend,
++ .resume = p54p_resume,
++#endif /* CONFIG_PM */
++};
++
++static int __init p54p_init(void)
++{
++ return pci_register_driver(&p54p_driver);
++}
++
++static void __exit p54p_exit(void)
++{
++ pci_unregister_driver(&p54p_driver);
++}
++
++module_init(p54p_init);
++module_exit(p54p_exit);
+diff --git a/drivers/net/wireless/p54/p54pci.h b/drivers/net/wireless/p54/p54pci.h
+new file mode 100644
+index 0000000..5bedd7a
+--- /dev/null
++++ b/drivers/net/wireless/p54/p54pci.h
+@@ -0,0 +1,106 @@
++#ifndef PRISM54PCI_H
++#define PRISM54PCI_H
++
++/*
++ * Defines for PCI based mac80211 Prism54 driver
++ *
++ * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
++ *
++ * Based on the islsm (softmac prism54) driver, which is:
++ * Copyright 2004-2006 Jean-Baptiste Note <jbnote at gmail.com>, et al.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++/* Device Interrupt register bits */
++#define ISL38XX_DEV_INT_RESET 0x0001
++#define ISL38XX_DEV_INT_UPDATE 0x0002
++#define ISL38XX_DEV_INT_WAKEUP 0x0008
++#define ISL38XX_DEV_INT_SLEEP 0x0010
++#define ISL38XX_DEV_INT_ABORT 0x0020
++/* these two only used in USB */
++#define ISL38XX_DEV_INT_DATA 0x0040
++#define ISL38XX_DEV_INT_MGMT 0x0080
++
++#define ISL38XX_DEV_INT_PCIUART_CTS 0x4000
++#define ISL38XX_DEV_INT_PCIUART_DR 0x8000
++
++/* Interrupt Identification/Acknowledge/Enable register bits */
++#define ISL38XX_INT_IDENT_UPDATE 0x0002
++#define ISL38XX_INT_IDENT_INIT 0x0004
++#define ISL38XX_INT_IDENT_WAKEUP 0x0008
++#define ISL38XX_INT_IDENT_SLEEP 0x0010
++#define ISL38XX_INT_IDENT_PCIUART_CTS 0x4000
++#define ISL38XX_INT_IDENT_PCIUART_DR 0x8000
++
++/* Control/Status register bits */
++#define ISL38XX_CTRL_STAT_SLEEPMODE 0x00000200
++#define ISL38XX_CTRL_STAT_CLKRUN 0x00800000
++#define ISL38XX_CTRL_STAT_RESET 0x10000000
++#define ISL38XX_CTRL_STAT_RAMBOOT 0x20000000
++#define ISL38XX_CTRL_STAT_STARTHALTED 0x40000000
++#define ISL38XX_CTRL_STAT_HOST_OVERRIDE 0x80000000
++
++struct p54p_csr {
++ __le32 dev_int;
++ u8 unused_1[12];
++ __le32 int_ident;
++ __le32 int_ack;
++ __le32 int_enable;
++ u8 unused_2[4];
++ union {
++ __le32 ring_control_base;
++ __le32 gen_purp_com[2];
++ };
++ u8 unused_3[8];
++ __le32 direct_mem_base;
++ u8 unused_4[44];
++ __le32 dma_addr;
++ __le32 dma_len;
++ __le32 dma_ctrl;
++ u8 unused_5[12];
++ __le32 ctrl_stat;
++ u8 unused_6[1924];
++ u8 cardbus_cis[0x800];
++ u8 direct_mem_win[0x1000];
++} __attribute__ ((packed));
++
++/* usb backend only needs the register defines above */
++#ifndef PRISM54USB_H
++struct p54p_desc {
++ __le32 host_addr;
++ __le32 device_addr;
++ __le16 len;
++ __le16 flags;
++} __attribute__ ((packed));
++
++struct p54p_ring_control {
++ __le32 host_idx[4];
++ __le32 device_idx[4];
++ struct p54p_desc rx_data[8];
++ struct p54p_desc tx_data[32];
++ struct p54p_desc rx_mgmt[4];
++ struct p54p_desc tx_mgmt[4];
++} __attribute__ ((packed));
++
++#define P54P_READ(r) (__force __le32)__raw_readl(&priv->map->r)
++#define P54P_WRITE(r, val) __raw_writel((__force u32)(__le32)(val), &priv->map->r)
++
++struct p54p_priv {
++ struct p54_common common;
++ struct pci_dev *pdev;
++ struct p54p_csr __iomem *map;
++
++ spinlock_t lock;
++ struct p54p_ring_control *ring_control;
++ dma_addr_t ring_control_dma;
++ u32 rx_idx, tx_idx;
++ struct sk_buff *rx_buf[8];
++ void *tx_buf[32];
++ struct completion boot_comp;
++};
++
++#endif /* PRISM54USB_H */
++#endif /* PRISM54PCI_H */
+diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
+new file mode 100644
+index 0000000..98ddbb3
+--- /dev/null
++++ b/drivers/net/wireless/p54/p54usb.c
+@@ -0,0 +1,910 @@
++
++/*
++ * Linux device driver for USB based Prism54
++ *
++ * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
++ *
++ * Based on the islsm (softmac prism54) driver, which is:
++ * Copyright 2004-2006 Jean-Baptiste Note <jbnote at gmail.com>, et al.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/init.h>
++#include <linux/usb.h>
++#include <linux/pci.h>
++#include <linux/firmware.h>
++#include <linux/etherdevice.h>
++#include <linux/delay.h>
++#include <linux/crc32.h>
++#include <net/mac80211.h>
++
++#include "p54.h"
++#include "p54usb.h"
++
++MODULE_AUTHOR("Michael Wu <flamingice at sourmilk.net>");
++MODULE_DESCRIPTION("Prism54 USB wireless driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("prism54usb");
++
++static struct usb_device_id p54u_table[] __devinitdata = {
++ /* Version 1 devices (pci chip + net2280) */
++ {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */
++ {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */
++ {USB_DEVICE(0x083a, 0x4501)}, /* Accton 802.11g WN4501 USB */
++ {USB_DEVICE(0x083a, 0x4502)}, /* Siemens Gigaset USB Adapter */
++ {USB_DEVICE(0x083a, 0x5501)}, /* Phillips CPWUA054 */
++ {USB_DEVICE(0x0846, 0x4200)}, /* Netgear WG121 */
++ {USB_DEVICE(0x0846, 0x4210)}, /* Netgear WG121 the second ? */
++ {USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */
++ {USB_DEVICE(0x0cde, 0x0006)}, /* Medion 40900, Roper Europe */
++ {USB_DEVICE(0x124a, 0x4023)}, /* Shuttle PN15, Airvast WM168g, IOGear GWU513 */
++ {USB_DEVICE(0x1915, 0x2234)}, /* Linksys WUSB54G OEM */
++ {USB_DEVICE(0x1915, 0x2235)}, /* Linksys WUSB54G Portable OEM */
++ {USB_DEVICE(0x2001, 0x3701)}, /* DLink DWL-G120 Spinnaker */
++ {USB_DEVICE(0x2001, 0x3703)}, /* DLink DWL-G122 */
++ {USB_DEVICE(0x5041, 0x2234)}, /* Linksys WUSB54G */
++ {USB_DEVICE(0x5041, 0x2235)}, /* Linksys WUSB54G Portable */
++
++ /* Version 2 devices (3887) */
++ {USB_DEVICE(0x050d, 0x7050)}, /* Belkin F5D7050 ver 1000 */
++ {USB_DEVICE(0x0572, 0x2000)}, /* Cohiba Proto board */
++ {USB_DEVICE(0x0572, 0x2002)}, /* Cohiba Proto board */
++ {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */
++ {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */
++ {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */
++ {USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */
++ {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */
++ {USB_DEVICE(0x0baf, 0x0118)}, /* U.S. Robotics U5 802.11g Adapter*/
++ {USB_DEVICE(0x0bf8, 0x1009)}, /* FUJITSU E-5400 USB D1700*/
++ {USB_DEVICE(0x0cde, 0x0006)}, /* Medion MD40900 */
++ {USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */
++ {USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */
++ {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */
++ {USB_DEVICE(0x124a, 0x4025)}, /* IOGear GWU513 (GW3887IK chip) */
++ {USB_DEVICE(0x13b1, 0x000a)}, /* Linksys WUSB54G ver 2 */
++ {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */
++ {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */
++ {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */
++ {USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */
++ {USB_DEVICE(0x413c, 0x8104)}, /* Cohiba Proto board */
++ {}
++};
++
++MODULE_DEVICE_TABLE(usb, p54u_table);
++
++static void p54u_rx_cb(struct urb *urb)
++{
++ struct sk_buff *skb = (struct sk_buff *) urb->context;
++ struct p54u_rx_info *info = (struct p54u_rx_info *)skb->cb;
++ struct ieee80211_hw *dev = info->dev;
++ struct p54u_priv *priv = dev->priv;
++
++ if (unlikely(urb->status)) {
++ info->urb = NULL;
++ usb_free_urb(urb);
++ return;
++ }
++
++ skb_unlink(skb, &priv->rx_queue);
++ skb_put(skb, urb->actual_length);
++ if (!priv->hw_type)
++ skb_pull(skb, sizeof(struct net2280_tx_hdr));
++
++ if (p54_rx(dev, skb)) {
++ skb = dev_alloc_skb(MAX_RX_SIZE);
++ if (unlikely(!skb)) {
++ usb_free_urb(urb);
++ /* TODO check rx queue length and refill *somewhere* */
++ return;
++ }
++
++ info = (struct p54u_rx_info *) skb->cb;
++ info->urb = urb;
++ info->dev = dev;
++ urb->transfer_buffer = skb_tail_pointer(skb);
++ urb->context = skb;
++ skb_queue_tail(&priv->rx_queue, skb);
++ } else {
++ skb_trim(skb, 0);
++ skb_queue_tail(&priv->rx_queue, skb);
++ }
++
++ usb_submit_urb(urb, GFP_ATOMIC);
++}
++
++static void p54u_tx_cb(struct urb *urb)
++{
++ usb_free_urb(urb);
++}
++
++static void p54u_tx_free_cb(struct urb *urb)
++{
++ kfree(urb->transfer_buffer);
++ usb_free_urb(urb);
++}
++
++static int p54u_init_urbs(struct ieee80211_hw *dev)
++{
++ struct p54u_priv *priv = dev->priv;
++ struct urb *entry;
++ struct sk_buff *skb;
++ struct p54u_rx_info *info;
++
++ while (skb_queue_len(&priv->rx_queue) < 32) {
++ skb = __dev_alloc_skb(MAX_RX_SIZE, GFP_KERNEL);
++ if (!skb)
++ break;
++ entry = usb_alloc_urb(0, GFP_KERNEL);
++ if (!entry) {
++ kfree_skb(skb);
++ break;
++ }
++ usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), skb_tail_pointer(skb), MAX_RX_SIZE, p54u_rx_cb, skb);
++ info = (struct p54u_rx_info *) skb->cb;
++ info->urb = entry;
++ info->dev = dev;
++ skb_queue_tail(&priv->rx_queue, skb);
++ usb_submit_urb(entry, GFP_KERNEL);
++ }
++
++ return 0;
++}
++
++static void p54u_free_urbs(struct ieee80211_hw *dev)
++{
++ struct p54u_priv *priv = dev->priv;
++ struct p54u_rx_info *info;
++ struct sk_buff *skb;
++
++ while ((skb = skb_dequeue(&priv->rx_queue))) {
++ info = (struct p54u_rx_info *) skb->cb;
++ if (!info->urb)
++ continue;
++
++ usb_kill_urb(info->urb);
++ kfree_skb(skb);
++ }
++}
++
++static void p54u_tx_3887(struct ieee80211_hw *dev, struct p54_control_hdr *data,
++ size_t len, int free_on_tx)
++{
++ struct p54u_priv *priv = dev->priv;
++ struct urb *addr_urb, *data_urb;
++
++ addr_urb = usb_alloc_urb(0, GFP_ATOMIC);
++ if (!addr_urb)
++ return;
++
++ data_urb = usb_alloc_urb(0, GFP_ATOMIC);
++ if (!data_urb) {
++ usb_free_urb(addr_urb);
++ return;
++ }
++
++ usb_fill_bulk_urb(addr_urb, priv->udev,
++ usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), &data->req_id,
++ sizeof(data->req_id), p54u_tx_cb, dev);
++ usb_fill_bulk_urb(data_urb, priv->udev,
++ usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), data, len,
++ free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev);
++
++ usb_submit_urb(addr_urb, GFP_ATOMIC);
++ usb_submit_urb(data_urb, GFP_ATOMIC);
++}
++
++static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *data,
++ size_t len, int free_on_tx)
++{
++ struct p54u_priv *priv = dev->priv;
++ struct urb *int_urb, *data_urb;
++ struct net2280_tx_hdr *hdr;
++ struct net2280_reg_write *reg;
++
++ reg = kmalloc(sizeof(*reg), GFP_ATOMIC);
++ if (!reg)
++ return;
++
++ int_urb = usb_alloc_urb(0, GFP_ATOMIC);
++ if (!int_urb) {
++ kfree(reg);
++ return;
++ }
++
++ data_urb = usb_alloc_urb(0, GFP_ATOMIC);
++ if (!data_urb) {
++ kfree(reg);
++ usb_free_urb(int_urb);
++ return;
++ }
++
++ reg->port = cpu_to_le16(NET2280_DEV_U32);
++ reg->addr = cpu_to_le32(P54U_DEV_BASE);
++ reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
++
++ len += sizeof(*data);
++ hdr = (void *)data - sizeof(*hdr);
++ memset(hdr, 0, sizeof(*hdr));
++ hdr->device_addr = data->req_id;
++ hdr->len = cpu_to_le16(len);
++
++ usb_fill_bulk_urb(int_urb, priv->udev,
++ usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg),
++ p54u_tx_free_cb, dev);
++ usb_submit_urb(int_urb, GFP_ATOMIC);
++
++ usb_fill_bulk_urb(data_urb, priv->udev,
++ usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr, len + sizeof(*hdr),
++ free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev);
++ usb_submit_urb(data_urb, GFP_ATOMIC);
++}
++
++static int p54u_write(struct p54u_priv *priv,
++ struct net2280_reg_write *buf,
++ enum net2280_op_type type,
++ __le32 addr, __le32 val)
++{
++ unsigned int ep;
++ int alen;
++
++ if (type & 0x0800)
++ ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV);
++ else
++ ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_BRG);
++
++ buf->port = cpu_to_le16(type);
++ buf->addr = addr;
++ buf->val = val;
++
++ return usb_bulk_msg(priv->udev, ep, buf, sizeof(*buf), &alen, 1000);
++}
++
++static int p54u_read(struct p54u_priv *priv, void *buf,
++ enum net2280_op_type type,
++ __le32 addr, __le32 *val)
++{
++ struct net2280_reg_read *read = buf;
++ __le32 *reg = buf;
++ unsigned int ep;
++ int alen, err;
++
++ if (type & 0x0800)
++ ep = P54U_PIPE_DEV;
++ else
++ ep = P54U_PIPE_BRG;
++
++ read->port = cpu_to_le16(type);
++ read->addr = addr;
++
++ err = usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),
++ read, sizeof(*read), &alen, 1000);
++ if (err)
++ return err;
++
++ err = usb_bulk_msg(priv->udev, usb_rcvbulkpipe(priv->udev, ep),
++ reg, sizeof(*reg), &alen, 1000);
++ if (err)
++ return err;
++
++ *val = *reg;
++ return 0;
++}
++
++static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep,
++ void *data, size_t len)
++{
++ int alen;
++ return usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),
++ data, len, &alen, 2000);
++}
++
++static int p54u_read_eeprom(struct ieee80211_hw *dev)
++{
++ struct p54u_priv *priv = dev->priv;
++ void *buf;
++ struct p54_control_hdr *hdr;
++ int err, alen;
++ size_t offset = priv->hw_type ? 0x10 : 0x20;
++
++ buf = kmalloc(0x2020, GFP_KERNEL);
++ if (!buf) {
++ printk(KERN_ERR "prism54usb: cannot allocate memory for "
++ "eeprom readback!\n");
++ return -ENOMEM;
++ }
++
++ if (priv->hw_type) {
++ *((u32 *) buf) = priv->common.rx_start;
++ err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
++ if (err) {
++ printk(KERN_ERR "prism54usb: addr send failed\n");
++ goto fail;
++ }
++ } else {
++ struct net2280_reg_write *reg = buf;
++ reg->port = cpu_to_le16(NET2280_DEV_U32);
++ reg->addr = cpu_to_le32(P54U_DEV_BASE);
++ reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
++ err = p54u_bulk_msg(priv, P54U_PIPE_DEV, buf, sizeof(*reg));
++ if (err) {
++ printk(KERN_ERR "prism54usb: dev_int send failed\n");
++ goto fail;
++ }
++ }
++
++ hdr = buf + priv->common.tx_hdr_len;
++ p54_fill_eeprom_readback(hdr);
++ hdr->req_id = cpu_to_le32(priv->common.rx_start);
++ if (priv->common.tx_hdr_len) {
++ struct net2280_tx_hdr *tx_hdr = buf;
++ tx_hdr->device_addr = hdr->req_id;
++ tx_hdr->len = cpu_to_le16(EEPROM_READBACK_LEN);
++ }
++
++ /* we can just pretend to send 0x2000 bytes of nothing in the headers */
++ err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf,
++ EEPROM_READBACK_LEN + priv->common.tx_hdr_len);
++ if (err) {
++ printk(KERN_ERR "prism54usb: eeprom req send failed\n");
++ goto fail;
++ }
++
++ err = usb_bulk_msg(priv->udev,
++ usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA),
++ buf, 0x2020, &alen, 1000);
++ if (!err && alen > offset) {
++ p54_parse_eeprom(dev, (u8 *)buf + offset, alen - offset);
++ } else {
++ printk(KERN_ERR "prism54usb: eeprom read failed!\n");
++ err = -EINVAL;
++ goto fail;
++ }
++
++ fail:
++ kfree(buf);
++ return err;
++}
++
++static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
++{
++ static char start_string[] = "~~~~<\r";
++ struct p54u_priv *priv = dev->priv;
++ const struct firmware *fw_entry = NULL;
++ int err, alen;
++ u8 carry = 0;
++ u8 *buf, *tmp, *data;
++ unsigned int left, remains, block_size;
++ struct x2_header *hdr;
++ unsigned long timeout;
++
++ tmp = buf = kmalloc(P54U_FW_BLOCK, GFP_KERNEL);
++ if (!buf) {
++ printk(KERN_ERR "p54usb: cannot allocate firmware upload buffer!\n");
++ err = -ENOMEM;
++ goto err_bufalloc;
++ }
++
++ memcpy(buf, start_string, 4);
++ err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 4);
++ if (err) {
++ printk(KERN_ERR "p54usb: reset failed! (%d)\n", err);
++ goto err_reset;
++ }
++
++ err = request_firmware(&fw_entry, "isl3887usb_bare", &priv->udev->dev);
++ if (err) {
++ printk(KERN_ERR "p54usb: cannot find firmware (isl3887usb_bare)!\n");
++ goto err_req_fw_failed;
++ }
++
++ p54_parse_firmware(dev, fw_entry);
++
++ left = block_size = min((size_t)P54U_FW_BLOCK, fw_entry->size);
++ strcpy(buf, start_string);
++ left -= strlen(start_string);
++ tmp += strlen(start_string);
++
++ data = fw_entry->data;
++ remains = fw_entry->size;
++
++ hdr = (struct x2_header *)(buf + strlen(start_string));
++ memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE);
++ hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR);
++ hdr->fw_length = cpu_to_le32(fw_entry->size);
++ hdr->crc = cpu_to_le32(~crc32_le(~0, (void *)&hdr->fw_load_addr,
++ sizeof(u32)*2));
++ left -= sizeof(*hdr);
++ tmp += sizeof(*hdr);
++
++ while (remains) {
++ while (left--) {
++ if (carry) {
++ *tmp++ = carry;
++ carry = 0;
++ remains--;
++ continue;
++ }
++ switch (*data) {
++ case '~':
++ *tmp++ = '}';
++ carry = '^';
++ break;
++ case '}':
++ *tmp++ = '}';
++ carry = ']';
++ break;
++ default:
++ *tmp++ = *data;
++ remains--;
++ break;
++ }
++ data++;
++ }
++
++ err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_size);
++ if (err) {
++ printk(KERN_ERR "prism54usb: firmware upload failed!\n");
++ goto err_upload_failed;
++ }
++
++ tmp = buf;
++ left = block_size = min((unsigned int)P54U_FW_BLOCK, remains);
++ }
++
++ *((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, fw_entry->data, fw_entry->size));
++ err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
++ if (err) {
++ printk(KERN_ERR "prism54usb: firmware upload failed!\n");
++ goto err_upload_failed;
++ }
++
++ timeout = jiffies + msecs_to_jiffies(1000);
++ while (!(err = usb_bulk_msg(priv->udev,
++ usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
++ if (alen > 2 && !memcmp(buf, "OK", 2))
++ break;
++
++ if (alen > 5 && !memcmp(buf, "ERROR", 5)) {
++ printk(KERN_INFO "prism54usb: firmware upload failed!\n");
++ err = -EINVAL;
++ break;
++ }
++
++ if (time_after(jiffies, timeout)) {
++ printk(KERN_ERR "prism54usb: firmware boot timed out!\n");
++ err = -ETIMEDOUT;
++ break;
++ }
++ }
++ if (err)
++ goto err_upload_failed;
++
++ buf[0] = 'g';
++ buf[1] = '\r';
++ err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 2);
++ if (err) {
++ printk(KERN_ERR "prism54usb: firmware boot failed!\n");
++ goto err_upload_failed;
++ }
++
++ timeout = jiffies + msecs_to_jiffies(1000);
++ while (!(err = usb_bulk_msg(priv->udev,
++ usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
++ if (alen > 0 && buf[0] == 'g')
++ break;
++
++ if (time_after(jiffies, timeout)) {
++ err = -ETIMEDOUT;
++ break;
++ }
++ }
++ if (err)
++ goto err_upload_failed;
++
++ err_upload_failed:
++ release_firmware(fw_entry);
++ err_req_fw_failed:
++ err_reset:
++ kfree(buf);
++ err_bufalloc:
++ return err;
++}
++
++static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
++{
++ struct p54u_priv *priv = dev->priv;
++ const struct firmware *fw_entry = NULL;
++ const struct p54p_csr *devreg = (const struct p54p_csr *) P54U_DEV_BASE;
++ int err, alen;
++ void *buf;
++ __le32 reg;
++ unsigned int remains, offset;
++ u8 *data;
++
++ buf = kmalloc(512, GFP_KERNEL);
++ if (!buf) {
++ printk(KERN_ERR "p54usb: firmware buffer alloc failed!\n");
++ return -ENOMEM;
++ }
++
++ err = request_firmware(&fw_entry, "isl3890usb", &priv->udev->dev);
++ if (err) {
++ printk(KERN_ERR "p54usb: cannot find firmware (isl3890usb)!\n");
++ kfree(buf);
++ return err;
++ }
++
++ p54_parse_firmware(dev, fw_entry);
++
++#define P54U_WRITE(type, addr, data) \
++ do {\
++ err = p54u_write(priv, buf, type,\
++ cpu_to_le32((u32)(unsigned long)addr), data);\
++ if (err) \
++ goto fail;\
++ } while (0)
++
++#define P54U_READ(type, addr) \
++ do {\
++ err = p54u_read(priv, buf, type,\
++ cpu_to_le32((u32)(unsigned long)addr), ®);\
++ if (err)\
++ goto fail;\
++ } while (0)
++
++ /* power down net2280 bridge */
++ P54U_READ(NET2280_BRG_U32, NET2280_GPIOCTL);
++ reg |= cpu_to_le32(P54U_BRG_POWER_DOWN);
++ reg &= cpu_to_le32(~P54U_BRG_POWER_UP);
++ P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);
++
++ mdelay(100);
++
++ /* power up bridge */
++ reg |= cpu_to_le32(P54U_BRG_POWER_UP);
++ reg &= cpu_to_le32(~P54U_BRG_POWER_DOWN);
++ P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);
++
++ mdelay(100);
++
++ P54U_WRITE(NET2280_BRG_U32, NET2280_DEVINIT,
++ cpu_to_le32(NET2280_CLK_30Mhz |
++ NET2280_PCI_ENABLE |
++ NET2280_PCI_SOFT_RESET));
++
++ mdelay(20);
++
++ P54U_WRITE(NET2280_BRG_CFG_U16, PCI_COMMAND,
++ cpu_to_le32(PCI_COMMAND_MEMORY |
++ PCI_COMMAND_MASTER));
++
++ P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_0,
++ cpu_to_le32(NET2280_BASE));
++
++ P54U_READ(NET2280_BRG_CFG_U16, PCI_STATUS);
++ reg |= cpu_to_le32(PCI_STATUS_REC_MASTER_ABORT);
++ P54U_WRITE(NET2280_BRG_CFG_U16, PCI_STATUS, reg);
++
++ // TODO: we really need this?
++ P54U_READ(NET2280_BRG_U32, NET2280_RELNUM);
++
++ P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_RSP,
++ cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));
++ P54U_WRITE(NET2280_BRG_U32, NET2280_EPC_RSP,
++ cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));
++
++ P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_2,
++ cpu_to_le32(NET2280_BASE2));
++
++ /* finally done setting up the bridge */
++
++ P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | PCI_COMMAND,
++ cpu_to_le32(PCI_COMMAND_MEMORY |
++ PCI_COMMAND_MASTER));
++
++ P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | 0x40 /* TRDY timeout */, 0);
++ P54U_WRITE(NET2280_DEV_CFG_U32, 0x10000 | PCI_BASE_ADDRESS_0,
++ cpu_to_le32(P54U_DEV_BASE));
++
++ P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);
++ P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
++ cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
++
++ /* do romboot */
++ P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable, 0);
++
++ P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);
++ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
++ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT);
++ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
++ P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
++
++ mdelay(20);
++
++ reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
++ P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
++
++ mdelay(20);
++
++ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
++ P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
++
++ mdelay(100);
++
++ P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
++ P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
++
++ /* finally, we can upload firmware now! */
++ remains = fw_entry->size;
++ data = fw_entry->data;
++ offset = ISL38XX_DEV_FIRMWARE_ADDR;
++
++ while (remains) {
++ unsigned int block_len = min(remains, (unsigned int)512);
++ memcpy(buf, data, block_len);
++
++ err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_len);
++ if (err) {
++ printk(KERN_ERR "prism54usb: firmware block upload "
++ "failed\n");
++ goto fail;
++ }
++
++ P54U_WRITE(NET2280_DEV_U32, &devreg->direct_mem_base,
++ cpu_to_le32(0xc0000f00));
++
++ P54U_WRITE(NET2280_DEV_U32,
++ 0x0020 | (unsigned long)&devreg->direct_mem_win, 0);
++ P54U_WRITE(NET2280_DEV_U32,
++ 0x0020 | (unsigned long)&devreg->direct_mem_win,
++ cpu_to_le32(1));
++
++ P54U_WRITE(NET2280_DEV_U32,
++ 0x0024 | (unsigned long)&devreg->direct_mem_win,
++ cpu_to_le32(block_len));
++ P54U_WRITE(NET2280_DEV_U32,
++ 0x0028 | (unsigned long)&devreg->direct_mem_win,
++ cpu_to_le32(offset));
++
++ P54U_WRITE(NET2280_DEV_U32, &devreg->dma_addr,
++ cpu_to_le32(NET2280_EPA_FIFO_PCI_ADDR));
++ P54U_WRITE(NET2280_DEV_U32, &devreg->dma_len,
++ cpu_to_le32(block_len >> 2));
++ P54U_WRITE(NET2280_DEV_U32, &devreg->dma_ctrl,
++ cpu_to_le32(ISL38XX_DMA_MASTER_CONTROL_TRIGGER));
++
++ mdelay(10);
++
++ P54U_READ(NET2280_DEV_U32,
++ 0x002C | (unsigned long)&devreg->direct_mem_win);
++ if (!(reg & cpu_to_le32(ISL38XX_DMA_STATUS_DONE)) ||
++ !(reg & cpu_to_le32(ISL38XX_DMA_STATUS_READY))) {
++ printk(KERN_ERR "prism54usb: firmware DMA transfer "
++ "failed\n");
++ goto fail;
++ }
++
++ P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_STAT,
++ cpu_to_le32(NET2280_FIFO_FLUSH));
++
++ remains -= block_len;
++ data += block_len;
++ offset += block_len;
++ }
++
++ /* do ramboot */
++ P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);
++ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
++ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
++ reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT);
++ P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
++
++ mdelay(20);
++
++ reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
++ P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
++
++ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
++ P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
++
++ mdelay(100);
++
++ P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
++ P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
++
++ /* start up the firmware */
++ P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable,
++ cpu_to_le32(ISL38XX_INT_IDENT_INIT));
++
++ P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
++ cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
++
++ P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1,
++ cpu_to_le32(NET2280_PCI_INTA_INTERRUPT_ENABLE |
++ NET2280_USB_INTERRUPT_ENABLE));
++
++ P54U_WRITE(NET2280_DEV_U32, &devreg->dev_int,
++ cpu_to_le32(ISL38XX_DEV_INT_RESET));
++
++ err = usb_interrupt_msg(priv->udev,
++ usb_rcvbulkpipe(priv->udev, P54U_PIPE_INT),
++ buf, sizeof(__le32), &alen, 1000);
++ if (err || alen != sizeof(__le32))
++ goto fail;
++
++ P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
++ P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
++
++ if (!(reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT)))
++ err = -EINVAL;
++
++ P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);
++ P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
++ cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
++
++#undef P54U_WRITE
++#undef P54U_READ
++
++ fail:
++ release_firmware(fw_entry);
++ kfree(buf);
++ return err;
++}
++
++static int p54u_open(struct ieee80211_hw *dev)
++{
++ struct p54u_priv *priv = dev->priv;
++ int err;
++
++ err = p54u_init_urbs(dev);
++ if (err) {
++ return err;
++ }
++
++ priv->common.open = p54u_init_urbs;
++
++ return 0;
++}
++
++static void p54u_stop(struct ieee80211_hw *dev)
++{
++ /* TODO: figure out how to reliably stop the 3887 and net2280 so
++ the hardware is still usable next time we want to start it.
++ until then, we just stop listening to the hardware.. */
++ p54u_free_urbs(dev);
++ return;
++}
++
++static int __devinit p54u_probe(struct usb_interface *intf,
++ const struct usb_device_id *id)
++{
++ struct usb_device *udev = interface_to_usbdev(intf);
++ struct ieee80211_hw *dev;
++ struct p54u_priv *priv;
++ int err;
++ unsigned int i, recognized_pipes;
++ DECLARE_MAC_BUF(mac);
++
++ dev = p54_init_common(sizeof(*priv));
++ if (!dev) {
++ printk(KERN_ERR "prism54usb: ieee80211 alloc failed\n");
++ return -ENOMEM;
++ }
++
++ priv = dev->priv;
++
++ SET_IEEE80211_DEV(dev, &intf->dev);
++ usb_set_intfdata(intf, dev);
++ priv->udev = udev;
++
++ usb_get_dev(udev);
++
++ /* really lazy and simple way of figuring out if we're a 3887 */
++ /* TODO: should just stick the identification in the device table */
++ i = intf->altsetting->desc.bNumEndpoints;
++ recognized_pipes = 0;
++ while (i--) {
++ switch (intf->altsetting->endpoint[i].desc.bEndpointAddress) {
++ case P54U_PIPE_DATA:
++ case P54U_PIPE_MGMT:
++ case P54U_PIPE_BRG:
++ case P54U_PIPE_DEV:
++ case P54U_PIPE_DATA | USB_DIR_IN:
++ case P54U_PIPE_MGMT | USB_DIR_IN:
++ case P54U_PIPE_BRG | USB_DIR_IN:
++ case P54U_PIPE_DEV | USB_DIR_IN:
++ case P54U_PIPE_INT | USB_DIR_IN:
++ recognized_pipes++;
++ }
++ }
++ priv->common.open = p54u_open;
++
++ if (recognized_pipes < P54U_PIPE_NUMBER) {
++ priv->hw_type = P54U_3887;
++ priv->common.tx = p54u_tx_3887;
++ } else {
++ dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr);
++ priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr);
++ priv->common.tx = p54u_tx_net2280;
++ }
++ priv->common.stop = p54u_stop;
++
++ if (priv->hw_type)
++ err = p54u_upload_firmware_3887(dev);
++ else
++ err = p54u_upload_firmware_net2280(dev);
++ if (err)
++ goto err_free_dev;
++
++ err = p54u_read_eeprom(dev);
++ if (err)
++ goto err_free_dev;
++
++ if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
++ u8 perm_addr[ETH_ALEN];
++
++ printk(KERN_WARNING "prism54usb: Invalid hwaddr! Using randomly generated MAC addr\n");
++ random_ether_addr(perm_addr);
++ SET_IEEE80211_PERM_ADDR(dev, perm_addr);
++ }
++
++ skb_queue_head_init(&priv->rx_queue);
++
++ err = ieee80211_register_hw(dev);
++ if (err) {
++ printk(KERN_ERR "prism54usb: Cannot register netdevice\n");
++ goto err_free_dev;
++ }
++
++ printk(KERN_INFO "%s: hwaddr %s, isl38%02x\n",
++ wiphy_name(dev->wiphy),
++ print_mac(mac, dev->wiphy->perm_addr),
++ priv->common.version);
++
++ return 0;
++
++ err_free_dev:
++ ieee80211_free_hw(dev);
++ usb_set_intfdata(intf, NULL);
++ usb_put_dev(udev);
++ return err;
++}
++
++static void __devexit p54u_disconnect(struct usb_interface *intf)
++{
++ struct ieee80211_hw *dev = usb_get_intfdata(intf);
++ struct p54u_priv *priv;
++
++ if (!dev)
++ return;
++
++ ieee80211_unregister_hw(dev);
++
++ priv = dev->priv;
++ usb_put_dev(interface_to_usbdev(intf));
++ p54_free_common(dev);
++ ieee80211_free_hw(dev);
++}
++
++static struct usb_driver p54u_driver = {
++ .name = "prism54usb",
++ .id_table = p54u_table,
++ .probe = p54u_probe,
++ .disconnect = p54u_disconnect,
++};
++
++static int __init p54u_init(void)
++{
++ return usb_register(&p54u_driver);
++}
++
++static void __exit p54u_exit(void)
++{
++ usb_deregister(&p54u_driver);
++}
++
++module_init(p54u_init);
++module_exit(p54u_exit);
+diff --git a/drivers/net/wireless/p54/p54usb.h b/drivers/net/wireless/p54/p54usb.h
+new file mode 100644
+index 0000000..d1896b3
+--- /dev/null
++++ b/drivers/net/wireless/p54/p54usb.h
+@@ -0,0 +1,133 @@
++#ifndef PRISM54USB_H
++#define PRISM54USB_H
++
++/*
++ * Defines for USB based mac80211 Prism54 driver
++ *
++ * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
++ *
++ * Based on the islsm (softmac prism54) driver, which is:
++ * Copyright 2004-2006 Jean-Baptiste Note <jbnote at gmail.com>, et al.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++/* for isl3886 register definitions used on ver 1 devices */
++#include "p54pci.h"
++#include "net2280.h"
++
++/* pci */
++#define NET2280_BASE 0x10000000
++#define NET2280_BASE2 0x20000000
++
++/* gpio */
++#define P54U_BRG_POWER_UP (1 << GPIO0_DATA)
++#define P54U_BRG_POWER_DOWN (1 << GPIO1_DATA)
++
++/* devinit */
++#define NET2280_CLK_4Mhz (15 << LOCAL_CLOCK_FREQUENCY)
++#define NET2280_CLK_30Mhz (2 << LOCAL_CLOCK_FREQUENCY)
++#define NET2280_CLK_60Mhz (1 << LOCAL_CLOCK_FREQUENCY)
++#define NET2280_CLK_STOP (0 << LOCAL_CLOCK_FREQUENCY)
++#define NET2280_PCI_ENABLE (1 << PCI_ENABLE)
++#define NET2280_PCI_SOFT_RESET (1 << PCI_SOFT_RESET)
++
++/* endpoints */
++#define NET2280_CLEAR_NAK_OUT_PACKETS_MODE (1 << CLEAR_NAK_OUT_PACKETS_MODE)
++#define NET2280_FIFO_FLUSH (1 << FIFO_FLUSH)
++
++/* irq */
++#define NET2280_USB_INTERRUPT_ENABLE (1 << USB_INTERRUPT_ENABLE)
++#define NET2280_PCI_INTA_INTERRUPT (1 << PCI_INTA_INTERRUPT)
++#define NET2280_PCI_INTA_INTERRUPT_ENABLE (1 << PCI_INTA_INTERRUPT_ENABLE)
++
++/* registers */
++#define NET2280_DEVINIT 0x00
++#define NET2280_USBIRQENB1 0x24
++#define NET2280_IRQSTAT1 0x2c
++#define NET2280_FIFOCTL 0x38
++#define NET2280_GPIOCTL 0x50
++#define NET2280_RELNUM 0x88
++#define NET2280_EPA_RSP 0x324
++#define NET2280_EPA_STAT 0x32c
++#define NET2280_EPB_STAT 0x34c
++#define NET2280_EPC_RSP 0x364
++#define NET2280_EPC_STAT 0x36c
++#define NET2280_EPD_STAT 0x38c
++
++#define NET2280_EPA_CFG 0x320
++#define NET2280_EPB_CFG 0x340
++#define NET2280_EPC_CFG 0x360
++#define NET2280_EPD_CFG 0x380
++#define NET2280_EPE_CFG 0x3A0
++#define NET2280_EPF_CFG 0x3C0
++#define P54U_DEV_BASE 0x40000000
++
++struct net2280_tx_hdr {
++ __le32 device_addr;
++ __le16 len;
++ __le16 follower; /* ? */
++ u8 padding[8];
++} __attribute__((packed));
++
++/* Some flags for the isl hardware registers controlling DMA inside the
++ * chip */
++#define ISL38XX_DMA_STATUS_DONE 0x00000001
++#define ISL38XX_DMA_STATUS_READY 0x00000002
++#define NET2280_EPA_FIFO_PCI_ADDR 0x20000000
++#define ISL38XX_DMA_MASTER_CONTROL_TRIGGER 0x00000004
++
++enum net2280_op_type {
++ NET2280_BRG_U32 = 0x001F,
++ NET2280_BRG_CFG_U32 = 0x000F,
++ NET2280_BRG_CFG_U16 = 0x0003,
++ NET2280_DEV_U32 = 0x080F,
++ NET2280_DEV_CFG_U32 = 0x088F,
++ NET2280_DEV_CFG_U16 = 0x0883
++};
++
++#define P54U_FW_BLOCK 2048
++
++#define X2_SIGNATURE "x2 "
++#define X2_SIGNATURE_SIZE 4
++
++struct x2_header {
++ u8 signature[X2_SIGNATURE_SIZE];
++ __le32 fw_load_addr;
++ __le32 fw_length;
++ __le32 crc;
++} __attribute__((packed));
++
++/* pipes 3 and 4 are not used by the driver */
++#define P54U_PIPE_NUMBER 9
++
++enum p54u_pipe_addr {
++ P54U_PIPE_DATA = 0x01,
++ P54U_PIPE_MGMT = 0x02,
++ P54U_PIPE_3 = 0x03,
++ P54U_PIPE_4 = 0x04,
++ P54U_PIPE_BRG = 0x0d,
++ P54U_PIPE_DEV = 0x0e,
++ P54U_PIPE_INT = 0x0f
++};
++
++struct p54u_rx_info {
++ struct urb *urb;
++ struct ieee80211_hw *dev;
++};
++
++struct p54u_priv {
++ struct p54_common common;
++ struct usb_device *udev;
++ enum {
++ P54U_NET2280 = 0,
++ P54U_3887
++ } hw_type;
++
++ spinlock_t lock;
++ struct sk_buff_head rx_queue;
++};
++
++#endif /* PRISM54USB_H */
+diff --git a/drivers/net/wireless/p54common.c b/drivers/net/wireless/p54common.c
+deleted file mode 100644
+index d191e05..0000000
+--- a/drivers/net/wireless/p54common.c
++++ /dev/null
+@@ -1,1025 +0,0 @@
+-
+-/*
+- * Common code for mac80211 Prism54 drivers
+- *
+- * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
+- * Copyright (c) 2007, Christian Lamparter <chunkeey at web.de>
+- *
+- * Based on the islsm (softmac prism54) driver, which is:
+- * Copyright 2004-2006 Jean-Baptiste Note <jbnote at gmail.com>, et al.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#include <linux/init.h>
+-#include <linux/firmware.h>
+-#include <linux/etherdevice.h>
+-
+-#include <net/mac80211.h>
+-
+-#include "p54.h"
+-#include "p54common.h"
+-
+-MODULE_AUTHOR("Michael Wu <flamingice at sourmilk.net>");
+-MODULE_DESCRIPTION("Softmac Prism54 common code");
+-MODULE_LICENSE("GPL");
+-MODULE_ALIAS("prism54common");
+-
+-void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
+-{
+- struct p54_common *priv = dev->priv;
+- struct bootrec_exp_if *exp_if;
+- struct bootrec *bootrec;
+- u32 *data = (u32 *)fw->data;
+- u32 *end_data = (u32 *)fw->data + (fw->size >> 2);
+- u8 *fw_version = NULL;
+- size_t len;
+- int i;
+-
+- if (priv->rx_start)
+- return;
+-
+- while (data < end_data && *data)
+- data++;
+-
+- while (data < end_data && !*data)
+- data++;
+-
+- bootrec = (struct bootrec *) data;
+-
+- while (bootrec->data <= end_data &&
+- (bootrec->data + (len = le32_to_cpu(bootrec->len))) <= end_data) {
+- u32 code = le32_to_cpu(bootrec->code);
+- switch (code) {
+- case BR_CODE_COMPONENT_ID:
+- switch (be32_to_cpu(*(__be32 *)bootrec->data)) {
+- case FW_FMAC:
+- printk(KERN_INFO "p54: FreeMAC firmware\n");
+- break;
+- case FW_LM20:
+- printk(KERN_INFO "p54: LM20 firmware\n");
+- break;
+- case FW_LM86:
+- printk(KERN_INFO "p54: LM86 firmware\n");
+- break;
+- case FW_LM87:
+- printk(KERN_INFO "p54: LM87 firmware - not supported yet!\n");
+- break;
+- default:
+- printk(KERN_INFO "p54: unknown firmware\n");
+- break;
+- }
+- break;
+- case BR_CODE_COMPONENT_VERSION:
+- /* 24 bytes should be enough for all firmwares */
+- if (strnlen((unsigned char*)bootrec->data, 24) < 24)
+- fw_version = (unsigned char*)bootrec->data;
+- break;
+- case BR_CODE_DESCR:
+- priv->rx_start = le32_to_cpu(((__le32 *)bootrec->data)[1]);
+- /* FIXME add sanity checking */
+- priv->rx_end = le32_to_cpu(((__le32 *)bootrec->data)[2]) - 0x3500;
+- break;
+- case BR_CODE_EXPOSED_IF:
+- exp_if = (struct bootrec_exp_if *) bootrec->data;
+- for (i = 0; i < (len * sizeof(*exp_if) / 4); i++)
+- if (exp_if[i].if_id == cpu_to_le16(0x1a))
+- priv->fw_var = le16_to_cpu(exp_if[i].variant);
+- break;
+- case BR_CODE_DEPENDENT_IF:
+- break;
+- case BR_CODE_END_OF_BRA:
+- case LEGACY_BR_CODE_END_OF_BRA:
+- end_data = NULL;
+- break;
+- default:
+- break;
+- }
+- bootrec = (struct bootrec *)&bootrec->data[len];
+- }
+-
+- if (fw_version)
+- printk(KERN_INFO "p54: FW rev %s - Softmac protocol %x.%x\n",
+- fw_version, priv->fw_var >> 8, priv->fw_var & 0xff);
+-
+- if (priv->fw_var >= 0x300) {
+- /* Firmware supports QoS, use it! */
+- priv->tx_stats.data[0].limit = 3;
+- priv->tx_stats.data[1].limit = 4;
+- priv->tx_stats.data[2].limit = 3;
+- priv->tx_stats.data[3].limit = 1;
+- dev->queues = 4;
+- }
+-}
+-EXPORT_SYMBOL_GPL(p54_parse_firmware);
+-
+-static int p54_convert_rev0_to_rev1(struct ieee80211_hw *dev,
+- struct pda_pa_curve_data *curve_data)
+-{
+- struct p54_common *priv = dev->priv;
+- struct pda_pa_curve_data_sample_rev1 *rev1;
+- struct pda_pa_curve_data_sample_rev0 *rev0;
+- size_t cd_len = sizeof(*curve_data) +
+- (curve_data->points_per_channel*sizeof(*rev1) + 2) *
+- curve_data->channels;
+- unsigned int i, j;
+- void *source, *target;
+-
+- priv->curve_data = kmalloc(cd_len, GFP_KERNEL);
+- if (!priv->curve_data)
+- return -ENOMEM;
+-
+- memcpy(priv->curve_data, curve_data, sizeof(*curve_data));
+- source = curve_data->data;
+- target = priv->curve_data->data;
+- for (i = 0; i < curve_data->channels; i++) {
+- __le16 *freq = source;
+- source += sizeof(__le16);
+- *((__le16 *)target) = *freq;
+- target += sizeof(__le16);
+- for (j = 0; j < curve_data->points_per_channel; j++) {
+- rev1 = target;
+- rev0 = source;
+-
+- rev1->rf_power = rev0->rf_power;
+- rev1->pa_detector = rev0->pa_detector;
+- rev1->data_64qam = rev0->pcv;
+- /* "invent" the points for the other modulations */
+-#define SUB(x,y) (u8)((x) - (y)) > (x) ? 0 : (x) - (y)
+- rev1->data_16qam = SUB(rev0->pcv, 12);
+- rev1->data_qpsk = SUB(rev1->data_16qam, 12);
+- rev1->data_bpsk = SUB(rev1->data_qpsk, 12);
+- rev1->data_barker= SUB(rev1->data_bpsk, 14);
+-#undef SUB
+- target += sizeof(*rev1);
+- source += sizeof(*rev0);
+- }
+- }
+-
+- return 0;
+-}
+-
+-int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
+-{
+- struct p54_common *priv = dev->priv;
+- struct eeprom_pda_wrap *wrap = NULL;
+- struct pda_entry *entry;
+- unsigned int data_len, entry_len;
+- void *tmp;
+- int err;
+- u8 *end = (u8 *)eeprom + len;
+-
+- wrap = (struct eeprom_pda_wrap *) eeprom;
+- entry = (void *)wrap->data + le16_to_cpu(wrap->len);
+-
+- /* verify that at least the entry length/code fits */
+- while ((u8 *)entry <= end - sizeof(*entry)) {
+- entry_len = le16_to_cpu(entry->len);
+- data_len = ((entry_len - 1) << 1);
+-
+- /* abort if entry exceeds whole structure */
+- if ((u8 *)entry + sizeof(*entry) + data_len > end)
+- break;
+-
+- switch (le16_to_cpu(entry->code)) {
+- case PDR_MAC_ADDRESS:
+- SET_IEEE80211_PERM_ADDR(dev, entry->data);
+- break;
+- case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS:
+- if (data_len < 2) {
+- err = -EINVAL;
+- goto err;
+- }
+-
+- if (2 + entry->data[1]*sizeof(*priv->output_limit) > data_len) {
+- err = -EINVAL;
+- goto err;
+- }
+-
+- priv->output_limit = kmalloc(entry->data[1] *
+- sizeof(*priv->output_limit), GFP_KERNEL);
+-
+- if (!priv->output_limit) {
+- err = -ENOMEM;
+- goto err;
+- }
+-
+- memcpy(priv->output_limit, &entry->data[2],
+- entry->data[1]*sizeof(*priv->output_limit));
+- priv->output_limit_len = entry->data[1];
+- break;
+- case PDR_PRISM_PA_CAL_CURVE_DATA:
+- if (data_len < sizeof(struct pda_pa_curve_data)) {
+- err = -EINVAL;
+- goto err;
+- }
+-
+- if (((struct pda_pa_curve_data *)entry->data)->cal_method_rev) {
+- priv->curve_data = kmalloc(data_len, GFP_KERNEL);
+- if (!priv->curve_data) {
+- err = -ENOMEM;
+- goto err;
+- }
+-
+- memcpy(priv->curve_data, entry->data, data_len);
+- } else {
+- err = p54_convert_rev0_to_rev1(dev, (struct pda_pa_curve_data *)entry->data);
+- if (err)
+- goto err;
+- }
+-
+- break;
+- case PDR_PRISM_ZIF_TX_IQ_CALIBRATION:
+- priv->iq_autocal = kmalloc(data_len, GFP_KERNEL);
+- if (!priv->iq_autocal) {
+- err = -ENOMEM;
+- goto err;
+- }
+-
+- memcpy(priv->iq_autocal, entry->data, data_len);
+- priv->iq_autocal_len = data_len / sizeof(struct pda_iq_autocal_entry);
+- break;
+- case PDR_INTERFACE_LIST:
+- tmp = entry->data;
+- while ((u8 *)tmp < entry->data + data_len) {
+- struct bootrec_exp_if *exp_if = tmp;
+- if (le16_to_cpu(exp_if->if_id) == 0xF)
+- priv->rxhw = exp_if->variant & cpu_to_le16(0x07);
+- tmp += sizeof(struct bootrec_exp_if);
+- }
+- break;
+- case PDR_HARDWARE_PLATFORM_COMPONENT_ID:
+- priv->version = *(u8 *)(entry->data + 1);
+- break;
+- case PDR_END:
+- /* make it overrun */
+- entry_len = len;
+- break;
+- }
+-
+- entry = (void *)entry + (entry_len + 1)*2;
+- }
+-
+- if (!priv->iq_autocal || !priv->output_limit || !priv->curve_data) {
+- printk(KERN_ERR "p54: not all required entries found in eeprom!\n");
+- err = -EINVAL;
+- goto err;
+- }
+-
+- return 0;
+-
+- err:
+- if (priv->iq_autocal) {
+- kfree(priv->iq_autocal);
+- priv->iq_autocal = NULL;
+- }
+-
+- if (priv->output_limit) {
+- kfree(priv->output_limit);
+- priv->output_limit = NULL;
+- }
+-
+- if (priv->curve_data) {
+- kfree(priv->curve_data);
+- priv->curve_data = NULL;
+- }
+-
+- printk(KERN_ERR "p54: eeprom parse failed!\n");
+- return err;
+-}
+-EXPORT_SYMBOL_GPL(p54_parse_eeprom);
+-
+-void p54_fill_eeprom_readback(struct p54_control_hdr *hdr)
+-{
+- struct p54_eeprom_lm86 *eeprom_hdr;
+-
+- hdr->magic1 = cpu_to_le16(0x8000);
+- hdr->len = cpu_to_le16(sizeof(*eeprom_hdr) + 0x2000);
+- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_EEPROM_READBACK);
+- hdr->retry1 = hdr->retry2 = 0;
+- eeprom_hdr = (struct p54_eeprom_lm86 *) hdr->data;
+- eeprom_hdr->offset = 0x0;
+- eeprom_hdr->len = cpu_to_le16(0x2000);
+-}
+-EXPORT_SYMBOL_GPL(p54_fill_eeprom_readback);
+-
+-static void p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
+-{
+- struct p54_rx_hdr *hdr = (struct p54_rx_hdr *) skb->data;
+- struct ieee80211_rx_status rx_status = {0};
+- u16 freq = le16_to_cpu(hdr->freq);
+-
+- rx_status.ssi = hdr->rssi;
+- rx_status.rate = hdr->rate & 0x1f; /* report short preambles & CCK too */
+- rx_status.channel = freq == 2484 ? 14 : (freq - 2407)/5;
+- rx_status.freq = freq;
+- rx_status.phymode = MODE_IEEE80211G;
+- rx_status.antenna = hdr->antenna;
+- rx_status.mactime = le64_to_cpu(hdr->timestamp);
+- rx_status.flag |= RX_FLAG_TSFT;
+-
+- skb_pull(skb, sizeof(*hdr));
+- skb_trim(skb, le16_to_cpu(hdr->len));
+-
+- ieee80211_rx_irqsafe(dev, skb, &rx_status);
+-}
+-
+-static void inline p54_wake_free_queues(struct ieee80211_hw *dev)
+-{
+- struct p54_common *priv = dev->priv;
+- int i;
+-
+- /* ieee80211_start_queues is great if all queues are really empty.
+- * But, what if some are full? */
+-
+- for (i = 0; i < dev->queues; i++)
+- if (priv->tx_stats.data[i].len < priv->tx_stats.data[i].limit)
+- ieee80211_wake_queue(dev, i);
+-}
+-
+-static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
+-{
+- struct p54_common *priv = dev->priv;
+- struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
+- struct p54_frame_sent_hdr *payload = (struct p54_frame_sent_hdr *) hdr->data;
+- struct sk_buff *entry = (struct sk_buff *) priv->tx_queue.next;
+- u32 addr = le32_to_cpu(hdr->req_id) - 0x70;
+- struct memrecord *range = NULL;
+- u32 freed = 0;
+- u32 last_addr = priv->rx_start;
+-
+- while (entry != (struct sk_buff *)&priv->tx_queue) {
+- range = (struct memrecord *)&entry->cb;
+- if (range->start_addr == addr) {
+- struct ieee80211_tx_status status = {{0}};
+- struct p54_control_hdr *entry_hdr;
+- struct p54_tx_control_allocdata *entry_data;
+- int pad = 0;
+-
+- if (entry->next != (struct sk_buff *)&priv->tx_queue)
+- freed = ((struct memrecord *)&entry->next->cb)->start_addr - last_addr;
+- else
+- freed = priv->rx_end - last_addr;
+-
+- last_addr = range->end_addr;
+- __skb_unlink(entry, &priv->tx_queue);
+- if (!range->control) {
+- kfree_skb(entry);
+- break;
+- }
+- memcpy(&status.control, range->control,
+- sizeof(status.control));
+- kfree(range->control);
+- priv->tx_stats.data[status.control.queue].len--;
+-
+- entry_hdr = (struct p54_control_hdr *) entry->data;
+- entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data;
+- if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0)
+- pad = entry_data->align[0];
+-
+- if (!(status.control.flags & IEEE80211_TXCTL_NO_ACK)) {
+- if (!(payload->status & 0x01))
+- status.flags |= IEEE80211_TX_STATUS_ACK;
+- else
+- status.excessive_retries = 1;
+- }
+- status.retry_count = payload->retries - 1;
+- status.ack_signal = le16_to_cpu(payload->ack_rssi);
+- skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data));
+- ieee80211_tx_status_irqsafe(dev, entry, &status);
+- break;
+- } else
+- last_addr = range->end_addr;
+- entry = entry->next;
+- }
+-
+- if (freed >= IEEE80211_MAX_RTS_THRESHOLD + 0x170 +
+- sizeof(struct p54_control_hdr))
+- p54_wake_free_queues(dev);
+-}
+-
+-static void p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb)
+-{
+- struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
+-
+- switch (le16_to_cpu(hdr->type)) {
+- case P54_CONTROL_TYPE_TXDONE:
+- p54_rx_frame_sent(dev, skb);
+- break;
+- case P54_CONTROL_TYPE_BBP:
+- break;
+- default:
+- printk(KERN_DEBUG "%s: not handling 0x%02x type control frame\n",
+- wiphy_name(dev->wiphy), le16_to_cpu(hdr->type));
+- break;
+- }
+-}
+-
+-/* returns zero if skb can be reused */
+-int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb)
+-{
+- u8 type = le16_to_cpu(*((__le16 *)skb->data)) >> 8;
+- switch (type) {
+- case 0x00:
+- case 0x01:
+- p54_rx_data(dev, skb);
+- return -1;
+- case 0x4d:
+- /* TODO: do something better... but then again, I've never seen this happen */
+- printk(KERN_ERR "%s: Received fault. Probably need to restart hardware now..\n",
+- wiphy_name(dev->wiphy));
+- break;
+- case 0x80:
+- p54_rx_control(dev, skb);
+- break;
+- default:
+- printk(KERN_ERR "%s: unknown frame RXed (0x%02x)\n",
+- wiphy_name(dev->wiphy), type);
+- break;
+- }
+- return 0;
+-}
+-EXPORT_SYMBOL_GPL(p54_rx);
+-
+-/*
+- * So, the firmware is somewhat stupid and doesn't know what places in its
+- * memory incoming data should go to. By poking around in the firmware, we
+- * can find some unused memory to upload our packets to. However, data that we
+- * want the card to TX needs to stay intact until the card has told us that
+- * it is done with it. This function finds empty places we can upload to and
+- * marks allocated areas as reserved if necessary. p54_rx_frame_sent frees
+- * allocated areas.
+- */
+-static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
+- struct p54_control_hdr *data, u32 len,
+- struct ieee80211_tx_control *control)
+-{
+- struct p54_common *priv = dev->priv;
+- struct sk_buff *entry = priv->tx_queue.next;
+- struct sk_buff *target_skb = NULL;
+- struct memrecord *range;
+- u32 last_addr = priv->rx_start;
+- u32 largest_hole = 0;
+- u32 target_addr = priv->rx_start;
+- unsigned long flags;
+- unsigned int left;
+- len = (len + 0x170 + 3) & ~0x3; /* 0x70 headroom, 0x100 tailroom */
+-
+- spin_lock_irqsave(&priv->tx_queue.lock, flags);
+- left = skb_queue_len(&priv->tx_queue);
+- while (left--) {
+- u32 hole_size;
+- range = (struct memrecord *)&entry->cb;
+- hole_size = range->start_addr - last_addr;
+- if (!target_skb && hole_size >= len) {
+- target_skb = entry->prev;
+- hole_size -= len;
+- target_addr = last_addr;
+- }
+- largest_hole = max(largest_hole, hole_size);
+- last_addr = range->end_addr;
+- entry = entry->next;
+- }
+- if (!target_skb && priv->rx_end - last_addr >= len) {
+- target_skb = priv->tx_queue.prev;
+- largest_hole = max(largest_hole, priv->rx_end - last_addr - len);
+- if (!skb_queue_empty(&priv->tx_queue)) {
+- range = (struct memrecord *)&target_skb->cb;
+- target_addr = range->end_addr;
+- }
+- } else
+- largest_hole = max(largest_hole, priv->rx_end - last_addr);
+-
+- if (skb) {
+- range = (struct memrecord *)&skb->cb;
+- range->start_addr = target_addr;
+- range->end_addr = target_addr + len;
+- range->control = control;
+- __skb_queue_after(&priv->tx_queue, target_skb, skb);
+- if (largest_hole < IEEE80211_MAX_RTS_THRESHOLD + 0x170 +
+- sizeof(struct p54_control_hdr))
+- ieee80211_stop_queues(dev);
+- }
+- spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+-
+- data->req_id = cpu_to_le32(target_addr + 0x70);
+-}
+-
+-static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
+- struct ieee80211_tx_control *control)
+-{
+- struct ieee80211_tx_queue_stats_data *current_queue;
+- struct p54_common *priv = dev->priv;
+- struct p54_control_hdr *hdr;
+- struct p54_tx_control_allocdata *txhdr;
+- struct ieee80211_tx_control *control_copy;
+- size_t padding, len;
+- u8 rate;
+-
+- current_queue = &priv->tx_stats.data[control->queue];
+- if (unlikely(current_queue->len > current_queue->limit))
+- return NETDEV_TX_BUSY;
+- current_queue->len++;
+- current_queue->count++;
+- if (current_queue->len == current_queue->limit)
+- ieee80211_stop_queue(dev, control->queue);
+-
+- padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3;
+- len = skb->len;
+-
+- control_copy = kmalloc(sizeof(*control), GFP_ATOMIC);
+- if (control_copy)
+- memcpy(control_copy, control, sizeof(*control));
+-
+- txhdr = (struct p54_tx_control_allocdata *)
+- skb_push(skb, sizeof(*txhdr) + padding);
+- hdr = (struct p54_control_hdr *) skb_push(skb, sizeof(*hdr));
+-
+- if (padding)
+- hdr->magic1 = cpu_to_le16(0x4010);
+- else
+- hdr->magic1 = cpu_to_le16(0x0010);
+- hdr->len = cpu_to_le16(len);
+- hdr->type = (control->flags & IEEE80211_TXCTL_NO_ACK) ? 0 : cpu_to_le16(1);
+- hdr->retry1 = hdr->retry2 = control->retry_limit;
+- p54_assign_address(dev, skb, hdr, skb->len, control_copy);
+-
+- memset(txhdr->wep_key, 0x0, 16);
+- txhdr->padding = 0;
+- txhdr->padding2 = 0;
+-
+- /* TODO: add support for alternate retry TX rates */
+- rate = control->tx_rate;
+- if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
+- rate |= 0x40;
+- else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
+- rate |= 0x20;
+- memset(txhdr->rateset, rate, 8);
+- txhdr->wep_key_present = 0;
+- txhdr->wep_key_len = 0;
+- txhdr->frame_type = cpu_to_le32(control->queue + 4);
+- txhdr->magic4 = 0;
+- txhdr->antenna = (control->antenna_sel_tx == 0) ?
+- 2 : control->antenna_sel_tx - 1;
+- txhdr->output_power = 0x7f; // HW Maximum
+- txhdr->magic5 = (control->flags & IEEE80211_TXCTL_NO_ACK) ?
+- 0 : ((rate > 0x3) ? cpu_to_le32(0x33) : cpu_to_le32(0x23));
+- if (padding)
+- txhdr->align[0] = padding;
+-
+- priv->tx(dev, hdr, skb->len, 0);
+- return 0;
+-}
+-
+-static int p54_set_filter(struct ieee80211_hw *dev, u16 filter_type,
+- const u8 *dst, const u8 *src, u8 antenna,
+- u32 magic3, u32 magic8, u32 magic9)
+-{
+- struct p54_common *priv = dev->priv;
+- struct p54_control_hdr *hdr;
+- struct p54_tx_control_filter *filter;
+-
+- hdr = kzalloc(sizeof(*hdr) + sizeof(*filter) +
+- priv->tx_hdr_len, GFP_ATOMIC);
+- if (!hdr)
+- return -ENOMEM;
+-
+- hdr = (void *)hdr + priv->tx_hdr_len;
+-
+- filter = (struct p54_tx_control_filter *) hdr->data;
+- hdr->magic1 = cpu_to_le16(0x8001);
+- hdr->len = cpu_to_le16(sizeof(*filter));
+- p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*filter), NULL);
+- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_FILTER_SET);
+-
+- filter->filter_type = cpu_to_le16(filter_type);
+- memcpy(filter->dst, dst, ETH_ALEN);
+- if (!src)
+- memset(filter->src, ~0, ETH_ALEN);
+- else
+- memcpy(filter->src, src, ETH_ALEN);
+- filter->antenna = antenna;
+- filter->magic3 = cpu_to_le32(magic3);
+- filter->rx_addr = cpu_to_le32(priv->rx_end);
+- filter->max_rx = cpu_to_le16(0x0620); /* FIXME: for usb ver 1.. maybe */
+- filter->rxhw = priv->rxhw;
+- filter->magic8 = cpu_to_le16(magic8);
+- filter->magic9 = cpu_to_le16(magic9);
+-
+- priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*filter), 1);
+- return 0;
+-}
+-
+-static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq)
+-{
+- struct p54_common *priv = dev->priv;
+- struct p54_control_hdr *hdr;
+- struct p54_tx_control_channel *chan;
+- unsigned int i;
+- size_t payload_len = sizeof(*chan) + sizeof(u32)*2 +
+- sizeof(*chan->curve_data) *
+- priv->curve_data->points_per_channel;
+- void *entry;
+-
+- hdr = kzalloc(sizeof(*hdr) + payload_len +
+- priv->tx_hdr_len, GFP_KERNEL);
+- if (!hdr)
+- return -ENOMEM;
+-
+- hdr = (void *)hdr + priv->tx_hdr_len;
+-
+- chan = (struct p54_tx_control_channel *) hdr->data;
+-
+- hdr->magic1 = cpu_to_le16(0x8001);
+- hdr->len = cpu_to_le16(sizeof(*chan));
+- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_CHANNEL_CHANGE);
+- p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + payload_len, NULL);
+-
+- chan->magic1 = cpu_to_le16(0x1);
+- chan->magic2 = cpu_to_le16(0x0);
+-
+- for (i = 0; i < priv->iq_autocal_len; i++) {
+- if (priv->iq_autocal[i].freq != freq)
+- continue;
+-
+- memcpy(&chan->iq_autocal, &priv->iq_autocal[i],
+- sizeof(*priv->iq_autocal));
+- break;
+- }
+- if (i == priv->iq_autocal_len)
+- goto err;
+-
+- for (i = 0; i < priv->output_limit_len; i++) {
+- if (priv->output_limit[i].freq != freq)
+- continue;
+-
+- chan->val_barker = 0x38;
+- chan->val_bpsk = priv->output_limit[i].val_bpsk;
+- chan->val_qpsk = priv->output_limit[i].val_qpsk;
+- chan->val_16qam = priv->output_limit[i].val_16qam;
+- chan->val_64qam = priv->output_limit[i].val_64qam;
+- break;
+- }
+- if (i == priv->output_limit_len)
+- goto err;
+-
+- chan->pa_points_per_curve = priv->curve_data->points_per_channel;
+-
+- entry = priv->curve_data->data;
+- for (i = 0; i < priv->curve_data->channels; i++) {
+- if (*((__le16 *)entry) != freq) {
+- entry += sizeof(__le16);
+- entry += sizeof(struct pda_pa_curve_data_sample_rev1) *
+- chan->pa_points_per_curve;
+- continue;
+- }
+-
+- entry += sizeof(__le16);
+- memcpy(chan->curve_data, entry, sizeof(*chan->curve_data) *
+- chan->pa_points_per_curve);
+- break;
+- }
+-
+- memcpy(hdr->data + payload_len - 4, &chan->val_bpsk, 4);
+-
+- priv->tx(dev, hdr, sizeof(*hdr) + payload_len, 1);
+- return 0;
+-
+- err:
+- printk(KERN_ERR "%s: frequency change failed\n", wiphy_name(dev->wiphy));
+- kfree(hdr);
+- return -EINVAL;
+-}
+-
+-static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act)
+-{
+- struct p54_common *priv = dev->priv;
+- struct p54_control_hdr *hdr;
+- struct p54_tx_control_led *led;
+-
+- hdr = kzalloc(sizeof(*hdr) + sizeof(*led) +
+- priv->tx_hdr_len, GFP_KERNEL);
+- if (!hdr)
+- return -ENOMEM;
+-
+- hdr = (void *)hdr + priv->tx_hdr_len;
+- hdr->magic1 = cpu_to_le16(0x8001);
+- hdr->len = cpu_to_le16(sizeof(*led));
+- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_LED);
+- p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*led), NULL);
+-
+- led = (struct p54_tx_control_led *) hdr->data;
+- led->mode = cpu_to_le16(mode);
+- led->led_permanent = cpu_to_le16(link);
+- led->led_temporary = cpu_to_le16(act);
+- led->duration = cpu_to_le16(1000);
+-
+- priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*led), 1);
+-
+- return 0;
+-}
+-
+-#define P54_SET_QUEUE(queue, ai_fs, cw_min, cw_max, burst) \
+-do { \
+- queue.aifs = cpu_to_le16(ai_fs); \
+- queue.cwmin = cpu_to_le16(cw_min); \
+- queue.cwmax = cpu_to_le16(cw_max); \
+- queue.txop = (burst == 0) ? \
+- 0 : cpu_to_le16((burst * 100) / 32 + 1); \
+-} while(0)
+-
+-static void p54_init_vdcf(struct ieee80211_hw *dev)
+-{
+- struct p54_common *priv = dev->priv;
+- struct p54_control_hdr *hdr;
+- struct p54_tx_control_vdcf *vdcf;
+-
+- /* all USB V1 adapters need a extra headroom */
+- hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len;
+- hdr->magic1 = cpu_to_le16(0x8001);
+- hdr->len = cpu_to_le16(sizeof(*vdcf));
+- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_DCFINIT);
+- hdr->req_id = cpu_to_le32(priv->rx_start);
+-
+- vdcf = (struct p54_tx_control_vdcf *) hdr->data;
+-
+- P54_SET_QUEUE(vdcf->queue[0], 0x0002, 0x0003, 0x0007, 0x000f);
+- P54_SET_QUEUE(vdcf->queue[1], 0x0002, 0x0007, 0x000f, 0x001e);
+- P54_SET_QUEUE(vdcf->queue[2], 0x0002, 0x000f, 0x03ff, 0x0014);
+- P54_SET_QUEUE(vdcf->queue[3], 0x0007, 0x000f, 0x03ff, 0x0000);
+-}
+-
+-static void p54_set_vdcf(struct ieee80211_hw *dev)
+-{
+- struct p54_common *priv = dev->priv;
+- struct p54_control_hdr *hdr;
+- struct p54_tx_control_vdcf *vdcf;
+-
+- hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len;
+-
+- p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*vdcf), NULL);
+-
+- vdcf = (struct p54_tx_control_vdcf *) hdr->data;
+-
+- if (dev->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
+- vdcf->slottime = 9;
+- vdcf->magic1 = 0x00;
+- vdcf->magic2 = 0x10;
+- } else {
+- vdcf->slottime = 20;
+- vdcf->magic1 = 0x0a;
+- vdcf->magic2 = 0x06;
+- }
+-
+- /* (see prism54/isl_oid.h for further details) */
+- vdcf->frameburst = cpu_to_le16(0);
+-
+- priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*vdcf), 0);
+-}
+-
+-static int p54_start(struct ieee80211_hw *dev)
+-{
+- struct p54_common *priv = dev->priv;
+- int err;
+-
+- err = priv->open(dev);
+- if (!err)
+- priv->mode = IEEE80211_IF_TYPE_MNTR;
+-
+- return err;
+-}
+-
+-static void p54_stop(struct ieee80211_hw *dev)
+-{
+- struct p54_common *priv = dev->priv;
+- struct sk_buff *skb;
+- while ((skb = skb_dequeue(&priv->tx_queue))) {
+- struct memrecord *range = (struct memrecord *)&skb->cb;
+- if (range->control)
+- kfree(range->control);
+- kfree_skb(skb);
+- }
+- priv->stop(dev);
+- priv->mode = IEEE80211_IF_TYPE_INVALID;
+-}
+-
+-static int p54_add_interface(struct ieee80211_hw *dev,
+- struct ieee80211_if_init_conf *conf)
+-{
+- struct p54_common *priv = dev->priv;
+-
+- if (priv->mode != IEEE80211_IF_TYPE_MNTR)
+- return -EOPNOTSUPP;
+-
+- switch (conf->type) {
+- case IEEE80211_IF_TYPE_STA:
+- priv->mode = conf->type;
+- break;
+- default:
+- return -EOPNOTSUPP;
+- }
+-
+- memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
+-
+- p54_set_filter(dev, 0, priv->mac_addr, NULL, 0, 1, 0, 0xF642);
+- p54_set_filter(dev, 0, priv->mac_addr, NULL, 1, 0, 0, 0xF642);
+-
+- switch (conf->type) {
+- case IEEE80211_IF_TYPE_STA:
+- p54_set_filter(dev, 1, priv->mac_addr, NULL, 0, 0x15F, 0x1F4, 0);
+- break;
+- default:
+- BUG(); /* impossible */
+- break;
+- }
+-
+- p54_set_leds(dev, 1, 0, 0);
+-
+- return 0;
+-}
+-
+-static void p54_remove_interface(struct ieee80211_hw *dev,
+- struct ieee80211_if_init_conf *conf)
+-{
+- struct p54_common *priv = dev->priv;
+- priv->mode = IEEE80211_IF_TYPE_MNTR;
+- memset(priv->mac_addr, 0, ETH_ALEN);
+- p54_set_filter(dev, 0, priv->mac_addr, NULL, 2, 0, 0, 0);
+-}
+-
+-static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
+-{
+- int ret;
+-
+- ret = p54_set_freq(dev, cpu_to_le16(conf->freq));
+- p54_set_vdcf(dev);
+- return ret;
+-}
+-
+-static int p54_config_interface(struct ieee80211_hw *dev,
+- struct ieee80211_vif *vif,
+- struct ieee80211_if_conf *conf)
+-{
+- struct p54_common *priv = dev->priv;
+-
+- p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 0, 1, 0, 0xF642);
+- p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 2, 0, 0, 0);
+- p54_set_leds(dev, 1, !is_multicast_ether_addr(conf->bssid), 0);
+- memcpy(priv->bssid, conf->bssid, ETH_ALEN);
+- return 0;
+-}
+-
+-static void p54_configure_filter(struct ieee80211_hw *dev,
+- unsigned int changed_flags,
+- unsigned int *total_flags,
+- int mc_count, struct dev_mc_list *mclist)
+-{
+- struct p54_common *priv = dev->priv;
+-
+- *total_flags &= FIF_BCN_PRBRESP_PROMISC;
+-
+- if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
+- if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
+- p54_set_filter(dev, 0, priv->mac_addr,
+- NULL, 2, 0, 0, 0);
+- else
+- p54_set_filter(dev, 0, priv->mac_addr,
+- priv->bssid, 2, 0, 0, 0);
+- }
+-}
+-
+-static int p54_conf_tx(struct ieee80211_hw *dev, int queue,
+- const struct ieee80211_tx_queue_params *params)
+-{
+- struct p54_common *priv = dev->priv;
+- struct p54_tx_control_vdcf *vdcf;
+-
+- vdcf = (struct p54_tx_control_vdcf *)(((struct p54_control_hdr *)
+- ((void *)priv->cached_vdcf + priv->tx_hdr_len))->data);
+-
+- if ((params) && !((queue < 0) || (queue > 4))) {
+- P54_SET_QUEUE(vdcf->queue[queue], params->aifs,
+- params->cw_min, params->cw_max, params->burst_time);
+- } else
+- return -EINVAL;
+-
+- p54_set_vdcf(dev);
+-
+- return 0;
+-}
+-
+-static int p54_get_stats(struct ieee80211_hw *dev,
+- struct ieee80211_low_level_stats *stats)
+-{
+- /* TODO */
+- return 0;
+-}
+-
+-static int p54_get_tx_stats(struct ieee80211_hw *dev,
+- struct ieee80211_tx_queue_stats *stats)
+-{
+- struct p54_common *priv = dev->priv;
+- unsigned int i;
+-
+- for (i = 0; i < dev->queues; i++)
+- memcpy(&stats->data[i], &priv->tx_stats.data[i],
+- sizeof(stats->data[i]));
+-
+- return 0;
+-}
+-
+-static const struct ieee80211_ops p54_ops = {
+- .tx = p54_tx,
+- .start = p54_start,
+- .stop = p54_stop,
+- .add_interface = p54_add_interface,
+- .remove_interface = p54_remove_interface,
+- .config = p54_config,
+- .config_interface = p54_config_interface,
+- .configure_filter = p54_configure_filter,
+- .conf_tx = p54_conf_tx,
+- .get_stats = p54_get_stats,
+- .get_tx_stats = p54_get_tx_stats
+-};
+-
+-struct ieee80211_hw *p54_init_common(size_t priv_data_len)
+-{
+- struct ieee80211_hw *dev;
+- struct p54_common *priv;
+- int i;
+-
+- dev = ieee80211_alloc_hw(priv_data_len, &p54_ops);
+- if (!dev)
+- return NULL;
+-
+- priv = dev->priv;
+- priv->mode = IEEE80211_IF_TYPE_INVALID;
+- skb_queue_head_init(&priv->tx_queue);
+- memcpy(priv->channels, p54_channels, sizeof(p54_channels));
+- memcpy(priv->rates, p54_rates, sizeof(p54_rates));
+- priv->modes[1].mode = MODE_IEEE80211B;
+- priv->modes[1].num_rates = 4;
+- priv->modes[1].rates = priv->rates;
+- priv->modes[1].num_channels = ARRAY_SIZE(p54_channels);
+- priv->modes[1].channels = priv->channels;
+- priv->modes[0].mode = MODE_IEEE80211G;
+- priv->modes[0].num_rates = ARRAY_SIZE(p54_rates);
+- priv->modes[0].rates = priv->rates;
+- priv->modes[0].num_channels = ARRAY_SIZE(p54_channels);
+- priv->modes[0].channels = priv->channels;
+- dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */
+- IEEE80211_HW_RX_INCLUDES_FCS;
+- dev->channel_change_time = 1000; /* TODO: find actual value */
+- dev->max_rssi = 127;
+-
+- priv->tx_stats.data[0].limit = 5;
+- dev->queues = 1;
+-
+- dev->extra_tx_headroom = sizeof(struct p54_control_hdr) + 4 +
+- sizeof(struct p54_tx_control_allocdata);
+-
+- priv->cached_vdcf = kzalloc(sizeof(struct p54_tx_control_vdcf) +
+- priv->tx_hdr_len + sizeof(struct p54_control_hdr), GFP_KERNEL);
+-
+- if (!priv->cached_vdcf) {
+- ieee80211_free_hw(dev);
+- return NULL;
+- }
+-
+- p54_init_vdcf(dev);
+-
+- for (i = 0; i < 2; i++) {
+- if (ieee80211_register_hwmode(dev, &priv->modes[i])) {
+- kfree(priv->cached_vdcf);
+- ieee80211_free_hw(dev);
+- return NULL;
+- }
+- }
+-
+- return dev;
+-}
+-EXPORT_SYMBOL_GPL(p54_init_common);
+-
+-void p54_free_common(struct ieee80211_hw *dev)
+-{
+- struct p54_common *priv = dev->priv;
+- kfree(priv->iq_autocal);
+- kfree(priv->output_limit);
+- kfree(priv->curve_data);
+- kfree(priv->cached_vdcf);
+-}
+-EXPORT_SYMBOL_GPL(p54_free_common);
+-
+-static int __init p54_init(void)
+-{
+- return 0;
+-}
+-
+-static void __exit p54_exit(void)
+-{
+-}
+-
+-module_init(p54_init);
+-module_exit(p54_exit);
+diff --git a/drivers/net/wireless/p54common.h b/drivers/net/wireless/p54common.h
+deleted file mode 100644
+index b67ff34..0000000
+--- a/drivers/net/wireless/p54common.h
++++ /dev/null
+@@ -1,329 +0,0 @@
+-#ifndef PRISM54COMMON_H
+-#define PRISM54COMMON_H
+-
+-/*
+- * Common code specific definitions for mac80211 Prism54 drivers
+- *
+- * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
+- * Copyright (c) 2007, Christian Lamparter <chunkeey at web.de>
+- *
+- * Based on the islsm (softmac prism54) driver, which is:
+- * Copyright 2004-2006 Jean-Baptiste Note <jbnote at gmail.com>, et al.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-struct bootrec {
+- __le32 code;
+- __le32 len;
+- u32 data[0];
+-} __attribute__((packed));
+-
+-struct bootrec_exp_if {
+- __le16 role;
+- __le16 if_id;
+- __le16 variant;
+- __le16 btm_compat;
+- __le16 top_compat;
+-} __attribute__((packed));
+-
+-#define BR_CODE_MIN 0x80000000
+-#define BR_CODE_COMPONENT_ID 0x80000001
+-#define BR_CODE_COMPONENT_VERSION 0x80000002
+-#define BR_CODE_DEPENDENT_IF 0x80000003
+-#define BR_CODE_EXPOSED_IF 0x80000004
+-#define BR_CODE_DESCR 0x80000101
+-#define BR_CODE_MAX 0x8FFFFFFF
+-#define BR_CODE_END_OF_BRA 0xFF0000FF
+-#define LEGACY_BR_CODE_END_OF_BRA 0xFFFFFFFF
+-
+-#define FW_FMAC 0x464d4143
+-#define FW_LM86 0x4c4d3836
+-#define FW_LM87 0x4c4d3837
+-#define FW_LM20 0x4c4d3230
+-
+-/* PDA defines are Copyright (C) 2005 Nokia Corporation (taken from islsm_pda.h) */
+-
+-struct pda_entry {
+- __le16 len; /* includes both code and data */
+- __le16 code;
+- u8 data[0];
+-} __attribute__ ((packed));
+-
+-struct eeprom_pda_wrap {
+- __le32 magic;
+- __le16 pad;
+- __le16 len;
+- __le32 arm_opcode;
+- u8 data[0];
+-} __attribute__ ((packed));
+-
+-struct pda_iq_autocal_entry {
+- __le16 freq;
+- __le16 iq_param[4];
+-} __attribute__ ((packed));
+-
+-struct pda_channel_output_limit {
+- __le16 freq;
+- u8 val_bpsk;
+- u8 val_qpsk;
+- u8 val_16qam;
+- u8 val_64qam;
+- u8 rate_set_mask;
+- u8 rate_set_size;
+-} __attribute__ ((packed));
+-
+-struct pda_pa_curve_data_sample_rev0 {
+- u8 rf_power;
+- u8 pa_detector;
+- u8 pcv;
+-} __attribute__ ((packed));
+-
+-struct pda_pa_curve_data_sample_rev1 {
+- u8 rf_power;
+- u8 pa_detector;
+- u8 data_barker;
+- u8 data_bpsk;
+- u8 data_qpsk;
+- u8 data_16qam;
+- u8 data_64qam;
+- u8 padding;
+-} __attribute__ ((packed));
+-
+-struct pda_pa_curve_data {
+- u8 cal_method_rev;
+- u8 channels;
+- u8 points_per_channel;
+- u8 padding;
+- u8 data[0];
+-} __attribute__ ((packed));
+-
+-/*
+- * this defines the PDR codes used to build PDAs as defined in document
+- * number 553155. The current implementation mirrors version 1.1 of the
+- * document and lists only PDRs supported by the ARM platform.
+- */
+-
+-/* common and choice range (0x0000 - 0x0fff) */
+-#define PDR_END 0x0000
+-#define PDR_MANUFACTURING_PART_NUMBER 0x0001
+-#define PDR_PDA_VERSION 0x0002
+-#define PDR_NIC_SERIAL_NUMBER 0x0003
+-
+-#define PDR_MAC_ADDRESS 0x0101
+-#define PDR_REGULATORY_DOMAIN_LIST 0x0103
+-#define PDR_TEMPERATURE_TYPE 0x0107
+-
+-#define PDR_PRISM_PCI_IDENTIFIER 0x0402
+-
+-/* ARM range (0x1000 - 0x1fff) */
+-#define PDR_COUNTRY_INFORMATION 0x1000
+-#define PDR_INTERFACE_LIST 0x1001
+-#define PDR_HARDWARE_PLATFORM_COMPONENT_ID 0x1002
+-#define PDR_OEM_NAME 0x1003
+-#define PDR_PRODUCT_NAME 0x1004
+-#define PDR_UTF8_OEM_NAME 0x1005
+-#define PDR_UTF8_PRODUCT_NAME 0x1006
+-#define PDR_COUNTRY_LIST 0x1007
+-#define PDR_DEFAULT_COUNTRY 0x1008
+-
+-#define PDR_ANTENNA_GAIN 0x1100
+-
+-#define PDR_PRISM_INDIGO_PA_CALIBRATION_DATA 0x1901
+-#define PDR_RSSI_LINEAR_APPROXIMATION 0x1902
+-#define PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS 0x1903
+-#define PDR_PRISM_PA_CAL_CURVE_DATA 0x1904
+-#define PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND 0x1905
+-#define PDR_PRISM_ZIF_TX_IQ_CALIBRATION 0x1906
+-#define PDR_REGULATORY_POWER_LIMITS 0x1907
+-#define PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED 0x1908
+-#define PDR_RADIATED_TRANSMISSION_CORRECTION 0x1909
+-#define PDR_PRISM_TX_IQ_CALIBRATION 0x190a
+-
+-/* reserved range (0x2000 - 0x7fff) */
+-
+-/* customer range (0x8000 - 0xffff) */
+-#define PDR_BASEBAND_REGISTERS 0x8000
+-#define PDR_PER_CHANNEL_BASEBAND_REGISTERS 0x8001
+-
+-/* stored in skb->cb */
+-struct memrecord {
+- u32 start_addr;
+- u32 end_addr;
+- struct ieee80211_tx_control *control;
+-};
+-
+-struct p54_eeprom_lm86 {
+- __le16 offset;
+- __le16 len;
+- u8 data[0];
+-} __attribute__ ((packed));
+-
+-struct p54_rx_hdr {
+- __le16 magic;
+- __le16 len;
+- __le16 freq;
+- u8 antenna;
+- u8 rate;
+- u8 rssi;
+- u8 quality;
+- u16 unknown2;
+- __le64 timestamp;
+- u8 data[0];
+-} __attribute__ ((packed));
+-
+-struct p54_frame_sent_hdr {
+- u8 status;
+- u8 retries;
+- __le16 ack_rssi;
+- __le16 seq;
+- u16 rate;
+-} __attribute__ ((packed));
+-
+-struct p54_tx_control_allocdata {
+- u8 rateset[8];
+- u16 padding;
+- u8 wep_key_present;
+- u8 wep_key_len;
+- u8 wep_key[16];
+- __le32 frame_type;
+- u32 padding2;
+- __le16 magic4;
+- u8 antenna;
+- u8 output_power;
+- __le32 magic5;
+- u8 align[0];
+-} __attribute__ ((packed));
+-
+-struct p54_tx_control_filter {
+- __le16 filter_type;
+- u8 dst[ETH_ALEN];
+- u8 src[ETH_ALEN];
+- u8 antenna;
+- u8 debug;
+- __le32 magic3;
+- u8 rates[8]; // FIXME: what's this for?
+- __le32 rx_addr;
+- __le16 max_rx;
+- __le16 rxhw;
+- __le16 magic8;
+- __le16 magic9;
+-} __attribute__ ((packed));
+-
+-struct p54_tx_control_channel {
+- __le16 magic1;
+- __le16 magic2;
+- u8 padding1[20];
+- struct pda_iq_autocal_entry iq_autocal;
+- u8 pa_points_per_curve;
+- u8 val_barker;
+- u8 val_bpsk;
+- u8 val_qpsk;
+- u8 val_16qam;
+- u8 val_64qam;
+- struct pda_pa_curve_data_sample_rev1 curve_data[0];
+- /* additional padding/data after curve_data */
+-} __attribute__ ((packed));
+-
+-struct p54_tx_control_led {
+- __le16 mode;
+- __le16 led_temporary;
+- __le16 led_permanent;
+- __le16 duration;
+-} __attribute__ ((packed));
+-
+-struct p54_tx_vdcf_queues {
+- __le16 aifs;
+- __le16 cwmin;
+- __le16 cwmax;
+- __le16 txop;
+-} __attribute__ ((packed));
+-
+-struct p54_tx_control_vdcf {
+- u8 padding;
+- u8 slottime;
+- u8 magic1;
+- u8 magic2;
+- struct p54_tx_vdcf_queues queue[8];
+- u8 pad2[4];
+- __le16 frameburst;
+-} __attribute__ ((packed));
+-
+-static const struct ieee80211_rate p54_rates[] = {
+- { .rate = 10,
+- .val = 0,
+- .val2 = 0x10,
+- .flags = IEEE80211_RATE_CCK_2 },
+- { .rate = 20,
+- .val = 1,
+- .val2 = 0x11,
+- .flags = IEEE80211_RATE_CCK_2 },
+- { .rate = 55,
+- .val = 2,
+- .val2 = 0x12,
+- .flags = IEEE80211_RATE_CCK_2 },
+- { .rate = 110,
+- .val = 3,
+- .val2 = 0x13,
+- .flags = IEEE80211_RATE_CCK_2 },
+- { .rate = 60,
+- .val = 4,
+- .flags = IEEE80211_RATE_OFDM },
+- { .rate = 90,
+- .val = 5,
+- .flags = IEEE80211_RATE_OFDM },
+- { .rate = 120,
+- .val = 6,
+- .flags = IEEE80211_RATE_OFDM },
+- { .rate = 180,
+- .val = 7,
+- .flags = IEEE80211_RATE_OFDM },
+- { .rate = 240,
+- .val = 8,
+- .flags = IEEE80211_RATE_OFDM },
+- { .rate = 360,
+- .val = 9,
+- .flags = IEEE80211_RATE_OFDM },
+- { .rate = 480,
+- .val = 10,
+- .flags = IEEE80211_RATE_OFDM },
+- { .rate = 540,
+- .val = 11,
+- .flags = IEEE80211_RATE_OFDM },
+-};
+-
+-// TODO: just generate this..
+-static const struct ieee80211_channel p54_channels[] = {
+- { .chan = 1,
+- .freq = 2412},
+- { .chan = 2,
+- .freq = 2417},
+- { .chan = 3,
+- .freq = 2422},
+- { .chan = 4,
+- .freq = 2427},
+- { .chan = 5,
+- .freq = 2432},
+- { .chan = 6,
+- .freq = 2437},
+- { .chan = 7,
+- .freq = 2442},
+- { .chan = 8,
+- .freq = 2447},
+- { .chan = 9,
+- .freq = 2452},
+- { .chan = 10,
+- .freq = 2457},
+- { .chan = 11,
+- .freq = 2462},
+- { .chan = 12,
+- .freq = 2467},
+- { .chan = 13,
+- .freq = 2472},
+- { .chan = 14,
+- .freq = 2484}
+-};
+-
+-#endif /* PRISM54COMMON_H */
+diff --git a/drivers/net/wireless/p54pci.c b/drivers/net/wireless/p54pci.c
+deleted file mode 100644
+index fa52772..0000000
+--- a/drivers/net/wireless/p54pci.c
++++ /dev/null
+@@ -1,697 +0,0 @@
+-
+-/*
+- * Linux device driver for PCI based Prism54
+- *
+- * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
+- *
+- * Based on the islsm (softmac prism54) driver, which is:
+- * Copyright 2004-2006 Jean-Baptiste Note <jean-baptiste.note at m4x.org>, et al.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#include <linux/init.h>
+-#include <linux/pci.h>
+-#include <linux/firmware.h>
+-#include <linux/etherdevice.h>
+-#include <linux/delay.h>
+-#include <linux/completion.h>
+-#include <net/mac80211.h>
+-
+-#include "p54.h"
+-#include "p54pci.h"
+-
+-MODULE_AUTHOR("Michael Wu <flamingice at sourmilk.net>");
+-MODULE_DESCRIPTION("Prism54 PCI wireless driver");
+-MODULE_LICENSE("GPL");
+-MODULE_ALIAS("prism54pci");
+-
+-static struct pci_device_id p54p_table[] __devinitdata = {
+- /* Intersil PRISM Duette/Prism GT Wireless LAN adapter */
+- { PCI_DEVICE(0x1260, 0x3890) },
+- /* 3COM 3CRWE154G72 Wireless LAN adapter */
+- { PCI_DEVICE(0x10b7, 0x6001) },
+- /* Intersil PRISM Indigo Wireless LAN adapter */
+- { PCI_DEVICE(0x1260, 0x3877) },
+- /* Intersil PRISM Javelin/Xbow Wireless LAN adapter */
+- { PCI_DEVICE(0x1260, 0x3886) },
+- { },
+-};
+-
+-MODULE_DEVICE_TABLE(pci, p54p_table);
+-
+-static int p54p_upload_firmware(struct ieee80211_hw *dev)
+-{
+- struct p54p_priv *priv = dev->priv;
+- const struct firmware *fw_entry = NULL;
+- __le32 reg;
+- int err;
+- __le32 *data;
+- u32 remains, left, device_addr;
+-
+- P54P_WRITE(int_enable, cpu_to_le32(0));
+- P54P_READ(int_enable);
+- udelay(10);
+-
+- reg = P54P_READ(ctrl_stat);
+- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
+- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT);
+- P54P_WRITE(ctrl_stat, reg);
+- P54P_READ(ctrl_stat);
+- udelay(10);
+-
+- reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
+- P54P_WRITE(ctrl_stat, reg);
+- wmb();
+- udelay(10);
+-
+- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
+- P54P_WRITE(ctrl_stat, reg);
+- wmb();
+-
+- mdelay(50);
+-
+- err = request_firmware(&fw_entry, "isl3886", &priv->pdev->dev);
+- if (err) {
+- printk(KERN_ERR "%s (prism54pci): cannot find firmware "
+- "(isl3886)\n", pci_name(priv->pdev));
+- return err;
+- }
+-
+- p54_parse_firmware(dev, fw_entry);
+-
+- data = (__le32 *) fw_entry->data;
+- remains = fw_entry->size;
+- device_addr = ISL38XX_DEV_FIRMWARE_ADDR;
+- while (remains) {
+- u32 i = 0;
+- left = min((u32)0x1000, remains);
+- P54P_WRITE(direct_mem_base, cpu_to_le32(device_addr));
+- P54P_READ(int_enable);
+-
+- device_addr += 0x1000;
+- while (i < left) {
+- P54P_WRITE(direct_mem_win[i], *data++);
+- i += sizeof(u32);
+- }
+-
+- remains -= left;
+- P54P_READ(int_enable);
+- }
+-
+- release_firmware(fw_entry);
+-
+- reg = P54P_READ(ctrl_stat);
+- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
+- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
+- reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT);
+- P54P_WRITE(ctrl_stat, reg);
+- P54P_READ(ctrl_stat);
+- udelay(10);
+-
+- reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
+- P54P_WRITE(ctrl_stat, reg);
+- wmb();
+- udelay(10);
+-
+- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
+- P54P_WRITE(ctrl_stat, reg);
+- wmb();
+- udelay(10);
+-
+- return 0;
+-}
+-
+-static irqreturn_t p54p_simple_interrupt(int irq, void *dev_id)
+-{
+- struct p54p_priv *priv = (struct p54p_priv *) dev_id;
+- __le32 reg;
+-
+- reg = P54P_READ(int_ident);
+- P54P_WRITE(int_ack, reg);
+-
+- if (reg & P54P_READ(int_enable))
+- complete(&priv->boot_comp);
+-
+- return IRQ_HANDLED;
+-}
+-
+-static int p54p_read_eeprom(struct ieee80211_hw *dev)
+-{
+- struct p54p_priv *priv = dev->priv;
+- struct p54p_ring_control *ring_control = priv->ring_control;
+- int err;
+- struct p54_control_hdr *hdr;
+- void *eeprom;
+- dma_addr_t rx_mapping, tx_mapping;
+- u16 alen;
+-
+- init_completion(&priv->boot_comp);
+- err = request_irq(priv->pdev->irq, &p54p_simple_interrupt,
+- IRQF_SHARED, "prism54pci", priv);
+- if (err) {
+- printk(KERN_ERR "%s (prism54pci): failed to register IRQ handler\n",
+- pci_name(priv->pdev));
+- return err;
+- }
+-
+- eeprom = kmalloc(0x2010 + EEPROM_READBACK_LEN, GFP_KERNEL);
+- if (!eeprom) {
+- printk(KERN_ERR "%s (prism54pci): no memory for eeprom!\n",
+- pci_name(priv->pdev));
+- err = -ENOMEM;
+- goto out;
+- }
+-
+- memset(ring_control, 0, sizeof(*ring_control));
+- P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma));
+- P54P_READ(ring_control_base);
+- udelay(10);
+-
+- P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_INIT));
+- P54P_READ(int_enable);
+- udelay(10);
+-
+- P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
+-
+- if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) {
+- printk(KERN_ERR "%s (prism54pci): Cannot boot firmware!\n",
+- pci_name(priv->pdev));
+- err = -EINVAL;
+- goto out;
+- }
+-
+- P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_UPDATE));
+- P54P_READ(int_enable);
+-
+- hdr = eeprom + 0x2010;
+- p54_fill_eeprom_readback(hdr);
+- hdr->req_id = cpu_to_le32(priv->common.rx_start);
+-
+- rx_mapping = pci_map_single(priv->pdev, eeprom,
+- 0x2010, PCI_DMA_FROMDEVICE);
+- tx_mapping = pci_map_single(priv->pdev, (void *)hdr,
+- EEPROM_READBACK_LEN, PCI_DMA_TODEVICE);
+-
+- ring_control->rx_mgmt[0].host_addr = cpu_to_le32(rx_mapping);
+- ring_control->rx_mgmt[0].len = cpu_to_le16(0x2010);
+- ring_control->tx_data[0].host_addr = cpu_to_le32(tx_mapping);
+- ring_control->tx_data[0].device_addr = hdr->req_id;
+- ring_control->tx_data[0].len = cpu_to_le16(EEPROM_READBACK_LEN);
+-
+- ring_control->host_idx[2] = cpu_to_le32(1);
+- ring_control->host_idx[1] = cpu_to_le32(1);
+-
+- wmb();
+- mdelay(100);
+- P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
+-
+- wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ);
+- wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ);
+-
+- pci_unmap_single(priv->pdev, tx_mapping,
+- EEPROM_READBACK_LEN, PCI_DMA_TODEVICE);
+- pci_unmap_single(priv->pdev, rx_mapping,
+- 0x2010, PCI_DMA_FROMDEVICE);
+-
+- alen = le16_to_cpu(ring_control->rx_mgmt[0].len);
+- if (le32_to_cpu(ring_control->device_idx[2]) != 1 ||
+- alen < 0x10) {
+- printk(KERN_ERR "%s (prism54pci): Cannot read eeprom!\n",
+- pci_name(priv->pdev));
+- err = -EINVAL;
+- goto out;
+- }
+-
+- p54_parse_eeprom(dev, (u8 *)eeprom + 0x10, alen - 0x10);
+-
+- out:
+- kfree(eeprom);
+- P54P_WRITE(int_enable, cpu_to_le32(0));
+- P54P_READ(int_enable);
+- udelay(10);
+- free_irq(priv->pdev->irq, priv);
+- P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
+- return err;
+-}
+-
+-static void p54p_refill_rx_ring(struct ieee80211_hw *dev)
+-{
+- struct p54p_priv *priv = dev->priv;
+- struct p54p_ring_control *ring_control = priv->ring_control;
+- u32 limit, host_idx, idx;
+-
+- host_idx = le32_to_cpu(ring_control->host_idx[0]);
+- limit = host_idx;
+- limit -= le32_to_cpu(ring_control->device_idx[0]);
+- limit = ARRAY_SIZE(ring_control->rx_data) - limit;
+-
+- idx = host_idx % ARRAY_SIZE(ring_control->rx_data);
+- while (limit-- > 1) {
+- struct p54p_desc *desc = &ring_control->rx_data[idx];
+-
+- if (!desc->host_addr) {
+- struct sk_buff *skb;
+- dma_addr_t mapping;
+- skb = dev_alloc_skb(MAX_RX_SIZE);
+- if (!skb)
+- break;
+-
+- mapping = pci_map_single(priv->pdev,
+- skb_tail_pointer(skb),
+- MAX_RX_SIZE,
+- PCI_DMA_FROMDEVICE);
+- desc->host_addr = cpu_to_le32(mapping);
+- desc->device_addr = 0; // FIXME: necessary?
+- desc->len = cpu_to_le16(MAX_RX_SIZE);
+- desc->flags = 0;
+- priv->rx_buf[idx] = skb;
+- }
+-
+- idx++;
+- host_idx++;
+- idx %= ARRAY_SIZE(ring_control->rx_data);
+- }
+-
+- wmb();
+- ring_control->host_idx[0] = cpu_to_le32(host_idx);
+-}
+-
+-static irqreturn_t p54p_interrupt(int irq, void *dev_id)
+-{
+- struct ieee80211_hw *dev = dev_id;
+- struct p54p_priv *priv = dev->priv;
+- struct p54p_ring_control *ring_control = priv->ring_control;
+- __le32 reg;
+-
+- spin_lock(&priv->lock);
+- reg = P54P_READ(int_ident);
+- if (unlikely(reg == cpu_to_le32(0xFFFFFFFF))) {
+- spin_unlock(&priv->lock);
+- return IRQ_HANDLED;
+- }
+-
+- P54P_WRITE(int_ack, reg);
+-
+- reg &= P54P_READ(int_enable);
+-
+- if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)) {
+- struct p54p_desc *desc;
+- u32 idx, i;
+- i = priv->tx_idx;
+- i %= ARRAY_SIZE(ring_control->tx_data);
+- priv->tx_idx = idx = le32_to_cpu(ring_control->device_idx[1]);
+- idx %= ARRAY_SIZE(ring_control->tx_data);
+-
+- while (i != idx) {
+- desc = &ring_control->tx_data[i];
+- if (priv->tx_buf[i]) {
+- kfree(priv->tx_buf[i]);
+- priv->tx_buf[i] = NULL;
+- }
+-
+- pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
+- le16_to_cpu(desc->len), PCI_DMA_TODEVICE);
+-
+- desc->host_addr = 0;
+- desc->device_addr = 0;
+- desc->len = 0;
+- desc->flags = 0;
+-
+- i++;
+- i %= ARRAY_SIZE(ring_control->tx_data);
+- }
+-
+- i = priv->rx_idx;
+- i %= ARRAY_SIZE(ring_control->rx_data);
+- priv->rx_idx = idx = le32_to_cpu(ring_control->device_idx[0]);
+- idx %= ARRAY_SIZE(ring_control->rx_data);
+- while (i != idx) {
+- u16 len;
+- struct sk_buff *skb;
+- desc = &ring_control->rx_data[i];
+- len = le16_to_cpu(desc->len);
+- skb = priv->rx_buf[i];
+-
+- skb_put(skb, len);
+-
+- if (p54_rx(dev, skb)) {
+- pci_unmap_single(priv->pdev,
+- le32_to_cpu(desc->host_addr),
+- MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
+-
+- priv->rx_buf[i] = NULL;
+- desc->host_addr = 0;
+- } else {
+- skb_trim(skb, 0);
+- desc->len = cpu_to_le16(MAX_RX_SIZE);
+- }
+-
+- i++;
+- i %= ARRAY_SIZE(ring_control->rx_data);
+- }
+-
+- p54p_refill_rx_ring(dev);
+-
+- wmb();
+- P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
+- } else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT))
+- complete(&priv->boot_comp);
+-
+- spin_unlock(&priv->lock);
+-
+- return reg ? IRQ_HANDLED : IRQ_NONE;
+-}
+-
+-static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data,
+- size_t len, int free_on_tx)
+-{
+- struct p54p_priv *priv = dev->priv;
+- struct p54p_ring_control *ring_control = priv->ring_control;
+- unsigned long flags;
+- struct p54p_desc *desc;
+- dma_addr_t mapping;
+- u32 device_idx, idx, i;
+-
+- spin_lock_irqsave(&priv->lock, flags);
+-
+- device_idx = le32_to_cpu(ring_control->device_idx[1]);
+- idx = le32_to_cpu(ring_control->host_idx[1]);
+- i = idx % ARRAY_SIZE(ring_control->tx_data);
+-
+- mapping = pci_map_single(priv->pdev, data, len, PCI_DMA_TODEVICE);
+- desc = &ring_control->tx_data[i];
+- desc->host_addr = cpu_to_le32(mapping);
+- desc->device_addr = data->req_id;
+- desc->len = cpu_to_le16(len);
+- desc->flags = 0;
+-
+- wmb();
+- ring_control->host_idx[1] = cpu_to_le32(idx + 1);
+-
+- if (free_on_tx)
+- priv->tx_buf[i] = data;
+-
+- spin_unlock_irqrestore(&priv->lock, flags);
+-
+- P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
+- P54P_READ(dev_int);
+-
+- /* FIXME: unlikely to happen because the device usually runs out of
+- memory before we fill the ring up, but we can make it impossible */
+- if (idx - device_idx > ARRAY_SIZE(ring_control->tx_data) - 2)
+- printk(KERN_INFO "%s: tx overflow.\n", wiphy_name(dev->wiphy));
+-}
+-
+-static int p54p_open(struct ieee80211_hw *dev)
+-{
+- struct p54p_priv *priv = dev->priv;
+- int err;
+-
+- init_completion(&priv->boot_comp);
+- err = request_irq(priv->pdev->irq, &p54p_interrupt,
+- IRQF_SHARED, "prism54pci", dev);
+- if (err) {
+- printk(KERN_ERR "%s: failed to register IRQ handler\n",
+- wiphy_name(dev->wiphy));
+- return err;
+- }
+-
+- memset(priv->ring_control, 0, sizeof(*priv->ring_control));
+- priv->rx_idx = priv->tx_idx = 0;
+- p54p_refill_rx_ring(dev);
+-
+- p54p_upload_firmware(dev);
+-
+- P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma));
+- P54P_READ(ring_control_base);
+- wmb();
+- udelay(10);
+-
+- P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_INIT));
+- P54P_READ(int_enable);
+- wmb();
+- udelay(10);
+-
+- P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
+- P54P_READ(dev_int);
+-
+- if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) {
+- printk(KERN_ERR "%s: Cannot boot firmware!\n",
+- wiphy_name(dev->wiphy));
+- free_irq(priv->pdev->irq, dev);
+- return -ETIMEDOUT;
+- }
+-
+- P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_UPDATE));
+- P54P_READ(int_enable);
+- wmb();
+- udelay(10);
+-
+- P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
+- P54P_READ(dev_int);
+- wmb();
+- udelay(10);
+-
+- return 0;
+-}
+-
+-static void p54p_stop(struct ieee80211_hw *dev)
+-{
+- struct p54p_priv *priv = dev->priv;
+- struct p54p_ring_control *ring_control = priv->ring_control;
+- unsigned int i;
+- struct p54p_desc *desc;
+-
+- P54P_WRITE(int_enable, cpu_to_le32(0));
+- P54P_READ(int_enable);
+- udelay(10);
+-
+- free_irq(priv->pdev->irq, dev);
+-
+- P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
+-
+- for (i = 0; i < ARRAY_SIZE(priv->rx_buf); i++) {
+- desc = &ring_control->rx_data[i];
+- if (desc->host_addr)
+- pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
+- MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
+- kfree_skb(priv->rx_buf[i]);
+- priv->rx_buf[i] = NULL;
+- }
+-
+- for (i = 0; i < ARRAY_SIZE(priv->tx_buf); i++) {
+- desc = &ring_control->tx_data[i];
+- if (desc->host_addr)
+- pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
+- le16_to_cpu(desc->len), PCI_DMA_TODEVICE);
+-
+- kfree(priv->tx_buf[i]);
+- priv->tx_buf[i] = NULL;
+- }
+-
+- memset(ring_control, 0, sizeof(ring_control));
+-}
+-
+-static int __devinit p54p_probe(struct pci_dev *pdev,
+- const struct pci_device_id *id)
+-{
+- struct p54p_priv *priv;
+- struct ieee80211_hw *dev;
+- unsigned long mem_addr, mem_len;
+- int err;
+- DECLARE_MAC_BUF(mac);
+-
+- err = pci_enable_device(pdev);
+- if (err) {
+- printk(KERN_ERR "%s (prism54pci): Cannot enable new PCI device\n",
+- pci_name(pdev));
+- return err;
+- }
+-
+- mem_addr = pci_resource_start(pdev, 0);
+- mem_len = pci_resource_len(pdev, 0);
+- if (mem_len < sizeof(struct p54p_csr)) {
+- printk(KERN_ERR "%s (prism54pci): Too short PCI resources\n",
+- pci_name(pdev));
+- pci_disable_device(pdev);
+- return err;
+- }
+-
+- err = pci_request_regions(pdev, "prism54pci");
+- if (err) {
+- printk(KERN_ERR "%s (prism54pci): Cannot obtain PCI resources\n",
+- pci_name(pdev));
+- return err;
+- }
+-
+- if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) ||
+- pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
+- printk(KERN_ERR "%s (prism54pci): No suitable DMA available\n",
+- pci_name(pdev));
+- goto err_free_reg;
+- }
+-
+- pci_set_master(pdev);
+- pci_try_set_mwi(pdev);
+-
+- pci_write_config_byte(pdev, 0x40, 0);
+- pci_write_config_byte(pdev, 0x41, 0);
+-
+- dev = p54_init_common(sizeof(*priv));
+- if (!dev) {
+- printk(KERN_ERR "%s (prism54pci): ieee80211 alloc failed\n",
+- pci_name(pdev));
+- err = -ENOMEM;
+- goto err_free_reg;
+- }
+-
+- priv = dev->priv;
+- priv->pdev = pdev;
+-
+- SET_IEEE80211_DEV(dev, &pdev->dev);
+- pci_set_drvdata(pdev, dev);
+-
+- priv->map = ioremap(mem_addr, mem_len);
+- if (!priv->map) {
+- printk(KERN_ERR "%s (prism54pci): Cannot map device memory\n",
+- pci_name(pdev));
+- err = -EINVAL; // TODO: use a better error code?
+- goto err_free_dev;
+- }
+-
+- priv->ring_control = pci_alloc_consistent(pdev, sizeof(*priv->ring_control),
+- &priv->ring_control_dma);
+- if (!priv->ring_control) {
+- printk(KERN_ERR "%s (prism54pci): Cannot allocate rings\n",
+- pci_name(pdev));
+- err = -ENOMEM;
+- goto err_iounmap;
+- }
+- memset(priv->ring_control, 0, sizeof(*priv->ring_control));
+-
+- err = p54p_upload_firmware(dev);
+- if (err)
+- goto err_free_desc;
+-
+- err = p54p_read_eeprom(dev);
+- if (err)
+- goto err_free_desc;
+-
+- priv->common.open = p54p_open;
+- priv->common.stop = p54p_stop;
+- priv->common.tx = p54p_tx;
+-
+- spin_lock_init(&priv->lock);
+-
+- err = ieee80211_register_hw(dev);
+- if (err) {
+- printk(KERN_ERR "%s (prism54pci): Cannot register netdevice\n",
+- pci_name(pdev));
+- goto err_free_common;
+- }
+-
+- printk(KERN_INFO "%s: hwaddr %s, isl38%02x\n",
+- wiphy_name(dev->wiphy),
+- print_mac(mac, dev->wiphy->perm_addr),
+- priv->common.version);
+-
+- return 0;
+-
+- err_free_common:
+- p54_free_common(dev);
+-
+- err_free_desc:
+- pci_free_consistent(pdev, sizeof(*priv->ring_control),
+- priv->ring_control, priv->ring_control_dma);
+-
+- err_iounmap:
+- iounmap(priv->map);
+-
+- err_free_dev:
+- pci_set_drvdata(pdev, NULL);
+- ieee80211_free_hw(dev);
+-
+- err_free_reg:
+- pci_release_regions(pdev);
+- pci_disable_device(pdev);
+- return err;
+-}
+-
+-static void __devexit p54p_remove(struct pci_dev *pdev)
+-{
+- struct ieee80211_hw *dev = pci_get_drvdata(pdev);
+- struct p54p_priv *priv;
+-
+- if (!dev)
+- return;
+-
+- ieee80211_unregister_hw(dev);
+- priv = dev->priv;
+- pci_free_consistent(pdev, sizeof(*priv->ring_control),
+- priv->ring_control, priv->ring_control_dma);
+- p54_free_common(dev);
+- iounmap(priv->map);
+- pci_release_regions(pdev);
+- pci_disable_device(pdev);
+- ieee80211_free_hw(dev);
+-}
+-
+-#ifdef CONFIG_PM
+-static int p54p_suspend(struct pci_dev *pdev, pm_message_t state)
+-{
+- struct ieee80211_hw *dev = pci_get_drvdata(pdev);
+- struct p54p_priv *priv = dev->priv;
+-
+- if (priv->common.mode != IEEE80211_IF_TYPE_INVALID) {
+- ieee80211_stop_queues(dev);
+- p54p_stop(dev);
+- }
+-
+- pci_save_state(pdev);
+- pci_set_power_state(pdev, pci_choose_state(pdev, state));
+- return 0;
+-}
+-
+-static int p54p_resume(struct pci_dev *pdev)
+-{
+- struct ieee80211_hw *dev = pci_get_drvdata(pdev);
+- struct p54p_priv *priv = dev->priv;
+-
+- pci_set_power_state(pdev, PCI_D0);
+- pci_restore_state(pdev);
+-
+- if (priv->common.mode != IEEE80211_IF_TYPE_INVALID) {
+- p54p_open(dev);
+- ieee80211_start_queues(dev);
+- }
+-
+- return 0;
+-}
+-#endif /* CONFIG_PM */
+-
+-static struct pci_driver p54p_driver = {
+- .name = "prism54pci",
+- .id_table = p54p_table,
+- .probe = p54p_probe,
+- .remove = __devexit_p(p54p_remove),
+-#ifdef CONFIG_PM
+- .suspend = p54p_suspend,
+- .resume = p54p_resume,
+-#endif /* CONFIG_PM */
+-};
+-
+-static int __init p54p_init(void)
+-{
+- return pci_register_driver(&p54p_driver);
+-}
+-
+-static void __exit p54p_exit(void)
+-{
+- pci_unregister_driver(&p54p_driver);
+-}
+-
+-module_init(p54p_init);
+-module_exit(p54p_exit);
+diff --git a/drivers/net/wireless/p54pci.h b/drivers/net/wireless/p54pci.h
+deleted file mode 100644
+index 5bedd7a..0000000
+--- a/drivers/net/wireless/p54pci.h
++++ /dev/null
+@@ -1,106 +0,0 @@
+-#ifndef PRISM54PCI_H
+-#define PRISM54PCI_H
+-
+-/*
+- * Defines for PCI based mac80211 Prism54 driver
+- *
+- * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
+- *
+- * Based on the islsm (softmac prism54) driver, which is:
+- * Copyright 2004-2006 Jean-Baptiste Note <jbnote at gmail.com>, et al.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-/* Device Interrupt register bits */
+-#define ISL38XX_DEV_INT_RESET 0x0001
+-#define ISL38XX_DEV_INT_UPDATE 0x0002
+-#define ISL38XX_DEV_INT_WAKEUP 0x0008
+-#define ISL38XX_DEV_INT_SLEEP 0x0010
+-#define ISL38XX_DEV_INT_ABORT 0x0020
+-/* these two only used in USB */
+-#define ISL38XX_DEV_INT_DATA 0x0040
+-#define ISL38XX_DEV_INT_MGMT 0x0080
+-
+-#define ISL38XX_DEV_INT_PCIUART_CTS 0x4000
+-#define ISL38XX_DEV_INT_PCIUART_DR 0x8000
+-
+-/* Interrupt Identification/Acknowledge/Enable register bits */
+-#define ISL38XX_INT_IDENT_UPDATE 0x0002
+-#define ISL38XX_INT_IDENT_INIT 0x0004
+-#define ISL38XX_INT_IDENT_WAKEUP 0x0008
+-#define ISL38XX_INT_IDENT_SLEEP 0x0010
+-#define ISL38XX_INT_IDENT_PCIUART_CTS 0x4000
+-#define ISL38XX_INT_IDENT_PCIUART_DR 0x8000
+-
+-/* Control/Status register bits */
+-#define ISL38XX_CTRL_STAT_SLEEPMODE 0x00000200
+-#define ISL38XX_CTRL_STAT_CLKRUN 0x00800000
+-#define ISL38XX_CTRL_STAT_RESET 0x10000000
+-#define ISL38XX_CTRL_STAT_RAMBOOT 0x20000000
+-#define ISL38XX_CTRL_STAT_STARTHALTED 0x40000000
+-#define ISL38XX_CTRL_STAT_HOST_OVERRIDE 0x80000000
+-
+-struct p54p_csr {
+- __le32 dev_int;
+- u8 unused_1[12];
+- __le32 int_ident;
+- __le32 int_ack;
+- __le32 int_enable;
+- u8 unused_2[4];
+- union {
+- __le32 ring_control_base;
+- __le32 gen_purp_com[2];
+- };
+- u8 unused_3[8];
+- __le32 direct_mem_base;
+- u8 unused_4[44];
+- __le32 dma_addr;
+- __le32 dma_len;
+- __le32 dma_ctrl;
+- u8 unused_5[12];
+- __le32 ctrl_stat;
+- u8 unused_6[1924];
+- u8 cardbus_cis[0x800];
+- u8 direct_mem_win[0x1000];
+-} __attribute__ ((packed));
+-
+-/* usb backend only needs the register defines above */
+-#ifndef PRISM54USB_H
+-struct p54p_desc {
+- __le32 host_addr;
+- __le32 device_addr;
+- __le16 len;
+- __le16 flags;
+-} __attribute__ ((packed));
+-
+-struct p54p_ring_control {
+- __le32 host_idx[4];
+- __le32 device_idx[4];
+- struct p54p_desc rx_data[8];
+- struct p54p_desc tx_data[32];
+- struct p54p_desc rx_mgmt[4];
+- struct p54p_desc tx_mgmt[4];
+-} __attribute__ ((packed));
+-
+-#define P54P_READ(r) (__force __le32)__raw_readl(&priv->map->r)
+-#define P54P_WRITE(r, val) __raw_writel((__force u32)(__le32)(val), &priv->map->r)
+-
+-struct p54p_priv {
+- struct p54_common common;
+- struct pci_dev *pdev;
+- struct p54p_csr __iomem *map;
+-
+- spinlock_t lock;
+- struct p54p_ring_control *ring_control;
+- dma_addr_t ring_control_dma;
+- u32 rx_idx, tx_idx;
+- struct sk_buff *rx_buf[8];
+- void *tx_buf[32];
+- struct completion boot_comp;
+-};
+-
+-#endif /* PRISM54USB_H */
+-#endif /* PRISM54PCI_H */
+diff --git a/drivers/net/wireless/p54usb.c b/drivers/net/wireless/p54usb.c
+deleted file mode 100644
+index 98ddbb3..0000000
+--- a/drivers/net/wireless/p54usb.c
++++ /dev/null
+@@ -1,910 +0,0 @@
+-
+-/*
+- * Linux device driver for USB based Prism54
+- *
+- * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
+- *
+- * Based on the islsm (softmac prism54) driver, which is:
+- * Copyright 2004-2006 Jean-Baptiste Note <jbnote at gmail.com>, et al.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#include <linux/init.h>
+-#include <linux/usb.h>
+-#include <linux/pci.h>
+-#include <linux/firmware.h>
+-#include <linux/etherdevice.h>
+-#include <linux/delay.h>
+-#include <linux/crc32.h>
+-#include <net/mac80211.h>
+-
+-#include "p54.h"
+-#include "p54usb.h"
+-
+-MODULE_AUTHOR("Michael Wu <flamingice at sourmilk.net>");
+-MODULE_DESCRIPTION("Prism54 USB wireless driver");
+-MODULE_LICENSE("GPL");
+-MODULE_ALIAS("prism54usb");
+-
+-static struct usb_device_id p54u_table[] __devinitdata = {
+- /* Version 1 devices (pci chip + net2280) */
+- {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */
+- {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */
+- {USB_DEVICE(0x083a, 0x4501)}, /* Accton 802.11g WN4501 USB */
+- {USB_DEVICE(0x083a, 0x4502)}, /* Siemens Gigaset USB Adapter */
+- {USB_DEVICE(0x083a, 0x5501)}, /* Phillips CPWUA054 */
+- {USB_DEVICE(0x0846, 0x4200)}, /* Netgear WG121 */
+- {USB_DEVICE(0x0846, 0x4210)}, /* Netgear WG121 the second ? */
+- {USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */
+- {USB_DEVICE(0x0cde, 0x0006)}, /* Medion 40900, Roper Europe */
+- {USB_DEVICE(0x124a, 0x4023)}, /* Shuttle PN15, Airvast WM168g, IOGear GWU513 */
+- {USB_DEVICE(0x1915, 0x2234)}, /* Linksys WUSB54G OEM */
+- {USB_DEVICE(0x1915, 0x2235)}, /* Linksys WUSB54G Portable OEM */
+- {USB_DEVICE(0x2001, 0x3701)}, /* DLink DWL-G120 Spinnaker */
+- {USB_DEVICE(0x2001, 0x3703)}, /* DLink DWL-G122 */
+- {USB_DEVICE(0x5041, 0x2234)}, /* Linksys WUSB54G */
+- {USB_DEVICE(0x5041, 0x2235)}, /* Linksys WUSB54G Portable */
+-
+- /* Version 2 devices (3887) */
+- {USB_DEVICE(0x050d, 0x7050)}, /* Belkin F5D7050 ver 1000 */
+- {USB_DEVICE(0x0572, 0x2000)}, /* Cohiba Proto board */
+- {USB_DEVICE(0x0572, 0x2002)}, /* Cohiba Proto board */
+- {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */
+- {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */
+- {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */
+- {USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */
+- {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */
+- {USB_DEVICE(0x0baf, 0x0118)}, /* U.S. Robotics U5 802.11g Adapter*/
+- {USB_DEVICE(0x0bf8, 0x1009)}, /* FUJITSU E-5400 USB D1700*/
+- {USB_DEVICE(0x0cde, 0x0006)}, /* Medion MD40900 */
+- {USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */
+- {USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */
+- {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */
+- {USB_DEVICE(0x124a, 0x4025)}, /* IOGear GWU513 (GW3887IK chip) */
+- {USB_DEVICE(0x13b1, 0x000a)}, /* Linksys WUSB54G ver 2 */
+- {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */
+- {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */
+- {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */
+- {USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */
+- {USB_DEVICE(0x413c, 0x8104)}, /* Cohiba Proto board */
+- {}
+-};
+-
+-MODULE_DEVICE_TABLE(usb, p54u_table);
+-
+-static void p54u_rx_cb(struct urb *urb)
+-{
+- struct sk_buff *skb = (struct sk_buff *) urb->context;
+- struct p54u_rx_info *info = (struct p54u_rx_info *)skb->cb;
+- struct ieee80211_hw *dev = info->dev;
+- struct p54u_priv *priv = dev->priv;
+-
+- if (unlikely(urb->status)) {
+- info->urb = NULL;
+- usb_free_urb(urb);
+- return;
+- }
+-
+- skb_unlink(skb, &priv->rx_queue);
+- skb_put(skb, urb->actual_length);
+- if (!priv->hw_type)
+- skb_pull(skb, sizeof(struct net2280_tx_hdr));
+-
+- if (p54_rx(dev, skb)) {
+- skb = dev_alloc_skb(MAX_RX_SIZE);
+- if (unlikely(!skb)) {
+- usb_free_urb(urb);
+- /* TODO check rx queue length and refill *somewhere* */
+- return;
+- }
+-
+- info = (struct p54u_rx_info *) skb->cb;
+- info->urb = urb;
+- info->dev = dev;
+- urb->transfer_buffer = skb_tail_pointer(skb);
+- urb->context = skb;
+- skb_queue_tail(&priv->rx_queue, skb);
+- } else {
+- skb_trim(skb, 0);
+- skb_queue_tail(&priv->rx_queue, skb);
+- }
+-
+- usb_submit_urb(urb, GFP_ATOMIC);
+-}
+-
+-static void p54u_tx_cb(struct urb *urb)
+-{
+- usb_free_urb(urb);
+-}
+-
+-static void p54u_tx_free_cb(struct urb *urb)
+-{
+- kfree(urb->transfer_buffer);
+- usb_free_urb(urb);
+-}
+-
+-static int p54u_init_urbs(struct ieee80211_hw *dev)
+-{
+- struct p54u_priv *priv = dev->priv;
+- struct urb *entry;
+- struct sk_buff *skb;
+- struct p54u_rx_info *info;
+-
+- while (skb_queue_len(&priv->rx_queue) < 32) {
+- skb = __dev_alloc_skb(MAX_RX_SIZE, GFP_KERNEL);
+- if (!skb)
+- break;
+- entry = usb_alloc_urb(0, GFP_KERNEL);
+- if (!entry) {
+- kfree_skb(skb);
+- break;
+- }
+- usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), skb_tail_pointer(skb), MAX_RX_SIZE, p54u_rx_cb, skb);
+- info = (struct p54u_rx_info *) skb->cb;
+- info->urb = entry;
+- info->dev = dev;
+- skb_queue_tail(&priv->rx_queue, skb);
+- usb_submit_urb(entry, GFP_KERNEL);
+- }
+-
+- return 0;
+-}
+-
+-static void p54u_free_urbs(struct ieee80211_hw *dev)
+-{
+- struct p54u_priv *priv = dev->priv;
+- struct p54u_rx_info *info;
+- struct sk_buff *skb;
+-
+- while ((skb = skb_dequeue(&priv->rx_queue))) {
+- info = (struct p54u_rx_info *) skb->cb;
+- if (!info->urb)
+- continue;
+-
+- usb_kill_urb(info->urb);
+- kfree_skb(skb);
+- }
+-}
+-
+-static void p54u_tx_3887(struct ieee80211_hw *dev, struct p54_control_hdr *data,
+- size_t len, int free_on_tx)
+-{
+- struct p54u_priv *priv = dev->priv;
+- struct urb *addr_urb, *data_urb;
+-
+- addr_urb = usb_alloc_urb(0, GFP_ATOMIC);
+- if (!addr_urb)
+- return;
+-
+- data_urb = usb_alloc_urb(0, GFP_ATOMIC);
+- if (!data_urb) {
+- usb_free_urb(addr_urb);
+- return;
+- }
+-
+- usb_fill_bulk_urb(addr_urb, priv->udev,
+- usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), &data->req_id,
+- sizeof(data->req_id), p54u_tx_cb, dev);
+- usb_fill_bulk_urb(data_urb, priv->udev,
+- usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), data, len,
+- free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev);
+-
+- usb_submit_urb(addr_urb, GFP_ATOMIC);
+- usb_submit_urb(data_urb, GFP_ATOMIC);
+-}
+-
+-static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *data,
+- size_t len, int free_on_tx)
+-{
+- struct p54u_priv *priv = dev->priv;
+- struct urb *int_urb, *data_urb;
+- struct net2280_tx_hdr *hdr;
+- struct net2280_reg_write *reg;
+-
+- reg = kmalloc(sizeof(*reg), GFP_ATOMIC);
+- if (!reg)
+- return;
+-
+- int_urb = usb_alloc_urb(0, GFP_ATOMIC);
+- if (!int_urb) {
+- kfree(reg);
+- return;
+- }
+-
+- data_urb = usb_alloc_urb(0, GFP_ATOMIC);
+- if (!data_urb) {
+- kfree(reg);
+- usb_free_urb(int_urb);
+- return;
+- }
+-
+- reg->port = cpu_to_le16(NET2280_DEV_U32);
+- reg->addr = cpu_to_le32(P54U_DEV_BASE);
+- reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
+-
+- len += sizeof(*data);
+- hdr = (void *)data - sizeof(*hdr);
+- memset(hdr, 0, sizeof(*hdr));
+- hdr->device_addr = data->req_id;
+- hdr->len = cpu_to_le16(len);
+-
+- usb_fill_bulk_urb(int_urb, priv->udev,
+- usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg),
+- p54u_tx_free_cb, dev);
+- usb_submit_urb(int_urb, GFP_ATOMIC);
+-
+- usb_fill_bulk_urb(data_urb, priv->udev,
+- usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr, len + sizeof(*hdr),
+- free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev);
+- usb_submit_urb(data_urb, GFP_ATOMIC);
+-}
+-
+-static int p54u_write(struct p54u_priv *priv,
+- struct net2280_reg_write *buf,
+- enum net2280_op_type type,
+- __le32 addr, __le32 val)
+-{
+- unsigned int ep;
+- int alen;
+-
+- if (type & 0x0800)
+- ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV);
+- else
+- ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_BRG);
+-
+- buf->port = cpu_to_le16(type);
+- buf->addr = addr;
+- buf->val = val;
+-
+- return usb_bulk_msg(priv->udev, ep, buf, sizeof(*buf), &alen, 1000);
+-}
+-
+-static int p54u_read(struct p54u_priv *priv, void *buf,
+- enum net2280_op_type type,
+- __le32 addr, __le32 *val)
+-{
+- struct net2280_reg_read *read = buf;
+- __le32 *reg = buf;
+- unsigned int ep;
+- int alen, err;
+-
+- if (type & 0x0800)
+- ep = P54U_PIPE_DEV;
+- else
+- ep = P54U_PIPE_BRG;
+-
+- read->port = cpu_to_le16(type);
+- read->addr = addr;
+-
+- err = usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),
+- read, sizeof(*read), &alen, 1000);
+- if (err)
+- return err;
+-
+- err = usb_bulk_msg(priv->udev, usb_rcvbulkpipe(priv->udev, ep),
+- reg, sizeof(*reg), &alen, 1000);
+- if (err)
+- return err;
+-
+- *val = *reg;
+- return 0;
+-}
+-
+-static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep,
+- void *data, size_t len)
+-{
+- int alen;
+- return usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),
+- data, len, &alen, 2000);
+-}
+-
+-static int p54u_read_eeprom(struct ieee80211_hw *dev)
+-{
+- struct p54u_priv *priv = dev->priv;
+- void *buf;
+- struct p54_control_hdr *hdr;
+- int err, alen;
+- size_t offset = priv->hw_type ? 0x10 : 0x20;
+-
+- buf = kmalloc(0x2020, GFP_KERNEL);
+- if (!buf) {
+- printk(KERN_ERR "prism54usb: cannot allocate memory for "
+- "eeprom readback!\n");
+- return -ENOMEM;
+- }
+-
+- if (priv->hw_type) {
+- *((u32 *) buf) = priv->common.rx_start;
+- err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
+- if (err) {
+- printk(KERN_ERR "prism54usb: addr send failed\n");
+- goto fail;
+- }
+- } else {
+- struct net2280_reg_write *reg = buf;
+- reg->port = cpu_to_le16(NET2280_DEV_U32);
+- reg->addr = cpu_to_le32(P54U_DEV_BASE);
+- reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
+- err = p54u_bulk_msg(priv, P54U_PIPE_DEV, buf, sizeof(*reg));
+- if (err) {
+- printk(KERN_ERR "prism54usb: dev_int send failed\n");
+- goto fail;
+- }
+- }
+-
+- hdr = buf + priv->common.tx_hdr_len;
+- p54_fill_eeprom_readback(hdr);
+- hdr->req_id = cpu_to_le32(priv->common.rx_start);
+- if (priv->common.tx_hdr_len) {
+- struct net2280_tx_hdr *tx_hdr = buf;
+- tx_hdr->device_addr = hdr->req_id;
+- tx_hdr->len = cpu_to_le16(EEPROM_READBACK_LEN);
+- }
+-
+- /* we can just pretend to send 0x2000 bytes of nothing in the headers */
+- err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf,
+- EEPROM_READBACK_LEN + priv->common.tx_hdr_len);
+- if (err) {
+- printk(KERN_ERR "prism54usb: eeprom req send failed\n");
+- goto fail;
+- }
+-
+- err = usb_bulk_msg(priv->udev,
+- usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA),
+- buf, 0x2020, &alen, 1000);
+- if (!err && alen > offset) {
+- p54_parse_eeprom(dev, (u8 *)buf + offset, alen - offset);
+- } else {
+- printk(KERN_ERR "prism54usb: eeprom read failed!\n");
+- err = -EINVAL;
+- goto fail;
+- }
+-
+- fail:
+- kfree(buf);
+- return err;
+-}
+-
+-static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
+-{
+- static char start_string[] = "~~~~<\r";
+- struct p54u_priv *priv = dev->priv;
+- const struct firmware *fw_entry = NULL;
+- int err, alen;
+- u8 carry = 0;
+- u8 *buf, *tmp, *data;
+- unsigned int left, remains, block_size;
+- struct x2_header *hdr;
+- unsigned long timeout;
+-
+- tmp = buf = kmalloc(P54U_FW_BLOCK, GFP_KERNEL);
+- if (!buf) {
+- printk(KERN_ERR "p54usb: cannot allocate firmware upload buffer!\n");
+- err = -ENOMEM;
+- goto err_bufalloc;
+- }
+-
+- memcpy(buf, start_string, 4);
+- err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 4);
+- if (err) {
+- printk(KERN_ERR "p54usb: reset failed! (%d)\n", err);
+- goto err_reset;
+- }
+-
+- err = request_firmware(&fw_entry, "isl3887usb_bare", &priv->udev->dev);
+- if (err) {
+- printk(KERN_ERR "p54usb: cannot find firmware (isl3887usb_bare)!\n");
+- goto err_req_fw_failed;
+- }
+-
+- p54_parse_firmware(dev, fw_entry);
+-
+- left = block_size = min((size_t)P54U_FW_BLOCK, fw_entry->size);
+- strcpy(buf, start_string);
+- left -= strlen(start_string);
+- tmp += strlen(start_string);
+-
+- data = fw_entry->data;
+- remains = fw_entry->size;
+-
+- hdr = (struct x2_header *)(buf + strlen(start_string));
+- memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE);
+- hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR);
+- hdr->fw_length = cpu_to_le32(fw_entry->size);
+- hdr->crc = cpu_to_le32(~crc32_le(~0, (void *)&hdr->fw_load_addr,
+- sizeof(u32)*2));
+- left -= sizeof(*hdr);
+- tmp += sizeof(*hdr);
+-
+- while (remains) {
+- while (left--) {
+- if (carry) {
+- *tmp++ = carry;
+- carry = 0;
+- remains--;
+- continue;
+- }
+- switch (*data) {
+- case '~':
+- *tmp++ = '}';
+- carry = '^';
+- break;
+- case '}':
+- *tmp++ = '}';
+- carry = ']';
+- break;
+- default:
+- *tmp++ = *data;
+- remains--;
+- break;
+- }
+- data++;
+- }
+-
+- err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_size);
+- if (err) {
+- printk(KERN_ERR "prism54usb: firmware upload failed!\n");
+- goto err_upload_failed;
+- }
+-
+- tmp = buf;
+- left = block_size = min((unsigned int)P54U_FW_BLOCK, remains);
+- }
+-
+- *((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, fw_entry->data, fw_entry->size));
+- err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
+- if (err) {
+- printk(KERN_ERR "prism54usb: firmware upload failed!\n");
+- goto err_upload_failed;
+- }
+-
+- timeout = jiffies + msecs_to_jiffies(1000);
+- while (!(err = usb_bulk_msg(priv->udev,
+- usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
+- if (alen > 2 && !memcmp(buf, "OK", 2))
+- break;
+-
+- if (alen > 5 && !memcmp(buf, "ERROR", 5)) {
+- printk(KERN_INFO "prism54usb: firmware upload failed!\n");
+- err = -EINVAL;
+- break;
+- }
+-
+- if (time_after(jiffies, timeout)) {
+- printk(KERN_ERR "prism54usb: firmware boot timed out!\n");
+- err = -ETIMEDOUT;
+- break;
+- }
+- }
+- if (err)
+- goto err_upload_failed;
+-
+- buf[0] = 'g';
+- buf[1] = '\r';
+- err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 2);
+- if (err) {
+- printk(KERN_ERR "prism54usb: firmware boot failed!\n");
+- goto err_upload_failed;
+- }
+-
+- timeout = jiffies + msecs_to_jiffies(1000);
+- while (!(err = usb_bulk_msg(priv->udev,
+- usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
+- if (alen > 0 && buf[0] == 'g')
+- break;
+-
+- if (time_after(jiffies, timeout)) {
+- err = -ETIMEDOUT;
+- break;
+- }
+- }
+- if (err)
+- goto err_upload_failed;
+-
+- err_upload_failed:
+- release_firmware(fw_entry);
+- err_req_fw_failed:
+- err_reset:
+- kfree(buf);
+- err_bufalloc:
+- return err;
+-}
+-
+-static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
+-{
+- struct p54u_priv *priv = dev->priv;
+- const struct firmware *fw_entry = NULL;
+- const struct p54p_csr *devreg = (const struct p54p_csr *) P54U_DEV_BASE;
+- int err, alen;
+- void *buf;
+- __le32 reg;
+- unsigned int remains, offset;
+- u8 *data;
+-
+- buf = kmalloc(512, GFP_KERNEL);
+- if (!buf) {
+- printk(KERN_ERR "p54usb: firmware buffer alloc failed!\n");
+- return -ENOMEM;
+- }
+-
+- err = request_firmware(&fw_entry, "isl3890usb", &priv->udev->dev);
+- if (err) {
+- printk(KERN_ERR "p54usb: cannot find firmware (isl3890usb)!\n");
+- kfree(buf);
+- return err;
+- }
+-
+- p54_parse_firmware(dev, fw_entry);
+-
+-#define P54U_WRITE(type, addr, data) \
+- do {\
+- err = p54u_write(priv, buf, type,\
+- cpu_to_le32((u32)(unsigned long)addr), data);\
+- if (err) \
+- goto fail;\
+- } while (0)
+-
+-#define P54U_READ(type, addr) \
+- do {\
+- err = p54u_read(priv, buf, type,\
+- cpu_to_le32((u32)(unsigned long)addr), ®);\
+- if (err)\
+- goto fail;\
+- } while (0)
+-
+- /* power down net2280 bridge */
+- P54U_READ(NET2280_BRG_U32, NET2280_GPIOCTL);
+- reg |= cpu_to_le32(P54U_BRG_POWER_DOWN);
+- reg &= cpu_to_le32(~P54U_BRG_POWER_UP);
+- P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);
+-
+- mdelay(100);
+-
+- /* power up bridge */
+- reg |= cpu_to_le32(P54U_BRG_POWER_UP);
+- reg &= cpu_to_le32(~P54U_BRG_POWER_DOWN);
+- P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);
+-
+- mdelay(100);
+-
+- P54U_WRITE(NET2280_BRG_U32, NET2280_DEVINIT,
+- cpu_to_le32(NET2280_CLK_30Mhz |
+- NET2280_PCI_ENABLE |
+- NET2280_PCI_SOFT_RESET));
+-
+- mdelay(20);
+-
+- P54U_WRITE(NET2280_BRG_CFG_U16, PCI_COMMAND,
+- cpu_to_le32(PCI_COMMAND_MEMORY |
+- PCI_COMMAND_MASTER));
+-
+- P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_0,
+- cpu_to_le32(NET2280_BASE));
+-
+- P54U_READ(NET2280_BRG_CFG_U16, PCI_STATUS);
+- reg |= cpu_to_le32(PCI_STATUS_REC_MASTER_ABORT);
+- P54U_WRITE(NET2280_BRG_CFG_U16, PCI_STATUS, reg);
+-
+- // TODO: we really need this?
+- P54U_READ(NET2280_BRG_U32, NET2280_RELNUM);
+-
+- P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_RSP,
+- cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));
+- P54U_WRITE(NET2280_BRG_U32, NET2280_EPC_RSP,
+- cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));
+-
+- P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_2,
+- cpu_to_le32(NET2280_BASE2));
+-
+- /* finally done setting up the bridge */
+-
+- P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | PCI_COMMAND,
+- cpu_to_le32(PCI_COMMAND_MEMORY |
+- PCI_COMMAND_MASTER));
+-
+- P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | 0x40 /* TRDY timeout */, 0);
+- P54U_WRITE(NET2280_DEV_CFG_U32, 0x10000 | PCI_BASE_ADDRESS_0,
+- cpu_to_le32(P54U_DEV_BASE));
+-
+- P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);
+- P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
+- cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
+-
+- /* do romboot */
+- P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable, 0);
+-
+- P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);
+- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
+- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT);
+- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
+- P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
+-
+- mdelay(20);
+-
+- reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
+- P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
+-
+- mdelay(20);
+-
+- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
+- P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
+-
+- mdelay(100);
+-
+- P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
+- P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
+-
+- /* finally, we can upload firmware now! */
+- remains = fw_entry->size;
+- data = fw_entry->data;
+- offset = ISL38XX_DEV_FIRMWARE_ADDR;
+-
+- while (remains) {
+- unsigned int block_len = min(remains, (unsigned int)512);
+- memcpy(buf, data, block_len);
+-
+- err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_len);
+- if (err) {
+- printk(KERN_ERR "prism54usb: firmware block upload "
+- "failed\n");
+- goto fail;
+- }
+-
+- P54U_WRITE(NET2280_DEV_U32, &devreg->direct_mem_base,
+- cpu_to_le32(0xc0000f00));
+-
+- P54U_WRITE(NET2280_DEV_U32,
+- 0x0020 | (unsigned long)&devreg->direct_mem_win, 0);
+- P54U_WRITE(NET2280_DEV_U32,
+- 0x0020 | (unsigned long)&devreg->direct_mem_win,
+- cpu_to_le32(1));
+-
+- P54U_WRITE(NET2280_DEV_U32,
+- 0x0024 | (unsigned long)&devreg->direct_mem_win,
+- cpu_to_le32(block_len));
+- P54U_WRITE(NET2280_DEV_U32,
+- 0x0028 | (unsigned long)&devreg->direct_mem_win,
+- cpu_to_le32(offset));
+-
+- P54U_WRITE(NET2280_DEV_U32, &devreg->dma_addr,
+- cpu_to_le32(NET2280_EPA_FIFO_PCI_ADDR));
+- P54U_WRITE(NET2280_DEV_U32, &devreg->dma_len,
+- cpu_to_le32(block_len >> 2));
+- P54U_WRITE(NET2280_DEV_U32, &devreg->dma_ctrl,
+- cpu_to_le32(ISL38XX_DMA_MASTER_CONTROL_TRIGGER));
+-
+- mdelay(10);
+-
+- P54U_READ(NET2280_DEV_U32,
+- 0x002C | (unsigned long)&devreg->direct_mem_win);
+- if (!(reg & cpu_to_le32(ISL38XX_DMA_STATUS_DONE)) ||
+- !(reg & cpu_to_le32(ISL38XX_DMA_STATUS_READY))) {
+- printk(KERN_ERR "prism54usb: firmware DMA transfer "
+- "failed\n");
+- goto fail;
+- }
+-
+- P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_STAT,
+- cpu_to_le32(NET2280_FIFO_FLUSH));
+-
+- remains -= block_len;
+- data += block_len;
+- offset += block_len;
+- }
+-
+- /* do ramboot */
+- P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);
+- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
+- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
+- reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT);
+- P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
+-
+- mdelay(20);
+-
+- reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
+- P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
+-
+- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
+- P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
+-
+- mdelay(100);
+-
+- P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
+- P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
+-
+- /* start up the firmware */
+- P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable,
+- cpu_to_le32(ISL38XX_INT_IDENT_INIT));
+-
+- P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
+- cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
+-
+- P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1,
+- cpu_to_le32(NET2280_PCI_INTA_INTERRUPT_ENABLE |
+- NET2280_USB_INTERRUPT_ENABLE));
+-
+- P54U_WRITE(NET2280_DEV_U32, &devreg->dev_int,
+- cpu_to_le32(ISL38XX_DEV_INT_RESET));
+-
+- err = usb_interrupt_msg(priv->udev,
+- usb_rcvbulkpipe(priv->udev, P54U_PIPE_INT),
+- buf, sizeof(__le32), &alen, 1000);
+- if (err || alen != sizeof(__le32))
+- goto fail;
+-
+- P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
+- P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
+-
+- if (!(reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT)))
+- err = -EINVAL;
+-
+- P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);
+- P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
+- cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
+-
+-#undef P54U_WRITE
+-#undef P54U_READ
+-
+- fail:
+- release_firmware(fw_entry);
+- kfree(buf);
+- return err;
+-}
+-
+-static int p54u_open(struct ieee80211_hw *dev)
+-{
+- struct p54u_priv *priv = dev->priv;
+- int err;
+-
+- err = p54u_init_urbs(dev);
+- if (err) {
+- return err;
+- }
+-
+- priv->common.open = p54u_init_urbs;
+-
+- return 0;
+-}
+-
+-static void p54u_stop(struct ieee80211_hw *dev)
+-{
+- /* TODO: figure out how to reliably stop the 3887 and net2280 so
+- the hardware is still usable next time we want to start it.
+- until then, we just stop listening to the hardware.. */
+- p54u_free_urbs(dev);
+- return;
+-}
+-
+-static int __devinit p54u_probe(struct usb_interface *intf,
+- const struct usb_device_id *id)
+-{
+- struct usb_device *udev = interface_to_usbdev(intf);
+- struct ieee80211_hw *dev;
+- struct p54u_priv *priv;
+- int err;
+- unsigned int i, recognized_pipes;
+- DECLARE_MAC_BUF(mac);
+-
+- dev = p54_init_common(sizeof(*priv));
+- if (!dev) {
+- printk(KERN_ERR "prism54usb: ieee80211 alloc failed\n");
+- return -ENOMEM;
+- }
+-
+- priv = dev->priv;
+-
+- SET_IEEE80211_DEV(dev, &intf->dev);
+- usb_set_intfdata(intf, dev);
+- priv->udev = udev;
+-
+- usb_get_dev(udev);
+-
+- /* really lazy and simple way of figuring out if we're a 3887 */
+- /* TODO: should just stick the identification in the device table */
+- i = intf->altsetting->desc.bNumEndpoints;
+- recognized_pipes = 0;
+- while (i--) {
+- switch (intf->altsetting->endpoint[i].desc.bEndpointAddress) {
+- case P54U_PIPE_DATA:
+- case P54U_PIPE_MGMT:
+- case P54U_PIPE_BRG:
+- case P54U_PIPE_DEV:
+- case P54U_PIPE_DATA | USB_DIR_IN:
+- case P54U_PIPE_MGMT | USB_DIR_IN:
+- case P54U_PIPE_BRG | USB_DIR_IN:
+- case P54U_PIPE_DEV | USB_DIR_IN:
+- case P54U_PIPE_INT | USB_DIR_IN:
+- recognized_pipes++;
+- }
+- }
+- priv->common.open = p54u_open;
+-
+- if (recognized_pipes < P54U_PIPE_NUMBER) {
+- priv->hw_type = P54U_3887;
+- priv->common.tx = p54u_tx_3887;
+- } else {
+- dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr);
+- priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr);
+- priv->common.tx = p54u_tx_net2280;
+- }
+- priv->common.stop = p54u_stop;
+-
+- if (priv->hw_type)
+- err = p54u_upload_firmware_3887(dev);
+- else
+- err = p54u_upload_firmware_net2280(dev);
+- if (err)
+- goto err_free_dev;
+-
+- err = p54u_read_eeprom(dev);
+- if (err)
+- goto err_free_dev;
+-
+- if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
+- u8 perm_addr[ETH_ALEN];
+-
+- printk(KERN_WARNING "prism54usb: Invalid hwaddr! Using randomly generated MAC addr\n");
+- random_ether_addr(perm_addr);
+- SET_IEEE80211_PERM_ADDR(dev, perm_addr);
+- }
+-
+- skb_queue_head_init(&priv->rx_queue);
+-
+- err = ieee80211_register_hw(dev);
+- if (err) {
+- printk(KERN_ERR "prism54usb: Cannot register netdevice\n");
+- goto err_free_dev;
+- }
+-
+- printk(KERN_INFO "%s: hwaddr %s, isl38%02x\n",
+- wiphy_name(dev->wiphy),
+- print_mac(mac, dev->wiphy->perm_addr),
+- priv->common.version);
+-
+- return 0;
+-
+- err_free_dev:
+- ieee80211_free_hw(dev);
+- usb_set_intfdata(intf, NULL);
+- usb_put_dev(udev);
+- return err;
+-}
+-
+-static void __devexit p54u_disconnect(struct usb_interface *intf)
+-{
+- struct ieee80211_hw *dev = usb_get_intfdata(intf);
+- struct p54u_priv *priv;
+-
+- if (!dev)
+- return;
+-
+- ieee80211_unregister_hw(dev);
+-
+- priv = dev->priv;
+- usb_put_dev(interface_to_usbdev(intf));
+- p54_free_common(dev);
+- ieee80211_free_hw(dev);
+-}
+-
+-static struct usb_driver p54u_driver = {
+- .name = "prism54usb",
+- .id_table = p54u_table,
+- .probe = p54u_probe,
+- .disconnect = p54u_disconnect,
+-};
+-
+-static int __init p54u_init(void)
+-{
+- return usb_register(&p54u_driver);
+-}
+-
+-static void __exit p54u_exit(void)
+-{
+- usb_deregister(&p54u_driver);
+-}
+-
+-module_init(p54u_init);
+-module_exit(p54u_exit);
+diff --git a/drivers/net/wireless/p54usb.h b/drivers/net/wireless/p54usb.h
+deleted file mode 100644
+index d1896b3..0000000
+--- a/drivers/net/wireless/p54usb.h
++++ /dev/null
+@@ -1,133 +0,0 @@
+-#ifndef PRISM54USB_H
+-#define PRISM54USB_H
+-
+-/*
+- * Defines for USB based mac80211 Prism54 driver
+- *
+- * Copyright (c) 2006, Michael Wu <flamingice at sourmilk.net>
+- *
+- * Based on the islsm (softmac prism54) driver, which is:
+- * Copyright 2004-2006 Jean-Baptiste Note <jbnote at gmail.com>, et al.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-/* for isl3886 register definitions used on ver 1 devices */
+-#include "p54pci.h"
+-#include "net2280.h"
+-
+-/* pci */
+-#define NET2280_BASE 0x10000000
+-#define NET2280_BASE2 0x20000000
+-
+-/* gpio */
+-#define P54U_BRG_POWER_UP (1 << GPIO0_DATA)
+-#define P54U_BRG_POWER_DOWN (1 << GPIO1_DATA)
+-
+-/* devinit */
+-#define NET2280_CLK_4Mhz (15 << LOCAL_CLOCK_FREQUENCY)
+-#define NET2280_CLK_30Mhz (2 << LOCAL_CLOCK_FREQUENCY)
+-#define NET2280_CLK_60Mhz (1 << LOCAL_CLOCK_FREQUENCY)
+-#define NET2280_CLK_STOP (0 << LOCAL_CLOCK_FREQUENCY)
+-#define NET2280_PCI_ENABLE (1 << PCI_ENABLE)
+-#define NET2280_PCI_SOFT_RESET (1 << PCI_SOFT_RESET)
+-
+-/* endpoints */
+-#define NET2280_CLEAR_NAK_OUT_PACKETS_MODE (1 << CLEAR_NAK_OUT_PACKETS_MODE)
+-#define NET2280_FIFO_FLUSH (1 << FIFO_FLUSH)
+-
+-/* irq */
+-#define NET2280_USB_INTERRUPT_ENABLE (1 << USB_INTERRUPT_ENABLE)
+-#define NET2280_PCI_INTA_INTERRUPT (1 << PCI_INTA_INTERRUPT)
+-#define NET2280_PCI_INTA_INTERRUPT_ENABLE (1 << PCI_INTA_INTERRUPT_ENABLE)
+-
+-/* registers */
+-#define NET2280_DEVINIT 0x00
+-#define NET2280_USBIRQENB1 0x24
+-#define NET2280_IRQSTAT1 0x2c
+-#define NET2280_FIFOCTL 0x38
+-#define NET2280_GPIOCTL 0x50
+-#define NET2280_RELNUM 0x88
+-#define NET2280_EPA_RSP 0x324
+-#define NET2280_EPA_STAT 0x32c
+-#define NET2280_EPB_STAT 0x34c
+-#define NET2280_EPC_RSP 0x364
+-#define NET2280_EPC_STAT 0x36c
+-#define NET2280_EPD_STAT 0x38c
+-
+-#define NET2280_EPA_CFG 0x320
+-#define NET2280_EPB_CFG 0x340
+-#define NET2280_EPC_CFG 0x360
+-#define NET2280_EPD_CFG 0x380
+-#define NET2280_EPE_CFG 0x3A0
+-#define NET2280_EPF_CFG 0x3C0
+-#define P54U_DEV_BASE 0x40000000
+-
+-struct net2280_tx_hdr {
+- __le32 device_addr;
+- __le16 len;
+- __le16 follower; /* ? */
+- u8 padding[8];
+-} __attribute__((packed));
+-
+-/* Some flags for the isl hardware registers controlling DMA inside the
+- * chip */
+-#define ISL38XX_DMA_STATUS_DONE 0x00000001
+-#define ISL38XX_DMA_STATUS_READY 0x00000002
+-#define NET2280_EPA_FIFO_PCI_ADDR 0x20000000
+-#define ISL38XX_DMA_MASTER_CONTROL_TRIGGER 0x00000004
+-
+-enum net2280_op_type {
+- NET2280_BRG_U32 = 0x001F,
+- NET2280_BRG_CFG_U32 = 0x000F,
+- NET2280_BRG_CFG_U16 = 0x0003,
+- NET2280_DEV_U32 = 0x080F,
+- NET2280_DEV_CFG_U32 = 0x088F,
+- NET2280_DEV_CFG_U16 = 0x0883
+-};
+-
+-#define P54U_FW_BLOCK 2048
+-
+-#define X2_SIGNATURE "x2 "
+-#define X2_SIGNATURE_SIZE 4
+-
+-struct x2_header {
+- u8 signature[X2_SIGNATURE_SIZE];
+- __le32 fw_load_addr;
+- __le32 fw_length;
+- __le32 crc;
+-} __attribute__((packed));
+-
+-/* pipes 3 and 4 are not used by the driver */
+-#define P54U_PIPE_NUMBER 9
+-
+-enum p54u_pipe_addr {
+- P54U_PIPE_DATA = 0x01,
+- P54U_PIPE_MGMT = 0x02,
+- P54U_PIPE_3 = 0x03,
+- P54U_PIPE_4 = 0x04,
+- P54U_PIPE_BRG = 0x0d,
+- P54U_PIPE_DEV = 0x0e,
+- P54U_PIPE_INT = 0x0f
+-};
+-
+-struct p54u_rx_info {
+- struct urb *urb;
+- struct ieee80211_hw *dev;
+-};
+-
+-struct p54u_priv {
+- struct p54_common common;
+- struct usb_device *udev;
+- enum {
+- P54U_NET2280 = 0,
+- P54U_3887
+- } hw_type;
+-
+- spinlock_t lock;
+- struct sk_buff_head rx_queue;
+-};
+-
+-#endif /* PRISM54USB_H */
+diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
+index 1b595a6..5b375b2 100644
+--- a/drivers/net/wireless/prism54/isl_ioctl.c
++++ b/drivers/net/wireless/prism54/isl_ioctl.c
+@@ -165,7 +165,7 @@ prism54_update_stats(struct work_struct *work)
+ struct obj_bss bss, *bss2;
+ union oid_res_t r;
+
+- down(&priv->stats_sem);
++ mutex_lock(&priv->stats_lock);
+
+ /* Noise floor.
+ * I'm not sure if the unit is dBm.
+@@ -207,7 +207,7 @@ prism54_update_stats(struct work_struct *work)
+ mgt_get_request(priv, DOT11_OID_MPDUTXFAILED, 0, NULL, &r);
+ priv->local_iwstatistics.discard.retries = r.u;
+
+- up(&priv->stats_sem);
++ mutex_unlock(&priv->stats_lock);
+
+ return;
+ }
+@@ -218,12 +218,12 @@ prism54_get_wireless_stats(struct net_device *ndev)
+ islpci_private *priv = netdev_priv(ndev);
+
+ /* If the stats are being updated return old data */
+- if (down_trylock(&priv->stats_sem) == 0) {
++ if (mutex_trylock(&priv->stats_lock)) {
+ memcpy(&priv->iwstatistics, &priv->local_iwstatistics,
+ sizeof (struct iw_statistics));
+ /* They won't be marked updated for the next time */
+ priv->local_iwstatistics.qual.updated = 0;
+- up(&priv->stats_sem);
++ mutex_unlock(&priv->stats_lock);
+ } else
+ priv->iwstatistics.qual.updated = 0;
+
+@@ -1186,7 +1186,7 @@ prism54_get_encode(struct net_device *ndev, struct iw_request_info *info,
+ rvalue |= mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r);
+ devindex = r.u;
+ /* Now get the key, return it */
+- if ((index < 0) || (index > 3))
++ if (index == -1 || index > 3)
+ /* no index provided, use the current one */
+ index = devindex;
+ rvalue |= mgt_get_request(priv, DOT11_OID_DEFKEYX, index, NULL, &r);
+@@ -1780,7 +1780,7 @@ prism54_set_raw(struct net_device *ndev, struct iw_request_info *info,
+ void
+ prism54_acl_init(struct islpci_acl *acl)
+ {
+- sema_init(&acl->sem, 1);
++ mutex_init(&acl->lock);
+ INIT_LIST_HEAD(&acl->mac_list);
+ acl->size = 0;
+ acl->policy = MAC_POLICY_OPEN;
+@@ -1792,10 +1792,10 @@ prism54_clear_mac(struct islpci_acl *acl)
+ struct list_head *ptr, *next;
+ struct mac_entry *entry;
+
+- down(&acl->sem);
++ mutex_lock(&acl->lock);
+
+ if (acl->size == 0) {
+- up(&acl->sem);
++ mutex_unlock(&acl->lock);
+ return;
+ }
+
+@@ -1806,7 +1806,7 @@ prism54_clear_mac(struct islpci_acl *acl)
+ kfree(entry);
+ }
+ acl->size = 0;
+- up(&acl->sem);
++ mutex_unlock(&acl->lock);
+ }
+
+ void
+@@ -1833,13 +1833,13 @@ prism54_add_mac(struct net_device *ndev, struct iw_request_info *info,
+
+ memcpy(entry->addr, addr->sa_data, ETH_ALEN);
+
+- if (down_interruptible(&acl->sem)) {
++ if (mutex_lock_interruptible(&acl->lock)) {
+ kfree(entry);
+ return -ERESTARTSYS;
+ }
+ list_add_tail(&entry->_list, &acl->mac_list);
+ acl->size++;
+- up(&acl->sem);
++ mutex_unlock(&acl->lock);
+
+ return 0;
+ }
+@@ -1856,18 +1856,18 @@ prism54_del_mac(struct net_device *ndev, struct iw_request_info *info,
+ if (addr->sa_family != ARPHRD_ETHER)
+ return -EOPNOTSUPP;
+
+- if (down_interruptible(&acl->sem))
++ if (mutex_lock_interruptible(&acl->lock))
+ return -ERESTARTSYS;
+ list_for_each_entry(entry, &acl->mac_list, _list) {
+ if (memcmp(entry->addr, addr->sa_data, ETH_ALEN) == 0) {
+ list_del(&entry->_list);
+ acl->size--;
+ kfree(entry);
+- up(&acl->sem);
++ mutex_unlock(&acl->lock);
+ return 0;
+ }
+ }
+- up(&acl->sem);
++ mutex_unlock(&acl->lock);
+ return -EINVAL;
+ }
+
+@@ -1882,7 +1882,7 @@ prism54_get_mac(struct net_device *ndev, struct iw_request_info *info,
+
+ dwrq->length = 0;
+
+- if (down_interruptible(&acl->sem))
++ if (mutex_lock_interruptible(&acl->lock))
+ return -ERESTARTSYS;
+
+ list_for_each_entry(entry, &acl->mac_list, _list) {
+@@ -1891,7 +1891,7 @@ prism54_get_mac(struct net_device *ndev, struct iw_request_info *info,
+ dwrq->length++;
+ dst++;
+ }
+- up(&acl->sem);
++ mutex_unlock(&acl->lock);
+ return 0;
+ }
+
+@@ -1955,11 +1955,11 @@ prism54_mac_accept(struct islpci_acl *acl, char *mac)
+ struct mac_entry *entry;
+ int res = 0;
+
+- if (down_interruptible(&acl->sem))
++ if (mutex_lock_interruptible(&acl->lock))
+ return -ERESTARTSYS;
+
+ if (acl->policy == MAC_POLICY_OPEN) {
+- up(&acl->sem);
++ mutex_unlock(&acl->lock);
+ return 1;
+ }
+
+@@ -1970,7 +1970,7 @@ prism54_mac_accept(struct islpci_acl *acl, char *mac)
+ }
+ }
+ res = (acl->policy == MAC_POLICY_ACCEPT) ? !res : res;
+- up(&acl->sem);
++ mutex_unlock(&acl->lock);
+
+ return res;
+ }
+@@ -2081,6 +2081,7 @@ link_changed(struct net_device *ndev, u32 bitrate)
+ islpci_private *priv = netdev_priv(ndev);
+
+ if (bitrate) {
++ netif_carrier_on(ndev);
+ if (priv->iw_mode == IW_MODE_INFRA) {
+ union iwreq_data uwrq;
+ prism54_get_wap(ndev, NULL, (struct sockaddr *) &uwrq,
+@@ -2089,8 +2090,10 @@ link_changed(struct net_device *ndev, u32 bitrate)
+ } else
+ send_simple_event(netdev_priv(ndev),
+ "Link established");
+- } else
++ } else {
++ netif_carrier_off(ndev);
+ send_simple_event(netdev_priv(ndev), "Link lost");
++ }
+ }
+
+ /* Beacon/ProbeResp payload header */
+@@ -2114,7 +2117,7 @@ prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid,
+ if (wpa_ie_len > MAX_WPA_IE_LEN)
+ wpa_ie_len = MAX_WPA_IE_LEN;
+
+- down(&priv->wpa_sem);
++ mutex_lock(&priv->wpa_lock);
+
+ /* try to use existing entry */
+ list_for_each(ptr, &priv->bss_wpa_list) {
+@@ -2165,7 +2168,7 @@ prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid,
+ kfree(bss);
+ }
+
+- up(&priv->wpa_sem);
++ mutex_unlock(&priv->wpa_lock);
+ }
+
+ static size_t
+@@ -2175,7 +2178,7 @@ prism54_wpa_bss_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie)
+ struct islpci_bss_wpa_ie *bss = NULL;
+ size_t len = 0;
+
+- down(&priv->wpa_sem);
++ mutex_lock(&priv->wpa_lock);
+
+ list_for_each(ptr, &priv->bss_wpa_list) {
+ bss = list_entry(ptr, struct islpci_bss_wpa_ie, list);
+@@ -2187,7 +2190,7 @@ prism54_wpa_bss_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie)
+ len = bss->wpa_ie_len;
+ memcpy(wpa_ie, bss->wpa_ie, len);
+ }
+- up(&priv->wpa_sem);
++ mutex_unlock(&priv->wpa_lock);
+
+ return len;
+ }
+@@ -2196,7 +2199,7 @@ void
+ prism54_wpa_bss_ie_init(islpci_private *priv)
+ {
+ INIT_LIST_HEAD(&priv->bss_wpa_list);
+- sema_init(&priv->wpa_sem, 1);
++ mutex_init(&priv->wpa_lock);
+ }
+
+ void
+diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
+index dbb538c..04c2638 100644
+--- a/drivers/net/wireless/prism54/islpci_dev.c
++++ b/drivers/net/wireless/prism54/islpci_dev.c
+@@ -387,7 +387,9 @@ islpci_open(struct net_device *ndev)
+ }
+
+ netif_start_queue(ndev);
+-/* netif_mark_up( ndev ); */
++
++ /* Turn off carrier unless we know we have associated */
++ netif_carrier_off(ndev);
+
+ return 0;
+ }
+@@ -864,7 +866,7 @@ islpci_setup(struct pci_dev *pdev)
+ mutex_init(&priv->mgmt_lock);
+ priv->mgmt_received = NULL;
+ init_waitqueue_head(&priv->mgmt_wqueue);
+- sema_init(&priv->stats_sem, 1);
++ mutex_init(&priv->stats_lock);
+ spin_lock_init(&priv->slock);
+
+ /* init state machine with off#1 state */
+diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h
+index 4e0182c..8e55a5f 100644
+--- a/drivers/net/wireless/prism54/islpci_dev.h
++++ b/drivers/net/wireless/prism54/islpci_dev.h
+@@ -55,7 +55,7 @@ struct islpci_acl {
+ enum { MAC_POLICY_OPEN=0, MAC_POLICY_ACCEPT=1, MAC_POLICY_REJECT=2 } policy;
+ struct list_head mac_list; /* a list of mac_entry */
+ int size; /* size of queue */
+- struct semaphore sem; /* accessed in ioctls and trap_work */
++ struct mutex lock; /* accessed in ioctls and trap_work */
+ };
+
+ struct islpci_membuf {
+@@ -88,7 +88,7 @@ typedef struct {
+
+ /* Take care of the wireless stats */
+ struct work_struct stats_work;
+- struct semaphore stats_sem;
++ struct mutex stats_lock;
+ /* remember when we last updated the stats */
+ unsigned long stats_timestamp;
+ /* The first is accessed under semaphore locking.
+@@ -178,7 +178,7 @@ typedef struct {
+ int wpa; /* WPA mode enabled */
+ struct list_head bss_wpa_list;
+ int num_bss_wpa;
+- struct semaphore wpa_sem;
++ struct mutex wpa_lock;
+ u8 wpa_ie[MAX_WPA_IE_LEN];
+ size_t wpa_ie_len;
+
+diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
+index f3858ee..963960d 100644
+--- a/drivers/net/wireless/ray_cs.c
++++ b/drivers/net/wireless/ray_cs.c
+@@ -34,6 +34,7 @@
+ #include <linux/kernel.h>
+ #include <linux/proc_fs.h>
+ #include <linux/ptrace.h>
++#include <linux/seq_file.h>
+ #include <linux/slab.h>
+ #include <linux/string.h>
+ #include <linux/timer.h>
+@@ -2582,7 +2583,7 @@ static char *nettype[] = {"Adhoc", "Infra "};
+ static char *framing[] = {"Encapsulation", "Translation"}
+ ;
+ /*===========================================================================*/
+-static int ray_cs_proc_read(char *buf, char **start, off_t offset, int len)
++static int ray_cs_proc_show(struct seq_file *m, void *v)
+ {
+ /* Print current values which are not available via other means
+ * eg ifconfig
+@@ -2606,83 +2607,93 @@ static int ray_cs_proc_read(char *buf, char **start, off_t offset, int len)
+ if (!local)
+ return 0;
+
+- len = 0;
+-
+- len += sprintf(buf + len, "Raylink Wireless LAN driver status\n");
+- len += sprintf(buf + len, "%s\n", rcsid);
++ seq_puts(m, "Raylink Wireless LAN driver status\n");
++ seq_printf(m, "%s\n", rcsid);
+ /* build 4 does not report version, and field is 0x55 after memtest */
+- len += sprintf(buf + len, "Firmware version = ");
++ seq_puts(m, "Firmware version = ");
+ if (local->fw_ver == 0x55)
+- len += sprintf(buf + len, "4 - Use dump_cis for more details\n");
++ seq_puts(m, "4 - Use dump_cis for more details\n");
+ else
+- len += sprintf(buf + len, "%2d.%02d.%02d\n",
++ seq_printf(m, "%2d.%02d.%02d\n",
+ local->fw_ver, local->fw_bld, local->fw_var);
+
+ for (i=0; i<32; i++) c[i] = local->sparm.b5.a_current_ess_id[i];
+ c[32] = 0;
+- len += sprintf(buf + len, "%s network ESSID = \"%s\"\n",
++ seq_printf(m, "%s network ESSID = \"%s\"\n",
+ nettype[local->sparm.b5.a_network_type], c);
+
+ p = local->bss_id;
+- len += sprintf(buf + len, "BSSID = %s\n",
++ seq_printf(m, "BSSID = %s\n",
+ print_mac(mac, p));
+
+- len += sprintf(buf + len, "Country code = %d\n",
++ seq_printf(m, "Country code = %d\n",
+ local->sparm.b5.a_curr_country_code);
+
+ i = local->card_status;
+ if (i < 0) i = 10;
+ if (i > 16) i = 10;
+- len += sprintf(buf + len, "Card status = %s\n", card_status[i]);
++ seq_printf(m, "Card status = %s\n", card_status[i]);
+
+- len += sprintf(buf + len, "Framing mode = %s\n",framing[translate]);
++ seq_printf(m, "Framing mode = %s\n",framing[translate]);
+
+- len += sprintf(buf + len, "Last pkt signal lvl = %d\n", local->last_rsl);
++ seq_printf(m, "Last pkt signal lvl = %d\n", local->last_rsl);
+
+ if (local->beacon_rxed) {
+ /* Pull some fields out of last beacon received */
+- len += sprintf(buf + len, "Beacon Interval = %d Kus\n",
++ seq_printf(m, "Beacon Interval = %d Kus\n",
+ local->last_bcn.beacon_intvl[0]
+ + 256 * local->last_bcn.beacon_intvl[1]);
+
+ p = local->last_bcn.elements;
+ if (p[0] == C_ESSID_ELEMENT_ID) p += p[1] + 2;
+ else {
+- len += sprintf(buf + len, "Parse beacon failed at essid element id = %d\n",p[0]);
+- return len;
++ seq_printf(m, "Parse beacon failed at essid element id = %d\n",p[0]);
++ return 0;
+ }
+
+ if (p[0] == C_SUPPORTED_RATES_ELEMENT_ID) {
+- len += sprintf(buf + len, "Supported rate codes = ");
++ seq_puts(m, "Supported rate codes = ");
+ for (i=2; i<p[1] + 2; i++)
+- len += sprintf(buf + len, "0x%02x ", p[i]);
+- len += sprintf(buf + len, "\n");
++ seq_printf(m, "0x%02x ", p[i]);
++ seq_putc(m, '\n');
+ p += p[1] + 2;
+ }
+ else {
+- len += sprintf(buf + len, "Parse beacon failed at rates element\n");
+- return len;
++ seq_puts(m, "Parse beacon failed at rates element\n");
++ return 0;
+ }
+
+ if (p[0] == C_FH_PARAM_SET_ELEMENT_ID) {
+ pfh = (struct freq_hop_element *)p;
+- len += sprintf(buf + len, "Hop dwell = %d Kus\n",
++ seq_printf(m, "Hop dwell = %d Kus\n",
+ pfh->dwell_time[0] + 256 * pfh->dwell_time[1]);
+- len += sprintf(buf + len, "Hop set = %d \n", pfh->hop_set);
+- len += sprintf(buf + len, "Hop pattern = %d \n", pfh->hop_pattern);
+- len += sprintf(buf + len, "Hop index = %d \n", pfh->hop_index);
++ seq_printf(m, "Hop set = %d \n", pfh->hop_set);
++ seq_printf(m, "Hop pattern = %d \n", pfh->hop_pattern);
++ seq_printf(m, "Hop index = %d \n", pfh->hop_index);
+ p += p[1] + 2;
+ }
+ else {
+- len += sprintf(buf + len, "Parse beacon failed at FH param element\n");
+- return len;
++ seq_puts(m, "Parse beacon failed at FH param element\n");
++ return 0;
+ }
+ } else {
+- len += sprintf(buf + len, "No beacons received\n");
++ seq_puts(m, "No beacons received\n");
+ }
+- return len;
++ return 0;
+ }
+
++static int ray_cs_proc_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, ray_cs_proc_show, NULL);
++}
++
++static const struct file_operations ray_cs_proc_fops = {
++ .owner = THIS_MODULE,
++ .open = ray_cs_proc_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
+ #endif
+ /*===========================================================================*/
+ static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type)
+@@ -2815,7 +2826,7 @@ static int __init init_ray_cs(void)
+ #ifdef CONFIG_PROC_FS
+ proc_mkdir("driver/ray_cs", NULL);
+
+- create_proc_info_entry("driver/ray_cs/ray_cs", 0, NULL, &ray_cs_proc_read);
++ proc_create("driver/ray_cs/ray_cs", 0, NULL, &ray_cs_proc_fops);
+ raycs_write("driver/ray_cs/essid", write_essid, NULL);
+ raycs_write("driver/ray_cs/net_type", write_int, &net_type);
+ raycs_write("driver/ray_cs/translate", write_int, &translate);
+diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
+index 10b776c..d0b1fb1 100644
+--- a/drivers/net/wireless/rndis_wlan.c
++++ b/drivers/net/wireless/rndis_wlan.c
+@@ -154,128 +154,121 @@ MODULE_PARM_DESC(workaround_interval,
+ #define NDIS_802_11_LENGTH_RATES 8
+ #define NDIS_802_11_LENGTH_RATES_EX 16
+
+-struct NDIS_802_11_SSID {
+- __le32 SsidLength;
+- u8 Ssid[NDIS_802_11_LENGTH_SSID];
+-} __attribute__((packed));
+-
+-enum NDIS_802_11_NETWORK_TYPE {
+- Ndis802_11FH,
+- Ndis802_11DS,
+- Ndis802_11OFDM5,
+- Ndis802_11OFDM24,
+- Ndis802_11NetworkTypeMax
++enum ndis_80211_net_type {
++ ndis_80211_type_freq_hop,
++ ndis_80211_type_direct_seq,
++ ndis_80211_type_ofdm_a,
++ ndis_80211_type_ofdm_g
+ };
+
+-struct NDIS_802_11_CONFIGURATION_FH {
+- __le32 Length;
+- __le32 HopPattern;
+- __le32 HopSet;
+- __le32 DwellTime;
+-} __attribute__((packed));
+-
+-struct NDIS_802_11_CONFIGURATION {
+- __le32 Length;
+- __le32 BeaconPeriod;
+- __le32 ATIMWindow;
+- __le32 DSConfig;
+- struct NDIS_802_11_CONFIGURATION_FH FHConfig;
+-} __attribute__((packed));
+-
+-enum NDIS_802_11_NETWORK_INFRASTRUCTURE {
+- Ndis802_11IBSS,
+- Ndis802_11Infrastructure,
+- Ndis802_11AutoUnknown,
+- Ndis802_11InfrastructureMax
++enum ndis_80211_net_infra {
++ ndis_80211_infra_adhoc,
++ ndis_80211_infra_infra,
++ ndis_80211_infra_auto_unknown
+ };
+
+-enum NDIS_802_11_AUTHENTICATION_MODE {
+- Ndis802_11AuthModeOpen,
+- Ndis802_11AuthModeShared,
+- Ndis802_11AuthModeAutoSwitch,
+- Ndis802_11AuthModeWPA,
+- Ndis802_11AuthModeWPAPSK,
+- Ndis802_11AuthModeWPANone,
+- Ndis802_11AuthModeWPA2,
+- Ndis802_11AuthModeWPA2PSK,
+- Ndis802_11AuthModeMax
++enum ndis_80211_auth_mode {
++ ndis_80211_auth_open,
++ ndis_80211_auth_shared,
++ ndis_80211_auth_auto_switch,
++ ndis_80211_auth_wpa,
++ ndis_80211_auth_wpa_psk,
++ ndis_80211_auth_wpa_none,
++ ndis_80211_auth_wpa2,
++ ndis_80211_auth_wpa2_psk
+ };
+
+-enum NDIS_802_11_ENCRYPTION_STATUS {
+- Ndis802_11WEPEnabled,
+- Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled,
+- Ndis802_11WEPDisabled,
+- Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled,
+- Ndis802_11WEPKeyAbsent,
+- Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent,
+- Ndis802_11WEPNotSupported,
+- Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported,
+- Ndis802_11Encryption2Enabled,
+- Ndis802_11Encryption2KeyAbsent,
+- Ndis802_11Encryption3Enabled,
+- Ndis802_11Encryption3KeyAbsent
++enum ndis_80211_encr_status {
++ ndis_80211_encr_wep_enabled,
++ ndis_80211_encr_disabled,
++ ndis_80211_encr_wep_key_absent,
++ ndis_80211_encr_not_supported,
++ ndis_80211_encr_tkip_enabled,
++ ndis_80211_encr_tkip_key_absent,
++ ndis_80211_encr_ccmp_enabled,
++ ndis_80211_encr_ccmp_key_absent
+ };
+
+-enum NDIS_802_11_PRIVACY_FILTER {
+- Ndis802_11PrivFilterAcceptAll,
+- Ndis802_11PrivFilter8021xWEP
++enum ndis_80211_priv_filter {
++ ndis_80211_priv_accept_all,
++ ndis_80211_priv_8021x_wep
+ };
+
+-struct NDIS_WLAN_BSSID_EX {
+- __le32 Length;
+- u8 MacAddress[6];
+- u8 Padding[2];
+- struct NDIS_802_11_SSID Ssid;
+- __le32 Privacy;
+- __le32 Rssi;
+- __le32 NetworkTypeInUse;
+- struct NDIS_802_11_CONFIGURATION Configuration;
+- __le32 InfrastructureMode;
+- u8 SupportedRates[NDIS_802_11_LENGTH_RATES_EX];
+- __le32 IELength;
+- u8 IEs[0];
++struct ndis_80211_ssid {
++ __le32 length;
++ u8 essid[NDIS_802_11_LENGTH_SSID];
+ } __attribute__((packed));
+
+-struct NDIS_802_11_BSSID_LIST_EX {
+- __le32 NumberOfItems;
+- struct NDIS_WLAN_BSSID_EX Bssid[0];
++struct ndis_80211_conf_freq_hop {
++ __le32 length;
++ __le32 hop_pattern;
++ __le32 hop_set;
++ __le32 dwell_time;
+ } __attribute__((packed));
+
+-struct NDIS_802_11_FIXED_IEs {
+- u8 Timestamp[8];
+- __le16 BeaconInterval;
+- __le16 Capabilities;
++struct ndis_80211_conf {
++ __le32 length;
++ __le32 beacon_period;
++ __le32 atim_window;
++ __le32 ds_config;
++ struct ndis_80211_conf_freq_hop fh_config;
+ } __attribute__((packed));
+
+-struct NDIS_802_11_WEP {
+- __le32 Length;
+- __le32 KeyIndex;
+- __le32 KeyLength;
+- u8 KeyMaterial[32];
++struct ndis_80211_bssid_ex {
++ __le32 length;
++ u8 mac[6];
++ u8 padding[2];
++ struct ndis_80211_ssid ssid;
++ __le32 privacy;
++ __le32 rssi;
++ __le32 net_type;
++ struct ndis_80211_conf config;
++ __le32 net_infra;
++ u8 rates[NDIS_802_11_LENGTH_RATES_EX];
++ __le32 ie_length;
++ u8 ies[0];
+ } __attribute__((packed));
+
+-struct NDIS_802_11_KEY {
+- __le32 Length;
+- __le32 KeyIndex;
+- __le32 KeyLength;
+- u8 Bssid[6];
+- u8 Padding[6];
+- u8 KeyRSC[8];
+- u8 KeyMaterial[32];
++struct ndis_80211_bssid_list_ex {
++ __le32 num_items;
++ struct ndis_80211_bssid_ex bssid[0];
+ } __attribute__((packed));
+
+-struct NDIS_802_11_REMOVE_KEY {
+- __le32 Length;
+- __le32 KeyIndex;
+- u8 Bssid[6];
++struct ndis_80211_fixed_ies {
++ u8 timestamp[8];
++ __le16 beacon_interval;
++ __le16 capabilities;
+ } __attribute__((packed));
+
+-struct RNDIS_CONFIG_PARAMETER_INFOBUFFER {
+- __le32 ParameterNameOffset;
+- __le32 ParameterNameLength;
+- __le32 ParameterType;
+- __le32 ParameterValueOffset;
+- __le32 ParameterValueLength;
++struct ndis_80211_wep_key {
++ __le32 size;
++ __le32 index;
++ __le32 length;
++ u8 material[32];
++} __attribute__((packed));
++
++struct ndis_80211_key {
++ __le32 size;
++ __le32 index;
++ __le32 length;
++ u8 bssid[6];
++ u8 padding[6];
++ u8 rsc[8];
++ u8 material[32];
++} __attribute__((packed));
++
++struct ndis_80211_remove_key {
++ __le32 size;
++ __le32 index;
++ u8 bssid[6];
++} __attribute__((packed));
++
++struct ndis_config_param {
++ __le32 name_offs;
++ __le32 name_length;
++ __le32 type;
++ __le32 value_offs;
++ __le32 value_length;
+ } __attribute__((packed));
+
+ /* these have to match what is in wpa_supplicant */
+@@ -334,7 +327,7 @@ struct rndis_wext_private {
+ /* hardware state */
+ int radio_on;
+ int infra_mode;
+- struct NDIS_802_11_SSID essid;
++ struct ndis_80211_ssid essid;
+
+ /* encryption stuff */
+ int encr_tx_key_index;
+@@ -484,7 +477,7 @@ static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len)
+ static int rndis_set_config_parameter(struct usbnet *dev, char *param,
+ int value_type, void *value)
+ {
+- struct RNDIS_CONFIG_PARAMETER_INFOBUFFER *infobuf;
++ struct ndis_config_param *infobuf;
+ int value_len, info_len, param_len, ret, i;
+ __le16 *unibuf;
+ __le32 *dst_value;
+@@ -519,12 +512,11 @@ static int rndis_set_config_parameter(struct usbnet *dev, char *param,
+ devdbg(dev, "setting config parameter: %s, value: %d",
+ param, *(u32 *)value);
+
+- infobuf->ParameterNameOffset = cpu_to_le32(sizeof(*infobuf));
+- infobuf->ParameterNameLength = cpu_to_le32(param_len);
+- infobuf->ParameterType = cpu_to_le32(value_type);
+- infobuf->ParameterValueOffset = cpu_to_le32(sizeof(*infobuf) +
+- param_len);
+- infobuf->ParameterValueLength = cpu_to_le32(value_len);
++ infobuf->name_offs = cpu_to_le32(sizeof(*infobuf));
++ infobuf->name_length = cpu_to_le32(param_len);
++ infobuf->type = cpu_to_le32(value_type);
++ infobuf->value_offs = cpu_to_le32(sizeof(*infobuf) + param_len);
++ infobuf->value_length = cpu_to_le32(value_len);
+
+ /* simple string to unicode string conversion */
+ unibuf = (void *)infobuf + sizeof(*infobuf);
+@@ -630,7 +622,7 @@ static int freq_to_dsconfig(struct iw_freq *freq, unsigned int *dsconfig)
+ static int
+ add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index);
+
+-static int get_essid(struct usbnet *usbdev, struct NDIS_802_11_SSID *ssid)
++static int get_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid)
+ {
+ int ret, len;
+
+@@ -638,14 +630,14 @@ static int get_essid(struct usbnet *usbdev, struct NDIS_802_11_SSID *ssid)
+ ret = rndis_query_oid(usbdev, OID_802_11_SSID, ssid, &len);
+
+ if (ret != 0)
+- ssid->SsidLength = 0;
++ ssid->length = 0;
+
+ #ifdef DEBUG
+ {
+ unsigned char tmp[NDIS_802_11_LENGTH_SSID + 1];
+
+- memcpy(tmp, ssid->Ssid, le32_to_cpu(ssid->SsidLength));
+- tmp[le32_to_cpu(ssid->SsidLength)] = 0;
++ memcpy(tmp, ssid->essid, le32_to_cpu(ssid->length));
++ tmp[le32_to_cpu(ssid->length)] = 0;
+ devdbg(usbdev, "get_essid: '%s', ret: %d", tmp, ret);
+ }
+ #endif
+@@ -653,7 +645,7 @@ static int get_essid(struct usbnet *usbdev, struct NDIS_802_11_SSID *ssid)
+ }
+
+
+-static int set_essid(struct usbnet *usbdev, struct NDIS_802_11_SSID *ssid)
++static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid)
+ {
+ struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+ int ret;
+@@ -697,7 +689,7 @@ static int is_associated(struct usbnet *usbdev)
+ static int disassociate(struct usbnet *usbdev, int reset_ssid)
+ {
+ struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+- struct NDIS_802_11_SSID ssid;
++ struct ndis_80211_ssid ssid;
+ int i, ret = 0;
+
+ if (priv->radio_on) {
+@@ -714,12 +706,12 @@ static int disassociate(struct usbnet *usbdev, int reset_ssid)
+ /* disassociate causes radio to be turned off; if reset_ssid
+ * is given, set random ssid to enable radio */
+ if (reset_ssid) {
+- ssid.SsidLength = cpu_to_le32(sizeof(ssid.Ssid));
+- get_random_bytes(&ssid.Ssid[2], sizeof(ssid.Ssid)-2);
+- ssid.Ssid[0] = 0x1;
+- ssid.Ssid[1] = 0xff;
+- for (i = 2; i < sizeof(ssid.Ssid); i++)
+- ssid.Ssid[i] = 0x1 + (ssid.Ssid[i] * 0xfe / 0xff);
++ ssid.length = cpu_to_le32(sizeof(ssid.essid));
++ get_random_bytes(&ssid.essid[2], sizeof(ssid.essid)-2);
++ ssid.essid[0] = 0x1;
++ ssid.essid[1] = 0xff;
++ for (i = 2; i < sizeof(ssid.essid); i++)
++ ssid.essid[i] = 0x1 + (ssid.essid[i] * 0xfe / 0xff);
+ ret = set_essid(usbdev, &ssid);
+ }
+ return ret;
+@@ -737,23 +729,23 @@ static int set_auth_mode(struct usbnet *usbdev, int wpa_version, int authalg)
+
+ if (wpa_version & IW_AUTH_WPA_VERSION_WPA2) {
+ if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_802_1X)
+- auth_mode = Ndis802_11AuthModeWPA2;
++ auth_mode = ndis_80211_auth_wpa2;
+ else
+- auth_mode = Ndis802_11AuthModeWPA2PSK;
++ auth_mode = ndis_80211_auth_wpa2_psk;
+ } else if (wpa_version & IW_AUTH_WPA_VERSION_WPA) {
+ if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_802_1X)
+- auth_mode = Ndis802_11AuthModeWPA;
++ auth_mode = ndis_80211_auth_wpa;
+ else if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_PSK)
+- auth_mode = Ndis802_11AuthModeWPAPSK;
++ auth_mode = ndis_80211_auth_wpa_psk;
+ else
+- auth_mode = Ndis802_11AuthModeWPANone;
++ auth_mode = ndis_80211_auth_wpa_none;
+ } else if (authalg & IW_AUTH_ALG_SHARED_KEY) {
+ if (authalg & IW_AUTH_ALG_OPEN_SYSTEM)
+- auth_mode = Ndis802_11AuthModeAutoSwitch;
++ auth_mode = ndis_80211_auth_auto_switch;
+ else
+- auth_mode = Ndis802_11AuthModeShared;
++ auth_mode = ndis_80211_auth_shared;
+ } else
+- auth_mode = Ndis802_11AuthModeOpen;
++ auth_mode = ndis_80211_auth_open;
+
+ tmp = cpu_to_le32(auth_mode);
+ ret = rndis_set_oid(usbdev, OID_802_11_AUTHENTICATION_MODE, &tmp,
+@@ -778,9 +770,9 @@ static int set_priv_filter(struct usbnet *usbdev)
+
+ if (priv->wpa_version & IW_AUTH_WPA_VERSION_WPA2 ||
+ priv->wpa_version & IW_AUTH_WPA_VERSION_WPA)
+- tmp = cpu_to_le32(Ndis802_11PrivFilter8021xWEP);
++ tmp = cpu_to_le32(ndis_80211_priv_8021x_wep);
+ else
+- tmp = cpu_to_le32(Ndis802_11PrivFilterAcceptAll);
++ tmp = cpu_to_le32(ndis_80211_priv_accept_all);
+
+ return rndis_set_oid(usbdev, OID_802_11_PRIVACY_FILTER, &tmp,
+ sizeof(tmp));
+@@ -798,18 +790,18 @@ static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise)
+ groupwise);
+
+ if (pairwise & IW_AUTH_CIPHER_CCMP)
+- encr_mode = Ndis802_11Encryption3Enabled;
++ encr_mode = ndis_80211_encr_ccmp_enabled;
+ else if (pairwise & IW_AUTH_CIPHER_TKIP)
+- encr_mode = Ndis802_11Encryption2Enabled;
++ encr_mode = ndis_80211_encr_tkip_enabled;
+ else if (pairwise &
+ (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104))
+- encr_mode = Ndis802_11Encryption1Enabled;
++ encr_mode = ndis_80211_encr_wep_enabled;
+ else if (groupwise & IW_AUTH_CIPHER_CCMP)
+- encr_mode = Ndis802_11Encryption3Enabled;
++ encr_mode = ndis_80211_encr_ccmp_enabled;
+ else if (groupwise & IW_AUTH_CIPHER_TKIP)
+- encr_mode = Ndis802_11Encryption2Enabled;
++ encr_mode = ndis_80211_encr_tkip_enabled;
+ else
+- encr_mode = Ndis802_11EncryptionDisabled;
++ encr_mode = ndis_80211_encr_disabled;
+
+ tmp = cpu_to_le32(encr_mode);
+ ret = rndis_set_oid(usbdev, OID_802_11_ENCRYPTION_STATUS, &tmp,
+@@ -877,7 +869,7 @@ static void set_default_iw_params(struct usbnet *usbdev)
+ priv->wpa_keymgmt = 0;
+ priv->wpa_version = 0;
+
+- set_infra_mode(usbdev, Ndis802_11Infrastructure);
++ set_infra_mode(usbdev, ndis_80211_infra_infra);
+ set_auth_mode(usbdev, IW_AUTH_WPA_VERSION_DISABLED,
+ IW_AUTH_ALG_OPEN_SYSTEM);
+ set_priv_filter(usbdev);
+@@ -899,7 +891,7 @@ static int deauthenticate(struct usbnet *usbdev)
+ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index)
+ {
+ struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+- struct NDIS_802_11_WEP ndis_key;
++ struct ndis_80211_wep_key ndis_key;
+ int ret;
+
+ if (key_len <= 0 || key_len > 32 || index < 0 || index >= 4)
+@@ -907,13 +899,13 @@ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index)
+
+ memset(&ndis_key, 0, sizeof(ndis_key));
+
+- ndis_key.Length = cpu_to_le32(sizeof(ndis_key));
+- ndis_key.KeyLength = cpu_to_le32(key_len);
+- ndis_key.KeyIndex = cpu_to_le32(index);
+- memcpy(&ndis_key.KeyMaterial, key, key_len);
++ ndis_key.size = cpu_to_le32(sizeof(ndis_key));
++ ndis_key.length = cpu_to_le32(key_len);
++ ndis_key.index = cpu_to_le32(index);
++ memcpy(&ndis_key.material, key, key_len);
+
+ if (index == priv->encr_tx_key_index) {
+- ndis_key.KeyIndex |= cpu_to_le32(1 << 31);
++ ndis_key.index |= cpu_to_le32(1 << 31);
+ ret = set_encr_mode(usbdev, IW_AUTH_CIPHER_WEP104,
+ IW_AUTH_CIPHER_NONE);
+ if (ret)
+@@ -940,7 +932,7 @@ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index)
+ static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN])
+ {
+ struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+- struct NDIS_802_11_REMOVE_KEY remove_key;
++ struct ndis_80211_remove_key remove_key;
+ __le32 keyindex;
+ int ret;
+
+@@ -954,17 +946,17 @@ static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN])
+ priv->wpa_cipher_pair == IW_AUTH_CIPHER_CCMP ||
+ priv->wpa_cipher_group == IW_AUTH_CIPHER_TKIP ||
+ priv->wpa_cipher_group == IW_AUTH_CIPHER_CCMP) {
+- remove_key.Length = cpu_to_le32(sizeof(remove_key));
+- remove_key.KeyIndex = cpu_to_le32(index);
++ remove_key.size = cpu_to_le32(sizeof(remove_key));
++ remove_key.index = cpu_to_le32(index);
+ if (bssid) {
+ /* pairwise key */
+ if (memcmp(bssid, ffff_bssid, ETH_ALEN) != 0)
+- remove_key.KeyIndex |= cpu_to_le32(1 << 30);
+- memcpy(remove_key.Bssid, bssid,
+- sizeof(remove_key.Bssid));
++ remove_key.index |= cpu_to_le32(1 << 30);
++ memcpy(remove_key.bssid, bssid,
++ sizeof(remove_key.bssid));
+ } else
+- memset(remove_key.Bssid, 0xff,
+- sizeof(remove_key.Bssid));
++ memset(remove_key.bssid, 0xff,
++ sizeof(remove_key.bssid));
+
+ ret = rndis_set_oid(usbdev, OID_802_11_REMOVE_KEY, &remove_key,
+ sizeof(remove_key));
+@@ -1184,7 +1176,7 @@ static int rndis_iw_get_name(struct net_device *dev,
+ static int rndis_iw_set_essid(struct net_device *dev,
+ struct iw_request_info *info, union iwreq_data *wrqu, char *essid)
+ {
+- struct NDIS_802_11_SSID ssid;
++ struct ndis_80211_ssid ssid;
+ int length = wrqu->essid.length;
+ struct usbnet *usbdev = dev->priv;
+
+@@ -1194,11 +1186,11 @@ static int rndis_iw_set_essid(struct net_device *dev,
+ if (length > NDIS_802_11_LENGTH_SSID)
+ length = NDIS_802_11_LENGTH_SSID;
+
+- ssid.SsidLength = cpu_to_le32(length);
++ ssid.length = cpu_to_le32(length);
+ if (length > 0)
+- memcpy(ssid.Ssid, essid, length);
++ memcpy(ssid.essid, essid, length);
+ else
+- memset(ssid.Ssid, 0, NDIS_802_11_LENGTH_SSID);
++ memset(ssid.essid, 0, NDIS_802_11_LENGTH_SSID);
+
+ set_assoc_params(usbdev);
+
+@@ -1212,16 +1204,16 @@ static int rndis_iw_set_essid(struct net_device *dev,
+ static int rndis_iw_get_essid(struct net_device *dev,
+ struct iw_request_info *info, union iwreq_data *wrqu, char *essid)
+ {
+- struct NDIS_802_11_SSID ssid;
++ struct ndis_80211_ssid ssid;
+ struct usbnet *usbdev = dev->priv;
+ int ret;
+
+ ret = get_essid(usbdev, &ssid);
+
+- if (ret == 0 && le32_to_cpu(ssid.SsidLength) > 0) {
++ if (ret == 0 && le32_to_cpu(ssid.length) > 0) {
+ wrqu->essid.flags = 1;
+- wrqu->essid.length = le32_to_cpu(ssid.SsidLength);
+- memcpy(essid, ssid.Ssid, wrqu->essid.length);
++ wrqu->essid.length = le32_to_cpu(ssid.length);
++ memcpy(essid, ssid.essid, wrqu->essid.length);
+ essid[wrqu->essid.length] = 0;
+ } else {
+ memset(essid, 0, sizeof(NDIS_802_11_LENGTH_SSID));
+@@ -1398,13 +1390,13 @@ static int rndis_iw_get_mode(struct net_device *dev,
+ struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+
+ switch (priv->infra_mode) {
+- case Ndis802_11IBSS:
++ case ndis_80211_infra_adhoc:
+ wrqu->mode = IW_MODE_ADHOC;
+ break;
+- case Ndis802_11Infrastructure:
++ case ndis_80211_infra_infra:
+ wrqu->mode = IW_MODE_INFRA;
+ break;
+- /*case Ndis802_11AutoUnknown:*/
++ /*case ndis_80211_infra_auto_unknown:*/
+ default:
+ wrqu->mode = IW_MODE_AUTO;
+ break;
+@@ -1424,14 +1416,14 @@ static int rndis_iw_set_mode(struct net_device *dev,
+
+ switch (wrqu->mode) {
+ case IW_MODE_ADHOC:
+- mode = Ndis802_11IBSS;
++ mode = ndis_80211_infra_adhoc;
+ break;
+ case IW_MODE_INFRA:
+- mode = Ndis802_11Infrastructure;
++ mode = ndis_80211_infra_infra;
+ break;
+ /*case IW_MODE_AUTO:*/
+ default:
+- mode = Ndis802_11AutoUnknown;
++ mode = ndis_80211_infra_auto_unknown;
+ break;
+ }
+
+@@ -1507,7 +1499,7 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
+ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+ struct usbnet *usbdev = dev->priv;
+ struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
+- struct NDIS_802_11_KEY ndis_key;
++ struct ndis_80211_key ndis_key;
+ int keyidx, ret;
+ u8 *addr;
+
+@@ -1532,54 +1524,54 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
+ ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0)
+ return remove_key(usbdev, keyidx, NULL);
+
+- if (ext->key_len > sizeof(ndis_key.KeyMaterial))
++ if (ext->key_len > sizeof(ndis_key.material))
+ return -1;
+
+ memset(&ndis_key, 0, sizeof(ndis_key));
+
+- ndis_key.Length = cpu_to_le32(sizeof(ndis_key) -
+- sizeof(ndis_key.KeyMaterial) + ext->key_len);
+- ndis_key.KeyLength = cpu_to_le32(ext->key_len);
+- ndis_key.KeyIndex = cpu_to_le32(keyidx);
++ ndis_key.size = cpu_to_le32(sizeof(ndis_key) -
++ sizeof(ndis_key.material) + ext->key_len);
++ ndis_key.length = cpu_to_le32(ext->key_len);
++ ndis_key.index = cpu_to_le32(keyidx);
+
+ if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
+- memcpy(ndis_key.KeyRSC, ext->rx_seq, 6);
+- ndis_key.KeyIndex |= cpu_to_le32(1 << 29);
++ memcpy(ndis_key.rsc, ext->rx_seq, 6);
++ ndis_key.index |= cpu_to_le32(1 << 29);
+ }
+
+ addr = ext->addr.sa_data;
+ if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
+ /* group key */
+- if (priv->infra_mode == Ndis802_11IBSS)
+- memset(ndis_key.Bssid, 0xff, ETH_ALEN);
++ if (priv->infra_mode == ndis_80211_infra_adhoc)
++ memset(ndis_key.bssid, 0xff, ETH_ALEN);
+ else
+- get_bssid(usbdev, ndis_key.Bssid);
++ get_bssid(usbdev, ndis_key.bssid);
+ } else {
+ /* pairwise key */
+- ndis_key.KeyIndex |= cpu_to_le32(1 << 30);
+- memcpy(ndis_key.Bssid, addr, ETH_ALEN);
++ ndis_key.index |= cpu_to_le32(1 << 30);
++ memcpy(ndis_key.bssid, addr, ETH_ALEN);
+ }
+
+ if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+- ndis_key.KeyIndex |= cpu_to_le32(1 << 31);
++ ndis_key.index |= cpu_to_le32(1 << 31);
+
+ if (ext->alg == IW_ENCODE_ALG_TKIP && ext->key_len == 32) {
+ /* wpa_supplicant gives us the Michael MIC RX/TX keys in
+ * different order than NDIS spec, so swap the order here. */
+- memcpy(ndis_key.KeyMaterial, ext->key, 16);
+- memcpy(ndis_key.KeyMaterial + 16, ext->key + 24, 8);
+- memcpy(ndis_key.KeyMaterial + 24, ext->key + 16, 8);
++ memcpy(ndis_key.material, ext->key, 16);
++ memcpy(ndis_key.material + 16, ext->key + 24, 8);
++ memcpy(ndis_key.material + 24, ext->key + 16, 8);
+ } else
+- memcpy(ndis_key.KeyMaterial, ext->key, ext->key_len);
++ memcpy(ndis_key.material, ext->key, ext->key_len);
+
+ ret = rndis_set_oid(usbdev, OID_802_11_ADD_KEY, &ndis_key,
+- le32_to_cpu(ndis_key.Length));
++ le32_to_cpu(ndis_key.size));
+ devdbg(usbdev, "SIOCSIWENCODEEXT: OID_802_11_ADD_KEY -> %08X", ret);
+ if (ret != 0)
+ return ret;
+
+ priv->encr_key_len[keyidx] = ext->key_len;
+- memcpy(&priv->encr_keys[keyidx], ndis_key.KeyMaterial, ext->key_len);
++ memcpy(&priv->encr_keys[keyidx], ndis_key.material, ext->key_len);
+ if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+ priv->encr_tx_key_index = keyidx;
+
+@@ -1611,7 +1603,7 @@ static int rndis_iw_set_scan(struct net_device *dev,
+
+
+ static char *rndis_translate_scan(struct net_device *dev,
+- char *cev, char *end_buf, struct NDIS_WLAN_BSSID_EX *bssid)
++ char *cev, char *end_buf, struct ndis_80211_bssid_ex *bssid)
+ {
+ #ifdef DEBUG
+ struct usbnet *usbdev = dev->priv;
+@@ -1624,60 +1616,55 @@ static char *rndis_translate_scan(struct net_device *dev,
+ unsigned char sbuf[32];
+ DECLARE_MAC_BUF(mac);
+
+- bssid_len = le32_to_cpu(bssid->Length);
++ bssid_len = le32_to_cpu(bssid->length);
+
+- devdbg(usbdev, "BSSID %s", print_mac(mac, bssid->MacAddress));
++ devdbg(usbdev, "BSSID %s", print_mac(mac, bssid->mac));
+ iwe.cmd = SIOCGIWAP;
+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+- memcpy(iwe.u.ap_addr.sa_data, bssid->MacAddress, ETH_ALEN);
++ memcpy(iwe.u.ap_addr.sa_data, bssid->mac, ETH_ALEN);
+ cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN);
+
+- devdbg(usbdev, "SSID(%d) %s",
+- le32_to_cpu(bssid->Ssid.SsidLength),
+- bssid->Ssid.Ssid);
++ devdbg(usbdev, "SSID(%d) %s", le32_to_cpu(bssid->ssid.length),
++ bssid->ssid.essid);
+ iwe.cmd = SIOCGIWESSID;
+- iwe.u.essid.length = le32_to_cpu(bssid->Ssid.SsidLength);
++ iwe.u.essid.length = le32_to_cpu(bssid->ssid.length);
+ iwe.u.essid.flags = 1;
+- cev = iwe_stream_add_point(cev, end_buf, &iwe,
+- bssid->Ssid.Ssid);
++ cev = iwe_stream_add_point(cev, end_buf, &iwe, bssid->ssid.essid);
+
+- devdbg(usbdev, "MODE %d",
+- le32_to_cpu(bssid->InfrastructureMode));
++ devdbg(usbdev, "MODE %d", le32_to_cpu(bssid->net_infra));
+ iwe.cmd = SIOCGIWMODE;
+- switch (le32_to_cpu(bssid->InfrastructureMode)) {
+- case Ndis802_11IBSS:
++ switch (le32_to_cpu(bssid->net_infra)) {
++ case ndis_80211_infra_adhoc:
+ iwe.u.mode = IW_MODE_ADHOC;
+ break;
+- case Ndis802_11Infrastructure:
++ case ndis_80211_infra_infra:
+ iwe.u.mode = IW_MODE_INFRA;
+ break;
+- /*case Ndis802_11AutoUnknown:*/
++ /*case ndis_80211_infra_auto_unknown:*/
+ default:
+ iwe.u.mode = IW_MODE_AUTO;
+ break;
+ }
+ cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN);
+
+- devdbg(usbdev, "FREQ %d kHz",
+- le32_to_cpu(bssid->Configuration.DSConfig));
++ devdbg(usbdev, "FREQ %d kHz", le32_to_cpu(bssid->config.ds_config));
+ iwe.cmd = SIOCGIWFREQ;
+- dsconfig_to_freq(le32_to_cpu(bssid->Configuration.DSConfig),
+- &iwe.u.freq);
++ dsconfig_to_freq(le32_to_cpu(bssid->config.ds_config), &iwe.u.freq);
+ cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN);
+
+- devdbg(usbdev, "QUAL %d", le32_to_cpu(bssid->Rssi));
++ devdbg(usbdev, "QUAL %d", le32_to_cpu(bssid->rssi));
+ iwe.cmd = IWEVQUAL;
+- iwe.u.qual.qual = level_to_qual(le32_to_cpu(bssid->Rssi));
+- iwe.u.qual.level = le32_to_cpu(bssid->Rssi);
++ iwe.u.qual.qual = level_to_qual(le32_to_cpu(bssid->rssi));
++ iwe.u.qual.level = le32_to_cpu(bssid->rssi);
+ iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED
+ | IW_QUAL_LEVEL_UPDATED
+ | IW_QUAL_NOISE_INVALID;
+ cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN);
+
+- devdbg(usbdev, "ENCODE %d", le32_to_cpu(bssid->Privacy));
++ devdbg(usbdev, "ENCODE %d", le32_to_cpu(bssid->privacy));
+ iwe.cmd = SIOCGIWENCODE;
+ iwe.u.data.length = 0;
+- if (le32_to_cpu(bssid->Privacy) == Ndis802_11PrivFilterAcceptAll)
++ if (le32_to_cpu(bssid->privacy) == ndis_80211_priv_accept_all)
+ iwe.u.data.flags = IW_ENCODE_DISABLED;
+ else
+ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+@@ -1687,10 +1674,10 @@ static char *rndis_translate_scan(struct net_device *dev,
+ devdbg(usbdev, "RATES:");
+ current_val = cev + IW_EV_LCP_LEN;
+ iwe.cmd = SIOCGIWRATE;
+- for (i = 0; i < sizeof(bssid->SupportedRates); i++) {
+- if (bssid->SupportedRates[i] & 0x7f) {
++ for (i = 0; i < sizeof(bssid->rates); i++) {
++ if (bssid->rates[i] & 0x7f) {
+ iwe.u.bitrate.value =
+- ((bssid->SupportedRates[i] & 0x7f) *
++ ((bssid->rates[i] & 0x7f) *
+ 500000);
+ devdbg(usbdev, " %d", iwe.u.bitrate.value);
+ current_val = iwe_stream_add_value(cev,
+@@ -1702,24 +1689,24 @@ static char *rndis_translate_scan(struct net_device *dev,
+ if ((current_val - cev) > IW_EV_LCP_LEN)
+ cev = current_val;
+
+- beacon = le32_to_cpu(bssid->Configuration.BeaconPeriod);
++ beacon = le32_to_cpu(bssid->config.beacon_period);
+ devdbg(usbdev, "BCN_INT %d", beacon);
+ iwe.cmd = IWEVCUSTOM;
+ snprintf(sbuf, sizeof(sbuf), "bcn_int=%d", beacon);
+ iwe.u.data.length = strlen(sbuf);
+ cev = iwe_stream_add_point(cev, end_buf, &iwe, sbuf);
+
+- atim = le32_to_cpu(bssid->Configuration.ATIMWindow);
++ atim = le32_to_cpu(bssid->config.atim_window);
+ devdbg(usbdev, "ATIM %d", atim);
+ iwe.cmd = IWEVCUSTOM;
+ snprintf(sbuf, sizeof(sbuf), "atim=%u", atim);
+ iwe.u.data.length = strlen(sbuf);
+ cev = iwe_stream_add_point(cev, end_buf, &iwe, sbuf);
+
+- ie = (void *)(bssid->IEs + sizeof(struct NDIS_802_11_FIXED_IEs));
++ ie = (void *)(bssid->ies + sizeof(struct ndis_80211_fixed_ies));
+ ie_len = min(bssid_len - (int)sizeof(*bssid),
+- (int)le32_to_cpu(bssid->IELength));
+- ie_len -= sizeof(struct NDIS_802_11_FIXED_IEs);
++ (int)le32_to_cpu(bssid->ie_length));
++ ie_len -= sizeof(struct ndis_80211_fixed_ies);
+ while (ie_len >= sizeof(*ie) && sizeof(*ie) + ie->len <= ie_len) {
+ if ((ie->id == MFIE_TYPE_GENERIC && ie->len >= 4 &&
+ memcmp(ie->data, "\x00\x50\xf2\x01", 4) == 0) ||
+@@ -1746,8 +1733,8 @@ static int rndis_iw_get_scan(struct net_device *dev,
+ struct usbnet *usbdev = dev->priv;
+ void *buf = NULL;
+ char *cev = extra;
+- struct NDIS_802_11_BSSID_LIST_EX *bssid_list;
+- struct NDIS_WLAN_BSSID_EX *bssid;
++ struct ndis_80211_bssid_list_ex *bssid_list;
++ struct ndis_80211_bssid_ex *bssid;
+ int ret = -EINVAL, len, count, bssid_len;
+
+ devdbg(usbdev, "SIOCGIWSCAN");
+@@ -1765,16 +1752,16 @@ static int rndis_iw_get_scan(struct net_device *dev,
+ goto out;
+
+ bssid_list = buf;
+- bssid = bssid_list->Bssid;
+- bssid_len = le32_to_cpu(bssid->Length);
+- count = le32_to_cpu(bssid_list->NumberOfItems);
++ bssid = bssid_list->bssid;
++ bssid_len = le32_to_cpu(bssid->length);
++ count = le32_to_cpu(bssid_list->num_items);
+ devdbg(usbdev, "SIOCGIWSCAN: %d BSSIDs found", count);
+
+ while (count && ((void *)bssid + bssid_len) <= (buf + len)) {
+ cev = rndis_translate_scan(dev, cev, extra + IW_SCAN_MAX_DATA,
+ bssid);
+ bssid = (void *)bssid + bssid_len;
+- bssid_len = le32_to_cpu(bssid->Length);
++ bssid_len = le32_to_cpu(bssid->length);
+ count--;
+ }
+
+@@ -1948,7 +1935,7 @@ static int rndis_iw_set_freq(struct net_device *dev,
+ struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+ {
+ struct usbnet *usbdev = dev->priv;
+- struct NDIS_802_11_CONFIGURATION config;
++ struct ndis_80211_conf config;
+ unsigned int dsconfig;
+ int len, ret;
+
+@@ -1967,7 +1954,7 @@ static int rndis_iw_set_freq(struct net_device *dev,
+ return 0;
+ }
+
+- config.DSConfig = cpu_to_le32(dsconfig);
++ config.ds_config = cpu_to_le32(dsconfig);
+
+ devdbg(usbdev, "SIOCSIWFREQ: %d * 10^%d", wrqu->freq.m, wrqu->freq.e);
+ return rndis_set_oid(usbdev, OID_802_11_CONFIGURATION, &config,
+@@ -1979,13 +1966,13 @@ static int rndis_iw_get_freq(struct net_device *dev,
+ struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
+ {
+ struct usbnet *usbdev = dev->priv;
+- struct NDIS_802_11_CONFIGURATION config;
++ struct ndis_80211_conf config;
+ int len, ret;
+
+ len = sizeof(config);
+ ret = rndis_query_oid(usbdev, OID_802_11_CONFIGURATION, &config, &len);
+ if (ret == 0)
+- dsconfig_to_freq(le32_to_cpu(config.DSConfig), &wrqu->freq);
++ dsconfig_to_freq(le32_to_cpu(config.ds_config), &wrqu->freq);
+
+ devdbg(usbdev, "SIOCGIWFREQ: %d", wrqu->freq.m);
+ return ret;
+@@ -2266,14 +2253,14 @@ static int rndis_wext_get_caps(struct usbnet *dev)
+ n = 8;
+ for (i = 0; i < n; i++) {
+ switch (le32_to_cpu(networks_supported.items[i])) {
+- case Ndis802_11FH:
+- case Ndis802_11DS:
++ case ndis_80211_type_freq_hop:
++ case ndis_80211_type_direct_seq:
+ priv->caps |= CAP_MODE_80211B;
+ break;
+- case Ndis802_11OFDM5:
++ case ndis_80211_type_ofdm_a:
+ priv->caps |= CAP_MODE_80211A;
+ break;
+- case Ndis802_11OFDM24:
++ case ndis_80211_type_ofdm_g:
+ priv->caps |= CAP_MODE_80211G;
+ break;
+ }
+@@ -2415,7 +2402,6 @@ static int bcm4320_early_init(struct usbnet *dev)
+ priv->param_power_output = modparam_power_output;
+ priv->param_roamtrigger = modparam_roamtrigger;
+ priv->param_roamdelta = modparam_roamdelta;
+- priv->param_workaround_interval = modparam_workaround_interval;
+
+ priv->param_country[0] = toupper(priv->param_country[0]);
+ priv->param_country[1] = toupper(priv->param_country[1]);
+@@ -2438,8 +2424,10 @@ static int bcm4320_early_init(struct usbnet *dev)
+ else if (priv->param_roamdelta > 2)
+ priv->param_roamdelta = 2;
+
+- if (priv->param_workaround_interval < 0)
++ if (modparam_workaround_interval < 0)
+ priv->param_workaround_interval = 500;
++ else
++ priv->param_workaround_interval = modparam_workaround_interval;
+
+ rndis_set_config_parameter_str(dev, "Country", priv->param_country);
+ rndis_set_config_parameter_str(dev, "FrameBursting",
+diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
+index da05b1f..ab1029e 100644
+--- a/drivers/net/wireless/rt2x00/Kconfig
++++ b/drivers/net/wireless/rt2x00/Kconfig
+@@ -5,30 +5,28 @@ config RT2X00
+ This will enable the experimental support for the Ralink drivers,
+ developed in the rt2x00 project <http://rt2x00.serialmonkey.com>.
+
+- These drivers will make use of the Devicescape ieee80211 stack.
++ These drivers will make use of the mac80211 stack.
+
+ When building one of the individual drivers, the rt2x00 library
+ will also be created. That library (when the driver is built as
+ a module) will be called "rt2x00lib.ko".
+
++if RT2X00
++
+ config RT2X00_LIB
+ tristate
+- depends on RT2X00
+
+ config RT2X00_LIB_PCI
+ tristate
+- depends on RT2X00
+ select RT2X00_LIB
+
+ config RT2X00_LIB_USB
+ tristate
+- depends on RT2X00
+ select RT2X00_LIB
+
+ config RT2X00_LIB_FIRMWARE
+ boolean
+ depends on RT2X00_LIB
+- select CRC_ITU_T
+ select FW_LOADER
+
+ config RT2X00_LIB_RFKILL
+@@ -37,9 +35,13 @@ config RT2X00_LIB_RFKILL
+ select RFKILL
+ select INPUT_POLLDEV
+
++config RT2X00_LIB_LEDS
++ boolean
++ depends on RT2X00_LIB
++
+ config RT2400PCI
+ tristate "Ralink rt2400 pci/pcmcia support"
+- depends on RT2X00 && PCI
++ depends on PCI
+ select RT2X00_LIB_PCI
+ select EEPROM_93CX6
+ ---help---
+@@ -56,9 +58,17 @@ config RT2400PCI_RFKILL
+ hardware button to control the radio state.
+ This feature depends on the RF switch subsystem rfkill.
+
++config RT2400PCI_LEDS
++ bool "RT2400 leds support"
++ depends on RT2400PCI
++ select LEDS_CLASS
++ select RT2X00_LIB_LEDS
++ ---help---
++ This adds support for led triggers provided my mac80211.
++
+ config RT2500PCI
+ tristate "Ralink rt2500 pci/pcmcia support"
+- depends on RT2X00 && PCI
++ depends on PCI
+ select RT2X00_LIB_PCI
+ select EEPROM_93CX6
+ ---help---
+@@ -75,11 +85,20 @@ config RT2500PCI_RFKILL
+ hardware button to control the radio state.
+ This feature depends on the RF switch subsystem rfkill.
+
++config RT2500PCI_LEDS
++ bool "RT2500 leds support"
++ depends on RT2500PCI
++ select LEDS_CLASS
++ select RT2X00_LIB_LEDS
++ ---help---
++ This adds support for led triggers provided my mac80211.
++
+ config RT61PCI
+ tristate "Ralink rt61 pci/pcmcia support"
+- depends on RT2X00 && PCI
++ depends on PCI
+ select RT2X00_LIB_PCI
+ select RT2X00_LIB_FIRMWARE
++ select CRC_ITU_T
+ select EEPROM_93CX6
+ ---help---
+ This is an experimental driver for the Ralink rt61 wireless chip.
+@@ -95,25 +114,50 @@ config RT61PCI_RFKILL
+ hardware button to control the radio state.
+ This feature depends on the RF switch subsystem rfkill.
+
++config RT61PCI_LEDS
++ bool "RT61 leds support"
++ depends on RT61PCI
++ select LEDS_CLASS
++ select RT2X00_LIB_LEDS
++ ---help---
++ This adds support for led triggers provided my mac80211.
++
+ config RT2500USB
+ tristate "Ralink rt2500 usb support"
+- depends on RT2X00 && USB
++ depends on USB
+ select RT2X00_LIB_USB
+ ---help---
+ This is an experimental driver for the Ralink rt2500 wireless chip.
+
+ When compiled as a module, this driver will be called "rt2500usb.ko".
+
++config RT2500USB_LEDS
++ bool "RT2500 leds support"
++ depends on RT2500USB
++ select LEDS_CLASS
++ select RT2X00_LIB_LEDS
++ ---help---
++ This adds support for led triggers provided my mac80211.
++
+ config RT73USB
+ tristate "Ralink rt73 usb support"
+- depends on RT2X00 && USB
++ depends on USB
+ select RT2X00_LIB_USB
+ select RT2X00_LIB_FIRMWARE
++ select CRC_ITU_T
+ ---help---
+ This is an experimental driver for the Ralink rt73 wireless chip.
+
+ When compiled as a module, this driver will be called "rt73usb.ko".
+
++config RT73USB_LEDS
++ bool "RT73 leds support"
++ depends on RT73USB
++ select LEDS_CLASS
++ select RT2X00_LIB_LEDS
++ ---help---
++ This adds support for led triggers provided my mac80211.
++
+ config RT2X00_LIB_DEBUGFS
+ bool "Ralink debugfs support"
+ depends on RT2X00_LIB && MAC80211_DEBUGFS
+@@ -128,3 +172,4 @@ config RT2X00_DEBUG
+ ---help---
+ Enable debugging output for all rt2x00 modules
+
++endif
+diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile
+index 30d654a..1087dbc 100644
+--- a/drivers/net/wireless/rt2x00/Makefile
++++ b/drivers/net/wireless/rt2x00/Makefile
+@@ -1,22 +1,17 @@
+-rt2x00lib-objs := rt2x00dev.o rt2x00mac.o rt2x00config.o
++rt2x00lib-y += rt2x00dev.o
++rt2x00lib-y += rt2x00mac.o
++rt2x00lib-y += rt2x00config.o
++rt2x00lib-y += rt2x00queue.o
++rt2x00lib-$(CONFIG_RT2X00_LIB_DEBUGFS) += rt2x00debug.o
++rt2x00lib-$(CONFIG_RT2X00_LIB_RFKILL) += rt2x00rfkill.o
++rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o
++rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS) += rt2x00leds.o
+
+-ifeq ($(CONFIG_RT2X00_LIB_DEBUGFS),y)
+- rt2x00lib-objs += rt2x00debug.o
+-endif
+-
+-ifeq ($(CONFIG_RT2X00_LIB_RFKILL),y)
+- rt2x00lib-objs += rt2x00rfkill.o
+-endif
+-
+-ifeq ($(CONFIG_RT2X00_LIB_FIRMWARE),y)
+- rt2x00lib-objs += rt2x00firmware.o
+-endif
+-
+-obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o
+-obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o
+-obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o
+-obj-$(CONFIG_RT2400PCI) += rt2400pci.o
+-obj-$(CONFIG_RT2500PCI) += rt2500pci.o
+-obj-$(CONFIG_RT61PCI) += rt61pci.o
+-obj-$(CONFIG_RT2500USB) += rt2500usb.o
+-obj-$(CONFIG_RT73USB) += rt73usb.o
++obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o
++obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o
++obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o
++obj-$(CONFIG_RT2400PCI) += rt2400pci.o
++obj-$(CONFIG_RT2500PCI) += rt2500pci.o
++obj-$(CONFIG_RT61PCI) += rt61pci.o
++obj-$(CONFIG_RT2500USB) += rt2500usb.o
++obj-$(CONFIG_RT73USB) += rt73usb.o
+diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
+index c69f85e..b41187a 100644
+--- a/drivers/net/wireless/rt2x00/rt2400pci.c
++++ b/drivers/net/wireless/rt2x00/rt2400pci.c
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+@@ -243,53 +243,109 @@ static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
+ #define rt2400pci_rfkill_poll NULL
+ #endif /* CONFIG_RT2400PCI_RFKILL */
+
+-/*
+- * Configuration handlers.
+- */
+-static void rt2400pci_config_mac_addr(struct rt2x00_dev *rt2x00dev,
+- __le32 *mac)
++#ifdef CONFIG_RT2400PCI_LEDS
++static void rt2400pci_brightness_set(struct led_classdev *led_cdev,
++ enum led_brightness brightness)
+ {
+- rt2x00pci_register_multiwrite(rt2x00dev, CSR3, mac,
+- (2 * sizeof(__le32)));
++ struct rt2x00_led *led =
++ container_of(led_cdev, struct rt2x00_led, led_dev);
++ unsigned int enabled = brightness != LED_OFF;
++ u32 reg;
++
++ rt2x00pci_register_read(led->rt2x00dev, LEDCSR, ®);
++
++ if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
++ rt2x00_set_field32(®, LEDCSR_LINK, enabled);
++ else if (led->type == LED_TYPE_ACTIVITY)
++ rt2x00_set_field32(®, LEDCSR_ACTIVITY, enabled);
++
++ rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
+ }
+
+-static void rt2400pci_config_bssid(struct rt2x00_dev *rt2x00dev,
+- __le32 *bssid)
++static int rt2400pci_blink_set(struct led_classdev *led_cdev,
++ unsigned long *delay_on,
++ unsigned long *delay_off)
+ {
+- rt2x00pci_register_multiwrite(rt2x00dev, CSR5, bssid,
+- (2 * sizeof(__le32)));
++ struct rt2x00_led *led =
++ container_of(led_cdev, struct rt2x00_led, led_dev);
++ u32 reg;
++
++ rt2x00pci_register_read(led->rt2x00dev, LEDCSR, ®);
++ rt2x00_set_field32(®, LEDCSR_ON_PERIOD, *delay_on);
++ rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, *delay_off);
++ rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
++
++ return 0;
+ }
++#endif /* CONFIG_RT2400PCI_LEDS */
+
+-static void rt2400pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,
+- const int tsf_sync)
++/*
++ * Configuration handlers.
++ */
++static void rt2400pci_config_filter(struct rt2x00_dev *rt2x00dev,
++ const unsigned int filter_flags)
+ {
+ u32 reg;
+
+- rt2x00pci_register_write(rt2x00dev, CSR14, 0);
+-
+ /*
+- * Enable beacon config
++ * Start configuration steps.
++ * Note that the version error will always be dropped
++ * since there is no filter for it at this time.
+ */
+- rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®);
+- rt2x00_set_field32(®, BCNCSR1_PRELOAD,
+- PREAMBLE + get_duration(IEEE80211_HEADER, 20));
+- rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg);
++ rt2x00pci_register_read(rt2x00dev, RXCSR0, ®);
++ rt2x00_set_field32(®, RXCSR0_DROP_CRC,
++ !(filter_flags & FIF_FCSFAIL));
++ rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL,
++ !(filter_flags & FIF_PLCPFAIL));
++ rt2x00_set_field32(®, RXCSR0_DROP_CONTROL,
++ !(filter_flags & FIF_CONTROL));
++ rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME,
++ !(filter_flags & FIF_PROMISC_IN_BSS));
++ rt2x00_set_field32(®, RXCSR0_DROP_TODS,
++ !(filter_flags & FIF_PROMISC_IN_BSS) &&
++ !rt2x00dev->intf_ap_count);
++ rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1);
++ rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
++}
+
+- /*
+- * Enable synchronisation.
+- */
+- rt2x00pci_register_read(rt2x00dev, CSR14, ®);
+- rt2x00_set_field32(®, CSR14_TSF_COUNT, 1);
+- rt2x00_set_field32(®, CSR14_TBCN, (tsf_sync == TSF_SYNC_BEACON));
+- rt2x00_set_field32(®, CSR14_BEACON_GEN, 0);
+- rt2x00_set_field32(®, CSR14_TSF_SYNC, tsf_sync);
+- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
++static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev,
++ struct rt2x00_intf *intf,
++ struct rt2x00intf_conf *conf,
++ const unsigned int flags)
++{
++ unsigned int bcn_preload;
++ u32 reg;
++
++ if (flags & CONFIG_UPDATE_TYPE) {
++ /*
++ * Enable beacon config
++ */
++ bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20);
++ rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®);
++ rt2x00_set_field32(®, BCNCSR1_PRELOAD, bcn_preload);
++ rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg);
++
++ /*
++ * Enable synchronisation.
++ */
++ rt2x00pci_register_read(rt2x00dev, CSR14, ®);
++ rt2x00_set_field32(®, CSR14_TSF_COUNT, 1);
++ rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync);
++ rt2x00_set_field32(®, CSR14_TBCN, 1);
++ rt2x00pci_register_write(rt2x00dev, CSR14, reg);
++ }
++
++ if (flags & CONFIG_UPDATE_MAC)
++ rt2x00pci_register_multiwrite(rt2x00dev, CSR3,
++ conf->mac, sizeof(conf->mac));
++
++ if (flags & CONFIG_UPDATE_BSSID)
++ rt2x00pci_register_multiwrite(rt2x00dev, CSR5,
++ conf->bssid, sizeof(conf->bssid));
+ }
+
+-static void rt2400pci_config_preamble(struct rt2x00_dev *rt2x00dev,
+- const int short_preamble,
+- const int ack_timeout,
+- const int ack_consume_time)
++static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
++ struct rt2x00lib_erp *erp)
+ {
+ int preamble_mask;
+ u32 reg;
+@@ -297,11 +353,13 @@ static void rt2400pci_config_preamble(struct rt2x00_dev *rt2x00dev,
+ /*
+ * When short preamble is enabled, we should set bit 0x08
+ */
+- preamble_mask = short_preamble << 3;
++ preamble_mask = erp->short_preamble << 3;
+
+ rt2x00pci_register_read(rt2x00dev, TXCSR1, ®);
+- rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, ack_timeout);
+- rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, ack_consume_time);
++ rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT,
++ erp->ack_timeout);
++ rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME,
++ erp->ack_consume_time);
+ rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
+
+ rt2x00pci_register_read(rt2x00dev, ARCSR2, ®);
+@@ -397,6 +455,13 @@ static void rt2400pci_config_antenna(struct rt2x00_dev *rt2x00dev,
+ u8 r1;
+ u8 r4;
+
++ /*
++ * We should never come here because rt2x00lib is supposed
++ * to catch this and send us the correct antenna explicitely.
++ */
++ BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
++ ant->tx == ANTENNA_SW_DIVERSITY);
++
+ rt2400pci_bbp_read(rt2x00dev, 4, &r4);
+ rt2400pci_bbp_read(rt2x00dev, 1, &r1);
+
+@@ -410,14 +475,8 @@ static void rt2400pci_config_antenna(struct rt2x00_dev *rt2x00dev,
+ case ANTENNA_A:
+ rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 0);
+ break;
+- case ANTENNA_SW_DIVERSITY:
+- /*
+- * NOTE: We should never come here because rt2x00lib is
+- * supposed to catch this and send us the correct antenna
+- * explicitely. However we are nog going to bug about this.
+- * Instead, just default to antenna B.
+- */
+ case ANTENNA_B:
++ default:
+ rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 2);
+ break;
+ }
+@@ -432,14 +491,8 @@ static void rt2400pci_config_antenna(struct rt2x00_dev *rt2x00dev,
+ case ANTENNA_A:
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 0);
+ break;
+- case ANTENNA_SW_DIVERSITY:
+- /*
+- * NOTE: We should never come here because rt2x00lib is
+- * supposed to catch this and send us the correct antenna
+- * explicitely. However we are nog going to bug about this.
+- * Instead, just default to antenna B.
+- */
+ case ANTENNA_B:
++ default:
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
+ break;
+ }
+@@ -481,8 +534,8 @@ static void rt2400pci_config_duration(struct rt2x00_dev *rt2x00dev,
+ }
+
+ static void rt2400pci_config(struct rt2x00_dev *rt2x00dev,
+- const unsigned int flags,
+- struct rt2x00lib_conf *libconf)
++ struct rt2x00lib_conf *libconf,
++ const unsigned int flags)
+ {
+ if (flags & CONFIG_UPDATE_PHYMODE)
+ rt2400pci_config_phymode(rt2x00dev, libconf->basic_rates);
+@@ -498,45 +551,17 @@ static void rt2400pci_config(struct rt2x00_dev *rt2x00dev,
+ }
+
+ static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev,
+- struct ieee80211_tx_queue_params *params)
++ const int cw_min, const int cw_max)
+ {
+ u32 reg;
+
+ rt2x00pci_register_read(rt2x00dev, CSR11, ®);
+- rt2x00_set_field32(®, CSR11_CWMIN, params->cw_min);
+- rt2x00_set_field32(®, CSR11_CWMAX, params->cw_max);
++ rt2x00_set_field32(®, CSR11_CWMIN, cw_min);
++ rt2x00_set_field32(®, CSR11_CWMAX, cw_max);
+ rt2x00pci_register_write(rt2x00dev, CSR11, reg);
+ }
+
+ /*
+- * LED functions.
+- */
+-static void rt2400pci_enable_led(struct rt2x00_dev *rt2x00dev)
+-{
+- u32 reg;
+-
+- rt2x00pci_register_read(rt2x00dev, LEDCSR, ®);
+-
+- rt2x00_set_field32(®, LEDCSR_ON_PERIOD, 70);
+- rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, 30);
+- rt2x00_set_field32(®, LEDCSR_LINK,
+- (rt2x00dev->led_mode != LED_MODE_ASUS));
+- rt2x00_set_field32(®, LEDCSR_ACTIVITY,
+- (rt2x00dev->led_mode != LED_MODE_TXRX_ACTIVITY));
+- rt2x00pci_register_write(rt2x00dev, LEDCSR, reg);
+-}
+-
+-static void rt2400pci_disable_led(struct rt2x00_dev *rt2x00dev)
+-{
+- u32 reg;
+-
+- rt2x00pci_register_read(rt2x00dev, LEDCSR, ®);
+- rt2x00_set_field32(®, LEDCSR_LINK, 0);
+- rt2x00_set_field32(®, LEDCSR_ACTIVITY, 0);
+- rt2x00pci_register_write(rt2x00dev, LEDCSR, reg);
+-}
+-
+-/*
+ * Link tuning
+ */
+ static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev,
+@@ -593,90 +618,94 @@ static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev)
+ * Initialization functions.
+ */
+ static void rt2400pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
+- struct data_entry *entry)
++ struct queue_entry *entry)
+ {
+- __le32 *rxd = entry->priv;
++ struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
+ u32 word;
+
+- rt2x00_desc_read(rxd, 2, &word);
+- rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->ring->data_size);
+- rt2x00_desc_write(rxd, 2, word);
++ rt2x00_desc_read(priv_rx->desc, 2, &word);
++ rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH,
++ entry->queue->data_size);
++ rt2x00_desc_write(priv_rx->desc, 2, word);
+
+- rt2x00_desc_read(rxd, 1, &word);
+- rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, entry->data_dma);
+- rt2x00_desc_write(rxd, 1, word);
++ rt2x00_desc_read(priv_rx->desc, 1, &word);
++ rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, priv_rx->data_dma);
++ rt2x00_desc_write(priv_rx->desc, 1, word);
+
+- rt2x00_desc_read(rxd, 0, &word);
++ rt2x00_desc_read(priv_rx->desc, 0, &word);
+ rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
+- rt2x00_desc_write(rxd, 0, word);
++ rt2x00_desc_write(priv_rx->desc, 0, word);
+ }
+
+ static void rt2400pci_init_txentry(struct rt2x00_dev *rt2x00dev,
+- struct data_entry *entry)
++ struct queue_entry *entry)
+ {
+- __le32 *txd = entry->priv;
++ struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
+ u32 word;
+
+- rt2x00_desc_read(txd, 1, &word);
+- rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, entry->data_dma);
+- rt2x00_desc_write(txd, 1, word);
++ rt2x00_desc_read(priv_tx->desc, 1, &word);
++ rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, priv_tx->data_dma);
++ rt2x00_desc_write(priv_tx->desc, 1, word);
+
+- rt2x00_desc_read(txd, 2, &word);
+- rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, entry->ring->data_size);
+- rt2x00_desc_write(txd, 2, word);
++ rt2x00_desc_read(priv_tx->desc, 2, &word);
++ rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH,
++ entry->queue->data_size);
++ rt2x00_desc_write(priv_tx->desc, 2, word);
+
+- rt2x00_desc_read(txd, 0, &word);
++ rt2x00_desc_read(priv_tx->desc, 0, &word);
+ rt2x00_set_field32(&word, TXD_W0_VALID, 0);
+ rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
+- rt2x00_desc_write(txd, 0, word);
++ rt2x00_desc_write(priv_tx->desc, 0, word);
+ }
+
+-static int rt2400pci_init_rings(struct rt2x00_dev *rt2x00dev)
++static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev)
+ {
++ struct queue_entry_priv_pci_rx *priv_rx;
++ struct queue_entry_priv_pci_tx *priv_tx;
+ u32 reg;
+
+ /*
+ * Initialize registers.
+ */
+ rt2x00pci_register_read(rt2x00dev, TXCSR2, ®);
+- rt2x00_set_field32(®, TXCSR2_TXD_SIZE,
+- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size);
+- rt2x00_set_field32(®, TXCSR2_NUM_TXD,
+- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit);
+- rt2x00_set_field32(®, TXCSR2_NUM_ATIM,
+- rt2x00dev->bcn[1].stats.limit);
+- rt2x00_set_field32(®, TXCSR2_NUM_PRIO,
+- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit);
++ rt2x00_set_field32(®, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
++ rt2x00_set_field32(®, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
++ rt2x00_set_field32(®, TXCSR2_NUM_ATIM, rt2x00dev->bcn[1].limit);
++ rt2x00_set_field32(®, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit);
+ rt2x00pci_register_write(rt2x00dev, TXCSR2, reg);
+
++ priv_tx = rt2x00dev->tx[1].entries[0].priv_data;
+ rt2x00pci_register_read(rt2x00dev, TXCSR3, ®);
+ rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER,
+- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma);
++ priv_tx->desc_dma);
+ rt2x00pci_register_write(rt2x00dev, TXCSR3, reg);
+
++ priv_tx = rt2x00dev->tx[0].entries[0].priv_data;
+ rt2x00pci_register_read(rt2x00dev, TXCSR5, ®);
+ rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER,
+- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma);
++ priv_tx->desc_dma);
+ rt2x00pci_register_write(rt2x00dev, TXCSR5, reg);
+
++ priv_tx = rt2x00dev->bcn[1].entries[0].priv_data;
+ rt2x00pci_register_read(rt2x00dev, TXCSR4, ®);
+ rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER,
+- rt2x00dev->bcn[1].data_dma);
++ priv_tx->desc_dma);
+ rt2x00pci_register_write(rt2x00dev, TXCSR4, reg);
+
++ priv_tx = rt2x00dev->bcn[0].entries[0].priv_data;
+ rt2x00pci_register_read(rt2x00dev, TXCSR6, ®);
+ rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER,
+- rt2x00dev->bcn[0].data_dma);
++ priv_tx->desc_dma);
+ rt2x00pci_register_write(rt2x00dev, TXCSR6, reg);
+
+ rt2x00pci_register_read(rt2x00dev, RXCSR1, ®);
+ rt2x00_set_field32(®, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);
+- rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->stats.limit);
++ rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->limit);
+ rt2x00pci_register_write(rt2x00dev, RXCSR1, reg);
+
++ priv_rx = rt2x00dev->rx->entries[0].priv_data;
+ rt2x00pci_register_read(rt2x00dev, RXCSR2, ®);
+- rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER,
+- rt2x00dev->rx->data_dma);
++ rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, priv_rx->desc_dma);
+ rt2x00pci_register_write(rt2x00dev, RXCSR2, reg);
+
+ return 0;
+@@ -795,19 +824,15 @@ continue_csr_init:
+ rt2400pci_bbp_write(rt2x00dev, 30, 0x21);
+ rt2400pci_bbp_write(rt2x00dev, 31, 0x00);
+
+- DEBUG(rt2x00dev, "Start initialization from EEPROM...\n");
+ for (i = 0; i < EEPROM_BBP_SIZE; i++) {
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+
+ if (eeprom != 0xffff && eeprom != 0x0000) {
+ reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
+ value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
+- DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n",
+- reg_id, value);
+ rt2400pci_bbp_write(rt2x00dev, reg_id, value);
+ }
+ }
+- DEBUG(rt2x00dev, "...End initialization from EEPROM.\n");
+
+ return 0;
+ }
+@@ -859,7 +884,7 @@ static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev)
+ /*
+ * Initialize all registers.
+ */
+- if (rt2400pci_init_rings(rt2x00dev) ||
++ if (rt2400pci_init_queues(rt2x00dev) ||
+ rt2400pci_init_registers(rt2x00dev) ||
+ rt2400pci_init_bbp(rt2x00dev)) {
+ ERROR(rt2x00dev, "Register initialization failed.\n");
+@@ -871,11 +896,6 @@ static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev)
+ */
+ rt2400pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_ON);
+
+- /*
+- * Enable LED
+- */
+- rt2400pci_enable_led(rt2x00dev);
+-
+ return 0;
+ }
+
+@@ -883,11 +903,6 @@ static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev)
+ {
+ u32 reg;
+
+- /*
+- * Disable LED
+- */
+- rt2400pci_disable_led(rt2x00dev);
+-
+ rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0);
+
+ /*
+@@ -986,10 +1001,10 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev,
+ */
+ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ struct sk_buff *skb,
+- struct txdata_entry_desc *desc,
++ struct txentry_desc *txdesc,
+ struct ieee80211_tx_control *control)
+ {
+- struct skb_desc *skbdesc = get_skb_desc(skb);
++ struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+ __le32 *txd = skbdesc->desc;
+ u32 word;
+
+@@ -1001,19 +1016,19 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ rt2x00_desc_write(txd, 2, word);
+
+ rt2x00_desc_read(txd, 3, &word);
+- rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, desc->signal);
++ rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->signal);
+ rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_REGNUM, 5);
+ rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_BUSY, 1);
+- rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, desc->service);
++ rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->service);
+ rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_REGNUM, 6);
+ rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_BUSY, 1);
+ rt2x00_desc_write(txd, 3, word);
+
+ rt2x00_desc_read(txd, 4, &word);
+- rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW, desc->length_low);
++ rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW, txdesc->length_low);
+ rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_REGNUM, 8);
+ rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_BUSY, 1);
+- rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH, desc->length_high);
++ rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH, txdesc->length_high);
+ rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_REGNUM, 7);
+ rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_BUSY, 1);
+ rt2x00_desc_write(txd, 4, word);
+@@ -1022,14 +1037,14 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
+ rt2x00_set_field32(&word, TXD_W0_VALID, 1);
+ rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
+- test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
++ test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_ACK,
+- test_bit(ENTRY_TXD_ACK, &desc->flags));
++ test_bit(ENTRY_TXD_ACK, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
+- test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
++ test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_RTS,
+- test_bit(ENTRY_TXD_RTS_FRAME, &desc->flags));
+- rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
++ test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags));
++ rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
+ rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
+ !!(control->flags &
+ IEEE80211_TXCTL_LONG_RETRY_LIMIT));
+@@ -1040,13 +1055,15 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ * TX data initialization
+ */
+ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
+- unsigned int queue)
++ const unsigned int queue)
+ {
+ u32 reg;
+
+- if (queue == IEEE80211_TX_QUEUE_BEACON) {
++ if (queue == RT2X00_BCN_QUEUE_BEACON) {
+ rt2x00pci_register_read(rt2x00dev, CSR14, ®);
+ if (!rt2x00_get_field32(reg, CSR14_BEACON_GEN)) {
++ rt2x00_set_field32(®, CSR14_TSF_COUNT, 1);
++ rt2x00_set_field32(®, CSR14_TBCN, 1);
+ rt2x00_set_field32(®, CSR14_BEACON_GEN, 1);
+ rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ }
+@@ -1059,56 +1076,62 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
+ rt2x00_set_field32(®, TXCSR0_KICK_TX,
+ (queue == IEEE80211_TX_QUEUE_DATA1));
+ rt2x00_set_field32(®, TXCSR0_KICK_ATIM,
+- (queue == IEEE80211_TX_QUEUE_AFTER_BEACON));
++ (queue == RT2X00_BCN_QUEUE_ATIM));
+ rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+ }
+
+ /*
+ * RX control handlers
+ */
+-static void rt2400pci_fill_rxdone(struct data_entry *entry,
+- struct rxdata_entry_desc *desc)
++static void rt2400pci_fill_rxdone(struct queue_entry *entry,
++ struct rxdone_entry_desc *rxdesc)
+ {
+- __le32 *rxd = entry->priv;
++ struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
+ u32 word0;
+ u32 word2;
++ u32 word3;
+
+- rt2x00_desc_read(rxd, 0, &word0);
+- rt2x00_desc_read(rxd, 2, &word2);
++ rt2x00_desc_read(priv_rx->desc, 0, &word0);
++ rt2x00_desc_read(priv_rx->desc, 2, &word2);
++ rt2x00_desc_read(priv_rx->desc, 3, &word3);
+
+- desc->flags = 0;
++ rxdesc->flags = 0;
+ if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
+- desc->flags |= RX_FLAG_FAILED_FCS_CRC;
++ rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
+ if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
+- desc->flags |= RX_FLAG_FAILED_PLCP_CRC;
++ rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC;
+
+ /*
+ * Obtain the status about this packet.
++ * The signal is the PLCP value, and needs to be stripped
++ * of the preamble bit (0x08).
+ */
+- desc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);
+- desc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) -
+- entry->ring->rt2x00dev->rssi_offset;
+- desc->ofdm = 0;
+- desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+- desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
++ rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL) & ~0x08;
++ rxdesc->rssi = rt2x00_get_field32(word2, RXD_W3_RSSI) -
++ entry->queue->rt2x00dev->rssi_offset;
++ rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
++
++ rxdesc->dev_flags = RXDONE_SIGNAL_PLCP;
++ if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
++ rxdesc->dev_flags |= RXDONE_MY_BSS;
+ }
+
+ /*
+ * Interrupt functions.
+ */
+-static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue)
++static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
++ const enum ieee80211_tx_queue queue_idx)
+ {
+- struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue);
+- struct data_entry *entry;
+- __le32 *txd;
++ struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
++ struct queue_entry_priv_pci_tx *priv_tx;
++ struct queue_entry *entry;
++ struct txdone_entry_desc txdesc;
+ u32 word;
+- int tx_status;
+- int retry;
+
+- while (!rt2x00_ring_empty(ring)) {
+- entry = rt2x00_get_data_entry_done(ring);
+- txd = entry->priv;
+- rt2x00_desc_read(txd, 0, &word);
++ while (!rt2x00queue_empty(queue)) {
++ entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
++ priv_tx = entry->priv_data;
++ rt2x00_desc_read(priv_tx->desc, 0, &word);
+
+ if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
+ !rt2x00_get_field32(word, TXD_W0_VALID))
+@@ -1117,10 +1140,10 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue)
+ /*
+ * Obtain the status about this packet.
+ */
+- tx_status = rt2x00_get_field32(word, TXD_W0_RESULT);
+- retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
++ txdesc.status = rt2x00_get_field32(word, TXD_W0_RESULT);
++ txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
+
+- rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry);
++ rt2x00pci_txdone(rt2x00dev, entry, &txdesc);
+ }
+ }
+
+@@ -1164,7 +1187,7 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
+ * 3 - Atim ring transmit done interrupt.
+ */
+ if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING))
+- rt2400pci_txdone(rt2x00dev, IEEE80211_TX_QUEUE_AFTER_BEACON);
++ rt2400pci_txdone(rt2x00dev, RT2X00_BCN_QUEUE_ATIM);
+
+ /*
+ * 4 - Priority ring transmit done interrupt.
+@@ -1272,8 +1295,27 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
+ /*
+ * Store led mode, for correct led behaviour.
+ */
+- rt2x00dev->led_mode =
+- rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
++#ifdef CONFIG_RT2400PCI_LEDS
++ value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
++
++ rt2x00dev->led_radio.rt2x00dev = rt2x00dev;
++ rt2x00dev->led_radio.type = LED_TYPE_RADIO;
++ rt2x00dev->led_radio.led_dev.brightness_set =
++ rt2400pci_brightness_set;
++ rt2x00dev->led_radio.led_dev.blink_set =
++ rt2400pci_blink_set;
++ rt2x00dev->led_radio.flags = LED_INITIALIZED;
++
++ if (value == LED_MODE_TXRX_ACTIVITY) {
++ rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
++ rt2x00dev->led_radio.type = LED_TYPE_ACTIVITY;
++ rt2x00dev->led_qual.led_dev.brightness_set =
++ rt2400pci_brightness_set;
++ rt2x00dev->led_qual.led_dev.blink_set =
++ rt2400pci_blink_set;
++ rt2x00dev->led_qual.flags = LED_INITIALIZED;
++ }
++#endif /* CONFIG_RT2400PCI_LEDS */
+
+ /*
+ * Detect if this device has an hardware controlled radio.
+@@ -1343,8 +1385,8 @@ static void rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+ /*
+ * Initialize hw_mode information.
+ */
+- spec->num_modes = 1;
+- spec->num_rates = 4;
++ spec->supported_bands = SUPPORT_BAND_2GHZ;
++ spec->supported_rates = SUPPORT_RATE_CCK;
+ spec->tx_power_a = NULL;
+ spec->tx_power_bg = txpower;
+ spec->tx_power_default = DEFAULT_TXPOWER;
+@@ -1374,9 +1416,9 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
+ rt2400pci_probe_hw_mode(rt2x00dev);
+
+ /*
+- * This device requires the beacon ring
++ * This device requires the atim queue
+ */
+- __set_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags);
++ __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
+
+ /*
+ * Set the rssi offset.
+@@ -1389,64 +1431,6 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
+ /*
+ * IEEE80211 stack callback functions.
+ */
+-static void rt2400pci_configure_filter(struct ieee80211_hw *hw,
+- unsigned int changed_flags,
+- unsigned int *total_flags,
+- int mc_count,
+- struct dev_addr_list *mc_list)
+-{
+- struct rt2x00_dev *rt2x00dev = hw->priv;
+- u32 reg;
+-
+- /*
+- * Mask off any flags we are going to ignore from
+- * the total_flags field.
+- */
+- *total_flags &=
+- FIF_ALLMULTI |
+- FIF_FCSFAIL |
+- FIF_PLCPFAIL |
+- FIF_CONTROL |
+- FIF_OTHER_BSS |
+- FIF_PROMISC_IN_BSS;
+-
+- /*
+- * Apply some rules to the filters:
+- * - Some filters imply different filters to be set.
+- * - Some things we can't filter out at all.
+- */
+- *total_flags |= FIF_ALLMULTI;
+- if (*total_flags & FIF_OTHER_BSS ||
+- *total_flags & FIF_PROMISC_IN_BSS)
+- *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
+-
+- /*
+- * Check if there is any work left for us.
+- */
+- if (rt2x00dev->packet_filter == *total_flags)
+- return;
+- rt2x00dev->packet_filter = *total_flags;
+-
+- /*
+- * Start configuration steps.
+- * Note that the version error will always be dropped
+- * since there is no filter for it at this time.
+- */
+- rt2x00pci_register_read(rt2x00dev, RXCSR0, ®);
+- rt2x00_set_field32(®, RXCSR0_DROP_CRC,
+- !(*total_flags & FIF_FCSFAIL));
+- rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL,
+- !(*total_flags & FIF_PLCPFAIL));
+- rt2x00_set_field32(®, RXCSR0_DROP_CONTROL,
+- !(*total_flags & FIF_CONTROL));
+- rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME,
+- !(*total_flags & FIF_PROMISC_IN_BSS));
+- rt2x00_set_field32(®, RXCSR0_DROP_TODS,
+- !(*total_flags & FIF_PROMISC_IN_BSS));
+- rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1);
+- rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
+-}
+-
+ static int rt2400pci_set_retry_limit(struct ieee80211_hw *hw,
+ u32 short_retry, u32 long_retry)
+ {
+@@ -1481,7 +1465,8 @@ static int rt2400pci_conf_tx(struct ieee80211_hw *hw,
+ /*
+ * Write configuration to register.
+ */
+- rt2400pci_config_cw(rt2x00dev, &rt2x00dev->tx->tx_params);
++ rt2400pci_config_cw(rt2x00dev,
++ rt2x00dev->tx->cw_min, rt2x00dev->tx->cw_max);
+
+ return 0;
+ }
+@@ -1500,12 +1485,58 @@ static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw)
+ return tsf;
+ }
+
+-static void rt2400pci_reset_tsf(struct ieee80211_hw *hw)
++static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
++ struct ieee80211_tx_control *control)
+ {
+ struct rt2x00_dev *rt2x00dev = hw->priv;
++ struct rt2x00_intf *intf = vif_to_intf(control->vif);
++ struct queue_entry_priv_pci_tx *priv_tx;
++ struct skb_frame_desc *skbdesc;
++ u32 reg;
++
++ if (unlikely(!intf->beacon))
++ return -ENOBUFS;
++ priv_tx = intf->beacon->priv_data;
+
+- rt2x00pci_register_write(rt2x00dev, CSR16, 0);
+- rt2x00pci_register_write(rt2x00dev, CSR17, 0);
++ /*
++ * Fill in skb descriptor
++ */
++ skbdesc = get_skb_frame_desc(skb);
++ memset(skbdesc, 0, sizeof(*skbdesc));
++ skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
++ skbdesc->data = skb->data;
++ skbdesc->data_len = skb->len;
++ skbdesc->desc = priv_tx->desc;
++ skbdesc->desc_len = intf->beacon->queue->desc_size;
++ skbdesc->entry = intf->beacon;
++
++ /*
++ * Disable beaconing while we are reloading the beacon data,
++ * otherwise we might be sending out invalid data.
++ */
++ rt2x00pci_register_read(rt2x00dev, CSR14, ®);
++ rt2x00_set_field32(®, CSR14_TSF_COUNT, 0);
++ rt2x00_set_field32(®, CSR14_TBCN, 0);
++ rt2x00_set_field32(®, CSR14_BEACON_GEN, 0);
++ rt2x00pci_register_write(rt2x00dev, CSR14, reg);
++
++ /*
++ * mac80211 doesn't provide the control->queue variable
++ * for beacons. Set our own queue identification so
++ * it can be used during descriptor initialization.
++ */
++ control->queue = RT2X00_BCN_QUEUE_BEACON;
++ rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
++
++ /*
++ * Enable beacon generation.
++ * Write entire beacon with descriptor to register,
++ * and kick the beacon generator.
++ */
++ memcpy(priv_tx->data, skb->data, skb->len);
++ rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue);
++
++ return 0;
+ }
+
+ static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw)
+@@ -1525,15 +1556,14 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
+ .remove_interface = rt2x00mac_remove_interface,
+ .config = rt2x00mac_config,
+ .config_interface = rt2x00mac_config_interface,
+- .configure_filter = rt2400pci_configure_filter,
++ .configure_filter = rt2x00mac_configure_filter,
+ .get_stats = rt2x00mac_get_stats,
+ .set_retry_limit = rt2400pci_set_retry_limit,
+ .bss_info_changed = rt2x00mac_bss_info_changed,
+ .conf_tx = rt2400pci_conf_tx,
+ .get_tx_stats = rt2x00mac_get_tx_stats,
+ .get_tsf = rt2400pci_get_tsf,
+- .reset_tsf = rt2400pci_reset_tsf,
+- .beacon_update = rt2x00pci_beacon_update,
++ .beacon_update = rt2400pci_beacon_update,
+ .tx_last_beacon = rt2400pci_tx_last_beacon,
+ };
+
+@@ -1553,19 +1583,50 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
+ .write_tx_data = rt2x00pci_write_tx_data,
+ .kick_tx_queue = rt2400pci_kick_tx_queue,
+ .fill_rxdone = rt2400pci_fill_rxdone,
+- .config_mac_addr = rt2400pci_config_mac_addr,
+- .config_bssid = rt2400pci_config_bssid,
+- .config_type = rt2400pci_config_type,
+- .config_preamble = rt2400pci_config_preamble,
++ .config_filter = rt2400pci_config_filter,
++ .config_intf = rt2400pci_config_intf,
++ .config_erp = rt2400pci_config_erp,
+ .config = rt2400pci_config,
+ };
+
++static const struct data_queue_desc rt2400pci_queue_rx = {
++ .entry_num = RX_ENTRIES,
++ .data_size = DATA_FRAME_SIZE,
++ .desc_size = RXD_DESC_SIZE,
++ .priv_size = sizeof(struct queue_entry_priv_pci_rx),
++};
++
++static const struct data_queue_desc rt2400pci_queue_tx = {
++ .entry_num = TX_ENTRIES,
++ .data_size = DATA_FRAME_SIZE,
++ .desc_size = TXD_DESC_SIZE,
++ .priv_size = sizeof(struct queue_entry_priv_pci_tx),
++};
++
++static const struct data_queue_desc rt2400pci_queue_bcn = {
++ .entry_num = BEACON_ENTRIES,
++ .data_size = MGMT_FRAME_SIZE,
++ .desc_size = TXD_DESC_SIZE,
++ .priv_size = sizeof(struct queue_entry_priv_pci_tx),
++};
++
++static const struct data_queue_desc rt2400pci_queue_atim = {
++ .entry_num = ATIM_ENTRIES,
++ .data_size = DATA_FRAME_SIZE,
++ .desc_size = TXD_DESC_SIZE,
++ .priv_size = sizeof(struct queue_entry_priv_pci_tx),
++};
++
+ static const struct rt2x00_ops rt2400pci_ops = {
+ .name = KBUILD_MODNAME,
+- .rxd_size = RXD_DESC_SIZE,
+- .txd_size = TXD_DESC_SIZE,
++ .max_sta_intf = 1,
++ .max_ap_intf = 1,
+ .eeprom_size = EEPROM_SIZE,
+ .rf_size = RF_SIZE,
++ .rx = &rt2400pci_queue_rx,
++ .tx = &rt2400pci_queue_tx,
++ .bcn = &rt2400pci_queue_bcn,
++ .atim = &rt2400pci_queue_atim,
+ .lib = &rt2400pci_rt2x00_ops,
+ .hw = &rt2400pci_mac80211_ops,
+ #ifdef CONFIG_RT2X00_LIB_DEBUGFS
+diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h
+index 369aac6..a5210f9 100644
+--- a/drivers/net/wireless/rt2x00/rt2400pci.h
++++ b/drivers/net/wireless/rt2x00/rt2400pci.h
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+@@ -899,13 +899,13 @@
+ * Word2
+ */
+ #define RXD_W2_BUFFER_LENGTH FIELD32(0x0000ffff)
+-#define RXD_W2_SIGNAL FIELD32(0x00ff0000)
+-#define RXD_W2_RSSI FIELD32(0xff000000)
++#define RXD_W2_BBR0 FIELD32(0x00ff0000)
++#define RXD_W2_SIGNAL FIELD32(0xff000000)
+
+ /*
+ * Word3
+ */
+-#define RXD_W3_BBR2 FIELD32(0x000000ff)
++#define RXD_W3_RSSI FIELD32(0x000000ff)
+ #define RXD_W3_BBR3 FIELD32(0x0000ff00)
+ #define RXD_W3_BBR4 FIELD32(0x00ff0000)
+ #define RXD_W3_BBR5 FIELD32(0xff000000)
+@@ -923,13 +923,13 @@
+ #define RXD_W7_RESERVED FIELD32(0xffffffff)
+
+ /*
+- * Macro's for converting txpower from EEPROM to dscape value
+- * and from dscape value to register value.
++ * Macro's for converting txpower from EEPROM to mac80211 value
++ * and from mac80211 value to register value.
+ * NOTE: Logics in rt2400pci for txpower are reversed
+ * compared to the other rt2x00 drivers. A higher txpower
+ * value means that the txpower must be lowered. This is
+ * important when converting the value coming from the
+- * dscape stack to the rt2400 acceptable value.
++ * mac80211 stack to the rt2400 acceptable value.
+ */
+ #define MIN_TXPOWER 31
+ #define MAX_TXPOWER 62
+diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
+index 91e87b5..5ade097 100644
+--- a/drivers/net/wireless/rt2x00/rt2500pci.c
++++ b/drivers/net/wireless/rt2x00/rt2500pci.c
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+@@ -243,57 +243,116 @@ static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
+ #define rt2500pci_rfkill_poll NULL
+ #endif /* CONFIG_RT2500PCI_RFKILL */
+
+-/*
+- * Configuration handlers.
+- */
+-static void rt2500pci_config_mac_addr(struct rt2x00_dev *rt2x00dev,
+- __le32 *mac)
++#ifdef CONFIG_RT2500PCI_LEDS
++static void rt2500pci_brightness_set(struct led_classdev *led_cdev,
++ enum led_brightness brightness)
+ {
+- rt2x00pci_register_multiwrite(rt2x00dev, CSR3, mac,
+- (2 * sizeof(__le32)));
++ struct rt2x00_led *led =
++ container_of(led_cdev, struct rt2x00_led, led_dev);
++ unsigned int enabled = brightness != LED_OFF;
++ u32 reg;
++
++ rt2x00pci_register_read(led->rt2x00dev, LEDCSR, ®);
++
++ if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
++ rt2x00_set_field32(®, LEDCSR_LINK, enabled);
++ else if (led->type == LED_TYPE_ACTIVITY)
++ rt2x00_set_field32(®, LEDCSR_ACTIVITY, enabled);
++
++ rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
+ }
+
+-static void rt2500pci_config_bssid(struct rt2x00_dev *rt2x00dev,
+- __le32 *bssid)
++static int rt2500pci_blink_set(struct led_classdev *led_cdev,
++ unsigned long *delay_on,
++ unsigned long *delay_off)
+ {
+- rt2x00pci_register_multiwrite(rt2x00dev, CSR5, bssid,
+- (2 * sizeof(__le32)));
++ struct rt2x00_led *led =
++ container_of(led_cdev, struct rt2x00_led, led_dev);
++ u32 reg;
++
++ rt2x00pci_register_read(led->rt2x00dev, LEDCSR, ®);
++ rt2x00_set_field32(®, LEDCSR_ON_PERIOD, *delay_on);
++ rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, *delay_off);
++ rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
++
++ return 0;
+ }
++#endif /* CONFIG_RT2500PCI_LEDS */
+
+-static void rt2500pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,
+- const int tsf_sync)
++/*
++ * Configuration handlers.
++ */
++static void rt2500pci_config_filter(struct rt2x00_dev *rt2x00dev,
++ const unsigned int filter_flags)
+ {
+ u32 reg;
+
+- rt2x00pci_register_write(rt2x00dev, CSR14, 0);
+-
+ /*
+- * Enable beacon config
++ * Start configuration steps.
++ * Note that the version error will always be dropped
++ * and broadcast frames will always be accepted since
++ * there is no filter for it at this time.
+ */
+- rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®);
+- rt2x00_set_field32(®, BCNCSR1_PRELOAD,
+- PREAMBLE + get_duration(IEEE80211_HEADER, 20));
+- rt2x00_set_field32(®, BCNCSR1_BEACON_CWMIN,
+- rt2x00lib_get_ring(rt2x00dev,
+- IEEE80211_TX_QUEUE_BEACON)
+- ->tx_params.cw_min);
+- rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg);
++ rt2x00pci_register_read(rt2x00dev, RXCSR0, ®);
++ rt2x00_set_field32(®, RXCSR0_DROP_CRC,
++ !(filter_flags & FIF_FCSFAIL));
++ rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL,
++ !(filter_flags & FIF_PLCPFAIL));
++ rt2x00_set_field32(®, RXCSR0_DROP_CONTROL,
++ !(filter_flags & FIF_CONTROL));
++ rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME,
++ !(filter_flags & FIF_PROMISC_IN_BSS));
++ rt2x00_set_field32(®, RXCSR0_DROP_TODS,
++ !(filter_flags & FIF_PROMISC_IN_BSS) &&
++ !rt2x00dev->intf_ap_count);
++ rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1);
++ rt2x00_set_field32(®, RXCSR0_DROP_MCAST,
++ !(filter_flags & FIF_ALLMULTI));
++ rt2x00_set_field32(®, RXCSR0_DROP_BCAST, 0);
++ rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
++}
+
+- /*
+- * Enable synchronisation.
+- */
+- rt2x00pci_register_read(rt2x00dev, CSR14, ®);
+- rt2x00_set_field32(®, CSR14_TSF_COUNT, 1);
+- rt2x00_set_field32(®, CSR14_TBCN, (tsf_sync == TSF_SYNC_BEACON));
+- rt2x00_set_field32(®, CSR14_BEACON_GEN, 0);
+- rt2x00_set_field32(®, CSR14_TSF_SYNC, tsf_sync);
+- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
++static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev,
++ struct rt2x00_intf *intf,
++ struct rt2x00intf_conf *conf,
++ const unsigned int flags)
++{
++ struct data_queue *queue =
++ rt2x00queue_get_queue(rt2x00dev, RT2X00_BCN_QUEUE_BEACON);
++ unsigned int bcn_preload;
++ u32 reg;
++
++ if (flags & CONFIG_UPDATE_TYPE) {
++ /*
++ * Enable beacon config
++ */
++ bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20);
++ rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®);
++ rt2x00_set_field32(®, BCNCSR1_PRELOAD, bcn_preload);
++ rt2x00_set_field32(®, BCNCSR1_BEACON_CWMIN, queue->cw_min);
++ rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg);
++
++ /*
++ * Enable synchronisation.
++ */
++ rt2x00pci_register_read(rt2x00dev, CSR14, ®);
++ rt2x00_set_field32(®, CSR14_TSF_COUNT, 1);
++ rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync);
++ rt2x00_set_field32(®, CSR14_TBCN, 1);
++ rt2x00pci_register_write(rt2x00dev, CSR14, reg);
++ }
++
++ if (flags & CONFIG_UPDATE_MAC)
++ rt2x00pci_register_multiwrite(rt2x00dev, CSR3,
++ conf->mac, sizeof(conf->mac));
++
++ if (flags & CONFIG_UPDATE_BSSID)
++ rt2x00pci_register_multiwrite(rt2x00dev, CSR5,
++ conf->bssid, sizeof(conf->bssid));
+ }
+
+-static void rt2500pci_config_preamble(struct rt2x00_dev *rt2x00dev,
+- const int short_preamble,
+- const int ack_timeout,
+- const int ack_consume_time)
++static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,
++ struct rt2x00lib_erp *erp)
+ {
+ int preamble_mask;
+ u32 reg;
+@@ -301,11 +360,13 @@ static void rt2500pci_config_preamble(struct rt2x00_dev *rt2x00dev,
+ /*
+ * When short preamble is enabled, we should set bit 0x08
+ */
+- preamble_mask = short_preamble << 3;
++ preamble_mask = erp->short_preamble << 3;
+
+ rt2x00pci_register_read(rt2x00dev, TXCSR1, ®);
+- rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, ack_timeout);
+- rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, ack_consume_time);
++ rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT,
++ erp->ack_timeout);
++ rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME,
++ erp->ack_consume_time);
+ rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
+
+ rt2x00pci_register_read(rt2x00dev, ARCSR2, ®);
+@@ -425,6 +486,13 @@ static void rt2500pci_config_antenna(struct rt2x00_dev *rt2x00dev,
+ u8 r14;
+ u8 r2;
+
++ /*
++ * We should never come here because rt2x00lib is supposed
++ * to catch this and send us the correct antenna explicitely.
++ */
++ BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
++ ant->tx == ANTENNA_SW_DIVERSITY);
++
+ rt2x00pci_register_read(rt2x00dev, BBPCSR1, ®);
+ rt2500pci_bbp_read(rt2x00dev, 14, &r14);
+ rt2500pci_bbp_read(rt2x00dev, 2, &r2);
+@@ -438,15 +506,8 @@ static void rt2500pci_config_antenna(struct rt2x00_dev *rt2x00dev,
+ rt2x00_set_field32(®, BBPCSR1_CCK, 0);
+ rt2x00_set_field32(®, BBPCSR1_OFDM, 0);
+ break;
+- case ANTENNA_HW_DIVERSITY:
+- case ANTENNA_SW_DIVERSITY:
+- /*
+- * NOTE: We should never come here because rt2x00lib is
+- * supposed to catch this and send us the correct antenna
+- * explicitely. However we are nog going to bug about this.
+- * Instead, just default to antenna B.
+- */
+ case ANTENNA_B:
++ default:
+ rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2);
+ rt2x00_set_field32(®, BBPCSR1_CCK, 2);
+ rt2x00_set_field32(®, BBPCSR1_OFDM, 2);
+@@ -460,15 +521,8 @@ static void rt2500pci_config_antenna(struct rt2x00_dev *rt2x00dev,
+ case ANTENNA_A:
+ rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0);
+ break;
+- case ANTENNA_HW_DIVERSITY:
+- case ANTENNA_SW_DIVERSITY:
+- /*
+- * NOTE: We should never come here because rt2x00lib is
+- * supposed to catch this and send us the correct antenna
+- * explicitely. However we are nog going to bug about this.
+- * Instead, just default to antenna B.
+- */
+ case ANTENNA_B:
++ default:
+ rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2);
+ break;
+ }
+@@ -530,8 +584,8 @@ static void rt2500pci_config_duration(struct rt2x00_dev *rt2x00dev,
+ }
+
+ static void rt2500pci_config(struct rt2x00_dev *rt2x00dev,
+- const unsigned int flags,
+- struct rt2x00lib_conf *libconf)
++ struct rt2x00lib_conf *libconf,
++ const unsigned int flags)
+ {
+ if (flags & CONFIG_UPDATE_PHYMODE)
+ rt2500pci_config_phymode(rt2x00dev, libconf->basic_rates);
+@@ -548,34 +602,6 @@ static void rt2500pci_config(struct rt2x00_dev *rt2x00dev,
+ }
+
+ /*
+- * LED functions.
+- */
+-static void rt2500pci_enable_led(struct rt2x00_dev *rt2x00dev)
+-{
+- u32 reg;
+-
+- rt2x00pci_register_read(rt2x00dev, LEDCSR, ®);
+-
+- rt2x00_set_field32(®, LEDCSR_ON_PERIOD, 70);
+- rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, 30);
+- rt2x00_set_field32(®, LEDCSR_LINK,
+- (rt2x00dev->led_mode != LED_MODE_ASUS));
+- rt2x00_set_field32(®, LEDCSR_ACTIVITY,
+- (rt2x00dev->led_mode != LED_MODE_TXRX_ACTIVITY));
+- rt2x00pci_register_write(rt2x00dev, LEDCSR, reg);
+-}
+-
+-static void rt2500pci_disable_led(struct rt2x00_dev *rt2x00dev)
+-{
+- u32 reg;
+-
+- rt2x00pci_register_read(rt2x00dev, LEDCSR, ®);
+- rt2x00_set_field32(®, LEDCSR_LINK, 0);
+- rt2x00_set_field32(®, LEDCSR_ACTIVITY, 0);
+- rt2x00pci_register_write(rt2x00dev, LEDCSR, reg);
+-}
+-
+-/*
+ * Link tuning
+ */
+ static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev,
+@@ -610,9 +636,10 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev)
+ /*
+ * To prevent collisions with MAC ASIC on chipsets
+ * up to version C the link tuning should halt after 20
+- * seconds.
++ * seconds while being associated.
+ */
+ if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D &&
++ rt2x00dev->intf_associated &&
+ rt2x00dev->link.count > 20)
+ return;
+
+@@ -620,9 +647,12 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev)
+
+ /*
+ * Chipset versions C and lower should directly continue
+- * to the dynamic CCA tuning.
++ * to the dynamic CCA tuning. Chipset version D and higher
++ * should go straight to dynamic CCA tuning when they
++ * are not associated.
+ */
+- if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D)
++ if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D ||
++ !rt2x00dev->intf_associated)
+ goto dynamic_cca_tune;
+
+ /*
+@@ -684,82 +714,84 @@ dynamic_cca_tune:
+ * Initialization functions.
+ */
+ static void rt2500pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
+- struct data_entry *entry)
++ struct queue_entry *entry)
+ {
+- __le32 *rxd = entry->priv;
++ struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
+ u32 word;
+
+- rt2x00_desc_read(rxd, 1, &word);
+- rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, entry->data_dma);
+- rt2x00_desc_write(rxd, 1, word);
++ rt2x00_desc_read(priv_rx->desc, 1, &word);
++ rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, priv_rx->data_dma);
++ rt2x00_desc_write(priv_rx->desc, 1, word);
+
+- rt2x00_desc_read(rxd, 0, &word);
++ rt2x00_desc_read(priv_rx->desc, 0, &word);
+ rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
+- rt2x00_desc_write(rxd, 0, word);
++ rt2x00_desc_write(priv_rx->desc, 0, word);
+ }
+
+ static void rt2500pci_init_txentry(struct rt2x00_dev *rt2x00dev,
+- struct data_entry *entry)
++ struct queue_entry *entry)
+ {
+- __le32 *txd = entry->priv;
++ struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
+ u32 word;
+
+- rt2x00_desc_read(txd, 1, &word);
+- rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, entry->data_dma);
+- rt2x00_desc_write(txd, 1, word);
++ rt2x00_desc_read(priv_tx->desc, 1, &word);
++ rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, priv_tx->data_dma);
++ rt2x00_desc_write(priv_tx->desc, 1, word);
+
+- rt2x00_desc_read(txd, 0, &word);
++ rt2x00_desc_read(priv_tx->desc, 0, &word);
+ rt2x00_set_field32(&word, TXD_W0_VALID, 0);
+ rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
+- rt2x00_desc_write(txd, 0, word);
++ rt2x00_desc_write(priv_tx->desc, 0, word);
+ }
+
+-static int rt2500pci_init_rings(struct rt2x00_dev *rt2x00dev)
++static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev)
+ {
++ struct queue_entry_priv_pci_rx *priv_rx;
++ struct queue_entry_priv_pci_tx *priv_tx;
+ u32 reg;
+
+ /*
+ * Initialize registers.
+ */
+ rt2x00pci_register_read(rt2x00dev, TXCSR2, ®);
+- rt2x00_set_field32(®, TXCSR2_TXD_SIZE,
+- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size);
+- rt2x00_set_field32(®, TXCSR2_NUM_TXD,
+- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit);
+- rt2x00_set_field32(®, TXCSR2_NUM_ATIM,
+- rt2x00dev->bcn[1].stats.limit);
+- rt2x00_set_field32(®, TXCSR2_NUM_PRIO,
+- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit);
++ rt2x00_set_field32(®, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
++ rt2x00_set_field32(®, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
++ rt2x00_set_field32(®, TXCSR2_NUM_ATIM, rt2x00dev->bcn[1].limit);
++ rt2x00_set_field32(®, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit);
+ rt2x00pci_register_write(rt2x00dev, TXCSR2, reg);
+
++ priv_tx = rt2x00dev->tx[1].entries[0].priv_data;
+ rt2x00pci_register_read(rt2x00dev, TXCSR3, ®);
+ rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER,
+- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma);
++ priv_tx->desc_dma);
+ rt2x00pci_register_write(rt2x00dev, TXCSR3, reg);
+
++ priv_tx = rt2x00dev->tx[0].entries[0].priv_data;
+ rt2x00pci_register_read(rt2x00dev, TXCSR5, ®);
+ rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER,
+- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma);
++ priv_tx->desc_dma);
+ rt2x00pci_register_write(rt2x00dev, TXCSR5, reg);
+
++ priv_tx = rt2x00dev->bcn[1].entries[0].priv_data;
+ rt2x00pci_register_read(rt2x00dev, TXCSR4, ®);
+ rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER,
+- rt2x00dev->bcn[1].data_dma);
++ priv_tx->desc_dma);
+ rt2x00pci_register_write(rt2x00dev, TXCSR4, reg);
+
++ priv_tx = rt2x00dev->bcn[0].entries[0].priv_data;
+ rt2x00pci_register_read(rt2x00dev, TXCSR6, ®);
+ rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER,
+- rt2x00dev->bcn[0].data_dma);
++ priv_tx->desc_dma);
+ rt2x00pci_register_write(rt2x00dev, TXCSR6, reg);
+
+ rt2x00pci_register_read(rt2x00dev, RXCSR1, ®);
+ rt2x00_set_field32(®, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);
+- rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->stats.limit);
++ rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->limit);
+ rt2x00pci_register_write(rt2x00dev, RXCSR1, reg);
+
++ priv_rx = rt2x00dev->rx->entries[0].priv_data;
+ rt2x00pci_register_read(rt2x00dev, RXCSR2, ®);
+- rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER,
+- rt2x00dev->rx->data_dma);
++ rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, priv_rx->desc_dma);
+ rt2x00pci_register_write(rt2x00dev, RXCSR2, reg);
+
+ return 0;
+@@ -947,19 +979,15 @@ continue_csr_init:
+ rt2500pci_bbp_write(rt2x00dev, 61, 0x6d);
+ rt2500pci_bbp_write(rt2x00dev, 62, 0x10);
+
+- DEBUG(rt2x00dev, "Start initialization from EEPROM...\n");
+ for (i = 0; i < EEPROM_BBP_SIZE; i++) {
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+
+ if (eeprom != 0xffff && eeprom != 0x0000) {
+ reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
+ value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
+- DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n",
+- reg_id, value);
+ rt2500pci_bbp_write(rt2x00dev, reg_id, value);
+ }
+ }
+- DEBUG(rt2x00dev, "...End initialization from EEPROM.\n");
+
+ return 0;
+ }
+@@ -1011,7 +1039,7 @@ static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev)
+ /*
+ * Initialize all registers.
+ */
+- if (rt2500pci_init_rings(rt2x00dev) ||
++ if (rt2500pci_init_queues(rt2x00dev) ||
+ rt2500pci_init_registers(rt2x00dev) ||
+ rt2500pci_init_bbp(rt2x00dev)) {
+ ERROR(rt2x00dev, "Register initialization failed.\n");
+@@ -1023,11 +1051,6 @@ static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev)
+ */
+ rt2500pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_ON);
+
+- /*
+- * Enable LED
+- */
+- rt2500pci_enable_led(rt2x00dev);
+-
+ return 0;
+ }
+
+@@ -1035,11 +1058,6 @@ static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev)
+ {
+ u32 reg;
+
+- /*
+- * Disable LED
+- */
+- rt2500pci_disable_led(rt2x00dev);
+-
+ rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0);
+
+ /*
+@@ -1138,10 +1156,10 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev,
+ */
+ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ struct sk_buff *skb,
+- struct txdata_entry_desc *desc,
++ struct txentry_desc *txdesc,
+ struct ieee80211_tx_control *control)
+ {
+- struct skb_desc *skbdesc = get_skb_desc(skb);
++ struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+ __le32 *txd = skbdesc->desc;
+ u32 word;
+
+@@ -1150,36 +1168,36 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ */
+ rt2x00_desc_read(txd, 2, &word);
+ rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER);
+- rt2x00_set_field32(&word, TXD_W2_AIFS, desc->aifs);
+- rt2x00_set_field32(&word, TXD_W2_CWMIN, desc->cw_min);
+- rt2x00_set_field32(&word, TXD_W2_CWMAX, desc->cw_max);
++ rt2x00_set_field32(&word, TXD_W2_AIFS, txdesc->aifs);
++ rt2x00_set_field32(&word, TXD_W2_CWMIN, txdesc->cw_min);
++ rt2x00_set_field32(&word, TXD_W2_CWMAX, txdesc->cw_max);
+ rt2x00_desc_write(txd, 2, word);
+
+ rt2x00_desc_read(txd, 3, &word);
+- rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, desc->signal);
+- rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, desc->service);
+- rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW, desc->length_low);
+- rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH, desc->length_high);
++ rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->signal);
++ rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->service);
++ rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW, txdesc->length_low);
++ rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH, txdesc->length_high);
+ rt2x00_desc_write(txd, 3, word);
+
+ rt2x00_desc_read(txd, 10, &word);
+ rt2x00_set_field32(&word, TXD_W10_RTS,
+- test_bit(ENTRY_TXD_RTS_FRAME, &desc->flags));
++ test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags));
+ rt2x00_desc_write(txd, 10, word);
+
+ rt2x00_desc_read(txd, 0, &word);
+ rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
+ rt2x00_set_field32(&word, TXD_W0_VALID, 1);
+ rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
+- test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
++ test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_ACK,
+- test_bit(ENTRY_TXD_ACK, &desc->flags));
++ test_bit(ENTRY_TXD_ACK, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
+- test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
++ test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_OFDM,
+- test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags));
++ test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_CIPHER_OWNER, 1);
+- rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
++ rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
+ rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
+ !!(control->flags &
+ IEEE80211_TXCTL_LONG_RETRY_LIMIT));
+@@ -1192,13 +1210,15 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ * TX data initialization
+ */
+ static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
+- unsigned int queue)
++ const unsigned int queue)
+ {
+ u32 reg;
+
+- if (queue == IEEE80211_TX_QUEUE_BEACON) {
++ if (queue == RT2X00_BCN_QUEUE_BEACON) {
+ rt2x00pci_register_read(rt2x00dev, CSR14, ®);
+ if (!rt2x00_get_field32(reg, CSR14_BEACON_GEN)) {
++ rt2x00_set_field32(®, CSR14_TSF_COUNT, 1);
++ rt2x00_set_field32(®, CSR14_TBCN, 1);
+ rt2x00_set_field32(®, CSR14_BEACON_GEN, 1);
+ rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ }
+@@ -1211,53 +1231,63 @@ static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
+ rt2x00_set_field32(®, TXCSR0_KICK_TX,
+ (queue == IEEE80211_TX_QUEUE_DATA1));
+ rt2x00_set_field32(®, TXCSR0_KICK_ATIM,
+- (queue == IEEE80211_TX_QUEUE_AFTER_BEACON));
++ (queue == RT2X00_BCN_QUEUE_ATIM));
+ rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+ }
+
+ /*
+ * RX control handlers
+ */
+-static void rt2500pci_fill_rxdone(struct data_entry *entry,
+- struct rxdata_entry_desc *desc)
++static void rt2500pci_fill_rxdone(struct queue_entry *entry,
++ struct rxdone_entry_desc *rxdesc)
+ {
+- __le32 *rxd = entry->priv;
++ struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
+ u32 word0;
+ u32 word2;
+
+- rt2x00_desc_read(rxd, 0, &word0);
+- rt2x00_desc_read(rxd, 2, &word2);
++ rt2x00_desc_read(priv_rx->desc, 0, &word0);
++ rt2x00_desc_read(priv_rx->desc, 2, &word2);
+
+- desc->flags = 0;
++ rxdesc->flags = 0;
+ if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
+- desc->flags |= RX_FLAG_FAILED_FCS_CRC;
++ rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
+ if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
+- desc->flags |= RX_FLAG_FAILED_PLCP_CRC;
+-
+- desc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);
+- desc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) -
+- entry->ring->rt2x00dev->rssi_offset;
+- desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
+- desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+- desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
++ rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC;
++
++ /*
++ * Obtain the status about this packet.
++ * When frame was received with an OFDM bitrate,
++ * the signal is the PLCP value. If it was received with
++ * a CCK bitrate the signal is the rate in 100kbit/s.
++ */
++ rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);
++ rxdesc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) -
++ entry->queue->rt2x00dev->rssi_offset;
++ rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
++
++ rxdesc->dev_flags = 0;
++ if (rt2x00_get_field32(word0, RXD_W0_OFDM))
++ rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
++ if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
++ rxdesc->dev_flags |= RXDONE_MY_BSS;
+ }
+
+ /*
+ * Interrupt functions.
+ */
+-static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue)
++static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
++ const enum ieee80211_tx_queue queue_idx)
+ {
+- struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue);
+- struct data_entry *entry;
+- __le32 *txd;
++ struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
++ struct queue_entry_priv_pci_tx *priv_tx;
++ struct queue_entry *entry;
++ struct txdone_entry_desc txdesc;
+ u32 word;
+- int tx_status;
+- int retry;
+
+- while (!rt2x00_ring_empty(ring)) {
+- entry = rt2x00_get_data_entry_done(ring);
+- txd = entry->priv;
+- rt2x00_desc_read(txd, 0, &word);
++ while (!rt2x00queue_empty(queue)) {
++ entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
++ priv_tx = entry->priv_data;
++ rt2x00_desc_read(priv_tx->desc, 0, &word);
+
+ if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
+ !rt2x00_get_field32(word, TXD_W0_VALID))
+@@ -1266,10 +1296,10 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue)
+ /*
+ * Obtain the status about this packet.
+ */
+- tx_status = rt2x00_get_field32(word, TXD_W0_RESULT);
+- retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
++ txdesc.status = rt2x00_get_field32(word, TXD_W0_RESULT);
++ txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
+
+- rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry);
++ rt2x00pci_txdone(rt2x00dev, entry, &txdesc);
+ }
+ }
+
+@@ -1313,7 +1343,7 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
+ * 3 - Atim ring transmit done interrupt.
+ */
+ if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING))
+- rt2500pci_txdone(rt2x00dev, IEEE80211_TX_QUEUE_AFTER_BEACON);
++ rt2500pci_txdone(rt2x00dev, RT2X00_BCN_QUEUE_ATIM);
+
+ /*
+ * 4 - Priority ring transmit done interrupt.
+@@ -1442,8 +1472,27 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
+ /*
+ * Store led mode, for correct led behaviour.
+ */
+- rt2x00dev->led_mode =
+- rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
++#ifdef CONFIG_RT2500PCI_LEDS
++ value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
++
++ rt2x00dev->led_radio.rt2x00dev = rt2x00dev;
++ rt2x00dev->led_radio.type = LED_TYPE_RADIO;
++ rt2x00dev->led_radio.led_dev.brightness_set =
++ rt2500pci_brightness_set;
++ rt2x00dev->led_radio.led_dev.blink_set =
++ rt2500pci_blink_set;
++ rt2x00dev->led_radio.flags = LED_INITIALIZED;
++
++ if (value == LED_MODE_TXRX_ACTIVITY) {
++ rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
++ rt2x00dev->led_radio.type = LED_TYPE_ACTIVITY;
++ rt2x00dev->led_qual.led_dev.brightness_set =
++ rt2500pci_brightness_set;
++ rt2x00dev->led_qual.led_dev.blink_set =
++ rt2500pci_blink_set;
++ rt2x00dev->led_qual.flags = LED_INITIALIZED;
++ }
++#endif /* CONFIG_RT2500PCI_LEDS */
+
+ /*
+ * Detect if this device has an hardware controlled radio.
+@@ -1656,8 +1705,8 @@ static void rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+ /*
+ * Initialize hw_mode information.
+ */
+- spec->num_modes = 2;
+- spec->num_rates = 12;
++ spec->supported_bands = SUPPORT_BAND_2GHZ;
++ spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
+ spec->tx_power_a = NULL;
+ spec->tx_power_bg = txpower;
+ spec->tx_power_default = DEFAULT_TXPOWER;
+@@ -1678,9 +1727,9 @@ static void rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+ spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e);
+ spec->channels = rf_vals_bg_2525e;
+ } else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) {
++ spec->supported_bands |= SUPPORT_BAND_5GHZ;
+ spec->num_channels = ARRAY_SIZE(rf_vals_5222);
+ spec->channels = rf_vals_5222;
+- spec->num_modes = 3;
+ }
+ }
+
+@@ -1705,9 +1754,9 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
+ rt2500pci_probe_hw_mode(rt2x00dev);
+
+ /*
+- * This device requires the beacon ring
++ * This device requires the atim queue
+ */
+- __set_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags);
++ __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
+
+ /*
+ * Set the rssi offset.
+@@ -1720,69 +1769,6 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
+ /*
+ * IEEE80211 stack callback functions.
+ */
+-static void rt2500pci_configure_filter(struct ieee80211_hw *hw,
+- unsigned int changed_flags,
+- unsigned int *total_flags,
+- int mc_count,
+- struct dev_addr_list *mc_list)
+-{
+- struct rt2x00_dev *rt2x00dev = hw->priv;
+- u32 reg;
+-
+- /*
+- * Mask off any flags we are going to ignore from
+- * the total_flags field.
+- */
+- *total_flags &=
+- FIF_ALLMULTI |
+- FIF_FCSFAIL |
+- FIF_PLCPFAIL |
+- FIF_CONTROL |
+- FIF_OTHER_BSS |
+- FIF_PROMISC_IN_BSS;
+-
+- /*
+- * Apply some rules to the filters:
+- * - Some filters imply different filters to be set.
+- * - Some things we can't filter out at all.
+- */
+- if (mc_count)
+- *total_flags |= FIF_ALLMULTI;
+- if (*total_flags & FIF_OTHER_BSS ||
+- *total_flags & FIF_PROMISC_IN_BSS)
+- *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
+-
+- /*
+- * Check if there is any work left for us.
+- */
+- if (rt2x00dev->packet_filter == *total_flags)
+- return;
+- rt2x00dev->packet_filter = *total_flags;
+-
+- /*
+- * Start configuration steps.
+- * Note that the version error will always be dropped
+- * and broadcast frames will always be accepted since
+- * there is no filter for it at this time.
+- */
+- rt2x00pci_register_read(rt2x00dev, RXCSR0, ®);
+- rt2x00_set_field32(®, RXCSR0_DROP_CRC,
+- !(*total_flags & FIF_FCSFAIL));
+- rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL,
+- !(*total_flags & FIF_PLCPFAIL));
+- rt2x00_set_field32(®, RXCSR0_DROP_CONTROL,
+- !(*total_flags & FIF_CONTROL));
+- rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME,
+- !(*total_flags & FIF_PROMISC_IN_BSS));
+- rt2x00_set_field32(®, RXCSR0_DROP_TODS,
+- !(*total_flags & FIF_PROMISC_IN_BSS));
+- rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1);
+- rt2x00_set_field32(®, RXCSR0_DROP_MCAST,
+- !(*total_flags & FIF_ALLMULTI));
+- rt2x00_set_field32(®, RXCSR0_DROP_BCAST, 0);
+- rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
+-}
+-
+ static int rt2500pci_set_retry_limit(struct ieee80211_hw *hw,
+ u32 short_retry, u32 long_retry)
+ {
+@@ -1811,12 +1797,59 @@ static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw)
+ return tsf;
+ }
+
+-static void rt2500pci_reset_tsf(struct ieee80211_hw *hw)
++static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
++ struct ieee80211_tx_control *control)
+ {
+ struct rt2x00_dev *rt2x00dev = hw->priv;
++ struct rt2x00_intf *intf = vif_to_intf(control->vif);
++ struct queue_entry_priv_pci_tx *priv_tx;
++ struct skb_frame_desc *skbdesc;
++ u32 reg;
+
+- rt2x00pci_register_write(rt2x00dev, CSR16, 0);
+- rt2x00pci_register_write(rt2x00dev, CSR17, 0);
++ if (unlikely(!intf->beacon))
++ return -ENOBUFS;
++
++ priv_tx = intf->beacon->priv_data;
++
++ /*
++ * Fill in skb descriptor
++ */
++ skbdesc = get_skb_frame_desc(skb);
++ memset(skbdesc, 0, sizeof(*skbdesc));
++ skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
++ skbdesc->data = skb->data;
++ skbdesc->data_len = skb->len;
++ skbdesc->desc = priv_tx->desc;
++ skbdesc->desc_len = intf->beacon->queue->desc_size;
++ skbdesc->entry = intf->beacon;
++
++ /*
++ * Disable beaconing while we are reloading the beacon data,
++ * otherwise we might be sending out invalid data.
++ */
++ rt2x00pci_register_read(rt2x00dev, CSR14, ®);
++ rt2x00_set_field32(®, CSR14_TSF_COUNT, 0);
++ rt2x00_set_field32(®, CSR14_TBCN, 0);
++ rt2x00_set_field32(®, CSR14_BEACON_GEN, 0);
++ rt2x00pci_register_write(rt2x00dev, CSR14, reg);
++
++ /*
++ * mac80211 doesn't provide the control->queue variable
++ * for beacons. Set our own queue identification so
++ * it can be used during descriptor initialization.
++ */
++ control->queue = RT2X00_BCN_QUEUE_BEACON;
++ rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
++
++ /*
++ * Enable beacon generation.
++ * Write entire beacon with descriptor to register,
++ * and kick the beacon generator.
++ */
++ memcpy(priv_tx->data, skb->data, skb->len);
++ rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue);
++
++ return 0;
+ }
+
+ static int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw)
+@@ -1836,15 +1869,14 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
+ .remove_interface = rt2x00mac_remove_interface,
+ .config = rt2x00mac_config,
+ .config_interface = rt2x00mac_config_interface,
+- .configure_filter = rt2500pci_configure_filter,
++ .configure_filter = rt2x00mac_configure_filter,
+ .get_stats = rt2x00mac_get_stats,
+ .set_retry_limit = rt2500pci_set_retry_limit,
+ .bss_info_changed = rt2x00mac_bss_info_changed,
+ .conf_tx = rt2x00mac_conf_tx,
+ .get_tx_stats = rt2x00mac_get_tx_stats,
+ .get_tsf = rt2500pci_get_tsf,
+- .reset_tsf = rt2500pci_reset_tsf,
+- .beacon_update = rt2x00pci_beacon_update,
++ .beacon_update = rt2500pci_beacon_update,
+ .tx_last_beacon = rt2500pci_tx_last_beacon,
+ };
+
+@@ -1864,19 +1896,50 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
+ .write_tx_data = rt2x00pci_write_tx_data,
+ .kick_tx_queue = rt2500pci_kick_tx_queue,
+ .fill_rxdone = rt2500pci_fill_rxdone,
+- .config_mac_addr = rt2500pci_config_mac_addr,
+- .config_bssid = rt2500pci_config_bssid,
+- .config_type = rt2500pci_config_type,
+- .config_preamble = rt2500pci_config_preamble,
++ .config_filter = rt2500pci_config_filter,
++ .config_intf = rt2500pci_config_intf,
++ .config_erp = rt2500pci_config_erp,
+ .config = rt2500pci_config,
+ };
+
++static const struct data_queue_desc rt2500pci_queue_rx = {
++ .entry_num = RX_ENTRIES,
++ .data_size = DATA_FRAME_SIZE,
++ .desc_size = RXD_DESC_SIZE,
++ .priv_size = sizeof(struct queue_entry_priv_pci_rx),
++};
++
++static const struct data_queue_desc rt2500pci_queue_tx = {
++ .entry_num = TX_ENTRIES,
++ .data_size = DATA_FRAME_SIZE,
++ .desc_size = TXD_DESC_SIZE,
++ .priv_size = sizeof(struct queue_entry_priv_pci_tx),
++};
++
++static const struct data_queue_desc rt2500pci_queue_bcn = {
++ .entry_num = BEACON_ENTRIES,
++ .data_size = MGMT_FRAME_SIZE,
++ .desc_size = TXD_DESC_SIZE,
++ .priv_size = sizeof(struct queue_entry_priv_pci_tx),
++};
++
++static const struct data_queue_desc rt2500pci_queue_atim = {
++ .entry_num = ATIM_ENTRIES,
++ .data_size = DATA_FRAME_SIZE,
++ .desc_size = TXD_DESC_SIZE,
++ .priv_size = sizeof(struct queue_entry_priv_pci_tx),
++};
++
+ static const struct rt2x00_ops rt2500pci_ops = {
+ .name = KBUILD_MODNAME,
+- .rxd_size = RXD_DESC_SIZE,
+- .txd_size = TXD_DESC_SIZE,
++ .max_sta_intf = 1,
++ .max_ap_intf = 1,
+ .eeprom_size = EEPROM_SIZE,
+ .rf_size = RF_SIZE,
++ .rx = &rt2500pci_queue_rx,
++ .tx = &rt2500pci_queue_tx,
++ .bcn = &rt2500pci_queue_bcn,
++ .atim = &rt2500pci_queue_atim,
+ .lib = &rt2500pci_rt2x00_ops,
+ .hw = &rt2500pci_mac80211_ops,
+ #ifdef CONFIG_RT2X00_LIB_DEBUGFS
+diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h
+index 92ba090..1389955 100644
+--- a/drivers/net/wireless/rt2x00/rt2500pci.h
++++ b/drivers/net/wireless/rt2x00/rt2500pci.h
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+@@ -1213,8 +1213,8 @@
+ #define RXD_W10_DROP FIELD32(0x00000001)
+
+ /*
+- * Macro's for converting txpower from EEPROM to dscape value
+- * and from dscape value to register value.
++ * Macro's for converting txpower from EEPROM to mac80211 value
++ * and from mac80211 value to register value.
+ */
+ #define MIN_TXPOWER 0
+ #define MAX_TXPOWER 31
+diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
+index 638c3d2..6bb07b3 100644
+--- a/drivers/net/wireless/rt2x00/rt2500usb.c
++++ b/drivers/net/wireless/rt2x00/rt2500usb.c
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+@@ -282,97 +282,136 @@ static const struct rt2x00debug rt2500usb_rt2x00debug = {
+ };
+ #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+
+-/*
+- * Configuration handlers.
+- */
+-static void rt2500usb_config_mac_addr(struct rt2x00_dev *rt2x00dev,
+- __le32 *mac)
++#ifdef CONFIG_RT2500USB_LEDS
++static void rt2500usb_brightness_set(struct led_classdev *led_cdev,
++ enum led_brightness brightness)
+ {
+- rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, mac,
+- (3 * sizeof(__le16)));
+-}
++ struct rt2x00_led *led =
++ container_of(led_cdev, struct rt2x00_led, led_dev);
++ unsigned int enabled = brightness != LED_OFF;
++ u16 reg;
+
+-static void rt2500usb_config_bssid(struct rt2x00_dev *rt2x00dev,
+- __le32 *bssid)
+-{
+- rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, bssid,
+- (3 * sizeof(__le16)));
++ rt2500usb_register_read(led->rt2x00dev, MAC_CSR20, ®);
++
++ if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
++ rt2x00_set_field16(®, MAC_CSR20_LINK, enabled);
++ else if (led->type == LED_TYPE_ACTIVITY)
++ rt2x00_set_field16(®, MAC_CSR20_ACTIVITY, enabled);
++
++ rt2500usb_register_write(led->rt2x00dev, MAC_CSR20, reg);
+ }
+
+-static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type,
+- const int tsf_sync)
++static int rt2500usb_blink_set(struct led_classdev *led_cdev,
++ unsigned long *delay_on,
++ unsigned long *delay_off)
+ {
++ struct rt2x00_led *led =
++ container_of(led_cdev, struct rt2x00_led, led_dev);
+ u16 reg;
+
+- rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0);
++ rt2500usb_register_read(led->rt2x00dev, MAC_CSR21, ®);
++ rt2x00_set_field16(®, MAC_CSR21_ON_PERIOD, *delay_on);
++ rt2x00_set_field16(®, MAC_CSR21_OFF_PERIOD, *delay_off);
++ rt2500usb_register_write(led->rt2x00dev, MAC_CSR21, reg);
+
+- /*
+- * Enable beacon config
+- */
+- rt2500usb_register_read(rt2x00dev, TXRX_CSR20, ®);
+- rt2x00_set_field16(®, TXRX_CSR20_OFFSET,
+- (PREAMBLE + get_duration(IEEE80211_HEADER, 20)) >> 6);
+- if (type == IEEE80211_IF_TYPE_STA)
+- rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW, 0);
+- else
+- rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW, 2);
+- rt2500usb_register_write(rt2x00dev, TXRX_CSR20, reg);
++ return 0;
++}
++#endif /* CONFIG_RT2500USB_LEDS */
++
++/*
++ * Configuration handlers.
++ */
++static void rt2500usb_config_filter(struct rt2x00_dev *rt2x00dev,
++ const unsigned int filter_flags)
++{
++ u16 reg;
+
+ /*
+- * Enable synchronisation.
++ * Start configuration steps.
++ * Note that the version error will always be dropped
++ * and broadcast frames will always be accepted since
++ * there is no filter for it at this time.
+ */
+- rt2500usb_register_read(rt2x00dev, TXRX_CSR18, ®);
+- rt2x00_set_field16(®, TXRX_CSR18_OFFSET, 0);
+- rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
+-
+- rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®);
+- rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1);
+- rt2x00_set_field16(®, TXRX_CSR19_TBCN,
+- (tsf_sync == TSF_SYNC_BEACON));
+- rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0);
+- rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, tsf_sync);
+- rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
++ rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®);
++ rt2x00_set_field16(®, TXRX_CSR2_DROP_CRC,
++ !(filter_flags & FIF_FCSFAIL));
++ rt2x00_set_field16(®, TXRX_CSR2_DROP_PHYSICAL,
++ !(filter_flags & FIF_PLCPFAIL));
++ rt2x00_set_field16(®, TXRX_CSR2_DROP_CONTROL,
++ !(filter_flags & FIF_CONTROL));
++ rt2x00_set_field16(®, TXRX_CSR2_DROP_NOT_TO_ME,
++ !(filter_flags & FIF_PROMISC_IN_BSS));
++ rt2x00_set_field16(®, TXRX_CSR2_DROP_TODS,
++ !(filter_flags & FIF_PROMISC_IN_BSS) &&
++ !rt2x00dev->intf_ap_count);
++ rt2x00_set_field16(®, TXRX_CSR2_DROP_VERSION_ERROR, 1);
++ rt2x00_set_field16(®, TXRX_CSR2_DROP_MULTICAST,
++ !(filter_flags & FIF_ALLMULTI));
++ rt2x00_set_field16(®, TXRX_CSR2_DROP_BROADCAST, 0);
++ rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
+ }
+
+-static void rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev,
+- const int short_preamble,
+- const int ack_timeout,
+- const int ack_consume_time)
++static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev,
++ struct rt2x00_intf *intf,
++ struct rt2x00intf_conf *conf,
++ const unsigned int flags)
+ {
++ unsigned int bcn_preload;
+ u16 reg;
+
+- /*
+- * When in atomic context, reschedule and let rt2x00lib
+- * call this function again.
+- */
+- if (in_atomic()) {
+- queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->config_work);
+- return;
++ if (flags & CONFIG_UPDATE_TYPE) {
++ /*
++ * Enable beacon config
++ */
++ bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20);
++ rt2500usb_register_read(rt2x00dev, TXRX_CSR20, ®);
++ rt2x00_set_field16(®, TXRX_CSR20_OFFSET, bcn_preload >> 6);
++ rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW,
++ 2 * (conf->type != IEEE80211_IF_TYPE_STA));
++ rt2500usb_register_write(rt2x00dev, TXRX_CSR20, reg);
++
++ /*
++ * Enable synchronisation.
++ */
++ rt2500usb_register_read(rt2x00dev, TXRX_CSR18, ®);
++ rt2x00_set_field16(®, TXRX_CSR18_OFFSET, 0);
++ rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
++
++ rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®);
++ rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1);
++ rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, conf->sync);
++ rt2x00_set_field16(®, TXRX_CSR19_TBCN, 1);
++ rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
+ }
+
++ if (flags & CONFIG_UPDATE_MAC)
++ rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, conf->mac,
++ (3 * sizeof(__le16)));
++
++ if (flags & CONFIG_UPDATE_BSSID)
++ rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, conf->bssid,
++ (3 * sizeof(__le16)));
++}
++
++static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev,
++ struct rt2x00lib_erp *erp)
++{
++ u16 reg;
++
+ rt2500usb_register_read(rt2x00dev, TXRX_CSR1, ®);
+- rt2x00_set_field16(®, TXRX_CSR1_ACK_TIMEOUT, ack_timeout);
++ rt2x00_set_field16(®, TXRX_CSR1_ACK_TIMEOUT, erp->ack_timeout);
+ rt2500usb_register_write(rt2x00dev, TXRX_CSR1, reg);
+
+ rt2500usb_register_read(rt2x00dev, TXRX_CSR10, ®);
+ rt2x00_set_field16(®, TXRX_CSR10_AUTORESPOND_PREAMBLE,
+- !!short_preamble);
++ !!erp->short_preamble);
+ rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg);
+ }
+
+ static void rt2500usb_config_phymode(struct rt2x00_dev *rt2x00dev,
+- const int phymode,
+ const int basic_rate_mask)
+ {
+ rt2500usb_register_write(rt2x00dev, TXRX_CSR11, basic_rate_mask);
+-
+- if (phymode == HWMODE_B) {
+- rt2500usb_register_write(rt2x00dev, MAC_CSR11, 0x000b);
+- rt2500usb_register_write(rt2x00dev, MAC_CSR12, 0x0040);
+- } else {
+- rt2500usb_register_write(rt2x00dev, MAC_CSR11, 0x0005);
+- rt2500usb_register_write(rt2x00dev, MAC_CSR12, 0x016c);
+- }
+ }
+
+ static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev,
+@@ -424,6 +463,13 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev,
+ u16 csr5;
+ u16 csr6;
+
++ /*
++ * We should never come here because rt2x00lib is supposed
++ * to catch this and send us the correct antenna explicitely.
++ */
++ BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
++ ant->tx == ANTENNA_SW_DIVERSITY);
++
+ rt2500usb_bbp_read(rt2x00dev, 2, &r2);
+ rt2500usb_bbp_read(rt2x00dev, 14, &r14);
+ rt2500usb_register_read(rt2x00dev, PHY_CSR5, &csr5);
+@@ -443,14 +489,8 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev,
+ rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 0);
+ rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 0);
+ break;
+- case ANTENNA_SW_DIVERSITY:
+- /*
+- * NOTE: We should never come here because rt2x00lib is
+- * supposed to catch this and send us the correct antenna
+- * explicitely. However we are nog going to bug about this.
+- * Instead, just default to antenna B.
+- */
+ case ANTENNA_B:
++ default:
+ rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2);
+ rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 2);
+ rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 2);
+@@ -467,14 +507,8 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev,
+ case ANTENNA_A:
+ rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0);
+ break;
+- case ANTENNA_SW_DIVERSITY:
+- /*
+- * NOTE: We should never come here because rt2x00lib is
+- * supposed to catch this and send us the correct antenna
+- * explicitely. However we are nog going to bug about this.
+- * Instead, just default to antenna B.
+- */
+ case ANTENNA_B:
++ default:
+ rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2);
+ break;
+ }
+@@ -510,6 +544,8 @@ static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev,
+ u16 reg;
+
+ rt2500usb_register_write(rt2x00dev, MAC_CSR10, libconf->slot_time);
++ rt2500usb_register_write(rt2x00dev, MAC_CSR11, libconf->sifs);
++ rt2500usb_register_write(rt2x00dev, MAC_CSR12, libconf->eifs);
+
+ rt2500usb_register_read(rt2x00dev, TXRX_CSR18, ®);
+ rt2x00_set_field16(®, TXRX_CSR18_INTERVAL,
+@@ -518,12 +554,11 @@ static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev,
+ }
+
+ static void rt2500usb_config(struct rt2x00_dev *rt2x00dev,
+- const unsigned int flags,
+- struct rt2x00lib_conf *libconf)
++ struct rt2x00lib_conf *libconf,
++ const unsigned int flags)
+ {
+ if (flags & CONFIG_UPDATE_PHYMODE)
+- rt2500usb_config_phymode(rt2x00dev, libconf->phymode,
+- libconf->basic_rates);
++ rt2500usb_config_phymode(rt2x00dev, libconf->basic_rates);
+ if (flags & CONFIG_UPDATE_CHANNEL)
+ rt2500usb_config_channel(rt2x00dev, &libconf->rf,
+ libconf->conf->power_level);
+@@ -537,36 +572,6 @@ static void rt2500usb_config(struct rt2x00_dev *rt2x00dev,
+ }
+
+ /*
+- * LED functions.
+- */
+-static void rt2500usb_enable_led(struct rt2x00_dev *rt2x00dev)
+-{
+- u16 reg;
+-
+- rt2500usb_register_read(rt2x00dev, MAC_CSR21, ®);
+- rt2x00_set_field16(®, MAC_CSR21_ON_PERIOD, 70);
+- rt2x00_set_field16(®, MAC_CSR21_OFF_PERIOD, 30);
+- rt2500usb_register_write(rt2x00dev, MAC_CSR21, reg);
+-
+- rt2500usb_register_read(rt2x00dev, MAC_CSR20, ®);
+- rt2x00_set_field16(®, MAC_CSR20_LINK,
+- (rt2x00dev->led_mode != LED_MODE_ASUS));
+- rt2x00_set_field16(®, MAC_CSR20_ACTIVITY,
+- (rt2x00dev->led_mode != LED_MODE_TXRX_ACTIVITY));
+- rt2500usb_register_write(rt2x00dev, MAC_CSR20, reg);
+-}
+-
+-static void rt2500usb_disable_led(struct rt2x00_dev *rt2x00dev)
+-{
+- u16 reg;
+-
+- rt2500usb_register_read(rt2x00dev, MAC_CSR20, ®);
+- rt2x00_set_field16(®, MAC_CSR20_LINK, 0);
+- rt2x00_set_field16(®, MAC_CSR20_ACTIVITY, 0);
+- rt2500usb_register_write(rt2x00dev, MAC_CSR20, reg);
+-}
+-
+-/*
+ * Link tuning
+ */
+ static void rt2500usb_link_stats(struct rt2x00_dev *rt2x00dev,
+@@ -626,6 +631,24 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev)
+ u8 low_bound;
+
+ /*
++ * Read current r17 value, as well as the sensitivity values
++ * for the r17 register.
++ */
++ rt2500usb_bbp_read(rt2x00dev, 17, &r17);
++ rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &r17_sens);
++
++ rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &vgc_bound);
++ up_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCUPPER);
++ low_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCLOWER);
++
++ /*
++ * If we are not associated, we should go straight to the
++ * dynamic CCA tuning.
++ */
++ if (!rt2x00dev->intf_associated)
++ goto dynamic_cca_tune;
++
++ /*
+ * Determine the BBP tuning threshold and correctly
+ * set BBP 24, 25 and 61.
+ */
+@@ -651,13 +674,6 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev)
+ rt2500usb_bbp_write(rt2x00dev, 61, r61);
+
+ /*
+- * Read current r17 value, as well as the sensitivity values
+- * for the r17 register.
+- */
+- rt2500usb_bbp_read(rt2x00dev, 17, &r17);
+- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &r17_sens);
+-
+- /*
+ * A too low RSSI will cause too much false CCA which will
+ * then corrupt the R17 tuning. To remidy this the tuning should
+ * be stopped (While making sure the R17 value will not exceed limits)
+@@ -692,14 +708,9 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev)
+ * Leave short or middle distance condition, restore r17
+ * to the dynamic tuning range.
+ */
+- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &vgc_bound);
+- vgc_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCUPPER);
+-
+ low_bound = 0x32;
+- if (rssi >= -77)
+- up_bound = vgc_bound;
+- else
+- up_bound = vgc_bound - (-77 - rssi);
++ if (rssi < -77)
++ up_bound -= (-77 - rssi);
+
+ if (up_bound < low_bound)
+ up_bound = low_bound;
+@@ -707,7 +718,16 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev)
+ if (r17 > up_bound) {
+ rt2500usb_bbp_write(rt2x00dev, 17, up_bound);
+ rt2x00dev->link.vgc_level = up_bound;
+- } else if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) {
++ return;
++ }
++
++dynamic_cca_tune:
++
++ /*
++ * R17 is inside the dynamic tuning range,
++ * start tuning the link based on the false cca counter.
++ */
++ if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) {
+ rt2500usb_bbp_write(rt2x00dev, 17, ++r17);
+ rt2x00dev->link.vgc_level = r17;
+ } else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) {
+@@ -878,19 +898,15 @@ continue_csr_init:
+ rt2500usb_bbp_write(rt2x00dev, 62, 0x10);
+ rt2500usb_bbp_write(rt2x00dev, 75, 0xff);
+
+- DEBUG(rt2x00dev, "Start initialization from EEPROM...\n");
+ for (i = 0; i < EEPROM_BBP_SIZE; i++) {
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+
+ if (eeprom != 0xffff && eeprom != 0x0000) {
+ reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
+ value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
+- DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n",
+- reg_id, value);
+ rt2500usb_bbp_write(rt2x00dev, reg_id, value);
+ }
+ }
+- DEBUG(rt2x00dev, "...End initialization from EEPROM.\n");
+
+ return 0;
+ }
+@@ -920,21 +936,11 @@ static int rt2500usb_enable_radio(struct rt2x00_dev *rt2x00dev)
+ return -EIO;
+ }
+
+- /*
+- * Enable LED
+- */
+- rt2500usb_enable_led(rt2x00dev);
+-
+ return 0;
+ }
+
+ static void rt2500usb_disable_radio(struct rt2x00_dev *rt2x00dev)
+ {
+- /*
+- * Disable LED
+- */
+- rt2500usb_disable_led(rt2x00dev);
+-
+ rt2500usb_register_write(rt2x00dev, MAC_CSR13, 0x2121);
+ rt2500usb_register_write(rt2x00dev, MAC_CSR14, 0x2121);
+
+@@ -1027,10 +1033,10 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev,
+ */
+ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ struct sk_buff *skb,
+- struct txdata_entry_desc *desc,
++ struct txentry_desc *txdesc,
+ struct ieee80211_tx_control *control)
+ {
+- struct skb_desc *skbdesc = get_skb_desc(skb);
++ struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+ __le32 *txd = skbdesc->desc;
+ u32 word;
+
+@@ -1039,31 +1045,31 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ */
+ rt2x00_desc_read(txd, 1, &word);
+ rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER);
+- rt2x00_set_field32(&word, TXD_W1_AIFS, desc->aifs);
+- rt2x00_set_field32(&word, TXD_W1_CWMIN, desc->cw_min);
+- rt2x00_set_field32(&word, TXD_W1_CWMAX, desc->cw_max);
++ rt2x00_set_field32(&word, TXD_W1_AIFS, txdesc->aifs);
++ rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
++ rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
+ rt2x00_desc_write(txd, 1, word);
+
+ rt2x00_desc_read(txd, 2, &word);
+- rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, desc->signal);
+- rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, desc->service);
+- rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, desc->length_low);
+- rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, desc->length_high);
++ rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal);
++ rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service);
++ rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low);
++ rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
+ rt2x00_desc_write(txd, 2, word);
+
+ rt2x00_desc_read(txd, 0, &word);
+ rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, control->retry_limit);
+ rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
+- test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
++ test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_ACK,
+- test_bit(ENTRY_TXD_ACK, &desc->flags));
++ test_bit(ENTRY_TXD_ACK, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
+- test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
++ test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_OFDM,
+- test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags));
++ test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_NEW_SEQ,
+ !!(control->flags & IEEE80211_TXCTL_FIRST_FRAGMENT));
+- rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
++ rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
+ rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
+ rt2x00_set_field32(&word, TXD_W0_CIPHER, CIPHER_NONE);
+ rt2x00_desc_write(txd, 0, word);
+@@ -1088,15 +1094,17 @@ static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
+ * TX data initialization
+ */
+ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
+- unsigned int queue)
++ const unsigned int queue)
+ {
+ u16 reg;
+
+- if (queue != IEEE80211_TX_QUEUE_BEACON)
++ if (queue != RT2X00_BCN_QUEUE_BEACON)
+ return;
+
+ rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®);
+ if (!rt2x00_get_field16(reg, TXRX_CSR19_BEACON_GEN)) {
++ rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1);
++ rt2x00_set_field16(®, TXRX_CSR19_TBCN, 1);
+ rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 1);
+ /*
+ * Beacon generation will fail initially.
+@@ -1114,42 +1122,68 @@ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
+ /*
+ * RX control handlers
+ */
+-static void rt2500usb_fill_rxdone(struct data_entry *entry,
+- struct rxdata_entry_desc *desc)
++static void rt2500usb_fill_rxdone(struct queue_entry *entry,
++ struct rxdone_entry_desc *rxdesc)
+ {
+- struct skb_desc *skbdesc = get_skb_desc(entry->skb);
+- struct urb *urb = entry->priv;
+- __le32 *rxd = (__le32 *)(entry->skb->data +
+- (urb->actual_length - entry->ring->desc_size));
++ struct queue_entry_priv_usb_rx *priv_rx = entry->priv_data;
++ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
++ __le32 *rxd =
++ (__le32 *)(entry->skb->data +
++ (priv_rx->urb->actual_length - entry->queue->desc_size));
++ unsigned int offset = entry->queue->desc_size + 2;
+ u32 word0;
+ u32 word1;
+
++ /*
++ * Copy descriptor to the available headroom inside the skbuffer.
++ */
++ skb_push(entry->skb, offset);
++ memcpy(entry->skb->data, rxd, entry->queue->desc_size);
++ rxd = (__le32 *)entry->skb->data;
++
++ /*
++ * The descriptor is now aligned to 4 bytes and thus it is
++ * now safe to read it on all architectures.
++ */
+ rt2x00_desc_read(rxd, 0, &word0);
+ rt2x00_desc_read(rxd, 1, &word1);
+
+- desc->flags = 0;
++ rxdesc->flags = 0;
+ if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
+- desc->flags |= RX_FLAG_FAILED_FCS_CRC;
++ rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
+ if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
+- desc->flags |= RX_FLAG_FAILED_PLCP_CRC;
++ rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC;
+
+ /*
+ * Obtain the status about this packet.
++ * When frame was received with an OFDM bitrate,
++ * the signal is the PLCP value. If it was received with
++ * a CCK bitrate the signal is the rate in 100kbit/s.
++ */
++ rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
++ rxdesc->rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) -
++ entry->queue->rt2x00dev->rssi_offset;
++ rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
++
++ rxdesc->dev_flags = 0;
++ if (rt2x00_get_field32(word0, RXD_W0_OFDM))
++ rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
++ if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
++ rxdesc->dev_flags |= RXDONE_MY_BSS;
++
++ /*
++ * Adjust the skb memory window to the frame boundaries.
+ */
+- desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
+- desc->rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) -
+- entry->ring->rt2x00dev->rssi_offset;
+- desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
+- desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+- desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
++ skb_pull(entry->skb, offset);
++ skb_trim(entry->skb, rxdesc->size);
+
+ /*
+ * Set descriptor and data pointer.
+ */
+- skbdesc->desc = entry->skb->data + desc->size;
+- skbdesc->desc_len = entry->ring->desc_size;
+ skbdesc->data = entry->skb->data;
+- skbdesc->data_len = desc->size;
++ skbdesc->data_len = rxdesc->size;
++ skbdesc->desc = rxd;
++ skbdesc->desc_len = entry->queue->desc_size;
+ }
+
+ /*
+@@ -1157,10 +1191,10 @@ static void rt2500usb_fill_rxdone(struct data_entry *entry,
+ */
+ static void rt2500usb_beacondone(struct urb *urb)
+ {
+- struct data_entry *entry = (struct data_entry *)urb->context;
+- struct data_ring *ring = entry->ring;
++ struct queue_entry *entry = (struct queue_entry *)urb->context;
++ struct queue_entry_priv_usb_bcn *priv_bcn = entry->priv_data;
+
+- if (!test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags))
++ if (!test_bit(DEVICE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags))
+ return;
+
+ /*
+@@ -1169,18 +1203,11 @@ static void rt2500usb_beacondone(struct urb *urb)
+ * Otherwise we should free the sk_buffer, the device
+ * should be doing the rest of the work now.
+ */
+- if (ring->index == 1) {
+- rt2x00_ring_index_done_inc(ring);
+- entry = rt2x00_get_data_entry(ring);
+- usb_submit_urb(entry->priv, GFP_ATOMIC);
+- rt2x00_ring_index_inc(ring);
+- } else if (ring->index_done == 1) {
+- entry = rt2x00_get_data_entry_done(ring);
+- if (entry->skb) {
+- dev_kfree_skb(entry->skb);
+- entry->skb = NULL;
+- }
+- rt2x00_ring_index_done_inc(ring);
++ if (priv_bcn->guardian_urb == urb) {
++ usb_submit_urb(priv_bcn->urb, GFP_ATOMIC);
++ } else if (priv_bcn->urb == urb) {
++ dev_kfree_skb(entry->skb);
++ entry->skb = NULL;
+ }
+ }
+
+@@ -1191,6 +1218,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
+ {
+ u16 word;
+ u8 *mac;
++ u8 bbp;
+
+ rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE);
+
+@@ -1245,9 +1273,17 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
+ EEPROM(rt2x00dev, "BBPtune: 0x%04x\n", word);
+ }
+
++ /*
++ * Switch lower vgc bound to current BBP R17 value,
++ * lower the value a bit for better quality.
++ */
++ rt2500usb_bbp_read(rt2x00dev, 17, &bbp);
++ bbp -= 6;
++
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &word);
+ if (word == 0xffff) {
+ rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCUPPER, 0x40);
++ rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);
+ rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word);
+ EEPROM(rt2x00dev, "BBPtune vgc: 0x%04x\n", word);
+ }
+@@ -1258,6 +1294,9 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
+ rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_HIGH, 0x41);
+ rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R17, word);
+ EEPROM(rt2x00dev, "BBPtune r17: 0x%04x\n", word);
++ } else {
++ rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);
++ rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word);
+ }
+
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &word);
+@@ -1342,8 +1381,27 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
+ /*
+ * Store led mode, for correct led behaviour.
+ */
+- rt2x00dev->led_mode =
+- rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
++#ifdef CONFIG_RT2500USB_LEDS
++ value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
++
++ rt2x00dev->led_radio.rt2x00dev = rt2x00dev;
++ rt2x00dev->led_radio.type = LED_TYPE_RADIO;
++ rt2x00dev->led_radio.led_dev.brightness_set =
++ rt2500usb_brightness_set;
++ rt2x00dev->led_radio.led_dev.blink_set =
++ rt2500usb_blink_set;
++ rt2x00dev->led_radio.flags = LED_INITIALIZED;
++
++ if (value == LED_MODE_TXRX_ACTIVITY) {
++ rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
++ rt2x00dev->led_radio.type = LED_TYPE_ACTIVITY;
++ rt2x00dev->led_qual.led_dev.brightness_set =
++ rt2500usb_brightness_set;
++ rt2x00dev->led_qual.led_dev.blink_set =
++ rt2500usb_blink_set;
++ rt2x00dev->led_qual.flags = LED_INITIALIZED;
++ }
++#endif /* CONFIG_RT2500USB_LEDS */
+
+ /*
+ * Check if the BBP tuning should be disabled.
+@@ -1550,8 +1608,8 @@ static void rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+ /*
+ * Initialize hw_mode information.
+ */
+- spec->num_modes = 2;
+- spec->num_rates = 12;
++ spec->supported_bands = SUPPORT_BAND_2GHZ;
++ spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
+ spec->tx_power_a = NULL;
+ spec->tx_power_bg = txpower;
+ spec->tx_power_default = DEFAULT_TXPOWER;
+@@ -1572,9 +1630,9 @@ static void rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+ spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e);
+ spec->channels = rf_vals_bg_2525e;
+ } else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) {
++ spec->supported_bands |= SUPPORT_BAND_5GHZ;
+ spec->num_channels = ARRAY_SIZE(rf_vals_5222);
+ spec->channels = rf_vals_5222;
+- spec->num_modes = 3;
+ }
+ }
+
+@@ -1599,9 +1657,11 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
+ rt2500usb_probe_hw_mode(rt2x00dev);
+
+ /*
+- * This device requires the beacon ring
++ * This device requires the atim queue
+ */
+- __set_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags);
++ __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
++ __set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags);
++ __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags);
+
+ /*
+ * Set the rssi offset.
+@@ -1614,125 +1674,58 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
+ /*
+ * IEEE80211 stack callback functions.
+ */
+-static void rt2500usb_configure_filter(struct ieee80211_hw *hw,
+- unsigned int changed_flags,
+- unsigned int *total_flags,
+- int mc_count,
+- struct dev_addr_list *mc_list)
+-{
+- struct rt2x00_dev *rt2x00dev = hw->priv;
+- u16 reg;
+-
+- /*
+- * Mask off any flags we are going to ignore from
+- * the total_flags field.
+- */
+- *total_flags &=
+- FIF_ALLMULTI |
+- FIF_FCSFAIL |
+- FIF_PLCPFAIL |
+- FIF_CONTROL |
+- FIF_OTHER_BSS |
+- FIF_PROMISC_IN_BSS;
+-
+- /*
+- * Apply some rules to the filters:
+- * - Some filters imply different filters to be set.
+- * - Some things we can't filter out at all.
+- */
+- if (mc_count)
+- *total_flags |= FIF_ALLMULTI;
+- if (*total_flags & FIF_OTHER_BSS ||
+- *total_flags & FIF_PROMISC_IN_BSS)
+- *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
+-
+- /*
+- * Check if there is any work left for us.
+- */
+- if (rt2x00dev->packet_filter == *total_flags)
+- return;
+- rt2x00dev->packet_filter = *total_flags;
+-
+- /*
+- * When in atomic context, reschedule and let rt2x00lib
+- * call this function again.
+- */
+- if (in_atomic()) {
+- queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work);
+- return;
+- }
+-
+- /*
+- * Start configuration steps.
+- * Note that the version error will always be dropped
+- * and broadcast frames will always be accepted since
+- * there is no filter for it at this time.
+- */
+- rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®);
+- rt2x00_set_field16(®, TXRX_CSR2_DROP_CRC,
+- !(*total_flags & FIF_FCSFAIL));
+- rt2x00_set_field16(®, TXRX_CSR2_DROP_PHYSICAL,
+- !(*total_flags & FIF_PLCPFAIL));
+- rt2x00_set_field16(®, TXRX_CSR2_DROP_CONTROL,
+- !(*total_flags & FIF_CONTROL));
+- rt2x00_set_field16(®, TXRX_CSR2_DROP_NOT_TO_ME,
+- !(*total_flags & FIF_PROMISC_IN_BSS));
+- rt2x00_set_field16(®, TXRX_CSR2_DROP_TODS,
+- !(*total_flags & FIF_PROMISC_IN_BSS));
+- rt2x00_set_field16(®, TXRX_CSR2_DROP_VERSION_ERROR, 1);
+- rt2x00_set_field16(®, TXRX_CSR2_DROP_MULTICAST,
+- !(*total_flags & FIF_ALLMULTI));
+- rt2x00_set_field16(®, TXRX_CSR2_DROP_BROADCAST, 0);
+- rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
+-}
+-
+ static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
+ struct sk_buff *skb,
+ struct ieee80211_tx_control *control)
+ {
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+- struct usb_device *usb_dev =
+- interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
+- struct skb_desc *desc;
+- struct data_ring *ring;
+- struct data_entry *beacon;
+- struct data_entry *guardian;
++ struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev);
++ struct rt2x00_intf *intf = vif_to_intf(control->vif);
++ struct queue_entry_priv_usb_bcn *priv_bcn;
++ struct skb_frame_desc *skbdesc;
+ int pipe = usb_sndbulkpipe(usb_dev, 1);
+ int length;
++ u16 reg;
++
++ if (unlikely(!intf->beacon))
++ return -ENOBUFS;
++
++ priv_bcn = intf->beacon->priv_data;
+
+ /*
+- * Just in case the ieee80211 doesn't set this,
+- * but we need this queue set for the descriptor
+- * initialization.
++ * Add the descriptor in front of the skb.
+ */
+- control->queue = IEEE80211_TX_QUEUE_BEACON;
+- ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
++ skb_push(skb, intf->beacon->queue->desc_size);
++ memset(skb->data, 0, intf->beacon->queue->desc_size);
+
+ /*
+- * Obtain 2 entries, one for the guardian byte,
+- * the second for the actual beacon.
++ * Fill in skb descriptor
+ */
+- guardian = rt2x00_get_data_entry(ring);
+- rt2x00_ring_index_inc(ring);
+- beacon = rt2x00_get_data_entry(ring);
++ skbdesc = get_skb_frame_desc(skb);
++ memset(skbdesc, 0, sizeof(*skbdesc));
++ skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
++ skbdesc->data = skb->data + intf->beacon->queue->desc_size;
++ skbdesc->data_len = skb->len - intf->beacon->queue->desc_size;
++ skbdesc->desc = skb->data;
++ skbdesc->desc_len = intf->beacon->queue->desc_size;
++ skbdesc->entry = intf->beacon;
+
+ /*
+- * Add the descriptor in front of the skb.
++ * Disable beaconing while we are reloading the beacon data,
++ * otherwise we might be sending out invalid data.
+ */
+- skb_push(skb, ring->desc_size);
+- memset(skb->data, 0, ring->desc_size);
++ rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®);
++ rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 0);
++ rt2x00_set_field16(®, TXRX_CSR19_TBCN, 0);
++ rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0);
++ rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
+
+ /*
+- * Fill in skb descriptor
++ * mac80211 doesn't provide the control->queue variable
++ * for beacons. Set our own queue identification so
++ * it can be used during descriptor initialization.
+ */
+- desc = get_skb_desc(skb);
+- desc->desc_len = ring->desc_size;
+- desc->data_len = skb->len - ring->desc_size;
+- desc->desc = skb->data;
+- desc->data = skb->data + ring->desc_size;
+- desc->ring = ring;
+- desc->entry = beacon;
+-
++ control->queue = RT2X00_BCN_QUEUE_BEACON;
+ rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
+
+ /*
+@@ -1742,27 +1735,29 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
+ */
+ length = rt2500usb_get_tx_data_len(rt2x00dev, skb);
+
+- usb_fill_bulk_urb(beacon->priv, usb_dev, pipe,
+- skb->data, length, rt2500usb_beacondone, beacon);
++ usb_fill_bulk_urb(priv_bcn->urb, usb_dev, pipe,
++ skb->data, length, rt2500usb_beacondone,
++ intf->beacon);
+
+ /*
+ * Second we need to create the guardian byte.
+ * We only need a single byte, so lets recycle
+ * the 'flags' field we are not using for beacons.
+ */
+- guardian->flags = 0;
+- usb_fill_bulk_urb(guardian->priv, usb_dev, pipe,
+- &guardian->flags, 1, rt2500usb_beacondone, guardian);
++ priv_bcn->guardian_data = 0;
++ usb_fill_bulk_urb(priv_bcn->guardian_urb, usb_dev, pipe,
++ &priv_bcn->guardian_data, 1, rt2500usb_beacondone,
++ intf->beacon);
+
+ /*
+ * Send out the guardian byte.
+ */
+- usb_submit_urb(guardian->priv, GFP_ATOMIC);
++ usb_submit_urb(priv_bcn->guardian_urb, GFP_ATOMIC);
+
+ /*
+ * Enable beacon generation.
+ */
+- rt2500usb_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
++ rt2500usb_kick_tx_queue(rt2x00dev, control->queue);
+
+ return 0;
+ }
+@@ -1775,7 +1770,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
+ .remove_interface = rt2x00mac_remove_interface,
+ .config = rt2x00mac_config,
+ .config_interface = rt2x00mac_config_interface,
+- .configure_filter = rt2500usb_configure_filter,
++ .configure_filter = rt2x00mac_configure_filter,
+ .get_stats = rt2x00mac_get_stats,
+ .bss_info_changed = rt2x00mac_bss_info_changed,
+ .conf_tx = rt2x00mac_conf_tx,
+@@ -1798,19 +1793,50 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
+ .get_tx_data_len = rt2500usb_get_tx_data_len,
+ .kick_tx_queue = rt2500usb_kick_tx_queue,
+ .fill_rxdone = rt2500usb_fill_rxdone,
+- .config_mac_addr = rt2500usb_config_mac_addr,
+- .config_bssid = rt2500usb_config_bssid,
+- .config_type = rt2500usb_config_type,
+- .config_preamble = rt2500usb_config_preamble,
++ .config_filter = rt2500usb_config_filter,
++ .config_intf = rt2500usb_config_intf,
++ .config_erp = rt2500usb_config_erp,
+ .config = rt2500usb_config,
+ };
+
++static const struct data_queue_desc rt2500usb_queue_rx = {
++ .entry_num = RX_ENTRIES,
++ .data_size = DATA_FRAME_SIZE,
++ .desc_size = RXD_DESC_SIZE,
++ .priv_size = sizeof(struct queue_entry_priv_usb_rx),
++};
++
++static const struct data_queue_desc rt2500usb_queue_tx = {
++ .entry_num = TX_ENTRIES,
++ .data_size = DATA_FRAME_SIZE,
++ .desc_size = TXD_DESC_SIZE,
++ .priv_size = sizeof(struct queue_entry_priv_usb_tx),
++};
++
++static const struct data_queue_desc rt2500usb_queue_bcn = {
++ .entry_num = BEACON_ENTRIES,
++ .data_size = MGMT_FRAME_SIZE,
++ .desc_size = TXD_DESC_SIZE,
++ .priv_size = sizeof(struct queue_entry_priv_usb_bcn),
++};
++
++static const struct data_queue_desc rt2500usb_queue_atim = {
++ .entry_num = ATIM_ENTRIES,
++ .data_size = DATA_FRAME_SIZE,
++ .desc_size = TXD_DESC_SIZE,
++ .priv_size = sizeof(struct queue_entry_priv_usb_tx),
++};
++
+ static const struct rt2x00_ops rt2500usb_ops = {
+ .name = KBUILD_MODNAME,
+- .rxd_size = RXD_DESC_SIZE,
+- .txd_size = TXD_DESC_SIZE,
++ .max_sta_intf = 1,
++ .max_ap_intf = 1,
+ .eeprom_size = EEPROM_SIZE,
+ .rf_size = RF_SIZE,
++ .rx = &rt2500usb_queue_rx,
++ .tx = &rt2500usb_queue_tx,
++ .bcn = &rt2500usb_queue_bcn,
++ .atim = &rt2500usb_queue_atim,
+ .lib = &rt2500usb_rt2x00_ops,
+ .hw = &rt2500usb_mac80211_ops,
+ #ifdef CONFIG_RT2X00_LIB_DEBUGFS
+diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h
+index 9e04337..a37a068 100644
+--- a/drivers/net/wireless/rt2x00/rt2500usb.h
++++ b/drivers/net/wireless/rt2x00/rt2500usb.h
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+@@ -135,7 +135,7 @@
+ * Misc MAC_CSR registers.
+ * MAC_CSR9: Timer control.
+ * MAC_CSR10: Slot time.
+- * MAC_CSR11: IFS.
++ * MAC_CSR11: SIFS.
+ * MAC_CSR12: EIFS.
+ * MAC_CSR13: Power mode0.
+ * MAC_CSR14: Power mode1.
+@@ -686,6 +686,7 @@
+ */
+ #define EEPROM_BBPTUNE_VGC 0x0034
+ #define EEPROM_BBPTUNE_VGCUPPER FIELD16(0x00ff)
++#define EEPROM_BBPTUNE_VGCLOWER FIELD16(0xff00)
+
+ /*
+ * EEPROM BBP R17 Tuning.
+@@ -786,8 +787,8 @@
+ #define RXD_W3_EIV FIELD32(0xffffffff)
+
+ /*
+- * Macro's for converting txpower from EEPROM to dscape value
+- * and from dscape value to register value.
++ * Macro's for converting txpower from EEPROM to mac80211 value
++ * and from mac80211 value to register value.
+ */
+ #define MIN_TXPOWER 0
+ #define MAX_TXPOWER 31
+diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
+index 6c72542..57bdc15 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/rt2x00/rt2x00.h
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+@@ -27,23 +27,24 @@
+ #define RT2X00_H
+
+ #include <linux/bitops.h>
+-#include <linux/prefetch.h>
+ #include <linux/skbuff.h>
+ #include <linux/workqueue.h>
+ #include <linux/firmware.h>
++#include <linux/leds.h>
+ #include <linux/mutex.h>
+ #include <linux/etherdevice.h>
+
+ #include <net/mac80211.h>
+
+ #include "rt2x00debug.h"
++#include "rt2x00leds.h"
+ #include "rt2x00reg.h"
+-#include "rt2x00ring.h"
++#include "rt2x00queue.h"
+
+ /*
+ * Module information.
+ */
+-#define DRV_VERSION "2.0.14"
++#define DRV_VERSION "2.1.4"
+ #define DRV_PROJECT "http://rt2x00.serialmonkey.com"
+
+ /*
+@@ -91,26 +92,6 @@
+ DEBUG_PRINTK(__dev, KERN_DEBUG, "EEPROM recovery", __msg, ##__args)
+
+ /*
+- * Ring sizes.
+- * Ralink PCI devices demand the Frame size to be a multiple of 128 bytes.
+- * DATA_FRAME_SIZE is used for TX, RX, ATIM and PRIO rings.
+- * MGMT_FRAME_SIZE is used for the BEACON ring.
+- */
+-#define DATA_FRAME_SIZE 2432
+-#define MGMT_FRAME_SIZE 256
+-
+-/*
+- * Number of entries in a packet ring.
+- * PCI devices only need 1 Beacon entry,
+- * but USB devices require a second because they
+- * have to send a Guardian byte first.
+- */
+-#define RX_ENTRIES 12
+-#define TX_ENTRIES 12
+-#define ATIM_ENTRIES 1
+-#define BEACON_ENTRIES 2
+-
+-/*
+ * Standard timing and size defines.
+ * These values should follow the ieee80211 specifications.
+ */
+@@ -364,20 +345,22 @@ static inline int rt2x00_update_ant_rssi(struct link *link, int rssi)
+
+ /*
+ * Interface structure
+- * Configuration details about the current interface.
++ * Per interface configuration details, this structure
++ * is allocated as the private data for ieee80211_vif.
+ */
+-struct interface {
++struct rt2x00_intf {
+ /*
+- * Interface identification. The value is assigned
+- * to us by the 80211 stack, and is used to request
+- * new beacons.
++ * All fields within the rt2x00_intf structure
++ * must be protected with a spinlock.
+ */
+- struct ieee80211_vif *id;
++ spinlock_t lock;
+
+ /*
+- * Current working type (IEEE80211_IF_TYPE_*).
++ * BSS configuration. Copied from the structure
++ * passed to us through the bss_info_changed()
++ * callback funtion.
+ */
+- int type;
++ struct ieee80211_bss_conf conf;
+
+ /*
+ * MAC of the device.
+@@ -388,42 +371,60 @@ struct interface {
+ * BBSID of the AP to associate with.
+ */
+ u8 bssid[ETH_ALEN];
+-};
+
+-static inline int is_interface_present(struct interface *intf)
+-{
+- return !!intf->id;
+-}
++ /*
++ * Entry in the beacon queue which belongs to
++ * this interface. Each interface has its own
++ * dedicated beacon entry.
++ */
++ struct queue_entry *beacon;
++
++ /*
++ * Actions that needed rescheduling.
++ */
++ unsigned int delayed_flags;
++#define DELAYED_UPDATE_BEACON 0x00000001
++#define DELAYED_CONFIG_ERP 0x00000002
++#define DELAYED_LED_ASSOC 0x00000004
++};
+
+-static inline int is_interface_type(struct interface *intf, int type)
++static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif)
+ {
+- return intf->type == type;
++ return (struct rt2x00_intf *)vif->drv_priv;
+ }
+
+-/*
++/**
++ * struct hw_mode_spec: Hardware specifications structure
++ *
+ * Details about the supported modes, rates and channels
+ * of a particular chipset. This is used by rt2x00lib
+ * to build the ieee80211_hw_mode array for mac80211.
++ *
++ * @supported_bands: Bitmask contained the supported bands (2.4GHz, 5.2GHz).
++ * @supported_rates: Rate types which are supported (CCK, OFDM).
++ * @num_channels: Number of supported channels. This is used as array size
++ * for @tx_power_a, @tx_power_bg and @channels.
++ * channels: Device/chipset specific channel values (See &struct rf_channel).
++ * @tx_power_a: TX power values for all 5.2GHz channels (may be NULL).
++ * @tx_power_bg: TX power values for all 2.4GHz channels (may be NULL).
++ * @tx_power_default: Default TX power value to use when either
++ * @tx_power_a or @tx_power_bg is missing.
+ */
+ struct hw_mode_spec {
+- /*
+- * Number of modes, rates and channels.
+- */
+- int num_modes;
+- int num_rates;
+- int num_channels;
++ unsigned int supported_bands;
++#define SUPPORT_BAND_2GHZ 0x00000001
++#define SUPPORT_BAND_5GHZ 0x00000002
++
++ unsigned int supported_rates;
++#define SUPPORT_RATE_CCK 0x00000001
++#define SUPPORT_RATE_OFDM 0x00000002
++
++ unsigned int num_channels;
++ const struct rf_channel *channels;
+
+- /*
+- * txpower values.
+- */
+ const u8 *tx_power_a;
+ const u8 *tx_power_bg;
+ u8 tx_power_default;
+-
+- /*
+- * Device/chipset specific value.
+- */
+- const struct rf_channel *channels;
+ };
+
+ /*
+@@ -439,10 +440,10 @@ struct rt2x00lib_conf {
+
+ struct antenna_setup ant;
+
+- int phymode;
++ enum ieee80211_band band;
+
+- int basic_rates;
+- int slot_time;
++ u32 basic_rates;
++ u32 slot_time;
+
+ short sifs;
+ short pifs;
+@@ -451,6 +452,47 @@ struct rt2x00lib_conf {
+ };
+
+ /*
++ * Configuration structure for erp settings.
++ */
++struct rt2x00lib_erp {
++ int short_preamble;
++
++ int ack_timeout;
++ int ack_consume_time;
++};
++
++/*
++ * Configuration structure wrapper around the
++ * rt2x00 interface configuration handler.
++ */
++struct rt2x00intf_conf {
++ /*
++ * Interface type
++ */
++ enum ieee80211_if_types type;
++
++ /*
++ * TSF sync value, this is dependant on the operation type.
++ */
++ enum tsf_sync sync;
++
++ /*
++ * The MAC and BSSID addressess are simple array of bytes,
++ * these arrays are little endian, so when sending the addressess
++ * to the drivers, copy the it into a endian-signed variable.
++ *
++ * Note that all devices (except rt2500usb) have 32 bits
++ * register word sizes. This means that whatever variable we
++ * pass _must_ be a multiple of 32 bits. Otherwise the device
++ * might not accept what we are sending to it.
++ * This will also make it easier for the driver to write
++ * the data to the device.
++ */
++ __le32 mac[2];
++ __le32 bssid[2];
++};
++
++/*
+ * rt2x00lib callback functions.
+ */
+ struct rt2x00lib_ops {
+@@ -464,6 +506,7 @@ struct rt2x00lib_ops {
+ */
+ int (*probe_hw) (struct rt2x00_dev *rt2x00dev);
+ char *(*get_firmware_name) (struct rt2x00_dev *rt2x00dev);
++ u16 (*get_firmware_crc) (void *data, const size_t len);
+ int (*load_firmware) (struct rt2x00_dev *rt2x00dev, void *data,
+ const size_t len);
+
+@@ -474,12 +517,12 @@ struct rt2x00lib_ops {
+ void (*uninitialize) (struct rt2x00_dev *rt2x00dev);
+
+ /*
+- * Ring initialization handlers
++ * queue initialization handlers
+ */
+ void (*init_rxentry) (struct rt2x00_dev *rt2x00dev,
+- struct data_entry *entry);
++ struct queue_entry *entry);
+ void (*init_txentry) (struct rt2x00_dev *rt2x00dev,
+- struct data_entry *entry);
++ struct queue_entry *entry);
+
+ /*
+ * Radio control handlers.
+@@ -497,35 +540,40 @@ struct rt2x00lib_ops {
+ */
+ void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev,
+ struct sk_buff *skb,
+- struct txdata_entry_desc *desc,
++ struct txentry_desc *txdesc,
+ struct ieee80211_tx_control *control);
+ int (*write_tx_data) (struct rt2x00_dev *rt2x00dev,
+- struct data_ring *ring, struct sk_buff *skb,
++ struct data_queue *queue, struct sk_buff *skb,
+ struct ieee80211_tx_control *control);
+ int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev,
+ struct sk_buff *skb);
+ void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev,
+- unsigned int queue);
++ const unsigned int queue);
+
+ /*
+ * RX control handlers
+ */
+- void (*fill_rxdone) (struct data_entry *entry,
+- struct rxdata_entry_desc *desc);
++ void (*fill_rxdone) (struct queue_entry *entry,
++ struct rxdone_entry_desc *rxdesc);
+
+ /*
+ * Configuration handlers.
+ */
+- void (*config_mac_addr) (struct rt2x00_dev *rt2x00dev, __le32 *mac);
+- void (*config_bssid) (struct rt2x00_dev *rt2x00dev, __le32 *bssid);
+- void (*config_type) (struct rt2x00_dev *rt2x00dev, const int type,
+- const int tsf_sync);
+- void (*config_preamble) (struct rt2x00_dev *rt2x00dev,
+- const int short_preamble,
+- const int ack_timeout,
+- const int ack_consume_time);
+- void (*config) (struct rt2x00_dev *rt2x00dev, const unsigned int flags,
+- struct rt2x00lib_conf *libconf);
++ void (*config_filter) (struct rt2x00_dev *rt2x00dev,
++ const unsigned int filter_flags);
++ void (*config_intf) (struct rt2x00_dev *rt2x00dev,
++ struct rt2x00_intf *intf,
++ struct rt2x00intf_conf *conf,
++ const unsigned int flags);
++#define CONFIG_UPDATE_TYPE ( 1 << 1 )
++#define CONFIG_UPDATE_MAC ( 1 << 2 )
++#define CONFIG_UPDATE_BSSID ( 1 << 3 )
++
++ void (*config_erp) (struct rt2x00_dev *rt2x00dev,
++ struct rt2x00lib_erp *erp);
++ void (*config) (struct rt2x00_dev *rt2x00dev,
++ struct rt2x00lib_conf *libconf,
++ const unsigned int flags);
+ #define CONFIG_UPDATE_PHYMODE ( 1 << 1 )
+ #define CONFIG_UPDATE_CHANNEL ( 1 << 2 )
+ #define CONFIG_UPDATE_TXPOWER ( 1 << 3 )
+@@ -540,10 +588,14 @@ struct rt2x00lib_ops {
+ */
+ struct rt2x00_ops {
+ const char *name;
+- const unsigned int rxd_size;
+- const unsigned int txd_size;
++ const unsigned int max_sta_intf;
++ const unsigned int max_ap_intf;
+ const unsigned int eeprom_size;
+ const unsigned int rf_size;
++ const struct data_queue_desc *rx;
++ const struct data_queue_desc *tx;
++ const struct data_queue_desc *bcn;
++ const struct data_queue_desc *atim;
+ const struct rt2x00lib_ops *lib;
+ const struct ieee80211_ops *hw;
+ #ifdef CONFIG_RT2X00_LIB_DEBUGFS
+@@ -569,8 +621,11 @@ enum rt2x00_flags {
+ /*
+ * Driver features
+ */
++ DRIVER_SUPPORT_MIXED_INTERFACES,
+ DRIVER_REQUIRE_FIRMWARE,
+- DRIVER_REQUIRE_BEACON_RING,
++ DRIVER_REQUIRE_BEACON_GUARD,
++ DRIVER_REQUIRE_ATIM_QUEUE,
++ DRIVER_REQUIRE_SCHEDULED,
+
+ /*
+ * Driver configuration
+@@ -582,7 +637,6 @@ enum rt2x00_flags {
+ CONFIG_EXTERNAL_LNA_BG,
+ CONFIG_DOUBLE_ANTENNA,
+ CONFIG_DISABLE_LINK_TUNING,
+- CONFIG_SHORT_PREAMBLE,
+ };
+
+ /*
+@@ -597,8 +651,10 @@ struct rt2x00_dev {
+ * macro's should be used for correct typecasting.
+ */
+ void *dev;
+-#define rt2x00dev_pci(__dev) ( (struct pci_dev*)(__dev)->dev )
+-#define rt2x00dev_usb(__dev) ( (struct usb_interface*)(__dev)->dev )
++#define rt2x00dev_pci(__dev) ( (struct pci_dev *)(__dev)->dev )
++#define rt2x00dev_usb(__dev) ( (struct usb_interface *)(__dev)->dev )
++#define rt2x00dev_usb_dev(__dev)\
++ ( (struct usb_device *)interface_to_usbdev(rt2x00dev_usb(__dev)) )
+
+ /*
+ * Callback functions.
+@@ -609,18 +665,15 @@ struct rt2x00_dev {
+ * IEEE80211 control structure.
+ */
+ struct ieee80211_hw *hw;
+- struct ieee80211_hw_mode *hwmodes;
+- unsigned int curr_hwmode;
+-#define HWMODE_B 0
+-#define HWMODE_G 1
+-#define HWMODE_A 2
++ struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
++ enum ieee80211_band curr_band;
+
+ /*
+ * rfkill structure for RF state switching support.
+ * This will only be compiled in when required.
+ */
+ #ifdef CONFIG_RT2X00_LIB_RFKILL
+-unsigned long rfkill_state;
++ unsigned long rfkill_state;
+ #define RFKILL_STATE_ALLOCATED 1
+ #define RFKILL_STATE_REGISTERED 2
+ struct rfkill *rfkill;
+@@ -636,6 +689,17 @@ unsigned long rfkill_state;
+ #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+
+ /*
++ * LED structure for changing the LED status
++ * by mac8011 or the kernel.
++ */
++#ifdef CONFIG_RT2X00_LIB_LEDS
++ struct rt2x00_led led_radio;
++ struct rt2x00_led led_assoc;
++ struct rt2x00_led led_qual;
++ u16 led_mcu_reg;
++#endif /* CONFIG_RT2X00_LIB_LEDS */
++
++ /*
+ * Device flags.
+ * In these flags the current status and some
+ * of the device capabilities are stored.
+@@ -661,11 +725,13 @@ unsigned long rfkill_state;
+
+ /*
+ * Register pointers
+- * csr_addr: Base register address. (PCI)
+- * csr_cache: CSR cache for usb_control_msg. (USB)
++ * csr.base: CSR base register address. (PCI)
++ * csr.cache: CSR cache for usb_control_msg. (USB)
+ */
+- void __iomem *csr_addr;
+- void *csr_cache;
++ union csr {
++ void __iomem *base;
++ void *cache;
++ } csr;
+
+ /*
+ * Mutex to protect register accesses on USB devices.
+@@ -687,9 +753,14 @@ unsigned long rfkill_state;
+ unsigned int packet_filter;
+
+ /*
+- * Interface configuration.
++ * Interface details:
++ * - Open ap interface count.
++ * - Open sta interface count.
++ * - Association count.
+ */
+- struct interface interface;
++ unsigned int intf_ap_count;
++ unsigned int intf_sta_count;
++ unsigned int intf_associated;
+
+ /*
+ * Link quality
+@@ -722,16 +793,6 @@ unsigned long rfkill_state;
+ u16 tx_power;
+
+ /*
+- * LED register (for rt61pci & rt73usb).
+- */
+- u16 led_reg;
+-
+- /*
+- * Led mode (LED_MODE_*)
+- */
+- u8 led_mode;
+-
+- /*
+ * Rssi <-> Dbm offset
+ */
+ u8 rssi_offset;
+@@ -755,19 +816,18 @@ unsigned long rfkill_state;
+ /*
+ * Scheduled work.
+ */
+- struct work_struct beacon_work;
++ struct work_struct intf_work;
+ struct work_struct filter_work;
+- struct work_struct config_work;
+
+ /*
+- * Data ring arrays for RX, TX and Beacon.
+- * The Beacon array also contains the Atim ring
++ * Data queue arrays for RX, TX and Beacon.
++ * The Beacon array also contains the Atim queue
+ * if that is supported by the device.
+ */
+- int data_rings;
+- struct data_ring *rx;
+- struct data_ring *tx;
+- struct data_ring *bcn;
++ int data_queues;
++ struct data_queue *rx;
++ struct data_queue *tx;
++ struct data_queue *bcn;
+
+ /*
+ * Firmware image.
+@@ -776,37 +836,6 @@ unsigned long rfkill_state;
+ };
+
+ /*
+- * For-each loop for the ring array.
+- * All rings have been allocated as a single array,
+- * this means we can create a very simply loop macro
+- * that is capable of looping through all rings.
+- * ring_end(), txring_end() and ring_loop() are helper macro's which
+- * should not be used directly. Instead the following should be used:
+- * ring_for_each() - Loops through all rings (RX, TX, Beacon & Atim)
+- * txring_for_each() - Loops through TX data rings (TX only)
+- * txringall_for_each() - Loops through all TX rings (TX, Beacon & Atim)
+- */
+-#define ring_end(__dev) \
+- &(__dev)->rx[(__dev)->data_rings]
+-
+-#define txring_end(__dev) \
+- &(__dev)->tx[(__dev)->hw->queues]
+-
+-#define ring_loop(__entry, __start, __end) \
+- for ((__entry) = (__start); \
+- prefetch(&(__entry)[1]), (__entry) != (__end); \
+- (__entry) = &(__entry)[1])
+-
+-#define ring_for_each(__dev, __entry) \
+- ring_loop(__entry, (__dev)->rx, ring_end(__dev))
+-
+-#define txring_for_each(__dev, __entry) \
+- ring_loop(__entry, (__dev)->tx, txring_end(__dev))
+-
+-#define txringall_for_each(__dev, __entry) \
+- ring_loop(__entry, (__dev)->tx, ring_end(__dev))
+-
+-/*
+ * Generic RF access.
+ * The RF is being accessed by word index.
+ */
+@@ -898,20 +927,43 @@ static inline u16 get_duration_res(const unsigned int size, const u8 rate)
+ return ((size * 8 * 10) % rate);
+ }
+
+-/*
+- * Library functions.
++/**
++ * rt2x00queue_get_queue - Convert mac80211 queue index to rt2x00 queue
++ * @rt2x00dev: Pointer to &struct rt2x00_dev.
++ * @queue: mac80211/rt2x00 queue index
++ * (see &enum ieee80211_tx_queue and &enum rt2x00_bcn_queue).
++ */
++struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,
++ const unsigned int queue);
++
++/**
++ * rt2x00queue_get_entry - Get queue entry where the given index points to.
++ * @rt2x00dev: Pointer to &struct rt2x00_dev.
++ * @index: Index identifier for obtaining the correct index.
++ */
++struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
++ enum queue_index index);
++
++/**
++ * rt2x00queue_index_inc - Index incrementation function
++ * @queue: Queue (&struct data_queue) to perform the action on.
++ * @action: Index type (&enum queue_index) to perform the action on.
++ *
++ * This function will increase the requested index on the queue,
++ * it will grab the appropriate locks and handle queue overflow events by
++ * resetting the index to the start of the queue.
+ */
+-struct data_ring *rt2x00lib_get_ring(struct rt2x00_dev *rt2x00dev,
+- const unsigned int queue);
++void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index);
++
+
+ /*
+ * Interrupt context handlers.
+ */
+ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev);
+-void rt2x00lib_txdone(struct data_entry *entry,
+- const int status, const int retry);
+-void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb,
+- struct rxdata_entry_desc *desc);
++void rt2x00lib_txdone(struct queue_entry *entry,
++ struct txdone_entry_desc *txdesc);
++void rt2x00lib_rxdone(struct queue_entry *entry,
++ struct rxdone_entry_desc *rxdesc);
+
+ /*
+ * TX descriptor initializer
+@@ -935,6 +987,10 @@ int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
+ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_if_conf *conf);
++void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
++ unsigned int changed_flags,
++ unsigned int *total_flags,
++ int mc_count, struct dev_addr_list *mc_list);
+ int rt2x00mac_get_stats(struct ieee80211_hw *hw,
+ struct ieee80211_low_level_stats *stats);
+ int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw,
+diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
+index 07adc57..a9930a0 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00config.c
++++ b/drivers/net/wireless/rt2x00/rt2x00config.c
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+@@ -29,64 +29,78 @@
+ #include "rt2x00.h"
+ #include "rt2x00lib.h"
+
+-
+-/*
+- * The MAC and BSSID addressess are simple array of bytes,
+- * these arrays are little endian, so when sending the addressess
+- * to the drivers, copy the it into a endian-signed variable.
+- *
+- * Note that all devices (except rt2500usb) have 32 bits
+- * register word sizes. This means that whatever variable we
+- * pass _must_ be a multiple of 32 bits. Otherwise the device
+- * might not accept what we are sending to it.
+- * This will also make it easier for the driver to write
+- * the data to the device.
+- *
+- * Also note that when NULL is passed as address the
+- * we will send 00:00:00:00:00 to the device to clear the address.
+- * This will prevent the device being confused when it wants
+- * to ACK frames or consideres itself associated.
+- */
+-void rt2x00lib_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *mac)
+-{
+- __le32 reg[2];
+-
+- memset(®, 0, sizeof(reg));
+- if (mac)
+- memcpy(®, mac, ETH_ALEN);
+-
+- rt2x00dev->ops->lib->config_mac_addr(rt2x00dev, ®[0]);
+-}
+-
+-void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid)
++void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
++ struct rt2x00_intf *intf,
++ enum ieee80211_if_types type,
++ u8 *mac, u8 *bssid)
+ {
+- __le32 reg[2];
++ struct rt2x00intf_conf conf;
++ unsigned int flags = 0;
+
+- memset(®, 0, sizeof(reg));
+- if (bssid)
+- memcpy(®, bssid, ETH_ALEN);
+-
+- rt2x00dev->ops->lib->config_bssid(rt2x00dev, ®[0]);
+-}
+-
+-void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type)
+-{
+- int tsf_sync;
++ conf.type = type;
+
+ switch (type) {
+ case IEEE80211_IF_TYPE_IBSS:
+ case IEEE80211_IF_TYPE_AP:
+- tsf_sync = TSF_SYNC_BEACON;
++ conf.sync = TSF_SYNC_BEACON;
+ break;
+ case IEEE80211_IF_TYPE_STA:
+- tsf_sync = TSF_SYNC_INFRA;
++ conf.sync = TSF_SYNC_INFRA;
+ break;
+ default:
+- tsf_sync = TSF_SYNC_NONE;
++ conf.sync = TSF_SYNC_NONE;
+ break;
+ }
+
+- rt2x00dev->ops->lib->config_type(rt2x00dev, type, tsf_sync);
++ /*
++ * Note that when NULL is passed as address we will send
++ * 00:00:00:00:00 to the device to clear the address.
++ * This will prevent the device being confused when it wants
++ * to ACK frames or consideres itself associated.
++ */
++ memset(&conf.mac, 0, sizeof(conf.mac));
++ if (mac)
++ memcpy(&conf.mac, mac, ETH_ALEN);
++
++ memset(&conf.bssid, 0, sizeof(conf.bssid));
++ if (bssid)
++ memcpy(&conf.bssid, bssid, ETH_ALEN);
++
++ flags |= CONFIG_UPDATE_TYPE;
++ if (mac || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count))
++ flags |= CONFIG_UPDATE_MAC;
++ if (bssid || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count))
++ flags |= CONFIG_UPDATE_BSSID;
++
++ rt2x00dev->ops->lib->config_intf(rt2x00dev, intf, &conf, flags);
++}
++
++void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
++ struct rt2x00_intf *intf,
++ struct ieee80211_bss_conf *bss_conf)
++{
++ struct rt2x00lib_erp erp;
++
++ memset(&erp, 0, sizeof(erp));
++
++ erp.short_preamble = bss_conf->use_short_preamble;
++ erp.ack_timeout = PLCP + get_duration(ACK_SIZE, 10);
++ erp.ack_consume_time = SIFS + PLCP + get_duration(ACK_SIZE, 10);
++
++ if (rt2x00dev->hw->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME)
++ erp.ack_timeout += SHORT_DIFS;
++ else
++ erp.ack_timeout += DIFS;
++
++ if (bss_conf->use_short_preamble) {
++ erp.ack_timeout += SHORT_PREAMBLE;
++ erp.ack_consume_time += SHORT_PREAMBLE;
++ } else {
++ erp.ack_timeout += PREAMBLE;
++ erp.ack_consume_time += PREAMBLE;
++ }
++
++ rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp);
+ }
+
+ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
+@@ -113,7 +127,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
+ * The latter is required since we need to recalibrate the
+ * noise-sensitivity ratio for the new setup.
+ */
+- rt2x00dev->ops->lib->config(rt2x00dev, CONFIG_UPDATE_ANTENNA, &libconf);
++ rt2x00dev->ops->lib->config(rt2x00dev, &libconf, CONFIG_UPDATE_ANTENNA);
+ rt2x00lib_reset_link_tuner(rt2x00dev);
+
+ rt2x00dev->link.ant.active.rx = libconf.ant.rx;
+@@ -123,12 +137,26 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
+ rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK);
+ }
+
++static u32 rt2x00lib_get_basic_rates(struct ieee80211_supported_band *band)
++{
++ const struct rt2x00_rate *rate;
++ unsigned int i;
++ u32 mask = 0;
++
++ for (i = 0; i < band->n_bitrates; i++) {
++ rate = rt2x00_get_rate(band->bitrates[i].hw_value);
++ if (rate->flags & DEV_RATE_BASIC)
++ mask |= rate->ratemask;
++ }
++
++ return mask;
++}
++
+ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_conf *conf, const int force_config)
+ {
+ struct rt2x00lib_conf libconf;
+- struct ieee80211_hw_mode *mode;
+- struct ieee80211_rate *rate;
++ struct ieee80211_supported_band *band;
+ struct antenna_setup *default_ant = &rt2x00dev->default_ant;
+ struct antenna_setup *active_ant = &rt2x00dev->link.ant.active;
+ int flags = 0;
+@@ -147,9 +175,9 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
+ * Check which configuration options have been
+ * updated and should be send to the device.
+ */
+- if (rt2x00dev->rx_status.phymode != conf->phymode)
++ if (rt2x00dev->rx_status.band != conf->channel->band)
+ flags |= CONFIG_UPDATE_PHYMODE;
+- if (rt2x00dev->rx_status.channel != conf->channel)
++ if (rt2x00dev->rx_status.freq != conf->channel->center_freq)
+ flags |= CONFIG_UPDATE_CHANNEL;
+ if (rt2x00dev->tx_power != conf->power_level)
+ flags |= CONFIG_UPDATE_TXPOWER;
+@@ -204,33 +232,15 @@ config:
+ memset(&libconf, 0, sizeof(libconf));
+
+ if (flags & CONFIG_UPDATE_PHYMODE) {
+- switch (conf->phymode) {
+- case MODE_IEEE80211A:
+- libconf.phymode = HWMODE_A;
+- break;
+- case MODE_IEEE80211B:
+- libconf.phymode = HWMODE_B;
+- break;
+- case MODE_IEEE80211G:
+- libconf.phymode = HWMODE_G;
+- break;
+- default:
+- ERROR(rt2x00dev,
+- "Attempt to configure unsupported mode (%d)"
+- "Defaulting to 802.11b", conf->phymode);
+- libconf.phymode = HWMODE_B;
+- }
+-
+- mode = &rt2x00dev->hwmodes[libconf.phymode];
+- rate = &mode->rates[mode->num_rates - 1];
+-
+- libconf.basic_rates =
+- DEVICE_GET_RATE_FIELD(rate->val, RATEMASK) & DEV_BASIC_RATEMASK;
++ band = &rt2x00dev->bands[conf->channel->band];
++
++ libconf.band = conf->channel->band;
++ libconf.basic_rates = rt2x00lib_get_basic_rates(band);
+ }
+
+ if (flags & CONFIG_UPDATE_CHANNEL) {
+ memcpy(&libconf.rf,
+- &rt2x00dev->spec.channels[conf->channel_val],
++ &rt2x00dev->spec.channels[conf->channel->hw_value],
+ sizeof(libconf.rf));
+ }
+
+@@ -266,7 +276,7 @@ config:
+ /*
+ * Start configuration.
+ */
+- rt2x00dev->ops->lib->config(rt2x00dev, flags, &libconf);
++ rt2x00dev->ops->lib->config(rt2x00dev, &libconf, flags);
+
+ /*
+ * Some configuration changes affect the link quality
+@@ -276,12 +286,11 @@ config:
+ rt2x00lib_reset_link_tuner(rt2x00dev);
+
+ if (flags & CONFIG_UPDATE_PHYMODE) {
+- rt2x00dev->curr_hwmode = libconf.phymode;
+- rt2x00dev->rx_status.phymode = conf->phymode;
++ rt2x00dev->curr_band = conf->channel->band;
++ rt2x00dev->rx_status.band = conf->channel->band;
+ }
+
+- rt2x00dev->rx_status.freq = conf->freq;
+- rt2x00dev->rx_status.channel = conf->channel;
++ rt2x00dev->rx_status.freq = conf->channel->center_freq;
+ rt2x00dev->tx_power = conf->power_level;
+
+ if (flags & CONFIG_UPDATE_ANTENNA) {
+diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
+index b44a9f4..bfab3b8 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
++++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+@@ -33,7 +33,7 @@
+ #include "rt2x00lib.h"
+ #include "rt2x00dump.h"
+
+-#define PRINT_LINE_LEN_MAX 32
++#define MAX_LINE_LENGTH 64
+
+ struct rt2x00debug_intf {
+ /*
+@@ -60,8 +60,9 @@ struct rt2x00debug_intf {
+ * - eeprom offset/value files
+ * - bbp offset/value files
+ * - rf offset/value files
+- * - frame dump folder
++ * - queue folder
+ * - frame dump file
++ * - queue stats file
+ */
+ struct dentry *driver_folder;
+ struct dentry *driver_entry;
+@@ -76,8 +77,9 @@ struct rt2x00debug_intf {
+ struct dentry *bbp_val_entry;
+ struct dentry *rf_off_entry;
+ struct dentry *rf_val_entry;
+- struct dentry *frame_folder;
+- struct dentry *frame_dump_entry;
++ struct dentry *queue_folder;
++ struct dentry *queue_frame_dump_entry;
++ struct dentry *queue_stats_entry;
+
+ /*
+ * The frame dump file only allows a single reader,
+@@ -116,7 +118,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
+ struct sk_buff *skb)
+ {
+ struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
+- struct skb_desc *desc = get_skb_desc(skb);
++ struct skb_frame_desc *desc = get_skb_frame_desc(skb);
+ struct sk_buff *skbcopy;
+ struct rt2x00dump_hdr *dump_hdr;
+ struct timeval timestamp;
+@@ -147,7 +149,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
+ dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf);
+ dump_hdr->chip_rev = cpu_to_le32(rt2x00dev->chip.rev);
+ dump_hdr->type = cpu_to_le16(desc->frame_type);
+- dump_hdr->ring_index = desc->ring->queue_idx;
++ dump_hdr->queue_index = desc->entry->queue->qid;
+ dump_hdr->entry_index = desc->entry->entry_idx;
+ dump_hdr->timestamp_sec = cpu_to_le32(timestamp.tv_sec);
+ dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec);
+@@ -186,7 +188,7 @@ static int rt2x00debug_file_release(struct inode *inode, struct file *file)
+ return 0;
+ }
+
+-static int rt2x00debug_open_ring_dump(struct inode *inode, struct file *file)
++static int rt2x00debug_open_queue_dump(struct inode *inode, struct file *file)
+ {
+ struct rt2x00debug_intf *intf = inode->i_private;
+ int retval;
+@@ -203,7 +205,7 @@ static int rt2x00debug_open_ring_dump(struct inode *inode, struct file *file)
+ return 0;
+ }
+
+-static int rt2x00debug_release_ring_dump(struct inode *inode, struct file *file)
++static int rt2x00debug_release_queue_dump(struct inode *inode, struct file *file)
+ {
+ struct rt2x00debug_intf *intf = inode->i_private;
+
+@@ -214,10 +216,10 @@ static int rt2x00debug_release_ring_dump(struct inode *inode, struct file *file)
+ return rt2x00debug_file_release(inode, file);
+ }
+
+-static ssize_t rt2x00debug_read_ring_dump(struct file *file,
+- char __user *buf,
+- size_t length,
+- loff_t *offset)
++static ssize_t rt2x00debug_read_queue_dump(struct file *file,
++ char __user *buf,
++ size_t length,
++ loff_t *offset)
+ {
+ struct rt2x00debug_intf *intf = file->private_data;
+ struct sk_buff *skb;
+@@ -248,8 +250,8 @@ exit:
+ return status;
+ }
+
+-static unsigned int rt2x00debug_poll_ring_dump(struct file *file,
+- poll_table *wait)
++static unsigned int rt2x00debug_poll_queue_dump(struct file *file,
++ poll_table *wait)
+ {
+ struct rt2x00debug_intf *intf = file->private_data;
+
+@@ -261,12 +263,68 @@ static unsigned int rt2x00debug_poll_ring_dump(struct file *file,
+ return 0;
+ }
+
+-static const struct file_operations rt2x00debug_fop_ring_dump = {
++static const struct file_operations rt2x00debug_fop_queue_dump = {
+ .owner = THIS_MODULE,
+- .read = rt2x00debug_read_ring_dump,
+- .poll = rt2x00debug_poll_ring_dump,
+- .open = rt2x00debug_open_ring_dump,
+- .release = rt2x00debug_release_ring_dump,
++ .read = rt2x00debug_read_queue_dump,
++ .poll = rt2x00debug_poll_queue_dump,
++ .open = rt2x00debug_open_queue_dump,
++ .release = rt2x00debug_release_queue_dump,
++};
++
++static ssize_t rt2x00debug_read_queue_stats(struct file *file,
++ char __user *buf,
++ size_t length,
++ loff_t *offset)
++{
++ struct rt2x00debug_intf *intf = file->private_data;
++ struct data_queue *queue;
++ unsigned long irqflags;
++ unsigned int lines = 1 + intf->rt2x00dev->data_queues;
++ size_t size;
++ char *data;
++ char *temp;
++
++ if (*offset)
++ return 0;
++
++ data = kzalloc(lines * MAX_LINE_LENGTH, GFP_KERNEL);
++ if (!data)
++ return -ENOMEM;
++
++ temp = data +
++ sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdone\tcrypto\n");
++
++ queue_for_each(intf->rt2x00dev, queue) {
++ spin_lock_irqsave(&queue->lock, irqflags);
++
++ temp += sprintf(temp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n", queue->qid,
++ queue->count, queue->limit, queue->length,
++ queue->index[Q_INDEX],
++ queue->index[Q_INDEX_DONE],
++ queue->index[Q_INDEX_CRYPTO]);
++
++ spin_unlock_irqrestore(&queue->lock, irqflags);
++ }
++
++ size = strlen(data);
++ size = min(size, length);
++
++ if (copy_to_user(buf, data, size)) {
++ kfree(data);
++ return -EFAULT;
++ }
++
++ kfree(data);
++
++ *offset += size;
++ return size;
++}
++
++static const struct file_operations rt2x00debug_fop_queue_stats = {
++ .owner = THIS_MODULE,
++ .read = rt2x00debug_read_queue_stats,
++ .open = rt2x00debug_file_open,
++ .release = rt2x00debug_file_release,
+ };
+
+ #define RT2X00DEBUGFS_OPS_READ(__name, __format, __type) \
+@@ -386,7 +444,7 @@ static struct dentry *rt2x00debug_create_file_driver(const char *name,
+ {
+ char *data;
+
+- data = kzalloc(3 * PRINT_LINE_LEN_MAX, GFP_KERNEL);
++ data = kzalloc(3 * MAX_LINE_LENGTH, GFP_KERNEL);
+ if (!data)
+ return NULL;
+
+@@ -409,7 +467,7 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name,
+ const struct rt2x00debug *debug = intf->debug;
+ char *data;
+
+- data = kzalloc(8 * PRINT_LINE_LEN_MAX, GFP_KERNEL);
++ data = kzalloc(8 * MAX_LINE_LENGTH, GFP_KERNEL);
+ if (!data)
+ return NULL;
+
+@@ -496,20 +554,24 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
+
+ #undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY
+
+- intf->frame_folder =
+- debugfs_create_dir("frame", intf->driver_folder);
+- if (IS_ERR(intf->frame_folder))
++ intf->queue_folder =
++ debugfs_create_dir("queue", intf->driver_folder);
++ if (IS_ERR(intf->queue_folder))
+ goto exit;
+
+- intf->frame_dump_entry =
+- debugfs_create_file("dump", S_IRUGO, intf->frame_folder,
+- intf, &rt2x00debug_fop_ring_dump);
+- if (IS_ERR(intf->frame_dump_entry))
++ intf->queue_frame_dump_entry =
++ debugfs_create_file("dump", S_IRUGO, intf->queue_folder,
++ intf, &rt2x00debug_fop_queue_dump);
++ if (IS_ERR(intf->queue_frame_dump_entry))
+ goto exit;
+
+ skb_queue_head_init(&intf->frame_dump_skbqueue);
+ init_waitqueue_head(&intf->frame_dump_waitqueue);
+
++ intf->queue_stats_entry =
++ debugfs_create_file("queue", S_IRUGO, intf->queue_folder,
++ intf, &rt2x00debug_fop_queue_stats);
++
+ return;
+
+ exit:
+@@ -528,8 +590,9 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
+
+ skb_queue_purge(&intf->frame_dump_skbqueue);
+
+- debugfs_remove(intf->frame_dump_entry);
+- debugfs_remove(intf->frame_folder);
++ debugfs_remove(intf->queue_stats_entry);
++ debugfs_remove(intf->queue_frame_dump_entry);
++ debugfs_remove(intf->queue_folder);
+ debugfs_remove(intf->rf_val_entry);
+ debugfs_remove(intf->rf_off_entry);
+ debugfs_remove(intf->bbp_val_entry);
+diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.h b/drivers/net/wireless/rt2x00/rt2x00debug.h
+index d37efbd..c4ce895 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00debug.h
++++ b/drivers/net/wireless/rt2x00/rt2x00debug.h
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
+index e873a39..f8fe7a1 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+@@ -31,34 +31,6 @@
+ #include "rt2x00dump.h"
+
+ /*
+- * Ring handler.
+- */
+-struct data_ring *rt2x00lib_get_ring(struct rt2x00_dev *rt2x00dev,
+- const unsigned int queue)
+-{
+- int beacon = test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags);
+-
+- /*
+- * Check if we are requesting a reqular TX ring,
+- * or if we are requesting a Beacon or Atim ring.
+- * For Atim rings, we should check if it is supported.
+- */
+- if (queue < rt2x00dev->hw->queues && rt2x00dev->tx)
+- return &rt2x00dev->tx[queue];
+-
+- if (!rt2x00dev->bcn || !beacon)
+- return NULL;
+-
+- if (queue == IEEE80211_TX_QUEUE_BEACON)
+- return &rt2x00dev->bcn[0];
+- else if (queue == IEEE80211_TX_QUEUE_AFTER_BEACON)
+- return &rt2x00dev->bcn[1];
+-
+- return NULL;
+-}
+-EXPORT_SYMBOL_GPL(rt2x00lib_get_ring);
+-
+-/*
+ * Link tuning handlers
+ */
+ void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev)
+@@ -113,46 +85,6 @@ static void rt2x00lib_stop_link_tuner(struct rt2x00_dev *rt2x00dev)
+ }
+
+ /*
+- * Ring initialization
+- */
+-static void rt2x00lib_init_rxrings(struct rt2x00_dev *rt2x00dev)
+-{
+- struct data_ring *ring = rt2x00dev->rx;
+- unsigned int i;
+-
+- if (!rt2x00dev->ops->lib->init_rxentry)
+- return;
+-
+- if (ring->data_addr)
+- memset(ring->data_addr, 0, rt2x00_get_ring_size(ring));
+-
+- for (i = 0; i < ring->stats.limit; i++)
+- rt2x00dev->ops->lib->init_rxentry(rt2x00dev, &ring->entry[i]);
+-
+- rt2x00_ring_index_clear(ring);
+-}
+-
+-static void rt2x00lib_init_txrings(struct rt2x00_dev *rt2x00dev)
+-{
+- struct data_ring *ring;
+- unsigned int i;
+-
+- if (!rt2x00dev->ops->lib->init_txentry)
+- return;
+-
+- txringall_for_each(rt2x00dev, ring) {
+- if (ring->data_addr)
+- memset(ring->data_addr, 0, rt2x00_get_ring_size(ring));
+-
+- for (i = 0; i < ring->stats.limit; i++)
+- rt2x00dev->ops->lib->init_txentry(rt2x00dev,
+- &ring->entry[i]);
+-
+- rt2x00_ring_index_clear(ring);
+- }
+-}
+-
+-/*
+ * Radio control handlers.
+ */
+ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
+@@ -168,19 +100,21 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
+ return 0;
+
+ /*
+- * Initialize all data rings.
++ * Initialize all data queues.
+ */
+- rt2x00lib_init_rxrings(rt2x00dev);
+- rt2x00lib_init_txrings(rt2x00dev);
++ rt2x00queue_init_rx(rt2x00dev);
++ rt2x00queue_init_tx(rt2x00dev);
+
+ /*
+ * Enable radio.
+ */
+- status = rt2x00dev->ops->lib->set_device_state(rt2x00dev,
+- STATE_RADIO_ON);
++ status =
++ rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_ON);
+ if (status)
+ return status;
+
++ rt2x00leds_led_radio(rt2x00dev, true);
++
+ __set_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags);
+
+ /*
+@@ -204,12 +138,10 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
+ /*
+ * Stop all scheduled work.
+ */
+- if (work_pending(&rt2x00dev->beacon_work))
+- cancel_work_sync(&rt2x00dev->beacon_work);
++ if (work_pending(&rt2x00dev->intf_work))
++ cancel_work_sync(&rt2x00dev->intf_work);
+ if (work_pending(&rt2x00dev->filter_work))
+ cancel_work_sync(&rt2x00dev->filter_work);
+- if (work_pending(&rt2x00dev->config_work))
+- cancel_work_sync(&rt2x00dev->config_work);
+
+ /*
+ * Stop the TX queues.
+@@ -225,6 +157,7 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
+ * Disable radio.
+ */
+ rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_OFF);
++ rt2x00leds_led_radio(rt2x00dev, false);
+ }
+
+ void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state)
+@@ -241,7 +174,7 @@ void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state)
+ * When we are enabling the RX, we should also start the link tuner.
+ */
+ if (state == STATE_RADIO_RX_ON &&
+- is_interface_present(&rt2x00dev->interface))
++ (rt2x00dev->intf_ap_count || rt2x00dev->intf_sta_count))
+ rt2x00lib_start_link_tuner(rt2x00dev);
+ }
+
+@@ -449,6 +382,11 @@ static void rt2x00lib_link_tuner(struct work_struct *work)
+ rt2x00lib_precalculate_link_signal(&rt2x00dev->link.qual);
+
+ /*
++ * Send a signal to the led to update the led signal strength.
++ */
++ rt2x00leds_led_quality(rt2x00dev, rt2x00dev->link.qual.avg_rssi);
++
++ /*
+ * Evaluate antenna setup, make this the last step since this could
+ * possibly reset some statistics.
+ */
+@@ -466,59 +404,76 @@ static void rt2x00lib_packetfilter_scheduled(struct work_struct *work)
+ {
+ struct rt2x00_dev *rt2x00dev =
+ container_of(work, struct rt2x00_dev, filter_work);
+- unsigned int filter = rt2x00dev->packet_filter;
++
++ rt2x00dev->ops->lib->config_filter(rt2x00dev, rt2x00dev->packet_filter);
++}
++
++static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
++ struct ieee80211_vif *vif)
++{
++ struct rt2x00_dev *rt2x00dev = data;
++ struct rt2x00_intf *intf = vif_to_intf(vif);
++ struct sk_buff *skb;
++ struct ieee80211_tx_control control;
++ struct ieee80211_bss_conf conf;
++ int delayed_flags;
+
+ /*
+- * Since we had stored the filter inside interface.filter,
+- * we should now clear that field. Otherwise the driver will
+- * assume nothing has changed (*total_flags will be compared
+- * to interface.filter to determine if any action is required).
++ * Copy all data we need during this action under the protection
++ * of a spinlock. Otherwise race conditions might occur which results
++ * into an invalid configuration.
+ */
+- rt2x00dev->packet_filter = 0;
++ spin_lock(&intf->lock);
++
++ memcpy(&conf, &intf->conf, sizeof(conf));
++ delayed_flags = intf->delayed_flags;
++ intf->delayed_flags = 0;
+
+- rt2x00dev->ops->hw->configure_filter(rt2x00dev->hw,
+- filter, &filter, 0, NULL);
++ spin_unlock(&intf->lock);
++
++ if (delayed_flags & DELAYED_UPDATE_BEACON) {
++ skb = ieee80211_beacon_get(rt2x00dev->hw, vif, &control);
++ if (skb && rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw,
++ skb, &control))
++ dev_kfree_skb(skb);
++ }
++
++ if (delayed_flags & DELAYED_CONFIG_ERP)
++ rt2x00lib_config_erp(rt2x00dev, intf, &intf->conf);
++
++ if (delayed_flags & DELAYED_LED_ASSOC)
++ rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated);
+ }
+
+-static void rt2x00lib_configuration_scheduled(struct work_struct *work)
++static void rt2x00lib_intf_scheduled(struct work_struct *work)
+ {
+ struct rt2x00_dev *rt2x00dev =
+- container_of(work, struct rt2x00_dev, config_work);
+- struct ieee80211_bss_conf bss_conf;
+-
+- bss_conf.use_short_preamble =
+- test_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags);
++ container_of(work, struct rt2x00_dev, intf_work);
+
+ /*
+- * FIXME: shouldn't invoke it this way because all other contents
+- * of bss_conf is invalid.
++ * Iterate over each interface and perform the
++ * requested configurations.
+ */
+- rt2x00mac_bss_info_changed(rt2x00dev->hw, rt2x00dev->interface.id,
+- &bss_conf, BSS_CHANGED_ERP_PREAMBLE);
++ ieee80211_iterate_active_interfaces(rt2x00dev->hw,
++ rt2x00lib_intf_scheduled_iter,
++ rt2x00dev);
+ }
+
+ /*
+ * Interrupt context handlers.
+ */
+-static void rt2x00lib_beacondone_scheduled(struct work_struct *work)
++static void rt2x00lib_beacondone_iter(void *data, u8 *mac,
++ struct ieee80211_vif *vif)
+ {
+- struct rt2x00_dev *rt2x00dev =
+- container_of(work, struct rt2x00_dev, beacon_work);
+- struct data_ring *ring =
+- rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
+- struct data_entry *entry = rt2x00_get_data_entry(ring);
+- struct sk_buff *skb;
++ struct rt2x00_intf *intf = vif_to_intf(vif);
+
+- skb = ieee80211_beacon_get(rt2x00dev->hw,
+- rt2x00dev->interface.id,
+- &entry->tx_status.control);
+- if (!skb)
++ if (vif->type != IEEE80211_IF_TYPE_AP &&
++ vif->type != IEEE80211_IF_TYPE_IBSS)
+ return;
+
+- rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb,
+- &entry->tx_status.control);
+-
+- dev_kfree_skb(skb);
++ spin_lock(&intf->lock);
++ intf->delayed_flags |= DELAYED_UPDATE_BEACON;
++ spin_unlock(&intf->lock);
+ }
+
+ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
+@@ -526,116 +481,140 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
+ if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
+ return;
+
+- queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->beacon_work);
++ ieee80211_iterate_active_interfaces(rt2x00dev->hw,
++ rt2x00lib_beacondone_iter,
++ rt2x00dev);
++
++ queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work);
+ }
+ EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
+
+-void rt2x00lib_txdone(struct data_entry *entry,
+- const int status, const int retry)
++void rt2x00lib_txdone(struct queue_entry *entry,
++ struct txdone_entry_desc *txdesc)
+ {
+- struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev;
+- struct ieee80211_tx_status *tx_status = &entry->tx_status;
+- struct ieee80211_low_level_stats *stats = &rt2x00dev->low_level_stats;
+- int success = !!(status == TX_SUCCESS || status == TX_SUCCESS_RETRY);
+- int fail = !!(status == TX_FAIL_RETRY || status == TX_FAIL_INVALID ||
+- status == TX_FAIL_OTHER);
++ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
++ struct skb_frame_desc *skbdesc;
++ struct ieee80211_tx_status tx_status;
++ int success = !!(txdesc->status == TX_SUCCESS ||
++ txdesc->status == TX_SUCCESS_RETRY);
++ int fail = !!(txdesc->status == TX_FAIL_RETRY ||
++ txdesc->status == TX_FAIL_INVALID ||
++ txdesc->status == TX_FAIL_OTHER);
+
+ /*
+ * Update TX statistics.
+ */
+- tx_status->flags = 0;
+- tx_status->ack_signal = 0;
+- tx_status->excessive_retries = (status == TX_FAIL_RETRY);
+- tx_status->retry_count = retry;
+ rt2x00dev->link.qual.tx_success += success;
+- rt2x00dev->link.qual.tx_failed += retry + fail;
++ rt2x00dev->link.qual.tx_failed += txdesc->retry + fail;
++
++ /*
++ * Initialize TX status
++ */
++ tx_status.flags = 0;
++ tx_status.ack_signal = 0;
++ tx_status.excessive_retries = (txdesc->status == TX_FAIL_RETRY);
++ tx_status.retry_count = txdesc->retry;
++ memcpy(&tx_status.control, txdesc->control, sizeof(*txdesc->control));
+
+- if (!(tx_status->control.flags & IEEE80211_TXCTL_NO_ACK)) {
++ if (!(tx_status.control.flags & IEEE80211_TXCTL_NO_ACK)) {
+ if (success)
+- tx_status->flags |= IEEE80211_TX_STATUS_ACK;
++ tx_status.flags |= IEEE80211_TX_STATUS_ACK;
+ else
+- stats->dot11ACKFailureCount++;
++ rt2x00dev->low_level_stats.dot11ACKFailureCount++;
+ }
+
+- tx_status->queue_length = entry->ring->stats.limit;
+- tx_status->queue_number = tx_status->control.queue;
++ tx_status.queue_length = entry->queue->limit;
++ tx_status.queue_number = tx_status.control.queue;
+
+- if (tx_status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) {
++ if (tx_status.control.flags & IEEE80211_TXCTL_USE_RTS_CTS) {
+ if (success)
+- stats->dot11RTSSuccessCount++;
++ rt2x00dev->low_level_stats.dot11RTSSuccessCount++;
+ else
+- stats->dot11RTSFailureCount++;
++ rt2x00dev->low_level_stats.dot11RTSFailureCount++;
+ }
+
+ /*
+- * Send the tx_status to mac80211 & debugfs.
+- * mac80211 will clean up the skb structure.
++ * Send the tx_status to debugfs. Only send the status report
++ * to mac80211 when the frame originated from there. If this was
++ * a extra frame coming through a mac80211 library call (RTS/CTS)
++ * then we should not send the status report back.
++ * If send to mac80211, mac80211 will clean up the skb structure,
++ * otherwise we have to do it ourself.
+ */
+- get_skb_desc(entry->skb)->frame_type = DUMP_FRAME_TXDONE;
++ skbdesc = get_skb_frame_desc(entry->skb);
++ skbdesc->frame_type = DUMP_FRAME_TXDONE;
++
+ rt2x00debug_dump_frame(rt2x00dev, entry->skb);
+- ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb, tx_status);
++
++ if (!(skbdesc->flags & FRAME_DESC_DRIVER_GENERATED))
++ ieee80211_tx_status_irqsafe(rt2x00dev->hw,
++ entry->skb, &tx_status);
++ else
++ dev_kfree_skb(entry->skb);
+ entry->skb = NULL;
+ }
+ EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
+
+-void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb,
+- struct rxdata_entry_desc *desc)
++void rt2x00lib_rxdone(struct queue_entry *entry,
++ struct rxdone_entry_desc *rxdesc)
+ {
+- struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev;
++ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+ struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status;
+- struct ieee80211_hw_mode *mode;
+- struct ieee80211_rate *rate;
++ struct ieee80211_supported_band *sband;
+ struct ieee80211_hdr *hdr;
++ const struct rt2x00_rate *rate;
+ unsigned int i;
+- int val = 0;
++ int idx = -1;
+ u16 fc;
+
+ /*
+ * Update RX statistics.
+ */
+- mode = &rt2x00dev->hwmodes[rt2x00dev->curr_hwmode];
+- for (i = 0; i < mode->num_rates; i++) {
+- rate = &mode->rates[i];
++ sband = &rt2x00dev->bands[rt2x00dev->curr_band];
++ for (i = 0; i < sband->n_bitrates; i++) {
++ rate = rt2x00_get_rate(sband->bitrates[i].hw_value);
+
+- /*
+- * When frame was received with an OFDM bitrate,
+- * the signal is the PLCP value. If it was received with
+- * a CCK bitrate the signal is the rate in 0.5kbit/s.
+- */
+- if (!desc->ofdm)
+- val = DEVICE_GET_RATE_FIELD(rate->val, RATE);
+- else
+- val = DEVICE_GET_RATE_FIELD(rate->val, PLCP);
+-
+- if (val == desc->signal) {
+- val = rate->val;
++ if (((rxdesc->dev_flags & RXDONE_SIGNAL_PLCP) &&
++ (rate->plcp == rxdesc->signal)) ||
++ (!(rxdesc->dev_flags & RXDONE_SIGNAL_PLCP) &&
++ (rate->bitrate == rxdesc->signal))) {
++ idx = i;
+ break;
+ }
+ }
+
++ if (idx < 0) {
++ WARNING(rt2x00dev, "Frame received with unrecognized signal,"
++ "signal=0x%.2x, plcp=%d.\n", rxdesc->signal,
++ !!(rxdesc->dev_flags & RXDONE_SIGNAL_PLCP));
++ idx = 0;
++ }
++
+ /*
+ * Only update link status if this is a beacon frame carrying our bssid.
+ */
+- hdr = (struct ieee80211_hdr*)skb->data;
++ hdr = (struct ieee80211_hdr *)entry->skb->data;
+ fc = le16_to_cpu(hdr->frame_control);
+- if (is_beacon(fc) && desc->my_bss)
+- rt2x00lib_update_link_stats(&rt2x00dev->link, desc->rssi);
++ if (is_beacon(fc) && (rxdesc->dev_flags & RXDONE_MY_BSS))
++ rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc->rssi);
+
+ rt2x00dev->link.qual.rx_success++;
+
+- rx_status->rate = val;
++ rx_status->rate_idx = idx;
+ rx_status->signal =
+- rt2x00lib_calculate_link_signal(rt2x00dev, desc->rssi);
+- rx_status->ssi = desc->rssi;
+- rx_status->flag = desc->flags;
++ rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc->rssi);
++ rx_status->ssi = rxdesc->rssi;
++ rx_status->flag = rxdesc->flags;
+ rx_status->antenna = rt2x00dev->link.ant.active.rx;
+
+ /*
+- * Send frame to mac80211 & debugfs
++ * Send frame to mac80211 & debugfs.
++ * mac80211 will clean up the skb structure.
+ */
+- get_skb_desc(skb)->frame_type = DUMP_FRAME_RXDONE;
+- rt2x00debug_dump_frame(rt2x00dev, skb);
+- ieee80211_rx_irqsafe(rt2x00dev->hw, skb, rx_status);
++ get_skb_frame_desc(entry->skb)->frame_type = DUMP_FRAME_RXDONE;
++ rt2x00debug_dump_frame(rt2x00dev, entry->skb);
++ ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb, rx_status);
++ entry->skb = NULL;
+ }
+ EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);
+
+@@ -646,83 +625,69 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ struct sk_buff *skb,
+ struct ieee80211_tx_control *control)
+ {
+- struct txdata_entry_desc desc;
+- struct skb_desc *skbdesc = get_skb_desc(skb);
+- struct ieee80211_hdr *ieee80211hdr = skbdesc->data;
++ struct txentry_desc txdesc;
++ struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skbdesc->data;
++ const struct rt2x00_rate *rate;
+ int tx_rate;
+- int bitrate;
+ int length;
+ int duration;
+ int residual;
+ u16 frame_control;
+ u16 seq_ctrl;
+
+- memset(&desc, 0, sizeof(desc));
++ memset(&txdesc, 0, sizeof(txdesc));
+
+- desc.cw_min = skbdesc->ring->tx_params.cw_min;
+- desc.cw_max = skbdesc->ring->tx_params.cw_max;
+- desc.aifs = skbdesc->ring->tx_params.aifs;
+-
+- /*
+- * Identify queue
+- */
+- if (control->queue < rt2x00dev->hw->queues)
+- desc.queue = control->queue;
+- else if (control->queue == IEEE80211_TX_QUEUE_BEACON ||
+- control->queue == IEEE80211_TX_QUEUE_AFTER_BEACON)
+- desc.queue = QUEUE_MGMT;
+- else
+- desc.queue = QUEUE_OTHER;
++ txdesc.queue = skbdesc->entry->queue->qid;
++ txdesc.cw_min = skbdesc->entry->queue->cw_min;
++ txdesc.cw_max = skbdesc->entry->queue->cw_max;
++ txdesc.aifs = skbdesc->entry->queue->aifs;
+
+ /*
+ * Read required fields from ieee80211 header.
+ */
+- frame_control = le16_to_cpu(ieee80211hdr->frame_control);
+- seq_ctrl = le16_to_cpu(ieee80211hdr->seq_ctrl);
++ frame_control = le16_to_cpu(hdr->frame_control);
++ seq_ctrl = le16_to_cpu(hdr->seq_ctrl);
+
+- tx_rate = control->tx_rate;
++ tx_rate = control->tx_rate->hw_value;
+
+ /*
+ * Check whether this frame is to be acked
+ */
+ if (!(control->flags & IEEE80211_TXCTL_NO_ACK))
+- __set_bit(ENTRY_TXD_ACK, &desc.flags);
++ __set_bit(ENTRY_TXD_ACK, &txdesc.flags);
+
+ /*
+ * Check if this is a RTS/CTS frame
+ */
+ if (is_rts_frame(frame_control) || is_cts_frame(frame_control)) {
+- __set_bit(ENTRY_TXD_BURST, &desc.flags);
++ __set_bit(ENTRY_TXD_BURST, &txdesc.flags);
+ if (is_rts_frame(frame_control)) {
+- __set_bit(ENTRY_TXD_RTS_FRAME, &desc.flags);
+- __set_bit(ENTRY_TXD_ACK, &desc.flags);
++ __set_bit(ENTRY_TXD_RTS_FRAME, &txdesc.flags);
++ __set_bit(ENTRY_TXD_ACK, &txdesc.flags);
+ } else
+- __clear_bit(ENTRY_TXD_ACK, &desc.flags);
++ __clear_bit(ENTRY_TXD_ACK, &txdesc.flags);
+ if (control->rts_cts_rate)
+- tx_rate = control->rts_cts_rate;
++ tx_rate = control->rts_cts_rate->hw_value;
+ }
+
+- /*
+- * Check for OFDM
+- */
+- if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATEMASK)
+- __set_bit(ENTRY_TXD_OFDM_RATE, &desc.flags);
++ rate = rt2x00_get_rate(tx_rate);
+
+ /*
+ * Check if more fragments are pending
+ */
+- if (ieee80211_get_morefrag(ieee80211hdr)) {
+- __set_bit(ENTRY_TXD_BURST, &desc.flags);
+- __set_bit(ENTRY_TXD_MORE_FRAG, &desc.flags);
++ if (ieee80211_get_morefrag(hdr)) {
++ __set_bit(ENTRY_TXD_BURST, &txdesc.flags);
++ __set_bit(ENTRY_TXD_MORE_FRAG, &txdesc.flags);
+ }
+
+ /*
+ * Beacons and probe responses require the tsf timestamp
+ * to be inserted into the frame.
+ */
+- if (control->queue == IEEE80211_TX_QUEUE_BEACON ||
++ if (control->queue == RT2X00_BCN_QUEUE_BEACON ||
+ is_probe_resp(frame_control))
+- __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc.flags);
++ __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc.flags);
+
+ /*
+ * Determine with what IFS priority this frame should be send.
+@@ -730,30 +695,30 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ * or this fragment came after RTS/CTS.
+ */
+ if ((seq_ctrl & IEEE80211_SCTL_FRAG) > 0 ||
+- test_bit(ENTRY_TXD_RTS_FRAME, &desc.flags))
+- desc.ifs = IFS_SIFS;
++ test_bit(ENTRY_TXD_RTS_FRAME, &txdesc.flags))
++ txdesc.ifs = IFS_SIFS;
+ else
+- desc.ifs = IFS_BACKOFF;
++ txdesc.ifs = IFS_BACKOFF;
+
+ /*
+ * PLCP setup
+ * Length calculation depends on OFDM/CCK rate.
+ */
+- desc.signal = DEVICE_GET_RATE_FIELD(tx_rate, PLCP);
+- desc.service = 0x04;
++ txdesc.signal = rate->plcp;
++ txdesc.service = 0x04;
+
+ length = skbdesc->data_len + FCS_LEN;
+- if (test_bit(ENTRY_TXD_OFDM_RATE, &desc.flags)) {
+- desc.length_high = (length >> 6) & 0x3f;
+- desc.length_low = length & 0x3f;
+- } else {
+- bitrate = DEVICE_GET_RATE_FIELD(tx_rate, RATE);
++ if (rate->flags & DEV_RATE_OFDM) {
++ __set_bit(ENTRY_TXD_OFDM_RATE, &txdesc.flags);
+
++ txdesc.length_high = (length >> 6) & 0x3f;
++ txdesc.length_low = length & 0x3f;
++ } else {
+ /*
+ * Convert length to microseconds.
+ */
+- residual = get_duration_res(length, bitrate);
+- duration = get_duration(length, bitrate);
++ residual = get_duration_res(length, rate->bitrate);
++ duration = get_duration(length, rate->bitrate);
+
+ if (residual != 0) {
+ duration++;
+@@ -761,28 +726,27 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ /*
+ * Check if we need to set the Length Extension
+ */
+- if (bitrate == 110 && residual <= 30)
+- desc.service |= 0x80;
++ if (rate->bitrate == 110 && residual <= 30)
++ txdesc.service |= 0x80;
+ }
+
+- desc.length_high = (duration >> 8) & 0xff;
+- desc.length_low = duration & 0xff;
++ txdesc.length_high = (duration >> 8) & 0xff;
++ txdesc.length_low = duration & 0xff;
+
+ /*
+ * When preamble is enabled we should set the
+ * preamble bit for the signal.
+ */
+- if (DEVICE_GET_RATE_FIELD(tx_rate, PREAMBLE))
+- desc.signal |= 0x08;
++ if (rt2x00_get_rate_preamble(tx_rate))
++ txdesc.signal |= 0x08;
+ }
+
+- rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, skb, &desc, control);
++ rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, skb, &txdesc, control);
+
+ /*
+- * Update ring entry.
++ * Update queue entry.
+ */
+ skbdesc->entry->skb = skb;
+- memcpy(&skbdesc->entry->tx_status.control, control, sizeof(*control));
+
+ /*
+ * The frame has been completely initialized and ready
+@@ -798,133 +762,167 @@ EXPORT_SYMBOL_GPL(rt2x00lib_write_tx_desc);
+ /*
+ * Driver initialization handlers.
+ */
++const struct rt2x00_rate rt2x00_supported_rates[12] = {
++ {
++ .flags = DEV_RATE_CCK | DEV_RATE_BASIC,
++ .bitrate = 10,
++ .ratemask = BIT(0),
++ .plcp = 0x00,
++ },
++ {
++ .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC,
++ .bitrate = 20,
++ .ratemask = BIT(1),
++ .plcp = 0x01,
++ },
++ {
++ .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC,
++ .bitrate = 55,
++ .ratemask = BIT(2),
++ .plcp = 0x02,
++ },
++ {
++ .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC,
++ .bitrate = 110,
++ .ratemask = BIT(3),
++ .plcp = 0x03,
++ },
++ {
++ .flags = DEV_RATE_OFDM | DEV_RATE_BASIC,
++ .bitrate = 60,
++ .ratemask = BIT(4),
++ .plcp = 0x0b,
++ },
++ {
++ .flags = DEV_RATE_OFDM,
++ .bitrate = 90,
++ .ratemask = BIT(5),
++ .plcp = 0x0f,
++ },
++ {
++ .flags = DEV_RATE_OFDM | DEV_RATE_BASIC,
++ .bitrate = 120,
++ .ratemask = BIT(6),
++ .plcp = 0x0a,
++ },
++ {
++ .flags = DEV_RATE_OFDM,
++ .bitrate = 180,
++ .ratemask = BIT(7),
++ .plcp = 0x0e,
++ },
++ {
++ .flags = DEV_RATE_OFDM | DEV_RATE_BASIC,
++ .bitrate = 240,
++ .ratemask = BIT(8),
++ .plcp = 0x09,
++ },
++ {
++ .flags = DEV_RATE_OFDM,
++ .bitrate = 360,
++ .ratemask = BIT(9),
++ .plcp = 0x0d,
++ },
++ {
++ .flags = DEV_RATE_OFDM,
++ .bitrate = 480,
++ .ratemask = BIT(10),
++ .plcp = 0x08,
++ },
++ {
++ .flags = DEV_RATE_OFDM,
++ .bitrate = 540,
++ .ratemask = BIT(11),
++ .plcp = 0x0c,
++ },
++};
++
+ static void rt2x00lib_channel(struct ieee80211_channel *entry,
+ const int channel, const int tx_power,
+ const int value)
+ {
+- entry->chan = channel;
+- if (channel <= 14)
+- entry->freq = 2407 + (5 * channel);
+- else
+- entry->freq = 5000 + (5 * channel);
+- entry->val = value;
+- entry->flag =
+- IEEE80211_CHAN_W_IBSS |
+- IEEE80211_CHAN_W_ACTIVE_SCAN |
+- IEEE80211_CHAN_W_SCAN;
+- entry->power_level = tx_power;
+- entry->antenna_max = 0xff;
++ entry->center_freq = ieee80211_channel_to_frequency(channel);
++ entry->hw_value = value;
++ entry->max_power = tx_power;
++ entry->max_antenna_gain = 0xff;
+ }
+
+ static void rt2x00lib_rate(struct ieee80211_rate *entry,
+- const int rate, const int mask,
+- const int plcp, const int flags)
++ const u16 index, const struct rt2x00_rate *rate)
+ {
+- entry->rate = rate;
+- entry->val =
+- DEVICE_SET_RATE_FIELD(rate, RATE) |
+- DEVICE_SET_RATE_FIELD(mask, RATEMASK) |
+- DEVICE_SET_RATE_FIELD(plcp, PLCP);
+- entry->flags = flags;
+- entry->val2 = entry->val;
+- if (entry->flags & IEEE80211_RATE_PREAMBLE2)
+- entry->val2 |= DEVICE_SET_RATE_FIELD(1, PREAMBLE);
+- entry->min_rssi_ack = 0;
+- entry->min_rssi_ack_delta = 0;
++ entry->flags = 0;
++ entry->bitrate = rate->bitrate;
++ entry->hw_value = rt2x00_create_rate_hw_value(index, 0);
++ entry->hw_value_short = entry->hw_value;
++
++ if (rate->flags & DEV_RATE_SHORT_PREAMBLE) {
++ entry->flags |= IEEE80211_RATE_SHORT_PREAMBLE;
++ entry->hw_value_short |= rt2x00_create_rate_hw_value(index, 1);
++ }
+ }
+
+ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
+ struct hw_mode_spec *spec)
+ {
+ struct ieee80211_hw *hw = rt2x00dev->hw;
+- struct ieee80211_hw_mode *hwmodes;
+ struct ieee80211_channel *channels;
+ struct ieee80211_rate *rates;
++ unsigned int num_rates;
+ unsigned int i;
+ unsigned char tx_power;
+
+- hwmodes = kzalloc(sizeof(*hwmodes) * spec->num_modes, GFP_KERNEL);
+- if (!hwmodes)
+- goto exit;
++ num_rates = 0;
++ if (spec->supported_rates & SUPPORT_RATE_CCK)
++ num_rates += 4;
++ if (spec->supported_rates & SUPPORT_RATE_OFDM)
++ num_rates += 8;
+
+ channels = kzalloc(sizeof(*channels) * spec->num_channels, GFP_KERNEL);
+ if (!channels)
+- goto exit_free_modes;
++ return -ENOMEM;
+
+- rates = kzalloc(sizeof(*rates) * spec->num_rates, GFP_KERNEL);
++ rates = kzalloc(sizeof(*rates) * num_rates, GFP_KERNEL);
+ if (!rates)
+ goto exit_free_channels;
+
+ /*
+ * Initialize Rate list.
+ */
+- rt2x00lib_rate(&rates[0], 10, DEV_RATEMASK_1MB,
+- 0x00, IEEE80211_RATE_CCK);
+- rt2x00lib_rate(&rates[1], 20, DEV_RATEMASK_2MB,
+- 0x01, IEEE80211_RATE_CCK_2);
+- rt2x00lib_rate(&rates[2], 55, DEV_RATEMASK_5_5MB,
+- 0x02, IEEE80211_RATE_CCK_2);
+- rt2x00lib_rate(&rates[3], 110, DEV_RATEMASK_11MB,
+- 0x03, IEEE80211_RATE_CCK_2);
+-
+- if (spec->num_rates > 4) {
+- rt2x00lib_rate(&rates[4], 60, DEV_RATEMASK_6MB,
+- 0x0b, IEEE80211_RATE_OFDM);
+- rt2x00lib_rate(&rates[5], 90, DEV_RATEMASK_9MB,
+- 0x0f, IEEE80211_RATE_OFDM);
+- rt2x00lib_rate(&rates[6], 120, DEV_RATEMASK_12MB,
+- 0x0a, IEEE80211_RATE_OFDM);
+- rt2x00lib_rate(&rates[7], 180, DEV_RATEMASK_18MB,
+- 0x0e, IEEE80211_RATE_OFDM);
+- rt2x00lib_rate(&rates[8], 240, DEV_RATEMASK_24MB,
+- 0x09, IEEE80211_RATE_OFDM);
+- rt2x00lib_rate(&rates[9], 360, DEV_RATEMASK_36MB,
+- 0x0d, IEEE80211_RATE_OFDM);
+- rt2x00lib_rate(&rates[10], 480, DEV_RATEMASK_48MB,
+- 0x08, IEEE80211_RATE_OFDM);
+- rt2x00lib_rate(&rates[11], 540, DEV_RATEMASK_54MB,
+- 0x0c, IEEE80211_RATE_OFDM);
+- }
++ for (i = 0; i < num_rates; i++)
++ rt2x00lib_rate(&rates[i], i, rt2x00_get_rate(i));
+
+ /*
+ * Initialize Channel list.
+ */
+ for (i = 0; i < spec->num_channels; i++) {
+- if (spec->channels[i].channel <= 14)
+- tx_power = spec->tx_power_bg[i];
+- else if (spec->tx_power_a)
+- tx_power = spec->tx_power_a[i];
+- else
+- tx_power = spec->tx_power_default;
++ if (spec->channels[i].channel <= 14) {
++ if (spec->tx_power_bg)
++ tx_power = spec->tx_power_bg[i];
++ else
++ tx_power = spec->tx_power_default;
++ } else {
++ if (spec->tx_power_a)
++ tx_power = spec->tx_power_a[i];
++ else
++ tx_power = spec->tx_power_default;
++ }
+
+ rt2x00lib_channel(&channels[i],
+ spec->channels[i].channel, tx_power, i);
+ }
+
+ /*
+- * Intitialize 802.11b
+- * Rates: CCK.
+- * Channels: OFDM.
+- */
+- if (spec->num_modes > HWMODE_B) {
+- hwmodes[HWMODE_B].mode = MODE_IEEE80211B;
+- hwmodes[HWMODE_B].num_channels = 14;
+- hwmodes[HWMODE_B].num_rates = 4;
+- hwmodes[HWMODE_B].channels = channels;
+- hwmodes[HWMODE_B].rates = rates;
+- }
+-
+- /*
+- * Intitialize 802.11g
++ * Intitialize 802.11b, 802.11g
+ * Rates: CCK, OFDM.
+- * Channels: OFDM.
+- */
+- if (spec->num_modes > HWMODE_G) {
+- hwmodes[HWMODE_G].mode = MODE_IEEE80211G;
+- hwmodes[HWMODE_G].num_channels = 14;
+- hwmodes[HWMODE_G].num_rates = spec->num_rates;
+- hwmodes[HWMODE_G].channels = channels;
+- hwmodes[HWMODE_G].rates = rates;
++ * Channels: 2.4 GHz
++ */
++ if (spec->supported_bands & SUPPORT_BAND_2GHZ) {
++ rt2x00dev->bands[IEEE80211_BAND_2GHZ].n_channels = 14;
++ rt2x00dev->bands[IEEE80211_BAND_2GHZ].n_bitrates = num_rates;
++ rt2x00dev->bands[IEEE80211_BAND_2GHZ].channels = channels;
++ rt2x00dev->bands[IEEE80211_BAND_2GHZ].bitrates = rates;
++ hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
++ &rt2x00dev->bands[IEEE80211_BAND_2GHZ];
+ }
+
+ /*
+@@ -932,40 +930,21 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
+ * Rates: OFDM.
+ * Channels: OFDM, UNII, HiperLAN2.
+ */
+- if (spec->num_modes > HWMODE_A) {
+- hwmodes[HWMODE_A].mode = MODE_IEEE80211A;
+- hwmodes[HWMODE_A].num_channels = spec->num_channels - 14;
+- hwmodes[HWMODE_A].num_rates = spec->num_rates - 4;
+- hwmodes[HWMODE_A].channels = &channels[14];
+- hwmodes[HWMODE_A].rates = &rates[4];
++ if (spec->supported_bands & SUPPORT_BAND_5GHZ) {
++ rt2x00dev->bands[IEEE80211_BAND_5GHZ].n_channels =
++ spec->num_channels - 14;
++ rt2x00dev->bands[IEEE80211_BAND_5GHZ].n_bitrates =
++ num_rates - 4;
++ rt2x00dev->bands[IEEE80211_BAND_5GHZ].channels = &channels[14];
++ rt2x00dev->bands[IEEE80211_BAND_5GHZ].bitrates = &rates[4];
++ hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
++ &rt2x00dev->bands[IEEE80211_BAND_5GHZ];
+ }
+
+- if (spec->num_modes > HWMODE_G &&
+- ieee80211_register_hwmode(hw, &hwmodes[HWMODE_G]))
+- goto exit_free_rates;
+-
+- if (spec->num_modes > HWMODE_B &&
+- ieee80211_register_hwmode(hw, &hwmodes[HWMODE_B]))
+- goto exit_free_rates;
+-
+- if (spec->num_modes > HWMODE_A &&
+- ieee80211_register_hwmode(hw, &hwmodes[HWMODE_A]))
+- goto exit_free_rates;
+-
+- rt2x00dev->hwmodes = hwmodes;
+-
+ return 0;
+
+-exit_free_rates:
+- kfree(rates);
+-
+-exit_free_channels:
++ exit_free_channels:
+ kfree(channels);
+-
+-exit_free_modes:
+- kfree(hwmodes);
+-
+-exit:
+ ERROR(rt2x00dev, "Allocation ieee80211 modes failed.\n");
+ return -ENOMEM;
+ }
+@@ -975,11 +954,11 @@ static void rt2x00lib_remove_hw(struct rt2x00_dev *rt2x00dev)
+ if (test_bit(DEVICE_REGISTERED_HW, &rt2x00dev->flags))
+ ieee80211_unregister_hw(rt2x00dev->hw);
+
+- if (likely(rt2x00dev->hwmodes)) {
+- kfree(rt2x00dev->hwmodes->channels);
+- kfree(rt2x00dev->hwmodes->rates);
+- kfree(rt2x00dev->hwmodes);
+- rt2x00dev->hwmodes = NULL;
++ if (likely(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ])) {
++ kfree(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
++ kfree(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->bitrates);
++ rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
++ rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
+ }
+ }
+
+@@ -1012,86 +991,6 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
+ /*
+ * Initialization/uninitialization handlers.
+ */
+-static int rt2x00lib_alloc_entries(struct data_ring *ring,
+- const u16 max_entries, const u16 data_size,
+- const u16 desc_size)
+-{
+- struct data_entry *entry;
+- unsigned int i;
+-
+- ring->stats.limit = max_entries;
+- ring->data_size = data_size;
+- ring->desc_size = desc_size;
+-
+- /*
+- * Allocate all ring entries.
+- */
+- entry = kzalloc(ring->stats.limit * sizeof(*entry), GFP_KERNEL);
+- if (!entry)
+- return -ENOMEM;
+-
+- for (i = 0; i < ring->stats.limit; i++) {
+- entry[i].flags = 0;
+- entry[i].ring = ring;
+- entry[i].skb = NULL;
+- entry[i].entry_idx = i;
+- }
+-
+- ring->entry = entry;
+-
+- return 0;
+-}
+-
+-static int rt2x00lib_alloc_ring_entries(struct rt2x00_dev *rt2x00dev)
+-{
+- struct data_ring *ring;
+-
+- /*
+- * Allocate the RX ring.
+- */
+- if (rt2x00lib_alloc_entries(rt2x00dev->rx, RX_ENTRIES, DATA_FRAME_SIZE,
+- rt2x00dev->ops->rxd_size))
+- return -ENOMEM;
+-
+- /*
+- * First allocate the TX rings.
+- */
+- txring_for_each(rt2x00dev, ring) {
+- if (rt2x00lib_alloc_entries(ring, TX_ENTRIES, DATA_FRAME_SIZE,
+- rt2x00dev->ops->txd_size))
+- return -ENOMEM;
+- }
+-
+- if (!test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags))
+- return 0;
+-
+- /*
+- * Allocate the BEACON ring.
+- */
+- if (rt2x00lib_alloc_entries(&rt2x00dev->bcn[0], BEACON_ENTRIES,
+- MGMT_FRAME_SIZE, rt2x00dev->ops->txd_size))
+- return -ENOMEM;
+-
+- /*
+- * Allocate the Atim ring.
+- */
+- if (rt2x00lib_alloc_entries(&rt2x00dev->bcn[1], ATIM_ENTRIES,
+- DATA_FRAME_SIZE, rt2x00dev->ops->txd_size))
+- return -ENOMEM;
+-
+- return 0;
+-}
+-
+-static void rt2x00lib_free_ring_entries(struct rt2x00_dev *rt2x00dev)
+-{
+- struct data_ring *ring;
+-
+- ring_for_each(rt2x00dev, ring) {
+- kfree(ring->entry);
+- ring->entry = NULL;
+- }
+-}
+-
+ static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)
+ {
+ if (!__test_and_clear_bit(DEVICE_INITIALIZED, &rt2x00dev->flags))
+@@ -1108,9 +1007,9 @@ static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)
+ rt2x00dev->ops->lib->uninitialize(rt2x00dev);
+
+ /*
+- * Free allocated ring entries.
++ * Free allocated queue entries.
+ */
+- rt2x00lib_free_ring_entries(rt2x00dev);
++ rt2x00queue_uninitialize(rt2x00dev);
+ }
+
+ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
+@@ -1121,13 +1020,11 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
+ return 0;
+
+ /*
+- * Allocate all ring entries.
++ * Allocate all queue entries.
+ */
+- status = rt2x00lib_alloc_ring_entries(rt2x00dev);
+- if (status) {
+- ERROR(rt2x00dev, "Ring entries allocation failed.\n");
++ status = rt2x00queue_initialize(rt2x00dev);
++ if (status)
+ return status;
+- }
+
+ /*
+ * Initialize the device.
+@@ -1146,7 +1043,7 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
+ return 0;
+
+ exit:
+- rt2x00lib_free_ring_entries(rt2x00dev);
++ rt2x00lib_uninitialize(rt2x00dev);
+
+ return status;
+ }
+@@ -1162,11 +1059,9 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
+ * If this is the first interface which is added,
+ * we should load the firmware now.
+ */
+- if (test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags)) {
+- retval = rt2x00lib_load_firmware(rt2x00dev);
+- if (retval)
+- return retval;
+- }
++ retval = rt2x00lib_load_firmware(rt2x00dev);
++ if (retval)
++ return retval;
+
+ /*
+ * Initialize the device.
+@@ -1184,6 +1079,10 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
+ return retval;
+ }
+
++ rt2x00dev->intf_ap_count = 0;
++ rt2x00dev->intf_sta_count = 0;
++ rt2x00dev->intf_associated = 0;
++
+ __set_bit(DEVICE_STARTED, &rt2x00dev->flags);
+
+ return 0;
+@@ -1200,74 +1099,25 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev)
+ */
+ rt2x00lib_disable_radio(rt2x00dev);
+
++ rt2x00dev->intf_ap_count = 0;
++ rt2x00dev->intf_sta_count = 0;
++ rt2x00dev->intf_associated = 0;
++
+ __clear_bit(DEVICE_STARTED, &rt2x00dev->flags);
+ }
+
+ /*
+ * driver allocation handlers.
+ */
+-static int rt2x00lib_alloc_rings(struct rt2x00_dev *rt2x00dev)
++int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
+ {
+- struct data_ring *ring;
+- unsigned int index;
+-
+- /*
+- * We need the following rings:
+- * RX: 1
+- * TX: hw->queues
+- * Beacon: 1 (if required)
+- * Atim: 1 (if required)
+- */
+- rt2x00dev->data_rings = 1 + rt2x00dev->hw->queues +
+- (2 * test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags));
+-
+- ring = kzalloc(rt2x00dev->data_rings * sizeof(*ring), GFP_KERNEL);
+- if (!ring) {
+- ERROR(rt2x00dev, "Ring allocation failed.\n");
+- return -ENOMEM;
+- }
+-
+- /*
+- * Initialize pointers
+- */
+- rt2x00dev->rx = ring;
+- rt2x00dev->tx = &rt2x00dev->rx[1];
+- if (test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags))
+- rt2x00dev->bcn = &rt2x00dev->tx[rt2x00dev->hw->queues];
++ int retval = -ENOMEM;
+
+ /*
+- * Initialize ring parameters.
+- * RX: queue_idx = 0
+- * TX: queue_idx = IEEE80211_TX_QUEUE_DATA0 + index
+- * TX: cw_min: 2^5 = 32.
+- * TX: cw_max: 2^10 = 1024.
++ * Make room for rt2x00_intf inside the per-interface
++ * structure ieee80211_vif.
+ */
+- rt2x00dev->rx->rt2x00dev = rt2x00dev;
+- rt2x00dev->rx->queue_idx = 0;
+-
+- index = IEEE80211_TX_QUEUE_DATA0;
+- txring_for_each(rt2x00dev, ring) {
+- ring->rt2x00dev = rt2x00dev;
+- ring->queue_idx = index++;
+- ring->tx_params.aifs = 2;
+- ring->tx_params.cw_min = 5;
+- ring->tx_params.cw_max = 10;
+- }
+-
+- return 0;
+-}
+-
+-static void rt2x00lib_free_rings(struct rt2x00_dev *rt2x00dev)
+-{
+- kfree(rt2x00dev->rx);
+- rt2x00dev->rx = NULL;
+- rt2x00dev->tx = NULL;
+- rt2x00dev->bcn = NULL;
+-}
+-
+-int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
+-{
+- int retval = -ENOMEM;
++ rt2x00dev->hw->vif_data_size = sizeof(struct rt2x00_intf);
+
+ /*
+ * Let the driver probe the device to detect the capabilities.
+@@ -1281,20 +1131,14 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
+ /*
+ * Initialize configuration work.
+ */
+- INIT_WORK(&rt2x00dev->beacon_work, rt2x00lib_beacondone_scheduled);
++ INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
+ INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled);
+- INIT_WORK(&rt2x00dev->config_work, rt2x00lib_configuration_scheduled);
+ INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner);
+
+ /*
+- * Reset current working type.
+- */
+- rt2x00dev->interface.type = IEEE80211_IF_TYPE_INVALID;
+-
+- /*
+- * Allocate ring array.
++ * Allocate queue array.
+ */
+- retval = rt2x00lib_alloc_rings(rt2x00dev);
++ retval = rt2x00queue_allocate(rt2x00dev);
+ if (retval)
+ goto exit;
+
+@@ -1310,6 +1154,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
+ /*
+ * Register extra components.
+ */
++ rt2x00leds_register(rt2x00dev);
+ rt2x00rfkill_allocate(rt2x00dev);
+ rt2x00debug_register(rt2x00dev);
+
+@@ -1343,6 +1188,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
+ */
+ rt2x00debug_deregister(rt2x00dev);
+ rt2x00rfkill_free(rt2x00dev);
++ rt2x00leds_unregister(rt2x00dev);
+
+ /*
+ * Free ieee80211_hw memory.
+@@ -1355,9 +1201,9 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
+ rt2x00lib_free_firmware(rt2x00dev);
+
+ /*
+- * Free ring structures.
++ * Free queue structures.
+ */
+- rt2x00lib_free_rings(rt2x00dev);
++ rt2x00queue_free(rt2x00dev);
+ }
+ EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev);
+
+@@ -1388,6 +1234,7 @@ int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state)
+ /*
+ * Suspend/disable extra components.
+ */
++ rt2x00leds_suspend(rt2x00dev);
+ rt2x00rfkill_suspend(rt2x00dev);
+ rt2x00debug_deregister(rt2x00dev);
+
+@@ -1412,9 +1259,30 @@ exit:
+ }
+ EXPORT_SYMBOL_GPL(rt2x00lib_suspend);
+
++static void rt2x00lib_resume_intf(void *data, u8 *mac,
++ struct ieee80211_vif *vif)
++{
++ struct rt2x00_dev *rt2x00dev = data;
++ struct rt2x00_intf *intf = vif_to_intf(vif);
++
++ spin_lock(&intf->lock);
++
++ rt2x00lib_config_intf(rt2x00dev, intf,
++ vif->type, intf->mac, intf->bssid);
++
++
++ /*
++ * Master or Ad-hoc mode require a new beacon update.
++ */
++ if (vif->type == IEEE80211_IF_TYPE_AP ||
++ vif->type == IEEE80211_IF_TYPE_IBSS)
++ intf->delayed_flags |= DELAYED_UPDATE_BEACON;
++
++ spin_unlock(&intf->lock);
++}
++
+ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
+ {
+- struct interface *intf = &rt2x00dev->interface;
+ int retval;
+
+ NOTICE(rt2x00dev, "Waking up.\n");
+@@ -1424,6 +1292,7 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
+ */
+ rt2x00debug_register(rt2x00dev);
+ rt2x00rfkill_resume(rt2x00dev);
++ rt2x00leds_resume(rt2x00dev);
+
+ /*
+ * Only continue if mac80211 had open interfaces.
+@@ -1445,9 +1314,12 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
+ if (!rt2x00dev->hw->conf.radio_enabled)
+ rt2x00lib_disable_radio(rt2x00dev);
+
+- rt2x00lib_config_mac_addr(rt2x00dev, intf->mac);
+- rt2x00lib_config_bssid(rt2x00dev, intf->bssid);
+- rt2x00lib_config_type(rt2x00dev, intf->type);
++ /*
++ * Iterator over each active interface to
++ * reconfigure the hardware.
++ */
++ ieee80211_iterate_active_interfaces(rt2x00dev->hw,
++ rt2x00lib_resume_intf, rt2x00dev);
+
+ /*
+ * We are ready again to receive requests from mac80211.
+@@ -1463,12 +1335,11 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
+ ieee80211_start_queues(rt2x00dev->hw);
+
+ /*
+- * When in Master or Ad-hoc mode,
+- * restart Beacon transmitting by faking a beacondone event.
++ * During interface iteration we might have changed the
++ * delayed_flags, time to handles the event by calling
++ * the work handler directly.
+ */
+- if (intf->type == IEEE80211_IF_TYPE_AP ||
+- intf->type == IEEE80211_IF_TYPE_IBSS)
+- rt2x00lib_beacondone(rt2x00dev);
++ rt2x00lib_intf_scheduled(&rt2x00dev->intf_work);
+
+ return 0;
+
+diff --git a/drivers/net/wireless/rt2x00/rt2x00dump.h b/drivers/net/wireless/rt2x00/rt2x00dump.h
+index 99f3f36..7169c22 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00dump.h
++++ b/drivers/net/wireless/rt2x00/rt2x00dump.h
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+@@ -93,8 +93,8 @@ enum rt2x00_dump_type {
+ * @chip_rf: RF chipset
+ * @chip_rev: Chipset revision
+ * @type: The frame type (&rt2x00_dump_type)
+- * @ring_index: The index number of the data ring.
+- * @entry_index: The index number of the entry inside the data ring.
++ * @queue_index: The index number of the data queue.
++ * @entry_index: The index number of the entry inside the data queue.
+ * @timestamp_sec: Timestamp - seconds
+ * @timestamp_usec: Timestamp - microseconds
+ */
+@@ -111,7 +111,7 @@ struct rt2x00dump_hdr {
+ __le32 chip_rev;
+
+ __le16 type;
+- __u8 ring_index;
++ __u8 queue_index;
+ __u8 entry_index;
+
+ __le32 timestamp_sec;
+diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c
+index 0a475e4..b971bc6 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00firmware.c
++++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+@@ -23,7 +23,6 @@
+ Abstract: rt2x00 firmware loading routines.
+ */
+
+-#include <linux/crc-itu-t.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+
+@@ -37,7 +36,6 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev)
+ char *fw_name;
+ int retval;
+ u16 crc;
+- u16 tmp;
+
+ /*
+ * Read correct firmware from harddisk.
+@@ -63,18 +61,9 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev)
+ return -ENOENT;
+ }
+
+- /*
+- * Validate the firmware using 16 bit CRC.
+- * The last 2 bytes of the firmware are the CRC
+- * so substract those 2 bytes from the CRC checksum,
+- * and set those 2 bytes to 0 when calculating CRC.
+- */
+- tmp = 0;
+- crc = crc_itu_t(0, fw->data, fw->size - 2);
+- crc = crc_itu_t(crc, (u8 *)&tmp, 2);
+-
++ crc = rt2x00dev->ops->lib->get_firmware_crc(fw->data, fw->size);
+ if (crc != (fw->data[fw->size - 2] << 8 | fw->data[fw->size - 1])) {
+- ERROR(rt2x00dev, "Firmware CRC error.\n");
++ ERROR(rt2x00dev, "Firmware checksum error.\n");
+ retval = -ENOENT;
+ goto exit;
+ }
+@@ -96,6 +85,9 @@ int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
+ {
+ int retval;
+
++ if (!test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags))
++ return 0;
++
+ if (!rt2x00dev->fw) {
+ retval = rt2x00lib_request_firmware(rt2x00dev);
+ if (retval)
+@@ -116,4 +108,3 @@ void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev)
+ release_firmware(rt2x00dev->fw);
+ rt2x00dev->fw = NULL;
+ }
+-
+diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c
+new file mode 100644
+index 0000000..40c1f5c
+--- /dev/null
++++ b/drivers/net/wireless/rt2x00/rt2x00leds.c
+@@ -0,0 +1,219 @@
++/*
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
++ <http://rt2x00.serialmonkey.com>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the
++ Free Software Foundation, Inc.,
++ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++/*
++ Module: rt2x00lib
++ Abstract: rt2x00 led specific routines.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++
++#include "rt2x00.h"
++#include "rt2x00lib.h"
++
++void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi)
++{
++ struct rt2x00_led *led = &rt2x00dev->led_qual;
++ unsigned int brightness;
++
++ if ((led->type != LED_TYPE_QUALITY) || !(led->flags & LED_REGISTERED))
++ return;
++
++ /*
++ * Led handling requires a positive value for the rssi,
++ * to do that correctly we need to add the correction.
++ */
++ rssi += rt2x00dev->rssi_offset;
++
++ /*
++ * Get the rssi level, this is used to convert the rssi
++ * to a LED value inside the range LED_OFF - LED_FULL.
++ */
++ if (rssi <= 30)
++ rssi = 0;
++ else if (rssi <= 39)
++ rssi = 1;
++ else if (rssi <= 49)
++ rssi = 2;
++ else if (rssi <= 53)
++ rssi = 3;
++ else if (rssi <= 63)
++ rssi = 4;
++ else
++ rssi = 5;
++
++ /*
++ * Note that we must _not_ send LED_OFF since the driver
++ * is going to calculate the value and might use it in a
++ * division.
++ */
++ brightness = ((LED_FULL / 6) * rssi) + 1;
++ if (brightness != led->led_dev.brightness) {
++ led->led_dev.brightness_set(&led->led_dev, brightness);
++ led->led_dev.brightness = brightness;
++ }
++}
++
++void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled)
++{
++ struct rt2x00_led *led = &rt2x00dev->led_assoc;
++ unsigned int brightness;
++
++ if ((led->type != LED_TYPE_ASSOC) || !(led->flags & LED_REGISTERED))
++ return;
++
++ brightness = enabled ? LED_FULL : LED_OFF;
++ if (brightness != led->led_dev.brightness) {
++ led->led_dev.brightness_set(&led->led_dev, brightness);
++ led->led_dev.brightness = brightness;
++ }
++}
++
++void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, bool enabled)
++{
++ struct rt2x00_led *led = &rt2x00dev->led_radio;
++ unsigned int brightness;
++
++ if ((led->type != LED_TYPE_RADIO) || !(led->flags & LED_REGISTERED))
++ return;
++
++ brightness = enabled ? LED_FULL : LED_OFF;
++ if (brightness != led->led_dev.brightness) {
++ led->led_dev.brightness_set(&led->led_dev, brightness);
++ led->led_dev.brightness = brightness;
++ }
++}
++
++static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev,
++ struct rt2x00_led *led,
++ const char *name)
++{
++ struct device *device = wiphy_dev(rt2x00dev->hw->wiphy);
++ int retval;
++
++ led->led_dev.name = name;
++
++ retval = led_classdev_register(device, &led->led_dev);
++ if (retval) {
++ ERROR(rt2x00dev, "Failed to register led handler.\n");
++ return retval;
++ }
++
++ led->flags |= LED_REGISTERED;
++
++ return 0;
++}
++
++void rt2x00leds_register(struct rt2x00_dev *rt2x00dev)
++{
++ char dev_name[16];
++ char name[32];
++ int retval;
++ unsigned long on_period;
++ unsigned long off_period;
++
++ snprintf(dev_name, sizeof(dev_name), "%s-%s",
++ rt2x00dev->ops->name, wiphy_name(rt2x00dev->hw->wiphy));
++
++ if (rt2x00dev->led_radio.flags & LED_INITIALIZED) {
++ snprintf(name, sizeof(name), "%s:radio", dev_name);
++
++ retval = rt2x00leds_register_led(rt2x00dev,
++ &rt2x00dev->led_radio,
++ name);
++ if (retval)
++ goto exit_fail;
++ }
++
++ if (rt2x00dev->led_assoc.flags & LED_INITIALIZED) {
++ snprintf(name, sizeof(name), "%s:assoc", dev_name);
++
++ retval = rt2x00leds_register_led(rt2x00dev,
++ &rt2x00dev->led_assoc,
++ name);
++ if (retval)
++ goto exit_fail;
++ }
++
++ if (rt2x00dev->led_qual.flags & LED_INITIALIZED) {
++ snprintf(name, sizeof(name), "%s:quality", dev_name);
++
++ retval = rt2x00leds_register_led(rt2x00dev,
++ &rt2x00dev->led_qual,
++ name);
++ if (retval)
++ goto exit_fail;
++ }
++
++ /*
++ * Initialize blink time to default value:
++ * On period: 70ms
++ * Off period: 30ms
++ */
++ if (rt2x00dev->led_radio.led_dev.blink_set) {
++ on_period = 70;
++ off_period = 30;
++ rt2x00dev->led_radio.led_dev.blink_set(
++ &rt2x00dev->led_radio.led_dev, &on_period, &off_period);
++ }
++
++ return;
++
++exit_fail:
++ rt2x00leds_unregister(rt2x00dev);
++}
++
++static void rt2x00leds_unregister_led(struct rt2x00_led *led)
++{
++ led_classdev_unregister(&led->led_dev);
++ led->led_dev.brightness_set(&led->led_dev, LED_OFF);
++ led->flags &= ~LED_REGISTERED;
++}
++
++void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev)
++{
++ if (rt2x00dev->led_qual.flags & LED_REGISTERED)
++ rt2x00leds_unregister_led(&rt2x00dev->led_qual);
++ if (rt2x00dev->led_assoc.flags & LED_REGISTERED)
++ rt2x00leds_unregister_led(&rt2x00dev->led_assoc);
++ if (rt2x00dev->led_radio.flags & LED_REGISTERED)
++ rt2x00leds_unregister_led(&rt2x00dev->led_radio);
++}
++
++void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev)
++{
++ if (rt2x00dev->led_qual.flags & LED_REGISTERED)
++ led_classdev_suspend(&rt2x00dev->led_qual.led_dev);
++ if (rt2x00dev->led_assoc.flags & LED_REGISTERED)
++ led_classdev_suspend(&rt2x00dev->led_assoc.led_dev);
++ if (rt2x00dev->led_radio.flags & LED_REGISTERED)
++ led_classdev_suspend(&rt2x00dev->led_radio.led_dev);
++}
++
++void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev)
++{
++ if (rt2x00dev->led_radio.flags & LED_REGISTERED)
++ led_classdev_resume(&rt2x00dev->led_radio.led_dev);
++ if (rt2x00dev->led_assoc.flags & LED_REGISTERED)
++ led_classdev_resume(&rt2x00dev->led_assoc.led_dev);
++ if (rt2x00dev->led_qual.flags & LED_REGISTERED)
++ led_classdev_resume(&rt2x00dev->led_qual.led_dev);
++}
+diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.h b/drivers/net/wireless/rt2x00/rt2x00leds.h
+new file mode 100644
+index 0000000..9df4a49
+--- /dev/null
++++ b/drivers/net/wireless/rt2x00/rt2x00leds.h
+@@ -0,0 +1,50 @@
++/*
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
++ <http://rt2x00.serialmonkey.com>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the
++ Free Software Foundation, Inc.,
++ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++/*
++ Module: rt2x00lib
++ Abstract: rt2x00 led datastructures and routines
++ */
++
++#ifndef RT2X00LEDS_H
++#define RT2X00LEDS_H
++
++enum led_type {
++ LED_TYPE_RADIO,
++ LED_TYPE_ASSOC,
++ LED_TYPE_ACTIVITY,
++ LED_TYPE_QUALITY,
++};
++
++#ifdef CONFIG_RT2X00_LIB_LEDS
++
++struct rt2x00_led {
++ struct rt2x00_dev *rt2x00dev;
++ struct led_classdev led_dev;
++
++ enum led_type type;
++ unsigned int flags;
++#define LED_INITIALIZED ( 1 << 0 )
++#define LED_REGISTERED ( 1 << 1 )
++};
++
++#endif /* CONFIG_RT2X00_LIB_LEDS */
++
++#endif /* RT2X00LEDS_H */
+diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
+index ce58c65..5be32ff 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
++++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+@@ -34,6 +34,40 @@
+ #define RFKILL_POLL_INTERVAL ( 1000 )
+
+ /*
++ * rt2x00_rate: Per rate device information
++ */
++struct rt2x00_rate {
++ unsigned short flags;
++#define DEV_RATE_CCK 0x0001
++#define DEV_RATE_OFDM 0x0002
++#define DEV_RATE_SHORT_PREAMBLE 0x0004
++#define DEV_RATE_BASIC 0x0008
++
++ unsigned short bitrate; /* In 100kbit/s */
++ unsigned short ratemask;
++
++ unsigned short plcp;
++};
++
++extern const struct rt2x00_rate rt2x00_supported_rates[12];
++
++static inline u16 rt2x00_create_rate_hw_value(const u16 index,
++ const u16 short_preamble)
++{
++ return (short_preamble << 8) | (index & 0xff);
++}
++
++static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value)
++{
++ return &rt2x00_supported_rates[hw_value & 0xff];
++}
++
++static inline int rt2x00_get_rate_preamble(const u16 hw_value)
++{
++ return (hw_value & 0xff00);
++}
++
++/*
+ * Radio control handlers.
+ */
+ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev);
+@@ -50,15 +84,29 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev);
+ /*
+ * Configuration handlers.
+ */
+-void rt2x00lib_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *mac);
+-void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid);
+-void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type);
++void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
++ struct rt2x00_intf *intf,
++ enum ieee80211_if_types type,
++ u8 *mac, u8 *bssid);
++void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
++ struct rt2x00_intf *intf,
++ struct ieee80211_bss_conf *conf);
+ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
+ enum antenna rx, enum antenna tx);
+ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_conf *conf, const int force_config);
+
+ /*
++ * Queue handlers.
++ */
++void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev);
++void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev);
++int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev);
++void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev);
++int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev);
++void rt2x00queue_free(struct rt2x00_dev *rt2x00dev);
++
++/*
+ * Firmware handlers.
+ */
+ #ifdef CONFIG_RT2X00_LIB_FIRMWARE
+@@ -132,4 +180,48 @@ static inline void rt2x00rfkill_resume(struct rt2x00_dev *rt2x00dev)
+ }
+ #endif /* CONFIG_RT2X00_LIB_RFKILL */
+
++/*
++ * LED handlers
++ */
++#ifdef CONFIG_RT2X00_LIB_LEDS
++void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi);
++void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled);
++void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, bool enabled);
++void rt2x00leds_register(struct rt2x00_dev *rt2x00dev);
++void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev);
++void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev);
++void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev);
++#else
++static inline void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev,
++ int rssi)
++{
++}
++
++static inline void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev,
++ bool enabled)
++{
++}
++
++static inline void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev,
++ bool enabled)
++{
++}
++
++static inline void rt2x00leds_register(struct rt2x00_dev *rt2x00dev)
++{
++}
++
++static inline void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev)
++{
++}
++
++static inline void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev)
++{
++}
++
++static inline void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev)
++{
++}
++#endif /* CONFIG_RT2X00_LIB_LEDS */
++
+ #endif /* RT2X00LIB_H */
+diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
+index e3f15e5..c206b50 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
++++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+@@ -30,10 +30,11 @@
+ #include "rt2x00lib.h"
+
+ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
+- struct data_ring *ring,
++ struct data_queue *queue,
+ struct sk_buff *frag_skb,
+ struct ieee80211_tx_control *control)
+ {
++ struct skb_frame_desc *skbdesc;
+ struct sk_buff *skb;
+ int size;
+
+@@ -52,15 +53,22 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
+ skb_put(skb, size);
+
+ if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
+- ieee80211_ctstoself_get(rt2x00dev->hw, rt2x00dev->interface.id,
++ ieee80211_ctstoself_get(rt2x00dev->hw, control->vif,
+ frag_skb->data, frag_skb->len, control,
+ (struct ieee80211_cts *)(skb->data));
+ else
+- ieee80211_rts_get(rt2x00dev->hw, rt2x00dev->interface.id,
++ ieee80211_rts_get(rt2x00dev->hw, control->vif,
+ frag_skb->data, frag_skb->len, control,
+ (struct ieee80211_rts *)(skb->data));
+
+- if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, ring, skb, control)) {
++ /*
++ * Initialize skb descriptor
++ */
++ skbdesc = get_skb_frame_desc(skb);
++ memset(skbdesc, 0, sizeof(*skbdesc));
++ skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
++
++ if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb, control)) {
+ WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n");
+ return NETDEV_TX_BUSY;
+ }
+@@ -73,7 +81,8 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ {
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+ struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
+- struct data_ring *ring;
++ struct data_queue *queue;
++ struct skb_frame_desc *skbdesc;
+ u16 frame_control;
+
+ /*
+@@ -88,10 +97,14 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ }
+
+ /*
+- * Determine which ring to put packet on.
++ * Determine which queue to put packet on.
+ */
+- ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
+- if (unlikely(!ring)) {
++ if (control->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM &&
++ test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags))
++ queue = rt2x00queue_get_queue(rt2x00dev, RT2X00_BCN_QUEUE_ATIM);
++ else
++ queue = rt2x00queue_get_queue(rt2x00dev, control->queue);
++ if (unlikely(!queue)) {
+ ERROR(rt2x00dev,
+ "Attempt to send packet over invalid queue %d.\n"
+ "Please file bug report to %s.\n",
+@@ -110,23 +123,29 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ if (!is_rts_frame(frame_control) && !is_cts_frame(frame_control) &&
+ (control->flags & (IEEE80211_TXCTL_USE_RTS_CTS |
+ IEEE80211_TXCTL_USE_CTS_PROTECT))) {
+- if (rt2x00_ring_free(ring) <= 1) {
++ if (rt2x00queue_available(queue) <= 1) {
+ ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+ return NETDEV_TX_BUSY;
+ }
+
+- if (rt2x00mac_tx_rts_cts(rt2x00dev, ring, skb, control)) {
++ if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb, control)) {
+ ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+ return NETDEV_TX_BUSY;
+ }
+ }
+
+- if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, ring, skb, control)) {
++ /*
++ * Initialize skb descriptor
++ */
++ skbdesc = get_skb_frame_desc(skb);
++ memset(skbdesc, 0, sizeof(*skbdesc));
++
++ if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb, control)) {
+ ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+ return NETDEV_TX_BUSY;
+ }
+
+- if (rt2x00_ring_full(ring))
++ if (rt2x00queue_full(queue))
+ ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+
+ if (rt2x00dev->ops->lib->kick_tx_queue)
+@@ -162,27 +181,67 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_init_conf *conf)
+ {
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+- struct interface *intf = &rt2x00dev->interface;
+-
+- /* FIXME: Beaconing is broken in rt2x00. */
+- if (conf->type == IEEE80211_IF_TYPE_IBSS ||
+- conf->type == IEEE80211_IF_TYPE_AP) {
+- ERROR(rt2x00dev,
+- "rt2x00 does not support Adhoc or Master mode");
+- return -EOPNOTSUPP;
+- }
++ struct rt2x00_intf *intf = vif_to_intf(conf->vif);
++ struct data_queue *queue =
++ rt2x00queue_get_queue(rt2x00dev, RT2X00_BCN_QUEUE_BEACON);
++ struct queue_entry *entry = NULL;
++ unsigned int i;
+
+ /*
+- * Don't allow interfaces to be added while
+- * either the device has disappeared or when
+- * another interface is already present.
++ * Don't allow interfaces to be added
++ * the device has disappeared.
+ */
+ if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
+- is_interface_present(intf))
++ !test_bit(DEVICE_STARTED, &rt2x00dev->flags))
++ return -ENODEV;
++
++ /*
++ * When we don't support mixed interfaces (a combination
++ * of sta and ap virtual interfaces) then we can only
++ * add this interface when the rival interface count is 0.
++ */
++ if (!test_bit(DRIVER_SUPPORT_MIXED_INTERFACES, &rt2x00dev->flags) &&
++ ((conf->type == IEEE80211_IF_TYPE_AP && rt2x00dev->intf_sta_count) ||
++ (conf->type != IEEE80211_IF_TYPE_AP && rt2x00dev->intf_ap_count)))
++ return -ENOBUFS;
++
++ /*
++ * Check if we exceeded the maximum amount of supported interfaces.
++ */
++ if ((conf->type == IEEE80211_IF_TYPE_AP &&
++ rt2x00dev->intf_ap_count >= rt2x00dev->ops->max_ap_intf) ||
++ (conf->type != IEEE80211_IF_TYPE_AP &&
++ rt2x00dev->intf_sta_count >= rt2x00dev->ops->max_sta_intf))
+ return -ENOBUFS;
+
+- intf->id = conf->vif;
+- intf->type = conf->type;
++ /*
++ * Loop through all beacon queues to find a free
++ * entry. Since there are as much beacon entries
++ * as the maximum interfaces, this search shouldn't
++ * fail.
++ */
++ for (i = 0; i < queue->limit; i++) {
++ entry = &queue->entries[i];
++ if (!__test_and_set_bit(ENTRY_BCN_ASSIGNED, &entry->flags))
++ break;
++ }
++
++ if (unlikely(i == queue->limit))
++ return -ENOBUFS;
++
++ /*
++ * We are now absolutely sure the interface can be created,
++ * increase interface count and start initialization.
++ */
++
++ if (conf->type == IEEE80211_IF_TYPE_AP)
++ rt2x00dev->intf_ap_count++;
++ else
++ rt2x00dev->intf_sta_count++;
++
++ spin_lock_init(&intf->lock);
++ intf->beacon = entry;
++
+ if (conf->type == IEEE80211_IF_TYPE_AP)
+ memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN);
+ memcpy(&intf->mac, conf->mac_addr, ETH_ALEN);
+@@ -192,8 +251,14 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
+ * has been initialized. Otherwise the device can reset
+ * the MAC registers.
+ */
+- rt2x00lib_config_mac_addr(rt2x00dev, intf->mac);
+- rt2x00lib_config_type(rt2x00dev, conf->type);
++ rt2x00lib_config_intf(rt2x00dev, intf, conf->type, intf->mac, NULL);
++
++ /*
++ * Some filters depend on the current working mode. We can force
++ * an update during the next configure_filter() run by mac80211 by
++ * resetting the current packet_filter state.
++ */
++ rt2x00dev->packet_filter = 0;
+
+ return 0;
+ }
+@@ -203,7 +268,7 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_init_conf *conf)
+ {
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+- struct interface *intf = &rt2x00dev->interface;
++ struct rt2x00_intf *intf = vif_to_intf(conf->vif);
+
+ /*
+ * Don't allow interfaces to be remove while
+@@ -211,21 +276,27 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
+ * no interface is present.
+ */
+ if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
+- !is_interface_present(intf))
++ (conf->type == IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_ap_count) ||
++ (conf->type != IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_sta_count))
+ return;
+
+- intf->id = 0;
+- intf->type = IEEE80211_IF_TYPE_INVALID;
+- memset(&intf->bssid, 0x00, ETH_ALEN);
+- memset(&intf->mac, 0x00, ETH_ALEN);
++ if (conf->type == IEEE80211_IF_TYPE_AP)
++ rt2x00dev->intf_ap_count--;
++ else
++ rt2x00dev->intf_sta_count--;
++
++ /*
++ * Release beacon entry so it is available for
++ * new interfaces again.
++ */
++ __clear_bit(ENTRY_BCN_ASSIGNED, &intf->beacon->flags);
+
+ /*
+ * Make sure the bssid and mac address registers
+ * are cleared to prevent false ACKing of frames.
+ */
+- rt2x00lib_config_mac_addr(rt2x00dev, intf->mac);
+- rt2x00lib_config_bssid(rt2x00dev, intf->bssid);
+- rt2x00lib_config_type(rt2x00dev, intf->type);
++ rt2x00lib_config_intf(rt2x00dev, intf,
++ IEEE80211_IF_TYPE_INVALID, NULL, NULL);
+ }
+ EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface);
+
+@@ -270,7 +341,7 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_conf *conf)
+ {
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+- struct interface *intf = &rt2x00dev->interface;
++ struct rt2x00_intf *intf = vif_to_intf(vif);
+ int status;
+
+ /*
+@@ -280,12 +351,7 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
+ if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
+ return 0;
+
+- /*
+- * If the given type does not match the configured type,
+- * there has been a problem.
+- */
+- if (conf->type != intf->type)
+- return -EINVAL;
++ spin_lock(&intf->lock);
+
+ /*
+ * If the interface does not work in master mode,
+@@ -294,7 +360,16 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
+ */
+ if (conf->type != IEEE80211_IF_TYPE_AP)
+ memcpy(&intf->bssid, conf->bssid, ETH_ALEN);
+- rt2x00lib_config_bssid(rt2x00dev, intf->bssid);
++
++ spin_unlock(&intf->lock);
++
++ /*
++ * Call rt2x00_config_intf() outside of the spinlock context since
++ * the call will sleep for USB drivers. By using the ieee80211_if_conf
++ * values as arguments we make keep access to rt2x00_intf thread safe
++ * even without the lock.
++ */
++ rt2x00lib_config_intf(rt2x00dev, intf, conf->type, NULL, conf->bssid);
+
+ /*
+ * We only need to initialize the beacon when master mode is enabled.
+@@ -312,6 +387,50 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
+ }
+ EXPORT_SYMBOL_GPL(rt2x00mac_config_interface);
+
++void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
++ unsigned int changed_flags,
++ unsigned int *total_flags,
++ int mc_count, struct dev_addr_list *mc_list)
++{
++ struct rt2x00_dev *rt2x00dev = hw->priv;
++
++ /*
++ * Mask off any flags we are going to ignore
++ * from the total_flags field.
++ */
++ *total_flags &=
++ FIF_ALLMULTI |
++ FIF_FCSFAIL |
++ FIF_PLCPFAIL |
++ FIF_CONTROL |
++ FIF_OTHER_BSS |
++ FIF_PROMISC_IN_BSS;
++
++ /*
++ * Apply some rules to the filters:
++ * - Some filters imply different filters to be set.
++ * - Some things we can't filter out at all.
++ * - Multicast filter seems to kill broadcast traffic so never use it.
++ */
++ *total_flags |= FIF_ALLMULTI;
++ if (*total_flags & FIF_OTHER_BSS ||
++ *total_flags & FIF_PROMISC_IN_BSS)
++ *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
++
++ /*
++ * Check if there is any work left for us.
++ */
++ if (rt2x00dev->packet_filter == *total_flags)
++ return;
++ rt2x00dev->packet_filter = *total_flags;
++
++ if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
++ rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags);
++ else
++ queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work);
++}
++EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter);
++
+ int rt2x00mac_get_stats(struct ieee80211_hw *hw,
+ struct ieee80211_low_level_stats *stats)
+ {
+@@ -334,9 +453,11 @@ int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw,
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+ unsigned int i;
+
+- for (i = 0; i < hw->queues; i++)
+- memcpy(&stats->data[i], &rt2x00dev->tx[i].stats,
+- sizeof(rt2x00dev->tx[i].stats));
++ for (i = 0; i < hw->queues; i++) {
++ stats->data[i].len = rt2x00dev->tx[i].length;
++ stats->data[i].limit = rt2x00dev->tx[i].limit;
++ stats->data[i].count = rt2x00dev->tx[i].count;
++ }
+
+ return 0;
+ }
+@@ -348,71 +469,83 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
+ u32 changes)
+ {
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+- int short_preamble;
+- int ack_timeout;
+- int ack_consume_time;
+- int difs;
+- int preamble;
++ struct rt2x00_intf *intf = vif_to_intf(vif);
++ unsigned int delayed = 0;
+
+ /*
+- * We only support changing preamble mode.
++ * When the association status has changed we must reset the link
++ * tuner counter. This is because some drivers determine if they
++ * should perform link tuning based on the number of seconds
++ * while associated or not associated.
+ */
+- if (!(changes & BSS_CHANGED_ERP_PREAMBLE))
+- return;
+-
+- short_preamble = bss_conf->use_short_preamble;
+- preamble = bss_conf->use_short_preamble ?
+- SHORT_PREAMBLE : PREAMBLE;
++ if (changes & BSS_CHANGED_ASSOC) {
++ rt2x00dev->link.count = 0;
+
+- difs = (hw->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) ?
+- SHORT_DIFS : DIFS;
+- ack_timeout = difs + PLCP + preamble + get_duration(ACK_SIZE, 10);
++ if (bss_conf->assoc)
++ rt2x00dev->intf_associated++;
++ else
++ rt2x00dev->intf_associated--;
+
+- ack_consume_time = SIFS + PLCP + preamble + get_duration(ACK_SIZE, 10);
++ if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
++ rt2x00leds_led_assoc(rt2x00dev,
++ !!rt2x00dev->intf_associated);
++ else
++ delayed |= DELAYED_LED_ASSOC;
++ }
+
+- if (short_preamble)
+- __set_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags);
+- else
+- __clear_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags);
++ /*
++ * When the erp information has changed, we should perform
++ * additional configuration steps. For all other changes we are done.
++ */
++ if (changes & BSS_CHANGED_ERP_PREAMBLE) {
++ if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
++ rt2x00lib_config_erp(rt2x00dev, intf, bss_conf);
++ else
++ delayed |= DELAYED_CONFIG_ERP;
++ }
+
+- rt2x00dev->ops->lib->config_preamble(rt2x00dev, short_preamble,
+- ack_timeout, ack_consume_time);
++ spin_lock(&intf->lock);
++ memcpy(&intf->conf, bss_conf, sizeof(*bss_conf));
++ if (delayed) {
++ intf->delayed_flags |= delayed;
++ queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work);
++ }
++ spin_unlock(&intf->lock);
+ }
+ EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed);
+
+-int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue,
++int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue_idx,
+ const struct ieee80211_tx_queue_params *params)
+ {
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+- struct data_ring *ring;
++ struct data_queue *queue;
+
+- ring = rt2x00lib_get_ring(rt2x00dev, queue);
+- if (unlikely(!ring))
++ queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
++ if (unlikely(!queue))
+ return -EINVAL;
+
+ /*
+ * The passed variables are stored as real value ((2^n)-1).
+ * Ralink registers require to know the bit number 'n'.
+ */
+- if (params->cw_min)
+- ring->tx_params.cw_min = fls(params->cw_min);
++ if (params->cw_min > 0)
++ queue->cw_min = fls(params->cw_min);
+ else
+- ring->tx_params.cw_min = 5; /* cw_min: 2^5 = 32. */
++ queue->cw_min = 5; /* cw_min: 2^5 = 32. */
+
+- if (params->cw_max)
+- ring->tx_params.cw_max = fls(params->cw_max);
++ if (params->cw_max > 0)
++ queue->cw_max = fls(params->cw_max);
+ else
+- ring->tx_params.cw_max = 10; /* cw_min: 2^10 = 1024. */
++ queue->cw_max = 10; /* cw_min: 2^10 = 1024. */
+
+- if (params->aifs)
+- ring->tx_params.aifs = params->aifs;
++ if (params->aifs >= 0)
++ queue->aifs = params->aifs;
+ else
+- ring->tx_params.aifs = 2;
++ queue->aifs = 2;
+
+ INFO(rt2x00dev,
+- "Configured TX ring %d - CWmin: %d, CWmax: %d, Aifs: %d.\n",
+- queue, ring->tx_params.cw_min, ring->tx_params.cw_max,
+- ring->tx_params.aifs);
++ "Configured TX queue %d - CWmin: %d, CWmax: %d, Aifs: %d.\n",
++ queue_idx, queue->cw_min, queue->cw_max, queue->aifs);
+
+ return 0;
+ }
+diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
+index 804a998..7867ec6 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
++++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+@@ -32,64 +32,21 @@
+ #include "rt2x00pci.h"
+
+ /*
+- * Beacon handlers.
+- */
+-int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
+- struct ieee80211_tx_control *control)
+-{
+- struct rt2x00_dev *rt2x00dev = hw->priv;
+- struct skb_desc *desc;
+- struct data_ring *ring;
+- struct data_entry *entry;
+-
+- /*
+- * Just in case mac80211 doesn't set this correctly,
+- * but we need this queue set for the descriptor
+- * initialization.
+- */
+- control->queue = IEEE80211_TX_QUEUE_BEACON;
+- ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
+- entry = rt2x00_get_data_entry(ring);
+-
+- /*
+- * Fill in skb descriptor
+- */
+- desc = get_skb_desc(skb);
+- desc->desc_len = ring->desc_size;
+- desc->data_len = skb->len;
+- desc->desc = entry->priv;
+- desc->data = skb->data;
+- desc->ring = ring;
+- desc->entry = entry;
+-
+- memcpy(entry->data_addr, skb->data, skb->len);
+- rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
+-
+- /*
+- * Enable beacon generation.
+- */
+- rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue);
+-
+- return 0;
+-}
+-EXPORT_SYMBOL_GPL(rt2x00pci_beacon_update);
+-
+-/*
+ * TX data handlers.
+ */
+ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
+- struct data_ring *ring, struct sk_buff *skb,
++ struct data_queue *queue, struct sk_buff *skb,
+ struct ieee80211_tx_control *control)
+ {
+- struct data_entry *entry = rt2x00_get_data_entry(ring);
+- __le32 *txd = entry->priv;
+- struct skb_desc *desc;
++ struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
++ struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
++ struct skb_frame_desc *skbdesc;
+ u32 word;
+
+- if (rt2x00_ring_full(ring))
++ if (rt2x00queue_full(queue))
+ return -EINVAL;
+
+- rt2x00_desc_read(txd, 0, &word);
++ rt2x00_desc_read(priv_tx->desc, 0, &word);
+
+ if (rt2x00_get_field32(word, TXD_ENTRY_OWNER_NIC) ||
+ rt2x00_get_field32(word, TXD_ENTRY_VALID)) {
+@@ -103,18 +60,18 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
+ /*
+ * Fill in skb descriptor
+ */
+- desc = get_skb_desc(skb);
+- desc->desc_len = ring->desc_size;
+- desc->data_len = skb->len;
+- desc->desc = entry->priv;
+- desc->data = skb->data;
+- desc->ring = ring;
+- desc->entry = entry;
+-
+- memcpy(entry->data_addr, skb->data, skb->len);
++ skbdesc = get_skb_frame_desc(skb);
++ skbdesc->data = skb->data;
++ skbdesc->data_len = skb->len;
++ skbdesc->desc = priv_tx->desc;
++ skbdesc->desc_len = queue->desc_size;
++ skbdesc->entry = entry;
++
++ memcpy(&priv_tx->control, control, sizeof(priv_tx->control));
++ memcpy(priv_tx->data, skb->data, skb->len);
+ rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
+
+- rt2x00_ring_index_inc(ring);
++ rt2x00queue_index_inc(queue, Q_INDEX);
+
+ return 0;
+ }
+@@ -125,29 +82,28 @@ EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data);
+ */
+ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
+ {
+- struct data_ring *ring = rt2x00dev->rx;
+- struct data_entry *entry;
+- struct sk_buff *skb;
++ struct data_queue *queue = rt2x00dev->rx;
++ struct queue_entry *entry;
++ struct queue_entry_priv_pci_rx *priv_rx;
+ struct ieee80211_hdr *hdr;
+- struct skb_desc *skbdesc;
+- struct rxdata_entry_desc desc;
++ struct skb_frame_desc *skbdesc;
++ struct rxdone_entry_desc rxdesc;
+ int header_size;
+- __le32 *rxd;
+ int align;
+ u32 word;
+
+ while (1) {
+- entry = rt2x00_get_data_entry(ring);
+- rxd = entry->priv;
+- rt2x00_desc_read(rxd, 0, &word);
++ entry = rt2x00queue_get_entry(queue, Q_INDEX);
++ priv_rx = entry->priv_data;
++ rt2x00_desc_read(priv_rx->desc, 0, &word);
+
+ if (rt2x00_get_field32(word, RXD_ENTRY_OWNER_NIC))
+ break;
+
+- memset(&desc, 0, sizeof(desc));
+- rt2x00dev->ops->lib->fill_rxdone(entry, &desc);
++ memset(&rxdesc, 0, sizeof(rxdesc));
++ rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);
+
+- hdr = (struct ieee80211_hdr *)entry->data_addr;
++ hdr = (struct ieee80211_hdr *)priv_rx->data;
+ header_size =
+ ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
+
+@@ -161,66 +117,68 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
+ * Allocate the sk_buffer, initialize it and copy
+ * all data into it.
+ */
+- skb = dev_alloc_skb(desc.size + align);
+- if (!skb)
++ entry->skb = dev_alloc_skb(rxdesc.size + align);
++ if (!entry->skb)
+ return;
+
+- skb_reserve(skb, align);
+- memcpy(skb_put(skb, desc.size), entry->data_addr, desc.size);
++ skb_reserve(entry->skb, align);
++ memcpy(skb_put(entry->skb, rxdesc.size),
++ priv_rx->data, rxdesc.size);
+
+ /*
+ * Fill in skb descriptor
+ */
+- skbdesc = get_skb_desc(skb);
+- skbdesc->desc_len = entry->ring->desc_size;
+- skbdesc->data_len = skb->len;
+- skbdesc->desc = entry->priv;
+- skbdesc->data = skb->data;
+- skbdesc->ring = ring;
++ skbdesc = get_skb_frame_desc(entry->skb);
++ memset(skbdesc, 0, sizeof(*skbdesc));
++ skbdesc->data = entry->skb->data;
++ skbdesc->data_len = entry->skb->len;
++ skbdesc->desc = priv_rx->desc;
++ skbdesc->desc_len = queue->desc_size;
+ skbdesc->entry = entry;
+
+ /*
+ * Send the frame to rt2x00lib for further processing.
+ */
+- rt2x00lib_rxdone(entry, skb, &desc);
++ rt2x00lib_rxdone(entry, &rxdesc);
+
+- if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) {
++ if (test_bit(DEVICE_ENABLED_RADIO, &queue->rt2x00dev->flags)) {
+ rt2x00_set_field32(&word, RXD_ENTRY_OWNER_NIC, 1);
+- rt2x00_desc_write(rxd, 0, word);
++ rt2x00_desc_write(priv_rx->desc, 0, word);
+ }
+
+- rt2x00_ring_index_inc(ring);
++ rt2x00queue_index_inc(queue, Q_INDEX);
+ }
+ }
+ EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
+
+-void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct data_entry *entry,
+- const int tx_status, const int retry)
++void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry,
++ struct txdone_entry_desc *txdesc)
+ {
++ struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
+ u32 word;
+
+- rt2x00lib_txdone(entry, tx_status, retry);
++ txdesc->control = &priv_tx->control;
++ rt2x00lib_txdone(entry, txdesc);
+
+ /*
+ * Make this entry available for reuse.
+ */
+ entry->flags = 0;
+
+- rt2x00_desc_read(entry->priv, 0, &word);
++ rt2x00_desc_read(priv_tx->desc, 0, &word);
+ rt2x00_set_field32(&word, TXD_ENTRY_OWNER_NIC, 0);
+ rt2x00_set_field32(&word, TXD_ENTRY_VALID, 0);
+- rt2x00_desc_write(entry->priv, 0, word);
++ rt2x00_desc_write(priv_tx->desc, 0, word);
+
+- rt2x00_ring_index_done_inc(entry->ring);
++ rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
+
+ /*
+- * If the data ring was full before the txdone handler
++ * If the data queue was full before the txdone handler
+ * we must make sure the packet queue in the mac80211 stack
+ * is reenabled when the txdone handler has finished.
+ */
+- if (!rt2x00_ring_full(entry->ring))
+- ieee80211_wake_queue(rt2x00dev->hw,
+- entry->tx_status.control.queue);
++ if (!rt2x00queue_full(entry->queue))
++ ieee80211_wake_queue(rt2x00dev->hw, priv_tx->control.queue);
+
+ }
+ EXPORT_SYMBOL_GPL(rt2x00pci_txdone);
+@@ -228,73 +186,122 @@ EXPORT_SYMBOL_GPL(rt2x00pci_txdone);
+ /*
+ * Device initialization handlers.
+ */
+-#define priv_offset(__ring, __i) \
+-({ \
+- ring->data_addr + (i * ring->desc_size); \
++#define desc_size(__queue) \
++({ \
++ ((__queue)->limit * (__queue)->desc_size);\
++})
++
++#define data_size(__queue) \
++({ \
++ ((__queue)->limit * (__queue)->data_size);\
+ })
+
+-#define data_addr_offset(__ring, __i) \
+-({ \
+- (__ring)->data_addr + \
+- ((__ring)->stats.limit * (__ring)->desc_size) + \
+- ((__i) * (__ring)->data_size); \
++#define dma_size(__queue) \
++({ \
++ data_size(__queue) + desc_size(__queue);\
+ })
+
+-#define data_dma_offset(__ring, __i) \
+-({ \
+- (__ring)->data_dma + \
+- ((__ring)->stats.limit * (__ring)->desc_size) + \
+- ((__i) * (__ring)->data_size); \
++#define desc_offset(__queue, __base, __i) \
++({ \
++ (__base) + data_size(__queue) + \
++ ((__i) * (__queue)->desc_size); \
+ })
+
+-static int rt2x00pci_alloc_dma(struct rt2x00_dev *rt2x00dev,
+- struct data_ring *ring)
++#define data_offset(__queue, __base, __i) \
++({ \
++ (__base) + \
++ ((__i) * (__queue)->data_size); \
++})
++
++static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
++ struct data_queue *queue)
+ {
++ struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev);
++ struct queue_entry_priv_pci_rx *priv_rx;
++ struct queue_entry_priv_pci_tx *priv_tx;
++ void *addr;
++ dma_addr_t dma;
++ void *desc_addr;
++ dma_addr_t desc_dma;
++ void *data_addr;
++ dma_addr_t data_dma;
+ unsigned int i;
+
+ /*
+ * Allocate DMA memory for descriptor and buffer.
+ */
+- ring->data_addr = pci_alloc_consistent(rt2x00dev_pci(rt2x00dev),
+- rt2x00_get_ring_size(ring),
+- &ring->data_dma);
+- if (!ring->data_addr)
++ addr = pci_alloc_consistent(pci_dev, dma_size(queue), &dma);
++ if (!addr)
+ return -ENOMEM;
+
++ memset(addr, 0, dma_size(queue));
++
+ /*
+- * Initialize all ring entries to contain valid
+- * addresses.
++ * Initialize all queue entries to contain valid addresses.
+ */
+- for (i = 0; i < ring->stats.limit; i++) {
+- ring->entry[i].priv = priv_offset(ring, i);
+- ring->entry[i].data_addr = data_addr_offset(ring, i);
+- ring->entry[i].data_dma = data_dma_offset(ring, i);
++ for (i = 0; i < queue->limit; i++) {
++ desc_addr = desc_offset(queue, addr, i);
++ desc_dma = desc_offset(queue, dma, i);
++ data_addr = data_offset(queue, addr, i);
++ data_dma = data_offset(queue, dma, i);
++
++ if (queue->qid == QID_RX) {
++ priv_rx = queue->entries[i].priv_data;
++ priv_rx->desc = desc_addr;
++ priv_rx->desc_dma = desc_dma;
++ priv_rx->data = data_addr;
++ priv_rx->data_dma = data_dma;
++ } else {
++ priv_tx = queue->entries[i].priv_data;
++ priv_tx->desc = desc_addr;
++ priv_tx->desc_dma = desc_dma;
++ priv_tx->data = data_addr;
++ priv_tx->data_dma = data_dma;
++ }
+ }
+
+ return 0;
+ }
+
+-static void rt2x00pci_free_dma(struct rt2x00_dev *rt2x00dev,
+- struct data_ring *ring)
++static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev,
++ struct data_queue *queue)
+ {
+- if (ring->data_addr)
+- pci_free_consistent(rt2x00dev_pci(rt2x00dev),
+- rt2x00_get_ring_size(ring),
+- ring->data_addr, ring->data_dma);
+- ring->data_addr = NULL;
++ struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev);
++ struct queue_entry_priv_pci_rx *priv_rx;
++ struct queue_entry_priv_pci_tx *priv_tx;
++ void *data_addr;
++ dma_addr_t data_dma;
++
++ if (queue->qid == QID_RX) {
++ priv_rx = queue->entries[0].priv_data;
++ data_addr = priv_rx->data;
++ data_dma = priv_rx->data_dma;
++
++ priv_rx->data = NULL;
++ } else {
++ priv_tx = queue->entries[0].priv_data;
++ data_addr = priv_tx->data;
++ data_dma = priv_tx->data_dma;
++
++ priv_tx->data = NULL;
++ }
++
++ if (data_addr)
++ pci_free_consistent(pci_dev, dma_size(queue),
++ data_addr, data_dma);
+ }
+
+ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
+ {
+ struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev);
+- struct data_ring *ring;
++ struct data_queue *queue;
+ int status;
+
+ /*
+ * Allocate DMA
+ */
+- ring_for_each(rt2x00dev, ring) {
+- status = rt2x00pci_alloc_dma(rt2x00dev, ring);
++ queue_for_each(rt2x00dev, queue) {
++ status = rt2x00pci_alloc_queue_dma(rt2x00dev, queue);
+ if (status)
+ goto exit;
+ }
+@@ -321,7 +328,7 @@ EXPORT_SYMBOL_GPL(rt2x00pci_initialize);
+
+ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev)
+ {
+- struct data_ring *ring;
++ struct data_queue *queue;
+
+ /*
+ * Free irq line.
+@@ -331,8 +338,8 @@ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev)
+ /*
+ * Free DMA
+ */
+- ring_for_each(rt2x00dev, ring)
+- rt2x00pci_free_dma(rt2x00dev, ring);
++ queue_for_each(rt2x00dev, queue)
++ rt2x00pci_free_queue_dma(rt2x00dev, queue);
+ }
+ EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize);
+
+@@ -347,9 +354,9 @@ static void rt2x00pci_free_reg(struct rt2x00_dev *rt2x00dev)
+ kfree(rt2x00dev->eeprom);
+ rt2x00dev->eeprom = NULL;
+
+- if (rt2x00dev->csr_addr) {
+- iounmap(rt2x00dev->csr_addr);
+- rt2x00dev->csr_addr = NULL;
++ if (rt2x00dev->csr.base) {
++ iounmap(rt2x00dev->csr.base);
++ rt2x00dev->csr.base = NULL;
+ }
+ }
+
+@@ -357,9 +364,9 @@ static int rt2x00pci_alloc_reg(struct rt2x00_dev *rt2x00dev)
+ {
+ struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev);
+
+- rt2x00dev->csr_addr = ioremap(pci_resource_start(pci_dev, 0),
++ rt2x00dev->csr.base = ioremap(pci_resource_start(pci_dev, 0),
+ pci_resource_len(pci_dev, 0));
+- if (!rt2x00dev->csr_addr)
++ if (!rt2x00dev->csr.base)
+ goto exit;
+
+ rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL);
+@@ -530,5 +537,5 @@ EXPORT_SYMBOL_GPL(rt2x00pci_resume);
+ */
+ MODULE_AUTHOR(DRV_PROJECT);
+ MODULE_VERSION(DRV_VERSION);
+-MODULE_DESCRIPTION("rt2x00 library");
++MODULE_DESCRIPTION("rt2x00 pci library");
+ MODULE_LICENSE("GPL");
+diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h
+index 2d1eb81..9d1cdb9 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00pci.h
++++ b/drivers/net/wireless/rt2x00/rt2x00pci.h
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+@@ -61,7 +61,7 @@ static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned long offset,
+ u32 *value)
+ {
+- *value = readl(rt2x00dev->csr_addr + offset);
++ *value = readl(rt2x00dev->csr.base + offset);
+ }
+
+ static inline void
+@@ -69,14 +69,14 @@ rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev,
+ const unsigned long offset,
+ void *value, const u16 length)
+ {
+- memcpy_fromio(value, rt2x00dev->csr_addr + offset, length);
++ memcpy_fromio(value, rt2x00dev->csr.base + offset, length);
+ }
+
+ static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev,
+ const unsigned long offset,
+ u32 value)
+ {
+- writel(value, rt2x00dev->csr_addr + offset);
++ writel(value, rt2x00dev->csr.base + offset);
+ }
+
+ static inline void
+@@ -84,28 +84,63 @@ rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev,
+ const unsigned long offset,
+ void *value, const u16 length)
+ {
+- memcpy_toio(rt2x00dev->csr_addr + offset, value, length);
++ memcpy_toio(rt2x00dev->csr.base + offset, value, length);
+ }
+
+ /*
+- * Beacon handlers.
+- */
+-int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
+- struct ieee80211_tx_control *control);
+-
+-/*
+ * TX data handlers.
+ */
+ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
+- struct data_ring *ring, struct sk_buff *skb,
++ struct data_queue *queue, struct sk_buff *skb,
+ struct ieee80211_tx_control *control);
+
+-/*
+- * RX/TX data handlers.
++/**
++ * struct queue_entry_priv_pci_rx: Per RX entry PCI specific information
++ *
++ * @desc: Pointer to device descriptor.
++ * @data: Pointer to device's entry memory.
++ * @dma: DMA pointer to &data.
++ */
++struct queue_entry_priv_pci_rx {
++ __le32 *desc;
++ dma_addr_t desc_dma;
++
++ void *data;
++ dma_addr_t data_dma;
++};
++
++/**
++ * struct queue_entry_priv_pci_tx: Per TX entry PCI specific information
++ *
++ * @desc: Pointer to device descriptor
++ * @data: Pointer to device's entry memory.
++ * @dma: DMA pointer to &data.
++ * @control: mac80211 control structure used to transmit data.
++ */
++struct queue_entry_priv_pci_tx {
++ __le32 *desc;
++ dma_addr_t desc_dma;
++
++ void *data;
++ dma_addr_t data_dma;
++
++ struct ieee80211_tx_control control;
++};
++
++/**
++ * rt2x00pci_rxdone - Handle RX done events
++ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ */
+ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev);
+-void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct data_entry *entry,
+- const int tx_status, const int retry);
++
++/**
++ * rt2x00pci_txdone - Handle TX done events
++ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
++ * @entry: Entry which has completed the transmission of a frame.
++ * @desc: TX done descriptor
++ */
++void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry,
++ struct txdone_entry_desc *desc);
+
+ /*
+ * Device initialization handlers.
+diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
+new file mode 100644
+index 0000000..659e9f4
+--- /dev/null
++++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
+@@ -0,0 +1,304 @@
++/*
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
++ <http://rt2x00.serialmonkey.com>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the
++ Free Software Foundation, Inc.,
++ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++/*
++ Module: rt2x00lib
++ Abstract: rt2x00 queue specific routines.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++
++#include "rt2x00.h"
++#include "rt2x00lib.h"
++
++struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,
++ const unsigned int queue)
++{
++ int atim = test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
++
++ if (queue < rt2x00dev->hw->queues && rt2x00dev->tx)
++ return &rt2x00dev->tx[queue];
++
++ if (!rt2x00dev->bcn)
++ return NULL;
++
++ if (queue == RT2X00_BCN_QUEUE_BEACON)
++ return &rt2x00dev->bcn[0];
++ else if (queue == RT2X00_BCN_QUEUE_ATIM && atim)
++ return &rt2x00dev->bcn[1];
++
++ return NULL;
++}
++EXPORT_SYMBOL_GPL(rt2x00queue_get_queue);
++
++struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
++ enum queue_index index)
++{
++ struct queue_entry *entry;
++ unsigned long irqflags;
++
++ if (unlikely(index >= Q_INDEX_MAX)) {
++ ERROR(queue->rt2x00dev,
++ "Entry requested from invalid index type (%d)\n", index);
++ return NULL;
++ }
++
++ spin_lock_irqsave(&queue->lock, irqflags);
++
++ entry = &queue->entries[queue->index[index]];
++
++ spin_unlock_irqrestore(&queue->lock, irqflags);
++
++ return entry;
++}
++EXPORT_SYMBOL_GPL(rt2x00queue_get_entry);
++
++void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
++{
++ unsigned long irqflags;
++
++ if (unlikely(index >= Q_INDEX_MAX)) {
++ ERROR(queue->rt2x00dev,
++ "Index change on invalid index type (%d)\n", index);
++ return;
++ }
++
++ spin_lock_irqsave(&queue->lock, irqflags);
++
++ queue->index[index]++;
++ if (queue->index[index] >= queue->limit)
++ queue->index[index] = 0;
++
++ if (index == Q_INDEX) {
++ queue->length++;
++ } else if (index == Q_INDEX_DONE) {
++ queue->length--;
++ queue->count ++;
++ }
++
++ spin_unlock_irqrestore(&queue->lock, irqflags);
++}
++EXPORT_SYMBOL_GPL(rt2x00queue_index_inc);
++
++static void rt2x00queue_reset(struct data_queue *queue)
++{
++ unsigned long irqflags;
++
++ spin_lock_irqsave(&queue->lock, irqflags);
++
++ queue->count = 0;
++ queue->length = 0;
++ memset(queue->index, 0, sizeof(queue->index));
++
++ spin_unlock_irqrestore(&queue->lock, irqflags);
++}
++
++void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev)
++{
++ struct data_queue *queue = rt2x00dev->rx;
++ unsigned int i;
++
++ rt2x00queue_reset(queue);
++
++ if (!rt2x00dev->ops->lib->init_rxentry)
++ return;
++
++ for (i = 0; i < queue->limit; i++)
++ rt2x00dev->ops->lib->init_rxentry(rt2x00dev,
++ &queue->entries[i]);
++}
++
++void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev)
++{
++ struct data_queue *queue;
++ unsigned int i;
++
++ txall_queue_for_each(rt2x00dev, queue) {
++ rt2x00queue_reset(queue);
++
++ if (!rt2x00dev->ops->lib->init_txentry)
++ continue;
++
++ for (i = 0; i < queue->limit; i++)
++ rt2x00dev->ops->lib->init_txentry(rt2x00dev,
++ &queue->entries[i]);
++ }
++}
++
++static int rt2x00queue_alloc_entries(struct data_queue *queue,
++ const struct data_queue_desc *qdesc)
++{
++ struct queue_entry *entries;
++ unsigned int entry_size;
++ unsigned int i;
++
++ rt2x00queue_reset(queue);
++
++ queue->limit = qdesc->entry_num;
++ queue->data_size = qdesc->data_size;
++ queue->desc_size = qdesc->desc_size;
++
++ /*
++ * Allocate all queue entries.
++ */
++ entry_size = sizeof(*entries) + qdesc->priv_size;
++ entries = kzalloc(queue->limit * entry_size, GFP_KERNEL);
++ if (!entries)
++ return -ENOMEM;
++
++#define QUEUE_ENTRY_PRIV_OFFSET(__base, __index, __limit, __esize, __psize) \
++ ( ((char *)(__base)) + ((__limit) * (__esize)) + \
++ ((__index) * (__psize)) )
++
++ for (i = 0; i < queue->limit; i++) {
++ entries[i].flags = 0;
++ entries[i].queue = queue;
++ entries[i].skb = NULL;
++ entries[i].entry_idx = i;
++ entries[i].priv_data =
++ QUEUE_ENTRY_PRIV_OFFSET(entries, i, queue->limit,
++ sizeof(*entries), qdesc->priv_size);
++ }
++
++#undef QUEUE_ENTRY_PRIV_OFFSET
++
++ queue->entries = entries;
++
++ return 0;
++}
++
++int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev)
++{
++ struct data_queue *queue;
++ int status;
++
++
++ status = rt2x00queue_alloc_entries(rt2x00dev->rx, rt2x00dev->ops->rx);
++ if (status)
++ goto exit;
++
++ tx_queue_for_each(rt2x00dev, queue) {
++ status = rt2x00queue_alloc_entries(queue, rt2x00dev->ops->tx);
++ if (status)
++ goto exit;
++ }
++
++ status = rt2x00queue_alloc_entries(rt2x00dev->bcn, rt2x00dev->ops->bcn);
++ if (status)
++ goto exit;
++
++ if (!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags))
++ return 0;
++
++ status = rt2x00queue_alloc_entries(&rt2x00dev->bcn[1],
++ rt2x00dev->ops->atim);
++ if (status)
++ goto exit;
++
++ return 0;
++
++exit:
++ ERROR(rt2x00dev, "Queue entries allocation failed.\n");
++
++ rt2x00queue_uninitialize(rt2x00dev);
++
++ return status;
++}
++
++void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev)
++{
++ struct data_queue *queue;
++
++ queue_for_each(rt2x00dev, queue) {
++ kfree(queue->entries);
++ queue->entries = NULL;
++ }
++}
++
++static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev,
++ struct data_queue *queue, enum data_queue_qid qid)
++{
++ spin_lock_init(&queue->lock);
++
++ queue->rt2x00dev = rt2x00dev;
++ queue->qid = qid;
++ queue->aifs = 2;
++ queue->cw_min = 5;
++ queue->cw_max = 10;
++}
++
++int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)
++{
++ struct data_queue *queue;
++ enum data_queue_qid qid;
++ unsigned int req_atim =
++ !!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
++
++ /*
++ * We need the following queues:
++ * RX: 1
++ * TX: hw->queues
++ * Beacon: 1
++ * Atim: 1 (if required)
++ */
++ rt2x00dev->data_queues = 2 + rt2x00dev->hw->queues + req_atim;
++
++ queue = kzalloc(rt2x00dev->data_queues * sizeof(*queue), GFP_KERNEL);
++ if (!queue) {
++ ERROR(rt2x00dev, "Queue allocation failed.\n");
++ return -ENOMEM;
++ }
++
++ /*
++ * Initialize pointers
++ */
++ rt2x00dev->rx = queue;
++ rt2x00dev->tx = &queue[1];
++ rt2x00dev->bcn = &queue[1 + rt2x00dev->hw->queues];
++
++ /*
++ * Initialize queue parameters.
++ * RX: qid = QID_RX
++ * TX: qid = QID_AC_BE + index
++ * TX: cw_min: 2^5 = 32.
++ * TX: cw_max: 2^10 = 1024.
++ * BCN & Atim: qid = QID_MGMT
++ */
++ rt2x00queue_init(rt2x00dev, rt2x00dev->rx, QID_RX);
++
++ qid = QID_AC_BE;
++ tx_queue_for_each(rt2x00dev, queue)
++ rt2x00queue_init(rt2x00dev, queue, qid++);
++
++ rt2x00queue_init(rt2x00dev, &rt2x00dev->bcn[0], QID_MGMT);
++ if (req_atim)
++ rt2x00queue_init(rt2x00dev, &rt2x00dev->bcn[1], QID_MGMT);
++
++ return 0;
++}
++
++void rt2x00queue_free(struct rt2x00_dev *rt2x00dev)
++{
++ kfree(rt2x00dev->rx);
++ rt2x00dev->rx = NULL;
++ rt2x00dev->tx = NULL;
++ rt2x00dev->bcn = NULL;
++}
+diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
+new file mode 100644
+index 0000000..7027c9f
+--- /dev/null
++++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
+@@ -0,0 +1,468 @@
++/*
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
++ <http://rt2x00.serialmonkey.com>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the
++ Free Software Foundation, Inc.,
++ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++/*
++ Module: rt2x00
++ Abstract: rt2x00 queue datastructures and routines
++ */
++
++#ifndef RT2X00QUEUE_H
++#define RT2X00QUEUE_H
++
++#include <linux/prefetch.h>
++
++/**
++ * DOC: Entrie frame size
++ *
++ * Ralink PCI devices demand the Frame size to be a multiple of 128 bytes,
++ * for USB devices this restriction does not apply, but the value of
++ * 2432 makes sense since it is big enough to contain the maximum fragment
++ * size according to the ieee802.11 specs.
++ */
++#define DATA_FRAME_SIZE 2432
++#define MGMT_FRAME_SIZE 256
++
++/**
++ * DOC: Number of entries per queue
++ *
++ * After research it was concluded that 12 entries in a RX and TX
++ * queue would be sufficient. Although this is almost one third of
++ * the amount the legacy driver allocated, the queues aren't getting
++ * filled to the maximum even when working with the maximum rate.
++ */
++#define RX_ENTRIES 12
++#define TX_ENTRIES 12
++#define BEACON_ENTRIES 1
++#define ATIM_ENTRIES 1
++
++/**
++ * enum data_queue_qid: Queue identification
++ */
++enum data_queue_qid {
++ QID_AC_BE = 0,
++ QID_AC_BK = 1,
++ QID_AC_VI = 2,
++ QID_AC_VO = 3,
++ QID_HCCA = 4,
++ QID_MGMT = 13,
++ QID_RX = 14,
++ QID_OTHER = 15,
++};
++
++/**
++ * enum rt2x00_bcn_queue: Beacon queue index
++ *
++ * Start counting with a high offset, this because this enumeration
++ * supplements &enum ieee80211_tx_queue and we should prevent value
++ * conflicts.
++ *
++ * @RT2X00_BCN_QUEUE_BEACON: Beacon queue
++ * @RT2X00_BCN_QUEUE_ATIM: Atim queue (sends frame after beacon)
++ */
++enum rt2x00_bcn_queue {
++ RT2X00_BCN_QUEUE_BEACON = 100,
++ RT2X00_BCN_QUEUE_ATIM = 101,
++};
++
++/**
++ * enum skb_frame_desc_flags: Flags for &struct skb_frame_desc
++ *
++ * @FRAME_DESC_DRIVER_GENERATED: Frame was generated inside driver
++ * and should not be reported back to mac80211 during txdone.
++ */
++enum skb_frame_desc_flags {
++ FRAME_DESC_DRIVER_GENERATED = 1 << 0,
++};
++
++/**
++ * struct skb_frame_desc: Descriptor information for the skb buffer
++ *
++ * This structure is placed over the skb->cb array, this means that
++ * this structure should not exceed the size of that array (48 bytes).
++ *
++ * @flags: Frame flags, see &enum skb_frame_desc_flags.
++ * @frame_type: Frame type, see &enum rt2x00_dump_type.
++ * @data: Pointer to data part of frame (Start of ieee80211 header).
++ * @desc: Pointer to descriptor part of the frame.
++ * Note that this pointer could point to something outside
++ * of the scope of the skb->data pointer.
++ * @data_len: Length of the frame data.
++ * @desc_len: Length of the frame descriptor.
++
++ * @entry: The entry to which this sk buffer belongs.
++ */
++struct skb_frame_desc {
++ unsigned int flags;
++
++ unsigned int frame_type;
++
++ void *data;
++ void *desc;
++
++ unsigned int data_len;
++ unsigned int desc_len;
++
++ struct queue_entry *entry;
++};
++
++static inline struct skb_frame_desc* get_skb_frame_desc(struct sk_buff *skb)
++{
++ BUILD_BUG_ON(sizeof(struct skb_frame_desc) > sizeof(skb->cb));
++ return (struct skb_frame_desc *)&skb->cb[0];
++}
++
++/**
++ * enum rxdone_entry_desc_flags: Flags for &struct rxdone_entry_desc
++ *
++ * @RXDONE_SIGNAL_PLCP: Does the signal field contain the plcp value,
++ * or does it contain the bitrate itself.
++ * @RXDONE_MY_BSS: Does this frame originate from device's BSS.
++ */
++enum rxdone_entry_desc_flags {
++ RXDONE_SIGNAL_PLCP = 1 << 0,
++ RXDONE_MY_BSS = 1 << 1,
++};
++
++/**
++ * struct rxdone_entry_desc: RX Entry descriptor
++ *
++ * Summary of information that has been read from the RX frame descriptor.
++ *
++ * @signal: Signal of the received frame.
++ * @rssi: RSSI of the received frame.
++ * @size: Data size of the received frame.
++ * @flags: MAC80211 receive flags (See &enum mac80211_rx_flags).
++ * @dev_flags: Ralink receive flags (See &enum rxdone_entry_desc_flags).
++
++ */
++struct rxdone_entry_desc {
++ int signal;
++ int rssi;
++ int size;
++ int flags;
++ int dev_flags;
++};
++
++/**
++ * struct txdone_entry_desc: TX done entry descriptor
++ *
++ * Summary of information that has been read from the TX frame descriptor
++ * after the device is done with transmission.
++ *
++ * @control: Control structure which was used to transmit the frame.
++ * @status: TX status (See &enum tx_status).
++ * @retry: Retry count.
++ */
++struct txdone_entry_desc {
++ struct ieee80211_tx_control *control;
++ int status;
++ int retry;
++};
++
++/**
++ * enum txentry_desc_flags: Status flags for TX entry descriptor
++ *
++ * @ENTRY_TXD_RTS_FRAME: This frame is a RTS frame.
++ * @ENTRY_TXD_OFDM_RATE: This frame is send out with an OFDM rate.
++ * @ENTRY_TXD_MORE_FRAG: This frame is followed by another fragment.
++ * @ENTRY_TXD_REQ_TIMESTAMP: Require timestamp to be inserted.
++ * @ENTRY_TXD_BURST: This frame belongs to the same burst event.
++ * @ENTRY_TXD_ACK: An ACK is required for this frame.
++ */
++enum txentry_desc_flags {
++ ENTRY_TXD_RTS_FRAME,
++ ENTRY_TXD_OFDM_RATE,
++ ENTRY_TXD_MORE_FRAG,
++ ENTRY_TXD_REQ_TIMESTAMP,
++ ENTRY_TXD_BURST,
++ ENTRY_TXD_ACK,
++};
++
++/**
++ * struct txentry_desc: TX Entry descriptor
++ *
++ * Summary of information for the frame descriptor before sending a TX frame.
++ *
++ * @flags: Descriptor flags (See &enum queue_entry_flags).
++ * @queue: Queue identification (See &enum data_queue_qid).
++ * @length_high: PLCP length high word.
++ * @length_low: PLCP length low word.
++ * @signal: PLCP signal.
++ * @service: PLCP service.
++ * @aifs: AIFS value.
++ * @ifs: IFS value.
++ * @cw_min: cwmin value.
++ * @cw_max: cwmax value.
++ */
++struct txentry_desc {
++ unsigned long flags;
++
++ enum data_queue_qid queue;
++
++ u16 length_high;
++ u16 length_low;
++ u16 signal;
++ u16 service;
++
++ int aifs;
++ int ifs;
++ int cw_min;
++ int cw_max;
++};
++
++/**
++ * enum queue_entry_flags: Status flags for queue entry
++ *
++ * @ENTRY_BCN_ASSIGNED: This entry has been assigned to an interface.
++ * As long as this bit is set, this entry may only be touched
++ * through the interface structure.
++ * @ENTRY_OWNER_DEVICE_DATA: This entry is owned by the device for data
++ * transfer (either TX or RX depending on the queue). The entry should
++ * only be touched after the device has signaled it is done with it.
++ * @ENTRY_OWNER_DEVICE_CRYPTO: This entry is owned by the device for data
++ * encryption or decryption. The entry should only be touched after
++ * the device has signaled it is done with it.
++ */
++
++enum queue_entry_flags {
++ ENTRY_BCN_ASSIGNED,
++ ENTRY_OWNER_DEVICE_DATA,
++ ENTRY_OWNER_DEVICE_CRYPTO,
++};
++
++/**
++ * struct queue_entry: Entry inside the &struct data_queue
++ *
++ * @flags: Entry flags, see &enum queue_entry_flags.
++ * @queue: The data queue (&struct data_queue) to which this entry belongs.
++ * @skb: The buffer which is currently being transmitted (for TX queue),
++ * or used to directly recieve data in (for RX queue).
++ * @entry_idx: The entry index number.
++ * @priv_data: Private data belonging to this queue entry. The pointer
++ * points to data specific to a particular driver and queue type.
++ */
++struct queue_entry {
++ unsigned long flags;
++
++ struct data_queue *queue;
++
++ struct sk_buff *skb;
++
++ unsigned int entry_idx;
++
++ void *priv_data;
++};
++
++/**
++ * enum queue_index: Queue index type
++ *
++ * @Q_INDEX: Index pointer to the current entry in the queue, if this entry is
++ * owned by the hardware then the queue is considered to be full.
++ * @Q_INDEX_DONE: Index pointer to the next entry which will be completed by
++ * the hardware and for which we need to run the txdone handler. If this
++ * entry is not owned by the hardware the queue is considered to be empty.
++ * @Q_INDEX_CRYPTO: Index pointer to the next entry which encryption/decription
++ * will be completed by the hardware next.
++ * @Q_INDEX_MAX: Keep last, used in &struct data_queue to determine the size
++ * of the index array.
++ */
++enum queue_index {
++ Q_INDEX,
++ Q_INDEX_DONE,
++ Q_INDEX_CRYPTO,
++ Q_INDEX_MAX,
++};
++
++/**
++ * struct data_queue: Data queue
++ *
++ * @rt2x00dev: Pointer to main &struct rt2x00dev where this queue belongs to.
++ * @entries: Base address of the &struct queue_entry which are
++ * part of this queue.
++ * @qid: The queue identification, see &enum data_queue_qid.
++ * @lock: Spinlock to protect index handling. Whenever @index, @index_done or
++ * @index_crypt needs to be changed this lock should be grabbed to prevent
++ * index corruption due to concurrency.
++ * @count: Number of frames handled in the queue.
++ * @limit: Maximum number of entries in the queue.
++ * @length: Number of frames in queue.
++ * @index: Index pointers to entry positions in the queue,
++ * use &enum queue_index to get a specific index field.
++ * @aifs: The aifs value for outgoing frames (field ignored in RX queue).
++ * @cw_min: The cw min value for outgoing frames (field ignored in RX queue).
++ * @cw_max: The cw max value for outgoing frames (field ignored in RX queue).
++ * @data_size: Maximum data size for the frames in this queue.
++ * @desc_size: Hardware descriptor size for the data in this queue.
++ */
++struct data_queue {
++ struct rt2x00_dev *rt2x00dev;
++ struct queue_entry *entries;
++
++ enum data_queue_qid qid;
++
++ spinlock_t lock;
++ unsigned int count;
++ unsigned short limit;
++ unsigned short length;
++ unsigned short index[Q_INDEX_MAX];
++
++ unsigned short aifs;
++ unsigned short cw_min;
++ unsigned short cw_max;
++
++ unsigned short data_size;
++ unsigned short desc_size;
++};
++
++/**
++ * struct data_queue_desc: Data queue description
++ *
++ * The information in this structure is used by drivers
++ * to inform rt2x00lib about the creation of the data queue.
++ *
++ * @entry_num: Maximum number of entries for a queue.
++ * @data_size: Maximum data size for the frames in this queue.
++ * @desc_size: Hardware descriptor size for the data in this queue.
++ * @priv_size: Size of per-queue_entry private data.
++ */
++struct data_queue_desc {
++ unsigned short entry_num;
++ unsigned short data_size;
++ unsigned short desc_size;
++ unsigned short priv_size;
++};
++
++/**
++ * queue_end - Return pointer to the last queue (HELPER MACRO).
++ * @__dev: Pointer to &struct rt2x00_dev
++ *
++ * Using the base rx pointer and the maximum number of available queues,
++ * this macro will return the address of 1 position beyond the end of the
++ * queues array.
++ */
++#define queue_end(__dev) \
++ &(__dev)->rx[(__dev)->data_queues]
++
++/**
++ * tx_queue_end - Return pointer to the last TX queue (HELPER MACRO).
++ * @__dev: Pointer to &struct rt2x00_dev
++ *
++ * Using the base tx pointer and the maximum number of available TX
++ * queues, this macro will return the address of 1 position beyond
++ * the end of the TX queue array.
++ */
++#define tx_queue_end(__dev) \
++ &(__dev)->tx[(__dev)->hw->queues]
++
++/**
++ * queue_loop - Loop through the queues within a specific range (HELPER MACRO).
++ * @__entry: Pointer where the current queue entry will be stored in.
++ * @__start: Start queue pointer.
++ * @__end: End queue pointer.
++ *
++ * This macro will loop through all queues between &__start and &__end.
++ */
++#define queue_loop(__entry, __start, __end) \
++ for ((__entry) = (__start); \
++ prefetch(&(__entry)[1]), (__entry) != (__end); \
++ (__entry) = &(__entry)[1])
++
++/**
++ * queue_for_each - Loop through all queues
++ * @__dev: Pointer to &struct rt2x00_dev
++ * @__entry: Pointer where the current queue entry will be stored in.
++ *
++ * This macro will loop through all available queues.
++ */
++#define queue_for_each(__dev, __entry) \
++ queue_loop(__entry, (__dev)->rx, queue_end(__dev))
++
++/**
++ * tx_queue_for_each - Loop through the TX queues
++ * @__dev: Pointer to &struct rt2x00_dev
++ * @__entry: Pointer where the current queue entry will be stored in.
++ *
++ * This macro will loop through all TX related queues excluding
++ * the Beacon and Atim queues.
++ */
++#define tx_queue_for_each(__dev, __entry) \
++ queue_loop(__entry, (__dev)->tx, tx_queue_end(__dev))
++
++/**
++ * txall_queue_for_each - Loop through all TX related queues
++ * @__dev: Pointer to &struct rt2x00_dev
++ * @__entry: Pointer where the current queue entry will be stored in.
++ *
++ * This macro will loop through all TX related queues including
++ * the Beacon and Atim queues.
++ */
++#define txall_queue_for_each(__dev, __entry) \
++ queue_loop(__entry, (__dev)->tx, queue_end(__dev))
++
++/**
++ * rt2x00queue_empty - Check if the queue is empty.
++ * @queue: Queue to check if empty.
++ */
++static inline int rt2x00queue_empty(struct data_queue *queue)
++{
++ return queue->length == 0;
++}
++
++/**
++ * rt2x00queue_full - Check if the queue is full.
++ * @queue: Queue to check if full.
++ */
++static inline int rt2x00queue_full(struct data_queue *queue)
++{
++ return queue->length == queue->limit;
++}
++
++/**
++ * rt2x00queue_free - Check the number of available entries in queue.
++ * @queue: Queue to check.
++ */
++static inline int rt2x00queue_available(struct data_queue *queue)
++{
++ return queue->limit - queue->length;
++}
++
++/**
++ * rt2x00_desc_read - Read a word from the hardware descriptor.
++ * @desc: Base descriptor address
++ * @word: Word index from where the descriptor should be read.
++ * @value: Address where the descriptor value should be written into.
++ */
++static inline void rt2x00_desc_read(__le32 *desc, const u8 word, u32 *value)
++{
++ *value = le32_to_cpu(desc[word]);
++}
++
++/**
++ * rt2x00_desc_write - wrote a word to the hardware descriptor.
++ * @desc: Base descriptor address
++ * @word: Word index from where the descriptor should be written.
++ * @value: Value that should be written into the descriptor.
++ */
++static inline void rt2x00_desc_write(__le32 *desc, const u8 word, u32 value)
++{
++ desc[word] = cpu_to_le32(value);
++}
++
++#endif /* RT2X00QUEUE_H */
+diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h
+index b1915dc..0325bed 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00reg.h
++++ b/drivers/net/wireless/rt2x00/rt2x00reg.h
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+@@ -29,7 +29,7 @@
+ /*
+ * TX result flags.
+ */
+-enum TX_STATUS {
++enum tx_status {
+ TX_SUCCESS = 0,
+ TX_SUCCESS_RETRY = 1,
+ TX_FAIL_RETRY = 2,
+@@ -220,75 +220,4 @@ static inline u8 rt2x00_get_field8(const u8 reg,
+ return (reg & field.bit_mask) >> field.bit_offset;
+ }
+
+-/*
+- * Device specific rate value.
+- * We will have to create the device specific rate value
+- * passed to the ieee80211 kernel. We need to make it a consist of
+- * multiple fields because we want to store more then 1 device specific
+- * values inside the value.
+- * 1 - rate, stored as 100 kbit/s.
+- * 2 - preamble, short_preamble enabled flag.
+- * 3 - MASK_RATE, which rates are enabled in this mode, this mask
+- * corresponds with the TX register format for the current device.
+- * 4 - plcp, 802.11b rates are device specific,
+- * 802.11g rates are set according to the ieee802.11a-1999 p.14.
+- * The bit to enable preamble is set in a seperate define.
+- */
+-#define DEV_RATE FIELD32(0x000007ff)
+-#define DEV_PREAMBLE FIELD32(0x00000800)
+-#define DEV_RATEMASK FIELD32(0x00fff000)
+-#define DEV_PLCP FIELD32(0xff000000)
+-
+-/*
+- * Bitfields
+- */
+-#define DEV_RATEBIT_1MB ( 1 << 0 )
+-#define DEV_RATEBIT_2MB ( 1 << 1 )
+-#define DEV_RATEBIT_5_5MB ( 1 << 2 )
+-#define DEV_RATEBIT_11MB ( 1 << 3 )
+-#define DEV_RATEBIT_6MB ( 1 << 4 )
+-#define DEV_RATEBIT_9MB ( 1 << 5 )
+-#define DEV_RATEBIT_12MB ( 1 << 6 )
+-#define DEV_RATEBIT_18MB ( 1 << 7 )
+-#define DEV_RATEBIT_24MB ( 1 << 8 )
+-#define DEV_RATEBIT_36MB ( 1 << 9 )
+-#define DEV_RATEBIT_48MB ( 1 << 10 )
+-#define DEV_RATEBIT_54MB ( 1 << 11 )
+-
+-/*
+- * Bitmasks for DEV_RATEMASK
+- */
+-#define DEV_RATEMASK_1MB ( (DEV_RATEBIT_1MB << 1) -1 )
+-#define DEV_RATEMASK_2MB ( (DEV_RATEBIT_2MB << 1) -1 )
+-#define DEV_RATEMASK_5_5MB ( (DEV_RATEBIT_5_5MB << 1) -1 )
+-#define DEV_RATEMASK_11MB ( (DEV_RATEBIT_11MB << 1) -1 )
+-#define DEV_RATEMASK_6MB ( (DEV_RATEBIT_6MB << 1) -1 )
+-#define DEV_RATEMASK_9MB ( (DEV_RATEBIT_9MB << 1) -1 )
+-#define DEV_RATEMASK_12MB ( (DEV_RATEBIT_12MB << 1) -1 )
+-#define DEV_RATEMASK_18MB ( (DEV_RATEBIT_18MB << 1) -1 )
+-#define DEV_RATEMASK_24MB ( (DEV_RATEBIT_24MB << 1) -1 )
+-#define DEV_RATEMASK_36MB ( (DEV_RATEBIT_36MB << 1) -1 )
+-#define DEV_RATEMASK_48MB ( (DEV_RATEBIT_48MB << 1) -1 )
+-#define DEV_RATEMASK_54MB ( (DEV_RATEBIT_54MB << 1) -1 )
+-
+-/*
+- * Bitmask groups of bitrates
+- */
+-#define DEV_BASIC_RATEMASK \
+- ( DEV_RATEMASK_11MB | \
+- DEV_RATEBIT_6MB | DEV_RATEBIT_12MB | DEV_RATEBIT_24MB )
+-
+-#define DEV_CCK_RATEMASK ( DEV_RATEMASK_11MB )
+-#define DEV_OFDM_RATEMASK ( DEV_RATEMASK_54MB & ~DEV_CCK_RATEMASK )
+-
+-/*
+- * Macro's to set and get specific fields from the device specific val and val2
+- * fields inside the ieee80211_rate entry.
+- */
+-#define DEVICE_SET_RATE_FIELD(__value, __mask) \
+- (int)( ((__value) << DEV_##__mask.bit_offset) & DEV_##__mask.bit_mask )
+-
+-#define DEVICE_GET_RATE_FIELD(__value, __mask) \
+- (int)( ((__value) & DEV_##__mask.bit_mask) >> DEV_##__mask.bit_offset )
+-
+ #endif /* RT2X00REG_H */
+diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c
+index f955775..fcef988 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c
++++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+diff --git a/drivers/net/wireless/rt2x00/rt2x00ring.h b/drivers/net/wireless/rt2x00/rt2x00ring.h
+deleted file mode 100644
+index 1caa6d6..0000000
+--- a/drivers/net/wireless/rt2x00/rt2x00ring.h
++++ /dev/null
+@@ -1,290 +0,0 @@
+-/*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
+- <http://rt2x00.serialmonkey.com>
+-
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; either version 2 of the License, or
+- (at your option) any later version.
+-
+- This program is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- GNU General Public License for more details.
+-
+- You should have received a copy of the GNU General Public License
+- along with this program; if not, write to the
+- Free Software Foundation, Inc.,
+- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+- */
+-
+-/*
+- Module: rt2x00
+- Abstract: rt2x00 ring datastructures and routines
+- */
+-
+-#ifndef RT2X00RING_H
+-#define RT2X00RING_H
+-
+-/*
+- * skb_desc
+- * Descriptor information for the skb buffer
+- */
+-struct skb_desc {
+- unsigned int frame_type;
+-
+- unsigned int desc_len;
+- unsigned int data_len;
+-
+- void *desc;
+- void *data;
+-
+- struct data_ring *ring;
+- struct data_entry *entry;
+-};
+-
+-static inline struct skb_desc* get_skb_desc(struct sk_buff *skb)
+-{
+- return (struct skb_desc*)&skb->cb[0];
+-}
+-
+-/*
+- * rxdata_entry_desc
+- * Summary of information that has been read from the
+- * RX frame descriptor.
+- */
+-struct rxdata_entry_desc {
+- int signal;
+- int rssi;
+- int ofdm;
+- int size;
+- int flags;
+- int my_bss;
+-};
+-
+-/*
+- * txdata_entry_desc
+- * Summary of information that should be written into the
+- * descriptor for sending a TX frame.
+- */
+-struct txdata_entry_desc {
+- unsigned long flags;
+-#define ENTRY_TXDONE 1
+-#define ENTRY_TXD_RTS_FRAME 2
+-#define ENTRY_TXD_OFDM_RATE 3
+-#define ENTRY_TXD_MORE_FRAG 4
+-#define ENTRY_TXD_REQ_TIMESTAMP 5
+-#define ENTRY_TXD_BURST 6
+-#define ENTRY_TXD_ACK 7
+-
+-/*
+- * Queue ID. ID's 0-4 are data TX rings
+- */
+- int queue;
+-#define QUEUE_MGMT 13
+-#define QUEUE_RX 14
+-#define QUEUE_OTHER 15
+-
+- /*
+- * PLCP values.
+- */
+- u16 length_high;
+- u16 length_low;
+- u16 signal;
+- u16 service;
+-
+- /*
+- * Timing information
+- */
+- int aifs;
+- int ifs;
+- int cw_min;
+- int cw_max;
+-};
+-
+-/*
+- * data_entry
+- * The data ring is a list of data entries.
+- * Each entry holds a reference to the descriptor
+- * and the data buffer. For TX rings the reference to the
+- * sk_buff of the packet being transmitted is also stored here.
+- */
+-struct data_entry {
+- /*
+- * Status flags
+- */
+- unsigned long flags;
+-#define ENTRY_OWNER_NIC 1
+-
+- /*
+- * Ring we belong to.
+- */
+- struct data_ring *ring;
+-
+- /*
+- * sk_buff for the packet which is being transmitted
+- * in this entry (Only used with TX related rings).
+- */
+- struct sk_buff *skb;
+-
+- /*
+- * Store a ieee80211_tx_status structure in each
+- * ring entry, this will optimize the txdone
+- * handler.
+- */
+- struct ieee80211_tx_status tx_status;
+-
+- /*
+- * private pointer specific to driver.
+- */
+- void *priv;
+-
+- /*
+- * Data address for this entry.
+- */
+- void *data_addr;
+- dma_addr_t data_dma;
+-
+- /*
+- * Entry identification number (index).
+- */
+- unsigned int entry_idx;
+-};
+-
+-/*
+- * data_ring
+- * Data rings are used by the device to send and receive packets.
+- * The data_addr is the base address of the data memory.
+- * To determine at which point in the ring we are,
+- * have to use the rt2x00_ring_index_*() functions.
+- */
+-struct data_ring {
+- /*
+- * Pointer to main rt2x00dev structure where this
+- * ring belongs to.
+- */
+- struct rt2x00_dev *rt2x00dev;
+-
+- /*
+- * Base address for the device specific data entries.
+- */
+- struct data_entry *entry;
+-
+- /*
+- * TX queue statistic info.
+- */
+- struct ieee80211_tx_queue_stats_data stats;
+-
+- /*
+- * TX Queue parameters.
+- */
+- struct ieee80211_tx_queue_params tx_params;
+-
+- /*
+- * Base address for data ring.
+- */
+- dma_addr_t data_dma;
+- void *data_addr;
+-
+- /*
+- * Queue identification number:
+- * RX: 0
+- * TX: IEEE80211_TX_*
+- */
+- unsigned int queue_idx;
+-
+- /*
+- * Index variables.
+- */
+- u16 index;
+- u16 index_done;
+-
+- /*
+- * Size of packet and descriptor in bytes.
+- */
+- u16 data_size;
+- u16 desc_size;
+-};
+-
+-/*
+- * Handlers to determine the address of the current device specific
+- * data entry, where either index or index_done points to.
+- */
+-static inline struct data_entry *rt2x00_get_data_entry(struct data_ring *ring)
+-{
+- return &ring->entry[ring->index];
+-}
+-
+-static inline struct data_entry *rt2x00_get_data_entry_done(struct data_ring
+- *ring)
+-{
+- return &ring->entry[ring->index_done];
+-}
+-
+-/*
+- * Total ring memory
+- */
+-static inline int rt2x00_get_ring_size(struct data_ring *ring)
+-{
+- return ring->stats.limit * (ring->desc_size + ring->data_size);
+-}
+-
+-/*
+- * Ring index manipulation functions.
+- */
+-static inline void rt2x00_ring_index_inc(struct data_ring *ring)
+-{
+- ring->index++;
+- if (ring->index >= ring->stats.limit)
+- ring->index = 0;
+- ring->stats.len++;
+-}
+-
+-static inline void rt2x00_ring_index_done_inc(struct data_ring *ring)
+-{
+- ring->index_done++;
+- if (ring->index_done >= ring->stats.limit)
+- ring->index_done = 0;
+- ring->stats.len--;
+- ring->stats.count++;
+-}
+-
+-static inline void rt2x00_ring_index_clear(struct data_ring *ring)
+-{
+- ring->index = 0;
+- ring->index_done = 0;
+- ring->stats.len = 0;
+- ring->stats.count = 0;
+-}
+-
+-static inline int rt2x00_ring_empty(struct data_ring *ring)
+-{
+- return ring->stats.len == 0;
+-}
+-
+-static inline int rt2x00_ring_full(struct data_ring *ring)
+-{
+- return ring->stats.len == ring->stats.limit;
+-}
+-
+-static inline int rt2x00_ring_free(struct data_ring *ring)
+-{
+- return ring->stats.limit - ring->stats.len;
+-}
+-
+-/*
+- * TX/RX Descriptor access functions.
+- */
+-static inline void rt2x00_desc_read(__le32 *desc,
+- const u8 word, u32 *value)
+-{
+- *value = le32_to_cpu(desc[word]);
+-}
+-
+-static inline void rt2x00_desc_write(__le32 *desc,
+- const u8 word, const u32 value)
+-{
+- desc[word] = cpu_to_le32(value);
+-}
+-
+-#endif /* RT2X00RING_H */
+diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
+index 84e9bdb..5a33167 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
++++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+@@ -40,8 +40,7 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
+ void *buffer, const u16 buffer_length,
+ const int timeout)
+ {
+- struct usb_device *usb_dev =
+- interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
++ struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev);
+ int status;
+ unsigned int i;
+ unsigned int pipe =
+@@ -85,20 +84,20 @@ int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
+ /*
+ * Check for Cache availability.
+ */
+- if (unlikely(!rt2x00dev->csr_cache || buffer_length > CSR_CACHE_SIZE)) {
++ if (unlikely(!rt2x00dev->csr.cache || buffer_length > CSR_CACHE_SIZE)) {
+ ERROR(rt2x00dev, "CSR cache not available.\n");
+ return -ENOMEM;
+ }
+
+ if (requesttype == USB_VENDOR_REQUEST_OUT)
+- memcpy(rt2x00dev->csr_cache, buffer, buffer_length);
++ memcpy(rt2x00dev->csr.cache, buffer, buffer_length);
+
+ status = rt2x00usb_vendor_request(rt2x00dev, request, requesttype,
+- offset, 0, rt2x00dev->csr_cache,
++ offset, 0, rt2x00dev->csr.cache,
+ buffer_length, timeout);
+
+ if (!status && requesttype == USB_VENDOR_REQUEST_IN)
+- memcpy(buffer, rt2x00dev->csr_cache, buffer_length);
++ memcpy(buffer, rt2x00dev->csr.cache, buffer_length);
+
+ return status;
+ }
+@@ -128,15 +127,15 @@ EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff);
+ */
+ static void rt2x00usb_interrupt_txdone(struct urb *urb)
+ {
+- struct data_entry *entry = (struct data_entry *)urb->context;
+- struct data_ring *ring = entry->ring;
+- struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
++ struct queue_entry *entry = (struct queue_entry *)urb->context;
++ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
++ struct queue_entry_priv_usb_tx *priv_tx = entry->priv_data;
++ struct txdone_entry_desc txdesc;
+ __le32 *txd = (__le32 *)entry->skb->data;
+ u32 word;
+- int tx_status;
+
+ if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
+- !__test_and_clear_bit(ENTRY_OWNER_NIC, &entry->flags))
++ !__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+ return;
+
+ rt2x00_desc_read(txd, 0, &word);
+@@ -144,45 +143,46 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
+ /*
+ * Remove the descriptor data from the buffer.
+ */
+- skb_pull(entry->skb, ring->desc_size);
++ skb_pull(entry->skb, entry->queue->desc_size);
+
+ /*
+ * Obtain the status about this packet.
+ */
+- tx_status = !urb->status ? TX_SUCCESS : TX_FAIL_RETRY;
++ txdesc.status = !urb->status ? TX_SUCCESS : TX_FAIL_RETRY;
++ txdesc.retry = 0;
++ txdesc.control = &priv_tx->control;
+
+- rt2x00lib_txdone(entry, tx_status, 0);
++ rt2x00lib_txdone(entry, &txdesc);
+
+ /*
+ * Make this entry available for reuse.
+ */
+ entry->flags = 0;
+- rt2x00_ring_index_done_inc(entry->ring);
++ rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
+
+ /*
+- * If the data ring was full before the txdone handler
++ * If the data queue was full before the txdone handler
+ * we must make sure the packet queue in the mac80211 stack
+ * is reenabled when the txdone handler has finished.
+ */
+- if (!rt2x00_ring_full(ring))
+- ieee80211_wake_queue(rt2x00dev->hw,
+- entry->tx_status.control.queue);
++ if (!rt2x00queue_full(entry->queue))
++ ieee80211_wake_queue(rt2x00dev->hw, priv_tx->control.queue);
+ }
+
+ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
+- struct data_ring *ring, struct sk_buff *skb,
++ struct data_queue *queue, struct sk_buff *skb,
+ struct ieee80211_tx_control *control)
+ {
+- struct usb_device *usb_dev =
+- interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
+- struct data_entry *entry = rt2x00_get_data_entry(ring);
+- struct skb_desc *desc;
++ struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev);
++ struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
++ struct queue_entry_priv_usb_tx *priv_tx = entry->priv_data;
++ struct skb_frame_desc *skbdesc;
+ u32 length;
+
+- if (rt2x00_ring_full(ring))
++ if (rt2x00queue_full(queue))
+ return -EINVAL;
+
+- if (test_bit(ENTRY_OWNER_NIC, &entry->flags)) {
++ if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) {
+ ERROR(rt2x00dev,
+ "Arrived at non-free entry in the non-full queue %d.\n"
+ "Please file bug report to %s.\n",
+@@ -193,20 +193,20 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
+ /*
+ * Add the descriptor in front of the skb.
+ */
+- skb_push(skb, ring->desc_size);
+- memset(skb->data, 0, ring->desc_size);
++ skb_push(skb, queue->desc_size);
++ memset(skb->data, 0, queue->desc_size);
+
+ /*
+ * Fill in skb descriptor
+ */
+- desc = get_skb_desc(skb);
+- desc->desc_len = ring->desc_size;
+- desc->data_len = skb->len - ring->desc_size;
+- desc->desc = skb->data;
+- desc->data = skb->data + ring->desc_size;
+- desc->ring = ring;
+- desc->entry = entry;
++ skbdesc = get_skb_frame_desc(skb);
++ skbdesc->data = skb->data + queue->desc_size;
++ skbdesc->data_len = skb->len - queue->desc_size;
++ skbdesc->desc = skb->data;
++ skbdesc->desc_len = queue->desc_size;
++ skbdesc->entry = entry;
+
++ memcpy(&priv_tx->control, control, sizeof(priv_tx->control));
+ rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
+
+ /*
+@@ -219,12 +219,12 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
+ /*
+ * Initialize URB and send the frame to the device.
+ */
+- __set_bit(ENTRY_OWNER_NIC, &entry->flags);
+- usb_fill_bulk_urb(entry->priv, usb_dev, usb_sndbulkpipe(usb_dev, 1),
++ __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
++ usb_fill_bulk_urb(priv_tx->urb, usb_dev, usb_sndbulkpipe(usb_dev, 1),
+ skb->data, length, rt2x00usb_interrupt_txdone, entry);
+- usb_submit_urb(entry->priv, GFP_ATOMIC);
++ usb_submit_urb(priv_tx->urb, GFP_ATOMIC);
+
+- rt2x00_ring_index_inc(ring);
++ rt2x00queue_index_inc(queue, Q_INDEX);
+
+ return 0;
+ }
+@@ -233,20 +233,42 @@ EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data);
+ /*
+ * RX data handlers.
+ */
++static struct sk_buff* rt2x00usb_alloc_rxskb(struct data_queue *queue)
++{
++ struct sk_buff *skb;
++ unsigned int frame_size;
++
++ /*
++ * As alignment we use 2 and not NET_IP_ALIGN because we need
++ * to be sure we have 2 bytes room in the head. (NET_IP_ALIGN
++ * can be 0 on some hardware). We use these 2 bytes for frame
++ * alignment later, we assume that the chance that
++ * header_size % 4 == 2 is bigger then header_size % 2 == 0
++ * and thus optimize alignment by reserving the 2 bytes in
++ * advance.
++ */
++ frame_size = queue->data_size + queue->desc_size;
++ skb = dev_alloc_skb(queue->desc_size + frame_size + 2);
++ if (!skb)
++ return NULL;
++
++ skb_reserve(skb, queue->desc_size + 2);
++ skb_put(skb, frame_size);
++
++ return skb;
++}
++
+ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
+ {
+- struct data_entry *entry = (struct data_entry *)urb->context;
+- struct data_ring *ring = entry->ring;
+- struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
++ struct queue_entry *entry = (struct queue_entry *)urb->context;
++ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+ struct sk_buff *skb;
+- struct ieee80211_hdr *hdr;
+- struct skb_desc *skbdesc;
+- struct rxdata_entry_desc desc;
++ struct skb_frame_desc *skbdesc;
++ struct rxdone_entry_desc rxdesc;
+ int header_size;
+- int frame_size;
+
+ if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
+- !test_and_clear_bit(ENTRY_OWNER_NIC, &entry->flags))
++ !test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+ return;
+
+ /*
+@@ -254,67 +276,45 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
+ * to be actually valid, or if the urb is signaling
+ * a problem.
+ */
+- if (urb->actual_length < entry->ring->desc_size || urb->status)
++ if (urb->actual_length < entry->queue->desc_size || urb->status)
+ goto skip_entry;
+
+ /*
+ * Fill in skb descriptor
+ */
+- skbdesc = get_skb_desc(entry->skb);
+- skbdesc->ring = ring;
++ skbdesc = get_skb_frame_desc(entry->skb);
++ memset(skbdesc, 0, sizeof(*skbdesc));
+ skbdesc->entry = entry;
+
+- memset(&desc, 0, sizeof(desc));
+- rt2x00dev->ops->lib->fill_rxdone(entry, &desc);
+-
+- /*
+- * Allocate a new sk buffer to replace the current one.
+- * If allocation fails, we should drop the current frame
+- * so we can recycle the existing sk buffer for the new frame.
+- * As alignment we use 2 and not NET_IP_ALIGN because we need
+- * to be sure we have 2 bytes room in the head. (NET_IP_ALIGN
+- * can be 0 on some hardware). We use these 2 bytes for frame
+- * alignment later, we assume that the chance that
+- * header_size % 4 == 2 is bigger then header_size % 2 == 0
+- * and thus optimize alignment by reserving the 2 bytes in
+- * advance.
+- */
+- frame_size = entry->ring->data_size + entry->ring->desc_size;
+- skb = dev_alloc_skb(frame_size + 2);
+- if (!skb)
+- goto skip_entry;
+-
+- skb_reserve(skb, 2);
+- skb_put(skb, frame_size);
++ memset(&rxdesc, 0, sizeof(rxdesc));
++ rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);
+
+ /*
+ * The data behind the ieee80211 header must be
+ * aligned on a 4 byte boundary.
+ */
+- hdr = (struct ieee80211_hdr *)entry->skb->data;
+- header_size =
+- ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
+-
++ header_size = ieee80211_get_hdrlen_from_skb(entry->skb);
+ if (header_size % 4 == 0) {
+ skb_push(entry->skb, 2);
+- memmove(entry->skb->data, entry->skb->data + 2, skb->len - 2);
++ memmove(entry->skb->data, entry->skb->data + 2,
++ entry->skb->len - 2);
++ skbdesc->data = entry->skb->data;
++ skb_trim(entry->skb,entry->skb->len - 2);
+ }
+
+ /*
+- * Trim the entire buffer down to only contain the valid frame data
+- * excluding the device descriptor. The position of the descriptor
+- * varies. This means that we should check where the descriptor is
+- * and decide if we need to pull the data pointer to exclude the
+- * device descriptor.
++ * Allocate a new sk buffer to replace the current one.
++ * If allocation fails, we should drop the current frame
++ * so we can recycle the existing sk buffer for the new frame.
+ */
+- if (skbdesc->data > skbdesc->desc)
+- skb_pull(entry->skb, skbdesc->desc_len);
+- skb_trim(entry->skb, desc.size);
++ skb = rt2x00usb_alloc_rxskb(entry->queue);
++ if (!skb)
++ goto skip_entry;
+
+ /*
+ * Send the frame to rt2x00lib for further processing.
+ */
+- rt2x00lib_rxdone(entry, entry->skb, &desc);
++ rt2x00lib_rxdone(entry, &rxdesc);
+
+ /*
+ * Replace current entry's skb with the newly allocated one,
+@@ -325,12 +325,12 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
+ urb->transfer_buffer_length = entry->skb->len;
+
+ skip_entry:
+- if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) {
+- __set_bit(ENTRY_OWNER_NIC, &entry->flags);
++ if (test_bit(DEVICE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags)) {
++ __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
+ usb_submit_urb(urb, GFP_ATOMIC);
+ }
+
+- rt2x00_ring_index_inc(ring);
++ rt2x00queue_index_inc(entry->queue, Q_INDEX);
+ }
+
+ /*
+@@ -338,18 +338,44 @@ skip_entry:
+ */
+ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev)
+ {
+- struct data_ring *ring;
++ struct queue_entry_priv_usb_rx *priv_rx;
++ struct queue_entry_priv_usb_tx *priv_tx;
++ struct queue_entry_priv_usb_bcn *priv_bcn;
++ struct data_queue *queue;
+ unsigned int i;
+
+ rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0x0000, 0x0000,
+ REGISTER_TIMEOUT);
+
+ /*
+- * Cancel all rings.
++ * Cancel all queues.
+ */
+- ring_for_each(rt2x00dev, ring) {
+- for (i = 0; i < ring->stats.limit; i++)
+- usb_kill_urb(ring->entry[i].priv);
++ for (i = 0; i < rt2x00dev->rx->limit; i++) {
++ priv_rx = rt2x00dev->rx->entries[i].priv_data;
++ usb_kill_urb(priv_rx->urb);
++ }
++
++ tx_queue_for_each(rt2x00dev, queue) {
++ for (i = 0; i < queue->limit; i++) {
++ priv_tx = queue->entries[i].priv_data;
++ usb_kill_urb(priv_tx->urb);
++ }
++ }
++
++ for (i = 0; i < rt2x00dev->bcn->limit; i++) {
++ priv_bcn = rt2x00dev->bcn->entries[i].priv_data;
++ usb_kill_urb(priv_bcn->urb);
++
++ if (priv_bcn->guardian_urb)
++ usb_kill_urb(priv_bcn->guardian_urb);
++ }
++
++ if (!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags))
++ return;
++
++ for (i = 0; i < rt2x00dev->bcn[1].limit; i++) {
++ priv_tx = rt2x00dev->bcn[1].entries[i].priv_data;
++ usb_kill_urb(priv_tx->urb);
+ }
+ }
+ EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
+@@ -358,64 +384,108 @@ EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
+ * Device initialization handlers.
+ */
+ void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev,
+- struct data_entry *entry)
++ struct queue_entry *entry)
+ {
+- struct usb_device *usb_dev =
+- interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
++ struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev);
++ struct queue_entry_priv_usb_rx *priv_rx = entry->priv_data;
+
+- usb_fill_bulk_urb(entry->priv, usb_dev,
++ usb_fill_bulk_urb(priv_rx->urb, usb_dev,
+ usb_rcvbulkpipe(usb_dev, 1),
+ entry->skb->data, entry->skb->len,
+ rt2x00usb_interrupt_rxdone, entry);
+
+- __set_bit(ENTRY_OWNER_NIC, &entry->flags);
+- usb_submit_urb(entry->priv, GFP_ATOMIC);
++ __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
++ usb_submit_urb(priv_rx->urb, GFP_ATOMIC);
+ }
+ EXPORT_SYMBOL_GPL(rt2x00usb_init_rxentry);
+
+ void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev,
+- struct data_entry *entry)
++ struct queue_entry *entry)
+ {
+ entry->flags = 0;
+ }
+ EXPORT_SYMBOL_GPL(rt2x00usb_init_txentry);
+
+ static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev,
+- struct data_ring *ring)
++ struct data_queue *queue)
+ {
++ struct queue_entry_priv_usb_rx *priv_rx;
++ struct queue_entry_priv_usb_tx *priv_tx;
++ struct queue_entry_priv_usb_bcn *priv_bcn;
++ struct urb *urb;
++ unsigned int guardian =
++ test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags);
+ unsigned int i;
+
+ /*
+ * Allocate the URB's
+ */
+- for (i = 0; i < ring->stats.limit; i++) {
+- ring->entry[i].priv = usb_alloc_urb(0, GFP_KERNEL);
+- if (!ring->entry[i].priv)
++ for (i = 0; i < queue->limit; i++) {
++ urb = usb_alloc_urb(0, GFP_KERNEL);
++ if (!urb)
+ return -ENOMEM;
++
++ if (queue->qid == QID_RX) {
++ priv_rx = queue->entries[i].priv_data;
++ priv_rx->urb = urb;
++ } else if (queue->qid == QID_MGMT && guardian) {
++ priv_bcn = queue->entries[i].priv_data;
++ priv_bcn->urb = urb;
++
++ urb = usb_alloc_urb(0, GFP_KERNEL);
++ if (!urb)
++ return -ENOMEM;
++
++ priv_bcn->guardian_urb = urb;
++ } else {
++ priv_tx = queue->entries[i].priv_data;
++ priv_tx->urb = urb;
++ }
+ }
+
+ return 0;
+ }
+
+ static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev,
+- struct data_ring *ring)
++ struct data_queue *queue)
+ {
++ struct queue_entry_priv_usb_rx *priv_rx;
++ struct queue_entry_priv_usb_tx *priv_tx;
++ struct queue_entry_priv_usb_bcn *priv_bcn;
++ struct urb *urb;
++ unsigned int guardian =
++ test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags);
+ unsigned int i;
+
+- if (!ring->entry)
++ if (!queue->entries)
+ return;
+
+- for (i = 0; i < ring->stats.limit; i++) {
+- usb_kill_urb(ring->entry[i].priv);
+- usb_free_urb(ring->entry[i].priv);
+- if (ring->entry[i].skb)
+- kfree_skb(ring->entry[i].skb);
++ for (i = 0; i < queue->limit; i++) {
++ if (queue->qid == QID_RX) {
++ priv_rx = queue->entries[i].priv_data;
++ urb = priv_rx->urb;
++ } else if (queue->qid == QID_MGMT && guardian) {
++ priv_bcn = queue->entries[i].priv_data;
++
++ usb_kill_urb(priv_bcn->guardian_urb);
++ usb_free_urb(priv_bcn->guardian_urb);
++
++ urb = priv_bcn->urb;
++ } else {
++ priv_tx = queue->entries[i].priv_data;
++ urb = priv_tx->urb;
++ }
++
++ usb_kill_urb(urb);
++ usb_free_urb(urb);
++ if (queue->entries[i].skb)
++ kfree_skb(queue->entries[i].skb);
+ }
+ }
+
+ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev)
+ {
+- struct data_ring *ring;
++ struct data_queue *queue;
+ struct sk_buff *skb;
+ unsigned int entry_size;
+ unsigned int i;
+@@ -424,25 +494,22 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev)
+ /*
+ * Allocate DMA
+ */
+- ring_for_each(rt2x00dev, ring) {
+- status = rt2x00usb_alloc_urb(rt2x00dev, ring);
++ queue_for_each(rt2x00dev, queue) {
++ status = rt2x00usb_alloc_urb(rt2x00dev, queue);
+ if (status)
+ goto exit;
+ }
+
+ /*
+- * For the RX ring, skb's should be allocated.
++ * For the RX queue, skb's should be allocated.
+ */
+ entry_size = rt2x00dev->rx->data_size + rt2x00dev->rx->desc_size;
+- for (i = 0; i < rt2x00dev->rx->stats.limit; i++) {
+- skb = dev_alloc_skb(NET_IP_ALIGN + entry_size);
++ for (i = 0; i < rt2x00dev->rx->limit; i++) {
++ skb = rt2x00usb_alloc_rxskb(rt2x00dev->rx);
+ if (!skb)
+ goto exit;
+
+- skb_reserve(skb, NET_IP_ALIGN);
+- skb_put(skb, entry_size);
+-
+- rt2x00dev->rx->entry[i].skb = skb;
++ rt2x00dev->rx->entries[i].skb = skb;
+ }
+
+ return 0;
+@@ -456,10 +523,10 @@ EXPORT_SYMBOL_GPL(rt2x00usb_initialize);
+
+ void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev)
+ {
+- struct data_ring *ring;
++ struct data_queue *queue;
+
+- ring_for_each(rt2x00dev, ring)
+- rt2x00usb_free_urb(rt2x00dev, ring);
++ queue_for_each(rt2x00dev, queue)
++ rt2x00usb_free_urb(rt2x00dev, queue);
+ }
+ EXPORT_SYMBOL_GPL(rt2x00usb_uninitialize);
+
+@@ -474,14 +541,14 @@ static void rt2x00usb_free_reg(struct rt2x00_dev *rt2x00dev)
+ kfree(rt2x00dev->eeprom);
+ rt2x00dev->eeprom = NULL;
+
+- kfree(rt2x00dev->csr_cache);
+- rt2x00dev->csr_cache = NULL;
++ kfree(rt2x00dev->csr.cache);
++ rt2x00dev->csr.cache = NULL;
+ }
+
+ static int rt2x00usb_alloc_reg(struct rt2x00_dev *rt2x00dev)
+ {
+- rt2x00dev->csr_cache = kzalloc(CSR_CACHE_SIZE, GFP_KERNEL);
+- if (!rt2x00dev->csr_cache)
++ rt2x00dev->csr.cache = kzalloc(CSR_CACHE_SIZE, GFP_KERNEL);
++ if (!rt2x00dev->csr.cache)
+ goto exit;
+
+ rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL);
+@@ -627,9 +694,9 @@ EXPORT_SYMBOL_GPL(rt2x00usb_resume);
+ #endif /* CONFIG_PM */
+
+ /*
+- * rt2x00pci module information.
++ * rt2x00usb module information.
+ */
+ MODULE_AUTHOR(DRV_PROJECT);
+ MODULE_VERSION(DRV_VERSION);
+-MODULE_DESCRIPTION("rt2x00 library");
++MODULE_DESCRIPTION("rt2x00 usb library");
+ MODULE_LICENSE("GPL");
+diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
+index e40df40..11e5518 100644
+--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
++++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+@@ -60,34 +60,47 @@
+ #define USB_VENDOR_REQUEST_IN ( USB_DIR_IN | USB_VENDOR_REQUEST )
+ #define USB_VENDOR_REQUEST_OUT ( USB_DIR_OUT | USB_VENDOR_REQUEST )
+
+-/*
+- * USB vendor commands.
+- */
+-#define USB_DEVICE_MODE 0x01
+-#define USB_SINGLE_WRITE 0x02
+-#define USB_SINGLE_READ 0x03
+-#define USB_MULTI_WRITE 0x06
+-#define USB_MULTI_READ 0x07
+-#define USB_EEPROM_WRITE 0x08
+-#define USB_EEPROM_READ 0x09
+-#define USB_LED_CONTROL 0x0a /* RT73USB */
+-#define USB_RX_CONTROL 0x0c
++/**
++ * enum rt2x00usb_vendor_request: USB vendor commands.
++ */
++enum rt2x00usb_vendor_request {
++ USB_DEVICE_MODE = 1,
++ USB_SINGLE_WRITE = 2,
++ USB_SINGLE_READ = 3,
++ USB_MULTI_WRITE = 6,
++ USB_MULTI_READ = 7,
++ USB_EEPROM_WRITE = 8,
++ USB_EEPROM_READ = 9,
++ USB_LED_CONTROL = 10, /* RT73USB */
++ USB_RX_CONTROL = 12,
++};
+
+-/*
+- * Device modes offset
++/**
++ * enum rt2x00usb_mode_offset: Device modes offset.
+ */
+-#define USB_MODE_RESET 0x01
+-#define USB_MODE_UNPLUG 0x02
+-#define USB_MODE_FUNCTION 0x03
+-#define USB_MODE_TEST 0x04
+-#define USB_MODE_SLEEP 0x07 /* RT73USB */
+-#define USB_MODE_FIRMWARE 0x08 /* RT73USB */
+-#define USB_MODE_WAKEUP 0x09 /* RT73USB */
++enum rt2x00usb_mode_offset {
++ USB_MODE_RESET = 1,
++ USB_MODE_UNPLUG = 2,
++ USB_MODE_FUNCTION = 3,
++ USB_MODE_TEST = 4,
++ USB_MODE_SLEEP = 7, /* RT73USB */
++ USB_MODE_FIRMWARE = 8, /* RT73USB */
++ USB_MODE_WAKEUP = 9, /* RT73USB */
++};
+
+-/*
+- * Used to read/write from/to the device.
++/**
++ * rt2x00usb_vendor_request - Send register command to device
++ * @rt2x00dev: Pointer to &struct rt2x00_dev
++ * @request: USB vendor command (See &enum rt2x00usb_vendor_request)
++ * @requesttype: Request type &USB_VENDOR_REQUEST_*
++ * @offset: Register offset to perform action on
++ * @value: Value to write to device
++ * @buffer: Buffer where information will be read/written to by device
++ * @buffer_length: Size of &buffer
++ * @timeout: Operation timeout
++ *
+ * This is the main function to communicate with the device,
+- * the buffer argument _must_ either be NULL or point to
++ * the &buffer argument _must_ either be NULL or point to
+ * a buffer allocated by kmalloc. Failure to do so can lead
+ * to unexpected behavior depending on the architecture.
+ */
+@@ -97,13 +110,21 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
+ void *buffer, const u16 buffer_length,
+ const int timeout);
+
+-/*
+- * Used to read/write from/to the device.
++/**
++ * rt2x00usb_vendor_request_buff - Send register command to device (buffered)
++ * @rt2x00dev: Pointer to &struct rt2x00_dev
++ * @request: USB vendor command (See &enum rt2x00usb_vendor_request)
++ * @requesttype: Request type &USB_VENDOR_REQUEST_*
++ * @offset: Register offset to perform action on
++ * @buffer: Buffer where information will be read/written to by device
++ * @buffer_length: Size of &buffer
++ * @timeout: Operation timeout
++ *
+ * This function will use a previously with kmalloc allocated cache
+ * to communicate with the device. The contents of the buffer pointer
+ * will be copied to this cache when writing, or read from the cache
+ * when reading.
+- * Buffers send to rt2x00usb_vendor_request _must_ be allocated with
++ * Buffers send to &rt2x00usb_vendor_request _must_ be allocated with
+ * kmalloc. Hence the reason for using a previously allocated cache
+ * which has been allocated properly.
+ */
+@@ -112,15 +133,32 @@ int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
+ const u16 offset, void *buffer,
+ const u16 buffer_length, const int timeout);
+
+-/*
+- * A version of rt2x00usb_vendor_request_buff which must be called
+- * if the usb_cache_mutex is already held. */
++/**
++ * rt2x00usb_vendor_request_buff - Send register command to device (buffered)
++ * @rt2x00dev: Pointer to &struct rt2x00_dev
++ * @request: USB vendor command (See &enum rt2x00usb_vendor_request)
++ * @requesttype: Request type &USB_VENDOR_REQUEST_*
++ * @offset: Register offset to perform action on
++ * @buffer: Buffer where information will be read/written to by device
++ * @buffer_length: Size of &buffer
++ * @timeout: Operation timeout
++ *
++ * A version of &rt2x00usb_vendor_request_buff which must be called
++ * if the usb_cache_mutex is already held.
++ */
+ int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
+ const u8 request, const u8 requesttype,
+ const u16 offset, void *buffer,
+ const u16 buffer_length, const int timeout);
+
+-/*
++/**
++ * rt2x00usb_vendor_request_sw - Send single register command to device
++ * @rt2x00dev: Pointer to &struct rt2x00_dev
++ * @request: USB vendor command (See &enum rt2x00usb_vendor_request)
++ * @offset: Register offset to perform action on
++ * @value: Value to write to device
++ * @timeout: Operation timeout
++ *
+ * Simple wrapper around rt2x00usb_vendor_request to write a single
+ * command to the device. Since we don't use the buffer argument we
+ * don't have to worry about kmalloc here.
+@@ -136,7 +174,12 @@ static inline int rt2x00usb_vendor_request_sw(struct rt2x00_dev *rt2x00dev,
+ value, NULL, 0, timeout);
+ }
+
+-/*
++/**
++ * rt2x00usb_eeprom_read - Read eeprom from device
++ * @rt2x00dev: Pointer to &struct rt2x00_dev
++ * @eeprom: Pointer to eeprom array to store the information in
++ * @length: Number of bytes to read from the eeprom
++ *
+ * Simple wrapper around rt2x00usb_vendor_request to read the eeprom
+ * from the device. Note that the eeprom argument _must_ be allocated using
+ * kmalloc for correct handling inside the kernel USB layer.
+@@ -147,8 +190,8 @@ static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev,
+ int timeout = REGISTER_TIMEOUT * (lenght / sizeof(u16));
+
+ return rt2x00usb_vendor_request(rt2x00dev, USB_EEPROM_READ,
+- USB_VENDOR_REQUEST_IN, 0x0000,
+- 0x0000, eeprom, lenght, timeout);
++ USB_VENDOR_REQUEST_IN, 0, 0,
++ eeprom, lenght, timeout);
+ }
+
+ /*
+@@ -160,16 +203,58 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev);
+ * TX data handlers.
+ */
+ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
+- struct data_ring *ring, struct sk_buff *skb,
++ struct data_queue *queue, struct sk_buff *skb,
+ struct ieee80211_tx_control *control);
+
++/**
++ * struct queue_entry_priv_usb_rx: Per RX entry USB specific information
++ *
++ * @urb: Urb structure used for device communication.
++ */
++struct queue_entry_priv_usb_rx {
++ struct urb *urb;
++};
++
++/**
++ * struct queue_entry_priv_usb_tx: Per TX entry USB specific information
++ *
++ * @urb: Urb structure used for device communication.
++ * @control: mac80211 control structure used to transmit data.
++ */
++struct queue_entry_priv_usb_tx {
++ struct urb *urb;
++
++ struct ieee80211_tx_control control;
++};
++
++/**
++ * struct queue_entry_priv_usb_tx: Per TX entry USB specific information
++ *
++ * The first section should match &struct queue_entry_priv_usb_tx exactly.
++ * rt2500usb can use this structure to send a guardian byte when working
++ * with beacons.
++ *
++ * @urb: Urb structure used for device communication.
++ * @control: mac80211 control structure used to transmit data.
++ * @guardian_data: Set to 0, used for sending the guardian data.
++ * @guardian_urb: Urb structure used to send the guardian data.
++ */
++struct queue_entry_priv_usb_bcn {
++ struct urb *urb;
++
++ struct ieee80211_tx_control control;
++
++ unsigned int guardian_data;
++ struct urb *guardian_urb;
++};
++
+ /*
+ * Device initialization handlers.
+ */
+ void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev,
+- struct data_entry *entry);
++ struct queue_entry *entry);
+ void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev,
+- struct data_entry *entry);
++ struct queue_entry *entry);
+ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev);
+ void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev);
+
+diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
+index ad2e7d5..468a31c 100644
+--- a/drivers/net/wireless/rt2x00/rt61pci.c
++++ b/drivers/net/wireless/rt2x00/rt61pci.c
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+@@ -24,6 +24,7 @@
+ Supported chipsets: RT2561, RT2561s, RT2661.
+ */
+
++#include <linux/crc-itu-t.h>
+ #include <linux/delay.h>
+ #include <linux/etherdevice.h>
+ #include <linux/init.h>
+@@ -155,6 +156,12 @@ rf_write:
+ rt2x00_rf_write(rt2x00dev, word, value);
+ }
+
++#ifdef CONFIG_RT61PCI_LEDS
++/*
++ * This function is only called from rt61pci_led_brightness()
++ * make gcc happy by placing this function inside the
++ * same ifdef statement as the caller.
++ */
+ static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev,
+ const u8 command, const u8 token,
+ const u8 arg0, const u8 arg1)
+@@ -181,6 +188,7 @@ static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev,
+ rt2x00_set_field32(®, HOST_CMD_CSR_INTERRUPT_MCU, 1);
+ rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg);
+ }
++#endif /* CONFIG_RT61PCI_LEDS */
+
+ static void rt61pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
+ {
+@@ -262,82 +270,162 @@ static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
+ u32 reg;
+
+ rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®);
+- return rt2x00_get_field32(reg, MAC_CSR13_BIT5);;
++ return rt2x00_get_field32(reg, MAC_CSR13_BIT5);
+ }
+ #else
+ #define rt61pci_rfkill_poll NULL
+ #endif /* CONFIG_RT61PCI_RFKILL */
+
+-/*
+- * Configuration handlers.
+- */
+-static void rt61pci_config_mac_addr(struct rt2x00_dev *rt2x00dev, __le32 *mac)
++#ifdef CONFIG_RT61PCI_LEDS
++static void rt61pci_brightness_set(struct led_classdev *led_cdev,
++ enum led_brightness brightness)
+ {
+- u32 tmp;
+-
+- tmp = le32_to_cpu(mac[1]);
+- rt2x00_set_field32(&tmp, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
+- mac[1] = cpu_to_le32(tmp);
+-
+- rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2, mac,
+- (2 * sizeof(__le32)));
++ struct rt2x00_led *led =
++ container_of(led_cdev, struct rt2x00_led, led_dev);
++ unsigned int enabled = brightness != LED_OFF;
++ unsigned int a_mode =
++ (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
++ unsigned int bg_mode =
++ (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
++
++ if (led->type == LED_TYPE_RADIO) {
++ rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
++ MCU_LEDCS_RADIO_STATUS, enabled);
++
++ rt61pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff,
++ (led->rt2x00dev->led_mcu_reg & 0xff),
++ ((led->rt2x00dev->led_mcu_reg >> 8)));
++ } else if (led->type == LED_TYPE_ASSOC) {
++ rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
++ MCU_LEDCS_LINK_BG_STATUS, bg_mode);
++ rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
++ MCU_LEDCS_LINK_A_STATUS, a_mode);
++
++ rt61pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff,
++ (led->rt2x00dev->led_mcu_reg & 0xff),
++ ((led->rt2x00dev->led_mcu_reg >> 8)));
++ } else if (led->type == LED_TYPE_QUALITY) {
++ /*
++ * The brightness is divided into 6 levels (0 - 5),
++ * this means we need to convert the brightness
++ * argument into the matching level within that range.
++ */
++ rt61pci_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff,
++ brightness / (LED_FULL / 6), 0);
++ }
+ }
+
+-static void rt61pci_config_bssid(struct rt2x00_dev *rt2x00dev, __le32 *bssid)
++static int rt61pci_blink_set(struct led_classdev *led_cdev,
++ unsigned long *delay_on,
++ unsigned long *delay_off)
+ {
+- u32 tmp;
++ struct rt2x00_led *led =
++ container_of(led_cdev, struct rt2x00_led, led_dev);
++ u32 reg;
+
+- tmp = le32_to_cpu(bssid[1]);
+- rt2x00_set_field32(&tmp, MAC_CSR5_BSS_ID_MASK, 3);
+- bssid[1] = cpu_to_le32(tmp);
++ rt2x00pci_register_read(led->rt2x00dev, MAC_CSR14, ®);
++ rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, *delay_on);
++ rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, *delay_off);
++ rt2x00pci_register_write(led->rt2x00dev, MAC_CSR14, reg);
+
+- rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4, bssid,
+- (2 * sizeof(__le32)));
++ return 0;
+ }
++#endif /* CONFIG_RT61PCI_LEDS */
+
+-static void rt61pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,
+- const int tsf_sync)
++/*
++ * Configuration handlers.
++ */
++static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev,
++ const unsigned int filter_flags)
+ {
+ u32 reg;
+
+ /*
+- * Clear current synchronisation setup.
+- * For the Beacon base registers we only need to clear
+- * the first byte since that byte contains the VALID and OWNER
+- * bits which (when set to 0) will invalidate the entire beacon.
++ * Start configuration steps.
++ * Note that the version error will always be dropped
++ * and broadcast frames will always be accepted since
++ * there is no filter for it at this time.
+ */
+- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0);
+- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
+- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
+- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
+- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
++ rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®);
++ rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC,
++ !(filter_flags & FIF_FCSFAIL));
++ rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL,
++ !(filter_flags & FIF_PLCPFAIL));
++ rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL,
++ !(filter_flags & FIF_CONTROL));
++ rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME,
++ !(filter_flags & FIF_PROMISC_IN_BSS));
++ rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS,
++ !(filter_flags & FIF_PROMISC_IN_BSS) &&
++ !rt2x00dev->intf_ap_count);
++ rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1);
++ rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST,
++ !(filter_flags & FIF_ALLMULTI));
++ rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0);
++ rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS,
++ !(filter_flags & FIF_CONTROL));
++ rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
++}
+
+- /*
+- * Enable synchronisation.
+- */
+- rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®);
+- rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1);
+- rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE,
+- (tsf_sync == TSF_SYNC_BEACON));
+- rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0);
+- rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, tsf_sync);
+- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
++static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,
++ struct rt2x00_intf *intf,
++ struct rt2x00intf_conf *conf,
++ const unsigned int flags)
++{
++ unsigned int beacon_base;
++ u32 reg;
++
++ if (flags & CONFIG_UPDATE_TYPE) {
++ /*
++ * Clear current synchronisation setup.
++ * For the Beacon base registers we only need to clear
++ * the first byte since that byte contains the VALID and OWNER
++ * bits which (when set to 0) will invalidate the entire beacon.
++ */
++ beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
++ rt2x00pci_register_write(rt2x00dev, beacon_base, 0);
++
++ /*
++ * Enable synchronisation.
++ */
++ rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®);
++ rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1);
++ rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync);
++ rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1);
++ rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
++ }
++
++ if (flags & CONFIG_UPDATE_MAC) {
++ reg = le32_to_cpu(conf->mac[1]);
++ rt2x00_set_field32(®, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
++ conf->mac[1] = cpu_to_le32(reg);
++
++ rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2,
++ conf->mac, sizeof(conf->mac));
++ }
++
++ if (flags & CONFIG_UPDATE_BSSID) {
++ reg = le32_to_cpu(conf->bssid[1]);
++ rt2x00_set_field32(®, MAC_CSR5_BSS_ID_MASK, 3);
++ conf->bssid[1] = cpu_to_le32(reg);
++
++ rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4,
++ conf->bssid, sizeof(conf->bssid));
++ }
+ }
+
+-static void rt61pci_config_preamble(struct rt2x00_dev *rt2x00dev,
+- const int short_preamble,
+- const int ack_timeout,
+- const int ack_consume_time)
++static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,
++ struct rt2x00lib_erp *erp)
+ {
+ u32 reg;
+
+ rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®);
+- rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout);
++ rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout);
+ rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
+
+ rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®);
+ rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE,
+- !!short_preamble);
++ !!erp->short_preamble);
+ rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
+ }
+
+@@ -427,27 +515,21 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
+ case ANTENNA_HW_DIVERSITY:
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
+ rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
+- (rt2x00dev->curr_hwmode != HWMODE_A));
++ (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ));
+ break;
+ case ANTENNA_A:
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
+- if (rt2x00dev->curr_hwmode == HWMODE_A)
++ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
+ else
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
+ break;
+- case ANTENNA_SW_DIVERSITY:
+- /*
+- * NOTE: We should never come here because rt2x00lib is
+- * supposed to catch this and send us the correct antenna
+- * explicitely. However we are nog going to bug about this.
+- * Instead, just default to antenna B.
+- */
+ case ANTENNA_B:
++ default:
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
+- if (rt2x00dev->curr_hwmode == HWMODE_A)
++ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
+ else
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
+@@ -486,14 +568,8 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
+ break;
+- case ANTENNA_SW_DIVERSITY:
+- /*
+- * NOTE: We should never come here because rt2x00lib is
+- * supposed to catch this and send us the correct antenna
+- * explicitely. However we are nog going to bug about this.
+- * Instead, just default to antenna B.
+- */
+ case ANTENNA_B:
++ default:
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
+ break;
+@@ -531,10 +607,6 @@ static void rt61pci_config_antenna_2529(struct rt2x00_dev *rt2x00dev,
+ rt61pci_bbp_read(rt2x00dev, 4, &r4);
+ rt61pci_bbp_read(rt2x00dev, 77, &r77);
+
+- /* FIXME: Antenna selection for the rf 2529 is very confusing in the
+- * legacy driver. The code below should be ok for non-diversity setups.
+- */
+-
+ /*
+ * Configure the RX antenna.
+ */
+@@ -544,15 +616,14 @@ static void rt61pci_config_antenna_2529(struct rt2x00_dev *rt2x00dev,
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
+ rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 0);
+ break;
+- case ANTENNA_SW_DIVERSITY:
+ case ANTENNA_HW_DIVERSITY:
+ /*
+- * NOTE: We should never come here because rt2x00lib is
+- * supposed to catch this and send us the correct antenna
+- * explicitely. However we are nog going to bug about this.
+- * Instead, just default to antenna B.
++ * FIXME: Antenna selection for the rf 2529 is very confusing
++ * in the legacy driver. Just default to antenna B until the
++ * legacy code can be properly translated into rt2x00 code.
+ */
+ case ANTENNA_B:
++ default:
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
+ rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 1);
+@@ -603,7 +674,14 @@ static void rt61pci_config_antenna(struct rt2x00_dev *rt2x00dev,
+ unsigned int i;
+ u32 reg;
+
+- if (rt2x00dev->curr_hwmode == HWMODE_A) {
++ /*
++ * We should never come here because rt2x00lib is supposed
++ * to catch this and send us the correct antenna explicitely.
++ */
++ BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
++ ant->tx == ANTENNA_SW_DIVERSITY);
++
++ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
+ sel = antenna_sel_a;
+ lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
+ } else {
+@@ -617,10 +695,9 @@ static void rt61pci_config_antenna(struct rt2x00_dev *rt2x00dev,
+ rt2x00pci_register_read(rt2x00dev, PHY_CSR0, ®);
+
+ rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG,
+- (rt2x00dev->curr_hwmode == HWMODE_B ||
+- rt2x00dev->curr_hwmode == HWMODE_G));
++ rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
+ rt2x00_set_field32(®, PHY_CSR0_PA_PE_A,
+- (rt2x00dev->curr_hwmode == HWMODE_A));
++ rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
+
+ rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg);
+
+@@ -667,8 +744,8 @@ static void rt61pci_config_duration(struct rt2x00_dev *rt2x00dev,
+ }
+
+ static void rt61pci_config(struct rt2x00_dev *rt2x00dev,
+- const unsigned int flags,
+- struct rt2x00lib_conf *libconf)
++ struct rt2x00lib_conf *libconf,
++ const unsigned int flags)
+ {
+ if (flags & CONFIG_UPDATE_PHYMODE)
+ rt61pci_config_phymode(rt2x00dev, libconf->basic_rates);
+@@ -684,78 +761,6 @@ static void rt61pci_config(struct rt2x00_dev *rt2x00dev,
+ }
+
+ /*
+- * LED functions.
+- */
+-static void rt61pci_enable_led(struct rt2x00_dev *rt2x00dev)
+-{
+- u32 reg;
+- u8 arg0;
+- u8 arg1;
+-
+- rt2x00pci_register_read(rt2x00dev, MAC_CSR14, ®);
+- rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, 70);
+- rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, 30);
+- rt2x00pci_register_write(rt2x00dev, MAC_CSR14, reg);
+-
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1);
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS,
+- (rt2x00dev->rx_status.phymode == MODE_IEEE80211A));
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS,
+- (rt2x00dev->rx_status.phymode != MODE_IEEE80211A));
+-
+- arg0 = rt2x00dev->led_reg & 0xff;
+- arg1 = (rt2x00dev->led_reg >> 8) & 0xff;
+-
+- rt61pci_mcu_request(rt2x00dev, MCU_LED, 0xff, arg0, arg1);
+-}
+-
+-static void rt61pci_disable_led(struct rt2x00_dev *rt2x00dev)
+-{
+- u16 led_reg;
+- u8 arg0;
+- u8 arg1;
+-
+- led_reg = rt2x00dev->led_reg;
+- rt2x00_set_field16(&led_reg, MCU_LEDCS_RADIO_STATUS, 0);
+- rt2x00_set_field16(&led_reg, MCU_LEDCS_LINK_BG_STATUS, 0);
+- rt2x00_set_field16(&led_reg, MCU_LEDCS_LINK_A_STATUS, 0);
+-
+- arg0 = led_reg & 0xff;
+- arg1 = (led_reg >> 8) & 0xff;
+-
+- rt61pci_mcu_request(rt2x00dev, MCU_LED, 0xff, arg0, arg1);
+-}
+-
+-static void rt61pci_activity_led(struct rt2x00_dev *rt2x00dev, int rssi)
+-{
+- u8 led;
+-
+- if (rt2x00dev->led_mode != LED_MODE_SIGNAL_STRENGTH)
+- return;
+-
+- /*
+- * Led handling requires a positive value for the rssi,
+- * to do that correctly we need to add the correction.
+- */
+- rssi += rt2x00dev->rssi_offset;
+-
+- if (rssi <= 30)
+- led = 0;
+- else if (rssi <= 39)
+- led = 1;
+- else if (rssi <= 49)
+- led = 2;
+- else if (rssi <= 53)
+- led = 3;
+- else if (rssi <= 63)
+- led = 4;
+- else
+- led = 5;
+-
+- rt61pci_mcu_request(rt2x00dev, MCU_LED_STRENGTH, 0xff, led, 0);
+-}
+-
+-/*
+ * Link tuning
+ */
+ static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev,
+@@ -789,17 +794,12 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev)
+ u8 up_bound;
+ u8 low_bound;
+
+- /*
+- * Update Led strength
+- */
+- rt61pci_activity_led(rt2x00dev, rssi);
+-
+ rt61pci_bbp_read(rt2x00dev, 17, &r17);
+
+ /*
+ * Determine r17 bounds.
+ */
+- if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
++ if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
+ low_bound = 0x28;
+ up_bound = 0x48;
+ if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
+@@ -816,6 +816,13 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev)
+ }
+
+ /*
++ * If we are not associated, we should go straight to the
++ * dynamic CCA tuning.
++ */
++ if (!rt2x00dev->intf_associated)
++ goto dynamic_cca_tune;
++
++ /*
+ * Special big-R17 for very short distance
+ */
+ if (rssi >= -35) {
+@@ -866,6 +873,8 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev)
+ return;
+ }
+
++dynamic_cca_tune:
++
+ /*
+ * r17 does not yet exceed upper limit, continue and base
+ * the r17 tuning on the false CCA count.
+@@ -882,7 +891,7 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev)
+ }
+
+ /*
+- * Firmware name function.
++ * Firmware functions
+ */
+ static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
+ {
+@@ -906,9 +915,23 @@ static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
+ return fw_name;
+ }
+
+-/*
+- * Initialization functions.
+- */
++static u16 rt61pci_get_firmware_crc(void *data, const size_t len)
++{
++ u16 crc;
++
++ /*
++ * Use the crc itu-t algorithm.
++ * The last 2 bytes in the firmware array are the crc checksum itself,
++ * this means that we should never pass those 2 bytes to the crc
++ * algorithm.
++ */
++ crc = crc_itu_t(0, data, len - 2);
++ crc = crc_itu_t_byte(crc, 0);
++ crc = crc_itu_t_byte(crc, 0);
++
++ return crc;
++}
++
+ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
+ const size_t len)
+ {
+@@ -989,50 +1012,55 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
+ return 0;
+ }
+
++/*
++ * Initialization functions.
++ */
+ static void rt61pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
+- struct data_entry *entry)
++ struct queue_entry *entry)
+ {
+- __le32 *rxd = entry->priv;
++ struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
+ u32 word;
+
+- rt2x00_desc_read(rxd, 5, &word);
++ rt2x00_desc_read(priv_rx->desc, 5, &word);
+ rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS,
+- entry->data_dma);
+- rt2x00_desc_write(rxd, 5, word);
++ priv_rx->data_dma);
++ rt2x00_desc_write(priv_rx->desc, 5, word);
+
+- rt2x00_desc_read(rxd, 0, &word);
++ rt2x00_desc_read(priv_rx->desc, 0, &word);
+ rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
+- rt2x00_desc_write(rxd, 0, word);
++ rt2x00_desc_write(priv_rx->desc, 0, word);
+ }
+
+ static void rt61pci_init_txentry(struct rt2x00_dev *rt2x00dev,
+- struct data_entry *entry)
++ struct queue_entry *entry)
+ {
+- __le32 *txd = entry->priv;
++ struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
+ u32 word;
+
+- rt2x00_desc_read(txd, 1, &word);
++ rt2x00_desc_read(priv_tx->desc, 1, &word);
+ rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1);
+- rt2x00_desc_write(txd, 1, word);
++ rt2x00_desc_write(priv_tx->desc, 1, word);
+
+- rt2x00_desc_read(txd, 5, &word);
+- rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->ring->queue_idx);
++ rt2x00_desc_read(priv_tx->desc, 5, &word);
++ rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->queue->qid);
+ rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE, entry->entry_idx);
+- rt2x00_desc_write(txd, 5, word);
++ rt2x00_desc_write(priv_tx->desc, 5, word);
+
+- rt2x00_desc_read(txd, 6, &word);
++ rt2x00_desc_read(priv_tx->desc, 6, &word);
+ rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
+- entry->data_dma);
+- rt2x00_desc_write(txd, 6, word);
++ priv_tx->data_dma);
++ rt2x00_desc_write(priv_tx->desc, 6, word);
+
+- rt2x00_desc_read(txd, 0, &word);
++ rt2x00_desc_read(priv_tx->desc, 0, &word);
+ rt2x00_set_field32(&word, TXD_W0_VALID, 0);
+ rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
+- rt2x00_desc_write(txd, 0, word);
++ rt2x00_desc_write(priv_tx->desc, 0, word);
+ }
+
+-static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev)
++static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)
+ {
++ struct queue_entry_priv_pci_rx *priv_rx;
++ struct queue_entry_priv_pci_tx *priv_tx;
+ u32 reg;
+
+ /*
+@@ -1040,59 +1068,55 @@ static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev)
+ */
+ rt2x00pci_register_read(rt2x00dev, TX_RING_CSR0, ®);
+ rt2x00_set_field32(®, TX_RING_CSR0_AC0_RING_SIZE,
+- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit);
++ rt2x00dev->tx[0].limit);
+ rt2x00_set_field32(®, TX_RING_CSR0_AC1_RING_SIZE,
+- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit);
++ rt2x00dev->tx[1].limit);
+ rt2x00_set_field32(®, TX_RING_CSR0_AC2_RING_SIZE,
+- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA2].stats.limit);
++ rt2x00dev->tx[2].limit);
+ rt2x00_set_field32(®, TX_RING_CSR0_AC3_RING_SIZE,
+- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA3].stats.limit);
++ rt2x00dev->tx[3].limit);
+ rt2x00pci_register_write(rt2x00dev, TX_RING_CSR0, reg);
+
+ rt2x00pci_register_read(rt2x00dev, TX_RING_CSR1, ®);
+- rt2x00_set_field32(®, TX_RING_CSR1_MGMT_RING_SIZE,
+- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA4].stats.limit);
+ rt2x00_set_field32(®, TX_RING_CSR1_TXD_SIZE,
+- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size /
+- 4);
++ rt2x00dev->tx[0].desc_size / 4);
+ rt2x00pci_register_write(rt2x00dev, TX_RING_CSR1, reg);
+
++ priv_tx = rt2x00dev->tx[0].entries[0].priv_data;
+ rt2x00pci_register_read(rt2x00dev, AC0_BASE_CSR, ®);
+ rt2x00_set_field32(®, AC0_BASE_CSR_RING_REGISTER,
+- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma);
++ priv_tx->desc_dma);
+ rt2x00pci_register_write(rt2x00dev, AC0_BASE_CSR, reg);
+
++ priv_tx = rt2x00dev->tx[1].entries[0].priv_data;
+ rt2x00pci_register_read(rt2x00dev, AC1_BASE_CSR, ®);
+ rt2x00_set_field32(®, AC1_BASE_CSR_RING_REGISTER,
+- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma);
++ priv_tx->desc_dma);
+ rt2x00pci_register_write(rt2x00dev, AC1_BASE_CSR, reg);
+
++ priv_tx = rt2x00dev->tx[2].entries[0].priv_data;
+ rt2x00pci_register_read(rt2x00dev, AC2_BASE_CSR, ®);
+ rt2x00_set_field32(®, AC2_BASE_CSR_RING_REGISTER,
+- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA2].data_dma);
++ priv_tx->desc_dma);
+ rt2x00pci_register_write(rt2x00dev, AC2_BASE_CSR, reg);
+
++ priv_tx = rt2x00dev->tx[3].entries[0].priv_data;
+ rt2x00pci_register_read(rt2x00dev, AC3_BASE_CSR, ®);
+ rt2x00_set_field32(®, AC3_BASE_CSR_RING_REGISTER,
+- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA3].data_dma);
++ priv_tx->desc_dma);
+ rt2x00pci_register_write(rt2x00dev, AC3_BASE_CSR, reg);
+
+- rt2x00pci_register_read(rt2x00dev, MGMT_BASE_CSR, ®);
+- rt2x00_set_field32(®, MGMT_BASE_CSR_RING_REGISTER,
+- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA4].data_dma);
+- rt2x00pci_register_write(rt2x00dev, MGMT_BASE_CSR, reg);
+-
+ rt2x00pci_register_read(rt2x00dev, RX_RING_CSR, ®);
+- rt2x00_set_field32(®, RX_RING_CSR_RING_SIZE,
+- rt2x00dev->rx->stats.limit);
++ rt2x00_set_field32(®, RX_RING_CSR_RING_SIZE, rt2x00dev->rx->limit);
+ rt2x00_set_field32(®, RX_RING_CSR_RXD_SIZE,
+ rt2x00dev->rx->desc_size / 4);
+ rt2x00_set_field32(®, RX_RING_CSR_RXD_WRITEBACK_SIZE, 4);
+ rt2x00pci_register_write(rt2x00dev, RX_RING_CSR, reg);
+
++ priv_rx = rt2x00dev->rx->entries[0].priv_data;
+ rt2x00pci_register_read(rt2x00dev, RX_BASE_CSR, ®);
+ rt2x00_set_field32(®, RX_BASE_CSR_RING_REGISTER,
+- rt2x00dev->rx->data_dma);
++ priv_rx->desc_dma);
+ rt2x00pci_register_write(rt2x00dev, RX_BASE_CSR, reg);
+
+ rt2x00pci_register_read(rt2x00dev, TX_DMA_DST_CSR, ®);
+@@ -1100,7 +1124,6 @@ static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev)
+ rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC1, 2);
+ rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC2, 2);
+ rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC3, 2);
+- rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_MGMT, 0);
+ rt2x00pci_register_write(rt2x00dev, TX_DMA_DST_CSR, reg);
+
+ rt2x00pci_register_read(rt2x00dev, LOAD_TX_RING_CSR, ®);
+@@ -1108,7 +1131,6 @@ static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev)
+ rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC1, 1);
+ rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC2, 1);
+ rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC3, 1);
+- rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_MGMT, 1);
+ rt2x00pci_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg);
+
+ rt2x00pci_register_read(rt2x00dev, RX_CNTL_CSR, ®);
+@@ -1224,6 +1246,17 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
+ rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR1, reg);
+
+ /*
++ * Clear all beacons
++ * For the Beacon base registers we only need to clear
++ * the first byte since that byte contains the VALID and OWNER
++ * bits which (when set to 0) will invalidate the entire beacon.
++ */
++ rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
++ rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
++ rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
++ rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
++
++ /*
+ * We must clear the error counters.
+ * These registers are cleared on read,
+ * so we may pass a useless variable to store the value.
+@@ -1296,19 +1329,15 @@ continue_csr_init:
+ rt61pci_bbp_write(rt2x00dev, 102, 0x16);
+ rt61pci_bbp_write(rt2x00dev, 107, 0x04);
+
+- DEBUG(rt2x00dev, "Start initialization from EEPROM...\n");
+ for (i = 0; i < EEPROM_BBP_SIZE; i++) {
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+
+ if (eeprom != 0xffff && eeprom != 0x0000) {
+ reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
+ value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
+- DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n",
+- reg_id, value);
+ rt61pci_bbp_write(rt2x00dev, reg_id, value);
+ }
+ }
+- DEBUG(rt2x00dev, "...End initialization from EEPROM.\n");
+
+ return 0;
+ }
+@@ -1375,7 +1404,7 @@ static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev)
+ /*
+ * Initialize all registers.
+ */
+- if (rt61pci_init_rings(rt2x00dev) ||
++ if (rt61pci_init_queues(rt2x00dev) ||
+ rt61pci_init_registers(rt2x00dev) ||
+ rt61pci_init_bbp(rt2x00dev)) {
+ ERROR(rt2x00dev, "Register initialization failed.\n");
+@@ -1394,11 +1423,6 @@ static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev)
+ rt2x00_set_field32(®, RX_CNTL_CSR_ENABLE_RX_DMA, 1);
+ rt2x00pci_register_write(rt2x00dev, RX_CNTL_CSR, reg);
+
+- /*
+- * Enable LED
+- */
+- rt61pci_enable_led(rt2x00dev);
+-
+ return 0;
+ }
+
+@@ -1406,11 +1430,6 @@ static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev)
+ {
+ u32 reg;
+
+- /*
+- * Disable LED
+- */
+- rt61pci_disable_led(rt2x00dev);
+-
+ rt2x00pci_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
+
+ /*
+@@ -1426,7 +1445,6 @@ static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev)
+ rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC1, 1);
+ rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC2, 1);
+ rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC3, 1);
+- rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_MGMT, 1);
+ rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+
+ /*
+@@ -1508,10 +1526,10 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev,
+ */
+ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ struct sk_buff *skb,
+- struct txdata_entry_desc *desc,
++ struct txentry_desc *txdesc,
+ struct ieee80211_tx_control *control)
+ {
+- struct skb_desc *skbdesc = get_skb_desc(skb);
++ struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+ __le32 *txd = skbdesc->desc;
+ u32 word;
+
+@@ -1519,50 +1537,52 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ * Start writing the descriptor words.
+ */
+ rt2x00_desc_read(txd, 1, &word);
+- rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, desc->queue);
+- rt2x00_set_field32(&word, TXD_W1_AIFSN, desc->aifs);
+- rt2x00_set_field32(&word, TXD_W1_CWMIN, desc->cw_min);
+- rt2x00_set_field32(&word, TXD_W1_CWMAX, desc->cw_max);
++ rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue);
++ rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs);
++ rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
++ rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
+ rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER);
+ rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, 1);
+ rt2x00_desc_write(txd, 1, word);
+
+ rt2x00_desc_read(txd, 2, &word);
+- rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, desc->signal);
+- rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, desc->service);
+- rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, desc->length_low);
+- rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, desc->length_high);
++ rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal);
++ rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service);
++ rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low);
++ rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
+ rt2x00_desc_write(txd, 2, word);
+
+ rt2x00_desc_read(txd, 5, &word);
+ rt2x00_set_field32(&word, TXD_W5_TX_POWER,
+- TXPOWER_TO_DEV(control->power_level));
++ TXPOWER_TO_DEV(rt2x00dev->tx_power));
+ rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
+ rt2x00_desc_write(txd, 5, word);
+
+- rt2x00_desc_read(txd, 11, &word);
+- rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skbdesc->data_len);
+- rt2x00_desc_write(txd, 11, word);
++ if (skbdesc->desc_len > TXINFO_SIZE) {
++ rt2x00_desc_read(txd, 11, &word);
++ rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skbdesc->data_len);
++ rt2x00_desc_write(txd, 11, word);
++ }
+
+ rt2x00_desc_read(txd, 0, &word);
+ rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
+ rt2x00_set_field32(&word, TXD_W0_VALID, 1);
+ rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
+- test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
++ test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_ACK,
+- test_bit(ENTRY_TXD_ACK, &desc->flags));
++ test_bit(ENTRY_TXD_ACK, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
+- test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
++ test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_OFDM,
+- test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags));
+- rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
++ test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
++ rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
+ rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
+ !!(control->flags &
+ IEEE80211_TXCTL_LONG_RETRY_LIMIT));
+ rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0);
+ rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
+ rt2x00_set_field32(&word, TXD_W0_BURST,
+- test_bit(ENTRY_TXD_BURST, &desc->flags));
++ test_bit(ENTRY_TXD_BURST, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
+ rt2x00_desc_write(txd, 0, word);
+ }
+@@ -1571,11 +1591,11 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ * TX data initialization
+ */
+ static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
+- unsigned int queue)
++ const unsigned int queue)
+ {
+ u32 reg;
+
+- if (queue == IEEE80211_TX_QUEUE_BEACON) {
++ if (queue == RT2X00_BCN_QUEUE_BEACON) {
+ /*
+ * For Wi-Fi faily generated beacons between participating
+ * stations. Set TBTT phase adaptive adjustment step to 8us.
+@@ -1584,6 +1604,8 @@ static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
+
+ rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®);
+ if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) {
++ rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1);
++ rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1);
+ rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1);
+ rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ }
+@@ -1599,8 +1621,6 @@ static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
+ (queue == IEEE80211_TX_QUEUE_DATA2));
+ rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC3,
+ (queue == IEEE80211_TX_QUEUE_DATA3));
+- rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_MGMT,
+- (queue == IEEE80211_TX_QUEUE_DATA4));
+ rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+ }
+
+@@ -1628,7 +1648,7 @@ static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
+ return 0;
+ }
+
+- if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
++ if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
+ if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
+ offset += 14;
+
+@@ -1648,28 +1668,35 @@ static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
+ return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
+ }
+
+-static void rt61pci_fill_rxdone(struct data_entry *entry,
+- struct rxdata_entry_desc *desc)
++static void rt61pci_fill_rxdone(struct queue_entry *entry,
++ struct rxdone_entry_desc *rxdesc)
+ {
+- __le32 *rxd = entry->priv;
++ struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
+ u32 word0;
+ u32 word1;
+
+- rt2x00_desc_read(rxd, 0, &word0);
+- rt2x00_desc_read(rxd, 1, &word1);
++ rt2x00_desc_read(priv_rx->desc, 0, &word0);
++ rt2x00_desc_read(priv_rx->desc, 1, &word1);
+
+- desc->flags = 0;
++ rxdesc->flags = 0;
+ if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
+- desc->flags |= RX_FLAG_FAILED_FCS_CRC;
++ rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
+
+ /*
+ * Obtain the status about this packet.
+- */
+- desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
+- desc->rssi = rt61pci_agc_to_rssi(entry->ring->rt2x00dev, word1);
+- desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
+- desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+- desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
++ * When frame was received with an OFDM bitrate,
++ * the signal is the PLCP value. If it was received with
++ * a CCK bitrate the signal is the rate in 100kbit/s.
++ */
++ rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
++ rxdesc->rssi = rt61pci_agc_to_rssi(entry->queue->rt2x00dev, word1);
++ rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
++
++ rxdesc->dev_flags = 0;
++ if (rt2x00_get_field32(word0, RXD_W0_OFDM))
++ rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
++ if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
++ rxdesc->dev_flags |= RXDONE_MY_BSS;
+ }
+
+ /*
+@@ -1677,17 +1704,16 @@ static void rt61pci_fill_rxdone(struct data_entry *entry,
+ */
+ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
+ {
+- struct data_ring *ring;
+- struct data_entry *entry;
+- struct data_entry *entry_done;
+- __le32 *txd;
++ struct data_queue *queue;
++ struct queue_entry *entry;
++ struct queue_entry *entry_done;
++ struct queue_entry_priv_pci_tx *priv_tx;
++ struct txdone_entry_desc txdesc;
+ u32 word;
+ u32 reg;
+ u32 old_reg;
+ int type;
+ int index;
+- int tx_status;
+- int retry;
+
+ /*
+ * During each loop we will compare the freshly read
+@@ -1710,11 +1736,11 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
+
+ /*
+ * Skip this entry when it contains an invalid
+- * ring identication number.
++ * queue identication number.
+ */
+ type = rt2x00_get_field32(reg, STA_CSR4_PID_TYPE);
+- ring = rt2x00lib_get_ring(rt2x00dev, type);
+- if (unlikely(!ring))
++ queue = rt2x00queue_get_queue(rt2x00dev, type);
++ if (unlikely(!queue))
+ continue;
+
+ /*
+@@ -1722,36 +1748,40 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
+ * index number.
+ */
+ index = rt2x00_get_field32(reg, STA_CSR4_PID_SUBTYPE);
+- if (unlikely(index >= ring->stats.limit))
++ if (unlikely(index >= queue->limit))
+ continue;
+
+- entry = &ring->entry[index];
+- txd = entry->priv;
+- rt2x00_desc_read(txd, 0, &word);
++ entry = &queue->entries[index];
++ priv_tx = entry->priv_data;
++ rt2x00_desc_read(priv_tx->desc, 0, &word);
+
+ if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
+ !rt2x00_get_field32(word, TXD_W0_VALID))
+ return;
+
+- entry_done = rt2x00_get_data_entry_done(ring);
++ entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+ while (entry != entry_done) {
+- /* Catch up. Just report any entries we missed as
+- * failed. */
++ /* Catch up.
++ * Just report any entries we missed as failed.
++ */
+ WARNING(rt2x00dev,
+- "TX status report missed for entry %p\n",
+- entry_done);
+- rt2x00pci_txdone(rt2x00dev, entry_done, TX_FAIL_OTHER,
+- 0);
+- entry_done = rt2x00_get_data_entry_done(ring);
++ "TX status report missed for entry %d\n",
++ entry_done->entry_idx);
++
++ txdesc.status = TX_FAIL_OTHER;
++ txdesc.retry = 0;
++
++ rt2x00pci_txdone(rt2x00dev, entry_done, &txdesc);
++ entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+ }
+
+ /*
+ * Obtain the status about this packet.
+ */
+- tx_status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT);
+- retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT);
++ txdesc.status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT);
++ txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT);
+
+- rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry);
++ rt2x00pci_txdone(rt2x00dev, entry, &txdesc);
+ }
+ }
+
+@@ -1906,7 +1936,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
+ rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
+ rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
+ rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
+- EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
++ EEPROM(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);
+ } else {
+ value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);
+ if (value < -10 || value > 10)
+@@ -2035,35 +2065,61 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
+ * If the eeprom value is invalid,
+ * switch to default led mode.
+ */
++#ifdef CONFIG_RT61PCI_LEDS
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
++ value = rt2x00_get_field16(eeprom, EEPROM_LED_LED_MODE);
++
++ rt2x00dev->led_radio.rt2x00dev = rt2x00dev;
++ rt2x00dev->led_radio.type = LED_TYPE_RADIO;
++ rt2x00dev->led_radio.led_dev.brightness_set =
++ rt61pci_brightness_set;
++ rt2x00dev->led_radio.led_dev.blink_set =
++ rt61pci_blink_set;
++ rt2x00dev->led_radio.flags = LED_INITIALIZED;
++
++ rt2x00dev->led_assoc.rt2x00dev = rt2x00dev;
++ rt2x00dev->led_assoc.type = LED_TYPE_ASSOC;
++ rt2x00dev->led_assoc.led_dev.brightness_set =
++ rt61pci_brightness_set;
++ rt2x00dev->led_assoc.led_dev.blink_set =
++ rt61pci_blink_set;
++ rt2x00dev->led_assoc.flags = LED_INITIALIZED;
++
++ if (value == LED_MODE_SIGNAL_STRENGTH) {
++ rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
++ rt2x00dev->led_radio.type = LED_TYPE_QUALITY;
++ rt2x00dev->led_qual.led_dev.brightness_set =
++ rt61pci_brightness_set;
++ rt2x00dev->led_qual.led_dev.blink_set =
++ rt61pci_blink_set;
++ rt2x00dev->led_qual.flags = LED_INITIALIZED;
++ }
+
+- rt2x00dev->led_mode = rt2x00_get_field16(eeprom, EEPROM_LED_LED_MODE);
+-
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LED_MODE,
+- rt2x00dev->led_mode);
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_0,
++ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value);
++ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0,
+ rt2x00_get_field16(eeprom,
+ EEPROM_LED_POLARITY_GPIO_0));
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_1,
++ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_1,
+ rt2x00_get_field16(eeprom,
+ EEPROM_LED_POLARITY_GPIO_1));
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_2,
++ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_2,
+ rt2x00_get_field16(eeprom,
+ EEPROM_LED_POLARITY_GPIO_2));
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_3,
++ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_3,
+ rt2x00_get_field16(eeprom,
+ EEPROM_LED_POLARITY_GPIO_3));
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_4,
++ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_4,
+ rt2x00_get_field16(eeprom,
+ EEPROM_LED_POLARITY_GPIO_4));
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_ACT,
++ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_ACT,
+ rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_ACT));
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_BG,
++ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_BG,
+ rt2x00_get_field16(eeprom,
+ EEPROM_LED_POLARITY_RDY_G));
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_A,
++ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_A,
+ rt2x00_get_field16(eeprom,
+ EEPROM_LED_POLARITY_RDY_A));
++#endif /* CONFIG_RT61PCI_LEDS */
+
+ return 0;
+ }
+@@ -2197,7 +2253,7 @@ static void rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+ rt2x00dev->hw->extra_tx_headroom = 0;
+ rt2x00dev->hw->max_signal = MAX_SIGNAL;
+ rt2x00dev->hw->max_rssi = MAX_RX_SSI;
+- rt2x00dev->hw->queues = 5;
++ rt2x00dev->hw->queues = 4;
+
+ SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
+ SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
+@@ -2214,8 +2270,8 @@ static void rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+ /*
+ * Initialize hw_mode information.
+ */
+- spec->num_modes = 2;
+- spec->num_rates = 12;
++ spec->supported_bands = SUPPORT_BAND_2GHZ;
++ spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
+ spec->tx_power_a = NULL;
+ spec->tx_power_bg = txpower;
+ spec->tx_power_default = DEFAULT_TXPOWER;
+@@ -2230,7 +2286,7 @@ static void rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+
+ if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
+ rt2x00_rf(&rt2x00dev->chip, RF5325)) {
+- spec->num_modes = 3;
++ spec->supported_bands |= SUPPORT_BAND_5GHZ;
+ spec->num_channels = ARRAY_SIZE(rf_vals_seq);
+
+ txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
+@@ -2262,7 +2318,7 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
+ rt61pci_probe_hw_mode(rt2x00dev);
+
+ /*
+- * This device requires firmware
++ * This device requires firmware.
+ */
+ __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
+
+@@ -2277,70 +2333,6 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
+ /*
+ * IEEE80211 stack callback functions.
+ */
+-static void rt61pci_configure_filter(struct ieee80211_hw *hw,
+- unsigned int changed_flags,
+- unsigned int *total_flags,
+- int mc_count,
+- struct dev_addr_list *mc_list)
+-{
+- struct rt2x00_dev *rt2x00dev = hw->priv;
+- u32 reg;
+-
+- /*
+- * Mask off any flags we are going to ignore from
+- * the total_flags field.
+- */
+- *total_flags &=
+- FIF_ALLMULTI |
+- FIF_FCSFAIL |
+- FIF_PLCPFAIL |
+- FIF_CONTROL |
+- FIF_OTHER_BSS |
+- FIF_PROMISC_IN_BSS;
+-
+- /*
+- * Apply some rules to the filters:
+- * - Some filters imply different filters to be set.
+- * - Some things we can't filter out at all.
+- * - Multicast filter seems to kill broadcast traffic so never use it.
+- */
+- *total_flags |= FIF_ALLMULTI;
+- if (*total_flags & FIF_OTHER_BSS ||
+- *total_flags & FIF_PROMISC_IN_BSS)
+- *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
+-
+- /*
+- * Check if there is any work left for us.
+- */
+- if (rt2x00dev->packet_filter == *total_flags)
+- return;
+- rt2x00dev->packet_filter = *total_flags;
+-
+- /*
+- * Start configuration steps.
+- * Note that the version error will always be dropped
+- * and broadcast frames will always be accepted since
+- * there is no filter for it at this time.
+- */
+- rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®);
+- rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC,
+- !(*total_flags & FIF_FCSFAIL));
+- rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL,
+- !(*total_flags & FIF_PLCPFAIL));
+- rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL,
+- !(*total_flags & FIF_CONTROL));
+- rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME,
+- !(*total_flags & FIF_PROMISC_IN_BSS));
+- rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS,
+- !(*total_flags & FIF_PROMISC_IN_BSS));
+- rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1);
+- rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST,
+- !(*total_flags & FIF_ALLMULTI));
+- rt2x00_set_field32(®, TXRX_CSR0_DROP_BORADCAST, 0);
+- rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, 1);
+- rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
+-}
+-
+ static int rt61pci_set_retry_limit(struct ieee80211_hw *hw,
+ u32 short_retry, u32 long_retry)
+ {
+@@ -2369,66 +2361,72 @@ static u64 rt61pci_get_tsf(struct ieee80211_hw *hw)
+ return tsf;
+ }
+
+-static void rt61pci_reset_tsf(struct ieee80211_hw *hw)
+-{
+- struct rt2x00_dev *rt2x00dev = hw->priv;
+-
+- rt2x00pci_register_write(rt2x00dev, TXRX_CSR12, 0);
+- rt2x00pci_register_write(rt2x00dev, TXRX_CSR13, 0);
+-}
+-
+ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct ieee80211_tx_control *control)
+ {
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+- struct skb_desc *desc;
+- struct data_ring *ring;
+- struct data_entry *entry;
++ struct rt2x00_intf *intf = vif_to_intf(control->vif);
++ struct skb_frame_desc *skbdesc;
++ unsigned int beacon_base;
++ u32 reg;
+
+- /*
+- * Just in case the ieee80211 doesn't set this,
+- * but we need this queue set for the descriptor
+- * initialization.
+- */
+- control->queue = IEEE80211_TX_QUEUE_BEACON;
+- ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
+- entry = rt2x00_get_data_entry(ring);
++ if (unlikely(!intf->beacon))
++ return -ENOBUFS;
+
+ /*
+ * We need to append the descriptor in front of the
+ * beacon frame.
+ */
+- if (skb_headroom(skb) < TXD_DESC_SIZE) {
+- if (pskb_expand_head(skb, TXD_DESC_SIZE, 0, GFP_ATOMIC))
++ if (skb_headroom(skb) < intf->beacon->queue->desc_size) {
++ if (pskb_expand_head(skb, intf->beacon->queue->desc_size,
++ 0, GFP_ATOMIC))
+ return -ENOMEM;
+ }
+
+ /*
+ * Add the descriptor in front of the skb.
+ */
+- skb_push(skb, ring->desc_size);
+- memset(skb->data, 0, ring->desc_size);
++ skb_push(skb, intf->beacon->queue->desc_size);
++ memset(skb->data, 0, intf->beacon->queue->desc_size);
+
+ /*
+ * Fill in skb descriptor
+ */
+- desc = get_skb_desc(skb);
+- desc->desc_len = ring->desc_size;
+- desc->data_len = skb->len - ring->desc_size;
+- desc->desc = skb->data;
+- desc->data = skb->data + ring->desc_size;
+- desc->ring = ring;
+- desc->entry = entry;
++ skbdesc = get_skb_frame_desc(skb);
++ memset(skbdesc, 0, sizeof(*skbdesc));
++ skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
++ skbdesc->data = skb->data + intf->beacon->queue->desc_size;
++ skbdesc->data_len = skb->len - intf->beacon->queue->desc_size;
++ skbdesc->desc = skb->data;
++ skbdesc->desc_len = intf->beacon->queue->desc_size;
++ skbdesc->entry = intf->beacon;
++
++ /*
++ * Disable beaconing while we are reloading the beacon data,
++ * otherwise we might be sending out invalid data.
++ */
++ rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®);
++ rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0);
++ rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0);
++ rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0);
++ rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+
++ /*
++ * mac80211 doesn't provide the control->queue variable
++ * for beacons. Set our own queue identification so
++ * it can be used during descriptor initialization.
++ */
++ control->queue = RT2X00_BCN_QUEUE_BEACON;
+ rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
+
+ /*
+ * Write entire beacon with descriptor to register,
+ * and kick the beacon generator.
+ */
+- rt2x00pci_register_multiwrite(rt2x00dev, HW_BEACON_BASE0,
++ beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
++ rt2x00pci_register_multiwrite(rt2x00dev, beacon_base,
+ skb->data, skb->len);
+- rt61pci_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
++ rt61pci_kick_tx_queue(rt2x00dev, control->queue);
+
+ return 0;
+ }
+@@ -2441,14 +2439,13 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
+ .remove_interface = rt2x00mac_remove_interface,
+ .config = rt2x00mac_config,
+ .config_interface = rt2x00mac_config_interface,
+- .configure_filter = rt61pci_configure_filter,
++ .configure_filter = rt2x00mac_configure_filter,
+ .get_stats = rt2x00mac_get_stats,
+ .set_retry_limit = rt61pci_set_retry_limit,
+ .bss_info_changed = rt2x00mac_bss_info_changed,
+ .conf_tx = rt2x00mac_conf_tx,
+ .get_tx_stats = rt2x00mac_get_tx_stats,
+ .get_tsf = rt61pci_get_tsf,
+- .reset_tsf = rt61pci_reset_tsf,
+ .beacon_update = rt61pci_beacon_update,
+ };
+
+@@ -2456,6 +2453,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
+ .irq_handler = rt61pci_interrupt,
+ .probe_hw = rt61pci_probe_hw,
+ .get_firmware_name = rt61pci_get_firmware_name,
++ .get_firmware_crc = rt61pci_get_firmware_crc,
+ .load_firmware = rt61pci_load_firmware,
+ .initialize = rt2x00pci_initialize,
+ .uninitialize = rt2x00pci_uninitialize,
+@@ -2470,19 +2468,42 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
+ .write_tx_data = rt2x00pci_write_tx_data,
+ .kick_tx_queue = rt61pci_kick_tx_queue,
+ .fill_rxdone = rt61pci_fill_rxdone,
+- .config_mac_addr = rt61pci_config_mac_addr,
+- .config_bssid = rt61pci_config_bssid,
+- .config_type = rt61pci_config_type,
+- .config_preamble = rt61pci_config_preamble,
++ .config_filter = rt61pci_config_filter,
++ .config_intf = rt61pci_config_intf,
++ .config_erp = rt61pci_config_erp,
+ .config = rt61pci_config,
+ };
+
++static const struct data_queue_desc rt61pci_queue_rx = {
++ .entry_num = RX_ENTRIES,
++ .data_size = DATA_FRAME_SIZE,
++ .desc_size = RXD_DESC_SIZE,
++ .priv_size = sizeof(struct queue_entry_priv_pci_rx),
++};
++
++static const struct data_queue_desc rt61pci_queue_tx = {
++ .entry_num = TX_ENTRIES,
++ .data_size = DATA_FRAME_SIZE,
++ .desc_size = TXD_DESC_SIZE,
++ .priv_size = sizeof(struct queue_entry_priv_pci_tx),
++};
++
++static const struct data_queue_desc rt61pci_queue_bcn = {
++ .entry_num = 4 * BEACON_ENTRIES,
++ .data_size = MGMT_FRAME_SIZE,
++ .desc_size = TXINFO_SIZE,
++ .priv_size = sizeof(struct queue_entry_priv_pci_tx),
++};
++
+ static const struct rt2x00_ops rt61pci_ops = {
+ .name = KBUILD_MODNAME,
+- .rxd_size = RXD_DESC_SIZE,
+- .txd_size = TXD_DESC_SIZE,
++ .max_sta_intf = 1,
++ .max_ap_intf = 4,
+ .eeprom_size = EEPROM_SIZE,
+ .rf_size = RF_SIZE,
++ .rx = &rt61pci_queue_rx,
++ .tx = &rt61pci_queue_tx,
++ .bcn = &rt61pci_queue_bcn,
+ .lib = &rt61pci_rt2x00_ops,
+ .hw = &rt61pci_mac80211_ops,
+ #ifdef CONFIG_RT2X00_LIB_DEBUGFS
+diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h
+index 4c6524e..3511bba 100644
+--- a/drivers/net/wireless/rt2x00/rt61pci.h
++++ b/drivers/net/wireless/rt2x00/rt61pci.h
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+@@ -161,7 +161,9 @@ struct hw_pairwise_ta_entry {
+ #define HW_BEACON_BASE1 0x2d00
+ #define HW_BEACON_BASE2 0x2e00
+ #define HW_BEACON_BASE3 0x2f00
+-#define HW_BEACON_OFFSET 0x0100
++
++#define HW_BEACON_OFFSET(__index) \
++ ( HW_BEACON_BASE0 + (__index * 0x0100) )
+
+ /*
+ * HOST-MCU shared memory.
+@@ -234,6 +236,11 @@ struct hw_pairwise_ta_entry {
+
+ /*
+ * MAC_CSR3: STA MAC register 1.
++ * UNICAST_TO_ME_MASK:
++ * Used to mask off bits from byte 5 of the MAC address
++ * to determine the UNICAST_TO_ME bit for RX frames.
++ * The full mask is complemented by BSS_ID_MASK:
++ * MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK
+ */
+ #define MAC_CSR3 0x300c
+ #define MAC_CSR3_BYTE4 FIELD32(0x000000ff)
+@@ -251,7 +258,14 @@ struct hw_pairwise_ta_entry {
+
+ /*
+ * MAC_CSR5: BSSID register 1.
+- * BSS_ID_MASK: 3: one BSSID, 0: 4 BSSID, 2 or 1: 2 BSSID.
++ * BSS_ID_MASK:
++ * This mask is used to mask off bits 0 and 1 of byte 5 of the
++ * BSSID. This will make sure that those bits will be ignored
++ * when determining the MY_BSS of RX frames.
++ * 0: 1-BSSID mode (BSS index = 0)
++ * 1: 2-BSSID mode (BSS index: Byte5, bit 0)
++ * 2: 2-BSSID mode (BSS index: byte5, bit 1)
++ * 3: 4-BSSID mode (BSS index: byte5, bit 0 - 1)
+ */
+ #define MAC_CSR5 0x3014
+ #define MAC_CSR5_BYTE4 FIELD32(0x000000ff)
+@@ -391,7 +405,7 @@ struct hw_pairwise_ta_entry {
+ #define TXRX_CSR0_DROP_TO_DS FIELD32(0x00200000)
+ #define TXRX_CSR0_DROP_VERSION_ERROR FIELD32(0x00400000)
+ #define TXRX_CSR0_DROP_MULTICAST FIELD32(0x00800000)
+-#define TXRX_CSR0_DROP_BORADCAST FIELD32(0x01000000)
++#define TXRX_CSR0_DROP_BROADCAST FIELD32(0x01000000)
+ #define TXRX_CSR0_DROP_ACK_CTS FIELD32(0x02000000)
+ #define TXRX_CSR0_TX_WITHOUT_WAITING FIELD32(0x04000000)
+
+@@ -866,7 +880,7 @@ struct hw_pairwise_ta_entry {
+ #define TX_CNTL_CSR_ABORT_TX_MGMT FIELD32(0x00100000)
+
+ /*
+- * LOAD_TX_RING_CSR: Load RX de
++ * LOAD_TX_RING_CSR: Load RX desriptor
+ */
+ #define LOAD_TX_RING_CSR 0x3434
+ #define LOAD_TX_RING_CSR_LOAD_TXD_AC0 FIELD32(0x00000001)
+@@ -1116,10 +1130,10 @@ struct hw_pairwise_ta_entry {
+ #define EEPROM_MAC_ADDR_0 0x0002
+ #define EEPROM_MAC_ADDR_BYTE0 FIELD16(0x00ff)
+ #define EEPROM_MAC_ADDR_BYTE1 FIELD16(0xff00)
+-#define EEPROM_MAC_ADDR1 0x0004
++#define EEPROM_MAC_ADDR1 0x0003
+ #define EEPROM_MAC_ADDR_BYTE2 FIELD16(0x00ff)
+ #define EEPROM_MAC_ADDR_BYTE3 FIELD16(0xff00)
+-#define EEPROM_MAC_ADDR_2 0x0006
++#define EEPROM_MAC_ADDR_2 0x0004
+ #define EEPROM_MAC_ADDR_BYTE4 FIELD16(0x00ff)
+ #define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00)
+
+@@ -1247,6 +1261,7 @@ struct hw_pairwise_ta_entry {
+ * DMA descriptor defines.
+ */
+ #define TXD_DESC_SIZE ( 16 * sizeof(__le32) )
++#define TXINFO_SIZE ( 6 * sizeof(__le32) )
+ #define RXD_DESC_SIZE ( 16 * sizeof(__le32) )
+
+ /*
+@@ -1440,8 +1455,8 @@ struct hw_pairwise_ta_entry {
+ #define RXD_W15_RESERVED FIELD32(0xffffffff)
+
+ /*
+- * Macro's for converting txpower from EEPROM to dscape value
+- * and from dscape value to register value.
++ * Macro's for converting txpower from EEPROM to mac80211 value
++ * and from mac80211 value to register value.
+ */
+ #define MIN_TXPOWER 0
+ #define MAX_TXPOWER 31
+diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
+index 3909cf4..a9efe25 100644
+--- a/drivers/net/wireless/rt2x00/rt73usb.c
++++ b/drivers/net/wireless/rt2x00/rt73usb.c
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+@@ -24,6 +24,7 @@
+ Supported chipsets: rt2571W & rt2671.
+ */
+
++#include <linux/crc-itu-t.h>
+ #include <linux/delay.h>
+ #include <linux/etherdevice.h>
+ #include <linux/init.h>
+@@ -278,85 +279,158 @@ static const struct rt2x00debug rt73usb_rt2x00debug = {
+ };
+ #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+
+-/*
+- * Configuration handlers.
+- */
+-static void rt73usb_config_mac_addr(struct rt2x00_dev *rt2x00dev, __le32 *mac)
++#ifdef CONFIG_RT73USB_LEDS
++static void rt73usb_brightness_set(struct led_classdev *led_cdev,
++ enum led_brightness brightness)
+ {
+- u32 tmp;
+-
+- tmp = le32_to_cpu(mac[1]);
+- rt2x00_set_field32(&tmp, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
+- mac[1] = cpu_to_le32(tmp);
+-
+- rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2, mac,
+- (2 * sizeof(__le32)));
++ struct rt2x00_led *led =
++ container_of(led_cdev, struct rt2x00_led, led_dev);
++ unsigned int enabled = brightness != LED_OFF;
++ unsigned int a_mode =
++ (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
++ unsigned int bg_mode =
++ (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
++
++ if (led->type == LED_TYPE_RADIO) {
++ rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
++ MCU_LEDCS_RADIO_STATUS, enabled);
++
++ rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
++ 0, led->rt2x00dev->led_mcu_reg,
++ REGISTER_TIMEOUT);
++ } else if (led->type == LED_TYPE_ASSOC) {
++ rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
++ MCU_LEDCS_LINK_BG_STATUS, bg_mode);
++ rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
++ MCU_LEDCS_LINK_A_STATUS, a_mode);
++
++ rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
++ 0, led->rt2x00dev->led_mcu_reg,
++ REGISTER_TIMEOUT);
++ } else if (led->type == LED_TYPE_QUALITY) {
++ /*
++ * The brightness is divided into 6 levels (0 - 5),
++ * this means we need to convert the brightness
++ * argument into the matching level within that range.
++ */
++ rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
++ brightness / (LED_FULL / 6),
++ led->rt2x00dev->led_mcu_reg,
++ REGISTER_TIMEOUT);
++ }
+ }
+
+-static void rt73usb_config_bssid(struct rt2x00_dev *rt2x00dev, __le32 *bssid)
++static int rt73usb_blink_set(struct led_classdev *led_cdev,
++ unsigned long *delay_on,
++ unsigned long *delay_off)
+ {
+- u32 tmp;
++ struct rt2x00_led *led =
++ container_of(led_cdev, struct rt2x00_led, led_dev);
++ u32 reg;
+
+- tmp = le32_to_cpu(bssid[1]);
+- rt2x00_set_field32(&tmp, MAC_CSR5_BSS_ID_MASK, 3);
+- bssid[1] = cpu_to_le32(tmp);
++ rt73usb_register_read(led->rt2x00dev, MAC_CSR14, ®);
++ rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, *delay_on);
++ rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, *delay_off);
++ rt73usb_register_write(led->rt2x00dev, MAC_CSR14, reg);
+
+- rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4, bssid,
+- (2 * sizeof(__le32)));
++ return 0;
+ }
++#endif /* CONFIG_RT73USB_LEDS */
+
+-static void rt73usb_config_type(struct rt2x00_dev *rt2x00dev, const int type,
+- const int tsf_sync)
++/*
++ * Configuration handlers.
++ */
++static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev,
++ const unsigned int filter_flags)
+ {
+ u32 reg;
+
+ /*
+- * Clear current synchronisation setup.
+- * For the Beacon base registers we only need to clear
+- * the first byte since that byte contains the VALID and OWNER
+- * bits which (when set to 0) will invalidate the entire beacon.
+- */
+- rt73usb_register_write(rt2x00dev, TXRX_CSR9, 0);
+- rt73usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
+- rt73usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
+- rt73usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
+- rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
+-
+- /*
+- * Enable synchronisation.
++ * Start configuration steps.
++ * Note that the version error will always be dropped
++ * and broadcast frames will always be accepted since
++ * there is no filter for it at this time.
+ */
+- rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®);
+- rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1);
+- rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE,
+- (tsf_sync == TSF_SYNC_BEACON));
+- rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0);
+- rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, tsf_sync);
+- rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
++ rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®);
++ rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC,
++ !(filter_flags & FIF_FCSFAIL));
++ rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL,
++ !(filter_flags & FIF_PLCPFAIL));
++ rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL,
++ !(filter_flags & FIF_CONTROL));
++ rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME,
++ !(filter_flags & FIF_PROMISC_IN_BSS));
++ rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS,
++ !(filter_flags & FIF_PROMISC_IN_BSS) &&
++ !rt2x00dev->intf_ap_count);
++ rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1);
++ rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST,
++ !(filter_flags & FIF_ALLMULTI));
++ rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0);
++ rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS,
++ !(filter_flags & FIF_CONTROL));
++ rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
+ }
+
+-static void rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev,
+- const int short_preamble,
+- const int ack_timeout,
+- const int ack_consume_time)
++static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
++ struct rt2x00_intf *intf,
++ struct rt2x00intf_conf *conf,
++ const unsigned int flags)
+ {
++ unsigned int beacon_base;
+ u32 reg;
+
+- /*
+- * When in atomic context, reschedule and let rt2x00lib
+- * call this function again.
+- */
+- if (in_atomic()) {
+- queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->config_work);
+- return;
++ if (flags & CONFIG_UPDATE_TYPE) {
++ /*
++ * Clear current synchronisation setup.
++ * For the Beacon base registers we only need to clear
++ * the first byte since that byte contains the VALID and OWNER
++ * bits which (when set to 0) will invalidate the entire beacon.
++ */
++ beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
++ rt73usb_register_write(rt2x00dev, beacon_base, 0);
++
++ /*
++ * Enable synchronisation.
++ */
++ rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®);
++ rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1);
++ rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync);
++ rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1);
++ rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+ }
+
++ if (flags & CONFIG_UPDATE_MAC) {
++ reg = le32_to_cpu(conf->mac[1]);
++ rt2x00_set_field32(®, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
++ conf->mac[1] = cpu_to_le32(reg);
++
++ rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2,
++ conf->mac, sizeof(conf->mac));
++ }
++
++ if (flags & CONFIG_UPDATE_BSSID) {
++ reg = le32_to_cpu(conf->bssid[1]);
++ rt2x00_set_field32(®, MAC_CSR5_BSS_ID_MASK, 3);
++ conf->bssid[1] = cpu_to_le32(reg);
++
++ rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4,
++ conf->bssid, sizeof(conf->bssid));
++ }
++}
++
++static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev,
++ struct rt2x00lib_erp *erp)
++{
++ u32 reg;
++
+ rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®);
+- rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout);
++ rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout);
+ rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
+
+ rt73usb_register_read(rt2x00dev, TXRX_CSR4, ®);
+ rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE,
+- !!short_preamble);
++ !!erp->short_preamble);
+ rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg);
+ }
+
+@@ -442,28 +516,22 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
+ case ANTENNA_HW_DIVERSITY:
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
+ temp = !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)
+- && (rt2x00dev->curr_hwmode != HWMODE_A);
++ && (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ);
+ rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp);
+ break;
+ case ANTENNA_A:
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
+- if (rt2x00dev->curr_hwmode == HWMODE_A)
++ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
+ else
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
+ break;
+- case ANTENNA_SW_DIVERSITY:
+- /*
+- * NOTE: We should never come here because rt2x00lib is
+- * supposed to catch this and send us the correct antenna
+- * explicitely. However we are nog going to bug about this.
+- * Instead, just default to antenna B.
+- */
+ case ANTENNA_B:
++ default:
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
+- if (rt2x00dev->curr_hwmode == HWMODE_A)
++ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
+ else
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
+@@ -501,14 +569,8 @@ static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ break;
+- case ANTENNA_SW_DIVERSITY:
+- /*
+- * NOTE: We should never come here because rt2x00lib is
+- * supposed to catch this and send us the correct antenna
+- * explicitely. However we are nog going to bug about this.
+- * Instead, just default to antenna B.
+- */
+ case ANTENNA_B:
++ default:
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ break;
+@@ -558,7 +620,14 @@ static void rt73usb_config_antenna(struct rt2x00_dev *rt2x00dev,
+ unsigned int i;
+ u32 reg;
+
+- if (rt2x00dev->curr_hwmode == HWMODE_A) {
++ /*
++ * We should never come here because rt2x00lib is supposed
++ * to catch this and send us the correct antenna explicitely.
++ */
++ BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
++ ant->tx == ANTENNA_SW_DIVERSITY);
++
++ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
+ sel = antenna_sel_a;
+ lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
+ } else {
+@@ -572,10 +641,9 @@ static void rt73usb_config_antenna(struct rt2x00_dev *rt2x00dev,
+ rt73usb_register_read(rt2x00dev, PHY_CSR0, ®);
+
+ rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG,
+- (rt2x00dev->curr_hwmode == HWMODE_B ||
+- rt2x00dev->curr_hwmode == HWMODE_G));
++ (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ));
+ rt2x00_set_field32(®, PHY_CSR0_PA_PE_A,
+- (rt2x00dev->curr_hwmode == HWMODE_A));
++ (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ));
+
+ rt73usb_register_write(rt2x00dev, PHY_CSR0, reg);
+
+@@ -617,8 +685,8 @@ static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev,
+ }
+
+ static void rt73usb_config(struct rt2x00_dev *rt2x00dev,
+- const unsigned int flags,
+- struct rt2x00lib_conf *libconf)
++ struct rt2x00lib_conf *libconf,
++ const unsigned int flags)
+ {
+ if (flags & CONFIG_UPDATE_PHYMODE)
+ rt73usb_config_phymode(rt2x00dev, libconf->basic_rates);
+@@ -634,68 +702,6 @@ static void rt73usb_config(struct rt2x00_dev *rt2x00dev,
+ }
+
+ /*
+- * LED functions.
+- */
+-static void rt73usb_enable_led(struct rt2x00_dev *rt2x00dev)
+-{
+- u32 reg;
+-
+- rt73usb_register_read(rt2x00dev, MAC_CSR14, ®);
+- rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, 70);
+- rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, 30);
+- rt73usb_register_write(rt2x00dev, MAC_CSR14, reg);
+-
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1);
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS,
+- (rt2x00dev->rx_status.phymode == MODE_IEEE80211A));
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS,
+- (rt2x00dev->rx_status.phymode != MODE_IEEE80211A));
+-
+- rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000,
+- rt2x00dev->led_reg, REGISTER_TIMEOUT);
+-}
+-
+-static void rt73usb_disable_led(struct rt2x00_dev *rt2x00dev)
+-{
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 0);
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS, 0);
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS, 0);
+-
+- rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000,
+- rt2x00dev->led_reg, REGISTER_TIMEOUT);
+-}
+-
+-static void rt73usb_activity_led(struct rt2x00_dev *rt2x00dev, int rssi)
+-{
+- u32 led;
+-
+- if (rt2x00dev->led_mode != LED_MODE_SIGNAL_STRENGTH)
+- return;
+-
+- /*
+- * Led handling requires a positive value for the rssi,
+- * to do that correctly we need to add the correction.
+- */
+- rssi += rt2x00dev->rssi_offset;
+-
+- if (rssi <= 30)
+- led = 0;
+- else if (rssi <= 39)
+- led = 1;
+- else if (rssi <= 49)
+- led = 2;
+- else if (rssi <= 53)
+- led = 3;
+- else if (rssi <= 63)
+- led = 4;
+- else
+- led = 5;
+-
+- rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, led,
+- rt2x00dev->led_reg, REGISTER_TIMEOUT);
+-}
+-
+-/*
+ * Link tuning
+ */
+ static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev,
+@@ -729,17 +735,12 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
+ u8 up_bound;
+ u8 low_bound;
+
+- /*
+- * Update Led strength
+- */
+- rt73usb_activity_led(rt2x00dev, rssi);
+-
+ rt73usb_bbp_read(rt2x00dev, 17, &r17);
+
+ /*
+ * Determine r17 bounds.
+ */
+- if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
++ if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
+ low_bound = 0x28;
+ up_bound = 0x48;
+
+@@ -766,6 +767,13 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
+ }
+
+ /*
++ * If we are not associated, we should go straight to the
++ * dynamic CCA tuning.
++ */
++ if (!rt2x00dev->intf_associated)
++ goto dynamic_cca_tune;
++
++ /*
+ * Special big-R17 for very short distance
+ */
+ if (rssi > -35) {
+@@ -815,6 +823,8 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
+ return;
+ }
+
++dynamic_cca_tune:
++
+ /*
+ * r17 does not yet exceed upper limit, continue and base
+ * the r17 tuning on the false CCA count.
+@@ -833,16 +843,30 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
+ }
+
+ /*
+- * Firmware name function.
++ * Firmware functions
+ */
+ static char *rt73usb_get_firmware_name(struct rt2x00_dev *rt2x00dev)
+ {
+ return FIRMWARE_RT2571;
+ }
+
+-/*
+- * Initialization functions.
+- */
++static u16 rt73usb_get_firmware_crc(void *data, const size_t len)
++{
++ u16 crc;
++
++ /*
++ * Use the crc itu-t algorithm.
++ * The last 2 bytes in the firmware array are the crc checksum itself,
++ * this means that we should never pass those 2 bytes to the crc
++ * algorithm.
++ */
++ crc = crc_itu_t(0, data, len - 2);
++ crc = crc_itu_t_byte(crc, 0);
++ crc = crc_itu_t_byte(crc, 0);
++
++ return crc;
++}
++
+ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
+ const size_t len)
+ {
+@@ -889,7 +913,7 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
+
+ rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE,
+ USB_VENDOR_REQUEST_OUT,
+- FIRMWARE_IMAGE_BASE + i, 0x0000,
++ FIRMWARE_IMAGE_BASE + i, 0,
+ cache, buflen, timeout);
+
+ ptr += buflen;
+@@ -902,18 +926,19 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
+ * we need to specify a long timeout time.
+ */
+ status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE,
+- 0x0000, USB_MODE_FIRMWARE,
++ 0, USB_MODE_FIRMWARE,
+ REGISTER_TIMEOUT_FIRMWARE);
+ if (status < 0) {
+ ERROR(rt2x00dev, "Failed to write Firmware to device.\n");
+ return status;
+ }
+
+- rt73usb_disable_led(rt2x00dev);
+-
+ return 0;
+ }
+
++/*
++ * Initialization functions.
++ */
+ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
+ {
+ u32 reg;
+@@ -1021,6 +1046,17 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
+ rt73usb_register_write(rt2x00dev, MAC_CSR9, reg);
+
+ /*
++ * Clear all beacons
++ * For the Beacon base registers we only need to clear
++ * the first byte since that byte contains the VALID and OWNER
++ * bits which (when set to 0) will invalidate the entire beacon.
++ */
++ rt73usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
++ rt73usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
++ rt73usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
++ rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
++
++ /*
+ * We must clear the error counters.
+ * These registers are cleared on read,
+ * so we may pass a useless variable to store the value.
+@@ -1094,19 +1130,15 @@ continue_csr_init:
+ rt73usb_bbp_write(rt2x00dev, 102, 0x16);
+ rt73usb_bbp_write(rt2x00dev, 107, 0x04);
+
+- DEBUG(rt2x00dev, "Start initialization from EEPROM...\n");
+ for (i = 0; i < EEPROM_BBP_SIZE; i++) {
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+
+ if (eeprom != 0xffff && eeprom != 0x0000) {
+ reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
+ value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
+- DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n",
+- reg_id, value);
+ rt73usb_bbp_write(rt2x00dev, reg_id, value);
+ }
+ }
+- DEBUG(rt2x00dev, "...End initialization from EEPROM.\n");
+
+ return 0;
+ }
+@@ -1136,21 +1168,11 @@ static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev)
+ return -EIO;
+ }
+
+- /*
+- * Enable LED
+- */
+- rt73usb_enable_led(rt2x00dev);
+-
+ return 0;
+ }
+
+ static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev)
+ {
+- /*
+- * Disable LED
+- */
+- rt73usb_disable_led(rt2x00dev);
+-
+ rt73usb_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
+
+ /*
+@@ -1234,10 +1256,10 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev,
+ */
+ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ struct sk_buff *skb,
+- struct txdata_entry_desc *desc,
++ struct txentry_desc *txdesc,
+ struct ieee80211_tx_control *control)
+ {
+- struct skb_desc *skbdesc = get_skb_desc(skb);
++ struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+ __le32 *txd = skbdesc->desc;
+ u32 word;
+
+@@ -1245,47 +1267,47 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
+ * Start writing the descriptor words.
+ */
+ rt2x00_desc_read(txd, 1, &word);
+- rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, desc->queue);
+- rt2x00_set_field32(&word, TXD_W1_AIFSN, desc->aifs);
+- rt2x00_set_field32(&word, TXD_W1_CWMIN, desc->cw_min);
+- rt2x00_set_field32(&word, TXD_W1_CWMAX, desc->cw_max);
++ rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue);
++ rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs);
++ rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
++ rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
+ rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER);
+ rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, 1);
+ rt2x00_desc_write(txd, 1, word);
+
+ rt2x00_desc_read(txd, 2, &word);
+- rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, desc->signal);
+- rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, desc->service);
+- rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, desc->length_low);
+- rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, desc->length_high);
++ rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal);
++ rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service);
++ rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low);
++ rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
+ rt2x00_desc_write(txd, 2, word);
+
+ rt2x00_desc_read(txd, 5, &word);
+ rt2x00_set_field32(&word, TXD_W5_TX_POWER,
+- TXPOWER_TO_DEV(control->power_level));
++ TXPOWER_TO_DEV(rt2x00dev->tx_power));
+ rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
+ rt2x00_desc_write(txd, 5, word);
+
+ rt2x00_desc_read(txd, 0, &word);
+ rt2x00_set_field32(&word, TXD_W0_BURST,
+- test_bit(ENTRY_TXD_BURST, &desc->flags));
++ test_bit(ENTRY_TXD_BURST, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_VALID, 1);
+ rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
+- test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
++ test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_ACK,
+- test_bit(ENTRY_TXD_ACK, &desc->flags));
++ test_bit(ENTRY_TXD_ACK, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
+- test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
++ test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_OFDM,
+- test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags));
+- rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
++ test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
++ rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
+ rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
+ !!(control->flags &
+ IEEE80211_TXCTL_LONG_RETRY_LIMIT));
+ rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0);
+ rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
+ rt2x00_set_field32(&word, TXD_W0_BURST2,
+- test_bit(ENTRY_TXD_BURST, &desc->flags));
++ test_bit(ENTRY_TXD_BURST, &txdesc->flags));
+ rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
+ rt2x00_desc_write(txd, 0, word);
+ }
+@@ -1309,11 +1331,11 @@ static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
+ * TX data initialization
+ */
+ static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
+- unsigned int queue)
++ const unsigned int queue)
+ {
+ u32 reg;
+
+- if (queue != IEEE80211_TX_QUEUE_BEACON)
++ if (queue != RT2X00_BCN_QUEUE_BEACON)
+ return;
+
+ /*
+@@ -1324,6 +1346,8 @@ static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
+
+ rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®);
+ if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) {
++ rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1);
++ rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1);
+ rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1);
+ rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+ }
+@@ -1353,7 +1377,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
+ return 0;
+ }
+
+- if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
++ if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
+ if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
+ if (lna == 3 || lna == 2)
+ offset += 10;
+@@ -1377,37 +1401,62 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
+ return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
+ }
+
+-static void rt73usb_fill_rxdone(struct data_entry *entry,
+- struct rxdata_entry_desc *desc)
++static void rt73usb_fill_rxdone(struct queue_entry *entry,
++ struct rxdone_entry_desc *rxdesc)
+ {
+- struct skb_desc *skbdesc = get_skb_desc(entry->skb);
++ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+ __le32 *rxd = (__le32 *)entry->skb->data;
++ unsigned int offset = entry->queue->desc_size + 2;
+ u32 word0;
+ u32 word1;
+
++ /*
++ * Copy descriptor to the available headroom inside the skbuffer.
++ */
++ skb_push(entry->skb, offset);
++ memcpy(entry->skb->data, rxd, entry->queue->desc_size);
++ rxd = (__le32 *)entry->skb->data;
++
++ /*
++ * The descriptor is now aligned to 4 bytes and thus it is
++ * now safe to read it on all architectures.
++ */
+ rt2x00_desc_read(rxd, 0, &word0);
+ rt2x00_desc_read(rxd, 1, &word1);
+
+- desc->flags = 0;
++ rxdesc->flags = 0;
+ if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
+- desc->flags |= RX_FLAG_FAILED_FCS_CRC;
++ rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
+
+ /*
+ * Obtain the status about this packet.
++ * When frame was received with an OFDM bitrate,
++ * the signal is the PLCP value. If it was received with
++ * a CCK bitrate the signal is the rate in 100kbit/s.
+ */
+- desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
+- desc->rssi = rt73usb_agc_to_rssi(entry->ring->rt2x00dev, word1);
+- desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
+- desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+- desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
++ rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
++ rxdesc->rssi = rt73usb_agc_to_rssi(entry->queue->rt2x00dev, word1);
++ rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
++
++ rxdesc->dev_flags = 0;
++ if (rt2x00_get_field32(word0, RXD_W0_OFDM))
++ rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
++ if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
++ rxdesc->dev_flags |= RXDONE_MY_BSS;
++
++ /*
++ * Adjust the skb memory window to the frame boundaries.
++ */
++ skb_pull(entry->skb, offset + entry->queue->desc_size);
++ skb_trim(entry->skb, rxdesc->size);
+
+ /*
+ * Set descriptor and data pointer.
+ */
+- skbdesc->desc = entry->skb->data;
+- skbdesc->desc_len = entry->ring->desc_size;
+- skbdesc->data = entry->skb->data + entry->ring->desc_size;
+- skbdesc->data_len = desc->size;
++ skbdesc->data = entry->skb->data;
++ skbdesc->data_len = rxdesc->size;
++ skbdesc->desc = rxd;
++ skbdesc->desc_len = entry->queue->desc_size;
+ }
+
+ /*
+@@ -1499,7 +1548,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
+ rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
+ rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
+ rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
+- EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
++ EEPROM(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);
+ } else {
+ value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);
+ if (value < -10 || value > 10)
+@@ -1577,33 +1626,60 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
+ /*
+ * Store led settings, for correct led behaviour.
+ */
++#ifdef CONFIG_RT73USB_LEDS
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
+
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LED_MODE,
+- rt2x00dev->led_mode);
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_0,
++ rt2x00dev->led_radio.rt2x00dev = rt2x00dev;
++ rt2x00dev->led_radio.type = LED_TYPE_RADIO;
++ rt2x00dev->led_radio.led_dev.brightness_set =
++ rt73usb_brightness_set;
++ rt2x00dev->led_radio.led_dev.blink_set =
++ rt73usb_blink_set;
++ rt2x00dev->led_radio.flags = LED_INITIALIZED;
++
++ rt2x00dev->led_assoc.rt2x00dev = rt2x00dev;
++ rt2x00dev->led_assoc.type = LED_TYPE_ASSOC;
++ rt2x00dev->led_assoc.led_dev.brightness_set =
++ rt73usb_brightness_set;
++ rt2x00dev->led_assoc.led_dev.blink_set =
++ rt73usb_blink_set;
++ rt2x00dev->led_assoc.flags = LED_INITIALIZED;
++
++ if (value == LED_MODE_SIGNAL_STRENGTH) {
++ rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
++ rt2x00dev->led_radio.type = LED_TYPE_QUALITY;
++ rt2x00dev->led_qual.led_dev.brightness_set =
++ rt73usb_brightness_set;
++ rt2x00dev->led_qual.led_dev.blink_set =
++ rt73usb_blink_set;
++ rt2x00dev->led_qual.flags = LED_INITIALIZED;
++ }
++
++ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value);
++ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0,
+ rt2x00_get_field16(eeprom,
+ EEPROM_LED_POLARITY_GPIO_0));
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_1,
++ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_1,
+ rt2x00_get_field16(eeprom,
+ EEPROM_LED_POLARITY_GPIO_1));
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_2,
++ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_2,
+ rt2x00_get_field16(eeprom,
+ EEPROM_LED_POLARITY_GPIO_2));
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_3,
++ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_3,
+ rt2x00_get_field16(eeprom,
+ EEPROM_LED_POLARITY_GPIO_3));
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_4,
++ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_4,
+ rt2x00_get_field16(eeprom,
+ EEPROM_LED_POLARITY_GPIO_4));
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_ACT,
++ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_ACT,
+ rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_ACT));
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_BG,
++ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_BG,
+ rt2x00_get_field16(eeprom,
+ EEPROM_LED_POLARITY_RDY_G));
+- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_A,
++ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_A,
+ rt2x00_get_field16(eeprom,
+ EEPROM_LED_POLARITY_RDY_A));
++#endif /* CONFIG_RT73USB_LEDS */
+
+ return 0;
+ }
+@@ -1759,7 +1835,7 @@ static void rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+ rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
+ rt2x00dev->hw->max_signal = MAX_SIGNAL;
+ rt2x00dev->hw->max_rssi = MAX_RX_SSI;
+- rt2x00dev->hw->queues = 5;
++ rt2x00dev->hw->queues = 4;
+
+ SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev);
+ SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
+@@ -1776,8 +1852,8 @@ static void rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+ /*
+ * Initialize hw_mode information.
+ */
+- spec->num_modes = 2;
+- spec->num_rates = 12;
++ spec->supported_bands = SUPPORT_BAND_2GHZ;
++ spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
+ spec->tx_power_a = NULL;
+ spec->tx_power_bg = txpower;
+ spec->tx_power_default = DEFAULT_TXPOWER;
+@@ -1786,20 +1862,20 @@ static void rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+ spec->num_channels = ARRAY_SIZE(rf_vals_bg_2528);
+ spec->channels = rf_vals_bg_2528;
+ } else if (rt2x00_rf(&rt2x00dev->chip, RF5226)) {
++ spec->supported_bands |= SUPPORT_BAND_5GHZ;
+ spec->num_channels = ARRAY_SIZE(rf_vals_5226);
+ spec->channels = rf_vals_5226;
+ } else if (rt2x00_rf(&rt2x00dev->chip, RF2527)) {
+ spec->num_channels = 14;
+ spec->channels = rf_vals_5225_2527;
+ } else if (rt2x00_rf(&rt2x00dev->chip, RF5225)) {
++ spec->supported_bands |= SUPPORT_BAND_5GHZ;
+ spec->num_channels = ARRAY_SIZE(rf_vals_5225_2527);
+ spec->channels = rf_vals_5225_2527;
+ }
+
+ if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
+ rt2x00_rf(&rt2x00dev->chip, RF5226)) {
+- spec->num_modes = 3;
+-
+ txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
+ for (i = 0; i < 14; i++)
+ txpower[i] = TXPOWER_FROM_DEV(txpower[i]);
+@@ -1829,9 +1905,10 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
+ rt73usb_probe_hw_mode(rt2x00dev);
+
+ /*
+- * This device requires firmware
++ * This device requires firmware.
+ */
+ __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
++ __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags);
+
+ /*
+ * Set the rssi offset.
+@@ -1844,79 +1921,6 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
+ /*
+ * IEEE80211 stack callback functions.
+ */
+-static void rt73usb_configure_filter(struct ieee80211_hw *hw,
+- unsigned int changed_flags,
+- unsigned int *total_flags,
+- int mc_count,
+- struct dev_addr_list *mc_list)
+-{
+- struct rt2x00_dev *rt2x00dev = hw->priv;
+- u32 reg;
+-
+- /*
+- * Mask off any flags we are going to ignore from
+- * the total_flags field.
+- */
+- *total_flags &=
+- FIF_ALLMULTI |
+- FIF_FCSFAIL |
+- FIF_PLCPFAIL |
+- FIF_CONTROL |
+- FIF_OTHER_BSS |
+- FIF_PROMISC_IN_BSS;
+-
+- /*
+- * Apply some rules to the filters:
+- * - Some filters imply different filters to be set.
+- * - Some things we can't filter out at all.
+- * - Multicast filter seems to kill broadcast traffic so never use it.
+- */
+- *total_flags |= FIF_ALLMULTI;
+- if (*total_flags & FIF_OTHER_BSS ||
+- *total_flags & FIF_PROMISC_IN_BSS)
+- *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
+-
+- /*
+- * Check if there is any work left for us.
+- */
+- if (rt2x00dev->packet_filter == *total_flags)
+- return;
+- rt2x00dev->packet_filter = *total_flags;
+-
+- /*
+- * When in atomic context, reschedule and let rt2x00lib
+- * call this function again.
+- */
+- if (in_atomic()) {
+- queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work);
+- return;
+- }
+-
+- /*
+- * Start configuration steps.
+- * Note that the version error will always be dropped
+- * and broadcast frames will always be accepted since
+- * there is no filter for it at this time.
+- */
+- rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®);
+- rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC,
+- !(*total_flags & FIF_FCSFAIL));
+- rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL,
+- !(*total_flags & FIF_PLCPFAIL));
+- rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL,
+- !(*total_flags & FIF_CONTROL));
+- rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME,
+- !(*total_flags & FIF_PROMISC_IN_BSS));
+- rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS,
+- !(*total_flags & FIF_PROMISC_IN_BSS));
+- rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1);
+- rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST,
+- !(*total_flags & FIF_ALLMULTI));
+- rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0);
+- rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, 1);
+- rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
+-}
+-
+ static int rt73usb_set_retry_limit(struct ieee80211_hw *hw,
+ u32 short_retry, u32 long_retry)
+ {
+@@ -1955,61 +1959,65 @@ static u64 rt73usb_get_tsf(struct ieee80211_hw *hw)
+ #define rt73usb_get_tsf NULL
+ #endif
+
+-static void rt73usb_reset_tsf(struct ieee80211_hw *hw)
+-{
+- struct rt2x00_dev *rt2x00dev = hw->priv;
+-
+- rt73usb_register_write(rt2x00dev, TXRX_CSR12, 0);
+- rt73usb_register_write(rt2x00dev, TXRX_CSR13, 0);
+-}
+-
+ static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
+- struct ieee80211_tx_control *control)
++ struct ieee80211_tx_control *control)
+ {
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+- struct skb_desc *desc;
+- struct data_ring *ring;
+- struct data_entry *entry;
+- int timeout;
++ struct rt2x00_intf *intf = vif_to_intf(control->vif);
++ struct skb_frame_desc *skbdesc;
++ unsigned int beacon_base;
++ unsigned int timeout;
++ u32 reg;
+
+- /*
+- * Just in case the ieee80211 doesn't set this,
+- * but we need this queue set for the descriptor
+- * initialization.
+- */
+- control->queue = IEEE80211_TX_QUEUE_BEACON;
+- ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
+- entry = rt2x00_get_data_entry(ring);
++ if (unlikely(!intf->beacon))
++ return -ENOBUFS;
+
+ /*
+ * Add the descriptor in front of the skb.
+ */
+- skb_push(skb, ring->desc_size);
+- memset(skb->data, 0, ring->desc_size);
++ skb_push(skb, intf->beacon->queue->desc_size);
++ memset(skb->data, 0, intf->beacon->queue->desc_size);
+
+ /*
+ * Fill in skb descriptor
+ */
+- desc = get_skb_desc(skb);
+- desc->desc_len = ring->desc_size;
+- desc->data_len = skb->len - ring->desc_size;
+- desc->desc = skb->data;
+- desc->data = skb->data + ring->desc_size;
+- desc->ring = ring;
+- desc->entry = entry;
++ skbdesc = get_skb_frame_desc(skb);
++ memset(skbdesc, 0, sizeof(*skbdesc));
++ skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
++ skbdesc->data = skb->data + intf->beacon->queue->desc_size;
++ skbdesc->data_len = skb->len - intf->beacon->queue->desc_size;
++ skbdesc->desc = skb->data;
++ skbdesc->desc_len = intf->beacon->queue->desc_size;
++ skbdesc->entry = intf->beacon;
+
++ /*
++ * Disable beaconing while we are reloading the beacon data,
++ * otherwise we might be sending out invalid data.
++ */
++ rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®);
++ rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0);
++ rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0);
++ rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0);
++ rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
++
++ /*
++ * mac80211 doesn't provide the control->queue variable
++ * for beacons. Set our own queue identification so
++ * it can be used during descriptor initialization.
++ */
++ control->queue = RT2X00_BCN_QUEUE_BEACON;
+ rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
+
+ /*
+ * Write entire beacon with descriptor to register,
+ * and kick the beacon generator.
+ */
++ beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
+ timeout = REGISTER_TIMEOUT * (skb->len / sizeof(u32));
+ rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE,
+- USB_VENDOR_REQUEST_OUT,
+- HW_BEACON_BASE0, 0x0000,
++ USB_VENDOR_REQUEST_OUT, beacon_base, 0,
+ skb->data, skb->len, timeout);
+- rt73usb_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
++ rt73usb_kick_tx_queue(rt2x00dev, control->queue);
+
+ return 0;
+ }
+@@ -2022,20 +2030,20 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
+ .remove_interface = rt2x00mac_remove_interface,
+ .config = rt2x00mac_config,
+ .config_interface = rt2x00mac_config_interface,
+- .configure_filter = rt73usb_configure_filter,
++ .configure_filter = rt2x00mac_configure_filter,
+ .get_stats = rt2x00mac_get_stats,
+ .set_retry_limit = rt73usb_set_retry_limit,
+ .bss_info_changed = rt2x00mac_bss_info_changed,
+ .conf_tx = rt2x00mac_conf_tx,
+ .get_tx_stats = rt2x00mac_get_tx_stats,
+ .get_tsf = rt73usb_get_tsf,
+- .reset_tsf = rt73usb_reset_tsf,
+ .beacon_update = rt73usb_beacon_update,
+ };
+
+ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
+ .probe_hw = rt73usb_probe_hw,
+ .get_firmware_name = rt73usb_get_firmware_name,
++ .get_firmware_crc = rt73usb_get_firmware_crc,
+ .load_firmware = rt73usb_load_firmware,
+ .initialize = rt2x00usb_initialize,
+ .uninitialize = rt2x00usb_uninitialize,
+@@ -2050,19 +2058,42 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
+ .get_tx_data_len = rt73usb_get_tx_data_len,
+ .kick_tx_queue = rt73usb_kick_tx_queue,
+ .fill_rxdone = rt73usb_fill_rxdone,
+- .config_mac_addr = rt73usb_config_mac_addr,
+- .config_bssid = rt73usb_config_bssid,
+- .config_type = rt73usb_config_type,
+- .config_preamble = rt73usb_config_preamble,
++ .config_filter = rt73usb_config_filter,
++ .config_intf = rt73usb_config_intf,
++ .config_erp = rt73usb_config_erp,
+ .config = rt73usb_config,
+ };
+
++static const struct data_queue_desc rt73usb_queue_rx = {
++ .entry_num = RX_ENTRIES,
++ .data_size = DATA_FRAME_SIZE,
++ .desc_size = RXD_DESC_SIZE,
++ .priv_size = sizeof(struct queue_entry_priv_usb_rx),
++};
++
++static const struct data_queue_desc rt73usb_queue_tx = {
++ .entry_num = TX_ENTRIES,
++ .data_size = DATA_FRAME_SIZE,
++ .desc_size = TXD_DESC_SIZE,
++ .priv_size = sizeof(struct queue_entry_priv_usb_tx),
++};
++
++static const struct data_queue_desc rt73usb_queue_bcn = {
++ .entry_num = 4 * BEACON_ENTRIES,
++ .data_size = MGMT_FRAME_SIZE,
++ .desc_size = TXINFO_SIZE,
++ .priv_size = sizeof(struct queue_entry_priv_usb_tx),
++};
++
+ static const struct rt2x00_ops rt73usb_ops = {
+ .name = KBUILD_MODNAME,
+- .rxd_size = RXD_DESC_SIZE,
+- .txd_size = TXD_DESC_SIZE,
++ .max_sta_intf = 1,
++ .max_ap_intf = 4,
+ .eeprom_size = EEPROM_SIZE,
+ .rf_size = RF_SIZE,
++ .rx = &rt73usb_queue_rx,
++ .tx = &rt73usb_queue_tx,
++ .bcn = &rt73usb_queue_bcn,
+ .lib = &rt73usb_rt2x00_ops,
+ .hw = &rt73usb_mac80211_ops,
+ #ifdef CONFIG_RT2X00_LIB_DEBUGFS
+diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h
+index d49dcaa..06d6874 100644
+--- a/drivers/net/wireless/rt2x00/rt73usb.h
++++ b/drivers/net/wireless/rt2x00/rt73usb.h
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+@@ -114,6 +114,9 @@ struct hw_pairwise_ta_entry {
+ #define HW_BEACON_BASE2 0x2600
+ #define HW_BEACON_BASE3 0x2700
+
++#define HW_BEACON_OFFSET(__index) \
++ ( HW_BEACON_BASE0 + (__index * 0x0100) )
++
+ /*
+ * MAC Control/Status Registers(CSR).
+ * Some values are set in TU, whereas 1 TU == 1024 us.
+@@ -146,6 +149,11 @@ struct hw_pairwise_ta_entry {
+
+ /*
+ * MAC_CSR3: STA MAC register 1.
++ * UNICAST_TO_ME_MASK:
++ * Used to mask off bits from byte 5 of the MAC address
++ * to determine the UNICAST_TO_ME bit for RX frames.
++ * The full mask is complemented by BSS_ID_MASK:
++ * MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK
+ */
+ #define MAC_CSR3 0x300c
+ #define MAC_CSR3_BYTE4 FIELD32(0x000000ff)
+@@ -163,7 +171,14 @@ struct hw_pairwise_ta_entry {
+
+ /*
+ * MAC_CSR5: BSSID register 1.
+- * BSS_ID_MASK: 3: one BSSID, 0: 4 BSSID, 2 or 1: 2 BSSID.
++ * BSS_ID_MASK:
++ * This mask is used to mask off bits 0 and 1 of byte 5 of the
++ * BSSID. This will make sure that those bits will be ignored
++ * when determining the MY_BSS of RX frames.
++ * 0: 1-BSSID mode (BSS index = 0)
++ * 1: 2-BSSID mode (BSS index: Byte5, bit 0)
++ * 2: 2-BSSID mode (BSS index: byte5, bit 1)
++ * 3: 4-BSSID mode (BSS index: byte5, bit 0 - 1)
+ */
+ #define MAC_CSR5 0x3014
+ #define MAC_CSR5_BYTE4 FIELD32(0x000000ff)
+@@ -867,6 +882,7 @@ struct hw_pairwise_ta_entry {
+ * DMA descriptor defines.
+ */
+ #define TXD_DESC_SIZE ( 6 * sizeof(__le32) )
++#define TXINFO_SIZE ( 6 * sizeof(__le32) )
+ #define RXD_DESC_SIZE ( 6 * sizeof(__le32) )
+
+ /*
+@@ -1007,8 +1023,8 @@ struct hw_pairwise_ta_entry {
+ #define RXD_W5_RESERVED FIELD32(0xffffffff)
+
+ /*
+- * Macro's for converting txpower from EEPROM to dscape value
+- * and from dscape value to register value.
++ * Macro's for converting txpower from EEPROM to mac80211 value
++ * and from mac80211 value to register value.
+ */
+ #define MIN_TXPOWER 0
+ #define MAX_TXPOWER 31
+diff --git a/drivers/net/wireless/rtl8180.h b/drivers/net/wireless/rtl8180.h
+index 2cbfe3c..082a11f 100644
+--- a/drivers/net/wireless/rtl8180.h
++++ b/drivers/net/wireless/rtl8180.h
+@@ -102,7 +102,7 @@ struct rtl8180_priv {
+ struct rtl8180_tx_ring tx_ring[4];
+ struct ieee80211_channel channels[14];
+ struct ieee80211_rate rates[12];
+- struct ieee80211_hw_mode modes[2];
++ struct ieee80211_supported_band band;
+ struct pci_dev *pdev;
+ u32 rx_conf;
+
+diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c
+index 5e9a8ac..c181f23 100644
+--- a/drivers/net/wireless/rtl8180_dev.c
++++ b/drivers/net/wireless/rtl8180_dev.c
+@@ -49,6 +49,41 @@ static struct pci_device_id rtl8180_table[] __devinitdata = {
+
+ MODULE_DEVICE_TABLE(pci, rtl8180_table);
+
++static const struct ieee80211_rate rtl818x_rates[] = {
++ { .bitrate = 10, .hw_value = 0, },
++ { .bitrate = 20, .hw_value = 1, },
++ { .bitrate = 55, .hw_value = 2, },
++ { .bitrate = 110, .hw_value = 3, },
++ { .bitrate = 60, .hw_value = 4, },
++ { .bitrate = 90, .hw_value = 5, },
++ { .bitrate = 120, .hw_value = 6, },
++ { .bitrate = 180, .hw_value = 7, },
++ { .bitrate = 240, .hw_value = 8, },
++ { .bitrate = 360, .hw_value = 9, },
++ { .bitrate = 480, .hw_value = 10, },
++ { .bitrate = 540, .hw_value = 11, },
++};
++
++static const struct ieee80211_channel rtl818x_channels[] = {
++ { .center_freq = 2412 },
++ { .center_freq = 2417 },
++ { .center_freq = 2422 },
++ { .center_freq = 2427 },
++ { .center_freq = 2432 },
++ { .center_freq = 2437 },
++ { .center_freq = 2442 },
++ { .center_freq = 2447 },
++ { .center_freq = 2452 },
++ { .center_freq = 2457 },
++ { .center_freq = 2462 },
++ { .center_freq = 2467 },
++ { .center_freq = 2472 },
++ { .center_freq = 2484 },
++};
++
++
++
++
+ void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
+ {
+ struct rtl8180_priv *priv = dev->priv;
+@@ -99,10 +134,10 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
+ /* TODO: improve signal/rssi reporting */
+ rx_status.signal = flags2 & 0xFF;
+ rx_status.ssi = (flags2 >> 8) & 0x7F;
+- rx_status.rate = (flags >> 20) & 0xF;
+- rx_status.freq = dev->conf.freq;
+- rx_status.channel = dev->conf.channel;
+- rx_status.phymode = dev->conf.phymode;
++ /* XXX: is this correct? */
++ rx_status.rate_idx = (flags >> 20) & 0xF;
++ rx_status.freq = dev->conf.channel->center_freq;
++ rx_status.band = dev->conf.channel->band;
+ rx_status.mactime = le64_to_cpu(entry->tsft);
+ rx_status.flag |= RX_FLAG_TSFT;
+ if (flags & RTL8180_RX_DESC_FLAG_CRC32_ERR)
+@@ -222,18 +257,25 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
+ mapping = pci_map_single(priv->pdev, skb->data,
+ skb->len, PCI_DMA_TODEVICE);
+
++ BUG_ON(!control->tx_rate);
++
+ tx_flags = RTL8180_TX_DESC_FLAG_OWN | RTL8180_TX_DESC_FLAG_FS |
+- RTL8180_TX_DESC_FLAG_LS | (control->tx_rate << 24) |
+- (control->rts_cts_rate << 19) | skb->len;
++ RTL8180_TX_DESC_FLAG_LS |
++ (control->tx_rate->hw_value << 24) | skb->len;
+
+ if (priv->r8185)
+ tx_flags |= RTL8180_TX_DESC_FLAG_DMA |
+ RTL8180_TX_DESC_FLAG_NO_ENC;
+
+- if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
++ if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
++ BUG_ON(!control->rts_cts_rate);
+ tx_flags |= RTL8180_TX_DESC_FLAG_RTS;
+- else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
++ tx_flags |= control->rts_cts_rate->hw_value << 19;
++ } else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
++ BUG_ON(!control->rts_cts_rate);
+ tx_flags |= RTL8180_TX_DESC_FLAG_CTS;
++ tx_flags |= control->rts_cts_rate->hw_value << 19;
++ }
+
+ *((struct ieee80211_tx_control **) skb->cb) =
+ kmemdup(control, sizeof(*control), GFP_ATOMIC);
+@@ -246,9 +288,9 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
+ unsigned int remainder;
+
+ plcp_len = DIV_ROUND_UP(16 * (skb->len + 4),
+- (control->rate->rate * 2) / 10);
++ (control->tx_rate->bitrate * 2) / 10);
+ remainder = (16 * (skb->len + 4)) %
+- ((control->rate->rate * 2) / 10);
++ ((control->tx_rate->bitrate * 2) / 10);
+ if (remainder > 0 && remainder <= 6)
+ plcp_len |= 1 << 15;
+ }
+@@ -261,8 +303,8 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
+ entry->plcp_len = cpu_to_le16(plcp_len);
+ entry->tx_buf = cpu_to_le32(mapping);
+ entry->frame_len = cpu_to_le32(skb->len);
+- entry->flags2 = control->alt_retry_rate != -1 ?
+- control->alt_retry_rate << 4 : 0;
++ entry->flags2 = control->alt_retry_rate != NULL ?
++ control->alt_retry_rate->bitrate << 4 : 0;
+ entry->retry_limit = control->retry_limit;
+ entry->flags = cpu_to_le32(tx_flags);
+ __skb_queue_tail(&ring->queue, skb);
+@@ -646,9 +688,9 @@ static int rtl8180_add_interface(struct ieee80211_hw *dev,
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0],
+- cpu_to_le32(*(u32 *)conf->mac_addr));
++ le32_to_cpu(*(__le32 *)conf->mac_addr));
+ rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->MAC[4],
+- cpu_to_le16(*(u16 *)(conf->mac_addr + 4)));
++ le16_to_cpu(*(__le16 *)(conf->mac_addr + 4)));
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ return 0;
+@@ -838,19 +880,19 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
+ goto err_free_dev;
+ }
+
++ BUILD_BUG_ON(sizeof(priv->channels) != sizeof(rtl818x_channels));
++ BUILD_BUG_ON(sizeof(priv->rates) != sizeof(rtl818x_rates));
++
+ memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels));
+ memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates));
+- priv->modes[0].mode = MODE_IEEE80211G;
+- priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates);
+- priv->modes[0].rates = priv->rates;
+- priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels);
+- priv->modes[0].channels = priv->channels;
+- priv->modes[1].mode = MODE_IEEE80211B;
+- priv->modes[1].num_rates = 4;
+- priv->modes[1].rates = priv->rates;
+- priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels);
+- priv->modes[1].channels = priv->channels;
+- priv->mode = IEEE80211_IF_TYPE_INVALID;
++
++ priv->band.band = IEEE80211_BAND_2GHZ;
++ priv->band.channels = priv->channels;
++ priv->band.n_channels = ARRAY_SIZE(rtl818x_channels);
++ priv->band.bitrates = priv->rates;
++ priv->band.n_bitrates = 4;
++ dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
++
+ dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+ IEEE80211_HW_RX_INCLUDES_FCS;
+ dev->queues = 1;
+@@ -879,15 +921,10 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
+
+ priv->r8185 = reg & RTL818X_TX_CONF_R8185_ABC;
+ if (priv->r8185) {
+- if ((err = ieee80211_register_hwmode(dev, &priv->modes[0])))
+- goto err_iounmap;
+-
++ priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates);
+ pci_try_set_mwi(pdev);
+ }
+
+- if ((err = ieee80211_register_hwmode(dev, &priv->modes[1])))
+- goto err_iounmap;
+-
+ eeprom.data = dev;
+ eeprom.register_read = rtl8180_eeprom_register_read;
+ eeprom.register_write = rtl8180_eeprom_register_write;
+@@ -950,8 +987,8 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
+ for (i = 0; i < 14; i += 2) {
+ u16 txpwr;
+ eeprom_93cx6_read(&eeprom, 0x10 + (i >> 1), &txpwr);
+- priv->channels[i].val = txpwr & 0xFF;
+- priv->channels[i + 1].val = txpwr >> 8;
++ priv->channels[i].hw_value = txpwr & 0xFF;
++ priv->channels[i + 1].hw_value = txpwr >> 8;
+ }
+
+ /* OFDM TX power */
+@@ -959,8 +996,8 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
+ for (i = 0; i < 14; i += 2) {
+ u16 txpwr;
+ eeprom_93cx6_read(&eeprom, 0x20 + (i >> 1), &txpwr);
+- priv->channels[i].val |= (txpwr & 0xFF) << 8;
+- priv->channels[i + 1].val |= txpwr & 0xFF00;
++ priv->channels[i].hw_value |= (txpwr & 0xFF) << 8;
++ priv->channels[i + 1].hw_value |= txpwr & 0xFF00;
+ }
+ }
+
+diff --git a/drivers/net/wireless/rtl8180_grf5101.c b/drivers/net/wireless/rtl8180_grf5101.c
+index 8293e19..5d47935 100644
+--- a/drivers/net/wireless/rtl8180_grf5101.c
++++ b/drivers/net/wireless/rtl8180_grf5101.c
+@@ -73,8 +73,9 @@ static void grf5101_rf_set_channel(struct ieee80211_hw *dev,
+ struct ieee80211_conf *conf)
+ {
+ struct rtl8180_priv *priv = dev->priv;
+- u32 txpw = priv->channels[conf->channel - 1].val & 0xFF;
+- u32 chan = conf->channel - 1;
++ int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
++ u32 txpw = priv->channels[channel - 1].hw_value & 0xFF;
++ u32 chan = channel - 1;
+
+ /* set TX power */
+ write_grf5101(dev, 0x15, 0x0);
+diff --git a/drivers/net/wireless/rtl8180_max2820.c b/drivers/net/wireless/rtl8180_max2820.c
+index 98fe9fd..a34dfd3 100644
+--- a/drivers/net/wireless/rtl8180_max2820.c
++++ b/drivers/net/wireless/rtl8180_max2820.c
+@@ -78,8 +78,9 @@ static void max2820_rf_set_channel(struct ieee80211_hw *dev,
+ struct ieee80211_conf *conf)
+ {
+ struct rtl8180_priv *priv = dev->priv;
+- unsigned int chan_idx = conf ? conf->channel - 1 : 0;
+- u32 txpw = priv->channels[chan_idx].val & 0xFF;
++ int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
++ unsigned int chan_idx = channel - 1;
++ u32 txpw = priv->channels[chan_idx].hw_value & 0xFF;
+ u32 chan = max2820_chan[chan_idx];
+
+ /* While philips SA2400 drive the PA bias from
+diff --git a/drivers/net/wireless/rtl8180_rtl8225.c b/drivers/net/wireless/rtl8180_rtl8225.c
+index ef3832b..cd22781 100644
+--- a/drivers/net/wireless/rtl8180_rtl8225.c
++++ b/drivers/net/wireless/rtl8180_rtl8225.c
+@@ -261,8 +261,8 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
+ u32 reg;
+ int i;
+
+- cck_power = priv->channels[channel - 1].val & 0xFF;
+- ofdm_power = priv->channels[channel - 1].val >> 8;
++ cck_power = priv->channels[channel - 1].hw_value & 0xFF;
++ ofdm_power = priv->channels[channel - 1].hw_value >> 8;
+
+ cck_power = min(cck_power, (u8)35);
+ ofdm_power = min(ofdm_power, (u8)35);
+@@ -476,8 +476,8 @@ static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
+ const u8 *tmp;
+ int i;
+
+- cck_power = priv->channels[channel - 1].val & 0xFF;
+- ofdm_power = priv->channels[channel - 1].val >> 8;
++ cck_power = priv->channels[channel - 1].hw_value & 0xFF;
++ ofdm_power = priv->channels[channel - 1].hw_value >> 8;
+
+ if (channel == 14)
+ tmp = rtl8225z2_tx_power_cck_ch14;
+@@ -716,13 +716,14 @@ static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
+ struct ieee80211_conf *conf)
+ {
+ struct rtl8180_priv *priv = dev->priv;
++ int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
+
+ if (priv->rf->init == rtl8225_rf_init)
+- rtl8225_rf_set_tx_power(dev, conf->channel);
++ rtl8225_rf_set_tx_power(dev, chan);
+ else
+- rtl8225z2_rf_set_tx_power(dev, conf->channel);
++ rtl8225z2_rf_set_tx_power(dev, chan);
+
+- rtl8225_write(dev, 0x7, rtl8225_chan[conf->channel - 1]);
++ rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
+ msleep(10);
+
+ if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
+diff --git a/drivers/net/wireless/rtl8180_sa2400.c b/drivers/net/wireless/rtl8180_sa2400.c
+index e08ace7..0311b4e 100644
+--- a/drivers/net/wireless/rtl8180_sa2400.c
++++ b/drivers/net/wireless/rtl8180_sa2400.c
+@@ -80,8 +80,9 @@ static void sa2400_rf_set_channel(struct ieee80211_hw *dev,
+ struct ieee80211_conf *conf)
+ {
+ struct rtl8180_priv *priv = dev->priv;
+- u32 txpw = priv->channels[conf->channel - 1].val & 0xFF;
+- u32 chan = sa2400_chan[conf->channel - 1];
++ int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
++ u32 txpw = priv->channels[channel - 1].hw_value & 0xFF;
++ u32 chan = sa2400_chan[channel - 1];
+
+ write_sa2400(dev, 7, txpw);
+
+diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h
+index 8680a0b..076d88b 100644
+--- a/drivers/net/wireless/rtl8187.h
++++ b/drivers/net/wireless/rtl8187.h
+@@ -71,7 +71,7 @@ struct rtl8187_priv {
+ /* rtl8187 specific */
+ struct ieee80211_channel channels[14];
+ struct ieee80211_rate rates[12];
+- struct ieee80211_hw_mode modes[2];
++ struct ieee80211_supported_band band;
+ struct usb_device *udev;
+ u32 rx_conf;
+ u16 txpwr_base;
+diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
+index 133b3f3..d5787b3 100644
+--- a/drivers/net/wireless/rtl8187_dev.c
++++ b/drivers/net/wireless/rtl8187_dev.c
+@@ -45,6 +45,38 @@ static struct usb_device_id rtl8187_table[] __devinitdata = {
+
+ MODULE_DEVICE_TABLE(usb, rtl8187_table);
+
++static const struct ieee80211_rate rtl818x_rates[] = {
++ { .bitrate = 10, .hw_value = 0, },
++ { .bitrate = 20, .hw_value = 1, },
++ { .bitrate = 55, .hw_value = 2, },
++ { .bitrate = 110, .hw_value = 3, },
++ { .bitrate = 60, .hw_value = 4, },
++ { .bitrate = 90, .hw_value = 5, },
++ { .bitrate = 120, .hw_value = 6, },
++ { .bitrate = 180, .hw_value = 7, },
++ { .bitrate = 240, .hw_value = 8, },
++ { .bitrate = 360, .hw_value = 9, },
++ { .bitrate = 480, .hw_value = 10, },
++ { .bitrate = 540, .hw_value = 11, },
++};
++
++static const struct ieee80211_channel rtl818x_channels[] = {
++ { .center_freq = 2412 },
++ { .center_freq = 2417 },
++ { .center_freq = 2422 },
++ { .center_freq = 2427 },
++ { .center_freq = 2432 },
++ { .center_freq = 2437 },
++ { .center_freq = 2442 },
++ { .center_freq = 2447 },
++ { .center_freq = 2452 },
++ { .center_freq = 2457 },
++ { .center_freq = 2462 },
++ { .center_freq = 2467 },
++ { .center_freq = 2472 },
++ { .center_freq = 2484 },
++};
++
+ static void rtl8187_iowrite_async_cb(struct urb *urb)
+ {
+ kfree(urb->context);
+@@ -146,17 +178,23 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
+
+ flags = skb->len;
+ flags |= RTL8187_TX_FLAG_NO_ENCRYPT;
+- flags |= control->rts_cts_rate << 19;
+- flags |= control->tx_rate << 24;
++
++ BUG_ON(!control->tx_rate);
++
++ flags |= control->tx_rate->hw_value << 24;
+ if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb->data))
+ flags |= RTL8187_TX_FLAG_MORE_FRAG;
+ if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
++ BUG_ON(!control->rts_cts_rate);
+ flags |= RTL8187_TX_FLAG_RTS;
++ flags |= control->rts_cts_rate->hw_value << 19;
+ rts_dur = ieee80211_rts_duration(dev, priv->vif,
+ skb->len, control);
+- }
+- if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
++ } else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
++ BUG_ON(!control->rts_cts_rate);
+ flags |= RTL8187_TX_FLAG_CTS;
++ flags |= control->rts_cts_rate->hw_value << 19;
++ }
+
+ hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr));
+ hdr->flags = cpu_to_le32(flags);
+@@ -225,10 +263,9 @@ static void rtl8187_rx_cb(struct urb *urb)
+ rx_status.antenna = (hdr->signal >> 7) & 1;
+ rx_status.signal = 64 - min(hdr->noise, (u8)64);
+ rx_status.ssi = signal;
+- rx_status.rate = rate;
+- rx_status.freq = dev->conf.freq;
+- rx_status.channel = dev->conf.channel;
+- rx_status.phymode = dev->conf.phymode;
++ rx_status.rate_idx = rate;
++ rx_status.freq = dev->conf.channel->center_freq;
++ rx_status.band = dev->conf.channel->band;
+ rx_status.mactime = le64_to_cpu(hdr->mac_time);
+ rx_status.flag |= RX_FLAG_TSFT;
+ if (flags & (1 << 13))
+@@ -685,19 +722,22 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
+ usb_get_dev(udev);
+
+ skb_queue_head_init(&priv->rx_queue);
++
++ BUILD_BUG_ON(sizeof(priv->channels) != sizeof(rtl818x_channels));
++ BUILD_BUG_ON(sizeof(priv->rates) != sizeof(rtl818x_rates));
++
+ memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels));
+ memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates));
+ priv->map = (struct rtl818x_csr *)0xFF00;
+- priv->modes[0].mode = MODE_IEEE80211G;
+- priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates);
+- priv->modes[0].rates = priv->rates;
+- priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels);
+- priv->modes[0].channels = priv->channels;
+- priv->modes[1].mode = MODE_IEEE80211B;
+- priv->modes[1].num_rates = 4;
+- priv->modes[1].rates = priv->rates;
+- priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels);
+- priv->modes[1].channels = priv->channels;
++
++ priv->band.band = IEEE80211_BAND_2GHZ;
++ priv->band.channels = priv->channels;
++ priv->band.n_channels = ARRAY_SIZE(rtl818x_channels);
++ priv->band.bitrates = priv->rates;
++ priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates);
++ dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
++
++
+ priv->mode = IEEE80211_IF_TYPE_MNTR;
+ dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+ IEEE80211_HW_RX_INCLUDES_FCS;
+@@ -706,10 +746,6 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
+ dev->max_rssi = 65;
+ dev->max_signal = 64;
+
+- for (i = 0; i < 2; i++)
+- if ((err = ieee80211_register_hwmode(dev, &priv->modes[i])))
+- goto err_free_dev;
+-
+ eeprom.data = dev;
+ eeprom.register_read = rtl8187_eeprom_register_read;
+ eeprom.register_write = rtl8187_eeprom_register_write;
+@@ -733,20 +769,20 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
+ for (i = 0; i < 3; i++) {
+ eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_1 + i,
+ &txpwr);
+- (*channel++).val = txpwr & 0xFF;
+- (*channel++).val = txpwr >> 8;
++ (*channel++).hw_value = txpwr & 0xFF;
++ (*channel++).hw_value = txpwr >> 8;
+ }
+ for (i = 0; i < 2; i++) {
+ eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_4 + i,
+ &txpwr);
+- (*channel++).val = txpwr & 0xFF;
+- (*channel++).val = txpwr >> 8;
++ (*channel++).hw_value = txpwr & 0xFF;
++ (*channel++).hw_value = txpwr >> 8;
+ }
+ for (i = 0; i < 2; i++) {
+ eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6 + i,
+ &txpwr);
+- (*channel++).val = txpwr & 0xFF;
+- (*channel++).val = txpwr >> 8;
++ (*channel++).hw_value = txpwr & 0xFF;
++ (*channel++).hw_value = txpwr >> 8;
+ }
+
+ eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_BASE,
+diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c
+index b713de1..9146387 100644
+--- a/drivers/net/wireless/rtl8187_rtl8225.c
++++ b/drivers/net/wireless/rtl8187_rtl8225.c
+@@ -283,8 +283,8 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
+ u32 reg;
+ int i;
+
+- cck_power = priv->channels[channel - 1].val & 0xF;
+- ofdm_power = priv->channels[channel - 1].val >> 4;
++ cck_power = priv->channels[channel - 1].hw_value & 0xF;
++ ofdm_power = priv->channels[channel - 1].hw_value >> 4;
+
+ cck_power = min(cck_power, (u8)11);
+ ofdm_power = min(ofdm_power, (u8)35);
+@@ -500,8 +500,8 @@ static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
+ u32 reg;
+ int i;
+
+- cck_power = priv->channels[channel - 1].val & 0xF;
+- ofdm_power = priv->channels[channel - 1].val >> 4;
++ cck_power = priv->channels[channel - 1].hw_value & 0xF;
++ ofdm_power = priv->channels[channel - 1].hw_value >> 4;
+
+ cck_power = min(cck_power, (u8)15);
+ cck_power += priv->txpwr_base & 0xF;
+@@ -735,13 +735,14 @@ static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
+ struct ieee80211_conf *conf)
+ {
+ struct rtl8187_priv *priv = dev->priv;
++ int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
+
+ if (priv->rf->init == rtl8225_rf_init)
+- rtl8225_rf_set_tx_power(dev, conf->channel);
++ rtl8225_rf_set_tx_power(dev, chan);
+ else
+- rtl8225z2_rf_set_tx_power(dev, conf->channel);
++ rtl8225z2_rf_set_tx_power(dev, chan);
+
+- rtl8225_write(dev, 0x7, rtl8225_chan[conf->channel - 1]);
++ rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
+ msleep(10);
+ }
+
+diff --git a/drivers/net/wireless/rtl818x.h b/drivers/net/wireless/rtl818x.h
+index 1e7d6f8..4f7d38f 100644
+--- a/drivers/net/wireless/rtl818x.h
++++ b/drivers/net/wireless/rtl818x.h
+@@ -175,74 +175,4 @@ struct rtl818x_rf_ops {
+ void (*set_chan)(struct ieee80211_hw *, struct ieee80211_conf *);
+ };
+
+-static const struct ieee80211_rate rtl818x_rates[] = {
+- { .rate = 10,
+- .val = 0,
+- .flags = IEEE80211_RATE_CCK },
+- { .rate = 20,
+- .val = 1,
+- .flags = IEEE80211_RATE_CCK },
+- { .rate = 55,
+- .val = 2,
+- .flags = IEEE80211_RATE_CCK },
+- { .rate = 110,
+- .val = 3,
+- .flags = IEEE80211_RATE_CCK },
+- { .rate = 60,
+- .val = 4,
+- .flags = IEEE80211_RATE_OFDM },
+- { .rate = 90,
+- .val = 5,
+- .flags = IEEE80211_RATE_OFDM },
+- { .rate = 120,
+- .val = 6,
+- .flags = IEEE80211_RATE_OFDM },
+- { .rate = 180,
+- .val = 7,
+- .flags = IEEE80211_RATE_OFDM },
+- { .rate = 240,
+- .val = 8,
+- .flags = IEEE80211_RATE_OFDM },
+- { .rate = 360,
+- .val = 9,
+- .flags = IEEE80211_RATE_OFDM },
+- { .rate = 480,
+- .val = 10,
+- .flags = IEEE80211_RATE_OFDM },
+- { .rate = 540,
+- .val = 11,
+- .flags = IEEE80211_RATE_OFDM },
+-};
+-
+-static const struct ieee80211_channel rtl818x_channels[] = {
+- { .chan = 1,
+- .freq = 2412},
+- { .chan = 2,
+- .freq = 2417},
+- { .chan = 3,
+- .freq = 2422},
+- { .chan = 4,
+- .freq = 2427},
+- { .chan = 5,
+- .freq = 2432},
+- { .chan = 6,
+- .freq = 2437},
+- { .chan = 7,
+- .freq = 2442},
+- { .chan = 8,
+- .freq = 2447},
+- { .chan = 9,
+- .freq = 2452},
+- { .chan = 10,
+- .freq = 2457},
+- { .chan = 11,
+- .freq = 2462},
+- { .chan = 12,
+- .freq = 2467},
+- { .chan = 13,
+- .freq = 2472},
+- { .chan = 14,
+- .freq = 2484}
+-};
+-
+ #endif /* RTL818X_H */
+diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
+index 88efe1b..bced3fe 100644
+--- a/drivers/net/wireless/strip.c
++++ b/drivers/net/wireless/strip.c
+@@ -962,12 +962,12 @@ static char *time_delta(char buffer[], long time)
+ /* get Nth element of the linked list */
+ static struct strip *strip_get_idx(loff_t pos)
+ {
+- struct list_head *l;
++ struct strip *str;
+ int i = 0;
+
+- list_for_each_rcu(l, &strip_list) {
++ list_for_each_entry_rcu(str, &strip_list, list) {
+ if (pos == i)
+- return list_entry(l, struct strip, list);
++ return str;
+ ++i;
+ }
+ return NULL;
+diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
+index 06eea6a..baf7401 100644
+--- a/drivers/net/wireless/wavelan_cs.c
++++ b/drivers/net/wireless/wavelan_cs.c
+@@ -102,7 +102,7 @@ hacr_write(u_long base,
+ * Write to card's Host Adapter Command Register. Include a delay for
+ * those times when it is needed.
+ */
+-static inline void
++static void
+ hacr_write_slow(u_long base,
+ u_char hacr)
+ {
+@@ -255,7 +255,7 @@ update_psa_checksum(struct net_device * dev)
+ /*
+ * Write 1 byte to the MMC.
+ */
+-static inline void
++static void
+ mmc_out(u_long base,
+ u_short o,
+ u_char d)
+@@ -275,7 +275,7 @@ mmc_out(u_long base,
+ * Routine to write bytes to the Modem Management Controller.
+ * We start by the end because it is the way it should be !
+ */
+-static inline void
++static void
+ mmc_write(u_long base,
+ u_char o,
+ u_char * b,
+@@ -293,7 +293,7 @@ mmc_write(u_long base,
+ * Read 1 byte from the MMC.
+ * Optimised version for 1 byte, avoid using memory...
+ */
+-static inline u_char
++static u_char
+ mmc_in(u_long base,
+ u_short o)
+ {
+@@ -318,7 +318,7 @@ mmc_in(u_long base,
+ * (code has just been moved in the above function)
+ * We start by the end because it is the way it should be !
+ */
+-static inline void
++static void
+ mmc_read(u_long base,
+ u_char o,
+ u_char * b,
+@@ -350,9 +350,8 @@ mmc_encr(u_long base) /* i/o port of the card */
+ /*------------------------------------------------------------------*/
+ /*
+ * Wait for the frequency EEprom to complete a command...
+- * I hope this one will be optimally inlined...
+ */
+-static inline void
++static void
+ fee_wait(u_long base, /* i/o port of the card */
+ int delay, /* Base delay to wait for */
+ int number) /* Number of time to wait */
+@@ -738,9 +737,9 @@ static void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp)
+ }
+
+ /* Called when a WavePoint beacon is received */
+-static inline void wl_roam_gather(struct net_device * dev,
+- u_char * hdr, /* Beacon header */
+- u_char * stats) /* SNR, Signal quality
++static void wl_roam_gather(struct net_device * dev,
++ u_char * hdr, /* Beacon header */
++ u_char * stats) /* SNR, Signal quality
+ of packet */
+ {
+ wavepoint_beacon *beacon= (wavepoint_beacon *)hdr; /* Rcvd. Beacon */
+@@ -794,7 +793,7 @@ out:
+ static inline int WAVELAN_BEACON(unsigned char *data)
+ {
+ wavepoint_beacon *beacon= (wavepoint_beacon *)data;
+- static wavepoint_beacon beacon_template={0xaa,0xaa,0x03,0x08,0x00,0x0e,0x20,0x03,0x00};
++ static const wavepoint_beacon beacon_template={0xaa,0xaa,0x03,0x08,0x00,0x0e,0x20,0x03,0x00};
+
+ if(memcmp(beacon,&beacon_template,9)==0)
+ return 1;
+@@ -980,7 +979,7 @@ read_ringbuf(struct net_device * dev,
+ * wavelan_interrupt is not an option...), so you may experience
+ * some delay sometime...
+ */
+-static inline void
++static void
+ wv_82593_reconfig(struct net_device * dev)
+ {
+ net_local * lp = netdev_priv(dev);
+@@ -1233,7 +1232,7 @@ wv_local_show(struct net_device * dev)
+ /*
+ * Dump packet header (and content if necessary) on the screen
+ */
+-static inline void
++static void
+ wv_packet_info(u_char * p, /* Packet to dump */
+ int length, /* Length of the packet */
+ char * msg1, /* Name of the device */
+@@ -1272,7 +1271,7 @@ wv_packet_info(u_char * p, /* Packet to dump */
+ * This is the information which is displayed by the driver at startup
+ * There is a lot of flag to configure it at your will...
+ */
+-static inline void
++static void
+ wv_init_info(struct net_device * dev)
+ {
+ unsigned int base = dev->base_addr;
+@@ -1509,7 +1508,7 @@ wavelan_set_mac_address(struct net_device * dev,
+ * Frequency setting (for hardware able of it)
+ * It's a bit complicated and you don't really want to look into it...
+ */
+-static inline int
++static int
+ wv_set_frequency(u_long base, /* i/o port of the card */
+ iw_freq * frequency)
+ {
+@@ -1706,7 +1705,7 @@ wv_set_frequency(u_long base, /* i/o port of the card */
+ /*
+ * Give the list of available frequencies
+ */
+-static inline int
++static int
+ wv_frequency_list(u_long base, /* i/o port of the card */
+ iw_freq * list, /* List of frequency to fill */
+ int max) /* Maximum number of frequencies */
+@@ -2759,7 +2758,7 @@ wavelan_get_wireless_stats(struct net_device * dev)
+ * frame pointer and verify that the frame seem correct
+ * (called by wv_packet_rcv())
+ */
+-static inline int
++static int
+ wv_start_of_frame(struct net_device * dev,
+ int rfp, /* end of frame */
+ int wrap) /* start of buffer */
+@@ -2821,7 +2820,7 @@ wv_start_of_frame(struct net_device * dev,
+ * Note: if any errors occur, the packet is "dropped on the floor"
+ * (called by wv_packet_rcv())
+ */
+-static inline void
++static void
+ wv_packet_read(struct net_device * dev,
+ int fd_p,
+ int sksize)
+@@ -2922,7 +2921,7 @@ wv_packet_read(struct net_device * dev,
+ * (called by wavelan_interrupt())
+ * Note : the spinlock is already grabbed for us and irq are disabled.
+ */
+-static inline void
++static void
+ wv_packet_rcv(struct net_device * dev)
+ {
+ unsigned int base = dev->base_addr;
+@@ -3056,7 +3055,7 @@ wv_packet_rcv(struct net_device * dev)
+ * the transmit.
+ * (called in wavelan_packet_xmit())
+ */
+-static inline void
++static void
+ wv_packet_write(struct net_device * dev,
+ void * buf,
+ short length)
+@@ -3180,7 +3179,7 @@ wavelan_packet_xmit(struct sk_buff * skb,
+ * Routine to initialize the Modem Management Controller.
+ * (called by wv_hw_config())
+ */
+-static inline int
++static int
+ wv_mmc_init(struct net_device * dev)
+ {
+ unsigned int base = dev->base_addr;
+@@ -3699,7 +3698,7 @@ wv_82593_config(struct net_device * dev)
+ * wavelan.
+ * (called by wv_config())
+ */
+-static inline int
++static int
+ wv_pcmcia_reset(struct net_device * dev)
+ {
+ int i;
+@@ -3864,7 +3863,7 @@ wv_hw_config(struct net_device * dev)
+ * 2. Start the LAN controller's receive unit
+ * (called by wavelan_event(), wavelan_watchdog() and wavelan_open())
+ */
+-static inline void
++static void
+ wv_hw_reset(struct net_device * dev)
+ {
+ net_local * lp = netdev_priv(dev);
+@@ -3895,7 +3894,7 @@ wv_hw_reset(struct net_device * dev)
+ * device available to the system.
+ * (called by wavelan_event())
+ */
+-static inline int
++static int
+ wv_pcmcia_config(struct pcmcia_device * link)
+ {
+ struct net_device * dev = (struct net_device *) link->priv;
+diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h
+index 33dd970..628192d 100644
+--- a/drivers/net/wireless/wavelan_cs.p.h
++++ b/drivers/net/wireless/wavelan_cs.p.h
+@@ -637,7 +637,7 @@ struct net_local
+ /* ----------------- MODEM MANAGEMENT SUBROUTINES ----------------- */
+ static inline u_char /* data */
+ hasr_read(u_long); /* Read the host interface : base address */
+-static inline void
++static void
+ hacr_write(u_long, /* Write to host interface : base address */
+ u_char), /* data */
+ hacr_write_slow(u_long,
+@@ -651,7 +651,7 @@ static void
+ int, /* Offset in psa */
+ u_char *, /* Buffer in memory */
+ int); /* Length of buffer */
+-static inline void
++static void
+ mmc_out(u_long, /* Write 1 byte to the Modem Manag Control */
+ u_short,
+ u_char),
+@@ -659,10 +659,10 @@ static inline void
+ u_char,
+ u_char *,
+ int);
+-static inline u_char /* Read 1 byte from the MMC */
++static u_char /* Read 1 byte from the MMC */
+ mmc_in(u_long,
+ u_short);
+-static inline void
++static void
+ mmc_read(u_long, /* Read n bytes from the MMC */
+ u_char,
+ u_char *,
+@@ -688,10 +688,10 @@ static int
+ int,
+ char *,
+ int);
+-static inline void
++static void
+ wv_82593_reconfig(struct net_device *); /* Reconfigure the controller */
+ /* ------------------- DEBUG & INFO SUBROUTINES ------------------- */
+-static inline void
++static void
+ wv_init_info(struct net_device *); /* display startup info */
+ /* ------------------- IOCTL, STATS & RECONFIG ------------------- */
+ static en_stats *
+@@ -699,17 +699,17 @@ static en_stats *
+ static iw_stats *
+ wavelan_get_wireless_stats(struct net_device *);
+ /* ----------------------- PACKET RECEPTION ----------------------- */
+-static inline int
++static int
+ wv_start_of_frame(struct net_device *, /* Seek beggining of current frame */
+ int, /* end of frame */
+ int); /* start of buffer */
+-static inline void
++static void
+ wv_packet_read(struct net_device *, /* Read a packet from a frame */
+ int,
+ int),
+ wv_packet_rcv(struct net_device *); /* Read all packets waiting */
+ /* --------------------- PACKET TRANSMISSION --------------------- */
+-static inline void
++static void
+ wv_packet_write(struct net_device *, /* Write a packet to the Tx buffer */
+ void *,
+ short);
+@@ -717,20 +717,20 @@ static int
+ wavelan_packet_xmit(struct sk_buff *, /* Send a packet */
+ struct net_device *);
+ /* -------------------- HARDWARE CONFIGURATION -------------------- */
+-static inline int
++static int
+ wv_mmc_init(struct net_device *); /* Initialize the modem */
+ static int
+ wv_ru_stop(struct net_device *), /* Stop the i82593 receiver unit */
+ wv_ru_start(struct net_device *); /* Start the i82593 receiver unit */
+ static int
+ wv_82593_config(struct net_device *); /* Configure the i82593 */
+-static inline int
++static int
+ wv_pcmcia_reset(struct net_device *); /* Reset the pcmcia interface */
+ static int
+ wv_hw_config(struct net_device *); /* Reset & configure the whole hardware */
+-static inline void
++static void
+ wv_hw_reset(struct net_device *); /* Same, + start receiver unit */
+-static inline int
++static int
+ wv_pcmcia_config(struct pcmcia_device *); /* Configure the pcmcia interface */
+ static void
+ wv_pcmcia_release(struct pcmcia_device *);/* Remove a device */
+diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
+index 99e5b03..0acb5c3 100644
+--- a/drivers/net/wireless/zd1211rw/zd_chip.c
++++ b/drivers/net/wireless/zd1211rw/zd_chip.c
+@@ -771,10 +771,10 @@ static int zd1211b_hw_init_hmac(struct zd_chip *chip)
+ {
+ static const struct zd_ioreq32 ioreqs[] = {
+ { CR_ZD1211B_RETRY_MAX, 0x02020202 },
+- { CR_ZD1211B_TX_PWR_CTL4, 0x007f003f },
+- { CR_ZD1211B_TX_PWR_CTL3, 0x007f003f },
+- { CR_ZD1211B_TX_PWR_CTL2, 0x003f001f },
+- { CR_ZD1211B_TX_PWR_CTL1, 0x001f000f },
++ { CR_ZD1211B_CWIN_MAX_MIN_AC0, 0x007f003f },
++ { CR_ZD1211B_CWIN_MAX_MIN_AC1, 0x007f003f },
++ { CR_ZD1211B_CWIN_MAX_MIN_AC2, 0x003f001f },
++ { CR_ZD1211B_CWIN_MAX_MIN_AC3, 0x001f000f },
+ { CR_ZD1211B_AIFS_CTL1, 0x00280028 },
+ { CR_ZD1211B_AIFS_CTL2, 0x008C003C },
+ { CR_ZD1211B_TXOP, 0x01800824 },
+@@ -809,6 +809,7 @@ static int hw_init_hmac(struct zd_chip *chip)
+ { CR_AFTER_PNP, 0x1 },
+ { CR_WEP_PROTECT, 0x114 },
+ { CR_IFS_VALUE, IFS_VALUE_DEFAULT },
++ { CR_CAM_MODE, MODE_AP_WDS},
+ };
+
+ ZD_ASSERT(mutex_is_locked(&chip->mutex));
+@@ -986,7 +987,7 @@ static int print_fw_version(struct zd_chip *chip)
+ return 0;
+ }
+
+-static int set_mandatory_rates(struct zd_chip *chip, int mode)
++static int set_mandatory_rates(struct zd_chip *chip, int gmode)
+ {
+ u32 rates;
+ ZD_ASSERT(mutex_is_locked(&chip->mutex));
+@@ -994,17 +995,12 @@ static int set_mandatory_rates(struct zd_chip *chip, int mode)
+ * that the device is supporting. Until further notice we should try
+ * to support 802.11g also for full speed USB.
+ */
+- switch (mode) {
+- case MODE_IEEE80211B:
++ if (!gmode)
+ rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M;
+- break;
+- case MODE_IEEE80211G:
++ else
+ rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M|
+ CR_RATE_6M|CR_RATE_12M|CR_RATE_24M;
+- break;
+- default:
+- return -EINVAL;
+- }
++
+ return zd_iowrite32_locked(chip, rates, CR_MANDATORY_RATE_TBL);
+ }
+
+@@ -1108,7 +1104,7 @@ int zd_chip_init_hw(struct zd_chip *chip)
+ * It might be discussed, whether we should suppport pure b mode for
+ * full speed USB.
+ */
+- r = set_mandatory_rates(chip, MODE_IEEE80211G);
++ r = set_mandatory_rates(chip, 1);
+ if (r)
+ goto out;
+ /* Disabling interrupts is certainly a smart thing here.
+diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
+index 009c037..f8c061a 100644
+--- a/drivers/net/wireless/zd1211rw/zd_chip.h
++++ b/drivers/net/wireless/zd1211rw/zd_chip.h
+@@ -489,6 +489,7 @@ enum {
+
+ #define CR_RX_OFFSET CTL_REG(0x065c)
+
++#define CR_BCN_LENGTH CTL_REG(0x0664)
+ #define CR_PHY_DELAY CTL_REG(0x066C)
+ #define CR_BCN_FIFO CTL_REG(0x0670)
+ #define CR_SNIFFER_ON CTL_REG(0x0674)
+@@ -545,6 +546,8 @@ enum {
+ #define RX_FILTER_CTRL (RX_FILTER_RTS | RX_FILTER_CTS | \
+ RX_FILTER_CFEND | RX_FILTER_CFACK)
+
++#define BCN_MODE_IBSS 0x2000000
++
+ /* Monitor mode sets filter to 0xfffff */
+
+ #define CR_ACK_TIMEOUT_EXT CTL_REG(0x0690)
+@@ -578,6 +581,11 @@ enum {
+
+ /* CAM: Continuous Access Mode (power management) */
+ #define CR_CAM_MODE CTL_REG(0x0700)
++#define MODE_IBSS 0x0
++#define MODE_AP 0x1
++#define MODE_STA 0x2
++#define MODE_AP_WDS 0x3
++
+ #define CR_CAM_ROLL_TB_LOW CTL_REG(0x0704)
+ #define CR_CAM_ROLL_TB_HIGH CTL_REG(0x0708)
+ #define CR_CAM_ADDRESS CTL_REG(0x070C)
+@@ -625,11 +633,10 @@ enum {
+ #define CR_S_MD CTL_REG(0x0830)
+
+ #define CR_USB_DEBUG_PORT CTL_REG(0x0888)
+-
+-#define CR_ZD1211B_TX_PWR_CTL1 CTL_REG(0x0b00)
+-#define CR_ZD1211B_TX_PWR_CTL2 CTL_REG(0x0b04)
+-#define CR_ZD1211B_TX_PWR_CTL3 CTL_REG(0x0b08)
+-#define CR_ZD1211B_TX_PWR_CTL4 CTL_REG(0x0b0c)
++#define CR_ZD1211B_CWIN_MAX_MIN_AC0 CTL_REG(0x0b00)
++#define CR_ZD1211B_CWIN_MAX_MIN_AC1 CTL_REG(0x0b04)
++#define CR_ZD1211B_CWIN_MAX_MIN_AC2 CTL_REG(0x0b08)
++#define CR_ZD1211B_CWIN_MAX_MIN_AC3 CTL_REG(0x0b0c)
+ #define CR_ZD1211B_AIFS_CTL1 CTL_REG(0x0b10)
+ #define CR_ZD1211B_AIFS_CTL2 CTL_REG(0x0b14)
+ #define CR_ZD1211B_TXOP CTL_REG(0x0b20)
+diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.c b/drivers/net/wireless/zd1211rw/zd_ieee80211.c
+index 7c277ec..d8dc41e 100644
+--- a/drivers/net/wireless/zd1211rw/zd_ieee80211.c
++++ b/drivers/net/wireless/zd1211rw/zd_ieee80211.c
+@@ -65,16 +65,14 @@ static const struct channel_range *zd_channel_range(u8 regdomain)
+
+ static void unmask_bg_channels(struct ieee80211_hw *hw,
+ const struct channel_range *range,
+- struct ieee80211_hw_mode *mode)
++ struct ieee80211_supported_band *sband)
+ {
+ u8 channel;
+
+ for (channel = range->start; channel < range->end; channel++) {
+ struct ieee80211_channel *chan =
+- &mode->channels[CHAN_TO_IDX(channel)];
+- chan->flag |= IEEE80211_CHAN_W_SCAN |
+- IEEE80211_CHAN_W_ACTIVE_SCAN |
+- IEEE80211_CHAN_W_IBSS;
++ &sband->channels[CHAN_TO_IDX(channel)];
++ chan->flags = 0;
+ }
+ }
+
+@@ -97,7 +95,6 @@ void zd_geo_init(struct ieee80211_hw *hw, u8 regdomain)
+ range = zd_channel_range(ZD_REGDOMAIN_FCC);
+ }
+
+- unmask_bg_channels(hw, range, &mac->modes[0]);
+- unmask_bg_channels(hw, range, &mac->modes[1]);
++ unmask_bg_channels(hw, range, &mac->band);
+ }
+
+diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
+index 76ef2d8..69c45ca 100644
+--- a/drivers/net/wireless/zd1211rw/zd_mac.c
++++ b/drivers/net/wireless/zd1211rw/zd_mac.c
+@@ -34,76 +34,61 @@
+
+ /* This table contains the hardware specific values for the modulation rates. */
+ static const struct ieee80211_rate zd_rates[] = {
+- { .rate = 10,
+- .val = ZD_CCK_RATE_1M,
+- .flags = IEEE80211_RATE_CCK },
+- { .rate = 20,
+- .val = ZD_CCK_RATE_2M,
+- .val2 = ZD_CCK_RATE_2M | ZD_CCK_PREA_SHORT,
+- .flags = IEEE80211_RATE_CCK_2 },
+- { .rate = 55,
+- .val = ZD_CCK_RATE_5_5M,
+- .val2 = ZD_CCK_RATE_5_5M | ZD_CCK_PREA_SHORT,
+- .flags = IEEE80211_RATE_CCK_2 },
+- { .rate = 110,
+- .val = ZD_CCK_RATE_11M,
+- .val2 = ZD_CCK_RATE_11M | ZD_CCK_PREA_SHORT,
+- .flags = IEEE80211_RATE_CCK_2 },
+- { .rate = 60,
+- .val = ZD_OFDM_RATE_6M,
+- .flags = IEEE80211_RATE_OFDM },
+- { .rate = 90,
+- .val = ZD_OFDM_RATE_9M,
+- .flags = IEEE80211_RATE_OFDM },
+- { .rate = 120,
+- .val = ZD_OFDM_RATE_12M,
+- .flags = IEEE80211_RATE_OFDM },
+- { .rate = 180,
+- .val = ZD_OFDM_RATE_18M,
+- .flags = IEEE80211_RATE_OFDM },
+- { .rate = 240,
+- .val = ZD_OFDM_RATE_24M,
+- .flags = IEEE80211_RATE_OFDM },
+- { .rate = 360,
+- .val = ZD_OFDM_RATE_36M,
+- .flags = IEEE80211_RATE_OFDM },
+- { .rate = 480,
+- .val = ZD_OFDM_RATE_48M,
+- .flags = IEEE80211_RATE_OFDM },
+- { .rate = 540,
+- .val = ZD_OFDM_RATE_54M,
+- .flags = IEEE80211_RATE_OFDM },
++ { .bitrate = 10,
++ .hw_value = ZD_CCK_RATE_1M, },
++ { .bitrate = 20,
++ .hw_value = ZD_CCK_RATE_2M,
++ .hw_value_short = ZD_CCK_RATE_2M | ZD_CCK_PREA_SHORT,
++ .flags = IEEE80211_RATE_SHORT_PREAMBLE },
++ { .bitrate = 55,
++ .hw_value = ZD_CCK_RATE_5_5M,
++ .hw_value_short = ZD_CCK_RATE_5_5M | ZD_CCK_PREA_SHORT,
++ .flags = IEEE80211_RATE_SHORT_PREAMBLE },
++ { .bitrate = 110,
++ .hw_value = ZD_CCK_RATE_11M,
++ .hw_value_short = ZD_CCK_RATE_11M | ZD_CCK_PREA_SHORT,
++ .flags = IEEE80211_RATE_SHORT_PREAMBLE },
++ { .bitrate = 60,
++ .hw_value = ZD_OFDM_RATE_6M,
++ .flags = 0 },
++ { .bitrate = 90,
++ .hw_value = ZD_OFDM_RATE_9M,
++ .flags = 0 },
++ { .bitrate = 120,
++ .hw_value = ZD_OFDM_RATE_12M,
++ .flags = 0 },
++ { .bitrate = 180,
++ .hw_value = ZD_OFDM_RATE_18M,
++ .flags = 0 },
++ { .bitrate = 240,
++ .hw_value = ZD_OFDM_RATE_24M,
++ .flags = 0 },
++ { .bitrate = 360,
++ .hw_value = ZD_OFDM_RATE_36M,
++ .flags = 0 },
++ { .bitrate = 480,
++ .hw_value = ZD_OFDM_RATE_48M,
++ .flags = 0 },
++ { .bitrate = 540,
++ .hw_value = ZD_OFDM_RATE_54M,
++ .flags = 0 },
+ };
+
+ static const struct ieee80211_channel zd_channels[] = {
+- { .chan = 1,
+- .freq = 2412},
+- { .chan = 2,
+- .freq = 2417},
+- { .chan = 3,
+- .freq = 2422},
+- { .chan = 4,
+- .freq = 2427},
+- { .chan = 5,
+- .freq = 2432},
+- { .chan = 6,
+- .freq = 2437},
+- { .chan = 7,
+- .freq = 2442},
+- { .chan = 8,
+- .freq = 2447},
+- { .chan = 9,
+- .freq = 2452},
+- { .chan = 10,
+- .freq = 2457},
+- { .chan = 11,
+- .freq = 2462},
+- { .chan = 12,
+- .freq = 2467},
+- { .chan = 13,
+- .freq = 2472},
+- { .chan = 14,
+- .freq = 2484}
++ { .center_freq = 2412, .hw_value = 1 },
++ { .center_freq = 2417, .hw_value = 2 },
++ { .center_freq = 2422, .hw_value = 3 },
++ { .center_freq = 2427, .hw_value = 4 },
++ { .center_freq = 2432, .hw_value = 5 },
++ { .center_freq = 2437, .hw_value = 6 },
++ { .center_freq = 2442, .hw_value = 7 },
++ { .center_freq = 2447, .hw_value = 8 },
++ { .center_freq = 2452, .hw_value = 9 },
++ { .center_freq = 2457, .hw_value = 10 },
++ { .center_freq = 2462, .hw_value = 11 },
++ { .center_freq = 2467, .hw_value = 12 },
++ { .center_freq = 2472, .hw_value = 13 },
++ { .center_freq = 2484, .hw_value = 14 },
+ };
+
+ static void housekeeping_init(struct zd_mac *mac);
+@@ -490,6 +475,46 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
+ /* FIXME: Management frame? */
+ }
+
++void zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
++{
++ struct zd_mac *mac = zd_hw_mac(hw);
++ u32 tmp, j = 0;
++ /* 4 more bytes for tail CRC */
++ u32 full_len = beacon->len + 4;
++ zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 0);
++ zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
++ while (tmp & 0x2) {
++ zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
++ if ((++j % 100) == 0) {
++ printk(KERN_ERR "CR_BCN_FIFO_SEMAPHORE not ready\n");
++ if (j >= 500) {
++ printk(KERN_ERR "Giving up beacon config.\n");
++ return;
++ }
++ }
++ msleep(1);
++ }
++
++ zd_iowrite32(&mac->chip, CR_BCN_FIFO, full_len - 1);
++ if (zd_chip_is_zd1211b(&mac->chip))
++ zd_iowrite32(&mac->chip, CR_BCN_LENGTH, full_len - 1);
++
++ for (j = 0 ; j < beacon->len; j++)
++ zd_iowrite32(&mac->chip, CR_BCN_FIFO,
++ *((u8 *)(beacon->data + j)));
++
++ for (j = 0; j < 4; j++)
++ zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0);
++
++ zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 1);
++ /* 802.11b/g 2.4G CCK 1Mb
++ * 802.11a, not yet implemented, uses different values (see GPL vendor
++ * driver)
++ */
++ zd_iowrite32(&mac->chip, CR_BCN_PLCP_CFG, 0x00000400 |
++ (full_len << 19));
++}
++
+ static int fill_ctrlset(struct zd_mac *mac,
+ struct sk_buff *skb,
+ struct ieee80211_tx_control *control)
+@@ -503,7 +528,9 @@ static int fill_ctrlset(struct zd_mac *mac,
+
+ ZD_ASSERT(frag_len <= 0xffff);
+
+- cs->modulation = control->tx_rate;
++ cs->modulation = control->tx_rate->hw_value;
++ if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE)
++ cs->modulation = control->tx_rate->hw_value_short;
+
+ cs->tx_length = cpu_to_le16(frag_len);
+
+@@ -631,6 +658,8 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
+ int bad_frame = 0;
+ u16 fc;
+ bool is_qos, is_4addr, need_padding;
++ int i;
++ u8 rate;
+
+ if (length < ZD_PLCP_HEADER_SIZE + 10 /* IEEE80211_1ADDR_LEN */ +
+ FCS_LEN + sizeof(struct rx_status))
+@@ -660,14 +689,19 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
+ }
+ }
+
+- stats.channel = _zd_chip_get_channel(&mac->chip);
+- stats.freq = zd_channels[stats.channel - 1].freq;
+- stats.phymode = MODE_IEEE80211G;
++ stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq;
++ stats.band = IEEE80211_BAND_2GHZ;
+ stats.ssi = status->signal_strength;
+ stats.signal = zd_rx_qual_percent(buffer,
+ length - sizeof(struct rx_status),
+ status);
+- stats.rate = zd_rx_rate(buffer, status);
++
++ rate = zd_rx_rate(buffer, status);
++
++ /* todo: return index in the big switches in zd_rx_rate instead */
++ for (i = 0; i < mac->band.n_bitrates; i++)
++ if (rate == mac->band.bitrates[i].hw_value)
++ stats.rate_idx = i;
+
+ length -= ZD_PLCP_HEADER_SIZE + sizeof(struct rx_status);
+ buffer += ZD_PLCP_HEADER_SIZE;
+@@ -715,6 +749,7 @@ static int zd_op_add_interface(struct ieee80211_hw *hw,
+
+ switch (conf->type) {
+ case IEEE80211_IF_TYPE_MNTR:
++ case IEEE80211_IF_TYPE_MESH_POINT:
+ case IEEE80211_IF_TYPE_STA:
+ mac->type = conf->type;
+ break;
+@@ -736,7 +771,7 @@ static void zd_op_remove_interface(struct ieee80211_hw *hw,
+ static int zd_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+ {
+ struct zd_mac *mac = zd_hw_mac(hw);
+- return zd_chip_set_channel(&mac->chip, conf->channel);
++ return zd_chip_set_channel(&mac->chip, conf->channel->hw_value);
+ }
+
+ static int zd_op_config_interface(struct ieee80211_hw *hw,
+@@ -744,15 +779,43 @@ static int zd_op_config_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_conf *conf)
+ {
+ struct zd_mac *mac = zd_hw_mac(hw);
++ int associated;
++
++ if (mac->type == IEEE80211_IF_TYPE_MESH_POINT) {
++ associated = true;
++ if (conf->beacon) {
++ zd_mac_config_beacon(hw, conf->beacon);
++ kfree_skb(conf->beacon);
++ zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS |
++ hw->conf.beacon_int);
++ }
++ } else
++ associated = is_valid_ether_addr(conf->bssid);
+
+ spin_lock_irq(&mac->lock);
+- mac->associated = is_valid_ether_addr(conf->bssid);
++ mac->associated = associated;
+ spin_unlock_irq(&mac->lock);
+
+ /* TODO: do hardware bssid filtering */
+ return 0;
+ }
+
++void zd_process_intr(struct work_struct *work)
++{
++ u16 int_status;
++ struct zd_mac *mac = container_of(work, struct zd_mac, process_intr);
++
++ int_status = le16_to_cpu(*(u16 *)(mac->intr_buffer+4));
++ if (int_status & INT_CFG_NEXT_BCN) {
++ if (net_ratelimit())
++ dev_dbg_f(zd_mac_dev(mac), "INT_CFG_NEXT_BCN\n");
++ } else
++ dev_dbg_f(zd_mac_dev(mac), "Unsupported interrupt\n");
++
++ zd_chip_enable_hwint(&mac->chip);
++}
++
++
+ static void set_multicast_hash_handler(struct work_struct *work)
+ {
+ struct zd_mac *mac =
+@@ -780,7 +843,7 @@ static void set_rx_filter_handler(struct work_struct *work)
+
+ #define SUPPORTED_FIF_FLAGS \
+ (FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | FIF_CONTROL | \
+- FIF_OTHER_BSS)
++ FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)
+ static void zd_op_configure_filter(struct ieee80211_hw *hw,
+ unsigned int changed_flags,
+ unsigned int *new_flags,
+@@ -894,7 +957,6 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
+ {
+ struct zd_mac *mac;
+ struct ieee80211_hw *hw;
+- int i;
+
+ hw = ieee80211_alloc_hw(sizeof(struct zd_mac), &zd_ops);
+ if (!hw) {
+@@ -912,19 +974,15 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
+
+ memcpy(mac->channels, zd_channels, sizeof(zd_channels));
+ memcpy(mac->rates, zd_rates, sizeof(zd_rates));
+- mac->modes[0].mode = MODE_IEEE80211G;
+- mac->modes[0].num_rates = ARRAY_SIZE(zd_rates);
+- mac->modes[0].rates = mac->rates;
+- mac->modes[0].num_channels = ARRAY_SIZE(zd_channels);
+- mac->modes[0].channels = mac->channels;
+- mac->modes[1].mode = MODE_IEEE80211B;
+- mac->modes[1].num_rates = 4;
+- mac->modes[1].rates = mac->rates;
+- mac->modes[1].num_channels = ARRAY_SIZE(zd_channels);
+- mac->modes[1].channels = mac->channels;
++ mac->band.n_bitrates = ARRAY_SIZE(zd_rates);
++ mac->band.bitrates = mac->rates;
++ mac->band.n_channels = ARRAY_SIZE(zd_channels);
++ mac->band.channels = mac->channels;
++
++ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band;
+
+ hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
+- IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED;
++ IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
+ hw->max_rssi = 100;
+ hw->max_signal = 100;
+
+@@ -933,19 +991,12 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
+
+ skb_queue_head_init(&mac->ack_wait_queue);
+
+- for (i = 0; i < 2; i++) {
+- if (ieee80211_register_hwmode(hw, &mac->modes[i])) {
+- dev_dbg_f(&intf->dev, "cannot register hwmode\n");
+- ieee80211_free_hw(hw);
+- return NULL;
+- }
+- }
+-
+ zd_chip_init(&mac->chip, hw, intf);
+ housekeeping_init(mac);
+ INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler);
+ INIT_WORK(&mac->set_rts_cts_work, set_rts_cts_work);
+ INIT_WORK(&mac->set_rx_filter_work, set_rx_filter_handler);
++ INIT_WORK(&mac->process_intr, zd_process_intr);
+
+ SET_IEEE80211_DEV(hw, &intf->dev);
+ return hw;
+diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
+index 2dde108..7117024 100644
+--- a/drivers/net/wireless/zd1211rw/zd_mac.h
++++ b/drivers/net/wireless/zd1211rw/zd_mac.h
+@@ -172,12 +172,15 @@ struct zd_tx_skb_control_block {
+ struct zd_mac {
+ struct zd_chip chip;
+ spinlock_t lock;
++ spinlock_t intr_lock;
+ struct ieee80211_hw *hw;
+ struct housekeeping housekeeping;
+ struct work_struct set_multicast_hash_work;
+ struct work_struct set_rts_cts_work;
+ struct work_struct set_rx_filter_work;
++ struct work_struct process_intr;
+ struct zd_mc_hash multicast_hash;
++ u8 intr_buffer[USB_MAX_EP_INT_BUFFER];
+ u8 regdomain;
+ u8 default_regdomain;
+ int type;
+@@ -185,7 +188,7 @@ struct zd_mac {
+ struct sk_buff_head ack_wait_queue;
+ struct ieee80211_channel channels[14];
+ struct ieee80211_rate rates[12];
+- struct ieee80211_hw_mode modes[2];
++ struct ieee80211_supported_band band;
+
+ /* Short preamble (used for RTS/CTS) */
+ unsigned int short_preamble:1;
+diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
+index 7942b15..e34675c 100644
+--- a/drivers/net/wireless/zd1211rw/zd_usb.c
++++ b/drivers/net/wireless/zd1211rw/zd_usb.c
+@@ -97,6 +97,7 @@ MODULE_DEVICE_TABLE(usb, usb_ids);
+ #define FW_ZD1211B_PREFIX "zd1211/zd1211b_"
+
+ /* USB device initialization */
++static void int_urb_complete(struct urb *urb);
+
+ static int request_fw_file(
+ const struct firmware **fw, const char *name, struct device *device)
+@@ -336,11 +337,18 @@ static inline void handle_regs_int(struct urb *urb)
+ struct zd_usb *usb = urb->context;
+ struct zd_usb_interrupt *intr = &usb->intr;
+ int len;
++ u16 int_num;
+
+ ZD_ASSERT(in_interrupt());
+ spin_lock(&intr->lock);
+
+- if (intr->read_regs_enabled) {
++ int_num = le16_to_cpu(*(u16 *)(urb->transfer_buffer+2));
++ if (int_num == CR_INTERRUPT) {
++ struct zd_mac *mac = zd_hw_mac(zd_usb_to_hw(urb->context));
++ memcpy(&mac->intr_buffer, urb->transfer_buffer,
++ USB_MAX_EP_INT_BUFFER);
++ schedule_work(&mac->process_intr);
++ } else if (intr->read_regs_enabled) {
+ intr->read_regs.length = len = urb->actual_length;
+
+ if (len > sizeof(intr->read_regs.buffer))
+@@ -351,7 +359,6 @@ static inline void handle_regs_int(struct urb *urb)
+ goto out;
+ }
+
+- dev_dbg_f(urb_dev(urb), "regs interrupt ignored\n");
+ out:
+ spin_unlock(&intr->lock);
+ }
+diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
+index 7483d45..e62018a 100644
+--- a/drivers/net/xen-netfront.c
++++ b/drivers/net/xen-netfront.c
+@@ -1809,3 +1809,5 @@ module_exit(netif_exit);
+
+ MODULE_DESCRIPTION("Xen virtual network device frontend");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("xen:vif");
++MODULE_ALIAS("xennet");
+diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
+index fe6ff3e..2464072 100644
+--- a/drivers/net/yellowfin.c
++++ b/drivers/net/yellowfin.c
+@@ -770,14 +770,14 @@ static void yellowfin_init_ring(struct net_device *dev)
+ /* Branch on Tx error. */
+ yp->tx_ring[j].dbdma_cmd = cpu_to_le32(CMD_STOP);
+ yp->tx_ring[j].branch_addr = cpu_to_le32(yp->tx_ring_dma +
+- (j+1)*sizeof(struct yellowfin_desc);
++ (j+1)*sizeof(struct yellowfin_desc));
+ j++;
+ if (yp->flags & FullTxStatus) {
+ yp->tx_ring[j].dbdma_cmd =
+ cpu_to_le32(CMD_TXSTATUS | sizeof(*yp->tx_status));
+ yp->tx_ring[j].request_cnt = sizeof(*yp->tx_status);
+ yp->tx_ring[j].addr = cpu_to_le32(yp->tx_status_dma +
+- i*sizeof(struct tx_status_words);
++ i*sizeof(struct tx_status_words));
+ } else {
+ /* Symbios chips write only tx_errs word. */
+ yp->tx_ring[j].dbdma_cmd =
+diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
+index c03072b..3a7a11a 100644
+--- a/drivers/of/Kconfig
++++ b/drivers/of/Kconfig
+@@ -1,3 +1,15 @@
+ config OF_DEVICE
+ def_bool y
+ depends on OF && (SPARC || PPC_OF)
++
++config OF_GPIO
++ def_bool y
++ depends on OF && PPC_OF && HAVE_GPIO_LIB
++ help
++ OpenFirmware GPIO accessors
++
++config OF_I2C
++ def_tristate I2C
++ depends on PPC_OF && I2C
++ help
++ OpenFirmware I2C accessors
+diff --git a/drivers/of/Makefile b/drivers/of/Makefile
+index ab9be5d..548772e 100644
+--- a/drivers/of/Makefile
++++ b/drivers/of/Makefile
+@@ -1,2 +1,4 @@
+ obj-y = base.o
+ obj-$(CONFIG_OF_DEVICE) += device.o platform.o
++obj-$(CONFIG_OF_GPIO) += gpio.o
++obj-$(CONFIG_OF_I2C) += of_i2c.o
+diff --git a/drivers/of/base.c b/drivers/of/base.c
+index 80c9dec..9bd7c4a 100644
+--- a/drivers/of/base.c
++++ b/drivers/of/base.c
+@@ -117,6 +117,32 @@ int of_device_is_compatible(const struct device_node *device,
+ EXPORT_SYMBOL(of_device_is_compatible);
+
+ /**
++ * of_device_is_available - check if a device is available for use
++ *
++ * @device: Node to check for availability
++ *
++ * Returns 1 if the status property is absent or set to "okay" or "ok",
++ * 0 otherwise
++ */
++int of_device_is_available(const struct device_node *device)
++{
++ const char *status;
++ int statlen;
++
++ status = of_get_property(device, "status", &statlen);
++ if (status == NULL)
++ return 1;
++
++ if (statlen > 0) {
++ if (!strcmp(status, "okay") || !strcmp(status, "ok"))
++ return 1;
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL(of_device_is_available);
++
++/**
+ * of_get_parent - Get a node's parent if any
+ * @node: Node to get parent
+ *
+diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c
+new file mode 100644
+index 0000000..000681e
+--- /dev/null
++++ b/drivers/of/gpio.c
+@@ -0,0 +1,242 @@
++/*
++ * OF helpers for the GPIO API
++ *
++ * Copyright (c) 2007-2008 MontaVista Software, Inc.
++ *
++ * Author: Anton Vorontsov <avorontsov at ru.mvista.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/kernel.h>
++#include <linux/errno.h>
++#include <linux/io.h>
++#include <linux/of.h>
++#include <linux/of_gpio.h>
++#include <asm/prom.h>
++
++/**
++ * of_get_gpio - Get a GPIO number from the device tree to use with GPIO API
++ * @np: device node to get GPIO from
++ * @index: index of the GPIO
++ *
++ * Returns GPIO number to use with Linux generic GPIO API, or one of the errno
++ * value on the error condition.
++ */
++int of_get_gpio(struct device_node *np, int index)
++{
++ int ret = -EINVAL;
++ struct device_node *gc;
++ struct of_gpio_chip *of_gc = NULL;
++ int size;
++ const u32 *gpios;
++ u32 nr_cells;
++ int i;
++ const void *gpio_spec;
++ const u32 *gpio_cells;
++ int gpio_index = 0;
++
++ gpios = of_get_property(np, "gpios", &size);
++ if (!gpios) {
++ ret = -ENOENT;
++ goto err0;
++ }
++ nr_cells = size / sizeof(u32);
++
++ for (i = 0; i < nr_cells; gpio_index++) {
++ const phandle *gpio_phandle;
++
++ gpio_phandle = gpios + i;
++ gpio_spec = gpio_phandle + 1;
++
++ /* one cell hole in the gpios = <>; */
++ if (!*gpio_phandle) {
++ if (gpio_index == index)
++ return -ENOENT;
++ i++;
++ continue;
++ }
++
++ gc = of_find_node_by_phandle(*gpio_phandle);
++ if (!gc) {
++ pr_debug("%s: could not find phandle for gpios\n",
++ np->full_name);
++ goto err0;
++ }
++
++ of_gc = gc->data;
++ if (!of_gc) {
++ pr_debug("%s: gpio controller %s isn't registered\n",
++ np->full_name, gc->full_name);
++ goto err1;
++ }
++
++ gpio_cells = of_get_property(gc, "#gpio-cells", &size);
++ if (!gpio_cells || size != sizeof(*gpio_cells) ||
++ *gpio_cells != of_gc->gpio_cells) {
++ pr_debug("%s: wrong #gpio-cells for %s\n",
++ np->full_name, gc->full_name);
++ goto err1;
++ }
++
++ /* Next phandle is at phandle cells + #gpio-cells */
++ i += sizeof(*gpio_phandle) / sizeof(u32) + *gpio_cells;
++ if (i >= nr_cells + 1) {
++ pr_debug("%s: insufficient gpio-spec length\n",
++ np->full_name);
++ goto err1;
++ }
++
++ if (gpio_index == index)
++ break;
++
++ of_gc = NULL;
++ of_node_put(gc);
++ }
++
++ if (!of_gc) {
++ ret = -ENOENT;
++ goto err0;
++ }
++
++ ret = of_gc->xlate(of_gc, np, gpio_spec);
++ if (ret < 0)
++ goto err1;
++
++ ret += of_gc->gc.base;
++err1:
++ of_node_put(gc);
++err0:
++ pr_debug("%s exited with status %d\n", __func__, ret);
++ return ret;
++}
++EXPORT_SYMBOL(of_get_gpio);
++
++/**
++ * of_gpio_simple_xlate - translate gpio_spec to the GPIO number
++ * @of_gc: pointer to the of_gpio_chip structure
++ * @np: device node of the GPIO chip
++ * @gpio_spec: gpio specifier as found in the device tree
++ *
++ * This is simple translation function, suitable for the most 1:1 mapped
++ * gpio chips. This function performs only one sanity check: whether gpio
++ * is less than ngpios (that is specified in the gpio_chip).
++ */
++int of_gpio_simple_xlate(struct of_gpio_chip *of_gc, struct device_node *np,
++ const void *gpio_spec)
++{
++ const u32 *gpio = gpio_spec;
++
++ if (*gpio > of_gc->gc.ngpio)
++ return -EINVAL;
++
++ return *gpio;
++}
++EXPORT_SYMBOL(of_gpio_simple_xlate);
++
++/* Should be sufficient for now, later we'll use dynamic bases. */
++#if defined(CONFIG_PPC32) || defined(CONFIG_SPARC32)
++#define GPIOS_PER_CHIP 32
++#else
++#define GPIOS_PER_CHIP 64
++#endif
++
++static int of_get_gpiochip_base(struct device_node *np)
++{
++ struct device_node *gc = NULL;
++ int gpiochip_base = 0;
++
++ while ((gc = of_find_all_nodes(gc))) {
++ if (!of_get_property(gc, "gpio-controller", NULL))
++ continue;
++
++ if (gc != np) {
++ gpiochip_base += GPIOS_PER_CHIP;
++ continue;
++ }
++
++ of_node_put(gc);
++
++ if (gpiochip_base >= ARCH_NR_GPIOS)
++ return -ENOSPC;
++
++ return gpiochip_base;
++ }
++
++ return -ENOENT;
++}
++
++/**
++ * of_mm_gpiochip_add - Add memory mapped GPIO chip (bank)
++ * @np: device node of the GPIO chip
++ * @mm_gc: pointer to the of_mm_gpio_chip allocated structure
++ *
++ * To use this function you should allocate and fill mm_gc with:
++ *
++ * 1) In the gpio_chip structure:
++ * - all the callbacks
++ *
++ * 2) In the of_gpio_chip structure:
++ * - gpio_cells
++ * - xlate callback (optional)
++ *
++ * 3) In the of_mm_gpio_chip structure:
++ * - save_regs callback (optional)
++ *
++ * If succeeded, this function will map bank's memory and will
++ * do all necessary work for you. Then you'll able to use .regs
++ * to manage GPIOs from the callbacks.
++ */
++int of_mm_gpiochip_add(struct device_node *np,
++ struct of_mm_gpio_chip *mm_gc)
++{
++ int ret = -ENOMEM;
++ struct of_gpio_chip *of_gc = &mm_gc->of_gc;
++ struct gpio_chip *gc = &of_gc->gc;
++
++ gc->label = kstrdup(np->full_name, GFP_KERNEL);
++ if (!gc->label)
++ goto err0;
++
++ mm_gc->regs = of_iomap(np, 0);
++ if (!mm_gc->regs)
++ goto err1;
++
++ gc->base = of_get_gpiochip_base(np);
++ if (gc->base < 0) {
++ ret = gc->base;
++ goto err1;
++ }
++
++ if (!of_gc->xlate)
++ of_gc->xlate = of_gpio_simple_xlate;
++
++ if (mm_gc->save_regs)
++ mm_gc->save_regs(mm_gc);
++
++ np->data = of_gc;
++
++ ret = gpiochip_add(gc);
++ if (ret)
++ goto err2;
++
++ /* We don't want to lose the node and its ->data */
++ of_node_get(np);
++
++ pr_debug("%s: registered as generic GPIO chip, base is %d\n",
++ np->full_name, gc->base);
++ return 0;
++err2:
++ np->data = NULL;
++ iounmap(mm_gc->regs);
++err1:
++ kfree(gc->label);
++err0:
++ pr_err("%s: GPIO chip registration failed with status %d\n",
++ np->full_name, ret);
++ return ret;
++}
++EXPORT_SYMBOL(of_mm_gpiochip_add);
+diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c
+new file mode 100644
+index 0000000..715a444
+--- /dev/null
++++ b/drivers/of/of_i2c.c
+@@ -0,0 +1,118 @@
++/*
++ * OF helpers for the I2C API
++ *
++ * Copyright (c) 2008 Jochen Friedrich <jochen at scram.de>
++ *
++ * Based on a previous patch from Jon Smirl <jonsmirl at gmail.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ */
++
++#include <linux/i2c.h>
++#include <linux/of.h>
++#include <linux/module.h>
++
++struct i2c_driver_device {
++ char *of_device;
++ char *i2c_type;
++};
++
++static struct i2c_driver_device i2c_devices[] = {
++ { "dallas,ds1374", "rtc-ds1374" },
++};
++
++static int of_find_i2c_driver(struct device_node *node,
++ struct i2c_board_info *info)
++{
++ int i, cplen;
++ const char *compatible;
++ const char *p;
++
++ /* 1. search for exception list entry */
++ for (i = 0; i < ARRAY_SIZE(i2c_devices); i++) {
++ if (!of_device_is_compatible(node, i2c_devices[i].of_device))
++ continue;
++ if (strlcpy(info->type, i2c_devices[i].i2c_type,
++ I2C_NAME_SIZE) >= I2C_NAME_SIZE)
++ return -ENOMEM;
++
++ return 0;
++ }
++
++ compatible = of_get_property(node, "compatible", &cplen);
++ if (!compatible)
++ return -ENODEV;
++
++ /* 2. search for linux,<i2c-type> entry */
++ p = compatible;
++ while (cplen > 0) {
++ if (!strncmp(p, "linux,", 6)) {
++ p += 6;
++ if (strlcpy(info->type, p,
++ I2C_NAME_SIZE) >= I2C_NAME_SIZE)
++ return -ENOMEM;
++ return 0;
++ }
++
++ i = strlen(p) + 1;
++ p += i;
++ cplen -= i;
++ }
++
++ /* 3. take fist compatible entry and strip manufacturer */
++ p = strchr(compatible, ',');
++ if (!p)
++ return -ENODEV;
++ p++;
++ if (strlcpy(info->type, p, I2C_NAME_SIZE) >= I2C_NAME_SIZE)
++ return -ENOMEM;
++ return 0;
++}
++
++void of_register_i2c_devices(struct i2c_adapter *adap,
++ struct device_node *adap_node)
++{
++ void *result;
++ struct device_node *node;
++
++ for_each_child_of_node(adap_node, node) {
++ struct i2c_board_info info = {};
++ const u32 *addr;
++ int len;
++
++ addr = of_get_property(node, "reg", &len);
++ if (!addr || len < sizeof(int) || *addr > (1 << 10) - 1) {
++ printk(KERN_ERR
++ "of-i2c: invalid i2c device entry\n");
++ continue;
++ }
++
++ info.irq = irq_of_parse_and_map(node, 0);
++ if (info.irq == NO_IRQ)
++ info.irq = -1;
++
++ if (of_find_i2c_driver(node, &info) < 0) {
++ irq_dispose_mapping(info.irq);
++ continue;
++ }
++
++ info.addr = *addr;
++
++ request_module(info.type);
++
++ result = i2c_new_device(adap, &info);
++ if (result == NULL) {
++ printk(KERN_ERR
++ "of-i2c: Failed to load driver for %s\n",
++ info.type);
++ irq_dispose_mapping(info.irq);
++ continue;
++ }
++ }
++}
++EXPORT_SYMBOL(of_register_i2c_devices);
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
+index 03c763c..d9c6322 100644
+--- a/drivers/parisc/dino.c
++++ b/drivers/parisc/dino.c
+@@ -496,7 +496,6 @@ dino_card_setup(struct pci_bus *bus, void __iomem *base_addr)
+ list_for_each_safe(ln, tmp_ln, &bus->devices) {
+ struct pci_dev *dev = pci_dev_b(ln);
+
+- list_del(&dev->global_list);
+ list_del(&dev->bus_list);
+ }
+
+diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
+index b7bcdcc..209b4a4 100644
+--- a/drivers/parport/Kconfig
++++ b/drivers/parport/Kconfig
+@@ -36,7 +36,7 @@ if PARPORT
+ config PARPORT_PC
+ tristate "PC-style hardware"
+ depends on (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV && \
+- (!M68K || ISA) && !MN10300
++ (!M68K || ISA) && !MN10300 && !AVR32
+ ---help---
+ You should say Y here if you have a PC-style parallel port. All
+ IBM PC compatible computers and some Alphas have PC-style
+diff --git a/drivers/pci/access.c b/drivers/pci/access.c
+index fc405f0..ec8f700 100644
+--- a/drivers/pci/access.c
++++ b/drivers/pci/access.c
+@@ -1,3 +1,4 @@
++#include <linux/delay.h>
+ #include <linux/pci.h>
+ #include <linux/module.h>
+ #include <linux/sched.h>
+@@ -126,6 +127,171 @@ PCI_USER_WRITE_CONFIG(byte, u8)
+ PCI_USER_WRITE_CONFIG(word, u16)
+ PCI_USER_WRITE_CONFIG(dword, u32)
+
++/* VPD access through PCI 2.2+ VPD capability */
++
++#define PCI_VPD_PCI22_SIZE (PCI_VPD_ADDR_MASK + 1)
++
++struct pci_vpd_pci22 {
++ struct pci_vpd base;
++ spinlock_t lock; /* controls access to hardware and the flags */
++ u8 cap;
++ bool busy;
++ bool flag; /* value of F bit to wait for */
++};
++
++/* Wait for last operation to complete */
++static int pci_vpd_pci22_wait(struct pci_dev *dev)
++{
++ struct pci_vpd_pci22 *vpd =
++ container_of(dev->vpd, struct pci_vpd_pci22, base);
++ u16 flag, status;
++ int wait;
++ int ret;
++
++ if (!vpd->busy)
++ return 0;
++
++ flag = vpd->flag ? PCI_VPD_ADDR_F : 0;
++ wait = vpd->flag ? 10 : 1000; /* read: 100 us; write: 10 ms */
++ for (;;) {
++ ret = pci_user_read_config_word(dev,
++ vpd->cap + PCI_VPD_ADDR,
++ &status);
++ if (ret < 0)
++ return ret;
++ if ((status & PCI_VPD_ADDR_F) == flag) {
++ vpd->busy = false;
++ return 0;
++ }
++ if (wait-- == 0)
++ return -ETIMEDOUT;
++ udelay(10);
++ }
++}
++
++static int pci_vpd_pci22_read(struct pci_dev *dev, int pos, int size,
++ char *buf)
++{
++ struct pci_vpd_pci22 *vpd =
++ container_of(dev->vpd, struct pci_vpd_pci22, base);
++ u32 val;
++ int ret;
++ int begin, end, i;
++
++ if (pos < 0 || pos > PCI_VPD_PCI22_SIZE ||
++ size > PCI_VPD_PCI22_SIZE - pos)
++ return -EINVAL;
++ if (size == 0)
++ return 0;
++
++ spin_lock_irq(&vpd->lock);
++ ret = pci_vpd_pci22_wait(dev);
++ if (ret < 0)
++ goto out;
++ ret = pci_user_write_config_word(dev, vpd->cap + PCI_VPD_ADDR,
++ pos & ~3);
++ if (ret < 0)
++ goto out;
++ vpd->busy = true;
++ vpd->flag = 1;
++ ret = pci_vpd_pci22_wait(dev);
++ if (ret < 0)
++ goto out;
++ ret = pci_user_read_config_dword(dev, vpd->cap + PCI_VPD_DATA,
++ &val);
++out:
++ spin_unlock_irq(&vpd->lock);
++ if (ret < 0)
++ return ret;
++
++ /* Convert to bytes */
++ begin = pos & 3;
++ end = min(4, begin + size);
++ for (i = 0; i < end; ++i) {
++ if (i >= begin)
++ *buf++ = val;
++ val >>= 8;
++ }
++ return end - begin;
++}
++
++static int pci_vpd_pci22_write(struct pci_dev *dev, int pos, int size,
++ const char *buf)
++{
++ struct pci_vpd_pci22 *vpd =
++ container_of(dev->vpd, struct pci_vpd_pci22, base);
++ u32 val;
++ int ret;
++
++ if (pos < 0 || pos > PCI_VPD_PCI22_SIZE || pos & 3 ||
++ size > PCI_VPD_PCI22_SIZE - pos || size < 4)
++ return -EINVAL;
++
++ val = (u8) *buf++;
++ val |= ((u8) *buf++) << 8;
++ val |= ((u8) *buf++) << 16;
++ val |= ((u32)(u8) *buf++) << 24;
++
++ spin_lock_irq(&vpd->lock);
++ ret = pci_vpd_pci22_wait(dev);
++ if (ret < 0)
++ goto out;
++ ret = pci_user_write_config_dword(dev, vpd->cap + PCI_VPD_DATA,
++ val);
++ if (ret < 0)
++ goto out;
++ ret = pci_user_write_config_word(dev, vpd->cap + PCI_VPD_ADDR,
++ pos | PCI_VPD_ADDR_F);
++ if (ret < 0)
++ goto out;
++ vpd->busy = true;
++ vpd->flag = 0;
++ ret = pci_vpd_pci22_wait(dev);
++out:
++ spin_unlock_irq(&vpd->lock);
++ if (ret < 0)
++ return ret;
++
++ return 4;
++}
++
++static int pci_vpd_pci22_get_size(struct pci_dev *dev)
++{
++ return PCI_VPD_PCI22_SIZE;
++}
++
++static void pci_vpd_pci22_release(struct pci_dev *dev)
++{
++ kfree(container_of(dev->vpd, struct pci_vpd_pci22, base));
++}
++
++static struct pci_vpd_ops pci_vpd_pci22_ops = {
++ .read = pci_vpd_pci22_read,
++ .write = pci_vpd_pci22_write,
++ .get_size = pci_vpd_pci22_get_size,
++ .release = pci_vpd_pci22_release,
++};
++
++int pci_vpd_pci22_init(struct pci_dev *dev)
++{
++ struct pci_vpd_pci22 *vpd;
++ u8 cap;
++
++ cap = pci_find_capability(dev, PCI_CAP_ID_VPD);
++ if (!cap)
++ return -ENODEV;
++ vpd = kzalloc(sizeof(*vpd), GFP_ATOMIC);
++ if (!vpd)
++ return -ENOMEM;
++
++ vpd->base.ops = &pci_vpd_pci22_ops;
++ spin_lock_init(&vpd->lock);
++ vpd->cap = cap;
++ vpd->busy = false;
++ dev->vpd = &vpd->base;
++ return 0;
++}
++
+ /**
+ * pci_block_user_cfg_access - Block userspace PCI config reads/writes
+ * @dev: pci device struct
+diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
+index d708358..529d9d7 100644
+--- a/drivers/pci/bus.c
++++ b/drivers/pci/bus.c
+@@ -84,10 +84,7 @@ int pci_bus_add_device(struct pci_dev *dev)
+ if (retval)
+ return retval;
+
+- down_write(&pci_bus_sem);
+- list_add_tail(&dev->global_list, &pci_devices);
+- up_write(&pci_bus_sem);
+-
++ dev->is_added = 1;
+ pci_proc_attach_device(dev);
+ pci_create_sysfs_dev_files(dev);
+ return 0;
+@@ -112,11 +109,8 @@ void pci_bus_add_devices(struct pci_bus *bus)
+ int retval;
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+- /*
+- * Skip already-present devices (which are on the
+- * global device list.)
+- */
+- if (!list_empty(&dev->global_list))
++ /* Skip already-added devices */
++ if (dev->is_added)
+ continue;
+ retval = pci_bus_add_device(dev);
+ if (retval)
+@@ -124,8 +118,7 @@ void pci_bus_add_devices(struct pci_bus *bus)
+ }
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+-
+- BUG_ON(list_empty(&dev->global_list));
++ BUG_ON(!dev->is_added);
+
+ /*
+ * If there is an unattached subordinate bus, attach
+diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
+index 2cdd832..eacfb13 100644
+--- a/drivers/pci/hotplug/Kconfig
++++ b/drivers/pci/hotplug/Kconfig
+@@ -63,7 +63,7 @@ config HOTPLUG_PCI_COMPAQ_NVRAM
+
+ config HOTPLUG_PCI_IBM
+ tristate "IBM PCI Hotplug driver"
+- depends on X86_IO_APIC && X86 && PCI_BIOS && PCI_LEGACY
++ depends on X86_IO_APIC && X86 && PCI_BIOS
+ help
+ Say Y here if you have a motherboard with a IBM PCI Hotplug
+ controller.
+@@ -119,7 +119,7 @@ config HOTPLUG_PCI_CPCI_ZT5550
+
+ config HOTPLUG_PCI_CPCI_GENERIC
+ tristate "Generic port I/O CompactPCI Hotplug driver"
+- depends on HOTPLUG_PCI_CPCI && X86 && PCI_LEGACY
++ depends on HOTPLUG_PCI_CPCI && X86
+ help
+ Say Y here if you have a CompactPCI system card that exposes the #ENUM
+ hotswap signal as a bit in a system register that can be read through
+diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
+index 270a33c..f8c187a 100644
+--- a/drivers/pci/hotplug/acpi_pcihp.c
++++ b/drivers/pci/hotplug/acpi_pcihp.c
+@@ -36,7 +36,7 @@
+
+ #define MY_NAME "acpi_pcihp"
+
+-#define dbg(fmt, arg...) do { if (debug_acpi) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __FUNCTION__ , ## arg); } while (0)
++#define dbg(fmt, arg...) do { if (debug_acpi) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __func__ , ## arg); } while (0)
+ #define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
+ #define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
+ #define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
+@@ -71,7 +71,7 @@ decode_type0_hpx_record(union acpi_object *record, struct hotplug_params *hpx)
+ default:
+ printk(KERN_WARNING
+ "%s: Type 0 Revision %d record not supported\n",
+- __FUNCTION__, revision);
++ __func__, revision);
+ return AE_ERROR;
+ }
+ return AE_OK;
+@@ -100,7 +100,7 @@ decode_type1_hpx_record(union acpi_object *record, struct hotplug_params *hpx)
+ default:
+ printk(KERN_WARNING
+ "%s: Type 1 Revision %d record not supported\n",
+- __FUNCTION__, revision);
++ __func__, revision);
+ return AE_ERROR;
+ }
+ return AE_OK;
+@@ -142,7 +142,7 @@ decode_type2_hpx_record(union acpi_object *record, struct hotplug_params *hpx)
+ default:
+ printk(KERN_WARNING
+ "%s: Type 2 Revision %d record not supported\n",
+- __FUNCTION__, revision);
++ __func__, revision);
+ return AE_ERROR;
+ }
+ return AE_OK;
+@@ -203,7 +203,7 @@ acpi_run_hpx(acpi_handle handle, struct hotplug_params *hpx)
+ break;
+ default:
+ printk(KERN_ERR "%s: Type %d record not supported\n",
+- __FUNCTION__, type);
++ __func__, type);
+ status = AE_ERROR;
+ goto exit;
+ }
+@@ -235,7 +235,7 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
+ ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
+ if (!ret_buf.pointer) {
+ printk(KERN_ERR "%s:%s alloc for _HPP fail\n",
+- __FUNCTION__, (char *)string.pointer);
++ __func__, (char *)string.pointer);
+ kfree(string.pointer);
+ return AE_NO_MEMORY;
+ }
+@@ -245,7 +245,7 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
+ break;
+ default:
+ if (ACPI_FAILURE(status)) {
+- pr_debug("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
++ pr_debug("%s:%s _HPP fail=0x%x\n", __func__,
+ (char *)string.pointer, status);
+ kfree(string.pointer);
+ return status;
+@@ -254,7 +254,7 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
+
+ ext_obj = (union acpi_object *) ret_buf.pointer;
+ if (ext_obj->type != ACPI_TYPE_PACKAGE) {
+- printk(KERN_ERR "%s:%s _HPP obj not a package\n", __FUNCTION__,
++ printk(KERN_ERR "%s:%s _HPP obj not a package\n", __func__,
+ (char *)string.pointer);
+ status = AE_ERROR;
+ goto free_and_return;
+@@ -270,7 +270,7 @@ acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
+ break;
+ default:
+ printk(KERN_ERR "%s:%s _HPP obj type incorrect\n",
+- __FUNCTION__, (char *)string.pointer);
++ __func__, (char *)string.pointer);
+ status = AE_ERROR;
+ goto free_and_return;
+ }
+@@ -311,12 +311,12 @@ acpi_status acpi_run_oshp(acpi_handle handle)
+ if (ACPI_FAILURE(status))
+ if (status != AE_NOT_FOUND)
+ printk(KERN_ERR "%s:%s OSHP fails=0x%x\n",
+- __FUNCTION__, (char *)string.pointer, status);
++ __func__, (char *)string.pointer, status);
+ else
+ dbg("%s:%s OSHP not found\n",
+- __FUNCTION__, (char *)string.pointer);
++ __func__, (char *)string.pointer);
+ else
+- pr_debug("%s:%s OSHP passes\n", __FUNCTION__,
++ pr_debug("%s:%s OSHP passes\n", __func__,
+ (char *)string.pointer);
+
+ kfree(string.pointer);
+diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
+index 9279d5b..7af68ba 100644
+--- a/drivers/pci/hotplug/acpiphp_core.c
++++ b/drivers/pci/hotplug/acpiphp_core.c
+@@ -138,7 +138,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
+ {
+ struct slot *slot = hotplug_slot->private;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ /* enable the specified slot */
+ return acpiphp_enable_slot(slot->acpi_slot);
+@@ -156,7 +156,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
+ struct slot *slot = hotplug_slot->private;
+ int retval;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ /* disable the specified slot */
+ retval = acpiphp_disable_slot(slot->acpi_slot);
+@@ -179,7 +179,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
+ {
+ int retval = -ENODEV;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ if (attention_info && try_module_get(attention_info->owner)) {
+ retval = attention_info->set_attn(hotplug_slot, status);
+@@ -202,7 +202,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ {
+ struct slot *slot = hotplug_slot->private;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ *value = acpiphp_get_power_status(slot->acpi_slot);
+
+@@ -224,7 +224,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ {
+ int retval = -EINVAL;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ if (attention_info && try_module_get(attention_info->owner)) {
+ retval = attention_info->get_attn(hotplug_slot, value);
+@@ -247,7 +247,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ {
+ struct slot *slot = hotplug_slot->private;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ *value = acpiphp_get_latch_status(slot->acpi_slot);
+
+@@ -267,7 +267,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ {
+ struct slot *slot = hotplug_slot->private;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ *value = acpiphp_get_adapter_status(slot->acpi_slot);
+
+@@ -284,7 +284,7 @@ static int get_address(struct hotplug_slot *hotplug_slot, u32 *value)
+ {
+ struct slot *slot = hotplug_slot->private;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ *value = acpiphp_get_address(slot->acpi_slot);
+
+@@ -318,7 +318,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
+ {
+ struct slot *slot = hotplug_slot->private;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ kfree(slot->hotplug_slot);
+ kfree(slot);
+diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
+index 5e50008..648596d 100644
+--- a/drivers/pci/hotplug/acpiphp_glue.c
++++ b/drivers/pci/hotplug/acpiphp_glue.c
+@@ -352,7 +352,7 @@ static void decode_hpp(struct acpiphp_bridge *bridge)
+ /* use default numbers */
+ printk(KERN_WARNING
+ "%s: Could not get hotplug parameters. Use defaults\n",
+- __FUNCTION__);
++ __func__);
+ bridge->hpp.t0 = &bridge->hpp.type0_data;
+ bridge->hpp.t0->revision = 0;
+ bridge->hpp.t0->cache_line_size = 0x10;
+@@ -534,7 +534,7 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
+
+ status = acpi_evaluate_integer(handle, "_ADR", NULL, &tmp);
+ if (ACPI_FAILURE(status)) {
+- dbg("%s: _ADR evaluation failure\n", __FUNCTION__);
++ dbg("%s: _ADR evaluation failure\n", __func__);
+ return AE_OK;
+ }
+
+@@ -578,7 +578,7 @@ static int add_bridge(acpi_handle handle)
+ if (ACPI_SUCCESS(status)) {
+ status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp);
+ if (ACPI_FAILURE(status)) {
+- dbg("%s: _STA evaluation failure\n", __FUNCTION__);
++ dbg("%s: _STA evaluation failure\n", __func__);
+ return 0;
+ }
+ if ((tmp & ACPI_STA_FUNCTIONING) == 0)
+@@ -928,10 +928,10 @@ static int power_on_slot(struct acpiphp_slot *slot)
+ func = list_entry(l, struct acpiphp_func, sibling);
+
+ if (func->flags & FUNC_HAS_PS0) {
+- dbg("%s: executing _PS0\n", __FUNCTION__);
++ dbg("%s: executing _PS0\n", __func__);
+ status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL);
+ if (ACPI_FAILURE(status)) {
+- warn("%s: _PS0 failed\n", __FUNCTION__);
++ warn("%s: _PS0 failed\n", __func__);
+ retval = -1;
+ goto err_exit;
+ } else
+@@ -966,7 +966,7 @@ static int power_off_slot(struct acpiphp_slot *slot)
+ if (func->flags & FUNC_HAS_PS3) {
+ status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL);
+ if (ACPI_FAILURE(status)) {
+- warn("%s: _PS3 failed\n", __FUNCTION__);
++ warn("%s: _PS3 failed\n", __func__);
+ retval = -1;
+ goto err_exit;
+ } else
+@@ -1300,7 +1300,7 @@ int acpiphp_eject_slot(struct acpiphp_slot *slot)
+
+ status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL);
+ if (ACPI_FAILURE(status)) {
+- warn("%s: _EJ0 failed\n", __FUNCTION__);
++ warn("%s: _EJ0 failed\n", __func__);
+ return -1;
+ } else
+ break;
+@@ -1349,7 +1349,7 @@ static int acpiphp_check_bridge(struct acpiphp_bridge *bridge)
+ }
+ }
+
+- dbg("%s: %d enabled, %d disabled\n", __FUNCTION__, enabled, disabled);
++ dbg("%s: %d enabled, %d disabled\n", __func__, enabled, disabled);
+
+ err_exit:
+ return retval;
+@@ -1527,7 +1527,7 @@ check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
+ if (bridge) {
+ acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+ dbg("%s: re-enumerating slots under %s\n",
+- __FUNCTION__, objname);
++ __func__, objname);
+ acpiphp_check_bridge(bridge);
+ }
+ return AE_OK ;
+@@ -1572,10 +1572,10 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
+ switch (type) {
+ case ACPI_NOTIFY_BUS_CHECK:
+ /* bus re-enumerate */
+- dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname);
++ dbg("%s: Bus check notify on %s\n", __func__, objname);
+ if (bridge) {
+ dbg("%s: re-enumerating slots under %s\n",
+- __FUNCTION__, objname);
++ __func__, objname);
+ acpiphp_check_bridge(bridge);
+ }
+ if (num_sub_bridges)
+@@ -1585,18 +1585,18 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
+
+ case ACPI_NOTIFY_DEVICE_CHECK:
+ /* device check */
+- dbg("%s: Device check notify on %s\n", __FUNCTION__, objname);
++ dbg("%s: Device check notify on %s\n", __func__, objname);
+ acpiphp_check_bridge(bridge);
+ break;
+
+ case ACPI_NOTIFY_DEVICE_WAKE:
+ /* wake event */
+- dbg("%s: Device wake notify on %s\n", __FUNCTION__, objname);
++ dbg("%s: Device wake notify on %s\n", __func__, objname);
+ break;
+
+ case ACPI_NOTIFY_EJECT_REQUEST:
+ /* request device eject */
+- dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname);
++ dbg("%s: Device eject notify on %s\n", __func__, objname);
+ if ((bridge->type != BRIDGE_TYPE_HOST) &&
+ (bridge->flags & BRIDGE_HAS_EJ0)) {
+ struct acpiphp_slot *slot;
+@@ -1649,24 +1649,24 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *contex
+ switch (type) {
+ case ACPI_NOTIFY_BUS_CHECK:
+ /* bus re-enumerate */
+- dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname);
++ dbg("%s: Bus check notify on %s\n", __func__, objname);
+ acpiphp_enable_slot(func->slot);
+ break;
+
+ case ACPI_NOTIFY_DEVICE_CHECK:
+ /* device check : re-enumerate from parent bus */
+- dbg("%s: Device check notify on %s\n", __FUNCTION__, objname);
++ dbg("%s: Device check notify on %s\n", __func__, objname);
+ acpiphp_check_bridge(func->slot->bridge);
+ break;
+
+ case ACPI_NOTIFY_DEVICE_WAKE:
+ /* wake event */
+- dbg("%s: Device wake notify on %s\n", __FUNCTION__, objname);
++ dbg("%s: Device wake notify on %s\n", __func__, objname);
+ break;
+
+ case ACPI_NOTIFY_EJECT_REQUEST:
+ /* request device eject */
+- dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname);
++ dbg("%s: Device eject notify on %s\n", __func__, objname);
+ if (!(acpiphp_disable_slot(func->slot)))
+ acpiphp_eject_slot(func->slot);
+ break;
+@@ -1796,7 +1796,7 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot)
+ if (retval)
+ power_off_slot(slot);
+ } else {
+- dbg("%s: Slot status is not ACPI_STA_ALL\n", __FUNCTION__);
++ dbg("%s: Slot status is not ACPI_STA_ALL\n", __func__);
+ power_off_slot(slot);
+ }
+
+diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
+index b0a22b9..ede9051 100644
+--- a/drivers/pci/hotplug/acpiphp_ibm.c
++++ b/drivers/pci/hotplug/acpiphp_ibm.c
+@@ -186,7 +186,7 @@ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status)
+
+ ibm_slot = ibm_slot_from_id(hpslot_to_sun(slot));
+
+- dbg("%s: set slot %d (%d) attention status to %d\n", __FUNCTION__,
++ dbg("%s: set slot %d (%d) attention status to %d\n", __func__,
+ ibm_slot->slot.slot_num, ibm_slot->slot.slot_id,
+ (status ? 1 : 0));
+
+@@ -231,7 +231,7 @@ static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status)
+ else
+ *status = 0;
+
+- dbg("%s: get slot %d (%d) attention status is %d\n", __FUNCTION__,
++ dbg("%s: get slot %d (%d) attention status is %d\n", __func__,
+ ibm_slot->slot.slot_num, ibm_slot->slot.slot_id,
+ *status);
+
+@@ -263,10 +263,10 @@ static void ibm_handle_events(acpi_handle handle, u32 event, void *context)
+ u8 subevent = event & 0xf0;
+ struct notification *note = context;
+
+- dbg("%s: Received notification %02x\n", __FUNCTION__, event);
++ dbg("%s: Received notification %02x\n", __func__, event);
+
+ if (subevent == 0x80) {
+- dbg("%s: generationg bus event\n", __FUNCTION__);
++ dbg("%s: generationg bus event\n", __func__);
+ acpi_bus_generate_proc_event(note->device, note->event, detail);
+ acpi_bus_generate_netlink_event(note->device->pnp.device_class,
+ note->device->dev.bus_id,
+@@ -299,7 +299,7 @@ static int ibm_get_table_from_acpi(char **bufp)
+
+ status = acpi_evaluate_object(ibm_acpi_handle, "APCI", NULL, &buffer);
+ if (ACPI_FAILURE(status)) {
+- err("%s: APCI evaluation failed\n", __FUNCTION__);
++ err("%s: APCI evaluation failed\n", __func__);
+ return -ENODEV;
+ }
+
+@@ -307,13 +307,13 @@ static int ibm_get_table_from_acpi(char **bufp)
+ if (!(package) ||
+ (package->type != ACPI_TYPE_PACKAGE) ||
+ !(package->package.elements)) {
+- err("%s: Invalid APCI object\n", __FUNCTION__);
++ err("%s: Invalid APCI object\n", __func__);
+ goto read_table_done;
+ }
+
+ for(size = 0, i = 0; i < package->package.count; i++) {
+ if (package->package.elements[i].type != ACPI_TYPE_BUFFER) {
+- err("%s: Invalid APCI element %d\n", __FUNCTION__, i);
++ err("%s: Invalid APCI element %d\n", __func__, i);
+ goto read_table_done;
+ }
+ size += package->package.elements[i].buffer.length;
+@@ -324,7 +324,7 @@ static int ibm_get_table_from_acpi(char **bufp)
+
+ lbuf = kzalloc(size, GFP_KERNEL);
+ dbg("%s: element count: %i, ASL table size: %i, &table = 0x%p\n",
+- __FUNCTION__, package->package.count, size, lbuf);
++ __func__, package->package.count, size, lbuf);
+
+ if (lbuf) {
+ *bufp = lbuf;
+@@ -368,7 +368,7 @@ static ssize_t ibm_read_apci_table(struct kobject *kobj,
+ int bytes_read = -EINVAL;
+ char *table = NULL;
+
+- dbg("%s: pos = %d, size = %zd\n", __FUNCTION__, (int)pos, size);
++ dbg("%s: pos = %d, size = %zd\n", __func__, (int)pos, size);
+
+ if (pos == 0) {
+ bytes_read = ibm_get_table_from_acpi(&table);
+@@ -402,7 +402,7 @@ static acpi_status __init ibm_find_acpi_device(acpi_handle handle,
+ status = acpi_get_object_info(handle, &info_buffer);
+ if (ACPI_FAILURE(status)) {
+ err("%s: Failed to get device information status=0x%x\n",
+- __FUNCTION__, status);
++ __func__, status);
+ return retval;
+ }
+ info = info_buffer.pointer;
+@@ -432,18 +432,18 @@ static int __init ibm_acpiphp_init(void)
+ struct acpi_device *device;
+ struct kobject *sysdir = &pci_hotplug_slots_kset->kobj;
+
+- dbg("%s\n", __FUNCTION__);
++ dbg("%s\n", __func__);
+
+ if (acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, ibm_find_acpi_device,
+ &ibm_acpi_handle, NULL) != FOUND_APCI) {
+- err("%s: acpi_walk_namespace failed\n", __FUNCTION__);
++ err("%s: acpi_walk_namespace failed\n", __func__);
+ retval = -ENODEV;
+ goto init_return;
+ }
+- dbg("%s: found IBM aPCI device\n", __FUNCTION__);
++ dbg("%s: found IBM aPCI device\n", __func__);
+ if (acpi_bus_get_device(ibm_acpi_handle, &device)) {
+- err("%s: acpi_bus_get_device failed\n", __FUNCTION__);
++ err("%s: acpi_bus_get_device failed\n", __func__);
+ retval = -ENODEV;
+ goto init_return;
+ }
+@@ -458,7 +458,7 @@ static int __init ibm_acpiphp_init(void)
+ &ibm_note);
+ if (ACPI_FAILURE(status)) {
+ err("%s: Failed to register notification handler\n",
+- __FUNCTION__);
++ __func__);
+ retval = -EBUSY;
+ goto init_cleanup;
+ }
+@@ -479,17 +479,17 @@ static void __exit ibm_acpiphp_exit(void)
+ acpi_status status;
+ struct kobject *sysdir = &pci_hotplug_slots_kset->kobj;
+
+- dbg("%s\n", __FUNCTION__);
++ dbg("%s\n", __func__);
+
+ if (acpiphp_unregister_attention(&ibm_attention_info))
+- err("%s: attention info deregistration failed", __FUNCTION__);
++ err("%s: attention info deregistration failed", __func__);
+
+ status = acpi_remove_notify_handler(
+ ibm_acpi_handle,
+ ACPI_DEVICE_NOTIFY,
+ ibm_handle_events);
+ if (ACPI_FAILURE(status))
+- err("%s: Notification handler removal failed\n", __FUNCTION__);
++ err("%s: Notification handler removal failed\n", __func__);
+ /* remove the /sys entries */
+ sysfs_remove_bin_file(sysdir, &ibm_apci_table_attr);
+ }
+diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c
+index ed4d44e..d8a6b80 100644
+--- a/drivers/pci/hotplug/cpci_hotplug_core.c
++++ b/drivers/pci/hotplug/cpci_hotplug_core.c
+@@ -108,7 +108,7 @@ enable_slot(struct hotplug_slot *hotplug_slot)
+ struct slot *slot = hotplug_slot->private;
+ int retval = 0;
+
+- dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s", __func__, hotplug_slot->name);
+
+ if (controller->ops->set_power)
+ retval = controller->ops->set_power(slot, 1);
+@@ -121,25 +121,25 @@ disable_slot(struct hotplug_slot *hotplug_slot)
+ struct slot *slot = hotplug_slot->private;
+ int retval = 0;
+
+- dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s", __func__, hotplug_slot->name);
+
+ down_write(&list_rwsem);
+
+ /* Unconfigure device */
+ dbg("%s - unconfiguring slot %s",
+- __FUNCTION__, slot->hotplug_slot->name);
++ __func__, slot->hotplug_slot->name);
+ if ((retval = cpci_unconfigure_slot(slot))) {
+ err("%s - could not unconfigure slot %s",
+- __FUNCTION__, slot->hotplug_slot->name);
++ __func__, slot->hotplug_slot->name);
+ goto disable_error;
+ }
+ dbg("%s - finished unconfiguring slot %s",
+- __FUNCTION__, slot->hotplug_slot->name);
++ __func__, slot->hotplug_slot->name);
+
+ /* Clear EXT (by setting it) */
+ if (cpci_clear_ext(slot)) {
+ err("%s - could not clear EXT for slot %s",
+- __FUNCTION__, slot->hotplug_slot->name);
++ __func__, slot->hotplug_slot->name);
+ retval = -ENODEV;
+ goto disable_error;
+ }
+@@ -372,7 +372,7 @@ init_slots(int clear_ins)
+ struct slot *slot;
+ struct pci_dev* dev;
+
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
+ down_read(&list_rwsem);
+ if (!slots) {
+ up_read(&list_rwsem);
+@@ -380,10 +380,10 @@ init_slots(int clear_ins)
+ }
+ list_for_each_entry(slot, &slot_list, slot_list) {
+ dbg("%s - looking at slot %s",
+- __FUNCTION__, slot->hotplug_slot->name);
++ __func__, slot->hotplug_slot->name);
+ if (clear_ins && cpci_check_and_clear_ins(slot))
+ dbg("%s - cleared INS for slot %s",
+- __FUNCTION__, slot->hotplug_slot->name);
++ __func__, slot->hotplug_slot->name);
+ dev = pci_get_slot(slot->bus, PCI_DEVFN(slot->number, 0));
+ if (dev) {
+ if (update_adapter_status(slot->hotplug_slot, 1))
+@@ -394,7 +394,7 @@ init_slots(int clear_ins)
+ }
+ }
+ up_read(&list_rwsem);
+- dbg("%s - exit", __FUNCTION__);
++ dbg("%s - exit", __func__);
+ return 0;
+ }
+
+@@ -415,7 +415,7 @@ check_slots(void)
+ extracted = inserted = 0;
+ list_for_each_entry(slot, &slot_list, slot_list) {
+ dbg("%s - looking at slot %s",
+- __FUNCTION__, slot->hotplug_slot->name);
++ __func__, slot->hotplug_slot->name);
+ if (cpci_check_and_clear_ins(slot)) {
+ /*
+ * Some broken hardware (e.g. PLX 9054AB) asserts
+@@ -430,28 +430,28 @@ check_slots(void)
+
+ /* Process insertion */
+ dbg("%s - slot %s inserted",
+- __FUNCTION__, slot->hotplug_slot->name);
++ __func__, slot->hotplug_slot->name);
+
+ /* GSM, debug */
+ hs_csr = cpci_get_hs_csr(slot);
+ dbg("%s - slot %s HS_CSR (1) = %04x",
+- __FUNCTION__, slot->hotplug_slot->name, hs_csr);
++ __func__, slot->hotplug_slot->name, hs_csr);
+
+ /* Configure device */
+ dbg("%s - configuring slot %s",
+- __FUNCTION__, slot->hotplug_slot->name);
++ __func__, slot->hotplug_slot->name);
+ if (cpci_configure_slot(slot)) {
+ err("%s - could not configure slot %s",
+- __FUNCTION__, slot->hotplug_slot->name);
++ __func__, slot->hotplug_slot->name);
+ continue;
+ }
+ dbg("%s - finished configuring slot %s",
+- __FUNCTION__, slot->hotplug_slot->name);
++ __func__, slot->hotplug_slot->name);
+
+ /* GSM, debug */
+ hs_csr = cpci_get_hs_csr(slot);
+ dbg("%s - slot %s HS_CSR (2) = %04x",
+- __FUNCTION__, slot->hotplug_slot->name, hs_csr);
++ __func__, slot->hotplug_slot->name, hs_csr);
+
+ if (update_latch_status(slot->hotplug_slot, 1))
+ warn("failure to update latch file");
+@@ -464,18 +464,18 @@ check_slots(void)
+ /* GSM, debug */
+ hs_csr = cpci_get_hs_csr(slot);
+ dbg("%s - slot %s HS_CSR (3) = %04x",
+- __FUNCTION__, slot->hotplug_slot->name, hs_csr);
++ __func__, slot->hotplug_slot->name, hs_csr);
+
+ inserted++;
+ } else if (cpci_check_ext(slot)) {
+ /* Process extraction request */
+ dbg("%s - slot %s extracted",
+- __FUNCTION__, slot->hotplug_slot->name);
++ __func__, slot->hotplug_slot->name);
+
+ /* GSM, debug */
+ hs_csr = cpci_get_hs_csr(slot);
+ dbg("%s - slot %s HS_CSR = %04x",
+- __FUNCTION__, slot->hotplug_slot->name, hs_csr);
++ __func__, slot->hotplug_slot->name, hs_csr);
+
+ if (!slot->extracting) {
+ if (update_latch_status(slot->hotplug_slot, 0)) {
+@@ -519,7 +519,7 @@ event_thread(void *data)
+ {
+ int rc;
+
+- dbg("%s - event thread started", __FUNCTION__);
++ dbg("%s - event thread started", __func__);
+ while (1) {
+ dbg("event thread sleeping");
+ set_current_state(TASK_INTERRUPTIBLE);
+@@ -532,7 +532,7 @@ event_thread(void *data)
+ /* Give userspace a chance to handle extraction */
+ msleep(500);
+ } else if (rc < 0) {
+- dbg("%s - error checking slots", __FUNCTION__);
++ dbg("%s - error checking slots", __func__);
+ thread_finished = 1;
+ goto out;
+ }
+@@ -541,7 +541,7 @@ event_thread(void *data)
+ break;
+
+ /* Re-enable ENUM# interrupt */
+- dbg("%s - re-enabling irq", __FUNCTION__);
++ dbg("%s - re-enabling irq", __func__);
+ controller->ops->enable_irq();
+ }
+ out:
+@@ -564,7 +564,7 @@ poll_thread(void *data)
+ /* Give userspace a chance to handle extraction */
+ msleep(500);
+ } else if (rc < 0) {
+- dbg("%s - error checking slots", __FUNCTION__);
++ dbg("%s - error checking slots", __func__);
+ thread_finished = 1;
+ goto out;
+ }
+@@ -621,7 +621,7 @@ cpci_hp_register_controller(struct cpci_hp_controller *new_controller)
+ status = -ENODEV;
+ }
+ dbg("%s - acquired controller irq %d",
+- __FUNCTION__, new_controller->irq);
++ __func__, new_controller->irq);
+ }
+ if (!status)
+ controller = new_controller;
+@@ -673,7 +673,7 @@ cpci_hp_start(void)
+ static int first = 1;
+ int status;
+
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
+ if (!controller)
+ return -ENODEV;
+
+@@ -693,14 +693,14 @@ cpci_hp_start(void)
+ status = cpci_start_thread();
+ if (status)
+ return status;
+- dbg("%s - thread started", __FUNCTION__);
++ dbg("%s - thread started", __func__);
+
+ if (controller->irq) {
+ /* Start enum interrupt processing */
+- dbg("%s - enabling irq", __FUNCTION__);
++ dbg("%s - enabling irq", __func__);
+ controller->ops->enable_irq();
+ }
+- dbg("%s - exit", __FUNCTION__);
++ dbg("%s - exit", __func__);
+ return 0;
+ }
+
+@@ -711,7 +711,7 @@ cpci_hp_stop(void)
+ return -ENODEV;
+ if (controller->irq) {
+ /* Stop enum interrupt processing */
+- dbg("%s - disabling irq", __FUNCTION__);
++ dbg("%s - disabling irq", __func__);
+ controller->ops->disable_irq();
+ }
+ cpci_stop_thread();
+diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c
+index b3515fc..df82b95 100644
+--- a/drivers/pci/hotplug/cpci_hotplug_pci.c
++++ b/drivers/pci/hotplug/cpci_hotplug_pci.c
+@@ -255,7 +255,7 @@ int __ref cpci_configure_slot(struct slot *slot)
+ struct pci_bus *parent;
+ int fn;
+
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
+
+ if (slot->dev == NULL) {
+ dbg("pci_dev null, finding %02x:%02x:%x",
+@@ -273,7 +273,7 @@ int __ref cpci_configure_slot(struct slot *slot)
+ * we will only call this case when lookup fails.
+ */
+ n = pci_scan_slot(slot->bus, slot->devfn);
+- dbg("%s: pci_scan_slot returned %d", __FUNCTION__, n);
++ dbg("%s: pci_scan_slot returned %d", __func__, n);
+ slot->dev = pci_get_slot(slot->bus, slot->devfn);
+ if (slot->dev == NULL) {
+ err("Could not find PCI device for slot %02x", slot->number);
+@@ -322,7 +322,7 @@ int __ref cpci_configure_slot(struct slot *slot)
+ pci_bus_add_devices(parent);
+ pci_enable_bridges(parent);
+
+- dbg("%s - exit", __FUNCTION__);
++ dbg("%s - exit", __func__);
+ return 0;
+ }
+
+@@ -331,7 +331,7 @@ int cpci_unconfigure_slot(struct slot* slot)
+ int i;
+ struct pci_dev *dev;
+
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
+ if (!slot->dev) {
+ err("No device for slot %02x\n", slot->number);
+ return -ENODEV;
+@@ -348,6 +348,6 @@ int cpci_unconfigure_slot(struct slot* slot)
+ pci_dev_put(slot->dev);
+ slot->dev = NULL;
+
+- dbg("%s - exit", __FUNCTION__);
++ dbg("%s - exit", __func__);
+ return 0;
+ }
+diff --git a/drivers/pci/hotplug/cpcihp_generic.c b/drivers/pci/hotplug/cpcihp_generic.c
+index f3852a6..148fb46 100644
+--- a/drivers/pci/hotplug/cpcihp_generic.c
++++ b/drivers/pci/hotplug/cpcihp_generic.c
+@@ -154,12 +154,18 @@ static int __init cpcihp_generic_init(void)
+ if(!r)
+ return -EBUSY;
+
+- dev = pci_find_slot(bridge_busnr, PCI_DEVFN(bridge_slot, 0));
++ bus = pci_find_bus(0, bridge_busnr);
++ if (!bus) {
++ err("Invalid bus number %d", bridge_busnr);
++ return -EINVAL;
++ }
++ dev = pci_get_slot(bus, PCI_DEVFN(bridge_slot, 0));
+ if(!dev || dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
+ err("Invalid bridge device %s", bridge);
+ return -EINVAL;
+ }
+ bus = dev->subordinate;
++ pci_dev_put(dev);
+
+ memset(&generic_hpc, 0, sizeof (struct cpci_hp_controller));
+ generic_hpc_ops.query_enum = query_enum;
+diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h
+index 298ad7f..b1decfa 100644
+--- a/drivers/pci/hotplug/cpqphp.h
++++ b/drivers/pci/hotplug/cpqphp.h
+@@ -674,7 +674,7 @@ static inline int cpq_get_latch_status(struct controller *ctrl, struct slot *slo
+
+ hp_slot = slot->device - ctrl->slot_device_offset;
+ dbg("%s: slot->device = %d, ctrl->slot_device_offset = %d \n",
+- __FUNCTION__, slot->device, ctrl->slot_device_offset);
++ __func__, slot->device, ctrl->slot_device_offset);
+
+ status = (readl(ctrl->hpc_reg + INT_INPUT_CLEAR) & (0x01L << hp_slot));
+
+@@ -709,7 +709,7 @@ static inline int wait_for_ctrl_irq(struct controller *ctrl)
+ DECLARE_WAITQUEUE(wait, current);
+ int retval = 0;
+
+- dbg("%s - start\n", __FUNCTION__);
++ dbg("%s - start\n", __func__);
+ add_wait_queue(&ctrl->queue, &wait);
+ /* Sleep for up to 1 second to wait for the LED to change. */
+ msleep_interruptible(1000);
+@@ -717,7 +717,7 @@ static inline int wait_for_ctrl_irq(struct controller *ctrl)
+ if (signal_pending(current))
+ retval = -EINTR;
+
+- dbg("%s - end\n", __FUNCTION__);
++ dbg("%s - end\n", __func__);
+ return retval;
+ }
+
+diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
+index 7417887..36b115b 100644
+--- a/drivers/pci/hotplug/cpqphp_core.c
++++ b/drivers/pci/hotplug/cpqphp_core.c
+@@ -315,7 +315,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
+ {
+ struct slot *slot = hotplug_slot->private;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ kfree(slot->hotplug_slot->info);
+ kfree(slot->hotplug_slot->name);
+@@ -338,7 +338,7 @@ static int ctrl_slot_setup(struct controller *ctrl,
+ void __iomem *slot_entry= NULL;
+ int result = -ENOMEM;
+
+- dbg("%s\n", __FUNCTION__);
++ dbg("%s\n", __func__);
+
+ tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
+
+@@ -513,7 +513,7 @@ get_slot_mapping(struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot)
+
+ u8 tbus, tdevice, tslot, bridgeSlot;
+
+- dbg("%s: %p, %d, %d, %p\n", __FUNCTION__, bus, bus_num, dev_num, slot);
++ dbg("%s: %p, %d, %d, %p\n", __func__, bus, bus_num, dev_num, slot);
+
+ bridgeSlot = 0xFF;
+
+@@ -636,7 +636,7 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
+ u8 device;
+ u8 function;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1)
+ return -ENODEV;
+@@ -663,7 +663,7 @@ static int process_SI(struct hotplug_slot *hotplug_slot)
+ u8 device;
+ u8 function;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1)
+ return -ENODEV;
+@@ -695,7 +695,7 @@ static int process_SS(struct hotplug_slot *hotplug_slot)
+ u8 device;
+ u8 function;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ if (cpqhp_get_bus_dev(ctrl, &bus, &devfn, slot->number) == -1)
+ return -ENODEV;
+@@ -708,7 +708,7 @@ static int process_SS(struct hotplug_slot *hotplug_slot)
+ if (!slot_func)
+ return -ENODEV;
+
+- dbg("In %s, slot_func = %p, ctrl = %p\n", __FUNCTION__, slot_func, ctrl);
++ dbg("In %s, slot_func = %p, ctrl = %p\n", __func__, slot_func, ctrl);
+ return cpqhp_process_SS(ctrl, slot_func);
+ }
+
+@@ -718,7 +718,7 @@ static int hardware_test(struct hotplug_slot *hotplug_slot, u32 value)
+ struct slot *slot = hotplug_slot->private;
+ struct controller *ctrl = slot->ctrl;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ return cpqhp_hardware_test(ctrl, value);
+ }
+@@ -729,7 +729,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ struct slot *slot = hotplug_slot->private;
+ struct controller *ctrl = slot->ctrl;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ *value = get_slot_enabled(ctrl, slot);
+ return 0;
+@@ -740,7 +740,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ struct slot *slot = hotplug_slot->private;
+ struct controller *ctrl = slot->ctrl;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ *value = cpq_get_attention_status(ctrl, slot);
+ return 0;
+@@ -751,7 +751,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ struct slot *slot = hotplug_slot->private;
+ struct controller *ctrl = slot->ctrl;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ *value = cpq_get_latch_status(ctrl, slot);
+
+@@ -763,7 +763,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ struct slot *slot = hotplug_slot->private;
+ struct controller *ctrl = slot->ctrl;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ *value = get_presence_status(ctrl, slot);
+
+@@ -775,7 +775,7 @@ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
+ struct slot *slot = hotplug_slot->private;
+ struct controller *ctrl = slot->ctrl;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ *value = ctrl->speed_capability;
+
+@@ -787,7 +787,7 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
+ struct slot *slot = hotplug_slot->private;
+ struct controller *ctrl = slot->ctrl;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ *value = ctrl->speed;
+
+@@ -841,7 +841,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ // TODO: This code can be made to support non-Compaq or Intel subsystem IDs
+ rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid);
+ if (rc) {
+- err("%s : pci_read_config_word failed\n", __FUNCTION__);
++ err("%s : pci_read_config_word failed\n", __func__);
+ goto err_disable_device;
+ }
+ dbg("Subsystem Vendor ID: %x\n", subsystem_vid);
+@@ -853,14 +853,14 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+
+ ctrl = kzalloc(sizeof(struct controller), GFP_KERNEL);
+ if (!ctrl) {
+- err("%s : out of memory\n", __FUNCTION__);
++ err("%s : out of memory\n", __func__);
+ rc = -ENOMEM;
+ goto err_disable_device;
+ }
+
+ rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid);
+ if (rc) {
+- err("%s : pci_read_config_word failed\n", __FUNCTION__);
++ err("%s : pci_read_config_word failed\n", __func__);
+ goto err_free_ctrl;
+ }
+
+@@ -1142,7 +1142,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ rc = cpqhp_save_config(ctrl, ctrl->bus, readb(ctrl->hpc_reg + SLOT_MASK));
+ if (rc) {
+ err("%s: unable to save PCI configuration data, error %d\n",
+- __FUNCTION__, rc);
++ __func__, rc);
+ goto err_iounmap;
+ }
+
+@@ -1180,7 +1180,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ if (rc) {
+ err(msg_initialization_err, 6);
+ err("%s: unable to save PCI configuration data, error %d\n",
+- __FUNCTION__, rc);
++ __func__, rc);
+ goto err_iounmap;
+ }
+
+diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c
+index 4018420..ef041ca 100644
+--- a/drivers/pci/hotplug/cpqphp_ctrl.c
++++ b/drivers/pci/hotplug/cpqphp_ctrl.c
+@@ -737,12 +737,12 @@ static struct pci_resource *get_resource(struct pci_resource **head, u32 size)
+
+ for (node = *head; node; node = node->next) {
+ dbg("%s: req_size =%x node=%p, base=%x, length=%x\n",
+- __FUNCTION__, size, node, node->base, node->length);
++ __func__, size, node, node->base, node->length);
+ if (node->length < size)
+ continue;
+
+ if (node->base & (size - 1)) {
+- dbg("%s: not aligned\n", __FUNCTION__);
++ dbg("%s: not aligned\n", __func__);
+ /* this one isn't base aligned properly
+ * so we'll make a new entry and split it up */
+ temp_dword = (node->base | (size-1)) + 1;
+@@ -767,7 +767,7 @@ static struct pci_resource *get_resource(struct pci_resource **head, u32 size)
+
+ /* Don't need to check if too small since we already did */
+ if (node->length > size) {
+- dbg("%s: too big\n", __FUNCTION__);
++ dbg("%s: too big\n", __func__);
+ /* this one is longer than we need
+ * so we'll make a new entry and split it up */
+ split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);
+@@ -784,7 +784,7 @@ static struct pci_resource *get_resource(struct pci_resource **head, u32 size)
+ node->next = split_node;
+ } /* End of too big on top end */
+
+- dbg("%s: got one!!!\n", __FUNCTION__);
++ dbg("%s: got one!!!\n", __func__);
+ /* If we got here, then it is the right size
+ * Now take it out of the list */
+ if (*head == node) {
+@@ -819,7 +819,7 @@ int cpqhp_resource_sort_and_combine(struct pci_resource **head)
+ struct pci_resource *node2;
+ int out_of_order = 1;
+
+- dbg("%s: head = %p, *head = %p\n", __FUNCTION__, head, *head);
++ dbg("%s: head = %p, *head = %p\n", __func__, head, *head);
+
+ if (!(*head))
+ return 1;
+@@ -907,7 +907,7 @@ irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data)
+ /* Read to clear posted writes */
+ misc = readw(ctrl->hpc_reg + MISC);
+
+- dbg ("%s - waking up\n", __FUNCTION__);
++ dbg ("%s - waking up\n", __func__);
+ wake_up_interruptible(&ctrl->queue);
+ }
+
+@@ -1421,7 +1421,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
+
+ hp_slot = func->device - ctrl->slot_device_offset;
+ dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n",
+- __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot);
++ __func__, func->device, ctrl->slot_device_offset, hp_slot);
+
+ mutex_lock(&ctrl->crit_sect);
+
+@@ -1466,55 +1466,55 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
+
+ /* turn on board and blink green LED */
+
+- dbg("%s: before down\n", __FUNCTION__);
++ dbg("%s: before down\n", __func__);
+ mutex_lock(&ctrl->crit_sect);
+- dbg("%s: after down\n", __FUNCTION__);
++ dbg("%s: after down\n", __func__);
+
+- dbg("%s: before slot_enable\n", __FUNCTION__);
++ dbg("%s: before slot_enable\n", __func__);
+ slot_enable (ctrl, hp_slot);
+
+- dbg("%s: before green_LED_blink\n", __FUNCTION__);
++ dbg("%s: before green_LED_blink\n", __func__);
+ green_LED_blink (ctrl, hp_slot);
+
+- dbg("%s: before amber_LED_blink\n", __FUNCTION__);
++ dbg("%s: before amber_LED_blink\n", __func__);
+ amber_LED_off (ctrl, hp_slot);
+
+- dbg("%s: before set_SOGO\n", __FUNCTION__);
++ dbg("%s: before set_SOGO\n", __func__);
+ set_SOGO(ctrl);
+
+ /* Wait for SOBS to be unset */
+- dbg("%s: before wait_for_ctrl_irq\n", __FUNCTION__);
++ dbg("%s: before wait_for_ctrl_irq\n", __func__);
+ wait_for_ctrl_irq (ctrl);
+- dbg("%s: after wait_for_ctrl_irq\n", __FUNCTION__);
++ dbg("%s: after wait_for_ctrl_irq\n", __func__);
+
+- dbg("%s: before up\n", __FUNCTION__);
++ dbg("%s: before up\n", __func__);
+ mutex_unlock(&ctrl->crit_sect);
+- dbg("%s: after up\n", __FUNCTION__);
++ dbg("%s: after up\n", __func__);
+
+ /* Wait for ~1 second because of hot plug spec */
+- dbg("%s: before long_delay\n", __FUNCTION__);
++ dbg("%s: before long_delay\n", __func__);
+ long_delay(1*HZ);
+- dbg("%s: after long_delay\n", __FUNCTION__);
++ dbg("%s: after long_delay\n", __func__);
+
+- dbg("%s: func status = %x\n", __FUNCTION__, func->status);
++ dbg("%s: func status = %x\n", __func__, func->status);
+ /* Check for a power fault */
+ if (func->status == 0xFF) {
+ /* power fault occurred, but it was benign */
+ temp_register = 0xFFFFFFFF;
+- dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register);
++ dbg("%s: temp register set to %x by power fault\n", __func__, temp_register);
+ rc = POWER_FAILURE;
+ func->status = 0;
+ } else {
+ /* Get vendor/device ID u32 */
+ ctrl->pci_bus->number = func->bus;
+ rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(func->device, func->function), PCI_VENDOR_ID, &temp_register);
+- dbg("%s: pci_read_config_dword returns %d\n", __FUNCTION__, rc);
+- dbg("%s: temp_register is %x\n", __FUNCTION__, temp_register);
++ dbg("%s: pci_read_config_dword returns %d\n", __func__, rc);
++ dbg("%s: temp_register is %x\n", __func__, temp_register);
+
+ if (rc != 0) {
+ /* Something's wrong here */
+ temp_register = 0xFFFFFFFF;
+- dbg("%s: temp register set to %x by error\n", __FUNCTION__, temp_register);
++ dbg("%s: temp register set to %x by error\n", __func__, temp_register);
+ }
+ /* Preset return code. It will be changed later if things go okay. */
+ rc = NO_ADAPTER_PRESENT;
+@@ -1530,7 +1530,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
+
+ rc = configure_new_device(ctrl, func, 0, &res_lists);
+
+- dbg("%s: back from configure_new_device\n", __FUNCTION__);
++ dbg("%s: back from configure_new_device\n", __func__);
+ ctrl->io_head = res_lists.io_head;
+ ctrl->mem_head = res_lists.mem_head;
+ ctrl->p_mem_head = res_lists.p_mem_head;
+@@ -1566,7 +1566,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
+
+ /* next, we will instantiate the linux pci_dev structures (with
+ * appropriate driver notification, if already present) */
+- dbg("%s: configure linux pci_dev structure\n", __FUNCTION__);
++ dbg("%s: configure linux pci_dev structure\n", __func__);
+ index = 0;
+ do {
+ new_slot = cpqhp_slot_find(ctrl->bus, func->device, index++);
+@@ -1628,7 +1628,7 @@ static u32 remove_board(struct pci_func * func, u32 replace_flag, struct control
+ device = func->device;
+
+ hp_slot = func->device - ctrl->slot_device_offset;
+- dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
++ dbg("In %s, hp_slot = %d\n", __func__, hp_slot);
+
+ /* When we get here, it is safe to change base address registers.
+ * We will attempt to save the base address register lengths */
+@@ -1928,7 +1928,7 @@ void cpqhp_pushbutton_thread(unsigned long slot)
+ func = cpqhp_slot_find(p_slot->bus, p_slot->device, 0);
+ dbg("In power_down_board, func = %p, ctrl = %p\n", func, ctrl);
+ if (!func) {
+- dbg("Error! func NULL in %s\n", __FUNCTION__);
++ dbg("Error! func NULL in %s\n", __func__);
+ return ;
+ }
+
+@@ -1950,7 +1950,7 @@ void cpqhp_pushbutton_thread(unsigned long slot)
+ func = cpqhp_slot_find(p_slot->bus, p_slot->device, 0);
+ dbg("In add_board, func = %p, ctrl = %p\n", func, ctrl);
+ if (!func) {
+- dbg("Error! func NULL in %s\n", __FUNCTION__);
++ dbg("Error! func NULL in %s\n", __func__);
+ return ;
+ }
+
+@@ -2058,7 +2058,7 @@ int cpqhp_process_SI(struct controller *ctrl, struct pci_func *func)
+ }
+
+ if (rc) {
+- dbg("%s: rc = %d\n", __FUNCTION__, rc);
++ dbg("%s: rc = %d\n", __func__, rc);
+ }
+
+ if (p_slot)
+@@ -2269,12 +2269,12 @@ static u32 configure_new_device(struct controller * ctrl, struct pci_func * func
+
+ new_slot = func;
+
+- dbg("%s\n", __FUNCTION__);
++ dbg("%s\n", __func__);
+ /* Check for Multi-function device */
+ ctrl->pci_bus->number = func->bus;
+ rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(func->device, func->function), 0x0E, &temp_byte);
+ if (rc) {
+- dbg("%s: rc = %d\n", __FUNCTION__, rc);
++ dbg("%s: rc = %d\n", __func__, rc);
+ return rc;
+ }
+
+diff --git a/drivers/pci/hotplug/cpqphp_nvram.c b/drivers/pci/hotplug/cpqphp_nvram.c
+index ae5e974..cb17488 100644
+--- a/drivers/pci/hotplug/cpqphp_nvram.c
++++ b/drivers/pci/hotplug/cpqphp_nvram.c
+@@ -160,7 +160,7 @@ static int check_for_compaq_ROM (void __iomem *rom_start)
+ (temp6 == 'Q')) {
+ result = 1;
+ }
+- dbg ("%s - returned %d\n", __FUNCTION__, result);
++ dbg ("%s - returned %d\n", __func__, result);
+ return result;
+ }
+
+diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c
+index 3f6cd20..0902193 100644
+--- a/drivers/pci/hotplug/cpqphp_pci.c
++++ b/drivers/pci/hotplug/cpqphp_pci.c
+@@ -120,7 +120,7 @@ int cpqhp_unconfigure_device(struct pci_func* func)
+ {
+ int j;
+
+- dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus, func->device, func->function);
++ dbg("%s: bus/dev/func = %x/%x/%x\n", __func__, func->bus, func->device, func->function);
+
+ for (j=0; j<8 ; j++) {
+ struct pci_dev* temp = pci_find_slot(func->bus, PCI_DEVFN(func->device, j));
+@@ -170,11 +170,11 @@ int cpqhp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
+ fakedev->bus = fakebus;
+ fakebus->number = bus_num;
+ dbg("%s: dev %d, bus %d, pin %d, num %d\n",
+- __FUNCTION__, dev_num, bus_num, int_pin, irq_num);
++ __func__, dev_num, bus_num, int_pin, irq_num);
+ rc = pcibios_set_irq_routing(fakedev, int_pin - 0x0a, irq_num);
+ kfree(fakedev);
+ kfree(fakebus);
+- dbg("%s: rc %d\n", __FUNCTION__, rc);
++ dbg("%s: rc %d\n", __func__, rc);
+ if (!rc)
+ return !rc;
+
+@@ -1423,7 +1423,7 @@ int cpqhp_return_board_resources(struct pci_func * func, struct resource_lists *
+ int rc = 0;
+ struct pci_resource *node;
+ struct pci_resource *t_node;
+- dbg("%s\n", __FUNCTION__);
++ dbg("%s\n", __func__);
+
+ if (!func)
+ return 1;
+diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c
+index 94b6401..7e9a827 100644
+--- a/drivers/pci/hotplug/fakephp.c
++++ b/drivers/pci/hotplug/fakephp.c
+@@ -293,7 +293,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
+ /* mis-use enable_slot for rescanning of the pci bus */
+ cancel_work_sync(&pci_rescan_work);
+ queue_work(dummyphp_wq, &pci_rescan_work);
+- return -ENODEV;
++ return 0;
+ }
+
+ /* find the hotplug_slot for the pci_dev */
+@@ -320,7 +320,7 @@ static int disable_slot(struct hotplug_slot *slot)
+ return -ENODEV;
+ dslot = slot->private;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, slot->name);
+
+ /* don't disable bridged devices just yet, we can't handle them easily... */
+ if (dslot->dev->subordinate) {
+diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
+index 87b6b8b..c892daa 100644
+--- a/drivers/pci/hotplug/ibmphp_core.c
++++ b/drivers/pci/hotplug/ibmphp_core.c
+@@ -148,8 +148,10 @@ int ibmphp_init_devno(struct slot **cur_slot)
+ len = (rtable->size - sizeof(struct irq_routing_table)) /
+ sizeof(struct irq_info);
+
+- if (!len)
++ if (!len) {
++ kfree(rtable);
+ return -1;
++ }
+ for (loop = 0; loop < len; loop++) {
+ if ((*cur_slot)->number == rtable->slots[loop].slot) {
+ if ((*cur_slot)->bus == rtable->slots[loop].bus) {
+@@ -187,11 +189,13 @@ int ibmphp_init_devno(struct slot **cur_slot)
+ debug("rtable->slots[loop].irq[3].link = %x\n",
+ rtable->slots[loop].irq[3].link);
+ debug("end of init_devno\n");
++ kfree(rtable);
+ return 0;
+ }
+ }
+ }
+
++ kfree(rtable);
+ return -1;
+ }
+
+@@ -395,7 +399,7 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
+ struct slot *pslot;
+ u8 mode = 0;
+
+- debug("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __FUNCTION__,
++ debug("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __func__,
+ hotplug_slot, value);
+
+ ibmphp_lock_operations();
+@@ -425,7 +429,7 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
+ }
+
+ ibmphp_unlock_operations();
+- debug("%s - Exit rc[%d] value[%x]\n", __FUNCTION__, rc, *value);
++ debug("%s - Exit rc[%d] value[%x]\n", __func__, rc, *value);
+ return rc;
+ }
+
+@@ -435,7 +439,7 @@ static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
+ struct slot *pslot;
+ u8 mode = 0;
+
+- debug("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __FUNCTION__,
++ debug("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __func__,
+ hotplug_slot, value);
+
+ ibmphp_lock_operations();
+@@ -471,7 +475,7 @@ static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
+ }
+
+ ibmphp_unlock_operations();
+- debug("%s - Exit rc[%d] value[%x]\n", __FUNCTION__, rc, *value);
++ debug("%s - Exit rc[%d] value[%x]\n", __func__, rc, *value);
+ return rc;
+ }
+
+@@ -741,13 +745,13 @@ static void free_slots(void)
+ struct list_head * tmp;
+ struct list_head * next;
+
+- debug("%s -- enter\n", __FUNCTION__);
++ debug("%s -- enter\n", __func__);
+
+ list_for_each_safe(tmp, next, &ibmphp_slot_head) {
+ slot_cur = list_entry(tmp, struct slot, ibm_slot_list);
+ pci_hp_deregister(slot_cur->hotplug_slot);
+ }
+- debug("%s -- exit\n", __FUNCTION__);
++ debug("%s -- exit\n", __func__);
+ }
+
+ static void ibm_unconfigure_device(struct pci_func *func)
+@@ -755,7 +759,7 @@ static void ibm_unconfigure_device(struct pci_func *func)
+ struct pci_dev *temp;
+ u8 j;
+
+- debug("inside %s\n", __FUNCTION__);
++ debug("inside %s\n", __func__);
+ debug("func->device = %x, func->function = %x\n",
+ func->device, func->function);
+ debug("func->device << 3 | 0x0 = %x\n", func->device << 3 | 0x0);
+@@ -786,13 +790,13 @@ static u8 bus_structure_fixup(u8 busno)
+
+ bus = kmalloc(sizeof(*bus), GFP_KERNEL);
+ if (!bus) {
+- err("%s - out of memory\n", __FUNCTION__);
++ err("%s - out of memory\n", __func__);
+ return 1;
+ }
+ dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev) {
+ kfree(bus);
+- err("%s - out of memory\n", __FUNCTION__);
++ err("%s - out of memory\n", __func__);
+ return 1;
+ }
+
+@@ -803,7 +807,7 @@ static u8 bus_structure_fixup(u8 busno)
+ if (!pci_read_config_word(dev, PCI_VENDOR_ID, &l) &&
+ (l != 0x0000) && (l != 0xffff)) {
+ debug("%s - Inside bus_struture_fixup()\n",
+- __FUNCTION__);
++ __func__);
+ pci_scan_bus(busno, ibmphp_pci_bus->ops, NULL);
+ break;
+ }
+@@ -900,7 +904,7 @@ static int set_bus(struct slot * slot_cur)
+ { },
+ };
+
+- debug("%s - entry slot # %d\n", __FUNCTION__, slot_cur->number);
++ debug("%s - entry slot # %d\n", __func__, slot_cur->number);
+ if (SET_BUS_STATUS(slot_cur->ctrl) && is_bus_empty(slot_cur)) {
+ rc = slot_update(&slot_cur);
+ if (rc)
+@@ -975,7 +979,7 @@ static int set_bus(struct slot * slot_cur)
+ /* This is for x440, once Brandon fixes the firmware,
+ will not need this delay */
+ msleep(1000);
+- debug("%s -Exit\n", __FUNCTION__);
++ debug("%s -Exit\n", __func__);
+ return 0;
+ }
+
+diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c
+index bbccde9..dca7efc 100644
+--- a/drivers/pci/hotplug/ibmphp_ebda.c
++++ b/drivers/pci/hotplug/ibmphp_ebda.c
+@@ -127,18 +127,18 @@ static void __init print_bus_info (void)
+
+ list_for_each (ptr1, &bus_info_head) {
+ ptr = list_entry (ptr1, struct bus_info, bus_info_list);
+- debug ("%s - slot_min = %x\n", __FUNCTION__, ptr->slot_min);
+- debug ("%s - slot_max = %x\n", __FUNCTION__, ptr->slot_max);
+- debug ("%s - slot_count = %x\n", __FUNCTION__, ptr->slot_count);
+- debug ("%s - bus# = %x\n", __FUNCTION__, ptr->busno);
+- debug ("%s - current_speed = %x\n", __FUNCTION__, ptr->current_speed);
+- debug ("%s - controller_id = %x\n", __FUNCTION__, ptr->controller_id);
++ debug ("%s - slot_min = %x\n", __func__, ptr->slot_min);
++ debug ("%s - slot_max = %x\n", __func__, ptr->slot_max);
++ debug ("%s - slot_count = %x\n", __func__, ptr->slot_count);
++ debug ("%s - bus# = %x\n", __func__, ptr->busno);
++ debug ("%s - current_speed = %x\n", __func__, ptr->current_speed);
++ debug ("%s - controller_id = %x\n", __func__, ptr->controller_id);
+
+- debug ("%s - slots_at_33_conv = %x\n", __FUNCTION__, ptr->slots_at_33_conv);
+- debug ("%s - slots_at_66_conv = %x\n", __FUNCTION__, ptr->slots_at_66_conv);
+- debug ("%s - slots_at_66_pcix = %x\n", __FUNCTION__, ptr->slots_at_66_pcix);
+- debug ("%s - slots_at_100_pcix = %x\n", __FUNCTION__, ptr->slots_at_100_pcix);
+- debug ("%s - slots_at_133_pcix = %x\n", __FUNCTION__, ptr->slots_at_133_pcix);
++ debug ("%s - slots_at_33_conv = %x\n", __func__, ptr->slots_at_33_conv);
++ debug ("%s - slots_at_66_conv = %x\n", __func__, ptr->slots_at_66_conv);
++ debug ("%s - slots_at_66_pcix = %x\n", __func__, ptr->slots_at_66_pcix);
++ debug ("%s - slots_at_100_pcix = %x\n", __func__, ptr->slots_at_100_pcix);
++ debug ("%s - slots_at_133_pcix = %x\n", __func__, ptr->slots_at_133_pcix);
+
+ }
+ }
+@@ -150,12 +150,12 @@ static void print_lo_info (void)
+ debug ("print_lo_info ----\n");
+ list_for_each (ptr1, &rio_lo_head) {
+ ptr = list_entry (ptr1, struct rio_detail, rio_detail_list);
+- debug ("%s - rio_node_id = %x\n", __FUNCTION__, ptr->rio_node_id);
+- debug ("%s - rio_type = %x\n", __FUNCTION__, ptr->rio_type);
+- debug ("%s - owner_id = %x\n", __FUNCTION__, ptr->owner_id);
+- debug ("%s - first_slot_num = %x\n", __FUNCTION__, ptr->first_slot_num);
+- debug ("%s - wpindex = %x\n", __FUNCTION__, ptr->wpindex);
+- debug ("%s - chassis_num = %x\n", __FUNCTION__, ptr->chassis_num);
++ debug ("%s - rio_node_id = %x\n", __func__, ptr->rio_node_id);
++ debug ("%s - rio_type = %x\n", __func__, ptr->rio_type);
++ debug ("%s - owner_id = %x\n", __func__, ptr->owner_id);
++ debug ("%s - first_slot_num = %x\n", __func__, ptr->first_slot_num);
++ debug ("%s - wpindex = %x\n", __func__, ptr->wpindex);
++ debug ("%s - chassis_num = %x\n", __func__, ptr->chassis_num);
+
+ }
+ }
+@@ -164,15 +164,15 @@ static void print_vg_info (void)
+ {
+ struct rio_detail *ptr;
+ struct list_head *ptr1;
+- debug ("%s ---\n", __FUNCTION__);
++ debug ("%s ---\n", __func__);
+ list_for_each (ptr1, &rio_vg_head) {
+ ptr = list_entry (ptr1, struct rio_detail, rio_detail_list);
+- debug ("%s - rio_node_id = %x\n", __FUNCTION__, ptr->rio_node_id);
+- debug ("%s - rio_type = %x\n", __FUNCTION__, ptr->rio_type);
+- debug ("%s - owner_id = %x\n", __FUNCTION__, ptr->owner_id);
+- debug ("%s - first_slot_num = %x\n", __FUNCTION__, ptr->first_slot_num);
+- debug ("%s - wpindex = %x\n", __FUNCTION__, ptr->wpindex);
+- debug ("%s - chassis_num = %x\n", __FUNCTION__, ptr->chassis_num);
++ debug ("%s - rio_node_id = %x\n", __func__, ptr->rio_node_id);
++ debug ("%s - rio_type = %x\n", __func__, ptr->rio_type);
++ debug ("%s - owner_id = %x\n", __func__, ptr->owner_id);
++ debug ("%s - first_slot_num = %x\n", __func__, ptr->first_slot_num);
++ debug ("%s - wpindex = %x\n", __func__, ptr->wpindex);
++ debug ("%s - chassis_num = %x\n", __func__, ptr->chassis_num);
+
+ }
+ }
+@@ -185,7 +185,7 @@ static void __init print_ebda_pci_rsrc (void)
+ list_for_each (ptr1, &ibmphp_ebda_pci_rsrc_head) {
+ ptr = list_entry (ptr1, struct ebda_pci_rsrc, ebda_pci_rsrc_list);
+ debug ("%s - rsrc type: %x bus#: %x dev_func: %x start addr: %x end addr: %x\n",
+- __FUNCTION__, ptr->rsrc_type ,ptr->bus_num, ptr->dev_fun,ptr->start_addr, ptr->end_addr);
++ __func__, ptr->rsrc_type ,ptr->bus_num, ptr->dev_fun,ptr->start_addr, ptr->end_addr);
+ }
+ }
+
+@@ -196,7 +196,7 @@ static void __init print_ibm_slot (void)
+
+ list_for_each (ptr1, &ibmphp_slot_head) {
+ ptr = list_entry (ptr1, struct slot, ibm_slot_list);
+- debug ("%s - slot_number: %x\n", __FUNCTION__, ptr->number);
++ debug ("%s - slot_number: %x\n", __func__, ptr->number);
+ }
+ }
+
+@@ -204,13 +204,13 @@ static void __init print_opt_vg (void)
+ {
+ struct opt_rio *ptr;
+ struct list_head *ptr1;
+- debug ("%s ---\n", __FUNCTION__);
++ debug ("%s ---\n", __func__);
+ list_for_each (ptr1, &opt_vg_head) {
+ ptr = list_entry (ptr1, struct opt_rio, opt_rio_list);
+- debug ("%s - rio_type %x\n", __FUNCTION__, ptr->rio_type);
+- debug ("%s - chassis_num: %x\n", __FUNCTION__, ptr->chassis_num);
+- debug ("%s - first_slot_num: %x\n", __FUNCTION__, ptr->first_slot_num);
+- debug ("%s - middle_num: %x\n", __FUNCTION__, ptr->middle_num);
++ debug ("%s - rio_type %x\n", __func__, ptr->rio_type);
++ debug ("%s - chassis_num: %x\n", __func__, ptr->chassis_num);
++ debug ("%s - first_slot_num: %x\n", __func__, ptr->first_slot_num);
++ debug ("%s - middle_num: %x\n", __func__, ptr->middle_num);
+ }
+ }
+
+@@ -225,35 +225,35 @@ static void __init print_ebda_hpc (void)
+ hpc_ptr = list_entry (ptr1, struct controller, ebda_hpc_list);
+
+ for (index = 0; index < hpc_ptr->slot_count; index++) {
+- debug ("%s - physical slot#: %x\n", __FUNCTION__, hpc_ptr->slots[index].slot_num);
+- debug ("%s - pci bus# of the slot: %x\n", __FUNCTION__, hpc_ptr->slots[index].slot_bus_num);
+- debug ("%s - index into ctlr addr: %x\n", __FUNCTION__, hpc_ptr->slots[index].ctl_index);
+- debug ("%s - cap of the slot: %x\n", __FUNCTION__, hpc_ptr->slots[index].slot_cap);
++ debug ("%s - physical slot#: %x\n", __func__, hpc_ptr->slots[index].slot_num);
++ debug ("%s - pci bus# of the slot: %x\n", __func__, hpc_ptr->slots[index].slot_bus_num);
++ debug ("%s - index into ctlr addr: %x\n", __func__, hpc_ptr->slots[index].ctl_index);
++ debug ("%s - cap of the slot: %x\n", __func__, hpc_ptr->slots[index].slot_cap);
+ }
+
+ for (index = 0; index < hpc_ptr->bus_count; index++) {
+- debug ("%s - bus# of each bus controlled by this ctlr: %x\n", __FUNCTION__, hpc_ptr->buses[index].bus_num);
++ debug ("%s - bus# of each bus controlled by this ctlr: %x\n", __func__, hpc_ptr->buses[index].bus_num);
+ }
+
+- debug ("%s - type of hpc: %x\n", __FUNCTION__, hpc_ptr->ctlr_type);
++ debug ("%s - type of hpc: %x\n", __func__, hpc_ptr->ctlr_type);
+ switch (hpc_ptr->ctlr_type) {
+ case 1:
+- debug ("%s - bus: %x\n", __FUNCTION__, hpc_ptr->u.pci_ctlr.bus);
+- debug ("%s - dev_fun: %x\n", __FUNCTION__, hpc_ptr->u.pci_ctlr.dev_fun);
+- debug ("%s - irq: %x\n", __FUNCTION__, hpc_ptr->irq);
++ debug ("%s - bus: %x\n", __func__, hpc_ptr->u.pci_ctlr.bus);
++ debug ("%s - dev_fun: %x\n", __func__, hpc_ptr->u.pci_ctlr.dev_fun);
++ debug ("%s - irq: %x\n", __func__, hpc_ptr->irq);
+ break;
+
+ case 0:
+- debug ("%s - io_start: %x\n", __FUNCTION__, hpc_ptr->u.isa_ctlr.io_start);
+- debug ("%s - io_end: %x\n", __FUNCTION__, hpc_ptr->u.isa_ctlr.io_end);
+- debug ("%s - irq: %x\n", __FUNCTION__, hpc_ptr->irq);
++ debug ("%s - io_start: %x\n", __func__, hpc_ptr->u.isa_ctlr.io_start);
++ debug ("%s - io_end: %x\n", __func__, hpc_ptr->u.isa_ctlr.io_end);
++ debug ("%s - irq: %x\n", __func__, hpc_ptr->irq);
+ break;
+
+ case 2:
+ case 4:
+- debug ("%s - wpegbbar: %lx\n", __FUNCTION__, hpc_ptr->u.wpeg_ctlr.wpegbbar);
+- debug ("%s - i2c_addr: %x\n", __FUNCTION__, hpc_ptr->u.wpeg_ctlr.i2c_addr);
+- debug ("%s - irq: %x\n", __FUNCTION__, hpc_ptr->irq);
++ debug ("%s - wpegbbar: %lx\n", __func__, hpc_ptr->u.wpeg_ctlr.wpegbbar);
++ debug ("%s - i2c_addr: %x\n", __func__, hpc_ptr->u.wpeg_ctlr.i2c_addr);
++ debug ("%s - irq: %x\n", __func__, hpc_ptr->irq);
+ break;
+ }
+ }
+diff --git a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c
+index c31e7bf..83f337c 100644
+--- a/drivers/pci/hotplug/ibmphp_hpc.c
++++ b/drivers/pci/hotplug/ibmphp_hpc.c
+@@ -129,14 +129,14 @@ static int hpc_wait_ctlr_notworking (int, struct controller *, void __iomem *, u
+ *---------------------------------------------------------------------*/
+ void __init ibmphp_hpc_initvars (void)
+ {
+- debug ("%s - Entry\n", __FUNCTION__);
++ debug ("%s - Entry\n", __func__);
+
+ mutex_init(&sem_hpcaccess);
+ init_MUTEX (&semOperations);
+ init_MUTEX_LOCKED (&sem_exit);
+ to_debug = 0;
+
+- debug ("%s - Exit\n", __FUNCTION__);
++ debug ("%s - Exit\n", __func__);
+ }
+
+ /*----------------------------------------------------------------------
+@@ -154,7 +154,7 @@ static u8 i2c_ctrl_read (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8
+ unsigned long ultemp;
+ unsigned long data; // actual data HILO format
+
+- debug_polling ("%s - Entry WPGBbar[%p] index[%x] \n", __FUNCTION__, WPGBbar, index);
++ debug_polling ("%s - Entry WPGBbar[%p] index[%x] \n", __func__, WPGBbar, index);
+
+ //--------------------------------------------------------------------
+ // READ - step 1
+@@ -213,7 +213,7 @@ static u8 i2c_ctrl_read (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8
+ i--;
+ }
+ if (i == 0) {
+- debug ("%s - Error : WPG timeout\n", __FUNCTION__);
++ debug ("%s - Error : WPG timeout\n", __func__);
+ return HPC_ERROR;
+ }
+ //--------------------------------------------------------------------
+@@ -241,7 +241,7 @@ static u8 i2c_ctrl_read (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8
+
+ status = (u8) data;
+
+- debug_polling ("%s - Exit index[%x] status[%x]\n", __FUNCTION__, index, status);
++ debug_polling ("%s - Exit index[%x] status[%x]\n", __func__, index, status);
+
+ return (status);
+ }
+@@ -262,7 +262,7 @@ static u8 i2c_ctrl_write (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8
+ unsigned long data; // actual data HILO format
+ int i;
+
+- debug_polling ("%s - Entry WPGBbar[%p] index[%x] cmd[%x]\n", __FUNCTION__, WPGBbar, index, cmd);
++ debug_polling ("%s - Entry WPGBbar[%p] index[%x] cmd[%x]\n", __func__, WPGBbar, index, cmd);
+
+ rc = 0;
+ //--------------------------------------------------------------------
+@@ -324,7 +324,7 @@ static u8 i2c_ctrl_write (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8
+ i--;
+ }
+ if (i == 0) {
+- debug ("%s - Exit Error:WPG timeout\n", __FUNCTION__);
++ debug ("%s - Exit Error:WPG timeout\n", __func__);
+ rc = HPC_ERROR;
+ }
+
+@@ -345,7 +345,7 @@ static u8 i2c_ctrl_write (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8
+ rc = HPC_ERROR;
+ }
+
+- debug_polling ("%s Exit rc[%x]\n", __FUNCTION__, rc);
++ debug_polling ("%s Exit rc[%x]\n", __func__, rc);
+ return (rc);
+ }
+
+@@ -541,12 +541,12 @@ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus)
+ int rc = 0;
+ int busindex;
+
+- debug_polling ("%s - Entry pslot[%p] cmd[%x] pstatus[%p]\n", __FUNCTION__, pslot, cmd, pstatus);
++ debug_polling ("%s - Entry pslot[%p] cmd[%x] pstatus[%p]\n", __func__, pslot, cmd, pstatus);
+
+ if ((pslot == NULL)
+ || ((pstatus == NULL) && (cmd != READ_ALLSTAT) && (cmd != READ_BUSSTATUS))) {
+ rc = -EINVAL;
+- err ("%s - Error invalid pointer, rc[%d]\n", __FUNCTION__, rc);
++ err ("%s - Error invalid pointer, rc[%d]\n", __func__, rc);
+ return rc;
+ }
+
+@@ -554,7 +554,7 @@ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus)
+ busindex = ibmphp_get_bus_index (pslot->bus);
+ if (busindex < 0) {
+ rc = -EINVAL;
+- err ("%s - Exit Error:invalid bus, rc[%d]\n", __FUNCTION__, rc);
++ err ("%s - Exit Error:invalid bus, rc[%d]\n", __func__, rc);
+ return rc;
+ } else
+ index = (u8) busindex;
+@@ -565,7 +565,7 @@ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus)
+
+ if (index == HPC_ERROR) {
+ rc = -EINVAL;
+- err ("%s - Exit Error:invalid index, rc[%d]\n", __FUNCTION__, rc);
++ err ("%s - Exit Error:invalid index, rc[%d]\n", __func__, rc);
+ return rc;
+ }
+
+@@ -641,7 +641,7 @@ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus)
+ ctrl_read (ctlr_ptr, wpg_bbar,
+ index + WPG_1ST_EXTSLOT_INDEX);
+ } else {
+- err ("%s - Error ctrl_read failed\n", __FUNCTION__);
++ err ("%s - Error ctrl_read failed\n", __func__);
+ rc = -EINVAL;
+ break;
+ }
+@@ -662,7 +662,7 @@ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus)
+
+ free_hpc_access ();
+
+- debug_polling ("%s - Exit rc[%d]\n", __FUNCTION__, rc);
++ debug_polling ("%s - Exit rc[%d]\n", __func__, rc);
+ return rc;
+ }
+
+@@ -681,10 +681,10 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd)
+ int rc = 0;
+ int timeout;
+
+- debug_polling ("%s - Entry pslot[%p] cmd[%x]\n", __FUNCTION__, pslot, cmd);
++ debug_polling ("%s - Entry pslot[%p] cmd[%x]\n", __func__, pslot, cmd);
+ if (pslot == NULL) {
+ rc = -EINVAL;
+- err ("%s - Error Exit rc[%d]\n", __FUNCTION__, rc);
++ err ("%s - Error Exit rc[%d]\n", __func__, rc);
+ return rc;
+ }
+
+@@ -694,7 +694,7 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd)
+ busindex = ibmphp_get_bus_index (pslot->bus);
+ if (busindex < 0) {
+ rc = -EINVAL;
+- err ("%s - Exit Error:invalid bus, rc[%d]\n", __FUNCTION__, rc);
++ err ("%s - Exit Error:invalid bus, rc[%d]\n", __func__, rc);
+ return rc;
+ } else
+ index = (u8) busindex;
+@@ -705,7 +705,7 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd)
+
+ if (index == HPC_ERROR) {
+ rc = -EINVAL;
+- err ("%s - Error Exit rc[%d]\n", __FUNCTION__, rc);
++ err ("%s - Error Exit rc[%d]\n", __func__, rc);
+ return rc;
+ }
+
+@@ -719,7 +719,7 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd)
+ if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4)) {
+ wpg_bbar = ioremap (ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE);
+
+- debug ("%s - ctlr id[%x] physical[%lx] logical[%lx] i2c[%x]\n", __FUNCTION__,
++ debug ("%s - ctlr id[%x] physical[%lx] logical[%lx] i2c[%x]\n", __func__,
+ ctlr_ptr->ctlr_id, (ulong) (ctlr_ptr->u.wpeg_ctlr.wpegbbar), (ulong) wpg_bbar,
+ ctlr_ptr->u.wpeg_ctlr.i2c_addr);
+ }
+@@ -750,7 +750,7 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd)
+ msleep(1000);
+ if (timeout < 1) {
+ done = 1;
+- err ("%s - Error command complete timeout\n", __FUNCTION__);
++ err ("%s - Error command complete timeout\n", __func__);
+ rc = -EFAULT;
+ } else
+ timeout--;
+@@ -765,7 +765,7 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd)
+ iounmap (wpg_bbar);
+ free_hpc_access ();
+
+- debug_polling ("%s - Exit rc[%d]\n", __FUNCTION__, rc);
++ debug_polling ("%s - Exit rc[%d]\n", __func__, rc);
+ return rc;
+ }
+
+@@ -803,10 +803,10 @@ void ibmphp_lock_operations (void)
+ *---------------------------------------------------------------------*/
+ void ibmphp_unlock_operations (void)
+ {
+- debug ("%s - Entry\n", __FUNCTION__);
++ debug ("%s - Entry\n", __func__);
+ up (&semOperations);
+ to_debug = 0;
+- debug ("%s - Exit\n", __FUNCTION__);
++ debug ("%s - Exit\n", __func__);
+ }
+
+ /*----------------------------------------------------------------------
+@@ -827,7 +827,7 @@ static int poll_hpc(void *data)
+ int poll_count = 0;
+ u8 ctrl_count = 0x00;
+
+- debug ("%s - Entry\n", __FUNCTION__);
++ debug ("%s - Entry\n", __func__);
+
+ while (!kthread_should_stop()) {
+ /* try to get the lock to do some kind of hardware access */
+@@ -907,7 +907,7 @@ static int poll_hpc(void *data)
+ msleep(100);
+ }
+ up (&sem_exit);
+- debug ("%s - Exit\n", __FUNCTION__);
++ debug ("%s - Exit\n", __func__);
+ return 0;
+ }
+
+@@ -999,7 +999,7 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot)
+ ibmphp_update_slot_info (pslot);
+ }
+
+- debug ("%s - Exit rc[%d] disable[%x] update[%x]\n", __FUNCTION__, rc, disable, update);
++ debug ("%s - Exit rc[%d] disable[%x] update[%x]\n", __func__, rc, disable, update);
+
+ return rc;
+ }
+@@ -1021,7 +1021,7 @@ static int process_changeinlatch (u8 old, u8 new, struct controller *ctrl)
+ u8 mask;
+ int rc = 0;
+
+- debug ("%s - Entry old[%x], new[%x]\n", __FUNCTION__, old, new);
++ debug ("%s - Entry old[%x], new[%x]\n", __func__, old, new);
+ // bit 0 reserved, 0 is LSB, check bit 1-6 for 6 slots
+
+ for (i = ctrl->starting_slot_num; i <= ctrl->ending_slot_num; i++) {
+@@ -1031,15 +1031,15 @@ static int process_changeinlatch (u8 old, u8 new, struct controller *ctrl)
+ if (pslot) {
+ memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot));
+ rc = ibmphp_hpc_readslot (pslot, READ_ALLSTAT, NULL);
+- debug ("%s - call process_changeinstatus for slot[%d]\n", __FUNCTION__, i);
++ debug ("%s - call process_changeinstatus for slot[%d]\n", __func__, i);
+ process_changeinstatus (pslot, &myslot);
+ } else {
+ rc = -EINVAL;
+- err ("%s - Error bad pointer for slot[%d]\n", __FUNCTION__, i);
++ err ("%s - Error bad pointer for slot[%d]\n", __func__, i);
+ }
+ }
+ }
+- debug ("%s - Exit rc[%d]\n", __FUNCTION__, rc);
++ debug ("%s - Exit rc[%d]\n", __func__, rc);
+ return rc;
+ }
+
+@@ -1050,11 +1050,11 @@ static int process_changeinlatch (u8 old, u8 new, struct controller *ctrl)
+ *---------------------------------------------------------------------*/
+ int __init ibmphp_hpc_start_poll_thread (void)
+ {
+- debug ("%s - Entry\n", __FUNCTION__);
++ debug ("%s - Entry\n", __func__);
+
+ ibmphp_poll_thread = kthread_run(poll_hpc, NULL, "hpc_poll");
+ if (IS_ERR(ibmphp_poll_thread)) {
+- err ("%s - Error, thread not started\n", __FUNCTION__);
++ err ("%s - Error, thread not started\n", __func__);
+ return PTR_ERR(ibmphp_poll_thread);
+ }
+ return 0;
+@@ -1067,7 +1067,7 @@ int __init ibmphp_hpc_start_poll_thread (void)
+ *---------------------------------------------------------------------*/
+ void __exit ibmphp_hpc_stop_poll_thread (void)
+ {
+- debug ("%s - Entry\n", __FUNCTION__);
++ debug ("%s - Entry\n", __func__);
+
+ kthread_stop(ibmphp_poll_thread);
+ debug ("before locking operations \n");
+@@ -1088,7 +1088,7 @@ void __exit ibmphp_hpc_stop_poll_thread (void)
+ up (&sem_exit);
+ debug ("after sem exit up\n");
+
+- debug ("%s - Exit\n", __FUNCTION__);
++ debug ("%s - Exit\n", __func__);
+ }
+
+ /*----------------------------------------------------------------------
+diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c
+index d8f05d7..7b09e16 100644
+--- a/drivers/pci/hotplug/ibmphp_pci.c
++++ b/drivers/pci/hotplug/ibmphp_pci.c
+@@ -364,7 +364,7 @@ static int configure_device (struct pci_func *func)
+ struct resource_node *pfmem[6];
+ unsigned int devfn;
+
+- debug ("%s - inside\n", __FUNCTION__);
++ debug ("%s - inside\n", __func__);
+
+ devfn = PCI_DEVFN(func->device, func->function);
+ ibmphp_pci_bus->number = func->busno;
+@@ -595,7 +595,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
+ u8 irq;
+ int retval;
+
+- debug ("%s - enter\n", __FUNCTION__);
++ debug ("%s - enter\n", __func__);
+
+ devfn = PCI_DEVFN(func->function, func->device);
+ ibmphp_pci_bus->number = func->busno;
+@@ -1234,7 +1234,7 @@ static int unconfigure_boot_device (u8 busno, u8 device, u8 function)
+ u32 tmp_address;
+ unsigned int devfn;
+
+- debug ("%s - enter\n", __FUNCTION__);
++ debug ("%s - enter\n", __func__);
+
+ bus = ibmphp_find_res_bus (busno);
+ if (!bus) {
+@@ -1351,7 +1351,7 @@ static int unconfigure_boot_bridge (u8 busno, u8 device, u8 function)
+ bus_no = (int) busno;
+ debug ("busno is %x\n", busno);
+ pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_PRIMARY_BUS, &pri_number);
+- debug ("%s - busno = %x, primary_number = %x\n", __FUNCTION__, busno, pri_number);
++ debug ("%s - busno = %x, primary_number = %x\n", __func__, busno, pri_number);
+
+ pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);
+ debug ("sec_number is %x\n", sec_number);
+@@ -1437,7 +1437,7 @@ static int unconfigure_boot_bridge (u8 busno, u8 device, u8 function)
+ }
+ } /* end of mem */
+ } /* end of for */
+- debug ("%s - exiting, returning success\n", __FUNCTION__);
++ debug ("%s - exiting, returning success\n", __func__);
+ return 0;
+ }
+
+@@ -1453,7 +1453,7 @@ static int unconfigure_boot_card (struct slot *slot_cur)
+ unsigned int devfn;
+ u8 valid_device = 0x00; /* To see if we are ever able to find valid device and read it */
+
+- debug ("%s - enter\n", __FUNCTION__);
++ debug ("%s - enter\n", __func__);
+
+ device = slot_cur->device;
+ busno = slot_cur->bus;
+@@ -1470,7 +1470,7 @@ static int unconfigure_boot_card (struct slot *slot_cur)
+ /* found correct device!!! */
+ ++valid_device;
+
+- debug ("%s - found correct device\n", __FUNCTION__);
++ debug ("%s - found correct device\n", __func__);
+
+ /* header: x x x x x x x x
+ * | |___________|=> 1=PPB bridge, 0=normal device, 2=CardBus Bridge
+@@ -1573,7 +1573,7 @@ int ibmphp_unconfigure_card (struct slot **slot_cur, int the_end)
+ struct pci_func *cur_func = NULL;
+ struct pci_func *temp_func;
+
+- debug ("%s - enter\n", __FUNCTION__);
++ debug ("%s - enter\n", __func__);
+
+ if (!the_end) {
+ /* Need to unconfigure the card */
+@@ -1624,7 +1624,7 @@ int ibmphp_unconfigure_card (struct slot **slot_cur, int the_end)
+
+ sl->func = NULL;
+ *slot_cur = sl;
+- debug ("%s - exit\n", __FUNCTION__);
++ debug ("%s - exit\n", __func__);
+ return 0;
+ }
+
+diff --git a/drivers/pci/hotplug/ibmphp_res.c b/drivers/pci/hotplug/ibmphp_res.c
+index 5636b1a..ec73294 100644
+--- a/drivers/pci/hotplug/ibmphp_res.c
++++ b/drivers/pci/hotplug/ibmphp_res.c
+@@ -563,7 +563,7 @@ static void fix_resources (struct bus_node *bus_cur)
+ struct range_node *range;
+ struct resource_node *res;
+
+- debug ("%s - bus_cur->busno = %d\n", __FUNCTION__, bus_cur->busno);
++ debug ("%s - bus_cur->busno = %d\n", __func__, bus_cur->busno);
+
+ if (bus_cur->needIOUpdate) {
+ res = bus_cur->firstIO;
+@@ -599,7 +599,7 @@ int ibmphp_add_resource (struct resource_node *res)
+ struct range_node *range_cur = NULL;
+ struct resource_node *res_start = NULL;
+
+- debug ("%s - enter\n", __FUNCTION__);
++ debug ("%s - enter\n", __func__);
+
+ if (!res) {
+ err ("NULL passed to add\n");
+@@ -762,7 +762,7 @@ int ibmphp_add_resource (struct resource_node *res)
+ }
+ }
+
+- debug ("%s - exit\n", __FUNCTION__);
++ debug ("%s - exit\n", __func__);
+ return 0;
+ }
+
+@@ -1001,7 +1001,7 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge)
+ return -EINVAL;
+ }
+
+- debug ("%s - enter\n", __FUNCTION__);
++ debug ("%s - enter\n", __func__);
+ debug ("bus_cur->busno is %d\n", bus_cur->busno);
+
+ /* This is a quick fix to not mess up with the code very much. i.e.,
+@@ -1029,7 +1029,7 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge)
+
+ while (res_cur) {
+ range = find_range (bus_cur, res_cur);
+- debug ("%s - rangeno = %d\n", __FUNCTION__, res_cur->rangeno);
++ debug ("%s - rangeno = %d\n", __func__, res_cur->rangeno);
+
+ if (!range) {
+ err ("no range for the device exists... bailing out...\n");
+@@ -1942,7 +1942,7 @@ static int __init update_bridge_ranges (struct bus_node **bus)
+ return -ENODEV;
+ ibmphp_pci_bus->number = bus_cur->busno;
+
+- debug ("inside %s\n", __FUNCTION__);
++ debug ("inside %s\n", __func__);
+ debug ("bus_cur->busno = %x\n", bus_cur->busno);
+
+ for (device = 0; device < 32; device++) {
+diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
+index dd59a05..925ba16 100644
+--- a/drivers/pci/hotplug/pci_hotplug_core.c
++++ b/drivers/pci/hotplug/pci_hotplug_core.c
+@@ -43,7 +43,7 @@
+
+ #define MY_NAME "pci_hotplug"
+
+-#define dbg(fmt, arg...) do { if (debug) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __FUNCTION__ , ## arg); } while (0)
++#define dbg(fmt, arg...) do { if (debug) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __func__ , ## arg); } while (0)
+ #define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
+ #define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
+ #define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
+diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
+index ca656b2..f14267e 100644
+--- a/drivers/pci/hotplug/pciehp.h
++++ b/drivers/pci/hotplug/pciehp.h
+@@ -168,7 +168,7 @@ static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
+ return slot;
+ }
+
+- err("%s: slot (device=0x%x) not found\n", __FUNCTION__, device);
++ err("%s: slot (device=0x%x) not found\n", __func__, device);
+ return NULL;
+ }
+
+diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
+index 5fa4ba0..aee19f0 100644
+--- a/drivers/pci/hotplug/pciehp_core.c
++++ b/drivers/pci/hotplug/pciehp_core.c
+@@ -184,7 +184,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
+ {
+ struct slot *slot = hotplug_slot->private;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ kfree(slot->hotplug_slot->info);
+ kfree(slot->hotplug_slot);
+@@ -301,7 +301,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
+ {
+ struct slot *slot = hotplug_slot->private;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ hotplug_slot->info->attention_status = status;
+
+@@ -316,7 +316,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
+ {
+ struct slot *slot = hotplug_slot->private;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ return pciehp_sysfs_enable_slot(slot);
+ }
+@@ -326,7 +326,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
+ {
+ struct slot *slot = hotplug_slot->private;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ return pciehp_sysfs_disable_slot(slot);
+ }
+@@ -336,7 +336,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ struct slot *slot = hotplug_slot->private;
+ int retval;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ retval = slot->hpc_ops->get_power_status(slot, value);
+ if (retval < 0)
+@@ -350,7 +350,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ struct slot *slot = hotplug_slot->private;
+ int retval;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ retval = slot->hpc_ops->get_attention_status(slot, value);
+ if (retval < 0)
+@@ -364,7 +364,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ struct slot *slot = hotplug_slot->private;
+ int retval;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ retval = slot->hpc_ops->get_latch_status(slot, value);
+ if (retval < 0)
+@@ -378,7 +378,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ struct slot *slot = hotplug_slot->private;
+ int retval;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ retval = slot->hpc_ops->get_adapter_status(slot, value);
+ if (retval < 0)
+@@ -392,7 +392,7 @@ static int get_address(struct hotplug_slot *hotplug_slot, u32 *value)
+ struct slot *slot = hotplug_slot->private;
+ struct pci_bus *bus = slot->ctrl->pci_dev->subordinate;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ *value = (pci_domain_nr(bus) << 16) | (slot->bus << 8) | slot->device;
+
+@@ -404,7 +404,7 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
+ struct slot *slot = hotplug_slot->private;
+ int retval;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ retval = slot->hpc_ops->get_max_bus_speed(slot, value);
+ if (retval < 0)
+@@ -418,7 +418,7 @@ static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
+ struct slot *slot = hotplug_slot->private;
+ int retval;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ retval = slot->hpc_ops->get_cur_bus_speed(slot, value);
+ if (retval < 0)
+@@ -437,7 +437,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
+
+ ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
+ if (!ctrl) {
+- err("%s : out of memory\n", __FUNCTION__);
++ err("%s : out of memory\n", __func__);
+ goto err_out_none;
+ }
+ INIT_LIST_HEAD(&ctrl->slot_list);
+@@ -454,7 +454,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
+ pci_set_drvdata(pdev, ctrl);
+
+ dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n",
+- __FUNCTION__, pdev->bus->number, PCI_SLOT(pdev->devfn),
++ __func__, pdev->bus->number, PCI_SLOT(pdev->devfn),
+ PCI_FUNC(pdev->devfn), pdev->irq);
+
+ /* Setup the slot information structures */
+@@ -503,13 +503,13 @@ static void pciehp_remove (struct pcie_device *dev)
+ #ifdef CONFIG_PM
+ static int pciehp_suspend (struct pcie_device *dev, pm_message_t state)
+ {
+- printk("%s ENTRY\n", __FUNCTION__);
++ printk("%s ENTRY\n", __func__);
+ return 0;
+ }
+
+ static int pciehp_resume (struct pcie_device *dev)
+ {
+- printk("%s ENTRY\n", __FUNCTION__);
++ printk("%s ENTRY\n", __func__);
+ if (pciehp_force) {
+ struct pci_dev *pdev = dev->port;
+ struct controller *ctrl = pci_get_drvdata(pdev);
+@@ -563,7 +563,7 @@ static int __init pcied_init(void)
+ dbg("pcie_port_service_register = %d\n", retval);
+ info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
+ if (retval)
+- dbg("%s: Failure to register service\n", __FUNCTION__);
++ dbg("%s: Failure to register service\n", __func__);
+ return retval;
+ }
+
+diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
+index b23061c..0c481f7 100644
+--- a/drivers/pci/hotplug/pciehp_ctrl.c
++++ b/drivers/pci/hotplug/pciehp_ctrl.c
+@@ -181,7 +181,7 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
+ if (POWER_CTRL(ctrl->ctrlcap)) {
+ if (pslot->hpc_ops->power_off_slot(pslot)) {
+ err("%s: Issue of Slot Power Off command failed\n",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+ }
+@@ -192,7 +192,7 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
+ if (ATTN_LED(ctrl->ctrlcap)) {
+ if (pslot->hpc_ops->set_attention_status(pslot, 1)) {
+ err("%s: Issue of Set Attention Led command failed\n",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+ }
+@@ -211,7 +211,7 @@ static int board_added(struct slot *p_slot)
+ struct controller *ctrl = p_slot->ctrl;
+
+ dbg("%s: slot device, slot offset, hp slot = %d, %d ,%d\n",
+- __FUNCTION__, p_slot->device,
++ __func__, p_slot->device,
+ ctrl->slot_device_offset, p_slot->hp_slot);
+
+ if (POWER_CTRL(ctrl->ctrlcap)) {
+@@ -230,14 +230,14 @@ static int board_added(struct slot *p_slot)
+ /* Check link training status */
+ retval = p_slot->hpc_ops->check_lnk_status(ctrl);
+ if (retval) {
+- err("%s: Failed to check link status\n", __FUNCTION__);
++ err("%s: Failed to check link status\n", __func__);
+ set_slot_off(ctrl, p_slot);
+ return retval;
+ }
+
+ /* Check for a power fault */
+ if (p_slot->hpc_ops->query_power_fault(p_slot)) {
+- dbg("%s: power fault detected\n", __FUNCTION__);
++ dbg("%s: power fault detected\n", __func__);
+ retval = POWER_FAILURE;
+ goto err_exit;
+ }
+@@ -277,14 +277,14 @@ static int remove_board(struct slot *p_slot)
+ if (retval)
+ return retval;
+
+- dbg("In %s, hp_slot = %d\n", __FUNCTION__, p_slot->hp_slot);
++ dbg("In %s, hp_slot = %d\n", __func__, p_slot->hp_slot);
+
+ if (POWER_CTRL(ctrl->ctrlcap)) {
+ /* power off slot */
+ retval = p_slot->hpc_ops->power_off_slot(p_slot);
+ if (retval) {
+ err("%s: Issue of Slot Disable command failed\n",
+- __FUNCTION__);
++ __func__);
+ return retval;
+ }
+ }
+@@ -319,7 +319,7 @@ static void pciehp_power_thread(struct work_struct *work)
+ case POWEROFF_STATE:
+ mutex_unlock(&p_slot->lock);
+ dbg("%s: disabling bus:device(%x:%x)\n",
+- __FUNCTION__, p_slot->bus, p_slot->device);
++ __func__, p_slot->bus, p_slot->device);
+ pciehp_disable_slot(p_slot);
+ mutex_lock(&p_slot->lock);
+ p_slot->state = STATIC_STATE;
+@@ -347,7 +347,7 @@ void pciehp_queue_pushbutton_work(struct work_struct *work)
+
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (!info) {
+- err("%s: Cannot allocate memory\n", __FUNCTION__);
++ err("%s: Cannot allocate memory\n", __func__);
+ return;
+ }
+ info->p_slot = p_slot;
+@@ -424,7 +424,7 @@ static void handle_button_press_event(struct slot *p_slot)
+ * expires to cancel hot-add or hot-remove
+ */
+ info("Button cancel on Slot(%s)\n", p_slot->name);
+- dbg("%s: button cancel\n", __FUNCTION__);
++ dbg("%s: button cancel\n", __func__);
+ cancel_delayed_work(&p_slot->work);
+ if (p_slot->state == BLINKINGOFF_STATE) {
+ if (PWR_LED(ctrl->ctrlcap))
+@@ -465,7 +465,7 @@ static void handle_surprise_event(struct slot *p_slot)
+
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (!info) {
+- err("%s: Cannot allocate memory\n", __FUNCTION__);
++ err("%s: Cannot allocate memory\n", __func__);
+ return;
+ }
+ info->p_slot = p_slot;
+@@ -526,7 +526,7 @@ int pciehp_enable_slot(struct slot *p_slot)
+
+ rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
+ if (rc || !getstatus) {
+- info("%s: no adapter on slot(%s)\n", __FUNCTION__,
++ info("%s: no adapter on slot(%s)\n", __func__,
+ p_slot->name);
+ mutex_unlock(&p_slot->ctrl->crit_sect);
+ return -ENODEV;
+@@ -534,7 +534,7 @@ int pciehp_enable_slot(struct slot *p_slot)
+ if (MRL_SENS(p_slot->ctrl->ctrlcap)) {
+ rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+ if (rc || getstatus) {
+- info("%s: latch open on slot(%s)\n", __FUNCTION__,
++ info("%s: latch open on slot(%s)\n", __func__,
+ p_slot->name);
+ mutex_unlock(&p_slot->ctrl->crit_sect);
+ return -ENODEV;
+@@ -544,7 +544,7 @@ int pciehp_enable_slot(struct slot *p_slot)
+ if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {
+ rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
+ if (rc || getstatus) {
+- info("%s: already enabled on slot(%s)\n", __FUNCTION__,
++ info("%s: already enabled on slot(%s)\n", __func__,
+ p_slot->name);
+ mutex_unlock(&p_slot->ctrl->crit_sect);
+ return -EINVAL;
+@@ -579,7 +579,7 @@ int pciehp_disable_slot(struct slot *p_slot)
+ if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) {
+ ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
+ if (ret || !getstatus) {
+- info("%s: no adapter on slot(%s)\n", __FUNCTION__,
++ info("%s: no adapter on slot(%s)\n", __func__,
+ p_slot->name);
+ mutex_unlock(&p_slot->ctrl->crit_sect);
+ return -ENODEV;
+@@ -589,7 +589,7 @@ int pciehp_disable_slot(struct slot *p_slot)
+ if (MRL_SENS(p_slot->ctrl->ctrlcap)) {
+ ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+ if (ret || getstatus) {
+- info("%s: latch open on slot(%s)\n", __FUNCTION__,
++ info("%s: latch open on slot(%s)\n", __func__,
+ p_slot->name);
+ mutex_unlock(&p_slot->ctrl->crit_sect);
+ return -ENODEV;
+@@ -599,7 +599,7 @@ int pciehp_disable_slot(struct slot *p_slot)
+ if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {
+ ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
+ if (ret || !getstatus) {
+- info("%s: already disabled slot(%s)\n", __FUNCTION__,
++ info("%s: already disabled slot(%s)\n", __func__,
+ p_slot->name);
+ mutex_unlock(&p_slot->ctrl->crit_sect);
+ return -EINVAL;
+diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
+index 698975a..b4bbd07 100644
+--- a/drivers/pci/hotplug/pciehp_hpc.c
++++ b/drivers/pci/hotplug/pciehp_hpc.c
+@@ -258,7 +258,7 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
+
+ retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ if (retval) {
+- err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
++ err("%s: Cannot read SLOTSTATUS register\n", __func__);
+ goto out;
+ }
+
+@@ -267,13 +267,13 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
+ proceed forward to issue the next command according
+ to spec. Just print out the error message */
+ dbg("%s: CMD_COMPLETED not clear after 1 sec.\n",
+- __FUNCTION__);
++ __func__);
+ }
+
+ spin_lock_irqsave(&ctrl->lock, flags);
+ retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
+ if (retval) {
+- err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
++ err("%s: Cannot read SLOTCTRL register\n", __func__);
+ goto out_spin_unlock;
+ }
+
+@@ -283,7 +283,7 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
+ ctrl->cmd_busy = 1;
+ retval = pciehp_writew(ctrl, SLOTCTRL, slot_ctrl);
+ if (retval)
+- err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
++ err("%s: Cannot write to SLOTCTRL register\n", __func__);
+
+ out_spin_unlock:
+ spin_unlock_irqrestore(&ctrl->lock, flags);
+@@ -305,14 +305,14 @@ static int hpc_check_lnk_status(struct controller *ctrl)
+
+ retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);
+ if (retval) {
+- err("%s: Cannot read LNKSTATUS register\n", __FUNCTION__);
++ err("%s: Cannot read LNKSTATUS register\n", __func__);
+ return retval;
+ }
+
+- dbg("%s: lnk_status = %x\n", __FUNCTION__, lnk_status);
++ dbg("%s: lnk_status = %x\n", __func__, lnk_status);
+ if ( (lnk_status & LNK_TRN) || (lnk_status & LNK_TRN_ERR) ||
+ !(lnk_status & NEG_LINK_WD)) {
+- err("%s : Link Training Error occurs \n", __FUNCTION__);
++ err("%s : Link Training Error occurs \n", __func__);
+ retval = -1;
+ return retval;
+ }
+@@ -329,12 +329,12 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status)
+
+ retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
+ if (retval) {
+- err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
++ err("%s: Cannot read SLOTCTRL register\n", __func__);
+ return retval;
+ }
+
+ dbg("%s: SLOTCTRL %x, value read %x\n",
+- __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
++ __func__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
+
+ atten_led_state = (slot_ctrl & ATTN_LED_CTRL) >> 6;
+
+@@ -368,11 +368,11 @@ static int hpc_get_power_status(struct slot *slot, u8 *status)
+
+ retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
+ if (retval) {
+- err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
++ err("%s: Cannot read SLOTCTRL register\n", __func__);
+ return retval;
+ }
+ dbg("%s: SLOTCTRL %x value read %x\n",
+- __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
++ __func__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
+
+ pwr_state = (slot_ctrl & PWR_CTRL) >> 10;
+
+@@ -399,7 +399,7 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status)
+
+ retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ if (retval) {
+- err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
++ err("%s: Cannot read SLOTSTATUS register\n", __func__);
+ return retval;
+ }
+
+@@ -417,7 +417,7 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status)
+
+ retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ if (retval) {
+- err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
++ err("%s: Cannot read SLOTSTATUS register\n", __func__);
+ return retval;
+ }
+ card_state = (u8)((slot_status & PRSN_STATE) >> 6);
+@@ -435,7 +435,7 @@ static int hpc_query_power_fault(struct slot *slot)
+
+ retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ if (retval) {
+- err("%s: Cannot check for power fault\n", __FUNCTION__);
++ err("%s: Cannot check for power fault\n", __func__);
+ return retval;
+ }
+ pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1);
+@@ -451,7 +451,7 @@ static int hpc_get_emi_status(struct slot *slot, u8 *status)
+
+ retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ if (retval) {
+- err("%s : Cannot check EMI status\n", __FUNCTION__);
++ err("%s : Cannot check EMI status\n", __func__);
+ return retval;
+ }
+ *status = (slot_status & EMI_STATE) >> EMI_STATUS_BIT;
+@@ -506,7 +506,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
+
+ rc = pcie_write_cmd(slot, slot_cmd, cmd_mask);
+ dbg("%s: SLOTCTRL %x write cmd %x\n",
+- __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
++ __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+
+ return rc;
+ }
+@@ -527,7 +527,7 @@ static void hpc_set_green_led_on(struct slot *slot)
+ pcie_write_cmd(slot, slot_cmd, cmd_mask);
+
+ dbg("%s: SLOTCTRL %x write cmd %x\n",
+- __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
++ __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+ }
+
+ static void hpc_set_green_led_off(struct slot *slot)
+@@ -545,7 +545,7 @@ static void hpc_set_green_led_off(struct slot *slot)
+
+ pcie_write_cmd(slot, slot_cmd, cmd_mask);
+ dbg("%s: SLOTCTRL %x write cmd %x\n",
+- __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
++ __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+ }
+
+ static void hpc_set_green_led_blink(struct slot *slot)
+@@ -564,7 +564,7 @@ static void hpc_set_green_led_blink(struct slot *slot)
+ pcie_write_cmd(slot, slot_cmd, cmd_mask);
+
+ dbg("%s: SLOTCTRL %x write cmd %x\n",
+- __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
++ __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+ }
+
+ static void hpc_release_ctlr(struct controller *ctrl)
+@@ -590,12 +590,12 @@ static int hpc_power_on_slot(struct slot * slot)
+ u16 slot_status;
+ int retval = 0;
+
+- dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot);
++ dbg("%s: slot->hp_slot %x\n", __func__, slot->hp_slot);
+
+ /* Clear sticky power-fault bit from previous power failures */
+ retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ if (retval) {
+- err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
++ err("%s: Cannot read SLOTSTATUS register\n", __func__);
+ return retval;
+ }
+ slot_status &= PWR_FAULT_DETECTED;
+@@ -603,7 +603,7 @@ static int hpc_power_on_slot(struct slot * slot)
+ retval = pciehp_writew(ctrl, SLOTSTATUS, slot_status);
+ if (retval) {
+ err("%s: Cannot write to SLOTSTATUS register\n",
+- __FUNCTION__);
++ __func__);
+ return retval;
+ }
+ }
+@@ -627,11 +627,11 @@ static int hpc_power_on_slot(struct slot * slot)
+ retval = pcie_write_cmd(slot, slot_cmd, cmd_mask);
+
+ if (retval) {
+- err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd);
++ err("%s: Write %x command failed!\n", __func__, slot_cmd);
+ return -1;
+ }
+ dbg("%s: SLOTCTRL %x write cmd %x\n",
+- __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
++ __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+
+ return retval;
+ }
+@@ -677,7 +677,7 @@ static int hpc_power_off_slot(struct slot * slot)
+ int retval = 0;
+ int changed;
+
+- dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot);
++ dbg("%s: slot->hp_slot %x\n", __func__, slot->hp_slot);
+
+ /*
+ * Set Bad DLLP Mask bit in Correctable Error Mask
+@@ -710,12 +710,12 @@ static int hpc_power_off_slot(struct slot * slot)
+
+ retval = pcie_write_cmd(slot, slot_cmd, cmd_mask);
+ if (retval) {
+- err("%s: Write command failed!\n", __FUNCTION__);
++ err("%s: Write command failed!\n", __func__);
+ retval = -1;
+ goto out;
+ }
+ dbg("%s: SLOTCTRL %x write cmd %x\n",
+- __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
++ __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+
+ /*
+ * After turning power off, we must wait for at least 1 second
+@@ -741,7 +741,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
+
+ rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ if (rc) {
+- err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
++ err("%s: Cannot read SLOTSTATUS register\n", __func__);
+ return IRQ_NONE;
+ }
+
+@@ -754,26 +754,26 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
+ if ( !intr_loc )
+ return IRQ_NONE;
+
+- dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc);
++ dbg("%s: intr_loc %x\n", __func__, intr_loc);
+ /* Mask Hot-plug Interrupt Enable */
+ if (!pciehp_poll_mode) {
+ spin_lock_irqsave(&ctrl->lock, flags);
+ rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+ if (rc) {
+ err("%s: Cannot read SLOT_CTRL register\n",
+- __FUNCTION__);
++ __func__);
+ spin_unlock_irqrestore(&ctrl->lock, flags);
+ return IRQ_NONE;
+ }
+
+ dbg("%s: pciehp_readw(SLOTCTRL) with value %x\n",
+- __FUNCTION__, temp_word);
++ __func__, temp_word);
+ temp_word = (temp_word & ~HP_INTR_ENABLE &
+ ~CMD_CMPL_INTR_ENABLE) | 0x00;
+ rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+ if (rc) {
+ err("%s: Cannot write to SLOTCTRL register\n",
+- __FUNCTION__);
++ __func__);
+ spin_unlock_irqrestore(&ctrl->lock, flags);
+ return IRQ_NONE;
+ }
+@@ -782,18 +782,18 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
+ rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ if (rc) {
+ err("%s: Cannot read SLOT_STATUS register\n",
+- __FUNCTION__);
++ __func__);
+ return IRQ_NONE;
+ }
+ dbg("%s: pciehp_readw(SLOTSTATUS) with value %x\n",
+- __FUNCTION__, slot_status);
++ __func__, slot_status);
+
+ /* Clear command complete interrupt caused by this write */
+ temp_word = 0x1f;
+ rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
+ if (rc) {
+ err("%s: Cannot write to SLOTSTATUS register\n",
+- __FUNCTION__);
++ __func__);
+ return IRQ_NONE;
+ }
+ }
+@@ -822,7 +822,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
+ temp_word = 0x1F;
+ rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
+ if (rc) {
+- err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
++ err("%s: Cannot write to SLOTSTATUS register\n", __func__);
+ return IRQ_NONE;
+ }
+ /* Unmask Hot-plug Interrupt Enable */
+@@ -831,18 +831,18 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
+ rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+ if (rc) {
+ err("%s: Cannot read SLOTCTRL register\n",
+- __FUNCTION__);
++ __func__);
+ spin_unlock_irqrestore(&ctrl->lock, flags);
+ return IRQ_NONE;
+ }
+
+- dbg("%s: Unmask Hot-plug Interrupt Enable\n", __FUNCTION__);
++ dbg("%s: Unmask Hot-plug Interrupt Enable\n", __func__);
+ temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
+
+ rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+ if (rc) {
+ err("%s: Cannot write to SLOTCTRL register\n",
+- __FUNCTION__);
++ __func__);
+ spin_unlock_irqrestore(&ctrl->lock, flags);
+ return IRQ_NONE;
+ }
+@@ -851,7 +851,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
+ rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ if (rc) {
+ err("%s: Cannot read SLOT_STATUS register\n",
+- __FUNCTION__);
++ __func__);
+ return IRQ_NONE;
+ }
+
+@@ -860,11 +860,11 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
+ rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
+ if (rc) {
+ err("%s: Cannot write to SLOTSTATUS failed\n",
+- __FUNCTION__);
++ __func__);
+ return IRQ_NONE;
+ }
+ dbg("%s: pciehp_writew(SLOTSTATUS) with value %x\n",
+- __FUNCTION__, temp_word);
++ __func__, temp_word);
+ }
+
+ return IRQ_HANDLED;
+@@ -879,7 +879,7 @@ static int hpc_get_max_lnk_speed(struct slot *slot, enum pci_bus_speed *value)
+
+ retval = pciehp_readl(ctrl, LNKCAP, &lnk_cap);
+ if (retval) {
+- err("%s: Cannot read LNKCAP register\n", __FUNCTION__);
++ err("%s: Cannot read LNKCAP register\n", __func__);
+ return retval;
+ }
+
+@@ -908,7 +908,7 @@ static int hpc_get_max_lnk_width(struct slot *slot,
+
+ retval = pciehp_readl(ctrl, LNKCAP, &lnk_cap);
+ if (retval) {
+- err("%s: Cannot read LNKCAP register\n", __FUNCTION__);
++ err("%s: Cannot read LNKCAP register\n", __func__);
+ return retval;
+ }
+
+@@ -957,7 +957,7 @@ static int hpc_get_cur_lnk_speed(struct slot *slot, enum pci_bus_speed *value)
+
+ retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);
+ if (retval) {
+- err("%s: Cannot read LNKSTATUS register\n", __FUNCTION__);
++ err("%s: Cannot read LNKSTATUS register\n", __func__);
+ return retval;
+ }
+
+@@ -986,7 +986,7 @@ static int hpc_get_cur_lnk_width(struct slot *slot,
+
+ retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);
+ if (retval) {
+- err("%s: Cannot read LNKSTATUS register\n", __FUNCTION__);
++ err("%s: Cannot read LNKSTATUS register\n", __func__);
+ return retval;
+ }
+
+@@ -1130,38 +1130,38 @@ static int pcie_init_hardware_part1(struct controller *ctrl,
+
+ rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
+ if (rc) {
+- err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
++ err("%s: Cannot read SLOTCAP register\n", __func__);
+ return -1;
+ }
+
+ /* Mask Hot-plug Interrupt Enable */
+ rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+ if (rc) {
+- err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
++ err("%s: Cannot read SLOTCTRL register\n", __func__);
+ return -1;
+ }
+
+ dbg("%s: SLOTCTRL %x value read %x\n",
+- __FUNCTION__, ctrl->cap_base + SLOTCTRL, temp_word);
++ __func__, ctrl->cap_base + SLOTCTRL, temp_word);
+ temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) |
+ 0x00;
+
+ rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+ if (rc) {
+- err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
++ err("%s: Cannot write to SLOTCTRL register\n", __func__);
+ return -1;
+ }
+
+ rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ if (rc) {
+- err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
++ err("%s: Cannot read SLOTSTATUS register\n", __func__);
+ return -1;
+ }
+
+ temp_word = 0x1F; /* Clear all events */
+ rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
+ if (rc) {
+- err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
++ err("%s: Cannot write to SLOTSTATUS register\n", __func__);
+ return -1;
+ }
+ return 0;
+@@ -1177,7 +1177,7 @@ int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
+
+ rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+ if (rc) {
+- err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
++ err("%s: Cannot read SLOTCTRL register\n", __func__);
+ goto abort;
+ }
+
+@@ -1185,7 +1185,7 @@ int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
+
+ rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
+ if (rc) {
+- err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
++ err("%s: Cannot read SLOTCAP register\n", __func__);
+ goto abort;
+ }
+
+@@ -1212,19 +1212,19 @@ int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
+ */
+ rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+ if (rc) {
+- err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
++ err("%s: Cannot write to SLOTCTRL register\n", __func__);
+ goto abort;
+ }
+ rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ if (rc) {
+- err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
++ err("%s: Cannot read SLOTSTATUS register\n", __func__);
+ goto abort_disable_intr;
+ }
+
+ temp_word = 0x1F; /* Clear all events */
+ rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
+ if (rc) {
+- err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
++ err("%s: Cannot write to SLOTSTATUS register\n", __func__);
+ goto abort_disable_intr;
+ }
+
+@@ -1247,7 +1247,7 @@ abort_disable_intr:
+ rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+ }
+ if (rc)
+- err("%s : disabling interrupts failed\n", __FUNCTION__);
++ err("%s : disabling interrupts failed\n", __func__);
+ abort:
+ return -1;
+ }
+@@ -1265,62 +1265,62 @@ int pcie_init(struct controller *ctrl, struct pcie_device *dev)
+ ctrl->pci_dev = pdev; /* save pci_dev in context */
+
+ dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n",
+- __FUNCTION__, pdev->vendor, pdev->device);
++ __func__, pdev->vendor, pdev->device);
+
+ cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ if (cap_base == 0) {
+- dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __FUNCTION__);
++ dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __func__);
+ goto abort;
+ }
+
+ ctrl->cap_base = cap_base;
+
+- dbg("%s: pcie_cap_base %x\n", __FUNCTION__, cap_base);
++ dbg("%s: pcie_cap_base %x\n", __func__, cap_base);
+
+ rc = pciehp_readw(ctrl, CAPREG, &cap_reg);
+ if (rc) {
+- err("%s: Cannot read CAPREG register\n", __FUNCTION__);
++ err("%s: Cannot read CAPREG register\n", __func__);
+ goto abort;
+ }
+ dbg("%s: CAPREG offset %x cap_reg %x\n",
+- __FUNCTION__, ctrl->cap_base + CAPREG, cap_reg);
++ __func__, ctrl->cap_base + CAPREG, cap_reg);
+
+ if (((cap_reg & SLOT_IMPL) == 0) ||
+ (((cap_reg & DEV_PORT_TYPE) != 0x0040)
+ && ((cap_reg & DEV_PORT_TYPE) != 0x0060))) {
+ dbg("%s : This is not a root port or the port is not "
+- "connected to a slot\n", __FUNCTION__);
++ "connected to a slot\n", __func__);
+ goto abort;
+ }
+
+ rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
+ if (rc) {
+- err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
++ err("%s: Cannot read SLOTCAP register\n", __func__);
+ goto abort;
+ }
+ dbg("%s: SLOTCAP offset %x slot_cap %x\n",
+- __FUNCTION__, ctrl->cap_base + SLOTCAP, slot_cap);
++ __func__, ctrl->cap_base + SLOTCAP, slot_cap);
+
+ if (!(slot_cap & HP_CAP)) {
+- dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__);
++ dbg("%s : This slot is not hot-plug capable\n", __func__);
+ goto abort;
+ }
+ /* For debugging purpose */
+ rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ if (rc) {
+- err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
++ err("%s: Cannot read SLOTSTATUS register\n", __func__);
+ goto abort;
+ }
+ dbg("%s: SLOTSTATUS offset %x slot_status %x\n",
+- __FUNCTION__, ctrl->cap_base + SLOTSTATUS, slot_status);
++ __func__, ctrl->cap_base + SLOTSTATUS, slot_status);
+
+ rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
+ if (rc) {
+- err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
++ err("%s: Cannot read SLOTCTRL register\n", __func__);
+ goto abort;
+ }
+ dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n",
+- __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
++ __func__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
+
+ for (rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
+ if (pci_resource_len(pdev, rc) > 0)
+@@ -1358,7 +1358,7 @@ int pcie_init(struct controller *ctrl, struct pcie_device *dev)
+ rc = request_irq(ctrl->pci_dev->irq, pcie_isr, IRQF_SHARED,
+ MY_NAME, (void *)ctrl);
+ dbg("%s: request_irq %d for hpc%d (returns %d)\n",
+- __FUNCTION__, ctrl->pci_dev->irq,
++ __func__, ctrl->pci_dev->irq,
+ atomic_read(&pciehp_num_controllers), rc);
+ if (rc) {
+ err("Can't get irq %d for the hotplug controller\n",
+diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
+index 9372a84..6040dcc 100644
+--- a/drivers/pci/hotplug/pciehp_pci.c
++++ b/drivers/pci/hotplug/pciehp_pci.c
+@@ -40,7 +40,7 @@ static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp)
+
+ if (hpp->revision > 1) {
+ printk(KERN_WARNING "%s: Rev.%d type0 record not supported\n",
+- __FUNCTION__, hpp->revision);
++ __func__, hpp->revision);
+ return;
+ }
+
+@@ -82,7 +82,7 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
+
+ if (hpp->revision > 1) {
+ printk(KERN_WARNING "%s: Rev.%d type2 record not supported\n",
+- __FUNCTION__, hpp->revision);
++ __func__, hpp->revision);
+ return;
+ }
+
+@@ -150,7 +150,7 @@ static void program_fw_provided_values(struct pci_dev *dev)
+
+ if (pciehp_get_hp_params_from_firmware(dev, &hpp)) {
+ printk(KERN_WARNING "%s: Could not get hotplug parameters\n",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+
+@@ -245,7 +245,7 @@ int pciehp_unconfigure_device(struct slot *p_slot)
+ struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
+ u16 command;
+
+- dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus,
++ dbg("%s: bus/dev = %x/%x\n", __func__, p_slot->bus,
+ p_slot->device);
+ ret = p_slot->hpc_ops->get_adapter_status(p_slot, &presence);
+ if (ret)
+diff --git a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c
+index 50bcd3f..e3dd6cf 100644
+--- a/drivers/pci/hotplug/pcihp_skeleton.c
++++ b/drivers/pci/hotplug/pcihp_skeleton.c
+@@ -98,7 +98,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
+ struct slot *slot = hotplug_slot->private;
+ int retval = 0;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ /*
+ * Fill in code here to enable the specified slot
+@@ -112,7 +112,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
+ struct slot *slot = hotplug_slot->private;
+ int retval = 0;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ /*
+ * Fill in code here to disable the specified slot
+@@ -126,7 +126,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
+ struct slot *slot = hotplug_slot->private;
+ int retval = 0;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ switch (status) {
+ case 0:
+@@ -151,7 +151,7 @@ static int hardware_test(struct hotplug_slot *hotplug_slot, u32 value)
+ struct slot *slot = hotplug_slot->private;
+ int retval = 0;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ switch (value) {
+ case 0:
+@@ -170,7 +170,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ struct slot *slot = hotplug_slot->private;
+ int retval = 0;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ /*
+ * Fill in logic to get the current power status of the specific
+@@ -185,7 +185,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ struct slot *slot = hotplug_slot->private;
+ int retval = 0;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ /*
+ * Fill in logic to get the current attention status of the specific
+@@ -200,7 +200,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ struct slot *slot = hotplug_slot->private;
+ int retval = 0;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ /*
+ * Fill in logic to get the current latch status of the specific
+@@ -215,7 +215,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
+ struct slot *slot = hotplug_slot->private;
+ int retval = 0;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ /*
+ * Fill in logic to get the current adapter status of the specific
+@@ -229,7 +229,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
+ {
+ struct slot *slot = hotplug_slot->private;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+ kfree(slot->hotplug_slot->info);
+ kfree(slot->hotplug_slot);
+ kfree(slot);
+diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
+index 191954b..9c2a22f 100644
+--- a/drivers/pci/hotplug/rpadlpar_core.c
++++ b/drivers/pci/hotplug/rpadlpar_core.c
+@@ -147,7 +147,7 @@ static void dlpar_pci_add_bus(struct device_node *dn)
+ dev = of_create_pci_dev(dn, phb->bus, pdn->devfn);
+ if (!dev) {
+ printk(KERN_ERR "%s: failed to create pci dev for %s\n",
+- __FUNCTION__, dn->full_name);
++ __func__, dn->full_name);
+ return;
+ }
+
+@@ -183,21 +183,21 @@ static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
+ dev = dlpar_find_new_dev(phb->bus, dn);
+
+ if (!dev) {
+- printk(KERN_ERR "%s: unable to add bus %s\n", __FUNCTION__,
++ printk(KERN_ERR "%s: unable to add bus %s\n", __func__,
+ drc_name);
+ return -EIO;
+ }
+
+ if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
+ printk(KERN_ERR "%s: unexpected header type %d, unable to add bus %s\n",
+- __FUNCTION__, dev->hdr_type, drc_name);
++ __func__, dev->hdr_type, drc_name);
+ return -EIO;
+ }
+
+ /* Add hotplug slot */
+ if (rpaphp_add_slot(dn)) {
+ printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
+- __FUNCTION__, drc_name);
++ __func__, drc_name);
+ return -EIO;
+ }
+ return 0;
+@@ -239,7 +239,7 @@ static int dlpar_remove_phb(char *drc_name, struct device_node *dn)
+ if (rpaphp_deregister_slot(slot)) {
+ printk(KERN_ERR
+ "%s: unable to remove hotplug slot %s\n",
+- __FUNCTION__, drc_name);
++ __func__, drc_name);
+ return -EIO;
+ }
+ }
+@@ -270,7 +270,7 @@ static int dlpar_add_phb(char *drc_name, struct device_node *dn)
+
+ if (rpaphp_add_slot(dn)) {
+ printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
+- __FUNCTION__, drc_name);
++ __func__, drc_name);
+ return -EIO;
+ }
+ return 0;
+@@ -284,7 +284,7 @@ static int dlpar_add_vio_slot(char *drc_name, struct device_node *dn)
+ if (!vio_register_device_node(dn)) {
+ printk(KERN_ERR
+ "%s: failed to register vio node %s\n",
+- __FUNCTION__, drc_name);
++ __func__, drc_name);
+ return -EIO;
+ }
+ return 0;
+@@ -384,7 +384,7 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
+ if (rpaphp_deregister_slot(slot)) {
+ printk(KERN_ERR
+ "%s: unable to remove hotplug slot %s\n",
+- __FUNCTION__, drc_name);
++ __func__, drc_name);
+ return -EIO;
+ }
+ } else
+@@ -392,7 +392,7 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
+
+ if (pcibios_unmap_io_space(bus)) {
+ printk(KERN_ERR "%s: failed to unmap bus range\n",
+- __FUNCTION__);
++ __func__);
+ return -ERANGE;
+ }
+
+@@ -458,7 +458,7 @@ int __init rpadlpar_io_init(void)
+
+ if (!is_dlpar_capable()) {
+ printk(KERN_WARNING "%s: partition not DLPAR capable\n",
+- __FUNCTION__);
++ __func__);
+ return -EPERM;
+ }
+
+diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
+index 58f1a99..1f84f40 100644
+--- a/drivers/pci/hotplug/rpaphp_core.c
++++ b/drivers/pci/hotplug/rpaphp_core.c
+@@ -317,7 +317,7 @@ int rpaphp_add_slot(struct device_node *dn)
+ if (!is_php_dn(dn, &indexes, &names, &types, &power_domains))
+ return 0;
+
+- dbg("Entry %s: dn->full_name=%s\n", __FUNCTION__, dn->full_name);
++ dbg("Entry %s: dn->full_name=%s\n", __func__, dn->full_name);
+
+ /* register PCI devices */
+ name = (char *) &names[1];
+@@ -343,7 +343,7 @@ int rpaphp_add_slot(struct device_node *dn)
+ name += strlen(name) + 1;
+ type += strlen(type) + 1;
+ }
+- dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
++ dbg("%s - Exit: rc[%d]\n", __func__, retval);
+
+ /* XXX FIXME: reports a failure only if last entry in loop failed */
+ return retval;
+@@ -404,7 +404,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
+ } else if (state == EMPTY) {
+ slot->state = EMPTY;
+ } else {
+- err("%s: slot[%s] is in invalid state\n", __FUNCTION__, slot->name);
++ err("%s: slot[%s] is in invalid state\n", __func__, slot->name);
+ slot->state = NOT_VALID;
+ return -EINVAL;
+ }
+diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
+index 6571e9b..5acfd4f 100644
+--- a/drivers/pci/hotplug/rpaphp_pci.c
++++ b/drivers/pci/hotplug/rpaphp_pci.c
+@@ -42,7 +42,7 @@ int rpaphp_get_sensor_state(struct slot *slot, int *state)
+ if (rc < 0) {
+ if (rc == -EFAULT || rc == -EEXIST) {
+ dbg("%s: slot must be power up to get sensor-state\n",
+- __FUNCTION__);
++ __func__);
+
+ /* some slots have to be powered up
+ * before get-sensor will succeed.
+@@ -51,15 +51,15 @@ int rpaphp_get_sensor_state(struct slot *slot, int *state)
+ &setlevel);
+ if (rc < 0) {
+ dbg("%s: power on slot[%s] failed rc=%d.\n",
+- __FUNCTION__, slot->name, rc);
++ __func__, slot->name, rc);
+ } else {
+ rc = rtas_get_sensor(DR_ENTITY_SENSE,
+ slot->index, state);
+ }
+ } else if (rc == -ENODEV)
+- info("%s: slot is unusable\n", __FUNCTION__);
++ info("%s: slot is unusable\n", __func__);
+ else
+- err("%s failed to get sensor state\n", __FUNCTION__);
++ err("%s failed to get sensor state\n", __func__);
+ }
+ return rc;
+ }
+@@ -95,7 +95,7 @@ int rpaphp_enable_slot(struct slot *slot)
+
+ bus = pcibios_find_pci_bus(slot->dn);
+ if (!bus) {
+- err("%s: no pci_bus for dn %s\n", __FUNCTION__, slot->dn->full_name);
++ err("%s: no pci_bus for dn %s\n", __func__, slot->dn->full_name);
+ return -EINVAL;
+ }
+
+@@ -111,7 +111,7 @@ int rpaphp_enable_slot(struct slot *slot)
+ /* non-empty slot has to have child */
+ if (!slot->dn->child) {
+ err("%s: slot[%s]'s device_node doesn't have child for adapter\n",
+- __FUNCTION__, slot->name);
++ __func__, slot->name);
+ return -EINVAL;
+ }
+
+@@ -125,7 +125,7 @@ int rpaphp_enable_slot(struct slot *slot)
+
+ if (debug) {
+ struct pci_dev *dev;
+- dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, slot->dn->full_name);
++ dbg("%s: pci_devs of slot[%s]\n", __func__, slot->dn->full_name);
+ list_for_each_entry (dev, &bus->devices, bus_list)
+ dbg("\t%s\n", pci_name(dev));
+ }
+diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
+index 8ad3deb..56197b6 100644
+--- a/drivers/pci/hotplug/rpaphp_slot.c
++++ b/drivers/pci/hotplug/rpaphp_slot.c
+@@ -131,7 +131,7 @@ int rpaphp_deregister_slot(struct slot *slot)
+ struct hotplug_slot *php_slot = slot->hotplug_slot;
+
+ dbg("%s - Entry: deregistering slot=%s\n",
+- __FUNCTION__, slot->name);
++ __func__, slot->name);
+
+ list_del(&slot->rpaphp_slot_list);
+
+@@ -142,7 +142,7 @@ int rpaphp_deregister_slot(struct slot *slot)
+ if (retval)
+ err("Problem unregistering a slot %s\n", slot->name);
+
+- dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
++ dbg("%s - Exit: rc[%d]\n", __func__, retval);
+ return retval;
+ }
+ EXPORT_SYMBOL_GPL(rpaphp_deregister_slot);
+@@ -153,7 +153,7 @@ int rpaphp_register_slot(struct slot *slot)
+ int retval;
+
+ dbg("%s registering slot:path[%s] index[%x], name[%s] pdomain[%x] type[%d]\n",
+- __FUNCTION__, slot->dn->full_name, slot->index, slot->name,
++ __func__, slot->dn->full_name, slot->index, slot->name,
+ slot->power_domain, slot->type);
+
+ /* should not try to register the same slot twice */
+diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c
+index ef07c36..2fe37cd 100644
+--- a/drivers/pci/hotplug/sgi_hotplug.c
++++ b/drivers/pci/hotplug/sgi_hotplug.c
+@@ -367,7 +367,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
+ ret = acpi_load_table((struct acpi_table_header *)ssdt);
+ if (ACPI_FAILURE(ret)) {
+ printk(KERN_ERR "%s: acpi_load_table failed (0x%x)\n",
+- __FUNCTION__, ret);
++ __func__, ret);
+ /* try to continue on */
+ }
+ }
+@@ -459,7 +459,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
+ if (ACPI_FAILURE(ret)) {
+ printk(KERN_ERR "%s: acpi_bus_add "
+ "failed (0x%x) for slot %d "
+- "func %d\n", __FUNCTION__,
++ "func %d\n", __func__,
+ ret, (int)(adr>>16),
+ (int)(adr&0xffff));
+ /* try to continue on */
+@@ -570,7 +570,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
+ if (ACPI_FAILURE(ret)) {
+ printk(KERN_ERR "%s: acpi_unload_table_id "
+ "failed (0x%x) for id %d\n",
+- __FUNCTION__, ret, ssdt_id);
++ __func__, ret, ssdt_id);
+ /* try to continue on */
+ }
+ }
+@@ -689,7 +689,7 @@ static int sn_pci_hotplug_init(void)
+
+ if (!sn_prom_feature_available(PRF_HOTPLUG_SUPPORT)) {
+ printk(KERN_ERR "%s: PROM version does not support hotplug.\n",
+- __FUNCTION__);
++ __func__);
+ return -EPERM;
+ }
+
+diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
+index 37ed088..f66e8d6 100644
+--- a/drivers/pci/hotplug/shpchp.h
++++ b/drivers/pci/hotplug/shpchp.h
+@@ -234,7 +234,7 @@ static inline struct slot *shpchp_find_slot(struct controller *ctrl, u8 device)
+ return slot;
+ }
+
+- err("%s: slot (device=0x%x) not found\n", __FUNCTION__, device);
++ err("%s: slot (device=0x%x) not found\n", __func__, device);
+ return NULL;
+ }
+
+@@ -268,7 +268,7 @@ static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot)
+ pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MISC_BRIDGE_ERRORS_OFFSET, &pcix_bridge_errors_reg);
+ perr_set = pcix_bridge_errors_reg & PERR_OBSERVED_MASK;
+ if (perr_set) {
+- dbg ("%s W1C: Bridge_Errors[ PERR_OBSERVED = %08X]\n",__FUNCTION__ , perr_set);
++ dbg ("%s W1C: Bridge_Errors[ PERR_OBSERVED = %08X]\n",__func__ , perr_set);
+
+ pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISC_BRIDGE_ERRORS_OFFSET, perr_set);
+ }
+@@ -277,7 +277,7 @@ static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot)
+ pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MEM_BASE_LIMIT_OFFSET, &pcix_mem_base_reg);
+ rse_set = pcix_mem_base_reg & RSE_MASK;
+ if (rse_set) {
+- dbg ("%s W1C: Memory_Base_Limit[ RSE ]\n",__FUNCTION__ );
++ dbg ("%s W1C: Memory_Base_Limit[ RSE ]\n",__func__ );
+
+ pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MEM_BASE_LIMIT_OFFSET, rse_set);
+ }
+diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
+index 80dec97..43816d4 100644
+--- a/drivers/pci/hotplug/shpchp_core.c
++++ b/drivers/pci/hotplug/shpchp_core.c
+@@ -91,7 +91,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
+ {
+ struct slot *slot = hotplug_slot->private;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ kfree(slot->hotplug_slot->info);
+ kfree(slot->hotplug_slot);
+@@ -195,7 +195,7 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
+ {
+ struct slot *slot = get_slot(hotplug_slot);
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ hotplug_slot->info->attention_status = status;
+ slot->hpc_ops->set_attention_status(slot, status);
+@@ -207,7 +207,7 @@ static int enable_slot (struct hotplug_slot *hotplug_slot)
+ {
+ struct slot *slot = get_slot(hotplug_slot);
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ return shpchp_sysfs_enable_slot(slot);
+ }
+@@ -216,7 +216,7 @@ static int disable_slot (struct hotplug_slot *hotplug_slot)
+ {
+ struct slot *slot = get_slot(hotplug_slot);
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ return shpchp_sysfs_disable_slot(slot);
+ }
+@@ -226,7 +226,7 @@ static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
+ struct slot *slot = get_slot(hotplug_slot);
+ int retval;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ retval = slot->hpc_ops->get_power_status(slot, value);
+ if (retval < 0)
+@@ -240,7 +240,7 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
+ struct slot *slot = get_slot(hotplug_slot);
+ int retval;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ retval = slot->hpc_ops->get_attention_status(slot, value);
+ if (retval < 0)
+@@ -254,7 +254,7 @@ static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
+ struct slot *slot = get_slot(hotplug_slot);
+ int retval;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ retval = slot->hpc_ops->get_latch_status(slot, value);
+ if (retval < 0)
+@@ -268,7 +268,7 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
+ struct slot *slot = get_slot(hotplug_slot);
+ int retval;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ retval = slot->hpc_ops->get_adapter_status(slot, value);
+ if (retval < 0)
+@@ -282,7 +282,7 @@ static int get_address (struct hotplug_slot *hotplug_slot, u32 *value)
+ struct slot *slot = get_slot(hotplug_slot);
+ struct pci_bus *bus = slot->ctrl->pci_dev->subordinate;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ *value = (pci_domain_nr(bus) << 16) | (slot->bus << 8) | slot->device;
+
+@@ -294,7 +294,7 @@ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
+ struct slot *slot = get_slot(hotplug_slot);
+ int retval;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ retval = slot->hpc_ops->get_max_bus_speed(slot, value);
+ if (retval < 0)
+@@ -308,7 +308,7 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
+ struct slot *slot = get_slot(hotplug_slot);
+ int retval;
+
+- dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
++ dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
+
+ retval = slot->hpc_ops->get_cur_bus_speed(slot, value);
+ if (retval < 0)
+@@ -338,7 +338,7 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+
+ ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
+ if (!ctrl) {
+- err("%s : out of memory\n", __FUNCTION__);
++ err("%s : out of memory\n", __func__);
+ goto err_out_none;
+ }
+ INIT_LIST_HEAD(&ctrl->slot_list);
+@@ -402,7 +402,7 @@ static int __init shpcd_init(void)
+ int retval = 0;
+
+ retval = pci_register_driver(&shpc_driver);
+- dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval);
++ dbg("%s: pci_register_driver = %d\n", __func__, retval);
+ info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
+ return retval;
+ }
+diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
+index eb5cac6..dfb5393 100644
+--- a/drivers/pci/hotplug/shpchp_ctrl.c
++++ b/drivers/pci/hotplug/shpchp_ctrl.c
+@@ -91,7 +91,7 @@ u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl)
+ p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+ p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
+ p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+- dbg("%s: Card present %x Power status %x\n", __FUNCTION__,
++ dbg("%s: Card present %x Power status %x\n", __func__,
+ p_slot->presence_save, p_slot->pwr_save);
+
+ if (getstatus) {
+@@ -191,10 +191,10 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot,
+ {
+ int rc = 0;
+
+- dbg("%s: change to speed %d\n", __FUNCTION__, speed);
++ dbg("%s: change to speed %d\n", __func__, speed);
+ if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) {
+ err("%s: Issue of set bus speed mode command failed\n",
+- __FUNCTION__);
++ __func__);
+ return WRONG_BUS_FREQUENCY;
+ }
+ return rc;
+@@ -213,7 +213,7 @@ static int fix_bus_speed(struct controller *ctrl, struct slot *pslot,
+ if (flag) {
+ if (asp < bsp) {
+ err("%s: speed of bus %x and adapter %x mismatch\n",
+- __FUNCTION__, bsp, asp);
++ __func__, bsp, asp);
+ rc = WRONG_BUS_FREQUENCY;
+ }
+ return rc;
+@@ -247,13 +247,13 @@ static int board_added(struct slot *p_slot)
+ hp_slot = p_slot->device - ctrl->slot_device_offset;
+
+ dbg("%s: p_slot->device, slot_offset, hp_slot = %d, %d ,%d\n",
+- __FUNCTION__, p_slot->device,
++ __func__, p_slot->device,
+ ctrl->slot_device_offset, hp_slot);
+
+ /* Power on slot without connecting to bus */
+ rc = p_slot->hpc_ops->power_on_slot(p_slot);
+ if (rc) {
+- err("%s: Failed to power on slot\n", __FUNCTION__);
++ err("%s: Failed to power on slot\n", __func__);
+ return -1;
+ }
+
+@@ -262,13 +262,13 @@ static int board_added(struct slot *p_slot)
+ return WRONG_BUS_FREQUENCY;
+
+ if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) {
+- err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
++ err("%s: Issue of set bus speed mode command failed\n", __func__);
+ return WRONG_BUS_FREQUENCY;
+ }
+
+ /* turn on board, blink green LED, turn off Amber LED */
+ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) {
+- err("%s: Issue of Slot Enable command failed\n", __FUNCTION__);
++ err("%s: Issue of Slot Enable command failed\n", __func__);
+ return rc;
+ }
+ }
+@@ -276,19 +276,19 @@ static int board_added(struct slot *p_slot)
+ rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &asp);
+ if (rc) {
+ err("%s: Can't get adapter speed or bus mode mismatch\n",
+- __FUNCTION__);
++ __func__);
+ return WRONG_BUS_FREQUENCY;
+ }
+
+ rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bsp);
+ if (rc) {
+- err("%s: Can't get bus operation speed\n", __FUNCTION__);
++ err("%s: Can't get bus operation speed\n", __func__);
+ return WRONG_BUS_FREQUENCY;
+ }
+
+ rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &msp);
+ if (rc) {
+- err("%s: Can't get max bus operation speed\n", __FUNCTION__);
++ err("%s: Can't get max bus operation speed\n", __func__);
+ msp = bsp;
+ }
+
+@@ -297,7 +297,7 @@ static int board_added(struct slot *p_slot)
+ slots_not_empty = 1;
+
+ dbg("%s: slots_not_empty %d, adapter_speed %d, bus_speed %d, "
+- "max_bus_speed %d\n", __FUNCTION__, slots_not_empty, asp,
++ "max_bus_speed %d\n", __func__, slots_not_empty, asp,
+ bsp, msp);
+
+ rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, asp, bsp, msp);
+@@ -306,18 +306,18 @@ static int board_added(struct slot *p_slot)
+
+ /* turn on board, blink green LED, turn off Amber LED */
+ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) {
+- err("%s: Issue of Slot Enable command failed\n", __FUNCTION__);
++ err("%s: Issue of Slot Enable command failed\n", __func__);
+ return rc;
+ }
+
+ /* Wait for ~1 second */
+ msleep(1000);
+
+- dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status);
++ dbg("%s: slot status = %x\n", __func__, p_slot->status);
+ /* Check for a power fault */
+ if (p_slot->status == 0xFF) {
+ /* power fault occurred, but it was benign */
+- dbg("%s: power fault\n", __FUNCTION__);
++ dbg("%s: power fault\n", __func__);
+ rc = POWER_FAILURE;
+ p_slot->status = 0;
+ goto err_exit;
+@@ -341,7 +341,7 @@ err_exit:
+ /* turn off slot, turn on Amber LED, turn off Green LED */
+ rc = p_slot->hpc_ops->slot_disable(p_slot);
+ if (rc) {
+- err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
++ err("%s: Issue of Slot Disable command failed\n", __func__);
+ return rc;
+ }
+
+@@ -365,7 +365,7 @@ static int remove_board(struct slot *p_slot)
+ hp_slot = p_slot->device - ctrl->slot_device_offset;
+ p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
+
+- dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
++ dbg("In %s, hp_slot = %d\n", __func__, hp_slot);
+
+ /* Change status to shutdown */
+ if (p_slot->is_a_board)
+@@ -374,13 +374,13 @@ static int remove_board(struct slot *p_slot)
+ /* turn off slot, turn on Amber LED, turn off Green LED */
+ rc = p_slot->hpc_ops->slot_disable(p_slot);
+ if (rc) {
+- err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
++ err("%s: Issue of Slot Disable command failed\n", __func__);
+ return rc;
+ }
+
+ rc = p_slot->hpc_ops->set_attention_status(p_slot, 0);
+ if (rc) {
+- err("%s: Issue of Set Attention command failed\n", __FUNCTION__);
++ err("%s: Issue of Set Attention command failed\n", __func__);
+ return rc;
+ }
+
+@@ -439,7 +439,7 @@ void shpchp_queue_pushbutton_work(struct work_struct *work)
+
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (!info) {
+- err("%s: Cannot allocate memory\n", __FUNCTION__);
++ err("%s: Cannot allocate memory\n", __func__);
+ return;
+ }
+ info->p_slot = p_slot;
+@@ -513,7 +513,7 @@ static void handle_button_press_event(struct slot *p_slot)
+ * expires to cancel hot-add or hot-remove
+ */
+ info("Button cancel on Slot(%s)\n", p_slot->name);
+- dbg("%s: button cancel\n", __FUNCTION__);
++ dbg("%s: button cancel\n", __func__);
+ cancel_delayed_work(&p_slot->work);
+ if (p_slot->state == BLINKINGOFF_STATE)
+ p_slot->hpc_ops->green_led_on(p_slot);
+@@ -551,7 +551,7 @@ static void interrupt_event_handler(struct work_struct *work)
+ handle_button_press_event(p_slot);
+ break;
+ case INT_POWER_FAULT:
+- dbg("%s: power fault\n", __FUNCTION__);
++ dbg("%s: power fault\n", __func__);
+ p_slot->hpc_ops->set_attention_status(p_slot, 1);
+ p_slot->hpc_ops->green_led_off(p_slot);
+ break;
+@@ -593,7 +593,7 @@ static int shpchp_enable_slot (struct slot *p_slot)
+ /* We have to save the presence info for these slots */
+ p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
+ p_slot->hpc_ops->get_power_status(p_slot, &(p_slot->pwr_save));
+- dbg("%s: p_slot->pwr_save %x\n", __FUNCTION__, p_slot->pwr_save);
++ dbg("%s: p_slot->pwr_save %x\n", __func__, p_slot->pwr_save);
+ p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+
+ if(((p_slot->ctrl->pci_dev->vendor == PCI_VENDOR_ID_AMD) ||
+diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
+index e8aa138..7d770b2 100644
+--- a/drivers/pci/hotplug/shpchp_hpc.c
++++ b/drivers/pci/hotplug/shpchp_hpc.c
+@@ -321,14 +321,14 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
+ if (!shpc_poll_ctrl_busy(ctrl)) {
+ /* After 1 sec and and the controller is still busy */
+ err("%s : Controller is still busy after 1 sec.\n",
+- __FUNCTION__);
++ __func__);
+ retval = -EBUSY;
+ goto out;
+ }
+
+ ++t_slot;
+ temp_word = (t_slot << 8) | (cmd & 0xFF);
+- dbg("%s: t_slot %x cmd %x\n", __FUNCTION__, t_slot, cmd);
++ dbg("%s: t_slot %x cmd %x\n", __func__, t_slot, cmd);
+
+ /* To make sure the Controller Busy bit is 0 before we send out the
+ * command.
+@@ -345,7 +345,7 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
+ cmd_status = hpc_check_cmd_status(slot->ctrl);
+ if (cmd_status) {
+ err("%s: Failed to issued command 0x%x (error code = %d)\n",
+- __FUNCTION__, cmd, cmd_status);
++ __func__, cmd, cmd_status);
+ retval = -EIO;
+ }
+ out:
+@@ -364,15 +364,15 @@ static int hpc_check_cmd_status(struct controller *ctrl)
+ break;
+ case 1:
+ retval = SWITCH_OPEN;
+- err("%s: Switch opened!\n", __FUNCTION__);
++ err("%s: Switch opened!\n", __func__);
+ break;
+ case 2:
+ retval = INVALID_CMD;
+- err("%s: Invalid HPC command!\n", __FUNCTION__);
++ err("%s: Invalid HPC command!\n", __func__);
+ break;
+ case 4:
+ retval = INVALID_SPEED_MODE;
+- err("%s: Invalid bus speed/mode!\n", __FUNCTION__);
++ err("%s: Invalid bus speed/mode!\n", __func__);
+ break;
+ default:
+ retval = cmd_status;
+@@ -484,7 +484,7 @@ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
+ }
+
+ dbg("%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n",
+- __FUNCTION__, slot_reg, pcix_cap, m66_cap);
++ __func__, slot_reg, pcix_cap, m66_cap);
+
+ switch (pcix_cap) {
+ case 0x0:
+@@ -629,7 +629,7 @@ static int hpc_power_on_slot(struct slot * slot)
+
+ retval = shpc_write_cmd(slot, slot->hp_slot, SET_SLOT_PWR);
+ if (retval)
+- err("%s: Write command failed!\n", __FUNCTION__);
++ err("%s: Write command failed!\n", __func__);
+
+ return retval;
+ }
+@@ -642,7 +642,7 @@ static int hpc_slot_enable(struct slot * slot)
+ retval = shpc_write_cmd(slot, slot->hp_slot,
+ SET_SLOT_ENABLE | SET_PWR_BLINK | SET_ATTN_OFF);
+ if (retval)
+- err("%s: Write command failed!\n", __FUNCTION__);
++ err("%s: Write command failed!\n", __func__);
+
+ return retval;
+ }
+@@ -655,7 +655,7 @@ static int hpc_slot_disable(struct slot * slot)
+ retval = shpc_write_cmd(slot, slot->hp_slot,
+ SET_SLOT_DISABLE | SET_PWR_OFF | SET_ATTN_ON);
+ if (retval)
+- err("%s: Write command failed!\n", __FUNCTION__);
++ err("%s: Write command failed!\n", __func__);
+
+ return retval;
+ }
+@@ -719,7 +719,7 @@ static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
+
+ retval = shpc_write_cmd(slot, 0, cmd);
+ if (retval)
+- err("%s: Write command failed!\n", __FUNCTION__);
++ err("%s: Write command failed!\n", __func__);
+
+ return retval;
+ }
+@@ -735,7 +735,7 @@ static irqreturn_t shpc_isr(int irq, void *dev_id)
+ if (!intr_loc)
+ return IRQ_NONE;
+
+- dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc);
++ dbg("%s: intr_loc = %x\n",__func__, intr_loc);
+
+ if(!shpchp_poll_mode) {
+ /*
+@@ -748,7 +748,7 @@ static irqreturn_t shpc_isr(int irq, void *dev_id)
+ shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
+
+ intr_loc2 = shpc_readl(ctrl, INTR_LOC);
+- dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2);
++ dbg("%s: intr_loc2 = %x\n",__func__, intr_loc2);
+ }
+
+ if (intr_loc & CMD_INTR_PENDING) {
+@@ -774,7 +774,7 @@ static irqreturn_t shpc_isr(int irq, void *dev_id)
+
+ slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
+ dbg("%s: Slot %x with intr, slot register = %x\n",
+- __FUNCTION__, hp_slot, slot_reg);
++ __func__, hp_slot, slot_reg);
+
+ if (slot_reg & MRL_CHANGE_DETECTED)
+ shpchp_handle_switch_change(hp_slot, ctrl);
+@@ -958,33 +958,33 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
+ } else {
+ ctrl->cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC);
+ if (!ctrl->cap_offset) {
+- err("%s : cap_offset == 0\n", __FUNCTION__);
++ err("%s : cap_offset == 0\n", __func__);
+ goto abort;
+ }
+- dbg("%s: cap_offset = %x\n", __FUNCTION__, ctrl->cap_offset);
++ dbg("%s: cap_offset = %x\n", __func__, ctrl->cap_offset);
+
+ rc = shpc_indirect_read(ctrl, 0, &shpc_base_offset);
+ if (rc) {
+- err("%s: cannot read base_offset\n", __FUNCTION__);
++ err("%s: cannot read base_offset\n", __func__);
+ goto abort;
+ }
+
+ rc = shpc_indirect_read(ctrl, 3, &tempdword);
+ if (rc) {
+- err("%s: cannot read slot config\n", __FUNCTION__);
++ err("%s: cannot read slot config\n", __func__);
+ goto abort;
+ }
+ num_slots = tempdword & SLOT_NUM;
+- dbg("%s: num_slots (indirect) %x\n", __FUNCTION__, num_slots);
++ dbg("%s: num_slots (indirect) %x\n", __func__, num_slots);
+
+ for (i = 0; i < 9 + num_slots; i++) {
+ rc = shpc_indirect_read(ctrl, i, &tempdword);
+ if (rc) {
+ err("%s: cannot read creg (index = %d)\n",
+- __FUNCTION__, i);
++ __func__, i);
+ goto abort;
+ }
+- dbg("%s: offset %d: value %x\n", __FUNCTION__,i,
++ dbg("%s: offset %d: value %x\n", __func__,i,
+ tempdword);
+ }
+
+@@ -998,25 +998,25 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
+
+ rc = pci_enable_device(pdev);
+ if (rc) {
+- err("%s: pci_enable_device failed\n", __FUNCTION__);
++ err("%s: pci_enable_device failed\n", __func__);
+ goto abort;
+ }
+
+ if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) {
+- err("%s: cannot reserve MMIO region\n", __FUNCTION__);
++ err("%s: cannot reserve MMIO region\n", __func__);
+ rc = -1;
+ goto abort;
+ }
+
+ ctrl->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size);
+ if (!ctrl->creg) {
+- err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__,
++ err("%s: cannot remap MMIO region %lx @ %lx\n", __func__,
+ ctrl->mmio_size, ctrl->mmio_base);
+ release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
+ rc = -1;
+ goto abort;
+ }
+- dbg("%s: ctrl->creg %p\n", __FUNCTION__, ctrl->creg);
++ dbg("%s: ctrl->creg %p\n", __func__, ctrl->creg);
+
+ mutex_init(&ctrl->crit_sect);
+ mutex_init(&ctrl->cmd_lock);
+@@ -1035,20 +1035,20 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
+
+ /* Mask Global Interrupt Mask & Command Complete Interrupt Mask */
+ tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
+- dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword);
++ dbg("%s: SERR_INTR_ENABLE = %x\n", __func__, tempdword);
+ tempdword |= (GLOBAL_INTR_MASK | GLOBAL_SERR_MASK |
+ COMMAND_INTR_MASK | ARBITER_SERR_MASK);
+ tempdword &= ~SERR_INTR_RSVDZ_MASK;
+ shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword);
+ tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
+- dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword);
++ dbg("%s: SERR_INTR_ENABLE = %x\n", __func__, tempdword);
+
+ /* Mask the MRL sensor SERR Mask of individual slot in
+ * Slot SERR-INT Mask & clear all the existing event if any
+ */
+ for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) {
+ slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
+- dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__,
++ dbg("%s: Default Logical Slot Register %d value %x\n", __func__,
+ hp_slot, slot_reg);
+ slot_reg |= (PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK |
+ BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK |
+@@ -1073,7 +1073,7 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
+ rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED,
+ MY_NAME, (void *)ctrl);
+ dbg("%s: request_irq %d for hpc%d (returns %d)\n",
+- __FUNCTION__, ctrl->pci_dev->irq,
++ __func__, ctrl->pci_dev->irq,
+ atomic_read(&shpchp_num_controllers), rc);
+ if (rc) {
+ err("Can't get irq %d for the hotplug controller\n",
+@@ -1081,7 +1081,7 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
+ goto abort_iounmap;
+ }
+ }
+- dbg("%s: HPC at b:d:f:irq=0x%x:%x:%x:%x\n", __FUNCTION__,
++ dbg("%s: HPC at b:d:f:irq=0x%x:%x:%x:%x\n", __func__,
+ pdev->bus->number, PCI_SLOT(pdev->devfn),
+ PCI_FUNC(pdev->devfn), pdev->irq);
+ get_hp_hw_control_from_firmware(pdev);
+@@ -1103,7 +1103,7 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
+ */
+ for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) {
+ slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
+- dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__,
++ dbg("%s: Default Logical Slot Register %d value %x\n", __func__,
+ hp_slot, slot_reg);
+ slot_reg &= ~(PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK |
+ BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK |
+@@ -1117,7 +1117,7 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
+ SERR_INTR_RSVDZ_MASK);
+ shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword);
+ tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
+- dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword);
++ dbg("%s: SERR_INTR_ENABLE = %x\n", __func__, tempdword);
+ }
+
+ return 0;
+diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c
+index a69a215..3fc4ec0 100644
+--- a/drivers/pci/hotplug/shpchp_pci.c
++++ b/drivers/pci/hotplug/shpchp_pci.c
+@@ -51,7 +51,7 @@ static void program_fw_provided_values(struct pci_dev *dev)
+ !hpp.t0 || (hpp.t0->revision > 1)) {
+ printk(KERN_WARNING
+ "%s: Could not get hotplug parameters. Use defaults\n",
+- __FUNCTION__);
++ __func__);
+ hpp.t0 = &hpp.type0_data;
+ hpp.t0->revision = 0;
+ hpp.t0->cache_line_size = 8;
+@@ -169,7 +169,7 @@ int shpchp_unconfigure_device(struct slot *p_slot)
+ u8 bctl = 0;
+ struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
+
+- dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus, p_slot->device);
++ dbg("%s: bus/dev = %x/%x\n", __func__, p_slot->bus, p_slot->device);
+
+ for (j=0; j<8 ; j++) {
+ struct pci_dev* temp = pci_get_slot(parent,
+diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
+index 4cb949f..1fd8bb7 100644
+--- a/drivers/pci/intel-iommu.c
++++ b/drivers/pci/intel-iommu.c
+@@ -22,6 +22,7 @@
+
+ #include <linux/init.h>
+ #include <linux/bitmap.h>
++#include <linux/debugfs.h>
+ #include <linux/slab.h>
+ #include <linux/irq.h>
+ #include <linux/interrupt.h>
+@@ -31,6 +32,7 @@
+ #include <linux/dmar.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/mempool.h>
++#include <linux/timer.h>
+ #include "iova.h"
+ #include "intel-iommu.h"
+ #include <asm/proto.h> /* force_iommu in this header in x86-64*/
+@@ -51,11 +53,37 @@
+
+ #define DOMAIN_MAX_ADDR(gaw) ((((u64)1) << gaw) - 1)
+
++
++static void flush_unmaps_timeout(unsigned long data);
++
++DEFINE_TIMER(unmap_timer, flush_unmaps_timeout, 0, 0);
++
++static struct intel_iommu *g_iommus;
++
++#define HIGH_WATER_MARK 250
++struct deferred_flush_tables {
++ int next;
++ struct iova *iova[HIGH_WATER_MARK];
++ struct dmar_domain *domain[HIGH_WATER_MARK];
++};
++
++static struct deferred_flush_tables *deferred_flush;
++
++/* bitmap for indexing intel_iommus */
++static int g_num_of_iommus;
++
++static DEFINE_SPINLOCK(async_umap_flush_lock);
++static LIST_HEAD(unmaps_to_do);
++
++static int timer_on;
++static long list_size;
++
+ static void domain_remove_dev_info(struct dmar_domain *domain);
+
+ static int dmar_disabled;
+ static int __initdata dmar_map_gfx = 1;
+ static int dmar_forcedac;
++static int intel_iommu_strict;
+
+ #define DUMMY_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-1))
+ static DEFINE_SPINLOCK(device_domain_lock);
+@@ -74,9 +102,13 @@ static int __init intel_iommu_setup(char *str)
+ printk(KERN_INFO
+ "Intel-IOMMU: disable GFX device mapping\n");
+ } else if (!strncmp(str, "forcedac", 8)) {
+- printk (KERN_INFO
++ printk(KERN_INFO
+ "Intel-IOMMU: Forcing DAC for PCI devices\n");
+ dmar_forcedac = 1;
++ } else if (!strncmp(str, "strict", 6)) {
++ printk(KERN_INFO
++ "Intel-IOMMU: disable batched IOTLB flush\n");
++ intel_iommu_strict = 1;
+ }
+
+ str += strcspn(str, ",");
+@@ -966,17 +998,13 @@ static int iommu_init_domains(struct intel_iommu *iommu)
+ set_bit(0, iommu->domain_ids);
+ return 0;
+ }
+-
+-static struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd)
++static struct intel_iommu *alloc_iommu(struct intel_iommu *iommu,
++ struct dmar_drhd_unit *drhd)
+ {
+- struct intel_iommu *iommu;
+ int ret;
+ int map_size;
+ u32 ver;
+
+- iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
+- if (!iommu)
+- return NULL;
+ iommu->reg = ioremap(drhd->reg_base_addr, PAGE_SIZE_4K);
+ if (!iommu->reg) {
+ printk(KERN_ERR "IOMMU: can't map the region\n");
+@@ -1404,7 +1432,7 @@ static int dmar_pci_device_match(struct pci_dev *devices[], int cnt,
+ int index;
+
+ while (dev) {
+- for (index = 0; index < cnt; index ++)
++ for (index = 0; index < cnt; index++)
+ if (dev == devices[index])
+ return 1;
+
+@@ -1669,7 +1697,7 @@ int __init init_dmars(void)
+ struct dmar_rmrr_unit *rmrr;
+ struct pci_dev *pdev;
+ struct intel_iommu *iommu;
+- int ret, unit = 0;
++ int i, ret, unit = 0;
+
+ /*
+ * for each drhd
+@@ -1680,7 +1708,34 @@ int __init init_dmars(void)
+ for_each_drhd_unit(drhd) {
+ if (drhd->ignored)
+ continue;
+- iommu = alloc_iommu(drhd);
++ g_num_of_iommus++;
++ /*
++ * lock not needed as this is only incremented in the single
++ * threaded kernel __init code path all other access are read
++ * only
++ */
++ }
++
++ g_iommus = kzalloc(g_num_of_iommus * sizeof(*iommu), GFP_KERNEL);
++ if (!g_iommus) {
++ ret = -ENOMEM;
++ goto error;
++ }
++
++ deferred_flush = kzalloc(g_num_of_iommus *
++ sizeof(struct deferred_flush_tables), GFP_KERNEL);
++ if (!deferred_flush) {
++ kfree(g_iommus);
++ ret = -ENOMEM;
++ goto error;
++ }
++
++ i = 0;
++ for_each_drhd_unit(drhd) {
++ if (drhd->ignored)
++ continue;
++ iommu = alloc_iommu(&g_iommus[i], drhd);
++ i++;
+ if (!iommu) {
+ ret = -ENOMEM;
+ goto error;
+@@ -1713,7 +1768,6 @@ int __init init_dmars(void)
+ * endfor
+ */
+ for_each_rmrr_units(rmrr) {
+- int i;
+ for (i = 0; i < rmrr->devices_cnt; i++) {
+ pdev = rmrr->devices[i];
+ /* some BIOS lists non-exist devices in DMAR table */
+@@ -1769,6 +1823,7 @@ error:
+ iommu = drhd->iommu;
+ free_iommu(iommu);
+ }
++ kfree(g_iommus);
+ return ret;
+ }
+
+@@ -1850,32 +1905,31 @@ get_valid_domain_for_dev(struct pci_dev *pdev)
+ return domain;
+ }
+
+-static dma_addr_t intel_map_single(struct device *hwdev, void *addr,
+- size_t size, int dir)
++static dma_addr_t
++intel_map_single(struct device *hwdev, phys_addr_t paddr, size_t size, int dir)
+ {
+ struct pci_dev *pdev = to_pci_dev(hwdev);
+- int ret;
+ struct dmar_domain *domain;
+- unsigned long start_addr;
++ unsigned long start_paddr;
+ struct iova *iova;
+ int prot = 0;
++ int ret;
+
+ BUG_ON(dir == DMA_NONE);
+ if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
+- return virt_to_bus(addr);
++ return paddr;
+
+ domain = get_valid_domain_for_dev(pdev);
+ if (!domain)
+ return 0;
+
+- addr = (void *)virt_to_phys(addr);
+- size = aligned_size((u64)addr, size);
++ size = aligned_size((u64)paddr, size);
+
+ iova = __intel_alloc_iova(hwdev, domain, size);
+ if (!iova)
+ goto error;
+
+- start_addr = iova->pfn_lo << PAGE_SHIFT_4K;
++ start_paddr = iova->pfn_lo << PAGE_SHIFT_4K;
+
+ /*
+ * Check if DMAR supports zero-length reads on write only
+@@ -1887,36 +1941,89 @@ static dma_addr_t intel_map_single(struct device *hwdev, void *addr,
+ if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
+ prot |= DMA_PTE_WRITE;
+ /*
+- * addr - (addr + size) might be partial page, we should map the whole
++ * paddr - (paddr + size) might be partial page, we should map the whole
+ * page. Note: if two part of one page are separately mapped, we
+- * might have two guest_addr mapping to the same host addr, but this
++ * might have two guest_addr mapping to the same host paddr, but this
+ * is not a big problem
+ */
+- ret = domain_page_mapping(domain, start_addr,
+- ((u64)addr) & PAGE_MASK_4K, size, prot);
++ ret = domain_page_mapping(domain, start_paddr,
++ ((u64)paddr) & PAGE_MASK_4K, size, prot);
+ if (ret)
+ goto error;
+
+ pr_debug("Device %s request: %lx@%llx mapping: %lx@%llx, dir %d\n",
+- pci_name(pdev), size, (u64)addr,
+- size, (u64)start_addr, dir);
++ pci_name(pdev), size, (u64)paddr,
++ size, (u64)start_paddr, dir);
+
+ /* it's a non-present to present mapping */
+ ret = iommu_flush_iotlb_psi(domain->iommu, domain->id,
+- start_addr, size >> PAGE_SHIFT_4K, 1);
++ start_paddr, size >> PAGE_SHIFT_4K, 1);
+ if (ret)
+ iommu_flush_write_buffer(domain->iommu);
+
+- return (start_addr + ((u64)addr & (~PAGE_MASK_4K)));
++ return (start_paddr + ((u64)paddr & (~PAGE_MASK_4K)));
+
+ error:
+ if (iova)
+ __free_iova(&domain->iovad, iova);
+ printk(KERN_ERR"Device %s request: %lx@%llx dir %d --- failed\n",
+- pci_name(pdev), size, (u64)addr, dir);
++ pci_name(pdev), size, (u64)paddr, dir);
+ return 0;
+ }
+
++static void flush_unmaps(void)
++{
++ int i, j;
++
++ timer_on = 0;
++
++ /* just flush them all */
++ for (i = 0; i < g_num_of_iommus; i++) {
++ if (deferred_flush[i].next) {
++ iommu_flush_iotlb_global(&g_iommus[i], 0);
++ for (j = 0; j < deferred_flush[i].next; j++) {
++ __free_iova(&deferred_flush[i].domain[j]->iovad,
++ deferred_flush[i].iova[j]);
++ }
++ deferred_flush[i].next = 0;
++ }
++ }
++
++ list_size = 0;
++}
++
++static void flush_unmaps_timeout(unsigned long data)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&async_umap_flush_lock, flags);
++ flush_unmaps();
++ spin_unlock_irqrestore(&async_umap_flush_lock, flags);
++}
++
++static void add_unmap(struct dmar_domain *dom, struct iova *iova)
++{
++ unsigned long flags;
++ int next, iommu_id;
++
++ spin_lock_irqsave(&async_umap_flush_lock, flags);
++ if (list_size == HIGH_WATER_MARK)
++ flush_unmaps();
++
++ iommu_id = dom->iommu - g_iommus;
++ next = deferred_flush[iommu_id].next;
++ deferred_flush[iommu_id].domain[next] = dom;
++ deferred_flush[iommu_id].iova[next] = iova;
++ deferred_flush[iommu_id].next++;
++
++ if (!timer_on) {
++ mod_timer(&unmap_timer, jiffies + msecs_to_jiffies(10));
++ timer_on = 1;
++ }
++ list_size++;
++ spin_unlock_irqrestore(&async_umap_flush_lock, flags);
++}
++
+ static void intel_unmap_single(struct device *dev, dma_addr_t dev_addr,
+ size_t size, int dir)
+ {
+@@ -1944,13 +2051,19 @@ static void intel_unmap_single(struct device *dev, dma_addr_t dev_addr,
+ dma_pte_clear_range(domain, start_addr, start_addr + size);
+ /* free page tables */
+ dma_pte_free_pagetable(domain, start_addr, start_addr + size);
+-
+- if (iommu_flush_iotlb_psi(domain->iommu, domain->id, start_addr,
+- size >> PAGE_SHIFT_4K, 0))
+- iommu_flush_write_buffer(domain->iommu);
+-
+- /* free iova */
+- __free_iova(&domain->iovad, iova);
++ if (intel_iommu_strict) {
++ if (iommu_flush_iotlb_psi(domain->iommu,
++ domain->id, start_addr, size >> PAGE_SHIFT_4K, 0))
++ iommu_flush_write_buffer(domain->iommu);
++ /* free iova */
++ __free_iova(&domain->iovad, iova);
++ } else {
++ add_unmap(domain, iova);
++ /*
++ * queue up the release of the unmap to save the 1/6th of the
++ * cpu used up by the iotlb flush operation...
++ */
++ }
+ }
+
+ static void * intel_alloc_coherent(struct device *hwdev, size_t size,
+@@ -1968,7 +2081,7 @@ static void * intel_alloc_coherent(struct device *hwdev, size_t size,
+ return NULL;
+ memset(vaddr, 0, size);
+
+- *dma_handle = intel_map_single(hwdev, vaddr, size, DMA_BIDIRECTIONAL);
++ *dma_handle = intel_map_single(hwdev, virt_to_bus(vaddr), size, DMA_BIDIRECTIONAL);
+ if (*dma_handle)
+ return vaddr;
+ free_pages((unsigned long)vaddr, order);
+@@ -2289,6 +2402,7 @@ int __init intel_iommu_init(void)
+ printk(KERN_INFO
+ "PCI-DMA: Intel(R) Virtualization Technology for Directed I/O\n");
+
++ init_timer(&unmap_timer);
+ force_iommu = 1;
+ dma_ops = &intel_dma_ops;
+ return 0;
+diff --git a/drivers/pci/iova.c b/drivers/pci/iova.c
+index dbcdd6b..3ef4ac0 100644
+--- a/drivers/pci/iova.c
++++ b/drivers/pci/iova.c
+@@ -73,10 +73,11 @@ iova_get_pad_size(int size, unsigned int limit_pfn)
+ return pad_size;
+ }
+
+-static int __alloc_iova_range(struct iova_domain *iovad, unsigned long size,
+- unsigned long limit_pfn, struct iova *new, bool size_aligned)
++static int __alloc_and_insert_iova_range(struct iova_domain *iovad,
++ unsigned long size, unsigned long limit_pfn,
++ struct iova *new, bool size_aligned)
+ {
+- struct rb_node *curr = NULL;
++ struct rb_node *prev, *curr = NULL;
+ unsigned long flags;
+ unsigned long saved_pfn;
+ unsigned int pad_size = 0;
+@@ -85,8 +86,10 @@ static int __alloc_iova_range(struct iova_domain *iovad, unsigned long size,
+ spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
+ saved_pfn = limit_pfn;
+ curr = __get_cached_rbnode(iovad, &limit_pfn);
++ prev = curr;
+ while (curr) {
+ struct iova *curr_iova = container_of(curr, struct iova, node);
++
+ if (limit_pfn < curr_iova->pfn_lo)
+ goto move_left;
+ else if (limit_pfn < curr_iova->pfn_hi)
+@@ -100,6 +103,7 @@ static int __alloc_iova_range(struct iova_domain *iovad, unsigned long size,
+ adjust_limit_pfn:
+ limit_pfn = curr_iova->pfn_lo - 1;
+ move_left:
++ prev = curr;
+ curr = rb_prev(curr);
+ }
+
+@@ -116,7 +120,33 @@ move_left:
+ new->pfn_lo = limit_pfn - (size + pad_size) + 1;
+ new->pfn_hi = new->pfn_lo + size - 1;
+
++ /* Insert the new_iova into domain rbtree by holding writer lock */
++ /* Add new node and rebalance tree. */
++ {
++ struct rb_node **entry = &((prev)), *parent = NULL;
++ /* Figure out where to put new node */
++ while (*entry) {
++ struct iova *this = container_of(*entry,
++ struct iova, node);
++ parent = *entry;
++
++ if (new->pfn_lo < this->pfn_lo)
++ entry = &((*entry)->rb_left);
++ else if (new->pfn_lo > this->pfn_lo)
++ entry = &((*entry)->rb_right);
++ else
++ BUG(); /* this should not happen */
++ }
++
++ /* Add new node and rebalance tree. */
++ rb_link_node(&new->node, parent, entry);
++ rb_insert_color(&new->node, &iovad->rbroot);
++ }
++ __cached_rbnode_insert_update(iovad, saved_pfn, new);
++
+ spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
++
++
+ return 0;
+ }
+
+@@ -172,23 +202,15 @@ alloc_iova(struct iova_domain *iovad, unsigned long size,
+ size = __roundup_pow_of_two(size);
+
+ spin_lock_irqsave(&iovad->iova_alloc_lock, flags);
+- ret = __alloc_iova_range(iovad, size, limit_pfn, new_iova,
+- size_aligned);
++ ret = __alloc_and_insert_iova_range(iovad, size, limit_pfn,
++ new_iova, size_aligned);
+
++ spin_unlock_irqrestore(&iovad->iova_alloc_lock, flags);
+ if (ret) {
+- spin_unlock_irqrestore(&iovad->iova_alloc_lock, flags);
+ free_iova_mem(new_iova);
+ return NULL;
+ }
+
+- /* Insert the new_iova into domain rbtree by holding writer lock */
+- spin_lock(&iovad->iova_rbtree_lock);
+- iova_insert_rbtree(&iovad->rbroot, new_iova);
+- __cached_rbnode_insert_update(iovad, limit_pfn, new_iova);
+- spin_unlock(&iovad->iova_rbtree_lock);
+-
+- spin_unlock_irqrestore(&iovad->iova_alloc_lock, flags);
+-
+ return new_iova;
+ }
+
+diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
+index e571c72..e8d94fa 100644
+--- a/drivers/pci/pci-driver.c
++++ b/drivers/pci/pci-driver.c
+@@ -182,15 +182,18 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
+ struct mempolicy *oldpol;
+ cpumask_t oldmask = current->cpus_allowed;
+ int node = pcibus_to_node(dev->bus);
+- if (node >= 0 && node_online(node))
+- set_cpus_allowed(current, node_to_cpumask(node));
++
++ if (node >= 0) {
++ node_to_cpumask_ptr(nodecpumask, node);
++ set_cpus_allowed_ptr(current, nodecpumask);
++ }
+ /* And set default memory allocation policy */
+ oldpol = current->mempolicy;
+ current->mempolicy = NULL; /* fall back to system default policy */
+ #endif
+ error = drv->probe(dev, id);
+ #ifdef CONFIG_NUMA
+- set_cpus_allowed(current, oldmask);
++ set_cpus_allowed_ptr(current, &oldmask);
+ current->mempolicy = oldpol;
+ #endif
+ return error;
+diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
+index 8dcf145..271d41c 100644
+--- a/drivers/pci/pci-sysfs.c
++++ b/drivers/pci/pci-sysfs.c
+@@ -21,6 +21,7 @@
+ #include <linux/topology.h>
+ #include <linux/mm.h>
+ #include <linux/capability.h>
++#include <linux/pci-aspm.h>
+ #include "pci.h"
+
+ static int sysfs_initialized; /* = 0 */
+@@ -73,8 +74,23 @@ static ssize_t local_cpus_show(struct device *dev,
+
+ mask = pcibus_to_cpumask(to_pci_dev(dev)->bus);
+ len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask);
+- strcat(buf,"\n");
+- return 1+len;
++ buf[len++] = '\n';
++ buf[len] = '\0';
++ return len;
++}
++
++
++static ssize_t local_cpulist_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ cpumask_t mask;
++ int len;
++
++ mask = pcibus_to_cpumask(to_pci_dev(dev)->bus);
++ len = cpulist_scnprintf(buf, PAGE_SIZE-2, mask);
++ buf[len++] = '\n';
++ buf[len] = '\0';
++ return len;
+ }
+
+ /* show resources */
+@@ -201,6 +217,7 @@ struct device_attribute pci_dev_attrs[] = {
+ __ATTR_RO(class),
+ __ATTR_RO(irq),
+ __ATTR_RO(local_cpus),
++ __ATTR_RO(local_cpulist),
+ __ATTR_RO(modalias),
+ #ifdef CONFIG_NUMA
+ __ATTR_RO(numa_node),
+@@ -342,6 +359,58 @@ pci_write_config(struct kobject *kobj, struct bin_attribute *bin_attr,
+ return count;
+ }
+
++static ssize_t
++pci_read_vpd(struct kobject *kobj, struct bin_attribute *bin_attr,
++ char *buf, loff_t off, size_t count)
++{
++ struct pci_dev *dev =
++ to_pci_dev(container_of(kobj, struct device, kobj));
++ int end;
++ int ret;
++
++ if (off > bin_attr->size)
++ count = 0;
++ else if (count > bin_attr->size - off)
++ count = bin_attr->size - off;
++ end = off + count;
++
++ while (off < end) {
++ ret = dev->vpd->ops->read(dev, off, end - off, buf);
++ if (ret < 0)
++ return ret;
++ buf += ret;
++ off += ret;
++ }
++
++ return count;
++}
++
++static ssize_t
++pci_write_vpd(struct kobject *kobj, struct bin_attribute *bin_attr,
++ char *buf, loff_t off, size_t count)
++{
++ struct pci_dev *dev =
++ to_pci_dev(container_of(kobj, struct device, kobj));
++ int end;
++ int ret;
++
++ if (off > bin_attr->size)
++ count = 0;
++ else if (count > bin_attr->size - off)
++ count = bin_attr->size - off;
++ end = off + count;
++
++ while (off < end) {
++ ret = dev->vpd->ops->write(dev, off, end - off, buf);
++ if (ret < 0)
++ return ret;
++ buf += ret;
++ off += ret;
++ }
++
++ return count;
++}
++
+ #ifdef HAVE_PCI_LEGACY
+ /**
+ * pci_read_legacy_io - read byte(s) from legacy I/O port space
+@@ -610,7 +679,7 @@ int __attribute__ ((weak)) pcibios_add_platform_entries(struct pci_dev *dev)
+
+ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
+ {
+- struct bin_attribute *rom_attr = NULL;
++ struct bin_attribute *attr = NULL;
+ int retval;
+
+ if (!sysfs_initialized)
+@@ -623,22 +692,41 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
+ if (retval)
+ goto err;
+
++ /* If the device has VPD, try to expose it in sysfs. */
++ if (pdev->vpd) {
++ attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
++ if (attr) {
++ pdev->vpd->attr = attr;
++ attr->size = pdev->vpd->ops->get_size(pdev);
++ attr->attr.name = "vpd";
++ attr->attr.mode = S_IRUGO | S_IWUSR;
++ attr->read = pci_read_vpd;
++ attr->write = pci_write_vpd;
++ retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
++ if (retval)
++ goto err_vpd;
++ } else {
++ retval = -ENOMEM;
++ goto err_config_file;
++ }
++ }
++
+ retval = pci_create_resource_files(pdev);
+ if (retval)
+- goto err_bin_file;
++ goto err_vpd_file;
+
+ /* If the device has a ROM, try to expose it in sysfs. */
+ if (pci_resource_len(pdev, PCI_ROM_RESOURCE) ||
+ (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)) {
+- rom_attr = kzalloc(sizeof(*rom_attr), GFP_ATOMIC);
+- if (rom_attr) {
+- pdev->rom_attr = rom_attr;
+- rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
+- rom_attr->attr.name = "rom";
+- rom_attr->attr.mode = S_IRUSR;
+- rom_attr->read = pci_read_rom;
+- rom_attr->write = pci_write_rom;
+- retval = sysfs_create_bin_file(&pdev->dev.kobj, rom_attr);
++ attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
++ if (attr) {
++ pdev->rom_attr = attr;
++ attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
++ attr->attr.name = "rom";
++ attr->attr.mode = S_IRUSR;
++ attr->read = pci_read_rom;
++ attr->write = pci_write_rom;
++ retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
+ if (retval)
+ goto err_rom;
+ } else {
+@@ -650,16 +738,24 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
+ if (pcibios_add_platform_entries(pdev))
+ goto err_rom_file;
+
++ pcie_aspm_create_sysfs_dev_files(pdev);
++
+ return 0;
+
+ err_rom_file:
+ if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
+- sysfs_remove_bin_file(&pdev->dev.kobj, rom_attr);
++ sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
+ err_rom:
+- kfree(rom_attr);
++ kfree(pdev->rom_attr);
+ err_resource_files:
+ pci_remove_resource_files(pdev);
+-err_bin_file:
++err_vpd_file:
++ if (pdev->vpd) {
++ sysfs_remove_bin_file(&pdev->dev.kobj, pdev->vpd->attr);
++err_vpd:
++ kfree(pdev->vpd->attr);
++ }
++err_config_file:
+ if (pdev->cfg_size < 4096)
+ sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
+ else
+@@ -679,6 +775,12 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
+ if (!sysfs_initialized)
+ return;
+
++ pcie_aspm_remove_sysfs_dev_files(pdev);
++
++ if (pdev->vpd) {
++ sysfs_remove_bin_file(&pdev->dev.kobj, pdev->vpd->attr);
++ kfree(pdev->vpd->attr);
++ }
+ if (pdev->cfg_size < 4096)
+ sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
+ else
+diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
+index a4445b7..e4548ab 100644
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -18,6 +18,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/string.h>
+ #include <linux/log2.h>
++#include <linux/pci-aspm.h>
+ #include <asm/dma.h> /* isa_dma_bridge_buggy */
+ #include "pci.h"
+
+@@ -424,7 +425,7 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
+ */
+ if (state != PCI_D0 && dev->current_state > state) {
+ printk(KERN_ERR "%s(): %s: state=%d, current state=%d\n",
+- __FUNCTION__, pci_name(dev), state, dev->current_state);
++ __func__, pci_name(dev), state, dev->current_state);
+ return -EINVAL;
+ } else if (dev->current_state == state)
+ return 0; /* we're already there */
+@@ -501,6 +502,9 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
+ if (need_restore)
+ pci_restore_bars(dev);
+
++ if (dev->bus->self)
++ pcie_aspm_pm_state_change(dev->bus->self);
++
+ return 0;
+ }
+
+diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
+index eabeb1f..0a497c1 100644
+--- a/drivers/pci/pci.h
++++ b/drivers/pci/pci.h
+@@ -18,6 +18,25 @@ extern int pci_user_write_config_byte(struct pci_dev *dev, int where, u8 val);
+ extern int pci_user_write_config_word(struct pci_dev *dev, int where, u16 val);
+ extern int pci_user_write_config_dword(struct pci_dev *dev, int where, u32 val);
+
++struct pci_vpd_ops {
++ int (*read)(struct pci_dev *dev, int pos, int size, char *buf);
++ int (*write)(struct pci_dev *dev, int pos, int size, const char *buf);
++ int (*get_size)(struct pci_dev *dev);
++ void (*release)(struct pci_dev *dev);
++};
++
++struct pci_vpd {
++ struct pci_vpd_ops *ops;
++ struct bin_attribute *attr; /* descriptor for sysfs VPD entry */
++};
++
++extern int pci_vpd_pci22_init(struct pci_dev *dev);
++static inline void pci_vpd_release(struct pci_dev *dev)
++{
++ if (dev->vpd)
++ dev->vpd->ops->release(dev);
++}
++
+ /* PCI /proc functions */
+ #ifdef CONFIG_PROC_FS
+ extern int pci_proc_attach_device(struct pci_dev *dev);
+diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig
+index 287a931..25b04fb 100644
+--- a/drivers/pci/pcie/Kconfig
++++ b/drivers/pci/pcie/Kconfig
+@@ -26,3 +26,23 @@ config HOTPLUG_PCI_PCIE
+ When in doubt, say N.
+
+ source "drivers/pci/pcie/aer/Kconfig"
++
++#
++# PCI Express ASPM
++#
++config PCIEASPM
++ bool "PCI Express ASPM support(Experimental)"
++ depends on PCI && EXPERIMENTAL && PCIEPORTBUS
++ default y
++ help
++ This enables PCI Express ASPM (Active State Power Management) and
++ Clock Power Management. ASPM supports state L0/L0s/L1.
++
++ When in doubt, say N.
++config PCIEASPM_DEBUG
++ bool "Debug PCI Express ASPM"
++ depends on PCIEASPM
++ default n
++ help
++ This enables PCI Express ASPM debug support. It will add per-device
++ interface to control ASPM.
+diff --git a/drivers/pci/pcie/Makefile b/drivers/pci/pcie/Makefile
+index e00fb99..11f6bb1 100644
+--- a/drivers/pci/pcie/Makefile
++++ b/drivers/pci/pcie/Makefile
+@@ -2,6 +2,9 @@
+ # Makefile for PCI-Express PORT Driver
+ #
+
++# Build PCI Express ASPM if needed
++obj-$(CONFIG_PCIEASPM) += aspm.o
++
+ pcieportdrv-y := portdrv_core.o portdrv_pci.o portdrv_bus.o
+
+ obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o
+diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
+index 7a62f7d..07c3bdb 100644
+--- a/drivers/pci/pcie/aer/aerdrv.c
++++ b/drivers/pci/pcie/aer/aerdrv.c
+@@ -220,7 +220,7 @@ static int __devinit aer_probe (struct pcie_device *dev,
+ /* Alloc rpc data structure */
+ if (!(rpc = aer_alloc_rpc(dev))) {
+ printk(KERN_DEBUG "%s: Alloc rpc fails on PCIE device[%s]\n",
+- __FUNCTION__, device->bus_id);
++ __func__, device->bus_id);
+ aer_remove(dev);
+ return -ENOMEM;
+ }
+@@ -229,7 +229,7 @@ static int __devinit aer_probe (struct pcie_device *dev,
+ if ((status = request_irq(dev->irq, aer_irq, IRQF_SHARED, "aerdrv",
+ dev))) {
+ printk(KERN_DEBUG "%s: Request ISR fails on PCIE device[%s]\n",
+- __FUNCTION__, device->bus_id);
++ __func__, device->bus_id);
+ aer_remove(dev);
+ return status;
+ }
+diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c
+index 8c199ae..96ac540 100644
+--- a/drivers/pci/pcie/aer/aerdrv_acpi.c
++++ b/drivers/pci/pcie/aer/aerdrv_acpi.c
+@@ -33,8 +33,11 @@ int aer_osc_setup(struct pcie_device *pciedev)
+ struct pci_dev *pdev = pciedev->port;
+ acpi_handle handle = 0;
+
++ if (acpi_pci_disabled)
++ return -1;
++
+ /* Find root host bridge */
+- while (pdev->bus && pdev->bus->self)
++ while (pdev->bus->self)
+ pdev = pdev->bus->self;
+ handle = acpi_get_pci_rootbridge_handle(
+ pci_domain_nr(pdev->bus), pdev->bus->number);
+diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
+index 3c0d8d1..aaa8239 100644
+--- a/drivers/pci/pcie/aer/aerdrv_core.c
++++ b/drivers/pci/pcie/aer/aerdrv_core.c
+@@ -117,6 +117,7 @@ int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
+ return 0;
+ }
+
++#if 0
+ int pci_cleanup_aer_correct_error_status(struct pci_dev *dev)
+ {
+ int pos;
+@@ -131,6 +132,7 @@ int pci_cleanup_aer_correct_error_status(struct pci_dev *dev)
+
+ return 0;
+ }
++#endif /* 0 */
+
+ static int find_device_iter(struct device *device, void *data)
+ {
+@@ -689,7 +691,7 @@ static void aer_isr_one_error(struct pcie_device *p_device,
+ e_info.flags |= AER_MULTI_ERROR_VALID_FLAG;
+ if (!(s_device = find_source_device(p_device->port, id))) {
+ printk(KERN_DEBUG "%s->can't find device of ID%04x\n",
+- __FUNCTION__, id);
++ __func__, id);
+ continue;
+ }
+ if (get_device_error_info(to_pci_dev(s_device), &e_info) ==
+@@ -757,5 +759,4 @@ EXPORT_SYMBOL_GPL(pci_find_aer_capability);
+ EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting);
+ EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting);
+ EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status);
+-EXPORT_SYMBOL_GPL(pci_cleanup_aer_correct_error_status);
+
+diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
+new file mode 100644
+index 0000000..61fedb2
+--- /dev/null
++++ b/drivers/pci/pcie/aspm.c
+@@ -0,0 +1,811 @@
++/*
++ * File: drivers/pci/pcie/aspm.c
++ * Enabling PCIE link L0s/L1 state and Clock Power Management
++ *
++ * Copyright (C) 2007 Intel
++ * Copyright (C) Zhang Yanmin (yanmin.zhang at intel.com)
++ * Copyright (C) Shaohua Li (shaohua.li at intel.com)
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/pci.h>
++#include <linux/pci_regs.h>
++#include <linux/errno.h>
++#include <linux/pm.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/pci-aspm.h>
++#include "../pci.h"
++
++#ifdef MODULE_PARAM_PREFIX
++#undef MODULE_PARAM_PREFIX
++#endif
++#define MODULE_PARAM_PREFIX "pcie_aspm."
++
++struct endpoint_state {
++ unsigned int l0s_acceptable_latency;
++ unsigned int l1_acceptable_latency;
++};
++
++struct pcie_link_state {
++ struct list_head sibiling;
++ struct pci_dev *pdev;
++
++ /* ASPM state */
++ unsigned int support_state;
++ unsigned int enabled_state;
++ unsigned int bios_aspm_state;
++ /* upstream component */
++ unsigned int l0s_upper_latency;
++ unsigned int l1_upper_latency;
++ /* downstream component */
++ unsigned int l0s_down_latency;
++ unsigned int l1_down_latency;
++ /* Clock PM state*/
++ unsigned int clk_pm_capable;
++ unsigned int clk_pm_enabled;
++ unsigned int bios_clk_state;
++
++ /*
++ * A pcie downstream port only has one slot under it, so at most there
++ * are 8 functions
++ */
++ struct endpoint_state endpoints[8];
++};
++
++static int aspm_disabled;
++static DEFINE_MUTEX(aspm_lock);
++static LIST_HEAD(link_list);
++
++#define POLICY_DEFAULT 0 /* BIOS default setting */
++#define POLICY_PERFORMANCE 1 /* high performance */
++#define POLICY_POWERSAVE 2 /* high power saving */
++static int aspm_policy;
++static const char *policy_str[] = {
++ [POLICY_DEFAULT] = "default",
++ [POLICY_PERFORMANCE] = "performance",
++ [POLICY_POWERSAVE] = "powersave"
++};
++
++static int policy_to_aspm_state(struct pci_dev *pdev)
++{
++ struct pcie_link_state *link_state = pdev->link_state;
++
++ switch (aspm_policy) {
++ case POLICY_PERFORMANCE:
++ /* Disable ASPM and Clock PM */
++ return 0;
++ case POLICY_POWERSAVE:
++ /* Enable ASPM L0s/L1 */
++ return PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1;
++ case POLICY_DEFAULT:
++ return link_state->bios_aspm_state;
++ }
++ return 0;
++}
++
++static int policy_to_clkpm_state(struct pci_dev *pdev)
++{
++ struct pcie_link_state *link_state = pdev->link_state;
++
++ switch (aspm_policy) {
++ case POLICY_PERFORMANCE:
++ /* Disable ASPM and Clock PM */
++ return 0;
++ case POLICY_POWERSAVE:
++ /* Disable Clock PM */
++ return 1;
++ case POLICY_DEFAULT:
++ return link_state->bios_clk_state;
++ }
++ return 0;
++}
++
++static void pcie_set_clock_pm(struct pci_dev *pdev, int enable)
++{
++ struct pci_dev *child_dev;
++ int pos;
++ u16 reg16;
++ struct pcie_link_state *link_state = pdev->link_state;
++
++ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
++ pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
++ if (!pos)
++ return;
++ pci_read_config_word(child_dev, pos + PCI_EXP_LNKCTL, ®16);
++ if (enable)
++ reg16 |= PCI_EXP_LNKCTL_CLKREQ_EN;
++ else
++ reg16 &= ~PCI_EXP_LNKCTL_CLKREQ_EN;
++ pci_write_config_word(child_dev, pos + PCI_EXP_LNKCTL, reg16);
++ }
++ link_state->clk_pm_enabled = !!enable;
++}
++
++static void pcie_check_clock_pm(struct pci_dev *pdev)
++{
++ int pos;
++ u32 reg32;
++ u16 reg16;
++ int capable = 1, enabled = 1;
++ struct pci_dev *child_dev;
++ struct pcie_link_state *link_state = pdev->link_state;
++
++ /* All functions should have the same cap and state, take the worst */
++ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
++ pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
++ if (!pos)
++ return;
++ pci_read_config_dword(child_dev, pos + PCI_EXP_LNKCAP, ®32);
++ if (!(reg32 & PCI_EXP_LNKCAP_CLKPM)) {
++ capable = 0;
++ enabled = 0;
++ break;
++ }
++ pci_read_config_word(child_dev, pos + PCI_EXP_LNKCTL, ®16);
++ if (!(reg16 & PCI_EXP_LNKCTL_CLKREQ_EN))
++ enabled = 0;
++ }
++ link_state->clk_pm_capable = capable;
++ link_state->clk_pm_enabled = enabled;
++ link_state->bios_clk_state = enabled;
++ pcie_set_clock_pm(pdev, policy_to_clkpm_state(pdev));
++}
++
++/*
++ * pcie_aspm_configure_common_clock: check if the 2 ends of a link
++ * could use common clock. If they are, configure them to use the
++ * common clock. That will reduce the ASPM state exit latency.
++ */
++static void pcie_aspm_configure_common_clock(struct pci_dev *pdev)
++{
++ int pos, child_pos;
++ u16 reg16 = 0;
++ struct pci_dev *child_dev;
++ int same_clock = 1;
++
++ /*
++ * all functions of a slot should have the same Slot Clock
++ * Configuration, so just check one function
++ * */
++ child_dev = list_entry(pdev->subordinate->devices.next, struct pci_dev,
++ bus_list);
++ BUG_ON(!child_dev->is_pcie);
++
++ /* Check downstream component if bit Slot Clock Configuration is 1 */
++ child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
++ pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKSTA, ®16);
++ if (!(reg16 & PCI_EXP_LNKSTA_SLC))
++ same_clock = 0;
++
++ /* Check upstream component if bit Slot Clock Configuration is 1 */
++ pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
++ pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, ®16);
++ if (!(reg16 & PCI_EXP_LNKSTA_SLC))
++ same_clock = 0;
++
++ /* Configure downstream component, all functions */
++ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
++ child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
++ pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKCTL,
++ ®16);
++ if (same_clock)
++ reg16 |= PCI_EXP_LNKCTL_CCC;
++ else
++ reg16 &= ~PCI_EXP_LNKCTL_CCC;
++ pci_write_config_word(child_dev, child_pos + PCI_EXP_LNKCTL,
++ reg16);
++ }
++
++ /* Configure upstream component */
++ pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16);
++ if (same_clock)
++ reg16 |= PCI_EXP_LNKCTL_CCC;
++ else
++ reg16 &= ~PCI_EXP_LNKCTL_CCC;
++ pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
++
++ /* retrain link */
++ reg16 |= PCI_EXP_LNKCTL_RL;
++ pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
++
++ /* Wait for link training end */
++ while (1) {
++ pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, ®16);
++ if (!(reg16 & PCI_EXP_LNKSTA_LT))
++ break;
++ cpu_relax();
++ }
++}
++
++/*
++ * calc_L0S_latency: Convert L0s latency encoding to ns
++ */
++static unsigned int calc_L0S_latency(unsigned int latency_encoding, int ac)
++{
++ unsigned int ns = 64;
++
++ if (latency_encoding == 0x7) {
++ if (ac)
++ ns = -1U;
++ else
++ ns = 5*1000; /* > 4us */
++ } else
++ ns *= (1 << latency_encoding);
++ return ns;
++}
++
++/*
++ * calc_L1_latency: Convert L1 latency encoding to ns
++ */
++static unsigned int calc_L1_latency(unsigned int latency_encoding, int ac)
++{
++ unsigned int ns = 1000;
++
++ if (latency_encoding == 0x7) {
++ if (ac)
++ ns = -1U;
++ else
++ ns = 65*1000; /* > 64us */
++ } else
++ ns *= (1 << latency_encoding);
++ return ns;
++}
++
++static void pcie_aspm_get_cap_device(struct pci_dev *pdev, u32 *state,
++ unsigned int *l0s, unsigned int *l1, unsigned int *enabled)
++{
++ int pos;
++ u16 reg16;
++ u32 reg32;
++ unsigned int latency;
++
++ pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
++ pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, ®32);
++ *state = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10;
++ if (*state != PCIE_LINK_STATE_L0S &&
++ *state != (PCIE_LINK_STATE_L1|PCIE_LINK_STATE_L0S))
++ *state = 0;
++ if (*state == 0)
++ return;
++
++ latency = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12;
++ *l0s = calc_L0S_latency(latency, 0);
++ if (*state & PCIE_LINK_STATE_L1) {
++ latency = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15;
++ *l1 = calc_L1_latency(latency, 0);
++ }
++ pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16);
++ *enabled = reg16 & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1);
++}
++
++static void pcie_aspm_cap_init(struct pci_dev *pdev)
++{
++ struct pci_dev *child_dev;
++ u32 state, tmp;
++ struct pcie_link_state *link_state = pdev->link_state;
++
++ /* upstream component states */
++ pcie_aspm_get_cap_device(pdev, &link_state->support_state,
++ &link_state->l0s_upper_latency,
++ &link_state->l1_upper_latency,
++ &link_state->enabled_state);
++ /* downstream component states, all functions have the same setting */
++ child_dev = list_entry(pdev->subordinate->devices.next, struct pci_dev,
++ bus_list);
++ pcie_aspm_get_cap_device(child_dev, &state,
++ &link_state->l0s_down_latency,
++ &link_state->l1_down_latency,
++ &tmp);
++ link_state->support_state &= state;
++ if (!link_state->support_state)
++ return;
++ link_state->enabled_state &= link_state->support_state;
++ link_state->bios_aspm_state = link_state->enabled_state;
++
++ /* ENDPOINT states*/
++ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
++ int pos;
++ u32 reg32;
++ unsigned int latency;
++ struct endpoint_state *ep_state =
++ &link_state->endpoints[PCI_FUNC(child_dev->devfn)];
++
++ if (child_dev->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
++ child_dev->pcie_type != PCI_EXP_TYPE_LEG_END)
++ continue;
++
++ pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
++ pci_read_config_dword(child_dev, pos + PCI_EXP_DEVCAP, ®32);
++ latency = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6;
++ latency = calc_L0S_latency(latency, 1);
++ ep_state->l0s_acceptable_latency = latency;
++ if (link_state->support_state & PCIE_LINK_STATE_L1) {
++ latency = (reg32 & PCI_EXP_DEVCAP_L1) >> 9;
++ latency = calc_L1_latency(latency, 1);
++ ep_state->l1_acceptable_latency = latency;
++ }
++ }
++}
++
++static unsigned int __pcie_aspm_check_state_one(struct pci_dev *pdev,
++ unsigned int state)
++{
++ struct pci_dev *parent_dev, *tmp_dev;
++ unsigned int latency, l1_latency = 0;
++ struct pcie_link_state *link_state;
++ struct endpoint_state *ep_state;
++
++ parent_dev = pdev->bus->self;
++ link_state = parent_dev->link_state;
++ state &= link_state->support_state;
++ if (state == 0)
++ return 0;
++ ep_state = &link_state->endpoints[PCI_FUNC(pdev->devfn)];
++
++ /*
++ * Check latency for endpoint device.
++ * TBD: The latency from the endpoint to root complex vary per
++ * switch's upstream link state above the device. Here we just do a
++ * simple check which assumes all links above the device can be in L1
++ * state, that is we just consider the worst case. If switch's upstream
++ * link can't be put into L0S/L1, then our check is too strictly.
++ */
++ tmp_dev = pdev;
++ while (state & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
++ parent_dev = tmp_dev->bus->self;
++ link_state = parent_dev->link_state;
++ if (state & PCIE_LINK_STATE_L0S) {
++ latency = max_t(unsigned int,
++ link_state->l0s_upper_latency,
++ link_state->l0s_down_latency);
++ if (latency > ep_state->l0s_acceptable_latency)
++ state &= ~PCIE_LINK_STATE_L0S;
++ }
++ if (state & PCIE_LINK_STATE_L1) {
++ latency = max_t(unsigned int,
++ link_state->l1_upper_latency,
++ link_state->l1_down_latency);
++ if (latency + l1_latency >
++ ep_state->l1_acceptable_latency)
++ state &= ~PCIE_LINK_STATE_L1;
++ }
++ if (!parent_dev->bus->self) /* parent_dev is a root port */
++ break;
++ else {
++ /*
++ * parent_dev is the downstream port of a switch, make
++ * tmp_dev the upstream port of the switch
++ */
++ tmp_dev = parent_dev->bus->self;
++ /*
++ * every switch on the path to root complex need 1 more
++ * microsecond for L1. Spec doesn't mention L0S.
++ */
++ if (state & PCIE_LINK_STATE_L1)
++ l1_latency += 1000;
++ }
++ }
++ return state;
++}
++
++static unsigned int pcie_aspm_check_state(struct pci_dev *pdev,
++ unsigned int state)
++{
++ struct pci_dev *child_dev;
++
++ /* If no child, disable the link */
++ if (list_empty(&pdev->subordinate->devices))
++ return 0;
++ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
++ if (child_dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
++ /*
++ * If downstream component of a link is pci bridge, we
++ * disable ASPM for now for the link
++ * */
++ state = 0;
++ break;
++ }
++ if ((child_dev->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
++ child_dev->pcie_type != PCI_EXP_TYPE_LEG_END))
++ continue;
++ /* Device not in D0 doesn't need check latency */
++ if (child_dev->current_state == PCI_D1 ||
++ child_dev->current_state == PCI_D2 ||
++ child_dev->current_state == PCI_D3hot ||
++ child_dev->current_state == PCI_D3cold)
++ continue;
++ state = __pcie_aspm_check_state_one(child_dev, state);
++ }
++ return state;
++}
++
++static void __pcie_aspm_config_one_dev(struct pci_dev *pdev, unsigned int state)
++{
++ u16 reg16;
++ int pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
++
++ pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16);
++ reg16 &= ~0x3;
++ reg16 |= state;
++ pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
++}
++
++static void __pcie_aspm_config_link(struct pci_dev *pdev, unsigned int state)
++{
++ struct pci_dev *child_dev;
++ int valid = 1;
++ struct pcie_link_state *link_state = pdev->link_state;
++
++ /*
++ * if the downstream component has pci bridge function, don't do ASPM
++ * now
++ */
++ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
++ if (child_dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
++ valid = 0;
++ break;
++ }
++ }
++ if (!valid)
++ return;
++
++ /*
++ * spec 2.0 suggests all functions should be configured the same
++ * setting for ASPM. Enabling ASPM L1 should be done in upstream
++ * component first and then downstream, and vice versa for disabling
++ * ASPM L1. Spec doesn't mention L0S.
++ */
++ if (state & PCIE_LINK_STATE_L1)
++ __pcie_aspm_config_one_dev(pdev, state);
++
++ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list)
++ __pcie_aspm_config_one_dev(child_dev, state);
++
++ if (!(state & PCIE_LINK_STATE_L1))
++ __pcie_aspm_config_one_dev(pdev, state);
++
++ link_state->enabled_state = state;
++}
++
++static void __pcie_aspm_configure_link_state(struct pci_dev *pdev,
++ unsigned int state)
++{
++ struct pcie_link_state *link_state = pdev->link_state;
++
++ if (link_state->support_state == 0)
++ return;
++ state &= PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1;
++
++ /* state 0 means disabling aspm */
++ state = pcie_aspm_check_state(pdev, state);
++ if (link_state->enabled_state == state)
++ return;
++ __pcie_aspm_config_link(pdev, state);
++}
++
++/*
++ * pcie_aspm_configure_link_state: enable/disable PCI express link state
++ * @pdev: the root port or switch downstream port
++ */
++static void pcie_aspm_configure_link_state(struct pci_dev *pdev,
++ unsigned int state)
++{
++ down_read(&pci_bus_sem);
++ mutex_lock(&aspm_lock);
++ __pcie_aspm_configure_link_state(pdev, state);
++ mutex_unlock(&aspm_lock);
++ up_read(&pci_bus_sem);
++}
++
++static void free_link_state(struct pci_dev *pdev)
++{
++ kfree(pdev->link_state);
++ pdev->link_state = NULL;
++}
++
++/*
++ * pcie_aspm_init_link_state: Initiate PCI express link state.
++ * It is called after the pcie and its children devices are scaned.
++ * @pdev: the root port or switch downstream port
++ */
++void pcie_aspm_init_link_state(struct pci_dev *pdev)
++{
++ unsigned int state;
++ struct pcie_link_state *link_state;
++ int error = 0;
++
++ if (aspm_disabled || !pdev->is_pcie || pdev->link_state)
++ return;
++ if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
++ pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
++ return;
++ down_read(&pci_bus_sem);
++ if (list_empty(&pdev->subordinate->devices))
++ goto out;
++
++ mutex_lock(&aspm_lock);
++
++ link_state = kzalloc(sizeof(*link_state), GFP_KERNEL);
++ if (!link_state)
++ goto unlock_out;
++ pdev->link_state = link_state;
++
++ pcie_aspm_configure_common_clock(pdev);
++
++ pcie_aspm_cap_init(pdev);
++
++ /* config link state to avoid BIOS error */
++ state = pcie_aspm_check_state(pdev, policy_to_aspm_state(pdev));
++ __pcie_aspm_config_link(pdev, state);
++
++ pcie_check_clock_pm(pdev);
++
++ link_state->pdev = pdev;
++ list_add(&link_state->sibiling, &link_list);
++
++unlock_out:
++ if (error)
++ free_link_state(pdev);
++ mutex_unlock(&aspm_lock);
++out:
++ up_read(&pci_bus_sem);
++}
++
++/* @pdev: the endpoint device */
++void pcie_aspm_exit_link_state(struct pci_dev *pdev)
++{
++ struct pci_dev *parent = pdev->bus->self;
++ struct pcie_link_state *link_state = parent->link_state;
++
++ if (aspm_disabled || !pdev->is_pcie || !parent || !link_state)
++ return;
++ if (parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
++ parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
++ return;
++ down_read(&pci_bus_sem);
++ mutex_lock(&aspm_lock);
++
++ /*
++ * All PCIe functions are in one slot, remove one function will remove
++ * the the whole slot, so just wait
++ */
++ if (!list_empty(&parent->subordinate->devices))
++ goto out;
++
++ /* All functions are removed, so just disable ASPM for the link */
++ __pcie_aspm_config_one_dev(parent, 0);
++ list_del(&link_state->sibiling);
++ /* Clock PM is for endpoint device */
++
++ free_link_state(parent);
++out:
++ mutex_unlock(&aspm_lock);
++ up_read(&pci_bus_sem);
++}
++
++/* @pdev: the root port or switch downstream port */
++void pcie_aspm_pm_state_change(struct pci_dev *pdev)
++{
++ struct pcie_link_state *link_state = pdev->link_state;
++
++ if (aspm_disabled || !pdev->is_pcie || !pdev->link_state)
++ return;
++ if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
++ pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
++ return;
++ /*
++ * devices changed PM state, we should recheck if latency meets all
++ * functions' requirement
++ */
++ pcie_aspm_configure_link_state(pdev, link_state->enabled_state);
++}
++
++/*
++ * pci_disable_link_state - disable pci device's link state, so the link will
++ * never enter specific states
++ */
++void pci_disable_link_state(struct pci_dev *pdev, int state)
++{
++ struct pci_dev *parent = pdev->bus->self;
++ struct pcie_link_state *link_state;
++
++ if (aspm_disabled || !pdev->is_pcie)
++ return;
++ if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
++ pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
++ parent = pdev;
++ if (!parent || !parent->link_state)
++ return;
++
++ down_read(&pci_bus_sem);
++ mutex_lock(&aspm_lock);
++ link_state = parent->link_state;
++ link_state->support_state &=
++ ~(state & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1));
++ if (state & PCIE_LINK_STATE_CLKPM)
++ link_state->clk_pm_capable = 0;
++
++ __pcie_aspm_configure_link_state(parent, link_state->enabled_state);
++ if (!link_state->clk_pm_capable && link_state->clk_pm_enabled)
++ pcie_set_clock_pm(parent, 0);
++ mutex_unlock(&aspm_lock);
++ up_read(&pci_bus_sem);
++}
++EXPORT_SYMBOL(pci_disable_link_state);
++
++static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp)
++{
++ int i;
++ struct pci_dev *pdev;
++ struct pcie_link_state *link_state;
++
++ for (i = 0; i < ARRAY_SIZE(policy_str); i++)
++ if (!strncmp(val, policy_str[i], strlen(policy_str[i])))
++ break;
++ if (i >= ARRAY_SIZE(policy_str))
++ return -EINVAL;
++ if (i == aspm_policy)
++ return 0;
++
++ down_read(&pci_bus_sem);
++ mutex_lock(&aspm_lock);
++ aspm_policy = i;
++ list_for_each_entry(link_state, &link_list, sibiling) {
++ pdev = link_state->pdev;
++ __pcie_aspm_configure_link_state(pdev,
++ policy_to_aspm_state(pdev));
++ if (link_state->clk_pm_capable &&
++ link_state->clk_pm_enabled != policy_to_clkpm_state(pdev))
++ pcie_set_clock_pm(pdev, policy_to_clkpm_state(pdev));
++
++ }
++ mutex_unlock(&aspm_lock);
++ up_read(&pci_bus_sem);
++ return 0;
++}
++
++static int pcie_aspm_get_policy(char *buffer, struct kernel_param *kp)
++{
++ int i, cnt = 0;
++ for (i = 0; i < ARRAY_SIZE(policy_str); i++)
++ if (i == aspm_policy)
++ cnt += sprintf(buffer + cnt, "[%s] ", policy_str[i]);
++ else
++ cnt += sprintf(buffer + cnt, "%s ", policy_str[i]);
++ return cnt;
++}
++
++module_param_call(policy, pcie_aspm_set_policy, pcie_aspm_get_policy,
++ NULL, 0644);
++
++#ifdef CONFIG_PCIEASPM_DEBUG
++static ssize_t link_state_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct pci_dev *pci_device = to_pci_dev(dev);
++ struct pcie_link_state *link_state = pci_device->link_state;
++
++ return sprintf(buf, "%d\n", link_state->enabled_state);
++}
++
++static ssize_t link_state_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf,
++ size_t n)
++{
++ struct pci_dev *pci_device = to_pci_dev(dev);
++ int state;
++
++ if (n < 1)
++ return -EINVAL;
++ state = buf[0]-'0';
++ if (state >= 0 && state <= 3) {
++ /* setup link aspm state */
++ pcie_aspm_configure_link_state(pci_device, state);
++ return n;
++ }
++
++ return -EINVAL;
++}
++
++static ssize_t clk_ctl_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct pci_dev *pci_device = to_pci_dev(dev);
++ struct pcie_link_state *link_state = pci_device->link_state;
++
++ return sprintf(buf, "%d\n", link_state->clk_pm_enabled);
++}
++
++static ssize_t clk_ctl_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf,
++ size_t n)
++{
++ struct pci_dev *pci_device = to_pci_dev(dev);
++ int state;
++
++ if (n < 1)
++ return -EINVAL;
++ state = buf[0]-'0';
++
++ down_read(&pci_bus_sem);
++ mutex_lock(&aspm_lock);
++ pcie_set_clock_pm(pci_device, !!state);
++ mutex_unlock(&aspm_lock);
++ up_read(&pci_bus_sem);
++
++ return n;
++}
++
++static DEVICE_ATTR(link_state, 0644, link_state_show, link_state_store);
++static DEVICE_ATTR(clk_ctl, 0644, clk_ctl_show, clk_ctl_store);
++
++static char power_group[] = "power";
++void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev)
++{
++ struct pcie_link_state *link_state = pdev->link_state;
++
++ if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
++ pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
++ return;
++
++ if (link_state->support_state)
++ sysfs_add_file_to_group(&pdev->dev.kobj,
++ &dev_attr_link_state.attr, power_group);
++ if (link_state->clk_pm_capable)
++ sysfs_add_file_to_group(&pdev->dev.kobj,
++ &dev_attr_clk_ctl.attr, power_group);
++}
++
++void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
++{
++ struct pcie_link_state *link_state = pdev->link_state;
++
++ if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
++ pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
++ return;
++
++ if (link_state->support_state)
++ sysfs_remove_file_from_group(&pdev->dev.kobj,
++ &dev_attr_link_state.attr, power_group);
++ if (link_state->clk_pm_capable)
++ sysfs_remove_file_from_group(&pdev->dev.kobj,
++ &dev_attr_clk_ctl.attr, power_group);
++}
++#endif
++
++static int __init pcie_aspm_disable(char *str)
++{
++ aspm_disabled = 1;
++ return 1;
++}
++
++__setup("pcie_noaspm", pcie_aspm_disable);
++
++#ifdef CONFIG_ACPI
++#include <acpi/acpi_bus.h>
++#include <linux/pci-acpi.h>
++static void pcie_aspm_platform_init(void)
++{
++ pcie_osc_support_set(OSC_ACTIVE_STATE_PWR_SUPPORT|
++ OSC_CLOCK_PWR_CAPABILITY_SUPPORT);
++}
++#else
++static inline void pcie_aspm_platform_init(void) { }
++#endif
++
++static int __init pcie_aspm_init(void)
++{
++ if (aspm_disabled)
++ return 0;
++ pcie_aspm_platform_init();
++ return 0;
++}
++
++fs_initcall(pcie_aspm_init);
+diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
+index 23d9eb0..fb0abfa 100644
+--- a/drivers/pci/pcie/portdrv_core.c
++++ b/drivers/pci/pcie/portdrv_core.c
+@@ -150,7 +150,7 @@ static int assign_interrupt_mode(struct pci_dev *dev, int *vectors, int mask)
+ if (pos) {
+ struct msix_entry msix_entries[PCIE_PORT_DEVICE_MAXSERVICES] =
+ {{0, 0}, {0, 1}, {0, 2}, {0, 3}};
+- printk("%s Found MSIX capability\n", __FUNCTION__);
++ printk("%s Found MSIX capability\n", __func__);
+ status = pci_enable_msix(dev, msix_entries, nvec);
+ if (!status) {
+ int j = 0;
+@@ -165,7 +165,7 @@ static int assign_interrupt_mode(struct pci_dev *dev, int *vectors, int mask)
+ if (status) {
+ pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+ if (pos) {
+- printk("%s Found MSI capability\n", __FUNCTION__);
++ printk("%s Found MSI capability\n", __func__);
+ status = pci_enable_msi(dev);
+ if (!status) {
+ interrupt_mode = PCIE_PORT_MSI_MODE;
+diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
+index 26057f9..51d1632 100644
+--- a/drivers/pci/pcie/portdrv_pci.c
++++ b/drivers/pci/pcie/portdrv_pci.c
+@@ -93,7 +93,7 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev,
+ if (!dev->irq && dev->pin) {
+ printk(KERN_WARNING
+ "%s->Dev[%04x:%04x] has invalid IRQ. Check vendor BIOS\n",
+- __FUNCTION__, dev->vendor, dev->device);
++ __func__, dev->vendor, dev->device);
+ }
+ if (pcie_port_device_register(dev)) {
+ pci_disable_device(dev);
+diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
+index 2db2e4b..f991359 100644
+--- a/drivers/pci/probe.c
++++ b/drivers/pci/probe.c
+@@ -9,6 +9,7 @@
+ #include <linux/slab.h>
+ #include <linux/module.h>
+ #include <linux/cpumask.h>
++#include <linux/pci-aspm.h>
+ #include "pci.h"
+
+ #define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */
+@@ -20,18 +21,27 @@
+ LIST_HEAD(pci_root_buses);
+ EXPORT_SYMBOL(pci_root_buses);
+
+-LIST_HEAD(pci_devices);
++
++static int find_anything(struct device *dev, void *data)
++{
++ return 1;
++}
+
+ /*
+ * Some device drivers need know if pci is initiated.
+ * Basically, we think pci is not initiated when there
+- * is no device in list of pci_devices.
++ * is no device to be found on the pci_bus_type.
+ */
+ int no_pci_devices(void)
+ {
+- return list_empty(&pci_devices);
+-}
++ struct device *dev;
++ int no_devices;
+
++ dev = bus_find_device(&pci_bus_type, NULL, NULL, find_anything);
++ no_devices = (dev == NULL);
++ put_device(dev);
++ return no_devices;
++}
+ EXPORT_SYMBOL(no_pci_devices);
+
+ #ifdef HAVE_PCI_LEGACY
+@@ -82,6 +92,7 @@ void pci_remove_legacy_files(struct pci_bus *bus) { return; }
+ * PCI Bus Class Devices
+ */
+ static ssize_t pci_bus_show_cpuaffinity(struct device *dev,
++ int type,
+ struct device_attribute *attr,
+ char *buf)
+ {
+@@ -89,12 +100,30 @@ static ssize_t pci_bus_show_cpuaffinity(struct device *dev,
+ cpumask_t cpumask;
+
+ cpumask = pcibus_to_cpumask(to_pci_bus(dev));
+- ret = cpumask_scnprintf(buf, PAGE_SIZE, cpumask);
+- if (ret < PAGE_SIZE)
+- buf[ret++] = '\n';
++ ret = type?
++ cpulist_scnprintf(buf, PAGE_SIZE-2, cpumask):
++ cpumask_scnprintf(buf, PAGE_SIZE-2, cpumask);
++ buf[ret++] = '\n';
++ buf[ret] = '\0';
+ return ret;
+ }
+-DEVICE_ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpuaffinity, NULL);
++
++static ssize_t inline pci_bus_show_cpumaskaffinity(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ return pci_bus_show_cpuaffinity(dev, 0, attr, buf);
++}
++
++static ssize_t inline pci_bus_show_cpulistaffinity(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ return pci_bus_show_cpuaffinity(dev, 1, attr, buf);
++}
++
++DEVICE_ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpumaskaffinity, NULL);
++DEVICE_ATTR(cpulistaffinity, S_IRUGO, pci_bus_show_cpulistaffinity, NULL);
+
+ /*
+ * PCI Bus Class
+@@ -225,7 +254,7 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
+ res->flags |= l & ~PCI_BASE_ADDRESS_IO_MASK;
+ }
+ res->end = res->start + (unsigned long) sz;
+- res->flags |= pci_calc_resource_flags(l);
++ res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN;
+ if (is_64bit_memory(l)) {
+ u32 szhi, lhi;
+
+@@ -278,7 +307,8 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
+ if (sz) {
+ res->flags = (l & IORESOURCE_ROM_ENABLE) |
+ IORESOURCE_MEM | IORESOURCE_PREFETCH |
+- IORESOURCE_READONLY | IORESOURCE_CACHEABLE;
++ IORESOURCE_READONLY | IORESOURCE_CACHEABLE |
++ IORESOURCE_SIZEALIGN;
+ res->start = l & PCI_ROM_ADDRESS_MASK;
+ res->end = res->start + (unsigned long) sz;
+ }
+@@ -388,8 +418,8 @@ static struct pci_bus * pci_alloc_bus(void)
+ return b;
+ }
+
+-static struct pci_bus * __devinit
+-pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
++static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
++ struct pci_dev *bridge, int busnr)
+ {
+ struct pci_bus *child;
+ int i;
+@@ -622,7 +652,9 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
+ pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
+ }
+
+- sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number);
++ sprintf(child->name,
++ (is_cardbus ? "PCI CardBus %04x:%02x" : "PCI Bus %04x:%02x"),
++ pci_domain_nr(bus), child->number);
+
+ /* Has only triggered on CardBus, fixup is in yenta_socket */
+ while (bus->parent) {
+@@ -782,6 +814,7 @@ static void pci_release_dev(struct device *dev)
+ struct pci_dev *pci_dev;
+
+ pci_dev = to_pci_dev(dev);
++ pci_vpd_release(pci_dev);
+ kfree(pci_dev);
+ }
+
+@@ -849,7 +882,6 @@ struct pci_dev *alloc_pci_dev(void)
+ if (!dev)
+ return NULL;
+
+- INIT_LIST_HEAD(&dev->global_list);
+ INIT_LIST_HEAD(&dev->bus_list);
+
+ pci_msi_init_pci_dev(dev);
+@@ -862,8 +894,7 @@ EXPORT_SYMBOL(alloc_pci_dev);
+ * Read the config data for a PCI device, sanity-check it
+ * and fill in the dev structure...
+ */
+-static struct pci_dev * __devinit
+-pci_scan_device(struct pci_bus *bus, int devfn)
++static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
+ {
+ struct pci_dev *dev;
+ u32 l;
+@@ -922,6 +953,8 @@ pci_scan_device(struct pci_bus *bus, int devfn)
+ return NULL;
+ }
+
++ pci_vpd_pci22_init(dev);
++
+ return dev;
+ }
+
+@@ -946,7 +979,6 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
+ * Add the device to our list of discovered devices
+ * and the bus list for fixup functions, etc.
+ */
+- INIT_LIST_HEAD(&dev->global_list);
+ down_write(&pci_bus_sem);
+ list_add_tail(&dev->bus_list, &bus->devices);
+ up_write(&pci_bus_sem);
+@@ -973,7 +1005,7 @@ EXPORT_SYMBOL(pci_scan_single_device);
+ *
+ * Scan a PCI slot on the specified PCI bus for devices, adding
+ * discovered devices to the @bus->devices list. New devices
+- * will have an empty dev->global_list head.
++ * will not have is_added set.
+ */
+ int pci_scan_slot(struct pci_bus *bus, int devfn)
+ {
+@@ -1005,6 +1037,10 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
+ break;
+ }
+ }
++
++ if (bus->self)
++ pcie_aspm_init_link_state(bus->self);
++
+ return nr;
+ }
+
+@@ -1175,7 +1211,7 @@ static void __init pci_insertion_sort_klist(struct pci_dev *a, struct list_head
+ list_move_tail(&a->dev.knode_bus.n_node, list);
+ }
+
+-static void __init pci_sort_breadthfirst_klist(void)
++void __init pci_sort_breadthfirst(void)
+ {
+ LIST_HEAD(sorted_devices);
+ struct list_head *pos, *tmp;
+@@ -1196,36 +1232,3 @@ static void __init pci_sort_breadthfirst_klist(void)
+ list_splice(&sorted_devices, &device_klist->k_list);
+ spin_unlock(&device_klist->k_lock);
+ }
+-
+-static void __init pci_insertion_sort_devices(struct pci_dev *a, struct list_head *list)
+-{
+- struct pci_dev *b;
+-
+- list_for_each_entry(b, list, global_list) {
+- if (pci_sort_bf_cmp(a, b) <= 0) {
+- list_move_tail(&a->global_list, &b->global_list);
+- return;
+- }
+- }
+- list_move_tail(&a->global_list, list);
+-}
+-
+-static void __init pci_sort_breadthfirst_devices(void)
+-{
+- LIST_HEAD(sorted_devices);
+- struct pci_dev *dev, *tmp;
+-
+- down_write(&pci_bus_sem);
+- list_for_each_entry_safe(dev, tmp, &pci_devices, global_list) {
+- pci_insertion_sort_devices(dev, &sorted_devices);
+- }
+- list_splice(&sorted_devices, &pci_devices);
+- up_write(&pci_bus_sem);
+-}
+-
+-void __init pci_sort_breadthfirst(void)
+-{
+- pci_sort_breadthfirst_devices();
+- pci_sort_breadthfirst_klist();
+-}
+-
+diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
+index e887aa4..afd914e 100644
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -1502,8 +1502,8 @@ static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_f
+ if ((f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) &&
+ (f->device == dev->device || f->device == (u16) PCI_ANY_ID)) {
+ #ifdef DEBUG
+- dev_dbg(&dev->dev, "calling quirk 0x%p", f->hook);
+- print_fn_descriptor_symbol(": %s()\n",
++ dev_dbg(&dev->dev, "calling ");
++ print_fn_descriptor_symbol("%s()\n",
+ (unsigned long) f->hook);
+ #endif
+ f->hook(dev);
+@@ -1648,13 +1648,24 @@ static void __devinit quirk_via_cx700_pci_parking_caching(struct pci_dev *dev)
+ /* Turn off PCI Bus Parking */
+ pci_write_config_byte(dev, 0x76, b ^ 0x40);
+
++ dev_info(&dev->dev,
++ "Disabling VIA CX700 PCI parking\n");
++ }
++ }
++
++ if (pci_read_config_byte(dev, 0x72, &b) == 0) {
++ if (b != 0) {
+ /* Turn off PCI Master read caching */
+ pci_write_config_byte(dev, 0x72, 0x0);
++
++ /* Set PCI Master Bus time-out to "1x16 PCLK" */
+ pci_write_config_byte(dev, 0x75, 0x1);
++
++ /* Disable "Read FIFO Timer" */
+ pci_write_config_byte(dev, 0x77, 0x0);
+
+ dev_info(&dev->dev,
+- "Disabling VIA CX700 PCI parking/caching\n");
++ "Disabling VIA CX700 PCI caching\n");
+ }
+ }
+ }
+diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
+index 9684e1b..bdc2a44 100644
+--- a/drivers/pci/remove.c
++++ b/drivers/pci/remove.c
+@@ -1,5 +1,6 @@
+ #include <linux/pci.h>
+ #include <linux/module.h>
++#include <linux/pci-aspm.h>
+ #include "pci.h"
+
+ static void pci_free_resources(struct pci_dev *dev)
+@@ -18,18 +19,15 @@ static void pci_free_resources(struct pci_dev *dev)
+
+ static void pci_stop_dev(struct pci_dev *dev)
+ {
+- if (!dev->global_list.next)
+- return;
+-
+- if (!list_empty(&dev->global_list)) {
++ if (dev->is_added) {
+ pci_proc_detach_device(dev);
+ pci_remove_sysfs_dev_files(dev);
+ device_unregister(&dev->dev);
+- down_write(&pci_bus_sem);
+- list_del(&dev->global_list);
+- dev->global_list.next = dev->global_list.prev = NULL;
+- up_write(&pci_bus_sem);
++ dev->is_added = 0;
+ }
++
++ if (dev->bus->self)
++ pcie_aspm_exit_link_state(dev);
+ }
+
+ static void pci_destroy_dev(struct pci_dev *dev)
+diff --git a/drivers/pci/search.c b/drivers/pci/search.c
+index 8541034..217814f 100644
+--- a/drivers/pci/search.c
++++ b/drivers/pci/search.c
+@@ -114,31 +114,63 @@ pci_find_next_bus(const struct pci_bus *from)
+ }
+
+ #ifdef CONFIG_PCI_LEGACY
+-
+ /**
+ * pci_find_slot - locate PCI device from a given PCI slot
+ * @bus: number of PCI bus on which desired PCI device resides
+- * @devfn: encodes number of PCI slot in which the desired PCI
+- * device resides and the logical device number within that slot
++ * @devfn: encodes number of PCI slot in which the desired PCI
++ * device resides and the logical device number within that slot
+ * in case of multi-function devices.
+ *
+- * Given a PCI bus and slot/function number, the desired PCI device
++ * Given a PCI bus and slot/function number, the desired PCI device
+ * is located in system global list of PCI devices. If the device
+- * is found, a pointer to its data structure is returned. If no
++ * is found, a pointer to its data structure is returned. If no
+ * device is found, %NULL is returned.
++ *
++ * NOTE: Do not use this function any more; use pci_get_slot() instead, as
++ * the PCI device returned by this function can disappear at any moment in
++ * time.
+ */
+-struct pci_dev *
+-pci_find_slot(unsigned int bus, unsigned int devfn)
++struct pci_dev *pci_find_slot(unsigned int bus, unsigned int devfn)
+ {
+ struct pci_dev *dev = NULL;
+
+- while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+- if (dev->bus->number == bus && dev->devfn == devfn)
++ while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
++ if (dev->bus->number == bus && dev->devfn == devfn) {
++ pci_dev_put(dev);
+ return dev;
++ }
+ }
+ return NULL;
+ }
++EXPORT_SYMBOL(pci_find_slot);
++
++/**
++ * pci_find_device - begin or continue searching for a PCI device by vendor/device id
++ * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
++ * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
++ * @from: Previous PCI device found in search, or %NULL for new search.
++ *
++ * Iterates through the list of known PCI devices. If a PCI device is found
++ * with a matching @vendor and @device, a pointer to its device structure is
++ * returned. Otherwise, %NULL is returned.
++ * A new search is initiated by passing %NULL as the @from argument.
++ * Otherwise if @from is not %NULL, searches continue from next device
++ * on the global list.
++ *
++ * NOTE: Do not use this function any more; use pci_get_device() instead, as
++ * the PCI device returned by this function can disappear at any moment in
++ * time.
++ */
++struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device,
++ const struct pci_dev *from)
++{
++ struct pci_dev *pdev;
+
++ pdev = pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
++ pci_dev_put(pdev);
++ return pdev;
++}
++EXPORT_SYMBOL(pci_find_device);
+ #endif /* CONFIG_PCI_LEGACY */
+
+ /**
+@@ -204,86 +236,52 @@ struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn)
+ return NULL;
+ }
+
+-#ifdef CONFIG_PCI_LEGACY
+-/**
+- * pci_find_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id
+- * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
+- * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
+- * @ss_vendor: PCI subsystem vendor id to match, or %PCI_ANY_ID to match all vendor ids
+- * @ss_device: PCI subsystem device id to match, or %PCI_ANY_ID to match all device ids
+- * @from: Previous PCI device found in search, or %NULL for new search.
+- *
+- * Iterates through the list of known PCI devices. If a PCI device is
+- * found with a matching @vendor, @device, @ss_vendor and @ss_device, a
+- * pointer to its device structure is returned. Otherwise, %NULL is returned.
+- * A new search is initiated by passing %NULL as the @from argument.
+- * Otherwise if @from is not %NULL, searches continue from next device
+- * on the global list.
+- *
+- * NOTE: Do not use this function any more; use pci_get_subsys() instead, as
+- * the PCI device returned by this function can disappear at any moment in
+- * time.
+- */
+-static struct pci_dev * pci_find_subsys(unsigned int vendor,
+- unsigned int device,
+- unsigned int ss_vendor,
+- unsigned int ss_device,
+- const struct pci_dev *from)
++static int match_pci_dev_by_id(struct device *dev, void *data)
+ {
+- struct list_head *n;
+- struct pci_dev *dev;
+-
+- WARN_ON(in_interrupt());
++ struct pci_dev *pdev = to_pci_dev(dev);
++ struct pci_device_id *id = data;
+
+- /*
+- * pci_find_subsys() can be called on the ide_setup() path, super-early
+- * in boot. But the down_read() will enable local interrupts, which
+- * can cause some machines to crash. So here we detect and flag that
+- * situation and bail out early.
+- */
+- if (unlikely(no_pci_devices()))
+- return NULL;
+- down_read(&pci_bus_sem);
+- n = from ? from->global_list.next : pci_devices.next;
+-
+- while (n && (n != &pci_devices)) {
+- dev = pci_dev_g(n);
+- if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
+- (device == PCI_ANY_ID || dev->device == device) &&
+- (ss_vendor == PCI_ANY_ID || dev->subsystem_vendor == ss_vendor) &&
+- (ss_device == PCI_ANY_ID || dev->subsystem_device == ss_device))
+- goto exit;
+- n = n->next;
+- }
+- dev = NULL;
+-exit:
+- up_read(&pci_bus_sem);
+- return dev;
++ if (pci_match_one_device(id, pdev))
++ return 1;
++ return 0;
+ }
+
+-/**
+- * pci_find_device - begin or continue searching for a PCI device by vendor/device id
+- * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
+- * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
++/*
++ * pci_get_dev_by_id - begin or continue searching for a PCI device by id
++ * @id: pointer to struct pci_device_id to match for the device
+ * @from: Previous PCI device found in search, or %NULL for new search.
+ *
+ * Iterates through the list of known PCI devices. If a PCI device is found
+- * with a matching @vendor and @device, a pointer to its device structure is
+- * returned. Otherwise, %NULL is returned.
+- * A new search is initiated by passing %NULL as the @from argument.
+- * Otherwise if @from is not %NULL, searches continue from next device
+- * on the global list.
+- *
+- * NOTE: Do not use this function any more; use pci_get_device() instead, as
+- * the PCI device returned by this function can disappear at any moment in
+- * time.
++ * with a matching id a pointer to its device structure is returned, and the
++ * reference count to the device is incremented. Otherwise, %NULL is returned.
++ * A new search is initiated by passing %NULL as the @from argument. Otherwise
++ * if @from is not %NULL, searches continue from next device on the global
++ * list. The reference count for @from is always decremented if it is not
++ * %NULL.
++ *
++ * This is an internal function for use by the other search functions in
++ * this file.
+ */
+-struct pci_dev *
+-pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev *from)
++static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id,
++ const struct pci_dev *from)
+ {
+- return pci_find_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
++ struct device *dev;
++ struct device *dev_start = NULL;
++ struct pci_dev *pdev = NULL;
++
++ WARN_ON(in_interrupt());
++ if (from) {
++ /* FIXME
++ * take the cast off, when bus_find_device is made const.
++ */
++ dev_start = (struct device *)&from->dev;
++ }
++ dev = bus_find_device(&pci_bus_type, dev_start, (void *)id,
++ match_pci_dev_by_id);
++ if (dev)
++ pdev = to_pci_dev(dev);
++ return pdev;
+ }
+-#endif /* CONFIG_PCI_LEGACY */
+
+ /**
+ * pci_get_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id
+@@ -301,42 +299,34 @@ pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev *
+ * searches continue from next device on the global list.
+ * The reference count for @from is always decremented if it is not %NULL.
+ */
+-struct pci_dev *
+-pci_get_subsys(unsigned int vendor, unsigned int device,
+- unsigned int ss_vendor, unsigned int ss_device,
+- struct pci_dev *from)
++struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,
++ unsigned int ss_vendor, unsigned int ss_device,
++ const struct pci_dev *from)
+ {
+- struct list_head *n;
+- struct pci_dev *dev;
+-
+- WARN_ON(in_interrupt());
++ struct pci_dev *pdev;
++ struct pci_device_id *id;
+
+ /*
+- * pci_get_subsys() can potentially be called by drivers super-early
+- * in boot. But the down_read() will enable local interrupts, which
+- * can cause some machines to crash. So here we detect and flag that
+- * situation and bail out early.
++ * pci_find_subsys() can be called on the ide_setup() path,
++ * super-early in boot. But the down_read() will enable local
++ * interrupts, which can cause some machines to crash. So here we
++ * detect and flag that situation and bail out early.
+ */
+ if (unlikely(no_pci_devices()))
+ return NULL;
+- down_read(&pci_bus_sem);
+- n = from ? from->global_list.next : pci_devices.next;
+-
+- while (n && (n != &pci_devices)) {
+- dev = pci_dev_g(n);
+- if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
+- (device == PCI_ANY_ID || dev->device == device) &&
+- (ss_vendor == PCI_ANY_ID || dev->subsystem_vendor == ss_vendor) &&
+- (ss_device == PCI_ANY_ID || dev->subsystem_device == ss_device))
+- goto exit;
+- n = n->next;
+- }
+- dev = NULL;
+-exit:
+- dev = pci_dev_get(dev);
+- up_read(&pci_bus_sem);
+- pci_dev_put(from);
+- return dev;
++
++ id = kzalloc(sizeof(*id), GFP_KERNEL);
++ if (!id)
++ return NULL;
++ id->vendor = vendor;
++ id->device = device;
++ id->subvendor = ss_vendor;
++ id->subdevice = ss_device;
++
++ pdev = pci_get_dev_by_id(id, from);
++ kfree(id);
++
++ return pdev;
+ }
+
+ /**
+@@ -360,46 +350,6 @@ pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from)
+ }
+
+ /**
+- * pci_get_device_reverse - begin or continue searching for a PCI device by vendor/device id
+- * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
+- * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
+- * @from: Previous PCI device found in search, or %NULL for new search.
+- *
+- * Iterates through the list of known PCI devices in the reverse order of
+- * pci_get_device.
+- * If a PCI device is found with a matching @vendor and @device, the reference
+- * count to the device is incremented and a pointer to its device structure
+- * is returned Otherwise, %NULL is returned. A new search is initiated by
+- * passing %NULL as the @from argument. Otherwise if @from is not %NULL,
+- * searches continue from next device on the global list. The reference
+- * count for @from is always decremented if it is not %NULL.
+- */
+-struct pci_dev *
+-pci_get_device_reverse(unsigned int vendor, unsigned int device, struct pci_dev *from)
+-{
+- struct list_head *n;
+- struct pci_dev *dev;
+-
+- WARN_ON(in_interrupt());
+- down_read(&pci_bus_sem);
+- n = from ? from->global_list.prev : pci_devices.prev;
+-
+- while (n && (n != &pci_devices)) {
+- dev = pci_dev_g(n);
+- if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
+- (device == PCI_ANY_ID || dev->device == device))
+- goto exit;
+- n = n->prev;
+- }
+- dev = NULL;
+-exit:
+- dev = pci_dev_get(dev);
+- up_read(&pci_bus_sem);
+- pci_dev_put(from);
+- return dev;
+-}
+-
+-/**
+ * pci_get_class - begin or continue searching for a PCI device by class
+ * @class: search for a PCI device with this class designation
+ * @from: Previous PCI device found in search, or %NULL for new search.
+@@ -415,46 +365,21 @@ exit:
+ */
+ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from)
+ {
+- struct list_head *n;
+ struct pci_dev *dev;
++ struct pci_device_id *id;
+
+- WARN_ON(in_interrupt());
+- down_read(&pci_bus_sem);
+- n = from ? from->global_list.next : pci_devices.next;
++ id = kzalloc(sizeof(*id), GFP_KERNEL);
++ if (!id)
++ return NULL;
++ id->vendor = id->device = id->subvendor = id->subdevice = PCI_ANY_ID;
++ id->class_mask = PCI_ANY_ID;
++ id->class = class;
+
+- while (n && (n != &pci_devices)) {
+- dev = pci_dev_g(n);
+- if (dev->class == class)
+- goto exit;
+- n = n->next;
+- }
+- dev = NULL;
+-exit:
+- dev = pci_dev_get(dev);
+- up_read(&pci_bus_sem);
+- pci_dev_put(from);
++ dev = pci_get_dev_by_id(id, from);
++ kfree(id);
+ return dev;
+ }
+
+-const struct pci_device_id *pci_find_present(const struct pci_device_id *ids)
+-{
+- struct pci_dev *dev;
+- const struct pci_device_id *found = NULL;
+-
+- WARN_ON(in_interrupt());
+- down_read(&pci_bus_sem);
+- while (ids->vendor || ids->subvendor || ids->class_mask) {
+- list_for_each_entry(dev, &pci_devices, global_list) {
+- if ((found = pci_match_one_device(ids, dev)) != NULL)
+- goto exit;
+- }
+- ids++;
+- }
+-exit:
+- up_read(&pci_bus_sem);
+- return found;
+-}
+-
+ /**
+ * pci_dev_present - Returns 1 if device matching the device list is present, 0 if not.
+ * @ids: A pointer to a null terminated list of struct pci_device_id structures
+@@ -468,23 +393,27 @@ exit:
+ */
+ int pci_dev_present(const struct pci_device_id *ids)
+ {
+- return pci_find_present(ids) == NULL ? 0 : 1;
+-}
++ struct pci_dev *found = NULL;
+
++ WARN_ON(in_interrupt());
++ while (ids->vendor || ids->subvendor || ids->class_mask) {
++ found = pci_get_dev_by_id(ids, NULL);
++ if (found)
++ goto exit;
++ ids++;
++ }
++exit:
++ if (found)
++ return 1;
++ return 0;
++}
+ EXPORT_SYMBOL(pci_dev_present);
+-EXPORT_SYMBOL(pci_find_present);
+-
+-#ifdef CONFIG_PCI_LEGACY
+-EXPORT_SYMBOL(pci_find_device);
+-EXPORT_SYMBOL(pci_find_slot);
+-#endif /* CONFIG_PCI_LEGACY */
+
+ /* For boot time work */
+ EXPORT_SYMBOL(pci_find_bus);
+ EXPORT_SYMBOL(pci_find_next_bus);
+ /* For everyone */
+ EXPORT_SYMBOL(pci_get_device);
+-EXPORT_SYMBOL(pci_get_device_reverse);
+ EXPORT_SYMBOL(pci_get_subsys);
+ EXPORT_SYMBOL(pci_get_slot);
+ EXPORT_SYMBOL(pci_get_bus_and_slot);
+diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
+index f7cb8e0..8ddb918 100644
+--- a/drivers/pci/setup-bus.c
++++ b/drivers/pci/setup-bus.c
+@@ -65,6 +65,7 @@ static void pbus_assign_resources_sorted(struct pci_bus *bus)
+ res = list->res;
+ idx = res - &list->dev->resource[0];
+ if (pci_assign_resource(list->dev, idx)) {
++ /* FIXME: get rid of this */
+ res->start = 0;
+ res->end = 0;
+ res->flags = 0;
+@@ -144,8 +145,7 @@ EXPORT_SYMBOL(pci_setup_cardbus);
+ config space writes, so it's quite possible that an I/O window of
+ the bridge will have some undesirable address (e.g. 0) after the
+ first write. Ditto 64-bit prefetchable MMIO. */
+-static void __devinit
+-pci_setup_bridge(struct pci_bus *bus)
++static void pci_setup_bridge(struct pci_bus *bus)
+ {
+ struct pci_dev *bridge = bus->self;
+ struct pci_bus_region region;
+@@ -327,6 +327,7 @@ static void pbus_size_io(struct pci_bus *bus)
+ /* Alignment of the IO window is always 4K */
+ b_res->start = 4096;
+ b_res->end = b_res->start + size - 1;
++ b_res->flags |= IORESOURCE_STARTALIGN;
+ }
+
+ /* Calculate the size of the bus and minimal alignment which
+@@ -401,11 +402,11 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
+ }
+ b_res->start = min_align;
+ b_res->end = size + min_align - 1;
++ b_res->flags |= IORESOURCE_STARTALIGN;
+ return 1;
+ }
+
+-static void __devinit
+-pci_bus_size_cardbus(struct pci_bus *bus)
++static void pci_bus_size_cardbus(struct pci_bus *bus)
+ {
+ struct pci_dev *bridge = bus->self;
+ struct resource *b_res = &bridge->resource[PCI_BRIDGE_RESOURCES];
+@@ -415,13 +416,13 @@ pci_bus_size_cardbus(struct pci_bus *bus)
+ * Reserve some resources for CardBus. We reserve
+ * a fixed amount of bus space for CardBus bridges.
+ */
+- b_res[0].start = pci_cardbus_io_size;
+- b_res[0].end = b_res[0].start + pci_cardbus_io_size - 1;
+- b_res[0].flags |= IORESOURCE_IO;
++ b_res[0].start = 0;
++ b_res[0].end = pci_cardbus_io_size - 1;
++ b_res[0].flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN;
+
+- b_res[1].start = pci_cardbus_io_size;
+- b_res[1].end = b_res[1].start + pci_cardbus_io_size - 1;
+- b_res[1].flags |= IORESOURCE_IO;
++ b_res[1].start = 0;
++ b_res[1].end = pci_cardbus_io_size - 1;
++ b_res[1].flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN;
+
+ /*
+ * Check whether prefetchable memory is supported
+@@ -440,17 +441,17 @@ pci_bus_size_cardbus(struct pci_bus *bus)
+ * twice the size.
+ */
+ if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0) {
+- b_res[2].start = pci_cardbus_mem_size;
+- b_res[2].end = b_res[2].start + pci_cardbus_mem_size - 1;
+- b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH;
++ b_res[2].start = 0;
++ b_res[2].end = pci_cardbus_mem_size - 1;
++ b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_SIZEALIGN;
+
+- b_res[3].start = pci_cardbus_mem_size;
+- b_res[3].end = b_res[3].start + pci_cardbus_mem_size - 1;
+- b_res[3].flags |= IORESOURCE_MEM;
++ b_res[3].start = 0;
++ b_res[3].end = pci_cardbus_mem_size - 1;
++ b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN;
+ } else {
+- b_res[3].start = pci_cardbus_mem_size * 2;
+- b_res[3].end = b_res[3].start + pci_cardbus_mem_size * 2 - 1;
+- b_res[3].flags |= IORESOURCE_MEM;
++ b_res[3].start = 0;
++ b_res[3].end = pci_cardbus_mem_size * 2 - 1;
++ b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN;
+ }
+ }
+
+diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
+index 4be7ccf..7d35cdf 100644
+--- a/drivers/pci/setup-res.c
++++ b/drivers/pci/setup-res.c
+@@ -137,10 +137,16 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
+
+ size = res->end - res->start + 1;
+ min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
+- /* The bridge resources are special, as their
+- size != alignment. Sizing routines return
+- required alignment in the "start" field. */
+- align = (resno < PCI_BRIDGE_RESOURCES) ? size : res->start;
++
++ align = resource_alignment(res);
++ if (!align) {
++ printk(KERN_ERR "PCI: Cannot allocate resource (bogus "
++ "alignment) %d [%llx:%llx] (flags %lx) of %s\n",
++ resno, (unsigned long long)res->start,
++ (unsigned long long)res->end, res->flags,
++ pci_name(dev));
++ return -EINVAL;
++ }
+
+ /* First, try exact prefetching match.. */
+ ret = pci_bus_alloc_resource(bus, res, size, align, min,
+@@ -164,14 +170,16 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
+ res->flags & IORESOURCE_IO ? "I/O" : "mem",
+ resno, (unsigned long long)size,
+ (unsigned long long)res->start, pci_name(dev));
+- } else if (resno < PCI_BRIDGE_RESOURCES) {
+- pci_update_resource(dev, res, resno);
++ } else {
++ res->flags &= ~IORESOURCE_STARTALIGN;
++ if (resno < PCI_BRIDGE_RESOURCES)
++ pci_update_resource(dev, res, resno);
+ }
+
+ return ret;
+ }
+
+-#ifdef CONFIG_EMBEDDED
++#if 0
+ int pci_assign_resource_fixed(struct pci_dev *dev, int resno)
+ {
+ struct pci_bus *bus = dev->bus;
+@@ -226,29 +234,25 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
+ if (r->flags & IORESOURCE_PCI_FIXED)
+ continue;
+
+- r_align = r->end - r->start;
+-
+ if (!(r->flags) || r->parent)
+ continue;
++
++ r_align = resource_alignment(r);
+ if (!r_align) {
+- printk(KERN_WARNING "PCI: Ignore bogus resource %d "
+- "[%llx:%llx] of %s\n",
++ printk(KERN_WARNING "PCI: bogus alignment of resource "
++ "%d [%llx:%llx] (flags %lx) of %s\n",
+ i, (unsigned long long)r->start,
+- (unsigned long long)r->end, pci_name(dev));
++ (unsigned long long)r->end, r->flags,
++ pci_name(dev));
+ continue;
+ }
+- r_align = (i < PCI_BRIDGE_RESOURCES) ? r_align + 1 : r->start;
+ for (list = head; ; list = list->next) {
+ resource_size_t align = 0;
+ struct resource_list *ln = list->next;
+- int idx;
+
+- if (ln) {
+- idx = ln->res - &ln->dev->resource[0];
+- align = (idx < PCI_BRIDGE_RESOURCES) ?
+- ln->res->end - ln->res->start + 1 :
+- ln->res->start;
+- }
++ if (ln)
++ align = resource_alignment(ln->res);
++
+ if (r_align > align) {
+ tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
+ if (!tmp)
+@@ -263,3 +267,46 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
+ }
+ }
+ }
++
++int pci_enable_resources(struct pci_dev *dev, int mask)
++{
++ u16 cmd, old_cmd;
++ int i;
++ struct resource *r;
++
++ pci_read_config_word(dev, PCI_COMMAND, &cmd);
++ old_cmd = cmd;
++
++ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
++ if (!(mask & (1 << i)))
++ continue;
++
++ r = &dev->resource[i];
++
++ if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
++ continue;
++ if ((i == PCI_ROM_RESOURCE) &&
++ (!(r->flags & IORESOURCE_ROM_ENABLE)))
++ continue;
++
++ if (!r->parent) {
++ dev_err(&dev->dev, "device not available because of "
++ "BAR %d [%llx:%llx] collisions\n", i,
++ (unsigned long long) r->start,
++ (unsigned long long) r->end);
++ return -EINVAL;
++ }
++
++ if (r->flags & IORESOURCE_IO)
++ cmd |= PCI_COMMAND_IO;
++ if (r->flags & IORESOURCE_MEM)
++ cmd |= PCI_COMMAND_MEMORY;
++ }
++
++ if (cmd != old_cmd) {
++ dev_info(&dev->dev, "enabling device (%04x -> %04x)\n",
++ old_cmd, cmd);
++ pci_write_config_word(dev, PCI_COMMAND, cmd);
++ }
++ return 0;
++}
+diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
+index 8b22281..8d88526 100644
+--- a/drivers/pcmcia/Kconfig
++++ b/drivers/pcmcia/Kconfig
+@@ -220,6 +220,7 @@ config PCMCIA_SA1111
+ config PCMCIA_PXA2XX
+ tristate "PXA2xx support"
+ depends on ARM && ARCH_PXA && PCMCIA
++ depends on ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL || MACH_ARMCORE
+ help
+ Say Y here to include support for the PXA2xx PCMCIA controller
+
+diff --git a/drivers/pcmcia/pxa2xx_cm_x270.c b/drivers/pcmcia/pxa2xx_cm_x270.c
+index fbf2f3a..e7ab060 100644
+--- a/drivers/pcmcia/pxa2xx_cm_x270.c
++++ b/drivers/pcmcia/pxa2xx_cm_x270.c
+@@ -20,6 +20,7 @@
+ #include <asm/hardware.h>
+
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/cm-x270.h>
+
+ #include "soc_common.h"
+diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
+index 2dcd196..98cbc9f 100644
+--- a/drivers/pnp/pnpacpi/rsparser.c
++++ b/drivers/pnp/pnpacpi/rsparser.c
+@@ -84,10 +84,12 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res,
+ while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) &&
+ i < PNP_MAX_IRQ)
+ i++;
+- if (i >= PNP_MAX_IRQ && !warned) {
+- printk(KERN_WARNING "pnpacpi: exceeded the max number of IRQ "
+- "resources: %d \n", PNP_MAX_IRQ);
+- warned = 1;
++ if (i >= PNP_MAX_IRQ) {
++ if (!warned) {
++ printk(KERN_WARNING "pnpacpi: exceeded the max number"
++ " of IRQ resources: %d\n", PNP_MAX_IRQ);
++ warned = 1;
++ }
+ return;
+ }
+ /*
+diff --git a/drivers/ps3/ps3-sys-manager.c b/drivers/ps3/ps3-sys-manager.c
+index d4f6f96..7605453 100644
+--- a/drivers/ps3/ps3-sys-manager.c
++++ b/drivers/ps3/ps3-sys-manager.c
+@@ -24,6 +24,7 @@
+ #include <linux/reboot.h>
+
+ #include <asm/firmware.h>
++#include <asm/lv1call.h>
+ #include <asm/ps3.h>
+
+ #include "vuart.h"
+@@ -187,6 +188,7 @@ enum ps3_sys_manager_next_op {
+ * controller, and bluetooth controller.
+ * @PS3_SM_WAKE_RTC:
+ * @PS3_SM_WAKE_RTC_ERROR:
++ * @PS3_SM_WAKE_W_O_L: Ether or wireless LAN.
+ * @PS3_SM_WAKE_P_O_R: Power on reset.
+ *
+ * Additional wakeup sources when specifying PS3_SM_NEXT_OP_SYS_SHUTDOWN.
+@@ -200,10 +202,19 @@ enum ps3_sys_manager_wake_source {
+ PS3_SM_WAKE_DEFAULT = 0,
+ PS3_SM_WAKE_RTC = 0x00000040,
+ PS3_SM_WAKE_RTC_ERROR = 0x00000080,
++ PS3_SM_WAKE_W_O_L = 0x00000400,
+ PS3_SM_WAKE_P_O_R = 0x80000000,
+ };
+
+ /**
++ * user_wake_sources - User specified wakeup sources.
++ *
++ * Logical OR of enum ps3_sys_manager_wake_source types.
++ */
++
++static u32 user_wake_sources = PS3_SM_WAKE_DEFAULT;
++
++/**
+ * enum ps3_sys_manager_cmd - Command from system manager to guest.
+ *
+ * The guest completes the actions needed, then acks or naks the command via
+@@ -581,6 +592,23 @@ fail_id:
+ return -EIO;
+ }
+
++static void ps3_sys_manager_fin(struct ps3_system_bus_device *dev)
++{
++ ps3_sys_manager_send_request_shutdown(dev);
++
++ pr_emerg("System Halted, OK to turn off power\n");
++
++ while (ps3_sys_manager_handle_msg(dev)) {
++ /* pause until next DEC interrupt */
++ lv1_pause(0);
++ }
++
++ while (1) {
++ /* pause, ignoring DEC interrupt */
++ lv1_pause(1);
++ }
++}
++
+ /**
+ * ps3_sys_manager_final_power_off - The final platform machine_power_off routine.
+ *
+@@ -601,13 +629,9 @@ static void ps3_sys_manager_final_power_off(struct ps3_system_bus_device *dev)
+ ps3_vuart_cancel_async(dev);
+
+ ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_SHUTDOWN,
+- PS3_SM_WAKE_DEFAULT);
+- ps3_sys_manager_send_request_shutdown(dev);
+-
+- pr_emerg("System Halted, OK to turn off power\n");
++ user_wake_sources);
+
+- while (1)
+- ps3_sys_manager_handle_msg(dev);
++ ps3_sys_manager_fin(dev);
+ }
+
+ /**
+@@ -638,14 +662,42 @@ static void ps3_sys_manager_final_restart(struct ps3_system_bus_device *dev)
+
+ ps3_sys_manager_send_attr(dev, 0);
+ ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_REBOOT,
+- PS3_SM_WAKE_DEFAULT);
+- ps3_sys_manager_send_request_shutdown(dev);
++ user_wake_sources);
+
+- pr_emerg("System Halted, OK to turn off power\n");
++ ps3_sys_manager_fin(dev);
++}
++
++/**
++ * ps3_sys_manager_get_wol - Get wake-on-lan setting.
++ */
++
++int ps3_sys_manager_get_wol(void)
++{
++ pr_debug("%s:%d\n", __func__, __LINE__);
++
++ return (user_wake_sources & PS3_SM_WAKE_W_O_L) != 0;
++}
++EXPORT_SYMBOL_GPL(ps3_sys_manager_get_wol);
++
++/**
++ * ps3_sys_manager_set_wol - Set wake-on-lan setting.
++ */
++
++void ps3_sys_manager_set_wol(int state)
++{
++ static DEFINE_MUTEX(mutex);
++
++ mutex_lock(&mutex);
++
++ pr_debug("%s:%d: %d\n", __func__, __LINE__, state);
+
+- while (1)
+- ps3_sys_manager_handle_msg(dev);
++ if (state)
++ user_wake_sources |= PS3_SM_WAKE_W_O_L;
++ else
++ user_wake_sources &= ~PS3_SM_WAKE_W_O_L;
++ mutex_unlock(&mutex);
+ }
++EXPORT_SYMBOL_GPL(ps3_sys_manager_set_wol);
+
+ /**
+ * ps3_sys_manager_work - Asynchronous read handler.
+diff --git a/drivers/ps3/sys-manager-core.c b/drivers/ps3/sys-manager-core.c
+index 31648f7..4742258 100644
+--- a/drivers/ps3/sys-manager-core.c
++++ b/drivers/ps3/sys-manager-core.c
+@@ -19,6 +19,7 @@
+ */
+
+ #include <linux/kernel.h>
++#include <asm/lv1call.h>
+ #include <asm/ps3.h>
+
+ /**
+@@ -50,10 +51,7 @@ void ps3_sys_manager_power_off(void)
+ if (ps3_sys_manager_ops.power_off)
+ ps3_sys_manager_ops.power_off(ps3_sys_manager_ops.dev);
+
+- printk(KERN_EMERG "System Halted, OK to turn off power\n");
+- local_irq_disable();
+- while (1)
+- (void)0;
++ ps3_sys_manager_halt();
+ }
+
+ void ps3_sys_manager_restart(void)
+@@ -61,8 +59,14 @@ void ps3_sys_manager_restart(void)
+ if (ps3_sys_manager_ops.restart)
+ ps3_sys_manager_ops.restart(ps3_sys_manager_ops.dev);
+
+- printk(KERN_EMERG "System Halted, OK to turn off power\n");
++ ps3_sys_manager_halt();
++}
++
++void ps3_sys_manager_halt(void)
++{
++ pr_emerg("System Halted, OK to turn off power\n");
+ local_irq_disable();
+ while (1)
+- (void)0;
++ lv1_pause(1);
+ }
++
+diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
+index 9e9caa5..c594b34 100644
+--- a/drivers/rtc/rtc-sh.c
++++ b/drivers/rtc/rtc-sh.c
+@@ -1,8 +1,9 @@
+ /*
+ * SuperH On-Chip RTC Support
+ *
+- * Copyright (C) 2006, 2007 Paul Mundt
++ * Copyright (C) 2006, 2007, 2008 Paul Mundt
+ * Copyright (C) 2006 Jamie Lenehan
++ * Copyright (C) 2008 Angelo Castello
+ *
+ * Based on the old arch/sh/kernel/cpu/rtc.c by:
+ *
+@@ -26,7 +27,7 @@
+ #include <asm/rtc.h>
+
+ #define DRV_NAME "sh-rtc"
+-#define DRV_VERSION "0.1.6"
++#define DRV_VERSION "0.2.0"
+
+ #define RTC_REG(r) ((r) * rtc_reg_size)
+
+@@ -63,6 +64,13 @@
+ /* ALARM Bits - or with BCD encoded value */
+ #define AR_ENB 0x80 /* Enable for alarm cmp */
+
++/* Period Bits */
++#define PF_HP 0x100 /* Enable Half Period to support 8,32,128Hz */
++#define PF_COUNT 0x200 /* Half periodic counter */
++#define PF_OXS 0x400 /* Periodic One x Second */
++#define PF_KOU 0x800 /* Kernel or User periodic request 1=kernel */
++#define PF_MASK 0xf00
++
+ /* RCR1 Bits */
+ #define RCR1_CF 0x80 /* Carry Flag */
+ #define RCR1_CIE 0x10 /* Carry Interrupt Enable */
+@@ -84,33 +92,24 @@ struct sh_rtc {
+ unsigned int alarm_irq, periodic_irq, carry_irq;
+ struct rtc_device *rtc_dev;
+ spinlock_t lock;
+- int rearm_aie;
+ unsigned long capabilities; /* See asm-sh/rtc.h for cap bits */
++ unsigned short periodic_freq;
+ };
+
+ static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id)
+ {
+- struct platform_device *pdev = to_platform_device(dev_id);
+- struct sh_rtc *rtc = platform_get_drvdata(pdev);
+- unsigned int tmp, events = 0;
++ struct sh_rtc *rtc = dev_id;
++ unsigned int tmp;
+
+ spin_lock(&rtc->lock);
+
+ tmp = readb(rtc->regbase + RCR1);
+ tmp &= ~RCR1_CF;
+-
+- if (rtc->rearm_aie) {
+- if (tmp & RCR1_AF)
+- tmp &= ~RCR1_AF; /* try to clear AF again */
+- else {
+- tmp |= RCR1_AIE; /* AF has cleared, rearm IRQ */
+- rtc->rearm_aie = 0;
+- }
+- }
+-
+ writeb(tmp, rtc->regbase + RCR1);
+
+- rtc_update_irq(rtc->rtc_dev, 1, events);
++ /* Users have requested One x Second IRQ */
++ if (rtc->periodic_freq & PF_OXS)
++ rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF);
+
+ spin_unlock(&rtc->lock);
+
+@@ -119,47 +118,48 @@ static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id)
+
+ static irqreturn_t sh_rtc_alarm(int irq, void *dev_id)
+ {
+- struct platform_device *pdev = to_platform_device(dev_id);
+- struct sh_rtc *rtc = platform_get_drvdata(pdev);
+- unsigned int tmp, events = 0;
++ struct sh_rtc *rtc = dev_id;
++ unsigned int tmp;
+
+ spin_lock(&rtc->lock);
+
+ tmp = readb(rtc->regbase + RCR1);
+-
+- /*
+- * If AF is set then the alarm has triggered. If we clear AF while
+- * the alarm time still matches the RTC time then AF will
+- * immediately be set again, and if AIE is enabled then the alarm
+- * interrupt will immediately be retrigger. So we clear AIE here
+- * and use rtc->rearm_aie so that the carry interrupt will keep
+- * trying to clear AF and once it stays cleared it'll re-enable
+- * AIE.
+- */
+- if (tmp & RCR1_AF) {
+- events |= RTC_AF | RTC_IRQF;
+-
+- tmp &= ~(RCR1_AF|RCR1_AIE);
+-
++ tmp &= ~(RCR1_AF | RCR1_AIE);
+ writeb(tmp, rtc->regbase + RCR1);
+
+- rtc->rearm_aie = 1;
+-
+- rtc_update_irq(rtc->rtc_dev, 1, events);
+- }
++ rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
+
+ spin_unlock(&rtc->lock);
++
+ return IRQ_HANDLED;
+ }
+
+ static irqreturn_t sh_rtc_periodic(int irq, void *dev_id)
+ {
+- struct platform_device *pdev = to_platform_device(dev_id);
+- struct sh_rtc *rtc = platform_get_drvdata(pdev);
++ struct sh_rtc *rtc = dev_id;
++ struct rtc_device *rtc_dev = rtc->rtc_dev;
++ unsigned int tmp;
+
+ spin_lock(&rtc->lock);
+
+- rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF);
++ tmp = readb(rtc->regbase + RCR2);
++ tmp &= ~RCR2_PEF;
++ writeb(tmp, rtc->regbase + RCR2);
++
++ /* Half period enabled than one skipped and the next notified */
++ if ((rtc->periodic_freq & PF_HP) && (rtc->periodic_freq & PF_COUNT))
++ rtc->periodic_freq &= ~PF_COUNT;
++ else {
++ if (rtc->periodic_freq & PF_HP)
++ rtc->periodic_freq |= PF_COUNT;
++ if (rtc->periodic_freq & PF_KOU) {
++ spin_lock(&rtc_dev->irq_task_lock);
++ if (rtc_dev->irq_task)
++ rtc_dev->irq_task->func(rtc_dev->irq_task->private_data);
++ spin_unlock(&rtc_dev->irq_task_lock);
++ } else
++ rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF);
++ }
+
+ spin_unlock(&rtc->lock);
+
+@@ -176,8 +176,8 @@ static inline void sh_rtc_setpie(struct device *dev, unsigned int enable)
+ tmp = readb(rtc->regbase + RCR2);
+
+ if (enable) {
+- tmp &= ~RCR2_PESMASK;
+- tmp |= RCR2_PEF | (2 << 4);
++ tmp &= ~RCR2_PEF; /* Clear PES bit */
++ tmp |= (rtc->periodic_freq & ~PF_HP); /* Set PES2-0 */
+ } else
+ tmp &= ~(RCR2_PESMASK | RCR2_PEF);
+
+@@ -186,82 +186,81 @@ static inline void sh_rtc_setpie(struct device *dev, unsigned int enable)
+ spin_unlock_irq(&rtc->lock);
+ }
+
+-static inline void sh_rtc_setaie(struct device *dev, unsigned int enable)
++static inline int sh_rtc_setfreq(struct device *dev, unsigned int freq)
+ {
+ struct sh_rtc *rtc = dev_get_drvdata(dev);
+- unsigned int tmp;
++ int tmp, ret = 0;
+
+ spin_lock_irq(&rtc->lock);
++ tmp = rtc->periodic_freq & PF_MASK;
+
+- tmp = readb(rtc->regbase + RCR1);
+-
+- if (!enable) {
+- tmp &= ~RCR1_AIE;
+- rtc->rearm_aie = 0;
+- } else if (rtc->rearm_aie == 0)
+- tmp |= RCR1_AIE;
++ switch (freq) {
++ case 0:
++ rtc->periodic_freq = 0x00;
++ break;
++ case 1:
++ rtc->periodic_freq = 0x60;
++ break;
++ case 2:
++ rtc->periodic_freq = 0x50;
++ break;
++ case 4:
++ rtc->periodic_freq = 0x40;
++ break;
++ case 8:
++ rtc->periodic_freq = 0x30 | PF_HP;
++ break;
++ case 16:
++ rtc->periodic_freq = 0x30;
++ break;
++ case 32:
++ rtc->periodic_freq = 0x20 | PF_HP;
++ break;
++ case 64:
++ rtc->periodic_freq = 0x20;
++ break;
++ case 128:
++ rtc->periodic_freq = 0x10 | PF_HP;
++ break;
++ case 256:
++ rtc->periodic_freq = 0x10;
++ break;
++ default:
++ ret = -ENOTSUPP;
++ }
+
+- writeb(tmp, rtc->regbase + RCR1);
++ if (ret == 0) {
++ rtc->periodic_freq |= tmp;
++ rtc->rtc_dev->irq_freq = freq;
++ }
+
+ spin_unlock_irq(&rtc->lock);
++ return ret;
+ }
+
+-static int sh_rtc_open(struct device *dev)
++static inline void sh_rtc_setaie(struct device *dev, unsigned int enable)
+ {
+ struct sh_rtc *rtc = dev_get_drvdata(dev);
+ unsigned int tmp;
+- int ret;
+-
+- tmp = readb(rtc->regbase + RCR1);
+- tmp &= ~RCR1_CF;
+- tmp |= RCR1_CIE;
+- writeb(tmp, rtc->regbase + RCR1);
+
+- ret = request_irq(rtc->periodic_irq, sh_rtc_periodic, IRQF_DISABLED,
+- "sh-rtc period", dev);
+- if (unlikely(ret)) {
+- dev_err(dev, "request period IRQ failed with %d, IRQ %d\n",
+- ret, rtc->periodic_irq);
+- return ret;
+- }
+-
+- ret = request_irq(rtc->carry_irq, sh_rtc_interrupt, IRQF_DISABLED,
+- "sh-rtc carry", dev);
+- if (unlikely(ret)) {
+- dev_err(dev, "request carry IRQ failed with %d, IRQ %d\n",
+- ret, rtc->carry_irq);
+- free_irq(rtc->periodic_irq, dev);
+- goto err_bad_carry;
+- }
++ spin_lock_irq(&rtc->lock);
+
+- ret = request_irq(rtc->alarm_irq, sh_rtc_alarm, IRQF_DISABLED,
+- "sh-rtc alarm", dev);
+- if (unlikely(ret)) {
+- dev_err(dev, "request alarm IRQ failed with %d, IRQ %d\n",
+- ret, rtc->alarm_irq);
+- goto err_bad_alarm;
+- }
++ tmp = readb(rtc->regbase + RCR1);
+
+- return 0;
++ if (!enable)
++ tmp &= ~RCR1_AIE;
++ else
++ tmp |= RCR1_AIE;
+
+-err_bad_alarm:
+- free_irq(rtc->carry_irq, dev);
+-err_bad_carry:
+- free_irq(rtc->periodic_irq, dev);
++ writeb(tmp, rtc->regbase + RCR1);
+
+- return ret;
++ spin_unlock_irq(&rtc->lock);
+ }
+
+ static void sh_rtc_release(struct device *dev)
+ {
+- struct sh_rtc *rtc = dev_get_drvdata(dev);
+-
+ sh_rtc_setpie(dev, 0);
+ sh_rtc_setaie(dev, 0);
+-
+- free_irq(rtc->periodic_irq, dev);
+- free_irq(rtc->carry_irq, dev);
+- free_irq(rtc->alarm_irq, dev);
+ }
+
+ static int sh_rtc_proc(struct device *dev, struct seq_file *seq)
+@@ -270,31 +269,44 @@ static int sh_rtc_proc(struct device *dev, struct seq_file *seq)
+ unsigned int tmp;
+
+ tmp = readb(rtc->regbase + RCR1);
+- seq_printf(seq, "carry_IRQ\t: %s\n",
+- (tmp & RCR1_CIE) ? "yes" : "no");
++ seq_printf(seq, "carry_IRQ\t: %s\n", (tmp & RCR1_CIE) ? "yes" : "no");
+
+ tmp = readb(rtc->regbase + RCR2);
+ seq_printf(seq, "periodic_IRQ\t: %s\n",
+- (tmp & RCR2_PEF) ? "yes" : "no");
++ (tmp & RCR2_PESMASK) ? "yes" : "no");
+
+ return 0;
+ }
+
+ static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+ {
+- unsigned int ret = -ENOIOCTLCMD;
++ struct sh_rtc *rtc = dev_get_drvdata(dev);
++ unsigned int ret = 0;
+
+ switch (cmd) {
+ case RTC_PIE_OFF:
+ case RTC_PIE_ON:
+ sh_rtc_setpie(dev, cmd == RTC_PIE_ON);
+- ret = 0;
+ break;
+ case RTC_AIE_OFF:
+ case RTC_AIE_ON:
+ sh_rtc_setaie(dev, cmd == RTC_AIE_ON);
+- ret = 0;
+ break;
++ case RTC_UIE_OFF:
++ rtc->periodic_freq &= ~PF_OXS;
++ break;
++ case RTC_UIE_ON:
++ rtc->periodic_freq |= PF_OXS;
++ break;
++ case RTC_IRQP_READ:
++ ret = put_user(rtc->rtc_dev->irq_freq,
++ (unsigned long __user *)arg);
++ break;
++ case RTC_IRQP_SET:
++ ret = sh_rtc_setfreq(dev, arg);
++ break;
++ default:
++ ret = -ENOIOCTLCMD;
+ }
+
+ return ret;
+@@ -421,7 +433,7 @@ static int sh_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+ {
+ struct platform_device *pdev = to_platform_device(dev);
+ struct sh_rtc *rtc = platform_get_drvdata(pdev);
+- struct rtc_time* tm = &wkalrm->time;
++ struct rtc_time *tm = &wkalrm->time;
+
+ spin_lock_irq(&rtc->lock);
+
+@@ -452,7 +464,7 @@ static inline void sh_rtc_write_alarm_value(struct sh_rtc *rtc,
+ writeb(BIN2BCD(value) | AR_ENB, rtc->regbase + reg_off);
+ }
+
+-static int sh_rtc_check_alarm(struct rtc_time* tm)
++static int sh_rtc_check_alarm(struct rtc_time *tm)
+ {
+ /*
+ * The original rtc says anything > 0xc0 is "don't care" or "match
+@@ -503,11 +515,9 @@ static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+
+ /* disable alarm interrupt and clear the alarm flag */
+ rcr1 = readb(rtc->regbase + RCR1);
+- rcr1 &= ~(RCR1_AF|RCR1_AIE);
++ rcr1 &= ~(RCR1_AF | RCR1_AIE);
+ writeb(rcr1, rtc->regbase + RCR1);
+
+- rtc->rearm_aie = 0;
+-
+ /* set alarm time */
+ sh_rtc_write_alarm_value(rtc, tm->tm_sec, RSECAR);
+ sh_rtc_write_alarm_value(rtc, tm->tm_min, RMINAR);
+@@ -529,14 +539,34 @@ static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+ return 0;
+ }
+
++static int sh_rtc_irq_set_state(struct device *dev, int enabled)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct sh_rtc *rtc = platform_get_drvdata(pdev);
++
++ if (enabled) {
++ rtc->periodic_freq |= PF_KOU;
++ return sh_rtc_ioctl(dev, RTC_PIE_ON, 0);
++ } else {
++ rtc->periodic_freq &= ~PF_KOU;
++ return sh_rtc_ioctl(dev, RTC_PIE_OFF, 0);
++ }
++}
++
++static int sh_rtc_irq_set_freq(struct device *dev, int freq)
++{
++ return sh_rtc_ioctl(dev, RTC_IRQP_SET, freq);
++}
++
+ static struct rtc_class_ops sh_rtc_ops = {
+- .open = sh_rtc_open,
+ .release = sh_rtc_release,
+ .ioctl = sh_rtc_ioctl,
+ .read_time = sh_rtc_read_time,
+ .set_time = sh_rtc_set_time,
+ .read_alarm = sh_rtc_read_alarm,
+ .set_alarm = sh_rtc_set_alarm,
++ .irq_set_state = sh_rtc_irq_set_state,
++ .irq_set_freq = sh_rtc_irq_set_freq,
+ .proc = sh_rtc_proc,
+ };
+
+@@ -544,6 +574,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
+ {
+ struct sh_rtc *rtc;
+ struct resource *res;
++ unsigned int tmp;
+ int ret = -ENOENT;
+
+ rtc = kzalloc(sizeof(struct sh_rtc), GFP_KERNEL);
+@@ -552,6 +583,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
+
+ spin_lock_init(&rtc->lock);
+
++ /* get periodic/carry/alarm irqs */
+ rtc->periodic_irq = platform_get_irq(pdev, 0);
+ if (unlikely(rtc->periodic_irq < 0)) {
+ dev_err(&pdev->dev, "No IRQ for period\n");
+@@ -608,8 +640,48 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
+ rtc->capabilities |= pinfo->capabilities;
+ }
+
++ rtc->rtc_dev->max_user_freq = 256;
++ rtc->rtc_dev->irq_freq = 1;
++ rtc->periodic_freq = 0x60;
++
+ platform_set_drvdata(pdev, rtc);
+
++ /* register periodic/carry/alarm irqs */
++ ret = request_irq(rtc->periodic_irq, sh_rtc_periodic, IRQF_DISABLED,
++ "sh-rtc period", rtc);
++ if (unlikely(ret)) {
++ dev_err(&pdev->dev,
++ "request period IRQ failed with %d, IRQ %d\n", ret,
++ rtc->periodic_irq);
++ goto err_badmap;
++ }
++
++ ret = request_irq(rtc->carry_irq, sh_rtc_interrupt, IRQF_DISABLED,
++ "sh-rtc carry", rtc);
++ if (unlikely(ret)) {
++ dev_err(&pdev->dev,
++ "request carry IRQ failed with %d, IRQ %d\n", ret,
++ rtc->carry_irq);
++ free_irq(rtc->periodic_irq, rtc);
++ goto err_badmap;
++ }
++
++ ret = request_irq(rtc->alarm_irq, sh_rtc_alarm, IRQF_DISABLED,
++ "sh-rtc alarm", rtc);
++ if (unlikely(ret)) {
++ dev_err(&pdev->dev,
++ "request alarm IRQ failed with %d, IRQ %d\n", ret,
++ rtc->alarm_irq);
++ free_irq(rtc->carry_irq, rtc);
++ free_irq(rtc->periodic_irq, rtc);
++ goto err_badmap;
++ }
++
++ tmp = readb(rtc->regbase + RCR1);
++ tmp &= ~RCR1_CF;
++ tmp |= RCR1_CIE;
++ writeb(tmp, rtc->regbase + RCR1);
++
+ return 0;
+
+ err_badmap:
+@@ -630,6 +702,10 @@ static int __devexit sh_rtc_remove(struct platform_device *pdev)
+ sh_rtc_setpie(&pdev->dev, 0);
+ sh_rtc_setaie(&pdev->dev, 0);
+
++ free_irq(rtc->carry_irq, rtc);
++ free_irq(rtc->periodic_irq, rtc);
++ free_irq(rtc->alarm_irq, rtc);
++
+ release_resource(rtc->res);
+
+ platform_set_drvdata(pdev, NULL);
+@@ -662,6 +738,8 @@ module_exit(sh_rtc_exit);
+
+ MODULE_DESCRIPTION("SuperH on-chip RTC driver");
+ MODULE_VERSION(DRV_VERSION);
+-MODULE_AUTHOR("Paul Mundt <lethal at linux-sh.org>, Jamie Lenehan <lenehan at twibble.org>");
++MODULE_AUTHOR("Paul Mundt <lethal at linux-sh.org>, "
++ "Jamie Lenehan <lenehan at twibble.org>, "
++ "Angelo Castello <angelo.castello at st.com>");
+ MODULE_LICENSE("GPL");
+ MODULE_ALIAS("platform:" DRV_NAME);
+diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig
+index e879b21..0788319 100644
+--- a/drivers/s390/block/Kconfig
++++ b/drivers/s390/block/Kconfig
+@@ -20,6 +20,7 @@ config DCSSBLK
+ config DASD
+ tristate "Support for DASD devices"
+ depends on CCW && BLOCK
++ select IOSCHED_DEADLINE
+ help
+ Enable this option if you want to access DASDs directly utilizing
+ S/390s channel subsystem commands. This is necessary for running
+diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
+index ccf46c9..ac6d4d3 100644
+--- a/drivers/s390/block/dasd.c
++++ b/drivers/s390/block/dasd.c
+@@ -980,12 +980,12 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
+ break;
+ case -ETIMEDOUT:
+ printk(KERN_WARNING"%s(%s): request timed out\n",
+- __FUNCTION__, cdev->dev.bus_id);
++ __func__, cdev->dev.bus_id);
+ //FIXME - dasd uses own timeout interface...
+ break;
+ default:
+ printk(KERN_WARNING"%s(%s): unknown error %ld\n",
+- __FUNCTION__, cdev->dev.bus_id, PTR_ERR(irb));
++ __func__, cdev->dev.bus_id, PTR_ERR(irb));
+ }
+ return;
+ }
+@@ -1956,6 +1956,7 @@ static int dasd_alloc_queue(struct dasd_block *block)
+ block->request_queue->queuedata = block;
+
+ elevator_exit(block->request_queue->elevator);
++ block->request_queue->elevator = NULL;
+ rc = elevator_init(block->request_queue, "deadline");
+ if (rc) {
+ blk_cleanup_queue(block->request_queue);
+@@ -2298,9 +2299,8 @@ int dasd_generic_set_offline(struct ccw_device *cdev)
+ * in the other openers.
+ */
+ if (device->block) {
+- struct dasd_block *block = device->block;
+- max_count = block->bdev ? 0 : -1;
+- open_count = (int) atomic_read(&block->open_count);
++ max_count = device->block->bdev ? 0 : -1;
++ open_count = atomic_read(&device->block->open_count);
+ if (open_count > max_count) {
+ if (open_count > 0)
+ printk(KERN_WARNING "Can't offline dasd "
+diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
+index b19db20..e6700df 100644
+--- a/drivers/s390/block/dasd_3990_erp.c
++++ b/drivers/s390/block/dasd_3990_erp.c
+@@ -1996,6 +1996,36 @@ dasd_3990_erp_compound(struct dasd_ccw_req * erp, char *sense)
+ } /* end dasd_3990_erp_compound */
+
+ /*
++ *DASD_3990_ERP_HANDLE_SIM
++ *
++ *DESCRIPTION
++ * inspects the SIM SENSE data and starts an appropriate action
++ *
++ * PARAMETER
++ * sense sense data of the actual error
++ *
++ * RETURN VALUES
++ * none
++ */
++void
++dasd_3990_erp_handle_sim(struct dasd_device *device, char *sense)
++{
++ /* print message according to log or message to operator mode */
++ if ((sense[24] & DASD_SIM_MSG_TO_OP) || (sense[1] & 0x10)) {
++
++ /* print SIM SRC from RefCode */
++ DEV_MESSAGE(KERN_ERR, device, "SIM - SRC: "
++ "%02x%02x%02x%02x", sense[22],
++ sense[23], sense[11], sense[12]);
++ } else if (sense[24] & DASD_SIM_LOG) {
++ /* print SIM SRC Refcode */
++ DEV_MESSAGE(KERN_WARNING, device, "SIM - SRC: "
++ "%02x%02x%02x%02x", sense[22],
++ sense[23], sense[11], sense[12]);
++ }
++}
++
++/*
+ * DASD_3990_ERP_INSPECT_32
+ *
+ * DESCRIPTION
+@@ -2018,6 +2048,10 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)
+
+ erp->function = dasd_3990_erp_inspect_32;
+
++ /* check for SIM sense data */
++ if ((sense[6] & DASD_SIM_SENSE) == DASD_SIM_SENSE)
++ dasd_3990_erp_handle_sim(device, sense);
++
+ if (sense[25] & DASD_SENSE_BIT_0) {
+
+ /* compound program action codes (byte25 bit 0 == '1') */
+diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c
+index 3a40bee..2d8df0b 100644
+--- a/drivers/s390/block/dasd_alias.c
++++ b/drivers/s390/block/dasd_alias.c
+@@ -745,6 +745,19 @@ static void flush_all_alias_devices_on_lcu(struct alias_lcu *lcu)
+ spin_unlock_irqrestore(&lcu->lock, flags);
+ }
+
++static void __stop_device_on_lcu(struct dasd_device *device,
++ struct dasd_device *pos)
++{
++ /* If pos == device then device is already locked! */
++ if (pos == device) {
++ pos->stopped |= DASD_STOPPED_SU;
++ return;
++ }
++ spin_lock(get_ccwdev_lock(pos->cdev));
++ pos->stopped |= DASD_STOPPED_SU;
++ spin_unlock(get_ccwdev_lock(pos->cdev));
++}
++
+ /*
+ * This function is called in interrupt context, so the
+ * cdev lock for device is already locked!
+@@ -755,35 +768,15 @@ static void _stop_all_devices_on_lcu(struct alias_lcu *lcu,
+ struct alias_pav_group *pavgroup;
+ struct dasd_device *pos;
+
+- list_for_each_entry(pos, &lcu->active_devices, alias_list) {
+- if (pos != device)
+- spin_lock(get_ccwdev_lock(pos->cdev));
+- pos->stopped |= DASD_STOPPED_SU;
+- if (pos != device)
+- spin_unlock(get_ccwdev_lock(pos->cdev));
+- }
+- list_for_each_entry(pos, &lcu->inactive_devices, alias_list) {
+- if (pos != device)
+- spin_lock(get_ccwdev_lock(pos->cdev));
+- pos->stopped |= DASD_STOPPED_SU;
+- if (pos != device)
+- spin_unlock(get_ccwdev_lock(pos->cdev));
+- }
++ list_for_each_entry(pos, &lcu->active_devices, alias_list)
++ __stop_device_on_lcu(device, pos);
++ list_for_each_entry(pos, &lcu->inactive_devices, alias_list)
++ __stop_device_on_lcu(device, pos);
+ list_for_each_entry(pavgroup, &lcu->grouplist, group) {
+- list_for_each_entry(pos, &pavgroup->baselist, alias_list) {
+- if (pos != device)
+- spin_lock(get_ccwdev_lock(pos->cdev));
+- pos->stopped |= DASD_STOPPED_SU;
+- if (pos != device)
+- spin_unlock(get_ccwdev_lock(pos->cdev));
+- }
+- list_for_each_entry(pos, &pavgroup->aliaslist, alias_list) {
+- if (pos != device)
+- spin_lock(get_ccwdev_lock(pos->cdev));
+- pos->stopped |= DASD_STOPPED_SU;
+- if (pos != device)
+- spin_unlock(get_ccwdev_lock(pos->cdev));
+- }
++ list_for_each_entry(pos, &pavgroup->baselist, alias_list)
++ __stop_device_on_lcu(device, pos);
++ list_for_each_entry(pos, &pavgroup->aliaslist, alias_list)
++ __stop_device_on_lcu(device, pos);
+ }
+ }
+
+diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
+index 61f1693..a0edae0 100644
+--- a/drivers/s390/block/dasd_eckd.c
++++ b/drivers/s390/block/dasd_eckd.c
+@@ -1415,6 +1415,13 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device,
+ return;
+ }
+
++
++ /* service information message SIM */
++ if ((irb->ecw[6] & DASD_SIM_SENSE) == DASD_SIM_SENSE) {
++ dasd_3990_erp_handle_sim(device, irb->ecw);
++ return;
++ }
++
+ /* just report other unsolicited interrupts */
+ DEV_MESSAGE(KERN_DEBUG, device, "%s",
+ "unsolicited interrupt received");
+diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
+index d13ea05..1166115 100644
+--- a/drivers/s390/block/dasd_fba.c
++++ b/drivers/s390/block/dasd_fba.c
+@@ -125,7 +125,8 @@ dasd_fba_check_characteristics(struct dasd_device *device)
+
+ private = (struct dasd_fba_private *) device->private;
+ if (private == NULL) {
+- private = kzalloc(sizeof(struct dasd_fba_private), GFP_KERNEL);
++ private = kzalloc(sizeof(struct dasd_fba_private),
++ GFP_KERNEL | GFP_DMA);
+ if (private == NULL) {
+ DEV_MESSAGE(KERN_WARNING, device, "%s",
+ "memory allocation failed for private "
+diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
+index 44b2984..6c624bf 100644
+--- a/drivers/s390/block/dasd_int.h
++++ b/drivers/s390/block/dasd_int.h
+@@ -72,6 +72,11 @@ struct dasd_block;
+ #define DASD_SENSE_BIT_2 0x20
+ #define DASD_SENSE_BIT_3 0x10
+
++/* BIT DEFINITIONS FOR SIM SENSE */
++#define DASD_SIM_SENSE 0x0F
++#define DASD_SIM_MSG_TO_OP 0x03
++#define DASD_SIM_LOG 0x0C
++
+ /*
+ * SECTION: MACROs for klogd and s390 debug feature (dbf)
+ */
+@@ -621,6 +626,7 @@ void dasd_log_sense(struct dasd_ccw_req *, struct irb *);
+
+ /* externals in dasd_3990_erp.c */
+ struct dasd_ccw_req *dasd_3990_erp_action(struct dasd_ccw_req *);
++void dasd_3990_erp_handle_sim(struct dasd_device *, char *);
+
+ /* externals in dasd_eer.c */
+ #ifdef CONFIG_DASD_EER
+diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
+index e6c94db..04787ea 100644
+--- a/drivers/s390/block/dcssblk.c
++++ b/drivers/s390/block/dcssblk.c
+@@ -142,57 +142,6 @@ dcssblk_get_device_by_name(char *name)
+ return NULL;
+ }
+
+-/*
+- * print appropriate error message for segment_load()/segment_type()
+- * return code
+- */
+-static void
+-dcssblk_segment_warn(int rc, char* seg_name)
+-{
+- switch (rc) {
+- case -ENOENT:
+- PRINT_WARN("cannot load/query segment %s, does not exist\n",
+- seg_name);
+- break;
+- case -ENOSYS:
+- PRINT_WARN("cannot load/query segment %s, not running on VM\n",
+- seg_name);
+- break;
+- case -EIO:
+- PRINT_WARN("cannot load/query segment %s, hardware error\n",
+- seg_name);
+- break;
+- case -ENOTSUPP:
+- PRINT_WARN("cannot load/query segment %s, is a multi-part "
+- "segment\n", seg_name);
+- break;
+- case -ENOSPC:
+- PRINT_WARN("cannot load/query segment %s, overlaps with "
+- "storage\n", seg_name);
+- break;
+- case -EBUSY:
+- PRINT_WARN("cannot load/query segment %s, overlaps with "
+- "already loaded dcss\n", seg_name);
+- break;
+- case -EPERM:
+- PRINT_WARN("cannot load/query segment %s, already loaded in "
+- "incompatible mode\n", seg_name);
+- break;
+- case -ENOMEM:
+- PRINT_WARN("cannot load/query segment %s, out of memory\n",
+- seg_name);
+- break;
+- case -ERANGE:
+- PRINT_WARN("cannot load/query segment %s, exceeds kernel "
+- "mapping range\n", seg_name);
+- break;
+- default:
+- PRINT_WARN("cannot load/query segment %s, return value %i\n",
+- seg_name, rc);
+- break;
+- }
+-}
+-
+ static void dcssblk_unregister_callback(struct device *dev)
+ {
+ device_unregister(dev);
+@@ -423,7 +372,7 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
+ rc = segment_load(local_buf, SEGMENT_SHARED,
+ &dev_info->start, &dev_info->end);
+ if (rc < 0) {
+- dcssblk_segment_warn(rc, dev_info->segment_name);
++ segment_warning(rc, dev_info->segment_name);
+ goto dealloc_gendisk;
+ }
+ seg_byte_size = (dev_info->end - dev_info->start + 1);
+diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
+index 67009bf..1e1f506 100644
+--- a/drivers/s390/char/monreader.c
++++ b/drivers/s390/char/monreader.c
+@@ -111,56 +111,6 @@ static void dcss_mkname(char *ascii_name, char *ebcdic_name)
+ ASCEBC(ebcdic_name, 8);
+ }
+
+-/*
+- * print appropriate error message for segment_load()/segment_type()
+- * return code
+- */
+-static void mon_segment_warn(int rc, char* seg_name)
+-{
+- switch (rc) {
+- case -ENOENT:
+- P_WARNING("cannot load/query segment %s, does not exist\n",
+- seg_name);
+- break;
+- case -ENOSYS:
+- P_WARNING("cannot load/query segment %s, not running on VM\n",
+- seg_name);
+- break;
+- case -EIO:
+- P_WARNING("cannot load/query segment %s, hardware error\n",
+- seg_name);
+- break;
+- case -ENOTSUPP:
+- P_WARNING("cannot load/query segment %s, is a multi-part "
+- "segment\n", seg_name);
+- break;
+- case -ENOSPC:
+- P_WARNING("cannot load/query segment %s, overlaps with "
+- "storage\n", seg_name);
+- break;
+- case -EBUSY:
+- P_WARNING("cannot load/query segment %s, overlaps with "
+- "already loaded dcss\n", seg_name);
+- break;
+- case -EPERM:
+- P_WARNING("cannot load/query segment %s, already loaded in "
+- "incompatible mode\n", seg_name);
+- break;
+- case -ENOMEM:
+- P_WARNING("cannot load/query segment %s, out of memory\n",
+- seg_name);
+- break;
+- case -ERANGE:
+- P_WARNING("cannot load/query segment %s, exceeds kernel "
+- "mapping range\n", seg_name);
+- break;
+- default:
+- P_WARNING("cannot load/query segment %s, return value %i\n",
+- seg_name, rc);
+- break;
+- }
+-}
+-
+ static inline unsigned long mon_mca_start(struct mon_msg *monmsg)
+ {
+ return *(u32 *) &monmsg->msg.rmmsg;
+@@ -585,7 +535,7 @@ static int __init mon_init(void)
+
+ rc = segment_type(mon_dcss_name);
+ if (rc < 0) {
+- mon_segment_warn(rc, mon_dcss_name);
++ segment_warning(rc, mon_dcss_name);
+ goto out_iucv;
+ }
+ if (rc != SEG_TYPE_SC) {
+@@ -598,7 +548,7 @@ static int __init mon_init(void)
+ rc = segment_load(mon_dcss_name, SEGMENT_SHARED,
+ &mon_dcss_start, &mon_dcss_end);
+ if (rc < 0) {
+- mon_segment_warn(rc, mon_dcss_name);
++ segment_warning(rc, mon_dcss_name);
+ rc = -EINVAL;
+ goto out_iucv;
+ }
+diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
+index 2e616e3..e3b3d39 100644
+--- a/drivers/s390/char/sclp_tty.c
++++ b/drivers/s390/char/sclp_tty.c
+@@ -332,7 +332,7 @@ sclp_tty_write_string(const unsigned char *str, int count)
+ if (sclp_ttybuf == NULL) {
+ while (list_empty(&sclp_tty_pages)) {
+ spin_unlock_irqrestore(&sclp_tty_lock, flags);
+- if (in_atomic())
++ if (in_interrupt())
+ sclp_sync_wait();
+ else
+ wait_event(sclp_tty_waitq,
+diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
+index f7b258d..ed50759 100644
+--- a/drivers/s390/char/sclp_vt220.c
++++ b/drivers/s390/char/sclp_vt220.c
+@@ -383,7 +383,7 @@ sclp_vt220_timeout(unsigned long data)
+ */
+ static int
+ __sclp_vt220_write(const unsigned char *buf, int count, int do_schedule,
+- int convertlf)
++ int convertlf, int may_schedule)
+ {
+ unsigned long flags;
+ void *page;
+@@ -398,9 +398,8 @@ __sclp_vt220_write(const unsigned char *buf, int count, int do_schedule,
+ /* Create a sclp output buffer if none exists yet */
+ if (sclp_vt220_current_request == NULL) {
+ while (list_empty(&sclp_vt220_empty)) {
+- spin_unlock_irqrestore(&sclp_vt220_lock,
+- flags);
+- if (in_atomic())
++ spin_unlock_irqrestore(&sclp_vt220_lock, flags);
++ if (in_interrupt() || !may_schedule)
+ sclp_sync_wait();
+ else
+ wait_event(sclp_vt220_waitq,
+@@ -450,7 +449,7 @@ __sclp_vt220_write(const unsigned char *buf, int count, int do_schedule,
+ static int
+ sclp_vt220_write(struct tty_struct *tty, const unsigned char *buf, int count)
+ {
+- return __sclp_vt220_write(buf, count, 1, 0);
++ return __sclp_vt220_write(buf, count, 1, 0, 1);
+ }
+
+ #define SCLP_VT220_SESSION_ENDED 0x01
+@@ -529,7 +528,7 @@ sclp_vt220_close(struct tty_struct *tty, struct file *filp)
+ static void
+ sclp_vt220_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+- __sclp_vt220_write(&ch, 1, 0, 0);
++ __sclp_vt220_write(&ch, 1, 0, 0, 1);
+ }
+
+ /*
+@@ -746,7 +745,7 @@ __initcall(sclp_vt220_tty_init);
+ static void
+ sclp_vt220_con_write(struct console *con, const char *buf, unsigned int count)
+ {
+- __sclp_vt220_write((const unsigned char *) buf, count, 1, 1);
++ __sclp_vt220_write((const unsigned char *) buf, count, 1, 1, 0);
+ }
+
+ static struct tty_driver *
+diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c
+index 5b47e9c..874adf3 100644
+--- a/drivers/s390/char/tape_34xx.c
++++ b/drivers/s390/char/tape_34xx.c
+@@ -394,7 +394,7 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
+ return tape_34xx_erp_failed(request, -ENOSPC);
+ default:
+ PRINT_ERR("Invalid op in %s:%i\n",
+- __FUNCTION__, __LINE__);
++ __func__, __LINE__);
+ return tape_34xx_erp_failed(request, 0);
+ }
+ }
+diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
+index b830a8c..ebe8406 100644
+--- a/drivers/s390/char/tape_char.c
++++ b/drivers/s390/char/tape_char.c
+@@ -83,9 +83,9 @@ tapechar_setup_device(struct tape_device * device)
+ void
+ tapechar_cleanup_device(struct tape_device *device)
+ {
+- unregister_tape_dev(device->rt);
++ unregister_tape_dev(&device->cdev->dev, device->rt);
+ device->rt = NULL;
+- unregister_tape_dev(device->nt);
++ unregister_tape_dev(&device->cdev->dev, device->nt);
+ device->nt = NULL;
+ }
+
+diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
+index aa7f166..6dfdb7c 100644
+--- a/drivers/s390/char/tape_class.c
++++ b/drivers/s390/char/tape_class.c
+@@ -99,11 +99,10 @@ fail_with_tcd:
+ }
+ EXPORT_SYMBOL(register_tape_dev);
+
+-void unregister_tape_dev(struct tape_class_device *tcd)
++void unregister_tape_dev(struct device *device, struct tape_class_device *tcd)
+ {
+ if (tcd != NULL && !IS_ERR(tcd)) {
+- sysfs_remove_link(&tcd->class_device->kobj,
+- tcd->mode_name);
++ sysfs_remove_link(&device->kobj, tcd->mode_name);
+ device_destroy(tape_class, tcd->char_device->dev);
+ cdev_del(tcd->char_device);
+ kfree(tcd);
+diff --git a/drivers/s390/char/tape_class.h b/drivers/s390/char/tape_class.h
+index e2b5ac9..707b7f4 100644
+--- a/drivers/s390/char/tape_class.h
++++ b/drivers/s390/char/tape_class.h
+@@ -56,6 +56,6 @@ struct tape_class_device *register_tape_dev(
+ char * device_name,
+ char * node_name
+ );
+-void unregister_tape_dev(struct tape_class_device *tcd);
++void unregister_tape_dev(struct device *device, struct tape_class_device *tcd);
+
+ #endif /* __TAPE_CLASS_H__ */
+diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
+index 7689b50..83ae9a8 100644
+--- a/drivers/s390/char/vmur.c
++++ b/drivers/s390/char/vmur.c
+@@ -100,7 +100,8 @@ static struct urdev *urdev_alloc(struct ccw_device *cdev)
+ urd->reclen = cdev->id.driver_info;
+ ccw_device_get_id(cdev, &urd->dev_id);
+ mutex_init(&urd->io_mutex);
+- mutex_init(&urd->open_mutex);
++ init_waitqueue_head(&urd->wait);
++ spin_lock_init(&urd->open_lock);
+ atomic_set(&urd->ref_count, 1);
+ urd->cdev = cdev;
+ get_device(&cdev->dev);
+@@ -678,17 +679,21 @@ static int ur_open(struct inode *inode, struct file *file)
+ if (!urd)
+ return -ENXIO;
+
+- if (file->f_flags & O_NONBLOCK) {
+- if (!mutex_trylock(&urd->open_mutex)) {
++ spin_lock(&urd->open_lock);
++ while (urd->open_flag) {
++ spin_unlock(&urd->open_lock);
++ if (file->f_flags & O_NONBLOCK) {
+ rc = -EBUSY;
+ goto fail_put;
+ }
+- } else {
+- if (mutex_lock_interruptible(&urd->open_mutex)) {
++ if (wait_event_interruptible(urd->wait, urd->open_flag == 0)) {
+ rc = -ERESTARTSYS;
+ goto fail_put;
+ }
++ spin_lock(&urd->open_lock);
+ }
++ urd->open_flag++;
++ spin_unlock(&urd->open_lock);
+
+ TRACE("ur_open\n");
+
+@@ -720,7 +725,9 @@ static int ur_open(struct inode *inode, struct file *file)
+ fail_urfile_free:
+ urfile_free(urf);
+ fail_unlock:
+- mutex_unlock(&urd->open_mutex);
++ spin_lock(&urd->open_lock);
++ urd->open_flag--;
++ spin_unlock(&urd->open_lock);
+ fail_put:
+ urdev_put(urd);
+ return rc;
+@@ -731,7 +738,10 @@ static int ur_release(struct inode *inode, struct file *file)
+ struct urfile *urf = file->private_data;
+
+ TRACE("ur_release\n");
+- mutex_unlock(&urf->urd->open_mutex);
++ spin_lock(&urf->urd->open_lock);
++ urf->urd->open_flag--;
++ spin_unlock(&urf->urd->open_lock);
++ wake_up_interruptible(&urf->urd->wait);
+ urdev_put(urf->urd);
+ urfile_free(urf);
+ return 0;
+diff --git a/drivers/s390/char/vmur.h b/drivers/s390/char/vmur.h
+index fa95964..fa320ad 100644
+--- a/drivers/s390/char/vmur.h
++++ b/drivers/s390/char/vmur.h
+@@ -62,7 +62,6 @@ struct file_control_block {
+ struct urdev {
+ struct ccw_device *cdev; /* Backpointer to ccw device */
+ struct mutex io_mutex; /* Serialises device IO */
+- struct mutex open_mutex; /* Serialises access to device */
+ struct completion *io_done; /* do_ur_io waits; irq completes */
+ struct device *device;
+ struct cdev *char_device;
+@@ -71,6 +70,9 @@ struct urdev {
+ int class; /* VM device class */
+ int io_request_rc; /* return code from I/O request */
+ atomic_t ref_count; /* reference counter */
++ wait_queue_head_t wait; /* wait queue to serialize open */
++ int open_flag; /* "urdev is open" flag */
++ spinlock_t open_lock; /* serialize critical sections */
+ };
+
+ /*
+diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c
+index 6f40fac..19f8389 100644
+--- a/drivers/s390/char/vmwatchdog.c
++++ b/drivers/s390/char/vmwatchdog.c
+@@ -96,7 +96,7 @@ static int vmwdt_keepalive(void)
+
+ if (ret) {
+ printk(KERN_WARNING "%s: problem setting interval %d, "
+- "cmd %s\n", __FUNCTION__, vmwdt_interval,
++ "cmd %s\n", __func__, vmwdt_interval,
+ vmwdt_cmd);
+ }
+ return ret;
+@@ -107,7 +107,7 @@ static int vmwdt_disable(void)
+ int ret = __diag288(wdt_cancel, 0, "", 0);
+ if (ret) {
+ printk(KERN_WARNING "%s: problem disabling watchdog\n",
+- __FUNCTION__);
++ __func__);
+ }
+ return ret;
+ }
+diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
+index f523501..bbbd14e 100644
+--- a/drivers/s390/char/zcore.c
++++ b/drivers/s390/char/zcore.c
+@@ -224,7 +224,7 @@ static int __init init_cpu_info(enum arch_id arch)
+
+ sa = kmalloc(sizeof(*sa), GFP_KERNEL);
+ if (!sa) {
+- ERROR_MSG("kmalloc failed: %s: %i\n",__FUNCTION__, __LINE__);
++ ERROR_MSG("kmalloc failed: %s: %i\n",__func__, __LINE__);
+ return -ENOMEM;
+ }
+ if (memcpy_hsa_kernel(sa, sys_info.sa_base, sys_info.sa_size) < 0) {
+diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
+index 03914fa..fe1ad17 100644
+--- a/drivers/s390/cio/ccwgroup.c
++++ b/drivers/s390/cio/ccwgroup.c
+@@ -16,7 +16,6 @@
+ #include <linux/ctype.h>
+ #include <linux/dcache.h>
+
+-#include <asm/semaphore.h>
+ #include <asm/ccwdev.h>
+ #include <asm/ccwgroup.h>
+
+diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
+index 007aaeb..5de8690 100644
+--- a/drivers/s390/cio/chsc.c
++++ b/drivers/s390/cio/chsc.c
+@@ -217,6 +217,8 @@ void chsc_chp_offline(struct chp_id chpid)
+
+ if (chp_get_status(chpid) <= 0)
+ return;
++ /* Wait until previous actions have settled. */
++ css_wait_for_slow_path();
+ for_each_subchannel_staged(s390_subchannel_remove_chpid, NULL, &chpid);
+ }
+
+@@ -303,7 +305,8 @@ static void s390_process_res_acc (struct res_acc_data *res_data)
+ sprintf(dbf_txt, "fla%x", res_data->fla);
+ CIO_TRACE_EVENT( 2, dbf_txt);
+ }
+-
++ /* Wait until previous actions have settled. */
++ css_wait_for_slow_path();
+ /*
+ * I/O resources may have become accessible.
+ * Scan through all subchannels that may be concerned and
+@@ -561,9 +564,12 @@ void chsc_chp_online(struct chp_id chpid)
+ sprintf(dbf_txt, "cadd%x.%02x", chpid.cssid, chpid.id);
+ CIO_TRACE_EVENT(2, dbf_txt);
+
+- if (chp_get_status(chpid) != 0)
++ if (chp_get_status(chpid) != 0) {
++ /* Wait until previous actions have settled. */
++ css_wait_for_slow_path();
+ for_each_subchannel_staged(__chp_add, __chp_add_new_sch,
+ &chpid);
++ }
+ }
+
+ static void __s390_subchannel_vary_chpid(struct subchannel *sch,
+@@ -650,6 +656,8 @@ __s390_vary_chpid_on(struct subchannel_id schid, void *data)
+ */
+ int chsc_chp_vary(struct chp_id chpid, int on)
+ {
++ /* Wait until previous actions have settled. */
++ css_wait_for_slow_path();
+ /*
+ * Redo PathVerification on the devices the chpid connects to
+ */
+@@ -758,7 +766,6 @@ chsc_secm(struct channel_subsystem *css, int enable)
+ if (!secm_area)
+ return -ENOMEM;
+
+- mutex_lock(&css->mutex);
+ if (enable && !css->cm_enabled) {
+ css->cub_addr1 = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ css->cub_addr2 = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+@@ -766,7 +773,6 @@ chsc_secm(struct channel_subsystem *css, int enable)
+ free_page((unsigned long)css->cub_addr1);
+ free_page((unsigned long)css->cub_addr2);
+ free_page((unsigned long)secm_area);
+- mutex_unlock(&css->mutex);
+ return -ENOMEM;
+ }
+ }
+@@ -787,7 +793,6 @@ chsc_secm(struct channel_subsystem *css, int enable)
+ free_page((unsigned long)css->cub_addr1);
+ free_page((unsigned long)css->cub_addr2);
+ }
+- mutex_unlock(&css->mutex);
+ free_page((unsigned long)secm_area);
+ return ret;
+ }
+diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
+index 60590a1..23ffcc4 100644
+--- a/drivers/s390/cio/cio.c
++++ b/drivers/s390/cio/cio.c
+@@ -24,6 +24,7 @@
+ #include <asm/ipl.h>
+ #include <asm/chpid.h>
+ #include <asm/airq.h>
++#include <asm/cpu.h>
+ #include "cio.h"
+ #include "css.h"
+ #include "chsc.h"
+@@ -649,13 +650,10 @@ do_IRQ (struct pt_regs *regs)
+
+ old_regs = set_irq_regs(regs);
+ irq_enter();
+- asm volatile ("mc 0,0");
+- if (S390_lowcore.int_clock >= S390_lowcore.jiffy_timer)
+- /**
+- * Make sure that the i/o interrupt did not "overtake"
+- * the last HZ timer interrupt.
+- */
+- account_ticks(S390_lowcore.int_clock);
++ s390_idle_check();
++ if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
++ /* Serve timer interrupts first. */
++ clock_comparator_work();
+ /*
+ * Get interrupt information from lowcore
+ */
+@@ -672,10 +670,14 @@ do_IRQ (struct pt_regs *regs)
+ continue;
+ }
+ sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
+- if (sch)
+- spin_lock(sch->lock);
++ if (!sch) {
++ /* Clear pending interrupt condition. */
++ tsch(tpi_info->schid, irb);
++ continue;
++ }
++ spin_lock(sch->lock);
+ /* Store interrupt response block to lowcore. */
+- if (tsch (tpi_info->schid, irb) == 0 && sch) {
++ if (tsch(tpi_info->schid, irb) == 0) {
+ /* Keep subchannel information word up to date. */
+ memcpy (&sch->schib.scsw, &irb->scsw,
+ sizeof (irb->scsw));
+@@ -683,8 +685,7 @@ do_IRQ (struct pt_regs *regs)
+ if (sch->driver && sch->driver->irq)
+ sch->driver->irq(sch);
+ }
+- if (sch)
+- spin_unlock(sch->lock);
++ spin_unlock(sch->lock);
+ /*
+ * Are more interrupts pending?
+ * If so, the tpi instruction will update the lowcore
+@@ -710,8 +711,9 @@ void *cio_get_console_priv(void)
+ /*
+ * busy wait for the next interrupt on the console
+ */
+-void
+-wait_cons_dev (void)
++void wait_cons_dev(void)
++ __releases(console_subchannel.lock)
++ __acquires(console_subchannel.lock)
+ {
+ unsigned long cr6 __attribute__ ((aligned (8)));
+ unsigned long save_cr6 __attribute__ ((aligned (8)));
+diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
+index 52afa4c..08f2235 100644
+--- a/drivers/s390/cio/cio.h
++++ b/drivers/s390/cio/cio.h
+@@ -100,6 +100,7 @@ extern int cio_modify (struct subchannel *);
+
+ int cio_create_sch_lock(struct subchannel *);
+ void do_adapter_IO(void);
++void do_IRQ(struct pt_regs *);
+
+ /* Use with care. */
+ #ifdef CONFIG_CCW_CONSOLE
+diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
+index 3b45bbe..c1afab5 100644
+--- a/drivers/s390/cio/css.c
++++ b/drivers/s390/cio/css.c
+@@ -533,6 +533,12 @@ void css_schedule_eval_all(void)
+ spin_unlock_irqrestore(&slow_subchannel_lock, flags);
+ }
+
++void css_wait_for_slow_path(void)
++{
++ flush_workqueue(ccw_device_notify_work);
++ flush_workqueue(slow_path_wq);
++}
++
+ /* Reprobe subchannel if unregistered. */
+ static int reprobe_subchannel(struct subchannel_id schid, void *data)
+ {
+@@ -683,10 +689,14 @@ css_cm_enable_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+ {
+ struct channel_subsystem *css = to_css(dev);
++ int ret;
+
+ if (!css)
+ return 0;
+- return sprintf(buf, "%x\n", css->cm_enabled);
++ mutex_lock(&css->mutex);
++ ret = sprintf(buf, "%x\n", css->cm_enabled);
++ mutex_unlock(&css->mutex);
++ return ret;
+ }
+
+ static ssize_t
+@@ -696,6 +706,7 @@ css_cm_enable_store(struct device *dev, struct device_attribute *attr,
+ struct channel_subsystem *css = to_css(dev);
+ int ret;
+
++ mutex_lock(&css->mutex);
+ switch (buf[0]) {
+ case '0':
+ ret = css->cm_enabled ? chsc_secm(css, 0) : 0;
+@@ -706,6 +717,7 @@ css_cm_enable_store(struct device *dev, struct device_attribute *attr,
+ default:
+ ret = -EINVAL;
+ }
++ mutex_unlock(&css->mutex);
+ return ret < 0 ? ret : count;
+ }
+
+@@ -752,9 +764,11 @@ static int css_reboot_event(struct notifier_block *this,
+ struct channel_subsystem *css;
+
+ css = channel_subsystems[i];
++ mutex_lock(&css->mutex);
+ if (css->cm_enabled)
+ if (chsc_secm(css, 0))
+ ret = NOTIFY_BAD;
++ mutex_unlock(&css->mutex);
+ }
+
+ return ret;
+diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
+index b705545..e191351 100644
+--- a/drivers/s390/cio/css.h
++++ b/drivers/s390/cio/css.h
+@@ -144,6 +144,7 @@ struct schib;
+ int css_sch_is_valid(struct schib *);
+
+ extern struct workqueue_struct *slow_path_wq;
++void css_wait_for_slow_path(void);
+
+ extern struct attribute_group *subch_attr_groups[];
+ #endif
+diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
+index fec004f..e0c7adb 100644
+--- a/drivers/s390/cio/device.c
++++ b/drivers/s390/cio/device.c
+@@ -577,7 +577,6 @@ static DEVICE_ATTR(devtype, 0444, devtype_show, NULL);
+ static DEVICE_ATTR(cutype, 0444, cutype_show, NULL);
+ static DEVICE_ATTR(modalias, 0444, modalias_show, NULL);
+ static DEVICE_ATTR(online, 0644, online_show, online_store);
+-extern struct device_attribute dev_attr_cmb_enable;
+ static DEVICE_ATTR(availability, 0444, available_show, NULL);
+
+ static struct attribute * subch_attrs[] = {
+diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
+index d40a2ff..cb08092 100644
+--- a/drivers/s390/cio/device.h
++++ b/drivers/s390/cio/device.h
+@@ -127,4 +127,5 @@ extern struct bus_type ccw_bus_type;
+ void retry_set_schib(struct ccw_device *cdev);
+ void cmf_retry_copy_block(struct ccw_device *);
+ int cmf_reenable(struct ccw_device *);
++extern struct device_attribute dev_attr_cmb_enable;
+ #endif
+diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
+index 49b58eb..a1718a0 100644
+--- a/drivers/s390/cio/device_ops.c
++++ b/drivers/s390/cio/device_ops.c
+@@ -193,8 +193,15 @@ int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
+ return -EACCES;
+ }
+ ret = cio_start_key (sch, cpa, lpm, key);
+- if (ret == 0)
++ switch (ret) {
++ case 0:
+ cdev->private->intparm = intparm;
++ break;
++ case -EACCES:
++ case -ENODEV:
++ dev_fsm_event(cdev, DEV_EVENT_VERIFY);
++ break;
++ }
+ return ret;
+ }
+
+diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c
+index ebe0848..4a38993 100644
+--- a/drivers/s390/cio/device_status.c
++++ b/drivers/s390/cio/device_status.c
+@@ -62,7 +62,7 @@ ccw_device_path_notoper(struct ccw_device *cdev)
+ stsch (sch->schid, &sch->schib);
+
+ CIO_MSG_EVENT(0, "%s(0.%x.%04x) - path(s) %02x are "
+- "not operational \n", __FUNCTION__,
++ "not operational \n", __func__,
+ sch->schid.ssid, sch->schid.sch_no,
+ sch->schib.pmcw.pnom);
+
+@@ -312,6 +312,7 @@ ccw_device_do_sense(struct ccw_device *cdev, struct irb *irb)
+ {
+ struct subchannel *sch;
+ struct ccw1 *sense_ccw;
++ int rc;
+
+ sch = to_subchannel(cdev->dev.parent);
+
+@@ -337,7 +338,10 @@ ccw_device_do_sense(struct ccw_device *cdev, struct irb *irb)
+ /* Reset internal retry indication. */
+ cdev->private->flags.intretry = 0;
+
+- return cio_start(sch, sense_ccw, 0xff);
++ rc = cio_start(sch, sense_ccw, 0xff);
++ if (rc == -ENODEV || rc == -EACCES)
++ dev_fsm_event(cdev, DEV_EVENT_VERIFY);
++ return rc;
+ }
+
+ /*
+diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
+index 2b5bfb7..10aa1e7 100644
+--- a/drivers/s390/cio/qdio.c
++++ b/drivers/s390/cio/qdio.c
+@@ -38,11 +38,11 @@
+ #include <linux/proc_fs.h>
+ #include <linux/timer.h>
+ #include <linux/mempool.h>
++#include <linux/semaphore.h>
+
+ #include <asm/ccwdev.h>
+ #include <asm/io.h>
+ #include <asm/atomic.h>
+-#include <asm/semaphore.h>
+ #include <asm/timex.h>
+
+ #include <asm/debug.h>
+@@ -1399,7 +1399,7 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set)
+ * q->dev_st_chg_ind is the indicator, be it shared or not.
+ * only clear it, if indicator is non-shared
+ */
+- if (!spare_ind_was_set)
++ if (q->dev_st_chg_ind != &spare_indicator)
+ tiqdio_clear_summary_bit((__u32*)q->dev_st_chg_ind);
+
+ if (q->hydra_gives_outbound_pcis) {
+@@ -2217,9 +2217,78 @@ qdio_synchronize(struct ccw_device *cdev, unsigned int flags,
+ return cc;
+ }
+
++static int
++qdio_get_ssqd_information(struct subchannel_id *schid,
++ struct qdio_chsc_ssqd **ssqd_area)
++{
++ int result;
++
++ QDIO_DBF_TEXT0(0, setup, "getssqd");
++ *ssqd_area = mempool_alloc(qdio_mempool_scssc, GFP_ATOMIC);
++ if (!ssqd_area) {
++ QDIO_PRINT_WARN("Could not get memory for chsc on sch x%x.\n",
++ schid->sch_no);
++ return -ENOMEM;
++ }
++
++ (*ssqd_area)->request = (struct chsc_header) {
++ .length = 0x0010,
++ .code = 0x0024,
++ };
++ (*ssqd_area)->first_sch = schid->sch_no;
++ (*ssqd_area)->last_sch = schid->sch_no;
++ (*ssqd_area)->ssid = schid->ssid;
++ result = chsc(*ssqd_area);
++
++ if (result) {
++ QDIO_PRINT_WARN("CHSC returned cc %i on sch 0.%x.%x.\n",
++ result, schid->ssid, schid->sch_no);
++ goto out;
++ }
++
++ if ((*ssqd_area)->response.code != QDIO_CHSC_RESPONSE_CODE_OK) {
++ QDIO_PRINT_WARN("CHSC response is 0x%x on sch 0.%x.%x.\n",
++ (*ssqd_area)->response.code,
++ schid->ssid, schid->sch_no);
++ goto out;
++ }
++ if (!((*ssqd_area)->flags & CHSC_FLAG_QDIO_CAPABILITY) ||
++ !((*ssqd_area)->flags & CHSC_FLAG_VALIDITY) ||
++ ((*ssqd_area)->sch != schid->sch_no)) {
++ QDIO_PRINT_WARN("huh? problems checking out sch 0.%x.%x... " \
++ "using all SIGAs.\n",
++ schid->ssid, schid->sch_no);
++ goto out;
++ }
++ return 0;
++out:
++ return -EINVAL;
++}
++
++int
++qdio_get_ssqd_pct(struct ccw_device *cdev)
++{
++ struct qdio_chsc_ssqd *ssqd_area;
++ struct subchannel_id schid;
++ char dbf_text[15];
++ int rc;
++ int pct = 0;
++
++ QDIO_DBF_TEXT0(0, setup, "getpct");
++ schid = ccw_device_get_subchannel_id(cdev);
++ rc = qdio_get_ssqd_information(&schid, &ssqd_area);
++ if (!rc)
++ pct = (int)ssqd_area->pct;
++ if (rc != -ENOMEM)
++ mempool_free(ssqd_area, qdio_mempool_scssc);
++ sprintf(dbf_text, "pct: %d", pct);
++ QDIO_DBF_TEXT2(0, setup, dbf_text);
++ return pct;
++}
++EXPORT_SYMBOL(qdio_get_ssqd_pct);
++
+ static void
+-qdio_check_subchannel_qebsm(struct qdio_irq *irq_ptr, unsigned char qdioac,
+- unsigned long token)
++qdio_check_subchannel_qebsm(struct qdio_irq *irq_ptr, unsigned long token)
+ {
+ struct qdio_q *q;
+ int i;
+@@ -2227,7 +2296,7 @@ qdio_check_subchannel_qebsm(struct qdio_irq *irq_ptr, unsigned char qdioac,
+ char dbf_text[15];
+
+ /*check if QEBSM is disabled */
+- if (!(irq_ptr->is_qebsm) || !(qdioac & 0x01)) {
++ if (!(irq_ptr->is_qebsm) || !(irq_ptr->qdioac & 0x01)) {
+ irq_ptr->is_qebsm = 0;
+ irq_ptr->sch_token = 0;
+ irq_ptr->qib.rflags &= ~QIB_RFLAGS_ENABLE_QEBSM;
+@@ -2256,102 +2325,27 @@ qdio_check_subchannel_qebsm(struct qdio_irq *irq_ptr, unsigned char qdioac,
+ }
+
+ static void
+-qdio_get_ssqd_information(struct qdio_irq *irq_ptr)
++qdio_get_ssqd_siga(struct qdio_irq *irq_ptr)
+ {
+- int result;
+- unsigned char qdioac;
+- struct {
+- struct chsc_header request;
+- u16 reserved1:10;
+- u16 ssid:2;
+- u16 fmt:4;
+- u16 first_sch;
+- u16 reserved2;
+- u16 last_sch;
+- u32 reserved3;
+- struct chsc_header response;
+- u32 reserved4;
+- u8 flags;
+- u8 reserved5;
+- u16 sch;
+- u8 qfmt;
+- u8 parm;
+- u8 qdioac1;
+- u8 sch_class;
+- u8 reserved7;
+- u8 icnt;
+- u8 reserved8;
+- u8 ocnt;
+- u8 reserved9;
+- u8 mbccnt;
+- u16 qdioac2;
+- u64 sch_token;
+- } *ssqd_area;
++ int rc;
++ struct qdio_chsc_ssqd *ssqd_area;
+
+ QDIO_DBF_TEXT0(0,setup,"getssqd");
+- qdioac = 0;
+- ssqd_area = mempool_alloc(qdio_mempool_scssc, GFP_ATOMIC);
+- if (!ssqd_area) {
+- QDIO_PRINT_WARN("Could not get memory for chsc. Using all " \
+- "SIGAs for sch x%x.\n", irq_ptr->schid.sch_no);
++ irq_ptr->qdioac = 0;
++ rc = qdio_get_ssqd_information(&irq_ptr->schid, &ssqd_area);
++ if (rc) {
++ QDIO_PRINT_WARN("using all SIGAs for sch x%x.n",
++ irq_ptr->schid.sch_no);
+ irq_ptr->qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY |
+ CHSC_FLAG_SIGA_OUTPUT_NECESSARY |
+ CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
+ irq_ptr->is_qebsm = 0;
+- irq_ptr->sch_token = 0;
+- irq_ptr->qib.rflags &= ~QIB_RFLAGS_ENABLE_QEBSM;
+- return;
+- }
+-
+- ssqd_area->request = (struct chsc_header) {
+- .length = 0x0010,
+- .code = 0x0024,
+- };
+- ssqd_area->first_sch = irq_ptr->schid.sch_no;
+- ssqd_area->last_sch = irq_ptr->schid.sch_no;
+- ssqd_area->ssid = irq_ptr->schid.ssid;
+- result = chsc(ssqd_area);
+-
+- if (result) {
+- QDIO_PRINT_WARN("CHSC returned cc %i. Using all " \
+- "SIGAs for sch 0.%x.%x.\n", result,
+- irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
+- qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY |
+- CHSC_FLAG_SIGA_OUTPUT_NECESSARY |
+- CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
+- irq_ptr->is_qebsm = 0;
+- goto out;
+- }
++ } else
++ irq_ptr->qdioac = ssqd_area->qdioac1;
+
+- if (ssqd_area->response.code != QDIO_CHSC_RESPONSE_CODE_OK) {
+- QDIO_PRINT_WARN("response upon checking SIGA needs " \
+- "is 0x%x. Using all SIGAs for sch 0.%x.%x.\n",
+- ssqd_area->response.code,
+- irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
+- qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY |
+- CHSC_FLAG_SIGA_OUTPUT_NECESSARY |
+- CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
+- irq_ptr->is_qebsm = 0;
+- goto out;
+- }
+- if (!(ssqd_area->flags & CHSC_FLAG_QDIO_CAPABILITY) ||
+- !(ssqd_area->flags & CHSC_FLAG_VALIDITY) ||
+- (ssqd_area->sch != irq_ptr->schid.sch_no)) {
+- QDIO_PRINT_WARN("huh? problems checking out sch 0.%x.%x... " \
+- "using all SIGAs.\n",
+- irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
+- qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY |
+- CHSC_FLAG_SIGA_OUTPUT_NECESSARY |
+- CHSC_FLAG_SIGA_SYNC_NECESSARY; /* worst case */
+- irq_ptr->is_qebsm = 0;
+- goto out;
+- }
+- qdioac = ssqd_area->qdioac1;
+-out:
+- qdio_check_subchannel_qebsm(irq_ptr, qdioac,
+- ssqd_area->sch_token);
+- mempool_free(ssqd_area, qdio_mempool_scssc);
+- irq_ptr->qdioac = qdioac;
++ qdio_check_subchannel_qebsm(irq_ptr, ssqd_area->sch_token);
++ if (rc != -ENOMEM)
++ mempool_free(ssqd_area, qdio_mempool_scssc);
+ }
+
+ static unsigned int
+@@ -3227,7 +3221,7 @@ qdio_establish(struct qdio_initialize *init_data)
+ return -EIO;
+ }
+
+- qdio_get_ssqd_information(irq_ptr);
++ qdio_get_ssqd_siga(irq_ptr);
+ /* if this gets set once, we're running under VM and can omit SVSes */
+ if (irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_NECESSARY)
+ omit_svs=1;
+diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
+index da8a272..c3df6b2 100644
+--- a/drivers/s390/cio/qdio.h
++++ b/drivers/s390/cio/qdio.h
+@@ -406,6 +406,34 @@ do_clear_global_summary(void)
+ #define CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS 0x08
+ #define CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS 0x04
+
++struct qdio_chsc_ssqd {
++ struct chsc_header request;
++ u16 reserved1:10;
++ u16 ssid:2;
++ u16 fmt:4;
++ u16 first_sch;
++ u16 reserved2;
++ u16 last_sch;
++ u32 reserved3;
++ struct chsc_header response;
++ u32 reserved4;
++ u8 flags;
++ u8 reserved5;
++ u16 sch;
++ u8 qfmt;
++ u8 parm;
++ u8 qdioac1;
++ u8 sch_class;
++ u8 pct;
++ u8 icnt;
++ u8 reserved7;
++ u8 ocnt;
++ u8 reserved8;
++ u8 mbccnt;
++ u16 qdioac2;
++ u64 sch_token;
++};
++
+ struct qdio_perf_stats {
+ #ifdef CONFIG_64BIT
+ atomic64_t tl_runs;
+diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
+index 7b0b819..a1ab3e3 100644
+--- a/drivers/s390/crypto/ap_bus.c
++++ b/drivers/s390/crypto/ap_bus.c
+@@ -45,7 +45,7 @@ static int ap_poll_thread_start(void);
+ static void ap_poll_thread_stop(void);
+ static void ap_request_timeout(unsigned long);
+
+-/**
++/*
+ * Module description.
+ */
+ MODULE_AUTHOR("IBM Corporation");
+@@ -53,7 +53,7 @@ MODULE_DESCRIPTION("Adjunct Processor Bus driver, "
+ "Copyright 2006 IBM Corporation");
+ MODULE_LICENSE("GPL");
+
+-/**
++/*
+ * Module parameter
+ */
+ int ap_domain_index = -1; /* Adjunct Processor Domain Index */
+@@ -69,7 +69,7 @@ static struct device *ap_root_device = NULL;
+ static DEFINE_SPINLOCK(ap_device_lock);
+ static LIST_HEAD(ap_device_list);
+
+-/**
++/*
+ * Workqueue & timer for bus rescan.
+ */
+ static struct workqueue_struct *ap_work_queue;
+@@ -77,7 +77,7 @@ static struct timer_list ap_config_timer;
+ static int ap_config_time = AP_CONFIG_TIME;
+ static DECLARE_WORK(ap_config_work, ap_scan_bus);
+
+-/**
++/*
+ * Tasklet & timer for AP request polling.
+ */
+ static struct timer_list ap_poll_timer = TIMER_INITIALIZER(ap_poll_timeout,0,0);
+@@ -88,9 +88,9 @@ static struct task_struct *ap_poll_kthread = NULL;
+ static DEFINE_MUTEX(ap_poll_thread_mutex);
+
+ /**
+- * Test if ap instructions are available.
++ * ap_intructions_available() - Test if AP instructions are available.
+ *
+- * Returns 0 if the ap instructions are installed.
++ * Returns 0 if the AP instructions are installed.
+ */
+ static inline int ap_instructions_available(void)
+ {
+@@ -108,12 +108,12 @@ static inline int ap_instructions_available(void)
+ }
+
+ /**
+- * Test adjunct processor queue.
+- * @qid: the ap queue number
+- * @queue_depth: pointer to queue depth value
+- * @device_type: pointer to device type value
++ * ap_test_queue(): Test adjunct processor queue.
++ * @qid: The AP queue number
++ * @queue_depth: Pointer to queue depth value
++ * @device_type: Pointer to device type value
+ *
+- * Returns ap queue status structure.
++ * Returns AP queue status structure.
+ */
+ static inline struct ap_queue_status
+ ap_test_queue(ap_qid_t qid, int *queue_depth, int *device_type)
+@@ -130,10 +130,10 @@ ap_test_queue(ap_qid_t qid, int *queue_depth, int *device_type)
+ }
+
+ /**
+- * Reset adjunct processor queue.
+- * @qid: the ap queue number
++ * ap_reset_queue(): Reset adjunct processor queue.
++ * @qid: The AP queue number
+ *
+- * Returns ap queue status structure.
++ * Returns AP queue status structure.
+ */
+ static inline struct ap_queue_status ap_reset_queue(ap_qid_t qid)
+ {
+@@ -148,16 +148,14 @@ static inline struct ap_queue_status ap_reset_queue(ap_qid_t qid)
+ }
+
+ /**
+- * Send message to adjunct processor queue.
+- * @qid: the ap queue number
+- * @psmid: the program supplied message identifier
+- * @msg: the message text
+- * @length: the message length
+- *
+- * Returns ap queue status structure.
++ * __ap_send(): Send message to adjunct processor queue.
++ * @qid: The AP queue number
++ * @psmid: The program supplied message identifier
++ * @msg: The message text
++ * @length: The message length
+ *
++ * Returns AP queue status structure.
+ * Condition code 1 on NQAP can't happen because the L bit is 1.
+- *
+ * Condition code 2 on NQAP also means the send is incomplete,
+ * because a segment boundary was reached. The NQAP is repeated.
+ */
+@@ -198,23 +196,20 @@ int ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length)
+ }
+ EXPORT_SYMBOL(ap_send);
+
+-/*
+- * Receive message from adjunct processor queue.
+- * @qid: the ap queue number
+- * @psmid: pointer to program supplied message identifier
+- * @msg: the message text
+- * @length: the message length
+- *
+- * Returns ap queue status structure.
++/**
++ * __ap_recv(): Receive message from adjunct processor queue.
++ * @qid: The AP queue number
++ * @psmid: Pointer to program supplied message identifier
++ * @msg: The message text
++ * @length: The message length
+ *
++ * Returns AP queue status structure.
+ * Condition code 1 on DQAP means the receive has taken place
+ * but only partially. The response is incomplete, hence the
+ * DQAP is repeated.
+- *
+ * Condition code 2 on DQAP also means the receive is incomplete,
+ * this time because a segment boundary was reached. Again, the
+ * DQAP is repeated.
+- *
+ * Note that gpr2 is used by the DQAP instruction to keep track of
+ * any 'residual' length, in case the instruction gets interrupted.
+ * Hence it gets zeroed before the instruction.
+@@ -263,11 +258,12 @@ int ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
+ EXPORT_SYMBOL(ap_recv);
+
+ /**
+- * Check if an AP queue is available. The test is repeated for
+- * AP_MAX_RESET times.
+- * @qid: the ap queue number
+- * @queue_depth: pointer to queue depth value
+- * @device_type: pointer to device type value
++ * ap_query_queue(): Check if an AP queue is available.
++ * @qid: The AP queue number
++ * @queue_depth: Pointer to queue depth value
++ * @device_type: Pointer to device type value
++ *
++ * The test is repeated for AP_MAX_RESET times.
+ */
+ static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type)
+ {
+@@ -308,8 +304,10 @@ static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type)
+ }
+
+ /**
++ * ap_init_queue(): Reset an AP queue.
++ * @qid: The AP queue number
++ *
+ * Reset an AP queue and wait for it to become available again.
+- * @qid: the ap queue number
+ */
+ static int ap_init_queue(ap_qid_t qid)
+ {
+@@ -346,7 +344,10 @@ static int ap_init_queue(ap_qid_t qid)
+ }
+
+ /**
+- * Arm request timeout if a AP device was idle and a new request is submitted.
++ * ap_increase_queue_count(): Arm request timeout.
++ * @ap_dev: Pointer to an AP device.
++ *
++ * Arm request timeout if an AP device was idle and a new request is submitted.
+ */
+ static void ap_increase_queue_count(struct ap_device *ap_dev)
+ {
+@@ -360,7 +361,10 @@ static void ap_increase_queue_count(struct ap_device *ap_dev)
+ }
+
+ /**
+- * AP device is still alive, re-schedule request timeout if there are still
++ * ap_decrease_queue_count(): Decrease queue count.
++ * @ap_dev: Pointer to an AP device.
++ *
++ * If AP device is still alive, re-schedule request timeout if there are still
+ * pending requests.
+ */
+ static void ap_decrease_queue_count(struct ap_device *ap_dev)
+@@ -371,7 +375,7 @@ static void ap_decrease_queue_count(struct ap_device *ap_dev)
+ if (ap_dev->queue_count > 0)
+ mod_timer(&ap_dev->timeout, jiffies + timeout);
+ else
+- /**
++ /*
+ * The timeout timer should to be disabled now - since
+ * del_timer_sync() is very expensive, we just tell via the
+ * reset flag to ignore the pending timeout timer.
+@@ -379,7 +383,7 @@ static void ap_decrease_queue_count(struct ap_device *ap_dev)
+ ap_dev->reset = AP_RESET_IGNORE;
+ }
+
+-/**
++/*
+ * AP device related attributes.
+ */
+ static ssize_t ap_hwtype_show(struct device *dev,
+@@ -433,6 +437,10 @@ static struct attribute_group ap_dev_attr_group = {
+ };
+
+ /**
++ * ap_bus_match()
++ * @dev: Pointer to device
++ * @drv: Pointer to device_driver
++ *
+ * AP bus driver registration/unregistration.
+ */
+ static int ap_bus_match(struct device *dev, struct device_driver *drv)
+@@ -441,7 +449,7 @@ static int ap_bus_match(struct device *dev, struct device_driver *drv)
+ struct ap_driver *ap_drv = to_ap_drv(drv);
+ struct ap_device_id *id;
+
+- /**
++ /*
+ * Compare device type of the device with the list of
+ * supported types of the device_driver.
+ */
+@@ -455,8 +463,12 @@ static int ap_bus_match(struct device *dev, struct device_driver *drv)
+ }
+
+ /**
+- * uevent function for AP devices. It sets up a single environment
+- * variable DEV_TYPE which contains the hardware device type.
++ * ap_uevent(): Uevent function for AP devices.
++ * @dev: Pointer to device
++ * @env: Pointer to kobj_uevent_env
++ *
++ * It sets up a single environment variable DEV_TYPE which contains the
++ * hardware device type.
+ */
+ static int ap_uevent (struct device *dev, struct kobj_uevent_env *env)
+ {
+@@ -500,8 +512,10 @@ static int ap_device_probe(struct device *dev)
+ }
+
+ /**
++ * __ap_flush_queue(): Flush requests.
++ * @ap_dev: Pointer to the AP device
++ *
+ * Flush all requests from the request/pending queue of an AP device.
+- * @ap_dev: pointer to the AP device.
+ */
+ static void __ap_flush_queue(struct ap_device *ap_dev)
+ {
+@@ -565,7 +579,7 @@ void ap_driver_unregister(struct ap_driver *ap_drv)
+ }
+ EXPORT_SYMBOL(ap_driver_unregister);
+
+-/**
++/*
+ * AP bus attributes.
+ */
+ static ssize_t ap_domain_show(struct bus_type *bus, char *buf)
+@@ -630,14 +644,16 @@ static struct bus_attribute *const ap_bus_attrs[] = {
+ };
+
+ /**
+- * Pick one of the 16 ap domains.
++ * ap_select_domain(): Select an AP domain.
++ *
++ * Pick one of the 16 AP domains.
+ */
+ static int ap_select_domain(void)
+ {
+ int queue_depth, device_type, count, max_count, best_domain;
+ int rc, i, j;
+
+- /**
++ /*
+ * We want to use a single domain. Either the one specified with
+ * the "domain=" parameter or the domain with the maximum number
+ * of devices.
+@@ -669,8 +685,10 @@ static int ap_select_domain(void)
+ }
+
+ /**
+- * Find the device type if query queue returned a device type of 0.
++ * ap_probe_device_type(): Find the device type of an AP.
+ * @ap_dev: pointer to the AP device.
++ *
++ * Find the device type if query queue returned a device type of 0.
+ */
+ static int ap_probe_device_type(struct ap_device *ap_dev)
+ {
+@@ -764,7 +782,11 @@ out:
+ }
+
+ /**
+- * Scan the ap bus for new devices.
++ * __ap_scan_bus(): Scan the AP bus.
++ * @dev: Pointer to device
++ * @data: Pointer to data
++ *
++ * Scan the AP bus for new devices.
+ */
+ static int __ap_scan_bus(struct device *dev, void *data)
+ {
+@@ -867,6 +889,8 @@ ap_config_timeout(unsigned long ptr)
+ }
+
+ /**
++ * ap_schedule_poll_timer(): Schedule poll timer.
++ *
+ * Set up the timer to run the poll tasklet
+ */
+ static inline void ap_schedule_poll_timer(void)
+@@ -877,10 +901,11 @@ static inline void ap_schedule_poll_timer(void)
+ }
+
+ /**
+- * Receive pending reply messages from an AP device.
++ * ap_poll_read(): Receive pending reply messages from an AP device.
+ * @ap_dev: pointer to the AP device
+ * @flags: pointer to control flags, bit 2^0 is set if another poll is
+ * required, bit 2^1 is set if the poll timer needs to get armed
++ *
+ * Returns 0 if the device is still present, -ENODEV if not.
+ */
+ static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
+@@ -925,10 +950,11 @@ static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
+ }
+
+ /**
+- * Send messages from the request queue to an AP device.
++ * ap_poll_write(): Send messages from the request queue to an AP device.
+ * @ap_dev: pointer to the AP device
+ * @flags: pointer to control flags, bit 2^0 is set if another poll is
+ * required, bit 2^1 is set if the poll timer needs to get armed
++ *
+ * Returns 0 if the device is still present, -ENODEV if not.
+ */
+ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
+@@ -968,11 +994,13 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
+ }
+
+ /**
+- * Poll AP device for pending replies and send new messages. If either
+- * ap_poll_read or ap_poll_write returns -ENODEV unregister the device.
++ * ap_poll_queue(): Poll AP device for pending replies and send new messages.
+ * @ap_dev: pointer to the bus device
+ * @flags: pointer to control flags, bit 2^0 is set if another poll is
+ * required, bit 2^1 is set if the poll timer needs to get armed
++ *
++ * Poll AP device for pending replies and send new messages. If either
++ * ap_poll_read or ap_poll_write returns -ENODEV unregister the device.
+ * Returns 0.
+ */
+ static inline int ap_poll_queue(struct ap_device *ap_dev, unsigned long *flags)
+@@ -986,9 +1014,11 @@ static inline int ap_poll_queue(struct ap_device *ap_dev, unsigned long *flags)
+ }
+
+ /**
+- * Queue a message to a device.
++ * __ap_queue_message(): Queue a message to a device.
+ * @ap_dev: pointer to the AP device
+ * @ap_msg: the message to be queued
++ *
++ * Queue a message to a device. Returns 0 if successful.
+ */
+ static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
+ {
+@@ -1055,12 +1085,14 @@ void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
+ EXPORT_SYMBOL(ap_queue_message);
+
+ /**
++ * ap_cancel_message(): Cancel a crypto request.
++ * @ap_dev: The AP device that has the message queued
++ * @ap_msg: The message that is to be removed
++ *
+ * Cancel a crypto request. This is done by removing the request
+- * from the devive pendingq or requestq queue. Note that the
++ * from the device pending or request queue. Note that the
+ * request stays on the AP queue. When it finishes the message
+ * reply will be discarded because the psmid can't be found.
+- * @ap_dev: AP device that has the message queued
+- * @ap_msg: the message that is to be removed
+ */
+ void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
+ {
+@@ -1082,7 +1114,10 @@ void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
+ EXPORT_SYMBOL(ap_cancel_message);
+
+ /**
+- * AP receive polling for finished AP requests
++ * ap_poll_timeout(): AP receive polling for finished AP requests.
++ * @unused: Unused variable.
++ *
++ * Schedules the AP tasklet.
+ */
+ static void ap_poll_timeout(unsigned long unused)
+ {
+@@ -1090,6 +1125,9 @@ static void ap_poll_timeout(unsigned long unused)
+ }
+
+ /**
++ * ap_reset(): Reset a not responding AP device.
++ * @ap_dev: Pointer to the AP device
++ *
+ * Reset a not responding AP device and move all requests from the
+ * pending queue to the request queue.
+ */
+@@ -1108,11 +1146,6 @@ static void ap_reset(struct ap_device *ap_dev)
+ ap_dev->unregistered = 1;
+ }
+
+-/**
+- * Poll all AP devices on the bus in a round robin fashion. Continue
+- * polling until bit 2^0 of the control flags is not set. If bit 2^1
+- * of the control flags has been set arm the poll timer.
+- */
+ static int __ap_poll_all(struct ap_device *ap_dev, unsigned long *flags)
+ {
+ spin_lock(&ap_dev->lock);
+@@ -1126,6 +1159,14 @@ static int __ap_poll_all(struct ap_device *ap_dev, unsigned long *flags)
+ return 0;
+ }
+
++/**
++ * ap_poll_all(): Poll all AP devices.
++ * @dummy: Unused variable
++ *
++ * Poll all AP devices on the bus in a round robin fashion. Continue
++ * polling until bit 2^0 of the control flags is not set. If bit 2^1
++ * of the control flags has been set arm the poll timer.
++ */
+ static void ap_poll_all(unsigned long dummy)
+ {
+ unsigned long flags;
+@@ -1144,6 +1185,9 @@ static void ap_poll_all(unsigned long dummy)
+ }
+
+ /**
++ * ap_poll_thread(): Thread that polls for finished requests.
++ * @data: Unused pointer
++ *
+ * AP bus poll thread. The purpose of this thread is to poll for
+ * finished requests in a loop if there is a "free" cpu - that is
+ * a cpu that doesn't have anything better to do. The polling stops
+@@ -1213,7 +1257,10 @@ static void ap_poll_thread_stop(void)
+ }
+
+ /**
+- * Handling of request timeouts
++ * ap_request_timeout(): Handling of request timeouts
++ * @data: Holds the AP device.
++ *
++ * Handles request timeouts.
+ */
+ static void ap_request_timeout(unsigned long data)
+ {
+@@ -1246,7 +1293,9 @@ static struct reset_call ap_reset_call = {
+ };
+
+ /**
+- * The module initialization code.
++ * ap_module_init(): The module initialization code.
++ *
++ * Initializes the module.
+ */
+ int __init ap_module_init(void)
+ {
+@@ -1288,7 +1337,7 @@ int __init ap_module_init(void)
+ if (ap_select_domain() == 0)
+ ap_scan_bus(NULL);
+
+- /* Setup the ap bus rescan timer. */
++ /* Setup the AP bus rescan timer. */
+ init_timer(&ap_config_timer);
+ ap_config_timer.function = ap_config_timeout;
+ ap_config_timer.data = 0;
+@@ -1325,7 +1374,9 @@ static int __ap_match_all(struct device *dev, void *data)
+ }
+
+ /**
+- * The module termination code
++ * ap_modules_exit(): The module termination code
++ *
++ * Terminates the module.
+ */
+ void ap_module_exit(void)
+ {
+diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
+index 87c2d64..c1e1200 100644
+--- a/drivers/s390/crypto/ap_bus.h
++++ b/drivers/s390/crypto/ap_bus.h
+@@ -50,6 +50,15 @@ typedef unsigned int ap_qid_t;
+ #define AP_QID_QUEUE(_qid) ((_qid) & 15)
+
+ /**
++ * structy ap_queue_status - Holds the AP queue status.
++ * @queue_empty: Shows if queue is empty
++ * @replies_waiting: Waiting replies
++ * @queue_full: Is 1 if the queue is full
++ * @pad: A 4 bit pad
++ * @int_enabled: Shows if interrupts are enabled for the AP
++ * @response_conde: Holds the 8 bit response code
++ * @pad2: A 16 bit pad
++ *
+ * The ap queue status word is returned by all three AP functions
+ * (PQAP, NQAP and DQAP). There's a set of flags in the first
+ * byte, followed by a 1 byte response code.
+@@ -75,7 +84,7 @@ struct ap_queue_status {
+ #define AP_RESPONSE_NO_FIRST_PART 0x13
+ #define AP_RESPONSE_MESSAGE_TOO_BIG 0x15
+
+-/**
++/*
+ * Known device types
+ */
+ #define AP_DEVICE_TYPE_PCICC 3
+@@ -84,7 +93,7 @@ struct ap_queue_status {
+ #define AP_DEVICE_TYPE_CEX2A 6
+ #define AP_DEVICE_TYPE_CEX2C 7
+
+-/**
++/*
+ * AP reset flag states
+ */
+ #define AP_RESET_IGNORE 0 /* request timeout will be ignored */
+@@ -152,7 +161,7 @@ struct ap_message {
+ .dev_type=(dt), \
+ .match_flags=AP_DEVICE_ID_MATCH_DEVICE_TYPE,
+
+-/**
++/*
+ * Note: don't use ap_send/ap_recv after using ap_queue_message
+ * for the first time. Otherwise the ap message queue will get
+ * confused.
+diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
+index e3625a4..4d36e80 100644
+--- a/drivers/s390/crypto/zcrypt_api.c
++++ b/drivers/s390/crypto/zcrypt_api.c
+@@ -36,10 +36,11 @@
+ #include <linux/compat.h>
+ #include <asm/atomic.h>
+ #include <asm/uaccess.h>
++#include <linux/hw_random.h>
+
+ #include "zcrypt_api.h"
+
+-/**
++/*
+ * Module description.
+ */
+ MODULE_AUTHOR("IBM Corporation");
+@@ -52,7 +53,10 @@ static LIST_HEAD(zcrypt_device_list);
+ static int zcrypt_device_count = 0;
+ static atomic_t zcrypt_open_count = ATOMIC_INIT(0);
+
+-/**
++static int zcrypt_rng_device_add(void);
++static void zcrypt_rng_device_remove(void);
++
++/*
+ * Device attributes common for all crypto devices.
+ */
+ static ssize_t zcrypt_type_show(struct device *dev,
+@@ -99,6 +103,9 @@ static struct attribute_group zcrypt_device_attr_group = {
+ };
+
+ /**
++ * __zcrypt_increase_preference(): Increase preference of a crypto device.
++ * @zdev: Pointer the crypto device
++ *
+ * Move the device towards the head of the device list.
+ * Need to be called while holding the zcrypt device list lock.
+ * Note: cards with speed_rating of 0 are kept at the end of the list.
+@@ -125,6 +132,9 @@ static void __zcrypt_increase_preference(struct zcrypt_device *zdev)
+ }
+
+ /**
++ * __zcrypt_decrease_preference(): Decrease preference of a crypto device.
++ * @zdev: Pointer to a crypto device.
++ *
+ * Move the device towards the tail of the device list.
+ * Need to be called while holding the zcrypt device list lock.
+ * Note: cards with speed_rating of 0 are kept at the end of the list.
+@@ -198,7 +208,10 @@ void zcrypt_device_free(struct zcrypt_device *zdev)
+ EXPORT_SYMBOL(zcrypt_device_free);
+
+ /**
+- * Register a crypto device.
++ * zcrypt_device_register() - Register a crypto device.
++ * @zdev: Pointer to a crypto device
++ *
++ * Register a crypto device. Returns 0 if successful.
+ */
+ int zcrypt_device_register(struct zcrypt_device *zdev)
+ {
+@@ -216,16 +229,37 @@ int zcrypt_device_register(struct zcrypt_device *zdev)
+ __zcrypt_increase_preference(zdev);
+ zcrypt_device_count++;
+ spin_unlock_bh(&zcrypt_device_lock);
++ if (zdev->ops->rng) {
++ rc = zcrypt_rng_device_add();
++ if (rc)
++ goto out_unregister;
++ }
++ return 0;
++
++out_unregister:
++ spin_lock_bh(&zcrypt_device_lock);
++ zcrypt_device_count--;
++ list_del_init(&zdev->list);
++ spin_unlock_bh(&zcrypt_device_lock);
++ sysfs_remove_group(&zdev->ap_dev->device.kobj,
++ &zcrypt_device_attr_group);
++ put_device(&zdev->ap_dev->device);
++ zcrypt_device_put(zdev);
+ out:
+ return rc;
+ }
+ EXPORT_SYMBOL(zcrypt_device_register);
+
+ /**
++ * zcrypt_device_unregister(): Unregister a crypto device.
++ * @zdev: Pointer to crypto device
++ *
+ * Unregister a crypto device.
+ */
+ void zcrypt_device_unregister(struct zcrypt_device *zdev)
+ {
++ if (zdev->ops->rng)
++ zcrypt_rng_device_remove();
+ spin_lock_bh(&zcrypt_device_lock);
+ zcrypt_device_count--;
+ list_del_init(&zdev->list);
+@@ -238,7 +272,9 @@ void zcrypt_device_unregister(struct zcrypt_device *zdev)
+ EXPORT_SYMBOL(zcrypt_device_unregister);
+
+ /**
+- * zcrypt_read is not be supported beyond zcrypt 1.3.1
++ * zcrypt_read (): Not supported beyond zcrypt 1.3.1.
++ *
++ * This function is not supported beyond zcrypt 1.3.1.
+ */
+ static ssize_t zcrypt_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *f_pos)
+@@ -247,6 +283,8 @@ static ssize_t zcrypt_read(struct file *filp, char __user *buf,
+ }
+
+ /**
++ * zcrypt_write(): Not allowed.
++ *
+ * Write is is not allowed
+ */
+ static ssize_t zcrypt_write(struct file *filp, const char __user *buf,
+@@ -256,7 +294,9 @@ static ssize_t zcrypt_write(struct file *filp, const char __user *buf,
+ }
+
+ /**
+- * Device open/close functions to count number of users.
++ * zcrypt_open(): Count number of users.
++ *
++ * Device open function to count number of users.
+ */
+ static int zcrypt_open(struct inode *inode, struct file *filp)
+ {
+@@ -264,13 +304,18 @@ static int zcrypt_open(struct inode *inode, struct file *filp)
+ return 0;
+ }
+
++/**
++ * zcrypt_release(): Count number of users.
++ *
++ * Device close function to count number of users.
++ */
+ static int zcrypt_release(struct inode *inode, struct file *filp)
+ {
+ atomic_dec(&zcrypt_open_count);
+ return 0;
+ }
+
+-/**
++/*
+ * zcrypt ioctls.
+ */
+ static long zcrypt_rsa_modexpo(struct ica_rsa_modexpo *mex)
+@@ -280,7 +325,7 @@ static long zcrypt_rsa_modexpo(struct ica_rsa_modexpo *mex)
+
+ if (mex->outputdatalength < mex->inputdatalength)
+ return -EINVAL;
+- /**
++ /*
+ * As long as outputdatalength is big enough, we can set the
+ * outputdatalength equal to the inputdatalength, since that is the
+ * number of bytes we will copy in any case
+@@ -326,7 +371,7 @@ static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt)
+ if (crt->outputdatalength < crt->inputdatalength ||
+ (crt->inputdatalength & 1))
+ return -EINVAL;
+- /**
++ /*
+ * As long as outputdatalength is big enough, we can set the
+ * outputdatalength equal to the inputdatalength, since that is the
+ * number of bytes we will copy in any case
+@@ -343,7 +388,7 @@ static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt)
+ zdev->max_mod_size < crt->inputdatalength)
+ continue;
+ if (zdev->short_crt && crt->inputdatalength > 240) {
+- /**
++ /*
+ * Check inputdata for leading zeros for cards
+ * that can't handle np_prime, bp_key, or
+ * u_mult_inv > 128 bytes.
+@@ -359,7 +404,7 @@ static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt)
+ copy_from_user(&z3, crt->u_mult_inv, len))
+ return -EFAULT;
+ copied = 1;
+- /**
++ /*
+ * We have to restart device lookup -
+ * the device list may have changed by now.
+ */
+@@ -427,6 +472,37 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB)
+ return -ENODEV;
+ }
+
++static long zcrypt_rng(char *buffer)
++{
++ struct zcrypt_device *zdev;
++ int rc;
++
++ spin_lock_bh(&zcrypt_device_lock);
++ list_for_each_entry(zdev, &zcrypt_device_list, list) {
++ if (!zdev->online || !zdev->ops->rng)
++ continue;
++ zcrypt_device_get(zdev);
++ get_device(&zdev->ap_dev->device);
++ zdev->request_count++;
++ __zcrypt_decrease_preference(zdev);
++ if (try_module_get(zdev->ap_dev->drv->driver.owner)) {
++ spin_unlock_bh(&zcrypt_device_lock);
++ rc = zdev->ops->rng(zdev, buffer);
++ spin_lock_bh(&zcrypt_device_lock);
++ module_put(zdev->ap_dev->drv->driver.owner);
++ } else
++ rc = -EAGAIN;
++ zdev->request_count--;
++ __zcrypt_increase_preference(zdev);
++ put_device(&zdev->ap_dev->device);
++ zcrypt_device_put(zdev);
++ spin_unlock_bh(&zcrypt_device_lock);
++ return rc;
++ }
++ spin_unlock_bh(&zcrypt_device_lock);
++ return -ENODEV;
++}
++
+ static void zcrypt_status_mask(char status[AP_DEVICES])
+ {
+ struct zcrypt_device *zdev;
+@@ -514,6 +590,8 @@ static int zcrypt_count_type(int type)
+ }
+
+ /**
++ * zcrypt_ica_status(): Old, depracted combi status call.
++ *
+ * Old, deprecated combi status call.
+ */
+ static long zcrypt_ica_status(struct file *filp, unsigned long arg)
+@@ -615,7 +693,7 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
+ (int __user *) arg);
+ case Z90STAT_DOMAIN_INDEX:
+ return put_user(ap_domain_index, (int __user *) arg);
+- /**
++ /*
+ * Deprecated ioctls. Don't add another device count ioctl,
+ * you can count them yourself in the user space with the
+ * output of the Z90STAT_STATUS_MASK ioctl.
+@@ -653,7 +731,7 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
+ }
+
+ #ifdef CONFIG_COMPAT
+-/**
++/*
+ * ioctl32 conversion routines
+ */
+ struct compat_ica_rsa_modexpo {
+@@ -804,7 +882,7 @@ static long zcrypt_compat_ioctl(struct file *filp, unsigned int cmd,
+ }
+ #endif
+
+-/**
++/*
+ * Misc device file operations.
+ */
+ static const struct file_operations zcrypt_fops = {
+@@ -819,7 +897,7 @@ static const struct file_operations zcrypt_fops = {
+ .release = zcrypt_release
+ };
+
+-/**
++/*
+ * Misc device.
+ */
+ static struct miscdevice zcrypt_misc_device = {
+@@ -828,7 +906,7 @@ static struct miscdevice zcrypt_misc_device = {
+ .fops = &zcrypt_fops,
+ };
+
+-/**
++/*
+ * Deprecated /proc entry support.
+ */
+ static struct proc_dir_entry *zcrypt_entry;
+@@ -1022,7 +1100,7 @@ static int zcrypt_status_write(struct file *file, const char __user *buffer,
+ }
+
+ for (j = 0; j < 64 && *ptr; ptr++) {
+- /**
++ /*
+ * '0' for no device, '1' for PCICA, '2' for PCICC,
+ * '3' for PCIXCC_MCL2, '4' for PCIXCC_MCL3,
+ * '5' for CEX2C and '6' for CEX2A'
+@@ -1041,7 +1119,76 @@ out:
+ return count;
+ }
+
++static int zcrypt_rng_device_count;
++static u32 *zcrypt_rng_buffer;
++static int zcrypt_rng_buffer_index;
++static DEFINE_MUTEX(zcrypt_rng_mutex);
++
++static int zcrypt_rng_data_read(struct hwrng *rng, u32 *data)
++{
++ int rc;
++
++ /*
++ * We don't need locking here because the RNG API guarantees serialized
++ * read method calls.
++ */
++ if (zcrypt_rng_buffer_index == 0) {
++ rc = zcrypt_rng((char *) zcrypt_rng_buffer);
++ if (rc < 0)
++ return -EIO;
++ zcrypt_rng_buffer_index = rc / sizeof *data;
++ }
++ *data = zcrypt_rng_buffer[--zcrypt_rng_buffer_index];
++ return sizeof *data;
++}
++
++static struct hwrng zcrypt_rng_dev = {
++ .name = "zcrypt",
++ .data_read = zcrypt_rng_data_read,
++};
++
++static int zcrypt_rng_device_add(void)
++{
++ int rc = 0;
++
++ mutex_lock(&zcrypt_rng_mutex);
++ if (zcrypt_rng_device_count == 0) {
++ zcrypt_rng_buffer = (u32 *) get_zeroed_page(GFP_KERNEL);
++ if (!zcrypt_rng_buffer) {
++ rc = -ENOMEM;
++ goto out;
++ }
++ zcrypt_rng_buffer_index = 0;
++ rc = hwrng_register(&zcrypt_rng_dev);
++ if (rc)
++ goto out_free;
++ zcrypt_rng_device_count = 1;
++ } else
++ zcrypt_rng_device_count++;
++ mutex_unlock(&zcrypt_rng_mutex);
++ return 0;
++
++out_free:
++ free_page((unsigned long) zcrypt_rng_buffer);
++out:
++ mutex_unlock(&zcrypt_rng_mutex);
++ return rc;
++}
++
++static void zcrypt_rng_device_remove(void)
++{
++ mutex_lock(&zcrypt_rng_mutex);
++ zcrypt_rng_device_count--;
++ if (zcrypt_rng_device_count == 0) {
++ hwrng_unregister(&zcrypt_rng_dev);
++ free_page((unsigned long) zcrypt_rng_buffer);
++ }
++ mutex_unlock(&zcrypt_rng_mutex);
++}
++
+ /**
++ * zcrypt_api_init(): Module initialization.
++ *
+ * The module initialization code.
+ */
+ int __init zcrypt_api_init(void)
+@@ -1076,6 +1223,8 @@ out:
+ }
+
+ /**
++ * zcrypt_api_exit(): Module termination.
++ *
+ * The module termination code.
+ */
+ void zcrypt_api_exit(void)
+diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h
+index de4877e..5c6e222 100644
+--- a/drivers/s390/crypto/zcrypt_api.h
++++ b/drivers/s390/crypto/zcrypt_api.h
+@@ -43,17 +43,17 @@
+ #define DEV_NAME "zcrypt"
+
+ #define PRINTK(fmt, args...) \
+- printk(KERN_DEBUG DEV_NAME ": %s -> " fmt, __FUNCTION__ , ## args)
++ printk(KERN_DEBUG DEV_NAME ": %s -> " fmt, __func__ , ## args)
+ #define PRINTKN(fmt, args...) \
+ printk(KERN_DEBUG DEV_NAME ": " fmt, ## args)
+ #define PRINTKW(fmt, args...) \
+- printk(KERN_WARNING DEV_NAME ": %s -> " fmt, __FUNCTION__ , ## args)
++ printk(KERN_WARNING DEV_NAME ": %s -> " fmt, __func__ , ## args)
+ #define PRINTKC(fmt, args...) \
+- printk(KERN_CRIT DEV_NAME ": %s -> " fmt, __FUNCTION__ , ## args)
++ printk(KERN_CRIT DEV_NAME ": %s -> " fmt, __func__ , ## args)
+
+ #ifdef ZCRYPT_DEBUG
+ #define PDEBUG(fmt, args...) \
+- printk(KERN_DEBUG DEV_NAME ": %s -> " fmt, __FUNCTION__ , ## args)
++ printk(KERN_DEBUG DEV_NAME ": %s -> " fmt, __func__ , ## args)
+ #else
+ #define PDEBUG(fmt, args...) do {} while (0)
+ #endif
+@@ -100,6 +100,13 @@ struct ica_z90_status {
+ #define ZCRYPT_CEX2C 5
+ #define ZCRYPT_CEX2A 6
+
++/**
++ * Large random numbers are pulled in 4096 byte chunks from the crypto cards
++ * and stored in a page. Be carefull when increasing this buffer due to size
++ * limitations for AP requests.
++ */
++#define ZCRYPT_RNG_BUFFER_SIZE 4096
++
+ struct zcrypt_device;
+
+ struct zcrypt_ops {
+@@ -107,6 +114,7 @@ struct zcrypt_ops {
+ long (*rsa_modexpo_crt)(struct zcrypt_device *,
+ struct ica_rsa_modexpo_crt *);
+ long (*send_cprb)(struct zcrypt_device *, struct ica_xcRB *);
++ long (*rng)(struct zcrypt_device *, char *);
+ };
+
+ struct zcrypt_device {
+diff --git a/drivers/s390/crypto/zcrypt_cca_key.h b/drivers/s390/crypto/zcrypt_cca_key.h
+index 8dbcf0e..ed82f2f 100644
+--- a/drivers/s390/crypto/zcrypt_cca_key.h
++++ b/drivers/s390/crypto/zcrypt_cca_key.h
+@@ -174,7 +174,7 @@ static inline int zcrypt_type6_mex_key_de(struct ica_rsa_modexpo *mex,
+ key->pvtMeHdr = static_pvt_me_hdr;
+ key->pvtMeSec = static_pvt_me_sec;
+ key->pubMeSec = static_pub_me_sec;
+- /**
++ /*
+ * In a private key, the modulus doesn't appear in the public
+ * section. So, an arbitrary public exponent of 0x010001 will be
+ * used.
+@@ -338,7 +338,7 @@ static inline int zcrypt_type6_crt_key(struct ica_rsa_modexpo_crt *crt,
+ pub = (struct cca_public_sec *)(key->key_parts + key_len);
+ *pub = static_cca_pub_sec;
+ pub->modulus_bit_len = 8 * crt->inputdatalength;
+- /**
++ /*
+ * In a private key, the modulus doesn't appear in the public
+ * section. So, an arbitrary public exponent of 0x010001 will be
+ * used.
+diff --git a/drivers/s390/crypto/zcrypt_error.h b/drivers/s390/crypto/zcrypt_error.h
+index 2cb616b..3e27fe7 100644
+--- a/drivers/s390/crypto/zcrypt_error.h
++++ b/drivers/s390/crypto/zcrypt_error.h
+@@ -108,7 +108,7 @@ static inline int convert_error(struct zcrypt_device *zdev,
+ return -EINVAL;
+ case REP82_ERROR_MESSAGE_TYPE:
+ // REP88_ERROR_MESSAGE_TYPE // '20' CEX2A
+- /**
++ /*
+ * To sent a message of the wrong type is a bug in the
+ * device driver. Warn about it, disable the device
+ * and then repeat the request.
+diff --git a/drivers/s390/crypto/zcrypt_pcicc.c b/drivers/s390/crypto/zcrypt_pcicc.c
+index d6d59bf..17ea56c 100644
+--- a/drivers/s390/crypto/zcrypt_pcicc.c
++++ b/drivers/s390/crypto/zcrypt_pcicc.c
+@@ -42,7 +42,7 @@
+ #define PCICC_MAX_MOD_SIZE_OLD 128 /* 1024 bits */
+ #define PCICC_MAX_MOD_SIZE 256 /* 2048 bits */
+
+-/**
++/*
+ * PCICC cards need a speed rating of 0. This keeps them at the end of
+ * the zcrypt device list (see zcrypt_api.c). PCICC cards are only
+ * used if no other cards are present because they are slow and can only
+@@ -388,7 +388,7 @@ static int convert_type86(struct zcrypt_device *zdev,
+ reply_len = le16_to_cpu(msg->length) - 2;
+ if (reply_len > outputdatalength)
+ return -EINVAL;
+- /**
++ /*
+ * For all encipher requests, the length of the ciphertext (reply_len)
+ * will always equal the modulus length. For MEX decipher requests
+ * the output needs to get padded. Minimum pad size is 10.
+diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c
+index 70b9ddc..0bc9b31 100644
+--- a/drivers/s390/crypto/zcrypt_pcixcc.c
++++ b/drivers/s390/crypto/zcrypt_pcixcc.c
+@@ -356,6 +356,55 @@ static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
+ }
+
+ /**
++ * Prepare a type6 CPRB message for random number generation
++ *
++ * @ap_dev: AP device pointer
++ * @ap_msg: pointer to AP message
++ */
++static void rng_type6CPRB_msgX(struct ap_device *ap_dev,
++ struct ap_message *ap_msg,
++ unsigned random_number_length)
++{
++ struct {
++ struct type6_hdr hdr;
++ struct CPRBX cprbx;
++ char function_code[2];
++ short int rule_length;
++ char rule[8];
++ short int verb_length;
++ short int key_length;
++ } __attribute__((packed)) *msg = ap_msg->message;
++ static struct type6_hdr static_type6_hdrX = {
++ .type = 0x06,
++ .offset1 = 0x00000058,
++ .agent_id = {'C', 'A'},
++ .function_code = {'R', 'L'},
++ .ToCardLen1 = sizeof *msg - sizeof(msg->hdr),
++ .FromCardLen1 = sizeof *msg - sizeof(msg->hdr),
++ };
++ static struct CPRBX static_cprbx = {
++ .cprb_len = 0x00dc,
++ .cprb_ver_id = 0x02,
++ .func_id = {0x54, 0x32},
++ .req_parml = sizeof *msg - sizeof(msg->hdr) -
++ sizeof(msg->cprbx),
++ .rpl_msgbl = sizeof *msg - sizeof(msg->hdr),
++ };
++
++ msg->hdr = static_type6_hdrX;
++ msg->hdr.FromCardLen2 = random_number_length,
++ msg->cprbx = static_cprbx;
++ msg->cprbx.rpl_datal = random_number_length,
++ msg->cprbx.domain = AP_QID_QUEUE(ap_dev->qid);
++ memcpy(msg->function_code, msg->hdr.function_code, 0x02);
++ msg->rule_length = 0x0a;
++ memcpy(msg->rule, "RANDOM ", 8);
++ msg->verb_length = 0x02;
++ msg->key_length = 0x02;
++ ap_msg->length = sizeof *msg;
++}
++
++/**
+ * Copy results from a type 86 ICA reply message back to user space.
+ *
+ * @zdev: crypto device pointer
+@@ -452,7 +501,7 @@ static int convert_type86_ica(struct zcrypt_device *zdev,
+ reply_len = msg->length - 2;
+ if (reply_len > outputdatalength)
+ return -EINVAL;
+- /**
++ /*
+ * For all encipher requests, the length of the ciphertext (reply_len)
+ * will always equal the modulus length. For MEX decipher requests
+ * the output needs to get padded. Minimum pad size is 10.
+@@ -509,6 +558,26 @@ static int convert_type86_xcrb(struct zcrypt_device *zdev,
+ return 0;
+ }
+
++static int convert_type86_rng(struct zcrypt_device *zdev,
++ struct ap_message *reply,
++ char *buffer)
++{
++ struct {
++ struct type86_hdr hdr;
++ struct type86_fmt2_ext fmt2;
++ struct CPRBX cprbx;
++ } __attribute__((packed)) *msg = reply->message;
++ char *data = reply->message;
++
++ if (msg->cprbx.ccp_rtcode != 0 || msg->cprbx.ccp_rscode != 0) {
++ PDEBUG("RNG response error on PCIXCC/CEX2C rc=%hu/rs=%hu\n",
++ rc, rs);
++ return -EINVAL;
++ }
++ memcpy(buffer, data + msg->fmt2.offset2, msg->fmt2.count2);
++ return msg->fmt2.count2;
++}
++
+ static int convert_response_ica(struct zcrypt_device *zdev,
+ struct ap_message *reply,
+ char __user *outputdata,
+@@ -567,6 +636,31 @@ static int convert_response_xcrb(struct zcrypt_device *zdev,
+ }
+ }
+
++static int convert_response_rng(struct zcrypt_device *zdev,
++ struct ap_message *reply,
++ char *data)
++{
++ struct type86x_reply *msg = reply->message;
++
++ switch (msg->hdr.type) {
++ case TYPE82_RSP_CODE:
++ case TYPE88_RSP_CODE:
++ return -EINVAL;
++ case TYPE86_RSP_CODE:
++ if (msg->hdr.reply_code)
++ return -EINVAL;
++ if (msg->cprbx.cprb_ver_id == 0x02)
++ return convert_type86_rng(zdev, reply, data);
++ /* no break, incorrect cprb version is an unknown response */
++ default: /* Unknown response type, this should NEVER EVER happen */
++ PRINTK("Unrecognized Message Header: %08x%08x\n",
++ *(unsigned int *) reply->message,
++ *(unsigned int *) (reply->message+4));
++ zdev->online = 0;
++ return -EAGAIN; /* repeat the request on a different device. */
++ }
++}
++
+ /**
+ * This function is called from the AP bus code after a crypto request
+ * "msg" has finished with the reply message "reply".
+@@ -736,6 +830,42 @@ out_free:
+ }
+
+ /**
++ * The request distributor calls this function if it picked the PCIXCC/CEX2C
++ * device to generate random data.
++ * @zdev: pointer to zcrypt_device structure that identifies the
++ * PCIXCC/CEX2C device to the request distributor
++ * @buffer: pointer to a memory page to return random data
++ */
++
++static long zcrypt_pcixcc_rng(struct zcrypt_device *zdev,
++ char *buffer)
++{
++ struct ap_message ap_msg;
++ struct response_type resp_type = {
++ .type = PCIXCC_RESPONSE_TYPE_XCRB,
++ };
++ int rc;
++
++ ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
++ if (!ap_msg.message)
++ return -ENOMEM;
++ ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
++ atomic_inc_return(&zcrypt_step);
++ ap_msg.private = &resp_type;
++ rng_type6CPRB_msgX(zdev->ap_dev, &ap_msg, ZCRYPT_RNG_BUFFER_SIZE);
++ init_completion(&resp_type.work);
++ ap_queue_message(zdev->ap_dev, &ap_msg);
++ rc = wait_for_completion_interruptible(&resp_type.work);
++ if (rc == 0)
++ rc = convert_response_rng(zdev, &ap_msg, buffer);
++ else
++ /* Signal pending. */
++ ap_cancel_message(zdev->ap_dev, &ap_msg);
++ kfree(ap_msg.message);
++ return rc;
++}
++
++/**
+ * The crypto operations for a PCIXCC/CEX2C card.
+ */
+ static struct zcrypt_ops zcrypt_pcixcc_ops = {
+@@ -744,6 +874,13 @@ static struct zcrypt_ops zcrypt_pcixcc_ops = {
+ .send_cprb = zcrypt_pcixcc_send_cprb,
+ };
+
++static struct zcrypt_ops zcrypt_pcixcc_with_rng_ops = {
++ .rsa_modexpo = zcrypt_pcixcc_modexpo,
++ .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt,
++ .send_cprb = zcrypt_pcixcc_send_cprb,
++ .rng = zcrypt_pcixcc_rng,
++};
++
+ /**
+ * Micro-code detection function. Its sends a message to a pcixcc card
+ * to find out the microcode level.
+@@ -859,6 +996,58 @@ out_free:
+ }
+
+ /**
++ * Large random number detection function. Its sends a message to a pcixcc
++ * card to find out if large random numbers are supported.
++ * @ap_dev: pointer to the AP device.
++ *
++ * Returns 1 if large random numbers are supported, 0 if not and < 0 on error.
++ */
++static int zcrypt_pcixcc_rng_supported(struct ap_device *ap_dev)
++{
++ struct ap_message ap_msg;
++ unsigned long long psmid;
++ struct {
++ struct type86_hdr hdr;
++ struct type86_fmt2_ext fmt2;
++ struct CPRBX cprbx;
++ } __attribute__((packed)) *reply;
++ int rc, i;
++
++ ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
++ if (!ap_msg.message)
++ return -ENOMEM;
++
++ rng_type6CPRB_msgX(ap_dev, &ap_msg, 4);
++ rc = ap_send(ap_dev->qid, 0x0102030405060708ULL, ap_msg.message,
++ ap_msg.length);
++ if (rc)
++ goto out_free;
++
++ /* Wait for the test message to complete. */
++ for (i = 0; i < 2 * HZ; i++) {
++ msleep(1000 / HZ);
++ rc = ap_recv(ap_dev->qid, &psmid, ap_msg.message, 4096);
++ if (rc == 0 && psmid == 0x0102030405060708ULL)
++ break;
++ }
++
++ if (i >= 2 * HZ) {
++ /* Got no answer. */
++ rc = -ENODEV;
++ goto out_free;
++ }
++
++ reply = ap_msg.message;
++ if (reply->cprbx.ccp_rtcode == 0 && reply->cprbx.ccp_rscode == 0)
++ rc = 1;
++ else
++ rc = 0;
++out_free:
++ free_page((unsigned long) ap_msg.message);
++ return rc;
++}
++
++/**
+ * Probe function for PCIXCC/CEX2C cards. It always accepts the AP device
+ * since the bus_match already checked the hardware type. The PCIXCC
+ * cards come in two flavours: micro code level 2 and micro code level 3.
+@@ -874,7 +1063,6 @@ static int zcrypt_pcixcc_probe(struct ap_device *ap_dev)
+ if (!zdev)
+ return -ENOMEM;
+ zdev->ap_dev = ap_dev;
+- zdev->ops = &zcrypt_pcixcc_ops;
+ zdev->online = 1;
+ if (ap_dev->device_type == AP_DEVICE_TYPE_PCIXCC) {
+ rc = zcrypt_pcixcc_mcl(ap_dev);
+@@ -901,6 +1089,15 @@ static int zcrypt_pcixcc_probe(struct ap_device *ap_dev)
+ zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
+ zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
+ }
++ rc = zcrypt_pcixcc_rng_supported(ap_dev);
++ if (rc < 0) {
++ zcrypt_device_free(zdev);
++ return rc;
++ }
++ if (rc)
++ zdev->ops = &zcrypt_pcixcc_with_rng_ops;
++ else
++ zdev->ops = &zcrypt_pcixcc_ops;
+ ap_dev->reply = &zdev->reply;
+ ap_dev->private = zdev;
+ rc = zcrypt_device_register(zdev);
+diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig
+index eada69d..a7745c8 100644
+--- a/drivers/s390/net/Kconfig
++++ b/drivers/s390/net/Kconfig
+@@ -5,22 +5,25 @@ config LCS
+ tristate "Lan Channel Station Interface"
+ depends on CCW && NETDEVICES && (NET_ETHERNET || TR || FDDI)
+ help
+- Select this option if you want to use LCS networking on IBM S/390
+- or zSeries. This device driver supports Token Ring (IEEE 802.5),
+- FDDI (IEEE 802.7) and Ethernet.
+- This option is also available as a module which will be
+- called lcs.ko. If you do not know what it is, it's safe to say "Y".
++ Select this option if you want to use LCS networking on IBM System z.
++ This device driver supports Token Ring (IEEE 802.5),
++ FDDI (IEEE 802.7) and Ethernet.
++ To compile as a module, choose M. The module name is lcs.ko.
++ If you do not know what it is, it's safe to choose Y.
+
+-config CTC
+- tristate "CTC device support"
++config CTCM
++ tristate "CTC and MPC SNA device support"
+ depends on CCW && NETDEVICES
+ help
+- Select this option if you want to use channel-to-channel networking
+- on IBM S/390 or zSeries. This device driver supports real CTC
+- coupling using ESCON. It also supports virtual CTCs when running
+- under VM. It will use the channel device configuration if this is
+- available. This option is also available as a module which will be
+- called ctc.ko. If you do not know what it is, it's safe to say "Y".
++ Select this option if you want to use channel-to-channel
++ point-to-point networking on IBM System z.
++ This device driver supports real CTC coupling using ESCON.
++ It also supports virtual CTCs when running under VM.
++ This driver also supports channel-to-channel MPC SNA devices.
++ MPC is an SNA protocol device used by Communication Server for Linux.
++ To compile as a module, choose M. The module name is ctcm.ko.
++ To compile into the kernel, choose Y.
++ If you do not need any channel-to-channel connection, choose N.
+
+ config NETIUCV
+ tristate "IUCV network device support (VM only)"
+@@ -29,9 +32,9 @@ config NETIUCV
+ Select this option if you want to use inter-user communication
+ vehicle networking under VM or VIF. It enables a fast communication
+ link between VM guests. Using ifconfig a point-to-point connection
+- can be established to the Linux for zSeries and S7390 system
+- running on the other VM guest. This option is also available
+- as a module which will be called netiucv.ko. If unsure, say "Y".
++ can be established to the Linux on IBM System z
++ running on the other VM guest. To compile as a module, choose M.
++ The module name is netiucv.ko. If unsure, choose Y.
+
+ config SMSGIUCV
+ tristate "IUCV special message support (VM only)"
+@@ -47,43 +50,46 @@ config CLAW
+ This driver supports channel attached CLAW devices.
+ CLAW is Common Link Access for Workstation. Common devices
+ that use CLAW are RS/6000s, Cisco Routers (CIP) and 3172 devices.
+- To compile as a module choose M here: The module will be called
+- claw.ko to compile into the kernel choose Y
++ To compile as a module, choose M. The module name is claw.ko.
++ To compile into the kernel, choose Y.
+
+ config QETH
+ tristate "Gigabit Ethernet device support"
+ depends on CCW && NETDEVICES && IP_MULTICAST && QDIO
+ help
+- This driver supports the IBM S/390 and zSeries OSA Express adapters
++ This driver supports the IBM System z OSA Express adapters
+ in QDIO mode (all media types), HiperSockets interfaces and VM GuestLAN
+ interfaces in QDIO and HIPER mode.
+
+- For details please refer to the documentation provided by IBM at
+- <http://www10.software.ibm.com/developerworks/opensource/linux390>
++ For details please refer to the documentation provided by IBM at
++ <http://www.ibm.com/developerworks/linux/linux390>
+
+- To compile this driver as a module, choose M here: the
+- module will be called qeth.ko.
++ To compile this driver as a module, choose M.
++ The module name is qeth.ko.
+
++config QETH_L2
++ tristate "qeth layer 2 device support"
++ depends on QETH
++ help
++ Select this option to be able to run qeth devices in layer 2 mode.
++ To compile as a module, choose M. The module name is qeth_l2.ko.
++ If unsure, choose y.
+
+-comment "Gigabit Ethernet default settings"
+- depends on QETH
++config QETH_L3
++ tristate "qeth layer 3 device support"
++ depends on QETH
++ help
++ Select this option to be able to run qeth devices in layer 3 mode.
++ To compile as a module choose M. The module name is qeth_l3.ko.
++ If unsure, choose Y.
+
+ config QETH_IPV6
+- bool "IPv6 support for gigabit ethernet"
+- depends on (QETH = IPV6) || (QETH && IPV6 = 'y')
+- help
+- If CONFIG_QETH is switched on, this option will include IPv6
+- support in the qeth device driver.
+-
+-config QETH_VLAN
+- bool "VLAN support for gigabit ethernet"
+- depends on (QETH = VLAN_8021Q) || (QETH && VLAN_8021Q = 'y')
+- help
+- If CONFIG_QETH is switched on, this option will include IEEE
+- 802.1q VLAN support in the qeth device driver.
++ bool
++ depends on (QETH_L3 = IPV6) || (QETH_L3 && IPV6 = 'y')
++ default y
+
+ config CCWGROUP
+- tristate
+- default (LCS || CTC || QETH)
++ tristate
++ default (LCS || CTCM || QETH)
+
+ endmenu
+diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile
+index bbe3ab2..6382c04 100644
+--- a/drivers/s390/net/Makefile
++++ b/drivers/s390/net/Makefile
+@@ -2,13 +2,15 @@
+ # S/390 network devices
+ #
+
+-ctc-objs := ctcmain.o ctcdbug.o
+-
++ctcm-y += ctcm_main.o ctcm_fsms.o ctcm_mpc.o ctcm_sysfs.o ctcm_dbug.o
++obj-$(CONFIG_CTCM) += ctcm.o fsm.o cu3088.o
+ obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
+ obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
+-obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o
+ obj-$(CONFIG_LCS) += lcs.o cu3088.o
+ obj-$(CONFIG_CLAW) += claw.o cu3088.o
+-qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o
+-qeth-$(CONFIG_PROC_FS) += qeth_proc.o
++qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o qeth_core_offl.o
+ obj-$(CONFIG_QETH) += qeth.o
++qeth_l2-y += qeth_l2_main.o
++obj-$(CONFIG_QETH_L2) += qeth_l2.o
++qeth_l3-y += qeth_l3_main.o qeth_l3_sys.o
++obj-$(CONFIG_QETH_L3) += qeth_l3.o
+diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
+index d8a5c22..04a1d7b 100644
+--- a/drivers/s390/net/claw.c
++++ b/drivers/s390/net/claw.c
+@@ -299,7 +299,7 @@ claw_probe(struct ccwgroup_device *cgdev)
+ struct claw_privbk *privptr=NULL;
+
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s Enter\n",__FUNCTION__);
++ printk(KERN_INFO "%s Enter\n",__func__);
+ #endif
+ CLAW_DBF_TEXT(2,setup,"probe");
+ if (!get_device(&cgdev->dev))
+@@ -313,7 +313,7 @@ claw_probe(struct ccwgroup_device *cgdev)
+ probe_error(cgdev);
+ put_device(&cgdev->dev);
+ printk(KERN_WARNING "Out of memory %s %s Exit Line %d \n",
+- cgdev->cdev[0]->dev.bus_id,__FUNCTION__,__LINE__);
++ cgdev->cdev[0]->dev.bus_id,__func__,__LINE__);
+ CLAW_DBF_TEXT_(2,setup,"probex%d",-ENOMEM);
+ return -ENOMEM;
+ }
+@@ -323,7 +323,7 @@ claw_probe(struct ccwgroup_device *cgdev)
+ probe_error(cgdev);
+ put_device(&cgdev->dev);
+ printk(KERN_WARNING "Out of memory %s %s Exit Line %d \n",
+- cgdev->cdev[0]->dev.bus_id,__FUNCTION__,__LINE__);
++ cgdev->cdev[0]->dev.bus_id,__func__,__LINE__);
+ CLAW_DBF_TEXT_(2,setup,"probex%d",-ENOMEM);
+ return -ENOMEM;
+ }
+@@ -340,7 +340,7 @@ claw_probe(struct ccwgroup_device *cgdev)
+ probe_error(cgdev);
+ put_device(&cgdev->dev);
+ printk(KERN_WARNING "add_files failed %s %s Exit Line %d \n",
+- cgdev->cdev[0]->dev.bus_id,__FUNCTION__,__LINE__);
++ cgdev->cdev[0]->dev.bus_id,__func__,__LINE__);
+ CLAW_DBF_TEXT_(2,setup,"probex%d",rc);
+ return rc;
+ }
+@@ -351,7 +351,7 @@ claw_probe(struct ccwgroup_device *cgdev)
+ cgdev->dev.driver_data = privptr;
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "claw:%s exit on line %d, "
+- "rc = 0\n",__FUNCTION__,__LINE__);
++ "rc = 0\n",__func__,__LINE__);
+ #endif
+ CLAW_DBF_TEXT(2,setup,"prbext 0");
+
+@@ -371,7 +371,7 @@ claw_tx(struct sk_buff *skb, struct net_device *dev)
+ struct chbk *p_ch;
+
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s:%s enter\n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s enter\n",dev->name,__func__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"claw_tx");
+ p_ch=&privptr->channel[WRITE];
+@@ -381,7 +381,7 @@ claw_tx(struct sk_buff *skb, struct net_device *dev)
+ privptr->stats.tx_dropped++;
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() exit on line %d, rc = EIO\n",
+- dev->name,__FUNCTION__, __LINE__);
++ dev->name,__func__, __LINE__);
+ #endif
+ CLAW_DBF_TEXT_(2,trace,"clawtx%d",-EIO);
+ return -EIO;
+@@ -398,7 +398,7 @@ claw_tx(struct sk_buff *skb, struct net_device *dev)
+ spin_unlock_irqrestore(get_ccwdev_lock(p_ch->cdev), saveflags);
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s exit on line %d, rc = %d\n",
+- dev->name, __FUNCTION__, __LINE__, rc);
++ dev->name, __func__, __LINE__, rc);
+ #endif
+ CLAW_DBF_TEXT_(4,trace,"clawtx%d",rc);
+ return rc;
+@@ -460,7 +460,7 @@ claw_pack_skb(struct claw_privbk *privptr)
+ #ifdef IOTRACE
+ printk(KERN_INFO "%s: %s() Packed %d len %d\n",
+ p_env->ndev->name,
+- __FUNCTION__,pkt_cnt,new_skb->len);
++ __func__,pkt_cnt,new_skb->len);
+ #endif
+ }
+ CLAW_DBF_TEXT(4,trace,"PackSKBx");
+@@ -478,7 +478,7 @@ claw_change_mtu(struct net_device *dev, int new_mtu)
+ struct claw_privbk *privptr=dev->priv;
+ int buff_size;
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s:%s Enter \n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
+ #endif
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "variable dev =\n");
+@@ -491,14 +491,14 @@ claw_change_mtu(struct net_device *dev, int new_mtu)
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d, rc=EINVAL\n",
+ dev->name,
+- __FUNCTION__, __LINE__);
++ __func__, __LINE__);
+ #endif
+ return -EINVAL;
+ }
+ dev->mtu = new_mtu;
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",dev->name,
+- __FUNCTION__, __LINE__);
++ __func__, __LINE__);
+ #endif
+ return 0;
+ } /* end of claw_change_mtu */
+@@ -522,7 +522,7 @@ claw_open(struct net_device *dev)
+ struct ccwbk *p_buf;
+
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s:%s Enter \n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"open");
+ if (!dev || (dev->name[0] == 0x00)) {
+@@ -537,7 +537,7 @@ claw_open(struct net_device *dev)
+ if (rc) {
+ printk(KERN_INFO "%s:%s Exit on line %d, rc=ENOMEM\n",
+ dev->name,
+- __FUNCTION__, __LINE__);
++ __func__, __LINE__);
+ CLAW_DBF_TEXT(2,trace,"openmem");
+ return -ENOMEM;
+ }
+@@ -661,7 +661,7 @@ claw_open(struct net_device *dev)
+ claw_clear_busy(dev);
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d, rc=EIO\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ CLAW_DBF_TEXT(2,trace,"open EIO");
+ return -EIO;
+@@ -673,7 +673,7 @@ claw_open(struct net_device *dev)
+
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d, rc=0\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"openok");
+ return 0;
+@@ -696,7 +696,7 @@ claw_irq_handler(struct ccw_device *cdev,
+
+
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s enter \n",__FUNCTION__);
++ printk(KERN_INFO "%s enter \n",__func__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"clawirq");
+ /* Bypass all 'unsolicited interrupts' */
+@@ -706,7 +706,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ cdev->dev.bus_id,irb->scsw.cstat, irb->scsw.dstat);
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "claw: %s() "
+- "exit on line %d\n",__FUNCTION__,__LINE__);
++ "exit on line %d\n",__func__,__LINE__);
+ #endif
+ CLAW_DBF_TEXT(2,trace,"badirq");
+ return;
+@@ -752,7 +752,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ #endif
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ CLAW_DBF_TEXT(2,trace,"chanchk");
+ /* return; */
+@@ -777,7 +777,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ return;
+ }
+@@ -788,7 +788,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ #endif
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"stop");
+ return;
+@@ -804,7 +804,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"haltio");
+ return;
+@@ -838,7 +838,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ #endif
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"haltio");
+ return;
+@@ -858,7 +858,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ }
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"notrdy");
+ return;
+@@ -874,7 +874,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ }
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"PCI_read");
+ return;
+@@ -885,7 +885,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"SPend_rd");
+ return;
+@@ -906,7 +906,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ #endif
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"RdIRQXit");
+ return;
+@@ -929,7 +929,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ }
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"rstrtwrt");
+ return;
+@@ -946,7 +946,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"writeUE");
+ return;
+@@ -969,7 +969,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ #endif
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"StWtExit");
+ return;
+@@ -978,7 +978,7 @@ claw_irq_handler(struct ccw_device *cdev,
+ "state=%d\n",dev->name,p_ch->claw_state);
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ CLAW_DBF_TEXT(2,trace,"badIRQ");
+ return;
+@@ -1001,7 +1001,7 @@ claw_irq_tasklet ( unsigned long data )
+ p_ch = (struct chbk *) data;
+ dev = (struct net_device *)p_ch->ndev;
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s:%s Enter \n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
+ #endif
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s: variable p_ch =\n",dev->name);
+@@ -1021,7 +1021,7 @@ claw_irq_tasklet ( unsigned long data )
+ CLAW_DBF_TEXT(4,trace,"TskletXt");
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ return;
+ } /* end of claw_irq_bh */
+@@ -1048,7 +1048,7 @@ claw_release(struct net_device *dev)
+ if (!privptr)
+ return 0;
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s:%s Enter \n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"release");
+ #ifdef DEBUGMSG
+@@ -1090,7 +1090,7 @@ claw_release(struct net_device *dev)
+ if(privptr->buffs_alloc != 1) {
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"none2fre");
+ return 0;
+@@ -1171,7 +1171,7 @@ claw_release(struct net_device *dev)
+ }
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"rlsexit");
+ return 0;
+@@ -1192,7 +1192,7 @@ claw_write_retry ( struct chbk *p_ch )
+
+
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
+ printk(KERN_INFO "claw: variable p_ch =\n");
+ dumpit((char *) p_ch, sizeof(struct chbk));
+ #endif
+@@ -1200,20 +1200,20 @@ claw_write_retry ( struct chbk *p_ch )
+ if (p_ch->claw_state == CLAW_STOP) {
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ return;
+ }
+ #ifdef DEBUGMSG
+ printk( KERN_INFO "%s:%s state-%02x\n" ,
+ dev->name,
+- __FUNCTION__,
++ __func__,
+ p_ch->claw_state);
+ #endif
+ claw_strt_out_IO( dev );
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"rtry_xit");
+ return;
+@@ -1235,7 +1235,7 @@ claw_write_next ( struct chbk * p_ch )
+ int rc;
+
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s:%s Enter \n",p_ch->ndev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s Enter \n",p_ch->ndev->name,__func__);
+ printk(KERN_INFO "%s: variable p_ch =\n",p_ch->ndev->name);
+ dumpit((char *) p_ch, sizeof(struct chbk));
+ #endif
+@@ -1262,7 +1262,7 @@ claw_write_next ( struct chbk * p_ch )
+
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ return;
+ } /* end of claw_write_next */
+@@ -1276,7 +1276,7 @@ static void
+ claw_timer ( struct chbk * p_ch )
+ {
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s:%s Entry\n",p_ch->ndev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s Entry\n",p_ch->ndev->name,__func__);
+ printk(KERN_INFO "%s: variable p_ch =\n",p_ch->ndev->name);
+ dumpit((char *) p_ch, sizeof(struct chbk));
+ #endif
+@@ -1285,7 +1285,7 @@ claw_timer ( struct chbk * p_ch )
+ wake_up(&p_ch->wait);
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- p_ch->ndev->name,__FUNCTION__,__LINE__);
++ p_ch->ndev->name,__func__,__LINE__);
+ #endif
+ return;
+ } /* end of claw_timer */
+@@ -1312,7 +1312,7 @@ pages_to_order_of_mag(int num_of_pages)
+ int order_of_mag=1; /* assume 2 pages */
+ int nump=2;
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s Enter pages = %d \n",__FUNCTION__,num_of_pages);
++ printk(KERN_INFO "%s Enter pages = %d \n",__func__,num_of_pages);
+ #endif
+ CLAW_DBF_TEXT_(5,trace,"pages%d",num_of_pages);
+ if (num_of_pages == 1) {return 0; } /* magnitude of 0 = 1 page */
+@@ -1327,7 +1327,7 @@ pages_to_order_of_mag(int num_of_pages)
+ if (order_of_mag > 9) { order_of_mag = 9; } /* I know it's paranoid */
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s Exit on line %d, order = %d\n",
+- __FUNCTION__,__LINE__, order_of_mag);
++ __func__,__LINE__, order_of_mag);
+ #endif
+ CLAW_DBF_TEXT_(5,trace,"mag%d",order_of_mag);
+ return order_of_mag;
+@@ -1349,7 +1349,7 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
+ struct ccwbk* p_buf;
+ #endif
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s:%s Enter \n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
+ #endif
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "dev\n");
+@@ -1369,7 +1369,7 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
+ if ( p_first==NULL) {
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"addexit");
+ return 0;
+@@ -1400,9 +1400,9 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
+ if ( privptr-> p_read_active_first ==NULL ) {
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s:%s p_read_active_first == NULL \n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ printk(KERN_INFO "%s:%s Read active first/last changed \n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ #endif
+ privptr-> p_read_active_first= p_first; /* set new first */
+ privptr-> p_read_active_last = p_last; /* set new last */
+@@ -1411,7 +1411,7 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
+
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s:%s Read in progress \n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ #endif
+ /* set up TIC ccw */
+ temp_ccw.cda= (__u32)__pa(&p_first->read);
+@@ -1450,15 +1450,15 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
+ privptr->p_read_active_last=p_last;
+ } /* end of if ( privptr-> p_read_active_first ==NULL) */
+ #ifdef IOTRACE
+- printk(KERN_INFO "%s:%s dump p_last CCW BK \n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s dump p_last CCW BK \n",dev->name,__func__);
+ dumpit((char *)p_last, sizeof(struct ccwbk));
+- printk(KERN_INFO "%s:%s dump p_end CCW BK \n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s dump p_end CCW BK \n",dev->name,__func__);
+ dumpit((char *)p_end, sizeof(struct endccw));
+
+- printk(KERN_INFO "%s:%s dump p_first CCW BK \n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s dump p_first CCW BK \n",dev->name,__func__);
+ dumpit((char *)p_first, sizeof(struct ccwbk));
+ printk(KERN_INFO "%s:%s Dump Active CCW chain \n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ p_buf=privptr->p_read_active_first;
+ while (p_buf!=NULL) {
+ dumpit((char *)p_buf, sizeof(struct ccwbk));
+@@ -1467,7 +1467,7 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
+ #endif
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"addexit");
+ return 0;
+@@ -1483,7 +1483,7 @@ ccw_check_return_code(struct ccw_device *cdev, int return_code)
+ {
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() > enter \n",
+- cdev->dev.bus_id,__FUNCTION__);
++ cdev->dev.bus_id,__func__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"ccwret");
+ #ifdef DEBUGMSG
+@@ -1516,7 +1516,7 @@ ccw_check_return_code(struct ccw_device *cdev, int return_code)
+ }
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() > exit on line %d\n",
+- cdev->dev.bus_id,__FUNCTION__,__LINE__);
++ cdev->dev.bus_id,__func__,__LINE__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"ccwret");
+ } /* end of ccw_check_return_code */
+@@ -1531,7 +1531,7 @@ ccw_check_unit_check(struct chbk * p_ch, unsigned char sense )
+ struct net_device *dev = p_ch->ndev;
+
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s: %s() > enter\n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s: %s() > enter\n",dev->name,__func__);
+ #endif
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s: variable dev =\n",dev->name);
+@@ -1578,7 +1578,7 @@ ccw_check_unit_check(struct chbk * p_ch, unsigned char sense )
+
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ } /* end of ccw_check_unit_check */
+
+@@ -1706,7 +1706,7 @@ find_link(struct net_device *dev, char *host_name, char *ws_name )
+ int rc=0;
+
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s:%s > enter \n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s > enter \n",dev->name,__func__);
+ #endif
+ CLAW_DBF_TEXT(2,setup,"findlink");
+ #ifdef DEBUGMSG
+@@ -1739,7 +1739,7 @@ find_link(struct net_device *dev, char *host_name, char *ws_name )
+
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ return 0;
+ } /* end of find_link */
+@@ -1773,7 +1773,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
+ struct ccwbk *p_buf;
+ #endif
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s: %s() > enter\n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s: %s() > enter\n",dev->name,__func__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"hw_tx");
+ #ifdef DEBUGMSG
+@@ -1787,7 +1787,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
+ p_ch=(struct chbk *)&privptr->channel[WRITE];
+ p_env =privptr->p_env;
+ #ifdef IOTRACE
+- printk(KERN_INFO "%s: %s() dump sk_buff \n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s: %s() dump sk_buff \n",dev->name,__func__);
+ dumpit((char *)skb ,sizeof(struct sk_buff));
+ #endif
+ claw_free_wrt_buf(dev); /* Clean up free chain if posible */
+@@ -1877,7 +1877,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
+ while (len_of_data > 0) {
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() length-of-data is %ld \n",
+- dev->name ,__FUNCTION__,len_of_data);
++ dev->name ,__func__,len_of_data);
+ dumpit((char *)pDataAddress ,64);
+ #endif
+ p_this_ccw=privptr->p_write_free_chain; /* get a block */
+@@ -1913,7 +1913,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
+ p_last_ccw=p_this_ccw; /* save new last block */
+ #ifdef IOTRACE
+ printk(KERN_INFO "%s: %s() > CCW and Buffer %ld bytes long \n",
+- dev->name,__FUNCTION__,bytesInThisBuffer);
++ dev->name,__func__,bytesInThisBuffer);
+ dumpit((char *)p_this_ccw, sizeof(struct ccwbk));
+ dumpit((char *)p_this_ccw->p_buffer, 64);
+ #endif
+@@ -1998,7 +1998,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
+
+ #ifdef IOTRACE
+ printk(KERN_INFO "%s: %s() > Dump Active CCW chain \n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ p_buf=privptr->p_write_active_first;
+ while (p_buf!=NULL) {
+ dumpit((char *)p_buf, sizeof(struct ccwbk));
+@@ -2018,7 +2018,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
+ /* if write free count is zero , set NOBUFFER */
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() > free_count is %d\n",
+- dev->name,__FUNCTION__,
++ dev->name,__func__,
+ (int) privptr->write_free_count );
+ #endif
+ if (privptr->write_free_count==0) {
+@@ -2029,7 +2029,7 @@ Done2:
+ Done:
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() > exit on line %d, rc = %d \n",
+- dev->name,__FUNCTION__,__LINE__, rc);
++ dev->name,__func__,__LINE__, rc);
+ #endif
+ return(rc);
+ } /* end of claw_hw_tx */
+@@ -2063,7 +2063,7 @@ init_ccw_bk(struct net_device *dev)
+ addr_t real_TIC_address;
+ int i,j;
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s: %s() enter \n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s: %s() enter \n",dev->name,__func__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"init_ccw");
+ #ifdef DEBUGMSG
+@@ -2097,15 +2097,15 @@ init_ccw_bk(struct net_device *dev)
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() "
+ "ccw_blocks_required=%d\n",
+- dev->name,__FUNCTION__,
++ dev->name,__func__,
+ ccw_blocks_required);
+ printk(KERN_INFO "%s: %s() "
+ "PAGE_SIZE=0x%x\n",
+- dev->name,__FUNCTION__,
++ dev->name,__func__,
+ (unsigned int)PAGE_SIZE);
+ printk(KERN_INFO "%s: %s() > "
+ "PAGE_MASK=0x%x\n",
+- dev->name,__FUNCTION__,
++ dev->name,__func__,
+ (unsigned int)PAGE_MASK);
+ #endif
+ /*
+@@ -2117,10 +2117,10 @@ init_ccw_bk(struct net_device *dev)
+
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() > ccw_blocks_perpage=%d\n",
+- dev->name,__FUNCTION__,
++ dev->name,__func__,
+ ccw_blocks_perpage);
+ printk(KERN_INFO "%s: %s() > ccw_pages_required=%d\n",
+- dev->name,__FUNCTION__,
++ dev->name,__func__,
+ ccw_pages_required);
+ #endif
+ /*
+@@ -2156,29 +2156,29 @@ init_ccw_bk(struct net_device *dev)
+ #ifdef DEBUGMSG
+ if (privptr->p_env->read_size < PAGE_SIZE) {
+ printk(KERN_INFO "%s: %s() reads_perpage=%d\n",
+- dev->name,__FUNCTION__,
++ dev->name,__func__,
+ claw_reads_perpage);
+ }
+ else {
+ printk(KERN_INFO "%s: %s() pages_perread=%d\n",
+- dev->name,__FUNCTION__,
++ dev->name,__func__,
+ privptr->p_buff_pages_perread);
+ }
+ printk(KERN_INFO "%s: %s() read_pages=%d\n",
+- dev->name,__FUNCTION__,
++ dev->name,__func__,
+ claw_read_pages);
+ if (privptr->p_env->write_size < PAGE_SIZE) {
+ printk(KERN_INFO "%s: %s() writes_perpage=%d\n",
+- dev->name,__FUNCTION__,
++ dev->name,__func__,
+ claw_writes_perpage);
+ }
+ else {
+ printk(KERN_INFO "%s: %s() pages_perwrite=%d\n",
+- dev->name,__FUNCTION__,
++ dev->name,__func__,
+ privptr->p_buff_pages_perwrite);
+ }
+ printk(KERN_INFO "%s: %s() write_pages=%d\n",
+- dev->name,__FUNCTION__,
++ dev->name,__func__,
+ claw_write_pages);
+ #endif
+
+@@ -2194,12 +2194,12 @@ init_ccw_bk(struct net_device *dev)
+ printk(KERN_INFO "%s: %s() "
+ "__get_free_pages for CCWs failed : "
+ "pages is %d\n",
+- dev->name,__FUNCTION__,
++ dev->name,__func__,
+ ccw_pages_required );
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() > "
+ "exit on line %d, rc = ENOMEM\n",
+- dev->name,__FUNCTION__,
++ dev->name,__func__,
+ __LINE__);
+ #endif
+ return -ENOMEM;
+@@ -2218,7 +2218,7 @@ init_ccw_bk(struct net_device *dev)
+ /* Initialize ending CCW block */
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() begin initialize ending CCW blocks\n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ #endif
+
+ p_endccw=privptr->p_end_ccw;
+@@ -2276,7 +2276,7 @@ init_ccw_bk(struct net_device *dev)
+
+ #ifdef IOTRACE
+ printk(KERN_INFO "%s: %s() dump claw ending CCW BK \n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ dumpit((char *)p_endccw, sizeof(struct endccw));
+ #endif
+
+@@ -2287,7 +2287,7 @@ init_ccw_bk(struct net_device *dev)
+
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() Begin build a chain of CCW buffer \n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ #endif
+ p_buff=privptr->p_buff_ccw;
+
+@@ -2306,7 +2306,7 @@ init_ccw_bk(struct net_device *dev)
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() "
+ "End build a chain of CCW buffer \n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ p_buf=p_free_chain;
+ while (p_buf!=NULL) {
+ dumpit((char *)p_buf, sizeof(struct ccwbk));
+@@ -2321,7 +2321,7 @@ init_ccw_bk(struct net_device *dev)
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() "
+ "Begin initialize ClawSignalBlock \n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ #endif
+ if (privptr->p_claw_signal_blk==NULL) {
+ privptr->p_claw_signal_blk=p_free_chain;
+@@ -2334,7 +2334,7 @@ init_ccw_bk(struct net_device *dev)
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() > End initialize "
+ "ClawSignalBlock\n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ dumpit((char *)privptr->p_claw_signal_blk, sizeof(struct ccwbk));
+ #endif
+
+@@ -2349,14 +2349,14 @@ init_ccw_bk(struct net_device *dev)
+ if (privptr->p_buff_write==NULL) {
+ printk(KERN_INFO "%s: %s() __get_free_pages for write"
+ " bufs failed : get is for %d pages\n",
+- dev->name,__FUNCTION__,claw_write_pages );
++ dev->name,__func__,claw_write_pages );
+ free_pages((unsigned long)privptr->p_buff_ccw,
+ (int)pages_to_order_of_mag(privptr->p_buff_ccw_num));
+ privptr->p_buff_ccw=NULL;
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() > exit on line %d,"
+ "rc = ENOMEM\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ return -ENOMEM;
+ }
+@@ -2369,7 +2369,7 @@ init_ccw_bk(struct net_device *dev)
+ ccw_pages_required * PAGE_SIZE);
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() Begin build claw write free "
+- "chain \n",dev->name,__FUNCTION__);
++ "chain \n",dev->name,__func__);
+ #endif
+ privptr->p_write_free_chain=NULL;
+
+@@ -2409,14 +2409,14 @@ init_ccw_bk(struct net_device *dev)
+ #ifdef IOTRACE
+ printk(KERN_INFO "%s:%s __get_free_pages "
+ "for writes buf: get for %d pages\n",
+- dev->name,__FUNCTION__,
++ dev->name,__func__,
+ privptr->p_buff_pages_perwrite);
+ #endif
+ if (p_buff==NULL) {
+ printk(KERN_INFO "%s:%s __get_free_pages "
+ "for writes buf failed : get is for %d pages\n",
+ dev->name,
+- __FUNCTION__,
++ __func__,
+ privptr->p_buff_pages_perwrite );
+ free_pages((unsigned long)privptr->p_buff_ccw,
+ (int)pages_to_order_of_mag(
+@@ -2433,7 +2433,7 @@ init_ccw_bk(struct net_device *dev)
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s exit on line %d, rc = ENOMEM\n",
+ dev->name,
+- __FUNCTION__,
++ __func__,
+ __LINE__);
+ #endif
+ return -ENOMEM;
+@@ -2466,7 +2466,7 @@ init_ccw_bk(struct net_device *dev)
+
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s:%s End build claw write free chain \n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ p_buf=privptr->p_write_free_chain;
+ while (p_buf!=NULL) {
+ dumpit((char *)p_buf, sizeof(struct ccwbk));
+@@ -2485,7 +2485,7 @@ init_ccw_bk(struct net_device *dev)
+ printk(KERN_INFO "%s: %s() "
+ "__get_free_pages for read buf failed : "
+ "get is for %d pages\n",
+- dev->name,__FUNCTION__,claw_read_pages );
++ dev->name,__func__,claw_read_pages );
+ free_pages((unsigned long)privptr->p_buff_ccw,
+ (int)pages_to_order_of_mag(
+ privptr->p_buff_ccw_num));
+@@ -2497,7 +2497,7 @@ init_ccw_bk(struct net_device *dev)
+ privptr->p_buff_write=NULL;
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() > exit on line %d, rc ="
+- " ENOMEM\n",dev->name,__FUNCTION__,__LINE__);
++ " ENOMEM\n",dev->name,__func__,__LINE__);
+ #endif
+ return -ENOMEM;
+ }
+@@ -2509,7 +2509,7 @@ init_ccw_bk(struct net_device *dev)
+ */
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() Begin build claw read free chain \n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ #endif
+ p_buff=privptr->p_buff_read;
+ for (i=0 ; i< privptr->p_env->read_buffers ; i++) {
+@@ -2590,7 +2590,7 @@ init_ccw_bk(struct net_device *dev)
+
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() Begin build claw read free chain \n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ #endif
+ for (i=0 ; i< privptr->p_env->read_buffers ; i++) {
+ p_buff = (void *)__get_free_pages(__GFP_DMA,
+@@ -2598,7 +2598,7 @@ init_ccw_bk(struct net_device *dev)
+ if (p_buff==NULL) {
+ printk(KERN_INFO "%s: %s() __get_free_pages for read "
+ "buf failed : get is for %d pages\n",
+- dev->name,__FUNCTION__,
++ dev->name,__func__,
+ privptr->p_buff_pages_perread );
+ free_pages((unsigned long)privptr->p_buff_ccw,
+ (int)pages_to_order_of_mag(privptr->p_buff_ccw_num));
+@@ -2622,7 +2622,7 @@ init_ccw_bk(struct net_device *dev)
+ privptr->p_buff_write=NULL;
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() exit on line %d, rc = ENOMEM\n",
+- dev->name,__FUNCTION__,
++ dev->name,__func__,
+ __LINE__);
+ #endif
+ return -ENOMEM;
+@@ -2695,7 +2695,7 @@ init_ccw_bk(struct net_device *dev)
+ } /* pBuffread = NULL */
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() > End build claw read free chain \n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ p_buf=p_first_CCWB;
+ while (p_buf!=NULL) {
+ dumpit((char *)p_buf, sizeof(struct ccwbk));
+@@ -2707,7 +2707,7 @@ init_ccw_bk(struct net_device *dev)
+ privptr->buffs_alloc = 1;
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ return 0;
+ } /* end of init_ccw_bk */
+@@ -2723,11 +2723,11 @@ probe_error( struct ccwgroup_device *cgdev)
+ {
+ struct claw_privbk *privptr;
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s enter \n",__FUNCTION__);
++ printk(KERN_INFO "%s enter \n",__func__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"proberr");
+ #ifdef DEBUGMSG
+- printk(KERN_INFO "%s variable cgdev =\n",__FUNCTION__);
++ printk(KERN_INFO "%s variable cgdev =\n",__func__);
+ dumpit((char *) cgdev, sizeof(struct ccwgroup_device));
+ #endif
+ privptr=(struct claw_privbk *)cgdev->dev.driver_data;
+@@ -2741,7 +2741,7 @@ probe_error( struct ccwgroup_device *cgdev)
+ }
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s > exit on line %d\n",
+- __FUNCTION__,__LINE__);
++ __func__,__LINE__);
+ #endif
+
+ return;
+@@ -2772,7 +2772,7 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
+ struct chbk *p_ch = NULL;
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() > enter \n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ #endif
+ CLAW_DBF_TEXT(2,setup,"clw_cntl");
+ #ifdef DEBUGMSG
+@@ -2794,7 +2794,7 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() > "
+ "exit on line %d, rc=0\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ return 0;
+ }
+@@ -3057,7 +3057,7 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
+
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() exit on line %d, rc = 0\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+
+ return 0;
+@@ -3080,7 +3080,7 @@ claw_send_control(struct net_device *dev, __u8 type, __u8 link,
+ struct sk_buff *skb;
+
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s:%s > enter \n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s > enter \n",dev->name,__func__);
+ #endif
+ CLAW_DBF_TEXT(2,setup,"sndcntl");
+ #ifdef DEBUGMSG
+@@ -3143,10 +3143,10 @@ claw_send_control(struct net_device *dev, __u8 type, __u8 link,
+ skb = dev_alloc_skb(sizeof(struct clawctl));
+ if (!skb) {
+ printk( "%s:%s low on mem, returning...\n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ #ifdef DEBUG
+ printk(KERN_INFO "%s:%s Exit, rc = ENOMEM\n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ #endif
+ return -ENOMEM;
+ }
+@@ -3162,7 +3162,7 @@ claw_send_control(struct net_device *dev, __u8 type, __u8 link,
+ claw_hw_tx(skb, dev, 0);
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+
+ return 0;
+@@ -3180,7 +3180,7 @@ claw_snd_conn_req(struct net_device *dev, __u8 link)
+ struct clawctl *p_ctl;
+
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s:%s Enter \n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
+ #endif
+ CLAW_DBF_TEXT(2,setup,"snd_conn");
+ #ifdef DEBUGMSG
+@@ -3193,7 +3193,7 @@ claw_snd_conn_req(struct net_device *dev, __u8 link)
+ if ( privptr->system_validate_comp==0x00 ) {
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d, rc = 1\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ return rc;
+ }
+@@ -3209,7 +3209,7 @@ claw_snd_conn_req(struct net_device *dev, __u8 link)
+ HOST_APPL_NAME, privptr->p_env->api_type);
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
+- dev->name,__FUNCTION__,__LINE__, rc);
++ dev->name,__func__,__LINE__, rc);
+ #endif
+ return rc;
+
+@@ -3228,7 +3228,7 @@ claw_snd_disc(struct net_device *dev, struct clawctl * p_ctl)
+ struct conncmd * p_connect;
+
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
+ #endif
+ CLAW_DBF_TEXT(2,setup,"snd_dsc");
+ #ifdef DEBUGMSG
+@@ -3244,7 +3244,7 @@ claw_snd_disc(struct net_device *dev, struct clawctl * p_ctl)
+ p_connect->host_name, p_connect->WS_name);
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
+- dev->name,__FUNCTION__, __LINE__, rc);
++ dev->name,__func__, __LINE__, rc);
+ #endif
+ return rc;
+ } /* end of claw_snd_disc */
+@@ -3265,7 +3265,7 @@ claw_snd_sys_validate_rsp(struct net_device *dev,
+
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Enter\n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ #endif
+ CLAW_DBF_TEXT(2,setup,"chkresp");
+ #ifdef DEBUGMSG
+@@ -3285,7 +3285,7 @@ claw_snd_sys_validate_rsp(struct net_device *dev,
+ p_env->adapter_name );
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
+- dev->name,__FUNCTION__,__LINE__, rc);
++ dev->name,__func__,__LINE__, rc);
+ #endif
+ return rc;
+ } /* end of claw_snd_sys_validate_rsp */
+@@ -3301,7 +3301,7 @@ claw_strt_conn_req(struct net_device *dev )
+ int rc;
+
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
+ #endif
+ CLAW_DBF_TEXT(2,setup,"conn_req");
+ #ifdef DEBUGMSG
+@@ -3311,7 +3311,7 @@ claw_strt_conn_req(struct net_device *dev )
+ rc=claw_snd_conn_req(dev, 1);
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
+- dev->name,__FUNCTION__,__LINE__, rc);
++ dev->name,__func__,__LINE__, rc);
+ #endif
+ return rc;
+ } /* end of claw_strt_conn_req */
+@@ -3327,13 +3327,13 @@ net_device_stats *claw_stats(struct net_device *dev)
+ {
+ struct claw_privbk *privptr;
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"stats");
+ privptr = dev->priv;
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ return &privptr->stats;
+ } /* end of claw_stats */
+@@ -3366,7 +3366,7 @@ unpack_read(struct net_device *dev )
+ int p=0;
+
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s:%s enter \n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s enter \n",dev->name,__func__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"unpkread");
+ p_first_ccw=NULL;
+@@ -3408,7 +3408,7 @@ unpack_read(struct net_device *dev )
+ if ((p_this_ccw->header.opcode & MORE_to_COME_FLAG)!=0) {
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s > More_to_come is ON\n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ #endif
+ mtc_this_frm=1;
+ if (p_this_ccw->header.length!=
+@@ -3435,7 +3435,7 @@ unpack_read(struct net_device *dev )
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s:%s goto next "
+ "frame from MoretoComeSkip \n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ #endif
+ goto NextFrame;
+ }
+@@ -3445,7 +3445,7 @@ unpack_read(struct net_device *dev )
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s:%s goto next "
+ "frame from claw_process_control \n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"UnpkCntl");
+ goto NextFrame;
+@@ -3468,7 +3468,7 @@ unpack_next:
+ if (privptr->mtc_logical_link<0) {
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s mtc_logical_link < 0 \n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ #endif
+
+ /*
+@@ -3487,7 +3487,7 @@ unpack_next:
+ printk(KERN_INFO "%s: %s > goto next "
+ "frame from MoretoComeSkip \n",
+ dev->name,
+- __FUNCTION__);
++ __func__);
+ printk(KERN_INFO " bytes_to_mov %d > (MAX_ENVELOPE_"
+ "SIZE-privptr->mtc_offset %d)\n",
+ bytes_to_mov,(MAX_ENVELOPE_SIZE- privptr->mtc_offset));
+@@ -3505,13 +3505,13 @@ unpack_next:
+ }
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() received data \n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ if (p_env->packing == DO_PACKED)
+ dumpit((char *)p_packd+sizeof(struct clawph),32);
+ else
+ dumpit((char *)p_this_ccw->p_buffer, 32);
+ printk(KERN_INFO "%s: %s() bytelength %d \n",
+- dev->name,__FUNCTION__,bytes_to_mov);
++ dev->name,__func__,bytes_to_mov);
+ #endif
+ if (mtc_this_frm==0) {
+ len_of_data=privptr->mtc_offset+bytes_to_mov;
+@@ -3530,13 +3530,13 @@ unpack_next:
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() netif_"
+ "rx(skb) completed \n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ #endif
+ }
+ else {
+ privptr->stats.rx_dropped++;
+ printk(KERN_WARNING "%s: %s() low on memory\n",
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ }
+ privptr->mtc_offset=0;
+ privptr->mtc_logical_link=-1;
+@@ -3575,10 +3575,10 @@ NextFrame:
+
+ #ifdef IOTRACE
+ printk(KERN_INFO "%s:%s processed frame is %d \n",
+- dev->name,__FUNCTION__,i);
++ dev->name,__func__,i);
+ printk(KERN_INFO "%s:%s F:%lx L:%lx\n",
+ dev->name,
+- __FUNCTION__,
++ __func__,
+ (unsigned long)p_first_ccw,
+ (unsigned long)p_last_ccw);
+ #endif
+@@ -3588,7 +3588,7 @@ NextFrame:
+ claw_strt_read(dev, LOCK_YES);
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s exit on line %d\n",
+- dev->name, __FUNCTION__, __LINE__);
++ dev->name, __func__, __LINE__);
+ #endif
+ return;
+ } /* end of unpack_read */
+@@ -3610,7 +3610,7 @@ claw_strt_read (struct net_device *dev, int lock )
+ p_ch=&privptr->channel[READ];
+
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s:%s Enter \n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
+ printk(KERN_INFO "%s: variable lock = %d, dev =\n",dev->name, lock);
+ dumpit((char *) dev, sizeof(struct net_device));
+ #endif
+@@ -3626,7 +3626,7 @@ claw_strt_read (struct net_device *dev, int lock )
+ }
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s:%s state-%02x\n" ,
+- dev->name,__FUNCTION__, p_ch->claw_state);
++ dev->name,__func__, p_ch->claw_state);
+ #endif
+ if (lock==LOCK_YES) {
+ spin_lock_irqsave(get_ccwdev_lock(p_ch->cdev), saveflags);
+@@ -3634,7 +3634,7 @@ claw_strt_read (struct net_device *dev, int lock )
+ if (test_and_set_bit(0, (void *)&p_ch->IO_active) == 0) {
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s: HOT READ started in %s\n" ,
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ p_clawh=(struct clawh *)privptr->p_claw_signal_blk;
+ dumpit((char *)&p_clawh->flag , 1);
+ #endif
+@@ -3650,7 +3650,7 @@ claw_strt_read (struct net_device *dev, int lock )
+ else {
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s: No READ started by %s() In progress\n" ,
+- dev->name,__FUNCTION__);
++ dev->name,__func__);
+ #endif
+ CLAW_DBF_TEXT(2,trace,"ReadAct");
+ }
+@@ -3660,7 +3660,7 @@ claw_strt_read (struct net_device *dev, int lock )
+ }
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"StRdExit");
+ return;
+@@ -3681,7 +3681,7 @@ claw_strt_out_IO( struct net_device *dev )
+ struct ccwbk *p_first_ccw;
+
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
+ #endif
+ if (!dev) {
+ return;
+@@ -3691,7 +3691,7 @@ claw_strt_out_IO( struct net_device *dev )
+
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s:%s state-%02x\n" ,
+- dev->name,__FUNCTION__,p_ch->claw_state);
++ dev->name,__func__,p_ch->claw_state);
+ #endif
+ CLAW_DBF_TEXT(4,trace,"strt_io");
+ p_first_ccw=privptr->p_write_active_first;
+@@ -3701,14 +3701,14 @@ claw_strt_out_IO( struct net_device *dev )
+ if (p_first_ccw == NULL) {
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+ return;
+ }
+ if (test_and_set_bit(0, (void *)&p_ch->IO_active) == 0) {
+ parm = (unsigned long) p_ch;
+ #ifdef DEBUGMSG
+- printk(KERN_INFO "%s:%s do_io \n" ,dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s do_io \n" ,dev->name,__func__);
+ dumpit((char *)p_first_ccw, sizeof(struct ccwbk));
+ #endif
+ CLAW_DBF_TEXT(2,trace,"StWrtIO");
+@@ -3721,7 +3721,7 @@ claw_strt_out_IO( struct net_device *dev )
+ dev->trans_start = jiffies;
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- dev->name,__FUNCTION__,__LINE__);
++ dev->name,__func__,__LINE__);
+ #endif
+
+ return;
+@@ -3745,7 +3745,7 @@ claw_free_wrt_buf( struct net_device *dev )
+ struct ccwbk*p_buf;
+ #endif
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
+ printk(KERN_INFO "%s: free count = %d variable dev =\n",
+ dev->name,privptr->write_free_count);
+ #endif
+@@ -3798,7 +3798,7 @@ claw_free_wrt_buf( struct net_device *dev )
+ privptr->p_write_active_last=NULL;
+ #ifdef DEBUGMSG
+ printk(KERN_INFO "%s:%s p_write_"
+- "active_first==NULL\n",dev->name,__FUNCTION__);
++ "active_first==NULL\n",dev->name,__func__);
+ #endif
+ }
+ #ifdef IOTRACE
+@@ -3819,7 +3819,7 @@ claw_free_wrt_buf( struct net_device *dev )
+ CLAW_DBF_TEXT_(4,trace,"FWC=%d",privptr->write_free_count);
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d free_count =%d\n",
+- dev->name,__FUNCTION__, __LINE__,privptr->write_free_count);
++ dev->name,__func__, __LINE__,privptr->write_free_count);
+ #endif
+ return;
+ }
+@@ -3833,7 +3833,7 @@ claw_free_netdevice(struct net_device * dev, int free_dev)
+ {
+ struct claw_privbk *privptr;
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
+ #endif
+ CLAW_DBF_TEXT(2,setup,"free_dev");
+
+@@ -3854,7 +3854,7 @@ claw_free_netdevice(struct net_device * dev, int free_dev)
+ #endif
+ CLAW_DBF_TEXT(2,setup,"feee_ok");
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s:%s Exit\n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s Exit\n",dev->name,__func__);
+ #endif
+ }
+
+@@ -3867,13 +3867,13 @@ static void
+ claw_init_netdevice(struct net_device * dev)
+ {
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
+ #endif
+ CLAW_DBF_TEXT(2,setup,"init_dev");
+ CLAW_DBF_TEXT_(2,setup,"%s",dev->name);
+ if (!dev) {
+ printk(KERN_WARNING "claw:%s BAD Device exit line %d\n",
+- __FUNCTION__,__LINE__);
++ __func__,__LINE__);
+ CLAW_DBF_TEXT(2,setup,"baddev");
+ return;
+ }
+@@ -3889,7 +3889,7 @@ claw_init_netdevice(struct net_device * dev)
+ dev->tx_queue_len = 1300;
+ dev->flags = IFF_POINTOPOINT | IFF_NOARP;
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s:%s Exit\n",dev->name,__FUNCTION__);
++ printk(KERN_INFO "%s:%s Exit\n",dev->name,__func__);
+ #endif
+ CLAW_DBF_TEXT(2,setup,"initok");
+ return;
+@@ -3909,7 +3909,7 @@ add_channel(struct ccw_device *cdev,int i,struct claw_privbk *privptr)
+ struct ccw_dev_id dev_id;
+
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "%s:%s Enter\n",cdev->dev.bus_id,__FUNCTION__);
++ printk(KERN_INFO "%s:%s Enter\n",cdev->dev.bus_id,__func__);
+ #endif
+ CLAW_DBF_TEXT_(2,setup,"%s",cdev->dev.bus_id);
+ privptr->channel[i].flag = i+1; /* Read is 1 Write is 2 */
+@@ -3920,16 +3920,16 @@ add_channel(struct ccw_device *cdev,int i,struct claw_privbk *privptr)
+ p_ch->devno = dev_id.devno;
+ if ((p_ch->irb = kzalloc(sizeof (struct irb),GFP_KERNEL)) == NULL) {
+ printk(KERN_WARNING "%s Out of memory in %s for irb\n",
+- p_ch->id,__FUNCTION__);
++ p_ch->id,__func__);
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- p_ch->id,__FUNCTION__,__LINE__);
++ p_ch->id,__func__,__LINE__);
+ #endif
+ return -ENOMEM;
+ }
+ #ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+- cdev->dev.bus_id,__FUNCTION__,__LINE__);
++ cdev->dev.bus_id,__func__,__LINE__);
+ #endif
+ return 0;
+ }
+@@ -3952,7 +3952,7 @@ claw_new_device(struct ccwgroup_device *cgdev)
+ int ret;
+ struct ccw_dev_id dev_id;
+
+- pr_debug("%s() called\n", __FUNCTION__);
++ pr_debug("%s() called\n", __func__);
+ printk(KERN_INFO "claw: add for %s\n",cgdev->cdev[READ]->dev.bus_id);
+ CLAW_DBF_TEXT(2,setup,"new_dev");
+ privptr = cgdev->dev.driver_data;
+@@ -3990,7 +3990,7 @@ claw_new_device(struct ccwgroup_device *cgdev)
+ }
+ dev = alloc_netdev(0,"claw%d",claw_init_netdevice);
+ if (!dev) {
+- printk(KERN_WARNING "%s:alloc_netdev failed\n",__FUNCTION__);
++ printk(KERN_WARNING "%s:alloc_netdev failed\n",__func__);
+ goto out;
+ }
+ dev->priv = privptr;
+@@ -4065,7 +4065,7 @@ claw_shutdown_device(struct ccwgroup_device *cgdev)
+ struct net_device *ndev;
+ int ret;
+
+- pr_debug("%s() called\n", __FUNCTION__);
++ pr_debug("%s() called\n", __func__);
+ CLAW_DBF_TEXT_(2,setup,"%s",cgdev->dev.bus_id);
+ priv = cgdev->dev.driver_data;
+ if (!priv)
+@@ -4095,15 +4095,15 @@ claw_remove_device(struct ccwgroup_device *cgdev)
+ {
+ struct claw_privbk *priv;
+
+- pr_debug("%s() called\n", __FUNCTION__);
++ pr_debug("%s() called\n", __func__);
+ CLAW_DBF_TEXT_(2,setup,"%s",cgdev->dev.bus_id);
+ priv = cgdev->dev.driver_data;
+ if (!priv) {
+- printk(KERN_WARNING "claw: %s() no Priv exiting\n",__FUNCTION__);
++ printk(KERN_WARNING "claw: %s() no Priv exiting\n",__func__);
+ return;
+ }
+ printk(KERN_INFO "claw: %s() called %s will be removed.\n",
+- __FUNCTION__,cgdev->cdev[0]->dev.bus_id);
++ __func__,cgdev->cdev[0]->dev.bus_id);
+ if (cgdev->state == CCWGROUP_ONLINE)
+ claw_shutdown_device(cgdev);
+ claw_remove_files(&cgdev->dev);
+@@ -4346,7 +4346,7 @@ static struct attribute_group claw_attr_group = {
+ static int
+ claw_add_files(struct device *dev)
+ {
+- pr_debug("%s() called\n", __FUNCTION__);
++ pr_debug("%s() called\n", __func__);
+ CLAW_DBF_TEXT(2,setup,"add_file");
+ return sysfs_create_group(&dev->kobj, &claw_attr_group);
+ }
+@@ -4354,7 +4354,7 @@ claw_add_files(struct device *dev)
+ static void
+ claw_remove_files(struct device *dev)
+ {
+- pr_debug("%s() called\n", __FUNCTION__);
++ pr_debug("%s() called\n", __func__);
+ CLAW_DBF_TEXT(2,setup,"rem_file");
+ sysfs_remove_group(&dev->kobj, &claw_attr_group);
+ }
+@@ -4385,12 +4385,12 @@ claw_init(void)
+ printk(KERN_INFO "claw: starting driver\n");
+
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "claw: %s() enter \n",__FUNCTION__);
++ printk(KERN_INFO "claw: %s() enter \n",__func__);
+ #endif
+ ret = claw_register_debug_facility();
+ if (ret) {
+ printk(KERN_WARNING "claw: %s() debug_register failed %d\n",
+- __FUNCTION__,ret);
++ __func__,ret);
+ return ret;
+ }
+ CLAW_DBF_TEXT(2,setup,"init_mod");
+@@ -4398,10 +4398,10 @@ claw_init(void)
+ if (ret) {
+ claw_unregister_debug_facility();
+ printk(KERN_WARNING "claw; %s() cu3088 register failed %d\n",
+- __FUNCTION__,ret);
++ __func__,ret);
+ }
+ #ifdef FUNCTRACE
+- printk(KERN_INFO "claw: %s() exit \n",__FUNCTION__);
++ printk(KERN_INFO "claw: %s() exit \n",__func__);
+ #endif
+ return ret;
+ }
+diff --git a/drivers/s390/net/ctcdbug.c b/drivers/s390/net/ctcdbug.c
+deleted file mode 100644
+index e6e72de..0000000
+--- a/drivers/s390/net/ctcdbug.c
++++ /dev/null
+@@ -1,80 +0,0 @@
+-/*
+- *
+- * linux/drivers/s390/net/ctcdbug.c
+- *
+- * CTC / ESCON network driver - s390 dbf exploit.
+- *
+- * Copyright 2000,2003 IBM Corporation
+- *
+- * Author(s): Original Code written by
+- * Peter Tiedemann (ptiedem at de.ibm.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, or (at your option)
+- * any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#include "ctcdbug.h"
+-
+-/**
+- * Debug Facility Stuff
+- */
+-debug_info_t *ctc_dbf_setup = NULL;
+-debug_info_t *ctc_dbf_data = NULL;
+-debug_info_t *ctc_dbf_trace = NULL;
+-
+-DEFINE_PER_CPU(char[256], ctc_dbf_txt_buf);
+-
+-void
+-ctc_unregister_dbf_views(void)
+-{
+- if (ctc_dbf_setup)
+- debug_unregister(ctc_dbf_setup);
+- if (ctc_dbf_data)
+- debug_unregister(ctc_dbf_data);
+- if (ctc_dbf_trace)
+- debug_unregister(ctc_dbf_trace);
+-}
+-int
+-ctc_register_dbf_views(void)
+-{
+- ctc_dbf_setup = debug_register(CTC_DBF_SETUP_NAME,
+- CTC_DBF_SETUP_PAGES,
+- CTC_DBF_SETUP_NR_AREAS,
+- CTC_DBF_SETUP_LEN);
+- ctc_dbf_data = debug_register(CTC_DBF_DATA_NAME,
+- CTC_DBF_DATA_PAGES,
+- CTC_DBF_DATA_NR_AREAS,
+- CTC_DBF_DATA_LEN);
+- ctc_dbf_trace = debug_register(CTC_DBF_TRACE_NAME,
+- CTC_DBF_TRACE_PAGES,
+- CTC_DBF_TRACE_NR_AREAS,
+- CTC_DBF_TRACE_LEN);
+-
+- if ((ctc_dbf_setup == NULL) || (ctc_dbf_data == NULL) ||
+- (ctc_dbf_trace == NULL)) {
+- ctc_unregister_dbf_views();
+- return -ENOMEM;
+- }
+- debug_register_view(ctc_dbf_setup, &debug_hex_ascii_view);
+- debug_set_level(ctc_dbf_setup, CTC_DBF_SETUP_LEVEL);
+-
+- debug_register_view(ctc_dbf_data, &debug_hex_ascii_view);
+- debug_set_level(ctc_dbf_data, CTC_DBF_DATA_LEVEL);
+-
+- debug_register_view(ctc_dbf_trace, &debug_hex_ascii_view);
+- debug_set_level(ctc_dbf_trace, CTC_DBF_TRACE_LEVEL);
+-
+- return 0;
+-}
+-
+diff --git a/drivers/s390/net/ctcdbug.h b/drivers/s390/net/ctcdbug.h
+deleted file mode 100644
+index 413925e..0000000
+--- a/drivers/s390/net/ctcdbug.h
++++ /dev/null
+@@ -1,125 +0,0 @@
+-/*
+- *
+- * linux/drivers/s390/net/ctcdbug.h
+- *
+- * CTC / ESCON network driver - s390 dbf exploit.
+- *
+- * Copyright 2000,2003 IBM Corporation
+- *
+- * Author(s): Original Code written by
+- * Peter Tiedemann (ptiedem at de.ibm.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, or (at your option)
+- * any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-#ifndef _CTCDBUG_H_
+-#define _CTCDBUG_H_
+-
+-#include <asm/debug.h>
+-#include "ctcmain.h"
+-/**
+- * Debug Facility stuff
+- */
+-#define CTC_DBF_SETUP_NAME "ctc_setup"
+-#define CTC_DBF_SETUP_LEN 16
+-#define CTC_DBF_SETUP_PAGES 8
+-#define CTC_DBF_SETUP_NR_AREAS 1
+-#define CTC_DBF_SETUP_LEVEL 3
+-
+-#define CTC_DBF_DATA_NAME "ctc_data"
+-#define CTC_DBF_DATA_LEN 128
+-#define CTC_DBF_DATA_PAGES 8
+-#define CTC_DBF_DATA_NR_AREAS 1
+-#define CTC_DBF_DATA_LEVEL 3
+-
+-#define CTC_DBF_TRACE_NAME "ctc_trace"
+-#define CTC_DBF_TRACE_LEN 16
+-#define CTC_DBF_TRACE_PAGES 4
+-#define CTC_DBF_TRACE_NR_AREAS 2
+-#define CTC_DBF_TRACE_LEVEL 3
+-
+-#define DBF_TEXT(name,level,text) \
+- do { \
+- debug_text_event(ctc_dbf_##name,level,text); \
+- } while (0)
+-
+-#define DBF_HEX(name,level,addr,len) \
+- do { \
+- debug_event(ctc_dbf_##name,level,(void*)(addr),len); \
+- } while (0)
+-
+-DECLARE_PER_CPU(char[256], ctc_dbf_txt_buf);
+-extern debug_info_t *ctc_dbf_setup;
+-extern debug_info_t *ctc_dbf_data;
+-extern debug_info_t *ctc_dbf_trace;
+-
+-
+-#define DBF_TEXT_(name,level,text...) \
+- do { \
+- char* ctc_dbf_txt_buf = get_cpu_var(ctc_dbf_txt_buf); \
+- sprintf(ctc_dbf_txt_buf, text); \
+- debug_text_event(ctc_dbf_##name,level,ctc_dbf_txt_buf); \
+- put_cpu_var(ctc_dbf_txt_buf); \
+- } while (0)
+-
+-#define DBF_SPRINTF(name,level,text...) \
+- do { \
+- debug_sprintf_event(ctc_dbf_trace, level, ##text ); \
+- debug_sprintf_event(ctc_dbf_trace, level, text ); \
+- } while (0)
+-
+-
+-int ctc_register_dbf_views(void);
+-
+-void ctc_unregister_dbf_views(void);
+-
+-/**
+- * some more debug stuff
+- */
+-
+-#define HEXDUMP16(importance,header,ptr) \
+-PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \
+- "%02x %02x %02x %02x %02x %02x %02x %02x\n", \
+- *(((char*)ptr)),*(((char*)ptr)+1),*(((char*)ptr)+2), \
+- *(((char*)ptr)+3),*(((char*)ptr)+4),*(((char*)ptr)+5), \
+- *(((char*)ptr)+6),*(((char*)ptr)+7),*(((char*)ptr)+8), \
+- *(((char*)ptr)+9),*(((char*)ptr)+10),*(((char*)ptr)+11), \
+- *(((char*)ptr)+12),*(((char*)ptr)+13), \
+- *(((char*)ptr)+14),*(((char*)ptr)+15)); \
+-PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \
+- "%02x %02x %02x %02x %02x %02x %02x %02x\n", \
+- *(((char*)ptr)+16),*(((char*)ptr)+17), \
+- *(((char*)ptr)+18),*(((char*)ptr)+19), \
+- *(((char*)ptr)+20),*(((char*)ptr)+21), \
+- *(((char*)ptr)+22),*(((char*)ptr)+23), \
+- *(((char*)ptr)+24),*(((char*)ptr)+25), \
+- *(((char*)ptr)+26),*(((char*)ptr)+27), \
+- *(((char*)ptr)+28),*(((char*)ptr)+29), \
+- *(((char*)ptr)+30),*(((char*)ptr)+31));
+-
+-static inline void
+-hex_dump(unsigned char *buf, size_t len)
+-{
+- size_t i;
+-
+- for (i = 0; i < len; i++) {
+- if (i && !(i % 16))
+- printk("\n");
+- printk("%02x ", *(buf + i));
+- }
+- printk("\n");
+-}
+-
+-
+-#endif
+diff --git a/drivers/s390/net/ctcm_dbug.c b/drivers/s390/net/ctcm_dbug.c
+new file mode 100644
+index 0000000..8eb25d0
+--- /dev/null
++++ b/drivers/s390/net/ctcm_dbug.c
+@@ -0,0 +1,67 @@
++/*
++ * drivers/s390/net/ctcm_dbug.c
++ *
++ * Copyright IBM Corp. 2001, 2007
++ * Authors: Peter Tiedemann (ptiedem at de.ibm.com)
++ *
++ */
++
++#include <linux/stddef.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/ctype.h>
++#include <linux/sysctl.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/fs.h>
++#include <linux/debugfs.h>
++#include "ctcm_dbug.h"
++
++/*
++ * Debug Facility Stuff
++ */
++
++DEFINE_PER_CPU(char[256], ctcm_dbf_txt_buf);
++
++struct ctcm_dbf_info ctcm_dbf[CTCM_DBF_INFOS] = {
++ [CTCM_DBF_SETUP] = {"ctc_setup", 8, 1, 64, 5, NULL},
++ [CTCM_DBF_ERROR] = {"ctc_error", 8, 1, 64, 3, NULL},
++ [CTCM_DBF_TRACE] = {"ctc_trace", 8, 1, 64, 3, NULL},
++ [CTCM_DBF_MPC_SETUP] = {"mpc_setup", 8, 1, 64, 5, NULL},
++ [CTCM_DBF_MPC_ERROR] = {"mpc_error", 8, 1, 64, 3, NULL},
++ [CTCM_DBF_MPC_TRACE] = {"mpc_trace", 8, 1, 64, 3, NULL},
++};
++
++void ctcm_unregister_dbf_views(void)
++{
++ int x;
++ for (x = 0; x < CTCM_DBF_INFOS; x++) {
++ debug_unregister(ctcm_dbf[x].id);
++ ctcm_dbf[x].id = NULL;
++ }
++}
++
++int ctcm_register_dbf_views(void)
++{
++ int x;
++ for (x = 0; x < CTCM_DBF_INFOS; x++) {
++ /* register the areas */
++ ctcm_dbf[x].id = debug_register(ctcm_dbf[x].name,
++ ctcm_dbf[x].pages,
++ ctcm_dbf[x].areas,
++ ctcm_dbf[x].len);
++ if (ctcm_dbf[x].id == NULL) {
++ ctcm_unregister_dbf_views();
++ return -ENOMEM;
++ }
++
++ /* register a view */
++ debug_register_view(ctcm_dbf[x].id, &debug_hex_ascii_view);
++ /* set a passing level */
++ debug_set_level(ctcm_dbf[x].id, ctcm_dbf[x].level);
++ }
++
++ return 0;
++}
++
+diff --git a/drivers/s390/net/ctcm_dbug.h b/drivers/s390/net/ctcm_dbug.h
+new file mode 100644
+index 0000000..fdff34f
+--- /dev/null
++++ b/drivers/s390/net/ctcm_dbug.h
+@@ -0,0 +1,158 @@
++/*
++ * drivers/s390/net/ctcm_dbug.h
++ *
++ * Copyright IBM Corp. 2001, 2007
++ * Authors: Peter Tiedemann (ptiedem at de.ibm.com)
++ *
++ */
++
++#ifndef _CTCM_DBUG_H_
++#define _CTCM_DBUG_H_
++
++/*
++ * Debug Facility stuff
++ */
++
++#include <asm/debug.h>
++
++#ifdef DEBUG
++ #define do_debug 1
++#else
++ #define do_debug 0
++#endif
++#ifdef DEBUGDATA
++ #define do_debug_data 1
++#else
++ #define do_debug_data 0
++#endif
++#ifdef DEBUGCCW
++ #define do_debug_ccw 1
++#else
++ #define do_debug_ccw 0
++#endif
++
++/* define dbf debug levels similar to kernel msg levels */
++#define CTC_DBF_ALWAYS 0 /* always print this */
++#define CTC_DBF_EMERG 0 /* system is unusable */
++#define CTC_DBF_ALERT 1 /* action must be taken immediately */
++#define CTC_DBF_CRIT 2 /* critical conditions */
++#define CTC_DBF_ERROR 3 /* error conditions */
++#define CTC_DBF_WARN 4 /* warning conditions */
++#define CTC_DBF_NOTICE 5 /* normal but significant condition */
++#define CTC_DBF_INFO 5 /* informational */
++#define CTC_DBF_DEBUG 6 /* debug-level messages */
++
++DECLARE_PER_CPU(char[256], ctcm_dbf_txt_buf);
++
++enum ctcm_dbf_names {
++ CTCM_DBF_SETUP,
++ CTCM_DBF_ERROR,
++ CTCM_DBF_TRACE,
++ CTCM_DBF_MPC_SETUP,
++ CTCM_DBF_MPC_ERROR,
++ CTCM_DBF_MPC_TRACE,
++ CTCM_DBF_INFOS /* must be last element */
++};
++
++struct ctcm_dbf_info {
++ char name[DEBUG_MAX_NAME_LEN];
++ int pages;
++ int areas;
++ int len;
++ int level;
++ debug_info_t *id;
++};
++
++extern struct ctcm_dbf_info ctcm_dbf[CTCM_DBF_INFOS];
++
++int ctcm_register_dbf_views(void);
++void ctcm_unregister_dbf_views(void);
++
++static inline const char *strtail(const char *s, int n)
++{
++ int l = strlen(s);
++ return (l > n) ? s + (l - n) : s;
++}
++
++/* sort out levels early to avoid unnecessary sprintfs */
++static inline int ctcm_dbf_passes(debug_info_t *dbf_grp, int level)
++{
++ return (dbf_grp->level >= level);
++}
++
++#define CTCM_FUNTAIL strtail((char *)__func__, 16)
++
++#define CTCM_DBF_TEXT(name, level, text) \
++ do { \
++ debug_text_event(ctcm_dbf[CTCM_DBF_##name].id, level, text); \
++ } while (0)
++
++#define CTCM_DBF_HEX(name, level, addr, len) \
++ do { \
++ debug_event(ctcm_dbf[CTCM_DBF_##name].id, \
++ level, (void *)(addr), len); \
++ } while (0)
++
++#define CTCM_DBF_TEXT_(name, level, text...) \
++ do { \
++ if (ctcm_dbf_passes(ctcm_dbf[CTCM_DBF_##name].id, level)) { \
++ char *ctcm_dbf_txt_buf = \
++ get_cpu_var(ctcm_dbf_txt_buf); \
++ sprintf(ctcm_dbf_txt_buf, text); \
++ debug_text_event(ctcm_dbf[CTCM_DBF_##name].id, \
++ level, ctcm_dbf_txt_buf); \
++ put_cpu_var(ctcm_dbf_txt_buf); \
++ } \
++ } while (0)
++
++/*
++ * cat : one of {setup, mpc_setup, trace, mpc_trace, error, mpc_error}.
++ * dev : netdevice with valid name field.
++ * text: any text string.
++ */
++#define CTCM_DBF_DEV_NAME(cat, dev, text) \
++ do { \
++ CTCM_DBF_TEXT_(cat, CTC_DBF_INFO, "%s(%s) : %s", \
++ CTCM_FUNTAIL, dev->name, text); \
++ } while (0)
++
++#define MPC_DBF_DEV_NAME(cat, dev, text) \
++ do { \
++ CTCM_DBF_TEXT_(MPC_##cat, CTC_DBF_INFO, "%s(%s) : %s", \
++ CTCM_FUNTAIL, dev->name, text); \
++ } while (0)
++
++#define CTCMY_DBF_DEV_NAME(cat, dev, text) \
++ do { \
++ if (IS_MPCDEV(dev)) \
++ MPC_DBF_DEV_NAME(cat, dev, text); \
++ else \
++ CTCM_DBF_DEV_NAME(cat, dev, text); \
++ } while (0)
++
++/*
++ * cat : one of {setup, mpc_setup, trace, mpc_trace, error, mpc_error}.
++ * dev : netdevice.
++ * text: any text string.
++ */
++#define CTCM_DBF_DEV(cat, dev, text) \
++ do { \
++ CTCM_DBF_TEXT_(cat, CTC_DBF_INFO, "%s(%p) : %s", \
++ CTCM_FUNTAIL, dev, text); \
++ } while (0)
++
++#define MPC_DBF_DEV(cat, dev, text) \
++ do { \
++ CTCM_DBF_TEXT_(MPC_##cat, CTC_DBF_INFO, "%s(%p) : %s", \
++ CTCM_FUNTAIL, dev, text); \
++ } while (0)
++
++#define CTCMY_DBF_DEV(cat, dev, text) \
++ do { \
++ if (IS_MPCDEV(dev)) \
++ MPC_DBF_DEV(cat, dev, text); \
++ else \
++ CTCM_DBF_DEV(cat, dev, text); \
++ } while (0)
++
++#endif
+diff --git a/drivers/s390/net/ctcm_fsms.c b/drivers/s390/net/ctcm_fsms.c
+new file mode 100644
+index 0000000..2a106f3
+--- /dev/null
++++ b/drivers/s390/net/ctcm_fsms.c
+@@ -0,0 +1,2347 @@
++/*
++ * drivers/s390/net/ctcm_fsms.c
++ *
++ * Copyright IBM Corp. 2001, 2007
++ * Authors: Fritz Elfert (felfert at millenux.com)
++ * Peter Tiedemann (ptiedem at de.ibm.com)
++ * MPC additions :
++ * Belinda Thompson (belindat at us.ibm.com)
++ * Andy Richter (richtera at us.ibm.com)
++ */
++
++#undef DEBUG
++#undef DEBUGDATA
++#undef DEBUGCCW
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/timer.h>
++#include <linux/bitops.h>
++
++#include <linux/signal.h>
++#include <linux/string.h>
++
++#include <linux/ip.h>
++#include <linux/if_arp.h>
++#include <linux/tcp.h>
++#include <linux/skbuff.h>
++#include <linux/ctype.h>
++#include <net/dst.h>
++
++#include <linux/io.h>
++#include <asm/ccwdev.h>
++#include <asm/ccwgroup.h>
++#include <linux/uaccess.h>
++
++#include <asm/idals.h>
++
++#include "fsm.h"
++#include "cu3088.h"
++
++#include "ctcm_dbug.h"
++#include "ctcm_main.h"
++#include "ctcm_fsms.h"
++
++const char *dev_state_names[] = {
++ [DEV_STATE_STOPPED] = "Stopped",
++ [DEV_STATE_STARTWAIT_RXTX] = "StartWait RXTX",
++ [DEV_STATE_STARTWAIT_RX] = "StartWait RX",
++ [DEV_STATE_STARTWAIT_TX] = "StartWait TX",
++ [DEV_STATE_STOPWAIT_RXTX] = "StopWait RXTX",
++ [DEV_STATE_STOPWAIT_RX] = "StopWait RX",
++ [DEV_STATE_STOPWAIT_TX] = "StopWait TX",
++ [DEV_STATE_RUNNING] = "Running",
++};
++
++const char *dev_event_names[] = {
++ [DEV_EVENT_START] = "Start",
++ [DEV_EVENT_STOP] = "Stop",
++ [DEV_EVENT_RXUP] = "RX up",
++ [DEV_EVENT_TXUP] = "TX up",
++ [DEV_EVENT_RXDOWN] = "RX down",
++ [DEV_EVENT_TXDOWN] = "TX down",
++ [DEV_EVENT_RESTART] = "Restart",
++};
++
++const char *ctc_ch_event_names[] = {
++ [CTC_EVENT_IO_SUCCESS] = "ccw_device success",
++ [CTC_EVENT_IO_EBUSY] = "ccw_device busy",
++ [CTC_EVENT_IO_ENODEV] = "ccw_device enodev",
++ [CTC_EVENT_IO_UNKNOWN] = "ccw_device unknown",
++ [CTC_EVENT_ATTNBUSY] = "Status ATTN & BUSY",
++ [CTC_EVENT_ATTN] = "Status ATTN",
++ [CTC_EVENT_BUSY] = "Status BUSY",
++ [CTC_EVENT_UC_RCRESET] = "Unit check remote reset",
++ [CTC_EVENT_UC_RSRESET] = "Unit check remote system reset",
++ [CTC_EVENT_UC_TXTIMEOUT] = "Unit check TX timeout",
++ [CTC_EVENT_UC_TXPARITY] = "Unit check TX parity",
++ [CTC_EVENT_UC_HWFAIL] = "Unit check Hardware failure",
++ [CTC_EVENT_UC_RXPARITY] = "Unit check RX parity",
++ [CTC_EVENT_UC_ZERO] = "Unit check ZERO",
++ [CTC_EVENT_UC_UNKNOWN] = "Unit check Unknown",
++ [CTC_EVENT_SC_UNKNOWN] = "SubChannel check Unknown",
++ [CTC_EVENT_MC_FAIL] = "Machine check failure",
++ [CTC_EVENT_MC_GOOD] = "Machine check operational",
++ [CTC_EVENT_IRQ] = "IRQ normal",
++ [CTC_EVENT_FINSTAT] = "IRQ final",
++ [CTC_EVENT_TIMER] = "Timer",
++ [CTC_EVENT_START] = "Start",
++ [CTC_EVENT_STOP] = "Stop",
++ /*
++ * additional MPC events
++ */
++ [CTC_EVENT_SEND_XID] = "XID Exchange",
++ [CTC_EVENT_RSWEEP_TIMER] = "MPC Group Sweep Timer",
++};
++
++const char *ctc_ch_state_names[] = {
++ [CTC_STATE_IDLE] = "Idle",
++ [CTC_STATE_STOPPED] = "Stopped",
++ [CTC_STATE_STARTWAIT] = "StartWait",
++ [CTC_STATE_STARTRETRY] = "StartRetry",
++ [CTC_STATE_SETUPWAIT] = "SetupWait",
++ [CTC_STATE_RXINIT] = "RX init",
++ [CTC_STATE_TXINIT] = "TX init",
++ [CTC_STATE_RX] = "RX",
++ [CTC_STATE_TX] = "TX",
++ [CTC_STATE_RXIDLE] = "RX idle",
++ [CTC_STATE_TXIDLE] = "TX idle",
++ [CTC_STATE_RXERR] = "RX error",
++ [CTC_STATE_TXERR] = "TX error",
++ [CTC_STATE_TERM] = "Terminating",
++ [CTC_STATE_DTERM] = "Restarting",
++ [CTC_STATE_NOTOP] = "Not operational",
++ /*
++ * additional MPC states
++ */
++ [CH_XID0_PENDING] = "Pending XID0 Start",
++ [CH_XID0_INPROGRESS] = "In XID0 Negotiations ",
++ [CH_XID7_PENDING] = "Pending XID7 P1 Start",
++ [CH_XID7_PENDING1] = "Active XID7 P1 Exchange ",
++ [CH_XID7_PENDING2] = "Pending XID7 P2 Start ",
++ [CH_XID7_PENDING3] = "Active XID7 P2 Exchange ",
++ [CH_XID7_PENDING4] = "XID7 Complete - Pending READY ",
++};
++
++static void ctcm_action_nop(fsm_instance *fi, int event, void *arg);
++
++/*
++ * ----- static ctcm actions for channel statemachine -----
++ *
++*/
++static void chx_txdone(fsm_instance *fi, int event, void *arg);
++static void chx_rx(fsm_instance *fi, int event, void *arg);
++static void chx_rxidle(fsm_instance *fi, int event, void *arg);
++static void chx_firstio(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_setmode(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_start(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_haltio(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_stopped(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_stop(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_fail(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_setuperr(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_restart(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_rxiniterr(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_rxinitfail(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_rxdisc(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_txiniterr(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_txretry(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_iofatal(fsm_instance *fi, int event, void *arg);
++
++/*
++ * ----- static ctcmpc actions for ctcmpc channel statemachine -----
++ *
++*/
++static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg);
++static void ctcmpc_chx_rx(fsm_instance *fi, int event, void *arg);
++static void ctcmpc_chx_firstio(fsm_instance *fi, int event, void *arg);
++/* shared :
++static void ctcm_chx_setmode(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_start(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_haltio(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_stopped(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_stop(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_fail(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_setuperr(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_restart(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_rxiniterr(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_rxinitfail(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_rxdisc(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_txiniterr(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_txretry(fsm_instance *fi, int event, void *arg);
++static void ctcm_chx_iofatal(fsm_instance *fi, int event, void *arg);
++*/
++static void ctcmpc_chx_attn(fsm_instance *fsm, int event, void *arg);
++static void ctcmpc_chx_attnbusy(fsm_instance *, int, void *);
++static void ctcmpc_chx_resend(fsm_instance *, int, void *);
++static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg);
++
++/**
++ * Check return code of a preceeding ccw_device call, halt_IO etc...
++ *
++ * ch : The channel, the error belongs to.
++ * Returns the error code (!= 0) to inspect.
++ */
++void ctcm_ccw_check_rc(struct channel *ch, int rc, char *msg)
++{
++ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
++ "ccw error %s (%s): %04x\n", ch->id, msg, rc);
++ switch (rc) {
++ case -EBUSY:
++ ctcm_pr_warn("%s (%s): Busy !\n", ch->id, msg);
++ fsm_event(ch->fsm, CTC_EVENT_IO_EBUSY, ch);
++ break;
++ case -ENODEV:
++ ctcm_pr_emerg("%s (%s): Invalid device called for IO\n",
++ ch->id, msg);
++ fsm_event(ch->fsm, CTC_EVENT_IO_ENODEV, ch);
++ break;
++ default:
++ ctcm_pr_emerg("%s (%s): Unknown error in do_IO %04x\n",
++ ch->id, msg, rc);
++ fsm_event(ch->fsm, CTC_EVENT_IO_UNKNOWN, ch);
++ }
++}
++
++void ctcm_purge_skb_queue(struct sk_buff_head *q)
++{
++ struct sk_buff *skb;
++
++ CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
++
++ while ((skb = skb_dequeue(q))) {
++ atomic_dec(&skb->users);
++ dev_kfree_skb_any(skb);
++ }
++}
++
++/**
++ * NOP action for statemachines
++ */
++static void ctcm_action_nop(fsm_instance *fi, int event, void *arg)
++{
++}
++
++/*
++ * Actions for channel - statemachines.
++ */
++
++/**
++ * Normal data has been send. Free the corresponding
++ * skb (it's in io_queue), reset dev->tbusy and
++ * revert to idle state.
++ *
++ * fi An instance of a channel statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from channel * upon call.
++ */
++static void chx_txdone(fsm_instance *fi, int event, void *arg)
++{
++ struct channel *ch = arg;
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++ struct sk_buff *skb;
++ int first = 1;
++ int i;
++ unsigned long duration;
++ struct timespec done_stamp = current_kernel_time(); /* xtime */
++
++ duration =
++ (done_stamp.tv_sec - ch->prof.send_stamp.tv_sec) * 1000000 +
++ (done_stamp.tv_nsec - ch->prof.send_stamp.tv_nsec) / 1000;
++ if (duration > ch->prof.tx_time)
++ ch->prof.tx_time = duration;
++
++ if (ch->irb->scsw.count != 0)
++ ctcm_pr_debug("%s: TX not complete, remaining %d bytes\n",
++ dev->name, ch->irb->scsw.count);
++ fsm_deltimer(&ch->timer);
++ while ((skb = skb_dequeue(&ch->io_queue))) {
++ priv->stats.tx_packets++;
++ priv->stats.tx_bytes += skb->len - LL_HEADER_LENGTH;
++ if (first) {
++ priv->stats.tx_bytes += 2;
++ first = 0;
++ }
++ atomic_dec(&skb->users);
++ dev_kfree_skb_irq(skb);
++ }
++ spin_lock(&ch->collect_lock);
++ clear_normalized_cda(&ch->ccw[4]);
++ if (ch->collect_len > 0) {
++ int rc;
++
++ if (ctcm_checkalloc_buffer(ch)) {
++ spin_unlock(&ch->collect_lock);
++ return;
++ }
++ ch->trans_skb->data = ch->trans_skb_data;
++ skb_reset_tail_pointer(ch->trans_skb);
++ ch->trans_skb->len = 0;
++ if (ch->prof.maxmulti < (ch->collect_len + 2))
++ ch->prof.maxmulti = ch->collect_len + 2;
++ if (ch->prof.maxcqueue < skb_queue_len(&ch->collect_queue))
++ ch->prof.maxcqueue = skb_queue_len(&ch->collect_queue);
++ *((__u16 *)skb_put(ch->trans_skb, 2)) = ch->collect_len + 2;
++ i = 0;
++ while ((skb = skb_dequeue(&ch->collect_queue))) {
++ skb_copy_from_linear_data(skb,
++ skb_put(ch->trans_skb, skb->len), skb->len);
++ priv->stats.tx_packets++;
++ priv->stats.tx_bytes += skb->len - LL_HEADER_LENGTH;
++ atomic_dec(&skb->users);
++ dev_kfree_skb_irq(skb);
++ i++;
++ }
++ ch->collect_len = 0;
++ spin_unlock(&ch->collect_lock);
++ ch->ccw[1].count = ch->trans_skb->len;
++ fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
++ ch->prof.send_stamp = current_kernel_time(); /* xtime */
++ rc = ccw_device_start(ch->cdev, &ch->ccw[0],
++ (unsigned long)ch, 0xff, 0);
++ ch->prof.doios_multi++;
++ if (rc != 0) {
++ priv->stats.tx_dropped += i;
++ priv->stats.tx_errors += i;
++ fsm_deltimer(&ch->timer);
++ ctcm_ccw_check_rc(ch, rc, "chained TX");
++ }
++ } else {
++ spin_unlock(&ch->collect_lock);
++ fsm_newstate(fi, CTC_STATE_TXIDLE);
++ }
++ ctcm_clear_busy_do(dev);
++}
++
++/**
++ * Initial data is sent.
++ * Notify device statemachine that we are up and
++ * running.
++ *
++ * fi An instance of a channel statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from channel * upon call.
++ */
++void ctcm_chx_txidle(fsm_instance *fi, int event, void *arg)
++{
++ struct channel *ch = arg;
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++
++ CTCM_DBF_TEXT(TRACE, 6, __FUNCTION__);
++ fsm_deltimer(&ch->timer);
++ fsm_newstate(fi, CTC_STATE_TXIDLE);
++ fsm_event(priv->fsm, DEV_EVENT_TXUP, ch->netdev);
++}
++
++/**
++ * Got normal data, check for sanity, queue it up, allocate new buffer
++ * trigger bottom half, and initiate next read.
++ *
++ * fi An instance of a channel statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from channel * upon call.
++ */
++static void chx_rx(fsm_instance *fi, int event, void *arg)
++{
++ struct channel *ch = arg;
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++ int len = ch->max_bufsize - ch->irb->scsw.count;
++ struct sk_buff *skb = ch->trans_skb;
++ __u16 block_len = *((__u16 *)skb->data);
++ int check_len;
++ int rc;
++
++ fsm_deltimer(&ch->timer);
++ if (len < 8) {
++ ctcm_pr_debug("%s: got packet with length %d < 8\n",
++ dev->name, len);
++ priv->stats.rx_dropped++;
++ priv->stats.rx_length_errors++;
++ goto again;
++ }
++ if (len > ch->max_bufsize) {
++ ctcm_pr_debug("%s: got packet with length %d > %d\n",
++ dev->name, len, ch->max_bufsize);
++ priv->stats.rx_dropped++;
++ priv->stats.rx_length_errors++;
++ goto again;
++ }
++
++ /*
++ * VM TCP seems to have a bug sending 2 trailing bytes of garbage.
++ */
++ switch (ch->protocol) {
++ case CTCM_PROTO_S390:
++ case CTCM_PROTO_OS390:
++ check_len = block_len + 2;
++ break;
++ default:
++ check_len = block_len;
++ break;
++ }
++ if ((len < block_len) || (len > check_len)) {
++ ctcm_pr_debug("%s: got block length %d != rx length %d\n",
++ dev->name, block_len, len);
++ if (do_debug)
++ ctcmpc_dump_skb(skb, 0);
++
++ *((__u16 *)skb->data) = len;
++ priv->stats.rx_dropped++;
++ priv->stats.rx_length_errors++;
++ goto again;
++ }
++ block_len -= 2;
++ if (block_len > 0) {
++ *((__u16 *)skb->data) = block_len;
++ ctcm_unpack_skb(ch, skb);
++ }
++ again:
++ skb->data = ch->trans_skb_data;
++ skb_reset_tail_pointer(skb);
++ skb->len = 0;
++ if (ctcm_checkalloc_buffer(ch))
++ return;
++ ch->ccw[1].count = ch->max_bufsize;
++ rc = ccw_device_start(ch->cdev, &ch->ccw[0],
++ (unsigned long)ch, 0xff, 0);
++ if (rc != 0)
++ ctcm_ccw_check_rc(ch, rc, "normal RX");
++}
++
++/**
++ * Initialize connection by sending a __u16 of value 0.
++ *
++ * fi An instance of a channel statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from channel * upon call.
++ */
++static void chx_firstio(fsm_instance *fi, int event, void *arg)
++{
++ struct channel *ch = arg;
++ int rc;
++
++ CTCM_DBF_TEXT(TRACE, 6, __FUNCTION__);
++
++ if (fsm_getstate(fi) == CTC_STATE_TXIDLE)
++ ctcm_pr_debug("%s: remote side issued READ?, init.\n", ch->id);
++ fsm_deltimer(&ch->timer);
++ if (ctcm_checkalloc_buffer(ch))
++ return;
++ if ((fsm_getstate(fi) == CTC_STATE_SETUPWAIT) &&
++ (ch->protocol == CTCM_PROTO_OS390)) {
++ /* OS/390 resp. z/OS */
++ if (CHANNEL_DIRECTION(ch->flags) == READ) {
++ *((__u16 *)ch->trans_skb->data) = CTCM_INITIAL_BLOCKLEN;
++ fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC,
++ CTC_EVENT_TIMER, ch);
++ chx_rxidle(fi, event, arg);
++ } else {
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++ fsm_newstate(fi, CTC_STATE_TXIDLE);
++ fsm_event(priv->fsm, DEV_EVENT_TXUP, dev);
++ }
++ return;
++ }
++
++ /*
++ * Don't setup a timer for receiving the initial RX frame
++ * if in compatibility mode, since VM TCP delays the initial
++ * frame until it has some data to send.
++ */
++ if ((CHANNEL_DIRECTION(ch->flags) == WRITE) ||
++ (ch->protocol != CTCM_PROTO_S390))
++ fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
++
++ *((__u16 *)ch->trans_skb->data) = CTCM_INITIAL_BLOCKLEN;
++ ch->ccw[1].count = 2; /* Transfer only length */
++
++ fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == READ)
++ ? CTC_STATE_RXINIT : CTC_STATE_TXINIT);
++ rc = ccw_device_start(ch->cdev, &ch->ccw[0],
++ (unsigned long)ch, 0xff, 0);
++ if (rc != 0) {
++ fsm_deltimer(&ch->timer);
++ fsm_newstate(fi, CTC_STATE_SETUPWAIT);
++ ctcm_ccw_check_rc(ch, rc, "init IO");
++ }
++ /*
++ * If in compatibility mode since we don't setup a timer, we
++ * also signal RX channel up immediately. This enables us
++ * to send packets early which in turn usually triggers some
++ * reply from VM TCP which brings up the RX channel to it's
++ * final state.
++ */
++ if ((CHANNEL_DIRECTION(ch->flags) == READ) &&
++ (ch->protocol == CTCM_PROTO_S390)) {
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++ fsm_event(priv->fsm, DEV_EVENT_RXUP, dev);
++ }
++}
++
++/**
++ * Got initial data, check it. If OK,
++ * notify device statemachine that we are up and
++ * running.
++ *
++ * fi An instance of a channel statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from channel * upon call.
++ */
++static void chx_rxidle(fsm_instance *fi, int event, void *arg)
++{
++ struct channel *ch = arg;
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++ __u16 buflen;
++ int rc;
++
++ CTCM_DBF_TEXT(TRACE, 6, __FUNCTION__);
++ fsm_deltimer(&ch->timer);
++ buflen = *((__u16 *)ch->trans_skb->data);
++ if (do_debug)
++ ctcm_pr_debug("%s: Initial RX count %d\n", dev->name, buflen);
++
++ if (buflen >= CTCM_INITIAL_BLOCKLEN) {
++ if (ctcm_checkalloc_buffer(ch))
++ return;
++ ch->ccw[1].count = ch->max_bufsize;
++ fsm_newstate(fi, CTC_STATE_RXIDLE);
++ rc = ccw_device_start(ch->cdev, &ch->ccw[0],
++ (unsigned long)ch, 0xff, 0);
++ if (rc != 0) {
++ fsm_newstate(fi, CTC_STATE_RXINIT);
++ ctcm_ccw_check_rc(ch, rc, "initial RX");
++ } else
++ fsm_event(priv->fsm, DEV_EVENT_RXUP, dev);
++ } else {
++ if (do_debug)
++ ctcm_pr_debug("%s: Initial RX count %d not %d\n",
++ dev->name, buflen, CTCM_INITIAL_BLOCKLEN);
++ chx_firstio(fi, event, arg);
++ }
++}
++
++/**
++ * Set channel into extended mode.
++ *
++ * fi An instance of a channel statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_setmode(fsm_instance *fi, int event, void *arg)
++{
++ struct channel *ch = arg;
++ int rc;
++ unsigned long saveflags = 0;
++ int timeout = CTCM_TIME_5_SEC;
++
++ fsm_deltimer(&ch->timer);
++ if (IS_MPC(ch)) {
++ timeout = 1500;
++ if (do_debug)
++ ctcm_pr_debug("ctcm enter: %s(): cp=%i ch=0x%p id=%s\n",
++ __FUNCTION__, smp_processor_id(), ch, ch->id);
++ }
++ fsm_addtimer(&ch->timer, timeout, CTC_EVENT_TIMER, ch);
++ fsm_newstate(fi, CTC_STATE_SETUPWAIT);
++ if (do_debug_ccw && IS_MPC(ch))
++ ctcmpc_dumpit((char *)&ch->ccw[6], sizeof(struct ccw1) * 2);
++
++ if (event == CTC_EVENT_TIMER) /* only for timer not yet locked */
++ spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
++ /* Such conditional locking is undeterministic in
++ * static view. => ignore sparse warnings here. */
++
++ rc = ccw_device_start(ch->cdev, &ch->ccw[6],
++ (unsigned long)ch, 0xff, 0);
++ if (event == CTC_EVENT_TIMER) /* see above comments */
++ spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
++ if (rc != 0) {
++ fsm_deltimer(&ch->timer);
++ fsm_newstate(fi, CTC_STATE_STARTWAIT);
++ ctcm_ccw_check_rc(ch, rc, "set Mode");
++ } else
++ ch->retry = 0;
++}
++
++/**
++ * Setup channel.
++ *
++ * fi An instance of a channel statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_start(fsm_instance *fi, int event, void *arg)
++{
++ struct channel *ch = arg;
++ int rc;
++ struct net_device *dev;
++ unsigned long saveflags;
++
++ CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__);
++ if (ch == NULL) {
++ ctcm_pr_warn("chx_start ch=NULL\n");
++ return;
++ }
++ if (ch->netdev == NULL) {
++ ctcm_pr_warn("chx_start dev=NULL, id=%s\n", ch->id);
++ return;
++ }
++ dev = ch->netdev;
++
++ if (do_debug)
++ ctcm_pr_debug("%s: %s channel start\n", dev->name,
++ (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
++
++ if (ch->trans_skb != NULL) {
++ clear_normalized_cda(&ch->ccw[1]);
++ dev_kfree_skb(ch->trans_skb);
++ ch->trans_skb = NULL;
++ }
++ if (CHANNEL_DIRECTION(ch->flags) == READ) {
++ ch->ccw[1].cmd_code = CCW_CMD_READ;
++ ch->ccw[1].flags = CCW_FLAG_SLI;
++ ch->ccw[1].count = 0;
++ } else {
++ ch->ccw[1].cmd_code = CCW_CMD_WRITE;
++ ch->ccw[1].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
++ ch->ccw[1].count = 0;
++ }
++ if (ctcm_checkalloc_buffer(ch)) {
++ ctcm_pr_notice("%s: %s trans_skb allocation delayed "
++ "until first transfer\n", dev->name,
++ (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
++ }
++
++ ch->ccw[0].cmd_code = CCW_CMD_PREPARE;
++ ch->ccw[0].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
++ ch->ccw[0].count = 0;
++ ch->ccw[0].cda = 0;
++ ch->ccw[2].cmd_code = CCW_CMD_NOOP; /* jointed CE + DE */
++ ch->ccw[2].flags = CCW_FLAG_SLI;
++ ch->ccw[2].count = 0;
++ ch->ccw[2].cda = 0;
++ memcpy(&ch->ccw[3], &ch->ccw[0], sizeof(struct ccw1) * 3);
++ ch->ccw[4].cda = 0;
++ ch->ccw[4].flags &= ~CCW_FLAG_IDA;
++
++ fsm_newstate(fi, CTC_STATE_STARTWAIT);
++ fsm_addtimer(&ch->timer, 1000, CTC_EVENT_TIMER, ch);
++ spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
++ rc = ccw_device_halt(ch->cdev, (unsigned long)ch);
++ spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
++ if (rc != 0) {
++ if (rc != -EBUSY)
++ fsm_deltimer(&ch->timer);
++ ctcm_ccw_check_rc(ch, rc, "initial HaltIO");
++ }
++}
++
++/**
++ * Shutdown a channel.
++ *
++ * fi An instance of a channel statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_haltio(fsm_instance *fi, int event, void *arg)
++{
++ struct channel *ch = arg;
++ unsigned long saveflags = 0;
++ int rc;
++ int oldstate;
++
++ CTCM_DBF_TEXT(TRACE, 2, __FUNCTION__);
++ fsm_deltimer(&ch->timer);
++ if (IS_MPC(ch))
++ fsm_deltimer(&ch->sweep_timer);
++
++ fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
++
++ if (event == CTC_EVENT_STOP) /* only for STOP not yet locked */
++ spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
++ /* Such conditional locking is undeterministic in
++ * static view. => ignore sparse warnings here. */
++ oldstate = fsm_getstate(fi);
++ fsm_newstate(fi, CTC_STATE_TERM);
++ rc = ccw_device_halt(ch->cdev, (unsigned long)ch);
++
++ if (event == CTC_EVENT_STOP)
++ spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
++ /* see remark above about conditional locking */
++
++ if (rc != 0 && rc != -EBUSY) {
++ fsm_deltimer(&ch->timer);
++ if (event != CTC_EVENT_STOP) {
++ fsm_newstate(fi, oldstate);
++ ctcm_ccw_check_rc(ch, rc, (char *)__FUNCTION__);
++ }
++ }
++}
++
++/**
++ * Cleanup helper for chx_fail and chx_stopped
++ * cleanup channels queue and notify interface statemachine.
++ *
++ * fi An instance of a channel statemachine.
++ * state The next state (depending on caller).
++ * ch The channel to operate on.
++ */
++static void ctcm_chx_cleanup(fsm_instance *fi, int state,
++ struct channel *ch)
++{
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++
++ CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
++
++ fsm_deltimer(&ch->timer);
++ if (IS_MPC(ch))
++ fsm_deltimer(&ch->sweep_timer);
++
++ fsm_newstate(fi, state);
++ if (state == CTC_STATE_STOPPED && ch->trans_skb != NULL) {
++ clear_normalized_cda(&ch->ccw[1]);
++ dev_kfree_skb_any(ch->trans_skb);
++ ch->trans_skb = NULL;
++ }
++
++ ch->th_seg = 0x00;
++ ch->th_seq_num = 0x00;
++ if (CHANNEL_DIRECTION(ch->flags) == READ) {
++ skb_queue_purge(&ch->io_queue);
++ fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
++ } else {
++ ctcm_purge_skb_queue(&ch->io_queue);
++ if (IS_MPC(ch))
++ ctcm_purge_skb_queue(&ch->sweep_queue);
++ spin_lock(&ch->collect_lock);
++ ctcm_purge_skb_queue(&ch->collect_queue);
++ ch->collect_len = 0;
++ spin_unlock(&ch->collect_lock);
++ fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
++ }
++}
++
++/**
++ * A channel has successfully been halted.
++ * Cleanup it's queue and notify interface statemachine.
++ *
++ * fi An instance of a channel statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_stopped(fsm_instance *fi, int event, void *arg)
++{
++ CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
++ ctcm_chx_cleanup(fi, CTC_STATE_STOPPED, arg);
++}
++
++/**
++ * A stop command from device statemachine arrived and we are in
++ * not operational mode. Set state to stopped.
++ *
++ * fi An instance of a channel statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_stop(fsm_instance *fi, int event, void *arg)
++{
++ fsm_newstate(fi, CTC_STATE_STOPPED);
++}
++
++/**
++ * A machine check for no path, not operational status or gone device has
++ * happened.
++ * Cleanup queue and notify interface statemachine.
++ *
++ * fi An instance of a channel statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_fail(fsm_instance *fi, int event, void *arg)
++{
++ CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
++ ctcm_chx_cleanup(fi, CTC_STATE_NOTOP, arg);
++}
++
++/**
++ * Handle error during setup of channel.
++ *
++ * fi An instance of a channel statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_setuperr(fsm_instance *fi, int event, void *arg)
++{
++ struct channel *ch = arg;
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++
++ /*
++ * Special case: Got UC_RCRESET on setmode.
++ * This means that remote side isn't setup. In this case
++ * simply retry after some 10 secs...
++ */
++ if ((fsm_getstate(fi) == CTC_STATE_SETUPWAIT) &&
++ ((event == CTC_EVENT_UC_RCRESET) ||
++ (event == CTC_EVENT_UC_RSRESET))) {
++ fsm_newstate(fi, CTC_STATE_STARTRETRY);
++ fsm_deltimer(&ch->timer);
++ fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
++ if (!IS_MPC(ch) && (CHANNEL_DIRECTION(ch->flags) == READ)) {
++ int rc = ccw_device_halt(ch->cdev, (unsigned long)ch);
++ if (rc != 0)
++ ctcm_ccw_check_rc(ch, rc,
++ "HaltIO in chx_setuperr");
++ }
++ return;
++ }
++
++ CTCM_DBF_TEXT_(ERROR, CTC_DBF_CRIT,
++ "%s : %s error during %s channel setup state=%s\n",
++ dev->name, ctc_ch_event_names[event],
++ (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX",
++ fsm_getstate_str(fi));
++
++ if (CHANNEL_DIRECTION(ch->flags) == READ) {
++ fsm_newstate(fi, CTC_STATE_RXERR);
++ fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
++ } else {
++ fsm_newstate(fi, CTC_STATE_TXERR);
++ fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
++ }
++}
++
++/**
++ * Restart a channel after an error.
++ *
++ * fi An instance of a channel statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_restart(fsm_instance *fi, int event, void *arg)
++{
++ struct channel *ch = arg;
++ struct net_device *dev = ch->netdev;
++ unsigned long saveflags = 0;
++ int oldstate;
++ int rc;
++
++ CTCM_DBF_TEXT(TRACE, CTC_DBF_NOTICE, __FUNCTION__);
++ fsm_deltimer(&ch->timer);
++ ctcm_pr_debug("%s: %s channel restart\n", dev->name,
++ (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
++ fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
++ oldstate = fsm_getstate(fi);
++ fsm_newstate(fi, CTC_STATE_STARTWAIT);
++ if (event == CTC_EVENT_TIMER) /* only for timer not yet locked */
++ spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
++ /* Such conditional locking is a known problem for
++ * sparse because its undeterministic in static view.
++ * Warnings should be ignored here. */
++ rc = ccw_device_halt(ch->cdev, (unsigned long)ch);
++ if (event == CTC_EVENT_TIMER)
++ spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
++ if (rc != 0) {
++ if (rc != -EBUSY) {
++ fsm_deltimer(&ch->timer);
++ fsm_newstate(fi, oldstate);
++ }
++ ctcm_ccw_check_rc(ch, rc, "HaltIO in ctcm_chx_restart");
++ }
++}
++
++/**
++ * Handle error during RX initial handshake (exchange of
++ * 0-length block header)
++ *
++ * fi An instance of a channel statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_rxiniterr(fsm_instance *fi, int event, void *arg)
++{
++ struct channel *ch = arg;
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++
++ CTCM_DBF_TEXT(SETUP, 3, __FUNCTION__);
++ if (event == CTC_EVENT_TIMER) {
++ if (!IS_MPCDEV(dev))
++ /* TODO : check if MPC deletes timer somewhere */
++ fsm_deltimer(&ch->timer);
++ ctcm_pr_debug("%s: Timeout during RX init handshake\n",
++ dev->name);
++ if (ch->retry++ < 3)
++ ctcm_chx_restart(fi, event, arg);
++ else {
++ fsm_newstate(fi, CTC_STATE_RXERR);
++ fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
++ }
++ } else
++ ctcm_pr_warn("%s: Error during RX init handshake\n", dev->name);
++}
++
++/**
++ * Notify device statemachine if we gave up initialization
++ * of RX channel.
++ *
++ * fi An instance of a channel statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_rxinitfail(fsm_instance *fi, int event, void *arg)
++{
++ struct channel *ch = arg;
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++
++ CTCM_DBF_TEXT(SETUP, 3, __FUNCTION__);
++ fsm_newstate(fi, CTC_STATE_RXERR);
++ ctcm_pr_warn("%s: RX busy. Initialization failed\n", dev->name);
++ fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
++}
++
++/**
++ * Handle RX Unit check remote reset (remote disconnected)
++ *
++ * fi An instance of a channel statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_rxdisc(fsm_instance *fi, int event, void *arg)
++{
++ struct channel *ch = arg;
++ struct channel *ch2;
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++
++ CTCM_DBF_DEV_NAME(TRACE, dev, "Got remote disconnect, re-initializing");
++ fsm_deltimer(&ch->timer);
++ if (do_debug)
++ ctcm_pr_debug("%s: Got remote disconnect, "
++ "re-initializing ...\n", dev->name);
++ /*
++ * Notify device statemachine
++ */
++ fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
++ fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
++
++ fsm_newstate(fi, CTC_STATE_DTERM);
++ ch2 = priv->channel[WRITE];
++ fsm_newstate(ch2->fsm, CTC_STATE_DTERM);
++
++ ccw_device_halt(ch->cdev, (unsigned long)ch);
++ ccw_device_halt(ch2->cdev, (unsigned long)ch2);
++}
++
++/**
++ * Handle error during TX channel initialization.
++ *
++ * fi An instance of a channel statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_txiniterr(fsm_instance *fi, int event, void *arg)
++{
++ struct channel *ch = arg;
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++
++ if (event == CTC_EVENT_TIMER) {
++ fsm_deltimer(&ch->timer);
++ CTCM_DBF_DEV_NAME(ERROR, dev,
++ "Timeout during TX init handshake");
++ if (ch->retry++ < 3)
++ ctcm_chx_restart(fi, event, arg);
++ else {
++ fsm_newstate(fi, CTC_STATE_TXERR);
++ fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
++ }
++ } else {
++ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
++ "%s : %s error during channel setup state=%s",
++ dev->name, ctc_ch_event_names[event],
++ fsm_getstate_str(fi));
++
++ ctcm_pr_warn("%s: Error during TX init handshake\n", dev->name);
++ }
++}
++
++/**
++ * Handle TX timeout by retrying operation.
++ *
++ * fi An instance of a channel statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_txretry(fsm_instance *fi, int event, void *arg)
++{
++ struct channel *ch = arg;
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++ struct sk_buff *skb;
++
++ if (do_debug)
++ ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
++ __FUNCTION__, smp_processor_id(), ch, ch->id);
++
++ fsm_deltimer(&ch->timer);
++ if (ch->retry++ > 3) {
++ struct mpc_group *gptr = priv->mpcg;
++ ctcm_pr_debug("%s: TX retry failed, restarting channel\n",
++ dev->name);
++ fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
++ /* call restart if not MPC or if MPC and mpcg fsm is ready.
++ use gptr as mpc indicator */
++ if (!(gptr && (fsm_getstate(gptr->fsm) != MPCG_STATE_READY)))
++ ctcm_chx_restart(fi, event, arg);
++ goto done;
++ }
++
++ ctcm_pr_debug("%s: TX retry %d\n", dev->name, ch->retry);
++ skb = skb_peek(&ch->io_queue);
++ if (skb) {
++ int rc = 0;
++ unsigned long saveflags = 0;
++ clear_normalized_cda(&ch->ccw[4]);
++ ch->ccw[4].count = skb->len;
++ if (set_normalized_cda(&ch->ccw[4], skb->data)) {
++ ctcm_pr_debug("%s: IDAL alloc failed, chan restart\n",
++ dev->name);
++ fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
++ ctcm_chx_restart(fi, event, arg);
++ goto done;
++ }
++ fsm_addtimer(&ch->timer, 1000, CTC_EVENT_TIMER, ch);
++ if (event == CTC_EVENT_TIMER) /* for TIMER not yet locked */
++ spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
++ /* Such conditional locking is a known problem for
++ * sparse because its undeterministic in static view.
++ * Warnings should be ignored here. */
++ if (do_debug_ccw)
++ ctcmpc_dumpit((char *)&ch->ccw[3],
++ sizeof(struct ccw1) * 3);
++
++ rc = ccw_device_start(ch->cdev, &ch->ccw[3],
++ (unsigned long)ch, 0xff, 0);
++ if (event == CTC_EVENT_TIMER)
++ spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev),
++ saveflags);
++ if (rc != 0) {
++ fsm_deltimer(&ch->timer);
++ ctcm_ccw_check_rc(ch, rc, "TX in chx_txretry");
++ ctcm_purge_skb_queue(&ch->io_queue);
++ }
++ }
++done:
++ return;
++}
++
++/**
++ * Handle fatal errors during an I/O command.
++ *
++ * fi An instance of a channel statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from channel * upon call.
++ */
++static void ctcm_chx_iofatal(fsm_instance *fi, int event, void *arg)
++{
++ struct channel *ch = arg;
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++
++ CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
++ fsm_deltimer(&ch->timer);
++ ctcm_pr_warn("%s %s : unrecoverable channel error\n",
++ CTC_DRIVER_NAME, dev->name);
++ if (IS_MPC(ch)) {
++ priv->stats.tx_dropped++;
++ priv->stats.tx_errors++;
++ }
++
++ if (CHANNEL_DIRECTION(ch->flags) == READ) {
++ ctcm_pr_debug("%s: RX I/O error\n", dev->name);
++ fsm_newstate(fi, CTC_STATE_RXERR);
++ fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
++ } else {
++ ctcm_pr_debug("%s: TX I/O error\n", dev->name);
++ fsm_newstate(fi, CTC_STATE_TXERR);
++ fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
++ }
++}
++
++/*
++ * The ctcm statemachine for a channel.
++ */
++const fsm_node ch_fsm[] = {
++ { CTC_STATE_STOPPED, CTC_EVENT_STOP, ctcm_action_nop },
++ { CTC_STATE_STOPPED, CTC_EVENT_START, ctcm_chx_start },
++ { CTC_STATE_STOPPED, CTC_EVENT_FINSTAT, ctcm_action_nop },
++ { CTC_STATE_STOPPED, CTC_EVENT_MC_FAIL, ctcm_action_nop },
++
++ { CTC_STATE_NOTOP, CTC_EVENT_STOP, ctcm_chx_stop },
++ { CTC_STATE_NOTOP, CTC_EVENT_START, ctcm_action_nop },
++ { CTC_STATE_NOTOP, CTC_EVENT_FINSTAT, ctcm_action_nop },
++ { CTC_STATE_NOTOP, CTC_EVENT_MC_FAIL, ctcm_action_nop },
++ { CTC_STATE_NOTOP, CTC_EVENT_MC_GOOD, ctcm_chx_start },
++
++ { CTC_STATE_STARTWAIT, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CTC_STATE_STARTWAIT, CTC_EVENT_START, ctcm_action_nop },
++ { CTC_STATE_STARTWAIT, CTC_EVENT_FINSTAT, ctcm_chx_setmode },
++ { CTC_STATE_STARTWAIT, CTC_EVENT_TIMER, ctcm_chx_setuperr },
++ { CTC_STATE_STARTWAIT, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++ { CTC_STATE_STARTWAIT, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++
++ { CTC_STATE_STARTRETRY, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CTC_STATE_STARTRETRY, CTC_EVENT_TIMER, ctcm_chx_setmode },
++ { CTC_STATE_STARTRETRY, CTC_EVENT_FINSTAT, ctcm_action_nop },
++ { CTC_STATE_STARTRETRY, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++
++ { CTC_STATE_SETUPWAIT, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CTC_STATE_SETUPWAIT, CTC_EVENT_START, ctcm_action_nop },
++ { CTC_STATE_SETUPWAIT, CTC_EVENT_FINSTAT, chx_firstio },
++ { CTC_STATE_SETUPWAIT, CTC_EVENT_UC_RCRESET, ctcm_chx_setuperr },
++ { CTC_STATE_SETUPWAIT, CTC_EVENT_UC_RSRESET, ctcm_chx_setuperr },
++ { CTC_STATE_SETUPWAIT, CTC_EVENT_TIMER, ctcm_chx_setmode },
++ { CTC_STATE_SETUPWAIT, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++ { CTC_STATE_SETUPWAIT, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++
++ { CTC_STATE_RXINIT, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CTC_STATE_RXINIT, CTC_EVENT_START, ctcm_action_nop },
++ { CTC_STATE_RXINIT, CTC_EVENT_FINSTAT, chx_rxidle },
++ { CTC_STATE_RXINIT, CTC_EVENT_UC_RCRESET, ctcm_chx_rxiniterr },
++ { CTC_STATE_RXINIT, CTC_EVENT_UC_RSRESET, ctcm_chx_rxiniterr },
++ { CTC_STATE_RXINIT, CTC_EVENT_TIMER, ctcm_chx_rxiniterr },
++ { CTC_STATE_RXINIT, CTC_EVENT_ATTNBUSY, ctcm_chx_rxinitfail },
++ { CTC_STATE_RXINIT, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++ { CTC_STATE_RXINIT, CTC_EVENT_UC_ZERO, chx_firstio },
++ { CTC_STATE_RXINIT, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++
++ { CTC_STATE_RXIDLE, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CTC_STATE_RXIDLE, CTC_EVENT_START, ctcm_action_nop },
++ { CTC_STATE_RXIDLE, CTC_EVENT_FINSTAT, chx_rx },
++ { CTC_STATE_RXIDLE, CTC_EVENT_UC_RCRESET, ctcm_chx_rxdisc },
++ { CTC_STATE_RXIDLE, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++ { CTC_STATE_RXIDLE, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++ { CTC_STATE_RXIDLE, CTC_EVENT_UC_ZERO, chx_rx },
++
++ { CTC_STATE_TXINIT, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CTC_STATE_TXINIT, CTC_EVENT_START, ctcm_action_nop },
++ { CTC_STATE_TXINIT, CTC_EVENT_FINSTAT, ctcm_chx_txidle },
++ { CTC_STATE_TXINIT, CTC_EVENT_UC_RCRESET, ctcm_chx_txiniterr },
++ { CTC_STATE_TXINIT, CTC_EVENT_UC_RSRESET, ctcm_chx_txiniterr },
++ { CTC_STATE_TXINIT, CTC_EVENT_TIMER, ctcm_chx_txiniterr },
++ { CTC_STATE_TXINIT, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++ { CTC_STATE_TXINIT, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++
++ { CTC_STATE_TXIDLE, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CTC_STATE_TXIDLE, CTC_EVENT_START, ctcm_action_nop },
++ { CTC_STATE_TXIDLE, CTC_EVENT_FINSTAT, chx_firstio },
++ { CTC_STATE_TXIDLE, CTC_EVENT_UC_RCRESET, ctcm_action_nop },
++ { CTC_STATE_TXIDLE, CTC_EVENT_UC_RSRESET, ctcm_action_nop },
++ { CTC_STATE_TXIDLE, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++ { CTC_STATE_TXIDLE, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++
++ { CTC_STATE_TERM, CTC_EVENT_STOP, ctcm_action_nop },
++ { CTC_STATE_TERM, CTC_EVENT_START, ctcm_chx_restart },
++ { CTC_STATE_TERM, CTC_EVENT_FINSTAT, ctcm_chx_stopped },
++ { CTC_STATE_TERM, CTC_EVENT_UC_RCRESET, ctcm_action_nop },
++ { CTC_STATE_TERM, CTC_EVENT_UC_RSRESET, ctcm_action_nop },
++ { CTC_STATE_TERM, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++
++ { CTC_STATE_DTERM, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CTC_STATE_DTERM, CTC_EVENT_START, ctcm_chx_restart },
++ { CTC_STATE_DTERM, CTC_EVENT_FINSTAT, ctcm_chx_setmode },
++ { CTC_STATE_DTERM, CTC_EVENT_UC_RCRESET, ctcm_action_nop },
++ { CTC_STATE_DTERM, CTC_EVENT_UC_RSRESET, ctcm_action_nop },
++ { CTC_STATE_DTERM, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++
++ { CTC_STATE_TX, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CTC_STATE_TX, CTC_EVENT_START, ctcm_action_nop },
++ { CTC_STATE_TX, CTC_EVENT_FINSTAT, chx_txdone },
++ { CTC_STATE_TX, CTC_EVENT_UC_RCRESET, ctcm_chx_txretry },
++ { CTC_STATE_TX, CTC_EVENT_UC_RSRESET, ctcm_chx_txretry },
++ { CTC_STATE_TX, CTC_EVENT_TIMER, ctcm_chx_txretry },
++ { CTC_STATE_TX, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++ { CTC_STATE_TX, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++
++ { CTC_STATE_RXERR, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CTC_STATE_TXERR, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CTC_STATE_TXERR, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++ { CTC_STATE_RXERR, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++};
++
++int ch_fsm_len = ARRAY_SIZE(ch_fsm);
++
++/*
++ * MPC actions for mpc channel statemachine
++ * handling of MPC protocol requires extra
++ * statemachine and actions which are prefixed ctcmpc_ .
++ * The ctc_ch_states and ctc_ch_state_names,
++ * ctc_ch_events and ctc_ch_event_names share the ctcm definitions
++ * which are expanded by some elements.
++ */
++
++/*
++ * Actions for mpc channel statemachine.
++ */
++
++/**
++ * Normal data has been send. Free the corresponding
++ * skb (it's in io_queue), reset dev->tbusy and
++ * revert to idle state.
++ *
++ * fi An instance of a channel statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from channel * upon call.
++ */
++static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg)
++{
++ struct channel *ch = arg;
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++ struct mpc_group *grp = priv->mpcg;
++ struct sk_buff *skb;
++ int first = 1;
++ int i;
++ struct timespec done_stamp;
++ __u32 data_space;
++ unsigned long duration;
++ struct sk_buff *peekskb;
++ int rc;
++ struct th_header *header;
++ struct pdu *p_header;
++
++ if (do_debug)
++ ctcm_pr_debug("%s cp:%i enter: %s()\n",
++ dev->name, smp_processor_id(), __FUNCTION__);
++
++ done_stamp = current_kernel_time(); /* xtime */
++ duration = (done_stamp.tv_sec - ch->prof.send_stamp.tv_sec) * 1000000
++ + (done_stamp.tv_nsec - ch->prof.send_stamp.tv_nsec) / 1000;
++ if (duration > ch->prof.tx_time)
++ ch->prof.tx_time = duration;
++
++ if (ch->irb->scsw.count != 0)
++ ctcm_pr_debug("%s: TX not complete, remaining %d bytes\n",
++ dev->name, ch->irb->scsw.count);
++ fsm_deltimer(&ch->timer);
++ while ((skb = skb_dequeue(&ch->io_queue))) {
++ priv->stats.tx_packets++;
++ priv->stats.tx_bytes += skb->len - TH_HEADER_LENGTH;
++ if (first) {
++ priv->stats.tx_bytes += 2;
++ first = 0;
++ }
++ atomic_dec(&skb->users);
++ dev_kfree_skb_irq(skb);
++ }
++ spin_lock(&ch->collect_lock);
++ clear_normalized_cda(&ch->ccw[4]);
++
++ if ((ch->collect_len <= 0) || (grp->in_sweep != 0)) {
++ spin_unlock(&ch->collect_lock);
++ fsm_newstate(fi, CTC_STATE_TXIDLE);
++ goto done;
++ }
++
++ if (ctcm_checkalloc_buffer(ch)) {
++ spin_unlock(&ch->collect_lock);
++ goto done;
++ }
++ ch->trans_skb->data = ch->trans_skb_data;
++ skb_reset_tail_pointer(ch->trans_skb);
++ ch->trans_skb->len = 0;
++ if (ch->prof.maxmulti < (ch->collect_len + TH_HEADER_LENGTH))
++ ch->prof.maxmulti = ch->collect_len + TH_HEADER_LENGTH;
++ if (ch->prof.maxcqueue < skb_queue_len(&ch->collect_queue))
++ ch->prof.maxcqueue = skb_queue_len(&ch->collect_queue);
++ i = 0;
++
++ if (do_debug_data)
++ ctcm_pr_debug("ctcmpc: %s() building "
++ "trans_skb from collect_q \n", __FUNCTION__);
++
++ data_space = grp->group_max_buflen - TH_HEADER_LENGTH;
++
++ if (do_debug_data)
++ ctcm_pr_debug("ctcmpc: %s() building trans_skb from collect_q"
++ " data_space:%04x\n", __FUNCTION__, data_space);
++ p_header = NULL;
++ while ((skb = skb_dequeue(&ch->collect_queue))) {
++ memcpy(skb_put(ch->trans_skb, skb->len), skb->data, skb->len);
++ p_header = (struct pdu *)
++ (skb_tail_pointer(ch->trans_skb) - skb->len);
++ p_header->pdu_flag = 0x00;
++ if (skb->protocol == ntohs(ETH_P_SNAP))
++ p_header->pdu_flag |= 0x60;
++ else
++ p_header->pdu_flag |= 0x20;
++
++ if (do_debug_data) {
++ ctcm_pr_debug("ctcmpc: %s()trans_skb len:%04x \n",
++ __FUNCTION__, ch->trans_skb->len);
++ ctcm_pr_debug("ctcmpc: %s() pdu header and data"
++ " for up to 32 bytes sent to vtam\n",
++ __FUNCTION__);
++ ctcmpc_dumpit((char *)p_header,
++ min_t(int, skb->len, 32));
++ }
++ ch->collect_len -= skb->len;
++ data_space -= skb->len;
++ priv->stats.tx_packets++;
++ priv->stats.tx_bytes += skb->len;
++ atomic_dec(&skb->users);
++ dev_kfree_skb_any(skb);
++ peekskb = skb_peek(&ch->collect_queue);
++ if (peekskb->len > data_space)
++ break;
++ i++;
++ }
++ /* p_header points to the last one we handled */
++ if (p_header)
++ p_header->pdu_flag |= PDU_LAST; /*Say it's the last one*/
++ header = kzalloc(TH_HEADER_LENGTH, gfp_type());
++
++ if (!header) {
++ printk(KERN_WARNING "ctcmpc: OUT OF MEMORY IN %s()"
++ ": Data Lost \n", __FUNCTION__);
++ spin_unlock(&ch->collect_lock);
++ fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
++ goto done;
++ }
++
++ header->th_ch_flag = TH_HAS_PDU; /* Normal data */
++ ch->th_seq_num++;
++ header->th_seq_num = ch->th_seq_num;
++
++ if (do_debug_data)
++ ctcm_pr_debug("%s: ToVTAM_th_seq= %08x\n" ,
++ __FUNCTION__, ch->th_seq_num);
++
++ memcpy(skb_push(ch->trans_skb, TH_HEADER_LENGTH), header,
++ TH_HEADER_LENGTH); /* put the TH on the packet */
++
++ kfree(header);
++
++ if (do_debug_data) {
++ ctcm_pr_debug("ctcmpc: %s()trans_skb len:%04x \n",
++ __FUNCTION__, ch->trans_skb->len);
++
++ ctcm_pr_debug("ctcmpc: %s() up-to-50 bytes of trans_skb "
++ "data to vtam from collect_q\n", __FUNCTION__);
++ ctcmpc_dumpit((char *)ch->trans_skb->data,
++ min_t(int, ch->trans_skb->len, 50));
++ }
++
++ spin_unlock(&ch->collect_lock);
++ clear_normalized_cda(&ch->ccw[1]);
++ if (set_normalized_cda(&ch->ccw[1], ch->trans_skb->data)) {
++ dev_kfree_skb_any(ch->trans_skb);
++ ch->trans_skb = NULL;
++ printk(KERN_WARNING
++ "ctcmpc: %s()CCW failure - data lost\n",
++ __FUNCTION__);
++ fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
++ return;
++ }
++ ch->ccw[1].count = ch->trans_skb->len;
++ fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
++ ch->prof.send_stamp = current_kernel_time(); /* xtime */
++ if (do_debug_ccw)
++ ctcmpc_dumpit((char *)&ch->ccw[0], sizeof(struct ccw1) * 3);
++ rc = ccw_device_start(ch->cdev, &ch->ccw[0],
++ (unsigned long)ch, 0xff, 0);
++ ch->prof.doios_multi++;
++ if (rc != 0) {
++ priv->stats.tx_dropped += i;
++ priv->stats.tx_errors += i;
++ fsm_deltimer(&ch->timer);
++ ctcm_ccw_check_rc(ch, rc, "chained TX");
++ }
++done:
++ ctcm_clear_busy(dev);
++ ctcm_pr_debug("ctcmpc exit: %s %s()\n", dev->name, __FUNCTION__);
++ return;
++}
++
++/**
++ * Got normal data, check for sanity, queue it up, allocate new buffer
++ * trigger bottom half, and initiate next read.
++ *
++ * fi An instance of a channel statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from channel * upon call.
++ */
++static void ctcmpc_chx_rx(fsm_instance *fi, int event, void *arg)
++{
++ struct channel *ch = arg;
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++ struct mpc_group *grp = priv->mpcg;
++ struct sk_buff *skb = ch->trans_skb;
++ struct sk_buff *new_skb;
++ unsigned long saveflags = 0; /* avoids compiler warning */
++ int len = ch->max_bufsize - ch->irb->scsw.count;
++
++ if (do_debug_data) {
++ CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG, "mpc_ch_rx %s cp:%i %s\n",
++ dev->name, smp_processor_id(), ch->id);
++ CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG, "mpc_ch_rx: maxbuf: %04x "
++ "len: %04x\n", ch->max_bufsize, len);
++ }
++ fsm_deltimer(&ch->timer);
++
++ if (skb == NULL) {
++ ctcm_pr_debug("ctcmpc exit: %s() TRANS_SKB = NULL \n",
++ __FUNCTION__);
++ goto again;
++ }
++
++ if (len < TH_HEADER_LENGTH) {
++ ctcm_pr_info("%s: got packet with invalid length %d\n",
++ dev->name, len);
++ priv->stats.rx_dropped++;
++ priv->stats.rx_length_errors++;
++ } else {
++ /* must have valid th header or game over */
++ __u32 block_len = len;
++ len = TH_HEADER_LENGTH + XID2_LENGTH + 4;
++ new_skb = __dev_alloc_skb(ch->max_bufsize, GFP_ATOMIC);
++
++ if (new_skb == NULL) {
++ printk(KERN_INFO "ctcmpc:%s() NEW_SKB = NULL\n",
++ __FUNCTION__);
++ printk(KERN_WARNING "ctcmpc: %s() MEMORY ALLOC FAILED"
++ " - DATA LOST - MPC FAILED\n",
++ __FUNCTION__);
++ fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
++ goto again;
++ }
++ switch (fsm_getstate(grp->fsm)) {
++ case MPCG_STATE_RESET:
++ case MPCG_STATE_INOP:
++ dev_kfree_skb_any(new_skb);
++ break;
++ case MPCG_STATE_FLOWC:
++ case MPCG_STATE_READY:
++ memcpy(skb_put(new_skb, block_len),
++ skb->data, block_len);
++ skb_queue_tail(&ch->io_queue, new_skb);
++ tasklet_schedule(&ch->ch_tasklet);
++ break;
++ default:
++ memcpy(skb_put(new_skb, len), skb->data, len);
++ skb_queue_tail(&ch->io_queue, new_skb);
++ tasklet_hi_schedule(&ch->ch_tasklet);
++ break;
++ }
++ }
++
++again:
++ switch (fsm_getstate(grp->fsm)) {
++ int rc, dolock;
++ case MPCG_STATE_FLOWC:
++ case MPCG_STATE_READY:
++ if (ctcm_checkalloc_buffer(ch))
++ break;
++ ch->trans_skb->data = ch->trans_skb_data;
++ skb_reset_tail_pointer(ch->trans_skb);
++ ch->trans_skb->len = 0;
++ ch->ccw[1].count = ch->max_bufsize;
++ if (do_debug_ccw)
++ ctcmpc_dumpit((char *)&ch->ccw[0],
++ sizeof(struct ccw1) * 3);
++ dolock = !in_irq();
++ if (dolock)
++ spin_lock_irqsave(
++ get_ccwdev_lock(ch->cdev), saveflags);
++ rc = ccw_device_start(ch->cdev, &ch->ccw[0],
++ (unsigned long)ch, 0xff, 0);
++ if (dolock) /* see remark about conditional locking */
++ spin_unlock_irqrestore(
++ get_ccwdev_lock(ch->cdev), saveflags);
++ if (rc != 0)
++ ctcm_ccw_check_rc(ch, rc, "normal RX");
++ default:
++ break;
++ }
++
++ if (do_debug)
++ ctcm_pr_debug("ctcmpc exit : %s %s(): ch=0x%p id=%s\n",
++ dev->name, __FUNCTION__, ch, ch->id);
++
++}
++
++/**
++ * Initialize connection by sending a __u16 of value 0.
++ *
++ * fi An instance of a channel statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from channel * upon call.
++ */
++static void ctcmpc_chx_firstio(fsm_instance *fi, int event, void *arg)
++{
++ struct channel *ch = arg;
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++
++ if (do_debug) {
++ struct mpc_group *gptr = priv->mpcg;
++ ctcm_pr_debug("ctcmpc enter: %s(): ch=0x%p id=%s\n",
++ __FUNCTION__, ch, ch->id);
++ ctcm_pr_debug("%s() %s chstate:%i grpstate:%i chprotocol:%i\n",
++ __FUNCTION__, ch->id, fsm_getstate(fi),
++ fsm_getstate(gptr->fsm), ch->protocol);
++ }
++ if (fsm_getstate(fi) == CTC_STATE_TXIDLE)
++ MPC_DBF_DEV_NAME(TRACE, dev, "remote side issued READ? ");
++
++ fsm_deltimer(&ch->timer);
++ if (ctcm_checkalloc_buffer(ch))
++ goto done;
++
++ switch (fsm_getstate(fi)) {
++ case CTC_STATE_STARTRETRY:
++ case CTC_STATE_SETUPWAIT:
++ if (CHANNEL_DIRECTION(ch->flags) == READ) {
++ ctcmpc_chx_rxidle(fi, event, arg);
++ } else {
++ fsm_newstate(fi, CTC_STATE_TXIDLE);
++ fsm_event(priv->fsm, DEV_EVENT_TXUP, dev);
++ }
++ goto done;
++ default:
++ break;
++ };
++
++ fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == READ)
++ ? CTC_STATE_RXINIT : CTC_STATE_TXINIT);
++
++done:
++ if (do_debug)
++ ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
++ __FUNCTION__, ch, ch->id);
++ return;
++}
++
++/**
++ * Got initial data, check it. If OK,
++ * notify device statemachine that we are up and
++ * running.
++ *
++ * fi An instance of a channel statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from channel * upon call.
++ */
++void ctcmpc_chx_rxidle(fsm_instance *fi, int event, void *arg)
++{
++ struct channel *ch = arg;
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++ struct mpc_group *grp = priv->mpcg;
++ int rc;
++ unsigned long saveflags = 0; /* avoids compiler warning */
++
++ fsm_deltimer(&ch->timer);
++ ctcm_pr_debug("%s cp:%i enter: %s()\n",
++ dev->name, smp_processor_id(), __FUNCTION__);
++ if (do_debug)
++ ctcm_pr_debug("%s() %s chstate:%i grpstate:%i\n",
++ __FUNCTION__, ch->id,
++ fsm_getstate(fi), fsm_getstate(grp->fsm));
++
++ fsm_newstate(fi, CTC_STATE_RXIDLE);
++ /* XID processing complete */
++
++ switch (fsm_getstate(grp->fsm)) {
++ case MPCG_STATE_FLOWC:
++ case MPCG_STATE_READY:
++ if (ctcm_checkalloc_buffer(ch))
++ goto done;
++ ch->trans_skb->data = ch->trans_skb_data;
++ skb_reset_tail_pointer(ch->trans_skb);
++ ch->trans_skb->len = 0;
++ ch->ccw[1].count = ch->max_bufsize;
++ if (do_debug_ccw)
++ ctcmpc_dumpit((char *)&ch->ccw[0],
++ sizeof(struct ccw1) * 3);
++ if (event == CTC_EVENT_START)
++ /* see remark about conditional locking */
++ spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
++ rc = ccw_device_start(ch->cdev, &ch->ccw[0],
++ (unsigned long)ch, 0xff, 0);
++ if (event == CTC_EVENT_START)
++ spin_unlock_irqrestore(
++ get_ccwdev_lock(ch->cdev), saveflags);
++ if (rc != 0) {
++ fsm_newstate(fi, CTC_STATE_RXINIT);
++ ctcm_ccw_check_rc(ch, rc, "initial RX");
++ goto done;
++ }
++ break;
++ default:
++ break;
++ }
++
++ fsm_event(priv->fsm, DEV_EVENT_RXUP, dev);
++done:
++ if (do_debug)
++ ctcm_pr_debug("ctcmpc exit: %s %s()\n",
++ dev->name, __FUNCTION__);
++ return;
++}
++
++/*
++ * ctcmpc channel FSM action
++ * called from several points in ctcmpc_ch_fsm
++ * ctcmpc only
++ */
++static void ctcmpc_chx_attn(fsm_instance *fsm, int event, void *arg)
++{
++ struct channel *ch = arg;
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++ struct mpc_group *grp = priv->mpcg;
++
++ if (do_debug) {
++ ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s"
++ "GrpState:%s ChState:%s\n",
++ __FUNCTION__, smp_processor_id(), ch, ch->id,
++ fsm_getstate_str(grp->fsm),
++ fsm_getstate_str(ch->fsm));
++ }
++
++ switch (fsm_getstate(grp->fsm)) {
++ case MPCG_STATE_XID2INITW:
++ /* ok..start yside xid exchanges */
++ if (!ch->in_mpcgroup)
++ break;
++ if (fsm_getstate(ch->fsm) == CH_XID0_PENDING) {
++ fsm_deltimer(&grp->timer);
++ fsm_addtimer(&grp->timer,
++ MPC_XID_TIMEOUT_VALUE,
++ MPCG_EVENT_TIMER, dev);
++ fsm_event(grp->fsm, MPCG_EVENT_XID0DO, ch);
++
++ } else if (fsm_getstate(ch->fsm) < CH_XID7_PENDING1)
++ /* attn rcvd before xid0 processed via bh */
++ fsm_newstate(ch->fsm, CH_XID7_PENDING1);
++ break;
++ case MPCG_STATE_XID2INITX:
++ case MPCG_STATE_XID0IOWAIT:
++ case MPCG_STATE_XID0IOWAIX:
++ /* attn rcvd before xid0 processed on ch
++ but mid-xid0 processing for group */
++ if (fsm_getstate(ch->fsm) < CH_XID7_PENDING1)
++ fsm_newstate(ch->fsm, CH_XID7_PENDING1);
++ break;
++ case MPCG_STATE_XID7INITW:
++ case MPCG_STATE_XID7INITX:
++ case MPCG_STATE_XID7INITI:
++ case MPCG_STATE_XID7INITZ:
++ switch (fsm_getstate(ch->fsm)) {
++ case CH_XID7_PENDING:
++ fsm_newstate(ch->fsm, CH_XID7_PENDING1);
++ break;
++ case CH_XID7_PENDING2:
++ fsm_newstate(ch->fsm, CH_XID7_PENDING3);
++ break;
++ }
++ fsm_event(grp->fsm, MPCG_EVENT_XID7DONE, dev);
++ break;
++ }
++
++ if (do_debug)
++ ctcm_pr_debug("ctcmpc exit : %s(): cp=%i ch=0x%p id=%s\n",
++ __FUNCTION__, smp_processor_id(), ch, ch->id);
++ return;
++
++}
++
++/*
++ * ctcmpc channel FSM action
++ * called from one point in ctcmpc_ch_fsm
++ * ctcmpc only
++ */
++static void ctcmpc_chx_attnbusy(fsm_instance *fsm, int event, void *arg)
++{
++ struct channel *ch = arg;
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++ struct mpc_group *grp = priv->mpcg;
++
++ ctcm_pr_debug("ctcmpc enter: %s %s() %s \nGrpState:%s ChState:%s\n",
++ dev->name,
++ __FUNCTION__, ch->id,
++ fsm_getstate_str(grp->fsm),
++ fsm_getstate_str(ch->fsm));
++
++ fsm_deltimer(&ch->timer);
++
++ switch (fsm_getstate(grp->fsm)) {
++ case MPCG_STATE_XID0IOWAIT:
++ /* vtam wants to be primary.start yside xid exchanges*/
++ /* only receive one attn-busy at a time so must not */
++ /* change state each time */
++ grp->changed_side = 1;
++ fsm_newstate(grp->fsm, MPCG_STATE_XID2INITW);
++ break;
++ case MPCG_STATE_XID2INITW:
++ if (grp->changed_side == 1) {
++ grp->changed_side = 2;
++ break;
++ }
++ /* process began via call to establish_conn */
++ /* so must report failure instead of reverting */
++ /* back to ready-for-xid passive state */
++ if (grp->estconnfunc)
++ goto done;
++ /* this attnbusy is NOT the result of xside xid */
++ /* collisions so yside must have been triggered */
++ /* by an ATTN that was not intended to start XID */
++ /* processing. Revert back to ready-for-xid and */
++ /* wait for ATTN interrupt to signal xid start */
++ if (fsm_getstate(ch->fsm) == CH_XID0_INPROGRESS) {
++ fsm_newstate(ch->fsm, CH_XID0_PENDING) ;
++ fsm_deltimer(&grp->timer);
++ goto done;
++ }
++ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++ goto done;
++ case MPCG_STATE_XID2INITX:
++ /* XID2 was received before ATTN Busy for second
++ channel.Send yside xid for second channel.
++ */
++ if (grp->changed_side == 1) {
++ grp->changed_side = 2;
++ break;
++ }
++ case MPCG_STATE_XID0IOWAIX:
++ case MPCG_STATE_XID7INITW:
++ case MPCG_STATE_XID7INITX:
++ case MPCG_STATE_XID7INITI:
++ case MPCG_STATE_XID7INITZ:
++ default:
++ /* multiple attn-busy indicates too out-of-sync */
++ /* and they are certainly not being received as part */
++ /* of valid mpc group negotiations.. */
++ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++ goto done;
++ }
++
++ if (grp->changed_side == 1) {
++ fsm_deltimer(&grp->timer);
++ fsm_addtimer(&grp->timer, MPC_XID_TIMEOUT_VALUE,
++ MPCG_EVENT_TIMER, dev);
++ }
++ if (ch->in_mpcgroup)
++ fsm_event(grp->fsm, MPCG_EVENT_XID0DO, ch);
++ else
++ printk(KERN_WARNING "ctcmpc: %s() Not all channels have"
++ " been added to group\n", __FUNCTION__);
++
++done:
++ if (do_debug)
++ ctcm_pr_debug("ctcmpc exit : %s()%s ch=0x%p id=%s\n",
++ __FUNCTION__, dev->name, ch, ch->id);
++
++ return;
++
++}
++
++/*
++ * ctcmpc channel FSM action
++ * called from several points in ctcmpc_ch_fsm
++ * ctcmpc only
++ */
++static void ctcmpc_chx_resend(fsm_instance *fsm, int event, void *arg)
++{
++ struct channel *ch = arg;
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++ struct mpc_group *grp = priv->mpcg;
++
++ ctcm_pr_debug("ctcmpc enter: %s %s() %s \nGrpState:%s ChState:%s\n",
++ dev->name, __FUNCTION__, ch->id,
++ fsm_getstate_str(grp->fsm),
++ fsm_getstate_str(ch->fsm));
++
++ fsm_event(grp->fsm, MPCG_EVENT_XID0DO, ch);
++
++ return;
++}
++
++/*
++ * ctcmpc channel FSM action
++ * called from several points in ctcmpc_ch_fsm
++ * ctcmpc only
++ */
++static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg)
++{
++ struct channel *ach = arg;
++ struct net_device *dev = ach->netdev;
++ struct ctcm_priv *priv = dev->priv;
++ struct mpc_group *grp = priv->mpcg;
++ struct channel *wch = priv->channel[WRITE];
++ struct channel *rch = priv->channel[READ];
++ struct sk_buff *skb;
++ struct th_sweep *header;
++ int rc = 0;
++ unsigned long saveflags = 0;
++
++ if (do_debug)
++ ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
++ __FUNCTION__, smp_processor_id(), ach, ach->id);
++
++ if (grp->in_sweep == 0)
++ goto done;
++
++ if (do_debug_data) {
++ ctcm_pr_debug("ctcmpc: %s() 1: ToVTAM_th_seq= %08x\n" ,
++ __FUNCTION__, wch->th_seq_num);
++ ctcm_pr_debug("ctcmpc: %s() 1: FromVTAM_th_seq= %08x\n" ,
++ __FUNCTION__, rch->th_seq_num);
++ }
++
++ if (fsm_getstate(wch->fsm) != CTC_STATE_TXIDLE) {
++ /* give the previous IO time to complete */
++ fsm_addtimer(&wch->sweep_timer,
++ 200, CTC_EVENT_RSWEEP_TIMER, wch);
++ goto done;
++ }
++
++ skb = skb_dequeue(&wch->sweep_queue);
++ if (!skb)
++ goto done;
++
++ if (set_normalized_cda(&wch->ccw[4], skb->data)) {
++ grp->in_sweep = 0;
++ ctcm_clear_busy_do(dev);
++ dev_kfree_skb_any(skb);
++ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++ goto done;
++ } else {
++ atomic_inc(&skb->users);
++ skb_queue_tail(&wch->io_queue, skb);
++ }
++
++ /* send out the sweep */
++ wch->ccw[4].count = skb->len;
++
++ header = (struct th_sweep *)skb->data;
++ switch (header->th.th_ch_flag) {
++ case TH_SWEEP_REQ:
++ grp->sweep_req_pend_num--;
++ break;
++ case TH_SWEEP_RESP:
++ grp->sweep_rsp_pend_num--;
++ break;
++ }
++
++ header->sw.th_last_seq = wch->th_seq_num;
++
++ if (do_debug_ccw)
++ ctcmpc_dumpit((char *)&wch->ccw[3], sizeof(struct ccw1) * 3);
++
++ ctcm_pr_debug("ctcmpc: %s() sweep packet\n", __FUNCTION__);
++ ctcmpc_dumpit((char *)header, TH_SWEEP_LENGTH);
++
++ fsm_addtimer(&wch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, wch);
++ fsm_newstate(wch->fsm, CTC_STATE_TX);
++
++ spin_lock_irqsave(get_ccwdev_lock(wch->cdev), saveflags);
++ wch->prof.send_stamp = current_kernel_time(); /* xtime */
++ rc = ccw_device_start(wch->cdev, &wch->ccw[3],
++ (unsigned long) wch, 0xff, 0);
++ spin_unlock_irqrestore(get_ccwdev_lock(wch->cdev), saveflags);
++
++ if ((grp->sweep_req_pend_num == 0) &&
++ (grp->sweep_rsp_pend_num == 0)) {
++ grp->in_sweep = 0;
++ rch->th_seq_num = 0x00;
++ wch->th_seq_num = 0x00;
++ ctcm_clear_busy_do(dev);
++ }
++
++ if (do_debug_data) {
++ ctcm_pr_debug("ctcmpc: %s()2: ToVTAM_th_seq= %08x\n" ,
++ __FUNCTION__, wch->th_seq_num);
++ ctcm_pr_debug("ctcmpc: %s()2: FromVTAM_th_seq= %08x\n" ,
++ __FUNCTION__, rch->th_seq_num);
++ }
++
++ if (rc != 0)
++ ctcm_ccw_check_rc(wch, rc, "send sweep");
++
++done:
++ if (do_debug)
++ ctcm_pr_debug("ctcmpc exit: %s() %s\n", __FUNCTION__, ach->id);
++ return;
++}
++
++
++/*
++ * The ctcmpc statemachine for a channel.
++ */
++
++const fsm_node ctcmpc_ch_fsm[] = {
++ { CTC_STATE_STOPPED, CTC_EVENT_STOP, ctcm_action_nop },
++ { CTC_STATE_STOPPED, CTC_EVENT_START, ctcm_chx_start },
++ { CTC_STATE_STOPPED, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++ { CTC_STATE_STOPPED, CTC_EVENT_FINSTAT, ctcm_action_nop },
++ { CTC_STATE_STOPPED, CTC_EVENT_MC_FAIL, ctcm_action_nop },
++
++ { CTC_STATE_NOTOP, CTC_EVENT_STOP, ctcm_chx_stop },
++ { CTC_STATE_NOTOP, CTC_EVENT_START, ctcm_action_nop },
++ { CTC_STATE_NOTOP, CTC_EVENT_FINSTAT, ctcm_action_nop },
++ { CTC_STATE_NOTOP, CTC_EVENT_MC_FAIL, ctcm_action_nop },
++ { CTC_STATE_NOTOP, CTC_EVENT_MC_GOOD, ctcm_chx_start },
++ { CTC_STATE_NOTOP, CTC_EVENT_UC_RCRESET, ctcm_chx_stop },
++ { CTC_STATE_NOTOP, CTC_EVENT_UC_RSRESET, ctcm_chx_stop },
++ { CTC_STATE_NOTOP, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++
++ { CTC_STATE_STARTWAIT, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CTC_STATE_STARTWAIT, CTC_EVENT_START, ctcm_action_nop },
++ { CTC_STATE_STARTWAIT, CTC_EVENT_FINSTAT, ctcm_chx_setmode },
++ { CTC_STATE_STARTWAIT, CTC_EVENT_TIMER, ctcm_chx_setuperr },
++ { CTC_STATE_STARTWAIT, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++ { CTC_STATE_STARTWAIT, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++
++ { CTC_STATE_STARTRETRY, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CTC_STATE_STARTRETRY, CTC_EVENT_TIMER, ctcm_chx_setmode },
++ { CTC_STATE_STARTRETRY, CTC_EVENT_FINSTAT, ctcm_chx_setmode },
++ { CTC_STATE_STARTRETRY, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++ { CTC_STATE_STARTRETRY, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++
++ { CTC_STATE_SETUPWAIT, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CTC_STATE_SETUPWAIT, CTC_EVENT_START, ctcm_action_nop },
++ { CTC_STATE_SETUPWAIT, CTC_EVENT_FINSTAT, ctcmpc_chx_firstio },
++ { CTC_STATE_SETUPWAIT, CTC_EVENT_UC_RCRESET, ctcm_chx_setuperr },
++ { CTC_STATE_SETUPWAIT, CTC_EVENT_UC_RSRESET, ctcm_chx_setuperr },
++ { CTC_STATE_SETUPWAIT, CTC_EVENT_TIMER, ctcm_chx_setmode },
++ { CTC_STATE_SETUPWAIT, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++ { CTC_STATE_SETUPWAIT, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++
++ { CTC_STATE_RXINIT, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CTC_STATE_RXINIT, CTC_EVENT_START, ctcm_action_nop },
++ { CTC_STATE_RXINIT, CTC_EVENT_FINSTAT, ctcmpc_chx_rxidle },
++ { CTC_STATE_RXINIT, CTC_EVENT_UC_RCRESET, ctcm_chx_rxiniterr },
++ { CTC_STATE_RXINIT, CTC_EVENT_UC_RSRESET, ctcm_chx_rxiniterr },
++ { CTC_STATE_RXINIT, CTC_EVENT_TIMER, ctcm_chx_rxiniterr },
++ { CTC_STATE_RXINIT, CTC_EVENT_ATTNBUSY, ctcm_chx_rxinitfail },
++ { CTC_STATE_RXINIT, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++ { CTC_STATE_RXINIT, CTC_EVENT_UC_ZERO, ctcmpc_chx_firstio },
++ { CTC_STATE_RXINIT, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++
++ { CH_XID0_PENDING, CTC_EVENT_FINSTAT, ctcm_action_nop },
++ { CH_XID0_PENDING, CTC_EVENT_ATTN, ctcmpc_chx_attn },
++ { CH_XID0_PENDING, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CH_XID0_PENDING, CTC_EVENT_START, ctcm_action_nop },
++ { CH_XID0_PENDING, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++ { CH_XID0_PENDING, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++ { CH_XID0_PENDING, CTC_EVENT_UC_RCRESET, ctcm_chx_setuperr },
++ { CH_XID0_PENDING, CTC_EVENT_UC_RSRESET, ctcm_chx_setuperr },
++ { CH_XID0_PENDING, CTC_EVENT_UC_RSRESET, ctcm_chx_setuperr },
++ { CH_XID0_PENDING, CTC_EVENT_ATTNBUSY, ctcm_chx_iofatal },
++
++ { CH_XID0_INPROGRESS, CTC_EVENT_FINSTAT, ctcmpc_chx_rx },
++ { CH_XID0_INPROGRESS, CTC_EVENT_ATTN, ctcmpc_chx_attn },
++ { CH_XID0_INPROGRESS, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CH_XID0_INPROGRESS, CTC_EVENT_START, ctcm_action_nop },
++ { CH_XID0_INPROGRESS, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++ { CH_XID0_INPROGRESS, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++ { CH_XID0_INPROGRESS, CTC_EVENT_UC_ZERO, ctcmpc_chx_rx },
++ { CH_XID0_INPROGRESS, CTC_EVENT_UC_RCRESET, ctcm_chx_setuperr },
++ { CH_XID0_INPROGRESS, CTC_EVENT_ATTNBUSY, ctcmpc_chx_attnbusy },
++ { CH_XID0_INPROGRESS, CTC_EVENT_TIMER, ctcmpc_chx_resend },
++ { CH_XID0_INPROGRESS, CTC_EVENT_IO_EBUSY, ctcm_chx_fail },
++
++ { CH_XID7_PENDING, CTC_EVENT_FINSTAT, ctcmpc_chx_rx },
++ { CH_XID7_PENDING, CTC_EVENT_ATTN, ctcmpc_chx_attn },
++ { CH_XID7_PENDING, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CH_XID7_PENDING, CTC_EVENT_START, ctcm_action_nop },
++ { CH_XID7_PENDING, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++ { CH_XID7_PENDING, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++ { CH_XID7_PENDING, CTC_EVENT_UC_ZERO, ctcmpc_chx_rx },
++ { CH_XID7_PENDING, CTC_EVENT_UC_RCRESET, ctcm_chx_setuperr },
++ { CH_XID7_PENDING, CTC_EVENT_UC_RSRESET, ctcm_chx_setuperr },
++ { CH_XID7_PENDING, CTC_EVENT_UC_RSRESET, ctcm_chx_setuperr },
++ { CH_XID7_PENDING, CTC_EVENT_ATTNBUSY, ctcm_chx_iofatal },
++ { CH_XID7_PENDING, CTC_EVENT_TIMER, ctcmpc_chx_resend },
++ { CH_XID7_PENDING, CTC_EVENT_IO_EBUSY, ctcm_chx_fail },
++
++ { CH_XID7_PENDING1, CTC_EVENT_FINSTAT, ctcmpc_chx_rx },
++ { CH_XID7_PENDING1, CTC_EVENT_ATTN, ctcmpc_chx_attn },
++ { CH_XID7_PENDING1, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CH_XID7_PENDING1, CTC_EVENT_START, ctcm_action_nop },
++ { CH_XID7_PENDING1, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++ { CH_XID7_PENDING1, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++ { CH_XID7_PENDING1, CTC_EVENT_UC_ZERO, ctcmpc_chx_rx },
++ { CH_XID7_PENDING1, CTC_EVENT_UC_RCRESET, ctcm_chx_setuperr },
++ { CH_XID7_PENDING1, CTC_EVENT_UC_RSRESET, ctcm_chx_setuperr },
++ { CH_XID7_PENDING1, CTC_EVENT_ATTNBUSY, ctcm_chx_iofatal },
++ { CH_XID7_PENDING1, CTC_EVENT_TIMER, ctcmpc_chx_resend },
++ { CH_XID7_PENDING1, CTC_EVENT_IO_EBUSY, ctcm_chx_fail },
++
++ { CH_XID7_PENDING2, CTC_EVENT_FINSTAT, ctcmpc_chx_rx },
++ { CH_XID7_PENDING2, CTC_EVENT_ATTN, ctcmpc_chx_attn },
++ { CH_XID7_PENDING2, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CH_XID7_PENDING2, CTC_EVENT_START, ctcm_action_nop },
++ { CH_XID7_PENDING2, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++ { CH_XID7_PENDING2, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++ { CH_XID7_PENDING2, CTC_EVENT_UC_ZERO, ctcmpc_chx_rx },
++ { CH_XID7_PENDING2, CTC_EVENT_UC_RCRESET, ctcm_chx_setuperr },
++ { CH_XID7_PENDING2, CTC_EVENT_UC_RSRESET, ctcm_chx_setuperr },
++ { CH_XID7_PENDING2, CTC_EVENT_ATTNBUSY, ctcm_chx_iofatal },
++ { CH_XID7_PENDING2, CTC_EVENT_TIMER, ctcmpc_chx_resend },
++ { CH_XID7_PENDING2, CTC_EVENT_IO_EBUSY, ctcm_chx_fail },
++
++ { CH_XID7_PENDING3, CTC_EVENT_FINSTAT, ctcmpc_chx_rx },
++ { CH_XID7_PENDING3, CTC_EVENT_ATTN, ctcmpc_chx_attn },
++ { CH_XID7_PENDING3, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CH_XID7_PENDING3, CTC_EVENT_START, ctcm_action_nop },
++ { CH_XID7_PENDING3, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++ { CH_XID7_PENDING3, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++ { CH_XID7_PENDING3, CTC_EVENT_UC_ZERO, ctcmpc_chx_rx },
++ { CH_XID7_PENDING3, CTC_EVENT_UC_RCRESET, ctcm_chx_setuperr },
++ { CH_XID7_PENDING3, CTC_EVENT_UC_RSRESET, ctcm_chx_setuperr },
++ { CH_XID7_PENDING3, CTC_EVENT_ATTNBUSY, ctcm_chx_iofatal },
++ { CH_XID7_PENDING3, CTC_EVENT_TIMER, ctcmpc_chx_resend },
++ { CH_XID7_PENDING3, CTC_EVENT_IO_EBUSY, ctcm_chx_fail },
++
++ { CH_XID7_PENDING4, CTC_EVENT_FINSTAT, ctcmpc_chx_rx },
++ { CH_XID7_PENDING4, CTC_EVENT_ATTN, ctcmpc_chx_attn },
++ { CH_XID7_PENDING4, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CH_XID7_PENDING4, CTC_EVENT_START, ctcm_action_nop },
++ { CH_XID7_PENDING4, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++ { CH_XID7_PENDING4, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++ { CH_XID7_PENDING4, CTC_EVENT_UC_ZERO, ctcmpc_chx_rx },
++ { CH_XID7_PENDING4, CTC_EVENT_UC_RCRESET, ctcm_chx_setuperr },
++ { CH_XID7_PENDING4, CTC_EVENT_UC_RSRESET, ctcm_chx_setuperr },
++ { CH_XID7_PENDING4, CTC_EVENT_ATTNBUSY, ctcm_chx_iofatal },
++ { CH_XID7_PENDING4, CTC_EVENT_TIMER, ctcmpc_chx_resend },
++ { CH_XID7_PENDING4, CTC_EVENT_IO_EBUSY, ctcm_chx_fail },
++
++ { CTC_STATE_RXIDLE, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CTC_STATE_RXIDLE, CTC_EVENT_START, ctcm_action_nop },
++ { CTC_STATE_RXIDLE, CTC_EVENT_FINSTAT, ctcmpc_chx_rx },
++ { CTC_STATE_RXIDLE, CTC_EVENT_UC_RCRESET, ctcm_chx_rxdisc },
++ { CTC_STATE_RXIDLE, CTC_EVENT_UC_RSRESET, ctcm_chx_fail },
++ { CTC_STATE_RXIDLE, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++ { CTC_STATE_RXIDLE, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++ { CTC_STATE_RXIDLE, CTC_EVENT_UC_ZERO, ctcmpc_chx_rx },
++
++ { CTC_STATE_TXINIT, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CTC_STATE_TXINIT, CTC_EVENT_START, ctcm_action_nop },
++ { CTC_STATE_TXINIT, CTC_EVENT_FINSTAT, ctcm_chx_txidle },
++ { CTC_STATE_TXINIT, CTC_EVENT_UC_RCRESET, ctcm_chx_txiniterr },
++ { CTC_STATE_TXINIT, CTC_EVENT_UC_RSRESET, ctcm_chx_txiniterr },
++ { CTC_STATE_TXINIT, CTC_EVENT_TIMER, ctcm_chx_txiniterr },
++ { CTC_STATE_TXINIT, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++ { CTC_STATE_TXINIT, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++ { CTC_STATE_TXINIT, CTC_EVENT_RSWEEP_TIMER, ctcmpc_chx_send_sweep },
++
++ { CTC_STATE_TXIDLE, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CTC_STATE_TXIDLE, CTC_EVENT_START, ctcm_action_nop },
++ { CTC_STATE_TXIDLE, CTC_EVENT_FINSTAT, ctcmpc_chx_firstio },
++ { CTC_STATE_TXIDLE, CTC_EVENT_UC_RCRESET, ctcm_chx_fail },
++ { CTC_STATE_TXIDLE, CTC_EVENT_UC_RSRESET, ctcm_chx_fail },
++ { CTC_STATE_TXIDLE, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++ { CTC_STATE_TXIDLE, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++ { CTC_STATE_TXIDLE, CTC_EVENT_RSWEEP_TIMER, ctcmpc_chx_send_sweep },
++
++ { CTC_STATE_TERM, CTC_EVENT_STOP, ctcm_action_nop },
++ { CTC_STATE_TERM, CTC_EVENT_START, ctcm_chx_restart },
++ { CTC_STATE_TERM, CTC_EVENT_FINSTAT, ctcm_chx_stopped },
++ { CTC_STATE_TERM, CTC_EVENT_UC_RCRESET, ctcm_action_nop },
++ { CTC_STATE_TERM, CTC_EVENT_UC_RSRESET, ctcm_action_nop },
++ { CTC_STATE_TERM, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++ { CTC_STATE_TERM, CTC_EVENT_IO_EBUSY, ctcm_chx_fail },
++ { CTC_STATE_TERM, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++
++ { CTC_STATE_DTERM, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CTC_STATE_DTERM, CTC_EVENT_START, ctcm_chx_restart },
++ { CTC_STATE_DTERM, CTC_EVENT_FINSTAT, ctcm_chx_setmode },
++ { CTC_STATE_DTERM, CTC_EVENT_UC_RCRESET, ctcm_action_nop },
++ { CTC_STATE_DTERM, CTC_EVENT_UC_RSRESET, ctcm_action_nop },
++ { CTC_STATE_DTERM, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++ { CTC_STATE_DTERM, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++
++ { CTC_STATE_TX, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CTC_STATE_TX, CTC_EVENT_START, ctcm_action_nop },
++ { CTC_STATE_TX, CTC_EVENT_FINSTAT, ctcmpc_chx_txdone },
++ { CTC_STATE_TX, CTC_EVENT_UC_RCRESET, ctcm_chx_fail },
++ { CTC_STATE_TX, CTC_EVENT_UC_RSRESET, ctcm_chx_fail },
++ { CTC_STATE_TX, CTC_EVENT_TIMER, ctcm_chx_txretry },
++ { CTC_STATE_TX, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++ { CTC_STATE_TX, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++ { CTC_STATE_TX, CTC_EVENT_RSWEEP_TIMER, ctcmpc_chx_send_sweep },
++ { CTC_STATE_TX, CTC_EVENT_IO_EBUSY, ctcm_chx_fail },
++
++ { CTC_STATE_RXERR, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CTC_STATE_TXERR, CTC_EVENT_STOP, ctcm_chx_haltio },
++ { CTC_STATE_TXERR, CTC_EVENT_IO_ENODEV, ctcm_chx_iofatal },
++ { CTC_STATE_TXERR, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++ { CTC_STATE_RXERR, CTC_EVENT_MC_FAIL, ctcm_chx_fail },
++};
++
++int mpc_ch_fsm_len = ARRAY_SIZE(ctcmpc_ch_fsm);
++
++/*
++ * Actions for interface - statemachine.
++ */
++
++/**
++ * Startup channels by sending CTC_EVENT_START to each channel.
++ *
++ * fi An instance of an interface statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from struct net_device * upon call.
++ */
++static void dev_action_start(fsm_instance *fi, int event, void *arg)
++{
++ struct net_device *dev = arg;
++ struct ctcm_priv *priv = dev->priv;
++ int direction;
++
++ CTCMY_DBF_DEV_NAME(SETUP, dev, "");
++
++ fsm_deltimer(&priv->restart_timer);
++ fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
++ if (IS_MPC(priv))
++ priv->mpcg->channels_terminating = 0;
++ for (direction = READ; direction <= WRITE; direction++) {
++ struct channel *ch = priv->channel[direction];
++ fsm_event(ch->fsm, CTC_EVENT_START, ch);
++ }
++}
++
++/**
++ * Shutdown channels by sending CTC_EVENT_STOP to each channel.
++ *
++ * fi An instance of an interface statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from struct net_device * upon call.
++ */
++static void dev_action_stop(fsm_instance *fi, int event, void *arg)
++{
++ int direction;
++ struct net_device *dev = arg;
++ struct ctcm_priv *priv = dev->priv;
++
++ CTCMY_DBF_DEV_NAME(SETUP, dev, "");
++
++ fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
++ for (direction = READ; direction <= WRITE; direction++) {
++ struct channel *ch = priv->channel[direction];
++ fsm_event(ch->fsm, CTC_EVENT_STOP, ch);
++ ch->th_seq_num = 0x00;
++ if (do_debug)
++ ctcm_pr_debug("ctcm: %s() CH_th_seq= %08x\n",
++ __FUNCTION__, ch->th_seq_num);
++ }
++ if (IS_MPC(priv))
++ fsm_newstate(priv->mpcg->fsm, MPCG_STATE_RESET);
++}
++
++static void dev_action_restart(fsm_instance *fi, int event, void *arg)
++{
++ int restart_timer;
++ struct net_device *dev = arg;
++ struct ctcm_priv *priv = dev->priv;
++
++ CTCMY_DBF_DEV_NAME(TRACE, dev, "");
++
++ if (IS_MPC(priv)) {
++ ctcm_pr_info("ctcm: %s Restarting Device and "
++ "MPC Group in 5 seconds\n",
++ dev->name);
++ restart_timer = CTCM_TIME_1_SEC;
++ } else {
++ ctcm_pr_info("%s: Restarting\n", dev->name);
++ restart_timer = CTCM_TIME_5_SEC;
++ }
++
++ dev_action_stop(fi, event, arg);
++ fsm_event(priv->fsm, DEV_EVENT_STOP, dev);
++ if (IS_MPC(priv))
++ fsm_newstate(priv->mpcg->fsm, MPCG_STATE_RESET);
++
++ /* going back into start sequence too quickly can */
++ /* result in the other side becoming unreachable due */
++ /* to sense reported when IO is aborted */
++ fsm_addtimer(&priv->restart_timer, restart_timer,
++ DEV_EVENT_START, dev);
++}
++
++/**
++ * Called from channel statemachine
++ * when a channel is up and running.
++ *
++ * fi An instance of an interface statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from struct net_device * upon call.
++ */
++static void dev_action_chup(fsm_instance *fi, int event, void *arg)
++{
++ struct net_device *dev = arg;
++ struct ctcm_priv *priv = dev->priv;
++
++ CTCMY_DBF_DEV_NAME(SETUP, dev, "");
++
++ switch (fsm_getstate(fi)) {
++ case DEV_STATE_STARTWAIT_RXTX:
++ if (event == DEV_EVENT_RXUP)
++ fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);
++ else
++ fsm_newstate(fi, DEV_STATE_STARTWAIT_RX);
++ break;
++ case DEV_STATE_STARTWAIT_RX:
++ if (event == DEV_EVENT_RXUP) {
++ fsm_newstate(fi, DEV_STATE_RUNNING);
++ ctcm_pr_info("%s: connected with remote side\n",
++ dev->name);
++ ctcm_clear_busy(dev);
++ }
++ break;
++ case DEV_STATE_STARTWAIT_TX:
++ if (event == DEV_EVENT_TXUP) {
++ fsm_newstate(fi, DEV_STATE_RUNNING);
++ ctcm_pr_info("%s: connected with remote side\n",
++ dev->name);
++ ctcm_clear_busy(dev);
++ }
++ break;
++ case DEV_STATE_STOPWAIT_TX:
++ if (event == DEV_EVENT_RXUP)
++ fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
++ break;
++ case DEV_STATE_STOPWAIT_RX:
++ if (event == DEV_EVENT_TXUP)
++ fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
++ break;
++ }
++
++ if (IS_MPC(priv)) {
++ if (event == DEV_EVENT_RXUP)
++ mpc_channel_action(priv->channel[READ],
++ READ, MPC_CHANNEL_ADD);
++ else
++ mpc_channel_action(priv->channel[WRITE],
++ WRITE, MPC_CHANNEL_ADD);
++ }
++}
++
++/**
++ * Called from device statemachine
++ * when a channel has been shutdown.
++ *
++ * fi An instance of an interface statemachine.
++ * event The event, just happened.
++ * arg Generic pointer, casted from struct net_device * upon call.
++ */
++static void dev_action_chdown(fsm_instance *fi, int event, void *arg)
++{
++
++ struct net_device *dev = arg;
++ struct ctcm_priv *priv = dev->priv;
++
++ CTCMY_DBF_DEV_NAME(SETUP, dev, "");
++
++ switch (fsm_getstate(fi)) {
++ case DEV_STATE_RUNNING:
++ if (event == DEV_EVENT_TXDOWN)
++ fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);
++ else
++ fsm_newstate(fi, DEV_STATE_STARTWAIT_RX);
++ break;
++ case DEV_STATE_STARTWAIT_RX:
++ if (event == DEV_EVENT_TXDOWN)
++ fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
++ break;
++ case DEV_STATE_STARTWAIT_TX:
++ if (event == DEV_EVENT_RXDOWN)
++ fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
++ break;
++ case DEV_STATE_STOPWAIT_RXTX:
++ if (event == DEV_EVENT_TXDOWN)
++ fsm_newstate(fi, DEV_STATE_STOPWAIT_RX);
++ else
++ fsm_newstate(fi, DEV_STATE_STOPWAIT_TX);
++ break;
++ case DEV_STATE_STOPWAIT_RX:
++ if (event == DEV_EVENT_RXDOWN)
++ fsm_newstate(fi, DEV_STATE_STOPPED);
++ break;
++ case DEV_STATE_STOPWAIT_TX:
++ if (event == DEV_EVENT_TXDOWN)
++ fsm_newstate(fi, DEV_STATE_STOPPED);
++ break;
++ }
++ if (IS_MPC(priv)) {
++ if (event == DEV_EVENT_RXDOWN)
++ mpc_channel_action(priv->channel[READ],
++ READ, MPC_CHANNEL_REMOVE);
++ else
++ mpc_channel_action(priv->channel[WRITE],
++ WRITE, MPC_CHANNEL_REMOVE);
++ }
++}
++
++const fsm_node dev_fsm[] = {
++ { DEV_STATE_STOPPED, DEV_EVENT_START, dev_action_start },
++ { DEV_STATE_STOPWAIT_RXTX, DEV_EVENT_START, dev_action_start },
++ { DEV_STATE_STOPWAIT_RXTX, DEV_EVENT_RXDOWN, dev_action_chdown },
++ { DEV_STATE_STOPWAIT_RXTX, DEV_EVENT_TXDOWN, dev_action_chdown },
++ { DEV_STATE_STOPWAIT_RXTX, DEV_EVENT_RESTART, dev_action_restart },
++ { DEV_STATE_STOPWAIT_RX, DEV_EVENT_START, dev_action_start },
++ { DEV_STATE_STOPWAIT_RX, DEV_EVENT_RXUP, dev_action_chup },
++ { DEV_STATE_STOPWAIT_RX, DEV_EVENT_TXUP, dev_action_chup },
++ { DEV_STATE_STOPWAIT_RX, DEV_EVENT_RXDOWN, dev_action_chdown },
++ { DEV_STATE_STOPWAIT_RX, DEV_EVENT_RESTART, dev_action_restart },
++ { DEV_STATE_STOPWAIT_TX, DEV_EVENT_START, dev_action_start },
++ { DEV_STATE_STOPWAIT_TX, DEV_EVENT_RXUP, dev_action_chup },
++ { DEV_STATE_STOPWAIT_TX, DEV_EVENT_TXUP, dev_action_chup },
++ { DEV_STATE_STOPWAIT_TX, DEV_EVENT_TXDOWN, dev_action_chdown },
++ { DEV_STATE_STOPWAIT_TX, DEV_EVENT_RESTART, dev_action_restart },
++ { DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_STOP, dev_action_stop },
++ { DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RXUP, dev_action_chup },
++ { DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_TXUP, dev_action_chup },
++ { DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RXDOWN, dev_action_chdown },
++ { DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_TXDOWN, dev_action_chdown },
++ { DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RESTART, dev_action_restart },
++ { DEV_STATE_STARTWAIT_TX, DEV_EVENT_STOP, dev_action_stop },
++ { DEV_STATE_STARTWAIT_TX, DEV_EVENT_RXUP, dev_action_chup },
++ { DEV_STATE_STARTWAIT_TX, DEV_EVENT_TXUP, dev_action_chup },
++ { DEV_STATE_STARTWAIT_TX, DEV_EVENT_RXDOWN, dev_action_chdown },
++ { DEV_STATE_STARTWAIT_TX, DEV_EVENT_RESTART, dev_action_restart },
++ { DEV_STATE_STARTWAIT_RX, DEV_EVENT_STOP, dev_action_stop },
++ { DEV_STATE_STARTWAIT_RX, DEV_EVENT_RXUP, dev_action_chup },
++ { DEV_STATE_STARTWAIT_RX, DEV_EVENT_TXUP, dev_action_chup },
++ { DEV_STATE_STARTWAIT_RX, DEV_EVENT_TXDOWN, dev_action_chdown },
++ { DEV_STATE_STARTWAIT_RX, DEV_EVENT_RESTART, dev_action_restart },
++ { DEV_STATE_RUNNING, DEV_EVENT_STOP, dev_action_stop },
++ { DEV_STATE_RUNNING, DEV_EVENT_RXDOWN, dev_action_chdown },
++ { DEV_STATE_RUNNING, DEV_EVENT_TXDOWN, dev_action_chdown },
++ { DEV_STATE_RUNNING, DEV_EVENT_TXUP, ctcm_action_nop },
++ { DEV_STATE_RUNNING, DEV_EVENT_RXUP, ctcm_action_nop },
++ { DEV_STATE_RUNNING, DEV_EVENT_RESTART, dev_action_restart },
++};
++
++int dev_fsm_len = ARRAY_SIZE(dev_fsm);
++
++/* --- This is the END my friend --- */
++
+diff --git a/drivers/s390/net/ctcm_fsms.h b/drivers/s390/net/ctcm_fsms.h
+new file mode 100644
+index 0000000..2326aba
+--- /dev/null
++++ b/drivers/s390/net/ctcm_fsms.h
+@@ -0,0 +1,359 @@
++/*
++ * drivers/s390/net/ctcm_fsms.h
++ *
++ * Copyright IBM Corp. 2001, 2007
++ * Authors: Fritz Elfert (felfert at millenux.com)
++ * Peter Tiedemann (ptiedem at de.ibm.com)
++ * MPC additions :
++ * Belinda Thompson (belindat at us.ibm.com)
++ * Andy Richter (richtera at us.ibm.com)
++ */
++#ifndef _CTCM_FSMS_H_
++#define _CTCM_FSMS_H_
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/timer.h>
++#include <linux/bitops.h>
++
++#include <linux/signal.h>
++#include <linux/string.h>
++
++#include <linux/ip.h>
++#include <linux/if_arp.h>
++#include <linux/tcp.h>
++#include <linux/skbuff.h>
++#include <linux/ctype.h>
++#include <net/dst.h>
++
++#include <linux/io.h>
++#include <asm/ccwdev.h>
++#include <asm/ccwgroup.h>
++#include <linux/uaccess.h>
++
++#include <asm/idals.h>
++
++#include "fsm.h"
++#include "cu3088.h"
++#include "ctcm_main.h"
++
++/*
++ * Definitions for the channel statemachine(s) for ctc and ctcmpc
++ *
++ * To allow better kerntyping, prefix-less definitions for channel states
++ * and channel events have been replaced :
++ * ch_event... -> ctc_ch_event...
++ * CH_EVENT... -> CTC_EVENT...
++ * ch_state... -> ctc_ch_state...
++ * CH_STATE... -> CTC_STATE...
++ */
++/*
++ * Events of the channel statemachine(s) for ctc and ctcmpc
++ */
++enum ctc_ch_events {
++ /*
++ * Events, representing return code of
++ * I/O operations (ccw_device_start, ccw_device_halt et al.)
++ */
++ CTC_EVENT_IO_SUCCESS,
++ CTC_EVENT_IO_EBUSY,
++ CTC_EVENT_IO_ENODEV,
++ CTC_EVENT_IO_UNKNOWN,
++
++ CTC_EVENT_ATTNBUSY,
++ CTC_EVENT_ATTN,
++ CTC_EVENT_BUSY,
++ /*
++ * Events, representing unit-check
++ */
++ CTC_EVENT_UC_RCRESET,
++ CTC_EVENT_UC_RSRESET,
++ CTC_EVENT_UC_TXTIMEOUT,
++ CTC_EVENT_UC_TXPARITY,
++ CTC_EVENT_UC_HWFAIL,
++ CTC_EVENT_UC_RXPARITY,
++ CTC_EVENT_UC_ZERO,
++ CTC_EVENT_UC_UNKNOWN,
++ /*
++ * Events, representing subchannel-check
++ */
++ CTC_EVENT_SC_UNKNOWN,
++ /*
++ * Events, representing machine checks
++ */
++ CTC_EVENT_MC_FAIL,
++ CTC_EVENT_MC_GOOD,
++ /*
++ * Event, representing normal IRQ
++ */
++ CTC_EVENT_IRQ,
++ CTC_EVENT_FINSTAT,
++ /*
++ * Event, representing timer expiry.
++ */
++ CTC_EVENT_TIMER,
++ /*
++ * Events, representing commands from upper levels.
++ */
++ CTC_EVENT_START,
++ CTC_EVENT_STOP,
++ CTC_NR_EVENTS,
++ /*
++ * additional MPC events
++ */
++ CTC_EVENT_SEND_XID = CTC_NR_EVENTS,
++ CTC_EVENT_RSWEEP_TIMER,
++ /*
++ * MUST be always the last element!!
++ */
++ CTC_MPC_NR_EVENTS,
++};
++
++/*
++ * States of the channel statemachine(s) for ctc and ctcmpc.
++ */
++enum ctc_ch_states {
++ /*
++ * Channel not assigned to any device,
++ * initial state, direction invalid
++ */
++ CTC_STATE_IDLE,
++ /*
++ * Channel assigned but not operating
++ */
++ CTC_STATE_STOPPED,
++ CTC_STATE_STARTWAIT,
++ CTC_STATE_STARTRETRY,
++ CTC_STATE_SETUPWAIT,
++ CTC_STATE_RXINIT,
++ CTC_STATE_TXINIT,
++ CTC_STATE_RX,
++ CTC_STATE_TX,
++ CTC_STATE_RXIDLE,
++ CTC_STATE_TXIDLE,
++ CTC_STATE_RXERR,
++ CTC_STATE_TXERR,
++ CTC_STATE_TERM,
++ CTC_STATE_DTERM,
++ CTC_STATE_NOTOP,
++ CTC_NR_STATES, /* MUST be the last element of non-expanded states */
++ /*
++ * additional MPC states
++ */
++ CH_XID0_PENDING = CTC_NR_STATES,
++ CH_XID0_INPROGRESS,
++ CH_XID7_PENDING,
++ CH_XID7_PENDING1,
++ CH_XID7_PENDING2,
++ CH_XID7_PENDING3,
++ CH_XID7_PENDING4,
++ CTC_MPC_NR_STATES, /* MUST be the last element of expanded mpc states */
++};
++
++extern const char *ctc_ch_event_names[];
++
++extern const char *ctc_ch_state_names[];
++
++void ctcm_ccw_check_rc(struct channel *ch, int rc, char *msg);
++void ctcm_purge_skb_queue(struct sk_buff_head *q);
++void fsm_action_nop(fsm_instance *fi, int event, void *arg);
++
++/*
++ * ----- non-static actions for ctcm channel statemachine -----
++ *
++ */
++void ctcm_chx_txidle(fsm_instance *fi, int event, void *arg);
++
++/*
++ * ----- FSM (state/event/action) of the ctcm channel statemachine -----
++ */
++extern const fsm_node ch_fsm[];
++extern int ch_fsm_len;
++
++
++/*
++ * ----- non-static actions for ctcmpc channel statemachine ----
++ *
++ */
++/* shared :
++void ctcm_chx_txidle(fsm_instance * fi, int event, void *arg);
++ */
++void ctcmpc_chx_rxidle(fsm_instance *fi, int event, void *arg);
++
++/*
++ * ----- FSM (state/event/action) of the ctcmpc channel statemachine -----
++ */
++extern const fsm_node ctcmpc_ch_fsm[];
++extern int mpc_ch_fsm_len;
++
++/*
++ * Definitions for the device interface statemachine for ctc and mpc
++ */
++
++/*
++ * States of the device interface statemachine.
++ */
++enum dev_states {
++ DEV_STATE_STOPPED,
++ DEV_STATE_STARTWAIT_RXTX,
++ DEV_STATE_STARTWAIT_RX,
++ DEV_STATE_STARTWAIT_TX,
++ DEV_STATE_STOPWAIT_RXTX,
++ DEV_STATE_STOPWAIT_RX,
++ DEV_STATE_STOPWAIT_TX,
++ DEV_STATE_RUNNING,
++ /*
++ * MUST be always the last element!!
++ */
++ CTCM_NR_DEV_STATES
++};
++
++extern const char *dev_state_names[];
++
++/*
++ * Events of the device interface statemachine.
++ * ctcm and ctcmpc
++ */
++enum dev_events {
++ DEV_EVENT_START,
++ DEV_EVENT_STOP,
++ DEV_EVENT_RXUP,
++ DEV_EVENT_TXUP,
++ DEV_EVENT_RXDOWN,
++ DEV_EVENT_TXDOWN,
++ DEV_EVENT_RESTART,
++ /*
++ * MUST be always the last element!!
++ */
++ CTCM_NR_DEV_EVENTS
++};
++
++extern const char *dev_event_names[];
++
++/*
++ * Actions for the device interface statemachine.
++ * ctc and ctcmpc
++ */
++/*
++static void dev_action_start(fsm_instance * fi, int event, void *arg);
++static void dev_action_stop(fsm_instance * fi, int event, void *arg);
++static void dev_action_restart(fsm_instance *fi, int event, void *arg);
++static void dev_action_chup(fsm_instance * fi, int event, void *arg);
++static void dev_action_chdown(fsm_instance * fi, int event, void *arg);
++*/
++
++/*
++ * The (state/event/action) fsm table of the device interface statemachine.
++ * ctcm and ctcmpc
++ */
++extern const fsm_node dev_fsm[];
++extern int dev_fsm_len;
++
++
++/*
++ * Definitions for the MPC Group statemachine
++ */
++
++/*
++ * MPC Group Station FSM States
++
++State Name When In This State
++====================== =======================================
++MPCG_STATE_RESET Initial State When Driver Loaded
++ We receive and send NOTHING
++
++MPCG_STATE_INOP INOP Received.
++ Group level non-recoverable error
++
++MPCG_STATE_READY XID exchanges for at least 1 write and
++ 1 read channel have completed.
++ Group is ready for data transfer.
++
++States from ctc_mpc_alloc_channel
++==============================================================
++MPCG_STATE_XID2INITW Awaiting XID2(0) Initiation
++ ATTN from other side will start
++ XID negotiations.
++ Y-side protocol only.
++
++MPCG_STATE_XID2INITX XID2(0) negotiations are in progress.
++ At least 1, but not all, XID2(0)'s
++ have been received from partner.
++
++MPCG_STATE_XID7INITW XID2(0) complete
++ No XID2(7)'s have yet been received.
++ XID2(7) negotiations pending.
++
++MPCG_STATE_XID7INITX XID2(7) negotiations in progress.
++ At least 1, but not all, XID2(7)'s
++ have been received from partner.
++
++MPCG_STATE_XID7INITF XID2(7) negotiations complete.
++ Transitioning to READY.
++
++MPCG_STATE_READY Ready for Data Transfer.
++
++
++States from ctc_mpc_establish_connectivity call
++==============================================================
++MPCG_STATE_XID0IOWAIT Initiating XID2(0) negotiations.
++ X-side protocol only.
++ ATTN-BUSY from other side will convert
++ this to Y-side protocol and the
++ ctc_mpc_alloc_channel flow will begin.
++
++MPCG_STATE_XID0IOWAIX XID2(0) negotiations are in progress.
++ At least 1, but not all, XID2(0)'s
++ have been received from partner.
++
++MPCG_STATE_XID7INITI XID2(0) complete
++ No XID2(7)'s have yet been received.
++ XID2(7) negotiations pending.
++
++MPCG_STATE_XID7INITZ XID2(7) negotiations in progress.
++ At least 1, but not all, XID2(7)'s
++ have been received from partner.
++
++MPCG_STATE_XID7INITF XID2(7) negotiations complete.
++ Transitioning to READY.
++
++MPCG_STATE_READY Ready for Data Transfer.
++
++*/
++
++enum mpcg_events {
++ MPCG_EVENT_INOP,
++ MPCG_EVENT_DISCONC,
++ MPCG_EVENT_XID0DO,
++ MPCG_EVENT_XID2,
++ MPCG_EVENT_XID2DONE,
++ MPCG_EVENT_XID7DONE,
++ MPCG_EVENT_TIMER,
++ MPCG_EVENT_DOIO,
++ MPCG_NR_EVENTS,
++};
++
++enum mpcg_states {
++ MPCG_STATE_RESET,
++ MPCG_STATE_INOP,
++ MPCG_STATE_XID2INITW,
++ MPCG_STATE_XID2INITX,
++ MPCG_STATE_XID7INITW,
++ MPCG_STATE_XID7INITX,
++ MPCG_STATE_XID0IOWAIT,
++ MPCG_STATE_XID0IOWAIX,
++ MPCG_STATE_XID7INITI,
++ MPCG_STATE_XID7INITZ,
++ MPCG_STATE_XID7INITF,
++ MPCG_STATE_FLOWC,
++ MPCG_STATE_READY,
++ MPCG_NR_STATES,
++};
++
++#endif
++/* --- This is the END my friend --- */
+diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
+new file mode 100644
+index 0000000..d52843d
+--- /dev/null
++++ b/drivers/s390/net/ctcm_main.c
+@@ -0,0 +1,1772 @@
++/*
++ * drivers/s390/net/ctcm_main.c
++ *
++ * Copyright IBM Corp. 2001, 2007
++ * Author(s):
++ * Original CTC driver(s):
++ * Fritz Elfert (felfert at millenux.com)
++ * Dieter Wellerdiek (wel at de.ibm.com)
++ * Martin Schwidefsky (schwidefsky at de.ibm.com)
++ * Denis Joseph Barrow (barrow_dj at yahoo.com)
++ * Jochen Roehrig (roehrig at de.ibm.com)
++ * Cornelia Huck <cornelia.huck at de.ibm.com>
++ * MPC additions:
++ * Belinda Thompson (belindat at us.ibm.com)
++ * Andy Richter (richtera at us.ibm.com)
++ * Revived by:
++ * Peter Tiedemann (ptiedem at de.ibm.com)
++ */
++
++#undef DEBUG
++#undef DEBUGDATA
++#undef DEBUGCCW
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/timer.h>
++#include <linux/bitops.h>
++
++#include <linux/signal.h>
++#include <linux/string.h>
++
++#include <linux/ip.h>
++#include <linux/if_arp.h>
++#include <linux/tcp.h>
++#include <linux/skbuff.h>
++#include <linux/ctype.h>
++#include <net/dst.h>
++
++#include <linux/io.h>
++#include <asm/ccwdev.h>
++#include <asm/ccwgroup.h>
++#include <linux/uaccess.h>
++
++#include <asm/idals.h>
++
++#include "cu3088.h"
++#include "ctcm_fsms.h"
++#include "ctcm_main.h"
++
++/* Some common global variables */
++
++/*
++ * Linked list of all detected channels.
++ */
++struct channel *channels;
++
++/**
++ * Unpack a just received skb and hand it over to
++ * upper layers.
++ *
++ * ch The channel where this skb has been received.
++ * pskb The received skb.
++ */
++void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb)
++{
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++ __u16 len = *((__u16 *) pskb->data);
++
++ skb_put(pskb, 2 + LL_HEADER_LENGTH);
++ skb_pull(pskb, 2);
++ pskb->dev = dev;
++ pskb->ip_summed = CHECKSUM_UNNECESSARY;
++ while (len > 0) {
++ struct sk_buff *skb;
++ int skblen;
++ struct ll_header *header = (struct ll_header *)pskb->data;
++
++ skb_pull(pskb, LL_HEADER_LENGTH);
++ if ((ch->protocol == CTCM_PROTO_S390) &&
++ (header->type != ETH_P_IP)) {
++
++ if (!(ch->logflags & LOG_FLAG_ILLEGALPKT)) {
++ /*
++ * Check packet type only if we stick strictly
++ * to S/390's protocol of OS390. This only
++ * supports IP. Otherwise allow any packet
++ * type.
++ */
++ ctcm_pr_warn("%s Illegal packet type 0x%04x "
++ "received, dropping\n",
++ dev->name, header->type);
++ ch->logflags |= LOG_FLAG_ILLEGALPKT;
++ }
++
++ priv->stats.rx_dropped++;
++ priv->stats.rx_frame_errors++;
++ return;
++ }
++ pskb->protocol = ntohs(header->type);
++ if (header->length <= LL_HEADER_LENGTH) {
++ if (!(ch->logflags & LOG_FLAG_ILLEGALSIZE)) {
++ ctcm_pr_warn(
++ "%s Illegal packet size %d "
++ "received (MTU=%d blocklen=%d), "
++ "dropping\n", dev->name, header->length,
++ dev->mtu, len);
++ ch->logflags |= LOG_FLAG_ILLEGALSIZE;
++ }
++
++ priv->stats.rx_dropped++;
++ priv->stats.rx_length_errors++;
++ return;
++ }
++ header->length -= LL_HEADER_LENGTH;
++ len -= LL_HEADER_LENGTH;
++ if ((header->length > skb_tailroom(pskb)) ||
++ (header->length > len)) {
++ if (!(ch->logflags & LOG_FLAG_OVERRUN)) {
++ ctcm_pr_warn(
++ "%s Illegal packet size %d (beyond the"
++ " end of received data), dropping\n",
++ dev->name, header->length);
++ ch->logflags |= LOG_FLAG_OVERRUN;
++ }
++
++ priv->stats.rx_dropped++;
++ priv->stats.rx_length_errors++;
++ return;
++ }
++ skb_put(pskb, header->length);
++ skb_reset_mac_header(pskb);
++ len -= header->length;
++ skb = dev_alloc_skb(pskb->len);
++ if (!skb) {
++ if (!(ch->logflags & LOG_FLAG_NOMEM)) {
++ ctcm_pr_warn(
++ "%s Out of memory in ctcm_unpack_skb\n",
++ dev->name);
++ ch->logflags |= LOG_FLAG_NOMEM;
++ }
++ priv->stats.rx_dropped++;
++ return;
++ }
++ skb_copy_from_linear_data(pskb, skb_put(skb, pskb->len),
++ pskb->len);
++ skb_reset_mac_header(skb);
++ skb->dev = pskb->dev;
++ skb->protocol = pskb->protocol;
++ pskb->ip_summed = CHECKSUM_UNNECESSARY;
++ skblen = skb->len;
++ /*
++ * reset logflags
++ */
++ ch->logflags = 0;
++ priv->stats.rx_packets++;
++ priv->stats.rx_bytes += skblen;
++ netif_rx_ni(skb);
++ dev->last_rx = jiffies;
++ if (len > 0) {
++ skb_pull(pskb, header->length);
++ if (skb_tailroom(pskb) < LL_HEADER_LENGTH) {
++ if (!(ch->logflags & LOG_FLAG_OVERRUN)) {
++ CTCM_DBF_DEV_NAME(TRACE, dev,
++ "Overrun in ctcm_unpack_skb");
++ ch->logflags |= LOG_FLAG_OVERRUN;
++ }
++ return;
++ }
++ skb_put(pskb, LL_HEADER_LENGTH);
++ }
++ }
++}
++
++/**
++ * Release a specific channel in the channel list.
++ *
++ * ch Pointer to channel struct to be released.
++ */
++static void channel_free(struct channel *ch)
++{
++ CTCM_DBF_TEXT(TRACE, 2, __FUNCTION__);
++ ch->flags &= ~CHANNEL_FLAGS_INUSE;
++ fsm_newstate(ch->fsm, CTC_STATE_IDLE);
++}
++
++/**
++ * Remove a specific channel in the channel list.
++ *
++ * ch Pointer to channel struct to be released.
++ */
++static void channel_remove(struct channel *ch)
++{
++ struct channel **c = &channels;
++ char chid[CTCM_ID_SIZE+1];
++ int ok = 0;
++
++ if (ch == NULL)
++ return;
++ else
++ strncpy(chid, ch->id, CTCM_ID_SIZE);
++
++ channel_free(ch);
++ while (*c) {
++ if (*c == ch) {
++ *c = ch->next;
++ fsm_deltimer(&ch->timer);
++ if (IS_MPC(ch))
++ fsm_deltimer(&ch->sweep_timer);
++
++ kfree_fsm(ch->fsm);
++ clear_normalized_cda(&ch->ccw[4]);
++ if (ch->trans_skb != NULL) {
++ clear_normalized_cda(&ch->ccw[1]);
++ dev_kfree_skb_any(ch->trans_skb);
++ }
++ if (IS_MPC(ch)) {
++ tasklet_kill(&ch->ch_tasklet);
++ tasklet_kill(&ch->ch_disc_tasklet);
++ kfree(ch->discontact_th);
++ }
++ kfree(ch->ccw);
++ kfree(ch->irb);
++ kfree(ch);
++ ok = 1;
++ break;
++ }
++ c = &((*c)->next);
++ }
++
++ CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s(%s) %s", CTCM_FUNTAIL,
++ chid, ok ? "OK" : "failed");
++}
++
++/**
++ * Get a specific channel from the channel list.
++ *
++ * type Type of channel we are interested in.
++ * id Id of channel we are interested in.
++ * direction Direction we want to use this channel for.
++ *
++ * returns Pointer to a channel or NULL if no matching channel available.
++ */
++static struct channel *channel_get(enum channel_types type,
++ char *id, int direction)
++{
++ struct channel *ch = channels;
++
++ if (do_debug) {
++ char buf[64];
++ sprintf(buf, "%s(%d, %s, %d)\n",
++ CTCM_FUNTAIL, type, id, direction);
++ CTCM_DBF_TEXT(TRACE, CTC_DBF_INFO, buf);
++ }
++ while (ch && (strncmp(ch->id, id, CTCM_ID_SIZE) || (ch->type != type)))
++ ch = ch->next;
++ if (!ch) {
++ char buf[64];
++ sprintf(buf, "%s(%d, %s, %d) not found in channel list\n",
++ CTCM_FUNTAIL, type, id, direction);
++ CTCM_DBF_TEXT(ERROR, CTC_DBF_ERROR, buf);
++ } else {
++ if (ch->flags & CHANNEL_FLAGS_INUSE)
++ ch = NULL;
++ else {
++ ch->flags |= CHANNEL_FLAGS_INUSE;
++ ch->flags &= ~CHANNEL_FLAGS_RWMASK;
++ ch->flags |= (direction == WRITE)
++ ? CHANNEL_FLAGS_WRITE : CHANNEL_FLAGS_READ;
++ fsm_newstate(ch->fsm, CTC_STATE_STOPPED);
++ }
++ }
++ return ch;
++}
++
++static long ctcm_check_irb_error(struct ccw_device *cdev, struct irb *irb)
++{
++ if (!IS_ERR(irb))
++ return 0;
++
++ CTCM_DBF_TEXT_(ERROR, CTC_DBF_WARN, "irb error %ld on device %s\n",
++ PTR_ERR(irb), cdev->dev.bus_id);
++
++ switch (PTR_ERR(irb)) {
++ case -EIO:
++ ctcm_pr_warn("i/o-error on device %s\n", cdev->dev.bus_id);
++ break;
++ case -ETIMEDOUT:
++ ctcm_pr_warn("timeout on device %s\n", cdev->dev.bus_id);
++ break;
++ default:
++ ctcm_pr_warn("unknown error %ld on device %s\n",
++ PTR_ERR(irb), cdev->dev.bus_id);
++ }
++ return PTR_ERR(irb);
++}
++
++
++/**
++ * Check sense of a unit check.
++ *
++ * ch The channel, the sense code belongs to.
++ * sense The sense code to inspect.
++ */
++static inline void ccw_unit_check(struct channel *ch, unsigned char sense)
++{
++ CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__);
++ if (sense & SNS0_INTERVENTION_REQ) {
++ if (sense & 0x01) {
++ ctcm_pr_debug("%s: Interface disc. or Sel. reset "
++ "(remote)\n", ch->id);
++ fsm_event(ch->fsm, CTC_EVENT_UC_RCRESET, ch);
++ } else {
++ ctcm_pr_debug("%s: System reset (remote)\n", ch->id);
++ fsm_event(ch->fsm, CTC_EVENT_UC_RSRESET, ch);
++ }
++ } else if (sense & SNS0_EQUIPMENT_CHECK) {
++ if (sense & SNS0_BUS_OUT_CHECK) {
++ ctcm_pr_warn("%s: Hardware malfunction (remote)\n",
++ ch->id);
++ fsm_event(ch->fsm, CTC_EVENT_UC_HWFAIL, ch);
++ } else {
++ ctcm_pr_warn("%s: Read-data parity error (remote)\n",
++ ch->id);
++ fsm_event(ch->fsm, CTC_EVENT_UC_RXPARITY, ch);
++ }
++ } else if (sense & SNS0_BUS_OUT_CHECK) {
++ if (sense & 0x04) {
++ ctcm_pr_warn("%s: Data-streaming timeout)\n", ch->id);
++ fsm_event(ch->fsm, CTC_EVENT_UC_TXTIMEOUT, ch);
++ } else {
++ ctcm_pr_warn("%s: Data-transfer parity error\n",
++ ch->id);
++ fsm_event(ch->fsm, CTC_EVENT_UC_TXPARITY, ch);
++ }
++ } else if (sense & SNS0_CMD_REJECT) {
++ ctcm_pr_warn("%s: Command reject\n", ch->id);
++ } else if (sense == 0) {
++ ctcm_pr_debug("%s: Unit check ZERO\n", ch->id);
++ fsm_event(ch->fsm, CTC_EVENT_UC_ZERO, ch);
++ } else {
++ ctcm_pr_warn("%s: Unit Check with sense code: %02x\n",
++ ch->id, sense);
++ fsm_event(ch->fsm, CTC_EVENT_UC_UNKNOWN, ch);
++ }
++}
++
++int ctcm_ch_alloc_buffer(struct channel *ch)
++{
++ CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__);
++
++ clear_normalized_cda(&ch->ccw[1]);
++ ch->trans_skb = __dev_alloc_skb(ch->max_bufsize, GFP_ATOMIC | GFP_DMA);
++ if (ch->trans_skb == NULL) {
++ ctcm_pr_warn("%s: Couldn't alloc %s trans_skb\n",
++ ch->id,
++ (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
++ return -ENOMEM;
++ }
++
++ ch->ccw[1].count = ch->max_bufsize;
++ if (set_normalized_cda(&ch->ccw[1], ch->trans_skb->data)) {
++ dev_kfree_skb(ch->trans_skb);
++ ch->trans_skb = NULL;
++ ctcm_pr_warn("%s: set_normalized_cda for %s "
++ "trans_skb failed, dropping packets\n",
++ ch->id,
++ (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
++ return -ENOMEM;
++ }
++
++ ch->ccw[1].count = 0;
++ ch->trans_skb_data = ch->trans_skb->data;
++ ch->flags &= ~CHANNEL_FLAGS_BUFSIZE_CHANGED;
++ return 0;
++}
++
++/*
++ * Interface API for upper network layers
++ */
++
++/**
++ * Open an interface.
++ * Called from generic network layer when ifconfig up is run.
++ *
++ * dev Pointer to interface struct.
++ *
++ * returns 0 on success, -ERRNO on failure. (Never fails.)
++ */
++int ctcm_open(struct net_device *dev)
++{
++ struct ctcm_priv *priv = dev->priv;
++
++ CTCMY_DBF_DEV_NAME(SETUP, dev, "");
++ if (!IS_MPC(priv))
++ fsm_event(priv->fsm, DEV_EVENT_START, dev);
++ return 0;
++}
++
++/**
++ * Close an interface.
++ * Called from generic network layer when ifconfig down is run.
++ *
++ * dev Pointer to interface struct.
++ *
++ * returns 0 on success, -ERRNO on failure. (Never fails.)
++ */
++int ctcm_close(struct net_device *dev)
++{
++ struct ctcm_priv *priv = dev->priv;
++
++ CTCMY_DBF_DEV_NAME(SETUP, dev, "");
++ if (!IS_MPC(priv))
++ fsm_event(priv->fsm, DEV_EVENT_STOP, dev);
++ return 0;
++}
++
++
++/**
++ * Transmit a packet.
++ * This is a helper function for ctcm_tx().
++ *
++ * ch Channel to be used for sending.
++ * skb Pointer to struct sk_buff of packet to send.
++ * The linklevel header has already been set up
++ * by ctcm_tx().
++ *
++ * returns 0 on success, -ERRNO on failure. (Never fails.)
++ */
++static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
++{
++ unsigned long saveflags;
++ struct ll_header header;
++ int rc = 0;
++ __u16 block_len;
++ int ccw_idx;
++ struct sk_buff *nskb;
++ unsigned long hi;
++
++ /* we need to acquire the lock for testing the state
++ * otherwise we can have an IRQ changing the state to
++ * TXIDLE after the test but before acquiring the lock.
++ */
++ spin_lock_irqsave(&ch->collect_lock, saveflags);
++ if (fsm_getstate(ch->fsm) != CTC_STATE_TXIDLE) {
++ int l = skb->len + LL_HEADER_LENGTH;
++
++ if (ch->collect_len + l > ch->max_bufsize - 2) {
++ spin_unlock_irqrestore(&ch->collect_lock, saveflags);
++ return -EBUSY;
++ } else {
++ atomic_inc(&skb->users);
++ header.length = l;
++ header.type = skb->protocol;
++ header.unused = 0;
++ memcpy(skb_push(skb, LL_HEADER_LENGTH), &header,
++ LL_HEADER_LENGTH);
++ skb_queue_tail(&ch->collect_queue, skb);
++ ch->collect_len += l;
++ }
++ spin_unlock_irqrestore(&ch->collect_lock, saveflags);
++ goto done;
++ }
++ spin_unlock_irqrestore(&ch->collect_lock, saveflags);
++ /*
++ * Protect skb against beeing free'd by upper
++ * layers.
++ */
++ atomic_inc(&skb->users);
++ ch->prof.txlen += skb->len;
++ header.length = skb->len + LL_HEADER_LENGTH;
++ header.type = skb->protocol;
++ header.unused = 0;
++ memcpy(skb_push(skb, LL_HEADER_LENGTH), &header, LL_HEADER_LENGTH);
++ block_len = skb->len + 2;
++ *((__u16 *)skb_push(skb, 2)) = block_len;
++
++ /*
++ * IDAL support in CTCM is broken, so we have to
++ * care about skb's above 2G ourselves.
++ */
++ hi = ((unsigned long)skb_tail_pointer(skb) + LL_HEADER_LENGTH) >> 31;
++ if (hi) {
++ nskb = alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
++ if (!nskb) {
++ atomic_dec(&skb->users);
++ skb_pull(skb, LL_HEADER_LENGTH + 2);
++ ctcm_clear_busy(ch->netdev);
++ return -ENOMEM;
++ } else {
++ memcpy(skb_put(nskb, skb->len), skb->data, skb->len);
++ atomic_inc(&nskb->users);
++ atomic_dec(&skb->users);
++ dev_kfree_skb_irq(skb);
++ skb = nskb;
++ }
++ }
++
++ ch->ccw[4].count = block_len;
++ if (set_normalized_cda(&ch->ccw[4], skb->data)) {
++ /*
++ * idal allocation failed, try via copying to
++ * trans_skb. trans_skb usually has a pre-allocated
++ * idal.
++ */
++ if (ctcm_checkalloc_buffer(ch)) {
++ /*
++ * Remove our header. It gets added
++ * again on retransmit.
++ */
++ atomic_dec(&skb->users);
++ skb_pull(skb, LL_HEADER_LENGTH + 2);
++ ctcm_clear_busy(ch->netdev);
++ return -EBUSY;
++ }
++
++ skb_reset_tail_pointer(ch->trans_skb);
++ ch->trans_skb->len = 0;
++ ch->ccw[1].count = skb->len;
++ skb_copy_from_linear_data(skb,
++ skb_put(ch->trans_skb, skb->len), skb->len);
++ atomic_dec(&skb->users);
++ dev_kfree_skb_irq(skb);
++ ccw_idx = 0;
++ } else {
++ skb_queue_tail(&ch->io_queue, skb);
++ ccw_idx = 3;
++ }
++ ch->retry = 0;
++ fsm_newstate(ch->fsm, CTC_STATE_TX);
++ fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
++ spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
++ ch->prof.send_stamp = current_kernel_time(); /* xtime */
++ rc = ccw_device_start(ch->cdev, &ch->ccw[ccw_idx],
++ (unsigned long)ch, 0xff, 0);
++ spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
++ if (ccw_idx == 3)
++ ch->prof.doios_single++;
++ if (rc != 0) {
++ fsm_deltimer(&ch->timer);
++ ctcm_ccw_check_rc(ch, rc, "single skb TX");
++ if (ccw_idx == 3)
++ skb_dequeue_tail(&ch->io_queue);
++ /*
++ * Remove our header. It gets added
++ * again on retransmit.
++ */
++ skb_pull(skb, LL_HEADER_LENGTH + 2);
++ } else if (ccw_idx == 0) {
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++ priv->stats.tx_packets++;
++ priv->stats.tx_bytes += skb->len - LL_HEADER_LENGTH;
++ }
++done:
++ ctcm_clear_busy(ch->netdev);
++ return rc;
++}
++
++static void ctcmpc_send_sweep_req(struct channel *rch)
++{
++ struct net_device *dev = rch->netdev;
++ struct ctcm_priv *priv;
++ struct mpc_group *grp;
++ struct th_sweep *header;
++ struct sk_buff *sweep_skb;
++ struct channel *ch;
++ int rc = 0;
++
++ priv = dev->priv;
++ grp = priv->mpcg;
++ ch = priv->channel[WRITE];
++
++ if (do_debug)
++ MPC_DBF_DEV_NAME(TRACE, dev, ch->id);
++
++ /* sweep processing is not complete until response and request */
++ /* has completed for all read channels in group */
++ if (grp->in_sweep == 0) {
++ grp->in_sweep = 1;
++ grp->sweep_rsp_pend_num = grp->active_channels[READ];
++ grp->sweep_req_pend_num = grp->active_channels[READ];
++ }
++
++ sweep_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC|GFP_DMA);
++
++ if (sweep_skb == NULL) {
++ printk(KERN_INFO "Couldn't alloc sweep_skb\n");
++ rc = -ENOMEM;
++ goto done;
++ }
++
++ header = kmalloc(TH_SWEEP_LENGTH, gfp_type());
++
++ if (!header) {
++ dev_kfree_skb_any(sweep_skb);
++ rc = -ENOMEM;
++ goto done;
++ }
++
++ header->th.th_seg = 0x00 ;
++ header->th.th_ch_flag = TH_SWEEP_REQ; /* 0x0f */
++ header->th.th_blk_flag = 0x00;
++ header->th.th_is_xid = 0x00;
++ header->th.th_seq_num = 0x00;
++ header->sw.th_last_seq = ch->th_seq_num;
++
++ memcpy(skb_put(sweep_skb, TH_SWEEP_LENGTH), header, TH_SWEEP_LENGTH);
++
++ kfree(header);
++
++ dev->trans_start = jiffies;
++ skb_queue_tail(&ch->sweep_queue, sweep_skb);
++
++ fsm_addtimer(&ch->sweep_timer, 100, CTC_EVENT_RSWEEP_TIMER, ch);
++
++ return;
++
++done:
++ if (rc != 0) {
++ grp->in_sweep = 0;
++ ctcm_clear_busy(dev);
++ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++ }
++
++ return;
++}
++
++/*
++ * MPC mode version of transmit_skb
++ */
++static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
++{
++ struct pdu *p_header;
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++ struct mpc_group *grp = priv->mpcg;
++ struct th_header *header;
++ struct sk_buff *nskb;
++ int rc = 0;
++ int ccw_idx;
++ unsigned long hi;
++ unsigned long saveflags = 0; /* avoids compiler warning */
++ __u16 block_len;
++
++ if (do_debug)
++ ctcm_pr_debug(
++ "ctcm enter: %s(): %s cp=%i ch=0x%p id=%s state=%s\n",
++ __FUNCTION__, dev->name, smp_processor_id(), ch,
++ ch->id, fsm_getstate_str(ch->fsm));
++
++ if ((fsm_getstate(ch->fsm) != CTC_STATE_TXIDLE) || grp->in_sweep) {
++ spin_lock_irqsave(&ch->collect_lock, saveflags);
++ atomic_inc(&skb->users);
++ p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type());
++
++ if (!p_header) {
++ printk(KERN_WARNING "ctcm: OUT OF MEMORY IN %s():"
++ " Data Lost \n", __FUNCTION__);
++
++ atomic_dec(&skb->users);
++ dev_kfree_skb_any(skb);
++ spin_unlock_irqrestore(&ch->collect_lock, saveflags);
++ fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
++ goto done;
++ }
++
++ p_header->pdu_offset = skb->len;
++ p_header->pdu_proto = 0x01;
++ p_header->pdu_flag = 0x00;
++ if (skb->protocol == ntohs(ETH_P_SNAP)) {
++ p_header->pdu_flag |= PDU_FIRST | PDU_CNTL;
++ } else {
++ p_header->pdu_flag |= PDU_FIRST;
++ }
++ p_header->pdu_seq = 0;
++ memcpy(skb_push(skb, PDU_HEADER_LENGTH), p_header,
++ PDU_HEADER_LENGTH);
++
++ if (do_debug_data) {
++ ctcm_pr_debug("ctcm: %s() Putting on collect_q"
++ " - skb len: %04x \n", __FUNCTION__, skb->len);
++ ctcm_pr_debug("ctcm: %s() pdu header and data"
++ " for up to 32 bytes\n", __FUNCTION__);
++ ctcmpc_dump32((char *)skb->data, skb->len);
++ }
++
++ skb_queue_tail(&ch->collect_queue, skb);
++ ch->collect_len += skb->len;
++ kfree(p_header);
++
++ spin_unlock_irqrestore(&ch->collect_lock, saveflags);
++ goto done;
++ }
++
++ /*
++ * Protect skb against beeing free'd by upper
++ * layers.
++ */
++ atomic_inc(&skb->users);
++
++ block_len = skb->len + TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
++ /*
++ * IDAL support in CTCM is broken, so we have to
++ * care about skb's above 2G ourselves.
++ */
++ hi = ((unsigned long)skb->tail + TH_HEADER_LENGTH) >> 31;
++ if (hi) {
++ nskb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
++ if (!nskb) {
++ printk(KERN_WARNING "ctcm: %s() OUT OF MEMORY"
++ "- Data Lost \n", __FUNCTION__);
++ atomic_dec(&skb->users);
++ dev_kfree_skb_any(skb);
++ fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
++ goto done;
++ } else {
++ memcpy(skb_put(nskb, skb->len), skb->data, skb->len);
++ atomic_inc(&nskb->users);
++ atomic_dec(&skb->users);
++ dev_kfree_skb_irq(skb);
++ skb = nskb;
++ }
++ }
++
++ p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type());
++
++ if (!p_header) {
++ printk(KERN_WARNING "ctcm: %s() OUT OF MEMORY"
++ ": Data Lost \n", __FUNCTION__);
++
++ atomic_dec(&skb->users);
++ dev_kfree_skb_any(skb);
++ fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
++ goto done;
++ }
++
++ p_header->pdu_offset = skb->len;
++ p_header->pdu_proto = 0x01;
++ p_header->pdu_flag = 0x00;
++ p_header->pdu_seq = 0;
++ if (skb->protocol == ntohs(ETH_P_SNAP)) {
++ p_header->pdu_flag |= PDU_FIRST | PDU_CNTL;
++ } else {
++ p_header->pdu_flag |= PDU_FIRST;
++ }
++ memcpy(skb_push(skb, PDU_HEADER_LENGTH), p_header, PDU_HEADER_LENGTH);
++
++ kfree(p_header);
++
++ if (ch->collect_len > 0) {
++ spin_lock_irqsave(&ch->collect_lock, saveflags);
++ skb_queue_tail(&ch->collect_queue, skb);
++ ch->collect_len += skb->len;
++ skb = skb_dequeue(&ch->collect_queue);
++ ch->collect_len -= skb->len;
++ spin_unlock_irqrestore(&ch->collect_lock, saveflags);
++ }
++
++ p_header = (struct pdu *)skb->data;
++ p_header->pdu_flag |= PDU_LAST;
++
++ ch->prof.txlen += skb->len - PDU_HEADER_LENGTH;
++
++ header = kmalloc(TH_HEADER_LENGTH, gfp_type());
++
++ if (!header) {
++ printk(KERN_WARNING "ctcm: %s() OUT OF MEMORY: Data Lost \n",
++ __FUNCTION__);
++ atomic_dec(&skb->users);
++ dev_kfree_skb_any(skb);
++ fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
++ goto done;
++ }
++
++ header->th_seg = 0x00;
++ header->th_ch_flag = TH_HAS_PDU; /* Normal data */
++ header->th_blk_flag = 0x00;
++ header->th_is_xid = 0x00; /* Just data here */
++ ch->th_seq_num++;
++ header->th_seq_num = ch->th_seq_num;
++
++ if (do_debug_data)
++ ctcm_pr_debug("ctcm: %s() ToVTAM_th_seq= %08x\n" ,
++ __FUNCTION__, ch->th_seq_num);
++
++ /* put the TH on the packet */
++ memcpy(skb_push(skb, TH_HEADER_LENGTH), header, TH_HEADER_LENGTH);
++
++ kfree(header);
++
++ if (do_debug_data) {
++ ctcm_pr_debug("ctcm: %s(): skb len: %04x \n",
++ __FUNCTION__, skb->len);
++ ctcm_pr_debug("ctcm: %s(): pdu header and data for up to 32 "
++ "bytes sent to vtam\n", __FUNCTION__);
++ ctcmpc_dump32((char *)skb->data, skb->len);
++ }
++
++ ch->ccw[4].count = skb->len;
++ if (set_normalized_cda(&ch->ccw[4], skb->data)) {
++ /*
++ * idal allocation failed, try via copying to
++ * trans_skb. trans_skb usually has a pre-allocated
++ * idal.
++ */
++ if (ctcm_checkalloc_buffer(ch)) {
++ /*
++ * Remove our header. It gets added
++ * again on retransmit.
++ */
++ atomic_dec(&skb->users);
++ dev_kfree_skb_any(skb);
++ printk(KERN_WARNING "ctcm: %s()OUT OF MEMORY:"
++ " Data Lost \n", __FUNCTION__);
++ fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
++ goto done;
++ }
++
++ skb_reset_tail_pointer(ch->trans_skb);
++ ch->trans_skb->len = 0;
++ ch->ccw[1].count = skb->len;
++ memcpy(skb_put(ch->trans_skb, skb->len), skb->data, skb->len);
++ atomic_dec(&skb->users);
++ dev_kfree_skb_irq(skb);
++ ccw_idx = 0;
++ if (do_debug_data) {
++ ctcm_pr_debug("ctcm: %s() TRANS skb len: %d \n",
++ __FUNCTION__, ch->trans_skb->len);
++ ctcm_pr_debug("ctcm: %s up to 32 bytes of data"
++ " sent to vtam\n", __FUNCTION__);
++ ctcmpc_dump32((char *)ch->trans_skb->data,
++ ch->trans_skb->len);
++ }
++ } else {
++ skb_queue_tail(&ch->io_queue, skb);
++ ccw_idx = 3;
++ }
++ ch->retry = 0;
++ fsm_newstate(ch->fsm, CTC_STATE_TX);
++ fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
++
++ if (do_debug_ccw)
++ ctcmpc_dumpit((char *)&ch->ccw[ccw_idx],
++ sizeof(struct ccw1) * 3);
++
++ spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
++ ch->prof.send_stamp = current_kernel_time(); /* xtime */
++ rc = ccw_device_start(ch->cdev, &ch->ccw[ccw_idx],
++ (unsigned long)ch, 0xff, 0);
++ spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
++ if (ccw_idx == 3)
++ ch->prof.doios_single++;
++ if (rc != 0) {
++ fsm_deltimer(&ch->timer);
++ ctcm_ccw_check_rc(ch, rc, "single skb TX");
++ if (ccw_idx == 3)
++ skb_dequeue_tail(&ch->io_queue);
++ } else if (ccw_idx == 0) {
++ priv->stats.tx_packets++;
++ priv->stats.tx_bytes += skb->len - TH_HEADER_LENGTH;
++ }
++ if (ch->th_seq_num > 0xf0000000) /* Chose 4Billion at random. */
++ ctcmpc_send_sweep_req(ch);
++
++done:
++ if (do_debug)
++ ctcm_pr_debug("ctcm exit: %s %s()\n", dev->name, __FUNCTION__);
++ return 0;
++}
++
++/**
++ * Start transmission of a packet.
++ * Called from generic network device layer.
++ *
++ * skb Pointer to buffer containing the packet.
++ * dev Pointer to interface struct.
++ *
++ * returns 0 if packet consumed, !0 if packet rejected.
++ * Note: If we return !0, then the packet is free'd by
++ * the generic network layer.
++ */
++/* first merge version - leaving both functions separated */
++static int ctcm_tx(struct sk_buff *skb, struct net_device *dev)
++{
++ int rc = 0;
++ struct ctcm_priv *priv;
++
++ CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__);
++ priv = dev->priv;
++
++ if (skb == NULL) {
++ ctcm_pr_warn("%s: NULL sk_buff passed\n", dev->name);
++ priv->stats.tx_dropped++;
++ return 0;
++ }
++ if (skb_headroom(skb) < (LL_HEADER_LENGTH + 2)) {
++ ctcm_pr_warn("%s: Got sk_buff with head room < %ld bytes\n",
++ dev->name, LL_HEADER_LENGTH + 2);
++ dev_kfree_skb(skb);
++ priv->stats.tx_dropped++;
++ return 0;
++ }
++
++ /*
++ * If channels are not running, try to restart them
++ * and throw away packet.
++ */
++ if (fsm_getstate(priv->fsm) != DEV_STATE_RUNNING) {
++ fsm_event(priv->fsm, DEV_EVENT_START, dev);
++ dev_kfree_skb(skb);
++ priv->stats.tx_dropped++;
++ priv->stats.tx_errors++;
++ priv->stats.tx_carrier_errors++;
++ return 0;
++ }
++
++ if (ctcm_test_and_set_busy(dev))
++ return -EBUSY;
++
++ dev->trans_start = jiffies;
++ if (ctcm_transmit_skb(priv->channel[WRITE], skb) != 0)
++ rc = 1;
++ return rc;
++}
++
++/* unmerged MPC variant of ctcm_tx */
++static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev)
++{
++ int len = 0;
++ struct ctcm_priv *priv = NULL;
++ struct mpc_group *grp = NULL;
++ struct sk_buff *newskb = NULL;
++
++ if (do_debug)
++ ctcm_pr_debug("ctcmpc enter: %s(): skb:%0lx\n",
++ __FUNCTION__, (unsigned long)skb);
++
++ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
++ "ctcmpc enter: %s(): skb:%0lx\n",
++ __FUNCTION__, (unsigned long)skb);
++
++ priv = dev->priv;
++ grp = priv->mpcg;
++ /*
++ * Some sanity checks ...
++ */
++ if (skb == NULL) {
++ ctcm_pr_warn("ctcmpc: %s: NULL sk_buff passed\n", dev->name);
++ priv->stats.tx_dropped++;
++ goto done;
++ }
++ if (skb_headroom(skb) < (TH_HEADER_LENGTH + PDU_HEADER_LENGTH)) {
++ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_WARN,
++ "%s: Got sk_buff with head room < %ld bytes\n",
++ dev->name, TH_HEADER_LENGTH + PDU_HEADER_LENGTH);
++
++ if (do_debug_data)
++ ctcmpc_dump32((char *)skb->data, skb->len);
++
++ len = skb->len + TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
++ newskb = __dev_alloc_skb(len, gfp_type() | GFP_DMA);
++
++ if (!newskb) {
++ printk(KERN_WARNING "ctcmpc: %s() OUT OF MEMORY-"
++ "Data Lost\n",
++ __FUNCTION__);
++
++ dev_kfree_skb_any(skb);
++ priv->stats.tx_dropped++;
++ priv->stats.tx_errors++;
++ priv->stats.tx_carrier_errors++;
++ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++ goto done;
++ }
++ newskb->protocol = skb->protocol;
++ skb_reserve(newskb, TH_HEADER_LENGTH + PDU_HEADER_LENGTH);
++ memcpy(skb_put(newskb, skb->len), skb->data, skb->len);
++ dev_kfree_skb_any(skb);
++ skb = newskb;
++ }
++
++ /*
++ * If channels are not running,
++ * notify anybody about a link failure and throw
++ * away packet.
++ */
++ if ((fsm_getstate(priv->fsm) != DEV_STATE_RUNNING) ||
++ (fsm_getstate(grp->fsm) < MPCG_STATE_XID2INITW)) {
++ dev_kfree_skb_any(skb);
++ printk(KERN_INFO "ctcmpc: %s() DATA RCVD - MPC GROUP "
++ "NOT ACTIVE - DROPPED\n",
++ __FUNCTION__);
++ priv->stats.tx_dropped++;
++ priv->stats.tx_errors++;
++ priv->stats.tx_carrier_errors++;
++ goto done;
++ }
++
++ if (ctcm_test_and_set_busy(dev)) {
++ printk(KERN_WARNING "%s:DEVICE ERR - UNRECOVERABLE DATA LOSS\n",
++ __FUNCTION__);
++ dev_kfree_skb_any(skb);
++ priv->stats.tx_dropped++;
++ priv->stats.tx_errors++;
++ priv->stats.tx_carrier_errors++;
++ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++ goto done;
++ }
++
++ dev->trans_start = jiffies;
++ if (ctcmpc_transmit_skb(priv->channel[WRITE], skb) != 0) {
++ printk(KERN_WARNING "ctcmpc: %s() DEVICE ERROR"
++ ": Data Lost \n",
++ __FUNCTION__);
++ printk(KERN_WARNING "ctcmpc: %s() DEVICE ERROR"
++ " - UNRECOVERABLE DATA LOSS\n",
++ __FUNCTION__);
++ dev_kfree_skb_any(skb);
++ priv->stats.tx_dropped++;
++ priv->stats.tx_errors++;
++ priv->stats.tx_carrier_errors++;
++ ctcm_clear_busy(dev);
++ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++ goto done;
++ }
++ ctcm_clear_busy(dev);
++done:
++ if (do_debug)
++ MPC_DBF_DEV_NAME(TRACE, dev, "exit");
++
++ return 0; /* handle freeing of skb here */
++}
++
++
++/**
++ * Sets MTU of an interface.
++ *
++ * dev Pointer to interface struct.
++ * new_mtu The new MTU to use for this interface.
++ *
++ * returns 0 on success, -EINVAL if MTU is out of valid range.
++ * (valid range is 576 .. 65527). If VM is on the
++ * remote side, maximum MTU is 32760, however this is
++ * not checked here.
++ */
++static int ctcm_change_mtu(struct net_device *dev, int new_mtu)
++{
++ struct ctcm_priv *priv;
++ int max_bufsize;
++
++ CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
++
++ if (new_mtu < 576 || new_mtu > 65527)
++ return -EINVAL;
++
++ priv = dev->priv;
++ max_bufsize = priv->channel[READ]->max_bufsize;
++
++ if (IS_MPC(priv)) {
++ if (new_mtu > max_bufsize - TH_HEADER_LENGTH)
++ return -EINVAL;
++ dev->hard_header_len = TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
++ } else {
++ if (new_mtu > max_bufsize - LL_HEADER_LENGTH - 2)
++ return -EINVAL;
++ dev->hard_header_len = LL_HEADER_LENGTH + 2;
++ }
++ dev->mtu = new_mtu;
++ return 0;
++}
++
++/**
++ * Returns interface statistics of a device.
++ *
++ * dev Pointer to interface struct.
++ *
++ * returns Pointer to stats struct of this interface.
++ */
++static struct net_device_stats *ctcm_stats(struct net_device *dev)
++{
++ return &((struct ctcm_priv *)dev->priv)->stats;
++}
++
++
++static void ctcm_netdev_unregister(struct net_device *dev)
++{
++ CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
++ if (!dev)
++ return;
++ unregister_netdev(dev);
++}
++
++static int ctcm_netdev_register(struct net_device *dev)
++{
++ CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
++ return register_netdev(dev);
++}
++
++static void ctcm_free_netdevice(struct net_device *dev)
++{
++ struct ctcm_priv *priv;
++ struct mpc_group *grp;
++
++ CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
++
++ if (!dev)
++ return;
++ priv = dev->priv;
++ if (priv) {
++ grp = priv->mpcg;
++ if (grp) {
++ if (grp->fsm)
++ kfree_fsm(grp->fsm);
++ if (grp->xid_skb)
++ dev_kfree_skb(grp->xid_skb);
++ if (grp->rcvd_xid_skb)
++ dev_kfree_skb(grp->rcvd_xid_skb);
++ tasklet_kill(&grp->mpc_tasklet2);
++ kfree(grp);
++ priv->mpcg = NULL;
++ }
++ if (priv->fsm) {
++ kfree_fsm(priv->fsm);
++ priv->fsm = NULL;
++ }
++ kfree(priv->xid);
++ priv->xid = NULL;
++ /*
++ * Note: kfree(priv); is done in "opposite" function of
++ * allocator function probe_device which is remove_device.
++ */
++ }
++#ifdef MODULE
++ free_netdev(dev);
++#endif
++}
++
++struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv);
++
++void static ctcm_dev_setup(struct net_device *dev)
++{
++ dev->open = ctcm_open;
++ dev->stop = ctcm_close;
++ dev->get_stats = ctcm_stats;
++ dev->change_mtu = ctcm_change_mtu;
++ dev->type = ARPHRD_SLIP;
++ dev->tx_queue_len = 100;
++ dev->flags = IFF_POINTOPOINT | IFF_NOARP;
++}
++
++/*
++ * Initialize everything of the net device except the name and the
++ * channel structs.
++ */
++static struct net_device *ctcm_init_netdevice(struct ctcm_priv *priv)
++{
++ struct net_device *dev;
++ struct mpc_group *grp;
++ if (!priv)
++ return NULL;
++
++ if (IS_MPC(priv))
++ dev = alloc_netdev(0, MPC_DEVICE_GENE, ctcm_dev_setup);
++ else
++ dev = alloc_netdev(0, CTC_DEVICE_GENE, ctcm_dev_setup);
++
++ if (!dev) {
++ ctcm_pr_err("%s: Out of memory\n", __FUNCTION__);
++ return NULL;
++ }
++ dev->priv = priv;
++ priv->fsm = init_fsm("ctcmdev", dev_state_names, dev_event_names,
++ CTCM_NR_DEV_STATES, CTCM_NR_DEV_EVENTS,
++ dev_fsm, dev_fsm_len, GFP_KERNEL);
++ if (priv->fsm == NULL) {
++ CTCMY_DBF_DEV(SETUP, dev, "init_fsm error");
++ kfree(dev);
++ return NULL;
++ }
++ fsm_newstate(priv->fsm, DEV_STATE_STOPPED);
++ fsm_settimer(priv->fsm, &priv->restart_timer);
++
++ if (IS_MPC(priv)) {
++ /* MPC Group Initializations */
++ grp = ctcmpc_init_mpc_group(priv);
++ if (grp == NULL) {
++ MPC_DBF_DEV(SETUP, dev, "init_mpc_group error");
++ kfree(dev);
++ return NULL;
++ }
++ tasklet_init(&grp->mpc_tasklet2,
++ mpc_group_ready, (unsigned long)dev);
++ dev->mtu = MPC_BUFSIZE_DEFAULT -
++ TH_HEADER_LENGTH - PDU_HEADER_LENGTH;
++
++ dev->hard_start_xmit = ctcmpc_tx;
++ dev->hard_header_len = TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
++ priv->buffer_size = MPC_BUFSIZE_DEFAULT;
++ } else {
++ dev->mtu = CTCM_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2;
++ dev->hard_start_xmit = ctcm_tx;
++ dev->hard_header_len = LL_HEADER_LENGTH + 2;
++ }
++
++ CTCMY_DBF_DEV(SETUP, dev, "finished");
++ return dev;
++}
++
++/**
++ * Main IRQ handler.
++ *
++ * cdev The ccw_device the interrupt is for.
++ * intparm interruption parameter.
++ * irb interruption response block.
++ */
++static void ctcm_irq_handler(struct ccw_device *cdev,
++ unsigned long intparm, struct irb *irb)
++{
++ struct channel *ch;
++ struct net_device *dev;
++ struct ctcm_priv *priv;
++ struct ccwgroup_device *cgdev;
++
++ CTCM_DBF_TEXT(TRACE, CTC_DBF_DEBUG, __FUNCTION__);
++ if (ctcm_check_irb_error(cdev, irb))
++ return;
++
++ cgdev = dev_get_drvdata(&cdev->dev);
++
++ /* Check for unsolicited interrupts. */
++ if (cgdev == NULL) {
++ ctcm_pr_warn("ctcm: Got unsolicited irq: %s c-%02x d-%02x\n",
++ cdev->dev.bus_id, irb->scsw.cstat,
++ irb->scsw.dstat);
++ return;
++ }
++
++ priv = dev_get_drvdata(&cgdev->dev);
++
++ /* Try to extract channel from driver data. */
++ if (priv->channel[READ]->cdev == cdev)
++ ch = priv->channel[READ];
++ else if (priv->channel[WRITE]->cdev == cdev)
++ ch = priv->channel[WRITE];
++ else {
++ ctcm_pr_err("ctcm: Can't determine channel for interrupt, "
++ "device %s\n", cdev->dev.bus_id);
++ return;
++ }
++
++ dev = (struct net_device *)(ch->netdev);
++ if (dev == NULL) {
++ ctcm_pr_crit("ctcm: %s dev=NULL bus_id=%s, ch=0x%p\n",
++ __FUNCTION__, cdev->dev.bus_id, ch);
++ return;
++ }
++
++ if (do_debug)
++ ctcm_pr_debug("%s: interrupt for device: %s "
++ "received c-%02x d-%02x\n",
++ dev->name,
++ ch->id,
++ irb->scsw.cstat,
++ irb->scsw.dstat);
++
++ /* Copy interruption response block. */
++ memcpy(ch->irb, irb, sizeof(struct irb));
++
++ /* Check for good subchannel return code, otherwise error message */
++ if (irb->scsw.cstat) {
++ fsm_event(ch->fsm, CTC_EVENT_SC_UNKNOWN, ch);
++ ctcm_pr_warn("%s: subchannel check for dev: %s - %02x %02x\n",
++ dev->name, ch->id, irb->scsw.cstat,
++ irb->scsw.dstat);
++ return;
++ }
++
++ /* Check the reason-code of a unit check */
++ if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK) {
++ ccw_unit_check(ch, irb->ecw[0]);
++ return;
++ }
++ if (irb->scsw.dstat & DEV_STAT_BUSY) {
++ if (irb->scsw.dstat & DEV_STAT_ATTENTION)
++ fsm_event(ch->fsm, CTC_EVENT_ATTNBUSY, ch);
++ else
++ fsm_event(ch->fsm, CTC_EVENT_BUSY, ch);
++ return;
++ }
++ if (irb->scsw.dstat & DEV_STAT_ATTENTION) {
++ fsm_event(ch->fsm, CTC_EVENT_ATTN, ch);
++ return;
++ }
++ if ((irb->scsw.stctl & SCSW_STCTL_SEC_STATUS) ||
++ (irb->scsw.stctl == SCSW_STCTL_STATUS_PEND) ||
++ (irb->scsw.stctl ==
++ (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))
++ fsm_event(ch->fsm, CTC_EVENT_FINSTAT, ch);
++ else
++ fsm_event(ch->fsm, CTC_EVENT_IRQ, ch);
++
++}
++
++/**
++ * Add ctcm specific attributes.
++ * Add ctcm private data.
++ *
++ * cgdev pointer to ccwgroup_device just added
++ *
++ * returns 0 on success, !0 on failure.
++ */
++static int ctcm_probe_device(struct ccwgroup_device *cgdev)
++{
++ struct ctcm_priv *priv;
++ int rc;
++
++ CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s %p", __FUNCTION__, cgdev);
++
++ if (!get_device(&cgdev->dev))
++ return -ENODEV;
++
++ priv = kzalloc(sizeof(struct ctcm_priv), GFP_KERNEL);
++ if (!priv) {
++ ctcm_pr_err("%s: Out of memory\n", __FUNCTION__);
++ put_device(&cgdev->dev);
++ return -ENOMEM;
++ }
++
++ rc = ctcm_add_files(&cgdev->dev);
++ if (rc) {
++ kfree(priv);
++ put_device(&cgdev->dev);
++ return rc;
++ }
++ priv->buffer_size = CTCM_BUFSIZE_DEFAULT;
++ cgdev->cdev[0]->handler = ctcm_irq_handler;
++ cgdev->cdev[1]->handler = ctcm_irq_handler;
++ dev_set_drvdata(&cgdev->dev, priv);
++
++ return 0;
++}
++
++/**
++ * Add a new channel to the list of channels.
++ * Keeps the channel list sorted.
++ *
++ * cdev The ccw_device to be added.
++ * type The type class of the new channel.
++ * priv Points to the private data of the ccwgroup_device.
++ *
++ * returns 0 on success, !0 on error.
++ */
++static int add_channel(struct ccw_device *cdev, enum channel_types type,
++ struct ctcm_priv *priv)
++{
++ struct channel **c = &channels;
++ struct channel *ch;
++ int ccw_num;
++ int rc = 0;
++
++ CTCM_DBF_TEXT(TRACE, 2, __FUNCTION__);
++ ch = kzalloc(sizeof(struct channel), GFP_KERNEL);
++ if (ch == NULL)
++ goto nomem_return;
++
++ ch->protocol = priv->protocol;
++ if (IS_MPC(priv)) {
++ ch->discontact_th = (struct th_header *)
++ kzalloc(TH_HEADER_LENGTH, gfp_type());
++ if (ch->discontact_th == NULL)
++ goto nomem_return;
++
++ ch->discontact_th->th_blk_flag = TH_DISCONTACT;
++ tasklet_init(&ch->ch_disc_tasklet,
++ mpc_action_send_discontact, (unsigned long)ch);
++
++ tasklet_init(&ch->ch_tasklet, ctcmpc_bh, (unsigned long)ch);
++ ch->max_bufsize = (MPC_BUFSIZE_DEFAULT - 35);
++ ccw_num = 17;
++ } else
++ ccw_num = 8;
++
++ ch->ccw = (struct ccw1 *)
++ kzalloc(ccw_num * sizeof(struct ccw1), GFP_KERNEL | GFP_DMA);
++ if (ch->ccw == NULL)
++ goto nomem_return;
++
++ ch->cdev = cdev;
++ snprintf(ch->id, CTCM_ID_SIZE, "ch-%s", cdev->dev.bus_id);
++ ch->type = type;
++
++ /**
++ * "static" ccws are used in the following way:
++ *
++ * ccw[0..2] (Channel program for generic I/O):
++ * 0: prepare
++ * 1: read or write (depending on direction) with fixed
++ * buffer (idal allocated once when buffer is allocated)
++ * 2: nop
++ * ccw[3..5] (Channel program for direct write of packets)
++ * 3: prepare
++ * 4: write (idal allocated on every write).
++ * 5: nop
++ * ccw[6..7] (Channel program for initial channel setup):
++ * 6: set extended mode
++ * 7: nop
++ *
++ * ch->ccw[0..5] are initialized in ch_action_start because
++ * the channel's direction is yet unknown here.
++ *
++ * ccws used for xid2 negotiations
++ * ch-ccw[8-14] need to be used for the XID exchange either
++ * X side XID2 Processing
++ * 8: write control
++ * 9: write th
++ * 10: write XID
++ * 11: read th from secondary
++ * 12: read XID from secondary
++ * 13: read 4 byte ID
++ * 14: nop
++ * Y side XID Processing
++ * 8: sense
++ * 9: read th
++ * 10: read XID
++ * 11: write th
++ * 12: write XID
++ * 13: write 4 byte ID
++ * 14: nop
++ *
++ * ccws used for double noop due to VM timing issues
++ * which result in unrecoverable Busy on channel
++ * 15: nop
++ * 16: nop
++ */
++ ch->ccw[6].cmd_code = CCW_CMD_SET_EXTENDED;
++ ch->ccw[6].flags = CCW_FLAG_SLI;
++
++ ch->ccw[7].cmd_code = CCW_CMD_NOOP;
++ ch->ccw[7].flags = CCW_FLAG_SLI;
++
++ if (IS_MPC(priv)) {
++ ch->ccw[15].cmd_code = CCW_CMD_WRITE;
++ ch->ccw[15].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
++ ch->ccw[15].count = TH_HEADER_LENGTH;
++ ch->ccw[15].cda = virt_to_phys(ch->discontact_th);
++
++ ch->ccw[16].cmd_code = CCW_CMD_NOOP;
++ ch->ccw[16].flags = CCW_FLAG_SLI;
++
++ ch->fsm = init_fsm(ch->id, ctc_ch_state_names,
++ ctc_ch_event_names, CTC_MPC_NR_STATES,
++ CTC_MPC_NR_EVENTS, ctcmpc_ch_fsm,
++ mpc_ch_fsm_len, GFP_KERNEL);
++ } else {
++ ch->fsm = init_fsm(ch->id, ctc_ch_state_names,
++ ctc_ch_event_names, CTC_NR_STATES,
++ CTC_NR_EVENTS, ch_fsm,
++ ch_fsm_len, GFP_KERNEL);
++ }
++ if (ch->fsm == NULL)
++ goto free_return;
++
++ fsm_newstate(ch->fsm, CTC_STATE_IDLE);
++
++ ch->irb = kzalloc(sizeof(struct irb), GFP_KERNEL);
++ if (ch->irb == NULL)
++ goto nomem_return;
++
++ while (*c && ctcm_less_than((*c)->id, ch->id))
++ c = &(*c)->next;
++
++ if (*c && (!strncmp((*c)->id, ch->id, CTCM_ID_SIZE))) {
++ CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
++ "%s (%s) already in list, using old entry",
++ __FUNCTION__, (*c)->id);
++
++ goto free_return;
++ }
++
++ spin_lock_init(&ch->collect_lock);
++
++ fsm_settimer(ch->fsm, &ch->timer);
++ skb_queue_head_init(&ch->io_queue);
++ skb_queue_head_init(&ch->collect_queue);
++
++ if (IS_MPC(priv)) {
++ fsm_settimer(ch->fsm, &ch->sweep_timer);
++ skb_queue_head_init(&ch->sweep_queue);
++ }
++ ch->next = *c;
++ *c = ch;
++ return 0;
++
++nomem_return:
++ ctcm_pr_warn("ctcm: Out of memory in %s\n", __FUNCTION__);
++ rc = -ENOMEM;
++
++free_return: /* note that all channel pointers are 0 or valid */
++ kfree(ch->ccw); /* TODO: check that again */
++ kfree(ch->discontact_th);
++ kfree_fsm(ch->fsm);
++ kfree(ch->irb);
++ kfree(ch);
++ return rc;
++}
++
++/*
++ * Return type of a detected device.
++ */
++static enum channel_types get_channel_type(struct ccw_device_id *id)
++{
++ enum channel_types type;
++ type = (enum channel_types)id->driver_info;
++
++ if (type == channel_type_ficon)
++ type = channel_type_escon;
++
++ return type;
++}
++
++/**
++ *
++ * Setup an interface.
++ *
++ * cgdev Device to be setup.
++ *
++ * returns 0 on success, !0 on failure.
++ */
++static int ctcm_new_device(struct ccwgroup_device *cgdev)
++{
++ char read_id[CTCM_ID_SIZE];
++ char write_id[CTCM_ID_SIZE];
++ int direction;
++ enum channel_types type;
++ struct ctcm_priv *priv;
++ struct net_device *dev;
++ int ret;
++
++ CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
++
++ priv = dev_get_drvdata(&cgdev->dev);
++ if (!priv)
++ return -ENODEV;
++
++ type = get_channel_type(&cgdev->cdev[0]->id);
++
++ snprintf(read_id, CTCM_ID_SIZE, "ch-%s", cgdev->cdev[0]->dev.bus_id);
++ snprintf(write_id, CTCM_ID_SIZE, "ch-%s", cgdev->cdev[1]->dev.bus_id);
++
++ ret = add_channel(cgdev->cdev[0], type, priv);
++ if (ret)
++ return ret;
++ ret = add_channel(cgdev->cdev[1], type, priv);
++ if (ret)
++ return ret;
++
++ ret = ccw_device_set_online(cgdev->cdev[0]);
++ if (ret != 0) {
++ CTCM_DBF_TEXT(SETUP, CTC_DBF_WARN,
++ "ccw_device_set_online (cdev[0]) failed ");
++ ctcm_pr_warn("ccw_device_set_online (cdev[0]) failed "
++ "with ret = %d\n", ret);
++ }
++
++ ret = ccw_device_set_online(cgdev->cdev[1]);
++ if (ret != 0) {
++ CTCM_DBF_TEXT(SETUP, CTC_DBF_WARN,
++ "ccw_device_set_online (cdev[1]) failed ");
++ ctcm_pr_warn("ccw_device_set_online (cdev[1]) failed "
++ "with ret = %d\n", ret);
++ }
++
++ dev = ctcm_init_netdevice(priv);
++
++ if (dev == NULL) {
++ ctcm_pr_warn("ctcm_init_netdevice failed\n");
++ goto out;
++ }
++
++ for (direction = READ; direction <= WRITE; direction++) {
++ priv->channel[direction] =
++ channel_get(type, direction == READ ? read_id : write_id,
++ direction);
++ if (priv->channel[direction] == NULL) {
++ if (direction == WRITE)
++ channel_free(priv->channel[READ]);
++ ctcm_free_netdevice(dev);
++ goto out;
++ }
++ priv->channel[direction]->netdev = dev;
++ priv->channel[direction]->protocol = priv->protocol;
++ priv->channel[direction]->max_bufsize = priv->buffer_size;
++ }
++ /* sysfs magic */
++ SET_NETDEV_DEV(dev, &cgdev->dev);
++
++ if (ctcm_netdev_register(dev) != 0) {
++ ctcm_free_netdevice(dev);
++ goto out;
++ }
++
++ if (ctcm_add_attributes(&cgdev->dev)) {
++ ctcm_netdev_unregister(dev);
++/* dev->priv = NULL; why that ???? */
++ ctcm_free_netdevice(dev);
++ goto out;
++ }
++
++ strlcpy(priv->fsm->name, dev->name, sizeof(priv->fsm->name));
++
++ CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
++ "setup(%s) ok : r/w = %s / %s, proto : %d",
++ dev->name, priv->channel[READ]->id,
++ priv->channel[WRITE]->id, priv->protocol);
++
++ return 0;
++out:
++ ccw_device_set_offline(cgdev->cdev[1]);
++ ccw_device_set_offline(cgdev->cdev[0]);
++
++ return -ENODEV;
++}
++
++/**
++ * Shutdown an interface.
++ *
++ * cgdev Device to be shut down.
++ *
++ * returns 0 on success, !0 on failure.
++ */
++static int ctcm_shutdown_device(struct ccwgroup_device *cgdev)
++{
++ struct ctcm_priv *priv;
++ struct net_device *dev;
++
++ priv = dev_get_drvdata(&cgdev->dev);
++ if (!priv)
++ return -ENODEV;
++
++ if (priv->channel[READ]) {
++ dev = priv->channel[READ]->netdev;
++ CTCM_DBF_DEV(SETUP, dev, "");
++ /* Close the device */
++ ctcm_close(dev);
++ dev->flags &= ~IFF_RUNNING;
++ ctcm_remove_attributes(&cgdev->dev);
++ channel_free(priv->channel[READ]);
++ } else
++ dev = NULL;
++
++ if (priv->channel[WRITE])
++ channel_free(priv->channel[WRITE]);
++
++ if (dev) {
++ ctcm_netdev_unregister(dev);
++/* dev->priv = NULL; why that ??? */
++ ctcm_free_netdevice(dev);
++ }
++
++ if (priv->fsm)
++ kfree_fsm(priv->fsm);
++
++ ccw_device_set_offline(cgdev->cdev[1]);
++ ccw_device_set_offline(cgdev->cdev[0]);
++
++ if (priv->channel[READ])
++ channel_remove(priv->channel[READ]);
++ if (priv->channel[WRITE])
++ channel_remove(priv->channel[WRITE]);
++ priv->channel[READ] = priv->channel[WRITE] = NULL;
++
++ return 0;
++
++}
++
++
++static void ctcm_remove_device(struct ccwgroup_device *cgdev)
++{
++ struct ctcm_priv *priv;
++
++ CTCM_DBF_TEXT(SETUP, CTC_DBF_ERROR, __FUNCTION__);
++
++ priv = dev_get_drvdata(&cgdev->dev);
++ if (!priv)
++ return;
++ if (cgdev->state == CCWGROUP_ONLINE)
++ ctcm_shutdown_device(cgdev);
++ ctcm_remove_files(&cgdev->dev);
++ dev_set_drvdata(&cgdev->dev, NULL);
++ kfree(priv);
++ put_device(&cgdev->dev);
++}
++
++static struct ccwgroup_driver ctcm_group_driver = {
++ .owner = THIS_MODULE,
++ .name = CTC_DRIVER_NAME,
++ .max_slaves = 2,
++ .driver_id = 0xC3E3C3D4, /* CTCM */
++ .probe = ctcm_probe_device,
++ .remove = ctcm_remove_device,
++ .set_online = ctcm_new_device,
++ .set_offline = ctcm_shutdown_device,
++};
++
++
++/*
++ * Module related routines
++ */
++
++/*
++ * Prepare to be unloaded. Free IRQ's and release all resources.
++ * This is called just before this module is unloaded. It is
++ * not called, if the usage count is !0, so we don't need to check
++ * for that.
++ */
++static void __exit ctcm_exit(void)
++{
++ unregister_cu3088_discipline(&ctcm_group_driver);
++ ctcm_unregister_dbf_views();
++ ctcm_pr_info("CTCM driver unloaded\n");
++}
++
++/*
++ * Print Banner.
++ */
++static void print_banner(void)
++{
++ printk(KERN_INFO "CTCM driver initialized\n");
++}
++
++/**
++ * Initialize module.
++ * This is called just after the module is loaded.
++ *
++ * returns 0 on success, !0 on error.
++ */
++static int __init ctcm_init(void)
++{
++ int ret;
++
++ channels = NULL;
++
++ ret = ctcm_register_dbf_views();
++ if (ret) {
++ ctcm_pr_crit("ctcm_init failed with ctcm_register_dbf_views "
++ "rc = %d\n", ret);
++ return ret;
++ }
++ ret = register_cu3088_discipline(&ctcm_group_driver);
++ if (ret) {
++ ctcm_unregister_dbf_views();
++ ctcm_pr_crit("ctcm_init failed with register_cu3088_discipline "
++ "(rc = %d)\n", ret);
++ return ret;
++ }
++ print_banner();
++ return ret;
++}
++
++module_init(ctcm_init);
++module_exit(ctcm_exit);
++
++MODULE_AUTHOR("Peter Tiedemann <ptiedem at de.ibm.com>");
++MODULE_DESCRIPTION("Network driver for S/390 CTC + CTCMPC (SNA)");
++MODULE_LICENSE("GPL");
++
+diff --git a/drivers/s390/net/ctcm_main.h b/drivers/s390/net/ctcm_main.h
+new file mode 100644
+index 0000000..95b0c0b
+--- /dev/null
++++ b/drivers/s390/net/ctcm_main.h
+@@ -0,0 +1,287 @@
++/*
++ * drivers/s390/net/ctcm_main.h
++ *
++ * Copyright IBM Corp. 2001, 2007
++ * Authors: Fritz Elfert (felfert at millenux.com)
++ * Peter Tiedemann (ptiedem at de.ibm.com)
++ */
++
++#ifndef _CTCM_MAIN_H_
++#define _CTCM_MAIN_H_
++
++#include <asm/ccwdev.h>
++#include <asm/ccwgroup.h>
++
++#include <linux/skbuff.h>
++#include <linux/netdevice.h>
++
++#include "fsm.h"
++#include "cu3088.h"
++#include "ctcm_dbug.h"
++#include "ctcm_mpc.h"
++
++#define CTC_DRIVER_NAME "ctcm"
++#define CTC_DEVICE_NAME "ctc"
++#define CTC_DEVICE_GENE "ctc%d"
++#define MPC_DEVICE_NAME "mpc"
++#define MPC_DEVICE_GENE "mpc%d"
++
++#define CHANNEL_FLAGS_READ 0
++#define CHANNEL_FLAGS_WRITE 1
++#define CHANNEL_FLAGS_INUSE 2
++#define CHANNEL_FLAGS_BUFSIZE_CHANGED 4
++#define CHANNEL_FLAGS_FAILED 8
++#define CHANNEL_FLAGS_WAITIRQ 16
++#define CHANNEL_FLAGS_RWMASK 1
++#define CHANNEL_DIRECTION(f) (f & CHANNEL_FLAGS_RWMASK)
++
++#define LOG_FLAG_ILLEGALPKT 1
++#define LOG_FLAG_ILLEGALSIZE 2
++#define LOG_FLAG_OVERRUN 4
++#define LOG_FLAG_NOMEM 8
++
++#define ctcm_pr_debug(fmt, arg...) printk(KERN_DEBUG fmt, ##arg)
++#define ctcm_pr_info(fmt, arg...) printk(KERN_INFO fmt, ##arg)
++#define ctcm_pr_notice(fmt, arg...) printk(KERN_NOTICE fmt, ##arg)
++#define ctcm_pr_warn(fmt, arg...) printk(KERN_WARNING fmt, ##arg)
++#define ctcm_pr_emerg(fmt, arg...) printk(KERN_EMERG fmt, ##arg)
++#define ctcm_pr_err(fmt, arg...) printk(KERN_ERR fmt, ##arg)
++#define ctcm_pr_crit(fmt, arg...) printk(KERN_CRIT fmt, ##arg)
++
++/*
++ * CCW commands, used in this driver.
++ */
++#define CCW_CMD_WRITE 0x01
++#define CCW_CMD_READ 0x02
++#define CCW_CMD_NOOP 0x03
++#define CCW_CMD_TIC 0x08
++#define CCW_CMD_SENSE_CMD 0x14
++#define CCW_CMD_WRITE_CTL 0x17
++#define CCW_CMD_SET_EXTENDED 0xc3
++#define CCW_CMD_PREPARE 0xe3
++
++#define CTCM_PROTO_S390 0
++#define CTCM_PROTO_LINUX 1
++#define CTCM_PROTO_LINUX_TTY 2
++#define CTCM_PROTO_OS390 3
++#define CTCM_PROTO_MPC 4
++#define CTCM_PROTO_MAX 4
++
++#define CTCM_BUFSIZE_LIMIT 65535
++#define CTCM_BUFSIZE_DEFAULT 32768
++#define MPC_BUFSIZE_DEFAULT CTCM_BUFSIZE_LIMIT
++
++#define CTCM_TIME_1_SEC 1000
++#define CTCM_TIME_5_SEC 5000
++#define CTCM_TIME_10_SEC 10000
++
++#define CTCM_INITIAL_BLOCKLEN 2
++
++#define READ 0
++#define WRITE 1
++
++#define CTCM_ID_SIZE BUS_ID_SIZE+3
++
++struct ctcm_profile {
++ unsigned long maxmulti;
++ unsigned long maxcqueue;
++ unsigned long doios_single;
++ unsigned long doios_multi;
++ unsigned long txlen;
++ unsigned long tx_time;
++ struct timespec send_stamp;
++};
++
++/*
++ * Definition of one channel
++ */
++struct channel {
++ struct channel *next;
++ char id[CTCM_ID_SIZE];
++ struct ccw_device *cdev;
++ /*
++ * Type of this channel.
++ * CTC/A or Escon for valid channels.
++ */
++ enum channel_types type;
++ /*
++ * Misc. flags. See CHANNEL_FLAGS_... below
++ */
++ __u32 flags;
++ __u16 protocol; /* protocol of this channel (4 = MPC) */
++ /*
++ * I/O and irq related stuff
++ */
++ struct ccw1 *ccw;
++ struct irb *irb;
++ /*
++ * RX/TX buffer size
++ */
++ int max_bufsize;
++ struct sk_buff *trans_skb; /* transmit/receive buffer */
++ struct sk_buff_head io_queue; /* universal I/O queue */
++ struct tasklet_struct ch_tasklet; /* MPC ONLY */
++ /*
++ * TX queue for collecting skb's during busy.
++ */
++ struct sk_buff_head collect_queue;
++ /*
++ * Amount of data in collect_queue.
++ */
++ int collect_len;
++ /*
++ * spinlock for collect_queue and collect_len
++ */
++ spinlock_t collect_lock;
++ /*
++ * Timer for detecting unresposive
++ * I/O operations.
++ */
++ fsm_timer timer;
++ /* MPC ONLY section begin */
++ __u32 th_seq_num; /* SNA TH seq number */
++ __u8 th_seg;
++ __u32 pdu_seq;
++ struct sk_buff *xid_skb;
++ char *xid_skb_data;
++ struct th_header *xid_th;
++ struct xid2 *xid;
++ char *xid_id;
++ struct th_header *rcvd_xid_th;
++ struct xid2 *rcvd_xid;
++ char *rcvd_xid_id;
++ __u8 in_mpcgroup;
++ fsm_timer sweep_timer;
++ struct sk_buff_head sweep_queue;
++ struct th_header *discontact_th;
++ struct tasklet_struct ch_disc_tasklet;
++ /* MPC ONLY section end */
++
++ int retry; /* retry counter for misc. operations */
++ fsm_instance *fsm; /* finite state machine of this channel */
++ struct net_device *netdev; /* corresponding net_device */
++ struct ctcm_profile prof;
++ unsigned char *trans_skb_data;
++ __u16 logflags;
++};
++
++struct ctcm_priv {
++ struct net_device_stats stats;
++ unsigned long tbusy;
++
++ /* The MPC group struct of this interface */
++ struct mpc_group *mpcg; /* MPC only */
++ struct xid2 *xid; /* MPC only */
++
++ /* The finite state machine of this interface */
++ fsm_instance *fsm;
++
++ /* The protocol of this device */
++ __u16 protocol;
++
++ /* Timer for restarting after I/O Errors */
++ fsm_timer restart_timer;
++
++ int buffer_size; /* ctc only */
++
++ struct channel *channel[2];
++};
++
++int ctcm_open(struct net_device *dev);
++int ctcm_close(struct net_device *dev);
++
++/*
++ * prototypes for non-static sysfs functions
++ */
++int ctcm_add_attributes(struct device *dev);
++void ctcm_remove_attributes(struct device *dev);
++int ctcm_add_files(struct device *dev);
++void ctcm_remove_files(struct device *dev);
++
++/*
++ * Compatibility macros for busy handling
++ * of network devices.
++ */
++static inline void ctcm_clear_busy_do(struct net_device *dev)
++{
++ clear_bit(0, &(((struct ctcm_priv *)dev->priv)->tbusy));
++ netif_wake_queue(dev);
++}
++
++static inline void ctcm_clear_busy(struct net_device *dev)
++{
++ struct mpc_group *grp;
++ grp = ((struct ctcm_priv *)dev->priv)->mpcg;
++
++ if (!(grp && grp->in_sweep))
++ ctcm_clear_busy_do(dev);
++}
++
++
++static inline int ctcm_test_and_set_busy(struct net_device *dev)
++{
++ netif_stop_queue(dev);
++ return test_and_set_bit(0, &(((struct ctcm_priv *)dev->priv)->tbusy));
++}
++
++extern int loglevel;
++extern struct channel *channels;
++
++void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb);
++
++/*
++ * Functions related to setup and device detection.
++ */
++
++static inline int ctcm_less_than(char *id1, char *id2)
++{
++ unsigned long dev1, dev2;
++
++ id1 = id1 + 5;
++ id2 = id2 + 5;
++
++ dev1 = simple_strtoul(id1, &id1, 16);
++ dev2 = simple_strtoul(id2, &id2, 16);
++
++ return (dev1 < dev2);
++}
++
++int ctcm_ch_alloc_buffer(struct channel *ch);
++
++static inline int ctcm_checkalloc_buffer(struct channel *ch)
++{
++ if (ch->trans_skb == NULL)
++ return ctcm_ch_alloc_buffer(ch);
++ if (ch->flags & CHANNEL_FLAGS_BUFSIZE_CHANGED) {
++ dev_kfree_skb(ch->trans_skb);
++ return ctcm_ch_alloc_buffer(ch);
++ }
++ return 0;
++}
++
++struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv);
++
++/* test if protocol attribute (of struct ctcm_priv or struct channel)
++ * has MPC protocol setting. Type is not checked
++ */
++#define IS_MPC(p) ((p)->protocol == CTCM_PROTO_MPC)
++
++/* test if struct ctcm_priv of struct net_device has MPC protocol setting */
++#define IS_MPCDEV(d) IS_MPC((struct ctcm_priv *)d->priv)
++
++static inline gfp_t gfp_type(void)
++{
++ return in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
++}
++
++/*
++ * Definition of our link level header.
++ */
++struct ll_header {
++ __u16 length;
++ __u16 type;
++ __u16 unused;
++};
++#define LL_HEADER_LENGTH (sizeof(struct ll_header))
++
++#endif
+diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c
+new file mode 100644
+index 0000000..044adde
+--- /dev/null
++++ b/drivers/s390/net/ctcm_mpc.c
+@@ -0,0 +1,2472 @@
++/*
++ * drivers/s390/net/ctcm_mpc.c
++ *
++ * Copyright IBM Corp. 2004, 2007
++ * Authors: Belinda Thompson (belindat at us.ibm.com)
++ * Andy Richter (richtera at us.ibm.com)
++ * Peter Tiedemann (ptiedem at de.ibm.com)
++ */
++
++/*
++ This module exports functions to be used by CCS:
++ EXPORT_SYMBOL(ctc_mpc_alloc_channel);
++ EXPORT_SYMBOL(ctc_mpc_establish_connectivity);
++ EXPORT_SYMBOL(ctc_mpc_dealloc_ch);
++ EXPORT_SYMBOL(ctc_mpc_flow_control);
++*/
++
++#undef DEBUG
++#undef DEBUGDATA
++#undef DEBUGCCW
++
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/timer.h>
++#include <linux/sched.h>
++
++#include <linux/signal.h>
++#include <linux/string.h>
++#include <linux/proc_fs.h>
++
++#include <linux/ip.h>
++#include <linux/if_arp.h>
++#include <linux/tcp.h>
++#include <linux/skbuff.h>
++#include <linux/ctype.h>
++#include <linux/netdevice.h>
++#include <net/dst.h>
++
++#include <linux/io.h> /* instead of <asm/io.h> ok ? */
++#include <asm/ccwdev.h>
++#include <asm/ccwgroup.h>
++#include <linux/bitops.h> /* instead of <asm/bitops.h> ok ? */
++#include <linux/uaccess.h> /* instead of <asm/uaccess.h> ok ? */
++#include <linux/wait.h>
++#include <linux/moduleparam.h>
++#include <asm/idals.h>
++
++#include "cu3088.h"
++#include "ctcm_mpc.h"
++#include "ctcm_main.h"
++#include "ctcm_fsms.h"
++
++static const struct xid2 init_xid = {
++ .xid2_type_id = XID_FM2,
++ .xid2_len = 0x45,
++ .xid2_adj_id = 0,
++ .xid2_rlen = 0x31,
++ .xid2_resv1 = 0,
++ .xid2_flag1 = 0,
++ .xid2_fmtt = 0,
++ .xid2_flag4 = 0x80,
++ .xid2_resv2 = 0,
++ .xid2_tgnum = 0,
++ .xid2_sender_id = 0,
++ .xid2_flag2 = 0,
++ .xid2_option = XID2_0,
++ .xid2_resv3 = "\x00",
++ .xid2_resv4 = 0,
++ .xid2_dlc_type = XID2_READ_SIDE,
++ .xid2_resv5 = 0,
++ .xid2_mpc_flag = 0,
++ .xid2_resv6 = 0,
++ .xid2_buf_len = (MPC_BUFSIZE_DEFAULT - 35),
++};
++
++static const struct th_header thnorm = {
++ .th_seg = 0x00,
++ .th_ch_flag = TH_IS_XID,
++ .th_blk_flag = TH_DATA_IS_XID,
++ .th_is_xid = 0x01,
++ .th_seq_num = 0x00000000,
++};
++
++static const struct th_header thdummy = {
++ .th_seg = 0x00,
++ .th_ch_flag = 0x00,
++ .th_blk_flag = TH_DATA_IS_XID,
++ .th_is_xid = 0x01,
++ .th_seq_num = 0x00000000,
++};
++
++/*
++ * Definition of one MPC group
++ */
++
++/*
++ * Compatibility macros for busy handling
++ * of network devices.
++ */
++
++static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb);
++
++/*
++ * MPC Group state machine actions (static prototypes)
++ */
++static void mpc_action_nop(fsm_instance *fsm, int event, void *arg);
++static void mpc_action_go_ready(fsm_instance *fsm, int event, void *arg);
++static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg);
++static void mpc_action_timeout(fsm_instance *fi, int event, void *arg);
++static int mpc_validate_xid(struct mpcg_info *mpcginfo);
++static void mpc_action_yside_xid(fsm_instance *fsm, int event, void *arg);
++static void mpc_action_doxid0(fsm_instance *fsm, int event, void *arg);
++static void mpc_action_doxid7(fsm_instance *fsm, int event, void *arg);
++static void mpc_action_xside_xid(fsm_instance *fsm, int event, void *arg);
++static void mpc_action_rcvd_xid0(fsm_instance *fsm, int event, void *arg);
++static void mpc_action_rcvd_xid7(fsm_instance *fsm, int event, void *arg);
++
++#ifdef DEBUGDATA
++/*-------------------------------------------------------------------*
++* Dump buffer format *
++* *
++*--------------------------------------------------------------------*/
++void ctcmpc_dumpit(char *buf, int len)
++{
++ __u32 ct, sw, rm, dup;
++ char *ptr, *rptr;
++ char tbuf[82], tdup[82];
++ #if (UTS_MACHINE == s390x)
++ char addr[22];
++ #else
++ char addr[12];
++ #endif
++ char boff[12];
++ char bhex[82], duphex[82];
++ char basc[40];
++
++ sw = 0;
++ rptr = ptr = buf;
++ rm = 16;
++ duphex[0] = 0x00;
++ dup = 0;
++
++ for (ct = 0; ct < len; ct++, ptr++, rptr++) {
++ if (sw == 0) {
++ #if (UTS_MACHINE == s390x)
++ sprintf(addr, "%16.16lx", (unsigned long)rptr);
++ #else
++ sprintf(addr, "%8.8X", (__u32)rptr);
++ #endif
++
++ sprintf(boff, "%4.4X", (__u32)ct);
++ bhex[0] = '\0';
++ basc[0] = '\0';
++ }
++ if ((sw == 4) || (sw == 12))
++ strcat(bhex, " ");
++ if (sw == 8)
++ strcat(bhex, " ");
++
++ #if (UTS_MACHINE == s390x)
++ sprintf(tbuf, "%2.2lX", (unsigned long)*ptr);
++ #else
++ sprintf(tbuf, "%2.2X", (__u32)*ptr);
++ #endif
++
++ tbuf[2] = '\0';
++ strcat(bhex, tbuf);
++ if ((0 != isprint(*ptr)) && (*ptr >= 0x20))
++ basc[sw] = *ptr;
++ else
++ basc[sw] = '.';
++
++ basc[sw+1] = '\0';
++ sw++;
++ rm--;
++ if (sw == 16) {
++ if ((strcmp(duphex, bhex)) != 0) {
++ if (dup != 0) {
++ sprintf(tdup, "Duplicate as above "
++ "to %s", addr);
++ printk(KERN_INFO " "
++ " --- %s ---\n", tdup);
++ }
++ printk(KERN_INFO " %s (+%s) : %s [%s]\n",
++ addr, boff, bhex, basc);
++ dup = 0;
++ strcpy(duphex, bhex);
++ } else
++ dup++;
++
++ sw = 0;
++ rm = 16;
++ }
++ } /* endfor */
++
++ if (sw != 0) {
++ for ( ; rm > 0; rm--, sw++) {
++ if ((sw == 4) || (sw == 12))
++ strcat(bhex, " ");
++ if (sw == 8)
++ strcat(bhex, " ");
++ strcat(bhex, " ");
++ strcat(basc, " ");
++ }
++ if (dup != 0) {
++ sprintf(tdup, "Duplicate as above to %s", addr);
++ printk(KERN_INFO " "
++ " --- %s ---\n", tdup);
++ }
++ printk(KERN_INFO " %s (+%s) : %s [%s]\n",
++ addr, boff, bhex, basc);
++ } else {
++ if (dup >= 1) {
++ sprintf(tdup, "Duplicate as above to %s", addr);
++ printk(KERN_INFO " "
++ " --- %s ---\n", tdup);
++ }
++ if (dup != 0) {
++ printk(KERN_INFO " %s (+%s) : %s [%s]\n",
++ addr, boff, bhex, basc);
++ }
++ }
++
++ return;
++
++} /* end of ctcmpc_dumpit */
++#endif
++
++#ifdef DEBUGDATA
++/*
++ * Dump header and first 16 bytes of an sk_buff for debugging purposes.
++ *
++ * skb The sk_buff to dump.
++ * offset Offset relative to skb-data, where to start the dump.
++ */
++void ctcmpc_dump_skb(struct sk_buff *skb, int offset)
++{
++ unsigned char *p = skb->data;
++ struct th_header *header;
++ struct pdu *pheader;
++ int bl = skb->len;
++ int i;
++
++ if (p == NULL)
++ return;
++
++ p += offset;
++ header = (struct th_header *)p;
++
++ printk(KERN_INFO "dump:\n");
++ printk(KERN_INFO "skb len=%d \n", skb->len);
++ if (skb->len > 2) {
++ switch (header->th_ch_flag) {
++ case TH_HAS_PDU:
++ break;
++ case 0x00:
++ case TH_IS_XID:
++ if ((header->th_blk_flag == TH_DATA_IS_XID) &&
++ (header->th_is_xid == 0x01))
++ goto dumpth;
++ case TH_SWEEP_REQ:
++ goto dumpth;
++ case TH_SWEEP_RESP:
++ goto dumpth;
++ default:
++ break;
++ }
++
++ pheader = (struct pdu *)p;
++ printk(KERN_INFO "pdu->offset: %d hex: %04x\n",
++ pheader->pdu_offset, pheader->pdu_offset);
++ printk(KERN_INFO "pdu->flag : %02x\n", pheader->pdu_flag);
++ printk(KERN_INFO "pdu->proto : %02x\n", pheader->pdu_proto);
++ printk(KERN_INFO "pdu->seq : %02x\n", pheader->pdu_seq);
++ goto dumpdata;
++
++dumpth:
++ printk(KERN_INFO "th->seg : %02x\n", header->th_seg);
++ printk(KERN_INFO "th->ch : %02x\n", header->th_ch_flag);
++ printk(KERN_INFO "th->blk_flag: %02x\n", header->th_blk_flag);
++ printk(KERN_INFO "th->type : %s\n",
++ (header->th_is_xid) ? "DATA" : "XID");
++ printk(KERN_INFO "th->seqnum : %04x\n", header->th_seq_num);
++
++ }
++dumpdata:
++ if (bl > 32)
++ bl = 32;
++ printk(KERN_INFO "data: ");
++ for (i = 0; i < bl; i++)
++ printk(KERN_INFO "%02x%s", *p++, (i % 16) ? " " : "\n<7>");
++ printk(KERN_INFO "\n");
++}
++#endif
++
++/*
++ * ctc_mpc_alloc_channel
++ * (exported interface)
++ *
++ * Device Initialization :
++ * ACTPATH driven IO operations
++ */
++int ctc_mpc_alloc_channel(int port_num, void (*callback)(int, int))
++{
++ char device[20];
++ struct net_device *dev;
++ struct mpc_group *grp;
++ struct ctcm_priv *priv;
++
++ ctcm_pr_debug("ctcmpc enter: %s()\n", __FUNCTION__);
++
++ sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
++ dev = __dev_get_by_name(&init_net, device);
++
++ if (dev == NULL) {
++ printk(KERN_INFO "ctc_mpc_alloc_channel %s dev=NULL\n", device);
++ return 1;
++ }
++
++ priv = dev->priv;
++ grp = priv->mpcg;
++ if (!grp)
++ return 1;
++
++ grp->allochanfunc = callback;
++ grp->port_num = port_num;
++ grp->port_persist = 1;
++
++ ctcm_pr_debug("ctcmpc: %s called for device %s state=%s\n",
++ __FUNCTION__,
++ dev->name,
++ fsm_getstate_str(grp->fsm));
++
++ switch (fsm_getstate(grp->fsm)) {
++ case MPCG_STATE_INOP:
++ /* Group is in the process of terminating */
++ grp->alloc_called = 1;
++ break;
++ case MPCG_STATE_RESET:
++ /* MPC Group will transition to state */
++ /* MPCG_STATE_XID2INITW iff the minimum number */
++ /* of 1 read and 1 write channel have successfully*/
++ /* activated */
++ /*fsm_newstate(grp->fsm, MPCG_STATE_XID2INITW);*/
++ if (callback)
++ grp->send_qllc_disc = 1;
++ case MPCG_STATE_XID0IOWAIT:
++ fsm_deltimer(&grp->timer);
++ grp->outstanding_xid2 = 0;
++ grp->outstanding_xid7 = 0;
++ grp->outstanding_xid7_p2 = 0;
++ grp->saved_xid2 = NULL;
++ if (callback)
++ ctcm_open(dev);
++ fsm_event(priv->fsm, DEV_EVENT_START, dev);
++ break;
++ case MPCG_STATE_READY:
++ /* XID exchanges completed after PORT was activated */
++ /* Link station already active */
++ /* Maybe timing issue...retry callback */
++ grp->allocchan_callback_retries++;
++ if (grp->allocchan_callback_retries < 4) {
++ if (grp->allochanfunc)
++ grp->allochanfunc(grp->port_num,
++ grp->group_max_buflen);
++ } else {
++ /* there are problems...bail out */
++ /* there may be a state mismatch so restart */
++ grp->port_persist = 1;
++ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++ grp->allocchan_callback_retries = 0;
++ }
++ break;
++ default:
++ return 0;
++
++ }
++
++ ctcm_pr_debug("ctcmpc exit: %s()\n", __FUNCTION__);
++ return 0;
++}
++EXPORT_SYMBOL(ctc_mpc_alloc_channel);
++
++/*
++ * ctc_mpc_establish_connectivity
++ * (exported interface)
++ */
++void ctc_mpc_establish_connectivity(int port_num,
++ void (*callback)(int, int, int))
++{
++ char device[20];
++ struct net_device *dev;
++ struct mpc_group *grp;
++ struct ctcm_priv *priv;
++ struct channel *rch, *wch;
++
++ ctcm_pr_debug("ctcmpc enter: %s()\n", __FUNCTION__);
++
++ sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
++ dev = __dev_get_by_name(&init_net, device);
++
++ if (dev == NULL) {
++ printk(KERN_INFO "ctc_mpc_establish_connectivity "
++ "%s dev=NULL\n", device);
++ return;
++ }
++ priv = dev->priv;
++ rch = priv->channel[READ];
++ wch = priv->channel[WRITE];
++
++ grp = priv->mpcg;
++
++ ctcm_pr_debug("ctcmpc: %s() called for device %s state=%s\n",
++ __FUNCTION__, dev->name,
++ fsm_getstate_str(grp->fsm));
++
++ grp->estconnfunc = callback;
++ grp->port_num = port_num;
++
++ switch (fsm_getstate(grp->fsm)) {
++ case MPCG_STATE_READY:
++ /* XID exchanges completed after PORT was activated */
++ /* Link station already active */
++ /* Maybe timing issue...retry callback */
++ fsm_deltimer(&grp->timer);
++ grp->estconn_callback_retries++;
++ if (grp->estconn_callback_retries < 4) {
++ if (grp->estconnfunc) {
++ grp->estconnfunc(grp->port_num, 0,
++ grp->group_max_buflen);
++ grp->estconnfunc = NULL;
++ }
++ } else {
++ /* there are problems...bail out */
++ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++ grp->estconn_callback_retries = 0;
++ }
++ break;
++ case MPCG_STATE_INOP:
++ case MPCG_STATE_RESET:
++ /* MPC Group is not ready to start XID - min num of */
++ /* 1 read and 1 write channel have not been acquired*/
++ printk(KERN_WARNING "ctcmpc: %s() REJECTED ACTIVE XID Req"
++ "uest - Channel Pair is not Active\n", __FUNCTION__);
++ if (grp->estconnfunc) {
++ grp->estconnfunc(grp->port_num, -1, 0);
++ grp->estconnfunc = NULL;
++ }
++ break;
++ case MPCG_STATE_XID2INITW:
++ /* alloc channel was called but no XID exchange */
++ /* has occurred. initiate xside XID exchange */
++ /* make sure yside XID0 processing has not started */
++ if ((fsm_getstate(rch->fsm) > CH_XID0_PENDING) ||
++ (fsm_getstate(wch->fsm) > CH_XID0_PENDING)) {
++ printk(KERN_WARNING "mpc: %s() ABORT ACTIVE XID"
++ " Request- PASSIVE XID in process\n"
++ , __FUNCTION__);
++ break;
++ }
++ grp->send_qllc_disc = 1;
++ fsm_newstate(grp->fsm, MPCG_STATE_XID0IOWAIT);
++ fsm_deltimer(&grp->timer);
++ fsm_addtimer(&grp->timer, MPC_XID_TIMEOUT_VALUE,
++ MPCG_EVENT_TIMER, dev);
++ grp->outstanding_xid7 = 0;
++ grp->outstanding_xid7_p2 = 0;
++ grp->saved_xid2 = NULL;
++ if ((rch->in_mpcgroup) &&
++ (fsm_getstate(rch->fsm) == CH_XID0_PENDING))
++ fsm_event(grp->fsm, MPCG_EVENT_XID0DO, rch);
++ else {
++ printk(KERN_WARNING "mpc: %s() Unable to start"
++ " ACTIVE XID0 on read channel\n",
++ __FUNCTION__);
++ if (grp->estconnfunc) {
++ grp->estconnfunc(grp->port_num, -1, 0);
++ grp->estconnfunc = NULL;
++ }
++ fsm_deltimer(&grp->timer);
++ goto done;
++ }
++ if ((wch->in_mpcgroup) &&
++ (fsm_getstate(wch->fsm) == CH_XID0_PENDING))
++ fsm_event(grp->fsm, MPCG_EVENT_XID0DO, wch);
++ else {
++ printk(KERN_WARNING "mpc: %s() Unable to start"
++ " ACTIVE XID0 on write channel\n",
++ __FUNCTION__);
++ if (grp->estconnfunc) {
++ grp->estconnfunc(grp->port_num, -1, 0);
++ grp->estconnfunc = NULL;
++ }
++ fsm_deltimer(&grp->timer);
++ goto done;
++ }
++ break;
++ case MPCG_STATE_XID0IOWAIT:
++ /* already in active XID negotiations */
++ default:
++ break;
++ }
++
++done:
++ ctcm_pr_debug("ctcmpc exit: %s()\n", __FUNCTION__);
++ return;
++}
++EXPORT_SYMBOL(ctc_mpc_establish_connectivity);
++
++/*
++ * ctc_mpc_dealloc_ch
++ * (exported interface)
++ */
++void ctc_mpc_dealloc_ch(int port_num)
++{
++ struct net_device *dev;
++ char device[20];
++ struct ctcm_priv *priv;
++ struct mpc_group *grp;
++
++ ctcm_pr_debug("ctcmpc enter: %s()\n", __FUNCTION__);
++ sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
++ dev = __dev_get_by_name(&init_net, device);
++
++ if (dev == NULL) {
++ printk(KERN_INFO "%s() %s dev=NULL\n", __FUNCTION__, device);
++ goto done;
++ }
++
++ ctcm_pr_debug("ctcmpc:%s %s() called for device %s refcount=%d\n",
++ dev->name, __FUNCTION__,
++ dev->name, atomic_read(&dev->refcnt));
++
++ priv = dev->priv;
++ if (priv == NULL) {
++ printk(KERN_INFO "%s() %s priv=NULL\n",
++ __FUNCTION__, device);
++ goto done;
++ }
++ fsm_deltimer(&priv->restart_timer);
++
++ grp = priv->mpcg;
++ if (grp == NULL) {
++ printk(KERN_INFO "%s() %s dev=NULL\n", __FUNCTION__, device);
++ goto done;
++ }
++ grp->channels_terminating = 0;
++
++ fsm_deltimer(&grp->timer);
++
++ grp->allochanfunc = NULL;
++ grp->estconnfunc = NULL;
++ grp->port_persist = 0;
++ grp->send_qllc_disc = 0;
++ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++
++ ctcm_close(dev);
++done:
++ ctcm_pr_debug("ctcmpc exit: %s()\n", __FUNCTION__);
++ return;
++}
++EXPORT_SYMBOL(ctc_mpc_dealloc_ch);
++
++/*
++ * ctc_mpc_flow_control
++ * (exported interface)
++ */
++void ctc_mpc_flow_control(int port_num, int flowc)
++{
++ char device[20];
++ struct ctcm_priv *priv;
++ struct mpc_group *grp;
++ struct net_device *dev;
++ struct channel *rch;
++ int mpcg_state;
++
++ ctcm_pr_debug("ctcmpc enter: %s() %i\n", __FUNCTION__, flowc);
++
++ sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
++ dev = __dev_get_by_name(&init_net, device);
++
++ if (dev == NULL) {
++ printk(KERN_INFO "ctc_mpc_flow_control %s dev=NULL\n", device);
++ return;
++ }
++
++ ctcm_pr_debug("ctcmpc: %s %s called \n", dev->name, __FUNCTION__);
++
++ priv = dev->priv;
++ if (priv == NULL) {
++ printk(KERN_INFO "ctcmpc:%s() %s priv=NULL\n",
++ __FUNCTION__, device);
++ return;
++ }
++ grp = priv->mpcg;
++ rch = priv->channel[READ];
++
++ mpcg_state = fsm_getstate(grp->fsm);
++ switch (flowc) {
++ case 1:
++ if (mpcg_state == MPCG_STATE_FLOWC)
++ break;
++ if (mpcg_state == MPCG_STATE_READY) {
++ if (grp->flow_off_called == 1)
++ grp->flow_off_called = 0;
++ else
++ fsm_newstate(grp->fsm, MPCG_STATE_FLOWC);
++ break;
++ }
++ break;
++ case 0:
++ if (mpcg_state == MPCG_STATE_FLOWC) {
++ fsm_newstate(grp->fsm, MPCG_STATE_READY);
++ /* ensure any data that has accumulated */
++ /* on the io_queue will now be sen t */
++ tasklet_schedule(&rch->ch_tasklet);
++ }
++ /* possible race condition */
++ if (mpcg_state == MPCG_STATE_READY) {
++ grp->flow_off_called = 1;
++ break;
++ }
++ break;
++ }
++
++ ctcm_pr_debug("ctcmpc exit: %s() %i\n", __FUNCTION__, flowc);
++}
++EXPORT_SYMBOL(ctc_mpc_flow_control);
++
++static int mpc_send_qllc_discontact(struct net_device *);
++
++/*
++ * helper function of ctcmpc_unpack_skb
++*/
++static void mpc_rcvd_sweep_resp(struct mpcg_info *mpcginfo)
++{
++ struct channel *rch = mpcginfo->ch;
++ struct net_device *dev = rch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++ struct mpc_group *grp = priv->mpcg;
++ struct channel *ch = priv->channel[WRITE];
++
++ if (do_debug)
++ ctcm_pr_debug("ctcmpc enter: %s(): ch=0x%p id=%s\n",
++ __FUNCTION__, ch, ch->id);
++
++ if (do_debug_data)
++ ctcmpc_dumpit((char *)mpcginfo->sweep, TH_SWEEP_LENGTH);
++
++ grp->sweep_rsp_pend_num--;
++
++ if ((grp->sweep_req_pend_num == 0) &&
++ (grp->sweep_rsp_pend_num == 0)) {
++ fsm_deltimer(&ch->sweep_timer);
++ grp->in_sweep = 0;
++ rch->th_seq_num = 0x00;
++ ch->th_seq_num = 0x00;
++ ctcm_clear_busy_do(dev);
++ }
++
++ kfree(mpcginfo);
++
++ return;
++
++}
++
++/*
++ * helper function of mpc_rcvd_sweep_req
++ * which is a helper of ctcmpc_unpack_skb
++ */
++static void ctcmpc_send_sweep_resp(struct channel *rch)
++{
++ struct net_device *dev = rch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++ struct mpc_group *grp = priv->mpcg;
++ int rc = 0;
++ struct th_sweep *header;
++ struct sk_buff *sweep_skb;
++ struct channel *ch = priv->channel[WRITE];
++
++ if (do_debug)
++ ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
++ __FUNCTION__, rch, rch->id);
++
++ sweep_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT,
++ GFP_ATOMIC|GFP_DMA);
++ if (sweep_skb == NULL) {
++ printk(KERN_INFO "Couldn't alloc sweep_skb\n");
++ rc = -ENOMEM;
++ goto done;
++ }
++
++ header = (struct th_sweep *)
++ kmalloc(sizeof(struct th_sweep), gfp_type());
++
++ if (!header) {
++ dev_kfree_skb_any(sweep_skb);
++ rc = -ENOMEM;
++ goto done;
++ }
++
++ header->th.th_seg = 0x00 ;
++ header->th.th_ch_flag = TH_SWEEP_RESP;
++ header->th.th_blk_flag = 0x00;
++ header->th.th_is_xid = 0x00;
++ header->th.th_seq_num = 0x00;
++ header->sw.th_last_seq = ch->th_seq_num;
++
++ memcpy(skb_put(sweep_skb, TH_SWEEP_LENGTH), header, TH_SWEEP_LENGTH);
++
++ kfree(header);
++
++ dev->trans_start = jiffies;
++ skb_queue_tail(&ch->sweep_queue, sweep_skb);
++
++ fsm_addtimer(&ch->sweep_timer, 100, CTC_EVENT_RSWEEP_TIMER, ch);
++
++ return;
++
++done:
++ if (rc != 0) {
++ grp->in_sweep = 0;
++ ctcm_clear_busy_do(dev);
++ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++ }
++
++ return;
++}
++
++/*
++ * helper function of ctcmpc_unpack_skb
++ */
++static void mpc_rcvd_sweep_req(struct mpcg_info *mpcginfo)
++{
++ struct channel *rch = mpcginfo->ch;
++ struct net_device *dev = rch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++ struct mpc_group *grp = priv->mpcg;
++ struct channel *ch = priv->channel[WRITE];
++
++ if (do_debug)
++ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
++ " %s(): ch=0x%p id=%s\n", __FUNCTION__, ch, ch->id);
++
++ if (grp->in_sweep == 0) {
++ grp->in_sweep = 1;
++ ctcm_test_and_set_busy(dev);
++ grp->sweep_req_pend_num = grp->active_channels[READ];
++ grp->sweep_rsp_pend_num = grp->active_channels[READ];
++ }
++
++ if (do_debug_data)
++ ctcmpc_dumpit((char *)mpcginfo->sweep, TH_SWEEP_LENGTH);
++
++ grp->sweep_req_pend_num--;
++ ctcmpc_send_sweep_resp(ch);
++ kfree(mpcginfo);
++ return;
++}
++
++/*
++ * MPC Group Station FSM definitions
++ */
++static const char *mpcg_event_names[] = {
++ [MPCG_EVENT_INOP] = "INOP Condition",
++ [MPCG_EVENT_DISCONC] = "Discontact Received",
++ [MPCG_EVENT_XID0DO] = "Channel Active - Start XID",
++ [MPCG_EVENT_XID2] = "XID2 Received",
++ [MPCG_EVENT_XID2DONE] = "XID0 Complete",
++ [MPCG_EVENT_XID7DONE] = "XID7 Complete",
++ [MPCG_EVENT_TIMER] = "XID Setup Timer",
++ [MPCG_EVENT_DOIO] = "XID DoIO",
++};
++
++static const char *mpcg_state_names[] = {
++ [MPCG_STATE_RESET] = "Reset",
++ [MPCG_STATE_INOP] = "INOP",
++ [MPCG_STATE_XID2INITW] = "Passive XID- XID0 Pending Start",
++ [MPCG_STATE_XID2INITX] = "Passive XID- XID0 Pending Complete",
++ [MPCG_STATE_XID7INITW] = "Passive XID- XID7 Pending P1 Start",
++ [MPCG_STATE_XID7INITX] = "Passive XID- XID7 Pending P2 Complete",
++ [MPCG_STATE_XID0IOWAIT] = "Active XID- XID0 Pending Start",
++ [MPCG_STATE_XID0IOWAIX] = "Active XID- XID0 Pending Complete",
++ [MPCG_STATE_XID7INITI] = "Active XID- XID7 Pending Start",
++ [MPCG_STATE_XID7INITZ] = "Active XID- XID7 Pending Complete ",
++ [MPCG_STATE_XID7INITF] = "XID - XID7 Complete ",
++ [MPCG_STATE_FLOWC] = "FLOW CONTROL ON",
++ [MPCG_STATE_READY] = "READY",
++};
++
++/*
++ * The MPC Group Station FSM
++ * 22 events
++ */
++static const fsm_node mpcg_fsm[] = {
++ { MPCG_STATE_RESET, MPCG_EVENT_INOP, mpc_action_go_inop },
++ { MPCG_STATE_INOP, MPCG_EVENT_INOP, mpc_action_nop },
++ { MPCG_STATE_FLOWC, MPCG_EVENT_INOP, mpc_action_go_inop },
++
++ { MPCG_STATE_READY, MPCG_EVENT_DISCONC, mpc_action_discontact },
++ { MPCG_STATE_READY, MPCG_EVENT_INOP, mpc_action_go_inop },
++
++ { MPCG_STATE_XID2INITW, MPCG_EVENT_XID0DO, mpc_action_doxid0 },
++ { MPCG_STATE_XID2INITW, MPCG_EVENT_XID2, mpc_action_rcvd_xid0 },
++ { MPCG_STATE_XID2INITW, MPCG_EVENT_INOP, mpc_action_go_inop },
++ { MPCG_STATE_XID2INITW, MPCG_EVENT_TIMER, mpc_action_timeout },
++ { MPCG_STATE_XID2INITW, MPCG_EVENT_DOIO, mpc_action_yside_xid },
++
++ { MPCG_STATE_XID2INITX, MPCG_EVENT_XID0DO, mpc_action_doxid0 },
++ { MPCG_STATE_XID2INITX, MPCG_EVENT_XID2, mpc_action_rcvd_xid0 },
++ { MPCG_STATE_XID2INITX, MPCG_EVENT_INOP, mpc_action_go_inop },
++ { MPCG_STATE_XID2INITX, MPCG_EVENT_TIMER, mpc_action_timeout },
++ { MPCG_STATE_XID2INITX, MPCG_EVENT_DOIO, mpc_action_yside_xid },
++
++ { MPCG_STATE_XID7INITW, MPCG_EVENT_XID2DONE, mpc_action_doxid7 },
++ { MPCG_STATE_XID7INITW, MPCG_EVENT_DISCONC, mpc_action_discontact },
++ { MPCG_STATE_XID7INITW, MPCG_EVENT_XID2, mpc_action_rcvd_xid7 },
++ { MPCG_STATE_XID7INITW, MPCG_EVENT_INOP, mpc_action_go_inop },
++ { MPCG_STATE_XID7INITW, MPCG_EVENT_TIMER, mpc_action_timeout },
++ { MPCG_STATE_XID7INITW, MPCG_EVENT_XID7DONE, mpc_action_doxid7 },
++ { MPCG_STATE_XID7INITW, MPCG_EVENT_DOIO, mpc_action_yside_xid },
++
++ { MPCG_STATE_XID7INITX, MPCG_EVENT_DISCONC, mpc_action_discontact },
++ { MPCG_STATE_XID7INITX, MPCG_EVENT_XID2, mpc_action_rcvd_xid7 },
++ { MPCG_STATE_XID7INITX, MPCG_EVENT_INOP, mpc_action_go_inop },
++ { MPCG_STATE_XID7INITX, MPCG_EVENT_XID7DONE, mpc_action_doxid7 },
++ { MPCG_STATE_XID7INITX, MPCG_EVENT_TIMER, mpc_action_timeout },
++ { MPCG_STATE_XID7INITX, MPCG_EVENT_DOIO, mpc_action_yside_xid },
++
++ { MPCG_STATE_XID0IOWAIT, MPCG_EVENT_XID0DO, mpc_action_doxid0 },
++ { MPCG_STATE_XID0IOWAIT, MPCG_EVENT_DISCONC, mpc_action_discontact },
++ { MPCG_STATE_XID0IOWAIT, MPCG_EVENT_XID2, mpc_action_rcvd_xid0 },
++ { MPCG_STATE_XID0IOWAIT, MPCG_EVENT_INOP, mpc_action_go_inop },
++ { MPCG_STATE_XID0IOWAIT, MPCG_EVENT_TIMER, mpc_action_timeout },
++ { MPCG_STATE_XID0IOWAIT, MPCG_EVENT_DOIO, mpc_action_xside_xid },
++
++ { MPCG_STATE_XID0IOWAIX, MPCG_EVENT_XID0DO, mpc_action_doxid0 },
++ { MPCG_STATE_XID0IOWAIX, MPCG_EVENT_DISCONC, mpc_action_discontact },
++ { MPCG_STATE_XID0IOWAIX, MPCG_EVENT_XID2, mpc_action_rcvd_xid0 },
++ { MPCG_STATE_XID0IOWAIX, MPCG_EVENT_INOP, mpc_action_go_inop },
++ { MPCG_STATE_XID0IOWAIX, MPCG_EVENT_TIMER, mpc_action_timeout },
++ { MPCG_STATE_XID0IOWAIX, MPCG_EVENT_DOIO, mpc_action_xside_xid },
++
++ { MPCG_STATE_XID7INITI, MPCG_EVENT_XID2DONE, mpc_action_doxid7 },
++ { MPCG_STATE_XID7INITI, MPCG_EVENT_XID2, mpc_action_rcvd_xid7 },
++ { MPCG_STATE_XID7INITI, MPCG_EVENT_DISCONC, mpc_action_discontact },
++ { MPCG_STATE_XID7INITI, MPCG_EVENT_INOP, mpc_action_go_inop },
++ { MPCG_STATE_XID7INITI, MPCG_EVENT_TIMER, mpc_action_timeout },
++ { MPCG_STATE_XID7INITI, MPCG_EVENT_XID7DONE, mpc_action_doxid7 },
++ { MPCG_STATE_XID7INITI, MPCG_EVENT_DOIO, mpc_action_xside_xid },
++
++ { MPCG_STATE_XID7INITZ, MPCG_EVENT_XID2, mpc_action_rcvd_xid7 },
++ { MPCG_STATE_XID7INITZ, MPCG_EVENT_XID7DONE, mpc_action_doxid7 },
++ { MPCG_STATE_XID7INITZ, MPCG_EVENT_DISCONC, mpc_action_discontact },
++ { MPCG_STATE_XID7INITZ, MPCG_EVENT_INOP, mpc_action_go_inop },
++ { MPCG_STATE_XID7INITZ, MPCG_EVENT_TIMER, mpc_action_timeout },
++ { MPCG_STATE_XID7INITZ, MPCG_EVENT_DOIO, mpc_action_xside_xid },
++
++ { MPCG_STATE_XID7INITF, MPCG_EVENT_INOP, mpc_action_go_inop },
++ { MPCG_STATE_XID7INITF, MPCG_EVENT_XID7DONE, mpc_action_go_ready },
++};
++
++static int mpcg_fsm_len = ARRAY_SIZE(mpcg_fsm);
++
++/*
++ * MPC Group Station FSM action
++ * CTCM_PROTO_MPC only
++ */
++static void mpc_action_go_ready(fsm_instance *fsm, int event, void *arg)
++{
++ struct net_device *dev = arg;
++ struct ctcm_priv *priv = NULL;
++ struct mpc_group *grp = NULL;
++
++ if (dev == NULL) {
++ printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
++ return;
++ }
++
++ ctcm_pr_debug("ctcmpc enter: %s %s()\n", dev->name, __FUNCTION__);
++
++ priv = dev->priv;
++ if (priv == NULL) {
++ printk(KERN_INFO "%s() priv=NULL\n", __FUNCTION__);
++ return;
++ }
++
++ grp = priv->mpcg;
++ if (grp == NULL) {
++ printk(KERN_INFO "%s() grp=NULL\n", __FUNCTION__);
++ return;
++ }
++
++ fsm_deltimer(&grp->timer);
++
++ if (grp->saved_xid2->xid2_flag2 == 0x40) {
++ priv->xid->xid2_flag2 = 0x00;
++ if (grp->estconnfunc) {
++ grp->estconnfunc(grp->port_num, 1,
++ grp->group_max_buflen);
++ grp->estconnfunc = NULL;
++ } else if (grp->allochanfunc)
++ grp->send_qllc_disc = 1;
++ goto done;
++ }
++
++ grp->port_persist = 1;
++ grp->out_of_sequence = 0;
++ grp->estconn_called = 0;
++
++ tasklet_hi_schedule(&grp->mpc_tasklet2);
++
++ ctcm_pr_debug("ctcmpc exit: %s %s()\n", dev->name, __FUNCTION__);
++ return;
++
++done:
++ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++
++
++ ctcm_pr_info("ctcmpc: %s()failure occurred\n", __FUNCTION__);
++}
++
++/*
++ * helper of ctcm_init_netdevice
++ * CTCM_PROTO_MPC only
++ */
++void mpc_group_ready(unsigned long adev)
++{
++ struct net_device *dev = (struct net_device *)adev;
++ struct ctcm_priv *priv = NULL;
++ struct mpc_group *grp = NULL;
++ struct channel *ch = NULL;
++
++
++ ctcm_pr_debug("ctcmpc enter: %s()\n", __FUNCTION__);
++
++ if (dev == NULL) {
++ printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
++ return;
++ }
++
++ priv = dev->priv;
++ if (priv == NULL) {
++ printk(KERN_INFO "%s() priv=NULL\n", __FUNCTION__);
++ return;
++ }
++
++ grp = priv->mpcg;
++ if (grp == NULL) {
++ printk(KERN_INFO "ctcmpc:%s() grp=NULL\n", __FUNCTION__);
++ return;
++ }
++
++ printk(KERN_NOTICE "ctcmpc: %s GROUP TRANSITIONED TO READY"
++ " maxbuf:%d\n",
++ dev->name, grp->group_max_buflen);
++
++ fsm_newstate(grp->fsm, MPCG_STATE_READY);
++
++ /* Put up a read on the channel */
++ ch = priv->channel[READ];
++ ch->pdu_seq = 0;
++ if (do_debug_data)
++ ctcm_pr_debug("ctcmpc: %s() ToDCM_pdu_seq= %08x\n" ,
++ __FUNCTION__, ch->pdu_seq);
++
++ ctcmpc_chx_rxidle(ch->fsm, CTC_EVENT_START, ch);
++ /* Put the write channel in idle state */
++ ch = priv->channel[WRITE];
++ if (ch->collect_len > 0) {
++ spin_lock(&ch->collect_lock);
++ ctcm_purge_skb_queue(&ch->collect_queue);
++ ch->collect_len = 0;
++ spin_unlock(&ch->collect_lock);
++ }
++ ctcm_chx_txidle(ch->fsm, CTC_EVENT_START, ch);
++
++ ctcm_clear_busy(dev);
++
++ if (grp->estconnfunc) {
++ grp->estconnfunc(grp->port_num, 0,
++ grp->group_max_buflen);
++ grp->estconnfunc = NULL;
++ } else
++ if (grp->allochanfunc)
++ grp->allochanfunc(grp->port_num,
++ grp->group_max_buflen);
++
++ grp->send_qllc_disc = 1;
++ grp->changed_side = 0;
++
++ ctcm_pr_debug("ctcmpc exit: %s()\n", __FUNCTION__);
++ return;
++
++}
++
++/*
++ * Increment the MPC Group Active Channel Counts
++ * helper of dev_action (called from channel fsm)
++ */
++int mpc_channel_action(struct channel *ch, int direction, int action)
++{
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv;
++ struct mpc_group *grp = NULL;
++ int rc = 0;
++
++ if (do_debug)
++ ctcm_pr_debug("ctcmpc enter: %s(): ch=0x%p id=%s\n",
++ __FUNCTION__, ch, ch->id);
++
++ if (dev == NULL) {
++ printk(KERN_INFO "ctcmpc_channel_action %i dev=NULL\n",
++ action);
++ rc = 1;
++ goto done;
++ }
++
++ priv = dev->priv;
++ if (priv == NULL) {
++ printk(KERN_INFO
++ "ctcmpc_channel_action%i priv=NULL, dev=%s\n",
++ action, dev->name);
++ rc = 2;
++ goto done;
++ }
++
++ grp = priv->mpcg;
++
++ if (grp == NULL) {
++ printk(KERN_INFO "ctcmpc: %s()%i mpcgroup=NULL, dev=%s\n",
++ __FUNCTION__, action, dev->name);
++ rc = 3;
++ goto done;
++ }
++
++ ctcm_pr_info(
++ "ctcmpc: %s() %i(): Grp:%s total_channel_paths=%i "
++ "active_channels read=%i, write=%i\n",
++ __FUNCTION__,
++ action,
++ fsm_getstate_str(grp->fsm),
++ grp->num_channel_paths,
++ grp->active_channels[READ],
++ grp->active_channels[WRITE]);
++
++ if ((action == MPC_CHANNEL_ADD) && (ch->in_mpcgroup == 0)) {
++ grp->num_channel_paths++;
++ grp->active_channels[direction]++;
++ grp->outstanding_xid2++;
++ ch->in_mpcgroup = 1;
++
++ if (ch->xid_skb != NULL)
++ dev_kfree_skb_any(ch->xid_skb);
++
++ ch->xid_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT,
++ GFP_ATOMIC | GFP_DMA);
++ if (ch->xid_skb == NULL) {
++ printk(KERN_INFO "ctcmpc: %s()"
++ "Couldn't alloc ch xid_skb\n", __FUNCTION__);
++ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++ return 1;
++ }
++ ch->xid_skb_data = ch->xid_skb->data;
++ ch->xid_th = (struct th_header *)ch->xid_skb->data;
++ skb_put(ch->xid_skb, TH_HEADER_LENGTH);
++ ch->xid = (struct xid2 *)skb_tail_pointer(ch->xid_skb);
++ skb_put(ch->xid_skb, XID2_LENGTH);
++ ch->xid_id = skb_tail_pointer(ch->xid_skb);
++ ch->xid_skb->data = ch->xid_skb_data;
++ skb_reset_tail_pointer(ch->xid_skb);
++ ch->xid_skb->len = 0;
++
++ memcpy(skb_put(ch->xid_skb, grp->xid_skb->len),
++ grp->xid_skb->data,
++ grp->xid_skb->len);
++
++ ch->xid->xid2_dlc_type = ((CHANNEL_DIRECTION(ch->flags) == READ)
++ ? XID2_READ_SIDE : XID2_WRITE_SIDE);
++
++ if (CHANNEL_DIRECTION(ch->flags) == WRITE)
++ ch->xid->xid2_buf_len = 0x00;
++
++ ch->xid_skb->data = ch->xid_skb_data;
++ skb_reset_tail_pointer(ch->xid_skb);
++ ch->xid_skb->len = 0;
++
++ fsm_newstate(ch->fsm, CH_XID0_PENDING);
++
++ if ((grp->active_channels[READ] > 0) &&
++ (grp->active_channels[WRITE] > 0) &&
++ (fsm_getstate(grp->fsm) < MPCG_STATE_XID2INITW)) {
++ fsm_newstate(grp->fsm, MPCG_STATE_XID2INITW);
++ printk(KERN_NOTICE "ctcmpc: %s MPC GROUP "
++ "CHANNELS ACTIVE\n", dev->name);
++ }
++ } else if ((action == MPC_CHANNEL_REMOVE) &&
++ (ch->in_mpcgroup == 1)) {
++ ch->in_mpcgroup = 0;
++ grp->num_channel_paths--;
++ grp->active_channels[direction]--;
++
++ if (ch->xid_skb != NULL)
++ dev_kfree_skb_any(ch->xid_skb);
++ ch->xid_skb = NULL;
++
++ if (grp->channels_terminating)
++ goto done;
++
++ if (((grp->active_channels[READ] == 0) &&
++ (grp->active_channels[WRITE] > 0))
++ || ((grp->active_channels[WRITE] == 0) &&
++ (grp->active_channels[READ] > 0)))
++ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++ }
++
++done:
++
++ if (do_debug) {
++ ctcm_pr_debug(
++ "ctcmpc: %s() %i Grp:%s ttl_chan_paths=%i "
++ "active_chans read=%i, write=%i\n",
++ __FUNCTION__,
++ action,
++ fsm_getstate_str(grp->fsm),
++ grp->num_channel_paths,
++ grp->active_channels[READ],
++ grp->active_channels[WRITE]);
++
++ ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
++ __FUNCTION__, ch, ch->id);
++ }
++ return rc;
++
++}
++
++/**
++ * Unpack a just received skb and hand it over to
++ * upper layers.
++ * special MPC version of unpack_skb.
++ *
++ * ch The channel where this skb has been received.
++ * pskb The received skb.
++ */
++static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
++{
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++ struct mpc_group *grp = priv->mpcg;
++ struct pdu *curr_pdu;
++ struct mpcg_info *mpcginfo;
++ struct th_header *header = NULL;
++ struct th_sweep *sweep = NULL;
++ int pdu_last_seen = 0;
++ __u32 new_len;
++ struct sk_buff *skb;
++ int skblen;
++ int sendrc = 0;
++
++ if (do_debug)
++ ctcm_pr_debug("ctcmpc enter: %s() %s cp:%i ch:%s\n",
++ __FUNCTION__, dev->name, smp_processor_id(), ch->id);
++
++ header = (struct th_header *)pskb->data;
++ if ((header->th_seg == 0) &&
++ (header->th_ch_flag == 0) &&
++ (header->th_blk_flag == 0) &&
++ (header->th_seq_num == 0))
++ /* nothing for us */ goto done;
++
++ if (do_debug_data) {
++ ctcm_pr_debug("ctcmpc: %s() th_header\n", __FUNCTION__);
++ ctcmpc_dumpit((char *)header, TH_HEADER_LENGTH);
++ ctcm_pr_debug("ctcmpc: %s() pskb len: %04x \n",
++ __FUNCTION__, pskb->len);
++ }
++
++ pskb->dev = dev;
++ pskb->ip_summed = CHECKSUM_UNNECESSARY;
++ skb_pull(pskb, TH_HEADER_LENGTH);
++
++ if (likely(header->th_ch_flag == TH_HAS_PDU)) {
++ if (do_debug_data)
++ ctcm_pr_debug("ctcmpc: %s() came into th_has_pdu\n",
++ __FUNCTION__);
++ if ((fsm_getstate(grp->fsm) == MPCG_STATE_FLOWC) ||
++ ((fsm_getstate(grp->fsm) == MPCG_STATE_READY) &&
++ (header->th_seq_num != ch->th_seq_num + 1) &&
++ (ch->th_seq_num != 0))) {
++ /* This is NOT the next segment *
++ * we are not the correct race winner *
++ * go away and let someone else win *
++ * BUT..this only applies if xid negot *
++ * is done *
++ */
++ grp->out_of_sequence += 1;
++ __skb_push(pskb, TH_HEADER_LENGTH);
++ skb_queue_tail(&ch->io_queue, pskb);
++ if (do_debug_data)
++ ctcm_pr_debug("ctcmpc: %s() th_seq_num "
++ "expect:%08x got:%08x\n", __FUNCTION__,
++ ch->th_seq_num + 1, header->th_seq_num);
++
++ return;
++ }
++ grp->out_of_sequence = 0;
++ ch->th_seq_num = header->th_seq_num;
++
++ if (do_debug_data)
++ ctcm_pr_debug("ctcmpc: %s() FromVTAM_th_seq=%08x\n",
++ __FUNCTION__, ch->th_seq_num);
++
++ if (unlikely(fsm_getstate(grp->fsm) != MPCG_STATE_READY))
++ goto done;
++ pdu_last_seen = 0;
++ while ((pskb->len > 0) && !pdu_last_seen) {
++ curr_pdu = (struct pdu *)pskb->data;
++ if (do_debug_data) {
++ ctcm_pr_debug("ctcm: %s() pdu_header\n",
++ __FUNCTION__);
++ ctcmpc_dumpit((char *)pskb->data,
++ PDU_HEADER_LENGTH);
++ ctcm_pr_debug("ctcm: %s() pskb len: %04x \n",
++ __FUNCTION__, pskb->len);
++ }
++ skb_pull(pskb, PDU_HEADER_LENGTH);
++
++ if (curr_pdu->pdu_flag & PDU_LAST)
++ pdu_last_seen = 1;
++ if (curr_pdu->pdu_flag & PDU_CNTL)
++ pskb->protocol = htons(ETH_P_SNAP);
++ else
++ pskb->protocol = htons(ETH_P_SNA_DIX);
++
++ if ((pskb->len <= 0) || (pskb->len > ch->max_bufsize)) {
++ printk(KERN_INFO
++ "%s Illegal packet size %d "
++ "received "
++ "dropping\n", dev->name,
++ pskb->len);
++ priv->stats.rx_dropped++;
++ priv->stats.rx_length_errors++;
++ goto done;
++ }
++ skb_reset_mac_header(pskb);
++ new_len = curr_pdu->pdu_offset;
++ if (do_debug_data)
++ ctcm_pr_debug("ctcmpc: %s() new_len: %04x \n",
++ __FUNCTION__, new_len);
++ if ((new_len == 0) || (new_len > pskb->len)) {
++ /* should never happen */
++ /* pskb len must be hosed...bail out */
++ printk(KERN_INFO
++ "ctcmpc: %s(): invalid pdu"
++ " offset of %04x - data may be"
++ "lost\n", __FUNCTION__, new_len);
++ goto done;
++ }
++ skb = __dev_alloc_skb(new_len+4, GFP_ATOMIC);
++
++ if (!skb) {
++ printk(KERN_INFO
++ "ctcm: %s Out of memory in "
++ "%s()- request-len:%04x \n",
++ dev->name,
++ __FUNCTION__,
++ new_len+4);
++ priv->stats.rx_dropped++;
++ fsm_event(grp->fsm,
++ MPCG_EVENT_INOP, dev);
++ goto done;
++ }
++
++ memcpy(skb_put(skb, new_len),
++ pskb->data, new_len);
++
++ skb_reset_mac_header(skb);
++ skb->dev = pskb->dev;
++ skb->protocol = pskb->protocol;
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++ *((__u32 *) skb_push(skb, 4)) = ch->pdu_seq;
++ ch->pdu_seq++;
++
++ if (do_debug_data)
++ ctcm_pr_debug("%s: ToDCM_pdu_seq= %08x\n",
++ __FUNCTION__, ch->pdu_seq);
++
++ ctcm_pr_debug("ctcm: %s() skb:%0lx "
++ "skb len: %d \n", __FUNCTION__,
++ (unsigned long)skb, skb->len);
++ if (do_debug_data) {
++ ctcm_pr_debug("ctcmpc: %s() up to 32 bytes"
++ " of pdu_data sent\n",
++ __FUNCTION__);
++ ctcmpc_dump32((char *)skb->data, skb->len);
++ }
++
++ skblen = skb->len;
++ sendrc = netif_rx(skb);
++ priv->stats.rx_packets++;
++ priv->stats.rx_bytes += skblen;
++ skb_pull(pskb, new_len); /* point to next PDU */
++ }
++ } else {
++ mpcginfo = (struct mpcg_info *)
++ kmalloc(sizeof(struct mpcg_info), gfp_type());
++ if (mpcginfo == NULL)
++ goto done;
++
++ mpcginfo->ch = ch;
++ mpcginfo->th = header;
++ mpcginfo->skb = pskb;
++ ctcm_pr_debug("ctcmpc: %s() Not PDU - may be control pkt\n",
++ __FUNCTION__);
++ /* it's a sweep? */
++ sweep = (struct th_sweep *)pskb->data;
++ mpcginfo->sweep = sweep;
++ if (header->th_ch_flag == TH_SWEEP_REQ)
++ mpc_rcvd_sweep_req(mpcginfo);
++ else if (header->th_ch_flag == TH_SWEEP_RESP)
++ mpc_rcvd_sweep_resp(mpcginfo);
++ else if (header->th_blk_flag == TH_DATA_IS_XID) {
++ struct xid2 *thisxid = (struct xid2 *)pskb->data;
++ skb_pull(pskb, XID2_LENGTH);
++ mpcginfo->xid = thisxid;
++ fsm_event(grp->fsm, MPCG_EVENT_XID2, mpcginfo);
++ } else if (header->th_blk_flag == TH_DISCONTACT)
++ fsm_event(grp->fsm, MPCG_EVENT_DISCONC, mpcginfo);
++ else if (header->th_seq_num != 0) {
++ printk(KERN_INFO "%s unexpected packet"
++ " expected control pkt\n", dev->name);
++ priv->stats.rx_dropped++;
++ /* mpcginfo only used for non-data transfers */
++ kfree(mpcginfo);
++ if (do_debug_data)
++ ctcmpc_dump_skb(pskb, -8);
++ }
++ }
++done:
++
++ dev_kfree_skb_any(pskb);
++ if (sendrc == NET_RX_DROP) {
++ printk(KERN_WARNING "%s %s() NETWORK BACKLOG EXCEEDED"
++ " - PACKET DROPPED\n", dev->name, __FUNCTION__);
++ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++ }
++
++ if (do_debug)
++ ctcm_pr_debug("ctcmpc exit : %s %s(): ch=0x%p id=%s\n",
++ dev->name, __FUNCTION__, ch, ch->id);
++}
++
++/**
++ * tasklet helper for mpc's skb unpacking.
++ *
++ * ch The channel to work on.
++ * Allow flow control back pressure to occur here.
++ * Throttling back channel can result in excessive
++ * channel inactivity and system deact of channel
++ */
++void ctcmpc_bh(unsigned long thischan)
++{
++ struct channel *ch = (struct channel *)thischan;
++ struct sk_buff *skb;
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++ struct mpc_group *grp = priv->mpcg;
++
++ if (do_debug)
++ ctcm_pr_debug("%s cp:%i enter: %s() %s\n",
++ dev->name, smp_processor_id(), __FUNCTION__, ch->id);
++ /* caller has requested driver to throttle back */
++ while ((fsm_getstate(grp->fsm) != MPCG_STATE_FLOWC) &&
++ (skb = skb_dequeue(&ch->io_queue))) {
++ ctcmpc_unpack_skb(ch, skb);
++ if (grp->out_of_sequence > 20) {
++ /* assume data loss has occurred if */
++ /* missing seq_num for extended */
++ /* period of time */
++ grp->out_of_sequence = 0;
++ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++ break;
++ }
++ if (skb == skb_peek(&ch->io_queue))
++ break;
++ }
++ if (do_debug)
++ ctcm_pr_debug("ctcmpc exit : %s %s(): ch=0x%p id=%s\n",
++ dev->name, __FUNCTION__, ch, ch->id);
++ return;
++}
++
++/*
++ * MPC Group Initializations
++ */
++struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv)
++{
++ struct mpc_group *grp;
++
++ CTCM_DBF_TEXT(MPC_SETUP, 3, __FUNCTION__);
++
++ grp = kzalloc(sizeof(struct mpc_group), GFP_KERNEL);
++ if (grp == NULL)
++ return NULL;
++
++ grp->fsm =
++ init_fsm("mpcg", mpcg_state_names, mpcg_event_names,
++ MPCG_NR_STATES, MPCG_NR_EVENTS, mpcg_fsm,
++ mpcg_fsm_len, GFP_KERNEL);
++ if (grp->fsm == NULL) {
++ kfree(grp);
++ return NULL;
++ }
++
++ fsm_newstate(grp->fsm, MPCG_STATE_RESET);
++ fsm_settimer(grp->fsm, &grp->timer);
++
++ grp->xid_skb =
++ __dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC | GFP_DMA);
++ if (grp->xid_skb == NULL) {
++ printk(KERN_INFO "Couldn't alloc MPCgroup xid_skb\n");
++ kfree_fsm(grp->fsm);
++ kfree(grp);
++ return NULL;
++ }
++ /* base xid for all channels in group */
++ grp->xid_skb_data = grp->xid_skb->data;
++ grp->xid_th = (struct th_header *)grp->xid_skb->data;
++ memcpy(skb_put(grp->xid_skb, TH_HEADER_LENGTH),
++ &thnorm, TH_HEADER_LENGTH);
++
++ grp->xid = (struct xid2 *) skb_tail_pointer(grp->xid_skb);
++ memcpy(skb_put(grp->xid_skb, XID2_LENGTH), &init_xid, XID2_LENGTH);
++ grp->xid->xid2_adj_id = jiffies | 0xfff00000;
++ grp->xid->xid2_sender_id = jiffies;
++
++ grp->xid_id = skb_tail_pointer(grp->xid_skb);
++ memcpy(skb_put(grp->xid_skb, 4), "VTAM", 4);
++
++ grp->rcvd_xid_skb =
++ __dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC|GFP_DMA);
++ if (grp->rcvd_xid_skb == NULL) {
++ printk(KERN_INFO "Couldn't alloc MPCgroup rcvd_xid_skb\n");
++ kfree_fsm(grp->fsm);
++ dev_kfree_skb(grp->xid_skb);
++ kfree(grp);
++ return NULL;
++ }
++ grp->rcvd_xid_data = grp->rcvd_xid_skb->data;
++ grp->rcvd_xid_th = (struct th_header *)grp->rcvd_xid_skb->data;
++ memcpy(skb_put(grp->rcvd_xid_skb, TH_HEADER_LENGTH),
++ &thnorm, TH_HEADER_LENGTH);
++ grp->saved_xid2 = NULL;
++ priv->xid = grp->xid;
++ priv->mpcg = grp;
++ return grp;
++}
++
++/*
++ * The MPC Group Station FSM
++ */
++
++/*
++ * MPC Group Station FSM actions
++ * CTCM_PROTO_MPC only
++ */
++
++/**
++ * NOP action for statemachines
++ */
++static void mpc_action_nop(fsm_instance *fi, int event, void *arg)
++{
++}
++
++/*
++ * invoked when the device transitions to dev_stopped
++ * MPC will stop each individual channel if a single XID failure
++ * occurs, or will intitiate all channels be stopped if a GROUP
++ * level failure occurs.
++ */
++static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg)
++{
++ struct net_device *dev = arg;
++ struct ctcm_priv *priv;
++ struct mpc_group *grp;
++ int rc = 0;
++ struct channel *wch, *rch;
++
++ if (dev == NULL) {
++ printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
++ return;
++ }
++
++ ctcm_pr_debug("ctcmpc enter: %s %s()\n", dev->name, __FUNCTION__);
++
++ priv = dev->priv;
++ grp = priv->mpcg;
++ grp->flow_off_called = 0;
++
++ fsm_deltimer(&grp->timer);
++
++ if (grp->channels_terminating)
++ goto done;
++
++ grp->channels_terminating = 1;
++
++ grp->saved_state = fsm_getstate(grp->fsm);
++ fsm_newstate(grp->fsm, MPCG_STATE_INOP);
++ if (grp->saved_state > MPCG_STATE_XID7INITF)
++ printk(KERN_NOTICE "%s:MPC GROUP INOPERATIVE\n", dev->name);
++ if ((grp->saved_state != MPCG_STATE_RESET) ||
++ /* dealloc_channel has been called */
++ ((grp->saved_state == MPCG_STATE_RESET) &&
++ (grp->port_persist == 0)))
++ fsm_deltimer(&priv->restart_timer);
++
++ wch = priv->channel[WRITE];
++ rch = priv->channel[READ];
++
++ switch (grp->saved_state) {
++ case MPCG_STATE_RESET:
++ case MPCG_STATE_INOP:
++ case MPCG_STATE_XID2INITW:
++ case MPCG_STATE_XID0IOWAIT:
++ case MPCG_STATE_XID2INITX:
++ case MPCG_STATE_XID7INITW:
++ case MPCG_STATE_XID7INITX:
++ case MPCG_STATE_XID0IOWAIX:
++ case MPCG_STATE_XID7INITI:
++ case MPCG_STATE_XID7INITZ:
++ case MPCG_STATE_XID7INITF:
++ break;
++ case MPCG_STATE_FLOWC:
++ case MPCG_STATE_READY:
++ default:
++ tasklet_hi_schedule(&wch->ch_disc_tasklet);
++ }
++
++ grp->xid2_tgnum = 0;
++ grp->group_max_buflen = 0; /*min of all received */
++ grp->outstanding_xid2 = 0;
++ grp->outstanding_xid7 = 0;
++ grp->outstanding_xid7_p2 = 0;
++ grp->saved_xid2 = NULL;
++ grp->xidnogood = 0;
++ grp->changed_side = 0;
++
++ grp->rcvd_xid_skb->data = grp->rcvd_xid_data;
++ skb_reset_tail_pointer(grp->rcvd_xid_skb);
++ grp->rcvd_xid_skb->len = 0;
++ grp->rcvd_xid_th = (struct th_header *)grp->rcvd_xid_skb->data;
++ memcpy(skb_put(grp->rcvd_xid_skb, TH_HEADER_LENGTH), &thnorm,
++ TH_HEADER_LENGTH);
++
++ if (grp->send_qllc_disc == 1) {
++ grp->send_qllc_disc = 0;
++ rc = mpc_send_qllc_discontact(dev);
++ }
++
++ /* DO NOT issue DEV_EVENT_STOP directly out of this code */
++ /* This can result in INOP of VTAM PU due to halting of */
++ /* outstanding IO which causes a sense to be returned */
++ /* Only about 3 senses are allowed and then IOS/VTAM will*/
++ /* ebcome unreachable without manual intervention */
++ if ((grp->port_persist == 1) || (grp->alloc_called)) {
++ grp->alloc_called = 0;
++ fsm_deltimer(&priv->restart_timer);
++ fsm_addtimer(&priv->restart_timer,
++ 500,
++ DEV_EVENT_RESTART,
++ dev);
++ fsm_newstate(grp->fsm, MPCG_STATE_RESET);
++ if (grp->saved_state > MPCG_STATE_XID7INITF)
++ printk(KERN_NOTICE "%s:MPC GROUP RECOVERY SCHEDULED\n",
++ dev->name);
++ } else {
++ fsm_deltimer(&priv->restart_timer);
++ fsm_addtimer(&priv->restart_timer, 500, DEV_EVENT_STOP, dev);
++ fsm_newstate(grp->fsm, MPCG_STATE_RESET);
++ printk(KERN_NOTICE "%s:MPC GROUP RECOVERY NOT ATTEMPTED\n",
++ dev->name);
++ }
++
++done:
++ ctcm_pr_debug("ctcmpc exit:%s %s()\n", dev->name, __FUNCTION__);
++ return;
++}
++
++/**
++ * Handle mpc group action timeout.
++ * MPC Group Station FSM action
++ * CTCM_PROTO_MPC only
++ *
++ * fi An instance of an mpc_group fsm.
++ * event The event, just happened.
++ * arg Generic pointer, casted from net_device * upon call.
++ */
++static void mpc_action_timeout(fsm_instance *fi, int event, void *arg)
++{
++ struct net_device *dev = arg;
++ struct ctcm_priv *priv;
++ struct mpc_group *grp;
++ struct channel *wch;
++ struct channel *rch;
++
++ CTCM_DBF_TEXT(MPC_TRACE, 6, __FUNCTION__);
++
++ if (dev == NULL) {
++ CTCM_DBF_TEXT_(MPC_ERROR, 4, "%s: dev=NULL\n", __FUNCTION__);
++ return;
++ }
++
++ priv = dev->priv;
++ grp = priv->mpcg;
++ wch = priv->channel[WRITE];
++ rch = priv->channel[READ];
++
++ switch (fsm_getstate(grp->fsm)) {
++ case MPCG_STATE_XID2INITW:
++ /* Unless there is outstanding IO on the */
++ /* channel just return and wait for ATTN */
++ /* interrupt to begin XID negotiations */
++ if ((fsm_getstate(rch->fsm) == CH_XID0_PENDING) &&
++ (fsm_getstate(wch->fsm) == CH_XID0_PENDING))
++ break;
++ default:
++ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++ }
++
++ CTCM_DBF_TEXT_(MPC_TRACE, 6, "%s: dev=%s exit",
++ __FUNCTION__, dev->name);
++ return;
++}
++
++/*
++ * MPC Group Station FSM action
++ * CTCM_PROTO_MPC only
++ */
++void mpc_action_discontact(fsm_instance *fi, int event, void *arg)
++{
++ struct mpcg_info *mpcginfo = arg;
++ struct channel *ch = mpcginfo->ch;
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++ struct mpc_group *grp = priv->mpcg;
++
++ if (ch == NULL) {
++ printk(KERN_INFO "%s() ch=NULL\n", __FUNCTION__);
++ return;
++ }
++ if (ch->netdev == NULL) {
++ printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
++ return;
++ }
++
++ ctcm_pr_debug("ctcmpc enter: %s %s()\n", dev->name, __FUNCTION__);
++
++ grp->send_qllc_disc = 1;
++ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++
++ ctcm_pr_debug("ctcmpc exit: %s %s()\n", dev->name, __FUNCTION__);
++ return;
++}
++
++/*
++ * MPC Group Station - not part of FSM
++ * CTCM_PROTO_MPC only
++ * called from add_channel in ctcm_main.c
++ */
++void mpc_action_send_discontact(unsigned long thischan)
++{
++ struct channel *ch;
++ struct net_device *dev;
++ struct ctcm_priv *priv;
++ struct mpc_group *grp;
++ int rc = 0;
++ unsigned long saveflags;
++
++ ch = (struct channel *)thischan;
++ dev = ch->netdev;
++ priv = dev->priv;
++ grp = priv->mpcg;
++
++ ctcm_pr_info("ctcmpc: %s cp:%i enter: %s() GrpState:%s ChState:%s\n",
++ dev->name,
++ smp_processor_id(),
++ __FUNCTION__,
++ fsm_getstate_str(grp->fsm),
++ fsm_getstate_str(ch->fsm));
++ saveflags = 0; /* avoids compiler warning with
++ spin_unlock_irqrestore */
++
++ spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
++ rc = ccw_device_start(ch->cdev, &ch->ccw[15],
++ (unsigned long)ch, 0xff, 0);
++ spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
++
++ if (rc != 0) {
++ ctcm_pr_info("ctcmpc: %s() ch:%s IO failed \n",
++ __FUNCTION__,
++ ch->id);
++ ctcm_ccw_check_rc(ch, rc, "send discontact");
++ /* Not checking return code value here */
++ /* Making best effort to notify partner*/
++ /* that MPC Group is going down */
++ }
++
++ ctcm_pr_debug("ctcmpc exit: %s %s()\n", dev->name, __FUNCTION__);
++ return;
++}
++
++
++/*
++ * helper function of mpc FSM
++ * CTCM_PROTO_MPC only
++ * mpc_action_rcvd_xid7
++*/
++static int mpc_validate_xid(struct mpcg_info *mpcginfo)
++{
++ struct channel *ch = mpcginfo->ch;
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++ struct mpc_group *grp = priv->mpcg;
++ struct xid2 *xid = mpcginfo->xid;
++ int failed = 0;
++ int rc = 0;
++ __u64 our_id, their_id = 0;
++ int len;
++
++ len = TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
++
++ ctcm_pr_debug("ctcmpc enter: %s()\n", __FUNCTION__);
++
++ if (mpcginfo->xid == NULL) {
++ printk(KERN_INFO "%s() xid=NULL\n", __FUNCTION__);
++ rc = 1;
++ goto done;
++ }
++
++ ctcm_pr_debug("ctcmpc : %s xid received()\n", __FUNCTION__);
++ ctcmpc_dumpit((char *)mpcginfo->xid, XID2_LENGTH);
++
++ /*the received direction should be the opposite of ours */
++ if (((CHANNEL_DIRECTION(ch->flags) == READ) ? XID2_WRITE_SIDE :
++ XID2_READ_SIDE) != xid->xid2_dlc_type) {
++ failed = 1;
++ printk(KERN_INFO "ctcmpc:%s() XID REJECTED - READ-WRITE CH "
++ "Pairing Invalid \n", __FUNCTION__);
++ }
++
++ if (xid->xid2_dlc_type == XID2_READ_SIDE) {
++ ctcm_pr_debug("ctcmpc: %s(): grpmaxbuf:%d xid2buflen:%d\n",
++ __FUNCTION__, grp->group_max_buflen,
++ xid->xid2_buf_len);
++
++ if (grp->group_max_buflen == 0 ||
++ grp->group_max_buflen > xid->xid2_buf_len - len)
++ grp->group_max_buflen = xid->xid2_buf_len - len;
++ }
++
++
++ if (grp->saved_xid2 == NULL) {
++ grp->saved_xid2 =
++ (struct xid2 *)skb_tail_pointer(grp->rcvd_xid_skb);
++
++ memcpy(skb_put(grp->rcvd_xid_skb,
++ XID2_LENGTH), xid, XID2_LENGTH);
++ grp->rcvd_xid_skb->data = grp->rcvd_xid_data;
++
++ skb_reset_tail_pointer(grp->rcvd_xid_skb);
++ grp->rcvd_xid_skb->len = 0;
++
++ /* convert two 32 bit numbers into 1 64 bit for id compare */
++ our_id = (__u64)priv->xid->xid2_adj_id;
++ our_id = our_id << 32;
++ our_id = our_id + priv->xid->xid2_sender_id;
++ their_id = (__u64)xid->xid2_adj_id;
++ their_id = their_id << 32;
++ their_id = their_id + xid->xid2_sender_id;
++ /* lower id assume the xside role */
++ if (our_id < their_id) {
++ grp->roll = XSIDE;
++ ctcm_pr_debug("ctcmpc :%s() WE HAVE LOW ID-"
++ "TAKE XSIDE\n", __FUNCTION__);
++ } else {
++ grp->roll = YSIDE;
++ ctcm_pr_debug("ctcmpc :%s() WE HAVE HIGH ID-"
++ "TAKE YSIDE\n", __FUNCTION__);
++ }
++
++ } else {
++ if (xid->xid2_flag4 != grp->saved_xid2->xid2_flag4) {
++ failed = 1;
++ printk(KERN_INFO "%s XID REJECTED - XID Flag Byte4\n",
++ __FUNCTION__);
++ }
++ if (xid->xid2_flag2 == 0x40) {
++ failed = 1;
++ printk(KERN_INFO "%s XID REJECTED - XID NOGOOD\n",
++ __FUNCTION__);
++ }
++ if (xid->xid2_adj_id != grp->saved_xid2->xid2_adj_id) {
++ failed = 1;
++ printk(KERN_INFO "%s XID REJECTED - "
++ "Adjacent Station ID Mismatch\n",
++ __FUNCTION__);
++ }
++ if (xid->xid2_sender_id != grp->saved_xid2->xid2_sender_id) {
++ failed = 1;
++ printk(KERN_INFO "%s XID REJECTED - "
++ "Sender Address Mismatch\n", __FUNCTION__);
++
++ }
++ }
++
++ if (failed) {
++ ctcm_pr_info("ctcmpc : %s() failed\n", __FUNCTION__);
++ priv->xid->xid2_flag2 = 0x40;
++ grp->saved_xid2->xid2_flag2 = 0x40;
++ rc = 1;
++ }
++
++done:
++
++ ctcm_pr_debug("ctcmpc exit: %s()\n", __FUNCTION__);
++ return rc;
++}
++
++/*
++ * MPC Group Station FSM action
++ * CTCM_PROTO_MPC only
++ */
++static void mpc_action_side_xid(fsm_instance *fsm, void *arg, int side)
++{
++ struct channel *ch = arg;
++ struct ctcm_priv *priv;
++ struct mpc_group *grp = NULL;
++ struct net_device *dev = NULL;
++ int rc = 0;
++ int gotlock = 0;
++ unsigned long saveflags = 0; /* avoids compiler warning with
++ spin_unlock_irqrestore */
++
++ if (ch == NULL) {
++ printk(KERN_INFO "%s ch=NULL\n", __FUNCTION__);
++ goto done;
++ }
++
++ if (do_debug)
++ ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
++ __FUNCTION__, smp_processor_id(), ch, ch->id);
++
++ dev = ch->netdev;
++ if (dev == NULL) {
++ printk(KERN_INFO "%s dev=NULL\n", __FUNCTION__);
++ goto done;
++ }
++
++ priv = dev->priv;
++ if (priv == NULL) {
++ printk(KERN_INFO "%s priv=NULL\n", __FUNCTION__);
++ goto done;
++ }
++
++ grp = priv->mpcg;
++ if (grp == NULL) {
++ printk(KERN_INFO "%s grp=NULL\n", __FUNCTION__);
++ goto done;
++ }
++
++ if (ctcm_checkalloc_buffer(ch))
++ goto done;
++
++ /* skb data-buffer referencing: */
++
++ ch->trans_skb->data = ch->trans_skb_data;
++ skb_reset_tail_pointer(ch->trans_skb);
++ ch->trans_skb->len = 0;
++ /* result of the previous 3 statements is NOT always
++ * already set after ctcm_checkalloc_buffer
++ * because of possible reuse of the trans_skb
++ */
++ memset(ch->trans_skb->data, 0, 16);
++ ch->rcvd_xid_th = (struct th_header *)ch->trans_skb_data;
++ /* check is main purpose here: */
++ skb_put(ch->trans_skb, TH_HEADER_LENGTH);
++ ch->rcvd_xid = (struct xid2 *)skb_tail_pointer(ch->trans_skb);
++ /* check is main purpose here: */
++ skb_put(ch->trans_skb, XID2_LENGTH);
++ ch->rcvd_xid_id = skb_tail_pointer(ch->trans_skb);
++ /* cleanup back to startpoint */
++ ch->trans_skb->data = ch->trans_skb_data;
++ skb_reset_tail_pointer(ch->trans_skb);
++ ch->trans_skb->len = 0;
++
++ /* non-checking rewrite of above skb data-buffer referencing: */
++ /*
++ memset(ch->trans_skb->data, 0, 16);
++ ch->rcvd_xid_th = (struct th_header *)ch->trans_skb_data;
++ ch->rcvd_xid = (struct xid2 *)(ch->trans_skb_data + TH_HEADER_LENGTH);
++ ch->rcvd_xid_id = ch->trans_skb_data + TH_HEADER_LENGTH + XID2_LENGTH;
++ */
++
++ ch->ccw[8].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
++ ch->ccw[8].count = 0;
++ ch->ccw[8].cda = 0x00;
++
++ if (side == XSIDE) {
++ /* mpc_action_xside_xid */
++ if (ch->xid_th == NULL) {
++ printk(KERN_INFO "%s ch->xid_th=NULL\n", __FUNCTION__);
++ goto done;
++ }
++ ch->ccw[9].cmd_code = CCW_CMD_WRITE;
++ ch->ccw[9].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
++ ch->ccw[9].count = TH_HEADER_LENGTH;
++ ch->ccw[9].cda = virt_to_phys(ch->xid_th);
++
++ if (ch->xid == NULL) {
++ printk(KERN_INFO "%s ch->xid=NULL\n", __FUNCTION__);
++ goto done;
++ }
++
++ ch->ccw[10].cmd_code = CCW_CMD_WRITE;
++ ch->ccw[10].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
++ ch->ccw[10].count = XID2_LENGTH;
++ ch->ccw[10].cda = virt_to_phys(ch->xid);
++
++ ch->ccw[11].cmd_code = CCW_CMD_READ;
++ ch->ccw[11].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
++ ch->ccw[11].count = TH_HEADER_LENGTH;
++ ch->ccw[11].cda = virt_to_phys(ch->rcvd_xid_th);
++
++ ch->ccw[12].cmd_code = CCW_CMD_READ;
++ ch->ccw[12].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
++ ch->ccw[12].count = XID2_LENGTH;
++ ch->ccw[12].cda = virt_to_phys(ch->rcvd_xid);
++
++ ch->ccw[13].cmd_code = CCW_CMD_READ;
++ ch->ccw[13].cda = virt_to_phys(ch->rcvd_xid_id);
++
++ } else { /* side == YSIDE : mpc_action_yside_xid */
++ ch->ccw[9].cmd_code = CCW_CMD_READ;
++ ch->ccw[9].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
++ ch->ccw[9].count = TH_HEADER_LENGTH;
++ ch->ccw[9].cda = virt_to_phys(ch->rcvd_xid_th);
++
++ ch->ccw[10].cmd_code = CCW_CMD_READ;
++ ch->ccw[10].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
++ ch->ccw[10].count = XID2_LENGTH;
++ ch->ccw[10].cda = virt_to_phys(ch->rcvd_xid);
++
++ if (ch->xid_th == NULL) {
++ printk(KERN_INFO "%s ch->xid_th=NULL\n", __FUNCTION__);
++ goto done;
++ }
++ ch->ccw[11].cmd_code = CCW_CMD_WRITE;
++ ch->ccw[11].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
++ ch->ccw[11].count = TH_HEADER_LENGTH;
++ ch->ccw[11].cda = virt_to_phys(ch->xid_th);
++
++ if (ch->xid == NULL) {
++ printk(KERN_INFO "%s ch->xid=NULL\n", __FUNCTION__);
++ goto done;
++ }
++ ch->ccw[12].cmd_code = CCW_CMD_WRITE;
++ ch->ccw[12].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
++ ch->ccw[12].count = XID2_LENGTH;
++ ch->ccw[12].cda = virt_to_phys(ch->xid);
++
++ if (ch->xid_id == NULL) {
++ printk(KERN_INFO "%s ch->xid_id=NULL\n", __FUNCTION__);
++ goto done;
++ }
++ ch->ccw[13].cmd_code = CCW_CMD_WRITE;
++ ch->ccw[13].cda = virt_to_phys(ch->xid_id);
++
++ }
++ ch->ccw[13].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
++ ch->ccw[13].count = 4;
++
++ ch->ccw[14].cmd_code = CCW_CMD_NOOP;
++ ch->ccw[14].flags = CCW_FLAG_SLI;
++ ch->ccw[14].count = 0;
++ ch->ccw[14].cda = 0;
++
++ if (do_debug_ccw)
++ ctcmpc_dumpit((char *)&ch->ccw[8], sizeof(struct ccw1) * 7);
++
++ ctcmpc_dumpit((char *)ch->xid_th, TH_HEADER_LENGTH);
++ ctcmpc_dumpit((char *)ch->xid, XID2_LENGTH);
++ ctcmpc_dumpit((char *)ch->xid_id, 4);
++ if (!in_irq()) {
++ /* Such conditional locking is a known problem for
++ * sparse because its static undeterministic.
++ * Warnings should be ignored here. */
++ spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
++ gotlock = 1;
++ }
++
++ fsm_addtimer(&ch->timer, 5000 , CTC_EVENT_TIMER, ch);
++ rc = ccw_device_start(ch->cdev, &ch->ccw[8],
++ (unsigned long)ch, 0xff, 0);
++
++ if (gotlock) /* see remark above about conditional locking */
++ spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
++
++ if (rc != 0) {
++ ctcm_pr_info("ctcmpc: %s() ch:%s IO failed \n",
++ __FUNCTION__, ch->id);
++ ctcm_ccw_check_rc(ch, rc,
++ (side == XSIDE) ? "x-side XID" : "y-side XID");
++ }
++
++done:
++ if (do_debug)
++ ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
++ __FUNCTION__, ch, ch->id);
++ return;
++
++}
++
++/*
++ * MPC Group Station FSM action
++ * CTCM_PROTO_MPC only
++ */
++static void mpc_action_xside_xid(fsm_instance *fsm, int event, void *arg)
++{
++ mpc_action_side_xid(fsm, arg, XSIDE);
++}
++
++/*
++ * MPC Group Station FSM action
++ * CTCM_PROTO_MPC only
++ */
++static void mpc_action_yside_xid(fsm_instance *fsm, int event, void *arg)
++{
++ mpc_action_side_xid(fsm, arg, YSIDE);
++}
++
++/*
++ * MPC Group Station FSM action
++ * CTCM_PROTO_MPC only
++ */
++static void mpc_action_doxid0(fsm_instance *fsm, int event, void *arg)
++{
++ struct channel *ch = arg;
++ struct ctcm_priv *priv;
++ struct mpc_group *grp = NULL;
++ struct net_device *dev = NULL;
++
++ if (do_debug)
++ ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
++ __FUNCTION__, smp_processor_id(), ch, ch->id);
++
++ if (ch == NULL) {
++ printk(KERN_WARNING "%s ch=NULL\n", __FUNCTION__);
++ goto done;
++ }
++
++ dev = ch->netdev;
++ if (dev == NULL) {
++ printk(KERN_WARNING "%s dev=NULL\n", __FUNCTION__);
++ goto done;
++ }
++
++ priv = dev->priv;
++ if (priv == NULL) {
++ printk(KERN_WARNING "%s priv=NULL\n", __FUNCTION__);
++ goto done;
++ }
++
++ grp = priv->mpcg;
++ if (grp == NULL) {
++ printk(KERN_WARNING "%s grp=NULL\n", __FUNCTION__);
++ goto done;
++ }
++
++ if (ch->xid == NULL) {
++ printk(KERN_WARNING "%s ch-xid=NULL\n", __FUNCTION__);
++ goto done;
++ }
++
++ fsm_newstate(ch->fsm, CH_XID0_INPROGRESS);
++
++ ch->xid->xid2_option = XID2_0;
++
++ switch (fsm_getstate(grp->fsm)) {
++ case MPCG_STATE_XID2INITW:
++ case MPCG_STATE_XID2INITX:
++ ch->ccw[8].cmd_code = CCW_CMD_SENSE_CMD;
++ break;
++ case MPCG_STATE_XID0IOWAIT:
++ case MPCG_STATE_XID0IOWAIX:
++ ch->ccw[8].cmd_code = CCW_CMD_WRITE_CTL;
++ break;
++ }
++
++ fsm_event(grp->fsm, MPCG_EVENT_DOIO, ch);
++
++done:
++ if (do_debug)
++ ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
++ __FUNCTION__, ch, ch->id);
++ return;
++
++}
++
++/*
++ * MPC Group Station FSM action
++ * CTCM_PROTO_MPC only
++*/
++static void mpc_action_doxid7(fsm_instance *fsm, int event, void *arg)
++{
++ struct net_device *dev = arg;
++ struct ctcm_priv *priv = NULL;
++ struct mpc_group *grp = NULL;
++ int direction;
++ int rc = 0;
++ int send = 0;
++
++ ctcm_pr_debug("ctcmpc enter: %s() \n", __FUNCTION__);
++
++ if (dev == NULL) {
++ printk(KERN_INFO "%s dev=NULL \n", __FUNCTION__);
++ rc = 1;
++ goto done;
++ }
++
++ priv = dev->priv;
++ if (priv == NULL) {
++ printk(KERN_INFO "%s priv=NULL \n", __FUNCTION__);
++ rc = 1;
++ goto done;
++ }
++
++ grp = priv->mpcg;
++ if (grp == NULL) {
++ printk(KERN_INFO "%s grp=NULL \n", __FUNCTION__);
++ rc = 1;
++ goto done;
++ }
++
++ for (direction = READ; direction <= WRITE; direction++) {
++ struct channel *ch = priv->channel[direction];
++ struct xid2 *thisxid = ch->xid;
++ ch->xid_skb->data = ch->xid_skb_data;
++ skb_reset_tail_pointer(ch->xid_skb);
++ ch->xid_skb->len = 0;
++ thisxid->xid2_option = XID2_7;
++ send = 0;
++
++ /* xid7 phase 1 */
++ if (grp->outstanding_xid7_p2 > 0) {
++ if (grp->roll == YSIDE) {
++ if (fsm_getstate(ch->fsm) == CH_XID7_PENDING1) {
++ fsm_newstate(ch->fsm, CH_XID7_PENDING2);
++ ch->ccw[8].cmd_code = CCW_CMD_SENSE_CMD;
++ memcpy(skb_put(ch->xid_skb,
++ TH_HEADER_LENGTH),
++ &thdummy, TH_HEADER_LENGTH);
++ send = 1;
++ }
++ } else if (fsm_getstate(ch->fsm) < CH_XID7_PENDING2) {
++ fsm_newstate(ch->fsm, CH_XID7_PENDING2);
++ ch->ccw[8].cmd_code = CCW_CMD_WRITE_CTL;
++ memcpy(skb_put(ch->xid_skb,
++ TH_HEADER_LENGTH),
++ &thnorm, TH_HEADER_LENGTH);
++ send = 1;
++ }
++ } else {
++ /* xid7 phase 2 */
++ if (grp->roll == YSIDE) {
++ if (fsm_getstate(ch->fsm) < CH_XID7_PENDING4) {
++ fsm_newstate(ch->fsm, CH_XID7_PENDING4);
++ memcpy(skb_put(ch->xid_skb,
++ TH_HEADER_LENGTH),
++ &thnorm, TH_HEADER_LENGTH);
++ ch->ccw[8].cmd_code = CCW_CMD_WRITE_CTL;
++ send = 1;
++ }
++ } else if (fsm_getstate(ch->fsm) == CH_XID7_PENDING3) {
++ fsm_newstate(ch->fsm, CH_XID7_PENDING4);
++ ch->ccw[8].cmd_code = CCW_CMD_SENSE_CMD;
++ memcpy(skb_put(ch->xid_skb, TH_HEADER_LENGTH),
++ &thdummy, TH_HEADER_LENGTH);
++ send = 1;
++ }
++ }
++
++ if (send)
++ fsm_event(grp->fsm, MPCG_EVENT_DOIO, ch);
++ }
++
++done:
++
++ if (rc != 0)
++ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
++
++ return;
++}
++
++/*
++ * MPC Group Station FSM action
++ * CTCM_PROTO_MPC only
++ */
++static void mpc_action_rcvd_xid0(fsm_instance *fsm, int event, void *arg)
++{
++
++ struct mpcg_info *mpcginfo = arg;
++ struct channel *ch = mpcginfo->ch;
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv;
++ struct mpc_group *grp;
++
++ if (do_debug)
++ ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
++ __FUNCTION__, smp_processor_id(), ch, ch->id);
++
++ priv = dev->priv;
++ grp = priv->mpcg;
++
++ ctcm_pr_debug("ctcmpc in:%s() %s xid2:%i xid7:%i xidt_p2:%i \n",
++ __FUNCTION__, ch->id,
++ grp->outstanding_xid2,
++ grp->outstanding_xid7,
++ grp->outstanding_xid7_p2);
++
++ if (fsm_getstate(ch->fsm) < CH_XID7_PENDING)
++ fsm_newstate(ch->fsm, CH_XID7_PENDING);
++
++ grp->outstanding_xid2--;
++ grp->outstanding_xid7++;
++ grp->outstanding_xid7_p2++;
++
++ /* must change state before validating xid to */
++ /* properly handle interim interrupts received*/
++ switch (fsm_getstate(grp->fsm)) {
++ case MPCG_STATE_XID2INITW:
++ fsm_newstate(grp->fsm, MPCG_STATE_XID2INITX);
++ mpc_validate_xid(mpcginfo);
++ break;
++ case MPCG_STATE_XID0IOWAIT:
++ fsm_newstate(grp->fsm, MPCG_STATE_XID0IOWAIX);
++ mpc_validate_xid(mpcginfo);
++ break;
++ case MPCG_STATE_XID2INITX:
++ if (grp->outstanding_xid2 == 0) {
++ fsm_newstate(grp->fsm, MPCG_STATE_XID7INITW);
++ mpc_validate_xid(mpcginfo);
++ fsm_event(grp->fsm, MPCG_EVENT_XID2DONE, dev);
++ }
++ break;
++ case MPCG_STATE_XID0IOWAIX:
++ if (grp->outstanding_xid2 == 0) {
++ fsm_newstate(grp->fsm, MPCG_STATE_XID7INITI);
++ mpc_validate_xid(mpcginfo);
++ fsm_event(grp->fsm, MPCG_EVENT_XID2DONE, dev);
++ }
++ break;
++ }
++ kfree(mpcginfo);
++
++ if (do_debug) {
++ ctcm_pr_debug("ctcmpc:%s() %s xid2:%i xid7:%i xidt_p2:%i \n",
++ __FUNCTION__, ch->id,
++ grp->outstanding_xid2,
++ grp->outstanding_xid7,
++ grp->outstanding_xid7_p2);
++ ctcm_pr_debug("ctcmpc:%s() %s grpstate: %s chanstate: %s \n",
++ __FUNCTION__, ch->id,
++ fsm_getstate_str(grp->fsm),
++ fsm_getstate_str(ch->fsm));
++ }
++ return;
++
++}
++
++
++/*
++ * MPC Group Station FSM action
++ * CTCM_PROTO_MPC only
++ */
++static void mpc_action_rcvd_xid7(fsm_instance *fsm, int event, void *arg)
++{
++ struct mpcg_info *mpcginfo = arg;
++ struct channel *ch = mpcginfo->ch;
++ struct net_device *dev = ch->netdev;
++ struct ctcm_priv *priv = dev->priv;
++ struct mpc_group *grp = priv->mpcg;
++
++ if (do_debug) {
++ ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
++ __FUNCTION__, smp_processor_id(), ch, ch->id);
++
++ ctcm_pr_debug("ctcmpc: outstanding_xid7: %i, "
++ " outstanding_xid7_p2: %i\n",
++ grp->outstanding_xid7,
++ grp->outstanding_xid7_p2);
++ }
++
++ grp->outstanding_xid7--;
++ ch->xid_skb->data = ch->xid_skb_data;
++ skb_reset_tail_pointer(ch->xid_skb);
++ ch->xid_skb->len = 0;
++
++ switch (fsm_getstate(grp->fsm)) {
++ case MPCG_STATE_XID7INITI:
++ fsm_newstate(grp->fsm, MPCG_STATE_XID7INITZ);
++ mpc_validate_xid(mpcginfo);
++ break;
++ case MPCG_STATE_XID7INITW:
++ fsm_newstate(grp->fsm, MPCG_STATE_XID7INITX);
++ mpc_validate_xid(mpcginfo);
++ break;
++ case MPCG_STATE_XID7INITZ:
++ case MPCG_STATE_XID7INITX:
++ if (grp->outstanding_xid7 == 0) {
++ if (grp->outstanding_xid7_p2 > 0) {
++ grp->outstanding_xid7 =
++ grp->outstanding_xid7_p2;
++ grp->outstanding_xid7_p2 = 0;
++ } else
++ fsm_newstate(grp->fsm, MPCG_STATE_XID7INITF);
++
++ mpc_validate_xid(mpcginfo);
++ fsm_event(grp->fsm, MPCG_EVENT_XID7DONE, dev);
++ break;
++ }
++ mpc_validate_xid(mpcginfo);
++ break;
++ }
++
++ kfree(mpcginfo);
++
++ if (do_debug)
++ ctcm_pr_debug("ctcmpc exit: %s(): cp=%i ch=0x%p id=%s\n",
++ __FUNCTION__, smp_processor_id(), ch, ch->id);
++ return;
++
++}
++
++/*
++ * mpc_action helper of an MPC Group Station FSM action
++ * CTCM_PROTO_MPC only
++ */
++static int mpc_send_qllc_discontact(struct net_device *dev)
++{
++ int rc = 0;
++ __u32 new_len = 0;
++ struct sk_buff *skb;
++ struct qllc *qllcptr;
++ struct ctcm_priv *priv;
++ struct mpc_group *grp;
++
++ ctcm_pr_debug("ctcmpc enter: %s()\n", __FUNCTION__);
++
++ if (dev == NULL) {
++ printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
++ rc = 1;
++ goto done;
++ }
++
++ priv = dev->priv;
++ if (priv == NULL) {
++ printk(KERN_INFO "%s() priv=NULL\n", __FUNCTION__);
++ rc = 1;
++ goto done;
++ }
++
++ grp = priv->mpcg;
++ if (grp == NULL) {
++ printk(KERN_INFO "%s() grp=NULL\n", __FUNCTION__);
++ rc = 1;
++ goto done;
++ }
++ ctcm_pr_info("ctcmpc: %s() GROUP STATE: %s\n", __FUNCTION__,
++ mpcg_state_names[grp->saved_state]);
++
++ switch (grp->saved_state) {
++ /*
++ * establish conn callback function is
++ * preferred method to report failure
++ */
++ case MPCG_STATE_XID0IOWAIT:
++ case MPCG_STATE_XID0IOWAIX:
++ case MPCG_STATE_XID7INITI:
++ case MPCG_STATE_XID7INITZ:
++ case MPCG_STATE_XID2INITW:
++ case MPCG_STATE_XID2INITX:
++ case MPCG_STATE_XID7INITW:
++ case MPCG_STATE_XID7INITX:
++ if (grp->estconnfunc) {
++ grp->estconnfunc(grp->port_num, -1, 0);
++ grp->estconnfunc = NULL;
++ break;
++ }
++ case MPCG_STATE_FLOWC:
++ case MPCG_STATE_READY:
++ grp->send_qllc_disc = 2;
++ new_len = sizeof(struct qllc);
++ qllcptr = kzalloc(new_len, gfp_type() | GFP_DMA);
++ if (qllcptr == NULL) {
++ printk(KERN_INFO
++ "ctcmpc: Out of memory in %s()\n",
++ dev->name);
++ rc = 1;
++ goto done;
++ }
++
++ qllcptr->qllc_address = 0xcc;
++ qllcptr->qllc_commands = 0x03;
++
++ skb = __dev_alloc_skb(new_len, GFP_ATOMIC);
++
++ if (skb == NULL) {
++ printk(KERN_INFO "%s Out of memory in mpc_send_qllc\n",
++ dev->name);
++ priv->stats.rx_dropped++;
++ rc = 1;
++ kfree(qllcptr);
++ goto done;
++ }
++
++ memcpy(skb_put(skb, new_len), qllcptr, new_len);
++ kfree(qllcptr);
++
++ if (skb_headroom(skb) < 4) {
++ printk(KERN_INFO "ctcmpc: %s() Unable to"
++ " build discontact for %s\n",
++ __FUNCTION__, dev->name);
++ rc = 1;
++ dev_kfree_skb_any(skb);
++ goto done;
++ }
++
++ *((__u32 *)skb_push(skb, 4)) = priv->channel[READ]->pdu_seq;
++ priv->channel[READ]->pdu_seq++;
++ if (do_debug_data)
++ ctcm_pr_debug("ctcmpc: %s ToDCM_pdu_seq= %08x\n",
++ __FUNCTION__, priv->channel[READ]->pdu_seq);
++
++ /* receipt of CC03 resets anticipated sequence number on
++ receiving side */
++ priv->channel[READ]->pdu_seq = 0x00;
++ skb_reset_mac_header(skb);
++ skb->dev = dev;
++ skb->protocol = htons(ETH_P_SNAP);
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++
++ ctcmpc_dumpit((char *)skb->data, (sizeof(struct qllc) + 4));
++
++ netif_rx(skb);
++ break;
++ default:
++ break;
++
++ }
++
++done:
++ ctcm_pr_debug("ctcmpc exit: %s()\n", __FUNCTION__);
++ return rc;
++}
++/* --- This is the END my friend --- */
++
+diff --git a/drivers/s390/net/ctcm_mpc.h b/drivers/s390/net/ctcm_mpc.h
+new file mode 100644
+index 0000000..f996860
+--- /dev/null
++++ b/drivers/s390/net/ctcm_mpc.h
+@@ -0,0 +1,239 @@
++/*
++ * drivers/s390/net/ctcm_mpc.h
++ *
++ * Copyright IBM Corp. 2007
++ * Authors: Peter Tiedemann (ptiedem at de.ibm.com)
++ *
++ * MPC additions:
++ * Belinda Thompson (belindat at us.ibm.com)
++ * Andy Richter (richtera at us.ibm.com)
++ */
++
++#ifndef _CTC_MPC_H_
++#define _CTC_MPC_H_
++
++#include <linux/skbuff.h>
++#include "fsm.h"
++
++/*
++ * MPC external interface
++ * Note that ctc_mpc_xyz are called with a lock on ................
++ */
++
++/* port_number is the mpc device 0, 1, 2 etc mpc2 is port_number 2 */
++
++/* passive open Just wait for XID2 exchange */
++extern int ctc_mpc_alloc_channel(int port,
++ void (*callback)(int port_num, int max_write_size));
++/* active open Alloc then send XID2 */
++extern void ctc_mpc_establish_connectivity(int port,
++ void (*callback)(int port_num, int rc, int max_write_size));
++
++extern void ctc_mpc_dealloc_ch(int port);
++extern void ctc_mpc_flow_control(int port, int flowc);
++
++/*
++ * other MPC Group prototypes and structures
++ */
++
++#define ETH_P_SNA_DIX 0x80D5
++
++/*
++ * Declaration of an XID2
++ *
++ */
++#define ALLZEROS 0x0000000000000000
++
++#define XID_FM2 0x20
++#define XID2_0 0x00
++#define XID2_7 0x07
++#define XID2_WRITE_SIDE 0x04
++#define XID2_READ_SIDE 0x05
++
++struct xid2 {
++ __u8 xid2_type_id;
++ __u8 xid2_len;
++ __u32 xid2_adj_id;
++ __u8 xid2_rlen;
++ __u8 xid2_resv1;
++ __u8 xid2_flag1;
++ __u8 xid2_fmtt;
++ __u8 xid2_flag4;
++ __u16 xid2_resv2;
++ __u8 xid2_tgnum;
++ __u32 xid2_sender_id;
++ __u8 xid2_flag2;
++ __u8 xid2_option;
++ char xid2_resv3[8];
++ __u16 xid2_resv4;
++ __u8 xid2_dlc_type;
++ __u16 xid2_resv5;
++ __u8 xid2_mpc_flag;
++ __u8 xid2_resv6;
++ __u16 xid2_buf_len;
++ char xid2_buffer[255 - (13 * sizeof(__u8) +
++ 2 * sizeof(__u32) +
++ 4 * sizeof(__u16) +
++ 8 * sizeof(char))];
++} __attribute__ ((packed));
++
++#define XID2_LENGTH (sizeof(struct xid2))
++
++struct th_header {
++ __u8 th_seg;
++ __u8 th_ch_flag;
++#define TH_HAS_PDU 0xf0
++#define TH_IS_XID 0x01
++#define TH_SWEEP_REQ 0xfe
++#define TH_SWEEP_RESP 0xff
++ __u8 th_blk_flag;
++#define TH_DATA_IS_XID 0x80
++#define TH_RETRY 0x40
++#define TH_DISCONTACT 0xc0
++#define TH_SEG_BLK 0x20
++#define TH_LAST_SEG 0x10
++#define TH_PDU_PART 0x08
++ __u8 th_is_xid; /* is 0x01 if this is XID */
++ __u32 th_seq_num;
++} __attribute__ ((packed));
++
++struct th_addon {
++ __u32 th_last_seq;
++ __u32 th_resvd;
++} __attribute__ ((packed));
++
++struct th_sweep {
++ struct th_header th;
++ struct th_addon sw;
++} __attribute__ ((packed));
++
++#define TH_HEADER_LENGTH (sizeof(struct th_header))
++#define TH_SWEEP_LENGTH (sizeof(struct th_sweep))
++
++#define PDU_LAST 0x80
++#define PDU_CNTL 0x40
++#define PDU_FIRST 0x20
++
++struct pdu {
++ __u32 pdu_offset;
++ __u8 pdu_flag;
++ __u8 pdu_proto; /* 0x01 is APPN SNA */
++ __u16 pdu_seq;
++} __attribute__ ((packed));
++
++#define PDU_HEADER_LENGTH (sizeof(struct pdu))
++
++struct qllc {
++ __u8 qllc_address;
++#define QLLC_REQ 0xFF
++#define QLLC_RESP 0x00
++ __u8 qllc_commands;
++#define QLLC_DISCONNECT 0x53
++#define QLLC_UNSEQACK 0x73
++#define QLLC_SETMODE 0x93
++#define QLLC_EXCHID 0xBF
++} __attribute__ ((packed));
++
++
++/*
++ * Definition of one MPC group
++ */
++
++#define MAX_MPCGCHAN 10
++#define MPC_XID_TIMEOUT_VALUE 10000
++#define MPC_CHANNEL_ADD 0
++#define MPC_CHANNEL_REMOVE 1
++#define MPC_CHANNEL_ATTN 2
++#define XSIDE 1
++#define YSIDE 0
++
++struct mpcg_info {
++ struct sk_buff *skb;
++ struct channel *ch;
++ struct xid2 *xid;
++ struct th_sweep *sweep;
++ struct th_header *th;
++};
++
++struct mpc_group {
++ struct tasklet_struct mpc_tasklet;
++ struct tasklet_struct mpc_tasklet2;
++ int changed_side;
++ int saved_state;
++ int channels_terminating;
++ int out_of_sequence;
++ int flow_off_called;
++ int port_num;
++ int port_persist;
++ int alloc_called;
++ __u32 xid2_adj_id;
++ __u8 xid2_tgnum;
++ __u32 xid2_sender_id;
++ int num_channel_paths;
++ int active_channels[2];
++ __u16 group_max_buflen;
++ int outstanding_xid2;
++ int outstanding_xid7;
++ int outstanding_xid7_p2;
++ int sweep_req_pend_num;
++ int sweep_rsp_pend_num;
++ struct sk_buff *xid_skb;
++ char *xid_skb_data;
++ struct th_header *xid_th;
++ struct xid2 *xid;
++ char *xid_id;
++ struct th_header *rcvd_xid_th;
++ struct sk_buff *rcvd_xid_skb;
++ char *rcvd_xid_data;
++ __u8 in_sweep;
++ __u8 roll;
++ struct xid2 *saved_xid2;
++ void (*allochanfunc)(int, int);
++ int allocchan_callback_retries;
++ void (*estconnfunc)(int, int, int);
++ int estconn_callback_retries;
++ int estconn_called;
++ int xidnogood;
++ int send_qllc_disc;
++ fsm_timer timer;
++ fsm_instance *fsm; /* group xid fsm */
++};
++
++#ifdef DEBUGDATA
++void ctcmpc_dumpit(char *buf, int len);
++#else
++static inline void ctcmpc_dumpit(char *buf, int len)
++{
++}
++#endif
++
++#ifdef DEBUGDATA
++/*
++ * Dump header and first 16 bytes of an sk_buff for debugging purposes.
++ *
++ * skb The struct sk_buff to dump.
++ * offset Offset relative to skb-data, where to start the dump.
++ */
++void ctcmpc_dump_skb(struct sk_buff *skb, int offset);
++#else
++static inline void ctcmpc_dump_skb(struct sk_buff *skb, int offset)
++{}
++#endif
++
++static inline void ctcmpc_dump32(char *buf, int len)
++{
++ if (len < 32)
++ ctcmpc_dumpit(buf, len);
++ else
++ ctcmpc_dumpit(buf, 32);
++}
++
++int ctcmpc_open(struct net_device *);
++void ctcm_ccw_check_rc(struct channel *, int, char *);
++void mpc_group_ready(unsigned long adev);
++int mpc_channel_action(struct channel *ch, int direction, int action);
++void mpc_action_send_discontact(unsigned long thischan);
++void mpc_action_discontact(fsm_instance *fi, int event, void *arg);
++void ctcmpc_bh(unsigned long thischan);
++#endif
++/* --- This is the END my friend --- */
+diff --git a/drivers/s390/net/ctcm_sysfs.c b/drivers/s390/net/ctcm_sysfs.c
+new file mode 100644
+index 0000000..bb2d137
+--- /dev/null
++++ b/drivers/s390/net/ctcm_sysfs.c
+@@ -0,0 +1,210 @@
++/*
++ * drivers/s390/net/ctcm_sysfs.c
++ *
++ * Copyright IBM Corp. 2007, 2007
++ * Authors: Peter Tiedemann (ptiedem at de.ibm.com)
++ *
++ */
++
++#undef DEBUG
++#undef DEBUGDATA
++#undef DEBUGCCW
++
++#include <linux/sysfs.h>
++#include "ctcm_main.h"
++
++/*
++ * sysfs attributes
++ */
++
++static ssize_t ctcm_buffer_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct ctcm_priv *priv = dev_get_drvdata(dev);
++
++ if (!priv)
++ return -ENODEV;
++ return sprintf(buf, "%d\n", priv->buffer_size);
++}
++
++static ssize_t ctcm_buffer_write(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct net_device *ndev;
++ int bs1;
++ struct ctcm_priv *priv = dev_get_drvdata(dev);
++
++ if (!(priv && priv->channel[READ] &&
++ (ndev = priv->channel[READ]->netdev))) {
++ CTCM_DBF_TEXT(SETUP, CTC_DBF_ERROR, "bfnondev");
++ return -ENODEV;
++ }
++
++ sscanf(buf, "%u", &bs1);
++ if (bs1 > CTCM_BUFSIZE_LIMIT)
++ goto einval;
++ if (bs1 < (576 + LL_HEADER_LENGTH + 2))
++ goto einval;
++ priv->buffer_size = bs1; /* just to overwrite the default */
++
++ if ((ndev->flags & IFF_RUNNING) &&
++ (bs1 < (ndev->mtu + LL_HEADER_LENGTH + 2)))
++ goto einval;
++
++ priv->channel[READ]->max_bufsize = bs1;
++ priv->channel[WRITE]->max_bufsize = bs1;
++ if (!(ndev->flags & IFF_RUNNING))
++ ndev->mtu = bs1 - LL_HEADER_LENGTH - 2;
++ priv->channel[READ]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
++ priv->channel[WRITE]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
++
++ CTCM_DBF_DEV(SETUP, ndev, buf);
++ return count;
++
++einval:
++ CTCM_DBF_DEV(SETUP, ndev, "buff_err");
++ return -EINVAL;
++}
++
++static void ctcm_print_statistics(struct ctcm_priv *priv)
++{
++ char *sbuf;
++ char *p;
++
++ if (!priv)
++ return;
++ sbuf = kmalloc(2048, GFP_KERNEL);
++ if (sbuf == NULL)
++ return;
++ p = sbuf;
++
++ p += sprintf(p, " Device FSM state: %s\n",
++ fsm_getstate_str(priv->fsm));
++ p += sprintf(p, " RX channel FSM state: %s\n",
++ fsm_getstate_str(priv->channel[READ]->fsm));
++ p += sprintf(p, " TX channel FSM state: %s\n",
++ fsm_getstate_str(priv->channel[WRITE]->fsm));
++ p += sprintf(p, " Max. TX buffer used: %ld\n",
++ priv->channel[WRITE]->prof.maxmulti);
++ p += sprintf(p, " Max. chained SKBs: %ld\n",
++ priv->channel[WRITE]->prof.maxcqueue);
++ p += sprintf(p, " TX single write ops: %ld\n",
++ priv->channel[WRITE]->prof.doios_single);
++ p += sprintf(p, " TX multi write ops: %ld\n",
++ priv->channel[WRITE]->prof.doios_multi);
++ p += sprintf(p, " Netto bytes written: %ld\n",
++ priv->channel[WRITE]->prof.txlen);
++ p += sprintf(p, " Max. TX IO-time: %ld\n",
++ priv->channel[WRITE]->prof.tx_time);
++
++ printk(KERN_INFO "Statistics for %s:\n%s",
++ priv->channel[WRITE]->netdev->name, sbuf);
++ kfree(sbuf);
++ return;
++}
++
++static ssize_t stats_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct ctcm_priv *priv = dev_get_drvdata(dev);
++ if (!priv)
++ return -ENODEV;
++ ctcm_print_statistics(priv);
++ return sprintf(buf, "0\n");
++}
++
++static ssize_t stats_write(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct ctcm_priv *priv = dev_get_drvdata(dev);
++ if (!priv)
++ return -ENODEV;
++ /* Reset statistics */
++ memset(&priv->channel[WRITE]->prof, 0,
++ sizeof(priv->channel[WRITE]->prof));
++ return count;
++}
++
++static ssize_t ctcm_proto_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct ctcm_priv *priv = dev_get_drvdata(dev);
++ if (!priv)
++ return -ENODEV;
++
++ return sprintf(buf, "%d\n", priv->protocol);
++}
++
++static ssize_t ctcm_proto_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ int value;
++ struct ctcm_priv *priv = dev_get_drvdata(dev);
++
++ if (!priv)
++ return -ENODEV;
++ sscanf(buf, "%u", &value);
++ if (!((value == CTCM_PROTO_S390) ||
++ (value == CTCM_PROTO_LINUX) ||
++ (value == CTCM_PROTO_MPC) ||
++ (value == CTCM_PROTO_OS390)))
++ return -EINVAL;
++ priv->protocol = value;
++ CTCM_DBF_DEV(SETUP, dev, buf);
++
++ return count;
++}
++
++static ssize_t ctcm_type_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct ccwgroup_device *cgdev;
++
++ cgdev = to_ccwgroupdev(dev);
++ if (!cgdev)
++ return -ENODEV;
++
++ return sprintf(buf, "%s\n",
++ cu3088_type[cgdev->cdev[0]->id.driver_info]);
++}
++
++static DEVICE_ATTR(buffer, 0644, ctcm_buffer_show, ctcm_buffer_write);
++static DEVICE_ATTR(protocol, 0644, ctcm_proto_show, ctcm_proto_store);
++static DEVICE_ATTR(type, 0444, ctcm_type_show, NULL);
++static DEVICE_ATTR(stats, 0644, stats_show, stats_write);
++
++static struct attribute *ctcm_attr[] = {
++ &dev_attr_protocol.attr,
++ &dev_attr_type.attr,
++ &dev_attr_buffer.attr,
++ NULL,
++};
++
++static struct attribute_group ctcm_attr_group = {
++ .attrs = ctcm_attr,
++};
++
++int ctcm_add_attributes(struct device *dev)
++{
++ int rc;
++
++ rc = device_create_file(dev, &dev_attr_stats);
++
++ return rc;
++}
++
++void ctcm_remove_attributes(struct device *dev)
++{
++ device_remove_file(dev, &dev_attr_stats);
++}
++
++int ctcm_add_files(struct device *dev)
++{
++ return sysfs_create_group(&dev->kobj, &ctcm_attr_group);
++}
++
++void ctcm_remove_files(struct device *dev)
++{
++ sysfs_remove_group(&dev->kobj, &ctcm_attr_group);
++}
++
+diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
+deleted file mode 100644
+index 77a5031..0000000
+--- a/drivers/s390/net/ctcmain.c
++++ /dev/null
+@@ -1,3062 +0,0 @@
+-/*
+- * CTC / ESCON network driver
+- *
+- * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
+- * Author(s): Fritz Elfert (elfert at de.ibm.com, felfert at millenux.com)
+- * Fixes by : Jochen Röhrig (roehrig at de.ibm.com)
+- * Arnaldo Carvalho de Melo <acme at conectiva.com.br>
+- Peter Tiedemann (ptiedem at de.ibm.com)
+- * Driver Model stuff by : Cornelia Huck <cornelia.huck at de.ibm.com>
+- *
+- * Documentation used:
+- * - Principles of Operation (IBM doc#: SA22-7201-06)
+- * - Common IO/-Device Commands and Self Description (IBM doc#: SA22-7204-02)
+- * - Common IO/-Device Commands and Self Description (IBM doc#: SN22-5535)
+- * - ESCON Channel-to-Channel Adapter (IBM doc#: SA22-7203-00)
+- * - ESCON I/O Interface (IBM doc#: SA22-7202-029
+- *
+- * and the source of the original CTC driver by:
+- * Dieter Wellerdiek (wel at de.ibm.com)
+- * Martin Schwidefsky (schwidefsky at de.ibm.com)
+- * Denis Joseph Barrow (djbarrow at de.ibm.com,barrow_dj at yahoo.com)
+- * Jochen Röhrig (roehrig at de.ibm.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, or (at your option)
+- * any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- *
+- */
+-#undef DEBUG
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/kernel.h>
+-#include <linux/slab.h>
+-#include <linux/errno.h>
+-#include <linux/types.h>
+-#include <linux/interrupt.h>
+-#include <linux/timer.h>
+-#include <linux/bitops.h>
+-
+-#include <linux/signal.h>
+-#include <linux/string.h>
+-
+-#include <linux/ip.h>
+-#include <linux/if_arp.h>
+-#include <linux/tcp.h>
+-#include <linux/skbuff.h>
+-#include <linux/ctype.h>
+-#include <net/dst.h>
+-
+-#include <asm/io.h>
+-#include <asm/ccwdev.h>
+-#include <asm/ccwgroup.h>
+-#include <asm/uaccess.h>
+-
+-#include <asm/idals.h>
+-
+-#include "fsm.h"
+-#include "cu3088.h"
+-
+-#include "ctcdbug.h"
+-#include "ctcmain.h"
+-
+-MODULE_AUTHOR("(C) 2000 IBM Corp. by Fritz Elfert (felfert at millenux.com)");
+-MODULE_DESCRIPTION("Linux for S/390 CTC/Escon Driver");
+-MODULE_LICENSE("GPL");
+-/**
+- * States of the interface statemachine.
+- */
+-enum dev_states {
+- DEV_STATE_STOPPED,
+- DEV_STATE_STARTWAIT_RXTX,
+- DEV_STATE_STARTWAIT_RX,
+- DEV_STATE_STARTWAIT_TX,
+- DEV_STATE_STOPWAIT_RXTX,
+- DEV_STATE_STOPWAIT_RX,
+- DEV_STATE_STOPWAIT_TX,
+- DEV_STATE_RUNNING,
+- /**
+- * MUST be always the last element!!
+- */
+- CTC_NR_DEV_STATES
+-};
+-
+-static const char *dev_state_names[] = {
+- "Stopped",
+- "StartWait RXTX",
+- "StartWait RX",
+- "StartWait TX",
+- "StopWait RXTX",
+- "StopWait RX",
+- "StopWait TX",
+- "Running",
+-};
+-
+-/**
+- * Events of the interface statemachine.
+- */
+-enum dev_events {
+- DEV_EVENT_START,
+- DEV_EVENT_STOP,
+- DEV_EVENT_RXUP,
+- DEV_EVENT_TXUP,
+- DEV_EVENT_RXDOWN,
+- DEV_EVENT_TXDOWN,
+- DEV_EVENT_RESTART,
+- /**
+- * MUST be always the last element!!
+- */
+- CTC_NR_DEV_EVENTS
+-};
+-
+-static const char *dev_event_names[] = {
+- "Start",
+- "Stop",
+- "RX up",
+- "TX up",
+- "RX down",
+- "TX down",
+- "Restart",
+-};
+-
+-/**
+- * Events of the channel statemachine
+- */
+-enum ch_events {
+- /**
+- * Events, representing return code of
+- * I/O operations (ccw_device_start, ccw_device_halt et al.)
+- */
+- CH_EVENT_IO_SUCCESS,
+- CH_EVENT_IO_EBUSY,
+- CH_EVENT_IO_ENODEV,
+- CH_EVENT_IO_EIO,
+- CH_EVENT_IO_UNKNOWN,
+-
+- CH_EVENT_ATTNBUSY,
+- CH_EVENT_ATTN,
+- CH_EVENT_BUSY,
+-
+- /**
+- * Events, representing unit-check
+- */
+- CH_EVENT_UC_RCRESET,
+- CH_EVENT_UC_RSRESET,
+- CH_EVENT_UC_TXTIMEOUT,
+- CH_EVENT_UC_TXPARITY,
+- CH_EVENT_UC_HWFAIL,
+- CH_EVENT_UC_RXPARITY,
+- CH_EVENT_UC_ZERO,
+- CH_EVENT_UC_UNKNOWN,
+-
+- /**
+- * Events, representing subchannel-check
+- */
+- CH_EVENT_SC_UNKNOWN,
+-
+- /**
+- * Events, representing machine checks
+- */
+- CH_EVENT_MC_FAIL,
+- CH_EVENT_MC_GOOD,
+-
+- /**
+- * Event, representing normal IRQ
+- */
+- CH_EVENT_IRQ,
+- CH_EVENT_FINSTAT,
+-
+- /**
+- * Event, representing timer expiry.
+- */
+- CH_EVENT_TIMER,
+-
+- /**
+- * Events, representing commands from upper levels.
+- */
+- CH_EVENT_START,
+- CH_EVENT_STOP,
+-
+- /**
+- * MUST be always the last element!!
+- */
+- NR_CH_EVENTS,
+-};
+-
+-/**
+- * States of the channel statemachine.
+- */
+-enum ch_states {
+- /**
+- * Channel not assigned to any device,
+- * initial state, direction invalid
+- */
+- CH_STATE_IDLE,
+-
+- /**
+- * Channel assigned but not operating
+- */
+- CH_STATE_STOPPED,
+- CH_STATE_STARTWAIT,
+- CH_STATE_STARTRETRY,
+- CH_STATE_SETUPWAIT,
+- CH_STATE_RXINIT,
+- CH_STATE_TXINIT,
+- CH_STATE_RX,
+- CH_STATE_TX,
+- CH_STATE_RXIDLE,
+- CH_STATE_TXIDLE,
+- CH_STATE_RXERR,
+- CH_STATE_TXERR,
+- CH_STATE_TERM,
+- CH_STATE_DTERM,
+- CH_STATE_NOTOP,
+-
+- /**
+- * MUST be always the last element!!
+- */
+- NR_CH_STATES,
+-};
+-
+-static int loglevel = CTC_LOGLEVEL_DEFAULT;
+-
+-/**
+- * Linked list of all detected channels.
+- */
+-static struct channel *channels = NULL;
+-
+-/**
+- * Print Banner.
+- */
+-static void
+-print_banner(void)
+-{
+- static int printed = 0;
+-
+- if (printed)
+- return;
+-
+- printk(KERN_INFO "CTC driver initialized\n");
+- printed = 1;
+-}
+-
+-/**
+- * Return type of a detected device.
+- */
+-static enum channel_types
+-get_channel_type(struct ccw_device_id *id)
+-{
+- enum channel_types type = (enum channel_types) id->driver_info;
+-
+- if (type == channel_type_ficon)
+- type = channel_type_escon;
+-
+- return type;
+-}
+-
+-static const char *ch_event_names[] = {
+- "ccw_device success",
+- "ccw_device busy",
+- "ccw_device enodev",
+- "ccw_device ioerr",
+- "ccw_device unknown",
+-
+- "Status ATTN & BUSY",
+- "Status ATTN",
+- "Status BUSY",
+-
+- "Unit check remote reset",
+- "Unit check remote system reset",
+- "Unit check TX timeout",
+- "Unit check TX parity",
+- "Unit check Hardware failure",
+- "Unit check RX parity",
+- "Unit check ZERO",
+- "Unit check Unknown",
+-
+- "SubChannel check Unknown",
+-
+- "Machine check failure",
+- "Machine check operational",
+-
+- "IRQ normal",
+- "IRQ final",
+-
+- "Timer",
+-
+- "Start",
+- "Stop",
+-};
+-
+-static const char *ch_state_names[] = {
+- "Idle",
+- "Stopped",
+- "StartWait",
+- "StartRetry",
+- "SetupWait",
+- "RX init",
+- "TX init",
+- "RX",
+- "TX",
+- "RX idle",
+- "TX idle",
+- "RX error",
+- "TX error",
+- "Terminating",
+- "Restarting",
+- "Not operational",
+-};
+-
+-#ifdef DEBUG
+-/**
+- * Dump header and first 16 bytes of an sk_buff for debugging purposes.
+- *
+- * @param skb The sk_buff to dump.
+- * @param offset Offset relative to skb-data, where to start the dump.
+- */
+-static void
+-ctc_dump_skb(struct sk_buff *skb, int offset)
+-{
+- unsigned char *p = skb->data;
+- __u16 bl;
+- struct ll_header *header;
+- int i;
+-
+- if (!(loglevel & CTC_LOGLEVEL_DEBUG))
+- return;
+- p += offset;
+- bl = *((__u16 *) p);
+- p += 2;
+- header = (struct ll_header *) p;
+- p -= 2;
+-
+- printk(KERN_DEBUG "dump:\n");
+- printk(KERN_DEBUG "blocklen=%d %04x\n", bl, bl);
+-
+- printk(KERN_DEBUG "h->length=%d %04x\n", header->length,
+- header->length);
+- printk(KERN_DEBUG "h->type=%04x\n", header->type);
+- printk(KERN_DEBUG "h->unused=%04x\n", header->unused);
+- if (bl > 16)
+- bl = 16;
+- printk(KERN_DEBUG "data: ");
+- for (i = 0; i < bl; i++)
+- printk("%02x%s", *p++, (i % 16) ? " " : "\n<7>");
+- printk("\n");
+-}
+-#else
+-static inline void
+-ctc_dump_skb(struct sk_buff *skb, int offset)
+-{
+-}
+-#endif
+-
+-/**
+- * Unpack a just received skb and hand it over to
+- * upper layers.
+- *
+- * @param ch The channel where this skb has been received.
+- * @param pskb The received skb.
+- */
+-static void
+-ctc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
+-{
+- struct net_device *dev = ch->netdev;
+- struct ctc_priv *privptr = (struct ctc_priv *) dev->priv;
+- __u16 len = *((__u16 *) pskb->data);
+-
+- DBF_TEXT(trace, 4, __FUNCTION__);
+- skb_put(pskb, 2 + LL_HEADER_LENGTH);
+- skb_pull(pskb, 2);
+- pskb->dev = dev;
+- pskb->ip_summed = CHECKSUM_UNNECESSARY;
+- while (len > 0) {
+- struct sk_buff *skb;
+- struct ll_header *header = (struct ll_header *) pskb->data;
+-
+- skb_pull(pskb, LL_HEADER_LENGTH);
+- if ((ch->protocol == CTC_PROTO_S390) &&
+- (header->type != ETH_P_IP)) {
+-
+-#ifndef DEBUG
+- if (!(ch->logflags & LOG_FLAG_ILLEGALPKT)) {
+-#endif
+- /**
+- * Check packet type only if we stick strictly
+- * to S/390's protocol of OS390. This only
+- * supports IP. Otherwise allow any packet
+- * type.
+- */
+- ctc_pr_warn(
+- "%s Illegal packet type 0x%04x received, dropping\n",
+- dev->name, header->type);
+- ch->logflags |= LOG_FLAG_ILLEGALPKT;
+-#ifndef DEBUG
+- }
+-#endif
+-#ifdef DEBUG
+- ctc_dump_skb(pskb, -6);
+-#endif
+- privptr->stats.rx_dropped++;
+- privptr->stats.rx_frame_errors++;
+- return;
+- }
+- pskb->protocol = ntohs(header->type);
+- if (header->length <= LL_HEADER_LENGTH) {
+-#ifndef DEBUG
+- if (!(ch->logflags & LOG_FLAG_ILLEGALSIZE)) {
+-#endif
+- ctc_pr_warn(
+- "%s Illegal packet size %d "
+- "received (MTU=%d blocklen=%d), "
+- "dropping\n", dev->name, header->length,
+- dev->mtu, len);
+- ch->logflags |= LOG_FLAG_ILLEGALSIZE;
+-#ifndef DEBUG
+- }
+-#endif
+-#ifdef DEBUG
+- ctc_dump_skb(pskb, -6);
+-#endif
+- privptr->stats.rx_dropped++;
+- privptr->stats.rx_length_errors++;
+- return;
+- }
+- header->length -= LL_HEADER_LENGTH;
+- len -= LL_HEADER_LENGTH;
+- if ((header->length > skb_tailroom(pskb)) ||
+- (header->length > len)) {
+-#ifndef DEBUG
+- if (!(ch->logflags & LOG_FLAG_OVERRUN)) {
+-#endif
+- ctc_pr_warn(
+- "%s Illegal packet size %d "
+- "(beyond the end of received data), "
+- "dropping\n", dev->name, header->length);
+- ch->logflags |= LOG_FLAG_OVERRUN;
+-#ifndef DEBUG
+- }
+-#endif
+-#ifdef DEBUG
+- ctc_dump_skb(pskb, -6);
+-#endif
+- privptr->stats.rx_dropped++;
+- privptr->stats.rx_length_errors++;
+- return;
+- }
+- skb_put(pskb, header->length);
+- skb_reset_mac_header(pskb);
+- len -= header->length;
+- skb = dev_alloc_skb(pskb->len);
+- if (!skb) {
+-#ifndef DEBUG
+- if (!(ch->logflags & LOG_FLAG_NOMEM)) {
+-#endif
+- ctc_pr_warn(
+- "%s Out of memory in ctc_unpack_skb\n",
+- dev->name);
+- ch->logflags |= LOG_FLAG_NOMEM;
+-#ifndef DEBUG
+- }
+-#endif
+- privptr->stats.rx_dropped++;
+- return;
+- }
+- skb_copy_from_linear_data(pskb, skb_put(skb, pskb->len),
+- pskb->len);
+- skb_reset_mac_header(skb);
+- skb->dev = pskb->dev;
+- skb->protocol = pskb->protocol;
+- pskb->ip_summed = CHECKSUM_UNNECESSARY;
+- /**
+- * reset logflags
+- */
+- ch->logflags = 0;
+- privptr->stats.rx_packets++;
+- privptr->stats.rx_bytes += skb->len;
+- netif_rx_ni(skb);
+- dev->last_rx = jiffies;
+- if (len > 0) {
+- skb_pull(pskb, header->length);
+- if (skb_tailroom(pskb) < LL_HEADER_LENGTH) {
+-#ifndef DEBUG
+- if (!(ch->logflags & LOG_FLAG_OVERRUN)) {
+-#endif
+- ctc_pr_warn(
+- "%s Overrun in ctc_unpack_skb\n",
+- dev->name);
+- ch->logflags |= LOG_FLAG_OVERRUN;
+-#ifndef DEBUG
+- }
+-#endif
+- return;
+- }
+- skb_put(pskb, LL_HEADER_LENGTH);
+- }
+- }
+-}
+-
+-/**
+- * Check return code of a preceeding ccw_device call, halt_IO etc...
+- *
+- * @param ch The channel, the error belongs to.
+- * @param return_code The error code to inspect.
+- */
+-static void
+-ccw_check_return_code(struct channel *ch, int return_code, char *msg)
+-{
+- DBF_TEXT(trace, 5, __FUNCTION__);
+- switch (return_code) {
+- case 0:
+- fsm_event(ch->fsm, CH_EVENT_IO_SUCCESS, ch);
+- break;
+- case -EBUSY:
+- ctc_pr_warn("%s (%s): Busy !\n", ch->id, msg);
+- fsm_event(ch->fsm, CH_EVENT_IO_EBUSY, ch);
+- break;
+- case -ENODEV:
+- ctc_pr_emerg("%s (%s): Invalid device called for IO\n",
+- ch->id, msg);
+- fsm_event(ch->fsm, CH_EVENT_IO_ENODEV, ch);
+- break;
+- case -EIO:
+- ctc_pr_emerg("%s (%s): Status pending... \n",
+- ch->id, msg);
+- fsm_event(ch->fsm, CH_EVENT_IO_EIO, ch);
+- break;
+- default:
+- ctc_pr_emerg("%s (%s): Unknown error in do_IO %04x\n",
+- ch->id, msg, return_code);
+- fsm_event(ch->fsm, CH_EVENT_IO_UNKNOWN, ch);
+- }
+-}
+-
+-/**
+- * Check sense of a unit check.
+- *
+- * @param ch The channel, the sense code belongs to.
+- * @param sense The sense code to inspect.
+- */
+-static void
+-ccw_unit_check(struct channel *ch, unsigned char sense)
+-{
+- DBF_TEXT(trace, 5, __FUNCTION__);
+- if (sense & SNS0_INTERVENTION_REQ) {
+- if (sense & 0x01) {
+- ctc_pr_debug("%s: Interface disc. or Sel. reset "
+- "(remote)\n", ch->id);
+- fsm_event(ch->fsm, CH_EVENT_UC_RCRESET, ch);
+- } else {
+- ctc_pr_debug("%s: System reset (remote)\n", ch->id);
+- fsm_event(ch->fsm, CH_EVENT_UC_RSRESET, ch);
+- }
+- } else if (sense & SNS0_EQUIPMENT_CHECK) {
+- if (sense & SNS0_BUS_OUT_CHECK) {
+- ctc_pr_warn("%s: Hardware malfunction (remote)\n",
+- ch->id);
+- fsm_event(ch->fsm, CH_EVENT_UC_HWFAIL, ch);
+- } else {
+- ctc_pr_warn("%s: Read-data parity error (remote)\n",
+- ch->id);
+- fsm_event(ch->fsm, CH_EVENT_UC_RXPARITY, ch);
+- }
+- } else if (sense & SNS0_BUS_OUT_CHECK) {
+- if (sense & 0x04) {
+- ctc_pr_warn("%s: Data-streaming timeout)\n", ch->id);
+- fsm_event(ch->fsm, CH_EVENT_UC_TXTIMEOUT, ch);
+- } else {
+- ctc_pr_warn("%s: Data-transfer parity error\n", ch->id);
+- fsm_event(ch->fsm, CH_EVENT_UC_TXPARITY, ch);
+- }
+- } else if (sense & SNS0_CMD_REJECT) {
+- ctc_pr_warn("%s: Command reject\n", ch->id);
+- } else if (sense == 0) {
+- ctc_pr_debug("%s: Unit check ZERO\n", ch->id);
+- fsm_event(ch->fsm, CH_EVENT_UC_ZERO, ch);
+- } else {
+- ctc_pr_warn("%s: Unit Check with sense code: %02x\n",
+- ch->id, sense);
+- fsm_event(ch->fsm, CH_EVENT_UC_UNKNOWN, ch);
+- }
+-}
+-
+-static void
+-ctc_purge_skb_queue(struct sk_buff_head *q)
+-{
+- struct sk_buff *skb;
+-
+- DBF_TEXT(trace, 5, __FUNCTION__);
+-
+- while ((skb = skb_dequeue(q))) {
+- atomic_dec(&skb->users);
+- dev_kfree_skb_irq(skb);
+- }
+-}
+-
+-static int
+-ctc_checkalloc_buffer(struct channel *ch, int warn)
+-{
+- DBF_TEXT(trace, 5, __FUNCTION__);
+- if ((ch->trans_skb == NULL) ||
+- (ch->flags & CHANNEL_FLAGS_BUFSIZE_CHANGED)) {
+- if (ch->trans_skb != NULL)
+- dev_kfree_skb(ch->trans_skb);
+- clear_normalized_cda(&ch->ccw[1]);
+- ch->trans_skb = __dev_alloc_skb(ch->max_bufsize,
+- GFP_ATOMIC | GFP_DMA);
+- if (ch->trans_skb == NULL) {
+- if (warn)
+- ctc_pr_warn(
+- "%s: Couldn't alloc %s trans_skb\n",
+- ch->id,
+- (CHANNEL_DIRECTION(ch->flags) == READ) ?
+- "RX" : "TX");
+- return -ENOMEM;
+- }
+- ch->ccw[1].count = ch->max_bufsize;
+- if (set_normalized_cda(&ch->ccw[1], ch->trans_skb->data)) {
+- dev_kfree_skb(ch->trans_skb);
+- ch->trans_skb = NULL;
+- if (warn)
+- ctc_pr_warn(
+- "%s: set_normalized_cda for %s "
+- "trans_skb failed, dropping packets\n",
+- ch->id,
+- (CHANNEL_DIRECTION(ch->flags) == READ) ?
+- "RX" : "TX");
+- return -ENOMEM;
+- }
+- ch->ccw[1].count = 0;
+- ch->trans_skb_data = ch->trans_skb->data;
+- ch->flags &= ~CHANNEL_FLAGS_BUFSIZE_CHANGED;
+- }
+- return 0;
+-}
+-
+-/**
+- * Dummy NOP action for statemachines
+- */
+-static void
+-fsm_action_nop(fsm_instance * fi, int event, void *arg)
+-{
+-}
+-
+-/**
+- * Actions for channel - statemachines.
+- *****************************************************************************/
+-
+-/**
+- * Normal data has been send. Free the corresponding
+- * skb (it's in io_queue), reset dev->tbusy and
+- * revert to idle state.
+- *
+- * @param fi An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_txdone(fsm_instance * fi, int event, void *arg)
+-{
+- struct channel *ch = (struct channel *) arg;
+- struct net_device *dev = ch->netdev;
+- struct ctc_priv *privptr = dev->priv;
+- struct sk_buff *skb;
+- int first = 1;
+- int i;
+- unsigned long duration;
+- struct timespec done_stamp = current_kernel_time();
+-
+- DBF_TEXT(trace, 4, __FUNCTION__);
+-
+- duration =
+- (done_stamp.tv_sec - ch->prof.send_stamp.tv_sec) * 1000000 +
+- (done_stamp.tv_nsec - ch->prof.send_stamp.tv_nsec) / 1000;
+- if (duration > ch->prof.tx_time)
+- ch->prof.tx_time = duration;
+-
+- if (ch->irb->scsw.count != 0)
+- ctc_pr_debug("%s: TX not complete, remaining %d bytes\n",
+- dev->name, ch->irb->scsw.count);
+- fsm_deltimer(&ch->timer);
+- while ((skb = skb_dequeue(&ch->io_queue))) {
+- privptr->stats.tx_packets++;
+- privptr->stats.tx_bytes += skb->len - LL_HEADER_LENGTH;
+- if (first) {
+- privptr->stats.tx_bytes += 2;
+- first = 0;
+- }
+- atomic_dec(&skb->users);
+- dev_kfree_skb_irq(skb);
+- }
+- spin_lock(&ch->collect_lock);
+- clear_normalized_cda(&ch->ccw[4]);
+- if (ch->collect_len > 0) {
+- int rc;
+-
+- if (ctc_checkalloc_buffer(ch, 1)) {
+- spin_unlock(&ch->collect_lock);
+- return;
+- }
+- ch->trans_skb->data = ch->trans_skb_data;
+- skb_reset_tail_pointer(ch->trans_skb);
+- ch->trans_skb->len = 0;
+- if (ch->prof.maxmulti < (ch->collect_len + 2))
+- ch->prof.maxmulti = ch->collect_len + 2;
+- if (ch->prof.maxcqueue < skb_queue_len(&ch->collect_queue))
+- ch->prof.maxcqueue = skb_queue_len(&ch->collect_queue);
+- *((__u16 *) skb_put(ch->trans_skb, 2)) = ch->collect_len + 2;
+- i = 0;
+- while ((skb = skb_dequeue(&ch->collect_queue))) {
+- skb_copy_from_linear_data(skb, skb_put(ch->trans_skb,
+- skb->len),
+- skb->len);
+- privptr->stats.tx_packets++;
+- privptr->stats.tx_bytes += skb->len - LL_HEADER_LENGTH;
+- atomic_dec(&skb->users);
+- dev_kfree_skb_irq(skb);
+- i++;
+- }
+- ch->collect_len = 0;
+- spin_unlock(&ch->collect_lock);
+- ch->ccw[1].count = ch->trans_skb->len;
+- fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
+- ch->prof.send_stamp = current_kernel_time();
+- rc = ccw_device_start(ch->cdev, &ch->ccw[0],
+- (unsigned long) ch, 0xff, 0);
+- ch->prof.doios_multi++;
+- if (rc != 0) {
+- privptr->stats.tx_dropped += i;
+- privptr->stats.tx_errors += i;
+- fsm_deltimer(&ch->timer);
+- ccw_check_return_code(ch, rc, "chained TX");
+- }
+- } else {
+- spin_unlock(&ch->collect_lock);
+- fsm_newstate(fi, CH_STATE_TXIDLE);
+- }
+- ctc_clear_busy(dev);
+-}
+-
+-/**
+- * Initial data is sent.
+- * Notify device statemachine that we are up and
+- * running.
+- *
+- * @param fi An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_txidle(fsm_instance * fi, int event, void *arg)
+-{
+- struct channel *ch = (struct channel *) arg;
+-
+- DBF_TEXT(trace, 4, __FUNCTION__);
+- fsm_deltimer(&ch->timer);
+- fsm_newstate(fi, CH_STATE_TXIDLE);
+- fsm_event(((struct ctc_priv *) ch->netdev->priv)->fsm, DEV_EVENT_TXUP,
+- ch->netdev);
+-}
+-
+-/**
+- * Got normal data, check for sanity, queue it up, allocate new buffer
+- * trigger bottom half, and initiate next read.
+- *
+- * @param fi An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_rx(fsm_instance * fi, int event, void *arg)
+-{
+- struct channel *ch = (struct channel *) arg;
+- struct net_device *dev = ch->netdev;
+- struct ctc_priv *privptr = dev->priv;
+- int len = ch->max_bufsize - ch->irb->scsw.count;
+- struct sk_buff *skb = ch->trans_skb;
+- __u16 block_len = *((__u16 *) skb->data);
+- int check_len;
+- int rc;
+-
+- DBF_TEXT(trace, 4, __FUNCTION__);
+- fsm_deltimer(&ch->timer);
+- if (len < 8) {
+- ctc_pr_debug("%s: got packet with length %d < 8\n",
+- dev->name, len);
+- privptr->stats.rx_dropped++;
+- privptr->stats.rx_length_errors++;
+- goto again;
+- }
+- if (len > ch->max_bufsize) {
+- ctc_pr_debug("%s: got packet with length %d > %d\n",
+- dev->name, len, ch->max_bufsize);
+- privptr->stats.rx_dropped++;
+- privptr->stats.rx_length_errors++;
+- goto again;
+- }
+-
+- /**
+- * VM TCP seems to have a bug sending 2 trailing bytes of garbage.
+- */
+- switch (ch->protocol) {
+- case CTC_PROTO_S390:
+- case CTC_PROTO_OS390:
+- check_len = block_len + 2;
+- break;
+- default:
+- check_len = block_len;
+- break;
+- }
+- if ((len < block_len) || (len > check_len)) {
+- ctc_pr_debug("%s: got block length %d != rx length %d\n",
+- dev->name, block_len, len);
+-#ifdef DEBUG
+- ctc_dump_skb(skb, 0);
+-#endif
+- *((__u16 *) skb->data) = len;
+- privptr->stats.rx_dropped++;
+- privptr->stats.rx_length_errors++;
+- goto again;
+- }
+- block_len -= 2;
+- if (block_len > 0) {
+- *((__u16 *) skb->data) = block_len;
+- ctc_unpack_skb(ch, skb);
+- }
+- again:
+- skb->data = ch->trans_skb_data;
+- skb_reset_tail_pointer(skb);
+- skb->len = 0;
+- if (ctc_checkalloc_buffer(ch, 1))
+- return;
+- ch->ccw[1].count = ch->max_bufsize;
+- rc = ccw_device_start(ch->cdev, &ch->ccw[0], (unsigned long) ch, 0xff, 0);
+- if (rc != 0)
+- ccw_check_return_code(ch, rc, "normal RX");
+-}
+-
+-static void ch_action_rxidle(fsm_instance * fi, int event, void *arg);
+-
+-/**
+- * Initialize connection by sending a __u16 of value 0.
+- *
+- * @param fi An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_firstio(fsm_instance * fi, int event, void *arg)
+-{
+- struct channel *ch = (struct channel *) arg;
+- int rc;
+-
+- DBF_TEXT(trace, 4, __FUNCTION__);
+-
+- if (fsm_getstate(fi) == CH_STATE_TXIDLE)
+- ctc_pr_debug("%s: remote side issued READ?, init ...\n", ch->id);
+- fsm_deltimer(&ch->timer);
+- if (ctc_checkalloc_buffer(ch, 1))
+- return;
+- if ((fsm_getstate(fi) == CH_STATE_SETUPWAIT) &&
+- (ch->protocol == CTC_PROTO_OS390)) {
+- /* OS/390 resp. z/OS */
+- if (CHANNEL_DIRECTION(ch->flags) == READ) {
+- *((__u16 *) ch->trans_skb->data) = CTC_INITIAL_BLOCKLEN;
+- fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC,
+- CH_EVENT_TIMER, ch);
+- ch_action_rxidle(fi, event, arg);
+- } else {
+- struct net_device *dev = ch->netdev;
+- fsm_newstate(fi, CH_STATE_TXIDLE);
+- fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+- DEV_EVENT_TXUP, dev);
+- }
+- return;
+- }
+-
+- /**
+- * Don't setup a timer for receiving the initial RX frame
+- * if in compatibility mode, since VM TCP delays the initial
+- * frame until it has some data to send.
+- */
+- if ((CHANNEL_DIRECTION(ch->flags) == WRITE) ||
+- (ch->protocol != CTC_PROTO_S390))
+- fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
+-
+- *((__u16 *) ch->trans_skb->data) = CTC_INITIAL_BLOCKLEN;
+- ch->ccw[1].count = 2; /* Transfer only length */
+-
+- fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == READ)
+- ? CH_STATE_RXINIT : CH_STATE_TXINIT);
+- rc = ccw_device_start(ch->cdev, &ch->ccw[0], (unsigned long) ch, 0xff, 0);
+- if (rc != 0) {
+- fsm_deltimer(&ch->timer);
+- fsm_newstate(fi, CH_STATE_SETUPWAIT);
+- ccw_check_return_code(ch, rc, "init IO");
+- }
+- /**
+- * If in compatibility mode since we don't setup a timer, we
+- * also signal RX channel up immediately. This enables us
+- * to send packets early which in turn usually triggers some
+- * reply from VM TCP which brings up the RX channel to it's
+- * final state.
+- */
+- if ((CHANNEL_DIRECTION(ch->flags) == READ) &&
+- (ch->protocol == CTC_PROTO_S390)) {
+- struct net_device *dev = ch->netdev;
+- fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_RXUP,
+- dev);
+- }
+-}
+-
+-/**
+- * Got initial data, check it. If OK,
+- * notify device statemachine that we are up and
+- * running.
+- *
+- * @param fi An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_rxidle(fsm_instance * fi, int event, void *arg)
+-{
+- struct channel *ch = (struct channel *) arg;
+- struct net_device *dev = ch->netdev;
+- __u16 buflen;
+- int rc;
+-
+- DBF_TEXT(trace, 4, __FUNCTION__);
+- fsm_deltimer(&ch->timer);
+- buflen = *((__u16 *) ch->trans_skb->data);
+-#ifdef DEBUG
+- ctc_pr_debug("%s: Initial RX count %d\n", dev->name, buflen);
+-#endif
+- if (buflen >= CTC_INITIAL_BLOCKLEN) {
+- if (ctc_checkalloc_buffer(ch, 1))
+- return;
+- ch->ccw[1].count = ch->max_bufsize;
+- fsm_newstate(fi, CH_STATE_RXIDLE);
+- rc = ccw_device_start(ch->cdev, &ch->ccw[0],
+- (unsigned long) ch, 0xff, 0);
+- if (rc != 0) {
+- fsm_newstate(fi, CH_STATE_RXINIT);
+- ccw_check_return_code(ch, rc, "initial RX");
+- } else
+- fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+- DEV_EVENT_RXUP, dev);
+- } else {
+- ctc_pr_debug("%s: Initial RX count %d not %d\n",
+- dev->name, buflen, CTC_INITIAL_BLOCKLEN);
+- ch_action_firstio(fi, event, arg);
+- }
+-}
+-
+-/**
+- * Set channel into extended mode.
+- *
+- * @param fi An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_setmode(fsm_instance * fi, int event, void *arg)
+-{
+- struct channel *ch = (struct channel *) arg;
+- int rc;
+- unsigned long saveflags;
+-
+- DBF_TEXT(trace, 4, __FUNCTION__);
+- fsm_deltimer(&ch->timer);
+- fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
+- fsm_newstate(fi, CH_STATE_SETUPWAIT);
+- saveflags = 0; /* avoids compiler warning with
+- spin_unlock_irqrestore */
+- if (event == CH_EVENT_TIMER) // only for timer not yet locked
+- spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
+- rc = ccw_device_start(ch->cdev, &ch->ccw[6], (unsigned long) ch, 0xff, 0);
+- if (event == CH_EVENT_TIMER)
+- spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
+- if (rc != 0) {
+- fsm_deltimer(&ch->timer);
+- fsm_newstate(fi, CH_STATE_STARTWAIT);
+- ccw_check_return_code(ch, rc, "set Mode");
+- } else
+- ch->retry = 0;
+-}
+-
+-/**
+- * Setup channel.
+- *
+- * @param fi An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_start(fsm_instance * fi, int event, void *arg)
+-{
+- struct channel *ch = (struct channel *) arg;
+- unsigned long saveflags;
+- int rc;
+- struct net_device *dev;
+-
+- DBF_TEXT(trace, 4, __FUNCTION__);
+- if (ch == NULL) {
+- ctc_pr_warn("ch_action_start ch=NULL\n");
+- return;
+- }
+- if (ch->netdev == NULL) {
+- ctc_pr_warn("ch_action_start dev=NULL, id=%s\n", ch->id);
+- return;
+- }
+- dev = ch->netdev;
+-
+-#ifdef DEBUG
+- ctc_pr_debug("%s: %s channel start\n", dev->name,
+- (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+-#endif
+-
+- if (ch->trans_skb != NULL) {
+- clear_normalized_cda(&ch->ccw[1]);
+- dev_kfree_skb(ch->trans_skb);
+- ch->trans_skb = NULL;
+- }
+- if (CHANNEL_DIRECTION(ch->flags) == READ) {
+- ch->ccw[1].cmd_code = CCW_CMD_READ;
+- ch->ccw[1].flags = CCW_FLAG_SLI;
+- ch->ccw[1].count = 0;
+- } else {
+- ch->ccw[1].cmd_code = CCW_CMD_WRITE;
+- ch->ccw[1].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
+- ch->ccw[1].count = 0;
+- }
+- if (ctc_checkalloc_buffer(ch, 0)) {
+- ctc_pr_notice(
+- "%s: Could not allocate %s trans_skb, delaying "
+- "allocation until first transfer\n",
+- dev->name,
+- (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+- }
+-
+- ch->ccw[0].cmd_code = CCW_CMD_PREPARE;
+- ch->ccw[0].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
+- ch->ccw[0].count = 0;
+- ch->ccw[0].cda = 0;
+- ch->ccw[2].cmd_code = CCW_CMD_NOOP; /* jointed CE + DE */
+- ch->ccw[2].flags = CCW_FLAG_SLI;
+- ch->ccw[2].count = 0;
+- ch->ccw[2].cda = 0;
+- memcpy(&ch->ccw[3], &ch->ccw[0], sizeof (struct ccw1) * 3);
+- ch->ccw[4].cda = 0;
+- ch->ccw[4].flags &= ~CCW_FLAG_IDA;
+-
+- fsm_newstate(fi, CH_STATE_STARTWAIT);
+- fsm_addtimer(&ch->timer, 1000, CH_EVENT_TIMER, ch);
+- spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
+- rc = ccw_device_halt(ch->cdev, (unsigned long) ch);
+- spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
+- if (rc != 0) {
+- if (rc != -EBUSY)
+- fsm_deltimer(&ch->timer);
+- ccw_check_return_code(ch, rc, "initial HaltIO");
+- }
+-#ifdef DEBUG
+- ctc_pr_debug("ctc: %s(): leaving\n", __func__);
+-#endif
+-}
+-
+-/**
+- * Shutdown a channel.
+- *
+- * @param fi An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_haltio(fsm_instance * fi, int event, void *arg)
+-{
+- struct channel *ch = (struct channel *) arg;
+- unsigned long saveflags;
+- int rc;
+- int oldstate;
+-
+- DBF_TEXT(trace, 3, __FUNCTION__);
+- fsm_deltimer(&ch->timer);
+- fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
+- saveflags = 0; /* avoids comp warning with
+- spin_unlock_irqrestore */
+- if (event == CH_EVENT_STOP) // only for STOP not yet locked
+- spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
+- oldstate = fsm_getstate(fi);
+- fsm_newstate(fi, CH_STATE_TERM);
+- rc = ccw_device_halt(ch->cdev, (unsigned long) ch);
+- if (event == CH_EVENT_STOP)
+- spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
+- if (rc != 0) {
+- if (rc != -EBUSY) {
+- fsm_deltimer(&ch->timer);
+- fsm_newstate(fi, oldstate);
+- }
+- ccw_check_return_code(ch, rc, "HaltIO in ch_action_haltio");
+- }
+-}
+-
+-/**
+- * A channel has successfully been halted.
+- * Cleanup it's queue and notify interface statemachine.
+- *
+- * @param fi An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_stopped(fsm_instance * fi, int event, void *arg)
+-{
+- struct channel *ch = (struct channel *) arg;
+- struct net_device *dev = ch->netdev;
+-
+- DBF_TEXT(trace, 3, __FUNCTION__);
+- fsm_deltimer(&ch->timer);
+- fsm_newstate(fi, CH_STATE_STOPPED);
+- if (ch->trans_skb != NULL) {
+- clear_normalized_cda(&ch->ccw[1]);
+- dev_kfree_skb(ch->trans_skb);
+- ch->trans_skb = NULL;
+- }
+- if (CHANNEL_DIRECTION(ch->flags) == READ) {
+- skb_queue_purge(&ch->io_queue);
+- fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+- DEV_EVENT_RXDOWN, dev);
+- } else {
+- ctc_purge_skb_queue(&ch->io_queue);
+- spin_lock(&ch->collect_lock);
+- ctc_purge_skb_queue(&ch->collect_queue);
+- ch->collect_len = 0;
+- spin_unlock(&ch->collect_lock);
+- fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+- DEV_EVENT_TXDOWN, dev);
+- }
+-}
+-
+-/**
+- * A stop command from device statemachine arrived and we are in
+- * not operational mode. Set state to stopped.
+- *
+- * @param fi An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_stop(fsm_instance * fi, int event, void *arg)
+-{
+- fsm_newstate(fi, CH_STATE_STOPPED);
+-}
+-
+-/**
+- * A machine check for no path, not operational status or gone device has
+- * happened.
+- * Cleanup queue and notify interface statemachine.
+- *
+- * @param fi An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_fail(fsm_instance * fi, int event, void *arg)
+-{
+- struct channel *ch = (struct channel *) arg;
+- struct net_device *dev = ch->netdev;
+-
+- DBF_TEXT(trace, 3, __FUNCTION__);
+- fsm_deltimer(&ch->timer);
+- fsm_newstate(fi, CH_STATE_NOTOP);
+- if (CHANNEL_DIRECTION(ch->flags) == READ) {
+- skb_queue_purge(&ch->io_queue);
+- fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+- DEV_EVENT_RXDOWN, dev);
+- } else {
+- ctc_purge_skb_queue(&ch->io_queue);
+- spin_lock(&ch->collect_lock);
+- ctc_purge_skb_queue(&ch->collect_queue);
+- ch->collect_len = 0;
+- spin_unlock(&ch->collect_lock);
+- fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+- DEV_EVENT_TXDOWN, dev);
+- }
+-}
+-
+-/**
+- * Handle error during setup of channel.
+- *
+- * @param fi An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_setuperr(fsm_instance * fi, int event, void *arg)
+-{
+- struct channel *ch = (struct channel *) arg;
+- struct net_device *dev = ch->netdev;
+-
+- DBF_TEXT(setup, 3, __FUNCTION__);
+- /**
+- * Special case: Got UC_RCRESET on setmode.
+- * This means that remote side isn't setup. In this case
+- * simply retry after some 10 secs...
+- */
+- if ((fsm_getstate(fi) == CH_STATE_SETUPWAIT) &&
+- ((event == CH_EVENT_UC_RCRESET) ||
+- (event == CH_EVENT_UC_RSRESET))) {
+- fsm_newstate(fi, CH_STATE_STARTRETRY);
+- fsm_deltimer(&ch->timer);
+- fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
+- if (CHANNEL_DIRECTION(ch->flags) == READ) {
+- int rc = ccw_device_halt(ch->cdev, (unsigned long) ch);
+- if (rc != 0)
+- ccw_check_return_code(
+- ch, rc, "HaltIO in ch_action_setuperr");
+- }
+- return;
+- }
+-
+- ctc_pr_debug("%s: Error %s during %s channel setup state=%s\n",
+- dev->name, ch_event_names[event],
+- (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX",
+- fsm_getstate_str(fi));
+- if (CHANNEL_DIRECTION(ch->flags) == READ) {
+- fsm_newstate(fi, CH_STATE_RXERR);
+- fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+- DEV_EVENT_RXDOWN, dev);
+- } else {
+- fsm_newstate(fi, CH_STATE_TXERR);
+- fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+- DEV_EVENT_TXDOWN, dev);
+- }
+-}
+-
+-/**
+- * Restart a channel after an error.
+- *
+- * @param fi An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_restart(fsm_instance * fi, int event, void *arg)
+-{
+- unsigned long saveflags;
+- int oldstate;
+- int rc;
+-
+- struct channel *ch = (struct channel *) arg;
+- struct net_device *dev = ch->netdev;
+-
+- DBF_TEXT(trace, 3, __FUNCTION__);
+- fsm_deltimer(&ch->timer);
+- ctc_pr_debug("%s: %s channel restart\n", dev->name,
+- (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+- fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
+- oldstate = fsm_getstate(fi);
+- fsm_newstate(fi, CH_STATE_STARTWAIT);
+- saveflags = 0; /* avoids compiler warning with
+- spin_unlock_irqrestore */
+- if (event == CH_EVENT_TIMER) // only for timer not yet locked
+- spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
+- rc = ccw_device_halt(ch->cdev, (unsigned long) ch);
+- if (event == CH_EVENT_TIMER)
+- spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
+- if (rc != 0) {
+- if (rc != -EBUSY) {
+- fsm_deltimer(&ch->timer);
+- fsm_newstate(fi, oldstate);
+- }
+- ccw_check_return_code(ch, rc, "HaltIO in ch_action_restart");
+- }
+-}
+-
+-/**
+- * Handle error during RX initial handshake (exchange of
+- * 0-length block header)
+- *
+- * @param fi An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_rxiniterr(fsm_instance * fi, int event, void *arg)
+-{
+- struct channel *ch = (struct channel *) arg;
+- struct net_device *dev = ch->netdev;
+-
+- DBF_TEXT(setup, 3, __FUNCTION__);
+- if (event == CH_EVENT_TIMER) {
+- fsm_deltimer(&ch->timer);
+- ctc_pr_debug("%s: Timeout during RX init handshake\n", dev->name);
+- if (ch->retry++ < 3)
+- ch_action_restart(fi, event, arg);
+- else {
+- fsm_newstate(fi, CH_STATE_RXERR);
+- fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+- DEV_EVENT_RXDOWN, dev);
+- }
+- } else
+- ctc_pr_warn("%s: Error during RX init handshake\n", dev->name);
+-}
+-
+-/**
+- * Notify device statemachine if we gave up initialization
+- * of RX channel.
+- *
+- * @param fi An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_rxinitfail(fsm_instance * fi, int event, void *arg)
+-{
+- struct channel *ch = (struct channel *) arg;
+- struct net_device *dev = ch->netdev;
+-
+- DBF_TEXT(setup, 3, __FUNCTION__);
+- fsm_newstate(fi, CH_STATE_RXERR);
+- ctc_pr_warn("%s: RX initialization failed\n", dev->name);
+- ctc_pr_warn("%s: RX <-> RX connection detected\n", dev->name);
+- fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_RXDOWN, dev);
+-}
+-
+-/**
+- * Handle RX Unit check remote reset (remote disconnected)
+- *
+- * @param fi An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_rxdisc(fsm_instance * fi, int event, void *arg)
+-{
+- struct channel *ch = (struct channel *) arg;
+- struct channel *ch2;
+- struct net_device *dev = ch->netdev;
+-
+- DBF_TEXT(trace, 3, __FUNCTION__);
+- fsm_deltimer(&ch->timer);
+- ctc_pr_debug("%s: Got remote disconnect, re-initializing ...\n",
+- dev->name);
+-
+- /**
+- * Notify device statemachine
+- */
+- fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_RXDOWN, dev);
+- fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_TXDOWN, dev);
+-
+- fsm_newstate(fi, CH_STATE_DTERM);
+- ch2 = ((struct ctc_priv *) dev->priv)->channel[WRITE];
+- fsm_newstate(ch2->fsm, CH_STATE_DTERM);
+-
+- ccw_device_halt(ch->cdev, (unsigned long) ch);
+- ccw_device_halt(ch2->cdev, (unsigned long) ch2);
+-}
+-
+-/**
+- * Handle error during TX channel initialization.
+- *
+- * @param fi An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_txiniterr(fsm_instance * fi, int event, void *arg)
+-{
+- struct channel *ch = (struct channel *) arg;
+- struct net_device *dev = ch->netdev;
+-
+- DBF_TEXT(setup, 2, __FUNCTION__);
+- if (event == CH_EVENT_TIMER) {
+- fsm_deltimer(&ch->timer);
+- ctc_pr_debug("%s: Timeout during TX init handshake\n", dev->name);
+- if (ch->retry++ < 3)
+- ch_action_restart(fi, event, arg);
+- else {
+- fsm_newstate(fi, CH_STATE_TXERR);
+- fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+- DEV_EVENT_TXDOWN, dev);
+- }
+- } else
+- ctc_pr_warn("%s: Error during TX init handshake\n", dev->name);
+-}
+-
+-/**
+- * Handle TX timeout by retrying operation.
+- *
+- * @param fi An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_txretry(fsm_instance * fi, int event, void *arg)
+-{
+- struct channel *ch = (struct channel *) arg;
+- struct net_device *dev = ch->netdev;
+- unsigned long saveflags;
+-
+- DBF_TEXT(trace, 4, __FUNCTION__);
+- fsm_deltimer(&ch->timer);
+- if (ch->retry++ > 3) {
+- ctc_pr_debug("%s: TX retry failed, restarting channel\n",
+- dev->name);
+- fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+- DEV_EVENT_TXDOWN, dev);
+- ch_action_restart(fi, event, arg);
+- } else {
+- struct sk_buff *skb;
+-
+- ctc_pr_debug("%s: TX retry %d\n", dev->name, ch->retry);
+- if ((skb = skb_peek(&ch->io_queue))) {
+- int rc = 0;
+-
+- clear_normalized_cda(&ch->ccw[4]);
+- ch->ccw[4].count = skb->len;
+- if (set_normalized_cda(&ch->ccw[4], skb->data)) {
+- ctc_pr_debug(
+- "%s: IDAL alloc failed, chan restart\n",
+- dev->name);
+- fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+- DEV_EVENT_TXDOWN, dev);
+- ch_action_restart(fi, event, arg);
+- return;
+- }
+- fsm_addtimer(&ch->timer, 1000, CH_EVENT_TIMER, ch);
+- saveflags = 0; /* avoids compiler warning with
+- spin_unlock_irqrestore */
+- if (event == CH_EVENT_TIMER) // only for TIMER not yet locked
+- spin_lock_irqsave(get_ccwdev_lock(ch->cdev),
+- saveflags);
+- rc = ccw_device_start(ch->cdev, &ch->ccw[3],
+- (unsigned long) ch, 0xff, 0);
+- if (event == CH_EVENT_TIMER)
+- spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev),
+- saveflags);
+- if (rc != 0) {
+- fsm_deltimer(&ch->timer);
+- ccw_check_return_code(ch, rc, "TX in ch_action_txretry");
+- ctc_purge_skb_queue(&ch->io_queue);
+- }
+- }
+- }
+-
+-}
+-
+-/**
+- * Handle fatal errors during an I/O command.
+- *
+- * @param fi An instance of a channel statemachine.
+- * @param event The event, just happened.
+- * @param arg Generic pointer, casted from channel * upon call.
+- */
+-static void
+-ch_action_iofatal(fsm_instance * fi, int event, void *arg)
+-{
+- struct channel *ch = (struct channel *) arg;
+- struct net_device *dev = ch->netdev;
+-
+- DBF_TEXT(trace, 3, __FUNCTION__);
+- fsm_deltimer(&ch->timer);
+- if (CHANNEL_DIRECTION(ch->flags) == READ) {
+- ctc_pr_debug("%s: RX I/O error\n", dev->name);
+- fsm_newstate(fi, CH_STATE_RXERR);
+- fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+- DEV_EVENT_RXDOWN, dev);
+- } else {
+- ctc_pr_debug("%s: TX I/O error\n", dev->name);
+- fsm_newstate(fi, CH_STATE_TXERR);
+- fsm_event(((struct ctc_priv *) dev->priv)->fsm,
+- DEV_EVENT_TXDOWN, dev);
+- }
+-}
+-
+-static void
+-ch_action_reinit(fsm_instance *fi, int event, void *arg)
+-{
+- struct channel *ch = (struct channel *)arg;
+- struct net_device *dev = ch->netdev;
+- struct ctc_priv *privptr = dev->priv;
+-
+- DBF_TEXT(trace, 4, __FUNCTION__);
+- ch_action_iofatal(fi, event, arg);
+- fsm_addtimer(&privptr->restart_timer, 1000, DEV_EVENT_RESTART, dev);
+-}
+-
+-/**
+- * The statemachine for a channel.
+- */
+-static const fsm_node ch_fsm[] = {
+- {CH_STATE_STOPPED, CH_EVENT_STOP, fsm_action_nop },
+- {CH_STATE_STOPPED, CH_EVENT_START, ch_action_start },
+- {CH_STATE_STOPPED, CH_EVENT_FINSTAT, fsm_action_nop },
+- {CH_STATE_STOPPED, CH_EVENT_MC_FAIL, fsm_action_nop },
+-
+- {CH_STATE_NOTOP, CH_EVENT_STOP, ch_action_stop },
+- {CH_STATE_NOTOP, CH_EVENT_START, fsm_action_nop },
+- {CH_STATE_NOTOP, CH_EVENT_FINSTAT, fsm_action_nop },
+- {CH_STATE_NOTOP, CH_EVENT_MC_FAIL, fsm_action_nop },
+- {CH_STATE_NOTOP, CH_EVENT_MC_GOOD, ch_action_start },
+-
+- {CH_STATE_STARTWAIT, CH_EVENT_STOP, ch_action_haltio },
+- {CH_STATE_STARTWAIT, CH_EVENT_START, fsm_action_nop },
+- {CH_STATE_STARTWAIT, CH_EVENT_FINSTAT, ch_action_setmode },
+- {CH_STATE_STARTWAIT, CH_EVENT_TIMER, ch_action_setuperr },
+- {CH_STATE_STARTWAIT, CH_EVENT_IO_ENODEV, ch_action_iofatal },
+- {CH_STATE_STARTWAIT, CH_EVENT_IO_EIO, ch_action_reinit },
+- {CH_STATE_STARTWAIT, CH_EVENT_MC_FAIL, ch_action_fail },
+-
+- {CH_STATE_STARTRETRY, CH_EVENT_STOP, ch_action_haltio },
+- {CH_STATE_STARTRETRY, CH_EVENT_TIMER, ch_action_setmode },
+- {CH_STATE_STARTRETRY, CH_EVENT_FINSTAT, fsm_action_nop },
+- {CH_STATE_STARTRETRY, CH_EVENT_MC_FAIL, ch_action_fail },
+-
+- {CH_STATE_SETUPWAIT, CH_EVENT_STOP, ch_action_haltio },
+- {CH_STATE_SETUPWAIT, CH_EVENT_START, fsm_action_nop },
+- {CH_STATE_SETUPWAIT, CH_EVENT_FINSTAT, ch_action_firstio },
+- {CH_STATE_SETUPWAIT, CH_EVENT_UC_RCRESET, ch_action_setuperr },
+- {CH_STATE_SETUPWAIT, CH_EVENT_UC_RSRESET, ch_action_setuperr },
+- {CH_STATE_SETUPWAIT, CH_EVENT_TIMER, ch_action_setmode },
+- {CH_STATE_SETUPWAIT, CH_EVENT_IO_ENODEV, ch_action_iofatal },
+- {CH_STATE_SETUPWAIT, CH_EVENT_IO_EIO, ch_action_reinit },
+- {CH_STATE_SETUPWAIT, CH_EVENT_MC_FAIL, ch_action_fail },
+-
+- {CH_STATE_RXINIT, CH_EVENT_STOP, ch_action_haltio },
+- {CH_STATE_RXINIT, CH_EVENT_START, fsm_action_nop },
+- {CH_STATE_RXINIT, CH_EVENT_FINSTAT, ch_action_rxidle },
+- {CH_STATE_RXINIT, CH_EVENT_UC_RCRESET, ch_action_rxiniterr },
+- {CH_STATE_RXINIT, CH_EVENT_UC_RSRESET, ch_action_rxiniterr },
+- {CH_STATE_RXINIT, CH_EVENT_TIMER, ch_action_rxiniterr },
+- {CH_STATE_RXINIT, CH_EVENT_ATTNBUSY, ch_action_rxinitfail },
+- {CH_STATE_RXINIT, CH_EVENT_IO_ENODEV, ch_action_iofatal },
+- {CH_STATE_RXINIT, CH_EVENT_IO_EIO, ch_action_reinit },
+- {CH_STATE_RXINIT, CH_EVENT_UC_ZERO, ch_action_firstio },
+- {CH_STATE_RXINIT, CH_EVENT_MC_FAIL, ch_action_fail },
+-
+- {CH_STATE_RXIDLE, CH_EVENT_STOP, ch_action_haltio },
+- {CH_STATE_RXIDLE, CH_EVENT_START, fsm_action_nop },
+- {CH_STATE_RXIDLE, CH_EVENT_FINSTAT, ch_action_rx },
+- {CH_STATE_RXIDLE, CH_EVENT_UC_RCRESET, ch_action_rxdisc },
+-// {CH_STATE_RXIDLE, CH_EVENT_UC_RSRESET, ch_action_rxretry },
+- {CH_STATE_RXIDLE, CH_EVENT_IO_ENODEV, ch_action_iofatal },
+- {CH_STATE_RXIDLE, CH_EVENT_IO_EIO, ch_action_reinit },
+- {CH_STATE_RXIDLE, CH_EVENT_MC_FAIL, ch_action_fail },
+- {CH_STATE_RXIDLE, CH_EVENT_UC_ZERO, ch_action_rx },
+-
+- {CH_STATE_TXINIT, CH_EVENT_STOP, ch_action_haltio },
+- {CH_STATE_TXINIT, CH_EVENT_START, fsm_action_nop },
+- {CH_STATE_TXINIT, CH_EVENT_FINSTAT, ch_action_txidle },
+- {CH_STATE_TXINIT, CH_EVENT_UC_RCRESET, ch_action_txiniterr },
+- {CH_STATE_TXINIT, CH_EVENT_UC_RSRESET, ch_action_txiniterr },
+- {CH_STATE_TXINIT, CH_EVENT_TIMER, ch_action_txiniterr },
+- {CH_STATE_TXINIT, CH_EVENT_IO_ENODEV, ch_action_iofatal },
+- {CH_STATE_TXINIT, CH_EVENT_IO_EIO, ch_action_reinit },
+- {CH_STATE_TXINIT, CH_EVENT_MC_FAIL, ch_action_fail },
+-
+- {CH_STATE_TXIDLE, CH_EVENT_STOP, ch_action_haltio },
+- {CH_STATE_TXIDLE, CH_EVENT_START, fsm_action_nop },
+- {CH_STATE_TXIDLE, CH_EVENT_FINSTAT, ch_action_firstio },
+- {CH_STATE_TXIDLE, CH_EVENT_UC_RCRESET, fsm_action_nop },
+- {CH_STATE_TXIDLE, CH_EVENT_UC_RSRESET, fsm_action_nop },
+- {CH_STATE_TXIDLE, CH_EVENT_IO_ENODEV, ch_action_iofatal },
+- {CH_STATE_TXIDLE, CH_EVENT_IO_EIO, ch_action_reinit },
+- {CH_STATE_TXIDLE, CH_EVENT_MC_FAIL, ch_action_fail },
+-
+- {CH_STATE_TERM, CH_EVENT_STOP, fsm_action_nop },
+- {CH_STATE_TERM, CH_EVENT_START, ch_action_restart },
+- {CH_STATE_TERM, CH_EVENT_FINSTAT, ch_action_stopped },
+- {CH_STATE_TERM, CH_EVENT_UC_RCRESET, fsm_action_nop },
+- {CH_STATE_TERM, CH_EVENT_UC_RSRESET, fsm_action_nop },
+- {CH_STATE_TERM, CH_EVENT_MC_FAIL, ch_action_fail },
+-
+- {CH_STATE_DTERM, CH_EVENT_STOP, ch_action_haltio },
+- {CH_STATE_DTERM, CH_EVENT_START, ch_action_restart },
+- {CH_STATE_DTERM, CH_EVENT_FINSTAT, ch_action_setmode },
+- {CH_STATE_DTERM, CH_EVENT_UC_RCRESET, fsm_action_nop },
+- {CH_STATE_DTERM, CH_EVENT_UC_RSRESET, fsm_action_nop },
+- {CH_STATE_DTERM, CH_EVENT_MC_FAIL, ch_action_fail },
+-
+- {CH_STATE_TX, CH_EVENT_STOP, ch_action_haltio },
+- {CH_STATE_TX, CH_EVENT_START, fsm_action_nop },
+- {CH_STATE_TX, CH_EVENT_FINSTAT, ch_action_txdone },
+- {CH_STATE_TX, CH_EVENT_UC_RCRESET, ch_action_txretry },
+- {CH_STATE_TX, CH_EVENT_UC_RSRESET, ch_action_txretry },
+- {CH_STATE_TX, CH_EVENT_TIMER, ch_action_txretry },
+- {CH_STATE_TX, CH_EVENT_IO_ENODEV, ch_action_iofatal },
+- {CH_STATE_TX, CH_EVENT_IO_EIO, ch_action_reinit },
+- {CH_STATE_TX, CH_EVENT_MC_FAIL, ch_action_fail },
+-
+- {CH_STATE_RXERR, CH_EVENT_STOP, ch_action_haltio },
+- {CH_STATE_TXERR, CH_EVENT_STOP, ch_action_haltio },
+- {CH_STATE_TXERR, CH_EVENT_MC_FAIL, ch_action_fail },
+- {CH_STATE_RXERR, CH_EVENT_MC_FAIL, ch_action_fail },
+-};
+-
+-static const int CH_FSM_LEN = sizeof (ch_fsm) / sizeof (fsm_node);
+-
+-/**
+- * Functions related to setup and device detection.
+- *****************************************************************************/
+-
+-static inline int
+-less_than(char *id1, char *id2)
+-{
+- int dev1, dev2, i;
+-
+- for (i = 0; i < 5; i++) {
+- id1++;
+- id2++;
+- }
+- dev1 = simple_strtoul(id1, &id1, 16);
+- dev2 = simple_strtoul(id2, &id2, 16);
+-
+- return (dev1 < dev2);
+-}
+-
+-/**
+- * Add a new channel to the list of channels.
+- * Keeps the channel list sorted.
+- *
+- * @param cdev The ccw_device to be added.
+- * @param type The type class of the new channel.
+- *
+- * @return 0 on success, !0 on error.
+- */
+-static int
+-add_channel(struct ccw_device *cdev, enum channel_types type)
+-{
+- struct channel **c = &channels;
+- struct channel *ch;
+-
+- DBF_TEXT(trace, 2, __FUNCTION__);
+- ch = kzalloc(sizeof(struct channel), GFP_KERNEL);
+- if (!ch) {
+- ctc_pr_warn("ctc: Out of memory in add_channel\n");
+- return -1;
+- }
+- /* assure all flags and counters are reset */
+- ch->ccw = kzalloc(8 * sizeof(struct ccw1), GFP_KERNEL | GFP_DMA);
+- if (!ch->ccw) {
+- kfree(ch);
+- ctc_pr_warn("ctc: Out of memory in add_channel\n");
+- return -1;
+- }
+-
+-
+- /**
+- * "static" ccws are used in the following way:
+- *
+- * ccw[0..2] (Channel program for generic I/O):
+- * 0: prepare
+- * 1: read or write (depending on direction) with fixed
+- * buffer (idal allocated once when buffer is allocated)
+- * 2: nop
+- * ccw[3..5] (Channel program for direct write of packets)
+- * 3: prepare
+- * 4: write (idal allocated on every write).
+- * 5: nop
+- * ccw[6..7] (Channel program for initial channel setup):
+- * 6: set extended mode
+- * 7: nop
+- *
+- * ch->ccw[0..5] are initialized in ch_action_start because
+- * the channel's direction is yet unknown here.
+- */
+- ch->ccw[6].cmd_code = CCW_CMD_SET_EXTENDED;
+- ch->ccw[6].flags = CCW_FLAG_SLI;
+-
+- ch->ccw[7].cmd_code = CCW_CMD_NOOP;
+- ch->ccw[7].flags = CCW_FLAG_SLI;
+-
+- ch->cdev = cdev;
+- snprintf(ch->id, CTC_ID_SIZE, "ch-%s", cdev->dev.bus_id);
+- ch->type = type;
+- ch->fsm = init_fsm(ch->id, ch_state_names,
+- ch_event_names, NR_CH_STATES, NR_CH_EVENTS,
+- ch_fsm, CH_FSM_LEN, GFP_KERNEL);
+- if (ch->fsm == NULL) {
+- ctc_pr_warn("ctc: Could not create FSM in add_channel\n");
+- kfree(ch->ccw);
+- kfree(ch);
+- return -1;
+- }
+- fsm_newstate(ch->fsm, CH_STATE_IDLE);
+- ch->irb = kzalloc(sizeof(struct irb), GFP_KERNEL);
+- if (!ch->irb) {
+- ctc_pr_warn("ctc: Out of memory in add_channel\n");
+- kfree_fsm(ch->fsm);
+- kfree(ch->ccw);
+- kfree(ch);
+- return -1;
+- }
+- while (*c && less_than((*c)->id, ch->id))
+- c = &(*c)->next;
+- if (*c && (!strncmp((*c)->id, ch->id, CTC_ID_SIZE))) {
+- ctc_pr_debug(
+- "ctc: add_channel: device %s already in list, "
+- "using old entry\n", (*c)->id);
+- kfree(ch->irb);
+- kfree_fsm(ch->fsm);
+- kfree(ch->ccw);
+- kfree(ch);
+- return 0;
+- }
+-
+- spin_lock_init(&ch->collect_lock);
+-
+- fsm_settimer(ch->fsm, &ch->timer);
+- skb_queue_head_init(&ch->io_queue);
+- skb_queue_head_init(&ch->collect_queue);
+- ch->next = *c;
+- *c = ch;
+- return 0;
+-}
+-
+-/**
+- * Release a specific channel in the channel list.
+- *
+- * @param ch Pointer to channel struct to be released.
+- */
+-static void
+-channel_free(struct channel *ch)
+-{
+- ch->flags &= ~CHANNEL_FLAGS_INUSE;
+- fsm_newstate(ch->fsm, CH_STATE_IDLE);
+-}
+-
+-/**
+- * Remove a specific channel in the channel list.
+- *
+- * @param ch Pointer to channel struct to be released.
+- */
+-static void
+-channel_remove(struct channel *ch)
+-{
+- struct channel **c = &channels;
+-
+- DBF_TEXT(trace, 2, __FUNCTION__);
+- if (ch == NULL)
+- return;
+-
+- channel_free(ch);
+- while (*c) {
+- if (*c == ch) {
+- *c = ch->next;
+- fsm_deltimer(&ch->timer);
+- kfree_fsm(ch->fsm);
+- clear_normalized_cda(&ch->ccw[4]);
+- if (ch->trans_skb != NULL) {
+- clear_normalized_cda(&ch->ccw[1]);
+- dev_kfree_skb(ch->trans_skb);
+- }
+- kfree(ch->ccw);
+- kfree(ch->irb);
+- kfree(ch);
+- return;
+- }
+- c = &((*c)->next);
+- }
+-}
+-
+-/**
+- * Get a specific channel from the channel list.
+- *
+- * @param type Type of channel we are interested in.
+- * @param id Id of channel we are interested in.
+- * @param direction Direction we want to use this channel for.
+- *
+- * @return Pointer to a channel or NULL if no matching channel available.
+- */
+-static struct channel
+-*
+-channel_get(enum channel_types type, char *id, int direction)
+-{
+- struct channel *ch = channels;
+-
+- DBF_TEXT(trace, 3, __FUNCTION__);
+-#ifdef DEBUG
+- ctc_pr_debug("ctc: %s(): searching for ch with id %s and type %d\n",
+- __func__, id, type);
+-#endif
+-
+- while (ch && ((strncmp(ch->id, id, CTC_ID_SIZE)) || (ch->type != type))) {
+-#ifdef DEBUG
+- ctc_pr_debug("ctc: %s(): ch=0x%p (id=%s, type=%d\n",
+- __func__, ch, ch->id, ch->type);
+-#endif
+- ch = ch->next;
+- }
+-#ifdef DEBUG
+- ctc_pr_debug("ctc: %s(): ch=0x%pq (id=%s, type=%d\n",
+- __func__, ch, ch->id, ch->type);
+-#endif
+- if (!ch) {
+- ctc_pr_warn("ctc: %s(): channel with id %s "
+- "and type %d not found in channel list\n",
+- __func__, id, type);
+- } else {
+- if (ch->flags & CHANNEL_FLAGS_INUSE)
+- ch = NULL;
+- else {
+- ch->flags |= CHANNEL_FLAGS_INUSE;
+- ch->flags &= ~CHANNEL_FLAGS_RWMASK;
+- ch->flags |= (direction == WRITE)
+- ? CHANNEL_FLAGS_WRITE : CHANNEL_FLAGS_READ;
+- fsm_newstate(ch->fsm, CH_STATE_STOPPED);
+- }
+- }
+- return ch;
+-}
+-
+-/**
+- * Return the channel type by name.
+- *
+- * @param name Name of network interface.
+- *
+- * @return Type class of channel to be used for that interface.
+- */
+-static enum channel_types inline
+-extract_channel_media(char *name)
+-{
+- enum channel_types ret = channel_type_unknown;
+-
+- if (name != NULL) {
+- if (strncmp(name, "ctc", 3) == 0)
+- ret = channel_type_parallel;
+- if (strncmp(name, "escon", 5) == 0)
+- ret = channel_type_escon;
+- }
+- return ret;
+-}
+-
+-static long
+-__ctc_check_irb_error(struct ccw_device *cdev, struct irb *irb)
+-{
+- if (!IS_ERR(irb))
+- return 0;
+-
+- switch (PTR_ERR(irb)) {
+- case -EIO:
+- ctc_pr_warn("i/o-error on device %s\n", cdev->dev.bus_id);
+-// CTC_DBF_TEXT(trace, 2, "ckirberr");
+-// CTC_DBF_TEXT_(trace, 2, " rc%d", -EIO);
+- break;
+- case -ETIMEDOUT:
+- ctc_pr_warn("timeout on device %s\n", cdev->dev.bus_id);
+-// CTC_DBF_TEXT(trace, 2, "ckirberr");
+-// CTC_DBF_TEXT_(trace, 2, " rc%d", -ETIMEDOUT);
+- break;
+- default:
+- ctc_pr_warn("unknown error %ld on device %s\n", PTR_ERR(irb),
+- cdev->dev.bus_id);
+-// CTC_DBF_TEXT(trace, 2, "ckirberr");
+-// CTC_DBF_TEXT(trace, 2, " rc???");
+- }
+- return PTR_ERR(irb);
+-}
+-
+-/**
+- * Main IRQ handler.
+- *
+- * @param cdev The ccw_device the interrupt is for.
+- * @param intparm interruption parameter.
+- * @param irb interruption response block.
+- */
+-static void
+-ctc_irq_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
+-{
+- struct channel *ch;
+- struct net_device *dev;
+- struct ctc_priv *priv;
+-
+- DBF_TEXT(trace, 5, __FUNCTION__);
+- if (__ctc_check_irb_error(cdev, irb))
+- return;
+-
+- /* Check for unsolicited interrupts. */
+- if (!cdev->dev.driver_data) {
+- ctc_pr_warn("ctc: Got unsolicited irq: %s c-%02x d-%02x\n",
+- cdev->dev.bus_id, irb->scsw.cstat,
+- irb->scsw.dstat);
+- return;
+- }
+-
+- priv = ((struct ccwgroup_device *)cdev->dev.driver_data)
+- ->dev.driver_data;
+-
+- /* Try to extract channel from driver data. */
+- if (priv->channel[READ]->cdev == cdev)
+- ch = priv->channel[READ];
+- else if (priv->channel[WRITE]->cdev == cdev)
+- ch = priv->channel[WRITE];
+- else {
+- ctc_pr_err("ctc: Can't determine channel for interrupt, "
+- "device %s\n", cdev->dev.bus_id);
+- return;
+- }
+-
+- dev = (struct net_device *) (ch->netdev);
+- if (dev == NULL) {
+- ctc_pr_crit("ctc: ctc_irq_handler dev=NULL bus_id=%s, ch=0x%p\n",
+- cdev->dev.bus_id, ch);
+- return;
+- }
+-
+-#ifdef DEBUG
+- ctc_pr_debug("%s: interrupt for device: %s received c-%02x d-%02x\n",
+- dev->name, ch->id, irb->scsw.cstat, irb->scsw.dstat);
+-#endif
+-
+- /* Copy interruption response block. */
+- memcpy(ch->irb, irb, sizeof(struct irb));
+-
+- /* Check for good subchannel return code, otherwise error message */
+- if (ch->irb->scsw.cstat) {
+- fsm_event(ch->fsm, CH_EVENT_SC_UNKNOWN, ch);
+- ctc_pr_warn("%s: subchannel check for device: %s - %02x %02x\n",
+- dev->name, ch->id, ch->irb->scsw.cstat,
+- ch->irb->scsw.dstat);
+- return;
+- }
+-
+- /* Check the reason-code of a unit check */
+- if (ch->irb->scsw.dstat & DEV_STAT_UNIT_CHECK) {
+- ccw_unit_check(ch, ch->irb->ecw[0]);
+- return;
+- }
+- if (ch->irb->scsw.dstat & DEV_STAT_BUSY) {
+- if (ch->irb->scsw.dstat & DEV_STAT_ATTENTION)
+- fsm_event(ch->fsm, CH_EVENT_ATTNBUSY, ch);
+- else
+- fsm_event(ch->fsm, CH_EVENT_BUSY, ch);
+- return;
+- }
+- if (ch->irb->scsw.dstat & DEV_STAT_ATTENTION) {
+- fsm_event(ch->fsm, CH_EVENT_ATTN, ch);
+- return;
+- }
+- if ((ch->irb->scsw.stctl & SCSW_STCTL_SEC_STATUS) ||
+- (ch->irb->scsw.stctl == SCSW_STCTL_STATUS_PEND) ||
+- (ch->irb->scsw.stctl ==
+- (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))
+- fsm_event(ch->fsm, CH_EVENT_FINSTAT, ch);
+- else
+- fsm_event(ch->fsm, CH_EVENT_IRQ, ch);
+-
+-}
+-
+-/**
+- * Actions for interface - statemachine.
+- *****************************************************************************/
+-
+-/**
+- * Startup channels by sending CH_EVENT_START to each channel.
+- *
+- * @param fi An instance of an interface statemachine.
+- * @param event The event, just happened.
+- * @param arg Generic pointer, casted from struct net_device * upon call.
+- */
+-static void
+-dev_action_start(fsm_instance * fi, int event, void *arg)
+-{
+- struct net_device *dev = (struct net_device *) arg;
+- struct ctc_priv *privptr = dev->priv;
+- int direction;
+-
+- DBF_TEXT(setup, 3, __FUNCTION__);
+- fsm_deltimer(&privptr->restart_timer);
+- fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
+- for (direction = READ; direction <= WRITE; direction++) {
+- struct channel *ch = privptr->channel[direction];
+- fsm_event(ch->fsm, CH_EVENT_START, ch);
+- }
+-}
+-
+-/**
+- * Shutdown channels by sending CH_EVENT_STOP to each channel.
+- *
+- * @param fi An instance of an interface statemachine.
+- * @param event The event, just happened.
+- * @param arg Generic pointer, casted from struct net_device * upon call.
+- */
+-static void
+-dev_action_stop(fsm_instance * fi, int event, void *arg)
+-{
+- struct net_device *dev = (struct net_device *) arg;
+- struct ctc_priv *privptr = dev->priv;
+- int direction;
+-
+- DBF_TEXT(trace, 3, __FUNCTION__);
+- fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
+- for (direction = READ; direction <= WRITE; direction++) {
+- struct channel *ch = privptr->channel[direction];
+- fsm_event(ch->fsm, CH_EVENT_STOP, ch);
+- }
+-}
+-static void
+-dev_action_restart(fsm_instance *fi, int event, void *arg)
+-{
+- struct net_device *dev = (struct net_device *)arg;
+- struct ctc_priv *privptr = dev->priv;
+-
+- DBF_TEXT(trace, 3, __FUNCTION__);
+- ctc_pr_debug("%s: Restarting\n", dev->name);
+- dev_action_stop(fi, event, arg);
+- fsm_event(privptr->fsm, DEV_EVENT_STOP, dev);
+- fsm_addtimer(&privptr->restart_timer, CTC_TIMEOUT_5SEC,
+- DEV_EVENT_START, dev);
+-}
+-
+-/**
+- * Called from channel statemachine
+- * when a channel is up and running.
+- *
+- * @param fi An instance of an interface statemachine.
+- * @param event The event, just happened.
+- * @param arg Generic pointer, casted from struct net_device * upon call.
+- */
+-static void
+-dev_action_chup(fsm_instance * fi, int event, void *arg)
+-{
+- struct net_device *dev = (struct net_device *) arg;
+-
+- DBF_TEXT(trace, 3, __FUNCTION__);
+- switch (fsm_getstate(fi)) {
+- case DEV_STATE_STARTWAIT_RXTX:
+- if (event == DEV_EVENT_RXUP)
+- fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);
+- else
+- fsm_newstate(fi, DEV_STATE_STARTWAIT_RX);
+- break;
+- case DEV_STATE_STARTWAIT_RX:
+- if (event == DEV_EVENT_RXUP) {
+- fsm_newstate(fi, DEV_STATE_RUNNING);
+- ctc_pr_info("%s: connected with remote side\n",
+- dev->name);
+- ctc_clear_busy(dev);
+- }
+- break;
+- case DEV_STATE_STARTWAIT_TX:
+- if (event == DEV_EVENT_TXUP) {
+- fsm_newstate(fi, DEV_STATE_RUNNING);
+- ctc_pr_info("%s: connected with remote side\n",
+- dev->name);
+- ctc_clear_busy(dev);
+- }
+- break;
+- case DEV_STATE_STOPWAIT_TX:
+- if (event == DEV_EVENT_RXUP)
+- fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
+- break;
+- case DEV_STATE_STOPWAIT_RX:
+- if (event == DEV_EVENT_TXUP)
+- fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
+- break;
+- }
+-}
+-
+-/**
+- * Called from channel statemachine
+- * when a channel has been shutdown.
+- *
+- * @param fi An instance of an interface statemachine.
+- * @param event The event, just happened.
+- * @param arg Generic pointer, casted from struct net_device * upon call.
+- */
+-static void
+-dev_action_chdown(fsm_instance * fi, int event, void *arg)
+-{
+-
+- DBF_TEXT(trace, 3, __FUNCTION__);
+- switch (fsm_getstate(fi)) {
+- case DEV_STATE_RUNNING:
+- if (event == DEV_EVENT_TXDOWN)
+- fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);
+- else
+- fsm_newstate(fi, DEV_STATE_STARTWAIT_RX);
+- break;
+- case DEV_STATE_STARTWAIT_RX:
+- if (event == DEV_EVENT_TXDOWN)
+- fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
+- break;
+- case DEV_STATE_STARTWAIT_TX:
+- if (event == DEV_EVENT_RXDOWN)
+- fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
+- break;
+- case DEV_STATE_STOPWAIT_RXTX:
+- if (event == DEV_EVENT_TXDOWN)
+- fsm_newstate(fi, DEV_STATE_STOPWAIT_RX);
+- else
+- fsm_newstate(fi, DEV_STATE_STOPWAIT_TX);
+- break;
+- case DEV_STATE_STOPWAIT_RX:
+- if (event == DEV_EVENT_RXDOWN)
+- fsm_newstate(fi, DEV_STATE_STOPPED);
+- break;
+- case DEV_STATE_STOPWAIT_TX:
+- if (event == DEV_EVENT_TXDOWN)
+- fsm_newstate(fi, DEV_STATE_STOPPED);
+- break;
+- }
+-}
+-
+-static const fsm_node dev_fsm[] = {
+- {DEV_STATE_STOPPED, DEV_EVENT_START, dev_action_start},
+-
+- {DEV_STATE_STOPWAIT_RXTX, DEV_EVENT_START, dev_action_start },
+- {DEV_STATE_STOPWAIT_RXTX, DEV_EVENT_RXDOWN, dev_action_chdown },
+- {DEV_STATE_STOPWAIT_RXTX, DEV_EVENT_TXDOWN, dev_action_chdown },
+- {DEV_STATE_STOPWAIT_RXTX, DEV_EVENT_RESTART, dev_action_restart },
+-
+- {DEV_STATE_STOPWAIT_RX, DEV_EVENT_START, dev_action_start },
+- {DEV_STATE_STOPWAIT_RX, DEV_EVENT_RXUP, dev_action_chup },
+- {DEV_STATE_STOPWAIT_RX, DEV_EVENT_TXUP, dev_action_chup },
+- {DEV_STATE_STOPWAIT_RX, DEV_EVENT_RXDOWN, dev_action_chdown },
+- {DEV_STATE_STOPWAIT_RX, DEV_EVENT_RESTART, dev_action_restart },
+-
+- {DEV_STATE_STOPWAIT_TX, DEV_EVENT_START, dev_action_start },
+- {DEV_STATE_STOPWAIT_TX, DEV_EVENT_RXUP, dev_action_chup },
+- {DEV_STATE_STOPWAIT_TX, DEV_EVENT_TXUP, dev_action_chup },
+- {DEV_STATE_STOPWAIT_TX, DEV_EVENT_TXDOWN, dev_action_chdown },
+- {DEV_STATE_STOPWAIT_TX, DEV_EVENT_RESTART, dev_action_restart },
+-
+- {DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_STOP, dev_action_stop },
+- {DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RXUP, dev_action_chup },
+- {DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_TXUP, dev_action_chup },
+- {DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RXDOWN, dev_action_chdown },
+- {DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_TXDOWN, dev_action_chdown },
+- {DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RESTART, dev_action_restart },
+-
+- {DEV_STATE_STARTWAIT_TX, DEV_EVENT_STOP, dev_action_stop },
+- {DEV_STATE_STARTWAIT_TX, DEV_EVENT_RXUP, dev_action_chup },
+- {DEV_STATE_STARTWAIT_TX, DEV_EVENT_TXUP, dev_action_chup },
+- {DEV_STATE_STARTWAIT_TX, DEV_EVENT_RXDOWN, dev_action_chdown },
+- {DEV_STATE_STARTWAIT_TX, DEV_EVENT_RESTART, dev_action_restart },
+-
+- {DEV_STATE_STARTWAIT_RX, DEV_EVENT_STOP, dev_action_stop },
+- {DEV_STATE_STARTWAIT_RX, DEV_EVENT_RXUP, dev_action_chup },
+- {DEV_STATE_STARTWAIT_RX, DEV_EVENT_TXUP, dev_action_chup },
+- {DEV_STATE_STARTWAIT_RX, DEV_EVENT_TXDOWN, dev_action_chdown },
+- {DEV_STATE_STARTWAIT_RX, DEV_EVENT_RESTART, dev_action_restart },
+-
+- {DEV_STATE_RUNNING, DEV_EVENT_STOP, dev_action_stop },
+- {DEV_STATE_RUNNING, DEV_EVENT_RXDOWN, dev_action_chdown },
+- {DEV_STATE_RUNNING, DEV_EVENT_TXDOWN, dev_action_chdown },
+- {DEV_STATE_RUNNING, DEV_EVENT_TXUP, fsm_action_nop },
+- {DEV_STATE_RUNNING, DEV_EVENT_RXUP, fsm_action_nop },
+- {DEV_STATE_RUNNING, DEV_EVENT_RESTART, dev_action_restart },
+-};
+-
+-static const int DEV_FSM_LEN = sizeof (dev_fsm) / sizeof (fsm_node);
+-
+-/**
+- * Transmit a packet.
+- * This is a helper function for ctc_tx().
+- *
+- * @param ch Channel to be used for sending.
+- * @param skb Pointer to struct sk_buff of packet to send.
+- * The linklevel header has already been set up
+- * by ctc_tx().
+- *
+- * @return 0 on success, -ERRNO on failure. (Never fails.)
+- */
+-static int
+-transmit_skb(struct channel *ch, struct sk_buff *skb)
+-{
+- unsigned long saveflags;
+- struct ll_header header;
+- int rc = 0;
+-
+- DBF_TEXT(trace, 5, __FUNCTION__);
+- /* we need to acquire the lock for testing the state
+- * otherwise we can have an IRQ changing the state to
+- * TXIDLE after the test but before acquiring the lock.
+- */
+- spin_lock_irqsave(&ch->collect_lock, saveflags);
+- if (fsm_getstate(ch->fsm) != CH_STATE_TXIDLE) {
+- int l = skb->len + LL_HEADER_LENGTH;
+-
+- if (ch->collect_len + l > ch->max_bufsize - 2) {
+- spin_unlock_irqrestore(&ch->collect_lock, saveflags);
+- return -EBUSY;
+- } else {
+- atomic_inc(&skb->users);
+- header.length = l;
+- header.type = skb->protocol;
+- header.unused = 0;
+- memcpy(skb_push(skb, LL_HEADER_LENGTH), &header,
+- LL_HEADER_LENGTH);
+- skb_queue_tail(&ch->collect_queue, skb);
+- ch->collect_len += l;
+- }
+- spin_unlock_irqrestore(&ch->collect_lock, saveflags);
+- } else {
+- __u16 block_len;
+- int ccw_idx;
+- struct sk_buff *nskb;
+- unsigned long hi;
+- spin_unlock_irqrestore(&ch->collect_lock, saveflags);
+- /**
+- * Protect skb against beeing free'd by upper
+- * layers.
+- */
+- atomic_inc(&skb->users);
+- ch->prof.txlen += skb->len;
+- header.length = skb->len + LL_HEADER_LENGTH;
+- header.type = skb->protocol;
+- header.unused = 0;
+- memcpy(skb_push(skb, LL_HEADER_LENGTH), &header,
+- LL_HEADER_LENGTH);
+- block_len = skb->len + 2;
+- *((__u16 *) skb_push(skb, 2)) = block_len;
+-
+- /**
+- * IDAL support in CTC is broken, so we have to
+- * care about skb's above 2G ourselves.
+- */
+- hi = ((unsigned long)skb_tail_pointer(skb) +
+- LL_HEADER_LENGTH) >> 31;
+- if (hi) {
+- nskb = alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
+- if (!nskb) {
+- atomic_dec(&skb->users);
+- skb_pull(skb, LL_HEADER_LENGTH + 2);
+- ctc_clear_busy(ch->netdev);
+- return -ENOMEM;
+- } else {
+- memcpy(skb_put(nskb, skb->len),
+- skb->data, skb->len);
+- atomic_inc(&nskb->users);
+- atomic_dec(&skb->users);
+- dev_kfree_skb_irq(skb);
+- skb = nskb;
+- }
+- }
+-
+- ch->ccw[4].count = block_len;
+- if (set_normalized_cda(&ch->ccw[4], skb->data)) {
+- /**
+- * idal allocation failed, try via copying to
+- * trans_skb. trans_skb usually has a pre-allocated
+- * idal.
+- */
+- if (ctc_checkalloc_buffer(ch, 1)) {
+- /**
+- * Remove our header. It gets added
+- * again on retransmit.
+- */
+- atomic_dec(&skb->users);
+- skb_pull(skb, LL_HEADER_LENGTH + 2);
+- ctc_clear_busy(ch->netdev);
+- return -EBUSY;
+- }
+-
+- skb_reset_tail_pointer(ch->trans_skb);
+- ch->trans_skb->len = 0;
+- ch->ccw[1].count = skb->len;
+- skb_copy_from_linear_data(skb, skb_put(ch->trans_skb,
+- skb->len),
+- skb->len);
+- atomic_dec(&skb->users);
+- dev_kfree_skb_irq(skb);
+- ccw_idx = 0;
+- } else {
+- skb_queue_tail(&ch->io_queue, skb);
+- ccw_idx = 3;
+- }
+- ch->retry = 0;
+- fsm_newstate(ch->fsm, CH_STATE_TX);
+- fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
+- spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
+- ch->prof.send_stamp = current_kernel_time();
+- rc = ccw_device_start(ch->cdev, &ch->ccw[ccw_idx],
+- (unsigned long) ch, 0xff, 0);
+- spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
+- if (ccw_idx == 3)
+- ch->prof.doios_single++;
+- if (rc != 0) {
+- fsm_deltimer(&ch->timer);
+- ccw_check_return_code(ch, rc, "single skb TX");
+- if (ccw_idx == 3)
+- skb_dequeue_tail(&ch->io_queue);
+- /**
+- * Remove our header. It gets added
+- * again on retransmit.
+- */
+- skb_pull(skb, LL_HEADER_LENGTH + 2);
+- } else {
+- if (ccw_idx == 0) {
+- struct net_device *dev = ch->netdev;
+- struct ctc_priv *privptr = dev->priv;
+- privptr->stats.tx_packets++;
+- privptr->stats.tx_bytes +=
+- skb->len - LL_HEADER_LENGTH;
+- }
+- }
+- }
+-
+- ctc_clear_busy(ch->netdev);
+- return rc;
+-}
+-
+-/**
+- * Interface API for upper network layers
+- *****************************************************************************/
+-
+-/**
+- * Open an interface.
+- * Called from generic network layer when ifconfig up is run.
+- *
+- * @param dev Pointer to interface struct.
+- *
+- * @return 0 on success, -ERRNO on failure. (Never fails.)
+- */
+-static int
+-ctc_open(struct net_device * dev)
+-{
+- DBF_TEXT(trace, 5, __FUNCTION__);
+- fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_START, dev);
+- return 0;
+-}
+-
+-/**
+- * Close an interface.
+- * Called from generic network layer when ifconfig down is run.
+- *
+- * @param dev Pointer to interface struct.
+- *
+- * @return 0 on success, -ERRNO on failure. (Never fails.)
+- */
+-static int
+-ctc_close(struct net_device * dev)
+-{
+- DBF_TEXT(trace, 5, __FUNCTION__);
+- fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_STOP, dev);
+- return 0;
+-}
+-
+-/**
+- * Start transmission of a packet.
+- * Called from generic network device layer.
+- *
+- * @param skb Pointer to buffer containing the packet.
+- * @param dev Pointer to interface struct.
+- *
+- * @return 0 if packet consumed, !0 if packet rejected.
+- * Note: If we return !0, then the packet is free'd by
+- * the generic network layer.
+- */
+-static int
+-ctc_tx(struct sk_buff *skb, struct net_device * dev)
+-{
+- int rc = 0;
+- struct ctc_priv *privptr = (struct ctc_priv *) dev->priv;
+-
+- DBF_TEXT(trace, 5, __FUNCTION__);
+- /**
+- * Some sanity checks ...
+- */
+- if (skb == NULL) {
+- ctc_pr_warn("%s: NULL sk_buff passed\n", dev->name);
+- privptr->stats.tx_dropped++;
+- return 0;
+- }
+- if (skb_headroom(skb) < (LL_HEADER_LENGTH + 2)) {
+- ctc_pr_warn("%s: Got sk_buff with head room < %ld bytes\n",
+- dev->name, LL_HEADER_LENGTH + 2);
+- dev_kfree_skb(skb);
+- privptr->stats.tx_dropped++;
+- return 0;
+- }
+-
+- /**
+- * If channels are not running, try to restart them
+- * and throw away packet.
+- */
+- if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) {
+- fsm_event(privptr->fsm, DEV_EVENT_START, dev);
+- dev_kfree_skb(skb);
+- privptr->stats.tx_dropped++;
+- privptr->stats.tx_errors++;
+- privptr->stats.tx_carrier_errors++;
+- return 0;
+- }
+-
+- if (ctc_test_and_set_busy(dev))
+- return -EBUSY;
+-
+- dev->trans_start = jiffies;
+- if (transmit_skb(privptr->channel[WRITE], skb) != 0)
+- rc = 1;
+- return rc;
+-}
+-
+-/**
+- * Sets MTU of an interface.
+- *
+- * @param dev Pointer to interface struct.
+- * @param new_mtu The new MTU to use for this interface.
+- *
+- * @return 0 on success, -EINVAL if MTU is out of valid range.
+- * (valid range is 576 .. 65527). If VM is on the
+- * remote side, maximum MTU is 32760, however this is
+- * <em>not</em> checked here.
+- */
+-static int
+-ctc_change_mtu(struct net_device * dev, int new_mtu)
+-{
+- struct ctc_priv *privptr = (struct ctc_priv *) dev->priv;
+-
+- DBF_TEXT(trace, 3, __FUNCTION__);
+- if ((new_mtu < 576) || (new_mtu > 65527) ||
+- (new_mtu > (privptr->channel[READ]->max_bufsize -
+- LL_HEADER_LENGTH - 2)))
+- return -EINVAL;
+- dev->mtu = new_mtu;
+- dev->hard_header_len = LL_HEADER_LENGTH + 2;
+- return 0;
+-}
+-
+-/**
+- * Returns interface statistics of a device.
+- *
+- * @param dev Pointer to interface struct.
+- *
+- * @return Pointer to stats struct of this interface.
+- */
+-static struct net_device_stats *
+-ctc_stats(struct net_device * dev)
+-{
+- return &((struct ctc_priv *) dev->priv)->stats;
+-}
+-
+-/*
+- * sysfs attributes
+- */
+-
+-static ssize_t
+-buffer_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct ctc_priv *priv;
+-
+- priv = dev->driver_data;
+- if (!priv)
+- return -ENODEV;
+- return sprintf(buf, "%d\n",
+- priv->buffer_size);
+-}
+-
+-static ssize_t
+-buffer_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct ctc_priv *priv;
+- struct net_device *ndev;
+- int bs1;
+- char buffer[16];
+-
+- DBF_TEXT(trace, 3, __FUNCTION__);
+- DBF_TEXT(trace, 3, buf);
+- priv = dev->driver_data;
+- if (!priv) {
+- DBF_TEXT(trace, 3, "bfnopriv");
+- return -ENODEV;
+- }
+-
+- sscanf(buf, "%u", &bs1);
+- if (bs1 > CTC_BUFSIZE_LIMIT)
+- goto einval;
+- if (bs1 < (576 + LL_HEADER_LENGTH + 2))
+- goto einval;
+- priv->buffer_size = bs1; // just to overwrite the default
+-
+- ndev = priv->channel[READ]->netdev;
+- if (!ndev) {
+- DBF_TEXT(trace, 3, "bfnondev");
+- return -ENODEV;
+- }
+-
+- if ((ndev->flags & IFF_RUNNING) &&
+- (bs1 < (ndev->mtu + LL_HEADER_LENGTH + 2)))
+- goto einval;
+-
+- priv->channel[READ]->max_bufsize = bs1;
+- priv->channel[WRITE]->max_bufsize = bs1;
+- if (!(ndev->flags & IFF_RUNNING))
+- ndev->mtu = bs1 - LL_HEADER_LENGTH - 2;
+- priv->channel[READ]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
+- priv->channel[WRITE]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
+-
+- sprintf(buffer, "%d",priv->buffer_size);
+- DBF_TEXT(trace, 3, buffer);
+- return count;
+-
+-einval:
+- DBF_TEXT(trace, 3, "buff_err");
+- return -EINVAL;
+-}
+-
+-static ssize_t
+-loglevel_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- return sprintf(buf, "%d\n", loglevel);
+-}
+-
+-static ssize_t
+-loglevel_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- int ll1;
+-
+- DBF_TEXT(trace, 5, __FUNCTION__);
+- sscanf(buf, "%i", &ll1);
+-
+- if ((ll1 > CTC_LOGLEVEL_MAX) || (ll1 < 0))
+- return -EINVAL;
+- loglevel = ll1;
+- return count;
+-}
+-
+-static void
+-ctc_print_statistics(struct ctc_priv *priv)
+-{
+- char *sbuf;
+- char *p;
+-
+- DBF_TEXT(trace, 4, __FUNCTION__);
+- if (!priv)
+- return;
+- sbuf = kmalloc(2048, GFP_KERNEL);
+- if (sbuf == NULL)
+- return;
+- p = sbuf;
+-
+- p += sprintf(p, " Device FSM state: %s\n",
+- fsm_getstate_str(priv->fsm));
+- p += sprintf(p, " RX channel FSM state: %s\n",
+- fsm_getstate_str(priv->channel[READ]->fsm));
+- p += sprintf(p, " TX channel FSM state: %s\n",
+- fsm_getstate_str(priv->channel[WRITE]->fsm));
+- p += sprintf(p, " Max. TX buffer used: %ld\n",
+- priv->channel[WRITE]->prof.maxmulti);
+- p += sprintf(p, " Max. chained SKBs: %ld\n",
+- priv->channel[WRITE]->prof.maxcqueue);
+- p += sprintf(p, " TX single write ops: %ld\n",
+- priv->channel[WRITE]->prof.doios_single);
+- p += sprintf(p, " TX multi write ops: %ld\n",
+- priv->channel[WRITE]->prof.doios_multi);
+- p += sprintf(p, " Netto bytes written: %ld\n",
+- priv->channel[WRITE]->prof.txlen);
+- p += sprintf(p, " Max. TX IO-time: %ld\n",
+- priv->channel[WRITE]->prof.tx_time);
+-
+- ctc_pr_debug("Statistics for %s:\n%s",
+- priv->channel[WRITE]->netdev->name, sbuf);
+- kfree(sbuf);
+- return;
+-}
+-
+-static ssize_t
+-stats_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct ctc_priv *priv = dev->driver_data;
+- if (!priv)
+- return -ENODEV;
+- ctc_print_statistics(priv);
+- return sprintf(buf, "0\n");
+-}
+-
+-static ssize_t
+-stats_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct ctc_priv *priv = dev->driver_data;
+- if (!priv)
+- return -ENODEV;
+- /* Reset statistics */
+- memset(&priv->channel[WRITE]->prof, 0,
+- sizeof(priv->channel[WRITE]->prof));
+- return count;
+-}
+-
+-static void
+-ctc_netdev_unregister(struct net_device * dev)
+-{
+- struct ctc_priv *privptr;
+-
+- if (!dev)
+- return;
+- privptr = (struct ctc_priv *) dev->priv;
+- unregister_netdev(dev);
+-}
+-
+-static int
+-ctc_netdev_register(struct net_device * dev)
+-{
+- return register_netdev(dev);
+-}
+-
+-static void
+-ctc_free_netdevice(struct net_device * dev, int free_dev)
+-{
+- struct ctc_priv *privptr;
+- if (!dev)
+- return;
+- privptr = dev->priv;
+- if (privptr) {
+- if (privptr->fsm)
+- kfree_fsm(privptr->fsm);
+- kfree(privptr);
+- }
+-#ifdef MODULE
+- if (free_dev)
+- free_netdev(dev);
+-#endif
+-}
+-
+-static ssize_t
+-ctc_proto_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct ctc_priv *priv;
+-
+- priv = dev->driver_data;
+- if (!priv)
+- return -ENODEV;
+-
+- return sprintf(buf, "%d\n", priv->protocol);
+-}
+-
+-static ssize_t
+-ctc_proto_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct ctc_priv *priv;
+- int value;
+-
+- DBF_TEXT(trace, 3, __FUNCTION__);
+- pr_debug("%s() called\n", __FUNCTION__);
+-
+- priv = dev->driver_data;
+- if (!priv)
+- return -ENODEV;
+- sscanf(buf, "%u", &value);
+- if (!((value == CTC_PROTO_S390) ||
+- (value == CTC_PROTO_LINUX) ||
+- (value == CTC_PROTO_OS390)))
+- return -EINVAL;
+- priv->protocol = value;
+-
+- return count;
+-}
+-
+-static ssize_t
+-ctc_type_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct ccwgroup_device *cgdev;
+-
+- cgdev = to_ccwgroupdev(dev);
+- if (!cgdev)
+- return -ENODEV;
+-
+- return sprintf(buf, "%s\n", cu3088_type[cgdev->cdev[0]->id.driver_info]);
+-}
+-
+-static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write);
+-static DEVICE_ATTR(protocol, 0644, ctc_proto_show, ctc_proto_store);
+-static DEVICE_ATTR(type, 0444, ctc_type_show, NULL);
+-
+-static DEVICE_ATTR(loglevel, 0644, loglevel_show, loglevel_write);
+-static DEVICE_ATTR(stats, 0644, stats_show, stats_write);
+-
+-static struct attribute *ctc_attr[] = {
+- &dev_attr_protocol.attr,
+- &dev_attr_type.attr,
+- &dev_attr_buffer.attr,
+- NULL,
+-};
+-
+-static struct attribute_group ctc_attr_group = {
+- .attrs = ctc_attr,
+-};
+-
+-static int
+-ctc_add_attributes(struct device *dev)
+-{
+- int rc;
+-
+- rc = device_create_file(dev, &dev_attr_loglevel);
+- if (rc)
+- goto out;
+- rc = device_create_file(dev, &dev_attr_stats);
+- if (!rc)
+- goto out;
+- device_remove_file(dev, &dev_attr_loglevel);
+-out:
+- return rc;
+-}
+-
+-static void
+-ctc_remove_attributes(struct device *dev)
+-{
+- device_remove_file(dev, &dev_attr_stats);
+- device_remove_file(dev, &dev_attr_loglevel);
+-}
+-
+-static int
+-ctc_add_files(struct device *dev)
+-{
+- pr_debug("%s() called\n", __FUNCTION__);
+-
+- return sysfs_create_group(&dev->kobj, &ctc_attr_group);
+-}
+-
+-static void
+-ctc_remove_files(struct device *dev)
+-{
+- pr_debug("%s() called\n", __FUNCTION__);
+-
+- sysfs_remove_group(&dev->kobj, &ctc_attr_group);
+-}
+-
+-/**
+- * Add ctc specific attributes.
+- * Add ctc private data.
+- *
+- * @param cgdev pointer to ccwgroup_device just added
+- *
+- * @returns 0 on success, !0 on failure.
+- */
+-static int
+-ctc_probe_device(struct ccwgroup_device *cgdev)
+-{
+- struct ctc_priv *priv;
+- int rc;
+- char buffer[16];
+-
+- pr_debug("%s() called\n", __FUNCTION__);
+- DBF_TEXT(setup, 3, __FUNCTION__);
+-
+- if (!get_device(&cgdev->dev))
+- return -ENODEV;
+-
+- priv = kzalloc(sizeof(struct ctc_priv), GFP_KERNEL);
+- if (!priv) {
+- ctc_pr_err("%s: Out of memory\n", __func__);
+- put_device(&cgdev->dev);
+- return -ENOMEM;
+- }
+-
+- rc = ctc_add_files(&cgdev->dev);
+- if (rc) {
+- kfree(priv);
+- put_device(&cgdev->dev);
+- return rc;
+- }
+- priv->buffer_size = CTC_BUFSIZE_DEFAULT;
+- cgdev->cdev[0]->handler = ctc_irq_handler;
+- cgdev->cdev[1]->handler = ctc_irq_handler;
+- cgdev->dev.driver_data = priv;
+-
+- sprintf(buffer, "%p", priv);
+- DBF_TEXT(data, 3, buffer);
+-
+- sprintf(buffer, "%u", (unsigned int)sizeof(struct ctc_priv));
+- DBF_TEXT(data, 3, buffer);
+-
+- sprintf(buffer, "%p", &channels);
+- DBF_TEXT(data, 3, buffer);
+-
+- sprintf(buffer, "%u", (unsigned int)sizeof(struct channel));
+- DBF_TEXT(data, 3, buffer);
+-
+- return 0;
+-}
+-
+-/**
+- * Device setup function called by alloc_netdev().
+- *
+- * @param dev Device to be setup.
+- */
+-void ctc_init_netdevice(struct net_device * dev)
+-{
+- DBF_TEXT(setup, 3, __FUNCTION__);
+-
+- if (dev->mtu == 0)
+- dev->mtu = CTC_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2;
+- dev->hard_start_xmit = ctc_tx;
+- dev->open = ctc_open;
+- dev->stop = ctc_close;
+- dev->get_stats = ctc_stats;
+- dev->change_mtu = ctc_change_mtu;
+- dev->hard_header_len = LL_HEADER_LENGTH + 2;
+- dev->addr_len = 0;
+- dev->type = ARPHRD_SLIP;
+- dev->tx_queue_len = 100;
+- dev->flags = IFF_POINTOPOINT | IFF_NOARP;
+-}
+-
+-
+-/**
+- *
+- * Setup an interface.
+- *
+- * @param cgdev Device to be setup.
+- *
+- * @returns 0 on success, !0 on failure.
+- */
+-static int
+-ctc_new_device(struct ccwgroup_device *cgdev)
+-{
+- char read_id[CTC_ID_SIZE];
+- char write_id[CTC_ID_SIZE];
+- int direction;
+- enum channel_types type;
+- struct ctc_priv *privptr;
+- struct net_device *dev;
+- int ret;
+- char buffer[16];
+-
+- pr_debug("%s() called\n", __FUNCTION__);
+- DBF_TEXT(setup, 3, __FUNCTION__);
+-
+- privptr = cgdev->dev.driver_data;
+- if (!privptr)
+- return -ENODEV;
+-
+- sprintf(buffer, "%d", privptr->buffer_size);
+- DBF_TEXT(setup, 3, buffer);
+-
+- type = get_channel_type(&cgdev->cdev[0]->id);
+-
+- snprintf(read_id, CTC_ID_SIZE, "ch-%s", cgdev->cdev[0]->dev.bus_id);
+- snprintf(write_id, CTC_ID_SIZE, "ch-%s", cgdev->cdev[1]->dev.bus_id);
+-
+- if (add_channel(cgdev->cdev[0], type))
+- return -ENOMEM;
+- if (add_channel(cgdev->cdev[1], type))
+- return -ENOMEM;
+-
+- ret = ccw_device_set_online(cgdev->cdev[0]);
+- if (ret != 0) {
+- printk(KERN_WARNING
+- "ccw_device_set_online (cdev[0]) failed with ret = %d\n", ret);
+- }
+-
+- ret = ccw_device_set_online(cgdev->cdev[1]);
+- if (ret != 0) {
+- printk(KERN_WARNING
+- "ccw_device_set_online (cdev[1]) failed with ret = %d\n", ret);
+- }
+-
+- dev = alloc_netdev(0, "ctc%d", ctc_init_netdevice);
+- if (!dev) {
+- ctc_pr_warn("ctc_init_netdevice failed\n");
+- goto out;
+- }
+- dev->priv = privptr;
+-
+- privptr->fsm = init_fsm("ctcdev", dev_state_names,
+- dev_event_names, CTC_NR_DEV_STATES, CTC_NR_DEV_EVENTS,
+- dev_fsm, DEV_FSM_LEN, GFP_KERNEL);
+- if (privptr->fsm == NULL) {
+- free_netdev(dev);
+- goto out;
+- }
+- fsm_newstate(privptr->fsm, DEV_STATE_STOPPED);
+- fsm_settimer(privptr->fsm, &privptr->restart_timer);
+-
+- for (direction = READ; direction <= WRITE; direction++) {
+- privptr->channel[direction] =
+- channel_get(type, direction == READ ? read_id : write_id,
+- direction);
+- if (privptr->channel[direction] == NULL) {
+- if (direction == WRITE)
+- channel_free(privptr->channel[READ]);
+-
+- ctc_free_netdevice(dev, 1);
+- goto out;
+- }
+- privptr->channel[direction]->netdev = dev;
+- privptr->channel[direction]->protocol = privptr->protocol;
+- privptr->channel[direction]->max_bufsize = privptr->buffer_size;
+- }
+- /* sysfs magic */
+- SET_NETDEV_DEV(dev, &cgdev->dev);
+-
+- if (ctc_netdev_register(dev) != 0) {
+- ctc_free_netdevice(dev, 1);
+- goto out;
+- }
+-
+- if (ctc_add_attributes(&cgdev->dev)) {
+- ctc_netdev_unregister(dev);
+- dev->priv = NULL;
+- ctc_free_netdevice(dev, 1);
+- goto out;
+- }
+-
+- strlcpy(privptr->fsm->name, dev->name, sizeof (privptr->fsm->name));
+-
+- print_banner();
+-
+- ctc_pr_info("%s: read: %s, write: %s, proto: %d\n",
+- dev->name, privptr->channel[READ]->id,
+- privptr->channel[WRITE]->id, privptr->protocol);
+-
+- return 0;
+-out:
+- ccw_device_set_offline(cgdev->cdev[1]);
+- ccw_device_set_offline(cgdev->cdev[0]);
+-
+- return -ENODEV;
+-}
+-
+-/**
+- * Shutdown an interface.
+- *
+- * @param cgdev Device to be shut down.
+- *
+- * @returns 0 on success, !0 on failure.
+- */
+-static int
+-ctc_shutdown_device(struct ccwgroup_device *cgdev)
+-{
+- struct ctc_priv *priv;
+- struct net_device *ndev;
+-
+- DBF_TEXT(setup, 3, __FUNCTION__);
+- pr_debug("%s() called\n", __FUNCTION__);
+-
+-
+- priv = cgdev->dev.driver_data;
+- ndev = NULL;
+- if (!priv)
+- return -ENODEV;
+-
+- if (priv->channel[READ]) {
+- ndev = priv->channel[READ]->netdev;
+-
+- /* Close the device */
+- ctc_close(ndev);
+- ndev->flags &=~IFF_RUNNING;
+-
+- ctc_remove_attributes(&cgdev->dev);
+-
+- channel_free(priv->channel[READ]);
+- }
+- if (priv->channel[WRITE])
+- channel_free(priv->channel[WRITE]);
+-
+- if (ndev) {
+- ctc_netdev_unregister(ndev);
+- ndev->priv = NULL;
+- ctc_free_netdevice(ndev, 1);
+- }
+-
+- if (priv->fsm)
+- kfree_fsm(priv->fsm);
+-
+- ccw_device_set_offline(cgdev->cdev[1]);
+- ccw_device_set_offline(cgdev->cdev[0]);
+-
+- if (priv->channel[READ])
+- channel_remove(priv->channel[READ]);
+- if (priv->channel[WRITE])
+- channel_remove(priv->channel[WRITE]);
+- priv->channel[READ] = priv->channel[WRITE] = NULL;
+-
+- return 0;
+-
+-}
+-
+-static void
+-ctc_remove_device(struct ccwgroup_device *cgdev)
+-{
+- struct ctc_priv *priv;
+-
+- pr_debug("%s() called\n", __FUNCTION__);
+- DBF_TEXT(setup, 3, __FUNCTION__);
+-
+- priv = cgdev->dev.driver_data;
+- if (!priv)
+- return;
+- if (cgdev->state == CCWGROUP_ONLINE)
+- ctc_shutdown_device(cgdev);
+- ctc_remove_files(&cgdev->dev);
+- cgdev->dev.driver_data = NULL;
+- kfree(priv);
+- put_device(&cgdev->dev);
+-}
+-
+-static struct ccwgroup_driver ctc_group_driver = {
+- .owner = THIS_MODULE,
+- .name = "ctc",
+- .max_slaves = 2,
+- .driver_id = 0xC3E3C3,
+- .probe = ctc_probe_device,
+- .remove = ctc_remove_device,
+- .set_online = ctc_new_device,
+- .set_offline = ctc_shutdown_device,
+-};
+-
+-/**
+- * Module related routines
+- *****************************************************************************/
+-
+-/**
+- * Prepare to be unloaded. Free IRQ's and release all resources.
+- * This is called just before this module is unloaded. It is
+- * <em>not</em> called, if the usage count is !0, so we don't need to check
+- * for that.
+- */
+-static void __exit
+-ctc_exit(void)
+-{
+- DBF_TEXT(setup, 3, __FUNCTION__);
+- unregister_cu3088_discipline(&ctc_group_driver);
+- ctc_unregister_dbf_views();
+- ctc_pr_info("CTC driver unloaded\n");
+-}
+-
+-/**
+- * Initialize module.
+- * This is called just after the module is loaded.
+- *
+- * @return 0 on success, !0 on error.
+- */
+-static int __init
+-ctc_init(void)
+-{
+- int ret = 0;
+-
+- loglevel = CTC_LOGLEVEL_DEFAULT;
+-
+- DBF_TEXT(setup, 3, __FUNCTION__);
+-
+- print_banner();
+-
+- ret = ctc_register_dbf_views();
+- if (ret){
+- ctc_pr_crit("ctc_init failed with ctc_register_dbf_views rc = %d\n", ret);
+- return ret;
+- }
+- ret = register_cu3088_discipline(&ctc_group_driver);
+- if (ret) {
+- ctc_unregister_dbf_views();
+- }
+- return ret;
+-}
+-
+-module_init(ctc_init);
+-module_exit(ctc_exit);
+-
+-/* --- This is the END my friend --- */
+diff --git a/drivers/s390/net/ctcmain.h b/drivers/s390/net/ctcmain.h
+deleted file mode 100644
+index 7f305d1..0000000
+--- a/drivers/s390/net/ctcmain.h
++++ /dev/null
+@@ -1,270 +0,0 @@
+-/*
+- * CTC / ESCON network driver
+- *
+- * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
+- * Author(s): Fritz Elfert (elfert at de.ibm.com, felfert at millenux.com)
+- Peter Tiedemann (ptiedem at de.ibm.com)
+- *
+- *
+- * Documentation used:
+- * - Principles of Operation (IBM doc#: SA22-7201-06)
+- * - Common IO/-Device Commands and Self Description (IBM doc#: SA22-7204-02)
+- * - Common IO/-Device Commands and Self Description (IBM doc#: SN22-5535)
+- * - ESCON Channel-to-Channel Adapter (IBM doc#: SA22-7203-00)
+- * - ESCON I/O Interface (IBM doc#: SA22-7202-029
+- *
+- * 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, or (at your option)
+- * any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- *
+- */
+-
+-#ifndef _CTCMAIN_H_
+-#define _CTCMAIN_H_
+-
+-#include <asm/ccwdev.h>
+-#include <asm/ccwgroup.h>
+-
+-#include <linux/skbuff.h>
+-#include <linux/netdevice.h>
+-
+-#include "fsm.h"
+-#include "cu3088.h"
+-
+-
+-/**
+- * CCW commands, used in this driver.
+- */
+-#define CCW_CMD_WRITE 0x01
+-#define CCW_CMD_READ 0x02
+-#define CCW_CMD_SET_EXTENDED 0xc3
+-#define CCW_CMD_PREPARE 0xe3
+-
+-#define CTC_PROTO_S390 0
+-#define CTC_PROTO_LINUX 1
+-#define CTC_PROTO_OS390 3
+-
+-#define CTC_BUFSIZE_LIMIT 65535
+-#define CTC_BUFSIZE_DEFAULT 32768
+-
+-#define CTC_TIMEOUT_5SEC 5000
+-
+-#define CTC_INITIAL_BLOCKLEN 2
+-
+-#define READ 0
+-#define WRITE 1
+-
+-#define CTC_ID_SIZE BUS_ID_SIZE+3
+-
+-
+-struct ctc_profile {
+- unsigned long maxmulti;
+- unsigned long maxcqueue;
+- unsigned long doios_single;
+- unsigned long doios_multi;
+- unsigned long txlen;
+- unsigned long tx_time;
+- struct timespec send_stamp;
+-};
+-
+-/**
+- * Definition of one channel
+- */
+-struct channel {
+-
+- /**
+- * Pointer to next channel in list.
+- */
+- struct channel *next;
+- char id[CTC_ID_SIZE];
+- struct ccw_device *cdev;
+-
+- /**
+- * Type of this channel.
+- * CTC/A or Escon for valid channels.
+- */
+- enum channel_types type;
+-
+- /**
+- * Misc. flags. See CHANNEL_FLAGS_... below
+- */
+- __u32 flags;
+-
+- /**
+- * The protocol of this channel
+- */
+- __u16 protocol;
+-
+- /**
+- * I/O and irq related stuff
+- */
+- struct ccw1 *ccw;
+- struct irb *irb;
+-
+- /**
+- * RX/TX buffer size
+- */
+- int max_bufsize;
+-
+- /**
+- * Transmit/Receive buffer.
+- */
+- struct sk_buff *trans_skb;
+-
+- /**
+- * Universal I/O queue.
+- */
+- struct sk_buff_head io_queue;
+-
+- /**
+- * TX queue for collecting skb's during busy.
+- */
+- struct sk_buff_head collect_queue;
+-
+- /**
+- * Amount of data in collect_queue.
+- */
+- int collect_len;
+-
+- /**
+- * spinlock for collect_queue and collect_len
+- */
+- spinlock_t collect_lock;
+-
+- /**
+- * Timer for detecting unresposive
+- * I/O operations.
+- */
+- fsm_timer timer;
+-
+- /**
+- * Retry counter for misc. operations.
+- */
+- int retry;
+-
+- /**
+- * The finite state machine of this channel
+- */
+- fsm_instance *fsm;
+-
+- /**
+- * The corresponding net_device this channel
+- * belongs to.
+- */
+- struct net_device *netdev;
+-
+- struct ctc_profile prof;
+-
+- unsigned char *trans_skb_data;
+-
+- __u16 logflags;
+-};
+-
+-#define CHANNEL_FLAGS_READ 0
+-#define CHANNEL_FLAGS_WRITE 1
+-#define CHANNEL_FLAGS_INUSE 2
+-#define CHANNEL_FLAGS_BUFSIZE_CHANGED 4
+-#define CHANNEL_FLAGS_FAILED 8
+-#define CHANNEL_FLAGS_WAITIRQ 16
+-#define CHANNEL_FLAGS_RWMASK 1
+-#define CHANNEL_DIRECTION(f) (f & CHANNEL_FLAGS_RWMASK)
+-
+-#define LOG_FLAG_ILLEGALPKT 1
+-#define LOG_FLAG_ILLEGALSIZE 2
+-#define LOG_FLAG_OVERRUN 4
+-#define LOG_FLAG_NOMEM 8
+-
+-#define CTC_LOGLEVEL_INFO 1
+-#define CTC_LOGLEVEL_NOTICE 2
+-#define CTC_LOGLEVEL_WARN 4
+-#define CTC_LOGLEVEL_EMERG 8
+-#define CTC_LOGLEVEL_ERR 16
+-#define CTC_LOGLEVEL_DEBUG 32
+-#define CTC_LOGLEVEL_CRIT 64
+-
+-#define CTC_LOGLEVEL_DEFAULT \
+-(CTC_LOGLEVEL_INFO | CTC_LOGLEVEL_NOTICE | CTC_LOGLEVEL_WARN | CTC_LOGLEVEL_CRIT)
+-
+-#define CTC_LOGLEVEL_MAX ((CTC_LOGLEVEL_CRIT<<1)-1)
+-
+-#define ctc_pr_debug(fmt, arg...) \
+-do { if (loglevel & CTC_LOGLEVEL_DEBUG) printk(KERN_DEBUG fmt,##arg); } while (0)
+-
+-#define ctc_pr_info(fmt, arg...) \
+-do { if (loglevel & CTC_LOGLEVEL_INFO) printk(KERN_INFO fmt,##arg); } while (0)
+-
+-#define ctc_pr_notice(fmt, arg...) \
+-do { if (loglevel & CTC_LOGLEVEL_NOTICE) printk(KERN_NOTICE fmt,##arg); } while (0)
+-
+-#define ctc_pr_warn(fmt, arg...) \
+-do { if (loglevel & CTC_LOGLEVEL_WARN) printk(KERN_WARNING fmt,##arg); } while (0)
+-
+-#define ctc_pr_emerg(fmt, arg...) \
+-do { if (loglevel & CTC_LOGLEVEL_EMERG) printk(KERN_EMERG fmt,##arg); } while (0)
+-
+-#define ctc_pr_err(fmt, arg...) \
+-do { if (loglevel & CTC_LOGLEVEL_ERR) printk(KERN_ERR fmt,##arg); } while (0)
+-
+-#define ctc_pr_crit(fmt, arg...) \
+-do { if (loglevel & CTC_LOGLEVEL_CRIT) printk(KERN_CRIT fmt,##arg); } while (0)
+-
+-struct ctc_priv {
+- struct net_device_stats stats;
+- unsigned long tbusy;
+- /**
+- * The finite state machine of this interface.
+- */
+- fsm_instance *fsm;
+- /**
+- * The protocol of this device
+- */
+- __u16 protocol;
+- /**
+- * Timer for restarting after I/O Errors
+- */
+- fsm_timer restart_timer;
+-
+- int buffer_size;
+-
+- struct channel *channel[2];
+-};
+-
+-/**
+- * Definition of our link level header.
+- */
+-struct ll_header {
+- __u16 length;
+- __u16 type;
+- __u16 unused;
+-};
+-#define LL_HEADER_LENGTH (sizeof(struct ll_header))
+-
+-/**
+- * Compatibility macros for busy handling
+- * of network devices.
+- */
+-static __inline__ void
+-ctc_clear_busy(struct net_device * dev)
+-{
+- clear_bit(0, &(((struct ctc_priv *) dev->priv)->tbusy));
+- netif_wake_queue(dev);
+-}
+-
+-static __inline__ int
+-ctc_test_and_set_busy(struct net_device * dev)
+-{
+- netif_stop_queue(dev);
+- return test_and_set_bit(0, &((struct ctc_priv *) dev->priv)->tbusy);
+-}
+-
+-#endif
+diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
+index 874a199..8f876f6 100644
+--- a/drivers/s390/net/netiucv.c
++++ b/drivers/s390/net/netiucv.c
+@@ -670,7 +670,7 @@ static void conn_action_rx(fsm_instance *fi, int event, void *arg)
+ struct netiucv_priv *privptr = netdev_priv(conn->netdev);
+ int rc;
+
+- IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 4, __func__);
+
+ if (!conn->netdev) {
+ iucv_message_reject(conn->path, msg);
+@@ -718,7 +718,7 @@ static void conn_action_txdone(fsm_instance *fi, int event, void *arg)
+ struct ll_header header;
+ int rc;
+
+- IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 4, __func__);
+
+ if (conn && conn->netdev)
+ privptr = netdev_priv(conn->netdev);
+@@ -799,7 +799,7 @@ static void conn_action_connaccept(fsm_instance *fi, int event, void *arg)
+ struct netiucv_priv *privptr = netdev_priv(netdev);
+ int rc;
+
+- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 3, __func__);
+
+ conn->path = path;
+ path->msglim = NETIUCV_QUEUELEN_DEFAULT;
+@@ -821,7 +821,7 @@ static void conn_action_connreject(fsm_instance *fi, int event, void *arg)
+ struct iucv_event *ev = arg;
+ struct iucv_path *path = ev->data;
+
+- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 3, __func__);
+ iucv_path_sever(path, NULL);
+ }
+
+@@ -831,7 +831,7 @@ static void conn_action_connack(fsm_instance *fi, int event, void *arg)
+ struct net_device *netdev = conn->netdev;
+ struct netiucv_priv *privptr = netdev_priv(netdev);
+
+- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 3, __func__);
+ fsm_deltimer(&conn->timer);
+ fsm_newstate(fi, CONN_STATE_IDLE);
+ netdev->tx_queue_len = conn->path->msglim;
+@@ -842,7 +842,7 @@ static void conn_action_conntimsev(fsm_instance *fi, int event, void *arg)
+ {
+ struct iucv_connection *conn = arg;
+
+- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 3, __func__);
+ fsm_deltimer(&conn->timer);
+ iucv_path_sever(conn->path, NULL);
+ fsm_newstate(fi, CONN_STATE_STARTWAIT);
+@@ -854,7 +854,7 @@ static void conn_action_connsever(fsm_instance *fi, int event, void *arg)
+ struct net_device *netdev = conn->netdev;
+ struct netiucv_priv *privptr = netdev_priv(netdev);
+
+- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 3, __func__);
+
+ fsm_deltimer(&conn->timer);
+ iucv_path_sever(conn->path, NULL);
+@@ -870,7 +870,7 @@ static void conn_action_start(fsm_instance *fi, int event, void *arg)
+ struct iucv_connection *conn = arg;
+ int rc;
+
+- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 3, __func__);
+
+ fsm_newstate(fi, CONN_STATE_STARTWAIT);
+ PRINT_DEBUG("%s('%s'): connecting ...\n",
+@@ -948,7 +948,7 @@ static void conn_action_stop(fsm_instance *fi, int event, void *arg)
+ struct net_device *netdev = conn->netdev;
+ struct netiucv_priv *privptr = netdev_priv(netdev);
+
+- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 3, __func__);
+
+ fsm_deltimer(&conn->timer);
+ fsm_newstate(fi, CONN_STATE_STOPPED);
+@@ -1024,7 +1024,7 @@ static void dev_action_start(fsm_instance *fi, int event, void *arg)
+ struct net_device *dev = arg;
+ struct netiucv_priv *privptr = netdev_priv(dev);
+
+- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 3, __func__);
+
+ fsm_newstate(fi, DEV_STATE_STARTWAIT);
+ fsm_event(privptr->conn->fsm, CONN_EVENT_START, privptr->conn);
+@@ -1044,7 +1044,7 @@ dev_action_stop(fsm_instance *fi, int event, void *arg)
+ struct netiucv_priv *privptr = netdev_priv(dev);
+ struct iucv_event ev;
+
+- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 3, __func__);
+
+ ev.conn = privptr->conn;
+
+@@ -1066,7 +1066,7 @@ dev_action_connup(fsm_instance *fi, int event, void *arg)
+ struct net_device *dev = arg;
+ struct netiucv_priv *privptr = netdev_priv(dev);
+
+- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 3, __func__);
+
+ switch (fsm_getstate(fi)) {
+ case DEV_STATE_STARTWAIT:
+@@ -1097,7 +1097,7 @@ dev_action_connup(fsm_instance *fi, int event, void *arg)
+ static void
+ dev_action_conndown(fsm_instance *fi, int event, void *arg)
+ {
+- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 3, __func__);
+
+ switch (fsm_getstate(fi)) {
+ case DEV_STATE_RUNNING:
+@@ -1288,7 +1288,7 @@ static int netiucv_tx(struct sk_buff *skb, struct net_device *dev)
+ struct netiucv_priv *privptr = netdev_priv(dev);
+ int rc;
+
+- IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 4, __func__);
+ /**
+ * Some sanity checks ...
+ */
+@@ -1344,7 +1344,7 @@ static struct net_device_stats *netiucv_stats (struct net_device * dev)
+ {
+ struct netiucv_priv *priv = netdev_priv(dev);
+
+- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 5, __func__);
+ return &priv->stats;
+ }
+
+@@ -1360,7 +1360,7 @@ static struct net_device_stats *netiucv_stats (struct net_device * dev)
+ */
+ static int netiucv_change_mtu(struct net_device * dev, int new_mtu)
+ {
+- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 3, __func__);
+ if (new_mtu < 576 || new_mtu > NETIUCV_MTU_MAX) {
+ IUCV_DBF_TEXT(setup, 2, "given MTU out of valid range\n");
+ return -EINVAL;
+@@ -1378,7 +1378,7 @@ static ssize_t user_show(struct device *dev, struct device_attribute *attr,
+ {
+ struct netiucv_priv *priv = dev->driver_data;
+
+- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 5, __func__);
+ return sprintf(buf, "%s\n", netiucv_printname(priv->conn->userid));
+ }
+
+@@ -1393,7 +1393,7 @@ static ssize_t user_write(struct device *dev, struct device_attribute *attr,
+ int i;
+ struct iucv_connection *cp;
+
+- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 3, __func__);
+ if (count > 9) {
+ PRINT_WARN("netiucv: username too long (%d)!\n", (int) count);
+ IUCV_DBF_TEXT_(setup, 2,
+@@ -1449,7 +1449,7 @@ static ssize_t buffer_show (struct device *dev, struct device_attribute *attr,
+ char *buf)
+ { struct netiucv_priv *priv = dev->driver_data;
+
+- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 5, __func__);
+ return sprintf(buf, "%d\n", priv->conn->max_buffsize);
+ }
+
+@@ -1461,7 +1461,7 @@ static ssize_t buffer_write (struct device *dev, struct device_attribute *attr,
+ char *e;
+ int bs1;
+
+- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 3, __func__);
+ if (count >= 39)
+ return -EINVAL;
+
+@@ -1513,7 +1513,7 @@ static ssize_t dev_fsm_show (struct device *dev, struct device_attribute *attr,
+ {
+ struct netiucv_priv *priv = dev->driver_data;
+
+- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 5, __func__);
+ return sprintf(buf, "%s\n", fsm_getstate_str(priv->fsm));
+ }
+
+@@ -1524,7 +1524,7 @@ static ssize_t conn_fsm_show (struct device *dev,
+ {
+ struct netiucv_priv *priv = dev->driver_data;
+
+- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 5, __func__);
+ return sprintf(buf, "%s\n", fsm_getstate_str(priv->conn->fsm));
+ }
+
+@@ -1535,7 +1535,7 @@ static ssize_t maxmulti_show (struct device *dev,
+ {
+ struct netiucv_priv *priv = dev->driver_data;
+
+- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 5, __func__);
+ return sprintf(buf, "%ld\n", priv->conn->prof.maxmulti);
+ }
+
+@@ -1545,7 +1545,7 @@ static ssize_t maxmulti_write (struct device *dev,
+ {
+ struct netiucv_priv *priv = dev->driver_data;
+
+- IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 4, __func__);
+ priv->conn->prof.maxmulti = 0;
+ return count;
+ }
+@@ -1557,7 +1557,7 @@ static ssize_t maxcq_show (struct device *dev, struct device_attribute *attr,
+ {
+ struct netiucv_priv *priv = dev->driver_data;
+
+- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 5, __func__);
+ return sprintf(buf, "%ld\n", priv->conn->prof.maxcqueue);
+ }
+
+@@ -1566,7 +1566,7 @@ static ssize_t maxcq_write (struct device *dev, struct device_attribute *attr,
+ {
+ struct netiucv_priv *priv = dev->driver_data;
+
+- IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 4, __func__);
+ priv->conn->prof.maxcqueue = 0;
+ return count;
+ }
+@@ -1578,7 +1578,7 @@ static ssize_t sdoio_show (struct device *dev, struct device_attribute *attr,
+ {
+ struct netiucv_priv *priv = dev->driver_data;
+
+- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 5, __func__);
+ return sprintf(buf, "%ld\n", priv->conn->prof.doios_single);
+ }
+
+@@ -1587,7 +1587,7 @@ static ssize_t sdoio_write (struct device *dev, struct device_attribute *attr,
+ {
+ struct netiucv_priv *priv = dev->driver_data;
+
+- IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 4, __func__);
+ priv->conn->prof.doios_single = 0;
+ return count;
+ }
+@@ -1599,7 +1599,7 @@ static ssize_t mdoio_show (struct device *dev, struct device_attribute *attr,
+ {
+ struct netiucv_priv *priv = dev->driver_data;
+
+- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 5, __func__);
+ return sprintf(buf, "%ld\n", priv->conn->prof.doios_multi);
+ }
+
+@@ -1608,7 +1608,7 @@ static ssize_t mdoio_write (struct device *dev, struct device_attribute *attr,
+ {
+ struct netiucv_priv *priv = dev->driver_data;
+
+- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 5, __func__);
+ priv->conn->prof.doios_multi = 0;
+ return count;
+ }
+@@ -1620,7 +1620,7 @@ static ssize_t txlen_show (struct device *dev, struct device_attribute *attr,
+ {
+ struct netiucv_priv *priv = dev->driver_data;
+
+- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 5, __func__);
+ return sprintf(buf, "%ld\n", priv->conn->prof.txlen);
+ }
+
+@@ -1629,7 +1629,7 @@ static ssize_t txlen_write (struct device *dev, struct device_attribute *attr,
+ {
+ struct netiucv_priv *priv = dev->driver_data;
+
+- IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 4, __func__);
+ priv->conn->prof.txlen = 0;
+ return count;
+ }
+@@ -1641,7 +1641,7 @@ static ssize_t txtime_show (struct device *dev, struct device_attribute *attr,
+ {
+ struct netiucv_priv *priv = dev->driver_data;
+
+- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 5, __func__);
+ return sprintf(buf, "%ld\n", priv->conn->prof.tx_time);
+ }
+
+@@ -1650,7 +1650,7 @@ static ssize_t txtime_write (struct device *dev, struct device_attribute *attr,
+ {
+ struct netiucv_priv *priv = dev->driver_data;
+
+- IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 4, __func__);
+ priv->conn->prof.tx_time = 0;
+ return count;
+ }
+@@ -1662,7 +1662,7 @@ static ssize_t txpend_show (struct device *dev, struct device_attribute *attr,
+ {
+ struct netiucv_priv *priv = dev->driver_data;
+
+- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 5, __func__);
+ return sprintf(buf, "%ld\n", priv->conn->prof.tx_pending);
+ }
+
+@@ -1671,7 +1671,7 @@ static ssize_t txpend_write (struct device *dev, struct device_attribute *attr,
+ {
+ struct netiucv_priv *priv = dev->driver_data;
+
+- IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 4, __func__);
+ priv->conn->prof.tx_pending = 0;
+ return count;
+ }
+@@ -1683,7 +1683,7 @@ static ssize_t txmpnd_show (struct device *dev, struct device_attribute *attr,
+ {
+ struct netiucv_priv *priv = dev->driver_data;
+
+- IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 5, __func__);
+ return sprintf(buf, "%ld\n", priv->conn->prof.tx_max_pending);
+ }
+
+@@ -1692,7 +1692,7 @@ static ssize_t txmpnd_write (struct device *dev, struct device_attribute *attr,
+ {
+ struct netiucv_priv *priv = dev->driver_data;
+
+- IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 4, __func__);
+ priv->conn->prof.tx_max_pending = 0;
+ return count;
+ }
+@@ -1732,7 +1732,7 @@ static int netiucv_add_files(struct device *dev)
+ {
+ int ret;
+
+- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 3, __func__);
+ ret = sysfs_create_group(&dev->kobj, &netiucv_attr_group);
+ if (ret)
+ return ret;
+@@ -1744,7 +1744,7 @@ static int netiucv_add_files(struct device *dev)
+
+ static void netiucv_remove_files(struct device *dev)
+ {
+- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 3, __func__);
+ sysfs_remove_group(&dev->kobj, &netiucv_stat_attr_group);
+ sysfs_remove_group(&dev->kobj, &netiucv_attr_group);
+ }
+@@ -1756,7 +1756,7 @@ static int netiucv_register_device(struct net_device *ndev)
+ int ret;
+
+
+- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 3, __func__);
+
+ if (dev) {
+ snprintf(dev->bus_id, BUS_ID_SIZE, "net%s", ndev->name);
+@@ -1792,7 +1792,7 @@ out_unreg:
+
+ static void netiucv_unregister_device(struct device *dev)
+ {
+- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 3, __func__);
+ netiucv_remove_files(dev);
+ device_unregister(dev);
+ }
+@@ -1857,7 +1857,7 @@ out:
+ */
+ static void netiucv_remove_connection(struct iucv_connection *conn)
+ {
+- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 3, __func__);
+ write_lock_bh(&iucv_connection_rwlock);
+ list_del_init(&conn->list);
+ write_unlock_bh(&iucv_connection_rwlock);
+@@ -1881,7 +1881,7 @@ static void netiucv_free_netdevice(struct net_device *dev)
+ {
+ struct netiucv_priv *privptr = netdev_priv(dev);
+
+- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 3, __func__);
+
+ if (!dev)
+ return;
+@@ -1963,7 +1963,7 @@ static ssize_t conn_write(struct device_driver *drv,
+ struct netiucv_priv *priv;
+ struct iucv_connection *cp;
+
+- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 3, __func__);
+ if (count>9) {
+ PRINT_WARN("netiucv: username too long (%d)!\n", (int)count);
+ IUCV_DBF_TEXT(setup, 2, "conn_write: too long\n");
+@@ -2048,7 +2048,7 @@ static ssize_t remove_write (struct device_driver *drv,
+ const char *p;
+ int i;
+
+- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 3, __func__);
+
+ if (count >= IFNAMSIZ)
+ count = IFNAMSIZ - 1;;
+@@ -2116,7 +2116,7 @@ static void __exit netiucv_exit(void)
+ struct netiucv_priv *priv;
+ struct device *dev;
+
+- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
++ IUCV_DBF_TEXT(trace, 3, __func__);
+ while (!list_empty(&iucv_connection_list)) {
+ cp = list_entry(iucv_connection_list.next,
+ struct iucv_connection, list);
+@@ -2146,8 +2146,7 @@ static int __init netiucv_init(void)
+ rc = iucv_register(&netiucv_handler, 1);
+ if (rc)
+ goto out_dbf;
+- IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
+- netiucv_driver.groups = netiucv_drv_attr_groups;
++ IUCV_DBF_TEXT(trace, 3, __func__);
+ rc = driver_register(&netiucv_driver);
+ if (rc) {
+ PRINT_ERR("NETIUCV: failed to register driver.\n");
+diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
+deleted file mode 100644
+index 8c6b72d..0000000
+--- a/drivers/s390/net/qeth.h
++++ /dev/null
+@@ -1,1253 +0,0 @@
+-#ifndef __QETH_H__
+-#define __QETH_H__
+-
+-#include <linux/if.h>
+-#include <linux/if_arp.h>
+-
+-#include <linux/if_tr.h>
+-#include <linux/trdevice.h>
+-#include <linux/etherdevice.h>
+-#include <linux/if_vlan.h>
+-#include <linux/ctype.h>
+-
+-#include <net/ipv6.h>
+-#include <linux/in6.h>
+-#include <net/if_inet6.h>
+-#include <net/addrconf.h>
+-
+-
+-#include <linux/bitops.h>
+-
+-#include <asm/debug.h>
+-#include <asm/qdio.h>
+-#include <asm/ccwdev.h>
+-#include <asm/ccwgroup.h>
+-
+-#include "qeth_mpc.h"
+-
+-#ifdef CONFIG_QETH_IPV6
+-#define QETH_VERSION_IPV6 ":IPv6"
+-#else
+-#define QETH_VERSION_IPV6 ""
+-#endif
+-#ifdef CONFIG_QETH_VLAN
+-#define QETH_VERSION_VLAN ":VLAN"
+-#else
+-#define QETH_VERSION_VLAN ""
+-#endif
+-
+-/**
+- * Debug Facility stuff
+- */
+-#define QETH_DBF_SETUP_NAME "qeth_setup"
+-#define QETH_DBF_SETUP_LEN 8
+-#define QETH_DBF_SETUP_PAGES 8
+-#define QETH_DBF_SETUP_NR_AREAS 1
+-#define QETH_DBF_SETUP_LEVEL 5
+-
+-#define QETH_DBF_MISC_NAME "qeth_misc"
+-#define QETH_DBF_MISC_LEN 128
+-#define QETH_DBF_MISC_PAGES 2
+-#define QETH_DBF_MISC_NR_AREAS 1
+-#define QETH_DBF_MISC_LEVEL 2
+-
+-#define QETH_DBF_DATA_NAME "qeth_data"
+-#define QETH_DBF_DATA_LEN 96
+-#define QETH_DBF_DATA_PAGES 8
+-#define QETH_DBF_DATA_NR_AREAS 1
+-#define QETH_DBF_DATA_LEVEL 2
+-
+-#define QETH_DBF_CONTROL_NAME "qeth_control"
+-#define QETH_DBF_CONTROL_LEN 256
+-#define QETH_DBF_CONTROL_PAGES 8
+-#define QETH_DBF_CONTROL_NR_AREAS 2
+-#define QETH_DBF_CONTROL_LEVEL 5
+-
+-#define QETH_DBF_TRACE_NAME "qeth_trace"
+-#define QETH_DBF_TRACE_LEN 8
+-#define QETH_DBF_TRACE_PAGES 4
+-#define QETH_DBF_TRACE_NR_AREAS 2
+-#define QETH_DBF_TRACE_LEVEL 3
+-extern debug_info_t *qeth_dbf_trace;
+-
+-#define QETH_DBF_SENSE_NAME "qeth_sense"
+-#define QETH_DBF_SENSE_LEN 64
+-#define QETH_DBF_SENSE_PAGES 2
+-#define QETH_DBF_SENSE_NR_AREAS 1
+-#define QETH_DBF_SENSE_LEVEL 2
+-
+-#define QETH_DBF_QERR_NAME "qeth_qerr"
+-#define QETH_DBF_QERR_LEN 8
+-#define QETH_DBF_QERR_PAGES 2
+-#define QETH_DBF_QERR_NR_AREAS 2
+-#define QETH_DBF_QERR_LEVEL 2
+-
+-#define QETH_DBF_TEXT(name,level,text) \
+- do { \
+- debug_text_event(qeth_dbf_##name,level,text); \
+- } while (0)
+-
+-#define QETH_DBF_HEX(name,level,addr,len) \
+- do { \
+- debug_event(qeth_dbf_##name,level,(void*)(addr),len); \
+- } while (0)
+-
+-DECLARE_PER_CPU(char[256], qeth_dbf_txt_buf);
+-
+-#define QETH_DBF_TEXT_(name,level,text...) \
+- do { \
+- char* dbf_txt_buf = get_cpu_var(qeth_dbf_txt_buf); \
+- sprintf(dbf_txt_buf, text); \
+- debug_text_event(qeth_dbf_##name,level,dbf_txt_buf); \
+- put_cpu_var(qeth_dbf_txt_buf); \
+- } while (0)
+-
+-#define QETH_DBF_SPRINTF(name,level,text...) \
+- do { \
+- debug_sprintf_event(qeth_dbf_trace, level, ##text ); \
+- debug_sprintf_event(qeth_dbf_trace, level, text ); \
+- } while (0)
+-
+-/**
+- * some more debug stuff
+- */
+-#define PRINTK_HEADER "qeth: "
+-
+-#define HEXDUMP16(importance,header,ptr) \
+-PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \
+- "%02x %02x %02x %02x %02x %02x %02x %02x\n", \
+- *(((char*)ptr)),*(((char*)ptr)+1),*(((char*)ptr)+2), \
+- *(((char*)ptr)+3),*(((char*)ptr)+4),*(((char*)ptr)+5), \
+- *(((char*)ptr)+6),*(((char*)ptr)+7),*(((char*)ptr)+8), \
+- *(((char*)ptr)+9),*(((char*)ptr)+10),*(((char*)ptr)+11), \
+- *(((char*)ptr)+12),*(((char*)ptr)+13), \
+- *(((char*)ptr)+14),*(((char*)ptr)+15)); \
+-PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \
+- "%02x %02x %02x %02x %02x %02x %02x %02x\n", \
+- *(((char*)ptr)+16),*(((char*)ptr)+17), \
+- *(((char*)ptr)+18),*(((char*)ptr)+19), \
+- *(((char*)ptr)+20),*(((char*)ptr)+21), \
+- *(((char*)ptr)+22),*(((char*)ptr)+23), \
+- *(((char*)ptr)+24),*(((char*)ptr)+25), \
+- *(((char*)ptr)+26),*(((char*)ptr)+27), \
+- *(((char*)ptr)+28),*(((char*)ptr)+29), \
+- *(((char*)ptr)+30),*(((char*)ptr)+31));
+-
+-static inline void
+-qeth_hex_dump(unsigned char *buf, size_t len)
+-{
+- size_t i;
+-
+- for (i = 0; i < len; i++) {
+- if (i && !(i % 16))
+- printk("\n");
+- printk("%02x ", *(buf + i));
+- }
+- printk("\n");
+-}
+-
+-#define SENSE_COMMAND_REJECT_BYTE 0
+-#define SENSE_COMMAND_REJECT_FLAG 0x80
+-#define SENSE_RESETTING_EVENT_BYTE 1
+-#define SENSE_RESETTING_EVENT_FLAG 0x80
+-
+-/*
+- * Common IO related definitions
+- */
+-extern struct device *qeth_root_dev;
+-extern struct ccw_driver qeth_ccw_driver;
+-extern struct ccwgroup_driver qeth_ccwgroup_driver;
+-
+-#define CARD_RDEV(card) card->read.ccwdev
+-#define CARD_WDEV(card) card->write.ccwdev
+-#define CARD_DDEV(card) card->data.ccwdev
+-#define CARD_BUS_ID(card) card->gdev->dev.bus_id
+-#define CARD_RDEV_ID(card) card->read.ccwdev->dev.bus_id
+-#define CARD_WDEV_ID(card) card->write.ccwdev->dev.bus_id
+-#define CARD_DDEV_ID(card) card->data.ccwdev->dev.bus_id
+-#define CHANNEL_ID(channel) channel->ccwdev->dev.bus_id
+-
+-#define CARD_FROM_CDEV(cdev) (struct qeth_card *) \
+- ((struct ccwgroup_device *)cdev->dev.driver_data)\
+- ->dev.driver_data;
+-
+-/**
+- * card stuff
+- */
+-struct qeth_perf_stats {
+- unsigned int bufs_rec;
+- unsigned int bufs_sent;
+-
+- unsigned int skbs_sent_pack;
+- unsigned int bufs_sent_pack;
+-
+- unsigned int sc_dp_p;
+- unsigned int sc_p_dp;
+- /* qdio_input_handler: number of times called, time spent in */
+- __u64 inbound_start_time;
+- unsigned int inbound_cnt;
+- unsigned int inbound_time;
+- /* qeth_send_packet: number of times called, time spent in */
+- __u64 outbound_start_time;
+- unsigned int outbound_cnt;
+- unsigned int outbound_time;
+- /* qdio_output_handler: number of times called, time spent in */
+- __u64 outbound_handler_start_time;
+- unsigned int outbound_handler_cnt;
+- unsigned int outbound_handler_time;
+- /* number of calls to and time spent in do_QDIO for inbound queue */
+- __u64 inbound_do_qdio_start_time;
+- unsigned int inbound_do_qdio_cnt;
+- unsigned int inbound_do_qdio_time;
+- /* number of calls to and time spent in do_QDIO for outbound queues */
+- __u64 outbound_do_qdio_start_time;
+- unsigned int outbound_do_qdio_cnt;
+- unsigned int outbound_do_qdio_time;
+- /* eddp data */
+- unsigned int large_send_bytes;
+- unsigned int large_send_cnt;
+- unsigned int sg_skbs_sent;
+- unsigned int sg_frags_sent;
+- /* initial values when measuring starts */
+- unsigned long initial_rx_packets;
+- unsigned long initial_tx_packets;
+- /* inbound scatter gather data */
+- unsigned int sg_skbs_rx;
+- unsigned int sg_frags_rx;
+- unsigned int sg_alloc_page_rx;
+-};
+-
+-/* Routing stuff */
+-struct qeth_routing_info {
+- enum qeth_routing_types type;
+-};
+-
+-/* IPA stuff */
+-struct qeth_ipa_info {
+- __u32 supported_funcs;
+- __u32 enabled_funcs;
+-};
+-
+-static inline int
+-qeth_is_ipa_supported(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func)
+-{
+- return (ipa->supported_funcs & func);
+-}
+-
+-static inline int
+-qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func)
+-{
+- return (ipa->supported_funcs & ipa->enabled_funcs & func);
+-}
+-
+-#define qeth_adp_supported(c,f) \
+- qeth_is_ipa_supported(&c->options.adp, f)
+-#define qeth_adp_enabled(c,f) \
+- qeth_is_ipa_enabled(&c->options.adp, f)
+-#define qeth_is_supported(c,f) \
+- qeth_is_ipa_supported(&c->options.ipa4, f)
+-#define qeth_is_enabled(c,f) \
+- qeth_is_ipa_enabled(&c->options.ipa4, f)
+-#ifdef CONFIG_QETH_IPV6
+-#define qeth_is_supported6(c,f) \
+- qeth_is_ipa_supported(&c->options.ipa6, f)
+-#define qeth_is_enabled6(c,f) \
+- qeth_is_ipa_enabled(&c->options.ipa6, f)
+-#else /* CONFIG_QETH_IPV6 */
+-#define qeth_is_supported6(c,f) 0
+-#define qeth_is_enabled6(c,f) 0
+-#endif /* CONFIG_QETH_IPV6 */
+-#define qeth_is_ipafunc_supported(c,prot,f) \
+- (prot==QETH_PROT_IPV6)? qeth_is_supported6(c,f):qeth_is_supported(c,f)
+-#define qeth_is_ipafunc_enabled(c,prot,f) \
+- (prot==QETH_PROT_IPV6)? qeth_is_enabled6(c,f):qeth_is_enabled(c,f)
+-
+-
+-#define QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT 0x0101
+-#define QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT 0x0101
+-#define QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT 0x4108
+-#define QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT 0x5108
+-
+-#define QETH_MODELLIST_ARRAY \
+- {{0x1731,0x01,0x1732,0x01,QETH_CARD_TYPE_OSAE,1, \
+- QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT, \
+- QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT, \
+- QETH_MAX_QUEUES,0}, \
+- {0x1731,0x05,0x1732,0x05,QETH_CARD_TYPE_IQD,0, \
+- QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT, \
+- QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT, \
+- QETH_MAX_QUEUES,0x103}, \
+- {0x1731,0x06,0x1732,0x06,QETH_CARD_TYPE_OSN,0, \
+- QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT, \
+- QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT, \
+- QETH_MAX_QUEUES,0}, \
+- {0,0,0,0,0,0,0,0,0}}
+-
+-#define QETH_REAL_CARD 1
+-#define QETH_VLAN_CARD 2
+-#define QETH_BUFSIZE 4096
+-
+-/**
+- * some more defs
+- */
+-#define IF_NAME_LEN 16
+-#define QETH_TX_TIMEOUT 100 * HZ
+-#define QETH_RCD_TIMEOUT 60 * HZ
+-#define QETH_HEADER_SIZE 32
+-#define MAX_PORTNO 15
+-#define QETH_FAKE_LL_LEN_ETH ETH_HLEN
+-#define QETH_FAKE_LL_LEN_TR (sizeof(struct trh_hdr)-TR_MAXRIFLEN+sizeof(struct trllc))
+-#define QETH_FAKE_LL_V6_ADDR_POS 24
+-
+-/*IPv6 address autoconfiguration stuff*/
+-#define UNIQUE_ID_IF_CREATE_ADDR_FAILED 0xfffe
+-#define UNIQUE_ID_NOT_BY_CARD 0x10000
+-
+-/*****************************************************************************/
+-/* QDIO queue and buffer handling */
+-/*****************************************************************************/
+-#define QETH_MAX_QUEUES 4
+-#define QETH_IN_BUF_SIZE_DEFAULT 65536
+-#define QETH_IN_BUF_COUNT_DEFAULT 16
+-#define QETH_IN_BUF_COUNT_MIN 8
+-#define QETH_IN_BUF_COUNT_MAX 128
+-#define QETH_MAX_BUFFER_ELEMENTS(card) ((card)->qdio.in_buf_size >> 12)
+-#define QETH_IN_BUF_REQUEUE_THRESHOLD(card) \
+- ((card)->qdio.in_buf_pool.buf_count / 2)
+-
+-/* buffers we have to be behind before we get a PCI */
+-#define QETH_PCI_THRESHOLD_A(card) ((card)->qdio.in_buf_pool.buf_count+1)
+-/*enqueued free buffers left before we get a PCI*/
+-#define QETH_PCI_THRESHOLD_B(card) 0
+-/*not used unless the microcode gets patched*/
+-#define QETH_PCI_TIMER_VALUE(card) 3
+-
+-#define QETH_MIN_INPUT_THRESHOLD 1
+-#define QETH_MAX_INPUT_THRESHOLD 500
+-#define QETH_MIN_OUTPUT_THRESHOLD 1
+-#define QETH_MAX_OUTPUT_THRESHOLD 300
+-
+-/* priority queing */
+-#define QETH_PRIOQ_DEFAULT QETH_NO_PRIO_QUEUEING
+-#define QETH_DEFAULT_QUEUE 2
+-#define QETH_NO_PRIO_QUEUEING 0
+-#define QETH_PRIO_Q_ING_PREC 1
+-#define QETH_PRIO_Q_ING_TOS 2
+-#define IP_TOS_LOWDELAY 0x10
+-#define IP_TOS_HIGHTHROUGHPUT 0x08
+-#define IP_TOS_HIGHRELIABILITY 0x04
+-#define IP_TOS_NOTIMPORTANT 0x02
+-
+-/* Packing */
+-#define QETH_LOW_WATERMARK_PACK 2
+-#define QETH_HIGH_WATERMARK_PACK 5
+-#define QETH_WATERMARK_PACK_FUZZ 1
+-
+-#define QETH_IP_HEADER_SIZE 40
+-
+-/* large receive scatter gather copy break */
+-#define QETH_RX_SG_CB (PAGE_SIZE >> 1)
+-
+-struct qeth_hdr_layer3 {
+- __u8 id;
+- __u8 flags;
+- __u16 inbound_checksum; /*TSO:__u16 seqno */
+- __u32 token; /*TSO: __u32 reserved */
+- __u16 length;
+- __u8 vlan_prio;
+- __u8 ext_flags;
+- __u16 vlan_id;
+- __u16 frame_offset;
+- __u8 dest_addr[16];
+-} __attribute__ ((packed));
+-
+-struct qeth_hdr_layer2 {
+- __u8 id;
+- __u8 flags[3];
+- __u8 port_no;
+- __u8 hdr_length;
+- __u16 pkt_length;
+- __u16 seq_no;
+- __u16 vlan_id;
+- __u32 reserved;
+- __u8 reserved2[16];
+-} __attribute__ ((packed));
+-
+-struct qeth_hdr_osn {
+- __u8 id;
+- __u8 reserved;
+- __u16 seq_no;
+- __u16 reserved2;
+- __u16 control_flags;
+- __u16 pdu_length;
+- __u8 reserved3[18];
+- __u32 ccid;
+-} __attribute__ ((packed));
+-
+-struct qeth_hdr {
+- union {
+- struct qeth_hdr_layer2 l2;
+- struct qeth_hdr_layer3 l3;
+- struct qeth_hdr_osn osn;
+- } hdr;
+-} __attribute__ ((packed));
+-
+-/*TCP Segmentation Offload header*/
+-struct qeth_hdr_ext_tso {
+- __u16 hdr_tot_len;
+- __u8 imb_hdr_no;
+- __u8 reserved;
+- __u8 hdr_type;
+- __u8 hdr_version;
+- __u16 hdr_len;
+- __u32 payload_len;
+- __u16 mss;
+- __u16 dg_hdr_len;
+- __u8 padding[16];
+-} __attribute__ ((packed));
+-
+-struct qeth_hdr_tso {
+- struct qeth_hdr hdr; /*hdr->hdr.l3.xxx*/
+- struct qeth_hdr_ext_tso ext;
+-} __attribute__ ((packed));
+-
+-
+-/* flags for qeth_hdr.flags */
+-#define QETH_HDR_PASSTHRU 0x10
+-#define QETH_HDR_IPV6 0x80
+-#define QETH_HDR_CAST_MASK 0x07
+-enum qeth_cast_flags {
+- QETH_CAST_UNICAST = 0x06,
+- QETH_CAST_MULTICAST = 0x04,
+- QETH_CAST_BROADCAST = 0x05,
+- QETH_CAST_ANYCAST = 0x07,
+- QETH_CAST_NOCAST = 0x00,
+-};
+-
+-enum qeth_layer2_frame_flags {
+- QETH_LAYER2_FLAG_MULTICAST = 0x01,
+- QETH_LAYER2_FLAG_BROADCAST = 0x02,
+- QETH_LAYER2_FLAG_UNICAST = 0x04,
+- QETH_LAYER2_FLAG_VLAN = 0x10,
+-};
+-
+-enum qeth_header_ids {
+- QETH_HEADER_TYPE_LAYER3 = 0x01,
+- QETH_HEADER_TYPE_LAYER2 = 0x02,
+- QETH_HEADER_TYPE_TSO = 0x03,
+- QETH_HEADER_TYPE_OSN = 0x04,
+-};
+-/* flags for qeth_hdr.ext_flags */
+-#define QETH_HDR_EXT_VLAN_FRAME 0x01
+-#define QETH_HDR_EXT_TOKEN_ID 0x02
+-#define QETH_HDR_EXT_INCLUDE_VLAN_TAG 0x04
+-#define QETH_HDR_EXT_SRC_MAC_ADDR 0x08
+-#define QETH_HDR_EXT_CSUM_HDR_REQ 0x10
+-#define QETH_HDR_EXT_CSUM_TRANSP_REQ 0x20
+-#define QETH_HDR_EXT_UDP_TSO 0x40 /*bit off for TCP*/
+-
+-static inline int
+-qeth_is_last_sbale(struct qdio_buffer_element *sbale)
+-{
+- return (sbale->flags & SBAL_FLAGS_LAST_ENTRY);
+-}
+-
+-enum qeth_qdio_buffer_states {
+- /*
+- * inbound: read out by driver; owned by hardware in order to be filled
+- * outbound: owned by driver in order to be filled
+- */
+- QETH_QDIO_BUF_EMPTY,
+- /*
+- * inbound: filled by hardware; owned by driver in order to be read out
+- * outbound: filled by driver; owned by hardware in order to be sent
+- */
+- QETH_QDIO_BUF_PRIMED,
+-};
+-
+-enum qeth_qdio_info_states {
+- QETH_QDIO_UNINITIALIZED,
+- QETH_QDIO_ALLOCATED,
+- QETH_QDIO_ESTABLISHED,
+- QETH_QDIO_CLEANING
+-};
+-
+-struct qeth_buffer_pool_entry {
+- struct list_head list;
+- struct list_head init_list;
+- void *elements[QDIO_MAX_ELEMENTS_PER_BUFFER];
+-};
+-
+-struct qeth_qdio_buffer_pool {
+- struct list_head entry_list;
+- int buf_count;
+-};
+-
+-struct qeth_qdio_buffer {
+- struct qdio_buffer *buffer;
+- volatile enum qeth_qdio_buffer_states state;
+- /* the buffer pool entry currently associated to this buffer */
+- struct qeth_buffer_pool_entry *pool_entry;
+-};
+-
+-struct qeth_qdio_q {
+- struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
+- struct qeth_qdio_buffer bufs[QDIO_MAX_BUFFERS_PER_Q];
+- /*
+- * buf_to_init means "buffer must be initialized by driver and must
+- * be made available for hardware" -> state is set to EMPTY
+- */
+- volatile int next_buf_to_init;
+-} __attribute__ ((aligned(256)));
+-
+-/* possible types of qeth large_send support */
+-enum qeth_large_send_types {
+- QETH_LARGE_SEND_NO,
+- QETH_LARGE_SEND_EDDP,
+- QETH_LARGE_SEND_TSO,
+-};
+-
+-struct qeth_qdio_out_buffer {
+- struct qdio_buffer *buffer;
+- atomic_t state;
+- volatile int next_element_to_fill;
+- struct sk_buff_head skb_list;
+- struct list_head ctx_list;
+-};
+-
+-struct qeth_card;
+-
+-enum qeth_out_q_states {
+- QETH_OUT_Q_UNLOCKED,
+- QETH_OUT_Q_LOCKED,
+- QETH_OUT_Q_LOCKED_FLUSH,
+-};
+-
+-struct qeth_qdio_out_q {
+- struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
+- struct qeth_qdio_out_buffer bufs[QDIO_MAX_BUFFERS_PER_Q];
+- int queue_no;
+- struct qeth_card *card;
+- atomic_t state;
+- volatile int do_pack;
+- /*
+- * index of buffer to be filled by driver; state EMPTY or PACKING
+- */
+- volatile int next_buf_to_fill;
+- /*
+- * number of buffers that are currently filled (PRIMED)
+- * -> these buffers are hardware-owned
+- */
+- atomic_t used_buffers;
+- /* indicates whether PCI flag must be set (or if one is outstanding) */
+- atomic_t set_pci_flags_count;
+-} __attribute__ ((aligned(256)));
+-
+-struct qeth_qdio_info {
+- atomic_t state;
+- /* input */
+- struct qeth_qdio_q *in_q;
+- struct qeth_qdio_buffer_pool in_buf_pool;
+- struct qeth_qdio_buffer_pool init_pool;
+- int in_buf_size;
+-
+- /* output */
+- int no_out_queues;
+- struct qeth_qdio_out_q **out_qs;
+-
+- /* priority queueing */
+- int do_prio_queueing;
+- int default_out_queue;
+-};
+-
+-enum qeth_send_errors {
+- QETH_SEND_ERROR_NONE,
+- QETH_SEND_ERROR_LINK_FAILURE,
+- QETH_SEND_ERROR_RETRY,
+- QETH_SEND_ERROR_KICK_IT,
+-};
+-
+-#define QETH_ETH_MAC_V4 0x0100 /* like v4 */
+-#define QETH_ETH_MAC_V6 0x3333 /* like v6 */
+-/* tr mc mac is longer, but that will be enough to detect mc frames */
+-#define QETH_TR_MAC_NC 0xc000 /* non-canonical */
+-#define QETH_TR_MAC_C 0x0300 /* canonical */
+-
+-#define DEFAULT_ADD_HHLEN 0
+-#define MAX_ADD_HHLEN 1024
+-
+-/**
+- * buffer stuff for read channel
+- */
+-#define QETH_CMD_BUFFER_NO 8
+-
+-/**
+- * channel state machine
+- */
+-enum qeth_channel_states {
+- CH_STATE_UP,
+- CH_STATE_DOWN,
+- CH_STATE_ACTIVATING,
+- CH_STATE_HALTED,
+- CH_STATE_STOPPED,
+- CH_STATE_RCD,
+- CH_STATE_RCD_DONE,
+-};
+-/**
+- * card state machine
+- */
+-enum qeth_card_states {
+- CARD_STATE_DOWN,
+- CARD_STATE_HARDSETUP,
+- CARD_STATE_SOFTSETUP,
+- CARD_STATE_UP,
+- CARD_STATE_RECOVER,
+-};
+-
+-/**
+- * Protocol versions
+- */
+-enum qeth_prot_versions {
+- QETH_PROT_IPV4 = 0x0004,
+- QETH_PROT_IPV6 = 0x0006,
+-};
+-
+-enum qeth_ip_types {
+- QETH_IP_TYPE_NORMAL,
+- QETH_IP_TYPE_VIPA,
+- QETH_IP_TYPE_RXIP,
+- QETH_IP_TYPE_DEL_ALL_MC,
+-};
+-
+-enum qeth_cmd_buffer_state {
+- BUF_STATE_FREE,
+- BUF_STATE_LOCKED,
+- BUF_STATE_PROCESSED,
+-};
+-/**
+- * IP address and multicast list
+- */
+-struct qeth_ipaddr {
+- struct list_head entry;
+- enum qeth_ip_types type;
+- enum qeth_ipa_setdelip_flags set_flags;
+- enum qeth_ipa_setdelip_flags del_flags;
+- int is_multicast;
+- volatile int users;
+- enum qeth_prot_versions proto;
+- unsigned char mac[OSA_ADDR_LEN];
+- union {
+- struct {
+- unsigned int addr;
+- unsigned int mask;
+- } a4;
+- struct {
+- struct in6_addr addr;
+- unsigned int pfxlen;
+- } a6;
+- } u;
+-};
+-
+-struct qeth_ipato_entry {
+- struct list_head entry;
+- enum qeth_prot_versions proto;
+- char addr[16];
+- int mask_bits;
+-};
+-
+-struct qeth_ipato {
+- int enabled;
+- int invert4;
+- int invert6;
+- struct list_head entries;
+-};
+-
+-struct qeth_channel;
+-
+-struct qeth_cmd_buffer {
+- enum qeth_cmd_buffer_state state;
+- struct qeth_channel *channel;
+- unsigned char *data;
+- int rc;
+- void (*callback) (struct qeth_channel *, struct qeth_cmd_buffer *);
+-};
+-
+-
+-/**
+- * definition of a qeth channel, used for read and write
+- */
+-struct qeth_channel {
+- enum qeth_channel_states state;
+- struct ccw1 ccw;
+- spinlock_t iob_lock;
+- wait_queue_head_t wait_q;
+- struct tasklet_struct irq_tasklet;
+- struct ccw_device *ccwdev;
+-/*command buffer for control data*/
+- struct qeth_cmd_buffer iob[QETH_CMD_BUFFER_NO];
+- atomic_t irq_pending;
+- volatile int io_buf_no;
+- volatile int buf_no;
+-};
+-
+-/**
+- * OSA card related definitions
+- */
+-struct qeth_token {
+- __u32 issuer_rm_w;
+- __u32 issuer_rm_r;
+- __u32 cm_filter_w;
+- __u32 cm_filter_r;
+- __u32 cm_connection_w;
+- __u32 cm_connection_r;
+- __u32 ulp_filter_w;
+- __u32 ulp_filter_r;
+- __u32 ulp_connection_w;
+- __u32 ulp_connection_r;
+-};
+-
+-struct qeth_seqno {
+- __u32 trans_hdr;
+- __u32 pdu_hdr;
+- __u32 pdu_hdr_ack;
+- __u16 ipa;
+- __u32 pkt_seqno;
+-};
+-
+-struct qeth_reply {
+- struct list_head list;
+- wait_queue_head_t wait_q;
+- int (*callback)(struct qeth_card *,struct qeth_reply *,unsigned long);
+- u32 seqno;
+- unsigned long offset;
+- atomic_t received;
+- int rc;
+- void *param;
+- struct qeth_card *card;
+- atomic_t refcnt;
+-};
+-
+-
+-struct qeth_card_blkt {
+- int time_total;
+- int inter_packet;
+- int inter_packet_jumbo;
+-};
+-
+-#define QETH_BROADCAST_WITH_ECHO 0x01
+-#define QETH_BROADCAST_WITHOUT_ECHO 0x02
+-#define QETH_LAYER2_MAC_READ 0x01
+-#define QETH_LAYER2_MAC_REGISTERED 0x02
+-struct qeth_card_info {
+- unsigned short unit_addr2;
+- unsigned short cula;
+- unsigned short chpid;
+- __u16 func_level;
+- char mcl_level[QETH_MCL_LENGTH + 1];
+- int guestlan;
+- int mac_bits;
+- int portname_required;
+- int portno;
+- char portname[9];
+- enum qeth_card_types type;
+- enum qeth_link_types link_type;
+- int is_multicast_different;
+- int initial_mtu;
+- int max_mtu;
+- int broadcast_capable;
+- int unique_id;
+- struct qeth_card_blkt blkt;
+- __u32 csum_mask;
+- enum qeth_ipa_promisc_modes promisc_mode;
+-};
+-
+-struct qeth_card_options {
+- struct qeth_routing_info route4;
+- struct qeth_ipa_info ipa4;
+- struct qeth_ipa_info adp; /*Adapter parameters*/
+-#ifdef CONFIG_QETH_IPV6
+- struct qeth_routing_info route6;
+- struct qeth_ipa_info ipa6;
+-#endif /* QETH_IPV6 */
+- enum qeth_checksum_types checksum_type;
+- int broadcast_mode;
+- int macaddr_mode;
+- int fake_broadcast;
+- int add_hhlen;
+- int fake_ll;
+- int layer2;
+- enum qeth_large_send_types large_send;
+- int performance_stats;
+- int rx_sg_cb;
+-};
+-
+-/*
+- * thread bits for qeth_card thread masks
+- */
+-enum qeth_threads {
+- QETH_SET_IP_THREAD = 1,
+- QETH_RECOVER_THREAD = 2,
+- QETH_SET_PROMISC_MODE_THREAD = 4,
+-};
+-
+-struct qeth_osn_info {
+- int (*assist_cb)(struct net_device *dev, void *data);
+- int (*data_cb)(struct sk_buff *skb);
+-};
+-
+-struct qeth_card {
+- struct list_head list;
+- enum qeth_card_states state;
+- int lan_online;
+- spinlock_t lock;
+-/*hardware and sysfs stuff*/
+- struct ccwgroup_device *gdev;
+- struct qeth_channel read;
+- struct qeth_channel write;
+- struct qeth_channel data;
+-
+- struct net_device *dev;
+- struct net_device_stats stats;
+-
+- struct qeth_card_info info;
+- struct qeth_token token;
+- struct qeth_seqno seqno;
+- struct qeth_card_options options;
+-
+- wait_queue_head_t wait_q;
+-#ifdef CONFIG_QETH_VLAN
+- spinlock_t vlanlock;
+- struct vlan_group *vlangrp;
+-#endif
+- struct work_struct kernel_thread_starter;
+- spinlock_t thread_mask_lock;
+- volatile unsigned long thread_start_mask;
+- volatile unsigned long thread_allowed_mask;
+- volatile unsigned long thread_running_mask;
+- spinlock_t ip_lock;
+- struct list_head ip_list;
+- struct list_head *ip_tbd_list;
+- struct qeth_ipato ipato;
+- struct list_head cmd_waiter_list;
+- /* QDIO buffer handling */
+- struct qeth_qdio_info qdio;
+- struct qeth_perf_stats perf_stats;
+- int use_hard_stop;
+- const struct header_ops *orig_header_ops;
+- struct qeth_osn_info osn_info;
+- atomic_t force_alloc_skb;
+-};
+-
+-struct qeth_card_list_struct {
+- struct list_head list;
+- rwlock_t rwlock;
+-};
+-
+-extern struct qeth_card_list_struct qeth_card_list;
+-
+-/*notifier list */
+-struct qeth_notify_list_struct {
+- struct list_head list;
+- struct task_struct *task;
+- int signum;
+-};
+-extern spinlock_t qeth_notify_lock;
+-extern struct list_head qeth_notify_list;
+-
+-/*some helper functions*/
+-
+-#define QETH_CARD_IFNAME(card) (((card)->dev)? (card)->dev->name : "")
+-
+-static inline __u8
+-qeth_get_ipa_adp_type(enum qeth_link_types link_type)
+-{
+- switch (link_type) {
+- case QETH_LINK_TYPE_HSTR:
+- return 2;
+- default:
+- return 1;
+- }
+-}
+-
+-static inline struct sk_buff *
+-qeth_realloc_headroom(struct qeth_card *card, struct sk_buff *skb, int size)
+-{
+- struct sk_buff *new_skb = skb;
+-
+- if (skb_headroom(skb) >= size)
+- return skb;
+- new_skb = skb_realloc_headroom(skb, size);
+- if (!new_skb)
+- PRINT_ERR("Could not realloc headroom for qeth_hdr "
+- "on interface %s", QETH_CARD_IFNAME(card));
+- return new_skb;
+-}
+-
+-static inline struct sk_buff *
+-qeth_pskb_unshare(struct sk_buff *skb, gfp_t pri)
+-{
+- struct sk_buff *nskb;
+- if (!skb_cloned(skb))
+- return skb;
+- nskb = skb_copy(skb, pri);
+- return nskb;
+-}
+-
+-static inline void *
+-qeth_push_skb(struct qeth_card *card, struct sk_buff *skb, int size)
+-{
+- void *hdr;
+-
+- hdr = (void *) skb_push(skb, size);
+- /*
+- * sanity check, the Linux memory allocation scheme should
+- * never present us cases like this one (the qdio header size plus
+- * the first 40 bytes of the paket cross a 4k boundary)
+- */
+- if ((((unsigned long) hdr) & (~(PAGE_SIZE - 1))) !=
+- (((unsigned long) hdr + size +
+- QETH_IP_HEADER_SIZE) & (~(PAGE_SIZE - 1)))) {
+- PRINT_ERR("Misaligned packet on interface %s. Discarded.",
+- QETH_CARD_IFNAME(card));
+- return NULL;
+- }
+- return hdr;
+-}
+-
+-
+-static inline int
+-qeth_get_hlen(__u8 link_type)
+-{
+-#ifdef CONFIG_QETH_IPV6
+- switch (link_type) {
+- case QETH_LINK_TYPE_HSTR:
+- case QETH_LINK_TYPE_LANE_TR:
+- return sizeof(struct qeth_hdr_tso) + TR_HLEN;
+- default:
+-#ifdef CONFIG_QETH_VLAN
+- return sizeof(struct qeth_hdr_tso) + VLAN_ETH_HLEN;
+-#else
+- return sizeof(struct qeth_hdr_tso) + ETH_HLEN;
+-#endif
+- }
+-#else /* CONFIG_QETH_IPV6 */
+-#ifdef CONFIG_QETH_VLAN
+- return sizeof(struct qeth_hdr_tso) + VLAN_HLEN;
+-#else
+- return sizeof(struct qeth_hdr_tso);
+-#endif
+-#endif /* CONFIG_QETH_IPV6 */
+-}
+-
+-static inline unsigned short
+-qeth_get_netdev_flags(struct qeth_card *card)
+-{
+- if (card->options.layer2 &&
+- (card->info.type == QETH_CARD_TYPE_OSAE))
+- return 0;
+- switch (card->info.type) {
+- case QETH_CARD_TYPE_IQD:
+- case QETH_CARD_TYPE_OSN:
+- return IFF_NOARP;
+-#ifdef CONFIG_QETH_IPV6
+- default:
+- return 0;
+-#else
+- default:
+- return IFF_NOARP;
+-#endif
+- }
+-}
+-
+-static inline int
+-qeth_get_initial_mtu_for_card(struct qeth_card * card)
+-{
+- switch (card->info.type) {
+- case QETH_CARD_TYPE_UNKNOWN:
+- return 1500;
+- case QETH_CARD_TYPE_IQD:
+- return card->info.max_mtu;
+- case QETH_CARD_TYPE_OSAE:
+- switch (card->info.link_type) {
+- case QETH_LINK_TYPE_HSTR:
+- case QETH_LINK_TYPE_LANE_TR:
+- return 2000;
+- default:
+- return 1492;
+- }
+- default:
+- return 1500;
+- }
+-}
+-
+-static inline int
+-qeth_get_max_mtu_for_card(int cardtype)
+-{
+- switch (cardtype) {
+-
+- case QETH_CARD_TYPE_UNKNOWN:
+- case QETH_CARD_TYPE_OSAE:
+- case QETH_CARD_TYPE_OSN:
+- return 61440;
+- case QETH_CARD_TYPE_IQD:
+- return 57344;
+- default:
+- return 1500;
+- }
+-}
+-
+-static inline int
+-qeth_get_mtu_out_of_mpc(int cardtype)
+-{
+- switch (cardtype) {
+- case QETH_CARD_TYPE_IQD:
+- return 1;
+- default:
+- return 0;
+- }
+-}
+-
+-static inline int
+-qeth_get_mtu_outof_framesize(int framesize)
+-{
+- switch (framesize) {
+- case 0x4000:
+- return 8192;
+- case 0x6000:
+- return 16384;
+- case 0xa000:
+- return 32768;
+- case 0xffff:
+- return 57344;
+- default:
+- return 0;
+- }
+-}
+-
+-static inline int
+-qeth_mtu_is_valid(struct qeth_card * card, int mtu)
+-{
+- switch (card->info.type) {
+- case QETH_CARD_TYPE_OSAE:
+- return ((mtu >= 576) && (mtu <= 61440));
+- case QETH_CARD_TYPE_IQD:
+- return ((mtu >= 576) &&
+- (mtu <= card->info.max_mtu + 4096 - 32));
+- case QETH_CARD_TYPE_OSN:
+- case QETH_CARD_TYPE_UNKNOWN:
+- default:
+- return 1;
+- }
+-}
+-
+-static inline int
+-qeth_get_arphdr_type(int cardtype, int linktype)
+-{
+- switch (cardtype) {
+- case QETH_CARD_TYPE_OSAE:
+- case QETH_CARD_TYPE_OSN:
+- switch (linktype) {
+- case QETH_LINK_TYPE_LANE_TR:
+- case QETH_LINK_TYPE_HSTR:
+- return ARPHRD_IEEE802_TR;
+- default:
+- return ARPHRD_ETHER;
+- }
+- case QETH_CARD_TYPE_IQD:
+- default:
+- return ARPHRD_ETHER;
+- }
+-}
+-
+-static inline int
+-qeth_get_micros(void)
+-{
+- return (int) (get_clock() >> 12);
+-}
+-
+-static inline int
+-qeth_get_qdio_q_format(struct qeth_card *card)
+-{
+- switch (card->info.type) {
+- case QETH_CARD_TYPE_IQD:
+- return 2;
+- default:
+- return 0;
+- }
+-}
+-
+-static inline int
+-qeth_isxdigit(char * buf)
+-{
+- while (*buf) {
+- if (!isxdigit(*buf++))
+- return 0;
+- }
+- return 1;
+-}
+-
+-static inline void
+-qeth_ipaddr4_to_string(const __u8 *addr, char *buf)
+-{
+- sprintf(buf, "%i.%i.%i.%i", addr[0], addr[1], addr[2], addr[3]);
+-}
+-
+-static inline int
+-qeth_string_to_ipaddr4(const char *buf, __u8 *addr)
+-{
+- int count = 0, rc = 0;
+- int in[4];
+- char c;
+-
+- rc = sscanf(buf, "%u.%u.%u.%u%c",
+- &in[0], &in[1], &in[2], &in[3], &c);
+- if (rc != 4 && (rc != 5 || c != '\n'))
+- return -EINVAL;
+- for (count = 0; count < 4; count++) {
+- if (in[count] > 255)
+- return -EINVAL;
+- addr[count] = in[count];
+- }
+- return 0;
+-}
+-
+-static inline void
+-qeth_ipaddr6_to_string(const __u8 *addr, char *buf)
+-{
+- sprintf(buf, "%02x%02x:%02x%02x:%02x%02x:%02x%02x"
+- ":%02x%02x:%02x%02x:%02x%02x:%02x%02x",
+- addr[0], addr[1], addr[2], addr[3],
+- addr[4], addr[5], addr[6], addr[7],
+- addr[8], addr[9], addr[10], addr[11],
+- addr[12], addr[13], addr[14], addr[15]);
+-}
+-
+-static inline int
+-qeth_string_to_ipaddr6(const char *buf, __u8 *addr)
+-{
+- const char *end, *end_tmp, *start;
+- __u16 *in;
+- char num[5];
+- int num2, cnt, out, found, save_cnt;
+- unsigned short in_tmp[8] = {0, };
+-
+- cnt = out = found = save_cnt = num2 = 0;
+- end = start = buf;
+- in = (__u16 *) addr;
+- memset(in, 0, 16);
+- while (*end) {
+- end = strchr(start,':');
+- if (end == NULL) {
+- end = buf + strlen(buf);
+- if ((end_tmp = strchr(start, '\n')) != NULL)
+- end = end_tmp;
+- out = 1;
+- }
+- if ((end - start)) {
+- memset(num, 0, 5);
+- if ((end - start) > 4)
+- return -EINVAL;
+- memcpy(num, start, end - start);
+- if (!qeth_isxdigit(num))
+- return -EINVAL;
+- sscanf(start, "%x", &num2);
+- if (found)
+- in_tmp[save_cnt++] = num2;
+- else
+- in[cnt++] = num2;
+- if (out)
+- break;
+- } else {
+- if (found)
+- return -EINVAL;
+- found = 1;
+- }
+- start = ++end;
+- }
+- if (cnt + save_cnt > 8)
+- return -EINVAL;
+- cnt = 7;
+- while (save_cnt)
+- in[cnt--] = in_tmp[--save_cnt];
+- return 0;
+-}
+-
+-static inline void
+-qeth_ipaddr_to_string(enum qeth_prot_versions proto, const __u8 *addr,
+- char *buf)
+-{
+- if (proto == QETH_PROT_IPV4)
+- qeth_ipaddr4_to_string(addr, buf);
+- else if (proto == QETH_PROT_IPV6)
+- qeth_ipaddr6_to_string(addr, buf);
+-}
+-
+-static inline int
+-qeth_string_to_ipaddr(const char *buf, enum qeth_prot_versions proto,
+- __u8 *addr)
+-{
+- if (proto == QETH_PROT_IPV4)
+- return qeth_string_to_ipaddr4(buf, addr);
+- else if (proto == QETH_PROT_IPV6)
+- return qeth_string_to_ipaddr6(buf, addr);
+- else
+- return -EINVAL;
+-}
+-
+-extern int
+-qeth_setrouting_v4(struct qeth_card *);
+-extern int
+-qeth_setrouting_v6(struct qeth_card *);
+-
+-extern int
+-qeth_add_ipato_entry(struct qeth_card *, struct qeth_ipato_entry *);
+-
+-extern void
+-qeth_del_ipato_entry(struct qeth_card *, enum qeth_prot_versions, u8 *, int);
+-
+-extern int
+-qeth_add_vipa(struct qeth_card *, enum qeth_prot_versions, const u8 *);
+-
+-extern void
+-qeth_del_vipa(struct qeth_card *, enum qeth_prot_versions, const u8 *);
+-
+-extern int
+-qeth_add_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *);
+-
+-extern void
+-qeth_del_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *);
+-
+-extern int
+-qeth_notifier_register(struct task_struct *, int );
+-
+-extern int
+-qeth_notifier_unregister(struct task_struct * );
+-
+-extern void
+-qeth_schedule_recovery(struct qeth_card *);
+-
+-extern int
+-qeth_realloc_buffer_pool(struct qeth_card *, int);
+-
+-extern int
+-qeth_set_large_send(struct qeth_card *, enum qeth_large_send_types);
+-
+-extern void
+-qeth_fill_header(struct qeth_card *, struct qeth_hdr *,
+- struct sk_buff *, int, int);
+-extern void
+-qeth_flush_buffers(struct qeth_qdio_out_q *, int, int, int);
+-
+-extern int
+-qeth_osn_assist(struct net_device *, void *, int);
+-
+-extern int
+-qeth_osn_register(unsigned char *read_dev_no,
+- struct net_device **,
+- int (*assist_cb)(struct net_device *, void *),
+- int (*data_cb)(struct sk_buff *));
+-
+-extern void
+-qeth_osn_deregister(struct net_device *);
+-
+-#endif /* __QETH_H__ */
+diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
+new file mode 100644
+index 0000000..66f4f12
+--- /dev/null
++++ b/drivers/s390/net/qeth_core.h
+@@ -0,0 +1,905 @@
++/*
++ * drivers/s390/net/qeth_core.h
++ *
++ * Copyright IBM Corp. 2007
++ * Author(s): Utz Bacher <utz.bacher at de.ibm.com>,
++ * Frank Pavlic <fpavlic at de.ibm.com>,
++ * Thomas Spatzier <tspat at de.ibm.com>,
++ * Frank Blaschka <frank.blaschka at de.ibm.com>
++ */
++
++#ifndef __QETH_CORE_H__
++#define __QETH_CORE_H__
++
++#include <linux/if.h>
++#include <linux/if_arp.h>
++#include <linux/if_tr.h>
++#include <linux/trdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/if_vlan.h>
++#include <linux/ctype.h>
++#include <linux/in6.h>
++#include <linux/bitops.h>
++#include <linux/seq_file.h>
++#include <linux/ethtool.h>
++
++#include <net/ipv6.h>
++#include <net/if_inet6.h>
++#include <net/addrconf.h>
++
++#include <asm/debug.h>
++#include <asm/qdio.h>
++#include <asm/ccwdev.h>
++#include <asm/ccwgroup.h>
++
++#include "qeth_core_mpc.h"
++
++#define KMSG_COMPONENT "qeth"
++
++/**
++ * Debug Facility stuff
++ */
++enum qeth_dbf_names {
++ QETH_DBF_SETUP,
++ QETH_DBF_QERR,
++ QETH_DBF_TRACE,
++ QETH_DBF_MSG,
++ QETH_DBF_SENSE,
++ QETH_DBF_MISC,
++ QETH_DBF_CTRL,
++ QETH_DBF_INFOS /* must be last element */
++};
++
++struct qeth_dbf_info {
++ char name[DEBUG_MAX_NAME_LEN];
++ int pages;
++ int areas;
++ int len;
++ int level;
++ struct debug_view *view;
++ debug_info_t *id;
++};
++
++#define QETH_DBF_CTRL_LEN 256
++
++#define QETH_DBF_TEXT(name, level, text) \
++ debug_text_event(qeth_dbf[QETH_DBF_##name].id, level, text)
++
++#define QETH_DBF_HEX(name, level, addr, len) \
++ debug_event(qeth_dbf[QETH_DBF_##name].id, level, (void *)(addr), len)
++
++#define QETH_DBF_MESSAGE(level, text...) \
++ debug_sprintf_event(qeth_dbf[QETH_DBF_MSG].id, level, text)
++
++#define QETH_DBF_TEXT_(name, level, text...) \
++ do { \
++ if (qeth_dbf_passes(qeth_dbf[QETH_DBF_##name].id, level)) { \
++ char *dbf_txt_buf = \
++ get_cpu_var(QETH_DBF_TXT_BUF); \
++ sprintf(dbf_txt_buf, text); \
++ debug_text_event(qeth_dbf[QETH_DBF_##name].id, \
++ level, dbf_txt_buf); \
++ put_cpu_var(QETH_DBF_TXT_BUF); \
++ } \
++ } while (0)
++
++/* Allow to sort out low debug levels early to avoid wasted sprints */
++static inline int qeth_dbf_passes(debug_info_t *dbf_grp, int level)
++{
++ return (level <= dbf_grp->level);
++}
++
++/**
++ * some more debug stuff
++ */
++#define PRINTK_HEADER "qeth: "
++
++#define SENSE_COMMAND_REJECT_BYTE 0
++#define SENSE_COMMAND_REJECT_FLAG 0x80
++#define SENSE_RESETTING_EVENT_BYTE 1
++#define SENSE_RESETTING_EVENT_FLAG 0x80
++
++/*
++ * Common IO related definitions
++ */
++#define CARD_RDEV(card) card->read.ccwdev
++#define CARD_WDEV(card) card->write.ccwdev
++#define CARD_DDEV(card) card->data.ccwdev
++#define CARD_BUS_ID(card) card->gdev->dev.bus_id
++#define CARD_RDEV_ID(card) card->read.ccwdev->dev.bus_id
++#define CARD_WDEV_ID(card) card->write.ccwdev->dev.bus_id
++#define CARD_DDEV_ID(card) card->data.ccwdev->dev.bus_id
++#define CHANNEL_ID(channel) channel->ccwdev->dev.bus_id
++
++/**
++ * card stuff
++ */
++struct qeth_perf_stats {
++ unsigned int bufs_rec;
++ unsigned int bufs_sent;
++
++ unsigned int skbs_sent_pack;
++ unsigned int bufs_sent_pack;
++
++ unsigned int sc_dp_p;
++ unsigned int sc_p_dp;
++ /* qdio_input_handler: number of times called, time spent in */
++ __u64 inbound_start_time;
++ unsigned int inbound_cnt;
++ unsigned int inbound_time;
++ /* qeth_send_packet: number of times called, time spent in */
++ __u64 outbound_start_time;
++ unsigned int outbound_cnt;
++ unsigned int outbound_time;
++ /* qdio_output_handler: number of times called, time spent in */
++ __u64 outbound_handler_start_time;
++ unsigned int outbound_handler_cnt;
++ unsigned int outbound_handler_time;
++ /* number of calls to and time spent in do_QDIO for inbound queue */
++ __u64 inbound_do_qdio_start_time;
++ unsigned int inbound_do_qdio_cnt;
++ unsigned int inbound_do_qdio_time;
++ /* number of calls to and time spent in do_QDIO for outbound queues */
++ __u64 outbound_do_qdio_start_time;
++ unsigned int outbound_do_qdio_cnt;
++ unsigned int outbound_do_qdio_time;
++ /* eddp data */
++ unsigned int large_send_bytes;
++ unsigned int large_send_cnt;
++ unsigned int sg_skbs_sent;
++ unsigned int sg_frags_sent;
++ /* initial values when measuring starts */
++ unsigned long initial_rx_packets;
++ unsigned long initial_tx_packets;
++ /* inbound scatter gather data */
++ unsigned int sg_skbs_rx;
++ unsigned int sg_frags_rx;
++ unsigned int sg_alloc_page_rx;
++};
++
++/* Routing stuff */
++struct qeth_routing_info {
++ enum qeth_routing_types type;
++};
++
++/* IPA stuff */
++struct qeth_ipa_info {
++ __u32 supported_funcs;
++ __u32 enabled_funcs;
++};
++
++static inline int qeth_is_ipa_supported(struct qeth_ipa_info *ipa,
++ enum qeth_ipa_funcs func)
++{
++ return (ipa->supported_funcs & func);
++}
++
++static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa,
++ enum qeth_ipa_funcs func)
++{
++ return (ipa->supported_funcs & ipa->enabled_funcs & func);
++}
++
++#define qeth_adp_supported(c, f) \
++ qeth_is_ipa_supported(&c->options.adp, f)
++#define qeth_adp_enabled(c, f) \
++ qeth_is_ipa_enabled(&c->options.adp, f)
++#define qeth_is_supported(c, f) \
++ qeth_is_ipa_supported(&c->options.ipa4, f)
++#define qeth_is_enabled(c, f) \
++ qeth_is_ipa_enabled(&c->options.ipa4, f)
++#define qeth_is_supported6(c, f) \
++ qeth_is_ipa_supported(&c->options.ipa6, f)
++#define qeth_is_enabled6(c, f) \
++ qeth_is_ipa_enabled(&c->options.ipa6, f)
++#define qeth_is_ipafunc_supported(c, prot, f) \
++ ((prot == QETH_PROT_IPV6) ? \
++ qeth_is_supported6(c, f) : qeth_is_supported(c, f))
++#define qeth_is_ipafunc_enabled(c, prot, f) \
++ ((prot == QETH_PROT_IPV6) ? \
++ qeth_is_enabled6(c, f) : qeth_is_enabled(c, f))
++
++#define QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT 0x0101
++#define QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT 0x0101
++#define QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT 0x4108
++#define QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT 0x5108
++
++#define QETH_MODELLIST_ARRAY \
++ {{0x1731, 0x01, 0x1732, 0x01, QETH_CARD_TYPE_OSAE, 1, \
++ QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT, \
++ QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT, \
++ QETH_MAX_QUEUES, 0}, \
++ {0x1731, 0x05, 0x1732, 0x05, QETH_CARD_TYPE_IQD, 0, \
++ QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT, \
++ QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT, \
++ QETH_MAX_QUEUES, 0x103}, \
++ {0x1731, 0x06, 0x1732, 0x06, QETH_CARD_TYPE_OSN, 0, \
++ QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT, \
++ QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT, \
++ QETH_MAX_QUEUES, 0}, \
++ {0, 0, 0, 0, 0, 0, 0, 0, 0} }
++
++#define QETH_REAL_CARD 1
++#define QETH_VLAN_CARD 2
++#define QETH_BUFSIZE 4096
++
++/**
++ * some more defs
++ */
++#define QETH_TX_TIMEOUT 100 * HZ
++#define QETH_RCD_TIMEOUT 60 * HZ
++#define QETH_HEADER_SIZE 32
++#define QETH_MAX_PORTNO 15
++
++/*IPv6 address autoconfiguration stuff*/
++#define UNIQUE_ID_IF_CREATE_ADDR_FAILED 0xfffe
++#define UNIQUE_ID_NOT_BY_CARD 0x10000
++
++/*****************************************************************************/
++/* QDIO queue and buffer handling */
++/*****************************************************************************/
++#define QETH_MAX_QUEUES 4
++#define QETH_IN_BUF_SIZE_DEFAULT 65536
++#define QETH_IN_BUF_COUNT_DEFAULT 16
++#define QETH_IN_BUF_COUNT_MIN 8
++#define QETH_IN_BUF_COUNT_MAX 128
++#define QETH_MAX_BUFFER_ELEMENTS(card) ((card)->qdio.in_buf_size >> 12)
++#define QETH_IN_BUF_REQUEUE_THRESHOLD(card) \
++ ((card)->qdio.in_buf_pool.buf_count / 2)
++
++/* buffers we have to be behind before we get a PCI */
++#define QETH_PCI_THRESHOLD_A(card) ((card)->qdio.in_buf_pool.buf_count+1)
++/*enqueued free buffers left before we get a PCI*/
++#define QETH_PCI_THRESHOLD_B(card) 0
++/*not used unless the microcode gets patched*/
++#define QETH_PCI_TIMER_VALUE(card) 3
++
++#define QETH_MIN_INPUT_THRESHOLD 1
++#define QETH_MAX_INPUT_THRESHOLD 500
++#define QETH_MIN_OUTPUT_THRESHOLD 1
++#define QETH_MAX_OUTPUT_THRESHOLD 300
++
++/* priority queing */
++#define QETH_PRIOQ_DEFAULT QETH_NO_PRIO_QUEUEING
++#define QETH_DEFAULT_QUEUE 2
++#define QETH_NO_PRIO_QUEUEING 0
++#define QETH_PRIO_Q_ING_PREC 1
++#define QETH_PRIO_Q_ING_TOS 2
++#define IP_TOS_LOWDELAY 0x10
++#define IP_TOS_HIGHTHROUGHPUT 0x08
++#define IP_TOS_HIGHRELIABILITY 0x04
++#define IP_TOS_NOTIMPORTANT 0x02
++
++/* Packing */
++#define QETH_LOW_WATERMARK_PACK 2
++#define QETH_HIGH_WATERMARK_PACK 5
++#define QETH_WATERMARK_PACK_FUZZ 1
++
++#define QETH_IP_HEADER_SIZE 40
++
++/* large receive scatter gather copy break */
++#define QETH_RX_SG_CB (PAGE_SIZE >> 1)
++
++struct qeth_hdr_layer3 {
++ __u8 id;
++ __u8 flags;
++ __u16 inbound_checksum; /*TSO:__u16 seqno */
++ __u32 token; /*TSO: __u32 reserved */
++ __u16 length;
++ __u8 vlan_prio;
++ __u8 ext_flags;
++ __u16 vlan_id;
++ __u16 frame_offset;
++ __u8 dest_addr[16];
++} __attribute__ ((packed));
++
++struct qeth_hdr_layer2 {
++ __u8 id;
++ __u8 flags[3];
++ __u8 port_no;
++ __u8 hdr_length;
++ __u16 pkt_length;
++ __u16 seq_no;
++ __u16 vlan_id;
++ __u32 reserved;
++ __u8 reserved2[16];
++} __attribute__ ((packed));
++
++struct qeth_hdr_osn {
++ __u8 id;
++ __u8 reserved;
++ __u16 seq_no;
++ __u16 reserved2;
++ __u16 control_flags;
++ __u16 pdu_length;
++ __u8 reserved3[18];
++ __u32 ccid;
++} __attribute__ ((packed));
++
++struct qeth_hdr {
++ union {
++ struct qeth_hdr_layer2 l2;
++ struct qeth_hdr_layer3 l3;
++ struct qeth_hdr_osn osn;
++ } hdr;
++} __attribute__ ((packed));
++
++/*TCP Segmentation Offload header*/
++struct qeth_hdr_ext_tso {
++ __u16 hdr_tot_len;
++ __u8 imb_hdr_no;
++ __u8 reserved;
++ __u8 hdr_type;
++ __u8 hdr_version;
++ __u16 hdr_len;
++ __u32 payload_len;
++ __u16 mss;
++ __u16 dg_hdr_len;
++ __u8 padding[16];
++} __attribute__ ((packed));
++
++struct qeth_hdr_tso {
++ struct qeth_hdr hdr; /*hdr->hdr.l3.xxx*/
++ struct qeth_hdr_ext_tso ext;
++} __attribute__ ((packed));
++
++
++/* flags for qeth_hdr.flags */
++#define QETH_HDR_PASSTHRU 0x10
++#define QETH_HDR_IPV6 0x80
++#define QETH_HDR_CAST_MASK 0x07
++enum qeth_cast_flags {
++ QETH_CAST_UNICAST = 0x06,
++ QETH_CAST_MULTICAST = 0x04,
++ QETH_CAST_BROADCAST = 0x05,
++ QETH_CAST_ANYCAST = 0x07,
++ QETH_CAST_NOCAST = 0x00,
++};
++
++enum qeth_layer2_frame_flags {
++ QETH_LAYER2_FLAG_MULTICAST = 0x01,
++ QETH_LAYER2_FLAG_BROADCAST = 0x02,
++ QETH_LAYER2_FLAG_UNICAST = 0x04,
++ QETH_LAYER2_FLAG_VLAN = 0x10,
++};
++
++enum qeth_header_ids {
++ QETH_HEADER_TYPE_LAYER3 = 0x01,
++ QETH_HEADER_TYPE_LAYER2 = 0x02,
++ QETH_HEADER_TYPE_TSO = 0x03,
++ QETH_HEADER_TYPE_OSN = 0x04,
++};
++/* flags for qeth_hdr.ext_flags */
++#define QETH_HDR_EXT_VLAN_FRAME 0x01
++#define QETH_HDR_EXT_TOKEN_ID 0x02
++#define QETH_HDR_EXT_INCLUDE_VLAN_TAG 0x04
++#define QETH_HDR_EXT_SRC_MAC_ADDR 0x08
++#define QETH_HDR_EXT_CSUM_HDR_REQ 0x10
++#define QETH_HDR_EXT_CSUM_TRANSP_REQ 0x20
++#define QETH_HDR_EXT_UDP_TSO 0x40 /*bit off for TCP*/
++
++static inline int qeth_is_last_sbale(struct qdio_buffer_element *sbale)
++{
++ return (sbale->flags & SBAL_FLAGS_LAST_ENTRY);
++}
++
++enum qeth_qdio_buffer_states {
++ /*
++ * inbound: read out by driver; owned by hardware in order to be filled
++ * outbound: owned by driver in order to be filled
++ */
++ QETH_QDIO_BUF_EMPTY,
++ /*
++ * inbound: filled by hardware; owned by driver in order to be read out
++ * outbound: filled by driver; owned by hardware in order to be sent
++ */
++ QETH_QDIO_BUF_PRIMED,
++};
++
++enum qeth_qdio_info_states {
++ QETH_QDIO_UNINITIALIZED,
++ QETH_QDIO_ALLOCATED,
++ QETH_QDIO_ESTABLISHED,
++ QETH_QDIO_CLEANING
++};
++
++struct qeth_buffer_pool_entry {
++ struct list_head list;
++ struct list_head init_list;
++ void *elements[QDIO_MAX_ELEMENTS_PER_BUFFER];
++};
++
++struct qeth_qdio_buffer_pool {
++ struct list_head entry_list;
++ int buf_count;
++};
++
++struct qeth_qdio_buffer {
++ struct qdio_buffer *buffer;
++ /* the buffer pool entry currently associated to this buffer */
++ struct qeth_buffer_pool_entry *pool_entry;
++};
++
++struct qeth_qdio_q {
++ struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
++ struct qeth_qdio_buffer bufs[QDIO_MAX_BUFFERS_PER_Q];
++ int next_buf_to_init;
++} __attribute__ ((aligned(256)));
++
++/* possible types of qeth large_send support */
++enum qeth_large_send_types {
++ QETH_LARGE_SEND_NO,
++ QETH_LARGE_SEND_EDDP,
++ QETH_LARGE_SEND_TSO,
++};
++
++struct qeth_qdio_out_buffer {
++ struct qdio_buffer *buffer;
++ atomic_t state;
++ int next_element_to_fill;
++ struct sk_buff_head skb_list;
++ struct list_head ctx_list;
++};
++
++struct qeth_card;
++
++enum qeth_out_q_states {
++ QETH_OUT_Q_UNLOCKED,
++ QETH_OUT_Q_LOCKED,
++ QETH_OUT_Q_LOCKED_FLUSH,
++};
++
++struct qeth_qdio_out_q {
++ struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
++ struct qeth_qdio_out_buffer bufs[QDIO_MAX_BUFFERS_PER_Q];
++ int queue_no;
++ struct qeth_card *card;
++ atomic_t state;
++ int do_pack;
++ /*
++ * index of buffer to be filled by driver; state EMPTY or PACKING
++ */
++ int next_buf_to_fill;
++ /*
++ * number of buffers that are currently filled (PRIMED)
++ * -> these buffers are hardware-owned
++ */
++ atomic_t used_buffers;
++ /* indicates whether PCI flag must be set (or if one is outstanding) */
++ atomic_t set_pci_flags_count;
++} __attribute__ ((aligned(256)));
++
++struct qeth_qdio_info {
++ atomic_t state;
++ /* input */
++ struct qeth_qdio_q *in_q;
++ struct qeth_qdio_buffer_pool in_buf_pool;
++ struct qeth_qdio_buffer_pool init_pool;
++ int in_buf_size;
++
++ /* output */
++ int no_out_queues;
++ struct qeth_qdio_out_q **out_qs;
++
++ /* priority queueing */
++ int do_prio_queueing;
++ int default_out_queue;
++};
++
++enum qeth_send_errors {
++ QETH_SEND_ERROR_NONE,
++ QETH_SEND_ERROR_LINK_FAILURE,
++ QETH_SEND_ERROR_RETRY,
++ QETH_SEND_ERROR_KICK_IT,
++};
++
++#define QETH_ETH_MAC_V4 0x0100 /* like v4 */
++#define QETH_ETH_MAC_V6 0x3333 /* like v6 */
++/* tr mc mac is longer, but that will be enough to detect mc frames */
++#define QETH_TR_MAC_NC 0xc000 /* non-canonical */
++#define QETH_TR_MAC_C 0x0300 /* canonical */
++
++#define DEFAULT_ADD_HHLEN 0
++#define MAX_ADD_HHLEN 1024
++
++/**
++ * buffer stuff for read channel
++ */
++#define QETH_CMD_BUFFER_NO 8
++
++/**
++ * channel state machine
++ */
++enum qeth_channel_states {
++ CH_STATE_UP,
++ CH_STATE_DOWN,
++ CH_STATE_ACTIVATING,
++ CH_STATE_HALTED,
++ CH_STATE_STOPPED,
++ CH_STATE_RCD,
++ CH_STATE_RCD_DONE,
++};
++/**
++ * card state machine
++ */
++enum qeth_card_states {
++ CARD_STATE_DOWN,
++ CARD_STATE_HARDSETUP,
++ CARD_STATE_SOFTSETUP,
++ CARD_STATE_UP,
++ CARD_STATE_RECOVER,
++};
++
++/**
++ * Protocol versions
++ */
++enum qeth_prot_versions {
++ QETH_PROT_IPV4 = 0x0004,
++ QETH_PROT_IPV6 = 0x0006,
++};
++
++enum qeth_ip_types {
++ QETH_IP_TYPE_NORMAL,
++ QETH_IP_TYPE_VIPA,
++ QETH_IP_TYPE_RXIP,
++ QETH_IP_TYPE_DEL_ALL_MC,
++};
++
++enum qeth_cmd_buffer_state {
++ BUF_STATE_FREE,
++ BUF_STATE_LOCKED,
++ BUF_STATE_PROCESSED,
++};
++
++struct qeth_ipato {
++ int enabled;
++ int invert4;
++ int invert6;
++ struct list_head entries;
++};
++
++struct qeth_channel;
++
++struct qeth_cmd_buffer {
++ enum qeth_cmd_buffer_state state;
++ struct qeth_channel *channel;
++ unsigned char *data;
++ int rc;
++ void (*callback) (struct qeth_channel *, struct qeth_cmd_buffer *);
++};
++
++/**
++ * definition of a qeth channel, used for read and write
++ */
++struct qeth_channel {
++ enum qeth_channel_states state;
++ struct ccw1 ccw;
++ spinlock_t iob_lock;
++ wait_queue_head_t wait_q;
++ struct tasklet_struct irq_tasklet;
++ struct ccw_device *ccwdev;
++/*command buffer for control data*/
++ struct qeth_cmd_buffer iob[QETH_CMD_BUFFER_NO];
++ atomic_t irq_pending;
++ int io_buf_no;
++ int buf_no;
++};
++
++/**
++ * OSA card related definitions
++ */
++struct qeth_token {
++ __u32 issuer_rm_w;
++ __u32 issuer_rm_r;
++ __u32 cm_filter_w;
++ __u32 cm_filter_r;
++ __u32 cm_connection_w;
++ __u32 cm_connection_r;
++ __u32 ulp_filter_w;
++ __u32 ulp_filter_r;
++ __u32 ulp_connection_w;
++ __u32 ulp_connection_r;
++};
++
++struct qeth_seqno {
++ __u32 trans_hdr;
++ __u32 pdu_hdr;
++ __u32 pdu_hdr_ack;
++ __u16 ipa;
++ __u32 pkt_seqno;
++};
++
++struct qeth_reply {
++ struct list_head list;
++ wait_queue_head_t wait_q;
++ int (*callback)(struct qeth_card *, struct qeth_reply *,
++ unsigned long);
++ u32 seqno;
++ unsigned long offset;
++ atomic_t received;
++ int rc;
++ void *param;
++ struct qeth_card *card;
++ atomic_t refcnt;
++};
++
++
++struct qeth_card_blkt {
++ int time_total;
++ int inter_packet;
++ int inter_packet_jumbo;
++};
++
++#define QETH_BROADCAST_WITH_ECHO 0x01
++#define QETH_BROADCAST_WITHOUT_ECHO 0x02
++#define QETH_LAYER2_MAC_READ 0x01
++#define QETH_LAYER2_MAC_REGISTERED 0x02
++struct qeth_card_info {
++ unsigned short unit_addr2;
++ unsigned short cula;
++ unsigned short chpid;
++ __u16 func_level;
++ char mcl_level[QETH_MCL_LENGTH + 1];
++ int guestlan;
++ int mac_bits;
++ int portname_required;
++ int portno;
++ char portname[9];
++ enum qeth_card_types type;
++ enum qeth_link_types link_type;
++ int is_multicast_different;
++ int initial_mtu;
++ int max_mtu;
++ int broadcast_capable;
++ int unique_id;
++ struct qeth_card_blkt blkt;
++ __u32 csum_mask;
++ enum qeth_ipa_promisc_modes promisc_mode;
++};
++
++struct qeth_card_options {
++ struct qeth_routing_info route4;
++ struct qeth_ipa_info ipa4;
++ struct qeth_ipa_info adp; /*Adapter parameters*/
++ struct qeth_routing_info route6;
++ struct qeth_ipa_info ipa6;
++ enum qeth_checksum_types checksum_type;
++ int broadcast_mode;
++ int macaddr_mode;
++ int fake_broadcast;
++ int add_hhlen;
++ int fake_ll;
++ int layer2;
++ enum qeth_large_send_types large_send;
++ int performance_stats;
++ int rx_sg_cb;
++};
++
++/*
++ * thread bits for qeth_card thread masks
++ */
++enum qeth_threads {
++ QETH_RECOVER_THREAD = 1,
++};
++
++struct qeth_osn_info {
++ int (*assist_cb)(struct net_device *dev, void *data);
++ int (*data_cb)(struct sk_buff *skb);
++};
++
++enum qeth_discipline_id {
++ QETH_DISCIPLINE_LAYER3 = 0,
++ QETH_DISCIPLINE_LAYER2 = 1,
++};
++
++struct qeth_discipline {
++ qdio_handler_t *input_handler;
++ qdio_handler_t *output_handler;
++ int (*recover)(void *ptr);
++ struct ccwgroup_driver *ccwgdriver;
++};
++
++struct qeth_vlan_vid {
++ struct list_head list;
++ unsigned short vid;
++};
++
++struct qeth_mc_mac {
++ struct list_head list;
++ __u8 mc_addr[MAX_ADDR_LEN];
++ unsigned char mc_addrlen;
++};
++
++struct qeth_card {
++ struct list_head list;
++ enum qeth_card_states state;
++ int lan_online;
++ spinlock_t lock;
++ struct ccwgroup_device *gdev;
++ struct qeth_channel read;
++ struct qeth_channel write;
++ struct qeth_channel data;
++
++ struct net_device *dev;
++ struct net_device_stats stats;
++
++ struct qeth_card_info info;
++ struct qeth_token token;
++ struct qeth_seqno seqno;
++ struct qeth_card_options options;
++
++ wait_queue_head_t wait_q;
++ spinlock_t vlanlock;
++ spinlock_t mclock;
++ struct vlan_group *vlangrp;
++ struct list_head vid_list;
++ struct list_head mc_list;
++ struct work_struct kernel_thread_starter;
++ spinlock_t thread_mask_lock;
++ unsigned long thread_start_mask;
++ unsigned long thread_allowed_mask;
++ unsigned long thread_running_mask;
++ spinlock_t ip_lock;
++ struct list_head ip_list;
++ struct list_head *ip_tbd_list;
++ struct qeth_ipato ipato;
++ struct list_head cmd_waiter_list;
++ /* QDIO buffer handling */
++ struct qeth_qdio_info qdio;
++ struct qeth_perf_stats perf_stats;
++ int use_hard_stop;
++ struct qeth_osn_info osn_info;
++ struct qeth_discipline discipline;
++ atomic_t force_alloc_skb;
++};
++
++struct qeth_card_list_struct {
++ struct list_head list;
++ rwlock_t rwlock;
++};
++
++/*some helper functions*/
++#define QETH_CARD_IFNAME(card) (((card)->dev)? (card)->dev->name : "")
++
++static inline struct qeth_card *CARD_FROM_CDEV(struct ccw_device *cdev)
++{
++ struct qeth_card *card = dev_get_drvdata(&((struct ccwgroup_device *)
++ dev_get_drvdata(&cdev->dev))->dev);
++ return card;
++}
++
++static inline int qeth_get_micros(void)
++{
++ return (int) (get_clock() >> 12);
++}
++
++static inline void *qeth_push_skb(struct qeth_card *card, struct sk_buff *skb,
++ int size)
++{
++ void *hdr;
++
++ hdr = (void *) skb_push(skb, size);
++ /*
++ * sanity check, the Linux memory allocation scheme should
++ * never present us cases like this one (the qdio header size plus
++ * the first 40 bytes of the paket cross a 4k boundary)
++ */
++ if ((((unsigned long) hdr) & (~(PAGE_SIZE - 1))) !=
++ (((unsigned long) hdr + size +
++ QETH_IP_HEADER_SIZE) & (~(PAGE_SIZE - 1)))) {
++ PRINT_ERR("Misaligned packet on interface %s. Discarded.",
++ QETH_CARD_IFNAME(card));
++ return NULL;
++ }
++ return hdr;
++}
++
++static inline int qeth_get_ip_version(struct sk_buff *skb)
++{
++ switch (skb->protocol) {
++ case ETH_P_IPV6:
++ return 6;
++ case ETH_P_IP:
++ return 4;
++ default:
++ return 0;
++ }
++}
++
++struct qeth_eddp_context;
++extern struct ccwgroup_driver qeth_l2_ccwgroup_driver;
++extern struct ccwgroup_driver qeth_l3_ccwgroup_driver;
++const char *qeth_get_cardname_short(struct qeth_card *);
++int qeth_realloc_buffer_pool(struct qeth_card *, int);
++int qeth_core_load_discipline(struct qeth_card *, enum qeth_discipline_id);
++void qeth_core_free_discipline(struct qeth_card *);
++int qeth_core_create_device_attributes(struct device *);
++void qeth_core_remove_device_attributes(struct device *);
++int qeth_core_create_osn_attributes(struct device *);
++void qeth_core_remove_osn_attributes(struct device *);
++
++/* exports for qeth discipline device drivers */
++extern struct qeth_card_list_struct qeth_core_card_list;
++
++extern struct qeth_dbf_info qeth_dbf[QETH_DBF_INFOS];
++
++void qeth_set_allowed_threads(struct qeth_card *, unsigned long , int);
++int qeth_threads_running(struct qeth_card *, unsigned long);
++int qeth_wait_for_threads(struct qeth_card *, unsigned long);
++int qeth_do_run_thread(struct qeth_card *, unsigned long);
++void qeth_clear_thread_start_bit(struct qeth_card *, unsigned long);
++void qeth_clear_thread_running_bit(struct qeth_card *, unsigned long);
++int qeth_core_hardsetup_card(struct qeth_card *);
++void qeth_print_status_message(struct qeth_card *);
++int qeth_init_qdio_queues(struct qeth_card *);
++int qeth_send_startlan(struct qeth_card *);
++int qeth_send_stoplan(struct qeth_card *);
++int qeth_send_ipa_cmd(struct qeth_card *, struct qeth_cmd_buffer *,
++ int (*reply_cb)
++ (struct qeth_card *, struct qeth_reply *, unsigned long),
++ void *);
++struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *,
++ enum qeth_ipa_cmds, enum qeth_prot_versions);
++int qeth_query_setadapterparms(struct qeth_card *);
++int qeth_check_qdio_errors(struct qdio_buffer *, unsigned int,
++ unsigned int, const char *);
++void qeth_put_buffer_pool_entry(struct qeth_card *,
++ struct qeth_buffer_pool_entry *);
++void qeth_queue_input_buffer(struct qeth_card *, int);
++struct sk_buff *qeth_core_get_next_skb(struct qeth_card *,
++ struct qdio_buffer *, struct qdio_buffer_element **, int *,
++ struct qeth_hdr **);
++void qeth_schedule_recovery(struct qeth_card *);
++void qeth_qdio_output_handler(struct ccw_device *, unsigned int,
++ unsigned int, unsigned int,
++ unsigned int, int, int,
++ unsigned long);
++void qeth_clear_ipacmd_list(struct qeth_card *);
++int qeth_qdio_clear_card(struct qeth_card *, int);
++void qeth_clear_working_pool_list(struct qeth_card *);
++void qeth_clear_cmd_buffers(struct qeth_channel *);
++void qeth_clear_qdio_buffers(struct qeth_card *);
++void qeth_setadp_promisc_mode(struct qeth_card *);
++struct net_device_stats *qeth_get_stats(struct net_device *);
++int qeth_change_mtu(struct net_device *, int);
++int qeth_setadpparms_change_macaddr(struct qeth_card *);
++void qeth_tx_timeout(struct net_device *);
++void qeth_prepare_control_data(struct qeth_card *, int,
++ struct qeth_cmd_buffer *);
++void qeth_release_buffer(struct qeth_channel *, struct qeth_cmd_buffer *);
++void qeth_prepare_ipa_cmd(struct qeth_card *, struct qeth_cmd_buffer *, char);
++struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *);
++int qeth_mdio_read(struct net_device *, int, int);
++int qeth_snmp_command(struct qeth_card *, char __user *);
++int qeth_set_large_send(struct qeth_card *, enum qeth_large_send_types);
++struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *, __u32, __u32);
++int qeth_default_setadapterparms_cb(struct qeth_card *, struct qeth_reply *,
++ unsigned long);
++int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *,
++ int (*reply_cb)(struct qeth_card *, struct qeth_reply*, unsigned long),
++ void *reply_param);
++int qeth_get_cast_type(struct qeth_card *, struct sk_buff *);
++int qeth_get_priority_queue(struct qeth_card *, struct sk_buff *, int, int);
++struct sk_buff *qeth_prepare_skb(struct qeth_card *, struct sk_buff *,
++ struct qeth_hdr **);
++int qeth_get_elements_no(struct qeth_card *, void *, struct sk_buff *, int);
++int qeth_do_send_packet_fast(struct qeth_card *, struct qeth_qdio_out_q *,
++ struct sk_buff *, struct qeth_hdr *, int,
++ struct qeth_eddp_context *);
++int qeth_do_send_packet(struct qeth_card *, struct qeth_qdio_out_q *,
++ struct sk_buff *, struct qeth_hdr *,
++ int, struct qeth_eddp_context *);
++int qeth_core_get_stats_count(struct net_device *);
++void qeth_core_get_ethtool_stats(struct net_device *,
++ struct ethtool_stats *, u64 *);
++void qeth_core_get_strings(struct net_device *, u32, u8 *);
++void qeth_core_get_drvinfo(struct net_device *, struct ethtool_drvinfo *);
++
++/* exports for OSN */
++int qeth_osn_assist(struct net_device *, void *, int);
++int qeth_osn_register(unsigned char *read_dev_no, struct net_device **,
++ int (*assist_cb)(struct net_device *, void *),
++ int (*data_cb)(struct sk_buff *));
++void qeth_osn_deregister(struct net_device *);
++
++#endif /* __QETH_CORE_H__ */
+diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
+new file mode 100644
+index 0000000..055f5c3
+--- /dev/null
++++ b/drivers/s390/net/qeth_core_main.c
+@@ -0,0 +1,4492 @@
++/*
++ * drivers/s390/net/qeth_core_main.c
++ *
++ * Copyright IBM Corp. 2007
++ * Author(s): Utz Bacher <utz.bacher at de.ibm.com>,
++ * Frank Pavlic <fpavlic at de.ibm.com>,
++ * Thomas Spatzier <tspat at de.ibm.com>,
++ * Frank Blaschka <frank.blaschka at de.ibm.com>
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/string.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/ip.h>
++#include <linux/ipv6.h>
++#include <linux/tcp.h>
++#include <linux/mii.h>
++#include <linux/kthread.h>
++
++#include <asm-s390/ebcdic.h>
++#include <asm-s390/io.h>
++#include <asm/s390_rdev.h>
++
++#include "qeth_core.h"
++#include "qeth_core_offl.h"
++
++static DEFINE_PER_CPU(char[256], qeth_core_dbf_txt_buf);
++#define QETH_DBF_TXT_BUF qeth_core_dbf_txt_buf
++
++struct qeth_dbf_info qeth_dbf[QETH_DBF_INFOS] = {
++ /* define dbf - Name, Pages, Areas, Maxlen, Level, View, Handle */
++ /* N P A M L V H */
++ [QETH_DBF_SETUP] = {"qeth_setup",
++ 8, 1, 8, 5, &debug_hex_ascii_view, NULL},
++ [QETH_DBF_QERR] = {"qeth_qerr",
++ 2, 1, 8, 2, &debug_hex_ascii_view, NULL},
++ [QETH_DBF_TRACE] = {"qeth_trace",
++ 4, 1, 8, 3, &debug_hex_ascii_view, NULL},
++ [QETH_DBF_MSG] = {"qeth_msg",
++ 8, 1, 128, 3, &debug_sprintf_view, NULL},
++ [QETH_DBF_SENSE] = {"qeth_sense",
++ 2, 1, 64, 2, &debug_hex_ascii_view, NULL},
++ [QETH_DBF_MISC] = {"qeth_misc",
++ 2, 1, 256, 2, &debug_hex_ascii_view, NULL},
++ [QETH_DBF_CTRL] = {"qeth_control",
++ 8, 1, QETH_DBF_CTRL_LEN, 5, &debug_hex_ascii_view, NULL},
++};
++EXPORT_SYMBOL_GPL(qeth_dbf);
++
++struct qeth_card_list_struct qeth_core_card_list;
++EXPORT_SYMBOL_GPL(qeth_core_card_list);
++
++static struct device *qeth_core_root_dev;
++static unsigned int known_devices[][10] = QETH_MODELLIST_ARRAY;
++static struct lock_class_key qdio_out_skb_queue_key;
++
++static void qeth_send_control_data_cb(struct qeth_channel *,
++ struct qeth_cmd_buffer *);
++static int qeth_issue_next_read(struct qeth_card *);
++static struct qeth_cmd_buffer *qeth_get_buffer(struct qeth_channel *);
++static void qeth_setup_ccw(struct qeth_channel *, unsigned char *, __u32);
++static void qeth_free_buffer_pool(struct qeth_card *);
++static int qeth_qdio_establish(struct qeth_card *);
++
++
++static inline void __qeth_fill_buffer_frag(struct sk_buff *skb,
++ struct qdio_buffer *buffer, int is_tso,
++ int *next_element_to_fill)
++{
++ struct skb_frag_struct *frag;
++ int fragno;
++ unsigned long addr;
++ int element, cnt, dlen;
++
++ fragno = skb_shinfo(skb)->nr_frags;
++ element = *next_element_to_fill;
++ dlen = 0;
++
++ if (is_tso)
++ buffer->element[element].flags =
++ SBAL_FLAGS_MIDDLE_FRAG;
++ else
++ buffer->element[element].flags =
++ SBAL_FLAGS_FIRST_FRAG;
++ dlen = skb->len - skb->data_len;
++ if (dlen) {
++ buffer->element[element].addr = skb->data;
++ buffer->element[element].length = dlen;
++ element++;
++ }
++ for (cnt = 0; cnt < fragno; cnt++) {
++ frag = &skb_shinfo(skb)->frags[cnt];
++ addr = (page_to_pfn(frag->page) << PAGE_SHIFT) +
++ frag->page_offset;
++ buffer->element[element].addr = (char *)addr;
++ buffer->element[element].length = frag->size;
++ if (cnt < (fragno - 1))
++ buffer->element[element].flags =
++ SBAL_FLAGS_MIDDLE_FRAG;
++ else
++ buffer->element[element].flags =
++ SBAL_FLAGS_LAST_FRAG;
++ element++;
++ }
++ *next_element_to_fill = element;
++}
++
++static inline const char *qeth_get_cardname(struct qeth_card *card)
++{
++ if (card->info.guestlan) {
++ switch (card->info.type) {
++ case QETH_CARD_TYPE_OSAE:
++ return " Guest LAN QDIO";
++ case QETH_CARD_TYPE_IQD:
++ return " Guest LAN Hiper";
++ default:
++ return " unknown";
++ }
++ } else {
++ switch (card->info.type) {
++ case QETH_CARD_TYPE_OSAE:
++ return " OSD Express";
++ case QETH_CARD_TYPE_IQD:
++ return " HiperSockets";
++ case QETH_CARD_TYPE_OSN:
++ return " OSN QDIO";
++ default:
++ return " unknown";
++ }
++ }
++ return " n/a";
++}
++
++/* max length to be returned: 14 */
++const char *qeth_get_cardname_short(struct qeth_card *card)
++{
++ if (card->info.guestlan) {
++ switch (card->info.type) {
++ case QETH_CARD_TYPE_OSAE:
++ return "GuestLAN QDIO";
++ case QETH_CARD_TYPE_IQD:
++ return "GuestLAN Hiper";
++ default:
++ return "unknown";
++ }
++ } else {
++ switch (card->info.type) {
++ case QETH_CARD_TYPE_OSAE:
++ switch (card->info.link_type) {
++ case QETH_LINK_TYPE_FAST_ETH:
++ return "OSD_100";
++ case QETH_LINK_TYPE_HSTR:
++ return "HSTR";
++ case QETH_LINK_TYPE_GBIT_ETH:
++ return "OSD_1000";
++ case QETH_LINK_TYPE_10GBIT_ETH:
++ return "OSD_10GIG";
++ case QETH_LINK_TYPE_LANE_ETH100:
++ return "OSD_FE_LANE";
++ case QETH_LINK_TYPE_LANE_TR:
++ return "OSD_TR_LANE";
++ case QETH_LINK_TYPE_LANE_ETH1000:
++ return "OSD_GbE_LANE";
++ case QETH_LINK_TYPE_LANE:
++ return "OSD_ATM_LANE";
++ default:
++ return "OSD_Express";
++ }
++ case QETH_CARD_TYPE_IQD:
++ return "HiperSockets";
++ case QETH_CARD_TYPE_OSN:
++ return "OSN";
++ default:
++ return "unknown";
++ }
++ }
++ return "n/a";
++}
++
++void qeth_set_allowed_threads(struct qeth_card *card, unsigned long threads,
++ int clear_start_mask)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&card->thread_mask_lock, flags);
++ card->thread_allowed_mask = threads;
++ if (clear_start_mask)
++ card->thread_start_mask &= threads;
++ spin_unlock_irqrestore(&card->thread_mask_lock, flags);
++ wake_up(&card->wait_q);
++}
++EXPORT_SYMBOL_GPL(qeth_set_allowed_threads);
++
++int qeth_threads_running(struct qeth_card *card, unsigned long threads)
++{
++ unsigned long flags;
++ int rc = 0;
++
++ spin_lock_irqsave(&card->thread_mask_lock, flags);
++ rc = (card->thread_running_mask & threads);
++ spin_unlock_irqrestore(&card->thread_mask_lock, flags);
++ return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_threads_running);
++
++int qeth_wait_for_threads(struct qeth_card *card, unsigned long threads)
++{
++ return wait_event_interruptible(card->wait_q,
++ qeth_threads_running(card, threads) == 0);
++}
++EXPORT_SYMBOL_GPL(qeth_wait_for_threads);
++
++void qeth_clear_working_pool_list(struct qeth_card *card)
++{
++ struct qeth_buffer_pool_entry *pool_entry, *tmp;
++
++ QETH_DBF_TEXT(TRACE, 5, "clwrklst");
++ list_for_each_entry_safe(pool_entry, tmp,
++ &card->qdio.in_buf_pool.entry_list, list){
++ list_del(&pool_entry->list);
++ }
++}
++EXPORT_SYMBOL_GPL(qeth_clear_working_pool_list);
++
++static int qeth_alloc_buffer_pool(struct qeth_card *card)
++{
++ struct qeth_buffer_pool_entry *pool_entry;
++ void *ptr;
++ int i, j;
++
++ QETH_DBF_TEXT(TRACE, 5, "alocpool");
++ for (i = 0; i < card->qdio.init_pool.buf_count; ++i) {
++ pool_entry = kmalloc(sizeof(*pool_entry), GFP_KERNEL);
++ if (!pool_entry) {
++ qeth_free_buffer_pool(card);
++ return -ENOMEM;
++ }
++ for (j = 0; j < QETH_MAX_BUFFER_ELEMENTS(card); ++j) {
++ ptr = (void *) __get_free_page(GFP_KERNEL);
++ if (!ptr) {
++ while (j > 0)
++ free_page((unsigned long)
++ pool_entry->elements[--j]);
++ kfree(pool_entry);
++ qeth_free_buffer_pool(card);
++ return -ENOMEM;
++ }
++ pool_entry->elements[j] = ptr;
++ }
++ list_add(&pool_entry->init_list,
++ &card->qdio.init_pool.entry_list);
++ }
++ return 0;
++}
++
++int qeth_realloc_buffer_pool(struct qeth_card *card, int bufcnt)
++{
++ QETH_DBF_TEXT(TRACE, 2, "realcbp");
++
++ if ((card->state != CARD_STATE_DOWN) &&
++ (card->state != CARD_STATE_RECOVER))
++ return -EPERM;
++
++ /* TODO: steel/add buffers from/to a running card's buffer pool (?) */
++ qeth_clear_working_pool_list(card);
++ qeth_free_buffer_pool(card);
++ card->qdio.in_buf_pool.buf_count = bufcnt;
++ card->qdio.init_pool.buf_count = bufcnt;
++ return qeth_alloc_buffer_pool(card);
++}
++
++int qeth_set_large_send(struct qeth_card *card,
++ enum qeth_large_send_types type)
++{
++ int rc = 0;
++
++ if (card->dev == NULL) {
++ card->options.large_send = type;
++ return 0;
++ }
++ if (card->state == CARD_STATE_UP)
++ netif_tx_disable(card->dev);
++ card->options.large_send = type;
++ switch (card->options.large_send) {
++ case QETH_LARGE_SEND_EDDP:
++ card->dev->features |= NETIF_F_TSO | NETIF_F_SG |
++ NETIF_F_HW_CSUM;
++ break;
++ case QETH_LARGE_SEND_TSO:
++ if (qeth_is_supported(card, IPA_OUTBOUND_TSO)) {
++ card->dev->features |= NETIF_F_TSO | NETIF_F_SG |
++ NETIF_F_HW_CSUM;
++ } else {
++ PRINT_WARN("TSO not supported on %s. "
++ "large_send set to 'no'.\n",
++ card->dev->name);
++ card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
++ NETIF_F_HW_CSUM);
++ card->options.large_send = QETH_LARGE_SEND_NO;
++ rc = -EOPNOTSUPP;
++ }
++ break;
++ default: /* includes QETH_LARGE_SEND_NO */
++ card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
++ NETIF_F_HW_CSUM);
++ break;
++ }
++ if (card->state == CARD_STATE_UP)
++ netif_wake_queue(card->dev);
++ return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_set_large_send);
++
++static int qeth_issue_next_read(struct qeth_card *card)
++{
++ int rc;
++ struct qeth_cmd_buffer *iob;
++
++ QETH_DBF_TEXT(TRACE, 5, "issnxrd");
++ if (card->read.state != CH_STATE_UP)
++ return -EIO;
++ iob = qeth_get_buffer(&card->read);
++ if (!iob) {
++ PRINT_WARN("issue_next_read failed: no iob available!\n");
++ return -ENOMEM;
++ }
++ qeth_setup_ccw(&card->read, iob->data, QETH_BUFSIZE);
++ QETH_DBF_TEXT(TRACE, 6, "noirqpnd");
++ rc = ccw_device_start(card->read.ccwdev, &card->read.ccw,
++ (addr_t) iob, 0, 0);
++ if (rc) {
++ PRINT_ERR("Error in starting next read ccw! rc=%i\n", rc);
++ atomic_set(&card->read.irq_pending, 0);
++ qeth_schedule_recovery(card);
++ wake_up(&card->wait_q);
++ }
++ return rc;
++}
++
++static struct qeth_reply *qeth_alloc_reply(struct qeth_card *card)
++{
++ struct qeth_reply *reply;
++
++ reply = kzalloc(sizeof(struct qeth_reply), GFP_ATOMIC);
++ if (reply) {
++ atomic_set(&reply->refcnt, 1);
++ atomic_set(&reply->received, 0);
++ reply->card = card;
++ };
++ return reply;
++}
++
++static void qeth_get_reply(struct qeth_reply *reply)
++{
++ WARN_ON(atomic_read(&reply->refcnt) <= 0);
++ atomic_inc(&reply->refcnt);
++}
++
++static void qeth_put_reply(struct qeth_reply *reply)
++{
++ WARN_ON(atomic_read(&reply->refcnt) <= 0);
++ if (atomic_dec_and_test(&reply->refcnt))
++ kfree(reply);
++}
++
++static void qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd, int rc,
++ struct qeth_card *card)
++{
++ char *ipa_name;
++ int com = cmd->hdr.command;
++ ipa_name = qeth_get_ipa_cmd_name(com);
++ if (rc)
++ QETH_DBF_MESSAGE(2, "IPA: %s(x%X) for %s returned x%X \"%s\"\n",
++ ipa_name, com, QETH_CARD_IFNAME(card),
++ rc, qeth_get_ipa_msg(rc));
++ else
++ QETH_DBF_MESSAGE(5, "IPA: %s(x%X) for %s succeeded\n",
++ ipa_name, com, QETH_CARD_IFNAME(card));
++}
++
++static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card,
++ struct qeth_cmd_buffer *iob)
++{
++ struct qeth_ipa_cmd *cmd = NULL;
++
++ QETH_DBF_TEXT(TRACE, 5, "chkipad");
++ if (IS_IPA(iob->data)) {
++ cmd = (struct qeth_ipa_cmd *) PDU_ENCAPSULATION(iob->data);
++ if (IS_IPA_REPLY(cmd)) {
++ if (cmd->hdr.command < IPA_CMD_SETCCID ||
++ cmd->hdr.command > IPA_CMD_MODCCID)
++ qeth_issue_ipa_msg(cmd,
++ cmd->hdr.return_code, card);
++ return cmd;
++ } else {
++ switch (cmd->hdr.command) {
++ case IPA_CMD_STOPLAN:
++ PRINT_WARN("Link failure on %s (CHPID 0x%X) - "
++ "there is a network problem or "
++ "someone pulled the cable or "
++ "disabled the port.\n",
++ QETH_CARD_IFNAME(card),
++ card->info.chpid);
++ card->lan_online = 0;
++ if (card->dev && netif_carrier_ok(card->dev))
++ netif_carrier_off(card->dev);
++ return NULL;
++ case IPA_CMD_STARTLAN:
++ PRINT_INFO("Link reestablished on %s "
++ "(CHPID 0x%X). Scheduling "
++ "IP address reset.\n",
++ QETH_CARD_IFNAME(card),
++ card->info.chpid);
++ netif_carrier_on(card->dev);
++ card->lan_online = 1;
++ qeth_schedule_recovery(card);
++ return NULL;
++ case IPA_CMD_MODCCID:
++ return cmd;
++ case IPA_CMD_REGISTER_LOCAL_ADDR:
++ QETH_DBF_TEXT(TRACE, 3, "irla");
++ break;
++ case IPA_CMD_UNREGISTER_LOCAL_ADDR:
++ QETH_DBF_TEXT(TRACE, 3, "urla");
++ break;
++ default:
++ PRINT_WARN("Received data is IPA "
++ "but not a reply!\n");
++ break;
++ }
++ }
++ }
++ return cmd;
++}
++
++void qeth_clear_ipacmd_list(struct qeth_card *card)
++{
++ struct qeth_reply *reply, *r;
++ unsigned long flags;
++
++ QETH_DBF_TEXT(TRACE, 4, "clipalst");
++
++ spin_lock_irqsave(&card->lock, flags);
++ list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
++ qeth_get_reply(reply);
++ reply->rc = -EIO;
++ atomic_inc(&reply->received);
++ list_del_init(&reply->list);
++ wake_up(&reply->wait_q);
++ qeth_put_reply(reply);
++ }
++ spin_unlock_irqrestore(&card->lock, flags);
++}
++EXPORT_SYMBOL_GPL(qeth_clear_ipacmd_list);
++
++static int qeth_check_idx_response(unsigned char *buffer)
++{
++ if (!buffer)
++ return 0;
++
++ QETH_DBF_HEX(CTRL, 2, buffer, QETH_DBF_CTRL_LEN);
++ if ((buffer[2] & 0xc0) == 0xc0) {
++ PRINT_WARN("received an IDX TERMINATE "
++ "with cause code 0x%02x%s\n",
++ buffer[4],
++ ((buffer[4] == 0x22) ?
++ " -- try another portname" : ""));
++ QETH_DBF_TEXT(TRACE, 2, "ckidxres");
++ QETH_DBF_TEXT(TRACE, 2, " idxterm");
++ QETH_DBF_TEXT_(TRACE, 2, " rc%d", -EIO);
++ return -EIO;
++ }
++ return 0;
++}
++
++static void qeth_setup_ccw(struct qeth_channel *channel, unsigned char *iob,
++ __u32 len)
++{
++ struct qeth_card *card;
++
++ QETH_DBF_TEXT(TRACE, 4, "setupccw");
++ card = CARD_FROM_CDEV(channel->ccwdev);
++ if (channel == &card->read)
++ memcpy(&channel->ccw, READ_CCW, sizeof(struct ccw1));
++ else
++ memcpy(&channel->ccw, WRITE_CCW, sizeof(struct ccw1));
++ channel->ccw.count = len;
++ channel->ccw.cda = (__u32) __pa(iob);
++}
++
++static struct qeth_cmd_buffer *__qeth_get_buffer(struct qeth_channel *channel)
++{
++ __u8 index;
++
++ QETH_DBF_TEXT(TRACE, 6, "getbuff");
++ index = channel->io_buf_no;
++ do {
++ if (channel->iob[index].state == BUF_STATE_FREE) {
++ channel->iob[index].state = BUF_STATE_LOCKED;
++ channel->io_buf_no = (channel->io_buf_no + 1) %
++ QETH_CMD_BUFFER_NO;
++ memset(channel->iob[index].data, 0, QETH_BUFSIZE);
++ return channel->iob + index;
++ }
++ index = (index + 1) % QETH_CMD_BUFFER_NO;
++ } while (index != channel->io_buf_no);
++
++ return NULL;
++}
++
++void qeth_release_buffer(struct qeth_channel *channel,
++ struct qeth_cmd_buffer *iob)
++{
++ unsigned long flags;
++
++ QETH_DBF_TEXT(TRACE, 6, "relbuff");
++ spin_lock_irqsave(&channel->iob_lock, flags);
++ memset(iob->data, 0, QETH_BUFSIZE);
++ iob->state = BUF_STATE_FREE;
++ iob->callback = qeth_send_control_data_cb;
++ iob->rc = 0;
++ spin_unlock_irqrestore(&channel->iob_lock, flags);
++}
++EXPORT_SYMBOL_GPL(qeth_release_buffer);
++
++static struct qeth_cmd_buffer *qeth_get_buffer(struct qeth_channel *channel)
++{
++ struct qeth_cmd_buffer *buffer = NULL;
++ unsigned long flags;
++
++ spin_lock_irqsave(&channel->iob_lock, flags);
++ buffer = __qeth_get_buffer(channel);
++ spin_unlock_irqrestore(&channel->iob_lock, flags);
++ return buffer;
++}
++
++struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *channel)
++{
++ struct qeth_cmd_buffer *buffer;
++ wait_event(channel->wait_q,
++ ((buffer = qeth_get_buffer(channel)) != NULL));
++ return buffer;
++}
++EXPORT_SYMBOL_GPL(qeth_wait_for_buffer);
++
++void qeth_clear_cmd_buffers(struct qeth_channel *channel)
++{
++ int cnt;
++
++ for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++)
++ qeth_release_buffer(channel, &channel->iob[cnt]);
++ channel->buf_no = 0;
++ channel->io_buf_no = 0;
++}
++EXPORT_SYMBOL_GPL(qeth_clear_cmd_buffers);
++
++static void qeth_send_control_data_cb(struct qeth_channel *channel,
++ struct qeth_cmd_buffer *iob)
++{
++ struct qeth_card *card;
++ struct qeth_reply *reply, *r;
++ struct qeth_ipa_cmd *cmd;
++ unsigned long flags;
++ int keep_reply;
++
++ QETH_DBF_TEXT(TRACE, 4, "sndctlcb");
++
++ card = CARD_FROM_CDEV(channel->ccwdev);
++ if (qeth_check_idx_response(iob->data)) {
++ qeth_clear_ipacmd_list(card);
++ qeth_schedule_recovery(card);
++ goto out;
++ }
++
++ cmd = qeth_check_ipa_data(card, iob);
++ if ((cmd == NULL) && (card->state != CARD_STATE_DOWN))
++ goto out;
++ /*in case of OSN : check if cmd is set */
++ if (card->info.type == QETH_CARD_TYPE_OSN &&
++ cmd &&
++ cmd->hdr.command != IPA_CMD_STARTLAN &&
++ card->osn_info.assist_cb != NULL) {
++ card->osn_info.assist_cb(card->dev, cmd);
++ goto out;
++ }
++
++ spin_lock_irqsave(&card->lock, flags);
++ list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
++ if ((reply->seqno == QETH_IDX_COMMAND_SEQNO) ||
++ ((cmd) && (reply->seqno == cmd->hdr.seqno))) {
++ qeth_get_reply(reply);
++ list_del_init(&reply->list);
++ spin_unlock_irqrestore(&card->lock, flags);
++ keep_reply = 0;
++ if (reply->callback != NULL) {
++ if (cmd) {
++ reply->offset = (__u16)((char *)cmd -
++ (char *)iob->data);
++ keep_reply = reply->callback(card,
++ reply,
++ (unsigned long)cmd);
++ } else
++ keep_reply = reply->callback(card,
++ reply,
++ (unsigned long)iob);
++ }
++ if (cmd)
++ reply->rc = (u16) cmd->hdr.return_code;
++ else if (iob->rc)
++ reply->rc = iob->rc;
++ if (keep_reply) {
++ spin_lock_irqsave(&card->lock, flags);
++ list_add_tail(&reply->list,
++ &card->cmd_waiter_list);
++ spin_unlock_irqrestore(&card->lock, flags);
++ } else {
++ atomic_inc(&reply->received);
++ wake_up(&reply->wait_q);
++ }
++ qeth_put_reply(reply);
++ goto out;
++ }
++ }
++ spin_unlock_irqrestore(&card->lock, flags);
++out:
++ memcpy(&card->seqno.pdu_hdr_ack,
++ QETH_PDU_HEADER_SEQ_NO(iob->data),
++ QETH_SEQ_NO_LENGTH);
++ qeth_release_buffer(channel, iob);
++}
++
++static int qeth_setup_channel(struct qeth_channel *channel)
++{
++ int cnt;
++
++ QETH_DBF_TEXT(SETUP, 2, "setupch");
++ for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++) {
++ channel->iob[cnt].data = (char *)
++ kmalloc(QETH_BUFSIZE, GFP_DMA|GFP_KERNEL);
++ if (channel->iob[cnt].data == NULL)
++ break;
++ channel->iob[cnt].state = BUF_STATE_FREE;
++ channel->iob[cnt].channel = channel;
++ channel->iob[cnt].callback = qeth_send_control_data_cb;
++ channel->iob[cnt].rc = 0;
++ }
++ if (cnt < QETH_CMD_BUFFER_NO) {
++ while (cnt-- > 0)
++ kfree(channel->iob[cnt].data);
++ return -ENOMEM;
++ }
++ channel->buf_no = 0;
++ channel->io_buf_no = 0;
++ atomic_set(&channel->irq_pending, 0);
++ spin_lock_init(&channel->iob_lock);
++
++ init_waitqueue_head(&channel->wait_q);
++ return 0;
++}
++
++static int qeth_set_thread_start_bit(struct qeth_card *card,
++ unsigned long thread)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&card->thread_mask_lock, flags);
++ if (!(card->thread_allowed_mask & thread) ||
++ (card->thread_start_mask & thread)) {
++ spin_unlock_irqrestore(&card->thread_mask_lock, flags);
++ return -EPERM;
++ }
++ card->thread_start_mask |= thread;
++ spin_unlock_irqrestore(&card->thread_mask_lock, flags);
++ return 0;
++}
++
++void qeth_clear_thread_start_bit(struct qeth_card *card, unsigned long thread)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&card->thread_mask_lock, flags);
++ card->thread_start_mask &= ~thread;
++ spin_unlock_irqrestore(&card->thread_mask_lock, flags);
++ wake_up(&card->wait_q);
++}
++EXPORT_SYMBOL_GPL(qeth_clear_thread_start_bit);
++
++void qeth_clear_thread_running_bit(struct qeth_card *card, unsigned long thread)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&card->thread_mask_lock, flags);
++ card->thread_running_mask &= ~thread;
++ spin_unlock_irqrestore(&card->thread_mask_lock, flags);
++ wake_up(&card->wait_q);
++}
++EXPORT_SYMBOL_GPL(qeth_clear_thread_running_bit);
++
++static int __qeth_do_run_thread(struct qeth_card *card, unsigned long thread)
++{
++ unsigned long flags;
++ int rc = 0;
++
++ spin_lock_irqsave(&card->thread_mask_lock, flags);
++ if (card->thread_start_mask & thread) {
++ if ((card->thread_allowed_mask & thread) &&
++ !(card->thread_running_mask & thread)) {
++ rc = 1;
++ card->thread_start_mask &= ~thread;
++ card->thread_running_mask |= thread;
++ } else
++ rc = -EPERM;
++ }
++ spin_unlock_irqrestore(&card->thread_mask_lock, flags);
++ return rc;
++}
++
++int qeth_do_run_thread(struct qeth_card *card, unsigned long thread)
++{
++ int rc = 0;
++
++ wait_event(card->wait_q,
++ (rc = __qeth_do_run_thread(card, thread)) >= 0);
++ return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_do_run_thread);
++
++void qeth_schedule_recovery(struct qeth_card *card)
++{
++ QETH_DBF_TEXT(TRACE, 2, "startrec");
++ if (qeth_set_thread_start_bit(card, QETH_RECOVER_THREAD) == 0)
++ schedule_work(&card->kernel_thread_starter);
++}
++EXPORT_SYMBOL_GPL(qeth_schedule_recovery);
++
++static int qeth_get_problem(struct ccw_device *cdev, struct irb *irb)
++{
++ int dstat, cstat;
++ char *sense;
++
++ sense = (char *) irb->ecw;
++ cstat = irb->scsw.cstat;
++ dstat = irb->scsw.dstat;
++
++ if (cstat & (SCHN_STAT_CHN_CTRL_CHK | SCHN_STAT_INTF_CTRL_CHK |
++ SCHN_STAT_CHN_DATA_CHK | SCHN_STAT_CHAIN_CHECK |
++ SCHN_STAT_PROT_CHECK | SCHN_STAT_PROG_CHECK)) {
++ QETH_DBF_TEXT(TRACE, 2, "CGENCHK");
++ PRINT_WARN("check on device %s, dstat=x%x, cstat=x%x ",
++ cdev->dev.bus_id, dstat, cstat);
++ print_hex_dump(KERN_WARNING, "qeth: irb ", DUMP_PREFIX_OFFSET,
++ 16, 1, irb, 64, 1);
++ return 1;
++ }
++
++ if (dstat & DEV_STAT_UNIT_CHECK) {
++ if (sense[SENSE_RESETTING_EVENT_BYTE] &
++ SENSE_RESETTING_EVENT_FLAG) {
++ QETH_DBF_TEXT(TRACE, 2, "REVIND");
++ return 1;
++ }
++ if (sense[SENSE_COMMAND_REJECT_BYTE] &
++ SENSE_COMMAND_REJECT_FLAG) {
++ QETH_DBF_TEXT(TRACE, 2, "CMDREJi");
++ return 0;
++ }
++ if ((sense[2] == 0xaf) && (sense[3] == 0xfe)) {
++ QETH_DBF_TEXT(TRACE, 2, "AFFE");
++ return 1;
++ }
++ if ((!sense[0]) && (!sense[1]) && (!sense[2]) && (!sense[3])) {
++ QETH_DBF_TEXT(TRACE, 2, "ZEROSEN");
++ return 0;
++ }
++ QETH_DBF_TEXT(TRACE, 2, "DGENCHK");
++ return 1;
++ }
++ return 0;
++}
++
++static long __qeth_check_irb_error(struct ccw_device *cdev,
++ unsigned long intparm, struct irb *irb)
++{
++ if (!IS_ERR(irb))
++ return 0;
++
++ switch (PTR_ERR(irb)) {
++ case -EIO:
++ PRINT_WARN("i/o-error on device %s\n", cdev->dev.bus_id);
++ QETH_DBF_TEXT(TRACE, 2, "ckirberr");
++ QETH_DBF_TEXT_(TRACE, 2, " rc%d", -EIO);
++ break;
++ case -ETIMEDOUT:
++ PRINT_WARN("timeout on device %s\n", cdev->dev.bus_id);
++ QETH_DBF_TEXT(TRACE, 2, "ckirberr");
++ QETH_DBF_TEXT_(TRACE, 2, " rc%d", -ETIMEDOUT);
++ if (intparm == QETH_RCD_PARM) {
++ struct qeth_card *card = CARD_FROM_CDEV(cdev);
++
++ if (card && (card->data.ccwdev == cdev)) {
++ card->data.state = CH_STATE_DOWN;
++ wake_up(&card->wait_q);
++ }
++ }
++ break;
++ default:
++ PRINT_WARN("unknown error %ld on device %s\n", PTR_ERR(irb),
++ cdev->dev.bus_id);
++ QETH_DBF_TEXT(TRACE, 2, "ckirberr");
++ QETH_DBF_TEXT(TRACE, 2, " rc???");
++ }
++ return PTR_ERR(irb);
++}
++
++static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
++ struct irb *irb)
++{
++ int rc;
++ int cstat, dstat;
++ struct qeth_cmd_buffer *buffer;
++ struct qeth_channel *channel;
++ struct qeth_card *card;
++ struct qeth_cmd_buffer *iob;
++ __u8 index;
++
++ QETH_DBF_TEXT(TRACE, 5, "irq");
++
++ if (__qeth_check_irb_error(cdev, intparm, irb))
++ return;
++ cstat = irb->scsw.cstat;
++ dstat = irb->scsw.dstat;
++
++ card = CARD_FROM_CDEV(cdev);
++ if (!card)
++ return;
++
++ if (card->read.ccwdev == cdev) {
++ channel = &card->read;
++ QETH_DBF_TEXT(TRACE, 5, "read");
++ } else if (card->write.ccwdev == cdev) {
++ channel = &card->write;
++ QETH_DBF_TEXT(TRACE, 5, "write");
++ } else {
++ channel = &card->data;
++ QETH_DBF_TEXT(TRACE, 5, "data");
++ }
++ atomic_set(&channel->irq_pending, 0);
++
++ if (irb->scsw.fctl & (SCSW_FCTL_CLEAR_FUNC))
++ channel->state = CH_STATE_STOPPED;
++
++ if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC))
++ channel->state = CH_STATE_HALTED;
++
++ /*let's wake up immediately on data channel*/
++ if ((channel == &card->data) && (intparm != 0) &&
++ (intparm != QETH_RCD_PARM))
++ goto out;
++
++ if (intparm == QETH_CLEAR_CHANNEL_PARM) {
++ QETH_DBF_TEXT(TRACE, 6, "clrchpar");
++ /* we don't have to handle this further */
++ intparm = 0;
++ }
++ if (intparm == QETH_HALT_CHANNEL_PARM) {
++ QETH_DBF_TEXT(TRACE, 6, "hltchpar");
++ /* we don't have to handle this further */
++ intparm = 0;
++ }
++ if ((dstat & DEV_STAT_UNIT_EXCEP) ||
++ (dstat & DEV_STAT_UNIT_CHECK) ||
++ (cstat)) {
++ if (irb->esw.esw0.erw.cons) {
++ /* TODO: we should make this s390dbf */
++ PRINT_WARN("sense data available on channel %s.\n",
++ CHANNEL_ID(channel));
++ PRINT_WARN(" cstat 0x%X\n dstat 0x%X\n", cstat, dstat);
++ print_hex_dump(KERN_WARNING, "qeth: irb ",
++ DUMP_PREFIX_OFFSET, 16, 1, irb, 32, 1);
++ print_hex_dump(KERN_WARNING, "qeth: sense data ",
++ DUMP_PREFIX_OFFSET, 16, 1, irb->ecw, 32, 1);
++ }
++ if (intparm == QETH_RCD_PARM) {
++ channel->state = CH_STATE_DOWN;
++ goto out;
++ }
++ rc = qeth_get_problem(cdev, irb);
++ if (rc) {
++ qeth_schedule_recovery(card);
++ goto out;
++ }
++ }
++
++ if (intparm == QETH_RCD_PARM) {
++ channel->state = CH_STATE_RCD_DONE;
++ goto out;
++ }
++ if (intparm) {
++ buffer = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
++ buffer->state = BUF_STATE_PROCESSED;
++ }
++ if (channel == &card->data)
++ return;
++ if (channel == &card->read &&
++ channel->state == CH_STATE_UP)
++ qeth_issue_next_read(card);
++
++ iob = channel->iob;
++ index = channel->buf_no;
++ while (iob[index].state == BUF_STATE_PROCESSED) {
++ if (iob[index].callback != NULL)
++ iob[index].callback(channel, iob + index);
++
++ index = (index + 1) % QETH_CMD_BUFFER_NO;
++ }
++ channel->buf_no = index;
++out:
++ wake_up(&card->wait_q);
++ return;
++}
++
++static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
++ struct qeth_qdio_out_buffer *buf)
++{
++ int i;
++ struct sk_buff *skb;
++
++ /* is PCI flag set on buffer? */
++ if (buf->buffer->element[0].flags & 0x40)
++ atomic_dec(&queue->set_pci_flags_count);
++
++ skb = skb_dequeue(&buf->skb_list);
++ while (skb) {
++ atomic_dec(&skb->users);
++ dev_kfree_skb_any(skb);
++ skb = skb_dequeue(&buf->skb_list);
++ }
++ qeth_eddp_buf_release_contexts(buf);
++ for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(queue->card); ++i) {
++ buf->buffer->element[i].length = 0;
++ buf->buffer->element[i].addr = NULL;
++ buf->buffer->element[i].flags = 0;
++ }
++ buf->next_element_to_fill = 0;
++ atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY);
++}
++
++void qeth_clear_qdio_buffers(struct qeth_card *card)
++{
++ int i, j;
++
++ QETH_DBF_TEXT(TRACE, 2, "clearqdbf");
++ /* clear outbound buffers to free skbs */
++ for (i = 0; i < card->qdio.no_out_queues; ++i)
++ if (card->qdio.out_qs[i]) {
++ for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
++ qeth_clear_output_buffer(card->qdio.out_qs[i],
++ &card->qdio.out_qs[i]->bufs[j]);
++ }
++}
++EXPORT_SYMBOL_GPL(qeth_clear_qdio_buffers);
++
++static void qeth_free_buffer_pool(struct qeth_card *card)
++{
++ struct qeth_buffer_pool_entry *pool_entry, *tmp;
++ int i = 0;
++ QETH_DBF_TEXT(TRACE, 5, "freepool");
++ list_for_each_entry_safe(pool_entry, tmp,
++ &card->qdio.init_pool.entry_list, init_list){
++ for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i)
++ free_page((unsigned long)pool_entry->elements[i]);
++ list_del(&pool_entry->init_list);
++ kfree(pool_entry);
++ }
++}
++
++static void qeth_free_qdio_buffers(struct qeth_card *card)
++{
++ int i, j;
++
++ QETH_DBF_TEXT(TRACE, 2, "freeqdbf");
++ if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) ==
++ QETH_QDIO_UNINITIALIZED)
++ return;
++ kfree(card->qdio.in_q);
++ card->qdio.in_q = NULL;
++ /* inbound buffer pool */
++ qeth_free_buffer_pool(card);
++ /* free outbound qdio_qs */
++ if (card->qdio.out_qs) {
++ for (i = 0; i < card->qdio.no_out_queues; ++i) {
++ for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
++ qeth_clear_output_buffer(card->qdio.out_qs[i],
++ &card->qdio.out_qs[i]->bufs[j]);
++ kfree(card->qdio.out_qs[i]);
++ }
++ kfree(card->qdio.out_qs);
++ card->qdio.out_qs = NULL;
++ }
++}
++
++static void qeth_clean_channel(struct qeth_channel *channel)
++{
++ int cnt;
++
++ QETH_DBF_TEXT(SETUP, 2, "freech");
++ for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++)
++ kfree(channel->iob[cnt].data);
++}
++
++static int qeth_is_1920_device(struct qeth_card *card)
++{
++ int single_queue = 0;
++ struct ccw_device *ccwdev;
++ struct channelPath_dsc {
++ u8 flags;
++ u8 lsn;
++ u8 desc;
++ u8 chpid;
++ u8 swla;
++ u8 zeroes;
++ u8 chla;
++ u8 chpp;
++ } *chp_dsc;
++
++ QETH_DBF_TEXT(SETUP, 2, "chk_1920");
++
++ ccwdev = card->data.ccwdev;
++ chp_dsc = (struct channelPath_dsc *)ccw_device_get_chp_desc(ccwdev, 0);
++ if (chp_dsc != NULL) {
++ /* CHPP field bit 6 == 1 -> single queue */
++ single_queue = ((chp_dsc->chpp & 0x02) == 0x02);
++ kfree(chp_dsc);
++ }
++ QETH_DBF_TEXT_(SETUP, 2, "rc:%x", single_queue);
++ return single_queue;
++}
++
++static void qeth_init_qdio_info(struct qeth_card *card)
++{
++ QETH_DBF_TEXT(SETUP, 4, "intqdinf");
++ atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED);
++ /* inbound */
++ card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT;
++ card->qdio.init_pool.buf_count = QETH_IN_BUF_COUNT_DEFAULT;
++ card->qdio.in_buf_pool.buf_count = card->qdio.init_pool.buf_count;
++ INIT_LIST_HEAD(&card->qdio.in_buf_pool.entry_list);
++ INIT_LIST_HEAD(&card->qdio.init_pool.entry_list);
++}
++
++static void qeth_set_intial_options(struct qeth_card *card)
++{
++ card->options.route4.type = NO_ROUTER;
++ card->options.route6.type = NO_ROUTER;
++ card->options.checksum_type = QETH_CHECKSUM_DEFAULT;
++ card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS;
++ card->options.macaddr_mode = QETH_TR_MACADDR_NONCANONICAL;
++ card->options.fake_broadcast = 0;
++ card->options.add_hhlen = DEFAULT_ADD_HHLEN;
++ card->options.fake_ll = 0;
++ card->options.performance_stats = 0;
++ card->options.rx_sg_cb = QETH_RX_SG_CB;
++}
++
++static int qeth_do_start_thread(struct qeth_card *card, unsigned long thread)
++{
++ unsigned long flags;
++ int rc = 0;
++
++ spin_lock_irqsave(&card->thread_mask_lock, flags);
++ QETH_DBF_TEXT_(TRACE, 4, " %02x%02x%02x",
++ (u8) card->thread_start_mask,
++ (u8) card->thread_allowed_mask,
++ (u8) card->thread_running_mask);
++ rc = (card->thread_start_mask & thread);
++ spin_unlock_irqrestore(&card->thread_mask_lock, flags);
++ return rc;
++}
++
++static void qeth_start_kernel_thread(struct work_struct *work)
++{
++ struct qeth_card *card = container_of(work, struct qeth_card,
++ kernel_thread_starter);
++ QETH_DBF_TEXT(TRACE , 2, "strthrd");
++
++ if (card->read.state != CH_STATE_UP &&
++ card->write.state != CH_STATE_UP)
++ return;
++ if (qeth_do_start_thread(card, QETH_RECOVER_THREAD))
++ kthread_run(card->discipline.recover, (void *) card,
++ "qeth_recover");
++}
++
++static int qeth_setup_card(struct qeth_card *card)
++{
++
++ QETH_DBF_TEXT(SETUP, 2, "setupcrd");
++ QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
++
++ card->read.state = CH_STATE_DOWN;
++ card->write.state = CH_STATE_DOWN;
++ card->data.state = CH_STATE_DOWN;
++ card->state = CARD_STATE_DOWN;
++ card->lan_online = 0;
++ card->use_hard_stop = 0;
++ card->dev = NULL;
++ spin_lock_init(&card->vlanlock);
++ spin_lock_init(&card->mclock);
++ card->vlangrp = NULL;
++ spin_lock_init(&card->lock);
++ spin_lock_init(&card->ip_lock);
++ spin_lock_init(&card->thread_mask_lock);
++ card->thread_start_mask = 0;
++ card->thread_allowed_mask = 0;
++ card->thread_running_mask = 0;
++ INIT_WORK(&card->kernel_thread_starter, qeth_start_kernel_thread);
++ INIT_LIST_HEAD(&card->ip_list);
++ card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_KERNEL);
++ if (!card->ip_tbd_list) {
++ QETH_DBF_TEXT(SETUP, 0, "iptbdnom");
++ return -ENOMEM;
++ }
++ INIT_LIST_HEAD(card->ip_tbd_list);
++ INIT_LIST_HEAD(&card->cmd_waiter_list);
++ init_waitqueue_head(&card->wait_q);
++ /* intial options */
++ qeth_set_intial_options(card);
++ /* IP address takeover */
++ INIT_LIST_HEAD(&card->ipato.entries);
++ card->ipato.enabled = 0;
++ card->ipato.invert4 = 0;
++ card->ipato.invert6 = 0;
++ /* init QDIO stuff */
++ qeth_init_qdio_info(card);
++ return 0;
++}
++
++static struct qeth_card *qeth_alloc_card(void)
++{
++ struct qeth_card *card;
++
++ QETH_DBF_TEXT(SETUP, 2, "alloccrd");
++ card = kzalloc(sizeof(struct qeth_card), GFP_DMA|GFP_KERNEL);
++ if (!card)
++ return NULL;
++ QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
++ if (qeth_setup_channel(&card->read)) {
++ kfree(card);
++ return NULL;
++ }
++ if (qeth_setup_channel(&card->write)) {
++ qeth_clean_channel(&card->read);
++ kfree(card);
++ return NULL;
++ }
++ card->options.layer2 = -1;
++ return card;
++}
++
++static int qeth_determine_card_type(struct qeth_card *card)
++{
++ int i = 0;
++
++ QETH_DBF_TEXT(SETUP, 2, "detcdtyp");
++
++ card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
++ card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
++ while (known_devices[i][4]) {
++ if ((CARD_RDEV(card)->id.dev_type == known_devices[i][2]) &&
++ (CARD_RDEV(card)->id.dev_model == known_devices[i][3])) {
++ card->info.type = known_devices[i][4];
++ card->qdio.no_out_queues = known_devices[i][8];
++ card->info.is_multicast_different = known_devices[i][9];
++ if (qeth_is_1920_device(card)) {
++ PRINT_INFO("Priority Queueing not able "
++ "due to hardware limitations!\n");
++ card->qdio.no_out_queues = 1;
++ card->qdio.default_out_queue = 0;
++ }
++ return 0;
++ }
++ i++;
++ }
++ card->info.type = QETH_CARD_TYPE_UNKNOWN;
++ PRINT_ERR("unknown card type on device %s\n", CARD_BUS_ID(card));
++ return -ENOENT;
++}
++
++static int qeth_clear_channel(struct qeth_channel *channel)
++{
++ unsigned long flags;
++ struct qeth_card *card;
++ int rc;
++
++ QETH_DBF_TEXT(TRACE, 3, "clearch");
++ card = CARD_FROM_CDEV(channel->ccwdev);
++ spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
++ rc = ccw_device_clear(channel->ccwdev, QETH_CLEAR_CHANNEL_PARM);
++ spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
++
++ if (rc)
++ return rc;
++ rc = wait_event_interruptible_timeout(card->wait_q,
++ channel->state == CH_STATE_STOPPED, QETH_TIMEOUT);
++ if (rc == -ERESTARTSYS)
++ return rc;
++ if (channel->state != CH_STATE_STOPPED)
++ return -ETIME;
++ channel->state = CH_STATE_DOWN;
++ return 0;
++}
++
++static int qeth_halt_channel(struct qeth_channel *channel)
++{
++ unsigned long flags;
++ struct qeth_card *card;
++ int rc;
++
++ QETH_DBF_TEXT(TRACE, 3, "haltch");
++ card = CARD_FROM_CDEV(channel->ccwdev);
++ spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
++ rc = ccw_device_halt(channel->ccwdev, QETH_HALT_CHANNEL_PARM);
++ spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
++
++ if (rc)
++ return rc;
++ rc = wait_event_interruptible_timeout(card->wait_q,
++ channel->state == CH_STATE_HALTED, QETH_TIMEOUT);
++ if (rc == -ERESTARTSYS)
++ return rc;
++ if (channel->state != CH_STATE_HALTED)
++ return -ETIME;
++ return 0;
++}
++
++static int qeth_halt_channels(struct qeth_card *card)
++{
++ int rc1 = 0, rc2 = 0, rc3 = 0;
++
++ QETH_DBF_TEXT(TRACE, 3, "haltchs");
++ rc1 = qeth_halt_channel(&card->read);
++ rc2 = qeth_halt_channel(&card->write);
++ rc3 = qeth_halt_channel(&card->data);
++ if (rc1)
++ return rc1;
++ if (rc2)
++ return rc2;
++ return rc3;
++}
++
++static int qeth_clear_channels(struct qeth_card *card)
++{
++ int rc1 = 0, rc2 = 0, rc3 = 0;
++
++ QETH_DBF_TEXT(TRACE, 3, "clearchs");
++ rc1 = qeth_clear_channel(&card->read);
++ rc2 = qeth_clear_channel(&card->write);
++ rc3 = qeth_clear_channel(&card->data);
++ if (rc1)
++ return rc1;
++ if (rc2)
++ return rc2;
++ return rc3;
++}
++
++static int qeth_clear_halt_card(struct qeth_card *card, int halt)
++{
++ int rc = 0;
++
++ QETH_DBF_TEXT(TRACE, 3, "clhacrd");
++ QETH_DBF_HEX(TRACE, 3, &card, sizeof(void *));
++
++ if (halt)
++ rc = qeth_halt_channels(card);
++ if (rc)
++ return rc;
++ return qeth_clear_channels(card);
++}
++
++int qeth_qdio_clear_card(struct qeth_card *card, int use_halt)
++{
++ int rc = 0;
++
++ QETH_DBF_TEXT(TRACE, 3, "qdioclr");
++ switch (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ESTABLISHED,
++ QETH_QDIO_CLEANING)) {
++ case QETH_QDIO_ESTABLISHED:
++ if (card->info.type == QETH_CARD_TYPE_IQD)
++ rc = qdio_cleanup(CARD_DDEV(card),
++ QDIO_FLAG_CLEANUP_USING_HALT);
++ else
++ rc = qdio_cleanup(CARD_DDEV(card),
++ QDIO_FLAG_CLEANUP_USING_CLEAR);
++ if (rc)
++ QETH_DBF_TEXT_(TRACE, 3, "1err%d", rc);
++ atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED);
++ break;
++ case QETH_QDIO_CLEANING:
++ return rc;
++ default:
++ break;
++ }
++ rc = qeth_clear_halt_card(card, use_halt);
++ if (rc)
++ QETH_DBF_TEXT_(TRACE, 3, "2err%d", rc);
++ card->state = CARD_STATE_DOWN;
++ return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_qdio_clear_card);
++
++static int qeth_read_conf_data(struct qeth_card *card, void **buffer,
++ int *length)
++{
++ struct ciw *ciw;
++ char *rcd_buf;
++ int ret;
++ struct qeth_channel *channel = &card->data;
++ unsigned long flags;
++
++ /*
++ * scan for RCD command in extended SenseID data
++ */
++ ciw = ccw_device_get_ciw(channel->ccwdev, CIW_TYPE_RCD);
++ if (!ciw || ciw->cmd == 0)
++ return -EOPNOTSUPP;
++ rcd_buf = kzalloc(ciw->count, GFP_KERNEL | GFP_DMA);
++ if (!rcd_buf)
++ return -ENOMEM;
++
++ channel->ccw.cmd_code = ciw->cmd;
++ channel->ccw.cda = (__u32) __pa(rcd_buf);
++ channel->ccw.count = ciw->count;
++ channel->ccw.flags = CCW_FLAG_SLI;
++ channel->state = CH_STATE_RCD;
++ spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
++ ret = ccw_device_start_timeout(channel->ccwdev, &channel->ccw,
++ QETH_RCD_PARM, LPM_ANYPATH, 0,
++ QETH_RCD_TIMEOUT);
++ spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
++ if (!ret)
++ wait_event(card->wait_q,
++ (channel->state == CH_STATE_RCD_DONE ||
++ channel->state == CH_STATE_DOWN));
++ if (channel->state == CH_STATE_DOWN)
++ ret = -EIO;
++ else
++ channel->state = CH_STATE_DOWN;
++ if (ret) {
++ kfree(rcd_buf);
++ *buffer = NULL;
++ *length = 0;
++ } else {
++ *length = ciw->count;
++ *buffer = rcd_buf;
++ }
++ return ret;
++}
++
++static int qeth_get_unitaddr(struct qeth_card *card)
++{
++ int length;
++ char *prcd;
++ int rc;
++
++ QETH_DBF_TEXT(SETUP, 2, "getunit");
++ rc = qeth_read_conf_data(card, (void **) &prcd, &length);
++ if (rc) {
++ PRINT_ERR("qeth_read_conf_data for device %s returned %i\n",
++ CARD_DDEV_ID(card), rc);
++ return rc;
++ }
++ card->info.chpid = prcd[30];
++ card->info.unit_addr2 = prcd[31];
++ card->info.cula = prcd[63];
++ card->info.guestlan = ((prcd[0x10] == _ascebc['V']) &&
++ (prcd[0x11] == _ascebc['M']));
++ kfree(prcd);
++ return 0;
++}
++
++static void qeth_init_tokens(struct qeth_card *card)
++{
++ card->token.issuer_rm_w = 0x00010103UL;
++ card->token.cm_filter_w = 0x00010108UL;
++ card->token.cm_connection_w = 0x0001010aUL;
++ card->token.ulp_filter_w = 0x0001010bUL;
++ card->token.ulp_connection_w = 0x0001010dUL;
++}
++
++static void qeth_init_func_level(struct qeth_card *card)
++{
++ if (card->ipato.enabled) {
++ if (card->info.type == QETH_CARD_TYPE_IQD)
++ card->info.func_level =
++ QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT;
++ else
++ card->info.func_level =
++ QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT;
++ } else {
++ if (card->info.type == QETH_CARD_TYPE_IQD)
++ /*FIXME:why do we have same values for dis and ena for
++ osae??? */
++ card->info.func_level =
++ QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT;
++ else
++ card->info.func_level =
++ QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT;
++ }
++}
++
++static inline __u16 qeth_raw_devno_from_bus_id(char *id)
++{
++ id += (strlen(id) - 4);
++ return (__u16) simple_strtoul(id, &id, 16);
++}
++
++static int qeth_idx_activate_get_answer(struct qeth_channel *channel,
++ void (*idx_reply_cb)(struct qeth_channel *,
++ struct qeth_cmd_buffer *))
++{
++ struct qeth_cmd_buffer *iob;
++ unsigned long flags;
++ int rc;
++ struct qeth_card *card;
++
++ QETH_DBF_TEXT(SETUP, 2, "idxanswr");
++ card = CARD_FROM_CDEV(channel->ccwdev);
++ iob = qeth_get_buffer(channel);
++ iob->callback = idx_reply_cb;
++ memcpy(&channel->ccw, READ_CCW, sizeof(struct ccw1));
++ channel->ccw.count = QETH_BUFSIZE;
++ channel->ccw.cda = (__u32) __pa(iob->data);
++
++ wait_event(card->wait_q,
++ atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
++ QETH_DBF_TEXT(SETUP, 6, "noirqpnd");
++ spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
++ rc = ccw_device_start(channel->ccwdev,
++ &channel->ccw, (addr_t) iob, 0, 0);
++ spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
++
++ if (rc) {
++ PRINT_ERR("Error2 in activating channel rc=%d\n", rc);
++ QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
++ atomic_set(&channel->irq_pending, 0);
++ wake_up(&card->wait_q);
++ return rc;
++ }
++ rc = wait_event_interruptible_timeout(card->wait_q,
++ channel->state == CH_STATE_UP, QETH_TIMEOUT);
++ if (rc == -ERESTARTSYS)
++ return rc;
++ if (channel->state != CH_STATE_UP) {
++ rc = -ETIME;
++ QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc);
++ qeth_clear_cmd_buffers(channel);
++ } else
++ rc = 0;
++ return rc;
++}
++
++static int qeth_idx_activate_channel(struct qeth_channel *channel,
++ void (*idx_reply_cb)(struct qeth_channel *,
++ struct qeth_cmd_buffer *))
++{
++ struct qeth_card *card;
++ struct qeth_cmd_buffer *iob;
++ unsigned long flags;
++ __u16 temp;
++ __u8 tmp;
++ int rc;
++
++ card = CARD_FROM_CDEV(channel->ccwdev);
++
++ QETH_DBF_TEXT(SETUP, 2, "idxactch");
++
++ iob = qeth_get_buffer(channel);
++ iob->callback = idx_reply_cb;
++ memcpy(&channel->ccw, WRITE_CCW, sizeof(struct ccw1));
++ channel->ccw.count = IDX_ACTIVATE_SIZE;
++ channel->ccw.cda = (__u32) __pa(iob->data);
++ if (channel == &card->write) {
++ memcpy(iob->data, IDX_ACTIVATE_WRITE, IDX_ACTIVATE_SIZE);
++ memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
++ &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
++ card->seqno.trans_hdr++;
++ } else {
++ memcpy(iob->data, IDX_ACTIVATE_READ, IDX_ACTIVATE_SIZE);
++ memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
++ &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
++ }
++ tmp = ((__u8)card->info.portno) | 0x80;
++ memcpy(QETH_IDX_ACT_PNO(iob->data), &tmp, 1);
++ memcpy(QETH_IDX_ACT_ISSUER_RM_TOKEN(iob->data),
++ &card->token.issuer_rm_w, QETH_MPC_TOKEN_LENGTH);
++ memcpy(QETH_IDX_ACT_FUNC_LEVEL(iob->data),
++ &card->info.func_level, sizeof(__u16));
++ temp = qeth_raw_devno_from_bus_id(CARD_DDEV_ID(card));
++ memcpy(QETH_IDX_ACT_QDIO_DEV_CUA(iob->data), &temp, 2);
++ temp = (card->info.cula << 8) + card->info.unit_addr2;
++ memcpy(QETH_IDX_ACT_QDIO_DEV_REALADDR(iob->data), &temp, 2);
++
++ wait_event(card->wait_q,
++ atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
++ QETH_DBF_TEXT(SETUP, 6, "noirqpnd");
++ spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
++ rc = ccw_device_start(channel->ccwdev,
++ &channel->ccw, (addr_t) iob, 0, 0);
++ spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
++
++ if (rc) {
++ PRINT_ERR("Error1 in activating channel. rc=%d\n", rc);
++ QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++ atomic_set(&channel->irq_pending, 0);
++ wake_up(&card->wait_q);
++ return rc;
++ }
++ rc = wait_event_interruptible_timeout(card->wait_q,
++ channel->state == CH_STATE_ACTIVATING, QETH_TIMEOUT);
++ if (rc == -ERESTARTSYS)
++ return rc;
++ if (channel->state != CH_STATE_ACTIVATING) {
++ PRINT_WARN("IDX activate timed out!\n");
++ QETH_DBF_TEXT_(SETUP, 2, "2err%d", -ETIME);
++ qeth_clear_cmd_buffers(channel);
++ return -ETIME;
++ }
++ return qeth_idx_activate_get_answer(channel, idx_reply_cb);
++}
++
++static int qeth_peer_func_level(int level)
++{
++ if ((level & 0xff) == 8)
++ return (level & 0xff) + 0x400;
++ if (((level >> 8) & 3) == 1)
++ return (level & 0xff) + 0x200;
++ return level;
++}
++
++static void qeth_idx_write_cb(struct qeth_channel *channel,
++ struct qeth_cmd_buffer *iob)
++{
++ struct qeth_card *card;
++ __u16 temp;
++
++ QETH_DBF_TEXT(SETUP , 2, "idxwrcb");
++
++ if (channel->state == CH_STATE_DOWN) {
++ channel->state = CH_STATE_ACTIVATING;
++ goto out;
++ }
++ card = CARD_FROM_CDEV(channel->ccwdev);
++
++ if (!(QETH_IS_IDX_ACT_POS_REPLY(iob->data))) {
++ if (QETH_IDX_ACT_CAUSE_CODE(iob->data) == 0x19)
++ PRINT_ERR("IDX_ACTIVATE on write channel device %s: "
++ "adapter exclusively used by another host\n",
++ CARD_WDEV_ID(card));
++ else
++ PRINT_ERR("IDX_ACTIVATE on write channel device %s: "
++ "negative reply\n", CARD_WDEV_ID(card));
++ goto out;
++ }
++ memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2);
++ if ((temp & ~0x0100) != qeth_peer_func_level(card->info.func_level)) {
++ PRINT_WARN("IDX_ACTIVATE on write channel device %s: "
++ "function level mismatch "
++ "(sent: 0x%x, received: 0x%x)\n",
++ CARD_WDEV_ID(card), card->info.func_level, temp);
++ goto out;
++ }
++ channel->state = CH_STATE_UP;
++out:
++ qeth_release_buffer(channel, iob);
++}
++
++static void qeth_idx_read_cb(struct qeth_channel *channel,
++ struct qeth_cmd_buffer *iob)
++{
++ struct qeth_card *card;
++ __u16 temp;
++
++ QETH_DBF_TEXT(SETUP , 2, "idxrdcb");
++ if (channel->state == CH_STATE_DOWN) {
++ channel->state = CH_STATE_ACTIVATING;
++ goto out;
++ }
++
++ card = CARD_FROM_CDEV(channel->ccwdev);
++ if (qeth_check_idx_response(iob->data))
++ goto out;
++
++ if (!(QETH_IS_IDX_ACT_POS_REPLY(iob->data))) {
++ if (QETH_IDX_ACT_CAUSE_CODE(iob->data) == 0x19)
++ PRINT_ERR("IDX_ACTIVATE on read channel device %s: "
++ "adapter exclusively used by another host\n",
++ CARD_RDEV_ID(card));
++ else
++ PRINT_ERR("IDX_ACTIVATE on read channel device %s: "
++ "negative reply\n", CARD_RDEV_ID(card));
++ goto out;
++ }
++
++/**
++ * temporary fix for microcode bug
++ * to revert it,replace OR by AND
++ */
++ if ((!QETH_IDX_NO_PORTNAME_REQUIRED(iob->data)) ||
++ (card->info.type == QETH_CARD_TYPE_OSAE))
++ card->info.portname_required = 1;
++
++ memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2);
++ if (temp != qeth_peer_func_level(card->info.func_level)) {
++ PRINT_WARN("IDX_ACTIVATE on read channel device %s: function "
++ "level mismatch (sent: 0x%x, received: 0x%x)\n",
++ CARD_RDEV_ID(card), card->info.func_level, temp);
++ goto out;
++ }
++ memcpy(&card->token.issuer_rm_r,
++ QETH_IDX_ACT_ISSUER_RM_TOKEN(iob->data),
++ QETH_MPC_TOKEN_LENGTH);
++ memcpy(&card->info.mcl_level[0],
++ QETH_IDX_REPLY_LEVEL(iob->data), QETH_MCL_LENGTH);
++ channel->state = CH_STATE_UP;
++out:
++ qeth_release_buffer(channel, iob);
++}
++
++void qeth_prepare_control_data(struct qeth_card *card, int len,
++ struct qeth_cmd_buffer *iob)
++{
++ qeth_setup_ccw(&card->write, iob->data, len);
++ iob->callback = qeth_release_buffer;
++
++ memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
++ &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
++ card->seqno.trans_hdr++;
++ memcpy(QETH_PDU_HEADER_SEQ_NO(iob->data),
++ &card->seqno.pdu_hdr, QETH_SEQ_NO_LENGTH);
++ card->seqno.pdu_hdr++;
++ memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(iob->data),
++ &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH);
++ QETH_DBF_HEX(CTRL, 2, iob->data, QETH_DBF_CTRL_LEN);
++}
++EXPORT_SYMBOL_GPL(qeth_prepare_control_data);
++
++int qeth_send_control_data(struct qeth_card *card, int len,
++ struct qeth_cmd_buffer *iob,
++ int (*reply_cb)(struct qeth_card *, struct qeth_reply *,
++ unsigned long),
++ void *reply_param)
++{
++ int rc;
++ unsigned long flags;
++ struct qeth_reply *reply = NULL;
++ unsigned long timeout;
++
++ QETH_DBF_TEXT(TRACE, 2, "sendctl");
++
++ reply = qeth_alloc_reply(card);
++ if (!reply) {
++ PRINT_WARN("Could not alloc qeth_reply!\n");
++ return -ENOMEM;
++ }
++ reply->callback = reply_cb;
++ reply->param = reply_param;
++ if (card->state == CARD_STATE_DOWN)
++ reply->seqno = QETH_IDX_COMMAND_SEQNO;
++ else
++ reply->seqno = card->seqno.ipa++;
++ init_waitqueue_head(&reply->wait_q);
++ spin_lock_irqsave(&card->lock, flags);
++ list_add_tail(&reply->list, &card->cmd_waiter_list);
++ spin_unlock_irqrestore(&card->lock, flags);
++ QETH_DBF_HEX(CTRL, 2, iob->data, QETH_DBF_CTRL_LEN);
++
++ while (atomic_cmpxchg(&card->write.irq_pending, 0, 1)) ;
++ qeth_prepare_control_data(card, len, iob);
++
++ if (IS_IPA(iob->data))
++ timeout = jiffies + QETH_IPA_TIMEOUT;
++ else
++ timeout = jiffies + QETH_TIMEOUT;
++
++ QETH_DBF_TEXT(TRACE, 6, "noirqpnd");
++ spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
++ rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
++ (addr_t) iob, 0, 0);
++ spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
++ if (rc) {
++ PRINT_WARN("qeth_send_control_data: "
++ "ccw_device_start rc = %i\n", rc);
++ QETH_DBF_TEXT_(TRACE, 2, " err%d", rc);
++ spin_lock_irqsave(&card->lock, flags);
++ list_del_init(&reply->list);
++ qeth_put_reply(reply);
++ spin_unlock_irqrestore(&card->lock, flags);
++ qeth_release_buffer(iob->channel, iob);
++ atomic_set(&card->write.irq_pending, 0);
++ wake_up(&card->wait_q);
++ return rc;
++ }
++ while (!atomic_read(&reply->received)) {
++ if (time_after(jiffies, timeout)) {
++ spin_lock_irqsave(&reply->card->lock, flags);
++ list_del_init(&reply->list);
++ spin_unlock_irqrestore(&reply->card->lock, flags);
++ reply->rc = -ETIME;
++ atomic_inc(&reply->received);
++ wake_up(&reply->wait_q);
++ }
++ cpu_relax();
++ };
++ rc = reply->rc;
++ qeth_put_reply(reply);
++ return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_send_control_data);
++
++static int qeth_cm_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
++ unsigned long data)
++{
++ struct qeth_cmd_buffer *iob;
++
++ QETH_DBF_TEXT(SETUP, 2, "cmenblcb");
++
++ iob = (struct qeth_cmd_buffer *) data;
++ memcpy(&card->token.cm_filter_r,
++ QETH_CM_ENABLE_RESP_FILTER_TOKEN(iob->data),
++ QETH_MPC_TOKEN_LENGTH);
++ QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc);
++ return 0;
++}
++
++static int qeth_cm_enable(struct qeth_card *card)
++{
++ int rc;
++ struct qeth_cmd_buffer *iob;
++
++ QETH_DBF_TEXT(SETUP, 2, "cmenable");
++
++ iob = qeth_wait_for_buffer(&card->write);
++ memcpy(iob->data, CM_ENABLE, CM_ENABLE_SIZE);
++ memcpy(QETH_CM_ENABLE_ISSUER_RM_TOKEN(iob->data),
++ &card->token.issuer_rm_r, QETH_MPC_TOKEN_LENGTH);
++ memcpy(QETH_CM_ENABLE_FILTER_TOKEN(iob->data),
++ &card->token.cm_filter_w, QETH_MPC_TOKEN_LENGTH);
++
++ rc = qeth_send_control_data(card, CM_ENABLE_SIZE, iob,
++ qeth_cm_enable_cb, NULL);
++ return rc;
++}
++
++static int qeth_cm_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
++ unsigned long data)
++{
++
++ struct qeth_cmd_buffer *iob;
++
++ QETH_DBF_TEXT(SETUP, 2, "cmsetpcb");
++
++ iob = (struct qeth_cmd_buffer *) data;
++ memcpy(&card->token.cm_connection_r,
++ QETH_CM_SETUP_RESP_DEST_ADDR(iob->data),
++ QETH_MPC_TOKEN_LENGTH);
++ QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc);
++ return 0;
++}
++
++static int qeth_cm_setup(struct qeth_card *card)
++{
++ int rc;
++ struct qeth_cmd_buffer *iob;
++
++ QETH_DBF_TEXT(SETUP, 2, "cmsetup");
++
++ iob = qeth_wait_for_buffer(&card->write);
++ memcpy(iob->data, CM_SETUP, CM_SETUP_SIZE);
++ memcpy(QETH_CM_SETUP_DEST_ADDR(iob->data),
++ &card->token.issuer_rm_r, QETH_MPC_TOKEN_LENGTH);
++ memcpy(QETH_CM_SETUP_CONNECTION_TOKEN(iob->data),
++ &card->token.cm_connection_w, QETH_MPC_TOKEN_LENGTH);
++ memcpy(QETH_CM_SETUP_FILTER_TOKEN(iob->data),
++ &card->token.cm_filter_r, QETH_MPC_TOKEN_LENGTH);
++ rc = qeth_send_control_data(card, CM_SETUP_SIZE, iob,
++ qeth_cm_setup_cb, NULL);
++ return rc;
++
++}
++
++static inline int qeth_get_initial_mtu_for_card(struct qeth_card *card)
++{
++ switch (card->info.type) {
++ case QETH_CARD_TYPE_UNKNOWN:
++ return 1500;
++ case QETH_CARD_TYPE_IQD:
++ return card->info.max_mtu;
++ case QETH_CARD_TYPE_OSAE:
++ switch (card->info.link_type) {
++ case QETH_LINK_TYPE_HSTR:
++ case QETH_LINK_TYPE_LANE_TR:
++ return 2000;
++ default:
++ return 1492;
++ }
++ default:
++ return 1500;
++ }
++}
++
++static inline int qeth_get_max_mtu_for_card(int cardtype)
++{
++ switch (cardtype) {
++
++ case QETH_CARD_TYPE_UNKNOWN:
++ case QETH_CARD_TYPE_OSAE:
++ case QETH_CARD_TYPE_OSN:
++ return 61440;
++ case QETH_CARD_TYPE_IQD:
++ return 57344;
++ default:
++ return 1500;
++ }
++}
++
++static inline int qeth_get_mtu_out_of_mpc(int cardtype)
++{
++ switch (cardtype) {
++ case QETH_CARD_TYPE_IQD:
++ return 1;
++ default:
++ return 0;
++ }
++}
++
++static inline int qeth_get_mtu_outof_framesize(int framesize)
++{
++ switch (framesize) {
++ case 0x4000:
++ return 8192;
++ case 0x6000:
++ return 16384;
++ case 0xa000:
++ return 32768;
++ case 0xffff:
++ return 57344;
++ default:
++ return 0;
++ }
++}
++
++static inline int qeth_mtu_is_valid(struct qeth_card *card, int mtu)
++{
++ switch (card->info.type) {
++ case QETH_CARD_TYPE_OSAE:
++ return ((mtu >= 576) && (mtu <= 61440));
++ case QETH_CARD_TYPE_IQD:
++ return ((mtu >= 576) &&
++ (mtu <= card->info.max_mtu + 4096 - 32));
++ case QETH_CARD_TYPE_OSN:
++ case QETH_CARD_TYPE_UNKNOWN:
++ default:
++ return 1;
++ }
++}
++
++static int qeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
++ unsigned long data)
++{
++
++ __u16 mtu, framesize;
++ __u16 len;
++ __u8 link_type;
++ struct qeth_cmd_buffer *iob;
++
++ QETH_DBF_TEXT(SETUP, 2, "ulpenacb");
++
++ iob = (struct qeth_cmd_buffer *) data;
++ memcpy(&card->token.ulp_filter_r,
++ QETH_ULP_ENABLE_RESP_FILTER_TOKEN(iob->data),
++ QETH_MPC_TOKEN_LENGTH);
++ if (qeth_get_mtu_out_of_mpc(card->info.type)) {
++ memcpy(&framesize, QETH_ULP_ENABLE_RESP_MAX_MTU(iob->data), 2);
++ mtu = qeth_get_mtu_outof_framesize(framesize);
++ if (!mtu) {
++ iob->rc = -EINVAL;
++ QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc);
++ return 0;
++ }
++ card->info.max_mtu = mtu;
++ card->info.initial_mtu = mtu;
++ card->qdio.in_buf_size = mtu + 2 * PAGE_SIZE;
++ } else {
++ card->info.initial_mtu = qeth_get_initial_mtu_for_card(card);
++ card->info.max_mtu = qeth_get_max_mtu_for_card(card->info.type);
++ card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT;
++ }
++
++ memcpy(&len, QETH_ULP_ENABLE_RESP_DIFINFO_LEN(iob->data), 2);
++ if (len >= QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE) {
++ memcpy(&link_type,
++ QETH_ULP_ENABLE_RESP_LINK_TYPE(iob->data), 1);
++ card->info.link_type = link_type;
++ } else
++ card->info.link_type = 0;
++ QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc);
++ return 0;
++}
++
++static int qeth_ulp_enable(struct qeth_card *card)
++{
++ int rc;
++ char prot_type;
++ struct qeth_cmd_buffer *iob;
++
++ /*FIXME: trace view callbacks*/
++ QETH_DBF_TEXT(SETUP, 2, "ulpenabl");
++
++ iob = qeth_wait_for_buffer(&card->write);
++ memcpy(iob->data, ULP_ENABLE, ULP_ENABLE_SIZE);
++
++ *(QETH_ULP_ENABLE_LINKNUM(iob->data)) =
++ (__u8) card->info.portno;
++ if (card->options.layer2)
++ if (card->info.type == QETH_CARD_TYPE_OSN)
++ prot_type = QETH_PROT_OSN2;
++ else
++ prot_type = QETH_PROT_LAYER2;
++ else
++ prot_type = QETH_PROT_TCPIP;
++
++ memcpy(QETH_ULP_ENABLE_PROT_TYPE(iob->data), &prot_type, 1);
++ memcpy(QETH_ULP_ENABLE_DEST_ADDR(iob->data),
++ &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
++ memcpy(QETH_ULP_ENABLE_FILTER_TOKEN(iob->data),
++ &card->token.ulp_filter_w, QETH_MPC_TOKEN_LENGTH);
++ memcpy(QETH_ULP_ENABLE_PORTNAME_AND_LL(iob->data),
++ card->info.portname, 9);
++ rc = qeth_send_control_data(card, ULP_ENABLE_SIZE, iob,
++ qeth_ulp_enable_cb, NULL);
++ return rc;
++
++}
++
++static int qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
++ unsigned long data)
++{
++ struct qeth_cmd_buffer *iob;
++
++ QETH_DBF_TEXT(SETUP, 2, "ulpstpcb");
++
++ iob = (struct qeth_cmd_buffer *) data;
++ memcpy(&card->token.ulp_connection_r,
++ QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(iob->data),
++ QETH_MPC_TOKEN_LENGTH);
++ QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc);
++ return 0;
++}
++
++static int qeth_ulp_setup(struct qeth_card *card)
++{
++ int rc;
++ __u16 temp;
++ struct qeth_cmd_buffer *iob;
++ struct ccw_dev_id dev_id;
++
++ QETH_DBF_TEXT(SETUP, 2, "ulpsetup");
++
++ iob = qeth_wait_for_buffer(&card->write);
++ memcpy(iob->data, ULP_SETUP, ULP_SETUP_SIZE);
++
++ memcpy(QETH_ULP_SETUP_DEST_ADDR(iob->data),
++ &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
++ memcpy(QETH_ULP_SETUP_CONNECTION_TOKEN(iob->data),
++ &card->token.ulp_connection_w, QETH_MPC_TOKEN_LENGTH);
++ memcpy(QETH_ULP_SETUP_FILTER_TOKEN(iob->data),
++ &card->token.ulp_filter_r, QETH_MPC_TOKEN_LENGTH);
++
++ ccw_device_get_id(CARD_DDEV(card), &dev_id);
++ memcpy(QETH_ULP_SETUP_CUA(iob->data), &dev_id.devno, 2);
++ temp = (card->info.cula << 8) + card->info.unit_addr2;
++ memcpy(QETH_ULP_SETUP_REAL_DEVADDR(iob->data), &temp, 2);
++ rc = qeth_send_control_data(card, ULP_SETUP_SIZE, iob,
++ qeth_ulp_setup_cb, NULL);
++ return rc;
++}
++
++static int qeth_alloc_qdio_buffers(struct qeth_card *card)
++{
++ int i, j;
++
++ QETH_DBF_TEXT(SETUP, 2, "allcqdbf");
++
++ if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED,
++ QETH_QDIO_ALLOCATED) != QETH_QDIO_UNINITIALIZED)
++ return 0;
++
++ card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q),
++ GFP_KERNEL);
++ if (!card->qdio.in_q)
++ goto out_nomem;
++ QETH_DBF_TEXT(SETUP, 2, "inq");
++ QETH_DBF_HEX(SETUP, 2, &card->qdio.in_q, sizeof(void *));
++ memset(card->qdio.in_q, 0, sizeof(struct qeth_qdio_q));
++ /* give inbound qeth_qdio_buffers their qdio_buffers */
++ for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i)
++ card->qdio.in_q->bufs[i].buffer =
++ &card->qdio.in_q->qdio_bufs[i];
++ /* inbound buffer pool */
++ if (qeth_alloc_buffer_pool(card))
++ goto out_freeinq;
++ /* outbound */
++ card->qdio.out_qs =
++ kmalloc(card->qdio.no_out_queues *
++ sizeof(struct qeth_qdio_out_q *), GFP_KERNEL);
++ if (!card->qdio.out_qs)
++ goto out_freepool;
++ for (i = 0; i < card->qdio.no_out_queues; ++i) {
++ card->qdio.out_qs[i] = kmalloc(sizeof(struct qeth_qdio_out_q),
++ GFP_KERNEL);
++ if (!card->qdio.out_qs[i])
++ goto out_freeoutq;
++ QETH_DBF_TEXT_(SETUP, 2, "outq %i", i);
++ QETH_DBF_HEX(SETUP, 2, &card->qdio.out_qs[i], sizeof(void *));
++ memset(card->qdio.out_qs[i], 0, sizeof(struct qeth_qdio_out_q));
++ card->qdio.out_qs[i]->queue_no = i;
++ /* give outbound qeth_qdio_buffers their qdio_buffers */
++ for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
++ card->qdio.out_qs[i]->bufs[j].buffer =
++ &card->qdio.out_qs[i]->qdio_bufs[j];
++ skb_queue_head_init(&card->qdio.out_qs[i]->bufs[j].
++ skb_list);
++ lockdep_set_class(
++ &card->qdio.out_qs[i]->bufs[j].skb_list.lock,
++ &qdio_out_skb_queue_key);
++ INIT_LIST_HEAD(&card->qdio.out_qs[i]->bufs[j].ctx_list);
++ }
++ }
++ return 0;
++
++out_freeoutq:
++ while (i > 0)
++ kfree(card->qdio.out_qs[--i]);
++ kfree(card->qdio.out_qs);
++ card->qdio.out_qs = NULL;
++out_freepool:
++ qeth_free_buffer_pool(card);
++out_freeinq:
++ kfree(card->qdio.in_q);
++ card->qdio.in_q = NULL;
++out_nomem:
++ atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED);
++ return -ENOMEM;
++}
++
++static void qeth_create_qib_param_field(struct qeth_card *card,
++ char *param_field)
++{
++
++ param_field[0] = _ascebc['P'];
++ param_field[1] = _ascebc['C'];
++ param_field[2] = _ascebc['I'];
++ param_field[3] = _ascebc['T'];
++ *((unsigned int *) (¶m_field[4])) = QETH_PCI_THRESHOLD_A(card);
++ *((unsigned int *) (¶m_field[8])) = QETH_PCI_THRESHOLD_B(card);
++ *((unsigned int *) (¶m_field[12])) = QETH_PCI_TIMER_VALUE(card);
++}
++
++static void qeth_create_qib_param_field_blkt(struct qeth_card *card,
++ char *param_field)
++{
++ param_field[16] = _ascebc['B'];
++ param_field[17] = _ascebc['L'];
++ param_field[18] = _ascebc['K'];
++ param_field[19] = _ascebc['T'];
++ *((unsigned int *) (¶m_field[20])) = card->info.blkt.time_total;
++ *((unsigned int *) (¶m_field[24])) = card->info.blkt.inter_packet;
++ *((unsigned int *) (¶m_field[28])) =
++ card->info.blkt.inter_packet_jumbo;
++}
++
++static int qeth_qdio_activate(struct qeth_card *card)
++{
++ QETH_DBF_TEXT(SETUP, 3, "qdioact");
++ return qdio_activate(CARD_DDEV(card), 0);
++}
++
++static int qeth_dm_act(struct qeth_card *card)
++{
++ int rc;
++ struct qeth_cmd_buffer *iob;
++
++ QETH_DBF_TEXT(SETUP, 2, "dmact");
++
++ iob = qeth_wait_for_buffer(&card->write);
++ memcpy(iob->data, DM_ACT, DM_ACT_SIZE);
++
++ memcpy(QETH_DM_ACT_DEST_ADDR(iob->data),
++ &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
++ memcpy(QETH_DM_ACT_CONNECTION_TOKEN(iob->data),
++ &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
++ rc = qeth_send_control_data(card, DM_ACT_SIZE, iob, NULL, NULL);
++ return rc;
++}
++
++static int qeth_mpc_initialize(struct qeth_card *card)
++{
++ int rc;
++
++ QETH_DBF_TEXT(SETUP, 2, "mpcinit");
++
++ rc = qeth_issue_next_read(card);
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++ return rc;
++ }
++ rc = qeth_cm_enable(card);
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
++ goto out_qdio;
++ }
++ rc = qeth_cm_setup(card);
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc);
++ goto out_qdio;
++ }
++ rc = qeth_ulp_enable(card);
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "4err%d", rc);
++ goto out_qdio;
++ }
++ rc = qeth_ulp_setup(card);
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc);
++ goto out_qdio;
++ }
++ rc = qeth_alloc_qdio_buffers(card);
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc);
++ goto out_qdio;
++ }
++ rc = qeth_qdio_establish(card);
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);
++ qeth_free_qdio_buffers(card);
++ goto out_qdio;
++ }
++ rc = qeth_qdio_activate(card);
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "7err%d", rc);
++ goto out_qdio;
++ }
++ rc = qeth_dm_act(card);
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "8err%d", rc);
++ goto out_qdio;
++ }
++
++ return 0;
++out_qdio:
++ qeth_qdio_clear_card(card, card->info.type != QETH_CARD_TYPE_IQD);
++ return rc;
++}
++
++static void qeth_print_status_with_portname(struct qeth_card *card)
++{
++ char dbf_text[15];
++ int i;
++
++ sprintf(dbf_text, "%s", card->info.portname + 1);
++ for (i = 0; i < 8; i++)
++ dbf_text[i] =
++ (char) _ebcasc[(__u8) dbf_text[i]];
++ dbf_text[8] = 0;
++ PRINT_INFO("Device %s/%s/%s is a%s card%s%s%s\n"
++ "with link type %s (portname: %s)\n",
++ CARD_RDEV_ID(card),
++ CARD_WDEV_ID(card),
++ CARD_DDEV_ID(card),
++ qeth_get_cardname(card),
++ (card->info.mcl_level[0]) ? " (level: " : "",
++ (card->info.mcl_level[0]) ? card->info.mcl_level : "",
++ (card->info.mcl_level[0]) ? ")" : "",
++ qeth_get_cardname_short(card),
++ dbf_text);
++
++}
++
++static void qeth_print_status_no_portname(struct qeth_card *card)
++{
++ if (card->info.portname[0])
++ PRINT_INFO("Device %s/%s/%s is a%s "
++ "card%s%s%s\nwith link type %s "
++ "(no portname needed by interface).\n",
++ CARD_RDEV_ID(card),
++ CARD_WDEV_ID(card),
++ CARD_DDEV_ID(card),
++ qeth_get_cardname(card),
++ (card->info.mcl_level[0]) ? " (level: " : "",
++ (card->info.mcl_level[0]) ? card->info.mcl_level : "",
++ (card->info.mcl_level[0]) ? ")" : "",
++ qeth_get_cardname_short(card));
++ else
++ PRINT_INFO("Device %s/%s/%s is a%s "
++ "card%s%s%s\nwith link type %s.\n",
++ CARD_RDEV_ID(card),
++ CARD_WDEV_ID(card),
++ CARD_DDEV_ID(card),
++ qeth_get_cardname(card),
++ (card->info.mcl_level[0]) ? " (level: " : "",
++ (card->info.mcl_level[0]) ? card->info.mcl_level : "",
++ (card->info.mcl_level[0]) ? ")" : "",
++ qeth_get_cardname_short(card));
++}
++
++void qeth_print_status_message(struct qeth_card *card)
++{
++ switch (card->info.type) {
++ case QETH_CARD_TYPE_OSAE:
++ /* VM will use a non-zero first character
++ * to indicate a HiperSockets like reporting
++ * of the level OSA sets the first character to zero
++ * */
++ if (!card->info.mcl_level[0]) {
++ sprintf(card->info.mcl_level, "%02x%02x",
++ card->info.mcl_level[2],
++ card->info.mcl_level[3]);
++
++ card->info.mcl_level[QETH_MCL_LENGTH] = 0;
++ break;
++ }
++ /* fallthrough */
++ case QETH_CARD_TYPE_IQD:
++ if (card->info.guestlan) {
++ card->info.mcl_level[0] = (char) _ebcasc[(__u8)
++ card->info.mcl_level[0]];
++ card->info.mcl_level[1] = (char) _ebcasc[(__u8)
++ card->info.mcl_level[1]];
++ card->info.mcl_level[2] = (char) _ebcasc[(__u8)
++ card->info.mcl_level[2]];
++ card->info.mcl_level[3] = (char) _ebcasc[(__u8)
++ card->info.mcl_level[3]];
++ card->info.mcl_level[QETH_MCL_LENGTH] = 0;
++ }
++ break;
++ default:
++ memset(&card->info.mcl_level[0], 0, QETH_MCL_LENGTH + 1);
++ }
++ if (card->info.portname_required)
++ qeth_print_status_with_portname(card);
++ else
++ qeth_print_status_no_portname(card);
++}
++EXPORT_SYMBOL_GPL(qeth_print_status_message);
++
++void qeth_put_buffer_pool_entry(struct qeth_card *card,
++ struct qeth_buffer_pool_entry *entry)
++{
++ QETH_DBF_TEXT(TRACE, 6, "ptbfplen");
++ list_add_tail(&entry->list, &card->qdio.in_buf_pool.entry_list);
++}
++EXPORT_SYMBOL_GPL(qeth_put_buffer_pool_entry);
++
++static void qeth_initialize_working_pool_list(struct qeth_card *card)
++{
++ struct qeth_buffer_pool_entry *entry;
++
++ QETH_DBF_TEXT(TRACE, 5, "inwrklst");
++
++ list_for_each_entry(entry,
++ &card->qdio.init_pool.entry_list, init_list) {
++ qeth_put_buffer_pool_entry(card, entry);
++ }
++}
++
++static inline struct qeth_buffer_pool_entry *qeth_find_free_buffer_pool_entry(
++ struct qeth_card *card)
++{
++ struct list_head *plh;
++ struct qeth_buffer_pool_entry *entry;
++ int i, free;
++ struct page *page;
++
++ if (list_empty(&card->qdio.in_buf_pool.entry_list))
++ return NULL;
++
++ list_for_each(plh, &card->qdio.in_buf_pool.entry_list) {
++ entry = list_entry(plh, struct qeth_buffer_pool_entry, list);
++ free = 1;
++ for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
++ if (page_count(virt_to_page(entry->elements[i])) > 1) {
++ free = 0;
++ break;
++ }
++ }
++ if (free) {
++ list_del_init(&entry->list);
++ return entry;
++ }
++ }
++
++ /* no free buffer in pool so take first one and swap pages */
++ entry = list_entry(card->qdio.in_buf_pool.entry_list.next,
++ struct qeth_buffer_pool_entry, list);
++ for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
++ if (page_count(virt_to_page(entry->elements[i])) > 1) {
++ page = alloc_page(GFP_ATOMIC);
++ if (!page) {
++ return NULL;
++ } else {
++ free_page((unsigned long)entry->elements[i]);
++ entry->elements[i] = page_address(page);
++ if (card->options.performance_stats)
++ card->perf_stats.sg_alloc_page_rx++;
++ }
++ }
++ }
++ list_del_init(&entry->list);
++ return entry;
++}
++
++static int qeth_init_input_buffer(struct qeth_card *card,
++ struct qeth_qdio_buffer *buf)
++{
++ struct qeth_buffer_pool_entry *pool_entry;
++ int i;
++
++ pool_entry = qeth_find_free_buffer_pool_entry(card);
++ if (!pool_entry)
++ return 1;
++
++ /*
++ * since the buffer is accessed only from the input_tasklet
++ * there shouldn't be a need to synchronize; also, since we use
++ * the QETH_IN_BUF_REQUEUE_THRESHOLD we should never run out off
++ * buffers
++ */
++ BUG_ON(!pool_entry);
++
++ buf->pool_entry = pool_entry;
++ for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
++ buf->buffer->element[i].length = PAGE_SIZE;
++ buf->buffer->element[i].addr = pool_entry->elements[i];
++ if (i == QETH_MAX_BUFFER_ELEMENTS(card) - 1)
++ buf->buffer->element[i].flags = SBAL_FLAGS_LAST_ENTRY;
++ else
++ buf->buffer->element[i].flags = 0;
++ }
++ return 0;
++}
++
++int qeth_init_qdio_queues(struct qeth_card *card)
++{
++ int i, j;
++ int rc;
++
++ QETH_DBF_TEXT(SETUP, 2, "initqdqs");
++
++ /* inbound queue */
++ memset(card->qdio.in_q->qdio_bufs, 0,
++ QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
++ qeth_initialize_working_pool_list(card);
++ /*give only as many buffers to hardware as we have buffer pool entries*/
++ for (i = 0; i < card->qdio.in_buf_pool.buf_count - 1; ++i)
++ qeth_init_input_buffer(card, &card->qdio.in_q->bufs[i]);
++ card->qdio.in_q->next_buf_to_init =
++ card->qdio.in_buf_pool.buf_count - 1;
++ rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0, 0,
++ card->qdio.in_buf_pool.buf_count - 1, NULL);
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++ return rc;
++ }
++ rc = qdio_synchronize(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0);
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
++ return rc;
++ }
++ /* outbound queue */
++ for (i = 0; i < card->qdio.no_out_queues; ++i) {
++ memset(card->qdio.out_qs[i]->qdio_bufs, 0,
++ QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
++ for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
++ qeth_clear_output_buffer(card->qdio.out_qs[i],
++ &card->qdio.out_qs[i]->bufs[j]);
++ }
++ card->qdio.out_qs[i]->card = card;
++ card->qdio.out_qs[i]->next_buf_to_fill = 0;
++ card->qdio.out_qs[i]->do_pack = 0;
++ atomic_set(&card->qdio.out_qs[i]->used_buffers, 0);
++ atomic_set(&card->qdio.out_qs[i]->set_pci_flags_count, 0);
++ atomic_set(&card->qdio.out_qs[i]->state,
++ QETH_OUT_Q_UNLOCKED);
++ }
++ return 0;
++}
++EXPORT_SYMBOL_GPL(qeth_init_qdio_queues);
++
++static inline __u8 qeth_get_ipa_adp_type(enum qeth_link_types link_type)
++{
++ switch (link_type) {
++ case QETH_LINK_TYPE_HSTR:
++ return 2;
++ default:
++ return 1;
++ }
++}
++
++static void qeth_fill_ipacmd_header(struct qeth_card *card,
++ struct qeth_ipa_cmd *cmd, __u8 command,
++ enum qeth_prot_versions prot)
++{
++ memset(cmd, 0, sizeof(struct qeth_ipa_cmd));
++ cmd->hdr.command = command;
++ cmd->hdr.initiator = IPA_CMD_INITIATOR_HOST;
++ cmd->hdr.seqno = card->seqno.ipa;
++ cmd->hdr.adapter_type = qeth_get_ipa_adp_type(card->info.link_type);
++ cmd->hdr.rel_adapter_no = (__u8) card->info.portno;
++ if (card->options.layer2)
++ cmd->hdr.prim_version_no = 2;
++ else
++ cmd->hdr.prim_version_no = 1;
++ cmd->hdr.param_count = 1;
++ cmd->hdr.prot_version = prot;
++ cmd->hdr.ipa_supported = 0;
++ cmd->hdr.ipa_enabled = 0;
++}
++
++struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *card,
++ enum qeth_ipa_cmds ipacmd, enum qeth_prot_versions prot)
++{
++ struct qeth_cmd_buffer *iob;
++ struct qeth_ipa_cmd *cmd;
++
++ iob = qeth_wait_for_buffer(&card->write);
++ cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++ qeth_fill_ipacmd_header(card, cmd, ipacmd, prot);
++
++ return iob;
++}
++EXPORT_SYMBOL_GPL(qeth_get_ipacmd_buffer);
++
++void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
++ char prot_type)
++{
++ memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
++ memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data), &prot_type, 1);
++ memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
++ &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
++}
++EXPORT_SYMBOL_GPL(qeth_prepare_ipa_cmd);
++
++int qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
++ int (*reply_cb)(struct qeth_card *, struct qeth_reply*,
++ unsigned long),
++ void *reply_param)
++{
++ int rc;
++ char prot_type;
++
++ QETH_DBF_TEXT(TRACE, 4, "sendipa");
++
++ if (card->options.layer2)
++ if (card->info.type == QETH_CARD_TYPE_OSN)
++ prot_type = QETH_PROT_OSN2;
++ else
++ prot_type = QETH_PROT_LAYER2;
++ else
++ prot_type = QETH_PROT_TCPIP;
++ qeth_prepare_ipa_cmd(card, iob, prot_type);
++ rc = qeth_send_control_data(card, IPA_CMD_LENGTH,
++ iob, reply_cb, reply_param);
++ return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_send_ipa_cmd);
++
++static int qeth_send_startstoplan(struct qeth_card *card,
++ enum qeth_ipa_cmds ipacmd, enum qeth_prot_versions prot)
++{
++ int rc;
++ struct qeth_cmd_buffer *iob;
++
++ iob = qeth_get_ipacmd_buffer(card, ipacmd, prot);
++ rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
++
++ return rc;
++}
++
++int qeth_send_startlan(struct qeth_card *card)
++{
++ int rc;
++
++ QETH_DBF_TEXT(SETUP, 2, "strtlan");
++
++ rc = qeth_send_startstoplan(card, IPA_CMD_STARTLAN, 0);
++ return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_send_startlan);
++
++int qeth_send_stoplan(struct qeth_card *card)
++{
++ int rc = 0;
++
++ /*
++ * TODO: according to the IPA format document page 14,
++ * TCP/IP (we!) never issue a STOPLAN
++ * is this right ?!?
++ */
++ QETH_DBF_TEXT(SETUP, 2, "stoplan");
++
++ rc = qeth_send_startstoplan(card, IPA_CMD_STOPLAN, 0);
++ return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_send_stoplan);
++
++int qeth_default_setadapterparms_cb(struct qeth_card *card,
++ struct qeth_reply *reply, unsigned long data)
++{
++ struct qeth_ipa_cmd *cmd;
++
++ QETH_DBF_TEXT(TRACE, 4, "defadpcb");
++
++ cmd = (struct qeth_ipa_cmd *) data;
++ if (cmd->hdr.return_code == 0)
++ cmd->hdr.return_code =
++ cmd->data.setadapterparms.hdr.return_code;
++ return 0;
++}
++EXPORT_SYMBOL_GPL(qeth_default_setadapterparms_cb);
++
++static int qeth_query_setadapterparms_cb(struct qeth_card *card,
++ struct qeth_reply *reply, unsigned long data)
++{
++ struct qeth_ipa_cmd *cmd;
++
++ QETH_DBF_TEXT(TRACE, 3, "quyadpcb");
++
++ cmd = (struct qeth_ipa_cmd *) data;
++ if (cmd->data.setadapterparms.data.query_cmds_supp.lan_type & 0x7f)
++ card->info.link_type =
++ cmd->data.setadapterparms.data.query_cmds_supp.lan_type;
++ card->options.adp.supported_funcs =
++ cmd->data.setadapterparms.data.query_cmds_supp.supported_cmds;
++ return qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
++}
++
++struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *card,
++ __u32 command, __u32 cmdlen)
++{
++ struct qeth_cmd_buffer *iob;
++ struct qeth_ipa_cmd *cmd;
++
++ iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETADAPTERPARMS,
++ QETH_PROT_IPV4);
++ cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++ cmd->data.setadapterparms.hdr.cmdlength = cmdlen;
++ cmd->data.setadapterparms.hdr.command_code = command;
++ cmd->data.setadapterparms.hdr.used_total = 1;
++ cmd->data.setadapterparms.hdr.seq_no = 1;
++
++ return iob;
++}
++EXPORT_SYMBOL_GPL(qeth_get_adapter_cmd);
++
++int qeth_query_setadapterparms(struct qeth_card *card)
++{
++ int rc;
++ struct qeth_cmd_buffer *iob;
++
++ QETH_DBF_TEXT(TRACE, 3, "queryadp");
++ iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_COMMANDS_SUPPORTED,
++ sizeof(struct qeth_ipacmd_setadpparms));
++ rc = qeth_send_ipa_cmd(card, iob, qeth_query_setadapterparms_cb, NULL);
++ return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_query_setadapterparms);
++
++int qeth_check_qdio_errors(struct qdio_buffer *buf, unsigned int qdio_error,
++ unsigned int siga_error, const char *dbftext)
++{
++ if (qdio_error || siga_error) {
++ QETH_DBF_TEXT(TRACE, 2, dbftext);
++ QETH_DBF_TEXT(QERR, 2, dbftext);
++ QETH_DBF_TEXT_(QERR, 2, " F15=%02X",
++ buf->element[15].flags & 0xff);
++ QETH_DBF_TEXT_(QERR, 2, " F14=%02X",
++ buf->element[14].flags & 0xff);
++ QETH_DBF_TEXT_(QERR, 2, " qerr=%X", qdio_error);
++ QETH_DBF_TEXT_(QERR, 2, " serr=%X", siga_error);
++ return 1;
++ }
++ return 0;
++}
++EXPORT_SYMBOL_GPL(qeth_check_qdio_errors);
++
++void qeth_queue_input_buffer(struct qeth_card *card, int index)
++{
++ struct qeth_qdio_q *queue = card->qdio.in_q;
++ int count;
++ int i;
++ int rc;
++ int newcount = 0;
++
++ QETH_DBF_TEXT(TRACE, 6, "queinbuf");
++ count = (index < queue->next_buf_to_init)?
++ card->qdio.in_buf_pool.buf_count -
++ (queue->next_buf_to_init - index) :
++ card->qdio.in_buf_pool.buf_count -
++ (queue->next_buf_to_init + QDIO_MAX_BUFFERS_PER_Q - index);
++ /* only requeue at a certain threshold to avoid SIGAs */
++ if (count >= QETH_IN_BUF_REQUEUE_THRESHOLD(card)) {
++ for (i = queue->next_buf_to_init;
++ i < queue->next_buf_to_init + count; ++i) {
++ if (qeth_init_input_buffer(card,
++ &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q])) {
++ break;
++ } else {
++ newcount++;
++ }
++ }
++
++ if (newcount < count) {
++ /* we are in memory shortage so we switch back to
++ traditional skb allocation and drop packages */
++ if (!atomic_read(&card->force_alloc_skb) &&
++ net_ratelimit())
++ PRINT_WARN("Switch to alloc skb\n");
++ atomic_set(&card->force_alloc_skb, 3);
++ count = newcount;
++ } else {
++ if ((atomic_read(&card->force_alloc_skb) == 1) &&
++ net_ratelimit())
++ PRINT_WARN("Switch to sg\n");
++ atomic_add_unless(&card->force_alloc_skb, -1, 0);
++ }
++
++ /*
++ * according to old code it should be avoided to requeue all
++ * 128 buffers in order to benefit from PCI avoidance.
++ * this function keeps at least one buffer (the buffer at
++ * 'index') un-requeued -> this buffer is the first buffer that
++ * will be requeued the next time
++ */
++ if (card->options.performance_stats) {
++ card->perf_stats.inbound_do_qdio_cnt++;
++ card->perf_stats.inbound_do_qdio_start_time =
++ qeth_get_micros();
++ }
++ rc = do_QDIO(CARD_DDEV(card),
++ QDIO_FLAG_SYNC_INPUT | QDIO_FLAG_UNDER_INTERRUPT,
++ 0, queue->next_buf_to_init, count, NULL);
++ if (card->options.performance_stats)
++ card->perf_stats.inbound_do_qdio_time +=
++ qeth_get_micros() -
++ card->perf_stats.inbound_do_qdio_start_time;
++ if (rc) {
++ PRINT_WARN("qeth_queue_input_buffer's do_QDIO "
++ "return %i (device %s).\n",
++ rc, CARD_DDEV_ID(card));
++ QETH_DBF_TEXT(TRACE, 2, "qinberr");
++ QETH_DBF_TEXT_(TRACE, 2, "%s", CARD_BUS_ID(card));
++ }
++ queue->next_buf_to_init = (queue->next_buf_to_init + count) %
++ QDIO_MAX_BUFFERS_PER_Q;
++ }
++}
++EXPORT_SYMBOL_GPL(qeth_queue_input_buffer);
++
++static int qeth_handle_send_error(struct qeth_card *card,
++ struct qeth_qdio_out_buffer *buffer, unsigned int qdio_err,
++ unsigned int siga_err)
++{
++ int sbalf15 = buffer->buffer->element[15].flags & 0xff;
++ int cc = siga_err & 3;
++
++ QETH_DBF_TEXT(TRACE, 6, "hdsnderr");
++ qeth_check_qdio_errors(buffer->buffer, qdio_err, siga_err, "qouterr");
++ switch (cc) {
++ case 0:
++ if (qdio_err) {
++ QETH_DBF_TEXT(TRACE, 1, "lnkfail");
++ QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
++ QETH_DBF_TEXT_(TRACE, 1, "%04x %02x",
++ (u16)qdio_err, (u8)sbalf15);
++ return QETH_SEND_ERROR_LINK_FAILURE;
++ }
++ return QETH_SEND_ERROR_NONE;
++ case 2:
++ if (siga_err & QDIO_SIGA_ERROR_B_BIT_SET) {
++ QETH_DBF_TEXT(TRACE, 1, "SIGAcc2B");
++ QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
++ return QETH_SEND_ERROR_KICK_IT;
++ }
++ if ((sbalf15 >= 15) && (sbalf15 <= 31))
++ return QETH_SEND_ERROR_RETRY;
++ return QETH_SEND_ERROR_LINK_FAILURE;
++ /* look at qdio_error and sbalf 15 */
++ case 1:
++ QETH_DBF_TEXT(TRACE, 1, "SIGAcc1");
++ QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
++ return QETH_SEND_ERROR_LINK_FAILURE;
++ case 3:
++ default:
++ QETH_DBF_TEXT(TRACE, 1, "SIGAcc3");
++ QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
++ return QETH_SEND_ERROR_KICK_IT;
++ }
++}
++
++/*
++ * Switched to packing state if the number of used buffers on a queue
++ * reaches a certain limit.
++ */
++static void qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue)
++{
++ if (!queue->do_pack) {
++ if (atomic_read(&queue->used_buffers)
++ >= QETH_HIGH_WATERMARK_PACK){
++ /* switch non-PACKING -> PACKING */
++ QETH_DBF_TEXT(TRACE, 6, "np->pack");
++ if (queue->card->options.performance_stats)
++ queue->card->perf_stats.sc_dp_p++;
++ queue->do_pack = 1;
++ }
++ }
++}
++
++/*
++ * Switches from packing to non-packing mode. If there is a packing
++ * buffer on the queue this buffer will be prepared to be flushed.
++ * In that case 1 is returned to inform the caller. If no buffer
++ * has to be flushed, zero is returned.
++ */
++static int qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue)
++{
++ struct qeth_qdio_out_buffer *buffer;
++ int flush_count = 0;
++
++ if (queue->do_pack) {
++ if (atomic_read(&queue->used_buffers)
++ <= QETH_LOW_WATERMARK_PACK) {
++ /* switch PACKING -> non-PACKING */
++ QETH_DBF_TEXT(TRACE, 6, "pack->np");
++ if (queue->card->options.performance_stats)
++ queue->card->perf_stats.sc_p_dp++;
++ queue->do_pack = 0;
++ /* flush packing buffers */
++ buffer = &queue->bufs[queue->next_buf_to_fill];
++ if ((atomic_read(&buffer->state) ==
++ QETH_QDIO_BUF_EMPTY) &&
++ (buffer->next_element_to_fill > 0)) {
++ atomic_set(&buffer->state,
++ QETH_QDIO_BUF_PRIMED);
++ flush_count++;
++ queue->next_buf_to_fill =
++ (queue->next_buf_to_fill + 1) %
++ QDIO_MAX_BUFFERS_PER_Q;
++ }
++ }
++ }
++ return flush_count;
++}
++
++/*
++ * Called to flush a packing buffer if no more pci flags are on the queue.
++ * Checks if there is a packing buffer and prepares it to be flushed.
++ * In that case returns 1, otherwise zero.
++ */
++static int qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue)
++{
++ struct qeth_qdio_out_buffer *buffer;
++
++ buffer = &queue->bufs[queue->next_buf_to_fill];
++ if ((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) &&
++ (buffer->next_element_to_fill > 0)) {
++ /* it's a packing buffer */
++ atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
++ queue->next_buf_to_fill =
++ (queue->next_buf_to_fill + 1) % QDIO_MAX_BUFFERS_PER_Q;
++ return 1;
++ }
++ return 0;
++}
++
++static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
++ int index, int count)
++{
++ struct qeth_qdio_out_buffer *buf;
++ int rc;
++ int i;
++ unsigned int qdio_flags;
++
++ QETH_DBF_TEXT(TRACE, 6, "flushbuf");
++
++ for (i = index; i < index + count; ++i) {
++ buf = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
++ buf->buffer->element[buf->next_element_to_fill - 1].flags |=
++ SBAL_FLAGS_LAST_ENTRY;
++
++ if (queue->card->info.type == QETH_CARD_TYPE_IQD)
++ continue;
++
++ if (!queue->do_pack) {
++ if ((atomic_read(&queue->used_buffers) >=
++ (QETH_HIGH_WATERMARK_PACK -
++ QETH_WATERMARK_PACK_FUZZ)) &&
++ !atomic_read(&queue->set_pci_flags_count)) {
++ /* it's likely that we'll go to packing
++ * mode soon */
++ atomic_inc(&queue->set_pci_flags_count);
++ buf->buffer->element[0].flags |= 0x40;
++ }
++ } else {
++ if (!atomic_read(&queue->set_pci_flags_count)) {
++ /*
++ * there's no outstanding PCI any more, so we
++ * have to request a PCI to be sure the the PCI
++ * will wake at some time in the future then we
++ * can flush packed buffers that might still be
++ * hanging around, which can happen if no
++ * further send was requested by the stack
++ */
++ atomic_inc(&queue->set_pci_flags_count);
++ buf->buffer->element[0].flags |= 0x40;
++ }
++ }
++ }
++
++ queue->card->dev->trans_start = jiffies;
++ if (queue->card->options.performance_stats) {
++ queue->card->perf_stats.outbound_do_qdio_cnt++;
++ queue->card->perf_stats.outbound_do_qdio_start_time =
++ qeth_get_micros();
++ }
++ qdio_flags = QDIO_FLAG_SYNC_OUTPUT;
++ if (under_int)
++ qdio_flags |= QDIO_FLAG_UNDER_INTERRUPT;
++ if (atomic_read(&queue->set_pci_flags_count))
++ qdio_flags |= QDIO_FLAG_PCI_OUT;
++ rc = do_QDIO(CARD_DDEV(queue->card), qdio_flags,
++ queue->queue_no, index, count, NULL);
++ if (queue->card->options.performance_stats)
++ queue->card->perf_stats.outbound_do_qdio_time +=
++ qeth_get_micros() -
++ queue->card->perf_stats.outbound_do_qdio_start_time;
++ if (rc) {
++ QETH_DBF_TEXT(TRACE, 2, "flushbuf");
++ QETH_DBF_TEXT_(TRACE, 2, " err%d", rc);
++ QETH_DBF_TEXT_(TRACE, 2, "%s", CARD_DDEV_ID(queue->card));
++ queue->card->stats.tx_errors += count;
++ /* this must not happen under normal circumstances. if it
++ * happens something is really wrong -> recover */
++ qeth_schedule_recovery(queue->card);
++ return;
++ }
++ atomic_add(count, &queue->used_buffers);
++ if (queue->card->options.performance_stats)
++ queue->card->perf_stats.bufs_sent += count;
++}
++
++static void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
++{
++ int index;
++ int flush_cnt = 0;
++ int q_was_packing = 0;
++
++ /*
++ * check if weed have to switch to non-packing mode or if
++ * we have to get a pci flag out on the queue
++ */
++ if ((atomic_read(&queue->used_buffers) <= QETH_LOW_WATERMARK_PACK) ||
++ !atomic_read(&queue->set_pci_flags_count)) {
++ if (atomic_xchg(&queue->state, QETH_OUT_Q_LOCKED_FLUSH) ==
++ QETH_OUT_Q_UNLOCKED) {
++ /*
++ * If we get in here, there was no action in
++ * do_send_packet. So, we check if there is a
++ * packing buffer to be flushed here.
++ */
++ netif_stop_queue(queue->card->dev);
++ index = queue->next_buf_to_fill;
++ q_was_packing = queue->do_pack;
++ /* queue->do_pack may change */
++ barrier();
++ flush_cnt += qeth_switch_to_nonpacking_if_needed(queue);
++ if (!flush_cnt &&
++ !atomic_read(&queue->set_pci_flags_count))
++ flush_cnt +=
++ qeth_flush_buffers_on_no_pci(queue);
++ if (queue->card->options.performance_stats &&
++ q_was_packing)
++ queue->card->perf_stats.bufs_sent_pack +=
++ flush_cnt;
++ if (flush_cnt)
++ qeth_flush_buffers(queue, 1, index, flush_cnt);
++ atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
++ }
++ }
++}
++
++void qeth_qdio_output_handler(struct ccw_device *ccwdev, unsigned int status,
++ unsigned int qdio_error, unsigned int siga_error,
++ unsigned int __queue, int first_element, int count,
++ unsigned long card_ptr)
++{
++ struct qeth_card *card = (struct qeth_card *) card_ptr;
++ struct qeth_qdio_out_q *queue = card->qdio.out_qs[__queue];
++ struct qeth_qdio_out_buffer *buffer;
++ int i;
++
++ QETH_DBF_TEXT(TRACE, 6, "qdouhdl");
++ if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
++ if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION) {
++ QETH_DBF_TEXT(TRACE, 2, "achkcond");
++ QETH_DBF_TEXT_(TRACE, 2, "%s", CARD_BUS_ID(card));
++ QETH_DBF_TEXT_(TRACE, 2, "%08x", status);
++ netif_stop_queue(card->dev);
++ qeth_schedule_recovery(card);
++ return;
++ }
++ }
++ if (card->options.performance_stats) {
++ card->perf_stats.outbound_handler_cnt++;
++ card->perf_stats.outbound_handler_start_time =
++ qeth_get_micros();
++ }
++ for (i = first_element; i < (first_element + count); ++i) {
++ buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
++ /*we only handle the KICK_IT error by doing a recovery */
++ if (qeth_handle_send_error(card, buffer,
++ qdio_error, siga_error)
++ == QETH_SEND_ERROR_KICK_IT){
++ netif_stop_queue(card->dev);
++ qeth_schedule_recovery(card);
++ return;
++ }
++ qeth_clear_output_buffer(queue, buffer);
++ }
++ atomic_sub(count, &queue->used_buffers);
++ /* check if we need to do something on this outbound queue */
++ if (card->info.type != QETH_CARD_TYPE_IQD)
++ qeth_check_outbound_queue(queue);
++
++ netif_wake_queue(queue->card->dev);
++ if (card->options.performance_stats)
++ card->perf_stats.outbound_handler_time += qeth_get_micros() -
++ card->perf_stats.outbound_handler_start_time;
++}
++EXPORT_SYMBOL_GPL(qeth_qdio_output_handler);
++
++int qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
++{
++ int cast_type = RTN_UNSPEC;
++
++ if (card->info.type == QETH_CARD_TYPE_OSN)
++ return cast_type;
++
++ if (skb->dst && skb->dst->neighbour) {
++ cast_type = skb->dst->neighbour->type;
++ if ((cast_type == RTN_BROADCAST) ||
++ (cast_type == RTN_MULTICAST) ||
++ (cast_type == RTN_ANYCAST))
++ return cast_type;
++ else
++ return RTN_UNSPEC;
++ }
++ /* try something else */
++ if (skb->protocol == ETH_P_IPV6)
++ return (skb_network_header(skb)[24] == 0xff) ?
++ RTN_MULTICAST : 0;
++ else if (skb->protocol == ETH_P_IP)
++ return ((skb_network_header(skb)[16] & 0xf0) == 0xe0) ?
++ RTN_MULTICAST : 0;
++ /* ... */
++ if (!memcmp(skb->data, skb->dev->broadcast, 6))
++ return RTN_BROADCAST;
++ else {
++ u16 hdr_mac;
++
++ hdr_mac = *((u16 *)skb->data);
++ /* tr multicast? */
++ switch (card->info.link_type) {
++ case QETH_LINK_TYPE_HSTR:
++ case QETH_LINK_TYPE_LANE_TR:
++ if ((hdr_mac == QETH_TR_MAC_NC) ||
++ (hdr_mac == QETH_TR_MAC_C))
++ return RTN_MULTICAST;
++ break;
++ /* eth or so multicast? */
++ default:
++ if ((hdr_mac == QETH_ETH_MAC_V4) ||
++ (hdr_mac == QETH_ETH_MAC_V6))
++ return RTN_MULTICAST;
++ }
++ }
++ return cast_type;
++}
++EXPORT_SYMBOL_GPL(qeth_get_cast_type);
++
++int qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb,
++ int ipv, int cast_type)
++{
++ if (!ipv && (card->info.type == QETH_CARD_TYPE_OSAE))
++ return card->qdio.default_out_queue;
++ switch (card->qdio.no_out_queues) {
++ case 4:
++ if (cast_type && card->info.is_multicast_different)
++ return card->info.is_multicast_different &
++ (card->qdio.no_out_queues - 1);
++ if (card->qdio.do_prio_queueing && (ipv == 4)) {
++ const u8 tos = ip_hdr(skb)->tos;
++
++ if (card->qdio.do_prio_queueing ==
++ QETH_PRIO_Q_ING_TOS) {
++ if (tos & IP_TOS_NOTIMPORTANT)
++ return 3;
++ if (tos & IP_TOS_HIGHRELIABILITY)
++ return 2;
++ if (tos & IP_TOS_HIGHTHROUGHPUT)
++ return 1;
++ if (tos & IP_TOS_LOWDELAY)
++ return 0;
++ }
++ if (card->qdio.do_prio_queueing ==
++ QETH_PRIO_Q_ING_PREC)
++ return 3 - (tos >> 6);
++ } else if (card->qdio.do_prio_queueing && (ipv == 6)) {
++ /* TODO: IPv6!!! */
++ }
++ return card->qdio.default_out_queue;
++ case 1: /* fallthrough for single-out-queue 1920-device */
++ default:
++ return card->qdio.default_out_queue;
++ }
++}
++EXPORT_SYMBOL_GPL(qeth_get_priority_queue);
++
++static void __qeth_free_new_skb(struct sk_buff *orig_skb,
++ struct sk_buff *new_skb)
++{
++ if (orig_skb != new_skb)
++ dev_kfree_skb_any(new_skb);
++}
++
++static inline struct sk_buff *qeth_realloc_headroom(struct qeth_card *card,
++ struct sk_buff *skb, int size)
++{
++ struct sk_buff *new_skb = skb;
++
++ if (skb_headroom(skb) >= size)
++ return skb;
++ new_skb = skb_realloc_headroom(skb, size);
++ if (!new_skb)
++ PRINT_ERR("Could not realloc headroom for qeth_hdr "
++ "on interface %s", QETH_CARD_IFNAME(card));
++ return new_skb;
++}
++
++struct sk_buff *qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb,
++ struct qeth_hdr **hdr)
++{
++ struct sk_buff *new_skb;
++
++ QETH_DBF_TEXT(TRACE, 6, "prepskb");
++
++ new_skb = qeth_realloc_headroom(card, skb,
++ sizeof(struct qeth_hdr));
++ if (!new_skb)
++ return NULL;
++
++ *hdr = ((struct qeth_hdr *)qeth_push_skb(card, new_skb,
++ sizeof(struct qeth_hdr)));
++ if (*hdr == NULL) {
++ __qeth_free_new_skb(skb, new_skb);
++ return NULL;
++ }
++ return new_skb;
++}
++EXPORT_SYMBOL_GPL(qeth_prepare_skb);
++
++int qeth_get_elements_no(struct qeth_card *card, void *hdr,
++ struct sk_buff *skb, int elems)
++{
++ int elements_needed = 0;
++
++ if (skb_shinfo(skb)->nr_frags > 0)
++ elements_needed = (skb_shinfo(skb)->nr_frags + 1);
++ if (elements_needed == 0)
++ elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE)
++ + skb->len) >> PAGE_SHIFT);
++ if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)) {
++ PRINT_ERR("Invalid size of IP packet "
++ "(Number=%d / Length=%d). Discarded.\n",
++ (elements_needed+elems), skb->len);
++ return 0;
++ }
++ return elements_needed;
++}
++EXPORT_SYMBOL_GPL(qeth_get_elements_no);
++
++static void __qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer,
++ int is_tso, int *next_element_to_fill)
++{
++ int length = skb->len;
++ int length_here;
++ int element;
++ char *data;
++ int first_lap ;
++
++ element = *next_element_to_fill;
++ data = skb->data;
++ first_lap = (is_tso == 0 ? 1 : 0);
++
++ while (length > 0) {
++ /* length_here is the remaining amount of data in this page */
++ length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE);
++ if (length < length_here)
++ length_here = length;
++
++ buffer->element[element].addr = data;
++ buffer->element[element].length = length_here;
++ length -= length_here;
++ if (!length) {
++ if (first_lap)
++ buffer->element[element].flags = 0;
++ else
++ buffer->element[element].flags =
++ SBAL_FLAGS_LAST_FRAG;
++ } else {
++ if (first_lap)
++ buffer->element[element].flags =
++ SBAL_FLAGS_FIRST_FRAG;
++ else
++ buffer->element[element].flags =
++ SBAL_FLAGS_MIDDLE_FRAG;
++ }
++ data += length_here;
++ element++;
++ first_lap = 0;
++ }
++ *next_element_to_fill = element;
++}
++
++static int qeth_fill_buffer(struct qeth_qdio_out_q *queue,
++ struct qeth_qdio_out_buffer *buf, struct sk_buff *skb)
++{
++ struct qdio_buffer *buffer;
++ struct qeth_hdr_tso *hdr;
++ int flush_cnt = 0, hdr_len, large_send = 0;
++
++ QETH_DBF_TEXT(TRACE, 6, "qdfillbf");
++
++ buffer = buf->buffer;
++ atomic_inc(&skb->users);
++ skb_queue_tail(&buf->skb_list, skb);
++
++ hdr = (struct qeth_hdr_tso *) skb->data;
++ /*check first on TSO ....*/
++ if (hdr->hdr.hdr.l3.id == QETH_HEADER_TYPE_TSO) {
++ int element = buf->next_element_to_fill;
++
++ hdr_len = sizeof(struct qeth_hdr_tso) + hdr->ext.dg_hdr_len;
++ /*fill first buffer entry only with header information */
++ buffer->element[element].addr = skb->data;
++ buffer->element[element].length = hdr_len;
++ buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG;
++ buf->next_element_to_fill++;
++ skb->data += hdr_len;
++ skb->len -= hdr_len;
++ large_send = 1;
++ }
++ if (skb_shinfo(skb)->nr_frags == 0)
++ __qeth_fill_buffer(skb, buffer, large_send,
++ (int *)&buf->next_element_to_fill);
++ else
++ __qeth_fill_buffer_frag(skb, buffer, large_send,
++ (int *)&buf->next_element_to_fill);
++
++ if (!queue->do_pack) {
++ QETH_DBF_TEXT(TRACE, 6, "fillbfnp");
++ /* set state to PRIMED -> will be flushed */
++ atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
++ flush_cnt = 1;
++ } else {
++ QETH_DBF_TEXT(TRACE, 6, "fillbfpa");
++ if (queue->card->options.performance_stats)
++ queue->card->perf_stats.skbs_sent_pack++;
++ if (buf->next_element_to_fill >=
++ QETH_MAX_BUFFER_ELEMENTS(queue->card)) {
++ /*
++ * packed buffer if full -> set state PRIMED
++ * -> will be flushed
++ */
++ atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
++ flush_cnt = 1;
++ }
++ }
++ return flush_cnt;
++}
++
++int qeth_do_send_packet_fast(struct qeth_card *card,
++ struct qeth_qdio_out_q *queue, struct sk_buff *skb,
++ struct qeth_hdr *hdr, int elements_needed,
++ struct qeth_eddp_context *ctx)
++{
++ struct qeth_qdio_out_buffer *buffer;
++ int buffers_needed = 0;
++ int flush_cnt = 0;
++ int index;
++
++ QETH_DBF_TEXT(TRACE, 6, "dosndpfa");
++
++ /* spin until we get the queue ... */
++ while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
++ QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
++ /* ... now we've got the queue */
++ index = queue->next_buf_to_fill;
++ buffer = &queue->bufs[queue->next_buf_to_fill];
++ /*
++ * check if buffer is empty to make sure that we do not 'overtake'
++ * ourselves and try to fill a buffer that is already primed
++ */
++ if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY)
++ goto out;
++ if (ctx == NULL)
++ queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) %
++ QDIO_MAX_BUFFERS_PER_Q;
++ else {
++ buffers_needed = qeth_eddp_check_buffers_for_context(queue,
++ ctx);
++ if (buffers_needed < 0)
++ goto out;
++ queue->next_buf_to_fill =
++ (queue->next_buf_to_fill + buffers_needed) %
++ QDIO_MAX_BUFFERS_PER_Q;
++ }
++ atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
++ if (ctx == NULL) {
++ qeth_fill_buffer(queue, buffer, skb);
++ qeth_flush_buffers(queue, 0, index, 1);
++ } else {
++ flush_cnt = qeth_eddp_fill_buffer(queue, ctx, index);
++ WARN_ON(buffers_needed != flush_cnt);
++ qeth_flush_buffers(queue, 0, index, flush_cnt);
++ }
++ return 0;
++out:
++ atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
++ return -EBUSY;
++}
++EXPORT_SYMBOL_GPL(qeth_do_send_packet_fast);
++
++int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
++ struct sk_buff *skb, struct qeth_hdr *hdr,
++ int elements_needed, struct qeth_eddp_context *ctx)
++{
++ struct qeth_qdio_out_buffer *buffer;
++ int start_index;
++ int flush_count = 0;
++ int do_pack = 0;
++ int tmp;
++ int rc = 0;
++
++ QETH_DBF_TEXT(TRACE, 6, "dosndpkt");
++
++ /* spin until we get the queue ... */
++ while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
++ QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
++ start_index = queue->next_buf_to_fill;
++ buffer = &queue->bufs[queue->next_buf_to_fill];
++ /*
++ * check if buffer is empty to make sure that we do not 'overtake'
++ * ourselves and try to fill a buffer that is already primed
++ */
++ if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) {
++ atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
++ return -EBUSY;
++ }
++ /* check if we need to switch packing state of this queue */
++ qeth_switch_to_packing_if_needed(queue);
++ if (queue->do_pack) {
++ do_pack = 1;
++ if (ctx == NULL) {
++ /* does packet fit in current buffer? */
++ if ((QETH_MAX_BUFFER_ELEMENTS(card) -
++ buffer->next_element_to_fill) < elements_needed) {
++ /* ... no -> set state PRIMED */
++ atomic_set(&buffer->state,
++ QETH_QDIO_BUF_PRIMED);
++ flush_count++;
++ queue->next_buf_to_fill =
++ (queue->next_buf_to_fill + 1) %
++ QDIO_MAX_BUFFERS_PER_Q;
++ buffer = &queue->bufs[queue->next_buf_to_fill];
++ /* we did a step forward, so check buffer state
++ * again */
++ if (atomic_read(&buffer->state) !=
++ QETH_QDIO_BUF_EMPTY){
++ qeth_flush_buffers(queue, 0,
++ start_index, flush_count);
++ atomic_set(&queue->state,
++ QETH_OUT_Q_UNLOCKED);
++ return -EBUSY;
++ }
++ }
++ } else {
++ /* check if we have enough elements (including following
++ * free buffers) to handle eddp context */
++ if (qeth_eddp_check_buffers_for_context(queue, ctx)
++ < 0) {
++ if (net_ratelimit())
++ PRINT_WARN("eddp tx_dropped 1\n");
++ rc = -EBUSY;
++ goto out;
++ }
++ }
++ }
++ if (ctx == NULL)
++ tmp = qeth_fill_buffer(queue, buffer, skb);
++ else {
++ tmp = qeth_eddp_fill_buffer(queue, ctx,
++ queue->next_buf_to_fill);
++ if (tmp < 0) {
++ PRINT_ERR("eddp tx_dropped 2\n");
++ rc = -EBUSY;
++ goto out;
++ }
++ }
++ queue->next_buf_to_fill = (queue->next_buf_to_fill + tmp) %
++ QDIO_MAX_BUFFERS_PER_Q;
++ flush_count += tmp;
++out:
++ if (flush_count)
++ qeth_flush_buffers(queue, 0, start_index, flush_count);
++ else if (!atomic_read(&queue->set_pci_flags_count))
++ atomic_xchg(&queue->state, QETH_OUT_Q_LOCKED_FLUSH);
++ /*
++ * queue->state will go from LOCKED -> UNLOCKED or from
++ * LOCKED_FLUSH -> LOCKED if output_handler wanted to 'notify' us
++ * (switch packing state or flush buffer to get another pci flag out).
++ * In that case we will enter this loop
++ */
++ while (atomic_dec_return(&queue->state)) {
++ flush_count = 0;
++ start_index = queue->next_buf_to_fill;
++ /* check if we can go back to non-packing state */
++ flush_count += qeth_switch_to_nonpacking_if_needed(queue);
++ /*
++ * check if we need to flush a packing buffer to get a pci
++ * flag out on the queue
++ */
++ if (!flush_count && !atomic_read(&queue->set_pci_flags_count))
++ flush_count += qeth_flush_buffers_on_no_pci(queue);
++ if (flush_count)
++ qeth_flush_buffers(queue, 0, start_index, flush_count);
++ }
++ /* at this point the queue is UNLOCKED again */
++ if (queue->card->options.performance_stats && do_pack)
++ queue->card->perf_stats.bufs_sent_pack += flush_count;
++
++ return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_do_send_packet);
++
++static int qeth_setadp_promisc_mode_cb(struct qeth_card *card,
++ struct qeth_reply *reply, unsigned long data)
++{
++ struct qeth_ipa_cmd *cmd;
++ struct qeth_ipacmd_setadpparms *setparms;
++
++ QETH_DBF_TEXT(TRACE, 4, "prmadpcb");
++
++ cmd = (struct qeth_ipa_cmd *) data;
++ setparms = &(cmd->data.setadapterparms);
++
++ qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
++ if (cmd->hdr.return_code) {
++ QETH_DBF_TEXT_(TRACE, 4, "prmrc%2.2x", cmd->hdr.return_code);
++ setparms->data.mode = SET_PROMISC_MODE_OFF;
++ }
++ card->info.promisc_mode = setparms->data.mode;
++ return 0;
++}
++
++void qeth_setadp_promisc_mode(struct qeth_card *card)
++{
++ enum qeth_ipa_promisc_modes mode;
++ struct net_device *dev = card->dev;
++ struct qeth_cmd_buffer *iob;
++ struct qeth_ipa_cmd *cmd;
++
++ QETH_DBF_TEXT(TRACE, 4, "setprom");
++
++ if (((dev->flags & IFF_PROMISC) &&
++ (card->info.promisc_mode == SET_PROMISC_MODE_ON)) ||
++ (!(dev->flags & IFF_PROMISC) &&
++ (card->info.promisc_mode == SET_PROMISC_MODE_OFF)))
++ return;
++ mode = SET_PROMISC_MODE_OFF;
++ if (dev->flags & IFF_PROMISC)
++ mode = SET_PROMISC_MODE_ON;
++ QETH_DBF_TEXT_(TRACE, 4, "mode:%x", mode);
++
++ iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_PROMISC_MODE,
++ sizeof(struct qeth_ipacmd_setadpparms));
++ cmd = (struct qeth_ipa_cmd *)(iob->data + IPA_PDU_HEADER_SIZE);
++ cmd->data.setadapterparms.data.mode = mode;
++ qeth_send_ipa_cmd(card, iob, qeth_setadp_promisc_mode_cb, NULL);
++}
++EXPORT_SYMBOL_GPL(qeth_setadp_promisc_mode);
++
++int qeth_change_mtu(struct net_device *dev, int new_mtu)
++{
++ struct qeth_card *card;
++ char dbf_text[15];
++
++ card = netdev_priv(dev);
++
++ QETH_DBF_TEXT(TRACE, 4, "chgmtu");
++ sprintf(dbf_text, "%8x", new_mtu);
++ QETH_DBF_TEXT(TRACE, 4, dbf_text);
++
++ if (new_mtu < 64)
++ return -EINVAL;
++ if (new_mtu > 65535)
++ return -EINVAL;
++ if ((!qeth_is_supported(card, IPA_IP_FRAGMENTATION)) &&
++ (!qeth_mtu_is_valid(card, new_mtu)))
++ return -EINVAL;
++ dev->mtu = new_mtu;
++ return 0;
++}
++EXPORT_SYMBOL_GPL(qeth_change_mtu);
++
++struct net_device_stats *qeth_get_stats(struct net_device *dev)
++{
++ struct qeth_card *card;
++
++ card = netdev_priv(dev);
++
++ QETH_DBF_TEXT(TRACE, 5, "getstat");
++
++ return &card->stats;
++}
++EXPORT_SYMBOL_GPL(qeth_get_stats);
++
++static int qeth_setadpparms_change_macaddr_cb(struct qeth_card *card,
++ struct qeth_reply *reply, unsigned long data)
++{
++ struct qeth_ipa_cmd *cmd;
++
++ QETH_DBF_TEXT(TRACE, 4, "chgmaccb");
++
++ cmd = (struct qeth_ipa_cmd *) data;
++ if (!card->options.layer2 ||
++ !(card->info.mac_bits & QETH_LAYER2_MAC_READ)) {
++ memcpy(card->dev->dev_addr,
++ &cmd->data.setadapterparms.data.change_addr.addr,
++ OSA_ADDR_LEN);
++ card->info.mac_bits |= QETH_LAYER2_MAC_READ;
++ }
++ qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
++ return 0;
++}
++
++int qeth_setadpparms_change_macaddr(struct qeth_card *card)
++{
++ int rc;
++ struct qeth_cmd_buffer *iob;
++ struct qeth_ipa_cmd *cmd;
++
++ QETH_DBF_TEXT(TRACE, 4, "chgmac");
++
++ iob = qeth_get_adapter_cmd(card, IPA_SETADP_ALTER_MAC_ADDRESS,
++ sizeof(struct qeth_ipacmd_setadpparms));
++ cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++ cmd->data.setadapterparms.data.change_addr.cmd = CHANGE_ADDR_READ_MAC;
++ cmd->data.setadapterparms.data.change_addr.addr_size = OSA_ADDR_LEN;
++ memcpy(&cmd->data.setadapterparms.data.change_addr.addr,
++ card->dev->dev_addr, OSA_ADDR_LEN);
++ rc = qeth_send_ipa_cmd(card, iob, qeth_setadpparms_change_macaddr_cb,
++ NULL);
++ return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_setadpparms_change_macaddr);
++
++void qeth_tx_timeout(struct net_device *dev)
++{
++ struct qeth_card *card;
++
++ card = netdev_priv(dev);
++ card->stats.tx_errors++;
++ qeth_schedule_recovery(card);
++}
++EXPORT_SYMBOL_GPL(qeth_tx_timeout);
++
++int qeth_mdio_read(struct net_device *dev, int phy_id, int regnum)
++{
++ struct qeth_card *card = netdev_priv(dev);
++ int rc = 0;
++
++ switch (regnum) {
++ case MII_BMCR: /* Basic mode control register */
++ rc = BMCR_FULLDPLX;
++ if ((card->info.link_type != QETH_LINK_TYPE_GBIT_ETH) &&
++ (card->info.link_type != QETH_LINK_TYPE_OSN) &&
++ (card->info.link_type != QETH_LINK_TYPE_10GBIT_ETH))
++ rc |= BMCR_SPEED100;
++ break;
++ case MII_BMSR: /* Basic mode status register */
++ rc = BMSR_ERCAP | BMSR_ANEGCOMPLETE | BMSR_LSTATUS |
++ BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | BMSR_100FULL |
++ BMSR_100BASE4;
++ break;
++ case MII_PHYSID1: /* PHYS ID 1 */
++ rc = (dev->dev_addr[0] << 16) | (dev->dev_addr[1] << 8) |
++ dev->dev_addr[2];
++ rc = (rc >> 5) & 0xFFFF;
++ break;
++ case MII_PHYSID2: /* PHYS ID 2 */
++ rc = (dev->dev_addr[2] << 10) & 0xFFFF;
++ break;
++ case MII_ADVERTISE: /* Advertisement control reg */
++ rc = ADVERTISE_ALL;
++ break;
++ case MII_LPA: /* Link partner ability reg */
++ rc = LPA_10HALF | LPA_10FULL | LPA_100HALF | LPA_100FULL |
++ LPA_100BASE4 | LPA_LPACK;
++ break;
++ case MII_EXPANSION: /* Expansion register */
++ break;
++ case MII_DCOUNTER: /* disconnect counter */
++ break;
++ case MII_FCSCOUNTER: /* false carrier counter */
++ break;
++ case MII_NWAYTEST: /* N-way auto-neg test register */
++ break;
++ case MII_RERRCOUNTER: /* rx error counter */
++ rc = card->stats.rx_errors;
++ break;
++ case MII_SREVISION: /* silicon revision */
++ break;
++ case MII_RESV1: /* reserved 1 */
++ break;
++ case MII_LBRERROR: /* loopback, rx, bypass error */
++ break;
++ case MII_PHYADDR: /* physical address */
++ break;
++ case MII_RESV2: /* reserved 2 */
++ break;
++ case MII_TPISTATUS: /* TPI status for 10mbps */
++ break;
++ case MII_NCONFIG: /* network interface config */
++ break;
++ default:
++ break;
++ }
++ return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_mdio_read);
++
++static int qeth_send_ipa_snmp_cmd(struct qeth_card *card,
++ struct qeth_cmd_buffer *iob, int len,
++ int (*reply_cb)(struct qeth_card *, struct qeth_reply *,
++ unsigned long),
++ void *reply_param)
++{
++ u16 s1, s2;
++
++ QETH_DBF_TEXT(TRACE, 4, "sendsnmp");
++
++ memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
++ memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
++ &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
++ /* adjust PDU length fields in IPA_PDU_HEADER */
++ s1 = (u32) IPA_PDU_HEADER_SIZE + len;
++ s2 = (u32) len;
++ memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
++ memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
++ memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
++ memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
++ return qeth_send_control_data(card, IPA_PDU_HEADER_SIZE + len, iob,
++ reply_cb, reply_param);
++}
++
++static int qeth_snmp_command_cb(struct qeth_card *card,
++ struct qeth_reply *reply, unsigned long sdata)
++{
++ struct qeth_ipa_cmd *cmd;
++ struct qeth_arp_query_info *qinfo;
++ struct qeth_snmp_cmd *snmp;
++ unsigned char *data;
++ __u16 data_len;
++
++ QETH_DBF_TEXT(TRACE, 3, "snpcmdcb");
++
++ cmd = (struct qeth_ipa_cmd *) sdata;
++ data = (unsigned char *)((char *)cmd - reply->offset);
++ qinfo = (struct qeth_arp_query_info *) reply->param;
++ snmp = &cmd->data.setadapterparms.data.snmp;
++
++ if (cmd->hdr.return_code) {
++ QETH_DBF_TEXT_(TRACE, 4, "scer1%i", cmd->hdr.return_code);
++ return 0;
++ }
++ if (cmd->data.setadapterparms.hdr.return_code) {
++ cmd->hdr.return_code =
++ cmd->data.setadapterparms.hdr.return_code;
++ QETH_DBF_TEXT_(TRACE, 4, "scer2%i", cmd->hdr.return_code);
++ return 0;
++ }
++ data_len = *((__u16 *)QETH_IPA_PDU_LEN_PDU1(data));
++ if (cmd->data.setadapterparms.hdr.seq_no == 1)
++ data_len -= (__u16)((char *)&snmp->data - (char *)cmd);
++ else
++ data_len -= (__u16)((char *)&snmp->request - (char *)cmd);
++
++ /* check if there is enough room in userspace */
++ if ((qinfo->udata_len - qinfo->udata_offset) < data_len) {
++ QETH_DBF_TEXT_(TRACE, 4, "scer3%i", -ENOMEM);
++ cmd->hdr.return_code = -ENOMEM;
++ return 0;
++ }
++ QETH_DBF_TEXT_(TRACE, 4, "snore%i",
++ cmd->data.setadapterparms.hdr.used_total);
++ QETH_DBF_TEXT_(TRACE, 4, "sseqn%i",
++ cmd->data.setadapterparms.hdr.seq_no);
++ /*copy entries to user buffer*/
++ if (cmd->data.setadapterparms.hdr.seq_no == 1) {
++ memcpy(qinfo->udata + qinfo->udata_offset,
++ (char *)snmp,
++ data_len + offsetof(struct qeth_snmp_cmd, data));
++ qinfo->udata_offset += offsetof(struct qeth_snmp_cmd, data);
++ } else {
++ memcpy(qinfo->udata + qinfo->udata_offset,
++ (char *)&snmp->request, data_len);
++ }
++ qinfo->udata_offset += data_len;
++ /* check if all replies received ... */
++ QETH_DBF_TEXT_(TRACE, 4, "srtot%i",
++ cmd->data.setadapterparms.hdr.used_total);
++ QETH_DBF_TEXT_(TRACE, 4, "srseq%i",
++ cmd->data.setadapterparms.hdr.seq_no);
++ if (cmd->data.setadapterparms.hdr.seq_no <
++ cmd->data.setadapterparms.hdr.used_total)
++ return 1;
++ return 0;
++}
++
++int qeth_snmp_command(struct qeth_card *card, char __user *udata)
++{
++ struct qeth_cmd_buffer *iob;
++ struct qeth_ipa_cmd *cmd;
++ struct qeth_snmp_ureq *ureq;
++ int req_len;
++ struct qeth_arp_query_info qinfo = {0, };
++ int rc = 0;
++
++ QETH_DBF_TEXT(TRACE, 3, "snmpcmd");
++
++ if (card->info.guestlan)
++ return -EOPNOTSUPP;
++
++ if ((!qeth_adp_supported(card, IPA_SETADP_SET_SNMP_CONTROL)) &&
++ (!card->options.layer2)) {
++ PRINT_WARN("SNMP Query MIBS not supported "
++ "on %s!\n", QETH_CARD_IFNAME(card));
++ return -EOPNOTSUPP;
++ }
++ /* skip 4 bytes (data_len struct member) to get req_len */
++ if (copy_from_user(&req_len, udata + sizeof(int), sizeof(int)))
++ return -EFAULT;
++ ureq = kmalloc(req_len+sizeof(struct qeth_snmp_ureq_hdr), GFP_KERNEL);
++ if (!ureq) {
++ QETH_DBF_TEXT(TRACE, 2, "snmpnome");
++ return -ENOMEM;
++ }
++ if (copy_from_user(ureq, udata,
++ req_len + sizeof(struct qeth_snmp_ureq_hdr))) {
++ kfree(ureq);
++ return -EFAULT;
++ }
++ qinfo.udata_len = ureq->hdr.data_len;
++ qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL);
++ if (!qinfo.udata) {
++ kfree(ureq);
++ return -ENOMEM;
++ }
++ qinfo.udata_offset = sizeof(struct qeth_snmp_ureq_hdr);
++
++ iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_SNMP_CONTROL,
++ QETH_SNMP_SETADP_CMDLENGTH + req_len);
++ cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++ memcpy(&cmd->data.setadapterparms.data.snmp, &ureq->cmd, req_len);
++ rc = qeth_send_ipa_snmp_cmd(card, iob, QETH_SETADP_BASE_LEN + req_len,
++ qeth_snmp_command_cb, (void *)&qinfo);
++ if (rc)
++ PRINT_WARN("SNMP command failed on %s: (0x%x)\n",
++ QETH_CARD_IFNAME(card), rc);
++ else {
++ if (copy_to_user(udata, qinfo.udata, qinfo.udata_len))
++ rc = -EFAULT;
++ }
++
++ kfree(ureq);
++ kfree(qinfo.udata);
++ return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_snmp_command);
++
++static inline int qeth_get_qdio_q_format(struct qeth_card *card)
++{
++ switch (card->info.type) {
++ case QETH_CARD_TYPE_IQD:
++ return 2;
++ default:
++ return 0;
++ }
++}
++
++static int qeth_qdio_establish(struct qeth_card *card)
++{
++ struct qdio_initialize init_data;
++ char *qib_param_field;
++ struct qdio_buffer **in_sbal_ptrs;
++ struct qdio_buffer **out_sbal_ptrs;
++ int i, j, k;
++ int rc = 0;
++
++ QETH_DBF_TEXT(SETUP, 2, "qdioest");
++
++ qib_param_field = kzalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(char),
++ GFP_KERNEL);
++ if (!qib_param_field)
++ return -ENOMEM;
++
++ qeth_create_qib_param_field(card, qib_param_field);
++ qeth_create_qib_param_field_blkt(card, qib_param_field);
++
++ in_sbal_ptrs = kmalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(void *),
++ GFP_KERNEL);
++ if (!in_sbal_ptrs) {
++ kfree(qib_param_field);
++ return -ENOMEM;
++ }
++ for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i)
++ in_sbal_ptrs[i] = (struct qdio_buffer *)
++ virt_to_phys(card->qdio.in_q->bufs[i].buffer);
++
++ out_sbal_ptrs =
++ kmalloc(card->qdio.no_out_queues * QDIO_MAX_BUFFERS_PER_Q *
++ sizeof(void *), GFP_KERNEL);
++ if (!out_sbal_ptrs) {
++ kfree(in_sbal_ptrs);
++ kfree(qib_param_field);
++ return -ENOMEM;
++ }
++ for (i = 0, k = 0; i < card->qdio.no_out_queues; ++i)
++ for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j, ++k) {
++ out_sbal_ptrs[k] = (struct qdio_buffer *)virt_to_phys(
++ card->qdio.out_qs[i]->bufs[j].buffer);
++ }
++
++ memset(&init_data, 0, sizeof(struct qdio_initialize));
++ init_data.cdev = CARD_DDEV(card);
++ init_data.q_format = qeth_get_qdio_q_format(card);
++ init_data.qib_param_field_format = 0;
++ init_data.qib_param_field = qib_param_field;
++ init_data.min_input_threshold = QETH_MIN_INPUT_THRESHOLD;
++ init_data.max_input_threshold = QETH_MAX_INPUT_THRESHOLD;
++ init_data.min_output_threshold = QETH_MIN_OUTPUT_THRESHOLD;
++ init_data.max_output_threshold = QETH_MAX_OUTPUT_THRESHOLD;
++ init_data.no_input_qs = 1;
++ init_data.no_output_qs = card->qdio.no_out_queues;
++ init_data.input_handler = card->discipline.input_handler;
++ init_data.output_handler = card->discipline.output_handler;
++ init_data.int_parm = (unsigned long) card;
++ init_data.flags = QDIO_INBOUND_0COPY_SBALS |
++ QDIO_OUTBOUND_0COPY_SBALS |
++ QDIO_USE_OUTBOUND_PCIS;
++ init_data.input_sbal_addr_array = (void **) in_sbal_ptrs;
++ init_data.output_sbal_addr_array = (void **) out_sbal_ptrs;
++
++ if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED,
++ QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED) {
++ rc = qdio_initialize(&init_data);
++ if (rc)
++ atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED);
++ }
++ kfree(out_sbal_ptrs);
++ kfree(in_sbal_ptrs);
++ kfree(qib_param_field);
++ return rc;
++}
++
++static void qeth_core_free_card(struct qeth_card *card)
++{
++
++ QETH_DBF_TEXT(SETUP, 2, "freecrd");
++ QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
++ qeth_clean_channel(&card->read);
++ qeth_clean_channel(&card->write);
++ if (card->dev)
++ free_netdev(card->dev);
++ kfree(card->ip_tbd_list);
++ qeth_free_qdio_buffers(card);
++ kfree(card);
++}
++
++static struct ccw_device_id qeth_ids[] = {
++ {CCW_DEVICE(0x1731, 0x01), .driver_info = QETH_CARD_TYPE_OSAE},
++ {CCW_DEVICE(0x1731, 0x05), .driver_info = QETH_CARD_TYPE_IQD},
++ {CCW_DEVICE(0x1731, 0x06), .driver_info = QETH_CARD_TYPE_OSN},
++ {},
++};
++MODULE_DEVICE_TABLE(ccw, qeth_ids);
++
++static struct ccw_driver qeth_ccw_driver = {
++ .name = "qeth",
++ .ids = qeth_ids,
++ .probe = ccwgroup_probe_ccwdev,
++ .remove = ccwgroup_remove_ccwdev,
++};
++
++static int qeth_core_driver_group(const char *buf, struct device *root_dev,
++ unsigned long driver_id)
++{
++ const char *start, *end;
++ char bus_ids[3][BUS_ID_SIZE], *argv[3];
++ int i;
++
++ start = buf;
++ for (i = 0; i < 3; i++) {
++ static const char delim[] = { ',', ',', '\n' };
++ int len;
++
++ end = strchr(start, delim[i]);
++ if (!end)
++ return -EINVAL;
++ len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start);
++ strncpy(bus_ids[i], start, len);
++ bus_ids[i][len] = '\0';
++ start = end + 1;
++ argv[i] = bus_ids[i];
++ }
++
++ return (ccwgroup_create(root_dev, driver_id,
++ &qeth_ccw_driver, 3, argv));
++}
++
++int qeth_core_hardsetup_card(struct qeth_card *card)
++{
++ int retries = 3;
++ int mpno;
++ int rc;
++
++ QETH_DBF_TEXT(SETUP, 2, "hrdsetup");
++ atomic_set(&card->force_alloc_skb, 0);
++retry:
++ if (retries < 3) {
++ PRINT_WARN("Retrying to do IDX activates.\n");
++ ccw_device_set_offline(CARD_DDEV(card));
++ ccw_device_set_offline(CARD_WDEV(card));
++ ccw_device_set_offline(CARD_RDEV(card));
++ ccw_device_set_online(CARD_RDEV(card));
++ ccw_device_set_online(CARD_WDEV(card));
++ ccw_device_set_online(CARD_DDEV(card));
++ }
++ rc = qeth_qdio_clear_card(card, card->info.type != QETH_CARD_TYPE_IQD);
++ if (rc == -ERESTARTSYS) {
++ QETH_DBF_TEXT(SETUP, 2, "break1");
++ return rc;
++ } else if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++ if (--retries < 0)
++ goto out;
++ else
++ goto retry;
++ }
++
++ rc = qeth_get_unitaddr(card);
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
++ return rc;
++ }
++
++ mpno = QETH_MAX_PORTNO;
++ if (card->info.portno > mpno) {
++ PRINT_ERR("Device %s does not offer port number %d \n.",
++ CARD_BUS_ID(card), card->info.portno);
++ rc = -ENODEV;
++ goto out;
++ }
++ qeth_init_tokens(card);
++ qeth_init_func_level(card);
++ rc = qeth_idx_activate_channel(&card->read, qeth_idx_read_cb);
++ if (rc == -ERESTARTSYS) {
++ QETH_DBF_TEXT(SETUP, 2, "break2");
++ return rc;
++ } else if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc);
++ if (--retries < 0)
++ goto out;
++ else
++ goto retry;
++ }
++ rc = qeth_idx_activate_channel(&card->write, qeth_idx_write_cb);
++ if (rc == -ERESTARTSYS) {
++ QETH_DBF_TEXT(SETUP, 2, "break3");
++ return rc;
++ } else if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "4err%d", rc);
++ if (--retries < 0)
++ goto out;
++ else
++ goto retry;
++ }
++ rc = qeth_mpc_initialize(card);
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc);
++ goto out;
++ }
++ return 0;
++out:
++ PRINT_ERR("Initialization in hardsetup failed! rc=%d\n", rc);
++ return rc;
++}
++EXPORT_SYMBOL_GPL(qeth_core_hardsetup_card);
++
++static inline int qeth_create_skb_frag(struct qdio_buffer_element *element,
++ struct sk_buff **pskb, int offset, int *pfrag, int data_len)
++{
++ struct page *page = virt_to_page(element->addr);
++ if (*pskb == NULL) {
++ /* the upper protocol layers assume that there is data in the
++ * skb itself. Copy a small amount (64 bytes) to make them
++ * happy. */
++ *pskb = dev_alloc_skb(64 + ETH_HLEN);
++ if (!(*pskb))
++ return -ENOMEM;
++ skb_reserve(*pskb, ETH_HLEN);
++ if (data_len <= 64) {
++ memcpy(skb_put(*pskb, data_len), element->addr + offset,
++ data_len);
++ } else {
++ get_page(page);
++ memcpy(skb_put(*pskb, 64), element->addr + offset, 64);
++ skb_fill_page_desc(*pskb, *pfrag, page, offset + 64,
++ data_len - 64);
++ (*pskb)->data_len += data_len - 64;
++ (*pskb)->len += data_len - 64;
++ (*pskb)->truesize += data_len - 64;
++ (*pfrag)++;
++ }
++ } else {
++ get_page(page);
++ skb_fill_page_desc(*pskb, *pfrag, page, offset, data_len);
++ (*pskb)->data_len += data_len;
++ (*pskb)->len += data_len;
++ (*pskb)->truesize += data_len;
++ (*pfrag)++;
++ }
++ return 0;
++}
++
++struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
++ struct qdio_buffer *buffer,
++ struct qdio_buffer_element **__element, int *__offset,
++ struct qeth_hdr **hdr)
++{
++ struct qdio_buffer_element *element = *__element;
++ int offset = *__offset;
++ struct sk_buff *skb = NULL;
++ int skb_len;
++ void *data_ptr;
++ int data_len;
++ int headroom = 0;
++ int use_rx_sg = 0;
++ int frag = 0;
++
++ QETH_DBF_TEXT(TRACE, 6, "nextskb");
++ /* qeth_hdr must not cross element boundaries */
++ if (element->length < offset + sizeof(struct qeth_hdr)) {
++ if (qeth_is_last_sbale(element))
++ return NULL;
++ element++;
++ offset = 0;
++ if (element->length < sizeof(struct qeth_hdr))
++ return NULL;
++ }
++ *hdr = element->addr + offset;
++
++ offset += sizeof(struct qeth_hdr);
++ if (card->options.layer2) {
++ if (card->info.type == QETH_CARD_TYPE_OSN) {
++ skb_len = (*hdr)->hdr.osn.pdu_length;
++ headroom = sizeof(struct qeth_hdr);
++ } else {
++ skb_len = (*hdr)->hdr.l2.pkt_length;
++ }
++ } else {
++ skb_len = (*hdr)->hdr.l3.length;
++ if ((card->info.link_type == QETH_LINK_TYPE_LANE_TR) ||
++ (card->info.link_type == QETH_LINK_TYPE_HSTR))
++ headroom = TR_HLEN;
++ else
++ headroom = ETH_HLEN;
++ }
++
++ if (!skb_len)
++ return NULL;
++
++ if ((skb_len >= card->options.rx_sg_cb) &&
++ (!(card->info.type == QETH_CARD_TYPE_OSN)) &&
++ (!atomic_read(&card->force_alloc_skb))) {
++ use_rx_sg = 1;
++ } else {
++ skb = dev_alloc_skb(skb_len + headroom);
++ if (!skb)
++ goto no_mem;
++ if (headroom)
++ skb_reserve(skb, headroom);
++ }
++
++ data_ptr = element->addr + offset;
++ while (skb_len) {
++ data_len = min(skb_len, (int)(element->length - offset));
++ if (data_len) {
++ if (use_rx_sg) {
++ if (qeth_create_skb_frag(element, &skb, offset,
++ &frag, data_len))
++ goto no_mem;
++ } else {
++ memcpy(skb_put(skb, data_len), data_ptr,
++ data_len);
++ }
++ }
++ skb_len -= data_len;
++ if (skb_len) {
++ if (qeth_is_last_sbale(element)) {
++ QETH_DBF_TEXT(TRACE, 4, "unexeob");
++ QETH_DBF_TEXT_(TRACE, 4, "%s",
++ CARD_BUS_ID(card));
++ QETH_DBF_TEXT(QERR, 2, "unexeob");
++ QETH_DBF_TEXT_(QERR, 2, "%s",
++ CARD_BUS_ID(card));
++ QETH_DBF_HEX(MISC, 4, buffer, sizeof(*buffer));
++ dev_kfree_skb_any(skb);
++ card->stats.rx_errors++;
++ return NULL;
++ }
++ element++;
++ offset = 0;
++ data_ptr = element->addr;
++ } else {
++ offset += data_len;
++ }
++ }
++ *__element = element;
++ *__offset = offset;
++ if (use_rx_sg && card->options.performance_stats) {
++ card->perf_stats.sg_skbs_rx++;
++ card->perf_stats.sg_frags_rx += skb_shinfo(skb)->nr_frags;
++ }
++ return skb;
++no_mem:
++ if (net_ratelimit()) {
++ PRINT_WARN("No memory for packet received on %s.\n",
++ QETH_CARD_IFNAME(card));
++ QETH_DBF_TEXT(TRACE, 2, "noskbmem");
++ QETH_DBF_TEXT_(TRACE, 2, "%s", CARD_BUS_ID(card));
++ }
++ card->stats.rx_dropped++;
++ return NULL;
++}
++EXPORT_SYMBOL_GPL(qeth_core_get_next_skb);
++
++static void qeth_unregister_dbf_views(void)
++{
++ int x;
++ for (x = 0; x < QETH_DBF_INFOS; x++) {
++ debug_unregister(qeth_dbf[x].id);
++ qeth_dbf[x].id = NULL;
++ }
++}
++
++static int qeth_register_dbf_views(void)
++{
++ int ret;
++ int x;
++
++ for (x = 0; x < QETH_DBF_INFOS; x++) {
++ /* register the areas */
++ qeth_dbf[x].id = debug_register(qeth_dbf[x].name,
++ qeth_dbf[x].pages,
++ qeth_dbf[x].areas,
++ qeth_dbf[x].len);
++ if (qeth_dbf[x].id == NULL) {
++ qeth_unregister_dbf_views();
++ return -ENOMEM;
++ }
++
++ /* register a view */
++ ret = debug_register_view(qeth_dbf[x].id, qeth_dbf[x].view);
++ if (ret) {
++ qeth_unregister_dbf_views();
++ return ret;
++ }
++
++ /* set a passing level */
++ debug_set_level(qeth_dbf[x].id, qeth_dbf[x].level);
++ }
++
++ return 0;
++}
++
++int qeth_core_load_discipline(struct qeth_card *card,
++ enum qeth_discipline_id discipline)
++{
++ int rc = 0;
++ switch (discipline) {
++ case QETH_DISCIPLINE_LAYER3:
++ card->discipline.ccwgdriver = try_then_request_module(
++ symbol_get(qeth_l3_ccwgroup_driver),
++ "qeth_l3");
++ break;
++ case QETH_DISCIPLINE_LAYER2:
++ card->discipline.ccwgdriver = try_then_request_module(
++ symbol_get(qeth_l2_ccwgroup_driver),
++ "qeth_l2");
++ break;
++ }
++ if (!card->discipline.ccwgdriver) {
++ PRINT_ERR("Support for discipline %d not present\n",
++ discipline);
++ rc = -EINVAL;
++ }
++ return rc;
++}
++
++void qeth_core_free_discipline(struct qeth_card *card)
++{
++ if (card->options.layer2)
++ symbol_put(qeth_l2_ccwgroup_driver);
++ else
++ symbol_put(qeth_l3_ccwgroup_driver);
++ card->discipline.ccwgdriver = NULL;
++}
++
++static int qeth_core_probe_device(struct ccwgroup_device *gdev)
++{
++ struct qeth_card *card;
++ struct device *dev;
++ int rc;
++ unsigned long flags;
++
++ QETH_DBF_TEXT(SETUP, 2, "probedev");
++
++ dev = &gdev->dev;
++ if (!get_device(dev))
++ return -ENODEV;
++
++ QETH_DBF_TEXT_(SETUP, 2, "%s", gdev->dev.bus_id);
++
++ card = qeth_alloc_card();
++ if (!card) {
++ QETH_DBF_TEXT_(SETUP, 2, "1err%d", -ENOMEM);
++ rc = -ENOMEM;
++ goto err_dev;
++ }
++ card->read.ccwdev = gdev->cdev[0];
++ card->write.ccwdev = gdev->cdev[1];
++ card->data.ccwdev = gdev->cdev[2];
++ dev_set_drvdata(&gdev->dev, card);
++ card->gdev = gdev;
++ gdev->cdev[0]->handler = qeth_irq;
++ gdev->cdev[1]->handler = qeth_irq;
++ gdev->cdev[2]->handler = qeth_irq;
++
++ rc = qeth_determine_card_type(card);
++ if (rc) {
++ PRINT_WARN("%s: not a valid card type\n", __func__);
++ QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc);
++ goto err_card;
++ }
++ rc = qeth_setup_card(card);
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
++ goto err_card;
++ }
++
++ if (card->info.type == QETH_CARD_TYPE_OSN) {
++ rc = qeth_core_create_osn_attributes(dev);
++ if (rc)
++ goto err_card;
++ rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2);
++ if (rc) {
++ qeth_core_remove_osn_attributes(dev);
++ goto err_card;
++ }
++ rc = card->discipline.ccwgdriver->probe(card->gdev);
++ if (rc) {
++ qeth_core_free_discipline(card);
++ qeth_core_remove_osn_attributes(dev);
++ goto err_card;
++ }
++ } else {
++ rc = qeth_core_create_device_attributes(dev);
++ if (rc)
++ goto err_card;
++ }
++
++ write_lock_irqsave(&qeth_core_card_list.rwlock, flags);
++ list_add_tail(&card->list, &qeth_core_card_list.list);
++ write_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
++ return 0;
++
++err_card:
++ qeth_core_free_card(card);
++err_dev:
++ put_device(dev);
++ return rc;
++}
++
++static void qeth_core_remove_device(struct ccwgroup_device *gdev)
++{
++ unsigned long flags;
++ struct qeth_card *card = dev_get_drvdata(&gdev->dev);
++
++ if (card->discipline.ccwgdriver) {
++ card->discipline.ccwgdriver->remove(gdev);
++ qeth_core_free_discipline(card);
++ }
++
++ if (card->info.type == QETH_CARD_TYPE_OSN) {
++ qeth_core_remove_osn_attributes(&gdev->dev);
++ } else {
++ qeth_core_remove_device_attributes(&gdev->dev);
++ }
++ write_lock_irqsave(&qeth_core_card_list.rwlock, flags);
++ list_del(&card->list);
++ write_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
++ qeth_core_free_card(card);
++ dev_set_drvdata(&gdev->dev, NULL);
++ put_device(&gdev->dev);
++ return;
++}
++
++static int qeth_core_set_online(struct ccwgroup_device *gdev)
++{
++ struct qeth_card *card = dev_get_drvdata(&gdev->dev);
++ int rc = 0;
++ int def_discipline;
++
++ if (!card->discipline.ccwgdriver) {
++ if (card->info.type == QETH_CARD_TYPE_IQD)
++ def_discipline = QETH_DISCIPLINE_LAYER3;
++ else
++ def_discipline = QETH_DISCIPLINE_LAYER2;
++ rc = qeth_core_load_discipline(card, def_discipline);
++ if (rc)
++ goto err;
++ rc = card->discipline.ccwgdriver->probe(card->gdev);
++ if (rc)
++ goto err;
++ }
++ rc = card->discipline.ccwgdriver->set_online(gdev);
++err:
++ return rc;
++}
++
++static int qeth_core_set_offline(struct ccwgroup_device *gdev)
++{
++ struct qeth_card *card = dev_get_drvdata(&gdev->dev);
++ return card->discipline.ccwgdriver->set_offline(gdev);
++}
++
++static void qeth_core_shutdown(struct ccwgroup_device *gdev)
++{
++ struct qeth_card *card = dev_get_drvdata(&gdev->dev);
++ if (card->discipline.ccwgdriver &&
++ card->discipline.ccwgdriver->shutdown)
++ card->discipline.ccwgdriver->shutdown(gdev);
++}
++
++static struct ccwgroup_driver qeth_core_ccwgroup_driver = {
++ .owner = THIS_MODULE,
++ .name = "qeth",
++ .driver_id = 0xD8C5E3C8,
++ .probe = qeth_core_probe_device,
++ .remove = qeth_core_remove_device,
++ .set_online = qeth_core_set_online,
++ .set_offline = qeth_core_set_offline,
++ .shutdown = qeth_core_shutdown,
++};
++
++static ssize_t
++qeth_core_driver_group_store(struct device_driver *ddrv, const char *buf,
++ size_t count)
++{
++ int err;
++ err = qeth_core_driver_group(buf, qeth_core_root_dev,
++ qeth_core_ccwgroup_driver.driver_id);
++ if (err)
++ return err;
++ else
++ return count;
++}
++
++static DRIVER_ATTR(group, 0200, NULL, qeth_core_driver_group_store);
++
++static struct {
++ const char str[ETH_GSTRING_LEN];
++} qeth_ethtool_stats_keys[] = {
++/* 0 */{"rx skbs"},
++ {"rx buffers"},
++ {"tx skbs"},
++ {"tx buffers"},
++ {"tx skbs no packing"},
++ {"tx buffers no packing"},
++ {"tx skbs packing"},
++ {"tx buffers packing"},
++ {"tx sg skbs"},
++ {"tx sg frags"},
++/* 10 */{"rx sg skbs"},
++ {"rx sg frags"},
++ {"rx sg page allocs"},
++ {"tx large kbytes"},
++ {"tx large count"},
++ {"tx pk state ch n->p"},
++ {"tx pk state ch p->n"},
++ {"tx pk watermark low"},
++ {"tx pk watermark high"},
++ {"queue 0 buffer usage"},
++/* 20 */{"queue 1 buffer usage"},
++ {"queue 2 buffer usage"},
++ {"queue 3 buffer usage"},
++ {"rx handler time"},
++ {"rx handler count"},
++ {"rx do_QDIO time"},
++ {"rx do_QDIO count"},
++ {"tx handler time"},
++ {"tx handler count"},
++ {"tx time"},
++/* 30 */{"tx count"},
++ {"tx do_QDIO time"},
++ {"tx do_QDIO count"},
++};
++
++int qeth_core_get_stats_count(struct net_device *dev)
++{
++ return (sizeof(qeth_ethtool_stats_keys) / ETH_GSTRING_LEN);
++}
++EXPORT_SYMBOL_GPL(qeth_core_get_stats_count);
++
++void qeth_core_get_ethtool_stats(struct net_device *dev,
++ struct ethtool_stats *stats, u64 *data)
++{
++ struct qeth_card *card = netdev_priv(dev);
++ data[0] = card->stats.rx_packets -
++ card->perf_stats.initial_rx_packets;
++ data[1] = card->perf_stats.bufs_rec;
++ data[2] = card->stats.tx_packets -
++ card->perf_stats.initial_tx_packets;
++ data[3] = card->perf_stats.bufs_sent;
++ data[4] = card->stats.tx_packets - card->perf_stats.initial_tx_packets
++ - card->perf_stats.skbs_sent_pack;
++ data[5] = card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack;
++ data[6] = card->perf_stats.skbs_sent_pack;
++ data[7] = card->perf_stats.bufs_sent_pack;
++ data[8] = card->perf_stats.sg_skbs_sent;
++ data[9] = card->perf_stats.sg_frags_sent;
++ data[10] = card->perf_stats.sg_skbs_rx;
++ data[11] = card->perf_stats.sg_frags_rx;
++ data[12] = card->perf_stats.sg_alloc_page_rx;
++ data[13] = (card->perf_stats.large_send_bytes >> 10);
++ data[14] = card->perf_stats.large_send_cnt;
++ data[15] = card->perf_stats.sc_dp_p;
++ data[16] = card->perf_stats.sc_p_dp;
++ data[17] = QETH_LOW_WATERMARK_PACK;
++ data[18] = QETH_HIGH_WATERMARK_PACK;
++ data[19] = atomic_read(&card->qdio.out_qs[0]->used_buffers);
++ data[20] = (card->qdio.no_out_queues > 1) ?
++ atomic_read(&card->qdio.out_qs[1]->used_buffers) : 0;
++ data[21] = (card->qdio.no_out_queues > 2) ?
++ atomic_read(&card->qdio.out_qs[2]->used_buffers) : 0;
++ data[22] = (card->qdio.no_out_queues > 3) ?
++ atomic_read(&card->qdio.out_qs[3]->used_buffers) : 0;
++ data[23] = card->perf_stats.inbound_time;
++ data[24] = card->perf_stats.inbound_cnt;
++ data[25] = card->perf_stats.inbound_do_qdio_time;
++ data[26] = card->perf_stats.inbound_do_qdio_cnt;
++ data[27] = card->perf_stats.outbound_handler_time;
++ data[28] = card->perf_stats.outbound_handler_cnt;
++ data[29] = card->perf_stats.outbound_time;
++ data[30] = card->perf_stats.outbound_cnt;
++ data[31] = card->perf_stats.outbound_do_qdio_time;
++ data[32] = card->perf_stats.outbound_do_qdio_cnt;
++}
++EXPORT_SYMBOL_GPL(qeth_core_get_ethtool_stats);
++
++void qeth_core_get_strings(struct net_device *dev, u32 stringset, u8 *data)
++{
++ switch (stringset) {
++ case ETH_SS_STATS:
++ memcpy(data, &qeth_ethtool_stats_keys,
++ sizeof(qeth_ethtool_stats_keys));
++ break;
++ default:
++ WARN_ON(1);
++ break;
++ }
++}
++EXPORT_SYMBOL_GPL(qeth_core_get_strings);
++
++void qeth_core_get_drvinfo(struct net_device *dev,
++ struct ethtool_drvinfo *info)
++{
++ struct qeth_card *card = netdev_priv(dev);
++ if (card->options.layer2)
++ strcpy(info->driver, "qeth_l2");
++ else
++ strcpy(info->driver, "qeth_l3");
++
++ strcpy(info->version, "1.0");
++ strcpy(info->fw_version, card->info.mcl_level);
++ sprintf(info->bus_info, "%s/%s/%s",
++ CARD_RDEV_ID(card),
++ CARD_WDEV_ID(card),
++ CARD_DDEV_ID(card));
++}
++EXPORT_SYMBOL_GPL(qeth_core_get_drvinfo);
++
++static int __init qeth_core_init(void)
++{
++ int rc;
++
++ PRINT_INFO("loading core functions\n");
++ INIT_LIST_HEAD(&qeth_core_card_list.list);
++ rwlock_init(&qeth_core_card_list.rwlock);
++
++ rc = qeth_register_dbf_views();
++ if (rc)
++ goto out_err;
++ rc = ccw_driver_register(&qeth_ccw_driver);
++ if (rc)
++ goto ccw_err;
++ rc = ccwgroup_driver_register(&qeth_core_ccwgroup_driver);
++ if (rc)
++ goto ccwgroup_err;
++ rc = driver_create_file(&qeth_core_ccwgroup_driver.driver,
++ &driver_attr_group);
++ if (rc)
++ goto driver_err;
++ qeth_core_root_dev = s390_root_dev_register("qeth");
++ rc = IS_ERR(qeth_core_root_dev) ? PTR_ERR(qeth_core_root_dev) : 0;
++ if (rc)
++ goto register_err;
++ return 0;
++
++register_err:
++ driver_remove_file(&qeth_core_ccwgroup_driver.driver,
++ &driver_attr_group);
++driver_err:
++ ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver);
++ccwgroup_err:
++ ccw_driver_unregister(&qeth_ccw_driver);
++ccw_err:
++ qeth_unregister_dbf_views();
++out_err:
++ PRINT_ERR("Initialization failed with code %d\n", rc);
++ return rc;
++}
++
++static void __exit qeth_core_exit(void)
++{
++ s390_root_dev_unregister(qeth_core_root_dev);
++ driver_remove_file(&qeth_core_ccwgroup_driver.driver,
++ &driver_attr_group);
++ ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver);
++ ccw_driver_unregister(&qeth_ccw_driver);
++ qeth_unregister_dbf_views();
++ PRINT_INFO("core functions removed\n");
++}
++
++module_init(qeth_core_init);
++module_exit(qeth_core_exit);
++MODULE_AUTHOR("Frank Blaschka <frank.blaschka at de.ibm.com>");
++MODULE_DESCRIPTION("qeth core functions");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/s390/net/qeth_core_mpc.c b/drivers/s390/net/qeth_core_mpc.c
+new file mode 100644
+index 0000000..06f4de1
+--- /dev/null
++++ b/drivers/s390/net/qeth_core_mpc.c
+@@ -0,0 +1,266 @@
++/*
++ * drivers/s390/net/qeth_core_mpc.c
++ *
++ * Copyright IBM Corp. 2007
++ * Author(s): Frank Pavlic <fpavlic at de.ibm.com>,
++ * Thomas Spatzier <tspat at de.ibm.com>,
++ * Frank Blaschka <frank.blaschka at de.ibm.com>
++ */
++
++#include <linux/module.h>
++#include <asm/cio.h>
++#include "qeth_core_mpc.h"
++
++unsigned char IDX_ACTIVATE_READ[] = {
++ 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x19, 0x01, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc1,
++ 0xd3, 0xd3, 0xd6, 0xd3, 0xc5, 0x40, 0x00, 0x00,
++ 0x00, 0x00
++};
++
++unsigned char IDX_ACTIVATE_WRITE[] = {
++ 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x15, 0x01, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00,
++ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc1,
++ 0xd3, 0xd3, 0xd6, 0xd3, 0xc5, 0x40, 0x00, 0x00,
++ 0x00, 0x00
++};
++
++unsigned char CM_ENABLE[] = {
++ 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
++ 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x63,
++ 0x10, 0x00, 0x00, 0x01,
++ 0x00, 0x00, 0x00, 0x00,
++ 0x81, 0x7e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x23,
++ 0x00, 0x00, 0x23, 0x05, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x01, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x40,
++ 0x00, 0x0c, 0x41, 0x02, 0x00, 0x17, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x0b, 0x04, 0x01,
++ 0x7e, 0x04, 0x05, 0x00, 0x01, 0x01, 0x0f,
++ 0x00,
++ 0x0c, 0x04, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff
++};
++
++unsigned char CM_SETUP[] = {
++ 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
++ 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x64,
++ 0x10, 0x00, 0x00, 0x01,
++ 0x00, 0x00, 0x00, 0x00,
++ 0x81, 0x7e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x24,
++ 0x00, 0x00, 0x24, 0x05, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x01, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x40,
++ 0x00, 0x0c, 0x41, 0x04, 0x00, 0x18, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x09, 0x04, 0x04,
++ 0x05, 0x00, 0x01, 0x01, 0x11,
++ 0x00, 0x09, 0x04,
++ 0x05, 0x05, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x06,
++ 0x04, 0x06, 0xc8, 0x00
++};
++
++unsigned char ULP_ENABLE[] = {
++ 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
++ 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x6b,
++ 0x10, 0x00, 0x00, 0x01,
++ 0x00, 0x00, 0x00, 0x00,
++ 0x41, 0x7e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x2b,
++ 0x00, 0x00, 0x2b, 0x05, 0x20, 0x01, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x01, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x40,
++ 0x00, 0x0c, 0x41, 0x02, 0x00, 0x1f, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x0b, 0x04, 0x01,
++ 0x03, 0x04, 0x05, 0x00, 0x01, 0x01, 0x12,
++ 0x00,
++ 0x14, 0x04, 0x0a, 0x00, 0x20, 0x00, 0x00, 0xff,
++ 0xff, 0x00, 0x08, 0xc8, 0xe8, 0xc4, 0xf1, 0xc7,
++ 0xf1, 0x00, 0x00
++};
++
++unsigned char ULP_SETUP[] = {
++ 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
++ 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x6c,
++ 0x10, 0x00, 0x00, 0x01,
++ 0x00, 0x00, 0x00, 0x00,
++ 0x41, 0x7e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02,
++ 0x00, 0x00, 0x00, 0x01, 0x00, 0x24, 0x00, 0x2c,
++ 0x00, 0x00, 0x2c, 0x05, 0x20, 0x01, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x01, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x40,
++ 0x00, 0x0c, 0x41, 0x04, 0x00, 0x20, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x09, 0x04, 0x04,
++ 0x05, 0x00, 0x01, 0x01, 0x14,
++ 0x00, 0x09, 0x04,
++ 0x05, 0x05, 0x30, 0x01, 0x00, 0x00,
++ 0x00, 0x06,
++ 0x04, 0x06, 0x40, 0x00,
++ 0x00, 0x08, 0x04, 0x0b,
++ 0x00, 0x00, 0x00, 0x00
++};
++
++unsigned char DM_ACT[] = {
++ 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
++ 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x55,
++ 0x10, 0x00, 0x00, 0x01,
++ 0x00, 0x00, 0x00, 0x00,
++ 0x41, 0x7e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03,
++ 0x00, 0x00, 0x00, 0x02, 0x00, 0x24, 0x00, 0x15,
++ 0x00, 0x00, 0x2c, 0x05, 0x20, 0x01, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x01, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x40,
++ 0x00, 0x0c, 0x43, 0x60, 0x00, 0x09, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x09, 0x04, 0x04,
++ 0x05, 0x40, 0x01, 0x01, 0x00
++};
++
++unsigned char IPA_PDU_HEADER[] = {
++ 0x00, 0xe0, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77,
++ 0x00, 0x00, 0x00, 0x14, 0x00, 0x00,
++ (IPA_PDU_HEADER_SIZE+sizeof(struct qeth_ipa_cmd)) / 256,
++ (IPA_PDU_HEADER_SIZE+sizeof(struct qeth_ipa_cmd)) % 256,
++ 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
++ 0xc1, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x24,
++ sizeof(struct qeth_ipa_cmd) / 256,
++ sizeof(struct qeth_ipa_cmd) % 256,
++ 0x00,
++ sizeof(struct qeth_ipa_cmd) / 256,
++ sizeof(struct qeth_ipa_cmd) % 256,
++ 0x05,
++ 0x77, 0x77, 0x77, 0x77,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x01, 0x00,
++ sizeof(struct qeth_ipa_cmd) / 256,
++ sizeof(struct qeth_ipa_cmd) % 256,
++ 0x00, 0x00, 0x00, 0x40,
++};
++EXPORT_SYMBOL_GPL(IPA_PDU_HEADER);
++
++unsigned char WRITE_CCW[] = {
++ 0x01, CCW_FLAG_SLI, 0, 0,
++ 0, 0, 0, 0
++};
++
++unsigned char READ_CCW[] = {
++ 0x02, CCW_FLAG_SLI, 0, 0,
++ 0, 0, 0, 0
++};
++
++
++struct ipa_rc_msg {
++ enum qeth_ipa_return_codes rc;
++ char *msg;
++};
++
++static struct ipa_rc_msg qeth_ipa_rc_msg[] = {
++ {IPA_RC_SUCCESS, "success"},
++ {IPA_RC_NOTSUPP, "Command not supported"},
++ {IPA_RC_IP_TABLE_FULL, "Add Addr IP Table Full - ipv6"},
++ {IPA_RC_UNKNOWN_ERROR, "IPA command failed - reason unknown"},
++ {IPA_RC_UNSUPPORTED_COMMAND, "Command not supported"},
++ {IPA_RC_DUP_IPV6_REMOTE, "ipv6 address already registered remote"},
++ {IPA_RC_DUP_IPV6_HOME, "ipv6 address already registered"},
++ {IPA_RC_UNREGISTERED_ADDR, "Address not registered"},
++ {IPA_RC_NO_ID_AVAILABLE, "No identifiers available"},
++ {IPA_RC_ID_NOT_FOUND, "Identifier not found"},
++ {IPA_RC_INVALID_IP_VERSION, "IP version incorrect"},
++ {IPA_RC_LAN_FRAME_MISMATCH, "LAN and frame mismatch"},
++ {IPA_RC_L2_UNSUPPORTED_CMD, "Unsupported layer 2 command"},
++ {IPA_RC_L2_DUP_MAC, "Duplicate MAC address"},
++ {IPA_RC_L2_ADDR_TABLE_FULL, "Layer2 address table full"},
++ {IPA_RC_L2_DUP_LAYER3_MAC, "Duplicate with layer 3 MAC"},
++ {IPA_RC_L2_GMAC_NOT_FOUND, "GMAC not found"},
++ {IPA_RC_L2_MAC_NOT_FOUND, "L2 mac address not found"},
++ {IPA_RC_L2_INVALID_VLAN_ID, "L2 invalid vlan id"},
++ {IPA_RC_L2_DUP_VLAN_ID, "L2 duplicate vlan id"},
++ {IPA_RC_L2_VLAN_ID_NOT_FOUND, "L2 vlan id not found"},
++ {IPA_RC_DATA_MISMATCH, "Data field mismatch (v4/v6 mixed)"},
++ {IPA_RC_INVALID_MTU_SIZE, "Invalid MTU size"},
++ {IPA_RC_INVALID_LANTYPE, "Invalid LAN type"},
++ {IPA_RC_INVALID_LANNUM, "Invalid LAN num"},
++ {IPA_RC_DUPLICATE_IP_ADDRESS, "Address already registered"},
++ {IPA_RC_IP_ADDR_TABLE_FULL, "IP address table full"},
++ {IPA_RC_LAN_PORT_STATE_ERROR, "LAN port state error"},
++ {IPA_RC_SETIP_NO_STARTLAN, "Setip no startlan received"},
++ {IPA_RC_SETIP_ALREADY_RECEIVED, "Setip already received"},
++ {IPA_RC_IP_ADDR_ALREADY_USED, "IP address already in use on LAN"},
++ {IPA_RC_MC_ADDR_NOT_FOUND, "Multicast address not found"},
++ {IPA_RC_SETIP_INVALID_VERSION, "SETIP invalid IP version"},
++ {IPA_RC_UNSUPPORTED_SUBCMD, "Unsupported assist subcommand"},
++ {IPA_RC_ARP_ASSIST_NO_ENABLE, "Only partial success, no enable"},
++ {IPA_RC_PRIMARY_ALREADY_DEFINED, "Primary already defined"},
++ {IPA_RC_SECOND_ALREADY_DEFINED, "Secondary already defined"},
++ {IPA_RC_INVALID_SETRTG_INDICATOR, "Invalid SETRTG indicator"},
++ {IPA_RC_MC_ADDR_ALREADY_DEFINED, "Multicast address already defined"},
++ {IPA_RC_LAN_OFFLINE, "STRTLAN_LAN_DISABLED - LAN offline"},
++ {IPA_RC_INVALID_IP_VERSION2, "Invalid IP version"},
++ {IPA_RC_FFFF, "Unknown Error"}
++};
++
++
++
++char *qeth_get_ipa_msg(enum qeth_ipa_return_codes rc)
++{
++ int x = 0;
++ qeth_ipa_rc_msg[sizeof(qeth_ipa_rc_msg) /
++ sizeof(struct ipa_rc_msg) - 1].rc = rc;
++ while (qeth_ipa_rc_msg[x].rc != rc)
++ x++;
++ return qeth_ipa_rc_msg[x].msg;
++}
++
++
++struct ipa_cmd_names {
++ enum qeth_ipa_cmds cmd;
++ char *name;
++};
++
++static struct ipa_cmd_names qeth_ipa_cmd_names[] = {
++ {IPA_CMD_STARTLAN, "startlan"},
++ {IPA_CMD_STOPLAN, "stoplan"},
++ {IPA_CMD_SETVMAC, "setvmac"},
++ {IPA_CMD_DELVMAC, "delvmac"},
++ {IPA_CMD_SETGMAC, "setgmac"},
++ {IPA_CMD_DELGMAC, "delgmac"},
++ {IPA_CMD_SETVLAN, "setvlan"},
++ {IPA_CMD_DELVLAN, "delvlan"},
++ {IPA_CMD_SETCCID, "setccid"},
++ {IPA_CMD_DELCCID, "delccid"},
++ {IPA_CMD_MODCCID, "modccid"},
++ {IPA_CMD_SETIP, "setip"},
++ {IPA_CMD_QIPASSIST, "qipassist"},
++ {IPA_CMD_SETASSPARMS, "setassparms"},
++ {IPA_CMD_SETIPM, "setipm"},
++ {IPA_CMD_DELIPM, "delipm"},
++ {IPA_CMD_SETRTG, "setrtg"},
++ {IPA_CMD_DELIP, "delip"},
++ {IPA_CMD_SETADAPTERPARMS, "setadapterparms"},
++ {IPA_CMD_SET_DIAG_ASS, "set_diag_ass"},
++ {IPA_CMD_CREATE_ADDR, "create_addr"},
++ {IPA_CMD_DESTROY_ADDR, "destroy_addr"},
++ {IPA_CMD_REGISTER_LOCAL_ADDR, "register_local_addr"},
++ {IPA_CMD_UNREGISTER_LOCAL_ADDR, "unregister_local_addr"},
++ {IPA_CMD_UNKNOWN, "unknown"},
++};
++
++char *qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd)
++{
++ int x = 0;
++ qeth_ipa_cmd_names[
++ sizeof(qeth_ipa_cmd_names) /
++ sizeof(struct ipa_cmd_names)-1].cmd = cmd;
++ while (qeth_ipa_cmd_names[x].cmd != cmd)
++ x++;
++ return qeth_ipa_cmd_names[x].name;
++}
+diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h
+new file mode 100644
+index 0000000..1854882
+--- /dev/null
++++ b/drivers/s390/net/qeth_core_mpc.h
+@@ -0,0 +1,566 @@
++/*
++ * drivers/s390/net/qeth_core_mpc.h
++ *
++ * Copyright IBM Corp. 2007
++ * Author(s): Frank Pavlic <fpavlic at de.ibm.com>,
++ * Thomas Spatzier <tspat at de.ibm.com>,
++ * Frank Blaschka <frank.blaschka at de.ibm.com>
++ */
++
++#ifndef __QETH_CORE_MPC_H__
++#define __QETH_CORE_MPC_H__
++
++#include <asm/qeth.h>
++
++#define IPA_PDU_HEADER_SIZE 0x40
++#define QETH_IPA_PDU_LEN_TOTAL(buffer) (buffer + 0x0e)
++#define QETH_IPA_PDU_LEN_PDU1(buffer) (buffer + 0x26)
++#define QETH_IPA_PDU_LEN_PDU2(buffer) (buffer + 0x29)
++#define QETH_IPA_PDU_LEN_PDU3(buffer) (buffer + 0x3a)
++
++extern unsigned char IPA_PDU_HEADER[];
++#define QETH_IPA_CMD_DEST_ADDR(buffer) (buffer + 0x2c)
++
++#define IPA_CMD_LENGTH (IPA_PDU_HEADER_SIZE + sizeof(struct qeth_ipa_cmd))
++
++#define QETH_SEQ_NO_LENGTH 4
++#define QETH_MPC_TOKEN_LENGTH 4
++#define QETH_MCL_LENGTH 4
++#define OSA_ADDR_LEN 6
++
++#define QETH_TIMEOUT (10 * HZ)
++#define QETH_IPA_TIMEOUT (45 * HZ)
++#define QETH_IDX_COMMAND_SEQNO 0xffff0000
++#define SR_INFO_LEN 16
++
++#define QETH_CLEAR_CHANNEL_PARM -10
++#define QETH_HALT_CHANNEL_PARM -11
++#define QETH_RCD_PARM -12
++
++/*****************************************************************************/
++/* IP Assist related definitions */
++/*****************************************************************************/
++#define IPA_CMD_INITIATOR_HOST 0x00
++#define IPA_CMD_INITIATOR_OSA 0x01
++#define IPA_CMD_INITIATOR_HOST_REPLY 0x80
++#define IPA_CMD_INITIATOR_OSA_REPLY 0x81
++#define IPA_CMD_PRIM_VERSION_NO 0x01
++
++enum qeth_card_types {
++ QETH_CARD_TYPE_UNKNOWN = 0,
++ QETH_CARD_TYPE_OSAE = 10,
++ QETH_CARD_TYPE_IQD = 1234,
++ QETH_CARD_TYPE_OSN = 11,
++};
++
++#define QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE 0x18
++/* only the first two bytes are looked at in qeth_get_cardname_short */
++enum qeth_link_types {
++ QETH_LINK_TYPE_FAST_ETH = 0x01,
++ QETH_LINK_TYPE_HSTR = 0x02,
++ QETH_LINK_TYPE_GBIT_ETH = 0x03,
++ QETH_LINK_TYPE_OSN = 0x04,
++ QETH_LINK_TYPE_10GBIT_ETH = 0x10,
++ QETH_LINK_TYPE_LANE_ETH100 = 0x81,
++ QETH_LINK_TYPE_LANE_TR = 0x82,
++ QETH_LINK_TYPE_LANE_ETH1000 = 0x83,
++ QETH_LINK_TYPE_LANE = 0x88,
++ QETH_LINK_TYPE_ATM_NATIVE = 0x90,
++};
++
++enum qeth_tr_macaddr_modes {
++ QETH_TR_MACADDR_NONCANONICAL = 0,
++ QETH_TR_MACADDR_CANONICAL = 1,
++};
++
++enum qeth_tr_broadcast_modes {
++ QETH_TR_BROADCAST_ALLRINGS = 0,
++ QETH_TR_BROADCAST_LOCAL = 1,
++};
++
++/* these values match CHECKSUM_* in include/linux/skbuff.h */
++enum qeth_checksum_types {
++ SW_CHECKSUMMING = 0, /* TODO: set to bit flag used in IPA Command */
++ HW_CHECKSUMMING = 1,
++ NO_CHECKSUMMING = 2,
++};
++#define QETH_CHECKSUM_DEFAULT SW_CHECKSUMMING
++
++/*
++ * Routing stuff
++ */
++#define RESET_ROUTING_FLAG 0x10 /* indicate that routing type shall be set */
++enum qeth_routing_types {
++ /* TODO: set to bit flag used in IPA Command */
++ NO_ROUTER = 0,
++ PRIMARY_ROUTER = 1,
++ SECONDARY_ROUTER = 2,
++ MULTICAST_ROUTER = 3,
++ PRIMARY_CONNECTOR = 4,
++ SECONDARY_CONNECTOR = 5,
++};
++
++/* IPA Commands */
++enum qeth_ipa_cmds {
++ IPA_CMD_STARTLAN = 0x01,
++ IPA_CMD_STOPLAN = 0x02,
++ IPA_CMD_SETVMAC = 0x21,
++ IPA_CMD_DELVMAC = 0x22,
++ IPA_CMD_SETGMAC = 0x23,
++ IPA_CMD_DELGMAC = 0x24,
++ IPA_CMD_SETVLAN = 0x25,
++ IPA_CMD_DELVLAN = 0x26,
++ IPA_CMD_SETCCID = 0x41,
++ IPA_CMD_DELCCID = 0x42,
++ IPA_CMD_MODCCID = 0x43,
++ IPA_CMD_SETIP = 0xb1,
++ IPA_CMD_QIPASSIST = 0xb2,
++ IPA_CMD_SETASSPARMS = 0xb3,
++ IPA_CMD_SETIPM = 0xb4,
++ IPA_CMD_DELIPM = 0xb5,
++ IPA_CMD_SETRTG = 0xb6,
++ IPA_CMD_DELIP = 0xb7,
++ IPA_CMD_SETADAPTERPARMS = 0xb8,
++ IPA_CMD_SET_DIAG_ASS = 0xb9,
++ IPA_CMD_CREATE_ADDR = 0xc3,
++ IPA_CMD_DESTROY_ADDR = 0xc4,
++ IPA_CMD_REGISTER_LOCAL_ADDR = 0xd1,
++ IPA_CMD_UNREGISTER_LOCAL_ADDR = 0xd2,
++ IPA_CMD_UNKNOWN = 0x00
++};
++
++enum qeth_ip_ass_cmds {
++ IPA_CMD_ASS_START = 0x0001,
++ IPA_CMD_ASS_STOP = 0x0002,
++ IPA_CMD_ASS_CONFIGURE = 0x0003,
++ IPA_CMD_ASS_ENABLE = 0x0004,
++};
++
++enum qeth_arp_process_subcmds {
++ IPA_CMD_ASS_ARP_SET_NO_ENTRIES = 0x0003,
++ IPA_CMD_ASS_ARP_QUERY_CACHE = 0x0004,
++ IPA_CMD_ASS_ARP_ADD_ENTRY = 0x0005,
++ IPA_CMD_ASS_ARP_REMOVE_ENTRY = 0x0006,
++ IPA_CMD_ASS_ARP_FLUSH_CACHE = 0x0007,
++ IPA_CMD_ASS_ARP_QUERY_INFO = 0x0104,
++ IPA_CMD_ASS_ARP_QUERY_STATS = 0x0204,
++};
++
++
++/* Return Codes for IPA Commands
++ * according to OSA card Specs */
++
++enum qeth_ipa_return_codes {
++ IPA_RC_SUCCESS = 0x0000,
++ IPA_RC_NOTSUPP = 0x0001,
++ IPA_RC_IP_TABLE_FULL = 0x0002,
++ IPA_RC_UNKNOWN_ERROR = 0x0003,
++ IPA_RC_UNSUPPORTED_COMMAND = 0x0004,
++ IPA_RC_DUP_IPV6_REMOTE = 0x0008,
++ IPA_RC_DUP_IPV6_HOME = 0x0010,
++ IPA_RC_UNREGISTERED_ADDR = 0x0011,
++ IPA_RC_NO_ID_AVAILABLE = 0x0012,
++ IPA_RC_ID_NOT_FOUND = 0x0013,
++ IPA_RC_INVALID_IP_VERSION = 0x0020,
++ IPA_RC_LAN_FRAME_MISMATCH = 0x0040,
++ IPA_RC_L2_UNSUPPORTED_CMD = 0x2003,
++ IPA_RC_L2_DUP_MAC = 0x2005,
++ IPA_RC_L2_ADDR_TABLE_FULL = 0x2006,
++ IPA_RC_L2_DUP_LAYER3_MAC = 0x200a,
++ IPA_RC_L2_GMAC_NOT_FOUND = 0x200b,
++ IPA_RC_L2_MAC_NOT_FOUND = 0x2010,
++ IPA_RC_L2_INVALID_VLAN_ID = 0x2015,
++ IPA_RC_L2_DUP_VLAN_ID = 0x2016,
++ IPA_RC_L2_VLAN_ID_NOT_FOUND = 0x2017,
++ IPA_RC_DATA_MISMATCH = 0xe001,
++ IPA_RC_INVALID_MTU_SIZE = 0xe002,
++ IPA_RC_INVALID_LANTYPE = 0xe003,
++ IPA_RC_INVALID_LANNUM = 0xe004,
++ IPA_RC_DUPLICATE_IP_ADDRESS = 0xe005,
++ IPA_RC_IP_ADDR_TABLE_FULL = 0xe006,
++ IPA_RC_LAN_PORT_STATE_ERROR = 0xe007,
++ IPA_RC_SETIP_NO_STARTLAN = 0xe008,
++ IPA_RC_SETIP_ALREADY_RECEIVED = 0xe009,
++ IPA_RC_IP_ADDR_ALREADY_USED = 0xe00a,
++ IPA_RC_MC_ADDR_NOT_FOUND = 0xe00b,
++ IPA_RC_SETIP_INVALID_VERSION = 0xe00d,
++ IPA_RC_UNSUPPORTED_SUBCMD = 0xe00e,
++ IPA_RC_ARP_ASSIST_NO_ENABLE = 0xe00f,
++ IPA_RC_PRIMARY_ALREADY_DEFINED = 0xe010,
++ IPA_RC_SECOND_ALREADY_DEFINED = 0xe011,
++ IPA_RC_INVALID_SETRTG_INDICATOR = 0xe012,
++ IPA_RC_MC_ADDR_ALREADY_DEFINED = 0xe013,
++ IPA_RC_LAN_OFFLINE = 0xe080,
++ IPA_RC_INVALID_IP_VERSION2 = 0xf001,
++ IPA_RC_FFFF = 0xffff
++};
++
++/* IPA function flags; each flag marks availability of respective function */
++enum qeth_ipa_funcs {
++ IPA_ARP_PROCESSING = 0x00000001L,
++ IPA_INBOUND_CHECKSUM = 0x00000002L,
++ IPA_OUTBOUND_CHECKSUM = 0x00000004L,
++ IPA_IP_FRAGMENTATION = 0x00000008L,
++ IPA_FILTERING = 0x00000010L,
++ IPA_IPV6 = 0x00000020L,
++ IPA_MULTICASTING = 0x00000040L,
++ IPA_IP_REASSEMBLY = 0x00000080L,
++ IPA_QUERY_ARP_COUNTERS = 0x00000100L,
++ IPA_QUERY_ARP_ADDR_INFO = 0x00000200L,
++ IPA_SETADAPTERPARMS = 0x00000400L,
++ IPA_VLAN_PRIO = 0x00000800L,
++ IPA_PASSTHRU = 0x00001000L,
++ IPA_FLUSH_ARP_SUPPORT = 0x00002000L,
++ IPA_FULL_VLAN = 0x00004000L,
++ IPA_INBOUND_PASSTHRU = 0x00008000L,
++ IPA_SOURCE_MAC = 0x00010000L,
++ IPA_OSA_MC_ROUTER = 0x00020000L,
++ IPA_QUERY_ARP_ASSIST = 0x00040000L,
++ IPA_INBOUND_TSO = 0x00080000L,
++ IPA_OUTBOUND_TSO = 0x00100000L,
++};
++
++/* SETIP/DELIP IPA Command: ***************************************************/
++enum qeth_ipa_setdelip_flags {
++ QETH_IPA_SETDELIP_DEFAULT = 0x00L, /* default */
++ QETH_IPA_SETIP_VIPA_FLAG = 0x01L, /* no grat. ARP */
++ QETH_IPA_SETIP_TAKEOVER_FLAG = 0x02L, /* nofail on grat. ARP */
++ QETH_IPA_DELIP_ADDR_2_B_TAKEN_OVER = 0x20L,
++ QETH_IPA_DELIP_VIPA_FLAG = 0x40L,
++ QETH_IPA_DELIP_ADDR_NEEDS_SETIP = 0x80L,
++};
++
++/* SETADAPTER IPA Command: ****************************************************/
++enum qeth_ipa_setadp_cmd {
++ IPA_SETADP_QUERY_COMMANDS_SUPPORTED = 0x0001,
++ IPA_SETADP_ALTER_MAC_ADDRESS = 0x0002,
++ IPA_SETADP_ADD_DELETE_GROUP_ADDRESS = 0x0004,
++ IPA_SETADP_ADD_DELETE_FUNCTIONAL_ADDR = 0x0008,
++ IPA_SETADP_SET_ADDRESSING_MODE = 0x0010,
++ IPA_SETADP_SET_CONFIG_PARMS = 0x0020,
++ IPA_SETADP_SET_CONFIG_PARMS_EXTENDED = 0x0040,
++ IPA_SETADP_SET_BROADCAST_MODE = 0x0080,
++ IPA_SETADP_SEND_OSA_MESSAGE = 0x0100,
++ IPA_SETADP_SET_SNMP_CONTROL = 0x0200,
++ IPA_SETADP_QUERY_CARD_INFO = 0x0400,
++ IPA_SETADP_SET_PROMISC_MODE = 0x0800,
++};
++enum qeth_ipa_mac_ops {
++ CHANGE_ADDR_READ_MAC = 0,
++ CHANGE_ADDR_REPLACE_MAC = 1,
++ CHANGE_ADDR_ADD_MAC = 2,
++ CHANGE_ADDR_DEL_MAC = 4,
++ CHANGE_ADDR_RESET_MAC = 8,
++};
++enum qeth_ipa_addr_ops {
++ CHANGE_ADDR_READ_ADDR = 0,
++ CHANGE_ADDR_ADD_ADDR = 1,
++ CHANGE_ADDR_DEL_ADDR = 2,
++ CHANGE_ADDR_FLUSH_ADDR_TABLE = 4,
++};
++enum qeth_ipa_promisc_modes {
++ SET_PROMISC_MODE_OFF = 0,
++ SET_PROMISC_MODE_ON = 1,
++};
++
++/* (SET)DELIP(M) IPA stuff ***************************************************/
++struct qeth_ipacmd_setdelip4 {
++ __u8 ip_addr[4];
++ __u8 mask[4];
++ __u32 flags;
++} __attribute__ ((packed));
++
++struct qeth_ipacmd_setdelip6 {
++ __u8 ip_addr[16];
++ __u8 mask[16];
++ __u32 flags;
++} __attribute__ ((packed));
++
++struct qeth_ipacmd_setdelipm {
++ __u8 mac[6];
++ __u8 padding[2];
++ __u8 ip6[12];
++ __u8 ip4[4];
++} __attribute__ ((packed));
++
++struct qeth_ipacmd_layer2setdelmac {
++ __u32 mac_length;
++ __u8 mac[6];
++} __attribute__ ((packed));
++
++struct qeth_ipacmd_layer2setdelvlan {
++ __u16 vlan_id;
++} __attribute__ ((packed));
++
++
++struct qeth_ipacmd_setassparms_hdr {
++ __u32 assist_no;
++ __u16 length;
++ __u16 command_code;
++ __u16 return_code;
++ __u8 number_of_replies;
++ __u8 seq_no;
++} __attribute__((packed));
++
++struct qeth_arp_query_data {
++ __u16 request_bits;
++ __u16 reply_bits;
++ __u32 no_entries;
++ char data;
++} __attribute__((packed));
++
++/* used as parameter for arp_query reply */
++struct qeth_arp_query_info {
++ __u32 udata_len;
++ __u16 mask_bits;
++ __u32 udata_offset;
++ __u32 no_entries;
++ char *udata;
++};
++
++/* SETASSPARMS IPA Command: */
++struct qeth_ipacmd_setassparms {
++ struct qeth_ipacmd_setassparms_hdr hdr;
++ union {
++ __u32 flags_32bit;
++ struct qeth_arp_cache_entry add_arp_entry;
++ struct qeth_arp_query_data query_arp;
++ __u8 ip[16];
++ } data;
++} __attribute__ ((packed));
++
++
++/* SETRTG IPA Command: ****************************************************/
++struct qeth_set_routing {
++ __u8 type;
++};
++
++/* SETADAPTERPARMS IPA Command: *******************************************/
++struct qeth_query_cmds_supp {
++ __u32 no_lantypes_supp;
++ __u8 lan_type;
++ __u8 reserved1[3];
++ __u32 supported_cmds;
++ __u8 reserved2[8];
++} __attribute__ ((packed));
++
++struct qeth_change_addr {
++ __u32 cmd;
++ __u32 addr_size;
++ __u32 no_macs;
++ __u8 addr[OSA_ADDR_LEN];
++} __attribute__ ((packed));
++
++
++struct qeth_snmp_cmd {
++ __u8 token[16];
++ __u32 request;
++ __u32 interface;
++ __u32 returncode;
++ __u32 firmwarelevel;
++ __u32 seqno;
++ __u8 data;
++} __attribute__ ((packed));
++
++struct qeth_snmp_ureq_hdr {
++ __u32 data_len;
++ __u32 req_len;
++ __u32 reserved1;
++ __u32 reserved2;
++} __attribute__ ((packed));
++
++struct qeth_snmp_ureq {
++ struct qeth_snmp_ureq_hdr hdr;
++ struct qeth_snmp_cmd cmd;
++} __attribute__((packed));
++
++struct qeth_ipacmd_setadpparms_hdr {
++ __u32 supp_hw_cmds;
++ __u32 reserved1;
++ __u16 cmdlength;
++ __u16 reserved2;
++ __u32 command_code;
++ __u16 return_code;
++ __u8 used_total;
++ __u8 seq_no;
++ __u32 reserved3;
++} __attribute__ ((packed));
++
++struct qeth_ipacmd_setadpparms {
++ struct qeth_ipacmd_setadpparms_hdr hdr;
++ union {
++ struct qeth_query_cmds_supp query_cmds_supp;
++ struct qeth_change_addr change_addr;
++ struct qeth_snmp_cmd snmp;
++ __u32 mode;
++ } data;
++} __attribute__ ((packed));
++
++/* CREATE_ADDR IPA Command: ***********************************************/
++struct qeth_create_destroy_address {
++ __u8 unique_id[8];
++} __attribute__ ((packed));
++
++/* Header for each IPA command */
++struct qeth_ipacmd_hdr {
++ __u8 command;
++ __u8 initiator;
++ __u16 seqno;
++ __u16 return_code;
++ __u8 adapter_type;
++ __u8 rel_adapter_no;
++ __u8 prim_version_no;
++ __u8 param_count;
++ __u16 prot_version;
++ __u32 ipa_supported;
++ __u32 ipa_enabled;
++} __attribute__ ((packed));
++
++/* The IPA command itself */
++struct qeth_ipa_cmd {
++ struct qeth_ipacmd_hdr hdr;
++ union {
++ struct qeth_ipacmd_setdelip4 setdelip4;
++ struct qeth_ipacmd_setdelip6 setdelip6;
++ struct qeth_ipacmd_setdelipm setdelipm;
++ struct qeth_ipacmd_setassparms setassparms;
++ struct qeth_ipacmd_layer2setdelmac setdelmac;
++ struct qeth_ipacmd_layer2setdelvlan setdelvlan;
++ struct qeth_create_destroy_address create_destroy_addr;
++ struct qeth_ipacmd_setadpparms setadapterparms;
++ struct qeth_set_routing setrtg;
++ } data;
++} __attribute__ ((packed));
++
++/*
++ * special command for ARP processing.
++ * this is not included in setassparms command before, because we get
++ * problem with the size of struct qeth_ipacmd_setassparms otherwise
++ */
++enum qeth_ipa_arp_return_codes {
++ QETH_IPA_ARP_RC_SUCCESS = 0x0000,
++ QETH_IPA_ARP_RC_FAILED = 0x0001,
++ QETH_IPA_ARP_RC_NOTSUPP = 0x0002,
++ QETH_IPA_ARP_RC_OUT_OF_RANGE = 0x0003,
++ QETH_IPA_ARP_RC_Q_NOTSUPP = 0x0004,
++ QETH_IPA_ARP_RC_Q_NO_DATA = 0x0008,
++};
++
++
++extern char *qeth_get_ipa_msg(enum qeth_ipa_return_codes rc);
++extern char *qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd);
++
++#define QETH_SETASS_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \
++ sizeof(struct qeth_ipacmd_setassparms_hdr))
++#define QETH_IPA_ARP_DATA_POS(buffer) (buffer + IPA_PDU_HEADER_SIZE + \
++ QETH_SETASS_BASE_LEN)
++#define QETH_SETADP_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \
++ sizeof(struct qeth_ipacmd_setadpparms_hdr))
++#define QETH_SNMP_SETADP_CMDLENGTH 16
++
++#define QETH_ARP_DATA_SIZE 3968
++#define QETH_ARP_CMD_LEN (QETH_ARP_DATA_SIZE + 8)
++/* Helper functions */
++#define IS_IPA_REPLY(cmd) ((cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST) || \
++ (cmd->hdr.initiator == IPA_CMD_INITIATOR_OSA_REPLY))
++
++/*****************************************************************************/
++/* END OF IP Assist related definitions */
++/*****************************************************************************/
++
++
++extern unsigned char WRITE_CCW[];
++extern unsigned char READ_CCW[];
++
++extern unsigned char CM_ENABLE[];
++#define CM_ENABLE_SIZE 0x63
++#define QETH_CM_ENABLE_ISSUER_RM_TOKEN(buffer) (buffer + 0x2c)
++#define QETH_CM_ENABLE_FILTER_TOKEN(buffer) (buffer + 0x53)
++#define QETH_CM_ENABLE_USER_DATA(buffer) (buffer + 0x5b)
++
++#define QETH_CM_ENABLE_RESP_FILTER_TOKEN(buffer) \
++ (PDU_ENCAPSULATION(buffer) + 0x13)
++
++
++extern unsigned char CM_SETUP[];
++#define CM_SETUP_SIZE 0x64
++#define QETH_CM_SETUP_DEST_ADDR(buffer) (buffer + 0x2c)
++#define QETH_CM_SETUP_CONNECTION_TOKEN(buffer) (buffer + 0x51)
++#define QETH_CM_SETUP_FILTER_TOKEN(buffer) (buffer + 0x5a)
++
++#define QETH_CM_SETUP_RESP_DEST_ADDR(buffer) \
++ (PDU_ENCAPSULATION(buffer) + 0x1a)
++
++extern unsigned char ULP_ENABLE[];
++#define ULP_ENABLE_SIZE 0x6b
++#define QETH_ULP_ENABLE_LINKNUM(buffer) (buffer + 0x61)
++#define QETH_ULP_ENABLE_DEST_ADDR(buffer) (buffer + 0x2c)
++#define QETH_ULP_ENABLE_FILTER_TOKEN(buffer) (buffer + 0x53)
++#define QETH_ULP_ENABLE_PORTNAME_AND_LL(buffer) (buffer + 0x62)
++#define QETH_ULP_ENABLE_RESP_FILTER_TOKEN(buffer) \
++ (PDU_ENCAPSULATION(buffer) + 0x13)
++#define QETH_ULP_ENABLE_RESP_MAX_MTU(buffer) \
++ (PDU_ENCAPSULATION(buffer) + 0x1f)
++#define QETH_ULP_ENABLE_RESP_DIFINFO_LEN(buffer) \
++ (PDU_ENCAPSULATION(buffer) + 0x17)
++#define QETH_ULP_ENABLE_RESP_LINK_TYPE(buffer) \
++ (PDU_ENCAPSULATION(buffer) + 0x2b)
++/* Layer 2 defintions */
++#define QETH_PROT_LAYER2 0x08
++#define QETH_PROT_TCPIP 0x03
++#define QETH_PROT_OSN2 0x0a
++#define QETH_ULP_ENABLE_PROT_TYPE(buffer) (buffer + 0x50)
++#define QETH_IPA_CMD_PROT_TYPE(buffer) (buffer + 0x19)
++
++extern unsigned char ULP_SETUP[];
++#define ULP_SETUP_SIZE 0x6c
++#define QETH_ULP_SETUP_DEST_ADDR(buffer) (buffer + 0x2c)
++#define QETH_ULP_SETUP_CONNECTION_TOKEN(buffer) (buffer + 0x51)
++#define QETH_ULP_SETUP_FILTER_TOKEN(buffer) (buffer + 0x5a)
++#define QETH_ULP_SETUP_CUA(buffer) (buffer + 0x68)
++#define QETH_ULP_SETUP_REAL_DEVADDR(buffer) (buffer + 0x6a)
++
++#define QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(buffer) \
++ (PDU_ENCAPSULATION(buffer) + 0x1a)
++
++
++extern unsigned char DM_ACT[];
++#define DM_ACT_SIZE 0x55
++#define QETH_DM_ACT_DEST_ADDR(buffer) (buffer + 0x2c)
++#define QETH_DM_ACT_CONNECTION_TOKEN(buffer) (buffer + 0x51)
++
++
++
++#define QETH_TRANSPORT_HEADER_SEQ_NO(buffer) (buffer + 4)
++#define QETH_PDU_HEADER_SEQ_NO(buffer) (buffer + 0x1c)
++#define QETH_PDU_HEADER_ACK_SEQ_NO(buffer) (buffer + 0x20)
++
++extern unsigned char IDX_ACTIVATE_READ[];
++extern unsigned char IDX_ACTIVATE_WRITE[];
++
++#define IDX_ACTIVATE_SIZE 0x22
++#define QETH_IDX_ACT_PNO(buffer) (buffer+0x0b)
++#define QETH_IDX_ACT_ISSUER_RM_TOKEN(buffer) (buffer + 0x0c)
++#define QETH_IDX_NO_PORTNAME_REQUIRED(buffer) ((buffer)[0x0b] & 0x80)
++#define QETH_IDX_ACT_FUNC_LEVEL(buffer) (buffer + 0x10)
++#define QETH_IDX_ACT_DATASET_NAME(buffer) (buffer + 0x16)
++#define QETH_IDX_ACT_QDIO_DEV_CUA(buffer) (buffer + 0x1e)
++#define QETH_IDX_ACT_QDIO_DEV_REALADDR(buffer) (buffer + 0x20)
++#define QETH_IS_IDX_ACT_POS_REPLY(buffer) (((buffer)[0x08] & 3) == 2)
++#define QETH_IDX_REPLY_LEVEL(buffer) (buffer + 0x12)
++#define QETH_IDX_ACT_CAUSE_CODE(buffer) (buffer)[0x09]
++
++#define PDU_ENCAPSULATION(buffer) \
++ (buffer + *(buffer + (*(buffer + 0x0b)) + \
++ *(buffer + *(buffer + 0x0b) + 0x11) + 0x07))
++
++#define IS_IPA(buffer) \
++ ((buffer) && \
++ (*(buffer + ((*(buffer + 0x0b)) + 4)) == 0xc1))
++
++#define ADDR_FRAME_TYPE_DIX 1
++#define ADDR_FRAME_TYPE_802_3 2
++#define ADDR_FRAME_TYPE_TR_WITHOUT_SR 0x10
++#define ADDR_FRAME_TYPE_TR_WITH_SR 0x20
++
++#endif
+diff --git a/drivers/s390/net/qeth_core_offl.c b/drivers/s390/net/qeth_core_offl.c
+new file mode 100644
+index 0000000..822df83
+--- /dev/null
++++ b/drivers/s390/net/qeth_core_offl.c
+@@ -0,0 +1,701 @@
++/*
++ * drivers/s390/net/qeth_core_offl.c
++ *
++ * Copyright IBM Corp. 2007
++ * Author(s): Thomas Spatzier <tspat at de.ibm.com>,
++ * Frank Blaschka <frank.blaschka at de.ibm.com>
++ */
++
++#include <linux/errno.h>
++#include <linux/ip.h>
++#include <linux/inetdevice.h>
++#include <linux/netdevice.h>
++#include <linux/kernel.h>
++#include <linux/tcp.h>
++#include <net/tcp.h>
++#include <linux/skbuff.h>
++
++#include <net/ip.h>
++#include <net/ip6_checksum.h>
++
++#include "qeth_core.h"
++#include "qeth_core_mpc.h"
++#include "qeth_core_offl.h"
++
++int qeth_eddp_check_buffers_for_context(struct qeth_qdio_out_q *queue,
++ struct qeth_eddp_context *ctx)
++{
++ int index = queue->next_buf_to_fill;
++ int elements_needed = ctx->num_elements;
++ int elements_in_buffer;
++ int skbs_in_buffer;
++ int buffers_needed = 0;
++
++ QETH_DBF_TEXT(TRACE, 5, "eddpcbfc");
++ while (elements_needed > 0) {
++ buffers_needed++;
++ if (atomic_read(&queue->bufs[index].state) !=
++ QETH_QDIO_BUF_EMPTY)
++ return -EBUSY;
++
++ elements_in_buffer = QETH_MAX_BUFFER_ELEMENTS(queue->card) -
++ queue->bufs[index].next_element_to_fill;
++ skbs_in_buffer = elements_in_buffer / ctx->elements_per_skb;
++ elements_needed -= skbs_in_buffer * ctx->elements_per_skb;
++ index = (index + 1) % QDIO_MAX_BUFFERS_PER_Q;
++ }
++ return buffers_needed;
++}
++
++static void qeth_eddp_free_context(struct qeth_eddp_context *ctx)
++{
++ int i;
++
++ QETH_DBF_TEXT(TRACE, 5, "eddpfctx");
++ for (i = 0; i < ctx->num_pages; ++i)
++ free_page((unsigned long)ctx->pages[i]);
++ kfree(ctx->pages);
++ kfree(ctx->elements);
++ kfree(ctx);
++}
++
++
++static void qeth_eddp_get_context(struct qeth_eddp_context *ctx)
++{
++ atomic_inc(&ctx->refcnt);
++}
++
++void qeth_eddp_put_context(struct qeth_eddp_context *ctx)
++{
++ if (atomic_dec_return(&ctx->refcnt) == 0)
++ qeth_eddp_free_context(ctx);
++}
++EXPORT_SYMBOL_GPL(qeth_eddp_put_context);
++
++void qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *buf)
++{
++ struct qeth_eddp_context_reference *ref;
++
++ QETH_DBF_TEXT(TRACE, 6, "eddprctx");
++ while (!list_empty(&buf->ctx_list)) {
++ ref = list_entry(buf->ctx_list.next,
++ struct qeth_eddp_context_reference, list);
++ qeth_eddp_put_context(ref->ctx);
++ list_del(&ref->list);
++ kfree(ref);
++ }
++}
++
++static int qeth_eddp_buf_ref_context(struct qeth_qdio_out_buffer *buf,
++ struct qeth_eddp_context *ctx)
++{
++ struct qeth_eddp_context_reference *ref;
++
++ QETH_DBF_TEXT(TRACE, 6, "eddprfcx");
++ ref = kmalloc(sizeof(struct qeth_eddp_context_reference), GFP_ATOMIC);
++ if (ref == NULL)
++ return -ENOMEM;
++ qeth_eddp_get_context(ctx);
++ ref->ctx = ctx;
++ list_add_tail(&ref->list, &buf->ctx_list);
++ return 0;
++}
++
++int qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue,
++ struct qeth_eddp_context *ctx, int index)
++{
++ struct qeth_qdio_out_buffer *buf = NULL;
++ struct qdio_buffer *buffer;
++ int elements = ctx->num_elements;
++ int element = 0;
++ int flush_cnt = 0;
++ int must_refcnt = 1;
++ int i;
++
++ QETH_DBF_TEXT(TRACE, 5, "eddpfibu");
++ while (elements > 0) {
++ buf = &queue->bufs[index];
++ if (atomic_read(&buf->state) != QETH_QDIO_BUF_EMPTY) {
++ /* normally this should not happen since we checked for
++ * available elements in qeth_check_elements_for_context
++ */
++ if (element == 0)
++ return -EBUSY;
++ else {
++ PRINT_WARN("could only partially fill eddp "
++ "buffer!\n");
++ goto out;
++ }
++ }
++ /* check if the whole next skb fits into current buffer */
++ if ((QETH_MAX_BUFFER_ELEMENTS(queue->card) -
++ buf->next_element_to_fill)
++ < ctx->elements_per_skb){
++ /* no -> go to next buffer */
++ atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
++ index = (index + 1) % QDIO_MAX_BUFFERS_PER_Q;
++ flush_cnt++;
++ /* new buffer, so we have to add ctx to buffer'ctx_list
++ * and increment ctx's refcnt */
++ must_refcnt = 1;
++ continue;
++ }
++ if (must_refcnt) {
++ must_refcnt = 0;
++ if (qeth_eddp_buf_ref_context(buf, ctx)) {
++ PRINT_WARN("no memory to create eddp context "
++ "reference\n");
++ goto out_check;
++ }
++ }
++ buffer = buf->buffer;
++ /* fill one skb into buffer */
++ for (i = 0; i < ctx->elements_per_skb; ++i) {
++ if (ctx->elements[element].length != 0) {
++ buffer->element[buf->next_element_to_fill].
++ addr = ctx->elements[element].addr;
++ buffer->element[buf->next_element_to_fill].
++ length = ctx->elements[element].length;
++ buffer->element[buf->next_element_to_fill].
++ flags = ctx->elements[element].flags;
++ buf->next_element_to_fill++;
++ }
++ element++;
++ elements--;
++ }
++ }
++out_check:
++ if (!queue->do_pack) {
++ QETH_DBF_TEXT(TRACE, 6, "fillbfnp");
++ /* set state to PRIMED -> will be flushed */
++ if (buf->next_element_to_fill > 0) {
++ atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
++ flush_cnt++;
++ }
++ } else {
++ if (queue->card->options.performance_stats)
++ queue->card->perf_stats.skbs_sent_pack++;
++ QETH_DBF_TEXT(TRACE, 6, "fillbfpa");
++ if (buf->next_element_to_fill >=
++ QETH_MAX_BUFFER_ELEMENTS(queue->card)) {
++ /*
++ * packed buffer if full -> set state PRIMED
++ * -> will be flushed
++ */
++ atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
++ flush_cnt++;
++ }
++ }
++out:
++ return flush_cnt;
++}
++
++static void qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx,
++ struct qeth_eddp_data *eddp, int data_len)
++{
++ u8 *page;
++ int page_remainder;
++ int page_offset;
++ int pkt_len;
++ struct qeth_eddp_element *element;
++
++ QETH_DBF_TEXT(TRACE, 5, "eddpcrsh");
++ page = ctx->pages[ctx->offset >> PAGE_SHIFT];
++ page_offset = ctx->offset % PAGE_SIZE;
++ element = &ctx->elements[ctx->num_elements];
++ pkt_len = eddp->nhl + eddp->thl + data_len;
++ /* FIXME: layer2 and VLAN !!! */
++ if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
++ pkt_len += ETH_HLEN;
++ if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
++ pkt_len += VLAN_HLEN;
++ /* does complete packet fit in current page ? */
++ page_remainder = PAGE_SIZE - page_offset;
++ if (page_remainder < (sizeof(struct qeth_hdr) + pkt_len)) {
++ /* no -> go to start of next page */
++ ctx->offset += page_remainder;
++ page = ctx->pages[ctx->offset >> PAGE_SHIFT];
++ page_offset = 0;
++ }
++ memcpy(page + page_offset, &eddp->qh, sizeof(struct qeth_hdr));
++ element->addr = page + page_offset;
++ element->length = sizeof(struct qeth_hdr);
++ ctx->offset += sizeof(struct qeth_hdr);
++ page_offset += sizeof(struct qeth_hdr);
++ /* add mac header (?) */
++ if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
++ memcpy(page + page_offset, &eddp->mac, ETH_HLEN);
++ element->length += ETH_HLEN;
++ ctx->offset += ETH_HLEN;
++ page_offset += ETH_HLEN;
++ }
++ /* add VLAN tag */
++ if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) {
++ memcpy(page + page_offset, &eddp->vlan, VLAN_HLEN);
++ element->length += VLAN_HLEN;
++ ctx->offset += VLAN_HLEN;
++ page_offset += VLAN_HLEN;
++ }
++ /* add network header */
++ memcpy(page + page_offset, (u8 *)&eddp->nh, eddp->nhl);
++ element->length += eddp->nhl;
++ eddp->nh_in_ctx = page + page_offset;
++ ctx->offset += eddp->nhl;
++ page_offset += eddp->nhl;
++ /* add transport header */
++ memcpy(page + page_offset, (u8 *)&eddp->th, eddp->thl);
++ element->length += eddp->thl;
++ eddp->th_in_ctx = page + page_offset;
++ ctx->offset += eddp->thl;
++}
++
++static void qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp,
++ int len, __wsum *hcsum)
++{
++ struct skb_frag_struct *frag;
++ int left_in_frag;
++ int copy_len;
++ u8 *src;
++
++ QETH_DBF_TEXT(TRACE, 5, "eddpcdtc");
++ if (skb_shinfo(eddp->skb)->nr_frags == 0) {
++ skb_copy_from_linear_data_offset(eddp->skb, eddp->skb_offset,
++ dst, len);
++ *hcsum = csum_partial(eddp->skb->data + eddp->skb_offset, len,
++ *hcsum);
++ eddp->skb_offset += len;
++ } else {
++ while (len > 0) {
++ if (eddp->frag < 0) {
++ /* we're in skb->data */
++ left_in_frag = (eddp->skb->len -
++ eddp->skb->data_len)
++ - eddp->skb_offset;
++ src = eddp->skb->data + eddp->skb_offset;
++ } else {
++ frag = &skb_shinfo(eddp->skb)->frags[
++ eddp->frag];
++ left_in_frag = frag->size - eddp->frag_offset;
++ src = (u8 *)((page_to_pfn(frag->page) <<
++ PAGE_SHIFT) + frag->page_offset +
++ eddp->frag_offset);
++ }
++ if (left_in_frag <= 0) {
++ eddp->frag++;
++ eddp->frag_offset = 0;
++ continue;
++ }
++ copy_len = min(left_in_frag, len);
++ memcpy(dst, src, copy_len);
++ *hcsum = csum_partial(src, copy_len, *hcsum);
++ dst += copy_len;
++ eddp->frag_offset += copy_len;
++ eddp->skb_offset += copy_len;
++ len -= copy_len;
++ }
++ }
++}
++
++static void qeth_eddp_create_segment_data_tcp(struct qeth_eddp_context *ctx,
++ struct qeth_eddp_data *eddp, int data_len, __wsum hcsum)
++{
++ u8 *page;
++ int page_remainder;
++ int page_offset;
++ struct qeth_eddp_element *element;
++ int first_lap = 1;
++
++ QETH_DBF_TEXT(TRACE, 5, "eddpcsdt");
++ page = ctx->pages[ctx->offset >> PAGE_SHIFT];
++ page_offset = ctx->offset % PAGE_SIZE;
++ element = &ctx->elements[ctx->num_elements];
++ while (data_len) {
++ page_remainder = PAGE_SIZE - page_offset;
++ if (page_remainder < data_len) {
++ qeth_eddp_copy_data_tcp(page + page_offset, eddp,
++ page_remainder, &hcsum);
++ element->length += page_remainder;
++ if (first_lap)
++ element->flags = SBAL_FLAGS_FIRST_FRAG;
++ else
++ element->flags = SBAL_FLAGS_MIDDLE_FRAG;
++ ctx->num_elements++;
++ element++;
++ data_len -= page_remainder;
++ ctx->offset += page_remainder;
++ page = ctx->pages[ctx->offset >> PAGE_SHIFT];
++ page_offset = 0;
++ element->addr = page + page_offset;
++ } else {
++ qeth_eddp_copy_data_tcp(page + page_offset, eddp,
++ data_len, &hcsum);
++ element->length += data_len;
++ if (!first_lap)
++ element->flags = SBAL_FLAGS_LAST_FRAG;
++ ctx->num_elements++;
++ ctx->offset += data_len;
++ data_len = 0;
++ }
++ first_lap = 0;
++ }
++ ((struct tcphdr *)eddp->th_in_ctx)->check = csum_fold(hcsum);
++}
++
++static __wsum qeth_eddp_check_tcp4_hdr(struct qeth_eddp_data *eddp,
++ int data_len)
++{
++ __wsum phcsum; /* pseudo header checksum */
++
++ QETH_DBF_TEXT(TRACE, 5, "eddpckt4");
++ eddp->th.tcp.h.check = 0;
++ /* compute pseudo header checksum */
++ phcsum = csum_tcpudp_nofold(eddp->nh.ip4.h.saddr, eddp->nh.ip4.h.daddr,
++ eddp->thl + data_len, IPPROTO_TCP, 0);
++ /* compute checksum of tcp header */
++ return csum_partial((u8 *)&eddp->th, eddp->thl, phcsum);
++}
++
++static __wsum qeth_eddp_check_tcp6_hdr(struct qeth_eddp_data *eddp,
++ int data_len)
++{
++ __be32 proto;
++ __wsum phcsum; /* pseudo header checksum */
++
++ QETH_DBF_TEXT(TRACE, 5, "eddpckt6");
++ eddp->th.tcp.h.check = 0;
++ /* compute pseudo header checksum */
++ phcsum = csum_partial((u8 *)&eddp->nh.ip6.h.saddr,
++ sizeof(struct in6_addr), 0);
++ phcsum = csum_partial((u8 *)&eddp->nh.ip6.h.daddr,
++ sizeof(struct in6_addr), phcsum);
++ proto = htonl(IPPROTO_TCP);
++ phcsum = csum_partial((u8 *)&proto, sizeof(u32), phcsum);
++ return phcsum;
++}
++
++static struct qeth_eddp_data *qeth_eddp_create_eddp_data(struct qeth_hdr *qh,
++ u8 *nh, u8 nhl, u8 *th, u8 thl)
++{
++ struct qeth_eddp_data *eddp;
++
++ QETH_DBF_TEXT(TRACE, 5, "eddpcrda");
++ eddp = kzalloc(sizeof(struct qeth_eddp_data), GFP_ATOMIC);
++ if (eddp) {
++ eddp->nhl = nhl;
++ eddp->thl = thl;
++ memcpy(&eddp->qh, qh, sizeof(struct qeth_hdr));
++ memcpy(&eddp->nh, nh, nhl);
++ memcpy(&eddp->th, th, thl);
++ eddp->frag = -1; /* initially we're in skb->data */
++ }
++ return eddp;
++}
++
++static void __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
++ struct qeth_eddp_data *eddp)
++{
++ struct tcphdr *tcph;
++ int data_len;
++ __wsum hcsum;
++
++ QETH_DBF_TEXT(TRACE, 5, "eddpftcp");
++ eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl;
++ if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
++ eddp->skb_offset += sizeof(struct ethhdr);
++ if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
++ eddp->skb_offset += VLAN_HLEN;
++ }
++ tcph = tcp_hdr(eddp->skb);
++ while (eddp->skb_offset < eddp->skb->len) {
++ data_len = min((int)skb_shinfo(eddp->skb)->gso_size,
++ (int)(eddp->skb->len - eddp->skb_offset));
++ /* prepare qdio hdr */
++ if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
++ eddp->qh.hdr.l2.pkt_length = data_len + ETH_HLEN +
++ eddp->nhl + eddp->thl;
++ if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
++ eddp->qh.hdr.l2.pkt_length += VLAN_HLEN;
++ } else
++ eddp->qh.hdr.l3.length = data_len + eddp->nhl +
++ eddp->thl;
++ /* prepare ip hdr */
++ if (eddp->skb->protocol == htons(ETH_P_IP)) {
++ eddp->nh.ip4.h.tot_len = htons(data_len + eddp->nhl +
++ eddp->thl);
++ eddp->nh.ip4.h.check = 0;
++ eddp->nh.ip4.h.check =
++ ip_fast_csum((u8 *)&eddp->nh.ip4.h,
++ eddp->nh.ip4.h.ihl);
++ } else
++ eddp->nh.ip6.h.payload_len = htons(data_len +
++ eddp->thl);
++ /* prepare tcp hdr */
++ if (data_len == (eddp->skb->len - eddp->skb_offset)) {
++ /* last segment -> set FIN and PSH flags */
++ eddp->th.tcp.h.fin = tcph->fin;
++ eddp->th.tcp.h.psh = tcph->psh;
++ }
++ if (eddp->skb->protocol == htons(ETH_P_IP))
++ hcsum = qeth_eddp_check_tcp4_hdr(eddp, data_len);
++ else
++ hcsum = qeth_eddp_check_tcp6_hdr(eddp, data_len);
++ /* fill the next segment into the context */
++ qeth_eddp_create_segment_hdrs(ctx, eddp, data_len);
++ qeth_eddp_create_segment_data_tcp(ctx, eddp, data_len, hcsum);
++ if (eddp->skb_offset >= eddp->skb->len)
++ break;
++ /* prepare headers for next round */
++ if (eddp->skb->protocol == htons(ETH_P_IP))
++ eddp->nh.ip4.h.id = htons(ntohs(eddp->nh.ip4.h.id) + 1);
++ eddp->th.tcp.h.seq = htonl(ntohl(eddp->th.tcp.h.seq) +
++ data_len);
++ }
++}
++
++static int qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
++ struct sk_buff *skb, struct qeth_hdr *qhdr)
++{
++ struct qeth_eddp_data *eddp = NULL;
++
++ QETH_DBF_TEXT(TRACE, 5, "eddpficx");
++ /* create our segmentation headers and copy original headers */
++ if (skb->protocol == htons(ETH_P_IP))
++ eddp = qeth_eddp_create_eddp_data(qhdr,
++ skb_network_header(skb),
++ ip_hdrlen(skb),
++ skb_transport_header(skb),
++ tcp_hdrlen(skb));
++ else
++ eddp = qeth_eddp_create_eddp_data(qhdr,
++ skb_network_header(skb),
++ sizeof(struct ipv6hdr),
++ skb_transport_header(skb),
++ tcp_hdrlen(skb));
++
++ if (eddp == NULL) {
++ QETH_DBF_TEXT(TRACE, 2, "eddpfcnm");
++ return -ENOMEM;
++ }
++ if (qhdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
++ skb_set_mac_header(skb, sizeof(struct qeth_hdr));
++ memcpy(&eddp->mac, eth_hdr(skb), ETH_HLEN);
++ if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) {
++ eddp->vlan[0] = skb->protocol;
++ eddp->vlan[1] = htons(vlan_tx_tag_get(skb));
++ }
++ }
++ /* the next flags will only be set on the last segment */
++ eddp->th.tcp.h.fin = 0;
++ eddp->th.tcp.h.psh = 0;
++ eddp->skb = skb;
++ /* begin segmentation and fill context */
++ __qeth_eddp_fill_context_tcp(ctx, eddp);
++ kfree(eddp);
++ return 0;
++}
++
++static void qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx,
++ struct sk_buff *skb, int hdr_len)
++{
++ int skbs_per_page;
++
++ QETH_DBF_TEXT(TRACE, 5, "eddpcanp");
++ /* can we put multiple skbs in one page? */
++ skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->gso_size + hdr_len);
++ if (skbs_per_page > 1) {
++ ctx->num_pages = (skb_shinfo(skb)->gso_segs + 1) /
++ skbs_per_page + 1;
++ ctx->elements_per_skb = 1;
++ } else {
++ /* no -> how many elements per skb? */
++ ctx->elements_per_skb = (skb_shinfo(skb)->gso_size + hdr_len +
++ PAGE_SIZE) >> PAGE_SHIFT;
++ ctx->num_pages = ctx->elements_per_skb *
++ (skb_shinfo(skb)->gso_segs + 1);
++ }
++ ctx->num_elements = ctx->elements_per_skb *
++ (skb_shinfo(skb)->gso_segs + 1);
++}
++
++static struct qeth_eddp_context *qeth_eddp_create_context_generic(
++ struct qeth_card *card, struct sk_buff *skb, int hdr_len)
++{
++ struct qeth_eddp_context *ctx = NULL;
++ u8 *addr;
++ int i;
++
++ QETH_DBF_TEXT(TRACE, 5, "creddpcg");
++ /* create the context and allocate pages */
++ ctx = kzalloc(sizeof(struct qeth_eddp_context), GFP_ATOMIC);
++ if (ctx == NULL) {
++ QETH_DBF_TEXT(TRACE, 2, "ceddpcn1");
++ return NULL;
++ }
++ ctx->type = QETH_LARGE_SEND_EDDP;
++ qeth_eddp_calc_num_pages(ctx, skb, hdr_len);
++ if (ctx->elements_per_skb > QETH_MAX_BUFFER_ELEMENTS(card)) {
++ QETH_DBF_TEXT(TRACE, 2, "ceddpcis");
++ kfree(ctx);
++ return NULL;
++ }
++ ctx->pages = kcalloc(ctx->num_pages, sizeof(u8 *), GFP_ATOMIC);
++ if (ctx->pages == NULL) {
++ QETH_DBF_TEXT(TRACE, 2, "ceddpcn2");
++ kfree(ctx);
++ return NULL;
++ }
++ for (i = 0; i < ctx->num_pages; ++i) {
++ addr = (u8 *)get_zeroed_page(GFP_ATOMIC);
++ if (addr == NULL) {
++ QETH_DBF_TEXT(TRACE, 2, "ceddpcn3");
++ ctx->num_pages = i;
++ qeth_eddp_free_context(ctx);
++ return NULL;
++ }
++ ctx->pages[i] = addr;
++ }
++ ctx->elements = kcalloc(ctx->num_elements,
++ sizeof(struct qeth_eddp_element), GFP_ATOMIC);
++ if (ctx->elements == NULL) {
++ QETH_DBF_TEXT(TRACE, 2, "ceddpcn4");
++ qeth_eddp_free_context(ctx);
++ return NULL;
++ }
++ /* reset num_elements; will be incremented again in fill_buffer to
++ * reflect number of actually used elements */
++ ctx->num_elements = 0;
++ return ctx;
++}
++
++static struct qeth_eddp_context *qeth_eddp_create_context_tcp(
++ struct qeth_card *card, struct sk_buff *skb,
++ struct qeth_hdr *qhdr)
++{
++ struct qeth_eddp_context *ctx = NULL;
++
++ QETH_DBF_TEXT(TRACE, 5, "creddpct");
++ if (skb->protocol == htons(ETH_P_IP))
++ ctx = qeth_eddp_create_context_generic(card, skb,
++ (sizeof(struct qeth_hdr) +
++ ip_hdrlen(skb) +
++ tcp_hdrlen(skb)));
++ else if (skb->protocol == htons(ETH_P_IPV6))
++ ctx = qeth_eddp_create_context_generic(card, skb,
++ sizeof(struct qeth_hdr) + sizeof(struct ipv6hdr) +
++ tcp_hdrlen(skb));
++ else
++ QETH_DBF_TEXT(TRACE, 2, "cetcpinv");
++
++ if (ctx == NULL) {
++ QETH_DBF_TEXT(TRACE, 2, "creddpnl");
++ return NULL;
++ }
++ if (qeth_eddp_fill_context_tcp(ctx, skb, qhdr)) {
++ QETH_DBF_TEXT(TRACE, 2, "ceddptfe");
++ qeth_eddp_free_context(ctx);
++ return NULL;
++ }
++ atomic_set(&ctx->refcnt, 1);
++ return ctx;
++}
++
++struct qeth_eddp_context *qeth_eddp_create_context(struct qeth_card *card,
++ struct sk_buff *skb, struct qeth_hdr *qhdr,
++ unsigned char sk_protocol)
++{
++ QETH_DBF_TEXT(TRACE, 5, "creddpc");
++ switch (sk_protocol) {
++ case IPPROTO_TCP:
++ return qeth_eddp_create_context_tcp(card, skb, qhdr);
++ default:
++ QETH_DBF_TEXT(TRACE, 2, "eddpinvp");
++ }
++ return NULL;
++}
++EXPORT_SYMBOL_GPL(qeth_eddp_create_context);
++
++void qeth_tso_fill_header(struct qeth_card *card, struct qeth_hdr *qhdr,
++ struct sk_buff *skb)
++{
++ struct qeth_hdr_tso *hdr = (struct qeth_hdr_tso *)qhdr;
++ struct tcphdr *tcph = tcp_hdr(skb);
++ struct iphdr *iph = ip_hdr(skb);
++ struct ipv6hdr *ip6h = ipv6_hdr(skb);
++
++ QETH_DBF_TEXT(TRACE, 5, "tsofhdr");
++
++ /*fix header to TSO values ...*/
++ hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO;
++ /*set values which are fix for the first approach ...*/
++ hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso);
++ hdr->ext.imb_hdr_no = 1;
++ hdr->ext.hdr_type = 1;
++ hdr->ext.hdr_version = 1;
++ hdr->ext.hdr_len = 28;
++ /*insert non-fix values */
++ hdr->ext.mss = skb_shinfo(skb)->gso_size;
++ hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4);
++ hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len -
++ sizeof(struct qeth_hdr_tso));
++ tcph->check = 0;
++ if (skb->protocol == ETH_P_IPV6) {
++ ip6h->payload_len = 0;
++ tcph->check = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
++ 0, IPPROTO_TCP, 0);
++ } else {
++ /*OSA want us to set these values ...*/
++ tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
++ 0, IPPROTO_TCP, 0);
++ iph->tot_len = 0;
++ iph->check = 0;
++ }
++}
++EXPORT_SYMBOL_GPL(qeth_tso_fill_header);
++
++void qeth_tx_csum(struct sk_buff *skb)
++{
++ int tlen;
++ if (skb->protocol == htons(ETH_P_IP)) {
++ tlen = ntohs(ip_hdr(skb)->tot_len) - (ip_hdr(skb)->ihl << 2);
++ switch (ip_hdr(skb)->protocol) {
++ case IPPROTO_TCP:
++ tcp_hdr(skb)->check = 0;
++ tcp_hdr(skb)->check = csum_tcpudp_magic(
++ ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
++ tlen, ip_hdr(skb)->protocol,
++ skb_checksum(skb, skb_transport_offset(skb),
++ tlen, 0));
++ break;
++ case IPPROTO_UDP:
++ udp_hdr(skb)->check = 0;
++ udp_hdr(skb)->check = csum_tcpudp_magic(
++ ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
++ tlen, ip_hdr(skb)->protocol,
++ skb_checksum(skb, skb_transport_offset(skb),
++ tlen, 0));
++ break;
++ }
++ } else if (skb->protocol == htons(ETH_P_IPV6)) {
++ switch (ipv6_hdr(skb)->nexthdr) {
++ case IPPROTO_TCP:
++ tcp_hdr(skb)->check = 0;
++ tcp_hdr(skb)->check = csum_ipv6_magic(
++ &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
++ ipv6_hdr(skb)->payload_len,
++ ipv6_hdr(skb)->nexthdr,
++ skb_checksum(skb, skb_transport_offset(skb),
++ ipv6_hdr(skb)->payload_len, 0));
++ break;
++ case IPPROTO_UDP:
++ udp_hdr(skb)->check = 0;
++ udp_hdr(skb)->check = csum_ipv6_magic(
++ &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
++ ipv6_hdr(skb)->payload_len,
++ ipv6_hdr(skb)->nexthdr,
++ skb_checksum(skb, skb_transport_offset(skb),
++ ipv6_hdr(skb)->payload_len, 0));
++ break;
++ }
++ }
++}
++EXPORT_SYMBOL_GPL(qeth_tx_csum);
+diff --git a/drivers/s390/net/qeth_core_offl.h b/drivers/s390/net/qeth_core_offl.h
+new file mode 100644
+index 0000000..86bf7df
+--- /dev/null
++++ b/drivers/s390/net/qeth_core_offl.h
+@@ -0,0 +1,76 @@
++/*
++ * drivers/s390/net/qeth_core_offl.h
++ *
++ * Copyright IBM Corp. 2007
++ * Author(s): Thomas Spatzier <tspat at de.ibm.com>,
++ * Frank Blaschka <frank.blaschka at de.ibm.com>
++ */
++
++#ifndef __QETH_CORE_OFFL_H__
++#define __QETH_CORE_OFFL_H__
++
++struct qeth_eddp_element {
++ u32 flags;
++ u32 length;
++ void *addr;
++};
++
++struct qeth_eddp_context {
++ atomic_t refcnt;
++ enum qeth_large_send_types type;
++ int num_pages; /* # of allocated pages */
++ u8 **pages; /* pointers to pages */
++ int offset; /* offset in ctx during creation */
++ int num_elements; /* # of required 'SBALEs' */
++ struct qeth_eddp_element *elements; /* array of 'SBALEs' */
++ int elements_per_skb; /* # of 'SBALEs' per skb **/
++};
++
++struct qeth_eddp_context_reference {
++ struct list_head list;
++ struct qeth_eddp_context *ctx;
++};
++
++struct qeth_eddp_data {
++ struct qeth_hdr qh;
++ struct ethhdr mac;
++ __be16 vlan[2];
++ union {
++ struct {
++ struct iphdr h;
++ u8 options[40];
++ } ip4;
++ struct {
++ struct ipv6hdr h;
++ } ip6;
++ } nh;
++ u8 nhl;
++ void *nh_in_ctx; /* address of nh within the ctx */
++ union {
++ struct {
++ struct tcphdr h;
++ u8 options[40];
++ } tcp;
++ } th;
++ u8 thl;
++ void *th_in_ctx; /* address of th within the ctx */
++ struct sk_buff *skb;
++ int skb_offset;
++ int frag;
++ int frag_offset;
++} __attribute__ ((packed));
++
++extern struct qeth_eddp_context *qeth_eddp_create_context(struct qeth_card *,
++ struct sk_buff *, struct qeth_hdr *, unsigned char);
++extern void qeth_eddp_put_context(struct qeth_eddp_context *);
++extern int qeth_eddp_fill_buffer(struct qeth_qdio_out_q *,
++ struct qeth_eddp_context *, int);
++extern void qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *);
++extern int qeth_eddp_check_buffers_for_context(struct qeth_qdio_out_q *,
++ struct qeth_eddp_context *);
++
++void qeth_tso_fill_header(struct qeth_card *, struct qeth_hdr *,
++ struct sk_buff *);
++void qeth_tx_csum(struct sk_buff *skb);
++
++#endif /* __QETH_CORE_EDDP_H__ */
+diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c
+new file mode 100644
+index 0000000..08a50f0
+--- /dev/null
++++ b/drivers/s390/net/qeth_core_sys.c
+@@ -0,0 +1,651 @@
++/*
++ * drivers/s390/net/qeth_core_sys.c
++ *
++ * Copyright IBM Corp. 2007
++ * Author(s): Utz Bacher <utz.bacher at de.ibm.com>,
++ * Frank Pavlic <fpavlic at de.ibm.com>,
++ * Thomas Spatzier <tspat at de.ibm.com>,
++ * Frank Blaschka <frank.blaschka at de.ibm.com>
++ */
++
++#include <linux/list.h>
++#include <linux/rwsem.h>
++#include <asm/ebcdic.h>
++
++#include "qeth_core.h"
++
++static ssize_t qeth_dev_state_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++ if (!card)
++ return -EINVAL;
++
++ switch (card->state) {
++ case CARD_STATE_DOWN:
++ return sprintf(buf, "DOWN\n");
++ case CARD_STATE_HARDSETUP:
++ return sprintf(buf, "HARDSETUP\n");
++ case CARD_STATE_SOFTSETUP:
++ return sprintf(buf, "SOFTSETUP\n");
++ case CARD_STATE_UP:
++ if (card->lan_online)
++ return sprintf(buf, "UP (LAN ONLINE)\n");
++ else
++ return sprintf(buf, "UP (LAN OFFLINE)\n");
++ case CARD_STATE_RECOVER:
++ return sprintf(buf, "RECOVER\n");
++ default:
++ return sprintf(buf, "UNKNOWN\n");
++ }
++}
++
++static DEVICE_ATTR(state, 0444, qeth_dev_state_show, NULL);
++
++static ssize_t qeth_dev_chpid_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++ if (!card)
++ return -EINVAL;
++
++ return sprintf(buf, "%02X\n", card->info.chpid);
++}
++
++static DEVICE_ATTR(chpid, 0444, qeth_dev_chpid_show, NULL);
++
++static ssize_t qeth_dev_if_name_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++ if (!card)
++ return -EINVAL;
++ return sprintf(buf, "%s\n", QETH_CARD_IFNAME(card));
++}
++
++static DEVICE_ATTR(if_name, 0444, qeth_dev_if_name_show, NULL);
++
++static ssize_t qeth_dev_card_type_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++ if (!card)
++ return -EINVAL;
++
++ return sprintf(buf, "%s\n", qeth_get_cardname_short(card));
++}
++
++static DEVICE_ATTR(card_type, 0444, qeth_dev_card_type_show, NULL);
++
++static inline const char *qeth_get_bufsize_str(struct qeth_card *card)
++{
++ if (card->qdio.in_buf_size == 16384)
++ return "16k";
++ else if (card->qdio.in_buf_size == 24576)
++ return "24k";
++ else if (card->qdio.in_buf_size == 32768)
++ return "32k";
++ else if (card->qdio.in_buf_size == 40960)
++ return "40k";
++ else
++ return "64k";
++}
++
++static ssize_t qeth_dev_inbuf_size_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++ if (!card)
++ return -EINVAL;
++
++ return sprintf(buf, "%s\n", qeth_get_bufsize_str(card));
++}
++
++static DEVICE_ATTR(inbuf_size, 0444, qeth_dev_inbuf_size_show, NULL);
++
++static ssize_t qeth_dev_portno_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++ if (!card)
++ return -EINVAL;
++
++ return sprintf(buf, "%i\n", card->info.portno);
++}
++
++static ssize_t qeth_dev_portno_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++ char *tmp;
++ unsigned int portno;
++
++ if (!card)
++ return -EINVAL;
++
++ if ((card->state != CARD_STATE_DOWN) &&
++ (card->state != CARD_STATE_RECOVER))
++ return -EPERM;
++
++ portno = simple_strtoul(buf, &tmp, 16);
++ if (portno > QETH_MAX_PORTNO) {
++ PRINT_WARN("portno 0x%X is out of range\n", portno);
++ return -EINVAL;
++ }
++
++ card->info.portno = portno;
++ return count;
++}
++
++static DEVICE_ATTR(portno, 0644, qeth_dev_portno_show, qeth_dev_portno_store);
++
++static ssize_t qeth_dev_portname_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++ char portname[9] = {0, };
++
++ if (!card)
++ return -EINVAL;
++
++ if (card->info.portname_required) {
++ memcpy(portname, card->info.portname + 1, 8);
++ EBCASC(portname, 8);
++ return sprintf(buf, "%s\n", portname);
++ } else
++ return sprintf(buf, "no portname required\n");
++}
++
++static ssize_t qeth_dev_portname_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++ char *tmp;
++ int i;
++
++ if (!card)
++ return -EINVAL;
++
++ if ((card->state != CARD_STATE_DOWN) &&
++ (card->state != CARD_STATE_RECOVER))
++ return -EPERM;
++
++ tmp = strsep((char **) &buf, "\n");
++ if ((strlen(tmp) > 8) || (strlen(tmp) == 0))
++ return -EINVAL;
++
++ card->info.portname[0] = strlen(tmp);
++ /* for beauty reasons */
++ for (i = 1; i < 9; i++)
++ card->info.portname[i] = ' ';
++ strcpy(card->info.portname + 1, tmp);
++ ASCEBC(card->info.portname + 1, 8);
++
++ return count;
++}
++
++static DEVICE_ATTR(portname, 0644, qeth_dev_portname_show,
++ qeth_dev_portname_store);
++
++static ssize_t qeth_dev_prioqing_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ switch (card->qdio.do_prio_queueing) {
++ case QETH_PRIO_Q_ING_PREC:
++ return sprintf(buf, "%s\n", "by precedence");
++ case QETH_PRIO_Q_ING_TOS:
++ return sprintf(buf, "%s\n", "by type of service");
++ default:
++ return sprintf(buf, "always queue %i\n",
++ card->qdio.default_out_queue);
++ }
++}
++
++static ssize_t qeth_dev_prioqing_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++ char *tmp;
++
++ if (!card)
++ return -EINVAL;
++
++ if ((card->state != CARD_STATE_DOWN) &&
++ (card->state != CARD_STATE_RECOVER))
++ return -EPERM;
++
++ /* check if 1920 devices are supported ,
++ * if though we have to permit priority queueing
++ */
++ if (card->qdio.no_out_queues == 1) {
++ PRINT_WARN("Priority queueing disabled due "
++ "to hardware limitations!\n");
++ card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
++ return -EPERM;
++ }
++
++ tmp = strsep((char **) &buf, "\n");
++ if (!strcmp(tmp, "prio_queueing_prec"))
++ card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_PREC;
++ else if (!strcmp(tmp, "prio_queueing_tos"))
++ card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_TOS;
++ else if (!strcmp(tmp, "no_prio_queueing:0")) {
++ card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
++ card->qdio.default_out_queue = 0;
++ } else if (!strcmp(tmp, "no_prio_queueing:1")) {
++ card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
++ card->qdio.default_out_queue = 1;
++ } else if (!strcmp(tmp, "no_prio_queueing:2")) {
++ card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
++ card->qdio.default_out_queue = 2;
++ } else if (!strcmp(tmp, "no_prio_queueing:3")) {
++ card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
++ card->qdio.default_out_queue = 3;
++ } else if (!strcmp(tmp, "no_prio_queueing")) {
++ card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
++ card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
++ } else {
++ PRINT_WARN("Unknown queueing type '%s'\n", tmp);
++ return -EINVAL;
++ }
++ return count;
++}
++
++static DEVICE_ATTR(priority_queueing, 0644, qeth_dev_prioqing_show,
++ qeth_dev_prioqing_store);
++
++static ssize_t qeth_dev_bufcnt_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return sprintf(buf, "%i\n", card->qdio.in_buf_pool.buf_count);
++}
++
++static ssize_t qeth_dev_bufcnt_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++ char *tmp;
++ int cnt, old_cnt;
++ int rc;
++
++ if (!card)
++ return -EINVAL;
++
++ if ((card->state != CARD_STATE_DOWN) &&
++ (card->state != CARD_STATE_RECOVER))
++ return -EPERM;
++
++ old_cnt = card->qdio.in_buf_pool.buf_count;
++ cnt = simple_strtoul(buf, &tmp, 10);
++ cnt = (cnt < QETH_IN_BUF_COUNT_MIN) ? QETH_IN_BUF_COUNT_MIN :
++ ((cnt > QETH_IN_BUF_COUNT_MAX) ? QETH_IN_BUF_COUNT_MAX : cnt);
++ if (old_cnt != cnt) {
++ rc = qeth_realloc_buffer_pool(card, cnt);
++ if (rc)
++ PRINT_WARN("Error (%d) while setting "
++ "buffer count.\n", rc);
++ }
++ return count;
++}
++
++static DEVICE_ATTR(buffer_count, 0644, qeth_dev_bufcnt_show,
++ qeth_dev_bufcnt_store);
++
++static ssize_t qeth_dev_recover_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++ char *tmp;
++ int i;
++
++ if (!card)
++ return -EINVAL;
++
++ if (card->state != CARD_STATE_UP)
++ return -EPERM;
++
++ i = simple_strtoul(buf, &tmp, 16);
++ if (i == 1)
++ qeth_schedule_recovery(card);
++
++ return count;
++}
++
++static DEVICE_ATTR(recover, 0200, NULL, qeth_dev_recover_store);
++
++static ssize_t qeth_dev_performance_stats_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return sprintf(buf, "%i\n", card->options.performance_stats ? 1:0);
++}
++
++static ssize_t qeth_dev_performance_stats_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++ char *tmp;
++ int i;
++
++ if (!card)
++ return -EINVAL;
++
++ i = simple_strtoul(buf, &tmp, 16);
++ if ((i == 0) || (i == 1)) {
++ if (i == card->options.performance_stats)
++ return count;
++ card->options.performance_stats = i;
++ if (i == 0)
++ memset(&card->perf_stats, 0,
++ sizeof(struct qeth_perf_stats));
++ card->perf_stats.initial_rx_packets = card->stats.rx_packets;
++ card->perf_stats.initial_tx_packets = card->stats.tx_packets;
++ } else {
++ PRINT_WARN("performance_stats: write 0 or 1 to this file!\n");
++ return -EINVAL;
++ }
++ return count;
++}
++
++static DEVICE_ATTR(performance_stats, 0644, qeth_dev_performance_stats_show,
++ qeth_dev_performance_stats_store);
++
++static ssize_t qeth_dev_layer2_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return sprintf(buf, "%i\n", card->options.layer2 ? 1:0);
++}
++
++static ssize_t qeth_dev_layer2_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++ char *tmp;
++ int i, rc;
++ enum qeth_discipline_id newdis;
++
++ if (!card)
++ return -EINVAL;
++
++ if (((card->state != CARD_STATE_DOWN) &&
++ (card->state != CARD_STATE_RECOVER)))
++ return -EPERM;
++
++ i = simple_strtoul(buf, &tmp, 16);
++ switch (i) {
++ case 0:
++ newdis = QETH_DISCIPLINE_LAYER3;
++ break;
++ case 1:
++ newdis = QETH_DISCIPLINE_LAYER2;
++ break;
++ default:
++ PRINT_WARN("layer2: write 0 or 1 to this file!\n");
++ return -EINVAL;
++ }
++
++ if (card->options.layer2 == newdis) {
++ return count;
++ } else {
++ if (card->discipline.ccwgdriver) {
++ card->discipline.ccwgdriver->remove(card->gdev);
++ qeth_core_free_discipline(card);
++ }
++ }
++
++ rc = qeth_core_load_discipline(card, newdis);
++ if (rc)
++ return rc;
++
++ rc = card->discipline.ccwgdriver->probe(card->gdev);
++ if (rc)
++ return rc;
++ return count;
++}
++
++static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show,
++ qeth_dev_layer2_store);
++
++static ssize_t qeth_dev_large_send_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ switch (card->options.large_send) {
++ case QETH_LARGE_SEND_NO:
++ return sprintf(buf, "%s\n", "no");
++ case QETH_LARGE_SEND_EDDP:
++ return sprintf(buf, "%s\n", "EDDP");
++ case QETH_LARGE_SEND_TSO:
++ return sprintf(buf, "%s\n", "TSO");
++ default:
++ return sprintf(buf, "%s\n", "N/A");
++ }
++}
++
++static ssize_t qeth_dev_large_send_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++ enum qeth_large_send_types type;
++ int rc = 0;
++ char *tmp;
++
++ if (!card)
++ return -EINVAL;
++ tmp = strsep((char **) &buf, "\n");
++ if (!strcmp(tmp, "no")) {
++ type = QETH_LARGE_SEND_NO;
++ } else if (!strcmp(tmp, "EDDP")) {
++ type = QETH_LARGE_SEND_EDDP;
++ } else if (!strcmp(tmp, "TSO")) {
++ type = QETH_LARGE_SEND_TSO;
++ } else {
++ PRINT_WARN("large_send: invalid mode %s!\n", tmp);
++ return -EINVAL;
++ }
++ if (card->options.large_send == type)
++ return count;
++ rc = qeth_set_large_send(card, type);
++ if (rc)
++ return rc;
++ return count;
++}
++
++static DEVICE_ATTR(large_send, 0644, qeth_dev_large_send_show,
++ qeth_dev_large_send_store);
++
++static ssize_t qeth_dev_blkt_show(char *buf, struct qeth_card *card, int value)
++{
++
++ if (!card)
++ return -EINVAL;
++
++ return sprintf(buf, "%i\n", value);
++}
++
++static ssize_t qeth_dev_blkt_store(struct qeth_card *card,
++ const char *buf, size_t count, int *value, int max_value)
++{
++ char *tmp;
++ int i;
++
++ if (!card)
++ return -EINVAL;
++
++ if ((card->state != CARD_STATE_DOWN) &&
++ (card->state != CARD_STATE_RECOVER))
++ return -EPERM;
++
++ i = simple_strtoul(buf, &tmp, 10);
++ if (i <= max_value) {
++ *value = i;
++ } else {
++ PRINT_WARN("blkt total time: write values between"
++ " 0 and %d to this file!\n", max_value);
++ return -EINVAL;
++ }
++ return count;
++}
++
++static ssize_t qeth_dev_blkt_total_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ return qeth_dev_blkt_show(buf, card, card->info.blkt.time_total);
++}
++
++static ssize_t qeth_dev_blkt_total_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ return qeth_dev_blkt_store(card, buf, count,
++ &card->info.blkt.time_total, 1000);
++}
++
++
++
++static DEVICE_ATTR(total, 0644, qeth_dev_blkt_total_show,
++ qeth_dev_blkt_total_store);
++
++static ssize_t qeth_dev_blkt_inter_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ return qeth_dev_blkt_show(buf, card, card->info.blkt.inter_packet);
++}
++
++static ssize_t qeth_dev_blkt_inter_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ return qeth_dev_blkt_store(card, buf, count,
++ &card->info.blkt.inter_packet, 100);
++}
++
++static DEVICE_ATTR(inter, 0644, qeth_dev_blkt_inter_show,
++ qeth_dev_blkt_inter_store);
++
++static ssize_t qeth_dev_blkt_inter_jumbo_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ return qeth_dev_blkt_show(buf, card,
++ card->info.blkt.inter_packet_jumbo);
++}
++
++static ssize_t qeth_dev_blkt_inter_jumbo_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ return qeth_dev_blkt_store(card, buf, count,
++ &card->info.blkt.inter_packet_jumbo, 100);
++}
++
++static DEVICE_ATTR(inter_jumbo, 0644, qeth_dev_blkt_inter_jumbo_show,
++ qeth_dev_blkt_inter_jumbo_store);
++
++static struct attribute *qeth_blkt_device_attrs[] = {
++ &dev_attr_total.attr,
++ &dev_attr_inter.attr,
++ &dev_attr_inter_jumbo.attr,
++ NULL,
++};
++
++static struct attribute_group qeth_device_blkt_group = {
++ .name = "blkt",
++ .attrs = qeth_blkt_device_attrs,
++};
++
++static struct attribute *qeth_device_attrs[] = {
++ &dev_attr_state.attr,
++ &dev_attr_chpid.attr,
++ &dev_attr_if_name.attr,
++ &dev_attr_card_type.attr,
++ &dev_attr_inbuf_size.attr,
++ &dev_attr_portno.attr,
++ &dev_attr_portname.attr,
++ &dev_attr_priority_queueing.attr,
++ &dev_attr_buffer_count.attr,
++ &dev_attr_recover.attr,
++ &dev_attr_performance_stats.attr,
++ &dev_attr_layer2.attr,
++ &dev_attr_large_send.attr,
++ NULL,
++};
++
++static struct attribute_group qeth_device_attr_group = {
++ .attrs = qeth_device_attrs,
++};
++
++static struct attribute *qeth_osn_device_attrs[] = {
++ &dev_attr_state.attr,
++ &dev_attr_chpid.attr,
++ &dev_attr_if_name.attr,
++ &dev_attr_card_type.attr,
++ &dev_attr_buffer_count.attr,
++ &dev_attr_recover.attr,
++ NULL,
++};
++
++static struct attribute_group qeth_osn_device_attr_group = {
++ .attrs = qeth_osn_device_attrs,
++};
++
++int qeth_core_create_device_attributes(struct device *dev)
++{
++ int ret;
++ ret = sysfs_create_group(&dev->kobj, &qeth_device_attr_group);
++ if (ret)
++ return ret;
++ ret = sysfs_create_group(&dev->kobj, &qeth_device_blkt_group);
++ if (ret)
++ sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
++
++ return 0;
++}
++
++void qeth_core_remove_device_attributes(struct device *dev)
++{
++ sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
++ sysfs_remove_group(&dev->kobj, &qeth_device_blkt_group);
++}
++
++int qeth_core_create_osn_attributes(struct device *dev)
++{
++ return sysfs_create_group(&dev->kobj, &qeth_osn_device_attr_group);
++}
++
++void qeth_core_remove_osn_attributes(struct device *dev)
++{
++ sysfs_remove_group(&dev->kobj, &qeth_osn_device_attr_group);
++ return;
++}
+diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c
+deleted file mode 100644
+index e3c268c..0000000
+--- a/drivers/s390/net/qeth_eddp.c
++++ /dev/null
+@@ -1,634 +0,0 @@
+-/*
+- * linux/drivers/s390/net/qeth_eddp.c
+- *
+- * Enhanced Device Driver Packing (EDDP) support for the qeth driver.
+- *
+- * Copyright 2004 IBM Corporation
+- *
+- * Author(s): Thomas Spatzier <tspat at de.ibm.com>
+- *
+- */
+-#include <linux/errno.h>
+-#include <linux/ip.h>
+-#include <linux/inetdevice.h>
+-#include <linux/netdevice.h>
+-#include <linux/kernel.h>
+-#include <linux/tcp.h>
+-#include <net/tcp.h>
+-#include <linux/skbuff.h>
+-
+-#include <net/ip.h>
+-
+-#include "qeth.h"
+-#include "qeth_mpc.h"
+-#include "qeth_eddp.h"
+-
+-int
+-qeth_eddp_check_buffers_for_context(struct qeth_qdio_out_q *queue,
+- struct qeth_eddp_context *ctx)
+-{
+- int index = queue->next_buf_to_fill;
+- int elements_needed = ctx->num_elements;
+- int elements_in_buffer;
+- int skbs_in_buffer;
+- int buffers_needed = 0;
+-
+- QETH_DBF_TEXT(trace, 5, "eddpcbfc");
+- while(elements_needed > 0) {
+- buffers_needed++;
+- if (atomic_read(&queue->bufs[index].state) !=
+- QETH_QDIO_BUF_EMPTY)
+- return -EBUSY;
+-
+- elements_in_buffer = QETH_MAX_BUFFER_ELEMENTS(queue->card) -
+- queue->bufs[index].next_element_to_fill;
+- skbs_in_buffer = elements_in_buffer / ctx->elements_per_skb;
+- elements_needed -= skbs_in_buffer * ctx->elements_per_skb;
+- index = (index + 1) % QDIO_MAX_BUFFERS_PER_Q;
+- }
+- return buffers_needed;
+-}
+-
+-static void
+-qeth_eddp_free_context(struct qeth_eddp_context *ctx)
+-{
+- int i;
+-
+- QETH_DBF_TEXT(trace, 5, "eddpfctx");
+- for (i = 0; i < ctx->num_pages; ++i)
+- free_page((unsigned long)ctx->pages[i]);
+- kfree(ctx->pages);
+- kfree(ctx->elements);
+- kfree(ctx);
+-}
+-
+-
+-static inline void
+-qeth_eddp_get_context(struct qeth_eddp_context *ctx)
+-{
+- atomic_inc(&ctx->refcnt);
+-}
+-
+-void
+-qeth_eddp_put_context(struct qeth_eddp_context *ctx)
+-{
+- if (atomic_dec_return(&ctx->refcnt) == 0)
+- qeth_eddp_free_context(ctx);
+-}
+-
+-void
+-qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *buf)
+-{
+- struct qeth_eddp_context_reference *ref;
+-
+- QETH_DBF_TEXT(trace, 6, "eddprctx");
+- while (!list_empty(&buf->ctx_list)){
+- ref = list_entry(buf->ctx_list.next,
+- struct qeth_eddp_context_reference, list);
+- qeth_eddp_put_context(ref->ctx);
+- list_del(&ref->list);
+- kfree(ref);
+- }
+-}
+-
+-static int
+-qeth_eddp_buf_ref_context(struct qeth_qdio_out_buffer *buf,
+- struct qeth_eddp_context *ctx)
+-{
+- struct qeth_eddp_context_reference *ref;
+-
+- QETH_DBF_TEXT(trace, 6, "eddprfcx");
+- ref = kmalloc(sizeof(struct qeth_eddp_context_reference), GFP_ATOMIC);
+- if (ref == NULL)
+- return -ENOMEM;
+- qeth_eddp_get_context(ctx);
+- ref->ctx = ctx;
+- list_add_tail(&ref->list, &buf->ctx_list);
+- return 0;
+-}
+-
+-int
+-qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue,
+- struct qeth_eddp_context *ctx,
+- int index)
+-{
+- struct qeth_qdio_out_buffer *buf = NULL;
+- struct qdio_buffer *buffer;
+- int elements = ctx->num_elements;
+- int element = 0;
+- int flush_cnt = 0;
+- int must_refcnt = 1;
+- int i;
+-
+- QETH_DBF_TEXT(trace, 5, "eddpfibu");
+- while (elements > 0) {
+- buf = &queue->bufs[index];
+- if (atomic_read(&buf->state) != QETH_QDIO_BUF_EMPTY){
+- /* normally this should not happen since we checked for
+- * available elements in qeth_check_elements_for_context
+- */
+- if (element == 0)
+- return -EBUSY;
+- else {
+- PRINT_WARN("could only partially fill eddp "
+- "buffer!\n");
+- goto out;
+- }
+- }
+- /* check if the whole next skb fits into current buffer */
+- if ((QETH_MAX_BUFFER_ELEMENTS(queue->card) -
+- buf->next_element_to_fill)
+- < ctx->elements_per_skb){
+- /* no -> go to next buffer */
+- atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
+- index = (index + 1) % QDIO_MAX_BUFFERS_PER_Q;
+- flush_cnt++;
+- /* new buffer, so we have to add ctx to buffer'ctx_list
+- * and increment ctx's refcnt */
+- must_refcnt = 1;
+- continue;
+- }
+- if (must_refcnt){
+- must_refcnt = 0;
+- if (qeth_eddp_buf_ref_context(buf, ctx)){
+- PRINT_WARN("no memory to create eddp context "
+- "reference\n");
+- goto out_check;
+- }
+- }
+- buffer = buf->buffer;
+- /* fill one skb into buffer */
+- for (i = 0; i < ctx->elements_per_skb; ++i){
+- if (ctx->elements[element].length != 0) {
+- buffer->element[buf->next_element_to_fill].
+- addr = ctx->elements[element].addr;
+- buffer->element[buf->next_element_to_fill].
+- length = ctx->elements[element].length;
+- buffer->element[buf->next_element_to_fill].
+- flags = ctx->elements[element].flags;
+- buf->next_element_to_fill++;
+- }
+- element++;
+- elements--;
+- }
+- }
+-out_check:
+- if (!queue->do_pack) {
+- QETH_DBF_TEXT(trace, 6, "fillbfnp");
+- /* set state to PRIMED -> will be flushed */
+- if (buf->next_element_to_fill > 0){
+- atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
+- flush_cnt++;
+- }
+- } else {
+- if (queue->card->options.performance_stats)
+- queue->card->perf_stats.skbs_sent_pack++;
+- QETH_DBF_TEXT(trace, 6, "fillbfpa");
+- if (buf->next_element_to_fill >=
+- QETH_MAX_BUFFER_ELEMENTS(queue->card)) {
+- /*
+- * packed buffer if full -> set state PRIMED
+- * -> will be flushed
+- */
+- atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
+- flush_cnt++;
+- }
+- }
+-out:
+- return flush_cnt;
+-}
+-
+-static void
+-qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx,
+- struct qeth_eddp_data *eddp, int data_len)
+-{
+- u8 *page;
+- int page_remainder;
+- int page_offset;
+- int pkt_len;
+- struct qeth_eddp_element *element;
+-
+- QETH_DBF_TEXT(trace, 5, "eddpcrsh");
+- page = ctx->pages[ctx->offset >> PAGE_SHIFT];
+- page_offset = ctx->offset % PAGE_SIZE;
+- element = &ctx->elements[ctx->num_elements];
+- pkt_len = eddp->nhl + eddp->thl + data_len;
+- /* FIXME: layer2 and VLAN !!! */
+- if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
+- pkt_len += ETH_HLEN;
+- if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
+- pkt_len += VLAN_HLEN;
+- /* does complete packet fit in current page ? */
+- page_remainder = PAGE_SIZE - page_offset;
+- if (page_remainder < (sizeof(struct qeth_hdr) + pkt_len)){
+- /* no -> go to start of next page */
+- ctx->offset += page_remainder;
+- page = ctx->pages[ctx->offset >> PAGE_SHIFT];
+- page_offset = 0;
+- }
+- memcpy(page + page_offset, &eddp->qh, sizeof(struct qeth_hdr));
+- element->addr = page + page_offset;
+- element->length = sizeof(struct qeth_hdr);
+- ctx->offset += sizeof(struct qeth_hdr);
+- page_offset += sizeof(struct qeth_hdr);
+- /* add mac header (?) */
+- if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2){
+- memcpy(page + page_offset, &eddp->mac, ETH_HLEN);
+- element->length += ETH_HLEN;
+- ctx->offset += ETH_HLEN;
+- page_offset += ETH_HLEN;
+- }
+- /* add VLAN tag */
+- if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)){
+- memcpy(page + page_offset, &eddp->vlan, VLAN_HLEN);
+- element->length += VLAN_HLEN;
+- ctx->offset += VLAN_HLEN;
+- page_offset += VLAN_HLEN;
+- }
+- /* add network header */
+- memcpy(page + page_offset, (u8 *)&eddp->nh, eddp->nhl);
+- element->length += eddp->nhl;
+- eddp->nh_in_ctx = page + page_offset;
+- ctx->offset += eddp->nhl;
+- page_offset += eddp->nhl;
+- /* add transport header */
+- memcpy(page + page_offset, (u8 *)&eddp->th, eddp->thl);
+- element->length += eddp->thl;
+- eddp->th_in_ctx = page + page_offset;
+- ctx->offset += eddp->thl;
+-}
+-
+-static void
+-qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len,
+- __wsum *hcsum)
+-{
+- struct skb_frag_struct *frag;
+- int left_in_frag;
+- int copy_len;
+- u8 *src;
+-
+- QETH_DBF_TEXT(trace, 5, "eddpcdtc");
+- if (skb_shinfo(eddp->skb)->nr_frags == 0) {
+- skb_copy_from_linear_data_offset(eddp->skb, eddp->skb_offset,
+- dst, len);
+- *hcsum = csum_partial(eddp->skb->data + eddp->skb_offset, len,
+- *hcsum);
+- eddp->skb_offset += len;
+- } else {
+- while (len > 0) {
+- if (eddp->frag < 0) {
+- /* we're in skb->data */
+- left_in_frag = (eddp->skb->len - eddp->skb->data_len)
+- - eddp->skb_offset;
+- src = eddp->skb->data + eddp->skb_offset;
+- } else {
+- frag = &skb_shinfo(eddp->skb)->
+- frags[eddp->frag];
+- left_in_frag = frag->size - eddp->frag_offset;
+- src = (u8 *)(
+- (page_to_pfn(frag->page) << PAGE_SHIFT)+
+- frag->page_offset + eddp->frag_offset);
+- }
+- if (left_in_frag <= 0) {
+- eddp->frag++;
+- eddp->frag_offset = 0;
+- continue;
+- }
+- copy_len = min(left_in_frag, len);
+- memcpy(dst, src, copy_len);
+- *hcsum = csum_partial(src, copy_len, *hcsum);
+- dst += copy_len;
+- eddp->frag_offset += copy_len;
+- eddp->skb_offset += copy_len;
+- len -= copy_len;
+- }
+- }
+-}
+-
+-static void
+-qeth_eddp_create_segment_data_tcp(struct qeth_eddp_context *ctx,
+- struct qeth_eddp_data *eddp, int data_len,
+- __wsum hcsum)
+-{
+- u8 *page;
+- int page_remainder;
+- int page_offset;
+- struct qeth_eddp_element *element;
+- int first_lap = 1;
+-
+- QETH_DBF_TEXT(trace, 5, "eddpcsdt");
+- page = ctx->pages[ctx->offset >> PAGE_SHIFT];
+- page_offset = ctx->offset % PAGE_SIZE;
+- element = &ctx->elements[ctx->num_elements];
+- while (data_len){
+- page_remainder = PAGE_SIZE - page_offset;
+- if (page_remainder < data_len){
+- qeth_eddp_copy_data_tcp(page + page_offset, eddp,
+- page_remainder, &hcsum);
+- element->length += page_remainder;
+- if (first_lap)
+- element->flags = SBAL_FLAGS_FIRST_FRAG;
+- else
+- element->flags = SBAL_FLAGS_MIDDLE_FRAG;
+- ctx->num_elements++;
+- element++;
+- data_len -= page_remainder;
+- ctx->offset += page_remainder;
+- page = ctx->pages[ctx->offset >> PAGE_SHIFT];
+- page_offset = 0;
+- element->addr = page + page_offset;
+- } else {
+- qeth_eddp_copy_data_tcp(page + page_offset, eddp,
+- data_len, &hcsum);
+- element->length += data_len;
+- if (!first_lap)
+- element->flags = SBAL_FLAGS_LAST_FRAG;
+- ctx->num_elements++;
+- ctx->offset += data_len;
+- data_len = 0;
+- }
+- first_lap = 0;
+- }
+- ((struct tcphdr *)eddp->th_in_ctx)->check = csum_fold(hcsum);
+-}
+-
+-static __wsum
+-qeth_eddp_check_tcp4_hdr(struct qeth_eddp_data *eddp, int data_len)
+-{
+- __wsum phcsum; /* pseudo header checksum */
+-
+- QETH_DBF_TEXT(trace, 5, "eddpckt4");
+- eddp->th.tcp.h.check = 0;
+- /* compute pseudo header checksum */
+- phcsum = csum_tcpudp_nofold(eddp->nh.ip4.h.saddr, eddp->nh.ip4.h.daddr,
+- eddp->thl + data_len, IPPROTO_TCP, 0);
+- /* compute checksum of tcp header */
+- return csum_partial((u8 *)&eddp->th, eddp->thl, phcsum);
+-}
+-
+-static __wsum
+-qeth_eddp_check_tcp6_hdr(struct qeth_eddp_data *eddp, int data_len)
+-{
+- __be32 proto;
+- __wsum phcsum; /* pseudo header checksum */
+-
+- QETH_DBF_TEXT(trace, 5, "eddpckt6");
+- eddp->th.tcp.h.check = 0;
+- /* compute pseudo header checksum */
+- phcsum = csum_partial((u8 *)&eddp->nh.ip6.h.saddr,
+- sizeof(struct in6_addr), 0);
+- phcsum = csum_partial((u8 *)&eddp->nh.ip6.h.daddr,
+- sizeof(struct in6_addr), phcsum);
+- proto = htonl(IPPROTO_TCP);
+- phcsum = csum_partial((u8 *)&proto, sizeof(u32), phcsum);
+- return phcsum;
+-}
+-
+-static struct qeth_eddp_data *
+-qeth_eddp_create_eddp_data(struct qeth_hdr *qh, u8 *nh, u8 nhl, u8 *th, u8 thl)
+-{
+- struct qeth_eddp_data *eddp;
+-
+- QETH_DBF_TEXT(trace, 5, "eddpcrda");
+- eddp = kzalloc(sizeof(struct qeth_eddp_data), GFP_ATOMIC);
+- if (eddp){
+- eddp->nhl = nhl;
+- eddp->thl = thl;
+- memcpy(&eddp->qh, qh, sizeof(struct qeth_hdr));
+- memcpy(&eddp->nh, nh, nhl);
+- memcpy(&eddp->th, th, thl);
+- eddp->frag = -1; /* initially we're in skb->data */
+- }
+- return eddp;
+-}
+-
+-static void
+-__qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
+- struct qeth_eddp_data *eddp)
+-{
+- struct tcphdr *tcph;
+- int data_len;
+- __wsum hcsum;
+-
+- QETH_DBF_TEXT(trace, 5, "eddpftcp");
+- eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl;
+- if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
+- eddp->skb_offset += sizeof(struct ethhdr);
+-#ifdef CONFIG_QETH_VLAN
+- if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
+- eddp->skb_offset += VLAN_HLEN;
+-#endif /* CONFIG_QETH_VLAN */
+- }
+- tcph = tcp_hdr(eddp->skb);
+- while (eddp->skb_offset < eddp->skb->len) {
+- data_len = min((int)skb_shinfo(eddp->skb)->gso_size,
+- (int)(eddp->skb->len - eddp->skb_offset));
+- /* prepare qdio hdr */
+- if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2){
+- eddp->qh.hdr.l2.pkt_length = data_len + ETH_HLEN +
+- eddp->nhl + eddp->thl;
+-#ifdef CONFIG_QETH_VLAN
+- if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
+- eddp->qh.hdr.l2.pkt_length += VLAN_HLEN;
+-#endif /* CONFIG_QETH_VLAN */
+- } else
+- eddp->qh.hdr.l3.length = data_len + eddp->nhl +
+- eddp->thl;
+- /* prepare ip hdr */
+- if (eddp->skb->protocol == htons(ETH_P_IP)){
+- eddp->nh.ip4.h.tot_len = htons(data_len + eddp->nhl +
+- eddp->thl);
+- eddp->nh.ip4.h.check = 0;
+- eddp->nh.ip4.h.check =
+- ip_fast_csum((u8 *)&eddp->nh.ip4.h,
+- eddp->nh.ip4.h.ihl);
+- } else
+- eddp->nh.ip6.h.payload_len = htons(data_len + eddp->thl);
+- /* prepare tcp hdr */
+- if (data_len == (eddp->skb->len - eddp->skb_offset)){
+- /* last segment -> set FIN and PSH flags */
+- eddp->th.tcp.h.fin = tcph->fin;
+- eddp->th.tcp.h.psh = tcph->psh;
+- }
+- if (eddp->skb->protocol == htons(ETH_P_IP))
+- hcsum = qeth_eddp_check_tcp4_hdr(eddp, data_len);
+- else
+- hcsum = qeth_eddp_check_tcp6_hdr(eddp, data_len);
+- /* fill the next segment into the context */
+- qeth_eddp_create_segment_hdrs(ctx, eddp, data_len);
+- qeth_eddp_create_segment_data_tcp(ctx, eddp, data_len, hcsum);
+- if (eddp->skb_offset >= eddp->skb->len)
+- break;
+- /* prepare headers for next round */
+- if (eddp->skb->protocol == htons(ETH_P_IP))
+- eddp->nh.ip4.h.id = htons(ntohs(eddp->nh.ip4.h.id) + 1);
+- eddp->th.tcp.h.seq = htonl(ntohl(eddp->th.tcp.h.seq) + data_len);
+- }
+-}
+-
+-static int
+-qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
+- struct sk_buff *skb, struct qeth_hdr *qhdr)
+-{
+- struct qeth_eddp_data *eddp = NULL;
+-
+- QETH_DBF_TEXT(trace, 5, "eddpficx");
+- /* create our segmentation headers and copy original headers */
+- if (skb->protocol == htons(ETH_P_IP))
+- eddp = qeth_eddp_create_eddp_data(qhdr,
+- skb_network_header(skb),
+- ip_hdrlen(skb),
+- skb_transport_header(skb),
+- tcp_hdrlen(skb));
+- else
+- eddp = qeth_eddp_create_eddp_data(qhdr,
+- skb_network_header(skb),
+- sizeof(struct ipv6hdr),
+- skb_transport_header(skb),
+- tcp_hdrlen(skb));
+-
+- if (eddp == NULL) {
+- QETH_DBF_TEXT(trace, 2, "eddpfcnm");
+- return -ENOMEM;
+- }
+- if (qhdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
+- skb_set_mac_header(skb, sizeof(struct qeth_hdr));
+- memcpy(&eddp->mac, eth_hdr(skb), ETH_HLEN);
+-#ifdef CONFIG_QETH_VLAN
+- if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) {
+- eddp->vlan[0] = skb->protocol;
+- eddp->vlan[1] = htons(vlan_tx_tag_get(skb));
+- }
+-#endif /* CONFIG_QETH_VLAN */
+- }
+- /* the next flags will only be set on the last segment */
+- eddp->th.tcp.h.fin = 0;
+- eddp->th.tcp.h.psh = 0;
+- eddp->skb = skb;
+- /* begin segmentation and fill context */
+- __qeth_eddp_fill_context_tcp(ctx, eddp);
+- kfree(eddp);
+- return 0;
+-}
+-
+-static void
+-qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, struct sk_buff *skb,
+- int hdr_len)
+-{
+- int skbs_per_page;
+-
+- QETH_DBF_TEXT(trace, 5, "eddpcanp");
+- /* can we put multiple skbs in one page? */
+- skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->gso_size + hdr_len);
+- if (skbs_per_page > 1){
+- ctx->num_pages = (skb_shinfo(skb)->gso_segs + 1) /
+- skbs_per_page + 1;
+- ctx->elements_per_skb = 1;
+- } else {
+- /* no -> how many elements per skb? */
+- ctx->elements_per_skb = (skb_shinfo(skb)->gso_size + hdr_len +
+- PAGE_SIZE) >> PAGE_SHIFT;
+- ctx->num_pages = ctx->elements_per_skb *
+- (skb_shinfo(skb)->gso_segs + 1);
+- }
+- ctx->num_elements = ctx->elements_per_skb *
+- (skb_shinfo(skb)->gso_segs + 1);
+-}
+-
+-static struct qeth_eddp_context *
+-qeth_eddp_create_context_generic(struct qeth_card *card, struct sk_buff *skb,
+- int hdr_len)
+-{
+- struct qeth_eddp_context *ctx = NULL;
+- u8 *addr;
+- int i;
+-
+- QETH_DBF_TEXT(trace, 5, "creddpcg");
+- /* create the context and allocate pages */
+- ctx = kzalloc(sizeof(struct qeth_eddp_context), GFP_ATOMIC);
+- if (ctx == NULL){
+- QETH_DBF_TEXT(trace, 2, "ceddpcn1");
+- return NULL;
+- }
+- ctx->type = QETH_LARGE_SEND_EDDP;
+- qeth_eddp_calc_num_pages(ctx, skb, hdr_len);
+- if (ctx->elements_per_skb > QETH_MAX_BUFFER_ELEMENTS(card)){
+- QETH_DBF_TEXT(trace, 2, "ceddpcis");
+- kfree(ctx);
+- return NULL;
+- }
+- ctx->pages = kcalloc(ctx->num_pages, sizeof(u8 *), GFP_ATOMIC);
+- if (ctx->pages == NULL){
+- QETH_DBF_TEXT(trace, 2, "ceddpcn2");
+- kfree(ctx);
+- return NULL;
+- }
+- for (i = 0; i < ctx->num_pages; ++i){
+- addr = (u8 *)__get_free_page(GFP_ATOMIC);
+- if (addr == NULL){
+- QETH_DBF_TEXT(trace, 2, "ceddpcn3");
+- ctx->num_pages = i;
+- qeth_eddp_free_context(ctx);
+- return NULL;
+- }
+- memset(addr, 0, PAGE_SIZE);
+- ctx->pages[i] = addr;
+- }
+- ctx->elements = kcalloc(ctx->num_elements,
+- sizeof(struct qeth_eddp_element), GFP_ATOMIC);
+- if (ctx->elements == NULL){
+- QETH_DBF_TEXT(trace, 2, "ceddpcn4");
+- qeth_eddp_free_context(ctx);
+- return NULL;
+- }
+- /* reset num_elements; will be incremented again in fill_buffer to
+- * reflect number of actually used elements */
+- ctx->num_elements = 0;
+- return ctx;
+-}
+-
+-static struct qeth_eddp_context *
+-qeth_eddp_create_context_tcp(struct qeth_card *card, struct sk_buff *skb,
+- struct qeth_hdr *qhdr)
+-{
+- struct qeth_eddp_context *ctx = NULL;
+-
+- QETH_DBF_TEXT(trace, 5, "creddpct");
+- if (skb->protocol == htons(ETH_P_IP))
+- ctx = qeth_eddp_create_context_generic(card, skb,
+- (sizeof(struct qeth_hdr) +
+- ip_hdrlen(skb) +
+- tcp_hdrlen(skb)));
+- else if (skb->protocol == htons(ETH_P_IPV6))
+- ctx = qeth_eddp_create_context_generic(card, skb,
+- sizeof(struct qeth_hdr) + sizeof(struct ipv6hdr) +
+- tcp_hdrlen(skb));
+- else
+- QETH_DBF_TEXT(trace, 2, "cetcpinv");
+-
+- if (ctx == NULL) {
+- QETH_DBF_TEXT(trace, 2, "creddpnl");
+- return NULL;
+- }
+- if (qeth_eddp_fill_context_tcp(ctx, skb, qhdr)){
+- QETH_DBF_TEXT(trace, 2, "ceddptfe");
+- qeth_eddp_free_context(ctx);
+- return NULL;
+- }
+- atomic_set(&ctx->refcnt, 1);
+- return ctx;
+-}
+-
+-struct qeth_eddp_context *
+-qeth_eddp_create_context(struct qeth_card *card, struct sk_buff *skb,
+- struct qeth_hdr *qhdr, unsigned char sk_protocol)
+-{
+- QETH_DBF_TEXT(trace, 5, "creddpc");
+- switch (sk_protocol) {
+- case IPPROTO_TCP:
+- return qeth_eddp_create_context_tcp(card, skb, qhdr);
+- default:
+- QETH_DBF_TEXT(trace, 2, "eddpinvp");
+- }
+- return NULL;
+-}
+diff --git a/drivers/s390/net/qeth_eddp.h b/drivers/s390/net/qeth_eddp.h
+deleted file mode 100644
+index 52910c9..0000000
+--- a/drivers/s390/net/qeth_eddp.h
++++ /dev/null
+@@ -1,84 +0,0 @@
+-/*
+- * linux/drivers/s390/net/qeth_eddp.h
+- *
+- * Header file for qeth enhanced device driver packing.
+- *
+- * Copyright 2004 IBM Corporation
+- *
+- * Author(s): Thomas Spatzier <tspat at de.ibm.com>
+- *
+- */
+-#ifndef __QETH_EDDP_H__
+-#define __QETH_EDDP_H__
+-
+-struct qeth_eddp_element {
+- u32 flags;
+- u32 length;
+- void *addr;
+-};
+-
+-struct qeth_eddp_context {
+- atomic_t refcnt;
+- enum qeth_large_send_types type;
+- int num_pages; /* # of allocated pages */
+- u8 **pages; /* pointers to pages */
+- int offset; /* offset in ctx during creation */
+- int num_elements; /* # of required 'SBALEs' */
+- struct qeth_eddp_element *elements; /* array of 'SBALEs' */
+- int elements_per_skb; /* # of 'SBALEs' per skb **/
+-};
+-
+-struct qeth_eddp_context_reference {
+- struct list_head list;
+- struct qeth_eddp_context *ctx;
+-};
+-
+-extern struct qeth_eddp_context *
+-qeth_eddp_create_context(struct qeth_card *,struct sk_buff *,
+- struct qeth_hdr *, unsigned char);
+-
+-extern void
+-qeth_eddp_put_context(struct qeth_eddp_context *);
+-
+-extern int
+-qeth_eddp_fill_buffer(struct qeth_qdio_out_q *,struct qeth_eddp_context *,int);
+-
+-extern void
+-qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *);
+-
+-extern int
+-qeth_eddp_check_buffers_for_context(struct qeth_qdio_out_q *,
+- struct qeth_eddp_context *);
+-/*
+- * Data used for fragmenting a IP packet.
+- */
+-struct qeth_eddp_data {
+- struct qeth_hdr qh;
+- struct ethhdr mac;
+- __be16 vlan[2];
+- union {
+- struct {
+- struct iphdr h;
+- u8 options[40];
+- } ip4;
+- struct {
+- struct ipv6hdr h;
+- } ip6;
+- } nh;
+- u8 nhl;
+- void *nh_in_ctx; /* address of nh within the ctx */
+- union {
+- struct {
+- struct tcphdr h;
+- u8 options[40];
+- } tcp;
+- } th;
+- u8 thl;
+- void *th_in_ctx; /* address of th within the ctx */
+- struct sk_buff *skb;
+- int skb_offset;
+- int frag;
+- int frag_offset;
+-} __attribute__ ((packed));
+-
+-#endif /* __QETH_EDDP_H__ */
+diff --git a/drivers/s390/net/qeth_fs.h b/drivers/s390/net/qeth_fs.h
+deleted file mode 100644
+index 61faf05..0000000
+--- a/drivers/s390/net/qeth_fs.h
++++ /dev/null
+@@ -1,168 +0,0 @@
+-/*
+- * linux/drivers/s390/net/qeth_fs.h
+- *
+- * Linux on zSeries OSA Express and HiperSockets support.
+- *
+- * This header file contains definitions related to sysfs and procfs.
+- *
+- * Copyright 2000,2003 IBM Corporation
+- * Author(s): Thomas Spatzier <tspat at de.ibm.com>
+- *
+- */
+-#ifndef __QETH_FS_H__
+-#define __QETH_FS_H__
+-
+-#ifdef CONFIG_PROC_FS
+-extern int
+-qeth_create_procfs_entries(void);
+-
+-extern void
+-qeth_remove_procfs_entries(void);
+-#else
+-static inline int
+-qeth_create_procfs_entries(void)
+-{
+- return 0;
+-}
+-
+-static inline void
+-qeth_remove_procfs_entries(void)
+-{
+-}
+-#endif /* CONFIG_PROC_FS */
+-
+-extern int
+-qeth_create_device_attributes(struct device *dev);
+-
+-extern void
+-qeth_remove_device_attributes(struct device *dev);
+-
+-extern int
+-qeth_create_device_attributes_osn(struct device *dev);
+-
+-extern void
+-qeth_remove_device_attributes_osn(struct device *dev);
+-
+-extern int
+-qeth_create_driver_attributes(void);
+-
+-extern void
+-qeth_remove_driver_attributes(void);
+-
+-/*
+- * utility functions used in qeth_proc.c and qeth_sys.c
+- */
+-
+-static inline const char *
+-qeth_get_checksum_str(struct qeth_card *card)
+-{
+- if (card->options.checksum_type == SW_CHECKSUMMING)
+- return "sw";
+- else if (card->options.checksum_type == HW_CHECKSUMMING)
+- return "hw";
+- else
+- return "no";
+-}
+-
+-static inline const char *
+-qeth_get_prioq_str(struct qeth_card *card, char *buf)
+-{
+- if (card->qdio.do_prio_queueing == QETH_NO_PRIO_QUEUEING)
+- sprintf(buf, "always_q_%i", card->qdio.default_out_queue);
+- else
+- strcpy(buf, (card->qdio.do_prio_queueing ==
+- QETH_PRIO_Q_ING_PREC)?
+- "by_prec." : "by_ToS");
+- return buf;
+-}
+-
+-static inline const char *
+-qeth_get_bufsize_str(struct qeth_card *card)
+-{
+- if (card->qdio.in_buf_size == 16384)
+- return "16k";
+- else if (card->qdio.in_buf_size == 24576)
+- return "24k";
+- else if (card->qdio.in_buf_size == 32768)
+- return "32k";
+- else if (card->qdio.in_buf_size == 40960)
+- return "40k";
+- else
+- return "64k";
+-}
+-
+-static inline const char *
+-qeth_get_cardname(struct qeth_card *card)
+-{
+- if (card->info.guestlan) {
+- switch (card->info.type) {
+- case QETH_CARD_TYPE_OSAE:
+- return " Guest LAN QDIO";
+- case QETH_CARD_TYPE_IQD:
+- return " Guest LAN Hiper";
+- default:
+- return " unknown";
+- }
+- } else {
+- switch (card->info.type) {
+- case QETH_CARD_TYPE_OSAE:
+- return " OSD Express";
+- case QETH_CARD_TYPE_IQD:
+- return " HiperSockets";
+- case QETH_CARD_TYPE_OSN:
+- return " OSN QDIO";
+- default:
+- return " unknown";
+- }
+- }
+- return " n/a";
+-}
+-
+-/* max length to be returned: 14 */
+-static inline const char *
+-qeth_get_cardname_short(struct qeth_card *card)
+-{
+- if (card->info.guestlan){
+- switch (card->info.type){
+- case QETH_CARD_TYPE_OSAE:
+- return "GuestLAN QDIO";
+- case QETH_CARD_TYPE_IQD:
+- return "GuestLAN Hiper";
+- default:
+- return "unknown";
+- }
+- } else {
+- switch (card->info.type) {
+- case QETH_CARD_TYPE_OSAE:
+- switch (card->info.link_type) {
+- case QETH_LINK_TYPE_FAST_ETH:
+- return "OSD_100";
+- case QETH_LINK_TYPE_HSTR:
+- return "HSTR";
+- case QETH_LINK_TYPE_GBIT_ETH:
+- return "OSD_1000";
+- case QETH_LINK_TYPE_10GBIT_ETH:
+- return "OSD_10GIG";
+- case QETH_LINK_TYPE_LANE_ETH100:
+- return "OSD_FE_LANE";
+- case QETH_LINK_TYPE_LANE_TR:
+- return "OSD_TR_LANE";
+- case QETH_LINK_TYPE_LANE_ETH1000:
+- return "OSD_GbE_LANE";
+- case QETH_LINK_TYPE_LANE:
+- return "OSD_ATM_LANE";
+- default:
+- return "OSD_Express";
+- }
+- case QETH_CARD_TYPE_IQD:
+- return "HiperSockets";
+- case QETH_CARD_TYPE_OSN:
+- return "OSN";
+- default:
+- return "unknown";
+- }
+- }
+- return "n/a";
+-}
+-
+-#endif /* __QETH_FS_H__ */
+diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
+new file mode 100644
+index 0000000..3921d16
+--- /dev/null
++++ b/drivers/s390/net/qeth_l2_main.c
+@@ -0,0 +1,1234 @@
++/*
++ * drivers/s390/net/qeth_l2_main.c
++ *
++ * Copyright IBM Corp. 2007
++ * Author(s): Utz Bacher <utz.bacher at de.ibm.com>,
++ * Frank Pavlic <fpavlic at de.ibm.com>,
++ * Thomas Spatzier <tspat at de.ibm.com>,
++ * Frank Blaschka <frank.blaschka at de.ibm.com>
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/string.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/etherdevice.h>
++#include <linux/mii.h>
++#include <linux/ip.h>
++
++#include <asm/s390_rdev.h>
++
++#include "qeth_core.h"
++#include "qeth_core_offl.h"
++
++#define QETH_DBF_TXT_BUF qeth_l2_dbf_txt_buf
++static DEFINE_PER_CPU(char[256], qeth_l2_dbf_txt_buf);
++
++static int qeth_l2_set_offline(struct ccwgroup_device *);
++static int qeth_l2_stop(struct net_device *);
++static int qeth_l2_send_delmac(struct qeth_card *, __u8 *);
++static int qeth_l2_send_setdelmac(struct qeth_card *, __u8 *,
++ enum qeth_ipa_cmds,
++ int (*reply_cb) (struct qeth_card *,
++ struct qeth_reply*,
++ unsigned long));
++static void qeth_l2_set_multicast_list(struct net_device *);
++static int qeth_l2_recover(void *);
++
++static int qeth_l2_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
++{
++ struct qeth_card *card = netdev_priv(dev);
++ struct mii_ioctl_data *mii_data;
++ int rc = 0;
++
++ if (!card)
++ return -ENODEV;
++
++ if ((card->state != CARD_STATE_UP) &&
++ (card->state != CARD_STATE_SOFTSETUP))
++ return -ENODEV;
++
++ if (card->info.type == QETH_CARD_TYPE_OSN)
++ return -EPERM;
++
++ switch (cmd) {
++ case SIOC_QETH_ADP_SET_SNMP_CONTROL:
++ rc = qeth_snmp_command(card, rq->ifr_ifru.ifru_data);
++ break;
++ case SIOC_QETH_GET_CARD_TYPE:
++ if ((card->info.type == QETH_CARD_TYPE_OSAE) &&
++ !card->info.guestlan)
++ return 1;
++ return 0;
++ break;
++ case SIOCGMIIPHY:
++ mii_data = if_mii(rq);
++ mii_data->phy_id = 0;
++ break;
++ case SIOCGMIIREG:
++ mii_data = if_mii(rq);
++ if (mii_data->phy_id != 0)
++ rc = -EINVAL;
++ else
++ mii_data->val_out = qeth_mdio_read(dev,
++ mii_data->phy_id, mii_data->reg_num);
++ break;
++ default:
++ rc = -EOPNOTSUPP;
++ }
++ if (rc)
++ QETH_DBF_TEXT_(TRACE, 2, "ioce%d", rc);
++ return rc;
++}
++
++static int qeth_l2_verify_dev(struct net_device *dev)
++{
++ struct qeth_card *card;
++ unsigned long flags;
++ int rc = 0;
++
++ read_lock_irqsave(&qeth_core_card_list.rwlock, flags);
++ list_for_each_entry(card, &qeth_core_card_list.list, list) {
++ if (card->dev == dev) {
++ rc = QETH_REAL_CARD;
++ break;
++ }
++ }
++ read_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
++
++ return rc;
++}
++
++static struct net_device *qeth_l2_netdev_by_devno(unsigned char *read_dev_no)
++{
++ struct qeth_card *card;
++ struct net_device *ndev;
++ unsigned char *readno;
++ __u16 temp_dev_no, card_dev_no;
++ char *endp;
++ unsigned long flags;
++
++ ndev = NULL;
++ memcpy(&temp_dev_no, read_dev_no, 2);
++ read_lock_irqsave(&qeth_core_card_list.rwlock, flags);
++ list_for_each_entry(card, &qeth_core_card_list.list, list) {
++ readno = CARD_RDEV_ID(card);
++ readno += (strlen(readno) - 4);
++ card_dev_no = simple_strtoul(readno, &endp, 16);
++ if (card_dev_no == temp_dev_no) {
++ ndev = card->dev;
++ break;
++ }
++ }
++ read_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
++ return ndev;
++}
++
++static int qeth_l2_send_setgroupmac_cb(struct qeth_card *card,
++ struct qeth_reply *reply,
++ unsigned long data)
++{
++ struct qeth_ipa_cmd *cmd;
++ __u8 *mac;
++
++ QETH_DBF_TEXT(TRACE, 2, "L2Sgmacb");
++ cmd = (struct qeth_ipa_cmd *) data;
++ mac = &cmd->data.setdelmac.mac[0];
++ /* MAC already registered, needed in couple/uncouple case */
++ if (cmd->hdr.return_code == 0x2005) {
++ PRINT_WARN("Group MAC %02x:%02x:%02x:%02x:%02x:%02x " \
++ "already existing on %s \n",
++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
++ QETH_CARD_IFNAME(card));
++ cmd->hdr.return_code = 0;
++ }
++ if (cmd->hdr.return_code)
++ PRINT_ERR("Could not set group MAC " \
++ "%02x:%02x:%02x:%02x:%02x:%02x on %s: %x\n",
++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
++ QETH_CARD_IFNAME(card), cmd->hdr.return_code);
++ return 0;
++}
++
++static int qeth_l2_send_setgroupmac(struct qeth_card *card, __u8 *mac)
++{
++ QETH_DBF_TEXT(TRACE, 2, "L2Sgmac");
++ return qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETGMAC,
++ qeth_l2_send_setgroupmac_cb);
++}
++
++static int qeth_l2_send_delgroupmac_cb(struct qeth_card *card,
++ struct qeth_reply *reply,
++ unsigned long data)
++{
++ struct qeth_ipa_cmd *cmd;
++ __u8 *mac;
++
++ QETH_DBF_TEXT(TRACE, 2, "L2Dgmacb");
++ cmd = (struct qeth_ipa_cmd *) data;
++ mac = &cmd->data.setdelmac.mac[0];
++ if (cmd->hdr.return_code)
++ PRINT_ERR("Could not delete group MAC " \
++ "%02x:%02x:%02x:%02x:%02x:%02x on %s: %x\n",
++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
++ QETH_CARD_IFNAME(card), cmd->hdr.return_code);
++ return 0;
++}
++
++static int qeth_l2_send_delgroupmac(struct qeth_card *card, __u8 *mac)
++{
++ QETH_DBF_TEXT(TRACE, 2, "L2Dgmac");
++ return qeth_l2_send_setdelmac(card, mac, IPA_CMD_DELGMAC,
++ qeth_l2_send_delgroupmac_cb);
++}
++
++static void qeth_l2_add_mc(struct qeth_card *card, __u8 *mac)
++{
++ struct qeth_mc_mac *mc;
++
++ mc = kmalloc(sizeof(struct qeth_mc_mac), GFP_ATOMIC);
++
++ if (!mc) {
++ PRINT_ERR("no mem vor mc mac address\n");
++ return;
++ }
++
++ memcpy(mc->mc_addr, mac, OSA_ADDR_LEN);
++ mc->mc_addrlen = OSA_ADDR_LEN;
++
++ if (!qeth_l2_send_setgroupmac(card, mac))
++ list_add_tail(&mc->list, &card->mc_list);
++ else
++ kfree(mc);
++}
++
++static void qeth_l2_del_all_mc(struct qeth_card *card)
++{
++ struct qeth_mc_mac *mc, *tmp;
++
++ spin_lock_bh(&card->mclock);
++ list_for_each_entry_safe(mc, tmp, &card->mc_list, list) {
++ qeth_l2_send_delgroupmac(card, mc->mc_addr);
++ list_del(&mc->list);
++ kfree(mc);
++ }
++ spin_unlock_bh(&card->mclock);
++}
++
++static void qeth_l2_get_packet_type(struct qeth_card *card,
++ struct qeth_hdr *hdr, struct sk_buff *skb)
++{
++ __u16 hdr_mac;
++
++ if (!memcmp(skb->data + QETH_HEADER_SIZE,
++ skb->dev->broadcast, 6)) {
++ /* broadcast? */
++ hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_BROADCAST;
++ return;
++ }
++ hdr_mac = *((__u16 *)skb->data);
++ /* tr multicast? */
++ switch (card->info.link_type) {
++ case QETH_LINK_TYPE_HSTR:
++ case QETH_LINK_TYPE_LANE_TR:
++ if ((hdr_mac == QETH_TR_MAC_NC) ||
++ (hdr_mac == QETH_TR_MAC_C))
++ hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_MULTICAST;
++ else
++ hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_UNICAST;
++ break;
++ /* eth or so multicast? */
++ default:
++ if ((hdr_mac == QETH_ETH_MAC_V4) ||
++ (hdr_mac == QETH_ETH_MAC_V6))
++ hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_MULTICAST;
++ else
++ hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_UNICAST;
++ }
++}
++
++static void qeth_l2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
++ struct sk_buff *skb, int ipv, int cast_type)
++{
++ struct vlan_ethhdr *veth = (struct vlan_ethhdr *)((skb->data) +
++ QETH_HEADER_SIZE);
++
++ memset(hdr, 0, sizeof(struct qeth_hdr));
++ hdr->hdr.l2.id = QETH_HEADER_TYPE_LAYER2;
++
++ /* set byte byte 3 to casting flags */
++ if (cast_type == RTN_MULTICAST)
++ hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_MULTICAST;
++ else if (cast_type == RTN_BROADCAST)
++ hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_BROADCAST;
++ else
++ qeth_l2_get_packet_type(card, hdr, skb);
++
++ hdr->hdr.l2.pkt_length = skb->len-QETH_HEADER_SIZE;
++ /* VSWITCH relies on the VLAN
++ * information to be present in
++ * the QDIO header */
++ if (veth->h_vlan_proto == __constant_htons(ETH_P_8021Q)) {
++ hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_VLAN;
++ hdr->hdr.l2.vlan_id = ntohs(veth->h_vlan_TCI);
++ }
++}
++
++static int qeth_l2_send_setdelvlan_cb(struct qeth_card *card,
++ struct qeth_reply *reply, unsigned long data)
++{
++ struct qeth_ipa_cmd *cmd;
++
++ QETH_DBF_TEXT(TRACE, 2, "L2sdvcb");
++ cmd = (struct qeth_ipa_cmd *) data;
++ if (cmd->hdr.return_code) {
++ PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. "
++ "Continuing\n", cmd->data.setdelvlan.vlan_id,
++ QETH_CARD_IFNAME(card), cmd->hdr.return_code);
++ QETH_DBF_TEXT_(TRACE, 2, "L2VL%4x", cmd->hdr.command);
++ QETH_DBF_TEXT_(TRACE, 2, "L2%s", CARD_BUS_ID(card));
++ QETH_DBF_TEXT_(TRACE, 2, "err%d", cmd->hdr.return_code);
++ }
++ return 0;
++}
++
++static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i,
++ enum qeth_ipa_cmds ipacmd)
++{
++ struct qeth_ipa_cmd *cmd;
++ struct qeth_cmd_buffer *iob;
++
++ QETH_DBF_TEXT_(TRACE, 4, "L2sdv%x", ipacmd);
++ iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
++ cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++ cmd->data.setdelvlan.vlan_id = i;
++ return qeth_send_ipa_cmd(card, iob,
++ qeth_l2_send_setdelvlan_cb, NULL);
++}
++
++static void qeth_l2_process_vlans(struct qeth_card *card, int clear)
++{
++ struct qeth_vlan_vid *id;
++ QETH_DBF_TEXT(TRACE, 3, "L2prcvln");
++ spin_lock_bh(&card->vlanlock);
++ list_for_each_entry(id, &card->vid_list, list) {
++ if (clear)
++ qeth_l2_send_setdelvlan(card, id->vid,
++ IPA_CMD_DELVLAN);
++ else
++ qeth_l2_send_setdelvlan(card, id->vid,
++ IPA_CMD_SETVLAN);
++ }
++ spin_unlock_bh(&card->vlanlock);
++}
++
++static void qeth_l2_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
++{
++ struct qeth_card *card = netdev_priv(dev);
++ struct qeth_vlan_vid *id;
++
++ QETH_DBF_TEXT_(TRACE, 4, "aid:%d", vid);
++ id = kmalloc(sizeof(struct qeth_vlan_vid), GFP_ATOMIC);
++ if (id) {
++ id->vid = vid;
++ qeth_l2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN);
++ spin_lock_bh(&card->vlanlock);
++ list_add_tail(&id->list, &card->vid_list);
++ spin_unlock_bh(&card->vlanlock);
++ } else {
++ PRINT_ERR("no memory for vid\n");
++ }
++}
++
++static void qeth_l2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
++{
++ struct qeth_vlan_vid *id, *tmpid = NULL;
++ struct qeth_card *card = netdev_priv(dev);
++
++ QETH_DBF_TEXT_(TRACE, 4, "kid:%d", vid);
++ spin_lock_bh(&card->vlanlock);
++ list_for_each_entry(id, &card->vid_list, list) {
++ if (id->vid == vid) {
++ list_del(&id->list);
++ tmpid = id;
++ break;
++ }
++ }
++ spin_unlock_bh(&card->vlanlock);
++ if (tmpid) {
++ qeth_l2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
++ kfree(tmpid);
++ }
++ qeth_l2_set_multicast_list(card->dev);
++}
++
++static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
++{
++ int rc = 0;
++
++ QETH_DBF_TEXT(SETUP , 2, "stopcard");
++ QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
++
++ qeth_set_allowed_threads(card, 0, 1);
++ if (qeth_wait_for_threads(card, ~QETH_RECOVER_THREAD))
++ return -ERESTARTSYS;
++ if (card->read.state == CH_STATE_UP &&
++ card->write.state == CH_STATE_UP &&
++ (card->state == CARD_STATE_UP)) {
++ if (recovery_mode &&
++ card->info.type != QETH_CARD_TYPE_OSN) {
++ qeth_l2_stop(card->dev);
++ } else {
++ rtnl_lock();
++ dev_close(card->dev);
++ rtnl_unlock();
++ }
++ if (!card->use_hard_stop) {
++ __u8 *mac = &card->dev->dev_addr[0];
++ rc = qeth_l2_send_delmac(card, mac);
++ QETH_DBF_TEXT_(SETUP, 2, "Lerr%d", rc);
++ }
++ card->state = CARD_STATE_SOFTSETUP;
++ }
++ if (card->state == CARD_STATE_SOFTSETUP) {
++ qeth_l2_process_vlans(card, 1);
++ qeth_l2_del_all_mc(card);
++ qeth_clear_ipacmd_list(card);
++ card->state = CARD_STATE_HARDSETUP;
++ }
++ if (card->state == CARD_STATE_HARDSETUP) {
++ qeth_qdio_clear_card(card, 0);
++ qeth_clear_qdio_buffers(card);
++ qeth_clear_working_pool_list(card);
++ card->state = CARD_STATE_DOWN;
++ }
++ if (card->state == CARD_STATE_DOWN) {
++ qeth_clear_cmd_buffers(&card->read);
++ qeth_clear_cmd_buffers(&card->write);
++ }
++ card->use_hard_stop = 0;
++ return rc;
++}
++
++static void qeth_l2_process_inbound_buffer(struct qeth_card *card,
++ struct qeth_qdio_buffer *buf, int index)
++{
++ struct qdio_buffer_element *element;
++ struct sk_buff *skb;
++ struct qeth_hdr *hdr;
++ int offset;
++ unsigned int len;
++
++ /* get first element of current buffer */
++ element = (struct qdio_buffer_element *)&buf->buffer->element[0];
++ offset = 0;
++ if (card->options.performance_stats)
++ card->perf_stats.bufs_rec++;
++ while ((skb = qeth_core_get_next_skb(card, buf->buffer, &element,
++ &offset, &hdr))) {
++ skb->dev = card->dev;
++ /* is device UP ? */
++ if (!(card->dev->flags & IFF_UP)) {
++ dev_kfree_skb_any(skb);
++ continue;
++ }
++
++ switch (hdr->hdr.l2.id) {
++ case QETH_HEADER_TYPE_LAYER2:
++ skb->pkt_type = PACKET_HOST;
++ skb->protocol = eth_type_trans(skb, skb->dev);
++ if (card->options.checksum_type == NO_CHECKSUMMING)
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++ else
++ skb->ip_summed = CHECKSUM_NONE;
++ if (skb->protocol == htons(ETH_P_802_2))
++ *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
++ len = skb->len;
++ netif_rx(skb);
++ break;
++ case QETH_HEADER_TYPE_OSN:
++ skb_push(skb, sizeof(struct qeth_hdr));
++ skb_copy_to_linear_data(skb, hdr,
++ sizeof(struct qeth_hdr));
++ len = skb->len;
++ card->osn_info.data_cb(skb);
++ break;
++ default:
++ dev_kfree_skb_any(skb);
++ QETH_DBF_TEXT(TRACE, 3, "inbunkno");
++ QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN);
++ continue;
++ }
++ card->dev->last_rx = jiffies;
++ card->stats.rx_packets++;
++ card->stats.rx_bytes += len;
++ }
++}
++
++static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac,
++ enum qeth_ipa_cmds ipacmd,
++ int (*reply_cb) (struct qeth_card *,
++ struct qeth_reply*,
++ unsigned long))
++{
++ struct qeth_ipa_cmd *cmd;
++ struct qeth_cmd_buffer *iob;
++
++ QETH_DBF_TEXT(TRACE, 2, "L2sdmac");
++ iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
++ cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++ cmd->data.setdelmac.mac_length = OSA_ADDR_LEN;
++ memcpy(&cmd->data.setdelmac.mac, mac, OSA_ADDR_LEN);
++ return qeth_send_ipa_cmd(card, iob, reply_cb, NULL);
++}
++
++static int qeth_l2_send_setmac_cb(struct qeth_card *card,
++ struct qeth_reply *reply,
++ unsigned long data)
++{
++ struct qeth_ipa_cmd *cmd;
++
++ QETH_DBF_TEXT(TRACE, 2, "L2Smaccb");
++ cmd = (struct qeth_ipa_cmd *) data;
++ if (cmd->hdr.return_code) {
++ QETH_DBF_TEXT_(TRACE, 2, "L2er%x", cmd->hdr.return_code);
++ card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
++ cmd->hdr.return_code = -EIO;
++ } else {
++ card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
++ memcpy(card->dev->dev_addr, cmd->data.setdelmac.mac,
++ OSA_ADDR_LEN);
++ PRINT_INFO("MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x "
++ "successfully registered on device %s\n",
++ card->dev->dev_addr[0], card->dev->dev_addr[1],
++ card->dev->dev_addr[2], card->dev->dev_addr[3],
++ card->dev->dev_addr[4], card->dev->dev_addr[5],
++ card->dev->name);
++ }
++ return 0;
++}
++
++static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac)
++{
++ QETH_DBF_TEXT(TRACE, 2, "L2Setmac");
++ return qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETVMAC,
++ qeth_l2_send_setmac_cb);
++}
++
++static int qeth_l2_send_delmac_cb(struct qeth_card *card,
++ struct qeth_reply *reply,
++ unsigned long data)
++{
++ struct qeth_ipa_cmd *cmd;
++
++ QETH_DBF_TEXT(TRACE, 2, "L2Dmaccb");
++ cmd = (struct qeth_ipa_cmd *) data;
++ if (cmd->hdr.return_code) {
++ QETH_DBF_TEXT_(TRACE, 2, "err%d", cmd->hdr.return_code);
++ cmd->hdr.return_code = -EIO;
++ return 0;
++ }
++ card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
++
++ return 0;
++}
++
++static int qeth_l2_send_delmac(struct qeth_card *card, __u8 *mac)
++{
++ QETH_DBF_TEXT(TRACE, 2, "L2Delmac");
++ if (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
++ return 0;
++ return qeth_l2_send_setdelmac(card, mac, IPA_CMD_DELVMAC,
++ qeth_l2_send_delmac_cb);
++}
++
++static int qeth_l2_request_initial_mac(struct qeth_card *card)
++{
++ int rc = 0;
++ char vendor_pre[] = {0x02, 0x00, 0x00};
++
++ QETH_DBF_TEXT(SETUP, 2, "doL2init");
++ QETH_DBF_TEXT_(SETUP, 2, "doL2%s", CARD_BUS_ID(card));
++
++ rc = qeth_query_setadapterparms(card);
++ if (rc) {
++ PRINT_WARN("could not query adapter parameters on device %s: "
++ "x%x\n", CARD_BUS_ID(card), rc);
++ }
++
++ if (card->info.guestlan) {
++ rc = qeth_setadpparms_change_macaddr(card);
++ if (rc) {
++ PRINT_WARN("couldn't get MAC address on "
++ "device %s: x%x\n",
++ CARD_BUS_ID(card), rc);
++ QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++ return rc;
++ }
++ QETH_DBF_HEX(SETUP, 2, card->dev->dev_addr, OSA_ADDR_LEN);
++ } else {
++ random_ether_addr(card->dev->dev_addr);
++ memcpy(card->dev->dev_addr, vendor_pre, 3);
++ }
++ return 0;
++}
++
++static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
++{
++ struct sockaddr *addr = p;
++ struct qeth_card *card = netdev_priv(dev);
++ int rc = 0;
++
++ QETH_DBF_TEXT(TRACE, 3, "setmac");
++
++ if (qeth_l2_verify_dev(dev) != QETH_REAL_CARD) {
++ QETH_DBF_TEXT(TRACE, 3, "setmcINV");
++ return -EOPNOTSUPP;
++ }
++
++ if (card->info.type == QETH_CARD_TYPE_OSN) {
++ PRINT_WARN("Setting MAC address on %s is not supported.\n",
++ dev->name);
++ QETH_DBF_TEXT(TRACE, 3, "setmcOSN");
++ return -EOPNOTSUPP;
++ }
++ QETH_DBF_TEXT_(TRACE, 3, "%s", CARD_BUS_ID(card));
++ QETH_DBF_HEX(TRACE, 3, addr->sa_data, OSA_ADDR_LEN);
++ rc = qeth_l2_send_delmac(card, &card->dev->dev_addr[0]);
++ if (!rc)
++ rc = qeth_l2_send_setmac(card, addr->sa_data);
++ return rc;
++}
++
++static void qeth_l2_set_multicast_list(struct net_device *dev)
++{
++ struct qeth_card *card = netdev_priv(dev);
++ struct dev_mc_list *dm;
++
++ if (card->info.type == QETH_CARD_TYPE_OSN)
++ return ;
++
++ QETH_DBF_TEXT(TRACE, 3, "setmulti");
++ qeth_l2_del_all_mc(card);
++ spin_lock_bh(&card->mclock);
++ for (dm = dev->mc_list; dm; dm = dm->next)
++ qeth_l2_add_mc(card, dm->dmi_addr);
++ spin_unlock_bh(&card->mclock);
++ if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
++ return;
++ qeth_setadp_promisc_mode(card);
++}
++
++static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++ int rc;
++ struct qeth_hdr *hdr = NULL;
++ int elements = 0;
++ struct qeth_card *card = netdev_priv(dev);
++ struct sk_buff *new_skb = skb;
++ int ipv = qeth_get_ip_version(skb);
++ int cast_type = qeth_get_cast_type(card, skb);
++ struct qeth_qdio_out_q *queue = card->qdio.out_qs
++ [qeth_get_priority_queue(card, skb, ipv, cast_type)];
++ int tx_bytes = skb->len;
++ enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
++ struct qeth_eddp_context *ctx = NULL;
++
++ QETH_DBF_TEXT(TRACE, 6, "l2xmit");
++
++ if ((card->state != CARD_STATE_UP) || !card->lan_online) {
++ card->stats.tx_carrier_errors++;
++ goto tx_drop;
++ }
++
++ if ((card->info.type == QETH_CARD_TYPE_OSN) &&
++ (skb->protocol == htons(ETH_P_IPV6)))
++ goto tx_drop;
++
++ if (card->options.performance_stats) {
++ card->perf_stats.outbound_cnt++;
++ card->perf_stats.outbound_start_time = qeth_get_micros();
++ }
++ netif_stop_queue(dev);
++
++ if (skb_is_gso(skb))
++ large_send = QETH_LARGE_SEND_EDDP;
++
++ if (card->info.type == QETH_CARD_TYPE_OSN)
++ hdr = (struct qeth_hdr *)skb->data;
++ else {
++ new_skb = qeth_prepare_skb(card, skb, &hdr);
++ if (!new_skb)
++ goto tx_drop;
++ qeth_l2_fill_header(card, hdr, new_skb, ipv, cast_type);
++ }
++
++ if (large_send == QETH_LARGE_SEND_EDDP) {
++ ctx = qeth_eddp_create_context(card, new_skb, hdr,
++ skb->sk->sk_protocol);
++ if (ctx == NULL) {
++ PRINT_WARN("could not create eddp context\n");
++ goto tx_drop;
++ }
++ } else {
++ elements = qeth_get_elements_no(card, (void *)hdr, new_skb, 0);
++ if (!elements)
++ goto tx_drop;
++ }
++
++ if ((large_send == QETH_LARGE_SEND_NO) &&
++ (skb->ip_summed == CHECKSUM_PARTIAL))
++ qeth_tx_csum(new_skb);
++
++ if (card->info.type != QETH_CARD_TYPE_IQD)
++ rc = qeth_do_send_packet(card, queue, new_skb, hdr,
++ elements, ctx);
++ else
++ rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr,
++ elements, ctx);
++ if (!rc) {
++ card->stats.tx_packets++;
++ card->stats.tx_bytes += tx_bytes;
++ if (new_skb != skb)
++ dev_kfree_skb_any(skb);
++ if (card->options.performance_stats) {
++ if (large_send != QETH_LARGE_SEND_NO) {
++ card->perf_stats.large_send_bytes += tx_bytes;
++ card->perf_stats.large_send_cnt++;
++ }
++ if (skb_shinfo(new_skb)->nr_frags > 0) {
++ card->perf_stats.sg_skbs_sent++;
++ /* nr_frags + skb->data */
++ card->perf_stats.sg_frags_sent +=
++ skb_shinfo(new_skb)->nr_frags + 1;
++ }
++ }
++
++ if (ctx != NULL) {
++ qeth_eddp_put_context(ctx);
++ dev_kfree_skb_any(new_skb);
++ }
++ } else {
++ if (ctx != NULL)
++ qeth_eddp_put_context(ctx);
++
++ if (rc == -EBUSY) {
++ if (new_skb != skb)
++ dev_kfree_skb_any(new_skb);
++ return NETDEV_TX_BUSY;
++ } else
++ goto tx_drop;
++ }
++
++ netif_wake_queue(dev);
++ if (card->options.performance_stats)
++ card->perf_stats.outbound_time += qeth_get_micros() -
++ card->perf_stats.outbound_start_time;
++ return rc;
++
++tx_drop:
++ card->stats.tx_dropped++;
++ card->stats.tx_errors++;
++ if ((new_skb != skb) && new_skb)
++ dev_kfree_skb_any(new_skb);
++ dev_kfree_skb_any(skb);
++ return NETDEV_TX_OK;
++}
++
++static void qeth_l2_qdio_input_handler(struct ccw_device *ccwdev,
++ unsigned int status, unsigned int qdio_err,
++ unsigned int siga_err, unsigned int queue,
++ int first_element, int count, unsigned long card_ptr)
++{
++ struct net_device *net_dev;
++ struct qeth_card *card;
++ struct qeth_qdio_buffer *buffer;
++ int index;
++ int i;
++
++ QETH_DBF_TEXT(TRACE, 6, "qdinput");
++ card = (struct qeth_card *) card_ptr;
++ net_dev = card->dev;
++ if (card->options.performance_stats) {
++ card->perf_stats.inbound_cnt++;
++ card->perf_stats.inbound_start_time = qeth_get_micros();
++ }
++ if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
++ if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION) {
++ QETH_DBF_TEXT(TRACE, 1, "qdinchk");
++ QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
++ QETH_DBF_TEXT_(TRACE, 1, "%04X%04X", first_element,
++ count);
++ QETH_DBF_TEXT_(TRACE, 1, "%04X%04X", queue, status);
++ qeth_schedule_recovery(card);
++ return;
++ }
++ }
++ for (i = first_element; i < (first_element + count); ++i) {
++ index = i % QDIO_MAX_BUFFERS_PER_Q;
++ buffer = &card->qdio.in_q->bufs[index];
++ if (!((status & QDIO_STATUS_LOOK_FOR_ERROR) &&
++ qeth_check_qdio_errors(buffer->buffer,
++ qdio_err, siga_err, "qinerr")))
++ qeth_l2_process_inbound_buffer(card, buffer, index);
++ /* clear buffer and give back to hardware */
++ qeth_put_buffer_pool_entry(card, buffer->pool_entry);
++ qeth_queue_input_buffer(card, index);
++ }
++ if (card->options.performance_stats)
++ card->perf_stats.inbound_time += qeth_get_micros() -
++ card->perf_stats.inbound_start_time;
++}
++
++static int qeth_l2_open(struct net_device *dev)
++{
++ struct qeth_card *card = netdev_priv(dev);
++
++ QETH_DBF_TEXT(TRACE, 4, "qethopen");
++ if (card->state != CARD_STATE_SOFTSETUP)
++ return -ENODEV;
++
++ if ((card->info.type != QETH_CARD_TYPE_OSN) &&
++ (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))) {
++ QETH_DBF_TEXT(TRACE, 4, "nomacadr");
++ return -EPERM;
++ }
++ card->data.state = CH_STATE_UP;
++ card->state = CARD_STATE_UP;
++ card->dev->flags |= IFF_UP;
++ netif_start_queue(dev);
++
++ if (!card->lan_online && netif_carrier_ok(dev))
++ netif_carrier_off(dev);
++ return 0;
++}
++
++
++static int qeth_l2_stop(struct net_device *dev)
++{
++ struct qeth_card *card = netdev_priv(dev);
++
++ QETH_DBF_TEXT(TRACE, 4, "qethstop");
++ netif_tx_disable(dev);
++ card->dev->flags &= ~IFF_UP;
++ if (card->state == CARD_STATE_UP)
++ card->state = CARD_STATE_SOFTSETUP;
++ return 0;
++}
++
++static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
++{
++ struct qeth_card *card = dev_get_drvdata(&gdev->dev);
++
++ INIT_LIST_HEAD(&card->vid_list);
++ INIT_LIST_HEAD(&card->mc_list);
++ card->options.layer2 = 1;
++ card->discipline.input_handler = (qdio_handler_t *)
++ qeth_l2_qdio_input_handler;
++ card->discipline.output_handler = (qdio_handler_t *)
++ qeth_qdio_output_handler;
++ card->discipline.recover = qeth_l2_recover;
++ return 0;
++}
++
++static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
++{
++ struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
++
++ wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
++
++ if (cgdev->state == CCWGROUP_ONLINE) {
++ card->use_hard_stop = 1;
++ qeth_l2_set_offline(cgdev);
++ }
++
++ if (card->dev) {
++ unregister_netdev(card->dev);
++ card->dev = NULL;
++ }
++
++ qeth_l2_del_all_mc(card);
++ return;
++}
++
++static struct ethtool_ops qeth_l2_ethtool_ops = {
++ .get_link = ethtool_op_get_link,
++ .get_tx_csum = ethtool_op_get_tx_csum,
++ .set_tx_csum = ethtool_op_set_tx_hw_csum,
++ .get_sg = ethtool_op_get_sg,
++ .set_sg = ethtool_op_set_sg,
++ .get_tso = ethtool_op_get_tso,
++ .set_tso = ethtool_op_set_tso,
++ .get_strings = qeth_core_get_strings,
++ .get_ethtool_stats = qeth_core_get_ethtool_stats,
++ .get_stats_count = qeth_core_get_stats_count,
++ .get_drvinfo = qeth_core_get_drvinfo,
++};
++
++static struct ethtool_ops qeth_l2_osn_ops = {
++ .get_strings = qeth_core_get_strings,
++ .get_ethtool_stats = qeth_core_get_ethtool_stats,
++ .get_stats_count = qeth_core_get_stats_count,
++ .get_drvinfo = qeth_core_get_drvinfo,
++};
++
++static int qeth_l2_setup_netdev(struct qeth_card *card)
++{
++ switch (card->info.type) {
++ case QETH_CARD_TYPE_OSAE:
++ card->dev = alloc_etherdev(0);
++ break;
++ case QETH_CARD_TYPE_IQD:
++ card->dev = alloc_netdev(0, "hsi%d", ether_setup);
++ break;
++ case QETH_CARD_TYPE_OSN:
++ card->dev = alloc_netdev(0, "osn%d", ether_setup);
++ card->dev->flags |= IFF_NOARP;
++ break;
++ default:
++ card->dev = alloc_etherdev(0);
++ }
++
++ if (!card->dev)
++ return -ENODEV;
++
++ card->dev->priv = card;
++ card->dev->tx_timeout = &qeth_tx_timeout;
++ card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
++ card->dev->open = qeth_l2_open;
++ card->dev->stop = qeth_l2_stop;
++ card->dev->hard_start_xmit = qeth_l2_hard_start_xmit;
++ card->dev->do_ioctl = qeth_l2_do_ioctl;
++ card->dev->get_stats = qeth_get_stats;
++ card->dev->change_mtu = qeth_change_mtu;
++ card->dev->set_multicast_list = qeth_l2_set_multicast_list;
++ card->dev->vlan_rx_kill_vid = qeth_l2_vlan_rx_kill_vid;
++ card->dev->vlan_rx_add_vid = qeth_l2_vlan_rx_add_vid;
++ card->dev->set_mac_address = qeth_l2_set_mac_address;
++ card->dev->mtu = card->info.initial_mtu;
++ if (card->info.type != QETH_CARD_TYPE_OSN)
++ SET_ETHTOOL_OPS(card->dev, &qeth_l2_ethtool_ops);
++ else
++ SET_ETHTOOL_OPS(card->dev, &qeth_l2_osn_ops);
++ card->dev->features |= NETIF_F_HW_VLAN_FILTER;
++ card->info.broadcast_capable = 1;
++ qeth_l2_request_initial_mac(card);
++ SET_NETDEV_DEV(card->dev, &card->gdev->dev);
++ return register_netdev(card->dev);
++}
++
++static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
++{
++ struct qeth_card *card = dev_get_drvdata(&gdev->dev);
++ int rc = 0;
++ enum qeth_card_states recover_flag;
++
++ BUG_ON(!card);
++ QETH_DBF_TEXT(SETUP, 2, "setonlin");
++ QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
++
++ qeth_set_allowed_threads(card, QETH_RECOVER_THREAD, 1);
++ if (qeth_wait_for_threads(card, ~QETH_RECOVER_THREAD)) {
++ PRINT_WARN("set_online of card %s interrupted by user!\n",
++ CARD_BUS_ID(card));
++ return -ERESTARTSYS;
++ }
++
++ recover_flag = card->state;
++ rc = ccw_device_set_online(CARD_RDEV(card));
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++ return -EIO;
++ }
++ rc = ccw_device_set_online(CARD_WDEV(card));
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++ return -EIO;
++ }
++ rc = ccw_device_set_online(CARD_DDEV(card));
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++ return -EIO;
++ }
++
++ rc = qeth_core_hardsetup_card(card);
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
++ goto out_remove;
++ }
++
++ if (!card->dev && qeth_l2_setup_netdev(card))
++ goto out_remove;
++
++ if (card->info.type != QETH_CARD_TYPE_OSN)
++ qeth_l2_send_setmac(card, &card->dev->dev_addr[0]);
++
++ card->state = CARD_STATE_HARDSETUP;
++ qeth_print_status_message(card);
++
++ /* softsetup */
++ QETH_DBF_TEXT(SETUP, 2, "softsetp");
++
++ rc = qeth_send_startlan(card);
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++ if (rc == 0xe080) {
++ PRINT_WARN("LAN on card %s if offline! "
++ "Waiting for STARTLAN from card.\n",
++ CARD_BUS_ID(card));
++ card->lan_online = 0;
++ }
++ return rc;
++ } else
++ card->lan_online = 1;
++
++ if (card->info.type != QETH_CARD_TYPE_OSN) {
++ qeth_set_large_send(card, card->options.large_send);
++ qeth_l2_process_vlans(card, 0);
++ }
++
++ netif_tx_disable(card->dev);
++
++ rc = qeth_init_qdio_queues(card);
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);
++ goto out_remove;
++ }
++ card->state = CARD_STATE_SOFTSETUP;
++ netif_carrier_on(card->dev);
++
++ qeth_set_allowed_threads(card, 0xffffffff, 0);
++ if (recover_flag == CARD_STATE_RECOVER) {
++ if (recovery_mode &&
++ card->info.type != QETH_CARD_TYPE_OSN) {
++ qeth_l2_open(card->dev);
++ } else {
++ rtnl_lock();
++ dev_open(card->dev);
++ rtnl_unlock();
++ }
++ /* this also sets saved unicast addresses */
++ qeth_l2_set_multicast_list(card->dev);
++ }
++ /* let user_space know that device is online */
++ kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
++ return 0;
++out_remove:
++ card->use_hard_stop = 1;
++ qeth_l2_stop_card(card, 0);
++ ccw_device_set_offline(CARD_DDEV(card));
++ ccw_device_set_offline(CARD_WDEV(card));
++ ccw_device_set_offline(CARD_RDEV(card));
++ if (recover_flag == CARD_STATE_RECOVER)
++ card->state = CARD_STATE_RECOVER;
++ else
++ card->state = CARD_STATE_DOWN;
++ return -ENODEV;
++}
++
++static int qeth_l2_set_online(struct ccwgroup_device *gdev)
++{
++ return __qeth_l2_set_online(gdev, 0);
++}
++
++static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev,
++ int recovery_mode)
++{
++ struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
++ int rc = 0, rc2 = 0, rc3 = 0;
++ enum qeth_card_states recover_flag;
++
++ QETH_DBF_TEXT(SETUP, 3, "setoffl");
++ QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *));
++
++ if (card->dev && netif_carrier_ok(card->dev))
++ netif_carrier_off(card->dev);
++ recover_flag = card->state;
++ if (qeth_l2_stop_card(card, recovery_mode) == -ERESTARTSYS) {
++ PRINT_WARN("Stopping card %s interrupted by user!\n",
++ CARD_BUS_ID(card));
++ return -ERESTARTSYS;
++ }
++ rc = ccw_device_set_offline(CARD_DDEV(card));
++ rc2 = ccw_device_set_offline(CARD_WDEV(card));
++ rc3 = ccw_device_set_offline(CARD_RDEV(card));
++ if (!rc)
++ rc = (rc2) ? rc2 : rc3;
++ if (rc)
++ QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++ if (recover_flag == CARD_STATE_UP)
++ card->state = CARD_STATE_RECOVER;
++ /* let user_space know that device is offline */
++ kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE);
++ return 0;
++}
++
++static int qeth_l2_set_offline(struct ccwgroup_device *cgdev)
++{
++ return __qeth_l2_set_offline(cgdev, 0);
++}
++
++static int qeth_l2_recover(void *ptr)
++{
++ struct qeth_card *card;
++ int rc = 0;
++
++ card = (struct qeth_card *) ptr;
++ QETH_DBF_TEXT(TRACE, 2, "recover1");
++ QETH_DBF_HEX(TRACE, 2, &card, sizeof(void *));
++ if (!qeth_do_run_thread(card, QETH_RECOVER_THREAD))
++ return 0;
++ QETH_DBF_TEXT(TRACE, 2, "recover2");
++ PRINT_WARN("Recovery of device %s started ...\n",
++ CARD_BUS_ID(card));
++ card->use_hard_stop = 1;
++ __qeth_l2_set_offline(card->gdev, 1);
++ rc = __qeth_l2_set_online(card->gdev, 1);
++ /* don't run another scheduled recovery */
++ qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
++ qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
++ if (!rc)
++ PRINT_INFO("Device %s successfully recovered!\n",
++ CARD_BUS_ID(card));
++ else
++ PRINT_INFO("Device %s could not be recovered!\n",
++ CARD_BUS_ID(card));
++ return 0;
++}
++
++static int __init qeth_l2_init(void)
++{
++ PRINT_INFO("register layer 2 discipline\n");
++ return 0;
++}
++
++static void __exit qeth_l2_exit(void)
++{
++ PRINT_INFO("unregister layer 2 discipline\n");
++}
++
++static void qeth_l2_shutdown(struct ccwgroup_device *gdev)
++{
++ struct qeth_card *card = dev_get_drvdata(&gdev->dev);
++ qeth_qdio_clear_card(card, 0);
++ qeth_clear_qdio_buffers(card);
++}
++
++struct ccwgroup_driver qeth_l2_ccwgroup_driver = {
++ .probe = qeth_l2_probe_device,
++ .remove = qeth_l2_remove_device,
++ .set_online = qeth_l2_set_online,
++ .set_offline = qeth_l2_set_offline,
++ .shutdown = qeth_l2_shutdown,
++};
++EXPORT_SYMBOL_GPL(qeth_l2_ccwgroup_driver);
++
++static int qeth_osn_send_control_data(struct qeth_card *card, int len,
++ struct qeth_cmd_buffer *iob)
++{
++ unsigned long flags;
++ int rc = 0;
++
++ QETH_DBF_TEXT(TRACE, 5, "osndctrd");
++
++ wait_event(card->wait_q,
++ atomic_cmpxchg(&card->write.irq_pending, 0, 1) == 0);
++ qeth_prepare_control_data(card, len, iob);
++ QETH_DBF_TEXT(TRACE, 6, "osnoirqp");
++ spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
++ rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
++ (addr_t) iob, 0, 0);
++ spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
++ if (rc) {
++ PRINT_WARN("qeth_osn_send_control_data: "
++ "ccw_device_start rc = %i\n", rc);
++ QETH_DBF_TEXT_(TRACE, 2, " err%d", rc);
++ qeth_release_buffer(iob->channel, iob);
++ atomic_set(&card->write.irq_pending, 0);
++ wake_up(&card->wait_q);
++ }
++ return rc;
++}
++
++static int qeth_osn_send_ipa_cmd(struct qeth_card *card,
++ struct qeth_cmd_buffer *iob, int data_len)
++{
++ u16 s1, s2;
++
++ QETH_DBF_TEXT(TRACE, 4, "osndipa");
++
++ qeth_prepare_ipa_cmd(card, iob, QETH_PROT_OSN2);
++ s1 = (u16)(IPA_PDU_HEADER_SIZE + data_len);
++ s2 = (u16)data_len;
++ memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
++ memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
++ memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
++ memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
++ return qeth_osn_send_control_data(card, s1, iob);
++}
++
++int qeth_osn_assist(struct net_device *dev, void *data, int data_len)
++{
++ struct qeth_cmd_buffer *iob;
++ struct qeth_card *card;
++ int rc;
++
++ QETH_DBF_TEXT(TRACE, 2, "osnsdmc");
++ if (!dev)
++ return -ENODEV;
++ card = netdev_priv(dev);
++ if (!card)
++ return -ENODEV;
++ if ((card->state != CARD_STATE_UP) &&
++ (card->state != CARD_STATE_SOFTSETUP))
++ return -ENODEV;
++ iob = qeth_wait_for_buffer(&card->write);
++ memcpy(iob->data+IPA_PDU_HEADER_SIZE, data, data_len);
++ rc = qeth_osn_send_ipa_cmd(card, iob, data_len);
++ return rc;
++}
++EXPORT_SYMBOL(qeth_osn_assist);
++
++int qeth_osn_register(unsigned char *read_dev_no, struct net_device **dev,
++ int (*assist_cb)(struct net_device *, void *),
++ int (*data_cb)(struct sk_buff *))
++{
++ struct qeth_card *card;
++
++ QETH_DBF_TEXT(TRACE, 2, "osnreg");
++ *dev = qeth_l2_netdev_by_devno(read_dev_no);
++ if (*dev == NULL)
++ return -ENODEV;
++ card = netdev_priv(*dev);
++ if (!card)
++ return -ENODEV;
++ if ((assist_cb == NULL) || (data_cb == NULL))
++ return -EINVAL;
++ card->osn_info.assist_cb = assist_cb;
++ card->osn_info.data_cb = data_cb;
++ return 0;
++}
++EXPORT_SYMBOL(qeth_osn_register);
++
++void qeth_osn_deregister(struct net_device *dev)
++{
++ struct qeth_card *card;
++
++ QETH_DBF_TEXT(TRACE, 2, "osndereg");
++ if (!dev)
++ return;
++ card = netdev_priv(dev);
++ if (!card)
++ return;
++ card->osn_info.assist_cb = NULL;
++ card->osn_info.data_cb = NULL;
++ return;
++}
++EXPORT_SYMBOL(qeth_osn_deregister);
++
++module_init(qeth_l2_init);
++module_exit(qeth_l2_exit);
++MODULE_AUTHOR("Frank Blaschka <frank.blaschka at de.ibm.com>");
++MODULE_DESCRIPTION("qeth layer 2 discipline");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/s390/net/qeth_l3.h b/drivers/s390/net/qeth_l3.h
+new file mode 100644
+index 0000000..1be3535
+--- /dev/null
++++ b/drivers/s390/net/qeth_l3.h
+@@ -0,0 +1,67 @@
++/*
++ * drivers/s390/net/qeth_l3.h
++ *
++ * Copyright IBM Corp. 2007
++ * Author(s): Utz Bacher <utz.bacher at de.ibm.com>,
++ * Frank Pavlic <fpavlic at de.ibm.com>,
++ * Thomas Spatzier <tspat at de.ibm.com>,
++ * Frank Blaschka <frank.blaschka at de.ibm.com>
++ */
++
++#ifndef __QETH_L3_H__
++#define __QETH_L3_H__
++
++#include "qeth_core.h"
++
++#define QETH_DBF_TXT_BUF qeth_l3_dbf_txt_buf
++DECLARE_PER_CPU(char[256], qeth_l3_dbf_txt_buf);
++
++struct qeth_ipaddr {
++ struct list_head entry;
++ enum qeth_ip_types type;
++ enum qeth_ipa_setdelip_flags set_flags;
++ enum qeth_ipa_setdelip_flags del_flags;
++ int is_multicast;
++ int users;
++ enum qeth_prot_versions proto;
++ unsigned char mac[OSA_ADDR_LEN];
++ union {
++ struct {
++ unsigned int addr;
++ unsigned int mask;
++ } a4;
++ struct {
++ struct in6_addr addr;
++ unsigned int pfxlen;
++ } a6;
++ } u;
++};
++
++struct qeth_ipato_entry {
++ struct list_head entry;
++ enum qeth_prot_versions proto;
++ char addr[16];
++ int mask_bits;
++};
++
++
++void qeth_l3_ipaddr4_to_string(const __u8 *, char *);
++int qeth_l3_string_to_ipaddr4(const char *, __u8 *);
++void qeth_l3_ipaddr6_to_string(const __u8 *, char *);
++int qeth_l3_string_to_ipaddr6(const char *, __u8 *);
++void qeth_l3_ipaddr_to_string(enum qeth_prot_versions, const __u8 *, char *);
++int qeth_l3_string_to_ipaddr(const char *, enum qeth_prot_versions, __u8 *);
++int qeth_l3_create_device_attributes(struct device *);
++void qeth_l3_remove_device_attributes(struct device *);
++int qeth_l3_setrouting_v4(struct qeth_card *);
++int qeth_l3_setrouting_v6(struct qeth_card *);
++int qeth_l3_add_ipato_entry(struct qeth_card *, struct qeth_ipato_entry *);
++void qeth_l3_del_ipato_entry(struct qeth_card *, enum qeth_prot_versions,
++ u8 *, int);
++int qeth_l3_add_vipa(struct qeth_card *, enum qeth_prot_versions, const u8 *);
++void qeth_l3_del_vipa(struct qeth_card *, enum qeth_prot_versions, const u8 *);
++int qeth_l3_add_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *);
++void qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions,
++ const u8 *);
++
++#endif /* __QETH_L3_H__ */
+diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
+new file mode 100644
+index 0000000..e1bfe56
+--- /dev/null
++++ b/drivers/s390/net/qeth_l3_main.c
+@@ -0,0 +1,3396 @@
++/*
++ * drivers/s390/net/qeth_l3_main.c
++ *
++ * Copyright IBM Corp. 2007
++ * Author(s): Utz Bacher <utz.bacher at de.ibm.com>,
++ * Frank Pavlic <fpavlic at de.ibm.com>,
++ * Thomas Spatzier <tspat at de.ibm.com>,
++ * Frank Blaschka <frank.blaschka at de.ibm.com>
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/string.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/etherdevice.h>
++#include <linux/mii.h>
++#include <linux/ip.h>
++#include <linux/reboot.h>
++#include <linux/inetdevice.h>
++#include <linux/igmp.h>
++
++#include <net/ip.h>
++#include <net/arp.h>
++
++#include <asm/s390_rdev.h>
++
++#include "qeth_l3.h"
++#include "qeth_core_offl.h"
++
++DEFINE_PER_CPU(char[256], qeth_l3_dbf_txt_buf);
++
++static int qeth_l3_set_offline(struct ccwgroup_device *);
++static int qeth_l3_recover(void *);
++static int qeth_l3_stop(struct net_device *);
++static void qeth_l3_set_multicast_list(struct net_device *);
++static int qeth_l3_neigh_setup(struct net_device *, struct neigh_parms *);
++static int qeth_l3_register_addr_entry(struct qeth_card *,
++ struct qeth_ipaddr *);
++static int qeth_l3_deregister_addr_entry(struct qeth_card *,
++ struct qeth_ipaddr *);
++static int __qeth_l3_set_online(struct ccwgroup_device *, int);
++static int __qeth_l3_set_offline(struct ccwgroup_device *, int);
++
++
++static int qeth_l3_isxdigit(char *buf)
++{
++ while (*buf) {
++ if (!isxdigit(*buf++))
++ return 0;
++ }
++ return 1;
++}
++
++void qeth_l3_ipaddr4_to_string(const __u8 *addr, char *buf)
++{
++ sprintf(buf, "%i.%i.%i.%i", addr[0], addr[1], addr[2], addr[3]);
++}
++
++int qeth_l3_string_to_ipaddr4(const char *buf, __u8 *addr)
++{
++ int count = 0, rc = 0;
++ int in[4];
++ char c;
++
++ rc = sscanf(buf, "%u.%u.%u.%u%c",
++ &in[0], &in[1], &in[2], &in[3], &c);
++ if (rc != 4 && (rc != 5 || c != '\n'))
++ return -EINVAL;
++ for (count = 0; count < 4; count++) {
++ if (in[count] > 255)
++ return -EINVAL;
++ addr[count] = in[count];
++ }
++ return 0;
++}
++
++void qeth_l3_ipaddr6_to_string(const __u8 *addr, char *buf)
++{
++ sprintf(buf, "%02x%02x:%02x%02x:%02x%02x:%02x%02x"
++ ":%02x%02x:%02x%02x:%02x%02x:%02x%02x",
++ addr[0], addr[1], addr[2], addr[3],
++ addr[4], addr[5], addr[6], addr[7],
++ addr[8], addr[9], addr[10], addr[11],
++ addr[12], addr[13], addr[14], addr[15]);
++}
++
++int qeth_l3_string_to_ipaddr6(const char *buf, __u8 *addr)
++{
++ const char *end, *end_tmp, *start;
++ __u16 *in;
++ char num[5];
++ int num2, cnt, out, found, save_cnt;
++ unsigned short in_tmp[8] = {0, };
++
++ cnt = out = found = save_cnt = num2 = 0;
++ end = start = buf;
++ in = (__u16 *) addr;
++ memset(in, 0, 16);
++ while (*end) {
++ end = strchr(start, ':');
++ if (end == NULL) {
++ end = buf + strlen(buf);
++ end_tmp = strchr(start, '\n');
++ if (end_tmp != NULL)
++ end = end_tmp;
++ out = 1;
++ }
++ if ((end - start)) {
++ memset(num, 0, 5);
++ if ((end - start) > 4)
++ return -EINVAL;
++ memcpy(num, start, end - start);
++ if (!qeth_l3_isxdigit(num))
++ return -EINVAL;
++ sscanf(start, "%x", &num2);
++ if (found)
++ in_tmp[save_cnt++] = num2;
++ else
++ in[cnt++] = num2;
++ if (out)
++ break;
++ } else {
++ if (found)
++ return -EINVAL;
++ found = 1;
++ }
++ start = ++end;
++ }
++ if (cnt + save_cnt > 8)
++ return -EINVAL;
++ cnt = 7;
++ while (save_cnt)
++ in[cnt--] = in_tmp[--save_cnt];
++ return 0;
++}
++
++void qeth_l3_ipaddr_to_string(enum qeth_prot_versions proto, const __u8 *addr,
++ char *buf)
++{
++ if (proto == QETH_PROT_IPV4)
++ qeth_l3_ipaddr4_to_string(addr, buf);
++ else if (proto == QETH_PROT_IPV6)
++ qeth_l3_ipaddr6_to_string(addr, buf);
++}
++
++int qeth_l3_string_to_ipaddr(const char *buf, enum qeth_prot_versions proto,
++ __u8 *addr)
++{
++ if (proto == QETH_PROT_IPV4)
++ return qeth_l3_string_to_ipaddr4(buf, addr);
++ else if (proto == QETH_PROT_IPV6)
++ return qeth_l3_string_to_ipaddr6(buf, addr);
++ else
++ return -EINVAL;
++}
++
++static void qeth_l3_convert_addr_to_bits(u8 *addr, u8 *bits, int len)
++{
++ int i, j;
++ u8 octet;
++
++ for (i = 0; i < len; ++i) {
++ octet = addr[i];
++ for (j = 7; j >= 0; --j) {
++ bits[i*8 + j] = octet & 1;
++ octet >>= 1;
++ }
++ }
++}
++
++static int qeth_l3_is_addr_covered_by_ipato(struct qeth_card *card,
++ struct qeth_ipaddr *addr)
++{
++ struct qeth_ipato_entry *ipatoe;
++ u8 addr_bits[128] = {0, };
++ u8 ipatoe_bits[128] = {0, };
++ int rc = 0;
++
++ if (!card->ipato.enabled)
++ return 0;
++
++ qeth_l3_convert_addr_to_bits((u8 *) &addr->u, addr_bits,
++ (addr->proto == QETH_PROT_IPV4)? 4:16);
++ list_for_each_entry(ipatoe, &card->ipato.entries, entry) {
++ if (addr->proto != ipatoe->proto)
++ continue;
++ qeth_l3_convert_addr_to_bits(ipatoe->addr, ipatoe_bits,
++ (ipatoe->proto == QETH_PROT_IPV4) ?
++ 4 : 16);
++ if (addr->proto == QETH_PROT_IPV4)
++ rc = !memcmp(addr_bits, ipatoe_bits,
++ min(32, ipatoe->mask_bits));
++ else
++ rc = !memcmp(addr_bits, ipatoe_bits,
++ min(128, ipatoe->mask_bits));
++ if (rc)
++ break;
++ }
++ /* invert? */
++ if ((addr->proto == QETH_PROT_IPV4) && card->ipato.invert4)
++ rc = !rc;
++ else if ((addr->proto == QETH_PROT_IPV6) && card->ipato.invert6)
++ rc = !rc;
++
++ return rc;
++}
++
++/*
++ * Add IP to be added to todo list. If there is already an "add todo"
++ * in this list we just incremenent the reference count.
++ * Returns 0 if we just incremented reference count.
++ */
++static int __qeth_l3_insert_ip_todo(struct qeth_card *card,
++ struct qeth_ipaddr *addr, int add)
++{
++ struct qeth_ipaddr *tmp, *t;
++ int found = 0;
++
++ list_for_each_entry_safe(tmp, t, card->ip_tbd_list, entry) {
++ if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) &&
++ (tmp->type == QETH_IP_TYPE_DEL_ALL_MC))
++ return 0;
++ if ((tmp->proto == QETH_PROT_IPV4) &&
++ (addr->proto == QETH_PROT_IPV4) &&
++ (tmp->type == addr->type) &&
++ (tmp->is_multicast == addr->is_multicast) &&
++ (tmp->u.a4.addr == addr->u.a4.addr) &&
++ (tmp->u.a4.mask == addr->u.a4.mask)) {
++ found = 1;
++ break;
++ }
++ if ((tmp->proto == QETH_PROT_IPV6) &&
++ (addr->proto == QETH_PROT_IPV6) &&
++ (tmp->type == addr->type) &&
++ (tmp->is_multicast == addr->is_multicast) &&
++ (tmp->u.a6.pfxlen == addr->u.a6.pfxlen) &&
++ (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr,
++ sizeof(struct in6_addr)) == 0)) {
++ found = 1;
++ break;
++ }
++ }
++ if (found) {
++ if (addr->users != 0)
++ tmp->users += addr->users;
++ else
++ tmp->users += add ? 1 : -1;
++ if (tmp->users == 0) {
++ list_del(&tmp->entry);
++ kfree(tmp);
++ }
++ return 0;
++ } else {
++ if (addr->type == QETH_IP_TYPE_DEL_ALL_MC)
++ list_add(&addr->entry, card->ip_tbd_list);
++ else {
++ if (addr->users == 0)
++ addr->users += add ? 1 : -1;
++ if (add && (addr->type == QETH_IP_TYPE_NORMAL) &&
++ qeth_l3_is_addr_covered_by_ipato(card, addr)) {
++ QETH_DBF_TEXT(TRACE, 2, "tkovaddr");
++ addr->set_flags |= QETH_IPA_SETIP_TAKEOVER_FLAG;
++ }
++ list_add_tail(&addr->entry, card->ip_tbd_list);
++ }
++ return 1;
++ }
++}
++
++static int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
++{
++ unsigned long flags;
++ int rc = 0;
++
++ QETH_DBF_TEXT(TRACE, 4, "delip");
++
++ if (addr->proto == QETH_PROT_IPV4)
++ QETH_DBF_HEX(TRACE, 4, &addr->u.a4.addr, 4);
++ else {
++ QETH_DBF_HEX(TRACE, 4, &addr->u.a6.addr, 8);
++ QETH_DBF_HEX(TRACE, 4, ((char *)&addr->u.a6.addr) + 8, 8);
++ }
++ spin_lock_irqsave(&card->ip_lock, flags);
++ rc = __qeth_l3_insert_ip_todo(card, addr, 0);
++ spin_unlock_irqrestore(&card->ip_lock, flags);
++ return rc;
++}
++
++static int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
++{
++ unsigned long flags;
++ int rc = 0;
++
++ QETH_DBF_TEXT(TRACE, 4, "addip");
++ if (addr->proto == QETH_PROT_IPV4)
++ QETH_DBF_HEX(TRACE, 4, &addr->u.a4.addr, 4);
++ else {
++ QETH_DBF_HEX(TRACE, 4, &addr->u.a6.addr, 8);
++ QETH_DBF_HEX(TRACE, 4, ((char *)&addr->u.a6.addr) + 8, 8);
++ }
++ spin_lock_irqsave(&card->ip_lock, flags);
++ rc = __qeth_l3_insert_ip_todo(card, addr, 1);
++ spin_unlock_irqrestore(&card->ip_lock, flags);
++ return rc;
++}
++
++
++static struct qeth_ipaddr *qeth_l3_get_addr_buffer(
++ enum qeth_prot_versions prot)
++{
++ struct qeth_ipaddr *addr;
++
++ addr = kzalloc(sizeof(struct qeth_ipaddr), GFP_ATOMIC);
++ if (addr == NULL) {
++ PRINT_WARN("Not enough memory to add address\n");
++ return NULL;
++ }
++ addr->type = QETH_IP_TYPE_NORMAL;
++ addr->proto = prot;
++ return addr;
++}
++
++static void qeth_l3_delete_mc_addresses(struct qeth_card *card)
++{
++ struct qeth_ipaddr *iptodo;
++ unsigned long flags;
++
++ QETH_DBF_TEXT(TRACE, 4, "delmc");
++ iptodo = qeth_l3_get_addr_buffer(QETH_PROT_IPV4);
++ if (!iptodo) {
++ QETH_DBF_TEXT(TRACE, 2, "dmcnomem");
++ return;
++ }
++ iptodo->type = QETH_IP_TYPE_DEL_ALL_MC;
++ spin_lock_irqsave(&card->ip_lock, flags);
++ if (!__qeth_l3_insert_ip_todo(card, iptodo, 0))
++ kfree(iptodo);
++ spin_unlock_irqrestore(&card->ip_lock, flags);
++}
++
++/*
++ * Add/remove address to/from card's ip list, i.e. try to add or remove
++ * reference to/from an IP address that is already registered on the card.
++ * Returns:
++ * 0 address was on card and its reference count has been adjusted,
++ * but is still > 0, so nothing has to be done
++ * also returns 0 if card was not on card and the todo was to delete
++ * the address -> there is also nothing to be done
++ * 1 address was not on card and the todo is to add it to the card's ip
++ * list
++ * -1 address was on card and its reference count has been decremented
++ * to <= 0 by the todo -> address must be removed from card
++ */
++static int __qeth_l3_ref_ip_on_card(struct qeth_card *card,
++ struct qeth_ipaddr *todo, struct qeth_ipaddr **__addr)
++{
++ struct qeth_ipaddr *addr;
++ int found = 0;
++
++ list_for_each_entry(addr, &card->ip_list, entry) {
++ if ((addr->proto == QETH_PROT_IPV4) &&
++ (todo->proto == QETH_PROT_IPV4) &&
++ (addr->type == todo->type) &&
++ (addr->u.a4.addr == todo->u.a4.addr) &&
++ (addr->u.a4.mask == todo->u.a4.mask)) {
++ found = 1;
++ break;
++ }
++ if ((addr->proto == QETH_PROT_IPV6) &&
++ (todo->proto == QETH_PROT_IPV6) &&
++ (addr->type == todo->type) &&
++ (addr->u.a6.pfxlen == todo->u.a6.pfxlen) &&
++ (memcmp(&addr->u.a6.addr, &todo->u.a6.addr,
++ sizeof(struct in6_addr)) == 0)) {
++ found = 1;
++ break;
++ }
++ }
++ if (found) {
++ addr->users += todo->users;
++ if (addr->users <= 0) {
++ *__addr = addr;
++ return -1;
++ } else {
++ /* for VIPA and RXIP limit refcount to 1 */
++ if (addr->type != QETH_IP_TYPE_NORMAL)
++ addr->users = 1;
++ return 0;
++ }
++ }
++ if (todo->users > 0) {
++ /* for VIPA and RXIP limit refcount to 1 */
++ if (todo->type != QETH_IP_TYPE_NORMAL)
++ todo->users = 1;
++ return 1;
++ } else
++ return 0;
++}
++
++static void __qeth_l3_delete_all_mc(struct qeth_card *card,
++ unsigned long *flags)
++{
++ struct list_head fail_list;
++ struct qeth_ipaddr *addr, *tmp;
++ int rc;
++
++ INIT_LIST_HEAD(&fail_list);
++again:
++ list_for_each_entry_safe(addr, tmp, &card->ip_list, entry) {
++ if (addr->is_multicast) {
++ list_del(&addr->entry);
++ spin_unlock_irqrestore(&card->ip_lock, *flags);
++ rc = qeth_l3_deregister_addr_entry(card, addr);
++ spin_lock_irqsave(&card->ip_lock, *flags);
++ if (!rc || (rc == IPA_RC_MC_ADDR_NOT_FOUND))
++ kfree(addr);
++ else
++ list_add_tail(&addr->entry, &fail_list);
++ goto again;
++ }
++ }
++ list_splice(&fail_list, &card->ip_list);
++}
++
++static void qeth_l3_set_ip_addr_list(struct qeth_card *card)
++{
++ struct list_head *tbd_list;
++ struct qeth_ipaddr *todo, *addr;
++ unsigned long flags;
++ int rc;
++
++ QETH_DBF_TEXT(TRACE, 2, "sdiplist");
++ QETH_DBF_HEX(TRACE, 2, &card, sizeof(void *));
++
++ spin_lock_irqsave(&card->ip_lock, flags);
++ tbd_list = card->ip_tbd_list;
++ card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_ATOMIC);
++ if (!card->ip_tbd_list) {
++ QETH_DBF_TEXT(TRACE, 0, "silnomem");
++ card->ip_tbd_list = tbd_list;
++ spin_unlock_irqrestore(&card->ip_lock, flags);
++ return;
++ } else
++ INIT_LIST_HEAD(card->ip_tbd_list);
++
++ while (!list_empty(tbd_list)) {
++ todo = list_entry(tbd_list->next, struct qeth_ipaddr, entry);
++ list_del(&todo->entry);
++ if (todo->type == QETH_IP_TYPE_DEL_ALL_MC) {
++ __qeth_l3_delete_all_mc(card, &flags);
++ kfree(todo);
++ continue;
++ }
++ rc = __qeth_l3_ref_ip_on_card(card, todo, &addr);
++ if (rc == 0) {
++ /* nothing to be done; only adjusted refcount */
++ kfree(todo);
++ } else if (rc == 1) {
++ /* new entry to be added to on-card list */
++ spin_unlock_irqrestore(&card->ip_lock, flags);
++ rc = qeth_l3_register_addr_entry(card, todo);
++ spin_lock_irqsave(&card->ip_lock, flags);
++ if (!rc || (rc == IPA_RC_LAN_OFFLINE))
++ list_add_tail(&todo->entry, &card->ip_list);
++ else
++ kfree(todo);
++ } else if (rc == -1) {
++ /* on-card entry to be removed */
++ list_del_init(&addr->entry);
++ spin_unlock_irqrestore(&card->ip_lock, flags);
++ rc = qeth_l3_deregister_addr_entry(card, addr);
++ spin_lock_irqsave(&card->ip_lock, flags);
++ if (!rc || (rc == IPA_RC_PRIMARY_ALREADY_DEFINED))
++ kfree(addr);
++ else
++ list_add_tail(&addr->entry, &card->ip_list);
++ kfree(todo);
++ }
++ }
++ spin_unlock_irqrestore(&card->ip_lock, flags);
++ kfree(tbd_list);
++}
++
++static void qeth_l3_clear_ip_list(struct qeth_card *card, int clean,
++ int recover)
++{
++ struct qeth_ipaddr *addr, *tmp;
++ unsigned long flags;
++
++ QETH_DBF_TEXT(TRACE, 4, "clearip");
++ spin_lock_irqsave(&card->ip_lock, flags);
++ /* clear todo list */
++ list_for_each_entry_safe(addr, tmp, card->ip_tbd_list, entry) {
++ list_del(&addr->entry);
++ kfree(addr);
++ }
++
++ while (!list_empty(&card->ip_list)) {
++ addr = list_entry(card->ip_list.next,
++ struct qeth_ipaddr, entry);
++ list_del_init(&addr->entry);
++ if (clean) {
++ spin_unlock_irqrestore(&card->ip_lock, flags);
++ qeth_l3_deregister_addr_entry(card, addr);
++ spin_lock_irqsave(&card->ip_lock, flags);
++ }
++ if (!recover || addr->is_multicast) {
++ kfree(addr);
++ continue;
++ }
++ list_add_tail(&addr->entry, card->ip_tbd_list);
++ }
++ spin_unlock_irqrestore(&card->ip_lock, flags);
++}
++
++static int qeth_l3_address_exists_in_list(struct list_head *list,
++ struct qeth_ipaddr *addr, int same_type)
++{
++ struct qeth_ipaddr *tmp;
++
++ list_for_each_entry(tmp, list, entry) {
++ if ((tmp->proto == QETH_PROT_IPV4) &&
++ (addr->proto == QETH_PROT_IPV4) &&
++ ((same_type && (tmp->type == addr->type)) ||
++ (!same_type && (tmp->type != addr->type))) &&
++ (tmp->u.a4.addr == addr->u.a4.addr))
++ return 1;
++
++ if ((tmp->proto == QETH_PROT_IPV6) &&
++ (addr->proto == QETH_PROT_IPV6) &&
++ ((same_type && (tmp->type == addr->type)) ||
++ (!same_type && (tmp->type != addr->type))) &&
++ (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr,
++ sizeof(struct in6_addr)) == 0))
++ return 1;
++
++ }
++ return 0;
++}
++
++static int qeth_l3_send_setdelmc(struct qeth_card *card,
++ struct qeth_ipaddr *addr, int ipacmd)
++{
++ int rc;
++ struct qeth_cmd_buffer *iob;
++ struct qeth_ipa_cmd *cmd;
++
++ QETH_DBF_TEXT(TRACE, 4, "setdelmc");
++
++ iob = qeth_get_ipacmd_buffer(card, ipacmd, addr->proto);
++ cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++ memcpy(&cmd->data.setdelipm.mac, addr->mac, OSA_ADDR_LEN);
++ if (addr->proto == QETH_PROT_IPV6)
++ memcpy(cmd->data.setdelipm.ip6, &addr->u.a6.addr,
++ sizeof(struct in6_addr));
++ else
++ memcpy(&cmd->data.setdelipm.ip4, &addr->u.a4.addr, 4);
++
++ rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
++
++ return rc;
++}
++
++static void qeth_l3_fill_netmask(u8 *netmask, unsigned int len)
++{
++ int i, j;
++ for (i = 0; i < 16; i++) {
++ j = (len) - (i * 8);
++ if (j >= 8)
++ netmask[i] = 0xff;
++ else if (j > 0)
++ netmask[i] = (u8)(0xFF00 >> j);
++ else
++ netmask[i] = 0;
++ }
++}
++
++static int qeth_l3_send_setdelip(struct qeth_card *card,
++ struct qeth_ipaddr *addr, int ipacmd, unsigned int flags)
++{
++ int rc;
++ struct qeth_cmd_buffer *iob;
++ struct qeth_ipa_cmd *cmd;
++ __u8 netmask[16];
++
++ QETH_DBF_TEXT(TRACE, 4, "setdelip");
++ QETH_DBF_TEXT_(TRACE, 4, "flags%02X", flags);
++
++ iob = qeth_get_ipacmd_buffer(card, ipacmd, addr->proto);
++ cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++ if (addr->proto == QETH_PROT_IPV6) {
++ memcpy(cmd->data.setdelip6.ip_addr, &addr->u.a6.addr,
++ sizeof(struct in6_addr));
++ qeth_l3_fill_netmask(netmask, addr->u.a6.pfxlen);
++ memcpy(cmd->data.setdelip6.mask, netmask,
++ sizeof(struct in6_addr));
++ cmd->data.setdelip6.flags = flags;
++ } else {
++ memcpy(cmd->data.setdelip4.ip_addr, &addr->u.a4.addr, 4);
++ memcpy(cmd->data.setdelip4.mask, &addr->u.a4.mask, 4);
++ cmd->data.setdelip4.flags = flags;
++ }
++
++ rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
++
++ return rc;
++}
++
++static int qeth_l3_send_setrouting(struct qeth_card *card,
++ enum qeth_routing_types type, enum qeth_prot_versions prot)
++{
++ int rc;
++ struct qeth_ipa_cmd *cmd;
++ struct qeth_cmd_buffer *iob;
++
++ QETH_DBF_TEXT(TRACE, 4, "setroutg");
++ iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETRTG, prot);
++ cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++ cmd->data.setrtg.type = (type);
++ rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
++
++ return rc;
++}
++
++static void qeth_l3_correct_routing_type(struct qeth_card *card,
++ enum qeth_routing_types *type, enum qeth_prot_versions prot)
++{
++ if (card->info.type == QETH_CARD_TYPE_IQD) {
++ switch (*type) {
++ case NO_ROUTER:
++ case PRIMARY_CONNECTOR:
++ case SECONDARY_CONNECTOR:
++ case MULTICAST_ROUTER:
++ return;
++ default:
++ goto out_inval;
++ }
++ } else {
++ switch (*type) {
++ case NO_ROUTER:
++ case PRIMARY_ROUTER:
++ case SECONDARY_ROUTER:
++ return;
++ case MULTICAST_ROUTER:
++ if (qeth_is_ipafunc_supported(card, prot,
++ IPA_OSA_MC_ROUTER))
++ return;
++ default:
++ goto out_inval;
++ }
++ }
++out_inval:
++ PRINT_WARN("Routing type '%s' not supported for interface %s.\n"
++ "Router status set to 'no router'.\n",
++ ((*type == PRIMARY_ROUTER)? "primary router" :
++ (*type == SECONDARY_ROUTER)? "secondary router" :
++ (*type == PRIMARY_CONNECTOR)? "primary connector" :
++ (*type == SECONDARY_CONNECTOR)? "secondary connector" :
++ (*type == MULTICAST_ROUTER)? "multicast router" :
++ "unknown"),
++ card->dev->name);
++ *type = NO_ROUTER;
++}
++
++int qeth_l3_setrouting_v4(struct qeth_card *card)
++{
++ int rc;
++
++ QETH_DBF_TEXT(TRACE, 3, "setrtg4");
++
++ qeth_l3_correct_routing_type(card, &card->options.route4.type,
++ QETH_PROT_IPV4);
++
++ rc = qeth_l3_send_setrouting(card, card->options.route4.type,
++ QETH_PROT_IPV4);
++ if (rc) {
++ card->options.route4.type = NO_ROUTER;
++ PRINT_WARN("Error (0x%04x) while setting routing type on %s. "
++ "Type set to 'no router'.\n",
++ rc, QETH_CARD_IFNAME(card));
++ }
++ return rc;
++}
++
++int qeth_l3_setrouting_v6(struct qeth_card *card)
++{
++ int rc = 0;
++
++ QETH_DBF_TEXT(TRACE, 3, "setrtg6");
++#ifdef CONFIG_QETH_IPV6
++
++ if (!qeth_is_supported(card, IPA_IPV6))
++ return 0;
++ qeth_l3_correct_routing_type(card, &card->options.route6.type,
++ QETH_PROT_IPV6);
++
++ rc = qeth_l3_send_setrouting(card, card->options.route6.type,
++ QETH_PROT_IPV6);
++ if (rc) {
++ card->options.route6.type = NO_ROUTER;
++ PRINT_WARN("Error (0x%04x) while setting routing type on %s. "
++ "Type set to 'no router'.\n",
++ rc, QETH_CARD_IFNAME(card));
++ }
++#endif
++ return rc;
++}
++
++/*
++ * IP address takeover related functions
++ */
++static void qeth_l3_clear_ipato_list(struct qeth_card *card)
++{
++
++ struct qeth_ipato_entry *ipatoe, *tmp;
++ unsigned long flags;
++
++ spin_lock_irqsave(&card->ip_lock, flags);
++ list_for_each_entry_safe(ipatoe, tmp, &card->ipato.entries, entry) {
++ list_del(&ipatoe->entry);
++ kfree(ipatoe);
++ }
++ spin_unlock_irqrestore(&card->ip_lock, flags);
++}
++
++int qeth_l3_add_ipato_entry(struct qeth_card *card,
++ struct qeth_ipato_entry *new)
++{
++ struct qeth_ipato_entry *ipatoe;
++ unsigned long flags;
++ int rc = 0;
++
++ QETH_DBF_TEXT(TRACE, 2, "addipato");
++ spin_lock_irqsave(&card->ip_lock, flags);
++ list_for_each_entry(ipatoe, &card->ipato.entries, entry) {
++ if (ipatoe->proto != new->proto)
++ continue;
++ if (!memcmp(ipatoe->addr, new->addr,
++ (ipatoe->proto == QETH_PROT_IPV4)? 4:16) &&
++ (ipatoe->mask_bits == new->mask_bits)) {
++ PRINT_WARN("ipato entry already exists!\n");
++ rc = -EEXIST;
++ break;
++ }
++ }
++ if (!rc)
++ list_add_tail(&new->entry, &card->ipato.entries);
++
++ spin_unlock_irqrestore(&card->ip_lock, flags);
++ return rc;
++}
++
++void qeth_l3_del_ipato_entry(struct qeth_card *card,
++ enum qeth_prot_versions proto, u8 *addr, int mask_bits)
++{
++ struct qeth_ipato_entry *ipatoe, *tmp;
++ unsigned long flags;
++
++ QETH_DBF_TEXT(TRACE, 2, "delipato");
++ spin_lock_irqsave(&card->ip_lock, flags);
++ list_for_each_entry_safe(ipatoe, tmp, &card->ipato.entries, entry) {
++ if (ipatoe->proto != proto)
++ continue;
++ if (!memcmp(ipatoe->addr, addr,
++ (proto == QETH_PROT_IPV4)? 4:16) &&
++ (ipatoe->mask_bits == mask_bits)) {
++ list_del(&ipatoe->entry);
++ kfree(ipatoe);
++ }
++ }
++ spin_unlock_irqrestore(&card->ip_lock, flags);
++}
++
++/*
++ * VIPA related functions
++ */
++int qeth_l3_add_vipa(struct qeth_card *card, enum qeth_prot_versions proto,
++ const u8 *addr)
++{
++ struct qeth_ipaddr *ipaddr;
++ unsigned long flags;
++ int rc = 0;
++
++ ipaddr = qeth_l3_get_addr_buffer(proto);
++ if (ipaddr) {
++ if (proto == QETH_PROT_IPV4) {
++ QETH_DBF_TEXT(TRACE, 2, "addvipa4");
++ memcpy(&ipaddr->u.a4.addr, addr, 4);
++ ipaddr->u.a4.mask = 0;
++ } else if (proto == QETH_PROT_IPV6) {
++ QETH_DBF_TEXT(TRACE, 2, "addvipa6");
++ memcpy(&ipaddr->u.a6.addr, addr, 16);
++ ipaddr->u.a6.pfxlen = 0;
++ }
++ ipaddr->type = QETH_IP_TYPE_VIPA;
++ ipaddr->set_flags = QETH_IPA_SETIP_VIPA_FLAG;
++ ipaddr->del_flags = QETH_IPA_DELIP_VIPA_FLAG;
++ } else
++ return -ENOMEM;
++ spin_lock_irqsave(&card->ip_lock, flags);
++ if (qeth_l3_address_exists_in_list(&card->ip_list, ipaddr, 0) ||
++ qeth_l3_address_exists_in_list(card->ip_tbd_list, ipaddr, 0))
++ rc = -EEXIST;
++ spin_unlock_irqrestore(&card->ip_lock, flags);
++ if (rc) {
++ PRINT_WARN("Cannot add VIPA. Address already exists!\n");
++ return rc;
++ }
++ if (!qeth_l3_add_ip(card, ipaddr))
++ kfree(ipaddr);
++ qeth_l3_set_ip_addr_list(card);
++ return rc;
++}
++
++void qeth_l3_del_vipa(struct qeth_card *card, enum qeth_prot_versions proto,
++ const u8 *addr)
++{
++ struct qeth_ipaddr *ipaddr;
++
++ ipaddr = qeth_l3_get_addr_buffer(proto);
++ if (ipaddr) {
++ if (proto == QETH_PROT_IPV4) {
++ QETH_DBF_TEXT(TRACE, 2, "delvipa4");
++ memcpy(&ipaddr->u.a4.addr, addr, 4);
++ ipaddr->u.a4.mask = 0;
++ } else if (proto == QETH_PROT_IPV6) {
++ QETH_DBF_TEXT(TRACE, 2, "delvipa6");
++ memcpy(&ipaddr->u.a6.addr, addr, 16);
++ ipaddr->u.a6.pfxlen = 0;
++ }
++ ipaddr->type = QETH_IP_TYPE_VIPA;
++ } else
++ return;
++ if (!qeth_l3_delete_ip(card, ipaddr))
++ kfree(ipaddr);
++ qeth_l3_set_ip_addr_list(card);
++}
++
++/*
++ * proxy ARP related functions
++ */
++int qeth_l3_add_rxip(struct qeth_card *card, enum qeth_prot_versions proto,
++ const u8 *addr)
++{
++ struct qeth_ipaddr *ipaddr;
++ unsigned long flags;
++ int rc = 0;
++
++ ipaddr = qeth_l3_get_addr_buffer(proto);
++ if (ipaddr) {
++ if (proto == QETH_PROT_IPV4) {
++ QETH_DBF_TEXT(TRACE, 2, "addrxip4");
++ memcpy(&ipaddr->u.a4.addr, addr, 4);
++ ipaddr->u.a4.mask = 0;
++ } else if (proto == QETH_PROT_IPV6) {
++ QETH_DBF_TEXT(TRACE, 2, "addrxip6");
++ memcpy(&ipaddr->u.a6.addr, addr, 16);
++ ipaddr->u.a6.pfxlen = 0;
++ }
++ ipaddr->type = QETH_IP_TYPE_RXIP;
++ ipaddr->set_flags = QETH_IPA_SETIP_TAKEOVER_FLAG;
++ ipaddr->del_flags = 0;
++ } else
++ return -ENOMEM;
++ spin_lock_irqsave(&card->ip_lock, flags);
++ if (qeth_l3_address_exists_in_list(&card->ip_list, ipaddr, 0) ||
++ qeth_l3_address_exists_in_list(card->ip_tbd_list, ipaddr, 0))
++ rc = -EEXIST;
++ spin_unlock_irqrestore(&card->ip_lock, flags);
++ if (rc) {
++ PRINT_WARN("Cannot add RXIP. Address already exists!\n");
++ return rc;
++ }
++ if (!qeth_l3_add_ip(card, ipaddr))
++ kfree(ipaddr);
++ qeth_l3_set_ip_addr_list(card);
++ return 0;
++}
++
++void qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions proto,
++ const u8 *addr)
++{
++ struct qeth_ipaddr *ipaddr;
++
++ ipaddr = qeth_l3_get_addr_buffer(proto);
++ if (ipaddr) {
++ if (proto == QETH_PROT_IPV4) {
++ QETH_DBF_TEXT(TRACE, 2, "addrxip4");
++ memcpy(&ipaddr->u.a4.addr, addr, 4);
++ ipaddr->u.a4.mask = 0;
++ } else if (proto == QETH_PROT_IPV6) {
++ QETH_DBF_TEXT(TRACE, 2, "addrxip6");
++ memcpy(&ipaddr->u.a6.addr, addr, 16);
++ ipaddr->u.a6.pfxlen = 0;
++ }
++ ipaddr->type = QETH_IP_TYPE_RXIP;
++ } else
++ return;
++ if (!qeth_l3_delete_ip(card, ipaddr))
++ kfree(ipaddr);
++ qeth_l3_set_ip_addr_list(card);
++}
++
++static int qeth_l3_register_addr_entry(struct qeth_card *card,
++ struct qeth_ipaddr *addr)
++{
++ char buf[50];
++ int rc = 0;
++ int cnt = 3;
++
++ if (addr->proto == QETH_PROT_IPV4) {
++ QETH_DBF_TEXT(TRACE, 2, "setaddr4");
++ QETH_DBF_HEX(TRACE, 3, &addr->u.a4.addr, sizeof(int));
++ } else if (addr->proto == QETH_PROT_IPV6) {
++ QETH_DBF_TEXT(TRACE, 2, "setaddr6");
++ QETH_DBF_HEX(TRACE, 3, &addr->u.a6.addr, 8);
++ QETH_DBF_HEX(TRACE, 3, ((char *)&addr->u.a6.addr) + 8, 8);
++ } else {
++ QETH_DBF_TEXT(TRACE, 2, "setaddr?");
++ QETH_DBF_HEX(TRACE, 3, addr, sizeof(struct qeth_ipaddr));
++ }
++ do {
++ if (addr->is_multicast)
++ rc = qeth_l3_send_setdelmc(card, addr, IPA_CMD_SETIPM);
++ else
++ rc = qeth_l3_send_setdelip(card, addr, IPA_CMD_SETIP,
++ addr->set_flags);
++ if (rc)
++ QETH_DBF_TEXT(TRACE, 2, "failed");
++ } while ((--cnt > 0) && rc);
++ if (rc) {
++ QETH_DBF_TEXT(TRACE, 2, "FAILED");
++ qeth_l3_ipaddr_to_string(addr->proto, (u8 *)&addr->u, buf);
++ PRINT_WARN("Could not register IP address %s (rc=0x%x/%d)\n",
++ buf, rc, rc);
++ }
++ return rc;
++}
++
++static int qeth_l3_deregister_addr_entry(struct qeth_card *card,
++ struct qeth_ipaddr *addr)
++{
++ int rc = 0;
++
++ if (addr->proto == QETH_PROT_IPV4) {
++ QETH_DBF_TEXT(TRACE, 2, "deladdr4");
++ QETH_DBF_HEX(TRACE, 3, &addr->u.a4.addr, sizeof(int));
++ } else if (addr->proto == QETH_PROT_IPV6) {
++ QETH_DBF_TEXT(TRACE, 2, "deladdr6");
++ QETH_DBF_HEX(TRACE, 3, &addr->u.a6.addr, 8);
++ QETH_DBF_HEX(TRACE, 3, ((char *)&addr->u.a6.addr) + 8, 8);
++ } else {
++ QETH_DBF_TEXT(TRACE, 2, "deladdr?");
++ QETH_DBF_HEX(TRACE, 3, addr, sizeof(struct qeth_ipaddr));
++ }
++ if (addr->is_multicast)
++ rc = qeth_l3_send_setdelmc(card, addr, IPA_CMD_DELIPM);
++ else
++ rc = qeth_l3_send_setdelip(card, addr, IPA_CMD_DELIP,
++ addr->del_flags);
++ if (rc) {
++ QETH_DBF_TEXT(TRACE, 2, "failed");
++ /* TODO: re-activate this warning as soon as we have a
++ * clean mirco code
++ qeth_ipaddr_to_string(addr->proto, (u8 *)&addr->u, buf);
++ PRINT_WARN("Could not deregister IP address %s (rc=%x)\n",
++ buf, rc);
++ */
++ }
++
++ return rc;
++}
++
++static inline u8 qeth_l3_get_qeth_hdr_flags4(int cast_type)
++{
++ if (cast_type == RTN_MULTICAST)
++ return QETH_CAST_MULTICAST;
++ if (cast_type == RTN_BROADCAST)
++ return QETH_CAST_BROADCAST;
++ return QETH_CAST_UNICAST;
++}
++
++static inline u8 qeth_l3_get_qeth_hdr_flags6(int cast_type)
++{
++ u8 ct = QETH_HDR_PASSTHRU | QETH_HDR_IPV6;
++ if (cast_type == RTN_MULTICAST)
++ return ct | QETH_CAST_MULTICAST;
++ if (cast_type == RTN_ANYCAST)
++ return ct | QETH_CAST_ANYCAST;
++ if (cast_type == RTN_BROADCAST)
++ return ct | QETH_CAST_BROADCAST;
++ return ct | QETH_CAST_UNICAST;
++}
++
++static int qeth_l3_send_setadp_mode(struct qeth_card *card, __u32 command,
++ __u32 mode)
++{
++ int rc;
++ struct qeth_cmd_buffer *iob;
++ struct qeth_ipa_cmd *cmd;
++
++ QETH_DBF_TEXT(TRACE, 4, "adpmode");
++
++ iob = qeth_get_adapter_cmd(card, command,
++ sizeof(struct qeth_ipacmd_setadpparms));
++ cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++ cmd->data.setadapterparms.data.mode = mode;
++ rc = qeth_send_ipa_cmd(card, iob, qeth_default_setadapterparms_cb,
++ NULL);
++ return rc;
++}
++
++static int qeth_l3_setadapter_hstr(struct qeth_card *card)
++{
++ int rc;
++
++ QETH_DBF_TEXT(TRACE, 4, "adphstr");
++
++ if (qeth_adp_supported(card, IPA_SETADP_SET_BROADCAST_MODE)) {
++ rc = qeth_l3_send_setadp_mode(card,
++ IPA_SETADP_SET_BROADCAST_MODE,
++ card->options.broadcast_mode);
++ if (rc)
++ PRINT_WARN("couldn't set broadcast mode on "
++ "device %s: x%x\n",
++ CARD_BUS_ID(card), rc);
++ rc = qeth_l3_send_setadp_mode(card,
++ IPA_SETADP_ALTER_MAC_ADDRESS,
++ card->options.macaddr_mode);
++ if (rc)
++ PRINT_WARN("couldn't set macaddr mode on "
++ "device %s: x%x\n", CARD_BUS_ID(card), rc);
++ return rc;
++ }
++ if (card->options.broadcast_mode == QETH_TR_BROADCAST_LOCAL)
++ PRINT_WARN("set adapter parameters not available "
++ "to set broadcast mode, using ALLRINGS "
++ "on device %s:\n", CARD_BUS_ID(card));
++ if (card->options.macaddr_mode == QETH_TR_MACADDR_CANONICAL)
++ PRINT_WARN("set adapter parameters not available "
++ "to set macaddr mode, using NONCANONICAL "
++ "on device %s:\n", CARD_BUS_ID(card));
++ return 0;
++}
++
++static int qeth_l3_setadapter_parms(struct qeth_card *card)
++{
++ int rc;
++
++ QETH_DBF_TEXT(SETUP, 2, "setadprm");
++
++ if (!qeth_is_supported(card, IPA_SETADAPTERPARMS)) {
++ PRINT_WARN("set adapter parameters not supported "
++ "on device %s.\n",
++ CARD_BUS_ID(card));
++ QETH_DBF_TEXT(SETUP, 2, " notsupp");
++ return 0;
++ }
++ rc = qeth_query_setadapterparms(card);
++ if (rc) {
++ PRINT_WARN("couldn't set adapter parameters on device %s: "
++ "x%x\n", CARD_BUS_ID(card), rc);
++ return rc;
++ }
++ if (qeth_adp_supported(card, IPA_SETADP_ALTER_MAC_ADDRESS)) {
++ rc = qeth_setadpparms_change_macaddr(card);
++ if (rc)
++ PRINT_WARN("couldn't get MAC address on "
++ "device %s: x%x\n",
++ CARD_BUS_ID(card), rc);
++ }
++
++ if ((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
++ (card->info.link_type == QETH_LINK_TYPE_LANE_TR))
++ rc = qeth_l3_setadapter_hstr(card);
++
++ return rc;
++}
++
++static int qeth_l3_default_setassparms_cb(struct qeth_card *card,
++ struct qeth_reply *reply, unsigned long data)
++{
++ struct qeth_ipa_cmd *cmd;
++
++ QETH_DBF_TEXT(TRACE, 4, "defadpcb");
++
++ cmd = (struct qeth_ipa_cmd *) data;
++ if (cmd->hdr.return_code == 0) {
++ cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code;
++ if (cmd->hdr.prot_version == QETH_PROT_IPV4)
++ card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
++ if (cmd->hdr.prot_version == QETH_PROT_IPV6)
++ card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
++ }
++ if (cmd->data.setassparms.hdr.assist_no == IPA_INBOUND_CHECKSUM &&
++ cmd->data.setassparms.hdr.command_code == IPA_CMD_ASS_START) {
++ card->info.csum_mask = cmd->data.setassparms.data.flags_32bit;
++ QETH_DBF_TEXT_(TRACE, 3, "csum:%d", card->info.csum_mask);
++ }
++ return 0;
++}
++
++static struct qeth_cmd_buffer *qeth_l3_get_setassparms_cmd(
++ struct qeth_card *card, enum qeth_ipa_funcs ipa_func, __u16 cmd_code,
++ __u16 len, enum qeth_prot_versions prot)
++{
++ struct qeth_cmd_buffer *iob;
++ struct qeth_ipa_cmd *cmd;
++
++ QETH_DBF_TEXT(TRACE, 4, "getasscm");
++ iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETASSPARMS, prot);
++
++ cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++ cmd->data.setassparms.hdr.assist_no = ipa_func;
++ cmd->data.setassparms.hdr.length = 8 + len;
++ cmd->data.setassparms.hdr.command_code = cmd_code;
++ cmd->data.setassparms.hdr.return_code = 0;
++ cmd->data.setassparms.hdr.seq_no = 0;
++
++ return iob;
++}
++
++static int qeth_l3_send_setassparms(struct qeth_card *card,
++ struct qeth_cmd_buffer *iob, __u16 len, long data,
++ int (*reply_cb)(struct qeth_card *, struct qeth_reply *,
++ unsigned long),
++ void *reply_param)
++{
++ int rc;
++ struct qeth_ipa_cmd *cmd;
++
++ QETH_DBF_TEXT(TRACE, 4, "sendassp");
++
++ cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++ if (len <= sizeof(__u32))
++ cmd->data.setassparms.data.flags_32bit = (__u32) data;
++ else /* (len > sizeof(__u32)) */
++ memcpy(&cmd->data.setassparms.data, (void *) data, len);
++
++ rc = qeth_send_ipa_cmd(card, iob, reply_cb, reply_param);
++ return rc;
++}
++
++#ifdef CONFIG_QETH_IPV6
++static int qeth_l3_send_simple_setassparms_ipv6(struct qeth_card *card,
++ enum qeth_ipa_funcs ipa_func, __u16 cmd_code)
++{
++ int rc;
++ struct qeth_cmd_buffer *iob;
++
++ QETH_DBF_TEXT(TRACE, 4, "simassp6");
++ iob = qeth_l3_get_setassparms_cmd(card, ipa_func, cmd_code,
++ 0, QETH_PROT_IPV6);
++ rc = qeth_l3_send_setassparms(card, iob, 0, 0,
++ qeth_l3_default_setassparms_cb, NULL);
++ return rc;
++}
++#endif
++
++static int qeth_l3_send_simple_setassparms(struct qeth_card *card,
++ enum qeth_ipa_funcs ipa_func, __u16 cmd_code, long data)
++{
++ int rc;
++ int length = 0;
++ struct qeth_cmd_buffer *iob;
++
++ QETH_DBF_TEXT(TRACE, 4, "simassp4");
++ if (data)
++ length = sizeof(__u32);
++ iob = qeth_l3_get_setassparms_cmd(card, ipa_func, cmd_code,
++ length, QETH_PROT_IPV4);
++ rc = qeth_l3_send_setassparms(card, iob, length, data,
++ qeth_l3_default_setassparms_cb, NULL);
++ return rc;
++}
++
++static int qeth_l3_start_ipa_arp_processing(struct qeth_card *card)
++{
++ int rc;
++
++ QETH_DBF_TEXT(TRACE, 3, "ipaarp");
++
++ if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
++ PRINT_WARN("ARP processing not supported "
++ "on %s!\n", QETH_CARD_IFNAME(card));
++ return 0;
++ }
++ rc = qeth_l3_send_simple_setassparms(card, IPA_ARP_PROCESSING,
++ IPA_CMD_ASS_START, 0);
++ if (rc) {
++ PRINT_WARN("Could not start ARP processing "
++ "assist on %s: 0x%x\n",
++ QETH_CARD_IFNAME(card), rc);
++ }
++ return rc;
++}
++
++static int qeth_l3_start_ipa_ip_fragmentation(struct qeth_card *card)
++{
++ int rc;
++
++ QETH_DBF_TEXT(TRACE, 3, "ipaipfrg");
++
++ if (!qeth_is_supported(card, IPA_IP_FRAGMENTATION)) {
++ PRINT_INFO("Hardware IP fragmentation not supported on %s\n",
++ QETH_CARD_IFNAME(card));
++ return -EOPNOTSUPP;
++ }
++
++ rc = qeth_l3_send_simple_setassparms(card, IPA_IP_FRAGMENTATION,
++ IPA_CMD_ASS_START, 0);
++ if (rc) {
++ PRINT_WARN("Could not start Hardware IP fragmentation "
++ "assist on %s: 0x%x\n",
++ QETH_CARD_IFNAME(card), rc);
++ } else
++ PRINT_INFO("Hardware IP fragmentation enabled \n");
++ return rc;
++}
++
++static int qeth_l3_start_ipa_source_mac(struct qeth_card *card)
++{
++ int rc;
++
++ QETH_DBF_TEXT(TRACE, 3, "stsrcmac");
++
++ if (!card->options.fake_ll)
++ return -EOPNOTSUPP;
++
++ if (!qeth_is_supported(card, IPA_SOURCE_MAC)) {
++ PRINT_INFO("Inbound source address not "
++ "supported on %s\n", QETH_CARD_IFNAME(card));
++ return -EOPNOTSUPP;
++ }
++
++ rc = qeth_l3_send_simple_setassparms(card, IPA_SOURCE_MAC,
++ IPA_CMD_ASS_START, 0);
++ if (rc)
++ PRINT_WARN("Could not start inbound source "
++ "assist on %s: 0x%x\n",
++ QETH_CARD_IFNAME(card), rc);
++ return rc;
++}
++
++static int qeth_l3_start_ipa_vlan(struct qeth_card *card)
++{
++ int rc = 0;
++
++ QETH_DBF_TEXT(TRACE, 3, "strtvlan");
++
++ if (!qeth_is_supported(card, IPA_FULL_VLAN)) {
++ PRINT_WARN("VLAN not supported on %s\n",
++ QETH_CARD_IFNAME(card));
++ return -EOPNOTSUPP;
++ }
++
++ rc = qeth_l3_send_simple_setassparms(card, IPA_VLAN_PRIO,
++ IPA_CMD_ASS_START, 0);
++ if (rc) {
++ PRINT_WARN("Could not start vlan "
++ "assist on %s: 0x%x\n",
++ QETH_CARD_IFNAME(card), rc);
++ } else {
++ PRINT_INFO("VLAN enabled \n");
++ }
++ return rc;
++}
++
++static int qeth_l3_start_ipa_multicast(struct qeth_card *card)
++{
++ int rc;
++
++ QETH_DBF_TEXT(TRACE, 3, "stmcast");
++
++ if (!qeth_is_supported(card, IPA_MULTICASTING)) {
++ PRINT_WARN("Multicast not supported on %s\n",
++ QETH_CARD_IFNAME(card));
++ return -EOPNOTSUPP;
++ }
++
++ rc = qeth_l3_send_simple_setassparms(card, IPA_MULTICASTING,
++ IPA_CMD_ASS_START, 0);
++ if (rc) {
++ PRINT_WARN("Could not start multicast "
++ "assist on %s: rc=%i\n",
++ QETH_CARD_IFNAME(card), rc);
++ } else {
++ PRINT_INFO("Multicast enabled\n");
++ card->dev->flags |= IFF_MULTICAST;
++ }
++ return rc;
++}
++
++static int qeth_l3_query_ipassists_cb(struct qeth_card *card,
++ struct qeth_reply *reply, unsigned long data)
++{
++ struct qeth_ipa_cmd *cmd;
++
++ QETH_DBF_TEXT(SETUP, 2, "qipasscb");
++
++ cmd = (struct qeth_ipa_cmd *) data;
++ if (cmd->hdr.prot_version == QETH_PROT_IPV4) {
++ card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported;
++ card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
++ } else {
++ card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported;
++ card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
++ }
++ QETH_DBF_TEXT(SETUP, 2, "suppenbl");
++ QETH_DBF_TEXT_(SETUP, 2, "%x", cmd->hdr.ipa_supported);
++ QETH_DBF_TEXT_(SETUP, 2, "%x", cmd->hdr.ipa_enabled);
++ return 0;
++}
++
++static int qeth_l3_query_ipassists(struct qeth_card *card,
++ enum qeth_prot_versions prot)
++{
++ int rc;
++ struct qeth_cmd_buffer *iob;
++
++ QETH_DBF_TEXT_(SETUP, 2, "qipassi%i", prot);
++ iob = qeth_get_ipacmd_buffer(card, IPA_CMD_QIPASSIST, prot);
++ rc = qeth_send_ipa_cmd(card, iob, qeth_l3_query_ipassists_cb, NULL);
++ return rc;
++}
++
++#ifdef CONFIG_QETH_IPV6
++static int qeth_l3_softsetup_ipv6(struct qeth_card *card)
++{
++ int rc;
++
++ QETH_DBF_TEXT(TRACE, 3, "softipv6");
++
++ if (card->info.type == QETH_CARD_TYPE_IQD)
++ goto out;
++
++ rc = qeth_l3_query_ipassists(card, QETH_PROT_IPV6);
++ if (rc) {
++ PRINT_ERR("IPv6 query ipassist failed on %s\n",
++ QETH_CARD_IFNAME(card));
++ return rc;
++ }
++ rc = qeth_l3_send_simple_setassparms(card, IPA_IPV6,
++ IPA_CMD_ASS_START, 3);
++ if (rc) {
++ PRINT_WARN("IPv6 start assist (version 4) failed "
++ "on %s: 0x%x\n",
++ QETH_CARD_IFNAME(card), rc);
++ return rc;
++ }
++ rc = qeth_l3_send_simple_setassparms_ipv6(card, IPA_IPV6,
++ IPA_CMD_ASS_START);
++ if (rc) {
++ PRINT_WARN("IPV6 start assist (version 6) failed "
++ "on %s: 0x%x\n",
++ QETH_CARD_IFNAME(card), rc);
++ return rc;
++ }
++ rc = qeth_l3_send_simple_setassparms_ipv6(card, IPA_PASSTHRU,
++ IPA_CMD_ASS_START);
++ if (rc) {
++ PRINT_WARN("Could not enable passthrough "
++ "on %s: 0x%x\n",
++ QETH_CARD_IFNAME(card), rc);
++ return rc;
++ }
++out:
++ PRINT_INFO("IPV6 enabled \n");
++ return 0;
++}
++#endif
++
++static int qeth_l3_start_ipa_ipv6(struct qeth_card *card)
++{
++ int rc = 0;
++
++ QETH_DBF_TEXT(TRACE, 3, "strtipv6");
++
++ if (!qeth_is_supported(card, IPA_IPV6)) {
++ PRINT_WARN("IPv6 not supported on %s\n",
++ QETH_CARD_IFNAME(card));
++ return 0;
++ }
++#ifdef CONFIG_QETH_IPV6
++ rc = qeth_l3_softsetup_ipv6(card);
++#endif
++ return rc ;
++}
++
++static int qeth_l3_start_ipa_broadcast(struct qeth_card *card)
++{
++ int rc;
++
++ QETH_DBF_TEXT(TRACE, 3, "stbrdcst");
++ card->info.broadcast_capable = 0;
++ if (!qeth_is_supported(card, IPA_FILTERING)) {
++ PRINT_WARN("Broadcast not supported on %s\n",
++ QETH_CARD_IFNAME(card));
++ rc = -EOPNOTSUPP;
++ goto out;
++ }
++ rc = qeth_l3_send_simple_setassparms(card, IPA_FILTERING,
++ IPA_CMD_ASS_START, 0);
++ if (rc) {
++ PRINT_WARN("Could not enable broadcasting filtering "
++ "on %s: 0x%x\n",
++ QETH_CARD_IFNAME(card), rc);
++ goto out;
++ }
++
++ rc = qeth_l3_send_simple_setassparms(card, IPA_FILTERING,
++ IPA_CMD_ASS_CONFIGURE, 1);
++ if (rc) {
++ PRINT_WARN("Could not set up broadcast filtering on %s: 0x%x\n",
++ QETH_CARD_IFNAME(card), rc);
++ goto out;
++ }
++ card->info.broadcast_capable = QETH_BROADCAST_WITH_ECHO;
++ PRINT_INFO("Broadcast enabled \n");
++ rc = qeth_l3_send_simple_setassparms(card, IPA_FILTERING,
++ IPA_CMD_ASS_ENABLE, 1);
++ if (rc) {
++ PRINT_WARN("Could not set up broadcast echo filtering on "
++ "%s: 0x%x\n", QETH_CARD_IFNAME(card), rc);
++ goto out;
++ }
++ card->info.broadcast_capable = QETH_BROADCAST_WITHOUT_ECHO;
++out:
++ if (card->info.broadcast_capable)
++ card->dev->flags |= IFF_BROADCAST;
++ else
++ card->dev->flags &= ~IFF_BROADCAST;
++ return rc;
++}
++
++static int qeth_l3_send_checksum_command(struct qeth_card *card)
++{
++ int rc;
++
++ rc = qeth_l3_send_simple_setassparms(card, IPA_INBOUND_CHECKSUM,
++ IPA_CMD_ASS_START, 0);
++ if (rc) {
++ PRINT_WARN("Starting Inbound HW Checksumming failed on %s: "
++ "0x%x,\ncontinuing using Inbound SW Checksumming\n",
++ QETH_CARD_IFNAME(card), rc);
++ return rc;
++ }
++ rc = qeth_l3_send_simple_setassparms(card, IPA_INBOUND_CHECKSUM,
++ IPA_CMD_ASS_ENABLE,
++ card->info.csum_mask);
++ if (rc) {
++ PRINT_WARN("Enabling Inbound HW Checksumming failed on %s: "
++ "0x%x,\ncontinuing using Inbound SW Checksumming\n",
++ QETH_CARD_IFNAME(card), rc);
++ return rc;
++ }
++ return 0;
++}
++
++static int qeth_l3_start_ipa_checksum(struct qeth_card *card)
++{
++ int rc = 0;
++
++ QETH_DBF_TEXT(TRACE, 3, "strtcsum");
++
++ if (card->options.checksum_type == NO_CHECKSUMMING) {
++ PRINT_WARN("Using no checksumming on %s.\n",
++ QETH_CARD_IFNAME(card));
++ return 0;
++ }
++ if (card->options.checksum_type == SW_CHECKSUMMING) {
++ PRINT_WARN("Using SW checksumming on %s.\n",
++ QETH_CARD_IFNAME(card));
++ return 0;
++ }
++ if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM)) {
++ PRINT_WARN("Inbound HW Checksumming not "
++ "supported on %s,\ncontinuing "
++ "using Inbound SW Checksumming\n",
++ QETH_CARD_IFNAME(card));
++ card->options.checksum_type = SW_CHECKSUMMING;
++ return 0;
++ }
++ rc = qeth_l3_send_checksum_command(card);
++ if (!rc)
++ PRINT_INFO("HW Checksumming (inbound) enabled \n");
++
++ return rc;
++}
++
++static int qeth_l3_start_ipa_tso(struct qeth_card *card)
++{
++ int rc;
++
++ QETH_DBF_TEXT(TRACE, 3, "sttso");
++
++ if (!qeth_is_supported(card, IPA_OUTBOUND_TSO)) {
++ PRINT_WARN("Outbound TSO not supported on %s\n",
++ QETH_CARD_IFNAME(card));
++ rc = -EOPNOTSUPP;
++ } else {
++ rc = qeth_l3_send_simple_setassparms(card, IPA_OUTBOUND_TSO,
++ IPA_CMD_ASS_START, 0);
++ if (rc)
++ PRINT_WARN("Could not start outbound TSO "
++ "assist on %s: rc=%i\n",
++ QETH_CARD_IFNAME(card), rc);
++ else
++ PRINT_INFO("Outbound TSO enabled\n");
++ }
++ if (rc && (card->options.large_send == QETH_LARGE_SEND_TSO)) {
++ card->options.large_send = QETH_LARGE_SEND_NO;
++ card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
++ }
++ return rc;
++}
++
++static int qeth_l3_start_ipassists(struct qeth_card *card)
++{
++ QETH_DBF_TEXT(TRACE, 3, "strtipas");
++ qeth_l3_start_ipa_arp_processing(card); /* go on*/
++ qeth_l3_start_ipa_ip_fragmentation(card); /* go on*/
++ qeth_l3_start_ipa_source_mac(card); /* go on*/
++ qeth_l3_start_ipa_vlan(card); /* go on*/
++ qeth_l3_start_ipa_multicast(card); /* go on*/
++ qeth_l3_start_ipa_ipv6(card); /* go on*/
++ qeth_l3_start_ipa_broadcast(card); /* go on*/
++ qeth_l3_start_ipa_checksum(card); /* go on*/
++ qeth_l3_start_ipa_tso(card); /* go on*/
++ return 0;
++}
++
++static int qeth_l3_put_unique_id(struct qeth_card *card)
++{
++
++ int rc = 0;
++ struct qeth_cmd_buffer *iob;
++ struct qeth_ipa_cmd *cmd;
++
++ QETH_DBF_TEXT(TRACE, 2, "puniqeid");
++
++ if ((card->info.unique_id & UNIQUE_ID_NOT_BY_CARD) ==
++ UNIQUE_ID_NOT_BY_CARD)
++ return -1;
++ iob = qeth_get_ipacmd_buffer(card, IPA_CMD_DESTROY_ADDR,
++ QETH_PROT_IPV6);
++ cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++ *((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) =
++ card->info.unique_id;
++ memcpy(&cmd->data.create_destroy_addr.unique_id[0],
++ card->dev->dev_addr, OSA_ADDR_LEN);
++ rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
++ return rc;
++}
++
++static int qeth_l3_iqd_read_initial_mac_cb(struct qeth_card *card,
++ struct qeth_reply *reply, unsigned long data)
++{
++ struct qeth_ipa_cmd *cmd;
++
++ cmd = (struct qeth_ipa_cmd *) data;
++ if (cmd->hdr.return_code == 0)
++ memcpy(card->dev->dev_addr,
++ cmd->data.create_destroy_addr.unique_id, ETH_ALEN);
++ else
++ random_ether_addr(card->dev->dev_addr);
++
++ return 0;
++}
++
++static int qeth_l3_iqd_read_initial_mac(struct qeth_card *card)
++{
++ int rc = 0;
++ struct qeth_cmd_buffer *iob;
++ struct qeth_ipa_cmd *cmd;
++
++ QETH_DBF_TEXT(SETUP, 2, "hsrmac");
++
++ iob = qeth_get_ipacmd_buffer(card, IPA_CMD_CREATE_ADDR,
++ QETH_PROT_IPV6);
++ cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++ *((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) =
++ card->info.unique_id;
++
++ rc = qeth_send_ipa_cmd(card, iob, qeth_l3_iqd_read_initial_mac_cb,
++ NULL);
++ return rc;
++}
++
++static int qeth_l3_get_unique_id_cb(struct qeth_card *card,
++ struct qeth_reply *reply, unsigned long data)
++{
++ struct qeth_ipa_cmd *cmd;
++
++ cmd = (struct qeth_ipa_cmd *) data;
++ if (cmd->hdr.return_code == 0)
++ card->info.unique_id = *((__u16 *)
++ &cmd->data.create_destroy_addr.unique_id[6]);
++ else {
++ card->info.unique_id = UNIQUE_ID_IF_CREATE_ADDR_FAILED |
++ UNIQUE_ID_NOT_BY_CARD;
++ PRINT_WARN("couldn't get a unique id from the card on device "
++ "%s (result=x%x), using default id. ipv6 "
++ "autoconfig on other lpars may lead to duplicate "
++ "ip addresses. please use manually "
++ "configured ones.\n",
++ CARD_BUS_ID(card), cmd->hdr.return_code);
++ }
++ return 0;
++}
++
++static int qeth_l3_get_unique_id(struct qeth_card *card)
++{
++ int rc = 0;
++ struct qeth_cmd_buffer *iob;
++ struct qeth_ipa_cmd *cmd;
++
++ QETH_DBF_TEXT(SETUP, 2, "guniqeid");
++
++ if (!qeth_is_supported(card, IPA_IPV6)) {
++ card->info.unique_id = UNIQUE_ID_IF_CREATE_ADDR_FAILED |
++ UNIQUE_ID_NOT_BY_CARD;
++ return 0;
++ }
++
++ iob = qeth_get_ipacmd_buffer(card, IPA_CMD_CREATE_ADDR,
++ QETH_PROT_IPV6);
++ cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
++ *((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) =
++ card->info.unique_id;
++
++ rc = qeth_send_ipa_cmd(card, iob, qeth_l3_get_unique_id_cb, NULL);
++ return rc;
++}
++
++static void qeth_l3_get_mac_for_ipm(__u32 ipm, char *mac,
++ struct net_device *dev)
++{
++ if (dev->type == ARPHRD_IEEE802_TR)
++ ip_tr_mc_map(ipm, mac);
++ else
++ ip_eth_mc_map(ipm, mac);
++}
++
++static void qeth_l3_add_mc(struct qeth_card *card, struct in_device *in4_dev)
++{
++ struct qeth_ipaddr *ipm;
++ struct ip_mc_list *im4;
++ char buf[MAX_ADDR_LEN];
++
++ QETH_DBF_TEXT(TRACE, 4, "addmc");
++ for (im4 = in4_dev->mc_list; im4; im4 = im4->next) {
++ qeth_l3_get_mac_for_ipm(im4->multiaddr, buf, in4_dev->dev);
++ ipm = qeth_l3_get_addr_buffer(QETH_PROT_IPV4);
++ if (!ipm)
++ continue;
++ ipm->u.a4.addr = im4->multiaddr;
++ memcpy(ipm->mac, buf, OSA_ADDR_LEN);
++ ipm->is_multicast = 1;
++ if (!qeth_l3_add_ip(card, ipm))
++ kfree(ipm);
++ }
++}
++
++static void qeth_l3_add_vlan_mc(struct qeth_card *card)
++{
++ struct in_device *in_dev;
++ struct vlan_group *vg;
++ int i;
++
++ QETH_DBF_TEXT(TRACE, 4, "addmcvl");
++ if (!qeth_is_supported(card, IPA_FULL_VLAN) || (card->vlangrp == NULL))
++ return;
++
++ vg = card->vlangrp;
++ for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
++ struct net_device *netdev = vlan_group_get_device(vg, i);
++ if (netdev == NULL ||
++ !(netdev->flags & IFF_UP))
++ continue;
++ in_dev = in_dev_get(netdev);
++ if (!in_dev)
++ continue;
++ read_lock(&in_dev->mc_list_lock);
++ qeth_l3_add_mc(card, in_dev);
++ read_unlock(&in_dev->mc_list_lock);
++ in_dev_put(in_dev);
++ }
++}
++
++static void qeth_l3_add_multicast_ipv4(struct qeth_card *card)
++{
++ struct in_device *in4_dev;
++
++ QETH_DBF_TEXT(TRACE, 4, "chkmcv4");
++ in4_dev = in_dev_get(card->dev);
++ if (in4_dev == NULL)
++ return;
++ read_lock(&in4_dev->mc_list_lock);
++ qeth_l3_add_mc(card, in4_dev);
++ qeth_l3_add_vlan_mc(card);
++ read_unlock(&in4_dev->mc_list_lock);
++ in_dev_put(in4_dev);
++}
++
++#ifdef CONFIG_QETH_IPV6
++static void qeth_l3_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev)
++{
++ struct qeth_ipaddr *ipm;
++ struct ifmcaddr6 *im6;
++ char buf[MAX_ADDR_LEN];
++
++ QETH_DBF_TEXT(TRACE, 4, "addmc6");
++ for (im6 = in6_dev->mc_list; im6 != NULL; im6 = im6->next) {
++ ndisc_mc_map(&im6->mca_addr, buf, in6_dev->dev, 0);
++ ipm = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
++ if (!ipm)
++ continue;
++ ipm->is_multicast = 1;
++ memcpy(ipm->mac, buf, OSA_ADDR_LEN);
++ memcpy(&ipm->u.a6.addr, &im6->mca_addr.s6_addr,
++ sizeof(struct in6_addr));
++ if (!qeth_l3_add_ip(card, ipm))
++ kfree(ipm);
++ }
++}
++
++static void qeth_l3_add_vlan_mc6(struct qeth_card *card)
++{
++ struct inet6_dev *in_dev;
++ struct vlan_group *vg;
++ int i;
++
++ QETH_DBF_TEXT(TRACE, 4, "admc6vl");
++ if (!qeth_is_supported(card, IPA_FULL_VLAN) || (card->vlangrp == NULL))
++ return;
++
++ vg = card->vlangrp;
++ for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
++ struct net_device *netdev = vlan_group_get_device(vg, i);
++ if (netdev == NULL ||
++ !(netdev->flags & IFF_UP))
++ continue;
++ in_dev = in6_dev_get(netdev);
++ if (!in_dev)
++ continue;
++ read_lock_bh(&in_dev->lock);
++ qeth_l3_add_mc6(card, in_dev);
++ read_unlock_bh(&in_dev->lock);
++ in6_dev_put(in_dev);
++ }
++}
++
++static void qeth_l3_add_multicast_ipv6(struct qeth_card *card)
++{
++ struct inet6_dev *in6_dev;
++
++ QETH_DBF_TEXT(TRACE, 4, "chkmcv6");
++ if (!qeth_is_supported(card, IPA_IPV6))
++ return ;
++ in6_dev = in6_dev_get(card->dev);
++ if (in6_dev == NULL)
++ return;
++ read_lock_bh(&in6_dev->lock);
++ qeth_l3_add_mc6(card, in6_dev);
++ qeth_l3_add_vlan_mc6(card);
++ read_unlock_bh(&in6_dev->lock);
++ in6_dev_put(in6_dev);
++}
++#endif /* CONFIG_QETH_IPV6 */
++
++static void qeth_l3_free_vlan_addresses4(struct qeth_card *card,
++ unsigned short vid)
++{
++ struct in_device *in_dev;
++ struct in_ifaddr *ifa;
++ struct qeth_ipaddr *addr;
++
++ QETH_DBF_TEXT(TRACE, 4, "frvaddr4");
++
++ in_dev = in_dev_get(vlan_group_get_device(card->vlangrp, vid));
++ if (!in_dev)
++ return;
++ for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
++ addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV4);
++ if (addr) {
++ addr->u.a4.addr = ifa->ifa_address;
++ addr->u.a4.mask = ifa->ifa_mask;
++ addr->type = QETH_IP_TYPE_NORMAL;
++ if (!qeth_l3_delete_ip(card, addr))
++ kfree(addr);
++ }
++ }
++ in_dev_put(in_dev);
++}
++
++static void qeth_l3_free_vlan_addresses6(struct qeth_card *card,
++ unsigned short vid)
++{
++#ifdef CONFIG_QETH_IPV6
++ struct inet6_dev *in6_dev;
++ struct inet6_ifaddr *ifa;
++ struct qeth_ipaddr *addr;
++
++ QETH_DBF_TEXT(TRACE, 4, "frvaddr6");
++
++ in6_dev = in6_dev_get(vlan_group_get_device(card->vlangrp, vid));
++ if (!in6_dev)
++ return;
++ for (ifa = in6_dev->addr_list; ifa; ifa = ifa->lst_next) {
++ addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
++ if (addr) {
++ memcpy(&addr->u.a6.addr, &ifa->addr,
++ sizeof(struct in6_addr));
++ addr->u.a6.pfxlen = ifa->prefix_len;
++ addr->type = QETH_IP_TYPE_NORMAL;
++ if (!qeth_l3_delete_ip(card, addr))
++ kfree(addr);
++ }
++ }
++ in6_dev_put(in6_dev);
++#endif /* CONFIG_QETH_IPV6 */
++}
++
++static void qeth_l3_free_vlan_addresses(struct qeth_card *card,
++ unsigned short vid)
++{
++ if (!card->vlangrp)
++ return;
++ qeth_l3_free_vlan_addresses4(card, vid);
++ qeth_l3_free_vlan_addresses6(card, vid);
++}
++
++static void qeth_l3_vlan_rx_register(struct net_device *dev,
++ struct vlan_group *grp)
++{
++ struct qeth_card *card = netdev_priv(dev);
++ unsigned long flags;
++
++ QETH_DBF_TEXT(TRACE, 4, "vlanreg");
++ spin_lock_irqsave(&card->vlanlock, flags);
++ card->vlangrp = grp;
++ spin_unlock_irqrestore(&card->vlanlock, flags);
++}
++
++static void qeth_l3_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
++{
++ struct net_device *vlandev;
++ struct qeth_card *card = (struct qeth_card *) dev->priv;
++ struct in_device *in_dev;
++
++ if (card->info.type == QETH_CARD_TYPE_IQD)
++ return;
++
++ vlandev = vlan_group_get_device(card->vlangrp, vid);
++ vlandev->neigh_setup = qeth_l3_neigh_setup;
++
++ in_dev = in_dev_get(vlandev);
++#ifdef CONFIG_SYSCTL
++ neigh_sysctl_unregister(in_dev->arp_parms);
++#endif
++ neigh_parms_release(&arp_tbl, in_dev->arp_parms);
++
++ in_dev->arp_parms = neigh_parms_alloc(vlandev, &arp_tbl);
++#ifdef CONFIG_SYSCTL
++ neigh_sysctl_register(vlandev, in_dev->arp_parms, NET_IPV4,
++ NET_IPV4_NEIGH, "ipv4", NULL, NULL);
++#endif
++ in_dev_put(in_dev);
++ return;
++}
++
++static void qeth_l3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
++{
++ struct qeth_card *card = netdev_priv(dev);
++ unsigned long flags;
++
++ QETH_DBF_TEXT_(TRACE, 4, "kid:%d", vid);
++ spin_lock_irqsave(&card->vlanlock, flags);
++ /* unregister IP addresses of vlan device */
++ qeth_l3_free_vlan_addresses(card, vid);
++ vlan_group_set_device(card->vlangrp, vid, NULL);
++ spin_unlock_irqrestore(&card->vlanlock, flags);
++ qeth_l3_set_multicast_list(card->dev);
++}
++
++static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card,
++ struct sk_buff *skb, struct qeth_hdr *hdr)
++{
++ unsigned short vlan_id = 0;
++ __be16 prot;
++ struct iphdr *ip_hdr;
++ unsigned char tg_addr[MAX_ADDR_LEN];
++
++ if (!(hdr->hdr.l3.flags & QETH_HDR_PASSTHRU)) {
++ prot = htons((hdr->hdr.l3.flags & QETH_HDR_IPV6)? ETH_P_IPV6 :
++ ETH_P_IP);
++ switch (hdr->hdr.l3.flags & QETH_HDR_CAST_MASK) {
++ case QETH_CAST_MULTICAST:
++ switch (prot) {
++#ifdef CONFIG_QETH_IPV6
++ case __constant_htons(ETH_P_IPV6):
++ ndisc_mc_map((struct in6_addr *)
++ skb->data + 24,
++ tg_addr, card->dev, 0);
++ break;
++#endif
++ case __constant_htons(ETH_P_IP):
++ ip_hdr = (struct iphdr *)skb->data;
++ (card->dev->type == ARPHRD_IEEE802_TR) ?
++ ip_tr_mc_map(ip_hdr->daddr, tg_addr):
++ ip_eth_mc_map(ip_hdr->daddr, tg_addr);
++ break;
++ default:
++ memcpy(tg_addr, card->dev->broadcast,
++ card->dev->addr_len);
++ }
++ card->stats.multicast++;
++ skb->pkt_type = PACKET_MULTICAST;
++ break;
++ case QETH_CAST_BROADCAST:
++ memcpy(tg_addr, card->dev->broadcast,
++ card->dev->addr_len);
++ card->stats.multicast++;
++ skb->pkt_type = PACKET_BROADCAST;
++ break;
++ case QETH_CAST_UNICAST:
++ case QETH_CAST_ANYCAST:
++ case QETH_CAST_NOCAST:
++ default:
++ skb->pkt_type = PACKET_HOST;
++ memcpy(tg_addr, card->dev->dev_addr,
++ card->dev->addr_len);
++ }
++ card->dev->header_ops->create(skb, card->dev, prot, tg_addr,
++ "FAKELL", card->dev->addr_len);
++ }
++
++#ifdef CONFIG_TR
++ if (card->dev->type == ARPHRD_IEEE802_TR)
++ skb->protocol = tr_type_trans(skb, card->dev);
++ else
++#endif
++ skb->protocol = eth_type_trans(skb, card->dev);
++
++ if (hdr->hdr.l3.ext_flags &
++ (QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) {
++ vlan_id = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME)?
++ hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]);
++ }
++
++ skb->ip_summed = card->options.checksum_type;
++ if (card->options.checksum_type == HW_CHECKSUMMING) {
++ if ((hdr->hdr.l3.ext_flags &
++ (QETH_HDR_EXT_CSUM_HDR_REQ |
++ QETH_HDR_EXT_CSUM_TRANSP_REQ)) ==
++ (QETH_HDR_EXT_CSUM_HDR_REQ |
++ QETH_HDR_EXT_CSUM_TRANSP_REQ))
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++ else
++ skb->ip_summed = SW_CHECKSUMMING;
++ }
++
++ return vlan_id;
++}
++
++static void qeth_l3_process_inbound_buffer(struct qeth_card *card,
++ struct qeth_qdio_buffer *buf, int index)
++{
++ struct qdio_buffer_element *element;
++ struct sk_buff *skb;
++ struct qeth_hdr *hdr;
++ int offset;
++ __u16 vlan_tag = 0;
++ unsigned int len;
++
++ /* get first element of current buffer */
++ element = (struct qdio_buffer_element *)&buf->buffer->element[0];
++ offset = 0;
++ if (card->options.performance_stats)
++ card->perf_stats.bufs_rec++;
++ while ((skb = qeth_core_get_next_skb(card, buf->buffer, &element,
++ &offset, &hdr))) {
++ skb->dev = card->dev;
++ /* is device UP ? */
++ if (!(card->dev->flags & IFF_UP)) {
++ dev_kfree_skb_any(skb);
++ continue;
++ }
++
++ switch (hdr->hdr.l3.id) {
++ case QETH_HEADER_TYPE_LAYER3:
++ vlan_tag = qeth_l3_rebuild_skb(card, skb, hdr);
++ len = skb->len;
++ if (vlan_tag)
++ if (card->vlangrp)
++ vlan_hwaccel_rx(skb, card->vlangrp,
++ vlan_tag);
++ else {
++ dev_kfree_skb_any(skb);
++ continue;
++ }
++ else
++ netif_rx(skb);
++ break;
++ default:
++ dev_kfree_skb_any(skb);
++ QETH_DBF_TEXT(TRACE, 3, "inbunkno");
++ QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN);
++ continue;
++ }
++
++ card->dev->last_rx = jiffies;
++ card->stats.rx_packets++;
++ card->stats.rx_bytes += len;
++ }
++}
++
++static int qeth_l3_verify_vlan_dev(struct net_device *dev,
++ struct qeth_card *card)
++{
++ int rc = 0;
++ struct vlan_group *vg;
++ int i;
++
++ vg = card->vlangrp;
++ if (!vg)
++ return rc;
++
++ for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
++ if (vlan_group_get_device(vg, i) == dev) {
++ rc = QETH_VLAN_CARD;
++ break;
++ }
++ }
++
++ if (rc && !(netdev_priv(vlan_dev_info(dev)->real_dev) == (void *)card))
++ return 0;
++
++ return rc;
++}
++
++static int qeth_l3_verify_dev(struct net_device *dev)
++{
++ struct qeth_card *card;
++ unsigned long flags;
++ int rc = 0;
++
++ read_lock_irqsave(&qeth_core_card_list.rwlock, flags);
++ list_for_each_entry(card, &qeth_core_card_list.list, list) {
++ if (card->dev == dev) {
++ rc = QETH_REAL_CARD;
++ break;
++ }
++ rc = qeth_l3_verify_vlan_dev(dev, card);
++ if (rc)
++ break;
++ }
++ read_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
++
++ return rc;
++}
++
++static struct qeth_card *qeth_l3_get_card_from_dev(struct net_device *dev)
++{
++ struct qeth_card *card = NULL;
++ int rc;
++
++ rc = qeth_l3_verify_dev(dev);
++ if (rc == QETH_REAL_CARD)
++ card = netdev_priv(dev);
++ else if (rc == QETH_VLAN_CARD)
++ card = netdev_priv(vlan_dev_info(dev)->real_dev);
++ if (card->options.layer2)
++ card = NULL;
++ QETH_DBF_TEXT_(TRACE, 4, "%d", rc);
++ return card ;
++}
++
++static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
++{
++ int rc = 0;
++
++ QETH_DBF_TEXT(SETUP, 2, "stopcard");
++ QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
++
++ qeth_set_allowed_threads(card, 0, 1);
++ if (qeth_wait_for_threads(card, ~QETH_RECOVER_THREAD))
++ return -ERESTARTSYS;
++ if (card->read.state == CH_STATE_UP &&
++ card->write.state == CH_STATE_UP &&
++ (card->state == CARD_STATE_UP)) {
++ if (recovery_mode)
++ qeth_l3_stop(card->dev);
++ if (!card->use_hard_stop) {
++ rc = qeth_send_stoplan(card);
++ if (rc)
++ QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++ }
++ card->state = CARD_STATE_SOFTSETUP;
++ }
++ if (card->state == CARD_STATE_SOFTSETUP) {
++ qeth_l3_clear_ip_list(card, !card->use_hard_stop, 1);
++ qeth_clear_ipacmd_list(card);
++ card->state = CARD_STATE_HARDSETUP;
++ }
++ if (card->state == CARD_STATE_HARDSETUP) {
++ if (!card->use_hard_stop &&
++ (card->info.type != QETH_CARD_TYPE_IQD)) {
++ rc = qeth_l3_put_unique_id(card);
++ if (rc)
++ QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
++ }
++ qeth_qdio_clear_card(card, 0);
++ qeth_clear_qdio_buffers(card);
++ qeth_clear_working_pool_list(card);
++ card->state = CARD_STATE_DOWN;
++ }
++ if (card->state == CARD_STATE_DOWN) {
++ qeth_clear_cmd_buffers(&card->read);
++ qeth_clear_cmd_buffers(&card->write);
++ }
++ card->use_hard_stop = 0;
++ return rc;
++}
++
++static void qeth_l3_set_multicast_list(struct net_device *dev)
++{
++ struct qeth_card *card = netdev_priv(dev);
++
++ QETH_DBF_TEXT(TRACE, 3, "setmulti");
++ qeth_l3_delete_mc_addresses(card);
++ qeth_l3_add_multicast_ipv4(card);
++#ifdef CONFIG_QETH_IPV6
++ qeth_l3_add_multicast_ipv6(card);
++#endif
++ qeth_l3_set_ip_addr_list(card);
++ if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
++ return;
++ qeth_setadp_promisc_mode(card);
++}
++
++static const char *qeth_l3_arp_get_error_cause(int *rc)
++{
++ switch (*rc) {
++ case QETH_IPA_ARP_RC_FAILED:
++ *rc = -EIO;
++ return "operation failed";
++ case QETH_IPA_ARP_RC_NOTSUPP:
++ *rc = -EOPNOTSUPP;
++ return "operation not supported";
++ case QETH_IPA_ARP_RC_OUT_OF_RANGE:
++ *rc = -EINVAL;
++ return "argument out of range";
++ case QETH_IPA_ARP_RC_Q_NOTSUPP:
++ *rc = -EOPNOTSUPP;
++ return "query operation not supported";
++ case QETH_IPA_ARP_RC_Q_NO_DATA:
++ *rc = -ENOENT;
++ return "no query data available";
++ default:
++ return "unknown error";
++ }
++}
++
++static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries)
++{
++ int tmp;
++ int rc;
++
++ QETH_DBF_TEXT(TRACE, 3, "arpstnoe");
++
++ /*
++ * currently GuestLAN only supports the ARP assist function
++ * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_SET_NO_ENTRIES;
++ * thus we say EOPNOTSUPP for this ARP function
++ */
++ if (card->info.guestlan)
++ return -EOPNOTSUPP;
++ if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
++ PRINT_WARN("ARP processing not supported "
++ "on %s!\n", QETH_CARD_IFNAME(card));
++ return -EOPNOTSUPP;
++ }
++ rc = qeth_l3_send_simple_setassparms(card, IPA_ARP_PROCESSING,
++ IPA_CMD_ASS_ARP_SET_NO_ENTRIES,
++ no_entries);
++ if (rc) {
++ tmp = rc;
++ PRINT_WARN("Could not set number of ARP entries on %s: "
++ "%s (0x%x/%d)\n", QETH_CARD_IFNAME(card),
++ qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
++ }
++ return rc;
++}
++
++static void qeth_l3_copy_arp_entries_stripped(struct qeth_arp_query_info *qinfo,
++ struct qeth_arp_query_data *qdata, int entry_size,
++ int uentry_size)
++{
++ char *entry_ptr;
++ char *uentry_ptr;
++ int i;
++
++ entry_ptr = (char *)&qdata->data;
++ uentry_ptr = (char *)(qinfo->udata + qinfo->udata_offset);
++ for (i = 0; i < qdata->no_entries; ++i) {
++ /* strip off 32 bytes "media specific information" */
++ memcpy(uentry_ptr, (entry_ptr + 32), entry_size - 32);
++ entry_ptr += entry_size;
++ uentry_ptr += uentry_size;
++ }
++}
++
++static int qeth_l3_arp_query_cb(struct qeth_card *card,
++ struct qeth_reply *reply, unsigned long data)
++{
++ struct qeth_ipa_cmd *cmd;
++ struct qeth_arp_query_data *qdata;
++ struct qeth_arp_query_info *qinfo;
++ int entry_size;
++ int uentry_size;
++ int i;
++
++ QETH_DBF_TEXT(TRACE, 4, "arpquecb");
++
++ qinfo = (struct qeth_arp_query_info *) reply->param;
++ cmd = (struct qeth_ipa_cmd *) data;
++ if (cmd->hdr.return_code) {
++ QETH_DBF_TEXT_(TRACE, 4, "qaer1%i", cmd->hdr.return_code);
++ return 0;
++ }
++ if (cmd->data.setassparms.hdr.return_code) {
++ cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code;
++ QETH_DBF_TEXT_(TRACE, 4, "qaer2%i", cmd->hdr.return_code);
++ return 0;
++ }
++ qdata = &cmd->data.setassparms.data.query_arp;
++ switch (qdata->reply_bits) {
++ case 5:
++ uentry_size = entry_size = sizeof(struct qeth_arp_qi_entry5);
++ if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES)
++ uentry_size = sizeof(struct qeth_arp_qi_entry5_short);
++ break;
++ case 7:
++ /* fall through to default */
++ default:
++ /* tr is the same as eth -> entry7 */
++ uentry_size = entry_size = sizeof(struct qeth_arp_qi_entry7);
++ if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES)
++ uentry_size = sizeof(struct qeth_arp_qi_entry7_short);
++ break;
++ }
++ /* check if there is enough room in userspace */
++ if ((qinfo->udata_len - qinfo->udata_offset) <
++ qdata->no_entries * uentry_size){
++ QETH_DBF_TEXT_(TRACE, 4, "qaer3%i", -ENOMEM);
++ cmd->hdr.return_code = -ENOMEM;
++ PRINT_WARN("query ARP user space buffer is too small for "
++ "the returned number of ARP entries. "
++ "Aborting query!\n");
++ goto out_error;
++ }
++ QETH_DBF_TEXT_(TRACE, 4, "anore%i",
++ cmd->data.setassparms.hdr.number_of_replies);
++ QETH_DBF_TEXT_(TRACE, 4, "aseqn%i", cmd->data.setassparms.hdr.seq_no);
++ QETH_DBF_TEXT_(TRACE, 4, "anoen%i", qdata->no_entries);
++
++ if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES) {
++ /* strip off "media specific information" */
++ qeth_l3_copy_arp_entries_stripped(qinfo, qdata, entry_size,
++ uentry_size);
++ } else
++ /*copy entries to user buffer*/
++ memcpy(qinfo->udata + qinfo->udata_offset,
++ (char *)&qdata->data, qdata->no_entries*uentry_size);
++
++ qinfo->no_entries += qdata->no_entries;
++ qinfo->udata_offset += (qdata->no_entries*uentry_size);
++ /* check if all replies received ... */
++ if (cmd->data.setassparms.hdr.seq_no <
++ cmd->data.setassparms.hdr.number_of_replies)
++ return 1;
++ memcpy(qinfo->udata, &qinfo->no_entries, 4);
++ /* keep STRIP_ENTRIES flag so the user program can distinguish
++ * stripped entries from normal ones */
++ if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES)
++ qdata->reply_bits |= QETH_QARP_STRIP_ENTRIES;
++ memcpy(qinfo->udata + QETH_QARP_MASK_OFFSET, &qdata->reply_bits, 2);
++ return 0;
++out_error:
++ i = 0;
++ memcpy(qinfo->udata, &i, 4);
++ return 0;
++}
++
++static int qeth_l3_send_ipa_arp_cmd(struct qeth_card *card,
++ struct qeth_cmd_buffer *iob, int len,
++ int (*reply_cb)(struct qeth_card *, struct qeth_reply *,
++ unsigned long),
++ void *reply_param)
++{
++ QETH_DBF_TEXT(TRACE, 4, "sendarp");
++
++ memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
++ memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
++ &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
++ return qeth_send_control_data(card, IPA_PDU_HEADER_SIZE + len, iob,
++ reply_cb, reply_param);
++}
++
++static int qeth_l3_arp_query(struct qeth_card *card, char __user *udata)
++{
++ struct qeth_cmd_buffer *iob;
++ struct qeth_arp_query_info qinfo = {0, };
++ int tmp;
++ int rc;
++
++ QETH_DBF_TEXT(TRACE, 3, "arpquery");
++
++ if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/
++ IPA_ARP_PROCESSING)) {
++ PRINT_WARN("ARP processing not supported "
++ "on %s!\n", QETH_CARD_IFNAME(card));
++ return -EOPNOTSUPP;
++ }
++ /* get size of userspace buffer and mask_bits -> 6 bytes */
++ if (copy_from_user(&qinfo, udata, 6))
++ return -EFAULT;
++ qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL);
++ if (!qinfo.udata)
++ return -ENOMEM;
++ qinfo.udata_offset = QETH_QARP_ENTRIES_OFFSET;
++ iob = qeth_l3_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
++ IPA_CMD_ASS_ARP_QUERY_INFO,
++ sizeof(int), QETH_PROT_IPV4);
++
++ rc = qeth_l3_send_ipa_arp_cmd(card, iob,
++ QETH_SETASS_BASE_LEN+QETH_ARP_CMD_LEN,
++ qeth_l3_arp_query_cb, (void *)&qinfo);
++ if (rc) {
++ tmp = rc;
++ PRINT_WARN("Error while querying ARP cache on %s: %s "
++ "(0x%x/%d)\n", QETH_CARD_IFNAME(card),
++ qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
++ if (copy_to_user(udata, qinfo.udata, 4))
++ rc = -EFAULT;
++ } else {
++ if (copy_to_user(udata, qinfo.udata, qinfo.udata_len))
++ rc = -EFAULT;
++ }
++ kfree(qinfo.udata);
++ return rc;
++}
++
++static int qeth_l3_arp_add_entry(struct qeth_card *card,
++ struct qeth_arp_cache_entry *entry)
++{
++ struct qeth_cmd_buffer *iob;
++ char buf[16];
++ int tmp;
++ int rc;
++
++ QETH_DBF_TEXT(TRACE, 3, "arpadent");
++
++ /*
++ * currently GuestLAN only supports the ARP assist function
++ * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_ADD_ENTRY;
++ * thus we say EOPNOTSUPP for this ARP function
++ */
++ if (card->info.guestlan)
++ return -EOPNOTSUPP;
++ if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
++ PRINT_WARN("ARP processing not supported "
++ "on %s!\n", QETH_CARD_IFNAME(card));
++ return -EOPNOTSUPP;
++ }
++
++ iob = qeth_l3_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
++ IPA_CMD_ASS_ARP_ADD_ENTRY,
++ sizeof(struct qeth_arp_cache_entry),
++ QETH_PROT_IPV4);
++ rc = qeth_l3_send_setassparms(card, iob,
++ sizeof(struct qeth_arp_cache_entry),
++ (unsigned long) entry,
++ qeth_l3_default_setassparms_cb, NULL);
++ if (rc) {
++ tmp = rc;
++ qeth_l3_ipaddr4_to_string((u8 *)entry->ipaddr, buf);
++ PRINT_WARN("Could not add ARP entry for address %s on %s: "
++ "%s (0x%x/%d)\n",
++ buf, QETH_CARD_IFNAME(card),
++ qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
++ }
++ return rc;
++}
++
++static int qeth_l3_arp_remove_entry(struct qeth_card *card,
++ struct qeth_arp_cache_entry *entry)
++{
++ struct qeth_cmd_buffer *iob;
++ char buf[16] = {0, };
++ int tmp;
++ int rc;
++
++ QETH_DBF_TEXT(TRACE, 3, "arprment");
++
++ /*
++ * currently GuestLAN only supports the ARP assist function
++ * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_REMOVE_ENTRY;
++ * thus we say EOPNOTSUPP for this ARP function
++ */
++ if (card->info.guestlan)
++ return -EOPNOTSUPP;
++ if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
++ PRINT_WARN("ARP processing not supported "
++ "on %s!\n", QETH_CARD_IFNAME(card));
++ return -EOPNOTSUPP;
++ }
++ memcpy(buf, entry, 12);
++ iob = qeth_l3_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
++ IPA_CMD_ASS_ARP_REMOVE_ENTRY,
++ 12,
++ QETH_PROT_IPV4);
++ rc = qeth_l3_send_setassparms(card, iob,
++ 12, (unsigned long)buf,
++ qeth_l3_default_setassparms_cb, NULL);
++ if (rc) {
++ tmp = rc;
++ memset(buf, 0, 16);
++ qeth_l3_ipaddr4_to_string((u8 *)entry->ipaddr, buf);
++ PRINT_WARN("Could not delete ARP entry for address %s on %s: "
++ "%s (0x%x/%d)\n",
++ buf, QETH_CARD_IFNAME(card),
++ qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
++ }
++ return rc;
++}
++
++static int qeth_l3_arp_flush_cache(struct qeth_card *card)
++{
++ int rc;
++ int tmp;
++
++ QETH_DBF_TEXT(TRACE, 3, "arpflush");
++
++ /*
++ * currently GuestLAN only supports the ARP assist function
++ * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_FLUSH_CACHE;
++ * thus we say EOPNOTSUPP for this ARP function
++ */
++ if (card->info.guestlan || (card->info.type == QETH_CARD_TYPE_IQD))
++ return -EOPNOTSUPP;
++ if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
++ PRINT_WARN("ARP processing not supported "
++ "on %s!\n", QETH_CARD_IFNAME(card));
++ return -EOPNOTSUPP;
++ }
++ rc = qeth_l3_send_simple_setassparms(card, IPA_ARP_PROCESSING,
++ IPA_CMD_ASS_ARP_FLUSH_CACHE, 0);
++ if (rc) {
++ tmp = rc;
++ PRINT_WARN("Could not flush ARP cache on %s: %s (0x%x/%d)\n",
++ QETH_CARD_IFNAME(card),
++ qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
++ }
++ return rc;
++}
++
++static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
++{
++ struct qeth_card *card = netdev_priv(dev);
++ struct qeth_arp_cache_entry arp_entry;
++ struct mii_ioctl_data *mii_data;
++ int rc = 0;
++
++ if (!card)
++ return -ENODEV;
++
++ if ((card->state != CARD_STATE_UP) &&
++ (card->state != CARD_STATE_SOFTSETUP))
++ return -ENODEV;
++
++ switch (cmd) {
++ case SIOC_QETH_ARP_SET_NO_ENTRIES:
++ if (!capable(CAP_NET_ADMIN)) {
++ rc = -EPERM;
++ break;
++ }
++ rc = qeth_l3_arp_set_no_entries(card, rq->ifr_ifru.ifru_ivalue);
++ break;
++ case SIOC_QETH_ARP_QUERY_INFO:
++ if (!capable(CAP_NET_ADMIN)) {
++ rc = -EPERM;
++ break;
++ }
++ rc = qeth_l3_arp_query(card, rq->ifr_ifru.ifru_data);
++ break;
++ case SIOC_QETH_ARP_ADD_ENTRY:
++ if (!capable(CAP_NET_ADMIN)) {
++ rc = -EPERM;
++ break;
++ }
++ if (copy_from_user(&arp_entry, rq->ifr_ifru.ifru_data,
++ sizeof(struct qeth_arp_cache_entry)))
++ rc = -EFAULT;
++ else
++ rc = qeth_l3_arp_add_entry(card, &arp_entry);
++ break;
++ case SIOC_QETH_ARP_REMOVE_ENTRY:
++ if (!capable(CAP_NET_ADMIN)) {
++ rc = -EPERM;
++ break;
++ }
++ if (copy_from_user(&arp_entry, rq->ifr_ifru.ifru_data,
++ sizeof(struct qeth_arp_cache_entry)))
++ rc = -EFAULT;
++ else
++ rc = qeth_l3_arp_remove_entry(card, &arp_entry);
++ break;
++ case SIOC_QETH_ARP_FLUSH_CACHE:
++ if (!capable(CAP_NET_ADMIN)) {
++ rc = -EPERM;
++ break;
++ }
++ rc = qeth_l3_arp_flush_cache(card);
++ break;
++ case SIOC_QETH_ADP_SET_SNMP_CONTROL:
++ rc = qeth_snmp_command(card, rq->ifr_ifru.ifru_data);
++ break;
++ case SIOC_QETH_GET_CARD_TYPE:
++ if ((card->info.type == QETH_CARD_TYPE_OSAE) &&
++ !card->info.guestlan)
++ return 1;
++ return 0;
++ break;
++ case SIOCGMIIPHY:
++ mii_data = if_mii(rq);
++ mii_data->phy_id = 0;
++ break;
++ case SIOCGMIIREG:
++ mii_data = if_mii(rq);
++ if (mii_data->phy_id != 0)
++ rc = -EINVAL;
++ else
++ mii_data->val_out = qeth_mdio_read(dev,
++ mii_data->phy_id,
++ mii_data->reg_num);
++ break;
++ default:
++ rc = -EOPNOTSUPP;
++ }
++ if (rc)
++ QETH_DBF_TEXT_(TRACE, 2, "ioce%d", rc);
++ return rc;
++}
++
++static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
++ struct sk_buff *skb, int ipv, int cast_type)
++{
++ QETH_DBF_TEXT(TRACE, 6, "fillhdr");
++
++ memset(hdr, 0, sizeof(struct qeth_hdr));
++ hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3;
++ hdr->hdr.l3.ext_flags = 0;
++
++ /*
++ * before we're going to overwrite this location with next hop ip.
++ * v6 uses passthrough, v4 sets the tag in the QDIO header.
++ */
++ if (card->vlangrp && vlan_tx_tag_present(skb)) {
++ hdr->hdr.l3.ext_flags = (ipv == 4) ?
++ QETH_HDR_EXT_VLAN_FRAME :
++ QETH_HDR_EXT_INCLUDE_VLAN_TAG;
++ hdr->hdr.l3.vlan_id = vlan_tx_tag_get(skb);
++ }
++
++ hdr->hdr.l3.length = skb->len - sizeof(struct qeth_hdr);
++ if (ipv == 4) {
++ /* IPv4 */
++ hdr->hdr.l3.flags = qeth_l3_get_qeth_hdr_flags4(cast_type);
++ memset(hdr->hdr.l3.dest_addr, 0, 12);
++ if ((skb->dst) && (skb->dst->neighbour)) {
++ *((u32 *) (&hdr->hdr.l3.dest_addr[12])) =
++ *((u32 *) skb->dst->neighbour->primary_key);
++ } else {
++ /* fill in destination address used in ip header */
++ *((u32 *) (&hdr->hdr.l3.dest_addr[12])) =
++ ip_hdr(skb)->daddr;
++ }
++ } else if (ipv == 6) {
++ /* IPv6 */
++ hdr->hdr.l3.flags = qeth_l3_get_qeth_hdr_flags6(cast_type);
++ if (card->info.type == QETH_CARD_TYPE_IQD)
++ hdr->hdr.l3.flags &= ~QETH_HDR_PASSTHRU;
++ if ((skb->dst) && (skb->dst->neighbour)) {
++ memcpy(hdr->hdr.l3.dest_addr,
++ skb->dst->neighbour->primary_key, 16);
++ } else {
++ /* fill in destination address used in ip header */
++ memcpy(hdr->hdr.l3.dest_addr,
++ &ipv6_hdr(skb)->daddr, 16);
++ }
++ } else {
++ /* passthrough */
++ if ((skb->dev->type == ARPHRD_IEEE802_TR) &&
++ !memcmp(skb->data + sizeof(struct qeth_hdr) +
++ sizeof(__u16), skb->dev->broadcast, 6)) {
++ hdr->hdr.l3.flags = QETH_CAST_BROADCAST |
++ QETH_HDR_PASSTHRU;
++ } else if (!memcmp(skb->data + sizeof(struct qeth_hdr),
++ skb->dev->broadcast, 6)) {
++ /* broadcast? */
++ hdr->hdr.l3.flags = QETH_CAST_BROADCAST |
++ QETH_HDR_PASSTHRU;
++ } else {
++ hdr->hdr.l3.flags = (cast_type == RTN_MULTICAST) ?
++ QETH_CAST_MULTICAST | QETH_HDR_PASSTHRU :
++ QETH_CAST_UNICAST | QETH_HDR_PASSTHRU;
++ }
++ }
++}
++
++static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++ int rc;
++ u16 *tag;
++ struct qeth_hdr *hdr = NULL;
++ int elements_needed = 0;
++ struct qeth_card *card = netdev_priv(dev);
++ struct sk_buff *new_skb = NULL;
++ int ipv = qeth_get_ip_version(skb);
++ int cast_type = qeth_get_cast_type(card, skb);
++ struct qeth_qdio_out_q *queue = card->qdio.out_qs
++ [qeth_get_priority_queue(card, skb, ipv, cast_type)];
++ int tx_bytes = skb->len;
++ enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
++ struct qeth_eddp_context *ctx = NULL;
++
++ QETH_DBF_TEXT(TRACE, 6, "l3xmit");
++
++ if ((card->info.type == QETH_CARD_TYPE_IQD) &&
++ (skb->protocol != htons(ETH_P_IPV6)) &&
++ (skb->protocol != htons(ETH_P_IP)))
++ goto tx_drop;
++
++ if ((card->state != CARD_STATE_UP) || !card->lan_online) {
++ card->stats.tx_carrier_errors++;
++ goto tx_drop;
++ }
++
++ if ((cast_type == RTN_BROADCAST) &&
++ (card->info.broadcast_capable == 0))
++ goto tx_drop;
++
++ if (card->options.performance_stats) {
++ card->perf_stats.outbound_cnt++;
++ card->perf_stats.outbound_start_time = qeth_get_micros();
++ }
++
++ /* create a clone with writeable headroom */
++ new_skb = skb_realloc_headroom(skb, sizeof(struct qeth_hdr_tso) +
++ VLAN_HLEN);
++ if (!new_skb)
++ goto tx_drop;
++
++ if (card->info.type == QETH_CARD_TYPE_IQD) {
++ skb_pull(new_skb, ETH_HLEN);
++ } else {
++ if (new_skb->protocol == htons(ETH_P_IP)) {
++ if (card->dev->type == ARPHRD_IEEE802_TR)
++ skb_pull(new_skb, TR_HLEN);
++ else
++ skb_pull(new_skb, ETH_HLEN);
++ }
++
++ if (new_skb->protocol == ETH_P_IPV6 && card->vlangrp &&
++ vlan_tx_tag_present(new_skb)) {
++ skb_push(new_skb, VLAN_HLEN);
++ skb_copy_to_linear_data(new_skb, new_skb->data + 4, 4);
++ skb_copy_to_linear_data_offset(new_skb, 4,
++ new_skb->data + 8, 4);
++ skb_copy_to_linear_data_offset(new_skb, 8,
++ new_skb->data + 12, 4);
++ tag = (u16 *)(new_skb->data + 12);
++ *tag = __constant_htons(ETH_P_8021Q);
++ *(tag + 1) = htons(vlan_tx_tag_get(new_skb));
++ VLAN_TX_SKB_CB(new_skb)->magic = 0;
++ }
++ }
++
++ netif_stop_queue(dev);
++
++ if (skb_is_gso(new_skb))
++ large_send = card->options.large_send;
++
++ /* fix hardware limitation: as long as we do not have sbal
++ * chaining we can not send long frag lists so we temporary
++ * switch to EDDP
++ */
++ if ((large_send == QETH_LARGE_SEND_TSO) &&
++ ((skb_shinfo(new_skb)->nr_frags + 2) > 16))
++ large_send = QETH_LARGE_SEND_EDDP;
++
++ if ((large_send == QETH_LARGE_SEND_TSO) &&
++ (cast_type == RTN_UNSPEC)) {
++ hdr = (struct qeth_hdr *)skb_push(new_skb,
++ sizeof(struct qeth_hdr_tso));
++ memset(hdr, 0, sizeof(struct qeth_hdr_tso));
++ qeth_l3_fill_header(card, hdr, new_skb, ipv, cast_type);
++ qeth_tso_fill_header(card, hdr, new_skb);
++ elements_needed++;
++ } else {
++ hdr = (struct qeth_hdr *)skb_push(new_skb,
++ sizeof(struct qeth_hdr));
++ qeth_l3_fill_header(card, hdr, new_skb, ipv, cast_type);
++ }
++
++ if (large_send == QETH_LARGE_SEND_EDDP) {
++ /* new_skb is not owned by a socket so we use skb to get
++ * the protocol
++ */
++ ctx = qeth_eddp_create_context(card, new_skb, hdr,
++ skb->sk->sk_protocol);
++ if (ctx == NULL) {
++ PRINT_WARN("could not create eddp context\n");
++ goto tx_drop;
++ }
++ } else {
++ int elems = qeth_get_elements_no(card, (void *)hdr, new_skb,
++ elements_needed);
++ if (!elems)
++ goto tx_drop;
++ elements_needed += elems;
++ }
++
++ if ((large_send == QETH_LARGE_SEND_NO) &&
++ (new_skb->ip_summed == CHECKSUM_PARTIAL))
++ qeth_tx_csum(new_skb);
++
++ if (card->info.type != QETH_CARD_TYPE_IQD)
++ rc = qeth_do_send_packet(card, queue, new_skb, hdr,
++ elements_needed, ctx);
++ else
++ rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr,
++ elements_needed, ctx);
++
++ if (!rc) {
++ card->stats.tx_packets++;
++ card->stats.tx_bytes += tx_bytes;
++ if (new_skb != skb)
++ dev_kfree_skb_any(skb);
++ if (card->options.performance_stats) {
++ if (large_send != QETH_LARGE_SEND_NO) {
++ card->perf_stats.large_send_bytes += tx_bytes;
++ card->perf_stats.large_send_cnt++;
++ }
++ if (skb_shinfo(new_skb)->nr_frags > 0) {
++ card->perf_stats.sg_skbs_sent++;
++ /* nr_frags + skb->data */
++ card->perf_stats.sg_frags_sent +=
++ skb_shinfo(new_skb)->nr_frags + 1;
++ }
++ }
++
++ if (ctx != NULL) {
++ qeth_eddp_put_context(ctx);
++ dev_kfree_skb_any(new_skb);
++ }
++ } else {
++ if (ctx != NULL)
++ qeth_eddp_put_context(ctx);
++
++ if (rc == -EBUSY) {
++ if (new_skb != skb)
++ dev_kfree_skb_any(new_skb);
++ return NETDEV_TX_BUSY;
++ } else
++ goto tx_drop;
++ }
++
++ netif_wake_queue(dev);
++ if (card->options.performance_stats)
++ card->perf_stats.outbound_time += qeth_get_micros() -
++ card->perf_stats.outbound_start_time;
++ return rc;
++
++tx_drop:
++ card->stats.tx_dropped++;
++ card->stats.tx_errors++;
++ if ((new_skb != skb) && new_skb)
++ dev_kfree_skb_any(new_skb);
++ dev_kfree_skb_any(skb);
++ return NETDEV_TX_OK;
++}
++
++static int qeth_l3_open(struct net_device *dev)
++{
++ struct qeth_card *card = netdev_priv(dev);
++
++ QETH_DBF_TEXT(TRACE, 4, "qethopen");
++ if (card->state != CARD_STATE_SOFTSETUP)
++ return -ENODEV;
++ card->data.state = CH_STATE_UP;
++ card->state = CARD_STATE_UP;
++ card->dev->flags |= IFF_UP;
++ netif_start_queue(dev);
++
++ if (!card->lan_online && netif_carrier_ok(dev))
++ netif_carrier_off(dev);
++ return 0;
++}
++
++static int qeth_l3_stop(struct net_device *dev)
++{
++ struct qeth_card *card = netdev_priv(dev);
++
++ QETH_DBF_TEXT(TRACE, 4, "qethstop");
++ netif_tx_disable(dev);
++ card->dev->flags &= ~IFF_UP;
++ if (card->state == CARD_STATE_UP)
++ card->state = CARD_STATE_SOFTSETUP;
++ return 0;
++}
++
++static u32 qeth_l3_ethtool_get_rx_csum(struct net_device *dev)
++{
++ struct qeth_card *card = netdev_priv(dev);
++
++ return (card->options.checksum_type == HW_CHECKSUMMING);
++}
++
++static int qeth_l3_ethtool_set_rx_csum(struct net_device *dev, u32 data)
++{
++ struct qeth_card *card = netdev_priv(dev);
++ enum qeth_card_states old_state;
++ enum qeth_checksum_types csum_type;
++
++ if ((card->state != CARD_STATE_UP) &&
++ (card->state != CARD_STATE_DOWN))
++ return -EPERM;
++
++ if (data)
++ csum_type = HW_CHECKSUMMING;
++ else
++ csum_type = SW_CHECKSUMMING;
++
++ if (card->options.checksum_type != csum_type) {
++ old_state = card->state;
++ if (card->state == CARD_STATE_UP)
++ __qeth_l3_set_offline(card->gdev, 1);
++ card->options.checksum_type = csum_type;
++ if (old_state == CARD_STATE_UP)
++ __qeth_l3_set_online(card->gdev, 1);
++ }
++ return 0;
++}
++
++static int qeth_l3_ethtool_set_tso(struct net_device *dev, u32 data)
++{
++ struct qeth_card *card = netdev_priv(dev);
++
++ if (data) {
++ if (card->options.large_send == QETH_LARGE_SEND_NO) {
++ if (card->info.type == QETH_CARD_TYPE_IQD)
++ card->options.large_send = QETH_LARGE_SEND_EDDP;
++ else
++ card->options.large_send = QETH_LARGE_SEND_TSO;
++ dev->features |= NETIF_F_TSO;
++ }
++ } else {
++ dev->features &= ~NETIF_F_TSO;
++ card->options.large_send = QETH_LARGE_SEND_NO;
++ }
++ return 0;
++}
++
++static struct ethtool_ops qeth_l3_ethtool_ops = {
++ .get_link = ethtool_op_get_link,
++ .get_tx_csum = ethtool_op_get_tx_csum,
++ .set_tx_csum = ethtool_op_set_tx_hw_csum,
++ .get_rx_csum = qeth_l3_ethtool_get_rx_csum,
++ .set_rx_csum = qeth_l3_ethtool_set_rx_csum,
++ .get_sg = ethtool_op_get_sg,
++ .set_sg = ethtool_op_set_sg,
++ .get_tso = ethtool_op_get_tso,
++ .set_tso = qeth_l3_ethtool_set_tso,
++ .get_strings = qeth_core_get_strings,
++ .get_ethtool_stats = qeth_core_get_ethtool_stats,
++ .get_stats_count = qeth_core_get_stats_count,
++ .get_drvinfo = qeth_core_get_drvinfo,
++};
++
++/*
++ * we need NOARP for IPv4 but we want neighbor solicitation for IPv6. Setting
++ * NOARP on the netdevice is no option because it also turns off neighbor
++ * solicitation. For IPv4 we install a neighbor_setup function. We don't want
++ * arp resolution but we want the hard header (packet socket will work
++ * e.g. tcpdump)
++ */
++static int qeth_l3_neigh_setup_noarp(struct neighbour *n)
++{
++ n->nud_state = NUD_NOARP;
++ memcpy(n->ha, "FAKELL", 6);
++ n->output = n->ops->connected_output;
++ return 0;
++}
++
++static int
++qeth_l3_neigh_setup(struct net_device *dev, struct neigh_parms *np)
++{
++ if (np->tbl->family == AF_INET)
++ np->neigh_setup = qeth_l3_neigh_setup_noarp;
++
++ return 0;
++}
++
++static int qeth_l3_setup_netdev(struct qeth_card *card)
++{
++ if (card->info.type == QETH_CARD_TYPE_OSAE) {
++ if ((card->info.link_type == QETH_LINK_TYPE_LANE_TR) ||
++ (card->info.link_type == QETH_LINK_TYPE_HSTR)) {
++#ifdef CONFIG_TR
++ card->dev = alloc_trdev(0);
++#endif
++ if (!card->dev)
++ return -ENODEV;
++ } else {
++ card->dev = alloc_etherdev(0);
++ if (!card->dev)
++ return -ENODEV;
++ card->dev->neigh_setup = qeth_l3_neigh_setup;
++
++ /*IPv6 address autoconfiguration stuff*/
++ qeth_l3_get_unique_id(card);
++ if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD))
++ card->dev->dev_id = card->info.unique_id &
++ 0xffff;
++ }
++ } else if (card->info.type == QETH_CARD_TYPE_IQD) {
++ card->dev = alloc_netdev(0, "hsi%d", ether_setup);
++ if (!card->dev)
++ return -ENODEV;
++ card->dev->flags |= IFF_NOARP;
++ qeth_l3_iqd_read_initial_mac(card);
++ } else
++ return -ENODEV;
++
++ card->dev->hard_start_xmit = qeth_l3_hard_start_xmit;
++ card->dev->priv = card;
++ card->dev->tx_timeout = &qeth_tx_timeout;
++ card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
++ card->dev->open = qeth_l3_open;
++ card->dev->stop = qeth_l3_stop;
++ card->dev->do_ioctl = qeth_l3_do_ioctl;
++ card->dev->get_stats = qeth_get_stats;
++ card->dev->change_mtu = qeth_change_mtu;
++ card->dev->set_multicast_list = qeth_l3_set_multicast_list;
++ card->dev->vlan_rx_register = qeth_l3_vlan_rx_register;
++ card->dev->vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid;
++ card->dev->vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid;
++ card->dev->mtu = card->info.initial_mtu;
++ card->dev->set_mac_address = NULL;
++ SET_ETHTOOL_OPS(card->dev, &qeth_l3_ethtool_ops);
++ card->dev->features |= NETIF_F_HW_VLAN_TX |
++ NETIF_F_HW_VLAN_RX |
++ NETIF_F_HW_VLAN_FILTER;
++
++ SET_NETDEV_DEV(card->dev, &card->gdev->dev);
++ return register_netdev(card->dev);
++}
++
++static void qeth_l3_qdio_input_handler(struct ccw_device *ccwdev,
++ unsigned int status, unsigned int qdio_err,
++ unsigned int siga_err, unsigned int queue, int first_element,
++ int count, unsigned long card_ptr)
++{
++ struct net_device *net_dev;
++ struct qeth_card *card;
++ struct qeth_qdio_buffer *buffer;
++ int index;
++ int i;
++
++ QETH_DBF_TEXT(TRACE, 6, "qdinput");
++ card = (struct qeth_card *) card_ptr;
++ net_dev = card->dev;
++ if (card->options.performance_stats) {
++ card->perf_stats.inbound_cnt++;
++ card->perf_stats.inbound_start_time = qeth_get_micros();
++ }
++ if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
++ if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION) {
++ QETH_DBF_TEXT(TRACE, 1, "qdinchk");
++ QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
++ QETH_DBF_TEXT_(TRACE, 1, "%04X%04X",
++ first_element, count);
++ QETH_DBF_TEXT_(TRACE, 1, "%04X%04X", queue, status);
++ qeth_schedule_recovery(card);
++ return;
++ }
++ }
++ for (i = first_element; i < (first_element + count); ++i) {
++ index = i % QDIO_MAX_BUFFERS_PER_Q;
++ buffer = &card->qdio.in_q->bufs[index];
++ if (!((status & QDIO_STATUS_LOOK_FOR_ERROR) &&
++ qeth_check_qdio_errors(buffer->buffer,
++ qdio_err, siga_err, "qinerr")))
++ qeth_l3_process_inbound_buffer(card, buffer, index);
++ /* clear buffer and give back to hardware */
++ qeth_put_buffer_pool_entry(card, buffer->pool_entry);
++ qeth_queue_input_buffer(card, index);
++ }
++ if (card->options.performance_stats)
++ card->perf_stats.inbound_time += qeth_get_micros() -
++ card->perf_stats.inbound_start_time;
++}
++
++static int qeth_l3_probe_device(struct ccwgroup_device *gdev)
++{
++ struct qeth_card *card = dev_get_drvdata(&gdev->dev);
++
++ qeth_l3_create_device_attributes(&gdev->dev);
++ card->options.layer2 = 0;
++ card->discipline.input_handler = (qdio_handler_t *)
++ qeth_l3_qdio_input_handler;
++ card->discipline.output_handler = (qdio_handler_t *)
++ qeth_qdio_output_handler;
++ card->discipline.recover = qeth_l3_recover;
++ return 0;
++}
++
++static void qeth_l3_remove_device(struct ccwgroup_device *cgdev)
++{
++ struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
++
++ wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
++
++ if (cgdev->state == CCWGROUP_ONLINE) {
++ card->use_hard_stop = 1;
++ qeth_l3_set_offline(cgdev);
++ }
++
++ if (card->dev) {
++ unregister_netdev(card->dev);
++ card->dev = NULL;
++ }
++
++ qeth_l3_remove_device_attributes(&cgdev->dev);
++ qeth_l3_clear_ip_list(card, 0, 0);
++ qeth_l3_clear_ipato_list(card);
++ return;
++}
++
++static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
++{
++ struct qeth_card *card = dev_get_drvdata(&gdev->dev);
++ int rc = 0;
++ enum qeth_card_states recover_flag;
++
++ BUG_ON(!card);
++ QETH_DBF_TEXT(SETUP, 2, "setonlin");
++ QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
++
++ qeth_set_allowed_threads(card, QETH_RECOVER_THREAD, 1);
++ if (qeth_wait_for_threads(card, ~QETH_RECOVER_THREAD)) {
++ PRINT_WARN("set_online of card %s interrupted by user!\n",
++ CARD_BUS_ID(card));
++ return -ERESTARTSYS;
++ }
++
++ recover_flag = card->state;
++ rc = ccw_device_set_online(CARD_RDEV(card));
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++ return -EIO;
++ }
++ rc = ccw_device_set_online(CARD_WDEV(card));
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++ return -EIO;
++ }
++ rc = ccw_device_set_online(CARD_DDEV(card));
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++ return -EIO;
++ }
++
++ rc = qeth_core_hardsetup_card(card);
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
++ goto out_remove;
++ }
++
++ qeth_l3_query_ipassists(card, QETH_PROT_IPV4);
++
++ if (!card->dev && qeth_l3_setup_netdev(card))
++ goto out_remove;
++
++ card->state = CARD_STATE_HARDSETUP;
++ qeth_print_status_message(card);
++
++ /* softsetup */
++ QETH_DBF_TEXT(SETUP, 2, "softsetp");
++
++ rc = qeth_send_startlan(card);
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++ if (rc == 0xe080) {
++ PRINT_WARN("LAN on card %s if offline! "
++ "Waiting for STARTLAN from card.\n",
++ CARD_BUS_ID(card));
++ card->lan_online = 0;
++ }
++ return rc;
++ } else
++ card->lan_online = 1;
++ qeth_set_large_send(card, card->options.large_send);
++
++ rc = qeth_l3_setadapter_parms(card);
++ if (rc)
++ QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
++ rc = qeth_l3_start_ipassists(card);
++ if (rc)
++ QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc);
++ rc = qeth_l3_setrouting_v4(card);
++ if (rc)
++ QETH_DBF_TEXT_(SETUP, 2, "4err%d", rc);
++ rc = qeth_l3_setrouting_v6(card);
++ if (rc)
++ QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc);
++ netif_tx_disable(card->dev);
++
++ rc = qeth_init_qdio_queues(card);
++ if (rc) {
++ QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);
++ goto out_remove;
++ }
++ card->state = CARD_STATE_SOFTSETUP;
++ netif_carrier_on(card->dev);
++
++ qeth_set_allowed_threads(card, 0xffffffff, 0);
++ if ((recover_flag == CARD_STATE_RECOVER) && recovery_mode) {
++ qeth_l3_open(card->dev);
++ qeth_l3_set_multicast_list(card->dev);
++ }
++ /* let user_space know that device is online */
++ kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
++ return 0;
++out_remove:
++ card->use_hard_stop = 1;
++ qeth_l3_stop_card(card, 0);
++ ccw_device_set_offline(CARD_DDEV(card));
++ ccw_device_set_offline(CARD_WDEV(card));
++ ccw_device_set_offline(CARD_RDEV(card));
++ if (recover_flag == CARD_STATE_RECOVER)
++ card->state = CARD_STATE_RECOVER;
++ else
++ card->state = CARD_STATE_DOWN;
++ return -ENODEV;
++}
++
++static int qeth_l3_set_online(struct ccwgroup_device *gdev)
++{
++ return __qeth_l3_set_online(gdev, 0);
++}
++
++static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev,
++ int recovery_mode)
++{
++ struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
++ int rc = 0, rc2 = 0, rc3 = 0;
++ enum qeth_card_states recover_flag;
++
++ QETH_DBF_TEXT(SETUP, 3, "setoffl");
++ QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *));
++
++ if (card->dev && netif_carrier_ok(card->dev))
++ netif_carrier_off(card->dev);
++ recover_flag = card->state;
++ if (qeth_l3_stop_card(card, recovery_mode) == -ERESTARTSYS) {
++ PRINT_WARN("Stopping card %s interrupted by user!\n",
++ CARD_BUS_ID(card));
++ return -ERESTARTSYS;
++ }
++ rc = ccw_device_set_offline(CARD_DDEV(card));
++ rc2 = ccw_device_set_offline(CARD_WDEV(card));
++ rc3 = ccw_device_set_offline(CARD_RDEV(card));
++ if (!rc)
++ rc = (rc2) ? rc2 : rc3;
++ if (rc)
++ QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
++ if (recover_flag == CARD_STATE_UP)
++ card->state = CARD_STATE_RECOVER;
++ /* let user_space know that device is offline */
++ kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE);
++ return 0;
++}
++
++static int qeth_l3_set_offline(struct ccwgroup_device *cgdev)
++{
++ return __qeth_l3_set_offline(cgdev, 0);
++}
++
++static int qeth_l3_recover(void *ptr)
++{
++ struct qeth_card *card;
++ int rc = 0;
++
++ card = (struct qeth_card *) ptr;
++ QETH_DBF_TEXT(TRACE, 2, "recover1");
++ QETH_DBF_HEX(TRACE, 2, &card, sizeof(void *));
++ if (!qeth_do_run_thread(card, QETH_RECOVER_THREAD))
++ return 0;
++ QETH_DBF_TEXT(TRACE, 2, "recover2");
++ PRINT_WARN("Recovery of device %s started ...\n",
++ CARD_BUS_ID(card));
++ card->use_hard_stop = 1;
++ __qeth_l3_set_offline(card->gdev, 1);
++ rc = __qeth_l3_set_online(card->gdev, 1);
++ /* don't run another scheduled recovery */
++ qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
++ qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
++ if (!rc)
++ PRINT_INFO("Device %s successfully recovered!\n",
++ CARD_BUS_ID(card));
++ else
++ PRINT_INFO("Device %s could not be recovered!\n",
++ CARD_BUS_ID(card));
++ return 0;
++}
++
++static void qeth_l3_shutdown(struct ccwgroup_device *gdev)
++{
++ struct qeth_card *card = dev_get_drvdata(&gdev->dev);
++ qeth_l3_clear_ip_list(card, 0, 0);
++ qeth_qdio_clear_card(card, 0);
++ qeth_clear_qdio_buffers(card);
++}
++
++struct ccwgroup_driver qeth_l3_ccwgroup_driver = {
++ .probe = qeth_l3_probe_device,
++ .remove = qeth_l3_remove_device,
++ .set_online = qeth_l3_set_online,
++ .set_offline = qeth_l3_set_offline,
++ .shutdown = qeth_l3_shutdown,
++};
++EXPORT_SYMBOL_GPL(qeth_l3_ccwgroup_driver);
++
++static int qeth_l3_ip_event(struct notifier_block *this,
++ unsigned long event, void *ptr)
++{
++ struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
++ struct net_device *dev = (struct net_device *)ifa->ifa_dev->dev;
++ struct qeth_ipaddr *addr;
++ struct qeth_card *card;
++
++ if (dev_net(dev) != &init_net)
++ return NOTIFY_DONE;
++
++ QETH_DBF_TEXT(TRACE, 3, "ipevent");
++ card = qeth_l3_get_card_from_dev(dev);
++ if (!card)
++ return NOTIFY_DONE;
++
++ addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV4);
++ if (addr != NULL) {
++ addr->u.a4.addr = ifa->ifa_address;
++ addr->u.a4.mask = ifa->ifa_mask;
++ addr->type = QETH_IP_TYPE_NORMAL;
++ } else
++ goto out;
++
++ switch (event) {
++ case NETDEV_UP:
++ if (!qeth_l3_add_ip(card, addr))
++ kfree(addr);
++ break;
++ case NETDEV_DOWN:
++ if (!qeth_l3_delete_ip(card, addr))
++ kfree(addr);
++ break;
++ default:
++ break;
++ }
++ qeth_l3_set_ip_addr_list(card);
++out:
++ return NOTIFY_DONE;
++}
++
++static struct notifier_block qeth_l3_ip_notifier = {
++ qeth_l3_ip_event,
++ NULL,
++};
++
++#ifdef CONFIG_QETH_IPV6
++/**
++ * IPv6 event handler
++ */
++static int qeth_l3_ip6_event(struct notifier_block *this,
++ unsigned long event, void *ptr)
++{
++ struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
++ struct net_device *dev = (struct net_device *)ifa->idev->dev;
++ struct qeth_ipaddr *addr;
++ struct qeth_card *card;
++
++ QETH_DBF_TEXT(TRACE, 3, "ip6event");
++
++ card = qeth_l3_get_card_from_dev(dev);
++ if (!card)
++ return NOTIFY_DONE;
++ if (!qeth_is_supported(card, IPA_IPV6))
++ return NOTIFY_DONE;
++
++ addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
++ if (addr != NULL) {
++ memcpy(&addr->u.a6.addr, &ifa->addr, sizeof(struct in6_addr));
++ addr->u.a6.pfxlen = ifa->prefix_len;
++ addr->type = QETH_IP_TYPE_NORMAL;
++ } else
++ goto out;
++
++ switch (event) {
++ case NETDEV_UP:
++ if (!qeth_l3_add_ip(card, addr))
++ kfree(addr);
++ break;
++ case NETDEV_DOWN:
++ if (!qeth_l3_delete_ip(card, addr))
++ kfree(addr);
++ break;
++ default:
++ break;
++ }
++ qeth_l3_set_ip_addr_list(card);
++out:
++ return NOTIFY_DONE;
++}
++
++static struct notifier_block qeth_l3_ip6_notifier = {
++ qeth_l3_ip6_event,
++ NULL,
++};
++#endif
++
++static int qeth_l3_register_notifiers(void)
++{
++ int rc;
++
++ QETH_DBF_TEXT(TRACE, 5, "regnotif");
++ rc = register_inetaddr_notifier(&qeth_l3_ip_notifier);
++ if (rc)
++ return rc;
++#ifdef CONFIG_QETH_IPV6
++ rc = register_inet6addr_notifier(&qeth_l3_ip6_notifier);
++ if (rc) {
++ unregister_inetaddr_notifier(&qeth_l3_ip_notifier);
++ return rc;
++ }
++#else
++ PRINT_WARN("layer 3 discipline no IPv6 support\n");
++#endif
++ return 0;
++}
++
++static void qeth_l3_unregister_notifiers(void)
++{
++
++ QETH_DBF_TEXT(TRACE, 5, "unregnot");
++ BUG_ON(unregister_inetaddr_notifier(&qeth_l3_ip_notifier));
++#ifdef CONFIG_QETH_IPV6
++ BUG_ON(unregister_inet6addr_notifier(&qeth_l3_ip6_notifier));
++#endif /* QETH_IPV6 */
++}
++
++static int __init qeth_l3_init(void)
++{
++ int rc = 0;
++
++ PRINT_INFO("register layer 3 discipline\n");
++ rc = qeth_l3_register_notifiers();
++ return rc;
++}
++
++static void __exit qeth_l3_exit(void)
++{
++ qeth_l3_unregister_notifiers();
++ PRINT_INFO("unregister layer 3 discipline\n");
++}
++
++module_init(qeth_l3_init);
++module_exit(qeth_l3_exit);
++MODULE_AUTHOR("Frank Blaschka <frank.blaschka at de.ibm.com>");
++MODULE_DESCRIPTION("qeth layer 3 discipline");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c
+new file mode 100644
+index 0000000..08f51fd
+--- /dev/null
++++ b/drivers/s390/net/qeth_l3_sys.c
+@@ -0,0 +1,1051 @@
++/*
++ * drivers/s390/net/qeth_l3_sys.c
++ *
++ * Copyright IBM Corp. 2007
++ * Author(s): Utz Bacher <utz.bacher at de.ibm.com>,
++ * Frank Pavlic <fpavlic at de.ibm.com>,
++ * Thomas Spatzier <tspat at de.ibm.com>,
++ * Frank Blaschka <frank.blaschka at de.ibm.com>
++ */
++
++#include "qeth_l3.h"
++
++#define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \
++struct device_attribute dev_attr_##_id = __ATTR(_name, _mode, _show, _store)
++
++static const char *qeth_l3_get_checksum_str(struct qeth_card *card)
++{
++ if (card->options.checksum_type == SW_CHECKSUMMING)
++ return "sw";
++ else if (card->options.checksum_type == HW_CHECKSUMMING)
++ return "hw";
++ else
++ return "no";
++}
++
++static ssize_t qeth_l3_dev_route_show(struct qeth_card *card,
++ struct qeth_routing_info *route, char *buf)
++{
++ switch (route->type) {
++ case PRIMARY_ROUTER:
++ return sprintf(buf, "%s\n", "primary router");
++ case SECONDARY_ROUTER:
++ return sprintf(buf, "%s\n", "secondary router");
++ case MULTICAST_ROUTER:
++ if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
++ return sprintf(buf, "%s\n", "multicast router+");
++ else
++ return sprintf(buf, "%s\n", "multicast router");
++ case PRIMARY_CONNECTOR:
++ if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
++ return sprintf(buf, "%s\n", "primary connector+");
++ else
++ return sprintf(buf, "%s\n", "primary connector");
++ case SECONDARY_CONNECTOR:
++ if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
++ return sprintf(buf, "%s\n", "secondary connector+");
++ else
++ return sprintf(buf, "%s\n", "secondary connector");
++ default:
++ return sprintf(buf, "%s\n", "no");
++ }
++}
++
++static ssize_t qeth_l3_dev_route4_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return qeth_l3_dev_route_show(card, &card->options.route4, buf);
++}
++
++static ssize_t qeth_l3_dev_route_store(struct qeth_card *card,
++ struct qeth_routing_info *route, enum qeth_prot_versions prot,
++ const char *buf, size_t count)
++{
++ enum qeth_routing_types old_route_type = route->type;
++ char *tmp;
++ int rc;
++
++ tmp = strsep((char **) &buf, "\n");
++
++ if (!strcmp(tmp, "no_router")) {
++ route->type = NO_ROUTER;
++ } else if (!strcmp(tmp, "primary_connector")) {
++ route->type = PRIMARY_CONNECTOR;
++ } else if (!strcmp(tmp, "secondary_connector")) {
++ route->type = SECONDARY_CONNECTOR;
++ } else if (!strcmp(tmp, "primary_router")) {
++ route->type = PRIMARY_ROUTER;
++ } else if (!strcmp(tmp, "secondary_router")) {
++ route->type = SECONDARY_ROUTER;
++ } else if (!strcmp(tmp, "multicast_router")) {
++ route->type = MULTICAST_ROUTER;
++ } else {
++ PRINT_WARN("Invalid routing type '%s'.\n", tmp);
++ return -EINVAL;
++ }
++ if (((card->state == CARD_STATE_SOFTSETUP) ||
++ (card->state == CARD_STATE_UP)) &&
++ (old_route_type != route->type)) {
++ if (prot == QETH_PROT_IPV4)
++ rc = qeth_l3_setrouting_v4(card);
++ else if (prot == QETH_PROT_IPV6)
++ rc = qeth_l3_setrouting_v6(card);
++ }
++ return count;
++}
++
++static ssize_t qeth_l3_dev_route4_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return qeth_l3_dev_route_store(card, &card->options.route4,
++ QETH_PROT_IPV4, buf, count);
++}
++
++static DEVICE_ATTR(route4, 0644, qeth_l3_dev_route4_show,
++ qeth_l3_dev_route4_store);
++
++static ssize_t qeth_l3_dev_route6_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ if (!qeth_is_supported(card, IPA_IPV6))
++ return sprintf(buf, "%s\n", "n/a");
++
++ return qeth_l3_dev_route_show(card, &card->options.route6, buf);
++}
++
++static ssize_t qeth_l3_dev_route6_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ if (!qeth_is_supported(card, IPA_IPV6)) {
++ PRINT_WARN("IPv6 not supported for interface %s.\n"
++ "Routing status no changed.\n",
++ QETH_CARD_IFNAME(card));
++ return -ENOTSUPP;
++ }
++
++ return qeth_l3_dev_route_store(card, &card->options.route6,
++ QETH_PROT_IPV6, buf, count);
++}
++
++static DEVICE_ATTR(route6, 0644, qeth_l3_dev_route6_show,
++ qeth_l3_dev_route6_store);
++
++static ssize_t qeth_l3_dev_fake_broadcast_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return sprintf(buf, "%i\n", card->options.fake_broadcast? 1:0);
++}
++
++static ssize_t qeth_l3_dev_fake_broadcast_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++ char *tmp;
++ int i;
++
++ if (!card)
++ return -EINVAL;
++
++ if ((card->state != CARD_STATE_DOWN) &&
++ (card->state != CARD_STATE_RECOVER))
++ return -EPERM;
++
++ i = simple_strtoul(buf, &tmp, 16);
++ if ((i == 0) || (i == 1))
++ card->options.fake_broadcast = i;
++ else {
++ PRINT_WARN("fake_broadcast: write 0 or 1 to this file!\n");
++ return -EINVAL;
++ }
++ return count;
++}
++
++static DEVICE_ATTR(fake_broadcast, 0644, qeth_l3_dev_fake_broadcast_show,
++ qeth_l3_dev_fake_broadcast_store);
++
++static ssize_t qeth_l3_dev_broadcast_mode_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
++ (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
++ return sprintf(buf, "n/a\n");
++
++ return sprintf(buf, "%s\n", (card->options.broadcast_mode ==
++ QETH_TR_BROADCAST_ALLRINGS)?
++ "all rings":"local");
++}
++
++static ssize_t qeth_l3_dev_broadcast_mode_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++ char *tmp;
++
++ if (!card)
++ return -EINVAL;
++
++ if ((card->state != CARD_STATE_DOWN) &&
++ (card->state != CARD_STATE_RECOVER))
++ return -EPERM;
++
++ if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
++ (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) {
++ PRINT_WARN("Device is not a tokenring device!\n");
++ return -EINVAL;
++ }
++
++ tmp = strsep((char **) &buf, "\n");
++
++ if (!strcmp(tmp, "local")) {
++ card->options.broadcast_mode = QETH_TR_BROADCAST_LOCAL;
++ return count;
++ } else if (!strcmp(tmp, "all_rings")) {
++ card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS;
++ return count;
++ } else {
++ PRINT_WARN("broadcast_mode: invalid mode %s!\n",
++ tmp);
++ return -EINVAL;
++ }
++ return count;
++}
++
++static DEVICE_ATTR(broadcast_mode, 0644, qeth_l3_dev_broadcast_mode_show,
++ qeth_l3_dev_broadcast_mode_store);
++
++static ssize_t qeth_l3_dev_canonical_macaddr_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
++ (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
++ return sprintf(buf, "n/a\n");
++
++ return sprintf(buf, "%i\n", (card->options.macaddr_mode ==
++ QETH_TR_MACADDR_CANONICAL)? 1:0);
++}
++
++static ssize_t qeth_l3_dev_canonical_macaddr_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++ char *tmp;
++ int i;
++
++ if (!card)
++ return -EINVAL;
++
++ if ((card->state != CARD_STATE_DOWN) &&
++ (card->state != CARD_STATE_RECOVER))
++ return -EPERM;
++
++ if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
++ (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) {
++ PRINT_WARN("Device is not a tokenring device!\n");
++ return -EINVAL;
++ }
++
++ i = simple_strtoul(buf, &tmp, 16);
++ if ((i == 0) || (i == 1))
++ card->options.macaddr_mode = i?
++ QETH_TR_MACADDR_CANONICAL :
++ QETH_TR_MACADDR_NONCANONICAL;
++ else {
++ PRINT_WARN("canonical_macaddr: write 0 or 1 to this file!\n");
++ return -EINVAL;
++ }
++ return count;
++}
++
++static DEVICE_ATTR(canonical_macaddr, 0644, qeth_l3_dev_canonical_macaddr_show,
++ qeth_l3_dev_canonical_macaddr_store);
++
++static ssize_t qeth_l3_dev_checksum_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return sprintf(buf, "%s checksumming\n",
++ qeth_l3_get_checksum_str(card));
++}
++
++static ssize_t qeth_l3_dev_checksum_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++ char *tmp;
++
++ if (!card)
++ return -EINVAL;
++
++ if ((card->state != CARD_STATE_DOWN) &&
++ (card->state != CARD_STATE_RECOVER))
++ return -EPERM;
++
++ tmp = strsep((char **) &buf, "\n");
++ if (!strcmp(tmp, "sw_checksumming"))
++ card->options.checksum_type = SW_CHECKSUMMING;
++ else if (!strcmp(tmp, "hw_checksumming"))
++ card->options.checksum_type = HW_CHECKSUMMING;
++ else if (!strcmp(tmp, "no_checksumming"))
++ card->options.checksum_type = NO_CHECKSUMMING;
++ else {
++ PRINT_WARN("Unknown checksumming type '%s'\n", tmp);
++ return -EINVAL;
++ }
++ return count;
++}
++
++static DEVICE_ATTR(checksumming, 0644, qeth_l3_dev_checksum_show,
++ qeth_l3_dev_checksum_store);
++
++static struct attribute *qeth_l3_device_attrs[] = {
++ &dev_attr_route4.attr,
++ &dev_attr_route6.attr,
++ &dev_attr_fake_broadcast.attr,
++ &dev_attr_broadcast_mode.attr,
++ &dev_attr_canonical_macaddr.attr,
++ &dev_attr_checksumming.attr,
++ NULL,
++};
++
++static struct attribute_group qeth_l3_device_attr_group = {
++ .attrs = qeth_l3_device_attrs,
++};
++
++static ssize_t qeth_l3_dev_ipato_enable_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return sprintf(buf, "%i\n", card->ipato.enabled? 1:0);
++}
++
++static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++ char *tmp;
++
++ if (!card)
++ return -EINVAL;
++
++ if ((card->state != CARD_STATE_DOWN) &&
++ (card->state != CARD_STATE_RECOVER))
++ return -EPERM;
++
++ tmp = strsep((char **) &buf, "\n");
++ if (!strcmp(tmp, "toggle")) {
++ card->ipato.enabled = (card->ipato.enabled)? 0 : 1;
++ } else if (!strcmp(tmp, "1")) {
++ card->ipato.enabled = 1;
++ } else if (!strcmp(tmp, "0")) {
++ card->ipato.enabled = 0;
++ } else {
++ PRINT_WARN("ipato_enable: write 0, 1 or 'toggle' to "
++ "this file\n");
++ return -EINVAL;
++ }
++ return count;
++}
++
++static QETH_DEVICE_ATTR(ipato_enable, enable, 0644,
++ qeth_l3_dev_ipato_enable_show,
++ qeth_l3_dev_ipato_enable_store);
++
++static ssize_t qeth_l3_dev_ipato_invert4_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return sprintf(buf, "%i\n", card->ipato.invert4? 1:0);
++}
++
++static ssize_t qeth_l3_dev_ipato_invert4_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++ char *tmp;
++
++ if (!card)
++ return -EINVAL;
++
++ tmp = strsep((char **) &buf, "\n");
++ if (!strcmp(tmp, "toggle")) {
++ card->ipato.invert4 = (card->ipato.invert4)? 0 : 1;
++ } else if (!strcmp(tmp, "1")) {
++ card->ipato.invert4 = 1;
++ } else if (!strcmp(tmp, "0")) {
++ card->ipato.invert4 = 0;
++ } else {
++ PRINT_WARN("ipato_invert4: write 0, 1 or 'toggle' to "
++ "this file\n");
++ return -EINVAL;
++ }
++ return count;
++}
++
++static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644,
++ qeth_l3_dev_ipato_invert4_show,
++ qeth_l3_dev_ipato_invert4_store);
++
++static ssize_t qeth_l3_dev_ipato_add_show(char *buf, struct qeth_card *card,
++ enum qeth_prot_versions proto)
++{
++ struct qeth_ipato_entry *ipatoe;
++ unsigned long flags;
++ char addr_str[40];
++ int entry_len; /* length of 1 entry string, differs between v4 and v6 */
++ int i = 0;
++
++ entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
++ /* add strlen for "/<mask>\n" */
++ entry_len += (proto == QETH_PROT_IPV4)? 5 : 6;
++ spin_lock_irqsave(&card->ip_lock, flags);
++ list_for_each_entry(ipatoe, &card->ipato.entries, entry) {
++ if (ipatoe->proto != proto)
++ continue;
++ /* String must not be longer than PAGE_SIZE. So we check if
++ * string length gets near PAGE_SIZE. Then we can savely display
++ * the next IPv6 address (worst case, compared to IPv4) */
++ if ((PAGE_SIZE - i) <= entry_len)
++ break;
++ qeth_l3_ipaddr_to_string(proto, ipatoe->addr, addr_str);
++ i += snprintf(buf + i, PAGE_SIZE - i,
++ "%s/%i\n", addr_str, ipatoe->mask_bits);
++ }
++ spin_unlock_irqrestore(&card->ip_lock, flags);
++ i += snprintf(buf + i, PAGE_SIZE - i, "\n");
++
++ return i;
++}
++
++static ssize_t qeth_l3_dev_ipato_add4_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV4);
++}
++
++static int qeth_l3_parse_ipatoe(const char *buf, enum qeth_prot_versions proto,
++ u8 *addr, int *mask_bits)
++{
++ const char *start, *end;
++ char *tmp;
++ char buffer[40] = {0, };
++
++ start = buf;
++ /* get address string */
++ end = strchr(start, '/');
++ if (!end || (end - start >= 40)) {
++ PRINT_WARN("Invalid format for ipato_addx/delx. "
++ "Use <ip addr>/<mask bits>\n");
++ return -EINVAL;
++ }
++ strncpy(buffer, start, end - start);
++ if (qeth_l3_string_to_ipaddr(buffer, proto, addr)) {
++ PRINT_WARN("Invalid IP address format!\n");
++ return -EINVAL;
++ }
++ start = end + 1;
++ *mask_bits = simple_strtoul(start, &tmp, 10);
++ if (!strlen(start) ||
++ (tmp == start) ||
++ (*mask_bits > ((proto == QETH_PROT_IPV4) ? 32 : 128))) {
++ PRINT_WARN("Invalid mask bits for ipato_addx/delx !\n");
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static ssize_t qeth_l3_dev_ipato_add_store(const char *buf, size_t count,
++ struct qeth_card *card, enum qeth_prot_versions proto)
++{
++ struct qeth_ipato_entry *ipatoe;
++ u8 addr[16];
++ int mask_bits;
++ int rc;
++
++ rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
++ if (rc)
++ return rc;
++
++ ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL);
++ if (!ipatoe) {
++ PRINT_WARN("No memory to allocate ipato entry\n");
++ return -ENOMEM;
++ }
++ ipatoe->proto = proto;
++ memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16);
++ ipatoe->mask_bits = mask_bits;
++
++ rc = qeth_l3_add_ipato_entry(card, ipatoe);
++ if (rc) {
++ kfree(ipatoe);
++ return rc;
++ }
++
++ return count;
++}
++
++static ssize_t qeth_l3_dev_ipato_add4_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV4);
++}
++
++static QETH_DEVICE_ATTR(ipato_add4, add4, 0644,
++ qeth_l3_dev_ipato_add4_show,
++ qeth_l3_dev_ipato_add4_store);
++
++static ssize_t qeth_l3_dev_ipato_del_store(const char *buf, size_t count,
++ struct qeth_card *card, enum qeth_prot_versions proto)
++{
++ u8 addr[16];
++ int mask_bits;
++ int rc;
++
++ rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
++ if (rc)
++ return rc;
++
++ qeth_l3_del_ipato_entry(card, proto, addr, mask_bits);
++
++ return count;
++}
++
++static ssize_t qeth_l3_dev_ipato_del4_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV4);
++}
++
++static QETH_DEVICE_ATTR(ipato_del4, del4, 0200, NULL,
++ qeth_l3_dev_ipato_del4_store);
++
++static ssize_t qeth_l3_dev_ipato_invert6_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return sprintf(buf, "%i\n", card->ipato.invert6? 1:0);
++}
++
++static ssize_t qeth_l3_dev_ipato_invert6_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++ char *tmp;
++
++ if (!card)
++ return -EINVAL;
++
++ tmp = strsep((char **) &buf, "\n");
++ if (!strcmp(tmp, "toggle")) {
++ card->ipato.invert6 = (card->ipato.invert6)? 0 : 1;
++ } else if (!strcmp(tmp, "1")) {
++ card->ipato.invert6 = 1;
++ } else if (!strcmp(tmp, "0")) {
++ card->ipato.invert6 = 0;
++ } else {
++ PRINT_WARN("ipato_invert6: write 0, 1 or 'toggle' to "
++ "this file\n");
++ return -EINVAL;
++ }
++ return count;
++}
++
++static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644,
++ qeth_l3_dev_ipato_invert6_show,
++ qeth_l3_dev_ipato_invert6_store);
++
++
++static ssize_t qeth_l3_dev_ipato_add6_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV6);
++}
++
++static ssize_t qeth_l3_dev_ipato_add6_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV6);
++}
++
++static QETH_DEVICE_ATTR(ipato_add6, add6, 0644,
++ qeth_l3_dev_ipato_add6_show,
++ qeth_l3_dev_ipato_add6_store);
++
++static ssize_t qeth_l3_dev_ipato_del6_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV6);
++}
++
++static QETH_DEVICE_ATTR(ipato_del6, del6, 0200, NULL,
++ qeth_l3_dev_ipato_del6_store);
++
++static struct attribute *qeth_ipato_device_attrs[] = {
++ &dev_attr_ipato_enable.attr,
++ &dev_attr_ipato_invert4.attr,
++ &dev_attr_ipato_add4.attr,
++ &dev_attr_ipato_del4.attr,
++ &dev_attr_ipato_invert6.attr,
++ &dev_attr_ipato_add6.attr,
++ &dev_attr_ipato_del6.attr,
++ NULL,
++};
++
++static struct attribute_group qeth_device_ipato_group = {
++ .name = "ipa_takeover",
++ .attrs = qeth_ipato_device_attrs,
++};
++
++static ssize_t qeth_l3_dev_vipa_add_show(char *buf, struct qeth_card *card,
++ enum qeth_prot_versions proto)
++{
++ struct qeth_ipaddr *ipaddr;
++ char addr_str[40];
++ int entry_len; /* length of 1 entry string, differs between v4 and v6 */
++ unsigned long flags;
++ int i = 0;
++
++ entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
++ entry_len += 2; /* \n + terminator */
++ spin_lock_irqsave(&card->ip_lock, flags);
++ list_for_each_entry(ipaddr, &card->ip_list, entry) {
++ if (ipaddr->proto != proto)
++ continue;
++ if (ipaddr->type != QETH_IP_TYPE_VIPA)
++ continue;
++ /* String must not be longer than PAGE_SIZE. So we check if
++ * string length gets near PAGE_SIZE. Then we can savely display
++ * the next IPv6 address (worst case, compared to IPv4) */
++ if ((PAGE_SIZE - i) <= entry_len)
++ break;
++ qeth_l3_ipaddr_to_string(proto, (const u8 *)&ipaddr->u,
++ addr_str);
++ i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
++ }
++ spin_unlock_irqrestore(&card->ip_lock, flags);
++ i += snprintf(buf + i, PAGE_SIZE - i, "\n");
++
++ return i;
++}
++
++static ssize_t qeth_l3_dev_vipa_add4_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return qeth_l3_dev_vipa_add_show(buf, card, QETH_PROT_IPV4);
++}
++
++static int qeth_l3_parse_vipae(const char *buf, enum qeth_prot_versions proto,
++ u8 *addr)
++{
++ if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
++ PRINT_WARN("Invalid IP address format!\n");
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static ssize_t qeth_l3_dev_vipa_add_store(const char *buf, size_t count,
++ struct qeth_card *card, enum qeth_prot_versions proto)
++{
++ u8 addr[16] = {0, };
++ int rc;
++
++ rc = qeth_l3_parse_vipae(buf, proto, addr);
++ if (rc)
++ return rc;
++
++ rc = qeth_l3_add_vipa(card, proto, addr);
++ if (rc)
++ return rc;
++
++ return count;
++}
++
++static ssize_t qeth_l3_dev_vipa_add4_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return qeth_l3_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV4);
++}
++
++static QETH_DEVICE_ATTR(vipa_add4, add4, 0644,
++ qeth_l3_dev_vipa_add4_show,
++ qeth_l3_dev_vipa_add4_store);
++
++static ssize_t qeth_l3_dev_vipa_del_store(const char *buf, size_t count,
++ struct qeth_card *card, enum qeth_prot_versions proto)
++{
++ u8 addr[16];
++ int rc;
++
++ rc = qeth_l3_parse_vipae(buf, proto, addr);
++ if (rc)
++ return rc;
++
++ qeth_l3_del_vipa(card, proto, addr);
++
++ return count;
++}
++
++static ssize_t qeth_l3_dev_vipa_del4_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return qeth_l3_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV4);
++}
++
++static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL,
++ qeth_l3_dev_vipa_del4_store);
++
++static ssize_t qeth_l3_dev_vipa_add6_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return qeth_l3_dev_vipa_add_show(buf, card, QETH_PROT_IPV6);
++}
++
++static ssize_t qeth_l3_dev_vipa_add6_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return qeth_l3_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV6);
++}
++
++static QETH_DEVICE_ATTR(vipa_add6, add6, 0644,
++ qeth_l3_dev_vipa_add6_show,
++ qeth_l3_dev_vipa_add6_store);
++
++static ssize_t qeth_l3_dev_vipa_del6_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return qeth_l3_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV6);
++}
++
++static QETH_DEVICE_ATTR(vipa_del6, del6, 0200, NULL,
++ qeth_l3_dev_vipa_del6_store);
++
++static struct attribute *qeth_vipa_device_attrs[] = {
++ &dev_attr_vipa_add4.attr,
++ &dev_attr_vipa_del4.attr,
++ &dev_attr_vipa_add6.attr,
++ &dev_attr_vipa_del6.attr,
++ NULL,
++};
++
++static struct attribute_group qeth_device_vipa_group = {
++ .name = "vipa",
++ .attrs = qeth_vipa_device_attrs,
++};
++
++static ssize_t qeth_l3_dev_rxip_add_show(char *buf, struct qeth_card *card,
++ enum qeth_prot_versions proto)
++{
++ struct qeth_ipaddr *ipaddr;
++ char addr_str[40];
++ int entry_len; /* length of 1 entry string, differs between v4 and v6 */
++ unsigned long flags;
++ int i = 0;
++
++ entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
++ entry_len += 2; /* \n + terminator */
++ spin_lock_irqsave(&card->ip_lock, flags);
++ list_for_each_entry(ipaddr, &card->ip_list, entry) {
++ if (ipaddr->proto != proto)
++ continue;
++ if (ipaddr->type != QETH_IP_TYPE_RXIP)
++ continue;
++ /* String must not be longer than PAGE_SIZE. So we check if
++ * string length gets near PAGE_SIZE. Then we can savely display
++ * the next IPv6 address (worst case, compared to IPv4) */
++ if ((PAGE_SIZE - i) <= entry_len)
++ break;
++ qeth_l3_ipaddr_to_string(proto, (const u8 *)&ipaddr->u,
++ addr_str);
++ i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
++ }
++ spin_unlock_irqrestore(&card->ip_lock, flags);
++ i += snprintf(buf + i, PAGE_SIZE - i, "\n");
++
++ return i;
++}
++
++static ssize_t qeth_l3_dev_rxip_add4_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return qeth_l3_dev_rxip_add_show(buf, card, QETH_PROT_IPV4);
++}
++
++static int qeth_l3_parse_rxipe(const char *buf, enum qeth_prot_versions proto,
++ u8 *addr)
++{
++ if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
++ PRINT_WARN("Invalid IP address format!\n");
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static ssize_t qeth_l3_dev_rxip_add_store(const char *buf, size_t count,
++ struct qeth_card *card, enum qeth_prot_versions proto)
++{
++ u8 addr[16] = {0, };
++ int rc;
++
++ rc = qeth_l3_parse_rxipe(buf, proto, addr);
++ if (rc)
++ return rc;
++
++ rc = qeth_l3_add_rxip(card, proto, addr);
++ if (rc)
++ return rc;
++
++ return count;
++}
++
++static ssize_t qeth_l3_dev_rxip_add4_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return qeth_l3_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV4);
++}
++
++static QETH_DEVICE_ATTR(rxip_add4, add4, 0644,
++ qeth_l3_dev_rxip_add4_show,
++ qeth_l3_dev_rxip_add4_store);
++
++static ssize_t qeth_l3_dev_rxip_del_store(const char *buf, size_t count,
++ struct qeth_card *card, enum qeth_prot_versions proto)
++{
++ u8 addr[16];
++ int rc;
++
++ rc = qeth_l3_parse_rxipe(buf, proto, addr);
++ if (rc)
++ return rc;
++
++ qeth_l3_del_rxip(card, proto, addr);
++
++ return count;
++}
++
++static ssize_t qeth_l3_dev_rxip_del4_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return qeth_l3_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV4);
++}
++
++static QETH_DEVICE_ATTR(rxip_del4, del4, 0200, NULL,
++ qeth_l3_dev_rxip_del4_store);
++
++static ssize_t qeth_l3_dev_rxip_add6_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return qeth_l3_dev_rxip_add_show(buf, card, QETH_PROT_IPV6);
++}
++
++static ssize_t qeth_l3_dev_rxip_add6_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return qeth_l3_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV6);
++}
++
++static QETH_DEVICE_ATTR(rxip_add6, add6, 0644,
++ qeth_l3_dev_rxip_add6_show,
++ qeth_l3_dev_rxip_add6_store);
++
++static ssize_t qeth_l3_dev_rxip_del6_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct qeth_card *card = dev_get_drvdata(dev);
++
++ if (!card)
++ return -EINVAL;
++
++ return qeth_l3_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV6);
++}
++
++static QETH_DEVICE_ATTR(rxip_del6, del6, 0200, NULL,
++ qeth_l3_dev_rxip_del6_store);
++
++static struct attribute *qeth_rxip_device_attrs[] = {
++ &dev_attr_rxip_add4.attr,
++ &dev_attr_rxip_del4.attr,
++ &dev_attr_rxip_add6.attr,
++ &dev_attr_rxip_del6.attr,
++ NULL,
++};
++
++static struct attribute_group qeth_device_rxip_group = {
++ .name = "rxip",
++ .attrs = qeth_rxip_device_attrs,
++};
++
++int qeth_l3_create_device_attributes(struct device *dev)
++{
++ int ret;
++
++ ret = sysfs_create_group(&dev->kobj, &qeth_l3_device_attr_group);
++ if (ret)
++ return ret;
++
++ ret = sysfs_create_group(&dev->kobj, &qeth_device_ipato_group);
++ if (ret) {
++ sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
++ return ret;
++ }
++
++ ret = sysfs_create_group(&dev->kobj, &qeth_device_vipa_group);
++ if (ret) {
++ sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
++ sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
++ return ret;
++ }
++
++ ret = sysfs_create_group(&dev->kobj, &qeth_device_rxip_group);
++ if (ret) {
++ sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
++ sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
++ sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
++ return ret;
++ }
++ return 0;
++}
++
++void qeth_l3_remove_device_attributes(struct device *dev)
++{
++ sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
++ sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
++ sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
++ sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group);
++}
+diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
+deleted file mode 100644
+index 62606ce..0000000
+--- a/drivers/s390/net/qeth_main.c
++++ /dev/null
+@@ -1,8956 +0,0 @@
+-/*
+- * linux/drivers/s390/net/qeth_main.c
+- *
+- * Linux on zSeries OSA Express and HiperSockets support
+- *
+- * Copyright 2000,2003 IBM Corporation
+- *
+- * Author(s): Original Code written by
+- * Utz Bacher (utz.bacher at de.ibm.com)
+- * Rewritten by
+- * Frank Pavlic (fpavlic at de.ibm.com) and
+- * Thomas Spatzier <tspat at de.ibm.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, or (at your option)
+- * any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-
+-#include <linux/module.h>
+-#include <linux/moduleparam.h>
+-#include <linux/string.h>
+-#include <linux/errno.h>
+-#include <linux/mm.h>
+-#include <linux/ip.h>
+-#include <linux/inetdevice.h>
+-#include <linux/netdevice.h>
+-#include <linux/sched.h>
+-#include <linux/workqueue.h>
+-#include <linux/kernel.h>
+-#include <linux/slab.h>
+-#include <linux/interrupt.h>
+-#include <linux/tcp.h>
+-#include <linux/icmp.h>
+-#include <linux/skbuff.h>
+-#include <linux/in.h>
+-#include <linux/igmp.h>
+-#include <linux/init.h>
+-#include <linux/reboot.h>
+-#include <linux/mii.h>
+-#include <linux/rcupdate.h>
+-#include <linux/ethtool.h>
+-
+-#include <net/arp.h>
+-#include <net/ip.h>
+-#include <net/route.h>
+-
+-#include <asm/ebcdic.h>
+-#include <asm/io.h>
+-#include <asm/qeth.h>
+-#include <asm/timex.h>
+-#include <asm/semaphore.h>
+-#include <asm/uaccess.h>
+-#include <asm/s390_rdev.h>
+-
+-#include "qeth.h"
+-#include "qeth_mpc.h"
+-#include "qeth_fs.h"
+-#include "qeth_eddp.h"
+-#include "qeth_tso.h"
+-
+-static const char *version = "qeth S/390 OSA-Express driver";
+-
+-/**
+- * Debug Facility Stuff
+- */
+-static debug_info_t *qeth_dbf_setup = NULL;
+-static debug_info_t *qeth_dbf_data = NULL;
+-static debug_info_t *qeth_dbf_misc = NULL;
+-static debug_info_t *qeth_dbf_control = NULL;
+-debug_info_t *qeth_dbf_trace = NULL;
+-static debug_info_t *qeth_dbf_sense = NULL;
+-static debug_info_t *qeth_dbf_qerr = NULL;
+-
+-DEFINE_PER_CPU(char[256], qeth_dbf_txt_buf);
+-
+-static struct lock_class_key qdio_out_skb_queue_key;
+-
+-/**
+- * some more definitions and declarations
+- */
+-static unsigned int known_devices[][10] = QETH_MODELLIST_ARRAY;
+-
+-/* list of our cards */
+-struct qeth_card_list_struct qeth_card_list;
+-/*process list want to be notified*/
+-spinlock_t qeth_notify_lock;
+-struct list_head qeth_notify_list;
+-
+-static void qeth_send_control_data_cb(struct qeth_channel *,
+- struct qeth_cmd_buffer *);
+-
+-/**
+- * here we go with function implementation
+- */
+-static void
+-qeth_init_qdio_info(struct qeth_card *card);
+-
+-static int
+-qeth_init_qdio_queues(struct qeth_card *card);
+-
+-static int
+-qeth_alloc_qdio_buffers(struct qeth_card *card);
+-
+-static void
+-qeth_free_qdio_buffers(struct qeth_card *);
+-
+-static void
+-qeth_clear_qdio_buffers(struct qeth_card *);
+-
+-static void
+-qeth_clear_ip_list(struct qeth_card *, int, int);
+-
+-static void
+-qeth_clear_ipacmd_list(struct qeth_card *);
+-
+-static int
+-qeth_qdio_clear_card(struct qeth_card *, int);
+-
+-static void
+-qeth_clear_working_pool_list(struct qeth_card *);
+-
+-static void
+-qeth_clear_cmd_buffers(struct qeth_channel *);
+-
+-static int
+-qeth_stop(struct net_device *);
+-
+-static void
+-qeth_clear_ipato_list(struct qeth_card *);
+-
+-static int
+-qeth_is_addr_covered_by_ipato(struct qeth_card *, struct qeth_ipaddr *);
+-
+-static void
+-qeth_irq_tasklet(unsigned long);
+-
+-static int
+-qeth_set_online(struct ccwgroup_device *);
+-
+-static int
+-__qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode);
+-
+-static struct qeth_ipaddr *
+-qeth_get_addr_buffer(enum qeth_prot_versions);
+-
+-static void
+-qeth_set_multicast_list(struct net_device *);
+-
+-static void
+-qeth_setadp_promisc_mode(struct qeth_card *);
+-
+-static int
+-qeth_hard_header_parse(const struct sk_buff *skb, unsigned char *haddr);
+-
+-static void
+-qeth_notify_processes(void)
+-{
+- /*notify all registered processes */
+- struct qeth_notify_list_struct *n_entry;
+-
+- QETH_DBF_TEXT(trace,3,"procnoti");
+- spin_lock(&qeth_notify_lock);
+- list_for_each_entry(n_entry, &qeth_notify_list, list) {
+- send_sig(n_entry->signum, n_entry->task, 1);
+- }
+- spin_unlock(&qeth_notify_lock);
+-
+-}
+-int
+-qeth_notifier_unregister(struct task_struct *p)
+-{
+- struct qeth_notify_list_struct *n_entry, *tmp;
+-
+- QETH_DBF_TEXT(trace, 2, "notunreg");
+- spin_lock(&qeth_notify_lock);
+- list_for_each_entry_safe(n_entry, tmp, &qeth_notify_list, list) {
+- if (n_entry->task == p) {
+- list_del(&n_entry->list);
+- kfree(n_entry);
+- goto out;
+- }
+- }
+-out:
+- spin_unlock(&qeth_notify_lock);
+- return 0;
+-}
+-int
+-qeth_notifier_register(struct task_struct *p, int signum)
+-{
+- struct qeth_notify_list_struct *n_entry;
+-
+- /*check first if entry already exists*/
+- spin_lock(&qeth_notify_lock);
+- list_for_each_entry(n_entry, &qeth_notify_list, list) {
+- if (n_entry->task == p) {
+- n_entry->signum = signum;
+- spin_unlock(&qeth_notify_lock);
+- return 0;
+- }
+- }
+- spin_unlock(&qeth_notify_lock);
+-
+- n_entry = (struct qeth_notify_list_struct *)
+- kmalloc(sizeof(struct qeth_notify_list_struct),GFP_KERNEL);
+- if (!n_entry)
+- return -ENOMEM;
+- n_entry->task = p;
+- n_entry->signum = signum;
+- spin_lock(&qeth_notify_lock);
+- list_add(&n_entry->list,&qeth_notify_list);
+- spin_unlock(&qeth_notify_lock);
+- return 0;
+-}
+-
+-
+-/**
+- * free channel command buffers
+- */
+-static void
+-qeth_clean_channel(struct qeth_channel *channel)
+-{
+- int cnt;
+-
+- QETH_DBF_TEXT(setup, 2, "freech");
+- for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++)
+- kfree(channel->iob[cnt].data);
+-}
+-
+-/**
+- * free card
+- */
+-static void
+-qeth_free_card(struct qeth_card *card)
+-{
+-
+- QETH_DBF_TEXT(setup, 2, "freecrd");
+- QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
+- qeth_clean_channel(&card->read);
+- qeth_clean_channel(&card->write);
+- if (card->dev)
+- free_netdev(card->dev);
+- qeth_clear_ip_list(card, 0, 0);
+- qeth_clear_ipato_list(card);
+- kfree(card->ip_tbd_list);
+- qeth_free_qdio_buffers(card);
+- kfree(card);
+-}
+-
+-/**
+- * alloc memory for command buffer per channel
+- */
+-static int
+-qeth_setup_channel(struct qeth_channel *channel)
+-{
+- int cnt;
+-
+- QETH_DBF_TEXT(setup, 2, "setupch");
+- for (cnt=0; cnt < QETH_CMD_BUFFER_NO; cnt++) {
+- channel->iob[cnt].data = (char *)
+- kmalloc(QETH_BUFSIZE, GFP_DMA|GFP_KERNEL);
+- if (channel->iob[cnt].data == NULL)
+- break;
+- channel->iob[cnt].state = BUF_STATE_FREE;
+- channel->iob[cnt].channel = channel;
+- channel->iob[cnt].callback = qeth_send_control_data_cb;
+- channel->iob[cnt].rc = 0;
+- }
+- if (cnt < QETH_CMD_BUFFER_NO) {
+- while (cnt-- > 0)
+- kfree(channel->iob[cnt].data);
+- return -ENOMEM;
+- }
+- channel->buf_no = 0;
+- channel->io_buf_no = 0;
+- atomic_set(&channel->irq_pending, 0);
+- spin_lock_init(&channel->iob_lock);
+-
+- init_waitqueue_head(&channel->wait_q);
+- channel->irq_tasklet.data = (unsigned long) channel;
+- channel->irq_tasklet.func = qeth_irq_tasklet;
+- return 0;
+-}
+-
+-/**
+- * alloc memory for card structure
+- */
+-static struct qeth_card *
+-qeth_alloc_card(void)
+-{
+- struct qeth_card *card;
+-
+- QETH_DBF_TEXT(setup, 2, "alloccrd");
+- card = kzalloc(sizeof(struct qeth_card), GFP_DMA|GFP_KERNEL);
+- if (!card)
+- return NULL;
+- QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
+- if (qeth_setup_channel(&card->read)) {
+- kfree(card);
+- return NULL;
+- }
+- if (qeth_setup_channel(&card->write)) {
+- qeth_clean_channel(&card->read);
+- kfree(card);
+- return NULL;
+- }
+- return card;
+-}
+-
+-static long
+-__qeth_check_irb_error(struct ccw_device *cdev, unsigned long intparm,
+- struct irb *irb)
+-{
+- if (!IS_ERR(irb))
+- return 0;
+-
+- switch (PTR_ERR(irb)) {
+- case -EIO:
+- PRINT_WARN("i/o-error on device %s\n", cdev->dev.bus_id);
+- QETH_DBF_TEXT(trace, 2, "ckirberr");
+- QETH_DBF_TEXT_(trace, 2, " rc%d", -EIO);
+- break;
+- case -ETIMEDOUT:
+- PRINT_WARN("timeout on device %s\n", cdev->dev.bus_id);
+- QETH_DBF_TEXT(trace, 2, "ckirberr");
+- QETH_DBF_TEXT_(trace, 2, " rc%d", -ETIMEDOUT);
+- if (intparm == QETH_RCD_PARM) {
+- struct qeth_card *card = CARD_FROM_CDEV(cdev);
+-
+- if (card && (card->data.ccwdev == cdev)) {
+- card->data.state = CH_STATE_DOWN;
+- wake_up(&card->wait_q);
+- }
+- }
+- break;
+- default:
+- PRINT_WARN("unknown error %ld on device %s\n", PTR_ERR(irb),
+- cdev->dev.bus_id);
+- QETH_DBF_TEXT(trace, 2, "ckirberr");
+- QETH_DBF_TEXT(trace, 2, " rc???");
+- }
+- return PTR_ERR(irb);
+-}
+-
+-static int
+-qeth_get_problem(struct ccw_device *cdev, struct irb *irb)
+-{
+- int dstat,cstat;
+- char *sense;
+-
+- sense = (char *) irb->ecw;
+- cstat = irb->scsw.cstat;
+- dstat = irb->scsw.dstat;
+-
+- if (cstat & (SCHN_STAT_CHN_CTRL_CHK | SCHN_STAT_INTF_CTRL_CHK |
+- SCHN_STAT_CHN_DATA_CHK | SCHN_STAT_CHAIN_CHECK |
+- SCHN_STAT_PROT_CHECK | SCHN_STAT_PROG_CHECK)) {
+- QETH_DBF_TEXT(trace,2, "CGENCHK");
+- PRINT_WARN("check on device %s, dstat=x%x, cstat=x%x ",
+- cdev->dev.bus_id, dstat, cstat);
+- HEXDUMP16(WARN, "irb: ", irb);
+- HEXDUMP16(WARN, "irb: ", ((char *) irb) + 32);
+- return 1;
+- }
+-
+- if (dstat & DEV_STAT_UNIT_CHECK) {
+- if (sense[SENSE_RESETTING_EVENT_BYTE] &
+- SENSE_RESETTING_EVENT_FLAG) {
+- QETH_DBF_TEXT(trace,2,"REVIND");
+- return 1;
+- }
+- if (sense[SENSE_COMMAND_REJECT_BYTE] &
+- SENSE_COMMAND_REJECT_FLAG) {
+- QETH_DBF_TEXT(trace,2,"CMDREJi");
+- return 0;
+- }
+- if ((sense[2] == 0xaf) && (sense[3] == 0xfe)) {
+- QETH_DBF_TEXT(trace,2,"AFFE");
+- return 1;
+- }
+- if ((!sense[0]) && (!sense[1]) && (!sense[2]) && (!sense[3])) {
+- QETH_DBF_TEXT(trace,2,"ZEROSEN");
+- return 0;
+- }
+- QETH_DBF_TEXT(trace,2,"DGENCHK");
+- return 1;
+- }
+- return 0;
+-}
+-static int qeth_issue_next_read(struct qeth_card *);
+-
+-/**
+- * interrupt handler
+- */
+-static void
+-qeth_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
+-{
+- int rc;
+- int cstat,dstat;
+- struct qeth_cmd_buffer *buffer;
+- struct qeth_channel *channel;
+- struct qeth_card *card;
+-
+- QETH_DBF_TEXT(trace,5,"irq");
+-
+- if (__qeth_check_irb_error(cdev, intparm, irb))
+- return;
+- cstat = irb->scsw.cstat;
+- dstat = irb->scsw.dstat;
+-
+- card = CARD_FROM_CDEV(cdev);
+- if (!card)
+- return;
+-
+- if (card->read.ccwdev == cdev){
+- channel = &card->read;
+- QETH_DBF_TEXT(trace,5,"read");
+- } else if (card->write.ccwdev == cdev) {
+- channel = &card->write;
+- QETH_DBF_TEXT(trace,5,"write");
+- } else {
+- channel = &card->data;
+- QETH_DBF_TEXT(trace,5,"data");
+- }
+- atomic_set(&channel->irq_pending, 0);
+-
+- if (irb->scsw.fctl & (SCSW_FCTL_CLEAR_FUNC))
+- channel->state = CH_STATE_STOPPED;
+-
+- if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC))
+- channel->state = CH_STATE_HALTED;
+-
+- /*let's wake up immediately on data channel*/
+- if ((channel == &card->data) && (intparm != 0) &&
+- (intparm != QETH_RCD_PARM))
+- goto out;
+-
+- if (intparm == QETH_CLEAR_CHANNEL_PARM) {
+- QETH_DBF_TEXT(trace, 6, "clrchpar");
+- /* we don't have to handle this further */
+- intparm = 0;
+- }
+- if (intparm == QETH_HALT_CHANNEL_PARM) {
+- QETH_DBF_TEXT(trace, 6, "hltchpar");
+- /* we don't have to handle this further */
+- intparm = 0;
+- }
+- if ((dstat & DEV_STAT_UNIT_EXCEP) ||
+- (dstat & DEV_STAT_UNIT_CHECK) ||
+- (cstat)) {
+- if (irb->esw.esw0.erw.cons) {
+- /* TODO: we should make this s390dbf */
+- PRINT_WARN("sense data available on channel %s.\n",
+- CHANNEL_ID(channel));
+- PRINT_WARN(" cstat 0x%X\n dstat 0x%X\n", cstat, dstat);
+- HEXDUMP16(WARN,"irb: ",irb);
+- HEXDUMP16(WARN,"sense data: ",irb->ecw);
+- }
+- if (intparm == QETH_RCD_PARM) {
+- channel->state = CH_STATE_DOWN;
+- goto out;
+- }
+- rc = qeth_get_problem(cdev,irb);
+- if (rc) {
+- qeth_schedule_recovery(card);
+- goto out;
+- }
+- }
+-
+- if (intparm == QETH_RCD_PARM) {
+- channel->state = CH_STATE_RCD_DONE;
+- goto out;
+- }
+- if (intparm) {
+- buffer = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
+- buffer->state = BUF_STATE_PROCESSED;
+- }
+- if (channel == &card->data)
+- return;
+-
+- if (channel == &card->read &&
+- channel->state == CH_STATE_UP)
+- qeth_issue_next_read(card);
+-
+- qeth_irq_tasklet((unsigned long)channel);
+- return;
+-out:
+- wake_up(&card->wait_q);
+-}
+-
+-/**
+- * tasklet function scheduled from irq handler
+- */
+-static void
+-qeth_irq_tasklet(unsigned long data)
+-{
+- struct qeth_card *card;
+- struct qeth_channel *channel;
+- struct qeth_cmd_buffer *iob;
+- __u8 index;
+-
+- QETH_DBF_TEXT(trace,5,"irqtlet");
+- channel = (struct qeth_channel *) data;
+- iob = channel->iob;
+- index = channel->buf_no;
+- card = CARD_FROM_CDEV(channel->ccwdev);
+- while (iob[index].state == BUF_STATE_PROCESSED) {
+- if (iob[index].callback !=NULL) {
+- iob[index].callback(channel,iob + index);
+- }
+- index = (index + 1) % QETH_CMD_BUFFER_NO;
+- }
+- channel->buf_no = index;
+- wake_up(&card->wait_q);
+-}
+-
+-static int qeth_stop_card(struct qeth_card *, int);
+-
+-static int
+-__qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode)
+-{
+- struct qeth_card *card = (struct qeth_card *) cgdev->dev.driver_data;
+- int rc = 0, rc2 = 0, rc3 = 0;
+- enum qeth_card_states recover_flag;
+-
+- QETH_DBF_TEXT(setup, 3, "setoffl");
+- QETH_DBF_HEX(setup, 3, &card, sizeof(void *));
+-
+- if (card->dev && netif_carrier_ok(card->dev))
+- netif_carrier_off(card->dev);
+- recover_flag = card->state;
+- if (qeth_stop_card(card, recovery_mode) == -ERESTARTSYS){
+- PRINT_WARN("Stopping card %s interrupted by user!\n",
+- CARD_BUS_ID(card));
+- return -ERESTARTSYS;
+- }
+- rc = ccw_device_set_offline(CARD_DDEV(card));
+- rc2 = ccw_device_set_offline(CARD_WDEV(card));
+- rc3 = ccw_device_set_offline(CARD_RDEV(card));
+- if (!rc)
+- rc = (rc2) ? rc2 : rc3;
+- if (rc)
+- QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+- if (recover_flag == CARD_STATE_UP)
+- card->state = CARD_STATE_RECOVER;
+- qeth_notify_processes();
+- return 0;
+-}
+-
+-static int
+-qeth_set_offline(struct ccwgroup_device *cgdev)
+-{
+- return __qeth_set_offline(cgdev, 0);
+-}
+-
+-static int
+-qeth_threads_running(struct qeth_card *card, unsigned long threads);
+-
+-
+-static void
+-qeth_remove_device(struct ccwgroup_device *cgdev)
+-{
+- struct qeth_card *card = (struct qeth_card *) cgdev->dev.driver_data;
+- unsigned long flags;
+-
+- QETH_DBF_TEXT(setup, 3, "rmdev");
+- QETH_DBF_HEX(setup, 3, &card, sizeof(void *));
+-
+- if (!card)
+- return;
+-
+- wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
+-
+- if (cgdev->state == CCWGROUP_ONLINE){
+- card->use_hard_stop = 1;
+- qeth_set_offline(cgdev);
+- }
+- /* remove form our internal list */
+- write_lock_irqsave(&qeth_card_list.rwlock, flags);
+- list_del(&card->list);
+- write_unlock_irqrestore(&qeth_card_list.rwlock, flags);
+- if (card->dev)
+- unregister_netdev(card->dev);
+- qeth_remove_device_attributes(&cgdev->dev);
+- qeth_free_card(card);
+- cgdev->dev.driver_data = NULL;
+- put_device(&cgdev->dev);
+-}
+-
+-static int
+-qeth_register_addr_entry(struct qeth_card *, struct qeth_ipaddr *);
+-static int
+-qeth_deregister_addr_entry(struct qeth_card *, struct qeth_ipaddr *);
+-
+-/**
+- * Add/remove address to/from card's ip list, i.e. try to add or remove
+- * reference to/from an IP address that is already registered on the card.
+- * Returns:
+- * 0 address was on card and its reference count has been adjusted,
+- * but is still > 0, so nothing has to be done
+- * also returns 0 if card was not on card and the todo was to delete
+- * the address -> there is also nothing to be done
+- * 1 address was not on card and the todo is to add it to the card's ip
+- * list
+- * -1 address was on card and its reference count has been decremented
+- * to <= 0 by the todo -> address must be removed from card
+- */
+-static int
+-__qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo,
+- struct qeth_ipaddr **__addr)
+-{
+- struct qeth_ipaddr *addr;
+- int found = 0;
+-
+- list_for_each_entry(addr, &card->ip_list, entry) {
+- if (card->options.layer2) {
+- if ((addr->type == todo->type) &&
+- (memcmp(&addr->mac, &todo->mac,
+- OSA_ADDR_LEN) == 0)) {
+- found = 1;
+- break;
+- }
+- continue;
+- }
+- if ((addr->proto == QETH_PROT_IPV4) &&
+- (todo->proto == QETH_PROT_IPV4) &&
+- (addr->type == todo->type) &&
+- (addr->u.a4.addr == todo->u.a4.addr) &&
+- (addr->u.a4.mask == todo->u.a4.mask)) {
+- found = 1;
+- break;
+- }
+- if ((addr->proto == QETH_PROT_IPV6) &&
+- (todo->proto == QETH_PROT_IPV6) &&
+- (addr->type == todo->type) &&
+- (addr->u.a6.pfxlen == todo->u.a6.pfxlen) &&
+- (memcmp(&addr->u.a6.addr, &todo->u.a6.addr,
+- sizeof(struct in6_addr)) == 0)) {
+- found = 1;
+- break;
+- }
+- }
+- if (found) {
+- addr->users += todo->users;
+- if (addr->users <= 0){
+- *__addr = addr;
+- return -1;
+- } else {
+- /* for VIPA and RXIP limit refcount to 1 */
+- if (addr->type != QETH_IP_TYPE_NORMAL)
+- addr->users = 1;
+- return 0;
+- }
+- }
+- if (todo->users > 0) {
+- /* for VIPA and RXIP limit refcount to 1 */
+- if (todo->type != QETH_IP_TYPE_NORMAL)
+- todo->users = 1;
+- return 1;
+- } else
+- return 0;
+-}
+-
+-static int
+-__qeth_address_exists_in_list(struct list_head *list, struct qeth_ipaddr *addr,
+- int same_type)
+-{
+- struct qeth_ipaddr *tmp;
+-
+- list_for_each_entry(tmp, list, entry) {
+- if ((tmp->proto == QETH_PROT_IPV4) &&
+- (addr->proto == QETH_PROT_IPV4) &&
+- ((same_type && (tmp->type == addr->type)) ||
+- (!same_type && (tmp->type != addr->type)) ) &&
+- (tmp->u.a4.addr == addr->u.a4.addr) ){
+- return 1;
+- }
+- if ((tmp->proto == QETH_PROT_IPV6) &&
+- (addr->proto == QETH_PROT_IPV6) &&
+- ((same_type && (tmp->type == addr->type)) ||
+- (!same_type && (tmp->type != addr->type)) ) &&
+- (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr,
+- sizeof(struct in6_addr)) == 0) ) {
+- return 1;
+- }
+- }
+- return 0;
+-}
+-
+-/*
+- * Add IP to be added to todo list. If there is already an "add todo"
+- * in this list we just incremenent the reference count.
+- * Returns 0 if we just incremented reference count.
+- */
+-static int
+-__qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add)
+-{
+- struct qeth_ipaddr *tmp, *t;
+- int found = 0;
+-
+- list_for_each_entry_safe(tmp, t, card->ip_tbd_list, entry) {
+- if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) &&
+- (tmp->type == QETH_IP_TYPE_DEL_ALL_MC))
+- return 0;
+- if (card->options.layer2) {
+- if ((tmp->type == addr->type) &&
+- (tmp->is_multicast == addr->is_multicast) &&
+- (memcmp(&tmp->mac, &addr->mac,
+- OSA_ADDR_LEN) == 0)) {
+- found = 1;
+- break;
+- }
+- continue;
+- }
+- if ((tmp->proto == QETH_PROT_IPV4) &&
+- (addr->proto == QETH_PROT_IPV4) &&
+- (tmp->type == addr->type) &&
+- (tmp->is_multicast == addr->is_multicast) &&
+- (tmp->u.a4.addr == addr->u.a4.addr) &&
+- (tmp->u.a4.mask == addr->u.a4.mask)) {
+- found = 1;
+- break;
+- }
+- if ((tmp->proto == QETH_PROT_IPV6) &&
+- (addr->proto == QETH_PROT_IPV6) &&
+- (tmp->type == addr->type) &&
+- (tmp->is_multicast == addr->is_multicast) &&
+- (tmp->u.a6.pfxlen == addr->u.a6.pfxlen) &&
+- (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr,
+- sizeof(struct in6_addr)) == 0)) {
+- found = 1;
+- break;
+- }
+- }
+- if (found){
+- if (addr->users != 0)
+- tmp->users += addr->users;
+- else
+- tmp->users += add? 1:-1;
+- if (tmp->users == 0) {
+- list_del(&tmp->entry);
+- kfree(tmp);
+- }
+- return 0;
+- } else {
+- if (addr->type == QETH_IP_TYPE_DEL_ALL_MC)
+- list_add(&addr->entry, card->ip_tbd_list);
+- else {
+- if (addr->users == 0)
+- addr->users += add? 1:-1;
+- if (add && (addr->type == QETH_IP_TYPE_NORMAL) &&
+- qeth_is_addr_covered_by_ipato(card, addr)){
+- QETH_DBF_TEXT(trace, 2, "tkovaddr");
+- addr->set_flags |= QETH_IPA_SETIP_TAKEOVER_FLAG;
+- }
+- list_add_tail(&addr->entry, card->ip_tbd_list);
+- }
+- return 1;
+- }
+-}
+-
+-/**
+- * Remove IP address from list
+- */
+-static int
+-qeth_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
+-{
+- unsigned long flags;
+- int rc = 0;
+-
+- QETH_DBF_TEXT(trace, 4, "delip");
+-
+- if (card->options.layer2)
+- QETH_DBF_HEX(trace, 4, &addr->mac, 6);
+- else if (addr->proto == QETH_PROT_IPV4)
+- QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4);
+- else {
+- QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);
+- QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8);
+- }
+- spin_lock_irqsave(&card->ip_lock, flags);
+- rc = __qeth_insert_ip_todo(card, addr, 0);
+- spin_unlock_irqrestore(&card->ip_lock, flags);
+- return rc;
+-}
+-
+-static int
+-qeth_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
+-{
+- unsigned long flags;
+- int rc = 0;
+-
+- QETH_DBF_TEXT(trace, 4, "addip");
+- if (card->options.layer2)
+- QETH_DBF_HEX(trace, 4, &addr->mac, 6);
+- else if (addr->proto == QETH_PROT_IPV4)
+- QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4);
+- else {
+- QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);
+- QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8);
+- }
+- spin_lock_irqsave(&card->ip_lock, flags);
+- rc = __qeth_insert_ip_todo(card, addr, 1);
+- spin_unlock_irqrestore(&card->ip_lock, flags);
+- return rc;
+-}
+-
+-static void
+-__qeth_delete_all_mc(struct qeth_card *card, unsigned long *flags)
+-{
+- struct qeth_ipaddr *addr, *tmp;
+- int rc;
+-again:
+- list_for_each_entry_safe(addr, tmp, &card->ip_list, entry) {
+- if (addr->is_multicast) {
+- list_del(&addr->entry);
+- spin_unlock_irqrestore(&card->ip_lock, *flags);
+- rc = qeth_deregister_addr_entry(card, addr);
+- spin_lock_irqsave(&card->ip_lock, *flags);
+- if (!rc) {
+- kfree(addr);
+- goto again;
+- } else
+- list_add(&addr->entry, &card->ip_list);
+- }
+- }
+-}
+-
+-static void
+-qeth_set_ip_addr_list(struct qeth_card *card)
+-{
+- struct list_head *tbd_list;
+- struct qeth_ipaddr *todo, *addr;
+- unsigned long flags;
+- int rc;
+-
+- QETH_DBF_TEXT(trace, 2, "sdiplist");
+- QETH_DBF_HEX(trace, 2, &card, sizeof(void *));
+-
+- spin_lock_irqsave(&card->ip_lock, flags);
+- tbd_list = card->ip_tbd_list;
+- card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_ATOMIC);
+- if (!card->ip_tbd_list) {
+- QETH_DBF_TEXT(trace, 0, "silnomem");
+- card->ip_tbd_list = tbd_list;
+- spin_unlock_irqrestore(&card->ip_lock, flags);
+- return;
+- } else
+- INIT_LIST_HEAD(card->ip_tbd_list);
+-
+- while (!list_empty(tbd_list)){
+- todo = list_entry(tbd_list->next, struct qeth_ipaddr, entry);
+- list_del(&todo->entry);
+- if (todo->type == QETH_IP_TYPE_DEL_ALL_MC){
+- __qeth_delete_all_mc(card, &flags);
+- kfree(todo);
+- continue;
+- }
+- rc = __qeth_ref_ip_on_card(card, todo, &addr);
+- if (rc == 0) {
+- /* nothing to be done; only adjusted refcount */
+- kfree(todo);
+- } else if (rc == 1) {
+- /* new entry to be added to on-card list */
+- spin_unlock_irqrestore(&card->ip_lock, flags);
+- rc = qeth_register_addr_entry(card, todo);
+- spin_lock_irqsave(&card->ip_lock, flags);
+- if (!rc)
+- list_add_tail(&todo->entry, &card->ip_list);
+- else
+- kfree(todo);
+- } else if (rc == -1) {
+- /* on-card entry to be removed */
+- list_del_init(&addr->entry);
+- spin_unlock_irqrestore(&card->ip_lock, flags);
+- rc = qeth_deregister_addr_entry(card, addr);
+- spin_lock_irqsave(&card->ip_lock, flags);
+- if (!rc)
+- kfree(addr);
+- else
+- list_add_tail(&addr->entry, &card->ip_list);
+- kfree(todo);
+- }
+- }
+- spin_unlock_irqrestore(&card->ip_lock, flags);
+- kfree(tbd_list);
+-}
+-
+-static void qeth_delete_mc_addresses(struct qeth_card *);
+-static void qeth_add_multicast_ipv4(struct qeth_card *);
+-static void qeth_layer2_add_multicast(struct qeth_card *);
+-#ifdef CONFIG_QETH_IPV6
+-static void qeth_add_multicast_ipv6(struct qeth_card *);
+-#endif
+-
+-static int
+-qeth_set_thread_start_bit(struct qeth_card *card, unsigned long thread)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&card->thread_mask_lock, flags);
+- if ( !(card->thread_allowed_mask & thread) ||
+- (card->thread_start_mask & thread) ) {
+- spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+- return -EPERM;
+- }
+- card->thread_start_mask |= thread;
+- spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+- return 0;
+-}
+-
+-static void
+-qeth_clear_thread_start_bit(struct qeth_card *card, unsigned long thread)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&card->thread_mask_lock, flags);
+- card->thread_start_mask &= ~thread;
+- spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+- wake_up(&card->wait_q);
+-}
+-
+-static void
+-qeth_clear_thread_running_bit(struct qeth_card *card, unsigned long thread)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&card->thread_mask_lock, flags);
+- card->thread_running_mask &= ~thread;
+- spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+- wake_up(&card->wait_q);
+-}
+-
+-static int
+-__qeth_do_run_thread(struct qeth_card *card, unsigned long thread)
+-{
+- unsigned long flags;
+- int rc = 0;
+-
+- spin_lock_irqsave(&card->thread_mask_lock, flags);
+- if (card->thread_start_mask & thread){
+- if ((card->thread_allowed_mask & thread) &&
+- !(card->thread_running_mask & thread)){
+- rc = 1;
+- card->thread_start_mask &= ~thread;
+- card->thread_running_mask |= thread;
+- } else
+- rc = -EPERM;
+- }
+- spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+- return rc;
+-}
+-
+-static int
+-qeth_do_run_thread(struct qeth_card *card, unsigned long thread)
+-{
+- int rc = 0;
+-
+- wait_event(card->wait_q,
+- (rc = __qeth_do_run_thread(card, thread)) >= 0);
+- return rc;
+-}
+-
+-static int
+-qeth_recover(void *ptr)
+-{
+- struct qeth_card *card;
+- int rc = 0;
+-
+- card = (struct qeth_card *) ptr;
+- daemonize("qeth_recover");
+- QETH_DBF_TEXT(trace,2,"recover1");
+- QETH_DBF_HEX(trace, 2, &card, sizeof(void *));
+- if (!qeth_do_run_thread(card, QETH_RECOVER_THREAD))
+- return 0;
+- QETH_DBF_TEXT(trace,2,"recover2");
+- PRINT_WARN("Recovery of device %s started ...\n",
+- CARD_BUS_ID(card));
+- card->use_hard_stop = 1;
+- __qeth_set_offline(card->gdev,1);
+- rc = __qeth_set_online(card->gdev,1);
+- /* don't run another scheduled recovery */
+- qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
+- qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
+- if (!rc)
+- PRINT_INFO("Device %s successfully recovered!\n",
+- CARD_BUS_ID(card));
+- else
+- PRINT_INFO("Device %s could not be recovered!\n",
+- CARD_BUS_ID(card));
+- return 0;
+-}
+-
+-void
+-qeth_schedule_recovery(struct qeth_card *card)
+-{
+- QETH_DBF_TEXT(trace,2,"startrec");
+- if (qeth_set_thread_start_bit(card, QETH_RECOVER_THREAD) == 0)
+- schedule_work(&card->kernel_thread_starter);
+-}
+-
+-static int
+-qeth_do_start_thread(struct qeth_card *card, unsigned long thread)
+-{
+- unsigned long flags;
+- int rc = 0;
+-
+- spin_lock_irqsave(&card->thread_mask_lock, flags);
+- QETH_DBF_TEXT_(trace, 4, " %02x%02x%02x",
+- (u8) card->thread_start_mask,
+- (u8) card->thread_allowed_mask,
+- (u8) card->thread_running_mask);
+- rc = (card->thread_start_mask & thread);
+- spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+- return rc;
+-}
+-
+-static void
+-qeth_start_kernel_thread(struct work_struct *work)
+-{
+- struct qeth_card *card = container_of(work, struct qeth_card, kernel_thread_starter);
+- QETH_DBF_TEXT(trace , 2, "strthrd");
+-
+- if (card->read.state != CH_STATE_UP &&
+- card->write.state != CH_STATE_UP)
+- return;
+- if (qeth_do_start_thread(card, QETH_RECOVER_THREAD))
+- kernel_thread(qeth_recover, (void *) card, SIGCHLD);
+-}
+-
+-
+-static void
+-qeth_set_intial_options(struct qeth_card *card)
+-{
+- card->options.route4.type = NO_ROUTER;
+-#ifdef CONFIG_QETH_IPV6
+- card->options.route6.type = NO_ROUTER;
+-#endif /* QETH_IPV6 */
+- card->options.checksum_type = QETH_CHECKSUM_DEFAULT;
+- card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS;
+- card->options.macaddr_mode = QETH_TR_MACADDR_NONCANONICAL;
+- card->options.fake_broadcast = 0;
+- card->options.add_hhlen = DEFAULT_ADD_HHLEN;
+- card->options.fake_ll = 0;
+- if (card->info.type == QETH_CARD_TYPE_OSN)
+- card->options.layer2 = 1;
+- else
+- card->options.layer2 = 0;
+- card->options.performance_stats = 0;
+- card->options.rx_sg_cb = QETH_RX_SG_CB;
+-}
+-
+-/**
+- * initialize channels ,card and all state machines
+- */
+-static int
+-qeth_setup_card(struct qeth_card *card)
+-{
+-
+- QETH_DBF_TEXT(setup, 2, "setupcrd");
+- QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
+-
+- card->read.state = CH_STATE_DOWN;
+- card->write.state = CH_STATE_DOWN;
+- card->data.state = CH_STATE_DOWN;
+- card->state = CARD_STATE_DOWN;
+- card->lan_online = 0;
+- card->use_hard_stop = 0;
+- card->dev = NULL;
+-#ifdef CONFIG_QETH_VLAN
+- spin_lock_init(&card->vlanlock);
+- card->vlangrp = NULL;
+-#endif
+- spin_lock_init(&card->lock);
+- spin_lock_init(&card->ip_lock);
+- spin_lock_init(&card->thread_mask_lock);
+- card->thread_start_mask = 0;
+- card->thread_allowed_mask = 0;
+- card->thread_running_mask = 0;
+- INIT_WORK(&card->kernel_thread_starter, qeth_start_kernel_thread);
+- INIT_LIST_HEAD(&card->ip_list);
+- card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_KERNEL);
+- if (!card->ip_tbd_list) {
+- QETH_DBF_TEXT(setup, 0, "iptbdnom");
+- return -ENOMEM;
+- }
+- INIT_LIST_HEAD(card->ip_tbd_list);
+- INIT_LIST_HEAD(&card->cmd_waiter_list);
+- init_waitqueue_head(&card->wait_q);
+- /* intial options */
+- qeth_set_intial_options(card);
+- /* IP address takeover */
+- INIT_LIST_HEAD(&card->ipato.entries);
+- card->ipato.enabled = 0;
+- card->ipato.invert4 = 0;
+- card->ipato.invert6 = 0;
+- /* init QDIO stuff */
+- qeth_init_qdio_info(card);
+- return 0;
+-}
+-
+-static int
+-is_1920_device (struct qeth_card *card)
+-{
+- int single_queue = 0;
+- struct ccw_device *ccwdev;
+- struct channelPath_dsc {
+- u8 flags;
+- u8 lsn;
+- u8 desc;
+- u8 chpid;
+- u8 swla;
+- u8 zeroes;
+- u8 chla;
+- u8 chpp;
+- } *chp_dsc;
+-
+- QETH_DBF_TEXT(setup, 2, "chk_1920");
+-
+- ccwdev = card->data.ccwdev;
+- chp_dsc = (struct channelPath_dsc *)ccw_device_get_chp_desc(ccwdev, 0);
+- if (chp_dsc != NULL) {
+- /* CHPP field bit 6 == 1 -> single queue */
+- single_queue = ((chp_dsc->chpp & 0x02) == 0x02);
+- kfree(chp_dsc);
+- }
+- QETH_DBF_TEXT_(setup, 2, "rc:%x", single_queue);
+- return single_queue;
+-}
+-
+-static int
+-qeth_determine_card_type(struct qeth_card *card)
+-{
+- int i = 0;
+-
+- QETH_DBF_TEXT(setup, 2, "detcdtyp");
+-
+- card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
+- card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
+- while (known_devices[i][4]) {
+- if ((CARD_RDEV(card)->id.dev_type == known_devices[i][2]) &&
+- (CARD_RDEV(card)->id.dev_model == known_devices[i][3])) {
+- card->info.type = known_devices[i][4];
+- card->qdio.no_out_queues = known_devices[i][8];
+- card->info.is_multicast_different = known_devices[i][9];
+- if (is_1920_device(card)) {
+- PRINT_INFO("Priority Queueing not able "
+- "due to hardware limitations!\n");
+- card->qdio.no_out_queues = 1;
+- card->qdio.default_out_queue = 0;
+- }
+- return 0;
+- }
+- i++;
+- }
+- card->info.type = QETH_CARD_TYPE_UNKNOWN;
+- PRINT_ERR("unknown card type on device %s\n", CARD_BUS_ID(card));
+- return -ENOENT;
+-}
+-
+-static int
+-qeth_probe_device(struct ccwgroup_device *gdev)
+-{
+- struct qeth_card *card;
+- struct device *dev;
+- unsigned long flags;
+- int rc;
+-
+- QETH_DBF_TEXT(setup, 2, "probedev");
+-
+- dev = &gdev->dev;
+- if (!get_device(dev))
+- return -ENODEV;
+-
+- QETH_DBF_TEXT_(setup, 2, "%s", gdev->dev.bus_id);
+-
+- card = qeth_alloc_card();
+- if (!card) {
+- put_device(dev);
+- QETH_DBF_TEXT_(setup, 2, "1err%d", -ENOMEM);
+- return -ENOMEM;
+- }
+- card->read.ccwdev = gdev->cdev[0];
+- card->write.ccwdev = gdev->cdev[1];
+- card->data.ccwdev = gdev->cdev[2];
+- gdev->dev.driver_data = card;
+- card->gdev = gdev;
+- gdev->cdev[0]->handler = qeth_irq;
+- gdev->cdev[1]->handler = qeth_irq;
+- gdev->cdev[2]->handler = qeth_irq;
+-
+- if ((rc = qeth_determine_card_type(card))){
+- PRINT_WARN("%s: not a valid card type\n", __func__);
+- QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+- put_device(dev);
+- qeth_free_card(card);
+- return rc;
+- }
+- if ((rc = qeth_setup_card(card))){
+- QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+- put_device(dev);
+- qeth_free_card(card);
+- return rc;
+- }
+- rc = qeth_create_device_attributes(dev);
+- if (rc) {
+- put_device(dev);
+- qeth_free_card(card);
+- return rc;
+- }
+- /* insert into our internal list */
+- write_lock_irqsave(&qeth_card_list.rwlock, flags);
+- list_add_tail(&card->list, &qeth_card_list.list);
+- write_unlock_irqrestore(&qeth_card_list.rwlock, flags);
+- return rc;
+-}
+-
+-
+-static int qeth_read_conf_data(struct qeth_card *card, void **buffer,
+- int *length)
+-{
+- struct ciw *ciw;
+- char *rcd_buf;
+- int ret;
+- struct qeth_channel *channel = &card->data;
+- unsigned long flags;
+-
+- /*
+- * scan for RCD command in extended SenseID data
+- */
+- ciw = ccw_device_get_ciw(channel->ccwdev, CIW_TYPE_RCD);
+- if (!ciw || ciw->cmd == 0)
+- return -EOPNOTSUPP;
+- rcd_buf = kzalloc(ciw->count, GFP_KERNEL | GFP_DMA);
+- if (!rcd_buf)
+- return -ENOMEM;
+-
+- channel->ccw.cmd_code = ciw->cmd;
+- channel->ccw.cda = (__u32) __pa (rcd_buf);
+- channel->ccw.count = ciw->count;
+- channel->ccw.flags = CCW_FLAG_SLI;
+- channel->state = CH_STATE_RCD;
+- spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+- ret = ccw_device_start_timeout(channel->ccwdev, &channel->ccw,
+- QETH_RCD_PARM, LPM_ANYPATH, 0,
+- QETH_RCD_TIMEOUT);
+- spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+- if (!ret)
+- wait_event(card->wait_q,
+- (channel->state == CH_STATE_RCD_DONE ||
+- channel->state == CH_STATE_DOWN));
+- if (channel->state == CH_STATE_DOWN)
+- ret = -EIO;
+- else
+- channel->state = CH_STATE_DOWN;
+- if (ret) {
+- kfree(rcd_buf);
+- *buffer = NULL;
+- *length = 0;
+- } else {
+- *length = ciw->count;
+- *buffer = rcd_buf;
+- }
+- return ret;
+-}
+-
+-static int
+-qeth_get_unitaddr(struct qeth_card *card)
+-{
+- int length;
+- char *prcd;
+- int rc;
+-
+- QETH_DBF_TEXT(setup, 2, "getunit");
+- rc = qeth_read_conf_data(card, (void **) &prcd, &length);
+- if (rc) {
+- PRINT_ERR("qeth_read_conf_data for device %s returned %i\n",
+- CARD_DDEV_ID(card), rc);
+- return rc;
+- }
+- card->info.chpid = prcd[30];
+- card->info.unit_addr2 = prcd[31];
+- card->info.cula = prcd[63];
+- card->info.guestlan = ((prcd[0x10] == _ascebc['V']) &&
+- (prcd[0x11] == _ascebc['M']));
+- kfree(prcd);
+- return 0;
+-}
+-
+-static void
+-qeth_init_tokens(struct qeth_card *card)
+-{
+- card->token.issuer_rm_w = 0x00010103UL;
+- card->token.cm_filter_w = 0x00010108UL;
+- card->token.cm_connection_w = 0x0001010aUL;
+- card->token.ulp_filter_w = 0x0001010bUL;
+- card->token.ulp_connection_w = 0x0001010dUL;
+-}
+-
+-static inline __u16
+-raw_devno_from_bus_id(char *id)
+-{
+- id += (strlen(id) - 4);
+- return (__u16) simple_strtoul(id, &id, 16);
+-}
+-/**
+- * setup channel
+- */
+-static void
+-qeth_setup_ccw(struct qeth_channel *channel,unsigned char *iob, __u32 len)
+-{
+- struct qeth_card *card;
+-
+- QETH_DBF_TEXT(trace, 4, "setupccw");
+- card = CARD_FROM_CDEV(channel->ccwdev);
+- if (channel == &card->read)
+- memcpy(&channel->ccw, READ_CCW, sizeof(struct ccw1));
+- else
+- memcpy(&channel->ccw, WRITE_CCW, sizeof(struct ccw1));
+- channel->ccw.count = len;
+- channel->ccw.cda = (__u32) __pa(iob);
+-}
+-
+-/**
+- * get free buffer for ccws (IDX activation, lancmds,ipassists...)
+- */
+-static struct qeth_cmd_buffer *
+-__qeth_get_buffer(struct qeth_channel *channel)
+-{
+- __u8 index;
+-
+- QETH_DBF_TEXT(trace, 6, "getbuff");
+- index = channel->io_buf_no;
+- do {
+- if (channel->iob[index].state == BUF_STATE_FREE) {
+- channel->iob[index].state = BUF_STATE_LOCKED;
+- channel->io_buf_no = (channel->io_buf_no + 1) %
+- QETH_CMD_BUFFER_NO;
+- memset(channel->iob[index].data, 0, QETH_BUFSIZE);
+- return channel->iob + index;
+- }
+- index = (index + 1) % QETH_CMD_BUFFER_NO;
+- } while(index != channel->io_buf_no);
+-
+- return NULL;
+-}
+-
+-/**
+- * release command buffer
+- */
+-static void
+-qeth_release_buffer(struct qeth_channel *channel, struct qeth_cmd_buffer *iob)
+-{
+- unsigned long flags;
+-
+- QETH_DBF_TEXT(trace, 6, "relbuff");
+- spin_lock_irqsave(&channel->iob_lock, flags);
+- memset(iob->data, 0, QETH_BUFSIZE);
+- iob->state = BUF_STATE_FREE;
+- iob->callback = qeth_send_control_data_cb;
+- iob->rc = 0;
+- spin_unlock_irqrestore(&channel->iob_lock, flags);
+-}
+-
+-static struct qeth_cmd_buffer *
+-qeth_get_buffer(struct qeth_channel *channel)
+-{
+- struct qeth_cmd_buffer *buffer = NULL;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&channel->iob_lock, flags);
+- buffer = __qeth_get_buffer(channel);
+- spin_unlock_irqrestore(&channel->iob_lock, flags);
+- return buffer;
+-}
+-
+-static struct qeth_cmd_buffer *
+-qeth_wait_for_buffer(struct qeth_channel *channel)
+-{
+- struct qeth_cmd_buffer *buffer;
+- wait_event(channel->wait_q,
+- ((buffer = qeth_get_buffer(channel)) != NULL));
+- return buffer;
+-}
+-
+-static void
+-qeth_clear_cmd_buffers(struct qeth_channel *channel)
+-{
+- int cnt;
+-
+- for (cnt=0; cnt < QETH_CMD_BUFFER_NO; cnt++)
+- qeth_release_buffer(channel,&channel->iob[cnt]);
+- channel->buf_no = 0;
+- channel->io_buf_no = 0;
+-}
+-
+-/**
+- * start IDX for read and write channel
+- */
+-static int
+-qeth_idx_activate_get_answer(struct qeth_channel *channel,
+- void (*idx_reply_cb)(struct qeth_channel *,
+- struct qeth_cmd_buffer *))
+-{
+- struct qeth_cmd_buffer *iob;
+- unsigned long flags;
+- int rc;
+- struct qeth_card *card;
+-
+- QETH_DBF_TEXT(setup, 2, "idxanswr");
+- card = CARD_FROM_CDEV(channel->ccwdev);
+- iob = qeth_get_buffer(channel);
+- iob->callback = idx_reply_cb;
+- memcpy(&channel->ccw, READ_CCW, sizeof(struct ccw1));
+- channel->ccw.count = QETH_BUFSIZE;
+- channel->ccw.cda = (__u32) __pa(iob->data);
+-
+- wait_event(card->wait_q,
+- atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
+- QETH_DBF_TEXT(setup, 6, "noirqpnd");
+- spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+- rc = ccw_device_start(channel->ccwdev,
+- &channel->ccw,(addr_t) iob, 0, 0);
+- spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+-
+- if (rc) {
+- PRINT_ERR("qeth: Error2 in activating channel rc=%d\n",rc);
+- QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+- atomic_set(&channel->irq_pending, 0);
+- wake_up(&card->wait_q);
+- return rc;
+- }
+- rc = wait_event_interruptible_timeout(card->wait_q,
+- channel->state == CH_STATE_UP, QETH_TIMEOUT);
+- if (rc == -ERESTARTSYS)
+- return rc;
+- if (channel->state != CH_STATE_UP){
+- rc = -ETIME;
+- QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+- qeth_clear_cmd_buffers(channel);
+- } else
+- rc = 0;
+- return rc;
+-}
+-
+-static int
+-qeth_idx_activate_channel(struct qeth_channel *channel,
+- void (*idx_reply_cb)(struct qeth_channel *,
+- struct qeth_cmd_buffer *))
+-{
+- struct qeth_card *card;
+- struct qeth_cmd_buffer *iob;
+- unsigned long flags;
+- __u16 temp;
+- int rc;
+-
+- card = CARD_FROM_CDEV(channel->ccwdev);
+-
+- QETH_DBF_TEXT(setup, 2, "idxactch");
+-
+- iob = qeth_get_buffer(channel);
+- iob->callback = idx_reply_cb;
+- memcpy(&channel->ccw, WRITE_CCW, sizeof(struct ccw1));
+- channel->ccw.count = IDX_ACTIVATE_SIZE;
+- channel->ccw.cda = (__u32) __pa(iob->data);
+- if (channel == &card->write) {
+- memcpy(iob->data, IDX_ACTIVATE_WRITE, IDX_ACTIVATE_SIZE);
+- memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
+- &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
+- card->seqno.trans_hdr++;
+- } else {
+- memcpy(iob->data, IDX_ACTIVATE_READ, IDX_ACTIVATE_SIZE);
+- memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
+- &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
+- }
+- memcpy(QETH_IDX_ACT_ISSUER_RM_TOKEN(iob->data),
+- &card->token.issuer_rm_w,QETH_MPC_TOKEN_LENGTH);
+- memcpy(QETH_IDX_ACT_FUNC_LEVEL(iob->data),
+- &card->info.func_level,sizeof(__u16));
+- temp = raw_devno_from_bus_id(CARD_DDEV_ID(card));
+- memcpy(QETH_IDX_ACT_QDIO_DEV_CUA(iob->data), &temp, 2);
+- temp = (card->info.cula << 8) + card->info.unit_addr2;
+- memcpy(QETH_IDX_ACT_QDIO_DEV_REALADDR(iob->data), &temp, 2);
+-
+- wait_event(card->wait_q,
+- atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
+- QETH_DBF_TEXT(setup, 6, "noirqpnd");
+- spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+- rc = ccw_device_start(channel->ccwdev,
+- &channel->ccw,(addr_t) iob, 0, 0);
+- spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+-
+- if (rc) {
+- PRINT_ERR("qeth: Error1 in activating channel. rc=%d\n",rc);
+- QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+- atomic_set(&channel->irq_pending, 0);
+- wake_up(&card->wait_q);
+- return rc;
+- }
+- rc = wait_event_interruptible_timeout(card->wait_q,
+- channel->state == CH_STATE_ACTIVATING, QETH_TIMEOUT);
+- if (rc == -ERESTARTSYS)
+- return rc;
+- if (channel->state != CH_STATE_ACTIVATING) {
+- PRINT_WARN("qeth: IDX activate timed out!\n");
+- QETH_DBF_TEXT_(setup, 2, "2err%d", -ETIME);
+- qeth_clear_cmd_buffers(channel);
+- return -ETIME;
+- }
+- return qeth_idx_activate_get_answer(channel,idx_reply_cb);
+-}
+-
+-static int
+-qeth_peer_func_level(int level)
+-{
+- if ((level & 0xff) == 8)
+- return (level & 0xff) + 0x400;
+- if (((level >> 8) & 3) == 1)
+- return (level & 0xff) + 0x200;
+- return level;
+-}
+-
+-static void
+-qeth_idx_write_cb(struct qeth_channel *channel, struct qeth_cmd_buffer *iob)
+-{
+- struct qeth_card *card;
+- __u16 temp;
+-
+- QETH_DBF_TEXT(setup ,2, "idxwrcb");
+-
+- if (channel->state == CH_STATE_DOWN) {
+- channel->state = CH_STATE_ACTIVATING;
+- goto out;
+- }
+- card = CARD_FROM_CDEV(channel->ccwdev);
+-
+- if (!(QETH_IS_IDX_ACT_POS_REPLY(iob->data))) {
+- if (QETH_IDX_ACT_CAUSE_CODE(iob->data) == 0x19)
+- PRINT_ERR("IDX_ACTIVATE on write channel device %s: "
+- "adapter exclusively used by another host\n",
+- CARD_WDEV_ID(card));
+- else
+- PRINT_ERR("IDX_ACTIVATE on write channel device %s: "
+- "negative reply\n", CARD_WDEV_ID(card));
+- goto out;
+- }
+- memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2);
+- if ((temp & ~0x0100) != qeth_peer_func_level(card->info.func_level)) {
+- PRINT_WARN("IDX_ACTIVATE on write channel device %s: "
+- "function level mismatch "
+- "(sent: 0x%x, received: 0x%x)\n",
+- CARD_WDEV_ID(card), card->info.func_level, temp);
+- goto out;
+- }
+- channel->state = CH_STATE_UP;
+-out:
+- qeth_release_buffer(channel, iob);
+-}
+-
+-static int
+-qeth_check_idx_response(unsigned char *buffer)
+-{
+- if (!buffer)
+- return 0;
+-
+- QETH_DBF_HEX(control, 2, buffer, QETH_DBF_CONTROL_LEN);
+- if ((buffer[2] & 0xc0) == 0xc0) {
+- PRINT_WARN("received an IDX TERMINATE "
+- "with cause code 0x%02x%s\n",
+- buffer[4],
+- ((buffer[4] == 0x22) ?
+- " -- try another portname" : ""));
+- QETH_DBF_TEXT(trace, 2, "ckidxres");
+- QETH_DBF_TEXT(trace, 2, " idxterm");
+- QETH_DBF_TEXT_(trace, 2, " rc%d", -EIO);
+- return -EIO;
+- }
+- return 0;
+-}
+-
+-static void
+-qeth_idx_read_cb(struct qeth_channel *channel, struct qeth_cmd_buffer *iob)
+-{
+- struct qeth_card *card;
+- __u16 temp;
+-
+- QETH_DBF_TEXT(setup , 2, "idxrdcb");
+- if (channel->state == CH_STATE_DOWN) {
+- channel->state = CH_STATE_ACTIVATING;
+- goto out;
+- }
+-
+- card = CARD_FROM_CDEV(channel->ccwdev);
+- if (qeth_check_idx_response(iob->data)) {
+- goto out;
+- }
+- if (!(QETH_IS_IDX_ACT_POS_REPLY(iob->data))) {
+- if (QETH_IDX_ACT_CAUSE_CODE(iob->data) == 0x19)
+- PRINT_ERR("IDX_ACTIVATE on read channel device %s: "
+- "adapter exclusively used by another host\n",
+- CARD_RDEV_ID(card));
+- else
+- PRINT_ERR("IDX_ACTIVATE on read channel device %s: "
+- "negative reply\n", CARD_RDEV_ID(card));
+- goto out;
+- }
+-
+-/**
+- * temporary fix for microcode bug
+- * to revert it,replace OR by AND
+- */
+- if ( (!QETH_IDX_NO_PORTNAME_REQUIRED(iob->data)) ||
+- (card->info.type == QETH_CARD_TYPE_OSAE) )
+- card->info.portname_required = 1;
+-
+- memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2);
+- if (temp != qeth_peer_func_level(card->info.func_level)) {
+- PRINT_WARN("IDX_ACTIVATE on read channel device %s: function "
+- "level mismatch (sent: 0x%x, received: 0x%x)\n",
+- CARD_RDEV_ID(card), card->info.func_level, temp);
+- goto out;
+- }
+- memcpy(&card->token.issuer_rm_r,
+- QETH_IDX_ACT_ISSUER_RM_TOKEN(iob->data),
+- QETH_MPC_TOKEN_LENGTH);
+- memcpy(&card->info.mcl_level[0],
+- QETH_IDX_REPLY_LEVEL(iob->data), QETH_MCL_LENGTH);
+- channel->state = CH_STATE_UP;
+-out:
+- qeth_release_buffer(channel,iob);
+-}
+-
+-static int
+-qeth_issue_next_read(struct qeth_card *card)
+-{
+- int rc;
+- struct qeth_cmd_buffer *iob;
+-
+- QETH_DBF_TEXT(trace,5,"issnxrd");
+- if (card->read.state != CH_STATE_UP)
+- return -EIO;
+- iob = qeth_get_buffer(&card->read);
+- if (!iob) {
+- PRINT_WARN("issue_next_read failed: no iob available!\n");
+- return -ENOMEM;
+- }
+- qeth_setup_ccw(&card->read, iob->data, QETH_BUFSIZE);
+- QETH_DBF_TEXT(trace, 6, "noirqpnd");
+- rc = ccw_device_start(card->read.ccwdev, &card->read.ccw,
+- (addr_t) iob, 0, 0);
+- if (rc) {
+- PRINT_ERR("Error in starting next read ccw! rc=%i\n", rc);
+- atomic_set(&card->read.irq_pending, 0);
+- qeth_schedule_recovery(card);
+- wake_up(&card->wait_q);
+- }
+- return rc;
+-}
+-
+-static struct qeth_reply *
+-qeth_alloc_reply(struct qeth_card *card)
+-{
+- struct qeth_reply *reply;
+-
+- reply = kzalloc(sizeof(struct qeth_reply), GFP_ATOMIC);
+- if (reply){
+- atomic_set(&reply->refcnt, 1);
+- atomic_set(&reply->received, 0);
+- reply->card = card;
+- };
+- return reply;
+-}
+-
+-static void
+-qeth_get_reply(struct qeth_reply *reply)
+-{
+- WARN_ON(atomic_read(&reply->refcnt) <= 0);
+- atomic_inc(&reply->refcnt);
+-}
+-
+-static void
+-qeth_put_reply(struct qeth_reply *reply)
+-{
+- WARN_ON(atomic_read(&reply->refcnt) <= 0);
+- if (atomic_dec_and_test(&reply->refcnt))
+- kfree(reply);
+-}
+-
+-static void
+-qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd, struct qeth_card *card)
+-{
+- int rc;
+- int com;
+- char * ipa_name;
+-
+- com = cmd->hdr.command;
+- rc = cmd->hdr.return_code;
+- ipa_name = qeth_get_ipa_cmd_name(com);
+-
+- PRINT_ERR("%s(x%X) for %s returned x%X \"%s\"\n", ipa_name, com,
+- QETH_CARD_IFNAME(card), rc, qeth_get_ipa_msg(rc));
+-}
+-
+-static struct qeth_ipa_cmd *
+-qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
+-{
+- struct qeth_ipa_cmd *cmd = NULL;
+-
+- QETH_DBF_TEXT(trace,5,"chkipad");
+- if (IS_IPA(iob->data)){
+- cmd = (struct qeth_ipa_cmd *) PDU_ENCAPSULATION(iob->data);
+- if (IS_IPA_REPLY(cmd)) {
+- if (cmd->hdr.return_code)
+- qeth_issue_ipa_msg(cmd, card);
+- return cmd;
+- }
+- else {
+- switch (cmd->hdr.command) {
+- case IPA_CMD_STOPLAN:
+- PRINT_WARN("Link failure on %s (CHPID 0x%X) - "
+- "there is a network problem or "
+- "someone pulled the cable or "
+- "disabled the port.\n",
+- QETH_CARD_IFNAME(card),
+- card->info.chpid);
+- card->lan_online = 0;
+- if (card->dev && netif_carrier_ok(card->dev))
+- netif_carrier_off(card->dev);
+- return NULL;
+- case IPA_CMD_STARTLAN:
+- PRINT_INFO("Link reestablished on %s "
+- "(CHPID 0x%X). Scheduling "
+- "IP address reset.\n",
+- QETH_CARD_IFNAME(card),
+- card->info.chpid);
+- netif_carrier_on(card->dev);
+- qeth_schedule_recovery(card);
+- return NULL;
+- case IPA_CMD_MODCCID:
+- return cmd;
+- case IPA_CMD_REGISTER_LOCAL_ADDR:
+- QETH_DBF_TEXT(trace,3, "irla");
+- break;
+- case IPA_CMD_UNREGISTER_LOCAL_ADDR:
+- QETH_DBF_TEXT(trace,3, "urla");
+- break;
+- default:
+- PRINT_WARN("Received data is IPA "
+- "but not a reply!\n");
+- break;
+- }
+- }
+- }
+- return cmd;
+-}
+-
+-/**
+- * wake all waiting ipa commands
+- */
+-static void
+-qeth_clear_ipacmd_list(struct qeth_card *card)
+-{
+- struct qeth_reply *reply, *r;
+- unsigned long flags;
+-
+- QETH_DBF_TEXT(trace, 4, "clipalst");
+-
+- spin_lock_irqsave(&card->lock, flags);
+- list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
+- qeth_get_reply(reply);
+- reply->rc = -EIO;
+- atomic_inc(&reply->received);
+- list_del_init(&reply->list);
+- wake_up(&reply->wait_q);
+- qeth_put_reply(reply);
+- }
+- spin_unlock_irqrestore(&card->lock, flags);
+-}
+-
+-static void
+-qeth_send_control_data_cb(struct qeth_channel *channel,
+- struct qeth_cmd_buffer *iob)
+-{
+- struct qeth_card *card;
+- struct qeth_reply *reply, *r;
+- struct qeth_ipa_cmd *cmd;
+- unsigned long flags;
+- int keep_reply;
+-
+- QETH_DBF_TEXT(trace,4,"sndctlcb");
+-
+- card = CARD_FROM_CDEV(channel->ccwdev);
+- if (qeth_check_idx_response(iob->data)) {
+- qeth_clear_ipacmd_list(card);
+- qeth_schedule_recovery(card);
+- goto out;
+- }
+-
+- cmd = qeth_check_ipa_data(card, iob);
+- if ((cmd == NULL) && (card->state != CARD_STATE_DOWN))
+- goto out;
+- /*in case of OSN : check if cmd is set */
+- if (card->info.type == QETH_CARD_TYPE_OSN &&
+- cmd &&
+- cmd->hdr.command != IPA_CMD_STARTLAN &&
+- card->osn_info.assist_cb != NULL) {
+- card->osn_info.assist_cb(card->dev, cmd);
+- goto out;
+- }
+-
+- spin_lock_irqsave(&card->lock, flags);
+- list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) {
+- if ((reply->seqno == QETH_IDX_COMMAND_SEQNO) ||
+- ((cmd) && (reply->seqno == cmd->hdr.seqno))) {
+- qeth_get_reply(reply);
+- list_del_init(&reply->list);
+- spin_unlock_irqrestore(&card->lock, flags);
+- keep_reply = 0;
+- if (reply->callback != NULL) {
+- if (cmd) {
+- reply->offset = (__u16)((char*)cmd -
+- (char *)iob->data);
+- keep_reply = reply->callback(card,
+- reply,
+- (unsigned long)cmd);
+- } else
+- keep_reply = reply->callback(card,
+- reply,
+- (unsigned long)iob);
+- }
+- if (cmd)
+- reply->rc = (u16) cmd->hdr.return_code;
+- else if (iob->rc)
+- reply->rc = iob->rc;
+- if (keep_reply) {
+- spin_lock_irqsave(&card->lock, flags);
+- list_add_tail(&reply->list,
+- &card->cmd_waiter_list);
+- spin_unlock_irqrestore(&card->lock, flags);
+- } else {
+- atomic_inc(&reply->received);
+- wake_up(&reply->wait_q);
+- }
+- qeth_put_reply(reply);
+- goto out;
+- }
+- }
+- spin_unlock_irqrestore(&card->lock, flags);
+-out:
+- memcpy(&card->seqno.pdu_hdr_ack,
+- QETH_PDU_HEADER_SEQ_NO(iob->data),
+- QETH_SEQ_NO_LENGTH);
+- qeth_release_buffer(channel,iob);
+-}
+-
+-static void
+-qeth_prepare_control_data(struct qeth_card *card, int len,
+- struct qeth_cmd_buffer *iob)
+-{
+- qeth_setup_ccw(&card->write,iob->data,len);
+- iob->callback = qeth_release_buffer;
+-
+- memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
+- &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
+- card->seqno.trans_hdr++;
+- memcpy(QETH_PDU_HEADER_SEQ_NO(iob->data),
+- &card->seqno.pdu_hdr, QETH_SEQ_NO_LENGTH);
+- card->seqno.pdu_hdr++;
+- memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(iob->data),
+- &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH);
+- QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
+-}
+-
+-static int
+-qeth_send_control_data(struct qeth_card *card, int len,
+- struct qeth_cmd_buffer *iob,
+- int (*reply_cb)
+- (struct qeth_card *, struct qeth_reply*, unsigned long),
+- void *reply_param)
+-
+-{
+- int rc;
+- unsigned long flags;
+- struct qeth_reply *reply = NULL;
+- unsigned long timeout;
+-
+- QETH_DBF_TEXT(trace, 2, "sendctl");
+-
+- reply = qeth_alloc_reply(card);
+- if (!reply) {
+- PRINT_WARN("Could no alloc qeth_reply!\n");
+- return -ENOMEM;
+- }
+- reply->callback = reply_cb;
+- reply->param = reply_param;
+- if (card->state == CARD_STATE_DOWN)
+- reply->seqno = QETH_IDX_COMMAND_SEQNO;
+- else
+- reply->seqno = card->seqno.ipa++;
+- init_waitqueue_head(&reply->wait_q);
+- spin_lock_irqsave(&card->lock, flags);
+- list_add_tail(&reply->list, &card->cmd_waiter_list);
+- spin_unlock_irqrestore(&card->lock, flags);
+- QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
+-
+- while (atomic_cmpxchg(&card->write.irq_pending, 0, 1)) ;
+- qeth_prepare_control_data(card, len, iob);
+-
+- if (IS_IPA(iob->data))
+- timeout = jiffies + QETH_IPA_TIMEOUT;
+- else
+- timeout = jiffies + QETH_TIMEOUT;
+-
+- QETH_DBF_TEXT(trace, 6, "noirqpnd");
+- spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
+- rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
+- (addr_t) iob, 0, 0);
+- spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
+- if (rc){
+- PRINT_WARN("qeth_send_control_data: "
+- "ccw_device_start rc = %i\n", rc);
+- QETH_DBF_TEXT_(trace, 2, " err%d", rc);
+- spin_lock_irqsave(&card->lock, flags);
+- list_del_init(&reply->list);
+- qeth_put_reply(reply);
+- spin_unlock_irqrestore(&card->lock, flags);
+- qeth_release_buffer(iob->channel, iob);
+- atomic_set(&card->write.irq_pending, 0);
+- wake_up(&card->wait_q);
+- return rc;
+- }
+- while (!atomic_read(&reply->received)) {
+- if (time_after(jiffies, timeout)) {
+- spin_lock_irqsave(&reply->card->lock, flags);
+- list_del_init(&reply->list);
+- spin_unlock_irqrestore(&reply->card->lock, flags);
+- reply->rc = -ETIME;
+- atomic_inc(&reply->received);
+- wake_up(&reply->wait_q);
+- }
+- cpu_relax();
+- };
+- rc = reply->rc;
+- qeth_put_reply(reply);
+- return rc;
+-}
+-
+-static int
+-qeth_osn_send_control_data(struct qeth_card *card, int len,
+- struct qeth_cmd_buffer *iob)
+-{
+- unsigned long flags;
+- int rc = 0;
+-
+- QETH_DBF_TEXT(trace, 5, "osndctrd");
+-
+- wait_event(card->wait_q,
+- atomic_cmpxchg(&card->write.irq_pending, 0, 1) == 0);
+- qeth_prepare_control_data(card, len, iob);
+- QETH_DBF_TEXT(trace, 6, "osnoirqp");
+- spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
+- rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
+- (addr_t) iob, 0, 0);
+- spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
+- if (rc){
+- PRINT_WARN("qeth_osn_send_control_data: "
+- "ccw_device_start rc = %i\n", rc);
+- QETH_DBF_TEXT_(trace, 2, " err%d", rc);
+- qeth_release_buffer(iob->channel, iob);
+- atomic_set(&card->write.irq_pending, 0);
+- wake_up(&card->wait_q);
+- }
+- return rc;
+-}
+-
+-static inline void
+-qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+- char prot_type)
+-{
+- memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
+- memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data),&prot_type,1);
+- memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
+- &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+-}
+-
+-static int
+-qeth_osn_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+- int data_len)
+-{
+- u16 s1, s2;
+-
+- QETH_DBF_TEXT(trace,4,"osndipa");
+-
+- qeth_prepare_ipa_cmd(card, iob, QETH_PROT_OSN2);
+- s1 = (u16)(IPA_PDU_HEADER_SIZE + data_len);
+- s2 = (u16)data_len;
+- memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
+- memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
+- memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
+- memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
+- return qeth_osn_send_control_data(card, s1, iob);
+-}
+-
+-static int
+-qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+- int (*reply_cb)
+- (struct qeth_card *,struct qeth_reply*, unsigned long),
+- void *reply_param)
+-{
+- int rc;
+- char prot_type;
+-
+- QETH_DBF_TEXT(trace,4,"sendipa");
+-
+- if (card->options.layer2)
+- if (card->info.type == QETH_CARD_TYPE_OSN)
+- prot_type = QETH_PROT_OSN2;
+- else
+- prot_type = QETH_PROT_LAYER2;
+- else
+- prot_type = QETH_PROT_TCPIP;
+- qeth_prepare_ipa_cmd(card,iob,prot_type);
+- rc = qeth_send_control_data(card, IPA_CMD_LENGTH, iob,
+- reply_cb, reply_param);
+- return rc;
+-}
+-
+-
+-static int
+-qeth_cm_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
+- unsigned long data)
+-{
+- struct qeth_cmd_buffer *iob;
+-
+- QETH_DBF_TEXT(setup, 2, "cmenblcb");
+-
+- iob = (struct qeth_cmd_buffer *) data;
+- memcpy(&card->token.cm_filter_r,
+- QETH_CM_ENABLE_RESP_FILTER_TOKEN(iob->data),
+- QETH_MPC_TOKEN_LENGTH);
+- QETH_DBF_TEXT_(setup, 2, " rc%d", iob->rc);
+- return 0;
+-}
+-
+-static int
+-qeth_cm_enable(struct qeth_card *card)
+-{
+- int rc;
+- struct qeth_cmd_buffer *iob;
+-
+- QETH_DBF_TEXT(setup,2,"cmenable");
+-
+- iob = qeth_wait_for_buffer(&card->write);
+- memcpy(iob->data, CM_ENABLE, CM_ENABLE_SIZE);
+- memcpy(QETH_CM_ENABLE_ISSUER_RM_TOKEN(iob->data),
+- &card->token.issuer_rm_r, QETH_MPC_TOKEN_LENGTH);
+- memcpy(QETH_CM_ENABLE_FILTER_TOKEN(iob->data),
+- &card->token.cm_filter_w, QETH_MPC_TOKEN_LENGTH);
+-
+- rc = qeth_send_control_data(card, CM_ENABLE_SIZE, iob,
+- qeth_cm_enable_cb, NULL);
+- return rc;
+-}
+-
+-static int
+-qeth_cm_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
+- unsigned long data)
+-{
+-
+- struct qeth_cmd_buffer *iob;
+-
+- QETH_DBF_TEXT(setup, 2, "cmsetpcb");
+-
+- iob = (struct qeth_cmd_buffer *) data;
+- memcpy(&card->token.cm_connection_r,
+- QETH_CM_SETUP_RESP_DEST_ADDR(iob->data),
+- QETH_MPC_TOKEN_LENGTH);
+- QETH_DBF_TEXT_(setup, 2, " rc%d", iob->rc);
+- return 0;
+-}
+-
+-static int
+-qeth_cm_setup(struct qeth_card *card)
+-{
+- int rc;
+- struct qeth_cmd_buffer *iob;
+-
+- QETH_DBF_TEXT(setup,2,"cmsetup");
+-
+- iob = qeth_wait_for_buffer(&card->write);
+- memcpy(iob->data, CM_SETUP, CM_SETUP_SIZE);
+- memcpy(QETH_CM_SETUP_DEST_ADDR(iob->data),
+- &card->token.issuer_rm_r, QETH_MPC_TOKEN_LENGTH);
+- memcpy(QETH_CM_SETUP_CONNECTION_TOKEN(iob->data),
+- &card->token.cm_connection_w, QETH_MPC_TOKEN_LENGTH);
+- memcpy(QETH_CM_SETUP_FILTER_TOKEN(iob->data),
+- &card->token.cm_filter_r, QETH_MPC_TOKEN_LENGTH);
+- rc = qeth_send_control_data(card, CM_SETUP_SIZE, iob,
+- qeth_cm_setup_cb, NULL);
+- return rc;
+-
+-}
+-
+-static int
+-qeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
+- unsigned long data)
+-{
+-
+- __u16 mtu, framesize;
+- __u16 len;
+- __u8 link_type;
+- struct qeth_cmd_buffer *iob;
+-
+- QETH_DBF_TEXT(setup, 2, "ulpenacb");
+-
+- iob = (struct qeth_cmd_buffer *) data;
+- memcpy(&card->token.ulp_filter_r,
+- QETH_ULP_ENABLE_RESP_FILTER_TOKEN(iob->data),
+- QETH_MPC_TOKEN_LENGTH);
+- if (qeth_get_mtu_out_of_mpc(card->info.type)) {
+- memcpy(&framesize, QETH_ULP_ENABLE_RESP_MAX_MTU(iob->data), 2);
+- mtu = qeth_get_mtu_outof_framesize(framesize);
+- if (!mtu) {
+- iob->rc = -EINVAL;
+- QETH_DBF_TEXT_(setup, 2, " rc%d", iob->rc);
+- return 0;
+- }
+- card->info.max_mtu = mtu;
+- card->info.initial_mtu = mtu;
+- card->qdio.in_buf_size = mtu + 2 * PAGE_SIZE;
+- } else {
+- card->info.initial_mtu = qeth_get_initial_mtu_for_card(card);
+- card->info.max_mtu = qeth_get_max_mtu_for_card(card->info.type);
+- card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT;
+- }
+-
+- memcpy(&len, QETH_ULP_ENABLE_RESP_DIFINFO_LEN(iob->data), 2);
+- if (len >= QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE) {
+- memcpy(&link_type,
+- QETH_ULP_ENABLE_RESP_LINK_TYPE(iob->data), 1);
+- card->info.link_type = link_type;
+- } else
+- card->info.link_type = 0;
+- QETH_DBF_TEXT_(setup, 2, " rc%d", iob->rc);
+- return 0;
+-}
+-
+-static int
+-qeth_ulp_enable(struct qeth_card *card)
+-{
+- int rc;
+- char prot_type;
+- struct qeth_cmd_buffer *iob;
+-
+- /*FIXME: trace view callbacks*/
+- QETH_DBF_TEXT(setup,2,"ulpenabl");
+-
+- iob = qeth_wait_for_buffer(&card->write);
+- memcpy(iob->data, ULP_ENABLE, ULP_ENABLE_SIZE);
+-
+- *(QETH_ULP_ENABLE_LINKNUM(iob->data)) =
+- (__u8) card->info.portno;
+- if (card->options.layer2)
+- if (card->info.type == QETH_CARD_TYPE_OSN)
+- prot_type = QETH_PROT_OSN2;
+- else
+- prot_type = QETH_PROT_LAYER2;
+- else
+- prot_type = QETH_PROT_TCPIP;
+-
+- memcpy(QETH_ULP_ENABLE_PROT_TYPE(iob->data),&prot_type,1);
+- memcpy(QETH_ULP_ENABLE_DEST_ADDR(iob->data),
+- &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
+- memcpy(QETH_ULP_ENABLE_FILTER_TOKEN(iob->data),
+- &card->token.ulp_filter_w, QETH_MPC_TOKEN_LENGTH);
+- memcpy(QETH_ULP_ENABLE_PORTNAME_AND_LL(iob->data),
+- card->info.portname, 9);
+- rc = qeth_send_control_data(card, ULP_ENABLE_SIZE, iob,
+- qeth_ulp_enable_cb, NULL);
+- return rc;
+-
+-}
+-
+-static int
+-qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
+- unsigned long data)
+-{
+- struct qeth_cmd_buffer *iob;
+-
+- QETH_DBF_TEXT(setup, 2, "ulpstpcb");
+-
+- iob = (struct qeth_cmd_buffer *) data;
+- memcpy(&card->token.ulp_connection_r,
+- QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(iob->data),
+- QETH_MPC_TOKEN_LENGTH);
+- QETH_DBF_TEXT_(setup, 2, " rc%d", iob->rc);
+- return 0;
+-}
+-
+-static int
+-qeth_ulp_setup(struct qeth_card *card)
+-{
+- int rc;
+- __u16 temp;
+- struct qeth_cmd_buffer *iob;
+- struct ccw_dev_id dev_id;
+-
+- QETH_DBF_TEXT(setup,2,"ulpsetup");
+-
+- iob = qeth_wait_for_buffer(&card->write);
+- memcpy(iob->data, ULP_SETUP, ULP_SETUP_SIZE);
+-
+- memcpy(QETH_ULP_SETUP_DEST_ADDR(iob->data),
+- &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
+- memcpy(QETH_ULP_SETUP_CONNECTION_TOKEN(iob->data),
+- &card->token.ulp_connection_w, QETH_MPC_TOKEN_LENGTH);
+- memcpy(QETH_ULP_SETUP_FILTER_TOKEN(iob->data),
+- &card->token.ulp_filter_r, QETH_MPC_TOKEN_LENGTH);
+-
+- ccw_device_get_id(CARD_DDEV(card), &dev_id);
+- memcpy(QETH_ULP_SETUP_CUA(iob->data), &dev_id.devno, 2);
+- temp = (card->info.cula << 8) + card->info.unit_addr2;
+- memcpy(QETH_ULP_SETUP_REAL_DEVADDR(iob->data), &temp, 2);
+- rc = qeth_send_control_data(card, ULP_SETUP_SIZE, iob,
+- qeth_ulp_setup_cb, NULL);
+- return rc;
+-}
+-
+-static inline int
+-qeth_check_qdio_errors(struct qdio_buffer *buf, unsigned int qdio_error,
+- unsigned int siga_error, const char *dbftext)
+-{
+- if (qdio_error || siga_error) {
+- QETH_DBF_TEXT(trace, 2, dbftext);
+- QETH_DBF_TEXT(qerr, 2, dbftext);
+- QETH_DBF_TEXT_(qerr, 2, " F15=%02X",
+- buf->element[15].flags & 0xff);
+- QETH_DBF_TEXT_(qerr, 2, " F14=%02X",
+- buf->element[14].flags & 0xff);
+- QETH_DBF_TEXT_(qerr, 2, " qerr=%X", qdio_error);
+- QETH_DBF_TEXT_(qerr, 2, " serr=%X", siga_error);
+- return 1;
+- }
+- return 0;
+-}
+-
+-static struct sk_buff *
+-qeth_get_skb(unsigned int length, struct qeth_hdr *hdr)
+-{
+- struct sk_buff* skb;
+- int add_len;
+-
+- add_len = 0;
+- if (hdr->hdr.osn.id == QETH_HEADER_TYPE_OSN)
+- add_len = sizeof(struct qeth_hdr);
+-#ifdef CONFIG_QETH_VLAN
+- else
+- add_len = VLAN_HLEN;
+-#endif
+- skb = dev_alloc_skb(length + add_len);
+- if (skb && add_len)
+- skb_reserve(skb, add_len);
+- return skb;
+-}
+-
+-static inline int
+-qeth_create_skb_frag(struct qdio_buffer_element *element,
+- struct sk_buff **pskb,
+- int offset, int *pfrag, int data_len)
+-{
+- struct page *page = virt_to_page(element->addr);
+- if (*pfrag == 0) {
+- /* the upper protocol layers assume that there is data in the
+- * skb itself. Copy a small amount (64 bytes) to make them
+- * happy. */
+- *pskb = dev_alloc_skb(64 + QETH_FAKE_LL_LEN_ETH);
+- if (!(*pskb))
+- return -ENOMEM;
+- skb_reserve(*pskb, QETH_FAKE_LL_LEN_ETH);
+- if (data_len <= 64) {
+- memcpy(skb_put(*pskb, data_len), element->addr + offset,
+- data_len);
+- } else {
+- get_page(page);
+- memcpy(skb_put(*pskb, 64), element->addr + offset, 64);
+- skb_fill_page_desc(*pskb, *pfrag, page, offset + 64,
+- data_len - 64);
+- (*pskb)->data_len += data_len - 64;
+- (*pskb)->len += data_len - 64;
+- (*pskb)->truesize += data_len - 64;
+- }
+- } else {
+- get_page(page);
+- skb_fill_page_desc(*pskb, *pfrag, page, offset, data_len);
+- (*pskb)->data_len += data_len;
+- (*pskb)->len += data_len;
+- (*pskb)->truesize += data_len;
+- }
+- (*pfrag)++;
+- return 0;
+-}
+-
+-static inline struct qeth_buffer_pool_entry *
+-qeth_find_free_buffer_pool_entry(struct qeth_card *card)
+-{
+- struct list_head *plh;
+- struct qeth_buffer_pool_entry *entry;
+- int i, free;
+- struct page *page;
+-
+- if (list_empty(&card->qdio.in_buf_pool.entry_list))
+- return NULL;
+-
+- list_for_each(plh, &card->qdio.in_buf_pool.entry_list) {
+- entry = list_entry(plh, struct qeth_buffer_pool_entry, list);
+- free = 1;
+- for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
+- if (page_count(virt_to_page(entry->elements[i])) > 1) {
+- free = 0;
+- break;
+- }
+- }
+- if (free) {
+- list_del_init(&entry->list);
+- return entry;
+- }
+- }
+-
+- /* no free buffer in pool so take first one and swap pages */
+- entry = list_entry(card->qdio.in_buf_pool.entry_list.next,
+- struct qeth_buffer_pool_entry, list);
+- for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
+- if (page_count(virt_to_page(entry->elements[i])) > 1) {
+- page = alloc_page(GFP_ATOMIC|GFP_DMA);
+- if (!page) {
+- return NULL;
+- } else {
+- free_page((unsigned long)entry->elements[i]);
+- entry->elements[i] = page_address(page);
+- if (card->options.performance_stats)
+- card->perf_stats.sg_alloc_page_rx++;
+- }
+- }
+- }
+- list_del_init(&entry->list);
+- return entry;
+-}
+-
+-static struct sk_buff *
+-qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
+- struct qdio_buffer_element **__element, int *__offset,
+- struct qeth_hdr **hdr)
+-{
+- struct qdio_buffer_element *element = *__element;
+- int offset = *__offset;
+- struct sk_buff *skb = NULL;
+- int skb_len;
+- void *data_ptr;
+- int data_len;
+- int use_rx_sg = 0;
+- int frag = 0;
+-
+- QETH_DBF_TEXT(trace,6,"nextskb");
+- /* qeth_hdr must not cross element boundaries */
+- if (element->length < offset + sizeof(struct qeth_hdr)){
+- if (qeth_is_last_sbale(element))
+- return NULL;
+- element++;
+- offset = 0;
+- if (element->length < sizeof(struct qeth_hdr))
+- return NULL;
+- }
+- *hdr = element->addr + offset;
+-
+- offset += sizeof(struct qeth_hdr);
+- if (card->options.layer2)
+- if (card->info.type == QETH_CARD_TYPE_OSN)
+- skb_len = (*hdr)->hdr.osn.pdu_length;
+- else
+- skb_len = (*hdr)->hdr.l2.pkt_length;
+- else
+- skb_len = (*hdr)->hdr.l3.length;
+-
+- if (!skb_len)
+- return NULL;
+- if ((skb_len >= card->options.rx_sg_cb) &&
+- (!(card->info.type == QETH_CARD_TYPE_OSN)) &&
+- (!atomic_read(&card->force_alloc_skb))) {
+- use_rx_sg = 1;
+- } else {
+- if (card->options.fake_ll) {
+- if (card->dev->type == ARPHRD_IEEE802_TR) {
+- if (!(skb = qeth_get_skb(skb_len +
+- QETH_FAKE_LL_LEN_TR, *hdr)))
+- goto no_mem;
+- skb_reserve(skb, QETH_FAKE_LL_LEN_TR);
+- } else {
+- if (!(skb = qeth_get_skb(skb_len +
+- QETH_FAKE_LL_LEN_ETH, *hdr)))
+- goto no_mem;
+- skb_reserve(skb, QETH_FAKE_LL_LEN_ETH);
+- }
+- } else {
+- skb = qeth_get_skb(skb_len, *hdr);
+- if (!skb)
+- goto no_mem;
+- }
+- }
+-
+- data_ptr = element->addr + offset;
+- while (skb_len) {
+- data_len = min(skb_len, (int)(element->length - offset));
+- if (data_len) {
+- if (use_rx_sg) {
+- if (qeth_create_skb_frag(element, &skb, offset,
+- &frag, data_len))
+- goto no_mem;
+- } else {
+- memcpy(skb_put(skb, data_len), data_ptr,
+- data_len);
+- }
+- }
+- skb_len -= data_len;
+- if (skb_len){
+- if (qeth_is_last_sbale(element)){
+- QETH_DBF_TEXT(trace,4,"unexeob");
+- QETH_DBF_TEXT_(trace,4,"%s",CARD_BUS_ID(card));
+- QETH_DBF_TEXT(qerr,2,"unexeob");
+- QETH_DBF_TEXT_(qerr,2,"%s",CARD_BUS_ID(card));
+- QETH_DBF_HEX(misc,4,buffer,sizeof(*buffer));
+- dev_kfree_skb_any(skb);
+- card->stats.rx_errors++;
+- return NULL;
+- }
+- element++;
+- offset = 0;
+- data_ptr = element->addr;
+- } else {
+- offset += data_len;
+- }
+- }
+- *__element = element;
+- *__offset = offset;
+- if (use_rx_sg && card->options.performance_stats) {
+- card->perf_stats.sg_skbs_rx++;
+- card->perf_stats.sg_frags_rx += skb_shinfo(skb)->nr_frags;
+- }
+- return skb;
+-no_mem:
+- if (net_ratelimit()){
+- PRINT_WARN("No memory for packet received on %s.\n",
+- QETH_CARD_IFNAME(card));
+- QETH_DBF_TEXT(trace,2,"noskbmem");
+- QETH_DBF_TEXT_(trace,2,"%s",CARD_BUS_ID(card));
+- }
+- card->stats.rx_dropped++;
+- return NULL;
+-}
+-
+-static __be16
+-qeth_type_trans(struct sk_buff *skb, struct net_device *dev)
+-{
+- struct qeth_card *card;
+- struct ethhdr *eth;
+-
+- QETH_DBF_TEXT(trace,6,"typtrans");
+-
+- card = (struct qeth_card *)dev->priv;
+-#ifdef CONFIG_TR
+- if ((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
+- (card->info.link_type == QETH_LINK_TYPE_LANE_TR))
+- return tr_type_trans(skb,dev);
+-#endif /* CONFIG_TR */
+- skb_reset_mac_header(skb);
+- skb_pull(skb, ETH_HLEN );
+- eth = eth_hdr(skb);
+-
+- if (*eth->h_dest & 1) {
+- if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
+- skb->pkt_type = PACKET_BROADCAST;
+- else
+- skb->pkt_type = PACKET_MULTICAST;
+- } else if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
+- skb->pkt_type = PACKET_OTHERHOST;
+-
+- if (ntohs(eth->h_proto) >= 1536)
+- return eth->h_proto;
+- if (*(unsigned short *) (skb->data) == 0xFFFF)
+- return htons(ETH_P_802_3);
+- return htons(ETH_P_802_2);
+-}
+-
+-static void
+-qeth_rebuild_skb_fake_ll_tr(struct qeth_card *card, struct sk_buff *skb,
+- struct qeth_hdr *hdr)
+-{
+- struct trh_hdr *fake_hdr;
+- struct trllc *fake_llc;
+- struct iphdr *ip_hdr;
+-
+- QETH_DBF_TEXT(trace,5,"skbfktr");
+- skb_set_mac_header(skb, (int)-QETH_FAKE_LL_LEN_TR);
+- /* this is a fake ethernet header */
+- fake_hdr = tr_hdr(skb);
+-
+- /* the destination MAC address */
+- switch (skb->pkt_type){
+- case PACKET_MULTICAST:
+- switch (skb->protocol){
+-#ifdef CONFIG_QETH_IPV6
+- case __constant_htons(ETH_P_IPV6):
+- ndisc_mc_map((struct in6_addr *)
+- skb->data + QETH_FAKE_LL_V6_ADDR_POS,
+- fake_hdr->daddr, card->dev, 0);
+- break;
+-#endif /* CONFIG_QETH_IPV6 */
+- case __constant_htons(ETH_P_IP):
+- ip_hdr = (struct iphdr *)skb->data;
+- ip_tr_mc_map(ip_hdr->daddr, fake_hdr->daddr);
+- break;
+- default:
+- memcpy(fake_hdr->daddr, card->dev->dev_addr, TR_ALEN);
+- }
+- break;
+- case PACKET_BROADCAST:
+- memset(fake_hdr->daddr, 0xff, TR_ALEN);
+- break;
+- default:
+- memcpy(fake_hdr->daddr, card->dev->dev_addr, TR_ALEN);
+- }
+- /* the source MAC address */
+- if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR)
+- memcpy(fake_hdr->saddr, &hdr->hdr.l3.dest_addr[2], TR_ALEN);
+- else
+- memset(fake_hdr->saddr, 0, TR_ALEN);
+- fake_hdr->rcf=0;
+- fake_llc = (struct trllc*)&(fake_hdr->rcf);
+- fake_llc->dsap = EXTENDED_SAP;
+- fake_llc->ssap = EXTENDED_SAP;
+- fake_llc->llc = UI_CMD;
+- fake_llc->protid[0] = 0;
+- fake_llc->protid[1] = 0;
+- fake_llc->protid[2] = 0;
+- fake_llc->ethertype = ETH_P_IP;
+-}
+-
+-static void
+-qeth_rebuild_skb_fake_ll_eth(struct qeth_card *card, struct sk_buff *skb,
+- struct qeth_hdr *hdr)
+-{
+- struct ethhdr *fake_hdr;
+- struct iphdr *ip_hdr;
+-
+- QETH_DBF_TEXT(trace,5,"skbfketh");
+- skb_set_mac_header(skb, -QETH_FAKE_LL_LEN_ETH);
+- /* this is a fake ethernet header */
+- fake_hdr = eth_hdr(skb);
+-
+- /* the destination MAC address */
+- switch (skb->pkt_type){
+- case PACKET_MULTICAST:
+- switch (skb->protocol){
+-#ifdef CONFIG_QETH_IPV6
+- case __constant_htons(ETH_P_IPV6):
+- ndisc_mc_map((struct in6_addr *)
+- skb->data + QETH_FAKE_LL_V6_ADDR_POS,
+- fake_hdr->h_dest, card->dev, 0);
+- break;
+-#endif /* CONFIG_QETH_IPV6 */
+- case __constant_htons(ETH_P_IP):
+- ip_hdr = (struct iphdr *)skb->data;
+- ip_eth_mc_map(ip_hdr->daddr, fake_hdr->h_dest);
+- break;
+- default:
+- memcpy(fake_hdr->h_dest, card->dev->dev_addr, ETH_ALEN);
+- }
+- break;
+- case PACKET_BROADCAST:
+- memset(fake_hdr->h_dest, 0xff, ETH_ALEN);
+- break;
+- default:
+- memcpy(fake_hdr->h_dest, card->dev->dev_addr, ETH_ALEN);
+- }
+- /* the source MAC address */
+- if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR)
+- memcpy(fake_hdr->h_source, &hdr->hdr.l3.dest_addr[2], ETH_ALEN);
+- else
+- memset(fake_hdr->h_source, 0, ETH_ALEN);
+- /* the protocol */
+- fake_hdr->h_proto = skb->protocol;
+-}
+-
+-static inline void
+-qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb,
+- struct qeth_hdr *hdr)
+-{
+- if (card->dev->type == ARPHRD_IEEE802_TR)
+- qeth_rebuild_skb_fake_ll_tr(card, skb, hdr);
+- else
+- qeth_rebuild_skb_fake_ll_eth(card, skb, hdr);
+-}
+-
+-static inline void
+-qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
+- struct qeth_hdr *hdr)
+-{
+- skb->pkt_type = PACKET_HOST;
+- skb->protocol = qeth_type_trans(skb, skb->dev);
+- if (card->options.checksum_type == NO_CHECKSUMMING)
+- skb->ip_summed = CHECKSUM_UNNECESSARY;
+- else
+- skb->ip_summed = CHECKSUM_NONE;
+- *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
+-}
+-
+-static __u16
+-qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
+- struct qeth_hdr *hdr)
+-{
+- unsigned short vlan_id = 0;
+-#ifdef CONFIG_QETH_IPV6
+- if (hdr->hdr.l3.flags & QETH_HDR_PASSTHRU) {
+- skb->pkt_type = PACKET_HOST;
+- skb->protocol = qeth_type_trans(skb, card->dev);
+- return 0;
+- }
+-#endif /* CONFIG_QETH_IPV6 */
+- skb->protocol = htons((hdr->hdr.l3.flags & QETH_HDR_IPV6)? ETH_P_IPV6 :
+- ETH_P_IP);
+- switch (hdr->hdr.l3.flags & QETH_HDR_CAST_MASK){
+- case QETH_CAST_UNICAST:
+- skb->pkt_type = PACKET_HOST;
+- break;
+- case QETH_CAST_MULTICAST:
+- skb->pkt_type = PACKET_MULTICAST;
+- card->stats.multicast++;
+- break;
+- case QETH_CAST_BROADCAST:
+- skb->pkt_type = PACKET_BROADCAST;
+- card->stats.multicast++;
+- break;
+- case QETH_CAST_ANYCAST:
+- case QETH_CAST_NOCAST:
+- default:
+- skb->pkt_type = PACKET_HOST;
+- }
+-
+- if (hdr->hdr.l3.ext_flags &
+- (QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) {
+- vlan_id = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME)?
+- hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]);
+- }
+-
+- if (card->options.fake_ll)
+- qeth_rebuild_skb_fake_ll(card, skb, hdr);
+- else
+- skb_reset_mac_header(skb);
+- skb->ip_summed = card->options.checksum_type;
+- if (card->options.checksum_type == HW_CHECKSUMMING){
+- if ( (hdr->hdr.l3.ext_flags &
+- (QETH_HDR_EXT_CSUM_HDR_REQ |
+- QETH_HDR_EXT_CSUM_TRANSP_REQ)) ==
+- (QETH_HDR_EXT_CSUM_HDR_REQ |
+- QETH_HDR_EXT_CSUM_TRANSP_REQ) )
+- skb->ip_summed = CHECKSUM_UNNECESSARY;
+- else
+- skb->ip_summed = SW_CHECKSUMMING;
+- }
+- return vlan_id;
+-}
+-
+-static void
+-qeth_process_inbound_buffer(struct qeth_card *card,
+- struct qeth_qdio_buffer *buf, int index)
+-{
+- struct qdio_buffer_element *element;
+- struct sk_buff *skb;
+- struct qeth_hdr *hdr;
+- int offset;
+- int rxrc;
+- __u16 vlan_tag = 0;
+-
+- /* get first element of current buffer */
+- element = (struct qdio_buffer_element *)&buf->buffer->element[0];
+- offset = 0;
+- if (card->options.performance_stats)
+- card->perf_stats.bufs_rec++;
+- while((skb = qeth_get_next_skb(card, buf->buffer, &element,
+- &offset, &hdr))) {
+- skb->dev = card->dev;
+- if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
+- qeth_layer2_rebuild_skb(card, skb, hdr);
+- else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3)
+- vlan_tag = qeth_rebuild_skb(card, skb, hdr);
+- else if (hdr->hdr.osn.id == QETH_HEADER_TYPE_OSN) {
+- skb_push(skb, sizeof(struct qeth_hdr));
+- skb_copy_to_linear_data(skb, hdr,
+- sizeof(struct qeth_hdr));
+- } else { /* unknown header type */
+- dev_kfree_skb_any(skb);
+- QETH_DBF_TEXT(trace, 3, "inbunkno");
+- QETH_DBF_HEX(control, 3, hdr, QETH_DBF_CONTROL_LEN);
+- continue;
+- }
+- /* is device UP ? */
+- if (!(card->dev->flags & IFF_UP)){
+- dev_kfree_skb_any(skb);
+- continue;
+- }
+- if (card->info.type == QETH_CARD_TYPE_OSN)
+- rxrc = card->osn_info.data_cb(skb);
+- else
+-#ifdef CONFIG_QETH_VLAN
+- if (vlan_tag)
+- if (card->vlangrp)
+- vlan_hwaccel_rx(skb, card->vlangrp, vlan_tag);
+- else {
+- dev_kfree_skb_any(skb);
+- continue;
+- }
+- else
+-#endif
+- rxrc = netif_rx(skb);
+- card->dev->last_rx = jiffies;
+- card->stats.rx_packets++;
+- card->stats.rx_bytes += skb->len;
+- }
+-}
+-
+-static int
+-qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf)
+-{
+- struct qeth_buffer_pool_entry *pool_entry;
+- int i;
+-
+- pool_entry = qeth_find_free_buffer_pool_entry(card);
+- if (!pool_entry)
+- return 1;
+- /*
+- * since the buffer is accessed only from the input_tasklet
+- * there shouldn't be a need to synchronize; also, since we use
+- * the QETH_IN_BUF_REQUEUE_THRESHOLD we should never run out off
+- * buffers
+- */
+- BUG_ON(!pool_entry);
+-
+- buf->pool_entry = pool_entry;
+- for(i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i){
+- buf->buffer->element[i].length = PAGE_SIZE;
+- buf->buffer->element[i].addr = pool_entry->elements[i];
+- if (i == QETH_MAX_BUFFER_ELEMENTS(card) - 1)
+- buf->buffer->element[i].flags = SBAL_FLAGS_LAST_ENTRY;
+- else
+- buf->buffer->element[i].flags = 0;
+- }
+- buf->state = QETH_QDIO_BUF_EMPTY;
+- return 0;
+-}
+-
+-static void
+-qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
+- struct qeth_qdio_out_buffer *buf)
+-{
+- int i;
+- struct sk_buff *skb;
+-
+- /* is PCI flag set on buffer? */
+- if (buf->buffer->element[0].flags & 0x40)
+- atomic_dec(&queue->set_pci_flags_count);
+-
+- while ((skb = skb_dequeue(&buf->skb_list))){
+- atomic_dec(&skb->users);
+- dev_kfree_skb_any(skb);
+- }
+- qeth_eddp_buf_release_contexts(buf);
+- for(i = 0; i < QETH_MAX_BUFFER_ELEMENTS(queue->card); ++i){
+- buf->buffer->element[i].length = 0;
+- buf->buffer->element[i].addr = NULL;
+- buf->buffer->element[i].flags = 0;
+- }
+- buf->next_element_to_fill = 0;
+- atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY);
+-}
+-
+-static void
+-qeth_queue_input_buffer(struct qeth_card *card, int index)
+-{
+- struct qeth_qdio_q *queue = card->qdio.in_q;
+- int count;
+- int i;
+- int rc;
+- int newcount = 0;
+-
+- QETH_DBF_TEXT(trace,6,"queinbuf");
+- count = (index < queue->next_buf_to_init)?
+- card->qdio.in_buf_pool.buf_count -
+- (queue->next_buf_to_init - index) :
+- card->qdio.in_buf_pool.buf_count -
+- (queue->next_buf_to_init + QDIO_MAX_BUFFERS_PER_Q - index);
+- /* only requeue at a certain threshold to avoid SIGAs */
+- if (count >= QETH_IN_BUF_REQUEUE_THRESHOLD(card)){
+- for (i = queue->next_buf_to_init;
+- i < queue->next_buf_to_init + count; ++i) {
+- if (qeth_init_input_buffer(card,
+- &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q])) {
+- break;
+- } else {
+- newcount++;
+- }
+- }
+-
+- if (newcount < count) {
+- /* we are in memory shortage so we switch back to
+- traditional skb allocation and drop packages */
+- if (!atomic_read(&card->force_alloc_skb) &&
+- net_ratelimit())
+- PRINT_WARN("Switch to alloc skb\n");
+- atomic_set(&card->force_alloc_skb, 3);
+- count = newcount;
+- } else {
+- if ((atomic_read(&card->force_alloc_skb) == 1) &&
+- net_ratelimit())
+- PRINT_WARN("Switch to sg\n");
+- atomic_add_unless(&card->force_alloc_skb, -1, 0);
+- }
+-
+- /*
+- * according to old code it should be avoided to requeue all
+- * 128 buffers in order to benefit from PCI avoidance.
+- * this function keeps at least one buffer (the buffer at
+- * 'index') un-requeued -> this buffer is the first buffer that
+- * will be requeued the next time
+- */
+- if (card->options.performance_stats) {
+- card->perf_stats.inbound_do_qdio_cnt++;
+- card->perf_stats.inbound_do_qdio_start_time =
+- qeth_get_micros();
+- }
+- rc = do_QDIO(CARD_DDEV(card),
+- QDIO_FLAG_SYNC_INPUT | QDIO_FLAG_UNDER_INTERRUPT,
+- 0, queue->next_buf_to_init, count, NULL);
+- if (card->options.performance_stats)
+- card->perf_stats.inbound_do_qdio_time +=
+- qeth_get_micros() -
+- card->perf_stats.inbound_do_qdio_start_time;
+- if (rc){
+- PRINT_WARN("qeth_queue_input_buffer's do_QDIO "
+- "return %i (device %s).\n",
+- rc, CARD_DDEV_ID(card));
+- QETH_DBF_TEXT(trace,2,"qinberr");
+- QETH_DBF_TEXT_(trace,2,"%s",CARD_BUS_ID(card));
+- }
+- queue->next_buf_to_init = (queue->next_buf_to_init + count) %
+- QDIO_MAX_BUFFERS_PER_Q;
+- }
+-}
+-
+-static inline void
+-qeth_put_buffer_pool_entry(struct qeth_card *card,
+- struct qeth_buffer_pool_entry *entry)
+-{
+- QETH_DBF_TEXT(trace, 6, "ptbfplen");
+- list_add_tail(&entry->list, &card->qdio.in_buf_pool.entry_list);
+-}
+-
+-static void
+-qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status,
+- unsigned int qdio_err, unsigned int siga_err,
+- unsigned int queue, int first_element, int count,
+- unsigned long card_ptr)
+-{
+- struct net_device *net_dev;
+- struct qeth_card *card;
+- struct qeth_qdio_buffer *buffer;
+- int index;
+- int i;
+-
+- QETH_DBF_TEXT(trace, 6, "qdinput");
+- card = (struct qeth_card *) card_ptr;
+- net_dev = card->dev;
+- if (card->options.performance_stats) {
+- card->perf_stats.inbound_cnt++;
+- card->perf_stats.inbound_start_time = qeth_get_micros();
+- }
+- if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
+- if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){
+- QETH_DBF_TEXT(trace, 1,"qdinchk");
+- QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card));
+- QETH_DBF_TEXT_(trace,1,"%04X%04X",first_element,count);
+- QETH_DBF_TEXT_(trace,1,"%04X%04X", queue, status);
+- qeth_schedule_recovery(card);
+- return;
+- }
+- }
+- for (i = first_element; i < (first_element + count); ++i) {
+- index = i % QDIO_MAX_BUFFERS_PER_Q;
+- buffer = &card->qdio.in_q->bufs[index];
+- if (!((status & QDIO_STATUS_LOOK_FOR_ERROR) &&
+- qeth_check_qdio_errors(buffer->buffer,
+- qdio_err, siga_err,"qinerr")))
+- qeth_process_inbound_buffer(card, buffer, index);
+- /* clear buffer and give back to hardware */
+- qeth_put_buffer_pool_entry(card, buffer->pool_entry);
+- qeth_queue_input_buffer(card, index);
+- }
+- if (card->options.performance_stats)
+- card->perf_stats.inbound_time += qeth_get_micros() -
+- card->perf_stats.inbound_start_time;
+-}
+-
+-static int
+-qeth_handle_send_error(struct qeth_card *card,
+- struct qeth_qdio_out_buffer *buffer,
+- unsigned int qdio_err, unsigned int siga_err)
+-{
+- int sbalf15 = buffer->buffer->element[15].flags & 0xff;
+- int cc = siga_err & 3;
+-
+- QETH_DBF_TEXT(trace, 6, "hdsnderr");
+- qeth_check_qdio_errors(buffer->buffer, qdio_err, siga_err, "qouterr");
+- switch (cc) {
+- case 0:
+- if (qdio_err){
+- QETH_DBF_TEXT(trace, 1,"lnkfail");
+- QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card));
+- QETH_DBF_TEXT_(trace,1,"%04x %02x",
+- (u16)qdio_err, (u8)sbalf15);
+- return QETH_SEND_ERROR_LINK_FAILURE;
+- }
+- return QETH_SEND_ERROR_NONE;
+- case 2:
+- if (siga_err & QDIO_SIGA_ERROR_B_BIT_SET) {
+- QETH_DBF_TEXT(trace, 1, "SIGAcc2B");
+- QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card));
+- return QETH_SEND_ERROR_KICK_IT;
+- }
+- if ((sbalf15 >= 15) && (sbalf15 <= 31))
+- return QETH_SEND_ERROR_RETRY;
+- return QETH_SEND_ERROR_LINK_FAILURE;
+- /* look at qdio_error and sbalf 15 */
+- case 1:
+- QETH_DBF_TEXT(trace, 1, "SIGAcc1");
+- QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card));
+- return QETH_SEND_ERROR_LINK_FAILURE;
+- case 3:
+- default:
+- QETH_DBF_TEXT(trace, 1, "SIGAcc3");
+- QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card));
+- return QETH_SEND_ERROR_KICK_IT;
+- }
+-}
+-
+-void
+-qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
+- int index, int count)
+-{
+- struct qeth_qdio_out_buffer *buf;
+- int rc;
+- int i;
+- unsigned int qdio_flags;
+-
+- QETH_DBF_TEXT(trace, 6, "flushbuf");
+-
+- for (i = index; i < index + count; ++i) {
+- buf = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
+- buf->buffer->element[buf->next_element_to_fill - 1].flags |=
+- SBAL_FLAGS_LAST_ENTRY;
+-
+- if (queue->card->info.type == QETH_CARD_TYPE_IQD)
+- continue;
+-
+- if (!queue->do_pack){
+- if ((atomic_read(&queue->used_buffers) >=
+- (QETH_HIGH_WATERMARK_PACK -
+- QETH_WATERMARK_PACK_FUZZ)) &&
+- !atomic_read(&queue->set_pci_flags_count)){
+- /* it's likely that we'll go to packing
+- * mode soon */
+- atomic_inc(&queue->set_pci_flags_count);
+- buf->buffer->element[0].flags |= 0x40;
+- }
+- } else {
+- if (!atomic_read(&queue->set_pci_flags_count)){
+- /*
+- * there's no outstanding PCI any more, so we
+- * have to request a PCI to be sure that the PCI
+- * will wake at some time in the future then we
+- * can flush packed buffers that might still be
+- * hanging around, which can happen if no
+- * further send was requested by the stack
+- */
+- atomic_inc(&queue->set_pci_flags_count);
+- buf->buffer->element[0].flags |= 0x40;
+- }
+- }
+- }
+-
+- queue->card->dev->trans_start = jiffies;
+- if (queue->card->options.performance_stats) {
+- queue->card->perf_stats.outbound_do_qdio_cnt++;
+- queue->card->perf_stats.outbound_do_qdio_start_time =
+- qeth_get_micros();
+- }
+- qdio_flags = QDIO_FLAG_SYNC_OUTPUT;
+- if (under_int)
+- qdio_flags |= QDIO_FLAG_UNDER_INTERRUPT;
+- if (atomic_read(&queue->set_pci_flags_count))
+- qdio_flags |= QDIO_FLAG_PCI_OUT;
+- rc = do_QDIO(CARD_DDEV(queue->card), qdio_flags,
+- queue->queue_no, index, count, NULL);
+- if (queue->card->options.performance_stats)
+- queue->card->perf_stats.outbound_do_qdio_time +=
+- qeth_get_micros() -
+- queue->card->perf_stats.outbound_do_qdio_start_time;
+- if (rc){
+- QETH_DBF_TEXT(trace, 2, "flushbuf");
+- QETH_DBF_TEXT_(trace, 2, " err%d", rc);
+- QETH_DBF_TEXT_(trace, 2, "%s", CARD_DDEV_ID(queue->card));
+- queue->card->stats.tx_errors += count;
+- /* this must not happen under normal circumstances. if it
+- * happens something is really wrong -> recover */
+- qeth_schedule_recovery(queue->card);
+- return;
+- }
+- atomic_add(count, &queue->used_buffers);
+- if (queue->card->options.performance_stats)
+- queue->card->perf_stats.bufs_sent += count;
+-}
+-
+-/*
+- * Switched to packing state if the number of used buffers on a queue
+- * reaches a certain limit.
+- */
+-static void
+-qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue)
+-{
+- if (!queue->do_pack) {
+- if (atomic_read(&queue->used_buffers)
+- >= QETH_HIGH_WATERMARK_PACK){
+- /* switch non-PACKING -> PACKING */
+- QETH_DBF_TEXT(trace, 6, "np->pack");
+- if (queue->card->options.performance_stats)
+- queue->card->perf_stats.sc_dp_p++;
+- queue->do_pack = 1;
+- }
+- }
+-}
+-
+-/*
+- * Switches from packing to non-packing mode. If there is a packing
+- * buffer on the queue this buffer will be prepared to be flushed.
+- * In that case 1 is returned to inform the caller. If no buffer
+- * has to be flushed, zero is returned.
+- */
+-static int
+-qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue)
+-{
+- struct qeth_qdio_out_buffer *buffer;
+- int flush_count = 0;
+-
+- if (queue->do_pack) {
+- if (atomic_read(&queue->used_buffers)
+- <= QETH_LOW_WATERMARK_PACK) {
+- /* switch PACKING -> non-PACKING */
+- QETH_DBF_TEXT(trace, 6, "pack->np");
+- if (queue->card->options.performance_stats)
+- queue->card->perf_stats.sc_p_dp++;
+- queue->do_pack = 0;
+- /* flush packing buffers */
+- buffer = &queue->bufs[queue->next_buf_to_fill];
+- if ((atomic_read(&buffer->state) ==
+- QETH_QDIO_BUF_EMPTY) &&
+- (buffer->next_element_to_fill > 0)) {
+- atomic_set(&buffer->state,QETH_QDIO_BUF_PRIMED);
+- flush_count++;
+- queue->next_buf_to_fill =
+- (queue->next_buf_to_fill + 1) %
+- QDIO_MAX_BUFFERS_PER_Q;
+- }
+- }
+- }
+- return flush_count;
+-}
+-
+-/*
+- * Called to flush a packing buffer if no more pci flags are on the queue.
+- * Checks if there is a packing buffer and prepares it to be flushed.
+- * In that case returns 1, otherwise zero.
+- */
+-static int
+-qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue)
+-{
+- struct qeth_qdio_out_buffer *buffer;
+-
+- buffer = &queue->bufs[queue->next_buf_to_fill];
+- if((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) &&
+- (buffer->next_element_to_fill > 0)){
+- /* it's a packing buffer */
+- atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
+- queue->next_buf_to_fill =
+- (queue->next_buf_to_fill + 1) % QDIO_MAX_BUFFERS_PER_Q;
+- return 1;
+- }
+- return 0;
+-}
+-
+-static void
+-qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
+-{
+- int index;
+- int flush_cnt = 0;
+- int q_was_packing = 0;
+-
+- /*
+- * check if weed have to switch to non-packing mode or if
+- * we have to get a pci flag out on the queue
+- */
+- if ((atomic_read(&queue->used_buffers) <= QETH_LOW_WATERMARK_PACK) ||
+- !atomic_read(&queue->set_pci_flags_count)){
+- if (atomic_xchg(&queue->state, QETH_OUT_Q_LOCKED_FLUSH) ==
+- QETH_OUT_Q_UNLOCKED) {
+- /*
+- * If we get in here, there was no action in
+- * do_send_packet. So, we check if there is a
+- * packing buffer to be flushed here.
+- */
+- netif_stop_queue(queue->card->dev);
+- index = queue->next_buf_to_fill;
+- q_was_packing = queue->do_pack;
+- flush_cnt += qeth_switch_to_nonpacking_if_needed(queue);
+- if (!flush_cnt &&
+- !atomic_read(&queue->set_pci_flags_count))
+- flush_cnt +=
+- qeth_flush_buffers_on_no_pci(queue);
+- if (queue->card->options.performance_stats &&
+- q_was_packing)
+- queue->card->perf_stats.bufs_sent_pack +=
+- flush_cnt;
+- if (flush_cnt)
+- qeth_flush_buffers(queue, 1, index, flush_cnt);
+- atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
+- }
+- }
+-}
+-
+-static void
+-qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status,
+- unsigned int qdio_error, unsigned int siga_error,
+- unsigned int __queue, int first_element, int count,
+- unsigned long card_ptr)
+-{
+- struct qeth_card *card = (struct qeth_card *) card_ptr;
+- struct qeth_qdio_out_q *queue = card->qdio.out_qs[__queue];
+- struct qeth_qdio_out_buffer *buffer;
+- int i;
+-
+- QETH_DBF_TEXT(trace, 6, "qdouhdl");
+- if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
+- if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){
+- QETH_DBF_TEXT(trace, 2, "achkcond");
+- QETH_DBF_TEXT_(trace, 2, "%s", CARD_BUS_ID(card));
+- QETH_DBF_TEXT_(trace, 2, "%08x", status);
+- netif_stop_queue(card->dev);
+- qeth_schedule_recovery(card);
+- return;
+- }
+- }
+- if (card->options.performance_stats) {
+- card->perf_stats.outbound_handler_cnt++;
+- card->perf_stats.outbound_handler_start_time =
+- qeth_get_micros();
+- }
+- for(i = first_element; i < (first_element + count); ++i){
+- buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
+- /*we only handle the KICK_IT error by doing a recovery */
+- if (qeth_handle_send_error(card, buffer,
+- qdio_error, siga_error)
+- == QETH_SEND_ERROR_KICK_IT){
+- netif_stop_queue(card->dev);
+- qeth_schedule_recovery(card);
+- return;
+- }
+- qeth_clear_output_buffer(queue, buffer);
+- }
+- atomic_sub(count, &queue->used_buffers);
+- /* check if we need to do something on this outbound queue */
+- if (card->info.type != QETH_CARD_TYPE_IQD)
+- qeth_check_outbound_queue(queue);
+-
+- netif_wake_queue(queue->card->dev);
+- if (card->options.performance_stats)
+- card->perf_stats.outbound_handler_time += qeth_get_micros() -
+- card->perf_stats.outbound_handler_start_time;
+-}
+-
+-static void
+-qeth_create_qib_param_field(struct qeth_card *card, char *param_field)
+-{
+-
+- param_field[0] = _ascebc['P'];
+- param_field[1] = _ascebc['C'];
+- param_field[2] = _ascebc['I'];
+- param_field[3] = _ascebc['T'];
+- *((unsigned int *) (¶m_field[4])) = QETH_PCI_THRESHOLD_A(card);
+- *((unsigned int *) (¶m_field[8])) = QETH_PCI_THRESHOLD_B(card);
+- *((unsigned int *) (¶m_field[12])) = QETH_PCI_TIMER_VALUE(card);
+-}
+-
+-static void
+-qeth_create_qib_param_field_blkt(struct qeth_card *card, char *param_field)
+-{
+- param_field[16] = _ascebc['B'];
+- param_field[17] = _ascebc['L'];
+- param_field[18] = _ascebc['K'];
+- param_field[19] = _ascebc['T'];
+- *((unsigned int *) (¶m_field[20])) = card->info.blkt.time_total;
+- *((unsigned int *) (¶m_field[24])) = card->info.blkt.inter_packet;
+- *((unsigned int *) (¶m_field[28])) = card->info.blkt.inter_packet_jumbo;
+-}
+-
+-static void
+-qeth_initialize_working_pool_list(struct qeth_card *card)
+-{
+- struct qeth_buffer_pool_entry *entry;
+-
+- QETH_DBF_TEXT(trace,5,"inwrklst");
+-
+- list_for_each_entry(entry,
+- &card->qdio.init_pool.entry_list, init_list) {
+- qeth_put_buffer_pool_entry(card,entry);
+- }
+-}
+-
+-static void
+-qeth_clear_working_pool_list(struct qeth_card *card)
+-{
+- struct qeth_buffer_pool_entry *pool_entry, *tmp;
+-
+- QETH_DBF_TEXT(trace,5,"clwrklst");
+- list_for_each_entry_safe(pool_entry, tmp,
+- &card->qdio.in_buf_pool.entry_list, list){
+- list_del(&pool_entry->list);
+- }
+-}
+-
+-static void
+-qeth_free_buffer_pool(struct qeth_card *card)
+-{
+- struct qeth_buffer_pool_entry *pool_entry, *tmp;
+- int i=0;
+- QETH_DBF_TEXT(trace,5,"freepool");
+- list_for_each_entry_safe(pool_entry, tmp,
+- &card->qdio.init_pool.entry_list, init_list){
+- for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i)
+- free_page((unsigned long)pool_entry->elements[i]);
+- list_del(&pool_entry->init_list);
+- kfree(pool_entry);
+- }
+-}
+-
+-static int
+-qeth_alloc_buffer_pool(struct qeth_card *card)
+-{
+- struct qeth_buffer_pool_entry *pool_entry;
+- void *ptr;
+- int i, j;
+-
+- QETH_DBF_TEXT(trace,5,"alocpool");
+- for (i = 0; i < card->qdio.init_pool.buf_count; ++i){
+- pool_entry = kmalloc(sizeof(*pool_entry), GFP_KERNEL);
+- if (!pool_entry){
+- qeth_free_buffer_pool(card);
+- return -ENOMEM;
+- }
+- for(j = 0; j < QETH_MAX_BUFFER_ELEMENTS(card); ++j){
+- ptr = (void *) __get_free_page(GFP_KERNEL|GFP_DMA);
+- if (!ptr) {
+- while (j > 0)
+- free_page((unsigned long)
+- pool_entry->elements[--j]);
+- kfree(pool_entry);
+- qeth_free_buffer_pool(card);
+- return -ENOMEM;
+- }
+- pool_entry->elements[j] = ptr;
+- }
+- list_add(&pool_entry->init_list,
+- &card->qdio.init_pool.entry_list);
+- }
+- return 0;
+-}
+-
+-int
+-qeth_realloc_buffer_pool(struct qeth_card *card, int bufcnt)
+-{
+- QETH_DBF_TEXT(trace, 2, "realcbp");
+-
+- if ((card->state != CARD_STATE_DOWN) &&
+- (card->state != CARD_STATE_RECOVER))
+- return -EPERM;
+-
+- /* TODO: steel/add buffers from/to a running card's buffer pool (?) */
+- qeth_clear_working_pool_list(card);
+- qeth_free_buffer_pool(card);
+- card->qdio.in_buf_pool.buf_count = bufcnt;
+- card->qdio.init_pool.buf_count = bufcnt;
+- return qeth_alloc_buffer_pool(card);
+-}
+-
+-static int
+-qeth_alloc_qdio_buffers(struct qeth_card *card)
+-{
+- int i, j;
+-
+- QETH_DBF_TEXT(setup, 2, "allcqdbf");
+-
+- if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED,
+- QETH_QDIO_ALLOCATED) != QETH_QDIO_UNINITIALIZED)
+- return 0;
+-
+- card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q),
+- GFP_KERNEL|GFP_DMA);
+- if (!card->qdio.in_q)
+- goto out_nomem;
+- QETH_DBF_TEXT(setup, 2, "inq");
+- QETH_DBF_HEX(setup, 2, &card->qdio.in_q, sizeof(void *));
+- memset(card->qdio.in_q, 0, sizeof(struct qeth_qdio_q));
+- /* give inbound qeth_qdio_buffers their qdio_buffers */
+- for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i)
+- card->qdio.in_q->bufs[i].buffer =
+- &card->qdio.in_q->qdio_bufs[i];
+- /* inbound buffer pool */
+- if (qeth_alloc_buffer_pool(card))
+- goto out_freeinq;
+- /* outbound */
+- card->qdio.out_qs =
+- kmalloc(card->qdio.no_out_queues *
+- sizeof(struct qeth_qdio_out_q *), GFP_KERNEL);
+- if (!card->qdio.out_qs)
+- goto out_freepool;
+- for (i = 0; i < card->qdio.no_out_queues; ++i) {
+- card->qdio.out_qs[i] = kmalloc(sizeof(struct qeth_qdio_out_q),
+- GFP_KERNEL|GFP_DMA);
+- if (!card->qdio.out_qs[i])
+- goto out_freeoutq;
+- QETH_DBF_TEXT_(setup, 2, "outq %i", i);
+- QETH_DBF_HEX(setup, 2, &card->qdio.out_qs[i], sizeof(void *));
+- memset(card->qdio.out_qs[i], 0, sizeof(struct qeth_qdio_out_q));
+- card->qdio.out_qs[i]->queue_no = i;
+- /* give outbound qeth_qdio_buffers their qdio_buffers */
+- for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j){
+- card->qdio.out_qs[i]->bufs[j].buffer =
+- &card->qdio.out_qs[i]->qdio_bufs[j];
+- skb_queue_head_init(&card->qdio.out_qs[i]->bufs[j].
+- skb_list);
+- lockdep_set_class(
+- &card->qdio.out_qs[i]->bufs[j].skb_list.lock,
+- &qdio_out_skb_queue_key);
+- INIT_LIST_HEAD(&card->qdio.out_qs[i]->bufs[j].ctx_list);
+- }
+- }
+- return 0;
+-
+-out_freeoutq:
+- while (i > 0)
+- kfree(card->qdio.out_qs[--i]);
+- kfree(card->qdio.out_qs);
+- card->qdio.out_qs = NULL;
+-out_freepool:
+- qeth_free_buffer_pool(card);
+-out_freeinq:
+- kfree(card->qdio.in_q);
+- card->qdio.in_q = NULL;
+-out_nomem:
+- atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED);
+- return -ENOMEM;
+-}
+-
+-static void
+-qeth_free_qdio_buffers(struct qeth_card *card)
+-{
+- int i, j;
+-
+- QETH_DBF_TEXT(trace, 2, "freeqdbf");
+- if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) ==
+- QETH_QDIO_UNINITIALIZED)
+- return;
+- kfree(card->qdio.in_q);
+- card->qdio.in_q = NULL;
+- /* inbound buffer pool */
+- qeth_free_buffer_pool(card);
+- /* free outbound qdio_qs */
+- if (card->qdio.out_qs) {
+- for (i = 0; i < card->qdio.no_out_queues; ++i) {
+- for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
+- qeth_clear_output_buffer(card->qdio.out_qs[i],
+- &card->qdio.out_qs[i]->bufs[j]);
+- kfree(card->qdio.out_qs[i]);
+- }
+- kfree(card->qdio.out_qs);
+- card->qdio.out_qs = NULL;
+- }
+-}
+-
+-static void
+-qeth_clear_qdio_buffers(struct qeth_card *card)
+-{
+- int i, j;
+-
+- QETH_DBF_TEXT(trace, 2, "clearqdbf");
+- /* clear outbound buffers to free skbs */
+- for (i = 0; i < card->qdio.no_out_queues; ++i)
+- if (card->qdio.out_qs && card->qdio.out_qs[i]) {
+- for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
+- qeth_clear_output_buffer(card->qdio.out_qs[i],
+- &card->qdio.out_qs[i]->bufs[j]);
+- }
+-}
+-
+-static void
+-qeth_init_qdio_info(struct qeth_card *card)
+-{
+- QETH_DBF_TEXT(setup, 4, "intqdinf");
+- atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED);
+- /* inbound */
+- card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT;
+- card->qdio.init_pool.buf_count = QETH_IN_BUF_COUNT_DEFAULT;
+- card->qdio.in_buf_pool.buf_count = card->qdio.init_pool.buf_count;
+- INIT_LIST_HEAD(&card->qdio.in_buf_pool.entry_list);
+- INIT_LIST_HEAD(&card->qdio.init_pool.entry_list);
+-}
+-
+-static int
+-qeth_init_qdio_queues(struct qeth_card *card)
+-{
+- int i, j;
+- int rc;
+-
+- QETH_DBF_TEXT(setup, 2, "initqdqs");
+-
+- /* inbound queue */
+- memset(card->qdio.in_q->qdio_bufs, 0,
+- QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
+- qeth_initialize_working_pool_list(card);
+- /*give only as many buffers to hardware as we have buffer pool entries*/
+- for (i = 0; i < card->qdio.in_buf_pool.buf_count - 1; ++i)
+- qeth_init_input_buffer(card, &card->qdio.in_q->bufs[i]);
+- card->qdio.in_q->next_buf_to_init = card->qdio.in_buf_pool.buf_count - 1;
+- rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0, 0,
+- card->qdio.in_buf_pool.buf_count - 1, NULL);
+- if (rc) {
+- QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+- return rc;
+- }
+- rc = qdio_synchronize(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0);
+- if (rc) {
+- QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+- return rc;
+- }
+- /* outbound queue */
+- for (i = 0; i < card->qdio.no_out_queues; ++i){
+- memset(card->qdio.out_qs[i]->qdio_bufs, 0,
+- QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
+- for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j){
+- qeth_clear_output_buffer(card->qdio.out_qs[i],
+- &card->qdio.out_qs[i]->bufs[j]);
+- }
+- card->qdio.out_qs[i]->card = card;
+- card->qdio.out_qs[i]->next_buf_to_fill = 0;
+- card->qdio.out_qs[i]->do_pack = 0;
+- atomic_set(&card->qdio.out_qs[i]->used_buffers,0);
+- atomic_set(&card->qdio.out_qs[i]->set_pci_flags_count, 0);
+- atomic_set(&card->qdio.out_qs[i]->state,
+- QETH_OUT_Q_UNLOCKED);
+- }
+- return 0;
+-}
+-
+-static int
+-qeth_qdio_establish(struct qeth_card *card)
+-{
+- struct qdio_initialize init_data;
+- char *qib_param_field;
+- struct qdio_buffer **in_sbal_ptrs;
+- struct qdio_buffer **out_sbal_ptrs;
+- int i, j, k;
+- int rc = 0;
+-
+- QETH_DBF_TEXT(setup, 2, "qdioest");
+-
+- qib_param_field = kzalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(char),
+- GFP_KERNEL);
+- if (!qib_param_field)
+- return -ENOMEM;
+-
+- qeth_create_qib_param_field(card, qib_param_field);
+- qeth_create_qib_param_field_blkt(card, qib_param_field);
+-
+- in_sbal_ptrs = kmalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(void *),
+- GFP_KERNEL);
+- if (!in_sbal_ptrs) {
+- kfree(qib_param_field);
+- return -ENOMEM;
+- }
+- for(i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i)
+- in_sbal_ptrs[i] = (struct qdio_buffer *)
+- virt_to_phys(card->qdio.in_q->bufs[i].buffer);
+-
+- out_sbal_ptrs =
+- kmalloc(card->qdio.no_out_queues * QDIO_MAX_BUFFERS_PER_Q *
+- sizeof(void *), GFP_KERNEL);
+- if (!out_sbal_ptrs) {
+- kfree(in_sbal_ptrs);
+- kfree(qib_param_field);
+- return -ENOMEM;
+- }
+- for(i = 0, k = 0; i < card->qdio.no_out_queues; ++i)
+- for(j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j, ++k){
+- out_sbal_ptrs[k] = (struct qdio_buffer *)
+- virt_to_phys(card->qdio.out_qs[i]->
+- bufs[j].buffer);
+- }
+-
+- memset(&init_data, 0, sizeof(struct qdio_initialize));
+- init_data.cdev = CARD_DDEV(card);
+- init_data.q_format = qeth_get_qdio_q_format(card);
+- init_data.qib_param_field_format = 0;
+- init_data.qib_param_field = qib_param_field;
+- init_data.min_input_threshold = QETH_MIN_INPUT_THRESHOLD;
+- init_data.max_input_threshold = QETH_MAX_INPUT_THRESHOLD;
+- init_data.min_output_threshold = QETH_MIN_OUTPUT_THRESHOLD;
+- init_data.max_output_threshold = QETH_MAX_OUTPUT_THRESHOLD;
+- init_data.no_input_qs = 1;
+- init_data.no_output_qs = card->qdio.no_out_queues;
+- init_data.input_handler = (qdio_handler_t *)
+- qeth_qdio_input_handler;
+- init_data.output_handler = (qdio_handler_t *)
+- qeth_qdio_output_handler;
+- init_data.int_parm = (unsigned long) card;
+- init_data.flags = QDIO_INBOUND_0COPY_SBALS |
+- QDIO_OUTBOUND_0COPY_SBALS |
+- QDIO_USE_OUTBOUND_PCIS;
+- init_data.input_sbal_addr_array = (void **) in_sbal_ptrs;
+- init_data.output_sbal_addr_array = (void **) out_sbal_ptrs;
+-
+- if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED,
+- QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED)
+- if ((rc = qdio_initialize(&init_data)))
+- atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED);
+-
+- kfree(out_sbal_ptrs);
+- kfree(in_sbal_ptrs);
+- kfree(qib_param_field);
+- return rc;
+-}
+-
+-static int
+-qeth_qdio_activate(struct qeth_card *card)
+-{
+- QETH_DBF_TEXT(setup,3,"qdioact");
+- return qdio_activate(CARD_DDEV(card), 0);
+-}
+-
+-static int
+-qeth_clear_channel(struct qeth_channel *channel)
+-{
+- unsigned long flags;
+- struct qeth_card *card;
+- int rc;
+-
+- QETH_DBF_TEXT(trace,3,"clearch");
+- card = CARD_FROM_CDEV(channel->ccwdev);
+- spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+- rc = ccw_device_clear(channel->ccwdev, QETH_CLEAR_CHANNEL_PARM);
+- spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+-
+- if (rc)
+- return rc;
+- rc = wait_event_interruptible_timeout(card->wait_q,
+- channel->state==CH_STATE_STOPPED, QETH_TIMEOUT);
+- if (rc == -ERESTARTSYS)
+- return rc;
+- if (channel->state != CH_STATE_STOPPED)
+- return -ETIME;
+- channel->state = CH_STATE_DOWN;
+- return 0;
+-}
+-
+-static int
+-qeth_halt_channel(struct qeth_channel *channel)
+-{
+- unsigned long flags;
+- struct qeth_card *card;
+- int rc;
+-
+- QETH_DBF_TEXT(trace,3,"haltch");
+- card = CARD_FROM_CDEV(channel->ccwdev);
+- spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+- rc = ccw_device_halt(channel->ccwdev, QETH_HALT_CHANNEL_PARM);
+- spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+-
+- if (rc)
+- return rc;
+- rc = wait_event_interruptible_timeout(card->wait_q,
+- channel->state==CH_STATE_HALTED, QETH_TIMEOUT);
+- if (rc == -ERESTARTSYS)
+- return rc;
+- if (channel->state != CH_STATE_HALTED)
+- return -ETIME;
+- return 0;
+-}
+-
+-static int
+-qeth_halt_channels(struct qeth_card *card)
+-{
+- int rc1 = 0, rc2=0, rc3 = 0;
+-
+- QETH_DBF_TEXT(trace,3,"haltchs");
+- rc1 = qeth_halt_channel(&card->read);
+- rc2 = qeth_halt_channel(&card->write);
+- rc3 = qeth_halt_channel(&card->data);
+- if (rc1)
+- return rc1;
+- if (rc2)
+- return rc2;
+- return rc3;
+-}
+-static int
+-qeth_clear_channels(struct qeth_card *card)
+-{
+- int rc1 = 0, rc2=0, rc3 = 0;
+-
+- QETH_DBF_TEXT(trace,3,"clearchs");
+- rc1 = qeth_clear_channel(&card->read);
+- rc2 = qeth_clear_channel(&card->write);
+- rc3 = qeth_clear_channel(&card->data);
+- if (rc1)
+- return rc1;
+- if (rc2)
+- return rc2;
+- return rc3;
+-}
+-
+-static int
+-qeth_clear_halt_card(struct qeth_card *card, int halt)
+-{
+- int rc = 0;
+-
+- QETH_DBF_TEXT(trace,3,"clhacrd");
+- QETH_DBF_HEX(trace, 3, &card, sizeof(void *));
+-
+- if (halt)
+- rc = qeth_halt_channels(card);
+- if (rc)
+- return rc;
+- return qeth_clear_channels(card);
+-}
+-
+-static int
+-qeth_qdio_clear_card(struct qeth_card *card, int use_halt)
+-{
+- int rc = 0;
+-
+- QETH_DBF_TEXT(trace,3,"qdioclr");
+- switch (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ESTABLISHED,
+- QETH_QDIO_CLEANING)) {
+- case QETH_QDIO_ESTABLISHED:
+- if ((rc = qdio_cleanup(CARD_DDEV(card),
+- (card->info.type == QETH_CARD_TYPE_IQD) ?
+- QDIO_FLAG_CLEANUP_USING_HALT :
+- QDIO_FLAG_CLEANUP_USING_CLEAR)))
+- QETH_DBF_TEXT_(trace, 3, "1err%d", rc);
+- atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED);
+- break;
+- case QETH_QDIO_CLEANING:
+- return rc;
+- default:
+- break;
+- }
+- if ((rc = qeth_clear_halt_card(card, use_halt)))
+- QETH_DBF_TEXT_(trace, 3, "2err%d", rc);
+- card->state = CARD_STATE_DOWN;
+- return rc;
+-}
+-
+-static int
+-qeth_dm_act(struct qeth_card *card)
+-{
+- int rc;
+- struct qeth_cmd_buffer *iob;
+-
+- QETH_DBF_TEXT(setup,2,"dmact");
+-
+- iob = qeth_wait_for_buffer(&card->write);
+- memcpy(iob->data, DM_ACT, DM_ACT_SIZE);
+-
+- memcpy(QETH_DM_ACT_DEST_ADDR(iob->data),
+- &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH);
+- memcpy(QETH_DM_ACT_CONNECTION_TOKEN(iob->data),
+- &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+- rc = qeth_send_control_data(card, DM_ACT_SIZE, iob, NULL, NULL);
+- return rc;
+-}
+-
+-static int
+-qeth_mpc_initialize(struct qeth_card *card)
+-{
+- int rc;
+-
+- QETH_DBF_TEXT(setup,2,"mpcinit");
+-
+- if ((rc = qeth_issue_next_read(card))){
+- QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+- return rc;
+- }
+- if ((rc = qeth_cm_enable(card))){
+- QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+- goto out_qdio;
+- }
+- if ((rc = qeth_cm_setup(card))){
+- QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+- goto out_qdio;
+- }
+- if ((rc = qeth_ulp_enable(card))){
+- QETH_DBF_TEXT_(setup, 2, "4err%d", rc);
+- goto out_qdio;
+- }
+- if ((rc = qeth_ulp_setup(card))){
+- QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
+- goto out_qdio;
+- }
+- if ((rc = qeth_alloc_qdio_buffers(card))){
+- QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
+- goto out_qdio;
+- }
+- if ((rc = qeth_qdio_establish(card))){
+- QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
+- qeth_free_qdio_buffers(card);
+- goto out_qdio;
+- }
+- if ((rc = qeth_qdio_activate(card))){
+- QETH_DBF_TEXT_(setup, 2, "7err%d", rc);
+- goto out_qdio;
+- }
+- if ((rc = qeth_dm_act(card))){
+- QETH_DBF_TEXT_(setup, 2, "8err%d", rc);
+- goto out_qdio;
+- }
+-
+- return 0;
+-out_qdio:
+- qeth_qdio_clear_card(card, card->info.type!=QETH_CARD_TYPE_IQD);
+- return rc;
+-}
+-
+-static struct net_device *
+-qeth_get_netdevice(enum qeth_card_types type, enum qeth_link_types linktype)
+-{
+- struct net_device *dev = NULL;
+-
+- switch (type) {
+- case QETH_CARD_TYPE_OSAE:
+- switch (linktype) {
+- case QETH_LINK_TYPE_LANE_TR:
+- case QETH_LINK_TYPE_HSTR:
+-#ifdef CONFIG_TR
+- dev = alloc_trdev(0);
+-#endif /* CONFIG_TR */
+- break;
+- default:
+- dev = alloc_etherdev(0);
+- }
+- break;
+- case QETH_CARD_TYPE_IQD:
+- dev = alloc_netdev(0, "hsi%d", ether_setup);
+- break;
+- case QETH_CARD_TYPE_OSN:
+- dev = alloc_netdev(0, "osn%d", ether_setup);
+- break;
+- default:
+- dev = alloc_etherdev(0);
+- }
+- return dev;
+-}
+-
+-/*hard_header fake function; used in case fake_ll is set */
+-static int
+-qeth_fake_header(struct sk_buff *skb, struct net_device *dev,
+- unsigned short type, const void *daddr, const void *saddr,
+- unsigned len)
+-{
+- if(dev->type == ARPHRD_IEEE802_TR){
+- struct trh_hdr *hdr;
+- hdr = (struct trh_hdr *)skb_push(skb, QETH_FAKE_LL_LEN_TR);
+- memcpy(hdr->saddr, dev->dev_addr, TR_ALEN);
+- memcpy(hdr->daddr, "FAKELL", TR_ALEN);
+- return QETH_FAKE_LL_LEN_TR;
+-
+- } else {
+- struct ethhdr *hdr;
+- hdr = (struct ethhdr *)skb_push(skb, QETH_FAKE_LL_LEN_ETH);
+- memcpy(hdr->h_source, dev->dev_addr, ETH_ALEN);
+- memcpy(hdr->h_dest, "FAKELL", ETH_ALEN);
+- if (type != ETH_P_802_3)
+- hdr->h_proto = htons(type);
+- else
+- hdr->h_proto = htons(len);
+- return QETH_FAKE_LL_LEN_ETH;
+-
+- }
+-}
+-
+-static const struct header_ops qeth_fake_ops = {
+- .create = qeth_fake_header,
+- .parse = qeth_hard_header_parse,
+-};
+-
+-static int
+-qeth_send_packet(struct qeth_card *, struct sk_buff *);
+-
+-static int
+-qeth_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+-{
+- int rc;
+- struct qeth_card *card;
+-
+- QETH_DBF_TEXT(trace, 6, "hrdstxmi");
+- card = (struct qeth_card *)dev->priv;
+- if (skb==NULL) {
+- card->stats.tx_dropped++;
+- card->stats.tx_errors++;
+- /* return OK; otherwise ksoftirqd goes to 100% */
+- return NETDEV_TX_OK;
+- }
+- if ((card->state != CARD_STATE_UP) || !card->lan_online) {
+- card->stats.tx_dropped++;
+- card->stats.tx_errors++;
+- card->stats.tx_carrier_errors++;
+- dev_kfree_skb_any(skb);
+- /* return OK; otherwise ksoftirqd goes to 100% */
+- return NETDEV_TX_OK;
+- }
+- if (card->options.performance_stats) {
+- card->perf_stats.outbound_cnt++;
+- card->perf_stats.outbound_start_time = qeth_get_micros();
+- }
+- netif_stop_queue(dev);
+- if ((rc = qeth_send_packet(card, skb))) {
+- if (rc == -EBUSY) {
+- return NETDEV_TX_BUSY;
+- } else {
+- card->stats.tx_errors++;
+- card->stats.tx_dropped++;
+- dev_kfree_skb_any(skb);
+- /*set to OK; otherwise ksoftirqd goes to 100% */
+- rc = NETDEV_TX_OK;
+- }
+- }
+- netif_wake_queue(dev);
+- if (card->options.performance_stats)
+- card->perf_stats.outbound_time += qeth_get_micros() -
+- card->perf_stats.outbound_start_time;
+- return rc;
+-}
+-
+-static int
+-qeth_verify_vlan_dev(struct net_device *dev, struct qeth_card *card)
+-{
+- int rc = 0;
+-#ifdef CONFIG_QETH_VLAN
+- struct vlan_group *vg;
+- int i;
+-
+- if (!(vg = card->vlangrp))
+- return rc;
+-
+- for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++){
+- if (vlan_group_get_device(vg, i) == dev){
+- rc = QETH_VLAN_CARD;
+- break;
+- }
+- }
+- if (rc && !(vlan_dev_info(dev)->real_dev->priv == (void *)card))
+- return 0;
+-
+-#endif
+- return rc;
+-}
+-
+-static int
+-qeth_verify_dev(struct net_device *dev)
+-{
+- struct qeth_card *card;
+- unsigned long flags;
+- int rc = 0;
+-
+- read_lock_irqsave(&qeth_card_list.rwlock, flags);
+- list_for_each_entry(card, &qeth_card_list.list, list){
+- if (card->dev == dev){
+- rc = QETH_REAL_CARD;
+- break;
+- }
+- rc = qeth_verify_vlan_dev(dev, card);
+- if (rc)
+- break;
+- }
+- read_unlock_irqrestore(&qeth_card_list.rwlock, flags);
+-
+- return rc;
+-}
+-
+-static struct qeth_card *
+-qeth_get_card_from_dev(struct net_device *dev)
+-{
+- struct qeth_card *card = NULL;
+- int rc;
+-
+- rc = qeth_verify_dev(dev);
+- if (rc == QETH_REAL_CARD)
+- card = (struct qeth_card *)dev->priv;
+- else if (rc == QETH_VLAN_CARD)
+- card = (struct qeth_card *)
+- vlan_dev_info(dev)->real_dev->priv;
+-
+- QETH_DBF_TEXT_(trace, 4, "%d", rc);
+- return card ;
+-}
+-
+-static void
+-qeth_tx_timeout(struct net_device *dev)
+-{
+- struct qeth_card *card;
+-
+- card = (struct qeth_card *) dev->priv;
+- card->stats.tx_errors++;
+- qeth_schedule_recovery(card);
+-}
+-
+-static int
+-qeth_open(struct net_device *dev)
+-{
+- struct qeth_card *card;
+-
+- QETH_DBF_TEXT(trace, 4, "qethopen");
+-
+- card = (struct qeth_card *) dev->priv;
+-
+- if (card->state != CARD_STATE_SOFTSETUP)
+- return -ENODEV;
+-
+- if ( (card->info.type != QETH_CARD_TYPE_OSN) &&
+- (card->options.layer2) &&
+- (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))) {
+- QETH_DBF_TEXT(trace,4,"nomacadr");
+- return -EPERM;
+- }
+- card->data.state = CH_STATE_UP;
+- card->state = CARD_STATE_UP;
+- card->dev->flags |= IFF_UP;
+- netif_start_queue(dev);
+-
+- if (!card->lan_online && netif_carrier_ok(dev))
+- netif_carrier_off(dev);
+- return 0;
+-}
+-
+-static int
+-qeth_stop(struct net_device *dev)
+-{
+- struct qeth_card *card;
+-
+- QETH_DBF_TEXT(trace, 4, "qethstop");
+-
+- card = (struct qeth_card *) dev->priv;
+-
+- netif_tx_disable(dev);
+- card->dev->flags &= ~IFF_UP;
+- if (card->state == CARD_STATE_UP)
+- card->state = CARD_STATE_SOFTSETUP;
+- return 0;
+-}
+-
+-static int
+-qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
+-{
+- int cast_type = RTN_UNSPEC;
+-
+- if (card->info.type == QETH_CARD_TYPE_OSN)
+- return cast_type;
+-
+- if (skb->dst && skb->dst->neighbour){
+- cast_type = skb->dst->neighbour->type;
+- if ((cast_type == RTN_BROADCAST) ||
+- (cast_type == RTN_MULTICAST) ||
+- (cast_type == RTN_ANYCAST))
+- return cast_type;
+- else
+- return RTN_UNSPEC;
+- }
+- /* try something else */
+- if (skb->protocol == ETH_P_IPV6)
+- return (skb_network_header(skb)[24] == 0xff) ?
+- RTN_MULTICAST : 0;
+- else if (skb->protocol == ETH_P_IP)
+- return ((skb_network_header(skb)[16] & 0xf0) == 0xe0) ?
+- RTN_MULTICAST : 0;
+- /* ... */
+- if (!memcmp(skb->data, skb->dev->broadcast, 6))
+- return RTN_BROADCAST;
+- else {
+- u16 hdr_mac;
+-
+- hdr_mac = *((u16 *)skb->data);
+- /* tr multicast? */
+- switch (card->info.link_type) {
+- case QETH_LINK_TYPE_HSTR:
+- case QETH_LINK_TYPE_LANE_TR:
+- if ((hdr_mac == QETH_TR_MAC_NC) ||
+- (hdr_mac == QETH_TR_MAC_C))
+- return RTN_MULTICAST;
+- break;
+- /* eth or so multicast? */
+- default:
+- if ((hdr_mac == QETH_ETH_MAC_V4) ||
+- (hdr_mac == QETH_ETH_MAC_V6))
+- return RTN_MULTICAST;
+- }
+- }
+- return cast_type;
+-}
+-
+-static int
+-qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb,
+- int ipv, int cast_type)
+-{
+- if (!ipv && (card->info.type == QETH_CARD_TYPE_OSAE))
+- return card->qdio.default_out_queue;
+- switch (card->qdio.no_out_queues) {
+- case 4:
+- if (cast_type && card->info.is_multicast_different)
+- return card->info.is_multicast_different &
+- (card->qdio.no_out_queues - 1);
+- if (card->qdio.do_prio_queueing && (ipv == 4)) {
+- const u8 tos = ip_hdr(skb)->tos;
+-
+- if (card->qdio.do_prio_queueing==QETH_PRIO_Q_ING_TOS){
+- if (tos & IP_TOS_NOTIMPORTANT)
+- return 3;
+- if (tos & IP_TOS_HIGHRELIABILITY)
+- return 2;
+- if (tos & IP_TOS_HIGHTHROUGHPUT)
+- return 1;
+- if (tos & IP_TOS_LOWDELAY)
+- return 0;
+- }
+- if (card->qdio.do_prio_queueing==QETH_PRIO_Q_ING_PREC)
+- return 3 - (tos >> 6);
+- } else if (card->qdio.do_prio_queueing && (ipv == 6)) {
+- /* TODO: IPv6!!! */
+- }
+- return card->qdio.default_out_queue;
+- case 1: /* fallthrough for single-out-queue 1920-device */
+- default:
+- return card->qdio.default_out_queue;
+- }
+-}
+-
+-static inline int
+-qeth_get_ip_version(struct sk_buff *skb)
+-{
+- switch (skb->protocol) {
+- case ETH_P_IPV6:
+- return 6;
+- case ETH_P_IP:
+- return 4;
+- default:
+- return 0;
+- }
+-}
+-
+-static struct qeth_hdr *
+-__qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, int ipv)
+-{
+-#ifdef CONFIG_QETH_VLAN
+- u16 *tag;
+- if (card->vlangrp && vlan_tx_tag_present(skb) &&
+- ((ipv == 6) || card->options.layer2) ) {
+- /*
+- * Move the mac addresses (6 bytes src, 6 bytes dest)
+- * to the beginning of the new header. We are using three
+- * memcpys instead of one memmove to save cycles.
+- */
+- skb_push(skb, VLAN_HLEN);
+- skb_copy_to_linear_data(skb, skb->data + 4, 4);
+- skb_copy_to_linear_data_offset(skb, 4, skb->data + 8, 4);
+- skb_copy_to_linear_data_offset(skb, 8, skb->data + 12, 4);
+- tag = (u16 *)(skb->data + 12);
+- /*
+- * first two bytes = ETH_P_8021Q (0x8100)
+- * second two bytes = VLANID
+- */
+- *tag = __constant_htons(ETH_P_8021Q);
+- *(tag + 1) = htons(vlan_tx_tag_get(skb));
+- }
+-#endif
+- return ((struct qeth_hdr *)
+- qeth_push_skb(card, skb, sizeof(struct qeth_hdr)));
+-}
+-
+-static void
+-__qeth_free_new_skb(struct sk_buff *orig_skb, struct sk_buff *new_skb)
+-{
+- if (orig_skb != new_skb)
+- dev_kfree_skb_any(new_skb);
+-}
+-
+-static struct sk_buff *
+-qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb,
+- struct qeth_hdr **hdr, int ipv)
+-{
+- struct sk_buff *new_skb, *new_skb2;
+-
+- QETH_DBF_TEXT(trace, 6, "prepskb");
+- new_skb = skb;
+- new_skb = qeth_pskb_unshare(skb, GFP_ATOMIC);
+- if (!new_skb)
+- return NULL;
+- new_skb2 = qeth_realloc_headroom(card, new_skb,
+- sizeof(struct qeth_hdr));
+- if (!new_skb2) {
+- __qeth_free_new_skb(skb, new_skb);
+- return NULL;
+- }
+- if (new_skb != skb)
+- __qeth_free_new_skb(new_skb2, new_skb);
+- new_skb = new_skb2;
+- *hdr = __qeth_prepare_skb(card, new_skb, ipv);
+- if (*hdr == NULL) {
+- __qeth_free_new_skb(skb, new_skb);
+- return NULL;
+- }
+- return new_skb;
+-}
+-
+-static inline u8
+-qeth_get_qeth_hdr_flags4(int cast_type)
+-{
+- if (cast_type == RTN_MULTICAST)
+- return QETH_CAST_MULTICAST;
+- if (cast_type == RTN_BROADCAST)
+- return QETH_CAST_BROADCAST;
+- return QETH_CAST_UNICAST;
+-}
+-
+-static inline u8
+-qeth_get_qeth_hdr_flags6(int cast_type)
+-{
+- u8 ct = QETH_HDR_PASSTHRU | QETH_HDR_IPV6;
+- if (cast_type == RTN_MULTICAST)
+- return ct | QETH_CAST_MULTICAST;
+- if (cast_type == RTN_ANYCAST)
+- return ct | QETH_CAST_ANYCAST;
+- if (cast_type == RTN_BROADCAST)
+- return ct | QETH_CAST_BROADCAST;
+- return ct | QETH_CAST_UNICAST;
+-}
+-
+-static void
+-qeth_layer2_get_packet_type(struct qeth_card *card, struct qeth_hdr *hdr,
+- struct sk_buff *skb)
+-{
+- __u16 hdr_mac;
+-
+- if (!memcmp(skb->data+QETH_HEADER_SIZE,
+- skb->dev->broadcast,6)) { /* broadcast? */
+- *(__u32 *)hdr->hdr.l2.flags |=
+- QETH_LAYER2_FLAG_BROADCAST << 8;
+- return;
+- }
+- hdr_mac=*((__u16*)skb->data);
+- /* tr multicast? */
+- switch (card->info.link_type) {
+- case QETH_LINK_TYPE_HSTR:
+- case QETH_LINK_TYPE_LANE_TR:
+- if ((hdr_mac == QETH_TR_MAC_NC) ||
+- (hdr_mac == QETH_TR_MAC_C) )
+- *(__u32 *)hdr->hdr.l2.flags |=
+- QETH_LAYER2_FLAG_MULTICAST << 8;
+- else
+- *(__u32 *)hdr->hdr.l2.flags |=
+- QETH_LAYER2_FLAG_UNICAST << 8;
+- break;
+- /* eth or so multicast? */
+- default:
+- if ( (hdr_mac==QETH_ETH_MAC_V4) ||
+- (hdr_mac==QETH_ETH_MAC_V6) )
+- *(__u32 *)hdr->hdr.l2.flags |=
+- QETH_LAYER2_FLAG_MULTICAST << 8;
+- else
+- *(__u32 *)hdr->hdr.l2.flags |=
+- QETH_LAYER2_FLAG_UNICAST << 8;
+- }
+-}
+-
+-static void
+-qeth_layer2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
+- struct sk_buff *skb, int cast_type)
+-{
+- memset(hdr, 0, sizeof(struct qeth_hdr));
+- hdr->hdr.l2.id = QETH_HEADER_TYPE_LAYER2;
+-
+- /* set byte 0 to "0x02" and byte 3 to casting flags */
+- if (cast_type==RTN_MULTICAST)
+- *(__u32 *)hdr->hdr.l2.flags |= QETH_LAYER2_FLAG_MULTICAST << 8;
+- else if (cast_type==RTN_BROADCAST)
+- *(__u32 *)hdr->hdr.l2.flags |= QETH_LAYER2_FLAG_BROADCAST << 8;
+- else
+- qeth_layer2_get_packet_type(card, hdr, skb);
+-
+- hdr->hdr.l2.pkt_length = skb->len-QETH_HEADER_SIZE;
+-#ifdef CONFIG_QETH_VLAN
+- /* VSWITCH relies on the VLAN
+- * information to be present in
+- * the QDIO header */
+- if ((card->vlangrp != NULL) &&
+- vlan_tx_tag_present(skb)) {
+- *(__u32 *)hdr->hdr.l2.flags |= QETH_LAYER2_FLAG_VLAN << 8;
+- hdr->hdr.l2.vlan_id = vlan_tx_tag_get(skb);
+- }
+-#endif
+-}
+-
+-void
+-qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
+- struct sk_buff *skb, int ipv, int cast_type)
+-{
+- QETH_DBF_TEXT(trace, 6, "fillhdr");
+-
+- memset(hdr, 0, sizeof(struct qeth_hdr));
+- if (card->options.layer2) {
+- qeth_layer2_fill_header(card, hdr, skb, cast_type);
+- return;
+- }
+- hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3;
+- hdr->hdr.l3.ext_flags = 0;
+-#ifdef CONFIG_QETH_VLAN
+- /*
+- * before we're going to overwrite this location with next hop ip.
+- * v6 uses passthrough, v4 sets the tag in the QDIO header.
+- */
+- if (card->vlangrp && vlan_tx_tag_present(skb)) {
+- hdr->hdr.l3.ext_flags = (ipv == 4) ?
+- QETH_HDR_EXT_VLAN_FRAME :
+- QETH_HDR_EXT_INCLUDE_VLAN_TAG;
+- hdr->hdr.l3.vlan_id = vlan_tx_tag_get(skb);
+- }
+-#endif /* CONFIG_QETH_VLAN */
+- hdr->hdr.l3.length = skb->len - sizeof(struct qeth_hdr);
+- if (ipv == 4) { /* IPv4 */
+- hdr->hdr.l3.flags = qeth_get_qeth_hdr_flags4(cast_type);
+- memset(hdr->hdr.l3.dest_addr, 0, 12);
+- if ((skb->dst) && (skb->dst->neighbour)) {
+- *((u32 *) (&hdr->hdr.l3.dest_addr[12])) =
+- *((u32 *) skb->dst->neighbour->primary_key);
+- } else {
+- /* fill in destination address used in ip header */
+- *((u32 *)(&hdr->hdr.l3.dest_addr[12])) =
+- ip_hdr(skb)->daddr;
+- }
+- } else if (ipv == 6) { /* IPv6 or passthru */
+- hdr->hdr.l3.flags = qeth_get_qeth_hdr_flags6(cast_type);
+- if ((skb->dst) && (skb->dst->neighbour)) {
+- memcpy(hdr->hdr.l3.dest_addr,
+- skb->dst->neighbour->primary_key, 16);
+- } else {
+- /* fill in destination address used in ip header */
+- memcpy(hdr->hdr.l3.dest_addr,
+- &ipv6_hdr(skb)->daddr, 16);
+- }
+- } else { /* passthrough */
+- if((skb->dev->type == ARPHRD_IEEE802_TR) &&
+- !memcmp(skb->data + sizeof(struct qeth_hdr) +
+- sizeof(__u16), skb->dev->broadcast, 6)) {
+- hdr->hdr.l3.flags = QETH_CAST_BROADCAST |
+- QETH_HDR_PASSTHRU;
+- } else if (!memcmp(skb->data + sizeof(struct qeth_hdr),
+- skb->dev->broadcast, 6)) { /* broadcast? */
+- hdr->hdr.l3.flags = QETH_CAST_BROADCAST |
+- QETH_HDR_PASSTHRU;
+- } else {
+- hdr->hdr.l3.flags = (cast_type == RTN_MULTICAST) ?
+- QETH_CAST_MULTICAST | QETH_HDR_PASSTHRU :
+- QETH_CAST_UNICAST | QETH_HDR_PASSTHRU;
+- }
+- }
+-}
+-
+-static void
+-__qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer,
+- int is_tso, int *next_element_to_fill)
+-{
+- int length = skb->len;
+- int length_here;
+- int element;
+- char *data;
+- int first_lap ;
+-
+- element = *next_element_to_fill;
+- data = skb->data;
+- first_lap = (is_tso == 0 ? 1 : 0);
+-
+- while (length > 0) {
+- /* length_here is the remaining amount of data in this page */
+- length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE);
+- if (length < length_here)
+- length_here = length;
+-
+- buffer->element[element].addr = data;
+- buffer->element[element].length = length_here;
+- length -= length_here;
+- if (!length) {
+- if (first_lap)
+- buffer->element[element].flags = 0;
+- else
+- buffer->element[element].flags =
+- SBAL_FLAGS_LAST_FRAG;
+- } else {
+- if (first_lap)
+- buffer->element[element].flags =
+- SBAL_FLAGS_FIRST_FRAG;
+- else
+- buffer->element[element].flags =
+- SBAL_FLAGS_MIDDLE_FRAG;
+- }
+- data += length_here;
+- element++;
+- first_lap = 0;
+- }
+- *next_element_to_fill = element;
+-}
+-
+-static int
+-qeth_fill_buffer(struct qeth_qdio_out_q *queue,
+- struct qeth_qdio_out_buffer *buf,
+- struct sk_buff *skb)
+-{
+- struct qdio_buffer *buffer;
+- struct qeth_hdr_tso *hdr;
+- int flush_cnt = 0, hdr_len, large_send = 0;
+-
+- QETH_DBF_TEXT(trace, 6, "qdfillbf");
+-
+- buffer = buf->buffer;
+- atomic_inc(&skb->users);
+- skb_queue_tail(&buf->skb_list, skb);
+-
+- hdr = (struct qeth_hdr_tso *) skb->data;
+- /*check first on TSO ....*/
+- if (hdr->hdr.hdr.l3.id == QETH_HEADER_TYPE_TSO) {
+- int element = buf->next_element_to_fill;
+-
+- hdr_len = sizeof(struct qeth_hdr_tso) + hdr->ext.dg_hdr_len;
+- /*fill first buffer entry only with header information */
+- buffer->element[element].addr = skb->data;
+- buffer->element[element].length = hdr_len;
+- buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG;
+- buf->next_element_to_fill++;
+- skb->data += hdr_len;
+- skb->len -= hdr_len;
+- large_send = 1;
+- }
+- if (skb_shinfo(skb)->nr_frags == 0)
+- __qeth_fill_buffer(skb, buffer, large_send,
+- (int *)&buf->next_element_to_fill);
+- else
+- __qeth_fill_buffer_frag(skb, buffer, large_send,
+- (int *)&buf->next_element_to_fill);
+-
+- if (!queue->do_pack) {
+- QETH_DBF_TEXT(trace, 6, "fillbfnp");
+- /* set state to PRIMED -> will be flushed */
+- atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
+- flush_cnt = 1;
+- } else {
+- QETH_DBF_TEXT(trace, 6, "fillbfpa");
+- if (queue->card->options.performance_stats)
+- queue->card->perf_stats.skbs_sent_pack++;
+- if (buf->next_element_to_fill >=
+- QETH_MAX_BUFFER_ELEMENTS(queue->card)) {
+- /*
+- * packed buffer if full -> set state PRIMED
+- * -> will be flushed
+- */
+- atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
+- flush_cnt = 1;
+- }
+- }
+- return flush_cnt;
+-}
+-
+-static int
+-qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue,
+- struct sk_buff *skb, struct qeth_hdr *hdr,
+- int elements_needed,
+- struct qeth_eddp_context *ctx)
+-{
+- struct qeth_qdio_out_buffer *buffer;
+- int buffers_needed = 0;
+- int flush_cnt = 0;
+- int index;
+-
+- QETH_DBF_TEXT(trace, 6, "dosndpfa");
+-
+- /* spin until we get the queue ... */
+- while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
+- QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
+- /* ... now we've got the queue */
+- index = queue->next_buf_to_fill;
+- buffer = &queue->bufs[queue->next_buf_to_fill];
+- /*
+- * check if buffer is empty to make sure that we do not 'overtake'
+- * ourselves and try to fill a buffer that is already primed
+- */
+- if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY)
+- goto out;
+- if (ctx == NULL)
+- queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) %
+- QDIO_MAX_BUFFERS_PER_Q;
+- else {
+- buffers_needed = qeth_eddp_check_buffers_for_context(queue,ctx);
+- if (buffers_needed < 0)
+- goto out;
+- queue->next_buf_to_fill =
+- (queue->next_buf_to_fill + buffers_needed) %
+- QDIO_MAX_BUFFERS_PER_Q;
+- }
+- atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
+- if (ctx == NULL) {
+- qeth_fill_buffer(queue, buffer, skb);
+- qeth_flush_buffers(queue, 0, index, 1);
+- } else {
+- flush_cnt = qeth_eddp_fill_buffer(queue, ctx, index);
+- WARN_ON(buffers_needed != flush_cnt);
+- qeth_flush_buffers(queue, 0, index, flush_cnt);
+- }
+- return 0;
+-out:
+- atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
+- return -EBUSY;
+-}
+-
+-static int
+-qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
+- struct sk_buff *skb, struct qeth_hdr *hdr,
+- int elements_needed, struct qeth_eddp_context *ctx)
+-{
+- struct qeth_qdio_out_buffer *buffer;
+- int start_index;
+- int flush_count = 0;
+- int do_pack = 0;
+- int tmp;
+- int rc = 0;
+-
+- QETH_DBF_TEXT(trace, 6, "dosndpkt");
+-
+- /* spin until we get the queue ... */
+- while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
+- QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
+- start_index = queue->next_buf_to_fill;
+- buffer = &queue->bufs[queue->next_buf_to_fill];
+- /*
+- * check if buffer is empty to make sure that we do not 'overtake'
+- * ourselves and try to fill a buffer that is already primed
+- */
+- if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) {
+- atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
+- return -EBUSY;
+- }
+- /* check if we need to switch packing state of this queue */
+- qeth_switch_to_packing_if_needed(queue);
+- if (queue->do_pack){
+- do_pack = 1;
+- if (ctx == NULL) {
+- /* does packet fit in current buffer? */
+- if((QETH_MAX_BUFFER_ELEMENTS(card) -
+- buffer->next_element_to_fill) < elements_needed){
+- /* ... no -> set state PRIMED */
+- atomic_set(&buffer->state,QETH_QDIO_BUF_PRIMED);
+- flush_count++;
+- queue->next_buf_to_fill =
+- (queue->next_buf_to_fill + 1) %
+- QDIO_MAX_BUFFERS_PER_Q;
+- buffer = &queue->bufs[queue->next_buf_to_fill];
+- /* we did a step forward, so check buffer state
+- * again */
+- if (atomic_read(&buffer->state) !=
+- QETH_QDIO_BUF_EMPTY){
+- qeth_flush_buffers(queue, 0, start_index, flush_count);
+- atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
+- return -EBUSY;
+- }
+- }
+- } else {
+- /* check if we have enough elements (including following
+- * free buffers) to handle eddp context */
+- if (qeth_eddp_check_buffers_for_context(queue,ctx) < 0){
+- if (net_ratelimit())
+- PRINT_WARN("eddp tx_dropped 1\n");
+- rc = -EBUSY;
+- goto out;
+- }
+- }
+- }
+- if (ctx == NULL)
+- tmp = qeth_fill_buffer(queue, buffer, skb);
+- else {
+- tmp = qeth_eddp_fill_buffer(queue,ctx,queue->next_buf_to_fill);
+- if (tmp < 0) {
+- printk("eddp tx_dropped 2\n");
+- rc = - EBUSY;
+- goto out;
+- }
+- }
+- queue->next_buf_to_fill = (queue->next_buf_to_fill + tmp) %
+- QDIO_MAX_BUFFERS_PER_Q;
+- flush_count += tmp;
+-out:
+- if (flush_count)
+- qeth_flush_buffers(queue, 0, start_index, flush_count);
+- else if (!atomic_read(&queue->set_pci_flags_count))
+- atomic_xchg(&queue->state, QETH_OUT_Q_LOCKED_FLUSH);
+- /*
+- * queue->state will go from LOCKED -> UNLOCKED or from
+- * LOCKED_FLUSH -> LOCKED if output_handler wanted to 'notify' us
+- * (switch packing state or flush buffer to get another pci flag out).
+- * In that case we will enter this loop
+- */
+- while (atomic_dec_return(&queue->state)){
+- flush_count = 0;
+- start_index = queue->next_buf_to_fill;
+- /* check if we can go back to non-packing state */
+- flush_count += qeth_switch_to_nonpacking_if_needed(queue);
+- /*
+- * check if we need to flush a packing buffer to get a pci
+- * flag out on the queue
+- */
+- if (!flush_count && !atomic_read(&queue->set_pci_flags_count))
+- flush_count += qeth_flush_buffers_on_no_pci(queue);
+- if (flush_count)
+- qeth_flush_buffers(queue, 0, start_index, flush_count);
+- }
+- /* at this point the queue is UNLOCKED again */
+- if (queue->card->options.performance_stats && do_pack)
+- queue->card->perf_stats.bufs_sent_pack += flush_count;
+-
+- return rc;
+-}
+-
+-static int
+-qeth_get_elements_no(struct qeth_card *card, void *hdr,
+- struct sk_buff *skb, int elems)
+-{
+- int elements_needed = 0;
+-
+- if (skb_shinfo(skb)->nr_frags > 0)
+- elements_needed = (skb_shinfo(skb)->nr_frags + 1);
+- if (elements_needed == 0)
+- elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE)
+- + skb->len) >> PAGE_SHIFT);
+- if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)){
+- PRINT_ERR("Invalid size of IP packet "
+- "(Number=%d / Length=%d). Discarded.\n",
+- (elements_needed+elems), skb->len);
+- return 0;
+- }
+- return elements_needed;
+-}
+-
+-static void qeth_tx_csum(struct sk_buff *skb)
+-{
+- int tlen;
+-
+- if (skb->protocol == htons(ETH_P_IP)) {
+- tlen = ntohs(ip_hdr(skb)->tot_len) - (ip_hdr(skb)->ihl << 2);
+- switch (ip_hdr(skb)->protocol) {
+- case IPPROTO_TCP:
+- tcp_hdr(skb)->check = 0;
+- tcp_hdr(skb)->check = csum_tcpudp_magic(
+- ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
+- tlen, ip_hdr(skb)->protocol,
+- skb_checksum(skb, skb_transport_offset(skb),
+- tlen, 0));
+- break;
+- case IPPROTO_UDP:
+- udp_hdr(skb)->check = 0;
+- udp_hdr(skb)->check = csum_tcpudp_magic(
+- ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
+- tlen, ip_hdr(skb)->protocol,
+- skb_checksum(skb, skb_transport_offset(skb),
+- tlen, 0));
+- break;
+- }
+- } else if (skb->protocol == htons(ETH_P_IPV6)) {
+- switch (ipv6_hdr(skb)->nexthdr) {
+- case IPPROTO_TCP:
+- tcp_hdr(skb)->check = 0;
+- tcp_hdr(skb)->check = csum_ipv6_magic(
+- &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
+- ipv6_hdr(skb)->payload_len,
+- ipv6_hdr(skb)->nexthdr,
+- skb_checksum(skb, skb_transport_offset(skb),
+- ipv6_hdr(skb)->payload_len, 0));
+- break;
+- case IPPROTO_UDP:
+- udp_hdr(skb)->check = 0;
+- udp_hdr(skb)->check = csum_ipv6_magic(
+- &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
+- ipv6_hdr(skb)->payload_len,
+- ipv6_hdr(skb)->nexthdr,
+- skb_checksum(skb, skb_transport_offset(skb),
+- ipv6_hdr(skb)->payload_len, 0));
+- break;
+- }
+- }
+-}
+-
+-static int
+-qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
+-{
+- int ipv = 0;
+- int cast_type;
+- struct qeth_qdio_out_q *queue;
+- struct qeth_hdr *hdr = NULL;
+- int elements_needed = 0;
+- enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
+- struct qeth_eddp_context *ctx = NULL;
+- int tx_bytes = skb->len;
+- unsigned short nr_frags = skb_shinfo(skb)->nr_frags;
+- unsigned short tso_size = skb_shinfo(skb)->gso_size;
+- struct sk_buff *new_skb, *new_skb2;
+- int rc;
+-
+- QETH_DBF_TEXT(trace, 6, "sendpkt");
+-
+- new_skb = skb;
+- if ((card->info.type == QETH_CARD_TYPE_OSN) &&
+- (skb->protocol == htons(ETH_P_IPV6)))
+- return -EPERM;
+- cast_type = qeth_get_cast_type(card, skb);
+- if ((cast_type == RTN_BROADCAST) &&
+- (card->info.broadcast_capable == 0))
+- return -EPERM;
+- queue = card->qdio.out_qs
+- [qeth_get_priority_queue(card, skb, ipv, cast_type)];
+- if (!card->options.layer2) {
+- ipv = qeth_get_ip_version(skb);
+- if ((card->dev->header_ops == &qeth_fake_ops) && ipv) {
+- new_skb = qeth_pskb_unshare(skb, GFP_ATOMIC);
+- if (!new_skb)
+- return -ENOMEM;
+- if(card->dev->type == ARPHRD_IEEE802_TR){
+- skb_pull(new_skb, QETH_FAKE_LL_LEN_TR);
+- } else {
+- skb_pull(new_skb, QETH_FAKE_LL_LEN_ETH);
+- }
+- }
+- }
+- if (skb_is_gso(skb))
+- large_send = card->options.large_send;
+- /* check on OSN device*/
+- if (card->info.type == QETH_CARD_TYPE_OSN)
+- hdr = (struct qeth_hdr *)new_skb->data;
+- /*are we able to do TSO ? */
+- if ((large_send == QETH_LARGE_SEND_TSO) &&
+- (cast_type == RTN_UNSPEC)) {
+- rc = qeth_tso_prepare_packet(card, new_skb, ipv, cast_type);
+- if (rc) {
+- __qeth_free_new_skb(skb, new_skb);
+- return rc;
+- }
+- elements_needed++;
+- } else if (card->info.type != QETH_CARD_TYPE_OSN) {
+- new_skb2 = qeth_prepare_skb(card, new_skb, &hdr, ipv);
+- if (!new_skb2) {
+- __qeth_free_new_skb(skb, new_skb);
+- return -EINVAL;
+- }
+- if (new_skb != skb)
+- __qeth_free_new_skb(new_skb2, new_skb);
+- new_skb = new_skb2;
+- qeth_fill_header(card, hdr, new_skb, ipv, cast_type);
+- }
+- if (large_send == QETH_LARGE_SEND_EDDP) {
+- ctx = qeth_eddp_create_context(card, new_skb, hdr,
+- skb->sk->sk_protocol);
+- if (ctx == NULL) {
+- __qeth_free_new_skb(skb, new_skb);
+- PRINT_WARN("could not create eddp context\n");
+- return -EINVAL;
+- }
+- } else {
+- int elems = qeth_get_elements_no(card,(void*) hdr, new_skb,
+- elements_needed);
+- if (!elems) {
+- __qeth_free_new_skb(skb, new_skb);
+- return -EINVAL;
+- }
+- elements_needed += elems;
+- }
+-
+- if ((large_send == QETH_LARGE_SEND_NO) &&
+- (skb->ip_summed == CHECKSUM_PARTIAL))
+- qeth_tx_csum(new_skb);
+-
+- if (card->info.type != QETH_CARD_TYPE_IQD)
+- rc = qeth_do_send_packet(card, queue, new_skb, hdr,
+- elements_needed, ctx);
+- else {
+- if ((!card->options.layer2) &&
+- (ipv == 0)) {
+- __qeth_free_new_skb(skb, new_skb);
+- return -EPERM;
+- }
+- rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr,
+- elements_needed, ctx);
+- }
+- if (!rc) {
+- card->stats.tx_packets++;
+- card->stats.tx_bytes += tx_bytes;
+- if (new_skb != skb)
+- dev_kfree_skb_any(skb);
+- if (card->options.performance_stats) {
+- if (tso_size &&
+- !(large_send == QETH_LARGE_SEND_NO)) {
+- card->perf_stats.large_send_bytes += tx_bytes;
+- card->perf_stats.large_send_cnt++;
+- }
+- if (nr_frags > 0) {
+- card->perf_stats.sg_skbs_sent++;
+- /* nr_frags + skb->data */
+- card->perf_stats.sg_frags_sent +=
+- nr_frags + 1;
+- }
+- }
+- } else {
+- card->stats.tx_dropped++;
+- __qeth_free_new_skb(skb, new_skb);
+- }
+- if (ctx != NULL) {
+- /* drop creator's reference */
+- qeth_eddp_put_context(ctx);
+- /* free skb; it's not referenced by a buffer */
+- if (!rc)
+- dev_kfree_skb_any(new_skb);
+- }
+- return rc;
+-}
+-
+-static int
+-qeth_mdio_read(struct net_device *dev, int phy_id, int regnum)
+-{
+- struct qeth_card *card = (struct qeth_card *) dev->priv;
+- int rc = 0;
+-
+- switch(regnum){
+- case MII_BMCR: /* Basic mode control register */
+- rc = BMCR_FULLDPLX;
+- if ((card->info.link_type != QETH_LINK_TYPE_GBIT_ETH)&&
+- (card->info.link_type != QETH_LINK_TYPE_OSN) &&
+- (card->info.link_type != QETH_LINK_TYPE_10GBIT_ETH))
+- rc |= BMCR_SPEED100;
+- break;
+- case MII_BMSR: /* Basic mode status register */
+- rc = BMSR_ERCAP | BMSR_ANEGCOMPLETE | BMSR_LSTATUS |
+- BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | BMSR_100FULL |
+- BMSR_100BASE4;
+- break;
+- case MII_PHYSID1: /* PHYS ID 1 */
+- rc = (dev->dev_addr[0] << 16) | (dev->dev_addr[1] << 8) |
+- dev->dev_addr[2];
+- rc = (rc >> 5) & 0xFFFF;
+- break;
+- case MII_PHYSID2: /* PHYS ID 2 */
+- rc = (dev->dev_addr[2] << 10) & 0xFFFF;
+- break;
+- case MII_ADVERTISE: /* Advertisement control reg */
+- rc = ADVERTISE_ALL;
+- break;
+- case MII_LPA: /* Link partner ability reg */
+- rc = LPA_10HALF | LPA_10FULL | LPA_100HALF | LPA_100FULL |
+- LPA_100BASE4 | LPA_LPACK;
+- break;
+- case MII_EXPANSION: /* Expansion register */
+- break;
+- case MII_DCOUNTER: /* disconnect counter */
+- break;
+- case MII_FCSCOUNTER: /* false carrier counter */
+- break;
+- case MII_NWAYTEST: /* N-way auto-neg test register */
+- break;
+- case MII_RERRCOUNTER: /* rx error counter */
+- rc = card->stats.rx_errors;
+- break;
+- case MII_SREVISION: /* silicon revision */
+- break;
+- case MII_RESV1: /* reserved 1 */
+- break;
+- case MII_LBRERROR: /* loopback, rx, bypass error */
+- break;
+- case MII_PHYADDR: /* physical address */
+- break;
+- case MII_RESV2: /* reserved 2 */
+- break;
+- case MII_TPISTATUS: /* TPI status for 10mbps */
+- break;
+- case MII_NCONFIG: /* network interface config */
+- break;
+- default:
+- break;
+- }
+- return rc;
+-}
+-
+-
+-static const char *
+-qeth_arp_get_error_cause(int *rc)
+-{
+- switch (*rc) {
+- case QETH_IPA_ARP_RC_FAILED:
+- *rc = -EIO;
+- return "operation failed";
+- case QETH_IPA_ARP_RC_NOTSUPP:
+- *rc = -EOPNOTSUPP;
+- return "operation not supported";
+- case QETH_IPA_ARP_RC_OUT_OF_RANGE:
+- *rc = -EINVAL;
+- return "argument out of range";
+- case QETH_IPA_ARP_RC_Q_NOTSUPP:
+- *rc = -EOPNOTSUPP;
+- return "query operation not supported";
+- case QETH_IPA_ARP_RC_Q_NO_DATA:
+- *rc = -ENOENT;
+- return "no query data available";
+- default:
+- return "unknown error";
+- }
+-}
+-
+-static int
+-qeth_send_simple_setassparms(struct qeth_card *, enum qeth_ipa_funcs,
+- __u16, long);
+-
+-static int
+-qeth_arp_set_no_entries(struct qeth_card *card, int no_entries)
+-{
+- int tmp;
+- int rc;
+-
+- QETH_DBF_TEXT(trace,3,"arpstnoe");
+-
+- /*
+- * currently GuestLAN only supports the ARP assist function
+- * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_SET_NO_ENTRIES;
+- * thus we say EOPNOTSUPP for this ARP function
+- */
+- if (card->info.guestlan)
+- return -EOPNOTSUPP;
+- if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
+- PRINT_WARN("ARP processing not supported "
+- "on %s!\n", QETH_CARD_IFNAME(card));
+- return -EOPNOTSUPP;
+- }
+- rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
+- IPA_CMD_ASS_ARP_SET_NO_ENTRIES,
+- no_entries);
+- if (rc) {
+- tmp = rc;
+- PRINT_WARN("Could not set number of ARP entries on %s: "
+- "%s (0x%x/%d)\n",
+- QETH_CARD_IFNAME(card), qeth_arp_get_error_cause(&rc),
+- tmp, tmp);
+- }
+- return rc;
+-}
+-
+-static void
+-qeth_copy_arp_entries_stripped(struct qeth_arp_query_info *qinfo,
+- struct qeth_arp_query_data *qdata,
+- int entry_size, int uentry_size)
+-{
+- char *entry_ptr;
+- char *uentry_ptr;
+- int i;
+-
+- entry_ptr = (char *)&qdata->data;
+- uentry_ptr = (char *)(qinfo->udata + qinfo->udata_offset);
+- for (i = 0; i < qdata->no_entries; ++i){
+- /* strip off 32 bytes "media specific information" */
+- memcpy(uentry_ptr, (entry_ptr + 32), entry_size - 32);
+- entry_ptr += entry_size;
+- uentry_ptr += uentry_size;
+- }
+-}
+-
+-static int
+-qeth_arp_query_cb(struct qeth_card *card, struct qeth_reply *reply,
+- unsigned long data)
+-{
+- struct qeth_ipa_cmd *cmd;
+- struct qeth_arp_query_data *qdata;
+- struct qeth_arp_query_info *qinfo;
+- int entry_size;
+- int uentry_size;
+- int i;
+-
+- QETH_DBF_TEXT(trace,4,"arpquecb");
+-
+- qinfo = (struct qeth_arp_query_info *) reply->param;
+- cmd = (struct qeth_ipa_cmd *) data;
+- if (cmd->hdr.return_code) {
+- QETH_DBF_TEXT_(trace,4,"qaer1%i", cmd->hdr.return_code);
+- return 0;
+- }
+- if (cmd->data.setassparms.hdr.return_code) {
+- cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code;
+- QETH_DBF_TEXT_(trace,4,"qaer2%i", cmd->hdr.return_code);
+- return 0;
+- }
+- qdata = &cmd->data.setassparms.data.query_arp;
+- switch(qdata->reply_bits){
+- case 5:
+- uentry_size = entry_size = sizeof(struct qeth_arp_qi_entry5);
+- if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES)
+- uentry_size = sizeof(struct qeth_arp_qi_entry5_short);
+- break;
+- case 7:
+- /* fall through to default */
+- default:
+- /* tr is the same as eth -> entry7 */
+- uentry_size = entry_size = sizeof(struct qeth_arp_qi_entry7);
+- if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES)
+- uentry_size = sizeof(struct qeth_arp_qi_entry7_short);
+- break;
+- }
+- /* check if there is enough room in userspace */
+- if ((qinfo->udata_len - qinfo->udata_offset) <
+- qdata->no_entries * uentry_size){
+- QETH_DBF_TEXT_(trace, 4, "qaer3%i", -ENOMEM);
+- cmd->hdr.return_code = -ENOMEM;
+- PRINT_WARN("query ARP user space buffer is too small for "
+- "the returned number of ARP entries. "
+- "Aborting query!\n");
+- goto out_error;
+- }
+- QETH_DBF_TEXT_(trace, 4, "anore%i",
+- cmd->data.setassparms.hdr.number_of_replies);
+- QETH_DBF_TEXT_(trace, 4, "aseqn%i", cmd->data.setassparms.hdr.seq_no);
+- QETH_DBF_TEXT_(trace, 4, "anoen%i", qdata->no_entries);
+-
+- if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES) {
+- /* strip off "media specific information" */
+- qeth_copy_arp_entries_stripped(qinfo, qdata, entry_size,
+- uentry_size);
+- } else
+- /*copy entries to user buffer*/
+- memcpy(qinfo->udata + qinfo->udata_offset,
+- (char *)&qdata->data, qdata->no_entries*uentry_size);
+-
+- qinfo->no_entries += qdata->no_entries;
+- qinfo->udata_offset += (qdata->no_entries*uentry_size);
+- /* check if all replies received ... */
+- if (cmd->data.setassparms.hdr.seq_no <
+- cmd->data.setassparms.hdr.number_of_replies)
+- return 1;
+- memcpy(qinfo->udata, &qinfo->no_entries, 4);
+- /* keep STRIP_ENTRIES flag so the user program can distinguish
+- * stripped entries from normal ones */
+- if (qinfo->mask_bits & QETH_QARP_STRIP_ENTRIES)
+- qdata->reply_bits |= QETH_QARP_STRIP_ENTRIES;
+- memcpy(qinfo->udata + QETH_QARP_MASK_OFFSET,&qdata->reply_bits,2);
+- return 0;
+-out_error:
+- i = 0;
+- memcpy(qinfo->udata, &i, 4);
+- return 0;
+-}
+-
+-static int
+-qeth_send_ipa_arp_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+- int len, int (*reply_cb)(struct qeth_card *,
+- struct qeth_reply *,
+- unsigned long),
+- void *reply_param)
+-{
+- QETH_DBF_TEXT(trace,4,"sendarp");
+-
+- memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
+- memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
+- &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+- return qeth_send_control_data(card, IPA_PDU_HEADER_SIZE + len, iob,
+- reply_cb, reply_param);
+-}
+-
+-static int
+-qeth_send_ipa_snmp_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+- int len, int (*reply_cb)(struct qeth_card *,
+- struct qeth_reply *,
+- unsigned long),
+- void *reply_param)
+-{
+- u16 s1, s2;
+-
+- QETH_DBF_TEXT(trace,4,"sendsnmp");
+-
+- memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
+- memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
+- &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+- /* adjust PDU length fields in IPA_PDU_HEADER */
+- s1 = (u32) IPA_PDU_HEADER_SIZE + len;
+- s2 = (u32) len;
+- memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
+- memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
+- memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
+- memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
+- return qeth_send_control_data(card, IPA_PDU_HEADER_SIZE + len, iob,
+- reply_cb, reply_param);
+-}
+-
+-static struct qeth_cmd_buffer *
+-qeth_get_setassparms_cmd(struct qeth_card *, enum qeth_ipa_funcs,
+- __u16, __u16, enum qeth_prot_versions);
+-static int
+-qeth_arp_query(struct qeth_card *card, char __user *udata)
+-{
+- struct qeth_cmd_buffer *iob;
+- struct qeth_arp_query_info qinfo = {0, };
+- int tmp;
+- int rc;
+-
+- QETH_DBF_TEXT(trace,3,"arpquery");
+-
+- if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/
+- IPA_ARP_PROCESSING)) {
+- PRINT_WARN("ARP processing not supported "
+- "on %s!\n", QETH_CARD_IFNAME(card));
+- return -EOPNOTSUPP;
+- }
+- /* get size of userspace buffer and mask_bits -> 6 bytes */
+- if (copy_from_user(&qinfo, udata, 6))
+- return -EFAULT;
+- if (!(qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL)))
+- return -ENOMEM;
+- qinfo.udata_offset = QETH_QARP_ENTRIES_OFFSET;
+- iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
+- IPA_CMD_ASS_ARP_QUERY_INFO,
+- sizeof(int),QETH_PROT_IPV4);
+-
+- rc = qeth_send_ipa_arp_cmd(card, iob,
+- QETH_SETASS_BASE_LEN+QETH_ARP_CMD_LEN,
+- qeth_arp_query_cb, (void *)&qinfo);
+- if (rc) {
+- tmp = rc;
+- PRINT_WARN("Error while querying ARP cache on %s: %s "
+- "(0x%x/%d)\n",
+- QETH_CARD_IFNAME(card), qeth_arp_get_error_cause(&rc),
+- tmp, tmp);
+- if (copy_to_user(udata, qinfo.udata, 4))
+- rc = -EFAULT;
+- } else {
+- if (copy_to_user(udata, qinfo.udata, qinfo.udata_len))
+- rc = -EFAULT;
+- }
+- kfree(qinfo.udata);
+- return rc;
+-}
+-
+-/**
+- * SNMP command callback
+- */
+-static int
+-qeth_snmp_command_cb(struct qeth_card *card, struct qeth_reply *reply,
+- unsigned long sdata)
+-{
+- struct qeth_ipa_cmd *cmd;
+- struct qeth_arp_query_info *qinfo;
+- struct qeth_snmp_cmd *snmp;
+- unsigned char *data;
+- __u16 data_len;
+-
+- QETH_DBF_TEXT(trace,3,"snpcmdcb");
+-
+- cmd = (struct qeth_ipa_cmd *) sdata;
+- data = (unsigned char *)((char *)cmd - reply->offset);
+- qinfo = (struct qeth_arp_query_info *) reply->param;
+- snmp = &cmd->data.setadapterparms.data.snmp;
+-
+- if (cmd->hdr.return_code) {
+- QETH_DBF_TEXT_(trace,4,"scer1%i", cmd->hdr.return_code);
+- return 0;
+- }
+- if (cmd->data.setadapterparms.hdr.return_code) {
+- cmd->hdr.return_code = cmd->data.setadapterparms.hdr.return_code;
+- QETH_DBF_TEXT_(trace,4,"scer2%i", cmd->hdr.return_code);
+- return 0;
+- }
+- data_len = *((__u16*)QETH_IPA_PDU_LEN_PDU1(data));
+- if (cmd->data.setadapterparms.hdr.seq_no == 1)
+- data_len -= (__u16)((char *)&snmp->data - (char *)cmd);
+- else
+- data_len -= (__u16)((char*)&snmp->request - (char *)cmd);
+-
+- /* check if there is enough room in userspace */
+- if ((qinfo->udata_len - qinfo->udata_offset) < data_len) {
+- QETH_DBF_TEXT_(trace, 4, "scer3%i", -ENOMEM);
+- cmd->hdr.return_code = -ENOMEM;
+- return 0;
+- }
+- QETH_DBF_TEXT_(trace, 4, "snore%i",
+- cmd->data.setadapterparms.hdr.used_total);
+- QETH_DBF_TEXT_(trace, 4, "sseqn%i", cmd->data.setadapterparms.hdr.seq_no);
+- /*copy entries to user buffer*/
+- if (cmd->data.setadapterparms.hdr.seq_no == 1) {
+- memcpy(qinfo->udata + qinfo->udata_offset,
+- (char *)snmp,
+- data_len + offsetof(struct qeth_snmp_cmd,data));
+- qinfo->udata_offset += offsetof(struct qeth_snmp_cmd, data);
+- } else {
+- memcpy(qinfo->udata + qinfo->udata_offset,
+- (char *)&snmp->request, data_len);
+- }
+- qinfo->udata_offset += data_len;
+- /* check if all replies received ... */
+- QETH_DBF_TEXT_(trace, 4, "srtot%i",
+- cmd->data.setadapterparms.hdr.used_total);
+- QETH_DBF_TEXT_(trace, 4, "srseq%i",
+- cmd->data.setadapterparms.hdr.seq_no);
+- if (cmd->data.setadapterparms.hdr.seq_no <
+- cmd->data.setadapterparms.hdr.used_total)
+- return 1;
+- return 0;
+-}
+-
+-static struct qeth_cmd_buffer *
+-qeth_get_ipacmd_buffer(struct qeth_card *, enum qeth_ipa_cmds,
+- enum qeth_prot_versions );
+-
+-static struct qeth_cmd_buffer *
+-qeth_get_adapter_cmd(struct qeth_card *card, __u32 command, __u32 cmdlen)
+-{
+- struct qeth_cmd_buffer *iob;
+- struct qeth_ipa_cmd *cmd;
+-
+- iob = qeth_get_ipacmd_buffer(card,IPA_CMD_SETADAPTERPARMS,
+- QETH_PROT_IPV4);
+- cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+- cmd->data.setadapterparms.hdr.cmdlength = cmdlen;
+- cmd->data.setadapterparms.hdr.command_code = command;
+- cmd->data.setadapterparms.hdr.used_total = 1;
+- cmd->data.setadapterparms.hdr.seq_no = 1;
+-
+- return iob;
+-}
+-
+-/**
+- * function to send SNMP commands to OSA-E card
+- */
+-static int
+-qeth_snmp_command(struct qeth_card *card, char __user *udata)
+-{
+- struct qeth_cmd_buffer *iob;
+- struct qeth_ipa_cmd *cmd;
+- struct qeth_snmp_ureq *ureq;
+- int req_len;
+- struct qeth_arp_query_info qinfo = {0, };
+- int rc = 0;
+-
+- QETH_DBF_TEXT(trace,3,"snmpcmd");
+-
+- if (card->info.guestlan)
+- return -EOPNOTSUPP;
+-
+- if ((!qeth_adp_supported(card,IPA_SETADP_SET_SNMP_CONTROL)) &&
+- (!card->options.layer2) ) {
+- PRINT_WARN("SNMP Query MIBS not supported "
+- "on %s!\n", QETH_CARD_IFNAME(card));
+- return -EOPNOTSUPP;
+- }
+- /* skip 4 bytes (data_len struct member) to get req_len */
+- if (copy_from_user(&req_len, udata + sizeof(int), sizeof(int)))
+- return -EFAULT;
+- ureq = kmalloc(req_len+sizeof(struct qeth_snmp_ureq_hdr), GFP_KERNEL);
+- if (!ureq) {
+- QETH_DBF_TEXT(trace, 2, "snmpnome");
+- return -ENOMEM;
+- }
+- if (copy_from_user(ureq, udata,
+- req_len+sizeof(struct qeth_snmp_ureq_hdr))){
+- kfree(ureq);
+- return -EFAULT;
+- }
+- qinfo.udata_len = ureq->hdr.data_len;
+- if (!(qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL))){
+- kfree(ureq);
+- return -ENOMEM;
+- }
+- qinfo.udata_offset = sizeof(struct qeth_snmp_ureq_hdr);
+-
+- iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_SNMP_CONTROL,
+- QETH_SNMP_SETADP_CMDLENGTH + req_len);
+- cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+- memcpy(&cmd->data.setadapterparms.data.snmp, &ureq->cmd, req_len);
+- rc = qeth_send_ipa_snmp_cmd(card, iob, QETH_SETADP_BASE_LEN + req_len,
+- qeth_snmp_command_cb, (void *)&qinfo);
+- if (rc)
+- PRINT_WARN("SNMP command failed on %s: (0x%x)\n",
+- QETH_CARD_IFNAME(card), rc);
+- else {
+- if (copy_to_user(udata, qinfo.udata, qinfo.udata_len))
+- rc = -EFAULT;
+- }
+-
+- kfree(ureq);
+- kfree(qinfo.udata);
+- return rc;
+-}
+-
+-static int
+-qeth_default_setassparms_cb(struct qeth_card *, struct qeth_reply *,
+- unsigned long);
+-
+-static int
+-qeth_default_setadapterparms_cb(struct qeth_card *card,
+- struct qeth_reply *reply,
+- unsigned long data);
+-static int
+-qeth_send_setassparms(struct qeth_card *, struct qeth_cmd_buffer *,
+- __u16, long,
+- int (*reply_cb)
+- (struct qeth_card *, struct qeth_reply *, unsigned long),
+- void *reply_param);
+-
+-static int
+-qeth_arp_add_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry)
+-{
+- struct qeth_cmd_buffer *iob;
+- char buf[16];
+- int tmp;
+- int rc;
+-
+- QETH_DBF_TEXT(trace,3,"arpadent");
+-
+- /*
+- * currently GuestLAN only supports the ARP assist function
+- * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_ADD_ENTRY;
+- * thus we say EOPNOTSUPP for this ARP function
+- */
+- if (card->info.guestlan)
+- return -EOPNOTSUPP;
+- if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
+- PRINT_WARN("ARP processing not supported "
+- "on %s!\n", QETH_CARD_IFNAME(card));
+- return -EOPNOTSUPP;
+- }
+-
+- iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
+- IPA_CMD_ASS_ARP_ADD_ENTRY,
+- sizeof(struct qeth_arp_cache_entry),
+- QETH_PROT_IPV4);
+- rc = qeth_send_setassparms(card, iob,
+- sizeof(struct qeth_arp_cache_entry),
+- (unsigned long) entry,
+- qeth_default_setassparms_cb, NULL);
+- if (rc) {
+- tmp = rc;
+- qeth_ipaddr4_to_string((u8 *)entry->ipaddr, buf);
+- PRINT_WARN("Could not add ARP entry for address %s on %s: "
+- "%s (0x%x/%d)\n",
+- buf, QETH_CARD_IFNAME(card),
+- qeth_arp_get_error_cause(&rc), tmp, tmp);
+- }
+- return rc;
+-}
+-
+-static int
+-qeth_arp_remove_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry)
+-{
+- struct qeth_cmd_buffer *iob;
+- char buf[16] = {0, };
+- int tmp;
+- int rc;
+-
+- QETH_DBF_TEXT(trace,3,"arprment");
+-
+- /*
+- * currently GuestLAN only supports the ARP assist function
+- * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_REMOVE_ENTRY;
+- * thus we say EOPNOTSUPP for this ARP function
+- */
+- if (card->info.guestlan)
+- return -EOPNOTSUPP;
+- if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
+- PRINT_WARN("ARP processing not supported "
+- "on %s!\n", QETH_CARD_IFNAME(card));
+- return -EOPNOTSUPP;
+- }
+- memcpy(buf, entry, 12);
+- iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
+- IPA_CMD_ASS_ARP_REMOVE_ENTRY,
+- 12,
+- QETH_PROT_IPV4);
+- rc = qeth_send_setassparms(card, iob,
+- 12, (unsigned long)buf,
+- qeth_default_setassparms_cb, NULL);
+- if (rc) {
+- tmp = rc;
+- memset(buf, 0, 16);
+- qeth_ipaddr4_to_string((u8 *)entry->ipaddr, buf);
+- PRINT_WARN("Could not delete ARP entry for address %s on %s: "
+- "%s (0x%x/%d)\n",
+- buf, QETH_CARD_IFNAME(card),
+- qeth_arp_get_error_cause(&rc), tmp, tmp);
+- }
+- return rc;
+-}
+-
+-static int
+-qeth_arp_flush_cache(struct qeth_card *card)
+-{
+- int rc;
+- int tmp;
+-
+- QETH_DBF_TEXT(trace,3,"arpflush");
+-
+- /*
+- * currently GuestLAN only supports the ARP assist function
+- * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_FLUSH_CACHE;
+- * thus we say EOPNOTSUPP for this ARP function
+- */
+- if (card->info.guestlan || (card->info.type == QETH_CARD_TYPE_IQD))
+- return -EOPNOTSUPP;
+- if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
+- PRINT_WARN("ARP processing not supported "
+- "on %s!\n", QETH_CARD_IFNAME(card));
+- return -EOPNOTSUPP;
+- }
+- rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
+- IPA_CMD_ASS_ARP_FLUSH_CACHE, 0);
+- if (rc){
+- tmp = rc;
+- PRINT_WARN("Could not flush ARP cache on %s: %s (0x%x/%d)\n",
+- QETH_CARD_IFNAME(card), qeth_arp_get_error_cause(&rc),
+- tmp, tmp);
+- }
+- return rc;
+-}
+-
+-static int
+-qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+-{
+- struct qeth_card *card = (struct qeth_card *)dev->priv;
+- struct qeth_arp_cache_entry arp_entry;
+- struct mii_ioctl_data *mii_data;
+- int rc = 0;
+-
+- if (!card)
+- return -ENODEV;
+-
+- if ((card->state != CARD_STATE_UP) &&
+- (card->state != CARD_STATE_SOFTSETUP))
+- return -ENODEV;
+-
+- if (card->info.type == QETH_CARD_TYPE_OSN)
+- return -EPERM;
+-
+- switch (cmd){
+- case SIOC_QETH_ARP_SET_NO_ENTRIES:
+- if ( !capable(CAP_NET_ADMIN) ||
+- (card->options.layer2) ) {
+- rc = -EPERM;
+- break;
+- }
+- rc = qeth_arp_set_no_entries(card, rq->ifr_ifru.ifru_ivalue);
+- break;
+- case SIOC_QETH_ARP_QUERY_INFO:
+- if ( !capable(CAP_NET_ADMIN) ||
+- (card->options.layer2) ) {
+- rc = -EPERM;
+- break;
+- }
+- rc = qeth_arp_query(card, rq->ifr_ifru.ifru_data);
+- break;
+- case SIOC_QETH_ARP_ADD_ENTRY:
+- if ( !capable(CAP_NET_ADMIN) ||
+- (card->options.layer2) ) {
+- rc = -EPERM;
+- break;
+- }
+- if (copy_from_user(&arp_entry, rq->ifr_ifru.ifru_data,
+- sizeof(struct qeth_arp_cache_entry)))
+- rc = -EFAULT;
+- else
+- rc = qeth_arp_add_entry(card, &arp_entry);
+- break;
+- case SIOC_QETH_ARP_REMOVE_ENTRY:
+- if ( !capable(CAP_NET_ADMIN) ||
+- (card->options.layer2) ) {
+- rc = -EPERM;
+- break;
+- }
+- if (copy_from_user(&arp_entry, rq->ifr_ifru.ifru_data,
+- sizeof(struct qeth_arp_cache_entry)))
+- rc = -EFAULT;
+- else
+- rc = qeth_arp_remove_entry(card, &arp_entry);
+- break;
+- case SIOC_QETH_ARP_FLUSH_CACHE:
+- if ( !capable(CAP_NET_ADMIN) ||
+- (card->options.layer2) ) {
+- rc = -EPERM;
+- break;
+- }
+- rc = qeth_arp_flush_cache(card);
+- break;
+- case SIOC_QETH_ADP_SET_SNMP_CONTROL:
+- rc = qeth_snmp_command(card, rq->ifr_ifru.ifru_data);
+- break;
+- case SIOC_QETH_GET_CARD_TYPE:
+- if ((card->info.type == QETH_CARD_TYPE_OSAE) &&
+- !card->info.guestlan)
+- return 1;
+- return 0;
+- break;
+- case SIOCGMIIPHY:
+- mii_data = if_mii(rq);
+- mii_data->phy_id = 0;
+- break;
+- case SIOCGMIIREG:
+- mii_data = if_mii(rq);
+- if (mii_data->phy_id != 0)
+- rc = -EINVAL;
+- else
+- mii_data->val_out = qeth_mdio_read(dev,mii_data->phy_id,
+- mii_data->reg_num);
+- break;
+- default:
+- rc = -EOPNOTSUPP;
+- }
+- if (rc)
+- QETH_DBF_TEXT_(trace, 2, "ioce%d", rc);
+- return rc;
+-}
+-
+-static struct net_device_stats *
+-qeth_get_stats(struct net_device *dev)
+-{
+- struct qeth_card *card;
+-
+- card = (struct qeth_card *) (dev->priv);
+-
+- QETH_DBF_TEXT(trace,5,"getstat");
+-
+- return &card->stats;
+-}
+-
+-static int
+-qeth_change_mtu(struct net_device *dev, int new_mtu)
+-{
+- struct qeth_card *card;
+- char dbf_text[15];
+-
+- card = (struct qeth_card *) (dev->priv);
+-
+- QETH_DBF_TEXT(trace,4,"chgmtu");
+- sprintf(dbf_text, "%8x", new_mtu);
+- QETH_DBF_TEXT(trace,4,dbf_text);
+-
+- if (new_mtu < 64)
+- return -EINVAL;
+- if (new_mtu > 65535)
+- return -EINVAL;
+- if ((!qeth_is_supported(card,IPA_IP_FRAGMENTATION)) &&
+- (!qeth_mtu_is_valid(card, new_mtu)))
+- return -EINVAL;
+- dev->mtu = new_mtu;
+- return 0;
+-}
+-
+-#ifdef CONFIG_QETH_VLAN
+-static void
+-qeth_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
+-{
+- struct qeth_card *card;
+- unsigned long flags;
+-
+- QETH_DBF_TEXT(trace,4,"vlanreg");
+-
+- card = (struct qeth_card *) dev->priv;
+- spin_lock_irqsave(&card->vlanlock, flags);
+- card->vlangrp = grp;
+- spin_unlock_irqrestore(&card->vlanlock, flags);
+-}
+-
+-static void
+-qeth_free_vlan_buffer(struct qeth_card *card, struct qeth_qdio_out_buffer *buf,
+- unsigned short vid)
+-{
+- int i;
+- struct sk_buff *skb;
+- struct sk_buff_head tmp_list;
+-
+- skb_queue_head_init(&tmp_list);
+- lockdep_set_class(&tmp_list.lock, &qdio_out_skb_queue_key);
+- for(i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i){
+- while ((skb = skb_dequeue(&buf->skb_list))){
+- if (vlan_tx_tag_present(skb) &&
+- (vlan_tx_tag_get(skb) == vid)) {
+- atomic_dec(&skb->users);
+- dev_kfree_skb(skb);
+- } else
+- skb_queue_tail(&tmp_list, skb);
+- }
+- }
+- while ((skb = skb_dequeue(&tmp_list)))
+- skb_queue_tail(&buf->skb_list, skb);
+-}
+-
+-static void
+-qeth_free_vlan_skbs(struct qeth_card *card, unsigned short vid)
+-{
+- int i, j;
+-
+- QETH_DBF_TEXT(trace, 4, "frvlskbs");
+- for (i = 0; i < card->qdio.no_out_queues; ++i){
+- for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
+- qeth_free_vlan_buffer(card, &card->qdio.
+- out_qs[i]->bufs[j], vid);
+- }
+-}
+-
+-static void
+-qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid)
+-{
+- struct in_device *in_dev;
+- struct in_ifaddr *ifa;
+- struct qeth_ipaddr *addr;
+-
+- QETH_DBF_TEXT(trace, 4, "frvaddr4");
+-
+- rcu_read_lock();
+- in_dev = __in_dev_get_rcu(vlan_group_get_device(card->vlangrp, vid));
+- if (!in_dev)
+- goto out;
+- for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
+- addr = qeth_get_addr_buffer(QETH_PROT_IPV4);
+- if (addr){
+- addr->u.a4.addr = ifa->ifa_address;
+- addr->u.a4.mask = ifa->ifa_mask;
+- addr->type = QETH_IP_TYPE_NORMAL;
+- if (!qeth_delete_ip(card, addr))
+- kfree(addr);
+- }
+- }
+-out:
+- rcu_read_unlock();
+-}
+-
+-static void
+-qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid)
+-{
+-#ifdef CONFIG_QETH_IPV6
+- struct inet6_dev *in6_dev;
+- struct inet6_ifaddr *ifa;
+- struct qeth_ipaddr *addr;
+-
+- QETH_DBF_TEXT(trace, 4, "frvaddr6");
+-
+- in6_dev = in6_dev_get(vlan_group_get_device(card->vlangrp, vid));
+- if (!in6_dev)
+- return;
+- for (ifa = in6_dev->addr_list; ifa; ifa = ifa->lst_next){
+- addr = qeth_get_addr_buffer(QETH_PROT_IPV6);
+- if (addr){
+- memcpy(&addr->u.a6.addr, &ifa->addr,
+- sizeof(struct in6_addr));
+- addr->u.a6.pfxlen = ifa->prefix_len;
+- addr->type = QETH_IP_TYPE_NORMAL;
+- if (!qeth_delete_ip(card, addr))
+- kfree(addr);
+- }
+- }
+- in6_dev_put(in6_dev);
+-#endif /* CONFIG_QETH_IPV6 */
+-}
+-
+-static void
+-qeth_free_vlan_addresses(struct qeth_card *card, unsigned short vid)
+-{
+- if (card->options.layer2 || !card->vlangrp)
+- return;
+- qeth_free_vlan_addresses4(card, vid);
+- qeth_free_vlan_addresses6(card, vid);
+-}
+-
+-static int
+-qeth_layer2_send_setdelvlan_cb(struct qeth_card *card,
+- struct qeth_reply *reply,
+- unsigned long data)
+-{
+- struct qeth_ipa_cmd *cmd;
+-
+- QETH_DBF_TEXT(trace, 2, "L2sdvcb");
+- cmd = (struct qeth_ipa_cmd *) data;
+- if (cmd->hdr.return_code) {
+- PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. "
+- "Continuing\n",cmd->data.setdelvlan.vlan_id,
+- QETH_CARD_IFNAME(card), cmd->hdr.return_code);
+- QETH_DBF_TEXT_(trace, 2, "L2VL%4x", cmd->hdr.command);
+- QETH_DBF_TEXT_(trace, 2, "L2%s", CARD_BUS_ID(card));
+- QETH_DBF_TEXT_(trace, 2, "err%d", cmd->hdr.return_code);
+- }
+- return 0;
+-}
+-
+-static int
+-qeth_layer2_send_setdelvlan(struct qeth_card *card, __u16 i,
+- enum qeth_ipa_cmds ipacmd)
+-{
+- struct qeth_ipa_cmd *cmd;
+- struct qeth_cmd_buffer *iob;
+-
+- QETH_DBF_TEXT_(trace, 4, "L2sdv%x",ipacmd);
+- iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
+- cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+- cmd->data.setdelvlan.vlan_id = i;
+- return qeth_send_ipa_cmd(card, iob,
+- qeth_layer2_send_setdelvlan_cb, NULL);
+-}
+-
+-static void
+-qeth_layer2_process_vlans(struct qeth_card *card, int clear)
+-{
+- unsigned short i;
+-
+- QETH_DBF_TEXT(trace, 3, "L2prcvln");
+-
+- if (!card->vlangrp)
+- return;
+- for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+- if (vlan_group_get_device(card->vlangrp, i) == NULL)
+- continue;
+- if (clear)
+- qeth_layer2_send_setdelvlan(card, i, IPA_CMD_DELVLAN);
+- else
+- qeth_layer2_send_setdelvlan(card, i, IPA_CMD_SETVLAN);
+- }
+-}
+-
+-/*add_vid is layer 2 used only ....*/
+-static void
+-qeth_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
+-{
+- struct qeth_card *card;
+-
+- QETH_DBF_TEXT_(trace, 4, "aid:%d", vid);
+-
+- card = (struct qeth_card *) dev->priv;
+- if (!card->options.layer2)
+- return;
+- qeth_layer2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN);
+-}
+-
+-/*... kill_vid used for both modes*/
+-static void
+-qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
+-{
+- struct qeth_card *card;
+- unsigned long flags;
+-
+- QETH_DBF_TEXT_(trace, 4, "kid:%d", vid);
+-
+- card = (struct qeth_card *) dev->priv;
+- /* free all skbs for the vlan device */
+- qeth_free_vlan_skbs(card, vid);
+- spin_lock_irqsave(&card->vlanlock, flags);
+- /* unregister IP addresses of vlan device */
+- qeth_free_vlan_addresses(card, vid);
+- vlan_group_set_device(card->vlangrp, vid, NULL);
+- spin_unlock_irqrestore(&card->vlanlock, flags);
+- if (card->options.layer2)
+- qeth_layer2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
+- qeth_set_multicast_list(card->dev);
+-}
+-#endif
+-/**
+- * Examine hardware response to SET_PROMISC_MODE
+- */
+-static int
+-qeth_setadp_promisc_mode_cb(struct qeth_card *card,
+- struct qeth_reply *reply,
+- unsigned long data)
+-{
+- struct qeth_ipa_cmd *cmd;
+- struct qeth_ipacmd_setadpparms *setparms;
+-
+- QETH_DBF_TEXT(trace,4,"prmadpcb");
+-
+- cmd = (struct qeth_ipa_cmd *) data;
+- setparms = &(cmd->data.setadapterparms);
+-
+- qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
+- if (cmd->hdr.return_code) {
+- QETH_DBF_TEXT_(trace,4,"prmrc%2.2x",cmd->hdr.return_code);
+- setparms->data.mode = SET_PROMISC_MODE_OFF;
+- }
+- card->info.promisc_mode = setparms->data.mode;
+- return 0;
+-}
+-/*
+- * Set promiscuous mode (on or off) (SET_PROMISC_MODE command)
+- */
+-static void
+-qeth_setadp_promisc_mode(struct qeth_card *card)
+-{
+- enum qeth_ipa_promisc_modes mode;
+- struct net_device *dev = card->dev;
+- struct qeth_cmd_buffer *iob;
+- struct qeth_ipa_cmd *cmd;
+-
+- QETH_DBF_TEXT(trace, 4, "setprom");
+-
+- if (((dev->flags & IFF_PROMISC) &&
+- (card->info.promisc_mode == SET_PROMISC_MODE_ON)) ||
+- (!(dev->flags & IFF_PROMISC) &&
+- (card->info.promisc_mode == SET_PROMISC_MODE_OFF)))
+- return;
+- mode = SET_PROMISC_MODE_OFF;
+- if (dev->flags & IFF_PROMISC)
+- mode = SET_PROMISC_MODE_ON;
+- QETH_DBF_TEXT_(trace, 4, "mode:%x", mode);
+-
+- iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_PROMISC_MODE,
+- sizeof(struct qeth_ipacmd_setadpparms));
+- cmd = (struct qeth_ipa_cmd *)(iob->data + IPA_PDU_HEADER_SIZE);
+- cmd->data.setadapterparms.data.mode = mode;
+- qeth_send_ipa_cmd(card, iob, qeth_setadp_promisc_mode_cb, NULL);
+-}
+-
+-/**
+- * set multicast address on card
+- */
+-static void
+-qeth_set_multicast_list(struct net_device *dev)
+-{
+- struct qeth_card *card = (struct qeth_card *) dev->priv;
+-
+- if (card->info.type == QETH_CARD_TYPE_OSN)
+- return ;
+-
+- QETH_DBF_TEXT(trace, 3, "setmulti");
+- qeth_delete_mc_addresses(card);
+- if (card->options.layer2) {
+- qeth_layer2_add_multicast(card);
+- goto out;
+- }
+- qeth_add_multicast_ipv4(card);
+-#ifdef CONFIG_QETH_IPV6
+- qeth_add_multicast_ipv6(card);
+-#endif
+-out:
+- qeth_set_ip_addr_list(card);
+- if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
+- return;
+- qeth_setadp_promisc_mode(card);
+-}
+-
+-static int
+-qeth_neigh_setup(struct net_device *dev, struct neigh_parms *np)
+-{
+- return 0;
+-}
+-
+-static void
+-qeth_get_mac_for_ipm(__u32 ipm, char *mac, struct net_device *dev)
+-{
+- if (dev->type == ARPHRD_IEEE802_TR)
+- ip_tr_mc_map(ipm, mac);
+- else
+- ip_eth_mc_map(ipm, mac);
+-}
+-
+-static struct qeth_ipaddr *
+-qeth_get_addr_buffer(enum qeth_prot_versions prot)
+-{
+- struct qeth_ipaddr *addr;
+-
+- addr = kzalloc(sizeof(struct qeth_ipaddr), GFP_ATOMIC);
+- if (addr == NULL) {
+- PRINT_WARN("Not enough memory to add address\n");
+- return NULL;
+- }
+- addr->type = QETH_IP_TYPE_NORMAL;
+- addr->proto = prot;
+- return addr;
+-}
+-
+-int
+-qeth_osn_assist(struct net_device *dev,
+- void *data,
+- int data_len)
+-{
+- struct qeth_cmd_buffer *iob;
+- struct qeth_card *card;
+- int rc;
+-
+- QETH_DBF_TEXT(trace, 2, "osnsdmc");
+- if (!dev)
+- return -ENODEV;
+- card = (struct qeth_card *)dev->priv;
+- if (!card)
+- return -ENODEV;
+- if ((card->state != CARD_STATE_UP) &&
+- (card->state != CARD_STATE_SOFTSETUP))
+- return -ENODEV;
+- iob = qeth_wait_for_buffer(&card->write);
+- memcpy(iob->data+IPA_PDU_HEADER_SIZE, data, data_len);
+- rc = qeth_osn_send_ipa_cmd(card, iob, data_len);
+- return rc;
+-}
+-
+-static struct net_device *
+-qeth_netdev_by_devno(unsigned char *read_dev_no)
+-{
+- struct qeth_card *card;
+- struct net_device *ndev;
+- unsigned char *readno;
+- __u16 temp_dev_no, card_dev_no;
+- char *endp;
+- unsigned long flags;
+-
+- ndev = NULL;
+- memcpy(&temp_dev_no, read_dev_no, 2);
+- read_lock_irqsave(&qeth_card_list.rwlock, flags);
+- list_for_each_entry(card, &qeth_card_list.list, list) {
+- readno = CARD_RDEV_ID(card);
+- readno += (strlen(readno) - 4);
+- card_dev_no = simple_strtoul(readno, &endp, 16);
+- if (card_dev_no == temp_dev_no) {
+- ndev = card->dev;
+- break;
+- }
+- }
+- read_unlock_irqrestore(&qeth_card_list.rwlock, flags);
+- return ndev;
+-}
+-
+-int
+-qeth_osn_register(unsigned char *read_dev_no,
+- struct net_device **dev,
+- int (*assist_cb)(struct net_device *, void *),
+- int (*data_cb)(struct sk_buff *))
+-{
+- struct qeth_card * card;
+-
+- QETH_DBF_TEXT(trace, 2, "osnreg");
+- *dev = qeth_netdev_by_devno(read_dev_no);
+- if (*dev == NULL)
+- return -ENODEV;
+- card = (struct qeth_card *)(*dev)->priv;
+- if (!card)
+- return -ENODEV;
+- if ((assist_cb == NULL) || (data_cb == NULL))
+- return -EINVAL;
+- card->osn_info.assist_cb = assist_cb;
+- card->osn_info.data_cb = data_cb;
+- return 0;
+-}
+-
+-void
+-qeth_osn_deregister(struct net_device * dev)
+-{
+- struct qeth_card *card;
+-
+- QETH_DBF_TEXT(trace, 2, "osndereg");
+- if (!dev)
+- return;
+- card = (struct qeth_card *)dev->priv;
+- if (!card)
+- return;
+- card->osn_info.assist_cb = NULL;
+- card->osn_info.data_cb = NULL;
+- return;
+-}
+-
+-static void
+-qeth_delete_mc_addresses(struct qeth_card *card)
+-{
+- struct qeth_ipaddr *iptodo;
+- unsigned long flags;
+-
+- QETH_DBF_TEXT(trace,4,"delmc");
+- iptodo = qeth_get_addr_buffer(QETH_PROT_IPV4);
+- if (!iptodo) {
+- QETH_DBF_TEXT(trace, 2, "dmcnomem");
+- return;
+- }
+- iptodo->type = QETH_IP_TYPE_DEL_ALL_MC;
+- spin_lock_irqsave(&card->ip_lock, flags);
+- if (!__qeth_insert_ip_todo(card, iptodo, 0))
+- kfree(iptodo);
+- spin_unlock_irqrestore(&card->ip_lock, flags);
+-}
+-
+-static void
+-qeth_add_mc(struct qeth_card *card, struct in_device *in4_dev)
+-{
+- struct qeth_ipaddr *ipm;
+- struct ip_mc_list *im4;
+- char buf[MAX_ADDR_LEN];
+-
+- QETH_DBF_TEXT(trace,4,"addmc");
+- for (im4 = in4_dev->mc_list; im4; im4 = im4->next) {
+- qeth_get_mac_for_ipm(im4->multiaddr, buf, in4_dev->dev);
+- ipm = qeth_get_addr_buffer(QETH_PROT_IPV4);
+- if (!ipm)
+- continue;
+- ipm->u.a4.addr = im4->multiaddr;
+- memcpy(ipm->mac,buf,OSA_ADDR_LEN);
+- ipm->is_multicast = 1;
+- if (!qeth_add_ip(card,ipm))
+- kfree(ipm);
+- }
+-}
+-
+-static inline void
+-qeth_add_vlan_mc(struct qeth_card *card)
+-{
+-#ifdef CONFIG_QETH_VLAN
+- struct in_device *in_dev;
+- struct vlan_group *vg;
+- int i;
+-
+- QETH_DBF_TEXT(trace,4,"addmcvl");
+- if ( ((card->options.layer2 == 0) &&
+- (!qeth_is_supported(card,IPA_FULL_VLAN))) ||
+- (card->vlangrp == NULL) )
+- return ;
+-
+- vg = card->vlangrp;
+- for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+- struct net_device *netdev = vlan_group_get_device(vg, i);
+- if (netdev == NULL ||
+- !(netdev->flags & IFF_UP))
+- continue;
+- in_dev = in_dev_get(netdev);
+- if (!in_dev)
+- continue;
+- read_lock(&in_dev->mc_list_lock);
+- qeth_add_mc(card,in_dev);
+- read_unlock(&in_dev->mc_list_lock);
+- in_dev_put(in_dev);
+- }
+-#endif
+-}
+-
+-static void
+-qeth_add_multicast_ipv4(struct qeth_card *card)
+-{
+- struct in_device *in4_dev;
+-
+- QETH_DBF_TEXT(trace,4,"chkmcv4");
+- in4_dev = in_dev_get(card->dev);
+- if (in4_dev == NULL)
+- return;
+- read_lock(&in4_dev->mc_list_lock);
+- qeth_add_mc(card, in4_dev);
+- qeth_add_vlan_mc(card);
+- read_unlock(&in4_dev->mc_list_lock);
+- in_dev_put(in4_dev);
+-}
+-
+-static void
+-qeth_layer2_add_multicast(struct qeth_card *card)
+-{
+- struct qeth_ipaddr *ipm;
+- struct dev_mc_list *dm;
+-
+- QETH_DBF_TEXT(trace,4,"L2addmc");
+- for (dm = card->dev->mc_list; dm; dm = dm->next) {
+- ipm = qeth_get_addr_buffer(QETH_PROT_IPV4);
+- if (!ipm)
+- continue;
+- memcpy(ipm->mac,dm->dmi_addr,MAX_ADDR_LEN);
+- ipm->is_multicast = 1;
+- if (!qeth_add_ip(card, ipm))
+- kfree(ipm);
+- }
+-}
+-
+-#ifdef CONFIG_QETH_IPV6
+-static void
+-qeth_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev)
+-{
+- struct qeth_ipaddr *ipm;
+- struct ifmcaddr6 *im6;
+- char buf[MAX_ADDR_LEN];
+-
+- QETH_DBF_TEXT(trace,4,"addmc6");
+- for (im6 = in6_dev->mc_list; im6 != NULL; im6 = im6->next) {
+- ndisc_mc_map(&im6->mca_addr, buf, in6_dev->dev, 0);
+- ipm = qeth_get_addr_buffer(QETH_PROT_IPV6);
+- if (!ipm)
+- continue;
+- ipm->is_multicast = 1;
+- memcpy(ipm->mac,buf,OSA_ADDR_LEN);
+- memcpy(&ipm->u.a6.addr,&im6->mca_addr.s6_addr,
+- sizeof(struct in6_addr));
+- if (!qeth_add_ip(card,ipm))
+- kfree(ipm);
+- }
+-}
+-
+-static inline void
+-qeth_add_vlan_mc6(struct qeth_card *card)
+-{
+-#ifdef CONFIG_QETH_VLAN
+- struct inet6_dev *in_dev;
+- struct vlan_group *vg;
+- int i;
+-
+- QETH_DBF_TEXT(trace,4,"admc6vl");
+- if ( ((card->options.layer2 == 0) &&
+- (!qeth_is_supported(card,IPA_FULL_VLAN))) ||
+- (card->vlangrp == NULL))
+- return ;
+-
+- vg = card->vlangrp;
+- for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+- struct net_device *netdev = vlan_group_get_device(vg, i);
+- if (netdev == NULL ||
+- !(netdev->flags & IFF_UP))
+- continue;
+- in_dev = in6_dev_get(netdev);
+- if (!in_dev)
+- continue;
+- read_lock_bh(&in_dev->lock);
+- qeth_add_mc6(card,in_dev);
+- read_unlock_bh(&in_dev->lock);
+- in6_dev_put(in_dev);
+- }
+-#endif /* CONFIG_QETH_VLAN */
+-}
+-
+-static void
+-qeth_add_multicast_ipv6(struct qeth_card *card)
+-{
+- struct inet6_dev *in6_dev;
+-
+- QETH_DBF_TEXT(trace,4,"chkmcv6");
+- if (!qeth_is_supported(card, IPA_IPV6))
+- return ;
+- in6_dev = in6_dev_get(card->dev);
+- if (in6_dev == NULL)
+- return;
+- read_lock_bh(&in6_dev->lock);
+- qeth_add_mc6(card, in6_dev);
+- qeth_add_vlan_mc6(card);
+- read_unlock_bh(&in6_dev->lock);
+- in6_dev_put(in6_dev);
+-}
+-#endif /* CONFIG_QETH_IPV6 */
+-
+-static int
+-qeth_layer2_send_setdelmac(struct qeth_card *card, __u8 *mac,
+- enum qeth_ipa_cmds ipacmd,
+- int (*reply_cb) (struct qeth_card *,
+- struct qeth_reply*,
+- unsigned long))
+-{
+- struct qeth_ipa_cmd *cmd;
+- struct qeth_cmd_buffer *iob;
+-
+- QETH_DBF_TEXT(trace, 2, "L2sdmac");
+- iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
+- cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+- cmd->data.setdelmac.mac_length = OSA_ADDR_LEN;
+- memcpy(&cmd->data.setdelmac.mac, mac, OSA_ADDR_LEN);
+- return qeth_send_ipa_cmd(card, iob, reply_cb, NULL);
+-}
+-
+-static int
+-qeth_layer2_send_setgroupmac_cb(struct qeth_card *card,
+- struct qeth_reply *reply,
+- unsigned long data)
+-{
+- struct qeth_ipa_cmd *cmd;
+- __u8 *mac;
+-
+- QETH_DBF_TEXT(trace, 2, "L2Sgmacb");
+- cmd = (struct qeth_ipa_cmd *) data;
+- mac = &cmd->data.setdelmac.mac[0];
+- /* MAC already registered, needed in couple/uncouple case */
+- if (cmd->hdr.return_code == 0x2005) {
+- PRINT_WARN("Group MAC %02x:%02x:%02x:%02x:%02x:%02x " \
+- "already existing on %s \n",
+- mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+- QETH_CARD_IFNAME(card));
+- cmd->hdr.return_code = 0;
+- }
+- if (cmd->hdr.return_code)
+- PRINT_ERR("Could not set group MAC " \
+- "%02x:%02x:%02x:%02x:%02x:%02x on %s: %x\n",
+- mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+- QETH_CARD_IFNAME(card),cmd->hdr.return_code);
+- return 0;
+-}
+-
+-static int
+-qeth_layer2_send_setgroupmac(struct qeth_card *card, __u8 *mac)
+-{
+- QETH_DBF_TEXT(trace, 2, "L2Sgmac");
+- return qeth_layer2_send_setdelmac(card, mac, IPA_CMD_SETGMAC,
+- qeth_layer2_send_setgroupmac_cb);
+-}
+-
+-static int
+-qeth_layer2_send_delgroupmac_cb(struct qeth_card *card,
+- struct qeth_reply *reply,
+- unsigned long data)
+-{
+- struct qeth_ipa_cmd *cmd;
+- __u8 *mac;
+-
+- QETH_DBF_TEXT(trace, 2, "L2Dgmacb");
+- cmd = (struct qeth_ipa_cmd *) data;
+- mac = &cmd->data.setdelmac.mac[0];
+- if (cmd->hdr.return_code)
+- PRINT_ERR("Could not delete group MAC " \
+- "%02x:%02x:%02x:%02x:%02x:%02x on %s: %x\n",
+- mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+- QETH_CARD_IFNAME(card), cmd->hdr.return_code);
+- return 0;
+-}
+-
+-static int
+-qeth_layer2_send_delgroupmac(struct qeth_card *card, __u8 *mac)
+-{
+- QETH_DBF_TEXT(trace, 2, "L2Dgmac");
+- return qeth_layer2_send_setdelmac(card, mac, IPA_CMD_DELGMAC,
+- qeth_layer2_send_delgroupmac_cb);
+-}
+-
+-static int
+-qeth_layer2_send_setmac_cb(struct qeth_card *card,
+- struct qeth_reply *reply,
+- unsigned long data)
+-{
+- struct qeth_ipa_cmd *cmd;
+-
+- QETH_DBF_TEXT(trace, 2, "L2Smaccb");
+- cmd = (struct qeth_ipa_cmd *) data;
+- if (cmd->hdr.return_code) {
+- QETH_DBF_TEXT_(trace, 2, "L2er%x", cmd->hdr.return_code);
+- card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
+- cmd->hdr.return_code = -EIO;
+- } else {
+- card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
+- memcpy(card->dev->dev_addr,cmd->data.setdelmac.mac,
+- OSA_ADDR_LEN);
+- PRINT_INFO("MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x "
+- "successfully registered on device %s\n",
+- card->dev->dev_addr[0], card->dev->dev_addr[1],
+- card->dev->dev_addr[2], card->dev->dev_addr[3],
+- card->dev->dev_addr[4], card->dev->dev_addr[5],
+- card->dev->name);
+- }
+- return 0;
+-}
+-
+-static int
+-qeth_layer2_send_setmac(struct qeth_card *card, __u8 *mac)
+-{
+- QETH_DBF_TEXT(trace, 2, "L2Setmac");
+- return qeth_layer2_send_setdelmac(card, mac, IPA_CMD_SETVMAC,
+- qeth_layer2_send_setmac_cb);
+-}
+-
+-static int
+-qeth_layer2_send_delmac_cb(struct qeth_card *card,
+- struct qeth_reply *reply,
+- unsigned long data)
+-{
+- struct qeth_ipa_cmd *cmd;
+-
+- QETH_DBF_TEXT(trace, 2, "L2Dmaccb");
+- cmd = (struct qeth_ipa_cmd *) data;
+- if (cmd->hdr.return_code) {
+- QETH_DBF_TEXT_(trace, 2, "err%d", cmd->hdr.return_code);
+- cmd->hdr.return_code = -EIO;
+- return 0;
+- }
+- card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
+-
+- return 0;
+-}
+-static int
+-qeth_layer2_send_delmac(struct qeth_card *card, __u8 *mac)
+-{
+- QETH_DBF_TEXT(trace, 2, "L2Delmac");
+- if (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
+- return 0;
+- return qeth_layer2_send_setdelmac(card, mac, IPA_CMD_DELVMAC,
+- qeth_layer2_send_delmac_cb);
+-}
+-
+-static int
+-qeth_layer2_set_mac_address(struct net_device *dev, void *p)
+-{
+- struct sockaddr *addr = p;
+- struct qeth_card *card;
+- int rc = 0;
+-
+- QETH_DBF_TEXT(trace, 3, "setmac");
+-
+- if (qeth_verify_dev(dev) != QETH_REAL_CARD) {
+- QETH_DBF_TEXT(trace, 3, "setmcINV");
+- return -EOPNOTSUPP;
+- }
+- card = (struct qeth_card *) dev->priv;
+-
+- if (!card->options.layer2) {
+- PRINT_WARN("Setting MAC address on %s is not supported "
+- "in Layer 3 mode.\n", dev->name);
+- QETH_DBF_TEXT(trace, 3, "setmcLY3");
+- return -EOPNOTSUPP;
+- }
+- if (card->info.type == QETH_CARD_TYPE_OSN) {
+- PRINT_WARN("Setting MAC address on %s is not supported.\n",
+- dev->name);
+- QETH_DBF_TEXT(trace, 3, "setmcOSN");
+- return -EOPNOTSUPP;
+- }
+- QETH_DBF_TEXT_(trace, 3, "%s", CARD_BUS_ID(card));
+- QETH_DBF_HEX(trace, 3, addr->sa_data, OSA_ADDR_LEN);
+- rc = qeth_layer2_send_delmac(card, &card->dev->dev_addr[0]);
+- if (!rc)
+- rc = qeth_layer2_send_setmac(card, addr->sa_data);
+- return rc;
+-}
+-
+-static void
+-qeth_fill_ipacmd_header(struct qeth_card *card, struct qeth_ipa_cmd *cmd,
+- __u8 command, enum qeth_prot_versions prot)
+-{
+- memset(cmd, 0, sizeof (struct qeth_ipa_cmd));
+- cmd->hdr.command = command;
+- cmd->hdr.initiator = IPA_CMD_INITIATOR_HOST;
+- cmd->hdr.seqno = card->seqno.ipa;
+- cmd->hdr.adapter_type = qeth_get_ipa_adp_type(card->info.link_type);
+- cmd->hdr.rel_adapter_no = (__u8) card->info.portno;
+- if (card->options.layer2)
+- cmd->hdr.prim_version_no = 2;
+- else
+- cmd->hdr.prim_version_no = 1;
+- cmd->hdr.param_count = 1;
+- cmd->hdr.prot_version = prot;
+- cmd->hdr.ipa_supported = 0;
+- cmd->hdr.ipa_enabled = 0;
+-}
+-
+-static struct qeth_cmd_buffer *
+-qeth_get_ipacmd_buffer(struct qeth_card *card, enum qeth_ipa_cmds ipacmd,
+- enum qeth_prot_versions prot)
+-{
+- struct qeth_cmd_buffer *iob;
+- struct qeth_ipa_cmd *cmd;
+-
+- iob = qeth_wait_for_buffer(&card->write);
+- cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+- qeth_fill_ipacmd_header(card, cmd, ipacmd, prot);
+-
+- return iob;
+-}
+-
+-static int
+-qeth_send_setdelmc(struct qeth_card *card, struct qeth_ipaddr *addr, int ipacmd)
+-{
+- int rc;
+- struct qeth_cmd_buffer *iob;
+- struct qeth_ipa_cmd *cmd;
+-
+- QETH_DBF_TEXT(trace,4,"setdelmc");
+-
+- iob = qeth_get_ipacmd_buffer(card, ipacmd, addr->proto);
+- cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+- memcpy(&cmd->data.setdelipm.mac,addr->mac, OSA_ADDR_LEN);
+- if (addr->proto == QETH_PROT_IPV6)
+- memcpy(cmd->data.setdelipm.ip6, &addr->u.a6.addr,
+- sizeof(struct in6_addr));
+- else
+- memcpy(&cmd->data.setdelipm.ip4, &addr->u.a4.addr,4);
+-
+- rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
+-
+- return rc;
+-}
+-static void
+-qeth_fill_netmask(u8 *netmask, unsigned int len)
+-{
+- int i,j;
+- for (i=0;i<16;i++) {
+- j=(len)-(i*8);
+- if (j >= 8)
+- netmask[i] = 0xff;
+- else if (j > 0)
+- netmask[i] = (u8)(0xFF00>>j);
+- else
+- netmask[i] = 0;
+- }
+-}
+-
+-static int
+-qeth_send_setdelip(struct qeth_card *card, struct qeth_ipaddr *addr,
+- int ipacmd, unsigned int flags)
+-{
+- int rc;
+- struct qeth_cmd_buffer *iob;
+- struct qeth_ipa_cmd *cmd;
+- __u8 netmask[16];
+-
+- QETH_DBF_TEXT(trace,4,"setdelip");
+- QETH_DBF_TEXT_(trace,4,"flags%02X", flags);
+-
+- iob = qeth_get_ipacmd_buffer(card, ipacmd, addr->proto);
+- cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+- if (addr->proto == QETH_PROT_IPV6) {
+- memcpy(cmd->data.setdelip6.ip_addr, &addr->u.a6.addr,
+- sizeof(struct in6_addr));
+- qeth_fill_netmask(netmask,addr->u.a6.pfxlen);
+- memcpy(cmd->data.setdelip6.mask, netmask,
+- sizeof(struct in6_addr));
+- cmd->data.setdelip6.flags = flags;
+- } else {
+- memcpy(cmd->data.setdelip4.ip_addr, &addr->u.a4.addr, 4);
+- memcpy(cmd->data.setdelip4.mask, &addr->u.a4.mask, 4);
+- cmd->data.setdelip4.flags = flags;
+- }
+-
+- rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
+-
+- return rc;
+-}
+-
+-static int
+-qeth_layer2_register_addr_entry(struct qeth_card *card,
+- struct qeth_ipaddr *addr)
+-{
+- if (!addr->is_multicast)
+- return 0;
+- QETH_DBF_TEXT(trace, 2, "setgmac");
+- QETH_DBF_HEX(trace,3,&addr->mac[0],OSA_ADDR_LEN);
+- return qeth_layer2_send_setgroupmac(card, &addr->mac[0]);
+-}
+-
+-static int
+-qeth_layer2_deregister_addr_entry(struct qeth_card *card,
+- struct qeth_ipaddr *addr)
+-{
+- if (!addr->is_multicast)
+- return 0;
+- QETH_DBF_TEXT(trace, 2, "delgmac");
+- QETH_DBF_HEX(trace,3,&addr->mac[0],OSA_ADDR_LEN);
+- return qeth_layer2_send_delgroupmac(card, &addr->mac[0]);
+-}
+-
+-static int
+-qeth_layer3_register_addr_entry(struct qeth_card *card,
+- struct qeth_ipaddr *addr)
+-{
+- char buf[50];
+- int rc;
+- int cnt = 3;
+-
+- if (addr->proto == QETH_PROT_IPV4) {
+- QETH_DBF_TEXT(trace, 2,"setaddr4");
+- QETH_DBF_HEX(trace, 3, &addr->u.a4.addr, sizeof(int));
+- } else if (addr->proto == QETH_PROT_IPV6) {
+- QETH_DBF_TEXT(trace, 2, "setaddr6");
+- QETH_DBF_HEX(trace,3,&addr->u.a6.addr,8);
+- QETH_DBF_HEX(trace,3,((char *)&addr->u.a6.addr)+8,8);
+- } else {
+- QETH_DBF_TEXT(trace, 2, "setaddr?");
+- QETH_DBF_HEX(trace, 3, addr, sizeof(struct qeth_ipaddr));
+- }
+- do {
+- if (addr->is_multicast)
+- rc = qeth_send_setdelmc(card, addr, IPA_CMD_SETIPM);
+- else
+- rc = qeth_send_setdelip(card, addr, IPA_CMD_SETIP,
+- addr->set_flags);
+- if (rc)
+- QETH_DBF_TEXT(trace, 2, "failed");
+- } while ((--cnt > 0) && rc);
+- if (rc){
+- QETH_DBF_TEXT(trace, 2, "FAILED");
+- qeth_ipaddr_to_string(addr->proto, (u8 *)&addr->u, buf);
+- PRINT_WARN("Could not register IP address %s (rc=0x%x/%d)\n",
+- buf, rc, rc);
+- }
+- return rc;
+-}
+-
+-static int
+-qeth_layer3_deregister_addr_entry(struct qeth_card *card,
+- struct qeth_ipaddr *addr)
+-{
+- //char buf[50];
+- int rc;
+-
+- if (addr->proto == QETH_PROT_IPV4) {
+- QETH_DBF_TEXT(trace, 2,"deladdr4");
+- QETH_DBF_HEX(trace, 3, &addr->u.a4.addr, sizeof(int));
+- } else if (addr->proto == QETH_PROT_IPV6) {
+- QETH_DBF_TEXT(trace, 2, "deladdr6");
+- QETH_DBF_HEX(trace,3,&addr->u.a6.addr,8);
+- QETH_DBF_HEX(trace,3,((char *)&addr->u.a6.addr)+8,8);
+- } else {
+- QETH_DBF_TEXT(trace, 2, "deladdr?");
+- QETH_DBF_HEX(trace, 3, addr, sizeof(struct qeth_ipaddr));
+- }
+- if (addr->is_multicast)
+- rc = qeth_send_setdelmc(card, addr, IPA_CMD_DELIPM);
+- else
+- rc = qeth_send_setdelip(card, addr, IPA_CMD_DELIP,
+- addr->del_flags);
+- if (rc) {
+- QETH_DBF_TEXT(trace, 2, "failed");
+- /* TODO: re-activate this warning as soon as we have a
+- * clean mirco code
+- qeth_ipaddr_to_string(addr->proto, (u8 *)&addr->u, buf);
+- PRINT_WARN("Could not deregister IP address %s (rc=%x)\n",
+- buf, rc);
+- */
+- }
+- return rc;
+-}
+-
+-static int
+-qeth_register_addr_entry(struct qeth_card *card, struct qeth_ipaddr *addr)
+-{
+- if (card->options.layer2)
+- return qeth_layer2_register_addr_entry(card, addr);
+-
+- return qeth_layer3_register_addr_entry(card, addr);
+-}
+-
+-static int
+-qeth_deregister_addr_entry(struct qeth_card *card, struct qeth_ipaddr *addr)
+-{
+- if (card->options.layer2)
+- return qeth_layer2_deregister_addr_entry(card, addr);
+-
+- return qeth_layer3_deregister_addr_entry(card, addr);
+-}
+-
+-static u32
+-qeth_ethtool_get_tx_csum(struct net_device *dev)
+-{
+- return (dev->features & NETIF_F_HW_CSUM) != 0;
+-}
+-
+-static int
+-qeth_ethtool_set_tx_csum(struct net_device *dev, u32 data)
+-{
+- if (data)
+- dev->features |= NETIF_F_HW_CSUM;
+- else
+- dev->features &= ~NETIF_F_HW_CSUM;
+-
+- return 0;
+-}
+-
+-static u32
+-qeth_ethtool_get_rx_csum(struct net_device *dev)
+-{
+- struct qeth_card *card = (struct qeth_card *)dev->priv;
+-
+- return (card->options.checksum_type == HW_CHECKSUMMING);
+-}
+-
+-static int
+-qeth_ethtool_set_rx_csum(struct net_device *dev, u32 data)
+-{
+- struct qeth_card *card = (struct qeth_card *)dev->priv;
+-
+- if ((card->state != CARD_STATE_DOWN) &&
+- (card->state != CARD_STATE_RECOVER))
+- return -EPERM;
+- if (data)
+- card->options.checksum_type = HW_CHECKSUMMING;
+- else
+- card->options.checksum_type = SW_CHECKSUMMING;
+- return 0;
+-}
+-
+-static u32
+-qeth_ethtool_get_sg(struct net_device *dev)
+-{
+- struct qeth_card *card = (struct qeth_card *)dev->priv;
+-
+- return ((card->options.large_send != QETH_LARGE_SEND_NO) &&
+- (dev->features & NETIF_F_SG));
+-}
+-
+-static int
+-qeth_ethtool_set_sg(struct net_device *dev, u32 data)
+-{
+- struct qeth_card *card = (struct qeth_card *)dev->priv;
+-
+- if (data) {
+- if (card->options.large_send != QETH_LARGE_SEND_NO)
+- dev->features |= NETIF_F_SG;
+- else {
+- dev->features &= ~NETIF_F_SG;
+- return -EINVAL;
+- }
+- } else
+- dev->features &= ~NETIF_F_SG;
+- return 0;
+-}
+-
+-static u32
+-qeth_ethtool_get_tso(struct net_device *dev)
+-{
+- struct qeth_card *card = (struct qeth_card *)dev->priv;
+-
+- return ((card->options.large_send != QETH_LARGE_SEND_NO) &&
+- (dev->features & NETIF_F_TSO));
+-}
+-
+-static int
+-qeth_ethtool_set_tso(struct net_device *dev, u32 data)
+-{
+- struct qeth_card *card = (struct qeth_card *)dev->priv;
+-
+- if (data) {
+- if (card->options.large_send != QETH_LARGE_SEND_NO)
+- dev->features |= NETIF_F_TSO;
+- else {
+- dev->features &= ~NETIF_F_TSO;
+- return -EINVAL;
+- }
+- } else
+- dev->features &= ~NETIF_F_TSO;
+- return 0;
+-}
+-
+-static struct ethtool_ops qeth_ethtool_ops = {
+- .get_tx_csum = qeth_ethtool_get_tx_csum,
+- .set_tx_csum = qeth_ethtool_set_tx_csum,
+- .get_rx_csum = qeth_ethtool_get_rx_csum,
+- .set_rx_csum = qeth_ethtool_set_rx_csum,
+- .get_sg = qeth_ethtool_get_sg,
+- .set_sg = qeth_ethtool_set_sg,
+- .get_tso = qeth_ethtool_get_tso,
+- .set_tso = qeth_ethtool_set_tso,
+-};
+-
+-static int
+-qeth_hard_header_parse(const struct sk_buff *skb, unsigned char *haddr)
+-{
+- const struct qeth_card *card;
+- const struct ethhdr *eth;
+- struct net_device *dev = skb->dev;
+-
+- if (dev->type != ARPHRD_IEEE802_TR)
+- return 0;
+-
+- card = qeth_get_card_from_dev(dev);
+- if (card->options.layer2)
+- goto haveheader;
+-#ifdef CONFIG_QETH_IPV6
+- /* cause of the manipulated arp constructor and the ARP
+- flag for OSAE devices we have some nasty exceptions */
+- if (card->info.type == QETH_CARD_TYPE_OSAE) {
+- if (!card->options.fake_ll) {
+- if ((skb->pkt_type==PACKET_OUTGOING) &&
+- (skb->protocol==ETH_P_IPV6))
+- goto haveheader;
+- else
+- return 0;
+- } else {
+- if ((skb->pkt_type==PACKET_OUTGOING) &&
+- (skb->protocol==ETH_P_IP))
+- return 0;
+- else
+- goto haveheader;
+- }
+- }
+-#endif
+- if (!card->options.fake_ll)
+- return 0;
+-haveheader:
+- eth = eth_hdr(skb);
+- memcpy(haddr, eth->h_source, ETH_ALEN);
+- return ETH_ALEN;
+-}
+-
+-static const struct header_ops qeth_null_ops = {
+- .parse = qeth_hard_header_parse,
+-};
+-
+-static int
+-qeth_netdev_init(struct net_device *dev)
+-{
+- struct qeth_card *card;
+-
+- card = (struct qeth_card *) dev->priv;
+-
+- QETH_DBF_TEXT(trace,3,"initdev");
+-
+- dev->tx_timeout = &qeth_tx_timeout;
+- dev->watchdog_timeo = QETH_TX_TIMEOUT;
+- dev->open = qeth_open;
+- dev->stop = qeth_stop;
+- dev->hard_start_xmit = qeth_hard_start_xmit;
+- dev->do_ioctl = qeth_do_ioctl;
+- dev->get_stats = qeth_get_stats;
+- dev->change_mtu = qeth_change_mtu;
+- dev->neigh_setup = qeth_neigh_setup;
+- dev->set_multicast_list = qeth_set_multicast_list;
+-#ifdef CONFIG_QETH_VLAN
+- dev->vlan_rx_register = qeth_vlan_rx_register;
+- dev->vlan_rx_kill_vid = qeth_vlan_rx_kill_vid;
+- dev->vlan_rx_add_vid = qeth_vlan_rx_add_vid;
+-#endif
+- if (qeth_get_netdev_flags(card) & IFF_NOARP)
+- dev->header_ops = &qeth_null_ops;
+-
+-#ifdef CONFIG_QETH_IPV6
+- /*IPv6 address autoconfiguration stuff*/
+- if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD))
+- card->dev->dev_id = card->info.unique_id & 0xffff;
+-#endif
+- if (card->options.fake_ll &&
+- (qeth_get_netdev_flags(card) & IFF_NOARP))
+- dev->header_ops = &qeth_fake_ops;
+-
+- dev->set_mac_address = qeth_layer2_set_mac_address;
+- dev->flags |= qeth_get_netdev_flags(card);
+- if ((card->options.fake_broadcast) ||
+- (card->info.broadcast_capable))
+- dev->flags |= IFF_BROADCAST;
+- dev->hard_header_len =
+- qeth_get_hlen(card->info.link_type) + card->options.add_hhlen;
+- dev->addr_len = OSA_ADDR_LEN;
+- dev->mtu = card->info.initial_mtu;
+- if (card->info.type != QETH_CARD_TYPE_OSN)
+- SET_ETHTOOL_OPS(dev, &qeth_ethtool_ops);
+- return 0;
+-}
+-
+-static void
+-qeth_init_func_level(struct qeth_card *card)
+-{
+- if (card->ipato.enabled) {
+- if (card->info.type == QETH_CARD_TYPE_IQD)
+- card->info.func_level =
+- QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT;
+- else
+- card->info.func_level =
+- QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT;
+- } else {
+- if (card->info.type == QETH_CARD_TYPE_IQD)
+- /*FIXME:why do we have same values for dis and ena for osae??? */
+- card->info.func_level =
+- QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT;
+- else
+- card->info.func_level =
+- QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT;
+- }
+-}
+-
+-/**
+- * hardsetup card, initialize MPC and QDIO stuff
+- */
+-static int
+-qeth_hardsetup_card(struct qeth_card *card)
+-{
+- int retries = 3;
+- int rc;
+-
+- QETH_DBF_TEXT(setup, 2, "hrdsetup");
+-
+- atomic_set(&card->force_alloc_skb, 0);
+-retry:
+- if (retries < 3){
+- PRINT_WARN("Retrying to do IDX activates.\n");
+- ccw_device_set_offline(CARD_DDEV(card));
+- ccw_device_set_offline(CARD_WDEV(card));
+- ccw_device_set_offline(CARD_RDEV(card));
+- ccw_device_set_online(CARD_RDEV(card));
+- ccw_device_set_online(CARD_WDEV(card));
+- ccw_device_set_online(CARD_DDEV(card));
+- }
+- rc = qeth_qdio_clear_card(card,card->info.type!=QETH_CARD_TYPE_IQD);
+- if (rc == -ERESTARTSYS) {
+- QETH_DBF_TEXT(setup, 2, "break1");
+- return rc;
+- } else if (rc) {
+- QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+- if (--retries < 0)
+- goto out;
+- else
+- goto retry;
+- }
+- if ((rc = qeth_get_unitaddr(card))){
+- QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+- return rc;
+- }
+- qeth_init_tokens(card);
+- qeth_init_func_level(card);
+- rc = qeth_idx_activate_channel(&card->read, qeth_idx_read_cb);
+- if (rc == -ERESTARTSYS) {
+- QETH_DBF_TEXT(setup, 2, "break2");
+- return rc;
+- } else if (rc) {
+- QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+- if (--retries < 0)
+- goto out;
+- else
+- goto retry;
+- }
+- rc = qeth_idx_activate_channel(&card->write, qeth_idx_write_cb);
+- if (rc == -ERESTARTSYS) {
+- QETH_DBF_TEXT(setup, 2, "break3");
+- return rc;
+- } else if (rc) {
+- QETH_DBF_TEXT_(setup, 2, "4err%d", rc);
+- if (--retries < 0)
+- goto out;
+- else
+- goto retry;
+- }
+- if ((rc = qeth_mpc_initialize(card))){
+- QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
+- goto out;
+- }
+- /*network device will be recovered*/
+- if (card->dev) {
+- card->dev->header_ops = card->orig_header_ops;
+- if (card->options.fake_ll &&
+- (qeth_get_netdev_flags(card) & IFF_NOARP))
+- card->dev->header_ops = &qeth_fake_ops;
+- return 0;
+- }
+- /* at first set_online allocate netdev */
+- card->dev = qeth_get_netdevice(card->info.type,
+- card->info.link_type);
+- if (!card->dev){
+- qeth_qdio_clear_card(card, card->info.type !=
+- QETH_CARD_TYPE_IQD);
+- rc = -ENODEV;
+- QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
+- goto out;
+- }
+- card->dev->priv = card;
+- card->orig_header_ops = card->dev->header_ops;
+- card->dev->type = qeth_get_arphdr_type(card->info.type,
+- card->info.link_type);
+- card->dev->init = qeth_netdev_init;
+- return 0;
+-out:
+- PRINT_ERR("Initialization in hardsetup failed! rc=%d\n", rc);
+- return rc;
+-}
+-
+-static int
+-qeth_default_setassparms_cb(struct qeth_card *card, struct qeth_reply *reply,
+- unsigned long data)
+-{
+- struct qeth_ipa_cmd *cmd;
+-
+- QETH_DBF_TEXT(trace,4,"defadpcb");
+-
+- cmd = (struct qeth_ipa_cmd *) data;
+- if (cmd->hdr.return_code == 0){
+- cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code;
+- if (cmd->hdr.prot_version == QETH_PROT_IPV4)
+- card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
+-#ifdef CONFIG_QETH_IPV6
+- if (cmd->hdr.prot_version == QETH_PROT_IPV6)
+- card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
+-#endif
+- }
+- if (cmd->data.setassparms.hdr.assist_no == IPA_INBOUND_CHECKSUM &&
+- cmd->data.setassparms.hdr.command_code == IPA_CMD_ASS_START) {
+- card->info.csum_mask = cmd->data.setassparms.data.flags_32bit;
+- QETH_DBF_TEXT_(trace, 3, "csum:%d", card->info.csum_mask);
+- }
+- return 0;
+-}
+-
+-static int
+-qeth_default_setadapterparms_cb(struct qeth_card *card,
+- struct qeth_reply *reply,
+- unsigned long data)
+-{
+- struct qeth_ipa_cmd *cmd;
+-
+- QETH_DBF_TEXT(trace,4,"defadpcb");
+-
+- cmd = (struct qeth_ipa_cmd *) data;
+- if (cmd->hdr.return_code == 0)
+- cmd->hdr.return_code = cmd->data.setadapterparms.hdr.return_code;
+- return 0;
+-}
+-
+-
+-
+-static int
+-qeth_query_setadapterparms_cb(struct qeth_card *card, struct qeth_reply *reply,
+- unsigned long data)
+-{
+- struct qeth_ipa_cmd *cmd;
+-
+- QETH_DBF_TEXT(trace,3,"quyadpcb");
+-
+- cmd = (struct qeth_ipa_cmd *) data;
+- if (cmd->data.setadapterparms.data.query_cmds_supp.lan_type & 0x7f)
+- card->info.link_type =
+- cmd->data.setadapterparms.data.query_cmds_supp.lan_type;
+- card->options.adp.supported_funcs =
+- cmd->data.setadapterparms.data.query_cmds_supp.supported_cmds;
+- return qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
+-}
+-
+-static int
+-qeth_query_setadapterparms(struct qeth_card *card)
+-{
+- int rc;
+- struct qeth_cmd_buffer *iob;
+-
+- QETH_DBF_TEXT(trace,3,"queryadp");
+- iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_COMMANDS_SUPPORTED,
+- sizeof(struct qeth_ipacmd_setadpparms));
+- rc = qeth_send_ipa_cmd(card, iob, qeth_query_setadapterparms_cb, NULL);
+- return rc;
+-}
+-
+-static int
+-qeth_setadpparms_change_macaddr_cb(struct qeth_card *card,
+- struct qeth_reply *reply,
+- unsigned long data)
+-{
+- struct qeth_ipa_cmd *cmd;
+-
+- QETH_DBF_TEXT(trace,4,"chgmaccb");
+-
+- cmd = (struct qeth_ipa_cmd *) data;
+- if (!card->options.layer2 ||
+- !(card->info.mac_bits & QETH_LAYER2_MAC_READ)) {
+- memcpy(card->dev->dev_addr,
+- &cmd->data.setadapterparms.data.change_addr.addr,
+- OSA_ADDR_LEN);
+- card->info.mac_bits |= QETH_LAYER2_MAC_READ;
+- }
+- qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
+- return 0;
+-}
+-
+-static int
+-qeth_setadpparms_change_macaddr(struct qeth_card *card)
+-{
+- int rc;
+- struct qeth_cmd_buffer *iob;
+- struct qeth_ipa_cmd *cmd;
+-
+- QETH_DBF_TEXT(trace,4,"chgmac");
+-
+- iob = qeth_get_adapter_cmd(card,IPA_SETADP_ALTER_MAC_ADDRESS,
+- sizeof(struct qeth_ipacmd_setadpparms));
+- cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+- cmd->data.setadapterparms.data.change_addr.cmd = CHANGE_ADDR_READ_MAC;
+- cmd->data.setadapterparms.data.change_addr.addr_size = OSA_ADDR_LEN;
+- memcpy(&cmd->data.setadapterparms.data.change_addr.addr,
+- card->dev->dev_addr, OSA_ADDR_LEN);
+- rc = qeth_send_ipa_cmd(card, iob, qeth_setadpparms_change_macaddr_cb,
+- NULL);
+- return rc;
+-}
+-
+-static int
+-qeth_send_setadp_mode(struct qeth_card *card, __u32 command, __u32 mode)
+-{
+- int rc;
+- struct qeth_cmd_buffer *iob;
+- struct qeth_ipa_cmd *cmd;
+-
+- QETH_DBF_TEXT(trace,4,"adpmode");
+-
+- iob = qeth_get_adapter_cmd(card, command,
+- sizeof(struct qeth_ipacmd_setadpparms));
+- cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+- cmd->data.setadapterparms.data.mode = mode;
+- rc = qeth_send_ipa_cmd(card, iob, qeth_default_setadapterparms_cb,
+- NULL);
+- return rc;
+-}
+-
+-static int
+-qeth_setadapter_hstr(struct qeth_card *card)
+-{
+- int rc;
+-
+- QETH_DBF_TEXT(trace,4,"adphstr");
+-
+- if (qeth_adp_supported(card,IPA_SETADP_SET_BROADCAST_MODE)) {
+- rc = qeth_send_setadp_mode(card, IPA_SETADP_SET_BROADCAST_MODE,
+- card->options.broadcast_mode);
+- if (rc)
+- PRINT_WARN("couldn't set broadcast mode on "
+- "device %s: x%x\n",
+- CARD_BUS_ID(card), rc);
+- rc = qeth_send_setadp_mode(card, IPA_SETADP_ALTER_MAC_ADDRESS,
+- card->options.macaddr_mode);
+- if (rc)
+- PRINT_WARN("couldn't set macaddr mode on "
+- "device %s: x%x\n", CARD_BUS_ID(card), rc);
+- return rc;
+- }
+- if (card->options.broadcast_mode == QETH_TR_BROADCAST_LOCAL)
+- PRINT_WARN("set adapter parameters not available "
+- "to set broadcast mode, using ALLRINGS "
+- "on device %s:\n", CARD_BUS_ID(card));
+- if (card->options.macaddr_mode == QETH_TR_MACADDR_CANONICAL)
+- PRINT_WARN("set adapter parameters not available "
+- "to set macaddr mode, using NONCANONICAL "
+- "on device %s:\n", CARD_BUS_ID(card));
+- return 0;
+-}
+-
+-static int
+-qeth_setadapter_parms(struct qeth_card *card)
+-{
+- int rc;
+-
+- QETH_DBF_TEXT(setup, 2, "setadprm");
+-
+- if (!qeth_is_supported(card, IPA_SETADAPTERPARMS)){
+- PRINT_WARN("set adapter parameters not supported "
+- "on device %s.\n",
+- CARD_BUS_ID(card));
+- QETH_DBF_TEXT(setup, 2, " notsupp");
+- return 0;
+- }
+- rc = qeth_query_setadapterparms(card);
+- if (rc) {
+- PRINT_WARN("couldn't set adapter parameters on device %s: "
+- "x%x\n", CARD_BUS_ID(card), rc);
+- return rc;
+- }
+- if (qeth_adp_supported(card,IPA_SETADP_ALTER_MAC_ADDRESS)) {
+- rc = qeth_setadpparms_change_macaddr(card);
+- if (rc)
+- PRINT_WARN("couldn't get MAC address on "
+- "device %s: x%x\n",
+- CARD_BUS_ID(card), rc);
+- }
+-
+- if ((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
+- (card->info.link_type == QETH_LINK_TYPE_LANE_TR))
+- rc = qeth_setadapter_hstr(card);
+-
+- return rc;
+-}
+-
+-static int
+-qeth_layer2_initialize(struct qeth_card *card)
+-{
+- int rc = 0;
+-
+-
+- QETH_DBF_TEXT(setup, 2, "doL2init");
+- QETH_DBF_TEXT_(setup, 2, "doL2%s", CARD_BUS_ID(card));
+-
+- rc = qeth_query_setadapterparms(card);
+- if (rc) {
+- PRINT_WARN("could not query adapter parameters on device %s: "
+- "x%x\n", CARD_BUS_ID(card), rc);
+- }
+-
+- rc = qeth_setadpparms_change_macaddr(card);
+- if (rc) {
+- PRINT_WARN("couldn't get MAC address on "
+- "device %s: x%x\n",
+- CARD_BUS_ID(card), rc);
+- QETH_DBF_TEXT_(setup, 2,"1err%d",rc);
+- return rc;
+- }
+- QETH_DBF_HEX(setup,2, card->dev->dev_addr, OSA_ADDR_LEN);
+-
+- rc = qeth_layer2_send_setmac(card, &card->dev->dev_addr[0]);
+- if (rc)
+- QETH_DBF_TEXT_(setup, 2,"2err%d",rc);
+- return 0;
+-}
+-
+-
+-static int
+-qeth_send_startstoplan(struct qeth_card *card, enum qeth_ipa_cmds ipacmd,
+- enum qeth_prot_versions prot)
+-{
+- int rc;
+- struct qeth_cmd_buffer *iob;
+-
+- iob = qeth_get_ipacmd_buffer(card,ipacmd,prot);
+- rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
+-
+- return rc;
+-}
+-
+-static int
+-qeth_send_startlan(struct qeth_card *card, enum qeth_prot_versions prot)
+-{
+- int rc;
+-
+- QETH_DBF_TEXT_(setup, 2, "strtlan%i", prot);
+-
+- rc = qeth_send_startstoplan(card, IPA_CMD_STARTLAN, prot);
+- return rc;
+-}
+-
+-static int
+-qeth_send_stoplan(struct qeth_card *card)
+-{
+- int rc = 0;
+-
+- /*
+- * TODO: according to the IPA format document page 14,
+- * TCP/IP (we!) never issue a STOPLAN
+- * is this right ?!?
+- */
+- QETH_DBF_TEXT(trace, 2, "stoplan");
+-
+- rc = qeth_send_startstoplan(card, IPA_CMD_STOPLAN, QETH_PROT_IPV4);
+- return rc;
+-}
+-
+-static int
+-qeth_query_ipassists_cb(struct qeth_card *card, struct qeth_reply *reply,
+- unsigned long data)
+-{
+- struct qeth_ipa_cmd *cmd;
+-
+- QETH_DBF_TEXT(setup, 2, "qipasscb");
+-
+- cmd = (struct qeth_ipa_cmd *) data;
+- if (cmd->hdr.prot_version == QETH_PROT_IPV4) {
+- card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported;
+- card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
+- /* Disable IPV6 support hard coded for Hipersockets */
+- if(card->info.type == QETH_CARD_TYPE_IQD)
+- card->options.ipa4.supported_funcs &= ~IPA_IPV6;
+- } else {
+-#ifdef CONFIG_QETH_IPV6
+- card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported;
+- card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
+-#endif
+- }
+- QETH_DBF_TEXT(setup, 2, "suppenbl");
+- QETH_DBF_TEXT_(setup, 2, "%x",cmd->hdr.ipa_supported);
+- QETH_DBF_TEXT_(setup, 2, "%x",cmd->hdr.ipa_enabled);
+- return 0;
+-}
+-
+-static int
+-qeth_query_ipassists(struct qeth_card *card, enum qeth_prot_versions prot)
+-{
+- int rc;
+- struct qeth_cmd_buffer *iob;
+-
+- QETH_DBF_TEXT_(setup, 2, "qipassi%i", prot);
+- if (card->options.layer2) {
+- QETH_DBF_TEXT(setup, 2, "noprmly2");
+- return -EPERM;
+- }
+-
+- iob = qeth_get_ipacmd_buffer(card,IPA_CMD_QIPASSIST,prot);
+- rc = qeth_send_ipa_cmd(card, iob, qeth_query_ipassists_cb, NULL);
+- return rc;
+-}
+-
+-static struct qeth_cmd_buffer *
+-qeth_get_setassparms_cmd(struct qeth_card *card, enum qeth_ipa_funcs ipa_func,
+- __u16 cmd_code, __u16 len,
+- enum qeth_prot_versions prot)
+-{
+- struct qeth_cmd_buffer *iob;
+- struct qeth_ipa_cmd *cmd;
+-
+- QETH_DBF_TEXT(trace,4,"getasscm");
+- iob = qeth_get_ipacmd_buffer(card,IPA_CMD_SETASSPARMS,prot);
+-
+- cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+- cmd->data.setassparms.hdr.assist_no = ipa_func;
+- cmd->data.setassparms.hdr.length = 8 + len;
+- cmd->data.setassparms.hdr.command_code = cmd_code;
+- cmd->data.setassparms.hdr.return_code = 0;
+- cmd->data.setassparms.hdr.seq_no = 0;
+-
+- return iob;
+-}
+-
+-static int
+-qeth_send_setassparms(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+- __u16 len, long data,
+- int (*reply_cb)
+- (struct qeth_card *,struct qeth_reply *,unsigned long),
+- void *reply_param)
+-{
+- int rc;
+- struct qeth_ipa_cmd *cmd;
+-
+- QETH_DBF_TEXT(trace,4,"sendassp");
+-
+- cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+- if (len <= sizeof(__u32))
+- cmd->data.setassparms.data.flags_32bit = (__u32) data;
+- else /* (len > sizeof(__u32)) */
+- memcpy(&cmd->data.setassparms.data, (void *) data, len);
+-
+- rc = qeth_send_ipa_cmd(card, iob, reply_cb, reply_param);
+- return rc;
+-}
+-
+-#ifdef CONFIG_QETH_IPV6
+-static int
+-qeth_send_simple_setassparms_ipv6(struct qeth_card *card,
+- enum qeth_ipa_funcs ipa_func, __u16 cmd_code)
+-
+-{
+- int rc;
+- struct qeth_cmd_buffer *iob;
+-
+- QETH_DBF_TEXT(trace,4,"simassp6");
+- iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code,
+- 0, QETH_PROT_IPV6);
+- rc = qeth_send_setassparms(card, iob, 0, 0,
+- qeth_default_setassparms_cb, NULL);
+- return rc;
+-}
+-#endif
+-
+-static int
+-qeth_send_simple_setassparms(struct qeth_card *card,
+- enum qeth_ipa_funcs ipa_func,
+- __u16 cmd_code, long data)
+-{
+- int rc;
+- int length = 0;
+- struct qeth_cmd_buffer *iob;
+-
+- QETH_DBF_TEXT(trace,4,"simassp4");
+- if (data)
+- length = sizeof(__u32);
+- iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code,
+- length, QETH_PROT_IPV4);
+- rc = qeth_send_setassparms(card, iob, length, data,
+- qeth_default_setassparms_cb, NULL);
+- return rc;
+-}
+-
+-static int
+-qeth_start_ipa_arp_processing(struct qeth_card *card)
+-{
+- int rc;
+-
+- QETH_DBF_TEXT(trace,3,"ipaarp");
+-
+- if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
+- PRINT_WARN("ARP processing not supported "
+- "on %s!\n", QETH_CARD_IFNAME(card));
+- return 0;
+- }
+- rc = qeth_send_simple_setassparms(card,IPA_ARP_PROCESSING,
+- IPA_CMD_ASS_START, 0);
+- if (rc) {
+- PRINT_WARN("Could not start ARP processing "
+- "assist on %s: 0x%x\n",
+- QETH_CARD_IFNAME(card), rc);
+- }
+- return rc;
+-}
+-
+-static int
+-qeth_start_ipa_ip_fragmentation(struct qeth_card *card)
+-{
+- int rc;
+-
+- QETH_DBF_TEXT(trace,3,"ipaipfrg");
+-
+- if (!qeth_is_supported(card, IPA_IP_FRAGMENTATION)) {
+- PRINT_INFO("Hardware IP fragmentation not supported on %s\n",
+- QETH_CARD_IFNAME(card));
+- return -EOPNOTSUPP;
+- }
+-
+- rc = qeth_send_simple_setassparms(card, IPA_IP_FRAGMENTATION,
+- IPA_CMD_ASS_START, 0);
+- if (rc) {
+- PRINT_WARN("Could not start Hardware IP fragmentation "
+- "assist on %s: 0x%x\n",
+- QETH_CARD_IFNAME(card), rc);
+- } else
+- PRINT_INFO("Hardware IP fragmentation enabled \n");
+- return rc;
+-}
+-
+-static int
+-qeth_start_ipa_source_mac(struct qeth_card *card)
+-{
+- int rc;
+-
+- QETH_DBF_TEXT(trace,3,"stsrcmac");
+-
+- if (!card->options.fake_ll)
+- return -EOPNOTSUPP;
+-
+- if (!qeth_is_supported(card, IPA_SOURCE_MAC)) {
+- PRINT_INFO("Inbound source address not "
+- "supported on %s\n", QETH_CARD_IFNAME(card));
+- return -EOPNOTSUPP;
+- }
+-
+- rc = qeth_send_simple_setassparms(card, IPA_SOURCE_MAC,
+- IPA_CMD_ASS_START, 0);
+- if (rc)
+- PRINT_WARN("Could not start inbound source "
+- "assist on %s: 0x%x\n",
+- QETH_CARD_IFNAME(card), rc);
+- return rc;
+-}
+-
+-static int
+-qeth_start_ipa_vlan(struct qeth_card *card)
+-{
+- int rc = 0;
+-
+- QETH_DBF_TEXT(trace,3,"strtvlan");
+-
+-#ifdef CONFIG_QETH_VLAN
+- if (!qeth_is_supported(card, IPA_FULL_VLAN)) {
+- PRINT_WARN("VLAN not supported on %s\n", QETH_CARD_IFNAME(card));
+- return -EOPNOTSUPP;
+- }
+-
+- rc = qeth_send_simple_setassparms(card, IPA_VLAN_PRIO,
+- IPA_CMD_ASS_START,0);
+- if (rc) {
+- PRINT_WARN("Could not start vlan "
+- "assist on %s: 0x%x\n",
+- QETH_CARD_IFNAME(card), rc);
+- } else {
+- PRINT_INFO("VLAN enabled \n");
+- card->dev->features |=
+- NETIF_F_HW_VLAN_FILTER |
+- NETIF_F_HW_VLAN_TX |
+- NETIF_F_HW_VLAN_RX;
+- }
+-#endif /* QETH_VLAN */
+- return rc;
+-}
+-
+-static int
+-qeth_start_ipa_multicast(struct qeth_card *card)
+-{
+- int rc;
+-
+- QETH_DBF_TEXT(trace,3,"stmcast");
+-
+- if (!qeth_is_supported(card, IPA_MULTICASTING)) {
+- PRINT_WARN("Multicast not supported on %s\n",
+- QETH_CARD_IFNAME(card));
+- return -EOPNOTSUPP;
+- }
+-
+- rc = qeth_send_simple_setassparms(card, IPA_MULTICASTING,
+- IPA_CMD_ASS_START,0);
+- if (rc) {
+- PRINT_WARN("Could not start multicast "
+- "assist on %s: rc=%i\n",
+- QETH_CARD_IFNAME(card), rc);
+- } else {
+- PRINT_INFO("Multicast enabled\n");
+- card->dev->flags |= IFF_MULTICAST;
+- }
+- return rc;
+-}
+-
+-#ifdef CONFIG_QETH_IPV6
+-static int
+-qeth_softsetup_ipv6(struct qeth_card *card)
+-{
+- int rc;
+-
+- QETH_DBF_TEXT(trace,3,"softipv6");
+-
+- rc = qeth_send_startlan(card, QETH_PROT_IPV6);
+- if (rc) {
+- PRINT_ERR("IPv6 startlan failed on %s\n",
+- QETH_CARD_IFNAME(card));
+- return rc;
+- }
+- rc = qeth_query_ipassists(card,QETH_PROT_IPV6);
+- if (rc) {
+- PRINT_ERR("IPv6 query ipassist failed on %s\n",
+- QETH_CARD_IFNAME(card));
+- return rc;
+- }
+- rc = qeth_send_simple_setassparms(card, IPA_IPV6,
+- IPA_CMD_ASS_START, 3);
+- if (rc) {
+- PRINT_WARN("IPv6 start assist (version 4) failed "
+- "on %s: 0x%x\n",
+- QETH_CARD_IFNAME(card), rc);
+- return rc;
+- }
+- rc = qeth_send_simple_setassparms_ipv6(card, IPA_IPV6,
+- IPA_CMD_ASS_START);
+- if (rc) {
+- PRINT_WARN("IPV6 start assist (version 6) failed "
+- "on %s: 0x%x\n",
+- QETH_CARD_IFNAME(card), rc);
+- return rc;
+- }
+- rc = qeth_send_simple_setassparms_ipv6(card, IPA_PASSTHRU,
+- IPA_CMD_ASS_START);
+- if (rc) {
+- PRINT_WARN("Could not enable passthrough "
+- "on %s: 0x%x\n",
+- QETH_CARD_IFNAME(card), rc);
+- return rc;
+- }
+- PRINT_INFO("IPV6 enabled \n");
+- return 0;
+-}
+-
+-#endif
+-
+-static int
+-qeth_start_ipa_ipv6(struct qeth_card *card)
+-{
+- int rc = 0;
+-#ifdef CONFIG_QETH_IPV6
+- QETH_DBF_TEXT(trace,3,"strtipv6");
+-
+- if (!qeth_is_supported(card, IPA_IPV6)) {
+- PRINT_WARN("IPv6 not supported on %s\n",
+- QETH_CARD_IFNAME(card));
+- return 0;
+- }
+- rc = qeth_softsetup_ipv6(card);
+-#endif
+- return rc ;
+-}
+-
+-static int
+-qeth_start_ipa_broadcast(struct qeth_card *card)
+-{
+- int rc;
+-
+- QETH_DBF_TEXT(trace,3,"stbrdcst");
+- card->info.broadcast_capable = 0;
+- if (!qeth_is_supported(card, IPA_FILTERING)) {
+- PRINT_WARN("Broadcast not supported on %s\n",
+- QETH_CARD_IFNAME(card));
+- rc = -EOPNOTSUPP;
+- goto out;
+- }
+- rc = qeth_send_simple_setassparms(card, IPA_FILTERING,
+- IPA_CMD_ASS_START, 0);
+- if (rc) {
+- PRINT_WARN("Could not enable broadcasting filtering "
+- "on %s: 0x%x\n",
+- QETH_CARD_IFNAME(card), rc);
+- goto out;
+- }
+-
+- rc = qeth_send_simple_setassparms(card, IPA_FILTERING,
+- IPA_CMD_ASS_CONFIGURE, 1);
+- if (rc) {
+- PRINT_WARN("Could not set up broadcast filtering on %s: 0x%x\n",
+- QETH_CARD_IFNAME(card), rc);
+- goto out;
+- }
+- card->info.broadcast_capable = QETH_BROADCAST_WITH_ECHO;
+- PRINT_INFO("Broadcast enabled \n");
+- rc = qeth_send_simple_setassparms(card, IPA_FILTERING,
+- IPA_CMD_ASS_ENABLE, 1);
+- if (rc) {
+- PRINT_WARN("Could not set up broadcast echo filtering on "
+- "%s: 0x%x\n", QETH_CARD_IFNAME(card), rc);
+- goto out;
+- }
+- card->info.broadcast_capable = QETH_BROADCAST_WITHOUT_ECHO;
+-out:
+- if (card->info.broadcast_capable)
+- card->dev->flags |= IFF_BROADCAST;
+- else
+- card->dev->flags &= ~IFF_BROADCAST;
+- return rc;
+-}
+-
+-static int
+-qeth_send_checksum_command(struct qeth_card *card)
+-{
+- int rc;
+-
+- rc = qeth_send_simple_setassparms(card, IPA_INBOUND_CHECKSUM,
+- IPA_CMD_ASS_START, 0);
+- if (rc) {
+- PRINT_WARN("Starting Inbound HW Checksumming failed on %s: "
+- "0x%x,\ncontinuing using Inbound SW Checksumming\n",
+- QETH_CARD_IFNAME(card), rc);
+- return rc;
+- }
+- rc = qeth_send_simple_setassparms(card, IPA_INBOUND_CHECKSUM,
+- IPA_CMD_ASS_ENABLE,
+- card->info.csum_mask);
+- if (rc) {
+- PRINT_WARN("Enabling Inbound HW Checksumming failed on %s: "
+- "0x%x,\ncontinuing using Inbound SW Checksumming\n",
+- QETH_CARD_IFNAME(card), rc);
+- return rc;
+- }
+- return 0;
+-}
+-
+-static int
+-qeth_start_ipa_checksum(struct qeth_card *card)
+-{
+- int rc = 0;
+-
+- QETH_DBF_TEXT(trace,3,"strtcsum");
+-
+- if (card->options.checksum_type == NO_CHECKSUMMING) {
+- PRINT_WARN("Using no checksumming on %s.\n",
+- QETH_CARD_IFNAME(card));
+- return 0;
+- }
+- if (card->options.checksum_type == SW_CHECKSUMMING) {
+- PRINT_WARN("Using SW checksumming on %s.\n",
+- QETH_CARD_IFNAME(card));
+- return 0;
+- }
+- if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM)) {
+- PRINT_WARN("Inbound HW Checksumming not "
+- "supported on %s,\ncontinuing "
+- "using Inbound SW Checksumming\n",
+- QETH_CARD_IFNAME(card));
+- card->options.checksum_type = SW_CHECKSUMMING;
+- return 0;
+- }
+- rc = qeth_send_checksum_command(card);
+- if (!rc) {
+- PRINT_INFO("HW Checksumming (inbound) enabled \n");
+- }
+- return rc;
+-}
+-
+-static int
+-qeth_start_ipa_tso(struct qeth_card *card)
+-{
+- int rc;
+-
+- QETH_DBF_TEXT(trace,3,"sttso");
+-
+- if (!qeth_is_supported(card, IPA_OUTBOUND_TSO)) {
+- PRINT_WARN("Outbound TSO not supported on %s\n",
+- QETH_CARD_IFNAME(card));
+- rc = -EOPNOTSUPP;
+- } else {
+- rc = qeth_send_simple_setassparms(card, IPA_OUTBOUND_TSO,
+- IPA_CMD_ASS_START,0);
+- if (rc)
+- PRINT_WARN("Could not start outbound TSO "
+- "assist on %s: rc=%i\n",
+- QETH_CARD_IFNAME(card), rc);
+- else
+- PRINT_INFO("Outbound TSO enabled\n");
+- }
+- if (rc && (card->options.large_send == QETH_LARGE_SEND_TSO)){
+- card->options.large_send = QETH_LARGE_SEND_NO;
+- card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
+- NETIF_F_HW_CSUM);
+- }
+- return rc;
+-}
+-
+-static int
+-qeth_start_ipassists(struct qeth_card *card)
+-{
+- QETH_DBF_TEXT(trace,3,"strtipas");
+- qeth_start_ipa_arp_processing(card); /* go on*/
+- qeth_start_ipa_ip_fragmentation(card); /* go on*/
+- qeth_start_ipa_source_mac(card); /* go on*/
+- qeth_start_ipa_vlan(card); /* go on*/
+- qeth_start_ipa_multicast(card); /* go on*/
+- qeth_start_ipa_ipv6(card); /* go on*/
+- qeth_start_ipa_broadcast(card); /* go on*/
+- qeth_start_ipa_checksum(card); /* go on*/
+- qeth_start_ipa_tso(card); /* go on*/
+- return 0;
+-}
+-
+-static int
+-qeth_send_setrouting(struct qeth_card *card, enum qeth_routing_types type,
+- enum qeth_prot_versions prot)
+-{
+- int rc;
+- struct qeth_ipa_cmd *cmd;
+- struct qeth_cmd_buffer *iob;
+-
+- QETH_DBF_TEXT(trace,4,"setroutg");
+- iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETRTG, prot);
+- cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+- cmd->data.setrtg.type = (type);
+- rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
+-
+- return rc;
+-
+-}
+-
+-static void
+-qeth_correct_routing_type(struct qeth_card *card, enum qeth_routing_types *type,
+- enum qeth_prot_versions prot)
+-{
+- if (card->info.type == QETH_CARD_TYPE_IQD) {
+- switch (*type) {
+- case NO_ROUTER:
+- case PRIMARY_CONNECTOR:
+- case SECONDARY_CONNECTOR:
+- case MULTICAST_ROUTER:
+- return;
+- default:
+- goto out_inval;
+- }
+- } else {
+- switch (*type) {
+- case NO_ROUTER:
+- case PRIMARY_ROUTER:
+- case SECONDARY_ROUTER:
+- return;
+- case MULTICAST_ROUTER:
+- if (qeth_is_ipafunc_supported(card, prot,
+- IPA_OSA_MC_ROUTER))
+- return;
+- default:
+- goto out_inval;
+- }
+- }
+-out_inval:
+- PRINT_WARN("Routing type '%s' not supported for interface %s.\n"
+- "Router status set to 'no router'.\n",
+- ((*type == PRIMARY_ROUTER)? "primary router" :
+- (*type == SECONDARY_ROUTER)? "secondary router" :
+- (*type == PRIMARY_CONNECTOR)? "primary connector" :
+- (*type == SECONDARY_CONNECTOR)? "secondary connector" :
+- (*type == MULTICAST_ROUTER)? "multicast router" :
+- "unknown"),
+- card->dev->name);
+- *type = NO_ROUTER;
+-}
+-
+-int
+-qeth_setrouting_v4(struct qeth_card *card)
+-{
+- int rc;
+-
+- QETH_DBF_TEXT(trace,3,"setrtg4");
+-
+- qeth_correct_routing_type(card, &card->options.route4.type,
+- QETH_PROT_IPV4);
+-
+- rc = qeth_send_setrouting(card, card->options.route4.type,
+- QETH_PROT_IPV4);
+- if (rc) {
+- card->options.route4.type = NO_ROUTER;
+- PRINT_WARN("Error (0x%04x) while setting routing type on %s. "
+- "Type set to 'no router'.\n",
+- rc, QETH_CARD_IFNAME(card));
+- }
+- return rc;
+-}
+-
+-int
+-qeth_setrouting_v6(struct qeth_card *card)
+-{
+- int rc = 0;
+-
+- QETH_DBF_TEXT(trace,3,"setrtg6");
+-#ifdef CONFIG_QETH_IPV6
+-
+- if (!qeth_is_supported(card, IPA_IPV6))
+- return 0;
+- qeth_correct_routing_type(card, &card->options.route6.type,
+- QETH_PROT_IPV6);
+-
+- rc = qeth_send_setrouting(card, card->options.route6.type,
+- QETH_PROT_IPV6);
+- if (rc) {
+- card->options.route6.type = NO_ROUTER;
+- PRINT_WARN("Error (0x%04x) while setting routing type on %s. "
+- "Type set to 'no router'.\n",
+- rc, QETH_CARD_IFNAME(card));
+- }
+-#endif
+- return rc;
+-}
+-
+-int
+-qeth_set_large_send(struct qeth_card *card, enum qeth_large_send_types type)
+-{
+- int rc = 0;
+-
+- if (card->dev == NULL) {
+- card->options.large_send = type;
+- return 0;
+- }
+- if (card->state == CARD_STATE_UP)
+- netif_tx_disable(card->dev);
+- card->options.large_send = type;
+- switch (card->options.large_send) {
+- case QETH_LARGE_SEND_EDDP:
+- card->dev->features |= NETIF_F_TSO | NETIF_F_SG |
+- NETIF_F_HW_CSUM;
+- break;
+- case QETH_LARGE_SEND_TSO:
+- if (qeth_is_supported(card, IPA_OUTBOUND_TSO)){
+- card->dev->features |= NETIF_F_TSO | NETIF_F_SG |
+- NETIF_F_HW_CSUM;
+- } else {
+- PRINT_WARN("TSO not supported on %s. "
+- "large_send set to 'no'.\n",
+- card->dev->name);
+- card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
+- NETIF_F_HW_CSUM);
+- card->options.large_send = QETH_LARGE_SEND_NO;
+- rc = -EOPNOTSUPP;
+- }
+- break;
+- default: /* includes QETH_LARGE_SEND_NO */
+- card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
+- NETIF_F_HW_CSUM);
+- break;
+- }
+- if (card->state == CARD_STATE_UP)
+- netif_wake_queue(card->dev);
+- return rc;
+-}
+-
+-/*
+- * softsetup card: init IPA stuff
+- */
+-static int
+-qeth_softsetup_card(struct qeth_card *card)
+-{
+- int rc;
+-
+- QETH_DBF_TEXT(setup, 2, "softsetp");
+-
+- if ((rc = qeth_send_startlan(card, QETH_PROT_IPV4))){
+- QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+- if (rc == 0xe080){
+- PRINT_WARN("LAN on card %s if offline! "
+- "Waiting for STARTLAN from card.\n",
+- CARD_BUS_ID(card));
+- card->lan_online = 0;
+- }
+- return rc;
+- } else
+- card->lan_online = 1;
+- if (card->info.type==QETH_CARD_TYPE_OSN)
+- goto out;
+- qeth_set_large_send(card, card->options.large_send);
+- if (card->options.layer2) {
+- card->dev->features |=
+- NETIF_F_HW_VLAN_FILTER |
+- NETIF_F_HW_VLAN_TX |
+- NETIF_F_HW_VLAN_RX;
+- card->dev->flags|=IFF_MULTICAST|IFF_BROADCAST;
+- card->info.broadcast_capable=1;
+- if ((rc = qeth_layer2_initialize(card))) {
+- QETH_DBF_TEXT_(setup, 2, "L2err%d", rc);
+- return rc;
+- }
+-#ifdef CONFIG_QETH_VLAN
+- qeth_layer2_process_vlans(card, 0);
+-#endif
+- goto out;
+- }
+- if ((rc = qeth_setadapter_parms(card)))
+- QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+- if ((rc = qeth_start_ipassists(card)))
+- QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+- if ((rc = qeth_setrouting_v4(card)))
+- QETH_DBF_TEXT_(setup, 2, "4err%d", rc);
+- if ((rc = qeth_setrouting_v6(card)))
+- QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
+-out:
+- netif_tx_disable(card->dev);
+- return 0;
+-}
+-
+-#ifdef CONFIG_QETH_IPV6
+-static int
+-qeth_get_unique_id_cb(struct qeth_card *card, struct qeth_reply *reply,
+- unsigned long data)
+-{
+- struct qeth_ipa_cmd *cmd;
+-
+- cmd = (struct qeth_ipa_cmd *) data;
+- if (cmd->hdr.return_code == 0)
+- card->info.unique_id = *((__u16 *)
+- &cmd->data.create_destroy_addr.unique_id[6]);
+- else {
+- card->info.unique_id = UNIQUE_ID_IF_CREATE_ADDR_FAILED |
+- UNIQUE_ID_NOT_BY_CARD;
+- PRINT_WARN("couldn't get a unique id from the card on device "
+- "%s (result=x%x), using default id. ipv6 "
+- "autoconfig on other lpars may lead to duplicate "
+- "ip addresses. please use manually "
+- "configured ones.\n",
+- CARD_BUS_ID(card), cmd->hdr.return_code);
+- }
+- return 0;
+-}
+-#endif
+-
+-static int
+-qeth_put_unique_id(struct qeth_card *card)
+-{
+-
+- int rc = 0;
+-#ifdef CONFIG_QETH_IPV6
+- struct qeth_cmd_buffer *iob;
+- struct qeth_ipa_cmd *cmd;
+-
+- QETH_DBF_TEXT(trace,2,"puniqeid");
+-
+- if ((card->info.unique_id & UNIQUE_ID_NOT_BY_CARD) ==
+- UNIQUE_ID_NOT_BY_CARD)
+- return -1;
+- iob = qeth_get_ipacmd_buffer(card, IPA_CMD_DESTROY_ADDR,
+- QETH_PROT_IPV6);
+- cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+- *((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) =
+- card->info.unique_id;
+- memcpy(&cmd->data.create_destroy_addr.unique_id[0],
+- card->dev->dev_addr, OSA_ADDR_LEN);
+- rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
+-#else
+- card->info.unique_id = UNIQUE_ID_IF_CREATE_ADDR_FAILED |
+- UNIQUE_ID_NOT_BY_CARD;
+-#endif
+- return rc;
+-}
+-
+-/**
+- * Clear IP List
+- */
+-static void
+-qeth_clear_ip_list(struct qeth_card *card, int clean, int recover)
+-{
+- struct qeth_ipaddr *addr, *tmp;
+- unsigned long flags;
+-
+- QETH_DBF_TEXT(trace,4,"clearip");
+- spin_lock_irqsave(&card->ip_lock, flags);
+- /* clear todo list */
+- list_for_each_entry_safe(addr, tmp, card->ip_tbd_list, entry){
+- list_del(&addr->entry);
+- kfree(addr);
+- }
+-
+- while (!list_empty(&card->ip_list)) {
+- addr = list_entry(card->ip_list.next,
+- struct qeth_ipaddr, entry);
+- list_del_init(&addr->entry);
+- if (clean) {
+- spin_unlock_irqrestore(&card->ip_lock, flags);
+- qeth_deregister_addr_entry(card, addr);
+- spin_lock_irqsave(&card->ip_lock, flags);
+- }
+- if (!recover || addr->is_multicast) {
+- kfree(addr);
+- continue;
+- }
+- list_add_tail(&addr->entry, card->ip_tbd_list);
+- }
+- spin_unlock_irqrestore(&card->ip_lock, flags);
+-}
+-
+-static void
+-qeth_set_allowed_threads(struct qeth_card *card, unsigned long threads,
+- int clear_start_mask)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&card->thread_mask_lock, flags);
+- card->thread_allowed_mask = threads;
+- if (clear_start_mask)
+- card->thread_start_mask &= threads;
+- spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+- wake_up(&card->wait_q);
+-}
+-
+-static int
+-qeth_threads_running(struct qeth_card *card, unsigned long threads)
+-{
+- unsigned long flags;
+- int rc = 0;
+-
+- spin_lock_irqsave(&card->thread_mask_lock, flags);
+- rc = (card->thread_running_mask & threads);
+- spin_unlock_irqrestore(&card->thread_mask_lock, flags);
+- return rc;
+-}
+-
+-static int
+-qeth_wait_for_threads(struct qeth_card *card, unsigned long threads)
+-{
+- return wait_event_interruptible(card->wait_q,
+- qeth_threads_running(card, threads) == 0);
+-}
+-
+-static int
+-qeth_stop_card(struct qeth_card *card, int recovery_mode)
+-{
+- int rc = 0;
+-
+- QETH_DBF_TEXT(setup ,2,"stopcard");
+- QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
+-
+- qeth_set_allowed_threads(card, 0, 1);
+- if (qeth_wait_for_threads(card, ~QETH_RECOVER_THREAD))
+- return -ERESTARTSYS;
+- if (card->read.state == CH_STATE_UP &&
+- card->write.state == CH_STATE_UP &&
+- (card->state == CARD_STATE_UP)) {
+- if (recovery_mode &&
+- card->info.type != QETH_CARD_TYPE_OSN) {
+- qeth_stop(card->dev);
+- } else {
+- rtnl_lock();
+- dev_close(card->dev);
+- rtnl_unlock();
+- }
+- if (!card->use_hard_stop) {
+- __u8 *mac = &card->dev->dev_addr[0];
+- rc = qeth_layer2_send_delmac(card, mac);
+- QETH_DBF_TEXT_(setup, 2, "Lerr%d", rc);
+- if ((rc = qeth_send_stoplan(card)))
+- QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+- }
+- card->state = CARD_STATE_SOFTSETUP;
+- }
+- if (card->state == CARD_STATE_SOFTSETUP) {
+-#ifdef CONFIG_QETH_VLAN
+- if (card->options.layer2)
+- qeth_layer2_process_vlans(card, 1);
+-#endif
+- qeth_clear_ip_list(card, !card->use_hard_stop, 1);
+- qeth_clear_ipacmd_list(card);
+- card->state = CARD_STATE_HARDSETUP;
+- }
+- if (card->state == CARD_STATE_HARDSETUP) {
+- if ((!card->use_hard_stop) &&
+- (!card->options.layer2))
+- if ((rc = qeth_put_unique_id(card)))
+- QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+- qeth_qdio_clear_card(card, 0);
+- qeth_clear_qdio_buffers(card);
+- qeth_clear_working_pool_list(card);
+- card->state = CARD_STATE_DOWN;
+- }
+- if (card->state == CARD_STATE_DOWN) {
+- qeth_clear_cmd_buffers(&card->read);
+- qeth_clear_cmd_buffers(&card->write);
+- }
+- card->use_hard_stop = 0;
+- return rc;
+-}
+-
+-
+-static int
+-qeth_get_unique_id(struct qeth_card *card)
+-{
+- int rc = 0;
+-#ifdef CONFIG_QETH_IPV6
+- struct qeth_cmd_buffer *iob;
+- struct qeth_ipa_cmd *cmd;
+-
+- QETH_DBF_TEXT(setup, 2, "guniqeid");
+-
+- if (!qeth_is_supported(card,IPA_IPV6)) {
+- card->info.unique_id = UNIQUE_ID_IF_CREATE_ADDR_FAILED |
+- UNIQUE_ID_NOT_BY_CARD;
+- return 0;
+- }
+-
+- iob = qeth_get_ipacmd_buffer(card, IPA_CMD_CREATE_ADDR,
+- QETH_PROT_IPV6);
+- cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+- *((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) =
+- card->info.unique_id;
+-
+- rc = qeth_send_ipa_cmd(card, iob, qeth_get_unique_id_cb, NULL);
+-#else
+- card->info.unique_id = UNIQUE_ID_IF_CREATE_ADDR_FAILED |
+- UNIQUE_ID_NOT_BY_CARD;
+-#endif
+- return rc;
+-}
+-static void
+-qeth_print_status_with_portname(struct qeth_card *card)
+-{
+- char dbf_text[15];
+- int i;
+-
+- sprintf(dbf_text, "%s", card->info.portname + 1);
+- for (i = 0; i < 8; i++)
+- dbf_text[i] =
+- (char) _ebcasc[(__u8) dbf_text[i]];
+- dbf_text[8] = 0;
+- printk("qeth: Device %s/%s/%s is a%s card%s%s%s\n"
+- "with link type %s (portname: %s)\n",
+- CARD_RDEV_ID(card),
+- CARD_WDEV_ID(card),
+- CARD_DDEV_ID(card),
+- qeth_get_cardname(card),
+- (card->info.mcl_level[0]) ? " (level: " : "",
+- (card->info.mcl_level[0]) ? card->info.mcl_level : "",
+- (card->info.mcl_level[0]) ? ")" : "",
+- qeth_get_cardname_short(card),
+- dbf_text);
+-
+-}
+-
+-static void
+-qeth_print_status_no_portname(struct qeth_card *card)
+-{
+- if (card->info.portname[0])
+- printk("qeth: Device %s/%s/%s is a%s "
+- "card%s%s%s\nwith link type %s "
+- "(no portname needed by interface).\n",
+- CARD_RDEV_ID(card),
+- CARD_WDEV_ID(card),
+- CARD_DDEV_ID(card),
+- qeth_get_cardname(card),
+- (card->info.mcl_level[0]) ? " (level: " : "",
+- (card->info.mcl_level[0]) ? card->info.mcl_level : "",
+- (card->info.mcl_level[0]) ? ")" : "",
+- qeth_get_cardname_short(card));
+- else
+- printk("qeth: Device %s/%s/%s is a%s "
+- "card%s%s%s\nwith link type %s.\n",
+- CARD_RDEV_ID(card),
+- CARD_WDEV_ID(card),
+- CARD_DDEV_ID(card),
+- qeth_get_cardname(card),
+- (card->info.mcl_level[0]) ? " (level: " : "",
+- (card->info.mcl_level[0]) ? card->info.mcl_level : "",
+- (card->info.mcl_level[0]) ? ")" : "",
+- qeth_get_cardname_short(card));
+-}
+-
+-static void
+-qeth_print_status_message(struct qeth_card *card)
+-{
+- switch (card->info.type) {
+- case QETH_CARD_TYPE_OSAE:
+- /* VM will use a non-zero first character
+- * to indicate a HiperSockets like reporting
+- * of the level OSA sets the first character to zero
+- * */
+- if (!card->info.mcl_level[0]) {
+- sprintf(card->info.mcl_level,"%02x%02x",
+- card->info.mcl_level[2],
+- card->info.mcl_level[3]);
+-
+- card->info.mcl_level[QETH_MCL_LENGTH] = 0;
+- break;
+- }
+- /* fallthrough */
+- case QETH_CARD_TYPE_IQD:
+- if (card->info.guestlan) {
+- card->info.mcl_level[0] = (char) _ebcasc[(__u8)
+- card->info.mcl_level[0]];
+- card->info.mcl_level[1] = (char) _ebcasc[(__u8)
+- card->info.mcl_level[1]];
+- card->info.mcl_level[2] = (char) _ebcasc[(__u8)
+- card->info.mcl_level[2]];
+- card->info.mcl_level[3] = (char) _ebcasc[(__u8)
+- card->info.mcl_level[3]];
+- card->info.mcl_level[QETH_MCL_LENGTH] = 0;
+- }
+- break;
+- default:
+- memset(&card->info.mcl_level[0], 0, QETH_MCL_LENGTH + 1);
+- }
+- if (card->info.portname_required)
+- qeth_print_status_with_portname(card);
+- else
+- qeth_print_status_no_portname(card);
+-}
+-
+-static int
+-qeth_register_netdev(struct qeth_card *card)
+-{
+- QETH_DBF_TEXT(setup, 3, "regnetd");
+- if (card->dev->reg_state != NETREG_UNINITIALIZED)
+- return 0;
+- /* sysfs magic */
+- SET_NETDEV_DEV(card->dev, &card->gdev->dev);
+- return register_netdev(card->dev);
+-}
+-
+-static void
+-qeth_start_again(struct qeth_card *card, int recovery_mode)
+-{
+- QETH_DBF_TEXT(setup ,2, "startag");
+-
+- if (recovery_mode &&
+- card->info.type != QETH_CARD_TYPE_OSN) {
+- qeth_open(card->dev);
+- } else {
+- rtnl_lock();
+- dev_open(card->dev);
+- rtnl_unlock();
+- }
+- /* this also sets saved unicast addresses */
+- qeth_set_multicast_list(card->dev);
+-}
+-
+-
+-/* Layer 2 specific stuff */
+-#define IGNORE_PARAM_EQ(option,value,reset_value,msg) \
+- if (card->options.option == value) { \
+- PRINT_ERR("%s not supported with layer 2 " \
+- "functionality, ignoring option on read" \
+- "channel device %s .\n",msg,CARD_RDEV_ID(card)); \
+- card->options.option = reset_value; \
+- }
+-#define IGNORE_PARAM_NEQ(option,value,reset_value,msg) \
+- if (card->options.option != value) { \
+- PRINT_ERR("%s not supported with layer 2 " \
+- "functionality, ignoring option on read" \
+- "channel device %s .\n",msg,CARD_RDEV_ID(card)); \
+- card->options.option = reset_value; \
+- }
+-
+-
+-static void qeth_make_parameters_consistent(struct qeth_card *card)
+-{
+-
+- if (card->options.layer2 == 0)
+- return;
+- if (card->info.type == QETH_CARD_TYPE_OSN)
+- return;
+- if (card->info.type == QETH_CARD_TYPE_IQD) {
+- PRINT_ERR("Device %s does not support layer 2 functionality." \
+- " Ignoring layer2 option.\n",CARD_BUS_ID(card));
+- card->options.layer2 = 0;
+- return;
+- }
+- IGNORE_PARAM_NEQ(route4.type, NO_ROUTER, NO_ROUTER,
+- "Routing options are");
+-#ifdef CONFIG_QETH_IPV6
+- IGNORE_PARAM_NEQ(route6.type, NO_ROUTER, NO_ROUTER,
+- "Routing options are");
+-#endif
+- IGNORE_PARAM_EQ(checksum_type, HW_CHECKSUMMING,
+- QETH_CHECKSUM_DEFAULT,
+- "Checksumming options are");
+- IGNORE_PARAM_NEQ(broadcast_mode, QETH_TR_BROADCAST_ALLRINGS,
+- QETH_TR_BROADCAST_ALLRINGS,
+- "Broadcast mode options are");
+- IGNORE_PARAM_NEQ(macaddr_mode, QETH_TR_MACADDR_NONCANONICAL,
+- QETH_TR_MACADDR_NONCANONICAL,
+- "Canonical MAC addr options are");
+- IGNORE_PARAM_NEQ(fake_broadcast, 0, 0,
+- "Broadcast faking options are");
+- IGNORE_PARAM_NEQ(add_hhlen, DEFAULT_ADD_HHLEN,
+- DEFAULT_ADD_HHLEN,"Option add_hhlen is");
+- IGNORE_PARAM_NEQ(fake_ll, 0, 0,"Option fake_ll is");
+-}
+-
+-
+-static int
+-__qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode)
+-{
+- struct qeth_card *card = gdev->dev.driver_data;
+- int rc = 0;
+- enum qeth_card_states recover_flag;
+-
+- BUG_ON(!card);
+- QETH_DBF_TEXT(setup ,2, "setonlin");
+- QETH_DBF_HEX(setup, 2, &card, sizeof(void *));
+-
+- qeth_set_allowed_threads(card, QETH_RECOVER_THREAD, 1);
+- if (qeth_wait_for_threads(card, ~QETH_RECOVER_THREAD)){
+- PRINT_WARN("set_online of card %s interrupted by user!\n",
+- CARD_BUS_ID(card));
+- return -ERESTARTSYS;
+- }
+-
+- recover_flag = card->state;
+- if ((rc = ccw_device_set_online(CARD_RDEV(card))) ||
+- (rc = ccw_device_set_online(CARD_WDEV(card))) ||
+- (rc = ccw_device_set_online(CARD_DDEV(card)))){
+- QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
+- return -EIO;
+- }
+-
+- qeth_make_parameters_consistent(card);
+-
+- if ((rc = qeth_hardsetup_card(card))){
+- QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
+- goto out_remove;
+- }
+- card->state = CARD_STATE_HARDSETUP;
+-
+- if (!(rc = qeth_query_ipassists(card,QETH_PROT_IPV4)))
+- rc = qeth_get_unique_id(card);
+-
+- if (rc && card->options.layer2 == 0) {
+- QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
+- goto out_remove;
+- }
+- qeth_print_status_message(card);
+- if ((rc = qeth_register_netdev(card))){
+- QETH_DBF_TEXT_(setup, 2, "4err%d", rc);
+- goto out_remove;
+- }
+- if ((rc = qeth_softsetup_card(card))){
+- QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
+- goto out_remove;
+- }
+-
+- if ((rc = qeth_init_qdio_queues(card))){
+- QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
+- goto out_remove;
+- }
+- card->state = CARD_STATE_SOFTSETUP;
+- netif_carrier_on(card->dev);
+-
+- qeth_set_allowed_threads(card, 0xffffffff, 0);
+- if (recover_flag == CARD_STATE_RECOVER)
+- qeth_start_again(card, recovery_mode);
+- qeth_notify_processes();
+- return 0;
+-out_remove:
+- card->use_hard_stop = 1;
+- qeth_stop_card(card, 0);
+- ccw_device_set_offline(CARD_DDEV(card));
+- ccw_device_set_offline(CARD_WDEV(card));
+- ccw_device_set_offline(CARD_RDEV(card));
+- if (recover_flag == CARD_STATE_RECOVER)
+- card->state = CARD_STATE_RECOVER;
+- else
+- card->state = CARD_STATE_DOWN;
+- return -ENODEV;
+-}
+-
+-static int
+-qeth_set_online(struct ccwgroup_device *gdev)
+-{
+- return __qeth_set_online(gdev, 0);
+-}
+-
+-static struct ccw_device_id qeth_ids[] = {
+- {CCW_DEVICE(0x1731, 0x01), .driver_info = QETH_CARD_TYPE_OSAE},
+- {CCW_DEVICE(0x1731, 0x05), .driver_info = QETH_CARD_TYPE_IQD},
+- {CCW_DEVICE(0x1731, 0x06), .driver_info = QETH_CARD_TYPE_OSN},
+- {},
+-};
+-MODULE_DEVICE_TABLE(ccw, qeth_ids);
+-
+-struct device *qeth_root_dev = NULL;
+-
+-struct ccwgroup_driver qeth_ccwgroup_driver = {
+- .owner = THIS_MODULE,
+- .name = "qeth",
+- .driver_id = 0xD8C5E3C8,
+- .probe = qeth_probe_device,
+- .remove = qeth_remove_device,
+- .set_online = qeth_set_online,
+- .set_offline = qeth_set_offline,
+-};
+-
+-struct ccw_driver qeth_ccw_driver = {
+- .name = "qeth",
+- .ids = qeth_ids,
+- .probe = ccwgroup_probe_ccwdev,
+- .remove = ccwgroup_remove_ccwdev,
+-};
+-
+-
+-static void
+-qeth_unregister_dbf_views(void)
+-{
+- if (qeth_dbf_setup)
+- debug_unregister(qeth_dbf_setup);
+- if (qeth_dbf_qerr)
+- debug_unregister(qeth_dbf_qerr);
+- if (qeth_dbf_sense)
+- debug_unregister(qeth_dbf_sense);
+- if (qeth_dbf_misc)
+- debug_unregister(qeth_dbf_misc);
+- if (qeth_dbf_data)
+- debug_unregister(qeth_dbf_data);
+- if (qeth_dbf_control)
+- debug_unregister(qeth_dbf_control);
+- if (qeth_dbf_trace)
+- debug_unregister(qeth_dbf_trace);
+-}
+-static int
+-qeth_register_dbf_views(void)
+-{
+- qeth_dbf_setup = debug_register(QETH_DBF_SETUP_NAME,
+- QETH_DBF_SETUP_PAGES,
+- QETH_DBF_SETUP_NR_AREAS,
+- QETH_DBF_SETUP_LEN);
+- qeth_dbf_misc = debug_register(QETH_DBF_MISC_NAME,
+- QETH_DBF_MISC_PAGES,
+- QETH_DBF_MISC_NR_AREAS,
+- QETH_DBF_MISC_LEN);
+- qeth_dbf_data = debug_register(QETH_DBF_DATA_NAME,
+- QETH_DBF_DATA_PAGES,
+- QETH_DBF_DATA_NR_AREAS,
+- QETH_DBF_DATA_LEN);
+- qeth_dbf_control = debug_register(QETH_DBF_CONTROL_NAME,
+- QETH_DBF_CONTROL_PAGES,
+- QETH_DBF_CONTROL_NR_AREAS,
+- QETH_DBF_CONTROL_LEN);
+- qeth_dbf_sense = debug_register(QETH_DBF_SENSE_NAME,
+- QETH_DBF_SENSE_PAGES,
+- QETH_DBF_SENSE_NR_AREAS,
+- QETH_DBF_SENSE_LEN);
+- qeth_dbf_qerr = debug_register(QETH_DBF_QERR_NAME,
+- QETH_DBF_QERR_PAGES,
+- QETH_DBF_QERR_NR_AREAS,
+- QETH_DBF_QERR_LEN);
+- qeth_dbf_trace = debug_register(QETH_DBF_TRACE_NAME,
+- QETH_DBF_TRACE_PAGES,
+- QETH_DBF_TRACE_NR_AREAS,
+- QETH_DBF_TRACE_LEN);
+-
+- if ((qeth_dbf_setup == NULL) || (qeth_dbf_misc == NULL) ||
+- (qeth_dbf_data == NULL) || (qeth_dbf_control == NULL) ||
+- (qeth_dbf_sense == NULL) || (qeth_dbf_qerr == NULL) ||
+- (qeth_dbf_trace == NULL)) {
+- qeth_unregister_dbf_views();
+- return -ENOMEM;
+- }
+- debug_register_view(qeth_dbf_setup, &debug_hex_ascii_view);
+- debug_set_level(qeth_dbf_setup, QETH_DBF_SETUP_LEVEL);
+-
+- debug_register_view(qeth_dbf_misc, &debug_hex_ascii_view);
+- debug_set_level(qeth_dbf_misc, QETH_DBF_MISC_LEVEL);
+-
+- debug_register_view(qeth_dbf_data, &debug_hex_ascii_view);
+- debug_set_level(qeth_dbf_data, QETH_DBF_DATA_LEVEL);
+-
+- debug_register_view(qeth_dbf_control, &debug_hex_ascii_view);
+- debug_set_level(qeth_dbf_control, QETH_DBF_CONTROL_LEVEL);
+-
+- debug_register_view(qeth_dbf_sense, &debug_hex_ascii_view);
+- debug_set_level(qeth_dbf_sense, QETH_DBF_SENSE_LEVEL);
+-
+- debug_register_view(qeth_dbf_qerr, &debug_hex_ascii_view);
+- debug_set_level(qeth_dbf_qerr, QETH_DBF_QERR_LEVEL);
+-
+- debug_register_view(qeth_dbf_trace, &debug_hex_ascii_view);
+- debug_set_level(qeth_dbf_trace, QETH_DBF_TRACE_LEVEL);
+-
+- return 0;
+-}
+-
+-#ifdef CONFIG_QETH_IPV6
+-extern struct neigh_table arp_tbl;
+-static struct neigh_ops *arp_direct_ops;
+-static int (*qeth_old_arp_constructor) (struct neighbour *);
+-
+-static struct neigh_ops arp_direct_ops_template = {
+- .family = AF_INET,
+- .solicit = NULL,
+- .error_report = NULL,
+- .output = dev_queue_xmit,
+- .connected_output = dev_queue_xmit,
+- .hh_output = dev_queue_xmit,
+- .queue_xmit = dev_queue_xmit
+-};
+-
+-static int
+-qeth_arp_constructor(struct neighbour *neigh)
+-{
+- struct net_device *dev = neigh->dev;
+- struct in_device *in_dev;
+- struct neigh_parms *parms;
+- struct qeth_card *card;
+-
+- card = qeth_get_card_from_dev(dev);
+- if (card == NULL)
+- goto out;
+- if((card->options.layer2) ||
+- (card->dev->header_ops == &qeth_fake_ops))
+- goto out;
+-
+- rcu_read_lock();
+- in_dev = __in_dev_get_rcu(dev);
+- if (in_dev == NULL) {
+- rcu_read_unlock();
+- return -EINVAL;
+- }
+-
+- parms = in_dev->arp_parms;
+- __neigh_parms_put(neigh->parms);
+- neigh->parms = neigh_parms_clone(parms);
+- rcu_read_unlock();
+-
+- neigh->type = inet_addr_type(&init_net, *(__be32 *) neigh->primary_key);
+- neigh->nud_state = NUD_NOARP;
+- neigh->ops = arp_direct_ops;
+- neigh->output = neigh->ops->queue_xmit;
+- return 0;
+-out:
+- return qeth_old_arp_constructor(neigh);
+-}
+-#endif /*CONFIG_QETH_IPV6*/
+-
+-/*
+- * IP address takeover related functions
+- */
+-static void
+-qeth_clear_ipato_list(struct qeth_card *card)
+-{
+- struct qeth_ipato_entry *ipatoe, *tmp;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&card->ip_lock, flags);
+- list_for_each_entry_safe(ipatoe, tmp, &card->ipato.entries, entry) {
+- list_del(&ipatoe->entry);
+- kfree(ipatoe);
+- }
+- spin_unlock_irqrestore(&card->ip_lock, flags);
+-}
+-
+-int
+-qeth_add_ipato_entry(struct qeth_card *card, struct qeth_ipato_entry *new)
+-{
+- struct qeth_ipato_entry *ipatoe;
+- unsigned long flags;
+- int rc = 0;
+-
+- QETH_DBF_TEXT(trace, 2, "addipato");
+- spin_lock_irqsave(&card->ip_lock, flags);
+- list_for_each_entry(ipatoe, &card->ipato.entries, entry){
+- if (ipatoe->proto != new->proto)
+- continue;
+- if (!memcmp(ipatoe->addr, new->addr,
+- (ipatoe->proto == QETH_PROT_IPV4)? 4:16) &&
+- (ipatoe->mask_bits == new->mask_bits)){
+- PRINT_WARN("ipato entry already exists!\n");
+- rc = -EEXIST;
+- break;
+- }
+- }
+- if (!rc) {
+- list_add_tail(&new->entry, &card->ipato.entries);
+- }
+- spin_unlock_irqrestore(&card->ip_lock, flags);
+- return rc;
+-}
+-
+-void
+-qeth_del_ipato_entry(struct qeth_card *card, enum qeth_prot_versions proto,
+- u8 *addr, int mask_bits)
+-{
+- struct qeth_ipato_entry *ipatoe, *tmp;
+- unsigned long flags;
+-
+- QETH_DBF_TEXT(trace, 2, "delipato");
+- spin_lock_irqsave(&card->ip_lock, flags);
+- list_for_each_entry_safe(ipatoe, tmp, &card->ipato.entries, entry){
+- if (ipatoe->proto != proto)
+- continue;
+- if (!memcmp(ipatoe->addr, addr,
+- (proto == QETH_PROT_IPV4)? 4:16) &&
+- (ipatoe->mask_bits == mask_bits)){
+- list_del(&ipatoe->entry);
+- kfree(ipatoe);
+- }
+- }
+- spin_unlock_irqrestore(&card->ip_lock, flags);
+-}
+-
+-static void
+-qeth_convert_addr_to_bits(u8 *addr, u8 *bits, int len)
+-{
+- int i, j;
+- u8 octet;
+-
+- for (i = 0; i < len; ++i){
+- octet = addr[i];
+- for (j = 7; j >= 0; --j){
+- bits[i*8 + j] = octet & 1;
+- octet >>= 1;
+- }
+- }
+-}
+-
+-static int
+-qeth_is_addr_covered_by_ipato(struct qeth_card *card, struct qeth_ipaddr *addr)
+-{
+- struct qeth_ipato_entry *ipatoe;
+- u8 addr_bits[128] = {0, };
+- u8 ipatoe_bits[128] = {0, };
+- int rc = 0;
+-
+- if (!card->ipato.enabled)
+- return 0;
+-
+- qeth_convert_addr_to_bits((u8 *) &addr->u, addr_bits,
+- (addr->proto == QETH_PROT_IPV4)? 4:16);
+- list_for_each_entry(ipatoe, &card->ipato.entries, entry){
+- if (addr->proto != ipatoe->proto)
+- continue;
+- qeth_convert_addr_to_bits(ipatoe->addr, ipatoe_bits,
+- (ipatoe->proto==QETH_PROT_IPV4) ?
+- 4:16);
+- if (addr->proto == QETH_PROT_IPV4)
+- rc = !memcmp(addr_bits, ipatoe_bits,
+- min(32, ipatoe->mask_bits));
+- else
+- rc = !memcmp(addr_bits, ipatoe_bits,
+- min(128, ipatoe->mask_bits));
+- if (rc)
+- break;
+- }
+- /* invert? */
+- if ((addr->proto == QETH_PROT_IPV4) && card->ipato.invert4)
+- rc = !rc;
+- else if ((addr->proto == QETH_PROT_IPV6) && card->ipato.invert6)
+- rc = !rc;
+-
+- return rc;
+-}
+-
+-/*
+- * VIPA related functions
+- */
+-int
+-qeth_add_vipa(struct qeth_card *card, enum qeth_prot_versions proto,
+- const u8 *addr)
+-{
+- struct qeth_ipaddr *ipaddr;
+- unsigned long flags;
+- int rc = 0;
+-
+- ipaddr = qeth_get_addr_buffer(proto);
+- if (ipaddr){
+- if (proto == QETH_PROT_IPV4){
+- QETH_DBF_TEXT(trace, 2, "addvipa4");
+- memcpy(&ipaddr->u.a4.addr, addr, 4);
+- ipaddr->u.a4.mask = 0;
+-#ifdef CONFIG_QETH_IPV6
+- } else if (proto == QETH_PROT_IPV6){
+- QETH_DBF_TEXT(trace, 2, "addvipa6");
+- memcpy(&ipaddr->u.a6.addr, addr, 16);
+- ipaddr->u.a6.pfxlen = 0;
+-#endif
+- }
+- ipaddr->type = QETH_IP_TYPE_VIPA;
+- ipaddr->set_flags = QETH_IPA_SETIP_VIPA_FLAG;
+- ipaddr->del_flags = QETH_IPA_DELIP_VIPA_FLAG;
+- } else
+- return -ENOMEM;
+- spin_lock_irqsave(&card->ip_lock, flags);
+- if (__qeth_address_exists_in_list(&card->ip_list, ipaddr, 0) ||
+- __qeth_address_exists_in_list(card->ip_tbd_list, ipaddr, 0))
+- rc = -EEXIST;
+- spin_unlock_irqrestore(&card->ip_lock, flags);
+- if (rc){
+- PRINT_WARN("Cannot add VIPA. Address already exists!\n");
+- return rc;
+- }
+- if (!qeth_add_ip(card, ipaddr))
+- kfree(ipaddr);
+- qeth_set_ip_addr_list(card);
+- return rc;
+-}
+-
+-void
+-qeth_del_vipa(struct qeth_card *card, enum qeth_prot_versions proto,
+- const u8 *addr)
+-{
+- struct qeth_ipaddr *ipaddr;
+-
+- ipaddr = qeth_get_addr_buffer(proto);
+- if (ipaddr){
+- if (proto == QETH_PROT_IPV4){
+- QETH_DBF_TEXT(trace, 2, "delvipa4");
+- memcpy(&ipaddr->u.a4.addr, addr, 4);
+- ipaddr->u.a4.mask = 0;
+-#ifdef CONFIG_QETH_IPV6
+- } else if (proto == QETH_PROT_IPV6){
+- QETH_DBF_TEXT(trace, 2, "delvipa6");
+- memcpy(&ipaddr->u.a6.addr, addr, 16);
+- ipaddr->u.a6.pfxlen = 0;
+-#endif
+- }
+- ipaddr->type = QETH_IP_TYPE_VIPA;
+- } else
+- return;
+- if (!qeth_delete_ip(card, ipaddr))
+- kfree(ipaddr);
+- qeth_set_ip_addr_list(card);
+-}
+-
+-/*
+- * proxy ARP related functions
+- */
+-int
+-qeth_add_rxip(struct qeth_card *card, enum qeth_prot_versions proto,
+- const u8 *addr)
+-{
+- struct qeth_ipaddr *ipaddr;
+- unsigned long flags;
+- int rc = 0;
+-
+- ipaddr = qeth_get_addr_buffer(proto);
+- if (ipaddr){
+- if (proto == QETH_PROT_IPV4){
+- QETH_DBF_TEXT(trace, 2, "addrxip4");
+- memcpy(&ipaddr->u.a4.addr, addr, 4);
+- ipaddr->u.a4.mask = 0;
+-#ifdef CONFIG_QETH_IPV6
+- } else if (proto == QETH_PROT_IPV6){
+- QETH_DBF_TEXT(trace, 2, "addrxip6");
+- memcpy(&ipaddr->u.a6.addr, addr, 16);
+- ipaddr->u.a6.pfxlen = 0;
+-#endif
+- }
+- ipaddr->type = QETH_IP_TYPE_RXIP;
+- ipaddr->set_flags = QETH_IPA_SETIP_TAKEOVER_FLAG;
+- ipaddr->del_flags = 0;
+- } else
+- return -ENOMEM;
+- spin_lock_irqsave(&card->ip_lock, flags);
+- if (__qeth_address_exists_in_list(&card->ip_list, ipaddr, 0) ||
+- __qeth_address_exists_in_list(card->ip_tbd_list, ipaddr, 0))
+- rc = -EEXIST;
+- spin_unlock_irqrestore(&card->ip_lock, flags);
+- if (rc){
+- PRINT_WARN("Cannot add RXIP. Address already exists!\n");
+- return rc;
+- }
+- if (!qeth_add_ip(card, ipaddr))
+- kfree(ipaddr);
+- qeth_set_ip_addr_list(card);
+- return 0;
+-}
+-
+-void
+-qeth_del_rxip(struct qeth_card *card, enum qeth_prot_versions proto,
+- const u8 *addr)
+-{
+- struct qeth_ipaddr *ipaddr;
+-
+- ipaddr = qeth_get_addr_buffer(proto);
+- if (ipaddr){
+- if (proto == QETH_PROT_IPV4){
+- QETH_DBF_TEXT(trace, 2, "addrxip4");
+- memcpy(&ipaddr->u.a4.addr, addr, 4);
+- ipaddr->u.a4.mask = 0;
+-#ifdef CONFIG_QETH_IPV6
+- } else if (proto == QETH_PROT_IPV6){
+- QETH_DBF_TEXT(trace, 2, "addrxip6");
+- memcpy(&ipaddr->u.a6.addr, addr, 16);
+- ipaddr->u.a6.pfxlen = 0;
+-#endif
+- }
+- ipaddr->type = QETH_IP_TYPE_RXIP;
+- } else
+- return;
+- if (!qeth_delete_ip(card, ipaddr))
+- kfree(ipaddr);
+- qeth_set_ip_addr_list(card);
+-}
+-
+-/**
+- * IP event handler
+- */
+-static int
+-qeth_ip_event(struct notifier_block *this,
+- unsigned long event,void *ptr)
+-{
+- struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
+- struct net_device *dev =(struct net_device *) ifa->ifa_dev->dev;
+- struct qeth_ipaddr *addr;
+- struct qeth_card *card;
+-
+- QETH_DBF_TEXT(trace,3,"ipevent");
+- card = qeth_get_card_from_dev(dev);
+- if (!card)
+- return NOTIFY_DONE;
+- if (card->options.layer2)
+- return NOTIFY_DONE;
+-
+- addr = qeth_get_addr_buffer(QETH_PROT_IPV4);
+- if (addr != NULL) {
+- addr->u.a4.addr = ifa->ifa_address;
+- addr->u.a4.mask = ifa->ifa_mask;
+- addr->type = QETH_IP_TYPE_NORMAL;
+- } else
+- goto out;
+-
+- switch(event) {
+- case NETDEV_UP:
+- if (!qeth_add_ip(card, addr))
+- kfree(addr);
+- break;
+- case NETDEV_DOWN:
+- if (!qeth_delete_ip(card, addr))
+- kfree(addr);
+- break;
+- default:
+- break;
+- }
+- qeth_set_ip_addr_list(card);
+-out:
+- return NOTIFY_DONE;
+-}
+-
+-static struct notifier_block qeth_ip_notifier = {
+- qeth_ip_event,
+- NULL,
+-};
+-
+-#ifdef CONFIG_QETH_IPV6
+-/**
+- * IPv6 event handler
+- */
+-static int
+-qeth_ip6_event(struct notifier_block *this,
+- unsigned long event,void *ptr)
+-{
+-
+- struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
+- struct net_device *dev = (struct net_device *)ifa->idev->dev;
+- struct qeth_ipaddr *addr;
+- struct qeth_card *card;
+-
+- QETH_DBF_TEXT(trace,3,"ip6event");
+-
+- card = qeth_get_card_from_dev(dev);
+- if (!card)
+- return NOTIFY_DONE;
+- if (!qeth_is_supported(card, IPA_IPV6))
+- return NOTIFY_DONE;
+-
+- addr = qeth_get_addr_buffer(QETH_PROT_IPV6);
+- if (addr != NULL) {
+- memcpy(&addr->u.a6.addr, &ifa->addr, sizeof(struct in6_addr));
+- addr->u.a6.pfxlen = ifa->prefix_len;
+- addr->type = QETH_IP_TYPE_NORMAL;
+- } else
+- goto out;
+-
+- switch(event) {
+- case NETDEV_UP:
+- if (!qeth_add_ip(card, addr))
+- kfree(addr);
+- break;
+- case NETDEV_DOWN:
+- if (!qeth_delete_ip(card, addr))
+- kfree(addr);
+- break;
+- default:
+- break;
+- }
+- qeth_set_ip_addr_list(card);
+-out:
+- return NOTIFY_DONE;
+-}
+-
+-static struct notifier_block qeth_ip6_notifier = {
+- qeth_ip6_event,
+- NULL,
+-};
+-#endif
+-
+-static int
+-__qeth_reboot_event_card(struct device *dev, void *data)
+-{
+- struct qeth_card *card;
+-
+- card = (struct qeth_card *) dev->driver_data;
+- qeth_clear_ip_list(card, 0, 0);
+- qeth_qdio_clear_card(card, 0);
+- qeth_clear_qdio_buffers(card);
+- return 0;
+-}
+-
+-static int
+-qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
+-{
+- int ret;
+-
+- ret = driver_for_each_device(&qeth_ccwgroup_driver.driver, NULL, NULL,
+- __qeth_reboot_event_card);
+- return ret ? NOTIFY_BAD : NOTIFY_DONE;
+-}
+-
+-
+-static struct notifier_block qeth_reboot_notifier = {
+- qeth_reboot_event,
+- NULL,
+-};
+-
+-static int
+-qeth_register_notifiers(void)
+-{
+- int r;
+-
+- QETH_DBF_TEXT(trace,5,"regnotif");
+- if ((r = register_reboot_notifier(&qeth_reboot_notifier)))
+- return r;
+- if ((r = register_inetaddr_notifier(&qeth_ip_notifier)))
+- goto out_reboot;
+-#ifdef CONFIG_QETH_IPV6
+- if ((r = register_inet6addr_notifier(&qeth_ip6_notifier)))
+- goto out_ipv4;
+-#endif
+- return 0;
+-
+-#ifdef CONFIG_QETH_IPV6
+-out_ipv4:
+- unregister_inetaddr_notifier(&qeth_ip_notifier);
+-#endif
+-out_reboot:
+- unregister_reboot_notifier(&qeth_reboot_notifier);
+- return r;
+-}
+-
+-/**
+- * unregister all event notifiers
+- */
+-static void
+-qeth_unregister_notifiers(void)
+-{
+-
+- QETH_DBF_TEXT(trace,5,"unregnot");
+- BUG_ON(unregister_reboot_notifier(&qeth_reboot_notifier));
+- BUG_ON(unregister_inetaddr_notifier(&qeth_ip_notifier));
+-#ifdef CONFIG_QETH_IPV6
+- BUG_ON(unregister_inet6addr_notifier(&qeth_ip6_notifier));
+-#endif /* QETH_IPV6 */
+-
+-}
+-
+-#ifdef CONFIG_QETH_IPV6
+-static int
+-qeth_ipv6_init(void)
+-{
+- qeth_old_arp_constructor = arp_tbl.constructor;
+- write_lock_bh(&arp_tbl.lock);
+- arp_tbl.constructor = qeth_arp_constructor;
+- write_unlock_bh(&arp_tbl.lock);
+-
+- arp_direct_ops = (struct neigh_ops*)
+- kmalloc(sizeof(struct neigh_ops), GFP_KERNEL);
+- if (!arp_direct_ops)
+- return -ENOMEM;
+-
+- memcpy(arp_direct_ops, &arp_direct_ops_template,
+- sizeof(struct neigh_ops));
+-
+- return 0;
+-}
+-
+-static void
+-qeth_ipv6_uninit(void)
+-{
+- write_lock_bh(&arp_tbl.lock);
+- arp_tbl.constructor = qeth_old_arp_constructor;
+- write_unlock_bh(&arp_tbl.lock);
+- kfree(arp_direct_ops);
+-}
+-#endif /* CONFIG_QETH_IPV6 */
+-
+-static void
+-qeth_sysfs_unregister(void)
+-{
+- s390_root_dev_unregister(qeth_root_dev);
+- qeth_remove_driver_attributes();
+- ccw_driver_unregister(&qeth_ccw_driver);
+- ccwgroup_driver_unregister(&qeth_ccwgroup_driver);
+-}
+-
+-/**
+- * register qeth at sysfs
+- */
+-static int
+-qeth_sysfs_register(void)
+-{
+- int rc;
+-
+- rc = ccwgroup_driver_register(&qeth_ccwgroup_driver);
+- if (rc)
+- goto out;
+-
+- rc = ccw_driver_register(&qeth_ccw_driver);
+- if (rc)
+- goto out_ccw_driver;
+-
+- rc = qeth_create_driver_attributes();
+- if (rc)
+- goto out_qeth_attr;
+-
+- qeth_root_dev = s390_root_dev_register("qeth");
+- rc = IS_ERR(qeth_root_dev) ? PTR_ERR(qeth_root_dev) : 0;
+- if (!rc)
+- goto out;
+-
+- qeth_remove_driver_attributes();
+-out_qeth_attr:
+- ccw_driver_unregister(&qeth_ccw_driver);
+-out_ccw_driver:
+- ccwgroup_driver_unregister(&qeth_ccwgroup_driver);
+-out:
+- return rc;
+-}
+-
+-/***
+- * init function
+- */
+-static int __init
+-qeth_init(void)
+-{
+- int rc;
+-
+- PRINT_INFO("loading %s\n", version);
+-
+- INIT_LIST_HEAD(&qeth_card_list.list);
+- INIT_LIST_HEAD(&qeth_notify_list);
+- spin_lock_init(&qeth_notify_lock);
+- rwlock_init(&qeth_card_list.rwlock);
+-
+- rc = qeth_register_dbf_views();
+- if (rc)
+- goto out_err;
+-
+- rc = qeth_sysfs_register();
+- if (rc)
+- goto out_dbf;
+-
+-#ifdef CONFIG_QETH_IPV6
+- rc = qeth_ipv6_init();
+- if (rc) {
+- PRINT_ERR("Out of memory during ipv6 init code = %d\n", rc);
+- goto out_sysfs;
+- }
+-#endif /* QETH_IPV6 */
+- rc = qeth_register_notifiers();
+- if (rc)
+- goto out_ipv6;
+- rc = qeth_create_procfs_entries();
+- if (rc)
+- goto out_notifiers;
+-
+- return rc;
+-
+-out_notifiers:
+- qeth_unregister_notifiers();
+-out_ipv6:
+-#ifdef CONFIG_QETH_IPV6
+- qeth_ipv6_uninit();
+-out_sysfs:
+-#endif /* QETH_IPV6 */
+- qeth_sysfs_unregister();
+-out_dbf:
+- qeth_unregister_dbf_views();
+-out_err:
+- PRINT_ERR("Initialization failed with code %d\n", rc);
+- return rc;
+-}
+-
+-static void
+-__exit qeth_exit(void)
+-{
+- struct qeth_card *card, *tmp;
+- unsigned long flags;
+-
+- QETH_DBF_TEXT(trace,1, "cleanup.");
+-
+- /*
+- * Weed would not need to clean up our devices here, because the
+- * common device layer calls qeth_remove_device for each device
+- * as soon as we unregister our driver (done in qeth_sysfs_unregister).
+- * But we do cleanup here so we can do a "soft" shutdown of our cards.
+- * qeth_remove_device called by the common device layer would otherwise
+- * do a "hard" shutdown (card->use_hard_stop is set to one in
+- * qeth_remove_device).
+- */
+-again:
+- read_lock_irqsave(&qeth_card_list.rwlock, flags);
+- list_for_each_entry_safe(card, tmp, &qeth_card_list.list, list){
+- read_unlock_irqrestore(&qeth_card_list.rwlock, flags);
+- qeth_set_offline(card->gdev);
+- qeth_remove_device(card->gdev);
+- goto again;
+- }
+- read_unlock_irqrestore(&qeth_card_list.rwlock, flags);
+-#ifdef CONFIG_QETH_IPV6
+- qeth_ipv6_uninit();
+-#endif
+- qeth_unregister_notifiers();
+- qeth_remove_procfs_entries();
+- qeth_sysfs_unregister();
+- qeth_unregister_dbf_views();
+- printk("qeth: removed\n");
+-}
+-
+-EXPORT_SYMBOL(qeth_osn_register);
+-EXPORT_SYMBOL(qeth_osn_deregister);
+-EXPORT_SYMBOL(qeth_osn_assist);
+-module_init(qeth_init);
+-module_exit(qeth_exit);
+-MODULE_AUTHOR("Frank Pavlic <fpavlic at de.ibm.com>");
+-MODULE_DESCRIPTION("Linux on zSeries OSA Express and HiperSockets support\n" \
+- "Copyright 2000,2003 IBM Corporation\n");
+-
+-MODULE_LICENSE("GPL");
+diff --git a/drivers/s390/net/qeth_mpc.c b/drivers/s390/net/qeth_mpc.c
+deleted file mode 100644
+index f29a4bc..0000000
+--- a/drivers/s390/net/qeth_mpc.c
++++ /dev/null
+@@ -1,269 +0,0 @@
+-/*
+- * linux/drivers/s390/net/qeth_mpc.c
+- *
+- * Linux on zSeries OSA Express and HiperSockets support
+- *
+- * Copyright 2000,2003 IBM Corporation
+- * Author(s): Frank Pavlic <fpavlic at de.ibm.com>
+- * Thomas Spatzier <tspat at de.ibm.com>
+- *
+- */
+-#include <asm/cio.h>
+-#include "qeth_mpc.h"
+-
+-unsigned char IDX_ACTIVATE_READ[]={
+- 0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x00,
+- 0x19,0x01,0x01,0x80, 0x00,0x00,0x00,0x00,
+- 0x00,0x00,0x00,0x00, 0x00,0x00,0xc8,0xc1,
+- 0xd3,0xd3,0xd6,0xd3, 0xc5,0x40,0x00,0x00,
+- 0x00,0x00
+-};
+-
+-unsigned char IDX_ACTIVATE_WRITE[]={
+- 0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x00,
+- 0x15,0x01,0x01,0x80, 0x00,0x00,0x00,0x00,
+- 0xff,0xff,0x00,0x00, 0x00,0x00,0xc8,0xc1,
+- 0xd3,0xd3,0xd6,0xd3, 0xc5,0x40,0x00,0x00,
+- 0x00,0x00
+-};
+-
+-unsigned char CM_ENABLE[]={
+- 0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x01,
+- 0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x63,
+- 0x10,0x00,0x00,0x01,
+- 0x00,0x00,0x00,0x00,
+- 0x81,0x7e,0x00,0x01, 0x00,0x00,0x00,0x00,
+- 0x00,0x00,0x00,0x00, 0x00,0x24,0x00,0x23,
+- 0x00,0x00,0x23,0x05, 0x00,0x00,0x00,0x00,
+- 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+- 0x01,0x00,0x00,0x23, 0x00,0x00,0x00,0x40,
+- 0x00,0x0c,0x41,0x02, 0x00,0x17,0x00,0x00,
+- 0x00,0x00,0x00,0x00,
+- 0x00,0x0b,0x04,0x01,
+- 0x7e,0x04,0x05,0x00, 0x01,0x01,0x0f,
+- 0x00,
+- 0x0c,0x04,0x02,0xff, 0xff,0xff,0xff,0xff,
+- 0xff,0xff,0xff
+-};
+-
+-unsigned char CM_SETUP[]={
+- 0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x02,
+- 0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x64,
+- 0x10,0x00,0x00,0x01,
+- 0x00,0x00,0x00,0x00,
+- 0x81,0x7e,0x00,0x01, 0x00,0x00,0x00,0x00,
+- 0x00,0x00,0x00,0x00, 0x00,0x24,0x00,0x24,
+- 0x00,0x00,0x24,0x05, 0x00,0x00,0x00,0x00,
+- 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+- 0x01,0x00,0x00,0x24, 0x00,0x00,0x00,0x40,
+- 0x00,0x0c,0x41,0x04, 0x00,0x18,0x00,0x00,
+- 0x00,0x00,0x00,0x00,
+- 0x00,0x09,0x04,0x04,
+- 0x05,0x00,0x01,0x01, 0x11,
+- 0x00,0x09,0x04,
+- 0x05,0x05,0x00,0x00, 0x00,0x00,
+- 0x00,0x06,
+- 0x04,0x06,0xc8,0x00
+-};
+-
+-unsigned char ULP_ENABLE[]={
+- 0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x03,
+- 0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x6b,
+- 0x10,0x00,0x00,0x01,
+- 0x00,0x00,0x00,0x00,
+- 0x41,0x7e,0x00,0x01, 0x00,0x00,0x00,0x01,
+- 0x00,0x00,0x00,0x00, 0x00,0x24,0x00,0x2b,
+- 0x00,0x00,0x2b,0x05, 0x20,0x01,0x00,0x00,
+- 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+- 0x01,0x00,0x00,0x2b, 0x00,0x00,0x00,0x40,
+- 0x00,0x0c,0x41,0x02, 0x00,0x1f,0x00,0x00,
+- 0x00,0x00,0x00,0x00,
+- 0x00,0x0b,0x04,0x01,
+- 0x03,0x04,0x05,0x00, 0x01,0x01,0x12,
+- 0x00,
+- 0x14,0x04,0x0a,0x00, 0x20,0x00,0x00,0xff,
+- 0xff,0x00,0x08,0xc8, 0xe8,0xc4,0xf1,0xc7,
+- 0xf1,0x00,0x00
+-};
+-
+-unsigned char ULP_SETUP[]={
+- 0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x04,
+- 0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x6c,
+- 0x10,0x00,0x00,0x01,
+- 0x00,0x00,0x00,0x00,
+- 0x41,0x7e,0x00,0x01, 0x00,0x00,0x00,0x02,
+- 0x00,0x00,0x00,0x01, 0x00,0x24,0x00,0x2c,
+- 0x00,0x00,0x2c,0x05, 0x20,0x01,0x00,0x00,
+- 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+- 0x01,0x00,0x00,0x2c, 0x00,0x00,0x00,0x40,
+- 0x00,0x0c,0x41,0x04, 0x00,0x20,0x00,0x00,
+- 0x00,0x00,0x00,0x00,
+- 0x00,0x09,0x04,0x04,
+- 0x05,0x00,0x01,0x01, 0x14,
+- 0x00,0x09,0x04,
+- 0x05,0x05,0x30,0x01, 0x00,0x00,
+- 0x00,0x06,
+- 0x04,0x06,0x40,0x00,
+- 0x00,0x08,0x04,0x0b,
+- 0x00,0x00,0x00,0x00
+-};
+-
+-unsigned char DM_ACT[]={
+- 0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x05,
+- 0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x55,
+- 0x10,0x00,0x00,0x01,
+- 0x00,0x00,0x00,0x00,
+- 0x41,0x7e,0x00,0x01, 0x00,0x00,0x00,0x03,
+- 0x00,0x00,0x00,0x02, 0x00,0x24,0x00,0x15,
+- 0x00,0x00,0x2c,0x05, 0x20,0x01,0x00,0x00,
+- 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+- 0x01,0x00,0x00,0x15, 0x00,0x00,0x00,0x40,
+- 0x00,0x0c,0x43,0x60, 0x00,0x09,0x00,0x00,
+- 0x00,0x00,0x00,0x00,
+- 0x00,0x09,0x04,0x04,
+- 0x05,0x40,0x01,0x01, 0x00
+-};
+-
+-unsigned char IPA_PDU_HEADER[]={
+- 0x00,0xe0,0x00,0x00, 0x77,0x77,0x77,0x77,
+- 0x00,0x00,0x00,0x14, 0x00,0x00,
+- (IPA_PDU_HEADER_SIZE+sizeof(struct qeth_ipa_cmd))/256,
+- (IPA_PDU_HEADER_SIZE+sizeof(struct qeth_ipa_cmd))%256,
+- 0x10,0x00,0x00,0x01, 0x00,0x00,0x00,0x00,
+- 0xc1,0x03,0x00,0x01, 0x00,0x00,0x00,0x00,
+- 0x00,0x00,0x00,0x00, 0x00,0x24,
+- sizeof(struct qeth_ipa_cmd)/256,
+- sizeof(struct qeth_ipa_cmd)%256,
+- 0x00,
+- sizeof(struct qeth_ipa_cmd)/256,
+- sizeof(struct qeth_ipa_cmd)%256,
+- 0x05,
+- 0x77,0x77,0x77,0x77,
+- 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+- 0x01,0x00,
+- sizeof(struct qeth_ipa_cmd)/256,
+- sizeof(struct qeth_ipa_cmd)%256,
+- 0x00,0x00,0x00,0x40,
+-};
+-
+-unsigned char WRITE_CCW[]={
+- 0x01,CCW_FLAG_SLI,0,0,
+- 0,0,0,0
+-};
+-
+-unsigned char READ_CCW[]={
+- 0x02,CCW_FLAG_SLI,0,0,
+- 0,0,0,0
+-};
+-
+-
+-struct ipa_rc_msg {
+- enum qeth_ipa_return_codes rc;
+- char *msg;
+-};
+-
+-static struct ipa_rc_msg qeth_ipa_rc_msg[] = {
+- {IPA_RC_SUCCESS, "success"},
+- {IPA_RC_NOTSUPP, "Command not supported"},
+- {IPA_RC_IP_TABLE_FULL, "Add Addr IP Table Full - ipv6"},
+- {IPA_RC_UNKNOWN_ERROR, "IPA command failed - reason unknown"},
+- {IPA_RC_UNSUPPORTED_COMMAND, "Command not supported"},
+- {IPA_RC_DUP_IPV6_REMOTE,"ipv6 address already registered remote"},
+- {IPA_RC_DUP_IPV6_HOME, "ipv6 address already registered"},
+- {IPA_RC_UNREGISTERED_ADDR, "Address not registered"},
+- {IPA_RC_NO_ID_AVAILABLE, "No identifiers available"},
+- {IPA_RC_ID_NOT_FOUND, "Identifier not found"},
+- {IPA_RC_INVALID_IP_VERSION, "IP version incorrect"},
+- {IPA_RC_LAN_FRAME_MISMATCH, "LAN and frame mismatch"},
+- {IPA_RC_L2_UNSUPPORTED_CMD, "Unsupported layer 2 command"},
+- {IPA_RC_L2_DUP_MAC, "Duplicate MAC address"},
+- {IPA_RC_L2_ADDR_TABLE_FULL, "Layer2 address table full"},
+- {IPA_RC_L2_DUP_LAYER3_MAC, "Duplicate with layer 3 MAC"},
+- {IPA_RC_L2_GMAC_NOT_FOUND, "GMAC not found"},
+- {IPA_RC_L2_MAC_NOT_FOUND, "L2 mac address not found"},
+- {IPA_RC_L2_INVALID_VLAN_ID, "L2 invalid vlan id"},
+- {IPA_RC_L2_DUP_VLAN_ID, "L2 duplicate vlan id"},
+- {IPA_RC_L2_VLAN_ID_NOT_FOUND, "L2 vlan id not found"},
+- {IPA_RC_DATA_MISMATCH, "Data field mismatch (v4/v6 mixed)"},
+- {IPA_RC_INVALID_MTU_SIZE, "Invalid MTU size"},
+- {IPA_RC_INVALID_LANTYPE, "Invalid LAN type"},
+- {IPA_RC_INVALID_LANNUM, "Invalid LAN num"},
+- {IPA_RC_DUPLICATE_IP_ADDRESS, "Address already registered"},
+- {IPA_RC_IP_ADDR_TABLE_FULL, "IP address table full"},
+- {IPA_RC_LAN_PORT_STATE_ERROR, "LAN port state error"},
+- {IPA_RC_SETIP_NO_STARTLAN, "Setip no startlan received"},
+- {IPA_RC_SETIP_ALREADY_RECEIVED, "Setip already received"},
+- {IPA_RC_IP_ADDR_ALREADY_USED, "IP address already in use on LAN"},
+- {IPA_RC_MULTICAST_FULL, "No task available, multicast full"},
+- {IPA_RC_SETIP_INVALID_VERSION, "SETIP invalid IP version"},
+- {IPA_RC_UNSUPPORTED_SUBCMD, "Unsupported assist subcommand"},
+- {IPA_RC_ARP_ASSIST_NO_ENABLE, "Only partial success, no enable"},
+- {IPA_RC_PRIMARY_ALREADY_DEFINED,"Primary already defined"},
+- {IPA_RC_SECOND_ALREADY_DEFINED, "Secondary already defined"},
+- {IPA_RC_INVALID_SETRTG_INDICATOR,"Invalid SETRTG indicator"},
+- {IPA_RC_MC_ADDR_ALREADY_DEFINED,"Multicast address already defined"},
+- {IPA_RC_LAN_OFFLINE, "STRTLAN_LAN_DISABLED - LAN offline"},
+- {IPA_RC_INVALID_IP_VERSION2, "Invalid IP version"},
+- {IPA_RC_FFFF, "Unknown Error"}
+-};
+-
+-
+-
+-char *
+-qeth_get_ipa_msg(enum qeth_ipa_return_codes rc)
+-{
+- int x = 0;
+- qeth_ipa_rc_msg[sizeof(qeth_ipa_rc_msg) /
+- sizeof(struct ipa_rc_msg) - 1].rc = rc;
+- while(qeth_ipa_rc_msg[x].rc != rc)
+- x++;
+- return qeth_ipa_rc_msg[x].msg;
+-}
+-
+-
+-struct ipa_cmd_names {
+- enum qeth_ipa_cmds cmd;
+- char *name;
+-};
+-
+-static struct ipa_cmd_names qeth_ipa_cmd_names[] = {
+- {IPA_CMD_STARTLAN, "startlan"},
+- {IPA_CMD_STOPLAN, "stoplan"},
+- {IPA_CMD_SETVMAC, "setvmac"},
+- {IPA_CMD_DELVMAC, "delvmca"},
+- {IPA_CMD_SETGMAC, "setgmac"},
+- {IPA_CMD_DELGMAC, "delgmac"},
+- {IPA_CMD_SETVLAN, "setvlan"},
+- {IPA_CMD_DELVLAN, "delvlan"},
+- {IPA_CMD_SETCCID, "setccid"},
+- {IPA_CMD_DELCCID, "delccid"},
+- {IPA_CMD_MODCCID, "setip"},
+- {IPA_CMD_SETIP, "setip"},
+- {IPA_CMD_QIPASSIST, "qipassist"},
+- {IPA_CMD_SETASSPARMS, "setassparms"},
+- {IPA_CMD_SETIPM, "setipm"},
+- {IPA_CMD_DELIPM, "delipm"},
+- {IPA_CMD_SETRTG, "setrtg"},
+- {IPA_CMD_DELIP, "delip"},
+- {IPA_CMD_SETADAPTERPARMS, "setadapterparms"},
+- {IPA_CMD_SET_DIAG_ASS, "set_diag_ass"},
+- {IPA_CMD_CREATE_ADDR, "create_addr"},
+- {IPA_CMD_DESTROY_ADDR, "destroy_addr"},
+- {IPA_CMD_REGISTER_LOCAL_ADDR, "register_local_addr"},
+- {IPA_CMD_UNREGISTER_LOCAL_ADDR, "unregister_local_addr"},
+- {IPA_CMD_UNKNOWN, "unknown"},
+-};
+-
+-char *
+-qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd)
+-{
+- int x = 0;
+- qeth_ipa_cmd_names[
+- sizeof(qeth_ipa_cmd_names)/
+- sizeof(struct ipa_cmd_names)-1].cmd = cmd;
+- while(qeth_ipa_cmd_names[x].cmd != cmd)
+- x++;
+- return qeth_ipa_cmd_names[x].name;
+-}
+-
+-
+diff --git a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h
+deleted file mode 100644
+index 6de2da5..0000000
+--- a/drivers/s390/net/qeth_mpc.h
++++ /dev/null
+@@ -1,583 +0,0 @@
+-/*
+- * linux/drivers/s390/net/qeth_mpc.h
+- *
+- * Linux on zSeries OSA Express and HiperSockets support
+- *
+- * Copyright 2000,2003 IBM Corporation
+- * Author(s): Utz Bacher <utz.bacher at de.ibm.com>
+- * Thomas Spatzier <tspat at de.ibm.com>
+- * Frank Pavlic <fpavlic at de.ibm.com>
+- *
+- */
+-#ifndef __QETH_MPC_H__
+-#define __QETH_MPC_H__
+-
+-#include <asm/qeth.h>
+-
+-#define IPA_PDU_HEADER_SIZE 0x40
+-#define QETH_IPA_PDU_LEN_TOTAL(buffer) (buffer+0x0e)
+-#define QETH_IPA_PDU_LEN_PDU1(buffer) (buffer+0x26)
+-#define QETH_IPA_PDU_LEN_PDU2(buffer) (buffer+0x29)
+-#define QETH_IPA_PDU_LEN_PDU3(buffer) (buffer+0x3a)
+-
+-extern unsigned char IPA_PDU_HEADER[];
+-#define QETH_IPA_CMD_DEST_ADDR(buffer) (buffer+0x2c)
+-
+-#define IPA_CMD_LENGTH (IPA_PDU_HEADER_SIZE + sizeof(struct qeth_ipa_cmd))
+-
+-#define QETH_SEQ_NO_LENGTH 4
+-#define QETH_MPC_TOKEN_LENGTH 4
+-#define QETH_MCL_LENGTH 4
+-#define OSA_ADDR_LEN 6
+-
+-#define QETH_TIMEOUT (10 * HZ)
+-#define QETH_IPA_TIMEOUT (45 * HZ)
+-#define QETH_IDX_COMMAND_SEQNO 0xffff0000
+-#define SR_INFO_LEN 16
+-
+-#define QETH_CLEAR_CHANNEL_PARM -10
+-#define QETH_HALT_CHANNEL_PARM -11
+-#define QETH_RCD_PARM -12
+-
+-/*****************************************************************************/
+-/* IP Assist related definitions */
+-/*****************************************************************************/
+-#define IPA_CMD_INITIATOR_HOST 0x00
+-#define IPA_CMD_INITIATOR_OSA 0x01
+-#define IPA_CMD_INITIATOR_HOST_REPLY 0x80
+-#define IPA_CMD_INITIATOR_OSA_REPLY 0x81
+-#define IPA_CMD_PRIM_VERSION_NO 0x01
+-
+-enum qeth_card_types {
+- QETH_CARD_TYPE_UNKNOWN = 0,
+- QETH_CARD_TYPE_OSAE = 10,
+- QETH_CARD_TYPE_IQD = 1234,
+- QETH_CARD_TYPE_OSN = 11,
+-};
+-
+-#define QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE 0x18
+-/* only the first two bytes are looked at in qeth_get_cardname_short */
+-enum qeth_link_types {
+- QETH_LINK_TYPE_FAST_ETH = 0x01,
+- QETH_LINK_TYPE_HSTR = 0x02,
+- QETH_LINK_TYPE_GBIT_ETH = 0x03,
+- QETH_LINK_TYPE_OSN = 0x04,
+- QETH_LINK_TYPE_10GBIT_ETH = 0x10,
+- QETH_LINK_TYPE_LANE_ETH100 = 0x81,
+- QETH_LINK_TYPE_LANE_TR = 0x82,
+- QETH_LINK_TYPE_LANE_ETH1000 = 0x83,
+- QETH_LINK_TYPE_LANE = 0x88,
+- QETH_LINK_TYPE_ATM_NATIVE = 0x90,
+-};
+-
+-enum qeth_tr_macaddr_modes {
+- QETH_TR_MACADDR_NONCANONICAL = 0,
+- QETH_TR_MACADDR_CANONICAL = 1,
+-};
+-
+-enum qeth_tr_broadcast_modes {
+- QETH_TR_BROADCAST_ALLRINGS = 0,
+- QETH_TR_BROADCAST_LOCAL = 1,
+-};
+-
+-/* these values match CHECKSUM_* in include/linux/skbuff.h */
+-enum qeth_checksum_types {
+- SW_CHECKSUMMING = 0, /* TODO: set to bit flag used in IPA Command */
+- HW_CHECKSUMMING = 1,
+- NO_CHECKSUMMING = 2,
+-};
+-#define QETH_CHECKSUM_DEFAULT SW_CHECKSUMMING
+-
+-/*
+- * Routing stuff
+- */
+-#define RESET_ROUTING_FLAG 0x10 /* indicate that routing type shall be set */
+-enum qeth_routing_types {
+- NO_ROUTER = 0, /* TODO: set to bit flag used in IPA Command */
+- PRIMARY_ROUTER = 1,
+- SECONDARY_ROUTER = 2,
+- MULTICAST_ROUTER = 3,
+- PRIMARY_CONNECTOR = 4,
+- SECONDARY_CONNECTOR = 5,
+-};
+-
+-/* IPA Commands */
+-enum qeth_ipa_cmds {
+- IPA_CMD_STARTLAN = 0x01,
+- IPA_CMD_STOPLAN = 0x02,
+- IPA_CMD_SETVMAC = 0x21,
+- IPA_CMD_DELVMAC = 0x22,
+- IPA_CMD_SETGMAC = 0x23,
+- IPA_CMD_DELGMAC = 0x24,
+- IPA_CMD_SETVLAN = 0x25,
+- IPA_CMD_DELVLAN = 0x26,
+- IPA_CMD_SETCCID = 0x41,
+- IPA_CMD_DELCCID = 0x42,
+- IPA_CMD_MODCCID = 0x43,
+- IPA_CMD_SETIP = 0xb1,
+- IPA_CMD_QIPASSIST = 0xb2,
+- IPA_CMD_SETASSPARMS = 0xb3,
+- IPA_CMD_SETIPM = 0xb4,
+- IPA_CMD_DELIPM = 0xb5,
+- IPA_CMD_SETRTG = 0xb6,
+- IPA_CMD_DELIP = 0xb7,
+- IPA_CMD_SETADAPTERPARMS = 0xb8,
+- IPA_CMD_SET_DIAG_ASS = 0xb9,
+- IPA_CMD_CREATE_ADDR = 0xc3,
+- IPA_CMD_DESTROY_ADDR = 0xc4,
+- IPA_CMD_REGISTER_LOCAL_ADDR = 0xd1,
+- IPA_CMD_UNREGISTER_LOCAL_ADDR = 0xd2,
+- IPA_CMD_UNKNOWN = 0x00
+-};
+-
+-enum qeth_ip_ass_cmds {
+- IPA_CMD_ASS_START = 0x0001,
+- IPA_CMD_ASS_STOP = 0x0002,
+- IPA_CMD_ASS_CONFIGURE = 0x0003,
+- IPA_CMD_ASS_ENABLE = 0x0004,
+-};
+-
+-enum qeth_arp_process_subcmds {
+- IPA_CMD_ASS_ARP_SET_NO_ENTRIES = 0x0003,
+- IPA_CMD_ASS_ARP_QUERY_CACHE = 0x0004,
+- IPA_CMD_ASS_ARP_ADD_ENTRY = 0x0005,
+- IPA_CMD_ASS_ARP_REMOVE_ENTRY = 0x0006,
+- IPA_CMD_ASS_ARP_FLUSH_CACHE = 0x0007,
+- IPA_CMD_ASS_ARP_QUERY_INFO = 0x0104,
+- IPA_CMD_ASS_ARP_QUERY_STATS = 0x0204,
+-};
+-
+-
+-/* Return Codes for IPA Commands
+- * according to OSA card Specs */
+-
+-enum qeth_ipa_return_codes {
+- IPA_RC_SUCCESS = 0x0000,
+- IPA_RC_NOTSUPP = 0x0001,
+- IPA_RC_IP_TABLE_FULL = 0x0002,
+- IPA_RC_UNKNOWN_ERROR = 0x0003,
+- IPA_RC_UNSUPPORTED_COMMAND = 0x0004,
+- IPA_RC_DUP_IPV6_REMOTE = 0x0008,
+- IPA_RC_DUP_IPV6_HOME = 0x0010,
+- IPA_RC_UNREGISTERED_ADDR = 0x0011,
+- IPA_RC_NO_ID_AVAILABLE = 0x0012,
+- IPA_RC_ID_NOT_FOUND = 0x0013,
+- IPA_RC_INVALID_IP_VERSION = 0x0020,
+- IPA_RC_LAN_FRAME_MISMATCH = 0x0040,
+- IPA_RC_L2_UNSUPPORTED_CMD = 0x2003,
+- IPA_RC_L2_DUP_MAC = 0x2005,
+- IPA_RC_L2_ADDR_TABLE_FULL = 0x2006,
+- IPA_RC_L2_DUP_LAYER3_MAC = 0x200a,
+- IPA_RC_L2_GMAC_NOT_FOUND = 0x200b,
+- IPA_RC_L2_MAC_NOT_FOUND = 0x2010,
+- IPA_RC_L2_INVALID_VLAN_ID = 0x2015,
+- IPA_RC_L2_DUP_VLAN_ID = 0x2016,
+- IPA_RC_L2_VLAN_ID_NOT_FOUND = 0x2017,
+- IPA_RC_DATA_MISMATCH = 0xe001,
+- IPA_RC_INVALID_MTU_SIZE = 0xe002,
+- IPA_RC_INVALID_LANTYPE = 0xe003,
+- IPA_RC_INVALID_LANNUM = 0xe004,
+- IPA_RC_DUPLICATE_IP_ADDRESS = 0xe005,
+- IPA_RC_IP_ADDR_TABLE_FULL = 0xe006,
+- IPA_RC_LAN_PORT_STATE_ERROR = 0xe007,
+- IPA_RC_SETIP_NO_STARTLAN = 0xe008,
+- IPA_RC_SETIP_ALREADY_RECEIVED = 0xe009,
+- IPA_RC_IP_ADDR_ALREADY_USED = 0xe00a,
+- IPA_RC_MULTICAST_FULL = 0xe00b,
+- IPA_RC_SETIP_INVALID_VERSION = 0xe00d,
+- IPA_RC_UNSUPPORTED_SUBCMD = 0xe00e,
+- IPA_RC_ARP_ASSIST_NO_ENABLE = 0xe00f,
+- IPA_RC_PRIMARY_ALREADY_DEFINED = 0xe010,
+- IPA_RC_SECOND_ALREADY_DEFINED = 0xe011,
+- IPA_RC_INVALID_SETRTG_INDICATOR = 0xe012,
+- IPA_RC_MC_ADDR_ALREADY_DEFINED = 0xe013,
+- IPA_RC_LAN_OFFLINE = 0xe080,
+- IPA_RC_INVALID_IP_VERSION2 = 0xf001,
+- IPA_RC_FFFF = 0xffff
+-};
+-
+-/* IPA function flags; each flag marks availability of respective function */
+-enum qeth_ipa_funcs {
+- IPA_ARP_PROCESSING = 0x00000001L,
+- IPA_INBOUND_CHECKSUM = 0x00000002L,
+- IPA_OUTBOUND_CHECKSUM = 0x00000004L,
+- IPA_IP_FRAGMENTATION = 0x00000008L,
+- IPA_FILTERING = 0x00000010L,
+- IPA_IPV6 = 0x00000020L,
+- IPA_MULTICASTING = 0x00000040L,
+- IPA_IP_REASSEMBLY = 0x00000080L,
+- IPA_QUERY_ARP_COUNTERS = 0x00000100L,
+- IPA_QUERY_ARP_ADDR_INFO = 0x00000200L,
+- IPA_SETADAPTERPARMS = 0x00000400L,
+- IPA_VLAN_PRIO = 0x00000800L,
+- IPA_PASSTHRU = 0x00001000L,
+- IPA_FLUSH_ARP_SUPPORT = 0x00002000L,
+- IPA_FULL_VLAN = 0x00004000L,
+- IPA_INBOUND_PASSTHRU = 0x00008000L,
+- IPA_SOURCE_MAC = 0x00010000L,
+- IPA_OSA_MC_ROUTER = 0x00020000L,
+- IPA_QUERY_ARP_ASSIST = 0x00040000L,
+- IPA_INBOUND_TSO = 0x00080000L,
+- IPA_OUTBOUND_TSO = 0x00100000L,
+-};
+-
+-/* SETIP/DELIP IPA Command: ***************************************************/
+-enum qeth_ipa_setdelip_flags {
+- QETH_IPA_SETDELIP_DEFAULT = 0x00L, /* default */
+- QETH_IPA_SETIP_VIPA_FLAG = 0x01L, /* no grat. ARP */
+- QETH_IPA_SETIP_TAKEOVER_FLAG = 0x02L, /* nofail on grat. ARP */
+- QETH_IPA_DELIP_ADDR_2_B_TAKEN_OVER = 0x20L,
+- QETH_IPA_DELIP_VIPA_FLAG = 0x40L,
+- QETH_IPA_DELIP_ADDR_NEEDS_SETIP = 0x80L,
+-};
+-
+-/* SETADAPTER IPA Command: ****************************************************/
+-enum qeth_ipa_setadp_cmd {
+- IPA_SETADP_QUERY_COMMANDS_SUPPORTED = 0x01,
+- IPA_SETADP_ALTER_MAC_ADDRESS = 0x02,
+- IPA_SETADP_ADD_DELETE_GROUP_ADDRESS = 0x04,
+- IPA_SETADP_ADD_DELETE_FUNCTIONAL_ADDR = 0x08,
+- IPA_SETADP_SET_ADDRESSING_MODE = 0x10,
+- IPA_SETADP_SET_CONFIG_PARMS = 0x20,
+- IPA_SETADP_SET_CONFIG_PARMS_EXTENDED = 0x40,
+- IPA_SETADP_SET_BROADCAST_MODE = 0x80,
+- IPA_SETADP_SEND_OSA_MESSAGE = 0x0100,
+- IPA_SETADP_SET_SNMP_CONTROL = 0x0200,
+- IPA_SETADP_QUERY_CARD_INFO = 0x0400,
+- IPA_SETADP_SET_PROMISC_MODE = 0x0800,
+-};
+-enum qeth_ipa_mac_ops {
+- CHANGE_ADDR_READ_MAC = 0,
+- CHANGE_ADDR_REPLACE_MAC = 1,
+- CHANGE_ADDR_ADD_MAC = 2,
+- CHANGE_ADDR_DEL_MAC = 4,
+- CHANGE_ADDR_RESET_MAC = 8,
+-};
+-enum qeth_ipa_addr_ops {
+- CHANGE_ADDR_READ_ADDR = 0,
+- CHANGE_ADDR_ADD_ADDR = 1,
+- CHANGE_ADDR_DEL_ADDR = 2,
+- CHANGE_ADDR_FLUSH_ADDR_TABLE = 4,
+-};
+-enum qeth_ipa_promisc_modes {
+- SET_PROMISC_MODE_OFF = 0,
+- SET_PROMISC_MODE_ON = 1,
+-};
+-
+-/* (SET)DELIP(M) IPA stuff ***************************************************/
+-struct qeth_ipacmd_setdelip4 {
+- __u8 ip_addr[4];
+- __u8 mask[4];
+- __u32 flags;
+-} __attribute__ ((packed));
+-
+-struct qeth_ipacmd_setdelip6 {
+- __u8 ip_addr[16];
+- __u8 mask[16];
+- __u32 flags;
+-} __attribute__ ((packed));
+-
+-struct qeth_ipacmd_setdelipm {
+- __u8 mac[6];
+- __u8 padding[2];
+- __u8 ip6[12];
+- __u8 ip4[4];
+-} __attribute__ ((packed));
+-
+-struct qeth_ipacmd_layer2setdelmac {
+- __u32 mac_length;
+- __u8 mac[6];
+-} __attribute__ ((packed));
+-
+-struct qeth_ipacmd_layer2setdelvlan {
+- __u16 vlan_id;
+-} __attribute__ ((packed));
+-
+-
+-struct qeth_ipacmd_setassparms_hdr {
+- __u32 assist_no;
+- __u16 length;
+- __u16 command_code;
+- __u16 return_code;
+- __u8 number_of_replies;
+- __u8 seq_no;
+-} __attribute__((packed));
+-
+-struct qeth_arp_query_data {
+- __u16 request_bits;
+- __u16 reply_bits;
+- __u32 no_entries;
+- char data;
+-} __attribute__((packed));
+-
+-/* used as parameter for arp_query reply */
+-struct qeth_arp_query_info {
+- __u32 udata_len;
+- __u16 mask_bits;
+- __u32 udata_offset;
+- __u32 no_entries;
+- char *udata;
+-};
+-
+-/* SETASSPARMS IPA Command: */
+-struct qeth_ipacmd_setassparms {
+- struct qeth_ipacmd_setassparms_hdr hdr;
+- union {
+- __u32 flags_32bit;
+- struct qeth_arp_cache_entry add_arp_entry;
+- struct qeth_arp_query_data query_arp;
+- __u8 ip[16];
+- } data;
+-} __attribute__ ((packed));
+-
+-
+-/* SETRTG IPA Command: ****************************************************/
+-struct qeth_set_routing {
+- __u8 type;
+-};
+-
+-/* SETADAPTERPARMS IPA Command: *******************************************/
+-struct qeth_query_cmds_supp {
+- __u32 no_lantypes_supp;
+- __u8 lan_type;
+- __u8 reserved1[3];
+- __u32 supported_cmds;
+- __u8 reserved2[8];
+-} __attribute__ ((packed));
+-
+-struct qeth_change_addr {
+- __u32 cmd;
+- __u32 addr_size;
+- __u32 no_macs;
+- __u8 addr[OSA_ADDR_LEN];
+-} __attribute__ ((packed));
+-
+-
+-struct qeth_snmp_cmd {
+- __u8 token[16];
+- __u32 request;
+- __u32 interface;
+- __u32 returncode;
+- __u32 firmwarelevel;
+- __u32 seqno;
+- __u8 data;
+-} __attribute__ ((packed));
+-
+-struct qeth_snmp_ureq_hdr {
+- __u32 data_len;
+- __u32 req_len;
+- __u32 reserved1;
+- __u32 reserved2;
+-} __attribute__ ((packed));
+-
+-struct qeth_snmp_ureq {
+- struct qeth_snmp_ureq_hdr hdr;
+- struct qeth_snmp_cmd cmd;
+-} __attribute__((packed));
+-
+-struct qeth_ipacmd_setadpparms_hdr {
+- __u32 supp_hw_cmds;
+- __u32 reserved1;
+- __u16 cmdlength;
+- __u16 reserved2;
+- __u32 command_code;
+- __u16 return_code;
+- __u8 used_total;
+- __u8 seq_no;
+- __u32 reserved3;
+-} __attribute__ ((packed));
+-
+-struct qeth_ipacmd_setadpparms {
+- struct qeth_ipacmd_setadpparms_hdr hdr;
+- union {
+- struct qeth_query_cmds_supp query_cmds_supp;
+- struct qeth_change_addr change_addr;
+- struct qeth_snmp_cmd snmp;
+- __u32 mode;
+- } data;
+-} __attribute__ ((packed));
+-
+-/* IPFRAME IPA Command: ***************************************************/
+-/* TODO: define in analogy to commands define above */
+-
+-/* ADD_ADDR_ENTRY IPA Command: ********************************************/
+-/* TODO: define in analogy to commands define above */
+-
+-/* DELETE_ADDR_ENTRY IPA Command: *****************************************/
+-/* TODO: define in analogy to commands define above */
+-
+-/* CREATE_ADDR IPA Command: ***********************************************/
+-struct qeth_create_destroy_address {
+- __u8 unique_id[8];
+-} __attribute__ ((packed));
+-
+-/* REGISTER_LOCAL_ADDR IPA Command: ***************************************/
+-/* TODO: define in analogy to commands define above */
+-
+-/* UNREGISTER_LOCAL_ADDR IPA Command: *************************************/
+-/* TODO: define in analogy to commands define above */
+-
+-/* Header for each IPA command */
+-struct qeth_ipacmd_hdr {
+- __u8 command;
+- __u8 initiator;
+- __u16 seqno;
+- __u16 return_code;
+- __u8 adapter_type;
+- __u8 rel_adapter_no;
+- __u8 prim_version_no;
+- __u8 param_count;
+- __u16 prot_version;
+- __u32 ipa_supported;
+- __u32 ipa_enabled;
+-} __attribute__ ((packed));
+-
+-/* The IPA command itself */
+-struct qeth_ipa_cmd {
+- struct qeth_ipacmd_hdr hdr;
+- union {
+- struct qeth_ipacmd_setdelip4 setdelip4;
+- struct qeth_ipacmd_setdelip6 setdelip6;
+- struct qeth_ipacmd_setdelipm setdelipm;
+- struct qeth_ipacmd_setassparms setassparms;
+- struct qeth_ipacmd_layer2setdelmac setdelmac;
+- struct qeth_ipacmd_layer2setdelvlan setdelvlan;
+- struct qeth_create_destroy_address create_destroy_addr;
+- struct qeth_ipacmd_setadpparms setadapterparms;
+- struct qeth_set_routing setrtg;
+- } data;
+-} __attribute__ ((packed));
+-
+-/*
+- * special command for ARP processing.
+- * this is not included in setassparms command before, because we get
+- * problem with the size of struct qeth_ipacmd_setassparms otherwise
+- */
+-enum qeth_ipa_arp_return_codes {
+- QETH_IPA_ARP_RC_SUCCESS = 0x0000,
+- QETH_IPA_ARP_RC_FAILED = 0x0001,
+- QETH_IPA_ARP_RC_NOTSUPP = 0x0002,
+- QETH_IPA_ARP_RC_OUT_OF_RANGE = 0x0003,
+- QETH_IPA_ARP_RC_Q_NOTSUPP = 0x0004,
+- QETH_IPA_ARP_RC_Q_NO_DATA = 0x0008,
+-};
+-
+-
+-extern char *
+-qeth_get_ipa_msg(enum qeth_ipa_return_codes rc);
+-extern char *
+-qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd);
+-
+-#define QETH_SETASS_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \
+- sizeof(struct qeth_ipacmd_setassparms_hdr))
+-#define QETH_IPA_ARP_DATA_POS(buffer) (buffer + IPA_PDU_HEADER_SIZE + \
+- QETH_SETASS_BASE_LEN)
+-#define QETH_SETADP_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \
+- sizeof(struct qeth_ipacmd_setadpparms_hdr))
+-#define QETH_SNMP_SETADP_CMDLENGTH 16
+-
+-#define QETH_ARP_DATA_SIZE 3968
+-#define QETH_ARP_CMD_LEN (QETH_ARP_DATA_SIZE + 8)
+-/* Helper functions */
+-#define IS_IPA_REPLY(cmd) ((cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST) || \
+- (cmd->hdr.initiator == IPA_CMD_INITIATOR_OSA_REPLY))
+-
+-/*****************************************************************************/
+-/* END OF IP Assist related definitions */
+-/*****************************************************************************/
+-
+-
+-extern unsigned char WRITE_CCW[];
+-extern unsigned char READ_CCW[];
+-
+-extern unsigned char CM_ENABLE[];
+-#define CM_ENABLE_SIZE 0x63
+-#define QETH_CM_ENABLE_ISSUER_RM_TOKEN(buffer) (buffer+0x2c)
+-#define QETH_CM_ENABLE_FILTER_TOKEN(buffer) (buffer+0x53)
+-#define QETH_CM_ENABLE_USER_DATA(buffer) (buffer+0x5b)
+-
+-#define QETH_CM_ENABLE_RESP_FILTER_TOKEN(buffer) \
+- (PDU_ENCAPSULATION(buffer)+ 0x13)
+-
+-
+-extern unsigned char CM_SETUP[];
+-#define CM_SETUP_SIZE 0x64
+-#define QETH_CM_SETUP_DEST_ADDR(buffer) (buffer+0x2c)
+-#define QETH_CM_SETUP_CONNECTION_TOKEN(buffer) (buffer+0x51)
+-#define QETH_CM_SETUP_FILTER_TOKEN(buffer) (buffer+0x5a)
+-
+-#define QETH_CM_SETUP_RESP_DEST_ADDR(buffer) \
+- (PDU_ENCAPSULATION(buffer) + 0x1a)
+-
+-extern unsigned char ULP_ENABLE[];
+-#define ULP_ENABLE_SIZE 0x6b
+-#define QETH_ULP_ENABLE_LINKNUM(buffer) (buffer+0x61)
+-#define QETH_ULP_ENABLE_DEST_ADDR(buffer) (buffer+0x2c)
+-#define QETH_ULP_ENABLE_FILTER_TOKEN(buffer) (buffer+0x53)
+-#define QETH_ULP_ENABLE_PORTNAME_AND_LL(buffer) (buffer+0x62)
+-#define QETH_ULP_ENABLE_RESP_FILTER_TOKEN(buffer) \
+- (PDU_ENCAPSULATION(buffer) + 0x13)
+-#define QETH_ULP_ENABLE_RESP_MAX_MTU(buffer) \
+- (PDU_ENCAPSULATION(buffer)+ 0x1f)
+-#define QETH_ULP_ENABLE_RESP_DIFINFO_LEN(buffer) \
+- (PDU_ENCAPSULATION(buffer) + 0x17)
+-#define QETH_ULP_ENABLE_RESP_LINK_TYPE(buffer) \
+- (PDU_ENCAPSULATION(buffer)+ 0x2b)
+-/* Layer 2 defintions */
+-#define QETH_PROT_LAYER2 0x08
+-#define QETH_PROT_TCPIP 0x03
+-#define QETH_PROT_OSN2 0x0a
+-#define QETH_ULP_ENABLE_PROT_TYPE(buffer) (buffer+0x50)
+-#define QETH_IPA_CMD_PROT_TYPE(buffer) (buffer+0x19)
+-
+-extern unsigned char ULP_SETUP[];
+-#define ULP_SETUP_SIZE 0x6c
+-#define QETH_ULP_SETUP_DEST_ADDR(buffer) (buffer+0x2c)
+-#define QETH_ULP_SETUP_CONNECTION_TOKEN(buffer) (buffer+0x51)
+-#define QETH_ULP_SETUP_FILTER_TOKEN(buffer) (buffer+0x5a)
+-#define QETH_ULP_SETUP_CUA(buffer) (buffer+0x68)
+-#define QETH_ULP_SETUP_REAL_DEVADDR(buffer) (buffer+0x6a)
+-
+-#define QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(buffer) \
+- (PDU_ENCAPSULATION(buffer)+0x1a)
+-
+-
+-extern unsigned char DM_ACT[];
+-#define DM_ACT_SIZE 0x55
+-#define QETH_DM_ACT_DEST_ADDR(buffer) (buffer+0x2c)
+-#define QETH_DM_ACT_CONNECTION_TOKEN(buffer) (buffer+0x51)
+-
+-
+-
+-#define QETH_TRANSPORT_HEADER_SEQ_NO(buffer) (buffer+4)
+-#define QETH_PDU_HEADER_SEQ_NO(buffer) (buffer+0x1c)
+-#define QETH_PDU_HEADER_ACK_SEQ_NO(buffer) (buffer+0x20)
+-
+-extern unsigned char IDX_ACTIVATE_READ[];
+-extern unsigned char IDX_ACTIVATE_WRITE[];
+-
+-#define IDX_ACTIVATE_SIZE 0x22
+-#define QETH_IDX_ACT_ISSUER_RM_TOKEN(buffer) (buffer+0x0c)
+-#define QETH_IDX_NO_PORTNAME_REQUIRED(buffer) ((buffer)[0x0b]&0x80)
+-#define QETH_IDX_ACT_FUNC_LEVEL(buffer) (buffer+0x10)
+-#define QETH_IDX_ACT_DATASET_NAME(buffer) (buffer+0x16)
+-#define QETH_IDX_ACT_QDIO_DEV_CUA(buffer) (buffer+0x1e)
+-#define QETH_IDX_ACT_QDIO_DEV_REALADDR(buffer) (buffer+0x20)
+-#define QETH_IS_IDX_ACT_POS_REPLY(buffer) (((buffer)[0x08]&3)==2)
+-#define QETH_IDX_REPLY_LEVEL(buffer) (buffer+0x12)
+-#define QETH_IDX_ACT_CAUSE_CODE(buffer) (buffer)[0x09]
+-
+-#define PDU_ENCAPSULATION(buffer) \
+- (buffer + *(buffer + (*(buffer+0x0b)) + \
+- *(buffer + *(buffer+0x0b)+0x11) +0x07))
+-
+-#define IS_IPA(buffer) \
+- ((buffer) && \
+- ( *(buffer + ((*(buffer+0x0b))+4) )==0xc1) )
+-
+-#define ADDR_FRAME_TYPE_DIX 1
+-#define ADDR_FRAME_TYPE_802_3 2
+-#define ADDR_FRAME_TYPE_TR_WITHOUT_SR 0x10
+-#define ADDR_FRAME_TYPE_TR_WITH_SR 0x20
+-
+-#endif
+diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c
+deleted file mode 100644
+index 46ecd03..0000000
+--- a/drivers/s390/net/qeth_proc.c
++++ /dev/null
+@@ -1,316 +0,0 @@
+-/*
+- *
+- * linux/drivers/s390/net/qeth_fs.c
+- *
+- * Linux on zSeries OSA Express and HiperSockets support
+- * This file contains code related to procfs.
+- *
+- * Copyright 2000,2003 IBM Corporation
+- *
+- * Author(s): Thomas Spatzier <tspat at de.ibm.com>
+- *
+- */
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/proc_fs.h>
+-#include <linux/seq_file.h>
+-#include <linux/list.h>
+-#include <linux/rwsem.h>
+-
+-#include "qeth.h"
+-#include "qeth_mpc.h"
+-#include "qeth_fs.h"
+-
+-/***** /proc/qeth *****/
+-#define QETH_PROCFILE_NAME "qeth"
+-static struct proc_dir_entry *qeth_procfile;
+-
+-static int
+-qeth_procfile_seq_match(struct device *dev, void *data)
+-{
+- return(dev ? 1 : 0);
+-}
+-
+-static void *
+-qeth_procfile_seq_start(struct seq_file *s, loff_t *offset)
+-{
+- struct device *dev = NULL;
+- loff_t nr = 0;
+-
+- if (*offset == 0)
+- return SEQ_START_TOKEN;
+- while (1) {
+- dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev,
+- NULL, qeth_procfile_seq_match);
+- if (++nr == *offset)
+- break;
+- put_device(dev);
+- }
+- return dev;
+-}
+-
+-static void
+-qeth_procfile_seq_stop(struct seq_file *s, void* it)
+-{
+-}
+-
+-static void *
+-qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
+-{
+- struct device *prev, *next;
+-
+- if (it == SEQ_START_TOKEN)
+- prev = NULL;
+- else
+- prev = (struct device *) it;
+- next = driver_find_device(&qeth_ccwgroup_driver.driver,
+- prev, NULL, qeth_procfile_seq_match);
+- (*offset)++;
+- return (void *) next;
+-}
+-
+-static inline const char *
+-qeth_get_router_str(struct qeth_card *card, int ipv)
+-{
+- enum qeth_routing_types routing_type = NO_ROUTER;
+-
+- if (ipv == 4) {
+- routing_type = card->options.route4.type;
+- } else {
+-#ifdef CONFIG_QETH_IPV6
+- routing_type = card->options.route6.type;
+-#else
+- return "n/a";
+-#endif /* CONFIG_QETH_IPV6 */
+- }
+-
+- switch (routing_type){
+- case PRIMARY_ROUTER:
+- return "pri";
+- case SECONDARY_ROUTER:
+- return "sec";
+- case MULTICAST_ROUTER:
+- if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
+- return "mc+";
+- return "mc";
+- case PRIMARY_CONNECTOR:
+- if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
+- return "p+c";
+- return "p.c";
+- case SECONDARY_CONNECTOR:
+- if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
+- return "s+c";
+- return "s.c";
+- default: /* NO_ROUTER */
+- return "no";
+- }
+-}
+-
+-static int
+-qeth_procfile_seq_show(struct seq_file *s, void *it)
+-{
+- struct device *device;
+- struct qeth_card *card;
+- char tmp[12]; /* for qeth_get_prioq_str */
+-
+- if (it == SEQ_START_TOKEN){
+- seq_printf(s, "devices CHPID interface "
+- "cardtype port chksum prio-q'ing rtr4 "
+- "rtr6 fsz cnt\n");
+- seq_printf(s, "-------------------------- ----- ---------- "
+- "-------------- ---- ------ ---------- ---- "
+- "---- ----- -----\n");
+- } else {
+- device = (struct device *) it;
+- card = device->driver_data;
+- seq_printf(s, "%s/%s/%s x%02X %-10s %-14s %-4i ",
+- CARD_RDEV_ID(card),
+- CARD_WDEV_ID(card),
+- CARD_DDEV_ID(card),
+- card->info.chpid,
+- QETH_CARD_IFNAME(card),
+- qeth_get_cardname_short(card),
+- card->info.portno);
+- if (card->lan_online)
+- seq_printf(s, "%-6s %-10s %-4s %-4s %-5s %-5i\n",
+- qeth_get_checksum_str(card),
+- qeth_get_prioq_str(card, tmp),
+- qeth_get_router_str(card, 4),
+- qeth_get_router_str(card, 6),
+- qeth_get_bufsize_str(card),
+- card->qdio.in_buf_pool.buf_count);
+- else
+- seq_printf(s, " +++ LAN OFFLINE +++\n");
+- put_device(device);
+- }
+- return 0;
+-}
+-
+-static const struct seq_operations qeth_procfile_seq_ops = {
+- .start = qeth_procfile_seq_start,
+- .stop = qeth_procfile_seq_stop,
+- .next = qeth_procfile_seq_next,
+- .show = qeth_procfile_seq_show,
+-};
+-
+-static int
+-qeth_procfile_open(struct inode *inode, struct file *file)
+-{
+- return seq_open(file, &qeth_procfile_seq_ops);
+-}
+-
+-static const struct file_operations qeth_procfile_fops = {
+- .owner = THIS_MODULE,
+- .open = qeth_procfile_open,
+- .read = seq_read,
+- .llseek = seq_lseek,
+- .release = seq_release,
+-};
+-
+-/***** /proc/qeth_perf *****/
+-#define QETH_PERF_PROCFILE_NAME "qeth_perf"
+-static struct proc_dir_entry *qeth_perf_procfile;
+-
+-static int
+-qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
+-{
+- struct device *device;
+- struct qeth_card *card;
+-
+-
+- if (it == SEQ_START_TOKEN)
+- return 0;
+-
+- device = (struct device *) it;
+- card = device->driver_data;
+- seq_printf(s, "For card with devnos %s/%s/%s (%s):\n",
+- CARD_RDEV_ID(card),
+- CARD_WDEV_ID(card),
+- CARD_DDEV_ID(card),
+- QETH_CARD_IFNAME(card)
+- );
+- if (!card->options.performance_stats)
+- seq_printf(s, "Performance statistics are deactivated.\n");
+- seq_printf(s, " Skb's/buffers received : %lu/%u\n"
+- " Skb's/buffers sent : %lu/%u\n\n",
+- card->stats.rx_packets -
+- card->perf_stats.initial_rx_packets,
+- card->perf_stats.bufs_rec,
+- card->stats.tx_packets -
+- card->perf_stats.initial_tx_packets,
+- card->perf_stats.bufs_sent
+- );
+- seq_printf(s, " Skb's/buffers sent without packing : %lu/%u\n"
+- " Skb's/buffers sent with packing : %u/%u\n\n",
+- card->stats.tx_packets - card->perf_stats.initial_tx_packets
+- - card->perf_stats.skbs_sent_pack,
+- card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack,
+- card->perf_stats.skbs_sent_pack,
+- card->perf_stats.bufs_sent_pack
+- );
+- seq_printf(s, " Skbs sent in SG mode : %u\n"
+- " Skb fragments sent in SG mode : %u\n\n",
+- card->perf_stats.sg_skbs_sent,
+- card->perf_stats.sg_frags_sent);
+- seq_printf(s, " Skbs received in SG mode : %u\n"
+- " Skb fragments received in SG mode : %u\n"
+- " Page allocations for rx SG mode : %u\n\n",
+- card->perf_stats.sg_skbs_rx,
+- card->perf_stats.sg_frags_rx,
+- card->perf_stats.sg_alloc_page_rx);
+- seq_printf(s, " large_send tx (in Kbytes) : %u\n"
+- " large_send count : %u\n\n",
+- card->perf_stats.large_send_bytes >> 10,
+- card->perf_stats.large_send_cnt);
+- seq_printf(s, " Packing state changes no pkg.->packing : %u/%u\n"
+- " Watermarks L/H : %i/%i\n"
+- " Current buffer usage (outbound q's) : "
+- "%i/%i/%i/%i\n\n",
+- card->perf_stats.sc_dp_p, card->perf_stats.sc_p_dp,
+- QETH_LOW_WATERMARK_PACK, QETH_HIGH_WATERMARK_PACK,
+- atomic_read(&card->qdio.out_qs[0]->used_buffers),
+- (card->qdio.no_out_queues > 1)?
+- atomic_read(&card->qdio.out_qs[1]->used_buffers)
+- : 0,
+- (card->qdio.no_out_queues > 2)?
+- atomic_read(&card->qdio.out_qs[2]->used_buffers)
+- : 0,
+- (card->qdio.no_out_queues > 3)?
+- atomic_read(&card->qdio.out_qs[3]->used_buffers)
+- : 0
+- );
+- seq_printf(s, " Inbound handler time (in us) : %u\n"
+- " Inbound handler count : %u\n"
+- " Inbound do_QDIO time (in us) : %u\n"
+- " Inbound do_QDIO count : %u\n\n"
+- " Outbound handler time (in us) : %u\n"
+- " Outbound handler count : %u\n\n"
+- " Outbound time (in us, incl QDIO) : %u\n"
+- " Outbound count : %u\n"
+- " Outbound do_QDIO time (in us) : %u\n"
+- " Outbound do_QDIO count : %u\n\n",
+- card->perf_stats.inbound_time,
+- card->perf_stats.inbound_cnt,
+- card->perf_stats.inbound_do_qdio_time,
+- card->perf_stats.inbound_do_qdio_cnt,
+- card->perf_stats.outbound_handler_time,
+- card->perf_stats.outbound_handler_cnt,
+- card->perf_stats.outbound_time,
+- card->perf_stats.outbound_cnt,
+- card->perf_stats.outbound_do_qdio_time,
+- card->perf_stats.outbound_do_qdio_cnt
+- );
+- put_device(device);
+- return 0;
+-}
+-
+-static const struct seq_operations qeth_perf_procfile_seq_ops = {
+- .start = qeth_procfile_seq_start,
+- .stop = qeth_procfile_seq_stop,
+- .next = qeth_procfile_seq_next,
+- .show = qeth_perf_procfile_seq_show,
+-};
+-
+-static int
+-qeth_perf_procfile_open(struct inode *inode, struct file *file)
+-{
+- return seq_open(file, &qeth_perf_procfile_seq_ops);
+-}
+-
+-static const struct file_operations qeth_perf_procfile_fops = {
+- .owner = THIS_MODULE,
+- .open = qeth_perf_procfile_open,
+- .read = seq_read,
+- .llseek = seq_lseek,
+- .release = seq_release,
+-};
+-
+-int __init
+-qeth_create_procfs_entries(void)
+-{
+- qeth_procfile = create_proc_entry(QETH_PROCFILE_NAME,
+- S_IFREG | 0444, NULL);
+- if (qeth_procfile)
+- qeth_procfile->proc_fops = &qeth_procfile_fops;
+-
+- qeth_perf_procfile = create_proc_entry(QETH_PERF_PROCFILE_NAME,
+- S_IFREG | 0444, NULL);
+- if (qeth_perf_procfile)
+- qeth_perf_procfile->proc_fops = &qeth_perf_procfile_fops;
+-
+- if (qeth_procfile &&
+- qeth_perf_procfile)
+- return 0;
+- else
+- return -ENOMEM;
+-}
+-
+-void __exit
+-qeth_remove_procfs_entries(void)
+-{
+- if (qeth_procfile)
+- remove_proc_entry(QETH_PROCFILE_NAME, NULL);
+- if (qeth_perf_procfile)
+- remove_proc_entry(QETH_PERF_PROCFILE_NAME, NULL);
+-}
+-
+diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c
+deleted file mode 100644
+index 2cc3f3a..0000000
+--- a/drivers/s390/net/qeth_sys.c
++++ /dev/null
+@@ -1,1858 +0,0 @@
+-/*
+- *
+- * linux/drivers/s390/net/qeth_sys.c
+- *
+- * Linux on zSeries OSA Express and HiperSockets support
+- * This file contains code related to sysfs.
+- *
+- * Copyright 2000,2003 IBM Corporation
+- *
+- * Author(s): Thomas Spatzier <tspat at de.ibm.com>
+- * Frank Pavlic <fpavlic at de.ibm.com>
+- *
+- */
+-#include <linux/list.h>
+-#include <linux/rwsem.h>
+-
+-#include <asm/ebcdic.h>
+-
+-#include "qeth.h"
+-#include "qeth_mpc.h"
+-#include "qeth_fs.h"
+-
+-/*****************************************************************************/
+-/* */
+-/* /sys-fs stuff UNDER DEVELOPMENT !!! */
+-/* */
+-/*****************************************************************************/
+-//low/high watermark
+-
+-static ssize_t
+-qeth_dev_state_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+- if (!card)
+- return -EINVAL;
+-
+- switch (card->state) {
+- case CARD_STATE_DOWN:
+- return sprintf(buf, "DOWN\n");
+- case CARD_STATE_HARDSETUP:
+- return sprintf(buf, "HARDSETUP\n");
+- case CARD_STATE_SOFTSETUP:
+- return sprintf(buf, "SOFTSETUP\n");
+- case CARD_STATE_UP:
+- if (card->lan_online)
+- return sprintf(buf, "UP (LAN ONLINE)\n");
+- else
+- return sprintf(buf, "UP (LAN OFFLINE)\n");
+- case CARD_STATE_RECOVER:
+- return sprintf(buf, "RECOVER\n");
+- default:
+- return sprintf(buf, "UNKNOWN\n");
+- }
+-}
+-
+-static DEVICE_ATTR(state, 0444, qeth_dev_state_show, NULL);
+-
+-static ssize_t
+-qeth_dev_chpid_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+- if (!card)
+- return -EINVAL;
+-
+- return sprintf(buf, "%02X\n", card->info.chpid);
+-}
+-
+-static DEVICE_ATTR(chpid, 0444, qeth_dev_chpid_show, NULL);
+-
+-static ssize_t
+-qeth_dev_if_name_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+- if (!card)
+- return -EINVAL;
+- return sprintf(buf, "%s\n", QETH_CARD_IFNAME(card));
+-}
+-
+-static DEVICE_ATTR(if_name, 0444, qeth_dev_if_name_show, NULL);
+-
+-static ssize_t
+-qeth_dev_card_type_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+- if (!card)
+- return -EINVAL;
+-
+- return sprintf(buf, "%s\n", qeth_get_cardname_short(card));
+-}
+-
+-static DEVICE_ATTR(card_type, 0444, qeth_dev_card_type_show, NULL);
+-
+-static ssize_t
+-qeth_dev_portno_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+- if (!card)
+- return -EINVAL;
+-
+- return sprintf(buf, "%i\n", card->info.portno);
+-}
+-
+-static ssize_t
+-qeth_dev_portno_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
+- unsigned int portno;
+-
+- if (!card)
+- return -EINVAL;
+-
+- if ((card->state != CARD_STATE_DOWN) &&
+- (card->state != CARD_STATE_RECOVER))
+- return -EPERM;
+-
+- portno = simple_strtoul(buf, &tmp, 16);
+- if (portno > MAX_PORTNO){
+- PRINT_WARN("portno 0x%X is out of range\n", portno);
+- return -EINVAL;
+- }
+-
+- card->info.portno = portno;
+- return count;
+-}
+-
+-static DEVICE_ATTR(portno, 0644, qeth_dev_portno_show, qeth_dev_portno_store);
+-
+-static ssize_t
+-qeth_dev_portname_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+- char portname[9] = {0, };
+-
+- if (!card)
+- return -EINVAL;
+-
+- if (card->info.portname_required) {
+- memcpy(portname, card->info.portname + 1, 8);
+- EBCASC(portname, 8);
+- return sprintf(buf, "%s\n", portname);
+- } else
+- return sprintf(buf, "no portname required\n");
+-}
+-
+-static ssize_t
+-qeth_dev_portname_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
+- int i;
+-
+- if (!card)
+- return -EINVAL;
+-
+- if ((card->state != CARD_STATE_DOWN) &&
+- (card->state != CARD_STATE_RECOVER))
+- return -EPERM;
+-
+- tmp = strsep((char **) &buf, "\n");
+- if ((strlen(tmp) > 8) || (strlen(tmp) == 0))
+- return -EINVAL;
+-
+- card->info.portname[0] = strlen(tmp);
+- /* for beauty reasons */
+- for (i = 1; i < 9; i++)
+- card->info.portname[i] = ' ';
+- strcpy(card->info.portname + 1, tmp);
+- ASCEBC(card->info.portname + 1, 8);
+-
+- return count;
+-}
+-
+-static DEVICE_ATTR(portname, 0644, qeth_dev_portname_show,
+- qeth_dev_portname_store);
+-
+-static ssize_t
+-qeth_dev_checksum_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return sprintf(buf, "%s checksumming\n", qeth_get_checksum_str(card));
+-}
+-
+-static ssize_t
+-qeth_dev_checksum_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
+-
+- if (!card)
+- return -EINVAL;
+-
+- if ((card->state != CARD_STATE_DOWN) &&
+- (card->state != CARD_STATE_RECOVER))
+- return -EPERM;
+-
+- tmp = strsep((char **) &buf, "\n");
+- if (!strcmp(tmp, "sw_checksumming"))
+- card->options.checksum_type = SW_CHECKSUMMING;
+- else if (!strcmp(tmp, "hw_checksumming"))
+- card->options.checksum_type = HW_CHECKSUMMING;
+- else if (!strcmp(tmp, "no_checksumming"))
+- card->options.checksum_type = NO_CHECKSUMMING;
+- else {
+- PRINT_WARN("Unknown checksumming type '%s'\n", tmp);
+- return -EINVAL;
+- }
+- return count;
+-}
+-
+-static DEVICE_ATTR(checksumming, 0644, qeth_dev_checksum_show,
+- qeth_dev_checksum_store);
+-
+-static ssize_t
+-qeth_dev_prioqing_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- switch (card->qdio.do_prio_queueing) {
+- case QETH_PRIO_Q_ING_PREC:
+- return sprintf(buf, "%s\n", "by precedence");
+- case QETH_PRIO_Q_ING_TOS:
+- return sprintf(buf, "%s\n", "by type of service");
+- default:
+- return sprintf(buf, "always queue %i\n",
+- card->qdio.default_out_queue);
+- }
+-}
+-
+-static ssize_t
+-qeth_dev_prioqing_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
+-
+- if (!card)
+- return -EINVAL;
+-
+- if ((card->state != CARD_STATE_DOWN) &&
+- (card->state != CARD_STATE_RECOVER))
+- return -EPERM;
+-
+- /* check if 1920 devices are supported ,
+- * if though we have to permit priority queueing
+- */
+- if (card->qdio.no_out_queues == 1) {
+- PRINT_WARN("Priority queueing disabled due "
+- "to hardware limitations!\n");
+- card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
+- return -EPERM;
+- }
+-
+- tmp = strsep((char **) &buf, "\n");
+- if (!strcmp(tmp, "prio_queueing_prec"))
+- card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_PREC;
+- else if (!strcmp(tmp, "prio_queueing_tos"))
+- card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_TOS;
+- else if (!strcmp(tmp, "no_prio_queueing:0")) {
+- card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
+- card->qdio.default_out_queue = 0;
+- } else if (!strcmp(tmp, "no_prio_queueing:1")) {
+- card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
+- card->qdio.default_out_queue = 1;
+- } else if (!strcmp(tmp, "no_prio_queueing:2")) {
+- card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
+- card->qdio.default_out_queue = 2;
+- } else if (!strcmp(tmp, "no_prio_queueing:3")) {
+- card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
+- card->qdio.default_out_queue = 3;
+- } else if (!strcmp(tmp, "no_prio_queueing")) {
+- card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
+- card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
+- } else {
+- PRINT_WARN("Unknown queueing type '%s'\n", tmp);
+- return -EINVAL;
+- }
+- return count;
+-}
+-
+-static DEVICE_ATTR(priority_queueing, 0644, qeth_dev_prioqing_show,
+- qeth_dev_prioqing_store);
+-
+-static ssize_t
+-qeth_dev_bufcnt_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return sprintf(buf, "%i\n", card->qdio.in_buf_pool.buf_count);
+-}
+-
+-static ssize_t
+-qeth_dev_bufcnt_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
+- int cnt, old_cnt;
+- int rc;
+-
+- if (!card)
+- return -EINVAL;
+-
+- if ((card->state != CARD_STATE_DOWN) &&
+- (card->state != CARD_STATE_RECOVER))
+- return -EPERM;
+-
+- old_cnt = card->qdio.in_buf_pool.buf_count;
+- cnt = simple_strtoul(buf, &tmp, 10);
+- cnt = (cnt < QETH_IN_BUF_COUNT_MIN) ? QETH_IN_BUF_COUNT_MIN :
+- ((cnt > QETH_IN_BUF_COUNT_MAX) ? QETH_IN_BUF_COUNT_MAX : cnt);
+- if (old_cnt != cnt) {
+- if ((rc = qeth_realloc_buffer_pool(card, cnt)))
+- PRINT_WARN("Error (%d) while setting "
+- "buffer count.\n", rc);
+- }
+- return count;
+-}
+-
+-static DEVICE_ATTR(buffer_count, 0644, qeth_dev_bufcnt_show,
+- qeth_dev_bufcnt_store);
+-
+-static ssize_t
+-qeth_dev_route_show(struct qeth_card *card, struct qeth_routing_info *route,
+- char *buf)
+-{
+- switch (route->type) {
+- case PRIMARY_ROUTER:
+- return sprintf(buf, "%s\n", "primary router");
+- case SECONDARY_ROUTER:
+- return sprintf(buf, "%s\n", "secondary router");
+- case MULTICAST_ROUTER:
+- if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
+- return sprintf(buf, "%s\n", "multicast router+");
+- else
+- return sprintf(buf, "%s\n", "multicast router");
+- case PRIMARY_CONNECTOR:
+- if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
+- return sprintf(buf, "%s\n", "primary connector+");
+- else
+- return sprintf(buf, "%s\n", "primary connector");
+- case SECONDARY_CONNECTOR:
+- if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
+- return sprintf(buf, "%s\n", "secondary connector+");
+- else
+- return sprintf(buf, "%s\n", "secondary connector");
+- default:
+- return sprintf(buf, "%s\n", "no");
+- }
+-}
+-
+-static ssize_t
+-qeth_dev_route4_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return qeth_dev_route_show(card, &card->options.route4, buf);
+-}
+-
+-static ssize_t
+-qeth_dev_route_store(struct qeth_card *card, struct qeth_routing_info *route,
+- enum qeth_prot_versions prot, const char *buf, size_t count)
+-{
+- enum qeth_routing_types old_route_type = route->type;
+- char *tmp;
+- int rc;
+-
+- tmp = strsep((char **) &buf, "\n");
+-
+- if (!strcmp(tmp, "no_router")){
+- route->type = NO_ROUTER;
+- } else if (!strcmp(tmp, "primary_connector")) {
+- route->type = PRIMARY_CONNECTOR;
+- } else if (!strcmp(tmp, "secondary_connector")) {
+- route->type = SECONDARY_CONNECTOR;
+- } else if (!strcmp(tmp, "primary_router")) {
+- route->type = PRIMARY_ROUTER;
+- } else if (!strcmp(tmp, "secondary_router")) {
+- route->type = SECONDARY_ROUTER;
+- } else if (!strcmp(tmp, "multicast_router")) {
+- route->type = MULTICAST_ROUTER;
+- } else {
+- PRINT_WARN("Invalid routing type '%s'.\n", tmp);
+- return -EINVAL;
+- }
+- if (((card->state == CARD_STATE_SOFTSETUP) ||
+- (card->state == CARD_STATE_UP)) &&
+- (old_route_type != route->type)){
+- if (prot == QETH_PROT_IPV4)
+- rc = qeth_setrouting_v4(card);
+- else if (prot == QETH_PROT_IPV6)
+- rc = qeth_setrouting_v6(card);
+- }
+- return count;
+-}
+-
+-static ssize_t
+-qeth_dev_route4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return qeth_dev_route_store(card, &card->options.route4,
+- QETH_PROT_IPV4, buf, count);
+-}
+-
+-static DEVICE_ATTR(route4, 0644, qeth_dev_route4_show, qeth_dev_route4_store);
+-
+-#ifdef CONFIG_QETH_IPV6
+-static ssize_t
+-qeth_dev_route6_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- if (!qeth_is_supported(card, IPA_IPV6))
+- return sprintf(buf, "%s\n", "n/a");
+-
+- return qeth_dev_route_show(card, &card->options.route6, buf);
+-}
+-
+-static ssize_t
+-qeth_dev_route6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- if (!qeth_is_supported(card, IPA_IPV6)){
+- PRINT_WARN("IPv6 not supported for interface %s.\n"
+- "Routing status no changed.\n",
+- QETH_CARD_IFNAME(card));
+- return -ENOTSUPP;
+- }
+-
+- return qeth_dev_route_store(card, &card->options.route6,
+- QETH_PROT_IPV6, buf, count);
+-}
+-
+-static DEVICE_ATTR(route6, 0644, qeth_dev_route6_show, qeth_dev_route6_store);
+-#endif
+-
+-static ssize_t
+-qeth_dev_add_hhlen_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return sprintf(buf, "%i\n", card->options.add_hhlen);
+-}
+-
+-static ssize_t
+-qeth_dev_add_hhlen_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
+- int i;
+-
+- if (!card)
+- return -EINVAL;
+-
+- if ((card->state != CARD_STATE_DOWN) &&
+- (card->state != CARD_STATE_RECOVER))
+- return -EPERM;
+-
+- i = simple_strtoul(buf, &tmp, 10);
+- if ((i < 0) || (i > MAX_ADD_HHLEN)) {
+- PRINT_WARN("add_hhlen out of range\n");
+- return -EINVAL;
+- }
+- card->options.add_hhlen = i;
+-
+- return count;
+-}
+-
+-static DEVICE_ATTR(add_hhlen, 0644, qeth_dev_add_hhlen_show,
+- qeth_dev_add_hhlen_store);
+-
+-static ssize_t
+-qeth_dev_fake_ll_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return sprintf(buf, "%i\n", card->options.fake_ll? 1:0);
+-}
+-
+-static ssize_t
+-qeth_dev_fake_ll_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
+- int i;
+-
+- if (!card)
+- return -EINVAL;
+-
+- if ((card->state != CARD_STATE_DOWN) &&
+- (card->state != CARD_STATE_RECOVER))
+- return -EPERM;
+-
+- i = simple_strtoul(buf, &tmp, 16);
+- if ((i != 0) && (i != 1)) {
+- PRINT_WARN("fake_ll: write 0 or 1 to this file!\n");
+- return -EINVAL;
+- }
+- card->options.fake_ll = i;
+- return count;
+-}
+-
+-static DEVICE_ATTR(fake_ll, 0644, qeth_dev_fake_ll_show,
+- qeth_dev_fake_ll_store);
+-
+-static ssize_t
+-qeth_dev_fake_broadcast_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return sprintf(buf, "%i\n", card->options.fake_broadcast? 1:0);
+-}
+-
+-static ssize_t
+-qeth_dev_fake_broadcast_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
+- int i;
+-
+- if (!card)
+- return -EINVAL;
+-
+- if ((card->state != CARD_STATE_DOWN) &&
+- (card->state != CARD_STATE_RECOVER))
+- return -EPERM;
+-
+- i = simple_strtoul(buf, &tmp, 16);
+- if ((i == 0) || (i == 1))
+- card->options.fake_broadcast = i;
+- else {
+- PRINT_WARN("fake_broadcast: write 0 or 1 to this file!\n");
+- return -EINVAL;
+- }
+- return count;
+-}
+-
+-static DEVICE_ATTR(fake_broadcast, 0644, qeth_dev_fake_broadcast_show,
+- qeth_dev_fake_broadcast_store);
+-
+-static ssize_t
+-qeth_dev_recover_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
+- int i;
+-
+- if (!card)
+- return -EINVAL;
+-
+- if (card->state != CARD_STATE_UP)
+- return -EPERM;
+-
+- i = simple_strtoul(buf, &tmp, 16);
+- if (i == 1)
+- qeth_schedule_recovery(card);
+-
+- return count;
+-}
+-
+-static DEVICE_ATTR(recover, 0200, NULL, qeth_dev_recover_store);
+-
+-static ssize_t
+-qeth_dev_broadcast_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
+- (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
+- return sprintf(buf, "n/a\n");
+-
+- return sprintf(buf, "%s\n", (card->options.broadcast_mode ==
+- QETH_TR_BROADCAST_ALLRINGS)?
+- "all rings":"local");
+-}
+-
+-static ssize_t
+-qeth_dev_broadcast_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
+-
+- if (!card)
+- return -EINVAL;
+-
+- if ((card->state != CARD_STATE_DOWN) &&
+- (card->state != CARD_STATE_RECOVER))
+- return -EPERM;
+-
+- if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
+- (card->info.link_type == QETH_LINK_TYPE_LANE_TR))){
+- PRINT_WARN("Device is not a tokenring device!\n");
+- return -EINVAL;
+- }
+-
+- tmp = strsep((char **) &buf, "\n");
+-
+- if (!strcmp(tmp, "local")){
+- card->options.broadcast_mode = QETH_TR_BROADCAST_LOCAL;
+- return count;
+- } else if (!strcmp(tmp, "all_rings")) {
+- card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS;
+- return count;
+- } else {
+- PRINT_WARN("broadcast_mode: invalid mode %s!\n",
+- tmp);
+- return -EINVAL;
+- }
+- return count;
+-}
+-
+-static DEVICE_ATTR(broadcast_mode, 0644, qeth_dev_broadcast_mode_show,
+- qeth_dev_broadcast_mode_store);
+-
+-static ssize_t
+-qeth_dev_canonical_macaddr_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
+- (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
+- return sprintf(buf, "n/a\n");
+-
+- return sprintf(buf, "%i\n", (card->options.macaddr_mode ==
+- QETH_TR_MACADDR_CANONICAL)? 1:0);
+-}
+-
+-static ssize_t
+-qeth_dev_canonical_macaddr_store(struct device *dev, struct device_attribute *attr, const char *buf,
+- size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
+- int i;
+-
+- if (!card)
+- return -EINVAL;
+-
+- if ((card->state != CARD_STATE_DOWN) &&
+- (card->state != CARD_STATE_RECOVER))
+- return -EPERM;
+-
+- if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
+- (card->info.link_type == QETH_LINK_TYPE_LANE_TR))){
+- PRINT_WARN("Device is not a tokenring device!\n");
+- return -EINVAL;
+- }
+-
+- i = simple_strtoul(buf, &tmp, 16);
+- if ((i == 0) || (i == 1))
+- card->options.macaddr_mode = i?
+- QETH_TR_MACADDR_CANONICAL :
+- QETH_TR_MACADDR_NONCANONICAL;
+- else {
+- PRINT_WARN("canonical_macaddr: write 0 or 1 to this file!\n");
+- return -EINVAL;
+- }
+- return count;
+-}
+-
+-static DEVICE_ATTR(canonical_macaddr, 0644, qeth_dev_canonical_macaddr_show,
+- qeth_dev_canonical_macaddr_store);
+-
+-static ssize_t
+-qeth_dev_layer2_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return sprintf(buf, "%i\n", card->options.layer2 ? 1:0);
+-}
+-
+-static ssize_t
+-qeth_dev_layer2_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
+- int i;
+-
+- if (!card)
+- return -EINVAL;
+- if (card->info.type == QETH_CARD_TYPE_IQD) {
+- PRINT_WARN("Layer2 on Hipersockets is not supported! \n");
+- return -EPERM;
+- }
+-
+- if (((card->state != CARD_STATE_DOWN) &&
+- (card->state != CARD_STATE_RECOVER)))
+- return -EPERM;
+-
+- i = simple_strtoul(buf, &tmp, 16);
+- if ((i == 0) || (i == 1))
+- card->options.layer2 = i;
+- else {
+- PRINT_WARN("layer2: write 0 or 1 to this file!\n");
+- return -EINVAL;
+- }
+- return count;
+-}
+-
+-static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show,
+- qeth_dev_layer2_store);
+-
+-static ssize_t
+-qeth_dev_performance_stats_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return sprintf(buf, "%i\n", card->options.performance_stats ? 1:0);
+-}
+-
+-static ssize_t
+-qeth_dev_performance_stats_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
+- int i;
+-
+- if (!card)
+- return -EINVAL;
+-
+- i = simple_strtoul(buf, &tmp, 16);
+- if ((i == 0) || (i == 1)) {
+- if (i == card->options.performance_stats)
+- return count;
+- card->options.performance_stats = i;
+- if (i == 0)
+- memset(&card->perf_stats, 0,
+- sizeof(struct qeth_perf_stats));
+- card->perf_stats.initial_rx_packets = card->stats.rx_packets;
+- card->perf_stats.initial_tx_packets = card->stats.tx_packets;
+- } else {
+- PRINT_WARN("performance_stats: write 0 or 1 to this file!\n");
+- return -EINVAL;
+- }
+- return count;
+-}
+-
+-static DEVICE_ATTR(performance_stats, 0644, qeth_dev_performance_stats_show,
+- qeth_dev_performance_stats_store);
+-
+-static ssize_t
+-qeth_dev_large_send_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- switch (card->options.large_send) {
+- case QETH_LARGE_SEND_NO:
+- return sprintf(buf, "%s\n", "no");
+- case QETH_LARGE_SEND_EDDP:
+- return sprintf(buf, "%s\n", "EDDP");
+- case QETH_LARGE_SEND_TSO:
+- return sprintf(buf, "%s\n", "TSO");
+- default:
+- return sprintf(buf, "%s\n", "N/A");
+- }
+-}
+-
+-static ssize_t
+-qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+- enum qeth_large_send_types type;
+- int rc = 0;
+- char *tmp;
+-
+- if (!card)
+- return -EINVAL;
+- tmp = strsep((char **) &buf, "\n");
+- if (!strcmp(tmp, "no")){
+- type = QETH_LARGE_SEND_NO;
+- } else if (!strcmp(tmp, "EDDP")) {
+- type = QETH_LARGE_SEND_EDDP;
+- } else if (!strcmp(tmp, "TSO")) {
+- type = QETH_LARGE_SEND_TSO;
+- } else {
+- PRINT_WARN("large_send: invalid mode %s!\n", tmp);
+- return -EINVAL;
+- }
+- if (card->options.large_send == type)
+- return count;
+- if ((rc = qeth_set_large_send(card, type)))
+- return rc;
+- return count;
+-}
+-
+-static DEVICE_ATTR(large_send, 0644, qeth_dev_large_send_show,
+- qeth_dev_large_send_store);
+-
+-static ssize_t
+-qeth_dev_blkt_show(char *buf, struct qeth_card *card, int value )
+-{
+-
+- if (!card)
+- return -EINVAL;
+-
+- return sprintf(buf, "%i\n", value);
+-}
+-
+-static ssize_t
+-qeth_dev_blkt_store(struct qeth_card *card, const char *buf, size_t count,
+- int *value, int max_value)
+-{
+- char *tmp;
+- int i;
+-
+- if (!card)
+- return -EINVAL;
+-
+- if ((card->state != CARD_STATE_DOWN) &&
+- (card->state != CARD_STATE_RECOVER))
+- return -EPERM;
+-
+- i = simple_strtoul(buf, &tmp, 10);
+- if (i <= max_value) {
+- *value = i;
+- } else {
+- PRINT_WARN("blkt total time: write values between"
+- " 0 and %d to this file!\n", max_value);
+- return -EINVAL;
+- }
+- return count;
+-}
+-
+-static ssize_t
+-qeth_dev_blkt_total_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- return qeth_dev_blkt_show(buf, card, card->info.blkt.time_total);
+-}
+-
+-
+-static ssize_t
+-qeth_dev_blkt_total_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- return qeth_dev_blkt_store(card, buf, count,
+- &card->info.blkt.time_total,1000);
+-}
+-
+-
+-
+-static DEVICE_ATTR(total, 0644, qeth_dev_blkt_total_show,
+- qeth_dev_blkt_total_store);
+-
+-static ssize_t
+-qeth_dev_blkt_inter_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- return qeth_dev_blkt_show(buf, card, card->info.blkt.inter_packet);
+-}
+-
+-
+-static ssize_t
+-qeth_dev_blkt_inter_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- return qeth_dev_blkt_store(card, buf, count,
+- &card->info.blkt.inter_packet,100);
+-}
+-
+-static DEVICE_ATTR(inter, 0644, qeth_dev_blkt_inter_show,
+- qeth_dev_blkt_inter_store);
+-
+-static ssize_t
+-qeth_dev_blkt_inter_jumbo_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- return qeth_dev_blkt_show(buf, card,
+- card->info.blkt.inter_packet_jumbo);
+-}
+-
+-
+-static ssize_t
+-qeth_dev_blkt_inter_jumbo_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- return qeth_dev_blkt_store(card, buf, count,
+- &card->info.blkt.inter_packet_jumbo,100);
+-}
+-
+-static DEVICE_ATTR(inter_jumbo, 0644, qeth_dev_blkt_inter_jumbo_show,
+- qeth_dev_blkt_inter_jumbo_store);
+-
+-static struct device_attribute * qeth_blkt_device_attrs[] = {
+- &dev_attr_total,
+- &dev_attr_inter,
+- &dev_attr_inter_jumbo,
+- NULL,
+-};
+-
+-static struct attribute_group qeth_device_blkt_group = {
+- .name = "blkt",
+- .attrs = (struct attribute **)qeth_blkt_device_attrs,
+-};
+-
+-static struct device_attribute * qeth_device_attrs[] = {
+- &dev_attr_state,
+- &dev_attr_chpid,
+- &dev_attr_if_name,
+- &dev_attr_card_type,
+- &dev_attr_portno,
+- &dev_attr_portname,
+- &dev_attr_checksumming,
+- &dev_attr_priority_queueing,
+- &dev_attr_buffer_count,
+- &dev_attr_route4,
+-#ifdef CONFIG_QETH_IPV6
+- &dev_attr_route6,
+-#endif
+- &dev_attr_add_hhlen,
+- &dev_attr_fake_ll,
+- &dev_attr_fake_broadcast,
+- &dev_attr_recover,
+- &dev_attr_broadcast_mode,
+- &dev_attr_canonical_macaddr,
+- &dev_attr_layer2,
+- &dev_attr_large_send,
+- &dev_attr_performance_stats,
+- NULL,
+-};
+-
+-static struct attribute_group qeth_device_attr_group = {
+- .attrs = (struct attribute **)qeth_device_attrs,
+-};
+-
+-static struct device_attribute * qeth_osn_device_attrs[] = {
+- &dev_attr_state,
+- &dev_attr_chpid,
+- &dev_attr_if_name,
+- &dev_attr_card_type,
+- &dev_attr_buffer_count,
+- &dev_attr_recover,
+- NULL,
+-};
+-
+-static struct attribute_group qeth_osn_device_attr_group = {
+- .attrs = (struct attribute **)qeth_osn_device_attrs,
+-};
+-
+-#define QETH_DEVICE_ATTR(_id,_name,_mode,_show,_store) \
+-struct device_attribute dev_attr_##_id = { \
+- .attr = {.name=__stringify(_name), .mode=_mode, },\
+- .show = _show, \
+- .store = _store, \
+-};
+-
+-static int
+-qeth_check_layer2(struct qeth_card *card)
+-{
+- if (card->options.layer2)
+- return -EPERM;
+- return 0;
+-}
+-
+-
+-static ssize_t
+-qeth_dev_ipato_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- if (qeth_check_layer2(card))
+- return -EPERM;
+- return sprintf(buf, "%i\n", card->ipato.enabled? 1:0);
+-}
+-
+-static ssize_t
+-qeth_dev_ipato_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
+-
+- if (!card)
+- return -EINVAL;
+-
+- if ((card->state != CARD_STATE_DOWN) &&
+- (card->state != CARD_STATE_RECOVER))
+- return -EPERM;
+-
+- if (qeth_check_layer2(card))
+- return -EPERM;
+-
+- tmp = strsep((char **) &buf, "\n");
+- if (!strcmp(tmp, "toggle")){
+- card->ipato.enabled = (card->ipato.enabled)? 0 : 1;
+- } else if (!strcmp(tmp, "1")){
+- card->ipato.enabled = 1;
+- } else if (!strcmp(tmp, "0")){
+- card->ipato.enabled = 0;
+- } else {
+- PRINT_WARN("ipato_enable: write 0, 1 or 'toggle' to "
+- "this file\n");
+- return -EINVAL;
+- }
+- return count;
+-}
+-
+-static QETH_DEVICE_ATTR(ipato_enable, enable, 0644,
+- qeth_dev_ipato_enable_show,
+- qeth_dev_ipato_enable_store);
+-
+-static ssize_t
+-qeth_dev_ipato_invert4_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- if (qeth_check_layer2(card))
+- return -EPERM;
+-
+- return sprintf(buf, "%i\n", card->ipato.invert4? 1:0);
+-}
+-
+-static ssize_t
+-qeth_dev_ipato_invert4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
+-
+- if (!card)
+- return -EINVAL;
+-
+- if (qeth_check_layer2(card))
+- return -EPERM;
+-
+- tmp = strsep((char **) &buf, "\n");
+- if (!strcmp(tmp, "toggle")){
+- card->ipato.invert4 = (card->ipato.invert4)? 0 : 1;
+- } else if (!strcmp(tmp, "1")){
+- card->ipato.invert4 = 1;
+- } else if (!strcmp(tmp, "0")){
+- card->ipato.invert4 = 0;
+- } else {
+- PRINT_WARN("ipato_invert4: write 0, 1 or 'toggle' to "
+- "this file\n");
+- return -EINVAL;
+- }
+- return count;
+-}
+-
+-static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644,
+- qeth_dev_ipato_invert4_show,
+- qeth_dev_ipato_invert4_store);
+-
+-static ssize_t
+-qeth_dev_ipato_add_show(char *buf, struct qeth_card *card,
+- enum qeth_prot_versions proto)
+-{
+- struct qeth_ipato_entry *ipatoe;
+- unsigned long flags;
+- char addr_str[40];
+- int entry_len; /* length of 1 entry string, differs between v4 and v6 */
+- int i = 0;
+-
+- if (qeth_check_layer2(card))
+- return -EPERM;
+-
+- entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
+- /* add strlen for "/<mask>\n" */
+- entry_len += (proto == QETH_PROT_IPV4)? 5 : 6;
+- spin_lock_irqsave(&card->ip_lock, flags);
+- list_for_each_entry(ipatoe, &card->ipato.entries, entry){
+- if (ipatoe->proto != proto)
+- continue;
+- /* String must not be longer than PAGE_SIZE. So we check if
+- * string length gets near PAGE_SIZE. Then we can savely display
+- * the next IPv6 address (worst case, compared to IPv4) */
+- if ((PAGE_SIZE - i) <= entry_len)
+- break;
+- qeth_ipaddr_to_string(proto, ipatoe->addr, addr_str);
+- i += snprintf(buf + i, PAGE_SIZE - i,
+- "%s/%i\n", addr_str, ipatoe->mask_bits);
+- }
+- spin_unlock_irqrestore(&card->ip_lock, flags);
+- i += snprintf(buf + i, PAGE_SIZE - i, "\n");
+-
+- return i;
+-}
+-
+-static ssize_t
+-qeth_dev_ipato_add4_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return qeth_dev_ipato_add_show(buf, card, QETH_PROT_IPV4);
+-}
+-
+-static int
+-qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto,
+- u8 *addr, int *mask_bits)
+-{
+- const char *start, *end;
+- char *tmp;
+- char buffer[40] = {0, };
+-
+- start = buf;
+- /* get address string */
+- end = strchr(start, '/');
+- if (!end || (end - start >= 40)){
+- PRINT_WARN("Invalid format for ipato_addx/delx. "
+- "Use <ip addr>/<mask bits>\n");
+- return -EINVAL;
+- }
+- strncpy(buffer, start, end - start);
+- if (qeth_string_to_ipaddr(buffer, proto, addr)){
+- PRINT_WARN("Invalid IP address format!\n");
+- return -EINVAL;
+- }
+- start = end + 1;
+- *mask_bits = simple_strtoul(start, &tmp, 10);
+- if (!strlen(start) ||
+- (tmp == start) ||
+- (*mask_bits > ((proto == QETH_PROT_IPV4) ? 32 : 128))) {
+- PRINT_WARN("Invalid mask bits for ipato_addx/delx !\n");
+- return -EINVAL;
+- }
+- return 0;
+-}
+-
+-static ssize_t
+-qeth_dev_ipato_add_store(const char *buf, size_t count,
+- struct qeth_card *card, enum qeth_prot_versions proto)
+-{
+- struct qeth_ipato_entry *ipatoe;
+- u8 addr[16];
+- int mask_bits;
+- int rc;
+-
+- if (qeth_check_layer2(card))
+- return -EPERM;
+- if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits)))
+- return rc;
+-
+- if (!(ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL))){
+- PRINT_WARN("No memory to allocate ipato entry\n");
+- return -ENOMEM;
+- }
+- ipatoe->proto = proto;
+- memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16);
+- ipatoe->mask_bits = mask_bits;
+-
+- if ((rc = qeth_add_ipato_entry(card, ipatoe))){
+- kfree(ipatoe);
+- return rc;
+- }
+-
+- return count;
+-}
+-
+-static ssize_t
+-qeth_dev_ipato_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return qeth_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV4);
+-}
+-
+-static QETH_DEVICE_ATTR(ipato_add4, add4, 0644,
+- qeth_dev_ipato_add4_show,
+- qeth_dev_ipato_add4_store);
+-
+-static ssize_t
+-qeth_dev_ipato_del_store(const char *buf, size_t count,
+- struct qeth_card *card, enum qeth_prot_versions proto)
+-{
+- u8 addr[16];
+- int mask_bits;
+- int rc;
+-
+- if (qeth_check_layer2(card))
+- return -EPERM;
+- if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits)))
+- return rc;
+-
+- qeth_del_ipato_entry(card, proto, addr, mask_bits);
+-
+- return count;
+-}
+-
+-static ssize_t
+-qeth_dev_ipato_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return qeth_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV4);
+-}
+-
+-static QETH_DEVICE_ATTR(ipato_del4, del4, 0200, NULL,
+- qeth_dev_ipato_del4_store);
+-
+-#ifdef CONFIG_QETH_IPV6
+-static ssize_t
+-qeth_dev_ipato_invert6_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- if (qeth_check_layer2(card))
+- return -EPERM;
+-
+- return sprintf(buf, "%i\n", card->ipato.invert6? 1:0);
+-}
+-
+-static ssize_t
+-qeth_dev_ipato_invert6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+- char *tmp;
+-
+- if (!card)
+- return -EINVAL;
+-
+- if (qeth_check_layer2(card))
+- return -EPERM;
+-
+- tmp = strsep((char **) &buf, "\n");
+- if (!strcmp(tmp, "toggle")){
+- card->ipato.invert6 = (card->ipato.invert6)? 0 : 1;
+- } else if (!strcmp(tmp, "1")){
+- card->ipato.invert6 = 1;
+- } else if (!strcmp(tmp, "0")){
+- card->ipato.invert6 = 0;
+- } else {
+- PRINT_WARN("ipato_invert6: write 0, 1 or 'toggle' to "
+- "this file\n");
+- return -EINVAL;
+- }
+- return count;
+-}
+-
+-static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644,
+- qeth_dev_ipato_invert6_show,
+- qeth_dev_ipato_invert6_store);
+-
+-
+-static ssize_t
+-qeth_dev_ipato_add6_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return qeth_dev_ipato_add_show(buf, card, QETH_PROT_IPV6);
+-}
+-
+-static ssize_t
+-qeth_dev_ipato_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return qeth_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV6);
+-}
+-
+-static QETH_DEVICE_ATTR(ipato_add6, add6, 0644,
+- qeth_dev_ipato_add6_show,
+- qeth_dev_ipato_add6_store);
+-
+-static ssize_t
+-qeth_dev_ipato_del6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return qeth_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV6);
+-}
+-
+-static QETH_DEVICE_ATTR(ipato_del6, del6, 0200, NULL,
+- qeth_dev_ipato_del6_store);
+-#endif /* CONFIG_QETH_IPV6 */
+-
+-static struct device_attribute * qeth_ipato_device_attrs[] = {
+- &dev_attr_ipato_enable,
+- &dev_attr_ipato_invert4,
+- &dev_attr_ipato_add4,
+- &dev_attr_ipato_del4,
+-#ifdef CONFIG_QETH_IPV6
+- &dev_attr_ipato_invert6,
+- &dev_attr_ipato_add6,
+- &dev_attr_ipato_del6,
+-#endif
+- NULL,
+-};
+-
+-static struct attribute_group qeth_device_ipato_group = {
+- .name = "ipa_takeover",
+- .attrs = (struct attribute **)qeth_ipato_device_attrs,
+-};
+-
+-static ssize_t
+-qeth_dev_vipa_add_show(char *buf, struct qeth_card *card,
+- enum qeth_prot_versions proto)
+-{
+- struct qeth_ipaddr *ipaddr;
+- char addr_str[40];
+- int entry_len; /* length of 1 entry string, differs between v4 and v6 */
+- unsigned long flags;
+- int i = 0;
+-
+- if (qeth_check_layer2(card))
+- return -EPERM;
+-
+- entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
+- entry_len += 2; /* \n + terminator */
+- spin_lock_irqsave(&card->ip_lock, flags);
+- list_for_each_entry(ipaddr, &card->ip_list, entry){
+- if (ipaddr->proto != proto)
+- continue;
+- if (ipaddr->type != QETH_IP_TYPE_VIPA)
+- continue;
+- /* String must not be longer than PAGE_SIZE. So we check if
+- * string length gets near PAGE_SIZE. Then we can savely display
+- * the next IPv6 address (worst case, compared to IPv4) */
+- if ((PAGE_SIZE - i) <= entry_len)
+- break;
+- qeth_ipaddr_to_string(proto, (const u8 *)&ipaddr->u, addr_str);
+- i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
+- }
+- spin_unlock_irqrestore(&card->ip_lock, flags);
+- i += snprintf(buf + i, PAGE_SIZE - i, "\n");
+-
+- return i;
+-}
+-
+-static ssize_t
+-qeth_dev_vipa_add4_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return qeth_dev_vipa_add_show(buf, card, QETH_PROT_IPV4);
+-}
+-
+-static int
+-qeth_parse_vipae(const char* buf, enum qeth_prot_versions proto,
+- u8 *addr)
+-{
+- if (qeth_string_to_ipaddr(buf, proto, addr)){
+- PRINT_WARN("Invalid IP address format!\n");
+- return -EINVAL;
+- }
+- return 0;
+-}
+-
+-static ssize_t
+-qeth_dev_vipa_add_store(const char *buf, size_t count,
+- struct qeth_card *card, enum qeth_prot_versions proto)
+-{
+- u8 addr[16] = {0, };
+- int rc;
+-
+- if (qeth_check_layer2(card))
+- return -EPERM;
+- if ((rc = qeth_parse_vipae(buf, proto, addr)))
+- return rc;
+-
+- if ((rc = qeth_add_vipa(card, proto, addr)))
+- return rc;
+-
+- return count;
+-}
+-
+-static ssize_t
+-qeth_dev_vipa_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return qeth_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV4);
+-}
+-
+-static QETH_DEVICE_ATTR(vipa_add4, add4, 0644,
+- qeth_dev_vipa_add4_show,
+- qeth_dev_vipa_add4_store);
+-
+-static ssize_t
+-qeth_dev_vipa_del_store(const char *buf, size_t count,
+- struct qeth_card *card, enum qeth_prot_versions proto)
+-{
+- u8 addr[16];
+- int rc;
+-
+- if (qeth_check_layer2(card))
+- return -EPERM;
+- if ((rc = qeth_parse_vipae(buf, proto, addr)))
+- return rc;
+-
+- qeth_del_vipa(card, proto, addr);
+-
+- return count;
+-}
+-
+-static ssize_t
+-qeth_dev_vipa_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return qeth_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV4);
+-}
+-
+-static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL,
+- qeth_dev_vipa_del4_store);
+-
+-#ifdef CONFIG_QETH_IPV6
+-static ssize_t
+-qeth_dev_vipa_add6_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return qeth_dev_vipa_add_show(buf, card, QETH_PROT_IPV6);
+-}
+-
+-static ssize_t
+-qeth_dev_vipa_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return qeth_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV6);
+-}
+-
+-static QETH_DEVICE_ATTR(vipa_add6, add6, 0644,
+- qeth_dev_vipa_add6_show,
+- qeth_dev_vipa_add6_store);
+-
+-static ssize_t
+-qeth_dev_vipa_del6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- if (qeth_check_layer2(card))
+- return -EPERM;
+-
+- return qeth_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV6);
+-}
+-
+-static QETH_DEVICE_ATTR(vipa_del6, del6, 0200, NULL,
+- qeth_dev_vipa_del6_store);
+-#endif /* CONFIG_QETH_IPV6 */
+-
+-static struct device_attribute * qeth_vipa_device_attrs[] = {
+- &dev_attr_vipa_add4,
+- &dev_attr_vipa_del4,
+-#ifdef CONFIG_QETH_IPV6
+- &dev_attr_vipa_add6,
+- &dev_attr_vipa_del6,
+-#endif
+- NULL,
+-};
+-
+-static struct attribute_group qeth_device_vipa_group = {
+- .name = "vipa",
+- .attrs = (struct attribute **)qeth_vipa_device_attrs,
+-};
+-
+-static ssize_t
+-qeth_dev_rxip_add_show(char *buf, struct qeth_card *card,
+- enum qeth_prot_versions proto)
+-{
+- struct qeth_ipaddr *ipaddr;
+- char addr_str[40];
+- int entry_len; /* length of 1 entry string, differs between v4 and v6 */
+- unsigned long flags;
+- int i = 0;
+-
+- if (qeth_check_layer2(card))
+- return -EPERM;
+-
+- entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
+- entry_len += 2; /* \n + terminator */
+- spin_lock_irqsave(&card->ip_lock, flags);
+- list_for_each_entry(ipaddr, &card->ip_list, entry){
+- if (ipaddr->proto != proto)
+- continue;
+- if (ipaddr->type != QETH_IP_TYPE_RXIP)
+- continue;
+- /* String must not be longer than PAGE_SIZE. So we check if
+- * string length gets near PAGE_SIZE. Then we can savely display
+- * the next IPv6 address (worst case, compared to IPv4) */
+- if ((PAGE_SIZE - i) <= entry_len)
+- break;
+- qeth_ipaddr_to_string(proto, (const u8 *)&ipaddr->u, addr_str);
+- i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
+- }
+- spin_unlock_irqrestore(&card->ip_lock, flags);
+- i += snprintf(buf + i, PAGE_SIZE - i, "\n");
+-
+- return i;
+-}
+-
+-static ssize_t
+-qeth_dev_rxip_add4_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return qeth_dev_rxip_add_show(buf, card, QETH_PROT_IPV4);
+-}
+-
+-static int
+-qeth_parse_rxipe(const char* buf, enum qeth_prot_versions proto,
+- u8 *addr)
+-{
+- if (qeth_string_to_ipaddr(buf, proto, addr)){
+- PRINT_WARN("Invalid IP address format!\n");
+- return -EINVAL;
+- }
+- return 0;
+-}
+-
+-static ssize_t
+-qeth_dev_rxip_add_store(const char *buf, size_t count,
+- struct qeth_card *card, enum qeth_prot_versions proto)
+-{
+- u8 addr[16] = {0, };
+- int rc;
+-
+- if (qeth_check_layer2(card))
+- return -EPERM;
+- if ((rc = qeth_parse_rxipe(buf, proto, addr)))
+- return rc;
+-
+- if ((rc = qeth_add_rxip(card, proto, addr)))
+- return rc;
+-
+- return count;
+-}
+-
+-static ssize_t
+-qeth_dev_rxip_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return qeth_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV4);
+-}
+-
+-static QETH_DEVICE_ATTR(rxip_add4, add4, 0644,
+- qeth_dev_rxip_add4_show,
+- qeth_dev_rxip_add4_store);
+-
+-static ssize_t
+-qeth_dev_rxip_del_store(const char *buf, size_t count,
+- struct qeth_card *card, enum qeth_prot_versions proto)
+-{
+- u8 addr[16];
+- int rc;
+-
+- if (qeth_check_layer2(card))
+- return -EPERM;
+- if ((rc = qeth_parse_rxipe(buf, proto, addr)))
+- return rc;
+-
+- qeth_del_rxip(card, proto, addr);
+-
+- return count;
+-}
+-
+-static ssize_t
+-qeth_dev_rxip_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return qeth_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV4);
+-}
+-
+-static QETH_DEVICE_ATTR(rxip_del4, del4, 0200, NULL,
+- qeth_dev_rxip_del4_store);
+-
+-#ifdef CONFIG_QETH_IPV6
+-static ssize_t
+-qeth_dev_rxip_add6_show(struct device *dev, struct device_attribute *attr, char *buf)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return qeth_dev_rxip_add_show(buf, card, QETH_PROT_IPV6);
+-}
+-
+-static ssize_t
+-qeth_dev_rxip_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return qeth_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV6);
+-}
+-
+-static QETH_DEVICE_ATTR(rxip_add6, add6, 0644,
+- qeth_dev_rxip_add6_show,
+- qeth_dev_rxip_add6_store);
+-
+-static ssize_t
+-qeth_dev_rxip_del6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (!card)
+- return -EINVAL;
+-
+- return qeth_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV6);
+-}
+-
+-static QETH_DEVICE_ATTR(rxip_del6, del6, 0200, NULL,
+- qeth_dev_rxip_del6_store);
+-#endif /* CONFIG_QETH_IPV6 */
+-
+-static struct device_attribute * qeth_rxip_device_attrs[] = {
+- &dev_attr_rxip_add4,
+- &dev_attr_rxip_del4,
+-#ifdef CONFIG_QETH_IPV6
+- &dev_attr_rxip_add6,
+- &dev_attr_rxip_del6,
+-#endif
+- NULL,
+-};
+-
+-static struct attribute_group qeth_device_rxip_group = {
+- .name = "rxip",
+- .attrs = (struct attribute **)qeth_rxip_device_attrs,
+-};
+-
+-int
+-qeth_create_device_attributes(struct device *dev)
+-{
+- int ret;
+- struct qeth_card *card = dev->driver_data;
+-
+- if (card->info.type == QETH_CARD_TYPE_OSN)
+- return sysfs_create_group(&dev->kobj,
+- &qeth_osn_device_attr_group);
+-
+- if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_attr_group)))
+- return ret;
+- if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_ipato_group))){
+- sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
+- return ret;
+- }
+- if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_vipa_group))){
+- sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
+- sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
+- return ret;
+- }
+- if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_rxip_group))){
+- sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
+- sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
+- sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
+- return ret;
+- }
+- if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_blkt_group))){
+- sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
+- sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
+- sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
+- sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group);
+- return ret;
+- }
+- return 0;
+-}
+-
+-void
+-qeth_remove_device_attributes(struct device *dev)
+-{
+- struct qeth_card *card = dev->driver_data;
+-
+- if (card->info.type == QETH_CARD_TYPE_OSN) {
+- sysfs_remove_group(&dev->kobj, &qeth_osn_device_attr_group);
+- return;
+- }
+- sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
+- sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
+- sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
+- sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group);
+- sysfs_remove_group(&dev->kobj, &qeth_device_blkt_group);
+-}
+-
+-/**********************/
+-/* DRIVER ATTRIBUTES */
+-/**********************/
+-static ssize_t
+-qeth_driver_group_store(struct device_driver *ddrv, const char *buf,
+- size_t count)
+-{
+- const char *start, *end;
+- char bus_ids[3][BUS_ID_SIZE], *argv[3];
+- int i;
+- int err;
+-
+- start = buf;
+- for (i = 0; i < 3; i++) {
+- static const char delim[] = { ',', ',', '\n' };
+- int len;
+-
+- if (!(end = strchr(start, delim[i])))
+- return -EINVAL;
+- len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start);
+- strncpy(bus_ids[i], start, len);
+- bus_ids[i][len] = '\0';
+- start = end + 1;
+- argv[i] = bus_ids[i];
+- }
+- err = ccwgroup_create(qeth_root_dev, qeth_ccwgroup_driver.driver_id,
+- &qeth_ccw_driver, 3, argv);
+- if (err)
+- return err;
+- else
+- return count;
+-}
+-
+-
+-static DRIVER_ATTR(group, 0200, NULL, qeth_driver_group_store);
+-
+-static ssize_t
+-qeth_driver_notifier_register_store(struct device_driver *ddrv, const char *buf,
+- size_t count)
+-{
+- int rc;
+- int signum;
+- char *tmp, *tmp2;
+-
+- tmp = strsep((char **) &buf, "\n");
+- if (!strncmp(tmp, "unregister", 10)){
+- if ((rc = qeth_notifier_unregister(current)))
+- return rc;
+- return count;
+- }
+-
+- signum = simple_strtoul(tmp, &tmp2, 10);
+- if ((signum < 0) || (signum > 32)){
+- PRINT_WARN("Signal number %d is out of range\n", signum);
+- return -EINVAL;
+- }
+- if ((rc = qeth_notifier_register(current, signum)))
+- return rc;
+-
+- return count;
+-}
+-
+-static DRIVER_ATTR(notifier_register, 0200, NULL,
+- qeth_driver_notifier_register_store);
+-
+-int
+-qeth_create_driver_attributes(void)
+-{
+- int rc;
+-
+- if ((rc = driver_create_file(&qeth_ccwgroup_driver.driver,
+- &driver_attr_group)))
+- return rc;
+- return driver_create_file(&qeth_ccwgroup_driver.driver,
+- &driver_attr_notifier_register);
+-}
+-
+-void
+-qeth_remove_driver_attributes(void)
+-{
+- driver_remove_file(&qeth_ccwgroup_driver.driver,
+- &driver_attr_group);
+- driver_remove_file(&qeth_ccwgroup_driver.driver,
+- &driver_attr_notifier_register);
+-}
+diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h
+deleted file mode 100644
+index c20e923..0000000
+--- a/drivers/s390/net/qeth_tso.h
++++ /dev/null
+@@ -1,148 +0,0 @@
+-/*
+- * linux/drivers/s390/net/qeth_tso.h
+- *
+- * Header file for qeth TCP Segmentation Offload support.
+- *
+- * Copyright 2004 IBM Corporation
+- *
+- * Author(s): Frank Pavlic <fpavlic at de.ibm.com>
+- *
+- */
+-#ifndef __QETH_TSO_H__
+-#define __QETH_TSO_H__
+-
+-#include <linux/skbuff.h>
+-#include <linux/tcp.h>
+-#include <linux/ip.h>
+-#include <linux/ipv6.h>
+-#include <net/ip6_checksum.h>
+-#include "qeth.h"
+-#include "qeth_mpc.h"
+-
+-
+-static inline struct qeth_hdr_tso *
+-qeth_tso_prepare_skb(struct qeth_card *card, struct sk_buff **skb)
+-{
+- QETH_DBF_TEXT(trace, 5, "tsoprsk");
+- return qeth_push_skb(card, *skb, sizeof(struct qeth_hdr_tso));
+-}
+-
+-/**
+- * fill header for a TSO packet
+- */
+-static inline void
+-qeth_tso_fill_header(struct qeth_card *card, struct sk_buff *skb)
+-{
+- struct qeth_hdr_tso *hdr;
+- struct tcphdr *tcph;
+- struct iphdr *iph;
+-
+- QETH_DBF_TEXT(trace, 5, "tsofhdr");
+-
+- hdr = (struct qeth_hdr_tso *) skb->data;
+- iph = ip_hdr(skb);
+- tcph = tcp_hdr(skb);
+- /*fix header to TSO values ...*/
+- hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO;
+- /*set values which are fix for the first approach ...*/
+- hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso);
+- hdr->ext.imb_hdr_no = 1;
+- hdr->ext.hdr_type = 1;
+- hdr->ext.hdr_version = 1;
+- hdr->ext.hdr_len = 28;
+- /*insert non-fix values */
+- hdr->ext.mss = skb_shinfo(skb)->gso_size;
+- hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4);
+- hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len -
+- sizeof(struct qeth_hdr_tso));
+-}
+-
+-/**
+- * change some header values as requested by hardware
+- */
+-static inline void
+-qeth_tso_set_tcpip_header(struct qeth_card *card, struct sk_buff *skb)
+-{
+- struct iphdr *iph = ip_hdr(skb);
+- struct ipv6hdr *ip6h = ipv6_hdr(skb);
+- struct tcphdr *tcph = tcp_hdr(skb);
+-
+- tcph->check = 0;
+- if (skb->protocol == ETH_P_IPV6) {
+- ip6h->payload_len = 0;
+- tcph->check = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
+- 0, IPPROTO_TCP, 0);
+- return;
+- }
+- /*OSA want us to set these values ...*/
+- tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
+- 0, IPPROTO_TCP, 0);
+- iph->tot_len = 0;
+- iph->check = 0;
+-}
+-
+-static inline int
+-qeth_tso_prepare_packet(struct qeth_card *card, struct sk_buff *skb,
+- int ipv, int cast_type)
+-{
+- struct qeth_hdr_tso *hdr;
+-
+- QETH_DBF_TEXT(trace, 5, "tsoprep");
+-
+- hdr = (struct qeth_hdr_tso *) qeth_tso_prepare_skb(card, &skb);
+- if (hdr == NULL) {
+- QETH_DBF_TEXT(trace, 4, "tsoperr");
+- return -ENOMEM;
+- }
+- memset(hdr, 0, sizeof(struct qeth_hdr_tso));
+- /*fill first 32 bytes of qdio header as used
+- *FIXME: TSO has two struct members
+- * with different names but same size
+- * */
+- qeth_fill_header(card, &hdr->hdr, skb, ipv, cast_type);
+- qeth_tso_fill_header(card, skb);
+- qeth_tso_set_tcpip_header(card, skb);
+- return 0;
+-}
+-
+-static inline void
+-__qeth_fill_buffer_frag(struct sk_buff *skb, struct qdio_buffer *buffer,
+- int is_tso, int *next_element_to_fill)
+-{
+- struct skb_frag_struct *frag;
+- int fragno;
+- unsigned long addr;
+- int element, cnt, dlen;
+-
+- fragno = skb_shinfo(skb)->nr_frags;
+- element = *next_element_to_fill;
+- dlen = 0;
+-
+- if (is_tso)
+- buffer->element[element].flags =
+- SBAL_FLAGS_MIDDLE_FRAG;
+- else
+- buffer->element[element].flags =
+- SBAL_FLAGS_FIRST_FRAG;
+- if ( (dlen = (skb->len - skb->data_len)) ) {
+- buffer->element[element].addr = skb->data;
+- buffer->element[element].length = dlen;
+- element++;
+- }
+- for (cnt = 0; cnt < fragno; cnt++) {
+- frag = &skb_shinfo(skb)->frags[cnt];
+- addr = (page_to_pfn(frag->page) << PAGE_SHIFT) +
+- frag->page_offset;
+- buffer->element[element].addr = (char *)addr;
+- buffer->element[element].length = frag->size;
+- if (cnt < (fragno - 1))
+- buffer->element[element].flags =
+- SBAL_FLAGS_MIDDLE_FRAG;
+- else
+- buffer->element[element].flags =
+- SBAL_FLAGS_LAST_FRAG;
+- element++;
+- }
+- *next_element_to_fill = element;
+-}
+-#endif /* __QETH_TSO_H__ */
+diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
+index 644a06e..4d4b542 100644
+--- a/drivers/s390/s390mach.c
++++ b/drivers/s390/s390mach.c
+@@ -59,15 +59,15 @@ repeat:
+
+ printk(KERN_WARNING"%s: Code does not support more "
+ "than two chained crws; please report to "
+- "linux390 at de.ibm.com!\n", __FUNCTION__);
++ "linux390 at de.ibm.com!\n", __func__);
+ ccode = stcrw(&tmp_crw);
+ printk(KERN_WARNING"%s: crw reports slct=%d, oflw=%d, "
+ "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
+- __FUNCTION__, tmp_crw.slct, tmp_crw.oflw,
++ __func__, tmp_crw.slct, tmp_crw.oflw,
+ tmp_crw.chn, tmp_crw.rsc, tmp_crw.anc,
+ tmp_crw.erc, tmp_crw.rsid);
+ printk(KERN_WARNING"%s: This was crw number %x in the "
+- "chain\n", __FUNCTION__, chain);
++ "chain\n", __func__, chain);
+ if (ccode != 0)
+ break;
+ chain = tmp_crw.chn ? chain + 1 : 0;
+@@ -83,7 +83,7 @@ repeat:
+ crw[chain].rsid);
+ /* Check for overflows. */
+ if (crw[chain].oflw) {
+- pr_debug("%s: crw overflow detected!\n", __FUNCTION__);
++ pr_debug("%s: crw overflow detected!\n", __func__);
+ css_schedule_eval_all();
+ chain = 0;
+ continue;
+diff --git a/drivers/s390/s390mach.h b/drivers/s390/s390mach.h
+index d3ca428..ca681f9 100644
+--- a/drivers/s390/s390mach.h
++++ b/drivers/s390/s390mach.h
+@@ -105,4 +105,8 @@ static inline int stcrw(struct crw *pcrw )
+ #define ED_ETR_SYNC 12 /* External damage ETR sync check */
+ #define ED_ETR_SWITCH 13 /* External damage ETR switch to local */
+
++struct pt_regs;
++
++void s390_handle_mcck(void);
++void s390_do_machine_check(struct pt_regs *regs);
+ #endif /* __s390mach */
+diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
+index 874b55e..8c7e2b7 100644
+--- a/drivers/s390/scsi/zfcp_aux.c
++++ b/drivers/s390/scsi/zfcp_aux.c
+@@ -1030,10 +1030,10 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
+
+ /* initialize debug locks */
+
+- spin_lock_init(&adapter->erp_dbf_lock);
+ spin_lock_init(&adapter->hba_dbf_lock);
+ spin_lock_init(&adapter->san_dbf_lock);
+ spin_lock_init(&adapter->scsi_dbf_lock);
++ spin_lock_init(&adapter->rec_dbf_lock);
+
+ retval = zfcp_adapter_debug_register(adapter);
+ if (retval)
+@@ -1325,10 +1325,10 @@ zfcp_nameserver_enqueue(struct zfcp_adapter *adapter)
+
+ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_FC
+
+-static void
+-zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
+- struct fsf_status_read_buffer *status_buffer)
++static void zfcp_fsf_incoming_els_rscn(struct zfcp_fsf_req *fsf_req)
+ {
++ struct fsf_status_read_buffer *status_buffer = (void*)fsf_req->data;
++ struct zfcp_adapter *adapter = fsf_req->adapter;
+ struct fcp_rscn_head *fcp_rscn_head;
+ struct fcp_rscn_element *fcp_rscn_element;
+ struct zfcp_port *port;
+@@ -1375,7 +1375,8 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
+ ZFCP_LOG_INFO("incoming RSCN, trying to open "
+ "port 0x%016Lx\n", port->wwpn);
+ zfcp_erp_port_reopen(port,
+- ZFCP_STATUS_COMMON_ERP_FAILED);
++ ZFCP_STATUS_COMMON_ERP_FAILED,
++ 82, fsf_req);
+ continue;
+ }
+
+@@ -1406,10 +1407,10 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
+ }
+ }
+
+-static void
+-zfcp_fsf_incoming_els_plogi(struct zfcp_adapter *adapter,
+- struct fsf_status_read_buffer *status_buffer)
++static void zfcp_fsf_incoming_els_plogi(struct zfcp_fsf_req *fsf_req)
+ {
++ struct fsf_status_read_buffer *status_buffer = (void*)fsf_req->data;
++ struct zfcp_adapter *adapter = fsf_req->adapter;
+ struct fsf_plogi *els_plogi;
+ struct zfcp_port *port;
+ unsigned long flags;
+@@ -1428,14 +1429,14 @@ zfcp_fsf_incoming_els_plogi(struct zfcp_adapter *adapter,
+ status_buffer->d_id,
+ zfcp_get_busid_by_adapter(adapter));
+ } else {
+- zfcp_erp_port_forced_reopen(port, 0);
++ zfcp_erp_port_forced_reopen(port, 0, 83, fsf_req);
+ }
+ }
+
+-static void
+-zfcp_fsf_incoming_els_logo(struct zfcp_adapter *adapter,
+- struct fsf_status_read_buffer *status_buffer)
++static void zfcp_fsf_incoming_els_logo(struct zfcp_fsf_req *fsf_req)
+ {
++ struct fsf_status_read_buffer *status_buffer = (void*)fsf_req->data;
++ struct zfcp_adapter *adapter = fsf_req->adapter;
+ struct fcp_logo *els_logo = (struct fcp_logo *) status_buffer->payload;
+ struct zfcp_port *port;
+ unsigned long flags;
+@@ -1453,7 +1454,7 @@ zfcp_fsf_incoming_els_logo(struct zfcp_adapter *adapter,
+ status_buffer->d_id,
+ zfcp_get_busid_by_adapter(adapter));
+ } else {
+- zfcp_erp_port_forced_reopen(port, 0);
++ zfcp_erp_port_forced_reopen(port, 0, 84, fsf_req);
+ }
+ }
+
+@@ -1480,12 +1481,12 @@ zfcp_fsf_incoming_els(struct zfcp_fsf_req *fsf_req)
+
+ zfcp_san_dbf_event_incoming_els(fsf_req);
+ if (els_type == LS_PLOGI)
+- zfcp_fsf_incoming_els_plogi(adapter, status_buffer);
++ zfcp_fsf_incoming_els_plogi(fsf_req);
+ else if (els_type == LS_LOGO)
+- zfcp_fsf_incoming_els_logo(adapter, status_buffer);
++ zfcp_fsf_incoming_els_logo(fsf_req);
+ else if ((els_type & 0xffff0000) == LS_RSCN)
+ /* we are only concerned with the command, not the length */
+- zfcp_fsf_incoming_els_rscn(adapter, status_buffer);
++ zfcp_fsf_incoming_els_rscn(fsf_req);
+ else
+ zfcp_fsf_incoming_els_unknown(adapter, status_buffer);
+ }
+diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
+index edc5015..66d3b88 100644
+--- a/drivers/s390/scsi/zfcp_ccw.c
++++ b/drivers/s390/scsi/zfcp_ccw.c
+@@ -170,9 +170,10 @@ zfcp_ccw_set_online(struct ccw_device *ccw_device)
+ BUG_ON(!zfcp_reqlist_isempty(adapter));
+ adapter->req_no = 0;
+
+- zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING,
+- ZFCP_SET);
+- zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
++ zfcp_erp_modify_adapter_status(adapter, 10, NULL,
++ ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
++ zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 85,
++ NULL);
+ zfcp_erp_wait(adapter);
+ goto out;
+
+@@ -197,7 +198,7 @@ zfcp_ccw_set_offline(struct ccw_device *ccw_device)
+
+ down(&zfcp_data.config_sema);
+ adapter = dev_get_drvdata(&ccw_device->dev);
+- zfcp_erp_adapter_shutdown(adapter, 0);
++ zfcp_erp_adapter_shutdown(adapter, 0, 86, NULL);
+ zfcp_erp_wait(adapter);
+ zfcp_erp_thread_kill(adapter);
+ up(&zfcp_data.config_sema);
+@@ -223,24 +224,21 @@ zfcp_ccw_notify(struct ccw_device *ccw_device, int event)
+ case CIO_GONE:
+ ZFCP_LOG_NORMAL("adapter %s: device gone\n",
+ zfcp_get_busid_by_adapter(adapter));
+- debug_text_event(adapter->erp_dbf,1,"dev_gone");
+- zfcp_erp_adapter_shutdown(adapter, 0);
++ zfcp_erp_adapter_shutdown(adapter, 0, 87, NULL);
+ break;
+ case CIO_NO_PATH:
+ ZFCP_LOG_NORMAL("adapter %s: no path\n",
+ zfcp_get_busid_by_adapter(adapter));
+- debug_text_event(adapter->erp_dbf,1,"no_path");
+- zfcp_erp_adapter_shutdown(adapter, 0);
++ zfcp_erp_adapter_shutdown(adapter, 0, 88, NULL);
+ break;
+ case CIO_OPER:
+ ZFCP_LOG_NORMAL("adapter %s: operational again\n",
+ zfcp_get_busid_by_adapter(adapter));
+- debug_text_event(adapter->erp_dbf,1,"dev_oper");
+- zfcp_erp_modify_adapter_status(adapter,
++ zfcp_erp_modify_adapter_status(adapter, 11, NULL,
+ ZFCP_STATUS_COMMON_RUNNING,
+ ZFCP_SET);
+- zfcp_erp_adapter_reopen(adapter,
+- ZFCP_STATUS_COMMON_ERP_FAILED);
++ zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
++ 89, NULL);
+ break;
+ }
+ zfcp_erp_wait(adapter);
+@@ -272,7 +270,7 @@ zfcp_ccw_shutdown(struct ccw_device *cdev)
+
+ down(&zfcp_data.config_sema);
+ adapter = dev_get_drvdata(&cdev->dev);
+- zfcp_erp_adapter_shutdown(adapter, 0);
++ zfcp_erp_adapter_shutdown(adapter, 0, 90, NULL);
+ zfcp_erp_wait(adapter);
+ up(&zfcp_data.config_sema);
+ }
+diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
+index 701046c..37b85c6 100644
+--- a/drivers/s390/scsi/zfcp_dbf.c
++++ b/drivers/s390/scsi/zfcp_dbf.c
+@@ -31,123 +31,128 @@ MODULE_PARM_DESC(dbfsize,
+
+ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_OTHER
+
+-static int
+-zfcp_dbf_stck(char *out_buf, const char *label, unsigned long long stck)
++static void zfcp_dbf_hexdump(debug_info_t *dbf, void *to, int to_len,
++ int level, char *from, int from_len)
++{
++ int offset;
++ struct zfcp_dbf_dump *dump = to;
++ int room = to_len - sizeof(*dump);
++
++ for (offset = 0; offset < from_len; offset += dump->size) {
++ memset(to, 0, to_len);
++ strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
++ dump->total_size = from_len;
++ dump->offset = offset;
++ dump->size = min(from_len - offset, room);
++ memcpy(dump->data, from + offset, dump->size);
++ debug_event(dbf, level, dump, dump->size);
++ }
++}
++
++/* FIXME: this duplicate this code in s390 debug feature */
++static void zfcp_dbf_timestamp(unsigned long long stck, struct timespec *time)
+ {
+ unsigned long long sec;
+- struct timespec dbftime;
+- int len = 0;
+
+ stck -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096);
+ sec = stck >> 12;
+ do_div(sec, 1000000);
+- dbftime.tv_sec = sec;
++ time->tv_sec = sec;
+ stck -= (sec * 1000000) << 12;
+- dbftime.tv_nsec = ((stck * 1000) >> 12);
+- len += sprintf(out_buf + len, "%-24s%011lu:%06lu\n",
+- label, dbftime.tv_sec, dbftime.tv_nsec);
+-
+- return len;
++ time->tv_nsec = ((stck * 1000) >> 12);
+ }
+
+-static int zfcp_dbf_tag(char *out_buf, const char *label, const char *tag)
++static void zfcp_dbf_tag(char **p, const char *label, const char *tag)
+ {
+- int len = 0, i;
++ int i;
+
+- len += sprintf(out_buf + len, "%-24s", label);
++ *p += sprintf(*p, "%-24s", label);
+ for (i = 0; i < ZFCP_DBF_TAG_SIZE; i++)
+- len += sprintf(out_buf + len, "%c", tag[i]);
+- len += sprintf(out_buf + len, "\n");
++ *p += sprintf(*p, "%c", tag[i]);
++ *p += sprintf(*p, "\n");
++}
+
+- return len;
++static void zfcp_dbf_outs(char **buf, const char *s1, const char *s2)
++{
++ *buf += sprintf(*buf, "%-24s%s\n", s1, s2);
+ }
+
+-static int
+-zfcp_dbf_view(char *out_buf, const char *label, const char *format, ...)
++static void zfcp_dbf_out(char **buf, const char *s, const char *format, ...)
+ {
+ va_list arg;
+- int len = 0;
+
+- len += sprintf(out_buf + len, "%-24s", label);
++ *buf += sprintf(*buf, "%-24s", s);
+ va_start(arg, format);
+- len += vsprintf(out_buf + len, format, arg);
++ *buf += vsprintf(*buf, format, arg);
+ va_end(arg);
+- len += sprintf(out_buf + len, "\n");
+-
+- return len;
++ *buf += sprintf(*buf, "\n");
+ }
+
+-static int
+-zfcp_dbf_view_dump(char *out_buf, const char *label,
+- char *buffer, int buflen, int offset, int total_size)
++static void zfcp_dbf_outd(char **p, const char *label, char *buffer,
++ int buflen, int offset, int total_size)
+ {
+- int len = 0;
+-
+- if (offset == 0)
+- len += sprintf(out_buf + len, "%-24s ", label);
+-
++ if (!offset)
++ *p += sprintf(*p, "%-24s ", label);
+ while (buflen--) {
+ if (offset > 0) {
+ if ((offset % 32) == 0)
+- len += sprintf(out_buf + len, "\n%-24c ", ' ');
++ *p += sprintf(*p, "\n%-24c ", ' ');
+ else if ((offset % 4) == 0)
+- len += sprintf(out_buf + len, " ");
++ *p += sprintf(*p, " ");
+ }
+- len += sprintf(out_buf + len, "%02x", *buffer++);
++ *p += sprintf(*p, "%02x", *buffer++);
+ if (++offset == total_size) {
+- len += sprintf(out_buf + len, "\n");
++ *p += sprintf(*p, "\n");
+ break;
+ }
+ }
+-
+- if (total_size == 0)
+- len += sprintf(out_buf + len, "\n");
+-
+- return len;
++ if (!total_size)
++ *p += sprintf(*p, "\n");
+ }
+
+-static int
+-zfcp_dbf_view_header(debug_info_t * id, struct debug_view *view, int area,
+- debug_entry_t * entry, char *out_buf)
++static int zfcp_dbf_view_header(debug_info_t *id, struct debug_view *view,
++ int area, debug_entry_t *entry, char *out_buf)
+ {
+ struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)DEBUG_DATA(entry);
+- int len = 0;
++ struct timespec t;
++ char *p = out_buf;
+
+ if (strncmp(dump->tag, "dump", ZFCP_DBF_TAG_SIZE) != 0) {
+- len += zfcp_dbf_stck(out_buf + len, "timestamp",
+- entry->id.stck);
+- len += zfcp_dbf_view(out_buf + len, "cpu", "%02i",
+- entry->id.fields.cpuid);
+- } else {
+- len += zfcp_dbf_view_dump(out_buf + len, NULL,
+- dump->data,
+- dump->size,
+- dump->offset, dump->total_size);
++ zfcp_dbf_timestamp(entry->id.stck, &t);
++ zfcp_dbf_out(&p, "timestamp", "%011lu:%06lu",
++ t.tv_sec, t.tv_nsec);
++ zfcp_dbf_out(&p, "cpu", "%02i", entry->id.fields.cpuid);
++ } else {
++ zfcp_dbf_outd(&p, NULL, dump->data, dump->size, dump->offset,
++ dump->total_size);
+ if ((dump->offset + dump->size) == dump->total_size)
+- len += sprintf(out_buf + len, "\n");
++ p += sprintf(p, "\n");
+ }
+-
+- return len;
++ return p - out_buf;
+ }
+
++/**
++ * zfcp_hba_dbf_event_fsf_response - trace event for request completion
++ * @fsf_req: request that has been completed
++ */
+ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
+ {
+ struct zfcp_adapter *adapter = fsf_req->adapter;
+ struct fsf_qtcb *qtcb = fsf_req->qtcb;
+ union fsf_prot_status_qual *prot_status_qual =
+- &qtcb->prefix.prot_status_qual;
++ &qtcb->prefix.prot_status_qual;
+ union fsf_status_qual *fsf_status_qual = &qtcb->header.fsf_status_qual;
+ struct scsi_cmnd *scsi_cmnd;
+ struct zfcp_port *port;
+ struct zfcp_unit *unit;
+ struct zfcp_send_els *send_els;
+ struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf;
+- struct zfcp_hba_dbf_record_response *response = &rec->type.response;
++ struct zfcp_hba_dbf_record_response *response = &rec->u.response;
+ int level;
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
+- memset(rec, 0, sizeof(struct zfcp_hba_dbf_record));
++ memset(rec, 0, sizeof(*rec));
+ strncpy(rec->tag, "resp", ZFCP_DBF_TAG_SIZE);
+
+ if ((qtcb->prefix.prot_status != FSF_PROT_GOOD) &&
+@@ -161,6 +166,9 @@ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
+ (fsf_req->fsf_command == FSF_QTCB_OPEN_LUN)) {
+ strncpy(rec->tag2, "open", ZFCP_DBF_TAG_SIZE);
+ level = 4;
++ } else if (qtcb->header.log_length) {
++ strncpy(rec->tag2, "qtcb", ZFCP_DBF_TAG_SIZE);
++ level = 5;
+ } else {
+ strncpy(rec->tag2, "norm", ZFCP_DBF_TAG_SIZE);
+ level = 6;
+@@ -188,11 +196,9 @@ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
+ if (fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
+ break;
+ scsi_cmnd = (struct scsi_cmnd *)fsf_req->data;
+- if (scsi_cmnd != NULL) {
+- response->data.send_fcp.scsi_cmnd
+- = (unsigned long)scsi_cmnd;
+- response->data.send_fcp.scsi_serial
+- = scsi_cmnd->serial_number;
++ if (scsi_cmnd) {
++ response->u.fcp.cmnd = (unsigned long)scsi_cmnd;
++ response->u.fcp.serial = scsi_cmnd->serial_number;
+ }
+ break;
+
+@@ -200,25 +206,25 @@ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
+ case FSF_QTCB_CLOSE_PORT:
+ case FSF_QTCB_CLOSE_PHYSICAL_PORT:
+ port = (struct zfcp_port *)fsf_req->data;
+- response->data.port.wwpn = port->wwpn;
+- response->data.port.d_id = port->d_id;
+- response->data.port.port_handle = qtcb->header.port_handle;
++ response->u.port.wwpn = port->wwpn;
++ response->u.port.d_id = port->d_id;
++ response->u.port.port_handle = qtcb->header.port_handle;
+ break;
+
+ case FSF_QTCB_OPEN_LUN:
+ case FSF_QTCB_CLOSE_LUN:
+ unit = (struct zfcp_unit *)fsf_req->data;
+ port = unit->port;
+- response->data.unit.wwpn = port->wwpn;
+- response->data.unit.fcp_lun = unit->fcp_lun;
+- response->data.unit.port_handle = qtcb->header.port_handle;
+- response->data.unit.lun_handle = qtcb->header.lun_handle;
++ response->u.unit.wwpn = port->wwpn;
++ response->u.unit.fcp_lun = unit->fcp_lun;
++ response->u.unit.port_handle = qtcb->header.port_handle;
++ response->u.unit.lun_handle = qtcb->header.lun_handle;
+ break;
+
+ case FSF_QTCB_SEND_ELS:
+ send_els = (struct zfcp_send_els *)fsf_req->data;
+- response->data.send_els.d_id = qtcb->bottom.support.d_id;
+- response->data.send_els.ls_code = send_els->ls_code >> 24;
++ response->u.els.d_id = qtcb->bottom.support.d_id;
++ response->u.els.ls_code = send_els->ls_code >> 24;
+ break;
+
+ case FSF_QTCB_ABORT_FCP_CMND:
+@@ -230,39 +236,54 @@ void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
+ break;
+ }
+
+- debug_event(adapter->hba_dbf, level,
+- rec, sizeof(struct zfcp_hba_dbf_record));
++ debug_event(adapter->hba_dbf, level, rec, sizeof(*rec));
++
++ /* have fcp channel microcode fixed to use as little as possible */
++ if (fsf_req->fsf_command != FSF_QTCB_FCP_CMND) {
++ /* adjust length skipping trailing zeros */
++ char *buf = (char *)qtcb + qtcb->header.log_start;
++ int len = qtcb->header.log_length;
++ for (; len && !buf[len - 1]; len--);
++ zfcp_dbf_hexdump(adapter->hba_dbf, rec, sizeof(*rec), level,
++ buf, len);
++ }
++
+ spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
+ }
+
+-void
+-zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter,
+- struct fsf_status_read_buffer *status_buffer)
++/**
++ * zfcp_hba_dbf_event_fsf_unsol - trace event for an unsolicited status buffer
++ * @tag: tag indicating which kind of unsolicited status has been received
++ * @adapter: adapter that has issued the unsolicited status buffer
++ * @status_buffer: buffer containing payload of unsolicited status
++ */
++void zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter,
++ struct fsf_status_read_buffer *status_buffer)
+ {
+ struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf;
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
+- memset(rec, 0, sizeof(struct zfcp_hba_dbf_record));
++ memset(rec, 0, sizeof(*rec));
+ strncpy(rec->tag, "stat", ZFCP_DBF_TAG_SIZE);
+ strncpy(rec->tag2, tag, ZFCP_DBF_TAG_SIZE);
+
+- rec->type.status.failed = adapter->status_read_failed;
++ rec->u.status.failed = adapter->status_read_failed;
+ if (status_buffer != NULL) {
+- rec->type.status.status_type = status_buffer->status_type;
+- rec->type.status.status_subtype = status_buffer->status_subtype;
+- memcpy(&rec->type.status.queue_designator,
++ rec->u.status.status_type = status_buffer->status_type;
++ rec->u.status.status_subtype = status_buffer->status_subtype;
++ memcpy(&rec->u.status.queue_designator,
+ &status_buffer->queue_designator,
+ sizeof(struct fsf_queue_designator));
+
+ switch (status_buffer->status_type) {
+ case FSF_STATUS_READ_SENSE_DATA_AVAIL:
+- rec->type.status.payload_size =
++ rec->u.status.payload_size =
+ ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL;
+ break;
+
+ case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
+- rec->type.status.payload_size =
++ rec->u.status.payload_size =
+ ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD;
+ break;
+
+@@ -270,119 +291,101 @@ zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter,
+ switch (status_buffer->status_subtype) {
+ case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
+ case FSF_STATUS_READ_SUB_FDISC_FAILED:
+- rec->type.status.payload_size =
++ rec->u.status.payload_size =
+ sizeof(struct fsf_link_down_info);
+ }
+ break;
+
+ case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
+- rec->type.status.payload_size =
++ rec->u.status.payload_size =
+ ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT;
+ break;
+ }
+- memcpy(&rec->type.status.payload,
+- &status_buffer->payload, rec->type.status.payload_size);
++ memcpy(&rec->u.status.payload,
++ &status_buffer->payload, rec->u.status.payload_size);
+ }
+
+- debug_event(adapter->hba_dbf, 2,
+- rec, sizeof(struct zfcp_hba_dbf_record));
++ debug_event(adapter->hba_dbf, 2, rec, sizeof(*rec));
+ spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
+ }
+
+-void
+-zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, unsigned int status,
+- unsigned int qdio_error, unsigned int siga_error,
+- int sbal_index, int sbal_count)
++/**
++ * zfcp_hba_dbf_event_qdio - trace event for QDIO related failure
++ * @adapter: adapter affected by this QDIO related event
++ * @status: as passed by qdio module
++ * @qdio_error: as passed by qdio module
++ * @siga_error: as passed by qdio module
++ * @sbal_index: first buffer with error condition, as passed by qdio module
++ * @sbal_count: number of buffers affected, as passed by qdio module
++ */
++void zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, unsigned int status,
++ unsigned int qdio_error, unsigned int siga_error,
++ int sbal_index, int sbal_count)
+ {
+- struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf;
++ struct zfcp_hba_dbf_record *r = &adapter->hba_dbf_buf;
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
+- memset(rec, 0, sizeof(struct zfcp_hba_dbf_record));
+- strncpy(rec->tag, "qdio", ZFCP_DBF_TAG_SIZE);
+- rec->type.qdio.status = status;
+- rec->type.qdio.qdio_error = qdio_error;
+- rec->type.qdio.siga_error = siga_error;
+- rec->type.qdio.sbal_index = sbal_index;
+- rec->type.qdio.sbal_count = sbal_count;
+- debug_event(adapter->hba_dbf, 0,
+- rec, sizeof(struct zfcp_hba_dbf_record));
++ memset(r, 0, sizeof(*r));
++ strncpy(r->tag, "qdio", ZFCP_DBF_TAG_SIZE);
++ r->u.qdio.status = status;
++ r->u.qdio.qdio_error = qdio_error;
++ r->u.qdio.siga_error = siga_error;
++ r->u.qdio.sbal_index = sbal_index;
++ r->u.qdio.sbal_count = sbal_count;
++ debug_event(adapter->hba_dbf, 0, r, sizeof(*r));
+ spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
+ }
+
+-static int
+-zfcp_hba_dbf_view_response(char *out_buf,
+- struct zfcp_hba_dbf_record_response *rec)
+-{
+- int len = 0;
+-
+- len += zfcp_dbf_view(out_buf + len, "fsf_command", "0x%08x",
+- rec->fsf_command);
+- len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
+- rec->fsf_reqid);
+- len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
+- rec->fsf_seqno);
+- len += zfcp_dbf_stck(out_buf + len, "fsf_issued", rec->fsf_issued);
+- len += zfcp_dbf_view(out_buf + len, "fsf_prot_status", "0x%08x",
+- rec->fsf_prot_status);
+- len += zfcp_dbf_view(out_buf + len, "fsf_status", "0x%08x",
+- rec->fsf_status);
+- len += zfcp_dbf_view_dump(out_buf + len, "fsf_prot_status_qual",
+- rec->fsf_prot_status_qual,
+- FSF_PROT_STATUS_QUAL_SIZE,
+- 0, FSF_PROT_STATUS_QUAL_SIZE);
+- len += zfcp_dbf_view_dump(out_buf + len, "fsf_status_qual",
+- rec->fsf_status_qual,
+- FSF_STATUS_QUALIFIER_SIZE,
+- 0, FSF_STATUS_QUALIFIER_SIZE);
+- len += zfcp_dbf_view(out_buf + len, "fsf_req_status", "0x%08x",
+- rec->fsf_req_status);
+- len += zfcp_dbf_view(out_buf + len, "sbal_first", "0x%02x",
+- rec->sbal_first);
+- len += zfcp_dbf_view(out_buf + len, "sbal_curr", "0x%02x",
+- rec->sbal_curr);
+- len += zfcp_dbf_view(out_buf + len, "sbal_last", "0x%02x",
+- rec->sbal_last);
+- len += zfcp_dbf_view(out_buf + len, "pool", "0x%02x", rec->pool);
+-
+- switch (rec->fsf_command) {
++static void zfcp_hba_dbf_view_response(char **p,
++ struct zfcp_hba_dbf_record_response *r)
++{
++ struct timespec t;
++
++ zfcp_dbf_out(p, "fsf_command", "0x%08x", r->fsf_command);
++ zfcp_dbf_out(p, "fsf_reqid", "0x%0Lx", r->fsf_reqid);
++ zfcp_dbf_out(p, "fsf_seqno", "0x%08x", r->fsf_seqno);
++ zfcp_dbf_timestamp(r->fsf_issued, &t);
++ zfcp_dbf_out(p, "fsf_issued", "%011lu:%06lu", t.tv_sec, t.tv_nsec);
++ zfcp_dbf_out(p, "fsf_prot_status", "0x%08x", r->fsf_prot_status);
++ zfcp_dbf_out(p, "fsf_status", "0x%08x", r->fsf_status);
++ zfcp_dbf_outd(p, "fsf_prot_status_qual", r->fsf_prot_status_qual,
++ FSF_PROT_STATUS_QUAL_SIZE, 0, FSF_PROT_STATUS_QUAL_SIZE);
++ zfcp_dbf_outd(p, "fsf_status_qual", r->fsf_status_qual,
++ FSF_STATUS_QUALIFIER_SIZE, 0, FSF_STATUS_QUALIFIER_SIZE);
++ zfcp_dbf_out(p, "fsf_req_status", "0x%08x", r->fsf_req_status);
++ zfcp_dbf_out(p, "sbal_first", "0x%02x", r->sbal_first);
++ zfcp_dbf_out(p, "sbal_curr", "0x%02x", r->sbal_curr);
++ zfcp_dbf_out(p, "sbal_last", "0x%02x", r->sbal_last);
++ zfcp_dbf_out(p, "pool", "0x%02x", r->pool);
++
++ switch (r->fsf_command) {
+ case FSF_QTCB_FCP_CMND:
+- if (rec->fsf_req_status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
++ if (r->fsf_req_status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
+ break;
+- len += zfcp_dbf_view(out_buf + len, "scsi_cmnd", "0x%0Lx",
+- rec->data.send_fcp.scsi_cmnd);
+- len += zfcp_dbf_view(out_buf + len, "scsi_serial", "0x%016Lx",
+- rec->data.send_fcp.scsi_serial);
++ zfcp_dbf_out(p, "scsi_cmnd", "0x%0Lx", r->u.fcp.cmnd);
++ zfcp_dbf_out(p, "scsi_serial", "0x%016Lx", r->u.fcp.serial);
+ break;
+
+ case FSF_QTCB_OPEN_PORT_WITH_DID:
+ case FSF_QTCB_CLOSE_PORT:
+ case FSF_QTCB_CLOSE_PHYSICAL_PORT:
+- len += zfcp_dbf_view(out_buf + len, "wwpn", "0x%016Lx",
+- rec->data.port.wwpn);
+- len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x",
+- rec->data.port.d_id);
+- len += zfcp_dbf_view(out_buf + len, "port_handle", "0x%08x",
+- rec->data.port.port_handle);
++ zfcp_dbf_out(p, "wwpn", "0x%016Lx", r->u.port.wwpn);
++ zfcp_dbf_out(p, "d_id", "0x%06x", r->u.port.d_id);
++ zfcp_dbf_out(p, "port_handle", "0x%08x", r->u.port.port_handle);
+ break;
+
+ case FSF_QTCB_OPEN_LUN:
+ case FSF_QTCB_CLOSE_LUN:
+- len += zfcp_dbf_view(out_buf + len, "wwpn", "0x%016Lx",
+- rec->data.unit.wwpn);
+- len += zfcp_dbf_view(out_buf + len, "fcp_lun", "0x%016Lx",
+- rec->data.unit.fcp_lun);
+- len += zfcp_dbf_view(out_buf + len, "port_handle", "0x%08x",
+- rec->data.unit.port_handle);
+- len += zfcp_dbf_view(out_buf + len, "lun_handle", "0x%08x",
+- rec->data.unit.lun_handle);
++ zfcp_dbf_out(p, "wwpn", "0x%016Lx", r->u.unit.wwpn);
++ zfcp_dbf_out(p, "fcp_lun", "0x%016Lx", r->u.unit.fcp_lun);
++ zfcp_dbf_out(p, "port_handle", "0x%08x", r->u.unit.port_handle);
++ zfcp_dbf_out(p, "lun_handle", "0x%08x", r->u.unit.lun_handle);
+ break;
+
+ case FSF_QTCB_SEND_ELS:
+- len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x",
+- rec->data.send_els.d_id);
+- len += zfcp_dbf_view(out_buf + len, "ls_code", "0x%02x",
+- rec->data.send_els.ls_code);
++ zfcp_dbf_out(p, "d_id", "0x%06x", r->u.els.d_id);
++ zfcp_dbf_out(p, "ls_code", "0x%02x", r->u.els.ls_code);
+ break;
+
+ case FSF_QTCB_ABORT_FCP_CMND:
+@@ -393,74 +396,52 @@ zfcp_hba_dbf_view_response(char *out_buf,
+ case FSF_QTCB_UPLOAD_CONTROL_FILE:
+ break;
+ }
+-
+- return len;
+ }
+
+-static int
+-zfcp_hba_dbf_view_status(char *out_buf, struct zfcp_hba_dbf_record_status *rec)
++static void zfcp_hba_dbf_view_status(char **p,
++ struct zfcp_hba_dbf_record_status *r)
+ {
+- int len = 0;
+-
+- len += zfcp_dbf_view(out_buf + len, "failed", "0x%02x", rec->failed);
+- len += zfcp_dbf_view(out_buf + len, "status_type", "0x%08x",
+- rec->status_type);
+- len += zfcp_dbf_view(out_buf + len, "status_subtype", "0x%08x",
+- rec->status_subtype);
+- len += zfcp_dbf_view_dump(out_buf + len, "queue_designator",
+- (char *)&rec->queue_designator,
+- sizeof(struct fsf_queue_designator),
+- 0, sizeof(struct fsf_queue_designator));
+- len += zfcp_dbf_view_dump(out_buf + len, "payload",
+- (char *)&rec->payload,
+- rec->payload_size, 0, rec->payload_size);
+-
+- return len;
++ zfcp_dbf_out(p, "failed", "0x%02x", r->failed);
++ zfcp_dbf_out(p, "status_type", "0x%08x", r->status_type);
++ zfcp_dbf_out(p, "status_subtype", "0x%08x", r->status_subtype);
++ zfcp_dbf_outd(p, "queue_designator", (char *)&r->queue_designator,
++ sizeof(struct fsf_queue_designator), 0,
++ sizeof(struct fsf_queue_designator));
++ zfcp_dbf_outd(p, "payload", (char *)&r->payload, r->payload_size, 0,
++ r->payload_size);
+ }
+
+-static int
+-zfcp_hba_dbf_view_qdio(char *out_buf, struct zfcp_hba_dbf_record_qdio *rec)
++static void zfcp_hba_dbf_view_qdio(char **p, struct zfcp_hba_dbf_record_qdio *r)
+ {
+- int len = 0;
+-
+- len += zfcp_dbf_view(out_buf + len, "status", "0x%08x", rec->status);
+- len += zfcp_dbf_view(out_buf + len, "qdio_error", "0x%08x",
+- rec->qdio_error);
+- len += zfcp_dbf_view(out_buf + len, "siga_error", "0x%08x",
+- rec->siga_error);
+- len += zfcp_dbf_view(out_buf + len, "sbal_index", "0x%02x",
+- rec->sbal_index);
+- len += zfcp_dbf_view(out_buf + len, "sbal_count", "0x%02x",
+- rec->sbal_count);
+-
+- return len;
++ zfcp_dbf_out(p, "status", "0x%08x", r->status);
++ zfcp_dbf_out(p, "qdio_error", "0x%08x", r->qdio_error);
++ zfcp_dbf_out(p, "siga_error", "0x%08x", r->siga_error);
++ zfcp_dbf_out(p, "sbal_index", "0x%02x", r->sbal_index);
++ zfcp_dbf_out(p, "sbal_count", "0x%02x", r->sbal_count);
+ }
+
+-static int
+-zfcp_hba_dbf_view_format(debug_info_t * id, struct debug_view *view,
+- char *out_buf, const char *in_buf)
++static int zfcp_hba_dbf_view_format(debug_info_t *id, struct debug_view *view,
++ char *out_buf, const char *in_buf)
+ {
+- struct zfcp_hba_dbf_record *rec = (struct zfcp_hba_dbf_record *)in_buf;
+- int len = 0;
++ struct zfcp_hba_dbf_record *r = (struct zfcp_hba_dbf_record *)in_buf;
++ char *p = out_buf;
+
+- if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
++ if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
+ return 0;
+
+- len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag);
+- if (isalpha(rec->tag2[0]))
+- len += zfcp_dbf_tag(out_buf + len, "tag2", rec->tag2);
+- if (strncmp(rec->tag, "resp", ZFCP_DBF_TAG_SIZE) == 0)
+- len += zfcp_hba_dbf_view_response(out_buf + len,
+- &rec->type.response);
+- else if (strncmp(rec->tag, "stat", ZFCP_DBF_TAG_SIZE) == 0)
+- len += zfcp_hba_dbf_view_status(out_buf + len,
+- &rec->type.status);
+- else if (strncmp(rec->tag, "qdio", ZFCP_DBF_TAG_SIZE) == 0)
+- len += zfcp_hba_dbf_view_qdio(out_buf + len, &rec->type.qdio);
++ zfcp_dbf_tag(&p, "tag", r->tag);
++ if (isalpha(r->tag2[0]))
++ zfcp_dbf_tag(&p, "tag2", r->tag2);
+
+- len += sprintf(out_buf + len, "\n");
++ if (strncmp(r->tag, "resp", ZFCP_DBF_TAG_SIZE) == 0)
++ zfcp_hba_dbf_view_response(&p, &r->u.response);
++ else if (strncmp(r->tag, "stat", ZFCP_DBF_TAG_SIZE) == 0)
++ zfcp_hba_dbf_view_status(&p, &r->u.status);
++ else if (strncmp(r->tag, "qdio", ZFCP_DBF_TAG_SIZE) == 0)
++ zfcp_hba_dbf_view_qdio(&p, &r->u.qdio);
+
+- return len;
++ p += sprintf(p, "\n");
++ return p - out_buf;
+ }
+
+ static struct debug_view zfcp_hba_dbf_view = {
+@@ -472,219 +453,570 @@ static struct debug_view zfcp_hba_dbf_view = {
+ NULL
+ };
+
+-static void
+-_zfcp_san_dbf_event_common_ct(const char *tag, struct zfcp_fsf_req *fsf_req,
+- u32 s_id, u32 d_id, void *buffer, int buflen)
++static const char *zfcp_rec_dbf_tags[] = {
++ [ZFCP_REC_DBF_ID_THREAD] = "thread",
++ [ZFCP_REC_DBF_ID_TARGET] = "target",
++ [ZFCP_REC_DBF_ID_TRIGGER] = "trigger",
++ [ZFCP_REC_DBF_ID_ACTION] = "action",
++};
++
++static const char *zfcp_rec_dbf_ids[] = {
++ [1] = "new",
++ [2] = "ready",
++ [3] = "kill",
++ [4] = "down sleep",
++ [5] = "down wakeup",
++ [6] = "down sleep ecd",
++ [7] = "down wakeup ecd",
++ [8] = "down sleep epd",
++ [9] = "down wakeup epd",
++ [10] = "online",
++ [11] = "operational",
++ [12] = "scsi slave destroy",
++ [13] = "propagate failed adapter",
++ [14] = "propagate failed port",
++ [15] = "block adapter",
++ [16] = "unblock adapter",
++ [17] = "block port",
++ [18] = "unblock port",
++ [19] = "block unit",
++ [20] = "unblock unit",
++ [21] = "unit recovery failed",
++ [22] = "port recovery failed",
++ [23] = "adapter recovery failed",
++ [24] = "qdio queues down",
++ [25] = "p2p failed",
++ [26] = "nameserver lookup failed",
++ [27] = "nameserver port failed",
++ [28] = "link up",
++ [29] = "link down",
++ [30] = "link up status read",
++ [31] = "open port failed",
++ [32] = "open port failed",
++ [33] = "close port",
++ [34] = "open unit failed",
++ [35] = "exclusive open unit failed",
++ [36] = "shared open unit failed",
++ [37] = "link down",
++ [38] = "link down status read no link",
++ [39] = "link down status read fdisc login",
++ [40] = "link down status read firmware update",
++ [41] = "link down status read unknown reason",
++ [42] = "link down ecd incomplete",
++ [43] = "link down epd incomplete",
++ [44] = "sysfs adapter recovery",
++ [45] = "sysfs port recovery",
++ [46] = "sysfs unit recovery",
++ [47] = "port boxed abort",
++ [48] = "unit boxed abort",
++ [49] = "port boxed ct",
++ [50] = "port boxed close physical",
++ [51] = "port boxed open unit",
++ [52] = "port boxed close unit",
++ [53] = "port boxed fcp",
++ [54] = "unit boxed fcp",
++ [55] = "port access denied ct",
++ [56] = "port access denied els",
++ [57] = "port access denied open port",
++ [58] = "port access denied close physical",
++ [59] = "unit access denied open unit",
++ [60] = "shared unit access denied open unit",
++ [61] = "unit access denied fcp",
++ [62] = "request timeout",
++ [63] = "adisc link test reject or timeout",
++ [64] = "adisc link test d_id changed",
++ [65] = "adisc link test failed",
++ [66] = "recovery out of memory",
++ [67] = "adapter recovery repeated after state change",
++ [68] = "port recovery repeated after state change",
++ [69] = "unit recovery repeated after state change",
++ [70] = "port recovery follow-up after successful adapter recovery",
++ [71] = "adapter recovery escalation after failed adapter recovery",
++ [72] = "port recovery follow-up after successful physical port "
++ "recovery",
++ [73] = "adapter recovery escalation after failed physical port "
++ "recovery",
++ [74] = "unit recovery follow-up after successful port recovery",
++ [75] = "physical port recovery escalation after failed port "
++ "recovery",
++ [76] = "port recovery escalation after failed unit recovery",
++ [77] = "recovery opening nameserver port",
++ [78] = "duplicate request id",
++ [79] = "link down",
++ [80] = "exclusive read-only unit access unsupported",
++ [81] = "shared read-write unit access unsupported",
++ [82] = "incoming rscn",
++ [83] = "incoming plogi",
++ [84] = "incoming logo",
++ [85] = "online",
++ [86] = "offline",
++ [87] = "ccw device gone",
++ [88] = "ccw device no path",
++ [89] = "ccw device operational",
++ [90] = "ccw device shutdown",
++ [91] = "sysfs port addition",
++ [92] = "sysfs port removal",
++ [93] = "sysfs adapter recovery",
++ [94] = "sysfs unit addition",
++ [95] = "sysfs unit removal",
++ [96] = "sysfs port recovery",
++ [97] = "sysfs unit recovery",
++ [98] = "sequence number mismatch",
++ [99] = "link up",
++ [100] = "error state",
++ [101] = "status read physical port closed",
++ [102] = "link up status read",
++ [103] = "too many failed status read buffers",
++ [104] = "port handle not valid abort",
++ [105] = "lun handle not valid abort",
++ [106] = "port handle not valid ct",
++ [107] = "port handle not valid close port",
++ [108] = "port handle not valid close physical port",
++ [109] = "port handle not valid open unit",
++ [110] = "port handle not valid close unit",
++ [111] = "lun handle not valid close unit",
++ [112] = "port handle not valid fcp",
++ [113] = "lun handle not valid fcp",
++ [114] = "handle mismatch fcp",
++ [115] = "lun not valid fcp",
++ [116] = "qdio send failed",
++ [117] = "version mismatch",
++ [118] = "incompatible qtcb type",
++ [119] = "unknown protocol status",
++ [120] = "unknown fsf command",
++ [121] = "no recommendation for status qualifier",
++ [122] = "status read physical port closed in error",
++ [123] = "fc service class not supported ct",
++ [124] = "fc service class not supported els",
++ [125] = "need newer zfcp",
++ [126] = "need newer microcode",
++ [127] = "arbitrated loop not supported",
++ [128] = "unknown topology",
++ [129] = "qtcb size mismatch",
++ [130] = "unknown fsf status ecd",
++ [131] = "fcp request too big",
++ [132] = "fc service class not supported fcp",
++ [133] = "data direction not valid fcp",
++ [134] = "command length not valid fcp",
++ [135] = "status read act update",
++ [136] = "status read cfdc update",
++ [137] = "hbaapi port open",
++ [138] = "hbaapi unit open",
++ [139] = "hbaapi unit shutdown",
++ [140] = "qdio error",
++ [141] = "scsi host reset",
++ [142] = "dismissing fsf request for recovery action",
++ [143] = "recovery action timed out",
++ [144] = "recovery action gone",
++ [145] = "recovery action being processed",
++ [146] = "recovery action ready for next step",
++};
++
++static int zfcp_rec_dbf_view_format(debug_info_t *id, struct debug_view *view,
++ char *buf, const char *_rec)
++{
++ struct zfcp_rec_dbf_record *r = (struct zfcp_rec_dbf_record *)_rec;
++ char *p = buf;
++
++ zfcp_dbf_outs(&p, "tag", zfcp_rec_dbf_tags[r->id]);
++ zfcp_dbf_outs(&p, "hint", zfcp_rec_dbf_ids[r->id2]);
++ zfcp_dbf_out(&p, "id", "%d", r->id2);
++ switch (r->id) {
++ case ZFCP_REC_DBF_ID_THREAD:
++ zfcp_dbf_out(&p, "total", "%d", r->u.thread.total);
++ zfcp_dbf_out(&p, "ready", "%d", r->u.thread.ready);
++ zfcp_dbf_out(&p, "running", "%d", r->u.thread.running);
++ break;
++ case ZFCP_REC_DBF_ID_TARGET:
++ zfcp_dbf_out(&p, "reference", "0x%016Lx", r->u.target.ref);
++ zfcp_dbf_out(&p, "status", "0x%08x", r->u.target.status);
++ zfcp_dbf_out(&p, "erp_count", "%d", r->u.target.erp_count);
++ zfcp_dbf_out(&p, "d_id", "0x%06x", r->u.target.d_id);
++ zfcp_dbf_out(&p, "wwpn", "0x%016Lx", r->u.target.wwpn);
++ zfcp_dbf_out(&p, "fcp_lun", "0x%016Lx", r->u.target.fcp_lun);
++ break;
++ case ZFCP_REC_DBF_ID_TRIGGER:
++ zfcp_dbf_out(&p, "reference", "0x%016Lx", r->u.trigger.ref);
++ zfcp_dbf_out(&p, "erp_action", "0x%016Lx", r->u.trigger.action);
++ zfcp_dbf_out(&p, "requested", "%d", r->u.trigger.want);
++ zfcp_dbf_out(&p, "executed", "%d", r->u.trigger.need);
++ zfcp_dbf_out(&p, "wwpn", "0x%016Lx", r->u.trigger.wwpn);
++ zfcp_dbf_out(&p, "fcp_lun", "0x%016Lx", r->u.trigger.fcp_lun);
++ zfcp_dbf_out(&p, "adapter_status", "0x%08x", r->u.trigger.as);
++ zfcp_dbf_out(&p, "port_status", "0x%08x", r->u.trigger.ps);
++ zfcp_dbf_out(&p, "unit_status", "0x%08x", r->u.trigger.us);
++ break;
++ case ZFCP_REC_DBF_ID_ACTION:
++ zfcp_dbf_out(&p, "erp_action", "0x%016Lx", r->u.action.action);
++ zfcp_dbf_out(&p, "fsf_req", "0x%016Lx", r->u.action.fsf_req);
++ zfcp_dbf_out(&p, "status", "0x%08Lx", r->u.action.status);
++ zfcp_dbf_out(&p, "step", "0x%08Lx", r->u.action.step);
++ break;
++ }
++ p += sprintf(p, "\n");
++ return p - buf;
++}
++
++static struct debug_view zfcp_rec_dbf_view = {
++ "structured",
++ NULL,
++ &zfcp_dbf_view_header,
++ &zfcp_rec_dbf_view_format,
++ NULL,
++ NULL
++};
++
++/**
++ * zfcp_rec_dbf_event_thread - trace event related to recovery thread operation
++ * @id2: identifier for event
++ * @adapter: adapter
++ * @lock: non-zero value indicates that erp_lock has not yet been acquired
++ */
++void zfcp_rec_dbf_event_thread(u8 id2, struct zfcp_adapter *adapter, int lock)
++{
++ struct zfcp_rec_dbf_record *r = &adapter->rec_dbf_buf;
++ unsigned long flags = 0;
++ struct list_head *entry;
++ unsigned ready = 0, running = 0, total;
++
++ if (lock)
++ read_lock_irqsave(&adapter->erp_lock, flags);
++ list_for_each(entry, &adapter->erp_ready_head)
++ ready++;
++ list_for_each(entry, &adapter->erp_running_head)
++ running++;
++ total = adapter->erp_total_count;
++ if (lock)
++ read_unlock_irqrestore(&adapter->erp_lock, flags);
++
++ spin_lock_irqsave(&adapter->rec_dbf_lock, flags);
++ memset(r, 0, sizeof(*r));
++ r->id = ZFCP_REC_DBF_ID_THREAD;
++ r->id2 = id2;
++ r->u.thread.total = total;
++ r->u.thread.ready = ready;
++ r->u.thread.running = running;
++ debug_event(adapter->rec_dbf, 5, r, sizeof(*r));
++ spin_unlock_irqrestore(&adapter->rec_dbf_lock, flags);
++}
++
++static void zfcp_rec_dbf_event_target(u8 id2, void *ref,
++ struct zfcp_adapter *adapter,
++ atomic_t *status, atomic_t *erp_count,
++ u64 wwpn, u32 d_id, u64 fcp_lun)
++{
++ struct zfcp_rec_dbf_record *r = &adapter->rec_dbf_buf;
++ unsigned long flags;
++
++ spin_lock_irqsave(&adapter->rec_dbf_lock, flags);
++ memset(r, 0, sizeof(*r));
++ r->id = ZFCP_REC_DBF_ID_TARGET;
++ r->id2 = id2;
++ r->u.target.ref = (unsigned long)ref;
++ r->u.target.status = atomic_read(status);
++ r->u.target.wwpn = wwpn;
++ r->u.target.d_id = d_id;
++ r->u.target.fcp_lun = fcp_lun;
++ r->u.target.erp_count = atomic_read(erp_count);
++ debug_event(adapter->rec_dbf, 3, r, sizeof(*r));
++ spin_unlock_irqrestore(&adapter->rec_dbf_lock, flags);
++}
++
++/**
++ * zfcp_rec_dbf_event_adapter - trace event for adapter state change
++ * @id: identifier for trigger of state change
++ * @ref: additional reference (e.g. request)
++ * @adapter: adapter
++ */
++void zfcp_rec_dbf_event_adapter(u8 id, void *ref, struct zfcp_adapter *adapter)
++{
++ zfcp_rec_dbf_event_target(id, ref, adapter, &adapter->status,
++ &adapter->erp_counter, 0, 0, 0);
++}
++
++/**
++ * zfcp_rec_dbf_event_port - trace event for port state change
++ * @id: identifier for trigger of state change
++ * @ref: additional reference (e.g. request)
++ * @port: port
++ */
++void zfcp_rec_dbf_event_port(u8 id, void *ref, struct zfcp_port *port)
+ {
+- struct zfcp_send_ct *send_ct = (struct zfcp_send_ct *)fsf_req->data;
+- struct zfcp_port *port = send_ct->port;
+ struct zfcp_adapter *adapter = port->adapter;
+- struct ct_hdr *header = (struct ct_hdr *)buffer;
+- struct zfcp_san_dbf_record *rec = &adapter->san_dbf_buf;
+- struct zfcp_san_dbf_record_ct *ct = &rec->type.ct;
++
++ zfcp_rec_dbf_event_target(id, ref, adapter, &port->status,
++ &port->erp_counter, port->wwpn, port->d_id,
++ 0);
++}
++
++/**
++ * zfcp_rec_dbf_event_unit - trace event for unit state change
++ * @id: identifier for trigger of state change
++ * @ref: additional reference (e.g. request)
++ * @unit: unit
++ */
++void zfcp_rec_dbf_event_unit(u8 id, void *ref, struct zfcp_unit *unit)
++{
++ struct zfcp_port *port = unit->port;
++ struct zfcp_adapter *adapter = port->adapter;
++
++ zfcp_rec_dbf_event_target(id, ref, adapter, &unit->status,
++ &unit->erp_counter, port->wwpn, port->d_id,
++ unit->fcp_lun);
++}
++
++/**
++ * zfcp_rec_dbf_event_trigger - trace event for triggered error recovery
++ * @id2: identifier for error recovery trigger
++ * @ref: additional reference (e.g. request)
++ * @want: originally requested error recovery action
++ * @need: error recovery action actually initiated
++ * @action: address of error recovery action struct
++ * @adapter: adapter
++ * @port: port
++ * @unit: unit
++ */
++void zfcp_rec_dbf_event_trigger(u8 id2, void *ref, u8 want, u8 need,
++ void *action, struct zfcp_adapter *adapter,
++ struct zfcp_port *port, struct zfcp_unit *unit)
++{
++ struct zfcp_rec_dbf_record *r = &adapter->rec_dbf_buf;
+ unsigned long flags;
+
+- spin_lock_irqsave(&adapter->san_dbf_lock, flags);
+- memset(rec, 0, sizeof(struct zfcp_san_dbf_record));
+- strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
+- rec->fsf_reqid = (unsigned long)fsf_req;
+- rec->fsf_seqno = fsf_req->seq_no;
+- rec->s_id = s_id;
+- rec->d_id = d_id;
+- if (strncmp(tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) {
+- ct->type.request.cmd_req_code = header->cmd_rsp_code;
+- ct->type.request.revision = header->revision;
+- ct->type.request.gs_type = header->gs_type;
+- ct->type.request.gs_subtype = header->gs_subtype;
+- ct->type.request.options = header->options;
+- ct->type.request.max_res_size = header->max_res_size;
+- } else if (strncmp(tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) {
+- ct->type.response.cmd_rsp_code = header->cmd_rsp_code;
+- ct->type.response.revision = header->revision;
+- ct->type.response.reason_code = header->reason_code;
+- ct->type.response.reason_code_expl = header->reason_code_expl;
+- ct->type.response.vendor_unique = header->vendor_unique;
++ spin_lock_irqsave(&adapter->rec_dbf_lock, flags);
++ memset(r, 0, sizeof(*r));
++ r->id = ZFCP_REC_DBF_ID_TRIGGER;
++ r->id2 = id2;
++ r->u.trigger.ref = (unsigned long)ref;
++ r->u.trigger.want = want;
++ r->u.trigger.need = need;
++ r->u.trigger.action = (unsigned long)action;
++ r->u.trigger.as = atomic_read(&adapter->status);
++ if (port) {
++ r->u.trigger.ps = atomic_read(&port->status);
++ r->u.trigger.wwpn = port->wwpn;
+ }
+- ct->payload_size =
+- min(buflen - (int)sizeof(struct ct_hdr), ZFCP_DBF_CT_PAYLOAD);
+- memcpy(ct->payload, buffer + sizeof(struct ct_hdr), ct->payload_size);
+- debug_event(adapter->san_dbf, 3,
+- rec, sizeof(struct zfcp_san_dbf_record));
+- spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
++ if (unit) {
++ r->u.trigger.us = atomic_read(&unit->status);
++ r->u.trigger.fcp_lun = unit->fcp_lun;
++ }
++ debug_event(adapter->rec_dbf, action ? 1 : 4, r, sizeof(*r));
++ spin_unlock_irqrestore(&adapter->rec_dbf_lock, flags);
+ }
+
++/**
++ * zfcp_rec_dbf_event_action - trace event showing progress of recovery action
++ * @id2: identifier
++ * @erp_action: error recovery action struct pointer
++ */
++void zfcp_rec_dbf_event_action(u8 id2, struct zfcp_erp_action *erp_action)
++{
++ struct zfcp_adapter *adapter = erp_action->adapter;
++ struct zfcp_rec_dbf_record *r = &adapter->rec_dbf_buf;
++ unsigned long flags;
++
++ spin_lock_irqsave(&adapter->rec_dbf_lock, flags);
++ memset(r, 0, sizeof(*r));
++ r->id = ZFCP_REC_DBF_ID_ACTION;
++ r->id2 = id2;
++ r->u.action.action = (unsigned long)erp_action;
++ r->u.action.status = erp_action->status;
++ r->u.action.step = erp_action->step;
++ r->u.action.fsf_req = (unsigned long)erp_action->fsf_req;
++ debug_event(adapter->rec_dbf, 4, r, sizeof(*r));
++ spin_unlock_irqrestore(&adapter->rec_dbf_lock, flags);
++}
++
++/**
++ * zfcp_san_dbf_event_ct_request - trace event for issued CT request
++ * @fsf_req: request containing issued CT data
++ */
+ void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req)
+ {
+ struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
+ struct zfcp_port *port = ct->port;
+ struct zfcp_adapter *adapter = port->adapter;
++ struct ct_hdr *hdr = zfcp_sg_to_address(ct->req);
++ struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf;
++ struct zfcp_san_dbf_record_ct_request *oct = &r->u.ct_req;
++ unsigned long flags;
+
+- _zfcp_san_dbf_event_common_ct("octc", fsf_req,
+- fc_host_port_id(adapter->scsi_host),
+- port->d_id, zfcp_sg_to_address(ct->req),
+- ct->req->length);
++ spin_lock_irqsave(&adapter->san_dbf_lock, flags);
++ memset(r, 0, sizeof(*r));
++ strncpy(r->tag, "octc", ZFCP_DBF_TAG_SIZE);
++ r->fsf_reqid = (unsigned long)fsf_req;
++ r->fsf_seqno = fsf_req->seq_no;
++ r->s_id = fc_host_port_id(adapter->scsi_host);
++ r->d_id = port->d_id;
++ oct->cmd_req_code = hdr->cmd_rsp_code;
++ oct->revision = hdr->revision;
++ oct->gs_type = hdr->gs_type;
++ oct->gs_subtype = hdr->gs_subtype;
++ oct->options = hdr->options;
++ oct->max_res_size = hdr->max_res_size;
++ oct->len = min((int)ct->req->length - (int)sizeof(struct ct_hdr),
++ ZFCP_DBF_CT_PAYLOAD);
++ memcpy(oct->payload, (void *)hdr + sizeof(struct ct_hdr), oct->len);
++ debug_event(adapter->san_dbf, 3, r, sizeof(*r));
++ spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
+ }
+
++/**
++ * zfcp_san_dbf_event_ct_response - trace event for completion of CT request
++ * @fsf_req: request containing CT response
++ */
+ void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req)
+ {
+ struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
+ struct zfcp_port *port = ct->port;
+ struct zfcp_adapter *adapter = port->adapter;
++ struct ct_hdr *hdr = zfcp_sg_to_address(ct->resp);
++ struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf;
++ struct zfcp_san_dbf_record_ct_response *rct = &r->u.ct_resp;
++ unsigned long flags;
+
+- _zfcp_san_dbf_event_common_ct("rctc", fsf_req, port->d_id,
+- fc_host_port_id(adapter->scsi_host),
+- zfcp_sg_to_address(ct->resp),
+- ct->resp->length);
++ spin_lock_irqsave(&adapter->san_dbf_lock, flags);
++ memset(r, 0, sizeof(*r));
++ strncpy(r->tag, "rctc", ZFCP_DBF_TAG_SIZE);
++ r->fsf_reqid = (unsigned long)fsf_req;
++ r->fsf_seqno = fsf_req->seq_no;
++ r->s_id = port->d_id;
++ r->d_id = fc_host_port_id(adapter->scsi_host);
++ rct->cmd_rsp_code = hdr->cmd_rsp_code;
++ rct->revision = hdr->revision;
++ rct->reason_code = hdr->reason_code;
++ rct->expl = hdr->reason_code_expl;
++ rct->vendor_unique = hdr->vendor_unique;
++ rct->len = min((int)ct->resp->length - (int)sizeof(struct ct_hdr),
++ ZFCP_DBF_CT_PAYLOAD);
++ memcpy(rct->payload, (void *)hdr + sizeof(struct ct_hdr), rct->len);
++ debug_event(adapter->san_dbf, 3, r, sizeof(*r));
++ spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
+ }
+
+-static void
+-_zfcp_san_dbf_event_common_els(const char *tag, int level,
+- struct zfcp_fsf_req *fsf_req, u32 s_id,
+- u32 d_id, u8 ls_code, void *buffer, int buflen)
++static void zfcp_san_dbf_event_els(const char *tag, int level,
++ struct zfcp_fsf_req *fsf_req, u32 s_id,
++ u32 d_id, u8 ls_code, void *buffer,
++ int buflen)
+ {
+ struct zfcp_adapter *adapter = fsf_req->adapter;
+ struct zfcp_san_dbf_record *rec = &adapter->san_dbf_buf;
+- struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
+ unsigned long flags;
+- int offset = 0;
+
+ spin_lock_irqsave(&adapter->san_dbf_lock, flags);
+- do {
+- memset(rec, 0, sizeof(struct zfcp_san_dbf_record));
+- if (offset == 0) {
+- strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
+- rec->fsf_reqid = (unsigned long)fsf_req;
+- rec->fsf_seqno = fsf_req->seq_no;
+- rec->s_id = s_id;
+- rec->d_id = d_id;
+- rec->type.els.ls_code = ls_code;
+- buflen = min(buflen, ZFCP_DBF_ELS_MAX_PAYLOAD);
+- rec->type.els.payload_size = buflen;
+- memcpy(rec->type.els.payload,
+- buffer, min(buflen, ZFCP_DBF_ELS_PAYLOAD));
+- offset += min(buflen, ZFCP_DBF_ELS_PAYLOAD);
+- } else {
+- strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
+- dump->total_size = buflen;
+- dump->offset = offset;
+- dump->size = min(buflen - offset,
+- (int)sizeof(struct zfcp_san_dbf_record)
+- - (int)sizeof(struct zfcp_dbf_dump));
+- memcpy(dump->data, buffer + offset, dump->size);
+- offset += dump->size;
+- }
+- debug_event(adapter->san_dbf, level,
+- rec, sizeof(struct zfcp_san_dbf_record));
+- } while (offset < buflen);
++ memset(rec, 0, sizeof(*rec));
++ strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
++ rec->fsf_reqid = (unsigned long)fsf_req;
++ rec->fsf_seqno = fsf_req->seq_no;
++ rec->s_id = s_id;
++ rec->d_id = d_id;
++ rec->u.els.ls_code = ls_code;
++ debug_event(adapter->san_dbf, level, rec, sizeof(*rec));
++ zfcp_dbf_hexdump(adapter->san_dbf, rec, sizeof(*rec), level,
++ buffer, min(buflen, ZFCP_DBF_ELS_MAX_PAYLOAD));
+ spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
+ }
+
++/**
++ * zfcp_san_dbf_event_els_request - trace event for issued ELS
++ * @fsf_req: request containing issued ELS
++ */
+ void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req)
+ {
+ struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
+
+- _zfcp_san_dbf_event_common_els("oels", 2, fsf_req,
+- fc_host_port_id(els->adapter->scsi_host),
+- els->d_id,
+- *(u8 *) zfcp_sg_to_address(els->req),
+- zfcp_sg_to_address(els->req),
+- els->req->length);
++ zfcp_san_dbf_event_els("oels", 2, fsf_req,
++ fc_host_port_id(els->adapter->scsi_host),
++ els->d_id, *(u8 *) zfcp_sg_to_address(els->req),
++ zfcp_sg_to_address(els->req), els->req->length);
+ }
+
++/**
++ * zfcp_san_dbf_event_els_response - trace event for completed ELS
++ * @fsf_req: request containing ELS response
++ */
+ void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req)
+ {
+ struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
+
+- _zfcp_san_dbf_event_common_els("rels", 2, fsf_req, els->d_id,
+- fc_host_port_id(els->adapter->scsi_host),
+- *(u8 *) zfcp_sg_to_address(els->req),
+- zfcp_sg_to_address(els->resp),
+- els->resp->length);
++ zfcp_san_dbf_event_els("rels", 2, fsf_req, els->d_id,
++ fc_host_port_id(els->adapter->scsi_host),
++ *(u8 *)zfcp_sg_to_address(els->req),
++ zfcp_sg_to_address(els->resp),
++ els->resp->length);
+ }
+
++/**
++ * zfcp_san_dbf_event_incoming_els - trace event for incomig ELS
++ * @fsf_req: request containing unsolicited status buffer with incoming ELS
++ */
+ void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *fsf_req)
+ {
+ struct zfcp_adapter *adapter = fsf_req->adapter;
+- struct fsf_status_read_buffer *status_buffer =
+- (struct fsf_status_read_buffer *)fsf_req->data;
+- int length = (int)status_buffer->length -
+- (int)((void *)&status_buffer->payload - (void *)status_buffer);
+-
+- _zfcp_san_dbf_event_common_els("iels", 1, fsf_req, status_buffer->d_id,
+- fc_host_port_id(adapter->scsi_host),
+- *(u8 *) status_buffer->payload,
+- (void *)status_buffer->payload, length);
++ struct fsf_status_read_buffer *buf =
++ (struct fsf_status_read_buffer *)fsf_req->data;
++ int length = (int)buf->length -
++ (int)((void *)&buf->payload - (void *)buf);
++
++ zfcp_san_dbf_event_els("iels", 1, fsf_req, buf->d_id,
++ fc_host_port_id(adapter->scsi_host),
++ *(u8 *)buf->payload, (void *)buf->payload,
++ length);
+ }
+
+-static int
+-zfcp_san_dbf_view_format(debug_info_t * id, struct debug_view *view,
+- char *out_buf, const char *in_buf)
++static int zfcp_san_dbf_view_format(debug_info_t *id, struct debug_view *view,
++ char *out_buf, const char *in_buf)
+ {
+- struct zfcp_san_dbf_record *rec = (struct zfcp_san_dbf_record *)in_buf;
++ struct zfcp_san_dbf_record *r = (struct zfcp_san_dbf_record *)in_buf;
+ char *buffer = NULL;
+ int buflen = 0, total = 0;
+- int len = 0;
++ char *p = out_buf;
+
+- if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
++ if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
+ return 0;
+
+- len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag);
+- len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
+- rec->fsf_reqid);
+- len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
+- rec->fsf_seqno);
+- len += zfcp_dbf_view(out_buf + len, "s_id", "0x%06x", rec->s_id);
+- len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x", rec->d_id);
+-
+- if (strncmp(rec->tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) {
+- len += zfcp_dbf_view(out_buf + len, "cmd_req_code", "0x%04x",
+- rec->type.ct.type.request.cmd_req_code);
+- len += zfcp_dbf_view(out_buf + len, "revision", "0x%02x",
+- rec->type.ct.type.request.revision);
+- len += zfcp_dbf_view(out_buf + len, "gs_type", "0x%02x",
+- rec->type.ct.type.request.gs_type);
+- len += zfcp_dbf_view(out_buf + len, "gs_subtype", "0x%02x",
+- rec->type.ct.type.request.gs_subtype);
+- len += zfcp_dbf_view(out_buf + len, "options", "0x%02x",
+- rec->type.ct.type.request.options);
+- len += zfcp_dbf_view(out_buf + len, "max_res_size", "0x%04x",
+- rec->type.ct.type.request.max_res_size);
+- total = rec->type.ct.payload_size;
+- buffer = rec->type.ct.payload;
++ zfcp_dbf_tag(&p, "tag", r->tag);
++ zfcp_dbf_out(&p, "fsf_reqid", "0x%0Lx", r->fsf_reqid);
++ zfcp_dbf_out(&p, "fsf_seqno", "0x%08x", r->fsf_seqno);
++ zfcp_dbf_out(&p, "s_id", "0x%06x", r->s_id);
++ zfcp_dbf_out(&p, "d_id", "0x%06x", r->d_id);
++
++ if (strncmp(r->tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) {
++ struct zfcp_san_dbf_record_ct_request *ct = &r->u.ct_req;
++ zfcp_dbf_out(&p, "cmd_req_code", "0x%04x", ct->cmd_req_code);
++ zfcp_dbf_out(&p, "revision", "0x%02x", ct->revision);
++ zfcp_dbf_out(&p, "gs_type", "0x%02x", ct->gs_type);
++ zfcp_dbf_out(&p, "gs_subtype", "0x%02x", ct->gs_subtype);
++ zfcp_dbf_out(&p, "options", "0x%02x", ct->options);
++ zfcp_dbf_out(&p, "max_res_size", "0x%04x", ct->max_res_size);
++ total = ct->len;
++ buffer = ct->payload;
+ buflen = min(total, ZFCP_DBF_CT_PAYLOAD);
+- } else if (strncmp(rec->tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) {
+- len += zfcp_dbf_view(out_buf + len, "cmd_rsp_code", "0x%04x",
+- rec->type.ct.type.response.cmd_rsp_code);
+- len += zfcp_dbf_view(out_buf + len, "revision", "0x%02x",
+- rec->type.ct.type.response.revision);
+- len += zfcp_dbf_view(out_buf + len, "reason_code", "0x%02x",
+- rec->type.ct.type.response.reason_code);
+- len +=
+- zfcp_dbf_view(out_buf + len, "reason_code_expl", "0x%02x",
+- rec->type.ct.type.response.reason_code_expl);
+- len +=
+- zfcp_dbf_view(out_buf + len, "vendor_unique", "0x%02x",
+- rec->type.ct.type.response.vendor_unique);
+- total = rec->type.ct.payload_size;
+- buffer = rec->type.ct.payload;
++ } else if (strncmp(r->tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) {
++ struct zfcp_san_dbf_record_ct_response *ct = &r->u.ct_resp;
++ zfcp_dbf_out(&p, "cmd_rsp_code", "0x%04x", ct->cmd_rsp_code);
++ zfcp_dbf_out(&p, "revision", "0x%02x", ct->revision);
++ zfcp_dbf_out(&p, "reason_code", "0x%02x", ct->reason_code);
++ zfcp_dbf_out(&p, "reason_code_expl", "0x%02x", ct->expl);
++ zfcp_dbf_out(&p, "vendor_unique", "0x%02x", ct->vendor_unique);
++ total = ct->len;
++ buffer = ct->payload;
+ buflen = min(total, ZFCP_DBF_CT_PAYLOAD);
+- } else if (strncmp(rec->tag, "oels", ZFCP_DBF_TAG_SIZE) == 0 ||
+- strncmp(rec->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 ||
+- strncmp(rec->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) {
+- len += zfcp_dbf_view(out_buf + len, "ls_code", "0x%02x",
+- rec->type.els.ls_code);
+- total = rec->type.els.payload_size;
+- buffer = rec->type.els.payload;
++ } else if (strncmp(r->tag, "oels", ZFCP_DBF_TAG_SIZE) == 0 ||
++ strncmp(r->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 ||
++ strncmp(r->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) {
++ struct zfcp_san_dbf_record_els *els = &r->u.els;
++ zfcp_dbf_out(&p, "ls_code", "0x%02x", els->ls_code);
++ total = els->len;
++ buffer = els->payload;
+ buflen = min(total, ZFCP_DBF_ELS_PAYLOAD);
+ }
+
+- len += zfcp_dbf_view_dump(out_buf + len, "payload",
+- buffer, buflen, 0, total);
+-
++ zfcp_dbf_outd(&p, "payload", buffer, buflen, 0, total);
+ if (buflen == total)
+- len += sprintf(out_buf + len, "\n");
++ p += sprintf(p, "\n");
+
+- return len;
++ return p - out_buf;
+ }
+
+ static struct debug_view zfcp_san_dbf_view = {
+@@ -696,12 +1028,11 @@ static struct debug_view zfcp_san_dbf_view = {
+ NULL
+ };
+
+-static void
+-_zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
+- struct zfcp_adapter *adapter,
+- struct scsi_cmnd *scsi_cmnd,
+- struct zfcp_fsf_req *fsf_req,
+- unsigned long old_req_id)
++static void zfcp_scsi_dbf_event(const char *tag, const char *tag2, int level,
++ struct zfcp_adapter *adapter,
++ struct scsi_cmnd *scsi_cmnd,
++ struct zfcp_fsf_req *fsf_req,
++ unsigned long old_req_id)
+ {
+ struct zfcp_scsi_dbf_record *rec = &adapter->scsi_dbf_buf;
+ struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
+@@ -712,7 +1043,7 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
+
+ spin_lock_irqsave(&adapter->scsi_dbf_lock, flags);
+ do {
+- memset(rec, 0, sizeof(struct zfcp_scsi_dbf_record));
++ memset(rec, 0, sizeof(*rec));
+ if (offset == 0) {
+ strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE);
+ strncpy(rec->tag2, tag2, ZFCP_DBF_TAG_SIZE);
+@@ -738,20 +1069,16 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
+ fcp_sns_info =
+ zfcp_get_fcp_sns_info_ptr(fcp_rsp);
+
+- rec->type.fcp.rsp_validity =
+- fcp_rsp->validity.value;
+- rec->type.fcp.rsp_scsi_status =
+- fcp_rsp->scsi_status;
+- rec->type.fcp.rsp_resid = fcp_rsp->fcp_resid;
++ rec->rsp_validity = fcp_rsp->validity.value;
++ rec->rsp_scsi_status = fcp_rsp->scsi_status;
++ rec->rsp_resid = fcp_rsp->fcp_resid;
+ if (fcp_rsp->validity.bits.fcp_rsp_len_valid)
+- rec->type.fcp.rsp_code =
+- *(fcp_rsp_info + 3);
++ rec->rsp_code = *(fcp_rsp_info + 3);
+ if (fcp_rsp->validity.bits.fcp_sns_len_valid) {
+ buflen = min((int)fcp_rsp->fcp_sns_len,
+ ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO);
+- rec->type.fcp.sns_info_len = buflen;
+- memcpy(rec->type.fcp.sns_info,
+- fcp_sns_info,
++ rec->sns_info_len = buflen;
++ memcpy(rec->sns_info, fcp_sns_info,
+ min(buflen,
+ ZFCP_DBF_SCSI_FCP_SNS_INFO));
+ offset += min(buflen,
+@@ -762,7 +1089,7 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
+ rec->fsf_seqno = fsf_req->seq_no;
+ rec->fsf_issued = fsf_req->issued;
+ }
+- rec->type.old_fsf_reqid = old_req_id;
++ rec->old_fsf_reqid = old_req_id;
+ } else {
+ strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
+ dump->total_size = buflen;
+@@ -774,108 +1101,101 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
+ memcpy(dump->data, fcp_sns_info + offset, dump->size);
+ offset += dump->size;
+ }
+- debug_event(adapter->scsi_dbf, level,
+- rec, sizeof(struct zfcp_scsi_dbf_record));
++ debug_event(adapter->scsi_dbf, level, rec, sizeof(*rec));
+ } while (offset < buflen);
+ spin_unlock_irqrestore(&adapter->scsi_dbf_lock, flags);
+ }
+
+-void
+-zfcp_scsi_dbf_event_result(const char *tag, int level,
+- struct zfcp_adapter *adapter,
+- struct scsi_cmnd *scsi_cmnd,
+- struct zfcp_fsf_req *fsf_req)
++/**
++ * zfcp_scsi_dbf_event_result - trace event for SCSI command completion
++ * @tag: tag indicating success or failure of SCSI command
++ * @level: trace level applicable for this event
++ * @adapter: adapter that has been used to issue the SCSI command
++ * @scsi_cmnd: SCSI command pointer
++ * @fsf_req: request used to issue SCSI command (might be NULL)
++ */
++void zfcp_scsi_dbf_event_result(const char *tag, int level,
++ struct zfcp_adapter *adapter,
++ struct scsi_cmnd *scsi_cmnd,
++ struct zfcp_fsf_req *fsf_req)
+ {
+- _zfcp_scsi_dbf_event_common("rslt", tag, level,
+- adapter, scsi_cmnd, fsf_req, 0);
++ zfcp_scsi_dbf_event("rslt", tag, level, adapter, scsi_cmnd, fsf_req, 0);
+ }
+
+-void
+-zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter,
+- struct scsi_cmnd *scsi_cmnd,
+- struct zfcp_fsf_req *new_fsf_req,
+- unsigned long old_req_id)
++/**
++ * zfcp_scsi_dbf_event_abort - trace event for SCSI command abort
++ * @tag: tag indicating success or failure of abort operation
++ * @adapter: adapter thas has been used to issue SCSI command to be aborted
++ * @scsi_cmnd: SCSI command to be aborted
++ * @new_fsf_req: request containing abort (might be NULL)
++ * @old_req_id: identifier of request containg SCSI command to be aborted
++ */
++void zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter,
++ struct scsi_cmnd *scsi_cmnd,
++ struct zfcp_fsf_req *new_fsf_req,
++ unsigned long old_req_id)
+ {
+- _zfcp_scsi_dbf_event_common("abrt", tag, 1,
+- adapter, scsi_cmnd, new_fsf_req, old_req_id);
++ zfcp_scsi_dbf_event("abrt", tag, 1, adapter, scsi_cmnd, new_fsf_req,
++ old_req_id);
+ }
+
+-void
+-zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
+- struct scsi_cmnd *scsi_cmnd)
++/**
++ * zfcp_scsi_dbf_event_devreset - trace event for Logical Unit or Target Reset
++ * @tag: tag indicating success or failure of reset operation
++ * @flag: indicates type of reset (Target Reset, Logical Unit Reset)
++ * @unit: unit that needs reset
++ * @scsi_cmnd: SCSI command which caused this error recovery
++ */
++void zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag,
++ struct zfcp_unit *unit,
++ struct scsi_cmnd *scsi_cmnd)
+ {
+- struct zfcp_adapter *adapter = unit->port->adapter;
+-
+- _zfcp_scsi_dbf_event_common(flag == FCP_TARGET_RESET ? "trst" : "lrst",
+- tag, 1, adapter, scsi_cmnd, NULL, 0);
++ zfcp_scsi_dbf_event(flag == FCP_TARGET_RESET ? "trst" : "lrst", tag, 1,
++ unit->port->adapter, scsi_cmnd, NULL, 0);
+ }
+
+-static int
+-zfcp_scsi_dbf_view_format(debug_info_t * id, struct debug_view *view,
+- char *out_buf, const char *in_buf)
++static int zfcp_scsi_dbf_view_format(debug_info_t *id, struct debug_view *view,
++ char *out_buf, const char *in_buf)
+ {
+- struct zfcp_scsi_dbf_record *rec =
+- (struct zfcp_scsi_dbf_record *)in_buf;
+- int len = 0;
++ struct zfcp_scsi_dbf_record *r = (struct zfcp_scsi_dbf_record *)in_buf;
++ struct timespec t;
++ char *p = out_buf;
+
+- if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
++ if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0)
+ return 0;
+
+- len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag);
+- len += zfcp_dbf_tag(out_buf + len, "tag2", rec->tag2);
+- len += zfcp_dbf_view(out_buf + len, "scsi_id", "0x%08x", rec->scsi_id);
+- len += zfcp_dbf_view(out_buf + len, "scsi_lun", "0x%08x",
+- rec->scsi_lun);
+- len += zfcp_dbf_view(out_buf + len, "scsi_result", "0x%08x",
+- rec->scsi_result);
+- len += zfcp_dbf_view(out_buf + len, "scsi_cmnd", "0x%0Lx",
+- rec->scsi_cmnd);
+- len += zfcp_dbf_view(out_buf + len, "scsi_serial", "0x%016Lx",
+- rec->scsi_serial);
+- len += zfcp_dbf_view_dump(out_buf + len, "scsi_opcode",
+- rec->scsi_opcode,
+- ZFCP_DBF_SCSI_OPCODE,
+- 0, ZFCP_DBF_SCSI_OPCODE);
+- len += zfcp_dbf_view(out_buf + len, "scsi_retries", "0x%02x",
+- rec->scsi_retries);
+- len += zfcp_dbf_view(out_buf + len, "scsi_allowed", "0x%02x",
+- rec->scsi_allowed);
+- if (strncmp(rec->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) {
+- len += zfcp_dbf_view(out_buf + len, "old_fsf_reqid", "0x%0Lx",
+- rec->type.old_fsf_reqid);
+- }
+- len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx",
+- rec->fsf_reqid);
+- len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x",
+- rec->fsf_seqno);
+- len += zfcp_dbf_stck(out_buf + len, "fsf_issued", rec->fsf_issued);
+- if (strncmp(rec->tag, "rslt", ZFCP_DBF_TAG_SIZE) == 0) {
+- len +=
+- zfcp_dbf_view(out_buf + len, "fcp_rsp_validity", "0x%02x",
+- rec->type.fcp.rsp_validity);
+- len +=
+- zfcp_dbf_view(out_buf + len, "fcp_rsp_scsi_status",
+- "0x%02x", rec->type.fcp.rsp_scsi_status);
+- len +=
+- zfcp_dbf_view(out_buf + len, "fcp_rsp_resid", "0x%08x",
+- rec->type.fcp.rsp_resid);
+- len +=
+- zfcp_dbf_view(out_buf + len, "fcp_rsp_code", "0x%08x",
+- rec->type.fcp.rsp_code);
+- len +=
+- zfcp_dbf_view(out_buf + len, "fcp_sns_info_len", "0x%08x",
+- rec->type.fcp.sns_info_len);
+- len +=
+- zfcp_dbf_view_dump(out_buf + len, "fcp_sns_info",
+- rec->type.fcp.sns_info,
+- min((int)rec->type.fcp.sns_info_len,
+- ZFCP_DBF_SCSI_FCP_SNS_INFO), 0,
+- rec->type.fcp.sns_info_len);
++ zfcp_dbf_tag(&p, "tag", r->tag);
++ zfcp_dbf_tag(&p, "tag2", r->tag2);
++ zfcp_dbf_out(&p, "scsi_id", "0x%08x", r->scsi_id);
++ zfcp_dbf_out(&p, "scsi_lun", "0x%08x", r->scsi_lun);
++ zfcp_dbf_out(&p, "scsi_result", "0x%08x", r->scsi_result);
++ zfcp_dbf_out(&p, "scsi_cmnd", "0x%0Lx", r->scsi_cmnd);
++ zfcp_dbf_out(&p, "scsi_serial", "0x%016Lx", r->scsi_serial);
++ zfcp_dbf_outd(&p, "scsi_opcode", r->scsi_opcode, ZFCP_DBF_SCSI_OPCODE,
++ 0, ZFCP_DBF_SCSI_OPCODE);
++ zfcp_dbf_out(&p, "scsi_retries", "0x%02x", r->scsi_retries);
++ zfcp_dbf_out(&p, "scsi_allowed", "0x%02x", r->scsi_allowed);
++ if (strncmp(r->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0)
++ zfcp_dbf_out(&p, "old_fsf_reqid", "0x%0Lx", r->old_fsf_reqid);
++ zfcp_dbf_out(&p, "fsf_reqid", "0x%0Lx", r->fsf_reqid);
++ zfcp_dbf_out(&p, "fsf_seqno", "0x%08x", r->fsf_seqno);
++ zfcp_dbf_timestamp(r->fsf_issued, &t);
++ zfcp_dbf_out(&p, "fsf_issued", "%011lu:%06lu", t.tv_sec, t.tv_nsec);
++
++ if (strncmp(r->tag, "rslt", ZFCP_DBF_TAG_SIZE) == 0) {
++ zfcp_dbf_out(&p, "fcp_rsp_validity", "0x%02x", r->rsp_validity);
++ zfcp_dbf_out(&p, "fcp_rsp_scsi_status", "0x%02x",
++ r->rsp_scsi_status);
++ zfcp_dbf_out(&p, "fcp_rsp_resid", "0x%08x", r->rsp_resid);
++ zfcp_dbf_out(&p, "fcp_rsp_code", "0x%08x", r->rsp_code);
++ zfcp_dbf_out(&p, "fcp_sns_info_len", "0x%08x", r->sns_info_len);
++ zfcp_dbf_outd(&p, "fcp_sns_info", r->sns_info,
++ min((int)r->sns_info_len,
++ ZFCP_DBF_SCSI_FCP_SNS_INFO), 0,
++ r->sns_info_len);
+ }
+-
+- len += sprintf(out_buf + len, "\n");
+-
+- return len;
++ p += sprintf(p, "\n");
++ return p - out_buf;
+ }
+
+ static struct debug_view zfcp_scsi_dbf_view = {
+@@ -897,13 +1217,14 @@ int zfcp_adapter_debug_register(struct zfcp_adapter *adapter)
+ char dbf_name[DEBUG_MAX_NAME_LEN];
+
+ /* debug feature area which records recovery activity */
+- sprintf(dbf_name, "zfcp_%s_erp", zfcp_get_busid_by_adapter(adapter));
+- adapter->erp_dbf = debug_register(dbf_name, dbfsize, 2,
+- sizeof(struct zfcp_erp_dbf_record));
+- if (!adapter->erp_dbf)
++ sprintf(dbf_name, "zfcp_%s_rec", zfcp_get_busid_by_adapter(adapter));
++ adapter->rec_dbf = debug_register(dbf_name, dbfsize, 1,
++ sizeof(struct zfcp_rec_dbf_record));
++ if (!adapter->rec_dbf)
+ goto failed;
+- debug_register_view(adapter->erp_dbf, &debug_hex_ascii_view);
+- debug_set_level(adapter->erp_dbf, 3);
++ debug_register_view(adapter->rec_dbf, &debug_hex_ascii_view);
++ debug_register_view(adapter->rec_dbf, &zfcp_rec_dbf_view);
++ debug_set_level(adapter->rec_dbf, 3);
+
+ /* debug feature area which records HBA (FSF and QDIO) conditions */
+ sprintf(dbf_name, "zfcp_%s_hba", zfcp_get_busid_by_adapter(adapter));
+@@ -952,11 +1273,11 @@ void zfcp_adapter_debug_unregister(struct zfcp_adapter *adapter)
+ debug_unregister(adapter->scsi_dbf);
+ debug_unregister(adapter->san_dbf);
+ debug_unregister(adapter->hba_dbf);
+- debug_unregister(adapter->erp_dbf);
++ debug_unregister(adapter->rec_dbf);
+ adapter->scsi_dbf = NULL;
+ adapter->san_dbf = NULL;
+ adapter->hba_dbf = NULL;
+- adapter->erp_dbf = NULL;
++ adapter->rec_dbf = NULL;
+ }
+
+ #undef ZFCP_LOG_AREA
+diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h
+new file mode 100644
+index 0000000..54c34e4
+--- /dev/null
++++ b/drivers/s390/scsi/zfcp_dbf.h
+@@ -0,0 +1,228 @@
++/*
++ * This file is part of the zfcp device driver for
++ * FCP adapters for IBM System z9 and zSeries.
++ *
++ * Copyright IBM Corp. 2008, 2008
++ *
++ * 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, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef ZFCP_DBF_H
++#define ZFCP_DBF_H
++
++#include "zfcp_fsf.h"
++
++#define ZFCP_DBF_TAG_SIZE 4
++
++struct zfcp_dbf_dump {
++ u8 tag[ZFCP_DBF_TAG_SIZE];
++ u32 total_size; /* size of total dump data */
++ u32 offset; /* how much data has being already dumped */
++ u32 size; /* how much data comes with this record */
++ u8 data[]; /* dump data */
++} __attribute__ ((packed));
++
++struct zfcp_rec_dbf_record_thread {
++ u32 total;
++ u32 ready;
++ u32 running;
++} __attribute__ ((packed));
++
++struct zfcp_rec_dbf_record_target {
++ u64 ref;
++ u32 status;
++ u32 d_id;
++ u64 wwpn;
++ u64 fcp_lun;
++ u32 erp_count;
++} __attribute__ ((packed));
++
++struct zfcp_rec_dbf_record_trigger {
++ u8 want;
++ u8 need;
++ u32 as;
++ u32 ps;
++ u32 us;
++ u64 ref;
++ u64 action;
++ u64 wwpn;
++ u64 fcp_lun;
++} __attribute__ ((packed));
++
++struct zfcp_rec_dbf_record_action {
++ u32 status;
++ u32 step;
++ u64 action;
++ u64 fsf_req;
++} __attribute__ ((packed));
++
++struct zfcp_rec_dbf_record {
++ u8 id;
++ u8 id2;
++ union {
++ struct zfcp_rec_dbf_record_action action;
++ struct zfcp_rec_dbf_record_thread thread;
++ struct zfcp_rec_dbf_record_target target;
++ struct zfcp_rec_dbf_record_trigger trigger;
++ } u;
++} __attribute__ ((packed));
++
++enum {
++ ZFCP_REC_DBF_ID_ACTION,
++ ZFCP_REC_DBF_ID_THREAD,
++ ZFCP_REC_DBF_ID_TARGET,
++ ZFCP_REC_DBF_ID_TRIGGER,
++};
++
++struct zfcp_hba_dbf_record_response {
++ u32 fsf_command;
++ u64 fsf_reqid;
++ u32 fsf_seqno;
++ u64 fsf_issued;
++ u32 fsf_prot_status;
++ u32 fsf_status;
++ u8 fsf_prot_status_qual[FSF_PROT_STATUS_QUAL_SIZE];
++ u8 fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE];
++ u32 fsf_req_status;
++ u8 sbal_first;
++ u8 sbal_curr;
++ u8 sbal_last;
++ u8 pool;
++ u64 erp_action;
++ union {
++ struct {
++ u64 cmnd;
++ u64 serial;
++ } fcp;
++ struct {
++ u64 wwpn;
++ u32 d_id;
++ u32 port_handle;
++ } port;
++ struct {
++ u64 wwpn;
++ u64 fcp_lun;
++ u32 port_handle;
++ u32 lun_handle;
++ } unit;
++ struct {
++ u32 d_id;
++ u8 ls_code;
++ } els;
++ } u;
++} __attribute__ ((packed));
++
++struct zfcp_hba_dbf_record_status {
++ u8 failed;
++ u32 status_type;
++ u32 status_subtype;
++ struct fsf_queue_designator
++ queue_designator;
++ u32 payload_size;
++#define ZFCP_DBF_UNSOL_PAYLOAD 80
++#define ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL 32
++#define ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD 56
++#define ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT 2 * sizeof(u32)
++ u8 payload[ZFCP_DBF_UNSOL_PAYLOAD];
++} __attribute__ ((packed));
++
++struct zfcp_hba_dbf_record_qdio {
++ u32 status;
++ u32 qdio_error;
++ u32 siga_error;
++ u8 sbal_index;
++ u8 sbal_count;
++} __attribute__ ((packed));
++
++struct zfcp_hba_dbf_record {
++ u8 tag[ZFCP_DBF_TAG_SIZE];
++ u8 tag2[ZFCP_DBF_TAG_SIZE];
++ union {
++ struct zfcp_hba_dbf_record_response response;
++ struct zfcp_hba_dbf_record_status status;
++ struct zfcp_hba_dbf_record_qdio qdio;
++ } u;
++} __attribute__ ((packed));
++
++struct zfcp_san_dbf_record_ct_request {
++ u16 cmd_req_code;
++ u8 revision;
++ u8 gs_type;
++ u8 gs_subtype;
++ u8 options;
++ u16 max_res_size;
++ u32 len;
++#define ZFCP_DBF_CT_PAYLOAD 24
++ u8 payload[ZFCP_DBF_CT_PAYLOAD];
++} __attribute__ ((packed));
++
++struct zfcp_san_dbf_record_ct_response {
++ u16 cmd_rsp_code;
++ u8 revision;
++ u8 reason_code;
++ u8 expl;
++ u8 vendor_unique;
++ u32 len;
++ u8 payload[ZFCP_DBF_CT_PAYLOAD];
++} __attribute__ ((packed));
++
++struct zfcp_san_dbf_record_els {
++ u8 ls_code;
++ u32 len;
++#define ZFCP_DBF_ELS_PAYLOAD 32
++#define ZFCP_DBF_ELS_MAX_PAYLOAD 1024
++ u8 payload[ZFCP_DBF_ELS_PAYLOAD];
++} __attribute__ ((packed));
++
++struct zfcp_san_dbf_record {
++ u8 tag[ZFCP_DBF_TAG_SIZE];
++ u64 fsf_reqid;
++ u32 fsf_seqno;
++ u32 s_id;
++ u32 d_id;
++ union {
++ struct zfcp_san_dbf_record_ct_request ct_req;
++ struct zfcp_san_dbf_record_ct_response ct_resp;
++ struct zfcp_san_dbf_record_els els;
++ } u;
++} __attribute__ ((packed));
++
++struct zfcp_scsi_dbf_record {
++ u8 tag[ZFCP_DBF_TAG_SIZE];
++ u8 tag2[ZFCP_DBF_TAG_SIZE];
++ u32 scsi_id;
++ u32 scsi_lun;
++ u32 scsi_result;
++ u64 scsi_cmnd;
++ u64 scsi_serial;
++#define ZFCP_DBF_SCSI_OPCODE 16
++ u8 scsi_opcode[ZFCP_DBF_SCSI_OPCODE];
++ u8 scsi_retries;
++ u8 scsi_allowed;
++ u64 fsf_reqid;
++ u32 fsf_seqno;
++ u64 fsf_issued;
++ u64 old_fsf_reqid;
++ u8 rsp_validity;
++ u8 rsp_scsi_status;
++ u32 rsp_resid;
++ u8 rsp_code;
++#define ZFCP_DBF_SCSI_FCP_SNS_INFO 16
++#define ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO 256
++ u32 sns_info_len;
++ u8 sns_info[ZFCP_DBF_SCSI_FCP_SNS_INFO];
++} __attribute__ ((packed));
++
++#endif /* ZFCP_DBF_H */
+diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
+index 9e9f6c1..bda8c77 100644
+--- a/drivers/s390/scsi/zfcp_def.h
++++ b/drivers/s390/scsi/zfcp_def.h
+@@ -47,6 +47,7 @@
+ #include <asm/qdio.h>
+ #include <asm/debug.h>
+ #include <asm/ebcdic.h>
++#include "zfcp_dbf.h"
+ #include "zfcp_fsf.h"
+
+
+@@ -262,167 +263,6 @@ struct fcp_logo {
+ } __attribute__((packed));
+
+ /*
+- * DBF stuff
+- */
+-#define ZFCP_DBF_TAG_SIZE 4
+-
+-struct zfcp_dbf_dump {
+- u8 tag[ZFCP_DBF_TAG_SIZE];
+- u32 total_size; /* size of total dump data */
+- u32 offset; /* how much data has being already dumped */
+- u32 size; /* how much data comes with this record */
+- u8 data[]; /* dump data */
+-} __attribute__ ((packed));
+-
+-/* FIXME: to be inflated when reworking the erp dbf */
+-struct zfcp_erp_dbf_record {
+- u8 dummy[16];
+-} __attribute__ ((packed));
+-
+-struct zfcp_hba_dbf_record_response {
+- u32 fsf_command;
+- u64 fsf_reqid;
+- u32 fsf_seqno;
+- u64 fsf_issued;
+- u32 fsf_prot_status;
+- u32 fsf_status;
+- u8 fsf_prot_status_qual[FSF_PROT_STATUS_QUAL_SIZE];
+- u8 fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE];
+- u32 fsf_req_status;
+- u8 sbal_first;
+- u8 sbal_curr;
+- u8 sbal_last;
+- u8 pool;
+- u64 erp_action;
+- union {
+- struct {
+- u64 scsi_cmnd;
+- u64 scsi_serial;
+- } send_fcp;
+- struct {
+- u64 wwpn;
+- u32 d_id;
+- u32 port_handle;
+- } port;
+- struct {
+- u64 wwpn;
+- u64 fcp_lun;
+- u32 port_handle;
+- u32 lun_handle;
+- } unit;
+- struct {
+- u32 d_id;
+- u8 ls_code;
+- } send_els;
+- } data;
+-} __attribute__ ((packed));
+-
+-struct zfcp_hba_dbf_record_status {
+- u8 failed;
+- u32 status_type;
+- u32 status_subtype;
+- struct fsf_queue_designator
+- queue_designator;
+- u32 payload_size;
+-#define ZFCP_DBF_UNSOL_PAYLOAD 80
+-#define ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL 32
+-#define ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD 56
+-#define ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT 2 * sizeof(u32)
+- u8 payload[ZFCP_DBF_UNSOL_PAYLOAD];
+-} __attribute__ ((packed));
+-
+-struct zfcp_hba_dbf_record_qdio {
+- u32 status;
+- u32 qdio_error;
+- u32 siga_error;
+- u8 sbal_index;
+- u8 sbal_count;
+-} __attribute__ ((packed));
+-
+-struct zfcp_hba_dbf_record {
+- u8 tag[ZFCP_DBF_TAG_SIZE];
+- u8 tag2[ZFCP_DBF_TAG_SIZE];
+- union {
+- struct zfcp_hba_dbf_record_response response;
+- struct zfcp_hba_dbf_record_status status;
+- struct zfcp_hba_dbf_record_qdio qdio;
+- } type;
+-} __attribute__ ((packed));
+-
+-struct zfcp_san_dbf_record_ct {
+- union {
+- struct {
+- u16 cmd_req_code;
+- u8 revision;
+- u8 gs_type;
+- u8 gs_subtype;
+- u8 options;
+- u16 max_res_size;
+- } request;
+- struct {
+- u16 cmd_rsp_code;
+- u8 revision;
+- u8 reason_code;
+- u8 reason_code_expl;
+- u8 vendor_unique;
+- } response;
+- } type;
+- u32 payload_size;
+-#define ZFCP_DBF_CT_PAYLOAD 24
+- u8 payload[ZFCP_DBF_CT_PAYLOAD];
+-} __attribute__ ((packed));
+-
+-struct zfcp_san_dbf_record_els {
+- u8 ls_code;
+- u32 payload_size;
+-#define ZFCP_DBF_ELS_PAYLOAD 32
+-#define ZFCP_DBF_ELS_MAX_PAYLOAD 1024
+- u8 payload[ZFCP_DBF_ELS_PAYLOAD];
+-} __attribute__ ((packed));
+-
+-struct zfcp_san_dbf_record {
+- u8 tag[ZFCP_DBF_TAG_SIZE];
+- u64 fsf_reqid;
+- u32 fsf_seqno;
+- u32 s_id;
+- u32 d_id;
+- union {
+- struct zfcp_san_dbf_record_ct ct;
+- struct zfcp_san_dbf_record_els els;
+- } type;
+-} __attribute__ ((packed));
+-
+-struct zfcp_scsi_dbf_record {
+- u8 tag[ZFCP_DBF_TAG_SIZE];
+- u8 tag2[ZFCP_DBF_TAG_SIZE];
+- u32 scsi_id;
+- u32 scsi_lun;
+- u32 scsi_result;
+- u64 scsi_cmnd;
+- u64 scsi_serial;
+-#define ZFCP_DBF_SCSI_OPCODE 16
+- u8 scsi_opcode[ZFCP_DBF_SCSI_OPCODE];
+- u8 scsi_retries;
+- u8 scsi_allowed;
+- u64 fsf_reqid;
+- u32 fsf_seqno;
+- u64 fsf_issued;
+- union {
+- u64 old_fsf_reqid;
+- struct {
+- u8 rsp_validity;
+- u8 rsp_scsi_status;
+- u32 rsp_resid;
+- u8 rsp_code;
+-#define ZFCP_DBF_SCSI_FCP_SNS_INFO 16
+-#define ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO 256
+- u32 sns_info_len;
+- u8 sns_info[ZFCP_DBF_SCSI_FCP_SNS_INFO];
+- } fcp;
+- } type;
+-} __attribute__ ((packed));
+-
+-/*
+ * FC-FS stuff
+ */
+ #define R_A_TOV 10 /* seconds */
+@@ -539,7 +379,7 @@ struct zfcp_rc_entry {
+
+ /* logging routine for zfcp */
+ #define _ZFCP_LOG(fmt, args...) \
+- printk(KERN_ERR ZFCP_NAME": %s(%d): " fmt, __FUNCTION__, \
++ printk(KERN_ERR ZFCP_NAME": %s(%d): " fmt, __func__, \
+ __LINE__ , ##args)
+
+ #define ZFCP_LOG(level, fmt, args...) \
+@@ -634,7 +474,6 @@ do { \
+ ZFCP_STATUS_PORT_NO_SCSI_ID)
+
+ /* logical unit status */
+-#define ZFCP_STATUS_UNIT_NOTSUPPUNITRESET 0x00000001
+ #define ZFCP_STATUS_UNIT_TEMPORARY 0x00000002
+ #define ZFCP_STATUS_UNIT_SHARED 0x00000004
+ #define ZFCP_STATUS_UNIT_READONLY 0x00000008
+@@ -917,15 +756,15 @@ struct zfcp_adapter {
+ u32 erp_low_mem_count; /* nr of erp actions waiting
+ for memory */
+ struct zfcp_port *nameserver_port; /* adapter's nameserver */
+- debug_info_t *erp_dbf;
++ debug_info_t *rec_dbf;
+ debug_info_t *hba_dbf;
+ debug_info_t *san_dbf; /* debug feature areas */
+ debug_info_t *scsi_dbf;
+- spinlock_t erp_dbf_lock;
++ spinlock_t rec_dbf_lock;
+ spinlock_t hba_dbf_lock;
+ spinlock_t san_dbf_lock;
+ spinlock_t scsi_dbf_lock;
+- struct zfcp_erp_dbf_record erp_dbf_buf;
++ struct zfcp_rec_dbf_record rec_dbf_buf;
+ struct zfcp_hba_dbf_record hba_dbf_buf;
+ struct zfcp_san_dbf_record san_dbf_buf;
+ struct zfcp_scsi_dbf_record scsi_dbf_buf;
+diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
+index 2dc8110..8054846 100644
+--- a/drivers/s390/scsi/zfcp_erp.c
++++ b/drivers/s390/scsi/zfcp_erp.c
+@@ -26,13 +26,17 @@
+ static int zfcp_erp_adisc(struct zfcp_port *);
+ static void zfcp_erp_adisc_handler(unsigned long);
+
+-static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int);
+-static int zfcp_erp_port_forced_reopen_internal(struct zfcp_port *, int);
+-static int zfcp_erp_port_reopen_internal(struct zfcp_port *, int);
+-static int zfcp_erp_unit_reopen_internal(struct zfcp_unit *, int);
+-
+-static int zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *, int);
+-static int zfcp_erp_unit_reopen_all_internal(struct zfcp_port *, int);
++static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int, u8,
++ void *);
++static int zfcp_erp_port_forced_reopen_internal(struct zfcp_port *, int, u8,
++ void *);
++static int zfcp_erp_port_reopen_internal(struct zfcp_port *, int, u8, void *);
++static int zfcp_erp_unit_reopen_internal(struct zfcp_unit *, int, u8, void *);
++
++static int zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *, int, u8,
++ void *);
++static int zfcp_erp_unit_reopen_all_internal(struct zfcp_port *, int, u8,
++ void *);
+
+ static void zfcp_erp_adapter_block(struct zfcp_adapter *, int);
+ static void zfcp_erp_adapter_unblock(struct zfcp_adapter *);
+@@ -97,7 +101,8 @@ static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *);
+ static void zfcp_erp_action_dismiss(struct zfcp_erp_action *);
+
+ static int zfcp_erp_action_enqueue(int, struct zfcp_adapter *,
+- struct zfcp_port *, struct zfcp_unit *);
++ struct zfcp_port *, struct zfcp_unit *,
++ u8 id, void *ref);
+ static int zfcp_erp_action_dequeue(struct zfcp_erp_action *);
+ static void zfcp_erp_action_cleanup(int, struct zfcp_adapter *,
+ struct zfcp_port *, struct zfcp_unit *,
+@@ -128,11 +133,9 @@ static void zfcp_close_qdio(struct zfcp_adapter *adapter)
+ atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
+ write_unlock_irq(&req_queue->queue_lock);
+
+- debug_text_event(adapter->erp_dbf, 3, "qdio_down2a");
+ while (qdio_shutdown(adapter->ccw_device,
+ QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS)
+ ssleep(1);
+- debug_text_event(adapter->erp_dbf, 3, "qdio_down2b");
+
+ /* cleanup used outbound sbals */
+ count = atomic_read(&req_queue->free_count);
+@@ -163,7 +166,7 @@ static void zfcp_close_fsf(struct zfcp_adapter *adapter)
+ /* reset FSF request sequence number */
+ adapter->fsf_req_seq_no = 0;
+ /* all ports and units are closed */
+- zfcp_erp_modify_adapter_status(adapter,
++ zfcp_erp_modify_adapter_status(adapter, 24, NULL,
+ ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
+ }
+
+@@ -179,7 +182,8 @@ static void zfcp_close_fsf(struct zfcp_adapter *adapter)
+ static void zfcp_fsf_request_timeout_handler(unsigned long data)
+ {
+ struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
+- zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
++ zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 62,
++ NULL);
+ }
+
+ void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, unsigned long timeout)
+@@ -200,12 +204,11 @@ void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, unsigned long timeout)
+ * returns: 0 - initiated action successfully
+ * <0 - failed to initiate action
+ */
+-static int
+-zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter, int clear_mask)
++static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter,
++ int clear_mask, u8 id, void *ref)
+ {
+ int retval;
+
+- debug_text_event(adapter->erp_dbf, 5, "a_ro");
+ ZFCP_LOG_DEBUG("reopen adapter %s\n",
+ zfcp_get_busid_by_adapter(adapter));
+
+@@ -214,14 +217,13 @@ zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter, int clear_mask)
+ if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &adapter->status)) {
+ ZFCP_LOG_DEBUG("skipped reopen of failed adapter %s\n",
+ zfcp_get_busid_by_adapter(adapter));
+- debug_text_event(adapter->erp_dbf, 5, "a_ro_f");
+ /* ensure propagation of failed status to new devices */
+- zfcp_erp_adapter_failed(adapter);
++ zfcp_erp_adapter_failed(adapter, 13, NULL);
+ retval = -EIO;
+ goto out;
+ }
+ retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER,
+- adapter, NULL, NULL);
++ adapter, NULL, NULL, id, ref);
+
+ out:
+ return retval;
+@@ -236,56 +238,56 @@ zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter, int clear_mask)
+ * returns: 0 - initiated action successfully
+ * <0 - failed to initiate action
+ */
+-int
+-zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear_mask)
++int zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear_mask,
++ u8 id, void *ref)
+ {
+ int retval;
+ unsigned long flags;
+
+ read_lock_irqsave(&zfcp_data.config_lock, flags);
+ write_lock(&adapter->erp_lock);
+- retval = zfcp_erp_adapter_reopen_internal(adapter, clear_mask);
++ retval = zfcp_erp_adapter_reopen_internal(adapter, clear_mask, id, ref);
+ write_unlock(&adapter->erp_lock);
+ read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+
+ return retval;
+ }
+
+-int
+-zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear_mask)
++int zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear_mask,
++ u8 id, void *ref)
+ {
+ int retval;
+
+ retval = zfcp_erp_adapter_reopen(adapter,
+ ZFCP_STATUS_COMMON_RUNNING |
+ ZFCP_STATUS_COMMON_ERP_FAILED |
+- clear_mask);
++ clear_mask, id, ref);
+
+ return retval;
+ }
+
+-int
+-zfcp_erp_port_shutdown(struct zfcp_port *port, int clear_mask)
++int zfcp_erp_port_shutdown(struct zfcp_port *port, int clear_mask, u8 id,
++ void *ref)
+ {
+ int retval;
+
+ retval = zfcp_erp_port_reopen(port,
+ ZFCP_STATUS_COMMON_RUNNING |
+ ZFCP_STATUS_COMMON_ERP_FAILED |
+- clear_mask);
++ clear_mask, id, ref);
+
+ return retval;
+ }
+
+-int
+-zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask)
++int zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask, u8 id,
++ void *ref)
+ {
+ int retval;
+
+ retval = zfcp_erp_unit_reopen(unit,
+ ZFCP_STATUS_COMMON_RUNNING |
+ ZFCP_STATUS_COMMON_ERP_FAILED |
+- clear_mask);
++ clear_mask, id, ref);
+
+ return retval;
+ }
+@@ -399,8 +401,7 @@ zfcp_erp_adisc_handler(unsigned long data)
+ "force physical port reopen "
+ "(adapter %s, port d_id=0x%06x)\n",
+ zfcp_get_busid_by_adapter(adapter), d_id);
+- debug_text_event(adapter->erp_dbf, 3, "forcreop");
+- if (zfcp_erp_port_forced_reopen(port, 0))
++ if (zfcp_erp_port_forced_reopen(port, 0, 63, NULL))
+ ZFCP_LOG_NORMAL("failed reopen of port "
+ "(adapter %s, wwpn=0x%016Lx)\n",
+ zfcp_get_busid_by_port(port),
+@@ -427,7 +428,7 @@ zfcp_erp_adisc_handler(unsigned long data)
+ "adisc_resp_wwpn=0x%016Lx)\n",
+ zfcp_get_busid_by_port(port),
+ port->wwpn, (wwn_t) adisc->wwpn);
+- if (zfcp_erp_port_reopen(port, 0))
++ if (zfcp_erp_port_reopen(port, 0, 64, NULL))
+ ZFCP_LOG_NORMAL("failed reopen of port "
+ "(adapter %s, wwpn=0x%016Lx)\n",
+ zfcp_get_busid_by_port(port),
+@@ -461,7 +462,7 @@ zfcp_test_link(struct zfcp_port *port)
+ ZFCP_LOG_NORMAL("reopen needed for port 0x%016Lx "
+ "on adapter %s\n ", port->wwpn,
+ zfcp_get_busid_by_port(port));
+- retval = zfcp_erp_port_forced_reopen(port, 0);
++ retval = zfcp_erp_port_forced_reopen(port, 0, 65, NULL);
+ if (retval != 0) {
+ ZFCP_LOG_NORMAL("reopen of remote port 0x%016Lx "
+ "on adapter %s failed\n", port->wwpn,
+@@ -484,14 +485,11 @@ zfcp_test_link(struct zfcp_port *port)
+ * returns: 0 - initiated action successfully
+ * <0 - failed to initiate action
+ */
+-static int
+-zfcp_erp_port_forced_reopen_internal(struct zfcp_port *port, int clear_mask)
++static int zfcp_erp_port_forced_reopen_internal(struct zfcp_port *port,
++ int clear_mask, u8 id,
++ void *ref)
+ {
+ int retval;
+- struct zfcp_adapter *adapter = port->adapter;
+-
+- debug_text_event(adapter->erp_dbf, 5, "pf_ro");
+- debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+
+ ZFCP_LOG_DEBUG("forced reopen of port 0x%016Lx on adapter %s\n",
+ port->wwpn, zfcp_get_busid_by_port(port));
+@@ -502,14 +500,12 @@ zfcp_erp_port_forced_reopen_internal(struct zfcp_port *port, int clear_mask)
+ ZFCP_LOG_DEBUG("skipped forced reopen of failed port 0x%016Lx "
+ "on adapter %s\n", port->wwpn,
+ zfcp_get_busid_by_port(port));
+- debug_text_event(adapter->erp_dbf, 5, "pf_ro_f");
+- debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ retval = -EIO;
+ goto out;
+ }
+
+ retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED,
+- port->adapter, port, NULL);
++ port->adapter, port, NULL, id, ref);
+
+ out:
+ return retval;
+@@ -524,8 +520,8 @@ zfcp_erp_port_forced_reopen_internal(struct zfcp_port *port, int clear_mask)
+ * returns: 0 - initiated action successfully
+ * <0 - failed to initiate action
+ */
+-int
+-zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear_mask)
++int zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear_mask, u8 id,
++ void *ref)
+ {
+ int retval;
+ unsigned long flags;
+@@ -534,7 +530,8 @@ zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear_mask)
+ adapter = port->adapter;
+ read_lock_irqsave(&zfcp_data.config_lock, flags);
+ write_lock(&adapter->erp_lock);
+- retval = zfcp_erp_port_forced_reopen_internal(port, clear_mask);
++ retval = zfcp_erp_port_forced_reopen_internal(port, clear_mask, id,
++ ref);
+ write_unlock(&adapter->erp_lock);
+ read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+
+@@ -551,14 +548,10 @@ zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear_mask)
+ * returns: 0 - initiated action successfully
+ * <0 - failed to initiate action
+ */
+-static int
+-zfcp_erp_port_reopen_internal(struct zfcp_port *port, int clear_mask)
++static int zfcp_erp_port_reopen_internal(struct zfcp_port *port, int clear_mask,
++ u8 id, void *ref)
+ {
+ int retval;
+- struct zfcp_adapter *adapter = port->adapter;
+-
+- debug_text_event(adapter->erp_dbf, 5, "p_ro");
+- debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+
+ ZFCP_LOG_DEBUG("reopen of port 0x%016Lx on adapter %s\n",
+ port->wwpn, zfcp_get_busid_by_port(port));
+@@ -569,16 +562,14 @@ zfcp_erp_port_reopen_internal(struct zfcp_port *port, int clear_mask)
+ ZFCP_LOG_DEBUG("skipped reopen of failed port 0x%016Lx "
+ "on adapter %s\n", port->wwpn,
+ zfcp_get_busid_by_port(port));
+- debug_text_event(adapter->erp_dbf, 5, "p_ro_f");
+- debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ /* ensure propagation of failed status to new devices */
+- zfcp_erp_port_failed(port);
++ zfcp_erp_port_failed(port, 14, NULL);
+ retval = -EIO;
+ goto out;
+ }
+
+ retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT,
+- port->adapter, port, NULL);
++ port->adapter, port, NULL, id, ref);
+
+ out:
+ return retval;
+@@ -594,8 +585,8 @@ zfcp_erp_port_reopen_internal(struct zfcp_port *port, int clear_mask)
+ * correct locking. An error recovery task is initiated to do the reopen.
+ * To wait for the completion of the reopen zfcp_erp_wait should be used.
+ */
+-int
+-zfcp_erp_port_reopen(struct zfcp_port *port, int clear_mask)
++int zfcp_erp_port_reopen(struct zfcp_port *port, int clear_mask, u8 id,
++ void *ref)
+ {
+ int retval;
+ unsigned long flags;
+@@ -603,7 +594,7 @@ zfcp_erp_port_reopen(struct zfcp_port *port, int clear_mask)
+
+ read_lock_irqsave(&zfcp_data.config_lock, flags);
+ write_lock(&adapter->erp_lock);
+- retval = zfcp_erp_port_reopen_internal(port, clear_mask);
++ retval = zfcp_erp_port_reopen_internal(port, clear_mask, id, ref);
+ write_unlock(&adapter->erp_lock);
+ read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+
+@@ -620,14 +611,12 @@ zfcp_erp_port_reopen(struct zfcp_port *port, int clear_mask)
+ * returns: 0 - initiated action successfully
+ * <0 - failed to initiate action
+ */
+-static int
+-zfcp_erp_unit_reopen_internal(struct zfcp_unit *unit, int clear_mask)
++static int zfcp_erp_unit_reopen_internal(struct zfcp_unit *unit, int clear_mask,
++ u8 id, void *ref)
+ {
+ int retval;
+ struct zfcp_adapter *adapter = unit->port->adapter;
+
+- debug_text_event(adapter->erp_dbf, 5, "u_ro");
+- debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, sizeof (fcp_lun_t));
+ ZFCP_LOG_DEBUG("reopen of unit 0x%016Lx on port 0x%016Lx "
+ "on adapter %s\n", unit->fcp_lun,
+ unit->port->wwpn, zfcp_get_busid_by_unit(unit));
+@@ -639,15 +628,12 @@ zfcp_erp_unit_reopen_internal(struct zfcp_unit *unit, int clear_mask)
+ "on port 0x%016Lx on adapter %s\n",
+ unit->fcp_lun, unit->port->wwpn,
+ zfcp_get_busid_by_unit(unit));
+- debug_text_event(adapter->erp_dbf, 5, "u_ro_f");
+- debug_event(adapter->erp_dbf, 5, &unit->fcp_lun,
+- sizeof (fcp_lun_t));
+ retval = -EIO;
+ goto out;
+ }
+
+ retval = zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_UNIT,
+- unit->port->adapter, unit->port, unit);
++ adapter, unit->port, unit, id, ref);
+ out:
+ return retval;
+ }
+@@ -662,8 +648,8 @@ zfcp_erp_unit_reopen_internal(struct zfcp_unit *unit, int clear_mask)
+ * locking. An error recovery task is initiated to do the reopen.
+ * To wait for the completion of the reopen zfcp_erp_wait should be used.
+ */
+-int
+-zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear_mask)
++int zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear_mask, u8 id,
++ void *ref)
+ {
+ int retval;
+ unsigned long flags;
+@@ -675,7 +661,7 @@ zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear_mask)
+
+ read_lock_irqsave(&zfcp_data.config_lock, flags);
+ write_lock(&adapter->erp_lock);
+- retval = zfcp_erp_unit_reopen_internal(unit, clear_mask);
++ retval = zfcp_erp_unit_reopen_internal(unit, clear_mask, id, ref);
+ write_unlock(&adapter->erp_lock);
+ read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+
+@@ -687,19 +673,43 @@ zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear_mask)
+ */
+ static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int clear_mask)
+ {
+- debug_text_event(adapter->erp_dbf, 6, "a_bl");
+- zfcp_erp_modify_adapter_status(adapter,
++ zfcp_erp_modify_adapter_status(adapter, 15, NULL,
+ ZFCP_STATUS_COMMON_UNBLOCKED |
+ clear_mask, ZFCP_CLEAR);
+ }
+
++/* FIXME: isn't really atomic */
++/*
++ * returns the mask which has not been set so far, i.e.
++ * 0 if no bit has been changed, !0 if some bit has been changed
++ */
++static int atomic_test_and_set_mask(unsigned long mask, atomic_t *v)
++{
++ int changed_bits = (atomic_read(v) /*XOR*/^ mask) & mask;
++ atomic_set_mask(mask, v);
++ return changed_bits;
++}
++
++/* FIXME: isn't really atomic */
++/*
++ * returns the mask which has not been cleared so far, i.e.
++ * 0 if no bit has been changed, !0 if some bit has been changed
++ */
++static int atomic_test_and_clear_mask(unsigned long mask, atomic_t *v)
++{
++ int changed_bits = atomic_read(v) & mask;
++ atomic_clear_mask(mask, v);
++ return changed_bits;
++}
++
+ /**
+ * zfcp_erp_adapter_unblock - mark adapter as unblocked, allow scsi requests
+ */
+ static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter)
+ {
+- debug_text_event(adapter->erp_dbf, 6, "a_ubl");
+- atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status);
++ if (atomic_test_and_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED,
++ &adapter->status))
++ zfcp_rec_dbf_event_adapter(16, NULL, adapter);
+ }
+
+ /*
+@@ -714,11 +724,7 @@ static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter)
+ static void
+ zfcp_erp_port_block(struct zfcp_port *port, int clear_mask)
+ {
+- struct zfcp_adapter *adapter = port->adapter;
+-
+- debug_text_event(adapter->erp_dbf, 6, "p_bl");
+- debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t));
+- zfcp_erp_modify_port_status(port,
++ zfcp_erp_modify_port_status(port, 17, NULL,
+ ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask,
+ ZFCP_CLEAR);
+ }
+@@ -733,11 +739,9 @@ zfcp_erp_port_block(struct zfcp_port *port, int clear_mask)
+ static void
+ zfcp_erp_port_unblock(struct zfcp_port *port)
+ {
+- struct zfcp_adapter *adapter = port->adapter;
+-
+- debug_text_event(adapter->erp_dbf, 6, "p_ubl");
+- debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t));
+- atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status);
++ if (atomic_test_and_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED,
++ &port->status))
++ zfcp_rec_dbf_event_port(18, NULL, port);
+ }
+
+ /*
+@@ -752,11 +756,7 @@ zfcp_erp_port_unblock(struct zfcp_port *port)
+ static void
+ zfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask)
+ {
+- struct zfcp_adapter *adapter = unit->port->adapter;
+-
+- debug_text_event(adapter->erp_dbf, 6, "u_bl");
+- debug_event(adapter->erp_dbf, 6, &unit->fcp_lun, sizeof (fcp_lun_t));
+- zfcp_erp_modify_unit_status(unit,
++ zfcp_erp_modify_unit_status(unit, 19, NULL,
+ ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask,
+ ZFCP_CLEAR);
+ }
+@@ -771,11 +771,9 @@ zfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask)
+ static void
+ zfcp_erp_unit_unblock(struct zfcp_unit *unit)
+ {
+- struct zfcp_adapter *adapter = unit->port->adapter;
+-
+- debug_text_event(adapter->erp_dbf, 6, "u_ubl");
+- debug_event(adapter->erp_dbf, 6, &unit->fcp_lun, sizeof (fcp_lun_t));
+- atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status);
++ if (atomic_test_and_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED,
++ &unit->status))
++ zfcp_rec_dbf_event_unit(20, NULL, unit);
+ }
+
+ static void
+@@ -783,11 +781,9 @@ zfcp_erp_action_ready(struct zfcp_erp_action *erp_action)
+ {
+ struct zfcp_adapter *adapter = erp_action->adapter;
+
+- debug_text_event(adapter->erp_dbf, 4, "a_ar");
+- debug_event(adapter->erp_dbf, 4, &erp_action->action, sizeof (int));
+-
+ zfcp_erp_action_to_ready(erp_action);
+ up(&adapter->erp_ready_sem);
++ zfcp_rec_dbf_event_thread(2, adapter, 0);
+ }
+
+ /*
+@@ -849,18 +845,15 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
+ if (zfcp_reqlist_find_safe(adapter, erp_action->fsf_req) &&
+ erp_action->fsf_req->erp_action == erp_action) {
+ /* fsf_req still exists */
+- debug_text_event(adapter->erp_dbf, 3, "a_ca_req");
+- debug_event(adapter->erp_dbf, 3, &erp_action->fsf_req,
+- sizeof (unsigned long));
+ /* dismiss fsf_req of timed out/dismissed erp_action */
+ if (erp_action->status & (ZFCP_STATUS_ERP_DISMISSED |
+ ZFCP_STATUS_ERP_TIMEDOUT)) {
+- debug_text_event(adapter->erp_dbf, 3,
+- "a_ca_disreq");
+ erp_action->fsf_req->status |=
+ ZFCP_STATUS_FSFREQ_DISMISSED;
++ zfcp_rec_dbf_event_action(142, erp_action);
+ }
+ if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
++ zfcp_rec_dbf_event_action(143, erp_action);
+ ZFCP_LOG_NORMAL("error: erp step timed out "
+ "(action=%d, fsf_req=%p)\n ",
+ erp_action->action,
+@@ -879,7 +872,6 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
+ erp_action->fsf_req = NULL;
+ }
+ } else {
+- debug_text_event(adapter->erp_dbf, 3, "a_ca_gonereq");
+ /*
+ * even if this fsf_req has gone, forget about
+ * association between erp_action and fsf_req
+@@ -887,8 +879,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
+ erp_action->fsf_req = NULL;
+ }
+ spin_unlock(&adapter->req_list_lock);
+- } else
+- debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq");
++ }
+ }
+
+ /**
+@@ -900,19 +891,11 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
+ static void zfcp_erp_async_handler_nolock(struct zfcp_erp_action *erp_action,
+ unsigned long set_mask)
+ {
+- struct zfcp_adapter *adapter = erp_action->adapter;
+-
+ if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) {
+- debug_text_event(adapter->erp_dbf, 2, "a_asyh_ex");
+- debug_event(adapter->erp_dbf, 2, &erp_action->action,
+- sizeof (int));
+ erp_action->status |= set_mask;
+ zfcp_erp_action_ready(erp_action);
+ } else {
+ /* action is ready or gone - nothing to do */
+- debug_text_event(adapter->erp_dbf, 3, "a_asyh_gone");
+- debug_event(adapter->erp_dbf, 3, &erp_action->action,
+- sizeof (int));
+ }
+ }
+
+@@ -939,10 +922,6 @@ static void
+ zfcp_erp_memwait_handler(unsigned long data)
+ {
+ struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data;
+- struct zfcp_adapter *adapter = erp_action->adapter;
+-
+- debug_text_event(adapter->erp_dbf, 2, "a_mwh");
+- debug_event(adapter->erp_dbf, 2, &erp_action->action, sizeof (int));
+
+ zfcp_erp_async_handler(erp_action, 0);
+ }
+@@ -955,10 +934,6 @@ zfcp_erp_memwait_handler(unsigned long data)
+ static void zfcp_erp_timeout_handler(unsigned long data)
+ {
+ struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data;
+- struct zfcp_adapter *adapter = erp_action->adapter;
+-
+- debug_text_event(adapter->erp_dbf, 2, "a_th");
+- debug_event(adapter->erp_dbf, 2, &erp_action->action, sizeof (int));
+
+ zfcp_erp_async_handler(erp_action, ZFCP_STATUS_ERP_TIMEDOUT);
+ }
+@@ -973,11 +948,6 @@ static void zfcp_erp_timeout_handler(unsigned long data)
+ */
+ static void zfcp_erp_action_dismiss(struct zfcp_erp_action *erp_action)
+ {
+- struct zfcp_adapter *adapter = erp_action->adapter;
+-
+- debug_text_event(adapter->erp_dbf, 2, "a_adis");
+- debug_event(adapter->erp_dbf, 2, &erp_action->action, sizeof (int));
+-
+ erp_action->status |= ZFCP_STATUS_ERP_DISMISSED;
+ if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING)
+ zfcp_erp_action_ready(erp_action);
+@@ -995,12 +965,10 @@ zfcp_erp_thread_setup(struct zfcp_adapter *adapter)
+ ZFCP_LOG_NORMAL("error: creation of erp thread failed for "
+ "adapter %s\n",
+ zfcp_get_busid_by_adapter(adapter));
+- debug_text_event(adapter->erp_dbf, 5, "a_thset_fail");
+ } else {
+ wait_event(adapter->erp_thread_wqh,
+ atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP,
+ &adapter->status));
+- debug_text_event(adapter->erp_dbf, 5, "a_thset_ok");
+ }
+
+ return (retval < 0);
+@@ -1027,6 +995,7 @@ zfcp_erp_thread_kill(struct zfcp_adapter *adapter)
+
+ atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, &adapter->status);
+ up(&adapter->erp_ready_sem);
++ zfcp_rec_dbf_event_thread(2, adapter, 1);
+
+ wait_event(adapter->erp_thread_wqh,
+ !atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP,
+@@ -1035,8 +1004,6 @@ zfcp_erp_thread_kill(struct zfcp_adapter *adapter)
+ atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL,
+ &adapter->status);
+
+- debug_text_event(adapter->erp_dbf, 5, "a_thki_ok");
+-
+ return retval;
+ }
+
+@@ -1059,7 +1026,6 @@ zfcp_erp_thread(void *data)
+ /* Block all signals */
+ siginitsetinv(¤t->blocked, 0);
+ atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
+- debug_text_event(adapter->erp_dbf, 5, "a_th_run");
+ wake_up(&adapter->erp_thread_wqh);
+
+ while (!atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL,
+@@ -1084,12 +1050,12 @@ zfcp_erp_thread(void *data)
+ * no action in 'ready' queue to be processed and
+ * thread is not to be killed
+ */
++ zfcp_rec_dbf_event_thread(4, adapter, 1);
+ down_interruptible(&adapter->erp_ready_sem);
+- debug_text_event(adapter->erp_dbf, 5, "a_th_woken");
++ zfcp_rec_dbf_event_thread(5, adapter, 1);
+ }
+
+ atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
+- debug_text_event(adapter->erp_dbf, 5, "a_th_stop");
+ wake_up(&adapter->erp_thread_wqh);
+
+ return 0;
+@@ -1125,7 +1091,6 @@ zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
+ /* dequeue dismissed action and leave, if required */
+ retval = zfcp_erp_strategy_check_action(erp_action, retval);
+ if (retval == ZFCP_ERP_DISMISSED) {
+- debug_text_event(adapter->erp_dbf, 4, "a_st_dis1");
+ goto unlock;
+ }
+
+@@ -1176,20 +1141,17 @@ zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
+ element was timed out.
+ */
+ if (adapter->erp_total_count == adapter->erp_low_mem_count) {
+- debug_text_event(adapter->erp_dbf, 3, "a_st_lowmem");
+ ZFCP_LOG_NORMAL("error: no mempool elements available, "
+ "restarting I/O on adapter %s "
+ "to free mempool\n",
+ zfcp_get_busid_by_adapter(adapter));
+- zfcp_erp_adapter_reopen_internal(adapter, 0);
++ zfcp_erp_adapter_reopen_internal(adapter, 0, 66, NULL);
+ } else {
+- debug_text_event(adapter->erp_dbf, 2, "a_st_memw");
+ retval = zfcp_erp_strategy_memwait(erp_action);
+ }
+ goto unlock;
+ case ZFCP_ERP_CONTINUES:
+ /* leave since this action runs asynchronously */
+- debug_text_event(adapter->erp_dbf, 6, "a_st_cont");
+ if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) {
+ --adapter->erp_low_mem_count;
+ erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM;
+@@ -1218,7 +1180,6 @@ zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
+ * action is repeated in order to process state change
+ */
+ if (retval == ZFCP_ERP_EXIT) {
+- debug_text_event(adapter->erp_dbf, 2, "a_st_exit");
+ goto unlock;
+ }
+
+@@ -1244,8 +1205,6 @@ zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
+ if (retval != ZFCP_ERP_DISMISSED)
+ zfcp_erp_strategy_check_queues(adapter);
+
+- debug_text_event(adapter->erp_dbf, 6, "a_st_done");
+-
+ return retval;
+ }
+
+@@ -1260,17 +1219,12 @@ zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
+ static int
+ zfcp_erp_strategy_check_action(struct zfcp_erp_action *erp_action, int retval)
+ {
+- struct zfcp_adapter *adapter = erp_action->adapter;
+-
+ zfcp_erp_strategy_check_fsfreq(erp_action);
+
+- debug_event(adapter->erp_dbf, 5, &erp_action->action, sizeof (int));
+ if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) {
+- debug_text_event(adapter->erp_dbf, 3, "a_stcd_dis");
+ zfcp_erp_action_dequeue(erp_action);
+ retval = ZFCP_ERP_DISMISSED;
+- } else
+- debug_text_event(adapter->erp_dbf, 5, "a_stcd_nodis");
++ }
+
+ return retval;
+ }
+@@ -1279,7 +1233,6 @@ static int
+ zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action)
+ {
+ int retval = ZFCP_ERP_FAILED;
+- struct zfcp_adapter *adapter = erp_action->adapter;
+
+ /*
+ * try to execute/continue action as far as possible,
+@@ -1309,9 +1262,6 @@ zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action)
+ break;
+
+ default:
+- debug_text_exception(adapter->erp_dbf, 1, "a_stda_bug");
+- debug_event(adapter->erp_dbf, 1, &erp_action->action,
+- sizeof (int));
+ ZFCP_LOG_NORMAL("bug: unknown erp action requested on "
+ "adapter %s (action=%d)\n",
+ zfcp_get_busid_by_adapter(erp_action->adapter),
+@@ -1333,10 +1283,7 @@ static int
+ zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action)
+ {
+ int retval = ZFCP_ERP_CONTINUES;
+- struct zfcp_adapter *adapter = erp_action->adapter;
+
+- debug_text_event(adapter->erp_dbf, 6, "a_mwinit");
+- debug_event(adapter->erp_dbf, 6, &erp_action->action, sizeof (int));
+ init_timer(&erp_action->timer);
+ erp_action->timer.function = zfcp_erp_memwait_handler;
+ erp_action->timer.data = (unsigned long) erp_action;
+@@ -1353,13 +1300,12 @@ zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action)
+ *
+ */
+ void
+-zfcp_erp_adapter_failed(struct zfcp_adapter *adapter)
++zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, u8 id, void *ref)
+ {
+- zfcp_erp_modify_adapter_status(adapter,
++ zfcp_erp_modify_adapter_status(adapter, id, ref,
+ ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
+ ZFCP_LOG_NORMAL("adapter erp failed on adapter %s\n",
+ zfcp_get_busid_by_adapter(adapter));
+- debug_text_event(adapter->erp_dbf, 2, "a_afail");
+ }
+
+ /*
+@@ -1369,9 +1315,9 @@ zfcp_erp_adapter_failed(struct zfcp_adapter *adapter)
+ *
+ */
+ void
+-zfcp_erp_port_failed(struct zfcp_port *port)
++zfcp_erp_port_failed(struct zfcp_port *port, u8 id, void *ref)
+ {
+- zfcp_erp_modify_port_status(port,
++ zfcp_erp_modify_port_status(port, id, ref,
+ ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
+
+ if (atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status))
+@@ -1381,9 +1327,6 @@ zfcp_erp_port_failed(struct zfcp_port *port)
+ else
+ ZFCP_LOG_NORMAL("port erp failed (adapter %s, wwpn=0x%016Lx)\n",
+ zfcp_get_busid_by_port(port), port->wwpn);
+-
+- debug_text_event(port->adapter->erp_dbf, 2, "p_pfail");
+- debug_event(port->adapter->erp_dbf, 2, &port->wwpn, sizeof (wwn_t));
+ }
+
+ /*
+@@ -1393,17 +1336,14 @@ zfcp_erp_port_failed(struct zfcp_port *port)
+ *
+ */
+ void
+-zfcp_erp_unit_failed(struct zfcp_unit *unit)
++zfcp_erp_unit_failed(struct zfcp_unit *unit, u8 id, void *ref)
+ {
+- zfcp_erp_modify_unit_status(unit,
++ zfcp_erp_modify_unit_status(unit, id, ref,
+ ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
+
+ ZFCP_LOG_NORMAL("unit erp failed on unit 0x%016Lx on port 0x%016Lx "
+ " on adapter %s\n", unit->fcp_lun,
+ unit->port->wwpn, zfcp_get_busid_by_unit(unit));
+- debug_text_event(unit->port->adapter->erp_dbf, 2, "u_ufail");
+- debug_event(unit->port->adapter->erp_dbf, 2,
+- &unit->fcp_lun, sizeof (fcp_lun_t));
+ }
+
+ /*
+@@ -1427,10 +1367,6 @@ zfcp_erp_strategy_check_target(struct zfcp_erp_action *erp_action, int result)
+ struct zfcp_port *port = erp_action->port;
+ struct zfcp_unit *unit = erp_action->unit;
+
+- debug_text_event(adapter->erp_dbf, 5, "a_stct_norm");
+- debug_event(adapter->erp_dbf, 5, &erp_action->action, sizeof (int));
+- debug_event(adapter->erp_dbf, 5, &result, sizeof (int));
+-
+ switch (erp_action->action) {
+
+ case ZFCP_ERP_ACTION_REOPEN_UNIT:
+@@ -1457,15 +1393,14 @@ zfcp_erp_strategy_statechange(int action,
+ struct zfcp_port *port,
+ struct zfcp_unit *unit, int retval)
+ {
+- debug_text_event(adapter->erp_dbf, 3, "a_stsc");
+- debug_event(adapter->erp_dbf, 3, &action, sizeof (int));
+-
+ switch (action) {
+
+ case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
+ if (zfcp_erp_strategy_statechange_detected(&adapter->status,
+ status)) {
+- zfcp_erp_adapter_reopen_internal(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
++ zfcp_erp_adapter_reopen_internal(adapter,
++ ZFCP_STATUS_COMMON_ERP_FAILED,
++ 67, NULL);
+ retval = ZFCP_ERP_EXIT;
+ }
+ break;
+@@ -1474,7 +1409,9 @@ zfcp_erp_strategy_statechange(int action,
+ case ZFCP_ERP_ACTION_REOPEN_PORT:
+ if (zfcp_erp_strategy_statechange_detected(&port->status,
+ status)) {
+- zfcp_erp_port_reopen_internal(port, ZFCP_STATUS_COMMON_ERP_FAILED);
++ zfcp_erp_port_reopen_internal(port,
++ ZFCP_STATUS_COMMON_ERP_FAILED,
++ 68, NULL);
+ retval = ZFCP_ERP_EXIT;
+ }
+ break;
+@@ -1482,7 +1419,9 @@ zfcp_erp_strategy_statechange(int action,
+ case ZFCP_ERP_ACTION_REOPEN_UNIT:
+ if (zfcp_erp_strategy_statechange_detected(&unit->status,
+ status)) {
+- zfcp_erp_unit_reopen_internal(unit, ZFCP_STATUS_COMMON_ERP_FAILED);
++ zfcp_erp_unit_reopen_internal(unit,
++ ZFCP_STATUS_COMMON_ERP_FAILED,
++ 69, NULL);
+ retval = ZFCP_ERP_EXIT;
+ }
+ break;
+@@ -1506,10 +1445,6 @@ zfcp_erp_strategy_statechange_detected(atomic_t * target_status, u32 erp_status)
+ static int
+ zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result)
+ {
+- debug_text_event(unit->port->adapter->erp_dbf, 5, "u_stct");
+- debug_event(unit->port->adapter->erp_dbf, 5, &unit->fcp_lun,
+- sizeof (fcp_lun_t));
+-
+ switch (result) {
+ case ZFCP_ERP_SUCCEEDED :
+ atomic_set(&unit->erp_counter, 0);
+@@ -1518,7 +1453,7 @@ zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result)
+ case ZFCP_ERP_FAILED :
+ atomic_inc(&unit->erp_counter);
+ if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS)
+- zfcp_erp_unit_failed(unit);
++ zfcp_erp_unit_failed(unit, 21, NULL);
+ break;
+ case ZFCP_ERP_EXIT :
+ /* nothing */
+@@ -1536,9 +1471,6 @@ zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result)
+ static int
+ zfcp_erp_strategy_check_port(struct zfcp_port *port, int result)
+ {
+- debug_text_event(port->adapter->erp_dbf, 5, "p_stct");
+- debug_event(port->adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+-
+ switch (result) {
+ case ZFCP_ERP_SUCCEEDED :
+ atomic_set(&port->erp_counter, 0);
+@@ -1547,7 +1479,7 @@ zfcp_erp_strategy_check_port(struct zfcp_port *port, int result)
+ case ZFCP_ERP_FAILED :
+ atomic_inc(&port->erp_counter);
+ if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS)
+- zfcp_erp_port_failed(port);
++ zfcp_erp_port_failed(port, 22, NULL);
+ break;
+ case ZFCP_ERP_EXIT :
+ /* nothing */
+@@ -1565,8 +1497,6 @@ zfcp_erp_strategy_check_port(struct zfcp_port *port, int result)
+ static int
+ zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, int result)
+ {
+- debug_text_event(adapter->erp_dbf, 5, "a_stct");
+-
+ switch (result) {
+ case ZFCP_ERP_SUCCEEDED :
+ atomic_set(&adapter->erp_counter, 0);
+@@ -1575,7 +1505,7 @@ zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, int result)
+ case ZFCP_ERP_FAILED :
+ atomic_inc(&adapter->erp_counter);
+ if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS)
+- zfcp_erp_adapter_failed(adapter);
++ zfcp_erp_adapter_failed(adapter, 23, NULL);
+ break;
+ case ZFCP_ERP_EXIT :
+ /* nothing */
+@@ -1658,37 +1588,34 @@ zfcp_erp_strategy_followup_actions(int action,
+ struct zfcp_port *port,
+ struct zfcp_unit *unit, int status)
+ {
+- debug_text_event(adapter->erp_dbf, 5, "a_stfol");
+- debug_event(adapter->erp_dbf, 5, &action, sizeof (int));
+-
+ /* initiate follow-up actions depending on success of finished action */
+ switch (action) {
+
+ case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
+ if (status == ZFCP_ERP_SUCCEEDED)
+- zfcp_erp_port_reopen_all_internal(adapter, 0);
++ zfcp_erp_port_reopen_all_internal(adapter, 0, 70, NULL);
+ else
+- zfcp_erp_adapter_reopen_internal(adapter, 0);
++ zfcp_erp_adapter_reopen_internal(adapter, 0, 71, NULL);
+ break;
+
+ case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
+ if (status == ZFCP_ERP_SUCCEEDED)
+- zfcp_erp_port_reopen_internal(port, 0);
++ zfcp_erp_port_reopen_internal(port, 0, 72, NULL);
+ else
+- zfcp_erp_adapter_reopen_internal(adapter, 0);
++ zfcp_erp_adapter_reopen_internal(adapter, 0, 73, NULL);
+ break;
+
+ case ZFCP_ERP_ACTION_REOPEN_PORT:
+ if (status == ZFCP_ERP_SUCCEEDED)
+- zfcp_erp_unit_reopen_all_internal(port, 0);
++ zfcp_erp_unit_reopen_all_internal(port, 0, 74, NULL);
+ else
+- zfcp_erp_port_forced_reopen_internal(port, 0);
++ zfcp_erp_port_forced_reopen_internal(port, 0, 75, NULL);
+ break;
+
+ case ZFCP_ERP_ACTION_REOPEN_UNIT:
+ /* Nothing to do if status == ZFCP_ERP_SUCCEEDED */
+ if (status != ZFCP_ERP_SUCCEEDED)
+- zfcp_erp_port_reopen_internal(unit->port, 0);
++ zfcp_erp_port_reopen_internal(unit->port, 0, 76, NULL);
+ break;
+ }
+
+@@ -1704,12 +1631,10 @@ zfcp_erp_strategy_check_queues(struct zfcp_adapter *adapter)
+ read_lock(&adapter->erp_lock);
+ if (list_empty(&adapter->erp_ready_head) &&
+ list_empty(&adapter->erp_running_head)) {
+- debug_text_event(adapter->erp_dbf, 4, "a_cq_wake");
+ atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING,
+ &adapter->status);
+ wake_up(&adapter->erp_done_wqh);
+- } else
+- debug_text_event(adapter->erp_dbf, 5, "a_cq_notempty");
++ }
+ read_unlock(&adapter->erp_lock);
+ read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+
+@@ -1733,29 +1658,27 @@ zfcp_erp_wait(struct zfcp_adapter *adapter)
+ return retval;
+ }
+
+-void
+-zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter,
+- u32 mask, int set_or_clear)
++void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, u8 id,
++ void *ref, u32 mask, int set_or_clear)
+ {
+ struct zfcp_port *port;
+- u32 common_mask = mask & ZFCP_COMMON_FLAGS;
++ u32 changed, common_mask = mask & ZFCP_COMMON_FLAGS;
+
+ if (set_or_clear == ZFCP_SET) {
+- atomic_set_mask(mask, &adapter->status);
+- debug_text_event(adapter->erp_dbf, 3, "a_mod_as_s");
++ changed = atomic_test_and_set_mask(mask, &adapter->status);
+ } else {
+- atomic_clear_mask(mask, &adapter->status);
++ changed = atomic_test_and_clear_mask(mask, &adapter->status);
+ if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
+ atomic_set(&adapter->erp_counter, 0);
+- debug_text_event(adapter->erp_dbf, 3, "a_mod_as_c");
+ }
+- debug_event(adapter->erp_dbf, 3, &mask, sizeof (u32));
++ if (changed)
++ zfcp_rec_dbf_event_adapter(id, ref, adapter);
+
+ /* Deal with all underlying devices, only pass common_mask */
+ if (common_mask)
+ list_for_each_entry(port, &adapter->port_list_head, list)
+- zfcp_erp_modify_port_status(port, common_mask,
+- set_or_clear);
++ zfcp_erp_modify_port_status(port, id, ref, common_mask,
++ set_or_clear);
+ }
+
+ /*
+@@ -1764,29 +1687,27 @@ zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter,
+ * purpose: sets the port and all underlying devices to ERP_FAILED
+ *
+ */
+-void
+-zfcp_erp_modify_port_status(struct zfcp_port *port, u32 mask, int set_or_clear)
++void zfcp_erp_modify_port_status(struct zfcp_port *port, u8 id, void *ref,
++ u32 mask, int set_or_clear)
+ {
+ struct zfcp_unit *unit;
+- u32 common_mask = mask & ZFCP_COMMON_FLAGS;
++ u32 changed, common_mask = mask & ZFCP_COMMON_FLAGS;
+
+ if (set_or_clear == ZFCP_SET) {
+- atomic_set_mask(mask, &port->status);
+- debug_text_event(port->adapter->erp_dbf, 3, "p_mod_ps_s");
++ changed = atomic_test_and_set_mask(mask, &port->status);
+ } else {
+- atomic_clear_mask(mask, &port->status);
++ changed = atomic_test_and_clear_mask(mask, &port->status);
+ if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
+ atomic_set(&port->erp_counter, 0);
+- debug_text_event(port->adapter->erp_dbf, 3, "p_mod_ps_c");
+ }
+- debug_event(port->adapter->erp_dbf, 3, &port->wwpn, sizeof (wwn_t));
+- debug_event(port->adapter->erp_dbf, 3, &mask, sizeof (u32));
++ if (changed)
++ zfcp_rec_dbf_event_port(id, ref, port);
+
+ /* Modify status of all underlying devices, only pass common mask */
+ if (common_mask)
+ list_for_each_entry(unit, &port->unit_list_head, list)
+- zfcp_erp_modify_unit_status(unit, common_mask,
+- set_or_clear);
++ zfcp_erp_modify_unit_status(unit, id, ref, common_mask,
++ set_or_clear);
+ }
+
+ /*
+@@ -1795,22 +1716,21 @@ zfcp_erp_modify_port_status(struct zfcp_port *port, u32 mask, int set_or_clear)
+ * purpose: sets the unit to ERP_FAILED
+ *
+ */
+-void
+-zfcp_erp_modify_unit_status(struct zfcp_unit *unit, u32 mask, int set_or_clear)
++void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, u8 id, void *ref,
++ u32 mask, int set_or_clear)
+ {
++ u32 changed;
++
+ if (set_or_clear == ZFCP_SET) {
+- atomic_set_mask(mask, &unit->status);
+- debug_text_event(unit->port->adapter->erp_dbf, 3, "u_mod_us_s");
++ changed = atomic_test_and_set_mask(mask, &unit->status);
+ } else {
+- atomic_clear_mask(mask, &unit->status);
++ changed = atomic_test_and_clear_mask(mask, &unit->status);
+ if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) {
+ atomic_set(&unit->erp_counter, 0);
+ }
+- debug_text_event(unit->port->adapter->erp_dbf, 3, "u_mod_us_c");
+ }
+- debug_event(unit->port->adapter->erp_dbf, 3, &unit->fcp_lun,
+- sizeof (fcp_lun_t));
+- debug_event(unit->port->adapter->erp_dbf, 3, &mask, sizeof (u32));
++ if (changed)
++ zfcp_rec_dbf_event_unit(id, ref, unit);
+ }
+
+ /*
+@@ -1822,30 +1742,32 @@ zfcp_erp_modify_unit_status(struct zfcp_unit *unit, u32 mask, int set_or_clear)
+ * returns: 0 - initiated action successfully
+ * <0 - failed to initiate action
+ */
+-int
+-zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, int clear_mask)
++int zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, int clear_mask,
++ u8 id, void *ref)
+ {
+ int retval;
+ unsigned long flags;
+
+ read_lock_irqsave(&zfcp_data.config_lock, flags);
+ write_lock(&adapter->erp_lock);
+- retval = zfcp_erp_port_reopen_all_internal(adapter, clear_mask);
++ retval = zfcp_erp_port_reopen_all_internal(adapter, clear_mask, id,
++ ref);
+ write_unlock(&adapter->erp_lock);
+ read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+
+ return retval;
+ }
+
+-static int
+-zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *adapter, int clear_mask)
++static int zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *adapter,
++ int clear_mask, u8 id, void *ref)
+ {
+ int retval = 0;
+ struct zfcp_port *port;
+
+ list_for_each_entry(port, &adapter->port_list_head, list)
+ if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status))
+- zfcp_erp_port_reopen_internal(port, clear_mask);
++ zfcp_erp_port_reopen_internal(port, clear_mask, id,
++ ref);
+
+ return retval;
+ }
+@@ -1857,14 +1779,14 @@ zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *adapter, int clear_mask)
+ *
+ * returns: FIXME
+ */
+-static int
+-zfcp_erp_unit_reopen_all_internal(struct zfcp_port *port, int clear_mask)
++static int zfcp_erp_unit_reopen_all_internal(struct zfcp_port *port,
++ int clear_mask, u8 id, void *ref)
+ {
+ int retval = 0;
+ struct zfcp_unit *unit;
+
+ list_for_each_entry(unit, &port->unit_list_head, list)
+- zfcp_erp_unit_reopen_internal(unit, clear_mask);
++ zfcp_erp_unit_reopen_internal(unit, clear_mask, id, ref);
+
+ return retval;
+ }
+@@ -1892,10 +1814,6 @@ zfcp_erp_adapter_strategy(struct zfcp_erp_action *erp_action)
+ else
+ retval = zfcp_erp_adapter_strategy_open(erp_action);
+
+- debug_text_event(adapter->erp_dbf, 3, "a_ast/ret");
+- debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int));
+- debug_event(adapter->erp_dbf, 3, &retval, sizeof (int));
+-
+ if (retval == ZFCP_ERP_FAILED) {
+ ZFCP_LOG_INFO("Waiting to allow the adapter %s "
+ "to recover itself\n",
+@@ -2021,7 +1939,6 @@ zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action)
+ zfcp_get_busid_by_adapter(adapter));
+ goto failed_qdio_establish;
+ }
+- debug_text_event(adapter->erp_dbf, 3, "qdio_est");
+
+ if (qdio_activate(adapter->ccw_device, 0) != 0) {
+ ZFCP_LOG_INFO("error: activation of QDIO queues failed "
+@@ -2029,7 +1946,6 @@ zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action)
+ zfcp_get_busid_by_adapter(adapter));
+ goto failed_qdio_activate;
+ }
+- debug_text_event(adapter->erp_dbf, 3, "qdio_act");
+
+ /*
+ * put buffers into response queue,
+@@ -2077,11 +1993,9 @@ zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action)
+ /* NOP */
+
+ failed_qdio_activate:
+- debug_text_event(adapter->erp_dbf, 3, "qdio_down1a");
+ while (qdio_shutdown(adapter->ccw_device,
+ QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS)
+ ssleep(1);
+- debug_text_event(adapter->erp_dbf, 3, "qdio_down1b");
+
+ failed_qdio_establish:
+ failed_sanity:
+@@ -2127,14 +2041,12 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
+ write_unlock_irq(&adapter->erp_lock);
+ if (zfcp_fsf_exchange_config_data(erp_action)) {
+ retval = ZFCP_ERP_FAILED;
+- debug_text_event(adapter->erp_dbf, 5, "a_fstx_xf");
+ ZFCP_LOG_INFO("error: initiation of exchange of "
+ "configuration data failed for "
+ "adapter %s\n",
+ zfcp_get_busid_by_adapter(adapter));
+ break;
+ }
+- debug_text_event(adapter->erp_dbf, 6, "a_fstx_xok");
+ ZFCP_LOG_DEBUG("Xchange underway\n");
+
+ /*
+@@ -2150,7 +2062,9 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
+ * _must_ be the one belonging to the 'exchange config
+ * data' request.
+ */
++ zfcp_rec_dbf_event_thread(6, adapter, 1);
+ down(&adapter->erp_ready_sem);
++ zfcp_rec_dbf_event_thread(7, adapter, 1);
+ if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
+ ZFCP_LOG_INFO("error: exchange of configuration data "
+ "for adapter %s timed out\n",
+@@ -2198,16 +2112,15 @@ zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
+
+ ret = zfcp_fsf_exchange_port_data(erp_action);
+ if (ret == -EOPNOTSUPP) {
+- debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp");
+ return ZFCP_ERP_SUCCEEDED;
+ } else if (ret) {
+- debug_text_event(adapter->erp_dbf, 3, "a_xport_failed");
+ return ZFCP_ERP_FAILED;
+ }
+- debug_text_event(adapter->erp_dbf, 6, "a_xport_ok");
+
+ ret = ZFCP_ERP_SUCCEEDED;
++ zfcp_rec_dbf_event_thread(8, adapter, 1);
+ down(&adapter->erp_ready_sem);
++ zfcp_rec_dbf_event_thread(9, adapter, 1);
+ if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
+ ZFCP_LOG_INFO("error: exchange port data timed out (adapter "
+ "%s)\n", zfcp_get_busid_by_adapter(adapter));
+@@ -2261,7 +2174,6 @@ zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
+ {
+ int retval = ZFCP_ERP_FAILED;
+ struct zfcp_port *port = erp_action->port;
+- struct zfcp_adapter *adapter = erp_action->adapter;
+
+ switch (erp_action->step) {
+
+@@ -2298,11 +2210,6 @@ zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
+ break;
+ }
+
+- debug_text_event(adapter->erp_dbf, 3, "p_pfst/ret");
+- debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof (wwn_t));
+- debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int));
+- debug_event(adapter->erp_dbf, 3, &retval, sizeof (int));
+-
+ return retval;
+ }
+
+@@ -2320,7 +2227,6 @@ zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action)
+ {
+ int retval = ZFCP_ERP_FAILED;
+ struct zfcp_port *port = erp_action->port;
+- struct zfcp_adapter *adapter = erp_action->adapter;
+
+ switch (erp_action->step) {
+
+@@ -2353,11 +2259,6 @@ zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action)
+ retval = zfcp_erp_port_strategy_open(erp_action);
+
+ out:
+- debug_text_event(adapter->erp_dbf, 3, "p_pst/ret");
+- debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof (wwn_t));
+- debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int));
+- debug_event(adapter->erp_dbf, 3, &retval, sizeof (int));
+-
+ return retval;
+ }
+
+@@ -2395,7 +2296,7 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action)
+ port->wwpn,
+ zfcp_get_busid_by_adapter(adapter),
+ adapter->peer_wwpn);
+- zfcp_erp_port_failed(port);
++ zfcp_erp_port_failed(port, 25, NULL);
+ retval = ZFCP_ERP_FAILED;
+ break;
+ }
+@@ -2421,8 +2322,8 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action)
+ /* nameserver port may live again */
+ atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING,
+ &adapter->nameserver_port->status);
+- if (zfcp_erp_port_reopen(adapter->nameserver_port, 0)
+- >= 0) {
++ if (zfcp_erp_port_reopen(adapter->nameserver_port, 0,
++ 77, erp_action) >= 0) {
+ erp_action->step =
+ ZFCP_ERP_STEP_NAMESERVER_OPEN;
+ retval = ZFCP_ERP_CONTINUES;
+@@ -2453,7 +2354,7 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action)
+ "for port 0x%016Lx "
+ "(misconfigured WWPN?)\n",
+ port->wwpn);
+- zfcp_erp_port_failed(port);
++ zfcp_erp_port_failed(port, 26, NULL);
+ retval = ZFCP_ERP_EXIT;
+ } else {
+ ZFCP_LOG_DEBUG("nameserver look-up failed for "
+@@ -2549,17 +2450,12 @@ zfcp_erp_port_strategy_open_nameserver_wakeup(struct zfcp_erp_action
+ read_lock_irqsave(&adapter->erp_lock, flags);
+ list_for_each_entry_safe(erp_action, tmp, &adapter->erp_running_head,
+ list) {
+- debug_text_event(adapter->erp_dbf, 4, "p_pstnsw_n");
+- debug_event(adapter->erp_dbf, 4, &erp_action->port->wwpn,
+- sizeof (wwn_t));
+ if (erp_action->step == ZFCP_ERP_STEP_NAMESERVER_OPEN) {
+- debug_text_event(adapter->erp_dbf, 3, "p_pstnsw_w");
+- debug_event(adapter->erp_dbf, 3,
+- &erp_action->port->wwpn, sizeof (wwn_t));
+ if (atomic_test_mask(
+ ZFCP_STATUS_COMMON_ERP_FAILED,
+ &adapter->nameserver_port->status))
+- zfcp_erp_port_failed(erp_action->port);
++ zfcp_erp_port_failed(erp_action->port, 27,
++ NULL);
+ zfcp_erp_action_ready(erp_action);
+ }
+ }
+@@ -2580,26 +2476,18 @@ static int
+ zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *erp_action)
+ {
+ int retval;
+- struct zfcp_adapter *adapter = erp_action->adapter;
+- struct zfcp_port *port = erp_action->port;
+
+ retval = zfcp_fsf_close_physical_port(erp_action);
+ if (retval == -ENOMEM) {
+- debug_text_event(adapter->erp_dbf, 5, "o_pfstc_nomem");
+- debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ retval = ZFCP_ERP_NOMEM;
+ goto out;
+ }
+ erp_action->step = ZFCP_ERP_STEP_PHYS_PORT_CLOSING;
+ if (retval != 0) {
+- debug_text_event(adapter->erp_dbf, 5, "o_pfstc_cpf");
+- debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ /* could not send 'open', fail */
+ retval = ZFCP_ERP_FAILED;
+ goto out;
+ }
+- debug_text_event(adapter->erp_dbf, 6, "o_pfstc_cpok");
+- debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t));
+ retval = ZFCP_ERP_CONTINUES;
+ out:
+ return retval;
+@@ -2609,10 +2497,6 @@ static int
+ zfcp_erp_port_strategy_clearstati(struct zfcp_port *port)
+ {
+ int retval = 0;
+- struct zfcp_adapter *adapter = port->adapter;
+-
+- debug_text_event(adapter->erp_dbf, 5, "p_pstclst");
+- debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+
+ atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING |
+ ZFCP_STATUS_COMMON_CLOSING |
+@@ -2636,26 +2520,18 @@ static int
+ zfcp_erp_port_strategy_close(struct zfcp_erp_action *erp_action)
+ {
+ int retval;
+- struct zfcp_adapter *adapter = erp_action->adapter;
+- struct zfcp_port *port = erp_action->port;
+
+ retval = zfcp_fsf_close_port(erp_action);
+ if (retval == -ENOMEM) {
+- debug_text_event(adapter->erp_dbf, 5, "p_pstc_nomem");
+- debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ retval = ZFCP_ERP_NOMEM;
+ goto out;
+ }
+ erp_action->step = ZFCP_ERP_STEP_PORT_CLOSING;
+ if (retval != 0) {
+- debug_text_event(adapter->erp_dbf, 5, "p_pstc_cpf");
+- debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ /* could not send 'close', fail */
+ retval = ZFCP_ERP_FAILED;
+ goto out;
+ }
+- debug_text_event(adapter->erp_dbf, 6, "p_pstc_cpok");
+- debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t));
+ retval = ZFCP_ERP_CONTINUES;
+ out:
+ return retval;
+@@ -2673,26 +2549,18 @@ static int
+ zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *erp_action)
+ {
+ int retval;
+- struct zfcp_adapter *adapter = erp_action->adapter;
+- struct zfcp_port *port = erp_action->port;
+
+ retval = zfcp_fsf_open_port(erp_action);
+ if (retval == -ENOMEM) {
+- debug_text_event(adapter->erp_dbf, 5, "p_psto_nomem");
+- debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ retval = ZFCP_ERP_NOMEM;
+ goto out;
+ }
+ erp_action->step = ZFCP_ERP_STEP_PORT_OPENING;
+ if (retval != 0) {
+- debug_text_event(adapter->erp_dbf, 5, "p_psto_opf");
+- debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ /* could not send 'open', fail */
+ retval = ZFCP_ERP_FAILED;
+ goto out;
+ }
+- debug_text_event(adapter->erp_dbf, 6, "p_psto_opok");
+- debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t));
+ retval = ZFCP_ERP_CONTINUES;
+ out:
+ return retval;
+@@ -2710,26 +2578,18 @@ static int
+ zfcp_erp_port_strategy_open_common_lookup(struct zfcp_erp_action *erp_action)
+ {
+ int retval;
+- struct zfcp_adapter *adapter = erp_action->adapter;
+- struct zfcp_port *port = erp_action->port;
+
+ retval = zfcp_ns_gid_pn_request(erp_action);
+ if (retval == -ENOMEM) {
+- debug_text_event(adapter->erp_dbf, 5, "p_pstn_nomem");
+- debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ retval = ZFCP_ERP_NOMEM;
+ goto out;
+ }
+ erp_action->step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP;
+ if (retval != 0) {
+- debug_text_event(adapter->erp_dbf, 5, "p_pstn_ref");
+- debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ /* could not send nameserver request, fail */
+ retval = ZFCP_ERP_FAILED;
+ goto out;
+ }
+- debug_text_event(adapter->erp_dbf, 6, "p_pstn_reok");
+- debug_event(adapter->erp_dbf, 6, &port->wwpn, sizeof (wwn_t));
+ retval = ZFCP_ERP_CONTINUES;
+ out:
+ return retval;
+@@ -2750,7 +2610,6 @@ zfcp_erp_unit_strategy(struct zfcp_erp_action *erp_action)
+ {
+ int retval = ZFCP_ERP_FAILED;
+ struct zfcp_unit *unit = erp_action->unit;
+- struct zfcp_adapter *adapter = erp_action->adapter;
+
+ switch (erp_action->step) {
+
+@@ -2797,10 +2656,6 @@ zfcp_erp_unit_strategy(struct zfcp_erp_action *erp_action)
+ break;
+ }
+
+- debug_text_event(adapter->erp_dbf, 3, "u_ust/ret");
+- debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof (fcp_lun_t));
+- debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int));
+- debug_event(adapter->erp_dbf, 3, &retval, sizeof (int));
+ return retval;
+ }
+
+@@ -2808,10 +2663,6 @@ static int
+ zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit)
+ {
+ int retval = 0;
+- struct zfcp_adapter *adapter = unit->port->adapter;
+-
+- debug_text_event(adapter->erp_dbf, 5, "u_ustclst");
+- debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, sizeof (fcp_lun_t));
+
+ atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING |
+ ZFCP_STATUS_COMMON_CLOSING |
+@@ -2835,28 +2686,18 @@ static int
+ zfcp_erp_unit_strategy_close(struct zfcp_erp_action *erp_action)
+ {
+ int retval;
+- struct zfcp_adapter *adapter = erp_action->adapter;
+- struct zfcp_unit *unit = erp_action->unit;
+
+ retval = zfcp_fsf_close_unit(erp_action);
+ if (retval == -ENOMEM) {
+- debug_text_event(adapter->erp_dbf, 5, "u_ustc_nomem");
+- debug_event(adapter->erp_dbf, 5, &unit->fcp_lun,
+- sizeof (fcp_lun_t));
+ retval = ZFCP_ERP_NOMEM;
+ goto out;
+ }
+ erp_action->step = ZFCP_ERP_STEP_UNIT_CLOSING;
+ if (retval != 0) {
+- debug_text_event(adapter->erp_dbf, 5, "u_ustc_cuf");
+- debug_event(adapter->erp_dbf, 5, &unit->fcp_lun,
+- sizeof (fcp_lun_t));
+ /* could not send 'close', fail */
+ retval = ZFCP_ERP_FAILED;
+ goto out;
+ }
+- debug_text_event(adapter->erp_dbf, 6, "u_ustc_cuok");
+- debug_event(adapter->erp_dbf, 6, &unit->fcp_lun, sizeof (fcp_lun_t));
+ retval = ZFCP_ERP_CONTINUES;
+
+ out:
+@@ -2875,28 +2716,18 @@ static int
+ zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action)
+ {
+ int retval;
+- struct zfcp_adapter *adapter = erp_action->adapter;
+- struct zfcp_unit *unit = erp_action->unit;
+
+ retval = zfcp_fsf_open_unit(erp_action);
+ if (retval == -ENOMEM) {
+- debug_text_event(adapter->erp_dbf, 5, "u_usto_nomem");
+- debug_event(adapter->erp_dbf, 5, &unit->fcp_lun,
+- sizeof (fcp_lun_t));
+ retval = ZFCP_ERP_NOMEM;
+ goto out;
+ }
+ erp_action->step = ZFCP_ERP_STEP_UNIT_OPENING;
+ if (retval != 0) {
+- debug_text_event(adapter->erp_dbf, 5, "u_usto_ouf");
+- debug_event(adapter->erp_dbf, 5, &unit->fcp_lun,
+- sizeof (fcp_lun_t));
+ /* could not send 'open', fail */
+ retval = ZFCP_ERP_FAILED;
+ goto out;
+ }
+- debug_text_event(adapter->erp_dbf, 6, "u_usto_ouok");
+- debug_event(adapter->erp_dbf, 6, &unit->fcp_lun, sizeof (fcp_lun_t));
+ retval = ZFCP_ERP_CONTINUES;
+ out:
+ return retval;
+@@ -2918,14 +2749,12 @@ void zfcp_erp_start_timer(struct zfcp_fsf_req *fsf_req)
+ *
+ * returns:
+ */
+-static int
+-zfcp_erp_action_enqueue(int action,
+- struct zfcp_adapter *adapter,
+- struct zfcp_port *port, struct zfcp_unit *unit)
++static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter,
++ struct zfcp_port *port,
++ struct zfcp_unit *unit, u8 id, void *ref)
+ {
+- int retval = 1;
++ int retval = 1, need = want;
+ struct zfcp_erp_action *erp_action = NULL;
+- int stronger_action = 0;
+ u32 status = 0;
+
+ /*
+@@ -2944,17 +2773,11 @@ zfcp_erp_action_enqueue(int action,
+ &adapter->status))
+ return -EIO;
+
+- debug_event(adapter->erp_dbf, 4, &action, sizeof (int));
+ /* check whether we really need this */
+- switch (action) {
++ switch (want) {
+ case ZFCP_ERP_ACTION_REOPEN_UNIT:
+ if (atomic_test_mask
+ (ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status)) {
+- debug_text_event(adapter->erp_dbf, 4, "u_actenq_drp");
+- debug_event(adapter->erp_dbf, 4, &port->wwpn,
+- sizeof (wwn_t));
+- debug_event(adapter->erp_dbf, 4, &unit->fcp_lun,
+- sizeof (fcp_lun_t));
+ goto out;
+ }
+ if (!atomic_test_mask
+@@ -2964,18 +2787,13 @@ zfcp_erp_action_enqueue(int action,
+ goto out;
+ }
+ if (!atomic_test_mask
+- (ZFCP_STATUS_COMMON_UNBLOCKED, &port->status)) {
+- stronger_action = ZFCP_ERP_ACTION_REOPEN_PORT;
+- unit = NULL;
+- }
++ (ZFCP_STATUS_COMMON_UNBLOCKED, &port->status))
++ need = ZFCP_ERP_ACTION_REOPEN_PORT;
+ /* fall through !!! */
+
+ case ZFCP_ERP_ACTION_REOPEN_PORT:
+ if (atomic_test_mask
+ (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status)) {
+- debug_text_event(adapter->erp_dbf, 4, "p_actenq_drp");
+- debug_event(adapter->erp_dbf, 4, &port->wwpn,
+- sizeof (wwn_t));
+ goto out;
+ }
+ /* fall through !!! */
+@@ -2987,15 +2805,9 @@ zfcp_erp_action_enqueue(int action,
+ ZFCP_ERP_ACTION_REOPEN_PORT_FORCED) {
+ ZFCP_LOG_INFO("dropped erp action %i (port "
+ "0x%016Lx, action in use: %i)\n",
+- action, port->wwpn,
++ want, port->wwpn,
+ port->erp_action.action);
+- debug_text_event(adapter->erp_dbf, 4,
+- "pf_actenq_drp");
+- } else
+- debug_text_event(adapter->erp_dbf, 4,
+- "pf_actenq_drpcp");
+- debug_event(adapter->erp_dbf, 4, &port->wwpn,
+- sizeof (wwn_t));
++ }
+ goto out;
+ }
+ if (!atomic_test_mask
+@@ -3005,46 +2817,36 @@ zfcp_erp_action_enqueue(int action,
+ goto out;
+ }
+ if (!atomic_test_mask
+- (ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status)) {
+- stronger_action = ZFCP_ERP_ACTION_REOPEN_ADAPTER;
+- port = NULL;
+- }
++ (ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status))
++ need = ZFCP_ERP_ACTION_REOPEN_ADAPTER;
+ /* fall through !!! */
+
+ case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
+ if (atomic_test_mask
+ (ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status)) {
+- debug_text_event(adapter->erp_dbf, 4, "a_actenq_drp");
+ goto out;
+ }
+ break;
+
+ default:
+- debug_text_exception(adapter->erp_dbf, 1, "a_actenq_bug");
+- debug_event(adapter->erp_dbf, 1, &action, sizeof (int));
+ ZFCP_LOG_NORMAL("bug: unknown erp action requested "
+ "on adapter %s (action=%d)\n",
+- zfcp_get_busid_by_adapter(adapter), action);
++ zfcp_get_busid_by_adapter(adapter), want);
+ goto out;
+ }
+
+ /* check whether we need something stronger first */
+- if (stronger_action) {
+- debug_text_event(adapter->erp_dbf, 4, "a_actenq_str");
+- debug_event(adapter->erp_dbf, 4, &stronger_action,
+- sizeof (int));
++ if (need) {
+ ZFCP_LOG_DEBUG("stronger erp action %d needed before "
+ "erp action %d on adapter %s\n",
+- stronger_action, action,
+- zfcp_get_busid_by_adapter(adapter));
+- action = stronger_action;
++ need, want, zfcp_get_busid_by_adapter(adapter));
+ }
+
+ /* mark adapter to have some error recovery pending */
+ atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status);
+
+ /* setup error recovery action */
+- switch (action) {
++ switch (need) {
+
+ case ZFCP_ERP_ACTION_REOPEN_UNIT:
+ zfcp_unit_get(unit);
+@@ -3077,13 +2879,11 @@ zfcp_erp_action_enqueue(int action,
+ break;
+ }
+
+- debug_text_event(adapter->erp_dbf, 4, "a_actenq");
+-
+ memset(erp_action, 0, sizeof (struct zfcp_erp_action));
+ erp_action->adapter = adapter;
+ erp_action->port = port;
+ erp_action->unit = unit;
+- erp_action->action = action;
++ erp_action->action = need;
+ erp_action->status = status;
+
+ ++adapter->erp_total_count;
+@@ -3091,8 +2891,11 @@ zfcp_erp_action_enqueue(int action,
+ /* finally put it into 'ready' queue and kick erp thread */
+ list_add_tail(&erp_action->list, &adapter->erp_ready_head);
+ up(&adapter->erp_ready_sem);
++ zfcp_rec_dbf_event_thread(1, adapter, 0);
+ retval = 0;
+ out:
++ zfcp_rec_dbf_event_trigger(id, ref, want, need, erp_action,
++ adapter, port, unit);
+ return retval;
+ }
+
+@@ -3108,9 +2911,9 @@ zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
+ erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM;
+ }
+
+- debug_text_event(adapter->erp_dbf, 4, "a_actdeq");
+- debug_event(adapter->erp_dbf, 4, &erp_action->action, sizeof (int));
+ list_del(&erp_action->list);
++ zfcp_rec_dbf_event_action(144, erp_action);
++
+ switch (erp_action->action) {
+ case ZFCP_ERP_ACTION_REOPEN_UNIT:
+ atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
+@@ -3215,7 +3018,6 @@ static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
+ {
+ struct zfcp_port *port;
+
+- debug_text_event(adapter->erp_dbf, 5, "a_actab");
+ if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status))
+ zfcp_erp_action_dismiss(&adapter->erp_action);
+ else
+@@ -3226,10 +3028,7 @@ static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
+ static void zfcp_erp_action_dismiss_port(struct zfcp_port *port)
+ {
+ struct zfcp_unit *unit;
+- struct zfcp_adapter *adapter = port->adapter;
+
+- debug_text_event(adapter->erp_dbf, 5, "p_actab");
+- debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t));
+ if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status))
+ zfcp_erp_action_dismiss(&port->erp_action);
+ else
+@@ -3239,92 +3038,60 @@ static void zfcp_erp_action_dismiss_port(struct zfcp_port *port)
+
+ static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit)
+ {
+- struct zfcp_adapter *adapter = unit->port->adapter;
+-
+- debug_text_event(adapter->erp_dbf, 5, "u_actab");
+- debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, sizeof (fcp_lun_t));
+ if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status))
+ zfcp_erp_action_dismiss(&unit->erp_action);
+ }
+
+ static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action)
+ {
+- struct zfcp_adapter *adapter = erp_action->adapter;
+-
+- debug_text_event(adapter->erp_dbf, 6, "a_toru");
+- debug_event(adapter->erp_dbf, 6, &erp_action->action, sizeof (int));
+ list_move(&erp_action->list, &erp_action->adapter->erp_running_head);
++ zfcp_rec_dbf_event_action(145, erp_action);
+ }
+
+ static void zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action)
+ {
+- struct zfcp_adapter *adapter = erp_action->adapter;
+-
+- debug_text_event(adapter->erp_dbf, 6, "a_tore");
+- debug_event(adapter->erp_dbf, 6, &erp_action->action, sizeof (int));
+ list_move(&erp_action->list, &erp_action->adapter->erp_ready_head);
++ zfcp_rec_dbf_event_action(146, erp_action);
+ }
+
+-void
+-zfcp_erp_port_boxed(struct zfcp_port *port)
++void zfcp_erp_port_boxed(struct zfcp_port *port, u8 id, void *ref)
+ {
+- struct zfcp_adapter *adapter = port->adapter;
+ unsigned long flags;
+
+- debug_text_event(adapter->erp_dbf, 3, "p_access_boxed");
+- debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t));
+ read_lock_irqsave(&zfcp_data.config_lock, flags);
+- zfcp_erp_modify_port_status(port,
+- ZFCP_STATUS_COMMON_ACCESS_BOXED,
+- ZFCP_SET);
++ zfcp_erp_modify_port_status(port, id, ref,
++ ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET);
+ read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+- zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED);
++ zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
+ }
+
+-void
+-zfcp_erp_unit_boxed(struct zfcp_unit *unit)
++void zfcp_erp_unit_boxed(struct zfcp_unit *unit, u8 id, void *ref)
+ {
+- struct zfcp_adapter *adapter = unit->port->adapter;
+-
+- debug_text_event(adapter->erp_dbf, 3, "u_access_boxed");
+- debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t));
+- zfcp_erp_modify_unit_status(unit,
+- ZFCP_STATUS_COMMON_ACCESS_BOXED,
+- ZFCP_SET);
+- zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED);
++ zfcp_erp_modify_unit_status(unit, id, ref,
++ ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET);
++ zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
+ }
+
+-void
+-zfcp_erp_port_access_denied(struct zfcp_port *port)
++void zfcp_erp_port_access_denied(struct zfcp_port *port, u8 id, void *ref)
+ {
+- struct zfcp_adapter *adapter = port->adapter;
+ unsigned long flags;
+
+- debug_text_event(adapter->erp_dbf, 3, "p_access_denied");
+- debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t));
+ read_lock_irqsave(&zfcp_data.config_lock, flags);
+- zfcp_erp_modify_port_status(port,
+- ZFCP_STATUS_COMMON_ERP_FAILED |
+- ZFCP_STATUS_COMMON_ACCESS_DENIED,
+- ZFCP_SET);
++ zfcp_erp_modify_port_status(port, id, ref,
++ ZFCP_STATUS_COMMON_ERP_FAILED |
++ ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
+ read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+ }
+
+-void
+-zfcp_erp_unit_access_denied(struct zfcp_unit *unit)
++void zfcp_erp_unit_access_denied(struct zfcp_unit *unit, u8 id, void *ref)
+ {
+- struct zfcp_adapter *adapter = unit->port->adapter;
+-
+- debug_text_event(adapter->erp_dbf, 3, "u_access_denied");
+- debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t));
+- zfcp_erp_modify_unit_status(unit,
+- ZFCP_STATUS_COMMON_ERP_FAILED |
+- ZFCP_STATUS_COMMON_ACCESS_DENIED,
+- ZFCP_SET);
++ zfcp_erp_modify_unit_status(unit, id, ref,
++ ZFCP_STATUS_COMMON_ERP_FAILED |
++ ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
+ }
+
+-void
+-zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter)
++void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, u8 id,
++ void *ref)
+ {
+ struct zfcp_port *port;
+ unsigned long flags;
+@@ -3332,54 +3099,43 @@ zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter)
+ if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
+ return;
+
+- debug_text_event(adapter->erp_dbf, 3, "a_access_recover");
+- debug_event(adapter->erp_dbf, 3, zfcp_get_busid_by_adapter(adapter), 8);
+-
+ read_lock_irqsave(&zfcp_data.config_lock, flags);
+ if (adapter->nameserver_port)
+- zfcp_erp_port_access_changed(adapter->nameserver_port);
++ zfcp_erp_port_access_changed(adapter->nameserver_port, id, ref);
+ list_for_each_entry(port, &adapter->port_list_head, list)
+ if (port != adapter->nameserver_port)
+- zfcp_erp_port_access_changed(port);
++ zfcp_erp_port_access_changed(port, id, ref);
+ read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+ }
+
+-void
+-zfcp_erp_port_access_changed(struct zfcp_port *port)
++void zfcp_erp_port_access_changed(struct zfcp_port *port, u8 id, void *ref)
+ {
+ struct zfcp_adapter *adapter = port->adapter;
+ struct zfcp_unit *unit;
+
+- debug_text_event(adapter->erp_dbf, 3, "p_access_recover");
+- debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t));
+-
+ if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED,
+ &port->status) &&
+ !atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED,
+ &port->status)) {
+ if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status))
+ list_for_each_entry(unit, &port->unit_list_head, list)
+- zfcp_erp_unit_access_changed(unit);
++ zfcp_erp_unit_access_changed(unit, id, ref);
+ return;
+ }
+
+ ZFCP_LOG_NORMAL("reopen of port 0x%016Lx on adapter %s "
+ "(due to ACT update)\n",
+ port->wwpn, zfcp_get_busid_by_adapter(adapter));
+- if (zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED) != 0)
++ if (zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref))
+ ZFCP_LOG_NORMAL("failed reopen of port"
+ "(adapter %s, wwpn=0x%016Lx)\n",
+ zfcp_get_busid_by_adapter(adapter), port->wwpn);
+ }
+
+-void
+-zfcp_erp_unit_access_changed(struct zfcp_unit *unit)
++void zfcp_erp_unit_access_changed(struct zfcp_unit *unit, u8 id, void *ref)
+ {
+ struct zfcp_adapter *adapter = unit->port->adapter;
+
+- debug_text_event(adapter->erp_dbf, 3, "u_access_recover");
+- debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t));
+-
+ if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED,
+ &unit->status) &&
+ !atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED,
+@@ -3390,7 +3146,7 @@ zfcp_erp_unit_access_changed(struct zfcp_unit *unit)
+ " on adapter %s (due to ACT update)\n",
+ unit->fcp_lun, unit->port->wwpn,
+ zfcp_get_busid_by_adapter(adapter));
+- if (zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED) != 0)
++ if (zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref))
+ ZFCP_LOG_NORMAL("failed reopen of unit (adapter %s, "
+ "wwpn=0x%016Lx, fcp_lun=0x%016Lx)\n",
+ zfcp_get_busid_by_adapter(adapter),
+diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
+index 06b1079..6abf178 100644
+--- a/drivers/s390/scsi/zfcp_ext.h
++++ b/drivers/s390/scsi/zfcp_ext.h
+@@ -131,22 +131,25 @@ extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *, int);
+ extern struct fc_function_template zfcp_transport_functions;
+
+ /******************************** ERP ****************************************/
+-extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, u32, int);
+-extern int zfcp_erp_adapter_reopen(struct zfcp_adapter *, int);
+-extern int zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int);
+-extern void zfcp_erp_adapter_failed(struct zfcp_adapter *);
+-
+-extern void zfcp_erp_modify_port_status(struct zfcp_port *, u32, int);
+-extern int zfcp_erp_port_reopen(struct zfcp_port *, int);
+-extern int zfcp_erp_port_shutdown(struct zfcp_port *, int);
+-extern int zfcp_erp_port_forced_reopen(struct zfcp_port *, int);
+-extern void zfcp_erp_port_failed(struct zfcp_port *);
+-extern int zfcp_erp_port_reopen_all(struct zfcp_adapter *, int);
+-
+-extern void zfcp_erp_modify_unit_status(struct zfcp_unit *, u32, int);
+-extern int zfcp_erp_unit_reopen(struct zfcp_unit *, int);
+-extern int zfcp_erp_unit_shutdown(struct zfcp_unit *, int);
+-extern void zfcp_erp_unit_failed(struct zfcp_unit *);
++extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, u8, void *,
++ u32, int);
++extern int zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, u8, void *);
++extern int zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, u8, void *);
++extern void zfcp_erp_adapter_failed(struct zfcp_adapter *, u8, void *);
++
++extern void zfcp_erp_modify_port_status(struct zfcp_port *, u8, void *, u32,
++ int);
++extern int zfcp_erp_port_reopen(struct zfcp_port *, int, u8, void *);
++extern int zfcp_erp_port_shutdown(struct zfcp_port *, int, u8, void *);
++extern int zfcp_erp_port_forced_reopen(struct zfcp_port *, int, u8, void *);
++extern void zfcp_erp_port_failed(struct zfcp_port *, u8, void *);
++extern int zfcp_erp_port_reopen_all(struct zfcp_adapter *, int, u8, void *);
++
++extern void zfcp_erp_modify_unit_status(struct zfcp_unit *, u8, void *, u32,
++ int);
++extern int zfcp_erp_unit_reopen(struct zfcp_unit *, int, u8, void *);
++extern int zfcp_erp_unit_shutdown(struct zfcp_unit *, int, u8, void *);
++extern void zfcp_erp_unit_failed(struct zfcp_unit *, u8, void *);
+
+ extern int zfcp_erp_thread_setup(struct zfcp_adapter *);
+ extern int zfcp_erp_thread_kill(struct zfcp_adapter *);
+@@ -155,15 +158,25 @@ extern void zfcp_erp_async_handler(struct zfcp_erp_action *, unsigned long);
+
+ extern int zfcp_test_link(struct zfcp_port *);
+
+-extern void zfcp_erp_port_boxed(struct zfcp_port *);
+-extern void zfcp_erp_unit_boxed(struct zfcp_unit *);
+-extern void zfcp_erp_port_access_denied(struct zfcp_port *);
+-extern void zfcp_erp_unit_access_denied(struct zfcp_unit *);
+-extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *);
+-extern void zfcp_erp_port_access_changed(struct zfcp_port *);
+-extern void zfcp_erp_unit_access_changed(struct zfcp_unit *);
++extern void zfcp_erp_port_boxed(struct zfcp_port *, u8 id, void *ref);
++extern void zfcp_erp_unit_boxed(struct zfcp_unit *, u8 id, void *ref);
++extern void zfcp_erp_port_access_denied(struct zfcp_port *, u8 id, void *ref);
++extern void zfcp_erp_unit_access_denied(struct zfcp_unit *, u8 id, void *ref);
++extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *, u8, void *);
++extern void zfcp_erp_port_access_changed(struct zfcp_port *, u8, void *);
++extern void zfcp_erp_unit_access_changed(struct zfcp_unit *, u8, void *);
+
+ /******************************** AUX ****************************************/
++extern void zfcp_rec_dbf_event_thread(u8 id, struct zfcp_adapter *adapter,
++ int lock);
++extern void zfcp_rec_dbf_event_adapter(u8 id, void *ref, struct zfcp_adapter *);
++extern void zfcp_rec_dbf_event_port(u8 id, void *ref, struct zfcp_port *port);
++extern void zfcp_rec_dbf_event_unit(u8 id, void *ref, struct zfcp_unit *unit);
++extern void zfcp_rec_dbf_event_trigger(u8 id, void *ref, u8 want, u8 need,
++ void *action, struct zfcp_adapter *,
++ struct zfcp_port *, struct zfcp_unit *);
++extern void zfcp_rec_dbf_event_action(u8 id, struct zfcp_erp_action *);
++
+ extern void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *);
+ extern void zfcp_hba_dbf_event_fsf_unsol(const char *, struct zfcp_adapter *,
+ struct fsf_status_read_buffer *);
+diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
+index 0dff058..7c3f028 100644
+--- a/drivers/s390/scsi/zfcp_fsf.c
++++ b/drivers/s390/scsi/zfcp_fsf.c
+@@ -46,7 +46,7 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *);
+ static int zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *);
+ static int zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *);
+ static int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *);
+-static void zfcp_fsf_link_down_info_eval(struct zfcp_adapter *,
++static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *, u8,
+ struct fsf_link_down_info *);
+ static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *);
+
+@@ -284,37 +284,6 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
+ goto skip_protstatus;
+ }
+
+- /* log additional information provided by FSF (if any) */
+- if (likely(qtcb->header.log_length)) {
+- /* do not trust them ;-) */
+- if (unlikely(qtcb->header.log_start >
+- sizeof(struct fsf_qtcb))) {
+- ZFCP_LOG_NORMAL
+- ("bug: ULP (FSF logging) log data starts "
+- "beyond end of packet header. Ignored. "
+- "(start=%i, size=%li)\n",
+- qtcb->header.log_start,
+- sizeof(struct fsf_qtcb));
+- goto forget_log;
+- }
+- if (unlikely((size_t) (qtcb->header.log_start +
+- qtcb->header.log_length) >
+- sizeof(struct fsf_qtcb))) {
+- ZFCP_LOG_NORMAL("bug: ULP (FSF logging) log data ends "
+- "beyond end of packet header. Ignored. "
+- "(start=%i, length=%i, size=%li)\n",
+- qtcb->header.log_start,
+- qtcb->header.log_length,
+- sizeof(struct fsf_qtcb));
+- goto forget_log;
+- }
+- ZFCP_LOG_TRACE("ULP log data: \n");
+- ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE,
+- (char *) qtcb + qtcb->header.log_start,
+- qtcb->header.log_length);
+- }
+- forget_log:
+-
+ /* evaluate FSF Protocol Status */
+ switch (qtcb->prefix.prot_status) {
+
+@@ -329,7 +298,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
+ zfcp_get_busid_by_adapter(adapter),
+ prot_status_qual->version_error.fsf_version,
+ ZFCP_QTCB_VERSION);
+- zfcp_erp_adapter_shutdown(adapter, 0);
++ zfcp_erp_adapter_shutdown(adapter, 0, 117, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -340,7 +309,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
+ qtcb->prefix.req_seq_no,
+ zfcp_get_busid_by_adapter(adapter),
+ prot_status_qual->sequence_error.exp_req_seq_no);
+- zfcp_erp_adapter_reopen(adapter, 0);
++ zfcp_erp_adapter_reopen(adapter, 0, 98, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_RETRY;
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+@@ -351,7 +320,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
+ "that used on adapter %s. "
+ "Stopping all operations on this adapter.\n",
+ zfcp_get_busid_by_adapter(adapter));
+- zfcp_erp_adapter_shutdown(adapter, 0);
++ zfcp_erp_adapter_shutdown(adapter, 0, 118, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -368,14 +337,15 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
+ *(unsigned long long*)
+ (&qtcb->bottom.support.req_handle),
+ zfcp_get_busid_by_adapter(adapter));
+- zfcp_erp_adapter_shutdown(adapter, 0);
++ zfcp_erp_adapter_shutdown(adapter, 0, 78, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+ case FSF_PROT_LINK_DOWN:
+- zfcp_fsf_link_down_info_eval(adapter,
++ zfcp_fsf_link_down_info_eval(fsf_req, 37,
+ &prot_status_qual->link_down_info);
+- zfcp_erp_adapter_reopen(adapter, 0);
++ /* FIXME: reopening adapter now? better wait for link up */
++ zfcp_erp_adapter_reopen(adapter, 0, 79, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -385,12 +355,13 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
+ "Re-starting operations on this adapter.\n",
+ zfcp_get_busid_by_adapter(adapter));
+ /* All ports should be marked as ready to run again */
+- zfcp_erp_modify_adapter_status(adapter,
++ zfcp_erp_modify_adapter_status(adapter, 28, NULL,
+ ZFCP_STATUS_COMMON_RUNNING,
+ ZFCP_SET);
+ zfcp_erp_adapter_reopen(adapter,
+ ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED
+- | ZFCP_STATUS_COMMON_ERP_FAILED);
++ | ZFCP_STATUS_COMMON_ERP_FAILED,
++ 99, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -400,7 +371,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
+ "Restarting all operations on this "
+ "adapter.\n",
+ zfcp_get_busid_by_adapter(adapter));
+- zfcp_erp_adapter_reopen(adapter, 0);
++ zfcp_erp_adapter_reopen(adapter, 0, 100, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_RETRY;
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+@@ -413,7 +384,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
+ "(debug info 0x%x).\n",
+ zfcp_get_busid_by_adapter(adapter),
+ qtcb->prefix.prot_status);
+- zfcp_erp_adapter_shutdown(adapter, 0);
++ zfcp_erp_adapter_shutdown(adapter, 0, 119, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ }
+
+@@ -452,7 +423,7 @@ zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *fsf_req)
+ "(debug info 0x%x).\n",
+ zfcp_get_busid_by_adapter(fsf_req->adapter),
+ fsf_req->qtcb->header.fsf_command);
+- zfcp_erp_adapter_shutdown(fsf_req->adapter, 0);
++ zfcp_erp_adapter_shutdown(fsf_req->adapter, 0, 120, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -506,7 +477,7 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req)
+ "problem on the adapter %s "
+ "Stopping all operations on this adapter. ",
+ zfcp_get_busid_by_adapter(fsf_req->adapter));
+- zfcp_erp_adapter_shutdown(fsf_req->adapter, 0);
++ zfcp_erp_adapter_shutdown(fsf_req->adapter, 0, 121, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ case FSF_SQ_ULP_PROGRAMMING_ERROR:
+@@ -537,9 +508,11 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req)
+ * zfcp_fsf_link_down_info_eval - evaluate link down information block
+ */
+ static void
+-zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
++zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *fsf_req, u8 id,
+ struct fsf_link_down_info *link_down)
+ {
++ struct zfcp_adapter *adapter = fsf_req->adapter;
++
+ if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
+ &adapter->status))
+ return;
+@@ -630,7 +603,7 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
+ link_down->vendor_specific_code);
+
+ out:
+- zfcp_erp_adapter_failed(adapter);
++ zfcp_erp_adapter_failed(adapter, id, fsf_req);
+ }
+
+ /*
+@@ -824,19 +797,14 @@ zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *fsf_req)
+ switch (status_buffer->status_subtype) {
+
+ case FSF_STATUS_READ_SUB_CLOSE_PHYS_PORT:
+- debug_text_event(adapter->erp_dbf, 3, "unsol_pc_phys:");
+- zfcp_erp_port_reopen(port, 0);
++ zfcp_erp_port_reopen(port, 0, 101, fsf_req);
+ break;
+
+ case FSF_STATUS_READ_SUB_ERROR_PORT:
+- debug_text_event(adapter->erp_dbf, 1, "unsol_pc_err:");
+- zfcp_erp_port_shutdown(port, 0);
++ zfcp_erp_port_shutdown(port, 0, 122, fsf_req);
+ break;
+
+ default:
+- debug_text_event(adapter->erp_dbf, 0, "unsol_unk_sub:");
+- debug_exception(adapter->erp_dbf, 0,
+- &status_buffer->status_subtype, sizeof (u32));
+ ZFCP_LOG_NORMAL("bug: Undefined status subtype received "
+ "for a reopen indication on port with "
+ "d_id 0x%06x on the adapter %s. "
+@@ -928,7 +896,7 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
+ case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
+ ZFCP_LOG_INFO("Physical link to adapter %s is down\n",
+ zfcp_get_busid_by_adapter(adapter));
+- zfcp_fsf_link_down_info_eval(adapter,
++ zfcp_fsf_link_down_info_eval(fsf_req, 38,
+ (struct fsf_link_down_info *)
+ &status_buffer->payload);
+ break;
+@@ -936,7 +904,7 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_LOG_INFO("Local link to adapter %s is down "
+ "due to failed FDISC login\n",
+ zfcp_get_busid_by_adapter(adapter));
+- zfcp_fsf_link_down_info_eval(adapter,
++ zfcp_fsf_link_down_info_eval(fsf_req, 39,
+ (struct fsf_link_down_info *)
+ &status_buffer->payload);
+ break;
+@@ -944,13 +912,13 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_LOG_INFO("Local link to adapter %s is down "
+ "due to firmware update on adapter\n",
+ zfcp_get_busid_by_adapter(adapter));
+- zfcp_fsf_link_down_info_eval(adapter, NULL);
++ zfcp_fsf_link_down_info_eval(fsf_req, 40, NULL);
+ break;
+ default:
+ ZFCP_LOG_INFO("Local link to adapter %s is down "
+ "due to unknown reason\n",
+ zfcp_get_busid_by_adapter(adapter));
+- zfcp_fsf_link_down_info_eval(adapter, NULL);
++ zfcp_fsf_link_down_info_eval(fsf_req, 41, NULL);
+ };
+ break;
+
+@@ -959,12 +927,13 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
+ "Restarting operations on this adapter\n",
+ zfcp_get_busid_by_adapter(adapter));
+ /* All ports should be marked as ready to run again */
+- zfcp_erp_modify_adapter_status(adapter,
++ zfcp_erp_modify_adapter_status(adapter, 30, NULL,
+ ZFCP_STATUS_COMMON_RUNNING,
+ ZFCP_SET);
+ zfcp_erp_adapter_reopen(adapter,
+ ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED
+- | ZFCP_STATUS_COMMON_ERP_FAILED);
++ | ZFCP_STATUS_COMMON_ERP_FAILED,
++ 102, fsf_req);
+ break;
+
+ case FSF_STATUS_READ_NOTIFICATION_LOST:
+@@ -998,13 +967,13 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
+
+ if (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_ACT_UPDATED)
+- zfcp_erp_adapter_access_changed(adapter);
++ zfcp_erp_adapter_access_changed(adapter, 135, fsf_req);
+ break;
+
+ case FSF_STATUS_READ_CFDC_UPDATED:
+ ZFCP_LOG_NORMAL("CFDC has been updated on the adapter %s\n",
+ zfcp_get_busid_by_adapter(adapter));
+- zfcp_erp_adapter_access_changed(adapter);
++ zfcp_erp_adapter_access_changed(adapter, 136, fsf_req);
+ break;
+
+ case FSF_STATUS_READ_CFDC_HARDENED:
+@@ -1025,7 +994,6 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
+ break;
+
+ case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
+- debug_text_event(adapter->erp_dbf, 2, "unsol_features:");
+ ZFCP_LOG_INFO("List of supported features on adapter %s has "
+ "been changed from 0x%08X to 0x%08X\n",
+ zfcp_get_busid_by_adapter(adapter),
+@@ -1073,7 +1041,7 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_LOG_INFO("restart adapter %s due to status read "
+ "buffer shortage\n",
+ zfcp_get_busid_by_adapter(adapter));
+- zfcp_erp_adapter_reopen(adapter, 0);
++ zfcp_erp_adapter_reopen(adapter, 0, 103, fsf_req);
+ }
+ }
+ out:
+@@ -1174,8 +1142,6 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
+
+ case FSF_PORT_HANDLE_NOT_VALID:
+ if (fsf_stat_qual->word[0] != fsf_stat_qual->word[1]) {
+- debug_text_event(new_fsf_req->adapter->erp_dbf, 3,
+- "fsf_s_phand_nv0");
+ /*
+ * In this case a command that was sent prior to a port
+ * reopen was aborted (handles are different). This is
+@@ -1194,17 +1160,14 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
+ fsf_status_qual,
+ sizeof (union fsf_status_qual));
+ /* Let's hope this sorts out the mess */
+- debug_text_event(new_fsf_req->adapter->erp_dbf, 1,
+- "fsf_s_phand_nv1");
+- zfcp_erp_adapter_reopen(unit->port->adapter, 0);
++ zfcp_erp_adapter_reopen(unit->port->adapter, 0, 104,
++ new_fsf_req);
+ new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ }
+ break;
+
+ case FSF_LUN_HANDLE_NOT_VALID:
+ if (fsf_stat_qual->word[0] != fsf_stat_qual->word[1]) {
+- debug_text_event(new_fsf_req->adapter->erp_dbf, 3,
+- "fsf_s_lhand_nv0");
+ /*
+ * In this case a command that was sent prior to a unit
+ * reopen was aborted (handles are different).
+@@ -1226,17 +1189,13 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
+ fsf_status_qual,
+ sizeof (union fsf_status_qual));
+ /* Let's hope this sorts out the mess */
+- debug_text_event(new_fsf_req->adapter->erp_dbf, 1,
+- "fsf_s_lhand_nv1");
+- zfcp_erp_port_reopen(unit->port, 0);
++ zfcp_erp_port_reopen(unit->port, 0, 105, new_fsf_req);
+ new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ }
+ break;
+
+ case FSF_FCP_COMMAND_DOES_NOT_EXIST:
+ retval = 0;
+- debug_text_event(new_fsf_req->adapter->erp_dbf, 3,
+- "fsf_s_no_exist");
+ new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED;
+ break;
+
+@@ -1244,9 +1203,7 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
+ ZFCP_LOG_INFO("Remote port 0x%016Lx on adapter %s needs to "
+ "be reopened\n", unit->port->wwpn,
+ zfcp_get_busid_by_unit(unit));
+- debug_text_event(new_fsf_req->adapter->erp_dbf, 2,
+- "fsf_s_pboxed");
+- zfcp_erp_port_boxed(unit->port);
++ zfcp_erp_port_boxed(unit->port, 47, new_fsf_req);
+ new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
+ | ZFCP_STATUS_FSFREQ_RETRY;
+ break;
+@@ -1257,8 +1214,7 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
+ "to be reopened\n",
+ unit->fcp_lun, unit->port->wwpn,
+ zfcp_get_busid_by_unit(unit));
+- debug_text_event(new_fsf_req->adapter->erp_dbf, 1, "fsf_s_lboxed");
+- zfcp_erp_unit_boxed(unit);
++ zfcp_erp_unit_boxed(unit, 48, new_fsf_req);
+ new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
+ | ZFCP_STATUS_FSFREQ_RETRY;
+ break;
+@@ -1266,26 +1222,17 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
+ case FSF_ADAPTER_STATUS_AVAILABLE:
+ switch (new_fsf_req->qtcb->header.fsf_status_qual.word[0]) {
+ case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
+- debug_text_event(new_fsf_req->adapter->erp_dbf, 1,
+- "fsf_sq_ltest");
+ zfcp_test_link(unit->port);
+ new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
+ /* SCSI stack will escalate */
+- debug_text_event(new_fsf_req->adapter->erp_dbf, 1,
+- "fsf_sq_ulp");
+ new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ default:
+ ZFCP_LOG_NORMAL
+ ("bug: Wrong status qualifier 0x%x arrived.\n",
+ new_fsf_req->qtcb->header.fsf_status_qual.word[0]);
+- debug_text_event(new_fsf_req->adapter->erp_dbf, 0,
+- "fsf_sq_inval:");
+- debug_exception(new_fsf_req->adapter->erp_dbf, 0,
+- &new_fsf_req->qtcb->header.
+- fsf_status_qual.word[0], sizeof (u32));
+ break;
+ }
+ break;
+@@ -1299,11 +1246,6 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
+ ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
+ "(debug info 0x%x)\n",
+ new_fsf_req->qtcb->header.fsf_status);
+- debug_text_event(new_fsf_req->adapter->erp_dbf, 0,
+- "fsf_s_inval:");
+- debug_exception(new_fsf_req->adapter->erp_dbf, 0,
+- &new_fsf_req->qtcb->header.fsf_status,
+- sizeof (u32));
+ break;
+ }
+ skip_fsfstatus:
+@@ -1506,8 +1448,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
+ zfcp_get_busid_by_port(port),
+ ZFCP_FC_SERVICE_CLASS_DEFAULT);
+ /* stop operation for this adapter */
+- debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup");
+- zfcp_erp_adapter_shutdown(adapter, 0);
++ zfcp_erp_adapter_shutdown(adapter, 0, 123, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -1515,13 +1456,11 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
+ switch (header->fsf_status_qual.word[0]){
+ case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
+ /* reopening link to port */
+- debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest");
+ zfcp_test_link(port);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
+ /* ERP strategy will escalate */
+- debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp");
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ default:
+@@ -1549,8 +1488,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
+ break;
+ }
+ }
+- debug_text_event(adapter->erp_dbf, 1, "fsf_s_access");
+- zfcp_erp_port_access_denied(port);
++ zfcp_erp_port_access_denied(port, 55, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -1562,7 +1500,6 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO,
+ (char *) &header->fsf_status_qual,
+ sizeof (union fsf_status_qual));
+- debug_text_event(adapter->erp_dbf, 1, "fsf_s_gcom_rej");
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -1575,8 +1512,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO,
+ (char *) &header->fsf_status_qual,
+ sizeof (union fsf_status_qual));
+- debug_text_event(adapter->erp_dbf, 1, "fsf_s_phandle_nv");
+- zfcp_erp_adapter_reopen(adapter, 0);
++ zfcp_erp_adapter_reopen(adapter, 0, 106, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -1584,8 +1520,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_LOG_INFO("port needs to be reopened "
+ "(adapter %s, port d_id=0x%06x)\n",
+ zfcp_get_busid_by_port(port), port->d_id);
+- debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed");
+- zfcp_erp_port_boxed(port);
++ zfcp_erp_port_boxed(port, 49, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
+ | ZFCP_STATUS_FSFREQ_RETRY;
+ break;
+@@ -1624,9 +1559,6 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
+ default:
+ ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
+ "(debug info 0x%x)\n", header->fsf_status);
+- debug_text_event(adapter->erp_dbf, 0, "fsf_sq_inval:");
+- debug_exception(adapter->erp_dbf, 0,
+- &header->fsf_status_qual.word[0], sizeof (u32));
+ break;
+ }
+
+@@ -1810,21 +1742,18 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
+ zfcp_get_busid_by_adapter(adapter),
+ ZFCP_FC_SERVICE_CLASS_DEFAULT);
+ /* stop operation for this adapter */
+- debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup");
+- zfcp_erp_adapter_shutdown(adapter, 0);
++ zfcp_erp_adapter_shutdown(adapter, 0, 124, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+ case FSF_ADAPTER_STATUS_AVAILABLE:
+ switch (header->fsf_status_qual.word[0]){
+ case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
+- debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest");
+ if (port && (send_els->ls_code != ZFCP_LS_ADISC))
+ zfcp_test_link(port);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
+- debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp");
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ retval =
+ zfcp_handle_els_rjt(header->fsf_status_qual.word[1],
+@@ -1832,7 +1761,6 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
+ &header->fsf_status_qual.word[2]);
+ break;
+ case FSF_SQ_RETRY_IF_POSSIBLE:
+- debug_text_event(adapter->erp_dbf, 1, "fsf_sq_retry");
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ default:
+@@ -1909,9 +1837,8 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
+ break;
+ }
+ }
+- debug_text_event(adapter->erp_dbf, 1, "fsf_s_access");
+ if (port != NULL)
+- zfcp_erp_port_access_denied(port);
++ zfcp_erp_port_access_denied(port, 56, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -1921,9 +1848,6 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
+ "(adapter: %s, fsf_status=0x%08x)\n",
+ zfcp_get_busid_by_adapter(adapter),
+ header->fsf_status);
+- debug_text_event(adapter->erp_dbf, 0, "fsf_sq_inval");
+- debug_exception(adapter->erp_dbf, 0,
+- &header->fsf_status_qual.word[0], sizeof(u32));
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ }
+@@ -2132,8 +2056,7 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
+ "versions in comparison to this device "
+ "driver (try updated device driver)\n",
+ zfcp_get_busid_by_adapter(adapter));
+- debug_text_event(adapter->erp_dbf, 0, "low_qtcb_ver");
+- zfcp_erp_adapter_shutdown(adapter, 0);
++ zfcp_erp_adapter_shutdown(adapter, 0, 125, fsf_req);
+ return -EIO;
+ }
+ if (ZFCP_QTCB_VERSION > bottom->high_qtcb_version) {
+@@ -2142,8 +2065,7 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
+ "versions than this device driver uses"
+ "(consider a microcode upgrade)\n",
+ zfcp_get_busid_by_adapter(adapter));
+- debug_text_event(adapter->erp_dbf, 0, "high_qtcb_ver");
+- zfcp_erp_adapter_shutdown(adapter, 0);
++ zfcp_erp_adapter_shutdown(adapter, 0, 126, fsf_req);
+ return -EIO;
+ }
+ return 0;
+@@ -2183,17 +2105,13 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
+ adapter->peer_wwnn,
+ adapter->peer_wwpn,
+ adapter->peer_d_id);
+- debug_text_event(fsf_req->adapter->erp_dbf, 0,
+- "top-p-to-p");
+ break;
+ case FC_PORTTYPE_NLPORT:
+ ZFCP_LOG_NORMAL("error: Arbitrated loop fibrechannel "
+ "topology detected at adapter %s "
+ "unsupported, shutting down adapter\n",
+ zfcp_get_busid_by_adapter(adapter));
+- debug_text_event(fsf_req->adapter->erp_dbf, 0,
+- "top-al");
+- zfcp_erp_adapter_shutdown(adapter, 0);
++ zfcp_erp_adapter_shutdown(adapter, 0, 127, fsf_req);
+ return -EIO;
+ case FC_PORTTYPE_NPORT:
+ ZFCP_LOG_NORMAL("Switched fabric fibrechannel "
+@@ -2208,9 +2126,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
+ "of a type known to the zfcp "
+ "driver, shutting down adapter\n",
+ zfcp_get_busid_by_adapter(adapter));
+- debug_text_exception(fsf_req->adapter->erp_dbf, 0,
+- "unknown-topo");
+- zfcp_erp_adapter_shutdown(adapter, 0);
++ zfcp_erp_adapter_shutdown(adapter, 0, 128, fsf_req);
+ return -EIO;
+ }
+ bottom = &qtcb->bottom.config;
+@@ -2222,33 +2138,24 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
+ bottom->max_qtcb_size,
+ zfcp_get_busid_by_adapter(adapter),
+ sizeof(struct fsf_qtcb));
+- debug_text_event(fsf_req->adapter->erp_dbf, 0,
+- "qtcb-size");
+- debug_event(fsf_req->adapter->erp_dbf, 0,
+- &bottom->max_qtcb_size, sizeof (u32));
+- zfcp_erp_adapter_shutdown(adapter, 0);
++ zfcp_erp_adapter_shutdown(adapter, 0, 129, fsf_req);
+ return -EIO;
+ }
+ atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
+ &adapter->status);
+ break;
+ case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
+- debug_text_event(adapter->erp_dbf, 0, "xchg-inco");
+-
+ if (zfcp_fsf_exchange_config_evaluate(fsf_req, 0))
+ return -EIO;
+
+ atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
+ &adapter->status);
+
+- zfcp_fsf_link_down_info_eval(adapter,
++ zfcp_fsf_link_down_info_eval(fsf_req, 42,
+ &qtcb->header.fsf_status_qual.link_down_info);
+ break;
+ default:
+- debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf-stat-ng");
+- debug_event(fsf_req->adapter->erp_dbf, 0,
+- &fsf_req->qtcb->header.fsf_status, sizeof(u32));
+- zfcp_erp_adapter_shutdown(adapter, 0);
++ zfcp_erp_adapter_shutdown(adapter, 0, 130, fsf_req);
+ return -EIO;
+ }
+ return 0;
+@@ -2424,13 +2331,9 @@ zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req)
+ case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
+ zfcp_fsf_exchange_port_evaluate(fsf_req, 0);
+ atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
+- zfcp_fsf_link_down_info_eval(adapter,
++ zfcp_fsf_link_down_info_eval(fsf_req, 43,
+ &qtcb->header.fsf_status_qual.link_down_info);
+ break;
+- default:
+- debug_text_event(adapter->erp_dbf, 0, "xchg-port-ng");
+- debug_event(adapter->erp_dbf, 0,
+- &fsf_req->qtcb->header.fsf_status, sizeof(u32));
+ }
+ }
+
+@@ -2528,8 +2431,6 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_LOG_NORMAL("bug: remote port 0x%016Lx on adapter %s "
+ "is already open.\n",
+ port->wwpn, zfcp_get_busid_by_port(port));
+- debug_text_exception(fsf_req->adapter->erp_dbf, 0,
+- "fsf_s_popen");
+ /*
+ * This is a bug, however operation should continue normally
+ * if it is simply ignored
+@@ -2553,8 +2454,7 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
+ break;
+ }
+ }
+- debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
+- zfcp_erp_port_access_denied(port);
++ zfcp_erp_port_access_denied(port, 57, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -2563,24 +2463,18 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
+ "The remote port 0x%016Lx on adapter %s "
+ "could not be opened. Disabling it.\n",
+ port->wwpn, zfcp_get_busid_by_port(port));
+- debug_text_event(fsf_req->adapter->erp_dbf, 1,
+- "fsf_s_max_ports");
+- zfcp_erp_port_failed(port);
++ zfcp_erp_port_failed(port, 31, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+ case FSF_ADAPTER_STATUS_AVAILABLE:
+ switch (header->fsf_status_qual.word[0]) {
+ case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
+- debug_text_event(fsf_req->adapter->erp_dbf, 1,
+- "fsf_sq_ltest");
+ /* ERP strategy will escalate */
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
+ /* ERP strategy will escalate */
+- debug_text_event(fsf_req->adapter->erp_dbf, 1,
+- "fsf_sq_ulp");
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ case FSF_SQ_NO_RETRY_POSSIBLE:
+@@ -2589,21 +2483,13 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
+ "Disabling it.\n",
+ port->wwpn,
+ zfcp_get_busid_by_port(port));
+- debug_text_exception(fsf_req->adapter->erp_dbf, 0,
+- "fsf_sq_no_retry");
+- zfcp_erp_port_failed(port);
++ zfcp_erp_port_failed(port, 32, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ default:
+ ZFCP_LOG_NORMAL
+ ("bug: Wrong status qualifier 0x%x arrived.\n",
+ header->fsf_status_qual.word[0]);
+- debug_text_event(fsf_req->adapter->erp_dbf, 0,
+- "fsf_sq_inval:");
+- debug_exception(
+- fsf_req->adapter->erp_dbf, 0,
+- &header->fsf_status_qual.word[0],
+- sizeof (u32));
+ break;
+ }
+ break;
+@@ -2646,17 +2532,12 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
+ "warning: insufficient length of "
+ "PLOGI payload (%i)\n",
+ fsf_req->qtcb->bottom.support.els1_length);
+- debug_text_event(fsf_req->adapter->erp_dbf, 0,
+- "fsf_s_short_plogi:");
+ /* skip sanity check and assume wwpn is ok */
+ } else {
+ if (plogi->serv_param.wwpn != port->wwpn) {
+ ZFCP_LOG_INFO("warning: d_id of port "
+ "0x%016Lx changed during "
+ "open\n", port->wwpn);
+- debug_text_event(
+- fsf_req->adapter->erp_dbf, 0,
+- "fsf_s_did_change:");
+ atomic_clear_mask(
+ ZFCP_STATUS_PORT_DID_DID,
+ &port->status);
+@@ -2681,9 +2562,6 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
+ "(debug info 0x%x)\n",
+ header->fsf_status);
+- debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:");
+- debug_exception(fsf_req->adapter->erp_dbf, 0,
+- &header->fsf_status, sizeof (u32));
+ break;
+ }
+
+@@ -2787,9 +2665,7 @@ zfcp_fsf_close_port_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
+ (char *) &fsf_req->qtcb->header.fsf_status_qual,
+ sizeof (union fsf_status_qual));
+- debug_text_event(fsf_req->adapter->erp_dbf, 1,
+- "fsf_s_phand_nv");
+- zfcp_erp_adapter_reopen(port->adapter, 0);
++ zfcp_erp_adapter_reopen(port->adapter, 0, 107, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -2804,7 +2680,7 @@ zfcp_fsf_close_port_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_LOG_TRACE("remote port 0x016%Lx on adapter %s closed, "
+ "port handle 0x%x\n", port->wwpn,
+ zfcp_get_busid_by_port(port), port->handle);
+- zfcp_erp_modify_port_status(port,
++ zfcp_erp_modify_port_status(port, 33, fsf_req,
+ ZFCP_STATUS_COMMON_OPEN,
+ ZFCP_CLEAR);
+ retval = 0;
+@@ -2814,10 +2690,6 @@ zfcp_fsf_close_port_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
+ "(debug info 0x%x)\n",
+ fsf_req->qtcb->header.fsf_status);
+- debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:");
+- debug_exception(fsf_req->adapter->erp_dbf, 0,
+- &fsf_req->qtcb->header.fsf_status,
+- sizeof (u32));
+ break;
+ }
+
+@@ -2930,9 +2802,7 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
+ (char *) &header->fsf_status_qual,
+ sizeof (union fsf_status_qual));
+- debug_text_event(fsf_req->adapter->erp_dbf, 1,
+- "fsf_s_phand_nv");
+- zfcp_erp_adapter_reopen(port->adapter, 0);
++ zfcp_erp_adapter_reopen(port->adapter, 0, 108, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -2953,8 +2823,7 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req)
+ break;
+ }
+ }
+- debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
+- zfcp_erp_port_access_denied(port);
++ zfcp_erp_port_access_denied(port, 58, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -2964,35 +2833,32 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req)
+ "to close it physically.\n",
+ port->wwpn,
+ zfcp_get_busid_by_port(port));
+- debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_pboxed");
+- zfcp_erp_port_boxed(port);
++ zfcp_erp_port_boxed(port, 50, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
+ ZFCP_STATUS_FSFREQ_RETRY;
++
++ /* can't use generic zfcp_erp_modify_port_status because
++ * ZFCP_STATUS_COMMON_OPEN must not be reset for the port */
++ atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
++ list_for_each_entry(unit, &port->unit_list_head, list)
++ atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
++ &unit->status);
+ break;
+
+ case FSF_ADAPTER_STATUS_AVAILABLE:
+ switch (header->fsf_status_qual.word[0]) {
+ case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
+- debug_text_event(fsf_req->adapter->erp_dbf, 1,
+- "fsf_sq_ltest");
+ /* This will now be escalated by ERP */
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
+ /* ERP strategy will escalate */
+- debug_text_event(fsf_req->adapter->erp_dbf, 1,
+- "fsf_sq_ulp");
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ default:
+ ZFCP_LOG_NORMAL
+ ("bug: Wrong status qualifier 0x%x arrived.\n",
+ header->fsf_status_qual.word[0]);
+- debug_text_event(fsf_req->adapter->erp_dbf, 0,
+- "fsf_sq_inval:");
+- debug_exception(
+- fsf_req->adapter->erp_dbf, 0,
+- &header->fsf_status_qual.word[0], sizeof (u32));
+ break;
+ }
+ break;
+@@ -3015,9 +2881,6 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
+ "(debug info 0x%x)\n",
+ header->fsf_status);
+- debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:");
+- debug_exception(fsf_req->adapter->erp_dbf, 0,
+- &header->fsf_status, sizeof (u32));
+ break;
+ }
+
+@@ -3149,8 +3012,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
+ (char *) &header->fsf_status_qual,
+ sizeof (union fsf_status_qual));
+- debug_text_event(adapter->erp_dbf, 1, "fsf_s_ph_nv");
+- zfcp_erp_adapter_reopen(unit->port->adapter, 0);
++ zfcp_erp_adapter_reopen(unit->port->adapter, 0, 109, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -3159,8 +3021,6 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
+ "remote port 0x%016Lx on adapter %s twice.\n",
+ unit->fcp_lun,
+ unit->port->wwpn, zfcp_get_busid_by_unit(unit));
+- debug_text_exception(adapter->erp_dbf, 0,
+- "fsf_s_uopen");
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -3182,8 +3042,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
+ break;
+ }
+ }
+- debug_text_event(adapter->erp_dbf, 1, "fsf_s_access");
+- zfcp_erp_unit_access_denied(unit);
++ zfcp_erp_unit_access_denied(unit, 59, fsf_req);
+ atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
+ atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+@@ -3193,8 +3052,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter %s "
+ "needs to be reopened\n",
+ unit->port->wwpn, zfcp_get_busid_by_unit(unit));
+- debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed");
+- zfcp_erp_port_boxed(unit->port);
++ zfcp_erp_port_boxed(unit->port, 51, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
+ ZFCP_STATUS_FSFREQ_RETRY;
+ break;
+@@ -3234,9 +3092,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
+ (char *) &header->fsf_status_qual,
+ sizeof (union fsf_status_qual));
+- debug_text_event(adapter->erp_dbf, 2,
+- "fsf_s_l_sh_vio");
+- zfcp_erp_unit_access_denied(unit);
++ zfcp_erp_unit_access_denied(unit, 60, fsf_req);
+ atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
+ atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+@@ -3250,9 +3106,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
+ unit->fcp_lun,
+ unit->port->wwpn,
+ zfcp_get_busid_by_unit(unit));
+- debug_text_event(adapter->erp_dbf, 1,
+- "fsf_s_max_units");
+- zfcp_erp_unit_failed(unit);
++ zfcp_erp_unit_failed(unit, 34, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -3260,26 +3114,17 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
+ switch (header->fsf_status_qual.word[0]) {
+ case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
+ /* Re-establish link to port */
+- debug_text_event(adapter->erp_dbf, 1,
+- "fsf_sq_ltest");
+ zfcp_test_link(unit->port);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
+ /* ERP strategy will escalate */
+- debug_text_event(adapter->erp_dbf, 1,
+- "fsf_sq_ulp");
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ default:
+ ZFCP_LOG_NORMAL
+ ("bug: Wrong status qualifier 0x%x arrived.\n",
+ header->fsf_status_qual.word[0]);
+- debug_text_event(adapter->erp_dbf, 0,
+- "fsf_sq_inval:");
+- debug_exception(adapter->erp_dbf, 0,
+- &header->fsf_status_qual.word[0],
+- sizeof (u32));
+ }
+ break;
+
+@@ -3331,15 +3176,15 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
+ if (exclusive && !readwrite) {
+ ZFCP_LOG_NORMAL("exclusive access of read-only "
+ "unit not supported\n");
+- zfcp_erp_unit_failed(unit);
++ zfcp_erp_unit_failed(unit, 35, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+- zfcp_erp_unit_shutdown(unit, 0);
++ zfcp_erp_unit_shutdown(unit, 0, 80, fsf_req);
+ } else if (!exclusive && readwrite) {
+ ZFCP_LOG_NORMAL("shared access of read-write "
+ "unit not supported\n");
+- zfcp_erp_unit_failed(unit);
++ zfcp_erp_unit_failed(unit, 36, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+- zfcp_erp_unit_shutdown(unit, 0);
++ zfcp_erp_unit_shutdown(unit, 0, 81, fsf_req);
+ }
+ }
+
+@@ -3350,9 +3195,6 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
+ "(debug info 0x%x)\n",
+ header->fsf_status);
+- debug_text_event(adapter->erp_dbf, 0, "fsf_s_inval:");
+- debug_exception(adapter->erp_dbf, 0,
+- &header->fsf_status, sizeof (u32));
+ break;
+ }
+
+@@ -3465,9 +3307,7 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
+ (char *) &fsf_req->qtcb->header.fsf_status_qual,
+ sizeof (union fsf_status_qual));
+- debug_text_event(fsf_req->adapter->erp_dbf, 1,
+- "fsf_s_phand_nv");
+- zfcp_erp_adapter_reopen(unit->port->adapter, 0);
++ zfcp_erp_adapter_reopen(unit->port->adapter, 0, 110, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -3483,9 +3323,7 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
+ (char *) &fsf_req->qtcb->header.fsf_status_qual,
+ sizeof (union fsf_status_qual));
+- debug_text_event(fsf_req->adapter->erp_dbf, 1,
+- "fsf_s_lhand_nv");
+- zfcp_erp_port_reopen(unit->port, 0);
++ zfcp_erp_port_reopen(unit->port, 0, 111, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -3494,8 +3332,7 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
+ "needs to be reopened\n",
+ unit->port->wwpn,
+ zfcp_get_busid_by_unit(unit));
+- debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_pboxed");
+- zfcp_erp_port_boxed(unit->port);
++ zfcp_erp_port_boxed(unit->port, 52, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
+ ZFCP_STATUS_FSFREQ_RETRY;
+ break;
+@@ -3504,27 +3341,17 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
+ switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) {
+ case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
+ /* re-establish link to port */
+- debug_text_event(fsf_req->adapter->erp_dbf, 1,
+- "fsf_sq_ltest");
+ zfcp_test_link(unit->port);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
+ /* ERP strategy will escalate */
+- debug_text_event(fsf_req->adapter->erp_dbf, 1,
+- "fsf_sq_ulp");
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+ default:
+ ZFCP_LOG_NORMAL
+ ("bug: Wrong status qualifier 0x%x arrived.\n",
+ fsf_req->qtcb->header.fsf_status_qual.word[0]);
+- debug_text_event(fsf_req->adapter->erp_dbf, 0,
+- "fsf_sq_inval:");
+- debug_exception(
+- fsf_req->adapter->erp_dbf, 0,
+- &fsf_req->qtcb->header.fsf_status_qual.word[0],
+- sizeof (u32));
+ break;
+ }
+ break;
+@@ -3545,10 +3372,6 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented "
+ "(debug info 0x%x)\n",
+ fsf_req->qtcb->header.fsf_status);
+- debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:");
+- debug_exception(fsf_req->adapter->erp_dbf, 0,
+- &fsf_req->qtcb->header.fsf_status,
+- sizeof (u32));
+ break;
+ }
+
+@@ -3703,7 +3526,7 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
+ zfcp_get_busid_by_unit(unit),
+ unit->port->wwpn,
+ unit->fcp_lun);
+- zfcp_erp_unit_shutdown(unit, 0);
++ zfcp_erp_unit_shutdown(unit, 0, 131, fsf_req);
+ retval = -EINVAL;
+ }
+ goto no_fit;
+@@ -3739,8 +3562,8 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
+ send_failed:
+ no_fit:
+ failed_scsi_cmnd:
+- unit_blocked:
+ zfcp_unit_put(unit);
++ unit_blocked:
+ zfcp_fsf_req_free(fsf_req);
+ fsf_req = NULL;
+ scsi_cmnd->host_scribble = NULL;
+@@ -3861,9 +3684,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
+ (char *) &header->fsf_status_qual,
+ sizeof (union fsf_status_qual));
+- debug_text_event(fsf_req->adapter->erp_dbf, 1,
+- "fsf_s_phand_nv");
+- zfcp_erp_adapter_reopen(unit->port->adapter, 0);
++ zfcp_erp_adapter_reopen(unit->port->adapter, 0, 112, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -3879,9 +3700,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL,
+ (char *) &header->fsf_status_qual,
+ sizeof (union fsf_status_qual));
+- debug_text_event(fsf_req->adapter->erp_dbf, 1,
+- "fsf_s_uhand_nv");
+- zfcp_erp_port_reopen(unit->port, 0);
++ zfcp_erp_port_reopen(unit->port, 0, 113, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -3897,9 +3716,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL,
+ (char *) &header->fsf_status_qual,
+ sizeof (union fsf_status_qual));
+- debug_text_event(fsf_req->adapter->erp_dbf, 1,
+- "fsf_s_hand_mis");
+- zfcp_erp_adapter_reopen(unit->port->adapter, 0);
++ zfcp_erp_adapter_reopen(unit->port->adapter, 0, 114, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -3909,9 +3726,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+ zfcp_get_busid_by_unit(unit),
+ ZFCP_FC_SERVICE_CLASS_DEFAULT);
+ /* stop operation for this adapter */
+- debug_text_exception(fsf_req->adapter->erp_dbf, 0,
+- "fsf_s_class_nsup");
+- zfcp_erp_adapter_shutdown(unit->port->adapter, 0);
++ zfcp_erp_adapter_shutdown(unit->port->adapter, 0, 132, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -3927,9 +3742,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
+ (char *) &header->fsf_status_qual,
+ sizeof (union fsf_status_qual));
+- debug_text_event(fsf_req->adapter->erp_dbf, 1,
+- "fsf_s_fcp_lun_nv");
+- zfcp_erp_port_reopen(unit->port, 0);
++ zfcp_erp_port_reopen(unit->port, 0, 115, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -3951,8 +3764,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+ break;
+ }
+ }
+- debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access");
+- zfcp_erp_unit_access_denied(unit);
++ zfcp_erp_unit_access_denied(unit, 61, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -3965,9 +3777,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+ zfcp_get_busid_by_unit(unit),
+ fsf_req->qtcb->bottom.io.data_direction);
+ /* stop operation for this adapter */
+- debug_text_event(fsf_req->adapter->erp_dbf, 0,
+- "fsf_s_dir_ind_nv");
+- zfcp_erp_adapter_shutdown(unit->port->adapter, 0);
++ zfcp_erp_adapter_shutdown(unit->port->adapter, 0, 133, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -3980,9 +3790,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+ zfcp_get_busid_by_unit(unit),
+ fsf_req->qtcb->bottom.io.fcp_cmnd_length);
+ /* stop operation for this adapter */
+- debug_text_event(fsf_req->adapter->erp_dbf, 0,
+- "fsf_s_cmd_len_nv");
+- zfcp_erp_adapter_shutdown(unit->port->adapter, 0);
++ zfcp_erp_adapter_shutdown(unit->port->adapter, 0, 134, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ break;
+
+@@ -3990,8 +3798,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+ ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter %s "
+ "needs to be reopened\n",
+ unit->port->wwpn, zfcp_get_busid_by_unit(unit));
+- debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_pboxed");
+- zfcp_erp_port_boxed(unit->port);
++ zfcp_erp_port_boxed(unit->port, 53, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
+ ZFCP_STATUS_FSFREQ_RETRY;
+ break;
+@@ -4001,8 +3808,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+ "wwpn=0x%016Lx, fcp_lun=0x%016Lx)\n",
+ zfcp_get_busid_by_unit(unit),
+ unit->port->wwpn, unit->fcp_lun);
+- debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_lboxed");
+- zfcp_erp_unit_boxed(unit);
++ zfcp_erp_unit_boxed(unit, 54, fsf_req);
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
+ | ZFCP_STATUS_FSFREQ_RETRY;
+ break;
+@@ -4011,25 +3817,16 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+ switch (header->fsf_status_qual.word[0]) {
+ case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
+ /* re-establish link to port */
+- debug_text_event(fsf_req->adapter->erp_dbf, 1,
+- "fsf_sq_ltest");
+ zfcp_test_link(unit->port);
+ break;
+ case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
+ /* FIXME(hw) need proper specs for proper action */
+ /* let scsi stack deal with retries and escalation */
+- debug_text_event(fsf_req->adapter->erp_dbf, 1,
+- "fsf_sq_ulp");
+ break;
+ default:
+ ZFCP_LOG_NORMAL
+ ("Unknown status qualifier 0x%x arrived.\n",
+ header->fsf_status_qual.word[0]);
+- debug_text_event(fsf_req->adapter->erp_dbf, 0,
+- "fsf_sq_inval:");
+- debug_exception(fsf_req->adapter->erp_dbf, 0,
+- &header->fsf_status_qual.word[0],
+- sizeof(u32));
+ break;
+ }
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+@@ -4040,12 +3837,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
+
+ case FSF_FCP_RSP_AVAILABLE:
+ break;
+-
+- default:
+- debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:");
+- debug_exception(fsf_req->adapter->erp_dbf, 0,
+- &header->fsf_status, sizeof(u32));
+- break;
+ }
+
+ skip_fsfstatus:
+@@ -4625,9 +4416,6 @@ zfcp_fsf_control_file_handler(struct zfcp_fsf_req *fsf_req)
+ "was presented on the adapter %s\n",
+ header->fsf_status,
+ zfcp_get_busid_by_adapter(adapter));
+- debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_sq_inval");
+- debug_exception(fsf_req->adapter->erp_dbf, 0,
+- &header->fsf_status_qual.word[0], sizeof(u32));
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ retval = -EINVAL;
+ break;
+@@ -4817,7 +4605,6 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req)
+ volatile struct qdio_buffer_element *sbale;
+ int inc_seq_no;
+ int new_distance_from_int;
+- u64 dbg_tmp[2];
+ int retval = 0;
+
+ adapter = fsf_req->adapter;
+@@ -4867,10 +4654,6 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req)
+ QDIO_FLAG_SYNC_OUTPUT,
+ 0, fsf_req->sbal_first, fsf_req->sbal_number, NULL);
+
+- dbg_tmp[0] = (unsigned long) sbale[0].addr;
+- dbg_tmp[1] = (u64) retval;
+- debug_event(adapter->erp_dbf, 4, (void *) dbg_tmp, 16);
+-
+ if (unlikely(retval)) {
+ /* Queues are down..... */
+ retval = -EIO;
+@@ -4885,7 +4668,7 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req)
+ req_queue->free_index -= fsf_req->sbal_number;
+ req_queue->free_index += QDIO_MAX_BUFFERS_PER_Q;
+ req_queue->free_index %= QDIO_MAX_BUFFERS_PER_Q; /* wrap */
+- zfcp_erp_adapter_reopen(adapter, 0);
++ zfcp_erp_adapter_reopen(adapter, 0, 116, fsf_req);
+ } else {
+ req_queue->distance_from_int = new_distance_from_int;
+ /*
+diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
+index 22fdc17..8ca5f07 100644
+--- a/drivers/s390/scsi/zfcp_qdio.c
++++ b/drivers/s390/scsi/zfcp_qdio.c
+@@ -175,8 +175,9 @@ zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter, unsigned int status,
+ * which is set again in case we have missed by a mile.
+ */
+ zfcp_erp_adapter_reopen(adapter,
+- ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
+- ZFCP_STATUS_COMMON_ERP_FAILED);
++ ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
++ ZFCP_STATUS_COMMON_ERP_FAILED, 140,
++ NULL);
+ }
+ return retval;
+ }
+@@ -239,8 +240,6 @@ static void zfcp_qdio_reqid_check(struct zfcp_adapter *adapter,
+ struct zfcp_fsf_req *fsf_req;
+ unsigned long flags;
+
+- debug_long_event(adapter->erp_dbf, 4, req_id);
+-
+ spin_lock_irqsave(&adapter->req_list_lock, flags);
+ fsf_req = zfcp_reqlist_find(adapter, req_id);
+
+diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
+index b9daf5c..f818506 100644
+--- a/drivers/s390/scsi/zfcp_scsi.c
++++ b/drivers/s390/scsi/zfcp_scsi.c
+@@ -31,6 +31,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *,
+ void (*done) (struct scsi_cmnd *));
+ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *);
+ static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *);
++static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *);
+ static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *);
+ static int zfcp_task_management_function(struct zfcp_unit *, u8,
+ struct scsi_cmnd *);
+@@ -51,6 +52,7 @@ struct zfcp_data zfcp_data = {
+ .queuecommand = zfcp_scsi_queuecommand,
+ .eh_abort_handler = zfcp_scsi_eh_abort_handler,
+ .eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler,
++ .eh_target_reset_handler = zfcp_scsi_eh_target_reset_handler,
+ .eh_host_reset_handler = zfcp_scsi_eh_host_reset_handler,
+ .can_queue = 4096,
+ .this_id = -1,
+@@ -179,11 +181,10 @@ static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
+ struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata;
+
+ if (unit) {
+- zfcp_erp_wait(unit->port->adapter);
+ atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status);
+ sdpnt->hostdata = NULL;
+ unit->device = NULL;
+- zfcp_erp_unit_failed(unit);
++ zfcp_erp_unit_failed(unit, 12, NULL);
+ zfcp_unit_put(unit);
+ } else
+ ZFCP_LOG_NORMAL("bug: no unit associated with SCSI device at "
+@@ -442,58 +443,32 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
+ return retval;
+ }
+
+-static int
+-zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
++static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
+ {
+ int retval;
+- struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata;
++ struct zfcp_unit *unit = scpnt->device->hostdata;
+
+ if (!unit) {
+- ZFCP_LOG_NORMAL("bug: Tried reset for nonexistent unit\n");
+- retval = SUCCESS;
+- goto out;
++ WARN_ON(1);
++ return SUCCESS;
+ }
+- ZFCP_LOG_NORMAL("resetting unit 0x%016Lx on port 0x%016Lx, adapter %s\n",
+- unit->fcp_lun, unit->port->wwpn,
+- zfcp_get_busid_by_adapter(unit->port->adapter));
++ retval = zfcp_task_management_function(unit,
++ FCP_LOGICAL_UNIT_RESET,
++ scpnt);
++ return retval ? FAILED : SUCCESS;
++}
+
+- /*
+- * If we do not know whether the unit supports 'logical unit reset'
+- * then try 'logical unit reset' and proceed with 'target reset'
+- * if 'logical unit reset' fails.
+- * If the unit is known not to support 'logical unit reset' then
+- * skip 'logical unit reset' and try 'target reset' immediately.
+- */
+- if (!atomic_test_mask(ZFCP_STATUS_UNIT_NOTSUPPUNITRESET,
+- &unit->status)) {
+- retval = zfcp_task_management_function(unit,
+- FCP_LOGICAL_UNIT_RESET,
+- scpnt);
+- if (retval) {
+- ZFCP_LOG_DEBUG("unit reset failed (unit=%p)\n", unit);
+- if (retval == -ENOTSUPP)
+- atomic_set_mask
+- (ZFCP_STATUS_UNIT_NOTSUPPUNITRESET,
+- &unit->status);
+- /* fall through and try 'target reset' next */
+- } else {
+- ZFCP_LOG_DEBUG("unit reset succeeded (unit=%p)\n",
+- unit);
+- /* avoid 'target reset' */
+- retval = SUCCESS;
+- goto out;
+- }
++static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt)
++{
++ int retval;
++ struct zfcp_unit *unit = scpnt->device->hostdata;
++
++ if (!unit) {
++ WARN_ON(1);
++ return SUCCESS;
+ }
+ retval = zfcp_task_management_function(unit, FCP_TARGET_RESET, scpnt);
+- if (retval) {
+- ZFCP_LOG_DEBUG("target reset failed (unit=%p)\n", unit);
+- retval = FAILED;
+- } else {
+- ZFCP_LOG_DEBUG("target reset succeeded (unit=%p)\n", unit);
+- retval = SUCCESS;
+- }
+- out:
+- return retval;
++ return retval ? FAILED : SUCCESS;
+ }
+
+ static int
+@@ -553,7 +528,7 @@ static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
+ unit->fcp_lun, unit->port->wwpn,
+ zfcp_get_busid_by_adapter(unit->port->adapter));
+
+- zfcp_erp_adapter_reopen(adapter, 0);
++ zfcp_erp_adapter_reopen(adapter, 0, 141, scpnt);
+ zfcp_erp_wait(adapter);
+
+ return SUCCESS;
+diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c
+index 705c6d4..ccbba4d 100644
+--- a/drivers/s390/scsi/zfcp_sysfs_adapter.c
++++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c
+@@ -89,7 +89,7 @@ zfcp_sysfs_port_add_store(struct device *dev, struct device_attribute *attr, con
+
+ retval = 0;
+
+- zfcp_erp_port_reopen(port, 0);
++ zfcp_erp_port_reopen(port, 0, 91, NULL);
+ zfcp_erp_wait(port->adapter);
+ zfcp_port_put(port);
+ out:
+@@ -147,7 +147,7 @@ zfcp_sysfs_port_remove_store(struct device *dev, struct device_attribute *attr,
+ goto out;
+ }
+
+- zfcp_erp_port_shutdown(port, 0);
++ zfcp_erp_port_shutdown(port, 0, 92, NULL);
+ zfcp_erp_wait(adapter);
+ zfcp_port_put(port);
+ zfcp_port_dequeue(port);
+@@ -191,9 +191,10 @@ zfcp_sysfs_adapter_failed_store(struct device *dev, struct device_attribute *att
+ goto out;
+ }
+
+- zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING,
+- ZFCP_SET);
+- zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
++ zfcp_erp_modify_adapter_status(adapter, 44, NULL,
++ ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
++ zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 93,
++ NULL);
+ zfcp_erp_wait(adapter);
+ out:
+ up(&zfcp_data.config_sema);
+diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c
+index 1320c05..703c1b5 100644
+--- a/drivers/s390/scsi/zfcp_sysfs_port.c
++++ b/drivers/s390/scsi/zfcp_sysfs_port.c
+@@ -94,7 +94,7 @@ zfcp_sysfs_unit_add_store(struct device *dev, struct device_attribute *attr, con
+
+ retval = 0;
+
+- zfcp_erp_unit_reopen(unit, 0);
++ zfcp_erp_unit_reopen(unit, 0, 94, NULL);
+ zfcp_erp_wait(unit->port->adapter);
+ zfcp_unit_put(unit);
+ out:
+@@ -150,7 +150,7 @@ zfcp_sysfs_unit_remove_store(struct device *dev, struct device_attribute *attr,
+ goto out;
+ }
+
+- zfcp_erp_unit_shutdown(unit, 0);
++ zfcp_erp_unit_shutdown(unit, 0, 95, NULL);
+ zfcp_erp_wait(unit->port->adapter);
+ zfcp_unit_put(unit);
+ zfcp_unit_dequeue(unit);
+@@ -193,8 +193,9 @@ zfcp_sysfs_port_failed_store(struct device *dev, struct device_attribute *attr,
+ goto out;
+ }
+
+- zfcp_erp_modify_port_status(port, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
+- zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED);
++ zfcp_erp_modify_port_status(port, 45, NULL,
++ ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
++ zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, 96, NULL);
+ zfcp_erp_wait(port->adapter);
+ out:
+ up(&zfcp_data.config_sema);
+diff --git a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c
+index 63f75ee..80fb2c2 100644
+--- a/drivers/s390/scsi/zfcp_sysfs_unit.c
++++ b/drivers/s390/scsi/zfcp_sysfs_unit.c
+@@ -94,8 +94,9 @@ zfcp_sysfs_unit_failed_store(struct device *dev, struct device_attribute *attr,
+ goto out;
+ }
+
+- zfcp_erp_modify_unit_status(unit, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
+- zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED);
++ zfcp_erp_modify_unit_status(unit, 46, NULL,
++ ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
++ zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, 97, NULL);
+ zfcp_erp_wait(unit->port->adapter);
+ out:
+ up(&zfcp_data.config_sema);
+diff --git a/drivers/s390/sysinfo.c b/drivers/s390/sysinfo.c
+index 291ff62..c3e4ab0 100644
+--- a/drivers/s390/sysinfo.c
++++ b/drivers/s390/sysinfo.c
+@@ -11,111 +11,13 @@
+ #include <linux/init.h>
+ #include <linux/delay.h>
+ #include <asm/ebcdic.h>
++#include <asm/sysinfo.h>
+
+ /* Sigh, math-emu. Don't ask. */
+ #include <asm/sfp-util.h>
+ #include <math-emu/soft-fp.h>
+ #include <math-emu/single.h>
+
+-struct sysinfo_1_1_1 {
+- char reserved_0[32];
+- char manufacturer[16];
+- char type[4];
+- char reserved_1[12];
+- char model_capacity[16];
+- char sequence[16];
+- char plant[4];
+- char model[16];
+-};
+-
+-struct sysinfo_1_2_1 {
+- char reserved_0[80];
+- char sequence[16];
+- char plant[4];
+- char reserved_1[2];
+- unsigned short cpu_address;
+-};
+-
+-struct sysinfo_1_2_2 {
+- char format;
+- char reserved_0[1];
+- unsigned short acc_offset;
+- char reserved_1[24];
+- unsigned int secondary_capability;
+- unsigned int capability;
+- unsigned short cpus_total;
+- unsigned short cpus_configured;
+- unsigned short cpus_standby;
+- unsigned short cpus_reserved;
+- unsigned short adjustment[0];
+-};
+-
+-struct sysinfo_1_2_2_extension {
+- unsigned int alt_capability;
+- unsigned short alt_adjustment[0];
+-};
+-
+-struct sysinfo_2_2_1 {
+- char reserved_0[80];
+- char sequence[16];
+- char plant[4];
+- unsigned short cpu_id;
+- unsigned short cpu_address;
+-};
+-
+-struct sysinfo_2_2_2 {
+- char reserved_0[32];
+- unsigned short lpar_number;
+- char reserved_1;
+- unsigned char characteristics;
+- unsigned short cpus_total;
+- unsigned short cpus_configured;
+- unsigned short cpus_standby;
+- unsigned short cpus_reserved;
+- char name[8];
+- unsigned int caf;
+- char reserved_2[16];
+- unsigned short cpus_dedicated;
+- unsigned short cpus_shared;
+-};
+-
+-#define LPAR_CHAR_DEDICATED (1 << 7)
+-#define LPAR_CHAR_SHARED (1 << 6)
+-#define LPAR_CHAR_LIMITED (1 << 5)
+-
+-struct sysinfo_3_2_2 {
+- char reserved_0[31];
+- unsigned char count;
+- struct {
+- char reserved_0[4];
+- unsigned short cpus_total;
+- unsigned short cpus_configured;
+- unsigned short cpus_standby;
+- unsigned short cpus_reserved;
+- char name[8];
+- unsigned int caf;
+- char cpi[16];
+- char reserved_1[24];
+-
+- } vm[8];
+-};
+-
+-static inline int stsi(void *sysinfo, int fc, int sel1, int sel2)
+-{
+- register int r0 asm("0") = (fc << 28) | sel1;
+- register int r1 asm("1") = sel2;
+-
+- asm volatile(
+- " stsi 0(%2)\n"
+- "0: jz 2f\n"
+- "1: lhi %0,%3\n"
+- "2:\n"
+- EX_TABLE(0b,1b)
+- : "+d" (r0) : "d" (r1), "a" (sysinfo), "K" (-ENOSYS)
+- : "cc", "memory" );
+- return r0;
+-}
+-
+ static inline int stsi_0(void)
+ {
+ int rc = stsi (NULL, 0, 0, 0);
+@@ -133,6 +35,8 @@ static int stsi_1_1_1(struct sysinfo_1_1_1 *info, char *page, int len)
+ EBCASC(info->sequence, sizeof(info->sequence));
+ EBCASC(info->plant, sizeof(info->plant));
+ EBCASC(info->model_capacity, sizeof(info->model_capacity));
++ EBCASC(info->model_perm_cap, sizeof(info->model_perm_cap));
++ EBCASC(info->model_temp_cap, sizeof(info->model_temp_cap));
+ len += sprintf(page + len, "Manufacturer: %-16.16s\n",
+ info->manufacturer);
+ len += sprintf(page + len, "Type: %-4.4s\n",
+@@ -155,8 +59,18 @@ static int stsi_1_1_1(struct sysinfo_1_1_1 *info, char *page, int len)
+ info->sequence);
+ len += sprintf(page + len, "Plant: %-4.4s\n",
+ info->plant);
+- len += sprintf(page + len, "Model Capacity: %-16.16s\n",
+- info->model_capacity);
++ len += sprintf(page + len, "Model Capacity: %-16.16s %08u\n",
++ info->model_capacity, *(u32 *) info->model_cap_rating);
++ if (info->model_perm_cap[0] != '\0')
++ len += sprintf(page + len,
++ "Model Perm. Capacity: %-16.16s %08u\n",
++ info->model_perm_cap,
++ *(u32 *) info->model_perm_cap_rating);
++ if (info->model_temp_cap[0] != '\0')
++ len += sprintf(page + len,
++ "Model Temp. Capacity: %-16.16s %08u\n",
++ info->model_temp_cap,
++ *(u32 *) info->model_temp_cap_rating);
+ return len;
+ }
+
+diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
+index b4912d1..b31faec 100644
+--- a/drivers/scsi/3w-9xxx.c
++++ b/drivers/scsi/3w-9xxx.c
+@@ -140,9 +140,10 @@ static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id);
+ /* Functions */
+
+ /* Show some statistics about the card */
+-static ssize_t twa_show_stats(struct class_device *class_dev, char *buf)
++static ssize_t twa_show_stats(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct Scsi_Host *host = class_to_shost(class_dev);
++ struct Scsi_Host *host = class_to_shost(dev);
+ TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
+ unsigned long flags = 0;
+ ssize_t len;
+@@ -184,7 +185,7 @@ static int twa_change_queue_depth(struct scsi_device *sdev, int queue_depth)
+ } /* End twa_change_queue_depth() */
+
+ /* Create sysfs 'stats' entry */
+-static struct class_device_attribute twa_host_stats_attr = {
++static struct device_attribute twa_host_stats_attr = {
+ .attr = {
+ .name = "stats",
+ .mode = S_IRUGO,
+@@ -193,7 +194,7 @@ static struct class_device_attribute twa_host_stats_attr = {
+ };
+
+ /* Host attributes initializer */
+-static struct class_device_attribute *twa_host_attrs[] = {
++static struct device_attribute *twa_host_attrs[] = {
+ &twa_host_stats_attr,
+ NULL,
+ };
+@@ -1838,12 +1839,11 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
+ if (scsi_sg_count(srb)) {
+ if ((scsi_sg_count(srb) == 1) &&
+ (scsi_bufflen(srb) < TW_MIN_SGL_LENGTH)) {
+- if (srb->sc_data_direction == DMA_TO_DEVICE || srb->sc_data_direction == DMA_BIDIRECTIONAL) {
+- struct scatterlist *sg = scsi_sglist(srb);
+- char *buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
+- memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length);
+- kunmap_atomic(buf - sg->offset, KM_IRQ0);
+- }
++ if (srb->sc_data_direction == DMA_TO_DEVICE ||
++ srb->sc_data_direction == DMA_BIDIRECTIONAL)
++ scsi_sg_copy_to_buffer(srb,
++ tw_dev->generic_buffer_virt[request_id],
++ TW_SECTOR_SIZE);
+ command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
+ command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH);
+ } else {
+@@ -1915,13 +1915,11 @@ static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int re
+ (cmd->sc_data_direction == DMA_FROM_DEVICE ||
+ cmd->sc_data_direction == DMA_BIDIRECTIONAL)) {
+ if (scsi_sg_count(cmd) == 1) {
+- struct scatterlist *sg = scsi_sglist(tw_dev->srb[request_id]);
+- char *buf;
+- unsigned long flags = 0;
++ unsigned long flags;
++ void *buf = tw_dev->generic_buffer_virt[request_id];
++
+ local_irq_save(flags);
+- buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
+- memcpy(buf, tw_dev->generic_buffer_virt[request_id], sg->length);
+- kunmap_atomic(buf - sg->offset, KM_IRQ0);
++ scsi_sg_copy_from_buffer(cmd, buf, TW_SECTOR_SIZE);
+ local_irq_restore(flags);
+ }
+ }
+@@ -2028,8 +2026,6 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
+ }
+ tw_dev = (TW_Device_Extension *)host->hostdata;
+
+- memset(tw_dev, 0, sizeof(TW_Device_Extension));
+-
+ /* Save values to device extension */
+ tw_dev->host = host;
+ tw_dev->tw_pci_dev = pdev;
+diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
+index d095321..8c22329 100644
+--- a/drivers/scsi/3w-xxxx.c
++++ b/drivers/scsi/3w-xxxx.c
+@@ -484,9 +484,10 @@ static void tw_state_request_start(TW_Device_Extension *tw_dev, int *request_id)
+ } /* End tw_state_request_start() */
+
+ /* Show some statistics about the card */
+-static ssize_t tw_show_stats(struct class_device *class_dev, char *buf)
++static ssize_t tw_show_stats(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *host = class_to_shost(class_dev);
++ struct Scsi_Host *host = class_to_shost(dev);
+ TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
+ unsigned long flags = 0;
+ ssize_t len;
+@@ -528,7 +529,7 @@ static int tw_change_queue_depth(struct scsi_device *sdev, int queue_depth)
+ } /* End tw_change_queue_depth() */
+
+ /* Create sysfs 'stats' entry */
+-static struct class_device_attribute tw_host_stats_attr = {
++static struct device_attribute tw_host_stats_attr = {
+ .attr = {
+ .name = "stats",
+ .mode = S_IRUGO,
+@@ -537,7 +538,7 @@ static struct class_device_attribute tw_host_stats_attr = {
+ };
+
+ /* Host attributes initializer */
+-static struct class_device_attribute *tw_host_attrs[] = {
++static struct device_attribute *tw_host_attrs[] = {
+ &tw_host_stats_attr,
+ NULL,
+ };
+@@ -1463,18 +1464,10 @@ static void tw_transfer_internal(TW_Device_Extension *tw_dev, int request_id,
+ void *data, unsigned int len)
+ {
+ struct scsi_cmnd *cmd = tw_dev->srb[request_id];
+- void *buf;
+- unsigned int transfer_len;
+- unsigned long flags = 0;
+- struct scatterlist *sg = scsi_sglist(cmd);
++ unsigned long flags;
+
+ local_irq_save(flags);
+- buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
+- transfer_len = min(sg->length, len);
+-
+- memcpy(buf, data, transfer_len);
+-
+- kunmap_atomic(buf - sg->offset, KM_IRQ0);
++ scsi_sg_copy_from_buffer(cmd, data, len);
+ local_irq_restore(flags);
+ }
+
+@@ -2294,8 +2287,6 @@ static int __devinit tw_probe(struct pci_dev *pdev, const struct pci_device_id *
+ }
+ tw_dev = (TW_Device_Extension *)host->hostdata;
+
+- memset(tw_dev, 0, sizeof(TW_Device_Extension));
+-
+ /* Save values to device extension */
+ tw_dev->host = host;
+ tw_dev->tw_pci_dev = pdev;
+diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
+index 4d3ebb1..2d689af 100644
+--- a/drivers/scsi/BusLogic.c
++++ b/drivers/scsi/BusLogic.c
+@@ -896,7 +896,7 @@ static int __init BusLogic_InitializeFlashPointProbeInfo(struct BusLogic_HostAda
+ IRQ_Channel = PCI_Device->irq;
+ IO_Address = BaseAddress0 = pci_resource_start(PCI_Device, 0);
+ PCI_Address = BaseAddress1 = pci_resource_start(PCI_Device, 1);
+-#ifndef CONFIG_SCSI_OMIT_FLASHPOINT
++#ifdef CONFIG_SCSI_FLASHPOINT
+ if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM) {
+ BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " "FlashPoint Host Adapter\n", NULL, BaseAddress0);
+ BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, Bus, Device, IO_Address);
+@@ -1006,6 +1006,9 @@ static void __init BusLogic_InitializeProbeInfoList(struct BusLogic_HostAdapter
+ }
+
+
++#else
++#define BusLogic_InitializeProbeInfoList(adapter) \
++ BusLogic_InitializeProbeInfoListISA(adapter)
+ #endif /* CONFIG_PCI */
+
+
+diff --git a/drivers/scsi/BusLogic.h b/drivers/scsi/BusLogic.h
+index bfbfb5c..73f237a 100644
+--- a/drivers/scsi/BusLogic.h
++++ b/drivers/scsi/BusLogic.h
+@@ -34,23 +34,6 @@
+ #endif
+
+ /*
+- FlashPoint support is only available for the Intel x86 Architecture with
+- CONFIG_PCI set.
+-*/
+-
+-#ifndef __i386__
+-#undef CONFIG_SCSI_OMIT_FLASHPOINT
+-#define CONFIG_SCSI_OMIT_FLASHPOINT
+-#endif
+-
+-#ifndef CONFIG_PCI
+-#undef CONFIG_SCSI_OMIT_FLASHPOINT
+-#define CONFIG_SCSI_OMIT_FLASHPOINT
+-#define BusLogic_InitializeProbeInfoListISA BusLogic_InitializeProbeInfoList
+-#endif
+-
+-
+-/*
+ Define the maximum number of BusLogic Host Adapters supported by this driver.
+ */
+
+@@ -178,7 +161,7 @@ static int BusLogic_HostAdapterAddressCount[3] = { 0, BusLogic_MultiMasterAddres
+ Define macros for testing the Host Adapter Type.
+ */
+
+-#ifndef CONFIG_SCSI_OMIT_FLASHPOINT
++#ifdef CONFIG_SCSI_FLASHPOINT
+
+ #define BusLogic_MultiMasterHostAdapterP(HostAdapter) \
+ (HostAdapter->HostAdapterType == BusLogic_MultiMaster)
+@@ -871,7 +854,7 @@ struct BusLogic_CCB {
+ void (*CallbackFunction) (struct BusLogic_CCB *); /* Bytes 40-43 */
+ u32 BaseAddress; /* Bytes 44-47 */
+ enum BusLogic_CompletionCode CompletionCode; /* Byte 48 */
+-#ifndef CONFIG_SCSI_OMIT_FLASHPOINT
++#ifdef CONFIG_SCSI_FLASHPOINT
+ unsigned char:8; /* Byte 49 */
+ unsigned short OS_Flags; /* Bytes 50-51 */
+ unsigned char Private[48]; /* Bytes 52-99 */
+diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c
+index 1c90781..b374e45 100644
+--- a/drivers/scsi/FlashPoint.c
++++ b/drivers/scsi/FlashPoint.c
+@@ -16,7 +16,7 @@
+ */
+
+
+-#ifndef CONFIG_SCSI_OMIT_FLASHPOINT
++#ifdef CONFIG_SCSI_FLASHPOINT
+
+ #define MAX_CARDS 8
+ #undef BUSTYPE_PCI
+@@ -7626,7 +7626,7 @@ FlashPoint__HandleInterrupt(FlashPoint_CardHandle_T CardHandle)
+ #define FlashPoint_InterruptPending FlashPoint__InterruptPending
+ #define FlashPoint_HandleInterrupt FlashPoint__HandleInterrupt
+
+-#else /* CONFIG_SCSI_OMIT_FLASHPOINT */
++#else /* !CONFIG_SCSI_FLASHPOINT */
+
+ /*
+ Define prototypes for the FlashPoint SCCB Manager Functions.
+@@ -7641,4 +7641,4 @@ extern bool FlashPoint_InterruptPending(FlashPoint_CardHandle_T);
+ extern int FlashPoint_HandleInterrupt(FlashPoint_CardHandle_T);
+ extern void FlashPoint_ReleaseHostAdapter(FlashPoint_CardHandle_T);
+
+-#endif /* CONFIG_SCSI_OMIT_FLASHPOINT */
++#endif /* CONFIG_SCSI_FLASHPOINT */
+diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
+index b9d3740..7f78e3e 100644
+--- a/drivers/scsi/Kconfig
++++ b/drivers/scsi/Kconfig
+@@ -588,18 +588,20 @@ config SCSI_BUSLOGIC
+ <http://www.tldp.org/docs.html#howto>, and the files
+ <file:Documentation/scsi/BusLogic.txt> and
+ <file:Documentation/scsi/FlashPoint.txt> for more information.
++ Note that support for FlashPoint is only available for 32-bit
++ x86 configurations.
+
+ To compile this driver as a module, choose M here: the
+ module will be called BusLogic.
+
+-config SCSI_OMIT_FLASHPOINT
+- bool "Omit FlashPoint support"
+- depends on SCSI_BUSLOGIC
++config SCSI_FLASHPOINT
++ bool "FlashPoint support"
++ depends on SCSI_BUSLOGIC && PCI && X86_32
+ help
+- This option allows you to omit the FlashPoint support from the
++ This option allows you to add FlashPoint support to the
+ BusLogic SCSI driver. The FlashPoint SCCB Manager code is
+- substantial, so users of MultiMaster Host Adapters may wish to omit
+- it.
++ substantial, so users of MultiMaster Host Adapters may not
++ wish to include it.
+
+ config SCSI_DMX3191D
+ tristate "DMX3191D SCSI support"
+diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c
+index 5ac3a3e..07d572f 100644
+--- a/drivers/scsi/a2091.c
++++ b/drivers/scsi/a2091.c
+@@ -179,6 +179,9 @@ int __init a2091_detect(struct scsi_host_template *tpnt)
+ DMA(instance)->DAWR = DAWR_A2091;
+ regs.SASR = &(DMA(instance)->SASR);
+ regs.SCMD = &(DMA(instance)->SCMD);
++ HDATA(instance)->no_sync = 0xff;
++ HDATA(instance)->fast = 0;
++ HDATA(instance)->dma_mode = CTRL_DMA;
+ wd33c93_init(instance, regs, dma_setup, dma_stop, WD33C93_FS_8_10);
+ request_irq(IRQ_AMIGA_PORTS, a2091_intr, IRQF_SHARED, "A2091 SCSI",
+ instance);
+diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c
+index 3aeec96..8b449d8 100644
+--- a/drivers/scsi/a3000.c
++++ b/drivers/scsi/a3000.c
+@@ -178,6 +178,9 @@ int __init a3000_detect(struct scsi_host_template *tpnt)
+ DMA(a3000_host)->DAWR = DAWR_A3000;
+ regs.SASR = &(DMA(a3000_host)->SASR);
+ regs.SCMD = &(DMA(a3000_host)->SCMD);
++ HDATA(a3000_host)->no_sync = 0xff;
++ HDATA(a3000_host)->fast = 0;
++ HDATA(a3000_host)->dma_mode = CTRL_DMA;
+ wd33c93_init(a3000_host, regs, dma_setup, dma_stop, WD33C93_FS_12_15);
+ if (request_irq(IRQ_AMIGA_PORTS, a3000_intr, IRQF_SHARED, "A3000 SCSI",
+ a3000_intr))
+diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
+index c05092f..460d402 100644
+--- a/drivers/scsi/aacraid/aachba.c
++++ b/drivers/scsi/aacraid/aachba.c
+@@ -31,7 +31,6 @@
+ #include <linux/slab.h>
+ #include <linux/completion.h>
+ #include <linux/blkdev.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ #include <linux/highmem.h> /* For flush_kernel_dcache_page */
+
+@@ -205,7 +204,7 @@ MODULE_PARM_DESC(check_interval, "Interval in seconds between adapter health"
+
+ int aac_check_reset = 1;
+ module_param_named(check_reset, aac_check_reset, int, S_IRUGO|S_IWUSR);
+-MODULE_PARM_DESC(aac_check_reset, "If adapter fails health check, reset the"
++MODULE_PARM_DESC(check_reset, "If adapter fails health check, reset the"
+ " adapter. a value of -1 forces the reset to adapters programmed to"
+ " ignore it.");
+
+@@ -379,24 +378,6 @@ int aac_get_containers(struct aac_dev *dev)
+ return status;
+ }
+
+-static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigned int offset, unsigned int len)
+-{
+- void *buf;
+- int transfer_len;
+- struct scatterlist *sg = scsi_sglist(scsicmd);
+-
+- buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
+- transfer_len = min(sg->length, len + offset);
+-
+- transfer_len -= offset;
+- if (buf && transfer_len > 0)
+- memcpy(buf + offset, data, transfer_len);
+-
+- flush_kernel_dcache_page(kmap_atomic_to_page(buf - sg->offset));
+- kunmap_atomic(buf - sg->offset, KM_IRQ0);
+-
+-}
+-
+ static void get_container_name_callback(void *context, struct fib * fibptr)
+ {
+ struct aac_get_name_resp * get_name_reply;
+@@ -419,14 +400,17 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
+ while (*sp == ' ')
+ ++sp;
+ if (*sp) {
++ struct inquiry_data inq;
+ char d[sizeof(((struct inquiry_data *)NULL)->inqd_pid)];
+ int count = sizeof(d);
+ char *dp = d;
+ do {
+ *dp++ = (*sp) ? *sp++ : ' ';
+ } while (--count > 0);
+- aac_internal_transfer(scsicmd, d,
+- offsetof(struct inquiry_data, inqd_pid), sizeof(d));
++
++ scsi_sg_copy_to_buffer(scsicmd, &inq, sizeof(inq));
++ memcpy(inq.inqd_pid, d, sizeof(d));
++ scsi_sg_copy_from_buffer(scsicmd, &inq, sizeof(inq));
+ }
+ }
+
+@@ -811,7 +795,7 @@ static void get_container_serial_callback(void *context, struct fib * fibptr)
+ sp[2] = 0;
+ sp[3] = snprintf(sp+4, sizeof(sp)-4, "%08X",
+ le32_to_cpu(get_serial_reply->uid));
+- aac_internal_transfer(scsicmd, sp, 0, sizeof(sp));
++ scsi_sg_copy_from_buffer(scsicmd, sp, sizeof(sp));
+ }
+
+ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
+@@ -1331,7 +1315,7 @@ int aac_get_adapter_info(struct aac_dev* dev)
+ tmp>>24,(tmp>>16)&0xff,tmp&0xff,
+ le32_to_cpu(dev->adapter_info.biosbuild));
+ buffer[0] = '\0';
+- if (aac_show_serial_number(
++ if (aac_get_serial_number(
+ shost_to_class(dev->scsi_host_ptr), buffer))
+ printk(KERN_INFO "%s%d: serial %s",
+ dev->name, dev->id, buffer);
+@@ -1986,8 +1970,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ arr[4] = 0x0;
+ arr[5] = 0x80;
+ arr[1] = scsicmd->cmnd[2];
+- aac_internal_transfer(scsicmd, &inq_data, 0,
+- sizeof(inq_data));
++ scsi_sg_copy_from_buffer(scsicmd, &inq_data,
++ sizeof(inq_data));
+ scsicmd->result = DID_OK << 16 |
+ COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
+ } else if (scsicmd->cmnd[2] == 0x80) {
+@@ -1995,8 +1979,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ arr[3] = setinqserial(dev, &arr[4],
+ scmd_id(scsicmd));
+ arr[1] = scsicmd->cmnd[2];
+- aac_internal_transfer(scsicmd, &inq_data, 0,
+- sizeof(inq_data));
++ scsi_sg_copy_from_buffer(scsicmd, &inq_data,
++ sizeof(inq_data));
+ return aac_get_container_serial(scsicmd);
+ } else {
+ /* vpd page not implemented */
+@@ -2027,7 +2011,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ if (cid == host->this_id) {
+ setinqstr(dev, (void *) (inq_data.inqd_vid), ARRAY_SIZE(container_types));
+ inq_data.inqd_pdt = INQD_PDT_PROC; /* Processor device */
+- aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
++ scsi_sg_copy_from_buffer(scsicmd, &inq_data,
++ sizeof(inq_data));
+ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
+ scsicmd->scsi_done(scsicmd);
+ return 0;
+@@ -2036,7 +2021,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ return -1;
+ setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type);
+ inq_data.inqd_pdt = INQD_PDT_DA; /* Direct/random access device */
+- aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
++ scsi_sg_copy_from_buffer(scsicmd, &inq_data, sizeof(inq_data));
+ return aac_get_container_name(scsicmd);
+ }
+ case SERVICE_ACTION_IN:
+@@ -2047,6 +2032,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ {
+ u64 capacity;
+ char cp[13];
++ unsigned int alloc_len;
+
+ dprintk((KERN_DEBUG "READ CAPACITY_16 command.\n"));
+ capacity = fsa_dev_ptr[cid].size - 1;
+@@ -2063,18 +2049,16 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ cp[10] = 2;
+ cp[11] = 0;
+ cp[12] = 0;
+- aac_internal_transfer(scsicmd, cp, 0,
+- min_t(size_t, scsicmd->cmnd[13], sizeof(cp)));
+- if (sizeof(cp) < scsicmd->cmnd[13]) {
+- unsigned int len, offset = sizeof(cp);
+
+- memset(cp, 0, offset);
+- do {
+- len = min_t(size_t, scsicmd->cmnd[13] - offset,
+- sizeof(cp));
+- aac_internal_transfer(scsicmd, cp, offset, len);
+- } while ((offset += len) < scsicmd->cmnd[13]);
+- }
++ alloc_len = ((scsicmd->cmnd[10] << 24)
++ + (scsicmd->cmnd[11] << 16)
++ + (scsicmd->cmnd[12] << 8) + scsicmd->cmnd[13]);
++
++ alloc_len = min_t(size_t, alloc_len, sizeof(cp));
++ scsi_sg_copy_from_buffer(scsicmd, cp, alloc_len);
++ if (alloc_len < scsi_bufflen(scsicmd))
++ scsi_set_resid(scsicmd,
++ scsi_bufflen(scsicmd) - alloc_len);
+
+ /* Do not cache partition table for arrays */
+ scsicmd->device->removable = 1;
+@@ -2104,7 +2088,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ cp[5] = 0;
+ cp[6] = 2;
+ cp[7] = 0;
+- aac_internal_transfer(scsicmd, cp, 0, sizeof(cp));
++ scsi_sg_copy_from_buffer(scsicmd, cp, sizeof(cp));
+ /* Do not cache partition table for arrays */
+ scsicmd->device->removable = 1;
+
+@@ -2139,7 +2123,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ if (mode_buf_length > scsicmd->cmnd[4])
+ mode_buf_length = scsicmd->cmnd[4];
+ }
+- aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length);
++ scsi_sg_copy_from_buffer(scsicmd, mode_buf, mode_buf_length);
+ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
+ scsicmd->scsi_done(scsicmd);
+
+@@ -2174,7 +2158,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
+ if (mode_buf_length > scsicmd->cmnd[8])
+ mode_buf_length = scsicmd->cmnd[8];
+ }
+- aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length);
++ scsi_sg_copy_from_buffer(scsicmd, mode_buf, mode_buf_length);
+
+ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
+ scsicmd->scsi_done(scsicmd);
+diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
+index ace0b75..113ca9c 100644
+--- a/drivers/scsi/aacraid/aacraid.h
++++ b/drivers/scsi/aacraid/aacraid.h
+@@ -1850,9 +1850,9 @@ int aac_get_containers(struct aac_dev *dev);
+ int aac_scsi_cmd(struct scsi_cmnd *cmd);
+ int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg);
+ #ifndef shost_to_class
+-#define shost_to_class(shost) &shost->shost_classdev
++#define shost_to_class(shost) &shost->shost_dev
+ #endif
+-ssize_t aac_show_serial_number(struct class_device *class_dev, char *buf);
++ssize_t aac_get_serial_number(struct device *dev, char *buf);
+ int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg);
+ int aac_rx_init(struct aac_dev *dev);
+ int aac_rkt_init(struct aac_dev *dev);
+diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
+index abef051..5fd83de 100644
+--- a/drivers/scsi/aacraid/commctrl.c
++++ b/drivers/scsi/aacraid/commctrl.c
+@@ -39,7 +39,7 @@
+ #include <linux/blkdev.h>
+ #include <linux/delay.h> /* ssleep prototype */
+ #include <linux/kthread.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+ #include <asm/uaccess.h>
+
+ #include "aacraid.h"
+diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
+index 89cc8b7..294a802 100644
+--- a/drivers/scsi/aacraid/comminit.c
++++ b/drivers/scsi/aacraid/comminit.c
+@@ -39,7 +39,6 @@
+ #include <linux/completion.h>
+ #include <linux/mm.h>
+ #include <scsi/scsi_host.h>
+-#include <asm/semaphore.h>
+
+ #include "aacraid.h"
+
+diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
+index 4743449..ef67816 100644
+--- a/drivers/scsi/aacraid/commsup.c
++++ b/drivers/scsi/aacraid/commsup.c
+@@ -41,11 +41,11 @@
+ #include <linux/delay.h>
+ #include <linux/kthread.h>
+ #include <linux/interrupt.h>
++#include <linux/semaphore.h>
+ #include <scsi/scsi.h>
+ #include <scsi/scsi_host.h>
+ #include <scsi/scsi_device.h>
+ #include <scsi/scsi_cmnd.h>
+-#include <asm/semaphore.h>
+
+ #include "aacraid.h"
+
+@@ -515,10 +515,12 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
+ }
+ udelay(5);
+ }
+- } else
+- (void)down_interruptible(&fibptr->event_wait);
++ } else if (down_interruptible(&fibptr->event_wait) == 0) {
++ fibptr->done = 2;
++ up(&fibptr->event_wait);
++ }
+ spin_lock_irqsave(&fibptr->event_lock, flags);
+- if (fibptr->done == 0) {
++ if ((fibptr->done == 0) || (fibptr->done == 2)) {
+ fibptr->done = 2; /* Tell interrupt we aborted */
+ spin_unlock_irqrestore(&fibptr->event_lock, flags);
+ return -EINTR;
+@@ -594,7 +596,7 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid)
+ if (le32_to_cpu(*q->headers.consumer) >= q->entries)
+ *q->headers.consumer = cpu_to_le32(1);
+ else
+- *q->headers.consumer = cpu_to_le32(le32_to_cpu(*q->headers.consumer)+1);
++ le32_add_cpu(q->headers.consumer, 1);
+
+ if (wasfull) {
+ switch (qid) {
+diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c
+index d1163de..933f208 100644
+--- a/drivers/scsi/aacraid/dpcsup.c
++++ b/drivers/scsi/aacraid/dpcsup.c
+@@ -36,7 +36,7 @@
+ #include <linux/slab.h>
+ #include <linux/completion.h>
+ #include <linux/blkdev.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+
+ #include "aacraid.h"
+
+diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
+index ae5f74f..c109f63 100644
+--- a/drivers/scsi/aacraid/linit.c
++++ b/drivers/scsi/aacraid/linit.c
+@@ -42,7 +42,6 @@
+ #include <linux/syscalls.h>
+ #include <linux/delay.h>
+ #include <linux/kthread.h>
+-#include <asm/semaphore.h>
+
+ #include <scsi/scsi.h>
+ #include <scsi/scsi_cmnd.h>
+@@ -755,10 +754,10 @@ static long aac_compat_cfg_ioctl(struct file *file, unsigned cmd, unsigned long
+ }
+ #endif
+
+-static ssize_t aac_show_model(struct class_device *class_dev,
+- char *buf)
++static ssize_t aac_show_model(struct device *device,
++ struct device_attribute *attr, char *buf)
+ {
+- struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
++ struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
+ int len;
+
+ if (dev->supplement_adapter_info.AdapterTypeText[0]) {
+@@ -774,10 +773,10 @@ static ssize_t aac_show_model(struct class_device *class_dev,
+ return len;
+ }
+
+-static ssize_t aac_show_vendor(struct class_device *class_dev,
+- char *buf)
++static ssize_t aac_show_vendor(struct device *device,
++ struct device_attribute *attr, char *buf)
+ {
+- struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
++ struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
+ int len;
+
+ if (dev->supplement_adapter_info.AdapterTypeText[0]) {
+@@ -793,10 +792,11 @@ static ssize_t aac_show_vendor(struct class_device *class_dev,
+ return len;
+ }
+
+-static ssize_t aac_show_flags(struct class_device *class_dev, char *buf)
++static ssize_t aac_show_flags(struct device *cdev,
++ struct device_attribute *attr, char *buf)
+ {
+ int len = 0;
+- struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
++ struct aac_dev *dev = (struct aac_dev*)class_to_shost(cdev)->hostdata;
+
+ if (nblank(dprintk(x)))
+ len = snprintf(buf, PAGE_SIZE, "dprintk\n");
+@@ -812,10 +812,11 @@ static ssize_t aac_show_flags(struct class_device *class_dev, char *buf)
+ return len;
+ }
+
+-static ssize_t aac_show_kernel_version(struct class_device *class_dev,
+- char *buf)
++static ssize_t aac_show_kernel_version(struct device *device,
++ struct device_attribute *attr,
++ char *buf)
+ {
+- struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
++ struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
+ int len, tmp;
+
+ tmp = le32_to_cpu(dev->adapter_info.kernelrev);
+@@ -825,10 +826,11 @@ static ssize_t aac_show_kernel_version(struct class_device *class_dev,
+ return len;
+ }
+
+-static ssize_t aac_show_monitor_version(struct class_device *class_dev,
+- char *buf)
++static ssize_t aac_show_monitor_version(struct device *device,
++ struct device_attribute *attr,
++ char *buf)
+ {
+- struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
++ struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
+ int len, tmp;
+
+ tmp = le32_to_cpu(dev->adapter_info.monitorrev);
+@@ -838,10 +840,11 @@ static ssize_t aac_show_monitor_version(struct class_device *class_dev,
+ return len;
+ }
+
+-static ssize_t aac_show_bios_version(struct class_device *class_dev,
+- char *buf)
++static ssize_t aac_show_bios_version(struct device *device,
++ struct device_attribute *attr,
++ char *buf)
+ {
+- struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
++ struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
+ int len, tmp;
+
+ tmp = le32_to_cpu(dev->adapter_info.biosrev);
+@@ -851,9 +854,10 @@ static ssize_t aac_show_bios_version(struct class_device *class_dev,
+ return len;
+ }
+
+-ssize_t aac_show_serial_number(struct class_device *class_dev, char *buf)
++ssize_t aac_show_serial_number(struct device *device,
++ struct device_attribute *attr, char *buf)
+ {
+- struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
++ struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
+ int len = 0;
+
+ if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0)
+@@ -869,35 +873,39 @@ ssize_t aac_show_serial_number(struct class_device *class_dev, char *buf)
+ return len;
+ }
+
+-static ssize_t aac_show_max_channel(struct class_device *class_dev, char *buf)
++static ssize_t aac_show_max_channel(struct device *device,
++ struct device_attribute *attr, char *buf)
+ {
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+- class_to_shost(class_dev)->max_channel);
++ class_to_shost(device)->max_channel);
+ }
+
+-static ssize_t aac_show_max_id(struct class_device *class_dev, char *buf)
++static ssize_t aac_show_max_id(struct device *device,
++ struct device_attribute *attr, char *buf)
+ {
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+- class_to_shost(class_dev)->max_id);
++ class_to_shost(device)->max_id);
+ }
+
+-static ssize_t aac_store_reset_adapter(struct class_device *class_dev,
+- const char *buf, size_t count)
++static ssize_t aac_store_reset_adapter(struct device *device,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+ int retval = -EACCES;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return retval;
+- retval = aac_reset_adapter((struct aac_dev*)class_to_shost(class_dev)->hostdata, buf[0] == '!');
++ retval = aac_reset_adapter((struct aac_dev*)class_to_shost(device)->hostdata, buf[0] == '!');
+ if (retval >= 0)
+ retval = count;
+ return retval;
+ }
+
+-static ssize_t aac_show_reset_adapter(struct class_device *class_dev,
+- char *buf)
++static ssize_t aac_show_reset_adapter(struct device *device,
++ struct device_attribute *attr,
++ char *buf)
+ {
+- struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
++ struct aac_dev *dev = (struct aac_dev*)class_to_shost(device)->hostdata;
+ int len, tmp;
+
+ tmp = aac_adapter_check_health(dev);
+@@ -907,70 +915,70 @@ static ssize_t aac_show_reset_adapter(struct class_device *class_dev,
+ return len;
+ }
+
+-static struct class_device_attribute aac_model = {
++static struct device_attribute aac_model = {
+ .attr = {
+ .name = "model",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_model,
+ };
+-static struct class_device_attribute aac_vendor = {
++static struct device_attribute aac_vendor = {
+ .attr = {
+ .name = "vendor",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_vendor,
+ };
+-static struct class_device_attribute aac_flags = {
++static struct device_attribute aac_flags = {
+ .attr = {
+ .name = "flags",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_flags,
+ };
+-static struct class_device_attribute aac_kernel_version = {
++static struct device_attribute aac_kernel_version = {
+ .attr = {
+ .name = "hba_kernel_version",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_kernel_version,
+ };
+-static struct class_device_attribute aac_monitor_version = {
++static struct device_attribute aac_monitor_version = {
+ .attr = {
+ .name = "hba_monitor_version",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_monitor_version,
+ };
+-static struct class_device_attribute aac_bios_version = {
++static struct device_attribute aac_bios_version = {
+ .attr = {
+ .name = "hba_bios_version",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_bios_version,
+ };
+-static struct class_device_attribute aac_serial_number = {
++static struct device_attribute aac_serial_number = {
+ .attr = {
+ .name = "serial_number",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_serial_number,
+ };
+-static struct class_device_attribute aac_max_channel = {
++static struct device_attribute aac_max_channel = {
+ .attr = {
+ .name = "max_channel",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_max_channel,
+ };
+-static struct class_device_attribute aac_max_id = {
++static struct device_attribute aac_max_id = {
+ .attr = {
+ .name = "max_id",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_max_id,
+ };
+-static struct class_device_attribute aac_reset = {
++static struct device_attribute aac_reset = {
+ .attr = {
+ .name = "reset_host",
+ .mode = S_IWUSR|S_IRUGO,
+@@ -979,7 +987,7 @@ static struct class_device_attribute aac_reset = {
+ .show = aac_show_reset_adapter,
+ };
+
+-static struct class_device_attribute *aac_attrs[] = {
++static struct device_attribute *aac_attrs[] = {
+ &aac_model,
+ &aac_vendor,
+ &aac_flags,
+@@ -993,6 +1001,10 @@ static struct class_device_attribute *aac_attrs[] = {
+ NULL
+ };
+
++ssize_t aac_get_serial_number(struct device *device, char *buf)
++{
++ return aac_show_serial_number(device, &aac_serial_number, buf);
++}
+
+ static const struct file_operations aac_cfg_fops = {
+ .owner = THIS_MODULE,
+diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
+index 1f18b83..073208b 100644
+--- a/drivers/scsi/aacraid/rx.c
++++ b/drivers/scsi/aacraid/rx.c
+@@ -39,7 +39,6 @@
+ #include <linux/completion.h>
+ #include <linux/time.h>
+ #include <linux/interrupt.h>
+-#include <asm/semaphore.h>
+
+ #include <scsi/scsi_host.h>
+
+diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
+index cfc3410..fc1a557 100644
+--- a/drivers/scsi/aacraid/sa.c
++++ b/drivers/scsi/aacraid/sa.c
+@@ -39,7 +39,6 @@
+ #include <linux/completion.h>
+ #include <linux/time.h>
+ #include <linux/interrupt.h>
+-#include <asm/semaphore.h>
+
+ #include <scsi/scsi_host.h>
+
+diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
+index 72fccd9..0081aa3 100644
+--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
++++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
+@@ -1413,6 +1413,10 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
+ unsigned long flags;
+ int nseg;
+
++ nseg = scsi_dma_map(cmd);
++ if (nseg < 0)
++ return SCSI_MLQUEUE_HOST_BUSY;
++
+ ahd_lock(ahd, &flags);
+
+ /*
+@@ -1430,6 +1434,7 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
+ if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
+ ahd->flags |= AHD_RESOURCE_SHORTAGE;
+ ahd_unlock(ahd, &flags);
++ scsi_dma_unmap(cmd);
+ return SCSI_MLQUEUE_HOST_BUSY;
+ }
+
+@@ -1485,8 +1490,6 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
+ ahd_set_sense_residual(scb, 0);
+ scb->sg_count = 0;
+
+- nseg = scsi_dma_map(cmd);
+- BUG_ON(nseg < 0);
+ if (nseg > 0) {
+ void *sg = scb->sg_list;
+ struct scatterlist *cur_seg;
+diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
+index 282aff6..42ad48e 100644
+--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
++++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
+@@ -1398,12 +1398,18 @@ ahc_linux_run_command(struct ahc_softc *ahc, struct ahc_linux_device *dev,
+ return SCSI_MLQUEUE_DEVICE_BUSY;
+ }
+
++ nseg = scsi_dma_map(cmd);
++ if (nseg < 0)
++ return SCSI_MLQUEUE_HOST_BUSY;
++
+ /*
+ * Get an scb to use.
+ */
+ scb = ahc_get_scb(ahc);
+- if (!scb)
++ if (!scb) {
++ scsi_dma_unmap(cmd);
+ return SCSI_MLQUEUE_HOST_BUSY;
++ }
+
+ scb->io_ctx = cmd;
+ scb->platform_data->dev = dev;
+@@ -1464,8 +1470,6 @@ ahc_linux_run_command(struct ahc_softc *ahc, struct ahc_linux_device *dev,
+ ahc_set_sense_residual(scb, 0);
+ scb->sg_count = 0;
+
+- nseg = scsi_dma_map(cmd);
+- BUG_ON(nseg < 0);
+ if (nseg > 0) {
+ struct ahc_dma_seg *sg;
+ struct scatterlist *cur_seg;
+diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y b/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
+index 6066998..702e2db 100644
+--- a/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
++++ b/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
+@@ -1837,7 +1837,7 @@ type_check(symbol_t *symbol, expression_t *expression, int opcode)
+ int and_op;
+
+ and_op = FALSE;
+- if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ || AIC_OP_JZ)
++ if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ || opcode == AIC_OP_JZ)
+ and_op = TRUE;
+
+ /*
+diff --git a/drivers/scsi/aic94xx/aic94xx.h b/drivers/scsi/aic94xx/aic94xx.h
+index eb8efdc..2ef459e 100644
+--- a/drivers/scsi/aic94xx/aic94xx.h
++++ b/drivers/scsi/aic94xx/aic94xx.h
+@@ -58,7 +58,6 @@
+
+ extern struct kmem_cache *asd_dma_token_cache;
+ extern struct kmem_cache *asd_ascb_cache;
+-extern char sas_addr_str[2*SAS_ADDR_SIZE + 1];
+
+ static inline void asd_stringify_sas_addr(char *p, const u8 *sas_addr)
+ {
+@@ -68,21 +67,6 @@ static inline void asd_stringify_sas_addr(char *p, const u8 *sas_addr)
+ *p = '\0';
+ }
+
+-static inline void asd_destringify_sas_addr(u8 *sas_addr, const char *p)
+-{
+- int i;
+- for (i = 0; i < SAS_ADDR_SIZE; i++) {
+- u8 h, l;
+- if (!*p)
+- break;
+- h = isdigit(*p) ? *p-'0' : *p-'A'+10;
+- p++;
+- l = isdigit(*p) ? *p-'0' : *p-'A'+10;
+- p++;
+- sas_addr[i] = (h<<4) | l;
+- }
+-}
+-
+ struct asd_ha_struct;
+ struct asd_ascb;
+
+diff --git a/drivers/scsi/aic94xx/aic94xx_dev.c b/drivers/scsi/aic94xx/aic94xx_dev.c
+index 72042ca..2e2ddec 100644
+--- a/drivers/scsi/aic94xx/aic94xx_dev.c
++++ b/drivers/scsi/aic94xx/aic94xx_dev.c
+@@ -35,7 +35,7 @@
+ #define SET_DDB(_ddb, _ha) set_bit(_ddb, (_ha)->hw_prof.ddb_bitmap)
+ #define CLEAR_DDB(_ddb, _ha) clear_bit(_ddb, (_ha)->hw_prof.ddb_bitmap)
+
+-static inline int asd_get_ddb(struct asd_ha_struct *asd_ha)
++static int asd_get_ddb(struct asd_ha_struct *asd_ha)
+ {
+ int ddb, i;
+
+@@ -71,7 +71,7 @@ out:
+ #define NCQ_DATA_SCB_PTR offsetof(struct asd_ddb_stp_sata_target_port, ncq_data_scb_ptr)
+ #define ITNL_TIMEOUT offsetof(struct asd_ddb_ssp_smp_target_port, itnl_timeout)
+
+-static inline void asd_free_ddb(struct asd_ha_struct *asd_ha, int ddb)
++static void asd_free_ddb(struct asd_ha_struct *asd_ha, int ddb)
+ {
+ if (!ddb || ddb >= 0xFFFF)
+ return;
+@@ -79,7 +79,7 @@ static inline void asd_free_ddb(struct asd_ha_struct *asd_ha, int ddb)
+ CLEAR_DDB(ddb, asd_ha);
+ }
+
+-static inline void asd_set_ddb_type(struct domain_device *dev)
++static void asd_set_ddb_type(struct domain_device *dev)
+ {
+ struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;
+ int ddb = (int) (unsigned long) dev->lldd_dev;
+@@ -109,7 +109,7 @@ static int asd_init_sata_tag_ddb(struct domain_device *dev)
+ return 0;
+ }
+
+-static inline int asd_init_sata(struct domain_device *dev)
++static int asd_init_sata(struct domain_device *dev)
+ {
+ struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;
+ int ddb = (int) (unsigned long) dev->lldd_dev;
+diff --git a/drivers/scsi/aic94xx/aic94xx_dump.c b/drivers/scsi/aic94xx/aic94xx_dump.c
+index 3d8c4ff..67eeba3 100644
+--- a/drivers/scsi/aic94xx/aic94xx_dump.c
++++ b/drivers/scsi/aic94xx/aic94xx_dump.c
+@@ -738,6 +738,8 @@ static void asd_dump_lseq_state(struct asd_ha_struct *asd_ha, int lseq)
+ PRINT_LMIP_dword(asd_ha, lseq, DEV_PRES_TIMER_TERM_TS);
+ }
+
++#if 0
++
+ /**
+ * asd_dump_ddb_site -- dump a CSEQ DDB site
+ * @asd_ha: pointer to host adapter structure
+@@ -880,6 +882,8 @@ void asd_dump_scb_sites(struct asd_ha_struct *asd_ha)
+ }
+ }
+
++#endif /* 0 */
++
+ /**
+ * ads_dump_seq_state -- dump CSEQ and LSEQ states
+ * @asd_ha: pointer to host adapter structure
+@@ -922,7 +926,9 @@ void asd_dump_frame_rcvd(struct asd_phy *phy,
+ spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags);
+ }
+
+-static inline void asd_dump_scb(struct asd_ascb *ascb, int ind)
++#if 0
++
++static void asd_dump_scb(struct asd_ascb *ascb, int ind)
+ {
+ asd_printk("scb%d: vaddr: 0x%p, dma_handle: 0x%llx, next: 0x%llx, "
+ "index:%d, opcode:0x%02x\n",
+@@ -956,4 +962,6 @@ void asd_dump_scb_list(struct asd_ascb *ascb, int num)
+ }
+ }
+
++#endif /* 0 */
++
+ #endif /* ASD_DEBUG */
+diff --git a/drivers/scsi/aic94xx/aic94xx_dump.h b/drivers/scsi/aic94xx/aic94xx_dump.h
+index 0c388e7..191a753 100644
+--- a/drivers/scsi/aic94xx/aic94xx_dump.h
++++ b/drivers/scsi/aic94xx/aic94xx_dump.h
+@@ -29,24 +29,15 @@
+
+ #ifdef ASD_DEBUG
+
+-void asd_dump_ddb_0(struct asd_ha_struct *asd_ha);
+-void asd_dump_target_ddb(struct asd_ha_struct *asd_ha, u16 site_no);
+-void asd_dump_scb_sites(struct asd_ha_struct *asd_ha);
+ void asd_dump_seq_state(struct asd_ha_struct *asd_ha, u8 lseq_mask);
+ void asd_dump_frame_rcvd(struct asd_phy *phy,
+ struct done_list_struct *dl);
+-void asd_dump_scb_list(struct asd_ascb *ascb, int num);
+ #else /* ASD_DEBUG */
+
+-static inline void asd_dump_ddb_0(struct asd_ha_struct *asd_ha) { }
+-static inline void asd_dump_target_ddb(struct asd_ha_struct *asd_ha,
+- u16 site_no) { }
+-static inline void asd_dump_scb_sites(struct asd_ha_struct *asd_ha) { }
+ static inline void asd_dump_seq_state(struct asd_ha_struct *asd_ha,
+ u8 lseq_mask) { }
+ static inline void asd_dump_frame_rcvd(struct asd_phy *phy,
+ struct done_list_struct *dl) { }
+-static inline void asd_dump_scb_list(struct asd_ascb *ascb, int num) { }
+ #endif /* ASD_DEBUG */
+
+ #endif /* _AIC94XX_DUMP_H_ */
+diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c
+index 098b5f3..83a7822 100644
+--- a/drivers/scsi/aic94xx/aic94xx_hwi.c
++++ b/drivers/scsi/aic94xx/aic94xx_hwi.c
+@@ -27,6 +27,7 @@
+ #include <linux/pci.h>
+ #include <linux/delay.h>
+ #include <linux/module.h>
++#include <linux/firmware.h>
+
+ #include "aic94xx.h"
+ #include "aic94xx_reg.h"
+@@ -38,16 +39,14 @@ u32 MBAR0_SWB_SIZE;
+
+ /* ---------- Initialization ---------- */
+
+-static void asd_get_user_sas_addr(struct asd_ha_struct *asd_ha)
++static int asd_get_user_sas_addr(struct asd_ha_struct *asd_ha)
+ {
+- extern char sas_addr_str[];
+- /* If the user has specified a WWN it overrides other settings
+- */
+- if (sas_addr_str[0] != '\0')
+- asd_destringify_sas_addr(asd_ha->hw_prof.sas_addr,
+- sas_addr_str);
+- else if (asd_ha->hw_prof.sas_addr[0] != 0)
+- asd_stringify_sas_addr(sas_addr_str, asd_ha->hw_prof.sas_addr);
++ /* adapter came with a sas address */
++ if (asd_ha->hw_prof.sas_addr[0])
++ return 0;
++
++ return sas_request_addr(asd_ha->sas_ha.core.shost,
++ asd_ha->hw_prof.sas_addr);
+ }
+
+ static void asd_propagate_sas_addr(struct asd_ha_struct *asd_ha)
+@@ -251,7 +250,7 @@ static int asd_init_scbs(struct asd_ha_struct *asd_ha)
+ return 0;
+ }
+
+-static inline void asd_get_max_scb_ddb(struct asd_ha_struct *asd_ha)
++static void asd_get_max_scb_ddb(struct asd_ha_struct *asd_ha)
+ {
+ asd_ha->hw_prof.max_scbs = asd_get_cmdctx_size(asd_ha)/ASD_SCB_SIZE;
+ asd_ha->hw_prof.max_ddbs = asd_get_devctx_size(asd_ha)/ASD_DDB_SIZE;
+@@ -657,8 +656,7 @@ int asd_init_hw(struct asd_ha_struct *asd_ha)
+
+ asd_init_ctxmem(asd_ha);
+
+- asd_get_user_sas_addr(asd_ha);
+- if (!asd_ha->hw_prof.sas_addr[0]) {
++ if (asd_get_user_sas_addr(asd_ha)) {
+ asd_printk("No SAS Address provided for %s\n",
+ pci_name(asd_ha->pcidev));
+ err = -ENODEV;
+@@ -773,7 +771,7 @@ static void asd_dl_tasklet_handler(unsigned long data)
+ * asd_process_donelist_isr -- schedule processing of done list entries
+ * @asd_ha: pointer to host adapter structure
+ */
+-static inline void asd_process_donelist_isr(struct asd_ha_struct *asd_ha)
++static void asd_process_donelist_isr(struct asd_ha_struct *asd_ha)
+ {
+ tasklet_schedule(&asd_ha->seq.dl_tasklet);
+ }
+@@ -782,7 +780,7 @@ static inline void asd_process_donelist_isr(struct asd_ha_struct *asd_ha)
+ * asd_com_sas_isr -- process device communication interrupt (COMINT)
+ * @asd_ha: pointer to host adapter structure
+ */
+-static inline void asd_com_sas_isr(struct asd_ha_struct *asd_ha)
++static void asd_com_sas_isr(struct asd_ha_struct *asd_ha)
+ {
+ u32 comstat = asd_read_reg_dword(asd_ha, COMSTAT);
+
+@@ -821,7 +819,7 @@ static inline void asd_com_sas_isr(struct asd_ha_struct *asd_ha)
+ asd_chip_reset(asd_ha);
+ }
+
+-static inline void asd_arp2_err(struct asd_ha_struct *asd_ha, u32 dchstatus)
++static void asd_arp2_err(struct asd_ha_struct *asd_ha, u32 dchstatus)
+ {
+ static const char *halt_code[256] = {
+ "UNEXPECTED_INTERRUPT0",
+@@ -908,7 +906,7 @@ static inline void asd_arp2_err(struct asd_ha_struct *asd_ha, u32 dchstatus)
+ * asd_dch_sas_isr -- process device channel interrupt (DEVINT)
+ * @asd_ha: pointer to host adapter structure
+ */
+-static inline void asd_dch_sas_isr(struct asd_ha_struct *asd_ha)
++static void asd_dch_sas_isr(struct asd_ha_struct *asd_ha)
+ {
+ u32 dchstatus = asd_read_reg_dword(asd_ha, DCHSTATUS);
+
+@@ -923,7 +921,7 @@ static inline void asd_dch_sas_isr(struct asd_ha_struct *asd_ha)
+ * ads_rbi_exsi_isr -- process external system interface interrupt (INITERR)
+ * @asd_ha: pointer to host adapter structure
+ */
+-static inline void asd_rbi_exsi_isr(struct asd_ha_struct *asd_ha)
++static void asd_rbi_exsi_isr(struct asd_ha_struct *asd_ha)
+ {
+ u32 stat0r = asd_read_reg_dword(asd_ha, ASISTAT0R);
+
+@@ -971,7 +969,7 @@ static inline void asd_rbi_exsi_isr(struct asd_ha_struct *asd_ha)
+ *
+ * Asserted on PCIX errors: target abort, etc.
+ */
+-static inline void asd_hst_pcix_isr(struct asd_ha_struct *asd_ha)
++static void asd_hst_pcix_isr(struct asd_ha_struct *asd_ha)
+ {
+ u16 status;
+ u32 pcix_status;
+@@ -1044,8 +1042,8 @@ irqreturn_t asd_hw_isr(int irq, void *dev_id)
+
+ /* ---------- SCB handling ---------- */
+
+-static inline struct asd_ascb *asd_ascb_alloc(struct asd_ha_struct *asd_ha,
+- gfp_t gfp_flags)
++static struct asd_ascb *asd_ascb_alloc(struct asd_ha_struct *asd_ha,
++ gfp_t gfp_flags)
+ {
+ extern struct kmem_cache *asd_ascb_cache;
+ struct asd_seq_data *seq = &asd_ha->seq;
+@@ -1144,8 +1142,8 @@ struct asd_ascb *asd_ascb_alloc_list(struct asd_ha_struct
+ *
+ * LOCKING: called with the pending list lock held.
+ */
+-static inline void asd_swap_head_scb(struct asd_ha_struct *asd_ha,
+- struct asd_ascb *ascb)
++static void asd_swap_head_scb(struct asd_ha_struct *asd_ha,
++ struct asd_ascb *ascb)
+ {
+ struct asd_seq_data *seq = &asd_ha->seq;
+ struct asd_ascb *last = list_entry(ascb->list.prev,
+@@ -1171,7 +1169,7 @@ static inline void asd_swap_head_scb(struct asd_ha_struct *asd_ha,
+ * intended to be called from asd_post_ascb_list(), just prior to
+ * posting the SCBs to the sequencer.
+ */
+-static inline void asd_start_scb_timers(struct list_head *list)
++static void asd_start_scb_timers(struct list_head *list)
+ {
+ struct asd_ascb *ascb;
+ list_for_each_entry(ascb, list, list) {
+diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.h b/drivers/scsi/aic94xx/aic94xx_hwi.h
+index abc7575..8c1c282 100644
+--- a/drivers/scsi/aic94xx/aic94xx_hwi.h
++++ b/drivers/scsi/aic94xx/aic94xx_hwi.h
+@@ -391,8 +391,6 @@ void asd_build_control_phy(struct asd_ascb *ascb, int phy_id, u8 subfunc);
+ void asd_control_led(struct asd_ha_struct *asd_ha, int phy_id, int op);
+ void asd_turn_led(struct asd_ha_struct *asd_ha, int phy_id, int op);
+ int asd_enable_phys(struct asd_ha_struct *asd_ha, const u8 phy_mask);
+-void asd_build_initiate_link_adm_task(struct asd_ascb *ascb, int phy_id,
+- u8 subfunc);
+
+ void asd_ascb_timedout(unsigned long data);
+ int asd_chip_hardrst(struct asd_ha_struct *asd_ha);
+diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
+index 88d1e73..90f5e0a 100644
+--- a/drivers/scsi/aic94xx/aic94xx_init.c
++++ b/drivers/scsi/aic94xx/aic94xx_init.c
+@@ -56,8 +56,6 @@ MODULE_PARM_DESC(collector, "\n"
+ "\tThe aic94xx SAS LLDD supports both modes.\n"
+ "\tDefault: 0 (Direct Mode).\n");
+
+-char sas_addr_str[2*SAS_ADDR_SIZE + 1] = "";
+-
+ static struct scsi_transport_template *aic94xx_transport_template;
+ static int asd_scan_finished(struct Scsi_Host *, unsigned long);
+ static void asd_scan_start(struct Scsi_Host *);
+@@ -547,7 +545,7 @@ static struct asd_pcidev_struct {
+ },
+ };
+
+-static inline int asd_create_ha_caches(struct asd_ha_struct *asd_ha)
++static int asd_create_ha_caches(struct asd_ha_struct *asd_ha)
+ {
+ asd_ha->scb_pool = dma_pool_create(ASD_DRIVER_NAME "_scb_pool",
+ &asd_ha->pcidev->dev,
+@@ -565,7 +563,7 @@ static inline int asd_create_ha_caches(struct asd_ha_struct *asd_ha)
+ * asd_free_edbs -- free empty data buffers
+ * asd_ha: pointer to host adapter structure
+ */
+-static inline void asd_free_edbs(struct asd_ha_struct *asd_ha)
++static void asd_free_edbs(struct asd_ha_struct *asd_ha)
+ {
+ struct asd_seq_data *seq = &asd_ha->seq;
+ int i;
+@@ -576,7 +574,7 @@ static inline void asd_free_edbs(struct asd_ha_struct *asd_ha)
+ seq->edb_arr = NULL;
+ }
+
+-static inline void asd_free_escbs(struct asd_ha_struct *asd_ha)
++static void asd_free_escbs(struct asd_ha_struct *asd_ha)
+ {
+ struct asd_seq_data *seq = &asd_ha->seq;
+ int i;
+@@ -591,7 +589,7 @@ static inline void asd_free_escbs(struct asd_ha_struct *asd_ha)
+ seq->escb_arr = NULL;
+ }
+
+-static inline void asd_destroy_ha_caches(struct asd_ha_struct *asd_ha)
++static void asd_destroy_ha_caches(struct asd_ha_struct *asd_ha)
+ {
+ int i;
+
+diff --git a/drivers/scsi/aic94xx/aic94xx_reg.c b/drivers/scsi/aic94xx/aic94xx_reg.c
+index f210dac..56b17c2 100644
+--- a/drivers/scsi/aic94xx/aic94xx_reg.c
++++ b/drivers/scsi/aic94xx/aic94xx_reg.c
+@@ -32,8 +32,8 @@
+ * Offset comes before value to remind that the operation of
+ * this function is *offs = val.
+ */
+-static inline void asd_write_byte(struct asd_ha_struct *asd_ha,
+- unsigned long offs, u8 val)
++static void asd_write_byte(struct asd_ha_struct *asd_ha,
++ unsigned long offs, u8 val)
+ {
+ if (unlikely(asd_ha->iospace))
+ outb(val,
+@@ -43,8 +43,8 @@ static inline void asd_write_byte(struct asd_ha_struct *asd_ha,
+ wmb();
+ }
+
+-static inline void asd_write_word(struct asd_ha_struct *asd_ha,
+- unsigned long offs, u16 val)
++static void asd_write_word(struct asd_ha_struct *asd_ha,
++ unsigned long offs, u16 val)
+ {
+ if (unlikely(asd_ha->iospace))
+ outw(val,
+@@ -54,8 +54,8 @@ static inline void asd_write_word(struct asd_ha_struct *asd_ha,
+ wmb();
+ }
+
+-static inline void asd_write_dword(struct asd_ha_struct *asd_ha,
+- unsigned long offs, u32 val)
++static void asd_write_dword(struct asd_ha_struct *asd_ha,
++ unsigned long offs, u32 val)
+ {
+ if (unlikely(asd_ha->iospace))
+ outl(val,
+@@ -67,8 +67,7 @@ static inline void asd_write_dword(struct asd_ha_struct *asd_ha,
+
+ /* Reading from device address space.
+ */
+-static inline u8 asd_read_byte(struct asd_ha_struct *asd_ha,
+- unsigned long offs)
++static u8 asd_read_byte(struct asd_ha_struct *asd_ha, unsigned long offs)
+ {
+ u8 val;
+ if (unlikely(asd_ha->iospace))
+@@ -80,8 +79,8 @@ static inline u8 asd_read_byte(struct asd_ha_struct *asd_ha,
+ return val;
+ }
+
+-static inline u16 asd_read_word(struct asd_ha_struct *asd_ha,
+- unsigned long offs)
++static u16 asd_read_word(struct asd_ha_struct *asd_ha,
++ unsigned long offs)
+ {
+ u16 val;
+ if (unlikely(asd_ha->iospace))
+@@ -93,8 +92,8 @@ static inline u16 asd_read_word(struct asd_ha_struct *asd_ha,
+ return val;
+ }
+
+-static inline u32 asd_read_dword(struct asd_ha_struct *asd_ha,
+- unsigned long offs)
++static u32 asd_read_dword(struct asd_ha_struct *asd_ha,
++ unsigned long offs)
+ {
+ u32 val;
+ if (unlikely(asd_ha->iospace))
+@@ -124,22 +123,22 @@ static inline u32 asd_mem_offs_swb(void)
+ /* We know that the register wanted is in the range
+ * of the sliding window.
+ */
+-#define ASD_READ_SW(ww, type, ord) \
+-static inline type asd_read_##ww##_##ord (struct asd_ha_struct *asd_ha,\
+- u32 reg) \
+-{ \
+- struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[0]; \
+- u32 map_offs=(reg - io_handle-> ww##_base )+asd_mem_offs_##ww ();\
+- return asd_read_##ord (asd_ha, (unsigned long) map_offs); \
++#define ASD_READ_SW(ww, type, ord) \
++static type asd_read_##ww##_##ord(struct asd_ha_struct *asd_ha, \
++ u32 reg) \
++{ \
++ struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[0]; \
++ u32 map_offs = (reg - io_handle->ww##_base) + asd_mem_offs_##ww();\
++ return asd_read_##ord(asd_ha, (unsigned long)map_offs); \
+ }
+
+-#define ASD_WRITE_SW(ww, type, ord) \
+-static inline void asd_write_##ww##_##ord (struct asd_ha_struct *asd_ha,\
+- u32 reg, type val) \
+-{ \
+- struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[0]; \
+- u32 map_offs=(reg - io_handle-> ww##_base )+asd_mem_offs_##ww ();\
+- asd_write_##ord (asd_ha, (unsigned long) map_offs, val); \
++#define ASD_WRITE_SW(ww, type, ord) \
++static void asd_write_##ww##_##ord(struct asd_ha_struct *asd_ha, \
++ u32 reg, type val) \
++{ \
++ struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[0]; \
++ u32 map_offs = (reg - io_handle->ww##_base) + asd_mem_offs_##ww();\
++ asd_write_##ord(asd_ha, (unsigned long)map_offs, val); \
+ }
+
+ ASD_READ_SW(swa, u8, byte);
+@@ -186,7 +185,7 @@ ASD_WRITE_SW(swc, u32, dword);
+ * @asd_ha: pointer to host adapter structure
+ * @reg: register desired to be within range of the new window
+ */
+-static inline void asd_move_swb(struct asd_ha_struct *asd_ha, u32 reg)
++static void asd_move_swb(struct asd_ha_struct *asd_ha, u32 reg)
+ {
+ u32 base = reg & ~(MBAR0_SWB_SIZE-1);
+ pci_write_config_dword(asd_ha->pcidev, PCI_CONF_MBAR0_SWB, base);
+diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c
+index ab35050..4664331 100644
+--- a/drivers/scsi/aic94xx/aic94xx_scb.c
++++ b/drivers/scsi/aic94xx/aic94xx_scb.c
+@@ -50,7 +50,7 @@
+ | CURRENT_SPINUP_HOLD | CURRENT_GTO_TIMEOUT \
+ | CURRENT_OOB_ERROR)
+
+-static inline void get_lrate_mode(struct asd_phy *phy, u8 oob_mode)
++static void get_lrate_mode(struct asd_phy *phy, u8 oob_mode)
+ {
+ struct sas_phy *sas_phy = phy->sas_phy.phy;
+
+@@ -81,7 +81,7 @@ static inline void get_lrate_mode(struct asd_phy *phy, u8 oob_mode)
+ phy->sas_phy.oob_mode = SATA_OOB_MODE;
+ }
+
+-static inline void asd_phy_event_tasklet(struct asd_ascb *ascb,
++static void asd_phy_event_tasklet(struct asd_ascb *ascb,
+ struct done_list_struct *dl)
+ {
+ struct asd_ha_struct *asd_ha = ascb->ha;
+@@ -125,8 +125,7 @@ static inline void asd_phy_event_tasklet(struct asd_ascb *ascb,
+ }
+
+ /* If phys are enabled sparsely, this will do the right thing. */
+-static inline unsigned ord_phy(struct asd_ha_struct *asd_ha,
+- struct asd_phy *phy)
++static unsigned ord_phy(struct asd_ha_struct *asd_ha, struct asd_phy *phy)
+ {
+ u8 enabled_mask = asd_ha->hw_prof.enabled_phys;
+ int i, k = 0;
+@@ -151,7 +150,7 @@ static inline unsigned ord_phy(struct asd_ha_struct *asd_ha,
+ * LOCKING: the frame_rcvd_lock needs to be held since this parses the frame
+ * buffer.
+ */
+-static inline void asd_get_attached_sas_addr(struct asd_phy *phy, u8 *sas_addr)
++static void asd_get_attached_sas_addr(struct asd_phy *phy, u8 *sas_addr)
+ {
+ if (phy->sas_phy.frame_rcvd[0] == 0x34
+ && phy->sas_phy.oob_mode == SATA_OOB_MODE) {
+@@ -232,9 +231,9 @@ static void asd_deform_port(struct asd_ha_struct *asd_ha, struct asd_phy *phy)
+ spin_unlock_irqrestore(&asd_ha->asd_ports_lock, flags);
+ }
+
+-static inline void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb,
+- struct done_list_struct *dl,
+- int edb_id, int phy_id)
++static void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb,
++ struct done_list_struct *dl,
++ int edb_id, int phy_id)
+ {
+ unsigned long flags;
+ int edb_el = edb_id + ascb->edb_index;
+@@ -255,9 +254,9 @@ static inline void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb,
+ sas_ha->notify_port_event(&phy->sas_phy, PORTE_BYTES_DMAED);
+ }
+
+-static inline void asd_link_reset_err_tasklet(struct asd_ascb *ascb,
+- struct done_list_struct *dl,
+- int phy_id)
++static void asd_link_reset_err_tasklet(struct asd_ascb *ascb,
++ struct done_list_struct *dl,
++ int phy_id)
+ {
+ struct asd_ha_struct *asd_ha = ascb->ha;
+ struct sas_ha_struct *sas_ha = &asd_ha->sas_ha;
+@@ -308,9 +307,9 @@ out:
+ ;
+ }
+
+-static inline void asd_primitive_rcvd_tasklet(struct asd_ascb *ascb,
+- struct done_list_struct *dl,
+- int phy_id)
++static void asd_primitive_rcvd_tasklet(struct asd_ascb *ascb,
++ struct done_list_struct *dl,
++ int phy_id)
+ {
+ unsigned long flags;
+ struct sas_ha_struct *sas_ha = &ascb->ha->sas_ha;
+@@ -715,7 +714,7 @@ out:
+ asd_ascb_free(ascb);
+ }
+
+-static inline void set_speed_mask(u8 *speed_mask, struct asd_phy_desc *pd)
++static void set_speed_mask(u8 *speed_mask, struct asd_phy_desc *pd)
+ {
+ /* disable all speeds, then enable defaults */
+ *speed_mask = SAS_SPEED_60_DIS | SAS_SPEED_30_DIS | SAS_SPEED_15_DIS
+@@ -820,6 +819,8 @@ void asd_build_control_phy(struct asd_ascb *ascb, int phy_id, u8 subfunc)
+
+ /* ---------- INITIATE LINK ADM TASK ---------- */
+
++#if 0
++
+ static void link_adm_tasklet_complete(struct asd_ascb *ascb,
+ struct done_list_struct *dl)
+ {
+@@ -852,6 +853,8 @@ void asd_build_initiate_link_adm_task(struct asd_ascb *ascb, int phy_id,
+ ascb->tasklet_complete = link_adm_tasklet_complete;
+ }
+
++#endif /* 0 */
++
+ /* ---------- SCB timer ---------- */
+
+ /**
+diff --git a/drivers/scsi/aic94xx/aic94xx_sds.c b/drivers/scsi/aic94xx/aic94xx_sds.c
+index 2a4c933..4446e3d 100644
+--- a/drivers/scsi/aic94xx/aic94xx_sds.c
++++ b/drivers/scsi/aic94xx/aic94xx_sds.c
+@@ -590,8 +590,8 @@ static int asd_reset_flash(struct asd_ha_struct *asd_ha)
+ return err;
+ }
+
+-static inline int asd_read_flash_seg(struct asd_ha_struct *asd_ha,
+- void *buffer, u32 offs, int size)
++static int asd_read_flash_seg(struct asd_ha_struct *asd_ha,
++ void *buffer, u32 offs, int size)
+ {
+ asd_read_reg_string(asd_ha, buffer, asd_ha->hw_prof.flash.bar+offs,
+ size);
+diff --git a/drivers/scsi/aic94xx/aic94xx_seq.c b/drivers/scsi/aic94xx/aic94xx_seq.c
+index c750fbf..f4272ac 100644
+--- a/drivers/scsi/aic94xx/aic94xx_seq.c
++++ b/drivers/scsi/aic94xx/aic94xx_seq.c
+@@ -60,7 +60,7 @@ static u16 last_scb_site_no;
+ *
+ * Return 0 on success, negative on failure.
+ */
+-int asd_pause_cseq(struct asd_ha_struct *asd_ha)
++static int asd_pause_cseq(struct asd_ha_struct *asd_ha)
+ {
+ int count = PAUSE_TRIES;
+ u32 arp2ctl;
+@@ -87,7 +87,7 @@ int asd_pause_cseq(struct asd_ha_struct *asd_ha)
+ *
+ * Return 0 on success, negative on error.
+ */
+-int asd_unpause_cseq(struct asd_ha_struct *asd_ha)
++static int asd_unpause_cseq(struct asd_ha_struct *asd_ha)
+ {
+ u32 arp2ctl;
+ int count = PAUSE_TRIES;
+@@ -115,7 +115,7 @@ int asd_unpause_cseq(struct asd_ha_struct *asd_ha)
+ *
+ * Return 0 on success, negative on error.
+ */
+-static inline int asd_seq_pause_lseq(struct asd_ha_struct *asd_ha, int lseq)
++static int asd_seq_pause_lseq(struct asd_ha_struct *asd_ha, int lseq)
+ {
+ u32 arp2ctl;
+ int count = PAUSE_TRIES;
+@@ -143,7 +143,7 @@ static inline int asd_seq_pause_lseq(struct asd_ha_struct *asd_ha, int lseq)
+ *
+ * Return 0 on success, negative on failure.
+ */
+-int asd_pause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask)
++static int asd_pause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask)
+ {
+ int lseq;
+ int err = 0;
+@@ -164,7 +164,7 @@ int asd_pause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask)
+ *
+ * Return 0 on success, negative on error.
+ */
+-static inline int asd_seq_unpause_lseq(struct asd_ha_struct *asd_ha, int lseq)
++static int asd_seq_unpause_lseq(struct asd_ha_struct *asd_ha, int lseq)
+ {
+ u32 arp2ctl;
+ int count = PAUSE_TRIES;
+@@ -186,27 +186,6 @@ static inline int asd_seq_unpause_lseq(struct asd_ha_struct *asd_ha, int lseq)
+ }
+
+
+-/**
+- * asd_unpause_lseq - unpause the link sequencer(s)
+- * @asd_ha: pointer to host adapter structure
+- * @lseq_mask: mask of link sequencers of interest
+- *
+- * Return 0 on success, negative on failure.
+- */
+-int asd_unpause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask)
+-{
+- int lseq;
+- int err = 0;
+-
+- for_each_sequencer(lseq_mask, lseq_mask, lseq) {
+- err = asd_seq_unpause_lseq(asd_ha, lseq);
+- if (err)
+- return err;
+- }
+-
+- return err;
+-}
+-
+ /* ---------- Downloading CSEQ/LSEQ microcode ---------- */
+
+ static int asd_verify_cseq(struct asd_ha_struct *asd_ha, const u8 *_prog,
+diff --git a/drivers/scsi/aic94xx/aic94xx_seq.h b/drivers/scsi/aic94xx/aic94xx_seq.h
+index 2ea6a0d..ad787c5 100644
+--- a/drivers/scsi/aic94xx/aic94xx_seq.h
++++ b/drivers/scsi/aic94xx/aic94xx_seq.h
+@@ -58,10 +58,6 @@ struct sequencer_file_header {
+ } __attribute__((packed));
+
+ #ifdef __KERNEL__
+-int asd_pause_cseq(struct asd_ha_struct *asd_ha);
+-int asd_unpause_cseq(struct asd_ha_struct *asd_ha);
+-int asd_pause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask);
+-int asd_unpause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask);
+ int asd_init_seqs(struct asd_ha_struct *asd_ha);
+ int asd_start_seqs(struct asd_ha_struct *asd_ha);
+ int asd_release_firmware(void);
+diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c
+index 008df9a..326765c 100644
+--- a/drivers/scsi/aic94xx/aic94xx_task.c
++++ b/drivers/scsi/aic94xx/aic94xx_task.c
+@@ -33,7 +33,7 @@ static void asd_unbuild_ata_ascb(struct asd_ascb *a);
+ static void asd_unbuild_smp_ascb(struct asd_ascb *a);
+ static void asd_unbuild_ssp_ascb(struct asd_ascb *a);
+
+-static inline void asd_can_dequeue(struct asd_ha_struct *asd_ha, int num)
++static void asd_can_dequeue(struct asd_ha_struct *asd_ha, int num)
+ {
+ unsigned long flags;
+
+@@ -51,9 +51,9 @@ static const u8 data_dir_flags[] = {
+ [PCI_DMA_NONE] = DATA_DIR_NONE, /* NO TRANSFER */
+ };
+
+-static inline int asd_map_scatterlist(struct sas_task *task,
+- struct sg_el *sg_arr,
+- gfp_t gfp_flags)
++static int asd_map_scatterlist(struct sas_task *task,
++ struct sg_el *sg_arr,
++ gfp_t gfp_flags)
+ {
+ struct asd_ascb *ascb = task->lldd_task;
+ struct asd_ha_struct *asd_ha = ascb->ha;
+@@ -131,7 +131,7 @@ err_unmap:
+ return res;
+ }
+
+-static inline void asd_unmap_scatterlist(struct asd_ascb *ascb)
++static void asd_unmap_scatterlist(struct asd_ascb *ascb)
+ {
+ struct asd_ha_struct *asd_ha = ascb->ha;
+ struct sas_task *task = ascb->uldd_task;
+@@ -527,7 +527,7 @@ static void asd_unbuild_ssp_ascb(struct asd_ascb *a)
+
+ /* ---------- Execute Task ---------- */
+
+-static inline int asd_can_queue(struct asd_ha_struct *asd_ha, int num)
++static int asd_can_queue(struct asd_ha_struct *asd_ha, int num)
+ {
+ int res = 0;
+ unsigned long flags;
+diff --git a/drivers/scsi/aic94xx/aic94xx_tmf.c b/drivers/scsi/aic94xx/aic94xx_tmf.c
+index b9ac8f7..633ff40 100644
+--- a/drivers/scsi/aic94xx/aic94xx_tmf.c
++++ b/drivers/scsi/aic94xx/aic94xx_tmf.c
+@@ -336,7 +336,7 @@ static void asd_tmf_tasklet_complete(struct asd_ascb *ascb,
+ asd_ascb_free(ascb);
+ }
+
+-static inline int asd_clear_nexus(struct sas_task *task)
++static int asd_clear_nexus(struct sas_task *task)
+ {
+ int res = TMF_RESP_FUNC_FAILED;
+ int leftover;
+diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h
+index 3288be2..ab646e5 100644
+--- a/drivers/scsi/arcmsr/arcmsr.h
++++ b/drivers/scsi/arcmsr/arcmsr.h
+@@ -44,7 +44,7 @@
+ */
+ #include <linux/interrupt.h>
+
+-struct class_device_attribute;
++struct device_attribute;
+ /*The limit of outstanding scsi command that firmware can handle*/
+ #define ARCMSR_MAX_OUTSTANDING_CMD 256
+ #define ARCMSR_MAX_FREECCB_NUM 320
+@@ -556,6 +556,6 @@ struct SENSE_DATA
+ extern void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *);
+ extern void arcmsr_iop_message_read(struct AdapterControlBlock *);
+ extern struct QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *);
+-extern struct class_device_attribute *arcmsr_host_attrs[];
++extern struct device_attribute *arcmsr_host_attrs[];
+ extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *);
+ void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb);
+diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c
+index 7d7b0a5..69f8346 100644
+--- a/drivers/scsi/arcmsr/arcmsr_attr.c
++++ b/drivers/scsi/arcmsr/arcmsr_attr.c
+@@ -57,15 +57,15 @@
+ #include <scsi/scsi_transport.h>
+ #include "arcmsr.h"
+
+-struct class_device_attribute *arcmsr_host_attrs[];
++struct device_attribute *arcmsr_host_attrs[];
+
+ static ssize_t arcmsr_sysfs_iop_message_read(struct kobject *kobj,
+ struct bin_attribute *bin,
+ char *buf, loff_t off,
+ size_t count)
+ {
+- struct class_device *cdev = container_of(kobj,struct class_device,kobj);
+- struct Scsi_Host *host = class_to_shost(cdev);
++ struct device *dev = container_of(kobj,struct device,kobj);
++ struct Scsi_Host *host = class_to_shost(dev);
+ struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
+ uint8_t *pQbuffer,*ptmpQbuffer;
+ int32_t allxfer_len = 0;
+@@ -110,8 +110,8 @@ static ssize_t arcmsr_sysfs_iop_message_write(struct kobject *kobj,
+ char *buf, loff_t off,
+ size_t count)
+ {
+- struct class_device *cdev = container_of(kobj,struct class_device,kobj);
+- struct Scsi_Host *host = class_to_shost(cdev);
++ struct device *dev = container_of(kobj,struct device,kobj);
++ struct Scsi_Host *host = class_to_shost(dev);
+ struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
+ int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
+ uint8_t *pQbuffer, *ptmpuserbuffer;
+@@ -158,8 +158,8 @@ static ssize_t arcmsr_sysfs_iop_message_clear(struct kobject *kobj,
+ char *buf, loff_t off,
+ size_t count)
+ {
+- struct class_device *cdev = container_of(kobj,struct class_device,kobj);
+- struct Scsi_Host *host = class_to_shost(cdev);
++ struct device *dev = container_of(kobj,struct device,kobj);
++ struct Scsi_Host *host = class_to_shost(dev);
+ struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
+ uint8_t *pQbuffer;
+
+@@ -220,87 +220,104 @@ int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb)
+ struct Scsi_Host *host = acb->host;
+ int error;
+
+- error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr);
++ error = sysfs_create_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_read_attr);
+ if (error) {
+ printk(KERN_ERR "arcmsr: alloc sysfs mu_read failed\n");
+ goto error_bin_file_message_read;
+ }
+- error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr);
++ error = sysfs_create_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_write_attr);
+ if (error) {
+ printk(KERN_ERR "arcmsr: alloc sysfs mu_write failed\n");
+ goto error_bin_file_message_write;
+ }
+- error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_clear_attr);
++ error = sysfs_create_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_clear_attr);
+ if (error) {
+ printk(KERN_ERR "arcmsr: alloc sysfs mu_clear failed\n");
+ goto error_bin_file_message_clear;
+ }
+ return 0;
+ error_bin_file_message_clear:
+- sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr);
++ sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_write_attr);
+ error_bin_file_message_write:
+- sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr);
++ sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_read_attr);
+ error_bin_file_message_read:
+ return error;
+ }
+
+-void
+-arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb) {
++void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb)
++{
+ struct Scsi_Host *host = acb->host;
+
+- sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_clear_attr);
+- sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr);
+- sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr);
++ sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_clear_attr);
++ sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_write_attr);
++ sysfs_remove_bin_file(&host->shost_dev.kobj, &arcmsr_sysfs_message_read_attr);
+ }
+
+
+ static ssize_t
+-arcmsr_attr_host_driver_version(struct class_device *cdev, char *buf) {
++arcmsr_attr_host_driver_version(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
+ return snprintf(buf, PAGE_SIZE,
+ "%s\n",
+ ARCMSR_DRIVER_VERSION);
+ }
+
+ static ssize_t
+-arcmsr_attr_host_driver_posted_cmd(struct class_device *cdev, char *buf) {
+- struct Scsi_Host *host = class_to_shost(cdev);
+- struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_driver_posted_cmd(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *host = class_to_shost(dev);
++ struct AdapterControlBlock *acb =
++ (struct AdapterControlBlock *) host->hostdata;
+ return snprintf(buf, PAGE_SIZE,
+ "%4d\n",
+ atomic_read(&acb->ccboutstandingcount));
+ }
+
+ static ssize_t
+-arcmsr_attr_host_driver_reset(struct class_device *cdev, char *buf) {
+- struct Scsi_Host *host = class_to_shost(cdev);
+- struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_driver_reset(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *host = class_to_shost(dev);
++ struct AdapterControlBlock *acb =
++ (struct AdapterControlBlock *) host->hostdata;
+ return snprintf(buf, PAGE_SIZE,
+ "%4d\n",
+ acb->num_resets);
+ }
+
+ static ssize_t
+-arcmsr_attr_host_driver_abort(struct class_device *cdev, char *buf) {
+- struct Scsi_Host *host = class_to_shost(cdev);
+- struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_driver_abort(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *host = class_to_shost(dev);
++ struct AdapterControlBlock *acb =
++ (struct AdapterControlBlock *) host->hostdata;
+ return snprintf(buf, PAGE_SIZE,
+ "%4d\n",
+ acb->num_aborts);
+ }
+
+ static ssize_t
+-arcmsr_attr_host_fw_model(struct class_device *cdev, char *buf) {
+- struct Scsi_Host *host = class_to_shost(cdev);
+- struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_fw_model(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct Scsi_Host *host = class_to_shost(dev);
++ struct AdapterControlBlock *acb =
++ (struct AdapterControlBlock *) host->hostdata;
+ return snprintf(buf, PAGE_SIZE,
+ "%s\n",
+ acb->firm_model);
+ }
+
+ static ssize_t
+-arcmsr_attr_host_fw_version(struct class_device *cdev, char *buf) {
+- struct Scsi_Host *host = class_to_shost(cdev);
+- struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_fw_version(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *host = class_to_shost(dev);
++ struct AdapterControlBlock *acb =
++ (struct AdapterControlBlock *) host->hostdata;
+
+ return snprintf(buf, PAGE_SIZE,
+ "%s\n",
+@@ -308,9 +325,12 @@ arcmsr_attr_host_fw_version(struct class_device *cdev, char *buf) {
+ }
+
+ static ssize_t
+-arcmsr_attr_host_fw_request_len(struct class_device *cdev, char *buf) {
+- struct Scsi_Host *host = class_to_shost(cdev);
+- struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_fw_request_len(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *host = class_to_shost(dev);
++ struct AdapterControlBlock *acb =
++ (struct AdapterControlBlock *) host->hostdata;
+
+ return snprintf(buf, PAGE_SIZE,
+ "%4d\n",
+@@ -318,9 +338,12 @@ arcmsr_attr_host_fw_request_len(struct class_device *cdev, char *buf) {
+ }
+
+ static ssize_t
+-arcmsr_attr_host_fw_numbers_queue(struct class_device *cdev, char *buf) {
+- struct Scsi_Host *host = class_to_shost(cdev);
+- struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_fw_numbers_queue(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *host = class_to_shost(dev);
++ struct AdapterControlBlock *acb =
++ (struct AdapterControlBlock *) host->hostdata;
+
+ return snprintf(buf, PAGE_SIZE,
+ "%4d\n",
+@@ -328,9 +351,12 @@ arcmsr_attr_host_fw_numbers_queue(struct class_device *cdev, char *buf) {
+ }
+
+ static ssize_t
+-arcmsr_attr_host_fw_sdram_size(struct class_device *cdev, char *buf) {
+- struct Scsi_Host *host = class_to_shost(cdev);
+- struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_fw_sdram_size(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *host = class_to_shost(dev);
++ struct AdapterControlBlock *acb =
++ (struct AdapterControlBlock *) host->hostdata;
+
+ return snprintf(buf, PAGE_SIZE,
+ "%4d\n",
+@@ -338,36 +364,39 @@ arcmsr_attr_host_fw_sdram_size(struct class_device *cdev, char *buf) {
+ }
+
+ static ssize_t
+-arcmsr_attr_host_fw_hd_channels(struct class_device *cdev, char *buf) {
+- struct Scsi_Host *host = class_to_shost(cdev);
+- struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
++arcmsr_attr_host_fw_hd_channels(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct Scsi_Host *host = class_to_shost(dev);
++ struct AdapterControlBlock *acb =
++ (struct AdapterControlBlock *) host->hostdata;
+
+ return snprintf(buf, PAGE_SIZE,
+ "%4d\n",
+ acb->firm_hd_channels);
+ }
+
+-static CLASS_DEVICE_ATTR(host_driver_version, S_IRUGO, arcmsr_attr_host_driver_version, NULL);
+-static CLASS_DEVICE_ATTR(host_driver_posted_cmd, S_IRUGO, arcmsr_attr_host_driver_posted_cmd, NULL);
+-static CLASS_DEVICE_ATTR(host_driver_reset, S_IRUGO, arcmsr_attr_host_driver_reset, NULL);
+-static CLASS_DEVICE_ATTR(host_driver_abort, S_IRUGO, arcmsr_attr_host_driver_abort, NULL);
+-static CLASS_DEVICE_ATTR(host_fw_model, S_IRUGO, arcmsr_attr_host_fw_model, NULL);
+-static CLASS_DEVICE_ATTR(host_fw_version, S_IRUGO, arcmsr_attr_host_fw_version, NULL);
+-static CLASS_DEVICE_ATTR(host_fw_request_len, S_IRUGO, arcmsr_attr_host_fw_request_len, NULL);
+-static CLASS_DEVICE_ATTR(host_fw_numbers_queue, S_IRUGO, arcmsr_attr_host_fw_numbers_queue, NULL);
+-static CLASS_DEVICE_ATTR(host_fw_sdram_size, S_IRUGO, arcmsr_attr_host_fw_sdram_size, NULL);
+-static CLASS_DEVICE_ATTR(host_fw_hd_channels, S_IRUGO, arcmsr_attr_host_fw_hd_channels, NULL);
+-
+-struct class_device_attribute *arcmsr_host_attrs[] = {
+- &class_device_attr_host_driver_version,
+- &class_device_attr_host_driver_posted_cmd,
+- &class_device_attr_host_driver_reset,
+- &class_device_attr_host_driver_abort,
+- &class_device_attr_host_fw_model,
+- &class_device_attr_host_fw_version,
+- &class_device_attr_host_fw_request_len,
+- &class_device_attr_host_fw_numbers_queue,
+- &class_device_attr_host_fw_sdram_size,
+- &class_device_attr_host_fw_hd_channels,
++static DEVICE_ATTR(host_driver_version, S_IRUGO, arcmsr_attr_host_driver_version, NULL);
++static DEVICE_ATTR(host_driver_posted_cmd, S_IRUGO, arcmsr_attr_host_driver_posted_cmd, NULL);
++static DEVICE_ATTR(host_driver_reset, S_IRUGO, arcmsr_attr_host_driver_reset, NULL);
++static DEVICE_ATTR(host_driver_abort, S_IRUGO, arcmsr_attr_host_driver_abort, NULL);
++static DEVICE_ATTR(host_fw_model, S_IRUGO, arcmsr_attr_host_fw_model, NULL);
++static DEVICE_ATTR(host_fw_version, S_IRUGO, arcmsr_attr_host_fw_version, NULL);
++static DEVICE_ATTR(host_fw_request_len, S_IRUGO, arcmsr_attr_host_fw_request_len, NULL);
++static DEVICE_ATTR(host_fw_numbers_queue, S_IRUGO, arcmsr_attr_host_fw_numbers_queue, NULL);
++static DEVICE_ATTR(host_fw_sdram_size, S_IRUGO, arcmsr_attr_host_fw_sdram_size, NULL);
++static DEVICE_ATTR(host_fw_hd_channels, S_IRUGO, arcmsr_attr_host_fw_hd_channels, NULL);
++
++struct device_attribute *arcmsr_host_attrs[] = {
++ &dev_attr_host_driver_version,
++ &dev_attr_host_driver_posted_cmd,
++ &dev_attr_host_driver_reset,
++ &dev_attr_host_driver_abort,
++ &dev_attr_host_fw_model,
++ &dev_attr_host_fw_version,
++ &dev_attr_host_fw_request_len,
++ &dev_attr_host_fw_numbers_queue,
++ &dev_attr_host_fw_sdram_size,
++ &dev_attr_host_fw_hd_channels,
+ NULL,
+ };
+diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c
+index 3bedf24..8e53f02 100644
+--- a/drivers/scsi/arm/acornscsi.c
++++ b/drivers/scsi/arm/acornscsi.c
+@@ -2983,7 +2983,6 @@ static struct scsi_host_template acornscsi_template = {
+ .this_id = 7,
+ .sg_tablesize = SG_ALL,
+ .cmd_per_lun = 2,
+- .unchecked_isa_dma = 0,
+ .use_clustering = DISABLE_CLUSTERING,
+ .proc_name = "acornscsi",
+ };
+diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c
+index 49d838e..a3398fe 100644
+--- a/drivers/scsi/arm/cumana_1.c
++++ b/drivers/scsi/arm/cumana_1.c
+@@ -222,7 +222,6 @@ static struct scsi_host_template cumanascsi_template = {
+ .this_id = 7,
+ .sg_tablesize = SG_ALL,
+ .cmd_per_lun = 2,
+- .unchecked_isa_dma = 0,
+ .use_clustering = DISABLE_CLUSTERING,
+ .proc_name = "CumanaSCSI-1",
+ };
+diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
+index 7aad154..75c84d7 100644
+--- a/drivers/scsi/ch.c
++++ b/drivers/scsi/ch.c
+@@ -113,7 +113,7 @@ static const struct {
+ unsigned char asc;
+ unsigned char ascq;
+ int errno;
+-} err[] = {
++} ch_err[] = {
+ /* Just filled in what looks right. Hav'nt checked any standard paper for
+ these errno assignments, so they may be wrong... */
+ {
+@@ -155,11 +155,11 @@ static int ch_find_errno(struct scsi_sense_hdr *sshdr)
+ /* Check to see if additional sense information is available */
+ if (scsi_sense_valid(sshdr) &&
+ sshdr->asc != 0) {
+- for (i = 0; err[i].errno != 0; i++) {
+- if (err[i].sense == sshdr->sense_key &&
+- err[i].asc == sshdr->asc &&
+- err[i].ascq == sshdr->ascq) {
+- errno = -err[i].errno;
++ for (i = 0; ch_err[i].errno != 0; i++) {
++ if (ch_err[i].sense == sshdr->sense_key &&
++ ch_err[i].asc == sshdr->asc &&
++ ch_err[i].ascq == sshdr->ascq) {
++ errno = -ch_err[i].errno;
+ break;
+ }
+ }
+@@ -721,8 +721,8 @@ static long ch_ioctl(struct file *file,
+ case CHIOGELEM:
+ {
+ struct changer_get_element cge;
+- u_char cmd[12];
+- u_char *buffer;
++ u_char ch_cmd[12];
++ u_char *buffer;
+ unsigned int elem;
+ int result,i;
+
+@@ -739,17 +739,18 @@ static long ch_ioctl(struct file *file,
+ mutex_lock(&ch->lock);
+
+ voltag_retry:
+- memset(cmd,0,sizeof(cmd));
+- cmd[0] = READ_ELEMENT_STATUS;
+- cmd[1] = (ch->device->lun << 5) |
++ memset(ch_cmd, 0, sizeof(ch_cmd));
++ ch_cmd[0] = READ_ELEMENT_STATUS;
++ ch_cmd[1] = (ch->device->lun << 5) |
+ (ch->voltags ? 0x10 : 0) |
+ ch_elem_to_typecode(ch,elem);
+- cmd[2] = (elem >> 8) & 0xff;
+- cmd[3] = elem & 0xff;
+- cmd[5] = 1;
+- cmd[9] = 255;
++ ch_cmd[2] = (elem >> 8) & 0xff;
++ ch_cmd[3] = elem & 0xff;
++ ch_cmd[5] = 1;
++ ch_cmd[9] = 255;
+
+- if (0 == (result = ch_do_scsi(ch, cmd, buffer, 256, DMA_FROM_DEVICE))) {
++ result = ch_do_scsi(ch, ch_cmd, buffer, 256, DMA_FROM_DEVICE);
++ if (!result) {
+ cge.cge_status = buffer[18];
+ cge.cge_flags = 0;
+ if (buffer[18] & CESTATUS_EXCEPT) {
+@@ -880,7 +881,7 @@ static long ch_ioctl_compat(struct file * file,
+ static int ch_probe(struct device *dev)
+ {
+ struct scsi_device *sd = to_scsi_device(dev);
+- struct class_device *class_dev;
++ struct device *class_dev;
+ int minor, ret = -ENOMEM;
+ scsi_changer *ch;
+
+@@ -909,11 +910,11 @@ static int ch_probe(struct device *dev)
+ ch->minor = minor;
+ sprintf(ch->name,"ch%d",ch->minor);
+
+- class_dev = class_device_create(ch_sysfs_class, NULL,
+- MKDEV(SCSI_CHANGER_MAJOR, ch->minor),
+- dev, "s%s", ch->name);
++ class_dev = device_create(ch_sysfs_class, dev,
++ MKDEV(SCSI_CHANGER_MAJOR,ch->minor),
++ "s%s", ch->name);
+ if (IS_ERR(class_dev)) {
+- printk(KERN_WARNING "ch%d: class_device_create failed\n",
++ printk(KERN_WARNING "ch%d: device_create failed\n",
+ ch->minor);
+ ret = PTR_ERR(class_dev);
+ goto remove_idr;
+@@ -944,8 +945,7 @@ static int ch_remove(struct device *dev)
+ idr_remove(&ch_index_idr, ch->minor);
+ spin_unlock(&ch_index_lock);
+
+- class_device_destroy(ch_sysfs_class,
+- MKDEV(SCSI_CHANGER_MAJOR,ch->minor));
++ device_destroy(ch_sysfs_class, MKDEV(SCSI_CHANGER_MAJOR,ch->minor));
+ kfree(ch->dt);
+ kfree(ch);
+ return 0;
+diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
+index e351db6..075e239 100644
+--- a/drivers/scsi/dc395x.c
++++ b/drivers/scsi/dc395x.c
+@@ -4761,7 +4761,6 @@ static struct scsi_host_template dc395x_driver_template = {
+ .cmd_per_lun = DC395x_MAX_CMD_PER_LUN,
+ .eh_abort_handler = dc395x_eh_abort,
+ .eh_bus_reset_handler = dc395x_eh_bus_reset,
+- .unchecked_isa_dma = 0,
+ .use_clustering = DISABLE_CLUSTERING,
+ };
+
+diff --git a/drivers/scsi/dpt/dpti_i2o.h b/drivers/scsi/dpt/dpti_i2o.h
+index 100b49b..19406ce 100644
+--- a/drivers/scsi/dpt/dpti_i2o.h
++++ b/drivers/scsi/dpt/dpti_i2o.h
+@@ -21,7 +21,6 @@
+
+ #include <linux/i2o-dev.h>
+
+-#include <asm/semaphore.h> /* Needed for MUTEX init macros */
+ #include <linux/version.h>
+ #include <linux/notifier.h>
+ #include <asm/atomic.h>
+diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c
+index b5a6092..952505c 100644
+--- a/drivers/scsi/eata_pio.c
++++ b/drivers/scsi/eata_pio.c
+@@ -815,8 +815,6 @@ static int register_pio_HBA(long base, struct get_conf *gc, struct pci_dev *pdev
+ else
+ hd->primary = 1;
+
+- sh->unchecked_isa_dma = 0; /* We can only do PIO */
+-
+ hd->next = NULL; /* build a linked list of all HBAs */
+ hd->prev = last_HBA;
+ if (hd->prev != NULL)
+diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
+index 0b2080d..c6d6e7c 100644
+--- a/drivers/scsi/gdth.c
++++ b/drivers/scsi/gdth.c
+@@ -85,10 +85,10 @@
+
+ /* The meaning of the Scsi_Pointer members in this driver is as follows:
+ * ptr: Chaining
+- * this_residual: gdth_bufflen
+- * buffer: gdth_sglist
++ * this_residual: unused
++ * buffer: unused
+ * dma_handle: unused
+- * buffers_residual: gdth_sg_count
++ * buffers_residual: unused
+ * Status: unused
+ * Message: unused
+ * have_data_in: unused
+@@ -372,47 +372,6 @@ static const struct file_operations gdth_fops = {
+ .release = gdth_close,
+ };
+
+-/*
+- * gdth scsi_command access wrappers.
+- * below 6 functions are used throughout the driver to access scsi_command's
+- * io parameters. The reason we do not use the regular accessors from
+- * scsi_cmnd.h is because of gdth_execute(). Since it is unrecommended for
+- * llds to directly set scsi_cmnd's IO members. This driver will use SCp
+- * members for IO parameters, and will copy scsi_cmnd's members to Scp
+- * members in queuecommand. For internal commands through gdth_execute()
+- * SCp's members will be set directly.
+- */
+-static inline unsigned gdth_bufflen(struct scsi_cmnd *cmd)
+-{
+- return (unsigned)cmd->SCp.this_residual;
+-}
+-
+-static inline void gdth_set_bufflen(struct scsi_cmnd *cmd, unsigned bufflen)
+-{
+- cmd->SCp.this_residual = bufflen;
+-}
+-
+-static inline unsigned gdth_sg_count(struct scsi_cmnd *cmd)
+-{
+- return (unsigned)cmd->SCp.buffers_residual;
+-}
+-
+-static inline void gdth_set_sg_count(struct scsi_cmnd *cmd, unsigned sg_count)
+-{
+- cmd->SCp.buffers_residual = sg_count;
+-}
+-
+-static inline struct scatterlist *gdth_sglist(struct scsi_cmnd *cmd)
+-{
+- return cmd->SCp.buffer;
+-}
+-
+-static inline void gdth_set_sglist(struct scsi_cmnd *cmd,
+- struct scatterlist *sglist)
+-{
+- cmd->SCp.buffer = sglist;
+-}
+-
+ #include "gdth_proc.h"
+ #include "gdth_proc.c"
+
+@@ -591,125 +550,111 @@ static int __init gdth_search_isa(ulong32 bios_adr)
+ #endif /* CONFIG_ISA */
+
+ #ifdef CONFIG_PCI
+-static void gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
+- ushort vendor, ushort dev);
++static bool gdth_pci_registered;
+
+-static int __init gdth_search_pci(gdth_pci_str *pcistr)
++static bool gdth_search_vortex(ushort device)
+ {
+- ushort device, cnt;
+-
+- TRACE(("gdth_search_pci()\n"));
+-
+- cnt = 0;
+- for (device = 0; device <= PCI_DEVICE_ID_VORTEX_GDT6555; ++device)
+- gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device);
+- for (device = PCI_DEVICE_ID_VORTEX_GDT6x17RP;
+- device <= PCI_DEVICE_ID_VORTEX_GDTMAXRP; ++device)
+- gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device);
+- gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX,
+- PCI_DEVICE_ID_VORTEX_GDTNEWRX);
+- gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX,
+- PCI_DEVICE_ID_VORTEX_GDTNEWRX2);
+- gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL,
+- PCI_DEVICE_ID_INTEL_SRC);
+- gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL,
+- PCI_DEVICE_ID_INTEL_SRC_XSCALE);
+- return cnt;
++ if (device <= PCI_DEVICE_ID_VORTEX_GDT6555)
++ return true;
++ if (device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP &&
++ device <= PCI_DEVICE_ID_VORTEX_GDTMAXRP)
++ return true;
++ if (device == PCI_DEVICE_ID_VORTEX_GDTNEWRX ||
++ device == PCI_DEVICE_ID_VORTEX_GDTNEWRX2)
++ return true;
++ return false;
+ }
+
++static int gdth_pci_probe_one(gdth_pci_str *pcistr, gdth_ha_str **ha_out);
++static int gdth_pci_init_one(struct pci_dev *pdev,
++ const struct pci_device_id *ent);
++static void gdth_pci_remove_one(struct pci_dev *pdev);
++static void gdth_remove_one(gdth_ha_str *ha);
++
+ /* Vortex only makes RAID controllers.
+ * We do not really want to specify all 550 ids here, so wildcard match.
+ */
+-static struct pci_device_id gdthtable[] __maybe_unused = {
+- {PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID},
+- {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID},
+- {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC_XSCALE,PCI_ANY_ID,PCI_ANY_ID},
+- {0}
++static const struct pci_device_id gdthtable[] = {
++ { PCI_VDEVICE(VORTEX, PCI_ANY_ID) },
++ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SRC) },
++ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SRC_XSCALE) },
++ { } /* terminate list */
++};
++MODULE_DEVICE_TABLE(pci, gdthtable);
++
++static struct pci_driver gdth_pci_driver = {
++ .name = "gdth",
++ .id_table = gdthtable,
++ .probe = gdth_pci_init_one,
++ .remove = gdth_pci_remove_one,
+ };
+-MODULE_DEVICE_TABLE(pci,gdthtable);
+
+-static void __init gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
+- ushort vendor, ushort device)
++static void gdth_pci_remove_one(struct pci_dev *pdev)
+ {
+- ulong base0, base1, base2;
+- struct pci_dev *pdev;
++ gdth_ha_str *ha = pci_get_drvdata(pdev);
++
++ pci_set_drvdata(pdev, NULL);
++
++ list_del(&ha->list);
++ gdth_remove_one(ha);
++
++ pci_disable_device(pdev);
++}
++
++static int gdth_pci_init_one(struct pci_dev *pdev,
++ const struct pci_device_id *ent)
++{
++ ushort vendor = pdev->vendor;
++ ushort device = pdev->device;
++ ulong base0, base1, base2;
++ int rc;
++ gdth_pci_str gdth_pcistr;
++ gdth_ha_str *ha = NULL;
+
+- TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n",
+- *cnt, vendor, device));
++ TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n",
++ gdth_ctr_count, vendor, device));
+
+- pdev = NULL;
+- while ((pdev = pci_get_device(vendor, device, pdev))
+- != NULL) {
+- if (pci_enable_device(pdev))
+- continue;
+- if (*cnt >= MAXHA) {
+- pci_dev_put(pdev);
+- return;
+- }
++ memset(&gdth_pcistr, 0, sizeof(gdth_pcistr));
++
++ if (vendor == PCI_VENDOR_ID_VORTEX && !gdth_search_vortex(device))
++ return -ENODEV;
++
++ rc = pci_enable_device(pdev);
++ if (rc)
++ return rc;
++
++ if (gdth_ctr_count >= MAXHA)
++ return -EBUSY;
+
+ /* GDT PCI controller found, resources are already in pdev */
+- pcistr[*cnt].pdev = pdev;
+- pcistr[*cnt].irq = pdev->irq;
++ gdth_pcistr.pdev = pdev;
+ base0 = pci_resource_flags(pdev, 0);
+ base1 = pci_resource_flags(pdev, 1);
+ base2 = pci_resource_flags(pdev, 2);
+ if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */
+ device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */
+ if (!(base0 & IORESOURCE_MEM))
+- continue;
+- pcistr[*cnt].dpmem = pci_resource_start(pdev, 0);
++ return -ENODEV;
++ gdth_pcistr.dpmem = pci_resource_start(pdev, 0);
+ } else { /* GDT6110, GDT6120, .. */
+ if (!(base0 & IORESOURCE_MEM) ||
+ !(base2 & IORESOURCE_MEM) ||
+ !(base1 & IORESOURCE_IO))
+- continue;
+- pcistr[*cnt].dpmem = pci_resource_start(pdev, 2);
+- pcistr[*cnt].io_mm = pci_resource_start(pdev, 0);
+- pcistr[*cnt].io = pci_resource_start(pdev, 1);
++ return -ENODEV;
++ gdth_pcistr.dpmem = pci_resource_start(pdev, 2);
++ gdth_pcistr.io = pci_resource_start(pdev, 1);
+ }
+ TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n",
+- pcistr[*cnt].pdev->bus->number,
+- PCI_SLOT(pcistr[*cnt].pdev->devfn),
+- pcistr[*cnt].irq, pcistr[*cnt].dpmem));
+- (*cnt)++;
+- }
+-}
++ gdth_pcistr.pdev->bus->number,
++ PCI_SLOT(gdth_pcistr.pdev->devfn),
++ gdth_pcistr.irq,
++ gdth_pcistr.dpmem));
+
+-static void __init gdth_sort_pci(gdth_pci_str *pcistr, int cnt)
+-{
+- gdth_pci_str temp;
+- int i, changed;
+-
+- TRACE(("gdth_sort_pci() cnt %d\n",cnt));
+- if (cnt == 0)
+- return;
++ rc = gdth_pci_probe_one(&gdth_pcistr, &ha);
++ if (rc)
++ return rc;
+
+- do {
+- changed = FALSE;
+- for (i = 0; i < cnt-1; ++i) {
+- if (!reverse_scan) {
+- if ((pcistr[i].pdev->bus->number > pcistr[i+1].pdev->bus->number) ||
+- (pcistr[i].pdev->bus->number == pcistr[i+1].pdev->bus->number &&
+- PCI_SLOT(pcistr[i].pdev->devfn) >
+- PCI_SLOT(pcistr[i+1].pdev->devfn))) {
+- temp = pcistr[i];
+- pcistr[i] = pcistr[i+1];
+- pcistr[i+1] = temp;
+- changed = TRUE;
+- }
+- } else {
+- if ((pcistr[i].pdev->bus->number < pcistr[i+1].pdev->bus->number) ||
+- (pcistr[i].pdev->bus->number == pcistr[i+1].pdev->bus->number &&
+- PCI_SLOT(pcistr[i].pdev->devfn) <
+- PCI_SLOT(pcistr[i+1].pdev->devfn))) {
+- temp = pcistr[i];
+- pcistr[i] = pcistr[i+1];
+- pcistr[i+1] = temp;
+- changed = TRUE;
+- }
+- }
+- }
+- } while (changed);
++ return 0;
+ }
+ #endif /* CONFIG_PCI */
+
+@@ -909,7 +854,8 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
+ #endif /* CONFIG_ISA */
+
+ #ifdef CONFIG_PCI
+-static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
++static int gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr,
++ gdth_ha_str *ha)
+ {
+ register gdt6_dpram_str __iomem *dp6_ptr;
+ register gdt6c_dpram_str __iomem *dp6c_ptr;
+@@ -921,14 +867,14 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
+
+ TRACE(("gdth_init_pci()\n"));
+
+- if (pcistr->pdev->vendor == PCI_VENDOR_ID_INTEL)
++ if (pdev->vendor == PCI_VENDOR_ID_INTEL)
+ ha->oem_id = OEM_ID_INTEL;
+ else
+ ha->oem_id = OEM_ID_ICP;
+- ha->brd_phys = (pcistr->pdev->bus->number << 8) | (pcistr->pdev->devfn & 0xf8);
+- ha->stype = (ulong32)pcistr->pdev->device;
+- ha->irq = pcistr->irq;
+- ha->pdev = pcistr->pdev;
++ ha->brd_phys = (pdev->bus->number << 8) | (pdev->devfn & 0xf8);
++ ha->stype = (ulong32)pdev->device;
++ ha->irq = pdev->irq;
++ ha->pdev = pdev;
+
+ if (ha->pdev->device <= PCI_DEVICE_ID_VORTEX_GDT6000B) { /* GDT6000/B */
+ TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
+@@ -956,8 +902,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
+ continue;
+ }
+ iounmap(ha->brd);
+- pci_write_config_dword(pcistr->pdev,
+- PCI_BASE_ADDRESS_0, i);
++ pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, i);
+ ha->brd = ioremap(i, sizeof(gdt6_dpram_str));
+ if (ha->brd == NULL) {
+ printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+@@ -1066,8 +1011,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
+ continue;
+ }
+ iounmap(ha->brd);
+- pci_write_config_dword(pcistr->pdev,
+- PCI_BASE_ADDRESS_2, i);
++ pci_write_config_dword(pdev, PCI_BASE_ADDRESS_2, i);
+ ha->brd = ioremap(i, sizeof(gdt6c_dpram_str));
+ if (ha->brd == NULL) {
+ printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+@@ -1159,16 +1103,16 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
+ }
+
+ /* manipulate config. space to enable DPMEM, start RP controller */
+- pci_read_config_word(pcistr->pdev, PCI_COMMAND, &command);
++ pci_read_config_word(pdev, PCI_COMMAND, &command);
+ command |= 6;
+- pci_write_config_word(pcistr->pdev, PCI_COMMAND, command);
+- if (pci_resource_start(pcistr->pdev, 8) == 1UL)
+- pci_resource_start(pcistr->pdev, 8) = 0UL;
++ pci_write_config_word(pdev, PCI_COMMAND, command);
++ if (pci_resource_start(pdev, 8) == 1UL)
++ pci_resource_start(pdev, 8) = 0UL;
+ i = 0xFEFF0001UL;
+- pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS, i);
++ pci_write_config_dword(pdev, PCI_ROM_ADDRESS, i);
+ gdth_delay(1);
+- pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS,
+- pci_resource_start(pcistr->pdev, 8));
++ pci_write_config_dword(pdev, PCI_ROM_ADDRESS,
++ pci_resource_start(pdev, 8));
+
+ dp6m_ptr = ha->brd;
+
+@@ -1195,8 +1139,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
+ continue;
+ }
+ iounmap(ha->brd);
+- pci_write_config_dword(pcistr->pdev,
+- PCI_BASE_ADDRESS_0, i);
++ pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, i);
+ ha->brd = ioremap(i, sizeof(gdt6m_dpram_str));
+ if (ha->brd == NULL) {
+ printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+@@ -2353,12 +2296,12 @@ static void gdth_next(gdth_ha_str *ha)
+ static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp,
+ char *buffer, ushort count)
+ {
+- ushort cpcount,i, max_sg = gdth_sg_count(scp);
++ ushort cpcount,i, max_sg = scsi_sg_count(scp);
+ ushort cpsum,cpnow;
+ struct scatterlist *sl;
+ char *address;
+
+- cpcount = min_t(ushort, count, gdth_bufflen(scp));
++ cpcount = min_t(ushort, count, scsi_bufflen(scp));
+
+ if (cpcount) {
+ cpsum=0;
+@@ -2366,7 +2309,7 @@ static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp,
+ unsigned long flags;
+ cpnow = (ushort)sl->length;
+ TRACE(("copy_internal() now %d sum %d count %d %d\n",
+- cpnow, cpsum, cpcount, gdth_bufflen(scp)));
++ cpnow, cpsum, cpcount, scsi_bufflen(scp)));
+ if (cpsum+cpnow > cpcount)
+ cpnow = cpcount - cpsum;
+ cpsum += cpnow;
+@@ -2589,10 +2532,10 @@ static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive)
+ cmdp->u.cache.BlockCnt = blockcnt;
+ }
+
+- if (gdth_bufflen(scp)) {
++ if (scsi_bufflen(scp)) {
+ cmndinfo->dma_dir = (read_write == 1 ?
+ PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
+- sgcnt = pci_map_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp),
++ sgcnt = pci_map_sg(ha->pdev, scsi_sglist(scp), scsi_sg_count(scp),
+ cmndinfo->dma_dir);
+ if (mode64) {
+ struct scatterlist *sl;
+@@ -2739,7 +2682,7 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b)
+ cmdp->u.raw64.lun = l;
+ cmdp->u.raw64.bus = b;
+ cmdp->u.raw64.priority = 0;
+- cmdp->u.raw64.sdlen = gdth_bufflen(scp);
++ cmdp->u.raw64.sdlen = scsi_bufflen(scp);
+ cmdp->u.raw64.sense_len = 16;
+ cmdp->u.raw64.sense_data = sense_paddr;
+ cmdp->u.raw64.direction =
+@@ -2756,7 +2699,7 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b)
+ cmdp->u.raw.bus = b;
+ cmdp->u.raw.priority = 0;
+ cmdp->u.raw.link_p = 0;
+- cmdp->u.raw.sdlen = gdth_bufflen(scp);
++ cmdp->u.raw.sdlen = scsi_bufflen(scp);
+ cmdp->u.raw.sense_len = 16;
+ cmdp->u.raw.sense_data = sense_paddr;
+ cmdp->u.raw.direction =
+@@ -2765,9 +2708,9 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b)
+ cmdp->u.raw.sg_ranz = 0;
+ }
+
+- if (gdth_bufflen(scp)) {
++ if (scsi_bufflen(scp)) {
+ cmndinfo->dma_dir = PCI_DMA_BIDIRECTIONAL;
+- sgcnt = pci_map_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp),
++ sgcnt = pci_map_sg(ha->pdev, scsi_sglist(scp), scsi_sg_count(scp),
+ cmndinfo->dma_dir);
+ if (mode64) {
+ struct scatterlist *sl;
+@@ -3388,8 +3331,8 @@ static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index,
+ /* retry */
+ return 2;
+ }
+- if (gdth_bufflen(scp))
+- pci_unmap_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp),
++ if (scsi_bufflen(scp))
++ pci_unmap_sg(ha->pdev, scsi_sglist(scp), scsi_sg_count(scp),
+ cmndinfo->dma_dir);
+
+ if (cmndinfo->sense_paddr)
+@@ -4031,10 +3974,6 @@ static int gdth_queuecommand(struct scsi_cmnd *scp,
+ gdth_update_timeout(scp, scp->timeout_per_command * 6);
+ cmndinfo->priority = DEFAULT_PRI;
+
+- gdth_set_bufflen(scp, scsi_bufflen(scp));
+- gdth_set_sg_count(scp, scsi_sg_count(scp));
+- gdth_set_sglist(scp, scsi_sglist(scp));
+-
+ return __gdth_queuecommand(ha, scp, cmndinfo);
+ }
+
+@@ -4955,12 +4894,16 @@ static int __init gdth_eisa_probe_one(ushort eisa_slot)
+ #endif /* CONFIG_EISA */
+
+ #ifdef CONFIG_PCI
+-static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
++static int gdth_pci_probe_one(gdth_pci_str *pcistr,
++ gdth_ha_str **ha_out)
+ {
+ struct Scsi_Host *shp;
+ gdth_ha_str *ha;
+ dma_addr_t scratch_dma_handle = 0;
+ int error, i;
++ struct pci_dev *pdev = pcistr->pdev;
++
++ *ha_out = NULL;
+
+ shp = scsi_host_alloc(&gdth_template, sizeof(gdth_ha_str));
+ if (!shp)
+@@ -4968,13 +4911,13 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
+ ha = shost_priv(shp);
+
+ error = -ENODEV;
+- if (!gdth_init_pci(&pcistr[ctr],ha))
++ if (!gdth_init_pci(pdev, pcistr, ha))
+ goto out_host_put;
+
+ /* controller found and initialized */
+ printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n",
+- pcistr[ctr].pdev->bus->number,
+- PCI_SLOT(pcistr[ctr].pdev->devfn),
++ pdev->bus->number,
++ PCI_SLOT(pdev->devfn),
+ ha->irq);
+
+ error = request_irq(ha->irq, gdth_interrupt,
+@@ -5019,7 +4962,7 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
+
+ ha->scratch_busy = FALSE;
+ ha->req_first = NULL;
+- ha->tid_cnt = pcistr[ctr].pdev->device >= 0x200 ? MAXID : MAX_HDRIVES;
++ ha->tid_cnt = pdev->device >= 0x200 ? MAXID : MAX_HDRIVES;
+ if (max_ids > 0 && max_ids < ha->tid_cnt)
+ ha->tid_cnt = max_ids;
+ for (i = 0; i < GDTH_MAXCMDS; ++i)
+@@ -5039,16 +4982,16 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
+ /* 64-bit DMA only supported from FW >= x.43 */
+ if (!(ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT) ||
+ !ha->dma64_support) {
+- if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) {
++ if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+ printk(KERN_WARNING "GDT-PCI %d: "
+ "Unable to set 32-bit DMA\n", ha->hanum);
+ goto out_free_coal_stat;
+ }
+ } else {
+ shp->max_cmd_len = 16;
+- if (!pci_set_dma_mask(pcistr[ctr].pdev, DMA_64BIT_MASK)) {
++ if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+ printk("GDT-PCI %d: 64-bit DMA enabled\n", ha->hanum);
+- } else if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) {
++ } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+ printk(KERN_WARNING "GDT-PCI %d: "
+ "Unable to set 64/32-bit DMA\n", ha->hanum);
+ goto out_free_coal_stat;
+@@ -5062,13 +5005,17 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
+ spin_lock_init(&ha->smp_lock);
+ gdth_enable_int(ha);
+
+- error = scsi_add_host(shp, &pcistr[ctr].pdev->dev);
++ error = scsi_add_host(shp, &pdev->dev);
+ if (error)
+ goto out_free_coal_stat;
+ list_add_tail(&ha->list, &gdth_instances);
+
++ pci_set_drvdata(ha->pdev, ha);
++
+ scsi_scan_host(shp);
+
++ *ha_out = ha;
++
+ return 0;
+
+ out_free_coal_stat:
+@@ -5185,16 +5132,8 @@ static int __init gdth_init(void)
+
+ #ifdef CONFIG_PCI
+ /* scanning for PCI controllers */
+- {
+- gdth_pci_str pcistr[MAXHA];
+- int cnt,ctr;
+-
+- cnt = gdth_search_pci(pcistr);
+- printk("GDT-HA: Found %d PCI Storage RAID Controllers\n", cnt);
+- gdth_sort_pci(pcistr,cnt);
+- for (ctr = 0; ctr < cnt; ++ctr)
+- gdth_pci_probe_one(pcistr, ctr);
+- }
++ if (pci_register_driver(&gdth_pci_driver) == 0)
++ gdth_pci_registered = true;
+ #endif /* CONFIG_PCI */
+
+ TRACE2(("gdth_detect() %d controller detected\n", gdth_ctr_count));
+@@ -5227,6 +5166,11 @@ static void __exit gdth_exit(void)
+ del_timer_sync(&gdth_timer);
+ #endif
+
++#ifdef CONFIG_PCI
++ if (gdth_pci_registered)
++ pci_unregister_driver(&gdth_pci_driver);
++#endif
++
+ list_for_each_entry(ha, &gdth_instances, list)
+ gdth_remove_one(ha);
+ }
+diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h
+index 26e4e92..ca92476 100644
+--- a/drivers/scsi/gdth.h
++++ b/drivers/scsi/gdth.h
+@@ -839,8 +839,6 @@ typedef struct {
+ struct pci_dev *pdev;
+ ulong dpmem; /* DPRAM address */
+ ulong io; /* IO address */
+- ulong io_mm; /* IO address mem. mapped */
+- unchar irq; /* IRQ */
+ } gdth_pci_str;
+
+
+diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c
+index 91f8522..ca73637 100644
+--- a/drivers/scsi/gvp11.c
++++ b/drivers/scsi/gvp11.c
+@@ -322,6 +322,9 @@ int __init gvp11_detect(struct scsi_host_template *tpnt)
+ */
+ regs.SASR = &(DMA(instance)->SASR);
+ regs.SCMD = &(DMA(instance)->SCMD);
++ HDATA(instance)->no_sync = 0xff;
++ HDATA(instance)->fast = 0;
++ HDATA(instance)->dma_mode = CTRL_DMA;
+ wd33c93_init(instance, regs, dma_setup, dma_stop,
+ (epc & GVP_SCSICLKMASK) ? WD33C93_FS_8_10
+ : WD33C93_FS_12_15);
+diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
+index ed7e0a1..c264a8c 100644
+--- a/drivers/scsi/hosts.c
++++ b/drivers/scsi/hosts.c
+@@ -43,14 +43,14 @@
+ static int scsi_host_next_hn; /* host_no for next new host */
+
+
+-static void scsi_host_cls_release(struct class_device *class_dev)
++static void scsi_host_cls_release(struct device *dev)
+ {
+- put_device(&class_to_shost(class_dev)->shost_gendev);
++ put_device(&class_to_shost(dev)->shost_gendev);
+ }
+
+ static struct class shost_class = {
+ .name = "scsi_host",
+- .release = scsi_host_cls_release,
++ .dev_release = scsi_host_cls_release,
+ };
+
+ /**
+@@ -174,7 +174,7 @@ void scsi_remove_host(struct Scsi_Host *shost)
+ spin_unlock_irqrestore(shost->host_lock, flags);
+
+ transport_unregister_device(&shost->shost_gendev);
+- class_device_unregister(&shost->shost_classdev);
++ device_unregister(&shost->shost_dev);
+ device_del(&shost->shost_gendev);
+ scsi_proc_hostdir_rm(shost->hostt);
+ }
+@@ -212,7 +212,7 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
+ scsi_host_set_state(shost, SHOST_RUNNING);
+ get_device(shost->shost_gendev.parent);
+
+- error = class_device_add(&shost->shost_classdev);
++ error = device_add(&shost->shost_dev);
+ if (error)
+ goto out_del_gendev;
+
+@@ -223,7 +223,7 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
+ GFP_KERNEL);
+ if (shost->shost_data == NULL) {
+ error = -ENOMEM;
+- goto out_del_classdev;
++ goto out_del_dev;
+ }
+ }
+
+@@ -250,8 +250,8 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
+ destroy_workqueue(shost->work_q);
+ out_free_shost_data:
+ kfree(shost->shost_data);
+- out_del_classdev:
+- class_device_del(&shost->shost_classdev);
++ out_del_dev:
++ device_del(&shost->shost_dev);
+ out_del_gendev:
+ device_del(&shost->shost_gendev);
+ out:
+@@ -347,7 +347,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
+ shost->unchecked_isa_dma = sht->unchecked_isa_dma;
+ shost->use_clustering = sht->use_clustering;
+ shost->ordered_tag = sht->ordered_tag;
+- shost->active_mode = sht->supported_mode;
+
+ if (sht->supported_mode == MODE_UNKNOWN)
+ /* means we didn't set it ... default to INITIATOR */
+@@ -386,11 +385,11 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
+ shost->host_no);
+ shost->shost_gendev.release = scsi_host_dev_release;
+
+- class_device_initialize(&shost->shost_classdev);
+- shost->shost_classdev.dev = &shost->shost_gendev;
+- shost->shost_classdev.class = &shost_class;
+- snprintf(shost->shost_classdev.class_id, BUS_ID_SIZE, "host%d",
+- shost->host_no);
++ device_initialize(&shost->shost_dev);
++ shost->shost_dev.parent = &shost->shost_gendev;
++ shost->shost_dev.class = &shost_class;
++ snprintf(shost->shost_dev.bus_id, BUS_ID_SIZE, "host%d",
++ shost->host_no);
+
+ shost->ehandler = kthread_run(scsi_error_handler, shost,
+ "scsi_eh_%d", shost->host_no);
+@@ -433,12 +432,12 @@ void scsi_unregister(struct Scsi_Host *shost)
+ }
+ EXPORT_SYMBOL(scsi_unregister);
+
+-static int __scsi_host_match(struct class_device *cdev, void *data)
++static int __scsi_host_match(struct device *dev, void *data)
+ {
+ struct Scsi_Host *p;
+ unsigned short *hostnum = (unsigned short *)data;
+
+- p = class_to_shost(cdev);
++ p = class_to_shost(dev);
+ return p->host_no == *hostnum;
+ }
+
+@@ -451,10 +450,10 @@ static int __scsi_host_match(struct class_device *cdev, void *data)
+ **/
+ struct Scsi_Host *scsi_host_lookup(unsigned short hostnum)
+ {
+- struct class_device *cdev;
++ struct device *cdev;
+ struct Scsi_Host *shost = ERR_PTR(-ENXIO);
+
+- cdev = class_find_child(&shost_class, &hostnum, __scsi_host_match);
++ cdev = class_find_device(&shost_class, &hostnum, __scsi_host_match);
+ if (cdev)
+ shost = scsi_host_get(class_to_shost(cdev));
+
+diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
+index ff149ad..5b7be1e 100644
+--- a/drivers/scsi/hptiop.c
++++ b/drivers/scsi/hptiop.c
+@@ -338,7 +338,8 @@ static int iop_get_config_mv(struct hptiop_hba *hba,
+ req->header.size =
+ cpu_to_le32(sizeof(struct hpt_iop_request_get_config));
+ req->header.result = cpu_to_le32(IOP_RESULT_PENDING);
+- req->header.context = cpu_to_le64(IOP_REQUEST_TYPE_GET_CONFIG<<5);
++ req->header.context = cpu_to_le32(IOP_REQUEST_TYPE_GET_CONFIG<<5);
++ req->header.context_hi32 = 0;
+
+ if (iop_send_sync_request_mv(hba, 0, 20000)) {
+ dprintk("Get config send cmd failed\n");
+@@ -392,7 +393,8 @@ static int iop_set_config_mv(struct hptiop_hba *hba,
+ req->header.size =
+ cpu_to_le32(sizeof(struct hpt_iop_request_set_config));
+ req->header.result = cpu_to_le32(IOP_RESULT_PENDING);
+- req->header.context = cpu_to_le64(IOP_REQUEST_TYPE_SET_CONFIG<<5);
++ req->header.context = cpu_to_le32(IOP_REQUEST_TYPE_SET_CONFIG<<5);
++ req->header.context_hi32 = 0;
+
+ if (iop_send_sync_request_mv(hba, 0, 20000)) {
+ dprintk("Set config send cmd failed\n");
+@@ -857,14 +859,16 @@ static int hptiop_adjust_disk_queue_depth(struct scsi_device *sdev,
+ return queue_depth;
+ }
+
+-static ssize_t hptiop_show_version(struct class_device *class_dev, char *buf)
++static ssize_t hptiop_show_version(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+ return snprintf(buf, PAGE_SIZE, "%s\n", driver_ver);
+ }
+
+-static ssize_t hptiop_show_fw_version(struct class_device *class_dev, char *buf)
++static ssize_t hptiop_show_fw_version(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct Scsi_Host *host = class_to_shost(class_dev);
++ struct Scsi_Host *host = class_to_shost(dev);
+ struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;
+
+ return snprintf(buf, PAGE_SIZE, "%d.%d.%d.%d\n",
+@@ -874,7 +878,7 @@ static ssize_t hptiop_show_fw_version(struct class_device *class_dev, char *buf)
+ hba->firmware_version & 0xff);
+ }
+
+-static struct class_device_attribute hptiop_attr_version = {
++static struct device_attribute hptiop_attr_version = {
+ .attr = {
+ .name = "driver-version",
+ .mode = S_IRUGO,
+@@ -882,7 +886,7 @@ static struct class_device_attribute hptiop_attr_version = {
+ .show = hptiop_show_version,
+ };
+
+-static struct class_device_attribute hptiop_attr_fw_version = {
++static struct device_attribute hptiop_attr_fw_version = {
+ .attr = {
+ .name = "firmware-version",
+ .mode = S_IRUGO,
+@@ -890,7 +894,7 @@ static struct class_device_attribute hptiop_attr_fw_version = {
+ .show = hptiop_show_fw_version,
+ };
+
+-static struct class_device_attribute *hptiop_attrs[] = {
++static struct device_attribute *hptiop_attrs[] = {
+ &hptiop_attr_version,
+ &hptiop_attr_fw_version,
+ NULL
+@@ -903,7 +907,6 @@ static struct scsi_host_template driver_template = {
+ .eh_device_reset_handler = hptiop_reset,
+ .eh_bus_reset_handler = hptiop_reset,
+ .info = hptiop_info,
+- .unchecked_isa_dma = 0,
+ .emulated = 0,
+ .use_clustering = ENABLE_CLUSTERING,
+ .proc_name = driver_name,
+diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
+index 78d46a9..4a922c5 100644
+--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
++++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
+@@ -1456,9 +1456,10 @@ static int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth)
+ /* ------------------------------------------------------------
+ * sysfs attributes
+ */
+-static ssize_t show_host_srp_version(struct class_device *class_dev, char *buf)
++static ssize_t show_host_srp_version(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(class_dev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct ibmvscsi_host_data *hostdata = shost_priv(shost);
+ int len;
+
+@@ -1467,7 +1468,7 @@ static ssize_t show_host_srp_version(struct class_device *class_dev, char *buf)
+ return len;
+ }
+
+-static struct class_device_attribute ibmvscsi_host_srp_version = {
++static struct device_attribute ibmvscsi_host_srp_version = {
+ .attr = {
+ .name = "srp_version",
+ .mode = S_IRUGO,
+@@ -1475,10 +1476,11 @@ static struct class_device_attribute ibmvscsi_host_srp_version = {
+ .show = show_host_srp_version,
+ };
+
+-static ssize_t show_host_partition_name(struct class_device *class_dev,
++static ssize_t show_host_partition_name(struct device *dev,
++ struct device_attribute *attr,
+ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(class_dev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct ibmvscsi_host_data *hostdata = shost_priv(shost);
+ int len;
+
+@@ -1487,7 +1489,7 @@ static ssize_t show_host_partition_name(struct class_device *class_dev,
+ return len;
+ }
+
+-static struct class_device_attribute ibmvscsi_host_partition_name = {
++static struct device_attribute ibmvscsi_host_partition_name = {
+ .attr = {
+ .name = "partition_name",
+ .mode = S_IRUGO,
+@@ -1495,10 +1497,11 @@ static struct class_device_attribute ibmvscsi_host_partition_name = {
+ .show = show_host_partition_name,
+ };
+
+-static ssize_t show_host_partition_number(struct class_device *class_dev,
++static ssize_t show_host_partition_number(struct device *dev,
++ struct device_attribute *attr,
+ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(class_dev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct ibmvscsi_host_data *hostdata = shost_priv(shost);
+ int len;
+
+@@ -1507,7 +1510,7 @@ static ssize_t show_host_partition_number(struct class_device *class_dev,
+ return len;
+ }
+
+-static struct class_device_attribute ibmvscsi_host_partition_number = {
++static struct device_attribute ibmvscsi_host_partition_number = {
+ .attr = {
+ .name = "partition_number",
+ .mode = S_IRUGO,
+@@ -1515,9 +1518,10 @@ static struct class_device_attribute ibmvscsi_host_partition_number = {
+ .show = show_host_partition_number,
+ };
+
+-static ssize_t show_host_mad_version(struct class_device *class_dev, char *buf)
++static ssize_t show_host_mad_version(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(class_dev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct ibmvscsi_host_data *hostdata = shost_priv(shost);
+ int len;
+
+@@ -1526,7 +1530,7 @@ static ssize_t show_host_mad_version(struct class_device *class_dev, char *buf)
+ return len;
+ }
+
+-static struct class_device_attribute ibmvscsi_host_mad_version = {
++static struct device_attribute ibmvscsi_host_mad_version = {
+ .attr = {
+ .name = "mad_version",
+ .mode = S_IRUGO,
+@@ -1534,9 +1538,10 @@ static struct class_device_attribute ibmvscsi_host_mad_version = {
+ .show = show_host_mad_version,
+ };
+
+-static ssize_t show_host_os_type(struct class_device *class_dev, char *buf)
++static ssize_t show_host_os_type(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(class_dev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct ibmvscsi_host_data *hostdata = shost_priv(shost);
+ int len;
+
+@@ -1544,7 +1549,7 @@ static ssize_t show_host_os_type(struct class_device *class_dev, char *buf)
+ return len;
+ }
+
+-static struct class_device_attribute ibmvscsi_host_os_type = {
++static struct device_attribute ibmvscsi_host_os_type = {
+ .attr = {
+ .name = "os_type",
+ .mode = S_IRUGO,
+@@ -1552,9 +1557,10 @@ static struct class_device_attribute ibmvscsi_host_os_type = {
+ .show = show_host_os_type,
+ };
+
+-static ssize_t show_host_config(struct class_device *class_dev, char *buf)
++static ssize_t show_host_config(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(class_dev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct ibmvscsi_host_data *hostdata = shost_priv(shost);
+
+ /* returns null-terminated host config data */
+@@ -1564,7 +1570,7 @@ static ssize_t show_host_config(struct class_device *class_dev, char *buf)
+ return 0;
+ }
+
+-static struct class_device_attribute ibmvscsi_host_config = {
++static struct device_attribute ibmvscsi_host_config = {
+ .attr = {
+ .name = "config",
+ .mode = S_IRUGO,
+@@ -1572,7 +1578,7 @@ static struct class_device_attribute ibmvscsi_host_config = {
+ .show = show_host_config,
+ };
+
+-static struct class_device_attribute *ibmvscsi_attrs[] = {
++static struct device_attribute *ibmvscsi_attrs[] = {
+ &ibmvscsi_host_srp_version,
+ &ibmvscsi_host_partition_name,
+ &ibmvscsi_host_partition_number,
+diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c
+index e5881e9..3b9514c 100644
+--- a/drivers/scsi/ibmvscsi/ibmvstgt.c
++++ b/drivers/scsi/ibmvscsi/ibmvstgt.c
+@@ -780,32 +780,35 @@ static int ibmvstgt_it_nexus_response(struct Scsi_Host *shost, u64 itn_id,
+ return 0;
+ }
+
+-static ssize_t system_id_show(struct class_device *cdev, char *buf)
++static ssize_t system_id_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+ return snprintf(buf, PAGE_SIZE, "%s\n", system_id);
+ }
+
+-static ssize_t partition_number_show(struct class_device *cdev, char *buf)
++static ssize_t partition_number_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+ return snprintf(buf, PAGE_SIZE, "%x\n", partition_number);
+ }
+
+-static ssize_t unit_address_show(struct class_device *cdev, char *buf)
++static ssize_t unit_address_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct srp_target *target = host_to_srp_target(shost);
+ struct vio_port *vport = target_to_port(target);
+ return snprintf(buf, PAGE_SIZE, "%x\n", vport->dma_dev->unit_address);
+ }
+
+-static CLASS_DEVICE_ATTR(system_id, S_IRUGO, system_id_show, NULL);
+-static CLASS_DEVICE_ATTR(partition_number, S_IRUGO, partition_number_show, NULL);
+-static CLASS_DEVICE_ATTR(unit_address, S_IRUGO, unit_address_show, NULL);
++static DEVICE_ATTR(system_id, S_IRUGO, system_id_show, NULL);
++static DEVICE_ATTR(partition_number, S_IRUGO, partition_number_show, NULL);
++static DEVICE_ATTR(unit_address, S_IRUGO, unit_address_show, NULL);
+
+-static struct class_device_attribute *ibmvstgt_attrs[] = {
+- &class_device_attr_system_id,
+- &class_device_attr_partition_number,
+- &class_device_attr_unit_address,
++static struct device_attribute *ibmvstgt_attrs[] = {
++ &dev_attr_system_id,
++ &dev_attr_partition_number,
++ &dev_attr_unit_address,
+ NULL,
+ };
+
+diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
+index 68e5c63..93c3fc2 100644
+--- a/drivers/scsi/ide-scsi.c
++++ b/drivers/scsi/ide-scsi.c
+@@ -60,31 +60,6 @@
+
+ #define IDESCSI_DEBUG_LOG 0
+
+-typedef struct idescsi_pc_s {
+- u8 c[12]; /* Actual packet bytes */
+- int request_transfer; /* Bytes to transfer */
+- int actually_transferred; /* Bytes actually transferred */
+- int buffer_size; /* Size of our data buffer */
+- struct request *rq; /* The corresponding request */
+- u8 *buffer; /* Data buffer */
+- u8 *current_position; /* Pointer into the above buffer */
+- struct scatterlist *sg; /* Scatter gather table */
+- unsigned int sg_cnt; /* Number of entries in sg */
+- int b_count; /* Bytes transferred from current entry */
+- struct scsi_cmnd *scsi_cmd; /* SCSI command */
+- void (*done)(struct scsi_cmnd *); /* Scsi completion routine */
+- unsigned long flags; /* Status/Action flags */
+- unsigned long timeout; /* Command timeout */
+-} idescsi_pc_t;
+-
+-/*
+- * Packet command status bits.
+- */
+-#define PC_DMA_IN_PROGRESS 0 /* 1 while DMA in progress */
+-#define PC_WRITING 1 /* Data direction */
+-#define PC_TIMEDOUT 3 /* command timed out */
+-#define PC_DMA_OK 4 /* Use DMA */
+-
+ /*
+ * SCSI command transformation layer
+ */
+@@ -101,14 +76,15 @@ typedef struct ide_scsi_obj {
+ struct gendisk *disk;
+ struct Scsi_Host *host;
+
+- idescsi_pc_t *pc; /* Current packet command */
++ struct ide_atapi_pc *pc; /* Current packet command */
+ unsigned long flags; /* Status/Action flags */
+ unsigned long transform; /* SCSI cmd translation layer */
+ unsigned long log; /* log flags */
+ } idescsi_scsi_t;
+
+ static DEFINE_MUTEX(idescsi_ref_mutex);
+-static int idescsi_nocd; /* Set by module param to skip cd */
++/* Set by module param to skip cd */
++static int idescsi_nocd;
+
+ #define ide_scsi_g(disk) \
+ container_of((disk)->private_data, struct ide_scsi_obj, driver)
+@@ -152,22 +128,11 @@ static inline idescsi_scsi_t *drive_to_idescsi(ide_drive_t *ide_drive)
+ */
+ #define IDESCSI_PC_RQ 90
+
+-static void idescsi_discard_data (ide_drive_t *drive, unsigned int bcount)
+-{
+- while (bcount--)
+- (void) HWIF(drive)->INB(IDE_DATA_REG);
+-}
+-
+-static void idescsi_output_zeros (ide_drive_t *drive, unsigned int bcount)
+-{
+- while (bcount--)
+- HWIF(drive)->OUTB(0, IDE_DATA_REG);
+-}
+-
+ /*
+ * PIO data transfer routines using the scatter gather table.
+ */
+-static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigned int bcount)
++static void idescsi_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
++ unsigned int bcount)
+ {
+ int count;
+ char *buf;
+@@ -200,11 +165,12 @@ static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigne
+
+ if (bcount) {
+ printk (KERN_ERR "ide-scsi: scatter gather table too small, discarding data\n");
+- idescsi_discard_data (drive, bcount);
++ ide_atapi_discard_data(drive, bcount);
+ }
+ }
+
+-static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigned int bcount)
++static void idescsi_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
++ unsigned int bcount)
+ {
+ int count;
+ char *buf;
+@@ -237,7 +203,7 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign
+
+ if (bcount) {
+ printk (KERN_ERR "ide-scsi: scatter gather table too small, padding with zeros\n");
+- idescsi_output_zeros (drive, bcount);
++ ide_atapi_write_zeros(drive, bcount);
+ }
+ }
+
+@@ -246,15 +212,16 @@ static void ide_scsi_hex_dump(u8 *data, int len)
+ print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1, data, len, 0);
+ }
+
+-static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_command)
++static int idescsi_check_condition(ide_drive_t *drive,
++ struct request *failed_cmd)
+ {
+ idescsi_scsi_t *scsi = drive_to_idescsi(drive);
+- idescsi_pc_t *pc;
++ struct ide_atapi_pc *pc;
+ struct request *rq;
+ u8 *buf;
+
+ /* stuff a sense request in front of our current request */
+- pc = kzalloc(sizeof(idescsi_pc_t), GFP_ATOMIC);
++ pc = kzalloc(sizeof(struct ide_atapi_pc), GFP_ATOMIC);
+ rq = kmalloc(sizeof(struct request), GFP_ATOMIC);
+ buf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_ATOMIC);
+ if (!pc || !rq || !buf) {
+@@ -266,14 +233,14 @@ static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_co
+ ide_init_drive_cmd(rq);
+ rq->special = (char *) pc;
+ pc->rq = rq;
+- pc->buffer = buf;
++ pc->buf = buf;
+ pc->c[0] = REQUEST_SENSE;
+- pc->c[4] = pc->request_transfer = pc->buffer_size = SCSI_SENSE_BUFFERSIZE;
++ pc->c[4] = pc->req_xfer = pc->buf_size = SCSI_SENSE_BUFFERSIZE;
+ rq->cmd_type = REQ_TYPE_SENSE;
+ pc->timeout = jiffies + WAIT_READY;
+ /* NOTE! Save the failed packet command in "rq->buffer" */
+- rq->buffer = (void *) failed_command->special;
+- pc->scsi_cmd = ((idescsi_pc_t *) failed_command->special)->scsi_cmd;
++ rq->buffer = (void *) failed_cmd->special;
++ pc->scsi_cmd = ((struct ide_atapi_pc *) failed_cmd->special)->scsi_cmd;
+ if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
+ printk ("ide-scsi: %s: queue cmd = ", drive->name);
+ ide_scsi_hex_dump(pc->c, 6);
+@@ -287,9 +254,12 @@ static int idescsi_end_request(ide_drive_t *, int, int);
+ static ide_startstop_t
+ idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
+ {
++ ide_hwif_t *hwif = drive->hwif;
++
+ if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
+ /* force an abort */
+- HWIF(drive)->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG);
++ hwif->OUTB(WIN_IDLEIMMEDIATE,
++ hwif->io_ports[IDE_COMMAND_OFFSET]);
+
+ rq->errors++;
+
+@@ -303,7 +273,7 @@ idescsi_atapi_abort(ide_drive_t *drive, struct request *rq)
+ {
+ #if IDESCSI_DEBUG_LOG
+ printk(KERN_WARNING "idescsi_atapi_abort called for %lu\n",
+- ((idescsi_pc_t *) rq->special)->scsi_cmd->serial_number);
++ ((struct ide_atapi_pc *) rq->special)->scsi_cmd->serial_number);
+ #endif
+ rq->errors |= ERROR_MAX;
+
+@@ -316,7 +286,7 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
+ {
+ idescsi_scsi_t *scsi = drive_to_idescsi(drive);
+ struct request *rq = HWGROUP(drive)->rq;
+- idescsi_pc_t *pc = (idescsi_pc_t *) rq->special;
++ struct ide_atapi_pc *pc = (struct ide_atapi_pc *) rq->special;
+ int log = test_bit(IDESCSI_LOG_CMD, &scsi->log);
+ struct Scsi_Host *host;
+ int errors = rq->errors;
+@@ -328,20 +298,23 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
+ }
+ ide_end_drive_cmd (drive, 0, 0);
+ if (blk_sense_request(rq)) {
+- idescsi_pc_t *opc = (idescsi_pc_t *) rq->buffer;
++ struct ide_atapi_pc *opc = (struct ide_atapi_pc *) rq->buffer;
+ if (log) {
+ printk ("ide-scsi: %s: wrap up check %lu, rst = ", drive->name, opc->scsi_cmd->serial_number);
+- ide_scsi_hex_dump(pc->buffer, 16);
++ ide_scsi_hex_dump(pc->buf, 16);
+ }
+- memcpy((void *) opc->scsi_cmd->sense_buffer, pc->buffer, SCSI_SENSE_BUFFERSIZE);
+- kfree(pc->buffer);
++ memcpy((void *) opc->scsi_cmd->sense_buffer, pc->buf,
++ SCSI_SENSE_BUFFERSIZE);
++ kfree(pc->buf);
+ kfree(pc);
+ kfree(rq);
+ pc = opc;
+ rq = pc->rq;
+ pc->scsi_cmd->result = (CHECK_CONDITION << 1) |
+- ((test_bit(PC_TIMEDOUT, &pc->flags)?DID_TIME_OUT:DID_OK) << 16);
+- } else if (test_bit(PC_TIMEDOUT, &pc->flags)) {
++ (((pc->flags & PC_FLAG_TIMEDOUT) ?
++ DID_TIME_OUT :
++ DID_OK) << 16);
++ } else if (pc->flags & PC_FLAG_TIMEDOUT) {
+ if (log)
+ printk (KERN_WARNING "ide-scsi: %s: timed out for %lu\n",
+ drive->name, pc->scsi_cmd->serial_number);
+@@ -370,7 +343,7 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
+ return 0;
+ }
+
+-static inline unsigned long get_timeout(idescsi_pc_t *pc)
++static inline unsigned long get_timeout(struct ide_atapi_pc *pc)
+ {
+ return max_t(unsigned long, WAIT_CMD, pc->timeout - jiffies);
+ }
+@@ -378,12 +351,12 @@ static inline unsigned long get_timeout(idescsi_pc_t *pc)
+ static int idescsi_expiry(ide_drive_t *drive)
+ {
+ idescsi_scsi_t *scsi = drive_to_idescsi(drive);
+- idescsi_pc_t *pc = scsi->pc;
++ struct ide_atapi_pc *pc = scsi->pc;
+
+ #if IDESCSI_DEBUG_LOG
+ printk(KERN_WARNING "idescsi_expiry called for %lu at %lu\n", pc->scsi_cmd->serial_number, jiffies);
+ #endif
+- set_bit(PC_TIMEDOUT, &pc->flags);
++ pc->flags |= PC_FLAG_TIMEDOUT;
+
+ return 0; /* we do not want the ide subsystem to retry */
+ }
+@@ -395,7 +368,7 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
+ {
+ idescsi_scsi_t *scsi = drive_to_idescsi(drive);
+ ide_hwif_t *hwif = drive->hwif;
+- idescsi_pc_t *pc = scsi->pc;
++ struct ide_atapi_pc *pc = scsi->pc;
+ struct request *rq = pc->rq;
+ unsigned int temp;
+ u16 bcount;
+@@ -405,7 +378,7 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
+ printk (KERN_INFO "ide-scsi: Reached idescsi_pc_intr interrupt handler\n");
+ #endif /* IDESCSI_DEBUG_LOG */
+
+- if (test_bit(PC_TIMEDOUT, &pc->flags)){
++ if (pc->flags & PC_FLAG_TIMEDOUT) {
+ #if IDESCSI_DEBUG_LOG
+ printk(KERN_WARNING "idescsi_pc_intr: got timed out packet %lu at %lu\n",
+ pc->scsi_cmd->serial_number, jiffies);
+@@ -414,11 +387,12 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
+ idescsi_end_request (drive, 1, 0);
+ return ide_stopped;
+ }
+- if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
++ if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
++ pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
+ #if IDESCSI_DEBUG_LOG
+ printk ("ide-scsi: %s: DMA complete\n", drive->name);
+ #endif /* IDESCSI_DEBUG_LOG */
+- pc->actually_transferred=pc->request_transfer;
++ pc->xferred = pc->req_xfer;
+ (void) HWIF(drive)->ide_dma_end(drive);
+ }
+
+@@ -428,42 +402,44 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
+ if ((stat & DRQ_STAT) == 0) {
+ /* No more interrupts */
+ if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
+- printk (KERN_INFO "Packet command completed, %d bytes transferred\n", pc->actually_transferred);
++ printk(KERN_INFO "Packet command completed, %d bytes"
++ " transferred\n", pc->xferred);
+ local_irq_enable_in_hardirq();
+ if (stat & ERR_STAT)
+ rq->errors++;
+ idescsi_end_request (drive, 1, 0);
+ return ide_stopped;
+ }
+- bcount = (hwif->INB(IDE_BCOUNTH_REG) << 8) |
+- hwif->INB(IDE_BCOUNTL_REG);
+- ireason = hwif->INB(IDE_IREASON_REG);
++ bcount = (hwif->INB(hwif->io_ports[IDE_BCOUNTH_OFFSET]) << 8) |
++ hwif->INB(hwif->io_ports[IDE_BCOUNTL_OFFSET]);
++ ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+
+ if (ireason & CD) {
+ printk(KERN_ERR "ide-scsi: CoD != 0 in idescsi_pc_intr\n");
+ return ide_do_reset (drive);
+ }
+ if (ireason & IO) {
+- temp = pc->actually_transferred + bcount;
+- if (temp > pc->request_transfer) {
+- if (temp > pc->buffer_size) {
++ temp = pc->xferred + bcount;
++ if (temp > pc->req_xfer) {
++ if (temp > pc->buf_size) {
+ printk(KERN_ERR "ide-scsi: The scsi wants to "
+ "send us more data than expected "
+ "- discarding data\n");
+- temp = pc->buffer_size - pc->actually_transferred;
++ temp = pc->buf_size - pc->xferred;
+ if (temp) {
+- clear_bit(PC_WRITING, &pc->flags);
++ pc->flags &= ~PC_FLAG_WRITING;
+ if (pc->sg)
+- idescsi_input_buffers(drive, pc, temp);
++ idescsi_input_buffers(drive, pc,
++ temp);
+ else
+- drive->hwif->atapi_input_bytes(drive, pc->current_position, temp);
++ drive->hwif->atapi_input_bytes(drive, pc->cur_pos, temp);
+ printk(KERN_ERR "ide-scsi: transferred"
+ " %d of %d bytes\n",
+ temp, bcount);
+ }
+- pc->actually_transferred += temp;
+- pc->current_position += temp;
+- idescsi_discard_data(drive, bcount - temp);
++ pc->xferred += temp;
++ pc->cur_pos += temp;
++ ide_atapi_discard_data(drive, bcount - temp);
+ ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry);
+ return ide_started;
+ }
+@@ -473,23 +449,23 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
+ }
+ }
+ if (ireason & IO) {
+- clear_bit(PC_WRITING, &pc->flags);
++ pc->flags &= ~PC_FLAG_WRITING;
+ if (pc->sg)
+ idescsi_input_buffers(drive, pc, bcount);
+ else
+- hwif->atapi_input_bytes(drive, pc->current_position,
++ hwif->atapi_input_bytes(drive, pc->cur_pos,
+ bcount);
+ } else {
+- set_bit(PC_WRITING, &pc->flags);
++ pc->flags |= PC_FLAG_WRITING;
+ if (pc->sg)
+ idescsi_output_buffers(drive, pc, bcount);
+ else
+- hwif->atapi_output_bytes(drive, pc->current_position,
++ hwif->atapi_output_bytes(drive, pc->cur_pos,
+ bcount);
+ }
+ /* Update the current position */
+- pc->actually_transferred += bcount;
+- pc->current_position += bcount;
++ pc->xferred += bcount;
++ pc->cur_pos += bcount;
+
+ /* And set the interrupt handler again */
+ ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry);
+@@ -500,7 +476,7 @@ static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive)
+ {
+ ide_hwif_t *hwif = drive->hwif;
+ idescsi_scsi_t *scsi = drive_to_idescsi(drive);
+- idescsi_pc_t *pc = scsi->pc;
++ struct ide_atapi_pc *pc = scsi->pc;
+ ide_startstop_t startstop;
+ u8 ireason;
+
+@@ -509,7 +485,7 @@ static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive)
+ "initiated yet DRQ isn't asserted\n");
+ return startstop;
+ }
+- ireason = hwif->INB(IDE_IREASON_REG);
++ ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+ if ((ireason & CD) == 0 || (ireason & IO)) {
+ printk(KERN_ERR "ide-scsi: (IO,CoD) != (0,1) while "
+ "issuing a packet command\n");
+@@ -520,34 +496,34 @@ static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive)
+ ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry);
+ /* Send the actual packet */
+ drive->hwif->atapi_output_bytes(drive, scsi->pc->c, 12);
+- if (test_bit (PC_DMA_OK, &pc->flags)) {
+- set_bit (PC_DMA_IN_PROGRESS, &pc->flags);
++ if (pc->flags & PC_FLAG_DMA_OK) {
++ pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
+ hwif->dma_start(drive);
+ }
+ return ide_started;
+ }
+
+-static inline int idescsi_set_direction(idescsi_pc_t *pc)
++static inline int idescsi_set_direction(struct ide_atapi_pc *pc)
+ {
+ switch (pc->c[0]) {
+ case READ_6: case READ_10: case READ_12:
+- clear_bit(PC_WRITING, &pc->flags);
++ pc->flags &= ~PC_FLAG_WRITING;
+ return 0;
+ case WRITE_6: case WRITE_10: case WRITE_12:
+- set_bit(PC_WRITING, &pc->flags);
++ pc->flags |= PC_FLAG_WRITING;
+ return 0;
+ default:
+ return 1;
+ }
+ }
+
+-static int idescsi_map_sg(ide_drive_t *drive, idescsi_pc_t *pc)
++static int idescsi_map_sg(ide_drive_t *drive, struct ide_atapi_pc *pc)
+ {
+ ide_hwif_t *hwif = drive->hwif;
+ struct scatterlist *sg, *scsi_sg;
+ int segments;
+
+- if (!pc->request_transfer || pc->request_transfer % 1024)
++ if (!pc->req_xfer || pc->req_xfer % 1024)
+ return 1;
+
+ if (idescsi_set_direction(pc))
+@@ -566,21 +542,21 @@ static int idescsi_map_sg(ide_drive_t *drive, idescsi_pc_t *pc)
+ return 0;
+ }
+
+-/*
+- * Issue a packet command
+- */
+-static ide_startstop_t idescsi_issue_pc (ide_drive_t *drive, idescsi_pc_t *pc)
++static ide_startstop_t idescsi_issue_pc(ide_drive_t *drive,
++ struct ide_atapi_pc *pc)
+ {
+ idescsi_scsi_t *scsi = drive_to_idescsi(drive);
+ ide_hwif_t *hwif = drive->hwif;
+ u16 bcount;
+ u8 dma = 0;
+
+- scsi->pc=pc; /* Set the current packet command */
+- pc->actually_transferred=0; /* We haven't transferred any data yet */
+- pc->current_position=pc->buffer;
++ /* Set the current packet command */
++ scsi->pc = pc;
++ /* We haven't transferred any data yet */
++ pc->xferred = 0;
++ pc->cur_pos = pc->buf;
+ /* Request to transfer the entire buffer at once */
+- bcount = min(pc->request_transfer, 63 * 1024);
++ bcount = min(pc->req_xfer, 63 * 1024);
+
+ if (drive->using_dma && !idescsi_map_sg(drive, pc)) {
+ hwif->sg_mapped = 1;
+@@ -591,7 +567,7 @@ static ide_startstop_t idescsi_issue_pc (ide_drive_t *drive, idescsi_pc_t *pc)
+ ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK, bcount, dma);
+
+ if (dma)
+- set_bit(PC_DMA_OK, &pc->flags);
++ pc->flags |= PC_FLAG_DMA_OK;
+
+ if (test_bit(IDESCSI_DRQ_INTERRUPT, &scsi->flags)) {
+ ide_execute_command(drive, WIN_PACKETCMD, &idescsi_transfer_pc,
+@@ -599,7 +575,7 @@ static ide_startstop_t idescsi_issue_pc (ide_drive_t *drive, idescsi_pc_t *pc)
+ return ide_started;
+ } else {
+ /* Issue the packet command */
+- HWIF(drive)->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG);
++ hwif->OUTB(WIN_PACKETCMD, hwif->io_ports[IDE_COMMAND_OFFSET]);
+ return idescsi_transfer_pc(drive);
+ }
+ }
+@@ -615,7 +591,8 @@ static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *r
+ #endif /* IDESCSI_DEBUG_LOG */
+
+ if (blk_sense_request(rq) || blk_special_request(rq)) {
+- return idescsi_issue_pc (drive, (idescsi_pc_t *) rq->special);
++ return idescsi_issue_pc(drive,
++ (struct ide_atapi_pc *) rq->special);
+ }
+ blk_dump_rq_flags(rq, "ide-scsi: unsup command");
+ idescsi_end_request (drive, 0, 0);
+@@ -773,15 +750,15 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
+ idescsi_scsi_t *scsi = scsihost_to_idescsi(host);
+ ide_drive_t *drive = scsi->drive;
+ struct request *rq = NULL;
+- idescsi_pc_t *pc = NULL;
++ struct ide_atapi_pc *pc = NULL;
+
+ if (!drive) {
+ scmd_printk (KERN_ERR, cmd, "drive not present\n");
+ goto abort;
+ }
+ scsi = drive_to_idescsi(drive);
+- pc = kmalloc (sizeof (idescsi_pc_t), GFP_ATOMIC);
+- rq = kmalloc (sizeof (struct request), GFP_ATOMIC);
++ pc = kmalloc(sizeof(struct ide_atapi_pc), GFP_ATOMIC);
++ rq = kmalloc(sizeof(struct request), GFP_ATOMIC);
+ if (rq == NULL || pc == NULL) {
+ printk (KERN_ERR "ide-scsi: %s: out of memory\n", drive->name);
+ goto abort;
+@@ -791,11 +768,11 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
+ pc->flags = 0;
+ pc->rq = rq;
+ memcpy (pc->c, cmd->cmnd, cmd->cmd_len);
+- pc->buffer = NULL;
++ pc->buf = NULL;
+ pc->sg = scsi_sglist(cmd);
+ pc->sg_cnt = scsi_sg_count(cmd);
+ pc->b_count = 0;
+- pc->request_transfer = pc->buffer_size = scsi_bufflen(cmd);
++ pc->req_xfer = pc->buf_size = scsi_bufflen(cmd);
+ pc->scsi_cmd = cmd;
+ pc->done = done;
+ pc->timeout = jiffies + cmd->timeout_per_command;
+@@ -866,7 +843,7 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd)
+ printk (KERN_ERR "ide-scsi: cmd aborted!\n");
+
+ if (blk_sense_request(scsi->pc->rq))
+- kfree(scsi->pc->buffer);
++ kfree(scsi->pc->buf);
+ kfree(scsi->pc->rq);
+ kfree(scsi->pc);
+ scsi->pc = NULL;
+@@ -916,7 +893,7 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
+ if (__blk_end_request(req, -EIO, 0))
+ BUG();
+ if (blk_sense_request(req))
+- kfree(scsi->pc->buffer);
++ kfree(scsi->pc->buf);
+ kfree(scsi->pc);
+ scsi->pc = NULL;
+ kfree(req);
+diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
+index 0cc8868..dbae3fd 100644
+--- a/drivers/scsi/initio.c
++++ b/drivers/scsi/initio.c
+@@ -2581,8 +2581,8 @@ static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * c
+ /* Map the sense buffer into bus memory */
+ dma_addr = dma_map_single(&host->pci_dev->dev, cmnd->sense_buffer,
+ SENSE_SIZE, DMA_FROM_DEVICE);
+- cblk->senseptr = cpu_to_le32((u32)dma_addr);
+- cblk->senselen = cpu_to_le32(SENSE_SIZE);
++ cblk->senseptr = (u32)dma_addr;
++ cblk->senselen = SENSE_SIZE;
+ cmnd->SCp.ptr = (char *)(unsigned long)dma_addr;
+ cblk->cdblen = cmnd->cmd_len;
+
+@@ -2606,7 +2606,7 @@ static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * c
+ dma_addr = dma_map_single(&host->pci_dev->dev, &cblk->sglist[0],
+ sizeof(struct sg_entry) * TOTAL_SG_ENTRY,
+ DMA_BIDIRECTIONAL);
+- cblk->bufptr = cpu_to_le32((u32)dma_addr);
++ cblk->bufptr = (u32)dma_addr;
+ cmnd->SCp.dma_handle = dma_addr;
+
+ cblk->sglen = nseg;
+@@ -2616,7 +2616,8 @@ static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * c
+ sg = &cblk->sglist[0];
+ scsi_for_each_sg(cmnd, sglist, cblk->sglen, i) {
+ sg->data = cpu_to_le32((u32)sg_dma_address(sglist));
+- total_len += sg->len = cpu_to_le32((u32)sg_dma_len(sglist));
++ sg->len = cpu_to_le32((u32)sg_dma_len(sglist));
++ total_len += sg_dma_len(sglist);
+ ++sg;
+ }
+
+diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
+index c72014a..de5ae6a 100644
+--- a/drivers/scsi/ipr.c
++++ b/drivers/scsi/ipr.c
+@@ -2431,7 +2431,7 @@ restart:
+ }
+
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+- kobject_uevent(&ioa_cfg->host->shost_classdev.kobj, KOBJ_CHANGE);
++ kobject_uevent(&ioa_cfg->host->shost_dev.kobj, KOBJ_CHANGE);
+ LEAVE;
+ }
+
+@@ -2451,8 +2451,8 @@ static ssize_t ipr_read_trace(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+ {
+- struct class_device *cdev = container_of(kobj,struct class_device,kobj);
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct device *dev = container_of(kobj, struct device, kobj);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ unsigned long lock_flags = 0;
+ int size = IPR_TRACE_SIZE;
+@@ -2492,15 +2492,16 @@ static const struct {
+
+ /**
+ * ipr_show_write_caching - Show the write caching attribute
+- * @class_dev: class device struct
+- * @buf: buffer
++ * @dev: device struct
++ * @buf: buffer
+ *
+ * Return value:
+ * number of bytes printed to buffer
+ **/
+-static ssize_t ipr_show_write_caching(struct class_device *class_dev, char *buf)
++static ssize_t ipr_show_write_caching(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(class_dev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ unsigned long lock_flags = 0;
+ int i, len = 0;
+@@ -2519,19 +2520,20 @@ static ssize_t ipr_show_write_caching(struct class_device *class_dev, char *buf)
+
+ /**
+ * ipr_store_write_caching - Enable/disable adapter write cache
+- * @class_dev: class_device struct
+- * @buf: buffer
+- * @count: buffer size
++ * @dev: device struct
++ * @buf: buffer
++ * @count: buffer size
+ *
+ * This function will enable/disable adapter write cache.
+ *
+ * Return value:
+ * count on success / other on failure
+ **/
+-static ssize_t ipr_store_write_caching(struct class_device *class_dev,
+- const char *buf, size_t count)
++static ssize_t ipr_store_write_caching(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+- struct Scsi_Host *shost = class_to_shost(class_dev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ unsigned long lock_flags = 0;
+ enum ipr_cache_state new_state = CACHE_INVALID;
+@@ -2569,7 +2571,7 @@ static ssize_t ipr_store_write_caching(struct class_device *class_dev,
+ return count;
+ }
+
+-static struct class_device_attribute ipr_ioa_cache_attr = {
++static struct device_attribute ipr_ioa_cache_attr = {
+ .attr = {
+ .name = "write_cache",
+ .mode = S_IRUGO | S_IWUSR,
+@@ -2580,15 +2582,16 @@ static struct class_device_attribute ipr_ioa_cache_attr = {
+
+ /**
+ * ipr_show_fw_version - Show the firmware version
+- * @class_dev: class device struct
+- * @buf: buffer
++ * @dev: class device struct
++ * @buf: buffer
+ *
+ * Return value:
+ * number of bytes printed to buffer
+ **/
+-static ssize_t ipr_show_fw_version(struct class_device *class_dev, char *buf)
++static ssize_t ipr_show_fw_version(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(class_dev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ struct ipr_inquiry_page3 *ucode_vpd = &ioa_cfg->vpd_cbs->page3_data;
+ unsigned long lock_flags = 0;
+@@ -2603,7 +2606,7 @@ static ssize_t ipr_show_fw_version(struct class_device *class_dev, char *buf)
+ return len;
+ }
+
+-static struct class_device_attribute ipr_fw_version_attr = {
++static struct device_attribute ipr_fw_version_attr = {
+ .attr = {
+ .name = "fw_version",
+ .mode = S_IRUGO,
+@@ -2613,15 +2616,16 @@ static struct class_device_attribute ipr_fw_version_attr = {
+
+ /**
+ * ipr_show_log_level - Show the adapter's error logging level
+- * @class_dev: class device struct
+- * @buf: buffer
++ * @dev: class device struct
++ * @buf: buffer
+ *
+ * Return value:
+ * number of bytes printed to buffer
+ **/
+-static ssize_t ipr_show_log_level(struct class_device *class_dev, char *buf)
++static ssize_t ipr_show_log_level(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(class_dev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ unsigned long lock_flags = 0;
+ int len;
+@@ -2634,16 +2638,17 @@ static ssize_t ipr_show_log_level(struct class_device *class_dev, char *buf)
+
+ /**
+ * ipr_store_log_level - Change the adapter's error logging level
+- * @class_dev: class device struct
+- * @buf: buffer
++ * @dev: class device struct
++ * @buf: buffer
+ *
+ * Return value:
+ * number of bytes printed to buffer
+ **/
+-static ssize_t ipr_store_log_level(struct class_device *class_dev,
++static ssize_t ipr_store_log_level(struct device *dev,
++ struct device_attribute *attr,
+ const char *buf, size_t count)
+ {
+- struct Scsi_Host *shost = class_to_shost(class_dev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ unsigned long lock_flags = 0;
+
+@@ -2653,7 +2658,7 @@ static ssize_t ipr_store_log_level(struct class_device *class_dev,
+ return strlen(buf);
+ }
+
+-static struct class_device_attribute ipr_log_level_attr = {
++static struct device_attribute ipr_log_level_attr = {
+ .attr = {
+ .name = "log_level",
+ .mode = S_IRUGO | S_IWUSR,
+@@ -2664,9 +2669,9 @@ static struct class_device_attribute ipr_log_level_attr = {
+
+ /**
+ * ipr_store_diagnostics - IOA Diagnostics interface
+- * @class_dev: class_device struct
+- * @buf: buffer
+- * @count: buffer size
++ * @dev: device struct
++ * @buf: buffer
++ * @count: buffer size
+ *
+ * This function will reset the adapter and wait a reasonable
+ * amount of time for any errors that the adapter might log.
+@@ -2674,10 +2679,11 @@ static struct class_device_attribute ipr_log_level_attr = {
+ * Return value:
+ * count on success / other on failure
+ **/
+-static ssize_t ipr_store_diagnostics(struct class_device *class_dev,
++static ssize_t ipr_store_diagnostics(struct device *dev,
++ struct device_attribute *attr,
+ const char *buf, size_t count)
+ {
+- struct Scsi_Host *shost = class_to_shost(class_dev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ unsigned long lock_flags = 0;
+ int rc = count;
+@@ -2714,7 +2720,7 @@ static ssize_t ipr_store_diagnostics(struct class_device *class_dev,
+ return rc;
+ }
+
+-static struct class_device_attribute ipr_diagnostics_attr = {
++static struct device_attribute ipr_diagnostics_attr = {
+ .attr = {
+ .name = "run_diagnostics",
+ .mode = S_IWUSR,
+@@ -2724,15 +2730,16 @@ static struct class_device_attribute ipr_diagnostics_attr = {
+
+ /**
+ * ipr_show_adapter_state - Show the adapter's state
+- * @class_dev: class device struct
+- * @buf: buffer
++ * @class_dev: device struct
++ * @buf: buffer
+ *
+ * Return value:
+ * number of bytes printed to buffer
+ **/
+-static ssize_t ipr_show_adapter_state(struct class_device *class_dev, char *buf)
++static ssize_t ipr_show_adapter_state(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(class_dev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ unsigned long lock_flags = 0;
+ int len;
+@@ -2748,19 +2755,20 @@ static ssize_t ipr_show_adapter_state(struct class_device *class_dev, char *buf)
+
+ /**
+ * ipr_store_adapter_state - Change adapter state
+- * @class_dev: class_device struct
+- * @buf: buffer
+- * @count: buffer size
++ * @dev: device struct
++ * @buf: buffer
++ * @count: buffer size
+ *
+ * This function will change the adapter's state.
+ *
+ * Return value:
+ * count on success / other on failure
+ **/
+-static ssize_t ipr_store_adapter_state(struct class_device *class_dev,
++static ssize_t ipr_store_adapter_state(struct device *dev,
++ struct device_attribute *attr,
+ const char *buf, size_t count)
+ {
+- struct Scsi_Host *shost = class_to_shost(class_dev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ unsigned long lock_flags;
+ int result = count;
+@@ -2781,7 +2789,7 @@ static ssize_t ipr_store_adapter_state(struct class_device *class_dev,
+ return result;
+ }
+
+-static struct class_device_attribute ipr_ioa_state_attr = {
++static struct device_attribute ipr_ioa_state_attr = {
+ .attr = {
+ .name = "state",
+ .mode = S_IRUGO | S_IWUSR,
+@@ -2792,19 +2800,20 @@ static struct class_device_attribute ipr_ioa_state_attr = {
+
+ /**
+ * ipr_store_reset_adapter - Reset the adapter
+- * @class_dev: class_device struct
+- * @buf: buffer
+- * @count: buffer size
++ * @dev: device struct
++ * @buf: buffer
++ * @count: buffer size
+ *
+ * This function will reset the adapter.
+ *
+ * Return value:
+ * count on success / other on failure
+ **/
+-static ssize_t ipr_store_reset_adapter(struct class_device *class_dev,
++static ssize_t ipr_store_reset_adapter(struct device *dev,
++ struct device_attribute *attr,
+ const char *buf, size_t count)
+ {
+- struct Scsi_Host *shost = class_to_shost(class_dev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ unsigned long lock_flags;
+ int result = count;
+@@ -2821,7 +2830,7 @@ static ssize_t ipr_store_reset_adapter(struct class_device *class_dev,
+ return result;
+ }
+
+-static struct class_device_attribute ipr_ioa_reset_attr = {
++static struct device_attribute ipr_ioa_reset_attr = {
+ .attr = {
+ .name = "reset_host",
+ .mode = S_IWUSR,
+@@ -3054,19 +3063,20 @@ static int ipr_update_ioa_ucode(struct ipr_ioa_cfg *ioa_cfg,
+
+ /**
+ * ipr_store_update_fw - Update the firmware on the adapter
+- * @class_dev: class_device struct
+- * @buf: buffer
+- * @count: buffer size
++ * @class_dev: device struct
++ * @buf: buffer
++ * @count: buffer size
+ *
+ * This function will update the firmware on the adapter.
+ *
+ * Return value:
+ * count on success / other on failure
+ **/
+-static ssize_t ipr_store_update_fw(struct class_device *class_dev,
+- const char *buf, size_t count)
++static ssize_t ipr_store_update_fw(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+- struct Scsi_Host *shost = class_to_shost(class_dev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ struct ipr_ucode_image_header *image_hdr;
+ const struct firmware *fw_entry;
+@@ -3124,7 +3134,7 @@ out:
+ return result;
+ }
+
+-static struct class_device_attribute ipr_update_fw_attr = {
++static struct device_attribute ipr_update_fw_attr = {
+ .attr = {
+ .name = "update_fw",
+ .mode = S_IWUSR,
+@@ -3132,7 +3142,7 @@ static struct class_device_attribute ipr_update_fw_attr = {
+ .store = ipr_store_update_fw
+ };
+
+-static struct class_device_attribute *ipr_ioa_attrs[] = {
++static struct device_attribute *ipr_ioa_attrs[] = {
+ &ipr_fw_version_attr,
+ &ipr_log_level_attr,
+ &ipr_diagnostics_attr,
+@@ -3159,7 +3169,7 @@ static ssize_t ipr_read_dump(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+ {
+- struct class_device *cdev = container_of(kobj,struct class_device,kobj);
++ struct device *cdev = container_of(kobj, struct device, kobj);
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ struct ipr_dump *dump;
+@@ -3322,7 +3332,7 @@ static ssize_t ipr_write_dump(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+ {
+- struct class_device *cdev = container_of(kobj,struct class_device,kobj);
++ struct device *cdev = container_of(kobj, struct device, kobj);
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
+ int rc;
+@@ -3937,7 +3947,7 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd)
+ if (ipr_is_gata(res) && res->sata_port) {
+ ap = res->sata_port->ap;
+ spin_unlock_irq(scsi_cmd->device->host->host_lock);
+- ata_do_eh(ap, NULL, NULL, ipr_sata_reset, NULL);
++ ata_std_error_handler(ap);
+ spin_lock_irq(scsi_cmd->device->host->host_lock);
+
+ list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) {
+@@ -5041,33 +5051,6 @@ static void ipr_ata_post_internal(struct ata_queued_cmd *qc)
+ }
+
+ /**
+- * ipr_tf_read - Read the current ATA taskfile for the ATA port
+- * @ap: ATA port
+- * @tf: destination ATA taskfile
+- *
+- * Return value:
+- * none
+- **/
+-static void ipr_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+-{
+- struct ipr_sata_port *sata_port = ap->private_data;
+- struct ipr_ioasa_gata *g = &sata_port->ioasa;
+-
+- tf->feature = g->error;
+- tf->nsect = g->nsect;
+- tf->lbal = g->lbal;
+- tf->lbam = g->lbam;
+- tf->lbah = g->lbah;
+- tf->device = g->device;
+- tf->command = g->status;
+- tf->hob_nsect = g->hob_nsect;
+- tf->hob_lbal = g->hob_lbal;
+- tf->hob_lbam = g->hob_lbam;
+- tf->hob_lbah = g->hob_lbah;
+- tf->ctl = g->alt_status;
+-}
+-
+-/**
+ * ipr_copy_sata_tf - Copy a SATA taskfile to an IOA data structure
+ * @regs: destination
+ * @tf: source ATA taskfile
+@@ -5245,40 +5228,41 @@ static unsigned int ipr_qc_issue(struct ata_queued_cmd *qc)
+ }
+
+ /**
+- * ipr_ata_check_status - Return last ATA status
+- * @ap: ATA port
++ * ipr_qc_fill_rtf - Read result TF
++ * @qc: ATA queued command
+ *
+ * Return value:
+- * ATA status
++ * true
+ **/
+-static u8 ipr_ata_check_status(struct ata_port *ap)
++static bool ipr_qc_fill_rtf(struct ata_queued_cmd *qc)
+ {
+- struct ipr_sata_port *sata_port = ap->private_data;
+- return sata_port->ioasa.status;
+-}
++ struct ipr_sata_port *sata_port = qc->ap->private_data;
++ struct ipr_ioasa_gata *g = &sata_port->ioasa;
++ struct ata_taskfile *tf = &qc->result_tf;
+
+-/**
+- * ipr_ata_check_altstatus - Return last ATA altstatus
+- * @ap: ATA port
+- *
+- * Return value:
+- * Alt ATA status
+- **/
+-static u8 ipr_ata_check_altstatus(struct ata_port *ap)
+-{
+- struct ipr_sata_port *sata_port = ap->private_data;
+- return sata_port->ioasa.alt_status;
++ tf->feature = g->error;
++ tf->nsect = g->nsect;
++ tf->lbal = g->lbal;
++ tf->lbam = g->lbam;
++ tf->lbah = g->lbah;
++ tf->device = g->device;
++ tf->command = g->status;
++ tf->hob_nsect = g->hob_nsect;
++ tf->hob_lbal = g->hob_lbal;
++ tf->hob_lbam = g->hob_lbam;
++ tf->hob_lbah = g->hob_lbah;
++ tf->ctl = g->alt_status;
++
++ return true;
+ }
+
+ static struct ata_port_operations ipr_sata_ops = {
+- .check_status = ipr_ata_check_status,
+- .check_altstatus = ipr_ata_check_altstatus,
+- .dev_select = ata_noop_dev_select,
+ .phy_reset = ipr_ata_phy_reset,
++ .hardreset = ipr_sata_reset,
+ .post_internal_cmd = ipr_ata_post_internal,
+- .tf_read = ipr_tf_read,
+ .qc_prep = ata_noop_qc_prep,
+ .qc_issue = ipr_qc_issue,
++ .qc_fill_rtf = ipr_qc_fill_rtf,
+ .port_start = ata_sas_port_start,
+ .port_stop = ata_sas_port_stop
+ };
+@@ -7697,9 +7681,9 @@ static void ipr_remove(struct pci_dev *pdev)
+
+ ENTER;
+
+- ipr_remove_trace_file(&ioa_cfg->host->shost_classdev.kobj,
++ ipr_remove_trace_file(&ioa_cfg->host->shost_dev.kobj,
+ &ipr_trace_attr);
+- ipr_remove_dump_file(&ioa_cfg->host->shost_classdev.kobj,
++ ipr_remove_dump_file(&ioa_cfg->host->shost_dev.kobj,
+ &ipr_dump_attr);
+ scsi_remove_host(ioa_cfg->host);
+
+@@ -7740,7 +7724,7 @@ static int __devinit ipr_probe(struct pci_dev *pdev,
+ return rc;
+ }
+
+- rc = ipr_create_trace_file(&ioa_cfg->host->shost_classdev.kobj,
++ rc = ipr_create_trace_file(&ioa_cfg->host->shost_dev.kobj,
+ &ipr_trace_attr);
+
+ if (rc) {
+@@ -7749,11 +7733,11 @@ static int __devinit ipr_probe(struct pci_dev *pdev,
+ return rc;
+ }
+
+- rc = ipr_create_dump_file(&ioa_cfg->host->shost_classdev.kobj,
++ rc = ipr_create_dump_file(&ioa_cfg->host->shost_dev.kobj,
+ &ipr_dump_attr);
+
+ if (rc) {
+- ipr_remove_trace_file(&ioa_cfg->host->shost_classdev.kobj,
++ ipr_remove_trace_file(&ioa_cfg->host->shost_dev.kobj,
+ &ipr_trace_attr);
+ scsi_remove_host(ioa_cfg->host);
+ __ipr_remove(pdev);
+diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
+index 7ed568f..7c615c7 100644
+--- a/drivers/scsi/ips.c
++++ b/drivers/scsi/ips.c
+@@ -2377,7 +2377,7 @@ ips_get_bios_version(ips_ha_t * ha, int intr)
+ if (inb(ha->io_addr + IPS_REG_FLDP) != 0x55)
+ return;
+
+- outl(cpu_to_le32(1), ha->io_addr + IPS_REG_FLAP);
++ outl(1, ha->io_addr + IPS_REG_FLAP);
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
+ udelay(25); /* 25 us */
+
+@@ -2385,21 +2385,21 @@ ips_get_bios_version(ips_ha_t * ha, int intr)
+ return;
+
+ /* Get Major version */
+- outl(cpu_to_le32(0x1FF), ha->io_addr + IPS_REG_FLAP);
++ outl(0x1FF, ha->io_addr + IPS_REG_FLAP);
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
+ udelay(25); /* 25 us */
+
+ major = inb(ha->io_addr + IPS_REG_FLDP);
+
+ /* Get Minor version */
+- outl(cpu_to_le32(0x1FE), ha->io_addr + IPS_REG_FLAP);
++ outl(0x1FE, ha->io_addr + IPS_REG_FLAP);
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
+ udelay(25); /* 25 us */
+
+ minor = inb(ha->io_addr + IPS_REG_FLDP);
+
+ /* Get SubMinor version */
+- outl(cpu_to_le32(0x1FD), ha->io_addr + IPS_REG_FLAP);
++ outl(0x1FD, ha->io_addr + IPS_REG_FLAP);
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
+ udelay(25); /* 25 us */
+
+@@ -3502,27 +3502,11 @@ ips_send_wait(ips_ha_t * ha, ips_scb_t * scb, int timeout, int intr)
+ static void
+ ips_scmd_buf_write(struct scsi_cmnd *scmd, void *data, unsigned int count)
+ {
+- int i;
+- unsigned int min_cnt, xfer_cnt;
+- char *cdata = (char *) data;
+- unsigned char *buffer;
+- unsigned long flags;
+- struct scatterlist *sg = scsi_sglist(scmd);
+-
+- for (i = 0, xfer_cnt = 0;
+- (i < scsi_sg_count(scmd)) && (xfer_cnt < count); i++) {
+- min_cnt = min(count - xfer_cnt, sg[i].length);
+-
+- /* kmap_atomic() ensures addressability of the data buffer.*/
+- /* local_irq_save() protects the KM_IRQ0 address slot. */
+- local_irq_save(flags);
+- buffer = kmap_atomic(sg_page(&sg[i]), KM_IRQ0) + sg[i].offset;
+- memcpy(buffer, &cdata[xfer_cnt], min_cnt);
+- kunmap_atomic(buffer - sg[i].offset, KM_IRQ0);
+- local_irq_restore(flags);
++ unsigned long flags;
+
+- xfer_cnt += min_cnt;
+- }
++ local_irq_save(flags);
++ scsi_sg_copy_from_buffer(scmd, data, count);
++ local_irq_restore(flags);
+ }
+
+ /****************************************************************************/
+@@ -3535,27 +3519,11 @@ ips_scmd_buf_write(struct scsi_cmnd *scmd, void *data, unsigned int count)
+ static void
+ ips_scmd_buf_read(struct scsi_cmnd *scmd, void *data, unsigned int count)
+ {
+- int i;
+- unsigned int min_cnt, xfer_cnt;
+- char *cdata = (char *) data;
+- unsigned char *buffer;
+- unsigned long flags;
+- struct scatterlist *sg = scsi_sglist(scmd);
+-
+- for (i = 0, xfer_cnt = 0;
+- (i < scsi_sg_count(scmd)) && (xfer_cnt < count); i++) {
+- min_cnt = min(count - xfer_cnt, sg[i].length);
+-
+- /* kmap_atomic() ensures addressability of the data buffer.*/
+- /* local_irq_save() protects the KM_IRQ0 address slot. */
+- local_irq_save(flags);
+- buffer = kmap_atomic(sg_page(&sg[i]), KM_IRQ0) + sg[i].offset;
+- memcpy(&cdata[xfer_cnt], buffer, min_cnt);
+- kunmap_atomic(buffer - sg[i].offset, KM_IRQ0);
+- local_irq_restore(flags);
++ unsigned long flags;
+
+- xfer_cnt += min_cnt;
+- }
++ local_irq_save(flags);
++ scsi_sg_copy_to_buffer(scmd, data, count);
++ local_irq_restore(flags);
+ }
+
+ /****************************************************************************/
+@@ -3696,9 +3664,7 @@ ips_send_cmd(ips_ha_t * ha, ips_scb_t * scb)
+ scb->cmd.basic_io.sg_count = scb->sg_len;
+
+ if (scb->cmd.basic_io.lba)
+- scb->cmd.basic_io.lba =
+- cpu_to_le32(le32_to_cpu
+- (scb->cmd.basic_io.lba) +
++ le32_add_cpu(&scb->cmd.basic_io.lba,
+ le16_to_cpu(scb->cmd.basic_io.
+ sector_count));
+ else
+@@ -3744,9 +3710,7 @@ ips_send_cmd(ips_ha_t * ha, ips_scb_t * scb)
+ scb->cmd.basic_io.sg_count = scb->sg_len;
+
+ if (scb->cmd.basic_io.lba)
+- scb->cmd.basic_io.lba =
+- cpu_to_le32(le32_to_cpu
+- (scb->cmd.basic_io.lba) +
++ le32_add_cpu(&scb->cmd.basic_io.lba,
+ le16_to_cpu(scb->cmd.basic_io.
+ sector_count));
+ else
+@@ -4888,7 +4852,7 @@ ips_init_copperhead(ips_ha_t * ha)
+ return (0);
+
+ /* setup CCCR */
+- outl(cpu_to_le32(0x1010), ha->io_addr + IPS_REG_CCCR);
++ outl(0x1010, ha->io_addr + IPS_REG_CCCR);
+
+ /* Enable busmastering */
+ outb(IPS_BIT_EBM, ha->io_addr + IPS_REG_SCPR);
+@@ -5270,12 +5234,12 @@ ips_statinit(ips_ha_t * ha)
+ ha->adapt->p_status_tail = ha->adapt->status;
+
+ phys_status_start = ha->adapt->hw_status_start;
+- outl(cpu_to_le32(phys_status_start), ha->io_addr + IPS_REG_SQSR);
+- outl(cpu_to_le32(phys_status_start + IPS_STATUS_Q_SIZE),
++ outl(phys_status_start, ha->io_addr + IPS_REG_SQSR);
++ outl(phys_status_start + IPS_STATUS_Q_SIZE,
+ ha->io_addr + IPS_REG_SQER);
+- outl(cpu_to_le32(phys_status_start + IPS_STATUS_SIZE),
++ outl(phys_status_start + IPS_STATUS_SIZE,
+ ha->io_addr + IPS_REG_SQHR);
+- outl(cpu_to_le32(phys_status_start), ha->io_addr + IPS_REG_SQTR);
++ outl(phys_status_start, ha->io_addr + IPS_REG_SQTR);
+
+ ha->adapt->hw_status_tail = phys_status_start;
+ }
+@@ -5332,7 +5296,7 @@ ips_statupd_copperhead(ips_ha_t * ha)
+ ha->adapt->hw_status_tail = ha->adapt->hw_status_start;
+ }
+
+- outl(cpu_to_le32(ha->adapt->hw_status_tail),
++ outl(ha->adapt->hw_status_tail,
+ ha->io_addr + IPS_REG_SQTR);
+
+ return (ha->adapt->p_status_tail->value);
+@@ -5434,8 +5398,8 @@ ips_issue_copperhead(ips_ha_t * ha, ips_scb_t * scb)
+ } /* end if */
+ } /* end while */
+
+- outl(cpu_to_le32(scb->scb_busaddr), ha->io_addr + IPS_REG_CCSAR);
+- outw(cpu_to_le32(IPS_BIT_START_CMD), ha->io_addr + IPS_REG_CCCR);
++ outl(scb->scb_busaddr, ha->io_addr + IPS_REG_CCSAR);
++ outw(IPS_BIT_START_CMD, ha->io_addr + IPS_REG_CCCR);
+
+ return (IPS_SUCCESS);
+ }
+@@ -5520,7 +5484,7 @@ ips_issue_i2o(ips_ha_t * ha, ips_scb_t * scb)
+ ips_name, ha->host_num, scb->cmd.basic_io.command_id);
+ }
+
+- outl(cpu_to_le32(scb->scb_busaddr), ha->io_addr + IPS_REG_I2O_INMSGQ);
++ outl(scb->scb_busaddr, ha->io_addr + IPS_REG_I2O_INMSGQ);
+
+ return (IPS_SUCCESS);
+ }
+@@ -6412,7 +6376,7 @@ ips_program_bios(ips_ha_t * ha, char *buffer, uint32_t buffersize,
+
+ for (i = 0; i < buffersize; i++) {
+ /* write a byte */
+- outl(cpu_to_le32(i + offset), ha->io_addr + IPS_REG_FLAP);
++ outl(i + offset, ha->io_addr + IPS_REG_FLAP);
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
+ udelay(25); /* 25 us */
+
+@@ -6597,7 +6561,7 @@ ips_verify_bios(ips_ha_t * ha, char *buffer, uint32_t buffersize,
+ if (inb(ha->io_addr + IPS_REG_FLDP) != 0x55)
+ return (1);
+
+- outl(cpu_to_le32(1), ha->io_addr + IPS_REG_FLAP);
++ outl(1, ha->io_addr + IPS_REG_FLAP);
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
+ udelay(25); /* 25 us */
+ if (inb(ha->io_addr + IPS_REG_FLDP) != 0xAA)
+@@ -6606,7 +6570,7 @@ ips_verify_bios(ips_ha_t * ha, char *buffer, uint32_t buffersize,
+ checksum = 0xff;
+ for (i = 2; i < buffersize; i++) {
+
+- outl(cpu_to_le32(i + offset), ha->io_addr + IPS_REG_FLAP);
++ outl(i + offset, ha->io_addr + IPS_REG_FLAP);
+ if (ha->pcidev->revision == IPS_REVID_TROMBONE64)
+ udelay(25); /* 25 us */
+
+@@ -6842,7 +6806,6 @@ ips_register_scsi(int index)
+ sh->sg_tablesize = sh->hostt->sg_tablesize;
+ sh->can_queue = sh->hostt->can_queue;
+ sh->cmd_per_lun = sh->hostt->cmd_per_lun;
+- sh->unchecked_isa_dma = sh->hostt->unchecked_isa_dma;
+ sh->use_clustering = sh->hostt->use_clustering;
+ sh->max_sectors = 128;
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 8a17867..72b9b2a 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -528,6 +528,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ struct iscsi_session *session = conn->session;
+ struct scsi_cmnd *sc = ctask->sc;
+ int datasn = be32_to_cpu(rhdr->datasn);
++ unsigned total_in_length = scsi_in(sc)->length;
+
+ iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
+ if (tcp_conn->in.datalen == 0)
+@@ -542,10 +543,10 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ tcp_ctask->exp_datasn++;
+
+ tcp_ctask->data_offset = be32_to_cpu(rhdr->offset);
+- if (tcp_ctask->data_offset + tcp_conn->in.datalen > scsi_bufflen(sc)) {
++ if (tcp_ctask->data_offset + tcp_conn->in.datalen > total_in_length) {
+ debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n",
+ __FUNCTION__, tcp_ctask->data_offset,
+- tcp_conn->in.datalen, scsi_bufflen(sc));
++ tcp_conn->in.datalen, total_in_length);
+ return ISCSI_ERR_DATA_OFFSET;
+ }
+
+@@ -558,8 +559,8 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+
+ if (res_count > 0 &&
+ (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
+- res_count <= scsi_bufflen(sc)))
+- scsi_set_resid(sc, res_count);
++ res_count <= total_in_length))
++ scsi_in(sc)->resid = res_count;
+ else
+ sc->result = (DID_BAD_TARGET << 16) |
+ rhdr->cmd_status;
+@@ -670,11 +671,11 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ r2t->data_length, session->max_burst);
+
+ r2t->data_offset = be32_to_cpu(rhdr->data_offset);
+- if (r2t->data_offset + r2t->data_length > scsi_bufflen(ctask->sc)) {
++ if (r2t->data_offset + r2t->data_length > scsi_out(ctask->sc)->length) {
+ iscsi_conn_printk(KERN_ERR, conn,
+ "invalid R2T with data len %u at offset %u "
+ "and total length %d\n", r2t->data_length,
+- r2t->data_offset, scsi_bufflen(ctask->sc));
++ r2t->data_offset, scsi_out(ctask->sc)->length);
+ __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
+ sizeof(void*));
+ return ISCSI_ERR_DATALEN;
+@@ -771,6 +772,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ if (tcp_conn->in.datalen) {
+ struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ struct hash_desc *rx_hash = NULL;
++ struct scsi_data_buffer *sdb = scsi_in(ctask->sc);
+
+ /*
+ * Setup copy of Data-In into the Scsi_Cmnd
+@@ -788,8 +790,8 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ tcp_ctask->data_offset,
+ tcp_conn->in.datalen);
+ return iscsi_segment_seek_sg(&tcp_conn->in.segment,
+- scsi_sglist(ctask->sc),
+- scsi_sg_count(ctask->sc),
++ sdb->table.sgl,
++ sdb->table.nents,
+ tcp_ctask->data_offset,
+ tcp_conn->in.datalen,
+ iscsi_tcp_process_data_in,
+@@ -1332,7 +1334,8 @@ iscsi_tcp_ctask_init(struct iscsi_cmd_task *ctask)
+ return 0;
+
+ /* If we have immediate data, attach a payload */
+- err = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc), scsi_sg_count(sc),
++ err = iscsi_tcp_send_data_prep(conn, scsi_out(sc)->table.sgl,
++ scsi_out(sc)->table.nents,
+ 0, ctask->imm_count);
+ if (err)
+ return err;
+@@ -1386,6 +1389,7 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+ struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ struct scsi_cmnd *sc = ctask->sc;
++ struct scsi_data_buffer *sdb = scsi_out(sc);
+ int rc = 0;
+
+ flush:
+@@ -1412,9 +1416,8 @@ flush:
+ ctask->itt, tcp_ctask->sent, ctask->data_count);
+
+ iscsi_tcp_send_hdr_prep(conn, hdr, sizeof(*hdr));
+- rc = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc),
+- scsi_sg_count(sc),
+- tcp_ctask->sent,
++ rc = iscsi_tcp_send_data_prep(conn, sdb->table.sgl,
++ sdb->table.nents, tcp_ctask->sent,
+ ctask->data_count);
+ if (rc)
+ goto fail;
+@@ -1460,8 +1463,8 @@ flush:
+ iscsi_tcp_send_hdr_prep(conn, &r2t->dtask.hdr,
+ sizeof(struct iscsi_hdr));
+
+- rc = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc),
+- scsi_sg_count(sc),
++ rc = iscsi_tcp_send_data_prep(conn, sdb->table.sgl,
++ sdb->table.nents,
+ r2t->data_offset + r2t->sent,
+ r2t->data_count);
+ if (rc)
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index bdd7de7..010c1b9 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -137,6 +137,70 @@ static int iscsi_add_hdr(struct iscsi_cmd_task *ctask, unsigned len)
+ return 0;
+ }
+
++/*
++ * make an extended cdb AHS
++ */
++static int iscsi_prep_ecdb_ahs(struct iscsi_cmd_task *ctask)
++{
++ struct scsi_cmnd *cmd = ctask->sc;
++ unsigned rlen, pad_len;
++ unsigned short ahslength;
++ struct iscsi_ecdb_ahdr *ecdb_ahdr;
++ int rc;
++
++ ecdb_ahdr = iscsi_next_hdr(ctask);
++ rlen = cmd->cmd_len - ISCSI_CDB_SIZE;
++
++ BUG_ON(rlen > sizeof(ecdb_ahdr->ecdb));
++ ahslength = rlen + sizeof(ecdb_ahdr->reserved);
++
++ pad_len = iscsi_padding(rlen);
++
++ rc = iscsi_add_hdr(ctask, sizeof(ecdb_ahdr->ahslength) +
++ sizeof(ecdb_ahdr->ahstype) + ahslength + pad_len);
++ if (rc)
++ return rc;
++
++ if (pad_len)
++ memset(&ecdb_ahdr->ecdb[rlen], 0, pad_len);
++
++ ecdb_ahdr->ahslength = cpu_to_be16(ahslength);
++ ecdb_ahdr->ahstype = ISCSI_AHSTYPE_CDB;
++ ecdb_ahdr->reserved = 0;
++ memcpy(ecdb_ahdr->ecdb, cmd->cmnd + ISCSI_CDB_SIZE, rlen);
++
++ debug_scsi("iscsi_prep_ecdb_ahs: varlen_cdb_len %d "
++ "rlen %d pad_len %d ahs_length %d iscsi_headers_size %u\n",
++ cmd->cmd_len, rlen, pad_len, ahslength, ctask->hdr_len);
++
++ return 0;
++}
++
++static int iscsi_prep_bidi_ahs(struct iscsi_cmd_task *ctask)
++{
++ struct scsi_cmnd *sc = ctask->sc;
++ struct iscsi_rlength_ahdr *rlen_ahdr;
++ int rc;
++
++ rlen_ahdr = iscsi_next_hdr(ctask);
++ rc = iscsi_add_hdr(ctask, sizeof(*rlen_ahdr));
++ if (rc)
++ return rc;
++
++ rlen_ahdr->ahslength =
++ cpu_to_be16(sizeof(rlen_ahdr->read_length) +
++ sizeof(rlen_ahdr->reserved));
++ rlen_ahdr->ahstype = ISCSI_AHSTYPE_RLENGTH;
++ rlen_ahdr->reserved = 0;
++ rlen_ahdr->read_length = cpu_to_be32(scsi_in(sc)->length);
++
++ debug_scsi("bidi-in rlen_ahdr->read_length(%d) "
++ "rlen_ahdr->ahslength(%d)\n",
++ be32_to_cpu(rlen_ahdr->read_length),
++ be16_to_cpu(rlen_ahdr->ahslength));
++ return 0;
++}
++
+ /**
+ * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu
+ * @ctask: iscsi cmd task
+@@ -150,7 +214,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ struct iscsi_session *session = conn->session;
+ struct iscsi_cmd *hdr = ctask->hdr;
+ struct scsi_cmnd *sc = ctask->sc;
+- unsigned hdrlength;
++ unsigned hdrlength, cmd_len;
+ int rc;
+
+ ctask->hdr_len = 0;
+@@ -161,17 +225,30 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ hdr->flags = ISCSI_ATTR_SIMPLE;
+ int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
+ hdr->itt = build_itt(ctask->itt, session->age);
+- hdr->data_length = cpu_to_be32(scsi_bufflen(sc));
+ hdr->cmdsn = cpu_to_be32(session->cmdsn);
+ session->cmdsn++;
+ hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
+- memcpy(hdr->cdb, sc->cmnd, sc->cmd_len);
+- if (sc->cmd_len < MAX_COMMAND_SIZE)
+- memset(&hdr->cdb[sc->cmd_len], 0,
+- MAX_COMMAND_SIZE - sc->cmd_len);
++ cmd_len = sc->cmd_len;
++ if (cmd_len < ISCSI_CDB_SIZE)
++ memset(&hdr->cdb[cmd_len], 0, ISCSI_CDB_SIZE - cmd_len);
++ else if (cmd_len > ISCSI_CDB_SIZE) {
++ rc = iscsi_prep_ecdb_ahs(ctask);
++ if (rc)
++ return rc;
++ cmd_len = ISCSI_CDB_SIZE;
++ }
++ memcpy(hdr->cdb, sc->cmnd, cmd_len);
+
+ ctask->imm_count = 0;
++ if (scsi_bidi_cmnd(sc)) {
++ hdr->flags |= ISCSI_FLAG_CMD_READ;
++ rc = iscsi_prep_bidi_ahs(ctask);
++ if (rc)
++ return rc;
++ }
+ if (sc->sc_data_direction == DMA_TO_DEVICE) {
++ unsigned out_len = scsi_out(sc)->length;
++ hdr->data_length = cpu_to_be32(out_len);
+ hdr->flags |= ISCSI_FLAG_CMD_WRITE;
+ /*
+ * Write counters:
+@@ -192,19 +269,19 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ ctask->unsol_datasn = 0;
+
+ if (session->imm_data_en) {
+- if (scsi_bufflen(sc) >= session->first_burst)
++ if (out_len >= session->first_burst)
+ ctask->imm_count = min(session->first_burst,
+ conn->max_xmit_dlength);
+ else
+- ctask->imm_count = min(scsi_bufflen(sc),
++ ctask->imm_count = min(out_len,
+ conn->max_xmit_dlength);
+ hton24(hdr->dlength, ctask->imm_count);
+ } else
+ zero_data(hdr->dlength);
+
+ if (!session->initial_r2t_en) {
+- ctask->unsol_count = min((session->first_burst),
+- (scsi_bufflen(sc))) - ctask->imm_count;
++ ctask->unsol_count = min(session->first_burst, out_len)
++ - ctask->imm_count;
+ ctask->unsol_offset = ctask->imm_count;
+ }
+
+@@ -214,6 +291,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ } else {
+ hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+ zero_data(hdr->dlength);
++ hdr->data_length = cpu_to_be32(scsi_in(sc)->length);
+
+ if (sc->sc_data_direction == DMA_FROM_DEVICE)
+ hdr->flags |= ISCSI_FLAG_CMD_READ;
+@@ -232,10 +310,12 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ return EIO;
+
+ conn->scsicmd_pdus_cnt++;
+- debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d "
+- "cmdsn %d win %d]\n",
+- sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
+- conn->id, sc, sc->cmnd[0], ctask->itt, scsi_bufflen(sc),
++ debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x "
++ "len %d bidi_len %d cmdsn %d win %d]\n",
++ scsi_bidi_cmnd(sc) ? "bidirectional" :
++ sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
++ conn->id, sc, sc->cmnd[0], ctask->itt,
++ scsi_bufflen(sc), scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0,
+ session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
+ return 0;
+ }
+@@ -298,7 +378,12 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ conn->session->tt->cleanup_cmd_task(conn, ctask);
+
+ sc->result = err;
+- scsi_set_resid(sc, scsi_bufflen(sc));
++ if (!scsi_bidi_cmnd(sc))
++ scsi_set_resid(sc, scsi_bufflen(sc));
++ else {
++ scsi_out(sc)->resid = scsi_out(sc)->length;
++ scsi_in(sc)->resid = scsi_in(sc)->length;
++ }
+ if (conn->ctask == ctask)
+ conn->ctask = NULL;
+ /* release ref from queuecommand */
+@@ -433,6 +518,18 @@ invalid_datalen:
+ min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
+ }
+
++ if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW |
++ ISCSI_FLAG_CMD_BIDI_OVERFLOW)) {
++ int res_count = be32_to_cpu(rhdr->bi_residual_count);
++
++ if (scsi_bidi_cmnd(sc) && res_count > 0 &&
++ (rhdr->flags & ISCSI_FLAG_CMD_BIDI_OVERFLOW ||
++ res_count <= scsi_in(sc)->length))
++ scsi_in(sc)->resid = res_count;
++ else
++ sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
++ }
++
+ if (rhdr->flags & (ISCSI_FLAG_CMD_UNDERFLOW |
+ ISCSI_FLAG_CMD_OVERFLOW)) {
+ int res_count = be32_to_cpu(rhdr->residual_count);
+@@ -440,13 +537,11 @@ invalid_datalen:
+ if (res_count > 0 &&
+ (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
+ res_count <= scsi_bufflen(sc)))
++ /* write side for bidi or uni-io set_resid */
+ scsi_set_resid(sc, res_count);
+ else
+ sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+- } else if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW |
+- ISCSI_FLAG_CMD_BIDI_OVERFLOW))
+- sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+-
++ }
+ out:
+ debug_scsi("done [sc %lx res %d itt 0x%x]\n",
+ (long)sc, sc->result, ctask->itt);
+@@ -1102,7 +1197,12 @@ reject:
+ fault:
+ spin_unlock(&session->lock);
+ debug_scsi("iscsi: cmd 0x%x is not queued (%d)\n", sc->cmnd[0], reason);
+- scsi_set_resid(sc, scsi_bufflen(sc));
++ if (!scsi_bidi_cmnd(sc))
++ scsi_set_resid(sc, scsi_bufflen(sc));
++ else {
++ scsi_out(sc)->resid = scsi_out(sc)->length;
++ scsi_in(sc)->resid = scsi_in(sc)->length;
++ }
+ sc->scsi_done(sc);
+ spin_lock(host->host_lock);
+ return 0;
+diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
+index b0e5ac3..744f06d 100644
+--- a/drivers/scsi/libsas/sas_ata.c
++++ b/drivers/scsi/libsas/sas_ata.c
+@@ -225,10 +225,12 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
+ return 0;
+ }
+
+-static u8 sas_ata_check_status(struct ata_port *ap)
++static bool sas_ata_qc_fill_rtf(struct ata_queued_cmd *qc)
+ {
+- struct domain_device *dev = ap->private_data;
+- return dev->sata_dev.tf.command;
++ struct domain_device *dev = qc->ap->private_data;
++
++ memcpy(&qc->result_tf, &dev->sata_dev.tf, sizeof(qc->result_tf));
++ return true;
+ }
+
+ static void sas_ata_phy_reset(struct ata_port *ap)
+@@ -292,12 +294,6 @@ static void sas_ata_post_internal(struct ata_queued_cmd *qc)
+ }
+ }
+
+-static void sas_ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+-{
+- struct domain_device *dev = ap->private_data;
+- memcpy(tf, &dev->sata_dev.tf, sizeof (*tf));
+-}
+-
+ static int sas_ata_scr_write(struct ata_port *ap, unsigned int sc_reg_in,
+ u32 val)
+ {
+@@ -348,14 +344,11 @@ static int sas_ata_scr_read(struct ata_port *ap, unsigned int sc_reg_in,
+ }
+
+ static struct ata_port_operations sas_sata_ops = {
+- .check_status = sas_ata_check_status,
+- .check_altstatus = sas_ata_check_status,
+- .dev_select = ata_noop_dev_select,
+ .phy_reset = sas_ata_phy_reset,
+ .post_internal_cmd = sas_ata_post_internal,
+- .tf_read = sas_ata_tf_read,
+ .qc_prep = ata_noop_qc_prep,
+ .qc_issue = sas_ata_qc_issue,
++ .qc_fill_rtf = sas_ata_qc_fill_rtf,
+ .port_start = ata_sas_port_start,
+ .port_stop = ata_sas_port_stop,
+ .scr_read = sas_ata_scr_read,
+@@ -698,7 +691,7 @@ static int sas_discover_sata_dev(struct domain_device *dev)
+ /* incomplete response */
+ SAS_DPRINTK("sending SET FEATURE/PUP_STBY_SPIN_UP to "
+ "dev %llx\n", SAS_ADDR(dev->sas_addr));
+- if (!le16_to_cpu(identify_x[83] & (1<<6)))
++ if (!(identify_x[83] & cpu_to_le16(1<<6)))
+ goto cont1;
+ res = sas_issue_ata_cmd(dev, ATA_SET_FEATURES,
+ ATA_FEATURE_PUP_STBY_SPIN_UP,
+diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
+index 1f82415..601ec5b 100644
+--- a/drivers/scsi/libsas/sas_scsi_host.c
++++ b/drivers/scsi/libsas/sas_scsi_host.c
+@@ -24,6 +24,8 @@
+ */
+
+ #include <linux/kthread.h>
++#include <linux/firmware.h>
++#include <linux/ctype.h>
+
+ #include "sas_internal.h"
+
+@@ -1064,6 +1066,45 @@ void sas_target_destroy(struct scsi_target *starget)
+ return;
+ }
+
++static void sas_parse_addr(u8 *sas_addr, const char *p)
++{
++ int i;
++ for (i = 0; i < SAS_ADDR_SIZE; i++) {
++ u8 h, l;
++ if (!*p)
++ break;
++ h = isdigit(*p) ? *p-'0' : toupper(*p)-'A'+10;
++ p++;
++ l = isdigit(*p) ? *p-'0' : toupper(*p)-'A'+10;
++ p++;
++ sas_addr[i] = (h<<4) | l;
++ }
++}
++
++#define SAS_STRING_ADDR_SIZE 16
++
++int sas_request_addr(struct Scsi_Host *shost, u8 *addr)
++{
++ int res;
++ const struct firmware *fw;
++
++ res = request_firmware(&fw, "sas_addr", &shost->shost_gendev);
++ if (res)
++ return res;
++
++ if (fw->size < SAS_STRING_ADDR_SIZE) {
++ res = -ENODEV;
++ goto out;
++ }
++
++ sas_parse_addr(addr, fw->data);
++
++out:
++ release_firmware(fw);
++ return res;
++}
++EXPORT_SYMBOL_GPL(sas_request_addr);
++
+ EXPORT_SYMBOL_GPL(sas_queuecommand);
+ EXPORT_SYMBOL_GPL(sas_target_alloc);
+ EXPORT_SYMBOL_GPL(sas_slave_configure);
+diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
+index 2ab2d24..ec0b0f6 100644
+--- a/drivers/scsi/lpfc/lpfc.h
++++ b/drivers/scsi/lpfc/lpfc.h
+@@ -23,7 +23,7 @@
+
+ struct lpfc_sli2_slim;
+
+-#define LPFC_MAX_TARGET 256 /* max number of targets supported */
++#define LPFC_MAX_TARGET 4096 /* max number of targets supported */
+ #define LPFC_MAX_DISC_THREADS 64 /* max outstanding discovery els
+ requests */
+ #define LPFC_MAX_NS_RETRY 3 /* Number of retry attempts to contact
+@@ -268,7 +268,6 @@ struct lpfc_vport {
+ #define FC_NLP_MORE 0x40 /* More node to process in node tbl */
+ #define FC_OFFLINE_MODE 0x80 /* Interface is offline for diag */
+ #define FC_FABRIC 0x100 /* We are fabric attached */
+-#define FC_ESTABLISH_LINK 0x200 /* Reestablish Link */
+ #define FC_RSCN_DISCOVERY 0x400 /* Auth all devices after RSCN */
+ #define FC_SCSI_SCAN_TMO 0x4000 /* scsi scan timer running */
+ #define FC_ABORT_DISCOVERY 0x8000 /* we want to abort discovery */
+@@ -433,8 +432,6 @@ struct lpfc_hba {
+
+ uint32_t fc_eventTag; /* event tag for link attention */
+
+-
+- struct timer_list fc_estabtmo; /* link establishment timer */
+ /* These fields used to be binfo */
+ uint32_t fc_pref_DID; /* preferred D_ID */
+ uint8_t fc_pref_ALPA; /* preferred AL_PA */
+diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
+index b12a841..a9fbb3f 100644
+--- a/drivers/scsi/lpfc/lpfc_attr.c
++++ b/drivers/scsi/lpfc/lpfc_attr.c
+@@ -66,23 +66,26 @@ lpfc_jedec_to_ascii(int incr, char hdw[])
+ }
+
+ static ssize_t
+-lpfc_drvr_version_show(struct class_device *cdev, char *buf)
++lpfc_drvr_version_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+ return snprintf(buf, PAGE_SIZE, LPFC_MODULE_DESC "\n");
+ }
+
+ static ssize_t
+-lpfc_info_show(struct class_device *cdev, char *buf)
++lpfc_info_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *host = class_to_shost(cdev);
++ struct Scsi_Host *host = class_to_shost(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%s\n",lpfc_info(host));
+ }
+
+ static ssize_t
+-lpfc_serialnum_show(struct class_device *cdev, char *buf)
++lpfc_serialnum_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+
+@@ -90,18 +93,20 @@ lpfc_serialnum_show(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-lpfc_temp_sensor_show(struct class_device *cdev, char *buf)
++lpfc_temp_sensor_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ return snprintf(buf, PAGE_SIZE, "%d\n",phba->temp_sensor_support);
+ }
+
+ static ssize_t
+-lpfc_modeldesc_show(struct class_device *cdev, char *buf)
++lpfc_modeldesc_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+
+@@ -109,9 +114,10 @@ lpfc_modeldesc_show(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-lpfc_modelname_show(struct class_device *cdev, char *buf)
++lpfc_modelname_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+
+@@ -119,9 +125,10 @@ lpfc_modelname_show(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-lpfc_programtype_show(struct class_device *cdev, char *buf)
++lpfc_programtype_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+
+@@ -129,9 +136,10 @@ lpfc_programtype_show(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-lpfc_vportnum_show(struct class_device *cdev, char *buf)
++lpfc_vportnum_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+
+@@ -139,9 +147,10 @@ lpfc_vportnum_show(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-lpfc_fwrev_show(struct class_device *cdev, char *buf)
++lpfc_fwrev_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ char fwrev[32];
+@@ -151,10 +160,10 @@ lpfc_fwrev_show(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-lpfc_hdw_show(struct class_device *cdev, char *buf)
++lpfc_hdw_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+ char hdw[9];
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ lpfc_vpd_t *vp = &phba->vpd;
+@@ -163,18 +172,20 @@ lpfc_hdw_show(struct class_device *cdev, char *buf)
+ return snprintf(buf, PAGE_SIZE, "%s\n", hdw);
+ }
+ static ssize_t
+-lpfc_option_rom_version_show(struct class_device *cdev, char *buf)
++lpfc_option_rom_version_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", phba->OptionROMVersion);
+ }
+ static ssize_t
+-lpfc_state_show(struct class_device *cdev, char *buf)
++lpfc_state_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ int len = 0;
+@@ -243,9 +254,10 @@ lpfc_state_show(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-lpfc_num_discovered_ports_show(struct class_device *cdev, char *buf)
++lpfc_num_discovered_ports_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+@@ -367,9 +379,10 @@ lpfc_selective_reset(struct lpfc_hba *phba)
+ }
+
+ static ssize_t
+-lpfc_issue_reset(struct class_device *cdev, const char *buf, size_t count)
++lpfc_issue_reset(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+
+@@ -385,9 +398,10 @@ lpfc_issue_reset(struct class_device *cdev, const char *buf, size_t count)
+ }
+
+ static ssize_t
+-lpfc_nport_evt_cnt_show(struct class_device *cdev, char *buf)
++lpfc_nport_evt_cnt_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+
+@@ -395,9 +409,10 @@ lpfc_nport_evt_cnt_show(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-lpfc_board_mode_show(struct class_device *cdev, char *buf)
++lpfc_board_mode_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ char * state;
+@@ -415,9 +430,10 @@ lpfc_board_mode_show(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-lpfc_board_mode_store(struct class_device *cdev, const char *buf, size_t count)
++lpfc_board_mode_store(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ struct completion online_compl;
+@@ -509,9 +525,10 @@ lpfc_get_hba_info(struct lpfc_hba *phba,
+ }
+
+ static ssize_t
+-lpfc_max_rpi_show(struct class_device *cdev, char *buf)
++lpfc_max_rpi_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ uint32_t cnt;
+@@ -522,9 +539,10 @@ lpfc_max_rpi_show(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-lpfc_used_rpi_show(struct class_device *cdev, char *buf)
++lpfc_used_rpi_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ uint32_t cnt, acnt;
+@@ -535,9 +553,10 @@ lpfc_used_rpi_show(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-lpfc_max_xri_show(struct class_device *cdev, char *buf)
++lpfc_max_xri_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ uint32_t cnt;
+@@ -548,9 +567,10 @@ lpfc_max_xri_show(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-lpfc_used_xri_show(struct class_device *cdev, char *buf)
++lpfc_used_xri_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ uint32_t cnt, acnt;
+@@ -561,9 +581,10 @@ lpfc_used_xri_show(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-lpfc_max_vpi_show(struct class_device *cdev, char *buf)
++lpfc_max_vpi_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ uint32_t cnt;
+@@ -574,9 +595,10 @@ lpfc_max_vpi_show(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-lpfc_used_vpi_show(struct class_device *cdev, char *buf)
++lpfc_used_vpi_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ uint32_t cnt, acnt;
+@@ -587,9 +609,10 @@ lpfc_used_vpi_show(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-lpfc_npiv_info_show(struct class_device *cdev, char *buf)
++lpfc_npiv_info_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+
+@@ -601,9 +624,10 @@ lpfc_npiv_info_show(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-lpfc_poll_show(struct class_device *cdev, char *buf)
++lpfc_poll_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+
+@@ -611,10 +635,10 @@ lpfc_poll_show(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-lpfc_poll_store(struct class_device *cdev, const char *buf,
+- size_t count)
++lpfc_poll_store(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ uint32_t creg_val;
+@@ -670,9 +694,10 @@ lpfc_poll_store(struct class_device *cdev, const char *buf,
+
+ #define lpfc_param_show(attr) \
+ static ssize_t \
+-lpfc_##attr##_show(struct class_device *cdev, char *buf) \
++lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
++ char *buf) \
+ { \
+- struct Scsi_Host *shost = class_to_shost(cdev);\
++ struct Scsi_Host *shost = class_to_shost(dev);\
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
+ struct lpfc_hba *phba = vport->phba;\
+ int val = 0;\
+@@ -683,9 +708,10 @@ lpfc_##attr##_show(struct class_device *cdev, char *buf) \
+
+ #define lpfc_param_hex_show(attr) \
+ static ssize_t \
+-lpfc_##attr##_show(struct class_device *cdev, char *buf) \
++lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
++ char *buf) \
+ { \
+- struct Scsi_Host *shost = class_to_shost(cdev);\
++ struct Scsi_Host *shost = class_to_shost(dev);\
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
+ struct lpfc_hba *phba = vport->phba;\
+ int val = 0;\
+@@ -725,9 +751,10 @@ lpfc_##attr##_set(struct lpfc_hba *phba, int val) \
+
+ #define lpfc_param_store(attr) \
+ static ssize_t \
+-lpfc_##attr##_store(struct class_device *cdev, const char *buf, size_t count) \
++lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \
++ const char *buf, size_t count) \
+ { \
+- struct Scsi_Host *shost = class_to_shost(cdev);\
++ struct Scsi_Host *shost = class_to_shost(dev);\
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
+ struct lpfc_hba *phba = vport->phba;\
+ int val=0;\
+@@ -743,9 +770,10 @@ lpfc_##attr##_store(struct class_device *cdev, const char *buf, size_t count) \
+
+ #define lpfc_vport_param_show(attr) \
+ static ssize_t \
+-lpfc_##attr##_show(struct class_device *cdev, char *buf) \
++lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
++ char *buf) \
+ { \
+- struct Scsi_Host *shost = class_to_shost(cdev);\
++ struct Scsi_Host *shost = class_to_shost(dev);\
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
+ int val = 0;\
+ val = vport->cfg_##attr;\
+@@ -754,9 +782,10 @@ lpfc_##attr##_show(struct class_device *cdev, char *buf) \
+
+ #define lpfc_vport_param_hex_show(attr) \
+ static ssize_t \
+-lpfc_##attr##_show(struct class_device *cdev, char *buf) \
++lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
++ char *buf) \
+ { \
+- struct Scsi_Host *shost = class_to_shost(cdev);\
++ struct Scsi_Host *shost = class_to_shost(dev);\
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
+ int val = 0;\
+ val = vport->cfg_##attr;\
+@@ -794,9 +823,10 @@ lpfc_##attr##_set(struct lpfc_vport *vport, int val) \
+
+ #define lpfc_vport_param_store(attr) \
+ static ssize_t \
+-lpfc_##attr##_store(struct class_device *cdev, const char *buf, size_t count) \
++lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \
++ const char *buf, size_t count) \
+ { \
+- struct Scsi_Host *shost = class_to_shost(cdev);\
++ struct Scsi_Host *shost = class_to_shost(dev);\
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\
+ int val=0;\
+ if (!isdigit(buf[0]))\
+@@ -822,7 +852,7 @@ module_param(lpfc_##name, int, 0);\
+ MODULE_PARM_DESC(lpfc_##name, desc);\
+ lpfc_param_show(name)\
+ lpfc_param_init(name, defval, minval, maxval)\
+-static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
++static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
+
+ #define LPFC_ATTR_RW(name, defval, minval, maxval, desc) \
+ static int lpfc_##name = defval;\
+@@ -832,8 +862,8 @@ lpfc_param_show(name)\
+ lpfc_param_init(name, defval, minval, maxval)\
+ lpfc_param_set(name, defval, minval, maxval)\
+ lpfc_param_store(name)\
+-static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
+- lpfc_##name##_show, lpfc_##name##_store)
++static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
++ lpfc_##name##_show, lpfc_##name##_store)
+
+ #define LPFC_ATTR_HEX_R(name, defval, minval, maxval, desc) \
+ static int lpfc_##name = defval;\
+@@ -841,7 +871,7 @@ module_param(lpfc_##name, int, 0);\
+ MODULE_PARM_DESC(lpfc_##name, desc);\
+ lpfc_param_hex_show(name)\
+ lpfc_param_init(name, defval, minval, maxval)\
+-static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
++static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
+
+ #define LPFC_ATTR_HEX_RW(name, defval, minval, maxval, desc) \
+ static int lpfc_##name = defval;\
+@@ -851,8 +881,8 @@ lpfc_param_hex_show(name)\
+ lpfc_param_init(name, defval, minval, maxval)\
+ lpfc_param_set(name, defval, minval, maxval)\
+ lpfc_param_store(name)\
+-static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
+- lpfc_##name##_show, lpfc_##name##_store)
++static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
++ lpfc_##name##_show, lpfc_##name##_store)
+
+ #define LPFC_VPORT_ATTR(name, defval, minval, maxval, desc) \
+ static int lpfc_##name = defval;\
+@@ -866,7 +896,7 @@ module_param(lpfc_##name, int, 0);\
+ MODULE_PARM_DESC(lpfc_##name, desc);\
+ lpfc_vport_param_show(name)\
+ lpfc_vport_param_init(name, defval, minval, maxval)\
+-static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
++static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
+
+ #define LPFC_VPORT_ATTR_RW(name, defval, minval, maxval, desc) \
+ static int lpfc_##name = defval;\
+@@ -876,8 +906,8 @@ lpfc_vport_param_show(name)\
+ lpfc_vport_param_init(name, defval, minval, maxval)\
+ lpfc_vport_param_set(name, defval, minval, maxval)\
+ lpfc_vport_param_store(name)\
+-static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
+- lpfc_##name##_show, lpfc_##name##_store)
++static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
++ lpfc_##name##_show, lpfc_##name##_store)
+
+ #define LPFC_VPORT_ATTR_HEX_R(name, defval, minval, maxval, desc) \
+ static int lpfc_##name = defval;\
+@@ -885,7 +915,7 @@ module_param(lpfc_##name, int, 0);\
+ MODULE_PARM_DESC(lpfc_##name, desc);\
+ lpfc_vport_param_hex_show(name)\
+ lpfc_vport_param_init(name, defval, minval, maxval)\
+-static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
++static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
+
+ #define LPFC_VPORT_ATTR_HEX_RW(name, defval, minval, maxval, desc) \
+ static int lpfc_##name = defval;\
+@@ -895,46 +925,44 @@ lpfc_vport_param_hex_show(name)\
+ lpfc_vport_param_init(name, defval, minval, maxval)\
+ lpfc_vport_param_set(name, defval, minval, maxval)\
+ lpfc_vport_param_store(name)\
+-static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
+- lpfc_##name##_show, lpfc_##name##_store)
+-
+-static CLASS_DEVICE_ATTR(info, S_IRUGO, lpfc_info_show, NULL);
+-static CLASS_DEVICE_ATTR(serialnum, S_IRUGO, lpfc_serialnum_show, NULL);
+-static CLASS_DEVICE_ATTR(modeldesc, S_IRUGO, lpfc_modeldesc_show, NULL);
+-static CLASS_DEVICE_ATTR(modelname, S_IRUGO, lpfc_modelname_show, NULL);
+-static CLASS_DEVICE_ATTR(programtype, S_IRUGO, lpfc_programtype_show, NULL);
+-static CLASS_DEVICE_ATTR(portnum, S_IRUGO, lpfc_vportnum_show, NULL);
+-static CLASS_DEVICE_ATTR(fwrev, S_IRUGO, lpfc_fwrev_show, NULL);
+-static CLASS_DEVICE_ATTR(hdw, S_IRUGO, lpfc_hdw_show, NULL);
+-static CLASS_DEVICE_ATTR(state, S_IRUGO, lpfc_state_show, NULL);
+-static CLASS_DEVICE_ATTR(option_rom_version, S_IRUGO,
+- lpfc_option_rom_version_show, NULL);
+-static CLASS_DEVICE_ATTR(num_discovered_ports, S_IRUGO,
+- lpfc_num_discovered_ports_show, NULL);
+-static CLASS_DEVICE_ATTR(nport_evt_cnt, S_IRUGO, lpfc_nport_evt_cnt_show, NULL);
+-static CLASS_DEVICE_ATTR(lpfc_drvr_version, S_IRUGO, lpfc_drvr_version_show,
+- NULL);
+-static CLASS_DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR,
+- lpfc_board_mode_show, lpfc_board_mode_store);
+-static CLASS_DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset);
+-static CLASS_DEVICE_ATTR(max_vpi, S_IRUGO, lpfc_max_vpi_show, NULL);
+-static CLASS_DEVICE_ATTR(used_vpi, S_IRUGO, lpfc_used_vpi_show, NULL);
+-static CLASS_DEVICE_ATTR(max_rpi, S_IRUGO, lpfc_max_rpi_show, NULL);
+-static CLASS_DEVICE_ATTR(used_rpi, S_IRUGO, lpfc_used_rpi_show, NULL);
+-static CLASS_DEVICE_ATTR(max_xri, S_IRUGO, lpfc_max_xri_show, NULL);
+-static CLASS_DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL);
+-static CLASS_DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL);
+-static CLASS_DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show,
+- NULL);
++static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
++ lpfc_##name##_show, lpfc_##name##_store)
++
++static DEVICE_ATTR(info, S_IRUGO, lpfc_info_show, NULL);
++static DEVICE_ATTR(serialnum, S_IRUGO, lpfc_serialnum_show, NULL);
++static DEVICE_ATTR(modeldesc, S_IRUGO, lpfc_modeldesc_show, NULL);
++static DEVICE_ATTR(modelname, S_IRUGO, lpfc_modelname_show, NULL);
++static DEVICE_ATTR(programtype, S_IRUGO, lpfc_programtype_show, NULL);
++static DEVICE_ATTR(portnum, S_IRUGO, lpfc_vportnum_show, NULL);
++static DEVICE_ATTR(fwrev, S_IRUGO, lpfc_fwrev_show, NULL);
++static DEVICE_ATTR(hdw, S_IRUGO, lpfc_hdw_show, NULL);
++static DEVICE_ATTR(state, S_IRUGO, lpfc_state_show, NULL);
++static DEVICE_ATTR(option_rom_version, S_IRUGO,
++ lpfc_option_rom_version_show, NULL);
++static DEVICE_ATTR(num_discovered_ports, S_IRUGO,
++ lpfc_num_discovered_ports_show, NULL);
++static DEVICE_ATTR(nport_evt_cnt, S_IRUGO, lpfc_nport_evt_cnt_show, NULL);
++static DEVICE_ATTR(lpfc_drvr_version, S_IRUGO, lpfc_drvr_version_show, NULL);
++static DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR,
++ lpfc_board_mode_show, lpfc_board_mode_store);
++static DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset);
++static DEVICE_ATTR(max_vpi, S_IRUGO, lpfc_max_vpi_show, NULL);
++static DEVICE_ATTR(used_vpi, S_IRUGO, lpfc_used_vpi_show, NULL);
++static DEVICE_ATTR(max_rpi, S_IRUGO, lpfc_max_rpi_show, NULL);
++static DEVICE_ATTR(used_rpi, S_IRUGO, lpfc_used_rpi_show, NULL);
++static DEVICE_ATTR(max_xri, S_IRUGO, lpfc_max_xri_show, NULL);
++static DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL);
++static DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL);
++static DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show, NULL);
+
+
+ static char *lpfc_soft_wwn_key = "C99G71SL8032A";
+
+ static ssize_t
+-lpfc_soft_wwn_enable_store(struct class_device *cdev, const char *buf,
+- size_t count)
++lpfc_soft_wwn_enable_store(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ unsigned int cnt = count;
+@@ -963,13 +991,14 @@ lpfc_soft_wwn_enable_store(struct class_device *cdev, const char *buf,
+ phba->soft_wwn_enable = 1;
+ return count;
+ }
+-static CLASS_DEVICE_ATTR(lpfc_soft_wwn_enable, S_IWUSR, NULL,
+- lpfc_soft_wwn_enable_store);
++static DEVICE_ATTR(lpfc_soft_wwn_enable, S_IWUSR, NULL,
++ lpfc_soft_wwn_enable_store);
+
+ static ssize_t
+-lpfc_soft_wwpn_show(struct class_device *cdev, char *buf)
++lpfc_soft_wwpn_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+
+@@ -979,9 +1008,10 @@ lpfc_soft_wwpn_show(struct class_device *cdev, char *buf)
+
+
+ static ssize_t
+-lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count)
++lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ struct completion online_compl;
+@@ -1047,13 +1077,14 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count)
+ "reinit adapter - %d\n", stat2);
+ return (stat1 || stat2) ? -EIO : count;
+ }
+-static CLASS_DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\
+- lpfc_soft_wwpn_show, lpfc_soft_wwpn_store);
++static DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\
++ lpfc_soft_wwpn_show, lpfc_soft_wwpn_store);
+
+ static ssize_t
+-lpfc_soft_wwnn_show(struct class_device *cdev, char *buf)
++lpfc_soft_wwnn_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
+ return snprintf(buf, PAGE_SIZE, "0x%llx\n",
+ (unsigned long long)phba->cfg_soft_wwnn);
+@@ -1061,9 +1092,10 @@ lpfc_soft_wwnn_show(struct class_device *cdev, char *buf)
+
+
+ static ssize_t
+-lpfc_soft_wwnn_store(struct class_device *cdev, const char *buf, size_t count)
++lpfc_soft_wwnn_store(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
+ unsigned int i, j, cnt=count;
+ u8 wwnn[8];
+@@ -1107,8 +1139,8 @@ lpfc_soft_wwnn_store(struct class_device *cdev, const char *buf, size_t count)
+
+ return count;
+ }
+-static CLASS_DEVICE_ATTR(lpfc_soft_wwnn, S_IRUGO | S_IWUSR,\
+- lpfc_soft_wwnn_show, lpfc_soft_wwnn_store);
++static DEVICE_ATTR(lpfc_soft_wwnn, S_IRUGO | S_IWUSR,\
++ lpfc_soft_wwnn_show, lpfc_soft_wwnn_store);
+
+
+ static int lpfc_poll = 0;
+@@ -1118,8 +1150,8 @@ MODULE_PARM_DESC(lpfc_poll, "FCP ring polling mode control:"
+ " 1 - poll with interrupts enabled"
+ " 3 - poll and disable FCP ring interrupts");
+
+-static CLASS_DEVICE_ATTR(lpfc_poll, S_IRUGO | S_IWUSR,
+- lpfc_poll_show, lpfc_poll_store);
++static DEVICE_ATTR(lpfc_poll, S_IRUGO | S_IWUSR,
++ lpfc_poll_show, lpfc_poll_store);
+
+ int lpfc_sli_mode = 0;
+ module_param(lpfc_sli_mode, int, 0);
+@@ -1133,7 +1165,7 @@ module_param(lpfc_enable_npiv, int, 0);
+ MODULE_PARM_DESC(lpfc_enable_npiv, "Enable NPIV functionality");
+ lpfc_param_show(enable_npiv);
+ lpfc_param_init(enable_npiv, 0, 0, 1);
+-static CLASS_DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO,
++static DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO,
+ lpfc_enable_npiv_show, NULL);
+
+ /*
+@@ -1147,9 +1179,10 @@ MODULE_PARM_DESC(lpfc_nodev_tmo,
+ "Seconds driver will hold I/O waiting "
+ "for a device to come back");
+ static ssize_t
+-lpfc_nodev_tmo_show(struct class_device *cdev, char *buf)
++lpfc_nodev_tmo_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ int val = 0;
+ val = vport->cfg_devloss_tmo;
+@@ -1221,8 +1254,8 @@ lpfc_nodev_tmo_set(struct lpfc_vport *vport, int val)
+
+ lpfc_vport_param_store(nodev_tmo)
+
+-static CLASS_DEVICE_ATTR(lpfc_nodev_tmo, S_IRUGO | S_IWUSR,
+- lpfc_nodev_tmo_show, lpfc_nodev_tmo_store);
++static DEVICE_ATTR(lpfc_nodev_tmo, S_IRUGO | S_IWUSR,
++ lpfc_nodev_tmo_show, lpfc_nodev_tmo_store);
+
+ /*
+ # lpfc_devloss_tmo: If set, it will hold all I/O errors on devices that
+@@ -1255,8 +1288,8 @@ lpfc_devloss_tmo_set(struct lpfc_vport *vport, int val)
+ }
+
+ lpfc_vport_param_store(devloss_tmo)
+-static CLASS_DEVICE_ATTR(lpfc_devloss_tmo, S_IRUGO | S_IWUSR,
+- lpfc_devloss_tmo_show, lpfc_devloss_tmo_store);
++static DEVICE_ATTR(lpfc_devloss_tmo, S_IRUGO | S_IWUSR,
++ lpfc_devloss_tmo_show, lpfc_devloss_tmo_store);
+
+ /*
+ # lpfc_log_verbose: Only turn this flag on if you are willing to risk being
+@@ -1374,8 +1407,8 @@ lpfc_restrict_login_set(struct lpfc_vport *vport, int val)
+ return 0;
+ }
+ lpfc_vport_param_store(restrict_login);
+-static CLASS_DEVICE_ATTR(lpfc_restrict_login, S_IRUGO | S_IWUSR,
+- lpfc_restrict_login_show, lpfc_restrict_login_store);
++static DEVICE_ATTR(lpfc_restrict_login, S_IRUGO | S_IWUSR,
++ lpfc_restrict_login_show, lpfc_restrict_login_store);
+
+ /*
+ # Some disk devices have a "select ID" or "select Target" capability.
+@@ -1433,7 +1466,7 @@ MODULE_PARM_DESC(lpfc_topology, "Select Fibre Channel topology");
+ lpfc_param_show(topology)
+ lpfc_param_init(topology, 0, 0, 6)
+ lpfc_param_store(topology)
+-static CLASS_DEVICE_ATTR(lpfc_topology, S_IRUGO | S_IWUSR,
++static DEVICE_ATTR(lpfc_topology, S_IRUGO | S_IWUSR,
+ lpfc_topology_show, lpfc_topology_store);
+
+ /*
+@@ -1497,7 +1530,7 @@ lpfc_link_speed_init(struct lpfc_hba *phba, int val)
+ }
+
+ lpfc_param_store(link_speed)
+-static CLASS_DEVICE_ATTR(lpfc_link_speed, S_IRUGO | S_IWUSR,
++static DEVICE_ATTR(lpfc_link_speed, S_IRUGO | S_IWUSR,
+ lpfc_link_speed_show, lpfc_link_speed_store);
+
+ /*
+@@ -1623,82 +1656,81 @@ LPFC_ATTR_R(enable_hba_heartbeat, 1, 0, 1, "Enable HBA Heartbeat.");
+ LPFC_ATTR_R(sg_seg_cnt, LPFC_DEFAULT_SG_SEG_CNT, LPFC_DEFAULT_SG_SEG_CNT,
+ LPFC_MAX_SG_SEG_CNT, "Max Scatter Gather Segment Count");
+
+-struct class_device_attribute *lpfc_hba_attrs[] = {
+- &class_device_attr_info,
+- &class_device_attr_serialnum,
+- &class_device_attr_modeldesc,
+- &class_device_attr_modelname,
+- &class_device_attr_programtype,
+- &class_device_attr_portnum,
+- &class_device_attr_fwrev,
+- &class_device_attr_hdw,
+- &class_device_attr_option_rom_version,
+- &class_device_attr_state,
+- &class_device_attr_num_discovered_ports,
+- &class_device_attr_lpfc_drvr_version,
+- &class_device_attr_lpfc_temp_sensor,
+- &class_device_attr_lpfc_log_verbose,
+- &class_device_attr_lpfc_lun_queue_depth,
+- &class_device_attr_lpfc_hba_queue_depth,
+- &class_device_attr_lpfc_peer_port_login,
+- &class_device_attr_lpfc_nodev_tmo,
+- &class_device_attr_lpfc_devloss_tmo,
+- &class_device_attr_lpfc_fcp_class,
+- &class_device_attr_lpfc_use_adisc,
+- &class_device_attr_lpfc_ack0,
+- &class_device_attr_lpfc_topology,
+- &class_device_attr_lpfc_scan_down,
+- &class_device_attr_lpfc_link_speed,
+- &class_device_attr_lpfc_cr_delay,
+- &class_device_attr_lpfc_cr_count,
+- &class_device_attr_lpfc_multi_ring_support,
+- &class_device_attr_lpfc_multi_ring_rctl,
+- &class_device_attr_lpfc_multi_ring_type,
+- &class_device_attr_lpfc_fdmi_on,
+- &class_device_attr_lpfc_max_luns,
+- &class_device_attr_lpfc_enable_npiv,
+- &class_device_attr_nport_evt_cnt,
+- &class_device_attr_board_mode,
+- &class_device_attr_max_vpi,
+- &class_device_attr_used_vpi,
+- &class_device_attr_max_rpi,
+- &class_device_attr_used_rpi,
+- &class_device_attr_max_xri,
+- &class_device_attr_used_xri,
+- &class_device_attr_npiv_info,
+- &class_device_attr_issue_reset,
+- &class_device_attr_lpfc_poll,
+- &class_device_attr_lpfc_poll_tmo,
+- &class_device_attr_lpfc_use_msi,
+- &class_device_attr_lpfc_soft_wwnn,
+- &class_device_attr_lpfc_soft_wwpn,
+- &class_device_attr_lpfc_soft_wwn_enable,
+- &class_device_attr_lpfc_enable_hba_reset,
+- &class_device_attr_lpfc_enable_hba_heartbeat,
+- &class_device_attr_lpfc_sg_seg_cnt,
++struct device_attribute *lpfc_hba_attrs[] = {
++ &dev_attr_info,
++ &dev_attr_serialnum,
++ &dev_attr_modeldesc,
++ &dev_attr_modelname,
++ &dev_attr_programtype,
++ &dev_attr_portnum,
++ &dev_attr_fwrev,
++ &dev_attr_hdw,
++ &dev_attr_option_rom_version,
++ &dev_attr_state,
++ &dev_attr_num_discovered_ports,
++ &dev_attr_lpfc_drvr_version,
++ &dev_attr_lpfc_temp_sensor,
++ &dev_attr_lpfc_log_verbose,
++ &dev_attr_lpfc_lun_queue_depth,
++ &dev_attr_lpfc_hba_queue_depth,
++ &dev_attr_lpfc_peer_port_login,
++ &dev_attr_lpfc_nodev_tmo,
++ &dev_attr_lpfc_devloss_tmo,
++ &dev_attr_lpfc_fcp_class,
++ &dev_attr_lpfc_use_adisc,
++ &dev_attr_lpfc_ack0,
++ &dev_attr_lpfc_topology,
++ &dev_attr_lpfc_scan_down,
++ &dev_attr_lpfc_link_speed,
++ &dev_attr_lpfc_cr_delay,
++ &dev_attr_lpfc_cr_count,
++ &dev_attr_lpfc_multi_ring_support,
++ &dev_attr_lpfc_multi_ring_rctl,
++ &dev_attr_lpfc_multi_ring_type,
++ &dev_attr_lpfc_fdmi_on,
++ &dev_attr_lpfc_max_luns,
++ &dev_attr_lpfc_enable_npiv,
++ &dev_attr_nport_evt_cnt,
++ &dev_attr_board_mode,
++ &dev_attr_max_vpi,
++ &dev_attr_used_vpi,
++ &dev_attr_max_rpi,
++ &dev_attr_used_rpi,
++ &dev_attr_max_xri,
++ &dev_attr_used_xri,
++ &dev_attr_npiv_info,
++ &dev_attr_issue_reset,
++ &dev_attr_lpfc_poll,
++ &dev_attr_lpfc_poll_tmo,
++ &dev_attr_lpfc_use_msi,
++ &dev_attr_lpfc_soft_wwnn,
++ &dev_attr_lpfc_soft_wwpn,
++ &dev_attr_lpfc_soft_wwn_enable,
++ &dev_attr_lpfc_enable_hba_reset,
++ &dev_attr_lpfc_enable_hba_heartbeat,
++ &dev_attr_lpfc_sg_seg_cnt,
+ NULL,
+ };
+
+-struct class_device_attribute *lpfc_vport_attrs[] = {
+- &class_device_attr_info,
+- &class_device_attr_state,
+- &class_device_attr_num_discovered_ports,
+- &class_device_attr_lpfc_drvr_version,
+-
+- &class_device_attr_lpfc_log_verbose,
+- &class_device_attr_lpfc_lun_queue_depth,
+- &class_device_attr_lpfc_nodev_tmo,
+- &class_device_attr_lpfc_devloss_tmo,
+- &class_device_attr_lpfc_hba_queue_depth,
+- &class_device_attr_lpfc_peer_port_login,
+- &class_device_attr_lpfc_restrict_login,
+- &class_device_attr_lpfc_fcp_class,
+- &class_device_attr_lpfc_use_adisc,
+- &class_device_attr_lpfc_fdmi_on,
+- &class_device_attr_lpfc_max_luns,
+- &class_device_attr_nport_evt_cnt,
+- &class_device_attr_npiv_info,
+- &class_device_attr_lpfc_enable_da_id,
++struct device_attribute *lpfc_vport_attrs[] = {
++ &dev_attr_info,
++ &dev_attr_state,
++ &dev_attr_num_discovered_ports,
++ &dev_attr_lpfc_drvr_version,
++ &dev_attr_lpfc_log_verbose,
++ &dev_attr_lpfc_lun_queue_depth,
++ &dev_attr_lpfc_nodev_tmo,
++ &dev_attr_lpfc_devloss_tmo,
++ &dev_attr_lpfc_hba_queue_depth,
++ &dev_attr_lpfc_peer_port_login,
++ &dev_attr_lpfc_restrict_login,
++ &dev_attr_lpfc_fcp_class,
++ &dev_attr_lpfc_use_adisc,
++ &dev_attr_lpfc_fdmi_on,
++ &dev_attr_lpfc_max_luns,
++ &dev_attr_nport_evt_cnt,
++ &dev_attr_npiv_info,
++ &dev_attr_lpfc_enable_da_id,
+ NULL,
+ };
+
+@@ -1707,9 +1739,8 @@ sysfs_ctlreg_write(struct kobject *kobj, struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+ {
+ size_t buf_off;
+- struct class_device *cdev = container_of(kobj, struct class_device,
+- kobj);
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct device *dev = container_of(kobj, struct device, kobj);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+
+@@ -1741,9 +1772,8 @@ sysfs_ctlreg_read(struct kobject *kobj, struct bin_attribute *bin_attr,
+ {
+ size_t buf_off;
+ uint32_t * tmp_ptr;
+- struct class_device *cdev = container_of(kobj, struct class_device,
+- kobj);
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct device *dev = container_of(kobj, struct device, kobj);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+
+@@ -1798,9 +1828,8 @@ static ssize_t
+ sysfs_mbox_write(struct kobject *kobj, struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+ {
+- struct class_device *cdev = container_of(kobj, struct class_device,
+- kobj);
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct device *dev = container_of(kobj, struct device, kobj);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ struct lpfcMboxq *mbox = NULL;
+@@ -1853,9 +1882,8 @@ static ssize_t
+ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+ {
+- struct class_device *cdev = container_of(kobj, struct class_device,
+- kobj);
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct device *dev = container_of(kobj, struct device, kobj);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ int rc;
+@@ -1954,7 +1982,9 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr,
+ (phba->sysfs_mbox.mbox->mb.mbxCommand !=
+ MBX_DUMP_MEMORY &&
+ phba->sysfs_mbox.mbox->mb.mbxCommand !=
+- MBX_RESTART)) {
++ MBX_RESTART &&
++ phba->sysfs_mbox.mbox->mb.mbxCommand !=
++ MBX_WRITE_VPARMS)) {
+ sysfs_mbox_idle(phba);
+ spin_unlock_irq(&phba->hbalock);
+ return -EPERM;
+@@ -1962,7 +1992,11 @@ sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr,
+
+ phba->sysfs_mbox.mbox->vport = vport;
+
+- if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) {
++ /* Don't allow mailbox commands to be sent when blocked
++ * or when in the middle of discovery
++ */
++ if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO ||
++ vport->fc_flag & FC_NDISC_ACTIVE) {
+ sysfs_mbox_idle(phba);
+ spin_unlock_irq(&phba->hbalock);
+ return -EAGAIN;
+@@ -2032,19 +2066,19 @@ lpfc_alloc_sysfs_attr(struct lpfc_vport *vport)
+ struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+ int error;
+
+- error = sysfs_create_bin_file(&shost->shost_classdev.kobj,
++ error = sysfs_create_bin_file(&shost->shost_dev.kobj,
+ &sysfs_ctlreg_attr);
+ if (error)
+ goto out;
+
+- error = sysfs_create_bin_file(&shost->shost_classdev.kobj,
++ error = sysfs_create_bin_file(&shost->shost_dev.kobj,
+ &sysfs_mbox_attr);
+ if (error)
+ goto out_remove_ctlreg_attr;
+
+ return 0;
+ out_remove_ctlreg_attr:
+- sysfs_remove_bin_file(&shost->shost_classdev.kobj, &sysfs_ctlreg_attr);
++ sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_ctlreg_attr);
+ out:
+ return error;
+ }
+@@ -2054,8 +2088,8 @@ lpfc_free_sysfs_attr(struct lpfc_vport *vport)
+ {
+ struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
+- sysfs_remove_bin_file(&shost->shost_classdev.kobj, &sysfs_mbox_attr);
+- sysfs_remove_bin_file(&shost->shost_classdev.kobj, &sysfs_ctlreg_attr);
++ sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_mbox_attr);
++ sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_ctlreg_attr);
+ }
+
+
+@@ -2437,9 +2471,11 @@ lpfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
+
+ #define lpfc_rport_show_function(field, format_string, sz, cast) \
+ static ssize_t \
+-lpfc_show_rport_##field (struct class_device *cdev, char *buf) \
++lpfc_show_rport_##field (struct device *dev, \
++ struct device_attribute *attr, \
++ char *buf) \
+ { \
+- struct fc_rport *rport = transport_class_to_rport(cdev); \
++ struct fc_rport *rport = transport_class_to_rport(dev); \
+ struct lpfc_rport_data *rdata = rport->hostdata; \
+ return snprintf(buf, sz, format_string, \
+ (rdata->target) ? cast rdata->target->field : 0); \
+diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
+index 0819f5f..7c9f831 100644
+--- a/drivers/scsi/lpfc/lpfc_crtn.h
++++ b/drivers/scsi/lpfc/lpfc_crtn.h
+@@ -253,8 +253,8 @@ void lpfc_get_cfgparam(struct lpfc_hba *);
+ void lpfc_get_vport_cfgparam(struct lpfc_vport *);
+ int lpfc_alloc_sysfs_attr(struct lpfc_vport *);
+ void lpfc_free_sysfs_attr(struct lpfc_vport *);
+-extern struct class_device_attribute *lpfc_hba_attrs[];
+-extern struct class_device_attribute *lpfc_vport_attrs[];
++extern struct device_attribute *lpfc_hba_attrs[];
++extern struct device_attribute *lpfc_vport_attrs[];
+ extern struct scsi_host_template lpfc_template;
+ extern struct scsi_host_template lpfc_vport_template;
+ extern struct fc_function_template lpfc_transport_functions;
+diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
+index 3d0ccd9..153afae 100644
+--- a/drivers/scsi/lpfc/lpfc_ct.c
++++ b/drivers/scsi/lpfc/lpfc_ct.c
+@@ -63,7 +63,7 @@ lpfc_ct_ignore_hbq_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
+ {
+ if (!mp) {
+ lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+- "0146 Ignoring unsolicted CT No HBQ "
++ "0146 Ignoring unsolicited CT No HBQ "
+ "status = x%x\n",
+ piocbq->iocb.ulpStatus);
+ }
+@@ -438,7 +438,7 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size)
+ (!(vport->ct_flags & FC_CT_RFF_ID)) ||
+ (!vport->cfg_restrict_login)) {
+ ndlp = lpfc_setup_disc_node(vport, Did);
+- if (ndlp) {
++ if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
+ lpfc_debugfs_disc_trc(vport,
+ LPFC_DISC_TRC_CT,
+ "Parse GID_FTrsp: "
+@@ -543,7 +543,7 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ struct lpfc_dmabuf *outp;
+ struct lpfc_sli_ct_request *CTrsp;
+ struct lpfc_nodelist *ndlp;
+- int rc, retry;
++ int rc;
+
+ /* First save ndlp, before we overwrite it */
+ ndlp = cmdiocb->context_un.ndlp;
+@@ -563,45 +563,29 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ if (vport->load_flag & FC_UNLOADING)
+ goto out;
+
+- if (lpfc_els_chk_latt(vport) || lpfc_error_lost_link(irsp)) {
++ if (lpfc_els_chk_latt(vport)) {
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ "0216 Link event during NS query\n");
+ lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+ goto out;
+ }
+-
++ if (lpfc_error_lost_link(irsp)) {
++ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
++ "0226 NS query failed due to link event\n");
++ goto out;
++ }
+ if (irsp->ulpStatus) {
+ /* Check for retry */
+ if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) {
+- retry = 1;
+- if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
+- switch (irsp->un.ulpWord[4]) {
+- case IOERR_NO_RESOURCES:
+- /* We don't increment the retry
+- * count for this case.
+- */
+- break;
+- case IOERR_LINK_DOWN:
+- case IOERR_SLI_ABORTED:
+- case IOERR_SLI_DOWN:
+- retry = 0;
+- break;
+- default:
+- vport->fc_ns_retry++;
+- }
+- }
+- else
++ if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT ||
++ irsp->un.ulpWord[4] != IOERR_NO_RESOURCES)
+ vport->fc_ns_retry++;
+
+- if (retry) {
+- /* CT command is being retried */
+- rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT,
++ /* CT command is being retried */
++ rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT,
+ vport->fc_ns_retry, 0);
+- if (rc == 0) {
+- /* success */
+- goto out;
+- }
+- }
++ if (rc == 0)
++ goto out;
+ }
+ lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+@@ -780,7 +764,7 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+
+ /* This is a target port, unregistered port, or the GFF_ID failed */
+ ndlp = lpfc_setup_disc_node(vport, did);
+- if (ndlp) {
++ if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ "0242 Process x%x GFF "
+ "NameServer Rsp Data: x%x x%x x%x\n",
+diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
+index 783d1ee..90272e6 100644
+--- a/drivers/scsi/lpfc/lpfc_debugfs.c
++++ b/drivers/scsi/lpfc/lpfc_debugfs.c
+@@ -503,6 +503,8 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
+ ndlp->nlp_sid);
+ if (ndlp->nlp_type & NLP_FCP_INITIATOR)
+ len += snprintf(buf+len, size-len, "FCP_INITIATOR ");
++ len += snprintf(buf+len, size-len, "usgmap:%x ",
++ ndlp->nlp_usg_map);
+ len += snprintf(buf+len, size-len, "refcnt:%x",
+ atomic_read(&ndlp->kref.refcount));
+ len += snprintf(buf+len, size-len, "\n");
+diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
+index cbb68a9..886c5f1 100644
+--- a/drivers/scsi/lpfc/lpfc_els.c
++++ b/drivers/scsi/lpfc/lpfc_els.c
+@@ -719,9 +719,9 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba)
+ if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR &&
+ icmd->un.elsreq64.bdl.ulpIoTag32) {
+ ndlp = (struct lpfc_nodelist *)(iocb->context1);
+- if (ndlp && (ndlp->nlp_DID == Fabric_DID)) {
++ if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
++ (ndlp->nlp_DID == Fabric_DID))
+ lpfc_sli_issue_abort_iotag(phba, pring, iocb);
+- }
+ }
+ }
+ spin_unlock_irq(&phba->hbalock);
+@@ -829,7 +829,7 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
+ struct fc_rport *rport;
+ struct serv_parm *sp;
+ uint8_t name[sizeof(struct lpfc_name)];
+- uint32_t rc;
++ uint32_t rc, keepDID = 0;
+
+ /* Fabric nodes can have the same WWPN so we don't bother searching
+ * by WWPN. Just return the ndlp that was given to us.
+@@ -858,11 +858,17 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
+ return ndlp;
+ lpfc_nlp_init(vport, new_ndlp, ndlp->nlp_DID);
+ } else if (!NLP_CHK_NODE_ACT(new_ndlp)) {
++ rc = memcmp(&ndlp->nlp_portname, name,
++ sizeof(struct lpfc_name));
++ if (!rc)
++ return ndlp;
+ new_ndlp = lpfc_enable_node(vport, new_ndlp,
+ NLP_STE_UNUSED_NODE);
+ if (!new_ndlp)
+ return ndlp;
+- }
++ keepDID = new_ndlp->nlp_DID;
++ } else
++ keepDID = new_ndlp->nlp_DID;
+
+ lpfc_unreg_rpi(vport, new_ndlp);
+ new_ndlp->nlp_DID = ndlp->nlp_DID;
+@@ -893,12 +899,24 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
+ }
+ new_ndlp->nlp_type = ndlp->nlp_type;
+ }
++ /* We shall actually free the ndlp with both nlp_DID and
++ * nlp_portname fields equals 0 to avoid any ndlp on the
++ * nodelist never to be used.
++ */
++ if (ndlp->nlp_DID == 0) {
++ spin_lock_irq(&phba->ndlp_lock);
++ NLP_SET_FREE_REQ(ndlp);
++ spin_unlock_irq(&phba->ndlp_lock);
++ }
+
++ /* Two ndlps cannot have the same did on the nodelist */
++ ndlp->nlp_DID = keepDID;
+ lpfc_drop_node(vport, ndlp);
+ }
+ else {
+ lpfc_unreg_rpi(vport, ndlp);
+- ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */
++ /* Two ndlps cannot have the same did */
++ ndlp->nlp_DID = keepDID;
+ lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+ }
+ return new_ndlp;
+@@ -2091,7 +2109,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ }
+
+ phba->fc_stat.elsXmitRetry++;
+- if (ndlp && delay) {
++ if (ndlp && NLP_CHK_NODE_ACT(ndlp) && delay) {
+ phba->fc_stat.elsDelayRetry++;
+ ndlp->nlp_retry = cmdiocb->retry;
+
+@@ -2121,7 +2139,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ lpfc_issue_els_fdisc(vport, ndlp, cmdiocb->retry);
+ return 1;
+ case ELS_CMD_PLOGI:
+- if (ndlp) {
++ if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
+ ndlp->nlp_prev_state = ndlp->nlp_state;
+ lpfc_nlp_set_state(vport, ndlp,
+ NLP_STE_PLOGI_ISSUE);
+@@ -2302,7 +2320,7 @@ lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+ lpfc_mbuf_free(phba, mp->virt, mp->phys);
+ kfree(mp);
+ mempool_free(pmb, phba->mbox_mem_pool);
+- if (ndlp) {
++ if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
+ lpfc_nlp_put(ndlp);
+ /* This is the end of the default RPI cleanup logic for this
+ * ndlp. If no other discovery threads are using this ndlp.
+@@ -2335,7 +2353,8 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ * function can have cmdiocb->contest1 (ndlp) field set to NULL.
+ */
+ pcmd = (uint8_t *) (((struct lpfc_dmabuf *) cmdiocb->context2)->virt);
+- if (ndlp && (*((uint32_t *) (pcmd)) == ELS_CMD_LS_RJT)) {
++ if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
++ (*((uint32_t *) (pcmd)) == ELS_CMD_LS_RJT)) {
+ /* A LS_RJT associated with Default RPI cleanup has its own
+ * seperate code path.
+ */
+@@ -2344,7 +2363,7 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ }
+
+ /* Check to see if link went down during discovery */
+- if (!ndlp || lpfc_els_chk_latt(vport)) {
++ if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) || lpfc_els_chk_latt(vport)) {
+ if (mbox) {
+ mp = (struct lpfc_dmabuf *) mbox->context1;
+ if (mp) {
+@@ -2353,7 +2372,8 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ }
+ mempool_free(mbox, phba->mbox_mem_pool);
+ }
+- if (ndlp && (ndlp->nlp_flag & NLP_RM_DFLT_RPI))
++ if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
++ (ndlp->nlp_flag & NLP_RM_DFLT_RPI))
+ if (lpfc_nlp_not_used(ndlp)) {
+ ndlp = NULL;
+ /* Indicate the node has already released,
+@@ -2443,7 +2463,7 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ mempool_free(mbox, phba->mbox_mem_pool);
+ }
+ out:
+- if (ndlp) {
++ if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
+ spin_lock_irq(shost->host_lock);
+ ndlp->nlp_flag &= ~(NLP_ACC_REGLOGIN | NLP_RM_DFLT_RPI);
+ spin_unlock_irq(shost->host_lock);
+@@ -3139,6 +3159,8 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+ /* Another thread is walking fc_rscn_id_list on this vport */
+ spin_unlock_irq(shost->host_lock);
+ vport->fc_flag |= FC_RSCN_DISCOVERY;
++ /* Send back ACC */
++ lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
+ return 0;
+ }
+ /* Indicate we are walking fc_rscn_id_list on this vport */
+@@ -3928,7 +3950,7 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport)
+ else {
+ struct lpfc_nodelist *ndlp;
+ ndlp = __lpfc_findnode_rpi(vport, cmd->ulpContext);
+- if (ndlp)
++ if (ndlp && NLP_CHK_NODE_ACT(ndlp))
+ remote_ID = ndlp->nlp_DID;
+ }
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+@@ -4097,21 +4119,22 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ newnode = 1;
+ if ((did & Fabric_DID_MASK) == Fabric_DID_MASK)
+ ndlp->nlp_type |= NLP_FABRIC;
+- } else {
+- if (!NLP_CHK_NODE_ACT(ndlp)) {
+- ndlp = lpfc_enable_node(vport, ndlp,
+- NLP_STE_UNUSED_NODE);
+- if (!ndlp)
+- goto dropit;
+- }
+- if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) {
+- /* This is simular to the new node path */
+- ndlp = lpfc_nlp_get(ndlp);
+- if (!ndlp)
+- goto dropit;
+- lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+- newnode = 1;
+- }
++ } else if (!NLP_CHK_NODE_ACT(ndlp)) {
++ ndlp = lpfc_enable_node(vport, ndlp,
++ NLP_STE_UNUSED_NODE);
++ if (!ndlp)
++ goto dropit;
++ lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
++ newnode = 1;
++ if ((did & Fabric_DID_MASK) == Fabric_DID_MASK)
++ ndlp->nlp_type |= NLP_FABRIC;
++ } else if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) {
++ /* This is similar to the new node path */
++ ndlp = lpfc_nlp_get(ndlp);
++ if (!ndlp)
++ goto dropit;
++ lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
++ newnode = 1;
+ }
+
+ phba->fc_stat.elsRcvFrame++;
+@@ -4451,7 +4474,6 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
+ return;
+ }
+ lpfc_nlp_init(vport, ndlp, NameServer_DID);
+- ndlp->nlp_type |= NLP_FABRIC;
+ } else if (!NLP_CHK_NODE_ACT(ndlp)) {
+ ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE);
+ if (!ndlp) {
+@@ -4465,6 +4487,7 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
+ return;
+ }
+ }
++ ndlp->nlp_type |= NLP_FABRIC;
+
+ lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
+
+@@ -4481,8 +4504,8 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
+ if (ndlp_fdmi) {
+ lpfc_nlp_init(vport, ndlp_fdmi, FDMI_DID);
+ ndlp_fdmi->nlp_type |= NLP_FABRIC;
+- ndlp_fdmi->nlp_state =
+- NLP_STE_PLOGI_ISSUE;
++ lpfc_nlp_set_state(vport, ndlp_fdmi,
++ NLP_STE_PLOGI_ISSUE);
+ lpfc_issue_els_plogi(vport, ndlp_fdmi->nlp_DID,
+ 0);
+ }
+@@ -5074,39 +5097,3 @@ void lpfc_fabric_abort_hba(struct lpfc_hba *phba)
+ (piocb->iocb_cmpl) (phba, piocb, piocb);
+ }
+ }
+-
+-
+-#if 0
+-void lpfc_fabric_abort_flogi(struct lpfc_hba *phba)
+-{
+- LIST_HEAD(completions);
+- struct lpfc_iocbq *tmp_iocb, *piocb;
+- IOCB_t *cmd;
+- struct lpfc_nodelist *ndlp;
+-
+- spin_lock_irq(&phba->hbalock);
+- list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
+- list) {
+-
+- cmd = &piocb->iocb;
+- ndlp = (struct lpfc_nodelist *) piocb->context1;
+- if (cmd->ulpCommand == CMD_ELS_REQUEST64_CR &&
+- ndlp != NULL &&
+- ndlp->nlp_DID == Fabric_DID)
+- list_move_tail(&piocb->list, &completions);
+- }
+- spin_unlock_irq(&phba->hbalock);
+-
+- while (!list_empty(&completions)) {
+- piocb = list_get_first(&completions, struct lpfc_iocbq, list);
+- list_del_init(&piocb->list);
+-
+- cmd = &piocb->iocb;
+- cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+- cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+- (piocb->iocb_cmpl) (phba, piocb, piocb);
+- }
+-}
+-#endif /* 0 */
+-
+-
+diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
+index 9766534..7cb68fe 100644
+--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
+@@ -69,7 +69,7 @@ lpfc_terminate_rport_io(struct fc_rport *rport)
+ rdata = rport->dd_data;
+ ndlp = rdata->pnode;
+
+- if (!ndlp) {
++ if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
+ if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
+ printk(KERN_ERR "Cannot find remote node"
+ " to terminate I/O Data x%x\n",
+@@ -114,7 +114,7 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
+
+ rdata = rport->dd_data;
+ ndlp = rdata->pnode;
+- if (!ndlp)
++ if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
+ return;
+
+ vport = ndlp->vport;
+@@ -243,8 +243,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
+ if (warn_on) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ "0203 Devloss timeout on "
+- "WWPN %x:%x:%x:%x:%x:%x:%x:%x "
+- "NPort x%x Data: x%x x%x x%x\n",
++ "WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
++ "NPort x%06x Data: x%x x%x x%x\n",
+ *name, *(name+1), *(name+2), *(name+3),
+ *(name+4), *(name+5), *(name+6), *(name+7),
+ ndlp->nlp_DID, ndlp->nlp_flag,
+@@ -252,8 +252,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
+ } else {
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ "0204 Devloss timeout on "
+- "WWPN %x:%x:%x:%x:%x:%x:%x:%x "
+- "NPort x%x Data: x%x x%x x%x\n",
++ "WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
++ "NPort x%06x Data: x%x x%x x%x\n",
+ *name, *(name+1), *(name+2), *(name+3),
+ *(name+4), *(name+5), *(name+6), *(name+7),
+ ndlp->nlp_DID, ndlp->nlp_flag,
+@@ -399,7 +399,10 @@ lpfc_work_done(struct lpfc_hba *phba)
+ vport = vports[i];
+ if (vport == NULL)
+ break;
++ spin_lock_irq(&vport->work_port_lock);
+ work_port_events = vport->work_port_events;
++ vport->work_port_events &= ~work_port_events;
++ spin_unlock_irq(&vport->work_port_lock);
+ if (work_port_events & WORKER_DISC_TMO)
+ lpfc_disc_timeout_handler(vport);
+ if (work_port_events & WORKER_ELS_TMO)
+@@ -416,9 +419,6 @@ lpfc_work_done(struct lpfc_hba *phba)
+ lpfc_ramp_down_queue_handler(phba);
+ if (work_port_events & WORKER_RAMP_UP_QUEUE)
+ lpfc_ramp_up_queue_handler(phba);
+- spin_lock_irq(&vport->work_port_lock);
+- vport->work_port_events &= ~work_port_events;
+- spin_unlock_irq(&vport->work_port_lock);
+ }
+ lpfc_destroy_vport_work_array(phba, vports);
+
+@@ -430,10 +430,10 @@ lpfc_work_done(struct lpfc_hba *phba)
+ if (pring->flag & LPFC_STOP_IOCB_EVENT) {
+ pring->flag |= LPFC_DEFERRED_RING_EVENT;
+ } else {
++ pring->flag &= ~LPFC_DEFERRED_RING_EVENT;
+ lpfc_sli_handle_slow_ring_event(phba, pring,
+ (status &
+ HA_RXMASK));
+- pring->flag &= ~LPFC_DEFERRED_RING_EVENT;
+ }
+ /*
+ * Turn on Ring interrupts
+@@ -519,7 +519,9 @@ lpfc_do_work(void *p)
+ schedule();
+ }
+ }
++ spin_lock_irq(&phba->hbalock);
+ phba->work_wait = NULL;
++ spin_unlock_irq(&phba->hbalock);
+ return 0;
+ }
+
+@@ -809,11 +811,9 @@ out:
+ mempool_free(pmb, phba->mbox_mem_pool);
+
+ spin_lock_irq(shost->host_lock);
+- vport->fc_flag &= ~(FC_ABORT_DISCOVERY | FC_ESTABLISH_LINK);
++ vport->fc_flag &= ~FC_ABORT_DISCOVERY;
+ spin_unlock_irq(shost->host_lock);
+
+- del_timer_sync(&phba->fc_estabtmo);
+-
+ lpfc_can_disctmo(vport);
+
+ /* turn on Link Attention interrupts */
+@@ -1340,10 +1340,14 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+ i++) {
+ if (vports[i]->port_type == LPFC_PHYSICAL_PORT)
+ continue;
++ if (phba->fc_topology == TOPOLOGY_LOOP) {
++ lpfc_vport_set_state(vports[i],
++ FC_VPORT_LINKDOWN);
++ continue;
++ }
+ if (phba->link_flag & LS_NPIV_FAB_SUPPORTED)
+ lpfc_initial_fdisc(vports[i]);
+- else if (phba->sli3_options &
+- LPFC_SLI3_NPIV_ENABLED) {
++ else {
+ lpfc_vport_set_state(vports[i],
+ FC_VPORT_NO_FABRIC_SUPP);
+ lpfc_printf_vlog(vport, KERN_ERR,
+@@ -2190,10 +2194,6 @@ lpfc_matchdid(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ if (did == Bcast_DID)
+ return 0;
+
+- if (ndlp->nlp_DID == 0) {
+- return 0;
+- }
+-
+ /* First check for Direct match */
+ if (ndlp->nlp_DID == did)
+ return 1;
+@@ -2301,7 +2301,8 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did)
+ return ndlp;
+ }
+
+- if (vport->fc_flag & FC_RSCN_MODE) {
++ if ((vport->fc_flag & FC_RSCN_MODE) &&
++ !(vport->fc_flag & FC_NDISC_ACTIVE)) {
+ if (lpfc_rscn_payload_check(vport, did)) {
+ /* If we've already recieved a PLOGI from this NPort
+ * we don't need to try to discover it again.
+@@ -2947,24 +2948,6 @@ __lpfc_find_node(struct lpfc_vport *vport, node_filter filter, void *param)
+ return NULL;
+ }
+
+-#if 0
+-/*
+- * Search node lists for a remote port matching filter criteria
+- * Caller needs to hold host_lock before calling this routine.
+- */
+-struct lpfc_nodelist *
+-lpfc_find_node(struct lpfc_vport *vport, node_filter filter, void *param)
+-{
+- struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+- struct lpfc_nodelist *ndlp;
+-
+- spin_lock_irq(shost->host_lock);
+- ndlp = __lpfc_find_node(vport, filter, param);
+- spin_unlock_irq(shost->host_lock);
+- return ndlp;
+-}
+-#endif /* 0 */
+-
+ /*
+ * This routine looks up the ndlp lists for the given RPI. If rpi found it
+ * returns the node list element pointer else return NULL.
+@@ -2975,20 +2958,6 @@ __lpfc_findnode_rpi(struct lpfc_vport *vport, uint16_t rpi)
+ return __lpfc_find_node(vport, lpfc_filter_by_rpi, &rpi);
+ }
+
+-#if 0
+-struct lpfc_nodelist *
+-lpfc_findnode_rpi(struct lpfc_vport *vport, uint16_t rpi)
+-{
+- struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+- struct lpfc_nodelist *ndlp;
+-
+- spin_lock_irq(shost->host_lock);
+- ndlp = __lpfc_findnode_rpi(vport, rpi);
+- spin_unlock_irq(shost->host_lock);
+- return ndlp;
+-}
+-#endif /* 0 */
+-
+ /*
+ * This routine looks up the ndlp lists for the given WWPN. If WWPN found it
+ * returns the node element list pointer else return NULL.
+diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
+index 2284375..fa757b2 100644
+--- a/drivers/scsi/lpfc/lpfc_init.c
++++ b/drivers/scsi/lpfc/lpfc_init.c
+@@ -559,8 +559,10 @@ lpfc_hb_timeout(unsigned long ptr)
+ phba->pport->work_port_events |= WORKER_HB_TMO;
+ spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
+
++ spin_lock_irqsave(&phba->hbalock, iflag);
+ if (phba->work_wait)
+ wake_up(phba->work_wait);
++ spin_unlock_irqrestore(&phba->hbalock, iflag);
+ return;
+ }
+
+@@ -714,12 +716,10 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
+ struct lpfc_vport *vport = phba->pport;
+ struct lpfc_sli *psli = &phba->sli;
+ struct lpfc_sli_ring *pring;
+- struct lpfc_vport **vports;
+ uint32_t event_data;
+ unsigned long temperature;
+ struct temp_event temp_event_data;
+ struct Scsi_Host *shost;
+- int i;
+
+ /* If the pci channel is offline, ignore possible errors,
+ * since we cannot communicate with the pci card anyway. */
+@@ -729,25 +729,14 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
+ if (!phba->cfg_enable_hba_reset)
+ return;
+
+- if (phba->work_hs & HS_FFER6 ||
+- phba->work_hs & HS_FFER5) {
++ if (phba->work_hs & HS_FFER6) {
+ /* Re-establishing Link */
+ lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
+ "1301 Re-establishing Link "
+ "Data: x%x x%x x%x\n",
+ phba->work_hs,
+ phba->work_status[0], phba->work_status[1]);
+- vports = lpfc_create_vport_work_array(phba);
+- if (vports != NULL)
+- for(i = 0;
+- i <= phba->max_vpi && vports[i] != NULL;
+- i++){
+- shost = lpfc_shost_from_vport(vports[i]);
+- spin_lock_irq(shost->host_lock);
+- vports[i]->fc_flag |= FC_ESTABLISH_LINK;
+- spin_unlock_irq(shost->host_lock);
+- }
+- lpfc_destroy_vport_work_array(phba, vports);
++
+ spin_lock_irq(&phba->hbalock);
+ psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
+ spin_unlock_irq(&phba->hbalock);
+@@ -761,7 +750,6 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
+ pring = &psli->ring[psli->fcp_ring];
+ lpfc_sli_abort_iocb_ring(phba, pring);
+
+-
+ /*
+ * There was a firmware error. Take the hba offline and then
+ * attempt to restart it.
+@@ -770,7 +758,6 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
+ lpfc_offline(phba);
+ lpfc_sli_brdrestart(phba);
+ if (lpfc_online(phba) == 0) { /* Initialize the HBA */
+- mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
+ lpfc_unblock_mgmt_io(phba);
+ return;
+ }
+@@ -1454,6 +1441,13 @@ lpfc_cleanup(struct lpfc_vport *vport)
+ NLP_SET_FREE_REQ(ndlp);
+ spin_unlock_irq(&phba->ndlp_lock);
+
++ if (vport->port_type != LPFC_PHYSICAL_PORT &&
++ ndlp->nlp_DID == Fabric_DID) {
++ /* Just free up ndlp with Fabric_DID for vports */
++ lpfc_nlp_put(ndlp);
++ continue;
++ }
++
+ if (ndlp->nlp_type & NLP_FABRIC)
+ lpfc_disc_state_machine(vport, ndlp, NULL,
+ NLP_EVT_DEVICE_RECOVERY);
+@@ -1491,31 +1485,6 @@ lpfc_cleanup(struct lpfc_vport *vport)
+ return;
+ }
+
+-static void
+-lpfc_establish_link_tmo(unsigned long ptr)
+-{
+- struct lpfc_hba *phba = (struct lpfc_hba *) ptr;
+- struct lpfc_vport **vports;
+- unsigned long iflag;
+- int i;
+-
+- /* Re-establishing Link, timer expired */
+- lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
+- "1300 Re-establishing Link, timer expired "
+- "Data: x%x x%x\n",
+- phba->pport->fc_flag, phba->pport->port_state);
+- vports = lpfc_create_vport_work_array(phba);
+- if (vports != NULL)
+- for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
+- struct Scsi_Host *shost;
+- shost = lpfc_shost_from_vport(vports[i]);
+- spin_lock_irqsave(shost->host_lock, iflag);
+- vports[i]->fc_flag &= ~FC_ESTABLISH_LINK;
+- spin_unlock_irqrestore(shost->host_lock, iflag);
+- }
+- lpfc_destroy_vport_work_array(phba, vports);
+-}
+-
+ void
+ lpfc_stop_vport_timers(struct lpfc_vport *vport)
+ {
+@@ -1529,7 +1498,6 @@ static void
+ lpfc_stop_phba_timers(struct lpfc_hba *phba)
+ {
+ del_timer_sync(&phba->fcp_poll_timer);
+- del_timer_sync(&phba->fc_estabtmo);
+ lpfc_stop_vport_timers(phba->pport);
+ del_timer_sync(&phba->sli.mbox_tmo);
+ del_timer_sync(&phba->fabric_block_timer);
+@@ -2005,10 +1973,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
+ phba->max_vpi = LPFC_MAX_VPI;
+
+ /* Initialize timers used by driver */
+- init_timer(&phba->fc_estabtmo);
+- phba->fc_estabtmo.function = lpfc_establish_link_tmo;
+- phba->fc_estabtmo.data = (unsigned long)phba;
+-
+ init_timer(&phba->hb_tmofunc);
+ phba->hb_tmofunc.function = lpfc_hb_timeout;
+ phba->hb_tmofunc.data = (unsigned long)phba;
+@@ -2406,6 +2370,7 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
+ struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
+ struct lpfc_sli *psli = &phba->sli;
++ int error, retval;
+
+ dev_printk(KERN_INFO, &pdev->dev, "recovering from a slot reset.\n");
+ if (pci_enable_device_mem(pdev)) {
+@@ -2416,15 +2381,40 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
+
+ pci_set_master(pdev);
+
+- /* Re-establishing Link */
+- spin_lock_irq(shost->host_lock);
+- phba->pport->fc_flag |= FC_ESTABLISH_LINK;
+- spin_unlock_irq(shost->host_lock);
+-
+ spin_lock_irq(&phba->hbalock);
+ psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
+ spin_unlock_irq(&phba->hbalock);
+
++ /* Enable configured interrupt method */
++ phba->intr_type = NONE;
++ if (phba->cfg_use_msi == 2) {
++ error = lpfc_enable_msix(phba);
++ if (!error)
++ phba->intr_type = MSIX;
++ }
++
++ /* Fallback to MSI if MSI-X initialization failed */
++ if (phba->cfg_use_msi >= 1 && phba->intr_type == NONE) {
++ retval = pci_enable_msi(phba->pcidev);
++ if (!retval)
++ phba->intr_type = MSI;
++ else
++ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
++ "0470 Enable MSI failed, continuing "
++ "with IRQ\n");
++ }
++
++ /* MSI-X is the only case the doesn't need to call request_irq */
++ if (phba->intr_type != MSIX) {
++ retval = request_irq(phba->pcidev->irq, lpfc_intr_handler,
++ IRQF_SHARED, LPFC_DRIVER_NAME, phba);
++ if (retval) {
++ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
++ "0471 Enable interrupt handler "
++ "failed\n");
++ } else if (phba->intr_type != MSI)
++ phba->intr_type = INTx;
++ }
+
+ /* Take device offline; this will perform cleanup */
+ lpfc_offline(phba);
+@@ -2445,9 +2435,7 @@ static void lpfc_io_resume(struct pci_dev *pdev)
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
+ struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
+
+- if (lpfc_online(phba) == 0) {
+- mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
+- }
++ lpfc_online(phba);
+ }
+
+ static struct pci_device_id lpfc_id_table[] = {
+diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
+index d513813..d08c4c8 100644
+--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
++++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
+@@ -451,7 +451,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ spin_unlock_irq(shost->host_lock);
+
+ if ((ndlp->nlp_flag & NLP_ADISC_SND) &&
+- (vport->num_disc_nodes)) {
++ (vport->num_disc_nodes)) {
+ /* Check to see if there are more
+ * ADISCs to be sent
+ */
+@@ -469,20 +469,23 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ lpfc_end_rscn(vport);
+ }
+ }
+- else if (vport->num_disc_nodes) {
+- /* Check to see if there are more
+- * PLOGIs to be sent
+- */
+- lpfc_more_plogi(vport);
+-
+- if (vport->num_disc_nodes == 0) {
+- spin_lock_irq(shost->host_lock);
+- vport->fc_flag &= ~FC_NDISC_ACTIVE;
+- spin_unlock_irq(shost->host_lock);
+- lpfc_can_disctmo(vport);
+- lpfc_end_rscn(vport);
+- }
+- }
++ }
++ } else if ((ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) &&
++ (ndlp->nlp_flag & NLP_NPR_2B_DISC) &&
++ (vport->num_disc_nodes)) {
++ spin_lock_irq(shost->host_lock);
++ ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
++ spin_unlock_irq(shost->host_lock);
++ /* Check to see if there are more
++ * PLOGIs to be sent
++ */
++ lpfc_more_plogi(vport);
++ if (vport->num_disc_nodes == 0) {
++ spin_lock_irq(shost->host_lock);
++ vport->fc_flag &= ~FC_NDISC_ACTIVE;
++ spin_unlock_irq(shost->host_lock);
++ lpfc_can_disctmo(vport);
++ lpfc_end_rscn(vport);
+ }
+ }
+
+@@ -869,8 +872,11 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
+
+ lp = (uint32_t *) prsp->virt;
+ sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
+- if (wwn_to_u64(sp->portName.u.wwn) == 0 ||
+- wwn_to_u64(sp->nodeName.u.wwn) == 0) {
++
++ /* Some switches have FDMI servers returning 0 for WWN */
++ if ((ndlp->nlp_DID != FDMI_DID) &&
++ (wwn_to_u64(sp->portName.u.wwn) == 0 ||
++ wwn_to_u64(sp->nodeName.u.wwn) == 0)) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ "0142 PLOGI RSP: Invalid WWN.\n");
+ goto out;
+diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
+index 70255c1..0910a9a 100644
+--- a/drivers/scsi/lpfc/lpfc_scsi.c
++++ b/drivers/scsi/lpfc/lpfc_scsi.c
+@@ -169,6 +169,9 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba)
+ for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
+ shost = lpfc_shost_from_vport(vports[i]);
+ shost_for_each_device(sdev, shost) {
++ if (vports[i]->cfg_lun_queue_depth <=
++ sdev->queue_depth)
++ continue;
+ if (sdev->ordered_tags)
+ scsi_adjust_queue_depth(sdev,
+ MSG_ORDERED_TAG,
+@@ -578,14 +581,14 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
+ lpfc_cmd->result == IOERR_NO_RESOURCES ||
+ lpfc_cmd->result == RJT_LOGIN_REQUIRED) {
+ cmd->result = ScsiResult(DID_REQUEUE, 0);
+- break;
+- } /* else: fall through */
++ break;
++ } /* else: fall through */
+ default:
+ cmd->result = ScsiResult(DID_ERROR, 0);
+ break;
+ }
+
+- if ((pnode == NULL )
++ if (!pnode || !NLP_CHK_NODE_ACT(pnode)
+ || (pnode->nlp_state != NLP_STE_MAPPED_NODE))
+ cmd->result = ScsiResult(DID_BUS_BUSY, SAM_STAT_BUSY);
+ } else {
+@@ -606,6 +609,9 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
+ result = cmd->result;
+ sdev = cmd->device;
+ lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
++ spin_lock_irqsave(sdev->host->host_lock, flags);
++ lpfc_cmd->pCmd = NULL; /* This must be done before scsi_done */
++ spin_unlock_irqrestore(sdev->host->host_lock, flags);
+ cmd->scsi_done(cmd);
+
+ if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
+@@ -614,7 +620,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
+ * wake up the thread.
+ */
+ spin_lock_irqsave(sdev->host->host_lock, flags);
+- lpfc_cmd->pCmd = NULL;
+ if (lpfc_cmd->waitq)
+ wake_up(lpfc_cmd->waitq);
+ spin_unlock_irqrestore(sdev->host->host_lock, flags);
+@@ -626,7 +631,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
+ if (!result)
+ lpfc_rampup_queue_depth(vport, sdev);
+
+- if (!result && pnode != NULL &&
++ if (!result && pnode && NLP_CHK_NODE_ACT(pnode) &&
+ ((jiffies - pnode->last_ramp_up_time) >
+ LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
+ ((jiffies - pnode->last_q_full_time) >
+@@ -654,7 +659,8 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
+ * Check for queue full. If the lun is reporting queue full, then
+ * back off the lun queue depth to prevent target overloads.
+ */
+- if (result == SAM_STAT_TASK_SET_FULL && pnode != NULL) {
++ if (result == SAM_STAT_TASK_SET_FULL && pnode &&
++ NLP_CHK_NODE_ACT(pnode)) {
+ pnode->last_q_full_time = jiffies;
+
+ shost_for_each_device(tmp_sdev, sdev->host) {
+@@ -684,7 +690,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
+ * wake up the thread.
+ */
+ spin_lock_irqsave(sdev->host->host_lock, flags);
+- lpfc_cmd->pCmd = NULL;
+ if (lpfc_cmd->waitq)
+ wake_up(lpfc_cmd->waitq);
+ spin_unlock_irqrestore(sdev->host->host_lock, flags);
+@@ -704,6 +709,9 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
+ int datadir = scsi_cmnd->sc_data_direction;
+ char tag[2];
+
++ if (!pnode || !NLP_CHK_NODE_ACT(pnode))
++ return;
++
+ lpfc_cmd->fcp_rsp->rspSnsLen = 0;
+ /* clear task management bits */
+ lpfc_cmd->fcp_cmnd->fcpCntl2 = 0;
+@@ -785,9 +793,9 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport,
+ struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
+ struct lpfc_nodelist *ndlp = rdata->pnode;
+
+- if ((ndlp == NULL) || (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
++ if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) ||
++ ndlp->nlp_state != NLP_STE_MAPPED_NODE)
+ return 0;
+- }
+
+ piocbq = &(lpfc_cmd->cur_iocbq);
+ piocbq->vport = vport;
+@@ -842,7 +850,7 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_vport *vport,
+ struct lpfc_iocbq *iocbqrsp;
+ int ret;
+
+- if (!rdata->pnode)
++ if (!rdata->pnode || !NLP_CHK_NODE_ACT(rdata->pnode))
+ return FAILED;
+
+ lpfc_cmd->rdata = rdata;
+@@ -959,7 +967,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
+ * Catch race where our node has transitioned, but the
+ * transport is still transitioning.
+ */
+- if (!ndlp) {
++ if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
+ cmnd->result = ScsiResult(DID_BUS_BUSY, 0);
+ goto out_fail_command;
+ }
+@@ -1146,7 +1154,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
+ * target is rediscovered or devloss timeout expires.
+ */
+ while (1) {
+- if (!pnode)
++ if (!pnode || !NLP_CHK_NODE_ACT(pnode))
+ goto out;
+
+ if (pnode->nlp_state != NLP_STE_MAPPED_NODE) {
+@@ -1162,7 +1170,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
+ goto out;
+ }
+ pnode = rdata->pnode;
+- if (!pnode)
++ if (!pnode || !NLP_CHK_NODE_ACT(pnode))
+ goto out;
+ }
+ if (pnode->nlp_state == NLP_STE_MAPPED_NODE)
+diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
+index fc0d950..70a0a9e 100644
+--- a/drivers/scsi/lpfc/lpfc_sli.c
++++ b/drivers/scsi/lpfc/lpfc_sli.c
+@@ -2648,7 +2648,6 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
+ spin_unlock_irq(&phba->pport->work_port_lock);
+ spin_lock_irq(&phba->hbalock);
+ phba->link_state = LPFC_LINK_UNKNOWN;
+- phba->pport->fc_flag |= FC_ESTABLISH_LINK;
+ psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
+ spin_unlock_irq(&phba->hbalock);
+
+@@ -2669,8 +2668,7 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
+ lpfc_offline_prep(phba);
+ lpfc_offline(phba);
+ lpfc_sli_brdrestart(phba);
+- if (lpfc_online(phba) == 0) /* Initialize the HBA */
+- mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
++ lpfc_online(phba);
+ lpfc_unblock_mgmt_io(phba);
+ return;
+ }
+@@ -2687,28 +2685,41 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
+ unsigned long drvr_flag = 0;
+ volatile uint32_t word0, ldata;
+ void __iomem *to_slim;
++ int processing_queue = 0;
++
++ spin_lock_irqsave(&phba->hbalock, drvr_flag);
++ if (!pmbox) {
++ /* processing mbox queue from intr_handler */
++ processing_queue = 1;
++ phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
++ pmbox = lpfc_mbox_get(phba);
++ if (!pmbox) {
++ spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
++ return MBX_SUCCESS;
++ }
++ }
+
+ if (pmbox->mbox_cmpl && pmbox->mbox_cmpl != lpfc_sli_def_mbox_cmpl &&
+ pmbox->mbox_cmpl != lpfc_sli_wake_mbox_wait) {
+ if(!pmbox->vport) {
++ spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_MBOX | LOG_VPORT,
+ "1806 Mbox x%x failed. No vport\n",
+ pmbox->mb.mbxCommand);
+ dump_stack();
+- return MBX_NOT_FINISHED;
++ goto out_not_finished;
+ }
+ }
+
+-
+ /* If the PCI channel is in offline state, do not post mbox. */
+- if (unlikely(pci_channel_offline(phba->pcidev)))
+- return MBX_NOT_FINISHED;
++ if (unlikely(pci_channel_offline(phba->pcidev))) {
++ spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
++ goto out_not_finished;
++ }
+
+- spin_lock_irqsave(&phba->hbalock, drvr_flag);
+ psli = &phba->sli;
+
+-
+ mb = &pmbox->mb;
+ status = MBX_SUCCESS;
+
+@@ -2717,14 +2728,14 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
+
+ /* Mbox command <mbxCommand> cannot issue */
+ LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
+- return MBX_NOT_FINISHED;
++ goto out_not_finished;
+ }
+
+ if (mb->mbxCommand != MBX_KILL_BOARD && flag & MBX_NOWAIT &&
+ !(readl(phba->HCregaddr) & HC_MBINT_ENA)) {
+ spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+ LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
+- return MBX_NOT_FINISHED;
++ goto out_not_finished;
+ }
+
+ if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) {
+@@ -2738,14 +2749,14 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
+
+ /* Mbox command <mbxCommand> cannot issue */
+ LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
+- return MBX_NOT_FINISHED;
++ goto out_not_finished;
+ }
+
+ if (!(psli->sli_flag & LPFC_SLI2_ACTIVE)) {
+ spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+ /* Mbox command <mbxCommand> cannot issue */
+ LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
+- return MBX_NOT_FINISHED;
++ goto out_not_finished;
+ }
+
+ /* Another mailbox command is still being processed, queue this
+@@ -2792,7 +2803,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
+ spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+ /* Mbox command <mbxCommand> cannot issue */
+ LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag);
+- return MBX_NOT_FINISHED;
++ goto out_not_finished;
+ }
+ /* timeout active mbox command */
+ mod_timer(&psli->mbox_tmo, (jiffies +
+@@ -2900,7 +2911,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
+ psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+ spin_unlock_irqrestore(&phba->hbalock,
+ drvr_flag);
+- return MBX_NOT_FINISHED;
++ goto out_not_finished;
+ }
+
+ /* Check if we took a mbox interrupt while we were
+@@ -2967,6 +2978,13 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
+
+ spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+ return status;
++
++out_not_finished:
++ if (processing_queue) {
++ pmbox->mb.mbxStatus = MBX_NOT_FINISHED;
++ lpfc_mbox_cmpl_put(phba, pmbox);
++ }
++ return MBX_NOT_FINISHED;
+ }
+
+ /*
+@@ -3463,26 +3481,21 @@ lpfc_sli_hba_down(struct lpfc_hba *phba)
+ phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
+ spin_unlock(&phba->pport->work_port_lock);
+
++ /* Return any pending or completed mbox cmds */
++ list_splice_init(&phba->sli.mboxq, &completions);
+ if (psli->mbox_active) {
+ list_add_tail(&psli->mbox_active->list, &completions);
+ psli->mbox_active = NULL;
+ psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+ }
+-
+- /* Return any pending or completed mbox cmds */
+- list_splice_init(&phba->sli.mboxq, &completions);
+ list_splice_init(&phba->sli.mboxq_cmpl, &completions);
+- INIT_LIST_HEAD(&psli->mboxq);
+- INIT_LIST_HEAD(&psli->mboxq_cmpl);
+-
+ spin_unlock_irqrestore(&phba->hbalock, flags);
+
+ while (!list_empty(&completions)) {
+ list_remove_head(&completions, pmb, LPFC_MBOXQ_t, list);
+ pmb->mb.mbxStatus = MBX_NOT_FINISHED;
+- if (pmb->mbox_cmpl) {
++ if (pmb->mbox_cmpl)
+ pmb->mbox_cmpl(phba,pmb);
+- }
+ }
+ return 1;
+ }
+@@ -3613,6 +3626,15 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ irsp->ulpStatus, irsp->un.ulpWord[4]);
+
+ /*
++ * If the iocb is not found in Firmware queue the iocb
++ * might have completed already. Do not free it again.
++ */
++ if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
++ spin_unlock_irq(&phba->hbalock);
++ lpfc_sli_release_iocbq(phba, cmdiocb);
++ return;
++ }
++ /*
+ * make sure we have the right iocbq before taking it
+ * off the txcmplq and try to call completion routine.
+ */
+@@ -4174,6 +4196,7 @@ lpfc_intr_handler(int irq, void *dev_id)
+ phba->pport->stopped = 1;
+ }
+
++ spin_lock(&phba->hbalock);
+ if ((work_ha_copy & HA_MBATT) &&
+ (phba->sli.mbox_active)) {
+ pmb = phba->sli.mbox_active;
+@@ -4184,6 +4207,7 @@ lpfc_intr_handler(int irq, void *dev_id)
+ /* First check out the status word */
+ lpfc_sli_pcimem_bcopy(mbox, pmbox, sizeof(uint32_t));
+ if (pmbox->mbxOwner != OWN_HOST) {
++ spin_unlock(&phba->hbalock);
+ /*
+ * Stray Mailbox Interrupt, mbxCommand <cmd>
+ * mbxStatus <status>
+@@ -4199,10 +4223,10 @@ lpfc_intr_handler(int irq, void *dev_id)
+ /* clear mailbox attention bit */
+ work_ha_copy &= ~HA_MBATT;
+ } else {
++ phba->sli.mbox_active = NULL;
++ spin_unlock(&phba->hbalock);
+ phba->last_completion_time = jiffies;
+ del_timer(&phba->sli.mbox_tmo);
+-
+- phba->sli.mbox_active = NULL;
+ if (pmb->mbox_cmpl) {
+ lpfc_sli_pcimem_bcopy(mbox, pmbox,
+ MAILBOX_CMD_SIZE);
+@@ -4237,10 +4261,15 @@ lpfc_intr_handler(int irq, void *dev_id)
+ pmb->context1 = mp;
+ pmb->context2 = ndlp;
+ pmb->vport = vport;
+- spin_lock(&phba->hbalock);
+- phba->sli.sli_flag &=
+- ~LPFC_SLI_MBOX_ACTIVE;
+- spin_unlock(&phba->hbalock);
++ rc = lpfc_sli_issue_mbox(phba,
++ pmb,
++ MBX_NOWAIT);
++ if (rc != MBX_BUSY)
++ lpfc_printf_log(phba,
++ KERN_ERR,
++ LOG_MBOX | LOG_SLI,
++ "0306 rc should have"
++ "been MBX_BUSY");
+ goto send_current_mbox;
+ }
+ }
+@@ -4250,25 +4279,20 @@ lpfc_intr_handler(int irq, void *dev_id)
+ spin_unlock(&phba->pport->work_port_lock);
+ lpfc_mbox_cmpl_put(phba, pmb);
+ }
+- }
++ } else
++ spin_unlock(&phba->hbalock);
+ if ((work_ha_copy & HA_MBATT) &&
+ (phba->sli.mbox_active == NULL)) {
+-send_next_mbox:
+- spin_lock(&phba->hbalock);
+- phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+- pmb = lpfc_mbox_get(phba);
+- spin_unlock(&phba->hbalock);
+ send_current_mbox:
+ /* Process next mailbox command if there is one */
+- if (pmb != NULL) {
+- rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
+- if (rc == MBX_NOT_FINISHED) {
+- pmb->mb.mbxStatus = MBX_NOT_FINISHED;
+- lpfc_mbox_cmpl_put(phba, pmb);
+- goto send_next_mbox;
+- }
+- }
+-
++ do {
++ rc = lpfc_sli_issue_mbox(phba, NULL,
++ MBX_NOWAIT);
++ } while (rc == MBX_NOT_FINISHED);
++ if (rc != MBX_SUCCESS)
++ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX |
++ LOG_SLI, "0349 rc should be "
++ "MBX_SUCCESS");
+ }
+
+ spin_lock(&phba->hbalock);
+diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
+index ca540d1..b22b893 100644
+--- a/drivers/scsi/lpfc/lpfc_version.h
++++ b/drivers/scsi/lpfc/lpfc_version.h
+@@ -18,7 +18,7 @@
+ * included with this package. *
+ *******************************************************************/
+
+-#define LPFC_DRIVER_VERSION "8.2.5"
++#define LPFC_DRIVER_VERSION "8.2.6"
+
+ #define LPFC_DRIVER_NAME "lpfc"
+
+diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c
+index 86d05be..6feaf59 100644
+--- a/drivers/scsi/lpfc/lpfc_vport.c
++++ b/drivers/scsi/lpfc/lpfc_vport.c
+@@ -538,7 +538,8 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
+ /* Otherwise, we will perform fabric logo as needed */
+ if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
+ ndlp->nlp_state == NLP_STE_UNMAPPED_NODE &&
+- phba->link_state >= LPFC_LINK_UP) {
++ phba->link_state >= LPFC_LINK_UP &&
++ phba->fc_topology != TOPOLOGY_LOOP) {
+ if (vport->cfg_enable_da_id) {
+ timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
+ if (!lpfc_ns_cmd(vport, SLI_CTNS_DA_ID, 0, 0))
+diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
+index 3b09ab2..0248919 100644
+--- a/drivers/scsi/mac_scsi.c
++++ b/drivers/scsi/mac_scsi.c
+@@ -592,7 +592,6 @@ static struct scsi_host_template driver_template = {
+ .this_id = 7,
+ .sg_tablesize = SG_ALL,
+ .cmd_per_lun = CMD_PER_LUN,
+- .unchecked_isa_dma = 0,
+ .use_clustering = DISABLE_CLUSTERING
+ };
+
+diff --git a/drivers/scsi/megaraid/mega_common.h b/drivers/scsi/megaraid/mega_common.h
+index fef9ac9..f62ed46 100644
+--- a/drivers/scsi/megaraid/mega_common.h
++++ b/drivers/scsi/megaraid/mega_common.h
+@@ -28,7 +28,6 @@
+ #include <linux/list.h>
+ #include <linux/moduleparam.h>
+ #include <linux/dma-mapping.h>
+-#include <asm/semaphore.h>
+ #include <scsi/scsi.h>
+ #include <scsi/scsi_cmnd.h>
+ #include <scsi/scsi_device.h>
+diff --git a/drivers/scsi/megaraid/megaraid_ioctl.h b/drivers/scsi/megaraid/megaraid_ioctl.h
+index 706fa05..05f6e4e 100644
+--- a/drivers/scsi/megaraid/megaraid_ioctl.h
++++ b/drivers/scsi/megaraid/megaraid_ioctl.h
+@@ -18,7 +18,7 @@
+ #define _MEGARAID_IOCTL_H_
+
+ #include <linux/types.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+
+ #include "mbox_defs.h"
+
+diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
+index 9f04192..820f91f 100644
+--- a/drivers/scsi/megaraid/megaraid_mbox.c
++++ b/drivers/scsi/megaraid/megaraid_mbox.c
+@@ -125,7 +125,7 @@ static irqreturn_t megaraid_isr(int, void *);
+
+ static void megaraid_mbox_dpc(unsigned long);
+
+-static ssize_t megaraid_sysfs_show_app_hndl(struct class_device *, char *);
++static ssize_t megaraid_sysfs_show_app_hndl(struct device *, struct device_attribute *attr, char *);
+ static ssize_t megaraid_sysfs_show_ldnum(struct device *, struct device_attribute *attr, char *);
+
+ static int megaraid_cmm_register(adapter_t *);
+@@ -313,12 +313,12 @@ static struct pci_driver megaraid_pci_driver = {
+ // definitions for the device attributes for exporting logical drive number
+ // for a scsi address (Host, Channel, Id, Lun)
+
+-CLASS_DEVICE_ATTR(megaraid_mbox_app_hndl, S_IRUSR, megaraid_sysfs_show_app_hndl,
++DEVICE_ATTR(megaraid_mbox_app_hndl, S_IRUSR, megaraid_sysfs_show_app_hndl,
+ NULL);
+
+ // Host template initializer for megaraid mbox sysfs device attributes
+-static struct class_device_attribute *megaraid_shost_attrs[] = {
+- &class_device_attr_megaraid_mbox_app_hndl,
++static struct device_attribute *megaraid_shost_attrs[] = {
++ &dev_attr_megaraid_mbox_app_hndl,
+ NULL,
+ };
+
+@@ -4063,9 +4063,10 @@ megaraid_sysfs_get_ldmap(adapter_t *adapter)
+ * handle, since we do not interface with applications directly.
+ */
+ static ssize_t
+-megaraid_sysfs_show_app_hndl(struct class_device *cdev, char *buf)
++megaraid_sysfs_show_app_hndl(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(cdev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ adapter_t *adapter = (adapter_t *)SCSIHOST2ADAP(shost);
+ uint32_t app_hndl;
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
+index 77a62a1..b937e9c 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.c
++++ b/drivers/scsi/megaraid/megaraid_sas.c
+@@ -68,6 +68,8 @@ static struct pci_device_id megasas_pci_table[] = {
+ /* xscale IOP */
+ {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078R)},
+ /* ppc IOP */
++ {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078DE)},
++ /* ppc IOP */
+ {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)},
+ /* xscale IOP, vega */
+ {PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)},
+@@ -488,12 +490,13 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp,
+
+ /**
+ * megasas_get_frame_count - Computes the number of frames
++ * @frame_type : type of frame- io or pthru frame
+ * @sge_count : number of sg elements
+ *
+ * Returns the number of frames required for numnber of sge's (sge_count)
+ */
+
+-static u32 megasas_get_frame_count(u8 sge_count)
++static u32 megasas_get_frame_count(u8 sge_count, u8 frame_type)
+ {
+ int num_cnt;
+ int sge_bytes;
+@@ -504,13 +507,22 @@ static u32 megasas_get_frame_count(u8 sge_count)
+ sizeof(struct megasas_sge32);
+
+ /*
+- * Main frame can contain 2 SGEs for 64-bit SGLs and
+- * 3 SGEs for 32-bit SGLs
+- */
+- if (IS_DMA64)
+- num_cnt = sge_count - 2;
+- else
+- num_cnt = sge_count - 3;
++ * Main frame can contain 2 SGEs for 64-bit SGLs and
++ * 3 SGEs for 32-bit SGLs for ldio &
++ * 1 SGEs for 64-bit SGLs and
++ * 2 SGEs for 32-bit SGLs for pthru frame
++ */
++ if (unlikely(frame_type == PTHRU_FRAME)) {
++ if (IS_DMA64)
++ num_cnt = sge_count - 1;
++ else
++ num_cnt = sge_count - 2;
++ } else {
++ if (IS_DMA64)
++ num_cnt = sge_count - 2;
++ else
++ num_cnt = sge_count - 3;
++ }
+
+ if(num_cnt>0){
+ sge_bytes = sge_sz * num_cnt;
+@@ -592,7 +604,8 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
+ * Compute the total number of frames this command consumes. FW uses
+ * this number to pull sufficient number of frames from host memory.
+ */
+- cmd->frame_count = megasas_get_frame_count(pthru->sge_count);
++ cmd->frame_count = megasas_get_frame_count(pthru->sge_count,
++ PTHRU_FRAME);
+
+ return cmd->frame_count;
+ }
+@@ -709,7 +722,7 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
+ * Compute the total number of frames this command consumes. FW uses
+ * this number to pull sufficient number of frames from host memory.
+ */
+- cmd->frame_count = megasas_get_frame_count(ldio->sge_count);
++ cmd->frame_count = megasas_get_frame_count(ldio->sge_count, IO_FRAME);
+
+ return cmd->frame_count;
+ }
+@@ -1460,7 +1473,7 @@ megasas_transition_to_ready(struct megasas_instance* instance)
+ instance->instancet->disable_intr(instance->reg_set);
+ writel(MFI_RESET_FLAGS, &instance->reg_set->inbound_doorbell);
+
+- max_wait = 10;
++ max_wait = 60;
+ cur_state = MFI_STATE_OPERATIONAL;
+ break;
+
+@@ -1980,7 +1993,8 @@ static int megasas_init_mfi(struct megasas_instance *instance)
+
+ switch(instance->pdev->device)
+ {
+- case PCI_DEVICE_ID_LSI_SAS1078R:
++ case PCI_DEVICE_ID_LSI_SAS1078R:
++ case PCI_DEVICE_ID_LSI_SAS1078DE:
+ instance->instancet = &megasas_instance_template_ppc;
+ break;
+ case PCI_DEVICE_ID_LSI_SAS1064R:
+@@ -2909,7 +2923,6 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
+ void *sense = NULL;
+ dma_addr_t sense_handle;
+ u32 *sense_ptr;
+- unsigned long *sense_buff;
+
+ memset(kbuff_arr, 0, sizeof(kbuff_arr));
+
+@@ -3014,14 +3027,14 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
+ */
+ if (ioc->sense_len) {
+ /*
+- * sense_buff points to the location that has the user
++ * sense_ptr points to the location that has the user
+ * sense buffer address
+ */
+- sense_buff = (unsigned long *) ((unsigned long)ioc->frame.raw +
+- ioc->sense_off);
++ sense_ptr = (u32 *) ((unsigned long)ioc->frame.raw +
++ ioc->sense_off);
+
+- if (copy_to_user((void __user *)(unsigned long)(*sense_buff),
+- sense, ioc->sense_len)) {
++ if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)),
++ sense, ioc->sense_len)) {
+ printk(KERN_ERR "megasas: Failed to copy out to user "
+ "sense data\n");
+ error = -EFAULT;
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index 6466bdf..3a997eb 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -26,6 +26,7 @@
+ * Device IDs
+ */
+ #define PCI_DEVICE_ID_LSI_SAS1078R 0x0060
++#define PCI_DEVICE_ID_LSI_SAS1078DE 0x007C
+ #define PCI_DEVICE_ID_LSI_VERDE_ZCR 0x0413
+
+ /*
+@@ -542,6 +543,10 @@ struct megasas_ctrl_info {
+
+ #define MEGASAS_FW_BUSY 1
+
++/* Frame Type */
++#define IO_FRAME 0
++#define PTHRU_FRAME 1
++
+ /*
+ * When SCSI mid-layer calls driver's reset routine, driver waits for
+ * MEGASAS_RESET_WAIT_TIME seconds for all outstanding IO to complete. Note
+diff --git a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c
+index be41aad..d722235 100644
+--- a/drivers/scsi/mvme147.c
++++ b/drivers/scsi/mvme147.c
+@@ -82,6 +82,9 @@ int mvme147_detect(struct scsi_host_template *tpnt)
+ mvme147_host->irq = MVME147_IRQ_SCSI_PORT;
+ regs.SASR = (volatile unsigned char *)0xfffe4000;
+ regs.SCMD = (volatile unsigned char *)0xfffe4001;
++ HDATA(mvme147_host)->no_sync = 0xff;
++ HDATA(mvme147_host)->fast = 0;
++ HDATA(mvme147_host)->dma_mode = CTRL_DMA;
+ wd33c93_init(mvme147_host, regs, dma_setup, dma_stop, WD33C93_FS_8_10);
+
+ if (request_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr, 0, "MVME147 SCSI PORT", mvme147_intr))
+diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
+index c5ebf01..d892894 100644
+--- a/drivers/scsi/ncr53c8xx.c
++++ b/drivers/scsi/ncr53c8xx.c
+@@ -8243,7 +8243,8 @@ static void process_waiting_list(struct ncb *np, int sts)
+
+ #undef next_wcmd
+
+-static ssize_t show_ncr53c8xx_revision(struct class_device *dev, char *buf)
++static ssize_t show_ncr53c8xx_revision(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+ struct Scsi_Host *host = class_to_shost(dev);
+ struct host_data *host_data = (struct host_data *)host->hostdata;
+@@ -8251,12 +8252,12 @@ static ssize_t show_ncr53c8xx_revision(struct class_device *dev, char *buf)
+ return snprintf(buf, 20, "0x%x\n", host_data->ncb->revision_id);
+ }
+
+-static struct class_device_attribute ncr53c8xx_revision_attr = {
++static struct device_attribute ncr53c8xx_revision_attr = {
+ .attr = { .name = "revision", .mode = S_IRUGO, },
+ .show = show_ncr53c8xx_revision,
+ };
+
+-static struct class_device_attribute *ncr53c8xx_host_attrs[] = {
++static struct device_attribute *ncr53c8xx_host_attrs[] = {
+ &ncr53c8xx_revision_attr,
+ NULL
+ };
+diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
+index abef704..31f7aec 100644
+--- a/drivers/scsi/osst.c
++++ b/drivers/scsi/osst.c
+@@ -5591,9 +5591,10 @@ static void osst_remove_sysfs_files(struct device_driver *sysfs)
+ * sysfs support for accessing ADR header information
+ */
+
+-static ssize_t osst_adr_rev_show(struct class_device *class_dev, char *buf)
++static ssize_t osst_adr_rev_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
++ struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
+ ssize_t l = 0;
+
+ if (STp && STp->header_ok && STp->linux_media)
+@@ -5601,11 +5602,13 @@ static ssize_t osst_adr_rev_show(struct class_device *class_dev, char *buf)
+ return l;
+ }
+
+-CLASS_DEVICE_ATTR(ADR_rev, S_IRUGO, osst_adr_rev_show, NULL);
++DEVICE_ATTR(ADR_rev, S_IRUGO, osst_adr_rev_show, NULL);
+
+-static ssize_t osst_linux_media_version_show(struct class_device *class_dev, char *buf)
++static ssize_t osst_linux_media_version_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
+ {
+- struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
++ struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
+ ssize_t l = 0;
+
+ if (STp && STp->header_ok && STp->linux_media)
+@@ -5613,11 +5616,12 @@ static ssize_t osst_linux_media_version_show(struct class_device *class_dev, cha
+ return l;
+ }
+
+-CLASS_DEVICE_ATTR(media_version, S_IRUGO, osst_linux_media_version_show, NULL);
++DEVICE_ATTR(media_version, S_IRUGO, osst_linux_media_version_show, NULL);
+
+-static ssize_t osst_capacity_show(struct class_device *class_dev, char *buf)
++static ssize_t osst_capacity_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
++ struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
+ ssize_t l = 0;
+
+ if (STp && STp->header_ok && STp->linux_media)
+@@ -5625,11 +5629,13 @@ static ssize_t osst_capacity_show(struct class_device *class_dev, char *buf)
+ return l;
+ }
+
+-CLASS_DEVICE_ATTR(capacity, S_IRUGO, osst_capacity_show, NULL);
++DEVICE_ATTR(capacity, S_IRUGO, osst_capacity_show, NULL);
+
+-static ssize_t osst_first_data_ppos_show(struct class_device *class_dev, char *buf)
++static ssize_t osst_first_data_ppos_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
+ {
+- struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
++ struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
+ ssize_t l = 0;
+
+ if (STp && STp->header_ok && STp->linux_media)
+@@ -5637,11 +5643,13 @@ static ssize_t osst_first_data_ppos_show(struct class_device *class_dev, char *b
+ return l;
+ }
+
+-CLASS_DEVICE_ATTR(BOT_frame, S_IRUGO, osst_first_data_ppos_show, NULL);
++DEVICE_ATTR(BOT_frame, S_IRUGO, osst_first_data_ppos_show, NULL);
+
+-static ssize_t osst_eod_frame_ppos_show(struct class_device *class_dev, char *buf)
++static ssize_t osst_eod_frame_ppos_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
+ {
+- struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
++ struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
+ ssize_t l = 0;
+
+ if (STp && STp->header_ok && STp->linux_media)
+@@ -5649,11 +5657,12 @@ static ssize_t osst_eod_frame_ppos_show(struct class_device *class_dev, char *bu
+ return l;
+ }
+
+-CLASS_DEVICE_ATTR(EOD_frame, S_IRUGO, osst_eod_frame_ppos_show, NULL);
++DEVICE_ATTR(EOD_frame, S_IRUGO, osst_eod_frame_ppos_show, NULL);
+
+-static ssize_t osst_filemark_cnt_show(struct class_device *class_dev, char *buf)
++static ssize_t osst_filemark_cnt_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct osst_tape * STp = (struct osst_tape *) class_get_devdata (class_dev);
++ struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
+ ssize_t l = 0;
+
+ if (STp && STp->header_ok && STp->linux_media)
+@@ -5661,7 +5670,7 @@ static ssize_t osst_filemark_cnt_show(struct class_device *class_dev, char *buf)
+ return l;
+ }
+
+-CLASS_DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
++DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
+
+ static struct class *osst_sysfs_class;
+
+@@ -5678,44 +5687,37 @@ static int osst_sysfs_init(void)
+
+ static void osst_sysfs_destroy(dev_t dev)
+ {
+- class_device_destroy(osst_sysfs_class, dev);
++ device_destroy(osst_sysfs_class, dev);
+ }
+
+ static int osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * STp, char * name)
+ {
+- struct class_device *osst_class_member;
++ struct device *osst_member;
+ int err;
+
+- osst_class_member = class_device_create(osst_sysfs_class, NULL, dev,
+- device, "%s", name);
+- if (IS_ERR(osst_class_member)) {
++ osst_member = device_create(osst_sysfs_class, device, dev, "%s", name);
++ if (IS_ERR(osst_member)) {
+ printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
+- return PTR_ERR(osst_class_member);
++ return PTR_ERR(osst_member);
+ }
+
+- class_set_devdata(osst_class_member, STp);
+- err = class_device_create_file(osst_class_member,
+- &class_device_attr_ADR_rev);
++ dev_set_drvdata(osst_member, STp);
++ err = device_create_file(osst_member, &dev_attr_ADR_rev);
+ if (err)
+ goto err_out;
+- err = class_device_create_file(osst_class_member,
+- &class_device_attr_media_version);
++ err = device_create_file(osst_member, &dev_attr_media_version);
+ if (err)
+ goto err_out;
+- err = class_device_create_file(osst_class_member,
+- &class_device_attr_capacity);
++ err = device_create_file(osst_member, &dev_attr_capacity);
+ if (err)
+ goto err_out;
+- err = class_device_create_file(osst_class_member,
+- &class_device_attr_BOT_frame);
++ err = device_create_file(osst_member, &dev_attr_BOT_frame);
+ if (err)
+ goto err_out;
+- err = class_device_create_file(osst_class_member,
+- &class_device_attr_EOD_frame);
++ err = device_create_file(osst_member, &dev_attr_EOD_frame);
+ if (err)
+ goto err_out;
+- err = class_device_create_file(osst_class_member,
+- &class_device_attr_file_count);
++ err = device_create_file(osst_member, &dev_attr_file_count);
+ if (err)
+ goto err_out;
+
+diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
+index 3454a57..0be232b 100644
+--- a/drivers/scsi/pcmcia/sym53c500_cs.c
++++ b/drivers/scsi/pcmcia/sym53c500_cs.c
+@@ -632,9 +632,10 @@ SYM53C500_biosparm(struct scsi_device *disk,
+ }
+
+ static ssize_t
+-SYM53C500_show_pio(struct class_device *cdev, char *buf)
++SYM53C500_show_pio(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *SHp = class_to_shost(cdev);
++ struct Scsi_Host *SHp = class_to_shost(dev);
+ struct sym53c500_data *data =
+ (struct sym53c500_data *)SHp->hostdata;
+
+@@ -642,10 +643,11 @@ SYM53C500_show_pio(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-SYM53C500_store_pio(struct class_device *cdev, const char *buf, size_t count)
++SYM53C500_store_pio(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+ int pio;
+- struct Scsi_Host *SHp = class_to_shost(cdev);
++ struct Scsi_Host *SHp = class_to_shost(dev);
+ struct sym53c500_data *data =
+ (struct sym53c500_data *)SHp->hostdata;
+
+@@ -662,7 +664,7 @@ SYM53C500_store_pio(struct class_device *cdev, const char *buf, size_t count)
+ * SCSI HBA device attributes we want to
+ * make available via sysfs.
+ */
+-static struct class_device_attribute SYM53C500_pio_attr = {
++static struct device_attribute SYM53C500_pio_attr = {
+ .attr = {
+ .name = "fast_pio",
+ .mode = (S_IRUGO | S_IWUSR),
+@@ -671,7 +673,7 @@ static struct class_device_attribute SYM53C500_pio_attr = {
+ .store = SYM53C500_store_pio,
+ };
+
+-static struct class_device_attribute *SYM53C500_shost_attrs[] = {
++static struct device_attribute *SYM53C500_shost_attrs[] = {
+ &SYM53C500_pio_attr,
+ NULL,
+ };
+diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c
+index fad6cb5..ce48e2d 100644
+--- a/drivers/scsi/ps3rom.c
++++ b/drivers/scsi/ps3rom.c
+@@ -26,6 +26,7 @@
+ #include <scsi/scsi_dbg.h>
+ #include <scsi/scsi_device.h>
+ #include <scsi/scsi_host.h>
++#include <scsi/scsi_eh.h>
+
+ #include <asm/lv1call.h>
+ #include <asm/ps3stor.h>
+@@ -90,78 +91,6 @@ static int ps3rom_slave_configure(struct scsi_device *scsi_dev)
+ return 0;
+ }
+
+-/*
+- * copy data from device into scatter/gather buffer
+- */
+-static int fill_from_dev_buffer(struct scsi_cmnd *cmd, const void *buf)
+-{
+- int k, req_len, act_len, len, active;
+- void *kaddr;
+- struct scatterlist *sgpnt;
+- unsigned int buflen;
+-
+- buflen = scsi_bufflen(cmd);
+- if (!buflen)
+- return 0;
+-
+- if (!scsi_sglist(cmd))
+- return -1;
+-
+- active = 1;
+- req_len = act_len = 0;
+- scsi_for_each_sg(cmd, sgpnt, scsi_sg_count(cmd), k) {
+- if (active) {
+- kaddr = kmap_atomic(sg_page(sgpnt), KM_IRQ0);
+- len = sgpnt->length;
+- if ((req_len + len) > buflen) {
+- active = 0;
+- len = buflen - req_len;
+- }
+- memcpy(kaddr + sgpnt->offset, buf + req_len, len);
+- flush_kernel_dcache_page(sg_page(sgpnt));
+- kunmap_atomic(kaddr, KM_IRQ0);
+- act_len += len;
+- }
+- req_len += sgpnt->length;
+- }
+- scsi_set_resid(cmd, buflen - act_len);
+- return 0;
+-}
+-
+-/*
+- * copy data from scatter/gather into device's buffer
+- */
+-static int fetch_to_dev_buffer(struct scsi_cmnd *cmd, void *buf)
+-{
+- int k, req_len, len, fin;
+- void *kaddr;
+- struct scatterlist *sgpnt;
+- unsigned int buflen;
+-
+- buflen = scsi_bufflen(cmd);
+- if (!buflen)
+- return 0;
+-
+- if (!scsi_sglist(cmd))
+- return -1;
+-
+- req_len = fin = 0;
+- scsi_for_each_sg(cmd, sgpnt, scsi_sg_count(cmd), k) {
+- kaddr = kmap_atomic(sg_page(sgpnt), KM_IRQ0);
+- len = sgpnt->length;
+- if ((req_len + len) > buflen) {
+- len = buflen - req_len;
+- fin = 1;
+- }
+- memcpy(buf + req_len, kaddr + sgpnt->offset, len);
+- kunmap_atomic(kaddr, KM_IRQ0);
+- if (fin)
+- return req_len + len;
+- req_len += sgpnt->length;
+- }
+- return req_len;
+-}
+-
+ static int ps3rom_atapi_request(struct ps3_storage_device *dev,
+ struct scsi_cmnd *cmd)
+ {
+@@ -195,9 +124,7 @@ static int ps3rom_atapi_request(struct ps3_storage_device *dev,
+ else
+ atapi_cmnd.proto = PIO_DATA_OUT_PROTO;
+ atapi_cmnd.in_out = DIR_WRITE;
+- res = fetch_to_dev_buffer(cmd, dev->bounce_buf);
+- if (res < 0)
+- return DID_ERROR << 16;
++ scsi_sg_copy_to_buffer(cmd, dev->bounce_buf, dev->bounce_size);
+ break;
+
+ default:
+@@ -269,9 +196,7 @@ static int ps3rom_write_request(struct ps3_storage_device *dev,
+ dev_dbg(&dev->sbd.core, "%s:%u: write %u sectors starting at %u\n",
+ __func__, __LINE__, sectors, start_sector);
+
+- res = fetch_to_dev_buffer(cmd, dev->bounce_buf);
+- if (res < 0)
+- return DID_ERROR << 16;
++ scsi_sg_copy_to_buffer(cmd, dev->bounce_buf, dev->bounce_size);
+
+ res = lv1_storage_write(dev->sbd.dev_id,
+ dev->regions[dev->region_idx].id, start_sector,
+@@ -381,11 +306,13 @@ static irqreturn_t ps3rom_interrupt(int irq, void *data)
+ if (!status) {
+ /* OK, completed */
+ if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
+- res = fill_from_dev_buffer(cmd, dev->bounce_buf);
+- if (res) {
+- cmd->result = DID_ERROR << 16;
+- goto done;
+- }
++ int len;
++
++ len = scsi_sg_copy_from_buffer(cmd,
++ dev->bounce_buf,
++ dev->bounce_size);
++
++ scsi_set_resid(cmd, scsi_bufflen(cmd) - len);
+ }
+ cmd->result = DID_OK << 16;
+ goto done;
+@@ -404,11 +331,7 @@ static irqreturn_t ps3rom_interrupt(int irq, void *data)
+ goto done;
+ }
+
+- cmd->sense_buffer[0] = 0x70;
+- cmd->sense_buffer[2] = sense_key;
+- cmd->sense_buffer[7] = 16 - 6;
+- cmd->sense_buffer[12] = asc;
+- cmd->sense_buffer[13] = ascq;
++ scsi_build_sense_buffer(0, cmd->sense_buffer, sense_key, asc, ascq);
+ cmd->result = SAM_STAT_CHECK_CONDITION;
+
+ done:
+@@ -427,7 +350,7 @@ static struct scsi_host_template ps3rom_host_template = {
+ .cmd_per_lun = 1,
+ .emulated = 1, /* only sg driver uses this */
+ .max_sectors = PS3ROM_MAX_SECTORS,
+- .use_clustering = DISABLE_CLUSTERING,
++ .use_clustering = ENABLE_CLUSTERING,
+ .module = THIS_MODULE,
+ };
+
+diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
+index 68c0d09..09ab3ea 100644
+--- a/drivers/scsi/qla1280.c
++++ b/drivers/scsi/qla1280.c
+@@ -333,7 +333,6 @@
+
+ #include <linux/module.h>
+
+-#include <linux/version.h>
+ #include <linux/types.h>
+ #include <linux/string.h>
+ #include <linux/errno.h>
+@@ -367,10 +366,6 @@
+ #include <asm/sn/io.h>
+ #endif
+
+-#if LINUX_VERSION_CODE < 0x020600
+-#error "Kernels older than 2.6.0 are no longer supported"
+-#endif
+-
+
+ /*
+ * Compile time Options:
+diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig
+index 8c865b9..6208d56 100644
+--- a/drivers/scsi/qla2xxx/Kconfig
++++ b/drivers/scsi/qla2xxx/Kconfig
+@@ -16,7 +16,8 @@ config SCSI_QLA_FC
+ 22xx ql2200_fw.bin
+ 2300, 2312, 6312 ql2300_fw.bin
+ 2322, 6322 ql2322_fw.bin
+- 24xx ql2400_fw.bin
++ 24xx, 54xx ql2400_fw.bin
++ 25xx ql2500_fw.bin
+
+ Upon request, the driver caches the firmware image until
+ the driver is unloaded.
+diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
+index 4894dc8..d61df03 100644
+--- a/drivers/scsi/qla2xxx/qla_attr.c
++++ b/drivers/scsi/qla2xxx/qla_attr.c
+@@ -1,6 +1,6 @@
+ /*
+ * QLogic Fibre Channel HBA Driver
+- * Copyright (c) 2003-2005 QLogic Corporation
++ * Copyright (c) 2003-2008 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+@@ -530,15 +530,17 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha)
+ /* Scsi_Host attributes. */
+
+ static ssize_t
+-qla2x00_drvr_version_show(struct class_device *cdev, char *buf)
++qla2x00_drvr_version_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+ return snprintf(buf, PAGE_SIZE, "%s\n", qla2x00_version_str);
+ }
+
+ static ssize_t
+-qla2x00_fw_version_show(struct class_device *cdev, char *buf)
++qla2x00_fw_version_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++ scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ char fw_str[30];
+
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+@@ -546,9 +548,10 @@ qla2x00_fw_version_show(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-qla2x00_serial_num_show(struct class_device *cdev, char *buf)
++qla2x00_serial_num_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++ scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ uint32_t sn;
+
+ if (IS_FWI2_CAPABLE(ha))
+@@ -560,40 +563,45 @@ qla2x00_serial_num_show(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-qla2x00_isp_name_show(struct class_device *cdev, char *buf)
++qla2x00_isp_name_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++ scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ return snprintf(buf, PAGE_SIZE, "ISP%04X\n", ha->pdev->device);
+ }
+
+ static ssize_t
+-qla2x00_isp_id_show(struct class_device *cdev, char *buf)
++qla2x00_isp_id_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++ scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ return snprintf(buf, PAGE_SIZE, "%04x %04x %04x %04x\n",
+ ha->product_id[0], ha->product_id[1], ha->product_id[2],
+ ha->product_id[3]);
+ }
+
+ static ssize_t
+-qla2x00_model_name_show(struct class_device *cdev, char *buf)
++qla2x00_model_name_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++ scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ return snprintf(buf, PAGE_SIZE, "%s\n", ha->model_number);
+ }
+
+ static ssize_t
+-qla2x00_model_desc_show(struct class_device *cdev, char *buf)
++qla2x00_model_desc_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++ scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ ha->model_desc ? ha->model_desc: "");
+ }
+
+ static ssize_t
+-qla2x00_pci_info_show(struct class_device *cdev, char *buf)
++qla2x00_pci_info_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++ scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ char pci_info[30];
+
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+@@ -601,9 +609,10 @@ qla2x00_pci_info_show(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-qla2x00_state_show(struct class_device *cdev, char *buf)
++qla2x00_state_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++ scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ int len = 0;
+
+ if (atomic_read(&ha->loop_state) == LOOP_DOWN ||
+@@ -639,9 +648,10 @@ qla2x00_state_show(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-qla2x00_zio_show(struct class_device *cdev, char *buf)
++qla2x00_zio_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++ scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ int len = 0;
+
+ switch (ha->zio_mode) {
+@@ -656,9 +666,10 @@ qla2x00_zio_show(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-qla2x00_zio_store(struct class_device *cdev, const char *buf, size_t count)
++qla2x00_zio_store(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+- scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++ scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ int val = 0;
+ uint16_t zio_mode;
+
+@@ -682,18 +693,19 @@ qla2x00_zio_store(struct class_device *cdev, const char *buf, size_t count)
+ }
+
+ static ssize_t
+-qla2x00_zio_timer_show(struct class_device *cdev, char *buf)
++qla2x00_zio_timer_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++ scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+
+ return snprintf(buf, PAGE_SIZE, "%d us\n", ha->zio_timer * 100);
+ }
+
+ static ssize_t
+-qla2x00_zio_timer_store(struct class_device *cdev, const char *buf,
+- size_t count)
++qla2x00_zio_timer_store(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+- scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++ scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ int val = 0;
+ uint16_t zio_timer;
+
+@@ -709,9 +721,10 @@ qla2x00_zio_timer_store(struct class_device *cdev, const char *buf,
+ }
+
+ static ssize_t
+-qla2x00_beacon_show(struct class_device *cdev, char *buf)
++qla2x00_beacon_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++ scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ int len = 0;
+
+ if (ha->beacon_blink_led)
+@@ -722,10 +735,10 @@ qla2x00_beacon_show(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-qla2x00_beacon_store(struct class_device *cdev, const char *buf,
+- size_t count)
++qla2x00_beacon_store(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+- scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++ scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+ int val = 0;
+ int rval;
+
+@@ -753,84 +766,86 @@ qla2x00_beacon_store(struct class_device *cdev, const char *buf,
+ }
+
+ static ssize_t
+-qla2x00_optrom_bios_version_show(struct class_device *cdev, char *buf)
++qla2x00_optrom_bios_version_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++ scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+
+ return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->bios_revision[1],
+ ha->bios_revision[0]);
+ }
+
+ static ssize_t
+-qla2x00_optrom_efi_version_show(struct class_device *cdev, char *buf)
++qla2x00_optrom_efi_version_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++ scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+
+ return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->efi_revision[1],
+ ha->efi_revision[0]);
+ }
+
+ static ssize_t
+-qla2x00_optrom_fcode_version_show(struct class_device *cdev, char *buf)
++qla2x00_optrom_fcode_version_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++ scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+
+ return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->fcode_revision[1],
+ ha->fcode_revision[0]);
+ }
+
+ static ssize_t
+-qla2x00_optrom_fw_version_show(struct class_device *cdev, char *buf)
++qla2x00_optrom_fw_version_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
++ scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+
+ return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d %d\n",
+ ha->fw_revision[0], ha->fw_revision[1], ha->fw_revision[2],
+ ha->fw_revision[3]);
+ }
+
+-static CLASS_DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show,
+- NULL);
+-static CLASS_DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
+-static CLASS_DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL);
+-static CLASS_DEVICE_ATTR(isp_name, S_IRUGO, qla2x00_isp_name_show, NULL);
+-static CLASS_DEVICE_ATTR(isp_id, S_IRUGO, qla2x00_isp_id_show, NULL);
+-static CLASS_DEVICE_ATTR(model_name, S_IRUGO, qla2x00_model_name_show, NULL);
+-static CLASS_DEVICE_ATTR(model_desc, S_IRUGO, qla2x00_model_desc_show, NULL);
+-static CLASS_DEVICE_ATTR(pci_info, S_IRUGO, qla2x00_pci_info_show, NULL);
+-static CLASS_DEVICE_ATTR(state, S_IRUGO, qla2x00_state_show, NULL);
+-static CLASS_DEVICE_ATTR(zio, S_IRUGO | S_IWUSR, qla2x00_zio_show,
+- qla2x00_zio_store);
+-static CLASS_DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show,
+- qla2x00_zio_timer_store);
+-static CLASS_DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show,
+- qla2x00_beacon_store);
+-static CLASS_DEVICE_ATTR(optrom_bios_version, S_IRUGO,
+- qla2x00_optrom_bios_version_show, NULL);
+-static CLASS_DEVICE_ATTR(optrom_efi_version, S_IRUGO,
+- qla2x00_optrom_efi_version_show, NULL);
+-static CLASS_DEVICE_ATTR(optrom_fcode_version, S_IRUGO,
+- qla2x00_optrom_fcode_version_show, NULL);
+-static CLASS_DEVICE_ATTR(optrom_fw_version, S_IRUGO,
+- qla2x00_optrom_fw_version_show, NULL);
+-
+-struct class_device_attribute *qla2x00_host_attrs[] = {
+- &class_device_attr_driver_version,
+- &class_device_attr_fw_version,
+- &class_device_attr_serial_num,
+- &class_device_attr_isp_name,
+- &class_device_attr_isp_id,
+- &class_device_attr_model_name,
+- &class_device_attr_model_desc,
+- &class_device_attr_pci_info,
+- &class_device_attr_state,
+- &class_device_attr_zio,
+- &class_device_attr_zio_timer,
+- &class_device_attr_beacon,
+- &class_device_attr_optrom_bios_version,
+- &class_device_attr_optrom_efi_version,
+- &class_device_attr_optrom_fcode_version,
+- &class_device_attr_optrom_fw_version,
++static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL);
++static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
++static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL);
++static DEVICE_ATTR(isp_name, S_IRUGO, qla2x00_isp_name_show, NULL);
++static DEVICE_ATTR(isp_id, S_IRUGO, qla2x00_isp_id_show, NULL);
++static DEVICE_ATTR(model_name, S_IRUGO, qla2x00_model_name_show, NULL);
++static DEVICE_ATTR(model_desc, S_IRUGO, qla2x00_model_desc_show, NULL);
++static DEVICE_ATTR(pci_info, S_IRUGO, qla2x00_pci_info_show, NULL);
++static DEVICE_ATTR(state, S_IRUGO, qla2x00_state_show, NULL);
++static DEVICE_ATTR(zio, S_IRUGO | S_IWUSR, qla2x00_zio_show, qla2x00_zio_store);
++static DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show,
++ qla2x00_zio_timer_store);
++static DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show,
++ qla2x00_beacon_store);
++static DEVICE_ATTR(optrom_bios_version, S_IRUGO,
++ qla2x00_optrom_bios_version_show, NULL);
++static DEVICE_ATTR(optrom_efi_version, S_IRUGO,
++ qla2x00_optrom_efi_version_show, NULL);
++static DEVICE_ATTR(optrom_fcode_version, S_IRUGO,
++ qla2x00_optrom_fcode_version_show, NULL);
++static DEVICE_ATTR(optrom_fw_version, S_IRUGO, qla2x00_optrom_fw_version_show,
++ NULL);
++
++struct device_attribute *qla2x00_host_attrs[] = {
++ &dev_attr_driver_version,
++ &dev_attr_fw_version,
++ &dev_attr_serial_num,
++ &dev_attr_isp_name,
++ &dev_attr_isp_id,
++ &dev_attr_model_name,
++ &dev_attr_model_desc,
++ &dev_attr_pci_info,
++ &dev_attr_state,
++ &dev_attr_zio,
++ &dev_attr_zio_timer,
++ &dev_attr_beacon,
++ &dev_attr_optrom_bios_version,
++ &dev_attr_optrom_efi_version,
++ &dev_attr_optrom_fcode_version,
++ &dev_attr_optrom_fw_version,
+ NULL,
+ };
+
+@@ -849,20 +864,20 @@ static void
+ qla2x00_get_host_speed(struct Scsi_Host *shost)
+ {
+ scsi_qla_host_t *ha = to_qla_parent(shost_priv(shost));
+- uint32_t speed = 0;
++ u32 speed = FC_PORTSPEED_UNKNOWN;
+
+ switch (ha->link_data_rate) {
+ case PORT_SPEED_1GB:
+- speed = 1;
++ speed = FC_PORTSPEED_1GBIT;
+ break;
+ case PORT_SPEED_2GB:
+- speed = 2;
++ speed = FC_PORTSPEED_2GBIT;
+ break;
+ case PORT_SPEED_4GB:
+- speed = 4;
++ speed = FC_PORTSPEED_4GBIT;
+ break;
+ case PORT_SPEED_8GB:
+- speed = 8;
++ speed = FC_PORTSPEED_8GBIT;
+ break;
+ }
+ fc_host_speed(shost) = speed;
+@@ -900,7 +915,8 @@ qla2x00_get_starget_node_name(struct scsi_target *starget)
+ u64 node_name = 0;
+
+ list_for_each_entry(fcport, &ha->fcports, list) {
+- if (starget->id == fcport->os_target_id) {
++ if (fcport->rport &&
++ starget->id == fcport->rport->scsi_target_id) {
+ node_name = wwn_to_u64(fcport->node_name);
+ break;
+ }
+@@ -918,7 +934,8 @@ qla2x00_get_starget_port_name(struct scsi_target *starget)
+ u64 port_name = 0;
+
+ list_for_each_entry(fcport, &ha->fcports, list) {
+- if (starget->id == fcport->os_target_id) {
++ if (fcport->rport &&
++ starget->id == fcport->rport->scsi_target_id) {
+ port_name = wwn_to_u64(fcport->port_name);
+ break;
+ }
+@@ -936,7 +953,8 @@ qla2x00_get_starget_port_id(struct scsi_target *starget)
+ uint32_t port_id = ~0U;
+
+ list_for_each_entry(fcport, &ha->fcports, list) {
+- if (starget->id == fcport->os_target_id) {
++ if (fcport->rport &&
++ starget->id == fcport->rport->scsi_target_id) {
+ port_id = fcport->d_id.b.domain << 16 |
+ fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa;
+ break;
+@@ -1196,6 +1214,7 @@ struct fc_function_template qla2xxx_transport_functions = {
+ .show_host_node_name = 1,
+ .show_host_port_name = 1,
+ .show_host_supported_classes = 1,
++ .show_host_supported_speeds = 1,
+
+ .get_host_port_id = qla2x00_get_host_port_id,
+ .show_host_port_id = 1,
+@@ -1276,9 +1295,23 @@ struct fc_function_template qla2xxx_transport_vport_functions = {
+ void
+ qla2x00_init_host_attr(scsi_qla_host_t *ha)
+ {
++ u32 speed = FC_PORTSPEED_UNKNOWN;
++
+ fc_host_node_name(ha->host) = wwn_to_u64(ha->node_name);
+ fc_host_port_name(ha->host) = wwn_to_u64(ha->port_name);
+ fc_host_supported_classes(ha->host) = FC_COS_CLASS3;
+ fc_host_max_npiv_vports(ha->host) = ha->max_npiv_vports;;
+ fc_host_npiv_vports_inuse(ha->host) = ha->cur_vport_count;
++
++ if (IS_QLA25XX(ha))
++ speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT |
++ FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT;
++ else if (IS_QLA24XX_TYPE(ha))
++ speed = FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT |
++ FC_PORTSPEED_1GBIT;
++ else if (IS_QLA23XX(ha))
++ speed = FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT;
++ else
++ speed = FC_PORTSPEED_1GBIT;
++ fc_host_supported_speeds(ha->host) = speed;
+ }
+diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
+index d88e98c..9d12d9f 100644
+--- a/drivers/scsi/qla2xxx/qla_dbg.c
++++ b/drivers/scsi/qla2xxx/qla_dbg.c
+@@ -1,6 +1,6 @@
+ /*
+ * QLogic Fibre Channel HBA Driver
+- * Copyright (c) 2003-2005 QLogic Corporation
++ * Copyright (c) 2003-2008 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+@@ -1410,125 +1410,3 @@ qla2x00_dump_buffer(uint8_t * b, uint32_t size)
+ if (cnt % 16)
+ printk("\n");
+ }
+-
+-/**************************************************************************
+- * qla2x00_print_scsi_cmd
+- * Dumps out info about the scsi cmd and srb.
+- * Input
+- * cmd : struct scsi_cmnd
+- **************************************************************************/
+-void
+-qla2x00_print_scsi_cmd(struct scsi_cmnd * cmd)
+-{
+- int i;
+- struct scsi_qla_host *ha;
+- srb_t *sp;
+-
+- ha = shost_priv(cmd->device->host);
+-
+- sp = (srb_t *) cmd->SCp.ptr;
+- printk("SCSI Command @=0x%p, Handle=0x%p\n", cmd, cmd->host_scribble);
+- printk(" chan=0x%02x, target=0x%02x, lun=0x%02x, cmd_len=0x%02x\n",
+- cmd->device->channel, cmd->device->id, cmd->device->lun,
+- cmd->cmd_len);
+- printk(" CDB: ");
+- for (i = 0; i < cmd->cmd_len; i++) {
+- printk("0x%02x ", cmd->cmnd[i]);
+- }
+- printk("\n seg_cnt=%d, allowed=%d, retries=%d\n",
+- scsi_sg_count(cmd), cmd->allowed, cmd->retries);
+- printk(" request buffer=0x%p, request buffer len=0x%x\n",
+- scsi_sglist(cmd), scsi_bufflen(cmd));
+- printk(" tag=%d, transfersize=0x%x\n",
+- cmd->tag, cmd->transfersize);
+- printk(" serial_number=%lx, SP=%p\n", cmd->serial_number, sp);
+- printk(" data direction=%d\n", cmd->sc_data_direction);
+-
+- if (!sp)
+- return;
+-
+- printk(" sp flags=0x%x\n", sp->flags);
+-}
+-
+-#if defined(QL_DEBUG_ROUTINES)
+-/*
+- * qla2x00_formatted_dump_buffer
+- * Prints string plus buffer.
+- *
+- * Input:
+- * string = Null terminated string (no newline at end).
+- * buffer = buffer address.
+- * wd_size = word size 8, 16, 32 or 64 bits
+- * count = number of words.
+- */
+-void
+-qla2x00_formatted_dump_buffer(char *string, uint8_t * buffer,
+- uint8_t wd_size, uint32_t count)
+-{
+- uint32_t cnt;
+- uint16_t *buf16;
+- uint32_t *buf32;
+-
+- if (strcmp(string, "") != 0)
+- printk("%s\n",string);
+-
+- switch (wd_size) {
+- case 8:
+- printk(" 0 1 2 3 4 5 6 7 "
+- "8 9 Ah Bh Ch Dh Eh Fh\n");
+- printk("-----------------------------------------"
+- "-------------------------------------\n");
+-
+- for (cnt = 1; cnt <= count; cnt++, buffer++) {
+- printk("%02x",*buffer);
+- if (cnt % 16 == 0)
+- printk("\n");
+- else
+- printk(" ");
+- }
+- if (cnt % 16 != 0)
+- printk("\n");
+- break;
+- case 16:
+- printk(" 0 2 4 6 8 Ah "
+- " Ch Eh\n");
+- printk("-----------------------------------------"
+- "-------------\n");
+-
+- buf16 = (uint16_t *) buffer;
+- for (cnt = 1; cnt <= count; cnt++, buf16++) {
+- printk("%4x",*buf16);
+-
+- if (cnt % 8 == 0)
+- printk("\n");
+- else if (*buf16 < 10)
+- printk(" ");
+- else
+- printk(" ");
+- }
+- if (cnt % 8 != 0)
+- printk("\n");
+- break;
+- case 32:
+- printk(" 0 4 8 Ch\n");
+- printk("------------------------------------------\n");
+-
+- buf32 = (uint32_t *) buffer;
+- for (cnt = 1; cnt <= count; cnt++, buf32++) {
+- printk("%8x", *buf32);
+-
+- if (cnt % 4 == 0)
+- printk("\n");
+- else if (*buf32 < 10)
+- printk(" ");
+- else
+- printk(" ");
+- }
+- if (cnt % 4 != 0)
+- printk("\n");
+- break;
+- default:
+- break;
+- }
+-}
+-#endif
+diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
+index 524598a..2e9c0c0 100644
+--- a/drivers/scsi/qla2xxx/qla_dbg.h
++++ b/drivers/scsi/qla2xxx/qla_dbg.h
+@@ -1,6 +1,6 @@
+ /*
+ * QLogic Fibre Channel HBA Driver
+- * Copyright (c) 2003-2005 QLogic Corporation
++ * Copyright (c) 2003-2008 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+@@ -22,19 +22,7 @@
+ /* #define QL_DEBUG_LEVEL_13 */ /* Output fdmi function trace msgs */
+ /* #define QL_DEBUG_LEVEL_14 */ /* Output RSCN trace msgs */
+ /* #define QL_DEBUG_LEVEL_15 */ /* Output NPIV trace msgs */
+-/*
+- * Local Macro Definitions.
+- */
+-#if defined(QL_DEBUG_LEVEL_1) || defined(QL_DEBUG_LEVEL_2) || \
+- defined(QL_DEBUG_LEVEL_3) || defined(QL_DEBUG_LEVEL_4) || \
+- defined(QL_DEBUG_LEVEL_5) || defined(QL_DEBUG_LEVEL_6) || \
+- defined(QL_DEBUG_LEVEL_7) || defined(QL_DEBUG_LEVEL_8) || \
+- defined(QL_DEBUG_LEVEL_9) || defined(QL_DEBUG_LEVEL_10) || \
+- defined(QL_DEBUG_LEVEL_11) || defined(QL_DEBUG_LEVEL_12) || \
+- defined(QL_DEBUG_LEVEL_13) || defined(QL_DEBUG_LEVEL_14) || \
+- defined(QL_DEBUG_LEVEL_15)
+- #define QL_DEBUG_ROUTINES
+-#endif
++/* #define QL_DEBUG_LEVEL_16 */ /* Output ISP84XX trace msgs */
+
+ /*
+ * Macros use for debugging the driver.
+@@ -54,6 +42,7 @@
+ #define DEBUG2_9_10(x) do { if (ql2xextended_error_logging) { x; } } while (0)
+ #define DEBUG2_11(x) do { if (ql2xextended_error_logging) { x; } } while (0)
+ #define DEBUG2_13(x) do { if (ql2xextended_error_logging) { x; } } while (0)
++#define DEBUG2_16(x) do { if (ql2xextended_error_logging) { x; } } while (0)
+
+ #if defined(QL_DEBUG_LEVEL_3)
+ #define DEBUG3(x) do {x;} while (0)
+@@ -133,6 +122,12 @@
+ #define DEBUG15(x) do {} while (0)
+ #endif
+
++#if defined(QL_DEBUG_LEVEL_16)
++#define DEBUG16(x) do {x;} while (0)
++#else
++#define DEBUG16(x) do {} while (0)
++#endif
++
+ /*
+ * Firmware Dump structure definition
+ */
+diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
+index 3750319..299eccf 100644
+--- a/drivers/scsi/qla2xxx/qla_def.h
++++ b/drivers/scsi/qla2xxx/qla_def.h
+@@ -1,6 +1,6 @@
+ /*
+ * QLogic Fibre Channel HBA Driver
+- * Copyright (c) 2003-2005 QLogic Corporation
++ * Copyright (c) 2003-2008 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+@@ -24,7 +24,8 @@
+ #include <linux/workqueue.h>
+ #include <linux/firmware.h>
+ #include <linux/aer.h>
+-#include <asm/semaphore.h>
++#include <linux/mutex.h>
++#include <linux/semaphore.h>
+
+ #include <scsi/scsi.h>
+ #include <scsi/scsi_host.h>
+@@ -192,9 +193,6 @@ typedef struct srb {
+
+ uint16_t flags;
+
+- /* Single transfer DMA context */
+- dma_addr_t dma_handle;
+-
+ uint32_t request_sense_length;
+ uint8_t *request_sense_ptr;
+ } srb_t;
+@@ -1542,8 +1540,6 @@ typedef struct fc_port {
+ atomic_t state;
+ uint32_t flags;
+
+- unsigned int os_target_id;
+-
+ int port_login_retry_count;
+ int login_retry;
+ atomic_t port_down_timer;
+@@ -1613,6 +1609,7 @@ typedef struct fc_port {
+ #define CT_ACCEPT_RESPONSE 0x8002
+ #define CT_REASON_INVALID_COMMAND_CODE 0x01
+ #define CT_REASON_CANNOT_PERFORM 0x09
++#define CT_REASON_COMMAND_UNSUPPORTED 0x0b
+ #define CT_EXPL_ALREADY_REGISTERED 0x10
+
+ #define NS_N_PORT_TYPE 0x01
+@@ -2063,7 +2060,8 @@ struct isp_operations {
+ void (*disable_intrs) (struct scsi_qla_host *);
+
+ int (*abort_command) (struct scsi_qla_host *, srb_t *);
+- int (*abort_target) (struct fc_port *);
++ int (*target_reset) (struct fc_port *, unsigned int);
++ int (*lun_reset) (struct fc_port *, unsigned int);
+ int (*fabric_login) (struct scsi_qla_host *, uint16_t, uint8_t,
+ uint8_t, uint8_t, uint16_t *, uint8_t);
+ int (*fabric_logout) (struct scsi_qla_host *, uint16_t, uint8_t,
+@@ -2117,6 +2115,46 @@ struct qla_msix_entry {
+
+ #define WATCH_INTERVAL 1 /* number of seconds */
+
++/* Work events. */
++enum qla_work_type {
++ QLA_EVT_AEN,
++ QLA_EVT_HWE_LOG,
++};
++
++
++struct qla_work_evt {
++ struct list_head list;
++ enum qla_work_type type;
++ u32 flags;
++#define QLA_EVT_FLAG_FREE 0x1
++
++ union {
++ struct {
++ enum fc_host_event_code code;
++ u32 data;
++ } aen;
++ struct {
++ uint16_t code;
++ uint16_t d1, d2, d3;
++ } hwe;
++ } u;
++};
++
++struct qla_chip_state_84xx {
++ struct list_head list;
++ struct kref kref;
++
++ void *bus;
++ spinlock_t access_lock;
++ struct mutex fw_update_mutex;
++ uint32_t fw_update;
++ uint32_t op_fw_version;
++ uint32_t op_fw_size;
++ uint32_t op_fw_seq_size;
++ uint32_t diag_fw_version;
++ uint32_t gold_fw_version;
++};
++
+ /*
+ * Linux Host Adapter structure
+ */
+@@ -2155,6 +2193,7 @@ typedef struct scsi_qla_host {
+ uint32_t vsan_enabled :1;
+ uint32_t npiv_supported :1;
+ uint32_t fce_enabled :1;
++ uint32_t hw_event_marker_found :1;
+ } flags;
+
+ atomic_t loop_state;
+@@ -2204,6 +2243,7 @@ typedef struct scsi_qla_host {
+ #define DFLG_NO_CABLE BIT_4
+
+ #define PCI_DEVICE_ID_QLOGIC_ISP2532 0x2532
++#define PCI_DEVICE_ID_QLOGIC_ISP8432 0x8432
+ uint32_t device_type;
+ #define DT_ISP2100 BIT_0
+ #define DT_ISP2200 BIT_1
+@@ -2217,7 +2257,8 @@ typedef struct scsi_qla_host {
+ #define DT_ISP5422 BIT_9
+ #define DT_ISP5432 BIT_10
+ #define DT_ISP2532 BIT_11
+-#define DT_ISP_LAST (DT_ISP2532 << 1)
++#define DT_ISP8432 BIT_12
++#define DT_ISP_LAST (DT_ISP8432 << 1)
+
+ #define DT_IIDMA BIT_26
+ #define DT_FWI2 BIT_27
+@@ -2239,12 +2280,16 @@ typedef struct scsi_qla_host {
+ #define IS_QLA5422(ha) (DT_MASK(ha) & DT_ISP5422)
+ #define IS_QLA5432(ha) (DT_MASK(ha) & DT_ISP5432)
+ #define IS_QLA2532(ha) (DT_MASK(ha) & DT_ISP2532)
++#define IS_QLA8432(ha) (DT_MASK(ha) & DT_ISP8432)
+
+ #define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \
+ IS_QLA6312(ha) || IS_QLA6322(ha))
+ #define IS_QLA24XX(ha) (IS_QLA2422(ha) || IS_QLA2432(ha))
+ #define IS_QLA54XX(ha) (IS_QLA5422(ha) || IS_QLA5432(ha))
+ #define IS_QLA25XX(ha) (IS_QLA2532(ha))
++#define IS_QLA84XX(ha) (IS_QLA8432(ha))
++#define IS_QLA24XX_TYPE(ha) (IS_QLA24XX(ha) || IS_QLA54XX(ha) || \
++ IS_QLA84XX(ha))
+
+ #define IS_IIDMA_CAPABLE(ha) ((ha)->device_type & DT_IIDMA)
+ #define IS_FWI2_CAPABLE(ha) ((ha)->device_type & DT_FWI2)
+@@ -2356,6 +2401,8 @@ typedef struct scsi_qla_host {
+ uint32_t login_retry_count;
+ int max_q_depth;
+
++ struct list_head work_list;
++
+ /* Fibre Channel Device List. */
+ struct list_head fcports;
+
+@@ -2423,8 +2470,6 @@ typedef struct scsi_qla_host {
+ #define MBX_TIMEDOUT BIT_5
+ #define MBX_ACCESS_TIMEDOUT BIT_6
+
+- mbx_cmd_t mc;
+-
+ /* Basic firmware related information. */
+ uint16_t fw_major_version;
+ uint16_t fw_minor_version;
+@@ -2458,6 +2503,10 @@ typedef struct scsi_qla_host {
+ uint64_t fce_wr, fce_rd;
+ struct mutex fce_mutex;
+
++ uint32_t hw_event_start;
++ uint32_t hw_event_ptr;
++ uint32_t hw_event_pause_errors;
++
+ uint8_t host_str[16];
+ uint32_t pci_attr;
+ uint16_t chip_revision;
+@@ -2493,6 +2542,13 @@ typedef struct scsi_qla_host {
+ uint8_t fcode_revision[16];
+ uint32_t fw_revision[4];
+
++ uint16_t fdt_odd_index;
++ uint32_t fdt_wrt_disable;
++ uint32_t fdt_erase_cmd;
++ uint32_t fdt_block_size;
++ uint32_t fdt_unprotect_sec_cmd;
++ uint32_t fdt_protect_sec_cmd;
++
+ /* Needed for BEACON */
+ uint16_t beacon_blink_led;
+ uint8_t beacon_color_state;
+@@ -2538,6 +2594,8 @@ typedef struct scsi_qla_host {
+ #define VP_ERR_ADAP_NORESOURCES 5
+ uint16_t max_npiv_vports; /* 63 or 125 per topoloty */
+ int cur_vport_count;
++
++ struct qla_chip_state_84xx *cs84xx;
+ } scsi_qla_host_t;
+
+
+diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
+index 2cd899b..561a441 100644
+--- a/drivers/scsi/qla2xxx/qla_dfs.c
++++ b/drivers/scsi/qla2xxx/qla_dfs.c
+@@ -1,6 +1,6 @@
+ /*
+ * QLogic Fibre Channel HBA Driver
+- * Copyright (c) 2003-2005 QLogic Corporation
++ * Copyright (c) 2003-2008 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
+index 9337e13..078f2a1 100644
+--- a/drivers/scsi/qla2xxx/qla_fw.h
++++ b/drivers/scsi/qla2xxx/qla_fw.h
+@@ -1,6 +1,6 @@
+ /*
+ * QLogic Fibre Channel HBA Driver
+- * Copyright (c) 2003-2005 QLogic Corporation
++ * Copyright (c) 2003-2008 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+@@ -719,7 +719,7 @@ struct tsk_mgmt_entry {
+
+ uint16_t timeout; /* Command timeout. */
+
+- uint8_t lun[8]; /* FCP LUN (BE). */
++ struct scsi_lun lun; /* FCP LUN (BE). */
+
+ uint32_t control_flags; /* Control Flags. */
+ #define TCF_NOTMCMD_TO_TARGET BIT_31
+@@ -793,7 +793,19 @@ struct device_reg_24xx {
+ #define FA_VPD_NVRAM_ADDR 0x48000
+ #define FA_FEATURE_ADDR 0x4C000
+ #define FA_FLASH_DESCR_ADDR 0x50000
+-#define FA_HW_EVENT_ADDR 0x54000
++#define FA_HW_EVENT0_ADDR 0x54000
++#define FA_HW_EVENT1_ADDR 0x54200
++#define FA_HW_EVENT_SIZE 0x200
++#define FA_HW_EVENT_ENTRY_SIZE 4
++/*
++ * Flash Error Log Event Codes.
++ */
++#define HW_EVENT_RESET_ERR 0xF00B
++#define HW_EVENT_ISP_ERR 0xF020
++#define HW_EVENT_PARITY_ERR 0xF022
++#define HW_EVENT_NVRAM_CHKSUM_ERR 0xF023
++#define HW_EVENT_FLASH_FW_ERR 0xF024
++
+ #define FA_BOOT_LOG_ADDR 0x58000
+ #define FA_FW_DUMP0_ADDR 0x60000
+ #define FA_FW_DUMP1_ADDR 0x70000
+@@ -1174,4 +1186,159 @@ struct vf_evfp_entry_24xx {
+ };
+
+ /* END MID Support ***********************************************************/
++
++/* Flash Description Table ***************************************************/
++
++struct qla_fdt_layout {
++ uint8_t sig[4];
++ uint16_t version;
++ uint16_t len;
++ uint16_t checksum;
++ uint8_t unused1[2];
++ uint8_t model[16];
++ uint16_t man_id;
++ uint16_t id;
++ uint8_t flags;
++ uint8_t erase_cmd;
++ uint8_t alt_erase_cmd;
++ uint8_t wrt_enable_cmd;
++ uint8_t wrt_enable_bits;
++ uint8_t wrt_sts_reg_cmd;
++ uint8_t unprotect_sec_cmd;
++ uint8_t read_man_id_cmd;
++ uint32_t block_size;
++ uint32_t alt_block_size;
++ uint32_t flash_size;
++ uint32_t wrt_enable_data;
++ uint8_t read_id_addr_len;
++ uint8_t wrt_disable_bits;
++ uint8_t read_dev_id_len;
++ uint8_t chip_erase_cmd;
++ uint16_t read_timeout;
++ uint8_t protect_sec_cmd;
++ uint8_t unused2[65];
++};
++
++/* 84XX Support **************************************************************/
++
++#define MBA_ISP84XX_ALERT 0x800f /* Alert Notification. */
++#define A84_PANIC_RECOVERY 0x1
++#define A84_OP_LOGIN_COMPLETE 0x2
++#define A84_DIAG_LOGIN_COMPLETE 0x3
++#define A84_GOLD_LOGIN_COMPLETE 0x4
++
++#define MBC_ISP84XX_RESET 0x3a /* Reset. */
++
++#define FSTATE_REMOTE_FC_DOWN BIT_0
++#define FSTATE_NSL_LINK_DOWN BIT_1
++#define FSTATE_IS_DIAG_FW BIT_2
++#define FSTATE_LOGGED_IN BIT_3
++#define FSTATE_WAITING_FOR_VERIFY BIT_4
++
++#define VERIFY_CHIP_IOCB_TYPE 0x1B
++struct verify_chip_entry_84xx {
++ uint8_t entry_type;
++ uint8_t entry_count;
++ uint8_t sys_defined;
++ uint8_t entry_status;
++
++ uint32_t handle;
++
++ uint16_t options;
++#define VCO_DONT_UPDATE_FW BIT_0
++#define VCO_FORCE_UPDATE BIT_1
++#define VCO_DONT_RESET_UPDATE BIT_2
++#define VCO_DIAG_FW BIT_3
++#define VCO_END_OF_DATA BIT_14
++#define VCO_ENABLE_DSD BIT_15
++
++ uint16_t reserved_1;
++
++ uint16_t data_seg_cnt;
++ uint16_t reserved_2[3];
++
++ uint32_t fw_ver;
++ uint32_t exchange_address;
++
++ uint32_t reserved_3[3];
++ uint32_t fw_size;
++ uint32_t fw_seq_size;
++ uint32_t relative_offset;
++
++ uint32_t dseg_address[2];
++ uint32_t dseg_length;
++};
++
++struct verify_chip_rsp_84xx {
++ uint8_t entry_type;
++ uint8_t entry_count;
++ uint8_t sys_defined;
++ uint8_t entry_status;
++
++ uint32_t handle;
++
++ uint16_t comp_status;
++#define CS_VCS_CHIP_FAILURE 0x3
++#define CS_VCS_BAD_EXCHANGE 0x8
++#define CS_VCS_SEQ_COMPLETEi 0x40
++
++ uint16_t failure_code;
++#define VFC_CHECKSUM_ERROR 0x1
++#define VFC_INVALID_LEN 0x2
++#define VFC_ALREADY_IN_PROGRESS 0x8
++
++ uint16_t reserved_1[4];
++
++ uint32_t fw_ver;
++ uint32_t exchange_address;
++
++ uint32_t reserved_2[6];
++};
++
++#define ACCESS_CHIP_IOCB_TYPE 0x2B
++struct access_chip_84xx {
++ uint8_t entry_type;
++ uint8_t entry_count;
++ uint8_t sys_defined;
++ uint8_t entry_status;
++
++ uint32_t handle;
++
++ uint16_t options;
++#define ACO_DUMP_MEMORY 0x0
++#define ACO_LOAD_MEMORY 0x1
++#define ACO_CHANGE_CONFIG_PARAM 0x2
++#define ACO_REQUEST_INFO 0x3
++
++ uint16_t reserved1;
++
++ uint16_t dseg_count;
++ uint16_t reserved2[3];
++
++ uint32_t parameter1;
++ uint32_t parameter2;
++ uint32_t parameter3;
++
++ uint32_t reserved3[3];
++ uint32_t total_byte_cnt;
++ uint32_t reserved4;
++
++ uint32_t dseg_address[2];
++ uint32_t dseg_length;
++};
++
++struct access_chip_rsp_84xx {
++ uint8_t entry_type;
++ uint8_t entry_count;
++ uint8_t sys_defined;
++ uint8_t entry_status;
++
++ uint32_t handle;
++
++ uint16_t comp_status;
++ uint16_t failure_code;
++ uint32_t residual_count;
++
++ uint32_t reserved[12];
++};
+ #endif
+diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
+index 193f688..76eb4fe 100644
+--- a/drivers/scsi/qla2xxx/qla_gbl.h
++++ b/drivers/scsi/qla2xxx/qla_gbl.h
+@@ -1,6 +1,6 @@
+ /*
+ * QLogic Fibre Channel HBA Driver
+- * Copyright (c) 2003-2005 QLogic Corporation
++ * Copyright (c) 2003-2008 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+@@ -38,9 +38,6 @@ extern int qla2x00_loop_resync(scsi_qla_host_t *);
+ extern int qla2x00_fabric_login(scsi_qla_host_t *, fc_port_t *, uint16_t *);
+ extern int qla2x00_local_device_login(scsi_qla_host_t *, fc_port_t *);
+
+-extern void qla2x00_restart_queues(scsi_qla_host_t *, uint8_t);
+-
+-extern void qla2x00_rescan_fcports(scsi_qla_host_t *);
+ extern void qla2x00_update_fcports(scsi_qla_host_t *);
+
+ extern int qla2x00_abort_isp(scsi_qla_host_t *);
+@@ -50,6 +47,8 @@ extern void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *);
+ extern void qla2x00_alloc_fw_dump(scsi_qla_host_t *);
+ extern void qla2x00_try_to_stop_firmware(scsi_qla_host_t *);
+
++extern void qla84xx_put_chip(struct scsi_qla_host *);
++
+ /*
+ * Global Data in qla_os.c source file.
+ */
+@@ -67,6 +66,10 @@ extern int num_hosts;
+
+ extern int qla2x00_loop_reset(scsi_qla_host_t *);
+ extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
++extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum
++ fc_host_event_code, u32);
++extern int qla2x00_post_hwe_work(struct scsi_qla_host *, uint16_t , uint16_t,
++ uint16_t, uint16_t);
+
+ /*
+ * Global Functions in qla_mid.c source file.
+@@ -149,12 +152,17 @@ extern int
+ qla2x00_issue_iocb(scsi_qla_host_t *, void *, dma_addr_t, size_t);
+
+ extern int
++qla2x00_issue_iocb_timeout(scsi_qla_host_t *, void *, dma_addr_t, size_t,
++ uint32_t);
++
++extern int
+ qla2x00_abort_command(scsi_qla_host_t *, srb_t *);
+
+-#if USE_ABORT_TGT
+ extern int
+-qla2x00_abort_target(fc_port_t *);
+-#endif
++qla2x00_abort_target(struct fc_port *, unsigned int);
++
++extern int
++qla2x00_lun_reset(struct fc_port *, unsigned int);
+
+ extern int
+ qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *,
+@@ -220,7 +228,8 @@ qla24xx_get_isp_stats(scsi_qla_host_t *, struct link_statistics *,
+ dma_addr_t);
+
+ extern int qla24xx_abort_command(scsi_qla_host_t *, srb_t *);
+-extern int qla24xx_abort_target(fc_port_t *);
++extern int qla24xx_abort_target(struct fc_port *, unsigned int);
++extern int qla24xx_lun_reset(struct fc_port *, unsigned int);
+
+ extern int
+ qla2x00_set_serdes_params(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t);
+@@ -246,6 +255,8 @@ qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t, uint16_t);
+ extern int
+ qla2x00_set_idma_speed(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t *);
+
++extern int qla84xx_verify_chip(struct scsi_qla_host *, uint16_t *);
++
+ /*
+ * Global Function Prototypes in qla_isr.c source file.
+ */
+@@ -298,6 +309,11 @@ extern uint8_t *qla25xx_read_optrom_data(struct scsi_qla_host *, uint8_t *,
+ extern int qla2x00_get_flash_version(scsi_qla_host_t *, void *);
+ extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *);
+
++extern int qla2xxx_hw_event_log(scsi_qla_host_t *, uint16_t , uint16_t,
++ uint16_t, uint16_t);
++
++extern void qla2xxx_get_flash_info(scsi_qla_host_t *);
++
+ /*
+ * Global Function Prototypes in qla_dbg.c source file.
+ */
+@@ -307,7 +323,6 @@ extern void qla24xx_fw_dump(scsi_qla_host_t *, int);
+ extern void qla25xx_fw_dump(scsi_qla_host_t *, int);
+ extern void qla2x00_dump_regs(scsi_qla_host_t *);
+ extern void qla2x00_dump_buffer(uint8_t *, uint32_t);
+-extern void qla2x00_print_scsi_cmd(struct scsi_cmnd *);
+
+ /*
+ * Global Function Prototypes in qla_gs.c source file.
+@@ -332,8 +347,8 @@ extern void qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *);
+ /*
+ * Global Function Prototypes in qla_attr.c source file.
+ */
+-struct class_device_attribute;
+-extern struct class_device_attribute *qla2x00_host_attrs[];
++struct device_attribute;
++extern struct device_attribute *qla2x00_host_attrs[];
+ struct fc_function_template;
+ extern struct fc_function_template qla2xxx_transport_functions;
+ extern struct fc_function_template qla2xxx_transport_vport_functions;
+diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
+index c180876..750d7ef 100644
+--- a/drivers/scsi/qla2xxx/qla_gs.c
++++ b/drivers/scsi/qla2xxx/qla_gs.c
+@@ -1,17 +1,11 @@
+ /*
+ * QLogic Fibre Channel HBA Driver
+- * Copyright (c) 2003-2005 QLogic Corporation
++ * Copyright (c) 2003-2008 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+ #include "qla_def.h"
+
+-static inline struct ct_sns_req *
+-qla2x00_prep_ct_req(struct ct_sns_req *, uint16_t, uint16_t);
+-
+-static inline struct sns_cmd_pkt *
+-qla2x00_prep_sns_cmd(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t);
+-
+ static int qla2x00_sns_ga_nxt(scsi_qla_host_t *, fc_port_t *);
+ static int qla2x00_sns_gid_pt(scsi_qla_host_t *, sw_info_t *);
+ static int qla2x00_sns_gpn_id(scsi_qla_host_t *, sw_info_t *);
+@@ -1538,7 +1532,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
+ eiter->a.sup_speed = __constant_cpu_to_be32(
+ FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
+ FDMI_PORT_SPEED_4GB|FDMI_PORT_SPEED_8GB);
+- else if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
++ else if (IS_QLA24XX_TYPE(ha))
+ eiter->a.sup_speed = __constant_cpu_to_be32(
+ FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
+ FDMI_PORT_SPEED_4GB);
+@@ -1847,8 +1841,10 @@ qla2x00_gpsc(scsi_qla_host_t *ha, sw_info_t *list)
+ "GPSC")) != QLA_SUCCESS) {
+ /* FM command unsupported? */
+ if (rval == QLA_INVALID_COMMAND &&
+- ct_rsp->header.reason_code ==
+- CT_REASON_INVALID_COMMAND_CODE) {
++ (ct_rsp->header.reason_code ==
++ CT_REASON_INVALID_COMMAND_CODE ||
++ ct_rsp->header.reason_code ==
++ CT_REASON_COMMAND_UNSUPPORTED)) {
+ DEBUG2(printk("scsi(%ld): GPSC command "
+ "unsupported, disabling query...\n",
+ ha->host_no));
+diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
+index 364be7d..01e2608 100644
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -1,6 +1,6 @@
+ /*
+ * QLogic Fibre Channel HBA Driver
+- * Copyright (c) 2003-2005 QLogic Corporation
++ * Copyright (c) 2003-2008 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+@@ -15,14 +15,6 @@
+ #include <asm/prom.h>
+ #endif
+
+-/* XXX(hch): this is ugly, but we don't want to pull in exioctl.h */
+-#ifndef EXT_IS_LUN_BIT_SET
+-#define EXT_IS_LUN_BIT_SET(P,L) \
+- (((P)->mask[L/8] & (0x80 >> (L%8)))?1:0)
+-#define EXT_SET_LUN_BIT(P,L) \
+- ((P)->mask[L/8] |= (0x80 >> (L%8)))
+-#endif
+-
+ /*
+ * QLogic ISP2x00 Hardware Support Function Prototypes.
+ */
+@@ -45,6 +37,9 @@ static int qla2x00_restart_isp(scsi_qla_host_t *);
+
+ static int qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev);
+
++static struct qla_chip_state_84xx *qla84xx_get_chip(struct scsi_qla_host *);
++static int qla84xx_init_chip(scsi_qla_host_t *);
++
+ /****************************************************************************/
+ /* QLogic ISP2x00 Hardware Support Functions. */
+ /****************************************************************************/
+@@ -114,6 +109,15 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
+ rval = qla2x00_setup_chip(ha);
+ if (rval)
+ return (rval);
++ qla2xxx_get_flash_info(ha);
++ }
++ if (IS_QLA84XX(ha)) {
++ ha->cs84xx = qla84xx_get_chip(ha);
++ if (!ha->cs84xx) {
++ qla_printk(KERN_ERR, ha,
++ "Unable to configure ISP84XX.\n");
++ return QLA_FUNCTION_FAILED;
++ }
+ }
+ rval = qla2x00_init_rings(ha);
+
+@@ -500,6 +504,7 @@ qla2x00_reset_chip(scsi_qla_host_t *ha)
+ static inline void
+ qla24xx_reset_risc(scsi_qla_host_t *ha)
+ {
++ int hw_evt = 0;
+ unsigned long flags = 0;
+ struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+ uint32_t cnt, d2;
+@@ -528,6 +533,8 @@ qla24xx_reset_risc(scsi_qla_host_t *ha)
+ d2 = (uint32_t) RD_REG_WORD(®->mailbox0);
+ barrier();
+ }
++ if (cnt == 0)
++ hw_evt = 1;
+
+ /* Wait for soft-reset to complete. */
+ d2 = RD_REG_DWORD(®->ctrl_status);
+@@ -536,6 +543,10 @@ qla24xx_reset_risc(scsi_qla_host_t *ha)
+ d2 = RD_REG_DWORD(®->ctrl_status);
+ barrier();
+ }
++ if (cnt == 0 || hw_evt)
++ qla2xxx_hw_event_log(ha, HW_EVENT_RESET_ERR,
++ RD_REG_WORD(®->mailbox1), RD_REG_WORD(®->mailbox2),
++ RD_REG_WORD(®->mailbox3));
+
+ WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_RESET);
+ RD_REG_DWORD(®->hccr);
+@@ -1243,10 +1254,10 @@ static int
+ qla2x00_fw_ready(scsi_qla_host_t *ha)
+ {
+ int rval;
+- unsigned long wtime, mtime;
++ unsigned long wtime, mtime, cs84xx_time;
+ uint16_t min_wait; /* Minimum wait time if loop is down */
+ uint16_t wait_time; /* Wait time if loop is coming ready */
+- uint16_t fw_state;
++ uint16_t state[3];
+
+ rval = QLA_SUCCESS;
+
+@@ -1275,12 +1286,34 @@ qla2x00_fw_ready(scsi_qla_host_t *ha)
+ ha->host_no));
+
+ do {
+- rval = qla2x00_get_firmware_state(ha, &fw_state);
++ rval = qla2x00_get_firmware_state(ha, state);
+ if (rval == QLA_SUCCESS) {
+- if (fw_state < FSTATE_LOSS_OF_SYNC) {
++ if (state[0] < FSTATE_LOSS_OF_SYNC) {
+ ha->device_flags &= ~DFLG_NO_CABLE;
+ }
+- if (fw_state == FSTATE_READY) {
++ if (IS_QLA84XX(ha) && state[0] != FSTATE_READY) {
++ DEBUG16(printk("scsi(%ld): fw_state=%x "
++ "84xx=%x.\n", ha->host_no, state[0],
++ state[2]));
++ if ((state[2] & FSTATE_LOGGED_IN) &&
++ (state[2] & FSTATE_WAITING_FOR_VERIFY)) {
++ DEBUG16(printk("scsi(%ld): Sending "
++ "verify iocb.\n", ha->host_no));
++
++ cs84xx_time = jiffies;
++ rval = qla84xx_init_chip(ha);
++ if (rval != QLA_SUCCESS)
++ break;
++
++ /* Add time taken to initialize. */
++ cs84xx_time = jiffies - cs84xx_time;
++ wtime += cs84xx_time;
++ mtime += cs84xx_time;
++ DEBUG16(printk("scsi(%ld): Increasing "
++ "wait time by %ld. New time %ld\n",
++ ha->host_no, cs84xx_time, wtime));
++ }
++ } else if (state[0] == FSTATE_READY) {
+ DEBUG(printk("scsi(%ld): F/W Ready - OK \n",
+ ha->host_no));
+
+@@ -1294,7 +1327,7 @@ qla2x00_fw_ready(scsi_qla_host_t *ha)
+ rval = QLA_FUNCTION_FAILED;
+
+ if (atomic_read(&ha->loop_down_timer) &&
+- fw_state != FSTATE_READY) {
++ state[0] != FSTATE_READY) {
+ /* Loop down. Timeout on min_wait for states
+ * other than Wait for Login.
+ */
+@@ -1319,11 +1352,11 @@ qla2x00_fw_ready(scsi_qla_host_t *ha)
+ msleep(500);
+
+ DEBUG3(printk("scsi(%ld): fw_state=%x curr time=%lx.\n",
+- ha->host_no, fw_state, jiffies));
++ ha->host_no, state[0], jiffies));
+ } while (1);
+
+ DEBUG(printk("scsi(%ld): fw_state=%x curr time=%lx.\n",
+- ha->host_no, fw_state, jiffies));
++ ha->host_no, state[0], jiffies));
+
+ if (rval) {
+ DEBUG2_3(printk("scsi(%ld): Firmware ready **** FAILED ****.\n",
+@@ -1555,6 +1588,10 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
+ qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
+ "invalid -- WWPN) defaults.\n");
+
++ if (chksum)
++ qla2xxx_hw_event_log(ha, HW_EVENT_NVRAM_CHKSUM_ERR, 0,
++ MSW(chksum), LSW(chksum));
++
+ /*
+ * Set default initialization control block.
+ */
+@@ -2165,20 +2202,6 @@ cleanup_allocation:
+ }
+
+ static void
+-qla2x00_probe_for_all_luns(scsi_qla_host_t *ha)
+-{
+- fc_port_t *fcport;
+-
+- qla2x00_mark_all_devices_lost(ha, 0);
+- list_for_each_entry(fcport, &ha->fcports, list) {
+- if (fcport->port_type != FCT_TARGET)
+- continue;
+-
+- qla2x00_update_fcport(ha, fcport);
+- }
+-}
+-
+-static void
+ qla2x00_iidma_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
+ {
+ #define LS_UNKNOWN 2
+@@ -2251,10 +2274,6 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
+ if (fcport->port_type == FCT_TARGET)
+ rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
+ fc_remote_port_rolechg(rport, rport_ids.roles);
+-
+- if (rport->scsi_target_id != -1 &&
+- rport->scsi_target_id < ha->host->max_id)
+- fcport->os_target_id = rport->scsi_target_id;
+ }
+
+ /*
+@@ -2434,7 +2453,8 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
+
+ if (fcport->loop_id == FC_NO_LOOP_ID) {
+ fcport->loop_id = next_loopid;
+- rval = qla2x00_find_new_loop_id(ha, fcport);
++ rval = qla2x00_find_new_loop_id(
++ to_qla_parent(ha), fcport);
+ if (rval != QLA_SUCCESS) {
+ /* Ran out of IDs to use */
+ break;
+@@ -2459,7 +2479,8 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
+
+ /* Find a new loop ID to use. */
+ fcport->loop_id = next_loopid;
+- rval = qla2x00_find_new_loop_id(ha, fcport);
++ rval = qla2x00_find_new_loop_id(to_qla_parent(ha),
++ fcport);
+ if (rval != QLA_SUCCESS) {
+ /* Ran out of IDs to use */
+ break;
+@@ -3193,25 +3214,6 @@ qla2x00_loop_resync(scsi_qla_host_t *ha)
+ }
+
+ void
+-qla2x00_rescan_fcports(scsi_qla_host_t *ha)
+-{
+- int rescan_done;
+- fc_port_t *fcport;
+-
+- rescan_done = 0;
+- list_for_each_entry(fcport, &ha->fcports, list) {
+- if ((fcport->flags & FCF_RESCAN_NEEDED) == 0)
+- continue;
+-
+- qla2x00_update_fcport(ha, fcport);
+- fcport->flags &= ~FCF_RESCAN_NEEDED;
+-
+- rescan_done = 1;
+- }
+- qla2x00_probe_for_all_luns(ha);
+-}
+-
+-void
+ qla2x00_update_fcports(scsi_qla_host_t *ha)
+ {
+ fc_port_t *fcport;
+@@ -4044,16 +4046,16 @@ qla24xx_configure_vhba(scsi_qla_host_t *ha)
+ if (!ha->parent)
+ return -EINVAL;
+
+- rval = qla2x00_fw_ready(ha);
++ rval = qla2x00_fw_ready(ha->parent);
+ if (rval == QLA_SUCCESS) {
+ clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
+- qla2x00_marker(ha, 0, 0, MK_SYNC_ALL);
++ qla2x00_marker(ha->parent, 0, 0, MK_SYNC_ALL);
+ }
+
+ ha->flags.management_server_logged_in = 0;
+
+ /* Login to SNS first */
+- qla24xx_login_fabric(ha, NPH_SNS, 0xff, 0xff, 0xfc,
++ qla24xx_login_fabric(ha->parent, NPH_SNS, 0xff, 0xff, 0xfc,
+ mb, BIT_1);
+ if (mb[0] != MBS_COMMAND_COMPLETE) {
+ DEBUG15(qla_printk(KERN_INFO, ha,
+@@ -4067,7 +4069,77 @@ qla24xx_configure_vhba(scsi_qla_host_t *ha)
+ atomic_set(&ha->loop_state, LOOP_UP);
+ set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
+ set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
+- rval = qla2x00_loop_resync(ha);
++ rval = qla2x00_loop_resync(ha->parent);
+
+ return rval;
+ }
++
++/* 84XX Support **************************************************************/
++
++static LIST_HEAD(qla_cs84xx_list);
++static DEFINE_MUTEX(qla_cs84xx_mutex);
++
++static struct qla_chip_state_84xx *
++qla84xx_get_chip(struct scsi_qla_host *ha)
++{
++ struct qla_chip_state_84xx *cs84xx;
++
++ mutex_lock(&qla_cs84xx_mutex);
++
++ /* Find any shared 84xx chip. */
++ list_for_each_entry(cs84xx, &qla_cs84xx_list, list) {
++ if (cs84xx->bus == ha->pdev->bus) {
++ kref_get(&cs84xx->kref);
++ goto done;
++ }
++ }
++
++ cs84xx = kzalloc(sizeof(*cs84xx), GFP_KERNEL);
++ if (!cs84xx)
++ goto done;
++
++ kref_init(&cs84xx->kref);
++ spin_lock_init(&cs84xx->access_lock);
++ mutex_init(&cs84xx->fw_update_mutex);
++ cs84xx->bus = ha->pdev->bus;
++
++ list_add_tail(&cs84xx->list, &qla_cs84xx_list);
++done:
++ mutex_unlock(&qla_cs84xx_mutex);
++ return cs84xx;
++}
++
++static void
++__qla84xx_chip_release(struct kref *kref)
++{
++ struct qla_chip_state_84xx *cs84xx =
++ container_of(kref, struct qla_chip_state_84xx, kref);
++
++ mutex_lock(&qla_cs84xx_mutex);
++ list_del(&cs84xx->list);
++ mutex_unlock(&qla_cs84xx_mutex);
++ kfree(cs84xx);
++}
++
++void
++qla84xx_put_chip(struct scsi_qla_host *ha)
++{
++ if (ha->cs84xx)
++ kref_put(&ha->cs84xx->kref, __qla84xx_chip_release);
++}
++
++static int
++qla84xx_init_chip(scsi_qla_host_t *ha)
++{
++ int rval;
++ uint16_t status[2];
++
++ mutex_lock(&ha->cs84xx->fw_update_mutex);
++
++ rval = qla84xx_verify_chip(ha, status);
++
++ mutex_unlock(&ha->cs84xx->fw_update_mutex);
++
++ return rval != QLA_SUCCESS || status[0] ? QLA_FUNCTION_FAILED:
++ QLA_SUCCESS;
++}
+diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
+index 5d1a3f7..e9bae27 100644
+--- a/drivers/scsi/qla2xxx/qla_inline.h
++++ b/drivers/scsi/qla2xxx/qla_inline.h
+@@ -1,11 +1,10 @@
+ /*
+ * QLogic Fibre Channel HBA Driver
+- * Copyright (c) 2003-2005 QLogic Corporation
++ * Copyright (c) 2003-2008 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+
+-static __inline__ uint16_t qla2x00_debounce_register(volatile uint16_t __iomem *);
+ /*
+ * qla2x00_debounce_register
+ * Debounce register.
+@@ -32,94 +31,12 @@ qla2x00_debounce_register(volatile uint16_t __iomem *addr)
+ return (first);
+ }
+
+-static __inline__ int qla2x00_normalize_dma_addr(
+- dma_addr_t *e_addr, uint32_t *e_len,
+- dma_addr_t *ne_addr, uint32_t *ne_len);
+-
+-/**
+- * qla2x00_normalize_dma_addr() - Normalize an DMA address.
+- * @e_addr: Raw DMA address
+- * @e_len: Raw DMA length
+- * @ne_addr: Normalized second DMA address
+- * @ne_len: Normalized second DMA length
+- *
+- * If the address does not span a 4GB page boundary, the contents of @ne_addr
+- * and @ne_len are undefined. @e_len is updated to reflect a normalization.
+- *
+- * Example:
+- *
+- * ffffabc0ffffeeee (e_addr) start of DMA address
+- * 0000000020000000 (e_len) length of DMA transfer
+- * ffffabc11fffeeed end of DMA transfer
+- *
+- * Is the 4GB boundary crossed?
+- *
+- * ffffabc0ffffeeee (e_addr)
+- * ffffabc11fffeeed (e_addr + e_len - 1)
+- * 00000001e0000003 ((e_addr ^ (e_addr + e_len - 1))
+- * 0000000100000000 ((e_addr ^ (e_addr + e_len - 1)) & ~(0xffffffff)
+- *
+- * Compute start of second DMA segment:
+- *
+- * ffffabc0ffffeeee (e_addr)
+- * ffffabc1ffffeeee (0x100000000 + e_addr)
+- * ffffabc100000000 (0x100000000 + e_addr) & ~(0xffffffff)
+- * ffffabc100000000 (ne_addr)
+- *
+- * Compute length of second DMA segment:
+- *
+- * 00000000ffffeeee (e_addr & 0xffffffff)
+- * 0000000000001112 (0x100000000 - (e_addr & 0xffffffff))
+- * 000000001fffeeee (e_len - (0x100000000 - (e_addr & 0xffffffff))
+- * 000000001fffeeee (ne_len)
+- *
+- * Adjust length of first DMA segment
+- *
+- * 0000000020000000 (e_len)
+- * 0000000000001112 (e_len - ne_len)
+- * 0000000000001112 (e_len)
+- *
+- * Returns non-zero if the specified address was normalized, else zero.
+- */
+-static __inline__ int
+-qla2x00_normalize_dma_addr(
+- dma_addr_t *e_addr, uint32_t *e_len,
+- dma_addr_t *ne_addr, uint32_t *ne_len)
+-{
+- int normalized;
+-
+- normalized = 0;
+- if ((*e_addr ^ (*e_addr + *e_len - 1)) & ~(0xFFFFFFFFULL)) {
+- /* Compute normalized crossed address and len */
+- *ne_addr = (0x100000000ULL + *e_addr) & ~(0xFFFFFFFFULL);
+- *ne_len = *e_len - (0x100000000ULL - (*e_addr & 0xFFFFFFFFULL));
+- *e_len -= *ne_len;
+-
+- normalized++;
+- }
+- return (normalized);
+-}
+-
+-static __inline__ void qla2x00_poll(scsi_qla_host_t *);
+ static inline void
+ qla2x00_poll(scsi_qla_host_t *ha)
+ {
+ ha->isp_ops->intr_handler(0, ha);
+ }
+
+-static __inline__ void qla2x00_check_fabric_devices(scsi_qla_host_t *);
+-/*
+- * This routine will wait for fabric devices for
+- * the reset delay.
+- */
+-static __inline__ void qla2x00_check_fabric_devices(scsi_qla_host_t *ha)
+-{
+- uint16_t fw_state;
+-
+- qla2x00_get_firmware_state(ha, &fw_state);
+-}
+-
+-static __inline__ scsi_qla_host_t * to_qla_parent(scsi_qla_host_t *);
+ static __inline__ scsi_qla_host_t *
+ to_qla_parent(scsi_qla_host_t *ha)
+ {
+@@ -152,7 +69,6 @@ qla2x00_issue_marker(scsi_qla_host_t *ha, int ha_locked)
+ return (QLA_SUCCESS);
+ }
+
+-static inline uint8_t *host_to_fcp_swap(uint8_t *, uint32_t);
+ static inline uint8_t *
+ host_to_fcp_swap(uint8_t *fcp, uint32_t bsize)
+ {
+@@ -166,7 +82,6 @@ host_to_fcp_swap(uint8_t *fcp, uint32_t bsize)
+ return fcp;
+ }
+
+-static inline int qla2x00_is_reserved_id(scsi_qla_host_t *, uint16_t);
+ static inline int
+ qla2x00_is_reserved_id(scsi_qla_host_t *ha, uint16_t loop_id)
+ {
+diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
+index 024c662..5489d50 100644
+--- a/drivers/scsi/qla2xxx/qla_iocb.c
++++ b/drivers/scsi/qla2xxx/qla_iocb.c
+@@ -1,6 +1,6 @@
+ /*
+ * QLogic Fibre Channel HBA Driver
+- * Copyright (c) 2003-2005 QLogic Corporation
++ * Copyright (c) 2003-2008 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+@@ -11,9 +11,6 @@
+
+ #include <scsi/scsi_tcq.h>
+
+-static inline uint16_t qla2x00_get_cmd_direction(struct scsi_cmnd *cmd);
+-static inline cont_entry_t *qla2x00_prep_cont_type0_iocb(scsi_qla_host_t *);
+-static inline cont_a64_entry_t *qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *);
+ static request_t *qla2x00_req_pkt(scsi_qla_host_t *ha);
+ static void qla2x00_isp_cmd(scsi_qla_host_t *ha);
+
+diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
+index f033703..285479b 100644
+--- a/drivers/scsi/qla2xxx/qla_isr.c
++++ b/drivers/scsi/qla2xxx/qla_isr.c
+@@ -1,6 +1,6 @@
+ /*
+ * QLogic Fibre Channel HBA Driver
+- * Copyright (c) 2003-2005 QLogic Corporation
++ * Copyright (c) 2003-2008 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+@@ -14,9 +14,6 @@ static void qla2x00_process_completed_request(struct scsi_qla_host *, uint32_t);
+ static void qla2x00_status_entry(scsi_qla_host_t *, void *);
+ static void qla2x00_status_cont_entry(scsi_qla_host_t *, sts_cont_entry_t *);
+ static void qla2x00_error_entry(scsi_qla_host_t *, sts_entry_t *);
+-static void qla2x00_ms_entry(scsi_qla_host_t *, ms_iocb_entry_t *);
+-
+-static void qla24xx_ms_entry(scsi_qla_host_t *, struct ct_entry_24xx *);
+
+ /**
+ * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200.
+@@ -33,7 +30,6 @@ qla2100_intr_handler(int irq, void *dev_id)
+ scsi_qla_host_t *ha;
+ struct device_reg_2xxx __iomem *reg;
+ int status;
+- unsigned long flags;
+ unsigned long iter;
+ uint16_t hccr;
+ uint16_t mb[4];
+@@ -48,7 +44,7 @@ qla2100_intr_handler(int irq, void *dev_id)
+ reg = &ha->iobase->isp;
+ status = 0;
+
+- spin_lock_irqsave(&ha->hardware_lock, flags);
++ spin_lock(&ha->hardware_lock);
+ for (iter = 50; iter--; ) {
+ hccr = RD_REG_WORD(®->hccr);
+ if (hccr & HCCR_RISC_PAUSE) {
+@@ -99,7 +95,7 @@ qla2100_intr_handler(int irq, void *dev_id)
+ RD_REG_WORD(®->hccr);
+ }
+ }
+- spin_unlock_irqrestore(&ha->hardware_lock, flags);
++ spin_unlock(&ha->hardware_lock);
+
+ if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
+ (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
+@@ -125,7 +121,6 @@ qla2300_intr_handler(int irq, void *dev_id)
+ scsi_qla_host_t *ha;
+ struct device_reg_2xxx __iomem *reg;
+ int status;
+- unsigned long flags;
+ unsigned long iter;
+ uint32_t stat;
+ uint16_t hccr;
+@@ -141,7 +136,7 @@ qla2300_intr_handler(int irq, void *dev_id)
+ reg = &ha->iobase->isp;
+ status = 0;
+
+- spin_lock_irqsave(&ha->hardware_lock, flags);
++ spin_lock(&ha->hardware_lock);
+ for (iter = 50; iter--; ) {
+ stat = RD_REG_DWORD(®->u.isp2300.host_status);
+ if (stat & HSR_RISC_PAUSED) {
+@@ -211,7 +206,7 @@ qla2300_intr_handler(int irq, void *dev_id)
+ WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT);
+ RD_REG_WORD_RELAXED(®->hccr);
+ }
+- spin_unlock_irqrestore(&ha->hardware_lock, flags);
++ spin_unlock(&ha->hardware_lock);
+
+ if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
+ (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
+@@ -276,6 +271,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+ struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+ uint32_t rscn_entry, host_pid;
+ uint8_t rscn_queue_index;
++ unsigned long flags;
++ scsi_qla_host_t *vha;
++ int i;
+
+ /* Setup to process RIO completion. */
+ handle_cnt = 0;
+@@ -351,6 +349,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+ "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n",
+ mb[1], mb[2], mb[3]);
+
++ qla2x00_post_hwe_work(ha, mb[0], mb[1], mb[2], mb[3]);
+ ha->isp_ops->fw_dump(ha, 1);
+
+ if (IS_FWI2_CAPABLE(ha)) {
+@@ -375,6 +374,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+ ha->host_no));
+ qla_printk(KERN_WARNING, ha, "ISP Request Transfer Error.\n");
+
++ qla2x00_post_hwe_work(ha, mb[0], mb[1], mb[2], mb[3]);
+ set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+ break;
+
+@@ -383,6 +383,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+ ha->host_no));
+ qla_printk(KERN_WARNING, ha, "ISP Response Transfer Error.\n");
+
++ qla2x00_post_hwe_work(ha, mb[0], mb[1], mb[2], mb[3]);
+ set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+ break;
+
+@@ -410,6 +411,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+ set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
+
+ ha->flags.management_server_logged_in = 0;
++ qla2x00_post_aen_work(ha, FCH_EVT_LIP, mb[1]);
+ break;
+
+ case MBA_LOOP_UP: /* Loop Up Event */
+@@ -429,12 +431,14 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+ link_speed);
+
+ ha->flags.management_server_logged_in = 0;
++ qla2x00_post_aen_work(ha, FCH_EVT_LINKUP, ha->link_data_rate);
+ break;
+
+ case MBA_LOOP_DOWN: /* Loop Down Event */
+- DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN (%x).\n",
+- ha->host_no, mb[1]));
+- qla_printk(KERN_INFO, ha, "LOOP DOWN detected (%x).\n", mb[1]);
++ DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN "
++ "(%x %x %x).\n", ha->host_no, mb[1], mb[2], mb[3]));
++ qla_printk(KERN_INFO, ha, "LOOP DOWN detected (%x %x %x).\n",
++ mb[1], mb[2], mb[3]);
+
+ if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
+ atomic_set(&ha->loop_state, LOOP_DOWN);
+@@ -452,6 +456,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+ ha->link_data_rate = PORT_SPEED_UNKNOWN;
+ if (ql2xfdmienable)
+ set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
++ qla2x00_post_aen_work(ha, FCH_EVT_LINKDOWN, 0);
+ break;
+
+ case MBA_LIP_RESET: /* LIP reset occurred */
+@@ -475,6 +480,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+
+ ha->operating_mode = LOOP;
+ ha->flags.management_server_logged_in = 0;
++ qla2x00_post_aen_work(ha, FCH_EVT_LIPRESET, mb[1]);
+ break;
+
+ case MBA_POINT_TO_POINT: /* Point-to-Point */
+@@ -538,6 +544,18 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+ break;
+
+ case MBA_PORT_UPDATE: /* Port database update */
++ if ((ha->flags.npiv_supported) && (ha->num_vhosts)) {
++ for_each_mapped_vp_idx(ha, i) {
++ list_for_each_entry(vha, &ha->vp_list,
++ vp_list) {
++ if ((mb[3] & 0xff)
++ == vha->vp_idx) {
++ ha = vha;
++ break;
++ }
++ }
++ }
++ }
+ /*
+ * If PORT UPDATE is global (recieved LIP_OCCURED/LIP_RESET
+ * event etc. earlier indicating loop is down) then process
+@@ -572,12 +590,18 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+ break;
+
+ case MBA_RSCN_UPDATE: /* State Change Registration */
+- /* Check if the Vport has issued a SCR */
+- if (ha->parent && test_bit(VP_SCR_NEEDED, &ha->vp_flags))
+- break;
+- /* Only handle SCNs for our Vport index. */
+- if (ha->flags.npiv_supported && ha->vp_idx != mb[3])
+- break;
++ if ((ha->flags.npiv_supported) && (ha->num_vhosts)) {
++ for_each_mapped_vp_idx(ha, i) {
++ list_for_each_entry(vha, &ha->vp_list,
++ vp_list) {
++ if ((mb[3] & 0xff)
++ == vha->vp_idx) {
++ ha = vha;
++ break;
++ }
++ }
++ }
++ }
+
+ DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n",
+ ha->host_no));
+@@ -612,6 +636,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+
+ set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
+ set_bit(RSCN_UPDATE, &ha->dpc_flags);
++ qla2x00_post_aen_work(ha, FCH_EVT_RSCN, rscn_entry);
+ break;
+
+ /* case MBA_RIO_RESPONSE: */
+@@ -637,6 +662,42 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
+ DEBUG2(printk("scsi(%ld): Trace Notification -- %04x %04x.\n",
+ ha->host_no, mb[1], mb[2]));
+ break;
++
++ case MBA_ISP84XX_ALERT:
++ DEBUG2(printk("scsi(%ld): ISP84XX Alert Notification -- "
++ "%04x %04x %04x\n", ha->host_no, mb[1], mb[2], mb[3]));
++
++ spin_lock_irqsave(&ha->cs84xx->access_lock, flags);
++ switch (mb[1]) {
++ case A84_PANIC_RECOVERY:
++ qla_printk(KERN_INFO, ha, "Alert 84XX: panic recovery "
++ "%04x %04x\n", mb[2], mb[3]);
++ break;
++ case A84_OP_LOGIN_COMPLETE:
++ ha->cs84xx->op_fw_version = mb[3] << 16 | mb[2];
++ DEBUG2(qla_printk(KERN_INFO, ha, "Alert 84XX:"
++ "firmware version %x\n", ha->cs84xx->op_fw_version));
++ break;
++ case A84_DIAG_LOGIN_COMPLETE:
++ ha->cs84xx->diag_fw_version = mb[3] << 16 | mb[2];
++ DEBUG2(qla_printk(KERN_INFO, ha, "Alert 84XX:"
++ "diagnostic firmware version %x\n",
++ ha->cs84xx->diag_fw_version));
++ break;
++ case A84_GOLD_LOGIN_COMPLETE:
++ ha->cs84xx->diag_fw_version = mb[3] << 16 | mb[2];
++ ha->cs84xx->fw_update = 1;
++ DEBUG2(qla_printk(KERN_INFO, ha, "Alert 84XX: gold "
++ "firmware version %x\n",
++ ha->cs84xx->gold_fw_version));
++ break;
++ default:
++ qla_printk(KERN_ERR, ha,
++ "Alert 84xx: Invalid Alert %04x %04x %04x\n",
++ mb[1], mb[2], mb[3]);
++ }
++ spin_unlock_irqrestore(&ha->cs84xx->access_lock, flags);
++ break;
+ }
+
+ if (!ha->parent && ha->num_vhosts)
+@@ -803,9 +864,6 @@ qla2x00_process_response_queue(struct scsi_qla_host *ha)
+ case STATUS_CONT_TYPE:
+ qla2x00_status_cont_entry(ha, (sts_cont_entry_t *)pkt);
+ break;
+- case MS_IOCB_TYPE:
+- qla2x00_ms_entry(ha, (ms_iocb_entry_t *)pkt);
+- break;
+ default:
+ /* Type Not Supported. */
+ DEBUG4(printk(KERN_WARNING
+@@ -1340,44 +1398,6 @@ qla2x00_error_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
+ }
+
+ /**
+- * qla2x00_ms_entry() - Process a Management Server entry.
+- * @ha: SCSI driver HA context
+- * @index: Response queue out pointer
+- */
+-static void
+-qla2x00_ms_entry(scsi_qla_host_t *ha, ms_iocb_entry_t *pkt)
+-{
+- srb_t *sp;
+-
+- DEBUG3(printk("%s(%ld): pkt=%p pkthandle=%d.\n",
+- __func__, ha->host_no, pkt, pkt->handle1));
+-
+- /* Validate handle. */
+- if (pkt->handle1 < MAX_OUTSTANDING_COMMANDS)
+- sp = ha->outstanding_cmds[pkt->handle1];
+- else
+- sp = NULL;
+-
+- if (sp == NULL) {
+- DEBUG2(printk("scsi(%ld): MS entry - invalid handle\n",
+- ha->host_no));
+- qla_printk(KERN_WARNING, ha, "MS entry - invalid handle\n");
+-
+- set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+- return;
+- }
+-
+- CMD_COMPL_STATUS(sp->cmd) = le16_to_cpu(pkt->status);
+- CMD_ENTRY_STATUS(sp->cmd) = pkt->entry_status;
+-
+- /* Free outstanding command slot. */
+- ha->outstanding_cmds[pkt->handle1] = NULL;
+-
+- qla2x00_sp_compl(ha, sp);
+-}
+-
+-
+-/**
+ * qla24xx_mbx_completion() - Process mailbox command completions.
+ * @ha: SCSI driver HA context
+ * @mb0: Mailbox0 register
+@@ -1449,9 +1469,6 @@ qla24xx_process_response_queue(struct scsi_qla_host *ha)
+ case STATUS_CONT_TYPE:
+ qla2x00_status_cont_entry(ha, (sts_cont_entry_t *)pkt);
+ break;
+- case MS_IOCB_TYPE:
+- qla24xx_ms_entry(ha, (struct ct_entry_24xx *)pkt);
+- break;
+ case VP_RPT_ID_IOCB_TYPE:
+ qla24xx_report_id_acquisition(ha,
+ (struct vp_rpt_id_entry_24xx *)pkt);
+@@ -1533,7 +1550,6 @@ qla24xx_intr_handler(int irq, void *dev_id)
+ scsi_qla_host_t *ha;
+ struct device_reg_24xx __iomem *reg;
+ int status;
+- unsigned long flags;
+ unsigned long iter;
+ uint32_t stat;
+ uint32_t hccr;
+@@ -1549,13 +1565,19 @@ qla24xx_intr_handler(int irq, void *dev_id)
+ reg = &ha->iobase->isp24;
+ status = 0;
+
+- spin_lock_irqsave(&ha->hardware_lock, flags);
++ spin_lock(&ha->hardware_lock);
+ for (iter = 50; iter--; ) {
+ stat = RD_REG_DWORD(®->host_status);
+ if (stat & HSRX_RISC_PAUSED) {
+ if (pci_channel_offline(ha->pdev))
+ break;
+
++ if (ha->hw_event_pause_errors == 0)
++ qla2x00_post_hwe_work(ha, HW_EVENT_PARITY_ERR,
++ 0, MSW(stat), LSW(stat));
++ else if (ha->hw_event_pause_errors < 0xffffffff)
++ ha->hw_event_pause_errors++;
++
+ hccr = RD_REG_DWORD(®->hccr);
+
+ qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
+@@ -1597,7 +1619,7 @@ qla24xx_intr_handler(int irq, void *dev_id)
+ WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT);
+ RD_REG_DWORD_RELAXED(®->hccr);
+ }
+- spin_unlock_irqrestore(&ha->hardware_lock, flags);
++ spin_unlock(&ha->hardware_lock);
+
+ if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
+ (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
+@@ -1608,66 +1630,21 @@ qla24xx_intr_handler(int irq, void *dev_id)
+ return IRQ_HANDLED;
+ }
+
+-/**
+- * qla24xx_ms_entry() - Process a Management Server entry.
+- * @ha: SCSI driver HA context
+- * @index: Response queue out pointer
+- */
+-static void
+-qla24xx_ms_entry(scsi_qla_host_t *ha, struct ct_entry_24xx *pkt)
+-{
+- srb_t *sp;
+-
+- DEBUG3(printk("%s(%ld): pkt=%p pkthandle=%d.\n",
+- __func__, ha->host_no, pkt, pkt->handle));
+-
+- DEBUG9(printk("%s: ct pkt dump:\n", __func__));
+- DEBUG9(qla2x00_dump_buffer((void *)pkt, sizeof(struct ct_entry_24xx)));
+-
+- /* Validate handle. */
+- if (pkt->handle < MAX_OUTSTANDING_COMMANDS)
+- sp = ha->outstanding_cmds[pkt->handle];
+- else
+- sp = NULL;
+-
+- if (sp == NULL) {
+- DEBUG2(printk("scsi(%ld): MS entry - invalid handle\n",
+- ha->host_no));
+- DEBUG10(printk("scsi(%ld): MS entry - invalid handle\n",
+- ha->host_no));
+- qla_printk(KERN_WARNING, ha, "MS entry - invalid handle %d\n",
+- pkt->handle);
+-
+- set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+- return;
+- }
+-
+- CMD_COMPL_STATUS(sp->cmd) = le16_to_cpu(pkt->comp_status);
+- CMD_ENTRY_STATUS(sp->cmd) = pkt->entry_status;
+-
+- /* Free outstanding command slot. */
+- ha->outstanding_cmds[pkt->handle] = NULL;
+-
+- qla2x00_sp_compl(ha, sp);
+-}
+-
+ static irqreturn_t
+ qla24xx_msix_rsp_q(int irq, void *dev_id)
+ {
+ scsi_qla_host_t *ha;
+ struct device_reg_24xx __iomem *reg;
+- unsigned long flags;
+
+ ha = dev_id;
+ reg = &ha->iobase->isp24;
+
+- spin_lock_irqsave(&ha->hardware_lock, flags);
++ spin_lock(&ha->hardware_lock);
+
+ qla24xx_process_response_queue(ha);
+-
+ WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT);
+
+- spin_unlock_irqrestore(&ha->hardware_lock, flags);
++ spin_unlock(&ha->hardware_lock);
+
+ return IRQ_HANDLED;
+ }
+@@ -1678,7 +1655,6 @@ qla24xx_msix_default(int irq, void *dev_id)
+ scsi_qla_host_t *ha;
+ struct device_reg_24xx __iomem *reg;
+ int status;
+- unsigned long flags;
+ uint32_t stat;
+ uint32_t hccr;
+ uint16_t mb[4];
+@@ -1687,13 +1663,19 @@ qla24xx_msix_default(int irq, void *dev_id)
+ reg = &ha->iobase->isp24;
+ status = 0;
+
+- spin_lock_irqsave(&ha->hardware_lock, flags);
++ spin_lock(&ha->hardware_lock);
+ do {
+ stat = RD_REG_DWORD(®->host_status);
+ if (stat & HSRX_RISC_PAUSED) {
+ if (pci_channel_offline(ha->pdev))
+ break;
+
++ if (ha->hw_event_pause_errors == 0)
++ qla2x00_post_hwe_work(ha, HW_EVENT_PARITY_ERR,
++ 0, MSW(stat), LSW(stat));
++ else if (ha->hw_event_pause_errors < 0xffffffff)
++ ha->hw_event_pause_errors++;
++
+ hccr = RD_REG_DWORD(®->hccr);
+
+ qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
+@@ -1734,7 +1716,7 @@ qla24xx_msix_default(int irq, void *dev_id)
+ }
+ WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT);
+ } while (0);
+- spin_unlock_irqrestore(&ha->hardware_lock, flags);
++ spin_unlock(&ha->hardware_lock);
+
+ if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
+ (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
+@@ -1821,10 +1803,9 @@ qla2x00_request_irqs(scsi_qla_host_t *ha)
+ {
+ int ret;
+ device_reg_t __iomem *reg = ha->iobase;
+- unsigned long flags;
+
+ /* If possible, enable MSI-X. */
+- if (!IS_QLA2432(ha) && !IS_QLA2532(ha))
++ if (!IS_QLA2432(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha))
+ goto skip_msix;
+
+ if (IS_QLA2432(ha) && (ha->chip_revision < QLA_MSIX_CHIP_REV_24XX ||
+@@ -1859,7 +1840,7 @@ qla2x00_request_irqs(scsi_qla_host_t *ha)
+ "MSI-X: Falling back-to INTa mode -- %d.\n", ret);
+ skip_msix:
+
+- if (!IS_QLA24XX(ha) && !IS_QLA2532(ha))
++ if (!IS_QLA24XX(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha))
+ goto skip_msi;
+
+ ret = pci_enable_msi(ha->pdev);
+@@ -1882,7 +1863,7 @@ skip_msi:
+ clear_risc_ints:
+
+ ha->isp_ops->disable_intrs(ha);
+- spin_lock_irqsave(&ha->hardware_lock, flags);
++ spin_lock_irq(&ha->hardware_lock);
+ if (IS_FWI2_CAPABLE(ha)) {
+ WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_HOST_INT);
+ WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_RISC_INT);
+@@ -1891,7 +1872,7 @@ clear_risc_ints:
+ WRT_REG_WORD(®->isp.hccr, HCCR_CLR_RISC_INT);
+ WRT_REG_WORD(®->isp.hccr, HCCR_CLR_HOST_INT);
+ }
+- spin_unlock_irqrestore(&ha->hardware_lock, flags);
++ spin_unlock_irq(&ha->hardware_lock);
+ ha->isp_ops->enable_intrs(ha);
+
+ fail:
+diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
+index bb10358..7d0a8a4 100644
+--- a/drivers/scsi/qla2xxx/qla_mbx.c
++++ b/drivers/scsi/qla2xxx/qla_mbx.c
+@@ -1,6 +1,6 @@
+ /*
+ * QLogic Fibre Channel HBA Driver
+- * Copyright (c) 2003-2005 QLogic Corporation
++ * Copyright (c) 2003-2008 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+@@ -310,7 +310,7 @@ qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr,
+ }
+
+ mcp->in_mb = MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+@@ -367,7 +367,7 @@ qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr)
+ }
+ }
+
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+@@ -417,7 +417,7 @@ qla2x00_get_fw_version(scsi_qla_host_t *ha, uint16_t *major, uint16_t *minor,
+ mcp->out_mb = MBX_0;
+ mcp->in_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->flags = 0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+ /* Return mailbox data. */
+@@ -466,7 +466,7 @@ qla2x00_get_fw_options(scsi_qla_host_t *ha, uint16_t *fwopts)
+ mcp->mb[0] = MBC_GET_FIRMWARE_OPTION;
+ mcp->out_mb = MBX_0;
+ mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+@@ -524,7 +524,7 @@ qla2x00_set_fw_options(scsi_qla_host_t *ha, uint16_t *fwopts)
+ mcp->mb[12] = 0; /* Undocumented, but used */
+ mcp->out_mb |= MBX_12|MBX_11|MBX_10;
+ }
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+@@ -576,7 +576,7 @@ qla2x00_mbx_reg_test(scsi_qla_host_t *ha)
+ mcp->mb[7] = 0x2525;
+ mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+@@ -587,6 +587,14 @@ qla2x00_mbx_reg_test(scsi_qla_host_t *ha)
+ if (mcp->mb[5] != 0xA5A5 || mcp->mb[6] != 0x5A5A ||
+ mcp->mb[7] != 0x2525)
+ rval = QLA_FUNCTION_FAILED;
++ if (rval == QLA_FUNCTION_FAILED) {
++ struct device_reg_24xx __iomem *reg =
++ &ha->iobase->isp24;
++
++ qla2xxx_hw_event_log(ha, HW_EVENT_ISP_ERR, 0,
++ LSW(RD_REG_DWORD(®->hccr)),
++ LSW(RD_REG_DWORD(®->istatus)));
++ }
+ }
+
+ if (rval != QLA_SUCCESS) {
+@@ -640,7 +648,7 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr)
+ mcp->in_mb |= MBX_1;
+ }
+
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+@@ -674,8 +682,8 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr)
+ * Kernel context.
+ */
+ int
+-qla2x00_issue_iocb(scsi_qla_host_t *ha, void* buffer, dma_addr_t phys_addr,
+- size_t size)
++qla2x00_issue_iocb_timeout(scsi_qla_host_t *ha, void *buffer,
++ dma_addr_t phys_addr, size_t size, uint32_t tov)
+ {
+ int rval;
+ mbx_cmd_t mc;
+@@ -689,7 +697,7 @@ qla2x00_issue_iocb(scsi_qla_host_t *ha, void* buffer, dma_addr_t phys_addr,
+ mcp->mb[7] = LSW(MSD(phys_addr));
+ mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_2|MBX_0;
+- mcp->tov = 30;
++ mcp->tov = tov;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+@@ -710,6 +718,14 @@ qla2x00_issue_iocb(scsi_qla_host_t *ha, void* buffer, dma_addr_t phys_addr,
+ return rval;
+ }
+
++int
++qla2x00_issue_iocb(scsi_qla_host_t *ha, void *buffer, dma_addr_t phys_addr,
++ size_t size)
++{
++ return qla2x00_issue_iocb_timeout(ha, buffer, phys_addr, size,
++ MBX_TOV_SECONDS);
++}
++
+ /*
+ * qla2x00_abort_command
+ * Abort command aborts a specified IOCB.
+@@ -760,7 +776,7 @@ qla2x00_abort_command(scsi_qla_host_t *ha, srb_t *sp)
+ mcp->mb[6] = (uint16_t)sp->cmd->device->lun;
+ mcp->out_mb = MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+@@ -776,36 +792,20 @@ qla2x00_abort_command(scsi_qla_host_t *ha, srb_t *sp)
+ return rval;
+ }
+
+-#if USE_ABORT_TGT
+-/*
+- * qla2x00_abort_target
+- * Issue abort target mailbox command.
+- *
+- * Input:
+- * ha = adapter block pointer.
+- *
+- * Returns:
+- * qla2x00 local function return status code.
+- *
+- * Context:
+- * Kernel context.
+- */
+ int
+-qla2x00_abort_target(fc_port_t *fcport)
++qla2x00_abort_target(struct fc_port *fcport, unsigned int l)
+ {
+- int rval;
++ int rval, rval2;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+ scsi_qla_host_t *ha;
+
+- if (fcport == NULL)
+- return 0;
+-
+ DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no));
+
++ l = l;
+ ha = fcport->ha;
+ mcp->mb[0] = MBC_ABORT_TARGET;
+- mcp->out_mb = MBX_2|MBX_1|MBX_0;
++ mcp->out_mb = MBX_9|MBX_2|MBX_1|MBX_0;
+ if (HAS_EXTENDED_IDS(ha)) {
+ mcp->mb[1] = fcport->loop_id;
+ mcp->mb[10] = 0;
+@@ -814,27 +814,70 @@ qla2x00_abort_target(fc_port_t *fcport)
+ mcp->mb[1] = fcport->loop_id << 8;
+ }
+ mcp->mb[2] = ha->loop_reset_delay;
++ mcp->mb[9] = ha->vp_idx;
+
+ mcp->in_mb = MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
++ if (rval != QLA_SUCCESS) {
++ DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
++ ha->host_no, rval));
++ }
+
+- /* Issue marker command. */
+- ha->marker_needed = 1;
++ /* Issue marker IOCB. */
++ rval2 = qla2x00_marker(ha, fcport->loop_id, 0, MK_SYNC_ID);
++ if (rval2 != QLA_SUCCESS) {
++ DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB "
++ "(%x).\n", __func__, ha->host_no, rval2));
++ } else {
++ DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
++ }
++
++ return rval;
++}
++
++int
++qla2x00_lun_reset(struct fc_port *fcport, unsigned int l)
++{
++ int rval, rval2;
++ mbx_cmd_t mc;
++ mbx_cmd_t *mcp = &mc;
++ scsi_qla_host_t *ha;
++
++ DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no));
++
++ ha = fcport->ha;
++ mcp->mb[0] = MBC_LUN_RESET;
++ mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0;
++ if (HAS_EXTENDED_IDS(ha))
++ mcp->mb[1] = fcport->loop_id;
++ else
++ mcp->mb[1] = fcport->loop_id << 8;
++ mcp->mb[2] = l;
++ mcp->mb[3] = 0;
++ mcp->mb[9] = ha->vp_idx;
+
++ mcp->in_mb = MBX_0;
++ mcp->tov = MBX_TOV_SECONDS;
++ mcp->flags = 0;
++ rval = qla2x00_mailbox_command(ha, mcp);
+ if (rval != QLA_SUCCESS) {
+- DEBUG2_3_11(printk("qla2x00_abort_target(%ld): failed=%x.\n",
++ DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
+ ha->host_no, rval));
++ }
++
++ /* Issue marker IOCB. */
++ rval2 = qla2x00_marker(ha, fcport->loop_id, l, MK_SYNC_ID_LUN);
++ if (rval2 != QLA_SUCCESS) {
++ DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB "
++ "(%x).\n", __func__, ha->host_no, rval2));
+ } else {
+- /*EMPTY*/
+- DEBUG11(printk("qla2x00_abort_target(%ld): done.\n",
+- ha->host_no));
++ DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
+ }
+
+ return rval;
+ }
+-#endif
+
+ /*
+ * qla2x00_get_adapter_id
+@@ -871,7 +914,7 @@ qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa,
+ mcp->mb[9] = ha->vp_idx;
+ mcp->out_mb = MBX_9|MBX_0;
+ mcp->in_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+ if (mcp->mb[0] == MBS_COMMAND_ERROR)
+@@ -928,7 +971,7 @@ qla2x00_get_retry_cnt(scsi_qla_host_t *ha, uint8_t *retry_cnt, uint8_t *tov,
+ mcp->mb[0] = MBC_GET_RETRY_COUNT;
+ mcp->out_mb = MBX_0;
+ mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+@@ -995,7 +1038,7 @@ qla2x00_init_firmware(scsi_qla_host_t *ha, uint16_t size)
+ mcp->in_mb = MBX_5|MBX_4|MBX_0;
+ mcp->buf_size = size;
+ mcp->flags = MBX_DMA_OUT;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+ if (rval != QLA_SUCCESS) {
+@@ -1173,7 +1216,7 @@ gpd_error_out:
+ * Kernel context.
+ */
+ int
+-qla2x00_get_firmware_state(scsi_qla_host_t *ha, uint16_t *dptr)
++qla2x00_get_firmware_state(scsi_qla_host_t *ha, uint16_t *states)
+ {
+ int rval;
+ mbx_cmd_t mc;
+@@ -1184,13 +1227,15 @@ qla2x00_get_firmware_state(scsi_qla_host_t *ha, uint16_t *dptr)
+
+ mcp->mb[0] = MBC_GET_FIRMWARE_STATE;
+ mcp->out_mb = MBX_0;
+- mcp->in_mb = MBX_2|MBX_1|MBX_0;
+- mcp->tov = 30;
++ mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+- /* Return firmware state. */
+- *dptr = mcp->mb[1];
++ /* Return firmware states. */
++ states[0] = mcp->mb[1];
++ states[1] = mcp->mb[2];
++ states[2] = mcp->mb[3];
+
+ if (rval != QLA_SUCCESS) {
+ /*EMPTY*/
+@@ -1246,7 +1291,7 @@ qla2x00_get_port_name(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t *name,
+ }
+
+ mcp->in_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+@@ -1318,7 +1363,7 @@ qla2x00_lip_reset(scsi_qla_host_t *ha)
+ mcp->mb[3] = 0;
+ }
+ mcp->in_mb = MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+@@ -1743,7 +1788,7 @@ qla2x00_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
+ }
+
+ mcp->in_mb = MBX_1|MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+@@ -1791,7 +1836,7 @@ qla2x00_full_login_lip(scsi_qla_host_t *ha)
+ mcp->mb[3] = 0;
+ mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+@@ -1852,7 +1897,7 @@ qla2x00_get_id_list(scsi_qla_host_t *ha, void *id_list, dma_addr_t id_list_dma,
+ mcp->out_mb |= MBX_6|MBX_3|MBX_2|MBX_1;
+ }
+ mcp->in_mb = MBX_1|MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+@@ -1896,7 +1941,7 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *ha, uint16_t *cur_xchg_cnt,
+ mcp->mb[0] = MBC_GET_RESOURCE_COUNTS;
+ mcp->out_mb = MBX_0;
+ mcp->in_mb = MBX_11|MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+@@ -2036,7 +2081,7 @@ qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id,
+ mcp->mb[1] = loop_id << 8;
+ mcp->out_mb |= MBX_1;
+ }
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = IOCTL_CMD;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+@@ -2082,7 +2127,7 @@ qla24xx_get_isp_stats(scsi_qla_host_t *ha, struct link_statistics *stats,
+ mcp->mb[10] = 0;
+ mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
+ mcp->in_mb = MBX_2|MBX_1|MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = IOCTL_CMD;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+@@ -2180,17 +2225,15 @@ struct tsk_mgmt_cmd {
+ } p;
+ };
+
+-int
+-qla24xx_abort_target(fc_port_t *fcport)
++static int
++__qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
++ unsigned int l)
+ {
+- int rval;
++ int rval, rval2;
+ struct tsk_mgmt_cmd *tsk;
+ dma_addr_t tsk_dma;
+ scsi_qla_host_t *ha, *pha;
+
+- if (fcport == NULL)
+- return 0;
+-
+ DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no));
+
+ ha = fcport->ha;
+@@ -2207,47 +2250,61 @@ qla24xx_abort_target(fc_port_t *fcport)
+ tsk->p.tsk.entry_count = 1;
+ tsk->p.tsk.nport_handle = cpu_to_le16(fcport->loop_id);
+ tsk->p.tsk.timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
+- tsk->p.tsk.control_flags = __constant_cpu_to_le32(TCF_TARGET_RESET);
++ tsk->p.tsk.control_flags = cpu_to_le32(type);
+ tsk->p.tsk.port_id[0] = fcport->d_id.b.al_pa;
+ tsk->p.tsk.port_id[1] = fcport->d_id.b.area;
+ tsk->p.tsk.port_id[2] = fcport->d_id.b.domain;
+ tsk->p.tsk.vp_index = fcport->vp_idx;
++ if (type == TCF_LUN_RESET) {
++ int_to_scsilun(l, &tsk->p.tsk.lun);
++ host_to_fcp_swap((uint8_t *)&tsk->p.tsk.lun,
++ sizeof(tsk->p.tsk.lun));
++ }
+
+ rval = qla2x00_issue_iocb(ha, tsk, tsk_dma, 0);
+ if (rval != QLA_SUCCESS) {
+- DEBUG2_3_11(printk("%s(%ld): failed to issue Target Reset IOCB "
+- "(%x).\n", __func__, ha->host_no, rval));
+- goto atarget_done;
++ DEBUG2_3_11(printk("%s(%ld): failed to issue %s Reset IOCB "
++ "(%x).\n", __func__, ha->host_no, name, rval));
+ } else if (tsk->p.sts.entry_status != 0) {
+ DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
+ "-- error status (%x).\n", __func__, ha->host_no,
+ tsk->p.sts.entry_status));
+ rval = QLA_FUNCTION_FAILED;
+- goto atarget_done;
+ } else if (tsk->p.sts.comp_status !=
+ __constant_cpu_to_le16(CS_COMPLETE)) {
+ DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
+ "-- completion status (%x).\n", __func__,
+ ha->host_no, le16_to_cpu(tsk->p.sts.comp_status)));
+ rval = QLA_FUNCTION_FAILED;
+- goto atarget_done;
+ }
+
+ /* Issue marker IOCB. */
+- rval = qla2x00_marker(ha, fcport->loop_id, 0, MK_SYNC_ID);
+- if (rval != QLA_SUCCESS) {
++ rval2 = qla2x00_marker(ha, fcport->loop_id, l,
++ type == TCF_LUN_RESET ? MK_SYNC_ID_LUN: MK_SYNC_ID);
++ if (rval2 != QLA_SUCCESS) {
+ DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB "
+- "(%x).\n", __func__, ha->host_no, rval));
++ "(%x).\n", __func__, ha->host_no, rval2));
+ } else {
+ DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
+ }
+
+-atarget_done:
+ dma_pool_free(pha->s_dma_pool, tsk, tsk_dma);
+
+ return rval;
+ }
+
++int
++qla24xx_abort_target(struct fc_port *fcport, unsigned int l)
++{
++ return __qla24xx_issue_tmf("Target", TCF_TARGET_RESET, fcport, l);
++}
++
++int
++qla24xx_lun_reset(struct fc_port *fcport, unsigned int l)
++{
++ return __qla24xx_issue_tmf("Lun", TCF_LUN_RESET, fcport, l);
++}
++
+ #if 0
+
+ int
+@@ -2304,7 +2361,7 @@ qla2x00_set_serdes_params(scsi_qla_host_t *ha, uint16_t sw_em_1g,
+ mcp->mb[4] = sw_em_4g | BIT_15;
+ mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+@@ -2372,7 +2429,7 @@ qla2x00_enable_eft_trace(scsi_qla_host_t *ha, dma_addr_t eft_dma,
+ mcp->mb[7] = TC_AEN_DISABLE;
+ mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_1|MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+ if (rval != QLA_SUCCESS) {
+@@ -2401,7 +2458,7 @@ qla2x00_disable_eft_trace(scsi_qla_host_t *ha)
+ mcp->mb[1] = TC_EFT_DISABLE;
+ mcp->out_mb = MBX_1|MBX_0;
+ mcp->in_mb = MBX_1|MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+ if (rval != QLA_SUCCESS) {
+@@ -2441,7 +2498,7 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *ha, dma_addr_t fce_dma,
+ mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|
+ MBX_1|MBX_0;
+ mcp->in_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+ if (rval != QLA_SUCCESS) {
+@@ -2477,7 +2534,7 @@ qla2x00_disable_fce_trace(scsi_qla_host_t *ha, uint64_t *wr, uint64_t *rd)
+ mcp->out_mb = MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_9|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|
+ MBX_1|MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+ if (rval != QLA_SUCCESS) {
+@@ -2525,7 +2582,7 @@ qla2x00_read_sfp(scsi_qla_host_t *ha, dma_addr_t sfp_dma, uint16_t addr,
+ mcp->mb[10] = 0;
+ mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+@@ -2559,7 +2616,7 @@ qla2x00_set_idma_speed(scsi_qla_host_t *ha, uint16_t loop_id,
+ mcp->mb[4] = mcp->mb[5] = 0;
+ mcp->out_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_5|MBX_4|MBX_3|MBX_1|MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+@@ -2877,7 +2934,7 @@ qla2x00_dump_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t addr,
+ }
+
+ mcp->in_mb = MBX_0;
+- mcp->tov = 30;
++ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+@@ -2890,3 +2947,104 @@ qla2x00_dump_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t addr,
+
+ return rval;
+ }
++
++/* 84XX Support **************************************************************/
++
++struct cs84xx_mgmt_cmd {
++ union {
++ struct verify_chip_entry_84xx req;
++ struct verify_chip_rsp_84xx rsp;
++ } p;
++};
++
++int
++qla84xx_verify_chip(struct scsi_qla_host *ha, uint16_t *status)
++{
++ int rval, retry;
++ struct cs84xx_mgmt_cmd *mn;
++ dma_addr_t mn_dma;
++ uint16_t options;
++ unsigned long flags;
++
++ DEBUG16(printk("%s(%ld): entered.\n", __func__, ha->host_no));
++
++ mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
++ if (mn == NULL) {
++ DEBUG2_3(printk("%s(%ld): failed to allocate Verify ISP84XX "
++ "IOCB.\n", __func__, ha->host_no));
++ return QLA_MEMORY_ALLOC_FAILED;
++ }
++
++ /* Force Update? */
++ options = ha->cs84xx->fw_update ? VCO_FORCE_UPDATE : 0;
++ /* Diagnostic firmware? */
++ /* options |= MENLO_DIAG_FW; */
++ /* We update the firmware with only one data sequence. */
++ options |= VCO_END_OF_DATA;
++
++ retry = 0;
++ do {
++ memset(mn, 0, sizeof(*mn));
++ mn->p.req.entry_type = VERIFY_CHIP_IOCB_TYPE;
++ mn->p.req.entry_count = 1;
++ mn->p.req.options = cpu_to_le16(options);
++
++ DEBUG16(printk("%s(%ld): Dump of Verify Request.\n", __func__,
++ ha->host_no));
++ DEBUG16(qla2x00_dump_buffer((uint8_t *)mn,
++ sizeof(*mn)));
++
++ rval = qla2x00_issue_iocb_timeout(ha, mn, mn_dma, 0, 120);
++ if (rval != QLA_SUCCESS) {
++ DEBUG2_16(printk("%s(%ld): failed to issue Verify "
++ "IOCB (%x).\n", __func__, ha->host_no, rval));
++ goto verify_done;
++ }
++
++ DEBUG16(printk("%s(%ld): Dump of Verify Response.\n", __func__,
++ ha->host_no));
++ DEBUG16(qla2x00_dump_buffer((uint8_t *)mn,
++ sizeof(*mn)));
++
++ status[0] = le16_to_cpu(mn->p.rsp.comp_status);
++ status[1] = status[0] == CS_VCS_CHIP_FAILURE ?
++ le16_to_cpu(mn->p.rsp.failure_code) : 0;
++ DEBUG2_16(printk("%s(%ld): cs=%x fc=%x\n", __func__,
++ ha->host_no, status[0], status[1]));
++
++ if (status[0] != CS_COMPLETE) {
++ rval = QLA_FUNCTION_FAILED;
++ if (!(options & VCO_DONT_UPDATE_FW)) {
++ DEBUG2_16(printk("%s(%ld): Firmware update "
++ "failed. Retrying without update "
++ "firmware.\n", __func__, ha->host_no));
++ options |= VCO_DONT_UPDATE_FW;
++ options &= ~VCO_FORCE_UPDATE;
++ retry = 1;
++ }
++ } else {
++ DEBUG2_16(printk("%s(%ld): firmware updated to %x.\n",
++ __func__, ha->host_no,
++ le32_to_cpu(mn->p.rsp.fw_ver)));
++
++ /* NOTE: we only update OP firmware. */
++ spin_lock_irqsave(&ha->cs84xx->access_lock, flags);
++ ha->cs84xx->op_fw_version =
++ le32_to_cpu(mn->p.rsp.fw_ver);
++ spin_unlock_irqrestore(&ha->cs84xx->access_lock,
++ flags);
++ }
++ } while (retry);
++
++verify_done:
++ dma_pool_free(ha->s_dma_pool, mn, mn_dma);
++
++ if (rval != QLA_SUCCESS) {
++ DEBUG2_16(printk("%s(%ld): failed=%x.\n", __func__,
++ ha->host_no, rval));
++ } else {
++ DEBUG16(printk("%s(%ld): done.\n", __func__, ha->host_no));
++ }
++
++ return rval;
++}
+diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
+index cf784cd..f2b0497 100644
+--- a/drivers/scsi/qla2xxx/qla_mid.c
++++ b/drivers/scsi/qla2xxx/qla_mid.c
+@@ -1,20 +1,8 @@
+ /*
+- * QLOGIC LINUX SOFTWARE
+- *
+- * QLogic ISP2x00 device driver for Linux 2.6.x
+- * Copyright (C) 2003-2005 QLogic Corporation
+- * (www.qlogic.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, 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.
++ * QLogic Fibre Channel HBA Driver
++ * Copyright (c) 2003-2008 QLogic Corporation
+ *
++ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+ #include "qla_def.h"
+
+@@ -28,8 +16,6 @@
+ #include <scsi/scsicam.h>
+ #include <linux/delay.h>
+
+-void qla2x00_vp_stop_timer(scsi_qla_host_t *);
+-
+ void
+ qla2x00_vp_stop_timer(scsi_qla_host_t *vha)
+ {
+@@ -268,9 +254,17 @@ qla2x00_vp_abort_isp(scsi_qla_host_t *vha)
+ static int
+ qla2x00_do_dpc_vp(scsi_qla_host_t *vha)
+ {
++ scsi_qla_host_t *ha = vha->parent;
++
+ if (test_and_clear_bit(VP_IDX_ACQUIRED, &vha->vp_flags)) {
+ /* VP acquired. complete port configuration */
+- qla24xx_configure_vp(vha);
++ if (atomic_read(&ha->loop_state) == LOOP_READY) {
++ qla24xx_configure_vp(vha);
++ } else {
++ set_bit(VP_IDX_ACQUIRED, &vha->vp_flags);
++ set_bit(VP_DPC_NEEDED, &ha->dpc_flags);
++ }
++
+ return 0;
+ }
+
+diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
+index 3c1b433..8b33b16 100644
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -1,6 +1,6 @@
+ /*
+ * QLogic Fibre Channel HBA Driver
+- * Copyright (c) 2003-2005 QLogic Corporation
++ * Copyright (c) 2003-2008 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+@@ -26,9 +26,6 @@ char qla2x00_version_str[40];
+ */
+ static struct kmem_cache *srb_cachep;
+
+-/*
+- * Ioctl related information.
+- */
+ int num_hosts;
+ int ql2xlogintimeout = 20;
+ module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR);
+@@ -103,9 +100,9 @@ static int qla24xx_queuecommand(struct scsi_cmnd *cmd,
+ void (*fn)(struct scsi_cmnd *));
+ static int qla2xxx_eh_abort(struct scsi_cmnd *);
+ static int qla2xxx_eh_device_reset(struct scsi_cmnd *);
++static int qla2xxx_eh_target_reset(struct scsi_cmnd *);
+ static int qla2xxx_eh_bus_reset(struct scsi_cmnd *);
+ static int qla2xxx_eh_host_reset(struct scsi_cmnd *);
+-static int qla2x00_device_reset(scsi_qla_host_t *, fc_port_t *);
+
+ static int qla2x00_change_queue_depth(struct scsi_device *, int);
+ static int qla2x00_change_queue_type(struct scsi_device *, int);
+@@ -117,6 +114,7 @@ static struct scsi_host_template qla2x00_driver_template = {
+
+ .eh_abort_handler = qla2xxx_eh_abort,
+ .eh_device_reset_handler = qla2xxx_eh_device_reset,
++ .eh_target_reset_handler = qla2xxx_eh_target_reset,
+ .eh_bus_reset_handler = qla2xxx_eh_bus_reset,
+ .eh_host_reset_handler = qla2xxx_eh_host_reset,
+
+@@ -148,6 +146,7 @@ struct scsi_host_template qla24xx_driver_template = {
+
+ .eh_abort_handler = qla2xxx_eh_abort,
+ .eh_device_reset_handler = qla2xxx_eh_device_reset,
++ .eh_target_reset_handler = qla2xxx_eh_target_reset,
+ .eh_bus_reset_handler = qla2xxx_eh_bus_reset,
+ .eh_host_reset_handler = qla2xxx_eh_host_reset,
+
+@@ -253,9 +252,9 @@ qla24xx_pci_info_str(struct scsi_qla_host *ha, char *str)
+
+ strcpy(str, "PCIe (");
+ if (lspeed == 1)
+- strcat(str, "2.5Gb/s ");
++ strcat(str, "2.5GT/s ");
+ else if (lspeed == 2)
+- strcat(str, "5.0Gb/s ");
++ strcat(str, "5.0GT/s ");
+ else
+ strcat(str, "<unknown> ");
+ snprintf(lwstr, sizeof(lwstr), "x%d)", lwidth);
+@@ -340,6 +339,8 @@ qla24xx_fw_version_str(struct scsi_qla_host *ha, char *str)
+ strcat(str, "[T10 CRC] ");
+ if (ha->fw_attributes & BIT_5)
+ strcat(str, "[VI] ");
++ if (ha->fw_attributes & BIT_10)
++ strcat(str, "[84XX] ");
+ if (ha->fw_attributes & BIT_13)
+ strcat(str, "[Experimental]");
+ return str;
+@@ -570,8 +571,6 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *ha)
+ else
+ return_status = QLA_FUNCTION_FAILED;
+
+- DEBUG2(printk("%s return_status=%d\n",__func__,return_status));
+-
+ return (return_status);
+ }
+
+@@ -685,7 +684,6 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
+
+ DEBUG2(printk("%s(%ld): aborting sp %p from RISC. pid=%ld.\n",
+ __func__, ha->host_no, sp, serial));
+- DEBUG3(qla2x00_print_scsi_cmd(cmd));
+
+ spin_unlock_irqrestore(&pha->hardware_lock, flags);
+ if (ha->isp_ops->abort_command(ha, sp)) {
+@@ -719,190 +717,122 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
+ return ret;
+ }
+
+-/**************************************************************************
+-* qla2x00_eh_wait_for_pending_target_commands
+-*
+-* Description:
+-* Waits for all the commands to come back from the specified target.
+-*
+-* Input:
+-* ha - pointer to scsi_qla_host structure.
+-* t - target
+-* Returns:
+-* Either SUCCESS or FAILED.
+-*
+-* Note:
+-**************************************************************************/
++enum nexus_wait_type {
++ WAIT_HOST = 0,
++ WAIT_TARGET,
++ WAIT_LUN,
++};
++
+ static int
+-qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t)
++qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha, unsigned int t,
++ unsigned int l, enum nexus_wait_type type)
+ {
+- int cnt;
+- int status;
+- srb_t *sp;
+- struct scsi_cmnd *cmd;
++ int cnt, match, status;
++ srb_t *sp;
+ unsigned long flags;
+ scsi_qla_host_t *pha = to_qla_parent(ha);
+
+- status = 0;
+-
+- /*
+- * Waiting for all commands for the designated target in the active
+- * array
+- */
+- for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
+- spin_lock_irqsave(&pha->hardware_lock, flags);
++ status = QLA_SUCCESS;
++ spin_lock_irqsave(&pha->hardware_lock, flags);
++ for (cnt = 1; status == QLA_SUCCESS && cnt < MAX_OUTSTANDING_COMMANDS;
++ cnt++) {
+ sp = pha->outstanding_cmds[cnt];
+- if (sp) {
+- cmd = sp->cmd;
+- spin_unlock_irqrestore(&pha->hardware_lock, flags);
+- if (cmd->device->id == t &&
+- ha->vp_idx == sp->ha->vp_idx) {
+- if (!qla2x00_eh_wait_on_command(ha, cmd)) {
+- status = 1;
+- break;
+- }
+- }
+- } else {
+- spin_unlock_irqrestore(&pha->hardware_lock, flags);
++ if (!sp)
++ continue;
++ if (ha->vp_idx != sp->ha->vp_idx)
++ continue;
++ match = 0;
++ switch (type) {
++ case WAIT_HOST:
++ match = 1;
++ break;
++ case WAIT_TARGET:
++ match = sp->cmd->device->id == t;
++ break;
++ case WAIT_LUN:
++ match = (sp->cmd->device->id == t &&
++ sp->cmd->device->lun == l);
++ break;
+ }
++ if (!match)
++ continue;
++
++ spin_unlock_irqrestore(&pha->hardware_lock, flags);
++ status = qla2x00_eh_wait_on_command(ha, sp->cmd);
++ spin_lock_irqsave(&pha->hardware_lock, flags);
+ }
+- return (status);
++ spin_unlock_irqrestore(&pha->hardware_lock, flags);
++
++ return status;
+ }
+
++static char *reset_errors[] = {
++ "HBA not online",
++ "HBA not ready",
++ "Task management failed",
++ "Waiting for command completions",
++};
+
+-/**************************************************************************
+-* qla2xxx_eh_device_reset
+-*
+-* Description:
+-* The device reset function will reset the target and abort any
+-* executing commands.
+-*
+-* NOTE: The use of SP is undefined within this context. Do *NOT*
+-* attempt to use this value, even if you determine it is
+-* non-null.
+-*
+-* Input:
+-* cmd = Linux SCSI command packet of the command that cause the
+-* bus device reset.
+-*
+-* Returns:
+-* SUCCESS/FAILURE (defined as macro in scsi.h).
+-*
+-**************************************************************************/
+ static int
+-qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
++__qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
++ struct scsi_cmnd *cmd, int (*do_reset)(struct fc_port *, unsigned int))
+ {
+ scsi_qla_host_t *ha = shost_priv(cmd->device->host);
+ fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
+- int ret = FAILED;
+- unsigned int id, lun;
+- unsigned long serial;
++ int err;
+
+ qla2x00_block_error_handler(cmd);
+
+- id = cmd->device->id;
+- lun = cmd->device->lun;
+- serial = cmd->serial_number;
+-
+ if (!fcport)
+- return ret;
++ return FAILED;
+
+- qla_printk(KERN_INFO, ha,
+- "scsi(%ld:%d:%d): DEVICE RESET ISSUED.\n", ha->host_no, id, lun);
++ qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d): %s RESET ISSUED.\n",
++ ha->host_no, cmd->device->id, cmd->device->lun, name);
+
++ err = 0;
+ if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS)
+- goto eh_dev_reset_done;
+-
+- if (qla2x00_wait_for_loop_ready(ha) == QLA_SUCCESS) {
+- if (qla2x00_device_reset(ha, fcport) == 0)
+- ret = SUCCESS;
+-
+-#if defined(LOGOUT_AFTER_DEVICE_RESET)
+- if (ret == SUCCESS) {
+- if (fcport->flags & FC_FABRIC_DEVICE) {
+- ha->isp_ops->fabric_logout(ha, fcport->loop_id);
+- qla2x00_mark_device_lost(ha, fcport, 0, 0);
+- }
+- }
+-#endif
+- } else {
+- DEBUG2(printk(KERN_INFO
+- "%s failed: loop not ready\n",__func__));
+- }
+-
+- if (ret == FAILED) {
+- DEBUG3(printk("%s(%ld): device reset failed\n",
+- __func__, ha->host_no));
+- qla_printk(KERN_INFO, ha, "%s: device reset failed\n",
+- __func__);
++ goto eh_reset_failed;
++ err = 1;
++ if (qla2x00_wait_for_loop_ready(ha) != QLA_SUCCESS)
++ goto eh_reset_failed;
++ err = 2;
++ if (do_reset(fcport, cmd->device->lun) != QLA_SUCCESS)
++ goto eh_reset_failed;
++ err = 3;
++ if (qla2x00_eh_wait_for_pending_commands(ha, cmd->device->id,
++ cmd->device->lun, type) != QLA_SUCCESS)
++ goto eh_reset_failed;
++
++ qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d): %s RESET SUCCEEDED.\n",
++ ha->host_no, cmd->device->id, cmd->device->lun, name);
++
++ return SUCCESS;
++
++ eh_reset_failed:
++ qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d): %s RESET FAILED: %s.\n",
++ ha->host_no, cmd->device->id, cmd->device->lun, name,
++ reset_errors[err]);
++ return FAILED;
++}
+
+- goto eh_dev_reset_done;
+- }
++static int
++qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
++{
++ scsi_qla_host_t *ha = shost_priv(cmd->device->host);
+
+- /* Flush outstanding commands. */
+- if (qla2x00_eh_wait_for_pending_target_commands(ha, id))
+- ret = FAILED;
+- if (ret == FAILED) {
+- DEBUG3(printk("%s(%ld): failed while waiting for commands\n",
+- __func__, ha->host_no));
+- qla_printk(KERN_INFO, ha,
+- "%s: failed while waiting for commands\n", __func__);
+- } else
+- qla_printk(KERN_INFO, ha,
+- "scsi(%ld:%d:%d): DEVICE RESET SUCCEEDED.\n", ha->host_no,
+- id, lun);
+- eh_dev_reset_done:
+- return ret;
++ return __qla2xxx_eh_generic_reset("DEVICE", WAIT_LUN, cmd,
++ ha->isp_ops->lun_reset);
+ }
+
+-/**************************************************************************
+-* qla2x00_eh_wait_for_pending_commands
+-*
+-* Description:
+-* Waits for all the commands to come back from the specified host.
+-*
+-* Input:
+-* ha - pointer to scsi_qla_host structure.
+-*
+-* Returns:
+-* 1 : SUCCESS
+-* 0 : FAILED
+-*
+-* Note:
+-**************************************************************************/
+ static int
+-qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha)
++qla2xxx_eh_target_reset(struct scsi_cmnd *cmd)
+ {
+- int cnt;
+- int status;
+- srb_t *sp;
+- struct scsi_cmnd *cmd;
+- unsigned long flags;
+-
+- status = 1;
++ scsi_qla_host_t *ha = shost_priv(cmd->device->host);
+
+- /*
+- * Waiting for all commands for the designated target in the active
+- * array
+- */
+- for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
+- spin_lock_irqsave(&ha->hardware_lock, flags);
+- sp = ha->outstanding_cmds[cnt];
+- if (sp) {
+- cmd = sp->cmd;
+- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+- status = qla2x00_eh_wait_on_command(ha, cmd);
+- if (status == 0)
+- break;
+- }
+- else {
+- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+- }
+- }
+- return (status);
++ return __qla2xxx_eh_generic_reset("TARGET", WAIT_TARGET, cmd,
++ ha->isp_ops->target_reset);
+ }
+
+-
+ /**************************************************************************
+ * qla2xxx_eh_bus_reset
+ *
+@@ -953,7 +883,8 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
+ goto eh_bus_reset_done;
+
+ /* Flush outstanding commands. */
+- if (!qla2x00_eh_wait_for_pending_commands(pha))
++ if (qla2x00_eh_wait_for_pending_commands(pha, 0, 0, WAIT_HOST) !=
++ QLA_SUCCESS)
+ ret = FAILED;
+
+ eh_bus_reset_done:
+@@ -1024,7 +955,8 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
+ clear_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags);
+
+ /* Waiting for our command in done_queue to be returned to OS.*/
+- if (qla2x00_eh_wait_for_pending_commands(pha))
++ if (qla2x00_eh_wait_for_pending_commands(pha, 0, 0, WAIT_HOST) ==
++ QLA_SUCCESS)
+ ret = SUCCESS;
+
+ if (ha->parent)
+@@ -1080,7 +1012,7 @@ qla2x00_loop_reset(scsi_qla_host_t *ha)
+ if (fcport->port_type != FCT_TARGET)
+ continue;
+
+- ret = qla2x00_device_reset(ha, fcport);
++ ret = ha->isp_ops->target_reset(fcport, 0);
+ if (ret != QLA_SUCCESS) {
+ DEBUG2_3(printk("%s(%ld): bus_reset failed: "
+ "target_reset=%d d_id=%x.\n", __func__,
+@@ -1095,26 +1027,6 @@ qla2x00_loop_reset(scsi_qla_host_t *ha)
+ return QLA_SUCCESS;
+ }
+
+-/*
+- * qla2x00_device_reset
+- * Issue bus device reset message to the target.
+- *
+- * Input:
+- * ha = adapter block pointer.
+- * t = SCSI ID.
+- * TARGET_QUEUE_LOCK must be released.
+- * ADAPTER_STATE_LOCK must be released.
+- *
+- * Context:
+- * Kernel context.
+- */
+-static int
+-qla2x00_device_reset(scsi_qla_host_t *ha, fc_port_t *reset_fcport)
+-{
+- /* Abort Target command will clear Reservation */
+- return ha->isp_ops->abort_target(reset_fcport);
+-}
+-
+ void
+ qla2x00_abort_all_cmds(scsi_qla_host_t *ha, int res)
+ {
+@@ -1292,7 +1204,8 @@ static struct isp_operations qla2100_isp_ops = {
+ .enable_intrs = qla2x00_enable_intrs,
+ .disable_intrs = qla2x00_disable_intrs,
+ .abort_command = qla2x00_abort_command,
+- .abort_target = qla2x00_abort_target,
++ .target_reset = qla2x00_abort_target,
++ .lun_reset = qla2x00_lun_reset,
+ .fabric_login = qla2x00_login_fabric,
+ .fabric_logout = qla2x00_fabric_logout,
+ .calc_req_entries = qla2x00_calc_iocbs_32,
+@@ -1325,7 +1238,8 @@ static struct isp_operations qla2300_isp_ops = {
+ .enable_intrs = qla2x00_enable_intrs,
+ .disable_intrs = qla2x00_disable_intrs,
+ .abort_command = qla2x00_abort_command,
+- .abort_target = qla2x00_abort_target,
++ .target_reset = qla2x00_abort_target,
++ .lun_reset = qla2x00_lun_reset,
+ .fabric_login = qla2x00_login_fabric,
+ .fabric_logout = qla2x00_fabric_logout,
+ .calc_req_entries = qla2x00_calc_iocbs_32,
+@@ -1358,7 +1272,8 @@ static struct isp_operations qla24xx_isp_ops = {
+ .enable_intrs = qla24xx_enable_intrs,
+ .disable_intrs = qla24xx_disable_intrs,
+ .abort_command = qla24xx_abort_command,
+- .abort_target = qla24xx_abort_target,
++ .target_reset = qla24xx_abort_target,
++ .lun_reset = qla24xx_lun_reset,
+ .fabric_login = qla24xx_login_fabric,
+ .fabric_logout = qla24xx_fabric_logout,
+ .calc_req_entries = NULL,
+@@ -1391,7 +1306,8 @@ static struct isp_operations qla25xx_isp_ops = {
+ .enable_intrs = qla24xx_enable_intrs,
+ .disable_intrs = qla24xx_disable_intrs,
+ .abort_command = qla24xx_abort_command,
+- .abort_target = qla24xx_abort_target,
++ .target_reset = qla24xx_abort_target,
++ .lun_reset = qla24xx_lun_reset,
+ .fabric_login = qla24xx_login_fabric,
+ .fabric_logout = qla24xx_fabric_logout,
+ .calc_req_entries = NULL,
+@@ -1464,6 +1380,13 @@ qla2x00_set_isp_flags(scsi_qla_host_t *ha)
+ ha->device_type |= DT_IIDMA;
+ ha->fw_srisc_address = RISC_START_ADDRESS_2400;
+ break;
++ case PCI_DEVICE_ID_QLOGIC_ISP8432:
++ ha->device_type |= DT_ISP8432;
++ ha->device_type |= DT_ZIO_SUPPORTED;
++ ha->device_type |= DT_FWI2;
++ ha->device_type |= DT_IIDMA;
++ ha->fw_srisc_address = RISC_START_ADDRESS_2400;
++ break;
+ case PCI_DEVICE_ID_QLOGIC_ISP5422:
+ ha->device_type |= DT_ISP5422;
+ ha->device_type |= DT_FWI2;
+@@ -1587,6 +1510,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ sht = &qla2x00_driver_template;
+ if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 ||
+ pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 ||
++ pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8432 ||
+ pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 ||
+ pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432 ||
+ pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532) {
+@@ -1677,7 +1601,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ if (IS_QLA2322(ha) || IS_QLA6322(ha))
+ ha->optrom_size = OPTROM_SIZE_2322;
+ ha->isp_ops = &qla2300_isp_ops;
+- } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
++ } else if (IS_QLA24XX_TYPE(ha)) {
+ host->max_id = MAX_TARGETS_2200;
+ ha->mbx_count = MAILBOX_REGISTER_COUNT;
+ ha->request_q_length = REQUEST_ENTRY_CNT_24XX;
+@@ -1699,6 +1623,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ ha->gid_list_info_size = 8;
+ ha->optrom_size = OPTROM_SIZE_25XX;
+ ha->isp_ops = &qla25xx_isp_ops;
++ ha->hw_event_start = PCI_FUNC(pdev->devfn) ?
++ FA_HW_EVENT1_ADDR: FA_HW_EVENT0_ADDR;
+ }
+ host->can_queue = ha->request_q_length + 128;
+
+@@ -1713,6 +1639,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ INIT_LIST_HEAD(&ha->list);
+ INIT_LIST_HEAD(&ha->fcports);
+ INIT_LIST_HEAD(&ha->vp_list);
++ INIT_LIST_HEAD(&ha->work_list);
+
+ set_bit(0, (unsigned long *) ha->vp_idx_map);
+
+@@ -1819,6 +1746,8 @@ qla2x00_remove_one(struct pci_dev *pdev)
+
+ qla2x00_dfs_remove(ha);
+
++ qla84xx_put_chip(ha);
++
+ qla2x00_free_sysfs_attr(ha);
+
+ fc_remove_host(ha->host);
+@@ -2206,6 +2135,97 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
+ kfree(ha->nvram);
+ }
+
++struct qla_work_evt *
++qla2x00_alloc_work(struct scsi_qla_host *ha, enum qla_work_type type,
++ int locked)
++{
++ struct qla_work_evt *e;
++
++ e = kzalloc(sizeof(struct qla_work_evt), locked ? GFP_ATOMIC:
++ GFP_KERNEL);
++ if (!e)
++ return NULL;
++
++ INIT_LIST_HEAD(&e->list);
++ e->type = type;
++ e->flags = QLA_EVT_FLAG_FREE;
++ return e;
++}
++
++int
++qla2x00_post_work(struct scsi_qla_host *ha, struct qla_work_evt *e, int locked)
++{
++ unsigned long flags;
++
++ if (!locked)
++ spin_lock_irqsave(&ha->hardware_lock, flags);
++ list_add_tail(&e->list, &ha->work_list);
++ qla2xxx_wake_dpc(ha);
++ if (!locked)
++ spin_unlock_irqrestore(&ha->hardware_lock, flags);
++ return QLA_SUCCESS;
++}
++
++int
++qla2x00_post_aen_work(struct scsi_qla_host *ha, enum fc_host_event_code code,
++ u32 data)
++{
++ struct qla_work_evt *e;
++
++ e = qla2x00_alloc_work(ha, QLA_EVT_AEN, 1);
++ if (!e)
++ return QLA_FUNCTION_FAILED;
++
++ e->u.aen.code = code;
++ e->u.aen.data = data;
++ return qla2x00_post_work(ha, e, 1);
++}
++
++int
++qla2x00_post_hwe_work(struct scsi_qla_host *ha, uint16_t code, uint16_t d1,
++ uint16_t d2, uint16_t d3)
++{
++ struct qla_work_evt *e;
++
++ e = qla2x00_alloc_work(ha, QLA_EVT_HWE_LOG, 1);
++ if (!e)
++ return QLA_FUNCTION_FAILED;
++
++ e->u.hwe.code = code;
++ e->u.hwe.d1 = d1;
++ e->u.hwe.d2 = d2;
++ e->u.hwe.d3 = d3;
++ return qla2x00_post_work(ha, e, 1);
++}
++
++static void
++qla2x00_do_work(struct scsi_qla_host *ha)
++{
++ struct qla_work_evt *e;
++
++ spin_lock_irq(&ha->hardware_lock);
++ while (!list_empty(&ha->work_list)) {
++ e = list_entry(ha->work_list.next, struct qla_work_evt, list);
++ list_del_init(&e->list);
++ spin_unlock_irq(&ha->hardware_lock);
++
++ switch (e->type) {
++ case QLA_EVT_AEN:
++ fc_host_post_event(ha->host, fc_get_event_number(),
++ e->u.aen.code, e->u.aen.data);
++ break;
++ case QLA_EVT_HWE_LOG:
++ qla2xxx_hw_event_log(ha, e->u.hwe.code, e->u.hwe.d1,
++ e->u.hwe.d2, e->u.hwe.d3);
++ break;
++ }
++ if (e->flags & QLA_EVT_FLAG_FREE)
++ kfree(e);
++ spin_lock_irq(&ha->hardware_lock);
++ }
++ spin_unlock_irq(&ha->hardware_lock);
++}
++
+ /**************************************************************************
+ * qla2x00_do_dpc
+ * This kernel thread is a task that is schedule by the interrupt handler
+@@ -2257,6 +2277,8 @@ qla2x00_do_dpc(void *data)
+ continue;
+ }
+
++ qla2x00_do_work(ha);
++
+ if (test_and_clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) {
+
+ DEBUG(printk("scsi(%ld): dpc: sched "
+@@ -2291,12 +2313,6 @@ qla2x00_do_dpc(void *data)
+ if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags))
+ qla2x00_update_fcports(ha);
+
+- if (test_and_clear_bit(LOOP_RESET_NEEDED, &ha->dpc_flags)) {
+- DEBUG(printk("scsi(%ld): dpc: sched loop_reset()\n",
+- ha->host_no));
+- qla2x00_loop_reset(ha);
+- }
+-
+ if (test_and_clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) &&
+ (!(test_and_set_bit(RESET_ACTIVE, &ha->dpc_flags)))) {
+
+@@ -2367,19 +2383,6 @@ qla2x00_do_dpc(void *data)
+ ha->host_no));
+ }
+
+- if ((test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags)) &&
+- atomic_read(&ha->loop_state) != LOOP_DOWN) {
+-
+- clear_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags);
+- DEBUG(printk("scsi(%ld): qla2x00_login_retry()\n",
+- ha->host_no));
+-
+- set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
+-
+- DEBUG(printk("scsi(%ld): qla2x00_login_retry - end\n",
+- ha->host_no));
+- }
+-
+ if (test_and_clear_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) {
+
+ DEBUG(printk("scsi(%ld): qla2x00_loop_resync()\n",
+@@ -2397,18 +2400,6 @@ qla2x00_do_dpc(void *data)
+ ha->host_no));
+ }
+
+- if (test_and_clear_bit(FCPORT_RESCAN_NEEDED, &ha->dpc_flags)) {
+-
+- DEBUG(printk("scsi(%ld): Rescan flagged fcports...\n",
+- ha->host_no));
+-
+- qla2x00_rescan_fcports(ha);
+-
+- DEBUG(printk("scsi(%ld): Rescan flagged fcports..."
+- "end.\n",
+- ha->host_no));
+- }
+-
+ if (!ha->interrupts_on)
+ ha->isp_ops->enable_intrs(ha);
+
+@@ -2586,7 +2577,8 @@ qla2x00_timer(scsi_qla_host_t *ha)
+ set_bit(RESTART_QUEUES_NEEDED, &ha->dpc_flags);
+ start_dpc++;
+
+- if (!(ha->device_flags & DFLG_NO_CABLE)) {
++ if (!(ha->device_flags & DFLG_NO_CABLE) &&
++ !ha->parent) {
+ DEBUG(printk("scsi(%ld): Loop down - "
+ "aborting ISP.\n",
+ ha->host_no));
+@@ -2610,10 +2602,8 @@ qla2x00_timer(scsi_qla_host_t *ha)
+ /* Schedule the DPC routine if needed */
+ if ((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) ||
+ test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) ||
+- test_bit(LOOP_RESET_NEEDED, &ha->dpc_flags) ||
+ test_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags) ||
+ start_dpc ||
+- test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) ||
+ test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) ||
+ test_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags) ||
+ test_bit(VP_DPC_NEEDED, &ha->dpc_flags) ||
+@@ -2665,7 +2655,7 @@ qla2x00_request_firmware(scsi_qla_host_t *ha)
+ blob = &qla_fw_blobs[FW_ISP2300];
+ } else if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
+ blob = &qla_fw_blobs[FW_ISP2322];
+- } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
++ } else if (IS_QLA24XX_TYPE(ha)) {
+ blob = &qla_fw_blobs[FW_ISP24XX];
+ } else if (IS_QLA25XX(ha)) {
+ blob = &qla_fw_blobs[FW_ISP25XX];
+@@ -2815,6 +2805,7 @@ static struct pci_device_id qla2xxx_pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6322) },
+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2422) },
+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432) },
++ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8432) },
+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5422) },
+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432) },
+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2532) },
+diff --git a/drivers/scsi/qla2xxx/qla_settings.h b/drivers/scsi/qla2xxx/qla_settings.h
+index 249e4d9..2801c26 100644
+--- a/drivers/scsi/qla2xxx/qla_settings.h
++++ b/drivers/scsi/qla2xxx/qla_settings.h
+@@ -1,26 +1,12 @@
+ /*
+ * QLogic Fibre Channel HBA Driver
+- * Copyright (c) 2003-2005 QLogic Corporation
++ * Copyright (c) 2003-2008 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+-/*
+- * Compile time Options:
+- * 0 - Disable and 1 - Enable
+- */
+-#define DEBUG_QLA2100 0 /* For Debug of qla2x00 */
+-
+-#define USE_ABORT_TGT 1 /* Use Abort Target mbx cmd */
+-
+ #define MAX_RETRIES_OF_ISP_ABORT 5
+
+ /* Max time to wait for the loop to be in LOOP_READY state */
+ #define MAX_LOOP_TIMEOUT (60 * 5)
+
+-/*
+- * Some vendor subsystems do not recover properly after a device reset. Define
+- * the following to force a logout after a successful device reset.
+- */
+-#undef LOGOUT_AFTER_DEVICE_RESET
+-
+ #include "qla_version.h"
+diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
+index 26822c8..1728ab3 100644
+--- a/drivers/scsi/qla2xxx/qla_sup.c
++++ b/drivers/scsi/qla2xxx/qla_sup.c
+@@ -1,6 +1,6 @@
+ /*
+ * QLogic Fibre Channel HBA Driver
+- * Copyright (c) 2003-2005 QLogic Corporation
++ * Copyright (c) 2003-2008 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+@@ -543,79 +543,174 @@ qla24xx_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id,
+ }
+ }
+
+-static int
+-qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
+- uint32_t dwords)
++void
++qla2xxx_get_flash_info(scsi_qla_host_t *ha)
+ {
+- int ret;
+- uint32_t liter, miter;
+- uint32_t sec_mask, rest_addr, conf_addr;
+- uint32_t fdata, findex, cnt;
++#define FLASH_BLK_SIZE_32K 0x8000
++#define FLASH_BLK_SIZE_64K 0x10000
++ uint16_t cnt, chksum;
++ uint16_t *wptr;
++ struct qla_fdt_layout *fdt;
+ uint8_t man_id, flash_id;
+- struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+- dma_addr_t optrom_dma;
+- void *optrom = NULL;
+- uint32_t *s, *d;
+
+- ret = QLA_SUCCESS;
++ if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha))
++ return;
+
+- /* Prepare burst-capable write on supported ISPs. */
+- if (IS_QLA25XX(ha) && !(faddr & 0xfff) &&
+- dwords > OPTROM_BURST_DWORDS) {
+- optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
+- &optrom_dma, GFP_KERNEL);
+- if (!optrom) {
+- qla_printk(KERN_DEBUG, ha,
+- "Unable to allocate memory for optrom burst write "
+- "(%x KB).\n", OPTROM_BURST_SIZE / 1024);
+- }
++ wptr = (uint16_t *)ha->request_ring;
++ fdt = (struct qla_fdt_layout *)ha->request_ring;
++ ha->isp_ops->read_optrom(ha, (uint8_t *)ha->request_ring,
++ FA_FLASH_DESCR_ADDR << 2, OPTROM_BURST_SIZE);
++ if (*wptr == __constant_cpu_to_le16(0xffff))
++ goto no_flash_data;
++ if (fdt->sig[0] != 'Q' || fdt->sig[1] != 'L' || fdt->sig[2] != 'I' ||
++ fdt->sig[3] != 'D')
++ goto no_flash_data;
++
++ for (cnt = 0, chksum = 0; cnt < sizeof(struct qla_fdt_layout) >> 1;
++ cnt++)
++ chksum += le16_to_cpu(*wptr++);
++ if (chksum) {
++ DEBUG2(qla_printk(KERN_INFO, ha, "Inconsistent FDT detected: "
++ "checksum=0x%x id=%c version=0x%x.\n", chksum, fdt->sig[0],
++ le16_to_cpu(fdt->version)));
++ DEBUG9(qla2x00_dump_buffer((uint8_t *)fdt, sizeof(*fdt)));
++ goto no_flash_data;
+ }
+
+- qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id);
+- DEBUG9(printk("%s(%ld): Flash man_id=%d flash_id=%d\n", __func__,
+- ha->host_no, man_id, flash_id));
++ ha->fdt_odd_index = le16_to_cpu(fdt->man_id) == 0x1f;
++ ha->fdt_wrt_disable = fdt->wrt_disable_bits;
++ ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0300 | fdt->erase_cmd);
++ ha->fdt_block_size = le32_to_cpu(fdt->block_size);
++ if (fdt->unprotect_sec_cmd) {
++ ha->fdt_unprotect_sec_cmd = flash_conf_to_access_addr(0x0300 |
++ fdt->unprotect_sec_cmd);
++ ha->fdt_protect_sec_cmd = fdt->protect_sec_cmd ?
++ flash_conf_to_access_addr(0x0300 | fdt->protect_sec_cmd):
++ flash_conf_to_access_addr(0x0336);
++ }
+
+- conf_addr = flash_conf_to_access_addr(0x03d8);
++ DEBUG2(qla_printk(KERN_DEBUG, ha, "Flash[FDT]: (0x%x/0x%x) erase=0x%x "
++ "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n",
++ le16_to_cpu(fdt->man_id), le16_to_cpu(fdt->id), ha->fdt_erase_cmd,
++ ha->fdt_protect_sec_cmd, ha->fdt_unprotect_sec_cmd,
++ ha->fdt_odd_index, ha->fdt_wrt_disable, ha->fdt_block_size));
++ return;
++
++no_flash_data:
++ qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id);
++ ha->fdt_wrt_disable = 0x9c;
++ ha->fdt_erase_cmd = flash_conf_to_access_addr(0x03d8);
+ switch (man_id) {
+ case 0xbf: /* STT flash. */
+- if (flash_id == 0x8e) {
+- rest_addr = 0x3fff;
+- sec_mask = 0x7c000;
+- } else {
+- rest_addr = 0x1fff;
+- sec_mask = 0x7e000;
+- }
++ if (flash_id == 0x8e)
++ ha->fdt_block_size = FLASH_BLK_SIZE_64K;
++ else
++ ha->fdt_block_size = FLASH_BLK_SIZE_32K;
++
+ if (flash_id == 0x80)
+- conf_addr = flash_conf_to_access_addr(0x0352);
++ ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0352);
+ break;
+ case 0x13: /* ST M25P80. */
+- rest_addr = 0x3fff;
+- sec_mask = 0x7c000;
++ ha->fdt_block_size = FLASH_BLK_SIZE_64K;
+ break;
+- case 0x1f: // Atmel 26DF081A
+- rest_addr = 0x3fff;
+- sec_mask = 0x7c000;
+- conf_addr = flash_conf_to_access_addr(0x0320);
++ case 0x1f: /* Atmel 26DF081A. */
++ ha->fdt_odd_index = 1;
++ ha->fdt_block_size = FLASH_BLK_SIZE_64K;
++ ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0320);
++ ha->fdt_unprotect_sec_cmd = flash_conf_to_access_addr(0x0339);
++ ha->fdt_protect_sec_cmd = flash_conf_to_access_addr(0x0336);
+ break;
+ default:
+ /* Default to 64 kb sector size. */
+- rest_addr = 0x3fff;
+- sec_mask = 0x7c000;
++ ha->fdt_block_size = FLASH_BLK_SIZE_64K;
+ break;
+ }
+
++ DEBUG2(qla_printk(KERN_DEBUG, ha, "Flash[MID]: (0x%x/0x%x) erase=0x%x "
++ "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n", man_id, flash_id,
++ ha->fdt_erase_cmd, ha->fdt_protect_sec_cmd,
++ ha->fdt_unprotect_sec_cmd, ha->fdt_odd_index, ha->fdt_wrt_disable,
++ ha->fdt_block_size));
++}
++
++static void
++qla24xx_unprotect_flash(scsi_qla_host_t *ha)
++{
++ struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
++
+ /* Enable flash write. */
+ WRT_REG_DWORD(®->ctrl_status,
+ RD_REG_DWORD(®->ctrl_status) | CSRX_FLASH_ENABLE);
+ RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */
+
++ if (!ha->fdt_wrt_disable)
++ return;
++
+ /* Disable flash write-protection. */
+ qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0);
+ /* Some flash parts need an additional zero-write to clear bits.*/
+ qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0);
++}
++
++static void
++qla24xx_protect_flash(scsi_qla_host_t *ha)
++{
++ uint32_t cnt;
++ struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
++
++ if (!ha->fdt_wrt_disable)
++ goto skip_wrt_protect;
++
++ /* Enable flash write-protection and wait for completion. */
++ qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101),
++ ha->fdt_wrt_disable);
++ for (cnt = 300; cnt &&
++ qla24xx_read_flash_dword(ha,
++ flash_conf_to_access_addr(0x005)) & BIT_0;
++ cnt--) {
++ udelay(10);
++ }
++
++skip_wrt_protect:
++ /* Disable flash write. */
++ WRT_REG_DWORD(®->ctrl_status,
++ RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE);
++ RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */
++}
++
++static int
++qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
++ uint32_t dwords)
++{
++ int ret;
++ uint32_t liter, miter;
++ uint32_t sec_mask, rest_addr;
++ uint32_t fdata, findex;
++ dma_addr_t optrom_dma;
++ void *optrom = NULL;
++ uint32_t *s, *d;
++
++ ret = QLA_SUCCESS;
++
++ /* Prepare burst-capable write on supported ISPs. */
++ if (IS_QLA25XX(ha) && !(faddr & 0xfff) &&
++ dwords > OPTROM_BURST_DWORDS) {
++ optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
++ &optrom_dma, GFP_KERNEL);
++ if (!optrom) {
++ qla_printk(KERN_DEBUG, ha,
++ "Unable to allocate memory for optrom burst write "
++ "(%x KB).\n", OPTROM_BURST_SIZE / 1024);
++ }
++ }
++
++ rest_addr = (ha->fdt_block_size >> 2) - 1;
++ sec_mask = 0x80000 - (ha->fdt_block_size >> 2);
++
++ qla24xx_unprotect_flash(ha);
+
+ for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) {
+- if (man_id == 0x1f) {
++ if (ha->fdt_odd_index) {
+ findex = faddr << 2;
+ fdata = findex & sec_mask;
+ } else {
+@@ -625,13 +720,13 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
+
+ /* Are we at the beginning of a sector? */
+ if ((findex & rest_addr) == 0) {
+- /* Do sector unprotect at 4K boundry for Atmel part. */
+- if (man_id == 0x1f)
++ /* Do sector unprotect. */
++ if (ha->fdt_unprotect_sec_cmd)
+ qla24xx_write_flash_dword(ha,
+- flash_conf_to_access_addr(0x0339),
++ ha->fdt_unprotect_sec_cmd,
+ (fdata & 0xff00) | ((fdata << 16) &
+ 0xff0000) | ((fdata >> 16) & 0xff));
+- ret = qla24xx_write_flash_dword(ha, conf_addr,
++ ret = qla24xx_write_flash_dword(ha, ha->fdt_erase_cmd,
+ (fdata & 0xff00) |((fdata << 16) &
+ 0xff0000) | ((fdata >> 16) & 0xff));
+ if (ret != QLA_SUCCESS) {
+@@ -681,28 +776,16 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
+ break;
+ }
+
+- /* Do sector protect at 4K boundry for Atmel part. */
+- if (man_id == 0x1f &&
++ /* Do sector protect. */
++ if (ha->fdt_unprotect_sec_cmd &&
+ ((faddr & rest_addr) == rest_addr))
+ qla24xx_write_flash_dword(ha,
+- flash_conf_to_access_addr(0x0336),
++ ha->fdt_protect_sec_cmd,
+ (fdata & 0xff00) | ((fdata << 16) &
+ 0xff0000) | ((fdata >> 16) & 0xff));
+ }
+
+- /* Enable flash write-protection and wait for completion. */
+- qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0x9c);
+- for (cnt = 300; cnt &&
+- qla24xx_read_flash_dword(ha,
+- flash_conf_to_access_addr(0x005)) & BIT_0;
+- cnt--) {
+- udelay(10);
+- }
+-
+- /* Disable flash write. */
+- WRT_REG_DWORD(®->ctrl_status,
+- RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE);
+- RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */
++ qla24xx_protect_flash(ha);
+
+ if (optrom)
+ dma_free_coherent(&ha->pdev->dev,
+@@ -2221,3 +2304,107 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf)
+
+ return ret;
+ }
++
++static int
++qla2xxx_hw_event_store(scsi_qla_host_t *ha, uint32_t *fdata)
++{
++ uint32_t d[2], faddr;
++
++ /* Locate first empty entry. */
++ for (;;) {
++ if (ha->hw_event_ptr >=
++ ha->hw_event_start + FA_HW_EVENT_SIZE) {
++ DEBUG2(qla_printk(KERN_WARNING, ha,
++ "HW event -- Log Full!\n"));
++ return QLA_MEMORY_ALLOC_FAILED;
++ }
++
++ qla24xx_read_flash_data(ha, d, ha->hw_event_ptr, 2);
++ faddr = flash_data_to_access_addr(ha->hw_event_ptr);
++ ha->hw_event_ptr += FA_HW_EVENT_ENTRY_SIZE;
++ if (d[0] == __constant_cpu_to_le32(0xffffffff) &&
++ d[1] == __constant_cpu_to_le32(0xffffffff)) {
++ qla24xx_unprotect_flash(ha);
++
++ qla24xx_write_flash_dword(ha, faddr++,
++ cpu_to_le32(jiffies));
++ qla24xx_write_flash_dword(ha, faddr++, 0);
++ qla24xx_write_flash_dword(ha, faddr++, *fdata++);
++ qla24xx_write_flash_dword(ha, faddr++, *fdata);
++
++ qla24xx_protect_flash(ha);
++ break;
++ }
++ }
++ return QLA_SUCCESS;
++}
++
++int
++qla2xxx_hw_event_log(scsi_qla_host_t *ha, uint16_t code, uint16_t d1,
++ uint16_t d2, uint16_t d3)
++{
++#define QMARK(a, b, c, d) \
++ cpu_to_le32(LSB(a) << 24 | LSB(b) << 16 | LSB(c) << 8 | LSB(d))
++
++ int rval;
++ uint32_t marker[2], fdata[4];
++
++ if (ha->hw_event_start == 0)
++ return QLA_FUNCTION_FAILED;
++
++ DEBUG2(qla_printk(KERN_WARNING, ha,
++ "HW event -- code=%x, d1=%x, d2=%x, d3=%x.\n", code, d1, d2, d3));
++
++ /* If marker not already found, locate or write. */
++ if (!ha->flags.hw_event_marker_found) {
++ /* Create marker. */
++ marker[0] = QMARK('L', ha->fw_major_version,
++ ha->fw_minor_version, ha->fw_subminor_version);
++ marker[1] = QMARK(QLA_DRIVER_MAJOR_VER, QLA_DRIVER_MINOR_VER,
++ QLA_DRIVER_PATCH_VER, QLA_DRIVER_BETA_VER);
++
++ /* Locate marker. */
++ ha->hw_event_ptr = ha->hw_event_start;
++ for (;;) {
++ qla24xx_read_flash_data(ha, fdata, ha->hw_event_ptr,
++ 4);
++ if (fdata[0] == __constant_cpu_to_le32(0xffffffff) &&
++ fdata[1] == __constant_cpu_to_le32(0xffffffff))
++ break;
++ ha->hw_event_ptr += FA_HW_EVENT_ENTRY_SIZE;
++ if (ha->hw_event_ptr >=
++ ha->hw_event_start + FA_HW_EVENT_SIZE) {
++ DEBUG2(qla_printk(KERN_WARNING, ha,
++ "HW event -- Log Full!\n"));
++ return QLA_MEMORY_ALLOC_FAILED;
++ }
++ if (fdata[2] == marker[0] && fdata[3] == marker[1]) {
++ ha->flags.hw_event_marker_found = 1;
++ break;
++ }
++ }
++ /* No marker, write it. */
++ if (!ha->flags.hw_event_marker_found) {
++ rval = qla2xxx_hw_event_store(ha, marker);
++ if (rval != QLA_SUCCESS) {
++ DEBUG2(qla_printk(KERN_WARNING, ha,
++ "HW event -- Failed marker write=%x.!\n",
++ rval));
++ return rval;
++ }
++ ha->flags.hw_event_marker_found = 1;
++ }
++ }
++
++ /* Store error. */
++ fdata[0] = cpu_to_le32(code << 16 | d1);
++ fdata[1] = cpu_to_le32(d2 << 16 | d3);
++ rval = qla2xxx_hw_event_store(ha, fdata);
++ if (rval != QLA_SUCCESS) {
++ DEBUG2(qla_printk(KERN_WARNING, ha,
++ "HW event -- Failed error write=%x.!\n",
++ rval));
++ }
++
++ return rval;
++}
+diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
+index ea08a12..f42f17a 100644
+--- a/drivers/scsi/qla2xxx/qla_version.h
++++ b/drivers/scsi/qla2xxx/qla_version.h
+@@ -1,15 +1,15 @@
+ /*
+ * QLogic Fibre Channel HBA Driver
+- * Copyright (c) 2003-2005 QLogic Corporation
++ * Copyright (c) 2003-2008 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+ /*
+ * Driver version
+ */
+-#define QLA2XXX_VERSION "8.02.00-k9"
++#define QLA2XXX_VERSION "8.02.01-k1"
+
+ #define QLA_DRIVER_MAJOR_VER 8
+ #define QLA_DRIVER_MINOR_VER 2
+-#define QLA_DRIVER_PATCH_VER 0
++#define QLA_DRIVER_PATCH_VER 1
+ #define QLA_DRIVER_BETA_VER 0
+diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
+index fe415ec..1b667a7 100644
+--- a/drivers/scsi/qla4xxx/ql4_fw.h
++++ b/drivers/scsi/qla4xxx/ql4_fw.h
+@@ -216,6 +216,7 @@ union external_hw_config_reg {
+ #define MBOX_CMD_ABOUT_FW 0x0009
+ #define MBOX_CMD_PING 0x000B
+ #define MBOX_CMD_LUN_RESET 0x0016
++#define MBOX_CMD_TARGET_WARM_RESET 0x0017
+ #define MBOX_CMD_GET_MANAGEMENT_DATA 0x001E
+ #define MBOX_CMD_GET_FW_STATUS 0x001F
+ #define MBOX_CMD_SET_ISNS_SERVICE 0x0021
+@@ -677,7 +678,8 @@ struct qla4_marker_entry {
+ uint32_t system_defined; /* 04-07 */
+ uint16_t target; /* 08-09 */
+ uint16_t modifier; /* 0A-0B */
+-#define MM_LUN_RESET 0
++#define MM_LUN_RESET 0
++#define MM_TGT_WARM_RESET 1
+
+ uint16_t flags; /* 0C-0D */
+ uint16_t reserved1; /* 0E-0F */
+diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
+index a3608e0..96ebfb0 100644
+--- a/drivers/scsi/qla4xxx/ql4_glbl.h
++++ b/drivers/scsi/qla4xxx/ql4_glbl.h
+@@ -27,6 +27,8 @@ int qla4xxx_relogin_device(struct scsi_qla_host * ha,
+ struct ddb_entry * ddb_entry);
+ int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
+ int lun);
++int qla4xxx_reset_target(struct scsi_qla_host * ha,
++ struct ddb_entry * ddb_entry);
+ int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
+ uint32_t offset, uint32_t len);
+ int qla4xxx_get_firmware_status(struct scsi_qla_host * ha);
+@@ -68,6 +70,8 @@ int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha);
+ int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha,
+ uint32_t fw_ddb_index, uint32_t state);
+ void qla4xxx_dump_buffer(void *b, uint32_t size);
++int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
++ struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod);
+
+ extern int ql4xextended_error_logging;
+ extern int ql4xdiscoverywait;
+diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c
+index e4461b5..912a674 100644
+--- a/drivers/scsi/qla4xxx/ql4_iocb.c
++++ b/drivers/scsi/qla4xxx/ql4_iocb.c
+@@ -66,8 +66,8 @@ static int qla4xxx_get_req_pkt(struct scsi_qla_host *ha,
+ *
+ * This routine issues a marker IOCB.
+ **/
+-static int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
+- struct ddb_entry *ddb_entry, int lun)
++int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
++ struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod)
+ {
+ struct qla4_marker_entry *marker_entry;
+ unsigned long flags = 0;
+@@ -87,7 +87,7 @@ static int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
+ marker_entry->hdr.entryType = ET_MARKER;
+ marker_entry->hdr.entryCount = 1;
+ marker_entry->target = cpu_to_le16(ddb_entry->fw_ddb_index);
+- marker_entry->modifier = cpu_to_le16(MM_LUN_RESET);
++ marker_entry->modifier = cpu_to_le16(mrkr_mod);
+ int_to_scsilun(lun, &marker_entry->lun);
+ wmb();
+
+@@ -210,14 +210,6 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)
+ /* Get real lun and adapter */
+ ddb_entry = srb->ddb;
+
+- /* Send marker(s) if needed. */
+- if (ha->marker_needed == 1) {
+- if (qla4xxx_send_marker_iocb(ha, ddb_entry,
+- cmd->device->lun) != QLA_SUCCESS)
+- return QLA_ERROR;
+-
+- ha->marker_needed = 0;
+- }
+ tot_dsds = 0;
+
+ /* Acquire hardware specific lock */
+diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
+index fc84db4..a91a57c 100644
+--- a/drivers/scsi/qla4xxx/ql4_isr.c
++++ b/drivers/scsi/qla4xxx/ql4_isr.c
+@@ -11,28 +11,6 @@
+ #include "ql4_inline.h"
+
+ /**
+- * qla2x00_process_completed_request() - Process a Fast Post response.
+- * @ha: SCSI driver HA context
+- * @index: SRB index
+- **/
+-static void qla4xxx_process_completed_request(struct scsi_qla_host *ha,
+- uint32_t index)
+-{
+- struct srb *srb;
+-
+- srb = qla4xxx_del_from_active_array(ha, index);
+- if (srb) {
+- /* Save ISP completion status */
+- srb->cmd->result = DID_OK << 16;
+- qla4xxx_srb_compl(ha, srb);
+- } else {
+- DEBUG2(printk("scsi%ld: Invalid ISP SCSI completion handle = "
+- "%d\n", ha->host_no, index));
+- set_bit(DPC_RESET_HA, &ha->dpc_flags);
+- }
+-}
+-
+-/**
+ * qla4xxx_status_entry - processes status IOCBs
+ * @ha: Pointer to host adapter structure.
+ * @sts_entry: Pointer to status entry structure.
+@@ -47,14 +25,6 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
+ uint32_t residual;
+ uint16_t sensebytecnt;
+
+- if (sts_entry->completionStatus == SCS_COMPLETE &&
+- sts_entry->scsiStatus == 0) {
+- qla4xxx_process_completed_request(ha,
+- le32_to_cpu(sts_entry->
+- handle));
+- return;
+- }
+-
+ srb = qla4xxx_del_from_active_array(ha, le32_to_cpu(sts_entry->handle));
+ if (!srb) {
+ /* FIXMEdg: Don't we need to reset ISP in this case??? */
+@@ -62,6 +32,9 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
+ "handle 0x%x, sp=%p. This cmd may have already "
+ "been completed.\n", ha->host_no, __func__,
+ le32_to_cpu(sts_entry->handle), srb));
++ dev_warn(&ha->pdev->dev, "%s invalid status entry:"
++ " handle=0x%0x\n", __func__, sts_entry->handle);
++ set_bit(DPC_RESET_HA, &ha->dpc_flags);
+ return;
+ }
+
+@@ -88,10 +61,6 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
+ scsi_status = sts_entry->scsiStatus;
+ switch (sts_entry->completionStatus) {
+ case SCS_COMPLETE:
+- if (scsi_status == 0) {
+- cmd->result = DID_OK << 16;
+- break;
+- }
+
+ if (sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) {
+ cmd->result = DID_ERROR << 16;
+@@ -100,7 +69,8 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
+
+ if (sts_entry->iscsiFlags &ISCSI_FLAG_RESIDUAL_UNDER) {
+ scsi_set_resid(cmd, residual);
+- if ((scsi_bufflen(cmd) - residual) < cmd->underflow) {
++ if (!scsi_status && ((scsi_bufflen(cmd) - residual) <
++ cmd->underflow)) {
+
+ cmd->result = DID_ERROR << 16;
+
+diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
+index 35cd73c..c577d79 100644
+--- a/drivers/scsi/qla4xxx/ql4_mbx.c
++++ b/drivers/scsi/qla4xxx/ql4_mbx.c
+@@ -713,6 +713,45 @@ int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
+ return status;
+ }
+
++/**
++ * qla4xxx_reset_target - issues target Reset
++ * @ha: Pointer to host adapter structure.
++ * @db_entry: Pointer to device database entry
++ * @un_entry: Pointer to lun entry structure
++ *
++ * This routine performs a TARGET RESET on the specified target.
++ * The caller must ensure that the ddb_entry pointers
++ * are valid before calling this routine.
++ **/
++int qla4xxx_reset_target(struct scsi_qla_host *ha,
++ struct ddb_entry *ddb_entry)
++{
++ uint32_t mbox_cmd[MBOX_REG_COUNT];
++ uint32_t mbox_sts[MBOX_REG_COUNT];
++ int status = QLA_SUCCESS;
++
++ DEBUG2(printk("scsi%ld:%d: target reset issued\n", ha->host_no,
++ ddb_entry->os_target_id));
++
++ /*
++ * Send target reset command to ISP, so that the ISP will return all
++ * outstanding requests with RESET status
++ */
++ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
++ memset(&mbox_sts, 0, sizeof(mbox_sts));
++
++ mbox_cmd[0] = MBOX_CMD_TARGET_WARM_RESET;
++ mbox_cmd[1] = ddb_entry->fw_ddb_index;
++ mbox_cmd[5] = 0x01; /* Immediate Command Enable */
++
++ qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
++ &mbox_sts[0]);
++ if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&
++ mbox_sts[0] != MBOX_STS_COMMAND_ERROR)
++ status = QLA_ERROR;
++
++ return status;
++}
+
+ int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
+ uint32_t offset, uint32_t len)
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 8b92f34..0c78694 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -71,6 +71,7 @@ static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session);
+ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
+ void (*done) (struct scsi_cmnd *));
+ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd);
++static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd);
+ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd);
+ static int qla4xxx_slave_alloc(struct scsi_device *device);
+ static int qla4xxx_slave_configure(struct scsi_device *device);
+@@ -84,6 +85,7 @@ static struct scsi_host_template qla4xxx_driver_template = {
+ .queuecommand = qla4xxx_queuecommand,
+
+ .eh_device_reset_handler = qla4xxx_eh_device_reset,
++ .eh_target_reset_handler = qla4xxx_eh_target_reset,
+ .eh_host_reset_handler = qla4xxx_eh_host_reset,
+
+ .slave_configure = qla4xxx_slave_configure,
+@@ -1482,7 +1484,7 @@ static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha)
+ }
+
+ /**
+- * qla4xxx_eh_wait_for_active_target_commands - wait for active cmds to finish.
++ * qla4xxx_eh_wait_for_commands - wait for active cmds to finish.
+ * @ha: pointer to to HBA
+ * @t: target id
+ * @l: lun id
+@@ -1490,20 +1492,22 @@ static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha)
+ * This function waits for all outstanding commands to a lun to complete. It
+ * returns 0 if all pending commands are returned and 1 otherwise.
+ **/
+-static int qla4xxx_eh_wait_for_active_target_commands(struct scsi_qla_host *ha,
+- int t, int l)
++static int qla4xxx_eh_wait_for_commands(struct scsi_qla_host *ha,
++ struct scsi_target *stgt,
++ struct scsi_device *sdev)
+ {
+ int cnt;
+ int status = 0;
+ struct scsi_cmnd *cmd;
+
+ /*
+- * Waiting for all commands for the designated target in the active
+- * array
++ * Waiting for all commands for the designated target or dev
++ * in the active array
+ */
+ for (cnt = 0; cnt < ha->host->can_queue; cnt++) {
+ cmd = scsi_host_find_tag(ha->host, cnt);
+- if (cmd && cmd->device->id == t && cmd->device->lun == l) {
++ if (cmd && stgt == scsi_target(cmd->device) &&
++ (!sdev || sdev == cmd->device)) {
+ if (!qla4xxx_eh_wait_on_command(ha, cmd)) {
+ status++;
+ break;
+@@ -1548,24 +1552,19 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
+ goto eh_dev_reset_done;
+ }
+
+- /* Send marker. */
+- ha->marker_needed = 1;
+-
+- /*
+- * If we are coming down the EH path, wait for all commands to complete
+- * for the device.
+- */
+- if (cmd->device->host->shost_state == SHOST_RECOVERY) {
+- if (qla4xxx_eh_wait_for_active_target_commands(ha,
+- cmd->device->id,
+- cmd->device->lun)){
+- dev_info(&ha->pdev->dev,
+- "DEVICE RESET FAILED - waiting for "
+- "commands.\n");
+- goto eh_dev_reset_done;
+- }
++ if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device),
++ cmd->device)) {
++ dev_info(&ha->pdev->dev,
++ "DEVICE RESET FAILED - waiting for "
++ "commands.\n");
++ goto eh_dev_reset_done;
+ }
+
++ /* Send marker. */
++ if (qla4xxx_send_marker_iocb(ha, ddb_entry, cmd->device->lun,
++ MM_LUN_RESET) != QLA_SUCCESS)
++ goto eh_dev_reset_done;
++
+ dev_info(&ha->pdev->dev,
+ "scsi(%ld:%d:%d:%d): DEVICE RESET SUCCEEDED.\n",
+ ha->host_no, cmd->device->channel, cmd->device->id,
+@@ -1579,6 +1578,59 @@ eh_dev_reset_done:
+ }
+
+ /**
++ * qla4xxx_eh_target_reset - callback for target reset.
++ * @cmd: Pointer to Linux's SCSI command structure
++ *
++ * This routine is called by the Linux OS to reset the target.
++ **/
++static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd)
++{
++ struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
++ struct ddb_entry *ddb_entry = cmd->device->hostdata;
++ int stat;
++
++ if (!ddb_entry)
++ return FAILED;
++
++ starget_printk(KERN_INFO, scsi_target(cmd->device),
++ "WARM TARGET RESET ISSUED.\n");
++
++ DEBUG2(printk(KERN_INFO
++ "scsi%ld: TARGET_DEVICE_RESET cmd=%p jiffies = 0x%lx, "
++ "to=%x,dpc_flags=%lx, status=%x allowed=%d\n",
++ ha->host_no, cmd, jiffies, cmd->timeout_per_command / HZ,
++ ha->dpc_flags, cmd->result, cmd->allowed));
++
++ stat = qla4xxx_reset_target(ha, ddb_entry);
++ if (stat != QLA_SUCCESS) {
++ starget_printk(KERN_INFO, scsi_target(cmd->device),
++ "WARM TARGET RESET FAILED.\n");
++ return FAILED;
++ }
++
++ if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device),
++ NULL)) {
++ starget_printk(KERN_INFO, scsi_target(cmd->device),
++ "WARM TARGET DEVICE RESET FAILED - "
++ "waiting for commands.\n");
++ return FAILED;
++ }
++
++ /* Send marker. */
++ if (qla4xxx_send_marker_iocb(ha, ddb_entry, cmd->device->lun,
++ MM_TGT_WARM_RESET) != QLA_SUCCESS) {
++ starget_printk(KERN_INFO, scsi_target(cmd->device),
++ "WARM TARGET DEVICE RESET FAILED - "
++ "marker iocb failed.\n");
++ return FAILED;
++ }
++
++ starget_printk(KERN_INFO, scsi_target(cmd->device),
++ "WARM TARGET RESET SUCCEEDED.\n");
++ return SUCCESS;
++}
++
++/**
+ * qla4xxx_eh_host_reset - kernel callback
+ * @cmd: Pointer to Linux's SCSI command structure
+ *
+diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c
+index 86e1318..913a931 100644
+--- a/drivers/scsi/raid_class.c
++++ b/drivers/scsi/raid_class.c
+@@ -24,15 +24,15 @@ struct raid_internal {
+ struct raid_template r;
+ struct raid_function_template *f;
+ /* The actual attributes */
+- struct class_device_attribute private_attrs[RAID_NUM_ATTRS];
++ struct device_attribute private_attrs[RAID_NUM_ATTRS];
+ /* The array of null terminated pointers to attributes
+ * needed by scsi_sysfs.c */
+- struct class_device_attribute *attrs[RAID_NUM_ATTRS + 1];
++ struct device_attribute *attrs[RAID_NUM_ATTRS + 1];
+ };
+
+ struct raid_component {
+ struct list_head node;
+- struct class_device cdev;
++ struct device dev;
+ int num;
+ };
+
+@@ -50,9 +50,9 @@ struct raid_component {
+ tc_to_raid_internal(tc); \
+ })
+
+-#define class_device_to_raid_internal(cdev) ({ \
++#define device_to_raid_internal(dev) ({ \
+ struct attribute_container *ac = \
+- attribute_container_classdev_to_container(cdev); \
++ attribute_container_classdev_to_container(dev); \
+ ac_to_raid_internal(ac); \
+ })
+
+@@ -76,33 +76,33 @@ static int raid_match(struct attribute_container *cont, struct device *dev)
+ }
+
+ static int raid_setup(struct transport_container *tc, struct device *dev,
+- struct class_device *cdev)
++ struct device *cdev)
+ {
+ struct raid_data *rd;
+
+- BUG_ON(class_get_devdata(cdev));
++ BUG_ON(dev_get_drvdata(cdev));
+
+ rd = kzalloc(sizeof(*rd), GFP_KERNEL);
+ if (!rd)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&rd->component_list);
+- class_set_devdata(cdev, rd);
++ dev_set_drvdata(cdev, rd);
+
+ return 0;
+ }
+
+ static int raid_remove(struct transport_container *tc, struct device *dev,
+- struct class_device *cdev)
++ struct device *cdev)
+ {
+- struct raid_data *rd = class_get_devdata(cdev);
++ struct raid_data *rd = dev_get_drvdata(cdev);
+ struct raid_component *rc, *next;
+ dev_printk(KERN_ERR, dev, "RAID REMOVE\n");
+- class_set_devdata(cdev, NULL);
++ dev_set_drvdata(cdev, NULL);
+ list_for_each_entry_safe(rc, next, &rd->component_list, node) {
+ list_del(&rc->node);
+- dev_printk(KERN_ERR, rc->cdev.dev, "RAID COMPONENT REMOVE\n");
+- class_device_unregister(&rc->cdev);
++ dev_printk(KERN_ERR, rc->dev.parent, "RAID COMPONENT REMOVE\n");
++ device_unregister(&rc->dev);
+ }
+ dev_printk(KERN_ERR, dev, "RAID REMOVE DONE\n");
+ kfree(rd);
+@@ -171,9 +171,11 @@ static const char *raid_level_name(enum raid_level level)
+ }
+
+ #define raid_attr_show_internal(attr, fmt, var, code) \
+-static ssize_t raid_show_##attr(struct class_device *cdev, char *buf) \
++static ssize_t raid_show_##attr(struct device *dev, \
++ struct device_attribute *attr, \
++ char *buf) \
+ { \
+- struct raid_data *rd = class_get_devdata(cdev); \
++ struct raid_data *rd = dev_get_drvdata(dev); \
+ code \
+ return snprintf(buf, 20, #fmt "\n", var); \
+ }
+@@ -184,17 +186,17 @@ raid_attr_show_internal(attr, %s, name, \
+ code \
+ name = raid_##states##_name(rd->attr); \
+ ) \
+-static CLASS_DEVICE_ATTR(attr, S_IRUGO, raid_show_##attr, NULL)
++static DEVICE_ATTR(attr, S_IRUGO, raid_show_##attr, NULL)
+
+
+ #define raid_attr_ro_internal(attr, code) \
+ raid_attr_show_internal(attr, %d, rd->attr, code) \
+-static CLASS_DEVICE_ATTR(attr, S_IRUGO, raid_show_##attr, NULL)
++static DEVICE_ATTR(attr, S_IRUGO, raid_show_##attr, NULL)
+
+ #define ATTR_CODE(attr) \
+- struct raid_internal *i = class_device_to_raid_internal(cdev); \
++ struct raid_internal *i = device_to_raid_internal(dev); \
+ if (i->f->get_##attr) \
+- i->f->get_##attr(cdev->dev);
++ i->f->get_##attr(dev->parent);
+
+ #define raid_attr_ro(attr) raid_attr_ro_internal(attr, )
+ #define raid_attr_ro_fn(attr) raid_attr_ro_internal(attr, ATTR_CODE(attr))
+@@ -206,23 +208,23 @@ raid_attr_ro_state(level);
+ raid_attr_ro_fn(resync);
+ raid_attr_ro_state_fn(state);
+
+-static void raid_component_release(struct class_device *cdev)
++static void raid_component_release(struct device *dev)
+ {
+- struct raid_component *rc = container_of(cdev, struct raid_component,
+- cdev);
+- dev_printk(KERN_ERR, rc->cdev.dev, "COMPONENT RELEASE\n");
+- put_device(rc->cdev.dev);
++ struct raid_component *rc =
++ container_of(dev, struct raid_component, dev);
++ dev_printk(KERN_ERR, rc->dev.parent, "COMPONENT RELEASE\n");
++ put_device(rc->dev.parent);
+ kfree(rc);
+ }
+
+ int raid_component_add(struct raid_template *r,struct device *raid_dev,
+ struct device *component_dev)
+ {
+- struct class_device *cdev =
++ struct device *cdev =
+ attribute_container_find_class_device(&r->raid_attrs.ac,
+ raid_dev);
+ struct raid_component *rc;
+- struct raid_data *rd = class_get_devdata(cdev);
++ struct raid_data *rd = dev_get_drvdata(cdev);
+ int err;
+
+ rc = kzalloc(sizeof(*rc), GFP_KERNEL);
+@@ -230,17 +232,16 @@ int raid_component_add(struct raid_template *r,struct device *raid_dev,
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&rc->node);
+- class_device_initialize(&rc->cdev);
+- rc->cdev.release = raid_component_release;
+- rc->cdev.dev = get_device(component_dev);
++ device_initialize(&rc->dev);
++ rc->dev.release = raid_component_release;
++ rc->dev.parent = get_device(component_dev);
+ rc->num = rd->component_count++;
+
+- snprintf(rc->cdev.class_id, sizeof(rc->cdev.class_id),
++ snprintf(rc->dev.bus_id, sizeof(rc->dev.bus_id),
+ "component-%d", rc->num);
+ list_add_tail(&rc->node, &rd->component_list);
+- rc->cdev.parent = cdev;
+- rc->cdev.class = &raid_class.class;
+- err = class_device_add(&rc->cdev);
++ rc->dev.class = &raid_class.class;
++ err = device_add(&rc->dev);
+ if (err)
+ goto err_out;
+
+@@ -273,9 +274,9 @@ raid_class_attach(struct raid_function_template *ft)
+
+ attribute_container_register(&i->r.raid_attrs.ac);
+
+- i->attrs[count++] = &class_device_attr_level;
+- i->attrs[count++] = &class_device_attr_resync;
+- i->attrs[count++] = &class_device_attr_state;
++ i->attrs[count++] = &dev_attr_level;
++ i->attrs[count++] = &dev_attr_resync;
++ i->attrs[count++] = &dev_attr_state;
+
+ i->attrs[count] = NULL;
+ BUG_ON(count > RAID_NUM_ATTRS);
+@@ -289,7 +290,7 @@ raid_class_release(struct raid_template *r)
+ {
+ struct raid_internal *i = to_raid_internal(r);
+
+- attribute_container_unregister(&i->r.raid_attrs.ac);
++ BUG_ON(attribute_container_unregister(&i->r.raid_attrs.ac));
+
+ kfree(i);
+ }
+diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
+index c78b836..12d69d7 100644
+--- a/drivers/scsi/scsi.c
++++ b/drivers/scsi/scsi.c
+@@ -166,6 +166,51 @@ static struct scsi_host_cmd_pool scsi_cmd_dma_pool = {
+ static DEFINE_MUTEX(host_cmd_pool_mutex);
+
+ /**
++ * scsi_pool_alloc_command - internal function to get a fully allocated command
++ * @pool: slab pool to allocate the command from
++ * @gfp_mask: mask for the allocation
++ *
++ * Returns a fully allocated command (with the allied sense buffer) or
++ * NULL on failure
++ */
++static struct scsi_cmnd *
++scsi_pool_alloc_command(struct scsi_host_cmd_pool *pool, gfp_t gfp_mask)
++{
++ struct scsi_cmnd *cmd;
++
++ cmd = kmem_cache_alloc(pool->cmd_slab, gfp_mask | pool->gfp_mask);
++ if (!cmd)
++ return NULL;
++
++ memset(cmd, 0, sizeof(*cmd));
++
++ cmd->sense_buffer = kmem_cache_alloc(pool->sense_slab,
++ gfp_mask | pool->gfp_mask);
++ if (!cmd->sense_buffer) {
++ kmem_cache_free(pool->cmd_slab, cmd);
++ return NULL;
++ }
++
++ return cmd;
++}
++
++/**
++ * scsi_pool_free_command - internal function to release a command
++ * @pool: slab pool to allocate the command from
++ * @cmd: command to release
++ *
++ * the command must previously have been allocated by
++ * scsi_pool_alloc_command.
++ */
++static void
++scsi_pool_free_command(struct scsi_host_cmd_pool *pool,
++ struct scsi_cmnd *cmd)
++{
++ kmem_cache_free(pool->sense_slab, cmd->sense_buffer);
++ kmem_cache_free(pool->cmd_slab, cmd);
++}
++
++/**
+ * __scsi_get_command - Allocate a struct scsi_cmnd
+ * @shost: host to transmit command
+ * @gfp_mask: allocation mask
+@@ -178,20 +223,7 @@ struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
+ struct scsi_cmnd *cmd;
+ unsigned char *buf;
+
+- cmd = kmem_cache_alloc(shost->cmd_pool->cmd_slab,
+- gfp_mask | shost->cmd_pool->gfp_mask);
+-
+- if (likely(cmd)) {
+- buf = kmem_cache_alloc(shost->cmd_pool->sense_slab,
+- gfp_mask | shost->cmd_pool->gfp_mask);
+- if (likely(buf)) {
+- memset(cmd, 0, sizeof(*cmd));
+- cmd->sense_buffer = buf;
+- } else {
+- kmem_cache_free(shost->cmd_pool->cmd_slab, cmd);
+- cmd = NULL;
+- }
+- }
++ cmd = scsi_pool_alloc_command(shost->cmd_pool, gfp_mask);
+
+ if (unlikely(!cmd)) {
+ unsigned long flags;
+@@ -268,11 +300,8 @@ void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd,
+ }
+ spin_unlock_irqrestore(&shost->free_list_lock, flags);
+
+- if (likely(cmd != NULL)) {
+- kmem_cache_free(shost->cmd_pool->sense_slab,
+- cmd->sense_buffer);
+- kmem_cache_free(shost->cmd_pool->cmd_slab, cmd);
+- }
++ if (likely(cmd != NULL))
++ scsi_pool_free_command(shost->cmd_pool, cmd);
+
+ put_device(dev);
+ }
+@@ -301,30 +330,16 @@ void scsi_put_command(struct scsi_cmnd *cmd)
+ }
+ EXPORT_SYMBOL(scsi_put_command);
+
+-/**
+- * scsi_setup_command_freelist - Setup the command freelist for a scsi host.
+- * @shost: host to allocate the freelist for.
+- *
+- * Description: The command freelist protects against system-wide out of memory
+- * deadlock by preallocating one SCSI command structure for each host, so the
+- * system can always write to a swap file on a device associated with that host.
+- *
+- * Returns: Nothing.
+- */
+-int scsi_setup_command_freelist(struct Scsi_Host *shost)
++static struct scsi_host_cmd_pool *scsi_get_host_cmd_pool(gfp_t gfp_mask)
+ {
+- struct scsi_host_cmd_pool *pool;
+- struct scsi_cmnd *cmd;
+-
+- spin_lock_init(&shost->free_list_lock);
+- INIT_LIST_HEAD(&shost->free_list);
+-
++ struct scsi_host_cmd_pool *retval = NULL, *pool;
+ /*
+ * Select a command slab for this host and create it if not
+ * yet existent.
+ */
+ mutex_lock(&host_cmd_pool_mutex);
+- pool = (shost->unchecked_isa_dma ? &scsi_cmd_dma_pool : &scsi_cmd_pool);
++ pool = (gfp_mask & __GFP_DMA) ? &scsi_cmd_dma_pool :
++ &scsi_cmd_pool;
+ if (!pool->users) {
+ pool->cmd_slab = kmem_cache_create(pool->cmd_name,
+ sizeof(struct scsi_cmnd), 0,
+@@ -342,37 +357,122 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
+ }
+
+ pool->users++;
+- shost->cmd_pool = pool;
++ retval = pool;
++ fail:
+ mutex_unlock(&host_cmd_pool_mutex);
++ return retval;
++}
++
++static void scsi_put_host_cmd_pool(gfp_t gfp_mask)
++{
++ struct scsi_host_cmd_pool *pool;
+
++ mutex_lock(&host_cmd_pool_mutex);
++ pool = (gfp_mask & __GFP_DMA) ? &scsi_cmd_dma_pool :
++ &scsi_cmd_pool;
+ /*
+- * Get one backup command for this host.
++ * This may happen if a driver has a mismatched get and put
++ * of the command pool; the driver should be implicated in
++ * the stack trace
+ */
+- cmd = kmem_cache_alloc(shost->cmd_pool->cmd_slab,
+- GFP_KERNEL | shost->cmd_pool->gfp_mask);
+- if (!cmd)
+- goto fail2;
++ BUG_ON(pool->users == 0);
+
+- cmd->sense_buffer = kmem_cache_alloc(shost->cmd_pool->sense_slab,
+- GFP_KERNEL |
+- shost->cmd_pool->gfp_mask);
+- if (!cmd->sense_buffer)
+- goto fail2;
+-
+- list_add(&cmd->list, &shost->free_list);
+- return 0;
+-
+- fail2:
+- if (cmd)
+- kmem_cache_free(shost->cmd_pool->cmd_slab, cmd);
+- mutex_lock(&host_cmd_pool_mutex);
+ if (!--pool->users) {
+ kmem_cache_destroy(pool->cmd_slab);
+ kmem_cache_destroy(pool->sense_slab);
+ }
+- fail:
+ mutex_unlock(&host_cmd_pool_mutex);
+- return -ENOMEM;
++}
++
++/**
++ * scsi_allocate_command - get a fully allocated SCSI command
++ * @gfp_mask: allocation mask
++ *
++ * This function is for use outside of the normal host based pools.
++ * It allocates the relevant command and takes an additional reference
++ * on the pool it used. This function *must* be paired with
++ * scsi_free_command which also has the identical mask, otherwise the
++ * free pool counts will eventually go wrong and you'll trigger a bug.
++ *
++ * This function should *only* be used by drivers that need a static
++ * command allocation at start of day for internal functions.
++ */
++struct scsi_cmnd *scsi_allocate_command(gfp_t gfp_mask)
++{
++ struct scsi_host_cmd_pool *pool = scsi_get_host_cmd_pool(gfp_mask);
++
++ if (!pool)
++ return NULL;
++
++ return scsi_pool_alloc_command(pool, gfp_mask);
++}
++EXPORT_SYMBOL(scsi_allocate_command);
++
++/**
++ * scsi_free_command - free a command allocated by scsi_allocate_command
++ * @gfp_mask: mask used in the original allocation
++ * @cmd: command to free
++ *
++ * Note: using the original allocation mask is vital because that's
++ * what determines which command pool we use to free the command. Any
++ * mismatch will cause the system to BUG eventually.
++ */
++void scsi_free_command(gfp_t gfp_mask, struct scsi_cmnd *cmd)
++{
++ struct scsi_host_cmd_pool *pool = scsi_get_host_cmd_pool(gfp_mask);
++
++ /*
++ * this could trigger if the mask to scsi_allocate_command
++ * doesn't match this mask. Otherwise we're guaranteed that this
++ * succeeds because scsi_allocate_command must have taken a reference
++ * on the pool
++ */
++ BUG_ON(!pool);
++
++ scsi_pool_free_command(pool, cmd);
++ /*
++ * scsi_put_host_cmd_pool is called twice; once to release the
++ * reference we took above, and once to release the reference
++ * originally taken by scsi_allocate_command
++ */
++ scsi_put_host_cmd_pool(gfp_mask);
++ scsi_put_host_cmd_pool(gfp_mask);
++}
++EXPORT_SYMBOL(scsi_free_command);
++
++/**
++ * scsi_setup_command_freelist - Setup the command freelist for a scsi host.
++ * @shost: host to allocate the freelist for.
++ *
++ * Description: The command freelist protects against system-wide out of memory
++ * deadlock by preallocating one SCSI command structure for each host, so the
++ * system can always write to a swap file on a device associated with that host.
++ *
++ * Returns: Nothing.
++ */
++int scsi_setup_command_freelist(struct Scsi_Host *shost)
++{
++ struct scsi_cmnd *cmd;
++ const gfp_t gfp_mask = shost->unchecked_isa_dma ? GFP_DMA : GFP_KERNEL;
++
++ spin_lock_init(&shost->free_list_lock);
++ INIT_LIST_HEAD(&shost->free_list);
++
++ shost->cmd_pool = scsi_get_host_cmd_pool(gfp_mask);
++
++ if (!shost->cmd_pool)
++ return -ENOMEM;
++
++ /*
++ * Get one backup command for this host.
++ */
++ cmd = scsi_pool_alloc_command(shost->cmd_pool, gfp_mask);
++ if (!cmd) {
++ scsi_put_host_cmd_pool(gfp_mask);
++ return -ENOMEM;
++ }
++ list_add(&cmd->list, &shost->free_list);
++ return 0;
+ }
+
+ /**
+@@ -386,17 +486,10 @@ void scsi_destroy_command_freelist(struct Scsi_Host *shost)
+
+ cmd = list_entry(shost->free_list.next, struct scsi_cmnd, list);
+ list_del_init(&cmd->list);
+- kmem_cache_free(shost->cmd_pool->sense_slab,
+- cmd->sense_buffer);
+- kmem_cache_free(shost->cmd_pool->cmd_slab, cmd);
++ scsi_pool_free_command(shost->cmd_pool, cmd);
+ }
+-
+- mutex_lock(&host_cmd_pool_mutex);
+- if (!--shost->cmd_pool->users) {
+- kmem_cache_destroy(shost->cmd_pool->cmd_slab);
+- kmem_cache_destroy(shost->cmd_pool->sense_slab);
+- }
+- mutex_unlock(&host_cmd_pool_mutex);
++ shost->cmd_pool = NULL;
++ scsi_put_host_cmd_pool(shost->unchecked_isa_dma ? GFP_DMA : GFP_KERNEL);
+ }
+
+ #ifdef CONFIG_SCSI_LOGGING
+@@ -759,7 +852,7 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
+ "Notifying upper driver of completion "
+ "(result %x)\n", cmd->result));
+
+- good_bytes = scsi_bufflen(cmd) + cmd->request->extra_len;
++ good_bytes = scsi_bufflen(cmd);
+ if (cmd->request->cmd_type != REQ_TYPE_BLOCK_PC) {
+ drv = scsi_cmd_to_driver(cmd);
+ if (drv->done)
+diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
+index d1777a9..07103c3 100644
+--- a/drivers/scsi/scsi_debug.c
++++ b/drivers/scsi/scsi_debug.c
+@@ -39,16 +39,18 @@
+ #include <linux/vmalloc.h>
+ #include <linux/moduleparam.h>
+ #include <linux/scatterlist.h>
+-
+ #include <linux/blkdev.h>
+-#include "scsi.h"
++
++#include <scsi/scsi.h>
++#include <scsi/scsi_cmnd.h>
++#include <scsi/scsi_device.h>
+ #include <scsi/scsi_host.h>
+ #include <scsi/scsicam.h>
++#include <scsi/scsi_eh.h>
+
+ #include <linux/stat.h>
+
+ #include "scsi_logging.h"
+-#include "scsi_debug.h"
+
+ #define SCSI_DEBUG_VERSION "1.81"
+ static const char * scsi_debug_version_date = "20070104";
+@@ -146,7 +148,6 @@ static int scsi_debug_cmnd_count = 0;
+ #define DEV_READONLY(TGT) (0)
+ #define DEV_REMOVEABLE(TGT) (0)
+
+-static unsigned int sdebug_store_size; /* in bytes */
+ static unsigned int sdebug_store_sectors;
+ static sector_t sdebug_capacity; /* in sectors */
+
+@@ -165,6 +166,9 @@ static int sdebug_sectors_per; /* sectors per cylinder */
+
+ #define SDEBUG_SENSE_LEN 32
+
++#define SCSI_DEBUG_CANQUEUE 255
++#define SCSI_DEBUG_MAX_CMD_LEN 16
++
+ struct sdebug_dev_info {
+ struct list_head dev_list;
+ unsigned char sense_buff[SDEBUG_SENSE_LEN]; /* weak nexus */
+@@ -202,30 +206,6 @@ struct sdebug_queued_cmd {
+ };
+ static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE];
+
+-static struct scsi_host_template sdebug_driver_template = {
+- .proc_info = scsi_debug_proc_info,
+- .name = "SCSI DEBUG",
+- .info = scsi_debug_info,
+- .slave_alloc = scsi_debug_slave_alloc,
+- .slave_configure = scsi_debug_slave_configure,
+- .slave_destroy = scsi_debug_slave_destroy,
+- .ioctl = scsi_debug_ioctl,
+- .queuecommand = scsi_debug_queuecommand,
+- .eh_abort_handler = scsi_debug_abort,
+- .eh_bus_reset_handler = scsi_debug_bus_reset,
+- .eh_device_reset_handler = scsi_debug_device_reset,
+- .eh_host_reset_handler = scsi_debug_host_reset,
+- .bios_param = scsi_debug_biosparam,
+- .can_queue = SCSI_DEBUG_CANQUEUE,
+- .this_id = 7,
+- .sg_tablesize = 256,
+- .cmd_per_lun = 16,
+- .max_sectors = 0xffff,
+- .unchecked_isa_dma = 0,
+- .use_clustering = DISABLE_CLUSTERING,
+- .module = THIS_MODULE,
+-};
+-
+ static unsigned char * fake_storep; /* ramdisk storage */
+
+ static int num_aborts = 0;
+@@ -238,8 +218,6 @@ static DEFINE_RWLOCK(atomic_rw);
+
+ static char sdebug_proc_name[] = "scsi_debug";
+
+-static int sdebug_driver_probe(struct device *);
+-static int sdebug_driver_remove(struct device *);
+ static struct bus_type pseudo_lld_bus;
+
+ static struct device_driver sdebug_driverfs_driver = {
+@@ -255,94 +233,77 @@ static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
+ static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
+ 0, 0, 0x0, 0x0};
+
+-/* function declarations */
+-static int resp_inquiry(struct scsi_cmnd * SCpnt, int target,
+- struct sdebug_dev_info * devip);
+-static int resp_requests(struct scsi_cmnd * SCpnt,
+- struct sdebug_dev_info * devip);
+-static int resp_start_stop(struct scsi_cmnd * scp,
+- struct sdebug_dev_info * devip);
+-static int resp_report_tgtpgs(struct scsi_cmnd * scp,
+- struct sdebug_dev_info * devip);
+-static int resp_readcap(struct scsi_cmnd * SCpnt,
+- struct sdebug_dev_info * devip);
+-static int resp_readcap16(struct scsi_cmnd * SCpnt,
+- struct sdebug_dev_info * devip);
+-static int resp_mode_sense(struct scsi_cmnd * scp, int target,
+- struct sdebug_dev_info * devip);
+-static int resp_mode_select(struct scsi_cmnd * scp, int mselect6,
+- struct sdebug_dev_info * devip);
+-static int resp_log_sense(struct scsi_cmnd * scp,
+- struct sdebug_dev_info * devip);
+-static int resp_read(struct scsi_cmnd * SCpnt, unsigned long long lba,
+- unsigned int num, struct sdebug_dev_info * devip);
+-static int resp_write(struct scsi_cmnd * SCpnt, unsigned long long lba,
+- unsigned int num, struct sdebug_dev_info * devip);
+-static int resp_report_luns(struct scsi_cmnd * SCpnt,
+- struct sdebug_dev_info * devip);
+-static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
+- unsigned int num, struct sdebug_dev_info *devip);
+-static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
+- int arr_len);
+-static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
+- int max_arr_len);
+-static void timer_intr_handler(unsigned long);
+-static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev);
+-static void mk_sense_buffer(struct sdebug_dev_info * devip, int key,
+- int asc, int asq);
+-static int check_readiness(struct scsi_cmnd * SCpnt, int reset_only,
+- struct sdebug_dev_info * devip);
+-static int schedule_resp(struct scsi_cmnd * cmnd,
+- struct sdebug_dev_info * devip,
+- done_funct_t done, int scsi_result, int delta_jiff);
+-static void __init sdebug_build_parts(unsigned char * ramp);
+-static void __init init_all_queued(void);
+-static void stop_all_queued(void);
+-static int stop_queued_cmnd(struct scsi_cmnd * cmnd);
+-static int inquiry_evpd_83(unsigned char * arr, int port_group_id,
+- int target_dev_id, int dev_id_num,
+- const char * dev_id_str, int dev_id_str_len);
+-static int inquiry_evpd_88(unsigned char * arr, int target_dev_id);
+-static int do_create_driverfs_files(void);
+-static void do_remove_driverfs_files(void);
+-
+ static int sdebug_add_adapter(void);
+ static void sdebug_remove_adapter(void);
+-static void sdebug_max_tgts_luns(void);
+
+-static struct device pseudo_primary;
+-static struct bus_type pseudo_lld_bus;
++static void sdebug_max_tgts_luns(void)
++{
++ struct sdebug_host_info *sdbg_host;
++ struct Scsi_Host *hpnt;
++
++ spin_lock(&sdebug_host_list_lock);
++ list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
++ hpnt = sdbg_host->shost;
++ if ((hpnt->this_id >= 0) &&
++ (scsi_debug_num_tgts > hpnt->this_id))
++ hpnt->max_id = scsi_debug_num_tgts + 1;
++ else
++ hpnt->max_id = scsi_debug_num_tgts;
++ /* scsi_debug_max_luns; */
++ hpnt->max_lun = SAM2_WLUN_REPORT_LUNS;
++ }
++ spin_unlock(&sdebug_host_list_lock);
++}
++
++static void mk_sense_buffer(struct sdebug_dev_info *devip, int key,
++ int asc, int asq)
++{
++ unsigned char *sbuff;
++
++ sbuff = devip->sense_buff;
++ memset(sbuff, 0, SDEBUG_SENSE_LEN);
++
++ scsi_build_sense_buffer(scsi_debug_dsense, sbuff, key, asc, asq);
++
++ if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
++ printk(KERN_INFO "scsi_debug: [sense_key,asc,ascq]: "
++ "[0x%x,0x%x,0x%x]\n", key, asc, asq);
++}
+
+ static void get_data_transfer_info(unsigned char *cmd,
+ unsigned long long *lba, unsigned int *num)
+ {
+- int i;
+-
+ switch (*cmd) {
+ case WRITE_16:
+ case READ_16:
+- for (*lba = 0, i = 0; i < 8; ++i) {
+- if (i > 0)
+- *lba <<= 8;
+- *lba += cmd[2 + i];
+- }
+- *num = cmd[13] + (cmd[12] << 8) +
+- (cmd[11] << 16) + (cmd[10] << 24);
++ *lba = (u64)cmd[9] | (u64)cmd[8] << 8 |
++ (u64)cmd[7] << 16 | (u64)cmd[6] << 24 |
++ (u64)cmd[5] << 32 | (u64)cmd[4] << 40 |
++ (u64)cmd[3] << 48 | (u64)cmd[2] << 56;
++
++ *num = (u32)cmd[13] | (u32)cmd[12] << 8 | (u32)cmd[11] << 16 |
++ (u32)cmd[10] << 24;
+ break;
+ case WRITE_12:
+ case READ_12:
+- *lba = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24);
+- *num = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
++ *lba = (u32)cmd[5] | (u32)cmd[4] << 8 | (u32)cmd[3] << 16 |
++ (u32)cmd[2] << 24;
++
++ *num = (u32)cmd[9] | (u32)cmd[8] << 8 | (u32)cmd[7] << 16 |
++ (u32)cmd[6] << 24;
+ break;
+ case WRITE_10:
+ case READ_10:
+ case XDWRITEREAD_10:
+- *lba = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24);
+- *num = cmd[8] + (cmd[7] << 8);
++ *lba = (u32)cmd[5] | (u32)cmd[4] << 8 | (u32)cmd[3] << 16 |
++ (u32)cmd[2] << 24;
++
++ *num = (u32)cmd[8] | (u32)cmd[7] << 8;
+ break;
+ case WRITE_6:
+ case READ_6:
+- *lba = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16);
++ *lba = (u32)cmd[3] | (u32)cmd[2] << 8 |
++ (u32)(cmd[1] & 0x1f) << 16;
+ *num = (0 == cmd[4]) ? 256 : cmd[4];
+ break;
+ default:
+@@ -350,237 +311,6 @@ static void get_data_transfer_info(unsigned char *cmd,
+ }
+ }
+
+-static
+-int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
+-{
+- unsigned char *cmd = (unsigned char *) SCpnt->cmnd;
+- int len, k;
+- unsigned int num;
+- unsigned long long lba;
+- int errsts = 0;
+- int target = SCpnt->device->id;
+- struct sdebug_dev_info * devip = NULL;
+- int inj_recovered = 0;
+- int inj_transport = 0;
+- int delay_override = 0;
+-
+- if (done == NULL)
+- return 0; /* assume mid level reprocessing command */
+-
+- scsi_set_resid(SCpnt, 0);
+- if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmd) {
+- printk(KERN_INFO "scsi_debug: cmd ");
+- for (k = 0, len = SCpnt->cmd_len; k < len; ++k)
+- printk("%02x ", (int)cmd[k]);
+- printk("\n");
+- }
+- if(target == sdebug_driver_template.this_id) {
+- printk(KERN_INFO "scsi_debug: initiator's id used as "
+- "target!\n");
+- return schedule_resp(SCpnt, NULL, done,
+- DID_NO_CONNECT << 16, 0);
+- }
+-
+- if ((SCpnt->device->lun >= scsi_debug_max_luns) &&
+- (SCpnt->device->lun != SAM2_WLUN_REPORT_LUNS))
+- return schedule_resp(SCpnt, NULL, done,
+- DID_NO_CONNECT << 16, 0);
+- devip = devInfoReg(SCpnt->device);
+- if (NULL == devip)
+- return schedule_resp(SCpnt, NULL, done,
+- DID_NO_CONNECT << 16, 0);
+-
+- if ((scsi_debug_every_nth != 0) &&
+- (++scsi_debug_cmnd_count >= abs(scsi_debug_every_nth))) {
+- scsi_debug_cmnd_count = 0;
+- if (scsi_debug_every_nth < -1)
+- scsi_debug_every_nth = -1;
+- if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
+- return 0; /* ignore command causing timeout */
+- else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts)
+- inj_recovered = 1; /* to reads and writes below */
+- else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts)
+- inj_transport = 1; /* to reads and writes below */
+- }
+-
+- if (devip->wlun) {
+- switch (*cmd) {
+- case INQUIRY:
+- case REQUEST_SENSE:
+- case TEST_UNIT_READY:
+- case REPORT_LUNS:
+- break; /* only allowable wlun commands */
+- default:
+- if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+- printk(KERN_INFO "scsi_debug: Opcode: 0x%x "
+- "not supported for wlun\n", *cmd);
+- mk_sense_buffer(devip, ILLEGAL_REQUEST,
+- INVALID_OPCODE, 0);
+- errsts = check_condition_result;
+- return schedule_resp(SCpnt, devip, done, errsts,
+- 0);
+- }
+- }
+-
+- switch (*cmd) {
+- case INQUIRY: /* mandatory, ignore unit attention */
+- delay_override = 1;
+- errsts = resp_inquiry(SCpnt, target, devip);
+- break;
+- case REQUEST_SENSE: /* mandatory, ignore unit attention */
+- delay_override = 1;
+- errsts = resp_requests(SCpnt, devip);
+- break;
+- case REZERO_UNIT: /* actually this is REWIND for SSC */
+- case START_STOP:
+- errsts = resp_start_stop(SCpnt, devip);
+- break;
+- case ALLOW_MEDIUM_REMOVAL:
+- if ((errsts = check_readiness(SCpnt, 1, devip)))
+- break;
+- if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+- printk(KERN_INFO "scsi_debug: Medium removal %s\n",
+- cmd[4] ? "inhibited" : "enabled");
+- break;
+- case SEND_DIAGNOSTIC: /* mandatory */
+- errsts = check_readiness(SCpnt, 1, devip);
+- break;
+- case TEST_UNIT_READY: /* mandatory */
+- delay_override = 1;
+- errsts = check_readiness(SCpnt, 0, devip);
+- break;
+- case RESERVE:
+- errsts = check_readiness(SCpnt, 1, devip);
+- break;
+- case RESERVE_10:
+- errsts = check_readiness(SCpnt, 1, devip);
+- break;
+- case RELEASE:
+- errsts = check_readiness(SCpnt, 1, devip);
+- break;
+- case RELEASE_10:
+- errsts = check_readiness(SCpnt, 1, devip);
+- break;
+- case READ_CAPACITY:
+- errsts = resp_readcap(SCpnt, devip);
+- break;
+- case SERVICE_ACTION_IN:
+- if (SAI_READ_CAPACITY_16 != cmd[1]) {
+- mk_sense_buffer(devip, ILLEGAL_REQUEST,
+- INVALID_OPCODE, 0);
+- errsts = check_condition_result;
+- break;
+- }
+- errsts = resp_readcap16(SCpnt, devip);
+- break;
+- case MAINTENANCE_IN:
+- if (MI_REPORT_TARGET_PGS != cmd[1]) {
+- mk_sense_buffer(devip, ILLEGAL_REQUEST,
+- INVALID_OPCODE, 0);
+- errsts = check_condition_result;
+- break;
+- }
+- errsts = resp_report_tgtpgs(SCpnt, devip);
+- break;
+- case READ_16:
+- case READ_12:
+- case READ_10:
+- case READ_6:
+- if ((errsts = check_readiness(SCpnt, 0, devip)))
+- break;
+- if (scsi_debug_fake_rw)
+- break;
+- get_data_transfer_info(cmd, &lba, &num);
+- errsts = resp_read(SCpnt, lba, num, devip);
+- if (inj_recovered && (0 == errsts)) {
+- mk_sense_buffer(devip, RECOVERED_ERROR,
+- THRESHOLD_EXCEEDED, 0);
+- errsts = check_condition_result;
+- } else if (inj_transport && (0 == errsts)) {
+- mk_sense_buffer(devip, ABORTED_COMMAND,
+- TRANSPORT_PROBLEM, ACK_NAK_TO);
+- errsts = check_condition_result;
+- }
+- break;
+- case REPORT_LUNS: /* mandatory, ignore unit attention */
+- delay_override = 1;
+- errsts = resp_report_luns(SCpnt, devip);
+- break;
+- case VERIFY: /* 10 byte SBC-2 command */
+- errsts = check_readiness(SCpnt, 0, devip);
+- break;
+- case WRITE_16:
+- case WRITE_12:
+- case WRITE_10:
+- case WRITE_6:
+- if ((errsts = check_readiness(SCpnt, 0, devip)))
+- break;
+- if (scsi_debug_fake_rw)
+- break;
+- get_data_transfer_info(cmd, &lba, &num);
+- errsts = resp_write(SCpnt, lba, num, devip);
+- if (inj_recovered && (0 == errsts)) {
+- mk_sense_buffer(devip, RECOVERED_ERROR,
+- THRESHOLD_EXCEEDED, 0);
+- errsts = check_condition_result;
+- }
+- break;
+- case MODE_SENSE:
+- case MODE_SENSE_10:
+- errsts = resp_mode_sense(SCpnt, target, devip);
+- break;
+- case MODE_SELECT:
+- errsts = resp_mode_select(SCpnt, 1, devip);
+- break;
+- case MODE_SELECT_10:
+- errsts = resp_mode_select(SCpnt, 0, devip);
+- break;
+- case LOG_SENSE:
+- errsts = resp_log_sense(SCpnt, devip);
+- break;
+- case SYNCHRONIZE_CACHE:
+- delay_override = 1;
+- errsts = check_readiness(SCpnt, 0, devip);
+- break;
+- case WRITE_BUFFER:
+- errsts = check_readiness(SCpnt, 1, devip);
+- break;
+- case XDWRITEREAD_10:
+- if (!scsi_bidi_cmnd(SCpnt)) {
+- mk_sense_buffer(devip, ILLEGAL_REQUEST,
+- INVALID_FIELD_IN_CDB, 0);
+- errsts = check_condition_result;
+- break;
+- }
+-
+- errsts = check_readiness(SCpnt, 0, devip);
+- if (errsts)
+- break;
+- if (scsi_debug_fake_rw)
+- break;
+- get_data_transfer_info(cmd, &lba, &num);
+- errsts = resp_read(SCpnt, lba, num, devip);
+- if (errsts)
+- break;
+- errsts = resp_write(SCpnt, lba, num, devip);
+- if (errsts)
+- break;
+- errsts = resp_xdwriteread(SCpnt, lba, num, devip);
+- break;
+- default:
+- if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+- printk(KERN_INFO "scsi_debug: Opcode: 0x%x not "
+- "supported\n", *cmd);
+- if ((errsts = check_readiness(SCpnt, 1, devip)))
+- break; /* Unit attention takes precedence */
+- mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_OPCODE, 0);
+- errsts = check_condition_result;
+- break;
+- }
+- return schedule_resp(SCpnt, devip, done, errsts,
+- (delay_override ? 0 : scsi_debug_delay));
+-}
+-
+ static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
+ {
+ if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) {
+@@ -613,81 +343,37 @@ static int check_readiness(struct scsi_cmnd * SCpnt, int reset_only,
+ }
+
+ /* Returns 0 if ok else (DID_ERROR << 16). Sets scp->resid . */
+-static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
++static int fill_from_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
+ int arr_len)
+ {
+- int k, req_len, act_len, len, active;
+- void * kaddr;
+- void * kaddr_off;
+- struct scatterlist *sg;
++ int act_len;
+ struct scsi_data_buffer *sdb = scsi_in(scp);
+
+ if (!sdb->length)
+ return 0;
+- if (!sdb->table.sgl)
+- return (DID_ERROR << 16);
+ if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_FROM_DEVICE))
+ return (DID_ERROR << 16);
+- active = 1;
+- req_len = act_len = 0;
+- for_each_sg(sdb->table.sgl, sg, sdb->table.nents, k) {
+- if (active) {
+- kaddr = (unsigned char *)
+- kmap_atomic(sg_page(sg), KM_USER0);
+- if (NULL == kaddr)
+- return (DID_ERROR << 16);
+- kaddr_off = (unsigned char *)kaddr + sg->offset;
+- len = sg->length;
+- if ((req_len + len) > arr_len) {
+- active = 0;
+- len = arr_len - req_len;
+- }
+- memcpy(kaddr_off, arr + req_len, len);
+- kunmap_atomic(kaddr, KM_USER0);
+- act_len += len;
+- }
+- req_len += sg->length;
+- }
++
++ act_len = sg_copy_from_buffer(sdb->table.sgl, sdb->table.nents,
++ arr, arr_len);
+ if (sdb->resid)
+ sdb->resid -= act_len;
+ else
+- sdb->resid = req_len - act_len;
++ sdb->resid = scsi_bufflen(scp) - act_len;
++
+ return 0;
+ }
+
+ /* Returns number of bytes fetched into 'arr' or -1 if error. */
+-static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
+- int max_arr_len)
++static int fetch_to_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
++ int arr_len)
+ {
+- int k, req_len, len, fin;
+- void * kaddr;
+- void * kaddr_off;
+- struct scatterlist * sg;
+-
+- if (0 == scsi_bufflen(scp))
++ if (!scsi_bufflen(scp))
+ return 0;
+- if (NULL == scsi_sglist(scp))
+- return -1;
+ if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_TO_DEVICE))
+ return -1;
+- req_len = fin = 0;
+- scsi_for_each_sg(scp, sg, scsi_sg_count(scp), k) {
+- kaddr = (unsigned char *)kmap_atomic(sg_page(sg), KM_USER0);
+- if (NULL == kaddr)
+- return -1;
+- kaddr_off = (unsigned char *)kaddr + sg->offset;
+- len = sg->length;
+- if ((req_len + len) > max_arr_len) {
+- len = max_arr_len - req_len;
+- fin = 1;
+- }
+- memcpy(arr + req_len, kaddr_off, len);
+- kunmap_atomic(kaddr, KM_USER0);
+- if (fin)
+- return req_len + len;
+- req_len += sg->length;
+- }
+- return req_len;
++
++ return scsi_sg_copy_to_buffer(scp, arr, arr_len);
+ }
+
+
+@@ -1159,6 +845,14 @@ static int resp_start_stop(struct scsi_cmnd * scp,
+ return 0;
+ }
+
++static sector_t get_sdebug_capacity(void)
++{
++ if (scsi_debug_virtual_gb > 0)
++ return 2048 * 1024 * scsi_debug_virtual_gb;
++ else
++ return sdebug_store_sectors;
++}
++
+ #define SDEBUG_READCAP_ARR_SZ 8
+ static int resp_readcap(struct scsi_cmnd * scp,
+ struct sdebug_dev_info * devip)
+@@ -1170,11 +864,7 @@ static int resp_readcap(struct scsi_cmnd * scp,
+ if ((errsts = check_readiness(scp, 1, devip)))
+ return errsts;
+ /* following just in case virtual_gb changed */
+- if (scsi_debug_virtual_gb > 0) {
+- sdebug_capacity = 2048 * 1024;
+- sdebug_capacity *= scsi_debug_virtual_gb;
+- } else
+- sdebug_capacity = sdebug_store_sectors;
++ sdebug_capacity = get_sdebug_capacity();
+ memset(arr, 0, SDEBUG_READCAP_ARR_SZ);
+ if (sdebug_capacity < 0xffffffff) {
+ capac = (unsigned int)sdebug_capacity - 1;
+@@ -1207,11 +897,7 @@ static int resp_readcap16(struct scsi_cmnd * scp,
+ alloc_len = ((cmd[10] << 24) + (cmd[11] << 16) + (cmd[12] << 8)
+ + cmd[13]);
+ /* following just in case virtual_gb changed */
+- if (scsi_debug_virtual_gb > 0) {
+- sdebug_capacity = 2048 * 1024;
+- sdebug_capacity *= scsi_debug_virtual_gb;
+- } else
+- sdebug_capacity = sdebug_store_sectors;
++ sdebug_capacity = get_sdebug_capacity();
+ memset(arr, 0, SDEBUG_READCAP16_ARR_SZ);
+ capac = sdebug_capacity - 1;
+ for (k = 0; k < 8; ++k, capac >>= 8)
+@@ -1505,13 +1191,9 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target,
+ offset = 8;
+ }
+ ap = arr + offset;
+- if ((bd_len > 0) && (0 == sdebug_capacity)) {
+- if (scsi_debug_virtual_gb > 0) {
+- sdebug_capacity = 2048 * 1024;
+- sdebug_capacity *= scsi_debug_virtual_gb;
+- } else
+- sdebug_capacity = sdebug_store_sectors;
+- }
++ if ((bd_len > 0) && (!sdebug_capacity))
++ sdebug_capacity = get_sdebug_capacity();
++
+ if (8 == bd_len) {
+ if (sdebug_capacity > 0xfffffffe) {
+ ap[0] = 0xff;
+@@ -1808,25 +1490,53 @@ static int resp_log_sense(struct scsi_cmnd * scp,
+ min(len, SDEBUG_MAX_INQ_ARR_SZ));
+ }
+
+-static int resp_read(struct scsi_cmnd * SCpnt, unsigned long long lba,
+- unsigned int num, struct sdebug_dev_info * devip)
++static int check_device_access_params(struct sdebug_dev_info *devi,
++ unsigned long long lba, unsigned int num)
+ {
+- unsigned long iflags;
+- unsigned int block, from_bottom;
+- unsigned long long u;
+- int ret;
+-
+ if (lba + num > sdebug_capacity) {
+- mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE,
+- 0);
++ mk_sense_buffer(devi, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, 0);
+ return check_condition_result;
+ }
+ /* transfer length excessive (tie in to block limits VPD page) */
+ if (num > sdebug_store_sectors) {
+- mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
+- 0);
++ mk_sense_buffer(devi, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
+ return check_condition_result;
+ }
++ return 0;
++}
++
++static int do_device_access(struct scsi_cmnd *scmd,
++ struct sdebug_dev_info *devi,
++ unsigned long long lba, unsigned int num, int write)
++{
++ int ret;
++ unsigned int block, rest = 0;
++ int (*func)(struct scsi_cmnd *, unsigned char *, int);
++
++ func = write ? fetch_to_dev_buffer : fill_from_dev_buffer;
++
++ block = do_div(lba, sdebug_store_sectors);
++ if (block + num > sdebug_store_sectors)
++ rest = block + num - sdebug_store_sectors;
++
++ ret = func(scmd, fake_storep + (block * SECT_SIZE),
++ (num - rest) * SECT_SIZE);
++ if (!ret && rest)
++ ret = func(scmd, fake_storep, rest * SECT_SIZE);
++
++ return ret;
++}
++
++static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
++ unsigned int num, struct sdebug_dev_info *devip)
++{
++ unsigned long iflags;
++ int ret;
++
++ ret = check_device_access_params(devip, lba, num);
++ if (ret)
++ return ret;
++
+ if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
+ (lba <= OPT_MEDIUM_ERR_ADDR) &&
+ ((lba + num) > OPT_MEDIUM_ERR_ADDR)) {
+@@ -1845,74 +1555,30 @@ static int resp_read(struct scsi_cmnd * SCpnt, unsigned long long lba,
+ return check_condition_result;
+ }
+ read_lock_irqsave(&atomic_rw, iflags);
+- if ((lba + num) <= sdebug_store_sectors)
+- ret = fill_from_dev_buffer(SCpnt,
+- fake_storep + (lba * SECT_SIZE),
+- num * SECT_SIZE);
+- else {
+- /* modulo when one arg is 64 bits needs do_div() */
+- u = lba;
+- block = do_div(u, sdebug_store_sectors);
+- from_bottom = 0;
+- if ((block + num) > sdebug_store_sectors)
+- from_bottom = (block + num) - sdebug_store_sectors;
+- ret = fill_from_dev_buffer(SCpnt,
+- fake_storep + (block * SECT_SIZE),
+- (num - from_bottom) * SECT_SIZE);
+- if ((0 == ret) && (from_bottom > 0))
+- ret = fill_from_dev_buffer(SCpnt, fake_storep,
+- from_bottom * SECT_SIZE);
+- }
++ ret = do_device_access(SCpnt, devip, lba, num, 0);
+ read_unlock_irqrestore(&atomic_rw, iflags);
+ return ret;
+ }
+
+-static int resp_write(struct scsi_cmnd * SCpnt, unsigned long long lba,
+- unsigned int num, struct sdebug_dev_info * devip)
++static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
++ unsigned int num, struct sdebug_dev_info *devip)
+ {
+ unsigned long iflags;
+- unsigned int block, to_bottom;
+- unsigned long long u;
+- int res;
++ int ret;
+
+- if (lba + num > sdebug_capacity) {
+- mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE,
+- 0);
+- return check_condition_result;
+- }
+- /* transfer length excessive (tie in to block limits VPD page) */
+- if (num > sdebug_store_sectors) {
+- mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
+- 0);
+- return check_condition_result;
+- }
++ ret = check_device_access_params(devip, lba, num);
++ if (ret)
++ return ret;
+
+ write_lock_irqsave(&atomic_rw, iflags);
+- if ((lba + num) <= sdebug_store_sectors)
+- res = fetch_to_dev_buffer(SCpnt,
+- fake_storep + (lba * SECT_SIZE),
+- num * SECT_SIZE);
+- else {
+- /* modulo when one arg is 64 bits needs do_div() */
+- u = lba;
+- block = do_div(u, sdebug_store_sectors);
+- to_bottom = 0;
+- if ((block + num) > sdebug_store_sectors)
+- to_bottom = (block + num) - sdebug_store_sectors;
+- res = fetch_to_dev_buffer(SCpnt,
+- fake_storep + (block * SECT_SIZE),
+- (num - to_bottom) * SECT_SIZE);
+- if ((0 == res) && (to_bottom > 0))
+- res = fetch_to_dev_buffer(SCpnt, fake_storep,
+- to_bottom * SECT_SIZE);
+- }
++ ret = do_device_access(SCpnt, devip, lba, num, 1);
+ write_unlock_irqrestore(&atomic_rw, iflags);
+- if (-1 == res)
++ if (-1 == ret)
+ return (DID_ERROR << 16);
+- else if ((res < (num * SECT_SIZE)) &&
++ else if ((ret < (num * SECT_SIZE)) &&
+ (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
+ printk(KERN_INFO "scsi_debug: write: cdb indicated=%u, "
+- " IO sent=%d bytes\n", num * SECT_SIZE, res);
++ " IO sent=%d bytes\n", num * SECT_SIZE, ret);
+ return 0;
+ }
+
+@@ -1987,16 +1653,7 @@ static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
+ if (!buf)
+ return ret;
+
+- offset = 0;
+- scsi_for_each_sg(scp, sg, scsi_sg_count(scp), i) {
+- kaddr = (unsigned char *)kmap_atomic(sg_page(sg), KM_USER0);
+- if (!kaddr)
+- goto out;
+-
+- memcpy(buf + offset, kaddr + sg->offset, sg->length);
+- offset += sg->length;
+- kunmap_atomic(kaddr, KM_USER0);
+- }
++ scsi_sg_copy_to_buffer(scp, buf, scsi_bufflen(scp));
+
+ offset = 0;
+ for_each_sg(sdb->table.sgl, sg, sdb->table.nents, i) {
+@@ -2045,7 +1702,73 @@ static void timer_intr_handler(unsigned long indx)
+ spin_unlock_irqrestore(&queued_arr_lock, iflags);
+ }
+
+-static int scsi_debug_slave_alloc(struct scsi_device * sdp)
++
++static struct sdebug_dev_info *
++sdebug_device_create(struct sdebug_host_info *sdbg_host, gfp_t flags)
++{
++ struct sdebug_dev_info *devip;
++
++ devip = kzalloc(sizeof(*devip), flags);
++ if (devip) {
++ devip->sdbg_host = sdbg_host;
++ list_add_tail(&devip->dev_list, &sdbg_host->dev_info_list);
++ }
++ return devip;
++}
++
++static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
++{
++ struct sdebug_host_info * sdbg_host;
++ struct sdebug_dev_info * open_devip = NULL;
++ struct sdebug_dev_info * devip =
++ (struct sdebug_dev_info *)sdev->hostdata;
++
++ if (devip)
++ return devip;
++ sdbg_host = *(struct sdebug_host_info **)shost_priv(sdev->host);
++ if (!sdbg_host) {
++ printk(KERN_ERR "Host info NULL\n");
++ return NULL;
++ }
++ list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) {
++ if ((devip->used) && (devip->channel == sdev->channel) &&
++ (devip->target == sdev->id) &&
++ (devip->lun == sdev->lun))
++ return devip;
++ else {
++ if ((!devip->used) && (!open_devip))
++ open_devip = devip;
++ }
++ }
++ if (!open_devip) { /* try and make a new one */
++ open_devip = sdebug_device_create(sdbg_host, GFP_ATOMIC);
++ if (!open_devip) {
++ printk(KERN_ERR "%s: out of memory at line %d\n",
++ __FUNCTION__, __LINE__);
++ return NULL;
++ }
++ }
++
++ open_devip->channel = sdev->channel;
++ open_devip->target = sdev->id;
++ open_devip->lun = sdev->lun;
++ open_devip->sdbg_host = sdbg_host;
++ open_devip->reset = 1;
++ open_devip->used = 1;
++ memset(open_devip->sense_buff, 0, SDEBUG_SENSE_LEN);
++ if (scsi_debug_dsense)
++ open_devip->sense_buff[0] = 0x72;
++ else {
++ open_devip->sense_buff[0] = 0x70;
++ open_devip->sense_buff[7] = 0xa;
++ }
++ if (sdev->lun == SAM2_WLUN_REPORT_LUNS)
++ open_devip->wlun = SAM2_WLUN_REPORT_LUNS & 0xff;
++
++ return open_devip;
++}
++
++static int scsi_debug_slave_alloc(struct scsi_device *sdp)
+ {
+ if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+ printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %u>\n",
+@@ -2054,9 +1777,9 @@ static int scsi_debug_slave_alloc(struct scsi_device * sdp)
+ return 0;
+ }
+
+-static int scsi_debug_slave_configure(struct scsi_device * sdp)
++static int scsi_debug_slave_configure(struct scsi_device *sdp)
+ {
+- struct sdebug_dev_info * devip;
++ struct sdebug_dev_info *devip;
+
+ if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+ printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %u>\n",
+@@ -2074,10 +1797,10 @@ static int scsi_debug_slave_configure(struct scsi_device * sdp)
+ return 0;
+ }
+
+-static void scsi_debug_slave_destroy(struct scsi_device * sdp)
++static void scsi_debug_slave_destroy(struct scsi_device *sdp)
+ {
+- struct sdebug_dev_info * devip =
+- (struct sdebug_dev_info *)sdp->hostdata;
++ struct sdebug_dev_info *devip =
++ (struct sdebug_dev_info *)sdp->hostdata;
+
+ if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+ printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %u>\n",
+@@ -2089,84 +1812,44 @@ static void scsi_debug_slave_destroy(struct scsi_device * sdp)
+ }
+ }
+
+-static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
++/* Returns 1 if found 'cmnd' and deleted its timer. else returns 0 */
++static int stop_queued_cmnd(struct scsi_cmnd *cmnd)
+ {
+- struct sdebug_host_info * sdbg_host;
+- struct sdebug_dev_info * open_devip = NULL;
+- struct sdebug_dev_info * devip =
+- (struct sdebug_dev_info *)sdev->hostdata;
++ unsigned long iflags;
++ int k;
++ struct sdebug_queued_cmd *sqcp;
+
+- if (devip)
+- return devip;
+- sdbg_host = *(struct sdebug_host_info **) sdev->host->hostdata;
+- if(! sdbg_host) {
+- printk(KERN_ERR "Host info NULL\n");
+- return NULL;
+- }
+- list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) {
+- if ((devip->used) && (devip->channel == sdev->channel) &&
+- (devip->target == sdev->id) &&
+- (devip->lun == sdev->lun))
+- return devip;
+- else {
+- if ((!devip->used) && (!open_devip))
+- open_devip = devip;
++ spin_lock_irqsave(&queued_arr_lock, iflags);
++ for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
++ sqcp = &queued_arr[k];
++ if (sqcp->in_use && (cmnd == sqcp->a_cmnd)) {
++ del_timer_sync(&sqcp->cmnd_timer);
++ sqcp->in_use = 0;
++ sqcp->a_cmnd = NULL;
++ break;
+ }
+ }
+- if (NULL == open_devip) { /* try and make a new one */
+- open_devip = kzalloc(sizeof(*open_devip),GFP_ATOMIC);
+- if (NULL == open_devip) {
+- printk(KERN_ERR "%s: out of memory at line %d\n",
+- __FUNCTION__, __LINE__);
+- return NULL;
+- }
+- open_devip->sdbg_host = sdbg_host;
+- list_add_tail(&open_devip->dev_list,
+- &sdbg_host->dev_info_list);
+- }
+- if (open_devip) {
+- open_devip->channel = sdev->channel;
+- open_devip->target = sdev->id;
+- open_devip->lun = sdev->lun;
+- open_devip->sdbg_host = sdbg_host;
+- open_devip->reset = 1;
+- open_devip->used = 1;
+- memset(open_devip->sense_buff, 0, SDEBUG_SENSE_LEN);
+- if (scsi_debug_dsense)
+- open_devip->sense_buff[0] = 0x72;
+- else {
+- open_devip->sense_buff[0] = 0x70;
+- open_devip->sense_buff[7] = 0xa;
+- }
+- if (sdev->lun == SAM2_WLUN_REPORT_LUNS)
+- open_devip->wlun = SAM2_WLUN_REPORT_LUNS & 0xff;
+- return open_devip;
+- }
+- return NULL;
++ spin_unlock_irqrestore(&queued_arr_lock, iflags);
++ return (k < SCSI_DEBUG_CANQUEUE) ? 1 : 0;
+ }
+
+-static void mk_sense_buffer(struct sdebug_dev_info * devip, int key,
+- int asc, int asq)
++/* Deletes (stops) timers of all queued commands */
++static void stop_all_queued(void)
+ {
+- unsigned char * sbuff;
++ unsigned long iflags;
++ int k;
++ struct sdebug_queued_cmd *sqcp;
+
+- sbuff = devip->sense_buff;
+- memset(sbuff, 0, SDEBUG_SENSE_LEN);
+- if (scsi_debug_dsense) {
+- sbuff[0] = 0x72; /* descriptor, current */
+- sbuff[1] = key;
+- sbuff[2] = asc;
+- sbuff[3] = asq;
+- } else {
+- sbuff[0] = 0x70; /* fixed, current */
+- sbuff[2] = key;
+- sbuff[7] = 0xa; /* implies 18 byte sense buffer */
+- sbuff[12] = asc;
+- sbuff[13] = asq;
++ spin_lock_irqsave(&queued_arr_lock, iflags);
++ for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
++ sqcp = &queued_arr[k];
++ if (sqcp->in_use && sqcp->a_cmnd) {
++ del_timer_sync(&sqcp->cmnd_timer);
++ sqcp->in_use = 0;
++ sqcp->a_cmnd = NULL;
++ }
+ }
+- if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+- printk(KERN_INFO "scsi_debug: [sense_key,asc,ascq]: "
+- "[0x%x,0x%x,0x%x]\n", key, asc, asq);
++ spin_unlock_irqrestore(&queued_arr_lock, iflags);
+ }
+
+ static int scsi_debug_abort(struct scsi_cmnd * SCpnt)
+@@ -2226,7 +1909,7 @@ static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt)
+ printk(KERN_INFO "scsi_debug: bus_reset\n");
+ ++num_bus_resets;
+ if (SCpnt && ((sdp = SCpnt->device)) && ((hp = sdp->host))) {
+- sdbg_host = *(struct sdebug_host_info **) hp->hostdata;
++ sdbg_host = *(struct sdebug_host_info **)shost_priv(hp);
+ if (sdbg_host) {
+ list_for_each_entry(dev_info,
+ &sdbg_host->dev_info_list,
+@@ -2256,46 +1939,6 @@ static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt)
+ return SUCCESS;
+ }
+
+-/* Returns 1 if found 'cmnd' and deleted its timer. else returns 0 */
+-static int stop_queued_cmnd(struct scsi_cmnd * cmnd)
+-{
+- unsigned long iflags;
+- int k;
+- struct sdebug_queued_cmd * sqcp;
+-
+- spin_lock_irqsave(&queued_arr_lock, iflags);
+- for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
+- sqcp = &queued_arr[k];
+- if (sqcp->in_use && (cmnd == sqcp->a_cmnd)) {
+- del_timer_sync(&sqcp->cmnd_timer);
+- sqcp->in_use = 0;
+- sqcp->a_cmnd = NULL;
+- break;
+- }
+- }
+- spin_unlock_irqrestore(&queued_arr_lock, iflags);
+- return (k < SCSI_DEBUG_CANQUEUE) ? 1 : 0;
+-}
+-
+-/* Deletes (stops) timers of all queued commands */
+-static void stop_all_queued(void)
+-{
+- unsigned long iflags;
+- int k;
+- struct sdebug_queued_cmd * sqcp;
+-
+- spin_lock_irqsave(&queued_arr_lock, iflags);
+- for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) {
+- sqcp = &queued_arr[k];
+- if (sqcp->in_use && sqcp->a_cmnd) {
+- del_timer_sync(&sqcp->cmnd_timer);
+- sqcp->in_use = 0;
+- sqcp->a_cmnd = NULL;
+- }
+- }
+- spin_unlock_irqrestore(&queued_arr_lock, iflags);
+-}
+-
+ /* Initializes timers in queued array */
+ static void __init init_all_queued(void)
+ {
+@@ -2313,7 +1956,8 @@ static void __init init_all_queued(void)
+ spin_unlock_irqrestore(&queued_arr_lock, iflags);
+ }
+
+-static void __init sdebug_build_parts(unsigned char * ramp)
++static void __init sdebug_build_parts(unsigned char *ramp,
++ unsigned long store_size)
+ {
+ struct partition * pp;
+ int starts[SDEBUG_MAX_PARTS + 2];
+@@ -2321,7 +1965,7 @@ static void __init sdebug_build_parts(unsigned char * ramp)
+ int heads_by_sects, start_sec, end_sec;
+
+ /* assume partition table already zeroed */
+- if ((scsi_debug_num_parts < 1) || (sdebug_store_size < 1048576))
++ if ((scsi_debug_num_parts < 1) || (store_size < 1048576))
+ return;
+ if (scsi_debug_num_parts > SDEBUG_MAX_PARTS) {
+ scsi_debug_num_parts = SDEBUG_MAX_PARTS;
+@@ -2419,7 +2063,6 @@ static int schedule_resp(struct scsi_cmnd * cmnd,
+ return 0;
+ }
+ }
+-
+ /* Note: The following macros create attribute files in the
+ /sys/module/scsi_debug/parameters directory. Unfortunately this
+ driver is unaware of a change and cannot trigger auxiliary actions
+@@ -2736,11 +2379,9 @@ static ssize_t sdebug_virtual_gb_store(struct device_driver * ddp,
+
+ if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
+ scsi_debug_virtual_gb = n;
+- if (scsi_debug_virtual_gb > 0) {
+- sdebug_capacity = 2048 * 1024;
+- sdebug_capacity *= scsi_debug_virtual_gb;
+- } else
+- sdebug_capacity = sdebug_store_sectors;
++
++ sdebug_capacity = get_sdebug_capacity();
++
+ return count;
+ }
+ return -EINVAL;
+@@ -2756,21 +2397,10 @@ static ssize_t sdebug_add_host_show(struct device_driver * ddp, char * buf)
+ static ssize_t sdebug_add_host_store(struct device_driver * ddp,
+ const char * buf, size_t count)
+ {
+- int delta_hosts;
+- char work[20];
++ int delta_hosts;
+
+- if (1 != sscanf(buf, "%10s", work))
++ if (sscanf(buf, "%d", &delta_hosts) != 1)
+ return -EINVAL;
+- { /* temporary hack around sscanf() problem with -ve nums */
+- int neg = 0;
+-
+- if ('-' == *work)
+- neg = 1;
+- if (1 != sscanf(work + neg, "%d", &delta_hosts))
+- return -EINVAL;
+- if (neg)
+- delta_hosts = -delta_hosts;
+- }
+ if (delta_hosts > 0) {
+ do {
+ sdebug_add_adapter();
+@@ -2782,7 +2412,7 @@ static ssize_t sdebug_add_host_store(struct device_driver * ddp,
+ }
+ return count;
+ }
+-DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_show,
++DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_show,
+ sdebug_add_host_store);
+
+ static ssize_t sdebug_vpd_use_hostno_show(struct device_driver * ddp,
+@@ -2851,22 +2481,29 @@ static void do_remove_driverfs_files(void)
+ driver_remove_file(&sdebug_driverfs_driver, &driver_attr_add_host);
+ }
+
++static void pseudo_0_release(struct device *dev)
++{
++ if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
++ printk(KERN_INFO "scsi_debug: pseudo_0_release() called\n");
++}
++
++static struct device pseudo_primary = {
++ .bus_id = "pseudo_0",
++ .release = pseudo_0_release,
++};
++
+ static int __init scsi_debug_init(void)
+ {
+- unsigned int sz;
++ unsigned long sz;
+ int host_to_add;
+ int k;
+ int ret;
+
+ if (scsi_debug_dev_size_mb < 1)
+ scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */
+- sdebug_store_size = (unsigned int)scsi_debug_dev_size_mb * 1048576;
+- sdebug_store_sectors = sdebug_store_size / SECT_SIZE;
+- if (scsi_debug_virtual_gb > 0) {
+- sdebug_capacity = 2048 * 1024;
+- sdebug_capacity *= scsi_debug_virtual_gb;
+- } else
+- sdebug_capacity = sdebug_store_sectors;
++ sz = (unsigned long)scsi_debug_dev_size_mb * 1048576;
++ sdebug_store_sectors = sz / SECT_SIZE;
++ sdebug_capacity = get_sdebug_capacity();
+
+ /* play around with geometry, don't waste too much on track 0 */
+ sdebug_heads = 8;
+@@ -2885,7 +2522,6 @@ static int __init scsi_debug_init(void)
+ (sdebug_sectors_per * sdebug_heads);
+ }
+
+- sz = sdebug_store_size;
+ fake_storep = vmalloc(sz);
+ if (NULL == fake_storep) {
+ printk(KERN_ERR "scsi_debug_init: out of memory, 1\n");
+@@ -2893,7 +2529,7 @@ static int __init scsi_debug_init(void)
+ }
+ memset(fake_storep, 0, sz);
+ if (scsi_debug_num_parts > 0)
+- sdebug_build_parts(fake_storep);
++ sdebug_build_parts(fake_storep, sz);
+
+ ret = device_register(&pseudo_primary);
+ if (ret < 0) {
+@@ -2922,8 +2558,6 @@ static int __init scsi_debug_init(void)
+
+ init_all_queued();
+
+- sdebug_driver_template.proc_name = sdebug_proc_name;
+-
+ host_to_add = scsi_debug_add_host;
+ scsi_debug_add_host = 0;
+
+@@ -2972,30 +2606,6 @@ static void __exit scsi_debug_exit(void)
+ device_initcall(scsi_debug_init);
+ module_exit(scsi_debug_exit);
+
+-static void pseudo_0_release(struct device * dev)
+-{
+- if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+- printk(KERN_INFO "scsi_debug: pseudo_0_release() called\n");
+-}
+-
+-static struct device pseudo_primary = {
+- .bus_id = "pseudo_0",
+- .release = pseudo_0_release,
+-};
+-
+-static int pseudo_lld_bus_match(struct device *dev,
+- struct device_driver *dev_driver)
+-{
+- return 1;
+-}
+-
+-static struct bus_type pseudo_lld_bus = {
+- .name = "pseudo",
+- .match = pseudo_lld_bus_match,
+- .probe = sdebug_driver_probe,
+- .remove = sdebug_driver_remove,
+-};
+-
+ static void sdebug_release_adapter(struct device * dev)
+ {
+ struct sdebug_host_info *sdbg_host;
+@@ -3009,8 +2619,7 @@ static int sdebug_add_adapter(void)
+ int k, devs_per_host;
+ int error = 0;
+ struct sdebug_host_info *sdbg_host;
+- struct sdebug_dev_info *sdbg_devinfo;
+- struct list_head *lh, *lh_sf;
++ struct sdebug_dev_info *sdbg_devinfo, *tmp;
+
+ sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL);
+ if (NULL == sdbg_host) {
+@@ -3023,16 +2632,13 @@ static int sdebug_add_adapter(void)
+
+ devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns;
+ for (k = 0; k < devs_per_host; k++) {
+- sdbg_devinfo = kzalloc(sizeof(*sdbg_devinfo),GFP_KERNEL);
+- if (NULL == sdbg_devinfo) {
++ sdbg_devinfo = sdebug_device_create(sdbg_host, GFP_KERNEL);
++ if (!sdbg_devinfo) {
+ printk(KERN_ERR "%s: out of memory at line %d\n",
+ __FUNCTION__, __LINE__);
+ error = -ENOMEM;
+ goto clean;
+ }
+- sdbg_devinfo->sdbg_host = sdbg_host;
+- list_add_tail(&sdbg_devinfo->dev_list,
+- &sdbg_host->dev_info_list);
+ }
+
+ spin_lock(&sdebug_host_list_lock);
+@@ -3053,9 +2659,8 @@ static int sdebug_add_adapter(void)
+ return error;
+
+ clean:
+- list_for_each_safe(lh, lh_sf, &sdbg_host->dev_info_list) {
+- sdbg_devinfo = list_entry(lh, struct sdebug_dev_info,
+- dev_list);
++ list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list,
++ dev_list) {
+ list_del(&sdbg_devinfo->dev_list);
+ kfree(sdbg_devinfo);
+ }
+@@ -3083,6 +2688,263 @@ static void sdebug_remove_adapter(void)
+ --scsi_debug_add_host;
+ }
+
++static
++int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
++{
++ unsigned char *cmd = (unsigned char *) SCpnt->cmnd;
++ int len, k;
++ unsigned int num;
++ unsigned long long lba;
++ int errsts = 0;
++ int target = SCpnt->device->id;
++ struct sdebug_dev_info *devip = NULL;
++ int inj_recovered = 0;
++ int inj_transport = 0;
++ int delay_override = 0;
++
++ scsi_set_resid(SCpnt, 0);
++ if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmd) {
++ printk(KERN_INFO "scsi_debug: cmd ");
++ for (k = 0, len = SCpnt->cmd_len; k < len; ++k)
++ printk("%02x ", (int)cmd[k]);
++ printk("\n");
++ }
++
++ if (target == SCpnt->device->host->hostt->this_id) {
++ printk(KERN_INFO "scsi_debug: initiator's id used as "
++ "target!\n");
++ return schedule_resp(SCpnt, NULL, done,
++ DID_NO_CONNECT << 16, 0);
++ }
++
++ if ((SCpnt->device->lun >= scsi_debug_max_luns) &&
++ (SCpnt->device->lun != SAM2_WLUN_REPORT_LUNS))
++ return schedule_resp(SCpnt, NULL, done,
++ DID_NO_CONNECT << 16, 0);
++ devip = devInfoReg(SCpnt->device);
++ if (NULL == devip)
++ return schedule_resp(SCpnt, NULL, done,
++ DID_NO_CONNECT << 16, 0);
++
++ if ((scsi_debug_every_nth != 0) &&
++ (++scsi_debug_cmnd_count >= abs(scsi_debug_every_nth))) {
++ scsi_debug_cmnd_count = 0;
++ if (scsi_debug_every_nth < -1)
++ scsi_debug_every_nth = -1;
++ if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
++ return 0; /* ignore command causing timeout */
++ else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts)
++ inj_recovered = 1; /* to reads and writes below */
++ else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts)
++ inj_transport = 1; /* to reads and writes below */
++ }
++
++ if (devip->wlun) {
++ switch (*cmd) {
++ case INQUIRY:
++ case REQUEST_SENSE:
++ case TEST_UNIT_READY:
++ case REPORT_LUNS:
++ break; /* only allowable wlun commands */
++ default:
++ if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
++ printk(KERN_INFO "scsi_debug: Opcode: 0x%x "
++ "not supported for wlun\n", *cmd);
++ mk_sense_buffer(devip, ILLEGAL_REQUEST,
++ INVALID_OPCODE, 0);
++ errsts = check_condition_result;
++ return schedule_resp(SCpnt, devip, done, errsts,
++ 0);
++ }
++ }
++
++ switch (*cmd) {
++ case INQUIRY: /* mandatory, ignore unit attention */
++ delay_override = 1;
++ errsts = resp_inquiry(SCpnt, target, devip);
++ break;
++ case REQUEST_SENSE: /* mandatory, ignore unit attention */
++ delay_override = 1;
++ errsts = resp_requests(SCpnt, devip);
++ break;
++ case REZERO_UNIT: /* actually this is REWIND for SSC */
++ case START_STOP:
++ errsts = resp_start_stop(SCpnt, devip);
++ break;
++ case ALLOW_MEDIUM_REMOVAL:
++ errsts = check_readiness(SCpnt, 1, devip);
++ if (errsts)
++ break;
++ if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
++ printk(KERN_INFO "scsi_debug: Medium removal %s\n",
++ cmd[4] ? "inhibited" : "enabled");
++ break;
++ case SEND_DIAGNOSTIC: /* mandatory */
++ errsts = check_readiness(SCpnt, 1, devip);
++ break;
++ case TEST_UNIT_READY: /* mandatory */
++ delay_override = 1;
++ errsts = check_readiness(SCpnt, 0, devip);
++ break;
++ case RESERVE:
++ errsts = check_readiness(SCpnt, 1, devip);
++ break;
++ case RESERVE_10:
++ errsts = check_readiness(SCpnt, 1, devip);
++ break;
++ case RELEASE:
++ errsts = check_readiness(SCpnt, 1, devip);
++ break;
++ case RELEASE_10:
++ errsts = check_readiness(SCpnt, 1, devip);
++ break;
++ case READ_CAPACITY:
++ errsts = resp_readcap(SCpnt, devip);
++ break;
++ case SERVICE_ACTION_IN:
++ if (SAI_READ_CAPACITY_16 != cmd[1]) {
++ mk_sense_buffer(devip, ILLEGAL_REQUEST,
++ INVALID_OPCODE, 0);
++ errsts = check_condition_result;
++ break;
++ }
++ errsts = resp_readcap16(SCpnt, devip);
++ break;
++ case MAINTENANCE_IN:
++ if (MI_REPORT_TARGET_PGS != cmd[1]) {
++ mk_sense_buffer(devip, ILLEGAL_REQUEST,
++ INVALID_OPCODE, 0);
++ errsts = check_condition_result;
++ break;
++ }
++ errsts = resp_report_tgtpgs(SCpnt, devip);
++ break;
++ case READ_16:
++ case READ_12:
++ case READ_10:
++ case READ_6:
++ errsts = check_readiness(SCpnt, 0, devip);
++ if (errsts)
++ break;
++ if (scsi_debug_fake_rw)
++ break;
++ get_data_transfer_info(cmd, &lba, &num);
++ errsts = resp_read(SCpnt, lba, num, devip);
++ if (inj_recovered && (0 == errsts)) {
++ mk_sense_buffer(devip, RECOVERED_ERROR,
++ THRESHOLD_EXCEEDED, 0);
++ errsts = check_condition_result;
++ } else if (inj_transport && (0 == errsts)) {
++ mk_sense_buffer(devip, ABORTED_COMMAND,
++ TRANSPORT_PROBLEM, ACK_NAK_TO);
++ errsts = check_condition_result;
++ }
++ break;
++ case REPORT_LUNS: /* mandatory, ignore unit attention */
++ delay_override = 1;
++ errsts = resp_report_luns(SCpnt, devip);
++ break;
++ case VERIFY: /* 10 byte SBC-2 command */
++ errsts = check_readiness(SCpnt, 0, devip);
++ break;
++ case WRITE_16:
++ case WRITE_12:
++ case WRITE_10:
++ case WRITE_6:
++ errsts = check_readiness(SCpnt, 0, devip);
++ if (errsts)
++ break;
++ if (scsi_debug_fake_rw)
++ break;
++ get_data_transfer_info(cmd, &lba, &num);
++ errsts = resp_write(SCpnt, lba, num, devip);
++ if (inj_recovered && (0 == errsts)) {
++ mk_sense_buffer(devip, RECOVERED_ERROR,
++ THRESHOLD_EXCEEDED, 0);
++ errsts = check_condition_result;
++ }
++ break;
++ case MODE_SENSE:
++ case MODE_SENSE_10:
++ errsts = resp_mode_sense(SCpnt, target, devip);
++ break;
++ case MODE_SELECT:
++ errsts = resp_mode_select(SCpnt, 1, devip);
++ break;
++ case MODE_SELECT_10:
++ errsts = resp_mode_select(SCpnt, 0, devip);
++ break;
++ case LOG_SENSE:
++ errsts = resp_log_sense(SCpnt, devip);
++ break;
++ case SYNCHRONIZE_CACHE:
++ delay_override = 1;
++ errsts = check_readiness(SCpnt, 0, devip);
++ break;
++ case WRITE_BUFFER:
++ errsts = check_readiness(SCpnt, 1, devip);
++ break;
++ case XDWRITEREAD_10:
++ if (!scsi_bidi_cmnd(SCpnt)) {
++ mk_sense_buffer(devip, ILLEGAL_REQUEST,
++ INVALID_FIELD_IN_CDB, 0);
++ errsts = check_condition_result;
++ break;
++ }
++
++ errsts = check_readiness(SCpnt, 0, devip);
++ if (errsts)
++ break;
++ if (scsi_debug_fake_rw)
++ break;
++ get_data_transfer_info(cmd, &lba, &num);
++ errsts = resp_read(SCpnt, lba, num, devip);
++ if (errsts)
++ break;
++ errsts = resp_write(SCpnt, lba, num, devip);
++ if (errsts)
++ break;
++ errsts = resp_xdwriteread(SCpnt, lba, num, devip);
++ break;
++ default:
++ if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
++ printk(KERN_INFO "scsi_debug: Opcode: 0x%x not "
++ "supported\n", *cmd);
++ errsts = check_readiness(SCpnt, 1, devip);
++ if (errsts)
++ break; /* Unit attention takes precedence */
++ mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_OPCODE, 0);
++ errsts = check_condition_result;
++ break;
++ }
++ return schedule_resp(SCpnt, devip, done, errsts,
++ (delay_override ? 0 : scsi_debug_delay));
++}
++
++static struct scsi_host_template sdebug_driver_template = {
++ .proc_info = scsi_debug_proc_info,
++ .proc_name = sdebug_proc_name,
++ .name = "SCSI DEBUG",
++ .info = scsi_debug_info,
++ .slave_alloc = scsi_debug_slave_alloc,
++ .slave_configure = scsi_debug_slave_configure,
++ .slave_destroy = scsi_debug_slave_destroy,
++ .ioctl = scsi_debug_ioctl,
++ .queuecommand = scsi_debug_queuecommand,
++ .eh_abort_handler = scsi_debug_abort,
++ .eh_bus_reset_handler = scsi_debug_bus_reset,
++ .eh_device_reset_handler = scsi_debug_device_reset,
++ .eh_host_reset_handler = scsi_debug_host_reset,
++ .bios_param = scsi_debug_biosparam,
++ .can_queue = SCSI_DEBUG_CANQUEUE,
++ .this_id = 7,
++ .sg_tablesize = 256,
++ .cmd_per_lun = 16,
++ .max_sectors = 0xffff,
++ .use_clustering = DISABLE_CLUSTERING,
++ .module = THIS_MODULE,
++};
++
+ static int sdebug_driver_probe(struct device * dev)
+ {
+ int error = 0;
+@@ -3120,9 +2982,8 @@ static int sdebug_driver_probe(struct device * dev)
+
+ static int sdebug_driver_remove(struct device * dev)
+ {
+- struct list_head *lh, *lh_sf;
+ struct sdebug_host_info *sdbg_host;
+- struct sdebug_dev_info *sdbg_devinfo;
++ struct sdebug_dev_info *sdbg_devinfo, *tmp;
+
+ sdbg_host = to_sdebug_host(dev);
+
+@@ -3134,9 +2995,8 @@ static int sdebug_driver_remove(struct device * dev)
+
+ scsi_remove_host(sdbg_host->shost);
+
+- list_for_each_safe(lh, lh_sf, &sdbg_host->dev_info_list) {
+- sdbg_devinfo = list_entry(lh, struct sdebug_dev_info,
+- dev_list);
++ list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list,
++ dev_list) {
+ list_del(&sdbg_devinfo->dev_list);
+ kfree(sdbg_devinfo);
+ }
+@@ -3145,20 +3005,15 @@ static int sdebug_driver_remove(struct device * dev)
+ return 0;
+ }
+
+-static void sdebug_max_tgts_luns(void)
++static int pseudo_lld_bus_match(struct device *dev,
++ struct device_driver *dev_driver)
+ {
+- struct sdebug_host_info * sdbg_host;
+- struct Scsi_Host *hpnt;
+-
+- spin_lock(&sdebug_host_list_lock);
+- list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
+- hpnt = sdbg_host->shost;
+- if ((hpnt->this_id >= 0) &&
+- (scsi_debug_num_tgts > hpnt->this_id))
+- hpnt->max_id = scsi_debug_num_tgts + 1;
+- else
+- hpnt->max_id = scsi_debug_num_tgts;
+- hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; /* scsi_debug_max_luns; */
+- }
+- spin_unlock(&sdebug_host_list_lock);
++ return 1;
+ }
++
++static struct bus_type pseudo_lld_bus = {
++ .name = "pseudo",
++ .match = pseudo_lld_bus_match,
++ .probe = sdebug_driver_probe,
++ .remove = sdebug_driver_remove,
++};
+diff --git a/drivers/scsi/scsi_debug.h b/drivers/scsi/scsi_debug.h
+deleted file mode 100644
+index 965dd5e..0000000
+--- a/drivers/scsi/scsi_debug.h
++++ /dev/null
+@@ -1,24 +0,0 @@
+-#ifndef _SCSI_DEBUG_H
+-
+-#include <linux/types.h>
+-
+-static int scsi_debug_slave_alloc(struct scsi_device *);
+-static int scsi_debug_slave_configure(struct scsi_device *);
+-static void scsi_debug_slave_destroy(struct scsi_device *);
+-static int scsi_debug_queuecommand(struct scsi_cmnd *,
+- void (*done) (struct scsi_cmnd *));
+-static int scsi_debug_ioctl(struct scsi_device *, int, void __user *);
+-static int scsi_debug_biosparam(struct scsi_device *, struct block_device *,
+- sector_t, int[]);
+-static int scsi_debug_abort(struct scsi_cmnd *);
+-static int scsi_debug_bus_reset(struct scsi_cmnd *);
+-static int scsi_debug_device_reset(struct scsi_cmnd *);
+-static int scsi_debug_host_reset(struct scsi_cmnd *);
+-static int scsi_debug_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
+-static const char * scsi_debug_info(struct Scsi_Host *);
+-
+-#define SCSI_DEBUG_CANQUEUE 255 /* needs to be >= 1 */
+-
+-#define SCSI_DEBUG_MAX_CMD_LEN 16
+-
+-#endif
+diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
+index 045a086..221f31e 100644
+--- a/drivers/scsi/scsi_error.c
++++ b/drivers/scsi/scsi_error.c
+@@ -524,6 +524,41 @@ static int scsi_try_bus_reset(struct scsi_cmnd *scmd)
+ return rtn;
+ }
+
++static void __scsi_report_device_reset(struct scsi_device *sdev, void *data)
++{
++ sdev->was_reset = 1;
++ sdev->expecting_cc_ua = 1;
++}
++
++/**
++ * scsi_try_target_reset - Ask host to perform a target reset
++ * @scmd: SCSI cmd used to send a target reset
++ *
++ * Notes:
++ * There is no timeout for this operation. if this operation is
++ * unreliable for a given host, then the host itself needs to put a
++ * timer on it, and set the host back to a consistent state prior to
++ * returning.
++ */
++static int scsi_try_target_reset(struct scsi_cmnd *scmd)
++{
++ unsigned long flags;
++ int rtn;
++
++ if (!scmd->device->host->hostt->eh_target_reset_handler)
++ return FAILED;
++
++ rtn = scmd->device->host->hostt->eh_target_reset_handler(scmd);
++ if (rtn == SUCCESS) {
++ spin_lock_irqsave(scmd->device->host->host_lock, flags);
++ __starget_for_each_device(scsi_target(scmd->device), NULL,
++ __scsi_report_device_reset);
++ spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
++ }
++
++ return rtn;
++}
++
+ /**
+ * scsi_try_bus_device_reset - Ask host to perform a BDR on a dev
+ * @scmd: SCSI cmd used to send BDR
+@@ -542,11 +577,8 @@ static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
+ return FAILED;
+
+ rtn = scmd->device->host->hostt->eh_device_reset_handler(scmd);
+- if (rtn == SUCCESS) {
+- scmd->device->was_reset = 1;
+- scmd->device->expecting_cc_ua = 1;
+- }
+-
++ if (rtn == SUCCESS)
++ __scsi_report_device_reset(scmd->device, NULL);
+ return rtn;
+ }
+
+@@ -584,8 +616,9 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
+ {
+ if (__scsi_try_to_abort_cmd(scmd) != SUCCESS)
+ if (scsi_try_bus_device_reset(scmd) != SUCCESS)
+- if (scsi_try_bus_reset(scmd) != SUCCESS)
+- scsi_try_host_reset(scmd);
++ if (scsi_try_target_reset(scmd) != SUCCESS)
++ if (scsi_try_bus_reset(scmd) != SUCCESS)
++ scsi_try_host_reset(scmd);
+ }
+
+ /**
+@@ -1060,6 +1093,56 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
+ }
+
+ /**
++ * scsi_eh_target_reset - send target reset if needed
++ * @shost: scsi host being recovered.
++ * @work_q: &list_head for pending commands.
++ * @done_q: &list_head for processed commands.
++ *
++ * Notes:
++ * Try a target reset.
++ */
++static int scsi_eh_target_reset(struct Scsi_Host *shost,
++ struct list_head *work_q,
++ struct list_head *done_q)
++{
++ struct scsi_cmnd *scmd, *tgtr_scmd, *next;
++ unsigned int id;
++ int rtn;
++
++ for (id = 0; id <= shost->max_id; id++) {
++ tgtr_scmd = NULL;
++ list_for_each_entry(scmd, work_q, eh_entry) {
++ if (id == scmd_id(scmd)) {
++ tgtr_scmd = scmd;
++ break;
++ }
++ }
++ if (!tgtr_scmd)
++ continue;
++
++ SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending target reset "
++ "to target %d\n",
++ current->comm, id));
++ rtn = scsi_try_target_reset(tgtr_scmd);
++ if (rtn == SUCCESS) {
++ list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
++ if (id == scmd_id(scmd))
++ if (!scsi_device_online(scmd->device) ||
++ !scsi_eh_tur(tgtr_scmd))
++ scsi_eh_finish_cmd(scmd,
++ done_q);
++ }
++ } else
++ SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Target reset"
++ " failed target: "
++ "%d\n",
++ current->comm, id));
++ }
++
++ return list_empty(work_q);
++}
++
++/**
+ * scsi_eh_bus_reset - send a bus reset
+ * @shost: &scsi host being recovered.
+ * @work_q: &list_head for pending commands.
+@@ -1447,9 +1530,11 @@ void scsi_eh_ready_devs(struct Scsi_Host *shost,
+ {
+ if (!scsi_eh_stu(shost, work_q, done_q))
+ if (!scsi_eh_bus_device_reset(shost, work_q, done_q))
+- if (!scsi_eh_bus_reset(shost, work_q, done_q))
+- if (!scsi_eh_host_reset(work_q, done_q))
+- scsi_eh_offline_sdevs(work_q, done_q);
++ if (!scsi_eh_target_reset(shost, work_q, done_q))
++ if (!scsi_eh_bus_reset(shost, work_q, done_q))
++ if (!scsi_eh_host_reset(work_q, done_q))
++ scsi_eh_offline_sdevs(work_q,
++ done_q);
+ }
+ EXPORT_SYMBOL_GPL(scsi_eh_ready_devs);
+
+@@ -1619,10 +1704,8 @@ void scsi_report_bus_reset(struct Scsi_Host *shost, int channel)
+ struct scsi_device *sdev;
+
+ __shost_for_each_device(sdev, shost) {
+- if (channel == sdev_channel(sdev)) {
+- sdev->was_reset = 1;
+- sdev->expecting_cc_ua = 1;
+- }
++ if (channel == sdev_channel(sdev))
++ __scsi_report_device_reset(sdev, NULL);
+ }
+ }
+ EXPORT_SYMBOL(scsi_report_bus_reset);
+@@ -1655,10 +1738,8 @@ void scsi_report_device_reset(struct Scsi_Host *shost, int channel, int target)
+
+ __shost_for_each_device(sdev, shost) {
+ if (channel == sdev_channel(sdev) &&
+- target == sdev_id(sdev)) {
+- sdev->was_reset = 1;
+- sdev->expecting_cc_ua = 1;
+- }
++ target == sdev_id(sdev))
++ __scsi_report_device_reset(sdev, NULL);
+ }
+ }
+ EXPORT_SYMBOL(scsi_report_device_reset);
+@@ -1714,6 +1795,11 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
+ if (rtn == SUCCESS)
+ break;
+ /* FALLTHROUGH */
++ case SCSI_TRY_RESET_TARGET:
++ rtn = scsi_try_target_reset(scmd);
++ if (rtn == SUCCESS)
++ break;
++ /* FALLTHROUGH */
+ case SCSI_TRY_RESET_BUS:
+ rtn = scsi_try_bus_reset(scmd);
+ if (rtn == SUCCESS)
+@@ -1907,3 +1993,31 @@ int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len,
+ }
+ }
+ EXPORT_SYMBOL(scsi_get_sense_info_fld);
++
++/**
++ * scsi_build_sense_buffer - build sense data in a buffer
++ * @desc: Sense format (non zero == descriptor format,
++ * 0 == fixed format)
++ * @buf: Where to build sense data
++ * @key: Sense key
++ * @asc: Additional sense code
++ * @ascq: Additional sense code qualifier
++ *
++ **/
++void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq)
++{
++ if (desc) {
++ buf[0] = 0x72; /* descriptor, current */
++ buf[1] = key;
++ buf[2] = asc;
++ buf[3] = ascq;
++ buf[7] = 0;
++ } else {
++ buf[0] = 0x70; /* fixed, current */
++ buf[2] = key;
++ buf[7] = 0xa;
++ buf[12] = asc;
++ buf[13] = ascq;
++ }
++}
++EXPORT_SYMBOL(scsi_build_sense_buffer);
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index f40898d..67f412b 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -784,7 +784,7 @@ EXPORT_SYMBOL(scsi_release_buffers);
+ * in req->data_len and req->next_rq->data_len. The upper-layer driver can
+ * decide what to do with this information.
+ */
+-void scsi_end_bidi_request(struct scsi_cmnd *cmd)
++static void scsi_end_bidi_request(struct scsi_cmnd *cmd)
+ {
+ struct request *req = cmd->request;
+ unsigned int dlen = req->data_len;
+@@ -839,7 +839,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
+ int this_count = scsi_bufflen(cmd);
+ struct request_queue *q = cmd->device->request_queue;
+ struct request *req = cmd->request;
+- int clear_errors = 1;
++ int error = 0;
+ struct scsi_sense_hdr sshdr;
+ int sense_valid = 0;
+ int sense_deferred = 0;
+@@ -853,7 +853,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
+ if (blk_pc_request(req)) { /* SG_IO ioctl from block level */
+ req->errors = result;
+ if (result) {
+- clear_errors = 0;
+ if (sense_valid && req->sense) {
+ /*
+ * SG_IO wants current and deferred errors
+@@ -865,6 +864,8 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
+ memcpy(req->sense, cmd->sense_buffer, len);
+ req->sense_len = len;
+ }
++ if (!sense_deferred)
++ error = -EIO;
+ }
+ if (scsi_bidi_cmnd(cmd)) {
+ /* will also release_buffers */
+@@ -885,14 +886,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
+ "%d bytes done.\n",
+ req->nr_sectors, good_bytes));
+
+- if (clear_errors)
+- req->errors = 0;
+-
+ /* A number of bytes were successfully read. If there
+ * are leftovers and there is some kind of error
+ * (result != 0), retry the rest.
+ */
+- if (scsi_end_request(cmd, 0, good_bytes, result == 0) == NULL)
++ if (scsi_end_request(cmd, error, good_bytes, result == 0) == NULL)
+ return;
+
+ /* good_bytes = 0, or (inclusive) there were leftovers and
+diff --git a/drivers/scsi/scsi_sas_internal.h b/drivers/scsi/scsi_sas_internal.h
+index e1edab4..998cb5b 100644
+--- a/drivers/scsi/scsi_sas_internal.h
++++ b/drivers/scsi/scsi_sas_internal.h
+@@ -13,12 +13,12 @@ struct sas_internal {
+ struct sas_function_template *f;
+ struct sas_domain_function_template *dft;
+
+- struct class_device_attribute private_host_attrs[SAS_HOST_ATTRS];
+- struct class_device_attribute private_phy_attrs[SAS_PHY_ATTRS];
+- struct class_device_attribute private_port_attrs[SAS_PORT_ATTRS];
+- struct class_device_attribute private_rphy_attrs[SAS_RPORT_ATTRS];
+- struct class_device_attribute private_end_dev_attrs[SAS_END_DEV_ATTRS];
+- struct class_device_attribute private_expander_attrs[SAS_EXPANDER_ATTRS];
++ struct device_attribute private_host_attrs[SAS_HOST_ATTRS];
++ struct device_attribute private_phy_attrs[SAS_PHY_ATTRS];
++ struct device_attribute private_port_attrs[SAS_PORT_ATTRS];
++ struct device_attribute private_rphy_attrs[SAS_RPORT_ATTRS];
++ struct device_attribute private_end_dev_attrs[SAS_END_DEV_ATTRS];
++ struct device_attribute private_expander_attrs[SAS_EXPANDER_ATTRS];
+
+ struct transport_container phy_attr_cont;
+ struct transport_container port_attr_cont;
+@@ -30,12 +30,12 @@ struct sas_internal {
+ * The array of null terminated pointers to attributes
+ * needed by scsi_sysfs.c
+ */
+- struct class_device_attribute *host_attrs[SAS_HOST_ATTRS + 1];
+- struct class_device_attribute *phy_attrs[SAS_PHY_ATTRS + 1];
+- struct class_device_attribute *port_attrs[SAS_PORT_ATTRS + 1];
+- struct class_device_attribute *rphy_attrs[SAS_RPORT_ATTRS + 1];
+- struct class_device_attribute *end_dev_attrs[SAS_END_DEV_ATTRS + 1];
+- struct class_device_attribute *expander_attrs[SAS_EXPANDER_ATTRS + 1];
++ struct device_attribute *host_attrs[SAS_HOST_ATTRS + 1];
++ struct device_attribute *phy_attrs[SAS_PHY_ATTRS + 1];
++ struct device_attribute *port_attrs[SAS_PORT_ATTRS + 1];
++ struct device_attribute *rphy_attrs[SAS_RPORT_ATTRS + 1];
++ struct device_attribute *end_dev_attrs[SAS_END_DEV_ATTRS + 1];
++ struct device_attribute *expander_attrs[SAS_EXPANDER_ATTRS + 1];
+ };
+ #define to_sas_internal(tmpl) container_of(tmpl, struct sas_internal, t)
+
+diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
+index ed83cdb..67bb20e 100644
+--- a/drivers/scsi/scsi_sysfs.c
++++ b/drivers/scsi/scsi_sysfs.c
+@@ -119,9 +119,10 @@ static int scsi_scan(struct Scsi_Host *shost, const char *str)
+ */
+ #define shost_show_function(name, field, format_string) \
+ static ssize_t \
+-show_##name (struct class_device *class_dev, char *buf) \
++show_##name (struct device *dev, struct device_attribute *attr, \
++ char *buf) \
+ { \
+- struct Scsi_Host *shost = class_to_shost(class_dev); \
++ struct Scsi_Host *shost = class_to_shost(dev); \
+ return snprintf (buf, 20, format_string, shost->field); \
+ }
+
+@@ -131,7 +132,7 @@ show_##name (struct class_device *class_dev, char *buf) \
+ */
+ #define shost_rd_attr2(name, field, format_string) \
+ shost_show_function(name, field, format_string) \
+-static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
++static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
+
+ #define shost_rd_attr(field, format_string) \
+ shost_rd_attr2(field, field, format_string)
+@@ -140,10 +141,11 @@ shost_rd_attr2(field, field, format_string)
+ * Create the actual show/store functions and data structures.
+ */
+
+-static ssize_t store_scan(struct class_device *class_dev, const char *buf,
+- size_t count)
++static ssize_t
++store_scan(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+- struct Scsi_Host *shost = class_to_shost(class_dev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ int res;
+
+ res = scsi_scan(shost, buf);
+@@ -151,13 +153,14 @@ static ssize_t store_scan(struct class_device *class_dev, const char *buf,
+ res = count;
+ return res;
+ };
+-static CLASS_DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
++static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
+
+ static ssize_t
+-store_shost_state(struct class_device *class_dev, const char *buf, size_t count)
++store_shost_state(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+ int i;
+- struct Scsi_Host *shost = class_to_shost(class_dev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ enum scsi_host_state state = 0;
+
+ for (i = 0; i < ARRAY_SIZE(shost_states); i++) {
+@@ -177,9 +180,9 @@ store_shost_state(struct class_device *class_dev, const char *buf, size_t count)
+ }
+
+ static ssize_t
+-show_shost_state(struct class_device *class_dev, char *buf)
++show_shost_state(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(class_dev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ const char *name = scsi_host_state_name(shost->shost_state);
+
+ if (!name)
+@@ -188,7 +191,9 @@ show_shost_state(struct class_device *class_dev, char *buf)
+ return snprintf(buf, 20, "%s\n", name);
+ }
+
+-static CLASS_DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_shost_state, store_shost_state);
++/* DEVICE_ATTR(state) clashes with dev_attr_state for sdev */
++struct device_attribute dev_attr_hstate =
++ __ATTR(state, S_IRUGO | S_IWUSR, show_shost_state, store_shost_state);
+
+ static ssize_t
+ show_shost_mode(unsigned int mode, char *buf)
+@@ -206,9 +211,11 @@ show_shost_mode(unsigned int mode, char *buf)
+ return len;
+ }
+
+-static ssize_t show_shost_supported_mode(struct class_device *class_dev, char *buf)
++static ssize_t
++show_shost_supported_mode(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(class_dev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+ unsigned int supported_mode = shost->hostt->supported_mode;
+
+ if (supported_mode == MODE_UNKNOWN)
+@@ -218,11 +225,13 @@ static ssize_t show_shost_supported_mode(struct class_device *class_dev, char *b
+ return show_shost_mode(supported_mode, buf);
+ }
+
+-static CLASS_DEVICE_ATTR(supported_mode, S_IRUGO | S_IWUSR, show_shost_supported_mode, NULL);
++static DEVICE_ATTR(supported_mode, S_IRUGO | S_IWUSR, show_shost_supported_mode, NULL);
+
+-static ssize_t show_shost_active_mode(struct class_device *class_dev, char *buf)
++static ssize_t
++show_shost_active_mode(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct Scsi_Host *shost = class_to_shost(class_dev);
++ struct Scsi_Host *shost = class_to_shost(dev);
+
+ if (shost->active_mode == MODE_UNKNOWN)
+ return snprintf(buf, 20, "unknown\n");
+@@ -230,7 +239,7 @@ static ssize_t show_shost_active_mode(struct class_device *class_dev, char *buf)
+ return show_shost_mode(shost->active_mode, buf);
+ }
+
+-static CLASS_DEVICE_ATTR(active_mode, S_IRUGO | S_IWUSR, show_shost_active_mode, NULL);
++static DEVICE_ATTR(active_mode, S_IRUGO | S_IWUSR, show_shost_active_mode, NULL);
+
+ shost_rd_attr(unique_id, "%u\n");
+ shost_rd_attr(host_busy, "%hu\n");
+@@ -240,22 +249,22 @@ shost_rd_attr(sg_tablesize, "%hu\n");
+ shost_rd_attr(unchecked_isa_dma, "%d\n");
+ shost_rd_attr2(proc_name, hostt->proc_name, "%s\n");
+
+-static struct class_device_attribute *scsi_sysfs_shost_attrs[] = {
+- &class_device_attr_unique_id,
+- &class_device_attr_host_busy,
+- &class_device_attr_cmd_per_lun,
+- &class_device_attr_can_queue,
+- &class_device_attr_sg_tablesize,
+- &class_device_attr_unchecked_isa_dma,
+- &class_device_attr_proc_name,
+- &class_device_attr_scan,
+- &class_device_attr_state,
+- &class_device_attr_supported_mode,
+- &class_device_attr_active_mode,
++static struct device_attribute *scsi_sysfs_shost_attrs[] = {
++ &dev_attr_unique_id,
++ &dev_attr_host_busy,
++ &dev_attr_cmd_per_lun,
++ &dev_attr_can_queue,
++ &dev_attr_sg_tablesize,
++ &dev_attr_unchecked_isa_dma,
++ &dev_attr_proc_name,
++ &dev_attr_scan,
++ &dev_attr_hstate,
++ &dev_attr_supported_mode,
++ &dev_attr_active_mode,
+ NULL
+ };
+
+-static void scsi_device_cls_release(struct class_device *class_dev)
++static void scsi_device_cls_release(struct device *class_dev)
+ {
+ struct scsi_device *sdev;
+
+@@ -320,7 +329,7 @@ static void scsi_device_dev_release(struct device *dev)
+
+ static struct class sdev_class = {
+ .name = "scsi_device",
+- .release = scsi_device_cls_release,
++ .dev_release = scsi_device_cls_release,
+ };
+
+ /* all probing is done in the individual ->probe routines */
+@@ -424,7 +433,8 @@ void scsi_sysfs_unregister(void)
+ */
+ #define sdev_show_function(field, format_string) \
+ static ssize_t \
+-sdev_show_##field (struct device *dev, struct device_attribute *attr, char *buf) \
++sdev_show_##field (struct device *dev, struct device_attribute *attr, \
++ char *buf) \
+ { \
+ struct scsi_device *sdev; \
+ sdev = to_scsi_device(dev); \
+@@ -448,7 +458,8 @@ static DEVICE_ATTR(field, S_IRUGO, sdev_show_##field, NULL);
+ sdev_show_function(field, format_string) \
+ \
+ static ssize_t \
+-sdev_store_##field (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
++sdev_store_##field (struct device *dev, struct device_attribute *attr, \
++ const char *buf, size_t count) \
+ { \
+ struct scsi_device *sdev; \
+ sdev = to_scsi_device(dev); \
+@@ -468,7 +479,8 @@ static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##fie
+ sdev_show_function(field, "%d\n") \
+ \
+ static ssize_t \
+-sdev_store_##field (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
++sdev_store_##field (struct device *dev, struct device_attribute *attr, \
++ const char *buf, size_t count) \
+ { \
+ int ret; \
+ struct scsi_device *sdev; \
+@@ -519,7 +531,8 @@ sdev_show_timeout (struct device *dev, struct device_attribute *attr, char *buf)
+ }
+
+ static ssize_t
+-sdev_store_timeout (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++sdev_store_timeout (struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+ struct scsi_device *sdev;
+ int timeout;
+@@ -531,7 +544,8 @@ sdev_store_timeout (struct device *dev, struct device_attribute *attr, const cha
+ static DEVICE_ATTR(timeout, S_IRUGO | S_IWUSR, sdev_show_timeout, sdev_store_timeout);
+
+ static ssize_t
+-store_rescan_field (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++store_rescan_field (struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+ scsi_rescan_device(dev);
+ return count;
+@@ -543,8 +557,9 @@ static void sdev_store_delete_callback(struct device *dev)
+ scsi_remove_device(to_scsi_device(dev));
+ }
+
+-static ssize_t sdev_store_delete(struct device *dev, struct device_attribute *attr, const char *buf,
+- size_t count)
++static ssize_t
++sdev_store_delete(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+ int rc;
+
+@@ -559,7 +574,8 @@ static ssize_t sdev_store_delete(struct device *dev, struct device_attribute *at
+ static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);
+
+ static ssize_t
+-store_state_field(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++store_state_field(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+ int i;
+ struct scsi_device *sdev = to_scsi_device(dev);
+@@ -596,7 +612,8 @@ show_state_field(struct device *dev, struct device_attribute *attr, char *buf)
+ static DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_state_field, store_state_field);
+
+ static ssize_t
+-show_queue_type_field(struct device *dev, struct device_attribute *attr, char *buf)
++show_queue_type_field(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+ struct scsi_device *sdev = to_scsi_device(dev);
+ const char *name = "none";
+@@ -612,7 +629,7 @@ show_queue_type_field(struct device *dev, struct device_attribute *attr, char *b
+ static DEVICE_ATTR(queue_type, S_IRUGO, show_queue_type_field, NULL);
+
+ static ssize_t
+-show_iostat_counterbits(struct device *dev, struct device_attribute *attr, char *buf)
++show_iostat_counterbits(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+ return snprintf(buf, 20, "%d\n", (int)sizeof(atomic_t) * 8);
+ }
+@@ -621,7 +638,8 @@ static DEVICE_ATTR(iocounterbits, S_IRUGO, show_iostat_counterbits, NULL);
+
+ #define show_sdev_iostat(field) \
+ static ssize_t \
+-show_iostat_##field(struct device *dev, struct device_attribute *attr, char *buf) \
++show_iostat_##field(struct device *dev, struct device_attribute *attr, \
++ char *buf) \
+ { \
+ struct scsi_device *sdev = to_scsi_device(dev); \
+ unsigned long long count = atomic_read(&sdev->field); \
+@@ -645,7 +663,7 @@ static DEVICE_ATTR(modalias, S_IRUGO, sdev_show_modalias, NULL);
+ #define DECLARE_EVT_SHOW(name, Cap_name) \
+ static ssize_t \
+ sdev_show_evt_##name(struct device *dev, struct device_attribute *attr, \
+- char *buf) \
++ char *buf) \
+ { \
+ struct scsi_device *sdev = to_scsi_device(dev); \
+ int val = test_bit(SDEV_EVT_##Cap_name, sdev->supported_events);\
+@@ -654,7 +672,7 @@ sdev_show_evt_##name(struct device *dev, struct device_attribute *attr, \
+
+ #define DECLARE_EVT_STORE(name, Cap_name) \
+ static ssize_t \
+-sdev_store_evt_##name(struct device *dev, struct device_attribute *attr, \
++sdev_store_evt_##name(struct device *dev, struct device_attribute *attr,\
+ const char *buf, size_t count) \
+ { \
+ struct scsi_device *sdev = to_scsi_device(dev); \
+@@ -707,8 +725,9 @@ static struct attribute_group *scsi_sdev_attr_groups[] = {
+ NULL
+ };
+
+-static ssize_t sdev_store_queue_depth_rw(struct device *dev, struct device_attribute *attr, const char *buf,
+- size_t count)
++static ssize_t
++sdev_store_queue_depth_rw(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+ int depth, retval;
+ struct scsi_device *sdev = to_scsi_device(dev);
+@@ -733,8 +752,9 @@ static struct device_attribute sdev_attr_queue_depth_rw =
+ __ATTR(queue_depth, S_IRUGO | S_IWUSR, sdev_show_queue_depth,
+ sdev_store_queue_depth_rw);
+
+-static ssize_t sdev_store_queue_type_rw(struct device *dev, struct device_attribute *attr, const char *buf,
+- size_t count)
++static ssize_t
++sdev_store_queue_type_rw(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct scsi_host_template *sht = sdev->host->hostt;
+@@ -786,13 +806,13 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
+ printk(KERN_INFO "error 1\n");
+ return error;
+ }
+- error = class_device_add(&sdev->sdev_classdev);
++ error = device_add(&sdev->sdev_dev);
+ if (error) {
+ printk(KERN_INFO "error 2\n");
+ goto clean_device;
+ }
+
+- /* take a reference for the sdev_classdev; this is
++ /* take a reference for the sdev_dev; this is
+ * released by the sdev_class .release */
+ get_device(&sdev->sdev_gendev);
+
+@@ -858,7 +878,7 @@ void __scsi_remove_device(struct scsi_device *sdev)
+ return;
+
+ bsg_unregister_queue(sdev->request_queue);
+- class_device_unregister(&sdev->sdev_classdev);
++ device_unregister(&sdev->sdev_dev);
+ transport_remove_device(dev);
+ device_del(dev);
+ scsi_device_set_state(sdev, SDEV_DEL);
+@@ -952,9 +972,9 @@ int scsi_register_interface(struct class_interface *intf)
+ EXPORT_SYMBOL(scsi_register_interface);
+
+
+-static struct class_device_attribute *class_attr_overridden(
+- struct class_device_attribute **attrs,
+- struct class_device_attribute *attr)
++static struct device_attribute *class_attr_overridden(
++ struct device_attribute **attrs,
++ struct device_attribute *attr)
+ {
+ int i;
+
+@@ -966,10 +986,10 @@ static struct class_device_attribute *class_attr_overridden(
+ return NULL;
+ }
+
+-static int class_attr_add(struct class_device *classdev,
+- struct class_device_attribute *attr)
++static int class_attr_add(struct device *classdev,
++ struct device_attribute *attr)
+ {
+- struct class_device_attribute *base_attr;
++ struct device_attribute *base_attr;
+
+ /*
+ * Spare the caller from having to copy things it's not interested in.
+@@ -986,7 +1006,7 @@ static int class_attr_add(struct class_device *classdev,
+ attr->store = base_attr->store;
+ }
+
+- return class_device_create_file(classdev, attr);
++ return device_create_file(classdev, attr);
+ }
+
+ /**
+@@ -1000,7 +1020,7 @@ int scsi_sysfs_add_host(struct Scsi_Host *shost)
+
+ if (shost->hostt->shost_attrs) {
+ for (i = 0; shost->hostt->shost_attrs[i]; i++) {
+- error = class_attr_add(&shost->shost_classdev,
++ error = class_attr_add(&shost->shost_dev,
+ shost->hostt->shost_attrs[i]);
+ if (error)
+ return error;
+@@ -1010,7 +1030,7 @@ int scsi_sysfs_add_host(struct Scsi_Host *shost)
+ for (i = 0; scsi_sysfs_shost_attrs[i]; i++) {
+ if (!class_attr_overridden(shost->hostt->shost_attrs,
+ scsi_sysfs_shost_attrs[i])) {
+- error = class_device_create_file(&shost->shost_classdev,
++ error = device_create_file(&shost->shost_dev,
+ scsi_sysfs_shost_attrs[i]);
+ if (error)
+ return error;
+@@ -1041,10 +1061,10 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev)
+ sdev->host->host_no, sdev->channel, sdev->id,
+ sdev->lun);
+
+- class_device_initialize(&sdev->sdev_classdev);
+- sdev->sdev_classdev.dev = &sdev->sdev_gendev;
+- sdev->sdev_classdev.class = &sdev_class;
+- snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE,
++ device_initialize(&sdev->sdev_dev);
++ sdev->sdev_dev.parent = &sdev->sdev_gendev;
++ sdev->sdev_dev.class = &sdev_class;
++ snprintf(sdev->sdev_dev.bus_id, BUS_ID_SIZE,
+ "%d:%d:%d:%d", sdev->host->host_no,
+ sdev->channel, sdev->id, sdev->lun);
+ sdev->scsi_level = starget->scsi_level;
+diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c
+index a0f308b..ee8496a 100644
+--- a/drivers/scsi/scsi_tgt_lib.c
++++ b/drivers/scsi/scsi_tgt_lib.c
+@@ -621,9 +621,7 @@ static int __init scsi_tgt_init(void)
+ {
+ int err;
+
+- scsi_tgt_cmd_cache = kmem_cache_create("scsi_tgt_cmd",
+- sizeof(struct scsi_tgt_cmd),
+- 0, 0, NULL);
++ scsi_tgt_cmd_cache = KMEM_CACHE(scsi_tgt_cmd, 0);
+ if (!scsi_tgt_cmd_cache)
+ return -ENOMEM;
+
+diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
+index b1119da..6b092a6 100644
+--- a/drivers/scsi/scsi_transport_fc.c
++++ b/drivers/scsi/scsi_transport_fc.c
+@@ -72,8 +72,8 @@ static int fc_vport_create(struct Scsi_Host *shost, int channel,
+ * Redefine so that we can have same named attributes in the
+ * sdev/starget/host objects.
+ */
+-#define FC_CLASS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \
+-struct class_device_attribute class_device_attr_##_prefix##_##_name = \
++#define FC_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \
++struct device_attribute device_attr_##_prefix##_##_name = \
+ __ATTR(_name,_mode,_show,_store)
+
+ #define fc_enum_name_search(title, table_type, table) \
+@@ -326,26 +326,26 @@ struct fc_internal {
+ * part of the midlayer. As the remote port is specific to the
+ * fc transport, we must provide the attribute container.
+ */
+- struct class_device_attribute private_starget_attrs[
++ struct device_attribute private_starget_attrs[
+ FC_STARGET_NUM_ATTRS];
+- struct class_device_attribute *starget_attrs[FC_STARGET_NUM_ATTRS + 1];
++ struct device_attribute *starget_attrs[FC_STARGET_NUM_ATTRS + 1];
+
+- struct class_device_attribute private_host_attrs[FC_HOST_NUM_ATTRS];
+- struct class_device_attribute *host_attrs[FC_HOST_NUM_ATTRS + 1];
++ struct device_attribute private_host_attrs[FC_HOST_NUM_ATTRS];
++ struct device_attribute *host_attrs[FC_HOST_NUM_ATTRS + 1];
+
+ struct transport_container rport_attr_cont;
+- struct class_device_attribute private_rport_attrs[FC_RPORT_NUM_ATTRS];
+- struct class_device_attribute *rport_attrs[FC_RPORT_NUM_ATTRS + 1];
++ struct device_attribute private_rport_attrs[FC_RPORT_NUM_ATTRS];
++ struct device_attribute *rport_attrs[FC_RPORT_NUM_ATTRS + 1];
+
+ struct transport_container vport_attr_cont;
+- struct class_device_attribute private_vport_attrs[FC_VPORT_NUM_ATTRS];
+- struct class_device_attribute *vport_attrs[FC_VPORT_NUM_ATTRS + 1];
++ struct device_attribute private_vport_attrs[FC_VPORT_NUM_ATTRS];
++ struct device_attribute *vport_attrs[FC_VPORT_NUM_ATTRS + 1];
+ };
+
+ #define to_fc_internal(tmpl) container_of(tmpl, struct fc_internal, t)
+
+ static int fc_target_setup(struct transport_container *tc, struct device *dev,
+- struct class_device *cdev)
++ struct device *cdev)
+ {
+ struct scsi_target *starget = to_scsi_target(dev);
+ struct fc_rport *rport = starget_to_rport(starget);
+@@ -375,7 +375,7 @@ static DECLARE_TRANSPORT_CLASS(fc_transport_class,
+ NULL);
+
+ static int fc_host_setup(struct transport_container *tc, struct device *dev,
+- struct class_device *cdev)
++ struct device *cdev)
+ {
+ struct Scsi_Host *shost = dev_to_shost(dev);
+ struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+@@ -682,9 +682,10 @@ static void __exit fc_transport_exit(void)
+
+ #define fc_rport_show_function(field, format_string, sz, cast) \
+ static ssize_t \
+-show_fc_rport_##field (struct class_device *cdev, char *buf) \
++show_fc_rport_##field (struct device *dev, \
++ struct device_attribute *attr, char *buf) \
+ { \
+- struct fc_rport *rport = transport_class_to_rport(cdev); \
++ struct fc_rport *rport = transport_class_to_rport(dev); \
+ struct Scsi_Host *shost = rport_to_shost(rport); \
+ struct fc_internal *i = to_fc_internal(shost->transportt); \
+ if ((i->f->get_rport_##field) && \
+@@ -697,11 +698,12 @@ show_fc_rport_##field (struct class_device *cdev, char *buf) \
+
+ #define fc_rport_store_function(field) \
+ static ssize_t \
+-store_fc_rport_##field(struct class_device *cdev, const char *buf, \
+- size_t count) \
++store_fc_rport_##field(struct device *dev, \
++ struct device_attribute *attr, \
++ const char *buf, size_t count) \
+ { \
+ int val; \
+- struct fc_rport *rport = transport_class_to_rport(cdev); \
++ struct fc_rport *rport = transport_class_to_rport(dev); \
+ struct Scsi_Host *shost = rport_to_shost(rport); \
+ struct fc_internal *i = to_fc_internal(shost->transportt); \
+ char *cp; \
+@@ -718,58 +720,60 @@ store_fc_rport_##field(struct class_device *cdev, const char *buf, \
+
+ #define fc_rport_rd_attr(field, format_string, sz) \
+ fc_rport_show_function(field, format_string, sz, ) \
+-static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO, \
++static FC_DEVICE_ATTR(rport, field, S_IRUGO, \
+ show_fc_rport_##field, NULL)
+
+ #define fc_rport_rd_attr_cast(field, format_string, sz, cast) \
+ fc_rport_show_function(field, format_string, sz, (cast)) \
+-static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO, \
++static FC_DEVICE_ATTR(rport, field, S_IRUGO, \
+ show_fc_rport_##field, NULL)
+
+ #define fc_rport_rw_attr(field, format_string, sz) \
+ fc_rport_show_function(field, format_string, sz, ) \
+ fc_rport_store_function(field) \
+-static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO | S_IWUSR, \
++static FC_DEVICE_ATTR(rport, field, S_IRUGO | S_IWUSR, \
+ show_fc_rport_##field, \
+ store_fc_rport_##field)
+
+
+ #define fc_private_rport_show_function(field, format_string, sz, cast) \
+ static ssize_t \
+-show_fc_rport_##field (struct class_device *cdev, char *buf) \
++show_fc_rport_##field (struct device *dev, \
++ struct device_attribute *attr, char *buf) \
+ { \
+- struct fc_rport *rport = transport_class_to_rport(cdev); \
++ struct fc_rport *rport = transport_class_to_rport(dev); \
+ return snprintf(buf, sz, format_string, cast rport->field); \
+ }
+
+ #define fc_private_rport_rd_attr(field, format_string, sz) \
+ fc_private_rport_show_function(field, format_string, sz, ) \
+-static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO, \
++static FC_DEVICE_ATTR(rport, field, S_IRUGO, \
+ show_fc_rport_##field, NULL)
+
+ #define fc_private_rport_rd_attr_cast(field, format_string, sz, cast) \
+ fc_private_rport_show_function(field, format_string, sz, (cast)) \
+-static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO, \
++static FC_DEVICE_ATTR(rport, field, S_IRUGO, \
+ show_fc_rport_##field, NULL)
+
+
+ #define fc_private_rport_rd_enum_attr(title, maxlen) \
+ static ssize_t \
+-show_fc_rport_##title (struct class_device *cdev, char *buf) \
++show_fc_rport_##title (struct device *dev, \
++ struct device_attribute *attr, char *buf) \
+ { \
+- struct fc_rport *rport = transport_class_to_rport(cdev); \
++ struct fc_rport *rport = transport_class_to_rport(dev); \
+ const char *name; \
+ name = get_fc_##title##_name(rport->title); \
+ if (!name) \
+ return -EINVAL; \
+ return snprintf(buf, maxlen, "%s\n", name); \
+ } \
+-static FC_CLASS_DEVICE_ATTR(rport, title, S_IRUGO, \
++static FC_DEVICE_ATTR(rport, title, S_IRUGO, \
+ show_fc_rport_##title, NULL)
+
+
+ #define SETUP_RPORT_ATTRIBUTE_RD(field) \
+- i->private_rport_attrs[count] = class_device_attr_rport_##field; \
++ i->private_rport_attrs[count] = device_attr_rport_##field; \
+ i->private_rport_attrs[count].attr.mode = S_IRUGO; \
+ i->private_rport_attrs[count].store = NULL; \
+ i->rport_attrs[count] = &i->private_rport_attrs[count]; \
+@@ -777,14 +781,14 @@ static FC_CLASS_DEVICE_ATTR(rport, title, S_IRUGO, \
+ count++
+
+ #define SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(field) \
+- i->private_rport_attrs[count] = class_device_attr_rport_##field; \
++ i->private_rport_attrs[count] = device_attr_rport_##field; \
+ i->private_rport_attrs[count].attr.mode = S_IRUGO; \
+ i->private_rport_attrs[count].store = NULL; \
+ i->rport_attrs[count] = &i->private_rport_attrs[count]; \
+ count++
+
+ #define SETUP_RPORT_ATTRIBUTE_RW(field) \
+- i->private_rport_attrs[count] = class_device_attr_rport_##field; \
++ i->private_rport_attrs[count] = device_attr_rport_##field; \
+ if (!i->f->set_rport_##field) { \
+ i->private_rport_attrs[count].attr.mode = S_IRUGO; \
+ i->private_rport_attrs[count].store = NULL; \
+@@ -795,7 +799,7 @@ static FC_CLASS_DEVICE_ATTR(rport, title, S_IRUGO, \
+
+ #define SETUP_PRIVATE_RPORT_ATTRIBUTE_RW(field) \
+ { \
+- i->private_rport_attrs[count] = class_device_attr_rport_##field; \
++ i->private_rport_attrs[count] = device_attr_rport_##field; \
+ i->rport_attrs[count] = &i->private_rport_attrs[count]; \
+ count++; \
+ }
+@@ -808,14 +812,15 @@ static FC_CLASS_DEVICE_ATTR(rport, title, S_IRUGO, \
+ fc_private_rport_rd_attr(maxframe_size, "%u bytes\n", 20);
+
+ static ssize_t
+-show_fc_rport_supported_classes (struct class_device *cdev, char *buf)
++show_fc_rport_supported_classes (struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct fc_rport *rport = transport_class_to_rport(cdev);
++ struct fc_rport *rport = transport_class_to_rport(dev);
+ if (rport->supported_classes == FC_COS_UNSPECIFIED)
+ return snprintf(buf, 20, "unspecified\n");
+ return get_fc_cos_names(rport->supported_classes, buf);
+ }
+-static FC_CLASS_DEVICE_ATTR(rport, supported_classes, S_IRUGO,
++static FC_DEVICE_ATTR(rport, supported_classes, S_IRUGO,
+ show_fc_rport_supported_classes, NULL);
+
+ /* Dynamic Remote Port Attributes */
+@@ -825,11 +830,11 @@ static FC_CLASS_DEVICE_ATTR(rport, supported_classes, S_IRUGO,
+ */
+ fc_rport_show_function(dev_loss_tmo, "%d\n", 20, )
+ static ssize_t
+-store_fc_rport_dev_loss_tmo(struct class_device *cdev, const char *buf,
+- size_t count)
++store_fc_rport_dev_loss_tmo(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+ int val;
+- struct fc_rport *rport = transport_class_to_rport(cdev);
++ struct fc_rport *rport = transport_class_to_rport(dev);
+ struct Scsi_Host *shost = rport_to_shost(rport);
+ struct fc_internal *i = to_fc_internal(shost->transportt);
+ char *cp;
+@@ -844,7 +849,7 @@ store_fc_rport_dev_loss_tmo(struct class_device *cdev, const char *buf,
+ i->f->set_rport_dev_loss_tmo(rport, val);
+ return count;
+ }
+-static FC_CLASS_DEVICE_ATTR(rport, dev_loss_tmo, S_IRUGO | S_IWUSR,
++static FC_DEVICE_ATTR(rport, dev_loss_tmo, S_IRUGO | S_IWUSR,
+ show_fc_rport_dev_loss_tmo, store_fc_rport_dev_loss_tmo);
+
+
+@@ -855,9 +860,10 @@ fc_private_rport_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
+ fc_private_rport_rd_attr(port_id, "0x%06x\n", 20);
+
+ static ssize_t
+-show_fc_rport_roles (struct class_device *cdev, char *buf)
++show_fc_rport_roles (struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct fc_rport *rport = transport_class_to_rport(cdev);
++ struct fc_rport *rport = transport_class_to_rport(dev);
+
+ /* identify any roles that are port_id specific */
+ if ((rport->port_id != -1) &&
+@@ -883,7 +889,7 @@ show_fc_rport_roles (struct class_device *cdev, char *buf)
+ return get_fc_port_roles_names(rport->roles, buf);
+ }
+ }
+-static FC_CLASS_DEVICE_ATTR(rport, roles, S_IRUGO,
++static FC_DEVICE_ATTR(rport, roles, S_IRUGO,
+ show_fc_rport_roles, NULL);
+
+ fc_private_rport_rd_enum_attr(port_state, FC_PORTSTATE_MAX_NAMELEN);
+@@ -893,9 +899,10 @@ fc_private_rport_rd_attr(scsi_target_id, "%d\n", 20);
+ * fast_io_fail_tmo attribute
+ */
+ static ssize_t
+-show_fc_rport_fast_io_fail_tmo (struct class_device *cdev, char *buf)
++show_fc_rport_fast_io_fail_tmo (struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct fc_rport *rport = transport_class_to_rport(cdev);
++ struct fc_rport *rport = transport_class_to_rport(dev);
+
+ if (rport->fast_io_fail_tmo == -1)
+ return snprintf(buf, 5, "off\n");
+@@ -903,12 +910,13 @@ show_fc_rport_fast_io_fail_tmo (struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-store_fc_rport_fast_io_fail_tmo(struct class_device *cdev, const char *buf,
+- size_t count)
++store_fc_rport_fast_io_fail_tmo(struct device *dev,
++ struct device_attribute *attr, const char *buf,
++ size_t count)
+ {
+ int val;
+ char *cp;
+- struct fc_rport *rport = transport_class_to_rport(cdev);
++ struct fc_rport *rport = transport_class_to_rport(dev);
+
+ if ((rport->port_state == FC_PORTSTATE_BLOCKED) ||
+ (rport->port_state == FC_PORTSTATE_DELETED) ||
+@@ -925,7 +933,7 @@ store_fc_rport_fast_io_fail_tmo(struct class_device *cdev, const char *buf,
+ }
+ return count;
+ }
+-static FC_CLASS_DEVICE_ATTR(rport, fast_io_fail_tmo, S_IRUGO | S_IWUSR,
++static FC_DEVICE_ATTR(rport, fast_io_fail_tmo, S_IRUGO | S_IWUSR,
+ show_fc_rport_fast_io_fail_tmo, store_fc_rport_fast_io_fail_tmo);
+
+
+@@ -941,9 +949,10 @@ static FC_CLASS_DEVICE_ATTR(rport, fast_io_fail_tmo, S_IRUGO | S_IWUSR,
+ */
+ #define fc_starget_show_function(field, format_string, sz, cast) \
+ static ssize_t \
+-show_fc_starget_##field (struct class_device *cdev, char *buf) \
++show_fc_starget_##field (struct device *dev, \
++ struct device_attribute *attr, char *buf) \
+ { \
+- struct scsi_target *starget = transport_class_to_starget(cdev); \
++ struct scsi_target *starget = transport_class_to_starget(dev); \
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \
+ struct fc_internal *i = to_fc_internal(shost->transportt); \
+ struct fc_rport *rport = starget_to_rport(starget); \
+@@ -957,16 +966,16 @@ show_fc_starget_##field (struct class_device *cdev, char *buf) \
+
+ #define fc_starget_rd_attr(field, format_string, sz) \
+ fc_starget_show_function(field, format_string, sz, ) \
+-static FC_CLASS_DEVICE_ATTR(starget, field, S_IRUGO, \
++static FC_DEVICE_ATTR(starget, field, S_IRUGO, \
+ show_fc_starget_##field, NULL)
+
+ #define fc_starget_rd_attr_cast(field, format_string, sz, cast) \
+ fc_starget_show_function(field, format_string, sz, (cast)) \
+-static FC_CLASS_DEVICE_ATTR(starget, field, S_IRUGO, \
++static FC_DEVICE_ATTR(starget, field, S_IRUGO, \
+ show_fc_starget_##field, NULL)
+
+ #define SETUP_STARGET_ATTRIBUTE_RD(field) \
+- i->private_starget_attrs[count] = class_device_attr_starget_##field; \
++ i->private_starget_attrs[count] = device_attr_starget_##field; \
+ i->private_starget_attrs[count].attr.mode = S_IRUGO; \
+ i->private_starget_attrs[count].store = NULL; \
+ i->starget_attrs[count] = &i->private_starget_attrs[count]; \
+@@ -974,7 +983,7 @@ static FC_CLASS_DEVICE_ATTR(starget, field, S_IRUGO, \
+ count++
+
+ #define SETUP_STARGET_ATTRIBUTE_RW(field) \
+- i->private_starget_attrs[count] = class_device_attr_starget_##field; \
++ i->private_starget_attrs[count] = device_attr_starget_##field; \
+ if (!i->f->set_starget_##field) { \
+ i->private_starget_attrs[count].attr.mode = S_IRUGO; \
+ i->private_starget_attrs[count].store = NULL; \
+@@ -995,9 +1004,10 @@ fc_starget_rd_attr(port_id, "0x%06x\n", 20);
+
+ #define fc_vport_show_function(field, format_string, sz, cast) \
+ static ssize_t \
+-show_fc_vport_##field (struct class_device *cdev, char *buf) \
++show_fc_vport_##field (struct device *dev, \
++ struct device_attribute *attr, char *buf) \
+ { \
+- struct fc_vport *vport = transport_class_to_vport(cdev); \
++ struct fc_vport *vport = transport_class_to_vport(dev); \
+ struct Scsi_Host *shost = vport_to_shost(vport); \
+ struct fc_internal *i = to_fc_internal(shost->transportt); \
+ if ((i->f->get_vport_##field) && \
+@@ -1008,11 +1018,12 @@ show_fc_vport_##field (struct class_device *cdev, char *buf) \
+
+ #define fc_vport_store_function(field) \
+ static ssize_t \
+-store_fc_vport_##field(struct class_device *cdev, const char *buf, \
+- size_t count) \
++store_fc_vport_##field(struct device *dev, \
++ struct device_attribute *attr, \
++ const char *buf, size_t count) \
+ { \
+ int val; \
+- struct fc_vport *vport = transport_class_to_vport(cdev); \
++ struct fc_vport *vport = transport_class_to_vport(dev); \
+ struct Scsi_Host *shost = vport_to_shost(vport); \
+ struct fc_internal *i = to_fc_internal(shost->transportt); \
+ char *cp; \
+@@ -1027,10 +1038,11 @@ store_fc_vport_##field(struct class_device *cdev, const char *buf, \
+
+ #define fc_vport_store_str_function(field, slen) \
+ static ssize_t \
+-store_fc_vport_##field(struct class_device *cdev, const char *buf, \
+- size_t count) \
++store_fc_vport_##field(struct device *dev, \
++ struct device_attribute *attr, \
++ const char *buf, size_t count) \
+ { \
+- struct fc_vport *vport = transport_class_to_vport(cdev); \
++ struct fc_vport *vport = transport_class_to_vport(dev); \
+ struct Scsi_Host *shost = vport_to_shost(vport); \
+ struct fc_internal *i = to_fc_internal(shost->transportt); \
+ unsigned int cnt=count; \
+@@ -1047,36 +1059,38 @@ store_fc_vport_##field(struct class_device *cdev, const char *buf, \
+
+ #define fc_vport_rd_attr(field, format_string, sz) \
+ fc_vport_show_function(field, format_string, sz, ) \
+-static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO, \
++static FC_DEVICE_ATTR(vport, field, S_IRUGO, \
+ show_fc_vport_##field, NULL)
+
+ #define fc_vport_rd_attr_cast(field, format_string, sz, cast) \
+ fc_vport_show_function(field, format_string, sz, (cast)) \
+-static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO, \
++static FC_DEVICE_ATTR(vport, field, S_IRUGO, \
+ show_fc_vport_##field, NULL)
+
+ #define fc_vport_rw_attr(field, format_string, sz) \
+ fc_vport_show_function(field, format_string, sz, ) \
+ fc_vport_store_function(field) \
+-static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO | S_IWUSR, \
++static FC_DEVICE_ATTR(vport, field, S_IRUGO | S_IWUSR, \
+ show_fc_vport_##field, \
+ store_fc_vport_##field)
+
+ #define fc_private_vport_show_function(field, format_string, sz, cast) \
+ static ssize_t \
+-show_fc_vport_##field (struct class_device *cdev, char *buf) \
++show_fc_vport_##field (struct device *dev, \
++ struct device_attribute *attr, char *buf) \
+ { \
+- struct fc_vport *vport = transport_class_to_vport(cdev); \
++ struct fc_vport *vport = transport_class_to_vport(dev); \
+ return snprintf(buf, sz, format_string, cast vport->field); \
+ }
+
+ #define fc_private_vport_store_u32_function(field) \
+ static ssize_t \
+-store_fc_vport_##field(struct class_device *cdev, const char *buf, \
+- size_t count) \
++store_fc_vport_##field(struct device *dev, \
++ struct device_attribute *attr, \
++ const char *buf, size_t count) \
+ { \
+ u32 val; \
+- struct fc_vport *vport = transport_class_to_vport(cdev); \
++ struct fc_vport *vport = transport_class_to_vport(dev); \
+ char *cp; \
+ if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING)) \
+ return -EBUSY; \
+@@ -1090,39 +1104,41 @@ store_fc_vport_##field(struct class_device *cdev, const char *buf, \
+
+ #define fc_private_vport_rd_attr(field, format_string, sz) \
+ fc_private_vport_show_function(field, format_string, sz, ) \
+-static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO, \
++static FC_DEVICE_ATTR(vport, field, S_IRUGO, \
+ show_fc_vport_##field, NULL)
+
+ #define fc_private_vport_rd_attr_cast(field, format_string, sz, cast) \
+ fc_private_vport_show_function(field, format_string, sz, (cast)) \
+-static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO, \
++static FC_DEVICE_ATTR(vport, field, S_IRUGO, \
+ show_fc_vport_##field, NULL)
+
+ #define fc_private_vport_rw_u32_attr(field, format_string, sz) \
+ fc_private_vport_show_function(field, format_string, sz, ) \
+ fc_private_vport_store_u32_function(field) \
+-static FC_CLASS_DEVICE_ATTR(vport, field, S_IRUGO | S_IWUSR, \
++static FC_DEVICE_ATTR(vport, field, S_IRUGO | S_IWUSR, \
+ show_fc_vport_##field, \
+ store_fc_vport_##field)
+
+
+ #define fc_private_vport_rd_enum_attr(title, maxlen) \
+ static ssize_t \
+-show_fc_vport_##title (struct class_device *cdev, char *buf) \
++show_fc_vport_##title (struct device *dev, \
++ struct device_attribute *attr, \
++ char *buf) \
+ { \
+- struct fc_vport *vport = transport_class_to_vport(cdev); \
++ struct fc_vport *vport = transport_class_to_vport(dev); \
+ const char *name; \
+ name = get_fc_##title##_name(vport->title); \
+ if (!name) \
+ return -EINVAL; \
+ return snprintf(buf, maxlen, "%s\n", name); \
+ } \
+-static FC_CLASS_DEVICE_ATTR(vport, title, S_IRUGO, \
++static FC_DEVICE_ATTR(vport, title, S_IRUGO, \
+ show_fc_vport_##title, NULL)
+
+
+ #define SETUP_VPORT_ATTRIBUTE_RD(field) \
+- i->private_vport_attrs[count] = class_device_attr_vport_##field; \
++ i->private_vport_attrs[count] = device_attr_vport_##field; \
+ i->private_vport_attrs[count].attr.mode = S_IRUGO; \
+ i->private_vport_attrs[count].store = NULL; \
+ i->vport_attrs[count] = &i->private_vport_attrs[count]; \
+@@ -1131,21 +1147,21 @@ static FC_CLASS_DEVICE_ATTR(vport, title, S_IRUGO, \
+ /* NOTE: Above MACRO differs: checks function not show bit */
+
+ #define SETUP_PRIVATE_VPORT_ATTRIBUTE_RD(field) \
+- i->private_vport_attrs[count] = class_device_attr_vport_##field; \
++ i->private_vport_attrs[count] = device_attr_vport_##field; \
+ i->private_vport_attrs[count].attr.mode = S_IRUGO; \
+ i->private_vport_attrs[count].store = NULL; \
+ i->vport_attrs[count] = &i->private_vport_attrs[count]; \
+ count++
+
+ #define SETUP_VPORT_ATTRIBUTE_WR(field) \
+- i->private_vport_attrs[count] = class_device_attr_vport_##field; \
++ i->private_vport_attrs[count] = device_attr_vport_##field; \
+ i->vport_attrs[count] = &i->private_vport_attrs[count]; \
+ if (i->f->field) \
+ count++
+ /* NOTE: Above MACRO differs: checks function */
+
+ #define SETUP_VPORT_ATTRIBUTE_RW(field) \
+- i->private_vport_attrs[count] = class_device_attr_vport_##field; \
++ i->private_vport_attrs[count] = device_attr_vport_##field; \
+ if (!i->f->set_vport_##field) { \
+ i->private_vport_attrs[count].attr.mode = S_IRUGO; \
+ i->private_vport_attrs[count].store = NULL; \
+@@ -1156,7 +1172,7 @@ static FC_CLASS_DEVICE_ATTR(vport, title, S_IRUGO, \
+
+ #define SETUP_PRIVATE_VPORT_ATTRIBUTE_RW(field) \
+ { \
+- i->private_vport_attrs[count] = class_device_attr_vport_##field; \
++ i->private_vport_attrs[count] = device_attr_vport_##field; \
+ i->vport_attrs[count] = &i->private_vport_attrs[count]; \
+ count++; \
+ }
+@@ -1176,35 +1192,36 @@ fc_private_vport_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);
+ fc_private_vport_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
+
+ static ssize_t
+-show_fc_vport_roles (struct class_device *cdev, char *buf)
++show_fc_vport_roles (struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct fc_vport *vport = transport_class_to_vport(cdev);
++ struct fc_vport *vport = transport_class_to_vport(dev);
+
+ if (vport->roles == FC_PORT_ROLE_UNKNOWN)
+ return snprintf(buf, 20, "unknown\n");
+ return get_fc_port_roles_names(vport->roles, buf);
+ }
+-static FC_CLASS_DEVICE_ATTR(vport, roles, S_IRUGO, show_fc_vport_roles, NULL);
++static FC_DEVICE_ATTR(vport, roles, S_IRUGO, show_fc_vport_roles, NULL);
+
+ fc_private_vport_rd_enum_attr(vport_type, FC_PORTTYPE_MAX_NAMELEN);
+
+ fc_private_vport_show_function(symbolic_name, "%s\n",
+ FC_VPORT_SYMBOLIC_NAMELEN + 1, )
+ fc_vport_store_str_function(symbolic_name, FC_VPORT_SYMBOLIC_NAMELEN)
+-static FC_CLASS_DEVICE_ATTR(vport, symbolic_name, S_IRUGO | S_IWUSR,
++static FC_DEVICE_ATTR(vport, symbolic_name, S_IRUGO | S_IWUSR,
+ show_fc_vport_symbolic_name, store_fc_vport_symbolic_name);
+
+ static ssize_t
+-store_fc_vport_delete(struct class_device *cdev, const char *buf,
+- size_t count)
++store_fc_vport_delete(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+- struct fc_vport *vport = transport_class_to_vport(cdev);
++ struct fc_vport *vport = transport_class_to_vport(dev);
+ struct Scsi_Host *shost = vport_to_shost(vport);
+
+ fc_queue_work(shost, &vport->vport_delete_work);
+ return count;
+ }
+-static FC_CLASS_DEVICE_ATTR(vport, vport_delete, S_IWUSR,
++static FC_DEVICE_ATTR(vport, vport_delete, S_IWUSR,
+ NULL, store_fc_vport_delete);
+
+
+@@ -1213,10 +1230,11 @@ static FC_CLASS_DEVICE_ATTR(vport, vport_delete, S_IWUSR,
+ * Write "1" to disable, write "0" to enable
+ */
+ static ssize_t
+-store_fc_vport_disable(struct class_device *cdev, const char *buf,
++store_fc_vport_disable(struct device *dev, struct device_attribute *attr,
++ const char *buf,
+ size_t count)
+ {
+- struct fc_vport *vport = transport_class_to_vport(cdev);
++ struct fc_vport *vport = transport_class_to_vport(dev);
+ struct Scsi_Host *shost = vport_to_shost(vport);
+ struct fc_internal *i = to_fc_internal(shost->transportt);
+ int stat;
+@@ -1236,7 +1254,7 @@ store_fc_vport_disable(struct class_device *cdev, const char *buf,
+ stat = i->f->vport_disable(vport, ((*buf == '0') ? false : true));
+ return stat ? stat : count;
+ }
+-static FC_CLASS_DEVICE_ATTR(vport, vport_disable, S_IWUSR,
++static FC_DEVICE_ATTR(vport, vport_disable, S_IWUSR,
+ NULL, store_fc_vport_disable);
+
+
+@@ -1246,9 +1264,10 @@ static FC_CLASS_DEVICE_ATTR(vport, vport_disable, S_IWUSR,
+
+ #define fc_host_show_function(field, format_string, sz, cast) \
+ static ssize_t \
+-show_fc_host_##field (struct class_device *cdev, char *buf) \
++show_fc_host_##field (struct device *dev, \
++ struct device_attribute *attr, char *buf) \
+ { \
+- struct Scsi_Host *shost = transport_class_to_shost(cdev); \
++ struct Scsi_Host *shost = transport_class_to_shost(dev); \
+ struct fc_internal *i = to_fc_internal(shost->transportt); \
+ if (i->f->get_host_##field) \
+ i->f->get_host_##field(shost); \
+@@ -1257,11 +1276,12 @@ show_fc_host_##field (struct class_device *cdev, char *buf) \
+
+ #define fc_host_store_function(field) \
+ static ssize_t \
+-store_fc_host_##field(struct class_device *cdev, const char *buf, \
+- size_t count) \
++store_fc_host_##field(struct device *dev, \
++ struct device_attribute *attr, \
++ const char *buf, size_t count) \
+ { \
+ int val; \
+- struct Scsi_Host *shost = transport_class_to_shost(cdev); \
++ struct Scsi_Host *shost = transport_class_to_shost(dev); \
+ struct fc_internal *i = to_fc_internal(shost->transportt); \
+ char *cp; \
+ \
+@@ -1274,10 +1294,11 @@ store_fc_host_##field(struct class_device *cdev, const char *buf, \
+
+ #define fc_host_store_str_function(field, slen) \
+ static ssize_t \
+-store_fc_host_##field(struct class_device *cdev, const char *buf, \
+- size_t count) \
++store_fc_host_##field(struct device *dev, \
++ struct device_attribute *attr, \
++ const char *buf, size_t count) \
+ { \
+- struct Scsi_Host *shost = transport_class_to_shost(cdev); \
++ struct Scsi_Host *shost = transport_class_to_shost(dev); \
+ struct fc_internal *i = to_fc_internal(shost->transportt); \
+ unsigned int cnt=count; \
+ \
+@@ -1293,26 +1314,27 @@ store_fc_host_##field(struct class_device *cdev, const char *buf, \
+
+ #define fc_host_rd_attr(field, format_string, sz) \
+ fc_host_show_function(field, format_string, sz, ) \
+-static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO, \
++static FC_DEVICE_ATTR(host, field, S_IRUGO, \
+ show_fc_host_##field, NULL)
+
+ #define fc_host_rd_attr_cast(field, format_string, sz, cast) \
+ fc_host_show_function(field, format_string, sz, (cast)) \
+-static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO, \
++static FC_DEVICE_ATTR(host, field, S_IRUGO, \
+ show_fc_host_##field, NULL)
+
+ #define fc_host_rw_attr(field, format_string, sz) \
+ fc_host_show_function(field, format_string, sz, ) \
+ fc_host_store_function(field) \
+-static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO | S_IWUSR, \
++static FC_DEVICE_ATTR(host, field, S_IRUGO | S_IWUSR, \
+ show_fc_host_##field, \
+ store_fc_host_##field)
+
+ #define fc_host_rd_enum_attr(title, maxlen) \
+ static ssize_t \
+-show_fc_host_##title (struct class_device *cdev, char *buf) \
++show_fc_host_##title (struct device *dev, \
++ struct device_attribute *attr, char *buf) \
+ { \
+- struct Scsi_Host *shost = transport_class_to_shost(cdev); \
++ struct Scsi_Host *shost = transport_class_to_shost(dev); \
+ struct fc_internal *i = to_fc_internal(shost->transportt); \
+ const char *name; \
+ if (i->f->get_host_##title) \
+@@ -1322,10 +1344,10 @@ show_fc_host_##title (struct class_device *cdev, char *buf) \
+ return -EINVAL; \
+ return snprintf(buf, maxlen, "%s\n", name); \
+ } \
+-static FC_CLASS_DEVICE_ATTR(host, title, S_IRUGO, show_fc_host_##title, NULL)
++static FC_DEVICE_ATTR(host, title, S_IRUGO, show_fc_host_##title, NULL)
+
+ #define SETUP_HOST_ATTRIBUTE_RD(field) \
+- i->private_host_attrs[count] = class_device_attr_host_##field; \
++ i->private_host_attrs[count] = device_attr_host_##field; \
+ i->private_host_attrs[count].attr.mode = S_IRUGO; \
+ i->private_host_attrs[count].store = NULL; \
+ i->host_attrs[count] = &i->private_host_attrs[count]; \
+@@ -1333,14 +1355,14 @@ static FC_CLASS_DEVICE_ATTR(host, title, S_IRUGO, show_fc_host_##title, NULL)
+ count++
+
+ #define SETUP_HOST_ATTRIBUTE_RD_NS(field) \
+- i->private_host_attrs[count] = class_device_attr_host_##field; \
++ i->private_host_attrs[count] = device_attr_host_##field; \
+ i->private_host_attrs[count].attr.mode = S_IRUGO; \
+ i->private_host_attrs[count].store = NULL; \
+ i->host_attrs[count] = &i->private_host_attrs[count]; \
+ count++
+
+ #define SETUP_HOST_ATTRIBUTE_RW(field) \
+- i->private_host_attrs[count] = class_device_attr_host_##field; \
++ i->private_host_attrs[count] = device_attr_host_##field; \
+ if (!i->f->set_host_##field) { \
+ i->private_host_attrs[count].attr.mode = S_IRUGO; \
+ i->private_host_attrs[count].store = NULL; \
+@@ -1352,24 +1374,25 @@ static FC_CLASS_DEVICE_ATTR(host, title, S_IRUGO, show_fc_host_##title, NULL)
+
+ #define fc_private_host_show_function(field, format_string, sz, cast) \
+ static ssize_t \
+-show_fc_host_##field (struct class_device *cdev, char *buf) \
++show_fc_host_##field (struct device *dev, \
++ struct device_attribute *attr, char *buf) \
+ { \
+- struct Scsi_Host *shost = transport_class_to_shost(cdev); \
++ struct Scsi_Host *shost = transport_class_to_shost(dev); \
+ return snprintf(buf, sz, format_string, cast fc_host_##field(shost)); \
+ }
+
+ #define fc_private_host_rd_attr(field, format_string, sz) \
+ fc_private_host_show_function(field, format_string, sz, ) \
+-static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO, \
++static FC_DEVICE_ATTR(host, field, S_IRUGO, \
+ show_fc_host_##field, NULL)
+
+ #define fc_private_host_rd_attr_cast(field, format_string, sz, cast) \
+ fc_private_host_show_function(field, format_string, sz, (cast)) \
+-static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO, \
++static FC_DEVICE_ATTR(host, field, S_IRUGO, \
+ show_fc_host_##field, NULL)
+
+ #define SETUP_PRIVATE_HOST_ATTRIBUTE_RD(field) \
+- i->private_host_attrs[count] = class_device_attr_host_##field; \
++ i->private_host_attrs[count] = device_attr_host_##field; \
+ i->private_host_attrs[count].attr.mode = S_IRUGO; \
+ i->private_host_attrs[count].store = NULL; \
+ i->host_attrs[count] = &i->private_host_attrs[count]; \
+@@ -1377,7 +1400,7 @@ static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO, \
+
+ #define SETUP_PRIVATE_HOST_ATTRIBUTE_RW(field) \
+ { \
+- i->private_host_attrs[count] = class_device_attr_host_##field; \
++ i->private_host_attrs[count] = device_attr_host_##field; \
+ i->host_attrs[count] = &i->private_host_attrs[count]; \
+ count++; \
+ }
+@@ -1386,38 +1409,41 @@ static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO, \
+ /* Fixed Host Attributes */
+
+ static ssize_t
+-show_fc_host_supported_classes (struct class_device *cdev, char *buf)
++show_fc_host_supported_classes (struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct Scsi_Host *shost = transport_class_to_shost(cdev);
++ struct Scsi_Host *shost = transport_class_to_shost(dev);
+
+ if (fc_host_supported_classes(shost) == FC_COS_UNSPECIFIED)
+ return snprintf(buf, 20, "unspecified\n");
+
+ return get_fc_cos_names(fc_host_supported_classes(shost), buf);
+ }
+-static FC_CLASS_DEVICE_ATTR(host, supported_classes, S_IRUGO,
++static FC_DEVICE_ATTR(host, supported_classes, S_IRUGO,
+ show_fc_host_supported_classes, NULL);
+
+ static ssize_t
+-show_fc_host_supported_fc4s (struct class_device *cdev, char *buf)
++show_fc_host_supported_fc4s (struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct Scsi_Host *shost = transport_class_to_shost(cdev);
++ struct Scsi_Host *shost = transport_class_to_shost(dev);
+ return (ssize_t)show_fc_fc4s(buf, fc_host_supported_fc4s(shost));
+ }
+-static FC_CLASS_DEVICE_ATTR(host, supported_fc4s, S_IRUGO,
++static FC_DEVICE_ATTR(host, supported_fc4s, S_IRUGO,
+ show_fc_host_supported_fc4s, NULL);
+
+ static ssize_t
+-show_fc_host_supported_speeds (struct class_device *cdev, char *buf)
++show_fc_host_supported_speeds (struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct Scsi_Host *shost = transport_class_to_shost(cdev);
++ struct Scsi_Host *shost = transport_class_to_shost(dev);
+
+ if (fc_host_supported_speeds(shost) == FC_PORTSPEED_UNKNOWN)
+ return snprintf(buf, 20, "unknown\n");
+
+ return get_fc_port_speed_names(fc_host_supported_speeds(shost), buf);
+ }
+-static FC_CLASS_DEVICE_ATTR(host, supported_speeds, S_IRUGO,
++static FC_DEVICE_ATTR(host, supported_speeds, S_IRUGO,
+ show_fc_host_supported_speeds, NULL);
+
+
+@@ -1433,9 +1459,10 @@ fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1));
+ /* Dynamic Host Attributes */
+
+ static ssize_t
+-show_fc_host_active_fc4s (struct class_device *cdev, char *buf)
++show_fc_host_active_fc4s (struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct Scsi_Host *shost = transport_class_to_shost(cdev);
++ struct Scsi_Host *shost = transport_class_to_shost(dev);
+ struct fc_internal *i = to_fc_internal(shost->transportt);
+
+ if (i->f->get_host_active_fc4s)
+@@ -1443,13 +1470,14 @@ show_fc_host_active_fc4s (struct class_device *cdev, char *buf)
+
+ return (ssize_t)show_fc_fc4s(buf, fc_host_active_fc4s(shost));
+ }
+-static FC_CLASS_DEVICE_ATTR(host, active_fc4s, S_IRUGO,
++static FC_DEVICE_ATTR(host, active_fc4s, S_IRUGO,
+ show_fc_host_active_fc4s, NULL);
+
+ static ssize_t
+-show_fc_host_speed (struct class_device *cdev, char *buf)
++show_fc_host_speed (struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct Scsi_Host *shost = transport_class_to_shost(cdev);
++ struct Scsi_Host *shost = transport_class_to_shost(dev);
+ struct fc_internal *i = to_fc_internal(shost->transportt);
+
+ if (i->f->get_host_speed)
+@@ -1460,7 +1488,7 @@ show_fc_host_speed (struct class_device *cdev, char *buf)
+
+ return get_fc_port_speed_names(fc_host_speed(shost), buf);
+ }
+-static FC_CLASS_DEVICE_ATTR(host, speed, S_IRUGO,
++static FC_DEVICE_ATTR(host, speed, S_IRUGO,
+ show_fc_host_speed, NULL);
+
+
+@@ -1473,16 +1501,17 @@ fc_host_rd_attr(symbolic_name, "%s\n", FC_SYMBOLIC_NAME_SIZE + 1);
+ fc_private_host_show_function(system_hostname, "%s\n",
+ FC_SYMBOLIC_NAME_SIZE + 1, )
+ fc_host_store_str_function(system_hostname, FC_SYMBOLIC_NAME_SIZE)
+-static FC_CLASS_DEVICE_ATTR(host, system_hostname, S_IRUGO | S_IWUSR,
++static FC_DEVICE_ATTR(host, system_hostname, S_IRUGO | S_IWUSR,
+ show_fc_host_system_hostname, store_fc_host_system_hostname);
+
+
+ /* Private Host Attributes */
+
+ static ssize_t
+-show_fc_private_host_tgtid_bind_type(struct class_device *cdev, char *buf)
++show_fc_private_host_tgtid_bind_type(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct Scsi_Host *shost = transport_class_to_shost(cdev);
++ struct Scsi_Host *shost = transport_class_to_shost(dev);
+ const char *name;
+
+ name = get_fc_tgtid_bind_type_name(fc_host_tgtid_bind_type(shost));
+@@ -1495,10 +1524,10 @@ show_fc_private_host_tgtid_bind_type(struct class_device *cdev, char *buf)
+ pos = list_entry((head)->next, typeof(*pos), member)
+
+ static ssize_t
+-store_fc_private_host_tgtid_bind_type(struct class_device *cdev,
+- const char *buf, size_t count)
++store_fc_private_host_tgtid_bind_type(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
+ {
+- struct Scsi_Host *shost = transport_class_to_shost(cdev);
++ struct Scsi_Host *shost = transport_class_to_shost(dev);
+ struct fc_rport *rport;
+ enum fc_tgtid_binding_type val;
+ unsigned long flags;
+@@ -1523,15 +1552,15 @@ store_fc_private_host_tgtid_bind_type(struct class_device *cdev,
+ return count;
+ }
+
+-static FC_CLASS_DEVICE_ATTR(host, tgtid_bind_type, S_IRUGO | S_IWUSR,
++static FC_DEVICE_ATTR(host, tgtid_bind_type, S_IRUGO | S_IWUSR,
+ show_fc_private_host_tgtid_bind_type,
+ store_fc_private_host_tgtid_bind_type);
+
+ static ssize_t
+-store_fc_private_host_issue_lip(struct class_device *cdev,
+- const char *buf, size_t count)
++store_fc_private_host_issue_lip(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
+ {
+- struct Scsi_Host *shost = transport_class_to_shost(cdev);
++ struct Scsi_Host *shost = transport_class_to_shost(dev);
+ struct fc_internal *i = to_fc_internal(shost->transportt);
+ int ret;
+
+@@ -1544,7 +1573,7 @@ store_fc_private_host_issue_lip(struct class_device *cdev,
+ return -ENOENT;
+ }
+
+-static FC_CLASS_DEVICE_ATTR(host, issue_lip, S_IWUSR, NULL,
++static FC_DEVICE_ATTR(host, issue_lip, S_IWUSR, NULL,
+ store_fc_private_host_issue_lip);
+
+ fc_private_host_rd_attr(npiv_vports_inuse, "%u\n", 20);
+@@ -1556,9 +1585,9 @@ fc_private_host_rd_attr(npiv_vports_inuse, "%u\n", 20);
+
+ /* Show a given an attribute in the statistics group */
+ static ssize_t
+-fc_stat_show(const struct class_device *cdev, char *buf, unsigned long offset)
++fc_stat_show(const struct device *dev, char *buf, unsigned long offset)
+ {
+- struct Scsi_Host *shost = transport_class_to_shost(cdev);
++ struct Scsi_Host *shost = transport_class_to_shost(dev);
+ struct fc_internal *i = to_fc_internal(shost->transportt);
+ struct fc_host_statistics *stats;
+ ssize_t ret = -ENOENT;
+@@ -1579,12 +1608,14 @@ fc_stat_show(const struct class_device *cdev, char *buf, unsigned long offset)
+
+ /* generate a read-only statistics attribute */
+ #define fc_host_statistic(name) \
+-static ssize_t show_fcstat_##name(struct class_device *cd, char *buf) \
++static ssize_t show_fcstat_##name(struct device *cd, \
++ struct device_attribute *attr, \
++ char *buf) \
+ { \
+ return fc_stat_show(cd, buf, \
+ offsetof(struct fc_host_statistics, name)); \
+ } \
+-static FC_CLASS_DEVICE_ATTR(host, name, S_IRUGO, show_fcstat_##name, NULL)
++static FC_DEVICE_ATTR(host, name, S_IRUGO, show_fcstat_##name, NULL)
+
+ fc_host_statistic(seconds_since_last_reset);
+ fc_host_statistic(tx_frames);
+@@ -1608,10 +1639,10 @@ fc_host_statistic(fcp_input_megabytes);
+ fc_host_statistic(fcp_output_megabytes);
+
+ static ssize_t
+-fc_reset_statistics(struct class_device *cdev, const char *buf,
+- size_t count)
++fc_reset_statistics(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+- struct Scsi_Host *shost = transport_class_to_shost(cdev);
++ struct Scsi_Host *shost = transport_class_to_shost(dev);
+ struct fc_internal *i = to_fc_internal(shost->transportt);
+
+ /* ignore any data value written to the attribute */
+@@ -1622,31 +1653,31 @@ fc_reset_statistics(struct class_device *cdev, const char *buf,
+
+ return -ENOENT;
+ }
+-static FC_CLASS_DEVICE_ATTR(host, reset_statistics, S_IWUSR, NULL,
++static FC_DEVICE_ATTR(host, reset_statistics, S_IWUSR, NULL,
+ fc_reset_statistics);
+
+ static struct attribute *fc_statistics_attrs[] = {
+- &class_device_attr_host_seconds_since_last_reset.attr,
+- &class_device_attr_host_tx_frames.attr,
+- &class_device_attr_host_tx_words.attr,
+- &class_device_attr_host_rx_frames.attr,
+- &class_device_attr_host_rx_words.attr,
+- &class_device_attr_host_lip_count.attr,
+- &class_device_attr_host_nos_count.attr,
+- &class_device_attr_host_error_frames.attr,
+- &class_device_attr_host_dumped_frames.attr,
+- &class_device_attr_host_link_failure_count.attr,
+- &class_device_attr_host_loss_of_sync_count.attr,
+- &class_device_attr_host_loss_of_signal_count.attr,
+- &class_device_attr_host_prim_seq_protocol_err_count.attr,
+- &class_device_attr_host_invalid_tx_word_count.attr,
+- &class_device_attr_host_invalid_crc_count.attr,
+- &class_device_attr_host_fcp_input_requests.attr,
+- &class_device_attr_host_fcp_output_requests.attr,
+- &class_device_attr_host_fcp_control_requests.attr,
+- &class_device_attr_host_fcp_input_megabytes.attr,
+- &class_device_attr_host_fcp_output_megabytes.attr,
+- &class_device_attr_host_reset_statistics.attr,
++ &device_attr_host_seconds_since_last_reset.attr,
++ &device_attr_host_tx_frames.attr,
++ &device_attr_host_tx_words.attr,
++ &device_attr_host_rx_frames.attr,
++ &device_attr_host_rx_words.attr,
++ &device_attr_host_lip_count.attr,
++ &device_attr_host_nos_count.attr,
++ &device_attr_host_error_frames.attr,
++ &device_attr_host_dumped_frames.attr,
++ &device_attr_host_link_failure_count.attr,
++ &device_attr_host_loss_of_sync_count.attr,
++ &device_attr_host_loss_of_signal_count.attr,
++ &device_attr_host_prim_seq_protocol_err_count.attr,
++ &device_attr_host_invalid_tx_word_count.attr,
++ &device_attr_host_invalid_crc_count.attr,
++ &device_attr_host_fcp_input_requests.attr,
++ &device_attr_host_fcp_output_requests.attr,
++ &device_attr_host_fcp_control_requests.attr,
++ &device_attr_host_fcp_input_megabytes.attr,
++ &device_attr_host_fcp_output_megabytes.attr,
++ &device_attr_host_reset_statistics.attr,
+ NULL
+ };
+
+@@ -1695,10 +1726,10 @@ fc_parse_wwn(const char *ns, u64 *nm)
+ * as hex characters, and may *not* contain any prefixes (e.g. 0x, x, etc)
+ */
+ static ssize_t
+-store_fc_host_vport_create(struct class_device *cdev, const char *buf,
+- size_t count)
++store_fc_host_vport_create(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+- struct Scsi_Host *shost = transport_class_to_shost(cdev);
++ struct Scsi_Host *shost = transport_class_to_shost(dev);
+ struct fc_vport_identifiers vid;
+ struct fc_vport *vport;
+ unsigned int cnt=count;
+@@ -1731,7 +1762,7 @@ store_fc_host_vport_create(struct class_device *cdev, const char *buf,
+ stat = fc_vport_create(shost, 0, &shost->shost_gendev, &vid, &vport);
+ return stat ? stat : count;
+ }
+-static FC_CLASS_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL,
++static FC_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL,
+ store_fc_host_vport_create);
+
+
+@@ -1742,10 +1773,10 @@ static FC_CLASS_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL,
+ * any prefixes (e.g. 0x, x, etc)
+ */
+ static ssize_t
+-store_fc_host_vport_delete(struct class_device *cdev, const char *buf,
+- size_t count)
++store_fc_host_vport_delete(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+- struct Scsi_Host *shost = transport_class_to_shost(cdev);
++ struct Scsi_Host *shost = transport_class_to_shost(dev);
+ struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+ struct fc_vport *vport;
+ u64 wwpn, wwnn;
+@@ -1787,7 +1818,7 @@ store_fc_host_vport_delete(struct class_device *cdev, const char *buf,
+ stat = fc_vport_terminate(vport);
+ return stat ? stat : count;
+ }
+-static FC_CLASS_DEVICE_ATTR(host, vport_delete, S_IWUSR, NULL,
++static FC_DEVICE_ATTR(host, vport_delete, S_IWUSR, NULL,
+ store_fc_host_vport_delete);
+
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index ca7bb6f..65d1737 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -40,13 +40,13 @@ struct iscsi_internal {
+ struct scsi_transport_template t;
+ struct iscsi_transport *iscsi_transport;
+ struct list_head list;
+- struct class_device cdev;
++ struct device dev;
+
+- struct class_device_attribute *host_attrs[ISCSI_HOST_ATTRS + 1];
++ struct device_attribute *host_attrs[ISCSI_HOST_ATTRS + 1];
+ struct transport_container conn_cont;
+- struct class_device_attribute *conn_attrs[ISCSI_CONN_ATTRS + 1];
++ struct device_attribute *conn_attrs[ISCSI_CONN_ATTRS + 1];
+ struct transport_container session_cont;
+- struct class_device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1];
++ struct device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1];
+ };
+
+ static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
+@@ -63,12 +63,12 @@ static DEFINE_SPINLOCK(iscsi_transport_lock);
+ #define to_iscsi_internal(tmpl) \
+ container_of(tmpl, struct iscsi_internal, t)
+
+-#define cdev_to_iscsi_internal(_cdev) \
+- container_of(_cdev, struct iscsi_internal, cdev)
++#define dev_to_iscsi_internal(_dev) \
++ container_of(_dev, struct iscsi_internal, dev)
+
+-static void iscsi_transport_release(struct class_device *cdev)
++static void iscsi_transport_release(struct device *dev)
+ {
+- struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev);
++ struct iscsi_internal *priv = dev_to_iscsi_internal(dev);
+ kfree(priv);
+ }
+
+@@ -78,25 +78,27 @@ static void iscsi_transport_release(struct class_device *cdev)
+ */
+ static struct class iscsi_transport_class = {
+ .name = "iscsi_transport",
+- .release = iscsi_transport_release,
++ .dev_release = iscsi_transport_release,
+ };
+
+ static ssize_t
+-show_transport_handle(struct class_device *cdev, char *buf)
++show_transport_handle(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev);
++ struct iscsi_internal *priv = dev_to_iscsi_internal(dev);
+ return sprintf(buf, "%llu\n", (unsigned long long)iscsi_handle(priv->iscsi_transport));
+ }
+-static CLASS_DEVICE_ATTR(handle, S_IRUGO, show_transport_handle, NULL);
++static DEVICE_ATTR(handle, S_IRUGO, show_transport_handle, NULL);
+
+ #define show_transport_attr(name, format) \
+ static ssize_t \
+-show_transport_##name(struct class_device *cdev, char *buf) \
++show_transport_##name(struct device *dev, \
++ struct device_attribute *attr,char *buf) \
+ { \
+- struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev); \
++ struct iscsi_internal *priv = dev_to_iscsi_internal(dev); \
+ return sprintf(buf, format"\n", priv->iscsi_transport->name); \
+ } \
+-static CLASS_DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL);
++static DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL);
+
+ show_transport_attr(caps, "0x%x");
+ show_transport_attr(max_lun, "%d");
+@@ -104,11 +106,11 @@ show_transport_attr(max_conn, "%d");
+ show_transport_attr(max_cmd_len, "%d");
+
+ static struct attribute *iscsi_transport_attrs[] = {
+- &class_device_attr_handle.attr,
+- &class_device_attr_caps.attr,
+- &class_device_attr_max_lun.attr,
+- &class_device_attr_max_conn.attr,
+- &class_device_attr_max_cmd_len.attr,
++ &dev_attr_handle.attr,
++ &dev_attr_caps.attr,
++ &dev_attr_max_lun.attr,
++ &dev_attr_max_conn.attr,
++ &dev_attr_max_cmd_len.attr,
+ NULL,
+ };
+
+@@ -119,7 +121,7 @@ static struct attribute_group iscsi_transport_group = {
+
+
+ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+- struct class_device *cdev)
++ struct device *cdev)
+ {
+ struct Scsi_Host *shost = dev_to_shost(dev);
+ struct iscsi_host *ihost = shost->shost_data;
+@@ -139,7 +141,7 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+ }
+
+ static int iscsi_remove_host(struct transport_container *tc, struct device *dev,
+- struct class_device *cdev)
++ struct device *cdev)
+ {
+ struct Scsi_Host *shost = dev_to_shost(dev);
+ struct iscsi_host *ihost = shost->shost_data;
+@@ -1337,11 +1339,8 @@ iscsi_if_rx(struct sk_buff *skb)
+ mutex_unlock(&rx_queue_mutex);
+ }
+
+-#define iscsi_cdev_to_conn(_cdev) \
+- iscsi_dev_to_conn(_cdev->dev)
+-
+ #define ISCSI_CLASS_ATTR(_prefix,_name,_mode,_show,_store) \
+-struct class_device_attribute class_device_attr_##_prefix##_##_name = \
++struct device_attribute dev_attr_##_prefix##_##_name = \
+ __ATTR(_name,_mode,_show,_store)
+
+ /*
+@@ -1349,9 +1348,10 @@ struct class_device_attribute class_device_attr_##_prefix##_##_name = \
+ */
+ #define iscsi_conn_attr_show(param) \
+ static ssize_t \
+-show_conn_param_##param(struct class_device *cdev, char *buf) \
++show_conn_param_##param(struct device *dev, \
++ struct device_attribute *attr, char *buf) \
+ { \
+- struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \
++ struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent); \
+ struct iscsi_transport *t = conn->transport; \
+ return t->get_conn_param(conn, param, buf); \
+ }
+@@ -1375,17 +1375,16 @@ iscsi_conn_attr(address, ISCSI_PARAM_CONN_ADDRESS);
+ iscsi_conn_attr(ping_tmo, ISCSI_PARAM_PING_TMO);
+ iscsi_conn_attr(recv_tmo, ISCSI_PARAM_RECV_TMO);
+
+-#define iscsi_cdev_to_session(_cdev) \
+- iscsi_dev_to_session(_cdev->dev)
+-
+ /*
+ * iSCSI session attrs
+ */
+ #define iscsi_session_attr_show(param, perm) \
+ static ssize_t \
+-show_session_param_##param(struct class_device *cdev, char *buf) \
++show_session_param_##param(struct device *dev, \
++ struct device_attribute *attr, char *buf) \
+ { \
+- struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
++ struct iscsi_cls_session *session = \
++ iscsi_dev_to_session(dev->parent); \
+ struct iscsi_transport *t = session->transport; \
+ \
+ if (perm && !capable(CAP_SYS_ADMIN)) \
+@@ -1417,9 +1416,10 @@ iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0);
+ iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 0);
+
+ static ssize_t
+-show_priv_session_state(struct class_device *cdev, char *buf)
++show_priv_session_state(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev);
++ struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
+ return sprintf(buf, "%s\n", iscsi_session_state_name(session->state));
+ }
+ static ISCSI_CLASS_ATTR(priv_sess, state, S_IRUGO, show_priv_session_state,
+@@ -1427,9 +1427,11 @@ static ISCSI_CLASS_ATTR(priv_sess, state, S_IRUGO, show_priv_session_state,
+
+ #define iscsi_priv_session_attr_show(field, format) \
+ static ssize_t \
+-show_priv_session_##field(struct class_device *cdev, char *buf) \
++show_priv_session_##field(struct device *dev, \
++ struct device_attribute *attr, char *buf) \
+ { \
+- struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev);\
++ struct iscsi_cls_session *session = \
++ iscsi_dev_to_session(dev->parent); \
+ return sprintf(buf, format"\n", session->field); \
+ }
+
+@@ -1444,9 +1446,10 @@ iscsi_priv_session_attr(recovery_tmo, "%d");
+ */
+ #define iscsi_host_attr_show(param) \
+ static ssize_t \
+-show_host_param_##param(struct class_device *cdev, char *buf) \
++show_host_param_##param(struct device *dev, \
++ struct device_attribute *attr, char *buf) \
+ { \
+- struct Scsi_Host *shost = transport_class_to_shost(cdev); \
++ struct Scsi_Host *shost = transport_class_to_shost(dev); \
+ struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \
+ return priv->iscsi_transport->get_host_param(shost, param, buf); \
+ }
+@@ -1463,7 +1466,7 @@ iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME);
+
+ #define SETUP_PRIV_SESSION_RD_ATTR(field) \
+ do { \
+- priv->session_attrs[count] = &class_device_attr_priv_sess_##field; \
++ priv->session_attrs[count] = &dev_attr_priv_sess_##field; \
+ count++; \
+ } while (0)
+
+@@ -1471,7 +1474,7 @@ do { \
+ #define SETUP_SESSION_RD_ATTR(field, param_flag) \
+ do { \
+ if (tt->param_mask & param_flag) { \
+- priv->session_attrs[count] = &class_device_attr_sess_##field; \
++ priv->session_attrs[count] = &dev_attr_sess_##field; \
+ count++; \
+ } \
+ } while (0)
+@@ -1479,7 +1482,7 @@ do { \
+ #define SETUP_CONN_RD_ATTR(field, param_flag) \
+ do { \
+ if (tt->param_mask & param_flag) { \
+- priv->conn_attrs[count] = &class_device_attr_conn_##field; \
++ priv->conn_attrs[count] = &dev_attr_conn_##field; \
+ count++; \
+ } \
+ } while (0)
+@@ -1487,7 +1490,7 @@ do { \
+ #define SETUP_HOST_RD_ATTR(field, param_flag) \
+ do { \
+ if (tt->host_param_mask & param_flag) { \
+- priv->host_attrs[count] = &class_device_attr_host_##field; \
++ priv->host_attrs[count] = &dev_attr_host_##field; \
+ count++; \
+ } \
+ } while (0)
+@@ -1578,15 +1581,15 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ priv->iscsi_transport = tt;
+ priv->t.user_scan = iscsi_user_scan;
+
+- priv->cdev.class = &iscsi_transport_class;
+- snprintf(priv->cdev.class_id, BUS_ID_SIZE, "%s", tt->name);
+- err = class_device_register(&priv->cdev);
++ priv->dev.class = &iscsi_transport_class;
++ snprintf(priv->dev.bus_id, BUS_ID_SIZE, "%s", tt->name);
++ err = device_register(&priv->dev);
+ if (err)
+ goto free_priv;
+
+- err = sysfs_create_group(&priv->cdev.kobj, &iscsi_transport_group);
++ err = sysfs_create_group(&priv->dev.kobj, &iscsi_transport_group);
+ if (err)
+- goto unregister_cdev;
++ goto unregister_dev;
+
+ /* host parameters */
+ priv->t.host_attrs.ac.attrs = &priv->host_attrs[0];
+@@ -1663,8 +1666,8 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name);
+ return &priv->t;
+
+-unregister_cdev:
+- class_device_unregister(&priv->cdev);
++unregister_dev:
++ device_unregister(&priv->dev);
+ free_priv:
+ kfree(priv);
+ return NULL;
+@@ -1691,8 +1694,8 @@ int iscsi_unregister_transport(struct iscsi_transport *tt)
+ transport_container_unregister(&priv->session_cont);
+ transport_container_unregister(&priv->t.host_attrs);
+
+- sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group);
+- class_device_unregister(&priv->cdev);
++ sysfs_remove_group(&priv->dev.kobj, &iscsi_transport_group);
++ device_unregister(&priv->dev);
+ mutex_unlock(&rx_queue_mutex);
+
+ return 0;
+diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
+index 43a964d..27ec625 100644
+--- a/drivers/scsi/scsi_transport_sas.c
++++ b/drivers/scsi/scsi_transport_sas.c
+@@ -53,8 +53,8 @@ struct sas_host_attrs {
+ /*
+ * Hack to allow attributes of the same name in different objects.
+ */
+-#define SAS_CLASS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \
+- struct class_device_attribute class_device_attr_##_prefix##_##_name = \
++#define SAS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \
++ struct device_attribute dev_attr_##_prefix##_##_name = \
+ __ATTR(_name,_mode,_show,_store)
+
+
+@@ -261,7 +261,7 @@ static void sas_bsg_remove(struct Scsi_Host *shost, struct sas_rphy *rphy)
+ */
+
+ static int sas_host_setup(struct transport_container *tc, struct device *dev,
+- struct class_device *cdev)
++ struct device *cdev)
+ {
+ struct Scsi_Host *shost = dev_to_shost(dev);
+ struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
+@@ -280,7 +280,7 @@ static int sas_host_setup(struct transport_container *tc, struct device *dev,
+ }
+
+ static int sas_host_remove(struct transport_container *tc, struct device *dev,
+- struct class_device *cdev)
++ struct device *cdev)
+ {
+ struct Scsi_Host *shost = dev_to_shost(dev);
+
+@@ -356,22 +356,24 @@ EXPORT_SYMBOL(sas_remove_host);
+
+ #define sas_phy_show_simple(field, name, format_string, cast) \
+ static ssize_t \
+-show_sas_phy_##name(struct class_device *cdev, char *buf) \
++show_sas_phy_##name(struct device *dev, \
++ struct device_attribute *attr, char *buf) \
+ { \
+- struct sas_phy *phy = transport_class_to_phy(cdev); \
++ struct sas_phy *phy = transport_class_to_phy(dev); \
+ \
+ return snprintf(buf, 20, format_string, cast phy->field); \
+ }
+
+ #define sas_phy_simple_attr(field, name, format_string, type) \
+ sas_phy_show_simple(field, name, format_string, (type)) \
+-static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)
++static DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)
+
+ #define sas_phy_show_protocol(field, name) \
+ static ssize_t \
+-show_sas_phy_##name(struct class_device *cdev, char *buf) \
++show_sas_phy_##name(struct device *dev, \
++ struct device_attribute *attr, char *buf) \
+ { \
+- struct sas_phy *phy = transport_class_to_phy(cdev); \
++ struct sas_phy *phy = transport_class_to_phy(dev); \
+ \
+ if (!phy->field) \
+ return snprintf(buf, 20, "none\n"); \
+@@ -380,13 +382,14 @@ show_sas_phy_##name(struct class_device *cdev, char *buf) \
+
+ #define sas_phy_protocol_attr(field, name) \
+ sas_phy_show_protocol(field, name) \
+-static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)
++static DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)
+
+ #define sas_phy_show_linkspeed(field) \
+ static ssize_t \
+-show_sas_phy_##field(struct class_device *cdev, char *buf) \
++show_sas_phy_##field(struct device *dev, \
++ struct device_attribute *attr, char *buf) \
+ { \
+- struct sas_phy *phy = transport_class_to_phy(cdev); \
++ struct sas_phy *phy = transport_class_to_phy(dev); \
+ \
+ return get_sas_linkspeed_names(phy->field, buf); \
+ }
+@@ -394,10 +397,11 @@ show_sas_phy_##field(struct class_device *cdev, char *buf) \
+ /* Fudge to tell if we're minimum or maximum */
+ #define sas_phy_store_linkspeed(field) \
+ static ssize_t \
+-store_sas_phy_##field(struct class_device *cdev, const char *buf, \
+- size_t count) \
++store_sas_phy_##field(struct device *dev, \
++ struct device_attribute *attr, \
++ const char *buf, size_t count) \
+ { \
+- struct sas_phy *phy = transport_class_to_phy(cdev); \
++ struct sas_phy *phy = transport_class_to_phy(dev); \
+ struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); \
+ struct sas_internal *i = to_sas_internal(shost->transportt); \
+ u32 value; \
+@@ -416,19 +420,20 @@ store_sas_phy_##field(struct class_device *cdev, const char *buf, \
+ #define sas_phy_linkspeed_rw_attr(field) \
+ sas_phy_show_linkspeed(field) \
+ sas_phy_store_linkspeed(field) \
+-static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, \
++static DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, \
+ store_sas_phy_##field)
+
+ #define sas_phy_linkspeed_attr(field) \
+ sas_phy_show_linkspeed(field) \
+-static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL)
++static DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL)
+
+
+ #define sas_phy_show_linkerror(field) \
+ static ssize_t \
+-show_sas_phy_##field(struct class_device *cdev, char *buf) \
++show_sas_phy_##field(struct device *dev, \
++ struct device_attribute *attr, char *buf) \
+ { \
+- struct sas_phy *phy = transport_class_to_phy(cdev); \
++ struct sas_phy *phy = transport_class_to_phy(dev); \
+ struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); \
+ struct sas_internal *i = to_sas_internal(shost->transportt); \
+ int error; \
+@@ -441,24 +446,25 @@ show_sas_phy_##field(struct class_device *cdev, char *buf) \
+
+ #define sas_phy_linkerror_attr(field) \
+ sas_phy_show_linkerror(field) \
+-static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL)
++static DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL)
+
+
+ static ssize_t
+-show_sas_device_type(struct class_device *cdev, char *buf)
++show_sas_device_type(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct sas_phy *phy = transport_class_to_phy(cdev);
++ struct sas_phy *phy = transport_class_to_phy(dev);
+
+ if (!phy->identify.device_type)
+ return snprintf(buf, 20, "none\n");
+ return get_sas_device_type_names(phy->identify.device_type, buf);
+ }
+-static CLASS_DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL);
++static DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL);
+
+-static ssize_t do_sas_phy_enable(struct class_device *cdev,
++static ssize_t do_sas_phy_enable(struct device *dev,
+ size_t count, int enable)
+ {
+- struct sas_phy *phy = transport_class_to_phy(cdev);
++ struct sas_phy *phy = transport_class_to_phy(dev);
+ struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+ struct sas_internal *i = to_sas_internal(shost->transportt);
+ int error;
+@@ -470,18 +476,19 @@ static ssize_t do_sas_phy_enable(struct class_device *cdev,
+ return count;
+ };
+
+-static ssize_t store_sas_phy_enable(struct class_device *cdev,
+- const char *buf, size_t count)
++static ssize_t
++store_sas_phy_enable(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+ if (count < 1)
+ return -EINVAL;
+
+ switch (buf[0]) {
+ case '0':
+- do_sas_phy_enable(cdev, count, 0);
++ do_sas_phy_enable(dev, count, 0);
+ break;
+ case '1':
+- do_sas_phy_enable(cdev, count, 1);
++ do_sas_phy_enable(dev, count, 1);
+ break;
+ default:
+ return -EINVAL;
+@@ -490,20 +497,22 @@ static ssize_t store_sas_phy_enable(struct class_device *cdev,
+ return count;
+ }
+
+-static ssize_t show_sas_phy_enable(struct class_device *cdev, char *buf)
++static ssize_t
++show_sas_phy_enable(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct sas_phy *phy = transport_class_to_phy(cdev);
++ struct sas_phy *phy = transport_class_to_phy(dev);
+
+ return snprintf(buf, 20, "%d", phy->enabled);
+ }
+
+-static CLASS_DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, show_sas_phy_enable,
++static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, show_sas_phy_enable,
+ store_sas_phy_enable);
+
+-static ssize_t do_sas_phy_reset(struct class_device *cdev,
+- size_t count, int hard_reset)
++static ssize_t
++do_sas_phy_reset(struct device *dev, size_t count, int hard_reset)
+ {
+- struct sas_phy *phy = transport_class_to_phy(cdev);
++ struct sas_phy *phy = transport_class_to_phy(dev);
+ struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+ struct sas_internal *i = to_sas_internal(shost->transportt);
+ int error;
+@@ -514,19 +523,21 @@ static ssize_t do_sas_phy_reset(struct class_device *cdev,
+ return count;
+ };
+
+-static ssize_t store_sas_link_reset(struct class_device *cdev,
+- const char *buf, size_t count)
++static ssize_t
++store_sas_link_reset(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+- return do_sas_phy_reset(cdev, count, 0);
++ return do_sas_phy_reset(dev, count, 0);
+ }
+-static CLASS_DEVICE_ATTR(link_reset, S_IWUSR, NULL, store_sas_link_reset);
++static DEVICE_ATTR(link_reset, S_IWUSR, NULL, store_sas_link_reset);
+
+-static ssize_t store_sas_hard_reset(struct class_device *cdev,
+- const char *buf, size_t count)
++static ssize_t
++store_sas_hard_reset(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+- return do_sas_phy_reset(cdev, count, 1);
++ return do_sas_phy_reset(dev, count, 1);
+ }
+-static CLASS_DEVICE_ATTR(hard_reset, S_IWUSR, NULL, store_sas_hard_reset);
++static DEVICE_ATTR(hard_reset, S_IWUSR, NULL, store_sas_hard_reset);
+
+ sas_phy_protocol_attr(identify.initiator_port_protocols,
+ initiator_port_protocols);
+@@ -695,16 +706,17 @@ EXPORT_SYMBOL(scsi_is_sas_phy);
+ */
+ #define sas_port_show_simple(field, name, format_string, cast) \
+ static ssize_t \
+-show_sas_port_##name(struct class_device *cdev, char *buf) \
++show_sas_port_##name(struct device *dev, \
++ struct device_attribute *attr, char *buf) \
+ { \
+- struct sas_port *port = transport_class_to_sas_port(cdev); \
++ struct sas_port *port = transport_class_to_sas_port(dev); \
+ \
+ return snprintf(buf, 20, format_string, cast port->field); \
+ }
+
+ #define sas_port_simple_attr(field, name, format_string, type) \
+ sas_port_show_simple(field, name, format_string, (type)) \
+-static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_port_##name, NULL)
++static DEVICE_ATTR(name, S_IRUGO, show_sas_port_##name, NULL)
+
+ sas_port_simple_attr(num_phys, num_phys, "%d\n", int);
+
+@@ -1017,23 +1029,25 @@ EXPORT_SYMBOL(sas_port_mark_backlink);
+
+ #define sas_rphy_show_simple(field, name, format_string, cast) \
+ static ssize_t \
+-show_sas_rphy_##name(struct class_device *cdev, char *buf) \
++show_sas_rphy_##name(struct device *dev, \
++ struct device_attribute *attr, char *buf) \
+ { \
+- struct sas_rphy *rphy = transport_class_to_rphy(cdev); \
++ struct sas_rphy *rphy = transport_class_to_rphy(dev); \
+ \
+ return snprintf(buf, 20, format_string, cast rphy->field); \
+ }
+
+ #define sas_rphy_simple_attr(field, name, format_string, type) \
+ sas_rphy_show_simple(field, name, format_string, (type)) \
+-static SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \
++static SAS_DEVICE_ATTR(rphy, name, S_IRUGO, \
+ show_sas_rphy_##name, NULL)
+
+ #define sas_rphy_show_protocol(field, name) \
+ static ssize_t \
+-show_sas_rphy_##name(struct class_device *cdev, char *buf) \
++show_sas_rphy_##name(struct device *dev, \
++ struct device_attribute *attr, char *buf) \
+ { \
+- struct sas_rphy *rphy = transport_class_to_rphy(cdev); \
++ struct sas_rphy *rphy = transport_class_to_rphy(dev); \
+ \
+ if (!rphy->field) \
+ return snprintf(buf, 20, "none\n"); \
+@@ -1042,13 +1056,14 @@ show_sas_rphy_##name(struct class_device *cdev, char *buf) \
+
+ #define sas_rphy_protocol_attr(field, name) \
+ sas_rphy_show_protocol(field, name) \
+-static SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \
++static SAS_DEVICE_ATTR(rphy, name, S_IRUGO, \
+ show_sas_rphy_##name, NULL)
+
+ static ssize_t
+-show_sas_rphy_device_type(struct class_device *cdev, char *buf)
++show_sas_rphy_device_type(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct sas_rphy *rphy = transport_class_to_rphy(cdev);
++ struct sas_rphy *rphy = transport_class_to_rphy(dev);
+
+ if (!rphy->identify.device_type)
+ return snprintf(buf, 20, "none\n");
+@@ -1056,13 +1071,14 @@ show_sas_rphy_device_type(struct class_device *cdev, char *buf)
+ rphy->identify.device_type, buf);
+ }
+
+-static SAS_CLASS_DEVICE_ATTR(rphy, device_type, S_IRUGO,
++static SAS_DEVICE_ATTR(rphy, device_type, S_IRUGO,
+ show_sas_rphy_device_type, NULL);
+
+ static ssize_t
+-show_sas_rphy_enclosure_identifier(struct class_device *cdev, char *buf)
++show_sas_rphy_enclosure_identifier(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct sas_rphy *rphy = transport_class_to_rphy(cdev);
++ struct sas_rphy *rphy = transport_class_to_rphy(dev);
+ struct sas_phy *phy = dev_to_phy(rphy->dev.parent);
+ struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+ struct sas_internal *i = to_sas_internal(shost->transportt);
+@@ -1082,13 +1098,14 @@ show_sas_rphy_enclosure_identifier(struct class_device *cdev, char *buf)
+ return sprintf(buf, "0x%llx\n", (unsigned long long)identifier);
+ }
+
+-static SAS_CLASS_DEVICE_ATTR(rphy, enclosure_identifier, S_IRUGO,
++static SAS_DEVICE_ATTR(rphy, enclosure_identifier, S_IRUGO,
+ show_sas_rphy_enclosure_identifier, NULL);
+
+ static ssize_t
+-show_sas_rphy_bay_identifier(struct class_device *cdev, char *buf)
++show_sas_rphy_bay_identifier(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct sas_rphy *rphy = transport_class_to_rphy(cdev);
++ struct sas_rphy *rphy = transport_class_to_rphy(dev);
+ struct sas_phy *phy = dev_to_phy(rphy->dev.parent);
+ struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+ struct sas_internal *i = to_sas_internal(shost->transportt);
+@@ -1103,7 +1120,7 @@ show_sas_rphy_bay_identifier(struct class_device *cdev, char *buf)
+ return sprintf(buf, "%d\n", val);
+ }
+
+-static SAS_CLASS_DEVICE_ATTR(rphy, bay_identifier, S_IRUGO,
++static SAS_DEVICE_ATTR(rphy, bay_identifier, S_IRUGO,
+ show_sas_rphy_bay_identifier, NULL);
+
+ sas_rphy_protocol_attr(identify.initiator_port_protocols,
+@@ -1161,9 +1178,10 @@ static DECLARE_TRANSPORT_CLASS(sas_end_dev_class,
+
+ #define sas_end_dev_show_simple(field, name, format_string, cast) \
+ static ssize_t \
+-show_sas_end_dev_##name(struct class_device *cdev, char *buf) \
++show_sas_end_dev_##name(struct device *dev, \
++ struct device_attribute *attr, char *buf) \
+ { \
+- struct sas_rphy *rphy = transport_class_to_rphy(cdev); \
++ struct sas_rphy *rphy = transport_class_to_rphy(dev); \
+ struct sas_end_device *rdev = rphy_to_end_device(rphy); \
+ \
+ return snprintf(buf, 20, format_string, cast rdev->field); \
+@@ -1171,7 +1189,7 @@ show_sas_end_dev_##name(struct class_device *cdev, char *buf) \
+
+ #define sas_end_dev_simple_attr(field, name, format_string, type) \
+ sas_end_dev_show_simple(field, name, format_string, (type)) \
+-static SAS_CLASS_DEVICE_ATTR(end_dev, name, S_IRUGO, \
++static SAS_DEVICE_ATTR(end_dev, name, S_IRUGO, \
+ show_sas_end_dev_##name, NULL)
+
+ sas_end_dev_simple_attr(ready_led_meaning, ready_led_meaning, "%d\n", int);
+@@ -1185,9 +1203,10 @@ static DECLARE_TRANSPORT_CLASS(sas_expander_class,
+
+ #define sas_expander_show_simple(field, name, format_string, cast) \
+ static ssize_t \
+-show_sas_expander_##name(struct class_device *cdev, char *buf) \
++show_sas_expander_##name(struct device *dev, \
++ struct device_attribute *attr, char *buf) \
+ { \
+- struct sas_rphy *rphy = transport_class_to_rphy(cdev); \
++ struct sas_rphy *rphy = transport_class_to_rphy(dev); \
+ struct sas_expander_device *edev = rphy_to_expander_device(rphy); \
+ \
+ return snprintf(buf, 20, format_string, cast edev->field); \
+@@ -1195,7 +1214,7 @@ show_sas_expander_##name(struct class_device *cdev, char *buf) \
+
+ #define sas_expander_simple_attr(field, name, format_string, type) \
+ sas_expander_show_simple(field, name, format_string, (type)) \
+-static SAS_CLASS_DEVICE_ATTR(expander, name, S_IRUGO, \
++static SAS_DEVICE_ATTR(expander, name, S_IRUGO, \
+ show_sas_expander_##name, NULL)
+
+ sas_expander_simple_attr(vendor_id, vendor_id, "%s\n", char *);
+@@ -1554,14 +1573,14 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
+ */
+
+ #define SETUP_TEMPLATE(attrb, field, perm, test) \
+- i->private_##attrb[count] = class_device_attr_##field; \
++ i->private_##attrb[count] = dev_attr_##field; \
+ i->private_##attrb[count].attr.mode = perm; \
+ i->attrb[count] = &i->private_##attrb[count]; \
+ if (test) \
+ count++
+
+ #define SETUP_TEMPLATE_RW(attrb, field, perm, test, ro_test, ro_perm) \
+- i->private_##attrb[count] = class_device_attr_##field; \
++ i->private_##attrb[count] = dev_attr_##field; \
+ i->private_##attrb[count].attr.mode = perm; \
+ if (ro_test) { \
+ i->private_##attrb[count].attr.mode = ro_perm; \
+diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
+index 1fb6031..bc12b5d 100644
+--- a/drivers/scsi/scsi_transport_spi.c
++++ b/drivers/scsi/scsi_transport_spi.c
+@@ -158,7 +158,7 @@ static inline enum spi_signal_type spi_signal_to_value(const char *name)
+ }
+
+ static int spi_host_setup(struct transport_container *tc, struct device *dev,
+- struct class_device *cdev)
++ struct device *cdev)
+ {
+ struct Scsi_Host *shost = dev_to_shost(dev);
+
+@@ -169,7 +169,7 @@ static int spi_host_setup(struct transport_container *tc, struct device *dev,
+
+ static int spi_host_configure(struct transport_container *tc,
+ struct device *dev,
+- struct class_device *cdev);
++ struct device *cdev);
+
+ static DECLARE_TRANSPORT_CLASS(spi_host_class,
+ "spi_host",
+@@ -195,11 +195,11 @@ static int spi_host_match(struct attribute_container *cont,
+
+ static int spi_target_configure(struct transport_container *tc,
+ struct device *dev,
+- struct class_device *cdev);
++ struct device *cdev);
+
+ static int spi_device_configure(struct transport_container *tc,
+ struct device *dev,
+- struct class_device *cdev)
++ struct device *cdev)
+ {
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct scsi_target *starget = sdev->sdev_target;
+@@ -219,7 +219,7 @@ static int spi_device_configure(struct transport_container *tc,
+
+ static int spi_setup_transport_attrs(struct transport_container *tc,
+ struct device *dev,
+- struct class_device *cdev)
++ struct device *cdev)
+ {
+ struct scsi_target *starget = to_scsi_target(dev);
+
+@@ -248,9 +248,10 @@ static int spi_setup_transport_attrs(struct transport_container *tc,
+ #define spi_transport_show_simple(field, format_string) \
+ \
+ static ssize_t \
+-show_spi_transport_##field(struct class_device *cdev, char *buf) \
++show_spi_transport_##field(struct device *dev, \
++ struct device_attribute *attr, char *buf) \
+ { \
+- struct scsi_target *starget = transport_class_to_starget(cdev); \
++ struct scsi_target *starget = transport_class_to_starget(dev); \
+ struct spi_transport_attrs *tp; \
+ \
+ tp = (struct spi_transport_attrs *)&starget->starget_data; \
+@@ -260,11 +261,12 @@ show_spi_transport_##field(struct class_device *cdev, char *buf) \
+ #define spi_transport_store_simple(field, format_string) \
+ \
+ static ssize_t \
+-store_spi_transport_##field(struct class_device *cdev, const char *buf, \
+- size_t count) \
++store_spi_transport_##field(struct device *dev, \
++ struct device_attribute *attr, \
++ const char *buf, size_t count) \
+ { \
+ int val; \
+- struct scsi_target *starget = transport_class_to_starget(cdev); \
++ struct scsi_target *starget = transport_class_to_starget(dev); \
+ struct spi_transport_attrs *tp; \
+ \
+ tp = (struct spi_transport_attrs *)&starget->starget_data; \
+@@ -276,9 +278,10 @@ store_spi_transport_##field(struct class_device *cdev, const char *buf, \
+ #define spi_transport_show_function(field, format_string) \
+ \
+ static ssize_t \
+-show_spi_transport_##field(struct class_device *cdev, char *buf) \
++show_spi_transport_##field(struct device *dev, \
++ struct device_attribute *attr, char *buf) \
+ { \
+- struct scsi_target *starget = transport_class_to_starget(cdev); \
++ struct scsi_target *starget = transport_class_to_starget(dev); \
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \
+ struct spi_transport_attrs *tp; \
+ struct spi_internal *i = to_spi_internal(shost->transportt); \
+@@ -290,11 +293,12 @@ show_spi_transport_##field(struct class_device *cdev, char *buf) \
+
+ #define spi_transport_store_function(field, format_string) \
+ static ssize_t \
+-store_spi_transport_##field(struct class_device *cdev, const char *buf, \
+- size_t count) \
++store_spi_transport_##field(struct device *dev, \
++ struct device_attribute *attr, \
++ const char *buf, size_t count) \
+ { \
+ int val; \
+- struct scsi_target *starget = transport_class_to_starget(cdev); \
++ struct scsi_target *starget = transport_class_to_starget(dev); \
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \
+ struct spi_internal *i = to_spi_internal(shost->transportt); \
+ \
+@@ -307,11 +311,12 @@ store_spi_transport_##field(struct class_device *cdev, const char *buf, \
+
+ #define spi_transport_store_max(field, format_string) \
+ static ssize_t \
+-store_spi_transport_##field(struct class_device *cdev, const char *buf, \
+- size_t count) \
++store_spi_transport_##field(struct device *dev, \
++ struct device_attribute *attr, \
++ const char *buf, size_t count) \
+ { \
+ int val; \
+- struct scsi_target *starget = transport_class_to_starget(cdev); \
++ struct scsi_target *starget = transport_class_to_starget(dev); \
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \
+ struct spi_internal *i = to_spi_internal(shost->transportt); \
+ struct spi_transport_attrs *tp \
+@@ -329,24 +334,24 @@ store_spi_transport_##field(struct class_device *cdev, const char *buf, \
+ #define spi_transport_rd_attr(field, format_string) \
+ spi_transport_show_function(field, format_string) \
+ spi_transport_store_function(field, format_string) \
+-static CLASS_DEVICE_ATTR(field, S_IRUGO, \
+- show_spi_transport_##field, \
+- store_spi_transport_##field);
++static DEVICE_ATTR(field, S_IRUGO, \
++ show_spi_transport_##field, \
++ store_spi_transport_##field);
+
+ #define spi_transport_simple_attr(field, format_string) \
+ spi_transport_show_simple(field, format_string) \
+ spi_transport_store_simple(field, format_string) \
+-static CLASS_DEVICE_ATTR(field, S_IRUGO, \
+- show_spi_transport_##field, \
+- store_spi_transport_##field);
++static DEVICE_ATTR(field, S_IRUGO, \
++ show_spi_transport_##field, \
++ store_spi_transport_##field);
+
+ #define spi_transport_max_attr(field, format_string) \
+ spi_transport_show_function(field, format_string) \
+ spi_transport_store_max(field, format_string) \
+ spi_transport_simple_attr(max_##field, format_string) \
+-static CLASS_DEVICE_ATTR(field, S_IRUGO, \
+- show_spi_transport_##field, \
+- store_spi_transport_##field);
++static DEVICE_ATTR(field, S_IRUGO, \
++ show_spi_transport_##field, \
++ store_spi_transport_##field);
+
+ /* The Parallel SCSI Tranport Attributes: */
+ spi_transport_max_attr(offset, "%d\n");
+@@ -370,14 +375,15 @@ static int child_iter(struct device *dev, void *data)
+ }
+
+ static ssize_t
+-store_spi_revalidate(struct class_device *cdev, const char *buf, size_t count)
++store_spi_revalidate(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+- struct scsi_target *starget = transport_class_to_starget(cdev);
++ struct scsi_target *starget = transport_class_to_starget(dev);
+
+ device_for_each_child(&starget->dev, NULL, child_iter);
+ return count;
+ }
+-static CLASS_DEVICE_ATTR(revalidate, S_IWUSR, NULL, store_spi_revalidate);
++static DEVICE_ATTR(revalidate, S_IWUSR, NULL, store_spi_revalidate);
+
+ /* Translate the period into ns according to the current spec
+ * for SDTR/PPR messages */
+@@ -412,7 +418,7 @@ show_spi_transport_period_helper(char *buf, int period)
+ }
+
+ static ssize_t
+-store_spi_transport_period_helper(struct class_device *cdev, const char *buf,
++store_spi_transport_period_helper(struct device *dev, const char *buf,
+ size_t count, int *periodp)
+ {
+ int j, picosec, period = -1;
+@@ -449,9 +455,10 @@ store_spi_transport_period_helper(struct class_device *cdev, const char *buf,
+ }
+
+ static ssize_t
+-show_spi_transport_period(struct class_device *cdev, char *buf)
++show_spi_transport_period(struct device *dev,
++ struct device_attribute *attr, char *buf)
+ {
+- struct scsi_target *starget = transport_class_to_starget(cdev);
++ struct scsi_target *starget = transport_class_to_starget(dev);
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct spi_internal *i = to_spi_internal(shost->transportt);
+ struct spi_transport_attrs *tp =
+@@ -464,8 +471,8 @@ show_spi_transport_period(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-store_spi_transport_period(struct class_device *cdev, const char *buf,
+- size_t count)
++store_spi_transport_period(struct device *cdev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+ struct scsi_target *starget = transport_class_to_starget(cdev);
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+@@ -487,12 +494,13 @@ store_spi_transport_period(struct class_device *cdev, const char *buf,
+ return retval;
+ }
+
+-static CLASS_DEVICE_ATTR(period, S_IRUGO,
+- show_spi_transport_period,
+- store_spi_transport_period);
++static DEVICE_ATTR(period, S_IRUGO,
++ show_spi_transport_period,
++ store_spi_transport_period);
+
+ static ssize_t
+-show_spi_transport_min_period(struct class_device *cdev, char *buf)
++show_spi_transport_min_period(struct device *cdev,
++ struct device_attribute *attr, char *buf)
+ {
+ struct scsi_target *starget = transport_class_to_starget(cdev);
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+@@ -507,8 +515,9 @@ show_spi_transport_min_period(struct class_device *cdev, char *buf)
+ }
+
+ static ssize_t
+-store_spi_transport_min_period(struct class_device *cdev, const char *buf,
+- size_t count)
++store_spi_transport_min_period(struct device *cdev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+ struct scsi_target *starget = transport_class_to_starget(cdev);
+ struct spi_transport_attrs *tp =
+@@ -519,12 +528,14 @@ store_spi_transport_min_period(struct class_device *cdev, const char *buf,
+ }
+
+
+-static CLASS_DEVICE_ATTR(min_period, S_IRUGO,
+- show_spi_transport_min_period,
+- store_spi_transport_min_period);
++static DEVICE_ATTR(min_period, S_IRUGO,
++ show_spi_transport_min_period,
++ store_spi_transport_min_period);
+
+
+-static ssize_t show_spi_host_signalling(struct class_device *cdev, char *buf)
++static ssize_t show_spi_host_signalling(struct device *cdev,
++ struct device_attribute *attr,
++ char *buf)
+ {
+ struct Scsi_Host *shost = transport_class_to_shost(cdev);
+ struct spi_internal *i = to_spi_internal(shost->transportt);
+@@ -534,10 +545,11 @@ static ssize_t show_spi_host_signalling(struct class_device *cdev, char *buf)
+
+ return sprintf(buf, "%s\n", spi_signal_to_string(spi_signalling(shost)));
+ }
+-static ssize_t store_spi_host_signalling(struct class_device *cdev,
++static ssize_t store_spi_host_signalling(struct device *dev,
++ struct device_attribute *attr,
+ const char *buf, size_t count)
+ {
+- struct Scsi_Host *shost = transport_class_to_shost(cdev);
++ struct Scsi_Host *shost = transport_class_to_shost(dev);
+ struct spi_internal *i = to_spi_internal(shost->transportt);
+ enum spi_signal_type type = spi_signal_to_value(buf);
+
+@@ -549,9 +561,9 @@ static ssize_t store_spi_host_signalling(struct class_device *cdev,
+
+ return count;
+ }
+-static CLASS_DEVICE_ATTR(signalling, S_IRUGO,
+- show_spi_host_signalling,
+- store_spi_host_signalling);
++static DEVICE_ATTR(signalling, S_IRUGO,
++ show_spi_host_signalling,
++ store_spi_host_signalling);
+
+ #define DV_SET(x, y) \
+ if(i->f->set_##x) \
+@@ -1334,7 +1346,7 @@ static DECLARE_ANON_TRANSPORT_CLASS(spi_device_class,
+ spi_device_configure);
+
+ static struct attribute *host_attributes[] = {
+- &class_device_attr_signalling.attr,
++ &dev_attr_signalling.attr,
+ NULL
+ };
+
+@@ -1344,12 +1356,12 @@ static struct attribute_group host_attribute_group = {
+
+ static int spi_host_configure(struct transport_container *tc,
+ struct device *dev,
+- struct class_device *cdev)
++ struct device *cdev)
+ {
+ struct kobject *kobj = &cdev->kobj;
+ struct Scsi_Host *shost = transport_class_to_shost(cdev);
+ struct spi_internal *si = to_spi_internal(shost->transportt);
+- struct attribute *attr = &class_device_attr_signalling.attr;
++ struct attribute *attr = &dev_attr_signalling.attr;
+ int rc = 0;
+
+ if (si->f->set_signalling)
+@@ -1368,76 +1380,75 @@ static int spi_host_configure(struct transport_container *tc,
+ static int target_attribute_is_visible(struct kobject *kobj,
+ struct attribute *attr, int i)
+ {
+- struct class_device *cdev =
+- container_of(kobj, struct class_device, kobj);
++ struct device *cdev = container_of(kobj, struct device, kobj);
+ struct scsi_target *starget = transport_class_to_starget(cdev);
+ struct Scsi_Host *shost = transport_class_to_shost(cdev);
+ struct spi_internal *si = to_spi_internal(shost->transportt);
+
+- if (attr == &class_device_attr_period.attr &&
++ if (attr == &dev_attr_period.attr &&
+ spi_support_sync(starget))
+ return TARGET_ATTRIBUTE_HELPER(period);
+- else if (attr == &class_device_attr_min_period.attr &&
++ else if (attr == &dev_attr_min_period.attr &&
+ spi_support_sync(starget))
+ return TARGET_ATTRIBUTE_HELPER(period);
+- else if (attr == &class_device_attr_offset.attr &&
++ else if (attr == &dev_attr_offset.attr &&
+ spi_support_sync(starget))
+ return TARGET_ATTRIBUTE_HELPER(offset);
+- else if (attr == &class_device_attr_max_offset.attr &&
++ else if (attr == &dev_attr_max_offset.attr &&
+ spi_support_sync(starget))
+ return TARGET_ATTRIBUTE_HELPER(offset);
+- else if (attr == &class_device_attr_width.attr &&
++ else if (attr == &dev_attr_width.attr &&
+ spi_support_wide(starget))
+ return TARGET_ATTRIBUTE_HELPER(width);
+- else if (attr == &class_device_attr_max_width.attr &&
++ else if (attr == &dev_attr_max_width.attr &&
+ spi_support_wide(starget))
+ return TARGET_ATTRIBUTE_HELPER(width);
+- else if (attr == &class_device_attr_iu.attr &&
++ else if (attr == &dev_attr_iu.attr &&
+ spi_support_ius(starget))
+ return TARGET_ATTRIBUTE_HELPER(iu);
+- else if (attr == &class_device_attr_dt.attr &&
++ else if (attr == &dev_attr_dt.attr &&
+ spi_support_dt(starget))
+ return TARGET_ATTRIBUTE_HELPER(dt);
+- else if (attr == &class_device_attr_qas.attr &&
++ else if (attr == &dev_attr_qas.attr &&
+ spi_support_qas(starget))
+ return TARGET_ATTRIBUTE_HELPER(qas);
+- else if (attr == &class_device_attr_wr_flow.attr &&
++ else if (attr == &dev_attr_wr_flow.attr &&
+ spi_support_ius(starget))
+ return TARGET_ATTRIBUTE_HELPER(wr_flow);
+- else if (attr == &class_device_attr_rd_strm.attr &&
++ else if (attr == &dev_attr_rd_strm.attr &&
+ spi_support_ius(starget))
+ return TARGET_ATTRIBUTE_HELPER(rd_strm);
+- else if (attr == &class_device_attr_rti.attr &&
++ else if (attr == &dev_attr_rti.attr &&
+ spi_support_ius(starget))
+ return TARGET_ATTRIBUTE_HELPER(rti);
+- else if (attr == &class_device_attr_pcomp_en.attr &&
++ else if (attr == &dev_attr_pcomp_en.attr &&
+ spi_support_ius(starget))
+ return TARGET_ATTRIBUTE_HELPER(pcomp_en);
+- else if (attr == &class_device_attr_hold_mcs.attr &&
++ else if (attr == &dev_attr_hold_mcs.attr &&
+ spi_support_ius(starget))
+ return TARGET_ATTRIBUTE_HELPER(hold_mcs);
+- else if (attr == &class_device_attr_revalidate.attr)
++ else if (attr == &dev_attr_revalidate.attr)
+ return 1;
+
+ return 0;
+ }
+
+ static struct attribute *target_attributes[] = {
+- &class_device_attr_period.attr,
+- &class_device_attr_min_period.attr,
+- &class_device_attr_offset.attr,
+- &class_device_attr_max_offset.attr,
+- &class_device_attr_width.attr,
+- &class_device_attr_max_width.attr,
+- &class_device_attr_iu.attr,
+- &class_device_attr_dt.attr,
+- &class_device_attr_qas.attr,
+- &class_device_attr_wr_flow.attr,
+- &class_device_attr_rd_strm.attr,
+- &class_device_attr_rti.attr,
+- &class_device_attr_pcomp_en.attr,
+- &class_device_attr_hold_mcs.attr,
+- &class_device_attr_revalidate.attr,
++ &dev_attr_period.attr,
++ &dev_attr_min_period.attr,
++ &dev_attr_offset.attr,
++ &dev_attr_max_offset.attr,
++ &dev_attr_width.attr,
++ &dev_attr_max_width.attr,
++ &dev_attr_iu.attr,
++ &dev_attr_dt.attr,
++ &dev_attr_qas.attr,
++ &dev_attr_wr_flow.attr,
++ &dev_attr_rd_strm.attr,
++ &dev_attr_rti.attr,
++ &dev_attr_pcomp_en.attr,
++ &dev_attr_hold_mcs.attr,
++ &dev_attr_revalidate.attr,
+ NULL
+ };
+
+@@ -1448,7 +1459,7 @@ static struct attribute_group target_attribute_group = {
+
+ static int spi_target_configure(struct transport_container *tc,
+ struct device *dev,
+- struct class_device *cdev)
++ struct device *cdev)
+ {
+ struct kobject *kobj = &cdev->kobj;
+ int i;
+@@ -1462,7 +1473,7 @@ static int spi_target_configure(struct transport_container *tc,
+ * to ignore, sysfs also does a WARN_ON and dumps a trace,
+ * which is bad, so temporarily, skip attributes that are
+ * already visible (the revalidate one) */
+- if (j && attr != &class_device_attr_revalidate.attr)
++ if (j && attr != &dev_attr_revalidate.attr)
+ rc = sysfs_add_file_to_group(kobj, attr,
+ target_attribute_group.name);
+ /* and make the attribute writeable if we have a set
+diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c
+index 2445c98..8a7af95 100644
+--- a/drivers/scsi/scsi_transport_srp.c
++++ b/drivers/scsi/scsi_transport_srp.c
+@@ -44,20 +44,20 @@ struct srp_internal {
+ struct scsi_transport_template t;
+ struct srp_function_template *f;
+
+- struct class_device_attribute *host_attrs[SRP_HOST_ATTRS + 1];
++ struct device_attribute *host_attrs[SRP_HOST_ATTRS + 1];
+
+- struct class_device_attribute *rport_attrs[SRP_RPORT_ATTRS + 1];
+- struct class_device_attribute private_rport_attrs[SRP_RPORT_ATTRS];
++ struct device_attribute *rport_attrs[SRP_RPORT_ATTRS + 1];
++ struct device_attribute private_rport_attrs[SRP_RPORT_ATTRS];
+ struct transport_container rport_attr_cont;
+ };
+
+ #define to_srp_internal(tmpl) container_of(tmpl, struct srp_internal, t)
+
+ #define dev_to_rport(d) container_of(d, struct srp_rport, dev)
+-#define transport_class_to_srp_rport(cdev) dev_to_rport((cdev)->dev)
++#define transport_class_to_srp_rport(dev) dev_to_rport((dev)->parent)
+
+ static int srp_host_setup(struct transport_container *tc, struct device *dev,
+- struct class_device *cdev)
++ struct device *cdev)
+ {
+ struct Scsi_Host *shost = dev_to_shost(dev);
+ struct srp_host_attrs *srp_host = to_srp_host_attrs(shost);
+@@ -73,7 +73,7 @@ static DECLARE_TRANSPORT_CLASS(srp_rport_class, "srp_remote_ports",
+ NULL, NULL, NULL);
+
+ #define SETUP_TEMPLATE(attrb, field, perm, test, ro_test, ro_perm) \
+- i->private_##attrb[count] = class_device_attr_##field; \
++ i->private_##attrb[count] = dev_attr_##field; \
+ i->private_##attrb[count].attr.mode = perm; \
+ if (ro_test) { \
+ i->private_##attrb[count].attr.mode = ro_perm; \
+@@ -100,13 +100,14 @@ static DECLARE_TRANSPORT_CLASS(srp_rport_class, "srp_remote_ports",
+ "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
+
+ static ssize_t
+-show_srp_rport_id(struct class_device *cdev, char *buf)
++show_srp_rport_id(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct srp_rport *rport = transport_class_to_srp_rport(cdev);
++ struct srp_rport *rport = transport_class_to_srp_rport(dev);
+ return sprintf(buf, SRP_PID_FMT "\n", SRP_PID(rport));
+ }
+
+-static CLASS_DEVICE_ATTR(port_id, S_IRUGO, show_srp_rport_id, NULL);
++static DEVICE_ATTR(port_id, S_IRUGO, show_srp_rport_id, NULL);
+
+ static const struct {
+ u32 value;
+@@ -117,9 +118,10 @@ static const struct {
+ };
+
+ static ssize_t
+-show_srp_rport_roles(struct class_device *cdev, char *buf)
++show_srp_rport_roles(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct srp_rport *rport = transport_class_to_srp_rport(cdev);
++ struct srp_rport *rport = transport_class_to_srp_rport(dev);
+ int i;
+ char *name = NULL;
+
+@@ -131,7 +133,7 @@ show_srp_rport_roles(struct class_device *cdev, char *buf)
+ return sprintf(buf, "%s\n", name ? : "unknown");
+ }
+
+-static CLASS_DEVICE_ATTR(roles, S_IRUGO, show_srp_rport_roles, NULL);
++static DEVICE_ATTR(roles, S_IRUGO, show_srp_rport_roles, NULL);
+
+ static void srp_rport_release(struct device *dev)
+ {
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index 5fe7aae..3cea17d 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -95,7 +95,7 @@ static int sd_resume(struct device *);
+ static void sd_rescan(struct device *);
+ static int sd_done(struct scsi_cmnd *);
+ static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer);
+-static void scsi_disk_release(struct class_device *cdev);
++static void scsi_disk_release(struct device *cdev);
+ static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *);
+ static void sd_print_result(struct scsi_disk *, int);
+
+@@ -112,11 +112,12 @@ static const char *sd_cache_types[] = {
+ "write back, no read (daft)"
+ };
+
+-static ssize_t sd_store_cache_type(struct class_device *cdev, const char *buf,
+- size_t count)
++static ssize_t
++sd_store_cache_type(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+ int i, ct = -1, rcd, wce, sp;
+- struct scsi_disk *sdkp = to_scsi_disk(cdev);
++ struct scsi_disk *sdkp = to_scsi_disk(dev);
+ struct scsi_device *sdp = sdkp->device;
+ char buffer[64];
+ char *buffer_data;
+@@ -163,10 +164,11 @@ static ssize_t sd_store_cache_type(struct class_device *cdev, const char *buf,
+ return count;
+ }
+
+-static ssize_t sd_store_manage_start_stop(struct class_device *cdev,
+- const char *buf, size_t count)
++static ssize_t
++sd_store_manage_start_stop(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+- struct scsi_disk *sdkp = to_scsi_disk(cdev);
++ struct scsi_disk *sdkp = to_scsi_disk(dev);
+ struct scsi_device *sdp = sdkp->device;
+
+ if (!capable(CAP_SYS_ADMIN))
+@@ -177,10 +179,11 @@ static ssize_t sd_store_manage_start_stop(struct class_device *cdev,
+ return count;
+ }
+
+-static ssize_t sd_store_allow_restart(struct class_device *cdev, const char *buf,
+- size_t count)
++static ssize_t
++sd_store_allow_restart(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
+ {
+- struct scsi_disk *sdkp = to_scsi_disk(cdev);
++ struct scsi_disk *sdkp = to_scsi_disk(dev);
+ struct scsi_device *sdp = sdkp->device;
+
+ if (!capable(CAP_SYS_ADMIN))
+@@ -194,37 +197,44 @@ static ssize_t sd_store_allow_restart(struct class_device *cdev, const char *buf
+ return count;
+ }
+
+-static ssize_t sd_show_cache_type(struct class_device *cdev, char *buf)
++static ssize_t
++sd_show_cache_type(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct scsi_disk *sdkp = to_scsi_disk(cdev);
++ struct scsi_disk *sdkp = to_scsi_disk(dev);
+ int ct = sdkp->RCD + 2*sdkp->WCE;
+
+ return snprintf(buf, 40, "%s\n", sd_cache_types[ct]);
+ }
+
+-static ssize_t sd_show_fua(struct class_device *cdev, char *buf)
++static ssize_t
++sd_show_fua(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+- struct scsi_disk *sdkp = to_scsi_disk(cdev);
++ struct scsi_disk *sdkp = to_scsi_disk(dev);
+
+ return snprintf(buf, 20, "%u\n", sdkp->DPOFUA);
+ }
+
+-static ssize_t sd_show_manage_start_stop(struct class_device *cdev, char *buf)
++static ssize_t
++sd_show_manage_start_stop(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct scsi_disk *sdkp = to_scsi_disk(cdev);
++ struct scsi_disk *sdkp = to_scsi_disk(dev);
+ struct scsi_device *sdp = sdkp->device;
+
+ return snprintf(buf, 20, "%u\n", sdp->manage_start_stop);
+ }
+
+-static ssize_t sd_show_allow_restart(struct class_device *cdev, char *buf)
++static ssize_t
++sd_show_allow_restart(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct scsi_disk *sdkp = to_scsi_disk(cdev);
++ struct scsi_disk *sdkp = to_scsi_disk(dev);
+
+ return snprintf(buf, 40, "%d\n", sdkp->device->allow_restart);
+ }
+
+-static struct class_device_attribute sd_disk_attrs[] = {
++static struct device_attribute sd_disk_attrs[] = {
+ __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type,
+ sd_store_cache_type),
+ __ATTR(FUA, S_IRUGO, sd_show_fua, NULL),
+@@ -238,8 +248,8 @@ static struct class_device_attribute sd_disk_attrs[] = {
+ static struct class sd_disk_class = {
+ .name = "scsi_disk",
+ .owner = THIS_MODULE,
+- .release = scsi_disk_release,
+- .class_dev_attrs = sd_disk_attrs,
++ .dev_release = scsi_disk_release,
++ .dev_attrs = sd_disk_attrs,
+ };
+
+ static struct scsi_driver sd_template = {
+@@ -297,7 +307,7 @@ static struct scsi_disk *__scsi_disk_get(struct gendisk *disk)
+ if (disk->private_data) {
+ sdkp = scsi_disk(disk);
+ if (scsi_device_get(sdkp->device) == 0)
+- class_device_get(&sdkp->cdev);
++ get_device(&sdkp->dev);
+ else
+ sdkp = NULL;
+ }
+@@ -331,7 +341,7 @@ static void scsi_disk_put(struct scsi_disk *sdkp)
+ struct scsi_device *sdev = sdkp->device;
+
+ mutex_lock(&sd_ref_mutex);
+- class_device_put(&sdkp->cdev);
++ put_device(&sdkp->dev);
+ scsi_device_put(sdev);
+ mutex_unlock(&sd_ref_mutex);
+ }
+@@ -1663,12 +1673,12 @@ static int sd_probe(struct device *dev)
+ sdp->timeout = SD_MOD_TIMEOUT;
+ }
+
+- class_device_initialize(&sdkp->cdev);
+- sdkp->cdev.dev = &sdp->sdev_gendev;
+- sdkp->cdev.class = &sd_disk_class;
+- strncpy(sdkp->cdev.class_id, sdp->sdev_gendev.bus_id, BUS_ID_SIZE);
++ device_initialize(&sdkp->dev);
++ sdkp->dev.parent = &sdp->sdev_gendev;
++ sdkp->dev.class = &sd_disk_class;
++ strncpy(sdkp->dev.bus_id, sdp->sdev_gendev.bus_id, BUS_ID_SIZE);
+
+- if (class_device_add(&sdkp->cdev))
++ if (device_add(&sdkp->dev))
+ goto out_put;
+
+ get_device(&sdp->sdev_gendev);
+@@ -1734,13 +1744,13 @@ static int sd_remove(struct device *dev)
+ {
+ struct scsi_disk *sdkp = dev_get_drvdata(dev);
+
+- class_device_del(&sdkp->cdev);
++ device_del(&sdkp->dev);
+ del_gendisk(sdkp->disk);
+ sd_shutdown(dev);
+
+ mutex_lock(&sd_ref_mutex);
+ dev_set_drvdata(dev, NULL);
+- class_device_put(&sdkp->cdev);
++ put_device(&sdkp->dev);
+ mutex_unlock(&sd_ref_mutex);
+
+ return 0;
+@@ -1748,16 +1758,16 @@ static int sd_remove(struct device *dev)
+
+ /**
+ * scsi_disk_release - Called to free the scsi_disk structure
+- * @cdev: pointer to embedded class device
++ * @dev: pointer to embedded class device
+ *
+ * sd_ref_mutex must be held entering this routine. Because it is
+ * called on last put, you should always use the scsi_disk_get()
+ * scsi_disk_put() helpers which manipulate the semaphore directly
+- * and never do a direct class_device_put().
++ * and never do a direct put_device.
+ **/
+-static void scsi_disk_release(struct class_device *cdev)
++static void scsi_disk_release(struct device *dev)
+ {
+- struct scsi_disk *sdkp = to_scsi_disk(cdev);
++ struct scsi_disk *sdkp = to_scsi_disk(dev);
+ struct gendisk *disk = sdkp->disk;
+
+ spin_lock(&sd_index_lock);
+diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c
+index a6d9669..45df83b 100644
+--- a/drivers/scsi/ses.c
++++ b/drivers/scsi/ses.c
+@@ -107,7 +107,7 @@ static int ses_set_page2_descriptor(struct enclosure_device *edev,
+ unsigned char *desc)
+ {
+ int i, j, count = 0, descriptor = ecomp->number;
+- struct scsi_device *sdev = to_scsi_device(edev->cdev.dev);
++ struct scsi_device *sdev = to_scsi_device(edev->edev.parent);
+ struct ses_device *ses_dev = edev->scratch;
+ unsigned char *type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11];
+ unsigned char *desc_ptr = ses_dev->page2 + 8;
+@@ -137,7 +137,7 @@ static unsigned char *ses_get_page2_descriptor(struct enclosure_device *edev,
+ struct enclosure_component *ecomp)
+ {
+ int i, j, count = 0, descriptor = ecomp->number;
+- struct scsi_device *sdev = to_scsi_device(edev->cdev.dev);
++ struct scsi_device *sdev = to_scsi_device(edev->edev.parent);
+ struct ses_device *ses_dev = edev->scratch;
+ unsigned char *type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11];
+ unsigned char *desc_ptr = ses_dev->page2 + 8;
+@@ -269,10 +269,10 @@ int ses_match_host(struct enclosure_device *edev, void *data)
+ struct ses_host_edev *sed = data;
+ struct scsi_device *sdev;
+
+- if (!scsi_is_sdev_device(edev->cdev.dev))
++ if (!scsi_is_sdev_device(edev->edev.parent))
+ return 0;
+
+- sdev = to_scsi_device(edev->cdev.dev);
++ sdev = to_scsi_device(edev->edev.parent);
+
+ if (sdev->host != sed->shost)
+ return 0;
+@@ -407,10 +407,10 @@ static void ses_match_to_enclosure(struct enclosure_device *edev,
+
+ #define INIT_ALLOC_SIZE 32
+
+-static int ses_intf_add(struct class_device *cdev,
++static int ses_intf_add(struct device *cdev,
+ struct class_interface *intf)
+ {
+- struct scsi_device *sdev = to_scsi_device(cdev->dev);
++ struct scsi_device *sdev = to_scsi_device(cdev->parent);
+ struct scsi_device *tmp_sdev;
+ unsigned char *buf = NULL, *hdr_buf, *type_ptr, *desc_ptr = NULL,
+ *addl_desc_ptr = NULL;
+@@ -426,7 +426,7 @@ static int ses_intf_add(struct class_device *cdev,
+ edev = enclosure_find(&sdev->host->shost_gendev);
+ if (edev) {
+ ses_match_to_enclosure(edev, sdev);
+- class_device_put(&edev->cdev);
++ put_device(&edev->edev);
+ }
+ return -ENODEV;
+ }
+@@ -515,7 +515,7 @@ static int ses_intf_add(struct class_device *cdev,
+ if (!scomp)
+ goto err_free;
+
+- edev = enclosure_register(cdev->dev, sdev->sdev_gendev.bus_id,
++ edev = enclosure_register(cdev->parent, sdev->sdev_gendev.bus_id,
+ components, &ses_enclosure_callbacks);
+ if (IS_ERR(edev)) {
+ err = PTR_ERR(edev);
+@@ -625,17 +625,17 @@ static int ses_remove(struct device *dev)
+ return 0;
+ }
+
+-static void ses_intf_remove(struct class_device *cdev,
++static void ses_intf_remove(struct device *cdev,
+ struct class_interface *intf)
+ {
+- struct scsi_device *sdev = to_scsi_device(cdev->dev);
++ struct scsi_device *sdev = to_scsi_device(cdev->parent);
+ struct enclosure_device *edev;
+ struct ses_device *ses_dev;
+
+ if (!scsi_device_enclosure(sdev))
+ return;
+
+- edev = enclosure_find(cdev->dev);
++ edev = enclosure_find(cdev->parent);
+ if (!edev)
+ return;
+
+@@ -649,13 +649,13 @@ static void ses_intf_remove(struct class_device *cdev,
+
+ kfree(edev->component[0].scratch);
+
+- class_device_put(&edev->cdev);
++ put_device(&edev->edev);
+ enclosure_unregister(edev);
+ }
+
+ static struct class_interface ses_interface = {
+- .add = ses_intf_add,
+- .remove = ses_intf_remove,
++ .add_dev = ses_intf_add,
++ .remove_dev = ses_intf_remove,
+ };
+
+ static struct scsi_driver ses_template = {
+diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
+index e5156aa..2029422 100644
+--- a/drivers/scsi/sg.c
++++ b/drivers/scsi/sg.c
+@@ -101,16 +101,16 @@ static int scatter_elem_sz_prev = SG_SCATTER_SZ;
+ #define SG_SECTOR_SZ 512
+ #define SG_SECTOR_MSK (SG_SECTOR_SZ - 1)
+
+-static int sg_add(struct class_device *, struct class_interface *);
+-static void sg_remove(struct class_device *, struct class_interface *);
++static int sg_add(struct device *, struct class_interface *);
++static void sg_remove(struct device *, struct class_interface *);
+
+ static DEFINE_IDR(sg_index_idr);
+ static DEFINE_RWLOCK(sg_index_lock); /* Also used to lock
+ file descriptor list for device */
+
+ static struct class_interface sg_interface = {
+- .add = sg_add,
+- .remove = sg_remove,
++ .add_dev = sg_add,
++ .remove_dev = sg_remove,
+ };
+
+ typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info */
+@@ -1401,9 +1401,9 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
+ }
+
+ static int
+-sg_add(struct class_device *cl_dev, struct class_interface *cl_intf)
++sg_add(struct device *cl_dev, struct class_interface *cl_intf)
+ {
+- struct scsi_device *scsidp = to_scsi_device(cl_dev->dev);
++ struct scsi_device *scsidp = to_scsi_device(cl_dev->parent);
+ struct gendisk *disk;
+ Sg_device *sdp = NULL;
+ struct cdev * cdev = NULL;
+@@ -1439,19 +1439,19 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf)
+
+ sdp->cdev = cdev;
+ if (sg_sysfs_valid) {
+- struct class_device * sg_class_member;
++ struct device *sg_class_member;
+
+- sg_class_member = class_device_create(sg_sysfs_class, NULL,
+- MKDEV(SCSI_GENERIC_MAJOR, sdp->index),
+- cl_dev->dev, "%s",
+- disk->disk_name);
++ sg_class_member = device_create(sg_sysfs_class, cl_dev->parent,
++ MKDEV(SCSI_GENERIC_MAJOR,
++ sdp->index),
++ "%s", disk->disk_name);
+ if (IS_ERR(sg_class_member)) {
+ printk(KERN_ERR "sg_add: "
+- "class_device_create failed\n");
++ "device_create failed\n");
+ error = PTR_ERR(sg_class_member);
+ goto cdev_add_err;
+ }
+- class_set_devdata(sg_class_member, sdp);
++ dev_set_drvdata(sg_class_member, sdp);
+ error = sysfs_create_link(&scsidp->sdev_gendev.kobj,
+ &sg_class_member->kobj, "generic");
+ if (error)
+@@ -1464,7 +1464,7 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf)
+ "Attached scsi generic sg%d type %d\n", sdp->index,
+ scsidp->type);
+
+- class_set_devdata(cl_dev, sdp);
++ dev_set_drvdata(cl_dev, sdp);
+
+ return 0;
+
+@@ -1482,10 +1482,10 @@ out:
+ }
+
+ static void
+-sg_remove(struct class_device *cl_dev, struct class_interface *cl_intf)
++sg_remove(struct device *cl_dev, struct class_interface *cl_intf)
+ {
+- struct scsi_device *scsidp = to_scsi_device(cl_dev->dev);
+- Sg_device *sdp = class_get_devdata(cl_dev);
++ struct scsi_device *scsidp = to_scsi_device(cl_dev->parent);
++ Sg_device *sdp = dev_get_drvdata(cl_dev);
+ unsigned long iflags;
+ Sg_fd *sfp;
+ Sg_fd *tsfp;
+@@ -1528,7 +1528,7 @@ sg_remove(struct class_device *cl_dev, struct class_interface *cl_intf)
+ write_unlock_irqrestore(&sg_index_lock, iflags);
+
+ sysfs_remove_link(&scsidp->sdev_gendev.kobj, "generic");
+- class_device_destroy(sg_sysfs_class, MKDEV(SCSI_GENERIC_MAJOR, sdp->index));
++ device_destroy(sg_sysfs_class, MKDEV(SCSI_GENERIC_MAJOR, sdp->index));
+ cdev_del(sdp->cdev);
+ sdp->cdev = NULL;
+ put_disk(sdp->disk);
+diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c
+index 26cfc56..03e3596 100644
+--- a/drivers/scsi/sgiwd93.c
++++ b/drivers/scsi/sgiwd93.c
+@@ -263,10 +263,11 @@ static int __init sgiwd93_probe(struct platform_device *pdev)
+ regs.SASR = wdregs + 3;
+ regs.SCMD = wdregs + 7;
+
+- wd33c93_init(host, regs, dma_setup, dma_stop, WD33C93_FS_MHZ(20));
++ hdata->wh.no_sync = 0;
++ hdata->wh.fast = 1;
++ hdata->wh.dma_mode = CTRL_BURST;
+
+- if (hdata->wh.no_sync == 0xff)
+- hdata->wh.no_sync = 0;
++ wd33c93_init(host, regs, dma_setup, dma_stop, WD33C93_FS_MHZ(20));
+
+ err = request_irq(irq, sgiwd93_intr, 0, "SGI WD93", host);
+ if (err) {
+diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
+index 0a52d9d..a860c3a 100644
+--- a/drivers/scsi/st.c
++++ b/drivers/scsi/st.c
+@@ -17,7 +17,7 @@
+ Last modified: 18-JAN-1998 Richard Gooch <rgooch at atnf.csiro.au> Devfs support
+ */
+
+-static const char *verstr = "20080221";
++static const char *verstr = "20080224";
+
+ #include <linux/module.h>
+
+@@ -183,6 +183,7 @@ static int modes_defined;
+
+ static struct st_buffer *new_tape_buffer(int, int, int);
+ static int enlarge_buffer(struct st_buffer *, int, int);
++static void clear_buffer(struct st_buffer *);
+ static void normalize_buffer(struct st_buffer *);
+ static int append_to_buffer(const char __user *, struct st_buffer *, int);
+ static int from_buffer(struct st_buffer *, char __user *, int);
+@@ -442,6 +443,7 @@ static void st_sleep_done(void *data, char *sense, int result, int resid)
+
+ memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE);
+ (STp->buffer)->cmdstat.midlevel_result = SRpnt->result = result;
++ (STp->buffer)->cmdstat.residual = resid;
+ DEB( STp->write_pending = 0; )
+
+ if (SRpnt->waiting)
+@@ -626,7 +628,7 @@ static int cross_eof(struct scsi_tape * STp, int forward)
+
+
+ /* Flush the write buffer (never need to write if variable blocksize). */
+-static int flush_write_buffer(struct scsi_tape * STp)
++static int st_flush_write_buffer(struct scsi_tape * STp)
+ {
+ int offset, transfer, blks;
+ int result;
+@@ -717,7 +719,7 @@ static int flush_buffer(struct scsi_tape *STp, int seek_next)
+ return 0;
+ STps = &(STp->ps[STp->partition]);
+ if (STps->rw == ST_WRITING) /* Writing */
+- return flush_write_buffer(STp);
++ return st_flush_write_buffer(STp);
+
+ if (STp->block_size == 0)
+ return 0;
+@@ -1159,6 +1161,7 @@ static int st_open(struct inode *inode, struct file *filp)
+ goto err_out;
+ }
+
++ (STp->buffer)->cleared = 0;
+ (STp->buffer)->writing = 0;
+ (STp->buffer)->syscall_result = 0;
+
+@@ -1211,7 +1214,7 @@ static int st_flush(struct file *filp, fl_owner_t id)
+ return 0;
+
+ if (STps->rw == ST_WRITING && !STp->pos_unknown) {
+- result = flush_write_buffer(STp);
++ result = st_flush_write_buffer(STp);
+ if (result != 0 && result != (-ENOSPC))
+ goto out;
+ }
+@@ -1432,8 +1435,14 @@ static int setup_buffering(struct scsi_tape *STp, const char __user *buf,
+ if (STp->block_size)
+ bufsize = STp->block_size > st_fixed_buffer_size ?
+ STp->block_size : st_fixed_buffer_size;
+- else
++ else {
+ bufsize = count;
++ /* Make sure that data from previous user is not leaked even if
++ HBA does not return correct residual */
++ if (is_read && STp->sili && !STbp->cleared)
++ clear_buffer(STbp);
++ }
++
+ if (bufsize > STbp->buffer_size &&
+ !enlarge_buffer(STbp, bufsize, STp->restr_dma)) {
+ printk(KERN_WARNING "%s: Can't allocate %d byte tape buffer.\n",
+@@ -1783,6 +1792,8 @@ static long read_tape(struct scsi_tape *STp, long count,
+ memset(cmd, 0, MAX_COMMAND_SIZE);
+ cmd[0] = READ_6;
+ cmd[1] = (STp->block_size != 0);
++ if (!cmd[1] && STp->sili)
++ cmd[1] |= 2;
+ cmd[2] = blks >> 16;
+ cmd[3] = blks >> 8;
+ cmd[4] = blks;
+@@ -1911,8 +1922,11 @@ static long read_tape(struct scsi_tape *STp, long count,
+
+ }
+ /* End of error handling */
+- else /* Read successful */
++ else { /* Read successful */
+ STbp->buffer_bytes = bytes;
++ if (STp->sili) /* In fixed block mode residual is always zero here */
++ STbp->buffer_bytes -= STp->buffer->cmdstat.residual;
++ }
+
+ if (STps->drv_block >= 0) {
+ if (STp->block_size == 0)
+@@ -2090,7 +2104,8 @@ static void st_log_options(struct scsi_tape * STp, struct st_modedef * STm, char
+ name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
+ STp->scsi2_logical);
+ printk(KERN_INFO
+- "%s: sysv: %d nowait: %d\n", name, STm->sysv, STp->immediate);
++ "%s: sysv: %d nowait: %d sili: %d\n", name, STm->sysv, STp->immediate,
++ STp->sili);
+ printk(KERN_INFO "%s: debugging: %d\n",
+ name, debugging);
+ }
+@@ -2133,6 +2148,7 @@ static int st_set_options(struct scsi_tape *STp, long options)
+ STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
+ STp->immediate = (options & MT_ST_NOWAIT) != 0;
+ STm->sysv = (options & MT_ST_SYSV) != 0;
++ STp->sili = (options & MT_ST_SILI) != 0;
+ DEB( debugging = (options & MT_ST_DEBUGGING) != 0;
+ st_log_options(STp, STm, name); )
+ } else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
+@@ -2164,6 +2180,8 @@ static int st_set_options(struct scsi_tape *STp, long options)
+ STp->immediate = value;
+ if ((options & MT_ST_SYSV) != 0)
+ STm->sysv = value;
++ if ((options & MT_ST_SILI) != 0)
++ STp->sili = value;
+ DEB(
+ if ((options & MT_ST_DEBUGGING) != 0)
+ debugging = value;
+@@ -3655,6 +3673,8 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm
+ STbuffer->frp_segs += 1;
+ got += b_size;
+ STbuffer->buffer_size = got;
++ if (STbuffer->cleared)
++ memset(page_address(STbuffer->frp[segs].page), 0, b_size);
+ segs++;
+ }
+ STbuffer->b_data = page_address(STbuffer->frp[0].page);
+@@ -3663,6 +3683,17 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm
+ }
+
+
++/* Make sure that no data from previous user is in the internal buffer */
++static void clear_buffer(struct st_buffer * st_bp)
++{
++ int i;
++
++ for (i=0; i < st_bp->frp_segs; i++)
++ memset(page_address(st_bp->frp[i].page), 0, st_bp->frp[i].length);
++ st_bp->cleared = 1;
++}
++
++
+ /* Release the extra buffer */
+ static void normalize_buffer(struct st_buffer * STbuffer)
+ {
+@@ -3987,6 +4018,7 @@ static int st_probe(struct device *dev)
+ tpnt->two_fm = ST_TWO_FM;
+ tpnt->fast_mteom = ST_FAST_MTEOM;
+ tpnt->scsi2_logical = ST_SCSI2LOGICAL;
++ tpnt->sili = ST_SILI;
+ tpnt->immediate = ST_NOWAIT;
+ tpnt->default_drvbuffer = 0xff; /* No forced buffering */
+ tpnt->partition = 0;
+@@ -4076,9 +4108,9 @@ out_free_tape:
+ if (STm->cdevs[j]) {
+ if (cdev == STm->cdevs[j])
+ cdev = NULL;
+- class_device_destroy(st_sysfs_class,
+- MKDEV(SCSI_TAPE_MAJOR,
+- TAPE_MINOR(i, mode, j)));
++ device_destroy(st_sysfs_class,
++ MKDEV(SCSI_TAPE_MAJOR,
++ TAPE_MINOR(i, mode, j)));
+ cdev_del(STm->cdevs[j]);
+ }
+ }
+@@ -4116,9 +4148,9 @@ static int st_remove(struct device *dev)
+ "tape");
+ for (mode = 0; mode < ST_NBR_MODES; ++mode) {
+ for (j=0; j < 2; j++) {
+- class_device_destroy(st_sysfs_class,
+- MKDEV(SCSI_TAPE_MAJOR,
+- TAPE_MINOR(i, mode, j)));
++ device_destroy(st_sysfs_class,
++ MKDEV(SCSI_TAPE_MAJOR,
++ TAPE_MINOR(i, mode, j)));
+ cdev_del(tpnt->modes[mode].cdevs[j]);
+ tpnt->modes[mode].cdevs[j] = NULL;
+ }
+@@ -4287,31 +4319,34 @@ static void do_remove_sysfs_files(void)
+
+
+ /* The sysfs simple class interface */
+-static ssize_t st_defined_show(struct class_device *class_dev, char *buf)
++static ssize_t
++st_defined_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+- struct st_modedef *STm = (struct st_modedef *)class_get_devdata(class_dev);
++ struct st_modedef *STm = (struct st_modedef *)dev_get_drvdata(dev);
+ ssize_t l = 0;
+
+ l = snprintf(buf, PAGE_SIZE, "%d\n", STm->defined);
+ return l;
+ }
+
+-CLASS_DEVICE_ATTR(defined, S_IRUGO, st_defined_show, NULL);
++DEVICE_ATTR(defined, S_IRUGO, st_defined_show, NULL);
+
+-static ssize_t st_defblk_show(struct class_device *class_dev, char *buf)
++static ssize_t
++st_defblk_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+- struct st_modedef *STm = (struct st_modedef *)class_get_devdata(class_dev);
++ struct st_modedef *STm = (struct st_modedef *)dev_get_drvdata(dev);
+ ssize_t l = 0;
+
+ l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_blksize);
+ return l;
+ }
+
+-CLASS_DEVICE_ATTR(default_blksize, S_IRUGO, st_defblk_show, NULL);
++DEVICE_ATTR(default_blksize, S_IRUGO, st_defblk_show, NULL);
+
+-static ssize_t st_defdensity_show(struct class_device *class_dev, char *buf)
++static ssize_t
++st_defdensity_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+- struct st_modedef *STm = (struct st_modedef *)class_get_devdata(class_dev);
++ struct st_modedef *STm = (struct st_modedef *)dev_get_drvdata(dev);
+ ssize_t l = 0;
+ char *fmt;
+
+@@ -4320,24 +4355,67 @@ static ssize_t st_defdensity_show(struct class_device *class_dev, char *buf)
+ return l;
+ }
+
+-CLASS_DEVICE_ATTR(default_density, S_IRUGO, st_defdensity_show, NULL);
++DEVICE_ATTR(default_density, S_IRUGO, st_defdensity_show, NULL);
+
+-static ssize_t st_defcompression_show(struct class_device *class_dev, char *buf)
++static ssize_t
++st_defcompression_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
+ {
+- struct st_modedef *STm = (struct st_modedef *)class_get_devdata(class_dev);
++ struct st_modedef *STm = (struct st_modedef *)dev_get_drvdata(dev);
+ ssize_t l = 0;
+
+ l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_compression - 1);
+ return l;
+ }
+
+-CLASS_DEVICE_ATTR(default_compression, S_IRUGO, st_defcompression_show, NULL);
++DEVICE_ATTR(default_compression, S_IRUGO, st_defcompression_show, NULL);
++
++static ssize_t
++st_options_show(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct st_modedef *STm = (struct st_modedef *)dev_get_drvdata(dev);
++ struct scsi_tape *STp;
++ int i, j, options;
++ ssize_t l = 0;
++
++ for (i=0; i < st_dev_max; i++) {
++ for (j=0; j < ST_NBR_MODES; j++)
++ if (&scsi_tapes[i]->modes[j] == STm)
++ break;
++ if (j < ST_NBR_MODES)
++ break;
++ }
++ if (i == st_dev_max)
++ return 0; /* should never happen */
++
++ STp = scsi_tapes[i];
++
++ options = STm->do_buffer_writes ? MT_ST_BUFFER_WRITES : 0;
++ options |= STm->do_async_writes ? MT_ST_ASYNC_WRITES : 0;
++ options |= STm->do_read_ahead ? MT_ST_READ_AHEAD : 0;
++ DEB( options |= debugging ? MT_ST_DEBUGGING : 0 );
++ options |= STp->two_fm ? MT_ST_TWO_FM : 0;
++ options |= STp->fast_mteom ? MT_ST_FAST_MTEOM : 0;
++ options |= STm->defaults_for_writes ? MT_ST_DEF_WRITES : 0;
++ options |= STp->can_bsr ? MT_ST_CAN_BSR : 0;
++ options |= STp->omit_blklims ? MT_ST_NO_BLKLIMS : 0;
++ options |= STp->can_partitions ? MT_ST_CAN_PARTITIONS : 0;
++ options |= STp->scsi2_logical ? MT_ST_SCSI2LOGICAL : 0;
++ options |= STm->sysv ? MT_ST_SYSV : 0;
++ options |= STp->immediate ? MT_ST_NOWAIT : 0;
++ options |= STp->sili ? MT_ST_SILI : 0;
++
++ l = snprintf(buf, PAGE_SIZE, "0x%08x\n", options);
++ return l;
++}
++
++DEVICE_ATTR(options, S_IRUGO, st_options_show, NULL);
+
+ static int do_create_class_files(struct scsi_tape *STp, int dev_num, int mode)
+ {
+ int i, rew, error;
+ char name[10];
+- struct class_device *st_class_member;
++ struct device *st_class_member;
+
+ for (rew=0; rew < 2; rew++) {
+ /* Make sure that the minor numbers corresponding to the four
+@@ -4346,29 +4424,32 @@ static int do_create_class_files(struct scsi_tape *STp, int dev_num, int mode)
+ snprintf(name, 10, "%s%s%s", rew ? "n" : "",
+ STp->disk->disk_name, st_formats[i]);
+ st_class_member =
+- class_device_create(st_sysfs_class, NULL,
+- MKDEV(SCSI_TAPE_MAJOR,
+- TAPE_MINOR(dev_num, mode, rew)),
+- &STp->device->sdev_gendev, "%s", name);
++ device_create(st_sysfs_class, &STp->device->sdev_gendev,
++ MKDEV(SCSI_TAPE_MAJOR,
++ TAPE_MINOR(dev_num, mode, rew)),
++ "%s", name);
+ if (IS_ERR(st_class_member)) {
+- printk(KERN_WARNING "st%d: class_device_create failed\n",
++ printk(KERN_WARNING "st%d: device_create failed\n",
+ dev_num);
+ error = PTR_ERR(st_class_member);
+ goto out;
+ }
+- class_set_devdata(st_class_member, &STp->modes[mode]);
++ dev_set_drvdata(st_class_member, &STp->modes[mode]);
+
+- error = class_device_create_file(st_class_member,
+- &class_device_attr_defined);
++ error = device_create_file(st_class_member,
++ &dev_attr_defined);
++ if (error) goto out;
++ error = device_create_file(st_class_member,
++ &dev_attr_default_blksize);
+ if (error) goto out;
+- error = class_device_create_file(st_class_member,
+- &class_device_attr_default_blksize);
++ error = device_create_file(st_class_member,
++ &dev_attr_default_density);
+ if (error) goto out;
+- error = class_device_create_file(st_class_member,
+- &class_device_attr_default_density);
++ error = device_create_file(st_class_member,
++ &dev_attr_default_compression);
+ if (error) goto out;
+- error = class_device_create_file(st_class_member,
+- &class_device_attr_default_compression);
++ error = device_create_file(st_class_member,
++ &dev_attr_options);
+ if (error) goto out;
+
+ if (mode == 0 && rew == 0) {
+diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h
+index 5931726..b92712f 100644
+--- a/drivers/scsi/st.h
++++ b/drivers/scsi/st.h
+@@ -12,6 +12,7 @@ struct st_cmdstatus {
+ int midlevel_result;
+ struct scsi_sense_hdr sense_hdr;
+ int have_sense;
++ int residual;
+ u64 uremainder64;
+ u8 flags;
+ u8 remainder_valid;
+@@ -34,6 +35,7 @@ struct st_request {
+ struct st_buffer {
+ unsigned char dma; /* DMA-able buffer */
+ unsigned char do_dio; /* direct i/o set up? */
++ unsigned char cleared; /* internal buffer cleared after open? */
+ int buffer_size;
+ int buffer_blocks;
+ int buffer_bytes;
+@@ -122,6 +124,7 @@ struct scsi_tape {
+ unsigned char try_dio_now; /* try direct i/o before next close? */
+ unsigned char c_algo; /* compression algorithm */
+ unsigned char pos_unknown; /* after reset position unknown */
++ unsigned char sili; /* use SILI when reading in variable b mode */
+ int tape_type;
+ int long_timeout; /* timeout for commands known to take long time */
+
+diff --git a/drivers/scsi/st_options.h b/drivers/scsi/st_options.h
+index b6b5c9c..d2f9479 100644
+--- a/drivers/scsi/st_options.h
++++ b/drivers/scsi/st_options.h
+@@ -3,7 +3,7 @@
+
+ Copyright 1995-2003 Kai Makisara.
+
+- Last modified: Mon Apr 7 22:49:18 2003 by makisara
++ Last modified: Thu Feb 21 21:47:07 2008 by kai.makisara
+ */
+
+ #ifndef _ST_OPTIONS_H
+@@ -94,6 +94,10 @@
+ The default is BSD semantics. */
+ #define ST_SYSV 0
+
++/* If ST_SILI is non-zero, the SILI bit is set when reading in variable block
++ mode and the block size is determined using the residual returned by the HBA. */
++#define ST_SILI 0
++
+ /* Time to wait for the drive to become ready if blocking open */
+ #define ST_BLOCK_SECONDS 120
+
+diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
+index 654430e..f308a03 100644
+--- a/drivers/scsi/stex.c
++++ b/drivers/scsi/stex.c
+@@ -33,6 +33,7 @@
+ #include <scsi/scsi_host.h>
+ #include <scsi/scsi_tcq.h>
+ #include <scsi/scsi_dbg.h>
++#include <scsi/scsi_eh.h>
+
+ #define DRV_NAME "stex"
+ #define ST_DRIVER_VERSION "3.6.0000.1"
+@@ -362,22 +363,14 @@ static struct status_msg *stex_get_status(struct st_hba *hba)
+ return status;
+ }
+
+-static void stex_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
+-{
+- cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+-
+- cmd->sense_buffer[0] = 0x70; /* fixed format, current */
+- cmd->sense_buffer[2] = sk;
+- cmd->sense_buffer[7] = 18 - 8; /* additional sense length */
+- cmd->sense_buffer[12] = asc;
+- cmd->sense_buffer[13] = ascq;
+-}
+-
+ static void stex_invalid_field(struct scsi_cmnd *cmd,
+ void (*done)(struct scsi_cmnd *))
+ {
++ cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
++
+ /* "Invalid field in cbd" */
+- stex_set_sense(cmd, ILLEGAL_REQUEST, 0x24, 0x0);
++ scsi_build_sense_buffer(0, cmd->sense_buffer, ILLEGAL_REQUEST, 0x24,
++ 0x0);
+ done(cmd);
+ }
+
+@@ -426,49 +419,13 @@ static int stex_map_sg(struct st_hba *hba,
+ return 0;
+ }
+
+-static void stex_internal_copy(struct scsi_cmnd *cmd,
+- const void *src, size_t *count, int sg_count, int direction)
+-{
+- size_t lcount;
+- size_t len;
+- void *s, *d, *base = NULL;
+- size_t offset;
+-
+- if (*count > scsi_bufflen(cmd))
+- *count = scsi_bufflen(cmd);
+- lcount = *count;
+- while (lcount) {
+- len = lcount;
+- s = (void *)src;
+-
+- offset = *count - lcount;
+- s += offset;
+- base = scsi_kmap_atomic_sg(scsi_sglist(cmd),
+- sg_count, &offset, &len);
+- if (!base) {
+- *count -= lcount;
+- return;
+- }
+- d = base + offset;
+-
+- if (direction == ST_TO_CMD)
+- memcpy(d, s, len);
+- else
+- memcpy(s, d, len);
+-
+- lcount -= len;
+- scsi_kunmap_atomic_sg(base);
+- }
+-}
+-
+ static void stex_controller_info(struct st_hba *hba, struct st_ccb *ccb)
+ {
+ struct st_frame *p;
+ size_t count = sizeof(struct st_frame);
+
+ p = hba->copy_buffer;
+- stex_internal_copy(ccb->cmd, p, &count, scsi_sg_count(ccb->cmd),
+- ST_FROM_CMD);
++ count = scsi_sg_copy_to_buffer(ccb->cmd, p, count);
+ memset(p->base, 0, sizeof(u32)*6);
+ *(unsigned long *)(p->base) = pci_resource_start(hba->pdev, 0);
+ p->rom_addr = 0;
+@@ -486,8 +443,7 @@ static void stex_controller_info(struct st_hba *hba, struct st_ccb *ccb)
+ p->subid =
+ hba->pdev->subsystem_vendor << 16 | hba->pdev->subsystem_device;
+
+- stex_internal_copy(ccb->cmd, p, &count, scsi_sg_count(ccb->cmd),
+- ST_TO_CMD);
++ count = scsi_sg_copy_from_buffer(ccb->cmd, p, count);
+ }
+
+ static void
+@@ -554,10 +510,8 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
+ unsigned char page;
+ page = cmd->cmnd[2] & 0x3f;
+ if (page == 0x8 || page == 0x3f) {
+- size_t cp_len = sizeof(ms10_caching_page);
+- stex_internal_copy(cmd, ms10_caching_page,
+- &cp_len, scsi_sg_count(cmd),
+- ST_TO_CMD);
++ scsi_sg_copy_from_buffer(cmd, ms10_caching_page,
++ sizeof(ms10_caching_page));
+ cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
+ done(cmd);
+ } else
+@@ -586,10 +540,8 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
+ if (id != host->max_id - 1)
+ break;
+ if (lun == 0 && (cmd->cmnd[1] & INQUIRY_EVPD) == 0) {
+- size_t cp_len = sizeof(console_inq_page);
+- stex_internal_copy(cmd, console_inq_page,
+- &cp_len, scsi_sg_count(cmd),
+- ST_TO_CMD);
++ scsi_sg_copy_from_buffer(cmd, (void *)console_inq_page,
++ sizeof(console_inq_page));
+ cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
+ done(cmd);
+ } else
+@@ -606,8 +558,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
+ ver.signature[0] = PASSTHRU_SIGNATURE;
+ ver.console_id = host->max_id - 1;
+ ver.host_no = hba->host->host_no;
+- stex_internal_copy(cmd, &ver, &cp_len,
+- scsi_sg_count(cmd), ST_TO_CMD);
++ cp_len = scsi_sg_copy_from_buffer(cmd, &ver, cp_len);
+ cmd->result = sizeof(ver) == cp_len ?
+ DID_OK << 16 | COMMAND_COMPLETE << 8 :
+ DID_ERROR << 16 | COMMAND_COMPLETE << 8;
+@@ -700,15 +651,12 @@ static void stex_copy_data(struct st_ccb *ccb,
+
+ if (ccb->cmd == NULL)
+ return;
+- stex_internal_copy(ccb->cmd,
+- resp->variable, &count, scsi_sg_count(ccb->cmd), ST_TO_CMD);
++ count = scsi_sg_copy_from_buffer(ccb->cmd, resp->variable, count);
+ }
+
+ static void stex_ys_commands(struct st_hba *hba,
+ struct st_ccb *ccb, struct status_msg *resp)
+ {
+- size_t count;
+-
+ if (ccb->cmd->cmnd[0] == MGT_CMD &&
+ resp->scsi_status != SAM_STAT_CHECK_CONDITION) {
+ scsi_set_resid(ccb->cmd, scsi_bufflen(ccb->cmd) -
+@@ -724,9 +672,8 @@ static void stex_ys_commands(struct st_hba *hba,
+ resp->scsi_status == SAM_STAT_GOOD) {
+ ST_INQ *inq_data;
+
+- count = STEX_EXTRA_SIZE;
+- stex_internal_copy(ccb->cmd, hba->copy_buffer,
+- &count, scsi_sg_count(ccb->cmd), ST_FROM_CMD);
++ scsi_sg_copy_to_buffer(ccb->cmd, hba->copy_buffer,
++ STEX_EXTRA_SIZE);
+ inq_data = (ST_INQ *)hba->copy_buffer;
+ if (inq_data->DeviceTypeQualifier != 0)
+ ccb->srb_status = SRB_STATUS_SELECTION_TIMEOUT;
+diff --git a/drivers/scsi/sun3_scsi_vme.c b/drivers/scsi/sun3_scsi_vme.c
+index 02d9727..aaa4fd0 100644
+--- a/drivers/scsi/sun3_scsi_vme.c
++++ b/drivers/scsi/sun3_scsi_vme.c
+@@ -582,3 +582,4 @@ static struct scsi_host_template driver_template = {
+
+ #include "scsi_module.c"
+
++MODULE_LICENSE("GPL");
+diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
+index f286c37..5fda881 100644
+--- a/drivers/scsi/wd33c93.c
++++ b/drivers/scsi/wd33c93.c
+@@ -1973,10 +1973,7 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
+ hostdata->incoming_ptr = 0;
+ hostdata->outgoing_len = 0;
+ hostdata->default_sx_per = DEFAULT_SX_PER;
+- hostdata->no_sync = 0xff; /* sync defaults to off */
+ hostdata->no_dma = 0; /* default is DMA enabled */
+- hostdata->fast = 0; /* default is Fast SCSI transfers disabled */
+- hostdata->dma_mode = CTRL_DMA; /* default is Single Byte DMA */
+
+ #ifdef PROC_INTERFACE
+ hostdata->proc = PR_VERSION | PR_INFO | PR_STATISTICS |
+diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
+index 77f7a7f..96a585e 100644
+--- a/drivers/serial/8250.c
++++ b/drivers/serial/8250.c
+@@ -1740,6 +1740,60 @@ static inline void wait_for_xmitr(struct uart_8250_port *up, int bits)
+ }
+ }
+
++#ifdef CONFIG_CONSOLE_POLL
++/*
++ * Console polling routines for writing and reading from the uart while
++ * in an interrupt or debug context.
++ */
++
++static int serial8250_get_poll_char(struct uart_port *port)
++{
++ struct uart_8250_port *up = (struct uart_8250_port *)port;
++ unsigned char lsr = serial_inp(up, UART_LSR);
++
++ while (!(lsr & UART_LSR_DR))
++ lsr = serial_inp(up, UART_LSR);
++
++ return serial_inp(up, UART_RX);
++}
++
++
++static void serial8250_put_poll_char(struct uart_port *port,
++ unsigned char c)
++{
++ unsigned int ier;
++ struct uart_8250_port *up = (struct uart_8250_port *)port;
++
++ /*
++ * First save the IER then disable the interrupts
++ */
++ ier = serial_in(up, UART_IER);
++ if (up->capabilities & UART_CAP_UUE)
++ serial_out(up, UART_IER, UART_IER_UUE);
++ else
++ serial_out(up, UART_IER, 0);
++
++ wait_for_xmitr(up, BOTH_EMPTY);
++ /*
++ * Send the character out.
++ * If a LF, also do CR...
++ */
++ serial_out(up, UART_TX, c);
++ if (c == 10) {
++ wait_for_xmitr(up, BOTH_EMPTY);
++ serial_out(up, UART_TX, 13);
++ }
++
++ /*
++ * Finally, wait for transmitter to become empty
++ * and restore the IER
++ */
++ wait_for_xmitr(up, BOTH_EMPTY);
++ serial_out(up, UART_IER, ier);
++}
++
++#endif /* CONFIG_CONSOLE_POLL */
++
+ static int serial8250_startup(struct uart_port *port)
+ {
+ struct uart_8250_port *up = (struct uart_8250_port *)port;
+@@ -2386,6 +2440,10 @@ static struct uart_ops serial8250_pops = {
+ .request_port = serial8250_request_port,
+ .config_port = serial8250_config_port,
+ .verify_port = serial8250_verify_port,
++#ifdef CONFIG_CONSOLE_POLL
++ .poll_get_char = serial8250_get_poll_char,
++ .poll_put_char = serial8250_put_poll_char,
++#endif
+ };
+
+ static struct uart_8250_port serial8250_ports[UART_NR];
+diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
+index cf627cd..f7cd950 100644
+--- a/drivers/serial/Kconfig
++++ b/drivers/serial/Kconfig
+@@ -961,6 +961,9 @@ config SERIAL_CORE
+ config SERIAL_CORE_CONSOLE
+ bool
+
++config CONSOLE_POLL
++ bool
++
+ config SERIAL_68328
+ bool "68328 serial support"
+ depends on M68328 || M68EZ328 || M68VZ328
+diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
+index 640cfe4..3cbea54 100644
+--- a/drivers/serial/Makefile
++++ b/drivers/serial/Makefile
+@@ -66,4 +66,5 @@ obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o
+ obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
+ obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
+ obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
++obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
+ obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
+diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
+index 40604a0..08adc1d 100644
+--- a/drivers/serial/amba-pl011.c
++++ b/drivers/serial/amba-pl011.c
+@@ -314,6 +314,32 @@ static void pl011_break_ctl(struct uart_port *port, int break_state)
+ spin_unlock_irqrestore(&uap->port.lock, flags);
+ }
+
++#ifdef CONFIG_CONSOLE_POLL
++static int pl010_get_poll_char(struct uart_port *port)
++{
++ struct uart_amba_port *uap = (struct uart_amba_port *)port;
++ unsigned int status;
++
++ do {
++ status = readw(uap->port.membase + UART01x_FR);
++ } while (status & UART01x_FR_RXFE);
++
++ return readw(uap->port.membase + UART01x_DR);
++}
++
++static void pl010_put_poll_char(struct uart_port *port,
++ unsigned char ch)
++{
++ struct uart_amba_port *uap = (struct uart_amba_port *)port;
++
++ while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
++ barrier();
++
++ writew(ch, uap->port.membase + UART01x_DR);
++}
++
++#endif /* CONFIG_CONSOLE_POLL */
++
+ static int pl011_startup(struct uart_port *port)
+ {
+ struct uart_amba_port *uap = (struct uart_amba_port *)port;
+@@ -572,6 +598,10 @@ static struct uart_ops amba_pl011_pops = {
+ .request_port = pl010_request_port,
+ .config_port = pl010_config_port,
+ .verify_port = pl010_verify_port,
++#ifdef CONFIG_CONSOLE_POLL
++ .poll_get_char = pl010_get_poll_char,
++ .poll_put_char = pl010_put_poll_char,
++#endif
+ };
+
+ static struct uart_amba_port *amba_ports[UART_NR];
+diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
+index 46bb47f..5f55534 100644
+--- a/drivers/serial/bfin_5xx.c
++++ b/drivers/serial/bfin_5xx.c
+@@ -151,7 +151,8 @@ void kgdb_put_debug_char(int chr)
+ {
+ struct bfin_serial_port *uart;
+
+- if (CONFIG_KGDB_UART_PORT<0 || CONFIG_KGDB_UART_PORT>=NR_PORTS)
++ if (CONFIG_KGDB_UART_PORT < 0
++ || CONFIG_KGDB_UART_PORT >= BFIN_UART_NR_PORTS)
+ uart = &bfin_serial_ports[0];
+ else
+ uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
+@@ -173,7 +174,8 @@ int kgdb_get_debug_char(void)
+ struct bfin_serial_port *uart;
+ unsigned char chr;
+
+- if (CONFIG_KGDB_UART_PORT<0 || CONFIG_KGDB_UART_PORT>=NR_PORTS)
++ if (CONFIG_KGDB_UART_PORT < 0
++ || CONFIG_KGDB_UART_PORT >= BFIN_UART_NR_PORTS)
+ uart = &bfin_serial_ports[0];
+ else
+ uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
+@@ -192,7 +194,7 @@ int kgdb_get_debug_char(void)
+ }
+ #endif
+
+-#if ANOMALY_05000230 && defined(CONFIG_SERIAL_BFIN_PIO)
++#if ANOMALY_05000363 && defined(CONFIG_SERIAL_BFIN_PIO)
+ # define UART_GET_ANOMALY_THRESHOLD(uart) ((uart)->anomaly_threshold)
+ # define UART_SET_ANOMALY_THRESHOLD(uart, v) ((uart)->anomaly_threshold = (v))
+ #else
+@@ -237,7 +239,7 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
+ }
+ #endif
+
+- if (ANOMALY_05000230) {
++ if (ANOMALY_05000363) {
+ /* The BF533 (and BF561) family of processors have a nice anomaly
+ * where they continuously generate characters for a "single" break.
+ * We have to basically ignore this flood until the "next" valid
+@@ -249,9 +251,6 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
+ * timeout was picked as it must absolutely be larger than 1
+ * character time +/- some percent. So 1.5 sounds good. All other
+ * Blackfin families operate properly. Woo.
+- * Note: While Anomaly 05000230 does not directly address this,
+- * the changes that went in for it also fixed this issue.
+- * That anomaly was fixed in 0.5+ silicon. I like bunnies.
+ */
+ if (anomaly_start.tv_sec) {
+ struct timeval curr;
+@@ -285,7 +284,7 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
+ }
+
+ if (status & BI) {
+- if (ANOMALY_05000230)
++ if (ANOMALY_05000363)
+ if (bfin_revid() < 5)
+ do_gettimeofday(&anomaly_start);
+ uart->port.icount.brk++;
+@@ -507,8 +506,7 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
+ uart->rx_dma_buf.tail = uart->rx_dma_buf.head;
+ }
+
+- uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES;
+- add_timer(&(uart->rx_dma_timer));
++ mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES);
+ }
+
+ static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id)
+@@ -551,9 +549,7 @@ static irqreturn_t bfin_serial_dma_rx_int(int irq, void *dev_id)
+ clear_dma_irqstat(uart->rx_dma_channel);
+ spin_unlock(&uart->port.lock);
+
+- del_timer(&(uart->rx_dma_timer));
+- uart->rx_dma_timer.expires = jiffies;
+- add_timer(&(uart->rx_dma_timer));
++ mod_timer(&(uart->rx_dma_timer), jiffies);
+
+ return IRQ_HANDLED;
+ }
+@@ -749,7 +745,7 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+ unsigned long flags;
+ unsigned int baud, quot;
+- unsigned short val, ier, lsr, lcr = 0;
++ unsigned short val, ier, lcr = 0;
+
+ switch (termios->c_cflag & CSIZE) {
+ case CS8:
+@@ -806,10 +802,6 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
+
+ UART_SET_ANOMALY_THRESHOLD(uart, USEC_PER_SEC / baud * 15);
+
+- do {
+- lsr = UART_GET_LSR(uart);
+- } while (!(lsr & TEMT));
+-
+ /* Disable UART */
+ ier = UART_GET_IER(uart);
+ #ifdef CONFIG_BF54x
+@@ -900,6 +892,31 @@ bfin_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
+ return 0;
+ }
+
++/*
++ * Enable the IrDA function if tty->ldisc.num is N_IRDA.
++ * In other cases, disable IrDA function.
++ */
++static void bfin_set_ldisc(struct tty_struct *tty)
++{
++ int line = tty->index;
++ unsigned short val;
++
++ if (line >= tty->driver->num)
++ return;
++
++ switch (tty->ldisc.num) {
++ case N_IRDA:
++ val = UART_GET_GCTL(&bfin_serial_ports[line]);
++ val |= (IREN | RPOLC);
++ UART_PUT_GCTL(&bfin_serial_ports[line], val);
++ break;
++ default:
++ val = UART_GET_GCTL(&bfin_serial_ports[line]);
++ val &= ~(IREN | RPOLC);
++ UART_PUT_GCTL(&bfin_serial_ports[line], val);
++ }
++}
++
+ static struct uart_ops bfin_serial_pops = {
+ .tx_empty = bfin_serial_tx_empty,
+ .set_mctrl = bfin_serial_set_mctrl,
+@@ -1172,7 +1189,7 @@ static struct uart_driver bfin_serial_reg = {
+ .dev_name = BFIN_SERIAL_NAME,
+ .major = BFIN_SERIAL_MAJOR,
+ .minor = BFIN_SERIAL_MINOR,
+- .nr = NR_PORTS,
++ .nr = BFIN_UART_NR_PORTS,
+ .cons = BFIN_SERIAL_CONSOLE,
+ };
+
+@@ -1261,6 +1278,7 @@ static int __init bfin_serial_init(void)
+
+ ret = uart_register_driver(&bfin_serial_reg);
+ if (ret == 0) {
++ bfin_serial_reg.tty_driver->set_ldisc = bfin_set_ldisc;
+ ret = platform_driver_register(&bfin_serial_driver);
+ if (ret) {
+ pr_debug("uart register failed\n");
+diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h
+index 32b9737..0cc39f8 100644
+--- a/drivers/serial/cpm_uart/cpm_uart.h
++++ b/drivers/serial/cpm_uart/cpm_uart.h
+@@ -92,6 +92,9 @@ extern struct uart_cpm_port cpm_uart_ports[UART_NR];
+
+ /* these are located in their respective files */
+ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd);
++void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port,
++ struct device_node *np);
++void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram);
+ int cpm_uart_init_portdesc(void);
+ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con);
+ void cpm_uart_freebuf(struct uart_cpm_port *pinfo);
+diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
+index 236af9d..a638ba0 100644
+--- a/drivers/serial/cpm_uart/cpm_uart_core.c
++++ b/drivers/serial/cpm_uart/cpm_uart_core.c
+@@ -966,24 +966,23 @@ static int cpm_uart_init_port(struct device_node *np,
+ if (!mem)
+ return -ENOMEM;
+
+- pram = of_iomap(np, 1);
+- if (!pram) {
+- ret = -ENOMEM;
+- goto out_mem;
+- }
+-
+ if (of_device_is_compatible(np, "fsl,cpm1-scc-uart") ||
+ of_device_is_compatible(np, "fsl,cpm2-scc-uart")) {
+ pinfo->sccp = mem;
+- pinfo->sccup = pram;
++ pinfo->sccup = pram = cpm_uart_map_pram(pinfo, np);
+ } else if (of_device_is_compatible(np, "fsl,cpm1-smc-uart") ||
+ of_device_is_compatible(np, "fsl,cpm2-smc-uart")) {
+ pinfo->flags |= FLAG_SMC;
+ pinfo->smcp = mem;
+- pinfo->smcup = pram;
++ pinfo->smcup = pram = cpm_uart_map_pram(pinfo, np);
+ } else {
+ ret = -ENODEV;
+- goto out_pram;
++ goto out_mem;
++ }
++
++ if (!pram) {
++ ret = -ENOMEM;
++ goto out_mem;
+ }
+
+ pinfo->tx_nrfifos = TX_NUM_FIFO;
+@@ -1007,7 +1006,7 @@ static int cpm_uart_init_port(struct device_node *np,
+ return cpm_uart_request_port(&pinfo->port);
+
+ out_pram:
+- iounmap(pram);
++ cpm_uart_unmap_pram(pinfo, pram);
+ out_mem:
+ iounmap(mem);
+ return ret;
+diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
+index 6ea0366..74f1432 100644
+--- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c
++++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
+@@ -45,6 +45,8 @@
+ #include <linux/serial_core.h>
+ #include <linux/kernel.h>
+
++#include <linux/of.h>
++
+ #include "cpm_uart.h"
+
+ /**************************************************************/
+@@ -54,6 +56,18 @@ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
+ {
+ cpm_command(port->command, cmd);
+ }
++
++void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port,
++ struct device_node *np)
++{
++ return of_iomap(np, 1);
++}
++
++void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram)
++{
++ iounmap(pram);
++}
++
+ #else
+ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
+ {
+diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+index d9af06a..bb862e2 100644
+--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
++++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+@@ -41,6 +41,9 @@
+ #include <asm/io.h>
+ #include <asm/irq.h>
+ #include <asm/fs_pd.h>
++#ifdef CONFIG_PPC_CPM_NEW_BINDING
++#include <asm/prom.h>
++#endif
+
+ #include <linux/serial_core.h>
+ #include <linux/kernel.h>
+@@ -54,6 +57,55 @@ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
+ {
+ cpm_command(port->command, cmd);
+ }
++
++void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port,
++ struct device_node *np)
++{
++ void __iomem *pram;
++ unsigned long offset;
++ struct resource res;
++ unsigned long len;
++
++ /* Don't remap parameter RAM if it has already been initialized
++ * during console setup.
++ */
++ if (IS_SMC(port) && port->smcup)
++ return port->smcup;
++ else if (!IS_SMC(port) && port->sccup)
++ return port->sccup;
++
++ if (of_address_to_resource(np, 1, &res))
++ return NULL;
++
++ len = 1 + res.end - res.start;
++ pram = ioremap(res.start, len);
++ if (!pram)
++ return NULL;
++
++ if (!IS_SMC(port))
++ return pram;
++
++ if (len != 2) {
++ printk(KERN_WARNING "cpm_uart[%d]: device tree references "
++ "SMC pram, using boot loader/wrapper pram mapping. "
++ "Please fix your device tree to reference the pram "
++ "base register instead.\n",
++ port->port.line);
++ return pram;
++ }
++
++ offset = cpm_dpalloc(PROFF_SMC_SIZE, 64);
++ out_be16(pram, offset);
++ iounmap(pram);
++ return cpm_muram_addr(offset);
++}
++
++void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram)
++{
++ if (!IS_SMC(port))
++ iounmap(pram);
++}
++
+ #else
+ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
+ {
+diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
+index 16ba9ac..5a375bf 100644
+--- a/drivers/serial/imx.c
++++ b/drivers/serial/imx.c
+@@ -166,15 +166,6 @@
+ #define SERIAL_IMX_MAJOR 204
+ #define MINOR_START 41
+
+-#define NR_PORTS 2
+-
+-#define IMX_ISR_PASS_LIMIT 256
+-
+-/*
+- * This is the size of our serial port register set.
+- */
+-#define UART_PORT_SIZE 0x100
+-
+ /*
+ * This determines how often we check the modem status signals
+ * for any change. They generally aren't connected to an IRQ
+@@ -358,66 +349,60 @@ static irqreturn_t imx_rxint(int irq, void *dev_id)
+ struct tty_struct *tty = sport->port.info->tty;
+ unsigned long flags, temp;
+
+- rx = readl(sport->port.membase + URXD0);
+ spin_lock_irqsave(&sport->port.lock,flags);
+
+- do {
++ while (readl(sport->port.membase + USR2) & USR2_RDR) {
+ flg = TTY_NORMAL;
+ sport->port.icount.rx++;
+
++ rx = readl(sport->port.membase + URXD0);
++
+ temp = readl(sport->port.membase + USR2);
+- if( temp & USR2_BRCD ) {
++ if (temp & USR2_BRCD) {
+ writel(temp | USR2_BRCD, sport->port.membase + USR2);
+- if(uart_handle_break(&sport->port))
+- goto ignore_char;
++ if (uart_handle_break(&sport->port))
++ continue;
+ }
+
+ if (uart_handle_sysrq_char
+ (&sport->port, (unsigned char)rx))
+- goto ignore_char;
++ continue;
++
++ if (rx & (URXD_PRERR | URXD_OVRRUN | URXD_FRMERR) ) {
++ if (rx & URXD_PRERR)
++ sport->port.icount.parity++;
++ else if (rx & URXD_FRMERR)
++ sport->port.icount.frame++;
++ if (rx & URXD_OVRRUN)
++ sport->port.icount.overrun++;
++
++ if (rx & sport->port.ignore_status_mask) {
++ if (++ignored > 100)
++ goto out;
++ continue;
++ }
++
++ rx &= sport->port.read_status_mask;
++
++ if (rx & URXD_PRERR)
++ flg = TTY_PARITY;
++ else if (rx & URXD_FRMERR)
++ flg = TTY_FRAME;
++ if (rx & URXD_OVRRUN)
++ flg = TTY_OVERRUN;
+
+- if( rx & (URXD_PRERR | URXD_OVRRUN | URXD_FRMERR) )
+- goto handle_error;
++#ifdef SUPPORT_SYSRQ
++ sport->port.sysrq = 0;
++#endif
++ }
+
+- error_return:
+ tty_insert_flip_char(tty, rx, flg);
+-
+- ignore_char:
+- rx = readl(sport->port.membase + URXD0);
+- } while(rx & URXD_CHARRDY);
++ }
+
+ out:
+ spin_unlock_irqrestore(&sport->port.lock,flags);
+ tty_flip_buffer_push(tty);
+ return IRQ_HANDLED;
+-
+-handle_error:
+- if (rx & URXD_PRERR)
+- sport->port.icount.parity++;
+- else if (rx & URXD_FRMERR)
+- sport->port.icount.frame++;
+- if (rx & URXD_OVRRUN)
+- sport->port.icount.overrun++;
+-
+- if (rx & sport->port.ignore_status_mask) {
+- if (++ignored > 100)
+- goto out;
+- goto ignore_char;
+- }
+-
+- rx &= sport->port.read_status_mask;
+-
+- if (rx & URXD_PRERR)
+- flg = TTY_PARITY;
+- else if (rx & URXD_FRMERR)
+- flg = TTY_FRAME;
+- if (rx & URXD_OVRRUN)
+- flg = TTY_OVERRUN;
+-
+-#ifdef SUPPORT_SYSRQ
+- sport->port.sysrq = 0;
+-#endif
+- goto error_return;
+ }
+
+ /*
+@@ -546,7 +531,7 @@ static int imx_startup(struct uart_port *port)
+ writel(USR1_RTSD, sport->port.membase + USR1);
+
+ temp = readl(sport->port.membase + UCR1);
+- temp |= (UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
++ temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN;
+ writel(temp, sport->port.membase + UCR1);
+
+ temp = readl(sport->port.membase + UCR2);
+@@ -731,9 +716,11 @@ static const char *imx_type(struct uart_port *port)
+ */
+ static void imx_release_port(struct uart_port *port)
+ {
+- struct imx_port *sport = (struct imx_port *)port;
++ struct platform_device *pdev = to_platform_device(port->dev);
++ struct resource *mmres;
+
+- release_mem_region(sport->port.mapbase, UART_PORT_SIZE);
++ mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ release_mem_region(mmres->start, mmres->end - mmres->start + 1);
+ }
+
+ /*
+@@ -741,10 +728,18 @@ static void imx_release_port(struct uart_port *port)
+ */
+ static int imx_request_port(struct uart_port *port)
+ {
+- struct imx_port *sport = (struct imx_port *)port;
++ struct platform_device *pdev = to_platform_device(port->dev);
++ struct resource *mmres;
++ void *ret;
++
++ mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!mmres)
++ return -ENODEV;
++
++ ret = request_mem_region(mmres->start, mmres->end - mmres->start + 1,
++ "imx-uart");
+
+- return request_mem_region(sport->port.mapbase, UART_PORT_SIZE,
+- "imx-uart") != NULL ? 0 : -EBUSY;
++ return ret ? 0 : -EBUSY;
+ }
+
+ /*
+@@ -815,7 +810,7 @@ static struct imx_port imx_ports[] = {
+ .type = PORT_IMX,
+ .iotype = UPIO_MEM,
+ .membase = (void *)IMX_UART1_BASE,
+- .mapbase = IMX_UART1_BASE, /* FIXME */
++ .mapbase = 0x00206000,
+ .irq = UART1_MINT_RX,
+ .uartclk = 16000000,
+ .fifosize = 32,
+@@ -831,7 +826,7 @@ static struct imx_port imx_ports[] = {
+ .type = PORT_IMX,
+ .iotype = UPIO_MEM,
+ .membase = (void *)IMX_UART2_BASE,
+- .mapbase = IMX_UART2_BASE, /* FIXME */
++ .mapbase = 0x00207000,
+ .irq = UART2_MINT_RX,
+ .uartclk = 16000000,
+ .fifosize = 32,
+diff --git a/drivers/serial/kgdboc.c b/drivers/serial/kgdboc.c
+new file mode 100644
+index 0000000..9cf0332
+--- /dev/null
++++ b/drivers/serial/kgdboc.c
+@@ -0,0 +1,168 @@
++/*
++ * Based on the same principle as kgdboe using the NETPOLL api, this
++ * driver uses a console polling api to implement a gdb serial inteface
++ * which is multiplexed on a console port.
++ *
++ * Maintainer: Jason Wessel <jason.wessel at windriver.com>
++ *
++ * 2007-2008 (c) Jason Wessel - Wind River Systems, Inc.
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++#include <linux/kernel.h>
++#include <linux/ctype.h>
++#include <linux/kgdb.h>
++#include <linux/tty.h>
++
++#define MAX_CONFIG_LEN 40
++
++static struct kgdb_io kgdboc_io_ops;
++
++/* -1 = init not run yet, 0 = unconfigured, 1 = configured. */
++static int configured = -1;
++
++static char config[MAX_CONFIG_LEN];
++static struct kparam_string kps = {
++ .string = config,
++ .maxlen = MAX_CONFIG_LEN,
++};
++
++static struct tty_driver *kgdb_tty_driver;
++static int kgdb_tty_line;
++
++static int kgdboc_option_setup(char *opt)
++{
++ if (strlen(opt) > MAX_CONFIG_LEN) {
++ printk(KERN_ERR "kgdboc: config string too long\n");
++ return -ENOSPC;
++ }
++ strcpy(config, opt);
++
++ return 0;
++}
++
++__setup("kgdboc=", kgdboc_option_setup);
++
++static int configure_kgdboc(void)
++{
++ struct tty_driver *p;
++ int tty_line = 0;
++ int err;
++
++ err = kgdboc_option_setup(config);
++ if (err || !strlen(config) || isspace(config[0]))
++ goto noconfig;
++
++ err = -ENODEV;
++
++ p = tty_find_polling_driver(config, &tty_line);
++ if (!p)
++ goto noconfig;
++
++ kgdb_tty_driver = p;
++ kgdb_tty_line = tty_line;
++
++ err = kgdb_register_io_module(&kgdboc_io_ops);
++ if (err)
++ goto noconfig;
++
++ configured = 1;
++
++ return 0;
++
++noconfig:
++ config[0] = 0;
++ configured = 0;
++
++ return err;
++}
++
++static int __init init_kgdboc(void)
++{
++ /* Already configured? */
++ if (configured == 1)
++ return 0;
++
++ return configure_kgdboc();
++}
++
++static void cleanup_kgdboc(void)
++{
++ if (configured == 1)
++ kgdb_unregister_io_module(&kgdboc_io_ops);
++}
++
++static int kgdboc_get_char(void)
++{
++ return kgdb_tty_driver->poll_get_char(kgdb_tty_driver, kgdb_tty_line);
++}
++
++static void kgdboc_put_char(u8 chr)
++{
++ kgdb_tty_driver->poll_put_char(kgdb_tty_driver, kgdb_tty_line, chr);
++}
++
++static int param_set_kgdboc_var(const char *kmessage, struct kernel_param *kp)
++{
++ int len = strlen(kmessage);
++
++ if (len >= MAX_CONFIG_LEN) {
++ printk(KERN_ERR "kgdboc: config string too long\n");
++ return -ENOSPC;
++ }
++
++ /* Only copy in the string if the init function has not run yet */
++ if (configured < 0) {
++ strcpy(config, kmessage);
++ return 0;
++ }
++
++ if (kgdb_connected) {
++ printk(KERN_ERR
++ "kgdboc: Cannot reconfigure while KGDB is connected.\n");
++
++ return -EBUSY;
++ }
++
++ strcpy(config, kmessage);
++ /* Chop out \n char as a result of echo */
++ if (config[len - 1] == '\n')
++ config[len - 1] = '\0';
++
++ if (configured == 1)
++ cleanup_kgdboc();
++
++ /* Go and configure with the new params. */
++ return configure_kgdboc();
++}
++
++static void kgdboc_pre_exp_handler(void)
++{
++ /* Increment the module count when the debugger is active */
++ if (!kgdb_connected)
++ try_module_get(THIS_MODULE);
++}
++
++static void kgdboc_post_exp_handler(void)
++{
++ /* decrement the module count when the debugger detaches */
++ if (!kgdb_connected)
++ module_put(THIS_MODULE);
++}
++
++static struct kgdb_io kgdboc_io_ops = {
++ .name = "kgdboc",
++ .read_char = kgdboc_get_char,
++ .write_char = kgdboc_put_char,
++ .pre_exception = kgdboc_pre_exp_handler,
++ .post_exception = kgdboc_post_exp_handler,
++};
++
++module_init(init_kgdboc);
++module_exit(cleanup_kgdboc);
++module_param_call(kgdboc, param_set_kgdboc_var, param_get_string, &kps, 0644);
++MODULE_PARM_DESC(kgdboc, "<serial_device>[,baud]");
++MODULE_DESCRIPTION("KGDB Console TTY Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
+index 99af084..ddd3aa5 100644
+--- a/drivers/serial/mcfserial.c
++++ b/drivers/serial/mcfserial.c
+@@ -40,7 +40,6 @@
+ #include <asm/io.h>
+ #include <asm/irq.h>
+ #include <asm/system.h>
+-#include <asm/semaphore.h>
+ #include <asm/delay.h>
+ #include <asm/coldfire.h>
+ #include <asm/mcfsim.h>
+diff --git a/drivers/serial/of_serial.c b/drivers/serial/of_serial.c
+index c0e50a4..25029c7 100644
+--- a/drivers/serial/of_serial.c
++++ b/drivers/serial/of_serial.c
+@@ -31,7 +31,8 @@ static int __devinit of_platform_serial_setup(struct of_device *ofdev,
+ struct resource resource;
+ struct device_node *np = ofdev->node;
+ const unsigned int *clk, *spd;
+- int ret;
++ const u32 *prop;
++ int ret, prop_size;
+
+ memset(port, 0, sizeof *port);
+ spd = of_get_property(np, "current-speed", NULL);
+@@ -49,6 +50,17 @@ static int __devinit of_platform_serial_setup(struct of_device *ofdev,
+
+ spin_lock_init(&port->lock);
+ port->mapbase = resource.start;
++
++ /* Check for shifted address mapping */
++ prop = of_get_property(np, "reg-offset", &prop_size);
++ if (prop && (prop_size == sizeof(u32)))
++ port->mapbase += *prop;
++
++ /* Check for registers offset within the devices address range */
++ prop = of_get_property(np, "reg-shift", &prop_size);
++ if (prop && (prop_size == sizeof(u32)))
++ port->regshift = *prop;
++
+ port->irq = irq_of_parse_and_map(np, 0);
+ port->iotype = UPIO_MEM;
+ port->type = type;
+@@ -56,7 +68,9 @@ static int __devinit of_platform_serial_setup(struct of_device *ofdev,
+ port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
+ | UPF_FIXED_PORT;
+ port->dev = &ofdev->dev;
+- port->custom_divisor = *clk / (16 * (*spd));
++ /* If current-speed was set, then try not to change it. */
++ if (spd)
++ port->custom_divisor = *clk / (16 * (*spd));
+
+ return 0;
+ }
+diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
+index 0f5a179..a9ca03e 100644
+--- a/drivers/serial/serial_core.c
++++ b/drivers/serial/serial_core.c
+@@ -1771,7 +1771,7 @@ static int uart_read_proc(char *page, char **start, off_t off,
+ }
+ #endif
+
+-#ifdef CONFIG_SERIAL_CORE_CONSOLE
++#if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL)
+ /*
+ * uart_console_write - write a console message to a serial port
+ * @port: the port to write the message
+@@ -1827,7 +1827,7 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co)
+ * options. The format of the string is <baud><parity><bits><flow>,
+ * eg: 115200n8r
+ */
+-void __init
++void
+ uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow)
+ {
+ char *s = options;
+@@ -1842,6 +1842,7 @@ uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow)
+ if (*s)
+ *flow = *s;
+ }
++EXPORT_SYMBOL_GPL(uart_parse_options);
+
+ struct baud_rates {
+ unsigned int rate;
+@@ -1872,7 +1873,7 @@ static const struct baud_rates baud_rates[] = {
+ * @bits: number of data bits
+ * @flow: flow control character - 'r' (rts)
+ */
+-int __init
++int
+ uart_set_options(struct uart_port *port, struct console *co,
+ int baud, int parity, int bits, int flow)
+ {
+@@ -1924,10 +1925,16 @@ uart_set_options(struct uart_port *port, struct console *co,
+ port->mctrl |= TIOCM_DTR;
+
+ port->ops->set_termios(port, &termios, &dummy);
+- co->cflag = termios.c_cflag;
++ /*
++ * Allow the setting of the UART parameters with a NULL console
++ * too:
++ */
++ if (co)
++ co->cflag = termios.c_cflag;
+
+ return 0;
+ }
++EXPORT_SYMBOL_GPL(uart_set_options);
+ #endif /* CONFIG_SERIAL_CORE_CONSOLE */
+
+ static void uart_change_pm(struct uart_state *state, int pm_state)
+@@ -2182,6 +2189,60 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
+ }
+ }
+
++#ifdef CONFIG_CONSOLE_POLL
++
++static int uart_poll_init(struct tty_driver *driver, int line, char *options)
++{
++ struct uart_driver *drv = driver->driver_state;
++ struct uart_state *state = drv->state + line;
++ struct uart_port *port;
++ int baud = 9600;
++ int bits = 8;
++ int parity = 'n';
++ int flow = 'n';
++
++ if (!state || !state->port)
++ return -1;
++
++ port = state->port;
++ if (!(port->ops->poll_get_char && port->ops->poll_put_char))
++ return -1;
++
++ if (options) {
++ uart_parse_options(options, &baud, &parity, &bits, &flow);
++ return uart_set_options(port, NULL, baud, parity, bits, flow);
++ }
++
++ return 0;
++}
++
++static int uart_poll_get_char(struct tty_driver *driver, int line)
++{
++ struct uart_driver *drv = driver->driver_state;
++ struct uart_state *state = drv->state + line;
++ struct uart_port *port;
++
++ if (!state || !state->port)
++ return -1;
++
++ port = state->port;
++ return port->ops->poll_get_char(port);
++}
++
++static void uart_poll_put_char(struct tty_driver *driver, int line, char ch)
++{
++ struct uart_driver *drv = driver->driver_state;
++ struct uart_state *state = drv->state + line;
++ struct uart_port *port;
++
++ if (!state || !state->port)
++ return;
++
++ port = state->port;
++ port->ops->poll_put_char(port, ch);
++}
++#endif
++
+ static const struct tty_operations uart_ops = {
+ .open = uart_open,
+ .close = uart_close,
+@@ -2206,6 +2267,11 @@ static const struct tty_operations uart_ops = {
+ #endif
+ .tiocmget = uart_tiocmget,
+ .tiocmset = uart_tiocmset,
++#ifdef CONFIG_CONSOLE_POLL
++ .poll_init = uart_poll_init,
++ .poll_get_char = uart_poll_get_char,
++ .poll_put_char = uart_poll_put_char,
++#endif
+ };
+
+ /**
+@@ -2356,7 +2422,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
+ */
+ tty_dev = tty_register_device(drv->tty_driver, port->line, port->dev);
+ if (likely(!IS_ERR(tty_dev))) {
+- device_can_wakeup(tty_dev) = 1;
++ device_init_wakeup(tty_dev, 1);
+ device_set_wakeup_enable(tty_dev, 0);
+ } else
+ printk(KERN_ERR "Cannot register tty device on line %d\n",
+diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
+index eff5930..c2ea5d4 100644
+--- a/drivers/serial/sh-sci.c
++++ b/drivers/serial/sh-sci.c
+@@ -333,7 +333,6 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
+ }
+ sci_out(port, SCFCR, fcr_val);
+ }
+-
+ #elif defined(CONFIG_CPU_SH3)
+ /* For SH7705, SH7706, SH7707, SH7709, SH7709A, SH7729 */
+ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
+@@ -384,6 +383,12 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
+
+ sci_out(port, SCFCR, fcr_val);
+ }
++#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
++static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
++{
++ /* Nothing to do here.. */
++ sci_out(port, SCFCR, 0);
++}
+ #else
+ /* For SH7750 */
+ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
+diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
+index 01a9dd7..fa8700a 100644
+--- a/drivers/serial/sh-sci.h
++++ b/drivers/serial/sh-sci.h
+@@ -1,20 +1,5 @@
+-/* $Id: sh-sci.h,v 1.4 2004/02/19 16:43:56 lethal Exp $
+- *
+- * linux/drivers/serial/sh-sci.h
+- *
+- * SuperH on-chip serial module support. (SCI with no FIFO / with FIFO)
+- * Copyright (C) 1999, 2000 Niibe Yutaka
+- * Copyright (C) 2000 Greg Banks
+- * Copyright (C) 2002, 2003 Paul Mundt
+- * Modified to support multiple serial ports. Stuart Menefy (May 2000).
+- * Modified to support SH7300(SH-Mobile) SCIF. Takashi Kusuda (Jun 2003).
+- * Modified to support H8/300 Series Yoshinori Sato (Feb 2004).
+- * Removed SH7300 support (Jul 2007).
+- * Modified to support SH7720 SCIF. Markus Brunner, Mark Jonas (Aug 2007).
+- */
+ #include <linux/serial_core.h>
+ #include <asm/io.h>
+-
+ #include <asm/gpio.h>
+
+ #if defined(CONFIG_H83007) || defined(CONFIG_H83068)
+@@ -102,6 +87,15 @@
+ # define SCSPTR0 SCPDR0
+ # define SCIF_ORER 0x0001 /* overrun error bit */
+ # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
++#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
++# define SCSPTR0 0xa4050160
++# define SCSPTR1 0xa405013e
++# define SCSPTR2 0xa4050160
++# define SCSPTR3 0xa405013e
++# define SCSPTR4 0xa4050128
++# define SCSPTR5 0xa4050128
++# define SCIF_ORER 0x0001 /* overrun error bit */
++# define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+ # define SCIF_ONLY
+ #elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
+ # define SCSPTR2 0xffe80020 /* 16 bit SCIF */
+@@ -395,6 +389,11 @@
+ h8_sci_offset, h8_sci_size) \
+ CPU_SCI_FNS(name, h8_sci_offset, h8_sci_size)
+ #define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size)
++#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
++ #define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size) \
++ CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size)
++ #define SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) \
++ CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size)
+ #else
+ #define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \
+ sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \
+@@ -419,6 +418,18 @@ SCIF_FNS(SCFDR, 0x1c, 16)
+ SCIF_FNS(SCxTDR, 0x20, 8)
+ SCIF_FNS(SCxRDR, 0x24, 8)
+ SCIF_FNS(SCLSR, 0x24, 16)
++#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
++SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16)
++SCIx_FNS(SCBRR, 0x04, 8, 0x04, 8)
++SCIx_FNS(SCSCR, 0x08, 16, 0x08, 16)
++SCIx_FNS(SCxTDR, 0x20, 8, 0x0c, 8)
++SCIx_FNS(SCxSR, 0x14, 16, 0x10, 16)
++SCIx_FNS(SCxRDR, 0x24, 8, 0x14, 8)
++SCIF_FNS(SCTDSR, 0x0c, 8)
++SCIF_FNS(SCFER, 0x10, 16)
++SCIF_FNS(SCFCR, 0x18, 16)
++SCIF_FNS(SCFDR, 0x1c, 16)
++SCIF_FNS(SCLSR, 0x24, 16)
+ #else
+ /* reg SCI/SH3 SCI/SH4 SCIF/SH3 SCIF/SH4 SCI/H8*/
+ /* name off sz off sz off sz off sz off sz*/
+@@ -589,6 +600,23 @@ static inline int sci_rxd_in(struct uart_port *port)
+ return ctrl_inb(SCPDR0) & 0x0001 ? 1 : 0; /* SCIF0 */
+ return 1;
+ }
++#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
++static inline int sci_rxd_in(struct uart_port *port)
++{
++ if (port->mapbase == 0xffe00000)
++ return ctrl_inb(SCSPTR0) & 0x0008 ? 1 : 0; /* SCIF0 */
++ if (port->mapbase == 0xffe10000)
++ return ctrl_inb(SCSPTR1) & 0x0020 ? 1 : 0; /* SCIF1 */
++ if (port->mapbase == 0xffe20000)
++ return ctrl_inb(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF2 */
++ if (port->mapbase == 0xa4e30000)
++ return ctrl_inb(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF3 */
++ if (port->mapbase == 0xa4e40000)
++ return ctrl_inb(SCSPTR4) & 0x0001 ? 1 : 0; /* SCIF4 */
++ if (port->mapbase == 0xa4e50000)
++ return ctrl_inb(SCSPTR5) & 0x0008 ? 1 : 0; /* SCIF5 */
++ return 1;
++}
+ #elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
+ static inline int sci_rxd_in(struct uart_port *port)
+ {
+@@ -727,6 +755,8 @@ static inline int sci_rxd_in(struct uart_port *port)
+ defined(CONFIG_CPU_SUBTYPE_SH7720) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7721)
+ #define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1)
++#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
++#define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(16*bps)-1)
+ #elif defined(__H8300H__) || defined(__H8300S__)
+ #define SCBRR_VALUE(bps) (((CONFIG_CPU_CLOCK*1000/32)/bps)-1)
+ #elif defined(CONFIG_SUPERH64)
+diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
+index cb2e405..3271379 100644
+--- a/drivers/serial/sunzilog.c
++++ b/drivers/serial/sunzilog.c
+@@ -1015,6 +1015,7 @@ static struct uart_ops sunzilog_pops = {
+ .verify_port = sunzilog_verify_port,
+ };
+
++static int uart_chip_count;
+ static struct uart_sunzilog_port *sunzilog_port_table;
+ static struct zilog_layout __iomem **sunzilog_chip_regs;
+
+@@ -1350,16 +1351,22 @@ static int zilog_irq = -1;
+
+ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *match)
+ {
+- static int inst;
++ static int kbm_inst, uart_inst;
++ int inst;
+ struct uart_sunzilog_port *up;
+ struct zilog_layout __iomem *rp;
+- int keyboard_mouse;
++ int keyboard_mouse = 0;
+ int err;
+
+- keyboard_mouse = 0;
+ if (of_find_property(op->node, "keyboard", NULL))
+ keyboard_mouse = 1;
+
++ /* uarts must come before keyboards/mice */
++ if (keyboard_mouse)
++ inst = uart_chip_count + kbm_inst;
++ else
++ inst = uart_inst;
++
+ sunzilog_chip_regs[inst] = of_ioremap(&op->resource[0], 0,
+ sizeof(struct zilog_layout),
+ "zs");
+@@ -1427,6 +1434,7 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m
+ rp, sizeof(struct zilog_layout));
+ return err;
+ }
++ uart_inst++;
+ } else {
+ printk(KERN_INFO "%s: Keyboard at MMIO 0x%llx (irq = %d) "
+ "is a %s\n",
+@@ -1438,12 +1446,11 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m
+ op->dev.bus_id,
+ (unsigned long long) up[1].port.mapbase,
+ op->irqs[0], sunzilog_type(&up[1].port));
++ kbm_inst++;
+ }
+
+ dev_set_drvdata(&op->dev, &up[0]);
+
+- inst++;
+-
+ return 0;
+ }
+
+@@ -1491,28 +1498,25 @@ static struct of_platform_driver zs_driver = {
+ static int __init sunzilog_init(void)
+ {
+ struct device_node *dp;
+- int err, uart_count;
+- int num_keybms;
++ int err;
++ int num_keybms = 0;
+ int num_sunzilog = 0;
+
+- num_keybms = 0;
+ for_each_node_by_name(dp, "zs") {
+ num_sunzilog++;
+ if (of_find_property(dp, "keyboard", NULL))
+ num_keybms++;
+ }
+
+- uart_count = 0;
+ if (num_sunzilog) {
+- int uart_count;
+-
+ err = sunzilog_alloc_tables(num_sunzilog);
+ if (err)
+ goto out;
+
+- uart_count = (num_sunzilog * 2) - (2 * num_keybms);
++ uart_chip_count = num_sunzilog - num_keybms;
+
+- err = sunserial_register_minors(&sunzilog_reg, uart_count);
++ err = sunserial_register_minors(&sunzilog_reg,
++ uart_chip_count * 2);
+ if (err)
+ goto out_free_tables;
+ }
+diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c
+index e0994f0..5e4310c 100644
+--- a/drivers/serial/ucc_uart.c
++++ b/drivers/serial/ucc_uart.c
+@@ -1270,10 +1270,18 @@ static int ucc_uart_probe(struct of_device *ofdev,
+
+ /* Get the UCC number (device ID) */
+ /* UCCs are numbered 1-7 */
+- iprop = of_get_property(np, "device-id", NULL);
+- if (!iprop || (*iprop < 1) || (*iprop > UCC_MAX_NUM)) {
+- dev_err(&ofdev->dev,
+- "missing or invalid UCC specified in device tree\n");
++ iprop = of_get_property(np, "cell-index", NULL);
++ if (!iprop) {
++ iprop = of_get_property(np, "device-id", NULL);
++ if (!iprop) {
++ dev_err(&ofdev->dev, "UCC is unspecified in "
++ "device tree\n");
++ return -EINVAL;
++ }
++ }
++
++ if ((*iprop < 1) || (*iprop > UCC_MAX_NUM)) {
++ dev_err(&ofdev->dev, "no support for UCC%u\n", *iprop);
+ kfree(qe_port);
+ return -ENODEV;
+ }
+diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig
+index adea792..cd845b8 100644
+--- a/drivers/ssb/Kconfig
++++ b/drivers/ssb/Kconfig
+@@ -20,6 +20,15 @@ config SSB
+
+ If unsure, say N.
+
++# Common SPROM support routines
++config SSB_SPROM
++ bool
++
++# Support for Block-I/O. SELECT this from the driver that needs it.
++config SSB_BLOCKIO
++ bool
++ depends on SSB
++
+ config SSB_PCIHOST_POSSIBLE
+ bool
+ depends on SSB && (PCI = y || PCI = SSB)
+@@ -28,6 +37,7 @@ config SSB_PCIHOST_POSSIBLE
+ config SSB_PCIHOST
+ bool "Support for SSB on PCI-bus host"
+ depends on SSB_PCIHOST_POSSIBLE
++ select SSB_SPROM
+ default y
+ help
+ Support for a Sonics Silicon Backplane on top
+@@ -48,6 +58,7 @@ config SSB_PCMCIAHOST_POSSIBLE
+ config SSB_PCMCIAHOST
+ bool "Support for SSB on PCMCIA-bus host (EXPERIMENTAL)"
+ depends on SSB_PCMCIAHOST_POSSIBLE
++ select SSB_SPROM
+ help
+ Support for a Sonics Silicon Backplane on top
+ of a PCMCIA device.
+@@ -125,4 +136,13 @@ config SSB_DRIVER_EXTIF
+
+ If unsure, say N
+
++config SSB_DRIVER_GIGE
++ bool "SSB Broadcom Gigabit Ethernet driver"
++ depends on SSB_PCIHOST_POSSIBLE && SSB_EMBEDDED && MIPS
++ help
++ Driver for the Sonics Silicon Backplane attached
++ Broadcom Gigabit Ethernet.
++
++ If unsure, say N
++
+ endmenu
+diff --git a/drivers/ssb/Makefile b/drivers/ssb/Makefile
+index de94c2e..6f255e9 100644
+--- a/drivers/ssb/Makefile
++++ b/drivers/ssb/Makefile
+@@ -1,6 +1,7 @@
+ # core
+ ssb-y += main.o scan.o
+ ssb-$(CONFIG_SSB_EMBEDDED) += embedded.o
++ssb-$(CONFIG_SSB_SPROM) += sprom.o
+
+ # host support
+ ssb-$(CONFIG_SSB_PCIHOST) += pci.o pcihost_wrapper.o
+@@ -11,6 +12,7 @@ ssb-y += driver_chipcommon.o
+ ssb-$(CONFIG_SSB_DRIVER_MIPS) += driver_mipscore.o
+ ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o
+ ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o
++ssb-$(CONFIG_SSB_DRIVER_GIGE) += driver_gige.o
+
+ # b43 pci-ssb-bridge driver
+ # Not strictly a part of SSB, but kept here for convenience
+diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c
+index e586321..571f4fd 100644
+--- a/drivers/ssb/driver_chipcommon.c
++++ b/drivers/ssb/driver_chipcommon.c
+@@ -251,7 +251,7 @@ void ssb_chipcommon_init(struct ssb_chipcommon *cc)
+ calc_fast_powerup_delay(cc);
+ }
+
+-void ssb_chipco_suspend(struct ssb_chipcommon *cc, pm_message_t state)
++void ssb_chipco_suspend(struct ssb_chipcommon *cc)
+ {
+ if (!cc->dev)
+ return;
+@@ -353,6 +353,16 @@ void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks)
+ chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks);
+ }
+
++void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value)
++{
++ chipco_write32_masked(cc, SSB_CHIPCO_IRQMASK, mask, value);
++}
++
++u32 ssb_chipco_irq_status(struct ssb_chipcommon *cc, u32 mask)
++{
++ return chipco_read32(cc, SSB_CHIPCO_IRQSTAT) & mask;
++}
++
+ u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask)
+ {
+ return chipco_read32(cc, SSB_CHIPCO_GPIOIN) & mask;
+diff --git a/drivers/ssb/driver_gige.c b/drivers/ssb/driver_gige.c
+new file mode 100644
+index 0000000..172f904
+--- /dev/null
++++ b/drivers/ssb/driver_gige.c
+@@ -0,0 +1,294 @@
++/*
++ * Sonics Silicon Backplane
++ * Broadcom Gigabit Ethernet core driver
++ *
++ * Copyright 2008, Broadcom Corporation
++ * Copyright 2008, Michael Buesch <mb at bu3sch.de>
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++
++#include <linux/ssb/ssb.h>
++#include <linux/ssb/ssb_driver_gige.h>
++#include <linux/pci.h>
++#include <linux/pci_regs.h>
++
++
++/*
++MODULE_DESCRIPTION("SSB Broadcom Gigabit Ethernet driver");
++MODULE_AUTHOR("Michael Buesch");
++MODULE_LICENSE("GPL");
++*/
++
++static const struct ssb_device_id ssb_gige_tbl[] = {
++ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_ETHERNET_GBIT, SSB_ANY_REV),
++ SSB_DEVTABLE_END
++};
++/* MODULE_DEVICE_TABLE(ssb, ssb_gige_tbl); */
++
++
++static inline u8 gige_read8(struct ssb_gige *dev, u16 offset)
++{
++ return ssb_read8(dev->dev, offset);
++}
++
++static inline u16 gige_read16(struct ssb_gige *dev, u16 offset)
++{
++ return ssb_read16(dev->dev, offset);
++}
++
++static inline u32 gige_read32(struct ssb_gige *dev, u16 offset)
++{
++ return ssb_read32(dev->dev, offset);
++}
++
++static inline void gige_write8(struct ssb_gige *dev,
++ u16 offset, u8 value)
++{
++ ssb_write8(dev->dev, offset, value);
++}
++
++static inline void gige_write16(struct ssb_gige *dev,
++ u16 offset, u16 value)
++{
++ ssb_write16(dev->dev, offset, value);
++}
++
++static inline void gige_write32(struct ssb_gige *dev,
++ u16 offset, u32 value)
++{
++ ssb_write32(dev->dev, offset, value);
++}
++
++static inline
++u8 gige_pcicfg_read8(struct ssb_gige *dev, unsigned int offset)
++{
++ BUG_ON(offset >= 256);
++ return gige_read8(dev, SSB_GIGE_PCICFG + offset);
++}
++
++static inline
++u16 gige_pcicfg_read16(struct ssb_gige *dev, unsigned int offset)
++{
++ BUG_ON(offset >= 256);
++ return gige_read16(dev, SSB_GIGE_PCICFG + offset);
++}
++
++static inline
++u32 gige_pcicfg_read32(struct ssb_gige *dev, unsigned int offset)
++{
++ BUG_ON(offset >= 256);
++ return gige_read32(dev, SSB_GIGE_PCICFG + offset);
++}
++
++static inline
++void gige_pcicfg_write8(struct ssb_gige *dev,
++ unsigned int offset, u8 value)
++{
++ BUG_ON(offset >= 256);
++ gige_write8(dev, SSB_GIGE_PCICFG + offset, value);
++}
++
++static inline
++void gige_pcicfg_write16(struct ssb_gige *dev,
++ unsigned int offset, u16 value)
++{
++ BUG_ON(offset >= 256);
++ gige_write16(dev, SSB_GIGE_PCICFG + offset, value);
++}
++
++static inline
++void gige_pcicfg_write32(struct ssb_gige *dev,
++ unsigned int offset, u32 value)
++{
++ BUG_ON(offset >= 256);
++ gige_write32(dev, SSB_GIGE_PCICFG + offset, value);
++}
++
++static int ssb_gige_pci_read_config(struct pci_bus *bus, unsigned int devfn,
++ int reg, int size, u32 *val)
++{
++ struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
++ unsigned long flags;
++
++ if ((PCI_SLOT(devfn) > 0) || (PCI_FUNC(devfn) > 0))
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ if (reg >= 256)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ spin_lock_irqsave(&dev->lock, flags);
++ switch (size) {
++ case 1:
++ *val = gige_pcicfg_read8(dev, reg);
++ break;
++ case 2:
++ *val = gige_pcicfg_read16(dev, reg);
++ break;
++ case 4:
++ *val = gige_pcicfg_read32(dev, reg);
++ break;
++ default:
++ WARN_ON(1);
++ }
++ spin_unlock_irqrestore(&dev->lock, flags);
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static int ssb_gige_pci_write_config(struct pci_bus *bus, unsigned int devfn,
++ int reg, int size, u32 val)
++{
++ struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
++ unsigned long flags;
++
++ if ((PCI_SLOT(devfn) > 0) || (PCI_FUNC(devfn) > 0))
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ if (reg >= 256)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ spin_lock_irqsave(&dev->lock, flags);
++ switch (size) {
++ case 1:
++ gige_pcicfg_write8(dev, reg, val);
++ break;
++ case 2:
++ gige_pcicfg_write16(dev, reg, val);
++ break;
++ case 4:
++ gige_pcicfg_write32(dev, reg, val);
++ break;
++ default:
++ WARN_ON(1);
++ }
++ spin_unlock_irqrestore(&dev->lock, flags);
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static int ssb_gige_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
++{
++ struct ssb_gige *dev;
++ u32 base, tmslow, tmshigh;
++
++ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
++ if (!dev)
++ return -ENOMEM;
++ dev->dev = sdev;
++
++ spin_lock_init(&dev->lock);
++ dev->pci_controller.pci_ops = &dev->pci_ops;
++ dev->pci_controller.io_resource = &dev->io_resource;
++ dev->pci_controller.mem_resource = &dev->mem_resource;
++ dev->pci_controller.io_map_base = 0x800;
++ dev->pci_ops.read = ssb_gige_pci_read_config;
++ dev->pci_ops.write = ssb_gige_pci_write_config;
++
++ dev->io_resource.name = SSB_GIGE_IO_RES_NAME;
++ dev->io_resource.start = 0x800;
++ dev->io_resource.end = 0x8FF;
++ dev->io_resource.flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED;
++
++ if (!ssb_device_is_enabled(sdev))
++ ssb_device_enable(sdev, 0);
++
++ /* Setup BAR0. This is a 64k MMIO region. */
++ base = ssb_admatch_base(ssb_read32(sdev, SSB_ADMATCH1));
++ gige_pcicfg_write32(dev, PCI_BASE_ADDRESS_0, base);
++ gige_pcicfg_write32(dev, PCI_BASE_ADDRESS_1, 0);
++
++ dev->mem_resource.name = SSB_GIGE_MEM_RES_NAME;
++ dev->mem_resource.start = base;
++ dev->mem_resource.end = base + 0x10000 - 1;
++ dev->mem_resource.flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED;
++
++ /* Enable the memory region. */
++ gige_pcicfg_write16(dev, PCI_COMMAND,
++ gige_pcicfg_read16(dev, PCI_COMMAND)
++ | PCI_COMMAND_MEMORY);
++
++ /* Write flushing is controlled by the Flush Status Control register.
++ * We want to flush every register write with a timeout and we want
++ * to disable the IRQ mask while flushing to avoid concurrency.
++ * Note that automatic write flushing does _not_ work from
++ * an IRQ handler. The driver must flush manually by reading a register.
++ */
++ gige_write32(dev, SSB_GIGE_SHIM_FLUSHSTAT, 0x00000068);
++
++ /* Check if we have an RGMII or GMII PHY-bus.
++ * On RGMII do not bypass the DLLs */
++ tmslow = ssb_read32(sdev, SSB_TMSLOW);
++ tmshigh = ssb_read32(sdev, SSB_TMSHIGH);
++ if (tmshigh & SSB_GIGE_TMSHIGH_RGMII) {
++ tmslow &= ~SSB_GIGE_TMSLOW_TXBYPASS;
++ tmslow &= ~SSB_GIGE_TMSLOW_RXBYPASS;
++ dev->has_rgmii = 1;
++ } else {
++ tmslow |= SSB_GIGE_TMSLOW_TXBYPASS;
++ tmslow |= SSB_GIGE_TMSLOW_RXBYPASS;
++ dev->has_rgmii = 0;
++ }
++ tmslow |= SSB_GIGE_TMSLOW_DLLEN;
++ ssb_write32(sdev, SSB_TMSLOW, tmslow);
++
++ ssb_set_drvdata(sdev, dev);
++ register_pci_controller(&dev->pci_controller);
++
++ return 0;
++}
++
++bool pdev_is_ssb_gige_core(struct pci_dev *pdev)
++{
++ if (!pdev->resource[0].name)
++ return 0;
++ return (strcmp(pdev->resource[0].name, SSB_GIGE_MEM_RES_NAME) == 0);
++}
++EXPORT_SYMBOL(pdev_is_ssb_gige_core);
++
++int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,
++ struct pci_dev *pdev)
++{
++ struct ssb_gige *dev = ssb_get_drvdata(sdev);
++ struct resource *res;
++
++ if (pdev->bus->ops != &dev->pci_ops) {
++ /* The PCI device is not on this SSB GigE bridge device. */
++ return -ENODEV;
++ }
++
++ /* Fixup the PCI resources. */
++ res = &(pdev->resource[0]);
++ res->flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED;
++ res->name = dev->mem_resource.name;
++ res->start = dev->mem_resource.start;
++ res->end = dev->mem_resource.end;
++
++ /* Fixup interrupt lines. */
++ pdev->irq = ssb_mips_irq(sdev) + 2;
++ pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, pdev->irq);
++
++ return 0;
++}
++
++int ssb_gige_map_irq(struct ssb_device *sdev,
++ const struct pci_dev *pdev)
++{
++ struct ssb_gige *dev = ssb_get_drvdata(sdev);
++
++ if (pdev->bus->ops != &dev->pci_ops) {
++ /* The PCI device is not on this SSB GigE bridge device. */
++ return -ENODEV;
++ }
++
++ return ssb_mips_irq(sdev) + 2;
++}
++
++static struct ssb_driver ssb_gige_driver = {
++ .name = "BCM-GigE",
++ .id_table = ssb_gige_tbl,
++ .probe = ssb_gige_probe,
++};
++
++int ssb_gige_init(void)
++{
++ return ssb_driver_register(&ssb_gige_driver);
++}
+diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c
+index a9e7eb4..3fd3e3b 100644
+--- a/drivers/ssb/driver_mipscore.c
++++ b/drivers/ssb/driver_mipscore.c
+@@ -210,6 +210,7 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore)
+ /* fallthrough */
+ case SSB_DEV_PCI:
+ case SSB_DEV_ETHERNET:
++ case SSB_DEV_ETHERNET_GBIT:
+ case SSB_DEV_80211:
+ case SSB_DEV_USB20_HOST:
+ /* These devices get their own IRQ line if available, the rest goes on IRQ0 */
+diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c
+index 5d777f2..75def13 100644
+--- a/drivers/ssb/driver_pcicore.c
++++ b/drivers/ssb/driver_pcicore.c
+@@ -60,77 +60,6 @@ static DEFINE_SPINLOCK(cfgspace_lock);
+ /* Core to access the external PCI config space. Can only have one. */
+ static struct ssb_pcicore *extpci_core;
+
+-static u32 ssb_pcicore_pcibus_iobase = 0x100;
+-static u32 ssb_pcicore_pcibus_membase = SSB_PCI_DMA;
+-
+-int pcibios_plat_dev_init(struct pci_dev *d)
+-{
+- struct resource *res;
+- int pos, size;
+- u32 *base;
+-
+- ssb_printk(KERN_INFO "PCI: Fixing up device %s\n",
+- pci_name(d));
+-
+- /* Fix up resource bases */
+- for (pos = 0; pos < 6; pos++) {
+- res = &d->resource[pos];
+- if (res->flags & IORESOURCE_IO)
+- base = &ssb_pcicore_pcibus_iobase;
+- else
+- base = &ssb_pcicore_pcibus_membase;
+- res->flags |= IORESOURCE_PCI_FIXED;
+- if (res->end) {
+- size = res->end - res->start + 1;
+- if (*base & (size - 1))
+- *base = (*base + size) & ~(size - 1);
+- res->start = *base;
+- res->end = res->start + size - 1;
+- *base += size;
+- pci_write_config_dword(d, PCI_BASE_ADDRESS_0 + (pos << 2), res->start);
+- }
+- /* Fix up PCI bridge BAR0 only */
+- if (d->bus->number == 0 && PCI_SLOT(d->devfn) == 0)
+- break;
+- }
+- /* Fix up interrupt lines */
+- d->irq = ssb_mips_irq(extpci_core->dev) + 2;
+- pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq);
+-
+- return 0;
+-}
+-
+-static void __init ssb_fixup_pcibridge(struct pci_dev *dev)
+-{
+- u8 lat;
+-
+- if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0)
+- return;
+-
+- ssb_printk(KERN_INFO "PCI: Fixing up bridge %s\n", pci_name(dev));
+-
+- /* Enable PCI bridge bus mastering and memory space */
+- pci_set_master(dev);
+- if (pcibios_enable_device(dev, ~0) < 0) {
+- ssb_printk(KERN_ERR "PCI: SSB bridge enable failed\n");
+- return;
+- }
+-
+- /* Enable PCI bridge BAR1 prefetch and burst */
+- pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3);
+-
+- /* Make sure our latency is high enough to handle the devices behind us */
+- lat = 168;
+- ssb_printk(KERN_INFO "PCI: Fixing latency timer of device %s to %u\n",
+- pci_name(dev), lat);
+- pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
+-}
+-DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_fixup_pcibridge);
+-
+-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+-{
+- return ssb_mips_irq(extpci_core->dev) + 2;
+-}
+
+ static u32 get_cfgspace_addr(struct ssb_pcicore *pc,
+ unsigned int bus, unsigned int dev,
+@@ -320,6 +249,95 @@ static struct pci_controller ssb_pcicore_controller = {
+ .mem_offset = 0x24000000,
+ };
+
++static u32 ssb_pcicore_pcibus_iobase = 0x100;
++static u32 ssb_pcicore_pcibus_membase = SSB_PCI_DMA;
++
++/* This function is called when doing a pci_enable_device().
++ * We must first check if the device is a device on the PCI-core bridge. */
++int ssb_pcicore_plat_dev_init(struct pci_dev *d)
++{
++ struct resource *res;
++ int pos, size;
++ u32 *base;
++
++ if (d->bus->ops != &ssb_pcicore_pciops) {
++ /* This is not a device on the PCI-core bridge. */
++ return -ENODEV;
++ }
++
++ ssb_printk(KERN_INFO "PCI: Fixing up device %s\n",
++ pci_name(d));
++
++ /* Fix up resource bases */
++ for (pos = 0; pos < 6; pos++) {
++ res = &d->resource[pos];
++ if (res->flags & IORESOURCE_IO)
++ base = &ssb_pcicore_pcibus_iobase;
++ else
++ base = &ssb_pcicore_pcibus_membase;
++ res->flags |= IORESOURCE_PCI_FIXED;
++ if (res->end) {
++ size = res->end - res->start + 1;
++ if (*base & (size - 1))
++ *base = (*base + size) & ~(size - 1);
++ res->start = *base;
++ res->end = res->start + size - 1;
++ *base += size;
++ pci_write_config_dword(d, PCI_BASE_ADDRESS_0 + (pos << 2), res->start);
++ }
++ /* Fix up PCI bridge BAR0 only */
++ if (d->bus->number == 0 && PCI_SLOT(d->devfn) == 0)
++ break;
++ }
++ /* Fix up interrupt lines */
++ d->irq = ssb_mips_irq(extpci_core->dev) + 2;
++ pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq);
++
++ return 0;
++}
++
++/* Early PCI fixup for a device on the PCI-core bridge. */
++static void ssb_pcicore_fixup_pcibridge(struct pci_dev *dev)
++{
++ u8 lat;
++
++ if (dev->bus->ops != &ssb_pcicore_pciops) {
++ /* This is not a device on the PCI-core bridge. */
++ return;
++ }
++ if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0)
++ return;
++
++ ssb_printk(KERN_INFO "PCI: Fixing up bridge %s\n", pci_name(dev));
++
++ /* Enable PCI bridge bus mastering and memory space */
++ pci_set_master(dev);
++ if (pcibios_enable_device(dev, ~0) < 0) {
++ ssb_printk(KERN_ERR "PCI: SSB bridge enable failed\n");
++ return;
++ }
++
++ /* Enable PCI bridge BAR1 prefetch and burst */
++ pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3);
++
++ /* Make sure our latency is high enough to handle the devices behind us */
++ lat = 168;
++ ssb_printk(KERN_INFO "PCI: Fixing latency timer of device %s to %u\n",
++ pci_name(dev), lat);
++ pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
++}
++DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_pcicore_fixup_pcibridge);
++
++/* PCI device IRQ mapping. */
++int ssb_pcicore_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
++{
++ if (dev->bus->ops != &ssb_pcicore_pciops) {
++ /* This is not a device on the PCI-core bridge. */
++ return -ENODEV;
++ }
++ return ssb_mips_irq(extpci_core->dev) + 2;
++}
++
+ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
+ {
+ u32 val;
+@@ -544,15 +562,9 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc,
+ u32 intvec;
+
+ intvec = ssb_read32(pdev, SSB_INTVEC);
+- if ((bus->chip_id & 0xFF00) == 0x4400) {
+- /* Workaround: On the BCM44XX the BPFLAG routing
+- * bit is wrong. Use a hardcoded constant. */
+- intvec |= 0x00000002;
+- } else {
+- tmp = ssb_read32(dev, SSB_TPSFLAG);
+- tmp &= SSB_TPSFLAG_BPFLAG;
+- intvec |= (1 << tmp);
+- }
++ tmp = ssb_read32(dev, SSB_TPSFLAG);
++ tmp &= SSB_TPSFLAG_BPFLAG;
++ intvec |= (1 << tmp);
+ ssb_write32(pdev, SSB_INTVEC, intvec);
+ }
+
+diff --git a/drivers/ssb/embedded.c b/drivers/ssb/embedded.c
+index d3ade82..7dc3a6b 100644
+--- a/drivers/ssb/embedded.c
++++ b/drivers/ssb/embedded.c
+@@ -10,6 +10,9 @@
+
+ #include <linux/ssb/ssb.h>
+ #include <linux/ssb/ssb_embedded.h>
++#include <linux/ssb/ssb_driver_pci.h>
++#include <linux/ssb/ssb_driver_gige.h>
++#include <linux/pci.h>
+
+ #include "ssb_private.h"
+
+@@ -130,3 +133,90 @@ u32 ssb_gpio_polarity(struct ssb_bus *bus, u32 mask, u32 value)
+ return res;
+ }
+ EXPORT_SYMBOL(ssb_gpio_polarity);
++
++#ifdef CONFIG_SSB_DRIVER_GIGE
++static int gige_pci_init_callback(struct ssb_bus *bus, unsigned long data)
++{
++ struct pci_dev *pdev = (struct pci_dev *)data;
++ struct ssb_device *dev;
++ unsigned int i;
++ int res;
++
++ for (i = 0; i < bus->nr_devices; i++) {
++ dev = &(bus->devices[i]);
++ if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT)
++ continue;
++ if (!dev->dev ||
++ !dev->dev->driver ||
++ !device_is_registered(dev->dev))
++ continue;
++ res = ssb_gige_pcibios_plat_dev_init(dev, pdev);
++ if (res >= 0)
++ return res;
++ }
++
++ return -ENODEV;
++}
++#endif /* CONFIG_SSB_DRIVER_GIGE */
++
++int ssb_pcibios_plat_dev_init(struct pci_dev *dev)
++{
++ int err;
++
++ err = ssb_pcicore_plat_dev_init(dev);
++ if (!err)
++ return 0;
++#ifdef CONFIG_SSB_DRIVER_GIGE
++ err = ssb_for_each_bus_call((unsigned long)dev, gige_pci_init_callback);
++ if (err >= 0)
++ return err;
++#endif
++ /* This is not a PCI device on any SSB device. */
++
++ return -ENODEV;
++}
++
++#ifdef CONFIG_SSB_DRIVER_GIGE
++static int gige_map_irq_callback(struct ssb_bus *bus, unsigned long data)
++{
++ const struct pci_dev *pdev = (const struct pci_dev *)data;
++ struct ssb_device *dev;
++ unsigned int i;
++ int res;
++
++ for (i = 0; i < bus->nr_devices; i++) {
++ dev = &(bus->devices[i]);
++ if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT)
++ continue;
++ if (!dev->dev ||
++ !dev->dev->driver ||
++ !device_is_registered(dev->dev))
++ continue;
++ res = ssb_gige_map_irq(dev, pdev);
++ if (res >= 0)
++ return res;
++ }
++
++ return -ENODEV;
++}
++#endif /* CONFIG_SSB_DRIVER_GIGE */
++
++int ssb_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
++{
++ int res;
++
++ /* Check if this PCI device is a device on a SSB bus or device
++ * and return the IRQ number for it. */
++
++ res = ssb_pcicore_pcibios_map_irq(dev, slot, pin);
++ if (res >= 0)
++ return res;
++#ifdef CONFIG_SSB_DRIVER_GIGE
++ res = ssb_for_each_bus_call((unsigned long)dev, gige_map_irq_callback);
++ if (res >= 0)
++ return res;
++#endif
++ /* This is not a PCI device on any SSB device. */
++
++ return -ENODEV;
++}
+diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
+index 8003a9e..7cf8851 100644
+--- a/drivers/ssb/main.c
++++ b/drivers/ssb/main.c
+@@ -14,6 +14,7 @@
+ #include <linux/io.h>
+ #include <linux/ssb/ssb.h>
+ #include <linux/ssb/ssb_regs.h>
++#include <linux/ssb/ssb_driver_gige.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/pci.h>
+
+@@ -68,6 +69,44 @@ found:
+ }
+ #endif /* CONFIG_SSB_PCIHOST */
+
++#ifdef CONFIG_SSB_PCMCIAHOST
++struct ssb_bus *ssb_pcmcia_dev_to_bus(struct pcmcia_device *pdev)
++{
++ struct ssb_bus *bus;
++
++ ssb_buses_lock();
++ list_for_each_entry(bus, &buses, list) {
++ if (bus->bustype == SSB_BUSTYPE_PCMCIA &&
++ bus->host_pcmcia == pdev)
++ goto found;
++ }
++ bus = NULL;
++found:
++ ssb_buses_unlock();
++
++ return bus;
++}
++#endif /* CONFIG_SSB_PCMCIAHOST */
++
++int ssb_for_each_bus_call(unsigned long data,
++ int (*func)(struct ssb_bus *bus, unsigned long data))
++{
++ struct ssb_bus *bus;
++ int res;
++
++ ssb_buses_lock();
++ list_for_each_entry(bus, &buses, list) {
++ res = func(bus, data);
++ if (res >= 0) {
++ ssb_buses_unlock();
++ return res;
++ }
++ }
++ ssb_buses_unlock();
++
++ return -ENODEV;
++}
++
+ static struct ssb_device *ssb_device_get(struct ssb_device *dev)
+ {
+ if (dev)
+@@ -81,35 +120,12 @@ static void ssb_device_put(struct ssb_device *dev)
+ put_device(dev->dev);
+ }
+
+-static int ssb_bus_resume(struct ssb_bus *bus)
+-{
+- int err;
+-
+- ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 1);
+- err = ssb_pcmcia_init(bus);
+- if (err) {
+- /* No need to disable XTAL, as we don't have one on PCMCIA. */
+- return err;
+- }
+- ssb_chipco_resume(&bus->chipco);
+-
+- return 0;
+-}
+-
+ static int ssb_device_resume(struct device *dev)
+ {
+ struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
+ struct ssb_driver *ssb_drv;
+- struct ssb_bus *bus;
+ int err = 0;
+
+- bus = ssb_dev->bus;
+- if (bus->suspend_cnt == bus->nr_devices) {
+- err = ssb_bus_resume(bus);
+- if (err)
+- return err;
+- }
+- bus->suspend_cnt--;
+ if (dev->driver) {
+ ssb_drv = drv_to_ssb_drv(dev->driver);
+ if (ssb_drv && ssb_drv->resume)
+@@ -121,27 +137,10 @@ out:
+ return err;
+ }
+
+-static void ssb_bus_suspend(struct ssb_bus *bus, pm_message_t state)
+-{
+- ssb_chipco_suspend(&bus->chipco, state);
+- ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0);
+-
+- /* Reset HW state information in memory, so that HW is
+- * completely reinitialized on resume. */
+- bus->mapped_device = NULL;
+-#ifdef CONFIG_SSB_DRIVER_PCICORE
+- bus->pcicore.setup_done = 0;
+-#endif
+-#ifdef CONFIG_SSB_DEBUG
+- bus->powered_up = 0;
+-#endif
+-}
+-
+ static int ssb_device_suspend(struct device *dev, pm_message_t state)
+ {
+ struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
+ struct ssb_driver *ssb_drv;
+- struct ssb_bus *bus;
+ int err = 0;
+
+ if (dev->driver) {
+@@ -151,19 +150,46 @@ static int ssb_device_suspend(struct device *dev, pm_message_t state)
+ if (err)
+ goto out;
+ }
++out:
++ return err;
++}
++
++int ssb_bus_resume(struct ssb_bus *bus)
++{
++ int err;
++
++ /* Reset HW state information in memory, so that HW is
++ * completely reinitialized. */
++ bus->mapped_device = NULL;
++#ifdef CONFIG_SSB_DRIVER_PCICORE
++ bus->pcicore.setup_done = 0;
++#endif
+
+- bus = ssb_dev->bus;
+- bus->suspend_cnt++;
+- if (bus->suspend_cnt == bus->nr_devices) {
+- /* All devices suspended. Shutdown the bus. */
+- ssb_bus_suspend(bus, state);
++ err = ssb_bus_powerup(bus, 0);
++ if (err)
++ return err;
++ err = ssb_pcmcia_hardware_setup(bus);
++ if (err) {
++ ssb_bus_may_powerdown(bus);
++ return err;
+ }
++ ssb_chipco_resume(&bus->chipco);
++ ssb_bus_may_powerdown(bus);
+
+-out:
+- return err;
++ return 0;
+ }
++EXPORT_SYMBOL(ssb_bus_resume);
+
+-#ifdef CONFIG_SSB_PCIHOST
++int ssb_bus_suspend(struct ssb_bus *bus)
++{
++ ssb_chipco_suspend(&bus->chipco);
++ ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0);
++
++ return 0;
++}
++EXPORT_SYMBOL(ssb_bus_suspend);
++
++#ifdef CONFIG_SSB_SPROM
+ int ssb_devices_freeze(struct ssb_bus *bus)
+ {
+ struct ssb_device *dev;
+@@ -249,7 +275,7 @@ int ssb_devices_thaw(struct ssb_bus *bus)
+
+ return 0;
+ }
+-#endif /* CONFIG_SSB_PCIHOST */
++#endif /* CONFIG_SSB_SPROM */
+
+ static void ssb_device_shutdown(struct device *dev)
+ {
+@@ -378,7 +404,7 @@ void ssb_bus_unregister(struct ssb_bus *bus)
+ list_del(&bus->list);
+ ssb_buses_unlock();
+
+- /* ssb_pcmcia_exit(bus); */
++ ssb_pcmcia_exit(bus);
+ ssb_pci_exit(bus);
+ ssb_iounmap(bus);
+ }
+@@ -508,6 +534,14 @@ error:
+ return err;
+ }
+
++static u8 ssb_ssb_read8(struct ssb_device *dev, u16 offset)
++{
++ struct ssb_bus *bus = dev->bus;
++
++ offset += dev->core_index * SSB_CORE_SIZE;
++ return readb(bus->mmio + offset);
++}
++
+ static u16 ssb_ssb_read16(struct ssb_device *dev, u16 offset)
+ {
+ struct ssb_bus *bus = dev->bus;
+@@ -524,6 +558,63 @@ static u32 ssb_ssb_read32(struct ssb_device *dev, u16 offset)
+ return readl(bus->mmio + offset);
+ }
+
++#ifdef CONFIG_SSB_BLOCKIO
++static void ssb_ssb_block_read(struct ssb_device *dev, void *buffer,
++ size_t count, u16 offset, u8 reg_width)
++{
++ struct ssb_bus *bus = dev->bus;
++ void __iomem *addr;
++
++ offset += dev->core_index * SSB_CORE_SIZE;
++ addr = bus->mmio + offset;
++
++ switch (reg_width) {
++ case sizeof(u8): {
++ u8 *buf = buffer;
++
++ while (count) {
++ *buf = __raw_readb(addr);
++ buf++;
++ count--;
++ }
++ break;
++ }
++ case sizeof(u16): {
++ __le16 *buf = buffer;
++
++ SSB_WARN_ON(count & 1);
++ while (count) {
++ *buf = (__force __le16)__raw_readw(addr);
++ buf++;
++ count -= 2;
++ }
++ break;
++ }
++ case sizeof(u32): {
++ __le32 *buf = buffer;
++
++ SSB_WARN_ON(count & 3);
++ while (count) {
++ *buf = (__force __le32)__raw_readl(addr);
++ buf++;
++ count -= 4;
++ }
++ break;
++ }
++ default:
++ SSB_WARN_ON(1);
++ }
++}
++#endif /* CONFIG_SSB_BLOCKIO */
++
++static void ssb_ssb_write8(struct ssb_device *dev, u16 offset, u8 value)
++{
++ struct ssb_bus *bus = dev->bus;
++
++ offset += dev->core_index * SSB_CORE_SIZE;
++ writeb(value, bus->mmio + offset);
++}
++
+ static void ssb_ssb_write16(struct ssb_device *dev, u16 offset, u16 value)
+ {
+ struct ssb_bus *bus = dev->bus;
+@@ -540,12 +631,67 @@ static void ssb_ssb_write32(struct ssb_device *dev, u16 offset, u32 value)
+ writel(value, bus->mmio + offset);
+ }
+
++#ifdef CONFIG_SSB_BLOCKIO
++static void ssb_ssb_block_write(struct ssb_device *dev, const void *buffer,
++ size_t count, u16 offset, u8 reg_width)
++{
++ struct ssb_bus *bus = dev->bus;
++ void __iomem *addr;
++
++ offset += dev->core_index * SSB_CORE_SIZE;
++ addr = bus->mmio + offset;
++
++ switch (reg_width) {
++ case sizeof(u8): {
++ const u8 *buf = buffer;
++
++ while (count) {
++ __raw_writeb(*buf, addr);
++ buf++;
++ count--;
++ }
++ break;
++ }
++ case sizeof(u16): {
++ const __le16 *buf = buffer;
++
++ SSB_WARN_ON(count & 1);
++ while (count) {
++ __raw_writew((__force u16)(*buf), addr);
++ buf++;
++ count -= 2;
++ }
++ break;
++ }
++ case sizeof(u32): {
++ const __le32 *buf = buffer;
++
++ SSB_WARN_ON(count & 3);
++ while (count) {
++ __raw_writel((__force u32)(*buf), addr);
++ buf++;
++ count -= 4;
++ }
++ break;
++ }
++ default:
++ SSB_WARN_ON(1);
++ }
++}
++#endif /* CONFIG_SSB_BLOCKIO */
++
+ /* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
+ static const struct ssb_bus_ops ssb_ssb_ops = {
++ .read8 = ssb_ssb_read8,
+ .read16 = ssb_ssb_read16,
+ .read32 = ssb_ssb_read32,
++ .write8 = ssb_ssb_write8,
+ .write16 = ssb_ssb_write16,
+ .write32 = ssb_ssb_write32,
++#ifdef CONFIG_SSB_BLOCKIO
++ .block_read = ssb_ssb_block_read,
++ .block_write = ssb_ssb_block_write,
++#endif
+ };
+
+ static int ssb_fetch_invariants(struct ssb_bus *bus,
+@@ -628,7 +774,7 @@ out:
+ err_dequeue:
+ list_del(&bus->list);
+ err_pcmcia_exit:
+-/* ssb_pcmcia_exit(bus); */
++ ssb_pcmcia_exit(bus);
+ err_pci_exit:
+ ssb_pci_exit(bus);
+ err_unmap:
+@@ -1010,9 +1156,9 @@ u32 ssb_dma_translation(struct ssb_device *dev)
+ {
+ switch (dev->bus->bustype) {
+ case SSB_BUSTYPE_SSB:
++ case SSB_BUSTYPE_PCMCIA:
+ return 0;
+ case SSB_BUSTYPE_PCI:
+- case SSB_BUSTYPE_PCMCIA:
+ return SSB_PCI_DMA;
+ }
+ return 0;
+@@ -1161,7 +1307,14 @@ static int __init ssb_modinit(void)
+ err = b43_pci_ssb_bridge_init();
+ if (err) {
+ ssb_printk(KERN_ERR "Broadcom 43xx PCI-SSB-bridge "
+- "initialization failed");
++ "initialization failed\n");
++ /* don't fail SSB init because of this */
++ err = 0;
++ }
++ err = ssb_gige_init();
++ if (err) {
++ ssb_printk(KERN_ERR "SSB Broadcom Gigabit Ethernet "
++ "driver initialization failed\n");
+ /* don't fail SSB init because of this */
+ err = 0;
+ }
+@@ -1175,6 +1328,7 @@ fs_initcall(ssb_modinit);
+
+ static void __exit ssb_modexit(void)
+ {
++ ssb_gige_exit();
+ b43_pci_ssb_bridge_exit();
+ bus_unregister(&ssb_bustype);
+ }
+diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
+index b434df7..57c4ccf 100644
+--- a/drivers/ssb/pci.c
++++ b/drivers/ssb/pci.c
+@@ -227,7 +227,7 @@ static u8 ssb_sprom_crc(const u16 *sprom, u16 size)
+ return crc;
+ }
+
+-static int sprom_check_crc(const u16 *sprom, u16 size)
++static int sprom_check_crc(const u16 *sprom, size_t size)
+ {
+ u8 crc;
+ u8 expected_crc;
+@@ -242,12 +242,14 @@ static int sprom_check_crc(const u16 *sprom, u16 size)
+ return 0;
+ }
+
+-static void sprom_do_read(struct ssb_bus *bus, u16 *sprom)
++static int sprom_do_read(struct ssb_bus *bus, u16 *sprom)
+ {
+ int i;
+
+ for (i = 0; i < bus->sprom_size; i++)
+ sprom[i] = ioread16(bus->mmio + SSB_SPROM_BASE + (i * 2));
++
++ return 0;
+ }
+
+ static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
+@@ -482,6 +484,11 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
+ goto unsupported;
+ }
+
++ if (out->boardflags_lo == 0xFFFF)
++ out->boardflags_lo = 0; /* per specs */
++ if (out->boardflags_hi == 0xFFFF)
++ out->boardflags_hi = 0; /* per specs */
++
+ return 0;
+ unsupported:
+ ssb_printk(KERN_WARNING PFX "Unsupported SPROM revision %d "
+@@ -572,6 +579,19 @@ static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
+ }
+ #endif /* DEBUG */
+
++static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
++{
++ struct ssb_bus *bus = dev->bus;
++
++ if (unlikely(ssb_pci_assert_buspower(bus)))
++ return 0xFF;
++ if (unlikely(bus->mapped_device != dev)) {
++ if (unlikely(ssb_pci_switch_core(bus, dev)))
++ return 0xFF;
++ }
++ return ioread8(bus->mmio + offset);
++}
++
+ static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
+ {
+ struct ssb_bus *bus = dev->bus;
+@@ -598,6 +618,54 @@ static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
+ return ioread32(bus->mmio + offset);
+ }
+
++#ifdef CONFIG_SSB_BLOCKIO
++static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
++ size_t count, u16 offset, u8 reg_width)
++{
++ struct ssb_bus *bus = dev->bus;
++ void __iomem *addr = bus->mmio + offset;
++
++ if (unlikely(ssb_pci_assert_buspower(bus)))
++ goto error;
++ if (unlikely(bus->mapped_device != dev)) {
++ if (unlikely(ssb_pci_switch_core(bus, dev)))
++ goto error;
++ }
++ switch (reg_width) {
++ case sizeof(u8):
++ ioread8_rep(addr, buffer, count);
++ break;
++ case sizeof(u16):
++ SSB_WARN_ON(count & 1);
++ ioread16_rep(addr, buffer, count >> 1);
++ break;
++ case sizeof(u32):
++ SSB_WARN_ON(count & 3);
++ ioread32_rep(addr, buffer, count >> 2);
++ break;
++ default:
++ SSB_WARN_ON(1);
++ }
++
++ return;
++error:
++ memset(buffer, 0xFF, count);
++}
++#endif /* CONFIG_SSB_BLOCKIO */
++
++static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
++{
++ struct ssb_bus *bus = dev->bus;
++
++ if (unlikely(ssb_pci_assert_buspower(bus)))
++ return;
++ if (unlikely(bus->mapped_device != dev)) {
++ if (unlikely(ssb_pci_switch_core(bus, dev)))
++ return;
++ }
++ iowrite8(value, bus->mmio + offset);
++}
++
+ static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
+ {
+ struct ssb_bus *bus = dev->bus;
+@@ -624,79 +692,63 @@ static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
+ iowrite32(value, bus->mmio + offset);
+ }
+
++#ifdef CONFIG_SSB_BLOCKIO
++static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
++ size_t count, u16 offset, u8 reg_width)
++{
++ struct ssb_bus *bus = dev->bus;
++ void __iomem *addr = bus->mmio + offset;
++
++ if (unlikely(ssb_pci_assert_buspower(bus)))
++ return;
++ if (unlikely(bus->mapped_device != dev)) {
++ if (unlikely(ssb_pci_switch_core(bus, dev)))
++ return;
++ }
++ switch (reg_width) {
++ case sizeof(u8):
++ iowrite8_rep(addr, buffer, count);
++ break;
++ case sizeof(u16):
++ SSB_WARN_ON(count & 1);
++ iowrite16_rep(addr, buffer, count >> 1);
++ break;
++ case sizeof(u32):
++ SSB_WARN_ON(count & 3);
++ iowrite32_rep(addr, buffer, count >> 2);
++ break;
++ default:
++ SSB_WARN_ON(1);
++ }
++}
++#endif /* CONFIG_SSB_BLOCKIO */
++
+ /* Not "static", as it's used in main.c */
+ const struct ssb_bus_ops ssb_pci_ops = {
++ .read8 = ssb_pci_read8,
+ .read16 = ssb_pci_read16,
+ .read32 = ssb_pci_read32,
++ .write8 = ssb_pci_write8,
+ .write16 = ssb_pci_write16,
+ .write32 = ssb_pci_write32,
++#ifdef CONFIG_SSB_BLOCKIO
++ .block_read = ssb_pci_block_read,
++ .block_write = ssb_pci_block_write,
++#endif
+ };
+
+-static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len, u16 size)
+-{
+- int i, pos = 0;
+-
+- for (i = 0; i < size; i++)
+- pos += snprintf(buf + pos, buf_len - pos - 1,
+- "%04X", swab16(sprom[i]) & 0xFFFF);
+- pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
+-
+- return pos + 1;
+-}
+-
+-static int hex2sprom(u16 *sprom, const char *dump, size_t len, u16 size)
+-{
+- char tmp[5] = { 0 };
+- int cnt = 0;
+- unsigned long parsed;
+-
+- if (len < size * 2)
+- return -EINVAL;
+-
+- while (cnt < size) {
+- memcpy(tmp, dump, 4);
+- dump += 4;
+- parsed = simple_strtoul(tmp, NULL, 16);
+- sprom[cnt++] = swab16((u16)parsed);
+- }
+-
+- return 0;
+-}
+-
+ static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
+ struct device_attribute *attr,
+ char *buf)
+ {
+ struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
+ struct ssb_bus *bus;
+- u16 *sprom;
+- int err = -ENODEV;
+- ssize_t count = 0;
+
+ bus = ssb_pci_dev_to_bus(pdev);
+ if (!bus)
+- goto out;
+- err = -ENOMEM;
+- sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
+- if (!sprom)
+- goto out;
++ return -ENODEV;
+
+- /* Use interruptible locking, as the SPROM write might
+- * be holding the lock for several seconds. So allow userspace
+- * to cancel operation. */
+- err = -ERESTARTSYS;
+- if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
+- goto out_kfree;
+- sprom_do_read(bus, sprom);
+- mutex_unlock(&bus->pci_sprom_mutex);
+-
+- count = sprom2hex(sprom, buf, PAGE_SIZE, bus->sprom_size);
+- err = 0;
+-
+-out_kfree:
+- kfree(sprom);
+-out:
+- return err ? err : count;
++ return ssb_attr_sprom_show(bus, buf, sprom_do_read);
+ }
+
+ static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
+@@ -705,55 +757,13 @@ static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
+ {
+ struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
+ struct ssb_bus *bus;
+- u16 *sprom;
+- int res = 0, err = -ENODEV;
+
+ bus = ssb_pci_dev_to_bus(pdev);
+ if (!bus)
+- goto out;
+- err = -ENOMEM;
+- sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
+- if (!sprom)
+- goto out;
+- err = hex2sprom(sprom, buf, count, bus->sprom_size);
+- if (err) {
+- err = -EINVAL;
+- goto out_kfree;
+- }
+- err = sprom_check_crc(sprom, bus->sprom_size);
+- if (err) {
+- err = -EINVAL;
+- goto out_kfree;
+- }
++ return -ENODEV;
+
+- /* Use interruptible locking, as the SPROM write might
+- * be holding the lock for several seconds. So allow userspace
+- * to cancel operation. */
+- err = -ERESTARTSYS;
+- if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
+- goto out_kfree;
+- err = ssb_devices_freeze(bus);
+- if (err == -EOPNOTSUPP) {
+- ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze devices. "
+- "No suspend support. Is CONFIG_PM enabled?\n");
+- goto out_unlock;
+- }
+- if (err) {
+- ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n");
+- goto out_unlock;
+- }
+- res = sprom_do_write(bus, sprom);
+- err = ssb_devices_thaw(bus);
+- if (err)
+- ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n");
+-out_unlock:
+- mutex_unlock(&bus->pci_sprom_mutex);
+-out_kfree:
+- kfree(sprom);
+-out:
+- if (res)
+- return res;
+- return err ? err : count;
++ return ssb_attr_sprom_store(bus, buf, count,
++ sprom_check_crc, sprom_do_write);
+ }
+
+ static DEVICE_ATTR(ssb_sprom, 0600,
+@@ -780,7 +790,7 @@ int ssb_pci_init(struct ssb_bus *bus)
+ return 0;
+
+ pdev = bus->host_pci;
+- mutex_init(&bus->pci_sprom_mutex);
++ mutex_init(&bus->sprom_mutex);
+ err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
+ if (err)
+ goto out;
+diff --git a/drivers/ssb/pcihost_wrapper.c b/drivers/ssb/pcihost_wrapper.c
+index 82a10ab..e82db4a 100644
+--- a/drivers/ssb/pcihost_wrapper.c
++++ b/drivers/ssb/pcihost_wrapper.c
+@@ -18,6 +18,12 @@
+ #ifdef CONFIG_PM
+ static int ssb_pcihost_suspend(struct pci_dev *dev, pm_message_t state)
+ {
++ struct ssb_bus *ssb = pci_get_drvdata(dev);
++ int err;
++
++ err = ssb_bus_suspend(ssb);
++ if (err)
++ return err;
+ pci_save_state(dev);
+ pci_disable_device(dev);
+ pci_set_power_state(dev, pci_choose_state(dev, state));
+@@ -27,6 +33,7 @@ static int ssb_pcihost_suspend(struct pci_dev *dev, pm_message_t state)
+
+ static int ssb_pcihost_resume(struct pci_dev *dev)
+ {
++ struct ssb_bus *ssb = pci_get_drvdata(dev);
+ int err;
+
+ pci_set_power_state(dev, 0);
+@@ -34,6 +41,9 @@ static int ssb_pcihost_resume(struct pci_dev *dev)
+ if (err)
+ return err;
+ pci_restore_state(dev);
++ err = ssb_bus_resume(ssb);
++ if (err)
++ return err;
+
+ return 0;
+ }
+diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c
+index 46816cd..24c2a46 100644
+--- a/drivers/ssb/pcmcia.c
++++ b/drivers/ssb/pcmcia.c
+@@ -3,7 +3,7 @@
+ * PCMCIA-Hostbus related functions
+ *
+ * Copyright 2006 Johannes Berg <johannes at sipsolutions.net>
+- * Copyright 2007 Michael Buesch <mb at bu3sch.de>
++ * Copyright 2007-2008 Michael Buesch <mb at bu3sch.de>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+@@ -11,6 +11,7 @@
+ #include <linux/ssb/ssb.h>
+ #include <linux/delay.h>
+ #include <linux/io.h>
++#include <linux/etherdevice.h>
+
+ #include <pcmcia/cs_types.h>
+ #include <pcmcia/cs.h>
+@@ -26,59 +27,127 @@
+ #define SSB_VERBOSE_PCMCIACORESWITCH_DEBUG 0
+
+
++/* PCMCIA configuration registers */
++#define SSB_PCMCIA_ADDRESS0 0x2E
++#define SSB_PCMCIA_ADDRESS1 0x30
++#define SSB_PCMCIA_ADDRESS2 0x32
++#define SSB_PCMCIA_MEMSEG 0x34
++#define SSB_PCMCIA_SPROMCTL 0x36
++#define SSB_PCMCIA_SPROMCTL_IDLE 0
++#define SSB_PCMCIA_SPROMCTL_WRITE 1
++#define SSB_PCMCIA_SPROMCTL_READ 2
++#define SSB_PCMCIA_SPROMCTL_WRITEEN 4
++#define SSB_PCMCIA_SPROMCTL_WRITEDIS 7
++#define SSB_PCMCIA_SPROMCTL_DONE 8
++#define SSB_PCMCIA_SPROM_DATALO 0x38
++#define SSB_PCMCIA_SPROM_DATAHI 0x3A
++#define SSB_PCMCIA_SPROM_ADDRLO 0x3C
++#define SSB_PCMCIA_SPROM_ADDRHI 0x3E
++
++/* Hardware invariants CIS tuples */
++#define SSB_PCMCIA_CIS 0x80
++#define SSB_PCMCIA_CIS_ID 0x01
++#define SSB_PCMCIA_CIS_BOARDREV 0x02
++#define SSB_PCMCIA_CIS_PA 0x03
++#define SSB_PCMCIA_CIS_PA_PA0B0_LO 0
++#define SSB_PCMCIA_CIS_PA_PA0B0_HI 1
++#define SSB_PCMCIA_CIS_PA_PA0B1_LO 2
++#define SSB_PCMCIA_CIS_PA_PA0B1_HI 3
++#define SSB_PCMCIA_CIS_PA_PA0B2_LO 4
++#define SSB_PCMCIA_CIS_PA_PA0B2_HI 5
++#define SSB_PCMCIA_CIS_PA_ITSSI 6
++#define SSB_PCMCIA_CIS_PA_MAXPOW 7
++#define SSB_PCMCIA_CIS_OEMNAME 0x04
++#define SSB_PCMCIA_CIS_CCODE 0x05
++#define SSB_PCMCIA_CIS_ANTENNA 0x06
++#define SSB_PCMCIA_CIS_ANTGAIN 0x07
++#define SSB_PCMCIA_CIS_BFLAGS 0x08
++#define SSB_PCMCIA_CIS_LEDS 0x09
++
++/* PCMCIA SPROM size. */
++#define SSB_PCMCIA_SPROM_SIZE 256
++#define SSB_PCMCIA_SPROM_SIZE_BYTES (SSB_PCMCIA_SPROM_SIZE * sizeof(u16))
++
++
++/* Write to a PCMCIA configuration register. */
++static int ssb_pcmcia_cfg_write(struct ssb_bus *bus, u8 offset, u8 value)
++{
++ conf_reg_t reg;
++ int res;
++
++ memset(®, 0, sizeof(reg));
++ reg.Offset = offset;
++ reg.Action = CS_WRITE;
++ reg.Value = value;
++ res = pcmcia_access_configuration_register(bus->host_pcmcia, ®);
++ if (unlikely(res != CS_SUCCESS))
++ return -EBUSY;
++
++ return 0;
++}
++
++/* Read from a PCMCIA configuration register. */
++static int ssb_pcmcia_cfg_read(struct ssb_bus *bus, u8 offset, u8 *value)
++{
++ conf_reg_t reg;
++ int res;
++
++ memset(®, 0, sizeof(reg));
++ reg.Offset = offset;
++ reg.Action = CS_READ;
++ res = pcmcia_access_configuration_register(bus->host_pcmcia, ®);
++ if (unlikely(res != CS_SUCCESS))
++ return -EBUSY;
++ *value = reg.Value;
++
++ return 0;
++}
++
+ int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
+ u8 coreidx)
+ {
+- struct pcmcia_device *pdev = bus->host_pcmcia;
+ int err;
+ int attempts = 0;
+ u32 cur_core;
+- conf_reg_t reg;
+ u32 addr;
+ u32 read_addr;
++ u8 val;
+
+ addr = (coreidx * SSB_CORE_SIZE) + SSB_ENUM_BASE;
+ while (1) {
+- reg.Action = CS_WRITE;
+- reg.Offset = 0x2E;
+- reg.Value = (addr & 0x0000F000) >> 12;
+- err = pcmcia_access_configuration_register(pdev, ®);
+- if (err != CS_SUCCESS)
++ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_ADDRESS0,
++ (addr & 0x0000F000) >> 12);
++ if (err)
+ goto error;
+- reg.Offset = 0x30;
+- reg.Value = (addr & 0x00FF0000) >> 16;
+- err = pcmcia_access_configuration_register(pdev, ®);
+- if (err != CS_SUCCESS)
++ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_ADDRESS1,
++ (addr & 0x00FF0000) >> 16);
++ if (err)
+ goto error;
+- reg.Offset = 0x32;
+- reg.Value = (addr & 0xFF000000) >> 24;
+- err = pcmcia_access_configuration_register(pdev, ®);
+- if (err != CS_SUCCESS)
++ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_ADDRESS2,
++ (addr & 0xFF000000) >> 24);
++ if (err)
+ goto error;
+
+ read_addr = 0;
+
+- reg.Action = CS_READ;
+- reg.Offset = 0x2E;
+- err = pcmcia_access_configuration_register(pdev, ®);
+- if (err != CS_SUCCESS)
++ err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_ADDRESS0, &val);
++ if (err)
+ goto error;
+- read_addr |= ((u32)(reg.Value & 0x0F)) << 12;
+- reg.Offset = 0x30;
+- err = pcmcia_access_configuration_register(pdev, ®);
+- if (err != CS_SUCCESS)
++ read_addr |= ((u32)(val & 0x0F)) << 12;
++ err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_ADDRESS1, &val);
++ if (err)
+ goto error;
+- read_addr |= ((u32)reg.Value) << 16;
+- reg.Offset = 0x32;
+- err = pcmcia_access_configuration_register(pdev, ®);
+- if (err != CS_SUCCESS)
++ read_addr |= ((u32)val) << 16;
++ err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_ADDRESS2, &val);
++ if (err)
+ goto error;
+- read_addr |= ((u32)reg.Value) << 24;
++ read_addr |= ((u32)val) << 24;
+
+ cur_core = (read_addr - SSB_ENUM_BASE) / SSB_CORE_SIZE;
+ if (cur_core == coreidx)
+ break;
+
++ err = -ETIMEDOUT;
+ if (attempts++ > SSB_BAR0_MAX_RETRIES)
+ goto error;
+ udelay(10);
+@@ -87,7 +156,7 @@ int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
+ return 0;
+ error:
+ ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx);
+- return -ENODEV;
++ return err;
+ }
+
+ int ssb_pcmcia_switch_core(struct ssb_bus *bus,
+@@ -112,27 +181,21 @@ int ssb_pcmcia_switch_core(struct ssb_bus *bus,
+ int ssb_pcmcia_switch_segment(struct ssb_bus *bus, u8 seg)
+ {
+ int attempts = 0;
+- conf_reg_t reg;
+- int res;
++ int err;
++ u8 val;
+
+ SSB_WARN_ON((seg != 0) && (seg != 1));
+- reg.Offset = 0x34;
+- reg.Function = 0;
+ while (1) {
+- reg.Action = CS_WRITE;
+- reg.Value = seg;
+- res = pcmcia_access_configuration_register(bus->host_pcmcia, ®);
+- if (unlikely(res != CS_SUCCESS))
++ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_MEMSEG, seg);
++ if (err)
+ goto error;
+- reg.Value = 0xFF;
+- reg.Action = CS_READ;
+- res = pcmcia_access_configuration_register(bus->host_pcmcia, ®);
+- if (unlikely(res != CS_SUCCESS))
++ err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_MEMSEG, &val);
++ if (err)
+ goto error;
+-
+- if (reg.Value == seg)
++ if (val == seg)
+ break;
+
++ err = -ETIMEDOUT;
+ if (unlikely(attempts++ > SSB_BAR0_MAX_RETRIES))
+ goto error;
+ udelay(10);
+@@ -142,7 +205,7 @@ int ssb_pcmcia_switch_segment(struct ssb_bus *bus, u8 seg)
+ return 0;
+ error:
+ ssb_printk(KERN_ERR PFX "Failed to switch pcmcia segment\n");
+- return -ENODEV;
++ return err;
+ }
+
+ static int select_core_and_segment(struct ssb_device *dev,
+@@ -172,6 +235,22 @@ static int select_core_and_segment(struct ssb_device *dev,
+ return 0;
+ }
+
++static u8 ssb_pcmcia_read8(struct ssb_device *dev, u16 offset)
++{
++ struct ssb_bus *bus = dev->bus;
++ unsigned long flags;
++ int err;
++ u8 value = 0xFF;
++
++ spin_lock_irqsave(&bus->bar_lock, flags);
++ err = select_core_and_segment(dev, &offset);
++ if (likely(!err))
++ value = readb(bus->mmio + offset);
++ spin_unlock_irqrestore(&bus->bar_lock, flags);
++
++ return value;
++}
++
+ static u16 ssb_pcmcia_read16(struct ssb_device *dev, u16 offset)
+ {
+ struct ssb_bus *bus = dev->bus;
+@@ -206,6 +285,78 @@ static u32 ssb_pcmcia_read32(struct ssb_device *dev, u16 offset)
+ return (lo | (hi << 16));
+ }
+
++#ifdef CONFIG_SSB_BLOCKIO
++static void ssb_pcmcia_block_read(struct ssb_device *dev, void *buffer,
++ size_t count, u16 offset, u8 reg_width)
++{
++ struct ssb_bus *bus = dev->bus;
++ unsigned long flags;
++ void __iomem *addr = bus->mmio + offset;
++ int err;
++
++ spin_lock_irqsave(&bus->bar_lock, flags);
++ err = select_core_and_segment(dev, &offset);
++ if (unlikely(err)) {
++ memset(buffer, 0xFF, count);
++ goto unlock;
++ }
++ switch (reg_width) {
++ case sizeof(u8): {
++ u8 *buf = buffer;
++
++ while (count) {
++ *buf = __raw_readb(addr);
++ buf++;
++ count--;
++ }
++ break;
++ }
++ case sizeof(u16): {
++ __le16 *buf = buffer;
++
++ SSB_WARN_ON(count & 1);
++ while (count) {
++ *buf = (__force __le16)__raw_readw(addr);
++ buf++;
++ count -= 2;
++ }
++ break;
++ }
++ case sizeof(u32): {
++ __le16 *buf = buffer;
++
++ SSB_WARN_ON(count & 3);
++ while (count) {
++ *buf = (__force __le16)__raw_readw(addr);
++ buf++;
++ *buf = (__force __le16)__raw_readw(addr + 2);
++ buf++;
++ count -= 4;
++ }
++ break;
++ }
++ default:
++ SSB_WARN_ON(1);
++ }
++unlock:
++ spin_unlock_irqrestore(&bus->bar_lock, flags);
++}
++#endif /* CONFIG_SSB_BLOCKIO */
++
++static void ssb_pcmcia_write8(struct ssb_device *dev, u16 offset, u8 value)
++{
++ struct ssb_bus *bus = dev->bus;
++ unsigned long flags;
++ int err;
++
++ spin_lock_irqsave(&bus->bar_lock, flags);
++ err = select_core_and_segment(dev, &offset);
++ if (likely(!err))
++ writeb(value, bus->mmio + offset);
++ mmiowb();
++ spin_unlock_irqrestore(&bus->bar_lock, flags);
++}
++
+ static void ssb_pcmcia_write16(struct ssb_device *dev, u16 offset, u16 value)
+ {
+ struct ssb_bus *bus = dev->bus;
+@@ -236,26 +387,425 @@ static void ssb_pcmcia_write32(struct ssb_device *dev, u16 offset, u32 value)
+ spin_unlock_irqrestore(&bus->bar_lock, flags);
+ }
+
++#ifdef CONFIG_SSB_BLOCKIO
++static void ssb_pcmcia_block_write(struct ssb_device *dev, const void *buffer,
++ size_t count, u16 offset, u8 reg_width)
++{
++ struct ssb_bus *bus = dev->bus;
++ unsigned long flags;
++ void __iomem *addr = bus->mmio + offset;
++ int err;
++
++ spin_lock_irqsave(&bus->bar_lock, flags);
++ err = select_core_and_segment(dev, &offset);
++ if (unlikely(err))
++ goto unlock;
++ switch (reg_width) {
++ case sizeof(u8): {
++ const u8 *buf = buffer;
++
++ while (count) {
++ __raw_writeb(*buf, addr);
++ buf++;
++ count--;
++ }
++ break;
++ }
++ case sizeof(u16): {
++ const __le16 *buf = buffer;
++
++ SSB_WARN_ON(count & 1);
++ while (count) {
++ __raw_writew((__force u16)(*buf), addr);
++ buf++;
++ count -= 2;
++ }
++ break;
++ }
++ case sizeof(u32): {
++ const __le16 *buf = buffer;
++
++ SSB_WARN_ON(count & 3);
++ while (count) {
++ __raw_writew((__force u16)(*buf), addr);
++ buf++;
++ __raw_writew((__force u16)(*buf), addr + 2);
++ buf++;
++ count -= 4;
++ }
++ break;
++ }
++ default:
++ SSB_WARN_ON(1);
++ }
++unlock:
++ mmiowb();
++ spin_unlock_irqrestore(&bus->bar_lock, flags);
++}
++#endif /* CONFIG_SSB_BLOCKIO */
++
+ /* Not "static", as it's used in main.c */
+ const struct ssb_bus_ops ssb_pcmcia_ops = {
++ .read8 = ssb_pcmcia_read8,
+ .read16 = ssb_pcmcia_read16,
+ .read32 = ssb_pcmcia_read32,
++ .write8 = ssb_pcmcia_write8,
+ .write16 = ssb_pcmcia_write16,
+ .write32 = ssb_pcmcia_write32,
++#ifdef CONFIG_SSB_BLOCKIO
++ .block_read = ssb_pcmcia_block_read,
++ .block_write = ssb_pcmcia_block_write,
++#endif
+ };
+
+-#include <linux/etherdevice.h>
++static int ssb_pcmcia_sprom_command(struct ssb_bus *bus, u8 command)
++{
++ unsigned int i;
++ int err;
++ u8 value;
++
++ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROMCTL, command);
++ if (err)
++ return err;
++ for (i = 0; i < 1000; i++) {
++ err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROMCTL, &value);
++ if (err)
++ return err;
++ if (value & SSB_PCMCIA_SPROMCTL_DONE)
++ return 0;
++ udelay(10);
++ }
++
++ return -ETIMEDOUT;
++}
++
++/* offset is the 16bit word offset */
++static int ssb_pcmcia_sprom_read(struct ssb_bus *bus, u16 offset, u16 *value)
++{
++ int err;
++ u8 lo, hi;
++
++ offset *= 2; /* Make byte offset */
++
++ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRLO,
++ (offset & 0x00FF));
++ if (err)
++ return err;
++ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRHI,
++ (offset & 0xFF00) >> 8);
++ if (err)
++ return err;
++ err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_READ);
++ if (err)
++ return err;
++ err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROM_DATALO, &lo);
++ if (err)
++ return err;
++ err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROM_DATAHI, &hi);
++ if (err)
++ return err;
++ *value = (lo | (((u16)hi) << 8));
++
++ return 0;
++}
++
++/* offset is the 16bit word offset */
++static int ssb_pcmcia_sprom_write(struct ssb_bus *bus, u16 offset, u16 value)
++{
++ int err;
++
++ offset *= 2; /* Make byte offset */
++
++ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRLO,
++ (offset & 0x00FF));
++ if (err)
++ return err;
++ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRHI,
++ (offset & 0xFF00) >> 8);
++ if (err)
++ return err;
++ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_DATALO,
++ (value & 0x00FF));
++ if (err)
++ return err;
++ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_DATAHI,
++ (value & 0xFF00) >> 8);
++ if (err)
++ return err;
++ err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITE);
++ if (err)
++ return err;
++ msleep(20);
++
++ return 0;
++}
++
++/* Read the SPROM image. bufsize is in 16bit words. */
++static int ssb_pcmcia_sprom_read_all(struct ssb_bus *bus, u16 *sprom)
++{
++ int err, i;
++
++ for (i = 0; i < SSB_PCMCIA_SPROM_SIZE; i++) {
++ err = ssb_pcmcia_sprom_read(bus, i, &sprom[i]);
++ if (err)
++ return err;
++ }
++
++ return 0;
++}
++
++/* Write the SPROM image. size is in 16bit words. */
++static int ssb_pcmcia_sprom_write_all(struct ssb_bus *bus, const u16 *sprom)
++{
++ int i, err;
++ bool failed = 0;
++ size_t size = SSB_PCMCIA_SPROM_SIZE;
++
++ ssb_printk(KERN_NOTICE PFX
++ "Writing SPROM. Do NOT turn off the power! "
++ "Please stand by...\n");
++ err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEEN);
++ if (err) {
++ ssb_printk(KERN_NOTICE PFX
++ "Could not enable SPROM write access.\n");
++ return -EBUSY;
++ }
++ ssb_printk(KERN_NOTICE PFX "[ 0%%");
++ msleep(500);
++ for (i = 0; i < size; i++) {
++ if (i == size / 4)
++ ssb_printk("25%%");
++ else if (i == size / 2)
++ ssb_printk("50%%");
++ else if (i == (size * 3) / 4)
++ ssb_printk("75%%");
++ else if (i % 2)
++ ssb_printk(".");
++ err = ssb_pcmcia_sprom_write(bus, i, sprom[i]);
++ if (err) {
++ ssb_printk("\n" KERN_NOTICE PFX
++ "Failed to write to SPROM.\n");
++ failed = 1;
++ break;
++ }
++ }
++ err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS);
++ if (err) {
++ ssb_printk("\n" KERN_NOTICE PFX
++ "Could not disable SPROM write access.\n");
++ failed = 1;
++ }
++ msleep(500);
++ if (!failed) {
++ ssb_printk("100%% ]\n");
++ ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
++ }
++
++ return failed ? -EBUSY : 0;
++}
++
++static int ssb_pcmcia_sprom_check_crc(const u16 *sprom, size_t size)
++{
++ //TODO
++ return 0;
++}
++
++#define GOTO_ERROR_ON(condition, description) do { \
++ if (unlikely(condition)) { \
++ error_description = description; \
++ goto error; \
++ } \
++ } while (0)
++
+ int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
+ struct ssb_init_invariants *iv)
+ {
+- //TODO
+- random_ether_addr(iv->sprom.il0mac);
++ tuple_t tuple;
++ int res;
++ unsigned char buf[32];
++ struct ssb_sprom *sprom = &iv->sprom;
++ struct ssb_boardinfo *bi = &iv->boardinfo;
++ const char *error_description;
++
++ memset(sprom, 0xFF, sizeof(*sprom));
++ sprom->revision = 1;
++ sprom->boardflags_lo = 0;
++ sprom->boardflags_hi = 0;
++
++ /* First fetch the MAC address. */
++ memset(&tuple, 0, sizeof(tuple));
++ tuple.DesiredTuple = CISTPL_FUNCE;
++ tuple.TupleData = buf;
++ tuple.TupleDataMax = sizeof(buf);
++ res = pcmcia_get_first_tuple(bus->host_pcmcia, &tuple);
++ GOTO_ERROR_ON(res != CS_SUCCESS, "MAC first tpl");
++ res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
++ GOTO_ERROR_ON(res != CS_SUCCESS, "MAC first tpl data");
++ while (1) {
++ GOTO_ERROR_ON(tuple.TupleDataLen < 1, "MAC tpl < 1");
++ if (tuple.TupleData[0] == CISTPL_FUNCE_LAN_NODE_ID)
++ break;
++ res = pcmcia_get_next_tuple(bus->host_pcmcia, &tuple);
++ GOTO_ERROR_ON(res != CS_SUCCESS, "MAC next tpl");
++ res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
++ GOTO_ERROR_ON(res != CS_SUCCESS, "MAC next tpl data");
++ }
++ GOTO_ERROR_ON(tuple.TupleDataLen != ETH_ALEN + 2, "MAC tpl size");
++ memcpy(sprom->il0mac, &tuple.TupleData[2], ETH_ALEN);
++
++ /* Fetch the vendor specific tuples. */
++ memset(&tuple, 0, sizeof(tuple));
++ tuple.DesiredTuple = SSB_PCMCIA_CIS;
++ tuple.TupleData = buf;
++ tuple.TupleDataMax = sizeof(buf);
++ res = pcmcia_get_first_tuple(bus->host_pcmcia, &tuple);
++ GOTO_ERROR_ON(res != CS_SUCCESS, "VEN first tpl");
++ res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
++ GOTO_ERROR_ON(res != CS_SUCCESS, "VEN first tpl data");
++ while (1) {
++ GOTO_ERROR_ON(tuple.TupleDataLen < 1, "VEN tpl < 1");
++ switch (tuple.TupleData[0]) {
++ case SSB_PCMCIA_CIS_ID:
++ GOTO_ERROR_ON((tuple.TupleDataLen != 5) &&
++ (tuple.TupleDataLen != 7),
++ "id tpl size");
++ bi->vendor = tuple.TupleData[1] |
++ ((u16)tuple.TupleData[2] << 8);
++ break;
++ case SSB_PCMCIA_CIS_BOARDREV:
++ GOTO_ERROR_ON(tuple.TupleDataLen != 2,
++ "boardrev tpl size");
++ sprom->board_rev = tuple.TupleData[1];
++ break;
++ case SSB_PCMCIA_CIS_PA:
++ GOTO_ERROR_ON(tuple.TupleDataLen != 9,
++ "pa tpl size");
++ sprom->pa0b0 = tuple.TupleData[1] |
++ ((u16)tuple.TupleData[2] << 8);
++ sprom->pa0b1 = tuple.TupleData[3] |
++ ((u16)tuple.TupleData[4] << 8);
++ sprom->pa0b2 = tuple.TupleData[5] |
++ ((u16)tuple.TupleData[6] << 8);
++ sprom->itssi_a = tuple.TupleData[7];
++ sprom->itssi_bg = tuple.TupleData[7];
++ sprom->maxpwr_a = tuple.TupleData[8];
++ sprom->maxpwr_bg = tuple.TupleData[8];
++ break;
++ case SSB_PCMCIA_CIS_OEMNAME:
++ /* We ignore this. */
++ break;
++ case SSB_PCMCIA_CIS_CCODE:
++ GOTO_ERROR_ON(tuple.TupleDataLen != 2,
++ "ccode tpl size");
++ sprom->country_code = tuple.TupleData[1];
++ break;
++ case SSB_PCMCIA_CIS_ANTENNA:
++ GOTO_ERROR_ON(tuple.TupleDataLen != 2,
++ "ant tpl size");
++ sprom->ant_available_a = tuple.TupleData[1];
++ sprom->ant_available_bg = tuple.TupleData[1];
++ break;
++ case SSB_PCMCIA_CIS_ANTGAIN:
++ GOTO_ERROR_ON(tuple.TupleDataLen != 2,
++ "antg tpl size");
++ sprom->antenna_gain.ghz24.a0 = tuple.TupleData[1];
++ sprom->antenna_gain.ghz24.a1 = tuple.TupleData[1];
++ sprom->antenna_gain.ghz24.a2 = tuple.TupleData[1];
++ sprom->antenna_gain.ghz24.a3 = tuple.TupleData[1];
++ sprom->antenna_gain.ghz5.a0 = tuple.TupleData[1];
++ sprom->antenna_gain.ghz5.a1 = tuple.TupleData[1];
++ sprom->antenna_gain.ghz5.a2 = tuple.TupleData[1];
++ sprom->antenna_gain.ghz5.a3 = tuple.TupleData[1];
++ break;
++ case SSB_PCMCIA_CIS_BFLAGS:
++ GOTO_ERROR_ON(tuple.TupleDataLen != 3,
++ "bfl tpl size");
++ sprom->boardflags_lo = tuple.TupleData[1] |
++ ((u16)tuple.TupleData[2] << 8);
++ break;
++ case SSB_PCMCIA_CIS_LEDS:
++ GOTO_ERROR_ON(tuple.TupleDataLen != 5,
++ "leds tpl size");
++ sprom->gpio0 = tuple.TupleData[1];
++ sprom->gpio1 = tuple.TupleData[2];
++ sprom->gpio2 = tuple.TupleData[3];
++ sprom->gpio3 = tuple.TupleData[4];
++ break;
++ }
++ res = pcmcia_get_next_tuple(bus->host_pcmcia, &tuple);
++ if (res == CS_NO_MORE_ITEMS)
++ break;
++ GOTO_ERROR_ON(res != CS_SUCCESS, "VEN next tpl");
++ res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
++ GOTO_ERROR_ON(res != CS_SUCCESS, "VEN next tpl data");
++ }
++
+ return 0;
++error:
++ ssb_printk(KERN_ERR PFX
++ "PCMCIA: Failed to fetch device invariants: %s\n",
++ error_description);
++ return -ENODEV;
+ }
+
+-int ssb_pcmcia_init(struct ssb_bus *bus)
++static ssize_t ssb_pcmcia_attr_sprom_show(struct device *pcmciadev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct pcmcia_device *pdev =
++ container_of(pcmciadev, struct pcmcia_device, dev);
++ struct ssb_bus *bus;
++
++ bus = ssb_pcmcia_dev_to_bus(pdev);
++ if (!bus)
++ return -ENODEV;
++
++ return ssb_attr_sprom_show(bus, buf,
++ ssb_pcmcia_sprom_read_all);
++}
++
++static ssize_t ssb_pcmcia_attr_sprom_store(struct device *pcmciadev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct pcmcia_device *pdev =
++ container_of(pcmciadev, struct pcmcia_device, dev);
++ struct ssb_bus *bus;
++
++ bus = ssb_pcmcia_dev_to_bus(pdev);
++ if (!bus)
++ return -ENODEV;
++
++ return ssb_attr_sprom_store(bus, buf, count,
++ ssb_pcmcia_sprom_check_crc,
++ ssb_pcmcia_sprom_write_all);
++}
++
++static DEVICE_ATTR(ssb_sprom, 0600,
++ ssb_pcmcia_attr_sprom_show,
++ ssb_pcmcia_attr_sprom_store);
++
++static int ssb_pcmcia_cor_setup(struct ssb_bus *bus, u8 cor)
++{
++ u8 val;
++ int err;
++
++ err = ssb_pcmcia_cfg_read(bus, cor, &val);
++ if (err)
++ return err;
++ val &= ~COR_SOFT_RESET;
++ val |= COR_FUNC_ENA | COR_IREQ_ENA | COR_LEVEL_REQ;
++ err = ssb_pcmcia_cfg_write(bus, cor, val);
++ if (err)
++ return err;
++ msleep(40);
++
++ return 0;
++}
++
++/* Initialize the PCMCIA hardware. This is called on Init and Resume. */
++int ssb_pcmcia_hardware_setup(struct ssb_bus *bus)
+ {
+- conf_reg_t reg;
+ int err;
+
+ if (bus->bustype != SSB_BUSTYPE_PCMCIA)
+@@ -264,24 +814,45 @@ int ssb_pcmcia_init(struct ssb_bus *bus)
+ /* Switch segment to a known state and sync
+ * bus->mapped_pcmcia_seg with hardware state. */
+ ssb_pcmcia_switch_segment(bus, 0);
++ /* Init the COR register. */
++ err = ssb_pcmcia_cor_setup(bus, CISREG_COR);
++ if (err)
++ return err;
++ /* Some cards also need this register to get poked. */
++ err = ssb_pcmcia_cor_setup(bus, CISREG_COR + 0x80);
++ if (err)
++ return err;
+
+- /* Init IRQ routing */
+- reg.Action = CS_READ;
+- reg.Function = 0;
+- if (bus->chip_id == 0x4306)
+- reg.Offset = 0x00;
+- else
+- reg.Offset = 0x80;
+- err = pcmcia_access_configuration_register(bus->host_pcmcia, ®);
+- if (err != CS_SUCCESS)
++ return 0;
++}
++
++void ssb_pcmcia_exit(struct ssb_bus *bus)
++{
++ if (bus->bustype != SSB_BUSTYPE_PCMCIA)
++ return;
++
++ device_remove_file(&bus->host_pcmcia->dev, &dev_attr_ssb_sprom);
++}
++
++int ssb_pcmcia_init(struct ssb_bus *bus)
++{
++ int err;
++
++ if (bus->bustype != SSB_BUSTYPE_PCMCIA)
++ return 0;
++
++ err = ssb_pcmcia_hardware_setup(bus);
++ if (err)
+ goto error;
+- reg.Action = CS_WRITE;
+- reg.Value |= 0x04 | 0x01;
+- err = pcmcia_access_configuration_register(bus->host_pcmcia, ®);
+- if (err != CS_SUCCESS)
++
++ bus->sprom_size = SSB_PCMCIA_SPROM_SIZE;
++ mutex_init(&bus->sprom_mutex);
++ err = device_create_file(&bus->host_pcmcia->dev, &dev_attr_ssb_sprom);
++ if (err)
+ goto error;
+
+ return 0;
+ error:
+- return -ENODEV;
++ ssb_printk(KERN_ERR PFX "Failed to initialize PCMCIA host device\n");
++ return err;
+ }
+diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c
+new file mode 100644
+index 0000000..3668edb
+--- /dev/null
++++ b/drivers/ssb/sprom.c
+@@ -0,0 +1,133 @@
++/*
++ * Sonics Silicon Backplane
++ * Common SPROM support routines
++ *
++ * Copyright (C) 2005-2008 Michael Buesch <mb at bu3sch.de>
++ * Copyright (C) 2005 Martin Langer <martin-langer at gmx.de>
++ * Copyright (C) 2005 Stefano Brivio <st3 at riseup.net>
++ * Copyright (C) 2005 Danny van Dyk <kugelfang at gentoo.org>
++ * Copyright (C) 2005 Andreas Jaggi <andreas.jaggi at waterwave.ch>
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++
++#include "ssb_private.h"
++
++
++static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len,
++ size_t sprom_size_words)
++{
++ int i, pos = 0;
++
++ for (i = 0; i < sprom_size_words; i++)
++ pos += snprintf(buf + pos, buf_len - pos - 1,
++ "%04X", swab16(sprom[i]) & 0xFFFF);
++ pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
++
++ return pos + 1;
++}
++
++static int hex2sprom(u16 *sprom, const char *dump, size_t len,
++ size_t sprom_size_words)
++{
++ char tmp[5] = { 0 };
++ int cnt = 0;
++ unsigned long parsed;
++
++ if (len < sprom_size_words * 2)
++ return -EINVAL;
++
++ while (cnt < sprom_size_words) {
++ memcpy(tmp, dump, 4);
++ dump += 4;
++ parsed = simple_strtoul(tmp, NULL, 16);
++ sprom[cnt++] = swab16((u16)parsed);
++ }
++
++ return 0;
++}
++
++/* Common sprom device-attribute show-handler */
++ssize_t ssb_attr_sprom_show(struct ssb_bus *bus, char *buf,
++ int (*sprom_read)(struct ssb_bus *bus, u16 *sprom))
++{
++ u16 *sprom;
++ int err = -ENOMEM;
++ ssize_t count = 0;
++ size_t sprom_size_words = bus->sprom_size;
++
++ sprom = kcalloc(sprom_size_words, sizeof(u16), GFP_KERNEL);
++ if (!sprom)
++ goto out;
++
++ /* Use interruptible locking, as the SPROM write might
++ * be holding the lock for several seconds. So allow userspace
++ * to cancel operation. */
++ err = -ERESTARTSYS;
++ if (mutex_lock_interruptible(&bus->sprom_mutex))
++ goto out_kfree;
++ err = sprom_read(bus, sprom);
++ mutex_unlock(&bus->sprom_mutex);
++
++ if (!err)
++ count = sprom2hex(sprom, buf, PAGE_SIZE, sprom_size_words);
++
++out_kfree:
++ kfree(sprom);
++out:
++ return err ? err : count;
++}
++
++/* Common sprom device-attribute store-handler */
++ssize_t ssb_attr_sprom_store(struct ssb_bus *bus,
++ const char *buf, size_t count,
++ int (*sprom_check_crc)(const u16 *sprom, size_t size),
++ int (*sprom_write)(struct ssb_bus *bus, const u16 *sprom))
++{
++ u16 *sprom;
++ int res = 0, err = -ENOMEM;
++ size_t sprom_size_words = bus->sprom_size;
++
++ sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
++ if (!sprom)
++ goto out;
++ err = hex2sprom(sprom, buf, count, sprom_size_words);
++ if (err) {
++ err = -EINVAL;
++ goto out_kfree;
++ }
++ err = sprom_check_crc(sprom, sprom_size_words);
++ if (err) {
++ err = -EINVAL;
++ goto out_kfree;
++ }
++
++ /* Use interruptible locking, as the SPROM write might
++ * be holding the lock for several seconds. So allow userspace
++ * to cancel operation. */
++ err = -ERESTARTSYS;
++ if (mutex_lock_interruptible(&bus->sprom_mutex))
++ goto out_kfree;
++ err = ssb_devices_freeze(bus);
++ if (err == -EOPNOTSUPP) {
++ ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze devices. "
++ "No suspend support. Is CONFIG_PM enabled?\n");
++ goto out_unlock;
++ }
++ if (err) {
++ ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n");
++ goto out_unlock;
++ }
++ res = sprom_write(bus, sprom);
++ err = ssb_devices_thaw(bus);
++ if (err)
++ ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n");
++out_unlock:
++ mutex_unlock(&bus->sprom_mutex);
++out_kfree:
++ kfree(sprom);
++out:
++ if (res)
++ return res;
++ return err ? err : count;
++}
+diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h
+index 21eca2b..ebc32d8 100644
+--- a/drivers/ssb/ssb_private.h
++++ b/drivers/ssb/ssb_private.h
+@@ -81,6 +81,8 @@ extern int ssb_pcmcia_switch_segment(struct ssb_bus *bus,
+ u8 seg);
+ extern int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
+ struct ssb_init_invariants *iv);
++extern int ssb_pcmcia_hardware_setup(struct ssb_bus *bus);
++extern void ssb_pcmcia_exit(struct ssb_bus *bus);
+ extern int ssb_pcmcia_init(struct ssb_bus *bus);
+ extern const struct ssb_bus_ops ssb_pcmcia_ops;
+ #else /* CONFIG_SSB_PCMCIAHOST */
+@@ -99,6 +101,13 @@ static inline int ssb_pcmcia_switch_segment(struct ssb_bus *bus,
+ {
+ return 0;
+ }
++static inline int ssb_pcmcia_hardware_setup(struct ssb_bus *bus)
++{
++ return 0;
++}
++static inline void ssb_pcmcia_exit(struct ssb_bus *bus)
++{
++}
+ static inline int ssb_pcmcia_init(struct ssb_bus *bus)
+ {
+ return 0;
+@@ -113,11 +122,26 @@ extern int ssb_bus_scan(struct ssb_bus *bus,
+ extern void ssb_iounmap(struct ssb_bus *ssb);
+
+
++/* sprom.c */
++extern
++ssize_t ssb_attr_sprom_show(struct ssb_bus *bus, char *buf,
++ int (*sprom_read)(struct ssb_bus *bus, u16 *sprom));
++extern
++ssize_t ssb_attr_sprom_store(struct ssb_bus *bus,
++ const char *buf, size_t count,
++ int (*sprom_check_crc)(const u16 *sprom, size_t size),
++ int (*sprom_write)(struct ssb_bus *bus, const u16 *sprom));
++
++
+ /* core.c */
+ extern u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m);
+ extern int ssb_devices_freeze(struct ssb_bus *bus);
+ extern int ssb_devices_thaw(struct ssb_bus *bus);
+ extern struct ssb_bus *ssb_pci_dev_to_bus(struct pci_dev *pdev);
++int ssb_for_each_bus_call(unsigned long data,
++ int (*func)(struct ssb_bus *bus, unsigned long data));
++extern struct ssb_bus *ssb_pcmcia_dev_to_bus(struct pcmcia_device *pdev);
++
+
+ /* b43_pci_bridge.c */
+ #ifdef CONFIG_SSB_B43_PCI_BRIDGE
+diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
+index b778ed7..a4aaab9 100644
+--- a/drivers/uio/Kconfig
++++ b/drivers/uio/Kconfig
+@@ -1,8 +1,6 @@
+-menu "Userspace I/O"
+- depends on !S390
+-
+-config UIO
++menuconfig UIO
+ tristate "Userspace I/O drivers"
++ depends on !S390
+ default n
+ help
+ Enable this to allow the userspace driver core code to be
+@@ -13,6 +11,8 @@ config UIO
+
+ If you don't know what to do here, say N.
+
++if UIO
++
+ config UIO_CIF
+ tristate "generic Hilscher CIF Card driver"
+ depends on UIO && PCI
+@@ -26,4 +26,17 @@ config UIO_CIF
+ To compile this driver as a module, choose M here: the module
+ will be called uio_cif.
+
+-endmenu
++config UIO_SMX
++ tristate "SMX cryptengine UIO interface"
++ depends on UIO
++ default n
++ help
++ Userspace IO interface to the Cryptography engine found on the
++ Nias Digital SMX boards. These will be available from Q4 2008
++ from http://www.niasdigital.com. The userspace part of this
++ driver will be released under the GPL at the same time as the
++ hardware and will be able to be downloaded from the same site.
++
++ If you compile this as a module, it will be called uio_smx.
++
++endif
+diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
+index 7fecfb4..18c4566 100644
+--- a/drivers/uio/Makefile
++++ b/drivers/uio/Makefile
+@@ -1,2 +1,3 @@
+ obj-$(CONFIG_UIO) += uio.o
+ obj-$(CONFIG_UIO_CIF) += uio_cif.o
++obj-$(CONFIG_UIO_SMX) += uio_smx.o
+diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
+index 1175908..55cc7b8 100644
+--- a/drivers/uio/uio.c
++++ b/drivers/uio/uio.c
+@@ -301,23 +301,33 @@ static int uio_open(struct inode *inode, struct file *filep)
+ if (!idev)
+ return -ENODEV;
+
++ if (!try_module_get(idev->owner))
++ return -ENODEV;
++
+ listener = kmalloc(sizeof(*listener), GFP_KERNEL);
+- if (!listener)
+- return -ENOMEM;
++ if (!listener) {
++ ret = -ENOMEM;
++ goto err_alloc_listener;
++ }
+
+ listener->dev = idev;
+ listener->event_count = atomic_read(&idev->event);
+ filep->private_data = listener;
+
+ if (idev->info->open) {
+- if (!try_module_get(idev->owner))
+- return -ENODEV;
+ ret = idev->info->open(idev->info, inode);
+- module_put(idev->owner);
++ if (ret)
++ goto err_infoopen;
+ }
+
+- if (ret)
+- kfree(listener);
++ return 0;
++
++err_infoopen:
++
++ kfree(listener);
++err_alloc_listener:
++
++ module_put(idev->owner);
+
+ return ret;
+ }
+@@ -336,12 +346,11 @@ static int uio_release(struct inode *inode, struct file *filep)
+ struct uio_listener *listener = filep->private_data;
+ struct uio_device *idev = listener->dev;
+
+- if (idev->info->release) {
+- if (!try_module_get(idev->owner))
+- return -ENODEV;
++ if (idev->info->release)
+ ret = idev->info->release(idev->info, inode);
+- module_put(idev->owner);
+- }
++
++ module_put(idev->owner);
++
+ if (filep->f_flags & FASYNC)
+ ret = uio_fasync(-1, filep, 0);
+ kfree(listener);
+@@ -510,10 +519,7 @@ static int uio_mmap(struct file *filep, struct vm_area_struct *vma)
+ return -EINVAL;
+
+ if (idev->info->mmap) {
+- if (!try_module_get(idev->owner))
+- return -ENODEV;
+ ret = idev->info->mmap(idev->info, vma);
+- module_put(idev->owner);
+ return ret;
+ }
+
+diff --git a/drivers/uio/uio_cif.c b/drivers/uio/uio_cif.c
+index 838bae4..5737606 100644
+--- a/drivers/uio/uio_cif.c
++++ b/drivers/uio/uio_cif.c
+@@ -15,10 +15,6 @@
+
+ #include <asm/io.h>
+
+-#ifndef PCI_DEVICE_ID_PLX_9030
+-#define PCI_DEVICE_ID_PLX_9030 0x9030
+-#endif
+-
+ #define PLX9030_INTCSR 0x4C
+ #define INTSCR_INT1_ENABLE 0x01
+ #define INTSCR_INT1_STATUS 0x04
+@@ -116,7 +112,7 @@ static void hilscher_pci_remove(struct pci_dev *dev)
+ kfree (info);
+ }
+
+-static struct pci_device_id hilscher_pci_ids[] = {
++static struct pci_device_id hilscher_pci_ids[] __devinitdata = {
+ {
+ .vendor = PCI_VENDOR_ID_PLX,
+ .device = PCI_DEVICE_ID_PLX_9030,
+diff --git a/drivers/uio/uio_smx.c b/drivers/uio/uio_smx.c
+new file mode 100644
+index 0000000..44054a6
+--- /dev/null
++++ b/drivers/uio/uio_smx.c
+@@ -0,0 +1,140 @@
++/*
++ * UIO SMX Cryptengine driver.
++ *
++ * (C) 2008 Nias Digital P/L <bn at niasdigital.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++
++#include <linux/device.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/uio_driver.h>
++#include <linux/io.h>
++
++#define DRV_NAME "smx-ce"
++#define DRV_VERSION "0.03"
++
++#define SMX_CSR 0x00000000
++#define SMX_EnD 0x00000001
++#define SMX_RUN 0x00000002
++#define SMX_DRDY 0x00000004
++#define SMX_ERR 0x00000008
++
++static irqreturn_t smx_handler(int irq, struct uio_info *dev_info)
++{
++ void __iomem *csr = dev_info->mem[0].internal_addr + SMX_CSR;
++
++ u32 status = ioread32(csr);
++
++ if (!(status & SMX_DRDY))
++ return IRQ_NONE;
++
++ /* Disable interrupt */
++ iowrite32(status & ~SMX_DRDY, csr);
++ return IRQ_HANDLED;
++}
++
++static int __devinit smx_ce_probe(struct platform_device *dev)
++{
++
++ int ret = -ENODEV;
++ struct uio_info *info;
++ struct resource *regs;
++
++ info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
++ if (!info)
++ return -ENOMEM;
++
++ regs = platform_get_resource(dev, IORESOURCE_MEM, 0);
++ if (!regs) {
++ dev_err(&dev->dev, "No memory resource specified\n");
++ goto out_free;
++ }
++
++ info->mem[0].addr = regs->start;
++ if (!info->mem[0].addr) {
++ dev_err(&dev->dev, "Invalid memory resource\n");
++ goto out_free;
++ }
++
++ info->mem[0].size = regs->end - regs->start + 1;
++ info->mem[0].internal_addr = ioremap(regs->start, info->mem[0].size);
++
++ if (!info->mem[0].internal_addr) {
++ dev_err(&dev->dev, "Can't remap memory address range\n");
++ goto out_free;
++ }
++
++ info->mem[0].memtype = UIO_MEM_PHYS;
++
++ info->name = "smx-ce";
++ info->version = "0.03";
++
++ info->irq = platform_get_irq(dev, 0);
++ if (info->irq < 0) {
++ ret = info->irq;
++ dev_err(&dev->dev, "No (or invalid) IRQ resource specified\n");
++ goto out_unmap;
++ }
++
++ info->irq_flags = IRQF_SHARED;
++ info->handler = smx_handler;
++
++ platform_set_drvdata(dev, info);
++
++ ret = uio_register_device(&dev->dev, info);
++
++ if (ret)
++ goto out_unmap;
++
++ return 0;
++
++out_unmap:
++ iounmap(info->mem[0].internal_addr);
++out_free:
++ kfree(info);
++
++ return ret;
++}
++
++static int __devexit smx_ce_remove(struct platform_device *dev)
++{
++ struct uio_info *info = platform_get_drvdata(dev);
++
++ uio_unregister_device(info);
++ platform_set_drvdata(dev, NULL);
++ iounmap(info->mem[0].internal_addr);
++
++ kfree(info);
++
++ return 0;
++}
++
++static struct platform_driver smx_ce_driver = {
++ .probe = smx_ce_probe,
++ .remove = __devexit_p(smx_ce_remove),
++ .driver = {
++ .name = DRV_NAME,
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init smx_ce_init_module(void)
++{
++ return platform_driver_register(&smx_ce_driver);
++}
++module_init(smx_ce_init_module);
++
++static void __exit smx_ce_exit_module(void)
++{
++ platform_driver_unregister(&smx_ce_driver);
++}
++module_exit(smx_ce_exit_module);
++
++MODULE_LICENSE("GPL v2");
++MODULE_VERSION(DRV_VERSION);
++MODULE_AUTHOR("Ben Nizette <bn at niasdigital.com>");
+diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
+index a51eeed..d470c72 100644
+--- a/drivers/usb/atm/cxacru.c
++++ b/drivers/usb/atm/cxacru.c
+@@ -444,7 +444,7 @@ CXACRU_ALL_FILES(INIT);
+ /* the following three functions are stolen from drivers/usb/core/message.c */
+ static void cxacru_blocking_completion(struct urb *urb)
+ {
+- complete((struct completion *)urb->context);
++ complete(urb->context);
+ }
+
+ static void cxacru_timeout_kill(unsigned long data)
+diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
+index c5ec1a5..abb7d74 100644
+--- a/drivers/usb/atm/ueagle-atm.c
++++ b/drivers/usb/atm/ueagle-atm.c
+@@ -83,7 +83,7 @@
+ if (debug >= 1) \
+ dev_dbg(&(usb_dev)->dev, \
+ "[ueagle-atm dbg] %s: " format, \
+- __FUNCTION__, ##args); \
++ __func__, ##args); \
+ } while (0)
+
+ #define uea_vdbg(usb_dev, format, args...) \
+@@ -94,10 +94,10 @@
+ } while (0)
+
+ #define uea_enters(usb_dev) \
+- uea_vdbg(usb_dev, "entering %s\n", __FUNCTION__)
++ uea_vdbg(usb_dev, "entering %s\n", __func__)
+
+ #define uea_leaves(usb_dev) \
+- uea_vdbg(usb_dev, "leaving %s\n", __FUNCTION__)
++ uea_vdbg(usb_dev, "leaving %s\n", __func__)
+
+ #define uea_err(usb_dev, format,args...) \
+ dev_err(&(usb_dev)->dev ,"[UEAGLE-ATM] " format , ##args)
+diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
+index e717f5b..0722872 100644
+--- a/drivers/usb/atm/usbatm.c
++++ b/drivers/usb/atm/usbatm.c
+@@ -80,6 +80,7 @@
+ #include <linux/stat.h>
+ #include <linux/timer.h>
+ #include <linux/wait.h>
++#include <linux/kthread.h>
+
+ #ifdef VERBOSE_DEBUG
+ static int usbatm_print_packet(const unsigned char *data, int len);
+@@ -1014,10 +1015,7 @@ static int usbatm_do_heavy_init(void *arg)
+ struct usbatm_data *instance = arg;
+ int ret;
+
+- daemonize(instance->driver->driver_name);
+ allow_signal(SIGTERM);
+- instance->thread_pid = current->pid;
+-
+ complete(&instance->thread_started);
+
+ ret = instance->driver->heavy_init(instance, instance->usb_intf);
+@@ -1026,7 +1024,7 @@ static int usbatm_do_heavy_init(void *arg)
+ ret = usbatm_atm_init(instance);
+
+ mutex_lock(&instance->serialize);
+- instance->thread_pid = -1;
++ instance->thread = NULL;
+ mutex_unlock(&instance->serialize);
+
+ complete_and_exit(&instance->thread_exited, ret);
+@@ -1034,13 +1032,18 @@ static int usbatm_do_heavy_init(void *arg)
+
+ static int usbatm_heavy_init(struct usbatm_data *instance)
+ {
+- int ret = kernel_thread(usbatm_do_heavy_init, instance, CLONE_FS | CLONE_FILES);
+-
+- if (ret < 0) {
+- usb_err(instance, "%s: failed to create kernel_thread (%d)!\n", __func__, ret);
+- return ret;
++ struct task_struct *t;
++
++ t = kthread_create(usbatm_do_heavy_init, instance,
++ instance->driver->driver_name);
++ if (IS_ERR(t)) {
++ usb_err(instance, "%s: failed to create kernel_thread (%ld)!\n",
++ __func__, PTR_ERR(t));
++ return PTR_ERR(t);
+ }
+
++ instance->thread = t;
++ wake_up_process(t);
+ wait_for_completion(&instance->thread_started);
+
+ return 0;
+@@ -1124,7 +1127,7 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
+ kref_init(&instance->refcount); /* dropped in usbatm_usb_disconnect */
+ mutex_init(&instance->serialize);
+
+- instance->thread_pid = -1;
++ instance->thread = NULL;
+ init_completion(&instance->thread_started);
+ init_completion(&instance->thread_exited);
+
+@@ -1287,8 +1290,8 @@ void usbatm_usb_disconnect(struct usb_interface *intf)
+
+ mutex_lock(&instance->serialize);
+ instance->disconnected = 1;
+- if (instance->thread_pid >= 0)
+- kill_proc(instance->thread_pid, SIGTERM, 1);
++ if (instance->thread != NULL)
++ send_sig(SIGTERM, instance->thread, 1);
+ mutex_unlock(&instance->serialize);
+
+ wait_for_completion(&instance->thread_exited);
+diff --git a/drivers/usb/atm/usbatm.h b/drivers/usb/atm/usbatm.h
+index ff8551e..e6887c6 100644
+--- a/drivers/usb/atm/usbatm.h
++++ b/drivers/usb/atm/usbatm.h
+@@ -24,7 +24,6 @@
+ #ifndef _USBATM_H_
+ #define _USBATM_H_
+
+-#include <asm/semaphore.h>
+ #include <linux/atm.h>
+ #include <linux/atmdev.h>
+ #include <linux/completion.h>
+@@ -176,7 +175,7 @@ struct usbatm_data {
+ int disconnected;
+
+ /* heavy init */
+- int thread_pid;
++ struct task_struct *thread;
+ struct completion thread_started;
+ struct completion thread_exited;
+
+diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
+index 0147ea3..7b572e7 100644
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -31,6 +31,7 @@
+ * v0.23 - use softirq for rx processing, as needed by tty layer
+ * v0.24 - change probe method to evaluate CDC union descriptor
+ * v0.25 - downstream tasks paralelized to maximize throughput
++ * v0.26 - multiple write urbs, writesize increased
+ */
+
+ /*
+@@ -72,7 +73,7 @@
+ /*
+ * Version Information
+ */
+-#define DRIVER_VERSION "v0.25"
++#define DRIVER_VERSION "v0.26"
+ #define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik, David Kubicek"
+ #define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters"
+
+@@ -118,7 +119,7 @@ static int acm_wb_alloc(struct acm *acm)
+ int i, wbn;
+ struct acm_wb *wb;
+
+- wbn = acm->write_current;
++ wbn = 0;
+ i = 0;
+ for (;;) {
+ wb = &acm->wb[wbn];
+@@ -132,11 +133,6 @@ static int acm_wb_alloc(struct acm *acm)
+ }
+ }
+
+-static void acm_wb_free(struct acm *acm, int wbn)
+-{
+- acm->wb[wbn].use = 0;
+-}
+-
+ static int acm_wb_is_avail(struct acm *acm)
+ {
+ int i, n;
+@@ -156,26 +152,22 @@ static inline int acm_wb_is_used(struct acm *acm, int wbn)
+ /*
+ * Finish write.
+ */
+-static void acm_write_done(struct acm *acm)
++static void acm_write_done(struct acm *acm, struct acm_wb *wb)
+ {
+ unsigned long flags;
+- int wbn;
+
+ spin_lock_irqsave(&acm->write_lock, flags);
+ acm->write_ready = 1;
+- wbn = acm->write_current;
+- acm_wb_free(acm, wbn);
+- acm->write_current = (wbn + 1) % ACM_NW;
++ wb->use = 0;
+ spin_unlock_irqrestore(&acm->write_lock, flags);
+ }
+
+ /*
+ * Poke write.
+ */
+-static int acm_write_start(struct acm *acm)
++static int acm_write_start(struct acm *acm, int wbn)
+ {
+ unsigned long flags;
+- int wbn;
+ struct acm_wb *wb;
+ int rc;
+
+@@ -190,24 +182,24 @@ static int acm_write_start(struct acm *acm)
+ return 0; /* A white lie */
+ }
+
+- wbn = acm->write_current;
+ if (!acm_wb_is_used(acm, wbn)) {
+ spin_unlock_irqrestore(&acm->write_lock, flags);
+ return 0;
+ }
+ wb = &acm->wb[wbn];
+
+- acm->write_ready = 0;
++ if(acm_wb_is_avail(acm) <= 1)
++ acm->write_ready = 0;
+ spin_unlock_irqrestore(&acm->write_lock, flags);
+
+- acm->writeurb->transfer_buffer = wb->buf;
+- acm->writeurb->transfer_dma = wb->dmah;
+- acm->writeurb->transfer_buffer_length = wb->len;
+- acm->writeurb->dev = acm->dev;
++ wb->urb->transfer_buffer = wb->buf;
++ wb->urb->transfer_dma = wb->dmah;
++ wb->urb->transfer_buffer_length = wb->len;
++ wb->urb->dev = acm->dev;
+
+- if ((rc = usb_submit_urb(acm->writeurb, GFP_ATOMIC)) < 0) {
++ if ((rc = usb_submit_urb(wb->urb, GFP_ATOMIC)) < 0) {
+ dbg("usb_submit_urb(write bulk) failed: %d", rc);
+- acm_write_done(acm);
++ acm_write_done(acm, wb);
+ }
+ return rc;
+ }
+@@ -268,10 +260,10 @@ static void acm_ctrl_irq(struct urb *urb)
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+- dbg("%s - urb shutting down with status: %d", __FUNCTION__, status);
++ dbg("%s - urb shutting down with status: %d", __func__, status);
+ return;
+ default:
+- dbg("%s - nonzero urb status received: %d", __FUNCTION__, status);
++ dbg("%s - nonzero urb status received: %d", __func__, status);
+ goto exit;
+ }
+
+@@ -315,7 +307,7 @@ exit:
+ retval = usb_submit_urb (urb, GFP_ATOMIC);
+ if (retval)
+ err ("%s - usb_submit_urb failed with result %d",
+- __FUNCTION__, retval);
++ __func__, retval);
+ }
+
+ /* data interface returns incoming bytes, or we got unthrottled */
+@@ -450,12 +442,13 @@ urbs:
+ /* data interface wrote those outgoing bytes */
+ static void acm_write_bulk(struct urb *urb)
+ {
+- struct acm *acm = (struct acm *)urb->context;
++ struct acm *acm;
++ struct acm_wb *wb = urb->context;
+
+ dbg("Entering acm_write_bulk with status %d", urb->status);
+
+- acm_write_done(acm);
+- acm_write_start(acm);
++ acm = wb->instance;
++ acm_write_done(acm, wb);
+ if (ACM_READY(acm))
+ schedule_work(&acm->work);
+ }
+@@ -489,6 +482,7 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
+ else
+ rv = 0;
+
++ set_bit(TTY_NO_WRITE_SPLIT, &tty->flags);
+ tty->driver_data = acm;
+ acm->tty = tty;
+
+@@ -556,7 +550,8 @@ static void acm_tty_unregister(struct acm *acm)
+ usb_put_intf(acm->control);
+ acm_table[acm->minor] = NULL;
+ usb_free_urb(acm->ctrlurb);
+- usb_free_urb(acm->writeurb);
++ for (i = 0; i < ACM_NW; i++)
++ usb_free_urb(acm->wb[i].urb);
+ for (i = 0; i < nr; i++)
+ usb_free_urb(acm->ru[i].urb);
+ kfree(acm->country_codes);
+@@ -577,7 +572,8 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
+ if (acm->dev) {
+ acm_set_control(acm, acm->ctrlout = 0);
+ usb_kill_urb(acm->ctrlurb);
+- usb_kill_urb(acm->writeurb);
++ for (i = 0; i < ACM_NW; i++)
++ usb_kill_urb(acm->wb[i].urb);
+ for (i = 0; i < nr; i++)
+ usb_kill_urb(acm->ru[i].urb);
+ usb_autopm_put_interface(acm->control);
+@@ -605,7 +601,6 @@ static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int c
+ spin_lock_irqsave(&acm->write_lock, flags);
+ if ((wbn = acm_wb_alloc(acm)) < 0) {
+ spin_unlock_irqrestore(&acm->write_lock, flags);
+- acm_write_start(acm);
+ return 0;
+ }
+ wb = &acm->wb[wbn];
+@@ -616,7 +611,7 @@ static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int c
+ wb->len = count;
+ spin_unlock_irqrestore(&acm->write_lock, flags);
+
+- if ((stat = acm_write_start(acm)) < 0)
++ if ((stat = acm_write_start(acm, wbn)) < 0)
+ return stat;
+ return count;
+ }
+@@ -809,7 +804,7 @@ static int acm_probe (struct usb_interface *intf,
+ {
+ struct usb_cdc_union_desc *union_header = NULL;
+ struct usb_cdc_country_functional_desc *cfd = NULL;
+- char *buffer = intf->altsetting->extra;
++ unsigned char *buffer = intf->altsetting->extra;
+ int buflen = intf->altsetting->extralen;
+ struct usb_interface *control_interface;
+ struct usb_interface *data_interface;
+@@ -886,9 +881,13 @@ static int acm_probe (struct usb_interface *intf,
+ if ((call_management_function & 3) != 3)
+ err("This device cannot do calls on its own. It is no modem.");
+ break;
+-
+ default:
+- err("Ignoring extra header, type %d, length %d", buffer[2], buffer[0]);
++ /* there are LOTS more CDC descriptors that
++ * could legitimately be found here.
++ */
++ dev_dbg(&intf->dev, "Ignoring descriptor: "
++ "type %02x, length %d\n",
++ buffer[2], buffer[0]);
+ break;
+ }
+ next_desc:
+@@ -976,7 +975,7 @@ skip_normal_probe:
+
+ ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize);
+ readsize = le16_to_cpu(epread->wMaxPacketSize)* ( quirks == SINGLE_RX_URB ? 1 : 2);
+- acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize);
++ acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize) * 20;
+ acm->control = control_interface;
+ acm->data = data_interface;
+ acm->minor = minor;
+@@ -1031,10 +1030,19 @@ skip_normal_probe:
+ goto alloc_fail7;
+ }
+ }
+- acm->writeurb = usb_alloc_urb(0, GFP_KERNEL);
+- if (!acm->writeurb) {
+- dev_dbg(&intf->dev, "out of memory (writeurb kmalloc)\n");
+- goto alloc_fail7;
++ for(i = 0; i < ACM_NW; i++)
++ {
++ struct acm_wb *snd = &(acm->wb[i]);
++
++ if (!(snd->urb = usb_alloc_urb(0, GFP_KERNEL))) {
++ dev_dbg(&intf->dev, "out of memory (write urbs usb_alloc_urb)");
++ goto alloc_fail7;
++ }
++
++ usb_fill_bulk_urb(snd->urb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
++ NULL, acm->writesize, acm_write_bulk, snd);
++ snd->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
++ snd->instance = acm;
+ }
+
+ usb_set_intfdata (intf, acm);
+@@ -1070,10 +1078,6 @@ skip_countries:
+ acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ acm->ctrlurb->transfer_dma = acm->ctrl_dma;
+
+- usb_fill_bulk_urb(acm->writeurb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
+- NULL, acm->writesize, acm_write_bulk, acm);
+- acm->writeurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP;
+-
+ dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor);
+
+ acm_set_control(acm, acm->ctrlout);
+@@ -1091,7 +1095,8 @@ skip_countries:
+
+ return 0;
+ alloc_fail8:
+- usb_free_urb(acm->writeurb);
++ for (i = 0; i < ACM_NW; i++)
++ usb_free_urb(acm->wb[i].urb);
+ alloc_fail7:
+ for (i = 0; i < num_rx_buf; i++)
+ usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
+@@ -1115,7 +1120,8 @@ static void stop_data_traffic(struct acm *acm)
+ tasklet_disable(&acm->urb_task);
+
+ usb_kill_urb(acm->ctrlurb);
+- usb_kill_urb(acm->writeurb);
++ for(i = 0; i < ACM_NW; i++)
++ usb_kill_urb(acm->wb[i].urb);
+ for (i = 0; i < acm->rx_buflimit; i++)
+ usb_kill_urb(acm->ru[i].urb);
+
+diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
+index 8df6a57..046e064 100644
+--- a/drivers/usb/class/cdc-acm.h
++++ b/drivers/usb/class/cdc-acm.h
+@@ -59,7 +59,7 @@
+ * when processing onlcr, so we only need 2 buffers. These values must be
+ * powers of 2.
+ */
+-#define ACM_NW 2
++#define ACM_NW 16
+ #define ACM_NR 16
+
+ struct acm_wb {
+@@ -67,6 +67,8 @@ struct acm_wb {
+ dma_addr_t dmah;
+ int len;
+ int use;
++ struct urb *urb;
++ struct acm *instance;
+ };
+
+ struct acm_rb {
+@@ -88,7 +90,7 @@ struct acm {
+ struct usb_interface *control; /* control interface */
+ struct usb_interface *data; /* data interface */
+ struct tty_struct *tty; /* the corresponding tty */
+- struct urb *ctrlurb, *writeurb; /* urbs */
++ struct urb *ctrlurb; /* urbs */
+ u8 *ctrl_buffer; /* buffers of urbs */
+ dma_addr_t ctrl_dma; /* dma handles of buffers */
+ u8 *country_codes; /* country codes from device */
+@@ -103,7 +105,6 @@ struct acm {
+ struct list_head spare_read_urbs;
+ struct list_head spare_read_bufs;
+ struct list_head filled_read_bufs;
+- int write_current; /* current write buffer */
+ int write_used; /* number of non-empty write buffers */
+ int write_ready; /* write urb is not running */
+ spinlock_t write_lock;
+diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
+index a2b0aa4..cc9f397 100644
+--- a/drivers/usb/core/Kconfig
++++ b/drivers/usb/core/Kconfig
+@@ -76,8 +76,8 @@ config USB_DEVICE_CLASS
+ NAME="bus/usb/$env{BUSNUM}/$env{DEVNUM}", MODE="0644"
+
+ config USB_DYNAMIC_MINORS
+- bool "Dynamic USB minor allocation (EXPERIMENTAL)"
+- depends on USB && EXPERIMENTAL
++ bool "Dynamic USB minor allocation"
++ depends on USB
+ help
+ If you say Y here, the USB subsystem will use dynamic minor
+ allocation for any device that uses the USB major number.
+@@ -102,31 +102,6 @@ config USB_SUSPEND
+
+ If you are unsure about this, say N here.
+
+-config USB_PERSIST
+- bool "USB device persistence during system suspend (DANGEROUS)"
+- depends on USB && PM && EXPERIMENTAL
+- default n
+- help
+-
+- If you say Y here and enable the "power/persist" attribute
+- for a USB device, the device's data structures will remain
+- persistent across system suspend, even if the USB bus loses
+- power. (This includes hibernation, also known as swsusp or
+- suspend-to-disk.) The devices will reappear as if by magic
+- when the system wakes up, with no need to unmount USB
+- filesystems, rmmod host-controller drivers, or do anything
+- else.
+-
+- WARNING: This option can be dangerous!
+-
+- If a USB device is replaced by another of the same type while
+- the system is asleep, there's a good chance the kernel won't
+- detect the change. Likewise if the media in a USB storage
+- device is replaced. When this happens it's almost certain to
+- cause data corruption and maybe even crash your system.
+-
+- If you are unsure, say N here.
+-
+ config USB_OTG
+ bool
+ depends on USB && EXPERIMENTAL
+@@ -136,14 +111,16 @@ config USB_OTG
+
+ config USB_OTG_WHITELIST
+ bool "Rely on OTG Targeted Peripherals List"
+- depends on USB_OTG
+- default y
++ depends on USB_OTG || EMBEDDED
++ default y if USB_OTG
++ default n if EMBEDDED
+ help
+ If you say Y here, the "otg_whitelist.h" file will be used as a
+ product whitelist, so USB peripherals not listed there will be
+ rejected during enumeration. This behavior is required by the
+ USB OTG specification for all devices not on your product's
+- "Targeted Peripherals List".
++ "Targeted Peripherals List". "Embedded Hosts" are likewise
++ allowed to support only a limited number of peripherals.
+
+ Otherwise, peripherals not listed there will only generate a
+ warning and enumeration will continue. That's more like what
+@@ -152,9 +129,10 @@ config USB_OTG_WHITELIST
+
+ config USB_OTG_BLACKLIST_HUB
+ bool "Disable external hubs"
+- depends on USB_OTG
++ depends on USB_OTG || EMBEDDED
+ help
+ If you say Y here, then Linux will refuse to enumerate
+ external hubs. OTG hosts are allowed to reduce hardware
+- and software costs by not supporting external hubs.
++ and software costs by not supporting external hubs. So
++ are "Emedded Hosts" that don't offer OTG support.
+
+diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
+index a92122a..568244c 100644
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -145,6 +145,23 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
+ endpoint->desc.wMaxPacketSize = cpu_to_le16(8);
+ }
+
++ /*
++ * Some buggy high speed devices have bulk endpoints using
++ * maxpacket sizes other than 512. High speed HCDs may not
++ * be able to handle that particular bug, so let's warn...
++ */
++ if (to_usb_device(ddev)->speed == USB_SPEED_HIGH
++ && usb_endpoint_xfer_bulk(d)) {
++ unsigned maxp;
++
++ maxp = le16_to_cpu(endpoint->desc.wMaxPacketSize) & 0x07ff;
++ if (maxp != 512)
++ dev_warn(ddev, "config %d interface %d altsetting %d "
++ "bulk endpoint 0x%X has invalid maxpacket %d\n",
++ cfgno, inum, asnum, d->bEndpointAddress,
++ maxp);
++ }
++
+ /* Skip over any Class Specific or Vendor Specific descriptors;
+ * find the next endpoint or interface descriptor */
+ endpoint->extra = buffer;
+diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
+index ae94176..de17738 100644
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -647,6 +647,7 @@ static int proc_control(struct dev_state *ps, void __user *arg)
+ struct usbdevfs_ctrltransfer ctrl;
+ unsigned int tmo;
+ unsigned char *tbuf;
++ unsigned wLength;
+ int i, j, ret;
+
+ if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
+@@ -654,7 +655,8 @@ static int proc_control(struct dev_state *ps, void __user *arg)
+ ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.wIndex);
+ if (ret)
+ return ret;
+- if (ctrl.wLength > PAGE_SIZE)
++ wLength = ctrl.wLength; /* To suppress 64k PAGE_SIZE warning */
++ if (wLength > PAGE_SIZE)
+ return -EINVAL;
+ tbuf = (unsigned char *)__get_free_page(GFP_KERNEL);
+ if (!tbuf)
+@@ -946,8 +948,11 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ int ret, ifnum = -1;
+ int is_in;
+
+- if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK|
+- URB_NO_FSBR|URB_ZERO_PACKET))
++ if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP |
++ USBDEVFS_URB_SHORT_NOT_OK |
++ USBDEVFS_URB_NO_FSBR |
++ USBDEVFS_URB_ZERO_PACKET |
++ USBDEVFS_URB_NO_INTERRUPT))
+ return -EINVAL;
+ if (!uurb->buffer)
+ return -EINVAL;
+@@ -1102,8 +1107,24 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ as->urb->pipe = (uurb->type << 30) |
+ __create_pipe(ps->dev, uurb->endpoint & 0xf) |
+ (uurb->endpoint & USB_DIR_IN);
+- as->urb->transfer_flags = uurb->flags |
+- (is_in ? URB_DIR_IN : URB_DIR_OUT);
++
++ /* This tedious sequence is necessary because the URB_* flags
++ * are internal to the kernel and subject to change, whereas
++ * the USBDEVFS_URB_* flags are a user API and must not be changed.
++ */
++ u = (is_in ? URB_DIR_IN : URB_DIR_OUT);
++ if (uurb->flags & USBDEVFS_URB_ISO_ASAP)
++ u |= URB_ISO_ASAP;
++ if (uurb->flags & USBDEVFS_URB_SHORT_NOT_OK)
++ u |= URB_SHORT_NOT_OK;
++ if (uurb->flags & USBDEVFS_URB_NO_FSBR)
++ u |= URB_NO_FSBR;
++ if (uurb->flags & USBDEVFS_URB_ZERO_PACKET)
++ u |= URB_ZERO_PACKET;
++ if (uurb->flags & USBDEVFS_URB_NO_INTERRUPT)
++ u |= URB_NO_INTERRUPT;
++ as->urb->transfer_flags = u;
++
+ as->urb->transfer_buffer_length = uurb->buffer_length;
+ as->urb->setup_packet = (unsigned char *)dr;
+ as->urb->start_frame = uurb->start_frame;
+@@ -1509,60 +1530,60 @@ static int usbdev_ioctl(struct inode *inode, struct file *file,
+
+ switch (cmd) {
+ case USBDEVFS_CONTROL:
+- snoop(&dev->dev, "%s: CONTROL\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: CONTROL\n", __func__);
+ ret = proc_control(ps, p);
+ if (ret >= 0)
+ inode->i_mtime = CURRENT_TIME;
+ break;
+
+ case USBDEVFS_BULK:
+- snoop(&dev->dev, "%s: BULK\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: BULK\n", __func__);
+ ret = proc_bulk(ps, p);
+ if (ret >= 0)
+ inode->i_mtime = CURRENT_TIME;
+ break;
+
+ case USBDEVFS_RESETEP:
+- snoop(&dev->dev, "%s: RESETEP\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: RESETEP\n", __func__);
+ ret = proc_resetep(ps, p);
+ if (ret >= 0)
+ inode->i_mtime = CURRENT_TIME;
+ break;
+
+ case USBDEVFS_RESET:
+- snoop(&dev->dev, "%s: RESET\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: RESET\n", __func__);
+ ret = proc_resetdevice(ps);
+ break;
+
+ case USBDEVFS_CLEAR_HALT:
+- snoop(&dev->dev, "%s: CLEAR_HALT\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: CLEAR_HALT\n", __func__);
+ ret = proc_clearhalt(ps, p);
+ if (ret >= 0)
+ inode->i_mtime = CURRENT_TIME;
+ break;
+
+ case USBDEVFS_GETDRIVER:
+- snoop(&dev->dev, "%s: GETDRIVER\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: GETDRIVER\n", __func__);
+ ret = proc_getdriver(ps, p);
+ break;
+
+ case USBDEVFS_CONNECTINFO:
+- snoop(&dev->dev, "%s: CONNECTINFO\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: CONNECTINFO\n", __func__);
+ ret = proc_connectinfo(ps, p);
+ break;
+
+ case USBDEVFS_SETINTERFACE:
+- snoop(&dev->dev, "%s: SETINTERFACE\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: SETINTERFACE\n", __func__);
+ ret = proc_setintf(ps, p);
+ break;
+
+ case USBDEVFS_SETCONFIGURATION:
+- snoop(&dev->dev, "%s: SETCONFIGURATION\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: SETCONFIGURATION\n", __func__);
+ ret = proc_setconfig(ps, p);
+ break;
+
+ case USBDEVFS_SUBMITURB:
+- snoop(&dev->dev, "%s: SUBMITURB\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: SUBMITURB\n", __func__);
+ ret = proc_submiturb(ps, p);
+ if (ret >= 0)
+ inode->i_mtime = CURRENT_TIME;
+@@ -1571,60 +1592,60 @@ static int usbdev_ioctl(struct inode *inode, struct file *file,
+ #ifdef CONFIG_COMPAT
+
+ case USBDEVFS_SUBMITURB32:
+- snoop(&dev->dev, "%s: SUBMITURB32\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: SUBMITURB32\n", __func__);
+ ret = proc_submiturb_compat(ps, p);
+ if (ret >= 0)
+ inode->i_mtime = CURRENT_TIME;
+ break;
+
+ case USBDEVFS_REAPURB32:
+- snoop(&dev->dev, "%s: REAPURB32\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: REAPURB32\n", __func__);
+ ret = proc_reapurb_compat(ps, p);
+ break;
+
+ case USBDEVFS_REAPURBNDELAY32:
+- snoop(&dev->dev, "%s: REAPURBDELAY32\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: REAPURBDELAY32\n", __func__);
+ ret = proc_reapurbnonblock_compat(ps, p);
+ break;
+
+ case USBDEVFS_IOCTL32:
+- snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: IOCTL\n", __func__);
+ ret = proc_ioctl_compat(ps, ptr_to_compat(p));
+ break;
+ #endif
+
+ case USBDEVFS_DISCARDURB:
+- snoop(&dev->dev, "%s: DISCARDURB\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: DISCARDURB\n", __func__);
+ ret = proc_unlinkurb(ps, p);
+ break;
+
+ case USBDEVFS_REAPURB:
+- snoop(&dev->dev, "%s: REAPURB\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: REAPURB\n", __func__);
+ ret = proc_reapurb(ps, p);
+ break;
+
+ case USBDEVFS_REAPURBNDELAY:
+- snoop(&dev->dev, "%s: REAPURBDELAY\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: REAPURBDELAY\n", __func__);
+ ret = proc_reapurbnonblock(ps, p);
+ break;
+
+ case USBDEVFS_DISCSIGNAL:
+- snoop(&dev->dev, "%s: DISCSIGNAL\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: DISCSIGNAL\n", __func__);
+ ret = proc_disconnectsignal(ps, p);
+ break;
+
+ case USBDEVFS_CLAIMINTERFACE:
+- snoop(&dev->dev, "%s: CLAIMINTERFACE\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: CLAIMINTERFACE\n", __func__);
+ ret = proc_claiminterface(ps, p);
+ break;
+
+ case USBDEVFS_RELEASEINTERFACE:
+- snoop(&dev->dev, "%s: RELEASEINTERFACE\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: RELEASEINTERFACE\n", __func__);
+ ret = proc_releaseinterface(ps, p);
+ break;
+
+ case USBDEVFS_IOCTL:
+- snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__);
++ snoop(&dev->dev, "%s: IOCTL\n", __func__);
+ ret = proc_ioctl_default(ps, p);
+ break;
+ }
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index 801b6f1..1e56f1c 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -157,7 +157,7 @@ static int usb_probe_device(struct device *dev)
+ struct usb_device *udev;
+ int error = -ENODEV;
+
+- dev_dbg(dev, "%s\n", __FUNCTION__);
++ dev_dbg(dev, "%s\n", __func__);
+
+ if (!is_usb_device(dev)) /* Sanity check */
+ return error;
+@@ -194,7 +194,7 @@ static int usb_probe_interface(struct device *dev)
+ const struct usb_device_id *id;
+ int error = -ENODEV;
+
+- dev_dbg(dev, "%s\n", __FUNCTION__);
++ dev_dbg(dev, "%s\n", __func__);
+
+ if (is_usb_device(dev)) /* Sanity check */
+ return error;
+@@ -211,7 +211,7 @@ static int usb_probe_interface(struct device *dev)
+ if (!id)
+ id = usb_match_dynamic_id(intf, driver);
+ if (id) {
+- dev_dbg(dev, "%s - got id\n", __FUNCTION__);
++ dev_dbg(dev, "%s - got id\n", __func__);
+
+ error = usb_autoresume_device(udev);
+ if (error)
+@@ -793,9 +793,7 @@ static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
+ status = udriver->suspend(udev, msg);
+
+ done:
+- dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+- if (status == 0)
+- udev->dev.power.power_state.event = msg.event;
++ dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
+ return status;
+ }
+
+@@ -823,11 +821,9 @@ static int usb_resume_device(struct usb_device *udev)
+ status = udriver->resume(udev);
+
+ done:
+- dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+- if (status == 0) {
++ dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
++ if (status == 0)
+ udev->autoresume_disabled = 0;
+- udev->dev.power.power_state.event = PM_EVENT_ON;
+- }
+ return status;
+ }
+
+@@ -864,7 +860,7 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
+ }
+
+ done:
+- dev_vdbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
++ dev_vdbg(&intf->dev, "%s: status %d\n", __func__, status);
+ return status;
+ }
+
+@@ -914,7 +910,7 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
+ }
+
+ done:
+- dev_vdbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
++ dev_vdbg(&intf->dev, "%s: status %d\n", __func__, status);
+ if (status == 0)
+ mark_active(intf);
+
+@@ -936,7 +932,6 @@ static int autosuspend_check(struct usb_device *udev, int reschedule)
+ * is disabled. Also fail if any interfaces require remote wakeup
+ * but it isn't available.
+ */
+- udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
+ if (udev->pm_usage_cnt > 0)
+ return -EBUSY;
+ if (udev->autosuspend_delay < 0 || udev->autosuspend_disabled)
+@@ -1098,7 +1093,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ }
+
+ done:
+- dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
++ dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
+ return status;
+ }
+
+@@ -1180,8 +1175,7 @@ static int usb_resume_both(struct usb_device *udev)
+ }
+ } else {
+
+- /* Needed for setting udev->dev.power.power_state.event,
+- * for possible debugging message, and for reset_resume. */
++ /* Needed for reset-resume */
+ status = usb_resume_device(udev);
+ }
+
+@@ -1193,8 +1187,9 @@ static int usb_resume_both(struct usb_device *udev)
+ }
+
+ done:
+- dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+- udev->reset_resume = 0;
++ dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status);
++ if (!status)
++ udev->reset_resume = 0;
+ return status;
+ }
+
+@@ -1262,7 +1257,7 @@ void usb_autosuspend_device(struct usb_device *udev)
+
+ status = usb_autopm_do_device(udev, -1);
+ dev_vdbg(&udev->dev, "%s: cnt %d\n",
+- __FUNCTION__, udev->pm_usage_cnt);
++ __func__, udev->pm_usage_cnt);
+ }
+
+ /**
+@@ -1282,7 +1277,7 @@ void usb_try_autosuspend_device(struct usb_device *udev)
+ {
+ usb_autopm_do_device(udev, 0);
+ dev_vdbg(&udev->dev, "%s: cnt %d\n",
+- __FUNCTION__, udev->pm_usage_cnt);
++ __func__, udev->pm_usage_cnt);
+ }
+
+ /**
+@@ -1310,7 +1305,7 @@ int usb_autoresume_device(struct usb_device *udev)
+
+ status = usb_autopm_do_device(udev, 1);
+ dev_vdbg(&udev->dev, "%s: status %d cnt %d\n",
+- __FUNCTION__, status, udev->pm_usage_cnt);
++ __func__, status, udev->pm_usage_cnt);
+ return status;
+ }
+
+@@ -1382,7 +1377,7 @@ void usb_autopm_put_interface(struct usb_interface *intf)
+
+ status = usb_autopm_do_interface(intf, -1);
+ dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+- __FUNCTION__, status, intf->pm_usage_cnt);
++ __func__, status, intf->pm_usage_cnt);
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
+
+@@ -1426,7 +1421,7 @@ int usb_autopm_get_interface(struct usb_interface *intf)
+
+ status = usb_autopm_do_interface(intf, 1);
+ dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+- __FUNCTION__, status, intf->pm_usage_cnt);
++ __func__, status, intf->pm_usage_cnt);
+ return status;
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
+@@ -1448,7 +1443,7 @@ int usb_autopm_set_interface(struct usb_interface *intf)
+
+ status = usb_autopm_do_interface(intf, 0);
+ dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+- __FUNCTION__, status, intf->pm_usage_cnt);
++ __func__, status, intf->pm_usage_cnt);
+ return status;
+ }
+ EXPORT_SYMBOL_GPL(usb_autopm_set_interface);
+@@ -1523,9 +1518,14 @@ static int usb_suspend(struct device *dev, pm_message_t message)
+ udev = to_usb_device(dev);
+
+ /* If udev is already suspended, we can skip this suspend and
+- * we should also skip the upcoming system resume. */
++ * we should also skip the upcoming system resume. High-speed
++ * root hubs are an exception; they need to resume whenever the
++ * system wakes up in order for USB-PERSIST port handover to work
++ * properly.
++ */
+ if (udev->state == USB_STATE_SUSPENDED) {
+- udev->skip_sys_resume = 1;
++ if (udev->parent || udev->speed != USB_SPEED_HIGH)
++ udev->skip_sys_resume = 1;
+ return 0;
+ }
+
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index 84760dd..5b87ae7 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -73,7 +73,6 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ if (pci_enable_device(dev) < 0)
+ return -ENODEV;
+ dev->current_state = PCI_D0;
+- dev->dev.power.power_state = PMSG_ON;
+
+ if (!dev->irq) {
+ dev_err(&dev->dev,
+@@ -216,9 +215,9 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message)
+ hcd->state == HC_STATE_HALT))
+ return -EBUSY;
+
+- if (hcd->driver->suspend) {
+- retval = hcd->driver->suspend(hcd, message);
+- suspend_report_result(hcd->driver->suspend, retval);
++ if (hcd->driver->pci_suspend) {
++ retval = hcd->driver->pci_suspend(hcd, message);
++ suspend_report_result(hcd->driver->pci_suspend, retval);
+ if (retval)
+ goto done;
+ }
+@@ -302,8 +301,6 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message)
+
+ done:
+ if (retval == 0) {
+- dev->dev.power.power_state = PMSG_SUSPEND;
+-
+ #ifdef CONFIG_PPC_PMAC
+ /* Disable ASIC clocks for USB */
+ if (machine_is(powermac)) {
+@@ -406,12 +403,10 @@ int usb_hcd_pci_resume(struct pci_dev *dev)
+ pci_set_master(dev);
+ pci_restore_state(dev);
+
+- dev->dev.power.power_state = PMSG_ON;
+-
+ clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+
+- if (hcd->driver->resume) {
+- retval = hcd->driver->resume(hcd);
++ if (hcd->driver->pci_resume) {
++ retval = hcd->driver->pci_resume(hcd);
+ if (retval) {
+ dev_err(hcd->self.controller,
+ "PCI post-resume error %d!\n", retval);
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index e52ed16..bf10e9c 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -129,7 +129,7 @@ static const u8 usb2_rh_dev_descriptor [18] = {
+
+ 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 bDeviceSubClass; */
+- 0x01, /* __u8 bDeviceProtocol; [ usb 2.0 single TT ]*/
++ 0x00, /* __u8 bDeviceProtocol; [ usb 2.0 no TT ] */
+ 0x40, /* __u8 bMaxPacketSize0; 64 Bytes */
+
+ 0x6b, 0x1d, /* __le16 idVendor; Linux Foundation */
+@@ -291,7 +291,6 @@ static int ascii2utf (char *s, u8 *utf, int utfmax)
+ * rh_string - provides manufacturer, product and serial strings for root hub
+ * @id: the string ID number (1: serial number, 2: product, 3: vendor)
+ * @hcd: the host controller for this root hub
+- * @type: string describing our driver
+ * @data: return packet in UTF-16 LE
+ * @len: length of the return packet
+ *
+@@ -355,9 +354,10 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
+ __attribute__((aligned(4)));
+ const u8 *bufp = tbuf;
+ int len = 0;
+- int patch_wakeup = 0;
+ int status;
+ int n;
++ u8 patch_wakeup = 0;
++ u8 patch_protocol = 0;
+
+ might_sleep();
+
+@@ -434,6 +434,8 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
+ else
+ goto error;
+ len = 18;
++ if (hcd->has_tt)
++ patch_protocol = 1;
+ break;
+ case USB_DT_CONFIG << 8:
+ if (hcd->driver->flags & HCD_USB2) {
+@@ -528,6 +530,13 @@ error:
+ bmAttributes))
+ ((struct usb_config_descriptor *)ubuf)->bmAttributes
+ |= USB_CONFIG_ATT_WAKEUP;
++
++ /* report whether RH hardware has an integrated TT */
++ if (patch_protocol &&
++ len > offsetof(struct usb_device_descriptor,
++ bDeviceProtocol))
++ ((struct usb_device_descriptor *) ubuf)->
++ bDeviceProtocol = 1;
+ }
+
+ /* any errors get returned through the urb completion */
+@@ -915,15 +924,6 @@ static int register_root_hub(struct usb_hcd *hcd)
+ return retval;
+ }
+
+-void usb_enable_root_hub_irq (struct usb_bus *bus)
+-{
+- struct usb_hcd *hcd;
+-
+- hcd = container_of (bus, struct usb_hcd, self);
+- if (hcd->driver->hub_irq_enable && hcd->state != HC_STATE_HALT)
+- hcd->driver->hub_irq_enable (hcd);
+-}
+-
+
+ /*-------------------------------------------------------------------------*/
+
+@@ -1677,7 +1677,6 @@ EXPORT_SYMBOL_GPL(usb_bus_start_enum);
+ * usb_hcd_irq - hook IRQs to HCD framework (bus glue)
+ * @irq: the IRQ being raised
+ * @__hcd: pointer to the HCD whose IRQ is being signaled
+- * @r: saved hardware registers
+ *
+ * If the controller isn't HALTed, calls the driver's irq handler.
+ * Checks whether the controller is now dead.
+diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
+index 2d1c3d5..1e4b81e 100644
+--- a/drivers/usb/core/hcd.h
++++ b/drivers/usb/core/hcd.h
+@@ -28,7 +28,7 @@
+ /*
+ * USB Packet IDs (PIDs)
+ */
+-#define USB_PID_UNDEF_0 0xf0
++#define USB_PID_EXT 0xf0 /* USB 2.0 LPM ECN */
+ #define USB_PID_OUT 0xe1
+ #define USB_PID_ACK 0xd2
+ #define USB_PID_DATA0 0xc3
+@@ -99,6 +99,7 @@ struct usb_hcd {
+ unsigned poll_pending:1; /* status has changed? */
+ unsigned wireless:1; /* Wireless USB HCD */
+ unsigned authorized_default:1;
++ unsigned has_tt:1; /* Integrated TT in root hub */
+
+ int irq; /* irq allocated */
+ void __iomem *regs; /* device memory/io */
+@@ -177,10 +178,10 @@ struct hc_driver {
+ * a whole, not just the root hub; they're for PCI bus glue.
+ */
+ /* called after suspending the hub, before entering D3 etc */
+- int (*suspend) (struct usb_hcd *hcd, pm_message_t message);
++ int (*pci_suspend) (struct usb_hcd *hcd, pm_message_t message);
+
+ /* called after entering D0 (etc), before resuming the hub */
+- int (*resume) (struct usb_hcd *hcd);
++ int (*pci_resume) (struct usb_hcd *hcd);
+
+ /* cleanly make HCD stop writing memory and doing I/O */
+ void (*stop) (struct usb_hcd *hcd);
+@@ -209,8 +210,6 @@ struct hc_driver {
+ int (*bus_suspend)(struct usb_hcd *);
+ int (*bus_resume)(struct usb_hcd *);
+ int (*start_port_reset)(struct usb_hcd *, unsigned port_num);
+- void (*hub_irq_enable)(struct usb_hcd *);
+- /* Needed only if port-change IRQs are level-triggered */
+
+ /* force handover of high-speed port to full-speed companion */
+ void (*relinquish_port)(struct usb_hcd *, int);
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 68fc521..eb57fcc 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -23,7 +23,6 @@
+ #include <linux/mutex.h>
+ #include <linux/freezer.h>
+
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ #include <asm/byteorder.h>
+
+@@ -31,12 +30,6 @@
+ #include "hcd.h"
+ #include "hub.h"
+
+-#ifdef CONFIG_USB_PERSIST
+-#define USB_PERSIST 1
+-#else
+-#define USB_PERSIST 0
+-#endif
+-
+ /* if we are in debug mode, always announce new devices */
+ #ifdef DEBUG
+ #ifndef CONFIG_USB_ANNOUNCE_NEW_DEVICES
+@@ -334,6 +327,27 @@ static int get_port_status(struct usb_device *hdev, int port1,
+ return status;
+ }
+
++static int hub_port_status(struct usb_hub *hub, int port1,
++ u16 *status, u16 *change)
++{
++ int ret;
++
++ mutex_lock(&hub->status_mutex);
++ ret = get_port_status(hub->hdev, port1, &hub->status->port);
++ if (ret < 4) {
++ dev_err(hub->intfdev,
++ "%s failed (err = %d)\n", __func__, ret);
++ if (ret >= 0)
++ ret = -EIO;
++ } else {
++ *status = le16_to_cpu(hub->status->port.wPortStatus);
++ *change = le16_to_cpu(hub->status->port.wPortChange);
++ ret = 0;
++ }
++ mutex_unlock(&hub->status_mutex);
++ return ret;
++}
++
+ static void kick_khubd(struct usb_hub *hub)
+ {
+ unsigned long flags;
+@@ -561,7 +575,7 @@ static int hub_hub_status(struct usb_hub *hub,
+ ret = get_hub_status(hub->hdev, &hub->status->hub);
+ if (ret < 0)
+ dev_err (hub->intfdev,
+- "%s failed (err = %d)\n", __FUNCTION__, ret);
++ "%s failed (err = %d)\n", __func__, ret);
+ else {
+ *status = le16_to_cpu(hub->status->hub.wHubStatus);
+ *change = le16_to_cpu(hub->status->hub.wHubChange);
+@@ -611,9 +625,8 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
+ }
+
+ /* caller has locked the hub device */
+-static int hub_pre_reset(struct usb_interface *intf)
++static void hub_stop(struct usb_hub *hub)
+ {
+- struct usb_hub *hub = usb_get_intfdata(intf);
+ struct usb_device *hdev = hub->hdev;
+ int i;
+
+@@ -623,6 +636,89 @@ static int hub_pre_reset(struct usb_interface *intf)
+ usb_disconnect(&hdev->children[i]);
+ }
+ hub_quiesce(hub);
++}
++
++#define HUB_RESET 1
++#define HUB_RESUME 2
++#define HUB_RESET_RESUME 3
++
++#ifdef CONFIG_PM
++
++static void hub_restart(struct usb_hub *hub, int type)
++{
++ struct usb_device *hdev = hub->hdev;
++ int port1;
++
++ /* Check each of the children to see if they require
++ * USB-PERSIST handling or disconnection. Also check
++ * each unoccupied port to make sure it is still disabled.
++ */
++ for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
++ struct usb_device *udev = hdev->children[port1-1];
++ int status = 0;
++ u16 portstatus, portchange;
++
++ if (!udev || udev->state == USB_STATE_NOTATTACHED) {
++ if (type != HUB_RESET) {
++ status = hub_port_status(hub, port1,
++ &portstatus, &portchange);
++ if (status == 0 && (portstatus &
++ USB_PORT_STAT_ENABLE))
++ clear_port_feature(hdev, port1,
++ USB_PORT_FEAT_ENABLE);
++ }
++ continue;
++ }
++
++ /* Was the power session lost while we were suspended? */
++ switch (type) {
++ case HUB_RESET_RESUME:
++ portstatus = 0;
++ portchange = USB_PORT_STAT_C_CONNECTION;
++ break;
++
++ case HUB_RESET:
++ case HUB_RESUME:
++ status = hub_port_status(hub, port1,
++ &portstatus, &portchange);
++ break;
++ }
++
++ /* For "USB_PERSIST"-enabled children we must
++ * mark the child device for reset-resume and
++ * turn off the various status changes to prevent
++ * khubd from disconnecting it later.
++ */
++ if (udev->persist_enabled && status == 0 &&
++ !(portstatus & USB_PORT_STAT_ENABLE)) {
++ if (portchange & USB_PORT_STAT_C_ENABLE)
++ clear_port_feature(hub->hdev, port1,
++ USB_PORT_FEAT_C_ENABLE);
++ if (portchange & USB_PORT_STAT_C_CONNECTION)
++ clear_port_feature(hub->hdev, port1,
++ USB_PORT_FEAT_C_CONNECTION);
++ udev->reset_resume = 1;
++ }
++
++ /* Otherwise for a reset_resume we must disconnect the child,
++ * but as we may not lock the child device here
++ * we have to do a "logical" disconnect.
++ */
++ else if (type == HUB_RESET_RESUME)
++ hub_port_logical_disconnect(hub, port1);
++ }
++
++ hub_activate(hub);
++}
++
++#endif /* CONFIG_PM */
++
++/* caller has locked the hub device */
++static int hub_pre_reset(struct usb_interface *intf)
++{
++ struct usb_hub *hub = usb_get_intfdata(intf);
++
++ hub_stop(hub);
+ return 0;
+ }
+
+@@ -911,7 +1007,7 @@ static void hub_disconnect(struct usb_interface *intf)
+
+ /* Disconnect all children and quiesce the hub */
+ hub->error = 0;
+- hub_pre_reset(intf);
++ hub_stop(hub);
+
+ usb_set_intfdata (intf, NULL);
+
+@@ -1099,21 +1195,42 @@ void usb_set_device_state(struct usb_device *udev,
+ spin_unlock_irqrestore(&device_state_lock, flags);
+ }
+
++/*
++ * WUSB devices are simple: they have no hubs behind, so the mapping
++ * device <-> virtual port number becomes 1:1. Why? to simplify the
++ * life of the device connection logic in
++ * drivers/usb/wusbcore/devconnect.c. When we do the initial secret
++ * handshake we need to assign a temporary address in the unauthorized
++ * space. For simplicity we use the first virtual port number found to
++ * be free [drivers/usb/wusbcore/devconnect.c:wusbhc_devconnect_ack()]
++ * and that becomes it's address [X < 128] or its unauthorized address
++ * [X | 0x80].
++ *
++ * We add 1 as an offset to the one-based USB-stack port number
++ * (zero-based wusb virtual port index) for two reasons: (a) dev addr
++ * 0 is reserved by USB for default address; (b) Linux's USB stack
++ * uses always #1 for the root hub of the controller. So USB stack's
++ * port #1, which is wusb virtual-port #0 has address #2.
++ */
+ static void choose_address(struct usb_device *udev)
+ {
+ int devnum;
+ struct usb_bus *bus = udev->bus;
+
+ /* If khubd ever becomes multithreaded, this will need a lock */
+-
+- /* Try to allocate the next devnum beginning at bus->devnum_next. */
+- devnum = find_next_zero_bit(bus->devmap.devicemap, 128,
+- bus->devnum_next);
+- if (devnum >= 128)
+- devnum = find_next_zero_bit(bus->devmap.devicemap, 128, 1);
+-
+- bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1);
+-
++ if (udev->wusb) {
++ devnum = udev->portnum + 1;
++ BUG_ON(test_bit(devnum, bus->devmap.devicemap));
++ } else {
++ /* Try to allocate the next devnum beginning at
++ * bus->devnum_next. */
++ devnum = find_next_zero_bit(bus->devmap.devicemap, 128,
++ bus->devnum_next);
++ if (devnum >= 128)
++ devnum = find_next_zero_bit(bus->devmap.devicemap,
++ 128, 1);
++ bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1);
++ }
+ if (devnum < 128) {
+ set_bit(devnum, bus->devmap.devicemap);
+ udev->devnum = devnum;
+@@ -1128,6 +1245,13 @@ static void release_address(struct usb_device *udev)
+ }
+ }
+
++static void update_address(struct usb_device *udev, int devnum)
++{
++ /* The address for a WUSB device is managed by wusbcore. */
++ if (!udev->wusb)
++ udev->devnum = devnum;
++}
++
+ #ifdef CONFIG_USB_SUSPEND
+
+ static void usb_stop_pm(struct usb_device *udev)
+@@ -1174,7 +1298,7 @@ void usb_disconnect(struct usb_device **pdev)
+ int i;
+
+ if (!udev) {
+- pr_debug ("%s nodev\n", __FUNCTION__);
++ pr_debug ("%s nodev\n", __func__);
+ return;
+ }
+
+@@ -1511,28 +1635,6 @@ out_authorized:
+ }
+
+
+-static int hub_port_status(struct usb_hub *hub, int port1,
+- u16 *status, u16 *change)
+-{
+- int ret;
+-
+- mutex_lock(&hub->status_mutex);
+- ret = get_port_status(hub->hdev, port1, &hub->status->port);
+- if (ret < 4) {
+- dev_err (hub->intfdev,
+- "%s failed (err = %d)\n", __FUNCTION__, ret);
+- if (ret >= 0)
+- ret = -EIO;
+- } else {
+- *status = le16_to_cpu(hub->status->port.wPortStatus);
+- *change = le16_to_cpu(hub->status->port.wPortChange);
+- ret = 0;
+- }
+- mutex_unlock(&hub->status_mutex);
+- return ret;
+-}
+-
+-
+ /* Returns 1 if @hub is a WUSB root hub, 0 otherwise */
+ static unsigned hub_is_wusb(struct usb_hub *hub)
+ {
+@@ -1638,7 +1740,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
+ case 0:
+ /* TRSTRCY = 10 ms; plus some extra */
+ msleep(10 + 40);
+- udev->devnum = 0; /* Device now at address 0 */
++ update_address(udev, 0);
+ /* FALL THROUGH */
+ case -ENOTCONN:
+ case -ENODEV:
+@@ -1843,9 +1945,8 @@ static int finish_port_resume(struct usb_device *udev)
+ * the host and the device is the same as it was when the device
+ * suspended.
+ *
+- * If CONFIG_USB_PERSIST and @udev->reset_resume are both set then this
+- * routine won't check that the port is still enabled. Furthermore,
+- * if @udev->reset_resume is set then finish_port_resume() above will
++ * If @udev->reset_resume is set then this routine won't check that the
++ * port is still enabled. Furthermore, finish_port_resume() above will
+ * reset @udev. The end result is that a broken power session can be
+ * recovered and @udev will appear to persist across a loss of VBUS power.
+ *
+@@ -1857,8 +1958,8 @@ static int finish_port_resume(struct usb_device *udev)
+ * to it will be lost. Using the USB_PERSIST facility, the device can be
+ * made to appear as if it had not disconnected.
+ *
+- * This facility is inherently dangerous. Although usb_reset_device()
+- * makes every effort to insure that the same device is present after the
++ * This facility can be dangerous. Although usb_reset_device() makes
++ * every effort to insure that the same device is present after the
+ * reset as before, it cannot provide a 100% guarantee. Furthermore it's
+ * quite possible for a device to remain unaltered but its media to be
+ * changed. If the user replaces a flash memory card while the system is
+@@ -1903,7 +2004,7 @@ int usb_port_resume(struct usb_device *udev)
+ status = hub_port_status(hub, port1, &portstatus, &portchange);
+
+ SuspendCleared:
+- if (USB_PERSIST && udev->reset_resume)
++ if (udev->reset_resume)
+ want_flags = USB_PORT_STAT_POWER
+ | USB_PORT_STAT_CONNECTION;
+ else
+@@ -1928,8 +2029,6 @@ int usb_port_resume(struct usb_device *udev)
+ }
+
+ clear_bit(port1, hub->busy_bits);
+- if (!hub->hdev->parent && !hub->busy_bits[0])
+- usb_enable_root_hub_irq(hub->hdev->bus);
+
+ if (status == 0)
+ status = finish_port_resume(udev);
+@@ -2001,7 +2100,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+ }
+ }
+
+- dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
++ dev_dbg(&intf->dev, "%s\n", __func__);
+
+ /* stop khubd and related activity */
+ hub_quiesce(hub);
+@@ -2010,49 +2109,20 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+
+ static int hub_resume(struct usb_interface *intf)
+ {
+- struct usb_hub *hub = usb_get_intfdata (intf);
+-
+- dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
++ struct usb_hub *hub = usb_get_intfdata(intf);
+
+- /* tell khubd to look for changes on this hub */
+- hub_activate(hub);
++ dev_dbg(&intf->dev, "%s\n", __func__);
++ hub_restart(hub, HUB_RESUME);
+ return 0;
+ }
+
+ static int hub_reset_resume(struct usb_interface *intf)
+ {
+ struct usb_hub *hub = usb_get_intfdata(intf);
+- struct usb_device *hdev = hub->hdev;
+- int port1;
+
++ dev_dbg(&intf->dev, "%s\n", __func__);
+ hub_power_on(hub);
+-
+- for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+- struct usb_device *child = hdev->children[port1-1];
+-
+- if (child) {
+-
+- /* For "USB_PERSIST"-enabled children we must
+- * mark the child device for reset-resume and
+- * turn off the connect-change status to prevent
+- * khubd from disconnecting it later.
+- */
+- if (USB_PERSIST && child->persist_enabled) {
+- child->reset_resume = 1;
+- clear_port_feature(hdev, port1,
+- USB_PORT_FEAT_C_CONNECTION);
+-
+- /* Otherwise we must disconnect the child,
+- * but as we may not lock the child device here
+- * we have to do a "logical" disconnect.
+- */
+- } else {
+- hub_port_logical_disconnect(hub, port1);
+- }
+- }
+- }
+-
+- hub_activate(hub);
++ hub_restart(hub, HUB_RESET_RESUME);
+ return 0;
+ }
+
+@@ -2062,10 +2132,10 @@ static int hub_reset_resume(struct usb_interface *intf)
+ *
+ * The USB host controller driver calls this function when its root hub
+ * is resumed and Vbus power has been interrupted or the controller
+- * has been reset. The routine marks @rhdev as having lost power. When
+- * the hub driver is resumed it will take notice; if CONFIG_USB_PERSIST
+- * is enabled then it will carry out power-session recovery, otherwise
+- * it will disconnect all the child devices.
++ * has been reset. The routine marks @rhdev as having lost power.
++ * When the hub driver is resumed it will take notice and carry out
++ * power-session recovery for all the "USB-PERSIST"-enabled child devices;
++ * the others will be disconnected.
+ */
+ void usb_root_hub_lost_power(struct usb_device *rhdev)
+ {
+@@ -2148,12 +2218,13 @@ static int hub_port_debounce(struct usb_hub *hub, int port1)
+ return portstatus;
+ }
+
+-static void ep0_reinit(struct usb_device *udev)
++void usb_ep0_reinit(struct usb_device *udev)
+ {
+ usb_disable_endpoint(udev, 0 + USB_DIR_IN);
+ usb_disable_endpoint(udev, 0 + USB_DIR_OUT);
+ usb_enable_endpoint(udev, &udev->ep0);
+ }
++EXPORT_SYMBOL_GPL(usb_ep0_reinit);
+
+ #define usb_sndaddr0pipe() (PIPE_CONTROL << 30)
+ #define usb_rcvaddr0pipe() ((PIPE_CONTROL << 30) | USB_DIR_IN)
+@@ -2172,9 +2243,10 @@ static int hub_set_address(struct usb_device *udev, int devnum)
+ USB_REQ_SET_ADDRESS, 0, devnum, 0,
+ NULL, 0, USB_CTRL_SET_TIMEOUT);
+ if (retval == 0) {
+- udev->devnum = devnum; /* Device now using proper address */
++ /* Device now using proper address. */
++ update_address(udev, devnum);
+ usb_set_device_state(udev, USB_STATE_ADDRESS);
+- ep0_reinit(udev);
++ usb_ep0_reinit(udev);
+ }
+ return retval;
+ }
+@@ -2356,26 +2428,33 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ #undef GET_DESCRIPTOR_BUFSIZE
+ }
+
+- for (j = 0; j < SET_ADDRESS_TRIES; ++j) {
+- retval = hub_set_address(udev, devnum);
+- if (retval >= 0)
++ /*
++ * If device is WUSB, we already assigned an
++ * unauthorized address in the Connect Ack sequence;
++ * authorization will assign the final address.
++ */
++ if (udev->wusb == 0) {
++ for (j = 0; j < SET_ADDRESS_TRIES; ++j) {
++ retval = hub_set_address(udev, devnum);
++ if (retval >= 0)
++ break;
++ msleep(200);
++ }
++ if (retval < 0) {
++ dev_err(&udev->dev,
++ "device not accepting address %d, error %d\n",
++ devnum, retval);
++ goto fail;
++ }
++
++ /* cope with hardware quirkiness:
++ * - let SET_ADDRESS settle, some device hardware wants it
++ * - read ep0 maxpacket even for high and low speed,
++ */
++ msleep(10);
++ if (USE_NEW_SCHEME(retry_counter))
+ break;
+- msleep(200);
+- }
+- if (retval < 0) {
+- dev_err(&udev->dev,
+- "device not accepting address %d, error %d\n",
+- devnum, retval);
+- goto fail;
+- }
+-
+- /* cope with hardware quirkiness:
+- * - let SET_ADDRESS settle, some device hardware wants it
+- * - read ep0 maxpacket even for high and low speed,
+- */
+- msleep(10);
+- if (USE_NEW_SCHEME(retry_counter))
+- break;
++ }
+
+ retval = usb_get_device_descriptor(udev, 8);
+ if (retval < 8) {
+@@ -2392,7 +2471,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ if (retval)
+ goto fail;
+
+- i = udev->descriptor.bMaxPacketSize0 == 0xff?
++ i = udev->descriptor.bMaxPacketSize0 == 0xff? /* wusb device? */
+ 512 : udev->descriptor.bMaxPacketSize0;
+ if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) {
+ if (udev->speed != USB_SPEED_FULL ||
+@@ -2403,7 +2482,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ }
+ dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
+ udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i);
+- ep0_reinit(udev);
++ usb_ep0_reinit(udev);
+ }
+
+ retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
+@@ -2420,7 +2499,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+ fail:
+ if (retval) {
+ hub_port_disable(hub, port1, 0);
+- udev->devnum = devnum; /* for disconnect processing */
++ update_address(udev, devnum); /* for disconnect processing */
+ }
+ mutex_unlock(&usb_address0_mutex);
+ return retval;
+@@ -2569,6 +2648,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ udev->speed = USB_SPEED_UNKNOWN;
+ udev->bus_mA = hub->mA_per_port;
+ udev->level = hdev->level + 1;
++ udev->wusb = hub_is_wusb(hub);
+
+ /* set the address */
+ choose_address(udev);
+@@ -2658,12 +2738,13 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ loop_disable:
+ hub_port_disable(hub, port1, 1);
+ loop:
+- ep0_reinit(udev);
++ usb_ep0_reinit(udev);
+ release_address(udev);
+ usb_put_dev(udev);
+ if ((status == -ENOTCONN) || (status == -ENOTSUPP))
+ break;
+ }
++ dev_err(hub_dev, "unable to enumerate USB device on port %d\n", port1);
+
+ done:
+ hub_port_disable(hub, port1, 1);
+@@ -2727,7 +2808,7 @@ static void hub_events(void)
+ /* If the hub has died, clean up after it */
+ if (hdev->state == USB_STATE_NOTATTACHED) {
+ hub->error = -ENODEV;
+- hub_pre_reset(intf);
++ hub_stop(hub);
+ goto loop;
+ }
+
+@@ -2873,11 +2954,6 @@ static void hub_events(void)
+
+ hub->activating = 0;
+
+- /* If this is a root hub, tell the HCD it's okay to
+- * re-enable port-change interrupts now. */
+- if (!hdev->parent && !hub->busy_bits[0])
+- usb_enable_root_hub_irq(hdev->bus);
+-
+ loop_autopm:
+ /* Allow autosuspend if we're not going to run again */
+ if (list_empty(&hub->event_list))
+@@ -2891,7 +2967,13 @@ loop:
+
+ static int hub_thread(void *__unused)
+ {
++ /* khubd needs to be freezable to avoid intefering with USB-PERSIST
++ * port handover. Otherwise it might see that a full-speed device
++ * was gone before the EHCI controller had handed its port over to
++ * the companion full-speed controller.
++ */
+ set_freezable();
++
+ do {
+ hub_events();
+ wait_event_freezable(khubd_wait,
+@@ -2960,16 +3042,36 @@ void usb_hub_cleanup(void)
+ usb_deregister(&hub_driver);
+ } /* usb_hub_cleanup() */
+
+-static int config_descriptors_changed(struct usb_device *udev)
++static int descriptors_changed(struct usb_device *udev,
++ struct usb_device_descriptor *old_device_descriptor)
+ {
+- unsigned index;
+- unsigned len = 0;
+- struct usb_config_descriptor *buf;
++ int changed = 0;
++ unsigned index;
++ unsigned serial_len = 0;
++ unsigned len;
++ unsigned old_length;
++ int length;
++ char *buf;
++
++ if (memcmp(&udev->descriptor, old_device_descriptor,
++ sizeof(*old_device_descriptor)) != 0)
++ return 1;
+
++ /* Since the idVendor, idProduct, and bcdDevice values in the
++ * device descriptor haven't changed, we will assume the
++ * Manufacturer and Product strings haven't changed either.
++ * But the SerialNumber string could be different (e.g., a
++ * different flash card of the same brand).
++ */
++ if (udev->serial)
++ serial_len = strlen(udev->serial) + 1;
++
++ len = serial_len;
+ for (index = 0; index < udev->descriptor.bNumConfigurations; index++) {
+- if (len < le16_to_cpu(udev->config[index].desc.wTotalLength))
+- len = le16_to_cpu(udev->config[index].desc.wTotalLength);
++ old_length = le16_to_cpu(udev->config[index].desc.wTotalLength);
++ len = max(len, old_length);
+ }
++
+ buf = kmalloc(len, GFP_NOIO);
+ if (buf == NULL) {
+ dev_err(&udev->dev, "no mem to re-read configs after reset\n");
+@@ -2977,25 +3079,41 @@ static int config_descriptors_changed(struct usb_device *udev)
+ return 1;
+ }
+ for (index = 0; index < udev->descriptor.bNumConfigurations; index++) {
+- int length;
+- int old_length = le16_to_cpu(udev->config[index].desc.wTotalLength);
+-
++ old_length = le16_to_cpu(udev->config[index].desc.wTotalLength);
+ length = usb_get_descriptor(udev, USB_DT_CONFIG, index, buf,
+ old_length);
+- if (length < old_length) {
++ if (length != old_length) {
+ dev_dbg(&udev->dev, "config index %d, error %d\n",
+ index, length);
++ changed = 1;
+ break;
+ }
+ if (memcmp (buf, udev->rawdescriptors[index], old_length)
+ != 0) {
+ dev_dbg(&udev->dev, "config index %d changed (#%d)\n",
+- index, buf->bConfigurationValue);
++ index,
++ ((struct usb_config_descriptor *) buf)->
++ bConfigurationValue);
++ changed = 1;
+ break;
+ }
+ }
++
++ if (!changed && serial_len) {
++ length = usb_string(udev, udev->descriptor.iSerialNumber,
++ buf, serial_len);
++ if (length + 1 != serial_len) {
++ dev_dbg(&udev->dev, "serial string error %d\n",
++ length);
++ changed = 1;
++ } else if (memcmp(buf, udev->serial, length) != 0) {
++ dev_dbg(&udev->dev, "serial string changed\n");
++ changed = 1;
++ }
++ }
++
+ kfree(buf);
+- return index != udev->descriptor.bNumConfigurations;
++ return changed;
+ }
+
+ /**
+@@ -3045,7 +3163,7 @@ int usb_reset_device(struct usb_device *udev)
+
+ if (!parent_hdev) {
+ /* this requires hcd-specific logic; see OHCI hc_restart() */
+- dev_dbg(&udev->dev, "%s for root hub!\n", __FUNCTION__);
++ dev_dbg(&udev->dev, "%s for root hub!\n", __func__);
+ return -EISDIR;
+ }
+ parent_hub = hdev_to_hub(parent_hdev);
+@@ -3055,21 +3173,18 @@ int usb_reset_device(struct usb_device *udev)
+
+ /* ep0 maxpacket size may change; let the HCD know about it.
+ * Other endpoints will be handled by re-enumeration. */
+- ep0_reinit(udev);
++ usb_ep0_reinit(udev);
+ ret = hub_port_init(parent_hub, udev, port1, i);
+ if (ret >= 0 || ret == -ENOTCONN || ret == -ENODEV)
+ break;
+ }
+ clear_bit(port1, parent_hub->busy_bits);
+- if (!parent_hdev->parent && !parent_hub->busy_bits[0])
+- usb_enable_root_hub_irq(parent_hdev->bus);
+
+ if (ret < 0)
+ goto re_enumerate;
+
+ /* Device might have changed firmware (DFU or similar) */
+- if (memcmp(&udev->descriptor, &descriptor, sizeof descriptor)
+- || config_descriptors_changed (udev)) {
++ if (descriptors_changed(udev, &descriptor)) {
+ dev_info(&udev->dev, "device firmware changed\n");
+ udev->descriptor = descriptor; /* for disconnect() calls */
+ goto re_enumerate;
+diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
+index 1551aed..2a116ce 100644
+--- a/drivers/usb/core/hub.h
++++ b/drivers/usb/core/hub.h
+@@ -41,9 +41,10 @@
+ */
+ #define USB_PORT_FEAT_CONNECTION 0
+ #define USB_PORT_FEAT_ENABLE 1
+-#define USB_PORT_FEAT_SUSPEND 2
++#define USB_PORT_FEAT_SUSPEND 2 /* L2 suspend */
+ #define USB_PORT_FEAT_OVER_CURRENT 3
+ #define USB_PORT_FEAT_RESET 4
++#define USB_PORT_FEAT_L1 5 /* L1 suspend */
+ #define USB_PORT_FEAT_POWER 8
+ #define USB_PORT_FEAT_LOWSPEED 9
+ #define USB_PORT_FEAT_HIGHSPEED 10
+@@ -54,6 +55,7 @@
+ #define USB_PORT_FEAT_C_RESET 20
+ #define USB_PORT_FEAT_TEST 21
+ #define USB_PORT_FEAT_INDICATOR 22
++#define USB_PORT_FEAT_C_PORT_L1 23
+
+ /*
+ * Hub Status and Hub Change results
+@@ -73,7 +75,8 @@ struct usb_port_status {
+ #define USB_PORT_STAT_SUSPEND 0x0004
+ #define USB_PORT_STAT_OVERCURRENT 0x0008
+ #define USB_PORT_STAT_RESET 0x0010
+-/* bits 5 to 7 are reserved */
++#define USB_PORT_STAT_L1 0x0020
++/* bits 6 to 7 are reserved */
+ #define USB_PORT_STAT_POWER 0x0100
+ #define USB_PORT_STAT_LOW_SPEED 0x0200
+ #define USB_PORT_STAT_HIGH_SPEED 0x0400
+@@ -91,6 +94,7 @@ struct usb_port_status {
+ #define USB_PORT_STAT_C_SUSPEND 0x0004
+ #define USB_PORT_STAT_C_OVERCURRENT 0x0008
+ #define USB_PORT_STAT_C_RESET 0x0010
++#define USB_PORT_STAT_C_L1 0x0020
+
+ /*
+ * wHubCharacteristics (masks)
+@@ -191,5 +195,6 @@ struct usb_tt_clear {
+ };
+
+ extern void usb_hub_tt_clear_buffer(struct usb_device *dev, int pipe);
++extern void usb_ep0_reinit(struct usb_device *);
+
+ #endif /* __LINUX_HUB_H */
+diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
+index 83a373e..8607846 100644
+--- a/drivers/usb/core/inode.c
++++ b/drivers/usb/core/inode.c
+@@ -463,13 +463,13 @@ static int usbfs_fill_super(struct super_block *sb, void *data, int silent)
+ inode = usbfs_get_inode(sb, S_IFDIR | 0755, 0);
+
+ if (!inode) {
+- dbg("%s: could not get inode!",__FUNCTION__);
++ dbg("%s: could not get inode!",__func__);
+ return -ENOMEM;
+ }
+
+ root = d_alloc_root(inode);
+ if (!root) {
+- dbg("%s: could not get root dentry!",__FUNCTION__);
++ dbg("%s: could not get root dentry!",__func__);
+ iput(inode);
+ return -ENOMEM;
+ }
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index c311f67..e819e53 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -312,7 +312,7 @@ static void sg_complete(struct urb *urb)
+ retval != -EBUSY)
+ dev_err(&io->dev->dev,
+ "%s, unlink --> %d\n",
+- __FUNCTION__, retval);
++ __func__, retval);
+ } else if (urb == io->urbs [i])
+ found = 1;
+ }
+@@ -550,7 +550,7 @@ void usb_sg_wait(struct usb_sg_request *io)
+ io->urbs[i]->dev = NULL;
+ io->urbs[i]->status = retval;
+ dev_dbg(&io->dev->dev, "%s, submit --> %d\n",
+- __FUNCTION__, retval);
++ __func__, retval);
+ usb_sg_cancel(io);
+ }
+ spin_lock_irq(&io->lock);
+@@ -600,7 +600,7 @@ void usb_sg_cancel(struct usb_sg_request *io)
+ retval = usb_unlink_urb(io->urbs [i]);
+ if (retval != -EINPROGRESS && retval != -EBUSY)
+ dev_warn(&io->dev->dev, "%s, unlink --> %d\n",
+- __FUNCTION__, retval);
++ __func__, retval);
+ }
+ spin_lock(&io->lock);
+ }
+@@ -784,7 +784,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
+ if (size <= 0 || !buf || !index)
+ return -EINVAL;
+ buf[0] = 0;
+- tbuf = kmalloc(256, GFP_KERNEL);
++ tbuf = kmalloc(256, GFP_NOIO);
+ if (!tbuf)
+ return -ENOMEM;
+
+@@ -1068,7 +1068,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
+ {
+ int i;
+
+- dev_dbg(&dev->dev, "%s nuking %s URBs\n", __FUNCTION__,
++ dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__,
+ skip_ep0 ? "non-ep0" : "all");
+ for (i = skip_ep0; i < 16; ++i) {
+ usb_disable_endpoint(dev, i);
+@@ -1089,8 +1089,8 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
+ continue;
+ dev_dbg(&dev->dev, "unregistering interface %s\n",
+ interface->dev.bus_id);
+- usb_remove_sysfs_intf_files(interface);
+ device_del(&interface->dev);
++ usb_remove_sysfs_intf_files(interface);
+ }
+
+ /* Now that the interfaces are unbound, nobody should
+@@ -1231,7 +1231,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
+ */
+
+ /* prevent submissions using previous endpoint settings */
+- if (iface->cur_altsetting != alt && device_is_registered(&iface->dev))
++ if (iface->cur_altsetting != alt)
+ usb_remove_sysfs_intf_files(iface);
+ usb_disable_interface(dev, iface);
+
+@@ -1330,8 +1330,7 @@ int usb_reset_configuration(struct usb_device *dev)
+ struct usb_interface *intf = config->interface[i];
+ struct usb_host_interface *alt;
+
+- if (device_is_registered(&intf->dev))
+- usb_remove_sysfs_intf_files(intf);
++ usb_remove_sysfs_intf_files(intf);
+ alt = usb_altnum_to_altsetting(intf, 0);
+
+ /* No altsetting 0? We'll assume the first altsetting.
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index dfc5418..2e20193 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -97,4 +97,18 @@ void usb_detect_quirks(struct usb_device *udev)
+ if (udev->descriptor.bDeviceClass != USB_CLASS_HUB)
+ udev->autosuspend_disabled = 1;
+ #endif
++
++ /* For the present, all devices default to USB-PERSIST enabled */
++#if 0 /* was: #ifdef CONFIG_PM */
++ /* Hubs are automatically enabled for USB-PERSIST */
++ if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
++ udev->persist_enabled = 1;
++
++#else
++ /* In the absence of PM, we can safely enable USB-PERSIST
++ * for all devices. It will affect things like hub resets
++ * and EMF-related port disables.
++ */
++ udev->persist_enabled = 1;
++#endif /* CONFIG_PM */
+ }
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index a37ccbd..5b20a60 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -180,11 +180,9 @@ show_urbnum(struct device *dev, struct device_attribute *attr, char *buf)
+ static DEVICE_ATTR(urbnum, S_IRUGO, show_urbnum, NULL);
+
+
+-#if defined(CONFIG_USB_PERSIST) || defined(CONFIG_USB_SUSPEND)
+-static const char power_group[] = "power";
+-#endif
++#ifdef CONFIG_PM
+
+-#ifdef CONFIG_USB_PERSIST
++static const char power_group[] = "power";
+
+ static ssize_t
+ show_persist(struct device *dev, struct device_attribute *attr, char *buf)
+@@ -222,12 +220,13 @@ static int add_persist_attributes(struct device *dev)
+ if (is_usb_device(dev)) {
+ struct usb_device *udev = to_usb_device(dev);
+
+- /* Hubs are automatically enabled for USB_PERSIST */
+- if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
+- udev->persist_enabled = 1;
+- rc = sysfs_add_file_to_group(&dev->kobj,
+- &dev_attr_persist.attr,
+- power_group);
++ /* Hubs are automatically enabled for USB_PERSIST,
++ * no point in creating the attribute file.
++ */
++ if (udev->descriptor.bDeviceClass != USB_CLASS_HUB)
++ rc = sysfs_add_file_to_group(&dev->kobj,
++ &dev_attr_persist.attr,
++ power_group);
+ }
+ return rc;
+ }
+@@ -238,13 +237,12 @@ static void remove_persist_attributes(struct device *dev)
+ &dev_attr_persist.attr,
+ power_group);
+ }
+-
+ #else
+
+ #define add_persist_attributes(dev) 0
+ #define remove_persist_attributes(dev) do {} while (0)
+
+-#endif /* CONFIG_USB_PERSIST */
++#endif /* CONFIG_PM */
+
+ #ifdef CONFIG_USB_SUSPEND
+
+diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
+index 9d7e632..c0b1ae2 100644
+--- a/drivers/usb/core/urb.c
++++ b/drivers/usb/core/urb.c
+@@ -334,7 +334,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
+ dev_dbg(&dev->dev,
+ "bogus endpoint ep%d%s in %s (bad maxpacket %d)\n",
+ usb_endpoint_num(&ep->desc), is_out ? "out" : "in",
+- __FUNCTION__, max);
++ __func__, max);
+ return -EMSGSIZE;
+ }
+
+@@ -590,6 +590,30 @@ void usb_kill_anchored_urbs(struct usb_anchor *anchor)
+ EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs);
+
+ /**
++ * usb_unlink_anchored_urbs - asynchronously cancel transfer requests en masse
++ * @anchor: anchor the requests are bound to
++ *
++ * this allows all outstanding URBs to be unlinked starting
++ * from the back of the queue. This function is asynchronous.
++ * The unlinking is just tiggered. It may happen after this
++ * function has returned.
++ */
++void usb_unlink_anchored_urbs(struct usb_anchor *anchor)
++{
++ struct urb *victim;
++
++ spin_lock_irq(&anchor->lock);
++ while (!list_empty(&anchor->urb_list)) {
++ victim = list_entry(anchor->urb_list.prev, struct urb,
++ anchor_list);
++ /* this will unanchor the URB */
++ usb_unlink_urb(victim);
++ }
++ spin_unlock_irq(&anchor->lock);
++}
++EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs);
++
++/**
+ * usb_wait_anchor_empty_timeout - wait for an anchor to be unused
+ * @anchor: the anchor you want to become unused
+ * @timeout: how long you are willing to wait in milliseconds
+diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
+index 2375194..1bf8ccb 100644
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -114,13 +114,11 @@ static inline int is_usb_device_driver(struct device_driver *drv)
+ static inline void mark_active(struct usb_interface *f)
+ {
+ f->is_active = 1;
+- f->dev.power.power_state.event = PM_EVENT_ON;
+ }
+
+ static inline void mark_quiesced(struct usb_interface *f)
+ {
+ f->is_active = 0;
+- f->dev.power.power_state.event = PM_EVENT_SUSPEND;
+ }
+
+ static inline int is_active(const struct usb_interface *f)
+diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
+index 6f45dd6..f7b5465 100644
+--- a/drivers/usb/gadget/Kconfig
++++ b/drivers/usb/gadget/Kconfig
+@@ -44,8 +44,8 @@ menuconfig USB_GADGET
+ if USB_GADGET
+
+ config USB_GADGET_DEBUG
+- boolean "Debugging messages"
+- depends on USB_GADGET && DEBUG_KERNEL && EXPERIMENTAL
++ boolean "Debugging messages (DEVELOPMENT)"
++ depends on USB_GADGET && DEBUG_KERNEL
+ help
+ Many controller and gadget drivers will print some debugging
+ messages if you use this option to ask for those messages.
+@@ -58,7 +58,7 @@ config USB_GADGET_DEBUG
+ production build.
+
+ config USB_GADGET_DEBUG_FILES
+- boolean "Debugging information files"
++ boolean "Debugging information files (DEVELOPMENT)"
+ depends on USB_GADGET && PROC_FS
+ help
+ Some of the drivers in the "gadget" framework can expose
+@@ -69,7 +69,7 @@ config USB_GADGET_DEBUG_FILES
+ here. If in doubt, or to conserve kernel memory, say "N".
+
+ config USB_GADGET_DEBUG_FS
+- boolean "Debugging information files in debugfs"
++ boolean "Debugging information files in debugfs (DEVELOPMENT)"
+ depends on USB_GADGET && DEBUG_FS
+ help
+ Some of the drivers in the "gadget" framework can expose
+@@ -118,10 +118,10 @@ config USB_AMD5536UDC
+ config USB_GADGET_ATMEL_USBA
+ boolean "Atmel USBA"
+ select USB_GADGET_DUALSPEED
+- depends on AVR32
++ depends on AVR32 || ARCH_AT91CAP9
+ help
+ USBA is the integrated high-speed USB Device controller on
+- the AT32AP700x processors from Atmel.
++ the AT32AP700x and AT91CAP9 processors from Atmel.
+
+ config USB_ATMEL_USBA
+ tristate
+@@ -337,7 +337,7 @@ config USB_AT91
+
+ config USB_GADGET_DUMMY_HCD
+ boolean "Dummy HCD (DEVELOPMENT)"
+- depends on (USB=y || (USB=m && USB_GADGET=m)) && EXPERIMENTAL
++ depends on USB=y || (USB=m && USB_GADGET=m)
+ select USB_GADGET_DUALSPEED
+ help
+ This host controller driver emulates USB, looping all data transfer
+@@ -404,7 +404,6 @@ choice
+
+ config USB_ZERO
+ tristate "Gadget Zero (DEVELOPMENT)"
+- depends on EXPERIMENTAL
+ help
+ Gadget Zero is a two-configuration device. It either sinks and
+ sources bulk data; or it loops back a configurable number of
+@@ -468,8 +467,8 @@ config USB_ETH
+ dynamically linked module called "g_ether".
+
+ config USB_ETH_RNDIS
+- bool "RNDIS support (EXPERIMENTAL)"
+- depends on USB_ETH && EXPERIMENTAL
++ bool "RNDIS support"
++ depends on USB_ETH
+ default y
+ help
+ Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol,
+@@ -495,6 +494,9 @@ config USB_GADGETFS
+ All endpoints, transfer speeds, and transfer types supported by
+ the hardware are available, through read() and write() calls.
+
++ Currently, this option is still labelled as EXPERIMENTAL because
++ of existing race conditions in the underlying in-kernel AIO core.
++
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "gadgetfs".
+
+diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
+index b663f23..fc6f348 100644
+--- a/drivers/usb/gadget/amd5536udc.c
++++ b/drivers/usb/gadget/amd5536udc.c
+@@ -3248,6 +3248,8 @@ static int udc_pci_probe(
+
+ /* pci setup */
+ if (pci_enable_device(pdev) < 0) {
++ kfree(dev);
++ dev = 0;
+ retval = -ENODEV;
+ goto finished;
+ }
+@@ -3259,6 +3261,8 @@ static int udc_pci_probe(
+
+ if (!request_mem_region(resource, len, name)) {
+ dev_dbg(&pdev->dev, "pci device used already\n");
++ kfree(dev);
++ dev = 0;
+ retval = -EBUSY;
+ goto finished;
+ }
+@@ -3267,18 +3271,24 @@ static int udc_pci_probe(
+ dev->virt_addr = ioremap_nocache(resource, len);
+ if (dev->virt_addr == NULL) {
+ dev_dbg(&pdev->dev, "start address cannot be mapped\n");
++ kfree(dev);
++ dev = 0;
+ retval = -EFAULT;
+ goto finished;
+ }
+
+ if (!pdev->irq) {
+ dev_err(&dev->pdev->dev, "irq not set\n");
++ kfree(dev);
++ dev = 0;
+ retval = -ENODEV;
+ goto finished;
+ }
+
+ if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) {
+ dev_dbg(&dev->pdev->dev, "request_irq(%d) fail\n", pdev->irq);
++ kfree(dev);
++ dev = 0;
+ retval = -EBUSY;
+ goto finished;
+ }
+diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
+index fd15ced..9b913af 100644
+--- a/drivers/usb/gadget/at91_udc.c
++++ b/drivers/usb/gadget/at91_udc.c
+@@ -389,6 +389,7 @@ static int write_fifo(struct at91_ep *ep, struct at91_request *req)
+ u32 csr = __raw_readl(creg);
+ u8 __iomem *dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0));
+ unsigned total, count, is_last;
++ u8 *buf;
+
+ /*
+ * TODO: allow for writing two packets to the fifo ... that'll
+@@ -413,6 +414,8 @@ static int write_fifo(struct at91_ep *ep, struct at91_request *req)
+ return 0;
+ }
+
++ buf = req->req.buf + req->req.actual;
++ prefetch(buf);
+ total = req->req.length - req->req.actual;
+ if (ep->ep.maxpacket < total) {
+ count = ep->ep.maxpacket;
+@@ -435,7 +438,7 @@ static int write_fifo(struct at91_ep *ep, struct at91_request *req)
+ * recover when the actual bytecount matters (e.g. for USB Test
+ * and Measurement Class devices).
+ */
+- __raw_writesb(dreg, req->req.buf + req->req.actual, count);
++ __raw_writesb(dreg, buf, count);
+ csr &= ~SET_FX;
+ csr |= CLR_FX | AT91_UDP_TXPKTRDY;
+ __raw_writel(csr, creg);
+@@ -457,7 +460,7 @@ static void nuke(struct at91_ep *ep, int status)
+ if (list_empty(&ep->queue))
+ return;
+
+- VDBG("%s %s\n", __FUNCTION__, ep->ep.name);
++ VDBG("%s %s\n", __func__, ep->ep.name);
+ while (!list_empty(&ep->queue)) {
+ req = list_entry(ep->queue.next, struct at91_request, queue);
+ done(ep, req, status);
+@@ -792,7 +795,7 @@ static int at91_wakeup(struct usb_gadget *gadget)
+ int status = -EINVAL;
+ unsigned long flags;
+
+- DBG("%s\n", __FUNCTION__ );
++ DBG("%s\n", __func__ );
+ local_irq_save(flags);
+
+ if (!udc->clocked || !udc->suspended)
+diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
+index b0db4c3..e756023 100644
+--- a/drivers/usb/gadget/atmel_usba_udc.c
++++ b/drivers/usb/gadget/atmel_usba_udc.c
+@@ -18,6 +18,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/usb/ch9.h>
+ #include <linux/usb/gadget.h>
++#include <linux/usb/atmel_usba_udc.h>
+ #include <linux/delay.h>
+
+ #include <asm/gpio.h>
+@@ -27,6 +28,7 @@
+
+
+ static struct usba_udc the_udc;
++static struct usba_ep *usba_ep;
+
+ #ifdef CONFIG_USB_GADGET_DEBUG_FS
+ #include <linux/debugfs.h>
+@@ -324,53 +326,28 @@ static int vbus_is_present(struct usba_udc *udc)
+ return 1;
+ }
+
+-static void copy_to_fifo(void __iomem *fifo, const void *buf, int len)
++#if defined(CONFIG_AVR32)
++
++static void toggle_bias(int is_on)
+ {
+- unsigned long tmp;
+-
+- DBG(DBG_FIFO, "copy to FIFO (len %d):\n", len);
+- for (; len > 0; len -= 4, buf += 4, fifo += 4) {
+- tmp = *(unsigned long *)buf;
+- if (len >= 4) {
+- DBG(DBG_FIFO, " -> %08lx\n", tmp);
+- __raw_writel(tmp, fifo);
+- } else {
+- do {
+- DBG(DBG_FIFO, " -> %02lx\n", tmp >> 24);
+- __raw_writeb(tmp >> 24, fifo);
+- fifo++;
+- tmp <<= 8;
+- } while (--len);
+- break;
+- }
+- }
+ }
+
+-static void copy_from_fifo(void *buf, void __iomem *fifo, int len)
++#elif defined(CONFIG_ARCH_AT91)
++
++#include <asm/arch/at91_pmc.h>
++
++static void toggle_bias(int is_on)
+ {
+- union {
+- unsigned long *w;
+- unsigned char *b;
+- } p;
+- unsigned long tmp;
+-
+- DBG(DBG_FIFO, "copy from FIFO (len %d):\n", len);
+- for (p.w = buf; len > 0; len -= 4, p.w++, fifo += 4) {
+- if (len >= 4) {
+- tmp = __raw_readl(fifo);
+- *p.w = tmp;
+- DBG(DBG_FIFO, " -> %08lx\n", tmp);
+- } else {
+- do {
+- tmp = __raw_readb(fifo);
+- *p.b = tmp;
+- DBG(DBG_FIFO, " -> %02lx\n", tmp);
+- fifo++, p.b++;
+- } while (--len);
+- }
+- }
++ unsigned int uckr = at91_sys_read(AT91_CKGR_UCKR);
++
++ if (is_on)
++ at91_sys_write(AT91_CKGR_UCKR, uckr | AT91_PMC_BIASEN);
++ else
++ at91_sys_write(AT91_CKGR_UCKR, uckr & ~(AT91_PMC_BIASEN));
+ }
+
++#endif /* CONFIG_ARCH_AT91 */
++
+ static void next_fifo_transaction(struct usba_ep *ep, struct usba_request *req)
+ {
+ unsigned int transaction_len;
+@@ -387,7 +364,7 @@ static void next_fifo_transaction(struct usba_ep *ep, struct usba_request *req)
+ ep->ep.name, req, transaction_len,
+ req->last_transaction ? ", done" : "");
+
+- copy_to_fifo(ep->fifo, req->req.buf + req->req.actual, transaction_len);
++ memcpy_toio(ep->fifo, req->req.buf + req->req.actual, transaction_len);
+ usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
+ req->req.actual += transaction_len;
+ }
+@@ -476,7 +453,7 @@ static void receive_data(struct usba_ep *ep)
+ bytecount = req->req.length - req->req.actual;
+ }
+
+- copy_from_fifo(req->req.buf + req->req.actual,
++ memcpy_fromio(req->req.buf + req->req.actual,
+ ep->fifo, bytecount);
+ req->req.actual += bytecount;
+
+@@ -1029,33 +1006,6 @@ static const struct usb_gadget_ops usba_udc_ops = {
+ .set_selfpowered = usba_udc_set_selfpowered,
+ };
+
+-#define EP(nam, idx, maxpkt, maxbk, dma, isoc) \
+-{ \
+- .ep = { \
+- .ops = &usba_ep_ops, \
+- .name = nam, \
+- .maxpacket = maxpkt, \
+- }, \
+- .udc = &the_udc, \
+- .queue = LIST_HEAD_INIT(usba_ep[idx].queue), \
+- .fifo_size = maxpkt, \
+- .nr_banks = maxbk, \
+- .index = idx, \
+- .can_dma = dma, \
+- .can_isoc = isoc, \
+-}
+-
+-static struct usba_ep usba_ep[] = {
+- EP("ep0", 0, 64, 1, 0, 0),
+- EP("ep1in-bulk", 1, 512, 2, 1, 1),
+- EP("ep2out-bulk", 2, 512, 2, 1, 1),
+- EP("ep3in-int", 3, 64, 3, 1, 0),
+- EP("ep4out-int", 4, 64, 3, 1, 0),
+- EP("ep5in-iso", 5, 1024, 3, 1, 1),
+- EP("ep6out-iso", 6, 1024, 3, 1, 1),
+-};
+-#undef EP
+-
+ static struct usb_endpoint_descriptor usba_ep0_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+@@ -1074,7 +1024,6 @@ static void nop_release(struct device *dev)
+ static struct usba_udc the_udc = {
+ .gadget = {
+ .ops = &usba_udc_ops,
+- .ep0 = &usba_ep[0].ep,
+ .ep_list = LIST_HEAD_INIT(the_udc.gadget.ep_list),
+ .is_dualspeed = 1,
+ .name = "atmel_usba_udc",
+@@ -1231,7 +1180,7 @@ static int do_test_mode(struct usba_udc *udc)
+ } else {
+ usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE);
+ usba_writel(udc, TST, USBA_TST_PKT_MODE);
+- copy_to_fifo(ep->fifo, test_packet_buffer,
++ memcpy_toio(ep->fifo, test_packet_buffer,
+ sizeof(test_packet_buffer));
+ usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
+ dev_info(dev, "Entering Test_Packet mode...\n");
+@@ -1530,13 +1479,13 @@ restart:
+ DBG(DBG_HW, "Packet length: %u\n", pkt_len);
+ if (pkt_len != sizeof(crq)) {
+ pr_warning("udc: Invalid packet length %u "
+- "(expected %lu)\n", pkt_len, sizeof(crq));
++ "(expected %zu)\n", pkt_len, sizeof(crq));
+ set_protocol_stall(udc, ep);
+ return;
+ }
+
+ DBG(DBG_FIFO, "Copying ctrl request from 0x%p:\n", ep->fifo);
+- copy_from_fifo(crq.data, ep->fifo, sizeof(crq));
++ memcpy_fromio(crq.data, ep->fifo, sizeof(crq));
+
+ /* Free up one bank in the FIFO so that we can
+ * generate or receive a reply right away. */
+@@ -1688,6 +1637,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
+ DBG(DBG_INT, "irq, status=%#08x\n", status);
+
+ if (status & USBA_DET_SUSPEND) {
++ toggle_bias(0);
+ usba_writel(udc, INT_CLR, USBA_DET_SUSPEND);
+ DBG(DBG_BUS, "Suspend detected\n");
+ if (udc->gadget.speed != USB_SPEED_UNKNOWN
+@@ -1699,6 +1649,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
+ }
+
+ if (status & USBA_WAKE_UP) {
++ toggle_bias(1);
+ usba_writel(udc, INT_CLR, USBA_WAKE_UP);
+ DBG(DBG_BUS, "Wake Up CPU detected\n");
+ }
+@@ -1792,12 +1743,14 @@ static irqreturn_t usba_vbus_irq(int irq, void *devid)
+ vbus = gpio_get_value(udc->vbus_pin);
+ if (vbus != udc->vbus_prev) {
+ if (vbus) {
+- usba_writel(udc, CTRL, USBA_EN_USBA);
++ toggle_bias(1);
++ usba_writel(udc, CTRL, USBA_ENABLE_MASK);
+ usba_writel(udc, INT_ENB, USBA_END_OF_RESET);
+ } else {
+ udc->gadget.speed = USB_SPEED_UNKNOWN;
+ reset_all_endpoints(udc);
+- usba_writel(udc, CTRL, 0);
++ toggle_bias(0);
++ usba_writel(udc, CTRL, USBA_DISABLE_MASK);
+ spin_unlock(&udc->lock);
+ udc->driver->disconnect(&udc->gadget);
+ spin_lock(&udc->lock);
+@@ -1850,7 +1803,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+ /* If Vbus is present, enable the controller and wait for reset */
+ spin_lock_irqsave(&udc->lock, flags);
+ if (vbus_is_present(udc) && udc->vbus_prev == 0) {
+- usba_writel(udc, CTRL, USBA_EN_USBA);
++ toggle_bias(1);
++ usba_writel(udc, CTRL, USBA_ENABLE_MASK);
+ usba_writel(udc, INT_ENB, USBA_END_OF_RESET);
+ }
+ spin_unlock_irqrestore(&udc->lock, flags);
+@@ -1883,7 +1837,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+ spin_unlock_irqrestore(&udc->lock, flags);
+
+ /* This will also disable the DP pullup */
+- usba_writel(udc, CTRL, 0);
++ toggle_bias(0);
++ usba_writel(udc, CTRL, USBA_DISABLE_MASK);
+
+ driver->unbind(&udc->gadget);
+ udc->gadget.dev.driver = NULL;
+@@ -1908,7 +1863,7 @@ static int __init usba_udc_probe(struct platform_device *pdev)
+
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, CTRL_IOMEM_ID);
+ fifo = platform_get_resource(pdev, IORESOURCE_MEM, FIFO_IOMEM_ID);
+- if (!regs || !fifo)
++ if (!regs || !fifo || !pdata)
+ return -ENXIO;
+
+ irq = platform_get_irq(pdev, 0);
+@@ -1953,19 +1908,48 @@ static int __init usba_udc_probe(struct platform_device *pdev)
+
+ /* Make sure we start from a clean slate */
+ clk_enable(pclk);
+- usba_writel(udc, CTRL, 0);
++ toggle_bias(0);
++ usba_writel(udc, CTRL, USBA_DISABLE_MASK);
+ clk_disable(pclk);
+
++ usba_ep = kmalloc(sizeof(struct usba_ep) * pdata->num_ep,
++ GFP_KERNEL);
++ if (!usba_ep)
++ goto err_alloc_ep;
++
++ the_udc.gadget.ep0 = &usba_ep[0].ep;
++
+ INIT_LIST_HEAD(&usba_ep[0].ep.ep_list);
+ usba_ep[0].ep_regs = udc->regs + USBA_EPT_BASE(0);
+ usba_ep[0].dma_regs = udc->regs + USBA_DMA_BASE(0);
+ usba_ep[0].fifo = udc->fifo + USBA_FIFO_BASE(0);
+- for (i = 1; i < ARRAY_SIZE(usba_ep); i++) {
++ usba_ep[0].ep.ops = &usba_ep_ops;
++ usba_ep[0].ep.name = pdata->ep[0].name;
++ usba_ep[0].ep.maxpacket = pdata->ep[0].fifo_size;
++ usba_ep[0].udc = &the_udc;
++ INIT_LIST_HEAD(&usba_ep[0].queue);
++ usba_ep[0].fifo_size = pdata->ep[0].fifo_size;
++ usba_ep[0].nr_banks = pdata->ep[0].nr_banks;
++ usba_ep[0].index = pdata->ep[0].index;
++ usba_ep[0].can_dma = pdata->ep[0].can_dma;
++ usba_ep[0].can_isoc = pdata->ep[0].can_isoc;
++
++ for (i = 1; i < pdata->num_ep; i++) {
+ struct usba_ep *ep = &usba_ep[i];
+
+ ep->ep_regs = udc->regs + USBA_EPT_BASE(i);
+ ep->dma_regs = udc->regs + USBA_DMA_BASE(i);
+ ep->fifo = udc->fifo + USBA_FIFO_BASE(i);
++ ep->ep.ops = &usba_ep_ops;
++ ep->ep.name = pdata->ep[i].name;
++ ep->ep.maxpacket = pdata->ep[i].fifo_size;
++ ep->udc = &the_udc;
++ INIT_LIST_HEAD(&ep->queue);
++ ep->fifo_size = pdata->ep[i].fifo_size;
++ ep->nr_banks = pdata->ep[i].nr_banks;
++ ep->index = pdata->ep[i].index;
++ ep->can_dma = pdata->ep[i].can_dma;
++ ep->can_isoc = pdata->ep[i].can_isoc;
+
+ list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
+ }
+@@ -1984,7 +1968,7 @@ static int __init usba_udc_probe(struct platform_device *pdev)
+ goto err_device_add;
+ }
+
+- if (pdata && pdata->vbus_pin != GPIO_PIN_NONE) {
++ if (pdata->vbus_pin >= 0) {
+ if (!gpio_request(pdata->vbus_pin, "atmel_usba_udc")) {
+ udc->vbus_pin = pdata->vbus_pin;
+
+@@ -2004,7 +1988,7 @@ static int __init usba_udc_probe(struct platform_device *pdev)
+ }
+
+ usba_init_debugfs(udc);
+- for (i = 1; i < ARRAY_SIZE(usba_ep); i++)
++ for (i = 1; i < pdata->num_ep; i++)
+ usba_ep_init_debugfs(udc, &usba_ep[i]);
+
+ return 0;
+@@ -2012,6 +1996,8 @@ static int __init usba_udc_probe(struct platform_device *pdev)
+ err_device_add:
+ free_irq(irq, udc);
+ err_request_irq:
++ kfree(usba_ep);
++err_alloc_ep:
+ iounmap(udc->fifo);
+ err_map_fifo:
+ iounmap(udc->regs);
+@@ -2029,10 +2015,11 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
+ {
+ struct usba_udc *udc;
+ int i;
++ struct usba_platform_data *pdata = pdev->dev.platform_data;
+
+ udc = platform_get_drvdata(pdev);
+
+- for (i = 1; i < ARRAY_SIZE(usba_ep); i++)
++ for (i = 1; i < pdata->num_ep; i++)
+ usba_ep_cleanup_debugfs(&usba_ep[i]);
+ usba_cleanup_debugfs(udc);
+
+@@ -2040,6 +2027,7 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
+ gpio_free(udc->vbus_pin);
+
+ free_irq(udc->irq, udc);
++ kfree(usba_ep);
+ iounmap(udc->fifo);
+ iounmap(udc->regs);
+ clk_put(udc->hclk);
+diff --git a/drivers/usb/gadget/atmel_usba_udc.h b/drivers/usb/gadget/atmel_usba_udc.h
+index 08bf6f9..f7baea3 100644
+--- a/drivers/usb/gadget/atmel_usba_udc.h
++++ b/drivers/usb/gadget/atmel_usba_udc.h
+@@ -41,6 +41,15 @@
+ #define USBA_EN_USBA (1 << 8)
+ #define USBA_DETACH (1 << 9)
+ #define USBA_REMOTE_WAKE_UP (1 << 10)
++#define USBA_PULLD_DIS (1 << 11)
++
++#if defined(CONFIG_AVR32)
++#define USBA_ENABLE_MASK USBA_EN_USBA
++#define USBA_DISABLE_MASK 0
++#elif defined(CONFIG_ARCH_AT91)
++#define USBA_ENABLE_MASK (USBA_EN_USBA | USBA_PULLD_DIS)
++#define USBA_DISABLE_MASK USBA_DETACH
++#endif /* CONFIG_ARCH_AT91 */
+
+ /* Bitfields in FNUM */
+ #define USBA_MICRO_FRAME_NUM_OFFSET 0
+diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
+index cbe4453..6629310 100644
+--- a/drivers/usb/gadget/dummy_hcd.c
++++ b/drivers/usb/gadget/dummy_hcd.c
+@@ -365,16 +365,14 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
+ case USB_SPEED_HIGH:
+ if (max == 512)
+ break;
+- /* conserve return statements */
+- default:
+- switch (max) {
+- case 8: case 16: case 32: case 64:
++ goto done;
++ case USB_SPEED_FULL:
++ if (max == 8 || max == 16 || max == 32 || max == 64)
+ /* we'll fake any legal size */
+ break;
+- default:
+- case USB_SPEED_LOW:
+- goto done;
+- }
++ /* save a return statement */
++ default:
++ goto done;
+ }
+ break;
+ case USB_ENDPOINT_XFER_INT:
+@@ -894,13 +892,12 @@ static int dummy_udc_suspend (struct platform_device *pdev, pm_message_t state)
+ {
+ struct dummy *dum = platform_get_drvdata(pdev);
+
+- dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
++ dev_dbg (&pdev->dev, "%s\n", __func__);
+ spin_lock_irq (&dum->lock);
+ dum->udc_suspended = 1;
+ set_link_state (dum);
+ spin_unlock_irq (&dum->lock);
+
+- pdev->dev.power.power_state = state;
+ usb_hcd_poll_rh_status (dummy_to_hcd (dum));
+ return 0;
+ }
+@@ -909,13 +906,12 @@ static int dummy_udc_resume (struct platform_device *pdev)
+ {
+ struct dummy *dum = platform_get_drvdata(pdev);
+
+- dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
++ dev_dbg (&pdev->dev, "%s\n", __func__);
+ spin_lock_irq (&dum->lock);
+ dum->udc_suspended = 0;
+ set_link_state (dum);
+ spin_unlock_irq (&dum->lock);
+
+- pdev->dev.power.power_state = PMSG_ON;
+ usb_hcd_poll_rh_status (dummy_to_hcd (dum));
+ return 0;
+ }
+@@ -1711,7 +1707,7 @@ static int dummy_bus_suspend (struct usb_hcd *hcd)
+ {
+ struct dummy *dum = hcd_to_dummy (hcd);
+
+- dev_dbg (&hcd->self.root_hub->dev, "%s\n", __FUNCTION__);
++ dev_dbg (&hcd->self.root_hub->dev, "%s\n", __func__);
+
+ spin_lock_irq (&dum->lock);
+ dum->rh_state = DUMMY_RH_SUSPENDED;
+@@ -1726,7 +1722,7 @@ static int dummy_bus_resume (struct usb_hcd *hcd)
+ struct dummy *dum = hcd_to_dummy (hcd);
+ int rc = 0;
+
+- dev_dbg (&hcd->self.root_hub->dev, "%s\n", __FUNCTION__);
++ dev_dbg (&hcd->self.root_hub->dev, "%s\n", __func__);
+
+ spin_lock_irq (&dum->lock);
+ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+@@ -1900,7 +1896,7 @@ static int dummy_hcd_suspend (struct platform_device *pdev, pm_message_t state)
+ struct dummy *dum;
+ int rc = 0;
+
+- dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
++ dev_dbg (&pdev->dev, "%s\n", __func__);
+
+ hcd = platform_get_drvdata (pdev);
+ dum = hcd_to_dummy (hcd);
+@@ -1916,7 +1912,7 @@ static int dummy_hcd_resume (struct platform_device *pdev)
+ {
+ struct usb_hcd *hcd;
+
+- dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
++ dev_dbg (&pdev->dev, "%s\n", __func__);
+
+ hcd = platform_get_drvdata (pdev);
+ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+@@ -1937,69 +1933,57 @@ static struct platform_driver dummy_hcd_driver = {
+
+ /*-------------------------------------------------------------------------*/
+
+-/* These don't need to do anything because the pdev structures are
+- * statically allocated. */
+-static void
+-dummy_udc_release (struct device *dev) {}
+-
+-static void
+-dummy_hcd_release (struct device *dev) {}
+-
+-static struct platform_device the_udc_pdev = {
+- .name = (char *) gadget_name,
+- .id = -1,
+- .dev = {
+- .release = dummy_udc_release,
+- },
+-};
+-
+-static struct platform_device the_hcd_pdev = {
+- .name = (char *) driver_name,
+- .id = -1,
+- .dev = {
+- .release = dummy_hcd_release,
+- },
+-};
++static struct platform_device *the_udc_pdev;
++static struct platform_device *the_hcd_pdev;
+
+ static int __init init (void)
+ {
+- int retval;
++ int retval = -ENOMEM;
+
+ if (usb_disabled ())
+ return -ENODEV;
+
+- retval = platform_driver_register (&dummy_hcd_driver);
+- if (retval < 0)
++ the_hcd_pdev = platform_device_alloc(driver_name, -1);
++ if (!the_hcd_pdev)
+ return retval;
++ the_udc_pdev = platform_device_alloc(gadget_name, -1);
++ if (!the_udc_pdev)
++ goto err_alloc_udc;
+
+- retval = platform_driver_register (&dummy_udc_driver);
++ retval = platform_driver_register(&dummy_hcd_driver);
++ if (retval < 0)
++ goto err_register_hcd_driver;
++ retval = platform_driver_register(&dummy_udc_driver);
+ if (retval < 0)
+ goto err_register_udc_driver;
+
+- retval = platform_device_register (&the_hcd_pdev);
++ retval = platform_device_add(the_hcd_pdev);
+ if (retval < 0)
+- goto err_register_hcd;
+-
+- retval = platform_device_register (&the_udc_pdev);
++ goto err_add_hcd;
++ retval = platform_device_add(the_udc_pdev);
+ if (retval < 0)
+- goto err_register_udc;
++ goto err_add_udc;
+ return retval;
+
+-err_register_udc:
+- platform_device_unregister (&the_hcd_pdev);
+-err_register_hcd:
+- platform_driver_unregister (&dummy_udc_driver);
++err_add_udc:
++ platform_device_del(the_hcd_pdev);
++err_add_hcd:
++ platform_driver_unregister(&dummy_udc_driver);
+ err_register_udc_driver:
+- platform_driver_unregister (&dummy_hcd_driver);
++ platform_driver_unregister(&dummy_hcd_driver);
++err_register_hcd_driver:
++ platform_device_put(the_udc_pdev);
++err_alloc_udc:
++ platform_device_put(the_hcd_pdev);
+ return retval;
+ }
+ module_init (init);
+
+ static void __exit cleanup (void)
+ {
+- platform_device_unregister (&the_udc_pdev);
+- platform_device_unregister (&the_hcd_pdev);
+- platform_driver_unregister (&dummy_udc_driver);
+- platform_driver_unregister (&dummy_hcd_driver);
++ platform_device_unregister(the_udc_pdev);
++ platform_device_unregister(the_hcd_pdev);
++ platform_driver_unregister(&dummy_udc_driver);
++ platform_driver_unregister(&dummy_hcd_driver);
+ }
+ module_exit (cleanup);
+diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
+index f9d0710..8bdad22 100644
+--- a/drivers/usb/gadget/epautoconf.c
++++ b/drivers/usb/gadget/epautoconf.c
+@@ -34,12 +34,12 @@
+
+
+ /* we must assign addresses for configurable endpoints (like net2280) */
+-static __devinitdata unsigned epnum;
++static __initdata unsigned epnum;
+
+ // #define MANY_ENDPOINTS
+ #ifdef MANY_ENDPOINTS
+ /* more than 15 configurable endpoints */
+-static __devinitdata unsigned in_epnum;
++static __initdata unsigned in_epnum;
+ #endif
+
+
+@@ -59,7 +59,7 @@ static __devinitdata unsigned in_epnum;
+ * NOTE: each endpoint is unidirectional, as specified by its USB
+ * descriptor; and isn't specific to a configuration or altsetting.
+ */
+-static int __devinit
++static int __init
+ ep_matches (
+ struct usb_gadget *gadget,
+ struct usb_ep *ep,
+@@ -186,7 +186,7 @@ ep_matches (
+ return 1;
+ }
+
+-static struct usb_ep * __devinit
++static struct usb_ep * __init
+ find_ep (struct usb_gadget *gadget, const char *name)
+ {
+ struct usb_ep *ep;
+@@ -228,7 +228,7 @@ find_ep (struct usb_gadget *gadget, const char *name)
+ *
+ * On failure, this returns a null endpoint descriptor.
+ */
+-struct usb_ep * __devinit usb_ep_autoconfig (
++struct usb_ep * __init usb_ep_autoconfig (
+ struct usb_gadget *gadget,
+ struct usb_endpoint_descriptor *desc
+ )
+@@ -295,7 +295,7 @@ struct usb_ep * __devinit usb_ep_autoconfig (
+ * state such as ep->driver_data and the record of assigned endpoints
+ * used by usb_ep_autoconfig().
+ */
+-void __devinit usb_ep_autoconfig_reset (struct usb_gadget *gadget)
++void __init usb_ep_autoconfig_reset (struct usb_gadget *gadget)
+ {
+ struct usb_ep *ep;
+
+diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
+index e998723..bb93bdd 100644
+--- a/drivers/usb/gadget/ether.c
++++ b/drivers/usb/gadget/ether.c
+@@ -1102,7 +1102,7 @@ static void eth_reset_config (struct eth_dev *dev)
+ if (dev->config == 0)
+ return;
+
+- DEBUG (dev, "%s\n", __FUNCTION__);
++ DEBUG (dev, "%s\n", __func__);
+
+ netif_stop_queue (dev->net);
+ netif_carrier_off (dev->net);
+@@ -1263,7 +1263,7 @@ static void issue_start_status (struct eth_dev *dev)
+ struct usb_cdc_notification *event;
+ int value;
+
+- DEBUG (dev, "%s, flush old status first\n", __FUNCTION__);
++ DEBUG (dev, "%s, flush old status first\n", __func__);
+
+ /* flush old status
+ *
+@@ -1329,7 +1329,7 @@ static void rndis_command_complete (struct usb_ep *ep, struct usb_request *req)
+ spin_lock(&dev->lock);
+ status = rndis_msg_parser (dev->rndis_config, (u8 *) req->buf);
+ if (status < 0)
+- ERROR(dev, "%s: rndis parse error %d\n", __FUNCTION__, status);
++ ERROR(dev, "%s: rndis parse error %d\n", __func__, status);
+ spin_unlock(&dev->lock);
+ }
+
+@@ -2113,7 +2113,7 @@ static int rndis_control_ack (struct net_device *net)
+
+ static void eth_start (struct eth_dev *dev, gfp_t gfp_flags)
+ {
+- DEBUG (dev, "%s\n", __FUNCTION__);
++ DEBUG (dev, "%s\n", __func__);
+
+ /* fill the rx queue */
+ rx_fill (dev, gfp_flags);
+@@ -2133,7 +2133,7 @@ static int eth_open (struct net_device *net)
+ {
+ struct eth_dev *dev = netdev_priv(net);
+
+- DEBUG (dev, "%s\n", __FUNCTION__);
++ DEBUG (dev, "%s\n", __func__);
+ if (netif_carrier_ok (dev->net))
+ eth_start (dev, GFP_KERNEL);
+ return 0;
+@@ -2143,7 +2143,7 @@ static int eth_stop (struct net_device *net)
+ {
+ struct eth_dev *dev = netdev_priv(net);
+
+- VDEBUG (dev, "%s\n", __FUNCTION__);
++ VDEBUG (dev, "%s\n", __func__);
+ netif_stop_queue (net);
+
+ DEBUG (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n",
+@@ -2229,7 +2229,7 @@ eth_unbind (struct usb_gadget *gadget)
+ set_gadget_data (gadget, NULL);
+ }
+
+-static u8 __devinit nibble (unsigned char c)
++static u8 __init nibble (unsigned char c)
+ {
+ if (likely (isdigit (c)))
+ return c - '0';
+@@ -2239,7 +2239,7 @@ static u8 __devinit nibble (unsigned char c)
+ return 0;
+ }
+
+-static int __devinit get_ether_addr(const char *str, u8 *dev_addr)
++static int __init get_ether_addr(const char *str, u8 *dev_addr)
+ {
+ if (str) {
+ unsigned i;
+@@ -2260,7 +2260,7 @@ static int __devinit get_ether_addr(const char *str, u8 *dev_addr)
+ return 1;
+ }
+
+-static int __devinit
++static int __init
+ eth_bind (struct usb_gadget *gadget)
+ {
+ struct eth_dev *dev;
+diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
+index 017a196..bf3f946 100644
+--- a/drivers/usb/gadget/file_storage.c
++++ b/drivers/usb/gadget/file_storage.c
+@@ -644,7 +644,7 @@ struct fsg_dev {
+
+ unsigned long atomic_bitflags;
+ #define REGISTERED 0
+-#define CLEAR_BULK_HALTS 1
++#define IGNORE_BULK_OUT 1
+ #define SUSPENDED 2
+
+ struct usb_ep *bulk_in;
+@@ -1104,7 +1104,7 @@ static void ep0_complete(struct usb_ep *ep, struct usb_request *req)
+ if (req->actual > 0)
+ dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual);
+ if (req->status || req->actual != req->length)
+- DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__,
++ DBG(fsg, "%s --> %d, %u/%u\n", __func__,
+ req->status, req->actual, req->length);
+ if (req->status == -ECONNRESET) // Request was cancelled
+ usb_ep_fifo_flush(ep);
+@@ -1125,7 +1125,7 @@ static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
+ struct fsg_buffhd *bh = req->context;
+
+ if (req->status || req->actual != req->length)
+- DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__,
++ DBG(fsg, "%s --> %d, %u/%u\n", __func__,
+ req->status, req->actual, req->length);
+ if (req->status == -ECONNRESET) // Request was cancelled
+ usb_ep_fifo_flush(ep);
+@@ -1146,7 +1146,7 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
+
+ dump_msg(fsg, "bulk-out", req->buf, req->actual);
+ if (req->status || req->actual != bh->bulk_out_intended_length)
+- DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__,
++ DBG(fsg, "%s --> %d, %u/%u\n", __func__,
+ req->status, req->actual,
+ bh->bulk_out_intended_length);
+ if (req->status == -ECONNRESET) // Request was cancelled
+@@ -1169,7 +1169,7 @@ static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
+ struct fsg_buffhd *bh = req->context;
+
+ if (req->status || req->actual != req->length)
+- DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__,
++ DBG(fsg, "%s --> %d, %u/%u\n", __func__,
+ req->status, req->actual, req->length);
+ if (req->status == -ECONNRESET) // Request was cancelled
+ usb_ep_fifo_flush(ep);
+@@ -2936,8 +2936,8 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+ struct usb_request *req = bh->outreq;
+ struct bulk_cb_wrap *cbw = req->buf;
+
+- /* Was this a real packet? */
+- if (req->status)
++ /* Was this a real packet? Should it be ignored? */
++ if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
+ return -EINVAL;
+
+ /* Is the CBW valid? */
+@@ -2948,13 +2948,17 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+ req->actual,
+ le32_to_cpu(cbw->Signature));
+
+- /* The Bulk-only spec says we MUST stall the bulk pipes!
+- * If we want to avoid stalls, set a flag so that we will
+- * clear the endpoint halts at the next reset. */
+- if (!mod_data.can_stall)
+- set_bit(CLEAR_BULK_HALTS, &fsg->atomic_bitflags);
+- fsg_set_halt(fsg, fsg->bulk_out);
++ /* The Bulk-only spec says we MUST stall the IN endpoint
++ * (6.6.1), so it's unavoidable. It also says we must
++ * retain this state until the next reset, but there's
++ * no way to tell the controller driver it should ignore
++ * Clear-Feature(HALT) requests.
++ *
++ * We aren't required to halt the OUT endpoint; instead
++ * we can simply accept and discard any data received
++ * until the next reset. */
+ halt_bulk_in_endpoint(fsg);
++ set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
+ return -EINVAL;
+ }
+
+@@ -3140,6 +3144,7 @@ reset:
+ goto reset;
+ fsg->bulk_out_enabled = 1;
+ fsg->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize);
++ clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
+
+ if (transport_is_cbi()) {
+ d = ep_desc(fsg->gadget, &fs_intr_in_desc, &hs_intr_in_desc);
+@@ -3321,11 +3326,8 @@ static void handle_exception(struct fsg_dev *fsg)
+ /* In case we were forced against our will to halt a
+ * bulk endpoint, clear the halt now. (The SuperH UDC
+ * requires this.) */
+- if (test_and_clear_bit(CLEAR_BULK_HALTS,
+- &fsg->atomic_bitflags)) {
++ if (test_and_clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
+ usb_ep_clear_halt(fsg->bulk_in);
+- usb_ep_clear_halt(fsg->bulk_out);
+- }
+
+ if (transport_is_bbb()) {
+ if (fsg->ep0_req_tag == exception_req_tag)
+diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c
+index 254012a..651b827 100644
+--- a/drivers/usb/gadget/fsl_usb2_udc.c
++++ b/drivers/usb/gadget/fsl_usb2_udc.c
+@@ -773,11 +773,11 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+ /* catch various bogus parameters */
+ if (!_req || !req->req.complete || !req->req.buf
+ || !list_empty(&req->queue)) {
+- VDBG("%s, bad params\n", __FUNCTION__);
++ VDBG("%s, bad params\n", __func__);
+ return -EINVAL;
+ }
+ if (unlikely(!_ep || !ep->desc)) {
+- VDBG("%s, bad ep\n", __FUNCTION__);
++ VDBG("%s, bad ep\n", __func__);
+ return -EINVAL;
+ }
+ if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h
+index 9fb0b1e..98b1483 100644
+--- a/drivers/usb/gadget/fsl_usb2_udc.h
++++ b/drivers/usb/gadget/fsl_usb2_udc.h
+@@ -512,7 +512,7 @@ struct fsl_udc {
+
+ #ifdef DEBUG
+ #define DBG(fmt, args...) printk(KERN_DEBUG "[%s] " fmt "\n", \
+- __FUNCTION__, ## args)
++ __func__, ## args)
+ #else
+ #define DBG(fmt, args...) do{}while(0)
+ #endif
+diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c
+index 5b42ccd..ff3a851 100644
+--- a/drivers/usb/gadget/gmidi.c
++++ b/drivers/usb/gadget/gmidi.c
+@@ -1149,7 +1149,7 @@ fail:
+ /*
+ * Creates an output endpoint, and initializes output ports.
+ */
+-static int __devinit gmidi_bind(struct usb_gadget *gadget)
++static int __init gmidi_bind(struct usb_gadget *gadget)
+ {
+ struct gmidi_device *dev;
+ struct usb_ep *in_ep, *out_ep;
+diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
+index d3e7025..64a592c 100644
+--- a/drivers/usb/gadget/goku_udc.c
++++ b/drivers/usb/gadget/goku_udc.c
+@@ -692,7 +692,7 @@ static void abort_dma(struct goku_ep *ep, int status)
+ req->req.actual = (curr - req->req.dma) + 1;
+ req->req.status = status;
+
+- VDBG(ep->dev, "%s %s %s %d/%d\n", __FUNCTION__, ep->ep.name,
++ VDBG(ep->dev, "%s %s %s %d/%d\n", __func__, ep->ep.name,
+ ep->is_in ? "IN" : "OUT",
+ req->req.actual, req->req.length);
+
+@@ -826,7 +826,7 @@ static int goku_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+ if (dev->ep0state == EP0_SUSPEND)
+ return -EBUSY;
+
+- VDBG(dev, "%s %s %s %s %p\n", __FUNCTION__, _ep->name,
++ VDBG(dev, "%s %s %s %s %p\n", __func__, _ep->name,
+ ep->is_in ? "IN" : "OUT",
+ ep->dma ? "dma" : "pio",
+ _req);
+@@ -898,7 +898,7 @@ static int goku_set_halt(struct usb_ep *_ep, int value)
+
+ /* don't change EPxSTATUS_EP_INVALID to READY */
+ } else if (!ep->desc) {
+- DBG(ep->dev, "%s %s inactive?\n", __FUNCTION__, ep->ep.name);
++ DBG(ep->dev, "%s %s inactive?\n", __func__, ep->ep.name);
+ return -EINVAL;
+ }
+
+@@ -940,7 +940,7 @@ static int goku_fifo_status(struct usb_ep *_ep)
+ regs = ep->dev->regs;
+ size = readl(®s->EPxSizeLA[ep->num]) & DATASIZE;
+ size += readl(®s->EPxSizeLB[ep->num]) & DATASIZE;
+- VDBG(ep->dev, "%s %s %u\n", __FUNCTION__, ep->ep.name, size);
++ VDBG(ep->dev, "%s %s %u\n", __func__, ep->ep.name, size);
+ return size;
+ }
+
+@@ -953,11 +953,11 @@ static void goku_fifo_flush(struct usb_ep *_ep)
+ if (!_ep)
+ return;
+ ep = container_of(_ep, struct goku_ep, ep);
+- VDBG(ep->dev, "%s %s\n", __FUNCTION__, ep->ep.name);
++ VDBG(ep->dev, "%s %s\n", __func__, ep->ep.name);
+
+ /* don't change EPxSTATUS_EP_INVALID to READY */
+ if (!ep->desc && ep->num != 0) {
+- DBG(ep->dev, "%s %s inactive?\n", __FUNCTION__, ep->ep.name);
++ DBG(ep->dev, "%s %s inactive?\n", __func__, ep->ep.name);
+ return;
+ }
+
+@@ -1286,7 +1286,7 @@ static void ep0_start(struct goku_udc *dev)
+ struct goku_udc_regs __iomem *regs = dev->regs;
+ unsigned i;
+
+- VDBG(dev, "%s\n", __FUNCTION__);
++ VDBG(dev, "%s\n", __func__);
+
+ udc_reset(dev);
+ udc_reinit (dev);
+@@ -1322,7 +1322,7 @@ static void udc_enable(struct goku_udc *dev)
+ if (readl(&dev->regs->power_detect) & PW_DETECT)
+ ep0_start(dev);
+ else {
+- DBG(dev, "%s\n", __FUNCTION__);
++ DBG(dev, "%s\n", __func__);
+ dev->int_enable = INT_PWRDETECT;
+ writel(dev->int_enable, &dev->regs->int_enable);
+ }
+@@ -1387,7 +1387,7 @@ stop_activity(struct goku_udc *dev, struct usb_gadget_driver *driver)
+ {
+ unsigned i;
+
+- DBG (dev, "%s\n", __FUNCTION__);
++ DBG (dev, "%s\n", __func__);
+
+ if (dev->gadget.speed == USB_SPEED_UNKNOWN)
+ driver = NULL;
+@@ -1726,7 +1726,7 @@ static void goku_remove(struct pci_dev *pdev)
+ {
+ struct goku_udc *dev = pci_get_drvdata(pdev);
+
+- DBG(dev, "%s\n", __FUNCTION__);
++ DBG(dev, "%s\n", __func__);
+
+ BUG_ON(dev->driver);
+
+diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
+index 0a6feaf..69b0a27 100644
+--- a/drivers/usb/gadget/inode.c
++++ b/drivers/usb/gadget/inode.c
+@@ -1107,13 +1107,13 @@ scan:
+
+ switch (state) {
+ default:
+- DBG (dev, "fail %s, state %d\n", __FUNCTION__, state);
++ DBG (dev, "fail %s, state %d\n", __func__, state);
+ retval = -ESRCH;
+ break;
+ case STATE_DEV_UNCONNECTED:
+ case STATE_DEV_CONNECTED:
+ spin_unlock_irq (&dev->lock);
+- DBG (dev, "%s wait\n", __FUNCTION__);
++ DBG (dev, "%s wait\n", __func__);
+
+ /* wait for events */
+ retval = wait_event_interruptible (dev->wait,
+@@ -1222,7 +1222,7 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+ DBG(dev, "bogus ep0out stall!\n");
+ }
+ } else
+- DBG (dev, "fail %s, state %d\n", __FUNCTION__, dev->state);
++ DBG (dev, "fail %s, state %d\n", __func__, dev->state);
+
+ spin_unlock_irq (&dev->lock);
+ return retval;
+@@ -1233,7 +1233,7 @@ ep0_fasync (int f, struct file *fd, int on)
+ {
+ struct dev_data *dev = fd->private_data;
+ // caller must F_SETOWN before signal delivery happens
+- VDEBUG (dev, "%s %s\n", __FUNCTION__, on ? "on" : "off");
++ VDEBUG (dev, "%s %s\n", __func__, on ? "on" : "off");
+ return fasync_helper (f, fd, on, &dev->fasync);
+ }
+
+@@ -1575,7 +1575,7 @@ static void destroy_ep_files (struct dev_data *dev)
+ {
+ struct list_head *entry, *tmp;
+
+- DBG (dev, "%s %d\n", __FUNCTION__, dev->state);
++ DBG (dev, "%s %d\n", __func__, dev->state);
+
+ /* dev->state must prevent interference */
+ restart:
+@@ -1662,7 +1662,7 @@ enomem1:
+ put_dev (dev);
+ kfree (data);
+ enomem0:
+- DBG (dev, "%s enomem\n", __FUNCTION__);
++ DBG (dev, "%s enomem\n", __func__);
+ destroy_ep_files (dev);
+ return -ENOMEM;
+ }
+@@ -1672,7 +1672,7 @@ gadgetfs_unbind (struct usb_gadget *gadget)
+ {
+ struct dev_data *dev = get_gadget_data (gadget);
+
+- DBG (dev, "%s\n", __FUNCTION__);
++ DBG (dev, "%s\n", __func__);
+
+ spin_lock_irq (&dev->lock);
+ dev->state = STATE_DEV_UNBOUND;
+@@ -1685,7 +1685,7 @@ gadgetfs_unbind (struct usb_gadget *gadget)
+ /* we've already been disconnected ... no i/o is active */
+ if (dev->req)
+ usb_ep_free_request (gadget->ep0, dev->req);
+- DBG (dev, "%s done\n", __FUNCTION__);
++ DBG (dev, "%s done\n", __func__);
+ put_dev (dev);
+ }
+
+@@ -1933,7 +1933,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+
+ fail:
+ spin_unlock_irq (&dev->lock);
+- pr_debug ("%s: %s fail %Zd, %p\n", shortname, __FUNCTION__, value, dev);
++ pr_debug ("%s: %s fail %Zd, %p\n", shortname, __func__, value, dev);
+ kfree (dev->buf);
+ dev->buf = NULL;
+ return value;
+diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
+index 078f724..825abd2 100644
+--- a/drivers/usb/gadget/lh7a40x_udc.c
++++ b/drivers/usb/gadget/lh7a40x_udc.c
+@@ -253,7 +253,7 @@ udc_proc_read(char *page, char **start, off_t off, int count,
+ */
+ static void udc_disable(struct lh7a40x_udc *dev)
+ {
+- DEBUG("%s, %p\n", __FUNCTION__, dev);
++ DEBUG("%s, %p\n", __func__, dev);
+
+ udc_set_address(dev, 0);
+
+@@ -285,7 +285,7 @@ static void udc_reinit(struct lh7a40x_udc *dev)
+ {
+ u32 i;
+
+- DEBUG("%s, %p\n", __FUNCTION__, dev);
++ DEBUG("%s, %p\n", __func__, dev);
+
+ /* device/ep0 records init */
+ INIT_LIST_HEAD(&dev->gadget.ep_list);
+@@ -318,7 +318,7 @@ static void udc_enable(struct lh7a40x_udc *dev)
+ {
+ int ep;
+
+- DEBUG("%s, %p\n", __FUNCTION__, dev);
++ DEBUG("%s, %p\n", __func__, dev);
+
+ dev->gadget.speed = USB_SPEED_UNKNOWN;
+
+@@ -412,7 +412,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+ struct lh7a40x_udc *dev = the_controller;
+ int retval;
+
+- DEBUG("%s: %s\n", __FUNCTION__, driver->driver.name);
++ DEBUG("%s: %s\n", __func__, driver->driver.name);
+
+ if (!driver
+ || driver->speed != USB_SPEED_FULL
+@@ -521,7 +521,7 @@ static int write_fifo(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
+ is_short = unlikely(max < ep_maxpacket(ep));
+ }
+
+- DEBUG("%s: wrote %s %d bytes%s%s %d left %p\n", __FUNCTION__,
++ DEBUG("%s: wrote %s %d bytes%s%s %d left %p\n", __func__,
+ ep->ep.name, count,
+ is_last ? "/L" : "", is_short ? "/S" : "",
+ req->req.length - req->req.actual, req);
+@@ -555,7 +555,7 @@ static int read_fifo(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
+ /* make sure there's a packet in the FIFO. */
+ csr = usb_read(ep->csr1);
+ if (!(csr & USB_OUT_CSR1_OUT_PKT_RDY)) {
+- DEBUG("%s: Packet NOT ready!\n", __FUNCTION__);
++ DEBUG("%s: Packet NOT ready!\n", __func__);
+ return -EINVAL;
+ }
+
+@@ -614,7 +614,7 @@ static void done(struct lh7a40x_ep *ep, struct lh7a40x_request *req, int status)
+ unsigned int stopped = ep->stopped;
+ u32 index;
+
+- DEBUG("%s, %p\n", __FUNCTION__, ep);
++ DEBUG("%s, %p\n", __func__, ep);
+ list_del_init(&req->queue);
+
+ if (likely(req->req.status == -EINPROGRESS))
+@@ -644,7 +644,7 @@ static void done(struct lh7a40x_ep *ep, struct lh7a40x_request *req, int status)
+ /** Enable EP interrupt */
+ static void pio_irq_enable(int ep)
+ {
+- DEBUG("%s: %d\n", __FUNCTION__, ep);
++ DEBUG("%s: %d\n", __func__, ep);
+
+ switch (ep) {
+ case 1:
+@@ -665,7 +665,7 @@ static void pio_irq_enable(int ep)
+ /** Disable EP interrupt */
+ static void pio_irq_disable(int ep)
+ {
+- DEBUG("%s: %d\n", __FUNCTION__, ep);
++ DEBUG("%s: %d\n", __func__, ep);
+
+ switch (ep) {
+ case 1:
+@@ -690,7 +690,7 @@ void nuke(struct lh7a40x_ep *ep, int status)
+ {
+ struct lh7a40x_request *req;
+
+- DEBUG("%s, %p\n", __FUNCTION__, ep);
++ DEBUG("%s, %p\n", __func__, ep);
+
+ /* Flush FIFO */
+ flush(ep);
+@@ -734,7 +734,7 @@ static void flush_all(struct lh7a40x_udc *dev)
+ */
+ static void flush(struct lh7a40x_ep *ep)
+ {
+- DEBUG("%s, %p\n", __FUNCTION__, ep);
++ DEBUG("%s, %p\n", __func__, ep);
+
+ switch (ep->ep_type) {
+ case ep_control:
+@@ -766,7 +766,7 @@ static void lh7a40x_in_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
+ usb_set_index(ep_idx);
+
+ csr = usb_read(ep->csr1);
+- DEBUG("%s: %d, csr %x\n", __FUNCTION__, ep_idx, csr);
++ DEBUG("%s: %d, csr %x\n", __func__, ep_idx, csr);
+
+ if (csr & USB_IN_CSR1_SENT_STALL) {
+ DEBUG("USB_IN_CSR1_SENT_STALL\n");
+@@ -776,7 +776,7 @@ static void lh7a40x_in_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
+ }
+
+ if (!ep->desc) {
+- DEBUG("%s: NO EP DESC\n", __FUNCTION__);
++ DEBUG("%s: NO EP DESC\n", __func__);
+ return;
+ }
+
+@@ -802,7 +802,7 @@ static void lh7a40x_out_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
+ struct lh7a40x_ep *ep = &dev->ep[ep_idx];
+ struct lh7a40x_request *req;
+
+- DEBUG("%s: %d\n", __FUNCTION__, ep_idx);
++ DEBUG("%s: %d\n", __func__, ep_idx);
+
+ usb_set_index(ep_idx);
+
+@@ -814,11 +814,11 @@ static void lh7a40x_out_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
+ usb_read(ep->
+ csr1)) & (USB_OUT_CSR1_OUT_PKT_RDY |
+ USB_OUT_CSR1_SENT_STALL)) {
+- DEBUG("%s: %x\n", __FUNCTION__, csr);
++ DEBUG("%s: %x\n", __func__, csr);
+
+ if (csr & USB_OUT_CSR1_SENT_STALL) {
+ DEBUG("%s: stall sent, flush fifo\n",
+- __FUNCTION__);
++ __func__);
+ /* usb_set(USB_OUT_CSR1_FIFO_FLUSH, ep->csr1); */
+ flush(ep);
+ } else if (csr & USB_OUT_CSR1_OUT_PKT_RDY) {
+@@ -832,7 +832,7 @@ static void lh7a40x_out_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
+
+ if (!req) {
+ printk("%s: NULL REQ %d\n",
+- __FUNCTION__, ep_idx);
++ __func__, ep_idx);
+ flush(ep);
+ break;
+ } else {
+@@ -844,7 +844,7 @@ static void lh7a40x_out_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
+
+ } else {
+ /* Throw packet away.. */
+- printk("%s: No descriptor?!?\n", __FUNCTION__);
++ printk("%s: No descriptor?!?\n", __func__);
+ flush(ep);
+ }
+ }
+@@ -886,7 +886,7 @@ static void lh7a40x_reset_intr(struct lh7a40x_udc *dev)
+ #if 0 /* def CONFIG_ARCH_LH7A404 */
+ /* Does not work always... */
+
+- DEBUG("%s: %d\n", __FUNCTION__, dev->usb_address);
++ DEBUG("%s: %d\n", __func__, dev->usb_address);
+
+ if (!dev->usb_address) {
+ /*usb_set(USB_RESET_IO, USB_RESET);
+@@ -936,7 +936,7 @@ static irqreturn_t lh7a40x_udc_irq(int irq, void *_dev)
+ if (!intr_out && !intr_in && !intr_int)
+ break;
+
+- DEBUG("%s (on state %s)\n", __FUNCTION__,
++ DEBUG("%s (on state %s)\n", __func__,
+ state_names[dev->ep0state]);
+ DEBUG("intr_out = %x\n", intr_out);
+ DEBUG("intr_in = %x\n", intr_in);
+@@ -1016,14 +1016,14 @@ static int lh7a40x_ep_enable(struct usb_ep *_ep,
+ struct lh7a40x_udc *dev;
+ unsigned long flags;
+
+- DEBUG("%s, %p\n", __FUNCTION__, _ep);
++ DEBUG("%s, %p\n", __func__, _ep);
+
+ ep = container_of(_ep, struct lh7a40x_ep, ep);
+ if (!_ep || !desc || ep->desc || _ep->name == ep0name
+ || desc->bDescriptorType != USB_DT_ENDPOINT
+ || ep->bEndpointAddress != desc->bEndpointAddress
+ || ep_maxpacket(ep) < le16_to_cpu(desc->wMaxPacketSize)) {
+- DEBUG("%s, bad ep or descriptor\n", __FUNCTION__);
++ DEBUG("%s, bad ep or descriptor\n", __func__);
+ return -EINVAL;
+ }
+
+@@ -1031,7 +1031,7 @@ static int lh7a40x_ep_enable(struct usb_ep *_ep,
+ if (ep->bmAttributes != desc->bmAttributes
+ && ep->bmAttributes != USB_ENDPOINT_XFER_BULK
+ && desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
+- DEBUG("%s, %s type mismatch\n", __FUNCTION__, _ep->name);
++ DEBUG("%s, %s type mismatch\n", __func__, _ep->name);
+ return -EINVAL;
+ }
+
+@@ -1039,13 +1039,13 @@ static int lh7a40x_ep_enable(struct usb_ep *_ep,
+ if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
+ && le16_to_cpu(desc->wMaxPacketSize) != ep_maxpacket(ep))
+ || !desc->wMaxPacketSize) {
+- DEBUG("%s, bad %s maxpacket\n", __FUNCTION__, _ep->name);
++ DEBUG("%s, bad %s maxpacket\n", __func__, _ep->name);
+ return -ERANGE;
+ }
+
+ dev = ep->dev;
+ if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
+- DEBUG("%s, bogus device state\n", __FUNCTION__);
++ DEBUG("%s, bogus device state\n", __func__);
+ return -ESHUTDOWN;
+ }
+
+@@ -1061,7 +1061,7 @@ static int lh7a40x_ep_enable(struct usb_ep *_ep,
+ /* Reset halt state (does flush) */
+ lh7a40x_set_halt(_ep, 0);
+
+- DEBUG("%s: enabled %s\n", __FUNCTION__, _ep->name);
++ DEBUG("%s: enabled %s\n", __func__, _ep->name);
+ return 0;
+ }
+
+@@ -1073,11 +1073,11 @@ static int lh7a40x_ep_disable(struct usb_ep *_ep)
+ struct lh7a40x_ep *ep;
+ unsigned long flags;
+
+- DEBUG("%s, %p\n", __FUNCTION__, _ep);
++ DEBUG("%s, %p\n", __func__, _ep);
+
+ ep = container_of(_ep, struct lh7a40x_ep, ep);
+ if (!_ep || !ep->desc) {
+- DEBUG("%s, %s not enabled\n", __FUNCTION__,
++ DEBUG("%s, %s not enabled\n", __func__,
+ _ep ? ep->ep.name : NULL);
+ return -EINVAL;
+ }
+@@ -1097,7 +1097,7 @@ static int lh7a40x_ep_disable(struct usb_ep *_ep)
+
+ spin_unlock_irqrestore(&ep->dev->lock, flags);
+
+- DEBUG("%s: disabled %s\n", __FUNCTION__, _ep->name);
++ DEBUG("%s: disabled %s\n", __func__, _ep->name);
+ return 0;
+ }
+
+@@ -1106,7 +1106,7 @@ static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep,
+ {
+ struct lh7a40x_request *req;
+
+- DEBUG("%s, %p\n", __FUNCTION__, ep);
++ DEBUG("%s, %p\n", __func__, ep);
+
+ req = kzalloc(sizeof(*req), gfp_flags);
+ if (!req)
+@@ -1121,7 +1121,7 @@ static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *_req)
+ {
+ struct lh7a40x_request *req;
+
+- DEBUG("%s, %p\n", __FUNCTION__, ep);
++ DEBUG("%s, %p\n", __func__, ep);
+
+ req = container_of(_req, struct lh7a40x_request, req);
+ WARN_ON(!list_empty(&req->queue));
+@@ -1140,25 +1140,25 @@ static int lh7a40x_queue(struct usb_ep *_ep, struct usb_request *_req,
+ struct lh7a40x_udc *dev;
+ unsigned long flags;
+
+- DEBUG("\n\n\n%s, %p\n", __FUNCTION__, _ep);
++ DEBUG("\n\n\n%s, %p\n", __func__, _ep);
+
+ req = container_of(_req, struct lh7a40x_request, req);
+ if (unlikely
+ (!_req || !_req->complete || !_req->buf
+ || !list_empty(&req->queue))) {
+- DEBUG("%s, bad params\n", __FUNCTION__);
++ DEBUG("%s, bad params\n", __func__);
+ return -EINVAL;
+ }
+
+ ep = container_of(_ep, struct lh7a40x_ep, ep);
+ if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+- DEBUG("%s, bad ep\n", __FUNCTION__);
++ DEBUG("%s, bad ep\n", __func__);
+ return -EINVAL;
+ }
+
+ dev = ep->dev;
+ if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
+- DEBUG("%s, bogus device state %p\n", __FUNCTION__, dev->driver);
++ DEBUG("%s, bogus device state %p\n", __func__, dev->driver);
+ return -ESHUTDOWN;
+ }
+
+@@ -1218,7 +1218,7 @@ static int lh7a40x_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+ struct lh7a40x_request *req;
+ unsigned long flags;
+
+- DEBUG("%s, %p\n", __FUNCTION__, _ep);
++ DEBUG("%s, %p\n", __func__, _ep);
+
+ ep = container_of(_ep, struct lh7a40x_ep, ep);
+ if (!_ep || ep->ep.name == ep0name)
+@@ -1253,13 +1253,13 @@ static int lh7a40x_set_halt(struct usb_ep *_ep, int value)
+
+ ep = container_of(_ep, struct lh7a40x_ep, ep);
+ if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+- DEBUG("%s, bad ep\n", __FUNCTION__);
++ DEBUG("%s, bad ep\n", __func__);
+ return -EINVAL;
+ }
+
+ usb_set_index(ep_index(ep));
+
+- DEBUG("%s, ep %d, val %d\n", __FUNCTION__, ep_index(ep), value);
++ DEBUG("%s, ep %d, val %d\n", __func__, ep_index(ep), value);
+
+ spin_lock_irqsave(&ep->dev->lock, flags);
+
+@@ -1325,11 +1325,11 @@ static int lh7a40x_fifo_status(struct usb_ep *_ep)
+
+ ep = container_of(_ep, struct lh7a40x_ep, ep);
+ if (!_ep) {
+- DEBUG("%s, bad ep\n", __FUNCTION__);
++ DEBUG("%s, bad ep\n", __func__);
+ return -ENODEV;
+ }
+
+- DEBUG("%s, %d\n", __FUNCTION__, ep_index(ep));
++ DEBUG("%s, %d\n", __func__, ep_index(ep));
+
+ /* LPD can't report unclaimed bytes from IN fifos */
+ if (ep_is_in(ep))
+@@ -1355,7 +1355,7 @@ static void lh7a40x_fifo_flush(struct usb_ep *_ep)
+
+ ep = container_of(_ep, struct lh7a40x_ep, ep);
+ if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+- DEBUG("%s, bad ep\n", __FUNCTION__);
++ DEBUG("%s, bad ep\n", __func__);
+ return;
+ }
+
+@@ -1376,7 +1376,7 @@ static int write_fifo_ep0(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
+
+ max = ep_maxpacket(ep);
+
+- DEBUG_EP0("%s\n", __FUNCTION__);
++ DEBUG_EP0("%s\n", __func__);
+
+ count = write_packet(ep, req, max);
+
+@@ -1390,7 +1390,7 @@ static int write_fifo_ep0(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
+ is_last = 1;
+ }
+
+- DEBUG_EP0("%s: wrote %s %d bytes%s %d left %p\n", __FUNCTION__,
++ DEBUG_EP0("%s: wrote %s %d bytes%s %d left %p\n", __func__,
+ ep->ep.name, count,
+ is_last ? "/L" : "", req->req.length - req->req.actual, req);
+
+@@ -1434,7 +1434,7 @@ static int read_fifo_ep0(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
+ unsigned bufferspace, count, is_short;
+ volatile u32 *fifo = (volatile u32 *)ep->fifo;
+
+- DEBUG_EP0("%s\n", __FUNCTION__);
++ DEBUG_EP0("%s\n", __func__);
+
+ csr = usb_read(USB_EP0_CSR);
+ if (!(csr & USB_OUT_CSR1_OUT_PKT_RDY))
+@@ -1492,7 +1492,7 @@ static int read_fifo_ep0(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
+ */
+ static void udc_set_address(struct lh7a40x_udc *dev, unsigned char address)
+ {
+- DEBUG_EP0("%s: %d\n", __FUNCTION__, address);
++ DEBUG_EP0("%s: %d\n", __func__, address);
+ /* c.f. 15.1.2.2 Table 15-4 address will be used after DATA_END is set */
+ dev->usb_address = address;
+ usb_set((address & USB_FA_FUNCTION_ADDR), USB_FA);
+@@ -1514,7 +1514,7 @@ static void lh7a40x_ep0_out(struct lh7a40x_udc *dev, u32 csr)
+ struct lh7a40x_ep *ep = &dev->ep[0];
+ int ret;
+
+- DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
++ DEBUG_EP0("%s: %x\n", __func__, csr);
+
+ if (list_empty(&ep->queue))
+ req = 0;
+@@ -1533,13 +1533,13 @@ static void lh7a40x_ep0_out(struct lh7a40x_udc *dev, u32 csr)
+ if (ret) {
+ /* Done! */
+ DEBUG_EP0("%s: finished, waiting for status\n",
+- __FUNCTION__);
++ __func__);
+
+ usb_set((EP0_CLR_OUT | EP0_DATA_END), USB_EP0_CSR);
+ dev->ep0state = WAIT_FOR_SETUP;
+ } else {
+ /* Not done yet.. */
+- DEBUG_EP0("%s: not finished\n", __FUNCTION__);
++ DEBUG_EP0("%s: not finished\n", __func__);
+ usb_set(EP0_CLR_OUT, USB_EP0_CSR);
+ }
+ } else {
+@@ -1556,7 +1556,7 @@ static int lh7a40x_ep0_in(struct lh7a40x_udc *dev, u32 csr)
+ struct lh7a40x_ep *ep = &dev->ep[0];
+ int ret, need_zlp = 0;
+
+- DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
++ DEBUG_EP0("%s: %x\n", __func__, csr);
+
+ if (list_empty(&ep->queue))
+ req = 0;
+@@ -1564,7 +1564,7 @@ static int lh7a40x_ep0_in(struct lh7a40x_udc *dev, u32 csr)
+ req = list_entry(ep->queue.next, struct lh7a40x_request, queue);
+
+ if (!req) {
+- DEBUG_EP0("%s: NULL REQ\n", __FUNCTION__);
++ DEBUG_EP0("%s: NULL REQ\n", __func__);
+ return 0;
+ }
+
+@@ -1585,17 +1585,17 @@ static int lh7a40x_ep0_in(struct lh7a40x_udc *dev, u32 csr)
+
+ if (ret == 1 && !need_zlp) {
+ /* Last packet */
+- DEBUG_EP0("%s: finished, waiting for status\n", __FUNCTION__);
++ DEBUG_EP0("%s: finished, waiting for status\n", __func__);
+
+ usb_set((EP0_IN_PKT_RDY | EP0_DATA_END), USB_EP0_CSR);
+ dev->ep0state = WAIT_FOR_SETUP;
+ } else {
+- DEBUG_EP0("%s: not finished\n", __FUNCTION__);
++ DEBUG_EP0("%s: not finished\n", __func__);
+ usb_set(EP0_IN_PKT_RDY, USB_EP0_CSR);
+ }
+
+ if (need_zlp) {
+- DEBUG_EP0("%s: Need ZLP!\n", __FUNCTION__);
++ DEBUG_EP0("%s: Need ZLP!\n", __func__);
+ usb_set(EP0_IN_PKT_RDY, USB_EP0_CSR);
+ dev->ep0state = DATA_STATE_NEED_ZLP;
+ }
+@@ -1694,7 +1694,7 @@ static void lh7a40x_ep0_setup(struct lh7a40x_udc *dev, u32 csr)
+ struct usb_ctrlrequest ctrl;
+ int i, bytes, is_in;
+
+- DEBUG_SETUP("%s: %x\n", __FUNCTION__, csr);
++ DEBUG_SETUP("%s: %x\n", __func__, csr);
+
+ /* Nuke all previous transfers */
+ nuke(ep, -EPROTO);
+@@ -1799,7 +1799,7 @@ static void lh7a40x_ep0_setup(struct lh7a40x_udc *dev, u32 csr)
+ */
+ static void lh7a40x_ep0_in_zlp(struct lh7a40x_udc *dev, u32 csr)
+ {
+- DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
++ DEBUG_EP0("%s: %x\n", __func__, csr);
+
+ /* c.f. Table 15-14 */
+ usb_set((EP0_IN_PKT_RDY | EP0_DATA_END), USB_EP0_CSR);
+@@ -1818,7 +1818,7 @@ static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr)
+ usb_set_index(0);
+ csr = usb_read(USB_EP0_CSR);
+
+- DEBUG_EP0("%s: csr = %x\n", __FUNCTION__, csr);
++ DEBUG_EP0("%s: csr = %x\n", __func__, csr);
+
+ /*
+ * For overview of what we should be doing see c.f. Chapter 18.1.2.4
+@@ -1832,7 +1832,7 @@ static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr)
+ * - clear the SENT_STALL bit
+ */
+ if (csr & EP0_SENT_STALL) {
+- DEBUG_EP0("%s: EP0_SENT_STALL is set: %x\n", __FUNCTION__, csr);
++ DEBUG_EP0("%s: EP0_SENT_STALL is set: %x\n", __func__, csr);
+ usb_clear((EP0_SENT_STALL | EP0_SEND_STALL), USB_EP0_CSR);
+ nuke(ep, -ECONNABORTED);
+ dev->ep0state = WAIT_FOR_SETUP;
+@@ -1849,7 +1849,7 @@ static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr)
+ */
+ if (!(csr & (EP0_IN_PKT_RDY | EP0_OUT_PKT_RDY))) {
+ DEBUG_EP0("%s: IN_PKT_RDY and OUT_PKT_RDY are clear\n",
+- __FUNCTION__);
++ __func__);
+
+ switch (dev->ep0state) {
+ case DATA_STATE_XMIT:
+@@ -1877,7 +1877,7 @@ static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr)
+ * - set SERVICED_SETUP_END_BIT
+ */
+ if (csr & EP0_SETUP_END) {
+- DEBUG_EP0("%s: EP0_SETUP_END is set: %x\n", __FUNCTION__, csr);
++ DEBUG_EP0("%s: EP0_SETUP_END is set: %x\n", __func__, csr);
+
+ usb_set(EP0_CLR_SETUP_END, USB_EP0_CSR);
+
+@@ -1896,7 +1896,7 @@ static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr)
+ */
+ if (csr & EP0_OUT_PKT_RDY) {
+
+- DEBUG_EP0("%s: EP0_OUT_PKT_RDY is set: %x\n", __FUNCTION__,
++ DEBUG_EP0("%s: EP0_OUT_PKT_RDY is set: %x\n", __func__,
+ csr);
+
+ switch (dev->ep0state) {
+@@ -1926,7 +1926,7 @@ static void lh7a40x_ep0_kick(struct lh7a40x_udc *dev, struct lh7a40x_ep *ep)
+ usb_set_index(0);
+ csr = usb_read(USB_EP0_CSR);
+
+- DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
++ DEBUG_EP0("%s: %x\n", __func__, csr);
+
+ /* Clear "out packet ready" */
+ usb_set(EP0_CLR_OUT, USB_EP0_CSR);
+@@ -1949,7 +1949,7 @@ static int lh7a40x_udc_get_frame(struct usb_gadget *_gadget)
+ {
+ u32 frame1 = usb_read(USB_FRM_NUM1); /* Least significant 8 bits */
+ u32 frame2 = usb_read(USB_FRM_NUM2); /* Most significant 3 bits */
+- DEBUG("%s, %p\n", __FUNCTION__, _gadget);
++ DEBUG("%s, %p\n", __func__, _gadget);
+ return ((frame2 & 0x07) << 8) | (frame1 & 0xff);
+ }
+
+@@ -1970,7 +1970,7 @@ static const struct usb_gadget_ops lh7a40x_udc_ops = {
+
+ static void nop_release(struct device *dev)
+ {
+- DEBUG("%s %s\n", __FUNCTION__, dev->bus_id);
++ DEBUG("%s %s\n", __func__, dev->bus_id);
+ }
+
+ static struct lh7a40x_udc memory = {
+@@ -2065,7 +2065,7 @@ static int lh7a40x_udc_probe(struct platform_device *pdev)
+ struct lh7a40x_udc *dev = &memory;
+ int retval;
+
+- DEBUG("%s: %p\n", __FUNCTION__, pdev);
++ DEBUG("%s: %p\n", __func__, pdev);
+
+ spin_lock_init(&dev->lock);
+ dev->dev = &pdev->dev;
+@@ -2098,7 +2098,7 @@ static int lh7a40x_udc_remove(struct platform_device *pdev)
+ {
+ struct lh7a40x_udc *dev = platform_get_drvdata(pdev);
+
+- DEBUG("%s: %p\n", __FUNCTION__, pdev);
++ DEBUG("%s: %p\n", __func__, pdev);
+
+ if (dev->driver)
+ return -EBUSY;
+@@ -2131,7 +2131,7 @@ static struct platform_driver udc_driver = {
+
+ static int __init udc_init(void)
+ {
+- DEBUG("%s: %s version %s\n", __FUNCTION__, driver_name, DRIVER_VERSION);
++ DEBUG("%s: %s version %s\n", __func__, driver_name, DRIVER_VERSION);
+ return platform_driver_register(&udc_driver);
+ }
+
+diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/m66592-udc.h
+index 17b792b..be0a4c1 100644
+--- a/drivers/usb/gadget/m66592-udc.h
++++ b/drivers/usb/gadget/m66592-udc.h
+@@ -486,10 +486,10 @@ struct m66592 {
+
+ struct usb_request *ep0_req; /* for internal request */
+ u16 ep0_data; /* for internal request */
++ u16 old_vbus;
+
+ struct timer_list timer;
+
+- u16 old_vbus;
+ int scount;
+
+ int old_dvsq;
+diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h
+index 44ca139..1f2af39 100644
+--- a/drivers/usb/gadget/net2280.h
++++ b/drivers/usb/gadget/net2280.h
+@@ -299,7 +299,7 @@ static inline void assert_out_naking (struct net2280_ep *ep, const char *where)
+ &ep->regs->ep_rsp);
+ }
+ }
+-#define ASSERT_OUT_NAKING(ep) assert_out_naking(ep,__FUNCTION__)
++#define ASSERT_OUT_NAKING(ep) assert_out_naking(ep,__func__)
+ #else
+ #define ASSERT_OUT_NAKING(ep) do {} while (0)
+ #endif
+diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
+index ee1e9a3..95f7662 100644
+--- a/drivers/usb/gadget/omap_udc.c
++++ b/drivers/usb/gadget/omap_udc.c
+@@ -163,7 +163,7 @@ static int omap_ep_enable(struct usb_ep *_ep,
+ || ep->bEndpointAddress != desc->bEndpointAddress
+ || ep->maxpacket < le16_to_cpu
+ (desc->wMaxPacketSize)) {
+- DBG("%s, bad ep or descriptor\n", __FUNCTION__);
++ DBG("%s, bad ep or descriptor\n", __func__);
+ return -EINVAL;
+ }
+ maxp = le16_to_cpu (desc->wMaxPacketSize);
+@@ -171,7 +171,7 @@ static int omap_ep_enable(struct usb_ep *_ep,
+ && maxp != ep->maxpacket)
+ || le16_to_cpu(desc->wMaxPacketSize) > ep->maxpacket
+ || !desc->wMaxPacketSize) {
+- DBG("%s, bad %s maxpacket\n", __FUNCTION__, _ep->name);
++ DBG("%s, bad %s maxpacket\n", __func__, _ep->name);
+ return -ERANGE;
+ }
+
+@@ -194,13 +194,13 @@ static int omap_ep_enable(struct usb_ep *_ep,
+ if (ep->bmAttributes != desc->bmAttributes
+ && ep->bmAttributes != USB_ENDPOINT_XFER_BULK
+ && desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
+- DBG("%s, %s type mismatch\n", __FUNCTION__, _ep->name);
++ DBG("%s, %s type mismatch\n", __func__, _ep->name);
+ return -EINVAL;
+ }
+
+ udc = ep->udc;
+ if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
+- DBG("%s, bogus device state\n", __FUNCTION__);
++ DBG("%s, bogus device state\n", __func__);
+ return -ESHUTDOWN;
+ }
+
+@@ -249,7 +249,7 @@ static int omap_ep_disable(struct usb_ep *_ep)
+ unsigned long flags;
+
+ if (!_ep || !ep->desc) {
+- DBG("%s, %s not enabled\n", __FUNCTION__,
++ DBG("%s, %s not enabled\n", __func__,
+ _ep ? ep->ep.name : NULL);
+ return -EINVAL;
+ }
+@@ -936,11 +936,11 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+ /* catch various bogus parameters */
+ if (!_req || !req->req.complete || !req->req.buf
+ || !list_empty(&req->queue)) {
+- DBG("%s, bad params\n", __FUNCTION__);
++ DBG("%s, bad params\n", __func__);
+ return -EINVAL;
+ }
+ if (!_ep || (!ep->desc && ep->bEndpointAddress)) {
+- DBG("%s, bad ep\n", __FUNCTION__);
++ DBG("%s, bad ep\n", __func__);
+ return -EINVAL;
+ }
+ if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+@@ -959,7 +959,7 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+ && (ep->bEndpointAddress & USB_DIR_IN) == 0
+ && !cpu_class_is_omap2()
+ && (req->req.length % ep->ep.maxpacket) != 0) {
+- DBG("%s, no partial packet OUT reads\n", __FUNCTION__);
++ DBG("%s, no partial packet OUT reads\n", __func__);
+ return -EMSGSIZE;
+ }
+
+@@ -1265,8 +1265,6 @@ static int can_pullup(struct omap_udc *udc)
+
+ static void pullup_enable(struct omap_udc *udc)
+ {
+- udc->gadget.dev.parent->power.power_state = PMSG_ON;
+- udc->gadget.dev.power.power_state = PMSG_ON;
+ UDC_SYSCON1_REG |= UDC_PULLUP_EN;
+ if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx())
+ OTG_CTRL_REG |= OTG_BSESSVLD;
+@@ -3061,8 +3059,6 @@ static int omap_udc_suspend(struct platform_device *dev, pm_message_t message)
+ omap_pullup(&udc->gadget, 0);
+ }
+
+- udc->gadget.dev.power.power_state = PMSG_SUSPEND;
+- udc->gadget.dev.parent->power.power_state = PMSG_SUSPEND;
+ return 0;
+ }
+
+diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
+index 2c32bd0..76be75e 100644
+--- a/drivers/usb/gadget/printer.c
++++ b/drivers/usb/gadget/printer.c
+@@ -390,9 +390,12 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)
+
+ /* normal completion */
+ case 0:
+- list_add_tail(&req->list, &dev->rx_buffers);
+- wake_up_interruptible(&dev->rx_wait);
+- DBG(dev, "G_Printer : rx length %d\n", req->actual);
++ if (req->actual > 0) {
++ list_add_tail(&req->list, &dev->rx_buffers);
++ DBG(dev, "G_Printer : rx length %d\n", req->actual);
++ } else {
++ list_add(&req->list, &dev->rx_reqs);
++ }
+ break;
+
+ /* software-driven interface shutdown */
+@@ -417,6 +420,8 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)
+ list_add(&req->list, &dev->rx_reqs);
+ break;
+ }
++
++ wake_up_interruptible(&dev->rx_wait);
+ spin_unlock_irqrestore(&dev->lock, flags);
+ }
+
+@@ -494,6 +499,39 @@ printer_close(struct inode *inode, struct file *fd)
+ return 0;
+ }
+
++/* This function must be called with interrupts turned off. */
++static void
++setup_rx_reqs(struct printer_dev *dev)
++{
++ struct usb_request *req;
++
++ while (likely(!list_empty(&dev->rx_reqs))) {
++ int error;
++
++ req = container_of(dev->rx_reqs.next,
++ struct usb_request, list);
++ list_del_init(&req->list);
++
++ /* The USB Host sends us whatever amount of data it wants to
++ * so we always set the length field to the full USB_BUFSIZE.
++ * If the amount of data is more than the read() caller asked
++ * for it will be stored in the request buffer until it is
++ * asked for by read().
++ */
++ req->length = USB_BUFSIZE;
++ req->complete = rx_complete;
++
++ error = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC);
++ if (error) {
++ DBG(dev, "rx submit --> %d\n", error);
++ list_add(&req->list, &dev->rx_reqs);
++ break;
++ } else {
++ list_add(&req->list, &dev->rx_reqs_active);
++ }
++ }
++}
++
+ static ssize_t
+ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
+ {
+@@ -522,31 +560,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
+ */
+ dev->reset_printer = 0;
+
+- while (likely(!list_empty(&dev->rx_reqs))) {
+- int error;
+-
+- req = container_of(dev->rx_reqs.next,
+- struct usb_request, list);
+- list_del_init(&req->list);
+-
+- /* The USB Host sends us whatever amount of data it wants to
+- * so we always set the length field to the full USB_BUFSIZE.
+- * If the amount of data is more than the read() caller asked
+- * for it will be stored in the request buffer until it is
+- * asked for by read().
+- */
+- req->length = USB_BUFSIZE;
+- req->complete = rx_complete;
+-
+- error = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC);
+- if (error) {
+- DBG(dev, "rx submit --> %d\n", error);
+- list_add(&req->list, &dev->rx_reqs);
+- break;
+- } else {
+- list_add(&req->list, &dev->rx_reqs_active);
+- }
+- }
++ setup_rx_reqs(dev);
+
+ bytes_copied = 0;
+ current_rx_req = dev->current_rx_req;
+@@ -615,9 +629,9 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
+
+ spin_lock_irqsave(&dev->lock, flags);
+
+- /* We've disconnected or reset free the req and buffer */
++ /* We've disconnected or reset so return. */
+ if (dev->reset_printer) {
+- printer_req_free(dev->out_ep, current_rx_req);
++ list_add(¤t_rx_req->list, &dev->rx_reqs);
+ spin_unlock_irqrestore(&dev->lock, flags);
+ spin_unlock(&dev->lock_printer_io);
+ return -EAGAIN;
+@@ -735,7 +749,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+
+ /* We've disconnected or reset so free the req and buffer */
+ if (dev->reset_printer) {
+- printer_req_free(dev->in_ep, req);
++ list_add(&req->list, &dev->tx_reqs);
+ spin_unlock_irqrestore(&dev->lock, flags);
+ spin_unlock(&dev->lock_printer_io);
+ return -EAGAIN;
+@@ -791,6 +805,12 @@ printer_poll(struct file *fd, poll_table *wait)
+ unsigned long flags;
+ int status = 0;
+
++ spin_lock(&dev->lock_printer_io);
++ spin_lock_irqsave(&dev->lock, flags);
++ setup_rx_reqs(dev);
++ spin_unlock_irqrestore(&dev->lock, flags);
++ spin_unlock(&dev->lock_printer_io);
++
+ poll_wait(fd, &dev->rx_wait, wait);
+ poll_wait(fd, &dev->tx_wait, wait);
+
+@@ -798,7 +818,8 @@ printer_poll(struct file *fd, poll_table *wait)
+ if (likely(!list_empty(&dev->tx_reqs)))
+ status |= POLLOUT | POLLWRNORM;
+
+- if (likely(!list_empty(&dev->rx_buffers)))
++ if (likely(dev->current_rx_bytes) ||
++ likely(!list_empty(&dev->rx_buffers)))
+ status |= POLLIN | POLLRDNORM;
+
+ spin_unlock_irqrestore(&dev->lock, flags);
+@@ -894,7 +915,7 @@ static void printer_reset_interface(struct printer_dev *dev)
+ if (dev->interface < 0)
+ return;
+
+- DBG(dev, "%s\n", __FUNCTION__);
++ DBG(dev, "%s\n", __func__);
+
+ if (dev->in)
+ usb_ep_disable(dev->in_ep);
+@@ -1084,6 +1105,7 @@ static void printer_soft_reset(struct printer_dev *dev)
+ if (usb_ep_enable(dev->out_ep, dev->out))
+ DBG(dev, "Failed to enable USB out_ep\n");
+
++ wake_up_interruptible(&dev->rx_wait);
+ wake_up_interruptible(&dev->tx_wait);
+ wake_up_interruptible(&dev->tx_flush_wait);
+ }
+@@ -1262,7 +1284,7 @@ printer_disconnect(struct usb_gadget *gadget)
+ struct printer_dev *dev = get_gadget_data(gadget);
+ unsigned long flags;
+
+- DBG(dev, "%s\n", __FUNCTION__);
++ DBG(dev, "%s\n", __func__);
+
+ spin_lock_irqsave(&dev->lock, flags);
+
+@@ -1278,7 +1300,7 @@ printer_unbind(struct usb_gadget *gadget)
+ struct usb_request *req;
+
+
+- DBG(dev, "%s\n", __FUNCTION__);
++ DBG(dev, "%s\n", __func__);
+
+ /* Remove sysfs files */
+ device_destroy(usb_gadget_class, g_printer_devno);
+diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
+index c00cd8b..08f699b 100644
+--- a/drivers/usb/gadget/pxa2xx_udc.c
++++ b/drivers/usb/gadget/pxa2xx_udc.c
+@@ -235,7 +235,7 @@ static int pxa2xx_ep_enable (struct usb_ep *_ep,
+ || ep->bEndpointAddress != desc->bEndpointAddress
+ || ep->fifo_size < le16_to_cpu
+ (desc->wMaxPacketSize)) {
+- DMSG("%s, bad ep or descriptor\n", __FUNCTION__);
++ DMSG("%s, bad ep or descriptor\n", __func__);
+ return -EINVAL;
+ }
+
+@@ -243,7 +243,7 @@ static int pxa2xx_ep_enable (struct usb_ep *_ep,
+ if (ep->bmAttributes != desc->bmAttributes
+ && ep->bmAttributes != USB_ENDPOINT_XFER_BULK
+ && desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
+- DMSG("%s, %s type mismatch\n", __FUNCTION__, _ep->name);
++ DMSG("%s, %s type mismatch\n", __func__, _ep->name);
+ return -EINVAL;
+ }
+
+@@ -252,13 +252,13 @@ static int pxa2xx_ep_enable (struct usb_ep *_ep,
+ && le16_to_cpu (desc->wMaxPacketSize)
+ != BULK_FIFO_SIZE)
+ || !desc->wMaxPacketSize) {
+- DMSG("%s, bad %s maxpacket\n", __FUNCTION__, _ep->name);
++ DMSG("%s, bad %s maxpacket\n", __func__, _ep->name);
+ return -ERANGE;
+ }
+
+ dev = ep->dev;
+ if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
+- DMSG("%s, bogus device state\n", __FUNCTION__);
++ DMSG("%s, bogus device state\n", __func__);
+ return -ESHUTDOWN;
+ }
+
+@@ -283,7 +283,7 @@ static int pxa2xx_ep_disable (struct usb_ep *_ep)
+
+ ep = container_of (_ep, struct pxa2xx_ep, ep);
+ if (!_ep || !ep->desc) {
+- DMSG("%s, %s not enabled\n", __FUNCTION__,
++ DMSG("%s, %s not enabled\n", __func__,
+ _ep ? ep->ep.name : NULL);
+ return -EINVAL;
+ }
+@@ -461,7 +461,7 @@ void ep0start(struct pxa2xx_udc *dev, u32 flags, const char *tag)
+ USIR0 = USIR0_IR0;
+ dev->req_pending = 0;
+ DBG(DBG_VERY_NOISY, "%s %s, %02x/%02x\n",
+- __FUNCTION__, tag, UDCCS0, flags);
++ __func__, tag, UDCCS0, flags);
+ }
+
+ static int
+@@ -651,20 +651,20 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+ req = container_of(_req, struct pxa2xx_request, req);
+ if (unlikely (!_req || !_req->complete || !_req->buf
+ || !list_empty(&req->queue))) {
+- DMSG("%s, bad params\n", __FUNCTION__);
++ DMSG("%s, bad params\n", __func__);
+ return -EINVAL;
+ }
+
+ ep = container_of(_ep, struct pxa2xx_ep, ep);
+ if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+- DMSG("%s, bad ep\n", __FUNCTION__);
++ DMSG("%s, bad ep\n", __func__);
+ return -EINVAL;
+ }
+
+ dev = ep->dev;
+ if (unlikely (!dev->driver
+ || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
+- DMSG("%s, bogus device state\n", __FUNCTION__);
++ DMSG("%s, bogus device state\n", __func__);
+ return -ESHUTDOWN;
+ }
+
+@@ -807,7 +807,7 @@ static int pxa2xx_ep_set_halt(struct usb_ep *_ep, int value)
+ if (unlikely (!_ep
+ || (!ep->desc && ep->ep.name != ep0name))
+ || ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+- DMSG("%s, bad ep\n", __FUNCTION__);
++ DMSG("%s, bad ep\n", __func__);
+ return -EINVAL;
+ }
+ if (value == 0) {
+@@ -859,7 +859,7 @@ static int pxa2xx_ep_fifo_status(struct usb_ep *_ep)
+
+ ep = container_of(_ep, struct pxa2xx_ep, ep);
+ if (!_ep) {
+- DMSG("%s, bad ep\n", __FUNCTION__);
++ DMSG("%s, bad ep\n", __func__);
+ return -ENODEV;
+ }
+ /* pxa can't report unclaimed bytes from IN fifos */
+@@ -878,7 +878,7 @@ static void pxa2xx_ep_fifo_flush(struct usb_ep *_ep)
+
+ ep = container_of(_ep, struct pxa2xx_ep, ep);
+ if (!_ep || ep->ep.name == ep0name || !list_empty(&ep->queue)) {
+- DMSG("%s, bad ep\n", __FUNCTION__);
++ DMSG("%s, bad ep\n", __func__);
+ return;
+ }
+
+@@ -1813,7 +1813,7 @@ pxa2xx_udc_irq(int irq, void *_dev)
+
+ static void nop_release (struct device *dev)
+ {
+- DMSG("%s %s\n", __FUNCTION__, dev->bus_id);
++ DMSG("%s %s\n", __func__, dev->bus_id);
+ }
+
+ /* this uses load-time allocation and initialization (instead of
+diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
+index 3d03664..bd58dd5 100644
+--- a/drivers/usb/gadget/rndis.c
++++ b/drivers/usb/gadget/rndis.c
+@@ -204,7 +204,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+
+ /* mandatory */
+ case OID_GEN_SUPPORTED_LIST:
+- DBG("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__);
++ DBG("%s: OID_GEN_SUPPORTED_LIST\n", __func__);
+ length = sizeof (oid_supported_list);
+ count = length / sizeof (u32);
+ for (i = 0; i < count; i++)
+@@ -214,7 +214,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+
+ /* mandatory */
+ case OID_GEN_HARDWARE_STATUS:
+- DBG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__);
++ DBG("%s: OID_GEN_HARDWARE_STATUS\n", __func__);
+ /* Bogus question!
+ * Hardware must be ready to receive high level protocols.
+ * BTW:
+@@ -227,14 +227,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+
+ /* mandatory */
+ case OID_GEN_MEDIA_SUPPORTED:
+- DBG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__);
++ DBG("%s: OID_GEN_MEDIA_SUPPORTED\n", __func__);
+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
+ retval = 0;
+ break;
+
+ /* mandatory */
+ case OID_GEN_MEDIA_IN_USE:
+- DBG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__);
++ DBG("%s: OID_GEN_MEDIA_IN_USE\n", __func__);
+ /* one medium, one transport... (maybe you do it better) */
+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
+ retval = 0;
+@@ -242,7 +242,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+
+ /* mandatory */
+ case OID_GEN_MAXIMUM_FRAME_SIZE:
+- DBG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__);
++ DBG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __func__);
+ if (rndis_per_dev_params [configNr].dev) {
+ *outbuf = cpu_to_le32 (
+ rndis_per_dev_params [configNr].dev->mtu);
+@@ -253,7 +253,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ /* mandatory */
+ case OID_GEN_LINK_SPEED:
+ if (rndis_debug > 1)
+- DBG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__);
++ DBG("%s: OID_GEN_LINK_SPEED\n", __func__);
+ if (rndis_per_dev_params [configNr].media_state
+ == NDIS_MEDIA_STATE_DISCONNECTED)
+ *outbuf = __constant_cpu_to_le32 (0);
+@@ -265,7 +265,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+
+ /* mandatory */
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:
+- DBG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__);
++ DBG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __func__);
+ if (rndis_per_dev_params [configNr].dev) {
+ *outbuf = cpu_to_le32 (
+ rndis_per_dev_params [configNr].dev->mtu);
+@@ -275,7 +275,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+
+ /* mandatory */
+ case OID_GEN_RECEIVE_BLOCK_SIZE:
+- DBG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__);
++ DBG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __func__);
+ if (rndis_per_dev_params [configNr].dev) {
+ *outbuf = cpu_to_le32 (
+ rndis_per_dev_params [configNr].dev->mtu);
+@@ -285,7 +285,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+
+ /* mandatory */
+ case OID_GEN_VENDOR_ID:
+- DBG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__);
++ DBG("%s: OID_GEN_VENDOR_ID\n", __func__);
+ *outbuf = cpu_to_le32 (
+ rndis_per_dev_params [configNr].vendorID);
+ retval = 0;
+@@ -293,7 +293,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+
+ /* mandatory */
+ case OID_GEN_VENDOR_DESCRIPTION:
+- DBG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__);
++ DBG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__);
+ length = strlen (rndis_per_dev_params [configNr].vendorDescr);
+ memcpy (outbuf,
+ rndis_per_dev_params [configNr].vendorDescr, length);
+@@ -301,7 +301,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ break;
+
+ case OID_GEN_VENDOR_DRIVER_VERSION:
+- DBG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__);
++ DBG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __func__);
+ /* Created as LE */
+ *outbuf = rndis_driver_version;
+ retval = 0;
+@@ -309,14 +309,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+
+ /* mandatory */
+ case OID_GEN_CURRENT_PACKET_FILTER:
+- DBG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__);
++ DBG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __func__);
+ *outbuf = cpu_to_le32 (*rndis_per_dev_params[configNr].filter);
+ retval = 0;
+ break;
+
+ /* mandatory */
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:
+- DBG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__);
++ DBG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __func__);
+ *outbuf = __constant_cpu_to_le32(RNDIS_MAX_TOTAL_SIZE);
+ retval = 0;
+ break;
+@@ -324,14 +324,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ /* mandatory */
+ case OID_GEN_MEDIA_CONNECT_STATUS:
+ if (rndis_debug > 1)
+- DBG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__);
++ DBG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __func__);
+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ .media_state);
+ retval = 0;
+ break;
+
+ case OID_GEN_PHYSICAL_MEDIUM:
+- DBG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__);
++ DBG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __func__);
+ *outbuf = __constant_cpu_to_le32 (0);
+ retval = 0;
+ break;
+@@ -341,7 +341,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ * versions emit undefined RNDIS messages. DOCUMENT ALL THESE!
+ */
+ case OID_GEN_MAC_OPTIONS: /* from WinME */
+- DBG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__);
++ DBG("%s: OID_GEN_MAC_OPTIONS\n", __func__);
+ *outbuf = __constant_cpu_to_le32(
+ NDIS_MAC_OPTION_RECEIVE_SERIALIZED
+ | NDIS_MAC_OPTION_FULL_DUPLEX);
+@@ -353,7 +353,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ /* mandatory */
+ case OID_GEN_XMIT_OK:
+ if (rndis_debug > 1)
+- DBG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__);
++ DBG("%s: OID_GEN_XMIT_OK\n", __func__);
+ if (rndis_per_dev_params [configNr].stats) {
+ *outbuf = cpu_to_le32 (
+ rndis_per_dev_params [configNr].stats->tx_packets -
+@@ -366,7 +366,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ /* mandatory */
+ case OID_GEN_RCV_OK:
+ if (rndis_debug > 1)
+- DBG("%s: OID_GEN_RCV_OK\n", __FUNCTION__);
++ DBG("%s: OID_GEN_RCV_OK\n", __func__);
+ if (rndis_per_dev_params [configNr].stats) {
+ *outbuf = cpu_to_le32 (
+ rndis_per_dev_params [configNr].stats->rx_packets -
+@@ -379,7 +379,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ /* mandatory */
+ case OID_GEN_XMIT_ERROR:
+ if (rndis_debug > 1)
+- DBG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__);
++ DBG("%s: OID_GEN_XMIT_ERROR\n", __func__);
+ if (rndis_per_dev_params [configNr].stats) {
+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ .stats->tx_errors);
+@@ -390,7 +390,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ /* mandatory */
+ case OID_GEN_RCV_ERROR:
+ if (rndis_debug > 1)
+- DBG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__);
++ DBG("%s: OID_GEN_RCV_ERROR\n", __func__);
+ if (rndis_per_dev_params [configNr].stats) {
+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ .stats->rx_errors);
+@@ -400,7 +400,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+
+ /* mandatory */
+ case OID_GEN_RCV_NO_BUFFER:
+- DBG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__);
++ DBG("%s: OID_GEN_RCV_NO_BUFFER\n", __func__);
+ if (rndis_per_dev_params [configNr].stats) {
+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ .stats->rx_dropped);
+@@ -410,7 +410,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+
+ #ifdef RNDIS_OPTIONAL_STATS
+ case OID_GEN_DIRECTED_BYTES_XMIT:
+- DBG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__);
++ DBG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __func__);
+ /*
+ * Aunt Tilly's size of shoes
+ * minus antarctica count of penguins
+@@ -430,7 +430,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ break;
+
+ case OID_GEN_DIRECTED_FRAMES_XMIT:
+- DBG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__);
++ DBG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __func__);
+ /* dito */
+ if (rndis_per_dev_params [configNr].stats) {
+ *outbuf = cpu_to_le32 (
+@@ -446,7 +446,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ break;
+
+ case OID_GEN_MULTICAST_BYTES_XMIT:
+- DBG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__);
++ DBG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __func__);
+ if (rndis_per_dev_params [configNr].stats) {
+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ .stats->multicast*1234);
+@@ -455,7 +455,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ break;
+
+ case OID_GEN_MULTICAST_FRAMES_XMIT:
+- DBG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__);
++ DBG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __func__);
+ if (rndis_per_dev_params [configNr].stats) {
+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ .stats->multicast);
+@@ -464,7 +464,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ break;
+
+ case OID_GEN_BROADCAST_BYTES_XMIT:
+- DBG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__);
++ DBG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __func__);
+ if (rndis_per_dev_params [configNr].stats) {
+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ .stats->tx_packets/42*255);
+@@ -473,7 +473,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ break;
+
+ case OID_GEN_BROADCAST_FRAMES_XMIT:
+- DBG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__);
++ DBG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __func__);
+ if (rndis_per_dev_params [configNr].stats) {
+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ .stats->tx_packets/42);
+@@ -482,19 +482,19 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ break;
+
+ case OID_GEN_DIRECTED_BYTES_RCV:
+- DBG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__);
++ DBG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __func__);
+ *outbuf = __constant_cpu_to_le32 (0);
+ retval = 0;
+ break;
+
+ case OID_GEN_DIRECTED_FRAMES_RCV:
+- DBG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__);
++ DBG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __func__);
+ *outbuf = __constant_cpu_to_le32 (0);
+ retval = 0;
+ break;
+
+ case OID_GEN_MULTICAST_BYTES_RCV:
+- DBG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__);
++ DBG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __func__);
+ if (rndis_per_dev_params [configNr].stats) {
+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ .stats->multicast * 1111);
+@@ -503,7 +503,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ break;
+
+ case OID_GEN_MULTICAST_FRAMES_RCV:
+- DBG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__);
++ DBG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __func__);
+ if (rndis_per_dev_params [configNr].stats) {
+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ .stats->multicast);
+@@ -512,7 +512,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ break;
+
+ case OID_GEN_BROADCAST_BYTES_RCV:
+- DBG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__);
++ DBG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __func__);
+ if (rndis_per_dev_params [configNr].stats) {
+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ .stats->rx_packets/42*255);
+@@ -521,7 +521,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ break;
+
+ case OID_GEN_BROADCAST_FRAMES_RCV:
+- DBG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__);
++ DBG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __func__);
+ if (rndis_per_dev_params [configNr].stats) {
+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ .stats->rx_packets/42);
+@@ -530,7 +530,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ break;
+
+ case OID_GEN_RCV_CRC_ERROR:
+- DBG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__);
++ DBG("%s: OID_GEN_RCV_CRC_ERROR\n", __func__);
+ if (rndis_per_dev_params [configNr].stats) {
+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ .stats->rx_crc_errors);
+@@ -539,7 +539,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ break;
+
+ case OID_GEN_TRANSMIT_QUEUE_LENGTH:
+- DBG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__);
++ DBG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __func__);
+ *outbuf = __constant_cpu_to_le32 (0);
+ retval = 0;
+ break;
+@@ -549,7 +549,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+
+ /* mandatory */
+ case OID_802_3_PERMANENT_ADDRESS:
+- DBG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__);
++ DBG("%s: OID_802_3_PERMANENT_ADDRESS\n", __func__);
+ if (rndis_per_dev_params [configNr].dev) {
+ length = ETH_ALEN;
+ memcpy (outbuf,
+@@ -561,7 +561,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+
+ /* mandatory */
+ case OID_802_3_CURRENT_ADDRESS:
+- DBG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__);
++ DBG("%s: OID_802_3_CURRENT_ADDRESS\n", __func__);
+ if (rndis_per_dev_params [configNr].dev) {
+ length = ETH_ALEN;
+ memcpy (outbuf,
+@@ -573,7 +573,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+
+ /* mandatory */
+ case OID_802_3_MULTICAST_LIST:
+- DBG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
++ DBG("%s: OID_802_3_MULTICAST_LIST\n", __func__);
+ /* Multicast base address only */
+ *outbuf = __constant_cpu_to_le32 (0xE0000000);
+ retval = 0;
+@@ -581,21 +581,21 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+
+ /* mandatory */
+ case OID_802_3_MAXIMUM_LIST_SIZE:
+- DBG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__);
++ DBG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __func__);
+ /* Multicast base address only */
+ *outbuf = __constant_cpu_to_le32 (1);
+ retval = 0;
+ break;
+
+ case OID_802_3_MAC_OPTIONS:
+- DBG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__);
++ DBG("%s: OID_802_3_MAC_OPTIONS\n", __func__);
+ break;
+
+ /* ieee802.3 statistics OIDs (table 4-4) */
+
+ /* mandatory */
+ case OID_802_3_RCV_ERROR_ALIGNMENT:
+- DBG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__);
++ DBG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __func__);
+ if (rndis_per_dev_params [configNr].stats) {
+ *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+ .stats->rx_frame_errors);
+@@ -605,51 +605,51 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+
+ /* mandatory */
+ case OID_802_3_XMIT_ONE_COLLISION:
+- DBG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__);
++ DBG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __func__);
+ *outbuf = __constant_cpu_to_le32 (0);
+ retval = 0;
+ break;
+
+ /* mandatory */
+ case OID_802_3_XMIT_MORE_COLLISIONS:
+- DBG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__);
++ DBG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __func__);
+ *outbuf = __constant_cpu_to_le32 (0);
+ retval = 0;
+ break;
+
+ #ifdef RNDIS_OPTIONAL_STATS
+ case OID_802_3_XMIT_DEFERRED:
+- DBG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__);
++ DBG("%s: OID_802_3_XMIT_DEFERRED\n", __func__);
+ /* TODO */
+ break;
+
+ case OID_802_3_XMIT_MAX_COLLISIONS:
+- DBG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__);
++ DBG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __func__);
+ /* TODO */
+ break;
+
+ case OID_802_3_RCV_OVERRUN:
+- DBG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__);
++ DBG("%s: OID_802_3_RCV_OVERRUN\n", __func__);
+ /* TODO */
+ break;
+
+ case OID_802_3_XMIT_UNDERRUN:
+- DBG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__);
++ DBG("%s: OID_802_3_XMIT_UNDERRUN\n", __func__);
+ /* TODO */
+ break;
+
+ case OID_802_3_XMIT_HEARTBEAT_FAILURE:
+- DBG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__);
++ DBG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __func__);
+ /* TODO */
+ break;
+
+ case OID_802_3_XMIT_TIMES_CRS_LOST:
+- DBG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__);
++ DBG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __func__);
+ /* TODO */
+ break;
+
+ case OID_802_3_XMIT_LATE_COLLISIONS:
+- DBG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__);
++ DBG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __func__);
+ /* TODO */
+ break;
+ #endif /* RNDIS_OPTIONAL_STATS */
+@@ -657,7 +657,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ #ifdef RNDIS_PM
+ /* power management OIDs (table 4-5) */
+ case OID_PNP_CAPABILITIES:
+- DBG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__);
++ DBG("%s: OID_PNP_CAPABILITIES\n", __func__);
+
+ /* for now, no wakeup capabilities */
+ length = sizeof (struct NDIS_PNP_CAPABILITIES);
+@@ -665,7 +665,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+ retval = 0;
+ break;
+ case OID_PNP_QUERY_POWER:
+- DBG("%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__,
++ DBG("%s: OID_PNP_QUERY_POWER D%d\n", __func__,
+ le32_to_cpu(get_unaligned((__le32 *)buf)) - 1);
+ /* only suspend is a real power state, and
+ * it can't be entered by OID_PNP_SET_POWER...
+@@ -677,7 +677,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
+
+ default:
+ pr_warning("%s: query unknown OID 0x%08X\n",
+- __FUNCTION__, OID);
++ __func__, OID);
+ }
+ if (retval < 0)
+ length = 0;
+@@ -729,7 +729,7 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
+ *params->filter = (u16) le32_to_cpu(get_unaligned(
+ (__le32 *)buf));
+ DBG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
+- __FUNCTION__, *params->filter);
++ __func__, *params->filter);
+
+ /* this call has a significant side effect: it's
+ * what makes the packet flow start and stop, like
+@@ -753,7 +753,7 @@ update_linkstate:
+
+ case OID_802_3_MULTICAST_LIST:
+ /* I think we can ignore this */
+- DBG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
++ DBG("%s: OID_802_3_MULTICAST_LIST\n", __func__);
+ retval = 0;
+ break;
+ #if 0
+@@ -762,7 +762,7 @@ update_linkstate:
+ struct rndis_config_parameter *param;
+ param = (struct rndis_config_parameter *) buf;
+ DBG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n",
+- __FUNCTION__,
++ __func__,
+ min(cpu_to_le32(param->ParameterNameLength),80),
+ buf + param->ParameterNameOffset);
+ retval = 0;
+@@ -778,7 +778,7 @@ update_linkstate:
+ * FIXME ... then things go batty; Windows wedges itself.
+ */
+ i = le32_to_cpu(get_unaligned((__le32 *)buf));
+- DBG("%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1);
++ DBG("%s: OID_PNP_SET_POWER D%d\n", __func__, i - 1);
+ switch (i) {
+ case NdisDeviceStateD0:
+ *params->filter = params->saved_filter;
+@@ -802,7 +802,7 @@ update_linkstate:
+
+ default:
+ pr_warning("%s: set unknown OID 0x%08X, size %d\n",
+- __FUNCTION__, OID, buf_len);
++ __func__, OID, buf_len);
+ }
+
+ return retval;
+@@ -855,7 +855,7 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
+ rndis_query_cmplt_type *resp;
+ rndis_resp_t *r;
+
+- // DBG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID));
++ // DBG("%s: OID = %08X\n", __func__, cpu_to_le32(buf->OID));
+ if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
+
+ /*
+@@ -908,9 +908,9 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
+ BufOffset = le32_to_cpu (buf->InformationBufferOffset);
+
+ #ifdef VERBOSE
+- DBG("%s: Length: %d\n", __FUNCTION__, BufLength);
+- DBG("%s: Offset: %d\n", __FUNCTION__, BufOffset);
+- DBG("%s: InfoBuffer: ", __FUNCTION__);
++ DBG("%s: Length: %d\n", __func__, BufLength);
++ DBG("%s: Offset: %d\n", __func__, BufOffset);
++ DBG("%s: InfoBuffer: ", __func__);
+
+ for (i = 0; i < BufLength; i++) {
+ DBG("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
+@@ -1080,14 +1080,14 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
+ switch (MsgType) {
+ case REMOTE_NDIS_INITIALIZE_MSG:
+ DBG("%s: REMOTE_NDIS_INITIALIZE_MSG\n",
+- __FUNCTION__ );
++ __func__ );
+ params->state = RNDIS_INITIALIZED;
+ return rndis_init_response (configNr,
+ (rndis_init_msg_type *) buf);
+
+ case REMOTE_NDIS_HALT_MSG:
+ DBG("%s: REMOTE_NDIS_HALT_MSG\n",
+- __FUNCTION__ );
++ __func__ );
+ params->state = RNDIS_UNINITIALIZED;
+ if (params->dev) {
+ netif_carrier_off (params->dev);
+@@ -1105,7 +1105,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
+
+ case REMOTE_NDIS_RESET_MSG:
+ DBG("%s: REMOTE_NDIS_RESET_MSG\n",
+- __FUNCTION__ );
++ __func__ );
+ return rndis_reset_response (configNr,
+ (rndis_reset_msg_type *) buf);
+
+@@ -1113,7 +1113,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
+ /* For USB: host does this every 5 seconds */
+ if (rndis_debug > 1)
+ DBG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n",
+- __FUNCTION__ );
++ __func__ );
+ return rndis_keepalive_response (configNr,
+ (rndis_keepalive_msg_type *)
+ buf);
+@@ -1124,7 +1124,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
+ * suspending itself.
+ */
+ pr_warning("%s: unknown RNDIS message 0x%08X len %d\n",
+- __FUNCTION__ , MsgType, MsgLength);
++ __func__ , MsgType, MsgLength);
+ {
+ unsigned i;
+ for (i = 0; i < MsgLength; i += 16) {
+@@ -1159,7 +1159,7 @@ int rndis_register (int (* rndis_control_ack) (struct net_device *))
+ if (!rndis_per_dev_params [i].used) {
+ rndis_per_dev_params [i].used = 1;
+ rndis_per_dev_params [i].ack = rndis_control_ack;
+- DBG("%s: configNr = %d\n", __FUNCTION__, i);
++ DBG("%s: configNr = %d\n", __func__, i);
+ return i;
+ }
+ }
+@@ -1170,7 +1170,7 @@ int rndis_register (int (* rndis_control_ack) (struct net_device *))
+
+ void rndis_deregister (int configNr)
+ {
+- DBG("%s: \n", __FUNCTION__ );
++ DBG("%s: \n", __func__ );
+
+ if (configNr >= RNDIS_MAX_CONFIGS) return;
+ rndis_per_dev_params [configNr].used = 0;
+@@ -1182,7 +1182,7 @@ int rndis_set_param_dev (u8 configNr, struct net_device *dev,
+ struct net_device_stats *stats,
+ u16 *cdc_filter)
+ {
+- DBG("%s:\n", __FUNCTION__ );
++ DBG("%s:\n", __func__ );
+ if (!dev || !stats) return -1;
+ if (configNr >= RNDIS_MAX_CONFIGS) return -1;
+
+@@ -1195,7 +1195,7 @@ int rndis_set_param_dev (u8 configNr, struct net_device *dev,
+
+ int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
+ {
+- DBG("%s:\n", __FUNCTION__ );
++ DBG("%s:\n", __func__ );
+ if (!vendorDescr) return -1;
+ if (configNr >= RNDIS_MAX_CONFIGS) return -1;
+
+@@ -1207,7 +1207,7 @@ int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
+
+ int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed)
+ {
+- DBG("%s: %u %u\n", __FUNCTION__, medium, speed);
++ DBG("%s: %u %u\n", __func__, medium, speed);
+ if (configNr >= RNDIS_MAX_CONFIGS) return -1;
+
+ rndis_per_dev_params [configNr].medium = medium;
+@@ -1403,7 +1403,7 @@ static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
+ #endif /* CONFIG_USB_GADGET_DEBUG_FILES */
+
+
+-int __devinit rndis_init (void)
++int __init rndis_init (void)
+ {
+ u8 i;
+
+@@ -1415,7 +1415,7 @@ int __devinit rndis_init (void)
+ if (!(rndis_connect_state [i]
+ = create_proc_entry (name, 0660, NULL)))
+ {
+- DBG("%s :remove entries", __FUNCTION__);
++ DBG("%s :remove entries", __func__);
+ while (i) {
+ sprintf (name, NAME_TEMPLATE, --i);
+ remove_proc_entry (name, NULL);
+diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
+index f5c3896..433b3f4 100644
+--- a/drivers/usb/gadget/serial.c
++++ b/drivers/usb/gadget/serial.c
+@@ -2163,8 +2163,7 @@ static void gs_free_ports(struct gs_dev *dev)
+ port->port_dev = NULL;
+ wake_up_interruptible(&port->port_write_wait);
+ if (port->port_tty) {
+- wake_up_interruptible(&port->port_tty->read_wait);
+- wake_up_interruptible(&port->port_tty->write_wait);
++ tty_hangup(port->port_tty);
+ }
+ spin_unlock_irqrestore(&port->port_lock, flags);
+ } else {
+diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
+index bf8be2a..0b87480 100644
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -30,8 +30,8 @@ config USB_EHCI_HCD
+ module will be called ehci-hcd.
+
+ config USB_EHCI_ROOT_HUB_TT
+- bool "Root Hub Transaction Translators (EXPERIMENTAL)"
+- depends on USB_EHCI_HCD && EXPERIMENTAL
++ bool "Root Hub Transaction Translators"
++ depends on USB_EHCI_HCD
+ ---help---
+ Some EHCI chips have vendor-specific extensions to integrate
+ transaction translators, so that no OHCI or UHCI companion
+@@ -260,3 +260,9 @@ config USB_R8A66597_HCD
+ To compile this driver as a module, choose M here: the
+ module will be called r8a66597-hcd.
+
++config SUPERH_ON_CHIP_R8A66597
++ boolean "Enable SuperH on-chip USB like the R8A66597"
++ depends on USB_R8A66597_HCD && CPU_SUBTYPE_SH7366
++ help
++ Renesas SuperH processor has USB like the R8A66597.
++ This driver supported processor is SH7366.
+diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
+index da7532d..8b5f991 100644
+--- a/drivers/usb/host/ehci-au1xxx.c
++++ b/drivers/usb/host/ehci-au1xxx.c
+@@ -237,6 +237,7 @@ static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
+ if (usb_disabled())
+ return -ENODEV;
+
++ /* FIXME we only want one one probe() not two */
+ ret = usb_ehci_au1xxx_probe(&ehci_au1xxx_hc_driver, &hcd, pdev);
+ return ret;
+ }
+@@ -245,6 +246,7 @@ static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
+ {
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
++ /* FIXME we only want one one remove() not two */
+ usb_ehci_au1xxx_remove(hcd, pdev);
+ return 0;
+ }
+@@ -265,7 +267,7 @@ static int ehci_hcd_au1xxx_drv_resume(struct device *dev)
+ return 0;
+ }
+ */
+-MODULE_ALIAS("au1xxx-ehci");
++MODULE_ALIAS("platform:au1xxx-ehci");
+ static struct platform_driver ehci_hcd_au1xxx_driver = {
+ .probe = ehci_hcd_au1xxx_drv_probe,
+ .remove = ehci_hcd_au1xxx_drv_remove,
+@@ -274,6 +276,5 @@ static struct platform_driver ehci_hcd_au1xxx_driver = {
+ /*.resume = ehci_hcd_au1xxx_drv_resume, */
+ .driver = {
+ .name = "au1xxx-ehci",
+- .bus = &platform_bus_type
+ }
+ };
+diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
+index 64ebfc5..4af90df 100644
+--- a/drivers/usb/host/ehci-dbg.c
++++ b/drivers/usb/host/ehci-dbg.c
+@@ -27,7 +27,7 @@
+ #define ehci_warn(ehci, fmt, args...) \
+ dev_warn (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
+
+-#ifdef EHCI_VERBOSE_DEBUG
++#ifdef VERBOSE_DEBUG
+ # define vdbg dbg
+ # define ehci_vdbg ehci_dbg
+ #else
+@@ -670,7 +670,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
+
+ spin_lock_irqsave (&ehci->lock, flags);
+
+- if (buf->bus->controller->power.power_state.event) {
++ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+ size = scnprintf (next, size,
+ "bus %s, device %s (driver " DRIVER_VERSION ")\n"
+ "%s\n"
+diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
+index adb0def..6d9bed6 100644
+--- a/drivers/usb/host/ehci-fsl.c
++++ b/drivers/usb/host/ehci-fsl.c
+@@ -1,5 +1,4 @@
+ /*
+- * (C) Copyright David Brownell 2000-2002
+ * Copyright (c) 2005 MontaVista Software
+ *
+ * This program is free software; you can redistribute it and/or modify it
+@@ -28,7 +27,6 @@
+ /* FIXME: Power Management is un-ported so temporarily disable it */
+ #undef CONFIG_PM
+
+-/* PCI-based HCs are common, but plenty of non-PCI HCs are used too */
+
+ /* configure so an HC device and id are always provided */
+ /* always called with process context; sleeping is OK */
+@@ -331,6 +329,7 @@ static int ehci_fsl_drv_probe(struct platform_device *pdev)
+ if (usb_disabled())
+ return -ENODEV;
+
++ /* FIXME we only want one one probe() not two */
+ return usb_hcd_fsl_probe(&ehci_fsl_hc_driver, pdev);
+ }
+
+@@ -338,12 +337,12 @@ static int ehci_fsl_drv_remove(struct platform_device *pdev)
+ {
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
++ /* FIXME we only want one one remove() not two */
+ usb_hcd_fsl_remove(hcd, pdev);
+-
+ return 0;
+ }
+
+-MODULE_ALIAS("fsl-ehci");
++MODULE_ALIAS("platform:fsl-ehci");
+
+ static struct platform_driver ehci_fsl_driver = {
+ .probe = ehci_fsl_drv_probe,
+@@ -351,5 +350,5 @@ static struct platform_driver ehci_fsl_driver = {
+ .shutdown = usb_hcd_platform_shutdown,
+ .driver = {
+ .name = "fsl-ehci",
+- },
++ },
+ };
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 46ee7f4..369a8a5 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -57,35 +57,6 @@
+ * Special thanks to Intel and VIA for providing host controllers to
+ * test this driver on, and Cypress (including In-System Design) for
+ * providing early devices for those host controllers to talk to!
+- *
+- * HISTORY:
+- *
+- * 2004-05-10 Root hub and PCI suspend/resume support; remote wakeup. (db)
+- * 2004-02-24 Replace pci_* with generic dma_* API calls (dsaxena at plexity.net)
+- * 2003-12-29 Rewritten high speed iso transfer support (by Michal Sojka,
+- * <sojkam at centrum.cz>, updates by DB).
+- *
+- * 2002-11-29 Correct handling for hw async_next register.
+- * 2002-08-06 Handling for bulk and interrupt transfers is mostly shared;
+- * only scheduling is different, no arbitrary limitations.
+- * 2002-07-25 Sanity check PCI reads, mostly for better cardbus support,
+- * clean up HC run state handshaking.
+- * 2002-05-24 Preliminary FS/LS interrupts, using scheduling shortcuts
+- * 2002-05-11 Clear TT errors for FS/LS ctrl/bulk. Fill in some other
+- * missing pieces: enabling 64bit dma, handoff from BIOS/SMM.
+- * 2002-05-07 Some error path cleanups to report better errors; wmb();
+- * use non-CVS version id; better iso bandwidth claim.
+- * 2002-04-19 Control/bulk/interrupt submit no longer uses giveback() on
+- * errors in submit path. Bugfixes to interrupt scheduling/processing.
+- * 2002-03-05 Initial high-speed ISO support; reduce ITD memory; shift
+- * more checking to generic hcd framework (db). Make it work with
+- * Philips EHCI; reduce PCI traffic; shorten IRQ path (Rory Bolt).
+- * 2002-01-14 Minor cleanup; version synch.
+- * 2002-01-08 Fix roothub handoff of FS/LS to companion controllers.
+- * 2002-01-04 Control/Bulk queuing behaves.
+- *
+- * 2001-12-12 Initial patch version for Linux 2.5.1 kernel.
+- * 2001-June Works with usb-storage and NEC EHCI on 2.4
+ */
+
+ #define DRIVER_VERSION "10 Dec 2004"
+@@ -95,7 +66,7 @@
+ static const char hcd_name [] = "ehci_hcd";
+
+
+-#undef EHCI_VERBOSE_DEBUG
++#undef VERBOSE_DEBUG
+ #undef EHCI_URB_TRACE
+
+ #ifdef DEBUG
+@@ -174,6 +145,16 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
+ return -ETIMEDOUT;
+ }
+
++static int handshake_on_error_set_halt(struct ehci_hcd *ehci, void __iomem *ptr,
++ u32 mask, u32 done, int usec)
++{
++ int error = handshake(ehci, ptr, mask, done, usec);
++ if (error)
++ ehci_to_hcd(ehci)->state = HC_STATE_HALT;
++
++ return error;
++}
++
+ /* force HC to halt state from unknown (EHCI spec section 2.3) */
+ static int ehci_halt (struct ehci_hcd *ehci)
+ {
+@@ -246,11 +227,9 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
+ /* wait for any schedule enables/disables to take effect */
+ temp = ehci_readl(ehci, &ehci->regs->command) << 10;
+ temp &= STS_ASS | STS_PSS;
+- if (handshake (ehci, &ehci->regs->status, STS_ASS | STS_PSS,
+- temp, 16 * 125) != 0) {
+- ehci_to_hcd(ehci)->state = HC_STATE_HALT;
++ if (handshake_on_error_set_halt(ehci, &ehci->regs->status,
++ STS_ASS | STS_PSS, temp, 16 * 125))
+ return;
+- }
+
+ /* then disable anything that's still active */
+ temp = ehci_readl(ehci, &ehci->regs->command);
+@@ -258,11 +237,8 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
+ ehci_writel(ehci, temp, &ehci->regs->command);
+
+ /* hardware can take 16 microframes to turn off ... */
+- if (handshake (ehci, &ehci->regs->status, STS_ASS | STS_PSS,
+- 0, 16 * 125) != 0) {
+- ehci_to_hcd(ehci)->state = HC_STATE_HALT;
+- return;
+- }
++ handshake_on_error_set_halt(ehci, &ehci->regs->status,
++ STS_ASS | STS_PSS, 0, 16 * 125);
+ }
+
+ /*-------------------------------------------------------------------------*/
+@@ -355,17 +331,13 @@ static void ehci_turn_off_all_ports(struct ehci_hcd *ehci)
+ &ehci->regs->port_status[port]);
+ }
+
+-/* ehci_shutdown kick in for silicon on any bus (not just pci, etc).
+- * This forcibly disables dma and IRQs, helping kexec and other cases
+- * where the next system software may expect clean state.
++/*
++ * Halt HC, turn off all ports, and let the BIOS use the companion controllers.
++ * Should be called with ehci->lock held.
+ */
+-static void
+-ehci_shutdown (struct usb_hcd *hcd)
++static void ehci_silence_controller(struct ehci_hcd *ehci)
+ {
+- struct ehci_hcd *ehci;
+-
+- ehci = hcd_to_ehci (hcd);
+- (void) ehci_halt (ehci);
++ ehci_halt(ehci);
+ ehci_turn_off_all_ports(ehci);
+
+ /* make BIOS/etc use companion controller during reboot */
+@@ -375,6 +347,22 @@ ehci_shutdown (struct usb_hcd *hcd)
+ ehci_readl(ehci, &ehci->regs->configured_flag);
+ }
+
++/* ehci_shutdown kick in for silicon on any bus (not just pci, etc).
++ * This forcibly disables dma and IRQs, helping kexec and other cases
++ * where the next system software may expect clean state.
++ */
++static void ehci_shutdown(struct usb_hcd *hcd)
++{
++ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
++
++ del_timer_sync(&ehci->watchdog);
++ del_timer_sync(&ehci->iaa_watchdog);
++
++ spin_lock_irq(&ehci->lock);
++ ehci_silence_controller(ehci);
++ spin_unlock_irq(&ehci->lock);
++}
++
+ static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
+ {
+ unsigned port;
+@@ -425,15 +413,15 @@ static void ehci_work (struct ehci_hcd *ehci)
+ timer_action (ehci, TIMER_IO_WATCHDOG);
+ }
+
++/*
++ * Called when the ehci_hcd module is removed.
++ */
+ static void ehci_stop (struct usb_hcd *hcd)
+ {
+ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
+
+ ehci_dbg (ehci, "stop\n");
+
+- /* Turn off port power on all root hub ports. */
+- ehci_port_power (ehci, 0);
+-
+ /* no more interrupts ... */
+ del_timer_sync (&ehci->watchdog);
+ del_timer_sync(&ehci->iaa_watchdog);
+@@ -442,13 +430,10 @@ static void ehci_stop (struct usb_hcd *hcd)
+ if (HC_IS_RUNNING (hcd->state))
+ ehci_quiesce (ehci);
+
++ ehci_silence_controller(ehci);
+ ehci_reset (ehci);
+- ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+ spin_unlock_irq(&ehci->lock);
+
+- /* let companion controllers work when we aren't */
+- ehci_writel(ehci, 0, &ehci->regs->configured_flag);
+-
+ remove_companion_file(ehci);
+ remove_debug_files (ehci);
+
+@@ -676,7 +661,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ cmd = ehci_readl(ehci, &ehci->regs->command);
+ bh = 0;
+
+-#ifdef EHCI_VERBOSE_DEBUG
++#ifdef VERBOSE_DEBUG
+ /* unrequested/ignored: Frame List Rollover */
+ dbg_status (ehci, "irq", status);
+ #endif
+@@ -710,6 +695,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ /* remote wakeup [4.3.1] */
+ if (status & STS_PCD) {
+ unsigned i = HCS_N_PORTS (ehci->hcs_params);
++
++ /* kick root hub later */
+ pcd_status = status;
+
+ /* resume root hub? */
+@@ -738,8 +725,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+
+ /* PCI errors [4.15.2.4] */
+ if (unlikely ((status & STS_FATAL) != 0)) {
+- /* bogus "fatal" IRQs appear on some chips... why? */
+- status = ehci_readl(ehci, &ehci->regs->status);
+ dbg_cmd (ehci, "fatal", ehci_readl(ehci,
+ &ehci->regs->command));
+ dbg_status (ehci, "fatal", status);
+@@ -758,7 +743,7 @@ dead:
+ if (bh)
+ ehci_work (ehci);
+ spin_unlock (&ehci->lock);
+- if (pcd_status & STS_PCD)
++ if (pcd_status)
+ usb_hcd_poll_rh_status(hcd);
+ return IRQ_HANDLED;
+ }
+@@ -788,8 +773,14 @@ static int ehci_urb_enqueue (
+ INIT_LIST_HEAD (&qtd_list);
+
+ switch (usb_pipetype (urb->pipe)) {
+- // case PIPE_CONTROL:
+- // case PIPE_BULK:
++ case PIPE_CONTROL:
++ /* qh_completions() code doesn't handle all the fault cases
++ * in multi-TD control transfers. Even 1KB is rare anyway.
++ */
++ if (urb->transfer_buffer_length > (16 * 1024))
++ return -EMSGSIZE;
++ /* FALLTHROUGH */
++ /* case PIPE_BULK: */
+ default:
+ if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags))
+ return -ENOMEM;
+@@ -1033,7 +1024,7 @@ MODULE_LICENSE ("GPL");
+ #define OF_PLATFORM_DRIVER ehci_hcd_ppc_of_driver
+ #endif
+
+-#ifdef CONFIG_ARCH_ORION
++#ifdef CONFIG_PLAT_ORION
+ #include "ehci-orion.c"
+ #define PLATFORM_DRIVER ehci_orion_driver
+ #endif
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 4e065e5..efffef6 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -28,7 +28,9 @@
+
+ /*-------------------------------------------------------------------------*/
+
+-#ifdef CONFIG_USB_PERSIST
++#define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
++
++#ifdef CONFIG_PM
+
+ static int ehci_hub_control(
+ struct usb_hcd *hcd,
+@@ -104,15 +106,6 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
+ ehci->owned_ports = 0;
+ }
+
+-#else /* CONFIG_USB_PERSIST */
+-
+-static inline void ehci_handover_companion_ports(struct ehci_hcd *ehci)
+-{ }
+-
+-#endif
+-
+-#ifdef CONFIG_PM
+-
+ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ {
+ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
+@@ -158,10 +151,10 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+ }
+
+ /* enable remote wakeup on all ports */
+- if (device_may_wakeup(&hcd->self.root_hub->dev))
+- t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E;
++ if (hcd->self.root_hub->do_remote_wakeup)
++ t2 |= PORT_WAKE_BITS;
+ else
+- t2 &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E);
++ t2 &= ~PORT_WAKE_BITS;
+
+ if (t1 != t2) {
+ ehci_vdbg (ehci, "port %d, %08x -> %08x\n",
+@@ -183,7 +176,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
+
+ /* allow remote wakeup */
+ mask = INTR_MASK;
+- if (!device_may_wakeup(&hcd->self.root_hub->dev))
++ if (!hcd->self.root_hub->do_remote_wakeup)
+ mask &= ~STS_PCD;
+ ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+ ehci_readl(ehci, &ehci->regs->intr_enable);
+@@ -241,8 +234,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ i = HCS_N_PORTS (ehci->hcs_params);
+ while (i--) {
+ temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
+- temp &= ~(PORT_RWC_BITS
+- | PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E);
++ temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
+ if (test_bit(i, &ehci->bus_suspended) &&
+ (temp & PORT_SUSPEND)) {
+ ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
+@@ -281,9 +273,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
+ ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
+
+ spin_unlock_irq (&ehci->lock);
+-
+- if (!power_okay)
+- ehci_handover_companion_ports(ehci);
++ ehci_handover_companion_ports(ehci);
+ return 0;
+ }
+
+@@ -545,8 +535,6 @@ ehci_hub_descriptor (
+
+ /*-------------------------------------------------------------------------*/
+
+-#define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
+-
+ static int ehci_hub_control (
+ struct usb_hcd *hcd,
+ u16 typeReq,
+@@ -778,7 +766,7 @@ static int ehci_hub_control (
+ if (temp & PORT_POWER)
+ status |= 1 << USB_PORT_FEAT_POWER;
+
+-#ifndef EHCI_VERBOSE_DEBUG
++#ifndef VERBOSE_DEBUG
+ if (status & ~0xffff) /* only if wPortChange is interesting */
+ #endif
+ dbg_port (ehci, "GetStatus", wIndex + 1, temp);
+@@ -812,8 +800,6 @@ static int ehci_hub_control (
+ if ((temp & PORT_PE) == 0
+ || (temp & PORT_RESET) != 0)
+ goto error;
+- if (device_may_wakeup(&hcd->self.root_hub->dev))
+- temp |= PORT_WAKE_BITS;
+ ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
+ break;
+ case USB_PORT_FEAT_POWER:
+diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c
+index 3041d8f..601c879 100644
+--- a/drivers/usb/host/ehci-ixp4xx.c
++++ b/drivers/usb/host/ehci-ixp4xx.c
+@@ -140,13 +140,12 @@ static int ixp4xx_ehci_remove(struct platform_device *pdev)
+ return 0;
+ }
+
+-MODULE_ALIAS("ixp4xx-ehci");
++MODULE_ALIAS("platform:ixp4xx-ehci");
+
+ static struct platform_driver ixp4xx_ehci_driver = {
+ .probe = ixp4xx_ehci_probe,
+ .remove = ixp4xx_ehci_remove,
+ .driver = {
+ .name = "ixp4xx-ehci",
+- .bus = &platform_bus_type
+ },
+ };
+diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
+index e129981..d187d03 100644
+--- a/drivers/usb/host/ehci-orion.c
++++ b/drivers/usb/host/ehci-orion.c
+@@ -11,15 +11,18 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+-#include <asm/arch/orion.h>
++#include <linux/mbus.h>
++#include <asm/plat-orion/ehci-orion.h>
+
+ #define rdl(off) __raw_readl(hcd->regs + (off))
+ #define wrl(off, val) __raw_writel((val), hcd->regs + (off))
+
+-#define USB_CAUSE 0x310
+-#define USB_MASK 0x314
+ #define USB_CMD 0x140
+ #define USB_MODE 0x1a8
++#define USB_CAUSE 0x310
++#define USB_MASK 0x314
++#define USB_WINDOW_CTRL(i) (0x320 + ((i) << 4))
++#define USB_WINDOW_BASE(i) (0x324 + ((i) << 4))
+ #define USB_IPG 0x360
+ #define USB_PHY_PWR_CTRL 0x400
+ #define USB_PHY_TX_CTRL 0x420
+@@ -162,8 +165,30 @@ static const struct hc_driver ehci_orion_hc_driver = {
+ .bus_resume = ehci_bus_resume,
+ };
+
++static void __init
++ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,
++ struct mbus_dram_target_info *dram)
++{
++ int i;
++
++ for (i = 0; i < 4; i++) {
++ wrl(USB_WINDOW_CTRL(i), 0);
++ wrl(USB_WINDOW_BASE(i), 0);
++ }
++
++ for (i = 0; i < dram->num_cs; i++) {
++ struct mbus_dram_window *cs = dram->cs + i;
++
++ wrl(USB_WINDOW_CTRL(i), ((cs->size - 1) & 0xffff0000) |
++ (cs->mbus_attr << 8) |
++ (dram->mbus_dram_target_id << 4) | 1);
++ wrl(USB_WINDOW_BASE(i), cs->base);
++ }
++}
++
+ static int __init ehci_orion_drv_probe(struct platform_device *pdev)
+ {
++ struct orion_ehci_data *pd = pdev->dev.platform_data;
+ struct resource *res;
+ struct usb_hcd *hcd;
+ struct ehci_hcd *ehci;
+@@ -227,6 +252,12 @@ static int __init ehci_orion_drv_probe(struct platform_device *pdev)
+ ehci->sbrn = 0x20;
+
+ /*
++ * (Re-)program MBUS remapping windows if we are asked to.
++ */
++ if (pd != NULL && pd->dram != NULL)
++ ehci_orion_conf_mbus_windows(hcd, pd->dram);
++
++ /*
+ * setup Orion USB controller
+ */
+ orion_usb_setup(hcd);
+diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
+index 72ccd56..5bb7f6b 100644
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -130,6 +130,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ case PCI_VENDOR_ID_TDI:
+ if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
+ ehci->is_tdi_rh_tt = 1;
++ hcd->has_tt = 1;
+ tdi_reset(ehci);
+ }
+ break;
+@@ -221,6 +222,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
+ ehci_warn(ehci, "selective suspend/wakeup unavailable\n");
+ #endif
+
++ ehci_port_power(ehci, 1);
+ retval = ehci_pci_reinit(ehci, pdev);
+ done:
+ return retval;
+@@ -299,7 +301,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
+ if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
+ int mask = INTR_MASK;
+
+- if (!device_may_wakeup(&hcd->self.root_hub->dev))
++ if (!hcd->self.root_hub->do_remote_wakeup)
+ mask &= ~STS_PCD;
+ ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+ ehci_readl(ehci, &ehci->regs->intr_enable);
+@@ -329,7 +331,6 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
+
+ /* here we "know" root ports should always stay powered */
+ ehci_port_power(ehci, 1);
+- ehci_handover_companion_ports(ehci);
+
+ hcd->state = HC_STATE_SUSPENDED;
+ return 0;
+@@ -353,8 +354,8 @@ static const struct hc_driver ehci_pci_hc_driver = {
+ .reset = ehci_pci_setup,
+ .start = ehci_run,
+ #ifdef CONFIG_PM
+- .suspend = ehci_pci_suspend,
+- .resume = ehci_pci_resume,
++ .pci_suspend = ehci_pci_suspend,
++ .pci_resume = ehci_pci_resume,
+ #endif
+ .stop = ehci_stop,
+ .shutdown = ehci_shutdown,
+diff --git a/drivers/usb/host/ehci-ppc-soc.c b/drivers/usb/host/ehci-ppc-soc.c
+index a324907..6c76036 100644
+--- a/drivers/usb/host/ehci-ppc-soc.c
++++ b/drivers/usb/host/ehci-ppc-soc.c
+@@ -175,6 +175,7 @@ static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev)
+ if (usb_disabled())
+ return -ENODEV;
+
++ /* FIXME we only want one one probe() not two */
+ ret = usb_ehci_ppc_soc_probe(&ehci_ppc_soc_hc_driver, &hcd, pdev);
+ return ret;
+ }
+@@ -183,17 +184,17 @@ static int ehci_hcd_ppc_soc_drv_remove(struct platform_device *pdev)
+ {
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
++ /* FIXME we only want one one remove() not two */
+ usb_ehci_ppc_soc_remove(hcd, pdev);
+ return 0;
+ }
+
+-MODULE_ALIAS("ppc-soc-ehci");
++MODULE_ALIAS("platform:ppc-soc-ehci");
+ static struct platform_driver ehci_ppc_soc_driver = {
+ .probe = ehci_hcd_ppc_soc_drv_probe,
+ .remove = ehci_hcd_ppc_soc_drv_remove,
+ .shutdown = usb_hcd_platform_shutdown,
+ .driver = {
+ .name = "ppc-soc-ehci",
+- .bus = &platform_bus_type
+ }
+ };
+diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
+index bbda58e..6978222 100644
+--- a/drivers/usb/host/ehci-ps3.c
++++ b/drivers/usb/host/ehci-ps3.c
+@@ -125,7 +125,6 @@ static int ps3_ehci_probe(struct ps3_system_bus_device *dev)
+ goto fail_irq;
+ }
+
+- dev->core.power.power_state = PMSG_ON;
+ dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */
+
+ hcd = usb_create_hcd(&ps3_ehci_hc_driver, &dev->core, dev->core.bus_id);
+diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
+index 2e49de8..5ae6891 100644
+--- a/drivers/usb/host/ehci-q.c
++++ b/drivers/usb/host/ehci-q.c
+@@ -242,7 +242,8 @@ __acquires(ehci->lock)
+ if (unlikely(urb->unlinked)) {
+ COUNT(ehci->stats.unlink);
+ } else {
+- if (likely(status == -EINPROGRESS))
++ /* report non-error and short read status as zero */
++ if (status == -EINPROGRESS || status == -EREMOTEIO)
+ status = 0;
+ COUNT(ehci->stats.complete);
+ }
+@@ -250,7 +251,7 @@ __acquires(ehci->lock)
+ #ifdef EHCI_URB_TRACE
+ ehci_dbg (ehci,
+ "%s %s urb %p ep%d%s status %d len %d/%d\n",
+- __FUNCTION__, urb->dev->devpath, urb,
++ __func__, urb->dev->devpath, urb,
+ usb_pipeendpoint (urb->pipe),
+ usb_pipein (urb->pipe) ? "in" : "out",
+ status,
+@@ -283,7 +284,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ int last_status = -EINPROGRESS;
+ int stopped;
+ unsigned count = 0;
+- int do_status = 0;
+ u8 state;
+ u32 halt = HALT_BIT(ehci);
+
+@@ -309,7 +309,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ struct ehci_qtd *qtd;
+ struct urb *urb;
+ u32 token = 0;
+- int qtd_status;
+
+ qtd = list_entry (entry, struct ehci_qtd, qtd_list);
+ urb = qtd->urb;
+@@ -336,11 +335,20 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ /* always clean up qtds the hc de-activated */
+ if ((token & QTD_STS_ACTIVE) == 0) {
+
++ /* on STALL, error, and short reads this urb must
++ * complete and all its qtds must be recycled.
++ */
+ if ((token & QTD_STS_HALT) != 0) {
+ stopped = 1;
+
+ /* magic dummy for some short reads; qh won't advance.
+ * that silicon quirk can kick in with this dummy too.
++ *
++ * other short reads won't stop the queue, including
++ * control transfers (status stage handles that) or
++ * most other single-qtd reads ... the queue stops if
++ * URB_SHORT_NOT_OK was set so the driver submitting
++ * the urbs could clean it up.
+ */
+ } else if (IS_SHORT_READ (token)
+ && !(qtd->hw_alt_next
+@@ -354,28 +362,21 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
+ && HC_IS_RUNNING (ehci_to_hcd(ehci)->state))) {
+ break;
+
++ /* scan the whole queue for unlinks whenever it stops */
+ } else {
+ stopped = 1;
+
+- if (unlikely (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)))
++ /* cancel everything if we halt, suspend, etc */
++ if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state))
+ last_status = -ESHUTDOWN;
+
+- /* ignore active urbs unless some previous qtd
+- * for the urb faulted (including short read) or
+- * its urb was canceled. we may patch qh or qtds.
++ /* this qtd is active; skip it unless a previous qtd
++ * for its urb faulted, or its urb was canceled.
+ */
+- if (likely(last_status == -EINPROGRESS &&
+- !urb->unlinked))
+- continue;
+-
+- /* issue status after short control reads */
+- if (unlikely (do_status != 0)
+- && QTD_PID (token) == 0 /* OUT */) {
+- do_status = 0;
++ else if (last_status == -EINPROGRESS && !urb->unlinked)
+ continue;
+- }
+
+- /* token in overlay may be most current */
++ /* qh unlinked; token in overlay may be most current */
+ if (state == QH_STATE_IDLE
+ && cpu_to_hc32(ehci, qtd->qtd_dma)
+ == qh->hw_current)
+@@ -392,21 +393,32 @@ halt:
+ }
+ }
+
+- /* remove it from the queue */
+- qtd_status = qtd_copy_status(ehci, urb, qtd->length, token);
+- if (unlikely(qtd_status == -EREMOTEIO)) {
+- do_status = (!urb->unlinked &&
+- usb_pipecontrol(urb->pipe));
+- qtd_status = 0;
++ /* unless we already know the urb's status, collect qtd status
++ * and update count of bytes transferred. in common short read
++ * cases with only one data qtd (including control transfers),
++ * queue processing won't halt. but with two or more qtds (for
++ * example, with a 32 KB transfer), when the first qtd gets a
++ * short read the second must be removed by hand.
++ */
++ if (last_status == -EINPROGRESS) {
++ last_status = qtd_copy_status(ehci, urb,
++ qtd->length, token);
++ if (last_status == -EREMOTEIO
++ && (qtd->hw_alt_next
++ & EHCI_LIST_END(ehci)))
++ last_status = -EINPROGRESS;
+ }
+- if (likely(last_status == -EINPROGRESS))
+- last_status = qtd_status;
+
++ /* if we're removing something not at the queue head,
++ * patch the hardware queue pointer.
++ */
+ if (stopped && qtd->qtd_list.prev != &qh->qtd_list) {
+ last = list_entry (qtd->qtd_list.prev,
+ struct ehci_qtd, qtd_list);
+ last->hw_next = qtd->hw_next;
+ }
++
++ /* remove qtd; it's recycled after possible urb completion */
+ list_del (&qtd->qtd_list);
+ last = qtd;
+ }
+@@ -431,7 +443,15 @@ halt:
+ qh_refresh(ehci, qh);
+ break;
+ case QH_STATE_LINKED:
+- /* should be rare for periodic transfers,
++ /* We won't refresh a QH that's linked (after the HC
++ * stopped the queue). That avoids a race:
++ * - HC reads first part of QH;
++ * - CPU updates that first part and the token;
++ * - HC reads rest of that QH, including token
++ * Result: HC gets an inconsistent image, and then
++ * DMAs to/from the wrong memory (corrupting it).
++ *
++ * That should be rare for interrupt transfers,
+ * except maybe high bandwidth ...
+ */
+ if ((cpu_to_hc32(ehci, QH_SMASK)
+@@ -549,6 +569,12 @@ qh_urb_transaction (
+ this_qtd_len = qtd_fill(ehci, qtd, buf, len, token, maxpacket);
+ len -= this_qtd_len;
+ buf += this_qtd_len;
++
++ /*
++ * short reads advance to a "magic" dummy instead of the next
++ * qtd ... that forces the queue to stop, for manual cleanup.
++ * (this will usually be overridden later.)
++ */
+ if (is_input)
+ qtd->hw_alt_next = ehci->async->hw_alt_next;
+
+@@ -568,8 +594,10 @@ qh_urb_transaction (
+ list_add_tail (&qtd->qtd_list, head);
+ }
+
+- /* unless the bulk/interrupt caller wants a chance to clean
+- * up after short reads, hc should advance qh past this urb
++ /*
++ * unless the caller requires manual cleanup after short reads,
++ * have the alt_next mechanism keep the queue running after the
++ * last data qtd (the only one, for control and most other cases).
+ */
+ if (likely ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0
+ || usb_pipecontrol (urb->pipe)))
+@@ -657,6 +685,14 @@ qh_make (
+ type = usb_pipetype (urb->pipe);
+ maxp = usb_maxpacket (urb->dev, urb->pipe, !is_input);
+
++ /* 1024 byte maxpacket is a hardware ceiling. High bandwidth
++ * acts like up to 3KB, but is built from smaller packets.
++ */
++ if (max_packet(maxp) > 1024) {
++ ehci_dbg(ehci, "bogus qh maxpacket %d\n", max_packet(maxp));
++ goto done;
++ }
++
+ /* Compute interrupt scheduling parameters just once, and save.
+ * - allowing for high bandwidth, how many nsec/uframe are used?
+ * - split transactions need a second CSPLIT uframe; same question
+@@ -757,7 +793,13 @@ qh_make (
+ info2 |= (EHCI_TUNE_MULT_HS << 30);
+ } else if (type == PIPE_BULK) {
+ info1 |= (EHCI_TUNE_RL_HS << 28);
+- info1 |= 512 << 16; /* usb2 fixed maxpacket */
++ /* The USB spec says that high speed bulk endpoints
++ * always use 512 byte maxpacket. But some device
++ * vendors decided to ignore that, and MSFT is happy
++ * to help them do so. So now people expect to use
++ * such nonconformant devices with Linux too; sigh.
++ */
++ info1 |= max_packet(maxp) << 16;
+ info2 |= (EHCI_TUNE_MULT_HS << 30);
+ } else { /* PIPE_INTERRUPT */
+ info1 |= max_packet (maxp) << 16;
+@@ -932,7 +974,7 @@ submit_async (
+ #ifdef EHCI_URB_TRACE
+ ehci_dbg (ehci,
+ "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n",
+- __FUNCTION__, urb->dev->devpath, urb,
++ __func__, urb->dev->devpath, urb,
+ epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out",
+ urb->transfer_buffer_length,
+ qtd, urb->ep->hcpriv);
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 8a8e08a..be575e4 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -440,11 +440,10 @@ static int enable_periodic (struct ehci_hcd *ehci)
+ /* did clearing PSE did take effect yet?
+ * takes effect only at frame boundaries...
+ */
+- status = handshake(ehci, &ehci->regs->status, STS_PSS, 0, 9 * 125);
+- if (status != 0) {
+- ehci_to_hcd(ehci)->state = HC_STATE_HALT;
++ status = handshake_on_error_set_halt(ehci, &ehci->regs->status,
++ STS_PSS, 0, 9 * 125);
++ if (status)
+ return status;
+- }
+
+ cmd = ehci_readl(ehci, &ehci->regs->command) | CMD_PSE;
+ ehci_writel(ehci, cmd, &ehci->regs->command);
+@@ -465,11 +464,10 @@ static int disable_periodic (struct ehci_hcd *ehci)
+ /* did setting PSE not take effect yet?
+ * takes effect only at frame boundaries...
+ */
+- status = handshake(ehci, &ehci->regs->status, STS_PSS, STS_PSS, 9 * 125);
+- if (status != 0) {
+- ehci_to_hcd(ehci)->state = HC_STATE_HALT;
++ status = handshake_on_error_set_halt(ehci, &ehci->regs->status,
++ STS_PSS, STS_PSS, 9 * 125);
++ if (status)
+ return status;
+- }
+
+ cmd = ehci_readl(ehci, &ehci->regs->command) & ~CMD_PSE;
+ ehci_writel(ehci, cmd, &ehci->regs->command);
+@@ -1183,21 +1181,18 @@ itd_urb_transaction (
+ struct ehci_itd, itd_list);
+ list_del (&itd->itd_list);
+ itd_dma = itd->itd_dma;
+- } else
+- itd = NULL;
+-
+- if (!itd) {
++ } else {
+ spin_unlock_irqrestore (&ehci->lock, flags);
+ itd = dma_pool_alloc (ehci->itd_pool, mem_flags,
+ &itd_dma);
+ spin_lock_irqsave (&ehci->lock, flags);
++ if (!itd) {
++ iso_sched_free(stream, sched);
++ spin_unlock_irqrestore(&ehci->lock, flags);
++ return -ENOMEM;
++ }
+ }
+
+- if (unlikely (NULL == itd)) {
+- iso_sched_free (stream, sched);
+- spin_unlock_irqrestore (&ehci->lock, flags);
+- return -ENOMEM;
+- }
+ memset (itd, 0, sizeof *itd);
+ itd->itd_dma = itd_dma;
+ list_add (&itd->itd_list, &sched->td_list);
+@@ -1682,7 +1677,7 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb,
+ #ifdef EHCI_URB_TRACE
+ ehci_dbg (ehci,
+ "%s %s urb %p ep%d%s len %d, %d pkts %d uframes [%p]\n",
+- __FUNCTION__, urb->dev->devpath, urb,
++ __func__, urb->dev->devpath, urb,
+ usb_pipeendpoint (urb->pipe),
+ usb_pipein (urb->pipe) ? "in" : "out",
+ urb->transfer_buffer_length,
+@@ -1816,21 +1811,18 @@ sitd_urb_transaction (
+ struct ehci_sitd, sitd_list);
+ list_del (&sitd->sitd_list);
+ sitd_dma = sitd->sitd_dma;
+- } else
+- sitd = NULL;
+-
+- if (!sitd) {
++ } else {
+ spin_unlock_irqrestore (&ehci->lock, flags);
+ sitd = dma_pool_alloc (ehci->sitd_pool, mem_flags,
+ &sitd_dma);
+ spin_lock_irqsave (&ehci->lock, flags);
++ if (!sitd) {
++ iso_sched_free(stream, iso_sched);
++ spin_unlock_irqrestore(&ehci->lock, flags);
++ return -ENOMEM;
++ }
+ }
+
+- if (!sitd) {
+- iso_sched_free (stream, iso_sched);
+- spin_unlock_irqrestore (&ehci->lock, flags);
+- return -ENOMEM;
+- }
+ memset (sitd, 0, sizeof *sitd);
+ sitd->sitd_dma = sitd_dma;
+ list_add (&sitd->sitd_list, &iso_sched->td_list);
+diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
+index 203a335..20b9a0d 100644
+--- a/drivers/usb/host/isp116x-hcd.c
++++ b/drivers/usb/host/isp116x-hcd.c
+@@ -1400,7 +1400,7 @@ static int isp116x_bus_suspend(struct usb_hcd *hcd)
+ spin_unlock_irqrestore(&isp116x->lock, flags);
+ val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE);
+ val |= HCCONTROL_USB_SUSPEND;
+- if (device_may_wakeup(&hcd->self.root_hub->dev))
++ if (hcd->self.root_hub->do_remote_wakeup)
+ val |= HCCONTROL_RWE;
+ /* Wait for usb transfers to finish */
+ msleep(2);
+@@ -1442,11 +1442,6 @@ static int isp116x_bus_resume(struct usb_hcd *hcd)
+ break;
+ case HCCONTROL_USB_OPER:
+ spin_unlock_irq(&isp116x->lock);
+- /* Without setting power_state here the
+- SUSPENDED state won't be removed from
+- sysfs/usbN/power.state as a response to remote
+- wakeup. Maybe in the future. */
+- hcd->self.root_hub->dev.power.power_state = PMSG_ON;
+ return 0;
+ default:
+ /* HCCONTROL_USB_RESET: this may happen, when during
+@@ -1460,7 +1455,6 @@ static int isp116x_bus_resume(struct usb_hcd *hcd)
+ if ((isp116x->rhdesca & RH_A_NDP) == 2)
+ isp116x_hub_control(hcd, SetPortFeature,
+ USB_PORT_FEAT_POWER, 2, NULL, 0);
+- hcd->self.root_hub->dev.power.power_state = PMSG_ON;
+ return 0;
+ }
+
+@@ -1486,8 +1480,6 @@ static int isp116x_bus_resume(struct usb_hcd *hcd)
+ isp116x_write_reg32(isp116x, HCCONTROL,
+ (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER);
+ spin_unlock_irq(&isp116x->lock);
+- /* see analogous comment above */
+- hcd->self.root_hub->dev.power.power_state = PMSG_ON;
+ hcd->state = HC_STATE_RUNNING;
+
+ return 0;
+@@ -1663,7 +1655,6 @@ static int __devinit isp116x_probe(struct platform_device *pdev)
+ static int isp116x_suspend(struct platform_device *dev, pm_message_t state)
+ {
+ VDBG("%s: state %x\n", __func__, state.event);
+- dev->dev.power.power_state = state;
+ return 0;
+ }
+
+@@ -1672,8 +1663,7 @@ static int isp116x_suspend(struct platform_device *dev, pm_message_t state)
+ */
+ static int isp116x_resume(struct platform_device *dev)
+ {
+- VDBG("%s: state %x\n", __func__, dev->power.power_state.event);
+- dev->dev.power.power_state = PMSG_ON;
++ VDBG("%s\n", __func__);
+ return 0;
+ }
+
+diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
+index d72dc07..c96db11 100644
+--- a/drivers/usb/host/ohci-at91.c
++++ b/drivers/usb/host/ohci-at91.c
+@@ -261,7 +261,6 @@ static const struct hc_driver ohci_at91_hc_driver = {
+ */
+ .hub_status_data = ohci_hub_status_data,
+ .hub_control = ohci_hub_control,
+- .hub_irq_enable = ohci_rhsc_enable,
+ #ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
+@@ -348,6 +347,7 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *pdev)
+ if (!clocked)
+ at91_start_clock();
+
++ ohci_finish_controller_resume(hcd);
+ return 0;
+ }
+ #else
+diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
+index f90fe0c..1b9abdb 100644
+--- a/drivers/usb/host/ohci-au1xxx.c
++++ b/drivers/usb/host/ohci-au1xxx.c
+@@ -288,7 +288,6 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
+ */
+ .hub_status_data = ohci_hub_status_data,
+ .hub_control = ohci_hub_control,
+- .hub_irq_enable = ohci_rhsc_enable,
+ #ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
+index a22c30a..e06bfae 100644
+--- a/drivers/usb/host/ohci-dbg.c
++++ b/drivers/usb/host/ohci-dbg.c
+@@ -655,7 +655,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
+ hcd->product_desc,
+ hcd_name);
+
+- if (bus->controller->power.power_state.event) {
++ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+ size -= scnprintf (next, size,
+ "SUSPENDED (no register access)\n");
+ goto done;
+diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
+index 156e93a..06aadfb 100644
+--- a/drivers/usb/host/ohci-ep93xx.c
++++ b/drivers/usb/host/ohci-ep93xx.c
+@@ -135,7 +135,6 @@ static struct hc_driver ohci_ep93xx_hc_driver = {
+ .get_frame_number = ohci_get_frame,
+ .hub_status_data = ohci_hub_status_data,
+ .hub_control = ohci_hub_control,
+- .hub_irq_enable = ohci_rhsc_enable,
+ #ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
+@@ -177,7 +176,6 @@ static int ohci_hcd_ep93xx_drv_suspend(struct platform_device *pdev, pm_message_
+
+ ep93xx_stop_hc(&pdev->dev);
+ hcd->state = HC_STATE_SUSPENDED;
+- pdev->dev.power.power_state = PMSG_SUSPEND;
+
+ return 0;
+ }
+@@ -193,9 +191,8 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev)
+ ohci->next_statechange = jiffies;
+
+ ep93xx_start_hc(&pdev->dev);
+- pdev->dev.power.power_state = PMSG_ON;
+- usb_hcd_resume_root_hub(hcd);
+
++ ohci_finish_controller_resume(hcd);
+ return 0;
+ }
+ #endif
+diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
+index 48e4b11..5be3bb3 100644
+--- a/drivers/usb/host/ohci-hub.c
++++ b/drivers/usb/host/ohci-hub.c
+@@ -36,18 +36,6 @@
+
+ /*-------------------------------------------------------------------------*/
+
+-/* hcd->hub_irq_enable() */
+-static void ohci_rhsc_enable (struct usb_hcd *hcd)
+-{
+- struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+-
+- spin_lock_irq(&ohci->lock);
+- if (!ohci->autostop)
+- del_timer(&hcd->rh_timer); /* Prevent next poll */
+- ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
+- spin_unlock_irq(&ohci->lock);
+-}
+-
+ #define OHCI_SCHED_ENABLES \
+ (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
+
+@@ -103,11 +91,11 @@ __acquires(ohci->lock)
+ finish_unlinks (ohci, ohci_frame_no(ohci));
+
+ /* maybe resume can wake root hub */
+- if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev) ||
+- autostop)
++ if (ohci_to_hcd(ohci)->self.root_hub->do_remote_wakeup || autostop) {
+ ohci->hc_control |= OHCI_CTRL_RWE;
+- else {
+- ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable);
++ } else {
++ ohci_writel(ohci, OHCI_INTR_RHSC | OHCI_INTR_RD,
++ &ohci->regs->intrdisable);
+ ohci->hc_control &= ~OHCI_CTRL_RWE;
+ }
+
+@@ -326,23 +314,76 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
+ return rc;
+ }
+
++/* Carry out the final steps of resuming the controller device */
++static void ohci_finish_controller_resume(struct usb_hcd *hcd)
++{
++ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
++ int port;
++ bool need_reinit = false;
++
++ /* See if the controller is already running or has been reset */
++ ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
++ if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
++ need_reinit = true;
++ } else {
++ switch (ohci->hc_control & OHCI_CTRL_HCFS) {
++ case OHCI_USB_OPER:
++ case OHCI_USB_RESET:
++ need_reinit = true;
++ }
++ }
++
++ /* If needed, reinitialize and suspend the root hub */
++ if (need_reinit) {
++ spin_lock_irq(&ohci->lock);
++ hcd->state = HC_STATE_RESUMING;
++ ohci_rh_resume(ohci);
++ hcd->state = HC_STATE_QUIESCING;
++ ohci_rh_suspend(ohci, 0);
++ hcd->state = HC_STATE_SUSPENDED;
++ spin_unlock_irq(&ohci->lock);
++ }
++
++ /* Normally just turn on port power and enable interrupts */
++ else {
++ ohci_dbg(ohci, "powerup ports\n");
++ for (port = 0; port < ohci->num_ports; port++)
++ ohci_writel(ohci, RH_PS_PPS,
++ &ohci->regs->roothub.portstatus[port]);
++
++ ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable);
++ ohci_readl(ohci, &ohci->regs->intrenable);
++ msleep(20);
++ }
++}
++
+ /* Carry out polling-, autostop-, and autoresume-related state changes */
+ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ int any_connected)
+ {
+ int poll_rh = 1;
++ int rhsc;
+
++ rhsc = ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC;
+ switch (ohci->hc_control & OHCI_CTRL_HCFS) {
+
+ case OHCI_USB_OPER:
+- /* keep on polling until we know a device is connected
+- * and RHSC is enabled */
++ /* If no status changes are pending, enable status-change
++ * interrupts.
++ */
++ if (!rhsc && !changed) {
++ rhsc = OHCI_INTR_RHSC;
++ ohci_writel(ohci, rhsc, &ohci->regs->intrenable);
++ }
++
++ /* Keep on polling until we know a device is connected
++ * and RHSC is enabled, or until we autostop.
++ */
+ if (!ohci->autostop) {
+ if (any_connected ||
+ !device_may_wakeup(&ohci_to_hcd(ohci)
+ ->self.root_hub->dev)) {
+- if (ohci_readl(ohci, &ohci->regs->intrenable) &
+- OHCI_INTR_RHSC)
++ if (rhsc)
+ poll_rh = 0;
+ } else {
+ ohci->autostop = 1;
+@@ -355,12 +396,13 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ ohci->autostop = 0;
+ ohci->next_statechange = jiffies +
+ STATECHANGE_DELAY;
+- } else if (time_after_eq(jiffies,
++ } else if (rhsc && time_after_eq(jiffies,
+ ohci->next_statechange)
+ && !ohci->ed_rm_list
+ && !(ohci->hc_control &
+ OHCI_SCHED_ENABLES)) {
+ ohci_rh_suspend(ohci, 1);
++ poll_rh = 0;
+ }
+ }
+ break;
+@@ -374,6 +416,12 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ else
+ usb_hcd_resume_root_hub(ohci_to_hcd(ohci));
+ } else {
++ if (!rhsc && (ohci->autostop ||
++ ohci_to_hcd(ohci)->self.root_hub->
++ do_remote_wakeup))
++ ohci_writel(ohci, OHCI_INTR_RHSC,
++ &ohci->regs->intrenable);
++
+ /* everything is idle, no need for polling */
+ poll_rh = 0;
+ }
+@@ -395,12 +443,16 @@ static inline int ohci_rh_resume(struct ohci_hcd *ohci)
+ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ int any_connected)
+ {
+- int poll_rh = 1;
+-
+- /* keep on polling until RHSC is enabled */
++ /* If RHSC is enabled, don't poll */
+ if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC)
+- poll_rh = 0;
+- return poll_rh;
++ return 0;
++
++ /* If no status changes are pending, enable status-change interrupts */
++ if (!changed) {
++ ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
++ return 0;
++ }
++ return 1;
+ }
+
+ #endif /* CONFIG_PM */
+@@ -564,14 +616,18 @@ static inline int root_port_reset (struct ohci_hcd *ohci, unsigned port)
+ u32 temp;
+ u16 now = ohci_readl(ohci, &ohci->regs->fmnumber);
+ u16 reset_done = now + PORT_RESET_MSEC;
++ int limit_1 = DIV_ROUND_UP(PORT_RESET_MSEC, PORT_RESET_HW_MSEC);
+
+ /* build a "continuous enough" reset signal, with up to
+ * 3msec gap between pulses. scheduler HZ==100 must work;
+ * this might need to be deadline-scheduled.
+ */
+ do {
++ int limit_2;
++
+ /* spin until any current reset finishes */
+- for (;;) {
++ limit_2 = PORT_RESET_HW_MSEC * 2;
++ while (--limit_2 >= 0) {
+ temp = ohci_readl (ohci, portstat);
+ /* handle e.g. CardBus eject */
+ if (temp == ~(u32)0)
+@@ -581,6 +637,17 @@ static inline int root_port_reset (struct ohci_hcd *ohci, unsigned port)
+ udelay (500);
+ }
+
++ /* timeout (a hardware error) has been observed when
++ * EHCI sets CF while this driver is resetting a port;
++ * presumably other disconnect paths might do it too.
++ */
++ if (limit_2 < 0) {
++ ohci_dbg(ohci,
++ "port[%d] reset timeout, stat %08x\n",
++ port, temp);
++ break;
++ }
++
+ if (!(temp & RH_PS_CCS))
+ break;
+ if (temp & RH_PS_PRSC)
+@@ -590,8 +657,11 @@ static inline int root_port_reset (struct ohci_hcd *ohci, unsigned port)
+ ohci_writel (ohci, RH_PS_PRS, portstat);
+ msleep(PORT_RESET_HW_MSEC);
+ now = ohci_readl(ohci, &ohci->regs->fmnumber);
+- } while (tick_before(now, reset_done));
+- /* caller synchronizes using PRSC */
++ } while (tick_before(now, reset_done) && --limit_1 >= 0);
++
++ /* caller synchronizes using PRSC ... and handles PRS
++ * still being set when this returns.
++ */
+
+ return 0;
+ }
+diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c
+index 13c12ed..96d14fa 100644
+--- a/drivers/usb/host/ohci-lh7a404.c
++++ b/drivers/usb/host/ohci-lh7a404.c
+@@ -193,7 +193,6 @@ static const struct hc_driver ohci_lh7a404_hc_driver = {
+ */
+ .hub_status_data = ohci_hub_status_data,
+ .hub_control = ohci_hub_control,
+- .hub_irq_enable = ohci_rhsc_enable,
+ #ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
+index 7bfca1e..6859fb5 100644
+--- a/drivers/usb/host/ohci-omap.c
++++ b/drivers/usb/host/ohci-omap.c
+@@ -466,7 +466,6 @@ static const struct hc_driver ohci_omap_hc_driver = {
+ */
+ .hub_status_data = ohci_hub_status_data,
+ .hub_control = ohci_hub_control,
+- .hub_irq_enable = ohci_rhsc_enable,
+ #ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
+@@ -505,21 +504,20 @@ static int ohci_omap_suspend(struct platform_device *dev, pm_message_t message)
+
+ omap_ohci_clock_power(0);
+ ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
+- dev->dev.power.power_state = PMSG_SUSPEND;
+ return 0;
+ }
+
+ static int ohci_omap_resume(struct platform_device *dev)
+ {
+- struct ohci_hcd *ohci = hcd_to_ohci(platform_get_drvdata(dev));
++ struct usb_hcd *hcd = platform_get_drvdata(dev);
++ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+
+ if (time_before(jiffies, ohci->next_statechange))
+ msleep(5);
+ ohci->next_statechange = jiffies;
+
+ omap_ohci_clock_power(1);
+- dev->dev.power.power_state = PMSG_ON;
+- usb_hcd_resume_root_hub(platform_get_drvdata(dev));
++ ohci_finish_controller_resume(hcd);
+ return 0;
+ }
+
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index d0360f6..3bf175d 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -238,42 +238,6 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd)
+ return ret;
+ }
+
+-#if defined(CONFIG_USB_PERSIST) && (defined(CONFIG_USB_EHCI_HCD) || \
+- defined(CONFIG_USB_EHCI_HCD_MODULE))
+-
+-/* Following a power loss, we must prepare to regain control of the ports
+- * we used to own. This means turning on the port power before ehci-hcd
+- * tries to switch ownership.
+- *
+- * This isn't a 100% perfect solution. On most systems the OHCI controllers
+- * lie at lower PCI addresses than the EHCI controller, so they will be
+- * discovered (and hence resumed) first. But there is no guarantee things
+- * will always work this way. If the EHCI controller is resumed first and
+- * the OHCI ports are unpowered, then the handover will fail.
+- */
+-static void prepare_for_handover(struct usb_hcd *hcd)
+-{
+- struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+- int port;
+-
+- /* Here we "know" root ports should always stay powered */
+- ohci_dbg(ohci, "powerup ports\n");
+- for (port = 0; port < ohci->num_ports; port++)
+- ohci_writel(ohci, RH_PS_PPS,
+- &ohci->regs->roothub.portstatus[port]);
+-
+- /* Flush those writes */
+- ohci_readl(ohci, &ohci->regs->control);
+- msleep(20);
+-}
+-
+-#else
+-
+-static inline void prepare_for_handover(struct usb_hcd *hcd)
+-{ }
+-
+-#endif /* CONFIG_USB_PERSIST etc. */
+-
+ #ifdef CONFIG_PM
+
+ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
+@@ -313,10 +277,7 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
+ static int ohci_pci_resume (struct usb_hcd *hcd)
+ {
+ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-
+- /* FIXME: we should try to detect loss of VBUS power here */
+- prepare_for_handover(hcd);
+-
++ ohci_finish_controller_resume(hcd);
+ return 0;
+ }
+
+@@ -345,9 +306,8 @@ static const struct hc_driver ohci_pci_hc_driver = {
+ .shutdown = ohci_shutdown,
+
+ #ifdef CONFIG_PM
+- /* these suspend/resume entries are for upstream PCI glue ONLY */
+- .suspend = ohci_pci_suspend,
+- .resume = ohci_pci_resume,
++ .pci_suspend = ohci_pci_suspend,
++ .pci_resume = ohci_pci_resume,
+ #endif
+
+ /*
+@@ -367,7 +327,6 @@ static const struct hc_driver ohci_pci_hc_driver = {
+ */
+ .hub_status_data = ohci_hub_status_data,
+ .hub_control = ohci_hub_control,
+- .hub_irq_enable = ohci_rhsc_enable,
+ #ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
+index 28b458f..664f07e 100644
+--- a/drivers/usb/host/ohci-pnx4008.c
++++ b/drivers/usb/host/ohci-pnx4008.c
+@@ -280,7 +280,6 @@ static const struct hc_driver ohci_pnx4008_hc_driver = {
+ */
+ .hub_status_data = ohci_hub_status_data,
+ .hub_control = ohci_hub_control,
+- .hub_irq_enable = ohci_rhsc_enable,
+ #ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c
+index 605d59c..28467e2 100644
+--- a/drivers/usb/host/ohci-pnx8550.c
++++ b/drivers/usb/host/ohci-pnx8550.c
+@@ -201,7 +201,6 @@ static const struct hc_driver ohci_pnx8550_hc_driver = {
+ */
+ .hub_status_data = ohci_hub_status_data,
+ .hub_control = ohci_hub_control,
+- .hub_irq_enable = ohci_rhsc_enable,
+ #ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
+index a672527..50e55db 100644
+--- a/drivers/usb/host/ohci-ppc-of.c
++++ b/drivers/usb/host/ohci-ppc-of.c
+@@ -72,7 +72,6 @@ static const struct hc_driver ohci_ppc_of_hc_driver = {
+ */
+ .hub_status_data = ohci_hub_status_data,
+ .hub_control = ohci_hub_control,
+- .hub_irq_enable = ohci_rhsc_enable,
+ #ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
+index 523c301..cd3398b 100644
+--- a/drivers/usb/host/ohci-ppc-soc.c
++++ b/drivers/usb/host/ohci-ppc-soc.c
+@@ -172,7 +172,6 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = {
+ */
+ .hub_status_data = ohci_hub_status_data,
+ .hub_control = ohci_hub_control,
+- .hub_irq_enable = ohci_rhsc_enable,
+ #ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c
+index 01a0cae..bfdeb0d 100644
+--- a/drivers/usb/host/ohci-ps3.c
++++ b/drivers/usb/host/ohci-ps3.c
+@@ -68,7 +68,6 @@ static const struct hc_driver ps3_ohci_hc_driver = {
+ .get_frame_number = ohci_get_frame,
+ .hub_status_data = ohci_hub_status_data,
+ .hub_control = ohci_hub_control,
+- .hub_irq_enable = ohci_rhsc_enable,
+ .start_port_reset = ohci_start_port_reset,
+ #if defined(CONFIG_PM)
+ .bus_suspend = ohci_bus_suspend,
+@@ -127,7 +126,6 @@ static int ps3_ohci_probe(struct ps3_system_bus_device *dev)
+ goto fail_irq;
+ }
+
+- dev->core.power.power_state = PMSG_ON;
+ dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */
+
+ hcd = usb_create_hcd(&ps3_ohci_hc_driver, &dev->core, dev->core.bus_id);
+diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
+index 8ad9b3b..70b0d4b 100644
+--- a/drivers/usb/host/ohci-pxa27x.c
++++ b/drivers/usb/host/ohci-pxa27x.c
+@@ -298,7 +298,6 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
+ */
+ .hub_status_data = ohci_hub_status_data,
+ .hub_control = ohci_hub_control,
+- .hub_irq_enable = ohci_rhsc_enable,
+ #ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
+@@ -339,7 +338,6 @@ static int ohci_hcd_pxa27x_drv_suspend(struct platform_device *pdev, pm_message_
+
+ pxa27x_stop_hc(&pdev->dev);
+ hcd->state = HC_STATE_SUSPENDED;
+- pdev->dev.power.power_state = PMSG_SUSPEND;
+
+ return 0;
+ }
+@@ -357,9 +355,7 @@ static int ohci_hcd_pxa27x_drv_resume(struct platform_device *pdev)
+ if ((status = pxa27x_start_hc(&pdev->dev)) < 0)
+ return status;
+
+- pdev->dev.power.power_state = PMSG_ON;
+- usb_hcd_resume_root_hub(hcd);
+-
++ ohci_finish_controller_resume(hcd);
+ return 0;
+ }
+ #endif
+diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
+index ead4772..a73d2ff 100644
+--- a/drivers/usb/host/ohci-s3c2410.c
++++ b/drivers/usb/host/ohci-s3c2410.c
+@@ -466,7 +466,6 @@ static const struct hc_driver ohci_s3c2410_hc_driver = {
+ */
+ .hub_status_data = ohci_s3c2410_hub_status_data,
+ .hub_control = ohci_s3c2410_hub_control,
+- .hub_irq_enable = ohci_rhsc_enable,
+ #ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
+index 0f48f2d..99438c6 100644
+--- a/drivers/usb/host/ohci-sa1111.c
++++ b/drivers/usb/host/ohci-sa1111.c
+@@ -231,7 +231,6 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
+ */
+ .hub_status_data = ohci_hub_status_data,
+ .hub_control = ohci_hub_control,
+- .hub_irq_enable = ohci_rhsc_enable,
+ #ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c
+index e7ee607..60f03cc 100644
+--- a/drivers/usb/host/ohci-sh.c
++++ b/drivers/usb/host/ohci-sh.c
+@@ -68,7 +68,6 @@ static const struct hc_driver ohci_sh_hc_driver = {
+ */
+ .hub_status_data = ohci_hub_status_data,
+ .hub_control = ohci_hub_control,
+- .hub_irq_enable = ohci_rhsc_enable,
+ #ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
+diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
+index 4ea9276..77204f0 100644
+--- a/drivers/usb/host/ohci-sm501.c
++++ b/drivers/usb/host/ohci-sm501.c
+@@ -75,7 +75,6 @@ static const struct hc_driver ohci_sm501_hc_driver = {
+ */
+ .hub_status_data = ohci_hub_status_data,
+ .hub_control = ohci_hub_control,
+- .hub_irq_enable = ohci_rhsc_enable,
+ #ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
+@@ -199,7 +198,8 @@ static int ohci_hcd_sm501_drv_remove(struct platform_device *pdev)
+ usb_put_hcd(hcd);
+ dma_release_declared_memory(&pdev->dev);
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+- release_mem_region(mem->start, mem->end - mem->start + 1);
++ if (mem)
++ release_mem_region(mem->start, mem->end - mem->start + 1);
+
+ /* mask interrupts and disable power */
+
+@@ -224,24 +224,26 @@ static int ohci_sm501_suspend(struct platform_device *pdev, pm_message_t msg)
+
+ sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 0);
+ ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
+- dev->power.power_state = PMSG_SUSPEND;
+ return 0;
+ }
+
+ static int ohci_sm501_resume(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+- struct ohci_hcd *ohci = hcd_to_ohci(platform_get_drvdata(pdev));
++ struct usb_hcd *hcd = platform_get_drvdata(pdev);
++ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+
+ if (time_before(jiffies, ohci->next_statechange))
+ msleep(5);
+ ohci->next_statechange = jiffies;
+
+ sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1);
+- dev->power.power_state = PMSG_ON;
+- usb_hcd_resume_root_hub(platform_get_drvdata(pdev));
++ ohci_finish_controller_resume(hcd);
+ return 0;
+ }
++#else
++#define ohci_sm501_suspend NULL
++#define ohci_sm501_resume NULL
+ #endif
+
+ /*-------------------------------------------------------------------------*/
+@@ -253,10 +255,8 @@ static struct platform_driver ohci_hcd_sm501_driver = {
+ .probe = ohci_hcd_sm501_drv_probe,
+ .remove = ohci_hcd_sm501_drv_remove,
+ .shutdown = usb_hcd_platform_shutdown,
+-#ifdef CONFIG_PM
+ .suspend = ohci_sm501_suspend,
+ .resume = ohci_sm501_resume,
+-#endif
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "sm501-usb",
+diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c
+index 6e9c2d6..c4265ca 100644
+--- a/drivers/usb/host/ohci-ssb.c
++++ b/drivers/usb/host/ohci-ssb.c
+@@ -60,36 +60,6 @@ static int ssb_ohci_start(struct usb_hcd *hcd)
+ return err;
+ }
+
+-#ifdef CONFIG_PM
+-static int ssb_ohci_hcd_suspend(struct usb_hcd *hcd, pm_message_t message)
+-{
+- struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
+- struct ohci_hcd *ohci = &ohcidev->ohci;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&ohci->lock, flags);
+-
+- ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
+- ohci_readl(ohci, &ohci->regs->intrdisable); /* commit write */
+-
+- /* make sure snapshot being resumed re-enumerates everything */
+- if (message.event == PM_EVENT_PRETHAW)
+- ohci_usb_reset(ohci);
+-
+- clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+-
+- spin_unlock_irqrestore(&ohci->lock, flags);
+- return 0;
+-}
+-
+-static int ssb_ohci_hcd_resume(struct usb_hcd *hcd)
+-{
+- set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+- usb_hcd_resume_root_hub(hcd);
+- return 0;
+-}
+-#endif /* CONFIG_PM */
+-
+ static const struct hc_driver ssb_ohci_hc_driver = {
+ .description = "ssb-usb-ohci",
+ .product_desc = "SSB OHCI Controller",
+@@ -103,11 +73,6 @@ static const struct hc_driver ssb_ohci_hc_driver = {
+ .stop = ohci_stop,
+ .shutdown = ohci_shutdown,
+
+-#ifdef CONFIG_PM
+- .suspend = ssb_ohci_hcd_suspend,
+- .resume = ssb_ohci_hcd_resume,
+-#endif
+-
+ .urb_enqueue = ohci_urb_enqueue,
+ .urb_dequeue = ohci_urb_dequeue,
+ .endpoint_disable = ohci_endpoint_disable,
+@@ -116,7 +81,6 @@ static const struct hc_driver ssb_ohci_hc_driver = {
+
+ .hub_status_data = ohci_hub_status_data,
+ .hub_control = ohci_hub_control,
+- .hub_irq_enable = ohci_rhsc_enable,
+ #ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
+@@ -224,6 +188,7 @@ static int ssb_ohci_resume(struct ssb_device *dev)
+
+ ssb_device_enable(dev, ohcidev->enable_flags);
+
++ ohci_finish_controller_resume(hcd);
+ return 0;
+ }
+
+diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
+index 0ee694f..ae6e70e 100644
+--- a/drivers/usb/host/pci-quirks.c
++++ b/drivers/usb/host/pci-quirks.c
+@@ -106,7 +106,7 @@ int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base)
+ pci_read_config_word(pdev, UHCI_USBLEGSUP, &legsup);
+ if (legsup & ~(UHCI_USBLEGSUP_RO | UHCI_USBLEGSUP_RWC)) {
+ dev_dbg(&pdev->dev, "%s: legsup = 0x%04x\n",
+- __FUNCTION__, legsup);
++ __func__, legsup);
+ goto reset_needed;
+ }
+
+@@ -114,14 +114,14 @@ int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base)
+ if ((cmd & UHCI_USBCMD_RUN) || !(cmd & UHCI_USBCMD_CONFIGURE) ||
+ !(cmd & UHCI_USBCMD_EGSM)) {
+ dev_dbg(&pdev->dev, "%s: cmd = 0x%04x\n",
+- __FUNCTION__, cmd);
++ __func__, cmd);
+ goto reset_needed;
+ }
+
+ intr = inw(base + UHCI_USBINTR);
+ if (intr & (~UHCI_USBINTR_RESUME)) {
+ dev_dbg(&pdev->dev, "%s: intr = 0x%04x\n",
+- __FUNCTION__, intr);
++ __func__, intr);
+ goto reset_needed;
+ }
+ return 0;
+diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
+index 9f80e52..f4fa93d 100644
+--- a/drivers/usb/host/r8a66597-hcd.c
++++ b/drivers/usb/host/r8a66597-hcd.c
+@@ -46,15 +46,17 @@ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Yoshihiro Shimoda");
+ MODULE_ALIAS("platform:r8a66597_hcd");
+
+-#define DRIVER_VERSION "29 May 2007"
++#define DRIVER_VERSION "10 Apr 2008"
+
+ static const char hcd_name[] = "r8a66597_hcd";
+
+ /* module parameters */
++#if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+ static unsigned short clock = XTAL12;
+ module_param(clock, ushort, 0644);
+ MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0 "
+ "(default=0)");
++#endif
+
+ static unsigned short vif = LDRV;
+ module_param(vif, ushort, 0644);
+@@ -106,11 +108,22 @@ static void set_devadd_reg(struct r8a66597 *r8a66597, u8 r8a66597_address,
+ r8a66597_write(r8a66597, val, devadd_reg);
+ }
+
+-static int enable_controller(struct r8a66597 *r8a66597)
++static int r8a66597_clock_enable(struct r8a66597 *r8a66597)
+ {
+ u16 tmp;
+ int i = 0;
+
++#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
++ do {
++ r8a66597_write(r8a66597, SCKE, SYSCFG0);
++ tmp = r8a66597_read(r8a66597, SYSCFG0);
++ if (i++ > 1000) {
++ err("register access fail.");
++ return -ENXIO;
++ }
++ } while ((tmp & SCKE) != SCKE);
++ r8a66597_write(r8a66597, 0x04, 0x02);
++#else
+ do {
+ r8a66597_write(r8a66597, USBE, SYSCFG0);
+ tmp = r8a66597_read(r8a66597, SYSCFG0);
+@@ -132,13 +145,63 @@ static int enable_controller(struct r8a66597 *r8a66597)
+ return -ENXIO;
+ }
+ } while ((tmp & SCKE) != SCKE);
++#endif /* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */
++
++ return 0;
++}
++
++static void r8a66597_clock_disable(struct r8a66597 *r8a66597)
++{
++ r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
++ udelay(1);
++#if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
++ r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
++ r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
++ r8a66597_bclr(r8a66597, USBE, SYSCFG0);
++#endif
++}
++
++static void r8a66597_enable_port(struct r8a66597 *r8a66597, int port)
++{
++ u16 val;
++
++ val = port ? DRPD : DCFM | DRPD;
++ r8a66597_bset(r8a66597, val, get_syscfg_reg(port));
++ r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port));
++
++ r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, get_dmacfg_reg(port));
++ r8a66597_bclr(r8a66597, DTCHE, get_intenb_reg(port));
++ r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port));
++}
+
+- r8a66597_bset(r8a66597, DCFM | DRPD, SYSCFG0);
+- r8a66597_bset(r8a66597, DRPD, SYSCFG1);
++static void r8a66597_disable_port(struct r8a66597 *r8a66597, int port)
++{
++ u16 val, tmp;
++
++ r8a66597_write(r8a66597, 0, get_intenb_reg(port));
++ r8a66597_write(r8a66597, 0, get_intsts_reg(port));
++
++ r8a66597_port_power(r8a66597, port, 0);
++
++ do {
++ tmp = r8a66597_read(r8a66597, SOFCFG) & EDGESTS;
++ udelay(640);
++ } while (tmp == EDGESTS);
++
++ val = port ? DRPD : DCFM | DRPD;
++ r8a66597_bclr(r8a66597, val, get_syscfg_reg(port));
++ r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port));
++}
++
++static int enable_controller(struct r8a66597 *r8a66597)
++{
++ int ret, port;
++
++ ret = r8a66597_clock_enable(r8a66597);
++ if (ret < 0)
++ return ret;
+
+ r8a66597_bset(r8a66597, vif & LDRV, PINCFG);
+- r8a66597_bset(r8a66597, HSE, SYSCFG0);
+- r8a66597_bset(r8a66597, HSE, SYSCFG1);
+ r8a66597_bset(r8a66597, USBE, SYSCFG0);
+
+ r8a66597_bset(r8a66597, BEMPE | NRDYE | BRDYE, INTENB0);
+@@ -146,53 +209,30 @@ static int enable_controller(struct r8a66597 *r8a66597)
+ r8a66597_bset(r8a66597, BRDY0, BRDYENB);
+ r8a66597_bset(r8a66597, BEMP0, BEMPENB);
+
+- r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, DMA0CFG);
+- r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, DMA1CFG);
+-
+ r8a66597_bset(r8a66597, endian & BIGEND, CFIFOSEL);
+ r8a66597_bset(r8a66597, endian & BIGEND, D0FIFOSEL);
+ r8a66597_bset(r8a66597, endian & BIGEND, D1FIFOSEL);
+-
+ r8a66597_bset(r8a66597, TRNENSEL, SOFCFG);
+
+ r8a66597_bset(r8a66597, SIGNE | SACKE, INTENB1);
+- r8a66597_bclr(r8a66597, DTCHE, INTENB1);
+- r8a66597_bset(r8a66597, ATTCHE, INTENB1);
+- r8a66597_bclr(r8a66597, DTCHE, INTENB2);
+- r8a66597_bset(r8a66597, ATTCHE, INTENB2);
++
++ for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
++ r8a66597_enable_port(r8a66597, port);
+
+ return 0;
+ }
+
+ static void disable_controller(struct r8a66597 *r8a66597)
+ {
+- u16 tmp;
++ int port;
+
+ r8a66597_write(r8a66597, 0, INTENB0);
+- r8a66597_write(r8a66597, 0, INTENB1);
+- r8a66597_write(r8a66597, 0, INTENB2);
+ r8a66597_write(r8a66597, 0, INTSTS0);
+- r8a66597_write(r8a66597, 0, INTSTS1);
+- r8a66597_write(r8a66597, 0, INTSTS2);
+-
+- r8a66597_port_power(r8a66597, 0, 0);
+- r8a66597_port_power(r8a66597, 1, 0);
+-
+- do {
+- tmp = r8a66597_read(r8a66597, SOFCFG) & EDGESTS;
+- udelay(640);
+- } while (tmp == EDGESTS);
+
+- r8a66597_bclr(r8a66597, DCFM | DRPD, SYSCFG0);
+- r8a66597_bclr(r8a66597, DRPD, SYSCFG1);
+- r8a66597_bclr(r8a66597, HSE, SYSCFG0);
+- r8a66597_bclr(r8a66597, HSE, SYSCFG1);
++ for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
++ r8a66597_disable_port(r8a66597, port);
+
+- r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
+- udelay(1);
+- r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
+- r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
+- r8a66597_bclr(r8a66597, USBE, SYSCFG0);
++ r8a66597_clock_disable(r8a66597);
+ }
+
+ static int get_parent_r8a66597_address(struct r8a66597 *r8a66597,
+@@ -577,13 +617,9 @@ static void pipe_buffer_setting(struct r8a66597 *r8a66597,
+ PIPEBUF);
+ r8a66597_write(r8a66597, make_devsel(info->address) | info->maxpacket,
+ PIPEMAXP);
+- if (info->interval)
+- info->interval--;
+ r8a66597_write(r8a66597, info->interval, PIPEPERI);
+ }
+
+-
+-
+ /* this function must be called with interrupt disabled */
+ static void pipe_setting(struct r8a66597 *r8a66597, struct r8a66597_td *td)
+ {
+@@ -715,6 +751,7 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
+ struct r8a66597_pipe *pipe,
+ struct urb *urb)
+ {
++#if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
+ int i;
+ struct r8a66597_pipe_info *info = &pipe->info;
+
+@@ -742,6 +779,7 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
+ break;
+ }
+ }
++#endif /* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */
+ }
+
+ /* this function must be called with interrupt disabled */
+@@ -825,6 +863,25 @@ static void disable_r8a66597_pipe_all(struct r8a66597 *r8a66597,
+ dev->dma_map = 0;
+ }
+
++static unsigned long get_timer_interval(struct urb *urb, __u8 interval)
++{
++ __u8 i;
++ unsigned long time = 1;
++
++ if (usb_pipeisoc(urb->pipe))
++ return 0;
++
++ if (get_r8a66597_usb_speed(urb->dev->speed) == HSMODE) {
++ for (i = 0; i < (interval - 1); i++)
++ time *= 2;
++ time = time * 125 / 1000; /* uSOF -> msec */
++ } else {
++ time = interval;
++ }
++
++ return time;
++}
++
+ /* this function must be called with interrupt disabled */
+ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb,
+ struct usb_host_endpoint *hep,
+@@ -840,7 +897,16 @@ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb,
+ & USB_ENDPOINT_XFERTYPE_MASK);
+ info.bufnum = get_bufnum(info.pipenum);
+ info.buf_bsize = get_buf_bsize(info.pipenum);
+- info.interval = ep->bInterval;
++ if (info.type == R8A66597_BULK) {
++ info.interval = 0;
++ info.timer_interval = 0;
++ } else {
++ if (ep->bInterval > IITV)
++ info.interval = IITV;
++ else
++ info.interval = ep->bInterval ? ep->bInterval - 1 : 0;
++ info.timer_interval = get_timer_interval(urb, ep->bInterval);
++ }
+ if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+ info.dir_in = 1;
+ else
+@@ -876,10 +942,19 @@ static void pipe_irq_disable(struct r8a66597 *r8a66597, u16 pipenum)
+ }
+
+ /* this function must be called with interrupt disabled */
+-static void r8a66597_usb_preconnect(struct r8a66597 *r8a66597, int port)
++static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port,
++ u16 syssts)
+ {
+- r8a66597->root_hub[port].port |= (1 << USB_PORT_FEAT_CONNECTION)
+- | (1 << USB_PORT_FEAT_C_CONNECTION);
++ if (syssts == SE0) {
++ r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port));
++ return;
++ }
++
++ if (syssts == FS_JSTS)
++ r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port));
++ else if (syssts == LS_JSTS)
++ r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port));
++
+ r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port));
+ r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port));
+ }
+@@ -960,9 +1035,9 @@ static void prepare_packet_read(struct r8a66597 *r8a66597,
+ r8a66597_write(r8a66597, TRCLR,
+ td->pipe->pipetre);
+ r8a66597_write(r8a66597,
+- (urb->transfer_buffer_length
+- + td->maxpacket - 1)
+- / td->maxpacket,
++ DIV_ROUND_UP
++ (urb->transfer_buffer_length,
++ td->maxpacket),
+ td->pipe->pipetrn);
+ r8a66597_bset(r8a66597, TRENB,
+ td->pipe->pipetre);
+@@ -1021,8 +1096,7 @@ static void prepare_status_packet(struct r8a66597 *r8a66597,
+ r8a66597_mdfy(r8a66597, ISEL, ISEL | CURPIPE, CFIFOSEL);
+ r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+ r8a66597_write(r8a66597, ~BEMP0, BEMPSTS);
+- r8a66597_write(r8a66597, BCLR, CFIFOCTR);
+- r8a66597_write(r8a66597, BVAL, CFIFOCTR);
++ r8a66597_write(r8a66597, BCLR | BVAL, CFIFOCTR);
+ enable_irq_empty(r8a66597, 0);
+ } else {
+ r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG);
+@@ -1454,13 +1528,21 @@ static void irq_pipe_nrdy(struct r8a66597 *r8a66597)
+ }
+ }
+
++static void r8a66597_root_hub_start_polling(struct r8a66597 *r8a66597)
++{
++ mod_timer(&r8a66597->rh_timer,
++ jiffies + msecs_to_jiffies(R8A66597_RH_POLL_TIME));
++}
++
+ static void start_root_hub_sampling(struct r8a66597 *r8a66597, int port)
+ {
+ struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
+
+ rh->old_syssts = r8a66597_read(r8a66597, get_syssts_reg(port)) & LNST;
+ rh->scount = R8A66597_MAX_SAMPLING;
+- mod_timer(&r8a66597->rh_timer, jiffies + msecs_to_jiffies(50));
++ r8a66597->root_hub[port].port |= (1 << USB_PORT_FEAT_CONNECTION)
++ | (1 << USB_PORT_FEAT_C_CONNECTION);
++ r8a66597_root_hub_start_polling(r8a66597);
+ }
+
+ static irqreturn_t r8a66597_irq(struct usb_hcd *hcd)
+@@ -1547,41 +1629,55 @@ static void r8a66597_root_hub_control(struct r8a66597 *r8a66597, int port)
+ if ((tmp & USBRST) == USBRST) {
+ r8a66597_mdfy(r8a66597, UACT, USBRST | UACT,
+ dvstctr_reg);
+- mod_timer(&r8a66597->rh_timer,
+- jiffies + msecs_to_jiffies(50));
++ r8a66597_root_hub_start_polling(r8a66597);
+ } else
+ r8a66597_usb_connect(r8a66597, port);
+ }
+
++ if (!(rh->port & (1 << USB_PORT_FEAT_CONNECTION))) {
++ r8a66597_write(r8a66597, ~ATTCH, get_intsts_reg(port));
++ r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port));
++ }
++
+ if (rh->scount > 0) {
+ tmp = r8a66597_read(r8a66597, get_syssts_reg(port)) & LNST;
+ if (tmp == rh->old_syssts) {
+ rh->scount--;
+- if (rh->scount == 0) {
+- if (tmp == FS_JSTS) {
+- r8a66597_bset(r8a66597, HSE,
+- get_syscfg_reg(port));
+- r8a66597_usb_preconnect(r8a66597, port);
+- } else if (tmp == LS_JSTS) {
+- r8a66597_bclr(r8a66597, HSE,
+- get_syscfg_reg(port));
+- r8a66597_usb_preconnect(r8a66597, port);
+- } else if (tmp == SE0)
+- r8a66597_bset(r8a66597, ATTCHE,
+- get_intenb_reg(port));
+- } else {
+- mod_timer(&r8a66597->rh_timer,
+- jiffies + msecs_to_jiffies(50));
+- }
++ if (rh->scount == 0)
++ r8a66597_check_syssts(r8a66597, port, tmp);
++ else
++ r8a66597_root_hub_start_polling(r8a66597);
+ } else {
+ rh->scount = R8A66597_MAX_SAMPLING;
+ rh->old_syssts = tmp;
+- mod_timer(&r8a66597->rh_timer,
+- jiffies + msecs_to_jiffies(50));
++ r8a66597_root_hub_start_polling(r8a66597);
+ }
+ }
+ }
+
++static void r8a66597_interval_timer(unsigned long _r8a66597)
++{
++ struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597;
++ unsigned long flags;
++ u16 pipenum;
++ struct r8a66597_td *td;
++
++ spin_lock_irqsave(&r8a66597->lock, flags);
++
++ for (pipenum = 0; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
++ if (!(r8a66597->interval_map & (1 << pipenum)))
++ continue;
++ if (timer_pending(&r8a66597->interval_timer[pipenum]))
++ continue;
++
++ td = r8a66597_get_td(r8a66597, pipenum);
++ if (td)
++ start_transfer(r8a66597, td);
++ }
++
++ spin_unlock_irqrestore(&r8a66597->lock, flags);
++}
++
+ static void r8a66597_td_timer(unsigned long _r8a66597)
+ {
+ struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597;
+@@ -1763,10 +1859,17 @@ static int r8a66597_urb_enqueue(struct usb_hcd *hcd,
+ urb->hcpriv = td;
+
+ if (request) {
+- ret = start_transfer(r8a66597, td);
+- if (ret < 0) {
+- list_del(&td->queue);
+- kfree(td);
++ if (td->pipe->info.timer_interval) {
++ r8a66597->interval_map |= 1 << td->pipenum;
++ mod_timer(&r8a66597->interval_timer[td->pipenum],
++ jiffies + msecs_to_jiffies(
++ td->pipe->info.timer_interval));
++ } else {
++ ret = start_transfer(r8a66597, td);
++ if (ret < 0) {
++ list_del(&td->queue);
++ kfree(td);
++ }
+ }
+ } else
+ set_td_timer(r8a66597, td);
+@@ -2107,13 +2210,11 @@ static struct hc_driver r8a66597_hc_driver = {
+ #if defined(CONFIG_PM)
+ static int r8a66597_suspend(struct platform_device *pdev, pm_message_t state)
+ {
+- pdev->dev.power.power_state = state;
+ return 0;
+ }
+
+ static int r8a66597_resume(struct platform_device *pdev)
+ {
+- pdev->dev.power.power_state = PMSG_ON;
+ return 0;
+ }
+ #else /* if defined(CONFIG_PM) */
+@@ -2194,6 +2295,9 @@ static int __init r8a66597_probe(struct platform_device *pdev)
+ init_timer(&r8a66597->td_timer[i]);
+ r8a66597->td_timer[i].function = r8a66597_td_timer;
+ r8a66597->td_timer[i].data = (unsigned long)r8a66597;
++ setup_timer(&r8a66597->interval_timer[i],
++ r8a66597_interval_timer,
++ (unsigned long)r8a66597);
+ }
+ INIT_LIST_HEAD(&r8a66597->child_device);
+
+diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h
+index 5738825..84ee014 100644
+--- a/drivers/usb/host/r8a66597.h
++++ b/drivers/usb/host/r8a66597.h
+@@ -187,7 +187,11 @@
+ #define REW 0x4000 /* b14: Buffer rewind */
+ #define DCLRM 0x2000 /* b13: DMA buffer clear mode */
+ #define DREQE 0x1000 /* b12: DREQ output enable */
++#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
++#define MBW 0x0800
++#else
+ #define MBW 0x0400 /* b10: Maximum bit width for FIFO access */
++#endif
+ #define MBW_8 0x0000 /* 8bit */
+ #define MBW_16 0x0400 /* 16bit */
+ #define BIGEND 0x0100 /* b8: Big endian mode */
+@@ -395,8 +399,13 @@
+ #define R8A66597_MAX_NUM_PIPE 10
+ #define R8A66597_BUF_BSIZE 8
+ #define R8A66597_MAX_DEVICE 10
++#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
++#define R8A66597_MAX_ROOT_HUB 1
++#else
+ #define R8A66597_MAX_ROOT_HUB 2
+-#define R8A66597_MAX_SAMPLING 10
++#endif
++#define R8A66597_MAX_SAMPLING 5
++#define R8A66597_RH_POLL_TIME 10
+ #define R8A66597_MAX_DMA_CHANNEL 2
+ #define R8A66597_PIPE_NO_DMA R8A66597_MAX_DMA_CHANNEL
+ #define check_bulk_or_isoc(pipenum) ((pipenum >= 1 && pipenum <= 5))
+@@ -404,6 +413,7 @@
+ #define make_devsel(addr) (addr << 12)
+
+ struct r8a66597_pipe_info {
++ unsigned long timer_interval;
+ u16 pipenum;
+ u16 address; /* R8A66597 HCD usb address */
+ u16 epnum;
+@@ -478,9 +488,11 @@ struct r8a66597 {
+
+ struct timer_list rh_timer;
+ struct timer_list td_timer[R8A66597_MAX_NUM_PIPE];
++ struct timer_list interval_timer[R8A66597_MAX_NUM_PIPE];
+
+ unsigned short address_map;
+ unsigned short timeout_map;
++ unsigned short interval_map;
+ unsigned char pipe_cnt[R8A66597_MAX_NUM_PIPE];
+ unsigned char dma_map;
+
+@@ -526,8 +538,21 @@ static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
+ unsigned long offset, u16 *buf,
+ int len)
+ {
++#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
++ unsigned long fifoaddr = r8a66597->reg + offset;
++ unsigned long count;
++
++ count = len / 4;
++ insl(fifoaddr, buf, count);
++
++ if (len & 0x00000003) {
++ unsigned long tmp = inl(fifoaddr);
++ memcpy((unsigned char *)buf + count * 4, &tmp, len & 0x03);
++ }
++#else
+ len = (len + 1) / 2;
+ insw(r8a66597->reg + offset, buf, len);
++#endif
+ }
+
+ static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
+@@ -541,6 +566,24 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
+ int len)
+ {
+ unsigned long fifoaddr = r8a66597->reg + offset;
++#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
++ unsigned long count;
++ unsigned char *pb;
++ int i;
++
++ count = len / 4;
++ outsl(fifoaddr, buf, count);
++
++ if (len & 0x00000003) {
++ pb = (unsigned char *)buf + count * 4;
++ for (i = 0; i < (len & 0x00000003); i++) {
++ if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)
++ outb(pb[i], fifoaddr + i);
++ else
++ outb(pb[i], fifoaddr + 3 - i);
++ }
++ }
++#else
+ int odd = len & 0x0001;
+
+ len = len / 2;
+@@ -549,6 +592,7 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
+ buf = &buf[len];
+ outb((unsigned char)*buf, fifoaddr);
+ }
++#endif
+ }
+
+ static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
+@@ -581,6 +625,11 @@ static inline unsigned long get_dvstctr_reg(int port)
+ return port == 0 ? DVSTCTR0 : DVSTCTR1;
+ }
+
++static inline unsigned long get_dmacfg_reg(int port)
++{
++ return port == 0 ? DMA0CFG : DMA1CFG;
++}
++
+ static inline unsigned long get_intenb_reg(int port)
+ {
+ return port == 0 ? INTENB1 : INTENB2;
+diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
+index 629bca0..274276c 100644
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -94,12 +94,10 @@ static void port_power(struct sl811 *sl811, int is_on)
+
+ sl811->port1 = (1 << USB_PORT_FEAT_POWER);
+ sl811->irq_enable = SL11H_INTMASK_INSRMV;
+- hcd->self.controller->power.power_state = PMSG_ON;
+ } else {
+ sl811->port1 = 0;
+ sl811->irq_enable = 0;
+ hcd->state = HC_STATE_HALT;
+- hcd->self.controller->power.power_state = PMSG_SUSPEND;
+ }
+ sl811->ctrl1 = 0;
+ sl811_write(sl811, SL11H_IRQ_ENABLE, 0);
+@@ -1337,7 +1335,7 @@ static int
+ sl811h_bus_suspend(struct usb_hcd *hcd)
+ {
+ // SOFs off
+- DBG("%s\n", __FUNCTION__);
++ DBG("%s\n", __func__);
+ return 0;
+ }
+
+@@ -1345,7 +1343,7 @@ static int
+ sl811h_bus_resume(struct usb_hcd *hcd)
+ {
+ // SOFs on
+- DBG("%s\n", __FUNCTION__);
++ DBG("%s\n", __func__);
+ return 0;
+ }
+
+@@ -1772,8 +1770,6 @@ sl811h_suspend(struct platform_device *dev, pm_message_t state)
+ port_power(sl811, 0);
+ break;
+ }
+- if (retval == 0)
+- dev->dev.power.power_state = state;
+ return retval;
+ }
+
+@@ -1786,15 +1782,13 @@ sl811h_resume(struct platform_device *dev)
+ /* with no "check to see if VBUS is still powered" board hook,
+ * let's assume it'd only be powered to enable remote wakeup.
+ */
+- if (dev->dev.power.power_state.event == PM_EVENT_SUSPEND
+- || !device_can_wakeup(&hcd->self.root_hub->dev)) {
++ if (!sl811->port1 || !device_can_wakeup(&hcd->self.root_hub->dev)) {
+ sl811->port1 = 0;
+ port_power(sl811, 1);
+ usb_root_hub_lost_power(hcd->self.root_hub);
+ return 0;
+ }
+
+- dev->dev.power.power_state = PMSG_ON;
+ return sl811h_bus_resume(hcd);
+ }
+
+diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
+index 8e117a7..f293074 100644
+--- a/drivers/usb/host/u132-hcd.c
++++ b/drivers/usb/host/u132-hcd.c
+@@ -67,7 +67,7 @@
+ #include "ohci.h"
+ #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR
+ #define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \
+- OHCI_INTR_WDH)
++ OHCI_INTR_WDH)
+ MODULE_AUTHOR("Tony Olech - Elan Digital Systems Limited");
+ MODULE_DESCRIPTION("U132 USB Host Controller Driver");
+ MODULE_LICENSE("GPL");
+@@ -77,15 +77,15 @@ INT_MODULE_PARM(testing, 0);
+ static int distrust_firmware = 1;
+ module_param(distrust_firmware, bool, 0);
+ MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren"
+- "t setup");
++ "t setup");
+ static DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait);
+ /*
+ * u132_module_lock exists to protect access to global variables
+ *
+ */
+ static struct mutex u132_module_lock;
+-static int u132_exiting = 0;
+-static int u132_instances = 0;
++static int u132_exiting;
++static int u132_instances;
+ static struct list_head u132_static_list;
+ /*
+ * end of the global variables protected by u132_module_lock
+@@ -97,115 +97,115 @@ static struct workqueue_struct *workqueue;
+ #define MAX_U132_ENDPS 100
+ #define MAX_U132_RINGS 4
+ static const char *cc_to_text[16] = {
+- "No Error ",
+- "CRC Error ",
+- "Bit Stuff ",
+- "Data Togg ",
+- "Stall ",
+- "DevNotResp ",
+- "PIDCheck ",
+- "UnExpPID ",
+- "DataOver ",
+- "DataUnder ",
+- "(for hw) ",
+- "(for hw) ",
+- "BufferOver ",
+- "BuffUnder ",
+- "(for HCD) ",
+- "(for HCD) "
++ "No Error ",
++ "CRC Error ",
++ "Bit Stuff ",
++ "Data Togg ",
++ "Stall ",
++ "DevNotResp ",
++ "PIDCheck ",
++ "UnExpPID ",
++ "DataOver ",
++ "DataUnder ",
++ "(for hw) ",
++ "(for hw) ",
++ "BufferOver ",
++ "BuffUnder ",
++ "(for HCD) ",
++ "(for HCD) "
+ };
+ struct u132_port {
+- struct u132 *u132;
+- int reset;
+- int enable;
+- int power;
+- int Status;
++ struct u132 *u132;
++ int reset;
++ int enable;
++ int power;
++ int Status;
+ };
+ struct u132_addr {
+- u8 address;
++ u8 address;
+ };
+ struct u132_udev {
+- struct kref kref;
+- struct usb_device *usb_device;
+- u8 enumeration;
+- u8 udev_number;
+- u8 usb_addr;
+- u8 portnumber;
+- u8 endp_number_in[16];
+- u8 endp_number_out[16];
++ struct kref kref;
++ struct usb_device *usb_device;
++ u8 enumeration;
++ u8 udev_number;
++ u8 usb_addr;
++ u8 portnumber;
++ u8 endp_number_in[16];
++ u8 endp_number_out[16];
+ };
+ #define ENDP_QUEUE_SHIFT 3
+ #define ENDP_QUEUE_SIZE (1<<ENDP_QUEUE_SHIFT)
+ #define ENDP_QUEUE_MASK (ENDP_QUEUE_SIZE-1)
+ struct u132_urbq {
+- struct list_head urb_more;
+- struct urb *urb;
++ struct list_head urb_more;
++ struct urb *urb;
+ };
+ struct u132_spin {
+- spinlock_t slock;
++ spinlock_t slock;
+ };
+ struct u132_endp {
+- struct kref kref;
+- u8 udev_number;
+- u8 endp_number;
+- u8 usb_addr;
+- u8 usb_endp;
+- struct u132 *u132;
+- struct list_head endp_ring;
+- struct u132_ring *ring;
+- unsigned toggle_bits:2;
+- unsigned active:1;
+- unsigned delayed:1;
+- unsigned input:1;
+- unsigned output:1;
+- unsigned pipetype:2;
+- unsigned dequeueing:1;
+- unsigned edset_flush:1;
+- unsigned spare_bits:14;
+- unsigned long jiffies;
+- struct usb_host_endpoint *hep;
+- struct u132_spin queue_lock;
+- u16 queue_size;
+- u16 queue_last;
+- u16 queue_next;
+- struct urb *urb_list[ENDP_QUEUE_SIZE];
+- struct list_head urb_more;
+- struct delayed_work scheduler;
++ struct kref kref;
++ u8 udev_number;
++ u8 endp_number;
++ u8 usb_addr;
++ u8 usb_endp;
++ struct u132 *u132;
++ struct list_head endp_ring;
++ struct u132_ring *ring;
++ unsigned toggle_bits:2;
++ unsigned active:1;
++ unsigned delayed:1;
++ unsigned input:1;
++ unsigned output:1;
++ unsigned pipetype:2;
++ unsigned dequeueing:1;
++ unsigned edset_flush:1;
++ unsigned spare_bits:14;
++ unsigned long jiffies;
++ struct usb_host_endpoint *hep;
++ struct u132_spin queue_lock;
++ u16 queue_size;
++ u16 queue_last;
++ u16 queue_next;
++ struct urb *urb_list[ENDP_QUEUE_SIZE];
++ struct list_head urb_more;
++ struct delayed_work scheduler;
+ };
+ struct u132_ring {
+- unsigned in_use:1;
+- unsigned length:7;
+- u8 number;
+- struct u132 *u132;
+- struct u132_endp *curr_endp;
+- struct delayed_work scheduler;
++ unsigned in_use:1;
++ unsigned length:7;
++ u8 number;
++ struct u132 *u132;
++ struct u132_endp *curr_endp;
++ struct delayed_work scheduler;
+ };
+ struct u132 {
+- struct kref kref;
+- struct list_head u132_list;
+- struct mutex sw_lock;
+- struct semaphore scheduler_lock;
+- struct u132_platform_data *board;
+- struct platform_device *platform_dev;
+- struct u132_ring ring[MAX_U132_RINGS];
+- int sequence_num;
+- int going;
+- int power;
+- int reset;
+- int num_ports;
+- u32 hc_control;
+- u32 hc_fminterval;
+- u32 hc_roothub_status;
+- u32 hc_roothub_a;
+- u32 hc_roothub_portstatus[MAX_ROOT_PORTS];
+- int flags;
+- unsigned long next_statechange;
+- struct delayed_work monitor;
+- int num_endpoints;
+- struct u132_addr addr[MAX_U132_ADDRS];
+- struct u132_udev udev[MAX_U132_UDEVS];
+- struct u132_port port[MAX_U132_PORTS];
+- struct u132_endp *endp[MAX_U132_ENDPS];
++ struct kref kref;
++ struct list_head u132_list;
++ struct mutex sw_lock;
++ struct mutex scheduler_lock;
++ struct u132_platform_data *board;
++ struct platform_device *platform_dev;
++ struct u132_ring ring[MAX_U132_RINGS];
++ int sequence_num;
++ int going;
++ int power;
++ int reset;
++ int num_ports;
++ u32 hc_control;
++ u32 hc_fminterval;
++ u32 hc_roothub_status;
++ u32 hc_roothub_a;
++ u32 hc_roothub_portstatus[MAX_ROOT_PORTS];
++ int flags;
++ unsigned long next_statechange;
++ struct delayed_work monitor;
++ int num_endpoints;
++ struct u132_addr addr[MAX_U132_ADDRS];
++ struct u132_udev udev[MAX_U132_UDEVS];
++ struct u132_port port[MAX_U132_PORTS];
++ struct u132_endp *endp[MAX_U132_ENDPS];
+ };
+
+ /*
+@@ -213,34 +213,34 @@ struct u132 {
+ * Does anyone have a better way?????
+ */
+ #define ftdi_read_pcimem(pdev, member, data) usb_ftdi_elan_read_pcimem(pdev, \
+- offsetof(struct ohci_regs, member), 0, data);
++ offsetof(struct ohci_regs, member), 0, data);
+ #define ftdi_write_pcimem(pdev, member, data) usb_ftdi_elan_write_pcimem(pdev, \
+- offsetof(struct ohci_regs, member), 0, data);
++ offsetof(struct ohci_regs, member), 0, data);
+ #define u132_read_pcimem(u132, member, data) \
+- usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \
+- ohci_regs, member), 0, data);
++ usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \
++ ohci_regs, member), 0, data);
+ #define u132_write_pcimem(u132, member, data) \
+- usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \
+- ohci_regs, member), 0, data);
++ usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \
++ ohci_regs, member), 0, data);
+ static inline struct u132 *udev_to_u132(struct u132_udev *udev)
+ {
+- u8 udev_number = udev->udev_number;
+- return container_of(udev, struct u132, udev[udev_number]);
++ u8 udev_number = udev->udev_number;
++ return container_of(udev, struct u132, udev[udev_number]);
+ }
+
+ static inline struct u132 *hcd_to_u132(struct usb_hcd *hcd)
+ {
+- return (struct u132 *)(hcd->hcd_priv);
++ return (struct u132 *)(hcd->hcd_priv);
+ }
+
+ static inline struct usb_hcd *u132_to_hcd(struct u132 *u132)
+ {
+- return container_of((void *)u132, struct usb_hcd, hcd_priv);
++ return container_of((void *)u132, struct usb_hcd, hcd_priv);
+ }
+
+ static inline void u132_disable(struct u132 *u132)
+ {
+- u132_to_hcd(u132)->state = HC_STATE_HALT;
++ u132_to_hcd(u132)->state = HC_STATE_HALT;
+ }
+
+
+@@ -250,147 +250,147 @@ static inline void u132_disable(struct u132 *u132)
+ #include "../misc/usb_u132.h"
+ static const char hcd_name[] = "u132_hcd";
+ #define PORT_C_MASK ((USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | \
+- USB_PORT_STAT_C_SUSPEND | USB_PORT_STAT_C_OVERCURRENT | \
+- USB_PORT_STAT_C_RESET) << 16)
++ USB_PORT_STAT_C_SUSPEND | USB_PORT_STAT_C_OVERCURRENT | \
++ USB_PORT_STAT_C_RESET) << 16)
+ static void u132_hcd_delete(struct kref *kref)
+ {
+- struct u132 *u132 = kref_to_u132(kref);
+- struct platform_device *pdev = u132->platform_dev;
+- struct usb_hcd *hcd = u132_to_hcd(u132);
+- u132->going += 1;
+- mutex_lock(&u132_module_lock);
+- list_del_init(&u132->u132_list);
+- u132_instances -= 1;
+- mutex_unlock(&u132_module_lock);
+- dev_warn(&u132->platform_dev->dev, "FREEING the hcd=%p and thus the u13"
+- "2=%p going=%d pdev=%p\n", hcd, u132, u132->going, pdev);
+- usb_put_hcd(hcd);
++ struct u132 *u132 = kref_to_u132(kref);
++ struct platform_device *pdev = u132->platform_dev;
++ struct usb_hcd *hcd = u132_to_hcd(u132);
++ u132->going += 1;
++ mutex_lock(&u132_module_lock);
++ list_del_init(&u132->u132_list);
++ u132_instances -= 1;
++ mutex_unlock(&u132_module_lock);
++ dev_warn(&u132->platform_dev->dev, "FREEING the hcd=%p and thus the u13"
++ "2=%p going=%d pdev=%p\n", hcd, u132, u132->going, pdev);
++ usb_put_hcd(hcd);
+ }
+
+ static inline void u132_u132_put_kref(struct u132 *u132)
+ {
+- kref_put(&u132->kref, u132_hcd_delete);
++ kref_put(&u132->kref, u132_hcd_delete);
+ }
+
+ static inline void u132_u132_init_kref(struct u132 *u132)
+ {
+- kref_init(&u132->kref);
++ kref_init(&u132->kref);
+ }
+
+ static void u132_udev_delete(struct kref *kref)
+ {
+- struct u132_udev *udev = kref_to_u132_udev(kref);
+- udev->udev_number = 0;
+- udev->usb_device = NULL;
+- udev->usb_addr = 0;
+- udev->enumeration = 0;
++ struct u132_udev *udev = kref_to_u132_udev(kref);
++ udev->udev_number = 0;
++ udev->usb_device = NULL;
++ udev->usb_addr = 0;
++ udev->enumeration = 0;
+ }
+
+ static inline void u132_udev_put_kref(struct u132 *u132, struct u132_udev *udev)
+ {
+- kref_put(&udev->kref, u132_udev_delete);
++ kref_put(&udev->kref, u132_udev_delete);
+ }
+
+ static inline void u132_udev_get_kref(struct u132 *u132, struct u132_udev *udev)
+ {
+- kref_get(&udev->kref);
++ kref_get(&udev->kref);
+ }
+
+ static inline void u132_udev_init_kref(struct u132 *u132,
+- struct u132_udev *udev)
++ struct u132_udev *udev)
+ {
+- kref_init(&udev->kref);
++ kref_init(&udev->kref);
+ }
+
+ static inline void u132_ring_put_kref(struct u132 *u132, struct u132_ring *ring)
+ {
+- kref_put(&u132->kref, u132_hcd_delete);
++ kref_put(&u132->kref, u132_hcd_delete);
+ }
+
+ static void u132_ring_requeue_work(struct u132 *u132, struct u132_ring *ring,
+- unsigned int delta)
++ unsigned int delta)
+ {
+- if (delta > 0) {
+- if (queue_delayed_work(workqueue, &ring->scheduler, delta))
+- return;
+- } else if (queue_delayed_work(workqueue, &ring->scheduler, 0))
+- return;
+- kref_put(&u132->kref, u132_hcd_delete);
+- return;
++ if (delta > 0) {
++ if (queue_delayed_work(workqueue, &ring->scheduler, delta))
++ return;
++ } else if (queue_delayed_work(workqueue, &ring->scheduler, 0))
++ return;
++ kref_put(&u132->kref, u132_hcd_delete);
++ return;
+ }
+
+ static void u132_ring_queue_work(struct u132 *u132, struct u132_ring *ring,
+- unsigned int delta)
++ unsigned int delta)
+ {
+- kref_get(&u132->kref);
+- u132_ring_requeue_work(u132, ring, delta);
+- return;
++ kref_get(&u132->kref);
++ u132_ring_requeue_work(u132, ring, delta);
++ return;
+ }
+
+ static void u132_ring_cancel_work(struct u132 *u132, struct u132_ring *ring)
+ {
+- if (cancel_delayed_work(&ring->scheduler)) {
+- kref_put(&u132->kref, u132_hcd_delete);
+- }
++ if (cancel_delayed_work(&ring->scheduler))
++ kref_put(&u132->kref, u132_hcd_delete);
+ }
+
+ static void u132_endp_delete(struct kref *kref)
+ {
+- struct u132_endp *endp = kref_to_u132_endp(kref);
+- struct u132 *u132 = endp->u132;
+- u8 usb_addr = endp->usb_addr;
+- u8 usb_endp = endp->usb_endp;
+- u8 address = u132->addr[usb_addr].address;
+- struct u132_udev *udev = &u132->udev[address];
+- u8 endp_number = endp->endp_number;
+- struct usb_host_endpoint *hep = endp->hep;
+- struct u132_ring *ring = endp->ring;
+- struct list_head *head = &endp->endp_ring;
+- ring->length -= 1;
+- if (endp == ring->curr_endp) {
+- if (list_empty(head)) {
+- ring->curr_endp = NULL;
+- list_del(head);
+- } else {
+- struct u132_endp *next_endp = list_entry(head->next,
+- struct u132_endp, endp_ring);
+- ring->curr_endp = next_endp;
+- list_del(head);
+- }} else
+- list_del(head);
+- if (endp->input) {
+- udev->endp_number_in[usb_endp] = 0;
+- u132_udev_put_kref(u132, udev);
+- }
+- if (endp->output) {
+- udev->endp_number_out[usb_endp] = 0;
+- u132_udev_put_kref(u132, udev);
+- }
+- u132->endp[endp_number - 1] = NULL;
+- hep->hcpriv = NULL;
+- kfree(endp);
+- u132_u132_put_kref(u132);
++ struct u132_endp *endp = kref_to_u132_endp(kref);
++ struct u132 *u132 = endp->u132;
++ u8 usb_addr = endp->usb_addr;
++ u8 usb_endp = endp->usb_endp;
++ u8 address = u132->addr[usb_addr].address;
++ struct u132_udev *udev = &u132->udev[address];
++ u8 endp_number = endp->endp_number;
++ struct usb_host_endpoint *hep = endp->hep;
++ struct u132_ring *ring = endp->ring;
++ struct list_head *head = &endp->endp_ring;
++ ring->length -= 1;
++ if (endp == ring->curr_endp) {
++ if (list_empty(head)) {
++ ring->curr_endp = NULL;
++ list_del(head);
++ } else {
++ struct u132_endp *next_endp = list_entry(head->next,
++ struct u132_endp, endp_ring);
++ ring->curr_endp = next_endp;
++ list_del(head);
++ }
++ } else
++ list_del(head);
++ if (endp->input) {
++ udev->endp_number_in[usb_endp] = 0;
++ u132_udev_put_kref(u132, udev);
++ }
++ if (endp->output) {
++ udev->endp_number_out[usb_endp] = 0;
++ u132_udev_put_kref(u132, udev);
++ }
++ u132->endp[endp_number - 1] = NULL;
++ hep->hcpriv = NULL;
++ kfree(endp);
++ u132_u132_put_kref(u132);
+ }
+
+ static inline void u132_endp_put_kref(struct u132 *u132, struct u132_endp *endp)
+ {
+- kref_put(&endp->kref, u132_endp_delete);
++ kref_put(&endp->kref, u132_endp_delete);
+ }
+
+ static inline void u132_endp_get_kref(struct u132 *u132, struct u132_endp *endp)
+ {
+- kref_get(&endp->kref);
++ kref_get(&endp->kref);
+ }
+
+ static inline void u132_endp_init_kref(struct u132 *u132,
+- struct u132_endp *endp)
++ struct u132_endp *endp)
+ {
+- kref_init(&endp->kref);
+- kref_get(&u132->kref);
++ kref_init(&endp->kref);
++ kref_get(&u132->kref);
+ }
+
+ static void u132_endp_queue_work(struct u132 *u132, struct u132_endp *endp,
+- unsigned int delta)
++ unsigned int delta)
+ {
+ if (queue_delayed_work(workqueue, &endp->scheduler, delta))
+ kref_get(&endp->kref);
+@@ -398,13 +398,13 @@ static void u132_endp_queue_work(struct u132 *u132, struct u132_endp *endp,
+
+ static void u132_endp_cancel_work(struct u132 *u132, struct u132_endp *endp)
+ {
+- if (cancel_delayed_work(&endp->scheduler))
+- kref_put(&endp->kref, u132_endp_delete);
++ if (cancel_delayed_work(&endp->scheduler))
++ kref_put(&endp->kref, u132_endp_delete);
+ }
+
+ static inline void u132_monitor_put_kref(struct u132 *u132)
+ {
+- kref_put(&u132->kref, u132_hcd_delete);
++ kref_put(&u132->kref, u132_hcd_delete);
+ }
+
+ static void u132_monitor_queue_work(struct u132 *u132, unsigned int delta)
+@@ -421,200 +421,201 @@ static void u132_monitor_requeue_work(struct u132 *u132, unsigned int delta)
+
+ static void u132_monitor_cancel_work(struct u132 *u132)
+ {
+- if (cancel_delayed_work(&u132->monitor))
+- kref_put(&u132->kref, u132_hcd_delete);
++ if (cancel_delayed_work(&u132->monitor))
++ kref_put(&u132->kref, u132_hcd_delete);
+ }
+
+ static int read_roothub_info(struct u132 *u132)
+ {
+- u32 revision;
+- int retval;
+- retval = u132_read_pcimem(u132, revision, &revision);
+- if (retval) {
+- dev_err(&u132->platform_dev->dev, "error %d accessing device co"
+- "ntrol\n", retval);
+- return retval;
+- } else if ((revision & 0xFF) == 0x10) {
+- } else if ((revision & 0xFF) == 0x11) {
+- } else {
+- dev_err(&u132->platform_dev->dev, "device revision is not valid"
+- " %08X\n", revision);
+- return -ENODEV;
+- }
+- retval = u132_read_pcimem(u132, control, &u132->hc_control);
+- if (retval) {
+- dev_err(&u132->platform_dev->dev, "error %d accessing device co"
+- "ntrol\n", retval);
+- return retval;
+- }
+- retval = u132_read_pcimem(u132, roothub.status,
+- &u132->hc_roothub_status);
+- if (retval) {
+- dev_err(&u132->platform_dev->dev, "error %d accessing device re"
+- "g roothub.status\n", retval);
+- return retval;
+- }
+- retval = u132_read_pcimem(u132, roothub.a, &u132->hc_roothub_a);
+- if (retval) {
+- dev_err(&u132->platform_dev->dev, "error %d accessing device re"
+- "g roothub.a\n", retval);
+- return retval;
+- }
+- {
+- int I = u132->num_ports;
+- int i = 0;
+- while (I-- > 0) {
+- retval = u132_read_pcimem(u132, roothub.portstatus[i],
+- &u132->hc_roothub_portstatus[i]);
+- if (retval) {
+- dev_err(&u132->platform_dev->dev, "error %d acc"
+- "essing device roothub.portstatus[%d]\n"
+- , retval, i);
+- return retval;
+- } else
+- i += 1;
+- }
+- }
+- return 0;
++ u32 revision;
++ int retval;
++ retval = u132_read_pcimem(u132, revision, &revision);
++ if (retval) {
++ dev_err(&u132->platform_dev->dev, "error %d accessing device co"
++ "ntrol\n", retval);
++ return retval;
++ } else if ((revision & 0xFF) == 0x10) {
++ } else if ((revision & 0xFF) == 0x11) {
++ } else {
++ dev_err(&u132->platform_dev->dev, "device revision is not valid"
++ " %08X\n", revision);
++ return -ENODEV;
++ }
++ retval = u132_read_pcimem(u132, control, &u132->hc_control);
++ if (retval) {
++ dev_err(&u132->platform_dev->dev, "error %d accessing device co"
++ "ntrol\n", retval);
++ return retval;
++ }
++ retval = u132_read_pcimem(u132, roothub.status,
++ &u132->hc_roothub_status);
++ if (retval) {
++ dev_err(&u132->platform_dev->dev, "error %d accessing device re"
++ "g roothub.status\n", retval);
++ return retval;
++ }
++ retval = u132_read_pcimem(u132, roothub.a, &u132->hc_roothub_a);
++ if (retval) {
++ dev_err(&u132->platform_dev->dev, "error %d accessing device re"
++ "g roothub.a\n", retval);
++ return retval;
++ }
++ {
++ int I = u132->num_ports;
++ int i = 0;
++ while (I-- > 0) {
++ retval = u132_read_pcimem(u132, roothub.portstatus[i],
++ &u132->hc_roothub_portstatus[i]);
++ if (retval) {
++ dev_err(&u132->platform_dev->dev, "error %d acc"
++ "essing device roothub.portstatus[%d]\n"
++ , retval, i);
++ return retval;
++ } else
++ i += 1;
++ }
++ }
++ return 0;
+ }
+
+ static void u132_hcd_monitor_work(struct work_struct *work)
+ {
+- struct u132 *u132 = container_of(work, struct u132, monitor.work);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- u132_monitor_put_kref(u132);
+- return;
+- } else if (u132->going > 0) {
+- dev_err(&u132->platform_dev->dev, "device is being removed\n");
+- u132_monitor_put_kref(u132);
+- return;
+- } else {
+- int retval;
+- mutex_lock(&u132->sw_lock);
+- retval = read_roothub_info(u132);
+- if (retval) {
+- struct usb_hcd *hcd = u132_to_hcd(u132);
+- u132_disable(u132);
+- u132->going = 1;
+- mutex_unlock(&u132->sw_lock);
+- usb_hc_died(hcd);
+- ftdi_elan_gone_away(u132->platform_dev);
+- u132_monitor_put_kref(u132);
+- return;
+- } else {
+- u132_monitor_requeue_work(u132, 500);
+- mutex_unlock(&u132->sw_lock);
+- return;
+- }
+- }
++ struct u132 *u132 = container_of(work, struct u132, monitor.work);
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++ , u132->going);
++ u132_monitor_put_kref(u132);
++ return;
++ } else if (u132->going > 0) {
++ dev_err(&u132->platform_dev->dev, "device is being removed\n");
++ u132_monitor_put_kref(u132);
++ return;
++ } else {
++ int retval;
++ mutex_lock(&u132->sw_lock);
++ retval = read_roothub_info(u132);
++ if (retval) {
++ struct usb_hcd *hcd = u132_to_hcd(u132);
++ u132_disable(u132);
++ u132->going = 1;
++ mutex_unlock(&u132->sw_lock);
++ usb_hc_died(hcd);
++ ftdi_elan_gone_away(u132->platform_dev);
++ u132_monitor_put_kref(u132);
++ return;
++ } else {
++ u132_monitor_requeue_work(u132, 500);
++ mutex_unlock(&u132->sw_lock);
++ return;
++ }
++ }
+ }
+
+ static void u132_hcd_giveback_urb(struct u132 *u132, struct u132_endp *endp,
+- struct urb *urb, int status)
++ struct urb *urb, int status)
+ {
+- struct u132_ring *ring;
+- unsigned long irqs;
+- struct usb_hcd *hcd = u132_to_hcd(u132);
+- urb->error_count = 0;
+- spin_lock_irqsave(&endp->queue_lock.slock, irqs);
++ struct u132_ring *ring;
++ unsigned long irqs;
++ struct usb_hcd *hcd = u132_to_hcd(u132);
++ urb->error_count = 0;
++ spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+ usb_hcd_unlink_urb_from_ep(hcd, urb);
+- endp->queue_next += 1;
+- if (ENDP_QUEUE_SIZE > --endp->queue_size) {
+- endp->active = 0;
+- spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+- } else {
+- struct list_head *next = endp->urb_more.next;
+- struct u132_urbq *urbq = list_entry(next, struct u132_urbq,
+- urb_more);
+- list_del(next);
+- endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
+- urbq->urb;
+- endp->active = 0;
+- spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+- kfree(urbq);
+- } down(&u132->scheduler_lock);
+- ring = endp->ring;
+- ring->in_use = 0;
+- u132_ring_cancel_work(u132, ring);
+- u132_ring_queue_work(u132, ring, 0);
+- up(&u132->scheduler_lock);
+- u132_endp_put_kref(u132, endp);
++ endp->queue_next += 1;
++ if (ENDP_QUEUE_SIZE > --endp->queue_size) {
++ endp->active = 0;
++ spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++ } else {
++ struct list_head *next = endp->urb_more.next;
++ struct u132_urbq *urbq = list_entry(next, struct u132_urbq,
++ urb_more);
++ list_del(next);
++ endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
++ urbq->urb;
++ endp->active = 0;
++ spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++ kfree(urbq);
++ }
++ mutex_lock(&u132->scheduler_lock);
++ ring = endp->ring;
++ ring->in_use = 0;
++ u132_ring_cancel_work(u132, ring);
++ u132_ring_queue_work(u132, ring, 0);
++ mutex_unlock(&u132->scheduler_lock);
++ u132_endp_put_kref(u132, endp);
+ usb_hcd_giveback_urb(hcd, urb, status);
+- return;
++ return;
+ }
+
+ static void u132_hcd_forget_urb(struct u132 *u132, struct u132_endp *endp,
+- struct urb *urb, int status)
++ struct urb *urb, int status)
+ {
+- u132_endp_put_kref(u132, endp);
++ u132_endp_put_kref(u132, endp);
+ }
+
+ static void u132_hcd_abandon_urb(struct u132 *u132, struct u132_endp *endp,
+- struct urb *urb, int status)
++ struct urb *urb, int status)
+ {
+- unsigned long irqs;
+- struct usb_hcd *hcd = u132_to_hcd(u132);
+- urb->error_count = 0;
+- spin_lock_irqsave(&endp->queue_lock.slock, irqs);
++ unsigned long irqs;
++ struct usb_hcd *hcd = u132_to_hcd(u132);
++ urb->error_count = 0;
++ spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+ usb_hcd_unlink_urb_from_ep(hcd, urb);
+- endp->queue_next += 1;
+- if (ENDP_QUEUE_SIZE > --endp->queue_size) {
+- endp->active = 0;
+- spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+- } else {
+- struct list_head *next = endp->urb_more.next;
+- struct u132_urbq *urbq = list_entry(next, struct u132_urbq,
+- urb_more);
+- list_del(next);
+- endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
+- urbq->urb;
+- endp->active = 0;
+- spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+- kfree(urbq);
++ endp->queue_next += 1;
++ if (ENDP_QUEUE_SIZE > --endp->queue_size) {
++ endp->active = 0;
++ spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++ } else {
++ struct list_head *next = endp->urb_more.next;
++ struct u132_urbq *urbq = list_entry(next, struct u132_urbq,
++ urb_more);
++ list_del(next);
++ endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
++ urbq->urb;
++ endp->active = 0;
++ spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++ kfree(urbq);
+ } usb_hcd_giveback_urb(hcd, urb, status);
+- return;
++ return;
+ }
+
+ static inline int edset_input(struct u132 *u132, struct u132_ring *ring,
+- struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
+- void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+- int toggle_bits, int error_count, int condition_code, int repeat_number,
+- int halted, int skipped, int actual, int non_null))
++ struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
++ void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
++ int toggle_bits, int error_count, int condition_code, int repeat_number,
++ int halted, int skipped, int actual, int non_null))
+ {
+- return usb_ftdi_elan_edset_input(u132->platform_dev, ring->number, endp,
+- urb, address, endp->usb_endp, toggle_bits, callback);
++ return usb_ftdi_elan_edset_input(u132->platform_dev, ring->number, endp,
++ urb, address, endp->usb_endp, toggle_bits, callback);
+ }
+
+ static inline int edset_setup(struct u132 *u132, struct u132_ring *ring,
+- struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
+- void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+- int toggle_bits, int error_count, int condition_code, int repeat_number,
+- int halted, int skipped, int actual, int non_null))
++ struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
++ void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
++ int toggle_bits, int error_count, int condition_code, int repeat_number,
++ int halted, int skipped, int actual, int non_null))
+ {
+- return usb_ftdi_elan_edset_setup(u132->platform_dev, ring->number, endp,
+- urb, address, endp->usb_endp, toggle_bits, callback);
++ return usb_ftdi_elan_edset_setup(u132->platform_dev, ring->number, endp,
++ urb, address, endp->usb_endp, toggle_bits, callback);
+ }
+
+ static inline int edset_single(struct u132 *u132, struct u132_ring *ring,
+- struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
+- void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+- int toggle_bits, int error_count, int condition_code, int repeat_number,
+- int halted, int skipped, int actual, int non_null))
++ struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
++ void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
++ int toggle_bits, int error_count, int condition_code, int repeat_number,
++ int halted, int skipped, int actual, int non_null))
+ {
+- return usb_ftdi_elan_edset_single(u132->platform_dev, ring->number,
+- endp, urb, address, endp->usb_endp, toggle_bits, callback);
++ return usb_ftdi_elan_edset_single(u132->platform_dev, ring->number,
++ endp, urb, address, endp->usb_endp, toggle_bits, callback);
+ }
+
+ static inline int edset_output(struct u132 *u132, struct u132_ring *ring,
+- struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
+- void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+- int toggle_bits, int error_count, int condition_code, int repeat_number,
+- int halted, int skipped, int actual, int non_null))
++ struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
++ void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
++ int toggle_bits, int error_count, int condition_code, int repeat_number,
++ int halted, int skipped, int actual, int non_null))
+ {
+- return usb_ftdi_elan_edset_output(u132->platform_dev, ring->number,
+- endp, urb, address, endp->usb_endp, toggle_bits, callback);
++ return usb_ftdi_elan_edset_output(u132->platform_dev, ring->number,
++ endp, urb, address, endp->usb_endp, toggle_bits, callback);
+ }
+
+
+@@ -623,683 +624,678 @@ static inline int edset_output(struct u132 *u132, struct u132_ring *ring,
+ *
+ */
+ static void u132_hcd_interrupt_recv(void *data, struct urb *urb, u8 *buf,
+- int len, int toggle_bits, int error_count, int condition_code,
+- int repeat_number, int halted, int skipped, int actual, int non_null)
+-{
+- struct u132_endp *endp = data;
+- struct u132 *u132 = endp->u132;
+- u8 address = u132->addr[endp->usb_addr].address;
+- struct u132_udev *udev = &u132->udev[address];
+- down(&u132->scheduler_lock);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- up(&u132->scheduler_lock);
+- u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+- return;
+- } else if (endp->dequeueing) {
+- endp->dequeueing = 0;
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+- return;
+- } else if (u132->going > 0) {
++ int len, int toggle_bits, int error_count, int condition_code,
++ int repeat_number, int halted, int skipped, int actual, int non_null)
++{
++ struct u132_endp *endp = data;
++ struct u132 *u132 = endp->u132;
++ u8 address = u132->addr[endp->usb_addr].address;
++ struct u132_udev *udev = &u132->udev[address];
++ mutex_lock(&u132->scheduler_lock);
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++ , u132->going);
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
++ return;
++ } else if (endp->dequeueing) {
++ endp->dequeueing = 0;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
++ return;
++ } else if (u132->going > 0) {
+ dev_err(&u132->platform_dev->dev, "device is being removed "
+ "urb=%p\n", urb);
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+- return;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
++ return;
+ } else if (!urb->unlinked) {
+- struct u132_ring *ring = endp->ring;
+- u8 *u = urb->transfer_buffer + urb->actual_length;
+- u8 *b = buf;
+- int L = len;
+- while (L-- > 0) {
+- *u++ = *b++;
+- }
+- urb->actual_length += len;
+- if ((condition_code == TD_CC_NOERROR) &&
+- (urb->transfer_buffer_length > urb->actual_length)) {
+- endp->toggle_bits = toggle_bits;
+- usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+- 1 & toggle_bits);
+- if (urb->actual_length > 0) {
+- int retval;
+- up(&u132->scheduler_lock);
+- retval = edset_single(u132, ring, endp, urb,
+- address, endp->toggle_bits,
+- u132_hcd_interrupt_recv);
+- if (retval == 0) {
+- } else
+- u132_hcd_giveback_urb(u132, endp, urb,
+- retval);
+- } else {
+- ring->in_use = 0;
+- endp->active = 0;
+- endp->jiffies = jiffies +
+- msecs_to_jiffies(urb->interval);
+- u132_ring_cancel_work(u132, ring);
+- u132_ring_queue_work(u132, ring, 0);
+- up(&u132->scheduler_lock);
+- u132_endp_put_kref(u132, endp);
+- }
+- return;
+- } else if ((condition_code == TD_DATAUNDERRUN) &&
+- ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) {
+- endp->toggle_bits = toggle_bits;
+- usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+- 1 & toggle_bits);
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, 0);
+- return;
+- } else {
+- if (condition_code == TD_CC_NOERROR) {
+- endp->toggle_bits = toggle_bits;
+- usb_settoggle(udev->usb_device, endp->usb_endp,
+- 0, 1 & toggle_bits);
+- } else if (condition_code == TD_CC_STALL) {
+- endp->toggle_bits = 0x2;
+- usb_settoggle(udev->usb_device, endp->usb_endp,
+- 0, 0);
+- } else {
+- endp->toggle_bits = 0x2;
+- usb_settoggle(udev->usb_device, endp->usb_endp,
+- 0, 0);
+- dev_err(&u132->platform_dev->dev, "urb=%p givin"
+- "g back INTERRUPT %s\n", urb,
+- cc_to_text[condition_code]);
+- }
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb,
+- cc_to_error[condition_code]);
+- return;
+- }
+- } else {
++ struct u132_ring *ring = endp->ring;
++ u8 *u = urb->transfer_buffer + urb->actual_length;
++ u8 *b = buf;
++ int L = len;
++
++ while (L-- > 0)
++ *u++ = *b++;
++
++ urb->actual_length += len;
++ if ((condition_code == TD_CC_NOERROR) &&
++ (urb->transfer_buffer_length > urb->actual_length)) {
++ endp->toggle_bits = toggle_bits;
++ usb_settoggle(udev->usb_device, endp->usb_endp, 0,
++ 1 & toggle_bits);
++ if (urb->actual_length > 0) {
++ int retval;
++ mutex_unlock(&u132->scheduler_lock);
++ retval = edset_single(u132, ring, endp, urb,
++ address, endp->toggle_bits,
++ u132_hcd_interrupt_recv);
++ if (retval != 0)
++ u132_hcd_giveback_urb(u132, endp, urb,
++ retval);
++ } else {
++ ring->in_use = 0;
++ endp->active = 0;
++ endp->jiffies = jiffies +
++ msecs_to_jiffies(urb->interval);
++ u132_ring_cancel_work(u132, ring);
++ u132_ring_queue_work(u132, ring, 0);
++ mutex_unlock(&u132->scheduler_lock);
++ u132_endp_put_kref(u132, endp);
++ }
++ return;
++ } else if ((condition_code == TD_DATAUNDERRUN) &&
++ ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) {
++ endp->toggle_bits = toggle_bits;
++ usb_settoggle(udev->usb_device, endp->usb_endp, 0,
++ 1 & toggle_bits);
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, 0);
++ return;
++ } else {
++ if (condition_code == TD_CC_NOERROR) {
++ endp->toggle_bits = toggle_bits;
++ usb_settoggle(udev->usb_device, endp->usb_endp,
++ 0, 1 & toggle_bits);
++ } else if (condition_code == TD_CC_STALL) {
++ endp->toggle_bits = 0x2;
++ usb_settoggle(udev->usb_device, endp->usb_endp,
++ 0, 0);
++ } else {
++ endp->toggle_bits = 0x2;
++ usb_settoggle(udev->usb_device, endp->usb_endp,
++ 0, 0);
++ dev_err(&u132->platform_dev->dev, "urb=%p givin"
++ "g back INTERRUPT %s\n", urb,
++ cc_to_text[condition_code]);
++ }
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb,
++ cc_to_error[condition_code]);
++ return;
++ }
++ } else {
+ dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ "unlinked=%d\n", urb, urb->unlinked);
+- up(&u132->scheduler_lock);
++ mutex_unlock(&u132->scheduler_lock);
+ u132_hcd_giveback_urb(u132, endp, urb, 0);
+- return;
+- }
++ return;
++ }
+ }
+
+ static void u132_hcd_bulk_output_sent(void *data, struct urb *urb, u8 *buf,
+- int len, int toggle_bits, int error_count, int condition_code,
+- int repeat_number, int halted, int skipped, int actual, int non_null)
+-{
+- struct u132_endp *endp = data;
+- struct u132 *u132 = endp->u132;
+- u8 address = u132->addr[endp->usb_addr].address;
+- down(&u132->scheduler_lock);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- up(&u132->scheduler_lock);
+- u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+- return;
+- } else if (endp->dequeueing) {
+- endp->dequeueing = 0;
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+- return;
+- } else if (u132->going > 0) {
++ int len, int toggle_bits, int error_count, int condition_code,
++ int repeat_number, int halted, int skipped, int actual, int non_null)
++{
++ struct u132_endp *endp = data;
++ struct u132 *u132 = endp->u132;
++ u8 address = u132->addr[endp->usb_addr].address;
++ mutex_lock(&u132->scheduler_lock);
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++ , u132->going);
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
++ return;
++ } else if (endp->dequeueing) {
++ endp->dequeueing = 0;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
++ return;
++ } else if (u132->going > 0) {
+ dev_err(&u132->platform_dev->dev, "device is being removed "
+ "urb=%p\n", urb);
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+- return;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
++ return;
+ } else if (!urb->unlinked) {
+- struct u132_ring *ring = endp->ring;
+- urb->actual_length += len;
+- endp->toggle_bits = toggle_bits;
+- if (urb->transfer_buffer_length > urb->actual_length) {
+- int retval;
+- up(&u132->scheduler_lock);
+- retval = edset_output(u132, ring, endp, urb, address,
+- endp->toggle_bits, u132_hcd_bulk_output_sent);
+- if (retval == 0) {
+- } else
+- u132_hcd_giveback_urb(u132, endp, urb, retval);
+- return;
+- } else {
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, 0);
+- return;
+- }
+- } else {
++ struct u132_ring *ring = endp->ring;
++ urb->actual_length += len;
++ endp->toggle_bits = toggle_bits;
++ if (urb->transfer_buffer_length > urb->actual_length) {
++ int retval;
++ mutex_unlock(&u132->scheduler_lock);
++ retval = edset_output(u132, ring, endp, urb, address,
++ endp->toggle_bits, u132_hcd_bulk_output_sent);
++ if (retval != 0)
++ u132_hcd_giveback_urb(u132, endp, urb, retval);
++ return;
++ } else {
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, 0);
++ return;
++ }
++ } else {
+ dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ "unlinked=%d\n", urb, urb->unlinked);
+- up(&u132->scheduler_lock);
++ mutex_unlock(&u132->scheduler_lock);
+ u132_hcd_giveback_urb(u132, endp, urb, 0);
+- return;
+- }
++ return;
++ }
+ }
+
+ static void u132_hcd_bulk_input_recv(void *data, struct urb *urb, u8 *buf,
+- int len, int toggle_bits, int error_count, int condition_code,
+- int repeat_number, int halted, int skipped, int actual, int non_null)
+-{
+- struct u132_endp *endp = data;
+- struct u132 *u132 = endp->u132;
+- u8 address = u132->addr[endp->usb_addr].address;
+- struct u132_udev *udev = &u132->udev[address];
+- down(&u132->scheduler_lock);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- up(&u132->scheduler_lock);
+- u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+- return;
+- } else if (endp->dequeueing) {
+- endp->dequeueing = 0;
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+- return;
+- } else if (u132->going > 0) {
++ int len, int toggle_bits, int error_count, int condition_code,
++ int repeat_number, int halted, int skipped, int actual, int non_null)
++{
++ struct u132_endp *endp = data;
++ struct u132 *u132 = endp->u132;
++ u8 address = u132->addr[endp->usb_addr].address;
++ struct u132_udev *udev = &u132->udev[address];
++ mutex_lock(&u132->scheduler_lock);
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++ , u132->going);
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
++ return;
++ } else if (endp->dequeueing) {
++ endp->dequeueing = 0;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
++ return;
++ } else if (u132->going > 0) {
+ dev_err(&u132->platform_dev->dev, "device is being removed "
+ "urb=%p\n", urb);
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+- return;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
++ return;
+ } else if (!urb->unlinked) {
+- struct u132_ring *ring = endp->ring;
+- u8 *u = urb->transfer_buffer + urb->actual_length;
+- u8 *b = buf;
+- int L = len;
+- while (L-- > 0) {
+- *u++ = *b++;
+- }
+- urb->actual_length += len;
+- if ((condition_code == TD_CC_NOERROR) &&
+- (urb->transfer_buffer_length > urb->actual_length)) {
+- int retval;
+- endp->toggle_bits = toggle_bits;
+- usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+- 1 & toggle_bits);
+- up(&u132->scheduler_lock);
+- retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+- ring->number, endp, urb, address,
+- endp->usb_endp, endp->toggle_bits,
+- u132_hcd_bulk_input_recv);
+- if (retval == 0) {
+- } else
+- u132_hcd_giveback_urb(u132, endp, urb, retval);
+- return;
+- } else if (condition_code == TD_CC_NOERROR) {
+- endp->toggle_bits = toggle_bits;
+- usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+- 1 & toggle_bits);
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb,
+- cc_to_error[condition_code]);
+- return;
+- } else if ((condition_code == TD_DATAUNDERRUN) &&
+- ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) {
+- endp->toggle_bits = toggle_bits;
+- usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+- 1 & toggle_bits);
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, 0);
+- return;
+- } else if (condition_code == TD_DATAUNDERRUN) {
+- endp->toggle_bits = toggle_bits;
+- usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+- 1 & toggle_bits);
+- dev_warn(&u132->platform_dev->dev, "urb=%p(SHORT NOT OK"
+- ") giving back BULK IN %s\n", urb,
+- cc_to_text[condition_code]);
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, 0);
+- return;
+- } else if (condition_code == TD_CC_STALL) {
+- endp->toggle_bits = 0x2;
+- usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0);
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb,
+- cc_to_error[condition_code]);
+- return;
+- } else {
+- endp->toggle_bits = 0x2;
+- usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0);
+- dev_err(&u132->platform_dev->dev, "urb=%p giving back B"
+- "ULK IN code=%d %s\n", urb, condition_code,
+- cc_to_text[condition_code]);
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb,
+- cc_to_error[condition_code]);
+- return;
+- }
+- } else {
++ struct u132_ring *ring = endp->ring;
++ u8 *u = urb->transfer_buffer + urb->actual_length;
++ u8 *b = buf;
++ int L = len;
++
++ while (L-- > 0)
++ *u++ = *b++;
++
++ urb->actual_length += len;
++ if ((condition_code == TD_CC_NOERROR) &&
++ (urb->transfer_buffer_length > urb->actual_length)) {
++ int retval;
++ endp->toggle_bits = toggle_bits;
++ usb_settoggle(udev->usb_device, endp->usb_endp, 0,
++ 1 & toggle_bits);
++ mutex_unlock(&u132->scheduler_lock);
++ retval = usb_ftdi_elan_edset_input(u132->platform_dev,
++ ring->number, endp, urb, address,
++ endp->usb_endp, endp->toggle_bits,
++ u132_hcd_bulk_input_recv);
++ if (retval != 0)
++ u132_hcd_giveback_urb(u132, endp, urb, retval);
++ return;
++ } else if (condition_code == TD_CC_NOERROR) {
++ endp->toggle_bits = toggle_bits;
++ usb_settoggle(udev->usb_device, endp->usb_endp, 0,
++ 1 & toggle_bits);
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb,
++ cc_to_error[condition_code]);
++ return;
++ } else if ((condition_code == TD_DATAUNDERRUN) &&
++ ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) {
++ endp->toggle_bits = toggle_bits;
++ usb_settoggle(udev->usb_device, endp->usb_endp, 0,
++ 1 & toggle_bits);
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, 0);
++ return;
++ } else if (condition_code == TD_DATAUNDERRUN) {
++ endp->toggle_bits = toggle_bits;
++ usb_settoggle(udev->usb_device, endp->usb_endp, 0,
++ 1 & toggle_bits);
++ dev_warn(&u132->platform_dev->dev, "urb=%p(SHORT NOT OK"
++ ") giving back BULK IN %s\n", urb,
++ cc_to_text[condition_code]);
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, 0);
++ return;
++ } else if (condition_code == TD_CC_STALL) {
++ endp->toggle_bits = 0x2;
++ usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0);
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb,
++ cc_to_error[condition_code]);
++ return;
++ } else {
++ endp->toggle_bits = 0x2;
++ usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0);
++ dev_err(&u132->platform_dev->dev, "urb=%p giving back B"
++ "ULK IN code=%d %s\n", urb, condition_code,
++ cc_to_text[condition_code]);
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb,
++ cc_to_error[condition_code]);
++ return;
++ }
++ } else {
+ dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ "unlinked=%d\n", urb, urb->unlinked);
+- up(&u132->scheduler_lock);
++ mutex_unlock(&u132->scheduler_lock);
+ u132_hcd_giveback_urb(u132, endp, urb, 0);
+- return;
+- }
++ return;
++ }
+ }
+
+ static void u132_hcd_configure_empty_sent(void *data, struct urb *urb, u8 *buf,
+- int len, int toggle_bits, int error_count, int condition_code,
+- int repeat_number, int halted, int skipped, int actual, int non_null)
+-{
+- struct u132_endp *endp = data;
+- struct u132 *u132 = endp->u132;
+- down(&u132->scheduler_lock);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- up(&u132->scheduler_lock);
+- u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+- return;
+- } else if (endp->dequeueing) {
+- endp->dequeueing = 0;
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+- return;
+- } else if (u132->going > 0) {
++ int len, int toggle_bits, int error_count, int condition_code,
++ int repeat_number, int halted, int skipped, int actual, int non_null)
++{
++ struct u132_endp *endp = data;
++ struct u132 *u132 = endp->u132;
++ mutex_lock(&u132->scheduler_lock);
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++ , u132->going);
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
++ return;
++ } else if (endp->dequeueing) {
++ endp->dequeueing = 0;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
++ return;
++ } else if (u132->going > 0) {
+ dev_err(&u132->platform_dev->dev, "device is being removed "
+ "urb=%p\n", urb);
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+- return;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
++ return;
+ } else if (!urb->unlinked) {
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, 0);
+- return;
+- } else {
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, 0);
++ return;
++ } else {
+ dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ "unlinked=%d\n", urb, urb->unlinked);
+- up(&u132->scheduler_lock);
++ mutex_unlock(&u132->scheduler_lock);
+ u132_hcd_giveback_urb(u132, endp, urb, 0);
+- return;
+- }
++ return;
++ }
+ }
+
+ static void u132_hcd_configure_input_recv(void *data, struct urb *urb, u8 *buf,
+- int len, int toggle_bits, int error_count, int condition_code,
+- int repeat_number, int halted, int skipped, int actual, int non_null)
+-{
+- struct u132_endp *endp = data;
+- struct u132 *u132 = endp->u132;
+- u8 address = u132->addr[endp->usb_addr].address;
+- down(&u132->scheduler_lock);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- up(&u132->scheduler_lock);
+- u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+- return;
+- } else if (endp->dequeueing) {
+- endp->dequeueing = 0;
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+- return;
+- } else if (u132->going > 0) {
++ int len, int toggle_bits, int error_count, int condition_code,
++ int repeat_number, int halted, int skipped, int actual, int non_null)
++{
++ struct u132_endp *endp = data;
++ struct u132 *u132 = endp->u132;
++ u8 address = u132->addr[endp->usb_addr].address;
++ mutex_lock(&u132->scheduler_lock);
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++ , u132->going);
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
++ return;
++ } else if (endp->dequeueing) {
++ endp->dequeueing = 0;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
++ return;
++ } else if (u132->going > 0) {
+ dev_err(&u132->platform_dev->dev, "device is being removed "
+ "urb=%p\n", urb);
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+- return;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
++ return;
+ } else if (!urb->unlinked) {
+- struct u132_ring *ring = endp->ring;
+- u8 *u = urb->transfer_buffer;
+- u8 *b = buf;
+- int L = len;
+- while (L-- > 0) {
+- *u++ = *b++;
+- }
+- urb->actual_length = len;
+- if ((condition_code == TD_CC_NOERROR) || ((condition_code ==
+- TD_DATAUNDERRUN) && ((urb->transfer_flags &
+- URB_SHORT_NOT_OK) == 0))) {
+- int retval;
+- up(&u132->scheduler_lock);
+- retval = usb_ftdi_elan_edset_empty(u132->platform_dev,
+- ring->number, endp, urb, address,
+- endp->usb_endp, 0x3,
+- u132_hcd_configure_empty_sent);
+- if (retval == 0) {
+- } else
+- u132_hcd_giveback_urb(u132, endp, urb, retval);
+- return;
+- } else if (condition_code == TD_CC_STALL) {
+- up(&u132->scheduler_lock);
+- dev_warn(&u132->platform_dev->dev, "giving back SETUP I"
+- "NPUT STALL urb %p\n", urb);
+- u132_hcd_giveback_urb(u132, endp, urb,
+- cc_to_error[condition_code]);
+- return;
+- } else {
+- up(&u132->scheduler_lock);
+- dev_err(&u132->platform_dev->dev, "giving back SETUP IN"
+- "PUT %s urb %p\n", cc_to_text[condition_code],
+- urb);
+- u132_hcd_giveback_urb(u132, endp, urb,
+- cc_to_error[condition_code]);
+- return;
+- }
+- } else {
++ struct u132_ring *ring = endp->ring;
++ u8 *u = urb->transfer_buffer;
++ u8 *b = buf;
++ int L = len;
++
++ while (L-- > 0)
++ *u++ = *b++;
++
++ urb->actual_length = len;
++ if ((condition_code == TD_CC_NOERROR) || ((condition_code ==
++ TD_DATAUNDERRUN) && ((urb->transfer_flags &
++ URB_SHORT_NOT_OK) == 0))) {
++ int retval;
++ mutex_unlock(&u132->scheduler_lock);
++ retval = usb_ftdi_elan_edset_empty(u132->platform_dev,
++ ring->number, endp, urb, address,
++ endp->usb_endp, 0x3,
++ u132_hcd_configure_empty_sent);
++ if (retval != 0)
++ u132_hcd_giveback_urb(u132, endp, urb, retval);
++ return;
++ } else if (condition_code == TD_CC_STALL) {
++ mutex_unlock(&u132->scheduler_lock);
++ dev_warn(&u132->platform_dev->dev, "giving back SETUP I"
++ "NPUT STALL urb %p\n", urb);
++ u132_hcd_giveback_urb(u132, endp, urb,
++ cc_to_error[condition_code]);
++ return;
++ } else {
++ mutex_unlock(&u132->scheduler_lock);
++ dev_err(&u132->platform_dev->dev, "giving back SETUP IN"
++ "PUT %s urb %p\n", cc_to_text[condition_code],
++ urb);
++ u132_hcd_giveback_urb(u132, endp, urb,
++ cc_to_error[condition_code]);
++ return;
++ }
++ } else {
+ dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ "unlinked=%d\n", urb, urb->unlinked);
+- up(&u132->scheduler_lock);
++ mutex_unlock(&u132->scheduler_lock);
+ u132_hcd_giveback_urb(u132, endp, urb, 0);
+- return;
+- }
++ return;
++ }
+ }
+
+ static void u132_hcd_configure_empty_recv(void *data, struct urb *urb, u8 *buf,
+- int len, int toggle_bits, int error_count, int condition_code,
+- int repeat_number, int halted, int skipped, int actual, int non_null)
+-{
+- struct u132_endp *endp = data;
+- struct u132 *u132 = endp->u132;
+- down(&u132->scheduler_lock);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- up(&u132->scheduler_lock);
+- u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+- return;
+- } else if (endp->dequeueing) {
+- endp->dequeueing = 0;
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+- return;
+- } else if (u132->going > 0) {
++ int len, int toggle_bits, int error_count, int condition_code,
++ int repeat_number, int halted, int skipped, int actual, int non_null)
++{
++ struct u132_endp *endp = data;
++ struct u132 *u132 = endp->u132;
++ mutex_lock(&u132->scheduler_lock);
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++ , u132->going);
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
++ return;
++ } else if (endp->dequeueing) {
++ endp->dequeueing = 0;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
++ return;
++ } else if (u132->going > 0) {
+ dev_err(&u132->platform_dev->dev, "device is being removed "
+ "urb=%p\n", urb);
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+- return;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
++ return;
+ } else if (!urb->unlinked) {
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, 0);
+- return;
+- } else {
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, 0);
++ return;
++ } else {
+ dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ "unlinked=%d\n", urb, urb->unlinked);
+- up(&u132->scheduler_lock);
++ mutex_unlock(&u132->scheduler_lock);
+ u132_hcd_giveback_urb(u132, endp, urb, 0);
+- return;
+- }
++ return;
++ }
+ }
+
+ static void u132_hcd_configure_setup_sent(void *data, struct urb *urb, u8 *buf,
+- int len, int toggle_bits, int error_count, int condition_code,
+- int repeat_number, int halted, int skipped, int actual, int non_null)
+-{
+- struct u132_endp *endp = data;
+- struct u132 *u132 = endp->u132;
+- u8 address = u132->addr[endp->usb_addr].address;
+- down(&u132->scheduler_lock);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- up(&u132->scheduler_lock);
+- u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+- return;
+- } else if (endp->dequeueing) {
+- endp->dequeueing = 0;
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+- return;
+- } else if (u132->going > 0) {
++ int len, int toggle_bits, int error_count, int condition_code,
++ int repeat_number, int halted, int skipped, int actual, int non_null)
++{
++ struct u132_endp *endp = data;
++ struct u132 *u132 = endp->u132;
++ u8 address = u132->addr[endp->usb_addr].address;
++ mutex_lock(&u132->scheduler_lock);
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++ , u132->going);
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
++ return;
++ } else if (endp->dequeueing) {
++ endp->dequeueing = 0;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
++ return;
++ } else if (u132->going > 0) {
+ dev_err(&u132->platform_dev->dev, "device is being removed "
+ "urb=%p\n", urb);
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+- return;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
++ return;
+ } else if (!urb->unlinked) {
+- if (usb_pipein(urb->pipe)) {
+- int retval;
+- struct u132_ring *ring = endp->ring;
+- up(&u132->scheduler_lock);
+- retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+- ring->number, endp, urb, address,
+- endp->usb_endp, 0,
+- u132_hcd_configure_input_recv);
+- if (retval == 0) {
+- } else
+- u132_hcd_giveback_urb(u132, endp, urb, retval);
+- return;
+- } else {
+- int retval;
+- struct u132_ring *ring = endp->ring;
+- up(&u132->scheduler_lock);
+- retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+- ring->number, endp, urb, address,
+- endp->usb_endp, 0,
+- u132_hcd_configure_empty_recv);
+- if (retval == 0) {
+- } else
+- u132_hcd_giveback_urb(u132, endp, urb, retval);
+- return;
+- }
+- } else {
++ if (usb_pipein(urb->pipe)) {
++ int retval;
++ struct u132_ring *ring = endp->ring;
++ mutex_unlock(&u132->scheduler_lock);
++ retval = usb_ftdi_elan_edset_input(u132->platform_dev,
++ ring->number, endp, urb, address,
++ endp->usb_endp, 0,
++ u132_hcd_configure_input_recv);
++ if (retval != 0)
++ u132_hcd_giveback_urb(u132, endp, urb, retval);
++ return;
++ } else {
++ int retval;
++ struct u132_ring *ring = endp->ring;
++ mutex_unlock(&u132->scheduler_lock);
++ retval = usb_ftdi_elan_edset_input(u132->platform_dev,
++ ring->number, endp, urb, address,
++ endp->usb_endp, 0,
++ u132_hcd_configure_empty_recv);
++ if (retval != 0)
++ u132_hcd_giveback_urb(u132, endp, urb, retval);
++ return;
++ }
++ } else {
+ dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ "unlinked=%d\n", urb, urb->unlinked);
+- up(&u132->scheduler_lock);
++ mutex_unlock(&u132->scheduler_lock);
+ u132_hcd_giveback_urb(u132, endp, urb, 0);
+- return;
+- }
++ return;
++ }
+ }
+
+ static void u132_hcd_enumeration_empty_recv(void *data, struct urb *urb,
+- u8 *buf, int len, int toggle_bits, int error_count, int condition_code,
+- int repeat_number, int halted, int skipped, int actual, int non_null)
+-{
+- struct u132_endp *endp = data;
+- struct u132 *u132 = endp->u132;
+- u8 address = u132->addr[endp->usb_addr].address;
+- struct u132_udev *udev = &u132->udev[address];
+- down(&u132->scheduler_lock);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- up(&u132->scheduler_lock);
+- u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+- return;
+- } else if (endp->dequeueing) {
+- endp->dequeueing = 0;
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+- return;
+- } else if (u132->going > 0) {
++ u8 *buf, int len, int toggle_bits, int error_count, int condition_code,
++ int repeat_number, int halted, int skipped, int actual, int non_null)
++{
++ struct u132_endp *endp = data;
++ struct u132 *u132 = endp->u132;
++ u8 address = u132->addr[endp->usb_addr].address;
++ struct u132_udev *udev = &u132->udev[address];
++ mutex_lock(&u132->scheduler_lock);
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++ , u132->going);
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
++ return;
++ } else if (endp->dequeueing) {
++ endp->dequeueing = 0;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
++ return;
++ } else if (u132->going > 0) {
+ dev_err(&u132->platform_dev->dev, "device is being removed "
+ "urb=%p\n", urb);
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+- return;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
++ return;
+ } else if (!urb->unlinked) {
+- u132->addr[0].address = 0;
+- endp->usb_addr = udev->usb_addr;
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, 0);
+- return;
+- } else {
++ u132->addr[0].address = 0;
++ endp->usb_addr = udev->usb_addr;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, 0);
++ return;
++ } else {
+ dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ "unlinked=%d\n", urb, urb->unlinked);
+- up(&u132->scheduler_lock);
++ mutex_unlock(&u132->scheduler_lock);
+ u132_hcd_giveback_urb(u132, endp, urb, 0);
+- return;
+- }
++ return;
++ }
+ }
+
+ static void u132_hcd_enumeration_address_sent(void *data, struct urb *urb,
+- u8 *buf, int len, int toggle_bits, int error_count, int condition_code,
+- int repeat_number, int halted, int skipped, int actual, int non_null)
+-{
+- struct u132_endp *endp = data;
+- struct u132 *u132 = endp->u132;
+- down(&u132->scheduler_lock);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- up(&u132->scheduler_lock);
+- u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+- return;
+- } else if (endp->dequeueing) {
+- endp->dequeueing = 0;
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+- return;
+- } else if (u132->going > 0) {
++ u8 *buf, int len, int toggle_bits, int error_count, int condition_code,
++ int repeat_number, int halted, int skipped, int actual, int non_null)
++{
++ struct u132_endp *endp = data;
++ struct u132 *u132 = endp->u132;
++ mutex_lock(&u132->scheduler_lock);
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++ , u132->going);
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
++ return;
++ } else if (endp->dequeueing) {
++ endp->dequeueing = 0;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
++ return;
++ } else if (u132->going > 0) {
+ dev_err(&u132->platform_dev->dev, "device is being removed "
+ "urb=%p\n", urb);
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+- return;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
++ return;
+ } else if (!urb->unlinked) {
+- int retval;
+- struct u132_ring *ring = endp->ring;
+- up(&u132->scheduler_lock);
+- retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+- ring->number, endp, urb, 0, endp->usb_endp, 0,
+- u132_hcd_enumeration_empty_recv);
+- if (retval == 0) {
+- } else
+- u132_hcd_giveback_urb(u132, endp, urb, retval);
+- return;
+- } else {
++ int retval;
++ struct u132_ring *ring = endp->ring;
++ mutex_unlock(&u132->scheduler_lock);
++ retval = usb_ftdi_elan_edset_input(u132->platform_dev,
++ ring->number, endp, urb, 0, endp->usb_endp, 0,
++ u132_hcd_enumeration_empty_recv);
++ if (retval != 0)
++ u132_hcd_giveback_urb(u132, endp, urb, retval);
++ return;
++ } else {
+ dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ "unlinked=%d\n", urb, urb->unlinked);
+- up(&u132->scheduler_lock);
++ mutex_unlock(&u132->scheduler_lock);
+ u132_hcd_giveback_urb(u132, endp, urb, 0);
+- return;
+- }
++ return;
++ }
+ }
+
+ static void u132_hcd_initial_empty_sent(void *data, struct urb *urb, u8 *buf,
+- int len, int toggle_bits, int error_count, int condition_code,
+- int repeat_number, int halted, int skipped, int actual, int non_null)
+-{
+- struct u132_endp *endp = data;
+- struct u132 *u132 = endp->u132;
+- down(&u132->scheduler_lock);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- up(&u132->scheduler_lock);
+- u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+- return;
+- } else if (endp->dequeueing) {
+- endp->dequeueing = 0;
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+- return;
+- } else if (u132->going > 0) {
++ int len, int toggle_bits, int error_count, int condition_code,
++ int repeat_number, int halted, int skipped, int actual, int non_null)
++{
++ struct u132_endp *endp = data;
++ struct u132 *u132 = endp->u132;
++ mutex_lock(&u132->scheduler_lock);
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++ , u132->going);
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
++ return;
++ } else if (endp->dequeueing) {
++ endp->dequeueing = 0;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
++ return;
++ } else if (u132->going > 0) {
+ dev_err(&u132->platform_dev->dev, "device is being removed "
+ "urb=%p\n", urb);
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+- return;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
++ return;
+ } else if (!urb->unlinked) {
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, 0);
+- return;
+- } else {
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, 0);
++ return;
++ } else {
+ dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ "unlinked=%d\n", urb, urb->unlinked);
+- up(&u132->scheduler_lock);
++ mutex_unlock(&u132->scheduler_lock);
+ u132_hcd_giveback_urb(u132, endp, urb, 0);
+- return;
+- }
++ return;
++ }
+ }
+
+ static void u132_hcd_initial_input_recv(void *data, struct urb *urb, u8 *buf,
+- int len, int toggle_bits, int error_count, int condition_code,
+- int repeat_number, int halted, int skipped, int actual, int non_null)
+-{
+- struct u132_endp *endp = data;
+- struct u132 *u132 = endp->u132;
+- u8 address = u132->addr[endp->usb_addr].address;
+- down(&u132->scheduler_lock);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- up(&u132->scheduler_lock);
+- u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+- return;
+- } else if (endp->dequeueing) {
+- endp->dequeueing = 0;
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+- return;
+- } else if (u132->going > 0) {
++ int len, int toggle_bits, int error_count, int condition_code,
++ int repeat_number, int halted, int skipped, int actual, int non_null)
++{
++ struct u132_endp *endp = data;
++ struct u132 *u132 = endp->u132;
++ u8 address = u132->addr[endp->usb_addr].address;
++ mutex_lock(&u132->scheduler_lock);
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++ , u132->going);
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
++ return;
++ } else if (endp->dequeueing) {
++ endp->dequeueing = 0;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
++ return;
++ } else if (u132->going > 0) {
+ dev_err(&u132->platform_dev->dev, "device is being removed "
+ "urb=%p\n", urb);
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+- return;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
++ return;
+ } else if (!urb->unlinked) {
+- int retval;
+- struct u132_ring *ring = endp->ring;
+- u8 *u = urb->transfer_buffer;
+- u8 *b = buf;
+- int L = len;
+- while (L-- > 0) {
+- *u++ = *b++;
+- }
+- urb->actual_length = len;
+- up(&u132->scheduler_lock);
+- retval = usb_ftdi_elan_edset_empty(u132->platform_dev,
+- ring->number, endp, urb, address, endp->usb_endp, 0x3,
+- u132_hcd_initial_empty_sent);
+- if (retval == 0) {
+- } else
+- u132_hcd_giveback_urb(u132, endp, urb, retval);
+- return;
+- } else {
++ int retval;
++ struct u132_ring *ring = endp->ring;
++ u8 *u = urb->transfer_buffer;
++ u8 *b = buf;
++ int L = len;
++
++ while (L-- > 0)
++ *u++ = *b++;
++
++ urb->actual_length = len;
++ mutex_unlock(&u132->scheduler_lock);
++ retval = usb_ftdi_elan_edset_empty(u132->platform_dev,
++ ring->number, endp, urb, address, endp->usb_endp, 0x3,
++ u132_hcd_initial_empty_sent);
++ if (retval != 0)
++ u132_hcd_giveback_urb(u132, endp, urb, retval);
++ return;
++ } else {
+ dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ "unlinked=%d\n", urb, urb->unlinked);
+- up(&u132->scheduler_lock);
++ mutex_unlock(&u132->scheduler_lock);
+ u132_hcd_giveback_urb(u132, endp, urb, 0);
+- return;
+- }
++ return;
++ }
+ }
+
+ static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf,
+- int len, int toggle_bits, int error_count, int condition_code,
+- int repeat_number, int halted, int skipped, int actual, int non_null)
+-{
+- struct u132_endp *endp = data;
+- struct u132 *u132 = endp->u132;
+- u8 address = u132->addr[endp->usb_addr].address;
+- down(&u132->scheduler_lock);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- up(&u132->scheduler_lock);
+- u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+- return;
+- } else if (endp->dequeueing) {
+- endp->dequeueing = 0;
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+- return;
+- } else if (u132->going > 0) {
++ int len, int toggle_bits, int error_count, int condition_code,
++ int repeat_number, int halted, int skipped, int actual, int non_null)
++{
++ struct u132_endp *endp = data;
++ struct u132 *u132 = endp->u132;
++ u8 address = u132->addr[endp->usb_addr].address;
++ mutex_lock(&u132->scheduler_lock);
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++ , u132->going);
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
++ return;
++ } else if (endp->dequeueing) {
++ endp->dequeueing = 0;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
++ return;
++ } else if (u132->going > 0) {
+ dev_err(&u132->platform_dev->dev, "device is being removed "
+ "urb=%p\n", urb);
+- up(&u132->scheduler_lock);
+- u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+- return;
++ mutex_unlock(&u132->scheduler_lock);
++ u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
++ return;
+ } else if (!urb->unlinked) {
+- int retval;
+- struct u132_ring *ring = endp->ring;
+- up(&u132->scheduler_lock);
+- retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+- ring->number, endp, urb, address, endp->usb_endp, 0,
+- u132_hcd_initial_input_recv);
+- if (retval == 0) {
+- } else
+- u132_hcd_giveback_urb(u132, endp, urb, retval);
+- return;
+- } else {
++ int retval;
++ struct u132_ring *ring = endp->ring;
++ mutex_unlock(&u132->scheduler_lock);
++ retval = usb_ftdi_elan_edset_input(u132->platform_dev,
++ ring->number, endp, urb, address, endp->usb_endp, 0,
++ u132_hcd_initial_input_recv);
++ if (retval != 0)
++ u132_hcd_giveback_urb(u132, endp, urb, retval);
++ return;
++ } else {
+ dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p "
+ "unlinked=%d\n", urb, urb->unlinked);
+- up(&u132->scheduler_lock);
++ mutex_unlock(&u132->scheduler_lock);
+ u132_hcd_giveback_urb(u132, endp, urb, 0);
+- return;
+- }
++ return;
++ }
+ }
+
+ /*
+@@ -1308,302 +1304,296 @@ static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf,
+ */
+ static void u132_hcd_ring_work_scheduler(struct work_struct *work)
+ {
+- struct u132_ring *ring =
++ struct u132_ring *ring =
+ container_of(work, struct u132_ring, scheduler.work);
+- struct u132 *u132 = ring->u132;
+- down(&u132->scheduler_lock);
+- if (ring->in_use) {
+- up(&u132->scheduler_lock);
+- u132_ring_put_kref(u132, ring);
+- return;
+- } else if (ring->curr_endp) {
+- struct u132_endp *last_endp = ring->curr_endp;
+- struct list_head *scan;
+- struct list_head *head = &last_endp->endp_ring;
+- unsigned long wakeup = 0;
+- list_for_each(scan, head) {
+- struct u132_endp *endp = list_entry(scan,
+- struct u132_endp, endp_ring);
+- if (endp->queue_next == endp->queue_last) {
+- } else if ((endp->delayed == 0)
+- || time_after_eq(jiffies, endp->jiffies)) {
+- ring->curr_endp = endp;
+- u132_endp_cancel_work(u132, last_endp);
+- u132_endp_queue_work(u132, last_endp, 0);
+- up(&u132->scheduler_lock);
+- u132_ring_put_kref(u132, ring);
+- return;
+- } else {
+- unsigned long delta = endp->jiffies - jiffies;
+- if (delta > wakeup)
+- wakeup = delta;
+- }
+- }
+- if (last_endp->queue_next == last_endp->queue_last) {
+- } else if ((last_endp->delayed == 0) || time_after_eq(jiffies,
+- last_endp->jiffies)) {
+- u132_endp_cancel_work(u132, last_endp);
+- u132_endp_queue_work(u132, last_endp, 0);
+- up(&u132->scheduler_lock);
+- u132_ring_put_kref(u132, ring);
+- return;
+- } else {
+- unsigned long delta = last_endp->jiffies - jiffies;
+- if (delta > wakeup)
+- wakeup = delta;
+- }
+- if (wakeup > 0) {
+- u132_ring_requeue_work(u132, ring, wakeup);
+- up(&u132->scheduler_lock);
+- return;
+- } else {
+- up(&u132->scheduler_lock);
+- u132_ring_put_kref(u132, ring);
+- return;
+- }
+- } else {
+- up(&u132->scheduler_lock);
+- u132_ring_put_kref(u132, ring);
+- return;
+- }
++ struct u132 *u132 = ring->u132;
++ mutex_lock(&u132->scheduler_lock);
++ if (ring->in_use) {
++ mutex_unlock(&u132->scheduler_lock);
++ u132_ring_put_kref(u132, ring);
++ return;
++ } else if (ring->curr_endp) {
++ struct u132_endp *last_endp = ring->curr_endp;
++ struct list_head *scan;
++ struct list_head *head = &last_endp->endp_ring;
++ unsigned long wakeup = 0;
++ list_for_each(scan, head) {
++ struct u132_endp *endp = list_entry(scan,
++ struct u132_endp, endp_ring);
++ if (endp->queue_next == endp->queue_last) {
++ } else if ((endp->delayed == 0)
++ || time_after_eq(jiffies, endp->jiffies)) {
++ ring->curr_endp = endp;
++ u132_endp_cancel_work(u132, last_endp);
++ u132_endp_queue_work(u132, last_endp, 0);
++ mutex_unlock(&u132->scheduler_lock);
++ u132_ring_put_kref(u132, ring);
++ return;
++ } else {
++ unsigned long delta = endp->jiffies - jiffies;
++ if (delta > wakeup)
++ wakeup = delta;
++ }
++ }
++ if (last_endp->queue_next == last_endp->queue_last) {
++ } else if ((last_endp->delayed == 0) || time_after_eq(jiffies,
++ last_endp->jiffies)) {
++ u132_endp_cancel_work(u132, last_endp);
++ u132_endp_queue_work(u132, last_endp, 0);
++ mutex_unlock(&u132->scheduler_lock);
++ u132_ring_put_kref(u132, ring);
++ return;
++ } else {
++ unsigned long delta = last_endp->jiffies - jiffies;
++ if (delta > wakeup)
++ wakeup = delta;
++ }
++ if (wakeup > 0) {
++ u132_ring_requeue_work(u132, ring, wakeup);
++ mutex_unlock(&u132->scheduler_lock);
++ return;
++ } else {
++ mutex_unlock(&u132->scheduler_lock);
++ u132_ring_put_kref(u132, ring);
++ return;
++ }
++ } else {
++ mutex_unlock(&u132->scheduler_lock);
++ u132_ring_put_kref(u132, ring);
++ return;
++ }
+ }
+
+ static void u132_hcd_endp_work_scheduler(struct work_struct *work)
+ {
+- struct u132_ring *ring;
+- struct u132_endp *endp =
++ struct u132_ring *ring;
++ struct u132_endp *endp =
+ container_of(work, struct u132_endp, scheduler.work);
+- struct u132 *u132 = endp->u132;
+- down(&u132->scheduler_lock);
+- ring = endp->ring;
+- if (endp->edset_flush) {
+- endp->edset_flush = 0;
+- if (endp->dequeueing)
+- usb_ftdi_elan_edset_flush(u132->platform_dev,
+- ring->number, endp);
+- up(&u132->scheduler_lock);
+- u132_endp_put_kref(u132, endp);
+- return;
+- } else if (endp->active) {
+- up(&u132->scheduler_lock);
+- u132_endp_put_kref(u132, endp);
+- return;
+- } else if (ring->in_use) {
+- up(&u132->scheduler_lock);
+- u132_endp_put_kref(u132, endp);
+- return;
+- } else if (endp->queue_next == endp->queue_last) {
+- up(&u132->scheduler_lock);
+- u132_endp_put_kref(u132, endp);
+- return;
+- } else if (endp->pipetype == PIPE_INTERRUPT) {
+- u8 address = u132->addr[endp->usb_addr].address;
+- if (ring->in_use) {
+- up(&u132->scheduler_lock);
+- u132_endp_put_kref(u132, endp);
+- return;
+- } else {
+- int retval;
+- struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+- endp->queue_next];
+- endp->active = 1;
+- ring->curr_endp = endp;
+- ring->in_use = 1;
+- up(&u132->scheduler_lock);
+- retval = edset_single(u132, ring, endp, urb, address,
+- endp->toggle_bits, u132_hcd_interrupt_recv);
+- if (retval == 0) {
+- } else
+- u132_hcd_giveback_urb(u132, endp, urb, retval);
+- return;
+- }
+- } else if (endp->pipetype == PIPE_CONTROL) {
+- u8 address = u132->addr[endp->usb_addr].address;
+- if (ring->in_use) {
+- up(&u132->scheduler_lock);
+- u132_endp_put_kref(u132, endp);
+- return;
+- } else if (address == 0) {
+- int retval;
+- struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+- endp->queue_next];
+- endp->active = 1;
+- ring->curr_endp = endp;
+- ring->in_use = 1;
+- up(&u132->scheduler_lock);
+- retval = edset_setup(u132, ring, endp, urb, address,
+- 0x2, u132_hcd_initial_setup_sent);
+- if (retval == 0) {
+- } else
+- u132_hcd_giveback_urb(u132, endp, urb, retval);
+- return;
+- } else if (endp->usb_addr == 0) {
+- int retval;
+- struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+- endp->queue_next];
+- endp->active = 1;
+- ring->curr_endp = endp;
+- ring->in_use = 1;
+- up(&u132->scheduler_lock);
+- retval = edset_setup(u132, ring, endp, urb, 0, 0x2,
+- u132_hcd_enumeration_address_sent);
+- if (retval == 0) {
+- } else
+- u132_hcd_giveback_urb(u132, endp, urb, retval);
+- return;
+- } else {
+- int retval;
+- u8 address = u132->addr[endp->usb_addr].address;
+- struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+- endp->queue_next];
+- endp->active = 1;
+- ring->curr_endp = endp;
+- ring->in_use = 1;
+- up(&u132->scheduler_lock);
+- retval = edset_setup(u132, ring, endp, urb, address,
+- 0x2, u132_hcd_configure_setup_sent);
+- if (retval == 0) {
+- } else
+- u132_hcd_giveback_urb(u132, endp, urb, retval);
+- return;
+- }
+- } else {
+- if (endp->input) {
+- u8 address = u132->addr[endp->usb_addr].address;
+- if (ring->in_use) {
+- up(&u132->scheduler_lock);
+- u132_endp_put_kref(u132, endp);
+- return;
+- } else {
+- int retval;
+- struct urb *urb = endp->urb_list[
+- ENDP_QUEUE_MASK & endp->queue_next];
+- endp->active = 1;
+- ring->curr_endp = endp;
+- ring->in_use = 1;
+- up(&u132->scheduler_lock);
+- retval = edset_input(u132, ring, endp, urb,
+- address, endp->toggle_bits,
+- u132_hcd_bulk_input_recv);
+- if (retval == 0) {
+- } else
+- u132_hcd_giveback_urb(u132, endp, urb,
+- retval);
+- return;
+- }
+- } else { /* output pipe */
+- u8 address = u132->addr[endp->usb_addr].address;
+- if (ring->in_use) {
+- up(&u132->scheduler_lock);
+- u132_endp_put_kref(u132, endp);
+- return;
+- } else {
+- int retval;
+- struct urb *urb = endp->urb_list[
+- ENDP_QUEUE_MASK & endp->queue_next];
+- endp->active = 1;
+- ring->curr_endp = endp;
+- ring->in_use = 1;
+- up(&u132->scheduler_lock);
+- retval = edset_output(u132, ring, endp, urb,
+- address, endp->toggle_bits,
+- u132_hcd_bulk_output_sent);
+- if (retval == 0) {
+- } else
+- u132_hcd_giveback_urb(u132, endp, urb,
+- retval);
+- return;
+- }
+- }
+- }
++ struct u132 *u132 = endp->u132;
++ mutex_lock(&u132->scheduler_lock);
++ ring = endp->ring;
++ if (endp->edset_flush) {
++ endp->edset_flush = 0;
++ if (endp->dequeueing)
++ usb_ftdi_elan_edset_flush(u132->platform_dev,
++ ring->number, endp);
++ mutex_unlock(&u132->scheduler_lock);
++ u132_endp_put_kref(u132, endp);
++ return;
++ } else if (endp->active) {
++ mutex_unlock(&u132->scheduler_lock);
++ u132_endp_put_kref(u132, endp);
++ return;
++ } else if (ring->in_use) {
++ mutex_unlock(&u132->scheduler_lock);
++ u132_endp_put_kref(u132, endp);
++ return;
++ } else if (endp->queue_next == endp->queue_last) {
++ mutex_unlock(&u132->scheduler_lock);
++ u132_endp_put_kref(u132, endp);
++ return;
++ } else if (endp->pipetype == PIPE_INTERRUPT) {
++ u8 address = u132->addr[endp->usb_addr].address;
++ if (ring->in_use) {
++ mutex_unlock(&u132->scheduler_lock);
++ u132_endp_put_kref(u132, endp);
++ return;
++ } else {
++ int retval;
++ struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
++ endp->queue_next];
++ endp->active = 1;
++ ring->curr_endp = endp;
++ ring->in_use = 1;
++ mutex_unlock(&u132->scheduler_lock);
++ retval = edset_single(u132, ring, endp, urb, address,
++ endp->toggle_bits, u132_hcd_interrupt_recv);
++ if (retval != 0)
++ u132_hcd_giveback_urb(u132, endp, urb, retval);
++ return;
++ }
++ } else if (endp->pipetype == PIPE_CONTROL) {
++ u8 address = u132->addr[endp->usb_addr].address;
++ if (ring->in_use) {
++ mutex_unlock(&u132->scheduler_lock);
++ u132_endp_put_kref(u132, endp);
++ return;
++ } else if (address == 0) {
++ int retval;
++ struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
++ endp->queue_next];
++ endp->active = 1;
++ ring->curr_endp = endp;
++ ring->in_use = 1;
++ mutex_unlock(&u132->scheduler_lock);
++ retval = edset_setup(u132, ring, endp, urb, address,
++ 0x2, u132_hcd_initial_setup_sent);
++ if (retval != 0)
++ u132_hcd_giveback_urb(u132, endp, urb, retval);
++ return;
++ } else if (endp->usb_addr == 0) {
++ int retval;
++ struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
++ endp->queue_next];
++ endp->active = 1;
++ ring->curr_endp = endp;
++ ring->in_use = 1;
++ mutex_unlock(&u132->scheduler_lock);
++ retval = edset_setup(u132, ring, endp, urb, 0, 0x2,
++ u132_hcd_enumeration_address_sent);
++ if (retval != 0)
++ u132_hcd_giveback_urb(u132, endp, urb, retval);
++ return;
++ } else {
++ int retval;
++ u8 address = u132->addr[endp->usb_addr].address;
++ struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
++ endp->queue_next];
++ endp->active = 1;
++ ring->curr_endp = endp;
++ ring->in_use = 1;
++ mutex_unlock(&u132->scheduler_lock);
++ retval = edset_setup(u132, ring, endp, urb, address,
++ 0x2, u132_hcd_configure_setup_sent);
++ if (retval != 0)
++ u132_hcd_giveback_urb(u132, endp, urb, retval);
++ return;
++ }
++ } else {
++ if (endp->input) {
++ u8 address = u132->addr[endp->usb_addr].address;
++ if (ring->in_use) {
++ mutex_unlock(&u132->scheduler_lock);
++ u132_endp_put_kref(u132, endp);
++ return;
++ } else {
++ int retval;
++ struct urb *urb = endp->urb_list[
++ ENDP_QUEUE_MASK & endp->queue_next];
++ endp->active = 1;
++ ring->curr_endp = endp;
++ ring->in_use = 1;
++ mutex_unlock(&u132->scheduler_lock);
++ retval = edset_input(u132, ring, endp, urb,
++ address, endp->toggle_bits,
++ u132_hcd_bulk_input_recv);
++ if (retval == 0) {
++ } else
++ u132_hcd_giveback_urb(u132, endp, urb,
++ retval);
++ return;
++ }
++ } else { /* output pipe */
++ u8 address = u132->addr[endp->usb_addr].address;
++ if (ring->in_use) {
++ mutex_unlock(&u132->scheduler_lock);
++ u132_endp_put_kref(u132, endp);
++ return;
++ } else {
++ int retval;
++ struct urb *urb = endp->urb_list[
++ ENDP_QUEUE_MASK & endp->queue_next];
++ endp->active = 1;
++ ring->curr_endp = endp;
++ ring->in_use = 1;
++ mutex_unlock(&u132->scheduler_lock);
++ retval = edset_output(u132, ring, endp, urb,
++ address, endp->toggle_bits,
++ u132_hcd_bulk_output_sent);
++ if (retval == 0) {
++ } else
++ u132_hcd_giveback_urb(u132, endp, urb,
++ retval);
++ return;
++ }
++ }
++ }
+ }
+ #ifdef CONFIG_PM
+
+ static void port_power(struct u132 *u132, int pn, int is_on)
+ {
+- u132->port[pn].power = is_on;
++ u132->port[pn].power = is_on;
+ }
+
+ #endif
+
+ static void u132_power(struct u132 *u132, int is_on)
+ {
+- struct usb_hcd *hcd = u132_to_hcd(u132)
+- ; /* hub is inactive unless the port is powered */
+- if (is_on) {
+- if (u132->power)
+- return;
+- u132->power = 1;
+- hcd->self.controller->power.power_state = PMSG_ON;
+- } else {
+- u132->power = 0;
+- hcd->state = HC_STATE_HALT;
+- hcd->self.controller->power.power_state = PMSG_SUSPEND;
+- }
++ struct usb_hcd *hcd = u132_to_hcd(u132)
++ ; /* hub is inactive unless the port is powered */
++ if (is_on) {
++ if (u132->power)
++ return;
++ u132->power = 1;
++ } else {
++ u132->power = 0;
++ hcd->state = HC_STATE_HALT;
++ }
+ }
+
+ static int u132_periodic_reinit(struct u132 *u132)
+ {
+- int retval;
+- u32 fi = u132->hc_fminterval & 0x03fff;
+- u32 fit;
+- u32 fminterval;
+- retval = u132_read_pcimem(u132, fminterval, &fminterval);
+- if (retval)
+- return retval;
+- fit = fminterval & FIT;
+- retval = u132_write_pcimem(u132, fminterval,
+- (fit ^ FIT) | u132->hc_fminterval);
+- if (retval)
+- return retval;
+- retval = u132_write_pcimem(u132, periodicstart,
+- ((9 *fi) / 10) & 0x3fff);
+- if (retval)
+- return retval;
+- return 0;
++ int retval;
++ u32 fi = u132->hc_fminterval & 0x03fff;
++ u32 fit;
++ u32 fminterval;
++ retval = u132_read_pcimem(u132, fminterval, &fminterval);
++ if (retval)
++ return retval;
++ fit = fminterval & FIT;
++ retval = u132_write_pcimem(u132, fminterval,
++ (fit ^ FIT) | u132->hc_fminterval);
++ if (retval)
++ return retval;
++ retval = u132_write_pcimem(u132, periodicstart,
++ ((9 * fi) / 10) & 0x3fff);
++ if (retval)
++ return retval;
++ return 0;
+ }
+
+ static char *hcfs2string(int state)
+ {
+- switch (state) {
+- case OHCI_USB_RESET:
+- return "reset";
+- case OHCI_USB_RESUME:
+- return "resume";
+- case OHCI_USB_OPER:
+- return "operational";
+- case OHCI_USB_SUSPEND:
+- return "suspend";
+- }
+- return "?";
++ switch (state) {
++ case OHCI_USB_RESET:
++ return "reset";
++ case OHCI_USB_RESUME:
++ return "resume";
++ case OHCI_USB_OPER:
++ return "operational";
++ case OHCI_USB_SUSPEND:
++ return "suspend";
++ }
++ return "?";
+ }
+
+ static int u132_init(struct u132 *u132)
+ {
+- int retval;
+- u32 control;
+- u132_disable(u132);
+- u132->next_statechange = jiffies;
+- retval = u132_write_pcimem(u132, intrdisable, OHCI_INTR_MIE);
+- if (retval)
+- return retval;
+- retval = u132_read_pcimem(u132, control, &control);
+- if (retval)
+- return retval;
+- if (u132->num_ports == 0) {
+- u32 rh_a = -1;
+- retval = u132_read_pcimem(u132, roothub.a, &rh_a);
+- if (retval)
+- return retval;
+- u132->num_ports = rh_a & RH_A_NDP;
+- retval = read_roothub_info(u132);
+- if (retval)
+- return retval;
+- }
+- if (u132->num_ports > MAX_U132_PORTS) {
+- return -EINVAL;
+- }
+- return 0;
++ int retval;
++ u32 control;
++ u132_disable(u132);
++ u132->next_statechange = jiffies;
++ retval = u132_write_pcimem(u132, intrdisable, OHCI_INTR_MIE);
++ if (retval)
++ return retval;
++ retval = u132_read_pcimem(u132, control, &control);
++ if (retval)
++ return retval;
++ if (u132->num_ports == 0) {
++ u32 rh_a = -1;
++ retval = u132_read_pcimem(u132, roothub.a, &rh_a);
++ if (retval)
++ return retval;
++ u132->num_ports = rh_a & RH_A_NDP;
++ retval = read_roothub_info(u132);
++ if (retval)
++ return retval;
++ }
++ if (u132->num_ports > MAX_U132_PORTS)
++ return -EINVAL;
++
++ return 0;
+ }
+
+
+@@ -1613,280 +1603,278 @@ static int u132_init(struct u132 *u132)
+ */
+ static int u132_run(struct u132 *u132)
+ {
+- int retval;
+- u32 control;
+- u32 status;
+- u32 fminterval;
+- u32 periodicstart;
+- u32 cmdstatus;
+- u32 roothub_a;
+- int mask = OHCI_INTR_INIT;
+- int first = u132->hc_fminterval == 0;
+- int sleep_time = 0;
+- int reset_timeout = 30; /* ... allow extra time */
+- u132_disable(u132);
+- if (first) {
+- u32 temp;
+- retval = u132_read_pcimem(u132, fminterval, &temp);
+- if (retval)
+- return retval;
+- u132->hc_fminterval = temp & 0x3fff;
+- if (u132->hc_fminterval != FI) {
+- }
+- u132->hc_fminterval |= FSMP(u132->hc_fminterval) << 16;
+- }
+- retval = u132_read_pcimem(u132, control, &u132->hc_control);
+- if (retval)
+- return retval;
+- dev_info(&u132->platform_dev->dev, "resetting from state '%s', control "
+- "= %08X\n", hcfs2string(u132->hc_control & OHCI_CTRL_HCFS),
+- u132->hc_control);
+- switch (u132->hc_control & OHCI_CTRL_HCFS) {
+- case OHCI_USB_OPER:
+- sleep_time = 0;
+- break;
+- case OHCI_USB_SUSPEND:
+- case OHCI_USB_RESUME:
+- u132->hc_control &= OHCI_CTRL_RWC;
+- u132->hc_control |= OHCI_USB_RESUME;
+- sleep_time = 10;
+- break;
+- default:
+- u132->hc_control &= OHCI_CTRL_RWC;
+- u132->hc_control |= OHCI_USB_RESET;
+- sleep_time = 50;
+- break;
+- }
+- retval = u132_write_pcimem(u132, control, u132->hc_control);
+- if (retval)
+- return retval;
+- retval = u132_read_pcimem(u132, control, &control);
+- if (retval)
+- return retval;
+- msleep(sleep_time);
+- retval = u132_read_pcimem(u132, roothub.a, &roothub_a);
+- if (retval)
+- return retval;
+- if (!(roothub_a & RH_A_NPS)) {
+- int temp; /* power down each port */
+- for (temp = 0; temp < u132->num_ports; temp++) {
+- retval = u132_write_pcimem(u132,
+- roothub.portstatus[temp], RH_PS_LSDA);
+- if (retval)
+- return retval;
+- }
+- }
+- retval = u132_read_pcimem(u132, control, &control);
+- if (retval)
+- return retval;
+- retry:retval = u132_read_pcimem(u132, cmdstatus, &status);
+- if (retval)
+- return retval;
+- retval = u132_write_pcimem(u132, cmdstatus, OHCI_HCR);
+- if (retval)
+- return retval;
+- extra:{
+- retval = u132_read_pcimem(u132, cmdstatus, &status);
+- if (retval)
+- return retval;
+- if (0 != (status & OHCI_HCR)) {
+- if (--reset_timeout == 0) {
+- dev_err(&u132->platform_dev->dev, "USB HC reset"
+- " timed out!\n");
+- return -ENODEV;
+- } else {
+- msleep(5);
+- goto extra;
+- }
+- }
+- }
+- if (u132->flags & OHCI_QUIRK_INITRESET) {
+- retval = u132_write_pcimem(u132, control, u132->hc_control);
+- if (retval)
+- return retval;
+- retval = u132_read_pcimem(u132, control, &control);
+- if (retval)
+- return retval;
+- }
+- retval = u132_write_pcimem(u132, ed_controlhead, 0x00000000);
+- if (retval)
+- return retval;
+- retval = u132_write_pcimem(u132, ed_bulkhead, 0x11000000);
+- if (retval)
+- return retval;
+- retval = u132_write_pcimem(u132, hcca, 0x00000000);
+- if (retval)
+- return retval;
+- retval = u132_periodic_reinit(u132);
+- if (retval)
+- return retval;
+- retval = u132_read_pcimem(u132, fminterval, &fminterval);
+- if (retval)
+- return retval;
+- retval = u132_read_pcimem(u132, periodicstart, &periodicstart);
+- if (retval)
+- return retval;
+- if (0 == (fminterval & 0x3fff0000) || 0 == periodicstart) {
+- if (!(u132->flags & OHCI_QUIRK_INITRESET)) {
+- u132->flags |= OHCI_QUIRK_INITRESET;
+- goto retry;
+- } else
+- dev_err(&u132->platform_dev->dev, "init err(%08x %04x)"
+- "\n", fminterval, periodicstart);
+- } /* start controller operations */
+- u132->hc_control &= OHCI_CTRL_RWC;
+- u132->hc_control |= OHCI_CONTROL_INIT | OHCI_CTRL_BLE | OHCI_USB_OPER;
+- retval = u132_write_pcimem(u132, control, u132->hc_control);
+- if (retval)
+- return retval;
+- retval = u132_write_pcimem(u132, cmdstatus, OHCI_BLF);
+- if (retval)
+- return retval;
+- retval = u132_read_pcimem(u132, cmdstatus, &cmdstatus);
+- if (retval)
+- return retval;
+- retval = u132_read_pcimem(u132, control, &control);
+- if (retval)
+- return retval;
+- u132_to_hcd(u132)->state = HC_STATE_RUNNING;
+- retval = u132_write_pcimem(u132, roothub.status, RH_HS_DRWE);
+- if (retval)
+- return retval;
+- retval = u132_write_pcimem(u132, intrstatus, mask);
+- if (retval)
+- return retval;
+- retval = u132_write_pcimem(u132, intrdisable,
+- OHCI_INTR_MIE | OHCI_INTR_OC | OHCI_INTR_RHSC | OHCI_INTR_FNO |
+- OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_SF | OHCI_INTR_WDH |
+- OHCI_INTR_SO);
+- if (retval)
+- return retval; /* handle root hub init quirks ... */
+- retval = u132_read_pcimem(u132, roothub.a, &roothub_a);
+- if (retval)
+- return retval;
+- roothub_a &= ~(RH_A_PSM | RH_A_OCPM);
+- if (u132->flags & OHCI_QUIRK_SUPERIO) {
+- roothub_a |= RH_A_NOCP;
+- roothub_a &= ~(RH_A_POTPGT | RH_A_NPS);
+- retval = u132_write_pcimem(u132, roothub.a, roothub_a);
+- if (retval)
+- return retval;
+- } else if ((u132->flags & OHCI_QUIRK_AMD756) || distrust_firmware) {
+- roothub_a |= RH_A_NPS;
+- retval = u132_write_pcimem(u132, roothub.a, roothub_a);
+- if (retval)
+- return retval;
+- }
+- retval = u132_write_pcimem(u132, roothub.status, RH_HS_LPSC);
+- if (retval)
+- return retval;
+- retval = u132_write_pcimem(u132, roothub.b,
+- (roothub_a & RH_A_NPS) ? 0 : RH_B_PPCM);
+- if (retval)
+- return retval;
+- retval = u132_read_pcimem(u132, control, &control);
+- if (retval)
+- return retval;
+- mdelay((roothub_a >> 23) & 0x1fe);
+- u132_to_hcd(u132)->state = HC_STATE_RUNNING;
+- return 0;
++ int retval;
++ u32 control;
++ u32 status;
++ u32 fminterval;
++ u32 periodicstart;
++ u32 cmdstatus;
++ u32 roothub_a;
++ int mask = OHCI_INTR_INIT;
++ int first = u132->hc_fminterval == 0;
++ int sleep_time = 0;
++ int reset_timeout = 30; /* ... allow extra time */
++ u132_disable(u132);
++ if (first) {
++ u32 temp;
++ retval = u132_read_pcimem(u132, fminterval, &temp);
++ if (retval)
++ return retval;
++ u132->hc_fminterval = temp & 0x3fff;
++ u132->hc_fminterval |= FSMP(u132->hc_fminterval) << 16;
++ }
++ retval = u132_read_pcimem(u132, control, &u132->hc_control);
++ if (retval)
++ return retval;
++ dev_info(&u132->platform_dev->dev, "resetting from state '%s', control "
++ "= %08X\n", hcfs2string(u132->hc_control & OHCI_CTRL_HCFS),
++ u132->hc_control);
++ switch (u132->hc_control & OHCI_CTRL_HCFS) {
++ case OHCI_USB_OPER:
++ sleep_time = 0;
++ break;
++ case OHCI_USB_SUSPEND:
++ case OHCI_USB_RESUME:
++ u132->hc_control &= OHCI_CTRL_RWC;
++ u132->hc_control |= OHCI_USB_RESUME;
++ sleep_time = 10;
++ break;
++ default:
++ u132->hc_control &= OHCI_CTRL_RWC;
++ u132->hc_control |= OHCI_USB_RESET;
++ sleep_time = 50;
++ break;
++ }
++ retval = u132_write_pcimem(u132, control, u132->hc_control);
++ if (retval)
++ return retval;
++ retval = u132_read_pcimem(u132, control, &control);
++ if (retval)
++ return retval;
++ msleep(sleep_time);
++ retval = u132_read_pcimem(u132, roothub.a, &roothub_a);
++ if (retval)
++ return retval;
++ if (!(roothub_a & RH_A_NPS)) {
++ int temp; /* power down each port */
++ for (temp = 0; temp < u132->num_ports; temp++) {
++ retval = u132_write_pcimem(u132,
++ roothub.portstatus[temp], RH_PS_LSDA);
++ if (retval)
++ return retval;
++ }
++ }
++ retval = u132_read_pcimem(u132, control, &control);
++ if (retval)
++ return retval;
++retry:
++ retval = u132_read_pcimem(u132, cmdstatus, &status);
++ if (retval)
++ return retval;
++ retval = u132_write_pcimem(u132, cmdstatus, OHCI_HCR);
++ if (retval)
++ return retval;
++extra: {
++ retval = u132_read_pcimem(u132, cmdstatus, &status);
++ if (retval)
++ return retval;
++ if (0 != (status & OHCI_HCR)) {
++ if (--reset_timeout == 0) {
++ dev_err(&u132->platform_dev->dev, "USB HC reset"
++ " timed out!\n");
++ return -ENODEV;
++ } else {
++ msleep(5);
++ goto extra;
++ }
++ }
++ }
++ if (u132->flags & OHCI_QUIRK_INITRESET) {
++ retval = u132_write_pcimem(u132, control, u132->hc_control);
++ if (retval)
++ return retval;
++ retval = u132_read_pcimem(u132, control, &control);
++ if (retval)
++ return retval;
++ }
++ retval = u132_write_pcimem(u132, ed_controlhead, 0x00000000);
++ if (retval)
++ return retval;
++ retval = u132_write_pcimem(u132, ed_bulkhead, 0x11000000);
++ if (retval)
++ return retval;
++ retval = u132_write_pcimem(u132, hcca, 0x00000000);
++ if (retval)
++ return retval;
++ retval = u132_periodic_reinit(u132);
++ if (retval)
++ return retval;
++ retval = u132_read_pcimem(u132, fminterval, &fminterval);
++ if (retval)
++ return retval;
++ retval = u132_read_pcimem(u132, periodicstart, &periodicstart);
++ if (retval)
++ return retval;
++ if (0 == (fminterval & 0x3fff0000) || 0 == periodicstart) {
++ if (!(u132->flags & OHCI_QUIRK_INITRESET)) {
++ u132->flags |= OHCI_QUIRK_INITRESET;
++ goto retry;
++ } else
++ dev_err(&u132->platform_dev->dev, "init err(%08x %04x)"
++ "\n", fminterval, periodicstart);
++ } /* start controller operations */
++ u132->hc_control &= OHCI_CTRL_RWC;
++ u132->hc_control |= OHCI_CONTROL_INIT | OHCI_CTRL_BLE | OHCI_USB_OPER;
++ retval = u132_write_pcimem(u132, control, u132->hc_control);
++ if (retval)
++ return retval;
++ retval = u132_write_pcimem(u132, cmdstatus, OHCI_BLF);
++ if (retval)
++ return retval;
++ retval = u132_read_pcimem(u132, cmdstatus, &cmdstatus);
++ if (retval)
++ return retval;
++ retval = u132_read_pcimem(u132, control, &control);
++ if (retval)
++ return retval;
++ u132_to_hcd(u132)->state = HC_STATE_RUNNING;
++ retval = u132_write_pcimem(u132, roothub.status, RH_HS_DRWE);
++ if (retval)
++ return retval;
++ retval = u132_write_pcimem(u132, intrstatus, mask);
++ if (retval)
++ return retval;
++ retval = u132_write_pcimem(u132, intrdisable,
++ OHCI_INTR_MIE | OHCI_INTR_OC | OHCI_INTR_RHSC | OHCI_INTR_FNO |
++ OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_SF | OHCI_INTR_WDH |
++ OHCI_INTR_SO);
++ if (retval)
++ return retval; /* handle root hub init quirks ... */
++ retval = u132_read_pcimem(u132, roothub.a, &roothub_a);
++ if (retval)
++ return retval;
++ roothub_a &= ~(RH_A_PSM | RH_A_OCPM);
++ if (u132->flags & OHCI_QUIRK_SUPERIO) {
++ roothub_a |= RH_A_NOCP;
++ roothub_a &= ~(RH_A_POTPGT | RH_A_NPS);
++ retval = u132_write_pcimem(u132, roothub.a, roothub_a);
++ if (retval)
++ return retval;
++ } else if ((u132->flags & OHCI_QUIRK_AMD756) || distrust_firmware) {
++ roothub_a |= RH_A_NPS;
++ retval = u132_write_pcimem(u132, roothub.a, roothub_a);
++ if (retval)
++ return retval;
++ }
++ retval = u132_write_pcimem(u132, roothub.status, RH_HS_LPSC);
++ if (retval)
++ return retval;
++ retval = u132_write_pcimem(u132, roothub.b,
++ (roothub_a & RH_A_NPS) ? 0 : RH_B_PPCM);
++ if (retval)
++ return retval;
++ retval = u132_read_pcimem(u132, control, &control);
++ if (retval)
++ return retval;
++ mdelay((roothub_a >> 23) & 0x1fe);
++ u132_to_hcd(u132)->state = HC_STATE_RUNNING;
++ return 0;
+ }
+
+ static void u132_hcd_stop(struct usb_hcd *hcd)
+ {
+- struct u132 *u132 = hcd_to_u132(hcd);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p) has b"
+- "een removed %d\n", u132, hcd, u132->going);
+- } else if (u132->going > 0) {
+- dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
+- "ed\n", hcd);
+- } else {
+- mutex_lock(&u132->sw_lock);
+- msleep(100);
+- u132_power(u132, 0);
+- mutex_unlock(&u132->sw_lock);
+- }
++ struct u132 *u132 = hcd_to_u132(hcd);
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p) has b"
++ "een removed %d\n", u132, hcd, u132->going);
++ } else if (u132->going > 0) {
++ dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
++ "ed\n", hcd);
++ } else {
++ mutex_lock(&u132->sw_lock);
++ msleep(100);
++ u132_power(u132, 0);
++ mutex_unlock(&u132->sw_lock);
++ }
+ }
+
+ static int u132_hcd_start(struct usb_hcd *hcd)
+ {
+- struct u132 *u132 = hcd_to_u132(hcd);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- return -ENODEV;
+- } else if (u132->going > 0) {
+- dev_err(&u132->platform_dev->dev, "device is being removed\n");
+- return -ESHUTDOWN;
+- } else if (hcd->self.controller) {
+- int retval;
+- struct platform_device *pdev =
+- to_platform_device(hcd->self.controller);
+- u16 vendor = ((struct u132_platform_data *)
+- (pdev->dev.platform_data))->vendor;
+- u16 device = ((struct u132_platform_data *)
+- (pdev->dev.platform_data))->device;
+- mutex_lock(&u132->sw_lock);
+- msleep(10);
+- if (vendor == PCI_VENDOR_ID_AMD && device == 0x740c) {
+- u132->flags = OHCI_QUIRK_AMD756;
+- } else if (vendor == PCI_VENDOR_ID_OPTI && device == 0xc861) {
+- dev_err(&u132->platform_dev->dev, "WARNING: OPTi workar"
+- "ounds unavailable\n");
+- } else if (vendor == PCI_VENDOR_ID_COMPAQ && device == 0xa0f8)
+- u132->flags |= OHCI_QUIRK_ZFMICRO;
+- retval = u132_run(u132);
+- if (retval) {
+- u132_disable(u132);
+- u132->going = 1;
+- }
+- msleep(100);
+- mutex_unlock(&u132->sw_lock);
+- return retval;
+- } else {
+- dev_err(&u132->platform_dev->dev, "platform_device missing\n");
+- return -ENODEV;
+- }
++ struct u132 *u132 = hcd_to_u132(hcd);
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++ , u132->going);
++ return -ENODEV;
++ } else if (u132->going > 0) {
++ dev_err(&u132->platform_dev->dev, "device is being removed\n");
++ return -ESHUTDOWN;
++ } else if (hcd->self.controller) {
++ int retval;
++ struct platform_device *pdev =
++ to_platform_device(hcd->self.controller);
++ u16 vendor = ((struct u132_platform_data *)
++ (pdev->dev.platform_data))->vendor;
++ u16 device = ((struct u132_platform_data *)
++ (pdev->dev.platform_data))->device;
++ mutex_lock(&u132->sw_lock);
++ msleep(10);
++ if (vendor == PCI_VENDOR_ID_AMD && device == 0x740c) {
++ u132->flags = OHCI_QUIRK_AMD756;
++ } else if (vendor == PCI_VENDOR_ID_OPTI && device == 0xc861) {
++ dev_err(&u132->platform_dev->dev, "WARNING: OPTi workar"
++ "ounds unavailable\n");
++ } else if (vendor == PCI_VENDOR_ID_COMPAQ && device == 0xa0f8)
++ u132->flags |= OHCI_QUIRK_ZFMICRO;
++ retval = u132_run(u132);
++ if (retval) {
++ u132_disable(u132);
++ u132->going = 1;
++ }
++ msleep(100);
++ mutex_unlock(&u132->sw_lock);
++ return retval;
++ } else {
++ dev_err(&u132->platform_dev->dev, "platform_device missing\n");
++ return -ENODEV;
++ }
+ }
+
+ static int u132_hcd_reset(struct usb_hcd *hcd)
+ {
+- struct u132 *u132 = hcd_to_u132(hcd);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- return -ENODEV;
+- } else if (u132->going > 0) {
+- dev_err(&u132->platform_dev->dev, "device is being removed\n");
+- return -ESHUTDOWN;
+- } else {
+- int retval;
+- mutex_lock(&u132->sw_lock);
+- retval = u132_init(u132);
+- if (retval) {
+- u132_disable(u132);
+- u132->going = 1;
+- }
+- mutex_unlock(&u132->sw_lock);
+- return retval;
+- }
++ struct u132 *u132 = hcd_to_u132(hcd);
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++ , u132->going);
++ return -ENODEV;
++ } else if (u132->going > 0) {
++ dev_err(&u132->platform_dev->dev, "device is being removed\n");
++ return -ESHUTDOWN;
++ } else {
++ int retval;
++ mutex_lock(&u132->sw_lock);
++ retval = u132_init(u132);
++ if (retval) {
++ u132_disable(u132);
++ u132->going = 1;
++ }
++ mutex_unlock(&u132->sw_lock);
++ return retval;
++ }
+ }
+
+ static int create_endpoint_and_queue_int(struct u132 *u132,
+ struct u132_udev *udev, struct urb *urb,
+- struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
+- gfp_t mem_flags)
++ struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
++ gfp_t mem_flags)
+ {
+- struct u132_ring *ring;
+- unsigned long irqs;
++ struct u132_ring *ring;
++ unsigned long irqs;
+ int rc;
+ u8 endp_number;
+ struct u132_endp *endp = kmalloc(sizeof(struct u132_endp), mem_flags);
+
+- if (!endp) {
+- return -ENOMEM;
+- }
++ if (!endp)
++ return -ENOMEM;
+
+ spin_lock_init(&endp->queue_lock.slock);
+ spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+@@ -1899,94 +1887,93 @@ static int create_endpoint_and_queue_int(struct u132 *u132,
+
+ endp_number = ++u132->num_endpoints;
+ urb->ep->hcpriv = u132->endp[endp_number - 1] = endp;
+- INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
+- INIT_LIST_HEAD(&endp->urb_more);
+- ring = endp->ring = &u132->ring[0];
+- if (ring->curr_endp) {
+- list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
+- } else {
+- INIT_LIST_HEAD(&endp->endp_ring);
+- ring->curr_endp = endp;
+- }
+- ring->length += 1;
+- endp->dequeueing = 0;
+- endp->edset_flush = 0;
+- endp->active = 0;
+- endp->delayed = 0;
+- endp->endp_number = endp_number;
+- endp->u132 = u132;
++ INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
++ INIT_LIST_HEAD(&endp->urb_more);
++ ring = endp->ring = &u132->ring[0];
++ if (ring->curr_endp) {
++ list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
++ } else {
++ INIT_LIST_HEAD(&endp->endp_ring);
++ ring->curr_endp = endp;
++ }
++ ring->length += 1;
++ endp->dequeueing = 0;
++ endp->edset_flush = 0;
++ endp->active = 0;
++ endp->delayed = 0;
++ endp->endp_number = endp_number;
++ endp->u132 = u132;
+ endp->hep = urb->ep;
+- endp->pipetype = usb_pipetype(urb->pipe);
+- u132_endp_init_kref(u132, endp);
+- if (usb_pipein(urb->pipe)) {
+- endp->toggle_bits = 0x2;
+- usb_settoggle(udev->usb_device, usb_endp, 0, 0);
+- endp->input = 1;
+- endp->output = 0;
+- udev->endp_number_in[usb_endp] = endp_number;
+- u132_udev_get_kref(u132, udev);
+- } else {
+- endp->toggle_bits = 0x2;
+- usb_settoggle(udev->usb_device, usb_endp, 1, 0);
+- endp->input = 0;
+- endp->output = 1;
+- udev->endp_number_out[usb_endp] = endp_number;
+- u132_udev_get_kref(u132, udev);
+- }
+- urb->hcpriv = u132;
+- endp->delayed = 1;
+- endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
+- endp->udev_number = address;
+- endp->usb_addr = usb_addr;
+- endp->usb_endp = usb_endp;
+- endp->queue_size = 1;
+- endp->queue_last = 0;
+- endp->queue_next = 0;
+- endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+- spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+- u132_endp_queue_work(u132, endp, msecs_to_jiffies(urb->interval));
+- return 0;
++ endp->pipetype = usb_pipetype(urb->pipe);
++ u132_endp_init_kref(u132, endp);
++ if (usb_pipein(urb->pipe)) {
++ endp->toggle_bits = 0x2;
++ usb_settoggle(udev->usb_device, usb_endp, 0, 0);
++ endp->input = 1;
++ endp->output = 0;
++ udev->endp_number_in[usb_endp] = endp_number;
++ u132_udev_get_kref(u132, udev);
++ } else {
++ endp->toggle_bits = 0x2;
++ usb_settoggle(udev->usb_device, usb_endp, 1, 0);
++ endp->input = 0;
++ endp->output = 1;
++ udev->endp_number_out[usb_endp] = endp_number;
++ u132_udev_get_kref(u132, udev);
++ }
++ urb->hcpriv = u132;
++ endp->delayed = 1;
++ endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
++ endp->udev_number = address;
++ endp->usb_addr = usb_addr;
++ endp->usb_endp = usb_endp;
++ endp->queue_size = 1;
++ endp->queue_last = 0;
++ endp->queue_next = 0;
++ endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
++ spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++ u132_endp_queue_work(u132, endp, msecs_to_jiffies(urb->interval));
++ return 0;
+ }
+
+ static int queue_int_on_old_endpoint(struct u132 *u132,
+ struct u132_udev *udev, struct urb *urb,
+- struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
+- u8 usb_endp, u8 address)
+-{
+- urb->hcpriv = u132;
+- endp->delayed = 1;
+- endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
+- if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+- endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+- } else {
+- struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq),
+- GFP_ATOMIC);
+- if (urbq == NULL) {
+- endp->queue_size -= 1;
+- return -ENOMEM;
+- } else {
+- list_add_tail(&urbq->urb_more, &endp->urb_more);
+- urbq->urb = urb;
+- }
+- }
+- return 0;
++ struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
++ u8 usb_endp, u8 address)
++{
++ urb->hcpriv = u132;
++ endp->delayed = 1;
++ endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
++ if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
++ endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
++ } else {
++ struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq),
++ GFP_ATOMIC);
++ if (urbq == NULL) {
++ endp->queue_size -= 1;
++ return -ENOMEM;
++ } else {
++ list_add_tail(&urbq->urb_more, &endp->urb_more);
++ urbq->urb = urb;
++ }
++ }
++ return 0;
+ }
+
+ static int create_endpoint_and_queue_bulk(struct u132 *u132,
+ struct u132_udev *udev, struct urb *urb,
+- struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
+- gfp_t mem_flags)
++ struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
++ gfp_t mem_flags)
+ {
+- int ring_number;
+- struct u132_ring *ring;
+- unsigned long irqs;
++ int ring_number;
++ struct u132_ring *ring;
++ unsigned long irqs;
+ int rc;
+ u8 endp_number;
+ struct u132_endp *endp = kmalloc(sizeof(struct u132_endp), mem_flags);
+
+- if (!endp) {
+- return -ENOMEM;
+- }
++ if (!endp)
++ return -ENOMEM;
+
+ spin_lock_init(&endp->queue_lock.slock);
+ spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+@@ -1999,91 +1986,90 @@ static int create_endpoint_and_queue_bulk(struct u132 *u132,
+
+ endp_number = ++u132->num_endpoints;
+ urb->ep->hcpriv = u132->endp[endp_number - 1] = endp;
+- INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
+- INIT_LIST_HEAD(&endp->urb_more);
+- endp->dequeueing = 0;
+- endp->edset_flush = 0;
+- endp->active = 0;
+- endp->delayed = 0;
+- endp->endp_number = endp_number;
+- endp->u132 = u132;
++ INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
++ INIT_LIST_HEAD(&endp->urb_more);
++ endp->dequeueing = 0;
++ endp->edset_flush = 0;
++ endp->active = 0;
++ endp->delayed = 0;
++ endp->endp_number = endp_number;
++ endp->u132 = u132;
+ endp->hep = urb->ep;
+- endp->pipetype = usb_pipetype(urb->pipe);
+- u132_endp_init_kref(u132, endp);
+- if (usb_pipein(urb->pipe)) {
+- endp->toggle_bits = 0x2;
+- usb_settoggle(udev->usb_device, usb_endp, 0, 0);
+- ring_number = 3;
+- endp->input = 1;
+- endp->output = 0;
+- udev->endp_number_in[usb_endp] = endp_number;
+- u132_udev_get_kref(u132, udev);
+- } else {
+- endp->toggle_bits = 0x2;
+- usb_settoggle(udev->usb_device, usb_endp, 1, 0);
+- ring_number = 2;
+- endp->input = 0;
+- endp->output = 1;
+- udev->endp_number_out[usb_endp] = endp_number;
+- u132_udev_get_kref(u132, udev);
+- }
+- ring = endp->ring = &u132->ring[ring_number - 1];
+- if (ring->curr_endp) {
+- list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
+- } else {
+- INIT_LIST_HEAD(&endp->endp_ring);
+- ring->curr_endp = endp;
+- }
+- ring->length += 1;
+- urb->hcpriv = u132;
+- endp->udev_number = address;
+- endp->usb_addr = usb_addr;
+- endp->usb_endp = usb_endp;
+- endp->queue_size = 1;
+- endp->queue_last = 0;
+- endp->queue_next = 0;
+- endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+- spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+- u132_endp_queue_work(u132, endp, 0);
+- return 0;
++ endp->pipetype = usb_pipetype(urb->pipe);
++ u132_endp_init_kref(u132, endp);
++ if (usb_pipein(urb->pipe)) {
++ endp->toggle_bits = 0x2;
++ usb_settoggle(udev->usb_device, usb_endp, 0, 0);
++ ring_number = 3;
++ endp->input = 1;
++ endp->output = 0;
++ udev->endp_number_in[usb_endp] = endp_number;
++ u132_udev_get_kref(u132, udev);
++ } else {
++ endp->toggle_bits = 0x2;
++ usb_settoggle(udev->usb_device, usb_endp, 1, 0);
++ ring_number = 2;
++ endp->input = 0;
++ endp->output = 1;
++ udev->endp_number_out[usb_endp] = endp_number;
++ u132_udev_get_kref(u132, udev);
++ }
++ ring = endp->ring = &u132->ring[ring_number - 1];
++ if (ring->curr_endp) {
++ list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
++ } else {
++ INIT_LIST_HEAD(&endp->endp_ring);
++ ring->curr_endp = endp;
++ }
++ ring->length += 1;
++ urb->hcpriv = u132;
++ endp->udev_number = address;
++ endp->usb_addr = usb_addr;
++ endp->usb_endp = usb_endp;
++ endp->queue_size = 1;
++ endp->queue_last = 0;
++ endp->queue_next = 0;
++ endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
++ spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++ u132_endp_queue_work(u132, endp, 0);
++ return 0;
+ }
+
+ static int queue_bulk_on_old_endpoint(struct u132 *u132, struct u132_udev *udev,
+ struct urb *urb,
+- struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
+- u8 usb_endp, u8 address)
+-{
+- urb->hcpriv = u132;
+- if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+- endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+- } else {
+- struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq),
+- GFP_ATOMIC);
+- if (urbq == NULL) {
+- endp->queue_size -= 1;
+- return -ENOMEM;
+- } else {
+- list_add_tail(&urbq->urb_more, &endp->urb_more);
+- urbq->urb = urb;
+- }
+- }
+- return 0;
++ struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
++ u8 usb_endp, u8 address)
++{
++ urb->hcpriv = u132;
++ if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
++ endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
++ } else {
++ struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq),
++ GFP_ATOMIC);
++ if (urbq == NULL) {
++ endp->queue_size -= 1;
++ return -ENOMEM;
++ } else {
++ list_add_tail(&urbq->urb_more, &endp->urb_more);
++ urbq->urb = urb;
++ }
++ }
++ return 0;
+ }
+
+ static int create_endpoint_and_queue_control(struct u132 *u132,
+ struct urb *urb,
+- struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp,
+- gfp_t mem_flags)
++ struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp,
++ gfp_t mem_flags)
+ {
+- struct u132_ring *ring;
++ struct u132_ring *ring;
+ unsigned long irqs;
+ int rc;
+ u8 endp_number;
+ struct u132_endp *endp = kmalloc(sizeof(struct u132_endp), mem_flags);
+
+- if (!endp) {
+- return -ENOMEM;
+- }
++ if (!endp)
++ return -ENOMEM;
+
+ spin_lock_init(&endp->queue_lock.slock);
+ spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+@@ -2096,204 +2082,203 @@ static int create_endpoint_and_queue_control(struct u132 *u132,
+
+ endp_number = ++u132->num_endpoints;
+ urb->ep->hcpriv = u132->endp[endp_number - 1] = endp;
+- INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
+- INIT_LIST_HEAD(&endp->urb_more);
+- ring = endp->ring = &u132->ring[0];
+- if (ring->curr_endp) {
+- list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
+- } else {
+- INIT_LIST_HEAD(&endp->endp_ring);
+- ring->curr_endp = endp;
+- }
+- ring->length += 1;
+- endp->dequeueing = 0;
+- endp->edset_flush = 0;
+- endp->active = 0;
+- endp->delayed = 0;
+- endp->endp_number = endp_number;
+- endp->u132 = u132;
++ INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
++ INIT_LIST_HEAD(&endp->urb_more);
++ ring = endp->ring = &u132->ring[0];
++ if (ring->curr_endp) {
++ list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
++ } else {
++ INIT_LIST_HEAD(&endp->endp_ring);
++ ring->curr_endp = endp;
++ }
++ ring->length += 1;
++ endp->dequeueing = 0;
++ endp->edset_flush = 0;
++ endp->active = 0;
++ endp->delayed = 0;
++ endp->endp_number = endp_number;
++ endp->u132 = u132;
+ endp->hep = urb->ep;
+- u132_endp_init_kref(u132, endp);
+- u132_endp_get_kref(u132, endp);
+- if (usb_addr == 0) {
+- u8 address = u132->addr[usb_addr].address;
+- struct u132_udev *udev = &u132->udev[address];
+- endp->udev_number = address;
+- endp->usb_addr = usb_addr;
+- endp->usb_endp = usb_endp;
+- endp->input = 1;
+- endp->output = 1;
+- endp->pipetype = usb_pipetype(urb->pipe);
+- u132_udev_init_kref(u132, udev);
+- u132_udev_get_kref(u132, udev);
+- udev->endp_number_in[usb_endp] = endp_number;
+- udev->endp_number_out[usb_endp] = endp_number;
+- urb->hcpriv = u132;
+- endp->queue_size = 1;
+- endp->queue_last = 0;
+- endp->queue_next = 0;
+- endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+- spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+- u132_endp_queue_work(u132, endp, 0);
+- return 0;
+- } else { /*(usb_addr > 0) */
+- u8 address = u132->addr[usb_addr].address;
+- struct u132_udev *udev = &u132->udev[address];
+- endp->udev_number = address;
+- endp->usb_addr = usb_addr;
+- endp->usb_endp = usb_endp;
+- endp->input = 1;
+- endp->output = 1;
+- endp->pipetype = usb_pipetype(urb->pipe);
+- u132_udev_get_kref(u132, udev);
+- udev->enumeration = 2;
+- udev->endp_number_in[usb_endp] = endp_number;
+- udev->endp_number_out[usb_endp] = endp_number;
+- urb->hcpriv = u132;
+- endp->queue_size = 1;
+- endp->queue_last = 0;
+- endp->queue_next = 0;
+- endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+- spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+- u132_endp_queue_work(u132, endp, 0);
+- return 0;
+- }
++ u132_endp_init_kref(u132, endp);
++ u132_endp_get_kref(u132, endp);
++ if (usb_addr == 0) {
++ u8 address = u132->addr[usb_addr].address;
++ struct u132_udev *udev = &u132->udev[address];
++ endp->udev_number = address;
++ endp->usb_addr = usb_addr;
++ endp->usb_endp = usb_endp;
++ endp->input = 1;
++ endp->output = 1;
++ endp->pipetype = usb_pipetype(urb->pipe);
++ u132_udev_init_kref(u132, udev);
++ u132_udev_get_kref(u132, udev);
++ udev->endp_number_in[usb_endp] = endp_number;
++ udev->endp_number_out[usb_endp] = endp_number;
++ urb->hcpriv = u132;
++ endp->queue_size = 1;
++ endp->queue_last = 0;
++ endp->queue_next = 0;
++ endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
++ spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++ u132_endp_queue_work(u132, endp, 0);
++ return 0;
++ } else { /*(usb_addr > 0) */
++ u8 address = u132->addr[usb_addr].address;
++ struct u132_udev *udev = &u132->udev[address];
++ endp->udev_number = address;
++ endp->usb_addr = usb_addr;
++ endp->usb_endp = usb_endp;
++ endp->input = 1;
++ endp->output = 1;
++ endp->pipetype = usb_pipetype(urb->pipe);
++ u132_udev_get_kref(u132, udev);
++ udev->enumeration = 2;
++ udev->endp_number_in[usb_endp] = endp_number;
++ udev->endp_number_out[usb_endp] = endp_number;
++ urb->hcpriv = u132;
++ endp->queue_size = 1;
++ endp->queue_last = 0;
++ endp->queue_next = 0;
++ endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
++ spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++ u132_endp_queue_work(u132, endp, 0);
++ return 0;
++ }
+ }
+
+ static int queue_control_on_old_endpoint(struct u132 *u132,
+ struct urb *urb,
+- struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
+- u8 usb_endp)
+-{
+- if (usb_addr == 0) {
+- if (usb_pipein(urb->pipe)) {
+- urb->hcpriv = u132;
+- if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+- endp->urb_list[ENDP_QUEUE_MASK &
+- endp->queue_last++] = urb;
+- } else {
+- struct u132_urbq *urbq =
+- kmalloc(sizeof(struct u132_urbq),
+- GFP_ATOMIC);
+- if (urbq == NULL) {
+- endp->queue_size -= 1;
+- return -ENOMEM;
+- } else {
+- list_add_tail(&urbq->urb_more,
+- &endp->urb_more);
+- urbq->urb = urb;
+- }
+- }
+- return 0;
+- } else { /* usb_pipeout(urb->pipe) */
+- struct u132_addr *addr = &u132->addr[usb_dev->devnum];
+- int I = MAX_U132_UDEVS;
+- int i = 0;
+- while (--I > 0) {
+- struct u132_udev *udev = &u132->udev[++i];
+- if (udev->usb_device) {
+- continue;
+- } else {
+- udev->enumeration = 1;
+- u132->addr[0].address = i;
+- endp->udev_number = i;
+- udev->udev_number = i;
+- udev->usb_addr = usb_dev->devnum;
+- u132_udev_init_kref(u132, udev);
+- udev->endp_number_in[usb_endp] =
+- endp->endp_number;
+- u132_udev_get_kref(u132, udev);
+- udev->endp_number_out[usb_endp] =
+- endp->endp_number;
+- udev->usb_device = usb_dev;
+- ((u8 *) (urb->setup_packet))[2] =
+- addr->address = i;
+- u132_udev_get_kref(u132, udev);
+- break;
+- }
+- }
+- if (I == 0) {
+- dev_err(&u132->platform_dev->dev, "run out of d"
+- "evice space\n");
+- return -EINVAL;
+- }
+- urb->hcpriv = u132;
+- if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+- endp->urb_list[ENDP_QUEUE_MASK &
+- endp->queue_last++] = urb;
+- } else {
+- struct u132_urbq *urbq =
+- kmalloc(sizeof(struct u132_urbq),
+- GFP_ATOMIC);
+- if (urbq == NULL) {
+- endp->queue_size -= 1;
+- return -ENOMEM;
+- } else {
+- list_add_tail(&urbq->urb_more,
+- &endp->urb_more);
+- urbq->urb = urb;
+- }
+- }
+- return 0;
+- }
+- } else { /*(usb_addr > 0) */
+- u8 address = u132->addr[usb_addr].address;
+- struct u132_udev *udev = &u132->udev[address];
+- urb->hcpriv = u132;
+- if (udev->enumeration == 2) {
+- } else
+- udev->enumeration = 2;
+- if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+- endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
+- urb;
+- } else {
+- struct u132_urbq *urbq =
+- kmalloc(sizeof(struct u132_urbq), GFP_ATOMIC);
+- if (urbq == NULL) {
+- endp->queue_size -= 1;
+- return -ENOMEM;
+- } else {
+- list_add_tail(&urbq->urb_more, &endp->urb_more);
+- urbq->urb = urb;
+- }
+- }
+- return 0;
+- }
++ struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
++ u8 usb_endp)
++{
++ if (usb_addr == 0) {
++ if (usb_pipein(urb->pipe)) {
++ urb->hcpriv = u132;
++ if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
++ endp->urb_list[ENDP_QUEUE_MASK &
++ endp->queue_last++] = urb;
++ } else {
++ struct u132_urbq *urbq =
++ kmalloc(sizeof(struct u132_urbq),
++ GFP_ATOMIC);
++ if (urbq == NULL) {
++ endp->queue_size -= 1;
++ return -ENOMEM;
++ } else {
++ list_add_tail(&urbq->urb_more,
++ &endp->urb_more);
++ urbq->urb = urb;
++ }
++ }
++ return 0;
++ } else { /* usb_pipeout(urb->pipe) */
++ struct u132_addr *addr = &u132->addr[usb_dev->devnum];
++ int I = MAX_U132_UDEVS;
++ int i = 0;
++ while (--I > 0) {
++ struct u132_udev *udev = &u132->udev[++i];
++ if (udev->usb_device) {
++ continue;
++ } else {
++ udev->enumeration = 1;
++ u132->addr[0].address = i;
++ endp->udev_number = i;
++ udev->udev_number = i;
++ udev->usb_addr = usb_dev->devnum;
++ u132_udev_init_kref(u132, udev);
++ udev->endp_number_in[usb_endp] =
++ endp->endp_number;
++ u132_udev_get_kref(u132, udev);
++ udev->endp_number_out[usb_endp] =
++ endp->endp_number;
++ udev->usb_device = usb_dev;
++ ((u8 *) (urb->setup_packet))[2] =
++ addr->address = i;
++ u132_udev_get_kref(u132, udev);
++ break;
++ }
++ }
++ if (I == 0) {
++ dev_err(&u132->platform_dev->dev, "run out of d"
++ "evice space\n");
++ return -EINVAL;
++ }
++ urb->hcpriv = u132;
++ if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
++ endp->urb_list[ENDP_QUEUE_MASK &
++ endp->queue_last++] = urb;
++ } else {
++ struct u132_urbq *urbq =
++ kmalloc(sizeof(struct u132_urbq),
++ GFP_ATOMIC);
++ if (urbq == NULL) {
++ endp->queue_size -= 1;
++ return -ENOMEM;
++ } else {
++ list_add_tail(&urbq->urb_more,
++ &endp->urb_more);
++ urbq->urb = urb;
++ }
++ }
++ return 0;
++ }
++ } else { /*(usb_addr > 0) */
++ u8 address = u132->addr[usb_addr].address;
++ struct u132_udev *udev = &u132->udev[address];
++ urb->hcpriv = u132;
++ if (udev->enumeration != 2)
++ udev->enumeration = 2;
++ if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
++ endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
++ urb;
++ } else {
++ struct u132_urbq *urbq =
++ kmalloc(sizeof(struct u132_urbq), GFP_ATOMIC);
++ if (urbq == NULL) {
++ endp->queue_size -= 1;
++ return -ENOMEM;
++ } else {
++ list_add_tail(&urbq->urb_more, &endp->urb_more);
++ urbq->urb = urb;
++ }
++ }
++ return 0;
++ }
+ }
+
+ static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+ gfp_t mem_flags)
+ {
+- struct u132 *u132 = hcd_to_u132(hcd);
+- if (irqs_disabled()) {
+- if (__GFP_WAIT & mem_flags) {
+- printk(KERN_ERR "invalid context for function that migh"
+- "t sleep\n");
+- return -EINVAL;
+- }
+- }
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- return -ENODEV;
+- } else if (u132->going > 0) {
++ struct u132 *u132 = hcd_to_u132(hcd);
++ if (irqs_disabled()) {
++ if (__GFP_WAIT & mem_flags) {
++ printk(KERN_ERR "invalid context for function that migh"
++ "t sleep\n");
++ return -EINVAL;
++ }
++ }
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++ , u132->going);
++ return -ENODEV;
++ } else if (u132->going > 0) {
+ dev_err(&u132->platform_dev->dev, "device is being removed "
+ "urb=%p\n", urb);
+- return -ESHUTDOWN;
+- } else {
+- u8 usb_addr = usb_pipedevice(urb->pipe);
+- u8 usb_endp = usb_pipeendpoint(urb->pipe);
+- struct usb_device *usb_dev = urb->dev;
+- if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
+- u8 address = u132->addr[usb_addr].address;
+- struct u132_udev *udev = &u132->udev[address];
+- struct u132_endp *endp = urb->ep->hcpriv;
+- urb->actual_length = 0;
+- if (endp) {
+- unsigned long irqs;
+- int retval;
+- spin_lock_irqsave(&endp->queue_lock.slock,
+- irqs);
++ return -ESHUTDOWN;
++ } else {
++ u8 usb_addr = usb_pipedevice(urb->pipe);
++ u8 usb_endp = usb_pipeendpoint(urb->pipe);
++ struct usb_device *usb_dev = urb->dev;
++ if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
++ u8 address = u132->addr[usb_addr].address;
++ struct u132_udev *udev = &u132->udev[address];
++ struct u132_endp *endp = urb->ep->hcpriv;
++ urb->actual_length = 0;
++ if (endp) {
++ unsigned long irqs;
++ int retval;
++ spin_lock_irqsave(&endp->queue_lock.slock,
++ irqs);
+ retval = usb_hcd_link_urb_to_ep(hcd, urb);
+ if (retval == 0) {
+ retval = queue_int_on_old_endpoint(
+@@ -2303,39 +2288,39 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+ address);
+ if (retval)
+ usb_hcd_unlink_urb_from_ep(
+- hcd, urb);
++ hcd, urb);
+ }
+- spin_unlock_irqrestore(&endp->queue_lock.slock,
+- irqs);
+- if (retval) {
+- return retval;
+- } else {
+- u132_endp_queue_work(u132, endp,
+- msecs_to_jiffies(urb->interval))
+- ;
+- return 0;
+- }
+- } else if (u132->num_endpoints == MAX_U132_ENDPS) {
+- return -EINVAL;
+- } else { /*(endp == NULL) */
+- return create_endpoint_and_queue_int(u132, udev,
++ spin_unlock_irqrestore(&endp->queue_lock.slock,
++ irqs);
++ if (retval) {
++ return retval;
++ } else {
++ u132_endp_queue_work(u132, endp,
++ msecs_to_jiffies(urb->interval))
++ ;
++ return 0;
++ }
++ } else if (u132->num_endpoints == MAX_U132_ENDPS) {
++ return -EINVAL;
++ } else { /*(endp == NULL) */
++ return create_endpoint_and_queue_int(u132, udev,
+ urb, usb_dev, usb_addr,
+ usb_endp, address, mem_flags);
+- }
+- } else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+- dev_err(&u132->platform_dev->dev, "the hardware does no"
+- "t support PIPE_ISOCHRONOUS\n");
+- return -EINVAL;
+- } else if (usb_pipetype(urb->pipe) == PIPE_BULK) {
+- u8 address = u132->addr[usb_addr].address;
+- struct u132_udev *udev = &u132->udev[address];
+- struct u132_endp *endp = urb->ep->hcpriv;
+- urb->actual_length = 0;
+- if (endp) {
+- unsigned long irqs;
+- int retval;
+- spin_lock_irqsave(&endp->queue_lock.slock,
+- irqs);
++ }
++ } else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
++ dev_err(&u132->platform_dev->dev, "the hardware does no"
++ "t support PIPE_ISOCHRONOUS\n");
++ return -EINVAL;
++ } else if (usb_pipetype(urb->pipe) == PIPE_BULK) {
++ u8 address = u132->addr[usb_addr].address;
++ struct u132_udev *udev = &u132->udev[address];
++ struct u132_endp *endp = urb->ep->hcpriv;
++ urb->actual_length = 0;
++ if (endp) {
++ unsigned long irqs;
++ int retval;
++ spin_lock_irqsave(&endp->queue_lock.slock,
++ irqs);
+ retval = usb_hcd_link_urb_to_ep(hcd, urb);
+ if (retval == 0) {
+ retval = queue_bulk_on_old_endpoint(
+@@ -2345,46 +2330,46 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+ address);
+ if (retval)
+ usb_hcd_unlink_urb_from_ep(
+- hcd, urb);
++ hcd, urb);
++ }
++ spin_unlock_irqrestore(&endp->queue_lock.slock,
++ irqs);
++ if (retval) {
++ return retval;
++ } else {
++ u132_endp_queue_work(u132, endp, 0);
++ return 0;
+ }
+- spin_unlock_irqrestore(&endp->queue_lock.slock,
+- irqs);
+- if (retval) {
+- return retval;
+- } else {
+- u132_endp_queue_work(u132, endp, 0);
+- return 0;
+- }
+- } else if (u132->num_endpoints == MAX_U132_ENDPS) {
+- return -EINVAL;
+- } else
+- return create_endpoint_and_queue_bulk(u132,
++ } else if (u132->num_endpoints == MAX_U132_ENDPS) {
++ return -EINVAL;
++ } else
++ return create_endpoint_and_queue_bulk(u132,
+ udev, urb, usb_dev, usb_addr,
+- usb_endp, address, mem_flags);
+- } else {
+- struct u132_endp *endp = urb->ep->hcpriv;
+- u16 urb_size = 8;
+- u8 *b = urb->setup_packet;
+- int i = 0;
+- char data[30 *3 + 4];
+- char *d = data;
+- int m = (sizeof(data) - 1) / 3;
+- int l = 0;
+- data[0] = 0;
+- while (urb_size-- > 0) {
+- if (i > m) {
+- } else if (i++ < m) {
+- int w = sprintf(d, " %02X", *b++);
+- d += w;
+- l += w;
+- } else
+- d += sprintf(d, " ..");
+- }
+- if (endp) {
+- unsigned long irqs;
+- int retval;
+- spin_lock_irqsave(&endp->queue_lock.slock,
+- irqs);
++ usb_endp, address, mem_flags);
++ } else {
++ struct u132_endp *endp = urb->ep->hcpriv;
++ u16 urb_size = 8;
++ u8 *b = urb->setup_packet;
++ int i = 0;
++ char data[30 * 3 + 4];
++ char *d = data;
++ int m = (sizeof(data) - 1) / 3;
++ int l = 0;
++ data[0] = 0;
++ while (urb_size-- > 0) {
++ if (i > m) {
++ } else if (i++ < m) {
++ int w = sprintf(d, " %02X", *b++);
++ d += w;
++ l += w;
++ } else
++ d += sprintf(d, " ..");
++ }
++ if (endp) {
++ unsigned long irqs;
++ int retval;
++ spin_lock_irqsave(&endp->queue_lock.slock,
++ irqs);
+ retval = usb_hcd_link_urb_to_ep(hcd, urb);
+ if (retval == 0) {
+ retval = queue_control_on_old_endpoint(
+@@ -2395,267 +2380,267 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+ usb_hcd_unlink_urb_from_ep(
+ hcd, urb);
+ }
+- spin_unlock_irqrestore(&endp->queue_lock.slock,
+- irqs);
+- if (retval) {
+- return retval;
+- } else {
+- u132_endp_queue_work(u132, endp, 0);
+- return 0;
+- }
+- } else if (u132->num_endpoints == MAX_U132_ENDPS) {
+- return -EINVAL;
+- } else
+- return create_endpoint_and_queue_control(u132,
++ spin_unlock_irqrestore(&endp->queue_lock.slock,
++ irqs);
++ if (retval) {
++ return retval;
++ } else {
++ u132_endp_queue_work(u132, endp, 0);
++ return 0;
++ }
++ } else if (u132->num_endpoints == MAX_U132_ENDPS) {
++ return -EINVAL;
++ } else
++ return create_endpoint_and_queue_control(u132,
+ urb, usb_dev, usb_addr, usb_endp,
+- mem_flags);
+- }
+- }
++ mem_flags);
++ }
++ }
+ }
+
+ static int dequeue_from_overflow_chain(struct u132 *u132,
+- struct u132_endp *endp, struct urb *urb)
+-{
+- struct list_head *scan;
+- struct list_head *head = &endp->urb_more;
+- list_for_each(scan, head) {
+- struct u132_urbq *urbq = list_entry(scan, struct u132_urbq,
+- urb_more);
+- if (urbq->urb == urb) {
+- struct usb_hcd *hcd = u132_to_hcd(u132);
+- list_del(scan);
+- endp->queue_size -= 1;
+- urb->error_count = 0;
++ struct u132_endp *endp, struct urb *urb)
++{
++ struct list_head *scan;
++ struct list_head *head = &endp->urb_more;
++ list_for_each(scan, head) {
++ struct u132_urbq *urbq = list_entry(scan, struct u132_urbq,
++ urb_more);
++ if (urbq->urb == urb) {
++ struct usb_hcd *hcd = u132_to_hcd(u132);
++ list_del(scan);
++ endp->queue_size -= 1;
++ urb->error_count = 0;
+ usb_hcd_giveback_urb(hcd, urb, 0);
+- return 0;
+- } else
+- continue;
+- }
+- dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]=%p ring"
+- "[%d] %c%c usb_endp=%d usb_addr=%d size=%d next=%04X last=%04X"
+- "\n", urb, endp->endp_number, endp, endp->ring->number,
+- endp->input ? 'I' : ' ', endp->output ? 'O' : ' ',
+- endp->usb_endp, endp->usb_addr, endp->queue_size,
+- endp->queue_next, endp->queue_last);
+- return -EINVAL;
++ return 0;
++ } else
++ continue;
++ }
++ dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]=%p ring"
++ "[%d] %c%c usb_endp=%d usb_addr=%d size=%d next=%04X last=%04X"
++ "\n", urb, endp->endp_number, endp, endp->ring->number,
++ endp->input ? 'I' : ' ', endp->output ? 'O' : ' ',
++ endp->usb_endp, endp->usb_addr, endp->queue_size,
++ endp->queue_next, endp->queue_last);
++ return -EINVAL;
+ }
+
+ static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
+ struct urb *urb, int status)
+ {
+- unsigned long irqs;
++ unsigned long irqs;
+ int rc;
+
+- spin_lock_irqsave(&endp->queue_lock.slock, irqs);
++ spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+ rc = usb_hcd_check_unlink_urb(u132_to_hcd(u132), urb, status);
+ if (rc) {
+ spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+ return rc;
+ }
+- if (endp->queue_size == 0) {
+- dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]"
+- "=%p ring[%d] %c%c usb_endp=%d usb_addr=%d\n", urb,
+- endp->endp_number, endp, endp->ring->number,
+- endp->input ? 'I' : ' ', endp->output ? 'O' : ' ',
+- endp->usb_endp, endp->usb_addr);
+- spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+- return -EINVAL;
+- }
+- if (urb == endp->urb_list[ENDP_QUEUE_MASK & endp->queue_next]) {
+- if (endp->active) {
+- endp->dequeueing = 1;
+- endp->edset_flush = 1;
+- u132_endp_queue_work(u132, endp, 0);
+- spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+- return 0;
+- } else {
+- spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++ if (endp->queue_size == 0) {
++ dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]"
++ "=%p ring[%d] %c%c usb_endp=%d usb_addr=%d\n", urb,
++ endp->endp_number, endp, endp->ring->number,
++ endp->input ? 'I' : ' ', endp->output ? 'O' : ' ',
++ endp->usb_endp, endp->usb_addr);
++ spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++ return -EINVAL;
++ }
++ if (urb == endp->urb_list[ENDP_QUEUE_MASK & endp->queue_next]) {
++ if (endp->active) {
++ endp->dequeueing = 1;
++ endp->edset_flush = 1;
++ u132_endp_queue_work(u132, endp, 0);
++ spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++ return 0;
++ } else {
++ spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+ u132_hcd_abandon_urb(u132, endp, urb, status);
+- return 0;
+- }
+- } else {
+- u16 queue_list = 0;
+- u16 queue_size = endp->queue_size;
+- u16 queue_scan = endp->queue_next;
+- struct urb **urb_slot = NULL;
+- while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) {
+- if (urb == endp->urb_list[ENDP_QUEUE_MASK &
+- ++queue_scan]) {
+- urb_slot = &endp->urb_list[ENDP_QUEUE_MASK &
+- queue_scan];
+- break;
+- } else
+- continue;
+- }
+- while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) {
+- *urb_slot = endp->urb_list[ENDP_QUEUE_MASK &
+- ++queue_scan];
+- urb_slot = &endp->urb_list[ENDP_QUEUE_MASK &
+- queue_scan];
+- }
+- if (urb_slot) {
+- struct usb_hcd *hcd = u132_to_hcd(u132);
++ return 0;
++ }
++ } else {
++ u16 queue_list = 0;
++ u16 queue_size = endp->queue_size;
++ u16 queue_scan = endp->queue_next;
++ struct urb **urb_slot = NULL;
++ while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) {
++ if (urb == endp->urb_list[ENDP_QUEUE_MASK &
++ ++queue_scan]) {
++ urb_slot = &endp->urb_list[ENDP_QUEUE_MASK &
++ queue_scan];
++ break;
++ } else
++ continue;
++ }
++ while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) {
++ *urb_slot = endp->urb_list[ENDP_QUEUE_MASK &
++ ++queue_scan];
++ urb_slot = &endp->urb_list[ENDP_QUEUE_MASK &
++ queue_scan];
++ }
++ if (urb_slot) {
++ struct usb_hcd *hcd = u132_to_hcd(u132);
+
+ usb_hcd_unlink_urb_from_ep(hcd, urb);
+- endp->queue_size -= 1;
+- if (list_empty(&endp->urb_more)) {
+- spin_unlock_irqrestore(&endp->queue_lock.slock,
+- irqs);
+- } else {
+- struct list_head *next = endp->urb_more.next;
+- struct u132_urbq *urbq = list_entry(next,
+- struct u132_urbq, urb_more);
+- list_del(next);
+- *urb_slot = urbq->urb;
+- spin_unlock_irqrestore(&endp->queue_lock.slock,
+- irqs);
+- kfree(urbq);
+- } urb->error_count = 0;
++ endp->queue_size -= 1;
++ if (list_empty(&endp->urb_more)) {
++ spin_unlock_irqrestore(&endp->queue_lock.slock,
++ irqs);
++ } else {
++ struct list_head *next = endp->urb_more.next;
++ struct u132_urbq *urbq = list_entry(next,
++ struct u132_urbq, urb_more);
++ list_del(next);
++ *urb_slot = urbq->urb;
++ spin_unlock_irqrestore(&endp->queue_lock.slock,
++ irqs);
++ kfree(urbq);
++ } urb->error_count = 0;
+ usb_hcd_giveback_urb(hcd, urb, status);
+- return 0;
+- } else if (list_empty(&endp->urb_more)) {
+- dev_err(&u132->platform_dev->dev, "urb=%p not found in "
+- "endp[%d]=%p ring[%d] %c%c usb_endp=%d usb_addr"
+- "=%d size=%d next=%04X last=%04X\n", urb,
+- endp->endp_number, endp, endp->ring->number,
+- endp->input ? 'I' : ' ',
+- endp->output ? 'O' : ' ', endp->usb_endp,
+- endp->usb_addr, endp->queue_size,
+- endp->queue_next, endp->queue_last);
+- spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+- return -EINVAL;
+- } else {
++ return 0;
++ } else if (list_empty(&endp->urb_more)) {
++ dev_err(&u132->platform_dev->dev, "urb=%p not found in "
++ "endp[%d]=%p ring[%d] %c%c usb_endp=%d usb_addr"
++ "=%d size=%d next=%04X last=%04X\n", urb,
++ endp->endp_number, endp, endp->ring->number,
++ endp->input ? 'I' : ' ',
++ endp->output ? 'O' : ' ', endp->usb_endp,
++ endp->usb_addr, endp->queue_size,
++ endp->queue_next, endp->queue_last);
++ spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++ return -EINVAL;
++ } else {
+ int retval;
+
+ usb_hcd_unlink_urb_from_ep(u132_to_hcd(u132), urb);
+ retval = dequeue_from_overflow_chain(u132, endp,
+- urb);
+- spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+- return retval;
+- }
+- }
++ urb);
++ spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
++ return retval;
++ }
++ }
+ }
+
+ static int u132_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+ {
+- struct u132 *u132 = hcd_to_u132(hcd);
+- if (u132->going > 2) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- return -ENODEV;
+- } else {
+- u8 usb_addr = usb_pipedevice(urb->pipe);
+- u8 usb_endp = usb_pipeendpoint(urb->pipe);
+- u8 address = u132->addr[usb_addr].address;
+- struct u132_udev *udev = &u132->udev[address];
+- if (usb_pipein(urb->pipe)) {
+- u8 endp_number = udev->endp_number_in[usb_endp];
+- struct u132_endp *endp = u132->endp[endp_number - 1];
+- return u132_endp_urb_dequeue(u132, endp, urb, status);
+- } else {
+- u8 endp_number = udev->endp_number_out[usb_endp];
+- struct u132_endp *endp = u132->endp[endp_number - 1];
+- return u132_endp_urb_dequeue(u132, endp, urb, status);
+- }
+- }
++ struct u132 *u132 = hcd_to_u132(hcd);
++ if (u132->going > 2) {
++ dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++ , u132->going);
++ return -ENODEV;
++ } else {
++ u8 usb_addr = usb_pipedevice(urb->pipe);
++ u8 usb_endp = usb_pipeendpoint(urb->pipe);
++ u8 address = u132->addr[usb_addr].address;
++ struct u132_udev *udev = &u132->udev[address];
++ if (usb_pipein(urb->pipe)) {
++ u8 endp_number = udev->endp_number_in[usb_endp];
++ struct u132_endp *endp = u132->endp[endp_number - 1];
++ return u132_endp_urb_dequeue(u132, endp, urb, status);
++ } else {
++ u8 endp_number = udev->endp_number_out[usb_endp];
++ struct u132_endp *endp = u132->endp[endp_number - 1];
++ return u132_endp_urb_dequeue(u132, endp, urb, status);
++ }
++ }
+ }
+
+ static void u132_endpoint_disable(struct usb_hcd *hcd,
+- struct usb_host_endpoint *hep)
+-{
+- struct u132 *u132 = hcd_to_u132(hcd);
+- if (u132->going > 2) {
+- dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p hep=%p"
+- ") has been removed %d\n", u132, hcd, hep,
+- u132->going);
+- } else {
+- struct u132_endp *endp = hep->hcpriv;
+- if (endp)
+- u132_endp_put_kref(u132, endp);
+- }
++ struct usb_host_endpoint *hep)
++{
++ struct u132 *u132 = hcd_to_u132(hcd);
++ if (u132->going > 2) {
++ dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p hep=%p"
++ ") has been removed %d\n", u132, hcd, hep,
++ u132->going);
++ } else {
++ struct u132_endp *endp = hep->hcpriv;
++ if (endp)
++ u132_endp_put_kref(u132, endp);
++ }
+ }
+
+ static int u132_get_frame(struct usb_hcd *hcd)
+ {
+- struct u132 *u132 = hcd_to_u132(hcd);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- return -ENODEV;
+- } else if (u132->going > 0) {
+- dev_err(&u132->platform_dev->dev, "device is being removed\n");
+- return -ESHUTDOWN;
+- } else {
+- int frame = 0;
+- dev_err(&u132->platform_dev->dev, "TODO: u132_get_frame\n");
+- msleep(100);
+- return frame;
+- }
++ struct u132 *u132 = hcd_to_u132(hcd);
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++ , u132->going);
++ return -ENODEV;
++ } else if (u132->going > 0) {
++ dev_err(&u132->platform_dev->dev, "device is being removed\n");
++ return -ESHUTDOWN;
++ } else {
++ int frame = 0;
++ dev_err(&u132->platform_dev->dev, "TODO: u132_get_frame\n");
++ msleep(100);
++ return frame;
++ }
+ }
+
+ static int u132_roothub_descriptor(struct u132 *u132,
+- struct usb_hub_descriptor *desc)
+-{
+- int retval;
+- u16 temp;
+- u32 rh_a = -1;
+- u32 rh_b = -1;
+- retval = u132_read_pcimem(u132, roothub.a, &rh_a);
+- if (retval)
+- return retval;
+- desc->bDescriptorType = 0x29;
+- desc->bPwrOn2PwrGood = (rh_a & RH_A_POTPGT) >> 24;
+- desc->bHubContrCurrent = 0;
+- desc->bNbrPorts = u132->num_ports;
+- temp = 1 + (u132->num_ports / 8);
+- desc->bDescLength = 7 + 2 *temp;
+- temp = 0;
+- if (rh_a & RH_A_NPS)
+- temp |= 0x0002;
+- if (rh_a & RH_A_PSM)
+- temp |= 0x0001;
+- if (rh_a & RH_A_NOCP) {
+- temp |= 0x0010;
+- } else if (rh_a & RH_A_OCPM)
+- temp |= 0x0008;
+- desc->wHubCharacteristics = cpu_to_le16(temp);
+- retval = u132_read_pcimem(u132, roothub.b, &rh_b);
+- if (retval)
+- return retval;
+- memset(desc->bitmap, 0xff, sizeof(desc->bitmap));
+- desc->bitmap[0] = rh_b & RH_B_DR;
+- if (u132->num_ports > 7) {
+- desc->bitmap[1] = (rh_b & RH_B_DR) >> 8;
+- desc->bitmap[2] = 0xff;
+- } else
+- desc->bitmap[1] = 0xff;
+- return 0;
++ struct usb_hub_descriptor *desc)
++{
++ int retval;
++ u16 temp;
++ u32 rh_a = -1;
++ u32 rh_b = -1;
++ retval = u132_read_pcimem(u132, roothub.a, &rh_a);
++ if (retval)
++ return retval;
++ desc->bDescriptorType = 0x29;
++ desc->bPwrOn2PwrGood = (rh_a & RH_A_POTPGT) >> 24;
++ desc->bHubContrCurrent = 0;
++ desc->bNbrPorts = u132->num_ports;
++ temp = 1 + (u132->num_ports / 8);
++ desc->bDescLength = 7 + 2 * temp;
++ temp = 0;
++ if (rh_a & RH_A_NPS)
++ temp |= 0x0002;
++ if (rh_a & RH_A_PSM)
++ temp |= 0x0001;
++ if (rh_a & RH_A_NOCP)
++ temp |= 0x0010;
++ else if (rh_a & RH_A_OCPM)
++ temp |= 0x0008;
++ desc->wHubCharacteristics = cpu_to_le16(temp);
++ retval = u132_read_pcimem(u132, roothub.b, &rh_b);
++ if (retval)
++ return retval;
++ memset(desc->bitmap, 0xff, sizeof(desc->bitmap));
++ desc->bitmap[0] = rh_b & RH_B_DR;
++ if (u132->num_ports > 7) {
++ desc->bitmap[1] = (rh_b & RH_B_DR) >> 8;
++ desc->bitmap[2] = 0xff;
++ } else
++ desc->bitmap[1] = 0xff;
++ return 0;
+ }
+
+ static int u132_roothub_status(struct u132 *u132, __le32 *desc)
+ {
+- u32 rh_status = -1;
+- int ret_status = u132_read_pcimem(u132, roothub.status, &rh_status);
+- *desc = cpu_to_le32(rh_status);
+- return ret_status;
++ u32 rh_status = -1;
++ int ret_status = u132_read_pcimem(u132, roothub.status, &rh_status);
++ *desc = cpu_to_le32(rh_status);
++ return ret_status;
+ }
+
+ static int u132_roothub_portstatus(struct u132 *u132, __le32 *desc, u16 wIndex)
+ {
+- if (wIndex == 0 || wIndex > u132->num_ports) {
+- return -EINVAL;
+- } else {
+- int port = wIndex - 1;
+- u32 rh_portstatus = -1;
+- int ret_portstatus = u132_read_pcimem(u132,
+- roothub.portstatus[port], &rh_portstatus);
+- *desc = cpu_to_le32(rh_portstatus);
+- if (*(u16 *) (desc + 2)) {
+- dev_info(&u132->platform_dev->dev, "Port %d Status Chan"
+- "ge = %08X\n", port, *desc);
+- }
+- return ret_portstatus;
+- }
++ if (wIndex == 0 || wIndex > u132->num_ports) {
++ return -EINVAL;
++ } else {
++ int port = wIndex - 1;
++ u32 rh_portstatus = -1;
++ int ret_portstatus = u132_read_pcimem(u132,
++ roothub.portstatus[port], &rh_portstatus);
++ *desc = cpu_to_le32(rh_portstatus);
++ if (*(u16 *) (desc + 2)) {
++ dev_info(&u132->platform_dev->dev, "Port %d Status Chan"
++ "ge = %08X\n", port, *desc);
++ }
++ return ret_portstatus;
++ }
+ }
+
+
+@@ -2666,381 +2651,340 @@ static int u132_roothub_portstatus(struct u132 *u132, __le32 *desc, u16 wIndex)
+ #define tick_before(t1, t2) ((s16)(((s16)(t1))-((s16)(t2))) < 0)
+ static int u132_roothub_portreset(struct u132 *u132, int port_index)
+ {
+- int retval;
+- u32 fmnumber;
+- u16 now;
+- u16 reset_done;
+- retval = u132_read_pcimem(u132, fmnumber, &fmnumber);
+- if (retval)
+- return retval;
+- now = fmnumber;
+- reset_done = now + PORT_RESET_MSEC;
+- do {
+- u32 portstat;
+- do {
+- retval = u132_read_pcimem(u132,
+- roothub.portstatus[port_index], &portstat);
+- if (retval)
+- return retval;
+- if (RH_PS_PRS & portstat) {
+- continue;
+- } else
+- break;
+- } while (tick_before(now, reset_done));
+- if (RH_PS_PRS & portstat)
+- return -ENODEV;
+- if (RH_PS_CCS & portstat) {
+- if (RH_PS_PRSC & portstat) {
+- retval = u132_write_pcimem(u132,
+- roothub.portstatus[port_index],
+- RH_PS_PRSC);
+- if (retval)
+- return retval;
+- }
+- } else
+- break; /* start the next reset,
+- sleep till it's probably done */
+- retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
+- RH_PS_PRS);
+- if (retval)
+- return retval;
+- msleep(PORT_RESET_HW_MSEC);
+- retval = u132_read_pcimem(u132, fmnumber, &fmnumber);
+- if (retval)
+- return retval;
+- now = fmnumber;
+- } while (tick_before(now, reset_done));
+- return 0;
++ int retval;
++ u32 fmnumber;
++ u16 now;
++ u16 reset_done;
++ retval = u132_read_pcimem(u132, fmnumber, &fmnumber);
++ if (retval)
++ return retval;
++ now = fmnumber;
++ reset_done = now + PORT_RESET_MSEC;
++ do {
++ u32 portstat;
++ do {
++ retval = u132_read_pcimem(u132,
++ roothub.portstatus[port_index], &portstat);
++ if (retval)
++ return retval;
++ if (RH_PS_PRS & portstat)
++ continue;
++ else
++ break;
++ } while (tick_before(now, reset_done));
++ if (RH_PS_PRS & portstat)
++ return -ENODEV;
++ if (RH_PS_CCS & portstat) {
++ if (RH_PS_PRSC & portstat) {
++ retval = u132_write_pcimem(u132,
++ roothub.portstatus[port_index],
++ RH_PS_PRSC);
++ if (retval)
++ return retval;
++ }
++ } else
++ break; /* start the next reset,
++ sleep till it's probably done */
++ retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
++ RH_PS_PRS);
++ if (retval)
++ return retval;
++ msleep(PORT_RESET_HW_MSEC);
++ retval = u132_read_pcimem(u132, fmnumber, &fmnumber);
++ if (retval)
++ return retval;
++ now = fmnumber;
++ } while (tick_before(now, reset_done));
++ return 0;
+ }
+
+ static int u132_roothub_setportfeature(struct u132 *u132, u16 wValue,
+- u16 wIndex)
+-{
+- if (wIndex == 0 || wIndex > u132->num_ports) {
+- return -EINVAL;
+- } else {
+- int retval;
+- int port_index = wIndex - 1;
+- struct u132_port *port = &u132->port[port_index];
+- port->Status &= ~(1 << wValue);
+- switch (wValue) {
+- case USB_PORT_FEAT_SUSPEND:
+- retval = u132_write_pcimem(u132,
+- roothub.portstatus[port_index], RH_PS_PSS);
+- if (retval)
+- return retval;
+- return 0;
+- case USB_PORT_FEAT_POWER:
+- retval = u132_write_pcimem(u132,
+- roothub.portstatus[port_index], RH_PS_PPS);
+- if (retval)
+- return retval;
+- return 0;
+- case USB_PORT_FEAT_RESET:
+- retval = u132_roothub_portreset(u132, port_index);
+- if (retval)
+- return retval;
+- return 0;
+- default:
+- return -EPIPE;
+- }
+- }
++ u16 wIndex)
++{
++ if (wIndex == 0 || wIndex > u132->num_ports) {
++ return -EINVAL;
++ } else {
++ int retval;
++ int port_index = wIndex - 1;
++ struct u132_port *port = &u132->port[port_index];
++ port->Status &= ~(1 << wValue);
++ switch (wValue) {
++ case USB_PORT_FEAT_SUSPEND:
++ retval = u132_write_pcimem(u132,
++ roothub.portstatus[port_index], RH_PS_PSS);
++ if (retval)
++ return retval;
++ return 0;
++ case USB_PORT_FEAT_POWER:
++ retval = u132_write_pcimem(u132,
++ roothub.portstatus[port_index], RH_PS_PPS);
++ if (retval)
++ return retval;
++ return 0;
++ case USB_PORT_FEAT_RESET:
++ retval = u132_roothub_portreset(u132, port_index);
++ if (retval)
++ return retval;
++ return 0;
++ default:
++ return -EPIPE;
++ }
++ }
+ }
+
+ static int u132_roothub_clearportfeature(struct u132 *u132, u16 wValue,
+- u16 wIndex)
+-{
+- if (wIndex == 0 || wIndex > u132->num_ports) {
+- return -EINVAL;
+- } else {
+- int port_index = wIndex - 1;
+- u32 temp;
+- int retval;
+- struct u132_port *port = &u132->port[port_index];
+- port->Status &= ~(1 << wValue);
+- switch (wValue) {
+- case USB_PORT_FEAT_ENABLE:
+- temp = RH_PS_CCS;
+- break;
+- case USB_PORT_FEAT_C_ENABLE:
+- temp = RH_PS_PESC;
+- break;
+- case USB_PORT_FEAT_SUSPEND:
+- temp = RH_PS_POCI;
+- if ((u132->hc_control & OHCI_CTRL_HCFS)
+- != OHCI_USB_OPER) {
+- dev_err(&u132->platform_dev->dev, "TODO resume_"
+- "root_hub\n");
+- }
+- break;
+- case USB_PORT_FEAT_C_SUSPEND:
+- temp = RH_PS_PSSC;
+- break;
+- case USB_PORT_FEAT_POWER:
+- temp = RH_PS_LSDA;
+- break;
+- case USB_PORT_FEAT_C_CONNECTION:
+- temp = RH_PS_CSC;
+- break;
+- case USB_PORT_FEAT_C_OVER_CURRENT:
+- temp = RH_PS_OCIC;
+- break;
+- case USB_PORT_FEAT_C_RESET:
+- temp = RH_PS_PRSC;
+- break;
+- default:
+- return -EPIPE;
+- }
+- retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
+- temp);
+- if (retval)
+- return retval;
+- return 0;
+- }
++ u16 wIndex)
++{
++ if (wIndex == 0 || wIndex > u132->num_ports) {
++ return -EINVAL;
++ } else {
++ int port_index = wIndex - 1;
++ u32 temp;
++ int retval;
++ struct u132_port *port = &u132->port[port_index];
++ port->Status &= ~(1 << wValue);
++ switch (wValue) {
++ case USB_PORT_FEAT_ENABLE:
++ temp = RH_PS_CCS;
++ break;
++ case USB_PORT_FEAT_C_ENABLE:
++ temp = RH_PS_PESC;
++ break;
++ case USB_PORT_FEAT_SUSPEND:
++ temp = RH_PS_POCI;
++ if ((u132->hc_control & OHCI_CTRL_HCFS)
++ != OHCI_USB_OPER) {
++ dev_err(&u132->platform_dev->dev, "TODO resume_"
++ "root_hub\n");
++ }
++ break;
++ case USB_PORT_FEAT_C_SUSPEND:
++ temp = RH_PS_PSSC;
++ break;
++ case USB_PORT_FEAT_POWER:
++ temp = RH_PS_LSDA;
++ break;
++ case USB_PORT_FEAT_C_CONNECTION:
++ temp = RH_PS_CSC;
++ break;
++ case USB_PORT_FEAT_C_OVER_CURRENT:
++ temp = RH_PS_OCIC;
++ break;
++ case USB_PORT_FEAT_C_RESET:
++ temp = RH_PS_PRSC;
++ break;
++ default:
++ return -EPIPE;
++ }
++ retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
++ temp);
++ if (retval)
++ return retval;
++ return 0;
++ }
+ }
+
+
+ /* the virtual root hub timer IRQ checks for hub status*/
+ static int u132_hub_status_data(struct usb_hcd *hcd, char *buf)
+ {
+- struct u132 *u132 = hcd_to_u132(hcd);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device hcd=%p has been remov"
+- "ed %d\n", hcd, u132->going);
+- return -ENODEV;
+- } else if (u132->going > 0) {
+- dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
+- "ed\n", hcd);
+- return -ESHUTDOWN;
+- } else {
+- int i, changed = 0, length = 1;
+- if (u132->flags & OHCI_QUIRK_AMD756) {
+- if ((u132->hc_roothub_a & RH_A_NDP) > MAX_ROOT_PORTS) {
+- dev_err(&u132->platform_dev->dev, "bogus NDP, r"
+- "ereads as NDP=%d\n",
+- u132->hc_roothub_a & RH_A_NDP);
+- goto done;
+- }
+- }
+- if (u132->hc_roothub_status & (RH_HS_LPSC | RH_HS_OCIC)) {
+- buf[0] = changed = 1;
+- } else
+- buf[0] = 0;
+- if (u132->num_ports > 7) {
+- buf[1] = 0;
+- length++;
+- }
+- for (i = 0; i < u132->num_ports; i++) {
+- if (u132->hc_roothub_portstatus[i] & (RH_PS_CSC |
+- RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC |
+- RH_PS_PRSC)) {
+- changed = 1;
+- if (i < 7) {
+- buf[0] |= 1 << (i + 1);
+- } else
+- buf[1] |= 1 << (i - 7);
+- continue;
+- }
+- if (!(u132->hc_roothub_portstatus[i] & RH_PS_CCS)) {
+- continue;
+- }
+- if ((u132->hc_roothub_portstatus[i] & RH_PS_PSS)) {
+- continue;
+- }
+- }
+- done:return changed ? length : 0;
+- }
++ struct u132 *u132 = hcd_to_u132(hcd);
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "device hcd=%p has been remov"
++ "ed %d\n", hcd, u132->going);
++ return -ENODEV;
++ } else if (u132->going > 0) {
++ dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
++ "ed\n", hcd);
++ return -ESHUTDOWN;
++ } else {
++ int i, changed = 0, length = 1;
++ if (u132->flags & OHCI_QUIRK_AMD756) {
++ if ((u132->hc_roothub_a & RH_A_NDP) > MAX_ROOT_PORTS) {
++ dev_err(&u132->platform_dev->dev, "bogus NDP, r"
++ "ereads as NDP=%d\n",
++ u132->hc_roothub_a & RH_A_NDP);
++ goto done;
++ }
++ }
++ if (u132->hc_roothub_status & (RH_HS_LPSC | RH_HS_OCIC))
++ buf[0] = changed = 1;
++ else
++ buf[0] = 0;
++ if (u132->num_ports > 7) {
++ buf[1] = 0;
++ length++;
++ }
++ for (i = 0; i < u132->num_ports; i++) {
++ if (u132->hc_roothub_portstatus[i] & (RH_PS_CSC |
++ RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC |
++ RH_PS_PRSC)) {
++ changed = 1;
++ if (i < 7)
++ buf[0] |= 1 << (i + 1);
++ else
++ buf[1] |= 1 << (i - 7);
++ continue;
++ }
++ if (!(u132->hc_roothub_portstatus[i] & RH_PS_CCS))
++ continue;
++
++ if ((u132->hc_roothub_portstatus[i] & RH_PS_PSS))
++ continue;
++ }
++done:
++ return changed ? length : 0;
++ }
+ }
+
+ static int u132_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+- u16 wIndex, char *buf, u16 wLength)
+-{
+- struct u132 *u132 = hcd_to_u132(hcd);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- return -ENODEV;
+- } else if (u132->going > 0) {
+- dev_err(&u132->platform_dev->dev, "device is being removed\n");
+- return -ESHUTDOWN;
+- } else {
+- int retval = 0;
+- mutex_lock(&u132->sw_lock);
+- switch (typeReq) {
+- case ClearHubFeature:
+- switch (wValue) {
+- case C_HUB_OVER_CURRENT:
+- case C_HUB_LOCAL_POWER:
+- break;
+- default:
+- goto stall;
+- }
+- break;
+- case SetHubFeature:
+- switch (wValue) {
+- case C_HUB_OVER_CURRENT:
+- case C_HUB_LOCAL_POWER:
+- break;
+- default:
+- goto stall;
+- }
+- break;
+- case ClearPortFeature:{
+- retval = u132_roothub_clearportfeature(u132,
+- wValue, wIndex);
+- if (retval)
+- goto error;
+- break;
+- }
+- case GetHubDescriptor:{
+- retval = u132_roothub_descriptor(u132,
+- (struct usb_hub_descriptor *)buf);
+- if (retval)
+- goto error;
+- break;
+- }
+- case GetHubStatus:{
+- retval = u132_roothub_status(u132,
+- (__le32 *) buf);
+- if (retval)
+- goto error;
+- break;
+- }
+- case GetPortStatus:{
+- retval = u132_roothub_portstatus(u132,
+- (__le32 *) buf, wIndex);
+- if (retval)
+- goto error;
+- break;
+- }
+- case SetPortFeature:{
+- retval = u132_roothub_setportfeature(u132,
+- wValue, wIndex);
+- if (retval)
+- goto error;
+- break;
+- }
+- default:
+- goto stall;
+- error:u132_disable(u132);
+- u132->going = 1;
+- break;
+- stall:retval = -EPIPE;
+- break;
+- }
+- mutex_unlock(&u132->sw_lock);
+- return retval;
+- }
++ u16 wIndex, char *buf, u16 wLength)
++{
++ struct u132 *u132 = hcd_to_u132(hcd);
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++ , u132->going);
++ return -ENODEV;
++ } else if (u132->going > 0) {
++ dev_err(&u132->platform_dev->dev, "device is being removed\n");
++ return -ESHUTDOWN;
++ } else {
++ int retval = 0;
++ mutex_lock(&u132->sw_lock);
++ switch (typeReq) {
++ case ClearHubFeature:
++ switch (wValue) {
++ case C_HUB_OVER_CURRENT:
++ case C_HUB_LOCAL_POWER:
++ break;
++ default:
++ goto stall;
++ }
++ break;
++ case SetHubFeature:
++ switch (wValue) {
++ case C_HUB_OVER_CURRENT:
++ case C_HUB_LOCAL_POWER:
++ break;
++ default:
++ goto stall;
++ }
++ break;
++ case ClearPortFeature:{
++ retval = u132_roothub_clearportfeature(u132,
++ wValue, wIndex);
++ if (retval)
++ goto error;
++ break;
++ }
++ case GetHubDescriptor:{
++ retval = u132_roothub_descriptor(u132,
++ (struct usb_hub_descriptor *)buf);
++ if (retval)
++ goto error;
++ break;
++ }
++ case GetHubStatus:{
++ retval = u132_roothub_status(u132,
++ (__le32 *) buf);
++ if (retval)
++ goto error;
++ break;
++ }
++ case GetPortStatus:{
++ retval = u132_roothub_portstatus(u132,
++ (__le32 *) buf, wIndex);
++ if (retval)
++ goto error;
++ break;
++ }
++ case SetPortFeature:{
++ retval = u132_roothub_setportfeature(u132,
++ wValue, wIndex);
++ if (retval)
++ goto error;
++ break;
++ }
++ default:
++ goto stall;
++ error:
++ u132_disable(u132);
++ u132->going = 1;
++ break;
++ stall:
++ retval = -EPIPE;
++ break;
++ }
++ mutex_unlock(&u132->sw_lock);
++ return retval;
++ }
+ }
+
+ static int u132_start_port_reset(struct usb_hcd *hcd, unsigned port_num)
+ {
+- struct u132 *u132 = hcd_to_u132(hcd);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- return -ENODEV;
+- } else if (u132->going > 0) {
+- dev_err(&u132->platform_dev->dev, "device is being removed\n");
+- return -ESHUTDOWN;
+- } else
+- return 0;
+-}
+-
+-static void u132_hub_irq_enable(struct usb_hcd *hcd)
+-{
+- struct u132 *u132 = hcd_to_u132(hcd);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- } else if (u132->going > 0)
+- dev_err(&u132->platform_dev->dev, "device is being removed\n");
++ struct u132 *u132 = hcd_to_u132(hcd);
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++ , u132->going);
++ return -ENODEV;
++ } else if (u132->going > 0) {
++ dev_err(&u132->platform_dev->dev, "device is being removed\n");
++ return -ESHUTDOWN;
++ } else
++ return 0;
+ }
+
+
+ #ifdef CONFIG_PM
+-static int u132_hcd_suspend(struct usb_hcd *hcd, pm_message_t message)
+-{
+- struct u132 *u132 = hcd_to_u132(hcd);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- return -ENODEV;
+- } else if (u132->going > 0) {
+- dev_err(&u132->platform_dev->dev, "device is being removed\n");
+- return -ESHUTDOWN;
+- } else
+- return 0;
+-}
+-
+-static int u132_hcd_resume(struct usb_hcd *hcd)
+-{
+- struct u132 *u132 = hcd_to_u132(hcd);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- return -ENODEV;
+- } else if (u132->going > 0) {
+- dev_err(&u132->platform_dev->dev, "device is being removed\n");
+- return -ESHUTDOWN;
+- } else
+- return 0;
+-}
+-
+ static int u132_bus_suspend(struct usb_hcd *hcd)
+ {
+- struct u132 *u132 = hcd_to_u132(hcd);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- return -ENODEV;
+- } else if (u132->going > 0) {
+- dev_err(&u132->platform_dev->dev, "device is being removed\n");
+- return -ESHUTDOWN;
+- } else
+- return 0;
++ struct u132 *u132 = hcd_to_u132(hcd);
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++ , u132->going);
++ return -ENODEV;
++ } else if (u132->going > 0) {
++ dev_err(&u132->platform_dev->dev, "device is being removed\n");
++ return -ESHUTDOWN;
++ } else
++ return 0;
+ }
+
+ static int u132_bus_resume(struct usb_hcd *hcd)
+ {
+- struct u132 *u132 = hcd_to_u132(hcd);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- return -ENODEV;
+- } else if (u132->going > 0) {
+- dev_err(&u132->platform_dev->dev, "device is being removed\n");
+- return -ESHUTDOWN;
+- } else
+- return 0;
++ struct u132 *u132 = hcd_to_u132(hcd);
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++ , u132->going);
++ return -ENODEV;
++ } else if (u132->going > 0) {
++ dev_err(&u132->platform_dev->dev, "device is being removed\n");
++ return -ESHUTDOWN;
++ } else
++ return 0;
+ }
+
+ #else
+-#define u132_hcd_suspend NULL
+-#define u132_hcd_resume NULL
+ #define u132_bus_suspend NULL
+ #define u132_bus_resume NULL
+ #endif
+ static struct hc_driver u132_hc_driver = {
+- .description = hcd_name,
+- .hcd_priv_size = sizeof(struct u132),
+- .irq = NULL,
+- .flags = HCD_USB11 | HCD_MEMORY,
+- .reset = u132_hcd_reset,
+- .start = u132_hcd_start,
+- .suspend = u132_hcd_suspend,
+- .resume = u132_hcd_resume,
+- .stop = u132_hcd_stop,
+- .urb_enqueue = u132_urb_enqueue,
+- .urb_dequeue = u132_urb_dequeue,
+- .endpoint_disable = u132_endpoint_disable,
+- .get_frame_number = u132_get_frame,
+- .hub_status_data = u132_hub_status_data,
+- .hub_control = u132_hub_control,
+- .bus_suspend = u132_bus_suspend,
+- .bus_resume = u132_bus_resume,
+- .start_port_reset = u132_start_port_reset,
+- .hub_irq_enable = u132_hub_irq_enable,
++ .description = hcd_name,
++ .hcd_priv_size = sizeof(struct u132),
++ .irq = NULL,
++ .flags = HCD_USB11 | HCD_MEMORY,
++ .reset = u132_hcd_reset,
++ .start = u132_hcd_start,
++ .stop = u132_hcd_stop,
++ .urb_enqueue = u132_urb_enqueue,
++ .urb_dequeue = u132_urb_dequeue,
++ .endpoint_disable = u132_endpoint_disable,
++ .get_frame_number = u132_get_frame,
++ .hub_status_data = u132_hub_status_data,
++ .hub_control = u132_hub_control,
++ .bus_suspend = u132_bus_suspend,
++ .bus_resume = u132_bus_resume,
++ .start_port_reset = u132_start_port_reset,
+ };
+
+ /*
+@@ -3051,148 +2995,152 @@ static struct hc_driver u132_hc_driver = {
+ */
+ static int __devexit u132_remove(struct platform_device *pdev)
+ {
+- struct usb_hcd *hcd = platform_get_drvdata(pdev);
+- if (hcd) {
+- struct u132 *u132 = hcd_to_u132(hcd);
+- if (u132->going++ > 1) {
+- dev_err(&u132->platform_dev->dev, "already being remove"
++ struct usb_hcd *hcd = platform_get_drvdata(pdev);
++ if (hcd) {
++ struct u132 *u132 = hcd_to_u132(hcd);
++ if (u132->going++ > 1) {
++ dev_err(&u132->platform_dev->dev, "already being remove"
+ "d\n");
+- return -ENODEV;
+- } else {
+- int rings = MAX_U132_RINGS;
+- int endps = MAX_U132_ENDPS;
+- dev_err(&u132->platform_dev->dev, "removing device u132"
++ return -ENODEV;
++ } else {
++ int rings = MAX_U132_RINGS;
++ int endps = MAX_U132_ENDPS;
++ dev_err(&u132->platform_dev->dev, "removing device u132"
+ ".%d\n", u132->sequence_num);
+- msleep(100);
+- mutex_lock(&u132->sw_lock);
+- u132_monitor_cancel_work(u132);
+- while (rings-- > 0) {
+- struct u132_ring *ring = &u132->ring[rings];
+- u132_ring_cancel_work(u132, ring);
+- } while (endps-- > 0) {
+- struct u132_endp *endp = u132->endp[endps];
+- if (endp)
+- u132_endp_cancel_work(u132, endp);
+- }
+- u132->going += 1;
+- printk(KERN_INFO "removing device u132.%d\n",
+- u132->sequence_num);
+- mutex_unlock(&u132->sw_lock);
+- usb_remove_hcd(hcd);
+- u132_u132_put_kref(u132);
+- return 0;
+- }
+- } else
+- return 0;
++ msleep(100);
++ mutex_lock(&u132->sw_lock);
++ u132_monitor_cancel_work(u132);
++ while (rings-- > 0) {
++ struct u132_ring *ring = &u132->ring[rings];
++ u132_ring_cancel_work(u132, ring);
++ } while (endps-- > 0) {
++ struct u132_endp *endp = u132->endp[endps];
++ if (endp)
++ u132_endp_cancel_work(u132, endp);
++ }
++ u132->going += 1;
++ printk(KERN_INFO "removing device u132.%d\n",
++ u132->sequence_num);
++ mutex_unlock(&u132->sw_lock);
++ usb_remove_hcd(hcd);
++ u132_u132_put_kref(u132);
++ return 0;
++ }
++ } else
++ return 0;
+ }
+
+ static void u132_initialise(struct u132 *u132, struct platform_device *pdev)
+ {
+- int rings = MAX_U132_RINGS;
+- int ports = MAX_U132_PORTS;
+- int addrs = MAX_U132_ADDRS;
+- int udevs = MAX_U132_UDEVS;
+- int endps = MAX_U132_ENDPS;
+- u132->board = pdev->dev.platform_data;
+- u132->platform_dev = pdev;
+- u132->power = 0;
+- u132->reset = 0;
+- mutex_init(&u132->sw_lock);
+- init_MUTEX(&u132->scheduler_lock);
+- while (rings-- > 0) {
+- struct u132_ring *ring = &u132->ring[rings];
+- ring->u132 = u132;
+- ring->number = rings + 1;
+- ring->length = 0;
+- ring->curr_endp = NULL;
+- INIT_DELAYED_WORK(&ring->scheduler,
++ int rings = MAX_U132_RINGS;
++ int ports = MAX_U132_PORTS;
++ int addrs = MAX_U132_ADDRS;
++ int udevs = MAX_U132_UDEVS;
++ int endps = MAX_U132_ENDPS;
++ u132->board = pdev->dev.platform_data;
++ u132->platform_dev = pdev;
++ u132->power = 0;
++ u132->reset = 0;
++ mutex_init(&u132->sw_lock);
++ mutex_init(&u132->scheduler_lock);
++ while (rings-- > 0) {
++ struct u132_ring *ring = &u132->ring[rings];
++ ring->u132 = u132;
++ ring->number = rings + 1;
++ ring->length = 0;
++ ring->curr_endp = NULL;
++ INIT_DELAYED_WORK(&ring->scheduler,
+ u132_hcd_ring_work_scheduler);
+- } mutex_lock(&u132->sw_lock);
+- INIT_DELAYED_WORK(&u132->monitor, u132_hcd_monitor_work);
+- while (ports-- > 0) {
+- struct u132_port *port = &u132->port[ports];
+- port->u132 = u132;
+- port->reset = 0;
+- port->enable = 0;
+- port->power = 0;
+- port->Status = 0;
+- } while (addrs-- > 0) {
+- struct u132_addr *addr = &u132->addr[addrs];
+- addr->address = 0;
+- } while (udevs-- > 0) {
+- struct u132_udev *udev = &u132->udev[udevs];
+- int i = ARRAY_SIZE(udev->endp_number_in);
+- int o = ARRAY_SIZE(udev->endp_number_out);
+- udev->usb_device = NULL;
+- udev->udev_number = 0;
+- udev->usb_addr = 0;
+- udev->portnumber = 0;
+- while (i-- > 0) {
+- udev->endp_number_in[i] = 0;
+- }
+- while (o-- > 0) {
+- udev->endp_number_out[o] = 0;
+- }
+- }
+- while (endps-- > 0) {
+- u132->endp[endps] = NULL;
+- }
+- mutex_unlock(&u132->sw_lock);
+- return;
++ }
++ mutex_lock(&u132->sw_lock);
++ INIT_DELAYED_WORK(&u132->monitor, u132_hcd_monitor_work);
++ while (ports-- > 0) {
++ struct u132_port *port = &u132->port[ports];
++ port->u132 = u132;
++ port->reset = 0;
++ port->enable = 0;
++ port->power = 0;
++ port->Status = 0;
++ }
++ while (addrs-- > 0) {
++ struct u132_addr *addr = &u132->addr[addrs];
++ addr->address = 0;
++ }
++ while (udevs-- > 0) {
++ struct u132_udev *udev = &u132->udev[udevs];
++ int i = ARRAY_SIZE(udev->endp_number_in);
++ int o = ARRAY_SIZE(udev->endp_number_out);
++ udev->usb_device = NULL;
++ udev->udev_number = 0;
++ udev->usb_addr = 0;
++ udev->portnumber = 0;
++ while (i-- > 0)
++ udev->endp_number_in[i] = 0;
++
++ while (o-- > 0)
++ udev->endp_number_out[o] = 0;
++
++ }
++ while (endps-- > 0)
++ u132->endp[endps] = NULL;
++
++ mutex_unlock(&u132->sw_lock);
++ return;
+ }
+
+ static int __devinit u132_probe(struct platform_device *pdev)
+ {
+- struct usb_hcd *hcd;
+- int retval;
+- u32 control;
+- u32 rh_a = -1;
+- u32 num_ports;
+- msleep(100);
+- if (u132_exiting > 0) {
+- return -ENODEV;
+- }
+- retval = ftdi_write_pcimem(pdev, intrdisable, OHCI_INTR_MIE);
+- if (retval)
+- return retval;
+- retval = ftdi_read_pcimem(pdev, control, &control);
+- if (retval)
+- return retval;
+- retval = ftdi_read_pcimem(pdev, roothub.a, &rh_a);
+- if (retval)
+- return retval;
+- num_ports = rh_a & RH_A_NDP; /* refuse to confuse usbcore */
+- if (pdev->dev.dma_mask) {
+- return -EINVAL;
+- }
+- hcd = usb_create_hcd(&u132_hc_driver, &pdev->dev, pdev->dev.bus_id);
+- if (!hcd) {
+- printk(KERN_ERR "failed to create the usb hcd struct for U132\n"
+- );
+- ftdi_elan_gone_away(pdev);
+- return -ENOMEM;
+- } else {
+- int retval = 0;
+- struct u132 *u132 = hcd_to_u132(hcd);
+- hcd->rsrc_start = 0;
+- mutex_lock(&u132_module_lock);
+- list_add_tail(&u132->u132_list, &u132_static_list);
+- u132->sequence_num = ++u132_instances;
+- mutex_unlock(&u132_module_lock);
+- u132_u132_init_kref(u132);
+- u132_initialise(u132, pdev);
+- hcd->product_desc = "ELAN U132 Host Controller";
+- retval = usb_add_hcd(hcd, 0, 0);
+- if (retval != 0) {
+- dev_err(&u132->platform_dev->dev, "init error %d\n",
+- retval);
+- u132_u132_put_kref(u132);
+- return retval;
+- } else {
+- u132_monitor_queue_work(u132, 100);
+- return 0;
+- }
+- }
++ struct usb_hcd *hcd;
++ int retval;
++ u32 control;
++ u32 rh_a = -1;
++ u32 num_ports;
++
++ msleep(100);
++ if (u132_exiting > 0)
++ return -ENODEV;
++
++ retval = ftdi_write_pcimem(pdev, intrdisable, OHCI_INTR_MIE);
++ if (retval)
++ return retval;
++ retval = ftdi_read_pcimem(pdev, control, &control);
++ if (retval)
++ return retval;
++ retval = ftdi_read_pcimem(pdev, roothub.a, &rh_a);
++ if (retval)
++ return retval;
++ num_ports = rh_a & RH_A_NDP; /* refuse to confuse usbcore */
++ if (pdev->dev.dma_mask)
++ return -EINVAL;
++
++ hcd = usb_create_hcd(&u132_hc_driver, &pdev->dev, pdev->dev.bus_id);
++ if (!hcd) {
++ printk(KERN_ERR "failed to create the usb hcd struct for U132\n"
++ );
++ ftdi_elan_gone_away(pdev);
++ return -ENOMEM;
++ } else {
++ int retval = 0;
++ struct u132 *u132 = hcd_to_u132(hcd);
++ hcd->rsrc_start = 0;
++ mutex_lock(&u132_module_lock);
++ list_add_tail(&u132->u132_list, &u132_static_list);
++ u132->sequence_num = ++u132_instances;
++ mutex_unlock(&u132_module_lock);
++ u132_u132_init_kref(u132);
++ u132_initialise(u132, pdev);
++ hcd->product_desc = "ELAN U132 Host Controller";
++ retval = usb_add_hcd(hcd, 0, 0);
++ if (retval != 0) {
++ dev_err(&u132->platform_dev->dev, "init error %d\n",
++ retval);
++ u132_u132_put_kref(u132);
++ return retval;
++ } else {
++ u132_monitor_queue_work(u132, 100);
++ return 0;
++ }
++ }
+ }
+
+
+@@ -3203,61 +3151,58 @@ static int __devinit u132_probe(struct platform_device *pdev)
+ */
+ static int u132_suspend(struct platform_device *pdev, pm_message_t state)
+ {
+- struct usb_hcd *hcd = platform_get_drvdata(pdev);
+- struct u132 *u132 = hcd_to_u132(hcd);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- return -ENODEV;
+- } else if (u132->going > 0) {
+- dev_err(&u132->platform_dev->dev, "device is being removed\n");
+- return -ESHUTDOWN;
+- } else {
++ struct usb_hcd *hcd = platform_get_drvdata(pdev);
++ struct u132 *u132 = hcd_to_u132(hcd);
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++ , u132->going);
++ return -ENODEV;
++ } else if (u132->going > 0) {
++ dev_err(&u132->platform_dev->dev, "device is being removed\n");
++ return -ESHUTDOWN;
++ } else {
+ int retval = 0, ports;
+
+ switch (state.event) {
+ case PM_EVENT_FREEZE:
+- retval = u132_bus_suspend(hcd);
++ retval = u132_bus_suspend(hcd);
+ break;
+ case PM_EVENT_SUSPEND:
+ case PM_EVENT_HIBERNATE:
+ ports = MAX_U132_PORTS;
+- while (ports-- > 0) {
+- port_power(u132, ports, 0);
+- }
++ while (ports-- > 0) {
++ port_power(u132, ports, 0);
++ }
+ break;
+ }
+- if (retval == 0)
+- pdev->dev.power.power_state = state;
+- return retval;
+- }
++ return retval;
++ }
+ }
+
+ static int u132_resume(struct platform_device *pdev)
+ {
+- struct usb_hcd *hcd = platform_get_drvdata(pdev);
+- struct u132 *u132 = hcd_to_u132(hcd);
+- if (u132->going > 1) {
+- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+- , u132->going);
+- return -ENODEV;
+- } else if (u132->going > 0) {
+- dev_err(&u132->platform_dev->dev, "device is being removed\n");
+- return -ESHUTDOWN;
+- } else {
+- int retval = 0;
+- if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
+- int ports = MAX_U132_PORTS;
+- while (ports-- > 0) {
+- port_power(u132, ports, 1);
+- }
+- retval = 0;
+- } else {
+- pdev->dev.power.power_state = PMSG_ON;
+- retval = u132_bus_resume(hcd);
+- }
+- return retval;
+- }
++ struct usb_hcd *hcd = platform_get_drvdata(pdev);
++ struct u132 *u132 = hcd_to_u132(hcd);
++ if (u132->going > 1) {
++ dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
++ , u132->going);
++ return -ENODEV;
++ } else if (u132->going > 0) {
++ dev_err(&u132->platform_dev->dev, "device is being removed\n");
++ return -ESHUTDOWN;
++ } else {
++ int retval = 0;
++ if (!u132->port[0].power) {
++ int ports = MAX_U132_PORTS;
++ while (ports-- > 0) {
++ port_power(u132, ports, 1);
++ }
++ retval = 0;
++ } else {
++ retval = u132_bus_resume(hcd);
++ }
++ return retval;
++ }
+ }
+
+ #else
+@@ -3270,47 +3215,48 @@ static int u132_resume(struct platform_device *pdev)
+ * the platform_driver struct is static because it is per type of module
+ */
+ static struct platform_driver u132_platform_driver = {
+- .probe = u132_probe,
+- .remove = __devexit_p(u132_remove),
+- .suspend = u132_suspend,
+- .resume = u132_resume,
+- .driver = {
+- .name = (char *)hcd_name,
+- .owner = THIS_MODULE,
+- },
++ .probe = u132_probe,
++ .remove = __devexit_p(u132_remove),
++ .suspend = u132_suspend,
++ .resume = u132_resume,
++ .driver = {
++ .name = (char *)hcd_name,
++ .owner = THIS_MODULE,
++ },
+ };
+ static int __init u132_hcd_init(void)
+ {
+- int retval;
+- INIT_LIST_HEAD(&u132_static_list);
+- u132_instances = 0;
+- u132_exiting = 0;
+- mutex_init(&u132_module_lock);
+- if (usb_disabled())
+- return -ENODEV;
+- printk(KERN_INFO "driver %s built at %s on %s\n", hcd_name, __TIME__,
+- __DATE__);
+- workqueue = create_singlethread_workqueue("u132");
+- retval = platform_driver_register(&u132_platform_driver);
+- return retval;
++ int retval;
++ INIT_LIST_HEAD(&u132_static_list);
++ u132_instances = 0;
++ u132_exiting = 0;
++ mutex_init(&u132_module_lock);
++ if (usb_disabled())
++ return -ENODEV;
++ printk(KERN_INFO "driver %s built at %s on %s\n", hcd_name, __TIME__,
++ __DATE__);
++ workqueue = create_singlethread_workqueue("u132");
++ retval = platform_driver_register(&u132_platform_driver);
++ return retval;
+ }
+
+
+ module_init(u132_hcd_init);
+ static void __exit u132_hcd_exit(void)
+ {
+- struct u132 *u132;
+- struct u132 *temp;
+- mutex_lock(&u132_module_lock);
+- u132_exiting += 1;
+- mutex_unlock(&u132_module_lock);
+- list_for_each_entry_safe(u132, temp, &u132_static_list, u132_list) {
+- platform_device_unregister(u132->platform_dev);
+- } platform_driver_unregister(&u132_platform_driver);
+- printk(KERN_INFO "u132-hcd driver deregistered\n");
+- wait_event(u132_hcd_wait, u132_instances == 0);
+- flush_workqueue(workqueue);
+- destroy_workqueue(workqueue);
++ struct u132 *u132;
++ struct u132 *temp;
++ mutex_lock(&u132_module_lock);
++ u132_exiting += 1;
++ mutex_unlock(&u132_module_lock);
++ list_for_each_entry_safe(u132, temp, &u132_static_list, u132_list) {
++ platform_device_unregister(u132->platform_dev);
++ }
++ platform_driver_unregister(&u132_platform_driver);
++ printk(KERN_INFO "u132-hcd driver deregistered\n");
++ wait_event(u132_hcd_wait, u132_instances == 0);
++ flush_workqueue(workqueue);
++ destroy_workqueue(workqueue);
+ }
+
+
+diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
+index ec98789..d3e0d8a 100644
+--- a/drivers/usb/host/uhci-hcd.c
++++ b/drivers/usb/host/uhci-hcd.c
+@@ -262,20 +262,12 @@ __acquires(uhci->lock)
+ {
+ int auto_stop;
+ int int_enable, egsm_enable;
++ struct usb_device *rhdev = uhci_to_hcd(uhci)->self.root_hub;
+
+ auto_stop = (new_state == UHCI_RH_AUTO_STOPPED);
+- dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev,
+- "%s%s\n", __FUNCTION__,
++ dev_dbg(&rhdev->dev, "%s%s\n", __func__,
+ (auto_stop ? " (auto-stop)" : ""));
+
+- /* If we get a suspend request when we're already auto-stopped
+- * then there's nothing to do.
+- */
+- if (uhci->rh_state == UHCI_RH_AUTO_STOPPED) {
+- uhci->rh_state = new_state;
+- return;
+- }
+-
+ /* Enable resume-detect interrupts if they work.
+ * Then enter Global Suspend mode if _it_ works, still configured.
+ */
+@@ -285,8 +277,10 @@ __acquires(uhci->lock)
+ if (remote_wakeup_is_broken(uhci))
+ egsm_enable = 0;
+ if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable ||
+- !device_may_wakeup(
+- &uhci_to_hcd(uhci)->self.root_hub->dev))
++#ifdef CONFIG_PM
++ (!auto_stop && !rhdev->do_remote_wakeup) ||
++#endif
++ (auto_stop && !device_may_wakeup(&rhdev->dev)))
+ uhci->working_RD = int_enable = 0;
+
+ outw(int_enable, uhci->io_addr + USBINTR);
+@@ -308,8 +302,7 @@ __acquires(uhci->lock)
+ return;
+ }
+ if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH))
+- dev_warn(&uhci_to_hcd(uhci)->self.root_hub->dev,
+- "Controller not stopped yet!\n");
++ dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n");
+
+ uhci_get_current_frame_number(uhci);
+
+@@ -342,7 +335,7 @@ __releases(uhci->lock)
+ __acquires(uhci->lock)
+ {
+ dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev,
+- "%s%s\n", __FUNCTION__,
++ "%s%s\n", __func__,
+ uhci->rh_state == UHCI_RH_AUTO_STOPPED ?
+ " (auto-start)" : "");
+
+@@ -737,12 +730,12 @@ static int uhci_rh_resume(struct usb_hcd *hcd)
+ return rc;
+ }
+
+-static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
++static int uhci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
+ {
+ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ int rc = 0;
+
+- dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
++ dev_dbg(uhci_dev(uhci), "%s\n", __func__);
+
+ spin_lock_irq(&uhci->lock);
+ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
+@@ -774,11 +767,11 @@ done:
+ return rc;
+ }
+
+-static int uhci_resume(struct usb_hcd *hcd)
++static int uhci_pci_resume(struct usb_hcd *hcd)
+ {
+ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+
+- dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
++ dev_dbg(uhci_dev(uhci), "%s\n", __func__);
+
+ /* Since we aren't in D3 any more, it's safe to set this flag
+ * even if the controller was dead.
+@@ -872,8 +865,8 @@ static const struct hc_driver uhci_driver = {
+ .reset = uhci_init,
+ .start = uhci_start,
+ #ifdef CONFIG_PM
+- .suspend = uhci_suspend,
+- .resume = uhci_resume,
++ .pci_suspend = uhci_pci_suspend,
++ .pci_resume = uhci_pci_resume,
+ .bus_suspend = uhci_rh_suspend,
+ .bus_resume = uhci_rh_resume,
+ #endif
+diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
+index 60379b1..db64593 100644
+--- a/drivers/usb/host/uhci-q.c
++++ b/drivers/usb/host/uhci-q.c
+@@ -1171,7 +1171,7 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
+ /* Some debugging code */
+ dev_dbg(&urb->dev->dev,
+ "%s: failed with status %x\n",
+- __FUNCTION__, status);
++ __func__, status);
+
+ if (debug > 1 && errbuf) {
+ /* Print the chain for debugging */
+diff --git a/drivers/usb/image/Kconfig b/drivers/usb/image/Kconfig
+index 7595dfb..33350f9 100644
+--- a/drivers/usb/image/Kconfig
++++ b/drivers/usb/image/Kconfig
+@@ -5,8 +5,8 @@ comment "USB Imaging devices"
+ depends on USB
+
+ config USB_MDC800
+- tristate "USB Mustek MDC800 Digital Camera support (EXPERIMENTAL)"
+- depends on USB && EXPERIMENTAL
++ tristate "USB Mustek MDC800 Digital Camera support"
++ depends on USB
+ ---help---
+ Say Y here if you want to connect this type of still camera to
+ your computer's USB port. This driver can be used with gphoto 0.4.3
+diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
+index bc207e3..885867a 100644
+--- a/drivers/usb/image/microtek.c
++++ b/drivers/usb/image/microtek.c
+@@ -185,7 +185,7 @@ static struct usb_driver mts_usb_driver = {
+ printk( KERN_DEBUG MTS_NAME x )
+
+ #define MTS_DEBUG_GOT_HERE() \
+- MTS_DEBUG("got to %s:%d (%s)\n", __FILE__, (int)__LINE__, __PRETTY_FUNCTION__ )
++ MTS_DEBUG("got to %s:%d (%s)\n", __FILE__, (int)__LINE__, __func__ )
+ #define MTS_DEBUG_INT() \
+ do { MTS_DEBUG_GOT_HERE(); \
+ MTS_DEBUG("transfer = 0x%x context = 0x%x\n",(int)transfer,(int)context ); \
+@@ -794,7 +794,6 @@ static int mts_usb_probe(struct usb_interface *intf,
+
+ new_desc->usb_dev = dev;
+ new_desc->usb_intf = intf;
+- init_MUTEX(&new_desc->lock);
+
+ /* endpoints */
+ new_desc->ep_out = ep_out;
+diff --git a/drivers/usb/image/microtek.h b/drivers/usb/image/microtek.h
+index d5d62a9..ccce318 100644
+--- a/drivers/usb/image/microtek.h
++++ b/drivers/usb/image/microtek.h
+@@ -39,7 +39,6 @@ struct mts_desc {
+ u8 ep_image;
+
+ struct Scsi_Host * host;
+- struct semaphore lock;
+
+ struct urb *urb;
+ struct mts_transfer_context context;
+diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
+index 9c7eb61..a53db1d 100644
+--- a/drivers/usb/misc/Kconfig
++++ b/drivers/usb/misc/Kconfig
+@@ -33,8 +33,8 @@ config USB_EMI26
+ module will be called emi26.
+
+ config USB_ADUTUX
+- tristate "ADU devices from Ontrak Control Systems (EXPERIMENTAL)"
+- depends on USB && EXPERIMENTAL
++ tristate "ADU devices from Ontrak Control Systems"
++ depends on USB
+ help
+ Say Y if you want to use an ADU device from Ontrak Control
+ Systems.
+@@ -43,8 +43,8 @@ config USB_ADUTUX
+ will be called adutux.
+
+ config USB_AUERSWALD
+- tristate "USB Auerswald ISDN support (EXPERIMENTAL)"
+- depends on USB && EXPERIMENTAL
++ tristate "USB Auerswald ISDN support"
++ depends on USB
+ help
+ Say Y here if you want to connect an Auerswald USB ISDN Device
+ to your computer's USB port.
+@@ -53,8 +53,8 @@ config USB_AUERSWALD
+ module will be called auerswald.
+
+ config USB_RIO500
+- tristate "USB Diamond Rio500 support (EXPERIMENTAL)"
+- depends on USB && EXPERIMENTAL
++ tristate "USB Diamond Rio500 support"
++ depends on USB
+ help
+ Say Y here if you want to connect a USB Rio500 mp3 player to your
+ computer's USB port. Please read <file:Documentation/usb/rio.txt>
+@@ -64,8 +64,8 @@ config USB_RIO500
+ module will be called rio500.
+
+ config USB_LEGOTOWER
+- tristate "USB Lego Infrared Tower support (EXPERIMENTAL)"
+- depends on USB && EXPERIMENTAL
++ tristate "USB Lego Infrared Tower support"
++ depends on USB
+ help
+ Say Y here if you want to connect a USB Lego Infrared Tower to your
+ computer's USB port.
+@@ -259,8 +259,8 @@ config USB_IOWARRIOR
+ module will be called iowarrior.
+
+ config USB_TEST
+- tristate "USB testing driver (DEVELOPMENT)"
+- depends on USB && USB_DEVICEFS && EXPERIMENTAL
++ tristate "USB testing driver"
++ depends on USB && USB_DEVICEFS
+ help
+ This driver is for testing host controller software. It is used
+ with specialized device firmware for regression and stress testing,
+diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
+index 5a2c44e..965f6ea 100644
+--- a/drivers/usb/misc/adutux.c
++++ b/drivers/usb/misc/adutux.c
+@@ -147,10 +147,10 @@ static void adu_abort_transfers(struct adu_device *dev)
+ {
+ unsigned long flags;
+
+- dbg(2," %s : enter", __FUNCTION__);
++ dbg(2," %s : enter", __func__);
+
+ if (dev->udev == NULL) {
+- dbg(1," %s : udev is null", __FUNCTION__);
++ dbg(1," %s : udev is null", __func__);
+ goto exit;
+ }
+
+@@ -172,12 +172,12 @@ static void adu_abort_transfers(struct adu_device *dev)
+ spin_unlock_irqrestore(&dev->buflock, flags);
+
+ exit:
+- dbg(2," %s : leave", __FUNCTION__);
++ dbg(2," %s : leave", __func__);
+ }
+
+ static void adu_delete(struct adu_device *dev)
+ {
+- dbg(2, "%s enter", __FUNCTION__);
++ dbg(2, "%s enter", __func__);
+
+ /* free data structures */
+ usb_free_urb(dev->interrupt_in_urb);
+@@ -188,7 +188,7 @@ static void adu_delete(struct adu_device *dev)
+ kfree(dev->interrupt_out_buffer);
+ kfree(dev);
+
+- dbg(2, "%s : leave", __FUNCTION__);
++ dbg(2, "%s : leave", __func__);
+ }
+
+ static void adu_interrupt_in_callback(struct urb *urb)
+@@ -196,8 +196,8 @@ static void adu_interrupt_in_callback(struct urb *urb)
+ struct adu_device *dev = urb->context;
+ int status = urb->status;
+
+- dbg(4," %s : enter, status %d", __FUNCTION__, status);
+- adu_debug_data(5, __FUNCTION__, urb->actual_length,
++ dbg(4," %s : enter, status %d", __func__, status);
++ adu_debug_data(5, __func__, urb->actual_length,
+ urb->transfer_buffer);
+
+ spin_lock(&dev->buflock);
+@@ -206,7 +206,7 @@ static void adu_interrupt_in_callback(struct urb *urb)
+ if ((status != -ENOENT) && (status != -ECONNRESET) &&
+ (status != -ESHUTDOWN)) {
+ dbg(1," %s : nonzero status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ }
+ goto exit;
+ }
+@@ -220,10 +220,10 @@ static void adu_interrupt_in_callback(struct urb *urb)
+ dev->interrupt_in_buffer, urb->actual_length);
+
+ dev->read_buffer_length += urb->actual_length;
+- dbg(2," %s reading %d ", __FUNCTION__,
++ dbg(2," %s reading %d ", __func__,
+ urb->actual_length);
+ } else {
+- dbg(1," %s : read_buffer overflow", __FUNCTION__);
++ dbg(1," %s : read_buffer overflow", __func__);
+ }
+ }
+
+@@ -232,9 +232,9 @@ exit:
+ spin_unlock(&dev->buflock);
+ /* always wake up so we recover from errors */
+ wake_up_interruptible(&dev->read_wait);
+- adu_debug_data(5, __FUNCTION__, urb->actual_length,
++ adu_debug_data(5, __func__, urb->actual_length,
+ urb->transfer_buffer);
+- dbg(4," %s : leave, status %d", __FUNCTION__, status);
++ dbg(4," %s : leave, status %d", __func__, status);
+ }
+
+ static void adu_interrupt_out_callback(struct urb *urb)
+@@ -242,14 +242,14 @@ static void adu_interrupt_out_callback(struct urb *urb)
+ struct adu_device *dev = urb->context;
+ int status = urb->status;
+
+- dbg(4," %s : enter, status %d", __FUNCTION__, status);
+- adu_debug_data(5,__FUNCTION__, urb->actual_length, urb->transfer_buffer);
++ dbg(4," %s : enter, status %d", __func__, status);
++ adu_debug_data(5,__func__, urb->actual_length, urb->transfer_buffer);
+
+ if (status != 0) {
+ if ((status != -ENOENT) &&
+ (status != -ECONNRESET)) {
+ dbg(1, " %s :nonzero status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ }
+ goto exit;
+ }
+@@ -260,9 +260,9 @@ static void adu_interrupt_out_callback(struct urb *urb)
+ spin_unlock(&dev->buflock);
+ exit:
+
+- adu_debug_data(5, __FUNCTION__, urb->actual_length,
++ adu_debug_data(5, __func__, urb->actual_length,
+ urb->transfer_buffer);
+- dbg(4," %s : leave, status %d", __FUNCTION__, status);
++ dbg(4," %s : leave, status %d", __func__, status);
+ }
+
+ static int adu_open(struct inode *inode, struct file *file)
+@@ -272,19 +272,19 @@ static int adu_open(struct inode *inode, struct file *file)
+ int subminor;
+ int retval;
+
+- dbg(2,"%s : enter", __FUNCTION__);
++ dbg(2,"%s : enter", __func__);
+
+ subminor = iminor(inode);
+
+ if ((retval = mutex_lock_interruptible(&adutux_mutex))) {
+- dbg(2, "%s : mutex lock failed", __FUNCTION__);
++ dbg(2, "%s : mutex lock failed", __func__);
+ goto exit_no_lock;
+ }
+
+ interface = usb_find_interface(&adu_driver, subminor);
+ if (!interface) {
+ err("%s - error, can't find device for minor %d",
+- __FUNCTION__, subminor);
++ __func__, subminor);
+ retval = -ENODEV;
+ goto exit_no_device;
+ }
+@@ -302,7 +302,7 @@ static int adu_open(struct inode *inode, struct file *file)
+ }
+
+ ++dev->open_count;
+- dbg(2,"%s : open count %d", __FUNCTION__, dev->open_count);
++ dbg(2,"%s : open count %d", __func__, dev->open_count);
+
+ /* save device in the file's private structure */
+ file->private_data = dev;
+@@ -332,23 +332,23 @@ static int adu_open(struct inode *inode, struct file *file)
+ exit_no_device:
+ mutex_unlock(&adutux_mutex);
+ exit_no_lock:
+- dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval);
++ dbg(2,"%s : leave, return value %d ", __func__, retval);
+ return retval;
+ }
+
+ static void adu_release_internal(struct adu_device *dev)
+ {
+- dbg(2," %s : enter", __FUNCTION__);
++ dbg(2," %s : enter", __func__);
+
+ /* decrement our usage count for the device */
+ --dev->open_count;
+- dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
++ dbg(2," %s : open count %d", __func__, dev->open_count);
+ if (dev->open_count <= 0) {
+ adu_abort_transfers(dev);
+ dev->open_count = 0;
+ }
+
+- dbg(2," %s : leave", __FUNCTION__);
++ dbg(2," %s : leave", __func__);
+ }
+
+ static int adu_release(struct inode *inode, struct file *file)
+@@ -356,17 +356,17 @@ static int adu_release(struct inode *inode, struct file *file)
+ struct adu_device *dev;
+ int retval = 0;
+
+- dbg(2," %s : enter", __FUNCTION__);
++ dbg(2," %s : enter", __func__);
+
+ if (file == NULL) {
+- dbg(1," %s : file is NULL", __FUNCTION__);
++ dbg(1," %s : file is NULL", __func__);
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ dev = file->private_data;
+ if (dev == NULL) {
+- dbg(1," %s : object is NULL", __FUNCTION__);
++ dbg(1," %s : object is NULL", __func__);
+ retval = -ENODEV;
+ goto exit;
+ }
+@@ -374,7 +374,7 @@ static int adu_release(struct inode *inode, struct file *file)
+ mutex_lock(&adutux_mutex); /* not interruptible */
+
+ if (dev->open_count <= 0) {
+- dbg(1," %s : device not opened", __FUNCTION__);
++ dbg(1," %s : device not opened", __func__);
+ retval = -ENODEV;
+ goto exit;
+ }
+@@ -388,7 +388,7 @@ static int adu_release(struct inode *inode, struct file *file)
+
+ exit:
+ mutex_unlock(&adutux_mutex);
+- dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
++ dbg(2," %s : leave, return value %d", __func__, retval);
+ return retval;
+ }
+
+@@ -405,10 +405,10 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
+ unsigned long flags;
+ DECLARE_WAITQUEUE(wait, current);
+
+- dbg(2," %s : enter, count = %Zd, file=%p", __FUNCTION__, count, file);
++ dbg(2," %s : enter, count = %Zd, file=%p", __func__, count, file);
+
+ dev = file->private_data;
+- dbg(2," %s : dev=%p", __FUNCTION__, dev);
++ dbg(2," %s : dev=%p", __func__, dev);
+
+ if (mutex_lock_interruptible(&dev->mtx))
+ return -ERESTARTSYS;
+@@ -422,16 +422,16 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
+
+ /* verify that some data was requested */
+ if (count == 0) {
+- dbg(1," %s : read request of 0 bytes", __FUNCTION__);
++ dbg(1," %s : read request of 0 bytes", __func__);
+ goto exit;
+ }
+
+ timeout = COMMAND_TIMEOUT;
+- dbg(2," %s : about to start looping", __FUNCTION__);
++ dbg(2," %s : about to start looping", __func__);
+ while (bytes_to_read) {
+ int data_in_secondary = dev->secondary_tail - dev->secondary_head;
+ dbg(2," %s : while, data_in_secondary=%d, status=%d",
+- __FUNCTION__, data_in_secondary,
++ __func__, data_in_secondary,
+ dev->interrupt_in_urb->status);
+
+ if (data_in_secondary) {
+@@ -456,7 +456,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
+ /* we secure access to the primary */
+ char *tmp;
+ dbg(2," %s : swap, read_buffer_length = %d",
+- __FUNCTION__, dev->read_buffer_length);
++ __func__, dev->read_buffer_length);
+ tmp = dev->read_buffer_secondary;
+ dev->read_buffer_secondary = dev->read_buffer_primary;
+ dev->read_buffer_primary = tmp;
+@@ -471,10 +471,10 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
+ if (!dev->read_urb_finished) {
+ /* somebody is doing IO */
+ spin_unlock_irqrestore(&dev->buflock, flags);
+- dbg(2," %s : submitted already", __FUNCTION__);
++ dbg(2," %s : submitted already", __func__);
+ } else {
+ /* we must initiate input */
+- dbg(2," %s : initiate input", __FUNCTION__);
++ dbg(2," %s : initiate input", __func__);
+ dev->read_urb_finished = 0;
+ spin_unlock_irqrestore(&dev->buflock, flags);
+
+@@ -492,7 +492,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
+ if (retval == -ENOMEM) {
+ retval = bytes_read ? bytes_read : -ENOMEM;
+ }
+- dbg(2," %s : submit failed", __FUNCTION__);
++ dbg(2," %s : submit failed", __func__);
+ goto exit;
+ }
+ }
+@@ -511,13 +511,13 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
+ remove_wait_queue(&dev->read_wait, &wait);
+
+ if (timeout <= 0) {
+- dbg(2," %s : timeout", __FUNCTION__);
++ dbg(2," %s : timeout", __func__);
+ retval = bytes_read ? bytes_read : -ETIMEDOUT;
+ goto exit;
+ }
+
+ if (signal_pending(current)) {
+- dbg(2," %s : signal pending", __FUNCTION__);
++ dbg(2," %s : signal pending", __func__);
+ retval = bytes_read ? bytes_read : -EINTR;
+ goto exit;
+ }
+@@ -550,7 +550,7 @@ exit:
+ /* unlock the device */
+ mutex_unlock(&dev->mtx);
+
+- dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
++ dbg(2," %s : leave, return value %d", __func__, retval);
+ return retval;
+ }
+
+@@ -565,7 +565,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
+ unsigned long flags;
+ int retval;
+
+- dbg(2," %s : enter, count = %Zd", __FUNCTION__, count);
++ dbg(2," %s : enter, count = %Zd", __func__, count);
+
+ dev = file->private_data;
+
+@@ -582,7 +582,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
+
+ /* verify that we actually have some data to write */
+ if (count == 0) {
+- dbg(1," %s : write request of 0 bytes", __FUNCTION__);
++ dbg(1," %s : write request of 0 bytes", __func__);
+ goto exit;
+ }
+
+@@ -595,13 +595,13 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
+
+ mutex_unlock(&dev->mtx);
+ if (signal_pending(current)) {
+- dbg(1," %s : interrupted", __FUNCTION__);
++ dbg(1," %s : interrupted", __func__);
+ set_current_state(TASK_RUNNING);
+ retval = -EINTR;
+ goto exit_onqueue;
+ }
+ if (schedule_timeout(COMMAND_TIMEOUT) == 0) {
+- dbg(1, "%s - command timed out.", __FUNCTION__);
++ dbg(1, "%s - command timed out.", __func__);
+ retval = -ETIMEDOUT;
+ goto exit_onqueue;
+ }
+@@ -612,18 +612,18 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
+ goto exit_nolock;
+ }
+
+- dbg(4," %s : in progress, count = %Zd", __FUNCTION__, count);
++ dbg(4," %s : in progress, count = %Zd", __func__, count);
+ } else {
+ spin_unlock_irqrestore(&dev->buflock, flags);
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&dev->write_wait, &waita);
+- dbg(4," %s : sending, count = %Zd", __FUNCTION__, count);
++ dbg(4," %s : sending, count = %Zd", __func__, count);
+
+ /* write the data into interrupt_out_buffer from userspace */
+ buffer_size = le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize);
+ bytes_to_write = count > buffer_size ? buffer_size : count;
+ dbg(4," %s : buffer_size = %Zd, count = %Zd, bytes_to_write = %Zd",
+- __FUNCTION__, buffer_size, count, bytes_to_write);
++ __func__, buffer_size, count, bytes_to_write);
+
+ if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write) != 0) {
+ retval = -EFAULT;
+@@ -661,7 +661,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
+ exit:
+ mutex_unlock(&dev->mtx);
+ exit_nolock:
+- dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
++ dbg(2," %s : leave, return value %d", __func__, retval);
+ return retval;
+
+ exit_onqueue:
+@@ -706,7 +706,7 @@ static int adu_probe(struct usb_interface *interface,
+ int out_end_size;
+ int i;
+
+- dbg(2," %s : enter", __FUNCTION__);
++ dbg(2," %s : enter", __func__);
+
+ if (udev == NULL) {
+ dev_err(&interface->dev, "udev is NULL.\n");
+@@ -807,7 +807,7 @@ static int adu_probe(struct usb_interface *interface,
+ dev_err(&interface->dev, "Could not retrieve serial number\n");
+ goto error;
+ }
+- dbg(2," %s : serial_number=%s", __FUNCTION__, dev->serial_number);
++ dbg(2," %s : serial_number=%s", __func__, dev->serial_number);
+
+ /* we can register the device now, as it is ready */
+ usb_set_intfdata(interface, dev);
+@@ -828,7 +828,7 @@ static int adu_probe(struct usb_interface *interface,
+ udev->descriptor.idProduct, dev->serial_number,
+ (dev->minor - ADU_MINOR_BASE));
+ exit:
+- dbg(2," %s : leave, return value %p (dev)", __FUNCTION__, dev);
++ dbg(2," %s : leave, return value %p (dev)", __func__, dev);
+
+ return retval;
+
+@@ -847,7 +847,7 @@ static void adu_disconnect(struct usb_interface *interface)
+ struct adu_device *dev;
+ int minor;
+
+- dbg(2," %s : enter", __FUNCTION__);
++ dbg(2," %s : enter", __func__);
+
+ dev = usb_get_intfdata(interface);
+
+@@ -861,7 +861,7 @@ static void adu_disconnect(struct usb_interface *interface)
+ usb_set_intfdata(interface, NULL);
+
+ /* if the device is not opened, then we clean up right now */
+- dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
++ dbg(2," %s : open count %d", __func__, dev->open_count);
+ if (!dev->open_count)
+ adu_delete(dev);
+
+@@ -870,7 +870,7 @@ static void adu_disconnect(struct usb_interface *interface)
+ dev_info(&interface->dev, "ADU device adutux%d now disconnected\n",
+ (minor - ADU_MINOR_BASE));
+
+- dbg(2," %s : leave", __FUNCTION__);
++ dbg(2," %s : leave", __func__);
+ }
+
+ /* usb specific object needed to register this driver with the usb subsystem */
+@@ -885,7 +885,7 @@ static int __init adu_init(void)
+ {
+ int result;
+
+- dbg(2," %s : enter", __FUNCTION__);
++ dbg(2," %s : enter", __func__);
+
+ /* register this driver with the USB subsystem */
+ result = usb_register(&adu_driver);
+@@ -899,17 +899,17 @@ static int __init adu_init(void)
+ info("adutux is an experimental driver. Use at your own risk");
+
+ exit:
+- dbg(2," %s : leave, return value %d", __FUNCTION__, result);
++ dbg(2," %s : leave, return value %d", __func__, result);
+
+ return result;
+ }
+
+ static void __exit adu_exit(void)
+ {
+- dbg(2," %s : enter", __FUNCTION__);
++ dbg(2," %s : enter", __func__);
+ /* deregister this driver with the USB subsystem */
+ usb_deregister(&adu_driver);
+- dbg(2," %s : leave", __FUNCTION__);
++ dbg(2," %s : leave", __func__);
+ }
+
+ module_init(adu_init);
+diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
+index 1cb56f2..a076c24 100644
+--- a/drivers/usb/misc/appledisplay.c
++++ b/drivers/usb/misc/appledisplay.c
+@@ -29,7 +29,6 @@
+ #include <linux/timer.h>
+ #include <linux/workqueue.h>
+ #include <asm/atomic.h>
+-#include <asm/semaphore.h>
+
+ #define APPLE_VENDOR_ID 0x05AC
+
+@@ -104,11 +103,11 @@ static void appledisplay_complete(struct urb *urb)
+ case -ESHUTDOWN:
+ /* This urb is terminated, clean up */
+ dbg("%s - urb shuttingdown with status: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ goto exit;
+ }
+
+@@ -132,7 +131,7 @@ exit:
+ retval = usb_submit_urb(pdata->urb, GFP_ATOMIC);
+ if (retval) {
+ err("%s - usb_submit_urb failed with result %d",
+- __FUNCTION__, retval);
++ __func__, retval);
+ }
+ }
+
+diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
+index df7e1ec..0939386 100644
+--- a/drivers/usb/misc/auerswald.c
++++ b/drivers/usb/misc/auerswald.c
+@@ -31,6 +31,7 @@
+ #include <linux/init.h>
+ #include <linux/wait.h>
+ #include <linux/usb.h>
++#include <linux/mutex.h>
+
+ /*-------------------------------------------------------------------*/
+ /* Debug support */
+@@ -232,7 +233,7 @@ typedef struct auerscon
+ /* USB device context */
+ typedef struct
+ {
+- struct semaphore mutex; /* protection in user context */
++ struct mutex mutex; /* protection in user context */
+ char name[20]; /* name of the /dev/usb entry */
+ unsigned int dtindex; /* index in the device table */
+ struct usb_device * usbdev; /* USB device handle */
+@@ -253,12 +254,12 @@ typedef struct
+ /* character device context */
+ typedef struct
+ {
+- struct semaphore mutex; /* protection in user context */
++ struct mutex mutex; /* protection in user context */
+ pauerswald_t auerdev; /* context pointer of assigned device */
+ auerbufctl_t bufctl; /* controls the buffer chain */
+ auerscon_t scontext; /* service context */
+ wait_queue_head_t readwait; /* for synchronous reading */
+- struct semaphore readmutex; /* protection against multiple reads */
++ struct mutex readmutex; /* protection against multiple reads */
+ pauerbuf_t readbuf; /* buffer held for partial reading */
+ unsigned int readoffset; /* current offset in readbuf */
+ unsigned int removed; /* is != 0 if device is removed */
+@@ -283,7 +284,7 @@ static void auerchain_complete (struct urb * urb)
+ int result;
+
+ /* get pointer to element and to chain */
+- pauerchainelement_t acep = (pauerchainelement_t) urb->context;
++ pauerchainelement_t acep = urb->context;
+ pauerchain_t acp = acep->chain;
+
+ /* restore original entries in urb */
+@@ -593,7 +594,7 @@ ac_fail:/* free the elements */
+ /* completion handler for synchronous chained URBs */
+ static void auerchain_blocking_completion (struct urb *urb)
+ {
+- pauerchain_chs_t pchs = (pauerchain_chs_t)urb->context;
++ pauerchain_chs_t pchs = urb->context;
+ pchs->done = 1;
+ wmb();
+ wake_up (&pchs->wqh);
+@@ -846,7 +847,7 @@ static int auerswald_status_retry (int status)
+ /* Completion of asynchronous write block */
+ static void auerchar_ctrlwrite_complete (struct urb * urb)
+ {
+- pauerbuf_t bp = (pauerbuf_t) urb->context;
++ pauerbuf_t bp = urb->context;
+ pauerswald_t cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl)));
+ dbg ("auerchar_ctrlwrite_complete called");
+
+@@ -859,7 +860,7 @@ static void auerchar_ctrlwrite_complete (struct urb * urb)
+ /* Completion handler for dummy retry packet */
+ static void auerswald_ctrlread_wretcomplete (struct urb * urb)
+ {
+- pauerbuf_t bp = (pauerbuf_t) urb->context;
++ pauerbuf_t bp = urb->context;
+ pauerswald_t cp;
+ int ret;
+ int status = urb->status;
+@@ -903,7 +904,7 @@ static void auerswald_ctrlread_complete (struct urb * urb)
+ unsigned int serviceid;
+ pauerswald_t cp;
+ pauerscon_t scp;
+- pauerbuf_t bp = (pauerbuf_t) urb->context;
++ pauerbuf_t bp = urb->context;
+ int status = urb->status;
+ int ret;
+
+@@ -980,9 +981,9 @@ static void auerswald_int_complete (struct urb * urb)
+ int ret;
+ int status = urb->status;
+ pauerbuf_t bp = NULL;
+- pauerswald_t cp = (pauerswald_t) urb->context;
++ pauerswald_t cp = urb->context;
+
+- dbg ("%s called", __FUNCTION__);
++ dbg ("%s called", __func__);
+
+ switch (status) {
+ case 0:
+@@ -992,10 +993,10 @@ static void auerswald_int_complete (struct urb * urb)
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+- dbg("%s - urb shutting down with status: %d", __FUNCTION__, status);
++ dbg("%s - urb shutting down with status: %d", __func__, status);
+ return;
+ default:
+- dbg("%s - nonzero urb status received: %d", __FUNCTION__, status);
++ dbg("%s - nonzero urb status received: %d", __func__, status);
+ goto exit;
+ }
+
+@@ -1080,7 +1081,7 @@ exit:
+ ret = usb_submit_urb (urb, GFP_ATOMIC);
+ if (ret)
+ err ("%s - usb_submit_urb failed with result %d",
+- __FUNCTION__, ret);
++ __func__, ret);
+ }
+
+ /* int memory deallocation
+@@ -1376,7 +1377,7 @@ static int auerchar_open (struct inode *inode, struct file *file)
+ if (cp == NULL) {
+ return -ENODEV;
+ }
+- if (down_interruptible (&cp->mutex)) {
++ if (mutex_lock_interruptible(&cp->mutex)) {
+ return -ERESTARTSYS;
+ }
+
+@@ -1389,8 +1390,8 @@ static int auerchar_open (struct inode *inode, struct file *file)
+ }
+
+ /* Initialize device descriptor */
+- init_MUTEX( &ccp->mutex);
+- init_MUTEX( &ccp->readmutex);
++ mutex_init(&ccp->mutex);
++ mutex_init(&ccp->readmutex);
+ auerbuf_init (&ccp->bufctl);
+ ccp->scontext.id = AUH_UNASSIGNED;
+ ccp->scontext.dispatch = auerchar_ctrlread_dispatch;
+@@ -1405,7 +1406,7 @@ static int auerchar_open (struct inode *inode, struct file *file)
+ cp->open_count++;
+ ccp->auerdev = cp;
+ dbg("open %s as /dev/%s", cp->dev_desc, cp->name);
+- up (&cp->mutex);
++ mutex_unlock(&cp->mutex);
+
+ /* file IO stuff */
+ file->f_pos = 0;
+@@ -1413,7 +1414,7 @@ static int auerchar_open (struct inode *inode, struct file *file)
+ return nonseekable_open(inode, file);
+
+ /* Error exit */
+-ofail: up (&cp->mutex);
++ofail: mutex_unlock(&cp->mutex);
+ auerchar_delete (ccp);
+ return ret;
+ }
+@@ -1432,23 +1433,23 @@ static int auerchar_ioctl (struct inode *inode, struct file *file, unsigned int
+ dbg ("ioctl");
+
+ /* get the mutexes */
+- if (down_interruptible (&ccp->mutex)) {
++ if (mutex_lock_interruptible(&ccp->mutex)) {
+ return -ERESTARTSYS;
+ }
+ cp = ccp->auerdev;
+ if (!cp) {
+- up (&ccp->mutex);
++ mutex_unlock(&ccp->mutex);
+ return -ENODEV;
+ }
+- if (down_interruptible (&cp->mutex)) {
+- up(&ccp->mutex);
++ if (mutex_lock_interruptible(&cp->mutex)) {
++ mutex_unlock(&ccp->mutex);
+ return -ERESTARTSYS;
+ }
+
+ /* Check for removal */
+ if (!cp->usbdev) {
+- up(&cp->mutex);
+- up(&ccp->mutex);
++ mutex_unlock(&cp->mutex);
++ mutex_unlock(&ccp->mutex);
+ return -ENODEV;
+ }
+
+@@ -1550,8 +1551,8 @@ static int auerchar_ioctl (struct inode *inode, struct file *file, unsigned int
+ break;
+ }
+ /* release the mutexes */
+- up(&cp->mutex);
+- up(&ccp->mutex);
++ mutex_unlock(&cp->mutex);
++ mutex_unlock(&ccp->mutex);
+ return ret;
+ }
+
+@@ -1574,18 +1575,18 @@ static ssize_t auerchar_read (struct file *file, char __user *buf, size_t count,
+ return 0;
+
+ /* get the mutex */
+- if (down_interruptible (&ccp->mutex))
++ if (mutex_lock_interruptible(&ccp->mutex))
+ return -ERESTARTSYS;
+
+ /* Can we expect to read something? */
+ if (ccp->scontext.id == AUH_UNASSIGNED) {
+- up (&ccp->mutex);
++ mutex_unlock(&ccp->mutex);
+ return -EIO;
+ }
+
+ /* only one reader per device allowed */
+- if (down_interruptible (&ccp->readmutex)) {
+- up (&ccp->mutex);
++ if (mutex_lock_interruptible(&ccp->readmutex)) {
++ mutex_unlock(&ccp->mutex);
+ return -ERESTARTSYS;
+ }
+
+@@ -1602,8 +1603,8 @@ doreadbuf:
+ if (count) {
+ if (copy_to_user (buf, bp->bufp+ccp->readoffset, count)) {
+ dbg ("auerswald_read: copy_to_user failed");
+- up (&ccp->readmutex);
+- up (&ccp->mutex);
++ mutex_unlock(&ccp->readmutex);
++ mutex_unlock(&ccp->mutex);
+ return -EFAULT;
+ }
+ }
+@@ -1617,8 +1618,8 @@ doreadbuf:
+ }
+ /* return with number of bytes read */
+ if (count) {
+- up (&ccp->readmutex);
+- up (&ccp->mutex);
++ mutex_unlock(&ccp->readmutex);
++ mutex_unlock(&ccp->mutex);
+ return count;
+ }
+ }
+@@ -1654,29 +1655,29 @@ doreadlist:
+ dbg ("No read buffer available, returning -EAGAIN");
+ set_current_state (TASK_RUNNING);
+ remove_wait_queue (&ccp->readwait, &wait);
+- up (&ccp->readmutex);
+- up (&ccp->mutex);
++ mutex_unlock(&ccp->readmutex);
++ mutex_unlock(&ccp->mutex);
+ return -EAGAIN; /* nonblocking, no data available */
+ }
+
+ /* yes, we should wait! */
+- up (&ccp->mutex); /* allow other operations while we wait */
++ mutex_unlock(&ccp->mutex); /* allow other operations while we wait */
+ schedule();
+ remove_wait_queue (&ccp->readwait, &wait);
+ if (signal_pending (current)) {
+ /* waked up by a signal */
+- up (&ccp->readmutex);
++ mutex_unlock(&ccp->readmutex);
+ return -ERESTARTSYS;
+ }
+
+ /* Anything left to read? */
+ if ((ccp->scontext.id == AUH_UNASSIGNED) || ccp->removed) {
+- up (&ccp->readmutex);
++ mutex_unlock(&ccp->readmutex);
+ return -EIO;
+ }
+
+- if (down_interruptible (&ccp->mutex)) {
+- up (&ccp->readmutex);
++ if (mutex_lock_interruptible(&ccp->mutex)) {
++ mutex_unlock(&ccp->readmutex);
+ return -ERESTARTSYS;
+ }
+
+@@ -1707,27 +1708,27 @@ static ssize_t auerchar_write (struct file *file, const char __user *buf, size_t
+
+ write_again:
+ /* get the mutex */
+- if (down_interruptible (&ccp->mutex))
++ if (mutex_lock_interruptible(&ccp->mutex))
+ return -ERESTARTSYS;
+
+ /* Can we expect to write something? */
+ if (ccp->scontext.id == AUH_UNASSIGNED) {
+- up (&ccp->mutex);
++ mutex_unlock(&ccp->mutex);
+ return -EIO;
+ }
+
+ cp = ccp->auerdev;
+ if (!cp) {
+- up (&ccp->mutex);
++ mutex_unlock(&ccp->mutex);
+ return -ERESTARTSYS;
+ }
+- if (down_interruptible (&cp->mutex)) {
+- up (&ccp->mutex);
++ if (mutex_lock_interruptible(&cp->mutex)) {
++ mutex_unlock(&ccp->mutex);
+ return -ERESTARTSYS;
+ }
+ if (!cp->usbdev) {
+- up (&cp->mutex);
+- up (&ccp->mutex);
++ mutex_unlock(&cp->mutex);
++ mutex_unlock(&ccp->mutex);
+ return -EIO;
+ }
+ /* Prepare for sleep */
+@@ -1750,8 +1751,8 @@ write_again:
+
+ /* are there any buffers left? */
+ if (!bp) {
+- up (&cp->mutex);
+- up (&ccp->mutex);
++ mutex_unlock(&cp->mutex);
++ mutex_unlock(&ccp->mutex);
+
+ /* NONBLOCK: don't wait */
+ if (file->f_flags & O_NONBLOCK) {
+@@ -1783,8 +1784,8 @@ write_again:
+ auerbuf_releasebuf (bp);
+ /* Wake up all processes waiting for a buffer */
+ wake_up (&cp->bufferwait);
+- up (&cp->mutex);
+- up (&ccp->mutex);
++ mutex_unlock(&cp->mutex);
++ mutex_unlock(&ccp->mutex);
+ return -EFAULT;
+ }
+
+@@ -1803,18 +1804,18 @@ write_again:
+ auerchar_ctrlwrite_complete, bp);
+ /* up we go */
+ ret = auerchain_submit_urb (&cp->controlchain, bp->urbp);
+- up (&cp->mutex);
++ mutex_unlock(&cp->mutex);
+ if (ret) {
+ dbg ("auerchar_write: nonzero result of auerchain_submit_urb %d", ret);
+ auerbuf_releasebuf (bp);
+ /* Wake up all processes waiting for a buffer */
+ wake_up (&cp->bufferwait);
+- up (&ccp->mutex);
++ mutex_unlock(&ccp->mutex);
+ return -EIO;
+ }
+ else {
+ dbg ("auerchar_write: Write OK");
+- up (&ccp->mutex);
++ mutex_unlock(&ccp->mutex);
+ return len;
+ }
+ }
+@@ -1827,24 +1828,24 @@ static int auerchar_release (struct inode *inode, struct file *file)
+ pauerswald_t cp;
+ dbg("release");
+
+- down(&ccp->mutex);
++ mutex_lock(&ccp->mutex);
+ cp = ccp->auerdev;
+ if (cp) {
+- down(&cp->mutex);
++ mutex_lock(&cp->mutex);
+ /* remove an open service */
+ auerswald_removeservice (cp, &ccp->scontext);
+ /* detach from device */
+ if ((--cp->open_count <= 0) && (cp->usbdev == NULL)) {
+ /* usb device waits for removal */
+- up (&cp->mutex);
++ mutex_unlock(&cp->mutex);
+ auerswald_delete (cp);
+ } else {
+- up (&cp->mutex);
++ mutex_unlock(&cp->mutex);
+ }
+ cp = NULL;
+ ccp->auerdev = NULL;
+ }
+- up (&ccp->mutex);
++ mutex_unlock(&ccp->mutex);
+ auerchar_delete (ccp);
+
+ return 0;
+@@ -1917,7 +1918,7 @@ static int auerswald_probe (struct usb_interface *intf,
+ }
+
+ /* Initialize device descriptor */
+- init_MUTEX (&cp->mutex);
++ mutex_init(&cp->mutex);
+ cp->usbdev = usbdev;
+ auerchain_init (&cp->controlchain);
+ auerbuf_init (&cp->bufctl);
+@@ -2042,7 +2043,7 @@ static void auerswald_disconnect (struct usb_interface *intf)
+ /* give back our USB minor number */
+ usb_deregister_dev(intf, &auerswald_class);
+
+- down (&cp->mutex);
++ mutex_lock(&cp->mutex);
+ info ("device /dev/%s now disconnecting", cp->name);
+
+ /* Stop the interrupt endpoint */
+@@ -2057,16 +2058,18 @@ static void auerswald_disconnect (struct usb_interface *intf)
+
+ if (cp->open_count == 0) {
+ /* nobody is using this device. So we can clean up now */
+- up (&cp->mutex);/* up() is possible here because no other task
+- can open the device (see above). I don't want
+- to kfree() a locked mutex. */
++ mutex_unlock(&cp->mutex);
++ /* mutex_unlock() is possible here because no other task
++ can open the device (see above). I don't want
++ to kfree() a locked mutex. */
++
+ auerswald_delete (cp);
+ } else {
+ /* device is used. Remove the pointer to the
+ usb device (it's not valid any more). The last
+ release() will do the clean up */
+ cp->usbdev = NULL;
+- up (&cp->mutex);
++ mutex_unlock(&cp->mutex);
+ /* Terminate waiting writers */
+ wake_up (&cp->bufferwait);
+ /* Inform all waiting readers */
+diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
+index 148b7fe..ec88b3b 100644
+--- a/drivers/usb/misc/ftdi-elan.c
++++ b/drivers/usb/misc/ftdi-elan.c
+@@ -746,7 +746,7 @@ static ssize_t ftdi_elan_read(struct file *file, char __user *buffer,
+
+ static void ftdi_elan_write_bulk_callback(struct urb *urb)
+ {
+- struct usb_ftdi *ftdi = (struct usb_ftdi *)urb->context;
++ struct usb_ftdi *ftdi = urb->context;
+ int status = urb->status;
+
+ if (status && !(status == -ENOENT || status == -ECONNRESET ||
+diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
+index 8010705..1cb54a2 100644
+--- a/drivers/usb/misc/iowarrior.c
++++ b/drivers/usb/misc/iowarrior.c
+@@ -154,7 +154,7 @@ MODULE_DEVICE_TABLE(usb, iowarrior_ids);
+ */
+ static void iowarrior_callback(struct urb *urb)
+ {
+- struct iowarrior *dev = (struct iowarrior *)urb->context;
++ struct iowarrior *dev = urb->context;
+ int intr_idx;
+ int read_idx;
+ int aux_idx;
+@@ -218,7 +218,7 @@ exit:
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval)
+ dev_err(&dev->interface->dev, "%s - usb_submit_urb failed with result %d\n",
+- __FUNCTION__, retval);
++ __func__, retval);
+
+ }
+
+@@ -230,7 +230,7 @@ static void iowarrior_write_callback(struct urb *urb)
+ struct iowarrior *dev;
+ int status = urb->status;
+
+- dev = (struct iowarrior *)urb->context;
++ dev = urb->context;
+ /* sync/async unlink faults aren't errors */
+ if (status &&
+ !(status == -ENOENT ||
+@@ -453,7 +453,7 @@ static ssize_t iowarrior_write(struct file *file,
+ default:
+ /* what do we have here ? An unsupported Product-ID ? */
+ dev_err(&dev->interface->dev, "%s - not supported for product=0x%x\n",
+- __FUNCTION__, dev->product_id);
++ __func__, dev->product_id);
+ retval = -EFAULT;
+ goto exit;
+ break;
+@@ -604,7 +604,7 @@ static int iowarrior_open(struct inode *inode, struct file *file)
+
+ interface = usb_find_interface(&iowarrior_driver, subminor);
+ if (!interface) {
+- err("%s - error, can't find device for minor %d", __FUNCTION__,
++ err("%s - error, can't find device for minor %d", __func__,
+ subminor);
+ return -ENODEV;
+ }
+diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
+index c730d20..11580e8 100644
+--- a/drivers/usb/misc/ldusb.c
++++ b/drivers/usb/misc/ldusb.c
+@@ -231,7 +231,7 @@ static void ld_usb_interrupt_in_callback(struct urb *urb)
+ goto exit;
+ } else {
+ dbg_info(&dev->intf->dev, "%s: nonzero status received: %d\n",
+- __FUNCTION__, status);
++ __func__, status);
+ spin_lock(&dev->rbsl);
+ goto resubmit; /* maybe we can recover */
+ }
+@@ -247,7 +247,7 @@ static void ld_usb_interrupt_in_callback(struct urb *urb)
+ memcpy(actual_buffer+1, dev->interrupt_in_buffer, urb->actual_length);
+ dev->ring_head = next_ring_head;
+ dbg_info(&dev->intf->dev, "%s: received %d bytes\n",
+- __FUNCTION__, urb->actual_length);
++ __func__, urb->actual_length);
+ } else {
+ dev_warn(&dev->intf->dev,
+ "Ring buffer overflow, %d bytes dropped\n",
+@@ -286,7 +286,7 @@ static void ld_usb_interrupt_out_callback(struct urb *urb)
+ status == -ESHUTDOWN))
+ dbg_info(&dev->intf->dev,
+ "%s - nonzero write interrupt status received: %d\n",
+- __FUNCTION__, status);
++ __func__, status);
+
+ dev->interrupt_out_busy = 0;
+ wake_up_interruptible(&dev->write_wait);
+@@ -309,7 +309,7 @@ static int ld_usb_open(struct inode *inode, struct file *file)
+
+ if (!interface) {
+ err("%s - error, can't find device for minor %d\n",
+- __FUNCTION__, subminor);
++ __func__, subminor);
+ return -ENODEV;
+ }
+
+@@ -556,7 +556,7 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer,
+ bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size);
+ if (bytes_to_write < count)
+ dev_warn(&dev->intf->dev, "Write buffer overflow, %zd bytes dropped\n",count-bytes_to_write);
+- dbg_info(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", __FUNCTION__, count, bytes_to_write);
++ dbg_info(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", __func__, count, bytes_to_write);
+
+ if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) {
+ retval = -EFAULT;
+diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
+index 6664043..9370326 100644
+--- a/drivers/usb/misc/legousbtower.c
++++ b/drivers/usb/misc/legousbtower.c
+@@ -31,7 +31,7 @@
+ * - imported into lejos project
+ * - changed wake_up to wake_up_interruptible
+ * - changed to use lego0 rather than tower0
+- * - changed dbg() to use __func__ rather than deprecated __FUNCTION__
++ * - changed dbg() to use __func__ rather than deprecated __func__
+ * 2003-01-12 - 0.53 david (david at csse.uwa.edu.au)
+ * - changed read and write to write everything or
+ * timeout (from a patch by Chris Riesen and Brett Thaeler driver)
+@@ -49,7 +49,7 @@
+ * - added poll
+ * - forbid seeking
+ * - added nonblocking I/O
+- * - changed back __func__ to __FUNCTION__
++ * - changed back __func__ to __func__
+ * - read and log tower firmware version
+ * - reset tower on probe, avoids failure of first write
+ * 2004-03-09 - 0.7 Juergen Stuber <starblue at users.sourceforge.net>
+@@ -309,7 +309,7 @@ static inline void lego_usb_tower_debug_data (int level, const char *function, i
+ */
+ static inline void tower_delete (struct lego_usb_tower *dev)
+ {
+- dbg(2, "%s: enter", __FUNCTION__);
++ dbg(2, "%s: enter", __func__);
+
+ tower_abort_transfers (dev);
+
+@@ -321,7 +321,7 @@ static inline void tower_delete (struct lego_usb_tower *dev)
+ kfree (dev->interrupt_out_buffer);
+ kfree (dev);
+
+- dbg(2, "%s: leave", __FUNCTION__);
++ dbg(2, "%s: leave", __func__);
+ }
+
+
+@@ -337,7 +337,7 @@ static int tower_open (struct inode *inode, struct file *file)
+ struct tower_reset_reply reset_reply;
+ int result;
+
+- dbg(2, "%s: enter", __FUNCTION__);
++ dbg(2, "%s: enter", __func__);
+
+ nonseekable_open(inode, file);
+ subminor = iminor(inode);
+@@ -346,7 +346,7 @@ static int tower_open (struct inode *inode, struct file *file)
+
+ if (!interface) {
+ err ("%s - error, can't find device for minor %d",
+- __FUNCTION__, subminor);
++ __func__, subminor);
+ retval = -ENODEV;
+ goto exit;
+ }
+@@ -424,7 +424,7 @@ unlock_exit:
+ mutex_unlock(&dev->lock);
+
+ exit:
+- dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval);
++ dbg(2, "%s: leave, return value %d ", __func__, retval);
+
+ return retval;
+ }
+@@ -437,12 +437,12 @@ static int tower_release (struct inode *inode, struct file *file)
+ struct lego_usb_tower *dev;
+ int retval = 0;
+
+- dbg(2, "%s: enter", __FUNCTION__);
++ dbg(2, "%s: enter", __func__);
+
+ dev = (struct lego_usb_tower *)file->private_data;
+
+ if (dev == NULL) {
+- dbg(1, "%s: object is NULL", __FUNCTION__);
++ dbg(1, "%s: object is NULL", __func__);
+ retval = -ENODEV;
+ goto exit_nolock;
+ }
+@@ -454,7 +454,7 @@ static int tower_release (struct inode *inode, struct file *file)
+ }
+
+ if (dev->open_count != 1) {
+- dbg(1, "%s: device not opened exactly once", __FUNCTION__);
++ dbg(1, "%s: device not opened exactly once", __func__);
+ retval = -ENODEV;
+ goto unlock_exit;
+ }
+@@ -480,7 +480,7 @@ unlock_exit:
+ exit:
+ mutex_unlock(&open_disc_mutex);
+ exit_nolock:
+- dbg(2, "%s: leave, return value %d", __FUNCTION__, retval);
++ dbg(2, "%s: leave, return value %d", __func__, retval);
+ return retval;
+ }
+
+@@ -491,10 +491,10 @@ exit_nolock:
+ */
+ static void tower_abort_transfers (struct lego_usb_tower *dev)
+ {
+- dbg(2, "%s: enter", __FUNCTION__);
++ dbg(2, "%s: enter", __func__);
+
+ if (dev == NULL) {
+- dbg(1, "%s: dev is null", __FUNCTION__);
++ dbg(1, "%s: dev is null", __func__);
+ goto exit;
+ }
+
+@@ -509,7 +509,7 @@ static void tower_abort_transfers (struct lego_usb_tower *dev)
+ usb_kill_urb(dev->interrupt_out_urb);
+
+ exit:
+- dbg(2, "%s: leave", __FUNCTION__);
++ dbg(2, "%s: leave", __func__);
+ }
+
+
+@@ -542,7 +542,7 @@ static unsigned int tower_poll (struct file *file, poll_table *wait)
+ struct lego_usb_tower *dev;
+ unsigned int mask = 0;
+
+- dbg(2, "%s: enter", __FUNCTION__);
++ dbg(2, "%s: enter", __func__);
+
+ dev = file->private_data;
+
+@@ -557,7 +557,7 @@ static unsigned int tower_poll (struct file *file, poll_table *wait)
+ mask |= POLLOUT | POLLWRNORM;
+ }
+
+- dbg(2, "%s: leave, mask = %d", __FUNCTION__, mask);
++ dbg(2, "%s: leave, mask = %d", __func__, mask);
+
+ return mask;
+ }
+@@ -583,7 +583,7 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count,
+ int retval = 0;
+ unsigned long timeout = 0;
+
+- dbg(2, "%s: enter, count = %Zd", __FUNCTION__, count);
++ dbg(2, "%s: enter, count = %Zd", __func__, count);
+
+ dev = (struct lego_usb_tower *)file->private_data;
+
+@@ -602,7 +602,7 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count,
+
+ /* verify that we actually have some data to read */
+ if (count == 0) {
+- dbg(1, "%s: read request of 0 bytes", __FUNCTION__);
++ dbg(1, "%s: read request of 0 bytes", __func__);
+ goto unlock_exit;
+ }
+
+@@ -658,7 +658,7 @@ unlock_exit:
+ mutex_unlock(&dev->lock);
+
+ exit:
+- dbg(2, "%s: leave, return value %d", __FUNCTION__, retval);
++ dbg(2, "%s: leave, return value %d", __func__, retval);
+ return retval;
+ }
+
+@@ -672,7 +672,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
+ size_t bytes_to_write;
+ int retval = 0;
+
+- dbg(2, "%s: enter, count = %Zd", __FUNCTION__, count);
++ dbg(2, "%s: enter, count = %Zd", __func__, count);
+
+ dev = (struct lego_usb_tower *)file->private_data;
+
+@@ -691,7 +691,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
+
+ /* verify that we actually have some data to write */
+ if (count == 0) {
+- dbg(1, "%s: write request of 0 bytes", __FUNCTION__);
++ dbg(1, "%s: write request of 0 bytes", __func__);
+ goto unlock_exit;
+ }
+
+@@ -709,7 +709,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
+
+ /* write the data into interrupt_out_buffer from userspace */
+ bytes_to_write = min_t(int, count, write_buffer_size);
+- dbg(4, "%s: count = %Zd, bytes_to_write = %Zd", __FUNCTION__, count, bytes_to_write);
++ dbg(4, "%s: count = %Zd, bytes_to_write = %Zd", __func__, count, bytes_to_write);
+
+ if (copy_from_user (dev->interrupt_out_buffer, buffer, bytes_to_write)) {
+ retval = -EFAULT;
+@@ -742,7 +742,7 @@ unlock_exit:
+ mutex_unlock(&dev->lock);
+
+ exit:
+- dbg(2, "%s: leave, return value %d", __FUNCTION__, retval);
++ dbg(2, "%s: leave, return value %d", __func__, retval);
+
+ return retval;
+ }
+@@ -753,13 +753,13 @@ exit:
+ */
+ static void tower_interrupt_in_callback (struct urb *urb)
+ {
+- struct lego_usb_tower *dev = (struct lego_usb_tower *)urb->context;
++ struct lego_usb_tower *dev = urb->context;
+ int status = urb->status;
+ int retval;
+
+- dbg(4, "%s: enter, status %d", __FUNCTION__, status);
++ dbg(4, "%s: enter, status %d", __func__, status);
+
+- lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
++ lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer);
+
+ if (status) {
+ if (status == -ENOENT ||
+@@ -767,7 +767,7 @@ static void tower_interrupt_in_callback (struct urb *urb)
+ status == -ESHUTDOWN) {
+ goto exit;
+ } else {
+- dbg(1, "%s: nonzero status received: %d", __FUNCTION__, status);
++ dbg(1, "%s: nonzero status received: %d", __func__, status);
+ goto resubmit; /* maybe we can recover */
+ }
+ }
+@@ -780,9 +780,9 @@ static void tower_interrupt_in_callback (struct urb *urb)
+ urb->actual_length);
+ dev->read_buffer_length += urb->actual_length;
+ dev->read_last_arrival = jiffies;
+- dbg(3, "%s: received %d bytes", __FUNCTION__, urb->actual_length);
++ dbg(3, "%s: received %d bytes", __func__, urb->actual_length);
+ } else {
+- printk(KERN_WARNING "%s: read_buffer overflow, %d bytes dropped", __FUNCTION__, urb->actual_length);
++ printk(KERN_WARNING "%s: read_buffer overflow, %d bytes dropped", __func__, urb->actual_length);
+ }
+ spin_unlock (&dev->read_buffer_lock);
+ }
+@@ -792,7 +792,7 @@ resubmit:
+ if (dev->interrupt_in_running && dev->udev) {
+ retval = usb_submit_urb (dev->interrupt_in_urb, GFP_ATOMIC);
+ if (retval) {
+- err("%s: usb_submit_urb failed (%d)", __FUNCTION__, retval);
++ err("%s: usb_submit_urb failed (%d)", __func__, retval);
+ }
+ }
+
+@@ -800,8 +800,8 @@ exit:
+ dev->interrupt_in_done = 1;
+ wake_up_interruptible (&dev->read_wait);
+
+- lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
+- dbg(4, "%s: leave, status %d", __FUNCTION__, status);
++ lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer);
++ dbg(4, "%s: leave, status %d", __func__, status);
+ }
+
+
+@@ -810,25 +810,25 @@ exit:
+ */
+ static void tower_interrupt_out_callback (struct urb *urb)
+ {
+- struct lego_usb_tower *dev = (struct lego_usb_tower *)urb->context;
++ struct lego_usb_tower *dev = urb->context;
+ int status = urb->status;
+
+- dbg(4, "%s: enter, status %d", __FUNCTION__, status);
+- lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
++ dbg(4, "%s: enter, status %d", __func__, status);
++ lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer);
+
+ /* sync/async unlink faults aren't errors */
+ if (status && !(status == -ENOENT ||
+ status == -ECONNRESET ||
+ status == -ESHUTDOWN)) {
+ dbg(1, "%s - nonzero write bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ }
+
+ dev->interrupt_out_busy = 0;
+ wake_up_interruptible(&dev->write_wait);
+
+- lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
+- dbg(4, "%s: leave, status %d", __FUNCTION__, status);
++ lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer);
++ dbg(4, "%s: leave, status %d", __func__, status);
+ }
+
+
+@@ -849,7 +849,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
+ int retval = -ENOMEM;
+ int result;
+
+- dbg(2, "%s: enter", __FUNCTION__);
++ dbg(2, "%s: enter", __func__);
+
+ if (udev == NULL) {
+ info ("udev is NULL.");
+@@ -978,7 +978,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
+
+
+ exit:
+- dbg(2, "%s: leave, return value 0x%.8lx (dev)", __FUNCTION__, (long) dev);
++ dbg(2, "%s: leave, return value 0x%.8lx (dev)", __func__, (long) dev);
+
+ return retval;
+
+@@ -998,7 +998,7 @@ static void tower_disconnect (struct usb_interface *interface)
+ struct lego_usb_tower *dev;
+ int minor;
+
+- dbg(2, "%s: enter", __FUNCTION__);
++ dbg(2, "%s: enter", __func__);
+
+ dev = usb_get_intfdata (interface);
+ mutex_lock(&open_disc_mutex);
+@@ -1023,7 +1023,7 @@ static void tower_disconnect (struct usb_interface *interface)
+
+ info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE));
+
+- dbg(2, "%s: leave", __FUNCTION__);
++ dbg(2, "%s: leave", __func__);
+ }
+
+
+@@ -1036,7 +1036,7 @@ static int __init lego_usb_tower_init(void)
+ int result;
+ int retval = 0;
+
+- dbg(2, "%s: enter", __FUNCTION__);
++ dbg(2, "%s: enter", __func__);
+
+ /* register this driver with the USB subsystem */
+ result = usb_register(&tower_driver);
+@@ -1049,7 +1049,7 @@ static int __init lego_usb_tower_init(void)
+ info(DRIVER_DESC " " DRIVER_VERSION);
+
+ exit:
+- dbg(2, "%s: leave, return value %d", __FUNCTION__, retval);
++ dbg(2, "%s: leave, return value %d", __func__, retval);
+
+ return retval;
+ }
+@@ -1060,12 +1060,12 @@ exit:
+ */
+ static void __exit lego_usb_tower_exit(void)
+ {
+- dbg(2, "%s: enter", __FUNCTION__);
++ dbg(2, "%s: enter", __func__);
+
+ /* deregister this driver with the USB subsystem */
+ usb_deregister (&tower_driver);
+
+- dbg(2, "%s: leave", __FUNCTION__);
++ dbg(2, "%s: leave", __func__);
+ }
+
+ module_init (lego_usb_tower_init);
+diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c
+index aa9bcce..24230c6 100644
+--- a/drivers/usb/misc/phidgetkit.c
++++ b/drivers/usb/misc/phidgetkit.c
+@@ -113,7 +113,7 @@ static int set_outputs(struct interfacekit *kit)
+
+ buffer = kzalloc(4, GFP_KERNEL);
+ if (!buffer) {
+- dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__);
++ dev_err(&kit->udev->dev, "%s - out of memory\n", __func__);
+ return -ENOMEM;
+ }
+ buffer[0] = (u8)kit->outputs;
+@@ -146,7 +146,7 @@ static int change_string(struct interfacekit *kit, const char *display, unsigned
+ buffer = kmalloc(8, GFP_KERNEL);
+ form_buffer = kmalloc(30, GFP_KERNEL);
+ if ((!buffer) || (!form_buffer)) {
+- dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__);
++ dev_err(&kit->udev->dev, "%s - out of memory\n", __func__);
+ goto exit;
+ }
+
+@@ -216,7 +216,7 @@ static ssize_t set_backlight(struct device *dev, struct device_attribute *attr,
+
+ buffer = kzalloc(8, GFP_KERNEL);
+ if (!buffer) {
+- dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__);
++ dev_err(&kit->udev->dev, "%s - out of memory\n", __func__);
+ goto exit;
+ }
+
+diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c
+index 2ad09b1..f0113c1 100644
+--- a/drivers/usb/misc/phidgetmotorcontrol.c
++++ b/drivers/usb/misc/phidgetmotorcontrol.c
+@@ -61,7 +61,7 @@ static int set_motor(struct motorcontrol *mc, int motor)
+
+ buffer = kzalloc(8, GFP_KERNEL);
+ if (!buffer) {
+- dev_err(&mc->intf->dev, "%s - out of memory\n", __FUNCTION__);
++ dev_err(&mc->intf->dev, "%s - out of memory\n", __func__);
+ return -ENOMEM;
+ }
+
+diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c
+index 0d9de2f..7d590c0 100644
+--- a/drivers/usb/misc/phidgetservo.c
++++ b/drivers/usb/misc/phidgetservo.c
+@@ -89,7 +89,7 @@ change_position_v30(struct phidget_servo *servo, int servo_no, int degrees,
+ buffer = kmalloc(6, GFP_KERNEL);
+ if (!buffer) {
+ dev_err(&servo->udev->dev, "%s - out of memory\n",
+- __FUNCTION__);
++ __func__);
+ return -ENOMEM;
+ }
+
+@@ -162,7 +162,7 @@ change_position_v20(struct phidget_servo *servo, int servo_no, int degrees,
+ buffer = kmalloc(2, GFP_KERNEL);
+ if (!buffer) {
+ dev_err(&servo->udev->dev, "%s - out of memory\n",
+- __FUNCTION__);
++ __func__);
+ return -ENOMEM;
+ }
+
+@@ -259,7 +259,7 @@ servo_probe(struct usb_interface *interface, const struct usb_device_id *id)
+
+ dev = kzalloc(sizeof (struct phidget_servo), GFP_KERNEL);
+ if (dev == NULL) {
+- dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__);
++ dev_err(&interface->dev, "%s - out of memory\n", __func__);
+ rc = -ENOMEM;
+ goto out;
+ }
+diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
+index 20777d0..7f7021e 100644
+--- a/drivers/usb/misc/usblcd.c
++++ b/drivers/usb/misc/usblcd.c
+@@ -78,7 +78,7 @@ static int lcd_open(struct inode *inode, struct file *file)
+ interface = usb_find_interface(&lcd_driver, subminor);
+ if (!interface) {
+ err ("USBLCD: %s - error, can't find device for minor %d",
+- __FUNCTION__, subminor);
++ __func__, subminor);
+ return -ENODEV;
+ }
+
+@@ -185,7 +185,7 @@ static void lcd_write_bulk_callback(struct urb *urb)
+ struct usb_lcd *dev;
+ int status = urb->status;
+
+- dev = (struct usb_lcd *)urb->context;
++ dev = urb->context;
+
+ /* sync/async unlink faults aren't errors */
+ if (status &&
+@@ -193,7 +193,7 @@ static void lcd_write_bulk_callback(struct urb *urb)
+ status == -ECONNRESET ||
+ status == -ESHUTDOWN)) {
+ dbg("USBLCD: %s - nonzero write bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ }
+
+ /* free up our allocated buffer */
+@@ -248,7 +248,7 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, siz
+ /* send the data out the bulk port */
+ retval = usb_submit_urb(urb, GFP_KERNEL);
+ if (retval) {
+- err("USBLCD: %s - failed submitting write urb, error %d", __FUNCTION__, retval);
++ err("USBLCD: %s - failed submitting write urb, error %d", __func__, retval);
+ goto error_unanchor;
+ }
+
+diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
+index b6b5b2a..a519838 100644
+--- a/drivers/usb/misc/usbtest.c
++++ b/drivers/usb/misc/usbtest.c
+@@ -201,7 +201,7 @@ found:
+
+ static void simple_callback (struct urb *urb)
+ {
+- complete ((struct completion *) urb->context);
++ complete(urb->context);
+ }
+
+ static struct urb *simple_alloc_urb (
+@@ -1046,7 +1046,7 @@ static void unlink1_callback (struct urb *urb)
+ status = usb_submit_urb (urb, GFP_ATOMIC);
+ if (status) {
+ urb->status = status;
+- complete ((struct completion *) urb->context);
++ complete(urb->context);
+ }
+ }
+
+@@ -1136,7 +1136,7 @@ static int verify_not_halted (int ep, struct urb *urb)
+ dbg ("ep %02x bogus status: %04x != 0", ep, status);
+ return -EINVAL;
+ }
+- retval = simple_io (urb, 1, 0, 0, __FUNCTION__);
++ retval = simple_io (urb, 1, 0, 0, __func__);
+ if (retval != 0)
+ return -EINVAL;
+ return 0;
+@@ -1158,7 +1158,7 @@ static int verify_halted (int ep, struct urb *urb)
+ dbg ("ep %02x bogus status: %04x != 1", ep, status);
+ return -EINVAL;
+ }
+- retval = simple_io (urb, 1, 0, -EPIPE, __FUNCTION__);
++ retval = simple_io (urb, 1, 0, -EPIPE, __func__);
+ if (retval != -EPIPE)
+ return -EINVAL;
+ retval = simple_io (urb, 1, 0, -EPIPE, "verify_still_halted");
+@@ -1404,7 +1404,7 @@ static struct urb *iso_alloc_urb (
+ return NULL;
+ maxp = 0x7ff & le16_to_cpu(desc->wMaxPacketSize);
+ maxp *= 1 + (0x3 & (le16_to_cpu(desc->wMaxPacketSize) >> 11));
+- packets = (bytes + maxp - 1) / maxp;
++ packets = DIV_ROUND_UP(bytes, maxp);
+
+ urb = usb_alloc_urb (packets, GFP_KERNEL);
+ if (!urb)
+@@ -1564,7 +1564,8 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
+ if (mutex_lock_interruptible(&dev->lock))
+ return -ERESTARTSYS;
+
+- if (intf->dev.power.power_state.event != PM_EVENT_ON) {
++ /* FIXME: What if a system sleep starts while a test is running? */
++ if (!intf->is_active) {
+ mutex_unlock(&dev->lock);
+ return -EHOSTUNREACH;
+ }
+diff --git a/drivers/usb/mon/Makefile b/drivers/usb/mon/Makefile
+index 90c5953..0f76ed5 100644
+--- a/drivers/usb/mon/Makefile
++++ b/drivers/usb/mon/Makefile
+@@ -1,5 +1,5 @@
+ #
+-# Makefile for USB Core files and filesystem
++# Makefile for USB monitor
+ #
+
+ usbmon-objs := mon_main.o mon_stat.o mon_text.o mon_bin.o mon_dma.o
+diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
+index 1774ba5..4914553 100644
+--- a/drivers/usb/mon/mon_bin.c
++++ b/drivers/usb/mon/mon_bin.c
+@@ -1026,8 +1026,6 @@ mon_bin_poll(struct file *file, struct poll_table_struct *wait)
+ return mask;
+ }
+
+-#if 0
+-
+ /*
+ * open and close: just keep track of how many times the device is
+ * mapped, to use the proper memory allocation function.
+@@ -1063,13 +1061,13 @@ static int mon_bin_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+ return 0;
+ }
+
+-struct vm_operations_struct mon_bin_vm_ops = {
++static struct vm_operations_struct mon_bin_vm_ops = {
+ .open = mon_bin_vma_open,
+ .close = mon_bin_vma_close,
+ .fault = mon_bin_vma_fault,
+ };
+
+-int mon_bin_mmap(struct file *filp, struct vm_area_struct *vma)
++static int mon_bin_mmap(struct file *filp, struct vm_area_struct *vma)
+ {
+ /* don't do anything here: "fault" will set up page table entries */
+ vma->vm_ops = &mon_bin_vm_ops;
+@@ -1079,8 +1077,6 @@ int mon_bin_mmap(struct file *filp, struct vm_area_struct *vma)
+ return 0;
+ }
+
+-#endif /* 0 */
+-
+ static const struct file_operations mon_fops_binary = {
+ .owner = THIS_MODULE,
+ .open = mon_bin_open,
+@@ -1090,6 +1086,7 @@ static const struct file_operations mon_fops_binary = {
+ .poll = mon_bin_poll,
+ .ioctl = mon_bin_ioctl,
+ .release = mon_bin_release,
++ .mmap = mon_bin_mmap,
+ };
+
+ static int mon_bin_wait_event(struct file *file, struct mon_reader_bin *rp)
+diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c
+index b371ffd..442d807 100644
+--- a/drivers/usb/mon/mon_main.c
++++ b/drivers/usb/mon/mon_main.c
+@@ -129,8 +129,7 @@ static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int error)
+
+ /*
+ */
+-static void mon_bus_complete(struct mon_bus *mbus, struct urb *urb,
+- int status)
++static void mon_bus_complete(struct mon_bus *mbus, struct urb *urb, int status)
+ {
+ unsigned long flags;
+ struct list_head *pos;
+diff --git a/drivers/usb/mon/mon_stat.c b/drivers/usb/mon/mon_stat.c
+index f6d1491..c7a595c 100644
+--- a/drivers/usb/mon/mon_stat.c
++++ b/drivers/usb/mon/mon_stat.c
+@@ -59,6 +59,9 @@ static ssize_t mon_stat_read(struct file *file, char __user *buf,
+
+ static int mon_stat_release(struct inode *inode, struct file *file)
+ {
++ struct snap *sp = file->private_data;
++ file->private_data = NULL;
++ kfree(sp);
+ return 0;
+ }
+
+diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
+index c1e65df..2cffec8 100644
+--- a/drivers/usb/serial/Kconfig
++++ b/drivers/usb/serial/Kconfig
+@@ -20,8 +20,8 @@ menuconfig USB_SERIAL
+ if USB_SERIAL
+
+ config USB_SERIAL_CONSOLE
+- bool "USB Serial Console device support (EXPERIMENTAL)"
+- depends on USB_SERIAL=y && EXPERIMENTAL
++ bool "USB Serial Console device support"
++ depends on USB_SERIAL=y
+ ---help---
+ If you say Y here, it will be possible to use a USB to serial
+ converter port as the system console (the system console is the
+@@ -44,13 +44,11 @@ config USB_SERIAL_CONSOLE
+
+ config USB_EZUSB
+ bool "Functions for loading firmware on EZUSB chips"
+- depends on USB_SERIAL
+ help
+ Say Y here if you need EZUSB device support.
+
+ config USB_SERIAL_GENERIC
+ bool "USB Generic Serial Driver"
+- depends on USB_SERIAL
+ help
+ Say Y here if you want to use the generic USB serial driver. Please
+ read <file:Documentation/usb/usb-serial.txt> for more information on
+@@ -59,8 +57,7 @@ config USB_SERIAL_GENERIC
+ properly.
+
+ config USB_SERIAL_AIRCABLE
+- tristate "USB AIRcable Bluetooth Dongle Driver (EXPERIMENTAL)"
+- depends on USB_SERIAL && EXPERIMENTAL
++ tristate "USB AIRcable Bluetooth Dongle Driver"
+ help
+ Say Y here if you want to use USB AIRcable Bluetooth Dongle.
+
+@@ -69,7 +66,6 @@ config USB_SERIAL_AIRCABLE
+
+ config USB_SERIAL_AIRPRIME
+ tristate "USB AirPrime CDMA Wireless Driver"
+- depends on USB_SERIAL
+ help
+ Say Y here if you want to use a AirPrime CDMA Wireless PC card.
+
+@@ -77,8 +73,7 @@ config USB_SERIAL_AIRPRIME
+ module will be called airprime.
+
+ config USB_SERIAL_ARK3116
+- tristate "USB ARK Micro 3116 USB Serial Driver (EXPERIMENTAL)"
+- depends on USB_SERIAL && EXPERIMENTAL
++ tristate "USB ARK Micro 3116 USB Serial Driver"
+ help
+ Say Y here if you want to use a ARK Micro 3116 USB to Serial
+ device.
+@@ -88,7 +83,6 @@ config USB_SERIAL_ARK3116
+
+ config USB_SERIAL_BELKIN
+ tristate "USB Belkin and Peracom Single Port Serial Driver"
+- depends on USB_SERIAL
+ help
+ Say Y here if you want to use a Belkin USB Serial single port
+ adaptor (F5U103 is one of the model numbers) or the Peracom single
+@@ -99,7 +93,6 @@ config USB_SERIAL_BELKIN
+
+ config USB_SERIAL_CH341
+ tristate "USB Winchiphead CH341 Single Port Serial Driver"
+- depends on USB_SERIAL
+ help
+ Say Y here if you want to use a Winchiphead CH341 single port
+ USB to serial adapter.
+@@ -109,7 +102,6 @@ config USB_SERIAL_CH341
+
+ config USB_SERIAL_WHITEHEAT
+ tristate "USB ConnectTech WhiteHEAT Serial Driver"
+- depends on USB_SERIAL
+ select USB_EZUSB
+ help
+ Say Y here if you want to use a ConnectTech WhiteHEAT 4 port
+@@ -120,7 +112,6 @@ config USB_SERIAL_WHITEHEAT
+
+ config USB_SERIAL_DIGI_ACCELEPORT
+ tristate "USB Digi International AccelePort USB Serial Driver"
+- depends on USB_SERIAL
+ ---help---
+ Say Y here if you want to use Digi AccelePort USB 2 or 4 devices,
+ 2 port (plus parallel port) and 4 port USB serial converters. The
+@@ -135,7 +126,6 @@ config USB_SERIAL_DIGI_ACCELEPORT
+
+ config USB_SERIAL_CP2101
+ tristate "USB CP2101 UART Bridge Controller"
+- depends on USB_SERIAL && EXPERIMENTAL
+ help
+ Say Y here if you want to use a CP2101/CP2102 based USB to RS232
+ converter.
+@@ -145,7 +135,6 @@ config USB_SERIAL_CP2101
+
+ config USB_SERIAL_CYPRESS_M8
+ tristate "USB Cypress M8 USB Serial Driver"
+- depends on USB_SERIAL && EXPERIMENTAL
+ help
+ Say Y here if you want to use a device that contains the Cypress
+ USB to Serial microcontroller, such as the DeLorme Earthmate GPS.
+@@ -160,7 +149,6 @@ config USB_SERIAL_CYPRESS_M8
+
+ config USB_SERIAL_EMPEG
+ tristate "USB Empeg empeg-car Mark I/II Driver"
+- depends on USB_SERIAL
+ help
+ Say Y here if you want to connect to your Empeg empeg-car Mark I/II
+ mp3 player via USB. The driver uses a single ttyUSB{0,1,2,...}
+@@ -171,8 +159,7 @@ config USB_SERIAL_EMPEG
+ module will be called empeg.
+
+ config USB_SERIAL_FTDI_SIO
+- tristate "USB FTDI Single Port Serial Driver (EXPERIMENTAL)"
+- depends on USB_SERIAL && EXPERIMENTAL
++ tristate "USB FTDI Single Port Serial Driver"
+ ---help---
+ Say Y here if you want to use a FTDI SIO single port USB to serial
+ converter device. The implementation I have is called the USC-1000.
+@@ -186,7 +173,6 @@ config USB_SERIAL_FTDI_SIO
+
+ config USB_SERIAL_FUNSOFT
+ tristate "USB Fundamental Software Dongle Driver"
+- depends on USB_SERIAL
+ ---help---
+ Say Y here if you want to use the Fundamental Software dongle.
+
+@@ -195,7 +181,6 @@ config USB_SERIAL_FUNSOFT
+
+ config USB_SERIAL_VISOR
+ tristate "USB Handspring Visor / Palm m50x / Sony Clie Driver"
+- depends on USB_SERIAL
+ help
+ Say Y here if you want to connect to your HandSpring Visor, Palm
+ m500 or m505 through its USB docking station. See
+@@ -207,7 +192,6 @@ config USB_SERIAL_VISOR
+
+ config USB_SERIAL_IPAQ
+ tristate "USB PocketPC PDA Driver"
+- depends on USB_SERIAL
+ help
+ Say Y here if you want to connect to your Compaq iPAQ, HP Jornada
+ or any other PDA running Windows CE 3.0 or PocketPC 2002
+@@ -218,8 +202,7 @@ config USB_SERIAL_IPAQ
+ module will be called ipaq.
+
+ config USB_SERIAL_IR
+- tristate "USB IR Dongle Serial Driver (EXPERIMENTAL)"
+- depends on USB_SERIAL && EXPERIMENTAL
++ tristate "USB IR Dongle Serial Driver"
+ help
+ Say Y here if you want to enable simple serial support for USB IrDA
+ devices. This is useful if you do not want to use the full IrDA
+@@ -230,7 +213,6 @@ config USB_SERIAL_IR
+
+ config USB_SERIAL_EDGEPORT
+ tristate "USB Inside Out Edgeport Serial Driver"
+- depends on USB_SERIAL
+ ---help---
+ Say Y here if you want to use any of the following devices from
+ Inside Out Networks (Digi):
+@@ -256,7 +238,6 @@ config USB_SERIAL_EDGEPORT
+
+ config USB_SERIAL_EDGEPORT_TI
+ tristate "USB Inside Out Edgeport Serial Driver (TI devices)"
+- depends on USB_SERIAL
+ help
+ Say Y here if you want to use any of the devices from Inside Out
+ Networks (Digi) that are not supported by the io_edgeport driver.
+@@ -267,7 +248,6 @@ config USB_SERIAL_EDGEPORT_TI
+
+ config USB_SERIAL_GARMIN
+ tristate "USB Garmin GPS driver"
+- depends on USB_SERIAL
+ help
+ Say Y here if you want to connect to your Garmin GPS.
+ Should work with most Garmin GPS devices which have a native USB port.
+@@ -279,8 +259,7 @@ config USB_SERIAL_GARMIN
+ module will be called garmin_gps.
+
+ config USB_SERIAL_IPW
+- tristate "USB IPWireless (3G UMTS TDD) Driver (EXPERIMENTAL)"
+- depends on USB_SERIAL && EXPERIMENTAL
++ tristate "USB IPWireless (3G UMTS TDD) Driver"
+ help
+ Say Y here if you want to use a IPWireless USB modem such as
+ the ones supplied by Axity3G/Sentech South Africa.
+@@ -289,8 +268,7 @@ config USB_SERIAL_IPW
+ module will be called ipw.
+
+ config USB_SERIAL_IUU
+- tristate "USB Infinity USB Unlimited Phoenix Driver (Experimental)"
+- depends on USB_SERIAL && EXPERIMENTAL
++ tristate "USB Infinity USB Unlimited Phoenix Driver"
+ help
+ Say Y here if you want to use a IUU in phoenix mode and get
+ an extra ttyUSBx device. More information available on
+@@ -301,7 +279,6 @@ config USB_SERIAL_IUU
+
+ config USB_SERIAL_KEYSPAN_PDA
+ tristate "USB Keyspan PDA Single Port Serial Driver"
+- depends on USB_SERIAL
+ select USB_EZUSB
+ help
+ Say Y here if you want to use a Keyspan PDA single port USB to
+@@ -405,8 +381,7 @@ config USB_SERIAL_KEYSPAN_USA49WLC
+ Say Y here to include firmware for the USA-49WLC converter.
+
+ config USB_SERIAL_KLSI
+- tristate "USB KL5KUSB105 (Palmconnect) Driver (EXPERIMENTAL)"
+- depends on USB_SERIAL && EXPERIMENTAL
++ tristate "USB KL5KUSB105 (Palmconnect) Driver"
+ ---help---
+ Say Y here if you want to use a KL5KUSB105 - based single port
+ serial adapter. The most widely known -- and currently the only
+@@ -422,7 +397,6 @@ config USB_SERIAL_KLSI
+
+ config USB_SERIAL_KOBIL_SCT
+ tristate "USB KOBIL chipcard reader"
+- depends on USB_SERIAL
+ ---help---
+ Say Y here if you want to use one of the following KOBIL USB chipcard
+ readers:
+@@ -440,7 +414,6 @@ config USB_SERIAL_KOBIL_SCT
+
+ config USB_SERIAL_MCT_U232
+ tristate "USB MCT Single Port Serial Driver"
+- depends on USB_SERIAL
+ ---help---
+ Say Y here if you want to use a USB Serial single port adapter from
+ Magic Control Technology Corp. (U232 is one of the model numbers).
+@@ -453,7 +426,6 @@ config USB_SERIAL_MCT_U232
+
+ config USB_SERIAL_MOS7720
+ tristate "USB Moschip 7720 Serial Driver"
+- depends on USB_SERIAL
+ ---help---
+ Say Y here if you want to use USB Serial single and double
+ port adapters from Moschip Semiconductor Tech.
+@@ -463,7 +435,6 @@ config USB_SERIAL_MOS7720
+
+ config USB_SERIAL_MOS7840
+ tristate "USB Moschip 7840/7820 USB Serial Driver"
+- depends on USB_SERIAL
+ ---help---
+ Say Y here if you want to use a MCS7840 Quad-Serial or MCS7820
+ Dual-Serial port device from MosChip Semiconductor.
+@@ -478,14 +449,12 @@ config USB_SERIAL_MOS7840
+
+ config USB_SERIAL_NAVMAN
+ tristate "USB Navman GPS device"
+- depends on USB_SERIAL
+ help
+ To compile this driver as a module, choose M here: the
+ module will be called navman.
+
+ config USB_SERIAL_PL2303
+ tristate "USB Prolific 2303 Single Port Serial Driver"
+- depends on USB_SERIAL
+ help
+ Say Y here if you want to use the PL2303 USB Serial single port
+ adapter from Prolific.
+@@ -494,8 +463,7 @@ config USB_SERIAL_PL2303
+ module will be called pl2303.
+
+ config USB_SERIAL_OTI6858
+- tristate "USB Ours Technology Inc. OTi-6858 USB To RS232 Bridge Controller (EXPERIMENTAL)"
+- depends on USB_SERIAL
++ tristate "USB Ours Technology Inc. OTi-6858 USB To RS232 Bridge Controller"
+ help
+ Say Y here if you want to use the OTi-6858 single port USB to serial
+ converter device.
+@@ -503,9 +471,17 @@ config USB_SERIAL_OTI6858
+ To compile this driver as a module, choose M here: the
+ module will be called oti6858.
+
++config USB_SERIAL_SPCP8X5
++ tristate "USB SPCP8x5 USB To Serial Driver"
++ help
++ Say Y here if you want to use the spcp8x5 converter chip. This is
++ commonly found in some Z-Wave USB devices.
++
++ To compile this driver as a module, choose M here: the
++ module will be called spcp8x5.
++
+ config USB_SERIAL_HP4X
+ tristate "USB HP4x Calculators support"
+- depends on USB_SERIAL
+ help
+ Say Y here if you want to use an Hewlett-Packard 4x Calculator.
+
+@@ -513,8 +489,7 @@ config USB_SERIAL_HP4X
+ module will be called hp4x.
+
+ config USB_SERIAL_SAFE
+- tristate "USB Safe Serial (Encapsulated) Driver (EXPERIMENTAL)"
+- depends on USB_SERIAL && EXPERIMENTAL
++ tristate "USB Safe Serial (Encapsulated) Driver"
+
+ config USB_SERIAL_SAFE_PADDED
+ bool "USB Secure Encapsulated Driver - Padded"
+@@ -522,7 +497,6 @@ config USB_SERIAL_SAFE_PADDED
+
+ config USB_SERIAL_SIERRAWIRELESS
+ tristate "USB Sierra Wireless Driver"
+- depends on USB_SERIAL
+ help
+ Say M here if you want to use a Sierra Wireless device (if
+ using an PC 5220 or AC580 please use the Airprime driver
+@@ -533,7 +507,6 @@ config USB_SERIAL_SIERRAWIRELESS
+
+ config USB_SERIAL_TI
+ tristate "USB TI 3410/5052 Serial Driver"
+- depends on USB_SERIAL
+ help
+ Say Y here if you want to use the TI USB 3410 or 5052
+ serial devices.
+@@ -542,8 +515,7 @@ config USB_SERIAL_TI
+ module will be called ti_usb_3410_5052.
+
+ config USB_SERIAL_CYBERJACK
+- tristate "USB REINER SCT cyberJack pinpad/e-com chipcard reader (EXPERIMENTAL)"
+- depends on USB_SERIAL && EXPERIMENTAL
++ tristate "USB REINER SCT cyberJack pinpad/e-com chipcard reader"
+ ---help---
+ Say Y here if you want to use a cyberJack pinpad/e-com USB chipcard
+ reader. This is an interface to ISO 7816 compatible contact-based
+@@ -556,7 +528,6 @@ config USB_SERIAL_CYBERJACK
+
+ config USB_SERIAL_XIRCOM
+ tristate "USB Xircom / Entregra Single Port Serial Driver"
+- depends on USB_SERIAL
+ select USB_EZUSB
+ help
+ Say Y here if you want to use a Xircom or Entregra single port USB to
+@@ -568,7 +539,6 @@ config USB_SERIAL_XIRCOM
+
+ config USB_SERIAL_OPTION
+ tristate "USB driver for GSM and CDMA modems"
+- depends on USB_SERIAL
+ help
+ Say Y here if you have a GSM or CDMA modem that's connected to USB.
+
+@@ -586,8 +556,7 @@ config USB_SERIAL_OPTION
+ it might be accessible via the FTDI_SIO driver.
+
+ config USB_SERIAL_OMNINET
+- tristate "USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)"
+- depends on USB_SERIAL && EXPERIMENTAL
++ tristate "USB ZyXEL omni.net LCD Plus Driver"
+ help
+ Say Y here if you want to use a ZyXEL omni.net LCD ISDN TA.
+
+@@ -596,7 +565,6 @@ config USB_SERIAL_OMNINET
+
+ config USB_SERIAL_DEBUG
+ tristate "USB Debugging Device"
+- depends on USB_SERIAL
+ help
+ Say Y here if you have a USB debugging device used to receive
+ debugging data from another machine. The most common of these
+diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
+index 0db109a..7568595 100644
+--- a/drivers/usb/serial/Makefile
++++ b/drivers/usb/serial/Makefile
+@@ -30,8 +30,8 @@ obj-$(CONFIG_USB_SERIAL_GARMIN) += garmin_gps.o
+ obj-$(CONFIG_USB_SERIAL_HP4X) += hp4x.o
+ obj-$(CONFIG_USB_SERIAL_IPAQ) += ipaq.o
+ obj-$(CONFIG_USB_SERIAL_IPW) += ipw.o
+-obj-$(CONFIG_USB_SERIAL_IUU) += iuu_phoenix.o
+ obj-$(CONFIG_USB_SERIAL_IR) += ir-usb.o
++obj-$(CONFIG_USB_SERIAL_IUU) += iuu_phoenix.o
+ obj-$(CONFIG_USB_SERIAL_KEYSPAN) += keyspan.o
+ obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA) += keyspan_pda.o
+ obj-$(CONFIG_USB_SERIAL_KLSI) += kl5kusb105.o
+@@ -46,6 +46,7 @@ obj-$(CONFIG_USB_SERIAL_OTI6858) += oti6858.o
+ obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o
+ obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o
+ obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o
++obj-$(CONFIG_USB_SERIAL_SPCP8X5) += spcp8x5.o
+ obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o
+ obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o
+ obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o
+diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
+index 1cd29cd..a238817 100644
+--- a/drivers/usb/serial/aircable.c
++++ b/drivers/usb/serial/aircable.c
+@@ -210,7 +210,7 @@ static void aircable_send(struct usb_serial_port *port)
+ struct aircable_private *priv = usb_get_serial_port_data(port);
+ unsigned char* buf;
+ u16 *dbuf;
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+ if (port->write_urb_busy)
+ return;
+
+@@ -220,7 +220,7 @@ static void aircable_send(struct usb_serial_port *port)
+
+ buf = kzalloc(count + HCI_HEADER_LENGTH, GFP_ATOMIC);
+ if (!buf) {
+- err("%s- kzalloc(%d) failed.", __FUNCTION__,
++ err("%s- kzalloc(%d) failed.", __func__,
+ count + HCI_HEADER_LENGTH);
+ return;
+ }
+@@ -236,7 +236,7 @@ static void aircable_send(struct usb_serial_port *port)
+
+ kfree(buf);
+ port->write_urb_busy = 1;
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
++ usb_serial_debug_data(debug, &port->dev, __func__,
+ count + HCI_HEADER_LENGTH,
+ port->write_urb->transfer_buffer);
+ port->write_urb->transfer_buffer_length = count + HCI_HEADER_LENGTH;
+@@ -246,7 +246,7 @@ static void aircable_send(struct usb_serial_port *port)
+ if (result) {
+ dev_err(&port->dev,
+ "%s - failed submitting write urb, error %d\n",
+- __FUNCTION__, result);
++ __func__, result);
+ port->write_urb_busy = 0;
+ }
+
+@@ -275,7 +275,7 @@ static void aircable_read(struct work_struct *work)
+
+ if (!tty) {
+ schedule_work(&priv->rx_work);
+- err("%s - No tty available", __FUNCTION__);
++ err("%s - No tty available", __func__);
+ return ;
+ }
+
+@@ -286,7 +286,7 @@ static void aircable_read(struct work_struct *work)
+
+ tty_prepare_flip_string(tty, &data, count);
+ if (!data){
+- err("%s- kzalloc(%d) failed.", __FUNCTION__, count);
++ err("%s- kzalloc(%d) failed.", __func__, count);
+ return;
+ }
+
+@@ -332,7 +332,7 @@ static int aircable_attach (struct usb_serial *serial)
+
+ priv = kzalloc(sizeof(struct aircable_private), GFP_KERNEL);
+ if (!priv){
+- err("%s- kmalloc(%Zd) failed.", __FUNCTION__,
++ err("%s- kmalloc(%Zd) failed.", __func__,
+ sizeof(struct aircable_private));
+ return -ENOMEM;
+ }
+@@ -366,7 +366,7 @@ static void aircable_shutdown(struct usb_serial *serial)
+ struct usb_serial_port *port = serial->port[0];
+ struct aircable_private *priv = usb_get_serial_port_data(port);
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ if (priv) {
+ serial_buf_free(priv->tx_buf);
+@@ -388,12 +388,12 @@ static int aircable_write(struct usb_serial_port *port,
+ struct aircable_private *priv = usb_get_serial_port_data(port);
+ int temp;
+
+- dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
++ dbg("%s - port %d, %d bytes", __func__, port->number, count);
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, source);
++ usb_serial_debug_data(debug, &port->dev, __func__, count, source);
+
+ if (!count){
+- dbg("%s - write request of 0 bytes", __FUNCTION__);
++ dbg("%s - write request of 0 bytes", __func__);
+ return count;
+ }
+
+@@ -414,7 +414,7 @@ static void aircable_write_bulk_callback(struct urb *urb)
+ int status = urb->status;
+ int result;
+
+- dbg("%s - urb status: %d", __FUNCTION__ , status);
++ dbg("%s - urb status: %d", __func__ , status);
+
+ /* This has been taken from cypress_m8.c cypress_write_int_callback */
+ switch (status) {
+@@ -426,21 +426,21 @@ static void aircable_write_bulk_callback(struct urb *urb)
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ port->write_urb_busy = 0;
+ return;
+ default:
+ /* error in the urb, so we have to resubmit it */
+- dbg("%s - Overflow in write", __FUNCTION__);
++ dbg("%s - Overflow in write", __func__);
+ dbg("%s - nonzero write bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ port->write_urb->transfer_buffer_length = 1;
+ port->write_urb->dev = port->serial->dev;
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ if (result)
+ dev_err(&urb->dev->dev,
+ "%s - failed resubmitting write urb, error %d\n",
+- __FUNCTION__, result);
++ __func__, result);
+ else
+ return;
+ }
+@@ -460,17 +460,17 @@ static void aircable_read_bulk_callback(struct urb *urb)
+ unsigned char *temp;
+ int status = urb->status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (status) {
+- dbg("%s - urb status = %d", __FUNCTION__, status);
++ dbg("%s - urb status = %d", __func__, status);
+ if (!port->open_count) {
+- dbg("%s - port is closed, exiting.", __FUNCTION__);
++ dbg("%s - port is closed, exiting.", __func__);
+ return;
+ }
+ if (status == -EPROTO) {
+ dbg("%s - caught -EPROTO, resubmitting the urb",
+- __FUNCTION__);
++ __func__);
+ usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+ usb_rcvbulkpipe(port->serial->dev,
+ port->bulk_in_endpointAddress),
+@@ -482,14 +482,14 @@ static void aircable_read_bulk_callback(struct urb *urb)
+ if (result)
+ dev_err(&urb->dev->dev,
+ "%s - failed resubmitting read urb, error %d\n",
+- __FUNCTION__, result);
++ __func__, result);
+ return;
+ }
+- dbg("%s - unable to handle the error, exiting.", __FUNCTION__);
++ dbg("%s - unable to handle the error, exiting.", __func__);
+ return;
+ }
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
++ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length,urb->transfer_buffer);
+
+ tty = port->tty;
+@@ -538,7 +538,7 @@ static void aircable_read_bulk_callback(struct urb *urb)
+ if (result)
+ dev_err(&urb->dev->dev,
+ "%s - failed resubmitting read urb, error %d\n",
+- __FUNCTION__, result);
++ __func__, result);
+ }
+
+ return;
+@@ -550,7 +550,7 @@ static void aircable_throttle(struct usb_serial_port *port)
+ struct aircable_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&priv->rx_lock, flags);
+ priv->rx_flags |= THROTTLED;
+@@ -564,7 +564,7 @@ static void aircable_unthrottle(struct usb_serial_port *port)
+ int actually_throttled;
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&priv->rx_lock, flags);
+ actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
+diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
+index f156dba..725b6b9 100644
+--- a/drivers/usb/serial/airprime.c
++++ b/drivers/usb/serial/airprime.c
+@@ -53,7 +53,7 @@ static int airprime_send_setup(struct usb_serial_port *port)
+ struct usb_serial *serial = port->serial;
+ struct airprime_private *priv;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ if (port->number != 0)
+ return 0;
+@@ -83,14 +83,14 @@ static void airprime_read_bulk_callback(struct urb *urb)
+ int result;
+ int status = urb->status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++ usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+
+ tty = port->tty;
+ if (tty && urb->actual_length) {
+@@ -101,7 +101,7 @@ static void airprime_read_bulk_callback(struct urb *urb)
+ result = usb_submit_urb (urb, GFP_ATOMIC);
+ if (result)
+ dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n",
+- __FUNCTION__, result);
++ __func__, result);
+ return;
+ }
+
+@@ -112,14 +112,14 @@ static void airprime_write_bulk_callback(struct urb *urb)
+ int status = urb->status;
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /* free up the transfer buffer, as usb_free_urb() does not do this */
+ kfree (urb->transfer_buffer);
+
+ if (status)
+ dbg("%s - nonzero write bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ spin_lock_irqsave(&priv->lock, flags);
+ --priv->outstanding_urbs;
+ spin_unlock_irqrestore(&priv->lock, flags);
+@@ -136,7 +136,7 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
+ int i;
+ int result = 0;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /* initialize our private data structure if it isn't already created */
+ if (!priv) {
+@@ -157,7 +157,7 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
+ buffer = kmalloc(buffer_size, GFP_KERNEL);
+ if (!buffer) {
+ dev_err(&port->dev, "%s - out of memory.\n",
+- __FUNCTION__);
++ __func__);
+ result = -ENOMEM;
+ goto errout;
+ }
+@@ -165,7 +165,7 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
+ if (!urb) {
+ kfree(buffer);
+ dev_err(&port->dev, "%s - no more urbs?\n",
+- __FUNCTION__);
++ __func__);
+ result = -ENOMEM;
+ goto errout;
+ }
+@@ -180,7 +180,7 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
+ kfree(buffer);
+ dev_err(&port->dev,
+ "%s - failed submitting read urb %d for port %d, error %d\n",
+- __FUNCTION__, i, port->number, result);
++ __func__, i, port->number, result);
+ goto errout;
+ }
+ /* remember this urb so we can kill it when the port is closed */
+@@ -212,7 +212,7 @@ static void airprime_close(struct usb_serial_port *port, struct file * filp)
+ struct airprime_private *priv = usb_get_serial_port_data(port);
+ int i;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ priv->rts_state = 0;
+ priv->dtr_state = 0;
+@@ -242,12 +242,12 @@ static int airprime_write(struct usb_serial_port *port,
+ unsigned char *buffer;
+ unsigned long flags;
+ int status;
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (priv->outstanding_urbs > NUM_WRITE_URBS) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+- dbg("%s - write limit hit\n", __FUNCTION__);
++ dbg("%s - write limit hit\n", __func__);
+ return 0;
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+@@ -264,7 +264,7 @@ static int airprime_write(struct usb_serial_port *port,
+ }
+ memcpy (buffer, buf, count);
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
++ usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
+
+ usb_fill_bulk_urb(urb, serial->dev,
+ usb_sndbulkpipe(serial->dev,
+@@ -277,7 +277,7 @@ static int airprime_write(struct usb_serial_port *port,
+ if (status) {
+ dev_err(&port->dev,
+ "%s - usb_submit_urb(write bulk) failed with status = %d\n",
+- __FUNCTION__, status);
++ __func__, status);
+ count = status;
+ kfree (buffer);
+ } else {
+@@ -306,9 +306,6 @@ static struct usb_serial_driver airprime_device = {
+ },
+ .usb_driver = &airprime_driver,
+ .id_table = id_table,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_bulk_in = NUM_DONT_CARE,
+- .num_bulk_out = NUM_DONT_CARE,
+ .open = airprime_open,
+ .close = airprime_close,
+ .write = airprime_write,
+@@ -331,7 +328,7 @@ static int __init airprime_init(void)
+
+ static void __exit airprime_exit(void)
+ {
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ usb_deregister(&airprime_driver);
+ usb_serial_deregister(&airprime_device);
+diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
+index fe2bfd6..599ab2e 100644
+--- a/drivers/usb/serial/ark3116.c
++++ b/drivers/usb/serial/ark3116.c
+@@ -173,7 +173,7 @@ static void ark3116_set_termios(struct usb_serial_port *port,
+
+ config = 0;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (!priv->termios_initialized) {
+@@ -192,6 +192,7 @@ static void ark3116_set_termios(struct usb_serial_port *port,
+ buf = kmalloc(1, GFP_KERNEL);
+ if (!buf) {
+ dbg("error kmalloc");
++ *port->tty->termios = *old_termios;
+ return;
+ }
+
+@@ -323,7 +324,7 @@ static int ark3116_open(struct usb_serial_port *port, struct file *filp)
+ char *buf;
+ int result = 0;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ buf = kmalloc(1, GFP_KERNEL);
+ if (!buf) {
+@@ -395,7 +396,7 @@ static int ark3116_ioctl(struct usb_serial_port *port, struct file *file,
+ return -EFAULT;
+ return 0;
+ default:
+- dbg("%s cmd 0x%04x not supported", __FUNCTION__, cmd);
++ dbg("%s cmd 0x%04x not supported", __func__, cmd);
+ break;
+ }
+
+@@ -447,9 +448,6 @@ static struct usb_serial_driver ark3116_device = {
+ },
+ .id_table = id_table,
+ .usb_driver = &ark3116_driver,
+- .num_interrupt_in = 1,
+- .num_bulk_in = 1,
+- .num_bulk_out = 1,
+ .num_ports = 1,
+ .attach = ark3116_attach,
+ .set_termios = ark3116_set_termios,
+diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
+index df0a2b3..0a322fc 100644
+--- a/drivers/usb/serial/belkin_sa.c
++++ b/drivers/usb/serial/belkin_sa.c
+@@ -128,9 +128,6 @@ static struct usb_serial_driver belkin_device = {
+ .description = "Belkin / Peracom / GoHubs USB Serial Adapter",
+ .usb_driver = &belkin_driver,
+ .id_table = id_table_combined,
+- .num_interrupt_in = 1,
+- .num_bulk_in = 1,
+- .num_bulk_out = 1,
+ .num_ports = 1,
+ .open = belkin_sa_open,
+ .close = belkin_sa_close,
+@@ -198,7 +195,7 @@ static void belkin_sa_shutdown (struct usb_serial *serial)
+ struct belkin_sa_private *priv;
+ int i;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+ /* stop reads and writes on all ports */
+ for (i=0; i < serial->num_ports; ++i) {
+@@ -213,7 +210,7 @@ static int belkin_sa_open (struct usb_serial_port *port, struct file *filp)
+ {
+ int retval = 0;
+
+- dbg("%s port %d", __FUNCTION__, port->number);
++ dbg("%s port %d", __func__, port->number);
+
+ /*Start reading from the device*/
+ /* TODO: Look at possibility of submitting multiple URBs to device to
+@@ -240,7 +237,7 @@ exit:
+
+ static void belkin_sa_close (struct usb_serial_port *port, struct file *filp)
+ {
+- dbg("%s port %d", __FUNCTION__, port->number);
++ dbg("%s port %d", __func__, port->number);
+
+ /* shutdown our bulk reads and writes */
+ usb_kill_urb(port->write_urb);
+@@ -251,7 +248,7 @@ static void belkin_sa_close (struct usb_serial_port *port, struct file *filp)
+
+ static void belkin_sa_read_int_callback (struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct belkin_sa_private *priv;
+ unsigned char *data = urb->transfer_buffer;
+ int retval;
+@@ -267,15 +264,15 @@ static void belkin_sa_read_int_callback (struct urb *urb)
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ goto exit;
+ }
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++ usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+
+ /* Handle known interrupt data */
+ /* ignore data[0] and data[1] */
+@@ -334,7 +331,7 @@ exit:
+ retval = usb_submit_urb (urb, GFP_ATOMIC);
+ if (retval)
+ err ("%s - usb_submit_urb failed with result %d",
+- __FUNCTION__, retval);
++ __func__, retval);
+ }
+
+ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
+@@ -481,7 +478,7 @@ static int belkin_sa_tiocmget (struct usb_serial_port *port, struct file *file)
+ unsigned long control_state;
+ unsigned long flags;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ control_state = priv->control_state;
+@@ -502,7 +499,7 @@ static int belkin_sa_tiocmset (struct usb_serial_port *port, struct file *file,
+ int rts = 0;
+ int dtr = 0;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ control_state = priv->control_state;
+diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
+index 42582d4..d947d95 100644
+--- a/drivers/usb/serial/ch341.c
++++ b/drivers/usb/serial/ch341.c
+@@ -318,9 +318,6 @@ static struct usb_serial_driver ch341_device = {
+ },
+ .id_table = id_table,
+ .usb_driver = &ch341_driver,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_bulk_in = 1,
+- .num_bulk_out = 1,
+ .num_ports = 1,
+ .open = ch341_open,
+ .set_termios = ch341_set_termios,
+diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
+index 66ce30c..201184c 100644
+--- a/drivers/usb/serial/console.c
++++ b/drivers/usb/serial/console.c
+@@ -67,7 +67,7 @@ static int usb_console_setup(struct console *co, char *options)
+ struct tty_struct *tty = NULL;
+ struct ktermios *termios = NULL, dummy;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+ if (options) {
+ baud = simple_strtoul(options, NULL, 10);
+@@ -225,10 +225,10 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun
+ if (count == 0)
+ return;
+
+- dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
++ dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
+
+ if (!port->open_count) {
+- dbg ("%s - port not opened", __FUNCTION__);
++ dbg ("%s - port not opened", __func__);
+ return;
+ }
+
+@@ -248,7 +248,7 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun
+ retval = serial->type->write(port, buf, i);
+ else
+ retval = usb_serial_generic_write(port, buf, i);
+- dbg("%s - return value : %d", __FUNCTION__, retval);
++ dbg("%s - return value : %d", __func__, retval);
+ if (lf) {
+ /* append CR after LF */
+ unsigned char cr = 13;
+@@ -256,7 +256,7 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun
+ retval = serial->type->write(port, &cr, 1);
+ else
+ retval = usb_serial_generic_write(port, &cr, 1);
+- dbg("%s - return value : %d", __FUNCTION__, retval);
++ dbg("%s - return value : %d", __func__, retval);
+ }
+ buf += i;
+ count -= i;
+diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
+index 324bb61..dc0ea08 100644
+--- a/drivers/usb/serial/cp2101.c
++++ b/drivers/usb/serial/cp2101.c
+@@ -53,9 +53,11 @@ static void cp2101_shutdown(struct usb_serial*);
+ static int debug;
+
+ static struct usb_device_id id_table [] = {
++ { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
+ { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */
+ { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */
+ { USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */
++ { USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */
+ { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */
+ { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
+ { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */
+@@ -71,6 +73,7 @@ static struct usb_device_id id_table [] = {
+ { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */
+ { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */
+ { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */
++ { USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */
+ { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */
+ { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */
+ { USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */
+@@ -106,9 +109,6 @@ static struct usb_serial_driver cp2101_device = {
+ },
+ .usb_driver = &cp2101_driver,
+ .id_table = id_table,
+- .num_interrupt_in = 0,
+- .num_bulk_in = NUM_DONT_CARE,
+- .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 1,
+ .open = cp2101_open,
+ .close = cp2101_close,
+@@ -193,7 +193,7 @@ static int cp2101_get_config(struct usb_serial_port* port, u8 request,
+
+ buf = kcalloc(length, sizeof(__le32), GFP_KERNEL);
+ if (!buf) {
+- dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__);
++ dev_err(&port->dev, "%s - out of memory.\n", __func__);
+ return -ENOMEM;
+ }
+
+@@ -214,7 +214,7 @@ static int cp2101_get_config(struct usb_serial_port* port, u8 request,
+ if (result != size) {
+ dev_err(&port->dev, "%s - Unable to send config request, "
+ "request=0x%x size=%d result=%d\n",
+- __FUNCTION__, request, size, result);
++ __func__, request, size, result);
+ return -EPROTO;
+ }
+
+@@ -240,7 +240,7 @@ static int cp2101_set_config(struct usb_serial_port* port, u8 request,
+ buf = kmalloc(length * sizeof(__le32), GFP_KERNEL);
+ if (!buf) {
+ dev_err(&port->dev, "%s - out of memory.\n",
+- __FUNCTION__);
++ __func__);
+ return -ENOMEM;
+ }
+
+@@ -265,7 +265,7 @@ static int cp2101_set_config(struct usb_serial_port* port, u8 request,
+ if ((size > 2 && result != size) || result < 0) {
+ dev_err(&port->dev, "%s - Unable to send request, "
+ "request=0x%x size=%d result=%d\n",
+- __FUNCTION__, request, size, result);
++ __func__, request, size, result);
+ return -EPROTO;
+ }
+
+@@ -293,11 +293,11 @@ static int cp2101_open (struct usb_serial_port *port, struct file *filp)
+ struct usb_serial *serial = port->serial;
+ int result;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (cp2101_set_config_single(port, CP2101_UART, UART_ENABLE)) {
+ dev_err(&port->dev, "%s - Unable to enable UART\n",
+- __FUNCTION__);
++ __func__);
+ return -EPROTO;
+ }
+
+@@ -312,7 +312,7 @@ static int cp2101_open (struct usb_serial_port *port, struct file *filp)
+ result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ if (result) {
+ dev_err(&port->dev, "%s - failed resubmitting read urb, "
+- "error %d\n", __FUNCTION__, result);
++ "error %d\n", __func__, result);
+ return result;
+ }
+
+@@ -329,7 +329,7 @@ static void cp2101_cleanup (struct usb_serial_port *port)
+ {
+ struct usb_serial *serial = port->serial;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (serial->dev) {
+ /* shutdown any bulk reads that might be going on */
+@@ -342,10 +342,10 @@ static void cp2101_cleanup (struct usb_serial_port *port)
+
+ static void cp2101_close (struct usb_serial_port *port, struct file * filp)
+ {
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /* shutdown our urbs */
+- dbg("%s - shutting down urbs", __FUNCTION__);
++ dbg("%s - shutting down urbs", __func__);
+ usb_kill_urb(port->write_urb);
+ usb_kill_urb(port->read_urb);
+
+@@ -367,10 +367,10 @@ static void cp2101_get_termios (struct usb_serial_port *port)
+ int baud;
+ int bits;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (!port->tty || !port->tty->termios) {
+- dbg("%s - no tty structures", __FUNCTION__);
++ dbg("%s - no tty structures", __func__);
+ return;
+ }
+
+@@ -379,7 +379,7 @@ static void cp2101_get_termios (struct usb_serial_port *port)
+ if (baud)
+ baud = BAUD_RATE_GEN_FREQ / baud;
+
+- dbg("%s - baud rate = %d", __FUNCTION__, baud);
++ dbg("%s - baud rate = %d", __func__, baud);
+
+ tty_encode_baud_rate(port->tty, baud, baud);
+ cflag = port->tty->termios->c_cflag;
+@@ -388,24 +388,24 @@ static void cp2101_get_termios (struct usb_serial_port *port)
+ cflag &= ~CSIZE;
+ switch(bits & BITS_DATA_MASK) {
+ case BITS_DATA_5:
+- dbg("%s - data bits = 5", __FUNCTION__);
++ dbg("%s - data bits = 5", __func__);
+ cflag |= CS5;
+ break;
+ case BITS_DATA_6:
+- dbg("%s - data bits = 6", __FUNCTION__);
++ dbg("%s - data bits = 6", __func__);
+ cflag |= CS6;
+ break;
+ case BITS_DATA_7:
+- dbg("%s - data bits = 7", __FUNCTION__);
++ dbg("%s - data bits = 7", __func__);
+ cflag |= CS7;
+ break;
+ case BITS_DATA_8:
+- dbg("%s - data bits = 8", __FUNCTION__);
++ dbg("%s - data bits = 8", __func__);
+ cflag |= CS8;
+ break;
+ case BITS_DATA_9:
+ dbg("%s - data bits = 9 (not supported, "
+- "using 8 data bits)", __FUNCTION__);
++ "using 8 data bits)", __func__);
+ cflag |= CS8;
+ bits &= ~BITS_DATA_MASK;
+ bits |= BITS_DATA_8;
+@@ -413,7 +413,7 @@ static void cp2101_get_termios (struct usb_serial_port *port)
+ break;
+ default:
+ dbg("%s - Unknown number of data bits, "
+- "using 8", __FUNCTION__);
++ "using 8", __func__);
+ cflag |= CS8;
+ bits &= ~BITS_DATA_MASK;
+ bits |= BITS_DATA_8;
+@@ -423,35 +423,35 @@ static void cp2101_get_termios (struct usb_serial_port *port)
+
+ switch(bits & BITS_PARITY_MASK) {
+ case BITS_PARITY_NONE:
+- dbg("%s - parity = NONE", __FUNCTION__);
++ dbg("%s - parity = NONE", __func__);
+ cflag &= ~PARENB;
+ break;
+ case BITS_PARITY_ODD:
+- dbg("%s - parity = ODD", __FUNCTION__);
++ dbg("%s - parity = ODD", __func__);
+ cflag |= (PARENB|PARODD);
+ break;
+ case BITS_PARITY_EVEN:
+- dbg("%s - parity = EVEN", __FUNCTION__);
++ dbg("%s - parity = EVEN", __func__);
+ cflag &= ~PARODD;
+ cflag |= PARENB;
+ break;
+ case BITS_PARITY_MARK:
+ dbg("%s - parity = MARK (not supported, "
+- "disabling parity)", __FUNCTION__);
++ "disabling parity)", __func__);
+ cflag &= ~PARENB;
+ bits &= ~BITS_PARITY_MASK;
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
+ break;
+ case BITS_PARITY_SPACE:
+ dbg("%s - parity = SPACE (not supported, "
+- "disabling parity)", __FUNCTION__);
++ "disabling parity)", __func__);
+ cflag &= ~PARENB;
+ bits &= ~BITS_PARITY_MASK;
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
+ break;
+ default:
+ dbg("%s - Unknown parity mode, "
+- "disabling parity", __FUNCTION__);
++ "disabling parity", __func__);
+ cflag &= ~PARENB;
+ bits &= ~BITS_PARITY_MASK;
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
+@@ -461,21 +461,21 @@ static void cp2101_get_termios (struct usb_serial_port *port)
+ cflag &= ~CSTOPB;
+ switch(bits & BITS_STOP_MASK) {
+ case BITS_STOP_1:
+- dbg("%s - stop bits = 1", __FUNCTION__);
++ dbg("%s - stop bits = 1", __func__);
+ break;
+ case BITS_STOP_1_5:
+ dbg("%s - stop bits = 1.5 (not supported, "
+- "using 1 stop bit)", __FUNCTION__);
++ "using 1 stop bit)", __func__);
+ bits &= ~BITS_STOP_MASK;
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
+ break;
+ case BITS_STOP_2:
+- dbg("%s - stop bits = 2", __FUNCTION__);
++ dbg("%s - stop bits = 2", __func__);
+ cflag |= CSTOPB;
+ break;
+ default:
+ dbg("%s - Unknown number of stop bits, "
+- "using 1 stop bit", __FUNCTION__);
++ "using 1 stop bit", __func__);
+ bits &= ~BITS_STOP_MASK;
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
+ break;
+@@ -483,10 +483,10 @@ static void cp2101_get_termios (struct usb_serial_port *port)
+
+ cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16);
+ if (modem_ctl[0] & 0x0008) {
+- dbg("%s - flow control = CRTSCTS", __FUNCTION__);
++ dbg("%s - flow control = CRTSCTS", __func__);
+ cflag |= CRTSCTS;
+ } else {
+- dbg("%s - flow control = NONE", __FUNCTION__);
++ dbg("%s - flow control = NONE", __func__);
+ cflag &= ~CRTSCTS;
+ }
+
+@@ -500,10 +500,10 @@ static void cp2101_set_termios (struct usb_serial_port *port,
+ int baud=0, bits;
+ unsigned int modem_ctl[4];
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (!port->tty || !port->tty->termios) {
+- dbg("%s - no tty structures", __FUNCTION__);
++ dbg("%s - no tty structures", __func__);
+ return;
+ }
+ port->tty->termios->c_cflag &= ~CMSPAR;
+@@ -542,7 +542,7 @@ static void cp2101_set_termios (struct usb_serial_port *port,
+ }
+
+ if (baud) {
+- dbg("%s - Setting baud rate to %d baud", __FUNCTION__,
++ dbg("%s - Setting baud rate to %d baud", __func__,
+ baud);
+ if (cp2101_set_config_single(port, CP2101_BAUDRATE,
+ (BAUD_RATE_GEN_FREQ / baud))) {
+@@ -562,23 +562,23 @@ static void cp2101_set_termios (struct usb_serial_port *port,
+ switch (cflag & CSIZE) {
+ case CS5:
+ bits |= BITS_DATA_5;
+- dbg("%s - data bits = 5", __FUNCTION__);
++ dbg("%s - data bits = 5", __func__);
+ break;
+ case CS6:
+ bits |= BITS_DATA_6;
+- dbg("%s - data bits = 6", __FUNCTION__);
++ dbg("%s - data bits = 6", __func__);
+ break;
+ case CS7:
+ bits |= BITS_DATA_7;
+- dbg("%s - data bits = 7", __FUNCTION__);
++ dbg("%s - data bits = 7", __func__);
+ break;
+ case CS8:
+ bits |= BITS_DATA_8;
+- dbg("%s - data bits = 8", __FUNCTION__);
++ dbg("%s - data bits = 8", __func__);
+ break;
+ /*case CS9:
+ bits |= BITS_DATA_9;
+- dbg("%s - data bits = 9", __FUNCTION__);
++ dbg("%s - data bits = 9", __func__);
+ break;*/
+ default:
+ dev_err(&port->dev, "cp2101 driver does not "
+@@ -598,10 +598,10 @@ static void cp2101_set_termios (struct usb_serial_port *port,
+ if (cflag & PARENB) {
+ if (cflag & PARODD) {
+ bits |= BITS_PARITY_ODD;
+- dbg("%s - parity = ODD", __FUNCTION__);
++ dbg("%s - parity = ODD", __func__);
+ } else {
+ bits |= BITS_PARITY_EVEN;
+- dbg("%s - parity = EVEN", __FUNCTION__);
++ dbg("%s - parity = EVEN", __func__);
+ }
+ }
+ if (cp2101_set_config(port, CP2101_BITS, &bits, 2))
+@@ -614,10 +614,10 @@ static void cp2101_set_termios (struct usb_serial_port *port,
+ bits &= ~BITS_STOP_MASK;
+ if (cflag & CSTOPB) {
+ bits |= BITS_STOP_2;
+- dbg("%s - stop bits = 2", __FUNCTION__);
++ dbg("%s - stop bits = 2", __func__);
+ } else {
+ bits |= BITS_STOP_1;
+- dbg("%s - stop bits = 1", __FUNCTION__);
++ dbg("%s - stop bits = 1", __func__);
+ }
+ if (cp2101_set_config(port, CP2101_BITS, &bits, 2))
+ dev_err(&port->dev, "Number of stop bits requested "
+@@ -627,23 +627,23 @@ static void cp2101_set_termios (struct usb_serial_port *port,
+ if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
+ cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16);
+ dbg("%s - read modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x",
+- __FUNCTION__, modem_ctl[0], modem_ctl[1],
++ __func__, modem_ctl[0], modem_ctl[1],
+ modem_ctl[2], modem_ctl[3]);
+
+ if (cflag & CRTSCTS) {
+ modem_ctl[0] &= ~0x7B;
+ modem_ctl[0] |= 0x09;
+ modem_ctl[1] = 0x80;
+- dbg("%s - flow control = CRTSCTS", __FUNCTION__);
++ dbg("%s - flow control = CRTSCTS", __func__);
+ } else {
+ modem_ctl[0] &= ~0x7B;
+ modem_ctl[0] |= 0x01;
+ modem_ctl[1] |= 0x40;
+- dbg("%s - flow control = NONE", __FUNCTION__);
++ dbg("%s - flow control = NONE", __func__);
+ }
+
+ dbg("%s - write modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x",
+- __FUNCTION__, modem_ctl[0], modem_ctl[1],
++ __func__, modem_ctl[0], modem_ctl[1],
+ modem_ctl[2], modem_ctl[3]);
+ cp2101_set_config(port, CP2101_MODEMCTL, modem_ctl, 16);
+ }
+@@ -655,7 +655,7 @@ static int cp2101_tiocmset (struct usb_serial_port *port, struct file *file,
+ {
+ int control = 0;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (set & TIOCM_RTS) {
+ control |= CONTROL_RTS;
+@@ -674,7 +674,7 @@ static int cp2101_tiocmset (struct usb_serial_port *port, struct file *file,
+ control |= CONTROL_WRITE_DTR;
+ }
+
+- dbg("%s - control = 0x%.4x", __FUNCTION__, control);
++ dbg("%s - control = 0x%.4x", __func__, control);
+
+ return cp2101_set_config(port, CP2101_CONTROL, &control, 2);
+
+@@ -684,7 +684,7 @@ static int cp2101_tiocmget (struct usb_serial_port *port, struct file *file)
+ {
+ int control, result;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ cp2101_get_config(port, CP2101_CONTROL, &control, 1);
+
+@@ -695,7 +695,7 @@ static int cp2101_tiocmget (struct usb_serial_port *port, struct file *file)
+ |((control & CONTROL_RING)? TIOCM_RI : 0)
+ |((control & CONTROL_DCD) ? TIOCM_CD : 0);
+
+- dbg("%s - control = 0x%.2x", __FUNCTION__, control);
++ dbg("%s - control = 0x%.2x", __func__, control);
+
+ return result;
+ }
+@@ -704,12 +704,12 @@ static void cp2101_break_ctl (struct usb_serial_port *port, int break_state)
+ {
+ int state;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+ if (break_state == 0)
+ state = BREAK_OFF;
+ else
+ state = BREAK_ON;
+- dbg("%s - turning break %s", __FUNCTION__,
++ dbg("%s - turning break %s", __func__,
+ state==BREAK_OFF ? "off" : "on");
+ cp2101_set_config(port, CP2101_BREAK, &state, 2);
+ }
+@@ -725,7 +725,7 @@ static void cp2101_shutdown (struct usb_serial *serial)
+ {
+ int i;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ /* Stop reads and writes on all ports */
+ for (i=0; i < serial->num_ports; ++i) {
+diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
+index 8d9b045..c164e2c 100644
+--- a/drivers/usb/serial/cyberjack.c
++++ b/drivers/usb/serial/cyberjack.c
+@@ -90,9 +90,6 @@ static struct usb_serial_driver cyberjack_device = {
+ .description = "Reiner SCT Cyberjack USB card reader",
+ .usb_driver = &cyberjack_driver,
+ .id_table = id_table,
+- .num_interrupt_in = 1,
+- .num_bulk_in = 1,
+- .num_bulk_out = 1,
+ .num_ports = 1,
+ .attach = cyberjack_startup,
+ .shutdown = cyberjack_shutdown,
+@@ -119,7 +116,7 @@ static int cyberjack_startup (struct usb_serial *serial)
+ struct cyberjack_private *priv;
+ int i;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ /* allocate the private data structure */
+ priv = kmalloc(sizeof(struct cyberjack_private), GFP_KERNEL);
+@@ -142,7 +139,7 @@ static int cyberjack_startup (struct usb_serial *serial)
+ GFP_KERNEL);
+ if (result)
+ err(" usb_submit_urb(read int) failed");
+- dbg("%s - usb_submit_urb(int urb)", __FUNCTION__);
++ dbg("%s - usb_submit_urb(int urb)", __func__);
+ }
+
+ return( 0 );
+@@ -152,9 +149,9 @@ static void cyberjack_shutdown (struct usb_serial *serial)
+ {
+ int i;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+- for (i=0; i < serial->num_ports; ++i) {
++ for (i = 0; i < serial->num_ports; ++i) {
+ usb_kill_urb(serial->port[i]->interrupt_in_urb);
+ /* My special items, the standard routines free my urbs */
+ kfree(usb_get_serial_port_data(serial->port[i]));
+@@ -168,9 +165,9 @@ static int cyberjack_open (struct usb_serial_port *port, struct file *filp)
+ unsigned long flags;
+ int result = 0;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+- dbg("%s - usb_clear_halt", __FUNCTION__ );
++ dbg("%s - usb_clear_halt", __func__ );
+ usb_clear_halt(port->serial->dev, port->write_urb->pipe);
+
+ /* force low_latency on so that our tty_push actually forces
+@@ -191,7 +188,7 @@ static int cyberjack_open (struct usb_serial_port *port, struct file *filp)
+
+ static void cyberjack_close (struct usb_serial_port *port, struct file *filp)
+ {
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (port->serial->dev) {
+ /* shutdown any bulk reads that might be going on */
+@@ -208,17 +205,17 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
+ int result;
+ int wrexpected;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (count == 0) {
+- dbg("%s - write request of 0 bytes", __FUNCTION__);
+- return (0);
++ dbg("%s - write request of 0 bytes", __func__);
++ return 0;
+ }
+
+ spin_lock_bh(&port->lock);
+ if (port->write_urb_busy) {
+ spin_unlock_bh(&port->lock);
+- dbg("%s - already writing", __FUNCTION__);
++ dbg("%s - already writing", __func__);
+ return 0;
+ }
+ port->write_urb_busy = 1;
+@@ -226,24 +223,24 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+- if( (count+priv->wrfilled)>sizeof(priv->wrbuf) ) {
++ if( (count+priv->wrfilled) > sizeof(priv->wrbuf) ) {
+ /* To much data for buffer. Reset buffer. */
+- priv->wrfilled=0;
+- spin_unlock_irqrestore(&priv->lock, flags);
++ priv->wrfilled = 0;
+ port->write_urb_busy = 0;
+- return (0);
++ spin_unlock_irqrestore(&priv->lock, flags);
++ return 0;
+ }
+
+ /* Copy data */
+ memcpy (priv->wrbuf+priv->wrfilled, buf, count);
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count,
++ usb_serial_debug_data(debug, &port->dev, __func__, count,
+ priv->wrbuf+priv->wrfilled);
+ priv->wrfilled += count;
+
+ if( priv->wrfilled >= 3 ) {
+ wrexpected = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3;
+- dbg("%s - expected data: %d", __FUNCTION__, wrexpected);
++ dbg("%s - expected data: %d", __func__, wrexpected);
+ } else {
+ wrexpected = sizeof(priv->wrbuf);
+ }
+@@ -252,7 +249,7 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
+ /* We have enough data to begin transmission */
+ int length;
+
+- dbg("%s - transmitting data (frame 1)", __FUNCTION__);
++ dbg("%s - transmitting data (frame 1)", __func__);
+ length = (wrexpected > port->bulk_out_size) ? port->bulk_out_size : wrexpected;
+
+ memcpy (port->write_urb->transfer_buffer, priv->wrbuf, length );
+@@ -270,23 +267,23 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
+ /* send the data out the bulk port */
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ if (result) {
+- err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
++ err("%s - failed submitting write urb, error %d", __func__, result);
+ /* Throw away data. No better idea what to do with it. */
+- priv->wrfilled=0;
+- priv->wrsent=0;
++ priv->wrfilled = 0;
++ priv->wrsent = 0;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ port->write_urb_busy = 0;
+ return 0;
+ }
+
+- dbg("%s - priv->wrsent=%d", __FUNCTION__,priv->wrsent);
+- dbg("%s - priv->wrfilled=%d", __FUNCTION__,priv->wrfilled);
++ dbg("%s - priv->wrsent=%d", __func__,priv->wrsent);
++ dbg("%s - priv->wrfilled=%d", __func__,priv->wrfilled);
+
+ if( priv->wrsent>=priv->wrfilled ) {
+- dbg("%s - buffer cleaned", __FUNCTION__);
++ dbg("%s - buffer cleaned", __func__);
+ memset( priv->wrbuf, 0, sizeof(priv->wrbuf) );
+- priv->wrfilled=0;
+- priv->wrsent=0;
++ priv->wrfilled = 0;
++ priv->wrsent = 0;
+ }
+ }
+
+@@ -297,27 +294,28 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
+
+ static int cyberjack_write_room( struct usb_serial_port *port )
+ {
++ /* FIXME: .... */
+ return CYBERJACK_LOCAL_BUF_SIZE;
+ }
+
+ static void cyberjack_read_int_callback( struct urb *urb )
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct cyberjack_private *priv = usb_get_serial_port_data(port);
+ unsigned char *data = urb->transfer_buffer;
+ int status = urb->status;
+ int result;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /* the urb might have been killed. */
+ if (status)
+ return;
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++ usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+
+ /* React only to interrupts signaling a bulk_in transfer */
+- if( (urb->actual_length==4) && (data[0]==0x01) ) {
++ if( (urb->actual_length == 4) && (data[0] == 0x01) ) {
+ short old_rdtodo;
+
+ /* This is a announcement of coming bulk_ins. */
+@@ -336,7 +334,7 @@ static void cyberjack_read_int_callback( struct urb *urb )
+ /* "+=" is probably more fault tollerant than "=" */
+ priv->rdtodo += size;
+
+- dbg("%s - rdtodo: %d", __FUNCTION__, priv->rdtodo);
++ dbg("%s - rdtodo: %d", __func__, priv->rdtodo);
+
+ spin_unlock(&priv->lock);
+
+@@ -344,8 +342,8 @@ static void cyberjack_read_int_callback( struct urb *urb )
+ port->read_urb->dev = port->serial->dev;
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ if( result )
+- err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
+- dbg("%s - usb_submit_urb(read urb)", __FUNCTION__);
++ err("%s - failed resubmitting read urb, error %d", __func__, result);
++ dbg("%s - usb_submit_urb(read urb)", __func__);
+ }
+ }
+
+@@ -354,12 +352,12 @@ resubmit:
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+ if (result)
+ err(" usb_submit_urb(read int) failed");
+- dbg("%s - usb_submit_urb(int urb)", __FUNCTION__);
++ dbg("%s - usb_submit_urb(int urb)", __func__);
+ }
+
+ static void cyberjack_read_bulk_callback (struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct cyberjack_private *priv = usb_get_serial_port_data(port);
+ struct tty_struct *tty;
+ unsigned char *data = urb->transfer_buffer;
+@@ -367,18 +365,18 @@ static void cyberjack_read_bulk_callback (struct urb *urb)
+ int result;
+ int status = urb->status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++ usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
+
+ tty = port->tty;
+ if (!tty) {
+- dbg("%s - ignoring since device not open\n", __FUNCTION__);
++ dbg("%s - ignoring since device not open\n", __func__);
+ return;
+ }
+ if (urb->actual_length) {
+@@ -397,30 +395,30 @@ static void cyberjack_read_bulk_callback (struct urb *urb)
+
+ spin_unlock(&priv->lock);
+
+- dbg("%s - rdtodo: %d", __FUNCTION__, todo);
++ dbg("%s - rdtodo: %d", __func__, todo);
+
+ /* Continue to read if we have still urbs to do. */
+ if( todo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/ ) {
+ port->read_urb->dev = port->serial->dev;
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ if (result)
+- err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
+- dbg("%s - usb_submit_urb(read urb)", __FUNCTION__);
++ err("%s - failed resubmitting read urb, error %d", __func__, result);
++ dbg("%s - usb_submit_urb(read urb)", __func__);
+ }
+ }
+
+ static void cyberjack_write_bulk_callback (struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct cyberjack_private *priv = usb_get_serial_port_data(port);
+ int status = urb->status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ port->write_urb_busy = 0;
+ if (status) {
+ dbg("%s - nonzero write bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
+
+@@ -430,7 +428,7 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
+ if( priv->wrfilled ) {
+ int length, blksize, result;
+
+- dbg("%s - transmitting data (frame n)", __FUNCTION__);
++ dbg("%s - transmitting data (frame n)", __func__);
+
+ length = ((priv->wrfilled - priv->wrsent) > port->bulk_out_size) ?
+ port->bulk_out_size : (priv->wrfilled - priv->wrsent);
+@@ -451,23 +449,23 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
+ /* send the data out the bulk port */
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ if (result) {
+- err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
++ err("%s - failed submitting write urb, error %d", __func__, result);
+ /* Throw away data. No better idea what to do with it. */
+- priv->wrfilled=0;
+- priv->wrsent=0;
++ priv->wrfilled = 0;
++ priv->wrsent = 0;
+ goto exit;
+ }
+
+- dbg("%s - priv->wrsent=%d", __FUNCTION__,priv->wrsent);
+- dbg("%s - priv->wrfilled=%d", __FUNCTION__,priv->wrfilled);
++ dbg("%s - priv->wrsent=%d", __func__,priv->wrsent);
++ dbg("%s - priv->wrfilled=%d", __func__,priv->wrfilled);
+
+ blksize = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3;
+
+ if( (priv->wrsent>=priv->wrfilled) || (priv->wrsent>=blksize) ) {
+- dbg("%s - buffer cleaned", __FUNCTION__);
++ dbg("%s - buffer cleaned", __func__);
+ memset( priv->wrbuf, 0, sizeof(priv->wrbuf) );
+- priv->wrfilled=0;
+- priv->wrsent=0;
++ priv->wrfilled = 0;
++ priv->wrsent = 0;
+ }
+ }
+
+diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
+index 779d078..3212179 100644
+--- a/drivers/usb/serial/cypress_m8.c
++++ b/drivers/usb/serial/cypress_m8.c
+@@ -122,6 +122,11 @@ static struct usb_driver cypress_driver = {
+ .no_dynamic_id = 1,
+ };
+
++enum packet_format {
++ packet_format_1, /* b0:status, b1:payload count */
++ packet_format_2 /* b0[7:3]:status, b0[2:0]:payload count */
++};
++
+ struct cypress_private {
+ spinlock_t lock; /* private lock */
+ int chiptype; /* identifier of device, for quirks/etc */
+@@ -139,8 +144,9 @@ struct cypress_private {
+ __u8 current_status; /* received from last read - info on dsr,cts,cd,ri,etc */
+ __u8 current_config; /* stores the current configuration byte */
+ __u8 rx_flags; /* throttling - used from whiteheat/ftdi_sio */
++ enum packet_format pkt_fmt; /* format to use for packet send / receive */
++ int get_cfg_unsafe; /* If true, the CYPRESS_GET_CONFIG is unsafe */
+ int baud_rate; /* stores current baud rate in integer form */
+- int cbr_mask; /* stores current baud rate in masked form */
+ int isthrottled; /* if throttled, discard reads */
+ wait_queue_head_t delta_msr_wait; /* used for TIOCMIWAIT */
+ char prev_status, diff_status; /* used for TIOCMIWAIT */
+@@ -176,9 +182,6 @@ static void cypress_unthrottle (struct usb_serial_port *port);
+ static void cypress_set_dead (struct usb_serial_port *port);
+ static void cypress_read_int_callback (struct urb *urb);
+ static void cypress_write_int_callback (struct urb *urb);
+-/* baud helper functions */
+-static int mask_to_rate (unsigned mask);
+-static unsigned rate_to_mask (int rate);
+ /* write buffer functions */
+ static struct cypress_buf *cypress_buf_alloc(unsigned int size);
+ static void cypress_buf_free(struct cypress_buf *cb);
+@@ -197,10 +200,6 @@ static struct usb_serial_driver cypress_earthmate_device = {
+ .description = "DeLorme Earthmate USB",
+ .usb_driver = &cypress_driver,
+ .id_table = id_table_earthmate,
+- .num_interrupt_in = 1,
+- .num_interrupt_out = 1,
+- .num_bulk_in = NUM_DONT_CARE,
+- .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 1,
+ .attach = cypress_earthmate_startup,
+ .shutdown = cypress_shutdown,
+@@ -227,10 +226,6 @@ static struct usb_serial_driver cypress_hidcom_device = {
+ .description = "HID->COM RS232 Adapter",
+ .usb_driver = &cypress_driver,
+ .id_table = id_table_cyphidcomrs232,
+- .num_interrupt_in = 1,
+- .num_interrupt_out = 1,
+- .num_bulk_in = NUM_DONT_CARE,
+- .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 1,
+ .attach = cypress_hidcom_startup,
+ .shutdown = cypress_shutdown,
+@@ -257,10 +252,6 @@ static struct usb_serial_driver cypress_ca42v2_device = {
+ .description = "Nokia CA-42 V2 Adapter",
+ .usb_driver = &cypress_driver,
+ .id_table = id_table_nokiaca42v2,
+- .num_interrupt_in = 1,
+- .num_interrupt_out = 1,
+- .num_bulk_in = NUM_DONT_CARE,
+- .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 1,
+ .attach = cypress_ca42v2_startup,
+ .shutdown = cypress_shutdown,
+@@ -284,16 +275,62 @@ static struct usb_serial_driver cypress_ca42v2_device = {
+ *****************************************************************************/
+
+
++static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate)
++{
++ struct cypress_private *priv;
++ priv = usb_get_serial_port_data(port);
++
++ /*
++ * The general purpose firmware for the Cypress M8 allows for
++ * a maximum speed of 57600bps (I have no idea whether DeLorme
++ * chose to use the general purpose firmware or not), if you
++ * need to modify this speed setting for your own project
++ * please add your own chiptype and modify the code likewise.
++ * The Cypress HID->COM device will work successfully up to
++ * 115200bps (but the actual throughput is around 3kBps).
++ */
++ if (port->serial->dev->speed == USB_SPEED_LOW) {
++ /*
++ * Mike Isely <isely at pobox.com> 2-Feb-2008: The
++ * Cypress app note that describes this mechanism
++ * states the the low-speed part can't handle more
++ * than 800 bytes/sec, in which case 4800 baud is the
++ * safest speed for a part like that.
++ */
++ if (new_rate > 4800) {
++ dbg("%s - failed setting baud rate, device incapable "
++ "speed %d", __func__, new_rate);
++ return -1;
++ }
++ }
++ switch (priv->chiptype) {
++ case CT_EARTHMATE:
++ if (new_rate <= 600) {
++ /* 300 and 600 baud rates are supported under
++ * the generic firmware, but are not used with
++ * NMEA and SiRF protocols */
++ dbg("%s - failed setting baud rate, unsupported speed "
++ "of %d on Earthmate GPS", __func__, new_rate);
++ return -1;
++ }
++ break;
++ default:
++ break;
++ }
++ return new_rate;
++}
++
++
+ /* This function can either set or retrieve the current serial line settings */
+-static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_mask, int data_bits, int stop_bits,
++static int cypress_serial_control (struct usb_serial_port *port, speed_t baud_rate, int data_bits, int stop_bits,
+ int parity_enable, int parity_type, int reset, int cypress_request_type)
+ {
+ int new_baudrate = 0, retval = 0, tries = 0;
+ struct cypress_private *priv;
+- __u8 feature_buffer[8];
++ __u8 feature_buffer[5];
+ unsigned long flags;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ priv = usb_get_serial_port_data(port);
+
+@@ -302,58 +339,23 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
+
+ switch(cypress_request_type) {
+ case CYPRESS_SET_CONFIG:
+-
+- /*
+- * The general purpose firmware for the Cypress M8 allows for a maximum speed
+- * of 57600bps (I have no idea whether DeLorme chose to use the general purpose
+- * firmware or not), if you need to modify this speed setting for your own
+- * project please add your own chiptype and modify the code likewise. The
+- * Cypress HID->COM device will work successfully up to 115200bps (but the
+- * actual throughput is around 3kBps).
+- */
+- if (baud_mask != priv->cbr_mask) {
+- dbg("%s - baud rate is changing", __FUNCTION__);
+- if ( priv->chiptype == CT_EARTHMATE ) {
+- /* 300 and 600 baud rates are supported under the generic firmware,
+- * but are not used with NMEA and SiRF protocols */
+-
+- if ( (baud_mask == B300) || (baud_mask == B600) ) {
+- err("%s - failed setting baud rate, unsupported speed",
+- __FUNCTION__);
+- new_baudrate = priv->baud_rate;
+- } else if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) {
+- err("%s - failed setting baud rate, unsupported speed",
+- __FUNCTION__);
+- new_baudrate = priv->baud_rate;
+- }
+- } else if (priv->chiptype == CT_CYPHIDCOM) {
+- if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) {
+- err("%s - failed setting baud rate, unsupported speed",
+- __FUNCTION__);
+- new_baudrate = priv->baud_rate;
+- }
+- } else if (priv->chiptype == CT_CA42V2) {
+- if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) {
+- err("%s - failed setting baud rate, unsupported speed",
+- __FUNCTION__);
+- new_baudrate = priv->baud_rate;
+- }
+- } else if (priv->chiptype == CT_GENERIC) {
+- if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) {
+- err("%s - failed setting baud rate, unsupported speed",
+- __FUNCTION__);
+- new_baudrate = priv->baud_rate;
+- }
+- } else {
+- info("%s - please define your chiptype", __FUNCTION__);
+- new_baudrate = priv->baud_rate;
+- }
+- } else { /* baud rate not changing, keep the old */
++ new_baudrate = priv->baud_rate;
++ /* 0 means 'Hang up' so doesn't change the true bit rate */
++ if (baud_rate == 0)
+ new_baudrate = priv->baud_rate;
++ /* Change of speed ? */
++ else if (baud_rate != priv->baud_rate) {
++ dbg("%s - baud rate is changing", __func__);
++ retval = analyze_baud_rate(port, baud_rate);
++ if (retval >= 0) {
++ new_baudrate = retval;
++ dbg("%s - New baud rate set to %d",
++ __func__, new_baudrate);
++ }
+ }
+- dbg("%s - baud rate is being sent as %d", __FUNCTION__, new_baudrate);
++ dbg("%s - baud rate is being sent as %d", __func__, new_baudrate);
+
+- memset(feature_buffer, 0, 8);
++ memset(feature_buffer, 0, sizeof(feature_buffer));
+ /* fill the feature_buffer with new configuration */
+ *((u_int32_t *)feature_buffer) = new_baudrate;
+
+@@ -365,48 +367,65 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
+ /* 1 bit gap */
+ feature_buffer[4] |= (reset << 7); /* assign reset at end of byte, 1 bit space */
+
+- dbg("%s - device is being sent this feature report:", __FUNCTION__);
+- dbg("%s - %02X - %02X - %02X - %02X - %02X", __FUNCTION__, feature_buffer[0], feature_buffer[1],
++ dbg("%s - device is being sent this feature report:", __func__);
++ dbg("%s - %02X - %02X - %02X - %02X - %02X", __func__, feature_buffer[0], feature_buffer[1],
+ feature_buffer[2], feature_buffer[3], feature_buffer[4]);
+
+ do {
+- retval = usb_control_msg (port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0),
+- HID_REQ_SET_REPORT, USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
+- 0x0300, 0, feature_buffer, 8, 500);
++ retval = usb_control_msg(port->serial->dev,
++ usb_sndctrlpipe(port->serial->dev, 0),
++ HID_REQ_SET_REPORT,
++ USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
++ 0x0300, 0, feature_buffer,
++ sizeof(feature_buffer), 500);
+
+ if (tries++ >= 3)
+ break;
+
+- } while (retval != 8 && retval != -ENODEV);
++ } while (retval != sizeof(feature_buffer) &&
++ retval != -ENODEV);
+
+- if (retval != 8) {
+- err("%s - failed sending serial line settings - %d", __FUNCTION__, retval);
++ if (retval != sizeof(feature_buffer)) {
++ err("%s - failed sending serial line settings - %d", __func__, retval);
+ cypress_set_dead(port);
+ } else {
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->baud_rate = new_baudrate;
+- priv->cbr_mask = baud_mask;
+ priv->current_config = feature_buffer[4];
+ spin_unlock_irqrestore(&priv->lock, flags);
++ /* If we asked for a speed change encode it */
++ if (baud_rate)
++ tty_encode_baud_rate(port->tty,
++ new_baudrate, new_baudrate);
+ }
+ break;
+ case CYPRESS_GET_CONFIG:
+- dbg("%s - retreiving serial line settings", __FUNCTION__);
++ if (priv->get_cfg_unsafe) {
++ /* Not implemented for this device,
++ and if we try to do it we're likely
++ to crash the hardware. */
++ return -ENOTTY;
++ }
++ dbg("%s - retreiving serial line settings", __func__);
+ /* set initial values in feature buffer */
+- memset(feature_buffer, 0, 8);
++ memset(feature_buffer, 0, sizeof(feature_buffer));
+
+ do {
+- retval = usb_control_msg (port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0),
+- HID_REQ_GET_REPORT, USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
+- 0x0300, 0, feature_buffer, 8, 500);
+-
++ retval = usb_control_msg(port->serial->dev,
++ usb_rcvctrlpipe(port->serial->dev, 0),
++ HID_REQ_GET_REPORT,
++ USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
++ 0x0300, 0, feature_buffer,
++ sizeof(feature_buffer), 500);
++
+ if (tries++ >= 3)
+ break;
+
+- } while (retval != 5 && retval != -ENODEV);
++ } while (retval != sizeof(feature_buffer) &&
++ retval != -ENODEV);
+
+- if (retval != 5) {
+- err("%s - failed to retrieve serial line settings - %d", __FUNCTION__, retval);
++ if (retval != sizeof(feature_buffer)) {
++ err("%s - failed to retrieve serial line settings - %d", __func__, retval);
+ cypress_set_dead(port);
+ return retval;
+ } else {
+@@ -415,9 +434,6 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
+ /* store the config in one byte, and later use bit masks to check values */
+ priv->current_config = feature_buffer[4];
+ priv->baud_rate = *((u_int32_t *)feature_buffer);
+-
+- if ( (priv->cbr_mask = rate_to_mask(priv->baud_rate)) == 0x40)
+- dbg("%s - failed setting the baud mask (not defined)", __FUNCTION__);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+ }
+@@ -447,51 +463,6 @@ static void cypress_set_dead(struct usb_serial_port *port)
+ }
+
+
+-/* given a baud mask, it will return integer baud on success */
+-static int mask_to_rate (unsigned mask)
+-{
+- int rate;
+-
+- switch (mask) {
+- case B0: rate = 0; break;
+- case B300: rate = 300; break;
+- case B600: rate = 600; break;
+- case B1200: rate = 1200; break;
+- case B2400: rate = 2400; break;
+- case B4800: rate = 4800; break;
+- case B9600: rate = 9600; break;
+- case B19200: rate = 19200; break;
+- case B38400: rate = 38400; break;
+- case B57600: rate = 57600; break;
+- case B115200: rate = 115200; break;
+- default: rate = -1;
+- }
+-
+- return rate;
+-}
+-
+-
+-static unsigned rate_to_mask (int rate)
+-{
+- unsigned mask;
+-
+- switch (rate) {
+- case 0: mask = B0; break;
+- case 300: mask = B300; break;
+- case 600: mask = B600; break;
+- case 1200: mask = B1200; break;
+- case 2400: mask = B2400; break;
+- case 4800: mask = B4800; break;
+- case 9600: mask = B9600; break;
+- case 19200: mask = B19200; break;
+- case 38400: mask = B38400; break;
+- case 57600: mask = B57600; break;
+- case 115200: mask = B115200; break;
+- default: mask = 0x40;
+- }
+-
+- return mask;
+-}
+ /*****************************************************************************
+ * Cypress serial driver functions
+ *****************************************************************************/
+@@ -502,7 +473,7 @@ static int generic_startup (struct usb_serial *serial)
+ struct cypress_private *priv;
+ struct usb_serial_port *port = serial->port[0];
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ priv = kzalloc(sizeof (struct cypress_private), GFP_KERNEL);
+ if (!priv)
+@@ -523,17 +494,27 @@ static int generic_startup (struct usb_serial *serial)
+ priv->line_control = 0;
+ priv->termios_initialized = 0;
+ priv->rx_flags = 0;
+- priv->cbr_mask = B300;
++ /* Default packet format setting is determined by packet size.
++ Anything with a size larger then 9 must have a separate
++ count field since the 3 bit count field is otherwise too
++ small. Otherwise we can use the slightly more compact
++ format. This is in accordance with the cypress_m8 serial
++ converter app note. */
++ if (port->interrupt_out_size > 9) {
++ priv->pkt_fmt = packet_format_1;
++ } else {
++ priv->pkt_fmt = packet_format_2;
++ }
+ if (interval > 0) {
+ priv->write_urb_interval = interval;
+ priv->read_urb_interval = interval;
+ dbg("%s - port %d read & write intervals forced to %d",
+- __FUNCTION__,port->number,interval);
++ __func__,port->number,interval);
+ } else {
+ priv->write_urb_interval = port->interrupt_out_urb->interval;
+ priv->read_urb_interval = port->interrupt_in_urb->interval;
+ dbg("%s - port %d intervals: read=%d write=%d",
+- __FUNCTION__,port->number,
++ __func__,port->number,
+ priv->read_urb_interval,priv->write_urb_interval);
+ }
+ usb_set_serial_port_data(port, priv);
+@@ -545,17 +526,30 @@ static int generic_startup (struct usb_serial *serial)
+ static int cypress_earthmate_startup (struct usb_serial *serial)
+ {
+ struct cypress_private *priv;
++ struct usb_serial_port *port = serial->port[0];
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ if (generic_startup(serial)) {
+- dbg("%s - Failed setting up port %d", __FUNCTION__,
+- serial->port[0]->number);
++ dbg("%s - Failed setting up port %d", __func__,
++ port->number);
+ return 1;
+ }
+
+- priv = usb_get_serial_port_data(serial->port[0]);
++ priv = usb_get_serial_port_data(port);
+ priv->chiptype = CT_EARTHMATE;
++ /* All Earthmate devices use the separated-count packet
++ format! Idiotic. */
++ priv->pkt_fmt = packet_format_1;
++ if (serial->dev->descriptor.idProduct != PRODUCT_ID_EARTHMATEUSB) {
++ /* The old original USB Earthmate seemed able to
++ handle GET_CONFIG requests; everything they've
++ produced since that time crashes if this command is
++ attempted :-( */
++ dbg("%s - Marking this device as unsafe for GET_CONFIG "
++ "commands", __func__);
++ priv->get_cfg_unsafe = !0;
++ }
+
+ return 0;
+ } /* cypress_earthmate_startup */
+@@ -565,10 +559,10 @@ static int cypress_hidcom_startup (struct usb_serial *serial)
+ {
+ struct cypress_private *priv;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ if (generic_startup(serial)) {
+- dbg("%s - Failed setting up port %d", __FUNCTION__,
++ dbg("%s - Failed setting up port %d", __func__,
+ serial->port[0]->number);
+ return 1;
+ }
+@@ -584,10 +578,10 @@ static int cypress_ca42v2_startup (struct usb_serial *serial)
+ {
+ struct cypress_private *priv;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ if (generic_startup(serial)) {
+- dbg("%s - Failed setting up port %d", __FUNCTION__,
++ dbg("%s - Failed setting up port %d", __func__,
+ serial->port[0]->number);
+ return 1;
+ }
+@@ -603,7 +597,7 @@ static void cypress_shutdown (struct usb_serial *serial)
+ {
+ struct cypress_private *priv;
+
+- dbg ("%s - port %d", __FUNCTION__, serial->port[0]->number);
++ dbg ("%s - port %d", __func__, serial->port[0]->number);
+
+ /* all open ports are closed at this point */
+
+@@ -624,7 +618,7 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp)
+ unsigned long flags;
+ int result = 0;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (!priv->comm_is_ok)
+ return -EIO;
+@@ -652,16 +646,16 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp)
+ result = cypress_write(port, NULL, 0);
+
+ if (result) {
+- dev_err(&port->dev, "%s - failed setting the control lines - error %d\n", __FUNCTION__, result);
++ dev_err(&port->dev, "%s - failed setting the control lines - error %d\n", __func__, result);
+ return result;
+ } else
+- dbg("%s - success setting the control lines", __FUNCTION__);
++ dbg("%s - success setting the control lines", __func__);
+
+ cypress_set_termios(port, &priv->tmp_termios);
+
+ /* setup the port and start reading from the device */
+ if(!port->interrupt_in_urb){
+- err("%s - interrupt_in_urb is empty!", __FUNCTION__);
++ err("%s - interrupt_in_urb is empty!", __func__);
+ return(-1);
+ }
+
+@@ -672,7 +666,7 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp)
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+
+ if (result){
+- dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
++ dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
+ cypress_set_dead(port);
+ }
+
+@@ -688,7 +682,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
+ long timeout;
+ wait_queue_t wait;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /* wait for data to drain from buffer */
+ spin_lock_irq(&priv->lock);
+@@ -726,7 +720,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
+ timeout = 2*HZ;
+ schedule_timeout_interruptible(timeout);
+
+- dbg("%s - stopping urbs", __FUNCTION__);
++ dbg("%s - stopping urbs", __func__);
+ usb_kill_urb (port->interrupt_in_urb);
+ usb_kill_urb (port->interrupt_out_urb);
+
+@@ -755,7 +749,7 @@ static int cypress_write(struct usb_serial_port *port, const unsigned char *buf,
+ struct cypress_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+
+- dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
++ dbg("%s - port %d, %d bytes", __func__, port->number, count);
+
+ /* line control commands, which need to be executed immediately,
+ are not put into the buffer for obvious reasons.
+@@ -788,12 +782,12 @@ static void cypress_send(struct usb_serial_port *port)
+ if (!priv->comm_is_ok)
+ return;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
+- dbg("%s - interrupt out size is %d", __FUNCTION__, port->interrupt_out_size);
++ dbg("%s - port %d", __func__, port->number);
++ dbg("%s - interrupt out size is %d", __func__, port->interrupt_out_size);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (priv->write_urb_in_use) {
+- dbg("%s - can't write, urb in use", __FUNCTION__);
++ dbg("%s - can't write, urb in use", __func__);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return;
+ }
+@@ -803,21 +797,18 @@ static void cypress_send(struct usb_serial_port *port)
+ memset(port->interrupt_out_urb->transfer_buffer, 0, port->interrupt_out_size);
+
+ spin_lock_irqsave(&priv->lock, flags);
+- switch (port->interrupt_out_size) {
+- case 32:
+- /* this is for the CY7C64013... */
+- offset = 2;
+- port->interrupt_out_buffer[0] = priv->line_control;
+- break;
+- case 8:
+- /* this is for the CY7C63743... */
+- offset = 1;
+- port->interrupt_out_buffer[0] = priv->line_control;
+- break;
+- default:
+- dbg("%s - wrong packet size", __FUNCTION__);
+- spin_unlock_irqrestore(&priv->lock, flags);
+- return;
++ switch (priv->pkt_fmt) {
++ default:
++ case packet_format_1:
++ /* this is for the CY7C64013... */
++ offset = 2;
++ port->interrupt_out_buffer[0] = priv->line_control;
++ break;
++ case packet_format_2:
++ /* this is for the CY7C63743... */
++ offset = 1;
++ port->interrupt_out_buffer[0] = priv->line_control;
++ break;
+ }
+
+ if (priv->line_control & CONTROL_RESET)
+@@ -825,7 +816,7 @@ static void cypress_send(struct usb_serial_port *port)
+
+ if (priv->cmd_ctrl) {
+ priv->cmd_count++;
+- dbg("%s - line control command being issued", __FUNCTION__);
++ dbg("%s - line control command being issued", __func__);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ goto send;
+ } else
+@@ -838,15 +829,16 @@ static void cypress_send(struct usb_serial_port *port)
+ return;
+ }
+
+- switch (port->interrupt_out_size) {
+- case 32:
+- port->interrupt_out_buffer[1] = count;
+- break;
+- case 8:
+- port->interrupt_out_buffer[0] |= count;
++ switch (priv->pkt_fmt) {
++ default:
++ case packet_format_1:
++ port->interrupt_out_buffer[1] = count;
++ break;
++ case packet_format_2:
++ port->interrupt_out_buffer[0] |= count;
+ }
+
+- dbg("%s - count is %d", __FUNCTION__, count);
++ dbg("%s - count is %d", __func__, count);
+
+ send:
+ spin_lock_irqsave(&priv->lock, flags);
+@@ -856,9 +848,10 @@ send:
+ if (priv->cmd_ctrl)
+ actual_size = 1;
+ else
+- actual_size = count + (port->interrupt_out_size == 32 ? 2 : 1);
+-
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, port->interrupt_out_size,
++ actual_size = count +
++ (priv->pkt_fmt == packet_format_1 ? 2 : 1);
++
++ usb_serial_debug_data(debug, &port->dev, __func__, port->interrupt_out_size,
+ port->interrupt_out_urb->transfer_buffer);
+
+ usb_fill_int_urb(port->interrupt_out_urb, port->serial->dev,
+@@ -867,7 +860,7 @@ send:
+ cypress_write_int_callback, port, priv->write_urb_interval);
+ result = usb_submit_urb (port->interrupt_out_urb, GFP_ATOMIC);
+ if (result) {
+- dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__,
++ dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__,
+ result);
+ priv->write_urb_in_use = 0;
+ cypress_set_dead(port);
+@@ -891,13 +884,13 @@ static int cypress_write_room(struct usb_serial_port *port)
+ int room = 0;
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ room = cypress_buf_space_avail(priv->buf);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+- dbg("%s - returns %d", __FUNCTION__, room);
++ dbg("%s - returns %d", __func__, room);
+ return room;
+ }
+
+@@ -909,7 +902,7 @@ static int cypress_tiocmget (struct usb_serial_port *port, struct file *file)
+ unsigned int result = 0;
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ control = priv->line_control;
+@@ -923,7 +916,7 @@ static int cypress_tiocmget (struct usb_serial_port *port, struct file *file)
+ | ((status & UART_RI) ? TIOCM_RI : 0)
+ | ((status & UART_CD) ? TIOCM_CD : 0);
+
+- dbg("%s - result = %x", __FUNCTION__, result);
++ dbg("%s - result = %x", __func__, result);
+
+ return result;
+ }
+@@ -935,7 +928,7 @@ static int cypress_tiocmset (struct usb_serial_port *port, struct file *file,
+ struct cypress_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (set & TIOCM_RTS)
+@@ -946,9 +939,9 @@ static int cypress_tiocmset (struct usb_serial_port *port, struct file *file,
+ priv->line_control &= ~CONTROL_RTS;
+ if (clear & TIOCM_DTR)
+ priv->line_control &= ~CONTROL_DTR;
++ priv->cmd_ctrl = 1;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+- priv->cmd_ctrl = 1;
+ return cypress_write(port, NULL, 0);
+ }
+
+@@ -957,23 +950,9 @@ static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsi
+ {
+ struct cypress_private *priv = usb_get_serial_port_data(port);
+
+- dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
++ dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
+
+ switch (cmd) {
+- case TIOCGSERIAL:
+- if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct ktermios))) {
+- return -EFAULT;
+- }
+- return (0);
+- break;
+- case TIOCSSERIAL:
+- if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct ktermios))) {
+- return -EFAULT;
+- }
+- /* here we need to call cypress_set_termios to invoke the new settings */
+- cypress_set_termios(port, &priv->tmp_termios);
+- return (0);
+- break;
+ /* This code comes from drivers/char/serial.c and ftdi_sio.c */
+ case TIOCMIWAIT:
+ while (priv != NULL) {
+@@ -1009,7 +988,7 @@ static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsi
+ break;
+ }
+
+- dbg("%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h", __FUNCTION__, cmd);
++ dbg("%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h", __func__, cmd);
+
+ return -ENOIOCTLCMD;
+ } /* cypress_ioctl */
+@@ -1021,18 +1000,14 @@ static void cypress_set_termios (struct usb_serial_port *port,
+ struct cypress_private *priv = usb_get_serial_port_data(port);
+ struct tty_struct *tty;
+ int data_bits, stop_bits, parity_type, parity_enable;
+- unsigned cflag, iflag, baud_mask;
++ unsigned cflag, iflag;
+ unsigned long flags;
+ __u8 oldlines;
+ int linechange = 0;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ tty = port->tty;
+- if ((!tty) || (!tty->termios)) {
+- dbg("%s - no tty structures", __FUNCTION__);
+- return;
+- }
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (!priv->termios_initialized) {
+@@ -1040,40 +1015,37 @@ static void cypress_set_termios (struct usb_serial_port *port,
+ *(tty->termios) = tty_std_termios;
+ tty->termios->c_cflag = B4800 | CS8 | CREAD | HUPCL |
+ CLOCAL;
++ tty->termios->c_ispeed = 4800;
++ tty->termios->c_ospeed = 4800;
+ } else if (priv->chiptype == CT_CYPHIDCOM) {
+ *(tty->termios) = tty_std_termios;
+ tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL |
+ CLOCAL;
++ tty->termios->c_ispeed = 9600;
++ tty->termios->c_ospeed = 9600;
+ } else if (priv->chiptype == CT_CA42V2) {
+ *(tty->termios) = tty_std_termios;
+ tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL |
+ CLOCAL;
++ tty->termios->c_ispeed = 9600;
++ tty->termios->c_ospeed = 9600;
+ }
+ priv->termios_initialized = 1;
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+
++ /* Unsupported features need clearing */
++ tty->termios->c_cflag &= ~(CMSPAR|CRTSCTS);
++
+ cflag = tty->termios->c_cflag;
+ iflag = tty->termios->c_iflag;
+
+ /* check if there are new settings */
+ if (old_termios) {
+- if ((cflag != old_termios->c_cflag) ||
+- (RELEVANT_IFLAG(iflag) !=
+- RELEVANT_IFLAG(old_termios->c_iflag))) {
+- dbg("%s - attempting to set new termios settings",
+- __FUNCTION__);
+- /* should make a copy of this in case something goes
+- * wrong in the function, we can restore it */
+- spin_lock_irqsave(&priv->lock, flags);
+- priv->tmp_termios = *(tty->termios);
+- spin_unlock_irqrestore(&priv->lock, flags);
+- } else {
+- dbg("%s - nothing to do, exiting", __FUNCTION__);
+- return;
+- }
+- } else
+- return;
++ spin_lock_irqsave(&priv->lock, flags);
++ priv->tmp_termios = *(tty->termios);
++ spin_unlock_irqrestore(&priv->lock, flags);
++ }
+
+ /* set number of data bits, parity, stop bits */
+ /* when parity is disabled the parity type bit is ignored */
+@@ -1104,7 +1076,7 @@ static void cypress_set_termios (struct usb_serial_port *port,
+ break;
+ default:
+ err("%s - CSIZE was set, but not CS5-CS8",
+- __FUNCTION__);
++ __func__);
+ data_bits = 3;
+ }
+ } else
+@@ -1114,54 +1086,17 @@ static void cypress_set_termios (struct usb_serial_port *port,
+ oldlines = priv->line_control;
+ if ((cflag & CBAUD) == B0) {
+ /* drop dtr and rts */
+- dbg("%s - dropping the lines, baud rate 0bps", __FUNCTION__);
+- baud_mask = B0;
++ dbg("%s - dropping the lines, baud rate 0bps", __func__);
+ priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
+- } else {
+- baud_mask = (cflag & CBAUD);
+- switch(baud_mask) {
+- case B300:
+- dbg("%s - setting baud 300bps", __FUNCTION__);
+- break;
+- case B600:
+- dbg("%s - setting baud 600bps", __FUNCTION__);
+- break;
+- case B1200:
+- dbg("%s - setting baud 1200bps", __FUNCTION__);
+- break;
+- case B2400:
+- dbg("%s - setting baud 2400bps", __FUNCTION__);
+- break;
+- case B4800:
+- dbg("%s - setting baud 4800bps", __FUNCTION__);
+- break;
+- case B9600:
+- dbg("%s - setting baud 9600bps", __FUNCTION__);
+- break;
+- case B19200:
+- dbg("%s - setting baud 19200bps", __FUNCTION__);
+- break;
+- case B38400:
+- dbg("%s - setting baud 38400bps", __FUNCTION__);
+- break;
+- case B57600:
+- dbg("%s - setting baud 57600bps", __FUNCTION__);
+- break;
+- case B115200:
+- dbg("%s - setting baud 115200bps", __FUNCTION__);
+- break;
+- default:
+- dbg("%s - unknown masked baud rate", __FUNCTION__);
+- }
++ } else
+ priv->line_control = (CONTROL_DTR | CONTROL_RTS);
+- }
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ dbg("%s - sending %d stop_bits, %d parity_enable, %d parity_type, "
+- "%d data_bits (+5)", __FUNCTION__, stop_bits,
++ "%d data_bits (+5)", __func__, stop_bits,
+ parity_enable, parity_type, data_bits);
+
+- cypress_serial_control(port, baud_mask, data_bits, stop_bits,
++ cypress_serial_control(port, tty_get_baud_rate(tty), data_bits, stop_bits,
+ parity_enable, parity_type, 0, CYPRESS_SET_CONFIG);
+
+ /* we perform a CYPRESS_GET_CONFIG so that the current settings are
+@@ -1219,13 +1154,13 @@ static int cypress_chars_in_buffer(struct usb_serial_port *port)
+ int chars = 0;
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ chars = cypress_buf_data_avail(priv->buf);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+- dbg("%s - returns %d", __FUNCTION__, chars);
++ dbg("%s - returns %d", __func__, chars);
+ return chars;
+ }
+
+@@ -1235,7 +1170,7 @@ static void cypress_throttle (struct usb_serial_port *port)
+ struct cypress_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->rx_flags = THROTTLED;
+@@ -1249,7 +1184,7 @@ static void cypress_unthrottle (struct usb_serial_port *port)
+ int actually_throttled, result;
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
+@@ -1265,7 +1200,7 @@ static void cypress_unthrottle (struct usb_serial_port *port)
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+ if (result) {
+ dev_err(&port->dev, "%s - failed submitting read urb, "
+- "error %d\n", __FUNCTION__, result);
++ "error %d\n", __func__, result);
+ cypress_set_dead(port);
+ }
+ }
+@@ -1274,7 +1209,7 @@ static void cypress_unthrottle (struct usb_serial_port *port)
+
+ static void cypress_read_int_callback(struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct cypress_private *priv = usb_get_serial_port_data(port);
+ struct tty_struct *tty;
+ unsigned char *data = urb->transfer_buffer;
+@@ -1286,7 +1221,7 @@ static void cypress_read_int_callback(struct urb *urb)
+ int i = 0;
+ int status = urb->status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ switch (status) {
+ case 0: /* success */
+@@ -1302,14 +1237,14 @@ static void cypress_read_int_callback(struct urb *urb)
+ default:
+ /* something ugly is going on... */
+ dev_err(&urb->dev->dev,"%s - unexpected nonzero read status received: %d\n",
+- __FUNCTION__, status);
++ __func__, status);
+ cypress_set_dead(port);
+ return;
+ }
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (priv->rx_flags & THROTTLED) {
+- dbg("%s - now throttling", __FUNCTION__);
++ dbg("%s - now throttling", __func__);
+ priv->rx_flags |= ACTUALLY_THROTTLED;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return;
+@@ -1318,48 +1253,48 @@ static void cypress_read_int_callback(struct urb *urb)
+
+ tty = port->tty;
+ if (!tty) {
+- dbg("%s - bad tty pointer - exiting", __FUNCTION__);
++ dbg("%s - bad tty pointer - exiting", __func__);
+ return;
+ }
+
+ spin_lock_irqsave(&priv->lock, flags);
+- switch(urb->actual_length) {
+- case 32:
+- /* This is for the CY7C64013... */
+- priv->current_status = data[0] & 0xF8;
+- bytes = data[1] + 2;
+- i = 2;
+- if (bytes > 2)
+- havedata = 1;
+- break;
+- case 8:
+- /* This is for the CY7C63743... */
+- priv->current_status = data[0] & 0xF8;
+- bytes = (data[0] & 0x07) + 1;
+- i = 1;
+- if (bytes > 1)
+- havedata = 1;
+- break;
+- default:
+- dbg("%s - wrong packet size - received %d bytes",
+- __FUNCTION__, urb->actual_length);
+- spin_unlock_irqrestore(&priv->lock, flags);
+- goto continue_read;
++ result = urb->actual_length;
++ switch (priv->pkt_fmt) {
++ default:
++ case packet_format_1:
++ /* This is for the CY7C64013... */
++ priv->current_status = data[0] & 0xF8;
++ bytes = data[1] + 2;
++ i = 2;
++ if (bytes > 2)
++ havedata = 1;
++ break;
++ case packet_format_2:
++ /* This is for the CY7C63743... */
++ priv->current_status = data[0] & 0xF8;
++ bytes = (data[0] & 0x07) + 1;
++ i = 1;
++ if (bytes > 1)
++ havedata = 1;
++ break;
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
++ if (result < bytes) {
++ dbg("%s - wrong packet size - received %d bytes but packet "
++ "said %d bytes", __func__, result, bytes);
++ goto continue_read;
++ }
+
+- usb_serial_debug_data (debug, &port->dev, __FUNCTION__,
++ usb_serial_debug_data (debug, &port->dev, __func__,
+ urb->actual_length, data);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ /* check to see if status has changed */
+- if (priv != NULL) {
+- if (priv->current_status != priv->prev_status) {
+- priv->diff_status |= priv->current_status ^
+- priv->prev_status;
+- wake_up_interruptible(&priv->delta_msr_wait);
+- priv->prev_status = priv->current_status;
+- }
++ if (priv->current_status != priv->prev_status) {
++ priv->diff_status |= priv->current_status ^
++ priv->prev_status;
++ wake_up_interruptible(&priv->delta_msr_wait);
++ priv->prev_status = priv->current_status;
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+@@ -1367,7 +1302,7 @@ static void cypress_read_int_callback(struct urb *urb)
+ * though */
+ if (tty && !(tty->termios->c_cflag & CLOCAL) &&
+ !(priv->current_status & UART_CD)) {
+- dbg("%s - calling hangup", __FUNCTION__);
++ dbg("%s - calling hangup", __func__);
+ tty_hangup(tty);
+ goto continue_read;
+ }
+@@ -1380,7 +1315,7 @@ static void cypress_read_int_callback(struct urb *urb)
+ if (priv->current_status & CYP_ERROR) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ tty_flag = TTY_PARITY;
+- dbg("%s - Parity Error detected", __FUNCTION__);
++ dbg("%s - Parity Error detected", __func__);
+ } else
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+@@ -1414,7 +1349,7 @@ continue_read:
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+ if (result) {
+ dev_err(&urb->dev->dev, "%s - failed resubmitting "
+- "read urb, error %d\n", __FUNCTION__,
++ "read urb, error %d\n", __func__,
+ result);
+ cypress_set_dead(port);
+ }
+@@ -1426,12 +1361,12 @@ continue_read:
+
+ static void cypress_write_int_callback(struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct cypress_private *priv = usb_get_serial_port_data(port);
+ int result;
+ int status = urb->status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ switch (status) {
+ case 0:
+@@ -1442,7 +1377,7 @@ static void cypress_write_int_callback(struct urb *urb)
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ priv->write_urb_in_use = 0;
+ return;
+ case -EPIPE: /* no break needed; clear halt and resubmit */
+@@ -1451,19 +1386,19 @@ static void cypress_write_int_callback(struct urb *urb)
+ usb_clear_halt(port->serial->dev, 0x02);
+ /* error in the urb, so we have to resubmit it */
+ dbg("%s - nonzero write bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ port->interrupt_out_urb->transfer_buffer_length = 1;
+ port->interrupt_out_urb->dev = port->serial->dev;
+ result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
+ if (!result)
+ return;
+ dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n",
+- __FUNCTION__, result);
++ __func__, result);
+ cypress_set_dead(port);
+ break;
+ default:
+ dev_err(&urb->dev->dev,"%s - unexpected nonzero write status received: %d\n",
+- __FUNCTION__, status);
++ __func__, status);
+ cypress_set_dead(port);
+ break;
+ }
+@@ -1668,7 +1603,7 @@ static int __init cypress_init(void)
+ {
+ int retval;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ retval = usb_serial_register(&cypress_earthmate_device);
+ if (retval)
+@@ -1699,7 +1634,7 @@ failed_em_register:
+
+ static void __exit cypress_exit (void)
+ {
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ usb_deregister (&cypress_driver);
+ usb_serial_deregister (&cypress_earthmate_device);
+diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
+index 5f9c6e4..d17d164 100644
+--- a/drivers/usb/serial/digi_acceleport.c
++++ b/drivers/usb/serial/digi_acceleport.c
+@@ -508,9 +508,6 @@ static struct usb_serial_driver digi_acceleport_2_device = {
+ .description = "Digi 2 port USB adapter",
+ .usb_driver = &digi_driver,
+ .id_table = id_table_2,
+- .num_interrupt_in = 0,
+- .num_bulk_in = 4,
+- .num_bulk_out = 4,
+ .num_ports = 3,
+ .open = digi_open,
+ .close = digi_close,
+@@ -538,9 +535,6 @@ static struct usb_serial_driver digi_acceleport_4_device = {
+ .description = "Digi 4 port USB adapter",
+ .usb_driver = &digi_driver,
+ .id_table = id_table_4,
+- .num_interrupt_in = 0,
+- .num_bulk_in = 5,
+- .num_bulk_out = 5,
+ .num_ports = 4,
+ .open = digi_open,
+ .close = digi_close,
+@@ -665,7 +659,7 @@ static int digi_write_oob_command(struct usb_serial_port *port,
+ }
+ spin_unlock_irqrestore(&oob_priv->dp_port_lock, flags);
+ if (ret)
+- err("%s: usb_submit_urb failed, ret=%d", __FUNCTION__, ret);
++ err("%s: usb_submit_urb failed, ret=%d", __func__, ret);
+ return ret;
+
+ }
+@@ -746,7 +740,7 @@ static int digi_write_inb_command(struct usb_serial_port *port,
+
+ if (ret)
+ err("%s: usb_submit_urb failed, ret=%d, port=%d",
+- __FUNCTION__, ret, priv->dp_port_num);
++ __func__, ret, priv->dp_port_num);
+ return ret;
+ }
+
+@@ -810,7 +804,7 @@ static int digi_set_modem_signals(struct usb_serial_port *port,
+ spin_unlock(&port_priv->dp_port_lock);
+ spin_unlock_irqrestore(&oob_priv->dp_port_lock, flags);
+ if (ret)
+- err("%s: usb_submit_urb failed, ret=%d", __FUNCTION__, ret);
++ err("%s: usb_submit_urb failed, ret=%d", __func__, ret);
+ return ret;
+ }
+
+@@ -903,7 +897,7 @@ static void digi_rx_unthrottle(struct usb_serial_port *port)
+
+ if (ret)
+ err("%s: usb_submit_urb failed, ret=%d, port=%d",
+- __FUNCTION__, ret, priv->dp_port_num);
++ __func__, ret, priv->dp_port_num);
+ }
+
+
+@@ -1113,7 +1107,7 @@ static int digi_tiocmget(struct usb_serial_port *port, struct file *file)
+ unsigned int val;
+ unsigned long flags;
+
+- dbg("%s: TOP: port=%d", __FUNCTION__, priv->dp_port_num);
++ dbg("%s: TOP: port=%d", __func__, priv->dp_port_num);
+
+ spin_lock_irqsave(&priv->dp_port_lock, flags);
+ val = priv->dp_modem_signals;
+@@ -1129,7 +1123,7 @@ static int digi_tiocmset(struct usb_serial_port *port, struct file *file,
+ unsigned int val;
+ unsigned long flags;
+
+- dbg("%s: TOP: port=%d", __FUNCTION__, priv->dp_port_num);
++ dbg("%s: TOP: port=%d", __func__, priv->dp_port_num);
+
+ spin_lock_irqsave(&priv->dp_port_lock, flags);
+ val = (priv->dp_modem_signals & ~clear) | set;
+@@ -1224,7 +1218,7 @@ static int digi_write(struct usb_serial_port *port, const unsigned char *buf, in
+ spin_unlock_irqrestore(&priv->dp_port_lock, flags);
+ if (ret < 0)
+ err("%s: usb_submit_urb failed, ret=%d, port=%d",
+- __FUNCTION__, ret, priv->dp_port_num);
++ __func__, ret, priv->dp_port_num);
+ dbg("digi_write: returning %d", ret);
+ return ret;
+
+@@ -1233,7 +1227,7 @@ static int digi_write(struct usb_serial_port *port, const unsigned char *buf, in
+ static void digi_write_bulk_callback(struct urb *urb)
+ {
+
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct usb_serial *serial;
+ struct digi_port *priv;
+ struct digi_serial *serial_priv;
+@@ -1245,13 +1239,13 @@ static void digi_write_bulk_callback(struct urb *urb)
+ /* port and serial sanity check */
+ if (port == NULL || (priv=usb_get_serial_port_data(port)) == NULL) {
+ err("%s: port or port->private is NULL, status=%d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
+ serial = port->serial;
+ if (serial == NULL || (serial_priv=usb_get_serial_data(serial)) == NULL) {
+ err("%s: serial or serial->private is NULL, status=%d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
+
+@@ -1292,7 +1286,7 @@ static void digi_write_bulk_callback(struct urb *urb)
+ spin_unlock(&priv->dp_port_lock);
+ if (ret)
+ err("%s: usb_submit_urb failed, ret=%d, port=%d",
+- __FUNCTION__, ret, priv->dp_port_num);
++ __func__, ret, priv->dp_port_num);
+ }
+
+ static int digi_write_room(struct usb_serial_port *port)
+@@ -1521,7 +1515,7 @@ static int digi_startup_device(struct usb_serial *serial)
+ port->write_urb->dev = port->serial->dev;
+ if ((ret = usb_submit_urb(port->read_urb, GFP_KERNEL)) != 0) {
+ err("%s: usb_submit_urb failed, ret=%d, port=%d",
+- __FUNCTION__, ret, i);
++ __func__, ret, i);
+ break;
+ }
+ }
+@@ -1611,7 +1605,7 @@ static void digi_shutdown(struct usb_serial *serial)
+
+ static void digi_read_bulk_callback(struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct digi_port *priv;
+ struct digi_serial *serial_priv;
+ int ret;
+@@ -1622,20 +1616,20 @@ static void digi_read_bulk_callback(struct urb *urb)
+ /* port sanity check, do not resubmit if port is not valid */
+ if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) {
+ err("%s: port or port->private is NULL, status=%d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
+ if (port->serial == NULL ||
+ (serial_priv=usb_get_serial_data(port->serial)) == NULL) {
+ err("%s: serial is bad or serial->private is NULL, status=%d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
+
+ /* do not resubmit urb if it has any status error */
+ if (status) {
+ err("%s: nonzero read bulk status: status=%d, port=%d",
+- __FUNCTION__, status, priv->dp_port_num);
++ __func__, status, priv->dp_port_num);
+ return;
+ }
+
+@@ -1652,7 +1646,7 @@ static void digi_read_bulk_callback(struct urb *urb)
+ urb->dev = port->serial->dev;
+ if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+ err("%s: failed resubmitting urb, ret=%d, port=%d",
+- __FUNCTION__, ret, priv->dp_port_num);
++ __func__, ret, priv->dp_port_num);
+ }
+
+ }
+@@ -1670,7 +1664,7 @@ static void digi_read_bulk_callback(struct urb *urb)
+ static int digi_read_inb_callback(struct urb *urb)
+ {
+
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct tty_struct *tty = port->tty;
+ struct digi_port *priv = usb_get_serial_port_data(port);
+ int opcode = ((unsigned char *)urb->transfer_buffer)[0];
+@@ -1690,7 +1684,7 @@ static int digi_read_inb_callback(struct urb *urb)
+ if (urb->actual_length != len + 2) {
+ err("%s: INCOMPLETE OR MULTIPLE PACKET, urb->status=%d, "
+ "port=%d, opcode=%d, len=%d, actual_length=%d, "
+- "status=%d", __FUNCTION__, status, priv->dp_port_num,
++ "status=%d", __func__, status, priv->dp_port_num,
+ opcode, len, urb->actual_length, port_status);
+ return -1;
+ }
+@@ -1739,9 +1733,9 @@ static int digi_read_inb_callback(struct urb *urb)
+ spin_unlock(&priv->dp_port_lock);
+
+ if (opcode == DIGI_CMD_RECEIVE_DISABLE)
+- dbg("%s: got RECEIVE_DISABLE", __FUNCTION__);
++ dbg("%s: got RECEIVE_DISABLE", __func__);
+ else if (opcode != DIGI_CMD_RECEIVE_DATA)
+- dbg("%s: unknown opcode: %d", __FUNCTION__, opcode);
++ dbg("%s: unknown opcode: %d", __func__, opcode);
+
+ return(throttled ? 1 : 0);
+
+@@ -1760,7 +1754,7 @@ static int digi_read_inb_callback(struct urb *urb)
+ static int digi_read_oob_callback(struct urb *urb)
+ {
+
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct usb_serial *serial = port->serial;
+ struct digi_port *priv = usb_get_serial_port_data(port);
+ int opcode, line, status, val;
+diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
+index a5c8e1e..c5ec309 100644
+--- a/drivers/usb/serial/empeg.c
++++ b/drivers/usb/serial/empeg.c
+@@ -118,9 +118,6 @@ static struct usb_serial_driver empeg_device = {
+ },
+ .id_table = id_table,
+ .usb_driver = &empeg_driver,
+- .num_interrupt_in = 0,
+- .num_bulk_in = 1,
+- .num_bulk_out = 1,
+ .num_ports = 1,
+ .open = empeg_open,
+ .close = empeg_close,
+@@ -153,7 +150,7 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp)
+ struct usb_serial *serial = port->serial;
+ int result = 0;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /* Force default termio settings */
+ empeg_set_termios (port, NULL) ;
+@@ -175,7 +172,7 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp)
+ result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+
+ if (result)
+- dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
++ dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
+
+ return result;
+ }
+@@ -183,7 +180,7 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp)
+
+ static void empeg_close (struct usb_serial_port *port, struct file * filp)
+ {
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /* shutdown our bulk read */
+ usb_kill_urb(port->read_urb);
+@@ -203,7 +200,7 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf,
+ int bytes_sent = 0;
+ int transfer_size;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ while (count > 0) {
+
+@@ -222,14 +219,14 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf,
+ spin_unlock_irqrestore (&write_urb_pool_lock, flags);
+
+ if (urb == NULL) {
+- dbg("%s - no more free urbs", __FUNCTION__);
++ dbg("%s - no more free urbs", __func__);
+ goto exit;
+ }
+
+ if (urb->transfer_buffer == NULL) {
+ urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
+ if (urb->transfer_buffer == NULL) {
+- dev_err(&port->dev, "%s no more kernel memory...\n", __FUNCTION__);
++ dev_err(&port->dev, "%s no more kernel memory...\n", __func__);
+ goto exit;
+ }
+ }
+@@ -238,7 +235,7 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf,
+
+ memcpy (urb->transfer_buffer, current_position, transfer_size);
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, transfer_size, urb->transfer_buffer);
++ usb_serial_debug_data(debug, &port->dev, __func__, transfer_size, urb->transfer_buffer);
+
+ /* build up our urb */
+ usb_fill_bulk_urb (
+@@ -254,7 +251,7 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf,
+ /* send it down the pipe */
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (status) {
+- dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n", __FUNCTION__, status);
++ dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n", __func__, status);
+ bytes_sent = status;
+ break;
+ }
+@@ -278,7 +275,7 @@ static int empeg_write_room (struct usb_serial_port *port)
+ int i;
+ int room = 0;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave (&write_urb_pool_lock, flags);
+
+@@ -291,7 +288,7 @@ static int empeg_write_room (struct usb_serial_port *port)
+
+ spin_unlock_irqrestore (&write_urb_pool_lock, flags);
+
+- dbg("%s - returns %d", __FUNCTION__, room);
++ dbg("%s - returns %d", __func__, room);
+
+ return (room);
+
+@@ -304,7 +301,7 @@ static int empeg_chars_in_buffer (struct usb_serial_port *port)
+ int i;
+ int chars = 0;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave (&write_urb_pool_lock, flags);
+
+@@ -317,7 +314,7 @@ static int empeg_chars_in_buffer (struct usb_serial_port *port)
+
+ spin_unlock_irqrestore (&write_urb_pool_lock, flags);
+
+- dbg("%s - returns %d", __FUNCTION__, chars);
++ dbg("%s - returns %d", __func__, chars);
+
+ return (chars);
+
+@@ -329,11 +326,11 @@ static void empeg_write_bulk_callback (struct urb *urb)
+ struct usb_serial_port *port = urb->context;
+ int status = urb->status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (status) {
+ dbg("%s - nonzero write bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
+
+@@ -343,21 +340,21 @@ static void empeg_write_bulk_callback (struct urb *urb)
+
+ static void empeg_read_bulk_callback (struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct tty_struct *tty;
+ unsigned char *data = urb->transfer_buffer;
+ int result;
+ int status = urb->status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++ usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+
+ tty = port->tty;
+
+@@ -382,7 +379,7 @@ static void empeg_read_bulk_callback (struct urb *urb)
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+
+ if (result)
+- dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
++ dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
+
+ return;
+
+@@ -391,7 +388,7 @@ static void empeg_read_bulk_callback (struct urb *urb)
+
+ static void empeg_throttle (struct usb_serial_port *port)
+ {
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+ usb_kill_urb(port->read_urb);
+ }
+
+@@ -400,14 +397,14 @@ static void empeg_unthrottle (struct usb_serial_port *port)
+ {
+ int result;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ port->read_urb->dev = port->serial->dev;
+
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+
+ if (result)
+- dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
++ dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
+
+ return;
+ }
+@@ -417,14 +414,14 @@ static int empeg_startup (struct usb_serial *serial)
+ {
+ int r;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
+ err("active config #%d != 1 ??",
+ serial->dev->actconfig->desc.bConfigurationValue);
+ return -ENODEV;
+ }
+- dbg("%s - reset config", __FUNCTION__);
++ dbg("%s - reset config", __func__);
+ r = usb_reset_configuration (serial->dev);
+
+ /* continue on with initialization */
+@@ -435,13 +432,13 @@ static int empeg_startup (struct usb_serial *serial)
+
+ static void empeg_shutdown (struct usb_serial *serial)
+ {
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+ }
+
+
+ static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+ {
+- dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
++ dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
+
+ return -ENOIOCTLCMD;
+ }
+@@ -450,7 +447,7 @@ static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsign
+ static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
+ {
+ struct ktermios *termios = port->tty->termios;
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /*
+ * The empeg-car player wants these particular tty settings.
+@@ -517,7 +514,7 @@ static int __init empeg_init (void)
+ urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+ if (!urb->transfer_buffer) {
+ err("%s - out of memory for urb buffers.",
+- __FUNCTION__);
++ __func__);
+ continue;
+ }
+ }
+diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c
+index 3f698ba..cc4fbd9 100644
+--- a/drivers/usb/serial/ezusb.c
++++ b/drivers/usb/serial/ezusb.c
+@@ -27,13 +27,13 @@ int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *da
+
+ /* dbg("ezusb_writememory %x, %d", address, length); */
+ if (!serial->dev) {
+- err("%s - no physical device present, failing.", __FUNCTION__);
++ err("%s - no physical device present, failing.", __func__);
+ return -ENODEV;
+ }
+
+ transfer_buffer = kmemdup(data, length, GFP_KERNEL);
+ if (!transfer_buffer) {
+- dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, length);
++ dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, length);
+ return -ENOMEM;
+ }
+ result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 3000);
+@@ -45,10 +45,10 @@ int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit)
+ {
+ int response;
+
+- /* dbg("%s - %d", __FUNCTION__, reset_bit); */
++ /* dbg("%s - %d", __func__, reset_bit); */
+ response = ezusb_writememory (serial, CPUCS_REG, &reset_bit, 1, 0xa0);
+ if (response < 0)
+- dev_err(&serial->dev->dev, "%s- %d failed\n", __FUNCTION__, reset_bit);
++ dev_err(&serial->dev->dev, "%s- %d failed\n", __func__, reset_bit);
+ return response;
+ }
+
+diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
+index 3abb3c8..23f51a4 100644
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -439,9 +439,6 @@ static struct usb_serial_driver ftdi_sio_device = {
+ .description = "FTDI USB Serial Device",
+ .usb_driver = &ftdi_driver ,
+ .id_table = id_table_combined,
+- .num_interrupt_in = 0,
+- .num_bulk_in = 1,
+- .num_bulk_out = 1,
+ .num_ports = 1,
+ .probe = ftdi_sio_probe,
+ .port_probe = ftdi_sio_port_probe,
+@@ -528,14 +525,13 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, unsigned
+ int rv;
+
+ if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) {
+- dbg("%s - DTR|RTS not being set|cleared", __FUNCTION__);
++ dbg("%s - DTR|RTS not being set|cleared", __func__);
+ return 0; /* no change */
+ }
+
+ buf = kmalloc(1, GFP_NOIO);
+- if (!buf) {
++ if (!buf)
+ return -ENOMEM;
+- }
+
+ clear &= ~set; /* 'set' takes precedence over 'clear' */
+ urb_value = 0;
+@@ -557,17 +553,18 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, unsigned
+ kfree(buf);
+ if (rv < 0) {
+ err("%s Error from MODEM_CTRL urb: DTR %s, RTS %s",
+- __FUNCTION__,
++ __func__,
+ (set & TIOCM_DTR) ? "HIGH" :
+ (clear & TIOCM_DTR) ? "LOW" : "unchanged",
+ (set & TIOCM_RTS) ? "HIGH" :
+ (clear & TIOCM_RTS) ? "LOW" : "unchanged");
+ } else {
+- dbg("%s - DTR %s, RTS %s", __FUNCTION__,
++ dbg("%s - DTR %s, RTS %s", __func__,
+ (set & TIOCM_DTR) ? "HIGH" :
+ (clear & TIOCM_DTR) ? "LOW" : "unchanged",
+ (set & TIOCM_RTS) ? "HIGH" :
+ (clear & TIOCM_RTS) ? "LOW" : "unchanged");
++ /* FIXME: locking on last_dtr_rts */
+ priv->last_dtr_rts = (priv->last_dtr_rts & ~clear) | set;
+ }
+ return rv;
+@@ -642,7 +639,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
+ /* 1. Get the baud rate from the tty settings, this observes alt_speed hack */
+
+ baud = tty_get_baud_rate(port->tty);
+- dbg("%s - tty_get_baud_rate reports speed %d", __FUNCTION__, baud);
++ dbg("%s - tty_get_baud_rate reports speed %d", __func__, baud);
+
+ /* 2. Observe async-compatible custom_divisor hack, update baudrate if needed */
+
+@@ -650,7 +647,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
+ ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
+ (priv->custom_divisor)) {
+ baud = priv->baud_base / priv->custom_divisor;
+- dbg("%s - custom divisor %d sets baud rate to %d", __FUNCTION__, priv->custom_divisor, baud);
++ dbg("%s - custom divisor %d sets baud rate to %d", __func__, priv->custom_divisor, baud);
+ }
+
+ /* 3. Convert baudrate to device-specific divisor */
+@@ -671,7 +668,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
+ case 115200: div_value = ftdi_sio_b115200; break;
+ } /* baud */
+ if (div_value == 0) {
+- dbg("%s - Baudrate (%d) requested is not supported", __FUNCTION__, baud);
++ dbg("%s - Baudrate (%d) requested is not supported", __func__, baud);
+ div_value = ftdi_sio_b9600;
+ baud = 9600;
+ div_okay = 0;
+@@ -681,7 +678,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
+ if (baud <= 3000000) {
+ div_value = ftdi_232am_baud_to_divisor(baud);
+ } else {
+- dbg("%s - Baud rate too high!", __FUNCTION__);
++ dbg("%s - Baud rate too high!", __func__);
+ baud = 9600;
+ div_value = ftdi_232am_baud_to_divisor(9600);
+ div_okay = 0;
+@@ -693,7 +690,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
+ if (baud <= 3000000) {
+ div_value = ftdi_232bm_baud_to_divisor(baud);
+ } else {
+- dbg("%s - Baud rate too high!", __FUNCTION__);
++ dbg("%s - Baud rate too high!", __func__);
+ div_value = ftdi_232bm_baud_to_divisor(9600);
+ div_okay = 0;
+ baud = 9600;
+@@ -703,7 +700,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
+
+ if (div_okay) {
+ dbg("%s - Baud rate set to %d (divisor 0x%lX) on chip %s",
+- __FUNCTION__, baud, (unsigned long)div_value,
++ __func__, baud, (unsigned long)div_value,
+ ftdi_chip_name[priv->chip_type]);
+ }
+
+@@ -804,7 +801,7 @@ static void ftdi_determine_type(struct usb_serial_port *port)
+
+ version = le16_to_cpu(udev->descriptor.bcdDevice);
+ interfaces = udev->actconfig->desc.bNumInterfaces;
+- dbg("%s: bcdDevice = 0x%x, bNumInterfaces = %u", __FUNCTION__,
++ dbg("%s: bcdDevice = 0x%x, bNumInterfaces = %u", __func__,
+ version, interfaces);
+ if (interfaces > 1) {
+ int inter;
+@@ -822,7 +819,7 @@ static void ftdi_determine_type(struct usb_serial_port *port)
+ * to 0x200 when iSerialNumber is 0. */
+ if (version < 0x500) {
+ dbg("%s: something fishy - bcdDevice too low for multi-interface device",
+- __FUNCTION__);
++ __func__);
+ }
+ } else if (version < 0x200) {
+ /* Old device. Assume its the original SIO. */
+@@ -860,7 +857,7 @@ static ssize_t show_latency_timer(struct device *dev, struct device_attribute *a
+ int rv = 0;
+
+
+- dbg("%s",__FUNCTION__);
++ dbg("%s",__func__);
+
+ rv = usb_control_msg(udev,
+ usb_rcvctrlpipe(udev, 0),
+@@ -887,7 +884,7 @@ static ssize_t store_latency_timer(struct device *dev, struct device_attribute *
+ int v = simple_strtoul(valbuf, NULL, 10);
+ int rv = 0;
+
+- dbg("%s: setting latency timer = %i", __FUNCTION__, v);
++ dbg("%s: setting latency timer = %i", __func__, v);
+
+ rv = usb_control_msg(udev,
+ usb_sndctrlpipe(udev, 0),
+@@ -916,7 +913,7 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att
+ int v = simple_strtoul(valbuf, NULL, 10);
+ int rv = 0;
+
+- dbg("%s: setting event char = %i", __FUNCTION__, v);
++ dbg("%s: setting event char = %i", __func__, v);
+
+ rv = usb_control_msg(udev,
+ usb_sndctrlpipe(udev, 0),
+@@ -941,7 +938,7 @@ static int create_sysfs_attrs(struct usb_serial_port *port)
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+ int retval = 0;
+
+- dbg("%s",__FUNCTION__);
++ dbg("%s",__func__);
+
+ /* XXX I've no idea if the original SIO supports the event_char
+ * sysfs parameter, so I'm playing it safe. */
+@@ -963,7 +960,7 @@ static void remove_sysfs_attrs(struct usb_serial_port *port)
+ {
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+
+- dbg("%s",__FUNCTION__);
++ dbg("%s",__func__);
+
+ /* XXX see create_sysfs_attrs */
+ if (priv->chip_type != SIO) {
+@@ -1005,11 +1002,11 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
+ struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial);
+
+
+- dbg("%s",__FUNCTION__);
++ dbg("%s",__func__);
+
+ priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL);
+ if (!priv){
+- err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct ftdi_private));
++ err("%s- kmalloc(%Zd) failed.", __func__, sizeof(struct ftdi_private));
+ return -ENOMEM;
+ }
+
+@@ -1058,7 +1055,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
+ /* Called from usbserial:serial_probe */
+ static void ftdi_USB_UIRT_setup (struct ftdi_private *priv)
+ {
+- dbg("%s",__FUNCTION__);
++ dbg("%s",__func__);
+
+ priv->flags |= ASYNC_SPD_CUST;
+ priv->custom_divisor = 77;
+@@ -1069,7 +1066,7 @@ static void ftdi_USB_UIRT_setup (struct ftdi_private *priv)
+ * baudrate (38400 gets mapped to 100000) and RTS-CTS enabled. */
+ static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv)
+ {
+- dbg("%s",__FUNCTION__);
++ dbg("%s",__func__);
+
+ priv->flags |= ASYNC_SPD_CUST;
+ priv->custom_divisor = 240;
+@@ -1087,7 +1084,7 @@ static int ftdi_jtag_probe(struct usb_serial *serial)
+ struct usb_device *udev = serial->dev;
+ struct usb_interface *interface = serial->interface;
+
+- dbg("%s",__FUNCTION__);
++ dbg("%s",__func__);
+
+ if (interface == udev->actconfig->interface[0]) {
+ info("Ignoring serial port reserved for JTAG");
+@@ -1123,14 +1120,14 @@ static int ftdi_mtxorb_hack_setup(struct usb_serial *serial)
+ */
+ static void ftdi_shutdown (struct usb_serial *serial)
+ {
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+ }
+
+ static int ftdi_sio_port_remove(struct usb_serial_port *port)
+ {
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ remove_sysfs_attrs(port);
+
+@@ -1155,7 +1152,7 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp)
+ int result = 0;
+ char buf[1]; /* Needed for the usb_control_msg I think */
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ spin_lock_irqsave(&priv->tx_lock, flags);
+ priv->tx_bytes = 0;
+@@ -1200,7 +1197,7 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp)
+ ftdi_read_bulk_callback, port);
+ result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ if (result)
+- err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
++ err("%s - failed submitting read urb, error %d", __func__, result);
+
+
+ return result;
+@@ -1222,7 +1219,7 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp)
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+ char buf[1];
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ mutex_lock(&port->serial->disc_mutex);
+ if (c_cflag & HUPCL && !port->serial->disconnected){
+@@ -1269,7 +1266,7 @@ static int ftdi_write (struct usb_serial_port *port,
+ int transfer_size;
+ unsigned long flags;
+
+- dbg("%s port %d, %d bytes", __FUNCTION__, port->number, count);
++ dbg("%s port %d, %d bytes", __func__, port->number, count);
+
+ if (count == 0) {
+ dbg("write request of 0 bytes");
+@@ -1278,7 +1275,7 @@ static int ftdi_write (struct usb_serial_port *port,
+ spin_lock_irqsave(&priv->tx_lock, flags);
+ if (priv->tx_outstanding_urbs > URB_UPPER_LIMIT) {
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
+- dbg("%s - write limit hit\n", __FUNCTION__);
++ dbg("%s - write limit hit\n", __func__);
+ return 0;
+ }
+ priv->tx_outstanding_urbs++;
+@@ -1298,14 +1295,14 @@ static int ftdi_write (struct usb_serial_port *port,
+
+ buffer = kmalloc (transfer_size, GFP_ATOMIC);
+ if (!buffer) {
+- err("%s ran out of kernel memory for urb ...", __FUNCTION__);
++ err("%s ran out of kernel memory for urb ...", __func__);
+ count = -ENOMEM;
+ goto error_no_buffer;
+ }
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb) {
+- err("%s - no more free urbs", __FUNCTION__);
++ err("%s - no more free urbs", __func__);
+ count = -ENOMEM;
+ goto error_no_urb;
+ }
+@@ -1337,7 +1334,7 @@ static int ftdi_write (struct usb_serial_port *port,
+ memcpy (buffer, buf, count);
+ }
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, transfer_size, buffer);
++ usb_serial_debug_data(debug, &port->dev, __func__, transfer_size, buffer);
+
+ /* fill the buffer and send it */
+ usb_fill_bulk_urb(urb, port->serial->dev,
+@@ -1347,7 +1344,7 @@ static int ftdi_write (struct usb_serial_port *port,
+
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (status) {
+- err("%s - failed submitting write urb, error %d", __FUNCTION__, status);
++ err("%s - failed submitting write urb, error %d", __func__, status);
+ count = status;
+ goto error;
+ } else {
+@@ -1361,7 +1358,7 @@ static int ftdi_write (struct usb_serial_port *port,
+ * really free it when it is finished with it */
+ usb_free_urb(urb);
+
+- dbg("%s write returning: %d", __FUNCTION__, count);
++ dbg("%s write returning: %d", __func__, count);
+ return count;
+ error:
+ usb_free_urb(urb);
+@@ -1380,7 +1377,7 @@ error_no_buffer:
+ static void ftdi_write_bulk_callback (struct urb *urb)
+ {
+ unsigned long flags;
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct ftdi_private *priv;
+ int data_offset; /* will be 1 for the SIO and 0 otherwise */
+ unsigned long countback;
+@@ -1389,7 +1386,7 @@ static void ftdi_write_bulk_callback (struct urb *urb)
+ /* free up the transfer buffer, as usb_free_urb() does not do this */
+ kfree (urb->transfer_buffer);
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (status) {
+ dbg("nonzero write bulk status received: %d", status);
+@@ -1398,7 +1395,7 @@ static void ftdi_write_bulk_callback (struct urb *urb)
+
+ priv = usb_get_serial_port_data(port);
+ if (!priv) {
+- dbg("%s - bad port private data pointer - exiting", __FUNCTION__);
++ dbg("%s - bad port private data pointer - exiting", __func__);
+ return;
+ }
+ /* account for transferred data */
+@@ -1406,7 +1403,7 @@ static void ftdi_write_bulk_callback (struct urb *urb)
+ data_offset = priv->write_offset;
+ if (data_offset > 0) {
+ /* Subtract the control bytes */
+- countback -= (data_offset * ((countback + (PKTSZ - 1)) / PKTSZ));
++ countback -= (data_offset * DIV_ROUND_UP(countback, PKTSZ));
+ }
+ spin_lock_irqsave(&priv->tx_lock, flags);
+ --priv->tx_outstanding_urbs;
+@@ -1423,7 +1420,7 @@ static int ftdi_write_room( struct usb_serial_port *port )
+ int room;
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&priv->tx_lock, flags);
+ if (priv->tx_outstanding_urbs < URB_UPPER_LIMIT) {
+@@ -1447,13 +1444,13 @@ static int ftdi_chars_in_buffer (struct usb_serial_port *port)
+ int buffered;
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&priv->tx_lock, flags);
+ buffered = (int)priv->tx_outstanding_bytes;
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
+ if (buffered < 0) {
+- err("%s outstanding tx bytes is negative!", __FUNCTION__);
++ err("%s outstanding tx bytes is negative!", __func__);
+ buffered = 0;
+ }
+ return buffered;
+@@ -1463,7 +1460,7 @@ static int ftdi_chars_in_buffer (struct usb_serial_port *port)
+
+ static void ftdi_read_bulk_callback (struct urb *urb)
+ { /* ftdi_read_bulk_callback */
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct tty_struct *tty;
+ struct ftdi_private *priv;
+ unsigned long countread;
+@@ -1471,30 +1468,30 @@ static void ftdi_read_bulk_callback (struct urb *urb)
+ int status = urb->status;
+
+ if (urb->number_of_packets > 0) {
+- err("%s transfer_buffer_length %d actual_length %d number of packets %d",__FUNCTION__,
++ err("%s transfer_buffer_length %d actual_length %d number of packets %d",__func__,
+ urb->transfer_buffer_length, urb->actual_length, urb->number_of_packets );
+- err("%s transfer_flags %x ", __FUNCTION__,urb->transfer_flags );
++ err("%s transfer_flags %x ", __func__,urb->transfer_flags );
+ }
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (port->open_count <= 0)
+ return;
+
+ tty = port->tty;
+ if (!tty) {
+- dbg("%s - bad tty pointer - exiting",__FUNCTION__);
++ dbg("%s - bad tty pointer - exiting",__func__);
+ return;
+ }
+
+ priv = usb_get_serial_port_data(port);
+ if (!priv) {
+- dbg("%s - bad port private data pointer - exiting", __FUNCTION__);
++ dbg("%s - bad port private data pointer - exiting", __func__);
+ return;
+ }
+
+ if (urb != port->read_urb) {
+- err("%s - Not my urb!", __FUNCTION__);
++ err("%s - Not my urb!", __func__);
+ }
+
+ if (status) {
+@@ -1506,7 +1503,7 @@ static void ftdi_read_bulk_callback (struct urb *urb)
+
+ /* count data bytes, but not status bytes */
+ countread = urb->actual_length;
+- countread -= 2 * ((countread + (PKTSZ - 1)) / PKTSZ);
++ countread -= 2 * DIV_ROUND_UP(countread, PKTSZ);
+ spin_lock_irqsave(&priv->rx_lock, flags);
+ priv->rx_bytes += countread;
+ spin_unlock_irqrestore(&priv->rx_lock, flags);
+@@ -1532,39 +1529,39 @@ static void ftdi_process_read (struct work_struct *work)
+ int packet_offset;
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (port->open_count <= 0)
+ return;
+
+ tty = port->tty;
+ if (!tty) {
+- dbg("%s - bad tty pointer - exiting",__FUNCTION__);
++ dbg("%s - bad tty pointer - exiting",__func__);
+ return;
+ }
+
+ priv = usb_get_serial_port_data(port);
+ if (!priv) {
+- dbg("%s - bad port private data pointer - exiting", __FUNCTION__);
++ dbg("%s - bad port private data pointer - exiting", __func__);
+ return;
+ }
+
+ urb = port->read_urb;
+ if (!urb) {
+- dbg("%s - bad read_urb pointer - exiting", __FUNCTION__);
++ dbg("%s - bad read_urb pointer - exiting", __func__);
+ return;
+ }
+
+ data = urb->transfer_buffer;
+
+ if (priv->rx_processed) {
+- dbg("%s - already processed: %d bytes, %d remain", __FUNCTION__,
++ dbg("%s - already processed: %d bytes, %d remain", __func__,
+ priv->rx_processed,
+ urb->actual_length - priv->rx_processed);
+ } else {
+ /* The first two bytes of every read packet are status */
+ if (urb->actual_length > 2) {
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++ usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ } else {
+ dbg("Status only: %03oo %03oo",data[0],data[1]);
+ }
+@@ -1594,17 +1591,17 @@ static void ftdi_process_read (struct work_struct *work)
+
+ length = min(PKTSZ, urb->actual_length-packet_offset)-2;
+ if (length < 0) {
+- err("%s - bad packet length: %d", __FUNCTION__, length+2);
++ err("%s - bad packet length: %d", __func__, length+2);
+ length = 0;
+ }
+
+ if (priv->rx_flags & THROTTLED) {
+- dbg("%s - throttled", __FUNCTION__);
++ dbg("%s - throttled", __func__);
+ break;
+ }
+ if (tty_buffer_request_room(tty, length) < length) {
+ /* break out & wait for throttling/unthrottling to happen */
+- dbg("%s - receive room low", __FUNCTION__);
++ dbg("%s - receive room low", __func__);
+ break;
+ }
+
+@@ -1672,7 +1669,7 @@ static void ftdi_process_read (struct work_struct *work)
+ /* not completely processed - record progress */
+ priv->rx_processed = packet_offset;
+ dbg("%s - incomplete, %d bytes processed, %d remain",
+- __FUNCTION__, packet_offset,
++ __func__, packet_offset,
+ urb->actual_length - packet_offset);
+ /* check if we were throttled while processing */
+ spin_lock_irqsave(&priv->rx_lock, flags);
+@@ -1680,7 +1677,7 @@ static void ftdi_process_read (struct work_struct *work)
+ priv->rx_flags |= ACTUALLY_THROTTLED;
+ spin_unlock_irqrestore(&priv->rx_lock, flags);
+ dbg("%s - deferring remainder until unthrottled",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+ spin_unlock_irqrestore(&priv->rx_lock, flags);
+@@ -1689,7 +1686,7 @@ static void ftdi_process_read (struct work_struct *work)
+ /* delay processing of remainder */
+ schedule_delayed_work(&priv->rx_work, 1);
+ } else {
+- dbg("%s - port is closed", __FUNCTION__);
++ dbg("%s - port is closed", __func__);
+ }
+ return;
+ }
+@@ -1707,7 +1704,7 @@ static void ftdi_process_read (struct work_struct *work)
+
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ if (result)
+- err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
++ err("%s - failed resubmitting read urb, error %d", __func__, result);
+ }
+
+ return;
+@@ -1736,10 +1733,10 @@ static void ftdi_break_ctl( struct usb_serial_port *port, int break_state )
+ FTDI_SIO_SET_DATA_REQUEST_TYPE,
+ urb_value , priv->interface,
+ buf, 0, WDR_TIMEOUT) < 0) {
+- err("%s FAILED to enable/disable break state (state was %d)", __FUNCTION__,break_state);
++ err("%s FAILED to enable/disable break state (state was %d)", __func__,break_state);
+ }
+
+- dbg("%s break state is %d - urb is %d", __FUNCTION__,break_state, urb_value);
++ dbg("%s break state is %d - urb is %d", __func__,break_state, urb_value);
+
+ }
+
+@@ -1763,18 +1760,18 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
+ unsigned char vstop;
+ unsigned char vstart;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ /* Force baud rate if this device requires it, unless it is set to B0. */
+ if (priv->force_baud && ((termios->c_cflag & CBAUD) != B0)) {
+- dbg("%s: forcing baud rate for this device", __FUNCTION__);
++ dbg("%s: forcing baud rate for this device", __func__);
+ tty_encode_baud_rate(port->tty, priv->force_baud,
+ priv->force_baud);
+ }
+
+ /* Force RTS-CTS if this device requires it. */
+ if (priv->force_rtscts) {
+- dbg("%s: forcing rtscts for this device", __FUNCTION__);
++ dbg("%s: forcing rtscts for this device", __func__);
+ termios->c_cflag |= CRTSCTS;
+ }
+
+@@ -1818,7 +1815,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
+ FTDI_SIO_SET_DATA_REQUEST_TYPE,
+ urb_value , priv->interface,
+ buf, 0, WDR_SHORT_TIMEOUT) < 0) {
+- err("%s FAILED to set databits/stopbits/parity", __FUNCTION__);
++ err("%s FAILED to set databits/stopbits/parity", __func__);
+ }
+
+ /* Now do the baudrate */
+@@ -1829,14 +1826,14 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
+ FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
+ 0, priv->interface,
+ buf, 0, WDR_TIMEOUT) < 0) {
+- err("%s error from disable flowcontrol urb", __FUNCTION__);
++ err("%s error from disable flowcontrol urb", __func__);
+ }
+ /* Drop RTS and DTR */
+ clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+ } else {
+ /* set the baudrate determined before */
+ if (change_speed(port)) {
+- err("%s urb failed to set baudrate", __FUNCTION__);
++ err("%s urb failed to set baudrate", __func__);
+ }
+ /* Ensure RTS and DTR are raised when baudrate changed from 0 */
+ if (!old_termios || (old_termios->c_cflag & CBAUD) == B0) {
+@@ -1847,7 +1844,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
+ /* Set flow control */
+ /* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */
+ if (cflag & CRTSCTS) {
+- dbg("%s Setting to CRTSCTS flow control", __FUNCTION__);
++ dbg("%s Setting to CRTSCTS flow control", __func__);
+ if (usb_control_msg(dev,
+ usb_sndctrlpipe(dev, 0),
+ FTDI_SIO_SET_FLOW_CTRL_REQUEST,
+@@ -1865,7 +1862,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
+ * if IXOFF is not set, the pre-xon/xoff code is executed.
+ */
+ if (iflag & IXOFF) {
+- dbg("%s request to enable xonxoff iflag=%04x",__FUNCTION__,iflag);
++ dbg("%s request to enable xonxoff iflag=%04x",__func__,iflag);
+ // Try to enable the XON/XOFF on the ftdi_sio
+ // Set the vstart and vstop -- could have been done up above where
+ // a lot of other dereferencing is done but that would be very
+@@ -1886,7 +1883,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
+ } else {
+ /* else clause to only run if cfag ! CRTSCTS and iflag ! XOFF */
+ /* CHECKME Assuming XON/XOFF handled by tty stack - not by device */
+- dbg("%s Turning off hardware flow control", __FUNCTION__);
++ dbg("%s Turning off hardware flow control", __func__);
+ if (usb_control_msg(dev,
+ usb_sndctrlpipe(dev, 0),
+ FTDI_SIO_SET_FLOW_CTRL_REQUEST,
+@@ -1908,7 +1905,7 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file)
+ unsigned char buf[2];
+ int ret;
+
+- dbg("%s TIOCMGET", __FUNCTION__);
++ dbg("%s TIOCMGET", __func__);
+ switch (priv->chip_type) {
+ case SIO:
+ /* Request the status from the device */
+@@ -1918,7 +1915,7 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file)
+ FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+ 0, 0,
+ buf, 1, WDR_TIMEOUT)) < 0 ) {
+- err("%s Could not get modem status of device - err: %d", __FUNCTION__,
++ err("%s Could not get modem status of device - err: %d", __func__,
+ ret);
+ return(ret);
+ }
+@@ -1935,7 +1932,7 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file)
+ FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+ 0, priv->interface,
+ buf, 2, WDR_TIMEOUT)) < 0 ) {
+- err("%s Could not get modem status of device - err: %d", __FUNCTION__,
++ err("%s Could not get modem status of device - err: %d", __func__,
+ ret);
+ return(ret);
+ }
+@@ -1954,7 +1951,7 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file)
+
+ static int ftdi_tiocmset(struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear)
+ {
+- dbg("%s TIOCMSET", __FUNCTION__);
++ dbg("%s TIOCMSET", __func__);
+ return update_mctrl(port, set, clear);
+ }
+
+@@ -1963,7 +1960,7 @@ static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigne
+ {
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+
+- dbg("%s cmd 0x%04x", __FUNCTION__, cmd);
++ dbg("%s cmd 0x%04x", __func__, cmd);
+
+ /* Based on code from acm.c and others */
+ switch (cmd) {
+@@ -2022,7 +2019,7 @@ static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigne
+ /* This is not necessarily an error - turns out the higher layers will do
+ * some ioctls itself (see comment above)
+ */
+- dbg("%s arg not supported - it was 0x%04x - check /usr/include/asm/ioctls.h", __FUNCTION__, cmd);
++ dbg("%s arg not supported - it was 0x%04x - check /usr/include/asm/ioctls.h", __func__, cmd);
+
+ return(-ENOIOCTLCMD);
+ } /* ftdi_ioctl */
+@@ -2033,7 +2030,7 @@ static void ftdi_throttle (struct usb_serial_port *port)
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&priv->rx_lock, flags);
+ priv->rx_flags |= THROTTLED;
+@@ -2047,7 +2044,7 @@ static void ftdi_unthrottle (struct usb_serial_port *port)
+ int actually_throttled;
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&priv->rx_lock, flags);
+ actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
+@@ -2062,7 +2059,7 @@ static int __init ftdi_init (void)
+ {
+ int retval;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+ if (vendor > 0 && product > 0) {
+ /* Add user specified VID/PID to reserved element of table. */
+ int i;
+@@ -2091,7 +2088,7 @@ failed_sio_register:
+ static void __exit ftdi_exit (void)
+ {
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ usb_deregister (&ftdi_driver);
+ usb_serial_deregister (&ftdi_sio_device);
+diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c
+index b5194dc..e8ba2cb 100644
+--- a/drivers/usb/serial/funsoft.c
++++ b/drivers/usb/serial/funsoft.c
+@@ -39,9 +39,6 @@ static struct usb_serial_driver funsoft_device = {
+ },
+ .id_table = id_table,
+ .usb_driver = &funsoft_driver,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_bulk_in = NUM_DONT_CARE,
+- .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 1,
+ };
+
+diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
+index d74e43d..8ce5a56 100644
+--- a/drivers/usb/serial/garmin_gps.c
++++ b/drivers/usb/serial/garmin_gps.c
+@@ -280,7 +280,7 @@ static void send_to_tty(struct usb_serial_port *port,
+ if (tty && actual_length) {
+
+ usb_serial_debug_data(debug, &port->dev,
+- __FUNCTION__, actual_length, data);
++ __func__, actual_length, data);
+
+ tty_buffer_request_room(tty, actual_length);
+ tty_insert_flip_string(tty, data, actual_length);
+@@ -355,7 +355,7 @@ static void pkt_clear(struct garmin_data * garmin_data_p)
+ unsigned long flags;
+ struct garmin_packet *result = NULL;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ spin_lock_irqsave(&garmin_data_p->lock, flags);
+ while (!list_empty(&garmin_data_p->pktlist)) {
+@@ -379,7 +379,7 @@ static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id)
+ __u8 *ptr = pkt;
+ unsigned l = 0;
+
+- dbg("%s - pkt-id: 0x%X.", __FUNCTION__, 0xFF & pkt_id);
++ dbg("%s - pkt-id: 0x%X.", __func__, 0xFF & pkt_id);
+
+ *ptr++ = DLE;
+ *ptr++ = ACK;
+@@ -429,11 +429,11 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
+ int size = recpkt[1];
+
+ usb_serial_debug_data(debug, &garmin_data_p->port->dev,
+- __FUNCTION__, count-GSP_INITIAL_OFFSET, recpkt);
++ __func__, count-GSP_INITIAL_OFFSET, recpkt);
+
+ if (size != (count-GSP_INITIAL_OFFSET-3)) {
+ dbg("%s - invalid size, expected %d bytes, got %d",
+- __FUNCTION__, size, (count-GSP_INITIAL_OFFSET-3));
++ __func__, size, (count-GSP_INITIAL_OFFSET-3));
+ return -EINVPKT;
+ }
+
+@@ -443,7 +443,7 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
+ // sanity check, remove after test ...
+ if ((__u8*)&(usbdata[3]) != recpkt) {
+ dbg("%s - ptr mismatch %p - %p",
+- __FUNCTION__, &(usbdata[4]), recpkt);
++ __func__, &(usbdata[4]), recpkt);
+ return -EINVPKT;
+ }
+
+@@ -454,7 +454,7 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
+
+ if ((0xff & (cksum + *recpkt)) != 0) {
+ dbg("%s - invalid checksum, expected %02x, got %02x",
+- __FUNCTION__, 0xff & -cksum, 0xff & *recpkt);
++ __func__, 0xff & -cksum, 0xff & *recpkt);
+ return -EINVPKT;
+ }
+
+@@ -519,7 +519,7 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
+ spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+
+ dbg("%s - dle=%d skip=%d size=%d count=%d",
+- __FUNCTION__, dleSeen, skip, size, count);
++ __func__, dleSeen, skip, size, count);
+
+ if (size == 0) {
+ size = GSP_INITIAL_OFFSET;
+@@ -578,7 +578,7 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
+ }
+
+ if (size >= GPS_IN_BUFSIZ) {
+- dbg("%s - packet too large.", __FUNCTION__);
++ dbg("%s - packet too large.", __func__);
+ skip = 1;
+ size = GSP_INITIAL_OFFSET;
+ dleSeen = 0;
+@@ -634,7 +634,7 @@ static int gsp_send(struct garmin_data * garmin_data_p,
+ int i=0;
+ int k;
+
+- dbg("%s - state %d - %d bytes.", __FUNCTION__,
++ dbg("%s - state %d - %d bytes.", __func__,
+ garmin_data_p->state, count);
+
+ k = garmin_data_p->outsize;
+@@ -658,13 +658,13 @@ static int gsp_send(struct garmin_data * garmin_data_p,
+ return 0;
+ }
+
+- dbg("%s - %d bytes in buffer, %d bytes in pkt.", __FUNCTION__,
++ dbg("%s - %d bytes in buffer, %d bytes in pkt.", __func__,
+ k, i);
+
+ /* garmin_data_p->outbuffer now contains a complete packet */
+
+ usb_serial_debug_data(debug, &garmin_data_p->port->dev,
+- __FUNCTION__, k, garmin_data_p->outbuffer);
++ __func__, k, garmin_data_p->outbuffer);
+
+ garmin_data_p->outsize = 0;
+
+@@ -749,7 +749,7 @@ static void gsp_next_packet(struct garmin_data * garmin_data_p)
+ struct garmin_packet *pkt = NULL;
+
+ while ((pkt = pkt_pop(garmin_data_p)) != NULL) {
+- dbg("%s - next pkt: %d", __FUNCTION__, pkt->seq);
++ dbg("%s - next pkt: %d", __func__, pkt->seq);
+ if (gsp_send(garmin_data_p, pkt->data, pkt->size) > 0) {
+ kfree(pkt);
+ return;
+@@ -794,7 +794,7 @@ static int nat_receive(struct garmin_data * garmin_data_p,
+ if (len >= GPS_IN_BUFSIZ) {
+ /* seem to be an invalid packet, ignore rest of input */
+ dbg("%s - packet size too large: %d",
+- __FUNCTION__, len);
++ __func__, len);
+ garmin_data_p->insize = 0;
+ count = 0;
+ result = -EINVPKT;
+@@ -873,11 +873,11 @@ static int process_resetdev_request(struct usb_serial_port *port)
+ spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+
+ usb_kill_urb (port->interrupt_in_urb);
+- dbg("%s - usb_reset_device", __FUNCTION__ );
++ dbg("%s - usb_reset_device", __func__ );
+ status = usb_reset_device(port->serial->dev);
+ if (status)
+ dbg("%s - usb_reset_device failed: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return status;
+ }
+
+@@ -926,18 +926,18 @@ static int garmin_init_session(struct usb_serial_port *port)
+ if (status == 0) {
+ usb_kill_urb (port->interrupt_in_urb);
+
+- dbg("%s - adding interrupt input", __FUNCTION__);
++ dbg("%s - adding interrupt input", __func__);
+ port->interrupt_in_urb->dev = serial->dev;
+ status = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ if (status)
+ dev_err(&serial->dev->dev,
+ "%s - failed submitting interrupt urb,"
+ " error %d\n",
+- __FUNCTION__, status);
++ __func__, status);
+ }
+
+ if (status == 0) {
+- dbg("%s - starting session ...", __FUNCTION__);
++ dbg("%s - starting session ...", __func__);
+ garmin_data_p->state = STATE_ACTIVE;
+ status = garmin_write_bulk(port, GARMIN_START_SESSION_REQ,
+ sizeof(GARMIN_START_SESSION_REQ),
+@@ -976,7 +976,7 @@ static int garmin_open (struct usb_serial_port *port, struct file *filp)
+ int status = 0;
+ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /*
+ * Force low_latency on so that our tty_push actually forces the data
+@@ -1013,7 +1013,7 @@ static void garmin_close (struct usb_serial_port *port, struct file * filp)
+ struct usb_serial *serial = port->serial;
+ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+
+- dbg("%s - port %d - mode=%d state=%d flags=0x%X", __FUNCTION__,
++ dbg("%s - port %d - mode=%d state=%d flags=0x%X", __func__,
+ port->number, garmin_data_p->mode,
+ garmin_data_p->state, garmin_data_p->flags);
+
+@@ -1046,13 +1046,13 @@ static void garmin_close (struct usb_serial_port *port, struct file * filp)
+ static void garmin_write_bulk_callback (struct urb *urb)
+ {
+ unsigned long flags;
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ int status = urb->status;
+
+ if (port) {
+ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (GARMIN_LAYERID_APPL == getLayerId(urb->transfer_buffer)
+ && (garmin_data_p->mode == MODE_GARMIN_SERIAL)) {
+@@ -1061,7 +1061,7 @@ static void garmin_write_bulk_callback (struct urb *urb)
+
+ if (status) {
+ dbg("%s - nonzero write bulk status received: %d",
+- __FUNCTION__, urb->status);
++ __func__, urb->status);
+ spin_lock_irqsave(&garmin_data_p->lock, flags);
+ garmin_data_p->flags |= CLEAR_HALT_REQUIRED;
+ spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+@@ -1088,7 +1088,7 @@ static int garmin_write_bulk (struct usb_serial_port *port,
+ unsigned char *buffer;
+ int status;
+
+- dbg("%s - port %d, state %d", __FUNCTION__, port->number,
++ dbg("%s - port %d, state %d", __func__, port->number,
+ garmin_data_p->state);
+
+ spin_lock_irqsave(&garmin_data_p->lock, flags);
+@@ -1110,7 +1110,7 @@ static int garmin_write_bulk (struct usb_serial_port *port,
+
+ memcpy (buffer, buf, count);
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
++ usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
+
+ usb_fill_bulk_urb (urb, serial->dev,
+ usb_sndbulkpipe (serial->dev,
+@@ -1134,7 +1134,7 @@ static int garmin_write_bulk (struct usb_serial_port *port,
+ dev_err(&port->dev,
+ "%s - usb_submit_urb(write bulk) "
+ "failed with status = %d\n",
+- __FUNCTION__, status);
++ __func__, status);
+ count = status;
+ }
+
+@@ -1154,7 +1154,7 @@ static int garmin_write (struct usb_serial_port *port,
+ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ __le32 *privpkt = (__le32 *)garmin_data_p->privpkt;
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buf);
++ usb_serial_debug_data(debug, &port->dev, __func__, count, buf);
+
+ /* check for our private packets */
+ if (count >= GARMIN_PKTHDR_LENGTH) {
+@@ -1172,7 +1172,7 @@ static int garmin_write (struct usb_serial_port *port,
+ && GARMIN_LAYERID_PRIVATE == getLayerId(garmin_data_p->privpkt)) {
+
+ dbg("%s - processing private request %d",
+- __FUNCTION__, pktid);
++ __func__, pktid);
+
+ // drop all unfinished transfers
+ garmin_clear(garmin_data_p);
+@@ -1184,7 +1184,7 @@ static int garmin_write (struct usb_serial_port *port,
+ return -EINVPKT;
+ debug = __le32_to_cpu(privpkt[3]);
+ dbg("%s - debug level set to 0x%X",
+- __FUNCTION__, debug);
++ __func__, debug);
+ break;
+
+ case PRIV_PKTID_SET_MODE:
+@@ -1192,7 +1192,7 @@ static int garmin_write (struct usb_serial_port *port,
+ return -EINVPKT;
+ garmin_data_p->mode = __le32_to_cpu(privpkt[3]);
+ dbg("%s - mode set to %d",
+- __FUNCTION__, garmin_data_p->mode);
++ __func__, garmin_data_p->mode);
+ break;
+
+ case PRIV_PKTID_INFO_REQ:
+@@ -1208,7 +1208,7 @@ static int garmin_write (struct usb_serial_port *port,
+ return -EINVPKT;
+ initial_mode = __le32_to_cpu(privpkt[3]);
+ dbg("%s - initial_mode set to %d",
+- __FUNCTION__,
++ __func__,
+ garmin_data_p->mode);
+ break;
+ }
+@@ -1255,7 +1255,7 @@ static void garmin_read_process(struct garmin_data * garmin_data_p,
+ {
+ if (garmin_data_p->flags & FLAGS_DROP_DATA) {
+ /* abort-transfer cmd is actice */
+- dbg("%s - pkt dropped", __FUNCTION__);
++ dbg("%s - pkt dropped", __func__);
+ } else if (garmin_data_p->state != STATE_DISCONNECTED &&
+ garmin_data_p->state != STATE_RESET ) {
+
+@@ -1286,28 +1286,28 @@ static void garmin_read_process(struct garmin_data * garmin_data_p,
+ static void garmin_read_bulk_callback (struct urb *urb)
+ {
+ unsigned long flags;
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct usb_serial *serial = port->serial;
+ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ unsigned char *data = urb->transfer_buffer;
+ int status = urb->status;
+ int retval;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (!serial) {
+- dbg("%s - bad serial pointer, exiting", __FUNCTION__);
++ dbg("%s - bad serial pointer, exiting", __func__);
+ return;
+ }
+
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
+
+ usb_serial_debug_data(debug, &port->dev,
+- __FUNCTION__, urb->actual_length, data);
++ __func__, urb->actual_length, data);
+
+ garmin_read_process(garmin_data_p, data, urb->actual_length);
+
+@@ -1320,7 +1320,7 @@ static void garmin_read_bulk_callback (struct urb *urb)
+ if (retval)
+ dev_err(&port->dev,
+ "%s - failed resubmitting read urb, error %d\n",
+- __FUNCTION__, retval);
++ __func__, retval);
+ } else if (urb->actual_length > 0) {
+ /* Continue trying to read until nothing more is received */
+ if (0 == (garmin_data_p->flags & FLAGS_THROTTLED)) {
+@@ -1328,10 +1328,10 @@ static void garmin_read_bulk_callback (struct urb *urb)
+ if (retval)
+ dev_err(&port->dev,
+ "%s - failed resubmitting read urb, "
+- "error %d\n", __FUNCTION__, retval);
++ "error %d\n", __func__, retval);
+ }
+ } else {
+- dbg("%s - end of bulk data", __FUNCTION__);
++ dbg("%s - end of bulk data", __func__);
+ spin_lock_irqsave(&garmin_data_p->lock, flags);
+ garmin_data_p->flags &= ~FLAGS_BULK_IN_ACTIVE;
+ spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+@@ -1344,7 +1344,7 @@ static void garmin_read_int_callback (struct urb *urb)
+ {
+ unsigned long flags;
+ int retval;
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct usb_serial *serial = port->serial;
+ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ unsigned char *data = urb->transfer_buffer;
+@@ -1359,22 +1359,22 @@ static void garmin_read_int_callback (struct urb *urb)
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
++ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, urb->transfer_buffer);
+
+ if (urb->actual_length == sizeof(GARMIN_BULK_IN_AVAIL_REPLY) &&
+ 0 == memcmp(data, GARMIN_BULK_IN_AVAIL_REPLY,
+ sizeof(GARMIN_BULK_IN_AVAIL_REPLY))) {
+
+- dbg("%s - bulk data available.", __FUNCTION__);
++ dbg("%s - bulk data available.", __func__);
+
+ if (0 == (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) {
+
+@@ -1389,7 +1389,7 @@ static void garmin_read_int_callback (struct urb *urb)
+ if (retval) {
+ dev_err(&port->dev,
+ "%s - failed submitting read urb, error %d\n",
+- __FUNCTION__, retval);
++ __func__, retval);
+ } else {
+ spin_lock_irqsave(&garmin_data_p->lock, flags);
+ garmin_data_p->flags |= FLAGS_BULK_IN_ACTIVE;
+@@ -1417,14 +1417,14 @@ static void garmin_read_int_callback (struct urb *urb)
+ = __le32_to_cpup((__le32*)(data+GARMIN_PKTHDR_LENGTH));
+
+ dbg("%s - start-of-session reply seen - serial %u.",
+- __FUNCTION__, garmin_data_p->serial_num);
++ __func__, garmin_data_p->serial_num);
+ }
+
+ if (garmin_data_p->ignorePkts) {
+ /* this reply belongs to a request generated by the driver,
+ ignore it. */
+ dbg("%s - pkt ignored (%d)",
+- __FUNCTION__, garmin_data_p->ignorePkts);
++ __func__, garmin_data_p->ignorePkts);
+ spin_lock_irqsave(&garmin_data_p->lock, flags);
+ garmin_data_p->ignorePkts--;
+ spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+@@ -1437,7 +1437,7 @@ static void garmin_read_int_callback (struct urb *urb)
+ if (retval)
+ dev_err(&urb->dev->dev,
+ "%s - Error %d submitting interrupt urb\n",
+- __FUNCTION__, retval);
++ __func__, retval);
+ }
+
+
+@@ -1473,7 +1473,7 @@ static void garmin_throttle (struct usb_serial_port *port)
+ unsigned long flags;
+ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+ /* set flag, data received will be put into a queue
+ for later processing */
+ spin_lock_irqsave(&garmin_data_p->lock, flags);
+@@ -1488,7 +1488,7 @@ static void garmin_unthrottle (struct usb_serial_port *port)
+ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ int status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+ spin_lock_irqsave(&garmin_data_p->lock, flags);
+ garmin_data_p->flags &= ~FLAGS_THROTTLED;
+ spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+@@ -1503,7 +1503,7 @@ static void garmin_unthrottle (struct usb_serial_port *port)
+ if (status)
+ dev_err(&port->dev,
+ "%s - failed resubmitting read urb, error %d\n",
+- __FUNCTION__, status);
++ __func__, status);
+ }
+ }
+
+@@ -1532,11 +1532,11 @@ static int garmin_attach (struct usb_serial *serial)
+ struct usb_serial_port *port = serial->port[0];
+ struct garmin_data * garmin_data_p = NULL;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL);
+ if (garmin_data_p == NULL) {
+- dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__);
++ dev_err(&port->dev, "%s - Out of memory\n", __func__);
+ return -ENOMEM;
+ }
+ init_timer(&garmin_data_p->timer);
+@@ -1561,7 +1561,7 @@ static void garmin_shutdown (struct usb_serial *serial)
+ struct usb_serial_port *port = serial->port[0];
+ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ usb_kill_urb (port->interrupt_in_urb);
+ del_timer_sync(&garmin_data_p->timer);
+@@ -1579,9 +1579,6 @@ static struct usb_serial_driver garmin_device = {
+ .description = "Garmin GPS usb/tty",
+ .usb_driver = &garmin_driver,
+ .id_table = id_table,
+- .num_interrupt_in = 1,
+- .num_bulk_in = 1,
+- .num_bulk_out = 1,
+ .num_ports = 1,
+ .open = garmin_open,
+ .close = garmin_close,
+diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
+index 7cfce9d..537f12a 100644
+--- a/drivers/usb/serial/generic.c
++++ b/drivers/usb/serial/generic.c
+@@ -62,9 +62,6 @@ struct usb_serial_driver usb_serial_generic_device = {
+ },
+ .id_table = generic_device_ids,
+ .usb_driver = &generic_driver,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_bulk_in = NUM_DONT_CARE,
+- .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 1,
+ .shutdown = usb_serial_generic_shutdown,
+ .throttle = usb_serial_generic_throttle,
+@@ -121,7 +118,7 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
+ int result = 0;
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /* force low_latency on so that our tty_push actually forces the data through,
+ otherwise it is scheduled, and with high data rates (like with OHCI) data
+@@ -148,7 +145,7 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
+ port);
+ result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ if (result)
+- dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
++ dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
+ }
+
+ return result;
+@@ -159,7 +156,7 @@ static void generic_cleanup (struct usb_serial_port *port)
+ {
+ struct usb_serial *serial = port->serial;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (serial->dev) {
+ /* shutdown any bulk reads that might be going on */
+@@ -197,7 +194,7 @@ int usb_serial_generic_resume(struct usb_serial *serial)
+
+ void usb_serial_generic_close (struct usb_serial_port *port, struct file * filp)
+ {
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+ generic_cleanup (port);
+ }
+
+@@ -207,10 +204,10 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *
+ int result;
+ unsigned char *data;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (count == 0) {
+- dbg("%s - write request of 0 bytes", __FUNCTION__);
++ dbg("%s - write request of 0 bytes", __func__);
+ return (0);
+ }
+
+@@ -220,7 +217,7 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *
+ spin_lock_irqsave(&port->lock, flags);
+ if (port->write_urb_busy) {
+ spin_unlock_irqrestore(&port->lock, flags);
+- dbg("%s - already writing", __FUNCTION__);
++ dbg("%s - already writing", __func__);
+ return 0;
+ }
+ port->write_urb_busy = 1;
+@@ -230,7 +227,7 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *
+
+ memcpy (port->write_urb->transfer_buffer, buf, count);
+ data = port->write_urb->transfer_buffer;
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, data);
++ usb_serial_debug_data(debug, &port->dev, __func__, count, data);
+
+ /* set up our urb */
+ usb_fill_bulk_urb (port->write_urb, serial->dev,
+@@ -245,7 +242,7 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *
+ port->write_urb_busy = 1;
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ if (result) {
+- dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
++ dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result);
+ /* don't have to grab the lock here, as we will retry if != 0 */
+ port->write_urb_busy = 0;
+ } else
+@@ -263,15 +260,16 @@ int usb_serial_generic_write_room (struct usb_serial_port *port)
+ struct usb_serial *serial = port->serial;
+ int room = 0;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
++ /* FIXME: Locking */
+ if (serial->num_bulk_out) {
+ if (!(port->write_urb_busy))
+ room = port->bulk_out_size;
+ }
+
+- dbg("%s - returns %d", __FUNCTION__, room);
+- return (room);
++ dbg("%s - returns %d", __func__, room);
++ return room;
+ }
+
+ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port)
+@@ -279,14 +277,15 @@ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port)
+ struct usb_serial *serial = port->serial;
+ int chars = 0;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
++ /* FIXME: Locking */
+ if (serial->num_bulk_out) {
+ if (port->write_urb_busy)
+ chars = port->write_urb->transfer_buffer_length;
+ }
+
+- dbg("%s - returns %d", __FUNCTION__, chars);
++ dbg("%s - returns %d", __func__, chars);
+ return (chars);
+ }
+
+@@ -308,7 +307,7 @@ static void resubmit_read_urb(struct usb_serial_port *port, gfp_t mem_flags)
+ usb_serial_generic_read_bulk_callback), port);
+ result = usb_submit_urb(urb, mem_flags);
+ if (result)
+- dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
++ dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
+ }
+
+ /* Push data to tty layer and resubmit the bulk read URB */
+@@ -332,20 +331,20 @@ static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
+
+ void usb_serial_generic_read_bulk_callback (struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ unsigned char *data = urb->transfer_buffer;
+ int status = urb->status;
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (unlikely(status != 0)) {
+ dbg("%s - nonzero read bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++ usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+
+ /* Throttle the device if requested by tty */
+ spin_lock_irqsave(&port->lock, flags);
+@@ -360,18 +359,17 @@ EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
+
+ void usb_serial_generic_write_bulk_callback (struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ int status = urb->status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ port->write_urb_busy = 0;
+ if (status) {
+ dbg("%s - nonzero write bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
+-
+ usb_serial_port_softint(port);
+ }
+ EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback);
+@@ -380,7 +378,7 @@ void usb_serial_generic_throttle (struct usb_serial_port *port)
+ {
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /* Set the throttle request flag. It will be picked up
+ * by usb_serial_generic_read_bulk_callback(). */
+@@ -394,7 +392,7 @@ void usb_serial_generic_unthrottle (struct usb_serial_port *port)
+ int was_throttled;
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /* Clear the throttle flags */
+ spin_lock_irqsave(&port->lock, flags);
+@@ -412,7 +410,7 @@ void usb_serial_generic_shutdown (struct usb_serial *serial)
+ {
+ int i;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ /* stop reads and writes on all ports */
+ for (i=0; i < serial->num_ports; ++i) {
+diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c
+index 6c6ebae..75b88b3 100644
+--- a/drivers/usb/serial/hp4x.c
++++ b/drivers/usb/serial/hp4x.c
+@@ -50,9 +50,6 @@ static struct usb_serial_driver hp49gp_device = {
+ },
+ .id_table = id_table,
+ .usb_driver = &hp49gp_driver,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_bulk_in = NUM_DONT_CARE,
+- .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 1,
+ };
+
+diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
+index 3428ccc..ce2e487 100644
+--- a/drivers/usb/serial/io_edgeport.c
++++ b/drivers/usb/serial/io_edgeport.c
+@@ -371,7 +371,7 @@ static int get_string (struct usb_device *dev, int Id, char *string, int buflen)
+ struct usb_string_descriptor StringDesc;
+ struct usb_string_descriptor *pStringDesc;
+
+- dbg("%s - USB String ID = %d", __FUNCTION__, Id );
++ dbg("%s - USB String ID = %d", __func__, Id );
+
+ if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc, sizeof(StringDesc))) {
+ return 0;
+@@ -391,7 +391,7 @@ static int get_string (struct usb_device *dev, int Id, char *string, int buflen)
+ unicode_to_ascii(string, buflen, pStringDesc->wData, pStringDesc->bLength/2);
+
+ kfree(pStringDesc);
+- dbg("%s - USB String %s", __FUNCTION__, string);
++ dbg("%s - USB String %s", __func__, string);
+ return strlen(string);
+ }
+
+@@ -407,7 +407,7 @@ static int get_string_desc (struct usb_device *dev, int Id, struct usb_string_de
+ struct usb_string_descriptor StringDesc;
+ struct usb_string_descriptor *pStringDesc;
+
+- dbg("%s - USB String ID = %d", __FUNCTION__, Id );
++ dbg("%s - USB String ID = %d", __func__, Id );
+
+ if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc, sizeof(StringDesc))) {
+ return 0;
+@@ -537,7 +537,7 @@ static int get_epic_descriptor(struct edgeport_serial *ep)
+ sizeof(struct edge_compatibility_descriptor),
+ 300);
+
+- dbg("%s result = %d", __FUNCTION__, result);
++ dbg("%s result = %d", __func__, result);
+
+ if (result > 0) {
+ ep->is_epic = 1;
+@@ -589,7 +589,7 @@ static int get_epic_descriptor(struct edgeport_serial *ep)
+ *****************************************************************************/
+ static void edge_interrupt_callback (struct urb *urb)
+ {
+- struct edgeport_serial *edge_serial = (struct edgeport_serial *)urb->context;
++ struct edgeport_serial *edge_serial = urb->context;
+ struct edgeport_port *edge_port;
+ struct usb_serial_port *port;
+ unsigned char *data = urb->transfer_buffer;
+@@ -601,7 +601,7 @@ static void edge_interrupt_callback (struct urb *urb)
+ int result;
+ int status = urb->status;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ switch (status) {
+ case 0:
+@@ -612,35 +612,35 @@ static void edge_interrupt_callback (struct urb *urb)
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ goto exit;
+ }
+
+ // process this interrupt-read even if there are no ports open
+ if (length) {
+- usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __FUNCTION__, length, data);
++ usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __func__, length, data);
+
+ if (length > 1) {
+ bytes_avail = data[0] | (data[1] << 8);
+ if (bytes_avail) {
+ spin_lock(&edge_serial->es_lock);
+ edge_serial->rxBytesAvail += bytes_avail;
+- dbg("%s - bytes_avail=%d, rxBytesAvail=%d, read_in_progress=%d", __FUNCTION__, bytes_avail, edge_serial->rxBytesAvail, edge_serial->read_in_progress);
++ dbg("%s - bytes_avail=%d, rxBytesAvail=%d, read_in_progress=%d", __func__, bytes_avail, edge_serial->rxBytesAvail, edge_serial->read_in_progress);
+
+ if (edge_serial->rxBytesAvail > 0 &&
+ !edge_serial->read_in_progress) {
+- dbg("%s - posting a read", __FUNCTION__);
++ dbg("%s - posting a read", __func__);
+ edge_serial->read_in_progress = true;
+
+ /* we have pending bytes on the bulk in pipe, send a request */
+ edge_serial->read_urb->dev = edge_serial->serial->dev;
+ result = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
+ if (result) {
+- dev_err(&edge_serial->serial->dev->dev, "%s - usb_submit_urb(read bulk) failed with result = %d\n", __FUNCTION__, result);
++ dev_err(&edge_serial->serial->dev->dev, "%s - usb_submit_urb(read bulk) failed with result = %d\n", __func__, result);
+ edge_serial->read_in_progress = false;
+ }
+ }
+@@ -659,7 +659,7 @@ static void edge_interrupt_callback (struct urb *urb)
+ spin_lock(&edge_port->ep_lock);
+ edge_port->txCredits += txCredits;
+ spin_unlock(&edge_port->ep_lock);
+- dbg("%s - txcredits for port%d = %d", __FUNCTION__, portNumber, edge_port->txCredits);
++ dbg("%s - txcredits for port%d = %d", __func__, portNumber, edge_port->txCredits);
+
+ /* tell the tty driver that something has changed */
+ if (edge_port->port->tty)
+@@ -677,7 +677,7 @@ static void edge_interrupt_callback (struct urb *urb)
+ exit:
+ result = usb_submit_urb (urb, GFP_ATOMIC);
+ if (result) {
+- dev_err(&urb->dev->dev, "%s - Error %d submitting control urb\n", __FUNCTION__, result);
++ dev_err(&urb->dev->dev, "%s - Error %d submitting control urb\n", __func__, result);
+ }
+ }
+
+@@ -689,49 +689,49 @@ exit:
+ *****************************************************************************/
+ static void edge_bulk_in_callback (struct urb *urb)
+ {
+- struct edgeport_serial *edge_serial = (struct edgeport_serial *)urb->context;
++ struct edgeport_serial *edge_serial = urb->context;
+ unsigned char *data = urb->transfer_buffer;
+ int retval;
+ __u16 raw_data_length;
+ int status = urb->status;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ edge_serial->read_in_progress = false;
+ return;
+ }
+
+ if (urb->actual_length == 0) {
+- dbg("%s - read bulk callback with no data", __FUNCTION__);
++ dbg("%s - read bulk callback with no data", __func__);
+ edge_serial->read_in_progress = false;
+ return;
+ }
+
+ raw_data_length = urb->actual_length;
+
+- usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __FUNCTION__, raw_data_length, data);
++ usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __func__, raw_data_length, data);
+
+ spin_lock(&edge_serial->es_lock);
+
+ /* decrement our rxBytes available by the number that we just got */
+ edge_serial->rxBytesAvail -= raw_data_length;
+
+- dbg("%s - Received = %d, rxBytesAvail %d", __FUNCTION__, raw_data_length, edge_serial->rxBytesAvail);
++ dbg("%s - Received = %d, rxBytesAvail %d", __func__, raw_data_length, edge_serial->rxBytesAvail);
+
+ process_rcvd_data (edge_serial, data, urb->actual_length);
+
+ /* check to see if there's any more data for us to read */
+ if (edge_serial->rxBytesAvail > 0) {
+- dbg("%s - posting a read", __FUNCTION__);
++ dbg("%s - posting a read", __func__);
+ edge_serial->read_urb->dev = edge_serial->serial->dev;
+ retval = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
+ if (retval) {
+ dev_err(&urb->dev->dev,
+ "%s - usb_submit_urb(read bulk) failed, "
+- "retval = %d\n", __FUNCTION__, retval);
++ "retval = %d\n", __func__, retval);
+ edge_serial->read_in_progress = false;
+ }
+ } else {
+@@ -749,15 +749,15 @@ static void edge_bulk_in_callback (struct urb *urb)
+ *****************************************************************************/
+ static void edge_bulk_out_data_callback (struct urb *urb)
+ {
+- struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;
++ struct edgeport_port *edge_port = urb->context;
+ struct tty_struct *tty;
+ int status = urb->status;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ if (status) {
+ dbg("%s - nonzero write bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ }
+
+ tty = edge_port->port->tty;
+@@ -782,14 +782,14 @@ static void edge_bulk_out_data_callback (struct urb *urb)
+ *****************************************************************************/
+ static void edge_bulk_out_cmd_callback (struct urb *urb)
+ {
+- struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;
++ struct edgeport_port *edge_port = urb->context;
+ struct tty_struct *tty;
+ int status = urb->status;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ atomic_dec(&CmdUrbs);
+- dbg("%s - FREE URB %p (outstanding %d)", __FUNCTION__, urb, atomic_read(&CmdUrbs));
++ dbg("%s - FREE URB %p (outstanding %d)", __func__, urb, atomic_read(&CmdUrbs));
+
+
+ /* clean up the transfer buffer */
+@@ -799,7 +799,7 @@ static void edge_bulk_out_cmd_callback (struct urb *urb)
+ usb_free_urb (urb);
+
+ if (status) {
+- dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, status);
++ dbg("%s - nonzero write bulk status received: %d", __func__, status);
+ return;
+ }
+
+@@ -833,7 +833,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ struct edgeport_serial *edge_serial;
+ int response;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (edge_port == NULL)
+ return -ENODEV;
+@@ -883,7 +883,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ * this interrupt will continue as long as the edgeport is connected */
+ response = usb_submit_urb (edge_serial->interrupt_read_urb, GFP_KERNEL);
+ if (response) {
+- dev_err(&port->dev, "%s - Error %d submitting control urb\n", __FUNCTION__, response);
++ dev_err(&port->dev, "%s - Error %d submitting control urb\n", __func__, response);
+ }
+ }
+
+@@ -907,7 +907,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ response = send_iosp_ext_cmd (edge_port, IOSP_CMD_OPEN_PORT, 0);
+
+ if (response < 0) {
+- dev_err(&port->dev, "%s - error sending open port command\n", __FUNCTION__);
++ dev_err(&port->dev, "%s - error sending open port command\n", __func__);
+ edge_port->openPending = false;
+ return -ENODEV;
+ }
+@@ -917,7 +917,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+
+ if (!edge_port->open) {
+ /* open timed out */
+- dbg("%s - open timedout", __FUNCTION__);
++ dbg("%s - open timedout", __func__);
+ edge_port->openPending = false;
+ return -ENODEV;
+ }
+@@ -930,7 +930,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ edge_port->txfifo.fifo = kmalloc (edge_port->maxTxCredits, GFP_KERNEL);
+
+ if (!edge_port->txfifo.fifo) {
+- dbg("%s - no memory", __FUNCTION__);
++ dbg("%s - no memory", __func__);
+ edge_close (port, filp);
+ return -ENOMEM;
+ }
+@@ -940,14 +940,14 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ edge_port->write_in_progress = false;
+
+ if (!edge_port->write_urb) {
+- dbg("%s - no memory", __FUNCTION__);
++ dbg("%s - no memory", __func__);
+ edge_close (port, filp);
+ return -ENOMEM;
+ }
+
+- dbg("%s(%d) - Initialize TX fifo to %d bytes", __FUNCTION__, port->number, edge_port->maxTxCredits);
++ dbg("%s(%d) - Initialize TX fifo to %d bytes", __func__, port->number, edge_port->maxTxCredits);
+
+- dbg("%s exited", __FUNCTION__);
++ dbg("%s exited", __func__);
+
+ return 0;
+ }
+@@ -976,11 +976,11 @@ static void block_until_chase_response(struct edgeport_port *edge_port)
+
+ // Did we get our Chase response
+ if (!edge_port->chaseResponsePending) {
+- dbg("%s - Got Chase Response", __FUNCTION__);
++ dbg("%s - Got Chase Response", __func__);
+
+ // did we get all of our credit back?
+ if (edge_port->txCredits == edge_port->maxTxCredits ) {
+- dbg("%s - Got all credits", __FUNCTION__);
++ dbg("%s - Got all credits", __func__);
+ return;
+ }
+ }
+@@ -995,12 +995,12 @@ static void block_until_chase_response(struct edgeport_port *edge_port)
+ loop--;
+ if (loop == 0) {
+ edge_port->chaseResponsePending = false;
+- dbg("%s - Chase TIMEOUT", __FUNCTION__);
++ dbg("%s - Chase TIMEOUT", __func__);
+ return;
+ }
+ } else {
+ // Reset timeout value back to 10 seconds
+- dbg("%s - Last %d, Current %d", __FUNCTION__, lastCredits, edge_port->txCredits);
++ dbg("%s - Last %d, Current %d", __func__, lastCredits, edge_port->txCredits);
+ loop = 10;
+ }
+ }
+@@ -1031,7 +1031,7 @@ static void block_until_tx_empty (struct edgeport_port *edge_port)
+
+ // Is the Edgeport Buffer empty?
+ if (lastCount == 0) {
+- dbg("%s - TX Buffer Empty", __FUNCTION__);
++ dbg("%s - TX Buffer Empty", __func__);
+ return;
+ }
+
+@@ -1040,13 +1040,13 @@ static void block_until_tx_empty (struct edgeport_port *edge_port)
+ schedule_timeout(timeout);
+ finish_wait(&edge_port->wait_chase, &wait);
+
+- dbg("%s wait", __FUNCTION__);
++ dbg("%s wait", __func__);
+
+ if (lastCount == fifo->count) {
+ // No activity.. count down.
+ loop--;
+ if (loop == 0) {
+- dbg("%s - TIMEOUT", __FUNCTION__);
++ dbg("%s - TIMEOUT", __func__);
+ return;
+ }
+ } else {
+@@ -1067,7 +1067,7 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
+ struct edgeport_port *edge_port;
+ int status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ edge_serial = usb_get_serial_data(port->serial);
+ edge_port = usb_get_serial_port_data(port);
+@@ -1085,7 +1085,7 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
+ /* flush and chase */
+ edge_port->chaseResponsePending = true;
+
+- dbg("%s - Sending IOSP_CMD_CHASE_PORT", __FUNCTION__);
++ dbg("%s - Sending IOSP_CMD_CHASE_PORT", __func__);
+ status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
+ if (status == 0) {
+ // block until chase finished
+@@ -1099,7 +1099,7 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
+ ((edge_serial->is_epic) &&
+ (edge_serial->epic_descriptor.Supports.IOSPClose))) {
+ /* close the port */
+- dbg("%s - Sending IOSP_CMD_CLOSE_PORT", __FUNCTION__);
++ dbg("%s - Sending IOSP_CMD_CLOSE_PORT", __func__);
+ send_iosp_ext_cmd (edge_port, IOSP_CMD_CLOSE_PORT, 0);
+ }
+
+@@ -1119,7 +1119,7 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
+ kfree(edge_port->txfifo.fifo);
+ edge_port->txfifo.fifo = NULL;
+
+- dbg("%s exited", __FUNCTION__);
++ dbg("%s exited", __func__);
+ }
+
+ /*****************************************************************************
+@@ -1139,7 +1139,7 @@ static int edge_write (struct usb_serial_port *port, const unsigned char *data,
+ int secondhalf;
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (edge_port == NULL)
+ return -ENODEV;
+@@ -1152,12 +1152,12 @@ static int edge_write (struct usb_serial_port *port, const unsigned char *data,
+ // calculate number of bytes to put in fifo
+ copySize = min ((unsigned int)count, (edge_port->txCredits - fifo->count));
+
+- dbg("%s(%d) of %d byte(s) Fifo room %d -- will copy %d bytes", __FUNCTION__,
++ dbg("%s(%d) of %d byte(s) Fifo room %d -- will copy %d bytes", __func__,
+ port->number, count, edge_port->txCredits - fifo->count, copySize);
+
+ /* catch writes of 0 bytes which the tty driver likes to give us, and when txCredits is empty */
+ if (copySize == 0) {
+- dbg("%s - copySize = Zero", __FUNCTION__);
++ dbg("%s - copySize = Zero", __func__);
+ goto finish_write;
+ }
+
+@@ -1169,11 +1169,11 @@ static int edge_write (struct usb_serial_port *port, const unsigned char *data,
+
+ bytesleft = fifo->size - fifo->head;
+ firsthalf = min (bytesleft, copySize);
+- dbg("%s - copy %d bytes of %d into fifo ", __FUNCTION__, firsthalf, bytesleft);
++ dbg("%s - copy %d bytes of %d into fifo ", __func__, firsthalf, bytesleft);
+
+ /* now copy our data */
+ memcpy(&fifo->fifo[fifo->head], data, firsthalf);
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, firsthalf, &fifo->fifo[fifo->head]);
++ usb_serial_debug_data(debug, &port->dev, __func__, firsthalf, &fifo->fifo[fifo->head]);
+
+ // update the index and size
+ fifo->head += firsthalf;
+@@ -1187,9 +1187,9 @@ static int edge_write (struct usb_serial_port *port, const unsigned char *data,
+ secondhalf = copySize-firsthalf;
+
+ if (secondhalf) {
+- dbg("%s - copy rest of data %d", __FUNCTION__, secondhalf);
++ dbg("%s - copy rest of data %d", __func__, secondhalf);
+ memcpy(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf);
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, secondhalf, &fifo->fifo[fifo->head]);
++ usb_serial_debug_data(debug, &port->dev, __func__, secondhalf, &fifo->fifo[fifo->head]);
+ // update the index and size
+ fifo->count += secondhalf;
+ fifo->head += secondhalf;
+@@ -1201,7 +1201,7 @@ finish_write:
+
+ send_more_port_data((struct edgeport_serial *)usb_get_serial_data(port->serial), edge_port);
+
+- dbg("%s wrote %d byte(s) TxCredits %d, Fifo %d", __FUNCTION__, copySize, edge_port->txCredits, fifo->count);
++ dbg("%s wrote %d byte(s) TxCredits %d, Fifo %d", __func__, copySize, edge_port->txCredits, fifo->count);
+
+ return copySize;
+ }
+@@ -1232,14 +1232,14 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
+ int secondhalf;
+ unsigned long flags;
+
+- dbg("%s(%d)", __FUNCTION__, edge_port->port->number);
++ dbg("%s(%d)", __func__, edge_port->port->number);
+
+ spin_lock_irqsave(&edge_port->ep_lock, flags);
+
+ if (edge_port->write_in_progress ||
+ !edge_port->open ||
+ (fifo->count == 0)) {
+- dbg("%s(%d) EXIT - fifo %d, PendingWrite = %d", __FUNCTION__, edge_port->port->number, fifo->count, edge_port->write_in_progress);
++ dbg("%s(%d) EXIT - fifo %d, PendingWrite = %d", __func__, edge_port->port->number, fifo->count, edge_port->write_in_progress);
+ goto exit_send;
+ }
+
+@@ -1251,7 +1251,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
+ // it's better to wait for more credits so we can do a larger
+ // write.
+ if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits,EDGE_FW_BULK_MAX_PACKET_SIZE)) {
+- dbg("%s(%d) Not enough credit - fifo %d TxCredit %d", __FUNCTION__, edge_port->port->number, fifo->count, edge_port->txCredits );
++ dbg("%s(%d) Not enough credit - fifo %d TxCredit %d", __func__, edge_port->port->number, fifo->count, edge_port->txCredits );
+ goto exit_send;
+ }
+
+@@ -1269,7 +1269,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
+ count = fifo->count;
+ buffer = kmalloc (count+2, GFP_ATOMIC);
+ if (buffer == NULL) {
+- dev_err(&edge_port->port->dev, "%s - no more kernel memory...\n", __FUNCTION__);
++ dev_err(&edge_port->port->dev, "%s - no more kernel memory...\n", __func__);
+ edge_port->write_in_progress = false;
+ goto exit_send;
+ }
+@@ -1294,7 +1294,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
+ }
+
+ if (count)
+- usb_serial_debug_data(debug, &edge_port->port->dev, __FUNCTION__, count, &buffer[2]);
++ usb_serial_debug_data(debug, &edge_port->port->dev, __func__, count, &buffer[2]);
+
+ /* fill up the urb with all of our data and submit it */
+ usb_fill_bulk_urb (urb, edge_serial->serial->dev,
+@@ -1309,14 +1309,14 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (status) {
+ /* something went wrong */
+- dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write bulk) failed, status = %d, data lost\n", __FUNCTION__, status);
++ dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write bulk) failed, status = %d, data lost\n", __func__, status);
+ edge_port->write_in_progress = false;
+
+ /* revert the credits as something bad happened. */
+ edge_port->txCredits += count;
+ edge_port->icount.tx -= count;
+ }
+- dbg("%s wrote %d byte(s) TxCredit %d, Fifo %d", __FUNCTION__, count, edge_port->txCredits, fifo->count);
++ dbg("%s wrote %d byte(s) TxCredit %d, Fifo %d", __func__, count, edge_port->txCredits, fifo->count);
+
+ exit_send:
+ spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+@@ -1337,17 +1337,17 @@ static int edge_write_room (struct usb_serial_port *port)
+ int room;
+ unsigned long flags;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ if (edge_port == NULL)
+ return -ENODEV;
+ if (edge_port->closePending)
+ return -ENODEV;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (!edge_port->open) {
+- dbg("%s - port not opened", __FUNCTION__);
++ dbg("%s - port not opened", __func__);
+ return -EINVAL;
+ }
+
+@@ -1356,7 +1356,7 @@ static int edge_write_room (struct usb_serial_port *port)
+ room = edge_port->txCredits - edge_port->txfifo.count;
+ spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+
+- dbg("%s - returns %d", __FUNCTION__, room);
++ dbg("%s - returns %d", __func__, room);
+ return room;
+ }
+
+@@ -1376,7 +1376,7 @@ static int edge_chars_in_buffer (struct usb_serial_port *port)
+ int num_chars;
+ unsigned long flags;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ if (edge_port == NULL)
+ return -ENODEV;
+@@ -1384,7 +1384,7 @@ static int edge_chars_in_buffer (struct usb_serial_port *port)
+ return -ENODEV;
+
+ if (!edge_port->open) {
+- dbg("%s - port not opened", __FUNCTION__);
++ dbg("%s - port not opened", __func__);
+ return -EINVAL;
+ }
+
+@@ -1392,7 +1392,7 @@ static int edge_chars_in_buffer (struct usb_serial_port *port)
+ num_chars = edge_port->maxTxCredits - edge_port->txCredits + edge_port->txfifo.count;
+ spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+ if (num_chars) {
+- dbg("%s(port %d) - returns %d", __FUNCTION__, port->number, num_chars);
++ dbg("%s(port %d) - returns %d", __func__, port->number, num_chars);
+ }
+
+ return num_chars;
+@@ -1410,19 +1410,19 @@ static void edge_throttle (struct usb_serial_port *port)
+ struct tty_struct *tty;
+ int status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (edge_port == NULL)
+ return;
+
+ if (!edge_port->open) {
+- dbg("%s - port not opened", __FUNCTION__);
++ dbg("%s - port not opened", __func__);
+ return;
+ }
+
+ tty = port->tty;
+ if (!tty) {
+- dbg ("%s - no tty available", __FUNCTION__);
++ dbg ("%s - no tty available", __func__);
+ return;
+ }
+
+@@ -1459,19 +1459,19 @@ static void edge_unthrottle (struct usb_serial_port *port)
+ struct tty_struct *tty;
+ int status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (edge_port == NULL)
+ return;
+
+ if (!edge_port->open) {
+- dbg("%s - port not opened", __FUNCTION__);
++ dbg("%s - port not opened", __func__);
+ return;
+ }
+
+ tty = port->tty;
+ if (!tty) {
+- dbg ("%s - no tty available", __FUNCTION__);
++ dbg ("%s - no tty available", __func__);
+ return;
+ }
+
+@@ -1509,18 +1509,18 @@ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old
+ unsigned int cflag;
+
+ cflag = tty->termios->c_cflag;
+- dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
++ dbg("%s - clfag %08x iflag %08x", __func__,
+ tty->termios->c_cflag, tty->termios->c_iflag);
+- dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
++ dbg("%s - old clfag %08x old iflag %08x", __func__,
+ old_termios->c_cflag, old_termios->c_iflag);
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (edge_port == NULL)
+ return;
+
+ if (!edge_port->open) {
+- dbg("%s - port not opened", __FUNCTION__);
++ dbg("%s - port not opened", __func__);
+ return;
+ }
+
+@@ -1549,7 +1549,7 @@ static int get_lsr_info(struct edgeport_port *edge_port, unsigned int __user *va
+ spin_lock_irqsave(&edge_port->ep_lock, flags);
+ if (edge_port->maxTxCredits == edge_port->txCredits &&
+ edge_port->txfifo.count == 0) {
+- dbg("%s -- Empty", __FUNCTION__);
++ dbg("%s -- Empty", __func__);
+ result = TIOCSER_TEMT;
+ }
+ spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+@@ -1569,7 +1569,7 @@ static int get_number_bytes_avail(struct edgeport_port *edge_port, unsigned int
+
+ result = tty->read_cnt;
+
+- dbg("%s(%d) = %d", __FUNCTION__, edge_port->port->number, result);
++ dbg("%s(%d) = %d", __func__, edge_port->port->number, result);
+ if (copy_to_user(value, &result, sizeof(int)))
+ return -EFAULT;
+ //return 0;
+@@ -1581,7 +1581,7 @@ static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsig
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+ unsigned int mcr;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ mcr = edge_port->shadowMCR;
+ if (set & TIOCM_RTS)
+@@ -1612,7 +1612,7 @@ static int edge_tiocmget(struct usb_serial_port *port, struct file *file)
+ unsigned int msr;
+ unsigned int mcr;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ msr = edge_port->shadowMSR;
+ mcr = edge_port->shadowMCR;
+@@ -1624,7 +1624,7 @@ static int edge_tiocmget(struct usb_serial_port *port, struct file *file)
+ | ((msr & EDGEPORT_MSR_DSR) ? TIOCM_DSR: 0); /* 0x100 */
+
+
+- dbg("%s -- %x", __FUNCTION__, result);
++ dbg("%s -- %x", __func__, result);
+
+ return result;
+ }
+@@ -1670,30 +1670,30 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned
+ struct async_icount cprev;
+ struct serial_icounter_struct icount;
+
+- dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
++ dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
+
+ switch (cmd) {
+ // return number of bytes available
+ case TIOCINQ:
+- dbg("%s (%d) TIOCINQ", __FUNCTION__, port->number);
++ dbg("%s (%d) TIOCINQ", __func__, port->number);
+ return get_number_bytes_avail(edge_port, (unsigned int __user *) arg);
+ break;
+
+ case TIOCSERGETLSR:
+- dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__, port->number);
++ dbg("%s (%d) TIOCSERGETLSR", __func__, port->number);
+ return get_lsr_info(edge_port, (unsigned int __user *) arg);
+ return 0;
+
+ case TIOCGSERIAL:
+- dbg("%s (%d) TIOCGSERIAL", __FUNCTION__, port->number);
++ dbg("%s (%d) TIOCGSERIAL", __func__, port->number);
+ return get_serial_info(edge_port, (struct serial_struct __user *) arg);
+
+ case TIOCSSERIAL:
+- dbg("%s (%d) TIOCSSERIAL", __FUNCTION__, port->number);
++ dbg("%s (%d) TIOCSSERIAL", __func__, port->number);
+ break;
+
+ case TIOCMIWAIT:
+- dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number);
++ dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
+ cprev = edge_port->icount;
+ while (1) {
+ prepare_to_wait(&edge_port->delta_msr_wait, &wait, TASK_INTERRUPTIBLE);
+@@ -1732,7 +1732,7 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned
+ icount.brk = cnow.brk;
+ icount.buf_overrun = cnow.buf_overrun;
+
+- dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__, port->number, icount.rx, icount.tx );
++ dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, port->number, icount.rx, icount.tx );
+ if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))
+ return -EFAULT;
+ return 0;
+@@ -1758,7 +1758,7 @@ static void edge_break (struct usb_serial_port *port, int break_state)
+ /* flush and chase */
+ edge_port->chaseResponsePending = true;
+
+- dbg("%s - Sending IOSP_CMD_CHASE_PORT", __FUNCTION__);
++ dbg("%s - Sending IOSP_CMD_CHASE_PORT", __func__);
+ status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
+ if (status == 0) {
+ // block until chase finished
+@@ -1772,14 +1772,14 @@ static void edge_break (struct usb_serial_port *port, int break_state)
+ ((edge_serial->is_epic) &&
+ (edge_serial->epic_descriptor.Supports.IOSPSetClrBreak))) {
+ if (break_state == -1) {
+- dbg("%s - Sending IOSP_CMD_SET_BREAK", __FUNCTION__);
++ dbg("%s - Sending IOSP_CMD_SET_BREAK", __func__);
+ status = send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_BREAK, 0);
+ } else {
+- dbg("%s - Sending IOSP_CMD_CLEAR_BREAK", __FUNCTION__);
++ dbg("%s - Sending IOSP_CMD_CLEAR_BREAK", __func__);
+ status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CLEAR_BREAK, 0);
+ }
+ if (status) {
+- dbg("%s - error sending break set/clear command.", __FUNCTION__);
++ dbg("%s - error sending break set/clear command.", __func__);
+ }
+ }
+
+@@ -1799,14 +1799,14 @@ static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned cha
+ __u16 lastBufferLength;
+ __u16 rxLen;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ lastBufferLength = bufferLength + 1;
+
+ while (bufferLength > 0) {
+ /* failsafe incase we get a message that we don't understand */
+ if (lastBufferLength == bufferLength) {
+- dbg("%s - stuck in loop, exiting it.", __FUNCTION__);
++ dbg("%s - stuck in loop, exiting it.", __func__);
+ break;
+ }
+ lastBufferLength = bufferLength;
+@@ -1828,7 +1828,7 @@ static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned cha
+ ++buffer;
+ --bufferLength;
+
+- dbg("%s - Hdr1=%02X Hdr2=%02X", __FUNCTION__, edge_serial->rxHeader1, edge_serial->rxHeader2);
++ dbg("%s - Hdr1=%02X Hdr2=%02X", __func__, edge_serial->rxHeader1, edge_serial->rxHeader2);
+
+ // Process depending on whether this header is
+ // data or status
+@@ -1858,7 +1858,7 @@ static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned cha
+ edge_serial->rxPort = IOSP_GET_HDR_PORT(edge_serial->rxHeader1);
+ edge_serial->rxBytesRemaining = IOSP_GET_HDR_DATA_LEN(edge_serial->rxHeader1, edge_serial->rxHeader2);
+
+- dbg("%s - Data for Port %u Len %u", __FUNCTION__, edge_serial->rxPort, edge_serial->rxBytesRemaining);
++ dbg("%s - Data for Port %u Len %u", __func__, edge_serial->rxPort, edge_serial->rxBytesRemaining);
+
+ //ASSERT( DevExt->RxPort < DevExt->NumPorts );
+ //ASSERT( DevExt->RxBytesRemaining < IOSP_MAX_DATA_LENGTH );
+@@ -1891,7 +1891,7 @@ static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned cha
+ if (edge_port->open) {
+ tty = edge_port->port->tty;
+ if (tty) {
+- dbg("%s - Sending %d bytes to TTY for port %d", __FUNCTION__, rxLen, edge_serial->rxPort);
++ dbg("%s - Sending %d bytes to TTY for port %d", __func__, rxLen, edge_serial->rxPort);
+ edge_tty_recv(&edge_serial->serial->dev->dev, tty, buffer, rxLen);
+ }
+ edge_port->icount.rx += rxLen;
+@@ -1930,17 +1930,17 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
+ port = edge_serial->serial->port[edge_serial->rxPort];
+ edge_port = usb_get_serial_port_data(port);
+ if (edge_port == NULL) {
+- dev_err(&edge_serial->serial->dev->dev, "%s - edge_port == NULL for port %d\n", __FUNCTION__, edge_serial->rxPort);
++ dev_err(&edge_serial->serial->dev->dev, "%s - edge_port == NULL for port %d\n", __func__, edge_serial->rxPort);
+ return;
+ }
+
+- dbg("%s - port %d", __FUNCTION__, edge_serial->rxPort);
++ dbg("%s - port %d", __func__, edge_serial->rxPort);
+
+ if (code == IOSP_EXT_STATUS) {
+ switch (byte2) {
+ case IOSP_EXT_STATUS_CHASE_RSP:
+ // we want to do EXT status regardless of port open/closed
+- dbg("%s - Port %u EXT CHASE_RSP Data = %02x", __FUNCTION__, edge_serial->rxPort, byte3 );
++ dbg("%s - Port %u EXT CHASE_RSP Data = %02x", __func__, edge_serial->rxPort, byte3 );
+ // Currently, the only EXT_STATUS is Chase, so process here instead of one more call
+ // to one more subroutine. If/when more EXT_STATUS, there'll be more work to do.
+ // Also, we currently clear flag and close the port regardless of content of above's Byte3.
+@@ -1951,7 +1951,7 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
+ return;
+
+ case IOSP_EXT_STATUS_RX_CHECK_RSP:
+- dbg("%s ========== Port %u CHECK_RSP Sequence = %02x =============\n", __FUNCTION__, edge_serial->rxPort, byte3 );
++ dbg("%s ========== Port %u CHECK_RSP Sequence = %02x =============\n", __func__, edge_serial->rxPort, byte3 );
+ //Port->RxCheckRsp = true;
+ return;
+ }
+@@ -1960,7 +1960,7 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
+ if (code == IOSP_STATUS_OPEN_RSP) {
+ edge_port->txCredits = GET_TX_BUFFER_SIZE(byte3);
+ edge_port->maxTxCredits = edge_port->txCredits;
+- dbg("%s - Port %u Open Response Inital MSR = %02x TxBufferSize = %d", __FUNCTION__, edge_serial->rxPort, byte2, edge_port->txCredits);
++ dbg("%s - Port %u Open Response Inital MSR = %02x TxBufferSize = %d", __func__, edge_serial->rxPort, byte2, edge_port->txCredits);
+ handle_new_msr (edge_port, byte2);
+
+ /* send the current line settings to the port so we are in sync with any further termios calls */
+@@ -1984,23 +1984,23 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
+ switch (code) {
+ // Not currently sent by Edgeport
+ case IOSP_STATUS_LSR:
+- dbg("%s - Port %u LSR Status = %02x", __FUNCTION__, edge_serial->rxPort, byte2);
++ dbg("%s - Port %u LSR Status = %02x", __func__, edge_serial->rxPort, byte2);
+ handle_new_lsr(edge_port, false, byte2, 0);
+ break;
+
+ case IOSP_STATUS_LSR_DATA:
+- dbg("%s - Port %u LSR Status = %02x, Data = %02x", __FUNCTION__, edge_serial->rxPort, byte2, byte3);
++ dbg("%s - Port %u LSR Status = %02x, Data = %02x", __func__, edge_serial->rxPort, byte2, byte3);
+ // byte2 is LSR Register
+ // byte3 is broken data byte
+ handle_new_lsr(edge_port, true, byte2, byte3);
+ break;
+ //
+ // case IOSP_EXT_4_STATUS:
+- // dbg("%s - Port %u LSR Status = %02x Data = %02x", __FUNCTION__, edge_serial->rxPort, byte2, byte3);
++ // dbg("%s - Port %u LSR Status = %02x Data = %02x", __func__, edge_serial->rxPort, byte2, byte3);
+ // break;
+ //
+ case IOSP_STATUS_MSR:
+- dbg("%s - Port %u MSR Status = %02x", __FUNCTION__, edge_serial->rxPort, byte2);
++ dbg("%s - Port %u MSR Status = %02x", __func__, edge_serial->rxPort, byte2);
+
+ // Process this new modem status and generate appropriate
+ // events, etc, based on the new status. This routine
+@@ -2009,7 +2009,7 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
+ break;
+
+ default:
+- dbg("%s - Unrecognized IOSP status code %u\n", __FUNCTION__, code);
++ dbg("%s - Unrecognized IOSP status code %u\n", __func__, code);
+ break;
+ }
+
+@@ -2029,7 +2029,7 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c
+ cnt = tty_buffer_request_room(tty, length);
+ if (cnt < length) {
+ dev_err(dev, "%s - dropping data, %d bytes lost\n",
+- __FUNCTION__, length - cnt);
++ __func__, length - cnt);
+ if(cnt == 0)
+ break;
+ }
+@@ -2050,7 +2050,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr)
+ {
+ struct async_icount *icount;
+
+- dbg("%s %02x", __FUNCTION__, newMsr);
++ dbg("%s %02x", __func__, newMsr);
+
+ if (newMsr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
+ icount = &edge_port->icount;
+@@ -2087,7 +2087,7 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, __u8 l
+ __u8 newLsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK));
+ struct async_icount *icount;
+
+- dbg("%s - %02x", __FUNCTION__, newLsr);
++ dbg("%s - %02x", __func__, newLsr);
+
+ edge_port->shadowLSR = lsr;
+
+@@ -2136,11 +2136,11 @@ static int sram_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u
+ __u16 current_length;
+ unsigned char *transfer_buffer;
+
+- dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length);
++ dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
+
+ transfer_buffer = kmalloc (64, GFP_KERNEL);
+ if (!transfer_buffer) {
+- dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 64);
++ dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, 64);
+ return -ENOMEM;
+ }
+
+@@ -2152,7 +2152,7 @@ static int sram_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u
+ } else {
+ current_length = length;
+ }
+-// dbg("%s - writing %x, %x, %d", __FUNCTION__, extAddr, addr, current_length);
++// dbg("%s - writing %x, %x, %d", __func__, extAddr, addr, current_length);
+ memcpy (transfer_buffer, data, current_length);
+ result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), USB_REQUEST_ION_WRITE_RAM,
+ 0x40, addr, extAddr, transfer_buffer, current_length, 300);
+@@ -2181,11 +2181,11 @@ static int rom_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u1
+ __u16 current_length;
+ unsigned char *transfer_buffer;
+
+-// dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length);
++// dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
+
+ transfer_buffer = kmalloc (64, GFP_KERNEL);
+ if (!transfer_buffer) {
+- dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 64);
++ dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, 64);
+ return -ENOMEM;
+ }
+
+@@ -2197,7 +2197,7 @@ static int rom_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u1
+ } else {
+ current_length = length;
+ }
+-// dbg("%s - writing %x, %x, %d", __FUNCTION__, extAddr, addr, current_length);
++// dbg("%s - writing %x, %x, %d", __func__, extAddr, addr, current_length);
+ memcpy (transfer_buffer, data, current_length);
+ result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), USB_REQUEST_ION_WRITE_ROM,
+ 0x40, addr, extAddr, transfer_buffer, current_length, 300);
+@@ -2226,11 +2226,11 @@ static int rom_read (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16
+ __u16 current_length;
+ unsigned char *transfer_buffer;
+
+- dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length);
++ dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
+
+ transfer_buffer = kmalloc (64, GFP_KERNEL);
+ if (!transfer_buffer) {
+- dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 64);
++ dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, 64);
+ return -ENOMEM;
+ }
+
+@@ -2242,7 +2242,7 @@ static int rom_read (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16
+ } else {
+ current_length = length;
+ }
+-// dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, current_length);
++// dbg("%s - %x, %x, %d", __func__, extAddr, addr, current_length);
+ result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), USB_REQUEST_ION_READ_ROM,
+ 0xC0, addr, extAddr, transfer_buffer, current_length, 300);
+ if (result < 0)
+@@ -2269,11 +2269,11 @@ static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u
+ int length = 0;
+ int status = 0;
+
+- dbg("%s - %d, %d", __FUNCTION__, command, param);
++ dbg("%s - %d, %d", __func__, command, param);
+
+ buffer = kmalloc (10, GFP_ATOMIC);
+ if (!buffer) {
+- dev_err(&edge_port->port->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 10);
++ dev_err(&edge_port->port->dev, "%s - kmalloc(%d) failed.\n", __func__, 10);
+ return -ENOMEM;
+ }
+
+@@ -2304,7 +2304,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
+ struct urb *urb;
+ int timeout;
+
+- usb_serial_debug_data(debug, &edge_port->port->dev, __FUNCTION__, length, buffer);
++ usb_serial_debug_data(debug, &edge_port->port->dev, __func__, length, buffer);
+
+ /* Allocate our next urb */
+ urb = usb_alloc_urb (0, GFP_ATOMIC);
+@@ -2312,7 +2312,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
+ return -ENOMEM;
+
+ atomic_inc(&CmdUrbs);
+- dbg("%s - ALLOCATE URB %p (outstanding %d)", __FUNCTION__, urb, atomic_read(&CmdUrbs));
++ dbg("%s - ALLOCATE URB %p (outstanding %d)", __func__, urb, atomic_read(&CmdUrbs));
+
+ usb_fill_bulk_urb (urb, edge_serial->serial->dev,
+ usb_sndbulkpipe(edge_serial->serial->dev, edge_serial->bulk_out_endpoint),
+@@ -2323,7 +2323,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
+
+ if (status) {
+ /* something went wrong */
+- dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write command) failed, status = %d\n", __FUNCTION__, status);
++ dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write command) failed, status = %d\n", __func__, status);
+ usb_kill_urb(urb);
+ usb_free_urb(urb);
+ atomic_dec(&CmdUrbs);
+@@ -2337,7 +2337,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
+
+ if (edge_port->commandPending) {
+ /* command timed out */
+- dbg("%s - command timed out", __FUNCTION__);
++ dbg("%s - command timed out", __func__);
+ status = -EINVAL;
+ }
+ #endif
+@@ -2367,18 +2367,18 @@ static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRa
+ return 0;
+ }
+
+- dbg("%s - port = %d, baud = %d", __FUNCTION__, edge_port->port->number, baudRate);
++ dbg("%s - port = %d, baud = %d", __func__, edge_port->port->number, baudRate);
+
+ status = calc_baud_rate_divisor (baudRate, &divisor);
+ if (status) {
+- dev_err(&edge_port->port->dev, "%s - bad baud rate\n", __FUNCTION__);
++ dev_err(&edge_port->port->dev, "%s - bad baud rate\n", __func__);
+ return status;
+ }
+
+ // Alloc memory for the string of commands.
+ cmdBuffer = kmalloc (0x100, GFP_ATOMIC);
+ if (!cmdBuffer) {
+- dev_err(&edge_port->port->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 0x100);
++ dev_err(&edge_port->port->dev, "%s - kmalloc(%d) failed.\n", __func__, 0x100);
+ return -ENOMEM;
+ }
+ currCmd = cmdBuffer;
+@@ -2414,7 +2414,7 @@ static int calc_baud_rate_divisor (int baudrate, int *divisor)
+ __u16 custom;
+
+
+- dbg("%s - %d", __FUNCTION__, baudrate);
++ dbg("%s - %d", __func__, baudrate);
+
+ for (i = 0; i < ARRAY_SIZE(divisor_table); i++) {
+ if ( divisor_table[i].BaudRate == baudrate ) {
+@@ -2432,7 +2432,7 @@ static int calc_baud_rate_divisor (int baudrate, int *divisor)
+
+ *divisor = custom;
+
+- dbg("%s - Baud %d = %d\n", __FUNCTION__, baudrate, custom);
++ dbg("%s - Baud %d = %d\n", __func__, baudrate, custom);
+ return 0;
+ }
+
+@@ -2452,7 +2452,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r
+ unsigned long cmdLen = 0;
+ int status;
+
+- dbg("%s - write to %s register 0x%02x", (regNum == MCR) ? "MCR" : "LCR", __FUNCTION__, regValue);
++ dbg("%s - write to %s register 0x%02x", (regNum == MCR) ? "MCR" : "LCR", __func__, regValue);
+
+ if (edge_serial->is_epic &&
+ !edge_serial->epic_descriptor.Supports.IOSPWriteMCR &&
+@@ -2513,29 +2513,29 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
+ __u8 txFlow;
+ int status;
+
+- dbg("%s - port %d", __FUNCTION__, edge_port->port->number);
++ dbg("%s - port %d", __func__, edge_port->port->number);
+
+ if (!edge_port->open &&
+ !edge_port->openPending) {
+- dbg("%s - port not opened", __FUNCTION__);
++ dbg("%s - port not opened", __func__);
+ return;
+ }
+
+ tty = edge_port->port->tty;
+ if ((!tty) ||
+ (!tty->termios)) {
+- dbg("%s - no tty structures", __FUNCTION__);
++ dbg("%s - no tty structures", __func__);
+ return;
+ }
+
+ cflag = tty->termios->c_cflag;
+
+ switch (cflag & CSIZE) {
+- case CS5: lData = LCR_BITS_5; mask = 0x1f; dbg("%s - data bits = 5", __FUNCTION__); break;
+- case CS6: lData = LCR_BITS_6; mask = 0x3f; dbg("%s - data bits = 6", __FUNCTION__); break;
+- case CS7: lData = LCR_BITS_7; mask = 0x7f; dbg("%s - data bits = 7", __FUNCTION__); break;
++ case CS5: lData = LCR_BITS_5; mask = 0x1f; dbg("%s - data bits = 5", __func__); break;
++ case CS6: lData = LCR_BITS_6; mask = 0x3f; dbg("%s - data bits = 6", __func__); break;
++ case CS7: lData = LCR_BITS_7; mask = 0x7f; dbg("%s - data bits = 7", __func__); break;
+ default:
+- case CS8: lData = LCR_BITS_8; dbg("%s - data bits = 8", __FUNCTION__); break;
++ case CS8: lData = LCR_BITS_8; dbg("%s - data bits = 8", __func__); break;
+ }
+
+ lParity = LCR_PAR_NONE;
+@@ -2543,28 +2543,28 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
+ if (cflag & CMSPAR) {
+ if (cflag & PARODD) {
+ lParity = LCR_PAR_MARK;
+- dbg("%s - parity = mark", __FUNCTION__);
++ dbg("%s - parity = mark", __func__);
+ } else {
+ lParity = LCR_PAR_SPACE;
+- dbg("%s - parity = space", __FUNCTION__);
++ dbg("%s - parity = space", __func__);
+ }
+ } else if (cflag & PARODD) {
+ lParity = LCR_PAR_ODD;
+- dbg("%s - parity = odd", __FUNCTION__);
++ dbg("%s - parity = odd", __func__);
+ } else {
+ lParity = LCR_PAR_EVEN;
+- dbg("%s - parity = even", __FUNCTION__);
++ dbg("%s - parity = even", __func__);
+ }
+ } else {
+- dbg("%s - parity = none", __FUNCTION__);
++ dbg("%s - parity = none", __func__);
+ }
+
+ if (cflag & CSTOPB) {
+ lStop = LCR_STOP_2;
+- dbg("%s - stop bits = 2", __FUNCTION__);
++ dbg("%s - stop bits = 2", __func__);
+ } else {
+ lStop = LCR_STOP_1;
+- dbg("%s - stop bits = 1", __FUNCTION__);
++ dbg("%s - stop bits = 1", __func__);
+ }
+
+ /* figure out the flow control settings */
+@@ -2572,9 +2572,9 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
+ if (cflag & CRTSCTS) {
+ rxFlow |= IOSP_RX_FLOW_RTS;
+ txFlow |= IOSP_TX_FLOW_CTS;
+- dbg("%s - RTS/CTS is enabled", __FUNCTION__);
++ dbg("%s - RTS/CTS is enabled", __func__);
+ } else {
+- dbg("%s - RTS/CTS is disabled", __FUNCTION__);
++ dbg("%s - RTS/CTS is disabled", __func__);
+ }
+
+ /* if we are implementing XON/XOFF, set the start and stop character in the device */
+@@ -2592,17 +2592,17 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
+ /* if we are implementing INBOUND XON/XOFF */
+ if (I_IXOFF(tty)) {
+ rxFlow |= IOSP_RX_FLOW_XON_XOFF;
+- dbg("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", __FUNCTION__, start_char, stop_char);
++ dbg("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", __func__, start_char, stop_char);
+ } else {
+- dbg("%s - INBOUND XON/XOFF is disabled", __FUNCTION__);
++ dbg("%s - INBOUND XON/XOFF is disabled", __func__);
+ }
+
+ /* if we are implementing OUTBOUND XON/XOFF */
+ if (I_IXON(tty)) {
+ txFlow |= IOSP_TX_FLOW_XON_XOFF;
+- dbg("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", __FUNCTION__, start_char, stop_char);
++ dbg("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", __func__, start_char, stop_char);
+ } else {
+- dbg("%s - OUTBOUND XON/XOFF is disabled", __FUNCTION__);
++ dbg("%s - OUTBOUND XON/XOFF is disabled", __func__);
+ }
+ }
+
+@@ -2645,7 +2645,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
+ baud = 9600;
+ }
+
+- dbg("%s - baud rate = %d", __FUNCTION__, baud);
++ dbg("%s - baud rate = %d", __func__, baud);
+ status = send_cmd_write_baud_rate (edge_port, baud);
+ if (status == -1) {
+ /* Speed change was not possible - put back the old speed */
+@@ -2843,7 +2843,7 @@ static int edge_startup (struct usb_serial *serial)
+ /* create our private serial structure */
+ edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL);
+ if (edge_serial == NULL) {
+- dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
++ dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
+ return -ENOMEM;
+ }
+ spin_lock_init(&edge_serial->es_lock);
+@@ -2885,19 +2885,19 @@ static int edge_startup (struct usb_serial *serial)
+ serial->num_ports);
+ }
+
+- dbg("%s - time 1 %ld", __FUNCTION__, jiffies);
++ dbg("%s - time 1 %ld", __func__, jiffies);
+
+ /* If not an EPiC device */
+ if (!edge_serial->is_epic) {
+ /* now load the application firmware into this device */
+ load_application_firmware (edge_serial);
+
+- dbg("%s - time 2 %ld", __FUNCTION__, jiffies);
++ dbg("%s - time 2 %ld", __func__, jiffies);
+
+ /* Check current Edgeport EEPROM and update if necessary */
+ update_edgeport_E2PROM (edge_serial);
+
+- dbg("%s - time 3 %ld", __FUNCTION__, jiffies);
++ dbg("%s - time 3 %ld", __func__, jiffies);
+
+ /* set the configuration to use #1 */
+ // dbg("set_configuration 1");
+@@ -2911,7 +2911,7 @@ static int edge_startup (struct usb_serial *serial)
+ for (i = 0; i < serial->num_ports; ++i) {
+ edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL);
+ if (edge_port == NULL) {
+- dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
++ dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
+ for (j = 0; j < i; ++j) {
+ kfree (usb_get_serial_port_data(serial->port[j]));
+ usb_set_serial_port_data(serial->port[j], NULL);
+@@ -3017,7 +3017,7 @@ static int edge_startup (struct usb_serial *serial)
+ * continue as long as the edgeport is connected */
+ response = usb_submit_urb(edge_serial->interrupt_read_urb, GFP_KERNEL);
+ if (response)
+- err("%s - Error %d submitting control urb", __FUNCTION__, response);
++ err("%s - Error %d submitting control urb", __func__, response);
+ }
+ return response;
+ }
+@@ -3032,7 +3032,7 @@ static void edge_shutdown (struct usb_serial *serial)
+ struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
+ int i;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ /* stop reads and writes on all ports */
+ for (i=0; i < serial->num_ports; ++i) {
+diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
+index 6d30087..2ec8589 100644
+--- a/drivers/usb/serial/io_tables.h
++++ b/drivers/usb/serial/io_tables.h
+@@ -111,9 +111,6 @@ static struct usb_serial_driver edgeport_2port_device = {
+ .description = "Edgeport 2 port adapter",
+ .usb_driver = &io_driver,
+ .id_table = edgeport_2port_id_table,
+- .num_interrupt_in = 1,
+- .num_bulk_in = 1,
+- .num_bulk_out = 1,
+ .num_ports = 2,
+ .open = edge_open,
+ .close = edge_close,
+@@ -142,9 +139,6 @@ static struct usb_serial_driver edgeport_4port_device = {
+ .description = "Edgeport 4 port adapter",
+ .usb_driver = &io_driver,
+ .id_table = edgeport_4port_id_table,
+- .num_interrupt_in = 1,
+- .num_bulk_in = 1,
+- .num_bulk_out = 1,
+ .num_ports = 4,
+ .open = edge_open,
+ .close = edge_close,
+@@ -173,9 +167,6 @@ static struct usb_serial_driver edgeport_8port_device = {
+ .description = "Edgeport 8 port adapter",
+ .usb_driver = &io_driver,
+ .id_table = edgeport_8port_id_table,
+- .num_interrupt_in = 1,
+- .num_bulk_in = 1,
+- .num_bulk_out = 1,
+ .num_ports = 8,
+ .open = edge_open,
+ .close = edge_close,
+@@ -203,9 +194,6 @@ static struct usb_serial_driver epic_device = {
+ },
+ .description = "EPiC device",
+ .id_table = Epic_port_id_table,
+- .num_interrupt_in = 1,
+- .num_bulk_in = 1,
+- .num_bulk_out = 1,
+ .num_ports = 1,
+ .open = edge_open,
+ .close = edge_close,
+diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
+index cd34059..05e4fa7 100644
+--- a/drivers/usb/serial/io_ti.c
++++ b/drivers/usb/serial/io_ti.c
+@@ -38,7 +38,6 @@
+ #include <linux/serial.h>
+ #include <linux/ioctl.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #include <linux/usb.h>
+ #include <linux/usb/serial.h>
+
+@@ -291,7 +290,7 @@ static int TIReadVendorRequestSync (struct usb_device *dev,
+ return status;
+ if (status != size) {
+ dbg ("%s - wanted to write %d, but only wrote %d",
+- __FUNCTION__, size, status);
++ __func__, size, status);
+ return -ECOMM;
+ }
+ return 0;
+@@ -321,7 +320,7 @@ static int TISendVendorRequestSync (struct usb_device *dev,
+ return status;
+ if (status != size) {
+ dbg ("%s - wanted to write %d, but only wrote %d",
+- __FUNCTION__, size, status);
++ __func__, size, status);
+ return -ECOMM;
+ }
+ return 0;
+@@ -345,7 +344,7 @@ static int TIPurgeDataSync (struct usb_serial_port *port, __u16 mask)
+ {
+ int port_number = port->number - port->serial->minor;
+
+- dbg ("%s - port %d, mask %x", __FUNCTION__, port_number, mask);
++ dbg ("%s - port %d, mask %x", __func__, port_number, mask);
+
+ return TIWriteCommandSync (port->serial->dev,
+ UMPC_PURGE_PORT,
+@@ -370,7 +369,7 @@ static int TIReadDownloadMemory(struct usb_device *dev, int start_address,
+ __u8 read_length;
+ __be16 be_start_address;
+
+- dbg ("%s - @ %x for %d", __FUNCTION__, start_address, length);
++ dbg ("%s - @ %x for %d", __func__, start_address, length);
+
+ /* Read in blocks of 64 bytes
+ * (TI firmware can't handle more than 64 byte reads)
+@@ -382,7 +381,7 @@ static int TIReadDownloadMemory(struct usb_device *dev, int start_address,
+ read_length = (__u8)length;
+
+ if (read_length > 1) {
+- dbg ("%s - @ %x for %d", __FUNCTION__,
++ dbg ("%s - @ %x for %d", __func__,
+ start_address, read_length);
+ }
+ be_start_address = cpu_to_be16 (start_address);
+@@ -394,12 +393,12 @@ static int TIReadDownloadMemory(struct usb_device *dev, int start_address,
+ read_length); // TransferBufferLength
+
+ if (status) {
+- dbg ("%s - ERROR %x", __FUNCTION__, status);
++ dbg ("%s - ERROR %x", __func__, status);
+ return status;
+ }
+
+ if (read_length > 1) {
+- usb_serial_debug_data(debug, &dev->dev, __FUNCTION__,
++ usb_serial_debug_data(debug, &dev->dev, __func__,
+ read_length, buffer);
+ }
+
+@@ -435,13 +434,13 @@ static int TIReadBootMemory (struct edgeport_serial *serial, int start_address,
+ &buffer[i], // TransferBuffer
+ 0x01); // TransferBufferLength
+ if (status) {
+- dbg ("%s - ERROR %x", __FUNCTION__, status);
++ dbg ("%s - ERROR %x", __func__, status);
+ return status;
+ }
+ }
+
+- dbg ("%s - start_address = %x, length = %d", __FUNCTION__, start_address, length);
+- usb_serial_debug_data(debug, &serial->serial->dev->dev, __FUNCTION__, length, buffer);
++ dbg ("%s - start_address = %x, length = %d", __func__, start_address, length);
++ usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, length, buffer);
+
+ serial->TiReadI2C = 1;
+
+@@ -473,8 +472,8 @@ static int TIWriteBootMemory (struct edgeport_serial *serial, int start_address,
+ return status;
+ }
+
+- dbg ("%s - start_sddr = %x, length = %d", __FUNCTION__, start_address, length);
+- usb_serial_debug_data(debug, &serial->serial->dev->dev, __FUNCTION__, length, buffer);
++ dbg ("%s - start_sddr = %x, length = %d", __func__, start_address, length);
++ usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, length, buffer);
+
+ return status;
+ }
+@@ -495,8 +494,8 @@ static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address
+ if (write_length > length)
+ write_length = length;
+
+- dbg ("%s - BytesInFirstPage Addr = %x, length = %d", __FUNCTION__, start_address, write_length);
+- usb_serial_debug_data(debug, &serial->serial->dev->dev, __FUNCTION__, write_length, buffer);
++ dbg ("%s - BytesInFirstPage Addr = %x, length = %d", __func__, start_address, write_length);
++ usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, write_length, buffer);
+
+ /* Write first page */
+ be_start_address = cpu_to_be16 (start_address);
+@@ -507,7 +506,7 @@ static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address
+ buffer, // TransferBuffer
+ write_length);
+ if (status) {
+- dbg ("%s - ERROR %d", __FUNCTION__, status);
++ dbg ("%s - ERROR %d", __func__, status);
+ return status;
+ }
+
+@@ -522,8 +521,8 @@ static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address
+ else
+ write_length = length;
+
+- dbg ("%s - Page Write Addr = %x, length = %d", __FUNCTION__, start_address, write_length);
+- usb_serial_debug_data(debug, &serial->serial->dev->dev, __FUNCTION__, write_length, buffer);
++ dbg ("%s - Page Write Addr = %x, length = %d", __func__, start_address, write_length);
++ usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, write_length, buffer);
+
+ /* Write next page */
+ be_start_address = cpu_to_be16 (start_address);
+@@ -534,7 +533,7 @@ static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address
+ buffer, // TransferBuffer
+ write_length); // TransferBufferLength
+ if (status) {
+- dev_err (&serial->serial->dev->dev, "%s - ERROR %d\n", __FUNCTION__, status);
++ dev_err (&serial->serial->dev->dev, "%s - ERROR %d\n", __func__, status);
+ return status;
+ }
+
+@@ -560,7 +559,7 @@ static int TIIsTxActive (struct edgeport_port *port)
+
+ oedb = kmalloc (sizeof (* oedb), GFP_KERNEL);
+ if (!oedb) {
+- dev_err (&port->port->dev, "%s - out of memory\n", __FUNCTION__);
++ dev_err (&port->port->dev, "%s - out of memory\n", __func__);
+ return -ENOMEM;
+ }
+
+@@ -580,7 +579,7 @@ static int TIIsTxActive (struct edgeport_port *port)
+ if (status)
+ goto exit_is_tx_active;
+
+- dbg ("%s - XByteCount 0x%X", __FUNCTION__, oedb->XByteCount);
++ dbg ("%s - XByteCount 0x%X", __func__, oedb->XByteCount);
+
+ /* and the LSR */
+ status = TIReadRam (port->port->serial->dev,
+@@ -590,7 +589,7 @@ static int TIIsTxActive (struct edgeport_port *port)
+
+ if (status)
+ goto exit_is_tx_active;
+- dbg ("%s - LSR = 0x%X", __FUNCTION__, *lsr);
++ dbg ("%s - LSR = 0x%X", __func__, *lsr);
+
+ /* If either buffer has data or we are transmitting then return TRUE */
+ if ((oedb->XByteCount & 0x80 ) != 0 )
+@@ -601,7 +600,7 @@ static int TIIsTxActive (struct edgeport_port *port)
+
+ /* We return Not Active if we get any kind of error */
+ exit_is_tx_active:
+- dbg ("%s - return %d", __FUNCTION__, bytes_left );
++ dbg ("%s - return %d", __func__, bytes_left );
+
+ kfree(lsr);
+ kfree(oedb);
+@@ -655,7 +654,7 @@ static void TIChasePort(struct edgeport_port *port, unsigned long timeout, int f
+ /* (TIIsTxActive doesn't seem to wait for the last byte) */
+ if ((baud_rate=port->baud_rate) == 0)
+ baud_rate = 50;
+- msleep(max(1,(10000+baud_rate-1)/baud_rate));
++ msleep(max(1, DIV_ROUND_UP(10000, baud_rate)));
+ }
+
+ static int TIChooseConfiguration (struct usb_device *dev)
+@@ -665,11 +664,11 @@ static int TIChooseConfiguration (struct usb_device *dev)
+ // we want. However, we just support one config at this point,
+ // configuration # 1, which is Config Descriptor 0.
+
+- dbg ("%s - Number of Interfaces = %d", __FUNCTION__, dev->config->desc.bNumInterfaces);
+- dbg ("%s - MAX Power = %d", __FUNCTION__, dev->config->desc.bMaxPower*2);
++ dbg ("%s - Number of Interfaces = %d", __func__, dev->config->desc.bNumInterfaces);
++ dbg ("%s - MAX Power = %d", __func__, dev->config->desc.bMaxPower*2);
+
+ if (dev->config->desc.bNumInterfaces != 1) {
+- dev_err (&dev->dev, "%s - bNumInterfaces is not 1, ERROR!\n", __FUNCTION__);
++ dev_err (&dev->dev, "%s - bNumInterfaces is not 1, ERROR!\n", __func__);
+ return -ENODEV;
+ }
+
+@@ -752,7 +751,7 @@ static int ValidChecksum(struct ti_i2c_desc *rom_desc, __u8 *buffer)
+ cs = (__u8)(cs + buffer[i]);
+ }
+ if (cs != rom_desc->CheckSum) {
+- dbg ("%s - Mismatch %x - %x", __FUNCTION__, rom_desc->CheckSum, cs);
++ dbg ("%s - Mismatch %x - %x", __func__, rom_desc->CheckSum, cs);
+ return -EINVAL;
+ }
+ return 0;
+@@ -770,12 +769,12 @@ static int TiValidateI2cImage (struct edgeport_serial *serial)
+
+ rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL);
+ if (!rom_desc) {
+- dev_err (dev, "%s - out of memory\n", __FUNCTION__);
++ dev_err (dev, "%s - out of memory\n", __func__);
+ return -ENOMEM;
+ }
+ buffer = kmalloc (TI_MAX_I2C_SIZE, GFP_KERNEL);
+ if (!buffer) {
+- dev_err (dev, "%s - out of memory when allocating buffer\n", __FUNCTION__);
++ dev_err (dev, "%s - out of memory when allocating buffer\n", __func__);
+ kfree (rom_desc);
+ return -ENOMEM;
+ }
+@@ -786,7 +785,7 @@ static int TiValidateI2cImage (struct edgeport_serial *serial)
+ goto ExitTiValidateI2cImage;
+
+ if (*buffer != UMP5152 && *buffer != UMP3410) {
+- dev_err (dev, "%s - invalid buffer signature\n", __FUNCTION__);
++ dev_err (dev, "%s - invalid buffer signature\n", __func__);
+ status = -ENODEV;
+ goto ExitTiValidateI2cImage;
+ }
+@@ -802,11 +801,11 @@ static int TiValidateI2cImage (struct edgeport_serial *serial)
+
+ if ((start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size) > TI_MAX_I2C_SIZE) {
+ status = -ENODEV;
+- dbg ("%s - structure too big, erroring out.", __FUNCTION__);
++ dbg ("%s - structure too big, erroring out.", __func__);
+ break;
+ }
+
+- dbg ("%s Type = 0x%x", __FUNCTION__, rom_desc->Type);
++ dbg ("%s Type = 0x%x", __func__, rom_desc->Type);
+
+ // Skip type 2 record
+ ttype = rom_desc->Type & 0x0f;
+@@ -846,13 +845,13 @@ static int TIReadManufDescriptor (struct edgeport_serial *serial, __u8 *buffer)
+
+ rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL);
+ if (!rom_desc) {
+- dev_err (&serial->serial->dev->dev, "%s - out of memory\n", __FUNCTION__);
++ dev_err (&serial->serial->dev->dev, "%s - out of memory\n", __func__);
+ return -ENOMEM;
+ }
+ start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_ION, rom_desc);
+
+ if (!start_address) {
+- dbg ("%s - Edge Descriptor not found in I2C", __FUNCTION__);
++ dbg ("%s - Edge Descriptor not found in I2C", __func__);
+ status = -ENODEV;
+ goto exit;
+ }
+@@ -868,12 +867,12 @@ static int TIReadManufDescriptor (struct edgeport_serial *serial, __u8 *buffer)
+ status = ValidChecksum(rom_desc, buffer);
+
+ desc = (struct edge_ti_manuf_descriptor *)buffer;
+- dbg ( "%s - IonConfig 0x%x", __FUNCTION__, desc->IonConfig );
+- dbg ( "%s - Version %d", __FUNCTION__, desc->Version );
+- dbg ( "%s - Cpu/Board 0x%x", __FUNCTION__, desc->CpuRev_BoardRev );
+- dbg ( "%s - NumPorts %d", __FUNCTION__, desc->NumPorts );
+- dbg ( "%s - NumVirtualPorts %d", __FUNCTION__, desc->NumVirtualPorts );
+- dbg ( "%s - TotalPorts %d", __FUNCTION__, desc->TotalPorts );
++ dbg ( "%s - IonConfig 0x%x", __func__, desc->IonConfig );
++ dbg ( "%s - Version %d", __func__, desc->Version );
++ dbg ( "%s - Cpu/Board 0x%x", __func__, desc->CpuRev_BoardRev );
++ dbg ( "%s - NumPorts %d", __func__, desc->NumPorts );
++ dbg ( "%s - NumVirtualPorts %d", __func__, desc->NumVirtualPorts );
++ dbg ( "%s - TotalPorts %d", __func__, desc->TotalPorts );
+
+ exit:
+ kfree (rom_desc);
+@@ -903,7 +902,7 @@ static int BuildI2CFirmwareHeader (__u8 *header, struct device *dev)
+
+ buffer = kmalloc (buffer_size, GFP_KERNEL);
+ if (!buffer) {
+- dev_err (dev, "%s - out of memory\n", __FUNCTION__);
++ dev_err (dev, "%s - out of memory\n", __func__);
+ return -ENOMEM;
+ }
+
+@@ -956,11 +955,11 @@ static int TIGetI2cTypeInBootMode (struct edgeport_serial *serial)
+ &data, // TransferBuffer
+ 0x01); // TransferBufferLength
+ if (status)
+- dbg ("%s - read 2 status error = %d", __FUNCTION__, status);
++ dbg ("%s - read 2 status error = %d", __func__, status);
+ else
+- dbg ("%s - read 2 data = 0x%x", __FUNCTION__, data);
++ dbg ("%s - read 2 data = 0x%x", __func__, data);
+ if ((!status) && (data == UMP5152 || data == UMP3410)) {
+- dbg ("%s - ROM_TYPE_II", __FUNCTION__);
++ dbg ("%s - ROM_TYPE_II", __func__);
+ serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
+ return 0;
+ }
+@@ -973,16 +972,16 @@ static int TIGetI2cTypeInBootMode (struct edgeport_serial *serial)
+ &data, // TransferBuffer
+ 0x01); // TransferBufferLength
+ if (status)
+- dbg ("%s - read 3 status error = %d", __FUNCTION__, status);
++ dbg ("%s - read 3 status error = %d", __func__, status);
+ else
+- dbg ("%s - read 2 data = 0x%x", __FUNCTION__, data);
++ dbg ("%s - read 2 data = 0x%x", __func__, data);
+ if ((!status) && (data == UMP5152 || data == UMP3410)) {
+- dbg ("%s - ROM_TYPE_III", __FUNCTION__);
++ dbg ("%s - ROM_TYPE_III", __func__);
+ serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_III;
+ return 0;
+ }
+
+- dbg ("%s - Unknown", __FUNCTION__);
++ dbg ("%s - Unknown", __func__);
+ serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
+ return -ENODEV;
+ }
+@@ -1064,7 +1063,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+
+ interface = &serial->serial->interface->cur_altsetting->desc;
+ if (!interface) {
+- dev_err (dev, "%s - no interface set, error!\n", __FUNCTION__);
++ dev_err (dev, "%s - no interface set, error!\n", __func__);
+ return -ENODEV;
+ }
+
+@@ -1087,12 +1086,11 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) {
+ struct ti_i2c_desc *rom_desc;
+
+- dbg ("%s - <<<<<<<<<<<<<<<RUNNING IN DOWNLOAD MODE>>>>>>>>>>", __FUNCTION__);
++ dbg("%s - RUNNING IN DOWNLOAD MODE", __func__);
+
+ status = TiValidateI2cImage (serial);
+ if (status) {
+- dbg ("%s - <<<<<<<<<<<<<<<DOWNLOAD MODE -- BAD I2C >>>>>>>>>>",
+- __FUNCTION__);
++ dbg("%s - DOWNLOAD MODE -- BAD I2C", __func__);
+ return status;
+ }
+
+@@ -1101,7 +1099,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ */
+ ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL);
+ if (!ti_manuf_desc) {
+- dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
++ dev_err (dev, "%s - out of memory.\n", __func__);
+ return -ENOMEM;
+ }
+ status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc);
+@@ -1112,7 +1110,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+
+ // Check version number of ION descriptor
+ if (!ignore_cpu_rev && TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev) < 2) {
+- dbg ( "%s - Wrong CPU Rev %d (Must be 2)", __FUNCTION__,
++ dbg ( "%s - Wrong CPU Rev %d (Must be 2)", __func__,
+ TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev));
+ kfree (ti_manuf_desc);
+ return -EINVAL;
+@@ -1120,7 +1118,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+
+ rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL);
+ if (!rom_desc) {
+- dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
++ dev_err (dev, "%s - out of memory.\n", __func__);
+ kfree (ti_manuf_desc);
+ return -ENOMEM;
+ }
+@@ -1130,11 +1128,11 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ struct ti_i2c_firmware_rec *firmware_version;
+ __u8 record;
+
+- dbg ("%s - Found Type FIRMWARE (Type 2) record", __FUNCTION__);
++ dbg ("%s - Found Type FIRMWARE (Type 2) record", __func__);
+
+ firmware_version = kmalloc (sizeof (*firmware_version), GFP_KERNEL);
+ if (!firmware_version) {
+- dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
++ dev_err (dev, "%s - out of memory.\n", __func__);
+ kfree (rom_desc);
+ kfree (ti_manuf_desc);
+ return -ENOMEM;
+@@ -1160,7 +1158,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ (OperationalCodeImageVersion.MinorVersion);
+
+ dbg ("%s - >>>Firmware Versions Device %d.%d Driver %d.%d",
+- __FUNCTION__,
++ __func__,
+ firmware_version->Ver_Major,
+ firmware_version->Ver_Minor,
+ OperationalCodeImageVersion.MajorVersion,
+@@ -1169,7 +1167,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ // Check if we have an old version in the I2C and update if necessary
+ if (download_cur_ver != download_new_ver) {
+ dbg ("%s - Update I2C Download from %d.%d to %d.%d",
+- __FUNCTION__,
++ __func__,
+ firmware_version->Ver_Major,
+ firmware_version->Ver_Minor,
+ OperationalCodeImageVersion.MajorVersion,
+@@ -1211,14 +1209,14 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ }
+
+ if (record != I2C_DESC_TYPE_FIRMWARE_BLANK) {
+- dev_err (dev, "%s - error resetting device\n", __FUNCTION__);
++ dev_err (dev, "%s - error resetting device\n", __func__);
+ kfree (firmware_version);
+ kfree (rom_desc);
+ kfree (ti_manuf_desc);
+ return -ENODEV;
+ }
+
+- dbg ("%s - HARDWARE RESET", __FUNCTION__);
++ dbg ("%s - HARDWARE RESET", __func__);
+
+ // Reset UMP -- Back to BOOT MODE
+ status = TISendVendorRequestSync (serial->serial->dev,
+@@ -1228,7 +1226,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ NULL, // TransferBuffer
+ 0); // TransferBufferLength
+
+- dbg ( "%s - HARDWARE RESET return %d", __FUNCTION__, status);
++ dbg ( "%s - HARDWARE RESET return %d", __func__, status);
+
+ /* return an error on purpose. */
+ kfree (firmware_version);
+@@ -1246,7 +1244,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+
+ header = kmalloc (HEADER_SIZE, GFP_KERNEL);
+ if (!header) {
+- dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
++ dev_err (dev, "%s - out of memory.\n", __func__);
+ kfree (rom_desc);
+ kfree (ti_manuf_desc);
+ return -ENOMEM;
+@@ -1254,14 +1252,14 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+
+ vheader = kmalloc (HEADER_SIZE, GFP_KERNEL);
+ if (!vheader) {
+- dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
++ dev_err (dev, "%s - out of memory.\n", __func__);
+ kfree (header);
+ kfree (rom_desc);
+ kfree (ti_manuf_desc);
+ return -ENOMEM;
+ }
+
+- dbg ("%s - Found Type BLANK FIRMWARE (Type F2) record", __FUNCTION__);
++ dbg ("%s - Found Type BLANK FIRMWARE (Type F2) record", __func__);
+
+ // In order to update the I2C firmware we must change the type 2 record to type 0xF2.
+ // This will force the UMP to come up in Boot Mode. Then while in boot mode, the driver
+@@ -1299,7 +1297,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ vheader);
+
+ if (status) {
+- dbg ("%s - can't read header back", __FUNCTION__);
++ dbg ("%s - can't read header back", __func__);
+ kfree (vheader);
+ kfree (header);
+ kfree (rom_desc);
+@@ -1307,7 +1305,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ return status;
+ }
+ if (memcmp(vheader, header, HEADER_SIZE)) {
+- dbg ("%s - write download record failed", __FUNCTION__);
++ dbg ("%s - write download record failed", __func__);
+ kfree (vheader);
+ kfree (header);
+ kfree (rom_desc);
+@@ -1318,7 +1316,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ kfree (vheader);
+ kfree (header);
+
+- dbg ("%s - Start firmware update", __FUNCTION__);
++ dbg ("%s - Start firmware update", __func__);
+
+ // Tell firmware to copy download image into I2C
+ status = TISendVendorRequestSync (serial->serial->dev,
+@@ -1328,9 +1326,9 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ NULL, // TransferBuffer
+ 0); // TransferBufferLength
+
+- dbg ("%s - Update complete 0x%x", __FUNCTION__, status);
++ dbg ("%s - Update complete 0x%x", __func__, status);
+ if (status) {
+- dev_err (dev, "%s - UMPC_COPY_DNLD_TO_I2C failed\n", __FUNCTION__);
++ dev_err (dev, "%s - UMPC_COPY_DNLD_TO_I2C failed\n", __func__);
+ kfree (rom_desc);
+ kfree (ti_manuf_desc);
+ return status;
+@@ -1346,8 +1344,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ /********************************************************************/
+ /* Boot Mode */
+ /********************************************************************/
+- dbg ("%s - <<<<<<<<<<<<<<<RUNNING IN BOOT MODE>>>>>>>>>>>>>>>",
+- __FUNCTION__);
++ dbg("%s - RUNNING IN BOOT MODE", __func__);
+
+ // Configure the TI device so we can use the BULK pipes for download
+ status = TIConfigureBootDevice (serial->serial->dev);
+@@ -1355,7 +1352,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ return status;
+
+ if (le16_to_cpu(serial->serial->dev->descriptor.idVendor) != USB_VENDOR_ID_ION) {
+- dbg ("%s - VID = 0x%x", __FUNCTION__,
++ dbg ("%s - VID = 0x%x", __func__,
+ le16_to_cpu(serial->serial->dev->descriptor.idVendor));
+ serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
+ goto StayInBootMode;
+@@ -1369,7 +1366,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+
+ // Registry variable set?
+ if (TIStayInBootMode) {
+- dbg ("%s - TIStayInBootMode", __FUNCTION__);
++ dbg ("%s - TIStayInBootMode", __func__);
+ goto StayInBootMode;
+ }
+
+@@ -1386,7 +1383,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ */
+ ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL);
+ if (!ti_manuf_desc) {
+- dev_err (dev, "%s - out of memory.\n", __FUNCTION__);
++ dev_err (dev, "%s - out of memory.\n", __func__);
+ return -ENOMEM;
+ }
+ status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc);
+@@ -1397,7 +1394,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+
+ // Check for version 2
+ if (!ignore_cpu_rev && TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev) < 2) {
+- dbg ("%s - Wrong CPU Rev %d (Must be 2)", __FUNCTION__,
++ dbg ("%s - Wrong CPU Rev %d (Must be 2)", __func__,
+ TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev));
+ kfree (ti_manuf_desc);
+ goto StayInBootMode;
+@@ -1421,7 +1418,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ buffer_size = (((1024 * 16) - 512) + sizeof(struct ti_i2c_image_header));
+ buffer = kmalloc (buffer_size, GFP_KERNEL);
+ if (!buffer) {
+- dev_err (dev, "%s - out of memory\n", __FUNCTION__);
++ dev_err (dev, "%s - out of memory\n", __func__);
+ return -ENOMEM;
+ }
+
+@@ -1441,20 +1438,20 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+ header->CheckSum = cs;
+
+ // Download the operational code
+- dbg ("%s - Downloading operational code image (TI UMP)", __FUNCTION__);
++ dbg ("%s - Downloading operational code image (TI UMP)", __func__);
+ status = TIDownloadCodeImage (serial, buffer, buffer_size);
+
+ kfree (buffer);
+
+ if (status) {
+- dbg ("%s - Error downloading operational code image", __FUNCTION__);
++ dbg ("%s - Error downloading operational code image", __func__);
+ return status;
+ }
+
+ // Device will reboot
+ serial->product_info.TiMode = TI_MODE_TRANSITIONING;
+
+- dbg ("%s - Download successful -- Device rebooting...", __FUNCTION__);
++ dbg ("%s - Download successful -- Device rebooting...", __func__);
+
+ /* return an error on purpose */
+ return -ENODEV;
+@@ -1462,7 +1459,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
+
+ StayInBootMode:
+ // Eprom is invalid or blank stay in boot mode
+- dbg ("%s - <<<<<<<<<<<<<<<STAYING IN BOOT MODE>>>>>>>>>>>>", __FUNCTION__);
++ dbg("%s - STAYING IN BOOT MODE", __func__);
+ serial->product_info.TiMode = TI_MODE_BOOT;
+
+ return 0;
+@@ -1473,7 +1470,7 @@ static int TISetDtr (struct edgeport_port *port)
+ {
+ int port_number = port->port->number - port->port->serial->minor;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+ port->shadow_mcr |= MCR_DTR;
+
+ return TIWriteCommandSync (port->port->serial->dev,
+@@ -1488,7 +1485,7 @@ static int TIClearDtr (struct edgeport_port *port)
+ {
+ int port_number = port->port->number - port->port->serial->minor;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+ port->shadow_mcr &= ~MCR_DTR;
+
+ return TIWriteCommandSync (port->port->serial->dev,
+@@ -1503,7 +1500,7 @@ static int TISetRts (struct edgeport_port *port)
+ {
+ int port_number = port->port->number - port->port->serial->minor;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+ port->shadow_mcr |= MCR_RTS;
+
+ return TIWriteCommandSync (port->port->serial->dev,
+@@ -1518,7 +1515,7 @@ static int TIClearRts (struct edgeport_port *port)
+ {
+ int port_number = port->port->number - port->port->serial->minor;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+ port->shadow_mcr &= ~MCR_RTS;
+
+ return TIWriteCommandSync (port->port->serial->dev,
+@@ -1533,7 +1530,7 @@ static int TISetLoopBack (struct edgeport_port *port)
+ {
+ int port_number = port->port->number - port->port->serial->minor;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+ return TIWriteCommandSync (port->port->serial->dev,
+ UMPC_SET_CLR_LOOPBACK,
+@@ -1547,7 +1544,7 @@ static int TIClearLoopBack (struct edgeport_port *port)
+ {
+ int port_number = port->port->number - port->port->serial->minor;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+ return TIWriteCommandSync (port->port->serial->dev,
+ UMPC_SET_CLR_LOOPBACK,
+@@ -1561,7 +1558,7 @@ static int TISetBreak (struct edgeport_port *port)
+ {
+ int port_number = port->port->number - port->port->serial->minor;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+ return TIWriteCommandSync (port->port->serial->dev,
+ UMPC_SET_CLR_BREAK,
+@@ -1575,7 +1572,7 @@ static int TIClearBreak (struct edgeport_port *port)
+ {
+ int port_number = port->port->number - port->port->serial->minor;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+ return TIWriteCommandSync (port->port->serial->dev,
+ UMPC_SET_CLR_BREAK,
+@@ -1589,7 +1586,7 @@ static int TIRestoreMCR (struct edgeport_port *port, __u8 mcr)
+ {
+ int status = 0;
+
+- dbg ("%s - %x", __FUNCTION__, mcr);
++ dbg ("%s - %x", __func__, mcr);
+
+ if (mcr & MCR_DTR)
+ status = TISetDtr (port);
+@@ -1643,7 +1640,7 @@ static void handle_new_msr (struct edgeport_port *edge_port, __u8 msr)
+ struct async_icount *icount;
+ struct tty_struct *tty;
+
+- dbg ("%s - %02x", __FUNCTION__, msr);
++ dbg ("%s - %02x", __func__, msr);
+
+ if (msr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
+ icount = &edge_port->icount;
+@@ -1682,7 +1679,7 @@ static void handle_new_lsr (struct edgeport_port *edge_port, int lsr_data, __u8
+ struct async_icount *icount;
+ __u8 new_lsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK));
+
+- dbg ("%s - %02x", __FUNCTION__, new_lsr);
++ dbg ("%s - %02x", __func__, new_lsr);
+
+ edge_port->shadow_lsr = lsr;
+
+@@ -1713,7 +1710,7 @@ static void handle_new_lsr (struct edgeport_port *edge_port, int lsr_data, __u8
+
+ static void edge_interrupt_callback (struct urb *urb)
+ {
+- struct edgeport_serial *edge_serial = (struct edgeport_serial *)urb->context;
++ struct edgeport_serial *edge_serial = urb->context;
+ struct usb_serial_port *port;
+ struct edgeport_port *edge_port;
+ unsigned char *data = urb->transfer_buffer;
+@@ -1725,7 +1722,7 @@ static void edge_interrupt_callback (struct urb *urb)
+ __u8 msr;
+ int status = urb->status;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ switch (status) {
+ case 0:
+@@ -1736,34 +1733,34 @@ static void edge_interrupt_callback (struct urb *urb)
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ default:
+ dev_err(&urb->dev->dev, "%s - nonzero urb status received: "
+- "%d\n", __FUNCTION__, status);
++ "%d\n", __func__, status);
+ goto exit;
+ }
+
+ if (!length) {
+- dbg ("%s - no data in urb", __FUNCTION__);
++ dbg ("%s - no data in urb", __func__);
+ goto exit;
+ }
+
+- usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __FUNCTION__, length, data);
++ usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __func__, length, data);
+
+ if (length != 2) {
+- dbg ("%s - expecting packet of size 2, got %d", __FUNCTION__, length);
++ dbg ("%s - expecting packet of size 2, got %d", __func__, length);
+ goto exit;
+ }
+
+ port_number = TIUMP_GET_PORT_FROM_CODE (data[0]);
+ function = TIUMP_GET_FUNC_FROM_CODE (data[0]);
+ dbg ("%s - port_number %d, function %d, info 0x%x",
+- __FUNCTION__, port_number, function, data[1]);
++ __func__, port_number, function, data[1]);
+ port = edge_serial->serial->port[port_number];
+ edge_port = usb_get_serial_port_data(port);
+ if (!edge_port) {
+- dbg ("%s - edge_port not found", __FUNCTION__);
++ dbg ("%s - edge_port not found", __func__);
+ return;
+ }
+ switch (function) {
+@@ -1772,12 +1769,12 @@ static void edge_interrupt_callback (struct urb *urb)
+ if (lsr & UMP_UART_LSR_DATA_MASK) {
+ /* Save the LSR event for bulk read completion routine */
+ dbg ("%s - LSR Event Port %u LSR Status = %02x",
+- __FUNCTION__, port_number, lsr);
++ __func__, port_number, lsr);
+ edge_port->lsr_event = 1;
+ edge_port->lsr_mask = lsr;
+ } else {
+ dbg ("%s - ===== Port %d LSR Status = %02x ======",
+- __FUNCTION__, port_number, lsr);
++ __func__, port_number, lsr);
+ handle_new_lsr (edge_port, 0, lsr, 0);
+ }
+ break;
+@@ -1786,13 +1783,13 @@ static void edge_interrupt_callback (struct urb *urb)
+ /* Copy MSR from UMP */
+ msr = data[1];
+ dbg ("%s - ===== Port %u MSR Status = %02x ======\n",
+- __FUNCTION__, port_number, msr);
++ __func__, port_number, msr);
+ handle_new_msr (edge_port, msr);
+ break;
+
+ default:
+ dev_err (&urb->dev->dev, "%s - Unknown Interrupt code from UMP %x\n",
+- __FUNCTION__, data[1]);
++ __func__, data[1]);
+ break;
+
+ }
+@@ -1801,19 +1798,19 @@ exit:
+ retval = usb_submit_urb (urb, GFP_ATOMIC);
+ if (retval)
+ dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n",
+- __FUNCTION__, retval);
++ __func__, retval);
+ }
+
+ static void edge_bulk_in_callback (struct urb *urb)
+ {
+- struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;
++ struct edgeport_port *edge_port = urb->context;
+ unsigned char *data = urb->transfer_buffer;
+ struct tty_struct *tty;
+ int retval = 0;
+ int port_number;
+ int status = urb->status;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ switch (status) {
+ case 0:
+@@ -1824,18 +1821,18 @@ static void edge_bulk_in_callback (struct urb *urb)
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ default:
+ dev_err (&urb->dev->dev,"%s - nonzero read bulk status received: %d\n",
+- __FUNCTION__, status);
++ __func__, status);
+ }
+
+ if (status == -EPIPE)
+ goto exit;
+
+ if (status) {
+- dev_err(&urb->dev->dev,"%s - stopping read!\n", __FUNCTION__);
++ dev_err(&urb->dev->dev,"%s - stopping read!\n", __func__);
+ return;
+ }
+
+@@ -1844,7 +1841,7 @@ static void edge_bulk_in_callback (struct urb *urb)
+ if (edge_port->lsr_event) {
+ edge_port->lsr_event = 0;
+ dbg ("%s ===== Port %u LSR Status = %02x, Data = %02x ======",
+- __FUNCTION__, port_number, edge_port->lsr_mask, *data);
++ __func__, port_number, edge_port->lsr_mask, *data);
+ handle_new_lsr (edge_port, 1, edge_port->lsr_mask, *data);
+ /* Adjust buffer length/pointer */
+ --urb->actual_length;
+@@ -1853,10 +1850,10 @@ static void edge_bulk_in_callback (struct urb *urb)
+
+ tty = edge_port->port->tty;
+ if (tty && urb->actual_length) {
+- usb_serial_debug_data(debug, &edge_port->port->dev, __FUNCTION__, urb->actual_length, data);
++ usb_serial_debug_data(debug, &edge_port->port->dev, __func__, urb->actual_length, data);
+
+ if (edge_port->close_pending) {
+- dbg ("%s - close is pending, dropping data on the floor.", __FUNCTION__);
++ dbg ("%s - close is pending, dropping data on the floor.", __func__);
+ } else {
+ edge_tty_recv(&edge_port->port->dev, tty, data, urb->actual_length);
+ }
+@@ -1875,7 +1872,7 @@ exit:
+ spin_unlock(&edge_port->ep_lock);
+ if (retval)
+ dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n",
+- __FUNCTION__, retval);
++ __func__, retval);
+ }
+
+ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length)
+@@ -1886,7 +1883,7 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c
+ cnt = tty_buffer_request_room(tty, length);
+ if (cnt < length) {
+ dev_err(dev, "%s - dropping data, %d bytes lost\n",
+- __FUNCTION__, length - cnt);
++ __func__, length - cnt);
+ if(cnt == 0)
+ break;
+ }
+@@ -1900,11 +1897,11 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c
+
+ static void edge_bulk_out_callback (struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+ int status = urb->status;
+
+- dbg ("%s - port %d", __FUNCTION__, port->number);
++ dbg ("%s - port %d", __func__, port->number);
+
+ edge_port->ep_write_urb_in_use = 0;
+
+@@ -1917,11 +1914,11 @@ static void edge_bulk_out_callback (struct urb *urb)
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ default:
+ dev_err(&urb->dev->dev, "%s - nonzero write bulk status "
+- "received: %d\n", __FUNCTION__, status);
++ "received: %d\n", __func__, status);
+ }
+
+ /* send any buffered data */
+@@ -1939,13 +1936,12 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ u16 open_settings;
+ u8 transaction_timeout;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (edge_port == NULL)
+ return -ENODEV;
+
+- if (port->tty)
+- port->tty->low_latency = low_latency;
++ port->tty->low_latency = low_latency;
+
+ port_number = port->number - port->serial->minor;
+ switch (port_number) {
+@@ -1963,7 +1959,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ }
+
+ dbg ("%s - port_number = %d, uart_base = %04x, dma_address = %04x",
+- __FUNCTION__, port_number, edge_port->uart_base, edge_port->dma_address);
++ __func__, port_number, edge_port->uart_base, edge_port->dma_address);
+
+ dev = port->serial->dev;
+
+@@ -1974,7 +1970,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ status = TIClearLoopBack (edge_port);
+ if (status) {
+ dev_err(&port->dev,"%s - cannot send clear loopback command, %d\n",
+- __FUNCTION__, status);
++ __func__, status);
+ return status;
+ }
+
+@@ -1993,7 +1989,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ UMP_PIPE_TRANS_TIMEOUT_ENA |
+ (transaction_timeout << 2));
+
+- dbg ("%s - Sending UMPC_OPEN_PORT", __FUNCTION__);
++ dbg ("%s - Sending UMPC_OPEN_PORT", __func__);
+
+ /* Tell TI to open and start the port */
+ status = TIWriteCommandSync (dev,
+@@ -2003,7 +1999,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ NULL,
+ 0);
+ if (status) {
+- dev_err(&port->dev,"%s - cannot send open command, %d\n", __FUNCTION__, status);
++ dev_err(&port->dev,"%s - cannot send open command, %d\n", __func__, status);
+ return status;
+ }
+
+@@ -2015,14 +2011,14 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ NULL,
+ 0);
+ if (status) {
+- dev_err(&port->dev,"%s - cannot send start DMA command, %d\n", __FUNCTION__, status);
++ dev_err(&port->dev,"%s - cannot send start DMA command, %d\n", __func__, status);
+ return status;
+ }
+
+ /* Clear TX and RX buffers in UMP */
+ status = TIPurgeDataSync (port, UMP_PORT_DIR_OUT | UMP_PORT_DIR_IN);
+ if (status) {
+- dev_err(&port->dev,"%s - cannot send clear buffers command, %d\n", __FUNCTION__, status);
++ dev_err(&port->dev,"%s - cannot send clear buffers command, %d\n", __func__, status);
+ return status;
+ }
+
+@@ -2034,7 +2030,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ &edge_port->shadow_msr, // TransferBuffer
+ 1); // TransferBufferLength
+ if (status) {
+- dev_err(&port->dev,"%s - cannot send read MSR command, %d\n", __FUNCTION__, status);
++ dev_err(&port->dev,"%s - cannot send read MSR command, %d\n", __func__, status);
+ return status;
+ }
+
+@@ -2051,7 +2047,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ /* we are the first port to be opened, let's post the interrupt urb */
+ urb = edge_serial->serial->port[0]->interrupt_in_urb;
+ if (!urb) {
+- dev_err (&port->dev, "%s - no interrupt urb present, exiting\n", __FUNCTION__);
++ dev_err (&port->dev, "%s - no interrupt urb present, exiting\n", __func__);
+ status = -EINVAL;
+ goto release_es_lock;
+ }
+@@ -2060,7 +2056,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ urb->dev = dev;
+ status = usb_submit_urb (urb, GFP_KERNEL);
+ if (status) {
+- dev_err (&port->dev, "%s - usb_submit_urb failed with value %d\n", __FUNCTION__, status);
++ dev_err (&port->dev, "%s - usb_submit_urb failed with value %d\n", __func__, status);
+ goto release_es_lock;
+ }
+ }
+@@ -2075,7 +2071,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ /* start up our bulk read urb */
+ urb = port->read_urb;
+ if (!urb) {
+- dev_err (&port->dev, "%s - no read urb present, exiting\n", __FUNCTION__);
++ dev_err (&port->dev, "%s - no read urb present, exiting\n", __func__);
+ status = -EINVAL;
+ goto unlink_int_urb;
+ }
+@@ -2085,13 +2081,13 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
+ urb->dev = dev;
+ status = usb_submit_urb (urb, GFP_KERNEL);
+ if (status) {
+- dev_err (&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __FUNCTION__, status);
++ dev_err (&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __func__, status);
+ goto unlink_int_urb;
+ }
+
+ ++edge_serial->num_ports_open;
+
+- dbg("%s - exited", __FUNCTION__);
++ dbg("%s - exited", __func__);
+
+ goto release_es_lock;
+
+@@ -2110,7 +2106,7 @@ static void edge_close (struct usb_serial_port *port, struct file *filp)
+ int port_number;
+ int status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ edge_serial = usb_get_serial_data(port->serial);
+ edge_port = usb_get_serial_port_data(port);
+@@ -2130,7 +2126,7 @@ static void edge_close (struct usb_serial_port *port, struct file *filp)
+
+ /* assuming we can still talk to the device,
+ * send a close port command to it */
+- dbg("%s - send umpc_close_port", __FUNCTION__);
++ dbg("%s - send umpc_close_port", __func__);
+ port_number = port->number - port->serial->minor;
+ status = TIWriteCommandSync (port->serial->dev,
+ UMPC_CLOSE_PORT,
+@@ -2148,7 +2144,7 @@ static void edge_close (struct usb_serial_port *port, struct file *filp)
+ mutex_unlock(&edge_serial->es_lock);
+ edge_port->close_pending = 0;
+
+- dbg("%s - exited", __FUNCTION__);
++ dbg("%s - exited", __func__);
+ }
+
+ static int edge_write (struct usb_serial_port *port, const unsigned char *data, int count)
+@@ -2156,10 +2152,10 @@ static int edge_write (struct usb_serial_port *port, const unsigned char *data,
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (count == 0) {
+- dbg("%s - write request of 0 bytes", __FUNCTION__);
++ dbg("%s - write request of 0 bytes", __func__);
+ return 0;
+ }
+
+@@ -2185,7 +2181,7 @@ static void edge_send(struct usb_serial_port *port)
+ unsigned long flags;
+
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&edge_port->ep_lock, flags);
+
+@@ -2207,7 +2203,7 @@ static void edge_send(struct usb_serial_port *port)
+
+ spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer);
++ usb_serial_debug_data(debug, &port->dev, __func__, count, port->write_urb->transfer_buffer);
+
+ /* set up our urb */
+ usb_fill_bulk_urb (port->write_urb, port->serial->dev,
+@@ -2220,7 +2216,7 @@ static void edge_send(struct usb_serial_port *port)
+ /* send the data out the bulk port */
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ if (result) {
+- dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
++ dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result);
+ edge_port->ep_write_urb_in_use = 0;
+ // TODO: reschedule edge_send
+ } else {
+@@ -2241,7 +2237,7 @@ static int edge_write_room (struct usb_serial_port *port)
+ int room = 0;
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (edge_port == NULL)
+ return -ENODEV;
+@@ -2252,7 +2248,7 @@ static int edge_write_room (struct usb_serial_port *port)
+ room = edge_buf_space_avail(edge_port->ep_out_buf);
+ spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+
+- dbg("%s - returns %d", __FUNCTION__, room);
++ dbg("%s - returns %d", __func__, room);
+ return room;
+ }
+
+@@ -2262,7 +2258,7 @@ static int edge_chars_in_buffer (struct usb_serial_port *port)
+ int chars = 0;
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (edge_port == NULL)
+ return -ENODEV;
+@@ -2273,7 +2269,7 @@ static int edge_chars_in_buffer (struct usb_serial_port *port)
+ chars = edge_buf_data_avail(edge_port->ep_out_buf);
+ spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+
+- dbg ("%s - returns %d", __FUNCTION__, chars);
++ dbg ("%s - returns %d", __func__, chars);
+ return chars;
+ }
+
+@@ -2283,14 +2279,14 @@ static void edge_throttle (struct usb_serial_port *port)
+ struct tty_struct *tty;
+ int status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (edge_port == NULL)
+ return;
+
+ tty = port->tty;
+ if (!tty) {
+- dbg ("%s - no tty available", __FUNCTION__);
++ dbg ("%s - no tty available", __func__);
+ return;
+ }
+
+@@ -2299,7 +2295,7 @@ static void edge_throttle (struct usb_serial_port *port)
+ unsigned char stop_char = STOP_CHAR(tty);
+ status = edge_write (port, &stop_char, 1);
+ if (status <= 0) {
+- dev_err(&port->dev, "%s - failed to write stop character, %d\n", __FUNCTION__, status);
++ dev_err(&port->dev, "%s - failed to write stop character, %d\n", __func__, status);
+ }
+ }
+
+@@ -2316,14 +2312,14 @@ static void edge_unthrottle (struct usb_serial_port *port)
+ struct tty_struct *tty;
+ int status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (edge_port == NULL)
+ return;
+
+ tty = port->tty;
+ if (!tty) {
+- dbg ("%s - no tty available", __FUNCTION__);
++ dbg ("%s - no tty available", __func__);
+ return;
+ }
+
+@@ -2332,7 +2328,7 @@ static void edge_unthrottle (struct usb_serial_port *port)
+ unsigned char start_char = START_CHAR(tty);
+ status = edge_write (port, &start_char, 1);
+ if (status <= 0) {
+- dev_err(&port->dev, "%s - failed to write start character, %d\n", __FUNCTION__, status);
++ dev_err(&port->dev, "%s - failed to write start character, %d\n", __func__, status);
+ }
+ }
+
+@@ -2341,7 +2337,7 @@ static void edge_unthrottle (struct usb_serial_port *port)
+ if (C_CRTSCTS(tty)) {
+ status = restart_read(edge_port);
+ if (status)
+- dev_err(&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __FUNCTION__, status);
++ dev_err(&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __func__, status);
+ }
+
+ }
+@@ -2391,13 +2387,13 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
+ int status;
+ int port_number = edge_port->port->number - edge_port->port->serial->minor;
+
+- dbg("%s - port %d", __FUNCTION__, edge_port->port->number);
++ dbg("%s - port %d", __func__, edge_port->port->number);
+
+ tty = edge_port->port->tty;
+
+ config = kmalloc (sizeof (*config), GFP_KERNEL);
+ if (!config) {
+- dev_err (&edge_port->port->dev, "%s - out of memory\n", __FUNCTION__);
++ dev_err (&edge_port->port->dev, "%s - out of memory\n", __func__);
+ return;
+ }
+
+@@ -2413,20 +2409,20 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
+ switch (cflag & CSIZE) {
+ case CS5:
+ config->bDataBits = UMP_UART_CHAR5BITS;
+- dbg ("%s - data bits = 5", __FUNCTION__);
++ dbg ("%s - data bits = 5", __func__);
+ break;
+ case CS6:
+ config->bDataBits = UMP_UART_CHAR6BITS;
+- dbg ("%s - data bits = 6", __FUNCTION__);
++ dbg ("%s - data bits = 6", __func__);
+ break;
+ case CS7:
+ config->bDataBits = UMP_UART_CHAR7BITS;
+- dbg ("%s - data bits = 7", __FUNCTION__);
++ dbg ("%s - data bits = 7", __func__);
+ break;
+ default:
+ case CS8:
+ config->bDataBits = UMP_UART_CHAR8BITS;
+- dbg ("%s - data bits = 8", __FUNCTION__);
++ dbg ("%s - data bits = 8", __func__);
+ break;
+ }
+
+@@ -2434,32 +2430,32 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
+ if (cflag & PARODD) {
+ config->wFlags |= UMP_MASK_UART_FLAGS_PARITY;
+ config->bParity = UMP_UART_ODDPARITY;
+- dbg("%s - parity = odd", __FUNCTION__);
++ dbg("%s - parity = odd", __func__);
+ } else {
+ config->wFlags |= UMP_MASK_UART_FLAGS_PARITY;
+ config->bParity = UMP_UART_EVENPARITY;
+- dbg("%s - parity = even", __FUNCTION__);
++ dbg("%s - parity = even", __func__);
+ }
+ } else {
+ config->bParity = UMP_UART_NOPARITY;
+- dbg("%s - parity = none", __FUNCTION__);
++ dbg("%s - parity = none", __func__);
+ }
+
+ if (cflag & CSTOPB) {
+ config->bStopBits = UMP_UART_STOPBIT2;
+- dbg("%s - stop bits = 2", __FUNCTION__);
++ dbg("%s - stop bits = 2", __func__);
+ } else {
+ config->bStopBits = UMP_UART_STOPBIT1;
+- dbg("%s - stop bits = 1", __FUNCTION__);
++ dbg("%s - stop bits = 1", __func__);
+ }
+
+ /* figure out the flow control settings */
+ if (cflag & CRTSCTS) {
+ config->wFlags |= UMP_MASK_UART_FLAGS_OUT_X_CTS_FLOW;
+ config->wFlags |= UMP_MASK_UART_FLAGS_RTS_FLOW;
+- dbg("%s - RTS/CTS is enabled", __FUNCTION__);
++ dbg("%s - RTS/CTS is enabled", __func__);
+ } else {
+- dbg("%s - RTS/CTS is disabled", __FUNCTION__);
++ dbg("%s - RTS/CTS is disabled", __func__);
+ tty->hw_stopped = 0;
+ restart_read(edge_port);
+ }
+@@ -2473,18 +2469,18 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
+ if (I_IXOFF(tty)) {
+ config->wFlags |= UMP_MASK_UART_FLAGS_IN_X;
+ dbg ("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
+- __FUNCTION__, config->cXon, config->cXoff);
++ __func__, config->cXon, config->cXoff);
+ } else {
+- dbg ("%s - INBOUND XON/XOFF is disabled", __FUNCTION__);
++ dbg ("%s - INBOUND XON/XOFF is disabled", __func__);
+ }
+
+ /* if we are implementing OUTBOUND XON/XOFF */
+ if (I_IXON(tty)) {
+ config->wFlags |= UMP_MASK_UART_FLAGS_OUT_X;
+ dbg ("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
+- __FUNCTION__, config->cXon, config->cXoff);
++ __func__, config->cXon, config->cXoff);
+ } else {
+- dbg ("%s - OUTBOUND XON/XOFF is disabled", __FUNCTION__);
++ dbg ("%s - OUTBOUND XON/XOFF is disabled", __func__);
+ }
+ }
+
+@@ -2503,7 +2499,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
+
+ /* FIXME: Recompute actual baud from divisor here */
+
+- dbg ("%s - baud rate = %d, wBaudRate = %d", __FUNCTION__, baud, config->wBaudRate);
++ dbg ("%s - baud rate = %d, wBaudRate = %d", __func__, baud, config->wBaudRate);
+
+ dbg ("wBaudRate: %d", (int)(461550L / config->wBaudRate));
+ dbg ("wFlags: 0x%x", config->wFlags);
+@@ -2526,7 +2522,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
+ sizeof(*config));
+ if (status) {
+ dbg ("%s - error %d when trying to write config to device",
+- __FUNCTION__, status);
++ __func__, status);
+ }
+
+ kfree (config);
+@@ -2542,12 +2538,12 @@ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old
+
+ cflag = tty->termios->c_cflag;
+
+- dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
++ dbg("%s - clfag %08x iflag %08x", __func__,
+ tty->termios->c_cflag, tty->termios->c_iflag);
+- dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
++ dbg("%s - old clfag %08x old iflag %08x", __func__,
+ old_termios->c_cflag, old_termios->c_iflag);
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (edge_port == NULL)
+ return;
+@@ -2562,9 +2558,11 @@ static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsig
+ {
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+ unsigned int mcr;
++ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
++ spin_lock_irqsave(&edge_port->ep_lock, flags);
+ mcr = edge_port->shadow_mcr;
+ if (set & TIOCM_RTS)
+ mcr |= MCR_RTS;
+@@ -2581,6 +2579,7 @@ static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsig
+ mcr &= ~MCR_LOOPBACK;
+
+ edge_port->shadow_mcr = mcr;
++ spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+
+ TIRestoreMCR (edge_port, mcr);
+
+@@ -2593,8 +2592,11 @@ static int edge_tiocmget(struct usb_serial_port *port, struct file *file)
+ unsigned int result = 0;
+ unsigned int msr;
+ unsigned int mcr;
++ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
++
++ spin_lock_irqsave(&edge_port->ep_lock, flags);
+
+ msr = edge_port->shadow_msr;
+ mcr = edge_port->shadow_mcr;
+@@ -2606,7 +2608,8 @@ static int edge_tiocmget(struct usb_serial_port *port, struct file *file)
+ | ((msr & EDGEPORT_MSR_DSR) ? TIOCM_DSR: 0); /* 0x100 */
+
+
+- dbg("%s -- %x", __FUNCTION__, result);
++ dbg("%s -- %x", __func__, result);
++ spin_unlock_irqrestore(&edge_port->ep_lock, flags);
+
+ return result;
+ }
+@@ -2645,30 +2648,30 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned
+ struct async_icount cnow;
+ struct async_icount cprev;
+
+- dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
++ dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
+
+ switch (cmd) {
+ case TIOCINQ:
+- dbg("%s - (%d) TIOCINQ", __FUNCTION__, port->number);
++ dbg("%s - (%d) TIOCINQ", __func__, port->number);
+ // return get_number_bytes_avail(edge_port, (unsigned int *) arg);
+ break;
+
+ case TIOCSERGETLSR:
+- dbg("%s - (%d) TIOCSERGETLSR", __FUNCTION__, port->number);
++ dbg("%s - (%d) TIOCSERGETLSR", __func__, port->number);
+ // return get_lsr_info(edge_port, (unsigned int *) arg);
+ break;
+
+ case TIOCGSERIAL:
+- dbg("%s - (%d) TIOCGSERIAL", __FUNCTION__, port->number);
++ dbg("%s - (%d) TIOCGSERIAL", __func__, port->number);
+ return get_serial_info(edge_port, (struct serial_struct __user *) arg);
+ break;
+
+ case TIOCSSERIAL:
+- dbg("%s - (%d) TIOCSSERIAL", __FUNCTION__, port->number);
++ dbg("%s - (%d) TIOCSSERIAL", __func__, port->number);
+ break;
+
+ case TIOCMIWAIT:
+- dbg("%s - (%d) TIOCMIWAIT", __FUNCTION__, port->number);
++ dbg("%s - (%d) TIOCMIWAIT", __func__, port->number);
+ cprev = edge_port->icount;
+ while (1) {
+ interruptible_sleep_on(&edge_port->delta_msr_wait);
+@@ -2691,7 +2694,7 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned
+ break;
+
+ case TIOCGICOUNT:
+- dbg ("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__,
++ dbg ("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
+ port->number, edge_port->icount.rx, edge_port->icount.tx);
+ if (copy_to_user((void __user *)arg, &edge_port->icount, sizeof(edge_port->icount)))
+ return -EFAULT;
+@@ -2706,7 +2709,7 @@ static void edge_break (struct usb_serial_port *port, int break_state)
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+ int status;
+
+- dbg ("%s - state = %d", __FUNCTION__, break_state);
++ dbg ("%s - state = %d", __func__, break_state);
+
+ /* chase the port close */
+ TIChasePort (edge_port, 0, 0);
+@@ -2718,7 +2721,7 @@ static void edge_break (struct usb_serial_port *port, int break_state)
+ }
+ if (status) {
+ dbg ("%s - error %d sending break set/clear command.",
+- __FUNCTION__, status);
++ __func__, status);
+ }
+ }
+
+@@ -2735,7 +2738,7 @@ static int edge_startup (struct usb_serial *serial)
+ /* create our private serial structure */
+ edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL);
+ if (edge_serial == NULL) {
+- dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
++ dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
+ return -ENOMEM;
+ }
+ mutex_init(&edge_serial->es_lock);
+@@ -2752,13 +2755,13 @@ static int edge_startup (struct usb_serial *serial)
+ for (i = 0; i < serial->num_ports; ++i) {
+ edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL);
+ if (edge_port == NULL) {
+- dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
++ dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
+ goto cleanup;
+ }
+ spin_lock_init(&edge_port->ep_lock);
+ edge_port->ep_out_buf = edge_buf_alloc(EDGE_OUT_BUF_SIZE);
+ if (edge_port->ep_out_buf == NULL) {
+- dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
++ dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
+ kfree(edge_port);
+ goto cleanup;
+ }
+@@ -2787,7 +2790,7 @@ static void edge_shutdown (struct usb_serial *serial)
+ int i;
+ struct edgeport_port *edge_port;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+ for (i = 0; i < serial->num_ports; ++i) {
+ edge_port = usb_get_serial_port_data(serial->port[i]);
+@@ -2819,12 +2822,12 @@ static ssize_t store_uart_mode(struct device *dev,
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+ unsigned int v = simple_strtoul(valbuf, NULL, 0);
+
+- dbg("%s: setting uart_mode = %d", __FUNCTION__, v);
++ dbg("%s: setting uart_mode = %d", __func__, v);
+
+ if (v < 256)
+ edge_port->bUartMode = v;
+ else
+- dev_err(dev, "%s - uart_mode %d is invalid\n", __FUNCTION__, v);
++ dev_err(dev, "%s - uart_mode %d is invalid\n", __func__, v);
+
+ return count;
+ }
+@@ -3029,9 +3032,6 @@ static struct usb_serial_driver edgeport_1port_device = {
+ .description = "Edgeport TI 1 port adapter",
+ .usb_driver = &io_driver,
+ .id_table = edgeport_1port_id_table,
+- .num_interrupt_in = 1,
+- .num_bulk_in = 1,
+- .num_bulk_out = 1,
+ .num_ports = 1,
+ .open = edge_open,
+ .close = edge_close,
+@@ -3061,9 +3061,6 @@ static struct usb_serial_driver edgeport_2port_device = {
+ .description = "Edgeport TI 2 port adapter",
+ .usb_driver = &io_driver,
+ .id_table = edgeport_2port_id_table,
+- .num_interrupt_in = 1,
+- .num_bulk_in = 2,
+- .num_bulk_out = 2,
+ .num_ports = 2,
+ .open = edge_open,
+ .close = edge_close,
+diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
+index 9b38a08..ea924dc 100644
+--- a/drivers/usb/serial/ipaq.c
++++ b/drivers/usb/serial/ipaq.c
+@@ -570,10 +570,7 @@ static struct usb_serial_driver ipaq_device = {
+ .description = "PocketPC PDA",
+ .usb_driver = &ipaq_driver,
+ .id_table = ipaq_id_table,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_bulk_in = 1,
+- .num_bulk_out = 1,
+- .num_ports = 1,
++ .num_ports = 2,
+ .open = ipaq_open,
+ .close = ipaq_close,
+ .attach = ipaq_startup,
+@@ -597,13 +594,13 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
+ int i, result = 0;
+ int retries = connect_retries;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ bytes_in = 0;
+ bytes_out = 0;
+ priv = kmalloc(sizeof(struct ipaq_private), GFP_KERNEL);
+ if (priv == NULL) {
+- err("%s - Out of memory", __FUNCTION__);
++ err("%s - Out of memory", __func__);
+ return -ENOMEM;
+ }
+ usb_set_serial_port_data(port, priv);
+@@ -682,7 +679,7 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
+ }
+
+ if (!retries && result) {
+- err("%s - failed doing control urb, error %d", __FUNCTION__,
++ err("%s - failed doing control urb, error %d", __func__,
+ result);
+ goto error;
+ }
+@@ -695,7 +692,7 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
+
+ result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ if (result) {
+- err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
++ err("%s - failed submitting read urb, error %d", __func__, result);
+ goto error;
+ }
+
+@@ -703,7 +700,7 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
+
+ enomem:
+ result = -ENOMEM;
+- err("%s - Out of memory", __FUNCTION__);
++ err("%s - Out of memory", __func__);
+ error:
+ ipaq_destroy_lists(port);
+ kfree(priv);
+@@ -715,7 +712,7 @@ static void ipaq_close(struct usb_serial_port *port, struct file *filp)
+ {
+ struct ipaq_private *priv = usb_get_serial_port_data(port);
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /*
+ * shut down bulk read and write
+@@ -732,21 +729,21 @@ static void ipaq_close(struct usb_serial_port *port, struct file *filp)
+
+ static void ipaq_read_bulk_callback(struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct tty_struct *tty;
+ unsigned char *data = urb->transfer_buffer;
+ int result;
+ int status = urb->status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++ usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+
+ tty = port->tty;
+ if (tty && urb->actual_length) {
+@@ -763,7 +760,7 @@ static void ipaq_read_bulk_callback(struct urb *urb)
+ ipaq_read_bulk_callback, port);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ if (result)
+- err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
++ err("%s - failed resubmitting read urb, error %d", __func__, result);
+ return;
+ }
+
+@@ -774,7 +771,7 @@ static int ipaq_write(struct usb_serial_port *port, const unsigned char *buf,
+ int bytes_sent = 0;
+ int transfer_size;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ while (count > 0) {
+ transfer_size = min(count, PACKET_SIZE);
+@@ -799,7 +796,7 @@ static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *bu
+ unsigned long flags;
+
+ if (priv->free_len <= 0) {
+- dbg("%s - we're stuffed", __FUNCTION__);
++ dbg("%s - we're stuffed", __func__);
+ return -EAGAIN;
+ }
+
+@@ -811,12 +808,12 @@ static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *bu
+ }
+ spin_unlock_irqrestore(&write_list_lock, flags);
+ if (pkt == NULL) {
+- dbg("%s - we're stuffed", __FUNCTION__);
++ dbg("%s - we're stuffed", __func__);
+ return -EAGAIN;
+ }
+
+ memcpy(pkt->data, buf, count);
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, pkt->data);
++ usb_serial_debug_data(debug, &port->dev, __func__, count, pkt->data);
+
+ pkt->len = count;
+ pkt->written = 0;
+@@ -829,7 +826,7 @@ static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *bu
+ spin_unlock_irqrestore(&write_list_lock, flags);
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ if (result) {
+- err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
++ err("%s - failed submitting write urb, error %d", __func__, result);
+ }
+ } else {
+ spin_unlock_irqrestore(&write_list_lock, flags);
+@@ -872,17 +869,17 @@ static void ipaq_write_gather(struct usb_serial_port *port)
+
+ static void ipaq_write_bulk_callback(struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct ipaq_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+ int result;
+ int status = urb->status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (status) {
+ dbg("%s - nonzero write bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
+
+@@ -892,7 +889,7 @@ static void ipaq_write_bulk_callback(struct urb *urb)
+ spin_unlock_irqrestore(&write_list_lock, flags);
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ if (result) {
+- err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
++ err("%s - failed submitting write urb, error %d", __func__, result);
+ }
+ } else {
+ priv->active = 0;
+@@ -906,7 +903,7 @@ static int ipaq_write_room(struct usb_serial_port *port)
+ {
+ struct ipaq_private *priv = usb_get_serial_port_data(port);
+
+- dbg("%s - freelen %d", __FUNCTION__, priv->free_len);
++ dbg("%s - freelen %d", __func__, priv->free_len);
+ return priv->free_len;
+ }
+
+@@ -914,7 +911,7 @@ static int ipaq_chars_in_buffer(struct usb_serial_port *port)
+ {
+ struct ipaq_private *priv = usb_get_serial_port_data(port);
+
+- dbg("%s - queuelen %d", __FUNCTION__, priv->queue_len);
++ dbg("%s - queuelen %d", __func__, priv->queue_len);
+ return priv->queue_len;
+ }
+
+@@ -936,7 +933,7 @@ static void ipaq_destroy_lists(struct usb_serial_port *port)
+
+ static int ipaq_startup(struct usb_serial *serial)
+ {
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+ if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
+ err("active config #%d != 1 ??",
+ serial->dev->actconfig->desc.bConfigurationValue);
+@@ -947,7 +944,7 @@ static int ipaq_startup(struct usb_serial *serial)
+
+ static void ipaq_shutdown(struct usb_serial *serial)
+ {
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+ }
+
+ static int __init ipaq_init(void)
+diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
+index cbe5530..bc85ca5 100644
+--- a/drivers/usb/serial/ipw.c
++++ b/drivers/usb/serial/ipw.c
+@@ -169,15 +169,15 @@ static void ipw_read_bulk_callback(struct urb *urb)
+ int result;
+ int status = urb->status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++ usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+
+ tty = port->tty;
+ if (tty && urb->actual_length) {
+@@ -195,7 +195,7 @@ static void ipw_read_bulk_callback(struct urb *urb)
+ ipw_read_bulk_callback, port);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ if (result)
+- dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
++ dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
+ return;
+ }
+
+@@ -206,7 +206,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
+ u8 *buf_flow_init;
+ int result;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ buf_flow_init = kmemdup(buf_flow_static, 16, GFP_KERNEL);
+ if (!buf_flow_init)
+@@ -217,7 +217,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
+
+ /* --1: Tell the modem to initialize (we think) From sniffs this is always the
+ * first thing that gets sent to the modem during opening of the device */
+- dbg("%s: Sending SIO_INIT (we guess)",__FUNCTION__);
++ dbg("%s: Sending SIO_INIT (we guess)",__func__);
+ result = usb_control_msg(dev, usb_sndctrlpipe(dev,0),
+ IPW_SIO_INIT,
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+@@ -234,7 +234,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
+ usb_clear_halt(dev, usb_sndbulkpipe(dev, port->bulk_out_endpointAddress));
+
+ /*--2: Start reading from the device */
+- dbg("%s: setting up bulk read callback",__FUNCTION__);
++ dbg("%s: setting up bulk read callback",__func__);
+ usb_fill_bulk_urb(port->read_urb, dev,
+ usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress),
+ port->bulk_in_buffer,
+@@ -242,10 +242,10 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
+ ipw_read_bulk_callback, port);
+ result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ if (result < 0)
+- dbg("%s - usb_submit_urb(read bulk) failed with status %d", __FUNCTION__, result);
++ dbg("%s - usb_submit_urb(read bulk) failed with status %d", __func__, result);
+
+ /*--3: Tell the modem to open the floodgates on the rx bulk channel */
+- dbg("%s:asking modem for RxRead (RXBULK_ON)",__FUNCTION__);
++ dbg("%s:asking modem for RxRead (RXBULK_ON)",__func__);
+ result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ IPW_SIO_RXCTL,
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+@@ -258,7 +258,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
+ dev_err(&port->dev, "Enabling bulk RxRead failed (error = %d)\n", result);
+
+ /*--4: setup the initial flowcontrol */
+- dbg("%s:setting init flowcontrol (%s)",__FUNCTION__,buf_flow_init);
++ dbg("%s:setting init flowcontrol (%s)",__func__,buf_flow_init);
+ result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ IPW_SIO_HANDFLOW,
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+@@ -272,7 +272,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
+
+
+ /*--5: raise the dtr */
+- dbg("%s:raising dtr",__FUNCTION__);
++ dbg("%s:raising dtr",__func__);
+ result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ IPW_SIO_SET_PIN,
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+@@ -285,7 +285,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
+ dev_err(&port->dev, "setting dtr failed (error = %d)\n", result);
+
+ /*--6: raise the rts */
+- dbg("%s:raising rts",__FUNCTION__);
++ dbg("%s:raising rts",__func__);
+ result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ IPW_SIO_SET_PIN,
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+@@ -307,12 +307,12 @@ static void ipw_close(struct usb_serial_port *port, struct file * filp)
+ int result;
+
+ if (tty_hung_up_p(filp)) {
+- dbg("%s: tty_hung_up_p ...", __FUNCTION__);
++ dbg("%s: tty_hung_up_p ...", __func__);
+ return;
+ }
+
+ /*--1: drop the dtr */
+- dbg("%s:dropping dtr",__FUNCTION__);
++ dbg("%s:dropping dtr",__func__);
+ result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ IPW_SIO_SET_PIN,
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+@@ -325,7 +325,7 @@ static void ipw_close(struct usb_serial_port *port, struct file * filp)
+ dev_err(&port->dev, "dropping dtr failed (error = %d)\n", result);
+
+ /*--2: drop the rts */
+- dbg("%s:dropping rts",__FUNCTION__);
++ dbg("%s:dropping rts",__func__);
+ result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ IPW_SIO_SET_PIN, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ IPW_PIN_CLRRTS,
+@@ -338,7 +338,7 @@ static void ipw_close(struct usb_serial_port *port, struct file * filp)
+
+
+ /*--3: purge */
+- dbg("%s:sending purge",__FUNCTION__);
++ dbg("%s:sending purge",__func__);
+ result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ IPW_SIO_PURGE, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ 0x03,
+@@ -373,13 +373,13 @@ static void ipw_write_bulk_callback(struct urb *urb)
+ struct usb_serial_port *port = urb->context;
+ int status = urb->status;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ port->write_urb_busy = 0;
+
+ if (status)
+ dbg("%s - nonzero write bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+
+ usb_serial_port_softint(port);
+ }
+@@ -389,18 +389,18 @@ static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int
+ struct usb_device *dev = port->serial->dev;
+ int ret;
+
+- dbg("%s: TOP: count=%d, in_interrupt=%ld", __FUNCTION__,
++ dbg("%s: TOP: count=%d, in_interrupt=%ld", __func__,
+ count, in_interrupt() );
+
+ if (count == 0) {
+- dbg("%s - write request of 0 bytes", __FUNCTION__);
++ dbg("%s - write request of 0 bytes", __func__);
+ return 0;
+ }
+
+ spin_lock_bh(&port->lock);
+ if (port->write_urb_busy) {
+ spin_unlock_bh(&port->lock);
+- dbg("%s - already writing", __FUNCTION__);
++ dbg("%s - already writing", __func__);
+ return 0;
+ }
+ port->write_urb_busy = 1;
+@@ -409,7 +409,7 @@ static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int
+ count = min(count, port->bulk_out_size);
+ memcpy(port->bulk_out_buffer, buf, count);
+
+- dbg("%s count now:%d", __FUNCTION__, count);
++ dbg("%s count now:%d", __func__, count);
+
+ usb_fill_bulk_urb(port->write_urb, dev,
+ usb_sndbulkpipe(dev, port->bulk_out_endpointAddress),
+@@ -421,11 +421,11 @@ static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int
+ ret = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ if (ret != 0) {
+ port->write_urb_busy = 0;
+- dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __FUNCTION__, ret);
++ dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __func__, ret);
+ return ret;
+ }
+
+- dbg("%s returning %d", __FUNCTION__, count);
++ dbg("%s returning %d", __func__, count);
+ return count;
+ }
+
+@@ -448,9 +448,6 @@ static struct usb_serial_driver ipw_device = {
+ .description = "IPWireless converter",
+ .usb_driver = &usb_ipw_driver,
+ .id_table = usb_ipw_ids,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_bulk_in = 1,
+- .num_bulk_out = 1,
+ .num_ports = 1,
+ .open = ipw_open,
+ .close = ipw_close,
+diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
+index 6b803ab..004d573 100644
+--- a/drivers/usb/serial/ir-usb.c
++++ b/drivers/usb/serial/ir-usb.c
+@@ -145,9 +145,6 @@ static struct usb_serial_driver ir_device = {
+ .description = "IR Dongle",
+ .usb_driver = &ir_driver,
+ .id_table = id_table,
+- .num_interrupt_in = 1,
+- .num_bulk_in = 1,
+- .num_bulk_out = 1,
+ .num_ports = 1,
+ .set_termios = ir_set_termios,
+ .attach = ir_startup,
+@@ -198,16 +195,16 @@ static struct irda_class_desc *irda_usb_find_class_desc(struct usb_device *dev,
+ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ 0, ifnum, desc, sizeof(*desc), 1000);
+
+- dbg("%s - ret=%d", __FUNCTION__, ret);
++ dbg("%s - ret=%d", __func__, ret);
+ if (ret < sizeof(*desc)) {
+ dbg("%s - class descriptor read %s (%d)",
+- __FUNCTION__,
++ __func__,
+ (ret<0) ? "failed" : "too short",
+ ret);
+ goto error;
+ }
+ if (desc->bDescriptorType != USB_DT_IRDA) {
+- dbg("%s - bad class descriptor type", __FUNCTION__);
++ dbg("%s - bad class descriptor type", __func__);
+ goto error;
+ }
+
+@@ -251,7 +248,7 @@ static int ir_startup (struct usb_serial *serial)
+ }
+
+ dbg ("%s - Baud rates supported:%s%s%s%s%s%s%s%s%s",
+- __FUNCTION__,
++ __func__,
+ (irda_desc->wBaudRate & 0x0001) ? " 2400" : "",
+ (irda_desc->wBaudRate & 0x0002) ? " 9600" : "",
+ (irda_desc->wBaudRate & 0x0004) ? " 19200" : "",
+@@ -284,13 +281,13 @@ static int ir_open (struct usb_serial_port *port, struct file *filp)
+ char *buffer;
+ int result = 0;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (buffer_size) {
+ /* override the default buffer sizes */
+ buffer = kmalloc (buffer_size, GFP_KERNEL);
+ if (!buffer) {
+- dev_err (&port->dev, "%s - out of memory.\n", __FUNCTION__);
++ dev_err (&port->dev, "%s - out of memory.\n", __func__);
+ return -ENOMEM;
+ }
+ kfree (port->read_urb->transfer_buffer);
+@@ -299,7 +296,7 @@ static int ir_open (struct usb_serial_port *port, struct file *filp)
+
+ buffer = kmalloc (buffer_size, GFP_KERNEL);
+ if (!buffer) {
+- dev_err (&port->dev, "%s - out of memory.\n", __FUNCTION__);
++ dev_err (&port->dev, "%s - out of memory.\n", __func__);
+ return -ENOMEM;
+ }
+ kfree (port->write_urb->transfer_buffer);
+@@ -319,14 +316,14 @@ static int ir_open (struct usb_serial_port *port, struct file *filp)
+ port);
+ result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ if (result)
+- dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
++ dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
+
+ return result;
+ }
+
+ static void ir_close (struct usb_serial_port *port, struct file * filp)
+ {
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /* shutdown our bulk read */
+ usb_kill_urb(port->read_urb);
+@@ -338,10 +335,10 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int
+ int result;
+ int transfer_size;
+
+- dbg("%s - port = %d, count = %d", __FUNCTION__, port->number, count);
++ dbg("%s - port = %d, count = %d", __func__, port->number, count);
+
+ if (!port->tty) {
+- dev_err (&port->dev, "%s - no tty???\n", __FUNCTION__);
++ dev_err (&port->dev, "%s - no tty???\n", __func__);
+ return 0;
+ }
+
+@@ -351,7 +348,7 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int
+ spin_lock_bh(&port->lock);
+ if (port->write_urb_busy) {
+ spin_unlock_bh(&port->lock);
+- dbg("%s - already writing", __FUNCTION__);
++ dbg("%s - already writing", __func__);
+ return 0;
+ }
+ port->write_urb_busy = 1;
+@@ -387,7 +384,7 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int
+ result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
+ if (result) {
+ port->write_urb_busy = 0;
+- dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
++ dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result);
+ } else
+ result = transfer_size;
+
+@@ -396,22 +393,22 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int
+
+ static void ir_write_bulk_callback (struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ int status = urb->status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ port->write_urb_busy = 0;
+ if (status) {
+ dbg("%s - nonzero write bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
+
+ usb_serial_debug_data (
+ debug,
+ &port->dev,
+- __FUNCTION__,
++ __func__,
+ urb->actual_length,
+ urb->transfer_buffer);
+
+@@ -420,16 +417,16 @@ static void ir_write_bulk_callback (struct urb *urb)
+
+ static void ir_read_bulk_callback (struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct tty_struct *tty;
+ unsigned char *data = urb->transfer_buffer;
+ int result;
+ int status = urb->status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (!port->open_count) {
+- dbg("%s - port closed.", __FUNCTION__);
++ dbg("%s - port closed.", __func__);
+ return;
+ }
+
+@@ -447,7 +444,7 @@ static void ir_read_bulk_callback (struct urb *urb)
+ usb_serial_debug_data (
+ debug,
+ &port->dev,
+- __FUNCTION__,
++ __func__,
+ urb->actual_length,
+ data);
+
+@@ -480,13 +477,13 @@ static void ir_read_bulk_callback (struct urb *urb)
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ if (result)
+ dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n",
+- __FUNCTION__, result);
++ __func__, result);
+
+ break ;
+
+ default:
+ dbg("%s - nonzero read bulk status received: %d",
+- __FUNCTION__,
++ __func__,
+ status);
+ break ;
+
+@@ -502,7 +499,7 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t
+ speed_t baud;
+ int ir_baud;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ baud = tty_get_baud_rate(port->tty);
+
+@@ -554,7 +551,7 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t
+
+ result = usb_submit_urb (port->write_urb, GFP_KERNEL);
+ if (result)
+- dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
++ dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result);
+
+ /* Only speed changes are supported */
+ tty_termios_copy_hw(port->tty->termios, old_termios);
+diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
+index fde188e..8a21764 100644
+--- a/drivers/usb/serial/iuu_phoenix.c
++++ b/drivers/usb/serial/iuu_phoenix.c
+@@ -98,10 +98,10 @@ static int iuu_alloc_buf(struct iuu_private *priv)
+ priv->writebuf = kzalloc(256, GFP_KERNEL);
+ if (!priv->buf || !priv->dbgbuf || !priv->writebuf) {
+ iuu_free_buf(priv);
+- dbg("%s problem allocation buffer", __FUNCTION__);
++ dbg("%s problem allocation buffer", __func__);
+ return -ENOMEM;
+ }
+- dbg("%s - Privates buffers allocation success", __FUNCTION__);
++ dbg("%s - Privates buffers allocation success", __func__);
+ return 0;
+ }
+
+@@ -109,7 +109,7 @@ static int iuu_startup(struct usb_serial *serial)
+ {
+ struct iuu_private *priv;
+ priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL);
+- dbg("%s- priv allocation success", __FUNCTION__);
++ dbg("%s- priv allocation success", __func__);
+ if (!priv)
+ return -ENOMEM;
+ if (iuu_alloc_buf(priv)) {
+@@ -130,17 +130,17 @@ static void iuu_shutdown(struct usb_serial *serial)
+ if (!port)
+ return;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ if (priv) {
+ iuu_free_buf(priv);
+- dbg("%s - I will free all", __FUNCTION__);
++ dbg("%s - I will free all", __func__);
+ usb_set_serial_port_data(port, NULL);
+
+- dbg("%s - priv is not anymore in port structure", __FUNCTION__);
++ dbg("%s - priv is not anymore in port structure", __func__);
+ kfree(priv);
+
+- dbg("%s priv is now kfree", __FUNCTION__);
++ dbg("%s priv is now kfree", __func__);
+ }
+ }
+
+@@ -148,20 +148,21 @@ static int iuu_tiocmset(struct usb_serial_port *port, struct file *file,
+ unsigned int set, unsigned int clear)
+ {
+ struct iuu_private *priv = usb_get_serial_port_data(port);
+- struct tty_struct *tty;
+- tty = port->tty;
++ unsigned long flags;
+
+- dbg("%s (%d) msg : SET = 0x%04x, CLEAR = 0x%04x ", __FUNCTION__,
++ /* FIXME: locking on tiomstatus */
++ dbg("%s (%d) msg : SET = 0x%04x, CLEAR = 0x%04x ", __func__,
+ port->number, set, clear);
++
++ spin_lock_irqsave(&priv->lock, flags);
+ if (set & TIOCM_RTS)
+ priv->tiostatus = TIOCM_RTS;
+
+ if (!(set & TIOCM_RTS) && priv->tiostatus == TIOCM_RTS) {
+- dbg("%s TIOCMSET RESET called !!!", __FUNCTION__);
++ dbg("%s TIOCMSET RESET called !!!", __func__);
+ priv->reset = 1;
+- return 0;
+ }
+-
++ spin_unlock_irqrestore(&priv->lock, flags);
+ return 0;
+ }
+
+@@ -173,17 +174,24 @@ static int iuu_tiocmset(struct usb_serial_port *port, struct file *file,
+ static int iuu_tiocmget(struct usb_serial_port *port, struct file *file)
+ {
+ struct iuu_private *priv = usb_get_serial_port_data(port);
+- return priv->tiostatus;
++ unsigned long flags;
++ int rc;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ rc = priv->tiostatus;
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ return rc;
+ }
+
+ static void iuu_rxcmd(struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ int result;
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
+
+ if (urb->status) {
+- dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
++ dbg("%s - urb->status = %d", __func__, urb->status);
+ /* error stop all */
+ return;
+ }
+@@ -203,7 +211,7 @@ static int iuu_reset(struct usb_serial_port *port, u8 wt)
+ struct iuu_private *priv = usb_get_serial_port_data(port);
+ int result;
+ char *buf_ptr = port->write_urb->transfer_buffer;
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
+
+ /* Prepare the reset sequence */
+
+@@ -232,19 +240,19 @@ static int iuu_reset(struct usb_serial_port *port, u8 wt)
+ */
+ static void iuu_update_status_callback(struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct iuu_private *priv = usb_get_serial_port_data(port);
+ u8 *st;
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
+
+ if (urb->status) {
+- dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
++ dbg("%s - urb->status = %d", __func__, urb->status);
+ /* error stop all */
+ return;
+ }
+
+ st = urb->transfer_buffer;
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
+ if (urb->actual_length == 1) {
+ switch (st[0]) {
+ case 0x1:
+@@ -262,11 +270,11 @@ static void iuu_update_status_callback(struct urb *urb)
+
+ static void iuu_status_callback(struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ int result;
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
+
+- dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
++ dbg("%s - urb->status = %d", __func__, urb->status);
+ usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+ usb_rcvbulkpipe(port->serial->dev,
+ port->bulk_in_endpointAddress),
+@@ -279,7 +287,7 @@ static int iuu_status(struct usb_serial_port *port)
+ {
+ int result;
+
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
+
+ memset(port->write_urb->transfer_buffer, IUU_GET_STATE_REGISTER, 1);
+ usb_fill_bulk_urb(port->write_urb, port->serial->dev,
+@@ -298,7 +306,7 @@ static int bulk_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
+ struct usb_serial *serial = port->serial;
+ int actual = 0;
+
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
+
+ /* send the data out the bulk port */
+
+@@ -309,9 +317,9 @@ static int bulk_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
+ count, &actual, HZ * 1);
+
+ if (status != IUU_OPERATION_OK) {
+- dbg("%s - error = %2x", __FUNCTION__, status);
++ dbg("%s - error = %2x", __func__, status);
+ } else {
+- dbg("%s - write OK !", __FUNCTION__);
++ dbg("%s - write OK !", __func__);
+ }
+ return status;
+ }
+@@ -322,7 +330,7 @@ static int read_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
+ struct usb_serial *serial = port->serial;
+ int actual = 0;
+
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
+
+ /* send the data out the bulk port */
+
+@@ -333,9 +341,9 @@ static int read_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
+ count, &actual, HZ * 1);
+
+ if (status != IUU_OPERATION_OK) {
+- dbg("%s - error = %2x", __FUNCTION__, status);
++ dbg("%s - error = %2x", __func__, status);
+ } else {
+- dbg("%s - read OK !", __FUNCTION__);
++ dbg("%s - read OK !", __func__);
+ }
+
+ return status;
+@@ -350,7 +358,7 @@ static int iuu_led(struct usb_serial_port *port, unsigned int R,
+ if (!buf)
+ return -ENOMEM;
+
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
+
+ buf[0] = IUU_SET_LED;
+ buf[1] = R & 0xFF;
+@@ -363,9 +371,9 @@ static int iuu_led(struct usb_serial_port *port, unsigned int R,
+ status = bulk_immediate(port, buf, 8);
+ kfree(buf);
+ if (status != IUU_OPERATION_OK)
+- dbg("%s - led error status = %2x", __FUNCTION__, status);
++ dbg("%s - led error status = %2x", __func__, status);
+ else
+- dbg("%s - led OK !", __FUNCTION__);
++ dbg("%s - led OK !", __func__);
+ return IUU_OPERATION_OK;
+ }
+
+@@ -384,7 +392,7 @@ static void iuu_rgbf_fill_buffer(u8 *buf, u8 r1, u8 r2, u8 g1, u8 g2, u8 b1,
+
+ static void iuu_led_activity_on(struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ int result;
+ char *buf_ptr = port->write_urb->transfer_buffer;
+ *buf_ptr++ = IUU_SET_LED;
+@@ -405,7 +413,7 @@ static void iuu_led_activity_on(struct urb *urb)
+
+ static void iuu_led_activity_off(struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ int result;
+ char *buf_ptr = port->write_urb->transfer_buffer;
+ if (xmas == 1) {
+@@ -443,7 +451,7 @@ static int iuu_clk(struct usb_serial_port *port, int dwFrq)
+ unsigned int P2 = 0;
+ int frq = (int)dwFrq;
+
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
+
+ if (frq == 0) {
+ priv->buf[Count++] = IUU_UART_WRITE_I2C;
+@@ -453,7 +461,7 @@ static int iuu_clk(struct usb_serial_port *port, int dwFrq)
+
+ status = bulk_immediate(port, (u8 *) priv->buf, Count);
+ if (status != 0) {
+- dbg("%s - write error ", __FUNCTION__);
++ dbg("%s - write error ", __func__);
+ return status;
+ }
+ } else if (frq == 3579000) {
+@@ -562,7 +570,7 @@ static int iuu_clk(struct usb_serial_port *port, int dwFrq)
+
+ status = bulk_immediate(port, (u8 *) priv->buf, Count);
+ if (status != IUU_OPERATION_OK)
+- dbg("%s - write error ", __FUNCTION__);
++ dbg("%s - write error ", __func__);
+ return status;
+ }
+
+@@ -573,7 +581,7 @@ static int iuu_uart_flush(struct usb_serial_port *port)
+ u8 rxcmd = IUU_UART_RX;
+ struct iuu_private *priv = usb_get_serial_port_data(port);
+
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
+
+ if (iuu_led(port, 0xF000, 0, 0, 0xFF) < 0)
+ return -EIO;
+@@ -581,50 +589,50 @@ static int iuu_uart_flush(struct usb_serial_port *port)
+ for (i = 0; i < 2; i++) {
+ status = bulk_immediate(port, &rxcmd, 1);
+ if (status != IUU_OPERATION_OK) {
+- dbg("%s - uart_flush_write error", __FUNCTION__);
++ dbg("%s - uart_flush_write error", __func__);
+ return status;
+ }
+
+ status = read_immediate(port, &priv->len, 1);
+ if (status != IUU_OPERATION_OK) {
+- dbg("%s - uart_flush_read error", __FUNCTION__);
++ dbg("%s - uart_flush_read error", __func__);
+ return status;
+ }
+
+ if (priv->len > 0) {
+- dbg("%s - uart_flush datalen is : %i ", __FUNCTION__,
++ dbg("%s - uart_flush datalen is : %i ", __func__,
+ priv->len);
+ status = read_immediate(port, priv->buf, priv->len);
+ if (status != IUU_OPERATION_OK) {
+- dbg("%s - uart_flush_read error", __FUNCTION__);
++ dbg("%s - uart_flush_read error", __func__);
+ return status;
+ }
+ }
+ }
+- dbg("%s - uart_flush_read OK!", __FUNCTION__);
++ dbg("%s - uart_flush_read OK!", __func__);
+ iuu_led(port, 0, 0xF000, 0, 0xFF);
+ return status;
+ }
+
+ static void read_buf_callback(struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ unsigned char *data = urb->transfer_buffer;
+ struct tty_struct *tty;
+- dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
++ dbg("%s - urb->status = %d", __func__, urb->status);
+
+ if (urb->status) {
+- dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
++ dbg("%s - urb->status = %d", __func__, urb->status);
+ if (urb->status == -EPROTO) {
+ /* reschedule needed */
+ }
+ return;
+ }
+
+- dbg("%s - %i chars to write", __FUNCTION__, urb->actual_length);
++ dbg("%s - %i chars to write", __func__, urb->actual_length);
+ tty = port->tty;
+ if (data == NULL)
+- dbg("%s - data is NULL !!!", __FUNCTION__);
++ dbg("%s - data is NULL !!!", __func__);
+ if (tty && urb->actual_length && data) {
+ tty_insert_flip_string(tty, data, urb->actual_length);
+ tty_flip_buffer_push(tty);
+@@ -639,7 +647,7 @@ static int iuu_bulk_write(struct usb_serial_port *port)
+ int result;
+ int i;
+ char *buf_ptr = port->write_urb->transfer_buffer;
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
+
+ *buf_ptr++ = IUU_UART_ESC;
+ *buf_ptr++ = IUU_UART_TX;
+@@ -652,7 +660,7 @@ static int iuu_bulk_write(struct usb_serial_port *port)
+ sprintf(priv->dbgbuf + i*2 ,
+ "%02X", priv->writebuf[i]);
+ priv->dbgbuf[priv->writelen+i*2] = 0;
+- dbg("%s - writing %i chars : %s", __FUNCTION__,
++ dbg("%s - writing %i chars : %s", __func__,
+ priv->writelen, priv->dbgbuf);
+ }
+ usb_fill_bulk_urb(port->write_urb, port->serial->dev,
+@@ -671,7 +679,7 @@ static int iuu_bulk_write(struct usb_serial_port *port)
+ static int iuu_read_buf(struct usb_serial_port *port, int len)
+ {
+ int result;
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
+
+ usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+ usb_rcvbulkpipe(port->serial->dev,
+@@ -684,7 +692,7 @@ static int iuu_read_buf(struct usb_serial_port *port, int len)
+
+ static void iuu_uart_read_callback(struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct iuu_private *priv = usb_get_serial_port_data(port);
+ unsigned int flags;
+ int status;
+@@ -693,21 +701,21 @@ static void iuu_uart_read_callback(struct urb *urb)
+ unsigned char *data = urb->transfer_buffer;
+ priv->poll++;
+
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
+
+ if (urb->status) {
+- dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
++ dbg("%s - urb->status = %d", __func__, urb->status);
+ /* error stop all */
+ return;
+ }
+ if (data == NULL)
+- dbg("%s - data is NULL !!!", __FUNCTION__);
++ dbg("%s - data is NULL !!!", __func__);
+
+ if (urb->actual_length == 1 && data != NULL)
+ len = (int) data[0];
+
+ if (urb->actual_length > 1) {
+- dbg("%s - urb->actual_length = %i", __FUNCTION__,
++ dbg("%s - urb->actual_length = %i", __func__,
+ urb->actual_length);
+ error = 1;
+ return;
+@@ -716,7 +724,7 @@ static void iuu_uart_read_callback(struct urb *urb)
+
+ if (len > 0 && error == 0) {
+ dbg("%s - call read buf - len to read is %i ",
+- __FUNCTION__, len);
++ __func__, len);
+ status = iuu_read_buf(port, len);
+ return;
+ }
+@@ -742,7 +750,7 @@ static void iuu_uart_read_callback(struct urb *urb)
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+ /* if nothing to write call again rxcmd */
+- dbg("%s - rxcmd recall", __FUNCTION__);
++ dbg("%s - rxcmd recall", __func__);
+ iuu_led_activity_off(urb);
+ return;
+ }
+@@ -752,7 +760,7 @@ static int iuu_uart_write(struct usb_serial_port *port, const u8 *buf,
+ {
+ struct iuu_private *priv = usb_get_serial_port_data(port);
+ unsigned int flags;
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
+
+ if (count > 256)
+ return -ENOMEM;
+@@ -773,14 +781,14 @@ static int iuu_uart_write(struct usb_serial_port *port, const u8 *buf,
+
+ static void read_rxcmd_callback(struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ int result;
+- dbg("%s - enter", __FUNCTION__);
++ dbg("%s - enter", __func__);
+
+- dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
++ dbg("%s - urb->status = %d", __func__, urb->status);
+
+ if (urb->status) {
+- dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
++ dbg("%s - urb->status = %d", __func__, urb->status);
+ /* error stop all */
+ return;
+ }
+@@ -791,7 +799,7 @@ static void read_rxcmd_callback(struct urb *urb)
+ port->read_urb->transfer_buffer, 256,
+ iuu_uart_read_callback, port);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+- dbg("%s - submit result = %d", __FUNCTION__, result);
++ dbg("%s - submit result = %d", __func__, result);
+ return;
+ }
+
+@@ -812,13 +820,13 @@ static int iuu_uart_on(struct usb_serial_port *port)
+
+ status = bulk_immediate(port, buf, 4);
+ if (status != IUU_OPERATION_OK) {
+- dbg("%s - uart_on error", __FUNCTION__);
++ dbg("%s - uart_on error", __func__);
+ goto uart_enable_failed;
+ }
+ /* iuu_reset() the card after iuu_uart_on() */
+ status = iuu_uart_flush(port);
+ if (status != IUU_OPERATION_OK)
+- dbg("%s - uart_flush error", __FUNCTION__);
++ dbg("%s - uart_flush error", __func__);
+ uart_enable_failed:
+ kfree(buf);
+ return status;
+@@ -836,7 +844,7 @@ static int iuu_uart_off(struct usb_serial_port *port)
+
+ status = bulk_immediate(port, buf, 1);
+ if (status != IUU_OPERATION_OK)
+- dbg("%s - uart_off error", __FUNCTION__);
++ dbg("%s - uart_off error", __func__);
+
+ kfree(buf);
+ return status;
+@@ -930,7 +938,7 @@ static int iuu_uart_baud(struct usb_serial_port *port, u32 baud,
+
+ status = bulk_immediate(port, dataout, DataCount);
+ if (status != IUU_OPERATION_OK)
+- dbg("%s - uart_off error", __FUNCTION__);
++ dbg("%s - uart_off error", __func__);
+ kfree(dataout);
+ return status;
+ }
+@@ -952,7 +960,7 @@ static void iuu_close(struct usb_serial_port *port, struct file *filp)
+ if (!serial)
+ return;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ iuu_uart_off(port);
+ if (serial->dev) {
+@@ -969,7 +977,7 @@ static void iuu_close(struct usb_serial_port *port, struct file *filp)
+ }
+ /* free writebuf */
+ /* shutdown our urbs */
+- dbg("%s - shutting down urbs", __FUNCTION__);
++ dbg("%s - shutting down urbs", __func__);
+ usb_kill_urb(port->write_urb);
+ usb_kill_urb(port->read_urb);
+ usb_kill_urb(port->interrupt_in_urb);
+@@ -990,7 +998,7 @@ static int iuu_open(struct usb_serial_port *port, struct file *filp)
+ unsigned long flags;
+ struct iuu_private *priv = usb_get_serial_port_data(port);
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+ usb_clear_halt(serial->dev, port->write_urb->pipe);
+ usb_clear_halt(serial->dev, port->read_urb->pipe);
+
+@@ -1127,7 +1135,7 @@ static int iuu_open(struct usb_serial_port *port, struct file *filp)
+
+ iuu_uart_flush(port);
+
+- dbg("%s - initialization done", __FUNCTION__);
++ dbg("%s - initialization done", __func__);
+
+ memset(port->write_urb->transfer_buffer, IUU_UART_RX, 1);
+ usb_fill_bulk_urb(port->write_urb, port->serial->dev,
+@@ -1139,11 +1147,11 @@ static int iuu_open(struct usb_serial_port *port, struct file *filp)
+
+ if (result) {
+ dev_err(&port->dev, "%s - failed submitting read urb,"
+- " error %d\n", __FUNCTION__, result);
++ " error %d\n", __func__, result);
+ iuu_close(port, NULL);
+ return -EPROTO;
+ } else {
+- dbg("%s - rxcmd OK", __FUNCTION__);
++ dbg("%s - rxcmd OK", __func__);
+ }
+ return result;
+ }
+@@ -1154,9 +1162,6 @@ static struct usb_serial_driver iuu_device = {
+ .name = "iuu_phoenix",
+ },
+ .id_table = id_table,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_bulk_in = 1,
+- .num_bulk_out = 1,
+ .num_ports = 1,
+ .open = iuu_open,
+ .close = iuu_close,
+diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
+index ea7bba6..3df8a66 100644
+--- a/drivers/usb/serial/keyspan.c
++++ b/drivers/usb/serial/keyspan.c
+@@ -244,13 +244,13 @@ module_exit(keyspan_exit);
+
+ static void keyspan_rx_throttle (struct usb_serial_port *port)
+ {
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+ }
+
+
+ static void keyspan_rx_unthrottle (struct usb_serial_port *port)
+ {
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+ }
+
+
+@@ -258,7 +258,7 @@ static void keyspan_break_ctl (struct usb_serial_port *port, int break_state)
+ {
+ struct keyspan_port_private *p_priv;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ p_priv = usb_get_serial_port_data(port);
+
+@@ -280,7 +280,7 @@ static void keyspan_set_termios (struct usb_serial_port *port,
+ unsigned int cflag;
+ struct tty_struct *tty = port->tty;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ p_priv = usb_get_serial_port_data(port);
+ d_details = p_priv->device_details;
+@@ -377,7 +377,7 @@ static int keyspan_write(struct usb_serial_port *port,
+ }
+
+ dbg("%s - for port %d (%d chars), flip=%d",
+- __FUNCTION__, port->number, count, p_priv->out_flip);
++ __func__, port->number, count, p_priv->out_flip);
+
+ for (left = count; left > 0; left -= todo) {
+ todo = left;
+@@ -389,11 +389,11 @@ static int keyspan_write(struct usb_serial_port *port,
+ /* Check we have a valid urb/endpoint before we use it... */
+ if ((this_urb = p_priv->out_urbs[flip]) == NULL) {
+ /* no bulk out, so return 0 bytes written */
+- dbg("%s - no output urb :(", __FUNCTION__);
++ dbg("%s - no output urb :(", __func__);
+ return count;
+ }
+
+- dbg("%s - endpoint %d flip %d", __FUNCTION__, usb_pipeendpoint(this_urb->pipe), flip);
++ dbg("%s - endpoint %d flip %d", __func__, usb_pipeendpoint(this_urb->pipe), flip);
+
+ if (this_urb->status == -EINPROGRESS) {
+ if (time_before(jiffies, p_priv->tx_start_time[flip] + 10 * HZ))
+@@ -435,17 +435,17 @@ static void usa26_indat_callback(struct urb *urb)
+ unsigned char *data = urb->transfer_buffer;
+ int status = urb->status;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+ endpoint = usb_pipeendpoint(urb->pipe);
+
+ if (status) {
+ dbg("%s - nonzero status: %x on endpoint %d.",
+- __FUNCTION__, status, endpoint);
++ __func__, status, endpoint);
+ return;
+ }
+
+- port = (struct usb_serial_port *) urb->context;
++ port = urb->context;
+ tty = port->tty;
+ if (tty && urb->actual_length) {
+ /* 0x80 bit is error flag */
+@@ -459,7 +459,7 @@ static void usa26_indat_callback(struct urb *urb)
+ }
+ } else {
+ /* some bytes had errors, every byte has status */
+- dbg("%s - RX error!!!!", __FUNCTION__);
++ dbg("%s - RX error!!!!", __func__);
+ for (i = 0; i + 1 < urb->actual_length; i += 2) {
+ int stat = data[i], flag = 0;
+ if (stat & RXERROR_OVERRUN)
+@@ -479,7 +479,7 @@ static void usa26_indat_callback(struct urb *urb)
+ urb->dev = port->serial->dev;
+ if (port->open_count)
+ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+- dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
++ dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ }
+ return;
+ }
+@@ -490,9 +490,9 @@ static void usa2x_outdat_callback(struct urb *urb)
+ struct usb_serial_port *port;
+ struct keyspan_port_private *p_priv;
+
+- port = (struct usb_serial_port *) urb->context;
++ port = urb->context;
+ p_priv = usb_get_serial_port_data(port);
+- dbg ("%s - urb %d", __FUNCTION__, urb == p_priv->out_urbs[1]);
++ dbg ("%s - urb %d", __func__, urb == p_priv->out_urbs[1]);
+
+ if (port->open_count)
+ usb_serial_port_softint(port);
+@@ -500,7 +500,7 @@ static void usa2x_outdat_callback(struct urb *urb)
+
+ static void usa26_inack_callback(struct urb *urb)
+ {
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+ }
+
+@@ -509,11 +509,11 @@ static void usa26_outcont_callback(struct urb *urb)
+ struct usb_serial_port *port;
+ struct keyspan_port_private *p_priv;
+
+- port = (struct usb_serial_port *) urb->context;
++ port = urb->context;
+ p_priv = usb_get_serial_port_data(port);
+
+ if (p_priv->resend_cont) {
+- dbg ("%s - sending setup", __FUNCTION__);
++ dbg ("%s - sending setup", __func__);
+ keyspan_usa26_send_setup(port->serial, port, p_priv->resend_cont - 1);
+ }
+ }
+@@ -528,14 +528,14 @@ static void usa26_instat_callback(struct urb *urb)
+ int old_dcd_state, err;
+ int status = urb->status;
+
+- serial = (struct usb_serial *) urb->context;
++ serial = urb->context;
+
+ if (status) {
+- dbg("%s - nonzero status: %x", __FUNCTION__, status);
++ dbg("%s - nonzero status: %x", __func__, status);
+ return;
+ }
+ if (urb->actual_length != 9) {
+- dbg("%s - %d byte report??", __FUNCTION__, urb->actual_length);
++ dbg("%s - %d byte report??", __func__, urb->actual_length);
+ goto exit;
+ }
+
+@@ -543,7 +543,7 @@ static void usa26_instat_callback(struct urb *urb)
+
+ #if 0
+ dbg("%s - port status: port %d cts %d dcd %d dsr %d ri %d toff %d txoff %d rxen %d cr %d",
+- __FUNCTION__, msg->port, msg->hskia_cts, msg->gpia_dcd, msg->dsr, msg->ri, msg->_txOff,
++ __func__, msg->port, msg->hskia_cts, msg->gpia_dcd, msg->dsr, msg->ri, msg->_txOff,
+ msg->_txXoff, msg->rxEnabled, msg->controlResponse);
+ #endif
+
+@@ -552,7 +552,7 @@ static void usa26_instat_callback(struct urb *urb)
+
+ /* Check port number from message and retrieve private data */
+ if (msg->port >= serial->num_ports) {
+- dbg ("%s - Unexpected port number %d", __FUNCTION__, msg->port);
++ dbg ("%s - Unexpected port number %d", __func__, msg->port);
+ goto exit;
+ }
+ port = serial->port[msg->port];
+@@ -576,14 +576,14 @@ static void usa26_instat_callback(struct urb *urb)
+ /* Resubmit urb so we continue receiving */
+ urb->dev = serial->dev;
+ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+- dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
++ dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ }
+ exit: ;
+ }
+
+ static void usa26_glocont_callback(struct urb *urb)
+ {
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+ }
+
+@@ -597,9 +597,9 @@ static void usa28_indat_callback(struct urb *urb)
+ struct keyspan_port_private *p_priv;
+ int status = urb->status;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+- port = (struct usb_serial_port *) urb->context;
++ port = urb->context;
+ p_priv = usb_get_serial_port_data(port);
+ data = urb->transfer_buffer;
+
+@@ -609,11 +609,11 @@ static void usa28_indat_callback(struct urb *urb)
+ do {
+ if (status) {
+ dbg("%s - nonzero status: %x on endpoint %d.",
+- __FUNCTION__, status, usb_pipeendpoint(urb->pipe));
++ __func__, status, usb_pipeendpoint(urb->pipe));
+ return;
+ }
+
+- port = (struct usb_serial_port *) urb->context;
++ port = urb->context;
+ p_priv = usb_get_serial_port_data(port);
+ data = urb->transfer_buffer;
+
+@@ -629,7 +629,7 @@ static void usa28_indat_callback(struct urb *urb)
+ urb->dev = port->serial->dev;
+ if (port->open_count)
+ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+- dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
++ dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ }
+ p_priv->in_flip ^= 1;
+
+@@ -639,7 +639,7 @@ static void usa28_indat_callback(struct urb *urb)
+
+ static void usa28_inack_callback(struct urb *urb)
+ {
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+ }
+
+ static void usa28_outcont_callback(struct urb *urb)
+@@ -647,11 +647,11 @@ static void usa28_outcont_callback(struct urb *urb)
+ struct usb_serial_port *port;
+ struct keyspan_port_private *p_priv;
+
+- port = (struct usb_serial_port *) urb->context;
++ port = urb->context;
+ p_priv = usb_get_serial_port_data(port);
+
+ if (p_priv->resend_cont) {
+- dbg ("%s - sending setup", __FUNCTION__);
++ dbg ("%s - sending setup", __func__);
+ keyspan_usa28_send_setup(port->serial, port, p_priv->resend_cont - 1);
+ }
+ }
+@@ -667,19 +667,19 @@ static void usa28_instat_callback(struct urb *urb)
+ int old_dcd_state;
+ int status = urb->status;
+
+- serial = (struct usb_serial *) urb->context;
++ serial = urb->context;
+
+ if (status) {
+- dbg("%s - nonzero status: %x", __FUNCTION__, status);
++ dbg("%s - nonzero status: %x", __func__, status);
+ return;
+ }
+
+ if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) {
+- dbg("%s - bad length %d", __FUNCTION__, urb->actual_length);
++ dbg("%s - bad length %d", __func__, urb->actual_length);
+ goto exit;
+ }
+
+- /*dbg("%s %x %x %x %x %x %x %x %x %x %x %x %x", __FUNCTION__
++ /*dbg("%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__
+ data[0], data[1], data[2], data[3], data[4], data[5],
+ data[6], data[7], data[8], data[9], data[10], data[11]);*/
+
+@@ -689,7 +689,7 @@ static void usa28_instat_callback(struct urb *urb)
+
+ /* Check port number from message and retrieve private data */
+ if (msg->port >= serial->num_ports) {
+- dbg ("%s - Unexpected port number %d", __FUNCTION__, msg->port);
++ dbg ("%s - Unexpected port number %d", __func__, msg->port);
+ goto exit;
+ }
+ port = serial->port[msg->port];
+@@ -713,14 +713,14 @@ static void usa28_instat_callback(struct urb *urb)
+ /* Resubmit urb so we continue receiving */
+ urb->dev = serial->dev;
+ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+- dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
++ dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ }
+ exit: ;
+ }
+
+ static void usa28_glocont_callback(struct urb *urb)
+ {
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+ }
+
+
+@@ -731,15 +731,15 @@ static void usa49_glocont_callback(struct urb *urb)
+ struct keyspan_port_private *p_priv;
+ int i;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+- serial = (struct usb_serial *) urb->context;
++ serial = urb->context;
+ for (i = 0; i < serial->num_ports; ++i) {
+ port = serial->port[i];
+ p_priv = usb_get_serial_port_data(port);
+
+ if (p_priv->resend_cont) {
+- dbg ("%s - sending setup", __FUNCTION__);
++ dbg ("%s - sending setup", __func__);
+ keyspan_usa49_send_setup(serial, port, p_priv->resend_cont - 1);
+ break;
+ }
+@@ -759,21 +759,21 @@ static void usa49_instat_callback(struct urb *urb)
+ int old_dcd_state;
+ int status = urb->status;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+- serial = (struct usb_serial *) urb->context;
++ serial = urb->context;
+
+ if (status) {
+- dbg("%s - nonzero status: %x", __FUNCTION__, status);
++ dbg("%s - nonzero status: %x", __func__, status);
+ return;
+ }
+
+ if (urb->actual_length != sizeof(struct keyspan_usa49_portStatusMessage)) {
+- dbg("%s - bad length %d", __FUNCTION__, urb->actual_length);
++ dbg("%s - bad length %d", __func__, urb->actual_length);
+ goto exit;
+ }
+
+- /*dbg(" %x %x %x %x %x %x %x %x %x %x %x", __FUNCTION__,
++ /*dbg(" %x %x %x %x %x %x %x %x %x %x %x", __func__,
+ data[0], data[1], data[2], data[3], data[4], data[5],
+ data[6], data[7], data[8], data[9], data[10]);*/
+
+@@ -782,7 +782,7 @@ static void usa49_instat_callback(struct urb *urb)
+
+ /* Check port number from message and retrieve private data */
+ if (msg->portNumber >= serial->num_ports) {
+- dbg ("%s - Unexpected port number %d", __FUNCTION__, msg->portNumber);
++ dbg ("%s - Unexpected port number %d", __func__, msg->portNumber);
+ goto exit;
+ }
+ port = serial->port[msg->portNumber];
+@@ -807,14 +807,14 @@ static void usa49_instat_callback(struct urb *urb)
+ urb->dev = serial->dev;
+
+ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+- dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
++ dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ }
+ exit: ;
+ }
+
+ static void usa49_inack_callback(struct urb *urb)
+ {
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+ }
+
+ static void usa49_indat_callback(struct urb *urb)
+@@ -826,17 +826,17 @@ static void usa49_indat_callback(struct urb *urb)
+ unsigned char *data = urb->transfer_buffer;
+ int status = urb->status;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+ endpoint = usb_pipeendpoint(urb->pipe);
+
+ if (status) {
+- dbg("%s - nonzero status: %x on endpoint %d.", __FUNCTION__,
++ dbg("%s - nonzero status: %x on endpoint %d.", __func__,
+ status, endpoint);
+ return;
+ }
+
+- port = (struct usb_serial_port *) urb->context;
++ port = urb->context;
+ tty = port->tty;
+ if (tty && urb->actual_length) {
+ /* 0x80 bit is error flag */
+@@ -866,7 +866,7 @@ static void usa49_indat_callback(struct urb *urb)
+ urb->dev = port->serial->dev;
+ if (port->open_count)
+ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+- dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
++ dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ }
+ }
+
+@@ -879,12 +879,12 @@ static void usa49wg_indat_callback(struct urb *urb)
+ unsigned char *data = urb->transfer_buffer;
+ int status = urb->status;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+ serial = urb->context;
+
+ if (status) {
+- dbg("%s - nonzero status: %x", __FUNCTION__, status);
++ dbg("%s - nonzero status: %x", __func__, status);
+ return;
+ }
+
+@@ -898,7 +898,7 @@ static void usa49wg_indat_callback(struct urb *urb)
+ /* Check port number from message*/
+ if (data[i] >= serial->num_ports) {
+ dbg ("%s - Unexpected port number %d",
+- __FUNCTION__, data[i]);
++ __func__, data[i]);
+ return;
+ }
+ port = serial->port[data[i++]];
+@@ -944,13 +944,13 @@ static void usa49wg_indat_callback(struct urb *urb)
+
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err != 0)
+- dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
++ dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ }
+
+ /* not used, usa-49 doesn't have per-port control endpoints */
+ static void usa49_outcont_callback(struct urb *urb)
+ {
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+ }
+
+ static void usa90_indat_callback(struct urb *urb)
+@@ -963,17 +963,17 @@ static void usa90_indat_callback(struct urb *urb)
+ unsigned char *data = urb->transfer_buffer;
+ int status = urb->status;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+ endpoint = usb_pipeendpoint(urb->pipe);
+
+ if (status) {
+ dbg("%s - nonzero status: %x on endpoint %d.",
+- __FUNCTION__, status, endpoint);
++ __func__, status, endpoint);
+ return;
+ }
+
+- port = (struct usb_serial_port *) urb->context;
++ port = urb->context;
+ p_priv = usb_get_serial_port_data(port);
+
+ tty = port->tty;
+@@ -1000,7 +1000,7 @@ static void usa90_indat_callback(struct urb *urb)
+ }
+ else {
+ /* some bytes had errors, every byte has status */
+- dbg("%s - RX error!!!!", __FUNCTION__);
++ dbg("%s - RX error!!!!", __func__);
+ for (i = 0; i + 1 < urb->actual_length; i += 2) {
+ int stat = data[i], flag = 0;
+ if (stat & RXERROR_OVERRUN)
+@@ -1021,7 +1021,7 @@ static void usa90_indat_callback(struct urb *urb)
+ urb->dev = port->serial->dev;
+ if (port->open_count)
+ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+- dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
++ dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ }
+ return;
+ }
+@@ -1037,14 +1037,14 @@ static void usa90_instat_callback(struct urb *urb)
+ int old_dcd_state, err;
+ int status = urb->status;
+
+- serial = (struct usb_serial *) urb->context;
++ serial = urb->context;
+
+ if (status) {
+- dbg("%s - nonzero status: %x", __FUNCTION__, status);
++ dbg("%s - nonzero status: %x", __func__, status);
+ return;
+ }
+ if (urb->actual_length < 14) {
+- dbg("%s - %d byte report??", __FUNCTION__, urb->actual_length);
++ dbg("%s - %d byte report??", __func__, urb->actual_length);
+ goto exit;
+ }
+
+@@ -1073,7 +1073,7 @@ static void usa90_instat_callback(struct urb *urb)
+ /* Resubmit urb so we continue receiving */
+ urb->dev = serial->dev;
+ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+- dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
++ dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ }
+ exit:
+ ;
+@@ -1084,11 +1084,11 @@ static void usa90_outcont_callback(struct urb *urb)
+ struct usb_serial_port *port;
+ struct keyspan_port_private *p_priv;
+
+- port = (struct usb_serial_port *) urb->context;
++ port = urb->context;
+ p_priv = usb_get_serial_port_data(port);
+
+ if (p_priv->resend_cont) {
+- dbg ("%s - sending setup", __FUNCTION__);
++ dbg ("%s - sending setup", __func__);
+ keyspan_usa90_send_setup(port->serial, port, p_priv->resend_cont - 1);
+ }
+ }
+@@ -1105,17 +1105,17 @@ static void usa67_instat_callback(struct urb *urb)
+ int old_dcd_state;
+ int status = urb->status;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+ serial = urb->context;
+
+ if (status) {
+- dbg("%s - nonzero status: %x", __FUNCTION__, status);
++ dbg("%s - nonzero status: %x", __func__, status);
+ return;
+ }
+
+ if (urb->actual_length != sizeof(struct keyspan_usa67_portStatusMessage)) {
+- dbg("%s - bad length %d", __FUNCTION__, urb->actual_length);
++ dbg("%s - bad length %d", __func__, urb->actual_length);
+ return;
+ }
+
+@@ -1125,7 +1125,7 @@ static void usa67_instat_callback(struct urb *urb)
+
+ /* Check port number from message and retrieve private data */
+ if (msg->port >= serial->num_ports) {
+- dbg ("%s - Unexpected port number %d", __FUNCTION__, msg->port);
++ dbg ("%s - Unexpected port number %d", __func__, msg->port);
+ return;
+ }
+
+@@ -1149,7 +1149,7 @@ static void usa67_instat_callback(struct urb *urb)
+ urb->dev = serial->dev;
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err != 0)
+- dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
++ dbg("%s - resubmit read urb failed. (%d)", __func__, err);
+ }
+
+ static void usa67_glocont_callback(struct urb *urb)
+@@ -1159,7 +1159,7 @@ static void usa67_glocont_callback(struct urb *urb)
+ struct keyspan_port_private *p_priv;
+ int i;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+ serial = urb->context;
+ for (i = 0; i < serial->num_ports; ++i) {
+@@ -1167,7 +1167,7 @@ static void usa67_glocont_callback(struct urb *urb)
+ p_priv = usb_get_serial_port_data(port);
+
+ if (p_priv->resend_cont) {
+- dbg ("%s - sending setup", __FUNCTION__);
++ dbg ("%s - sending setup", __func__);
+ keyspan_usa67_send_setup(serial, port,
+ p_priv->resend_cont - 1);
+ break;
+@@ -1183,10 +1183,11 @@ static int keyspan_write_room (struct usb_serial_port *port)
+ int data_len;
+ struct urb *this_urb;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+ p_priv = usb_get_serial_port_data(port);
+ d_details = p_priv->device_details;
+
++ /* FIXME: locking */
+ if (d_details->msg_format == msg_usa90)
+ data_len = 64;
+ else
+@@ -1203,13 +1204,13 @@ static int keyspan_write_room (struct usb_serial_port *port)
+ if (this_urb->status != -EINPROGRESS)
+ return (data_len);
+ }
+- return (0);
++ return 0;
+ }
+
+
+ static int keyspan_chars_in_buffer (struct usb_serial_port *port)
+ {
+- return (0);
++ return 0;
+ }
+
+
+@@ -1228,7 +1229,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
+ p_priv = usb_get_serial_port_data(port);
+ d_details = p_priv->device_details;
+
+- dbg("%s - port%d.", __FUNCTION__, port->number);
++ dbg("%s - port%d.", __func__, port->number);
+
+ /* Set some sane defaults */
+ p_priv->rts_state = 1;
+@@ -1253,7 +1254,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
+ usb_clear_halt(urb->dev, urb->pipe);
+
+ if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
+- dbg("%s - submit urb %d failed (%d)", __FUNCTION__, i, err);
++ dbg("%s - submit urb %d failed (%d)", __func__, i, err);
+ }
+ }
+
+@@ -1289,7 +1290,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
+ //mdelay(100);
+ //keyspan_set_termios(port, NULL);
+
+- return (0);
++ return 0;
+ }
+
+ static inline void stop_urb(struct urb *urb)
+@@ -1305,7 +1306,7 @@ static void keyspan_close(struct usb_serial_port *port, struct file *filp)
+ struct keyspan_serial_private *s_priv;
+ struct keyspan_port_private *p_priv;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+ s_priv = usb_get_serial_data(serial);
+ p_priv = usb_get_serial_port_data(port);
+
+@@ -1320,7 +1321,7 @@ static void keyspan_close(struct usb_serial_port *port, struct file *filp)
+ }
+
+ /*while (p_priv->outcont_urb->status == -EINPROGRESS) {
+- dbg("%s - urb in progress", __FUNCTION__);
++ dbg("%s - urb in progress", __func__);
+ }*/
+
+ p_priv->out_flip = 0;
+@@ -1484,10 +1485,10 @@ static struct urb *keyspan_setup_urb (struct usb_serial *serial, int endpoint,
+ if (endpoint == -1)
+ return NULL; /* endpoint not needed */
+
+- dbg ("%s - alloc for endpoint %d.", __FUNCTION__, endpoint);
++ dbg ("%s - alloc for endpoint %d.", __func__, endpoint);
+ urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
+ if (urb == NULL) {
+- dbg ("%s - alloc for endpoint %d failed.", __FUNCTION__, endpoint);
++ dbg ("%s - alloc for endpoint %d failed.", __func__, endpoint);
+ return NULL;
+ }
+
+@@ -1588,7 +1589,7 @@ static void keyspan_setup_urbs(struct usb_serial *serial)
+ struct callbacks *cback;
+ int endp;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+ s_priv = usb_get_serial_data(serial);
+ d_details = s_priv->device_details;
+@@ -1662,7 +1663,7 @@ static int keyspan_usa19_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
+ div, /* divisor */
+ cnt; /* inverse of divisor (programmed into 8051) */
+
+- dbg ("%s - %d.", __FUNCTION__, baud_rate);
++ dbg ("%s - %d.", __func__, baud_rate);
+
+ /* prevent divide by zero... */
+ if( (b16 = (baud_rate * 16L)) == 0) {
+@@ -1695,7 +1696,7 @@ static int keyspan_usa19_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
+ *rate_hi = (u8) ((cnt >> 8) & 0xff);
+ }
+ if (rate_low && rate_hi) {
+- dbg ("%s - %d %02x %02x.", __FUNCTION__, baud_rate, *rate_hi, *rate_low);
++ dbg ("%s - %d %02x %02x.", __func__, baud_rate, *rate_hi, *rate_low);
+ }
+
+ return (KEYSPAN_BAUD_RATE_OK);
+@@ -1708,7 +1709,7 @@ static int keyspan_usa19hs_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
+ u32 b16, /* baud rate times 16 (actual rate used internally) */
+ div; /* divisor */
+
+- dbg ("%s - %d.", __FUNCTION__, baud_rate);
++ dbg ("%s - %d.", __func__, baud_rate);
+
+ /* prevent divide by zero... */
+ if( (b16 = (baud_rate * 16L)) == 0)
+@@ -1731,7 +1732,7 @@ static int keyspan_usa19hs_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
+ *rate_hi = (u8) ((div >> 8) & 0xff);
+
+ if (rate_low && rate_hi)
+- dbg ("%s - %d %02x %02x.", __FUNCTION__, baud_rate, *rate_hi, *rate_low);
++ dbg ("%s - %d %02x %02x.", __func__, baud_rate, *rate_hi, *rate_low);
+
+ return (KEYSPAN_BAUD_RATE_OK);
+ }
+@@ -1748,7 +1749,7 @@ static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
+ u8 best_prescaler;
+ int i;
+
+- dbg ("%s - %d.", __FUNCTION__, baud_rate);
++ dbg ("%s - %d.", __func__, baud_rate);
+
+ /* prevent divide by zero */
+ if( (b16 = baud_rate * 16L) == 0) {
+@@ -1796,7 +1797,7 @@ static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
+ }
+ if (prescaler) {
+ *prescaler = best_prescaler;
+- /* dbg("%s - %d %d", __FUNCTION__, *prescaler, div); */
++ /* dbg("%s - %d %d", __func__, *prescaler, div); */
+ }
+ return (KEYSPAN_BAUD_RATE_OK);
+ }
+@@ -1809,7 +1810,7 @@ static int keyspan_usa28_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
+ div, /* divisor */
+ cnt; /* inverse of divisor (programmed into 8051) */
+
+- dbg ("%s - %d.", __FUNCTION__, baud_rate);
++ dbg ("%s - %d.", __func__, baud_rate);
+
+ /* prevent divide by zero */
+ if ((b16 = baud_rate * 16L) == 0)
+@@ -1848,7 +1849,7 @@ static int keyspan_usa28_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
+ if (rate_hi) {
+ *rate_hi = (u8) ((cnt >> 8) & 0xff);
+ }
+- dbg ("%s - %d OK.", __FUNCTION__, baud_rate);
++ dbg ("%s - %d OK.", __func__, baud_rate);
+ return (KEYSPAN_BAUD_RATE_OK);
+ }
+
+@@ -1864,7 +1865,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
+ struct urb *this_urb;
+ int device_port, err;
+
+- dbg ("%s reset=%d", __FUNCTION__, reset_port);
++ dbg ("%s reset=%d", __func__, reset_port);
+
+ s_priv = usb_get_serial_data(serial);
+ p_priv = usb_get_serial_port_data(port);
+@@ -1874,11 +1875,11 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
+ outcont_urb = d_details->outcont_endpoints[port->number];
+ this_urb = p_priv->outcont_urb;
+
+- dbg("%s - endpoint %d", __FUNCTION__, usb_pipeendpoint(this_urb->pipe));
++ dbg("%s - endpoint %d", __func__, usb_pipeendpoint(this_urb->pipe));
+
+ /* Make sure we have an urb then send the message */
+ if (this_urb == NULL) {
+- dbg("%s - oops no urb.", __FUNCTION__);
++ dbg("%s - oops no urb.", __func__);
+ return -1;
+ }
+
+@@ -1887,7 +1888,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
+ if ((reset_port + 1) > p_priv->resend_cont)
+ p_priv->resend_cont = reset_port + 1;
+ if (this_urb->status == -EINPROGRESS) {
+- /* dbg ("%s - already writing", __FUNCTION__); */
++ /* dbg ("%s - already writing", __func__); */
+ mdelay(5);
+ return(-1);
+ }
+@@ -1901,7 +1902,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
+ if (d_details->calculate_baud_rate
+ (p_priv->baud, d_details->baudclk, &msg.baudHi,
+ &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
+- dbg("%s - Invalid baud rate %d requested, using 9600.", __FUNCTION__,
++ dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
+ p_priv->baud);
+ msg.baudLo = 0;
+ msg.baudHi = 125; /* Values for 9600 baud */
+@@ -1996,17 +1997,17 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
+
+ this_urb->dev = serial->dev;
+ if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
+- dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__, err);
++ dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
+ }
+ #if 0
+ else {
+- dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __FUNCTION__
++ dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__
+ outcont_urb, this_urb->transfer_buffer_length,
+ usb_pipeendpoint(this_urb->pipe));
+ }
+ #endif
+
+- return (0);
++ return 0;
+ }
+
+ static int keyspan_usa28_send_setup(struct usb_serial *serial,
+@@ -2020,7 +2021,7 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
+ struct urb *this_urb;
+ int device_port, err;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+ s_priv = usb_get_serial_data(serial);
+ p_priv = usb_get_serial_port_data(port);
+@@ -2029,7 +2030,7 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
+
+ /* only do something if we have a bulk out endpoint */
+ if ((this_urb = p_priv->outcont_urb) == NULL) {
+- dbg("%s - oops no urb.", __FUNCTION__);
++ dbg("%s - oops no urb.", __func__);
+ return -1;
+ }
+
+@@ -2038,7 +2039,7 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
+ if ((reset_port + 1) > p_priv->resend_cont)
+ p_priv->resend_cont = reset_port + 1;
+ if (this_urb->status == -EINPROGRESS) {
+- dbg ("%s already writing", __FUNCTION__);
++ dbg ("%s already writing", __func__);
+ mdelay(5);
+ return(-1);
+ }
+@@ -2048,7 +2049,7 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
+ msg.setBaudRate = 1;
+ if (d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk,
+ &msg.baudHi, &msg.baudLo, NULL, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
+- dbg("%s - Invalid baud rate requested %d.", __FUNCTION__, p_priv->baud);
++ dbg("%s - Invalid baud rate requested %d.", __func__, p_priv->baud);
+ msg.baudLo = 0xff;
+ msg.baudHi = 0xb2; /* Values for 9600 baud */
+ }
+@@ -2122,16 +2123,16 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
+
+ this_urb->dev = serial->dev;
+ if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
+- dbg("%s - usb_submit_urb(setup) failed", __FUNCTION__);
++ dbg("%s - usb_submit_urb(setup) failed", __func__);
+ }
+ #if 0
+ else {
+- dbg("%s - usb_submit_urb(setup) OK %d bytes", __FUNCTION__,
++ dbg("%s - usb_submit_urb(setup) OK %d bytes", __func__,
+ this_urb->transfer_buffer_length);
+ }
+ #endif
+
+- return (0);
++ return 0;
+ }
+
+ static int keyspan_usa49_send_setup(struct usb_serial *serial,
+@@ -2146,7 +2147,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
+ struct urb *this_urb;
+ int err, device_port;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+ s_priv = usb_get_serial_data(serial);
+ p_priv = usb_get_serial_port_data(port);
+@@ -2157,11 +2158,11 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
+ /* Work out which port within the device is being setup */
+ device_port = port->number - port->serial->minor;
+
+- dbg("%s - endpoint %d port %d (%d)",__FUNCTION__, usb_pipeendpoint(this_urb->pipe), port->number, device_port);
++ dbg("%s - endpoint %d port %d (%d)",__func__, usb_pipeendpoint(this_urb->pipe), port->number, device_port);
+
+ /* Make sure we have an urb then send the message */
+ if (this_urb == NULL) {
+- dbg("%s - oops no urb for port %d.", __FUNCTION__, port->number);
++ dbg("%s - oops no urb for port %d.", __func__, port->number);
+ return -1;
+ }
+
+@@ -2171,7 +2172,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
+ p_priv->resend_cont = reset_port + 1;
+
+ if (this_urb->status == -EINPROGRESS) {
+- /* dbg ("%s - already writing", __FUNCTION__); */
++ /* dbg ("%s - already writing", __func__); */
+ mdelay(5);
+ return(-1);
+ }
+@@ -2188,7 +2189,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
+ if (d_details->calculate_baud_rate
+ (p_priv->baud, d_details->baudclk, &msg.baudHi,
+ &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
+- dbg("%s - Invalid baud rate %d requested, using 9600.", __FUNCTION__,
++ dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
+ p_priv->baud);
+ msg.baudLo = 0;
+ msg.baudHi = 125; /* Values for 9600 baud */
+@@ -2307,17 +2308,17 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
+ this_urb->dev = serial->dev;
+ }
+ if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
+- dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__, err);
++ dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
+ }
+ #if 0
+ else {
+- dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __FUNCTION__,
++ dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__,
+ outcont_urb, this_urb->transfer_buffer_length,
+ usb_pipeendpoint(this_urb->pipe));
+ }
+ #endif
+
+- return (0);
++ return 0;
+ }
+
+ static int keyspan_usa90_send_setup(struct usb_serial *serial,
+@@ -2332,7 +2333,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
+ int err;
+ u8 prescaler;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+ s_priv = usb_get_serial_data(serial);
+ p_priv = usb_get_serial_port_data(port);
+@@ -2340,7 +2341,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
+
+ /* only do something if we have a bulk out endpoint */
+ if ((this_urb = p_priv->outcont_urb) == NULL) {
+- dbg("%s - oops no urb.", __FUNCTION__);
++ dbg("%s - oops no urb.", __func__);
+ return -1;
+ }
+
+@@ -2349,7 +2350,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
+ if ((reset_port + 1) > p_priv->resend_cont)
+ p_priv->resend_cont = reset_port + 1;
+ if (this_urb->status == -EINPROGRESS) {
+- dbg ("%s already writing", __FUNCTION__);
++ dbg ("%s already writing", __func__);
+ mdelay(5);
+ return(-1);
+ }
+@@ -2363,7 +2364,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
+ if (d_details->calculate_baud_rate
+ (p_priv->baud, d_details->baudclk, &msg.baudHi,
+ &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE ) {
+- dbg("%s - Invalid baud rate %d requested, using 9600.", __FUNCTION__,
++ dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
+ p_priv->baud);
+ p_priv->baud = 9600;
+ d_details->calculate_baud_rate (p_priv->baud, d_details->baudclk,
+@@ -2453,9 +2454,9 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
+
+ this_urb->dev = serial->dev;
+ if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
+- dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__, err);
++ dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
+ }
+- return (0);
++ return 0;
+ }
+
+ static int keyspan_usa67_send_setup(struct usb_serial *serial,
+@@ -2469,7 +2470,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
+ struct urb *this_urb;
+ int err, device_port;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+ s_priv = usb_get_serial_data(serial);
+ p_priv = usb_get_serial_port_data(port);
+@@ -2482,7 +2483,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
+
+ /* Make sure we have an urb then send the message */
+ if (this_urb == NULL) {
+- dbg("%s - oops no urb for port %d.", __FUNCTION__,
++ dbg("%s - oops no urb for port %d.", __func__,
+ port->number);
+ return -1;
+ }
+@@ -2492,7 +2493,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
+ if ((reset_port + 1) > p_priv->resend_cont)
+ p_priv->resend_cont = reset_port + 1;
+ if (this_urb->status == -EINPROGRESS) {
+- /* dbg ("%s - already writing", __FUNCTION__); */
++ /* dbg ("%s - already writing", __func__); */
+ mdelay(5);
+ return(-1);
+ }
+@@ -2508,7 +2509,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
+ if (d_details->calculate_baud_rate
+ (p_priv->baud, d_details->baudclk, &msg.baudHi,
+ &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
+- dbg("%s - Invalid baud rate %d requested, using 9600.", __FUNCTION__,
++ dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
+ p_priv->baud);
+ msg.baudLo = 0;
+ msg.baudHi = 125; /* Values for 9600 baud */
+@@ -2601,9 +2602,9 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
+
+ err = usb_submit_urb(this_urb, GFP_ATOMIC);
+ if (err != 0)
+- dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__,
++ dbg("%s - usb_submit_urb(setup) failed (%d)", __func__,
+ err);
+- return (0);
++ return 0;
+ }
+
+ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
+@@ -2612,7 +2613,7 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
+ struct keyspan_serial_private *s_priv;
+ const struct keyspan_device_details *d_details;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+ s_priv = usb_get_serial_data(serial);
+ d_details = s_priv->device_details;
+@@ -2647,20 +2648,20 @@ static int keyspan_startup (struct usb_serial *serial)
+ struct keyspan_port_private *p_priv;
+ const struct keyspan_device_details *d_details;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
+ if (d_details->product_id == le16_to_cpu(serial->dev->descriptor.idProduct))
+ break;
+ if (d_details == NULL) {
+- dev_err(&serial->dev->dev, "%s - unknown product id %x\n", __FUNCTION__, le16_to_cpu(serial->dev->descriptor.idProduct));
++ dev_err(&serial->dev->dev, "%s - unknown product id %x\n", __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
+ return 1;
+ }
+
+ /* Setup private data for serial driver */
+ s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
+ if (!s_priv) {
+- dbg("%s - kmalloc for keyspan_serial_private failed.", __FUNCTION__);
++ dbg("%s - kmalloc for keyspan_serial_private failed.", __func__);
+ return -ENOMEM;
+ }
+
+@@ -2672,7 +2673,7 @@ static int keyspan_startup (struct usb_serial *serial)
+ port = serial->port[i];
+ p_priv = kzalloc(sizeof(struct keyspan_port_private), GFP_KERNEL);
+ if (!p_priv) {
+- dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __FUNCTION__, i);
++ dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __func__, i);
+ return (1);
+ }
+ p_priv->device_details = d_details;
+@@ -2685,18 +2686,18 @@ static int keyspan_startup (struct usb_serial *serial)
+ s_priv->instat_urb->dev = serial->dev;
+ err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
+ if (err != 0)
+- dbg("%s - submit instat urb failed %d", __FUNCTION__,
++ dbg("%s - submit instat urb failed %d", __func__,
+ err);
+ }
+ if (s_priv->indat_urb != NULL) {
+ s_priv->indat_urb->dev = serial->dev;
+ err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
+ if (err != 0)
+- dbg("%s - submit indat urb failed %d", __FUNCTION__,
++ dbg("%s - submit indat urb failed %d", __func__,
+ err);
+ }
+
+- return (0);
++ return 0;
+ }
+
+ static void keyspan_shutdown (struct usb_serial *serial)
+@@ -2706,7 +2707,7 @@ static void keyspan_shutdown (struct usb_serial *serial)
+ struct keyspan_serial_private *s_priv;
+ struct keyspan_port_private *p_priv;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ s_priv = usb_get_serial_data(serial);
+
+diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
+index 74ce8bc..8d6ed02 100644
+--- a/drivers/usb/serial/keyspan.h
++++ b/drivers/usb/serial/keyspan.h
+@@ -636,10 +636,6 @@ static struct usb_serial_driver keyspan_pre_device = {
+ },
+ .description = "Keyspan - (without firmware)",
+ .id_table = keyspan_pre_ids,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_interrupt_out = NUM_DONT_CARE,
+- .num_bulk_in = NUM_DONT_CARE,
+- .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 1,
+ .attach = keyspan_fake_startup,
+ };
+@@ -651,10 +647,6 @@ static struct usb_serial_driver keyspan_1port_device = {
+ },
+ .description = "Keyspan 1 port adapter",
+ .id_table = keyspan_1port_ids,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_interrupt_out = NUM_DONT_CARE,
+- .num_bulk_in = NUM_DONT_CARE,
+- .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 1,
+ .open = keyspan_open,
+ .close = keyspan_close,
+@@ -679,10 +671,6 @@ static struct usb_serial_driver keyspan_2port_device = {
+ },
+ .description = "Keyspan 2 port adapter",
+ .id_table = keyspan_2port_ids,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_interrupt_out = NUM_DONT_CARE,
+- .num_bulk_in = NUM_DONT_CARE,
+- .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 2,
+ .open = keyspan_open,
+ .close = keyspan_close,
+@@ -707,10 +695,6 @@ static struct usb_serial_driver keyspan_4port_device = {
+ },
+ .description = "Keyspan 4 port adapter",
+ .id_table = keyspan_4port_ids,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_interrupt_out = NUM_DONT_CARE,
+- .num_bulk_in = NUM_DONT_CARE,
+- .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 4,
+ .open = keyspan_open,
+ .close = keyspan_close,
+diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
+index b1fa5a3..ff54203 100644
+--- a/drivers/usb/serial/keyspan_pda.c
++++ b/drivers/usb/serial/keyspan_pda.c
+@@ -208,13 +208,13 @@ static void keyspan_pda_request_unthrottle(struct work_struct *work)
+ 2000);
+ if (result < 0)
+ dbg("%s - error %d from usb_control_msg",
+- __FUNCTION__, result);
++ __func__, result);
+ }
+
+
+ static void keyspan_pda_rx_interrupt (struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct tty_struct *tty = port->tty;
+ unsigned char *data = urb->transfer_buffer;
+ int i;
+@@ -232,11 +232,11 @@ static void keyspan_pda_rx_interrupt (struct urb *urb)
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ goto exit;
+ }
+
+@@ -274,7 +274,7 @@ exit:
+ retval = usb_submit_urb (urb, GFP_ATOMIC);
+ if (retval)
+ err ("%s - usb_submit_urb failed with result %d",
+- __FUNCTION__, retval);
++ __func__, retval);
+ }
+
+
+@@ -358,7 +358,7 @@ static void keyspan_pda_break_ctl (struct usb_serial_port *port, int break_state
+ value, 0, NULL, 0, 2000);
+ if (result < 0)
+ dbg("%s - error %d from usb_control_msg",
+- __FUNCTION__, result);
++ __func__, result);
+ /* there is something funky about this.. the TCSBRK that 'cu' performs
+ ought to translate into a break_ctl(-1),break_ctl(0) pair HZ/4
+ seconds apart, but it feels like the break sent isn't as long as it
+@@ -608,7 +608,7 @@ exit:
+
+ static void keyspan_pda_write_bulk_callback (struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct keyspan_pda_private *priv;
+
+ port->write_urb_busy = 0;
+@@ -636,14 +636,19 @@ static int keyspan_pda_write_room (struct usb_serial_port *port)
+ static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port)
+ {
+ struct keyspan_pda_private *priv;
++ unsigned long flags;
++ int ret = 0;
+
+ priv = usb_get_serial_port_data(port);
+
+ /* when throttled, return at least WAKEUP_CHARS to tell select() (via
+ n_tty.c:normal_poll() ) that we're not writeable. */
++
++ spin_lock_irqsave(&port->lock, flags);
+ if (port->write_urb_busy || priv->tx_throttled)
+- return 256;
+- return 0;
++ ret = 256;
++ spin_unlock_irqrestore(&port->lock, flags);
++ return ret;
+ }
+
+
+@@ -665,11 +670,11 @@ static int keyspan_pda_open (struct usb_serial_port *port, struct file *filp)
+ 1,
+ 2000);
+ if (rc < 0) {
+- dbg("%s - roomquery failed", __FUNCTION__);
++ dbg("%s - roomquery failed", __func__);
+ goto error;
+ }
+ if (rc == 0) {
+- dbg("%s - roomquery returned 0 bytes", __FUNCTION__);
++ dbg("%s - roomquery returned 0 bytes", __func__);
+ rc = -EIO;
+ goto error;
+ }
+@@ -688,7 +693,7 @@ static int keyspan_pda_open (struct usb_serial_port *port, struct file *filp)
+ port->interrupt_in_urb->dev = serial->dev;
+ rc = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ if (rc) {
+- dbg("%s - usb_submit_urb(read int) failed", __FUNCTION__);
++ dbg("%s - usb_submit_urb(read int) failed", __func__);
+ goto error;
+ }
+
+@@ -732,7 +737,7 @@ static int keyspan_pda_fake_startup (struct usb_serial *serial)
+ record = &xircom_pgs_firmware[0];
+ #endif
+ if (record == NULL) {
+- err("%s: unknown vendor, aborting.", __FUNCTION__);
++ err("%s: unknown vendor, aborting.", __func__);
+ return -ENODEV;
+ }
+
+@@ -779,7 +784,7 @@ static int keyspan_pda_startup (struct usb_serial *serial)
+
+ static void keyspan_pda_shutdown (struct usb_serial *serial)
+ {
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ kfree(usb_get_serial_port_data(serial->port[0]));
+ }
+@@ -793,9 +798,6 @@ static struct usb_serial_driver keyspan_pda_fake_device = {
+ .description = "Keyspan PDA - (prerenumeration)",
+ .usb_driver = &keyspan_pda_driver,
+ .id_table = id_table_fake,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_bulk_in = NUM_DONT_CARE,
+- .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 1,
+ .attach = keyspan_pda_fake_startup,
+ };
+@@ -810,9 +812,6 @@ static struct usb_serial_driver xircom_pgs_fake_device = {
+ .description = "Xircom / Entregra PGS - (prerenumeration)",
+ .usb_driver = &keyspan_pda_driver,
+ .id_table = id_table_fake_xircom,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_bulk_in = NUM_DONT_CARE,
+- .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 1,
+ .attach = keyspan_pda_fake_startup,
+ };
+@@ -826,9 +825,6 @@ static struct usb_serial_driver keyspan_pda_device = {
+ .description = "Keyspan PDA",
+ .usb_driver = &keyspan_pda_driver,
+ .id_table = id_table_std,
+- .num_interrupt_in = 1,
+- .num_bulk_in = 0,
+- .num_bulk_out = 1,
+ .num_ports = 1,
+ .open = keyspan_pda_open,
+ .close = keyspan_pda_close,
+diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
+index 55736df..b395ac7 100644
+--- a/drivers/usb/serial/kl5kusb105.c
++++ b/drivers/usb/serial/kl5kusb105.c
+@@ -126,9 +126,6 @@ static struct usb_serial_driver kl5kusb105d_device = {
+ .description = "KL5KUSB105D / PalmConnect",
+ .usb_driver = &kl5kusb105d_driver,
+ .id_table = id_table,
+- .num_interrupt_in = 1,
+- .num_bulk_in = 1,
+- .num_bulk_out = 1,
+ .num_ports = 1,
+ .open = klsi_105_open,
+ .close = klsi_105_close,
+@@ -194,7 +191,7 @@ static int klsi_105_chg_port_settings(struct usb_serial_port *port,
+ if (rc < 0)
+ err("Change port settings failed (error = %d)", rc);
+ info("%s - %d byte block, baudrate %x, databits %d, u1 %d, u2 %d",
+- __FUNCTION__,
++ __func__,
+ settings->pktlen,
+ settings->baudrate, settings->databits,
+ settings->unknown1, settings->unknown2);
+@@ -225,7 +222,7 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
+ __u8 status_buf[KLSI_STATUSBUF_LEN] = { -1,-1};
+ __u16 status;
+
+- info("%s - sending SIO Poll request", __FUNCTION__);
++ info("%s - sending SIO Poll request", __func__);
+ rc = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ KL5KUSB105A_SIO_POLL,
+@@ -240,7 +237,7 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
+ else {
+ status = le16_to_cpu(*(u16 *)status_buf);
+
+- info("%s - read status %x %x", __FUNCTION__,
++ info("%s - read status %x %x", __func__,
+ status_buf[0], status_buf[1]);
+
+ *line_state_p = klsi_105_status2linestate(status);
+@@ -268,7 +265,7 @@ static int klsi_105_startup (struct usb_serial *serial)
+ priv = kmalloc(sizeof(struct klsi_105_private),
+ GFP_KERNEL);
+ if (!priv) {
+- dbg("%skmalloc for klsi_105_private failed.", __FUNCTION__);
++ dbg("%skmalloc for klsi_105_private failed.", __func__);
+ i--;
+ goto err_cleanup;
+ }
+@@ -298,7 +295,7 @@ static int klsi_105_startup (struct usb_serial *serial)
+ urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE,
+ GFP_KERNEL);
+ if (!urb->transfer_buffer) {
+- err("%s - out of memory for urb buffers.", __FUNCTION__);
++ err("%s - out of memory for urb buffers.", __func__);
+ goto err_cleanup;
+ }
+ }
+@@ -328,7 +325,7 @@ static void klsi_105_shutdown (struct usb_serial *serial)
+ {
+ int i;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ /* stop reads and writes on all ports */
+ for (i=0; i < serial->num_ports; ++i) {
+@@ -373,7 +370,7 @@ static int klsi_105_open (struct usb_serial_port *port, struct file *filp)
+ struct klsi_105_port_settings cfg;
+ unsigned long flags;
+
+- dbg("%s port %d", __FUNCTION__, port->number);
++ dbg("%s port %d", __func__, port->number);
+
+ /* force low_latency on so that our tty_push actually forces
+ * the data through
+@@ -419,7 +416,7 @@ static int klsi_105_open (struct usb_serial_port *port, struct file *filp)
+
+ rc = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ if (rc) {
+- err("%s - failed submitting read urb, error %d", __FUNCTION__, rc);
++ err("%s - failed submitting read urb, error %d", __func__, rc);
+ retval = rc;
+ goto exit;
+ }
+@@ -437,14 +434,14 @@ static int klsi_105_open (struct usb_serial_port *port, struct file *filp)
+ err("Enabling read failed (error = %d)", rc);
+ retval = rc;
+ } else
+- dbg("%s - enabled reading", __FUNCTION__);
++ dbg("%s - enabled reading", __func__);
+
+ rc = klsi_105_get_line_state(port, &line_state);
+ if (rc >= 0) {
+ spin_lock_irqsave (&priv->lock, flags);
+ priv->line_state = line_state;
+ spin_unlock_irqrestore (&priv->lock, flags);
+- dbg("%s - read line state 0x%lx", __FUNCTION__, line_state);
++ dbg("%s - read line state 0x%lx", __func__, line_state);
+ retval = 0;
+ } else
+ retval = rc;
+@@ -459,7 +456,7 @@ static void klsi_105_close (struct usb_serial_port *port, struct file *filp)
+ struct klsi_105_private *priv = usb_get_serial_port_data(port);
+ int rc;
+
+- dbg("%s port %d", __FUNCTION__, port->number);
++ dbg("%s port %d", __func__, port->number);
+
+ mutex_lock(&port->serial->disc_mutex);
+ if (!port->serial->disconnected) {
+@@ -502,7 +499,7 @@ static int klsi_105_write (struct usb_serial_port *port,
+ int result, size;
+ int bytes_sent=0;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ while (count > 0) {
+ /* try to find a free urb (write 0 bytes if none) */
+@@ -514,21 +511,21 @@ static int klsi_105_write (struct usb_serial_port *port,
+ for (i=0; i<NUM_URBS; i++) {
+ if (priv->write_urb_pool[i]->status != -EINPROGRESS) {
+ urb = priv->write_urb_pool[i];
+- dbg("%s - using pool URB %d", __FUNCTION__, i);
++ dbg("%s - using pool URB %d", __func__, i);
+ break;
+ }
+ }
+ spin_unlock_irqrestore (&priv->lock, flags);
+
+ if (urb==NULL) {
+- dbg("%s - no more free urbs", __FUNCTION__);
++ dbg("%s - no more free urbs", __func__);
+ goto exit;
+ }
+
+ if (urb->transfer_buffer == NULL) {
+ urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
+ if (urb->transfer_buffer == NULL) {
+- err("%s - no more kernel memory...", __FUNCTION__);
++ err("%s - no more kernel memory...", __func__);
+ goto exit;
+ }
+ }
+@@ -554,7 +551,7 @@ static int klsi_105_write (struct usb_serial_port *port,
+ /* send the data out the bulk port */
+ result = usb_submit_urb(urb, GFP_ATOMIC);
+ if (result) {
+- err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
++ err("%s - failed submitting write urb, error %d", __func__, result);
+ goto exit;
+ }
+ buf += size;
+@@ -570,13 +567,13 @@ exit:
+
+ static void klsi_105_write_bulk_callback ( struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ int status = urb->status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (status) {
+- dbg("%s - nonzero write bulk status received: %d", __FUNCTION__,
++ dbg("%s - nonzero write bulk status received: %d", __func__,
+ status);
+ return;
+ }
+@@ -603,7 +600,7 @@ static int klsi_105_chars_in_buffer (struct usb_serial_port *port)
+
+ spin_unlock_irqrestore (&priv->lock, flags);
+
+- dbg("%s - returns %d", __FUNCTION__, chars);
++ dbg("%s - returns %d", __func__, chars);
+ return (chars);
+ }
+
+@@ -623,7 +620,7 @@ static int klsi_105_write_room (struct usb_serial_port *port)
+
+ spin_unlock_irqrestore (&priv->lock, flags);
+
+- dbg("%s - returns %d", __FUNCTION__, room);
++ dbg("%s - returns %d", __func__, room);
+ return (room);
+ }
+
+@@ -631,18 +628,18 @@ static int klsi_105_write_room (struct usb_serial_port *port)
+
+ static void klsi_105_read_bulk_callback (struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct klsi_105_private *priv = usb_get_serial_port_data(port);
+ struct tty_struct *tty;
+ unsigned char *data = urb->transfer_buffer;
+ int rc;
+ int status = urb->status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /* The urb might have been killed. */
+ if (status) {
+- dbg("%s - nonzero read bulk status received: %d", __FUNCTION__,
++ dbg("%s - nonzero read bulk status received: %d", __func__,
+ status);
+ return;
+ }
+@@ -652,12 +649,12 @@ static void klsi_105_read_bulk_callback (struct urb *urb)
+ */
+ if (urb->actual_length == 0) {
+ /* empty urbs seem to happen, we ignore them */
+- /* dbg("%s - emtpy URB", __FUNCTION__); */
++ /* dbg("%s - emtpy URB", __func__); */
+ ;
+ } else if (urb->actual_length <= 2) {
+- dbg("%s - size %d URB not understood", __FUNCTION__,
++ dbg("%s - size %d URB not understood", __func__,
+ urb->actual_length);
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
++ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
+ } else {
+ int bytes_sent = ((__u8 *) data)[0] +
+@@ -669,12 +666,12 @@ static void klsi_105_read_bulk_callback (struct urb *urb)
+ * intermixed tty_flip_buffer_push()s
+ * FIXME
+ */
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
++ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
+
+ if (bytes_sent + 2 > urb->actual_length) {
+ dbg("%s - trying to read more data than available"
+- " (%d vs. %d)", __FUNCTION__,
++ " (%d vs. %d)", __func__,
+ bytes_sent+2, urb->actual_length);
+ /* cap at implied limit */
+ bytes_sent = urb->actual_length - 2;
+@@ -697,7 +694,7 @@ static void klsi_105_read_bulk_callback (struct urb *urb)
+ port);
+ rc = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ if (rc)
+- err("%s - failed resubmitting read urb, error %d", __FUNCTION__, rc);
++ err("%s - failed resubmitting read urb, error %d", __func__, rc);
+ } /* klsi_105_read_bulk_callback */
+
+
+@@ -705,12 +702,14 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
+ struct ktermios *old_termios)
+ {
+ struct klsi_105_private *priv = usb_get_serial_port_data(port);
+- unsigned int iflag = port->tty->termios->c_iflag;
++ struct tty_struct *tty = port->tty;
++ unsigned int iflag = tty->termios->c_iflag;
+ unsigned int old_iflag = old_termios->c_iflag;
+- unsigned int cflag = port->tty->termios->c_cflag;
++ unsigned int cflag = tty->termios->c_cflag;
+ unsigned int old_cflag = old_termios->c_cflag;
+ struct klsi_105_port_settings cfg;
+ unsigned long flags;
++ speed_t baud;
+
+ /* lock while we are modifying the settings */
+ spin_lock_irqsave (&priv->lock, flags);
+@@ -718,10 +717,12 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
+ /*
+ * Update baud rate
+ */
++ baud = tty_get_baud_rate(tty);
++
+ if( (cflag & CBAUD) != (old_cflag & CBAUD) ) {
+ /* reassert DTR and (maybe) RTS on transition from B0 */
+ if( (old_cflag & CBAUD) == B0 ) {
+- dbg("%s: baud was B0", __FUNCTION__);
++ dbg("%s: baud was B0", __func__);
+ #if 0
+ priv->control_state |= TIOCM_DTR;
+ /* don't set RTS if using hardware flow control */
+@@ -731,8 +732,8 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
+ mct_u232_set_modem_ctrl(serial, priv->control_state);
+ #endif
+ }
+-
+- switch(tty_get_baud_rate(port->tty)) {
++ }
++ switch(baud) {
+ case 0: /* handled below */
+ break;
+ case 1200:
+@@ -760,35 +761,36 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
+ priv->cfg.baudrate = kl5kusb105a_sio_b115200;
+ break;
+ default:
+- err("KLSI USB->Serial converter:"
++ dbg("KLSI USB->Serial converter:"
+ " unsupported baudrate request, using default"
+ " of 9600");
+ priv->cfg.baudrate = kl5kusb105a_sio_b9600;
++ baud = 9600;
+ break;
+- }
+- if ((cflag & CBAUD) == B0 ) {
+- dbg("%s: baud is B0", __FUNCTION__);
+- /* Drop RTS and DTR */
+- /* maybe this should be simulated by sending read
+- * disable and read enable messages?
+- */
+- ;
++ }
++ if ((cflag & CBAUD) == B0 ) {
++ dbg("%s: baud is B0", __func__);
++ /* Drop RTS and DTR */
++ /* maybe this should be simulated by sending read
++ * disable and read enable messages?
++ */
++ ;
+ #if 0
+- priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
+- mct_u232_set_modem_ctrl(serial, priv->control_state);
++ priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
++ mct_u232_set_modem_ctrl(serial, priv->control_state);
+ #endif
+- }
+ }
++ tty_encode_baud_rate(tty, baud, baud);
+
+ if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
+ /* set the number of data bits */
+ switch (cflag & CSIZE) {
+ case CS5:
+- dbg("%s - 5 bits/byte not supported", __FUNCTION__);
++ dbg("%s - 5 bits/byte not supported", __func__);
+ spin_unlock_irqrestore (&priv->lock, flags);
+ return ;
+ case CS6:
+- dbg("%s - 6 bits/byte not supported", __FUNCTION__);
++ dbg("%s - 6 bits/byte not supported", __func__);
+ spin_unlock_irqrestore (&priv->lock, flags);
+ return ;
+ case CS7:
+@@ -810,6 +812,8 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
+ if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))
+ || (cflag & CSTOPB) != (old_cflag & CSTOPB) ) {
+
++ /* Not currently supported */
++ tty->termios->c_cflag &= ~(PARENB|PARODD|CSTOPB);
+ #if 0
+ priv->last_lcr = 0;
+
+@@ -837,6 +841,8 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
+ || (iflag & IXON) != (old_iflag & IXON)
+ || (cflag & CRTSCTS) != (old_cflag & CRTSCTS) ) {
+
++ /* Not currently supported */
++ tty->termios->c_cflag &= ~CRTSCTS;
+ /* Drop DTR/RTS if no flow control otherwise assert */
+ #if 0
+ if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS) )
+@@ -862,7 +868,7 @@ static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
+ struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
+ unsigned char lcr = priv->last_lcr;
+
+- dbg("%sstate=%d", __FUNCTION__, break_state);
++ dbg("%sstate=%d", __func__, break_state);
+
+ if (break_state)
+ lcr |= MCT_U232_SET_BREAK;
+@@ -877,7 +883,7 @@ static int klsi_105_tiocmget (struct usb_serial_port *port, struct file *file)
+ unsigned long flags;
+ int rc;
+ unsigned long line_state;
+- dbg("%s - request, just guessing", __FUNCTION__);
++ dbg("%s - request, just guessing", __func__);
+
+ rc = klsi_105_get_line_state(port, &line_state);
+ if (rc < 0) {
+@@ -889,7 +895,7 @@ static int klsi_105_tiocmget (struct usb_serial_port *port, struct file *file)
+ spin_lock_irqsave (&priv->lock, flags);
+ priv->line_state = line_state;
+ spin_unlock_irqrestore (&priv->lock, flags);
+- dbg("%s - read line state 0x%lx", __FUNCTION__, line_state);
++ dbg("%s - read line state 0x%lx", __func__, line_state);
+ return (int)line_state;
+ }
+
+@@ -898,7 +904,7 @@ static int klsi_105_tiocmset (struct usb_serial_port *port, struct file *file,
+ {
+ int retval = -EINVAL;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ /* if this ever gets implemented, it should be done something like this:
+ struct usb_serial *serial = port->serial;
+@@ -924,7 +930,7 @@ static int klsi_105_tiocmset (struct usb_serial_port *port, struct file *file,
+
+ static void klsi_105_throttle (struct usb_serial_port *port)
+ {
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+ usb_kill_urb(port->read_urb);
+ }
+
+@@ -932,12 +938,12 @@ static void klsi_105_unthrottle (struct usb_serial_port *port)
+ {
+ int result;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ port->read_urb->dev = port->serial->dev;
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ if (result)
+- err("%s - failed submitting read urb, error %d", __FUNCTION__,
++ err("%s - failed submitting read urb, error %d", __func__,
+ result);
+ }
+
+diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
+index 17b3bae..693f00d 100644
+--- a/drivers/usb/serial/kobil_sct.c
++++ b/drivers/usb/serial/kobil_sct.c
+@@ -113,10 +113,6 @@ static struct usb_serial_driver kobil_device = {
+ .description = "KOBIL USB smart card terminal",
+ .usb_driver = &kobil_driver,
+ .id_table = id_table,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_interrupt_out = NUM_DONT_CARE,
+- .num_bulk_in = 0,
+- .num_bulk_out = 0,
+ .num_ports = 1,
+ .attach = kobil_startup,
+ .shutdown = kobil_shutdown,
+@@ -139,7 +135,6 @@ struct kobil_private {
+ int filled; // index of the last char in buf
+ int cur_pos; // index of the next char to send in buf
+ __u16 device_type;
+- int line_state;
+ };
+
+
+@@ -161,7 +156,6 @@ static int kobil_startup (struct usb_serial *serial)
+ priv->filled = 0;
+ priv->cur_pos = 0;
+ priv->device_type = le16_to_cpu(serial->dev->descriptor.idProduct);
+- priv->line_state = 0;
+
+ switch (priv->device_type){
+ case KOBIL_ADAPTER_B_PRODUCT_ID:
+@@ -189,11 +183,11 @@ static int kobil_startup (struct usb_serial *serial)
+ for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
+ endpoint = &altsetting->endpoint[i];
+ if (usb_endpoint_is_int_out(&endpoint->desc)) {
+- dbg("%s Found interrupt out endpoint. Address: %d", __FUNCTION__, endpoint->desc.bEndpointAddress);
++ dbg("%s Found interrupt out endpoint. Address: %d", __func__, endpoint->desc.bEndpointAddress);
+ priv->write_int_endpoint_address = endpoint->desc.bEndpointAddress;
+ }
+ if (usb_endpoint_is_int_in(&endpoint->desc)) {
+- dbg("%s Found interrupt in endpoint. Address: %d", __FUNCTION__, endpoint->desc.bEndpointAddress);
++ dbg("%s Found interrupt in endpoint. Address: %d", __func__, endpoint->desc.bEndpointAddress);
+ priv->read_int_endpoint_address = endpoint->desc.bEndpointAddress;
+ }
+ }
+@@ -204,7 +198,7 @@ static int kobil_startup (struct usb_serial *serial)
+ static void kobil_shutdown (struct usb_serial *serial)
+ {
+ int i;
+- dbg("%s - port %d", __FUNCTION__, serial->port[0]->number);
++ dbg("%s - port %d", __func__, serial->port[0]->number);
+
+ for (i=0; i < serial->num_ports; ++i) {
+ while (serial->port[i]->open_count > 0) {
+@@ -224,9 +218,8 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
+ int transfer_buffer_length = 8;
+ int write_urb_transfer_buffer_length = 8;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+ priv = usb_get_serial_port_data(port);
+- priv->line_state = 0;
+
+ // someone sets the dev to 0 if the close method has been called
+ port->interrupt_in_urb->dev = port->serial->dev;
+@@ -252,10 +245,10 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
+
+ // allocate write_urb
+ if (!port->write_urb) {
+- dbg("%s - port %d Allocating port->write_urb", __FUNCTION__, port->number);
++ dbg("%s - port %d Allocating port->write_urb", __func__, port->number);
+ port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!port->write_urb) {
+- dbg("%s - port %d usb_alloc_urb failed", __FUNCTION__, port->number);
++ dbg("%s - port %d usb_alloc_urb failed", __func__, port->number);
+ kfree(transfer_buffer);
+ return -ENOMEM;
+ }
+@@ -281,7 +274,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
+ transfer_buffer_length,
+ KOBIL_TIMEOUT
+ );
+- dbg("%s - port %d Send get_HW_version URB returns: %i", __FUNCTION__, port->number, result);
++ dbg("%s - port %d Send get_HW_version URB returns: %i", __func__, port->number, result);
+ dbg("Harware version: %i.%i.%i", transfer_buffer[0], transfer_buffer[1], transfer_buffer[2] );
+
+ // get firmware version
+@@ -295,7 +288,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
+ transfer_buffer_length,
+ KOBIL_TIMEOUT
+ );
+- dbg("%s - port %d Send get_FW_version URB returns: %i", __FUNCTION__, port->number, result);
++ dbg("%s - port %d Send get_FW_version URB returns: %i", __func__, port->number, result);
+ dbg("Firmware version: %i.%i.%i", transfer_buffer[0], transfer_buffer[1], transfer_buffer[2] );
+
+ if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) {
+@@ -310,7 +303,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
+ 0,
+ KOBIL_TIMEOUT
+ );
+- dbg("%s - port %d Send set_baudrate URB returns: %i", __FUNCTION__, port->number, result);
++ dbg("%s - port %d Send set_baudrate URB returns: %i", __func__, port->number, result);
+
+ // reset all queues
+ result = usb_control_msg( port->serial->dev,
+@@ -323,13 +316,13 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
+ 0,
+ KOBIL_TIMEOUT
+ );
+- dbg("%s - port %d Send reset_all_queues URB returns: %i", __FUNCTION__, port->number, result);
++ dbg("%s - port %d Send reset_all_queues URB returns: %i", __func__, port->number, result);
+ }
+ if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
+ priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
+ // start reading (Adapter B 'cause PNP string)
+ result = usb_submit_urb( port->interrupt_in_urb, GFP_ATOMIC );
+- dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result);
++ dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result);
+ }
+
+ kfree(transfer_buffer);
+@@ -339,7 +332,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
+
+ static void kobil_close (struct usb_serial_port *port, struct file *filp)
+ {
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (port->write_urb) {
+ usb_kill_urb(port->write_urb);
+@@ -359,11 +352,11 @@ static void kobil_read_int_callback(struct urb *urb)
+ int status = urb->status;
+ // char *dbg_data;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (status) {
+ dbg("%s - port %d Read int status not zero: %d",
+- __FUNCTION__, port->number, status);
++ __func__, port->number, status);
+ return;
+ }
+
+@@ -393,7 +386,7 @@ static void kobil_read_int_callback(struct urb *urb)
+ port->interrupt_in_urb->dev = port->serial->dev;
+
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+- dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result);
++ dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result);
+ }
+
+
+@@ -411,21 +404,21 @@ static int kobil_write (struct usb_serial_port *port,
+ struct kobil_private * priv;
+
+ if (count == 0) {
+- dbg("%s - port %d write request of 0 bytes", __FUNCTION__, port->number);
++ dbg("%s - port %d write request of 0 bytes", __func__, port->number);
+ return 0;
+ }
+
+ priv = usb_get_serial_port_data(port);
+
+ if (count > (KOBIL_BUF_LENGTH - priv->filled)) {
+- dbg("%s - port %d Error: write request bigger than buffer size", __FUNCTION__, port->number);
++ dbg("%s - port %d Error: write request bigger than buffer size", __func__, port->number);
+ return -ENOMEM;
+ }
+
+ // Copy data to buffer
+ memcpy (priv->buf + priv->filled, buf, count);
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, priv->buf + priv->filled);
++ usb_serial_debug_data(debug, &port->dev, __func__, count, priv->buf + priv->filled);
+
+ priv->filled = priv->filled + count;
+
+@@ -457,7 +450,7 @@ static int kobil_write (struct usb_serial_port *port,
+
+ priv->cur_pos = priv->cur_pos + length;
+ result = usb_submit_urb( port->write_urb, GFP_NOIO );
+- dbg("%s - port %d Send write URB returns: %i", __FUNCTION__, port->number, result);
++ dbg("%s - port %d Send write URB returns: %i", __func__, port->number, result);
+ todo = priv->filled - priv->cur_pos;
+
+ if (todo > 0) {
+@@ -478,7 +471,7 @@ static int kobil_write (struct usb_serial_port *port,
+ port->interrupt_in_urb->dev = port->serial->dev;
+
+ result = usb_submit_urb( port->interrupt_in_urb, GFP_NOIO );
+- dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result);
++ dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result);
+ }
+ }
+ return count;
+@@ -487,7 +480,7 @@ static int kobil_write (struct usb_serial_port *port,
+
+ static int kobil_write_room (struct usb_serial_port *port)
+ {
+- //dbg("%s - port %d", __FUNCTION__, port->number);
++ //dbg("%s - port %d", __func__, port->number);
+ return 8;
+ }
+
+@@ -522,16 +515,13 @@ static int kobil_tiocmget(struct usb_serial_port *port, struct file *file)
+ KOBIL_TIMEOUT);
+
+ dbg("%s - port %d Send get_status_line_state URB returns: %i. Statusline: %02x",
+- __FUNCTION__, port->number, result, transfer_buffer[0]);
+-
+- if ((transfer_buffer[0] & SUSBCR_GSL_DSR) != 0) {
+- priv->line_state |= TIOCM_DSR;
+- } else {
+- priv->line_state &= ~TIOCM_DSR;
+- }
++ __func__, port->number, result, transfer_buffer[0]);
+
++ result = 0;
++ if ((transfer_buffer[0] & SUSBCR_GSL_DSR) != 0)
++ result = TIOCM_DSR;
+ kfree(transfer_buffer);
+- return priv->line_state;
++ return result;
+ }
+
+ static int kobil_tiocmset(struct usb_serial_port *port, struct file *file,
+@@ -544,6 +534,7 @@ static int kobil_tiocmset(struct usb_serial_port *port, struct file *file,
+ unsigned char *transfer_buffer;
+ int transfer_buffer_length = 8;
+
++ /* FIXME: locking ? */
+ priv = usb_get_serial_port_data(port);
+ if ((priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) || (priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)) {
+ // This device doesn't support ioctl calls
+@@ -567,9 +558,9 @@ static int kobil_tiocmset(struct usb_serial_port *port, struct file *file,
+
+ if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) {
+ if (dtr != 0)
+- dbg("%s - port %d Setting DTR", __FUNCTION__, port->number);
++ dbg("%s - port %d Setting DTR", __func__, port->number);
+ else
+- dbg("%s - port %d Clearing DTR", __FUNCTION__, port->number);
++ dbg("%s - port %d Clearing DTR", __func__, port->number);
+ result = usb_control_msg( port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0 ),
+ SUSBCRequest_SetStatusLinesOrQueues,
+@@ -581,9 +572,9 @@ static int kobil_tiocmset(struct usb_serial_port *port, struct file *file,
+ KOBIL_TIMEOUT);
+ } else {
+ if (rts != 0)
+- dbg("%s - port %d Setting RTS", __FUNCTION__, port->number);
++ dbg("%s - port %d Setting RTS", __func__, port->number);
+ else
+- dbg("%s - port %d Clearing RTS", __FUNCTION__, port->number);
++ dbg("%s - port %d Clearing RTS", __func__, port->number);
+ result = usb_control_msg( port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0 ),
+ SUSBCRequest_SetStatusLinesOrQueues,
+@@ -594,7 +585,7 @@ static int kobil_tiocmset(struct usb_serial_port *port, struct file *file,
+ 0,
+ KOBIL_TIMEOUT);
+ }
+- dbg("%s - port %d Send set_status_line URB returns: %i", __FUNCTION__, port->number, result);
++ dbg("%s - port %d Send set_status_line URB returns: %i", __func__, port->number, result);
+ kfree(transfer_buffer);
+ return (result < 0) ? result : 0;
+ }
+@@ -687,7 +678,7 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file * file, unsigne
+ KOBIL_TIMEOUT
+ );
+
+- dbg("%s - port %d Send reset_all_queues (FLUSH) URB returns: %i", __FUNCTION__, port->number, result);
++ dbg("%s - port %d Send reset_all_queues (FLUSH) URB returns: %i", __func__, port->number, result);
+ kfree(transfer_buffer);
+ return (result < 0) ? -EFAULT : 0;
+ default:
+diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
+index fc1cea4..5fc2cef 100644
+--- a/drivers/usb/serial/mct_u232.c
++++ b/drivers/usb/serial/mct_u232.c
+@@ -143,9 +143,6 @@ static struct usb_serial_driver mct_u232_device = {
+ .description = "MCT U232",
+ .usb_driver = &mct_u232_driver,
+ .id_table = id_table_combined,
+- .num_interrupt_in = 2,
+- .num_bulk_in = 0,
+- .num_bulk_out = 1,
+ .num_ports = 1,
+ .open = mct_u232_open,
+ .close = mct_u232_close,
+@@ -402,7 +399,7 @@ static void mct_u232_shutdown (struct usb_serial *serial)
+ struct mct_u232_private *priv;
+ int i;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ for (i=0; i < serial->num_ports; ++i) {
+ /* My special items, the standard routines free my urbs */
+@@ -424,7 +421,7 @@ static int mct_u232_open (struct usb_serial_port *port, struct file *filp)
+ unsigned char last_lcr;
+ unsigned char last_msr;
+
+- dbg("%s port %d", __FUNCTION__, port->number);
++ dbg("%s port %d", __func__, port->number);
+
+ /* Compensate for a hardware bug: although the Sitecom U232-P25
+ * device reports a maximum output packet size of 32 bytes,
+@@ -489,7 +486,7 @@ static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
+ unsigned int c_cflag;
+ unsigned int control_state;
+ struct mct_u232_private *priv = usb_get_serial_port_data(port);
+- dbg("%s port %d", __FUNCTION__, port->number);
++ dbg("%s port %d", __func__, port->number);
+
+ if (port->tty) {
+ c_cflag = port->tty->termios->c_cflag;
+@@ -517,7 +514,7 @@ static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
+
+ static void mct_u232_read_int_callback (struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct mct_u232_private *priv = usb_get_serial_port_data(port);
+ struct usb_serial *serial = port->serial;
+ struct tty_struct *tty;
+@@ -535,21 +532,21 @@ static void mct_u232_read_int_callback (struct urb *urb)
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ goto exit;
+ }
+
+ if (!serial) {
+- dbg("%s - bad serial pointer, exiting", __FUNCTION__);
++ dbg("%s - bad serial pointer, exiting", __func__);
+ return;
+ }
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++ dbg("%s - port %d", __func__, port->number);
++ usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+
+ /*
+ * Work-a-round: handle the 'usual' bulk-in pipe here
+@@ -606,7 +603,7 @@ exit:
+ retval = usb_submit_urb (urb, GFP_ATOMIC);
+ if (retval)
+ err ("%s - usb_submit_urb failed with result %d",
+- __FUNCTION__, retval);
++ __func__, retval);
+ } /* mct_u232_read_int_callback */
+
+ static void mct_u232_set_termios (struct usb_serial_port *port,
+@@ -636,7 +633,7 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
+
+ /* reassert DTR and RTS on transition from B0 */
+ if ((old_cflag & CBAUD) == B0) {
+- dbg("%s: baud was B0", __FUNCTION__);
++ dbg("%s: baud was B0", __func__);
+ control_state |= TIOCM_DTR | TIOCM_RTS;
+ mct_u232_set_modem_ctrl(serial, control_state);
+ }
+@@ -644,7 +641,7 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
+ mct_u232_set_baud_rate(serial, port, tty_get_baud_rate(port->tty));
+
+ if ((cflag & CBAUD) == B0 ) {
+- dbg("%s: baud is B0", __FUNCTION__);
++ dbg("%s: baud is B0", __func__);
+ /* Drop RTS and DTR */
+ control_state &= ~(TIOCM_DTR | TIOCM_RTS);
+ mct_u232_set_modem_ctrl(serial, control_state);
+@@ -699,7 +696,7 @@ static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
+ unsigned char lcr;
+ unsigned long flags;
+
+- dbg("%sstate=%d", __FUNCTION__, break_state);
++ dbg("%sstate=%d", __func__, break_state);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ lcr = priv->last_lcr;
+@@ -718,7 +715,7 @@ static int mct_u232_tiocmget (struct usb_serial_port *port, struct file *file)
+ unsigned int control_state;
+ unsigned long flags;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ control_state = priv->control_state;
+@@ -735,7 +732,7 @@ static int mct_u232_tiocmset (struct usb_serial_port *port, struct file *file,
+ unsigned int control_state;
+ unsigned long flags;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ control_state = priv->control_state;
+@@ -757,7 +754,7 @@ static int mct_u232_tiocmset (struct usb_serial_port *port, struct file *file,
+ static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
+ unsigned int cmd, unsigned long arg)
+ {
+- dbg("%scmd=0x%x", __FUNCTION__, cmd);
++ dbg("%scmd=0x%x", __func__, cmd);
+
+ /* Based on code from acm.c and others */
+ switch (cmd) {
+@@ -772,7 +769,7 @@ static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
+ return 0;
+
+ default:
+- dbg("%s: arg not supported - 0x%04x", __FUNCTION__,cmd);
++ dbg("%s: arg not supported - 0x%04x", __func__,cmd);
+ return(-ENOIOCTLCMD);
+ break;
+ }
+@@ -787,7 +784,7 @@ static void mct_u232_throttle (struct usb_serial_port *port)
+ struct tty_struct *tty;
+
+ tty = port->tty;
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->rx_flags |= THROTTLED;
+@@ -809,7 +806,7 @@ static void mct_u232_unthrottle (struct usb_serial_port *port)
+ unsigned int control_state;
+ struct tty_struct *tty;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ tty = port->tty;
+ spin_lock_irqsave(&priv->lock, flags);
+diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
+index 40f3a01..50f1fe2 100644
+--- a/drivers/usb/serial/mos7720.c
++++ b/drivers/usb/serial/mos7720.c
+@@ -118,11 +118,11 @@ static void mos7720_interrupt_callback(struct urb *urb)
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+- dbg("%s - urb shutting down with status: %d", __FUNCTION__,
++ dbg("%s - urb shutting down with status: %d", __func__,
+ status);
+ return;
+ default:
+- dbg("%s - nonzero urb status received: %d", __FUNCTION__,
++ dbg("%s - nonzero urb status received: %d", __func__,
+ status);
+ goto exit;
+ }
+@@ -183,7 +183,7 @@ exit:
+ if (result)
+ dev_err(&urb->dev->dev,
+ "%s - Error %d submitting control urb\n",
+- __FUNCTION__, result);
++ __func__, result);
+ return;
+ }
+
+@@ -214,7 +214,7 @@ static void mos7720_bulk_in_callback(struct urb *urb)
+
+ port = mos7720_port->port;
+
+- dbg("Entering...%s", __FUNCTION__);
++ dbg("Entering...%s", __func__);
+
+ data = urb->transfer_buffer;
+
+@@ -362,7 +362,7 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
+ urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
+ GFP_KERNEL);
+ if (!urb->transfer_buffer) {
+- err("%s-out of memory for urb buffers.", __FUNCTION__);
++ err("%s-out of memory for urb buffers.", __func__);
+ usb_free_urb(mos7720_port->write_urb_pool[j]);
+ mos7720_port->write_urb_pool[j] = NULL;
+ continue;
+@@ -479,7 +479,7 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
+ if (response)
+ dev_err(&port->dev,
+ "%s - Error %d submitting control urb\n",
+- __FUNCTION__, response);
++ __func__, response);
+ }
+
+ /* set up our bulk in urb */
+@@ -492,7 +492,7 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
+ response = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ if (response)
+ dev_err(&port->dev,
+- "%s - Error %d submitting read urb\n", __FUNCTION__, response);
++ "%s - Error %d submitting read urb\n", __func__, response);
+
+ /* initialize our icount structure */
+ memset(&(mos7720_port->icount), 0x00, sizeof(mos7720_port->icount));
+@@ -521,11 +521,11 @@ static int mos7720_chars_in_buffer(struct usb_serial_port *port)
+ int chars = 0;
+ struct moschip_port *mos7720_port;
+
+- dbg("%s:entering ...........", __FUNCTION__);
++ dbg("%s:entering ...........", __func__);
+
+ mos7720_port = usb_get_serial_port_data(port);
+ if (mos7720_port == NULL) {
+- dbg("%s:leaving ...........", __FUNCTION__);
++ dbg("%s:leaving ...........", __func__);
+ return -ENODEV;
+ }
+
+@@ -533,7 +533,7 @@ static int mos7720_chars_in_buffer(struct usb_serial_port *port)
+ if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status == -EINPROGRESS)
+ chars += URB_TRANSFER_BUFFER_SIZE;
+ }
+- dbg("%s - returns %d", __FUNCTION__, chars);
++ dbg("%s - returns %d", __func__, chars);
+ return chars;
+ }
+
+@@ -585,7 +585,7 @@ static void mos7720_close(struct usb_serial_port *port, struct file *filp)
+ mutex_unlock(&serial->disc_mutex);
+ mos7720_port->open = 0;
+
+- dbg("Leaving %s", __FUNCTION__);
++ dbg("Leaving %s", __func__);
+ }
+
+ static void mos7720_break(struct usb_serial_port *port, int break_state)
+@@ -594,7 +594,7 @@ static void mos7720_break(struct usb_serial_port *port, int break_state)
+ struct usb_serial *serial;
+ struct moschip_port *mos7720_port;
+
+- dbg("Entering %s", __FUNCTION__);
++ dbg("Entering %s", __func__);
+
+ serial = port->serial;
+
+@@ -627,20 +627,21 @@ static int mos7720_write_room(struct usb_serial_port *port)
+ int room = 0;
+ int i;
+
+- dbg("%s:entering ...........", __FUNCTION__);
++ dbg("%s:entering ...........", __func__);
+
+ mos7720_port = usb_get_serial_port_data(port);
+ if (mos7720_port == NULL) {
+- dbg("%s:leaving ...........", __FUNCTION__);
++ dbg("%s:leaving ...........", __func__);
+ return -ENODEV;
+ }
+
++ /* FIXME: Locking */
+ for (i = 0; i < NUM_URBS; ++i) {
+ if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status != -EINPROGRESS)
+ room += URB_TRANSFER_BUFFER_SIZE;
+ }
+
+- dbg("%s - returns %d", __FUNCTION__, room);
++ dbg("%s - returns %d", __func__, room);
+ return room;
+ }
+
+@@ -657,7 +658,7 @@ static int mos7720_write(struct usb_serial_port *port,
+ struct urb *urb;
+ const unsigned char *current_position = data;
+
+- dbg("%s:entering ...........", __FUNCTION__);
++ dbg("%s:entering ...........", __func__);
+
+ serial = port->serial;
+
+@@ -679,7 +680,7 @@ static int mos7720_write(struct usb_serial_port *port,
+ }
+
+ if (urb == NULL) {
+- dbg("%s - no more free urbs", __FUNCTION__);
++ dbg("%s - no more free urbs", __func__);
+ goto exit;
+ }
+
+@@ -687,14 +688,14 @@ static int mos7720_write(struct usb_serial_port *port,
+ urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
+ GFP_KERNEL);
+ if (urb->transfer_buffer == NULL) {
+- err("%s no more kernel memory...", __FUNCTION__);
++ err("%s no more kernel memory...", __func__);
+ goto exit;
+ }
+ }
+ transfer_size = min (count, URB_TRANSFER_BUFFER_SIZE);
+
+ memcpy(urb->transfer_buffer, current_position, transfer_size);
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, transfer_size,
++ usb_serial_debug_data(debug, &port->dev, __func__, transfer_size,
+ urb->transfer_buffer);
+
+ /* fill urb with data and submit */
+@@ -708,7 +709,7 @@ static int mos7720_write(struct usb_serial_port *port,
+ status = usb_submit_urb(urb,GFP_ATOMIC);
+ if (status) {
+ err("%s - usb_submit_urb(write bulk) failed with status = %d",
+- __FUNCTION__, status);
++ __func__, status);
+ bytes_sent = status;
+ goto exit;
+ }
+@@ -724,7 +725,7 @@ static void mos7720_throttle(struct usb_serial_port *port)
+ struct tty_struct *tty;
+ int status;
+
+- dbg("%s- port %d\n", __FUNCTION__, port->number);
++ dbg("%s- port %d\n", __func__, port->number);
+
+ mos7720_port = usb_get_serial_port_data(port);
+
+@@ -736,11 +737,11 @@ static void mos7720_throttle(struct usb_serial_port *port)
+ return;
+ }
+
+- dbg("%s: Entering ..........", __FUNCTION__);
++ dbg("%s: Entering ..........", __func__);
+
+ tty = port->tty;
+ if (!tty) {
+- dbg("%s - no tty available", __FUNCTION__);
++ dbg("%s - no tty available", __func__);
+ return;
+ }
+
+@@ -773,15 +774,15 @@ static void mos7720_unthrottle(struct usb_serial_port *port)
+ return;
+
+ if (!mos7720_port->open) {
+- dbg("%s - port not opened", __FUNCTION__);
++ dbg("%s - port not opened", __func__);
+ return;
+ }
+
+- dbg("%s: Entering ..........", __FUNCTION__);
++ dbg("%s: Entering ..........", __func__);
+
+ tty = port->tty;
+ if (!tty) {
+- dbg("%s - no tty available", __FUNCTION__);
++ dbg("%s - no tty available", __func__);
+ return;
+ }
+
+@@ -922,7 +923,7 @@ static int calc_baud_rate_divisor(int baudrate, int *divisor)
+ __u16 round;
+
+
+- dbg("%s - %d", __FUNCTION__, baudrate);
++ dbg("%s - %d", __func__, baudrate);
+
+ for (i = 0; i < ARRAY_SIZE(divisor_table); i++) {
+ if (divisor_table[i].baudrate == baudrate) {
+@@ -973,15 +974,15 @@ static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port,
+ port = mos7720_port->port;
+ serial = port->serial;
+
+- dbg("%s: Entering ..........", __FUNCTION__);
++ dbg("%s: Entering ..........", __func__);
+
+ number = port->number - port->serial->minor;
+- dbg("%s - port = %d, baud = %d", __FUNCTION__, port->number, baudrate);
++ dbg("%s - port = %d, baud = %d", __func__, port->number, baudrate);
+
+ /* Calculate the Divisor */
+ status = calc_baud_rate_divisor(baudrate, &divisor);
+ if (status) {
+- err("%s - bad baud rate", __FUNCTION__);
++ err("%s - bad baud rate", __func__);
+ return status;
+ }
+
+@@ -1034,16 +1035,16 @@ static void change_port_settings(struct moschip_port *mos7720_port,
+ serial = port->serial;
+ port_number = port->number - port->serial->minor;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (!mos7720_port->open) {
+- dbg("%s - port not opened", __FUNCTION__);
++ dbg("%s - port not opened", __func__);
+ return;
+ }
+
+ tty = mos7720_port->port->tty;
+
+- dbg("%s: Entering ..........", __FUNCTION__);
++ dbg("%s: Entering ..........", __func__);
+
+ lData = UART_LCR_WLEN8;
+ lStop = 0x00; /* 1 stop bit */
+@@ -1078,14 +1079,14 @@ static void change_port_settings(struct moschip_port *mos7720_port,
+ if (cflag & PARENB) {
+ if (cflag & PARODD) {
+ lParity = UART_LCR_PARITY;
+- dbg("%s - parity = odd", __FUNCTION__);
++ dbg("%s - parity = odd", __func__);
+ } else {
+ lParity = (UART_LCR_EPAR | UART_LCR_PARITY);
+- dbg("%s - parity = even", __FUNCTION__);
++ dbg("%s - parity = even", __func__);
+ }
+
+ } else {
+- dbg("%s - parity = none", __FUNCTION__);
++ dbg("%s - parity = none", __func__);
+ }
+
+ if (cflag & CMSPAR)
+@@ -1094,10 +1095,10 @@ static void change_port_settings(struct moschip_port *mos7720_port,
+ /* Change the Stop bit */
+ if (cflag & CSTOPB) {
+ lStop = UART_LCR_STOP;
+- dbg("%s - stop bits = 2", __FUNCTION__);
++ dbg("%s - stop bits = 2", __func__);
+ } else {
+ lStop = 0x00;
+- dbg("%s - stop bits = 1", __FUNCTION__);
++ dbg("%s - stop bits = 1", __func__);
+ }
+
+ #define LCR_BITS_MASK 0x03 /* Mask for bits/char field */
+@@ -1171,7 +1172,7 @@ static void change_port_settings(struct moschip_port *mos7720_port,
+ return;
+ }
+
+- dbg("%s - baud rate = %d", __FUNCTION__, baud);
++ dbg("%s - baud rate = %d", __func__, baud);
+ status = send_cmd_write_baud_rate(mos7720_port, baud);
+ /* FIXME: needs to write actual resulting baud back not just
+ blindly do so */
+@@ -1217,7 +1218,7 @@ static void mos7720_set_termios(struct usb_serial_port *port,
+
+
+ if (!mos7720_port->open) {
+- dbg("%s - port not opened", __FUNCTION__);
++ dbg("%s - port not opened", __func__);
+ return;
+ }
+
+@@ -1225,15 +1226,15 @@ static void mos7720_set_termios(struct usb_serial_port *port,
+
+ cflag = tty->termios->c_cflag;
+
+- dbg("%s - cflag %08x iflag %08x", __FUNCTION__,
++ dbg("%s - cflag %08x iflag %08x", __func__,
+ tty->termios->c_cflag,
+ RELEVANT_IFLAG(tty->termios->c_iflag));
+
+- dbg("%s - old cflag %08x old iflag %08x", __FUNCTION__,
++ dbg("%s - old cflag %08x old iflag %08x", __func__,
+ old_termios->c_cflag,
+ RELEVANT_IFLAG(old_termios->c_iflag));
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /* change the port settings to the new ones specified */
+ change_port_settings(mos7720_port, old_termios);
+@@ -1271,7 +1272,7 @@ static int get_lsr_info(struct moschip_port *mos7720_port,
+
+ count = mos7720_chars_in_buffer(mos7720_port->port);
+ if (count == 0) {
+- dbg("%s -- Empty", __FUNCTION__);
++ dbg("%s -- Empty", __func__);
+ result = TIOCSER_TEMT;
+ }
+
+@@ -1296,7 +1297,7 @@ static int get_number_bytes_avail(struct moschip_port *mos7720_port,
+
+ result = tty->read_cnt;
+
+- dbg("%s(%d) = %d", __FUNCTION__, mos7720_port->port->number, result);
++ dbg("%s(%d) = %d", __func__, mos7720_port->port->number, result);
+ if (copy_to_user(value, &result, sizeof(int)))
+ return -EFAULT;
+
+@@ -1374,7 +1375,7 @@ static int get_modem_info(struct moschip_port *mos7720_port,
+ | ((msr & UART_MSR_DSR) ? TIOCM_DSR: 0); /* 0x100 */
+
+
+- dbg("%s -- %x", __FUNCTION__, result);
++ dbg("%s -- %x", __func__, result);
+
+ if (copy_to_user(value, &result, sizeof(int)))
+ return -EFAULT;
+@@ -1418,45 +1419,45 @@ static int mos7720_ioctl(struct usb_serial_port *port, struct file *file,
+ if (mos7720_port == NULL)
+ return -ENODEV;
+
+- dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
++ dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
+
+ switch (cmd) {
+ case TIOCINQ:
+ /* return number of bytes available */
+- dbg("%s (%d) TIOCINQ", __FUNCTION__, port->number);
++ dbg("%s (%d) TIOCINQ", __func__, port->number);
+ return get_number_bytes_avail(mos7720_port,
+ (unsigned int __user *)arg);
+ break;
+
+ case TIOCSERGETLSR:
+- dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__, port->number);
++ dbg("%s (%d) TIOCSERGETLSR", __func__, port->number);
+ return get_lsr_info(mos7720_port, (unsigned int __user *)arg);
+ return 0;
+
+ case TIOCMBIS:
+ case TIOCMBIC:
+ case TIOCMSET:
+- dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __FUNCTION__,
++ dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __func__,
+ port->number);
+ return set_modem_info(mos7720_port, cmd,
+ (unsigned int __user *)arg);
+
+ case TIOCMGET:
+- dbg("%s (%d) TIOCMGET", __FUNCTION__, port->number);
++ dbg("%s (%d) TIOCMGET", __func__, port->number);
+ return get_modem_info(mos7720_port,
+ (unsigned int __user *)arg);
+
+ case TIOCGSERIAL:
+- dbg("%s (%d) TIOCGSERIAL", __FUNCTION__, port->number);
++ dbg("%s (%d) TIOCGSERIAL", __func__, port->number);
+ return get_serial_info(mos7720_port,
+ (struct serial_struct __user *)arg);
+
+ case TIOCSSERIAL:
+- dbg("%s (%d) TIOCSSERIAL", __FUNCTION__, port->number);
++ dbg("%s (%d) TIOCSSERIAL", __func__, port->number);
+ break;
+
+ case TIOCMIWAIT:
+- dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number);
++ dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
+ cprev = mos7720_port->icount;
+ while (1) {
+ if (signal_pending(current))
+@@ -1490,7 +1491,7 @@ static int mos7720_ioctl(struct usb_serial_port *port, struct file *file,
+ icount.brk = cnow.brk;
+ icount.buf_overrun = cnow.buf_overrun;
+
+- dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__,
++ dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
+ port->number, icount.rx, icount.tx );
+ if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))
+ return -EFAULT;
+@@ -1508,7 +1509,7 @@ static int mos7720_startup(struct usb_serial *serial)
+ int i;
+ char data;
+
+- dbg("%s: Entering ..........", __FUNCTION__);
++ dbg("%s: Entering ..........", __func__);
+
+ if (!serial) {
+ dbg("Invalid Handler");
+@@ -1520,7 +1521,7 @@ static int mos7720_startup(struct usb_serial *serial)
+ /* create our private serial structure */
+ mos7720_serial = kzalloc(sizeof(struct moschip_serial), GFP_KERNEL);
+ if (mos7720_serial == NULL) {
+- err("%s - Out of memory", __FUNCTION__);
++ err("%s - Out of memory", __func__);
+ return -ENOMEM;
+ }
+
+@@ -1533,7 +1534,7 @@ static int mos7720_startup(struct usb_serial *serial)
+ for (i = 0; i < serial->num_ports; ++i) {
+ mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
+ if (mos7720_port == NULL) {
+- err("%s - Out of memory", __FUNCTION__);
++ err("%s - Out of memory", __func__);
+ usb_set_serial_data(serial, NULL);
+ kfree(mos7720_serial);
+ return -ENOMEM;
+@@ -1596,9 +1597,6 @@ static struct usb_serial_driver moschip7720_2port_driver = {
+ .description = "Moschip 2 port adapter",
+ .usb_driver = &usb_driver,
+ .id_table = moschip_port_id_table,
+- .num_interrupt_in = 1,
+- .num_bulk_in = 2,
+- .num_bulk_out = 2,
+ .num_ports = 2,
+ .open = mos7720_open,
+ .close = mos7720_close,
+@@ -1620,7 +1618,7 @@ static int __init moschip7720_init(void)
+ {
+ int retval;
+
+- dbg("%s: Entering ..........", __FUNCTION__);
++ dbg("%s: Entering ..........", __func__);
+
+ /* Register with the usb serial */
+ retval = usb_serial_register(&moschip7720_2port_driver);
+diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
+index aeeb9cb..6bcb82d 100644
+--- a/drivers/usb/serial/mos7840.c
++++ b/drivers/usb/serial/mos7840.c
+@@ -403,7 +403,7 @@ static void mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr)
+ {
+ struct async_icount *icount;
+
+- dbg("%s - %02x", __FUNCTION__, new_lsr);
++ dbg("%s - %02x", __func__, new_lsr);
+
+ if (new_lsr & SERIAL_LSR_BI) {
+ //
+@@ -449,7 +449,7 @@ static void mos7840_control_callback(struct urb *urb)
+ int result = 0;
+ int status = urb->status;
+
+- mos7840_port = (struct moschip_port *)urb->context;
++ mos7840_port = urb->context;
+
+ switch (status) {
+ case 0:
+@@ -459,21 +459,21 @@ static void mos7840_control_callback(struct urb *urb)
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+- dbg("%s - urb shutting down with status: %d", __FUNCTION__,
++ dbg("%s - urb shutting down with status: %d", __func__,
+ status);
+ return;
+ default:
+- dbg("%s - nonzero urb status received: %d", __FUNCTION__,
++ dbg("%s - nonzero urb status received: %d", __func__,
+ status);
+ goto exit;
+ }
+
+- dbg("%s urb buffer size is %d\n", __FUNCTION__, urb->actual_length);
+- dbg("%s mos7840_port->MsrLsr is %d port %d\n", __FUNCTION__,
++ dbg("%s urb buffer size is %d\n", __func__, urb->actual_length);
++ dbg("%s mos7840_port->MsrLsr is %d port %d\n", __func__,
+ mos7840_port->MsrLsr, mos7840_port->port_num);
+ data = urb->transfer_buffer;
+ regval = (__u8) data[0];
+- dbg("%s data is %x\n", __FUNCTION__, regval);
++ dbg("%s data is %x\n", __func__, regval);
+ if (mos7840_port->MsrLsr == 0)
+ mos7840_handle_new_msr(mos7840_port, regval);
+ else if (mos7840_port->MsrLsr == 1)
+@@ -487,7 +487,7 @@ exit:
+ if (result) {
+ dev_err(&urb->dev->dev,
+ "%s - Error %d submitting interrupt urb\n",
+- __FUNCTION__, result);
++ __func__, result);
+ }
+ }
+
+@@ -542,11 +542,11 @@ static void mos7840_interrupt_callback(struct urb *urb)
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+- dbg("%s - urb shutting down with status: %d", __FUNCTION__,
++ dbg("%s - urb shutting down with status: %d", __func__,
+ status);
+ return;
+ default:
+- dbg("%s - nonzero urb status received: %d", __FUNCTION__,
++ dbg("%s - nonzero urb status received: %d", __func__,
+ status);
+ goto exit;
+ }
+@@ -554,7 +554,7 @@ static void mos7840_interrupt_callback(struct urb *urb)
+ length = urb->actual_length;
+ data = urb->transfer_buffer;
+
+- serial = (struct usb_serial *)urb->context;
++ serial = urb->context;
+
+ /* Moschip get 5 bytes
+ * Byte 1 IIR Port 1 (port.number is 0)
+@@ -614,7 +614,7 @@ exit:
+ if (result) {
+ dev_err(&urb->dev->dev,
+ "%s - Error %d submitting interrupt urb\n",
+- __FUNCTION__, result);
++ __func__, result);
+ }
+ }
+
+@@ -685,19 +685,19 @@ static void mos7840_bulk_in_callback(struct urb *urb)
+ return;
+ }
+
+- mos7840_port = (struct moschip_port *)urb->context;
++ mos7840_port = urb->context;
+ if (!mos7840_port) {
+ dbg("%s", "NULL mos7840_port pointer \n");
+ return;
+ }
+
+ port = (struct usb_serial_port *)mos7840_port->port;
+- if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++ if (mos7840_port_paranoia_check(port, __func__)) {
+ dbg("%s", "Port Paranoia failed \n");
+ return;
+ }
+
+- serial = mos7840_get_usb_serial(port, __FUNCTION__);
++ serial = mos7840_get_usb_serial(port, __func__);
+ if (!serial) {
+ dbg("%s\n", "Bad serial pointer ");
+ return;
+@@ -752,7 +752,7 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
+ int status = urb->status;
+ int i;
+
+- mos7840_port = (struct moschip_port *)urb->context;
++ mos7840_port = urb->context;
+ spin_lock(&mos7840_port->pool_lock);
+ for (i = 0; i < NUM_URBS; i++) {
+ if (urb == mos7840_port->write_urb_pool[i]) {
+@@ -767,7 +767,7 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
+ return;
+ }
+
+- if (mos7840_port_paranoia_check(mos7840_port->port, __FUNCTION__)) {
++ if (mos7840_port_paranoia_check(mos7840_port->port, __func__)) {
+ dbg("%s", "Port Paranoia failed \n");
+ return;
+ }
+@@ -815,14 +815,14 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
+ struct moschip_port *mos7840_port;
+ struct moschip_port *port0;
+
+- if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++ if (mos7840_port_paranoia_check(port, __func__)) {
+ dbg("%s", "Port Paranoia failed \n");
+ return -ENODEV;
+ }
+
+ serial = port->serial;
+
+- if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {
++ if (mos7840_serial_paranoia_check(serial, __func__)) {
+ dbg("%s", "Serial Paranoia failed \n");
+ return -ENODEV;
+ }
+@@ -851,7 +851,7 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
+ if (!urb->transfer_buffer) {
+ usb_free_urb(urb);
+ mos7840_port->write_urb_pool[j] = NULL;
+- err("%s-out of memory for urb buffers.", __FUNCTION__);
++ err("%s-out of memory for urb buffers.", __func__);
+ continue;
+ }
+ }
+@@ -1039,7 +1039,7 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
+ GFP_KERNEL);
+ if (response) {
+ err("%s - Error %d submitting interrupt urb",
+- __FUNCTION__, response);
++ __func__, response);
+ }
+
+ }
+@@ -1072,7 +1072,7 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
+ port->bulk_in_endpointAddress);
+ response = usb_submit_urb(mos7840_port->read_urb, GFP_KERNEL);
+ if (response) {
+- err("%s - Error %d submitting control urb", __FUNCTION__,
++ err("%s - Error %d submitting control urb", __func__,
+ response);
+ }
+
+@@ -1116,7 +1116,7 @@ static int mos7840_chars_in_buffer(struct usb_serial_port *port)
+
+ dbg("%s \n", " mos7840_chars_in_buffer:entering ...........");
+
+- if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++ if (mos7840_port_paranoia_check(port, __func__)) {
+ dbg("%s", "Invalid port \n");
+ return -1;
+ }
+@@ -1134,7 +1134,7 @@ static int mos7840_chars_in_buffer(struct usb_serial_port *port)
+ }
+ }
+ spin_unlock_irqrestore(&mos7840_port->pool_lock,flags);
+- dbg("%s - returns %d", __FUNCTION__, chars);
++ dbg("%s - returns %d", __func__, chars);
+ return chars;
+
+ }
+@@ -1171,7 +1171,7 @@ static void mos7840_block_until_tx_empty(struct moschip_port *mos7840_port)
+ /* No activity.. count down section */
+ wait--;
+ if (wait == 0) {
+- dbg("%s - TIMEOUT", __FUNCTION__);
++ dbg("%s - TIMEOUT", __func__);
+ return;
+ } else {
+ /* Reset timeout value back to seconds */
+@@ -1195,12 +1195,12 @@ static void mos7840_close(struct usb_serial_port *port, struct file *filp)
+
+ dbg("%s\n", "mos7840_close:entering...");
+
+- if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++ if (mos7840_port_paranoia_check(port, __func__)) {
+ dbg("%s", "Port Paranoia failed \n");
+ return;
+ }
+
+- serial = mos7840_get_usb_serial(port, __FUNCTION__);
++ serial = mos7840_get_usb_serial(port, __func__);
+ if (!serial) {
+ dbg("%s", "Serial Paranoia failed \n");
+ return;
+@@ -1314,7 +1314,7 @@ static void mos7840_block_until_chase_response(struct moschip_port
+ /* No activity.. count down section */
+ wait--;
+ if (wait == 0) {
+- dbg("%s - TIMEOUT", __FUNCTION__);
++ dbg("%s - TIMEOUT", __func__);
+ return;
+ } else {
+ /* Reset timeout value back to seconds */
+@@ -1337,12 +1337,12 @@ static void mos7840_break(struct usb_serial_port *port, int break_state)
+ dbg("%s \n", "Entering ...........");
+ dbg("mos7840_break: Start\n");
+
+- if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++ if (mos7840_port_paranoia_check(port, __func__)) {
+ dbg("%s", "Port Paranoia failed \n");
+ return;
+ }
+
+- serial = mos7840_get_usb_serial(port, __FUNCTION__);
++ serial = mos7840_get_usb_serial(port, __func__);
+ if (!serial) {
+ dbg("%s", "Serial Paranoia failed \n");
+ return;
+@@ -1392,7 +1392,7 @@ static int mos7840_write_room(struct usb_serial_port *port)
+
+ dbg("%s \n", " mos7840_write_room:entering ...........");
+
+- if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++ if (mos7840_port_paranoia_check(port, __func__)) {
+ dbg("%s", "Invalid port \n");
+ dbg("%s \n", " mos7840_write_room:leaving ...........");
+ return -1;
+@@ -1413,7 +1413,7 @@ static int mos7840_write_room(struct usb_serial_port *port)
+ spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
+
+ room = (room == 0) ? 0 : room - URB_TRANSFER_BUFFER_SIZE + 1;
+- dbg("%s - returns %d", __FUNCTION__, room);
++ dbg("%s - returns %d", __func__, room);
+ return room;
+
+ }
+@@ -1480,13 +1480,13 @@ static int mos7840_write(struct usb_serial_port *port,
+ status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+ #endif
+
+- if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++ if (mos7840_port_paranoia_check(port, __func__)) {
+ dbg("%s", "Port Paranoia failed \n");
+ return -1;
+ }
+
+ serial = port->serial;
+- if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {
++ if (mos7840_serial_paranoia_check(serial, __func__)) {
+ dbg("%s", "Serial Paranoia failed \n");
+ return -1;
+ }
+@@ -1512,7 +1512,7 @@ static int mos7840_write(struct usb_serial_port *port,
+ spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
+
+ if (urb == NULL) {
+- dbg("%s - no more free urbs", __FUNCTION__);
++ dbg("%s - no more free urbs", __func__);
+ goto exit;
+ }
+
+@@ -1521,7 +1521,7 @@ static int mos7840_write(struct usb_serial_port *port,
+ kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+
+ if (urb->transfer_buffer == NULL) {
+- err("%s no more kernel memory...", __FUNCTION__);
++ err("%s no more kernel memory...", __func__);
+ goto exit;
+ }
+ }
+@@ -1547,7 +1547,7 @@ static int mos7840_write(struct usb_serial_port *port,
+ if (status) {
+ mos7840_port->busy[i] = 0;
+ err("%s - usb_submit_urb(write bulk) failed with status = %d",
+- __FUNCTION__, status);
++ __func__, status);
+ bytes_sent = status;
+ goto exit;
+ }
+@@ -1573,7 +1573,7 @@ static void mos7840_throttle(struct usb_serial_port *port)
+ struct tty_struct *tty;
+ int status;
+
+- if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++ if (mos7840_port_paranoia_check(port, __func__)) {
+ dbg("%s", "Invalid port \n");
+ return;
+ }
+@@ -1594,7 +1594,7 @@ static void mos7840_throttle(struct usb_serial_port *port)
+
+ tty = port->tty;
+ if (!tty) {
+- dbg("%s - no tty available", __FUNCTION__);
++ dbg("%s - no tty available", __func__);
+ return;
+ }
+
+@@ -1634,7 +1634,7 @@ static void mos7840_unthrottle(struct usb_serial_port *port)
+ int status;
+ struct moschip_port *mos7840_port = mos7840_get_port_private(port);
+
+- if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++ if (mos7840_port_paranoia_check(port, __func__)) {
+ dbg("%s", "Invalid port \n");
+ return;
+ }
+@@ -1643,7 +1643,7 @@ static void mos7840_unthrottle(struct usb_serial_port *port)
+ return;
+
+ if (!mos7840_port->open) {
+- dbg("%s - port not opened", __FUNCTION__);
++ dbg("%s - port not opened", __func__);
+ return;
+ }
+
+@@ -1651,7 +1651,7 @@ static void mos7840_unthrottle(struct usb_serial_port *port)
+
+ tty = port->tty;
+ if (!tty) {
+- dbg("%s - no tty available", __FUNCTION__);
++ dbg("%s - no tty available", __func__);
+ return;
+ }
+
+@@ -1688,7 +1688,7 @@ static int mos7840_tiocmget(struct usb_serial_port *port, struct file *file)
+ int status = 0;
+ mos7840_port = mos7840_get_port_private(port);
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (mos7840_port == NULL)
+ return -ENODEV;
+@@ -1703,7 +1703,7 @@ static int mos7840_tiocmget(struct usb_serial_port *port, struct file *file)
+ | ((msr & MOS7840_MSR_RI) ? TIOCM_RI : 0)
+ | ((msr & MOS7840_MSR_DSR) ? TIOCM_DSR : 0);
+
+- dbg("%s - 0x%04X", __FUNCTION__, result);
++ dbg("%s - 0x%04X", __func__, result);
+
+ return result;
+ }
+@@ -1715,13 +1715,14 @@ static int mos7840_tiocmset(struct usb_serial_port *port, struct file *file,
+ unsigned int mcr;
+ unsigned int status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ mos7840_port = mos7840_get_port_private(port);
+
+ if (mos7840_port == NULL)
+ return -ENODEV;
+
++ /* FIXME: What locks the port registers ? */
+ mcr = mos7840_port->shadowMCR;
+ if (clear & TIOCM_RTS)
+ mcr &= ~MCR_RTS;
+@@ -1758,7 +1759,7 @@ static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor,
+ __u16 * clk_sel_val)
+ {
+
+- dbg("%s - %d", __FUNCTION__, baudRate);
++ dbg("%s - %d", __func__, baudRate);
+
+ if (baudRate <= 115200) {
+ *divisor = 115200 / baudRate;
+@@ -1841,12 +1842,12 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
+ return -1;
+
+ port = (struct usb_serial_port *)mos7840_port->port;
+- if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++ if (mos7840_port_paranoia_check(port, __func__)) {
+ dbg("%s", "Invalid port \n");
+ return -1;
+ }
+
+- if (mos7840_serial_paranoia_check(port->serial, __FUNCTION__)) {
++ if (mos7840_serial_paranoia_check(port->serial, __func__)) {
+ dbg("%s", "Invalid Serial \n");
+ return -1;
+ }
+@@ -1855,7 +1856,7 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
+
+ number = mos7840_port->port->number - mos7840_port->port->serial->minor;
+
+- dbg("%s - port = %d, baud = %d", __FUNCTION__,
++ dbg("%s - port = %d, baud = %d", __func__,
+ mos7840_port->port->number, baudRate);
+ //reset clk_uart_sel in spregOffset
+ if (baudRate > 115200) {
+@@ -1915,7 +1916,7 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
+ /* Calculate the Divisor */
+
+ if (status) {
+- err("%s - bad baud rate", __FUNCTION__);
++ err("%s - bad baud rate", __func__);
+ dbg("%s\n", "bad baud rate");
+ return status;
+ }
+@@ -1969,22 +1970,22 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
+
+ port = (struct usb_serial_port *)mos7840_port->port;
+
+- if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++ if (mos7840_port_paranoia_check(port, __func__)) {
+ dbg("%s", "Invalid port \n");
+ return;
+ }
+
+- if (mos7840_serial_paranoia_check(port->serial, __FUNCTION__)) {
++ if (mos7840_serial_paranoia_check(port->serial, __func__)) {
+ dbg("%s", "Invalid Serial \n");
+ return;
+ }
+
+ serial = port->serial;
+
+- dbg("%s - port %d", __FUNCTION__, mos7840_port->port->number);
++ dbg("%s - port %d", __func__, mos7840_port->port->number);
+
+ if (!mos7840_port->open) {
+- dbg("%s - port not opened", __FUNCTION__);
++ dbg("%s - port not opened", __func__);
+ return;
+ }
+
+@@ -2023,14 +2024,14 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
+ if (cflag & PARENB) {
+ if (cflag & PARODD) {
+ lParity = LCR_PAR_ODD;
+- dbg("%s - parity = odd", __FUNCTION__);
++ dbg("%s - parity = odd", __func__);
+ } else {
+ lParity = LCR_PAR_EVEN;
+- dbg("%s - parity = even", __FUNCTION__);
++ dbg("%s - parity = even", __func__);
+ }
+
+ } else {
+- dbg("%s - parity = none", __FUNCTION__);
++ dbg("%s - parity = none", __func__);
+ }
+
+ if (cflag & CMSPAR) {
+@@ -2040,10 +2041,10 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
+ /* Change the Stop bit */
+ if (cflag & CSTOPB) {
+ lStop = LCR_STOP_2;
+- dbg("%s - stop bits = 2", __FUNCTION__);
++ dbg("%s - stop bits = 2", __func__);
+ } else {
+ lStop = LCR_STOP_1;
+- dbg("%s - stop bits = 1", __FUNCTION__);
++ dbg("%s - stop bits = 1", __func__);
+ }
+
+ /* Update the LCR with the correct value */
+@@ -2100,7 +2101,7 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
+ baud = 9600;
+ }
+
+- dbg("%s - baud rate = %d", __FUNCTION__, baud);
++ dbg("%s - baud rate = %d", __func__, baud);
+ status = mos7840_send_cmd_write_baud_rate(mos7840_port, baud);
+
+ /* Enable Interrupts */
+@@ -2140,14 +2141,14 @@ static void mos7840_set_termios(struct usb_serial_port *port,
+ struct moschip_port *mos7840_port;
+ struct tty_struct *tty;
+ dbg("mos7840_set_termios: START\n");
+- if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++ if (mos7840_port_paranoia_check(port, __func__)) {
+ dbg("%s", "Invalid port \n");
+ return;
+ }
+
+ serial = port->serial;
+
+- if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {
++ if (mos7840_serial_paranoia_check(serial, __func__)) {
+ dbg("%s", "Invalid Serial \n");
+ return;
+ }
+@@ -2160,7 +2161,7 @@ static void mos7840_set_termios(struct usb_serial_port *port,
+ tty = port->tty;
+
+ if (!mos7840_port->open) {
+- dbg("%s - port not opened", __FUNCTION__);
++ dbg("%s - port not opened", __func__);
+ return;
+ }
+
+@@ -2168,11 +2169,11 @@ static void mos7840_set_termios(struct usb_serial_port *port,
+
+ cflag = tty->termios->c_cflag;
+
+- dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
++ dbg("%s - clfag %08x iflag %08x", __func__,
+ tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag));
+- dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
++ dbg("%s - old clfag %08x old iflag %08x", __func__,
+ old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag));
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /* change the port settings to the new ones specified */
+
+@@ -2213,7 +2214,7 @@ static int mos7840_get_lsr_info(struct moschip_port *mos7840_port,
+
+ count = mos7840_chars_in_buffer(mos7840_port->port);
+ if (count == 0) {
+- dbg("%s -- Empty", __FUNCTION__);
++ dbg("%s -- Empty", __func__);
+ result = TIOCSER_TEMT;
+ }
+
+@@ -2240,7 +2241,7 @@ static int mos7840_set_modem_info(struct moschip_port *mos7840_port,
+ return -1;
+
+ port = (struct usb_serial_port *)mos7840_port->port;
+- if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++ if (mos7840_port_paranoia_check(port, __func__)) {
+ dbg("%s", "Invalid port \n");
+ return -1;
+ }
+@@ -2314,7 +2315,7 @@ static int mos7840_get_modem_info(struct moschip_port *mos7840_port,
+ |((msr & MOS7840_MSR_RI) ? TIOCM_RI : 0) /* 0x080 */
+ |((msr & MOS7840_MSR_DSR) ? TIOCM_DSR : 0); /* 0x100 */
+
+- dbg("%s -- %x", __FUNCTION__, result);
++ dbg("%s -- %x", __func__, result);
+
+ if (copy_to_user(value, &result, sizeof(int)))
+ return -EFAULT;
+@@ -2371,7 +2372,7 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
+ struct serial_icounter_struct icount;
+ int mosret = 0;
+
+- if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
++ if (mos7840_port_paranoia_check(port, __func__)) {
+ dbg("%s", "Invalid port \n");
+ return -1;
+ }
+@@ -2383,39 +2384,39 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
+
+ tty = mos7840_port->port->tty;
+
+- dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
++ dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
+
+ switch (cmd) {
+ /* return number of bytes available */
+
+ case TIOCSERGETLSR:
+- dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__, port->number);
++ dbg("%s (%d) TIOCSERGETLSR", __func__, port->number);
+ return mos7840_get_lsr_info(mos7840_port, argp);
+ return 0;
+
+ case TIOCMBIS:
+ case TIOCMBIC:
+ case TIOCMSET:
+- dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __FUNCTION__,
++ dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __func__,
+ port->number);
+ mosret =
+ mos7840_set_modem_info(mos7840_port, cmd, argp);
+ return mosret;
+
+ case TIOCMGET:
+- dbg("%s (%d) TIOCMGET", __FUNCTION__, port->number);
++ dbg("%s (%d) TIOCMGET", __func__, port->number);
+ return mos7840_get_modem_info(mos7840_port, argp);
+
+ case TIOCGSERIAL:
+- dbg("%s (%d) TIOCGSERIAL", __FUNCTION__, port->number);
++ dbg("%s (%d) TIOCGSERIAL", __func__, port->number);
+ return mos7840_get_serial_info(mos7840_port, argp);
+
+ case TIOCSSERIAL:
+- dbg("%s (%d) TIOCSSERIAL", __FUNCTION__, port->number);
++ dbg("%s (%d) TIOCSSERIAL", __func__, port->number);
+ break;
+
+ case TIOCMIWAIT:
+- dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number);
++ dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
+ cprev = mos7840_port->icount;
+ while (1) {
+ //interruptible_sleep_on(&mos7840_port->delta_msr_wait);
+@@ -2458,7 +2459,7 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
+ icount.brk = cnow.brk;
+ icount.buf_overrun = cnow.buf_overrun;
+
+- dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__,
++ dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
+ port->number, icount.rx, icount.tx);
+ if (copy_to_user(argp, &icount, sizeof(icount)))
+ return -EFAULT;
+@@ -2521,7 +2522,7 @@ static int mos7840_startup(struct usb_serial *serial)
+ for (i = 0; i < serial->num_ports; ++i) {
+ mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
+ if (mos7840_port == NULL) {
+- err("%s - Out of memory", __FUNCTION__);
++ err("%s - Out of memory", __func__);
+ status = -ENOMEM;
+ i--; /* don't follow NULL pointer cleaning up */
+ goto error;
+@@ -2799,12 +2800,7 @@ static struct usb_serial_driver moschip7840_4port_device = {
+ .description = DRIVER_DESC,
+ .usb_driver = &io_driver,
+ .id_table = moschip_port_id_table,
+- .num_interrupt_in = 1, //NUM_DONT_CARE,//1,
+-#ifdef check
+- .num_bulk_in = 4,
+- .num_bulk_out = 4,
+ .num_ports = 4,
+-#endif
+ .open = mos7840_open,
+ .close = mos7840_close,
+ .write = mos7840_write,
+diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c
+index 7f337c9..43c8894 100644
+--- a/drivers/usb/serial/navman.c
++++ b/drivers/usb/serial/navman.c
+@@ -6,6 +6,10 @@
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
++ *
++ * TODO:
++ * Add termios method that uses copy_hw but also kills all echo
++ * flags as the navman is rx only so cannot echo.
+ */
+
+ #include <linux/kernel.h>
+@@ -49,15 +53,15 @@ static void navman_read_int_callback(struct urb *urb)
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ goto exit;
+ }
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
++ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
+
+ tty = port->tty;
+@@ -72,29 +76,29 @@ exit:
+ if (result)
+ dev_err(&urb->dev->dev,
+ "%s - Error %d submitting interrupt urb\n",
+- __FUNCTION__, result);
++ __func__, result);
+ }
+
+ static int navman_open(struct usb_serial_port *port, struct file *filp)
+ {
+ int result = 0;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (port->interrupt_in_urb) {
+- dbg("%s - adding interrupt input for treo", __FUNCTION__);
++ dbg("%s - adding interrupt input for treo", __func__);
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ if (result)
+ dev_err(&port->dev,
+ "%s - failed submitting interrupt urb, error %d\n",
+- __FUNCTION__, result);
++ __func__, result);
+ }
+ return result;
+ }
+
+ static void navman_close(struct usb_serial_port *port, struct file *filp)
+ {
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ usb_kill_urb(port->interrupt_in_urb);
+ }
+@@ -102,16 +106,12 @@ static void navman_close(struct usb_serial_port *port, struct file *filp)
+ static int navman_write(struct usb_serial_port *port,
+ const unsigned char *buf, int count)
+ {
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /*
+ * This device can't write any data, only read from the device
+- * so we just silently eat all data sent to us and say it was
+- * successfully sent.
+- * Evil, I know, but do you have a better idea?
+ */
+-
+- return count;
++ return -EOPNOTSUPP;
+ }
+
+ static struct usb_serial_driver navman_device = {
+@@ -121,9 +121,6 @@ static struct usb_serial_driver navman_device = {
+ },
+ .id_table = id_table,
+ .usb_driver = &navman_driver,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_bulk_in = NUM_DONT_CARE,
+- .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 1,
+ .open = navman_open,
+ .close = navman_close,
+diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
+index ee94d96..7b7422f 100644
+--- a/drivers/usb/serial/omninet.c
++++ b/drivers/usb/serial/omninet.c
+@@ -95,9 +95,6 @@ static struct usb_serial_driver zyxel_omninet_device = {
+ .description = "ZyXEL - omni.net lcd plus usb",
+ .usb_driver = &omninet_driver,
+ .id_table = id_table,
+- .num_interrupt_in = 1,
+- .num_bulk_in = 1,
+- .num_bulk_out = 2,
+ .num_ports = 1,
+ .attach = omninet_attach,
+ .open = omninet_open,
+@@ -153,7 +150,7 @@ static int omninet_attach (struct usb_serial *serial)
+
+ od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL );
+ if( !od ) {
+- err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct omninet_data));
++ err("%s- kmalloc(%Zd) failed.", __func__, sizeof(struct omninet_data));
+ return -ENOMEM;
+ }
+ usb_set_serial_port_data(port, od);
+@@ -166,7 +163,7 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp)
+ struct usb_serial_port *wport;
+ int result = 0;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ wport = serial->port[1];
+ wport->tty = port->tty;
+@@ -178,7 +175,7 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp)
+ omninet_read_bulk_callback, port);
+ result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ if (result) {
+- err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
++ err("%s - failed submitting read urb, error %d", __func__, result);
+ }
+
+ return result;
+@@ -186,7 +183,7 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp)
+
+ static void omninet_close (struct usb_serial_port *port, struct file * filp)
+ {
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+ usb_kill_urb(port->read_urb);
+ }
+
+@@ -197,18 +194,18 @@ static void omninet_close (struct usb_serial_port *port, struct file * filp)
+
+ static void omninet_read_bulk_callback (struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ unsigned char *data = urb->transfer_buffer;
+ struct omninet_header *header = (struct omninet_header *) &data[0];
+ int status = urb->status;
+ int i;
+ int result;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
+
+@@ -236,7 +233,7 @@ static void omninet_read_bulk_callback (struct urb *urb)
+ omninet_read_bulk_callback, port);
+ result = usb_submit_urb(urb, GFP_ATOMIC);
+ if (result)
+- err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
++ err("%s - failed resubmitting read urb, error %d", __func__, result);
+
+ return;
+ }
+@@ -251,17 +248,17 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf
+
+ int result;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (count == 0) {
+- dbg("%s - write request of 0 bytes", __FUNCTION__);
++ dbg("%s - write request of 0 bytes", __func__);
+ return (0);
+ }
+
+ spin_lock_bh(&wport->lock);
+ if (wport->write_urb_busy) {
+ spin_unlock_bh(&wport->lock);
+- dbg("%s - already writing", __FUNCTION__);
++ dbg("%s - already writing", __func__);
+ return 0;
+ }
+ wport->write_urb_busy = 1;
+@@ -271,7 +268,7 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf
+
+ memcpy (wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, buf, count);
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, wport->write_urb->transfer_buffer);
++ usb_serial_debug_data(debug, &port->dev, __func__, count, wport->write_urb->transfer_buffer);
+
+ header->oh_seq = od->od_outseq++;
+ header->oh_len = count;
+@@ -285,7 +282,7 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf
+ result = usb_submit_urb(wport->write_urb, GFP_ATOMIC);
+ if (result) {
+ wport->write_urb_busy = 0;
+- err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
++ err("%s - failed submitting write urb, error %d", __func__, result);
+ } else
+ result = count;
+
+@@ -298,12 +295,13 @@ static int omninet_write_room (struct usb_serial_port *port)
+ struct usb_serial *serial = port->serial;
+ struct usb_serial_port *wport = serial->port[1];
+
+- int room = 0; // Default: no room
++ int room = 0; /* Default: no room */
+
++ /* FIXME: no consistent locking for write_urb_busy */
+ if (wport->write_urb_busy)
+ room = wport->bulk_out_size - OMNINET_HEADERLEN;
+
+- dbg("%s - returns %d", __FUNCTION__, room);
++ dbg("%s - returns %d", __func__, room);
+
+ return (room);
+ }
+@@ -311,15 +309,15 @@ static int omninet_write_room (struct usb_serial_port *port)
+ static void omninet_write_bulk_callback (struct urb *urb)
+ {
+ /* struct omninet_header *header = (struct omninet_header *) urb->transfer_buffer; */
+- struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
++ struct usb_serial_port *port = urb->context;
+ int status = urb->status;
+
+- dbg("%s - port %0x\n", __FUNCTION__, port->number);
++ dbg("%s - port %0x\n", __func__, port->number);
+
+ port->write_urb_busy = 0;
+ if (status) {
+ dbg("%s - nonzero write bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
+
+@@ -331,7 +329,7 @@ static void omninet_shutdown (struct usb_serial *serial)
+ {
+ struct usb_serial_port *wport = serial->port[1];
+ struct usb_serial_port *port = serial->port[0];
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+ usb_kill_urb(wport->write_urb);
+ kfree(usb_get_serial_port_data(port));
+diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
+index d101025..e4be2d4 100644
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -28,7 +28,7 @@
+ device features.
+ */
+
+-#define DRIVER_VERSION "v0.7.1"
++#define DRIVER_VERSION "v0.7.2"
+ #define DRIVER_AUTHOR "Matthias Urlichs <smurf at smurf.noris.de>"
+ #define DRIVER_DESC "USB Driver for GSM modems"
+
+@@ -325,9 +325,6 @@ static struct usb_serial_driver option_1port_device = {
+ .description = "GSM modem (1-port)",
+ .usb_driver = &option_driver,
+ .id_table = option_ids,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_bulk_in = NUM_DONT_CARE,
+- .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 1,
+ .open = option_open,
+ .close = option_close,
+@@ -411,24 +408,24 @@ module_exit(option_exit);
+
+ static void option_rx_throttle(struct usb_serial_port *port)
+ {
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+ }
+
+ static void option_rx_unthrottle(struct usb_serial_port *port)
+ {
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+ }
+
+ static void option_break_ctl(struct usb_serial_port *port, int break_state)
+ {
+ /* Unfortunately, I don't know how to send a break */
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+ }
+
+ static void option_set_termios(struct usb_serial_port *port,
+ struct ktermios *old_termios)
+ {
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+ /* Doesn't support option setting */
+ tty_termios_copy_hw(port->tty->termios, old_termios);
+ option_send_setup(port);
+@@ -458,6 +455,7 @@ static int option_tiocmset(struct usb_serial_port *port, struct file *file,
+
+ portdata = usb_get_serial_port_data(port);
+
++ /* FIXME: what locks portdata fields ? */
+ if (set & TIOCM_RTS)
+ portdata->rts_state = 1;
+ if (set & TIOCM_DTR)
+@@ -488,7 +486,7 @@ static int option_write(struct usb_serial_port *port,
+
+ portdata = usb_get_serial_port_data(port);
+
+- dbg("%s: write (%d chars)", __FUNCTION__, count);
++ dbg("%s: write (%d chars)", __func__, count);
+
+ i = 0;
+ left = count;
+@@ -509,7 +507,7 @@ static int option_write(struct usb_serial_port *port,
+ dbg("usb_write %p failed (err=%d)",
+ this_urb, this_urb->status);
+
+- dbg("%s: endpoint %d buf %d", __FUNCTION__,
++ dbg("%s: endpoint %d buf %d", __func__,
+ usb_pipeendpoint(this_urb->pipe), i);
+
+ /* send the data */
+@@ -531,7 +529,7 @@ static int option_write(struct usb_serial_port *port,
+ }
+
+ count -= left;
+- dbg("%s: wrote (did %d)", __FUNCTION__, count);
++ dbg("%s: wrote (did %d)", __func__, count);
+ return count;
+ }
+
+@@ -544,14 +542,14 @@ static void option_indat_callback(struct urb *urb)
+ unsigned char *data = urb->transfer_buffer;
+ int status = urb->status;
+
+- dbg("%s: %p", __FUNCTION__, urb);
++ dbg("%s: %p", __func__, urb);
+
+ endpoint = usb_pipeendpoint(urb->pipe);
+- port = (struct usb_serial_port *) urb->context;
++ port = urb->context;
+
+ if (status) {
+ dbg("%s: nonzero status: %d on endpoint %02x.",
+- __FUNCTION__, status, endpoint);
++ __func__, status, endpoint);
+ } else {
+ tty = port->tty;
+ if (urb->actual_length) {
+@@ -559,7 +557,7 @@ static void option_indat_callback(struct urb *urb)
+ tty_insert_flip_string(tty, data, urb->actual_length);
+ tty_flip_buffer_push(tty);
+ } else {
+- dbg("%s: empty read urb received", __FUNCTION__);
++ dbg("%s: empty read urb received", __func__);
+ }
+
+ /* Resubmit urb so we continue receiving */
+@@ -567,7 +565,7 @@ static void option_indat_callback(struct urb *urb)
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err)
+ printk(KERN_ERR "%s: resubmit read urb failed. "
+- "(%d)", __FUNCTION__, err);
++ "(%d)", __func__, err);
+ }
+ }
+ return;
+@@ -579,9 +577,9 @@ static void option_outdat_callback(struct urb *urb)
+ struct option_port_private *portdata;
+ int i;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+- port = (struct usb_serial_port *) urb->context;
++ port = urb->context;
+
+ usb_serial_port_softint(port);
+
+@@ -599,19 +597,19 @@ static void option_instat_callback(struct urb *urb)
+ {
+ int err;
+ int status = urb->status;
+- struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct option_port_private *portdata = usb_get_serial_port_data(port);
+ struct usb_serial *serial = port->serial;
+
+- dbg("%s", __FUNCTION__);
+- dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata);
++ dbg("%s", __func__);
++ dbg("%s: urb %p port %p has data %p", __func__,urb,port,portdata);
+
+ if (status == 0) {
+ struct usb_ctrlrequest *req_pkt =
+ (struct usb_ctrlrequest *)urb->transfer_buffer;
+
+ if (!req_pkt) {
+- dbg("%s: NULL req_pkt\n", __FUNCTION__);
++ dbg("%s: NULL req_pkt\n", __func__);
+ return;
+ }
+ if ((req_pkt->bRequestType == 0xA1) &&
+@@ -621,7 +619,7 @@ static void option_instat_callback(struct urb *urb)
+ urb->transfer_buffer +
+ sizeof(struct usb_ctrlrequest));
+
+- dbg("%s: signal x%x", __FUNCTION__, signals);
++ dbg("%s: signal x%x", __func__, signals);
+
+ old_dcd_state = portdata->dcd_state;
+ portdata->cts_state = 1;
+@@ -633,11 +631,11 @@ static void option_instat_callback(struct urb *urb)
+ old_dcd_state && !portdata->dcd_state)
+ tty_hangup(port->tty);
+ } else {
+- dbg("%s: type %x req %x", __FUNCTION__,
++ dbg("%s: type %x req %x", __func__,
+ req_pkt->bRequestType,req_pkt->bRequest);
+ }
+ } else
+- dbg("%s: error %d", __FUNCTION__, status);
++ dbg("%s: error %d", __func__, status);
+
+ /* Resubmit urb so we continue receiving IRQ data */
+ if (status != -ESHUTDOWN) {
+@@ -645,7 +643,7 @@ static void option_instat_callback(struct urb *urb)
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err)
+ dbg("%s: resubmit intr urb failed. (%d)",
+- __FUNCTION__, err);
++ __func__, err);
+ }
+ }
+
+@@ -658,13 +656,14 @@ static int option_write_room(struct usb_serial_port *port)
+
+ portdata = usb_get_serial_port_data(port);
+
++
+ for (i=0; i < N_OUT_URB; i++) {
+ this_urb = portdata->out_urbs[i];
+ if (this_urb && !test_bit(i, &portdata->out_busy))
+ data_len += OUT_BUFLEN;
+ }
+
+- dbg("%s: %d", __FUNCTION__, data_len);
++ dbg("%s: %d", __func__, data_len);
+ return data_len;
+ }
+
+@@ -679,10 +678,12 @@ static int option_chars_in_buffer(struct usb_serial_port *port)
+
+ for (i=0; i < N_OUT_URB; i++) {
+ this_urb = portdata->out_urbs[i];
++ /* FIXME: This locking is insufficient as this_urb may
++ go unused during the test */
+ if (this_urb && test_bit(i, &portdata->out_busy))
+ data_len += this_urb->transfer_buffer_length;
+ }
+- dbg("%s: %d", __FUNCTION__, data_len);
++ dbg("%s: %d", __func__, data_len);
+ return data_len;
+ }
+
+@@ -695,7 +696,7 @@ static int option_open(struct usb_serial_port *port, struct file *filp)
+
+ portdata = usb_get_serial_port_data(port);
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ /* Set some sane defaults */
+ portdata->rts_state = 1;
+@@ -707,7 +708,7 @@ static int option_open(struct usb_serial_port *port, struct file *filp)
+ if (! urb)
+ continue;
+ if (urb->dev != serial->dev) {
+- dbg("%s: dev %p != %p", __FUNCTION__,
++ dbg("%s: dev %p != %p", __func__,
+ urb->dev, serial->dev);
+ continue;
+ }
+@@ -721,7 +722,7 @@ static int option_open(struct usb_serial_port *port, struct file *filp)
+ err = usb_submit_urb(urb, GFP_KERNEL);
+ if (err) {
+ dbg("%s: submit urb %d failed (%d) %d",
+- __FUNCTION__, i, err,
++ __func__, i, err,
+ urb->transfer_buffer_length);
+ }
+ }
+@@ -749,7 +750,7 @@ static void option_close(struct usb_serial_port *port, struct file *filp)
+ struct usb_serial *serial = port->serial;
+ struct option_port_private *portdata;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+ portdata = usb_get_serial_port_data(port);
+
+ portdata->rts_state = 0;
+@@ -782,7 +783,7 @@ static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint,
+
+ urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
+ if (urb == NULL) {
+- dbg("%s: alloc for endpoint %d failed.", __FUNCTION__, endpoint);
++ dbg("%s: alloc for endpoint %d failed.", __func__, endpoint);
+ return NULL;
+ }
+
+@@ -801,7 +802,7 @@ static void option_setup_urbs(struct usb_serial *serial)
+ struct usb_serial_port *port;
+ struct option_port_private *portdata;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ for (i = 0; i < serial->num_ports; i++) {
+ port = serial->port[i];
+@@ -823,15 +824,18 @@ static void option_setup_urbs(struct usb_serial *serial)
+ }
+ }
+
++
++/** send RTS/DTR state to the port.
++ *
++ * This is exactly the same as SET_CONTROL_LINE_STATE from the PSTN
++ * CDC.
++*/
+ static int option_send_setup(struct usb_serial_port *port)
+ {
+ struct usb_serial *serial = port->serial;
+ struct option_port_private *portdata;
+-
+- dbg("%s", __FUNCTION__);
+-
+- if (port->number != 0)
+- return 0;
++ int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
++ dbg("%s", __func__);
+
+ portdata = usb_get_serial_port_data(port);
+
+@@ -844,7 +848,7 @@ static int option_send_setup(struct usb_serial_port *port)
+
+ return usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
+- 0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
++ 0x22,0x21,val,ifNum,NULL,0,USB_CTRL_SET_TIMEOUT);
+ }
+
+ return 0;
+@@ -857,7 +861,7 @@ static int option_startup(struct usb_serial *serial)
+ struct option_port_private *portdata;
+ u8 *buffer;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ /* Now setup per port private data */
+ for (i = 0; i < serial->num_ports; i++) {
+@@ -865,7 +869,7 @@ static int option_startup(struct usb_serial *serial)
+ portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
+ if (!portdata) {
+ dbg("%s: kmalloc for option_port_private (%d) failed!.",
+- __FUNCTION__, i);
++ __func__, i);
+ return (1);
+ }
+
+@@ -890,7 +894,7 @@ static int option_startup(struct usb_serial *serial)
+ err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ if (err)
+ dbg("%s: submit irq_in urb failed %d",
+- __FUNCTION__, err);
++ __func__, err);
+ }
+
+ option_setup_urbs(serial);
+@@ -914,7 +918,7 @@ static void option_shutdown(struct usb_serial *serial)
+ struct usb_serial_port *port;
+ struct option_port_private *portdata;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ /* Stop reading/writing urbs */
+ for (i = 0; i < serial->num_ports; ++i) {
+diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
+index a3847d6..d92bb65 100644
+--- a/drivers/usb/serial/oti6858.c
++++ b/drivers/usb/serial/oti6858.c
+@@ -179,9 +179,6 @@ static struct usb_serial_driver oti6858_device = {
+ .name = "oti6858",
+ },
+ .id_table = id_table,
+- .num_interrupt_in = 1,
+- .num_bulk_in = 1,
+- .num_bulk_out = 1,
+ .num_ports = 1,
+ .open = oti6858_open,
+ .close = oti6858_close,
+@@ -238,10 +235,10 @@ static void setup_line(struct work_struct *work)
+ unsigned long flags;
+ int result;
+
+- dbg("%s(port = %d)", __FUNCTION__, port->number);
++ dbg("%s(port = %d)", __func__, port->number);
+
+ if ((new_setup = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) {
+- dev_err(&port->dev, "%s(): out of memory!\n", __FUNCTION__);
++ dev_err(&port->dev, "%s(): out of memory!\n", __func__);
+ /* we will try again */
+ schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2));
+ return;
+@@ -256,7 +253,7 @@ static void setup_line(struct work_struct *work)
+ 100);
+
+ if (result != OTI6858_CTRL_PKT_SIZE) {
+- dev_err(&port->dev, "%s(): error reading status\n", __FUNCTION__);
++ dev_err(&port->dev, "%s(): error reading status\n", __func__);
+ kfree(new_setup);
+ /* we will try again */
+ schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2));
+@@ -289,12 +286,12 @@ static void setup_line(struct work_struct *work)
+ priv->setup_done = 1;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+- dbg("%s(): submitting interrupt urb", __FUNCTION__);
++ dbg("%s(): submitting interrupt urb", __func__);
+ port->interrupt_in_urb->dev = port->serial->dev;
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+ if (result != 0) {
+ dev_err(&port->dev, "%s(): usb_submit_urb() failed"
+- " with error %d\n", __FUNCTION__, result);
++ " with error %d\n", __func__, result);
+ }
+ }
+
+@@ -306,7 +303,7 @@ void send_data(struct work_struct *work)
+ unsigned long flags;
+ unsigned char allow;
+
+- dbg("%s(port = %d)", __FUNCTION__, port->number);
++ dbg("%s(port = %d)", __func__, port->number);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (priv->flags.write_urb_in_use) {
+@@ -334,12 +331,12 @@ void send_data(struct work_struct *work)
+ if (count == 0) {
+ priv->flags.write_urb_in_use = 0;
+
+- dbg("%s(): submitting interrupt urb", __FUNCTION__);
++ dbg("%s(): submitting interrupt urb", __func__);
+ port->interrupt_in_urb->dev = port->serial->dev;
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+ if (result != 0) {
+ dev_err(&port->dev, "%s(): usb_submit_urb() failed"
+- " with error %d\n", __FUNCTION__, result);
++ " with error %d\n", __func__, result);
+ }
+ return;
+ }
+@@ -353,7 +350,7 @@ void send_data(struct work_struct *work)
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ if (result != 0) {
+ dev_err(&port->dev, "%s(): usb_submit_urb() failed"
+- " with error %d\n", __FUNCTION__, result);
++ " with error %d\n", __func__, result);
+ priv->flags.write_urb_in_use = 0;
+ }
+
+@@ -404,7 +401,7 @@ static int oti6858_write(struct usb_serial_port *port,
+ struct oti6858_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+
+- dbg("%s(port = %d, count = %d)", __FUNCTION__, port->number, count);
++ dbg("%s(port = %d, count = %d)", __func__, port->number, count);
+
+ if (!count)
+ return count;
+@@ -422,7 +419,7 @@ static int oti6858_write_room(struct usb_serial_port *port)
+ int room = 0;
+ unsigned long flags;
+
+- dbg("%s(port = %d)", __FUNCTION__, port->number);
++ dbg("%s(port = %d)", __func__, port->number);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ room = oti6858_buf_space_avail(priv->buf);
+@@ -437,7 +434,7 @@ static int oti6858_chars_in_buffer(struct usb_serial_port *port)
+ int chars = 0;
+ unsigned long flags;
+
+- dbg("%s(port = %d)", __FUNCTION__, port->number);
++ dbg("%s(port = %d)", __func__, port->number);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ chars = oti6858_buf_data_avail(priv->buf);
+@@ -456,10 +453,10 @@ static void oti6858_set_termios(struct usb_serial_port *port,
+ u16 divisor;
+ int br;
+
+- dbg("%s(port = %d)", __FUNCTION__, port->number);
++ dbg("%s(port = %d)", __func__, port->number);
+
+ if (!port->tty || !port->tty->termios) {
+- dbg("%s(): no tty structures", __FUNCTION__);
++ dbg("%s(): no tty structures", __func__);
+ return;
+ }
+
+@@ -575,7 +572,7 @@ static int oti6858_open(struct usb_serial_port *port, struct file *filp)
+ unsigned long flags;
+ int result;
+
+- dbg("%s(port = %d)", __FUNCTION__, port->number);
++ dbg("%s(port = %d)", __func__, port->number);
+
+ usb_clear_halt(serial->dev, port->write_urb->pipe);
+ usb_clear_halt(serial->dev, port->read_urb->pipe);
+@@ -584,7 +581,7 @@ static int oti6858_open(struct usb_serial_port *port, struct file *filp)
+ return 0;
+
+ if ((buf = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) {
+- dev_err(&port->dev, "%s(): out of memory!\n", __FUNCTION__);
++ dev_err(&port->dev, "%s(): out of memory!\n", __func__);
+ return -ENOMEM;
+ }
+
+@@ -613,12 +610,12 @@ static int oti6858_open(struct usb_serial_port *port, struct file *filp)
+ spin_unlock_irqrestore(&priv->lock, flags);
+ kfree(buf);
+
+- dbg("%s(): submitting interrupt urb", __FUNCTION__);
++ dbg("%s(): submitting interrupt urb", __func__);
+ port->interrupt_in_urb->dev = serial->dev;
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ if (result != 0) {
+ dev_err(&port->dev, "%s(): usb_submit_urb() failed"
+- " with error %d\n", __FUNCTION__, result);
++ " with error %d\n", __func__, result);
+ oti6858_close(port, NULL);
+ return -EPROTO;
+ }
+@@ -637,14 +634,14 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
+ long timeout;
+ wait_queue_t wait;
+
+- dbg("%s(port = %d)", __FUNCTION__, port->number);
++ dbg("%s(port = %d)", __func__, port->number);
+
+ /* wait for data to drain from the buffer */
+ spin_lock_irqsave(&priv->lock, flags);
+ timeout = 30 * HZ; /* PL2303_CLOSING_WAIT */
+ init_waitqueue_entry(&wait, current);
+ add_wait_queue(&port->tty->write_wait, &wait);
+- dbg("%s(): entering wait loop", __FUNCTION__);
++ dbg("%s(): entering wait loop", __func__);
+ for (;;) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (oti6858_buf_data_avail(priv->buf) == 0
+@@ -657,7 +654,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
+ }
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&port->tty->write_wait, &wait);
+- dbg("%s(): after wait loop", __FUNCTION__);
++ dbg("%s(): after wait loop", __func__);
+
+ /* clear out any remaining data in the buffer */
+ oti6858_buf_clear(priv->buf);
+@@ -678,7 +675,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
+ */
+ timeout = 2*HZ;
+ schedule_timeout_interruptible(timeout);
+- dbg("%s(): after schedule_timeout_interruptible()", __FUNCTION__);
++ dbg("%s(): after schedule_timeout_interruptible()", __func__);
+
+ /* cancel scheduled setup */
+ cancel_delayed_work(&priv->delayed_setup_work);
+@@ -686,7 +683,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
+ flush_scheduled_work();
+
+ /* shutdown our urbs */
+- dbg("%s(): shutting down urbs", __FUNCTION__);
++ dbg("%s(): shutting down urbs", __func__);
+ usb_kill_urb(port->write_urb);
+ usb_kill_urb(port->read_urb);
+ usb_kill_urb(port->interrupt_in_urb);
+@@ -709,7 +706,7 @@ static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file,
+ u8 control;
+
+ dbg("%s(port = %d, set = 0x%08x, clear = 0x%08x)",
+- __FUNCTION__, port->number, set, clear);
++ __func__, port->number, set, clear);
+
+ if (!usb_get_intfdata(port->serial->interface))
+ return -ENODEV;
+@@ -741,7 +738,7 @@ static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file)
+ unsigned pin_state;
+ unsigned result = 0;
+
+- dbg("%s(port = %d)", __FUNCTION__, port->number);
++ dbg("%s(port = %d)", __func__, port->number);
+
+ if (!usb_get_intfdata(port->serial->interface))
+ return -ENODEV;
+@@ -764,7 +761,7 @@ static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file)
+ if ((pin_state & PIN_DCD) != 0)
+ result |= TIOCM_CD;
+
+- dbg("%s() = 0x%08x", __FUNCTION__, result);
++ dbg("%s() = 0x%08x", __func__, result);
+
+ return result;
+ }
+@@ -811,13 +808,9 @@ static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
+ unsigned int x;
+
+ dbg("%s(port = %d, cmd = 0x%04x, arg = 0x%08lx)",
+- __FUNCTION__, port->number, cmd, arg);
++ __func__, port->number, cmd, arg);
+
+ switch (cmd) {
+- case TCFLSH:
+- /* FIXME */
+- return 0;
+-
+ case TIOCMBIS:
+ if (copy_from_user(&x, user_arg, sizeof(x)))
+ return -EFAULT;
+@@ -829,11 +822,11 @@ static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
+ return oti6858_tiocmset(port, NULL, 0, x);
+
+ case TIOCMIWAIT:
+- dbg("%s(): TIOCMIWAIT", __FUNCTION__);
++ dbg("%s(): TIOCMIWAIT", __func__);
+ return wait_modem_info(port, arg);
+
+ default:
+- dbg("%s(): 0x%04x not supported", __FUNCTION__, cmd);
++ dbg("%s(): 0x%04x not supported", __func__, cmd);
+ break;
+ }
+
+@@ -844,10 +837,10 @@ static void oti6858_break_ctl(struct usb_serial_port *port, int break_state)
+ {
+ int state;
+
+- dbg("%s(port = %d)", __FUNCTION__, port->number);
++ dbg("%s(port = %d)", __func__, port->number);
+
+ state = (break_state == 0) ? 0 : 1;
+- dbg("%s(): turning break %s", __FUNCTION__, state ? "on" : "off");
++ dbg("%s(): turning break %s", __func__, state ? "on" : "off");
+
+ /* FIXME */
+ /*
+@@ -855,7 +848,7 @@ static void oti6858_break_ctl(struct usb_serial_port *port, int break_state)
+ BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
+ 0, NULL, 0, 100);
+ if (result != 0)
+- dbg("%s(): error sending break", __FUNCTION__);
++ dbg("%s(): error sending break", __func__);
+ */
+ }
+
+@@ -864,7 +857,7 @@ static void oti6858_shutdown(struct usb_serial *serial)
+ struct oti6858_private *priv;
+ int i;
+
+- dbg("%s()", __FUNCTION__);
++ dbg("%s()", __func__);
+
+ for (i = 0; i < serial->num_ports; ++i) {
+ priv = usb_get_serial_port_data(serial->port[i]);
+@@ -878,13 +871,13 @@ static void oti6858_shutdown(struct usb_serial *serial)
+
+ static void oti6858_read_int_callback(struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct oti6858_private *priv = usb_get_serial_port_data(port);
+ int transient = 0, can_recv = 0, resubmit = 1;
+ int status = urb->status;
+
+ dbg("%s(port = %d, status = %d)",
+- __FUNCTION__, port->number, status);
++ __func__, port->number, status);
+
+ switch (status) {
+ case 0:
+@@ -895,11 +888,11 @@ static void oti6858_read_int_callback(struct urb *urb)
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s(): urb shutting down with status: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ default:
+ dbg("%s(): nonzero urb status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ break;
+ }
+
+@@ -916,7 +909,7 @@ static void oti6858_read_int_callback(struct urb *urb)
+ priv->setup_done = 0;
+ resubmit = 0;
+ dbg("%s(): scheduling setup_line()",
+- __FUNCTION__);
++ __func__);
+ schedule_delayed_work(&priv->delayed_setup_work, 0);
+ }
+ }
+@@ -931,7 +924,7 @@ static void oti6858_read_int_callback(struct urb *urb)
+ priv->setup_done = 0;
+ resubmit = 0;
+ dbg("%s(): scheduling setup_line()",
+- __FUNCTION__);
++ __func__);
+ schedule_delayed_work(&priv->delayed_setup_work, 0);
+ }
+ }
+@@ -960,7 +953,7 @@ static void oti6858_read_int_callback(struct urb *urb)
+ if (result != 0) {
+ priv->flags.read_urb_in_use = 0;
+ dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
+- " error %d\n", __FUNCTION__, result);
++ " error %d\n", __func__, result);
+ } else {
+ resubmit = 0;
+ }
+@@ -979,20 +972,20 @@ static void oti6858_read_int_callback(struct urb *urb)
+ if (resubmit) {
+ int result;
+
+-// dbg("%s(): submitting interrupt urb", __FUNCTION__);
++// dbg("%s(): submitting interrupt urb", __func__);
+ urb->dev = port->serial->dev;
+ result = usb_submit_urb(urb, GFP_ATOMIC);
+ if (result != 0) {
+ dev_err(&urb->dev->dev,
+ "%s(): usb_submit_urb() failed with"
+- " error %d\n", __FUNCTION__, result);
++ " error %d\n", __func__, result);
+ }
+ }
+ }
+
+ static void oti6858_read_bulk_callback(struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct oti6858_private *priv = usb_get_serial_port_data(port);
+ struct tty_struct *tty;
+ unsigned char *data = urb->transfer_buffer;
+@@ -1001,7 +994,7 @@ static void oti6858_read_bulk_callback(struct urb *urb)
+ int result;
+
+ dbg("%s(port = %d, status = %d)",
+- __FUNCTION__, port->number, status);
++ __func__, port->number, status);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->flags.read_urb_in_use = 0;
+@@ -1009,20 +1002,20 @@ static void oti6858_read_bulk_callback(struct urb *urb)
+
+ if (status != 0) {
+ if (!port->open_count) {
+- dbg("%s(): port is closed, exiting", __FUNCTION__);
++ dbg("%s(): port is closed, exiting", __func__);
+ return;
+ }
+ /*
+ if (status == -EPROTO) {
+ // PL2303 mysteriously fails with -EPROTO reschedule the read
+- dbg("%s - caught -EPROTO, resubmitting the urb", __FUNCTION__);
++ dbg("%s - caught -EPROTO, resubmitting the urb", __func__);
+ result = usb_submit_urb(urb, GFP_ATOMIC);
+ if (result)
+- dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
++ dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
+ return;
+ }
+ */
+- dbg("%s(): unable to handle the error, exiting", __FUNCTION__);
++ dbg("%s(): unable to handle the error, exiting", __func__);
+ return;
+ }
+
+@@ -1038,20 +1031,20 @@ static void oti6858_read_bulk_callback(struct urb *urb)
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+ if (result != 0) {
+ dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
+- " error %d\n", __FUNCTION__, result);
++ " error %d\n", __func__, result);
+ }
+ }
+ }
+
+ static void oti6858_write_bulk_callback(struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct oti6858_private *priv = usb_get_serial_port_data(port);
+ int status = urb->status;
+ int result;
+
+ dbg("%s(port = %d, status = %d)",
+- __FUNCTION__, port->number, status);
++ __func__, port->number, status);
+
+ switch (status) {
+ case 0:
+@@ -1062,21 +1055,21 @@ static void oti6858_write_bulk_callback(struct urb *urb)
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s(): urb shutting down with status: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ priv->flags.write_urb_in_use = 0;
+ return;
+ default:
+ /* error in the urb, so we have to resubmit it */
+ dbg("%s(): nonzero write bulk status received: %d",
+- __FUNCTION__, status);
+- dbg("%s(): overflow in write", __FUNCTION__);
++ __func__, status);
++ dbg("%s(): overflow in write", __func__);
+
+ port->write_urb->transfer_buffer_length = 1;
+ port->write_urb->dev = port->serial->dev;
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ if (result) {
+ dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
+- " error %d\n", __FUNCTION__, result);
++ " error %d\n", __func__, result);
+ } else {
+ return;
+ }
+@@ -1086,11 +1079,11 @@ static void oti6858_write_bulk_callback(struct urb *urb)
+
+ // schedule the interrupt urb if we are still open */
+ port->interrupt_in_urb->dev = port->serial->dev;
+- dbg("%s(): submitting interrupt urb", __FUNCTION__);
++ dbg("%s(): submitting interrupt urb", __func__);
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+ if (result != 0) {
+ dev_err(&port->dev, "%s(): failed submitting int urb,"
+- " error %d\n", __FUNCTION__, result);
++ " error %d\n", __func__, result);
+ }
+ }
+
+diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
+index 2af7785..c605fb6 100644
+--- a/drivers/usb/serial/pl2303.c
++++ b/drivers/usb/serial/pl2303.c
+@@ -410,7 +410,7 @@ static int set_control_lines(struct usb_device *dev, u8 value)
+ retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE,
+ value, 0, NULL, 0, 100);
+- dbg("%s - value = %d, retval = %d", __FUNCTION__, value, retval);
++ dbg("%s - value = %d, retval = %d", __func__, value, retval);
+ return retval;
+ }
+
+@@ -420,7 +420,7 @@ static void pl2303_send(struct usb_serial_port *port)
+ struct pl2303_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+@@ -441,7 +441,7 @@ static void pl2303_send(struct usb_serial_port *port)
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count,
++ usb_serial_debug_data(debug, &port->dev, __func__, count,
+ port->write_urb->transfer_buffer);
+
+ port->write_urb->transfer_buffer_length = count;
+@@ -449,7 +449,7 @@ static void pl2303_send(struct usb_serial_port *port)
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ if (result) {
+ dev_err(&port->dev, "%s - failed submitting write urb,"
+- " error %d\n", __FUNCTION__, result);
++ " error %d\n", __func__, result);
+ priv->write_urb_in_use = 0;
+ // TODO: reschedule pl2303_send
+ }
+@@ -463,7 +463,7 @@ static int pl2303_write(struct usb_serial_port *port, const unsigned char *buf,
+ struct pl2303_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+
+- dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
++ dbg("%s - port %d, %d bytes", __func__, port->number, count);
+
+ if (!count)
+ return count;
+@@ -483,13 +483,13 @@ static int pl2303_write_room(struct usb_serial_port *port)
+ int room = 0;
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ room = pl2303_buf_space_avail(priv->buf);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+- dbg("%s - returns %d", __FUNCTION__, room);
++ dbg("%s - returns %d", __func__, room);
+ return room;
+ }
+
+@@ -499,13 +499,13 @@ static int pl2303_chars_in_buffer(struct usb_serial_port *port)
+ int chars = 0;
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ chars = pl2303_buf_data_avail(priv->buf);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+- dbg("%s - returns %d", __FUNCTION__, chars);
++ dbg("%s - returns %d", __func__, chars);
+ return chars;
+ }
+
+@@ -521,7 +521,7 @@ static void pl2303_set_termios(struct usb_serial_port *port,
+ int i;
+ u8 control;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (!priv->termios_initialized) {
+@@ -545,7 +545,9 @@ static void pl2303_set_termios(struct usb_serial_port *port,
+
+ buf = kzalloc(7, GFP_KERNEL);
+ if (!buf) {
+- dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__);
++ dev_err(&port->dev, "%s - out of memory.\n", __func__);
++ /* Report back no change occurred */
++ *port->tty->termios = *old_termios;
+ return;
+ }
+
+@@ -563,11 +565,11 @@ static void pl2303_set_termios(struct usb_serial_port *port,
+ default:
+ case CS8: buf[6] = 8; break;
+ }
+- dbg("%s - data bits = %d", __FUNCTION__, buf[6]);
++ dbg("%s - data bits = %d", __func__, buf[6]);
+ }
+
+ baud = tty_get_baud_rate(port->tty);;
+- dbg("%s - baud = %d", __FUNCTION__, baud);
++ dbg("%s - baud = %d", __func__, baud);
+ if (baud) {
+ buf[0] = baud & 0xff;
+ buf[1] = (baud >> 8) & 0xff;
+@@ -580,10 +582,10 @@ static void pl2303_set_termios(struct usb_serial_port *port,
+ /* For reference buf[4]=2 is 2 stop bits */
+ if (cflag & CSTOPB) {
+ buf[4] = 2;
+- dbg("%s - stop bits = 2", __FUNCTION__);
++ dbg("%s - stop bits = 2", __func__);
+ } else {
+ buf[4] = 0;
+- dbg("%s - stop bits = 1", __FUNCTION__);
++ dbg("%s - stop bits = 1", __func__);
+ }
+
+ if (cflag & PARENB) {
+@@ -594,14 +596,14 @@ static void pl2303_set_termios(struct usb_serial_port *port,
+ /* For reference buf[5]=4 is space parity */
+ if (cflag & PARODD) {
+ buf[5] = 1;
+- dbg("%s - parity = odd", __FUNCTION__);
++ dbg("%s - parity = odd", __func__);
+ } else {
+ buf[5] = 2;
+- dbg("%s - parity = even", __FUNCTION__);
++ dbg("%s - parity = even", __func__);
+ }
+ } else {
+ buf[5] = 0;
+- dbg("%s - parity = none", __FUNCTION__);
++ dbg("%s - parity = none", __func__);
+ }
+
+ i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+@@ -657,7 +659,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
+ long timeout;
+ wait_queue_t wait;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /* wait for data to drain from the buffer */
+ spin_lock_irqsave(&priv->lock, flags);
+@@ -695,7 +697,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
+ schedule_timeout_interruptible(timeout);
+
+ /* shutdown our urbs */
+- dbg("%s - shutting down urbs", __FUNCTION__);
++ dbg("%s - shutting down urbs", __func__);
+ usb_kill_urb(port->write_urb);
+ usb_kill_urb(port->read_urb);
+ usb_kill_urb(port->interrupt_in_urb);
+@@ -719,7 +721,7 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp)
+ struct pl2303_private *priv = usb_get_serial_port_data(port);
+ int result;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (priv->type != HX) {
+ usb_clear_halt(serial->dev, port->write_urb->pipe);
+@@ -737,22 +739,22 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp)
+
+ //FIXME: need to assert RTS and DTR if CRTSCTS off
+
+- dbg("%s - submitting read urb", __FUNCTION__);
++ dbg("%s - submitting read urb", __func__);
+ port->read_urb->dev = serial->dev;
+ result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ if (result) {
+ dev_err(&port->dev, "%s - failed submitting read urb,"
+- " error %d\n", __FUNCTION__, result);
++ " error %d\n", __func__, result);
+ pl2303_close(port, NULL);
+ return -EPROTO;
+ }
+
+- dbg("%s - submitting interrupt urb", __FUNCTION__);
++ dbg("%s - submitting interrupt urb", __func__);
+ port->interrupt_in_urb->dev = serial->dev;
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ if (result) {
+ dev_err(&port->dev, "%s - failed submitting interrupt urb,"
+- " error %d\n", __FUNCTION__, result);
++ " error %d\n", __func__, result);
+ pl2303_close(port, NULL);
+ return -EPROTO;
+ }
+@@ -792,7 +794,7 @@ static int pl2303_tiocmget(struct usb_serial_port *port, struct file *file)
+ unsigned int status;
+ unsigned int result;
+
+- dbg("%s (%d)", __FUNCTION__, port->number);
++ dbg("%s (%d)", __func__, port->number);
+
+ if (!usb_get_intfdata(port->serial->interface))
+ return -ENODEV;
+@@ -809,7 +811,7 @@ static int pl2303_tiocmget(struct usb_serial_port *port, struct file *file)
+ | ((status & UART_RING) ? TIOCM_RI : 0)
+ | ((status & UART_DCD) ? TIOCM_CD : 0);
+
+- dbg("%s - result = %x", __FUNCTION__, result);
++ dbg("%s - result = %x", __func__, result);
+
+ return result;
+ }
+@@ -853,15 +855,15 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
+ static int pl2303_ioctl(struct usb_serial_port *port, struct file *file,
+ unsigned int cmd, unsigned long arg)
+ {
+- dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd);
++ dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
+
+ switch (cmd) {
+ case TIOCMIWAIT:
+- dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number);
++ dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
+ return wait_modem_info(port, arg);
+
+ default:
+- dbg("%s not supported = 0x%04x", __FUNCTION__, cmd);
++ dbg("%s not supported = 0x%04x", __func__, cmd);
+ break;
+ }
+
+@@ -874,19 +876,19 @@ static void pl2303_break_ctl(struct usb_serial_port *port, int break_state)
+ u16 state;
+ int result;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (break_state == 0)
+ state = BREAK_OFF;
+ else
+ state = BREAK_ON;
+- dbg("%s - turning break %s", __FUNCTION__, state==BREAK_OFF ? "off" : "on");
++ dbg("%s - turning break %s", __func__, state==BREAK_OFF ? "off" : "on");
+
+ result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
+ 0, NULL, 0, 100);
+ if (result)
+- dbg("%s - error sending break = %d", __FUNCTION__, result);
++ dbg("%s - error sending break = %d", __func__, result);
+ }
+
+ static void pl2303_shutdown(struct usb_serial *serial)
+@@ -894,7 +896,7 @@ static void pl2303_shutdown(struct usb_serial *serial)
+ int i;
+ struct pl2303_private *priv;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ for (i = 0; i < serial->num_ports; ++i) {
+ priv = usb_get_serial_port_data(serial->port[i]);
+@@ -943,13 +945,13 @@ static void pl2303_update_line_status(struct usb_serial_port *port,
+
+ static void pl2303_read_int_callback(struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
++ struct usb_serial_port *port = urb->context;
+ unsigned char *data = urb->transfer_buffer;
+ unsigned int actual_length = urb->actual_length;
+ int status = urb->status;
+ int retval;
+
+- dbg("%s (%d)", __FUNCTION__, port->number);
++ dbg("%s (%d)", __func__, port->number);
+
+ switch (status) {
+ case 0:
+@@ -959,16 +961,16 @@ static void pl2303_read_int_callback(struct urb *urb)
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+- dbg("%s - urb shutting down with status: %d", __FUNCTION__,
++ dbg("%s - urb shutting down with status: %d", __func__,
+ status);
+ return;
+ default:
+- dbg("%s - nonzero urb status received: %d", __FUNCTION__,
++ dbg("%s - nonzero urb status received: %d", __func__,
+ status);
+ goto exit;
+ }
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
++ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, urb->transfer_buffer);
+
+ pl2303_update_line_status(port, data, actual_length);
+@@ -978,12 +980,12 @@ exit:
+ if (retval)
+ dev_err(&urb->dev->dev,
+ "%s - usb_submit_urb failed with result %d\n",
+- __FUNCTION__, retval);
++ __func__, retval);
+ }
+
+ static void pl2303_read_bulk_callback(struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct pl2303_private *priv = usb_get_serial_port_data(port);
+ struct tty_struct *tty;
+ unsigned char *data = urb->transfer_buffer;
+@@ -994,32 +996,32 @@ static void pl2303_read_bulk_callback(struct urb *urb)
+ u8 line_status;
+ char tty_flag;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (status) {
+- dbg("%s - urb status = %d", __FUNCTION__, status);
++ dbg("%s - urb status = %d", __func__, status);
+ if (!port->open_count) {
+- dbg("%s - port is closed, exiting.", __FUNCTION__);
++ dbg("%s - port is closed, exiting.", __func__);
+ return;
+ }
+ if (status == -EPROTO) {
+ /* PL2303 mysteriously fails with -EPROTO reschedule
+ * the read */
+ dbg("%s - caught -EPROTO, resubmitting the urb",
+- __FUNCTION__);
++ __func__);
+ urb->dev = port->serial->dev;
+ result = usb_submit_urb(urb, GFP_ATOMIC);
+ if (result)
+ dev_err(&urb->dev->dev, "%s - failed"
+ " resubmitting read urb, error %d\n",
+- __FUNCTION__, result);
++ __func__, result);
+ return;
+ }
+- dbg("%s - unable to handle the error, exiting.", __FUNCTION__);
++ dbg("%s - unable to handle the error, exiting.", __func__);
+ return;
+ }
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
++ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
+
+ /* get tty_flag from status */
+@@ -1039,7 +1041,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
+ tty_flag = TTY_PARITY;
+ else if (line_status & UART_FRAME_ERROR)
+ tty_flag = TTY_FRAME;
+- dbg("%s - tty_flag = %d", __FUNCTION__, tty_flag);
++ dbg("%s - tty_flag = %d", __func__, tty_flag);
+
+ tty = port->tty;
+ if (tty && urb->actual_length) {
+@@ -1058,7 +1060,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
+ result = usb_submit_urb(urb, GFP_ATOMIC);
+ if (result)
+ dev_err(&urb->dev->dev, "%s - failed resubmitting"
+- " read urb, error %d\n", __FUNCTION__, result);
++ " read urb, error %d\n", __func__, result);
+ }
+
+ return;
+@@ -1066,12 +1068,12 @@ static void pl2303_read_bulk_callback(struct urb *urb)
+
+ static void pl2303_write_bulk_callback(struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct pl2303_private *priv = usb_get_serial_port_data(port);
+ int result;
+ int status = urb->status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ switch (status) {
+ case 0:
+@@ -1081,21 +1083,21 @@ static void pl2303_write_bulk_callback(struct urb *urb)
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+- dbg("%s - urb shutting down with status: %d", __FUNCTION__,
++ dbg("%s - urb shutting down with status: %d", __func__,
+ status);
+ priv->write_urb_in_use = 0;
+ return;
+ default:
+ /* error in the urb, so we have to resubmit it */
+- dbg("%s - Overflow in write", __FUNCTION__);
+- dbg("%s - nonzero write bulk status received: %d", __FUNCTION__,
++ dbg("%s - Overflow in write", __func__);
++ dbg("%s - nonzero write bulk status received: %d", __func__,
+ status);
+ port->write_urb->transfer_buffer_length = 1;
+ port->write_urb->dev = port->serial->dev;
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ if (result)
+ dev_err(&urb->dev->dev, "%s - failed resubmitting write"
+- " urb, error %d\n", __FUNCTION__, result);
++ " urb, error %d\n", __func__, result);
+ else
+ return;
+ }
+@@ -1114,9 +1116,6 @@ static struct usb_serial_driver pl2303_device = {
+ },
+ .id_table = id_table,
+ .usb_driver = &pl2303_driver,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_bulk_in = 1,
+- .num_bulk_out = 1,
+ .num_ports = 1,
+ .open = pl2303_open,
+ .close = pl2303_close,
+diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
+index 4e6dcc1..94bddf0 100644
+--- a/drivers/usb/serial/safe_serial.c
++++ b/drivers/usb/serial/safe_serial.c
+@@ -195,18 +195,17 @@ static __u16 __inline__ fcs_compute10 (unsigned char *sp, int len, __u16 fcs)
+
+ static void safe_read_bulk_callback (struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
++ struct usb_serial_port *port = urb->context;
+ unsigned char *data = urb->transfer_buffer;
+ unsigned char length = urb->actual_length;
+- int i;
+ int result;
+ int status = urb->status;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
+
+@@ -227,28 +226,20 @@ static void safe_read_bulk_callback (struct urb *urb)
+ if (safe) {
+ __u16 fcs;
+ if (!(fcs = fcs_compute10 (data, length, CRC10_INITFCS))) {
+-
+ int actual_length = data[length - 2] >> 2;
+-
+ if (actual_length <= (length - 2)) {
+-
+- info ("%s - actual: %d", __FUNCTION__, actual_length);
+-
+- for (i = 0; i < actual_length; i++) {
+- tty_insert_flip_char (port->tty, data[i], 0);
+- }
++ info ("%s - actual: %d", __func__, actual_length);
++ tty_insert_flip_string(port->tty, data, actual_length);
+ tty_flip_buffer_push (port->tty);
+ } else {
+- err ("%s - inconsistent lengths %d:%d", __FUNCTION__,
++ err ("%s - inconsistent lengths %d:%d", __func__,
+ actual_length, length);
+ }
+ } else {
+- err ("%s - bad CRC %x", __FUNCTION__, fcs);
++ err ("%s - bad CRC %x", __func__, fcs);
+ }
+ } else {
+- for (i = 0; i < length; i++) {
+- tty_insert_flip_char (port->tty, data[i], 0);
+- }
++ tty_insert_flip_string(port->tty, data, length);
+ tty_flip_buffer_push (port->tty);
+ }
+
+@@ -259,7 +250,8 @@ static void safe_read_bulk_callback (struct urb *urb)
+ safe_read_bulk_callback, port);
+
+ if ((result = usb_submit_urb (urb, GFP_ATOMIC))) {
+- err ("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
++ err ("%s - failed resubmitting read urb, error %d", __func__, result);
++ /* FIXME: Need a mechanism to retry later if this happens */
+ }
+ }
+
+@@ -274,25 +266,25 @@ static int safe_write (struct usb_serial_port *port, const unsigned char *buf, i
+ count);
+
+ if (!port->write_urb) {
+- dbg ("%s - write urb NULL", __FUNCTION__);
+- return (0);
++ dbg ("%s - write urb NULL", __func__);
++ return 0;
+ }
+
+ dbg ("safe_write write_urb: %d transfer_buffer_length",
+ port->write_urb->transfer_buffer_length);
+
+ if (!port->write_urb->transfer_buffer_length) {
+- dbg ("%s - write urb transfer_buffer_length zero", __FUNCTION__);
+- return (0);
++ dbg ("%s - write urb transfer_buffer_length zero", __func__);
++ return 0;
+ }
+ if (count == 0) {
+- dbg ("%s - write request of 0 bytes", __FUNCTION__);
+- return (0);
++ dbg ("%s - write request of 0 bytes", __func__);
++ return 0;
+ }
+ spin_lock_bh(&port->lock);
+ if (port->write_urb_busy) {
+ spin_unlock_bh(&port->lock);
+- dbg("%s - already writing", __FUNCTION__);
++ dbg("%s - already writing", __func__);
+ return 0;
+ }
+ port->write_urb_busy = 1;
+@@ -332,7 +324,7 @@ static int safe_write (struct usb_serial_port *port, const unsigned char *buf, i
+ port->write_urb->transfer_buffer_length = count;
+ }
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer);
++ usb_serial_debug_data(debug, &port->dev, __func__, count, port->write_urb->transfer_buffer);
+ #ifdef ECHO_TX
+ {
+ int i;
+@@ -349,28 +341,31 @@ static int safe_write (struct usb_serial_port *port, const unsigned char *buf, i
+ port->write_urb->dev = port->serial->dev;
+ if ((result = usb_submit_urb (port->write_urb, GFP_KERNEL))) {
+ port->write_urb_busy = 0;
+- err ("%s - failed submitting write urb, error %d", __FUNCTION__, result);
++ err ("%s - failed submitting write urb, error %d", __func__, result);
+ return 0;
+ }
+- dbg ("%s urb: %p submitted", __FUNCTION__, port->write_urb);
++ dbg ("%s urb: %p submitted", __func__, port->write_urb);
+
+ return (count);
+ }
+
+ static int safe_write_room (struct usb_serial_port *port)
+ {
+- int room = 0; // Default: no room
++ int room = 0; /* Default: no room */
++ unsigned long flags;
+
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
++ spin_lock_irqsave(&port->lock, flags);
+ if (port->write_urb_busy)
+ room = port->bulk_out_size - (safe ? 2 : 0);
++ spin_unlock_irqrestore(&port->lock, flags);
+
+ if (room) {
+ dbg ("safe_write_room returns %d", room);
+ }
+
+- return (room);
++ return room;
+ }
+
+ static int safe_startup (struct usb_serial *serial)
+@@ -394,9 +389,6 @@ static struct usb_serial_driver safe_device = {
+ },
+ .id_table = id_table,
+ .usb_driver = &safe_driver,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_bulk_in = NUM_DONT_CARE,
+- .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 1,
+ .write = safe_write,
+ .write_room = safe_write_room,
+diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
+index ed67881..29074c1 100644
+--- a/drivers/usb/serial/sierra.c
++++ b/drivers/usb/serial/sierra.c
+@@ -1,7 +1,7 @@
+ /*
+ USB Driver for Sierra Wireless
+
+- Copyright (C) 2006, 2007, 2008 Kevin Lloyd <linux at sierrawireless.com>
++ Copyright (C) 2006, 2007, 2008 Kevin Lloyd <klloyd at sierrawireless.com>
+
+ IMPORTANT DISCLAIMER: This driver is not commercially supported by
+ Sierra Wireless. Use at your own risk.
+@@ -14,8 +14,8 @@
+ Whom based his on the Keyspan driver by Hugh Blemings <hugh at blemings.org>
+ */
+
+-#define DRIVER_VERSION "v.1.2.8"
+-#define DRIVER_AUTHOR "Kevin Lloyd <linux at sierrawireless.com>"
++#define DRIVER_VERSION "v.1.2.9c"
++#define DRIVER_AUTHOR "Kevin Lloyd <klloyd at sierrawireless.com>"
+ #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
+
+ #include <linux/kernel.h>
+@@ -31,7 +31,6 @@
+ #define SWIMS_USB_REQUEST_SetPower 0x00
+ #define SWIMS_USB_REQUEST_SetNmea 0x07
+ #define SWIMS_USB_REQUEST_SetMode 0x0B
+-#define SWIMS_USB_REQUEST_TYPE_VSC_SET 0x40
+ #define SWIMS_SET_MODE_Modem 0x0001
+
+ /* per port private data */
+@@ -55,7 +54,7 @@ static int sierra_set_power_state(struct usb_device *udev, __u16 swiState)
+ dev_dbg(&udev->dev, "%s", "SET POWER STATE\n");
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ SWIMS_USB_REQUEST_SetPower, /* __u8 request */
+- SWIMS_USB_REQUEST_TYPE_VSC_SET, /* __u8 request type */
++ USB_TYPE_VENDOR, /* __u8 request type */
+ swiState, /* __u16 value */
+ 0, /* __u16 index */
+ NULL, /* void *data */
+@@ -70,7 +69,7 @@ static int sierra_set_ms_mode(struct usb_device *udev, __u16 eSWocMode)
+ dev_dbg(&udev->dev, "%s", "DEVICE MODE SWITCH\n");
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ SWIMS_USB_REQUEST_SetMode, /* __u8 request */
+- SWIMS_USB_REQUEST_TYPE_VSC_SET, /* __u8 request type */
++ USB_TYPE_VENDOR, /* __u8 request type */
+ eSWocMode, /* __u16 value */
+ 0x0000, /* __u16 index */
+ NULL, /* void *data */
+@@ -85,7 +84,7 @@ static int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable)
+ dev_dbg(&udev->dev, "%s", "NMEA Enable sent\n");
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ SWIMS_USB_REQUEST_SetNmea, /* __u8 request */
+- SWIMS_USB_REQUEST_TYPE_VSC_SET, /* __u8 request type */
++ USB_TYPE_VENDOR, /* __u8 request type */
+ enable, /* __u16 value */
+ 0x0000, /* __u16 index */
+ NULL, /* void *data */
+@@ -109,6 +108,26 @@ static int sierra_calc_num_ports(struct usb_serial *serial)
+ return result;
+ }
+
++static int sierra_calc_interface(struct usb_serial *serial)
++{
++ int interface;
++ struct usb_interface *p_interface;
++ struct usb_host_interface *p_host_interface;
++
++ /* Get the interface structure pointer from the serial struct */
++ p_interface = serial->interface;
++
++ /* Get a pointer to the host interface structure */
++ p_host_interface = p_interface->cur_altsetting;
++
++ /* read the interface descriptor for this active altsetting
++ * to find out the interface number we are on
++ */
++ interface = p_host_interface->desc.bInterfaceNumber;
++
++ return interface;
++}
++
+ static int sierra_probe(struct usb_serial *serial,
+ const struct usb_device_id *id)
+ {
+@@ -124,6 +143,22 @@ static int sierra_probe(struct usb_serial *serial,
+ ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
+ udev = serial->dev;
+
++ /* Figure out the interface number from the serial structure */
++ ifnum = sierra_calc_interface(serial);
++
++ /*
++ * If this interface supports more than 1 alternate
++ * select the 2nd one
++ */
++ if (serial->interface->num_altsetting == 2) {
++ dev_dbg(&udev->dev,
++ "Selecting alt setting for interface %d\n",
++ ifnum);
++
++ /* We know the alternate setting is 1 for the MC8785 */
++ usb_set_interface(udev, ifnum, 1);
++ }
++
+ /* Check if in installer mode */
+ if (truinstall && id->driver_info == DEVICE_INSTALLER) {
+ dev_dbg(&udev->dev, "%s", "FOUND TRU-INSTALL DEVICE(SW)\n");
+@@ -156,7 +191,7 @@ static struct usb_device_id id_table [] = {
+ { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */
+ { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */
+ { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U */
+- { USB_DEVICE(0x1199, 0x0023) }, /* Sierra Wireless AirCard */
++ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0023, 0xFF, 0xFF, 0xFF) }, /* Sierra Wireless C597 */
+
+ { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */
+ { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */
+@@ -164,15 +199,20 @@ static struct usb_device_id id_table [] = {
+ { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 & AC 875U */
+ { USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8775 (Thinkpad internal) */
+ { USB_DEVICE(0x1199, 0x6815) }, /* Sierra Wireless MC8775 */
++ { USB_DEVICE(0x03f0, 0x1e1d) }, /* HP hs2300 a.k.a MC8775 */
+ { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */
++ { USB_DEVICE(0x1199, 0x6821) }, /* Sierra Wireless AirCard 875U */
+ { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780*/
+ { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781*/
++ { USB_DEVICE(0x1199, 0x683B), .driver_info = DEVICE_1_PORT }, /* Sierra Wireless MC8785 Composite*/
+ { USB_DEVICE(0x1199, 0x6850) }, /* Sierra Wireless AirCard 880 */
+ { USB_DEVICE(0x1199, 0x6851) }, /* Sierra Wireless AirCard 881 */
+ { USB_DEVICE(0x1199, 0x6852) }, /* Sierra Wireless AirCard 880 E */
+ { USB_DEVICE(0x1199, 0x6853) }, /* Sierra Wireless AirCard 881 E */
+ { USB_DEVICE(0x1199, 0x6855) }, /* Sierra Wireless AirCard 880 U */
+ { USB_DEVICE(0x1199, 0x6856) }, /* Sierra Wireless AirCard 881 U */
++ { USB_DEVICE(0x1199, 0x6859), .driver_info = DEVICE_1_PORT }, /* Sierra Wireless AirCard 885 E */
++ { USB_DEVICE(0x1199, 0x685A), .driver_info = DEVICE_1_PORT }, /* Sierra Wireless AirCard 885 E */
+
+ { USB_DEVICE(0x1199, 0x6468) }, /* Sierra Wireless MP3G - EVDO */
+ { USB_DEVICE(0x1199, 0x6469) }, /* Sierra Wireless MP3G - UMTS/HSPA */
+@@ -216,7 +256,7 @@ static int sierra_send_setup(struct usb_serial_port *port)
+ struct sierra_port_private *portdata;
+ __u16 interface = 0;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ portdata = usb_get_serial_port_data(port);
+
+@@ -246,24 +286,24 @@ static int sierra_send_setup(struct usb_serial_port *port)
+
+ static void sierra_rx_throttle(struct usb_serial_port *port)
+ {
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+ }
+
+ static void sierra_rx_unthrottle(struct usb_serial_port *port)
+ {
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+ }
+
+ static void sierra_break_ctl(struct usb_serial_port *port, int break_state)
+ {
+ /* Unfortunately, I don't know how to send a break */
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+ }
+
+ static void sierra_set_termios(struct usb_serial_port *port,
+ struct ktermios *old_termios)
+ {
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+ tty_termios_copy_hw(port->tty->termios, old_termios);
+ sierra_send_setup(port);
+ }
+@@ -317,14 +357,14 @@ static void sierra_outdat_callback(struct urb *urb)
+ int status = urb->status;
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /* free up the transfer buffer, as usb_free_urb() does not do this */
+ kfree(urb->transfer_buffer);
+
+ if (status)
+ dbg("%s - nonzero write bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+
+ spin_lock_irqsave(&portdata->lock, flags);
+ --portdata->outstanding_urbs;
+@@ -346,12 +386,12 @@ static int sierra_write(struct usb_serial_port *port,
+
+ portdata = usb_get_serial_port_data(port);
+
+- dbg("%s: write (%d chars)", __FUNCTION__, count);
++ dbg("%s: write (%d chars)", __func__, count);
+
+ spin_lock_irqsave(&portdata->lock, flags);
+ if (portdata->outstanding_urbs > N_OUT_URB) {
+ spin_unlock_irqrestore(&portdata->lock, flags);
+- dbg("%s - write limit hit\n", __FUNCTION__);
++ dbg("%s - write limit hit\n", __func__);
+ return 0;
+ }
+ portdata->outstanding_urbs++;
+@@ -373,7 +413,7 @@ static int sierra_write(struct usb_serial_port *port,
+
+ memcpy(buffer, buf, count);
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
++ usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
+
+ usb_fill_bulk_urb(urb, serial->dev,
+ usb_sndbulkpipe(serial->dev,
+@@ -384,7 +424,7 @@ static int sierra_write(struct usb_serial_port *port,
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (status) {
+ dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed "
+- "with status = %d\n", __FUNCTION__, status);
++ "with status = %d\n", __func__, status);
+ count = status;
+ goto error;
+ }
+@@ -414,14 +454,14 @@ static void sierra_indat_callback(struct urb *urb)
+ unsigned char *data = urb->transfer_buffer;
+ int status = urb->status;
+
+- dbg("%s: %p", __FUNCTION__, urb);
++ dbg("%s: %p", __func__, urb);
+
+ endpoint = usb_pipeendpoint(urb->pipe);
+- port = (struct usb_serial_port *) urb->context;
++ port = urb->context;
+
+ if (status) {
+ dbg("%s: nonzero status: %d on endpoint %02x.",
+- __FUNCTION__, status, endpoint);
++ __func__, status, endpoint);
+ } else {
+ tty = port->tty;
+ if (urb->actual_length) {
+@@ -429,7 +469,7 @@ static void sierra_indat_callback(struct urb *urb)
+ tty_insert_flip_string(tty, data, urb->actual_length);
+ tty_flip_buffer_push(tty);
+ } else {
+- dbg("%s: empty read urb received", __FUNCTION__);
++ dbg("%s: empty read urb received", __func__);
+ }
+
+ /* Resubmit urb so we continue receiving */
+@@ -447,19 +487,19 @@ static void sierra_instat_callback(struct urb *urb)
+ {
+ int err;
+ int status = urb->status;
+- struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+ struct usb_serial *serial = port->serial;
+
+- dbg("%s", __FUNCTION__);
+- dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata);
++ dbg("%s", __func__);
++ dbg("%s: urb %p port %p has data %p", __func__, urb, port, portdata);
+
+ if (status == 0) {
+ struct usb_ctrlrequest *req_pkt =
+ (struct usb_ctrlrequest *)urb->transfer_buffer;
+
+ if (!req_pkt) {
+- dbg("%s: NULL req_pkt\n", __FUNCTION__);
++ dbg("%s: NULL req_pkt\n", __func__);
+ return;
+ }
+ if ((req_pkt->bRequestType == 0xA1) &&
+@@ -469,7 +509,7 @@ static void sierra_instat_callback(struct urb *urb)
+ urb->transfer_buffer +
+ sizeof(struct usb_ctrlrequest));
+
+- dbg("%s: signal x%x", __FUNCTION__, signals);
++ dbg("%s: signal x%x", __func__, signals);
+
+ old_dcd_state = portdata->dcd_state;
+ portdata->cts_state = 1;
+@@ -481,11 +521,11 @@ static void sierra_instat_callback(struct urb *urb)
+ old_dcd_state && !portdata->dcd_state)
+ tty_hangup(port->tty);
+ } else {
+- dbg("%s: type %x req %x", __FUNCTION__,
+- req_pkt->bRequestType,req_pkt->bRequest);
++ dbg("%s: type %x req %x", __func__,
++ req_pkt->bRequestType, req_pkt->bRequest);
+ }
+ } else
+- dbg("%s: error %d", __FUNCTION__, status);
++ dbg("%s: error %d", __func__, status);
+
+ /* Resubmit urb so we continue receiving IRQ data */
+ if (status != -ESHUTDOWN) {
+@@ -493,7 +533,7 @@ static void sierra_instat_callback(struct urb *urb)
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err)
+ dbg("%s: resubmit intr urb failed. (%d)",
+- __FUNCTION__, err);
++ __func__, err);
+ }
+ }
+
+@@ -502,14 +542,14 @@ static int sierra_write_room(struct usb_serial_port *port)
+ struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /* try to give a good number back based on if we have any free urbs at
+ * this point in time */
+ spin_lock_irqsave(&portdata->lock, flags);
+ if (portdata->outstanding_urbs > N_OUT_URB * 2 / 3) {
+ spin_unlock_irqrestore(&portdata->lock, flags);
+- dbg("%s - write limit hit\n", __FUNCTION__);
++ dbg("%s - write limit hit\n", __func__);
+ return 0;
+ }
+ spin_unlock_irqrestore(&portdata->lock, flags);
+@@ -519,13 +559,15 @@ static int sierra_write_room(struct usb_serial_port *port)
+
+ static int sierra_chars_in_buffer(struct usb_serial_port *port)
+ {
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /*
+ * We can't really account for how much data we
+ * have sent out, but hasn't made it through to the
+ * device as we can't see the backend here, so just
+ * tell the tty layer that everything is flushed.
++ *
++ * FIXME: should walk the outstanding urbs info
+ */
+ return 0;
+ }
+@@ -540,7 +582,7 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
+
+ portdata = usb_get_serial_port_data(port);
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ /* Set some sane defaults */
+ portdata->rts_state = 1;
+@@ -552,7 +594,7 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
+ if (!urb)
+ continue;
+ if (urb->dev != serial->dev) {
+- dbg("%s: dev %p != %p", __FUNCTION__,
++ dbg("%s: dev %p != %p", __func__,
+ urb->dev, serial->dev);
+ continue;
+ }
+@@ -590,7 +632,7 @@ static void sierra_close(struct usb_serial_port *port, struct file *filp)
+ struct usb_serial *serial = port->serial;
+ struct sierra_port_private *portdata;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+ portdata = usb_get_serial_port_data(port);
+
+ portdata->rts_state = 0;
+@@ -620,7 +662,7 @@ static int sierra_startup(struct usb_serial *serial)
+ int i;
+ int j;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ /* Set Device mode to D0 */
+ sierra_set_power_state(serial->dev, 0x0000);
+@@ -635,7 +677,7 @@ static int sierra_startup(struct usb_serial *serial)
+ portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
+ if (!portdata) {
+ dbg("%s: kmalloc for sierra_port_private (%d) failed!.",
+- __FUNCTION__, i);
++ __func__, i);
+ return -ENOMEM;
+ }
+ spin_lock_init(&portdata->lock);
+@@ -656,7 +698,7 @@ static int sierra_startup(struct usb_serial *serial)
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (urb == NULL) {
+ dbg("%s: alloc for in port failed.",
+- __FUNCTION__);
++ __func__);
+ continue;
+ }
+ /* Fill URB using supplied data. */
+@@ -678,7 +720,7 @@ static void sierra_shutdown(struct usb_serial *serial)
+ struct usb_serial_port *port;
+ struct sierra_port_private *portdata;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ for (i = 0; i < serial->num_ports; ++i) {
+ port = serial->port[i];
+@@ -706,9 +748,6 @@ static struct usb_serial_driver sierra_device = {
+ .description = "Sierra USB modem",
+ .id_table = id_table,
+ .usb_driver = &sierra_driver,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_bulk_in = NUM_DONT_CARE,
+- .num_bulk_out = NUM_DONT_CARE,
+ .calc_num_ports = sierra_calc_num_ports,
+ .probe = sierra_probe,
+ .open = sierra_open,
+diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
+new file mode 100644
+index 0000000..2282d62
+--- /dev/null
++++ b/drivers/usb/serial/spcp8x5.c
+@@ -0,0 +1,1072 @@
++/*
++ * spcp8x5 USB to serial adaptor driver
++ *
++ * Copyright (C) 2006 Linxb (xubin.lin at worldplus.com.cn)
++ * Copyright (C) 2006 S1 Corp.
++ *
++ * Original driver for 2.6.10 pl2303 driver by
++ * Greg Kroah-Hartman (greg at kroah.com)
++ * Changes for 2.6.20 by Harald Klein <hari at vt100.at>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ *
++ */
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/tty.h>
++#include <linux/tty_driver.h>
++#include <linux/tty_flip.h>
++#include <linux/module.h>
++#include <linux/spinlock.h>
++#include <linux/usb.h>
++#include <linux/usb/serial.h>
++
++
++/* Version Information */
++#define DRIVER_VERSION "v0.04"
++#define DRIVER_DESC "SPCP8x5 USB to serial adaptor driver"
++
++static int debug;
++
++#define SPCP8x5_007_VID 0x04FC
++#define SPCP8x5_007_PID 0x0201
++#define SPCP8x5_008_VID 0x04fc
++#define SPCP8x5_008_PID 0x0235
++#define SPCP8x5_PHILIPS_VID 0x0471
++#define SPCP8x5_PHILIPS_PID 0x081e
++#define SPCP8x5_INTERMATIC_VID 0x04FC
++#define SPCP8x5_INTERMATIC_PID 0x0204
++#define SPCP8x5_835_VID 0x04fc
++#define SPCP8x5_835_PID 0x0231
++
++static struct usb_device_id id_table [] = {
++ { USB_DEVICE(SPCP8x5_PHILIPS_VID , SPCP8x5_PHILIPS_PID)},
++ { USB_DEVICE(SPCP8x5_INTERMATIC_VID, SPCP8x5_INTERMATIC_PID)},
++ { USB_DEVICE(SPCP8x5_835_VID, SPCP8x5_835_PID)},
++ { USB_DEVICE(SPCP8x5_008_VID, SPCP8x5_008_PID)},
++ { USB_DEVICE(SPCP8x5_007_VID, SPCP8x5_007_PID)},
++ { } /* Terminating entry */
++};
++MODULE_DEVICE_TABLE(usb, id_table);
++
++struct spcp8x5_usb_ctrl_arg {
++ u8 type;
++ u8 cmd;
++ u8 cmd_type;
++ u16 value;
++ u16 index;
++ u16 length;
++};
++
++/* wait 30s before close */
++#define SPCP8x5_CLOSING_WAIT (30*HZ)
++
++#define SPCP8x5_BUF_SIZE 1024
++
++
++/* spcp8x5 spec register define */
++#define MCR_CONTROL_LINE_RTS 0x02
++#define MCR_CONTROL_LINE_DTR 0x01
++#define MCR_DTR 0x01
++#define MCR_RTS 0x02
++
++#define MSR_STATUS_LINE_DCD 0x80
++#define MSR_STATUS_LINE_RI 0x40
++#define MSR_STATUS_LINE_DSR 0x20
++#define MSR_STATUS_LINE_CTS 0x10
++
++/* verdor command here , we should define myself */
++#define SET_DEFAULT 0x40
++#define SET_DEFAULT_TYPE 0x20
++
++#define SET_UART_FORMAT 0x40
++#define SET_UART_FORMAT_TYPE 0x21
++#define SET_UART_FORMAT_SIZE_5 0x00
++#define SET_UART_FORMAT_SIZE_6 0x01
++#define SET_UART_FORMAT_SIZE_7 0x02
++#define SET_UART_FORMAT_SIZE_8 0x03
++#define SET_UART_FORMAT_STOP_1 0x00
++#define SET_UART_FORMAT_STOP_2 0x04
++#define SET_UART_FORMAT_PAR_NONE 0x00
++#define SET_UART_FORMAT_PAR_ODD 0x10
++#define SET_UART_FORMAT_PAR_EVEN 0x30
++#define SET_UART_FORMAT_PAR_MASK 0xD0
++#define SET_UART_FORMAT_PAR_SPACE 0x90
++
++#define GET_UART_STATUS_TYPE 0xc0
++#define GET_UART_STATUS 0x22
++#define GET_UART_STATUS_MSR 0x06
++
++#define SET_UART_STATUS 0x40
++#define SET_UART_STATUS_TYPE 0x23
++#define SET_UART_STATUS_MCR 0x0004
++#define SET_UART_STATUS_MCR_DTR 0x01
++#define SET_UART_STATUS_MCR_RTS 0x02
++#define SET_UART_STATUS_MCR_LOOP 0x10
++
++#define SET_WORKING_MODE 0x40
++#define SET_WORKING_MODE_TYPE 0x24
++#define SET_WORKING_MODE_U2C 0x00
++#define SET_WORKING_MODE_RS485 0x01
++#define SET_WORKING_MODE_PDMA 0x02
++#define SET_WORKING_MODE_SPP 0x03
++
++#define SET_FLOWCTL_CHAR 0x40
++#define SET_FLOWCTL_CHAR_TYPE 0x25
++
++#define GET_VERSION 0xc0
++#define GET_VERSION_TYPE 0x26
++
++#define SET_REGISTER 0x40
++#define SET_REGISTER_TYPE 0x27
++
++#define GET_REGISTER 0xc0
++#define GET_REGISTER_TYPE 0x28
++
++#define SET_RAM 0x40
++#define SET_RAM_TYPE 0x31
++
++#define GET_RAM 0xc0
++#define GET_RAM_TYPE 0x32
++
++/* how come ??? */
++#define UART_STATE 0x08
++#define UART_STATE_TRANSIENT_MASK 0x74
++#define UART_DCD 0x01
++#define UART_DSR 0x02
++#define UART_BREAK_ERROR 0x04
++#define UART_RING 0x08
++#define UART_FRAME_ERROR 0x10
++#define UART_PARITY_ERROR 0x20
++#define UART_OVERRUN_ERROR 0x40
++#define UART_CTS 0x80
++
++enum spcp8x5_type {
++ SPCP825_007_TYPE,
++ SPCP825_008_TYPE,
++ SPCP825_PHILIP_TYPE,
++ SPCP825_INTERMATIC_TYPE,
++ SPCP835_TYPE,
++};
++
++/* 1st in 1st out buffer 4 driver */
++struct ringbuf {
++ unsigned int buf_size;
++ char *buf_buf;
++ char *buf_get;
++ char *buf_put;
++};
++
++/* alloc the ring buf and alloc the buffer itself */
++static inline struct ringbuf *alloc_ringbuf(unsigned int size)
++{
++ struct ringbuf *pb;
++
++ if (size == 0)
++ return NULL;
++
++ pb = kmalloc(sizeof(*pb), GFP_KERNEL);
++ if (pb == NULL)
++ return NULL;
++
++ pb->buf_buf = kmalloc(size, GFP_KERNEL);
++ if (pb->buf_buf == NULL) {
++ kfree(pb);
++ return NULL;
++ }
++
++ pb->buf_size = size;
++ pb->buf_get = pb->buf_put = pb->buf_buf;
++
++ return pb;
++}
++
++/* free the ring buf and the buffer itself */
++static inline void free_ringbuf(struct ringbuf *pb)
++{
++ if (pb != NULL) {
++ kfree(pb->buf_buf);
++ kfree(pb);
++ }
++}
++
++/* clear pipo , juest repoint the pointer here */
++static inline void clear_ringbuf(struct ringbuf *pb)
++{
++ if (pb != NULL)
++ pb->buf_get = pb->buf_put;
++}
++
++/* get the number of data in the pipo */
++static inline unsigned int ringbuf_avail_data(struct ringbuf *pb)
++{
++ if (pb == NULL)
++ return 0;
++ return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
++}
++
++/* get the number of space in the pipo */
++static inline unsigned int ringbuf_avail_space(struct ringbuf *pb)
++{
++ if (pb == NULL)
++ return 0;
++ return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
++}
++
++/* put count data into pipo */
++static unsigned int put_ringbuf(struct ringbuf *pb, const char *buf,
++ unsigned int count)
++{
++ unsigned int len;
++
++ if (pb == NULL)
++ return 0;
++
++ len = ringbuf_avail_space(pb);
++ if (count > len)
++ count = len;
++
++ if (count == 0)
++ return 0;
++
++ len = pb->buf_buf + pb->buf_size - pb->buf_put;
++ if (count > len) {
++ memcpy(pb->buf_put, buf, len);
++ memcpy(pb->buf_buf, buf+len, count - len);
++ pb->buf_put = pb->buf_buf + count - len;
++ } else {
++ memcpy(pb->buf_put, buf, count);
++ if (count < len)
++ pb->buf_put += count;
++ else /* count == len */
++ pb->buf_put = pb->buf_buf;
++ }
++ return count;
++}
++
++/* get count data from pipo */
++static unsigned int get_ringbuf(struct ringbuf *pb, char *buf,
++ unsigned int count)
++{
++ unsigned int len;
++
++ if (pb == NULL || buf == NULL)
++ return 0;
++
++ len = ringbuf_avail_data(pb);
++ if (count > len)
++ count = len;
++
++ if (count == 0)
++ return 0;
++
++ len = pb->buf_buf + pb->buf_size - pb->buf_get;
++ if (count > len) {
++ memcpy(buf, pb->buf_get, len);
++ memcpy(buf+len, pb->buf_buf, count - len);
++ pb->buf_get = pb->buf_buf + count - len;
++ } else {
++ memcpy(buf, pb->buf_get, count);
++ if (count < len)
++ pb->buf_get += count;
++ else /* count == len */
++ pb->buf_get = pb->buf_buf;
++ }
++
++ return count;
++}
++
++static struct usb_driver spcp8x5_driver = {
++ .name = "spcp8x5",
++ .probe = usb_serial_probe,
++ .disconnect = usb_serial_disconnect,
++ .id_table = id_table,
++ .no_dynamic_id = 1,
++};
++
++
++struct spcp8x5_private {
++ spinlock_t lock;
++ struct ringbuf *buf;
++ int write_urb_in_use;
++ enum spcp8x5_type type;
++ wait_queue_head_t delta_msr_wait;
++ u8 line_control;
++ u8 line_status;
++ u8 termios_initialized;
++};
++
++/* desc : when device plug in,this function would be called.
++ * thanks to usb_serial subsystem,then do almost every things for us. And what
++ * we should do just alloc the buffer */
++static int spcp8x5_startup(struct usb_serial *serial)
++{
++ struct spcp8x5_private *priv;
++ int i;
++ enum spcp8x5_type type = SPCP825_007_TYPE;
++
++ if (serial->dev->descriptor.idProduct == 0x0201)
++ type = SPCP825_007_TYPE;
++ else if (serial->dev->descriptor.idProduct == 0x0231)
++ type = SPCP835_TYPE;
++ else if (serial->dev->descriptor.idProduct == 0x0235)
++ type = SPCP825_008_TYPE;
++ else if (serial->dev->descriptor.idProduct == 0x0204)
++ type = SPCP825_INTERMATIC_TYPE;
++ else if (serial->dev->descriptor.idProduct == 0x0471 &&
++ serial->dev->descriptor.idVendor == 0x081e)
++ type = SPCP825_PHILIP_TYPE;
++ dev_dbg(&serial->dev->dev, "device type = %d\n", (int)type);
++
++ for (i = 0; i < serial->num_ports; ++i) {
++ priv = kzalloc(sizeof(struct spcp8x5_private), GFP_KERNEL);
++ if (!priv)
++ goto cleanup;
++
++ spin_lock_init(&priv->lock);
++ priv->buf = alloc_ringbuf(SPCP8x5_BUF_SIZE);
++ if (priv->buf == NULL)
++ goto cleanup2;
++
++ init_waitqueue_head(&priv->delta_msr_wait);
++ priv->type = type;
++ usb_set_serial_port_data(serial->port[i] , priv);
++
++ }
++
++ return 0;
++
++cleanup2:
++ kfree(priv);
++cleanup:
++ for (--i; i >= 0; --i) {
++ priv = usb_get_serial_port_data(serial->port[i]);
++ free_ringbuf(priv->buf);
++ kfree(priv);
++ usb_set_serial_port_data(serial->port[i] , NULL);
++ }
++ return -ENOMEM;
++}
++
++/* call when the device plug out. free all the memory alloced by probe */
++static void spcp8x5_shutdown(struct usb_serial *serial)
++{
++ int i;
++ struct spcp8x5_private *priv;
++
++ for (i = 0; i < serial->num_ports; i++) {
++ priv = usb_get_serial_port_data(serial->port[i]);
++ if (priv) {
++ free_ringbuf(priv->buf);
++ kfree(priv);
++ usb_set_serial_port_data(serial->port[i] , NULL);
++ }
++ }
++}
++
++/* set the modem control line of the device.
++ * NOTE spcp825-007 not supported this */
++static int spcp8x5_set_ctrlLine(struct usb_device *dev, u8 value,
++ enum spcp8x5_type type)
++{
++ int retval;
++ u8 mcr = 0 ;
++
++ if (type == SPCP825_007_TYPE)
++ return -EPERM;
++
++ mcr = (unsigned short)value;
++ retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
++ SET_UART_STATUS_TYPE, SET_UART_STATUS,
++ mcr, 0x04, NULL, 0, 100);
++ if (retval != 0)
++ dev_dbg(&dev->dev, "usb_control_msg return %#x\n", retval);
++ return retval;
++}
++
++/* get the modem status register of the device
++ * NOTE spcp825-007 not supported this */
++static int spcp8x5_get_msr(struct usb_device *dev, u8 *status,
++ enum spcp8x5_type type)
++{
++ u8 *status_buffer;
++ int ret;
++
++ /* I return Permited not support here but seem inval device
++ * is more fix */
++ if (type == SPCP825_007_TYPE)
++ return -EPERM;
++ if (status == NULL)
++ return -EINVAL;
++
++ status_buffer = kmalloc(1, GFP_KERNEL);
++ if (!status_buffer)
++ return -ENOMEM;
++ status_buffer[0] = status[0];
++
++ ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
++ GET_UART_STATUS, GET_UART_STATUS_TYPE,
++ 0, GET_UART_STATUS_MSR, status_buffer, 1, 100);
++ if (ret < 0)
++ dev_dbg(&dev->dev, "Get MSR = 0x%p failed (error = %d)",
++ status_buffer, ret);
++
++ dev_dbg(&dev->dev, "0xc0:0x22:0:6 %d - 0x%p ", ret, status_buffer);
++ status[0] = status_buffer[0];
++ kfree(status_buffer);
++
++ return ret;
++}
++
++/* select the work mode.
++ * NOTE this function not supported by spcp825-007 */
++static void spcp8x5_set_workMode(struct usb_device *dev, u16 value,
++ u16 index, enum spcp8x5_type type)
++{
++ int ret;
++
++ /* I return Permited not support here but seem inval device
++ * is more fix */
++ if (type == SPCP825_007_TYPE)
++ return;
++
++ ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
++ SET_WORKING_MODE_TYPE, SET_WORKING_MODE,
++ value, index, NULL, 0, 100);
++ dev_dbg(&dev->dev, "value = %#x , index = %#x\n", value, index);
++ if (ret < 0)
++ dev_dbg(&dev->dev,
++ "RTSCTS usb_control_msg(enable flowctrl) = %d\n", ret);
++}
++
++/* close the serial port. We should wait for data sending to device 1st and
++ * then kill all urb. */
++static void spcp8x5_close(struct usb_serial_port *port, struct file *filp)
++{
++ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++ unsigned long flags;
++ unsigned int c_cflag;
++ int bps;
++ long timeout;
++ wait_queue_t wait;
++ int result;
++
++ dbg("%s - port %d", __func__, port->number);
++
++ /* wait for data to drain from the buffer */
++ spin_lock_irqsave(&priv->lock, flags);
++ timeout = SPCP8x5_CLOSING_WAIT;
++ init_waitqueue_entry(&wait, current);
++ add_wait_queue(&port->tty->write_wait, &wait);
++ for (;;) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ if (ringbuf_avail_data(priv->buf) == 0 ||
++ timeout == 0 || signal_pending(current))
++ break;
++ spin_unlock_irqrestore(&priv->lock, flags);
++ timeout = schedule_timeout(timeout);
++ spin_lock_irqsave(&priv->lock, flags);
++ }
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&port->tty->write_wait, &wait);
++
++ /* clear out any remaining data in the buffer */
++ clear_ringbuf(priv->buf);
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ /* wait for characters to drain from the device (this is long enough
++ * for the entire all byte spcp8x5 hardware buffer to drain with no
++ * flow control for data rates of 1200 bps or more, for lower rates we
++ * should really know how much data is in the buffer to compute a delay
++ * that is not unnecessarily long) */
++ bps = tty_get_baud_rate(port->tty);
++ if (bps > 1200)
++ timeout = max((HZ*2560) / bps, HZ/10);
++ else
++ timeout = 2*HZ;
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule_timeout(timeout);
++
++ /* clear control lines */
++ if (port->tty) {
++ c_cflag = port->tty->termios->c_cflag;
++ if (c_cflag & HUPCL) {
++ spin_lock_irqsave(&priv->lock, flags);
++ priv->line_control = 0;
++ spin_unlock_irqrestore(&priv->lock, flags);
++ spcp8x5_set_ctrlLine(port->serial->dev, 0 , priv->type);
++ }
++ }
++
++ /* kill urb */
++ if (port->write_urb != NULL) {
++ result = usb_unlink_urb(port->write_urb);
++ if (result)
++ dev_dbg(&port->dev,
++ "usb_unlink_urb(write_urb) = %d\n", result);
++ }
++ result = usb_unlink_urb(port->read_urb);
++ if (result)
++ dev_dbg(&port->dev, "usb_unlink_urb(read_urb) = %d\n", result);
++}
++
++/* set the serial param for transfer. we should check if we really need to
++ * transfer. then if be set flow contorl we should do this too. */
++static void spcp8x5_set_termios(struct usb_serial_port *port,
++ struct ktermios *old_termios)
++{
++ struct usb_serial *serial = port->serial;
++ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++ unsigned long flags;
++ unsigned int cflag = port->tty->termios->c_cflag;
++ unsigned int old_cflag = old_termios->c_cflag;
++ unsigned short uartdata;
++ unsigned char buf[2] = {0, 0};
++ int baud;
++ int i;
++ u8 control;
++
++ if ((!port->tty) || (!port->tty->termios))
++ return;
++
++ /* for the 1st time call this function */
++ spin_lock_irqsave(&priv->lock, flags);
++ if (!priv->termios_initialized) {
++ *(port->tty->termios) = tty_std_termios;
++ port->tty->termios->c_cflag = B115200 | CS8 | CREAD |
++ HUPCL | CLOCAL;
++ priv->termios_initialized = 1;
++ }
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ /* check that they really want us to change something */
++ if (!tty_termios_hw_change(port->tty->termios, old_termios))
++ return;
++
++ /* set DTR/RTS active */
++ spin_lock_irqsave(&priv->lock, flags);
++ control = priv->line_control;
++ if ((old_cflag & CBAUD) == B0) {
++ priv->line_control |= MCR_DTR;
++ if (!(old_cflag & CRTSCTS))
++ priv->line_control |= MCR_RTS;
++ }
++ if (control != priv->line_control) {
++ control = priv->line_control;
++ spin_unlock_irqrestore(&priv->lock, flags);
++ spcp8x5_set_ctrlLine(serial->dev, control , priv->type);
++ } else {
++ spin_unlock_irqrestore(&priv->lock, flags);
++ }
++
++ /* Set Baud Rate */
++ baud = tty_get_baud_rate(port->tty);;
++ switch (baud) {
++ case 300: buf[0] = 0x00; break;
++ case 600: buf[0] = 0x01; break;
++ case 1200: buf[0] = 0x02; break;
++ case 2400: buf[0] = 0x03; break;
++ case 4800: buf[0] = 0x04; break;
++ case 9600: buf[0] = 0x05; break;
++ case 19200: buf[0] = 0x07; break;
++ case 38400: buf[0] = 0x09; break;
++ case 57600: buf[0] = 0x0a; break;
++ case 115200: buf[0] = 0x0b; break;
++ case 230400: buf[0] = 0x0c; break;
++ case 460800: buf[0] = 0x0d; break;
++ case 921600: buf[0] = 0x0e; break;
++/* case 1200000: buf[0] = 0x0f; break; */
++/* case 2400000: buf[0] = 0x10; break; */
++ case 3000000: buf[0] = 0x11; break;
++/* case 6000000: buf[0] = 0x12; break; */
++ case 0:
++ case 1000000:
++ buf[0] = 0x0b; break;
++ default:
++ err("spcp825 driver does not support the baudrate "
++ "requested, using default of 9600.");
++ }
++
++ /* Set Data Length : 00:5bit, 01:6bit, 10:7bit, 11:8bit */
++ if (cflag & CSIZE) {
++ switch (cflag & CSIZE) {
++ case CS5:
++ buf[1] |= SET_UART_FORMAT_SIZE_5;
++ break;
++ case CS6:
++ buf[1] |= SET_UART_FORMAT_SIZE_6;
++ break;
++ case CS7:
++ buf[1] |= SET_UART_FORMAT_SIZE_7;
++ break;
++ default:
++ case CS8:
++ buf[1] |= SET_UART_FORMAT_SIZE_8;
++ break;
++ }
++ }
++
++ /* Set Stop bit2 : 0:1bit 1:2bit */
++ buf[1] |= (cflag & CSTOPB) ? SET_UART_FORMAT_STOP_2 :
++ SET_UART_FORMAT_STOP_1;
++
++ /* Set Parity bit3-4 01:Odd 11:Even */
++ if (cflag & PARENB) {
++ buf[1] |= (cflag & PARODD) ?
++ SET_UART_FORMAT_PAR_ODD : SET_UART_FORMAT_PAR_EVEN ;
++ } else
++ buf[1] |= SET_UART_FORMAT_PAR_NONE;
++
++ uartdata = buf[0] | buf[1]<<8;
++
++ i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
++ SET_UART_FORMAT_TYPE, SET_UART_FORMAT,
++ uartdata, 0, NULL, 0, 100);
++ if (i < 0)
++ err("Set UART format %#x failed (error = %d)", uartdata, i);
++ dbg("0x21:0x40:0:0 %d\n", i);
++
++ if (cflag & CRTSCTS) {
++ /* enable hardware flow control */
++ spcp8x5_set_workMode(serial->dev, 0x000a,
++ SET_WORKING_MODE_U2C, priv->type);
++ }
++ return;
++}
++
++/* open the serial port. do some usb system call. set termios and get the line
++ * status of the device. then submit the read urb */
++static int spcp8x5_open(struct usb_serial_port *port, struct file *filp)
++{
++ struct ktermios tmp_termios;
++ struct usb_serial *serial = port->serial;
++ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++ int ret;
++ unsigned long flags;
++ u8 status = 0x30;
++ /* status 0x30 means DSR and CTS = 1 other CDC RI and delta = 0 */
++
++ dbg("%s - port %d", __func__, port->number);
++
++ usb_clear_halt(serial->dev, port->write_urb->pipe);
++ usb_clear_halt(serial->dev, port->read_urb->pipe);
++
++ ret = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
++ 0x09, 0x00,
++ 0x01, 0x00, NULL, 0x00, 100);
++ if (ret)
++ return ret;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ if (port->tty->termios->c_cflag & CBAUD)
++ priv->line_control = MCR_DTR | MCR_RTS;
++ else
++ priv->line_control = 0;
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type);
++
++ /* Setup termios */
++ if (port->tty)
++ spcp8x5_set_termios(port, &tmp_termios);
++
++ spcp8x5_get_msr(serial->dev, &status, priv->type);
++
++ /* may be we should update uart status here but now we did not do */
++ spin_lock_irqsave(&priv->lock, flags);
++ priv->line_status = status & 0xf0 ;
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ /* FIXME: need to assert RTS and DTR if CRTSCTS off */
++
++ dbg("%s - submitting read urb", __func__);
++ port->read_urb->dev = serial->dev;
++ ret = usb_submit_urb(port->read_urb, GFP_KERNEL);
++ if (ret) {
++ spcp8x5_close(port, NULL);
++ return -EPROTO;
++ }
++ return 0;
++}
++
++/* bulk read call back function. check the status of the urb. if transfer
++ * failed return. then update the status and the tty send data to tty subsys.
++ * submit urb again.
++ */
++static void spcp8x5_read_bulk_callback(struct urb *urb)
++{
++ struct usb_serial_port *port = urb->context;
++ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++ struct tty_struct *tty;
++ unsigned char *data = urb->transfer_buffer;
++ unsigned long flags;
++ int i;
++ int result;
++ u8 status = 0;
++ char tty_flag;
++
++ dev_dbg(&port->dev, "start, urb->status = %d, "
++ "urb->actual_length = %d\n,", urb->status, urb->actual_length);
++
++ /* check the urb status */
++ if (urb->status) {
++ if (!port->open_count)
++ return;
++ if (urb->status == -EPROTO) {
++ /* spcp8x5 mysteriously fails with -EPROTO */
++ /* reschedule the read */
++ urb->status = 0;
++ urb->dev = port->serial->dev;
++ result = usb_submit_urb(urb , GFP_ATOMIC);
++ if (result)
++ dev_dbg(&port->dev,
++ "failed submitting read urb %d\n",
++ result);
++ return;
++ }
++ dev_dbg(&port->dev, "unable to handle the error, exiting.\n");
++ return;
++ }
++
++ /* get tty_flag from status */
++ tty_flag = TTY_NORMAL;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ status = priv->line_status;
++ priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
++ spin_unlock_irqrestore(&priv->lock, flags);
++ /* wake up the wait for termios */
++ wake_up_interruptible(&priv->delta_msr_wait);
++
++ /* break takes precedence over parity, which takes precedence over
++ * framing errors */
++ if (status & UART_BREAK_ERROR)
++ tty_flag = TTY_BREAK;
++ else if (status & UART_PARITY_ERROR)
++ tty_flag = TTY_PARITY;
++ else if (status & UART_FRAME_ERROR)
++ tty_flag = TTY_FRAME;
++ dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag);
++
++ tty = port->tty;
++ if (tty && urb->actual_length) {
++ tty_buffer_request_room(tty, urb->actual_length + 1);
++ /* overrun is special, not associated with a char */
++ if (status & UART_OVERRUN_ERROR)
++ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
++ for (i = 0; i < urb->actual_length; ++i)
++ tty_insert_flip_char(tty, data[i], tty_flag);
++ tty_flip_buffer_push(tty);
++ }
++
++ /* Schedule the next read _if_ we are still open */
++ if (port->open_count) {
++ urb->dev = port->serial->dev;
++ result = usb_submit_urb(urb , GFP_ATOMIC);
++ if (result)
++ dev_dbg(&port->dev, "failed submitting read urb %d\n",
++ result);
++ }
++
++ return;
++}
++
++/* get data from ring buffer and then write to usb bus */
++static void spcp8x5_send(struct usb_serial_port *port)
++{
++ int count, result;
++ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++ unsigned long flags;
++
++ spin_lock_irqsave(&priv->lock, flags);
++
++ if (priv->write_urb_in_use) {
++ dev_dbg(&port->dev, "write urb still used\n");
++ spin_unlock_irqrestore(&priv->lock, flags);
++ return;
++ }
++
++ /* send the 1st urb for writting */
++ memset(port->write_urb->transfer_buffer , 0x00 , port->bulk_out_size);
++ count = get_ringbuf(priv->buf, port->write_urb->transfer_buffer,
++ port->bulk_out_size);
++
++ if (count == 0) {
++ spin_unlock_irqrestore(&priv->lock, flags);
++ return;
++ }
++
++ /* update the urb status */
++ priv->write_urb_in_use = 1;
++
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ port->write_urb->transfer_buffer_length = count;
++ port->write_urb->dev = port->serial->dev;
++
++ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
++ if (result) {
++ dev_dbg(&port->dev, "failed submitting write urb, error %d\n",
++ result);
++ priv->write_urb_in_use = 0;
++ /* TODO: reschedule spcp8x5_send */
++ }
++
++
++ schedule_work(&port->work);
++}
++
++/* this is the call back function for write urb. NOTE we should not sleep in
++ * this routine. check the urb return code and then submit the write urb again
++ * to hold the write loop */
++static void spcp8x5_write_bulk_callback(struct urb *urb)
++{
++ struct usb_serial_port *port = urb->context;
++ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++ int result;
++
++ switch (urb->status) {
++ case 0:
++ /* success */
++ break;
++ case -ECONNRESET:
++ case -ENOENT:
++ case -ESHUTDOWN:
++ /* this urb is terminated, clean up */
++ dev_dbg(&port->dev, "urb shutting down with status: %d\n",
++ urb->status);
++ priv->write_urb_in_use = 0;
++ return;
++ default:
++ /* error in the urb, so we have to resubmit it */
++ dbg("%s - Overflow in write", __func__);
++ dbg("%s - nonzero write bulk status received: %d",
++ __func__, urb->status);
++ port->write_urb->transfer_buffer_length = 1;
++ port->write_urb->dev = port->serial->dev;
++ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
++ if (result)
++ dev_dbg(&port->dev,
++ "failed resubmitting write urb %d\n", result);
++ else
++ return;
++ }
++
++ priv->write_urb_in_use = 0;
++
++ /* send any buffered data */
++ spcp8x5_send(port);
++}
++
++/* write data to ring buffer. and then start the write transfer */
++static int spcp8x5_write(struct usb_serial_port *port,
++ const unsigned char *buf, int count)
++{
++ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++ unsigned long flags;
++
++ dev_dbg(&port->dev, "%d bytes\n", count);
++
++ if (!count)
++ return count;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ count = put_ringbuf(priv->buf, buf, count);
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ spcp8x5_send(port);
++
++ return count;
++}
++
++static int spcp8x5_wait_modem_info(struct usb_serial_port *port,
++ unsigned int arg)
++{
++ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++ unsigned long flags;
++ unsigned int prevstatus;
++ unsigned int status;
++ unsigned int changed;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ prevstatus = priv->line_status;
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ while (1) {
++ /* wake up in bulk read */
++ interruptible_sleep_on(&priv->delta_msr_wait);
++
++ /* see if a signal did it */
++ if (signal_pending(current))
++ return -ERESTARTSYS;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ status = priv->line_status;
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ changed = prevstatus^status;
++
++ if (((arg & TIOCM_RNG) && (changed & MSR_STATUS_LINE_RI)) ||
++ ((arg & TIOCM_DSR) && (changed & MSR_STATUS_LINE_DSR)) ||
++ ((arg & TIOCM_CD) && (changed & MSR_STATUS_LINE_DCD)) ||
++ ((arg & TIOCM_CTS) && (changed & MSR_STATUS_LINE_CTS)))
++ return 0;
++
++ prevstatus = status;
++ }
++ /* NOTREACHED */
++ return 0;
++}
++
++static int spcp8x5_ioctl(struct usb_serial_port *port, struct file *file,
++ unsigned int cmd, unsigned long arg)
++{
++ dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
++
++ switch (cmd) {
++ case TIOCMIWAIT:
++ dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
++ return spcp8x5_wait_modem_info(port, arg);
++
++ default:
++ dbg("%s not supported = 0x%04x", __func__, cmd);
++ break;
++ }
++
++ return -ENOIOCTLCMD;
++}
++
++static int spcp8x5_tiocmset(struct usb_serial_port *port, struct file *file,
++ unsigned int set, unsigned int clear)
++{
++ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++ unsigned long flags;
++ u8 control;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ if (set & TIOCM_RTS)
++ priv->line_control |= MCR_RTS;
++ if (set & TIOCM_DTR)
++ priv->line_control |= MCR_DTR;
++ if (clear & TIOCM_RTS)
++ priv->line_control &= ~MCR_RTS;
++ if (clear & TIOCM_DTR)
++ priv->line_control &= ~MCR_DTR;
++ control = priv->line_control;
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ return spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type);
++}
++
++static int spcp8x5_tiocmget(struct usb_serial_port *port, struct file *file)
++{
++ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++ unsigned long flags;
++ unsigned int mcr;
++ unsigned int status;
++ unsigned int result;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ mcr = priv->line_control;
++ status = priv->line_status;
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0)
++ | ((mcr & MCR_RTS) ? TIOCM_RTS : 0)
++ | ((status & MSR_STATUS_LINE_CTS) ? TIOCM_CTS : 0)
++ | ((status & MSR_STATUS_LINE_DSR) ? TIOCM_DSR : 0)
++ | ((status & MSR_STATUS_LINE_RI) ? TIOCM_RI : 0)
++ | ((status & MSR_STATUS_LINE_DCD) ? TIOCM_CD : 0);
++
++ return result;
++}
++
++/* get the avail space room in ring buffer */
++static int spcp8x5_write_room(struct usb_serial_port *port)
++{
++ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++ int room = 0;
++ unsigned long flags;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ room = ringbuf_avail_space(priv->buf);
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ return room;
++}
++
++/* get the number of avail data in write ring buffer */
++static int spcp8x5_chars_in_buffer(struct usb_serial_port *port)
++{
++ struct spcp8x5_private *priv = usb_get_serial_port_data(port);
++ int chars = 0;
++ unsigned long flags;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ chars = ringbuf_avail_data(priv->buf);
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ return chars;
++}
++
++/* All of the device info needed for the spcp8x5 SIO serial converter */
++static struct usb_serial_driver spcp8x5_device = {
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "SPCP8x5",
++ },
++ .id_table = id_table,
++ .num_ports = 1,
++ .open = spcp8x5_open,
++ .close = spcp8x5_close,
++ .write = spcp8x5_write,
++ .set_termios = spcp8x5_set_termios,
++ .ioctl = spcp8x5_ioctl,
++ .tiocmget = spcp8x5_tiocmget,
++ .tiocmset = spcp8x5_tiocmset,
++ .write_room = spcp8x5_write_room,
++ .read_bulk_callback = spcp8x5_read_bulk_callback,
++ .write_bulk_callback = spcp8x5_write_bulk_callback,
++ .chars_in_buffer = spcp8x5_chars_in_buffer,
++ .attach = spcp8x5_startup,
++ .shutdown = spcp8x5_shutdown,
++};
++
++static int __init spcp8x5_init(void)
++{
++ int retval;
++ retval = usb_serial_register(&spcp8x5_device);
++ if (retval)
++ goto failed_usb_serial_register;
++ retval = usb_register(&spcp8x5_driver);
++ if (retval)
++ goto failed_usb_register;
++ info(DRIVER_DESC " " DRIVER_VERSION);
++ return 0;
++failed_usb_register:
++ usb_serial_deregister(&spcp8x5_device);
++failed_usb_serial_register:
++ return retval;
++}
++
++static void __exit spcp8x5_exit(void)
++{
++ usb_deregister(&spcp8x5_driver);
++ usb_serial_deregister(&spcp8x5_device);
++}
++
++module_init(spcp8x5_init);
++module_exit(spcp8x5_exit);
++
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_VERSION(DRIVER_VERSION);
++MODULE_LICENSE("GPL");
++
++module_param(debug, bool, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(debug, "Debug enabled or not");
+diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
+index e3d241f..a1c8aef 100644
+--- a/drivers/usb/serial/ti_usb_3410_5052.c
++++ b/drivers/usb/serial/ti_usb_3410_5052.c
+@@ -82,7 +82,6 @@
+ #include <linux/circ_buf.h>
+ #include <linux/mutex.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #include <linux/usb.h>
+ #include <linux/usb/serial.h>
+
+@@ -265,9 +264,6 @@ static struct usb_serial_driver ti_1port_device = {
+ .description = "TI USB 3410 1 port adapter",
+ .usb_driver = &ti_usb_driver,
+ .id_table = ti_id_table_3410,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_bulk_in = NUM_DONT_CARE,
+- .num_bulk_out = 1,
+ .num_ports = 1,
+ .attach = ti_startup,
+ .shutdown = ti_shutdown,
+@@ -296,9 +292,6 @@ static struct usb_serial_driver ti_2port_device = {
+ .description = "TI USB 5052 2 port adapter",
+ .usb_driver = &ti_usb_driver,
+ .id_table = ti_id_table_5052,
+- .num_interrupt_in = 1,
+- .num_bulk_in = 2,
+- .num_bulk_out = 2,
+ .num_ports = 2,
+ .attach = ti_startup,
+ .shutdown = ti_shutdown,
+@@ -415,14 +408,14 @@ static int ti_startup(struct usb_serial *serial)
+
+
+ dbg("%s - product 0x%4X, num configurations %d, configuration value %d",
+- __FUNCTION__, le16_to_cpu(dev->descriptor.idProduct),
++ __func__, le16_to_cpu(dev->descriptor.idProduct),
+ dev->descriptor.bNumConfigurations,
+ dev->actconfig->desc.bConfigurationValue);
+
+ /* create device structure */
+ tdev = kzalloc(sizeof(struct ti_device), GFP_KERNEL);
+ if (tdev == NULL) {
+- dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
++ dev_err(&dev->dev, "%s - out of memory\n", __func__);
+ return -ENOMEM;
+ }
+ mutex_init(&tdev->td_open_close_lock);
+@@ -432,7 +425,7 @@ static int ti_startup(struct usb_serial *serial)
+ /* determine device type */
+ if (usb_match_id(serial->interface, ti_id_table_3410))
+ tdev->td_is_3410 = 1;
+- dbg("%s - device type is %s", __FUNCTION__, tdev->td_is_3410 ? "3410" : "5052");
++ dbg("%s - device type is %s", __func__, tdev->td_is_3410 ? "3410" : "5052");
+
+ /* if we have only 1 configuration, download firmware */
+ if (dev->descriptor.bNumConfigurations == 1) {
+@@ -466,7 +459,7 @@ static int ti_startup(struct usb_serial *serial)
+ for (i = 0; i < serial->num_ports; ++i) {
+ tport = kzalloc(sizeof(struct ti_port), GFP_KERNEL);
+ if (tport == NULL) {
+- dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
++ dev_err(&dev->dev, "%s - out of memory\n", __func__);
+ status = -ENOMEM;
+ goto free_tports;
+ }
+@@ -478,7 +471,7 @@ static int ti_startup(struct usb_serial *serial)
+ init_waitqueue_head(&tport->tp_write_wait);
+ tport->tp_write_buf = ti_buf_alloc();
+ if (tport->tp_write_buf == NULL) {
+- dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
++ dev_err(&dev->dev, "%s - out of memory\n", __func__);
+ kfree(tport);
+ status = -ENOMEM;
+ goto free_tports;
+@@ -511,7 +504,7 @@ static void ti_shutdown(struct usb_serial *serial)
+ struct ti_device *tdev = usb_get_serial_data(serial);
+ struct ti_port *tport;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ for (i=0; i < serial->num_ports; ++i) {
+ tport = usb_get_serial_port_data(serial->port[i]);
+@@ -539,7 +532,7 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
+ TI_PIPE_TIMEOUT_ENABLE |
+ (TI_TRANSFER_TIMEOUT << 2));
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (tport == NULL)
+ return -ENODEV;
+@@ -564,10 +557,10 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
+
+ /* start interrupt urb the first time a port is opened on this device */
+ if (tdev->td_open_port_count == 0) {
+- dbg("%s - start interrupt in urb", __FUNCTION__);
++ dbg("%s - start interrupt in urb", __func__);
+ urb = tdev->td_serial->port[0]->interrupt_in_urb;
+ if (!urb) {
+- dev_err(&port->dev, "%s - no interrupt urb\n", __FUNCTION__);
++ dev_err(&port->dev, "%s - no interrupt urb\n", __func__);
+ status = -EINVAL;
+ goto release_lock;
+ }
+@@ -576,40 +569,40 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
+ urb->dev = dev;
+ status = usb_submit_urb(urb, GFP_KERNEL);
+ if (status) {
+- dev_err(&port->dev, "%s - submit interrupt urb failed, %d\n", __FUNCTION__, status);
++ dev_err(&port->dev, "%s - submit interrupt urb failed, %d\n", __func__, status);
+ goto release_lock;
+ }
+ }
+
+ ti_set_termios(port, port->tty->termios);
+
+- dbg("%s - sending TI_OPEN_PORT", __FUNCTION__);
++ dbg("%s - sending TI_OPEN_PORT", __func__);
+ status = ti_command_out_sync(tdev, TI_OPEN_PORT,
+ (__u8)(TI_UART1_PORT + port_number), open_settings, NULL, 0);
+ if (status) {
+- dev_err(&port->dev, "%s - cannot send open command, %d\n", __FUNCTION__, status);
++ dev_err(&port->dev, "%s - cannot send open command, %d\n", __func__, status);
+ goto unlink_int_urb;
+ }
+
+- dbg("%s - sending TI_START_PORT", __FUNCTION__);
++ dbg("%s - sending TI_START_PORT", __func__);
+ status = ti_command_out_sync(tdev, TI_START_PORT,
+ (__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
+ if (status) {
+- dev_err(&port->dev, "%s - cannot send start command, %d\n", __FUNCTION__, status);
++ dev_err(&port->dev, "%s - cannot send start command, %d\n", __func__, status);
+ goto unlink_int_urb;
+ }
+
+- dbg("%s - sending TI_PURGE_PORT", __FUNCTION__);
++ dbg("%s - sending TI_PURGE_PORT", __func__);
+ status = ti_command_out_sync(tdev, TI_PURGE_PORT,
+ (__u8)(TI_UART1_PORT + port_number), TI_PURGE_INPUT, NULL, 0);
+ if (status) {
+- dev_err(&port->dev, "%s - cannot clear input buffers, %d\n", __FUNCTION__, status);
++ dev_err(&port->dev, "%s - cannot clear input buffers, %d\n", __func__, status);
+ goto unlink_int_urb;
+ }
+ status = ti_command_out_sync(tdev, TI_PURGE_PORT,
+ (__u8)(TI_UART1_PORT + port_number), TI_PURGE_OUTPUT, NULL, 0);
+ if (status) {
+- dev_err(&port->dev, "%s - cannot clear output buffers, %d\n", __FUNCTION__, status);
++ dev_err(&port->dev, "%s - cannot clear output buffers, %d\n", __func__, status);
+ goto unlink_int_urb;
+ }
+
+@@ -620,27 +613,27 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
+
+ ti_set_termios(port, port->tty->termios);
+
+- dbg("%s - sending TI_OPEN_PORT (2)", __FUNCTION__);
++ dbg("%s - sending TI_OPEN_PORT (2)", __func__);
+ status = ti_command_out_sync(tdev, TI_OPEN_PORT,
+ (__u8)(TI_UART1_PORT + port_number), open_settings, NULL, 0);
+ if (status) {
+- dev_err(&port->dev, "%s - cannot send open command (2), %d\n", __FUNCTION__, status);
++ dev_err(&port->dev, "%s - cannot send open command (2), %d\n", __func__, status);
+ goto unlink_int_urb;
+ }
+
+- dbg("%s - sending TI_START_PORT (2)", __FUNCTION__);
++ dbg("%s - sending TI_START_PORT (2)", __func__);
+ status = ti_command_out_sync(tdev, TI_START_PORT,
+ (__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
+ if (status) {
+- dev_err(&port->dev, "%s - cannot send start command (2), %d\n", __FUNCTION__, status);
++ dev_err(&port->dev, "%s - cannot send start command (2), %d\n", __func__, status);
+ goto unlink_int_urb;
+ }
+
+ /* start read urb */
+- dbg("%s - start read urb", __FUNCTION__);
++ dbg("%s - start read urb", __func__);
+ urb = port->read_urb;
+ if (!urb) {
+- dev_err(&port->dev, "%s - no read urb\n", __FUNCTION__);
++ dev_err(&port->dev, "%s - no read urb\n", __func__);
+ status = -EINVAL;
+ goto unlink_int_urb;
+ }
+@@ -650,7 +643,7 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
+ urb->dev = dev;
+ status = usb_submit_urb(urb, GFP_KERNEL);
+ if (status) {
+- dev_err(&port->dev, "%s - submit read urb failed, %d\n", __FUNCTION__, status);
++ dev_err(&port->dev, "%s - submit read urb failed, %d\n", __func__, status);
+ goto unlink_int_urb;
+ }
+
+@@ -664,7 +657,7 @@ unlink_int_urb:
+ usb_kill_urb(port->serial->port[0]->interrupt_in_urb);
+ release_lock:
+ mutex_unlock(&tdev->td_open_close_lock);
+- dbg("%s - exit %d", __FUNCTION__, status);
++ dbg("%s - exit %d", __func__, status);
+ return status;
+ }
+
+@@ -677,7 +670,7 @@ static void ti_close(struct usb_serial_port *port, struct file *file)
+ int status;
+ int do_unlock;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ tdev = usb_get_serial_data(port->serial);
+ tport = usb_get_serial_port_data(port);
+@@ -694,11 +687,11 @@ static void ti_close(struct usb_serial_port *port, struct file *file)
+
+ port_number = port->number - port->serial->minor;
+
+- dbg("%s - sending TI_CLOSE_PORT", __FUNCTION__);
++ dbg("%s - sending TI_CLOSE_PORT", __func__);
+ status = ti_command_out_sync(tdev, TI_CLOSE_PORT,
+ (__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
+ if (status)
+- dev_err(&port->dev, "%s - cannot send close port command, %d\n" , __FUNCTION__, status);
++ dev_err(&port->dev, "%s - cannot send close port command, %d\n" , __func__, status);
+
+ /* if mutex_lock is interrupted, continue anyway */
+ do_unlock = !mutex_lock_interruptible(&tdev->td_open_close_lock);
+@@ -711,7 +704,7 @@ static void ti_close(struct usb_serial_port *port, struct file *file)
+ if (do_unlock)
+ mutex_unlock(&tdev->td_open_close_lock);
+
+- dbg("%s - exit", __FUNCTION__);
++ dbg("%s - exit", __func__);
+ }
+
+
+@@ -721,10 +714,10 @@ static int ti_write(struct usb_serial_port *port, const unsigned char *data,
+ struct ti_port *tport = usb_get_serial_port_data(port);
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (count == 0) {
+- dbg("%s - write request of 0 bytes", __FUNCTION__);
++ dbg("%s - write request of 0 bytes", __func__);
+ return 0;
+ }
+
+@@ -747,7 +740,7 @@ static int ti_write_room(struct usb_serial_port *port)
+ int room = 0;
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (tport == NULL)
+ return -ENODEV;
+@@ -756,7 +749,7 @@ static int ti_write_room(struct usb_serial_port *port)
+ room = ti_buf_space_avail(tport->tp_write_buf);
+ spin_unlock_irqrestore(&tport->tp_lock, flags);
+
+- dbg("%s - returns %d", __FUNCTION__, room);
++ dbg("%s - returns %d", __func__, room);
+ return room;
+ }
+
+@@ -767,7 +760,7 @@ static int ti_chars_in_buffer(struct usb_serial_port *port)
+ int chars = 0;
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (tport == NULL)
+ return -ENODEV;
+@@ -776,7 +769,7 @@ static int ti_chars_in_buffer(struct usb_serial_port *port)
+ chars = ti_buf_data_avail(tport->tp_write_buf);
+ spin_unlock_irqrestore(&tport->tp_lock, flags);
+
+- dbg("%s - returns %d", __FUNCTION__, chars);
++ dbg("%s - returns %d", __func__, chars);
+ return chars;
+ }
+
+@@ -786,14 +779,14 @@ static void ti_throttle(struct usb_serial_port *port)
+ struct ti_port *tport = usb_get_serial_port_data(port);
+ struct tty_struct *tty;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (tport == NULL)
+ return;
+
+ tty = port->tty;
+ if (!tty) {
+- dbg("%s - no tty", __FUNCTION__);
++ dbg("%s - no tty", __func__);
+ return;
+ }
+
+@@ -809,21 +802,21 @@ static void ti_unthrottle(struct usb_serial_port *port)
+ struct tty_struct *tty;
+ int status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (tport == NULL)
+ return;
+
+ tty = port->tty;
+ if (!tty) {
+- dbg("%s - no tty", __FUNCTION__);
++ dbg("%s - no tty", __func__);
+ return;
+ }
+
+ if (I_IXOFF(tty) || C_CRTSCTS(tty)) {
+ status = ti_restart_read(tport, tty);
+ if (status)
+- dev_err(&port->dev, "%s - cannot restart read, %d\n", __FUNCTION__, status);
++ dev_err(&port->dev, "%s - cannot restart read, %d\n", __func__, status);
+ }
+ }
+
+@@ -835,24 +828,24 @@ static int ti_ioctl(struct usb_serial_port *port, struct file *file,
+ struct async_icount cnow;
+ struct async_icount cprev;
+
+- dbg("%s - port %d, cmd = 0x%04X", __FUNCTION__, port->number, cmd);
++ dbg("%s - port %d, cmd = 0x%04X", __func__, port->number, cmd);
+
+ if (tport == NULL)
+ return -ENODEV;
+
+ switch (cmd) {
+ case TIOCGSERIAL:
+- dbg("%s - (%d) TIOCGSERIAL", __FUNCTION__, port->number);
++ dbg("%s - (%d) TIOCGSERIAL", __func__, port->number);
+ return ti_get_serial_info(tport, (struct serial_struct __user *)arg);
+ break;
+
+ case TIOCSSERIAL:
+- dbg("%s - (%d) TIOCSSERIAL", __FUNCTION__, port->number);
++ dbg("%s - (%d) TIOCSSERIAL", __func__, port->number);
+ return ti_set_serial_info(tport, (struct serial_struct __user *)arg);
+ break;
+
+ case TIOCMIWAIT:
+- dbg("%s - (%d) TIOCMIWAIT", __FUNCTION__, port->number);
++ dbg("%s - (%d) TIOCMIWAIT", __func__, port->number);
+ cprev = tport->tp_icount;
+ while (1) {
+ interruptible_sleep_on(&tport->tp_msr_wait);
+@@ -873,7 +866,7 @@ static int ti_ioctl(struct usb_serial_port *port, struct file *file,
+ break;
+
+ case TIOCGICOUNT:
+- dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__, port->number, tport->tp_icount.rx, tport->tp_icount.tx);
++ dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, port->number, tport->tp_icount.rx, tport->tp_icount.tx);
+ if (copy_to_user((void __user *)arg, &tport->tp_icount, sizeof(tport->tp_icount)))
+ return -EFAULT;
+ return 0;
+@@ -895,20 +888,20 @@ static void ti_set_termios(struct usb_serial_port *port,
+ int port_number = port->number - port->serial->minor;
+ unsigned int mcr;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ cflag = tty->termios->c_cflag;
+ iflag = tty->termios->c_iflag;
+
+- dbg("%s - cflag %08x, iflag %08x", __FUNCTION__, cflag, iflag);
+- dbg("%s - old clfag %08x, old iflag %08x", __FUNCTION__, old_termios->c_cflag, old_termios->c_iflag);
++ dbg("%s - cflag %08x, iflag %08x", __func__, cflag, iflag);
++ dbg("%s - old clfag %08x, old iflag %08x", __func__, old_termios->c_cflag, old_termios->c_iflag);
+
+ if (tport == NULL)
+ return;
+
+ config = kmalloc(sizeof(*config), GFP_KERNEL);
+ if (!config) {
+- dev_err(&port->dev, "%s - out of memory\n", __FUNCTION__);
++ dev_err(&port->dev, "%s - out of memory\n", __func__);
+ return;
+ }
+
+@@ -992,7 +985,7 @@ static void ti_set_termios(struct usb_serial_port *port,
+ tty_encode_baud_rate(tty, baud, baud);
+
+ dbg("%s - BaudRate=%d, wBaudRate=%d, wFlags=0x%04X, bDataBits=%d, bParity=%d, bStopBits=%d, cXon=%d, cXoff=%d, bUartMode=%d",
+- __FUNCTION__, baud, config->wBaudRate, config->wFlags, config->bDataBits, config->bParity, config->bStopBits, config->cXon, config->cXoff, config->bUartMode);
++ __func__, baud, config->wBaudRate, config->wFlags, config->bDataBits, config->bParity, config->bStopBits, config->cXon, config->cXoff, config->bUartMode);
+
+ cpu_to_be16s(&config->wBaudRate);
+ cpu_to_be16s(&config->wFlags);
+@@ -1001,7 +994,7 @@ static void ti_set_termios(struct usb_serial_port *port,
+ (__u8)(TI_UART1_PORT + port_number), 0, (__u8 *)config,
+ sizeof(*config));
+ if (status)
+- dev_err(&port->dev, "%s - cannot set config on port %d, %d\n", __FUNCTION__, port_number, status);
++ dev_err(&port->dev, "%s - cannot set config on port %d, %d\n", __func__, port_number, status);
+
+ /* SET_CONFIG asserts RTS and DTR, reset them correctly */
+ mcr = tport->tp_shadow_mcr;
+@@ -1010,7 +1003,7 @@ static void ti_set_termios(struct usb_serial_port *port,
+ mcr &= ~(TI_MCR_DTR | TI_MCR_RTS);
+ status = ti_set_mcr(tport, mcr);
+ if (status)
+- dev_err(&port->dev, "%s - cannot set modem control on port %d, %d\n", __FUNCTION__, port_number, status);
++ dev_err(&port->dev, "%s - cannot set modem control on port %d, %d\n", __func__, port_number, status);
+
+ kfree(config);
+ }
+@@ -1022,14 +1015,17 @@ static int ti_tiocmget(struct usb_serial_port *port, struct file *file)
+ unsigned int result;
+ unsigned int msr;
+ unsigned int mcr;
++ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (tport == NULL)
+ return -ENODEV;
+
++ spin_lock_irqsave(&tport->tp_lock, flags);
+ msr = tport->tp_msr;
+ mcr = tport->tp_shadow_mcr;
++ spin_unlock_irqrestore(&tport->tp_lock, flags);
+
+ result = ((mcr & TI_MCR_DTR) ? TIOCM_DTR : 0)
+ | ((mcr & TI_MCR_RTS) ? TIOCM_RTS : 0)
+@@ -1039,7 +1035,7 @@ static int ti_tiocmget(struct usb_serial_port *port, struct file *file)
+ | ((msr & TI_MSR_RI) ? TIOCM_RI : 0)
+ | ((msr & TI_MSR_DSR) ? TIOCM_DSR : 0);
+
+- dbg("%s - 0x%04X", __FUNCTION__, result);
++ dbg("%s - 0x%04X", __func__, result);
+
+ return result;
+ }
+@@ -1050,12 +1046,14 @@ static int ti_tiocmset(struct usb_serial_port *port, struct file *file,
+ {
+ struct ti_port *tport = usb_get_serial_port_data(port);
+ unsigned int mcr;
++ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (tport == NULL)
+ return -ENODEV;
+
++ spin_lock_irqsave(&tport->tp_lock, flags);
+ mcr = tport->tp_shadow_mcr;
+
+ if (set & TIOCM_RTS)
+@@ -1071,6 +1069,7 @@ static int ti_tiocmset(struct usb_serial_port *port, struct file *file,
+ mcr &= ~TI_MCR_DTR;
+ if (clear & TIOCM_LOOP)
+ mcr &= ~TI_MCR_LOOP;
++ spin_unlock_irqrestore(&tport->tp_lock, flags);
+
+ return ti_set_mcr(tport, mcr);
+ }
+@@ -1081,7 +1080,7 @@ static void ti_break(struct usb_serial_port *port, int break_state)
+ struct ti_port *tport = usb_get_serial_port_data(port);
+ int status;
+
+- dbg("%s - state = %d", __FUNCTION__, break_state);
++ dbg("%s - state = %d", __func__, break_state);
+
+ if (tport == NULL)
+ return;
+@@ -1093,13 +1092,13 @@ static void ti_break(struct usb_serial_port *port, int break_state)
+ TI_LCR_BREAK, break_state == -1 ? TI_LCR_BREAK : 0);
+
+ if (status)
+- dbg("%s - error setting break, %d", __FUNCTION__, status);
++ dbg("%s - error setting break, %d", __func__, status);
+ }
+
+
+ static void ti_interrupt_callback(struct urb *urb)
+ {
+- struct ti_device *tdev = (struct ti_device *)urb->context;
++ struct ti_device *tdev = urb->context;
+ struct usb_serial_port *port;
+ struct usb_serial *serial = tdev->td_serial;
+ struct ti_port *tport;
+@@ -1112,7 +1111,7 @@ static void ti_interrupt_callback(struct urb *urb)
+ int retval;
+ __u8 msr;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ switch (status) {
+ case 0:
+@@ -1120,33 +1119,33 @@ static void ti_interrupt_callback(struct urb *urb)
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+- dbg("%s - urb shutting down, %d", __FUNCTION__, status);
++ dbg("%s - urb shutting down, %d", __func__, status);
+ tdev->td_urb_error = 1;
+ return;
+ default:
+ dev_err(dev, "%s - nonzero urb status, %d\n",
+- __FUNCTION__, status);
++ __func__, status);
+ tdev->td_urb_error = 1;
+ goto exit;
+ }
+
+ if (length != 2) {
+- dbg("%s - bad packet size, %d", __FUNCTION__, length);
++ dbg("%s - bad packet size, %d", __func__, length);
+ goto exit;
+ }
+
+ if (data[0] == TI_CODE_HARDWARE_ERROR) {
+- dev_err(dev, "%s - hardware error, %d\n", __FUNCTION__, data[1]);
++ dev_err(dev, "%s - hardware error, %d\n", __func__, data[1]);
+ goto exit;
+ }
+
+ port_number = TI_GET_PORT_FROM_CODE(data[0]);
+ function = TI_GET_FUNC_FROM_CODE(data[0]);
+
+- dbg("%s - port_number %d, function %d, data 0x%02X", __FUNCTION__, port_number, function, data[1]);
++ dbg("%s - port_number %d, function %d, data 0x%02X", __func__, port_number, function, data[1]);
+
+ if (port_number >= serial->num_ports) {
+- dev_err(dev, "%s - bad port number, %d\n", __FUNCTION__, port_number);
++ dev_err(dev, "%s - bad port number, %d\n", __func__, port_number);
+ goto exit;
+ }
+
+@@ -1158,17 +1157,17 @@ static void ti_interrupt_callback(struct urb *urb)
+
+ switch (function) {
+ case TI_CODE_DATA_ERROR:
+- dev_err(dev, "%s - DATA ERROR, port %d, data 0x%02X\n", __FUNCTION__, port_number, data[1]);
++ dev_err(dev, "%s - DATA ERROR, port %d, data 0x%02X\n", __func__, port_number, data[1]);
+ break;
+
+ case TI_CODE_MODEM_STATUS:
+ msr = data[1];
+- dbg("%s - port %d, msr 0x%02X", __FUNCTION__, port_number, msr);
++ dbg("%s - port %d, msr 0x%02X", __func__, port_number, msr);
+ ti_handle_new_msr(tport, msr);
+ break;
+
+ default:
+- dev_err(dev, "%s - unknown interrupt code, 0x%02X\n", __FUNCTION__, data[1]);
++ dev_err(dev, "%s - unknown interrupt code, 0x%02X\n", __func__, data[1]);
+ break;
+ }
+
+@@ -1176,19 +1175,19 @@ exit:
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval)
+ dev_err(dev, "%s - resubmit interrupt urb failed, %d\n",
+- __FUNCTION__, retval);
++ __func__, retval);
+ }
+
+
+ static void ti_bulk_in_callback(struct urb *urb)
+ {
+- struct ti_port *tport = (struct ti_port *)urb->context;
++ struct ti_port *tport = urb->context;
+ struct usb_serial_port *port = tport->tp_port;
+ struct device *dev = &urb->dev->dev;
+ int status = urb->status;
+ int retval = 0;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ switch (status) {
+ case 0:
+@@ -1196,13 +1195,13 @@ static void ti_bulk_in_callback(struct urb *urb)
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+- dbg("%s - urb shutting down, %d", __FUNCTION__, status);
++ dbg("%s - urb shutting down, %d", __func__, status);
+ tport->tp_tdev->td_urb_error = 1;
+ wake_up_interruptible(&tport->tp_write_wait);
+ return;
+ default:
+ dev_err(dev, "%s - nonzero urb status, %d\n",
+- __FUNCTION__, status );
++ __func__, status );
+ tport->tp_tdev->td_urb_error = 1;
+ wake_up_interruptible(&tport->tp_write_wait);
+ }
+@@ -1211,16 +1210,16 @@ static void ti_bulk_in_callback(struct urb *urb)
+ goto exit;
+
+ if (status) {
+- dev_err(dev, "%s - stopping read!\n", __FUNCTION__);
++ dev_err(dev, "%s - stopping read!\n", __func__);
+ return;
+ }
+
+ if (port->tty && urb->actual_length) {
+- usb_serial_debug_data(debug, dev, __FUNCTION__,
++ usb_serial_debug_data(debug, dev, __func__,
+ urb->actual_length, urb->transfer_buffer);
+
+ if (!tport->tp_is_open)
+- dbg("%s - port closed, dropping data", __FUNCTION__);
++ dbg("%s - port closed, dropping data", __func__);
+ else
+ ti_recv(&urb->dev->dev, port->tty, urb->transfer_buffer,
+ urb->actual_length);
+@@ -1242,18 +1241,18 @@ exit:
+ spin_unlock(&tport->tp_lock);
+ if (retval)
+ dev_err(dev, "%s - resubmit read urb failed, %d\n",
+- __FUNCTION__, retval);
++ __func__, retval);
+ }
+
+
+ static void ti_bulk_out_callback(struct urb *urb)
+ {
+- struct ti_port *tport = (struct ti_port *)urb->context;
++ struct ti_port *tport = urb->context;
+ struct usb_serial_port *port = tport->tp_port;
+ struct device *dev = &urb->dev->dev;
+ int status = urb->status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ tport->tp_write_urb_in_use = 0;
+
+@@ -1263,13 +1262,13 @@ static void ti_bulk_out_callback(struct urb *urb)
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+- dbg("%s - urb shutting down, %d", __FUNCTION__, status);
++ dbg("%s - urb shutting down, %d", __func__, status);
+ tport->tp_tdev->td_urb_error = 1;
+ wake_up_interruptible(&tport->tp_write_wait);
+ return;
+ default:
+ dev_err(dev, "%s - nonzero urb status, %d\n",
+- __FUNCTION__, status);
++ __func__, status);
+ tport->tp_tdev->td_urb_error = 1;
+ wake_up_interruptible(&tport->tp_write_wait);
+ }
+@@ -1287,7 +1286,7 @@ static void ti_recv(struct device *dev, struct tty_struct *tty,
+ do {
+ cnt = tty_buffer_request_room(tty, length);
+ if (cnt < length) {
+- dev_err(dev, "%s - dropping data, %d bytes lost\n", __FUNCTION__, length - cnt);
++ dev_err(dev, "%s - dropping data, %d bytes lost\n", __func__, length - cnt);
+ if(cnt == 0)
+ break;
+ }
+@@ -1308,7 +1307,7 @@ static void ti_send(struct ti_port *tport)
+ unsigned long flags;
+
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&tport->tp_lock, flags);
+
+@@ -1330,7 +1329,7 @@ static void ti_send(struct ti_port *tport)
+
+ spin_unlock_irqrestore(&tport->tp_lock, flags);
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer);
++ usb_serial_debug_data(debug, &port->dev, __func__, count, port->write_urb->transfer_buffer);
+
+ usb_fill_bulk_urb(port->write_urb, port->serial->dev,
+ usb_sndbulkpipe(port->serial->dev,
+@@ -1340,7 +1339,7 @@ static void ti_send(struct ti_port *tport)
+
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ if (result) {
+- dev_err(&port->dev, "%s - submit write urb failed, %d\n", __FUNCTION__, result);
++ dev_err(&port->dev, "%s - submit write urb failed, %d\n", __func__, result);
+ tport->tp_write_urb_in_use = 0;
+ /* TODO: reschedule ti_send */
+ } else {
+@@ -1358,14 +1357,17 @@ static void ti_send(struct ti_port *tport)
+
+ static int ti_set_mcr(struct ti_port *tport, unsigned int mcr)
+ {
++ unsigned long flags;
+ int status;
+
+ status = ti_write_byte(tport->tp_tdev,
+ tport->tp_uart_base_addr + TI_UART_OFFSET_MCR,
+ TI_MCR_RTS | TI_MCR_DTR | TI_MCR_LOOP, mcr);
+
++ spin_lock_irqsave(&tport->tp_lock, flags);
+ if (!status)
+ tport->tp_shadow_mcr = mcr;
++ spin_unlock_irqrestore(&tport->tp_lock, flags);
+
+ return status;
+ }
+@@ -1379,23 +1381,23 @@ static int ti_get_lsr(struct ti_port *tport)
+ int port_number = port->number - port->serial->minor;
+ struct ti_port_status *data;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ size = sizeof(struct ti_port_status);
+ data = kmalloc(size, GFP_KERNEL);
+ if (!data) {
+- dev_err(&port->dev, "%s - out of memory\n", __FUNCTION__);
++ dev_err(&port->dev, "%s - out of memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ status = ti_command_in_sync(tdev, TI_GET_PORT_STATUS,
+ (__u8)(TI_UART1_PORT+port_number), 0, (__u8 *)data, size);
+ if (status) {
+- dev_err(&port->dev, "%s - get port status command failed, %d\n", __FUNCTION__, status);
++ dev_err(&port->dev, "%s - get port status command failed, %d\n", __func__, status);
+ goto free_data;
+ }
+
+- dbg("%s - lsr 0x%02X", __FUNCTION__, data->bLSR);
++ dbg("%s - lsr 0x%02X", __func__, data->bLSR);
+
+ tport->tp_lsr = data->bLSR;
+
+@@ -1456,7 +1458,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)
+ struct tty_struct *tty;
+ unsigned long flags;
+
+- dbg("%s - msr 0x%02X", __FUNCTION__, msr);
++ dbg("%s - msr 0x%02X", __func__, msr);
+
+ if (msr & TI_MSR_DELTA_MASK) {
+ spin_lock_irqsave(&tport->tp_lock, flags);
+@@ -1494,7 +1496,7 @@ static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush)
+ struct usb_serial_port *port = tport->tp_port;
+ wait_queue_t wait;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irq(&tport->tp_lock);
+
+@@ -1626,12 +1628,12 @@ static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
+ struct ti_write_data_bytes *data;
+ struct device *dev = &tdev->td_serial->dev->dev;
+
+- dbg("%s - addr 0x%08lX, mask 0x%02X, byte 0x%02X", __FUNCTION__, addr, mask, byte);
++ dbg("%s - addr 0x%08lX, mask 0x%02X, byte 0x%02X", __func__, addr, mask, byte);
+
+ size = sizeof(struct ti_write_data_bytes) + 2;
+ data = kmalloc(size, GFP_KERNEL);
+ if (!data) {
+- dev_err(dev, "%s - out of memory\n", __FUNCTION__);
++ dev_err(dev, "%s - out of memory\n", __func__);
+ return -ENOMEM;
+ }
+
+@@ -1647,7 +1649,7 @@ static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
+ (__u8 *)data, size);
+
+ if (status < 0)
+- dev_err(dev, "%s - failed, %d\n", __FUNCTION__, status);
++ dev_err(dev, "%s - failed, %d\n", __func__, status);
+
+ kfree(data);
+
+@@ -1674,7 +1676,7 @@ static int ti_download_firmware(struct ti_device *tdev,
+ buffer_size = TI_FIRMWARE_BUF_SIZE + sizeof(struct ti_firmware_header);
+ buffer = kmalloc(buffer_size, GFP_KERNEL);
+ if (!buffer) {
+- dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
++ dev_err(&dev->dev, "%s - out of memory\n", __func__);
+ return -ENOMEM;
+ }
+
+@@ -1688,7 +1690,7 @@ static int ti_download_firmware(struct ti_device *tdev,
+ header->wLength = cpu_to_le16((__u16)(buffer_size - sizeof(struct ti_firmware_header)));
+ header->bCheckSum = cs;
+
+- dbg("%s - downloading firmware", __FUNCTION__);
++ dbg("%s - downloading firmware", __func__);
+ for (pos = 0; pos < buffer_size; pos += done) {
+ len = min(buffer_size - pos, TI_DOWNLOAD_MAX_PACKET_SIZE);
+ status = usb_bulk_msg(dev, pipe, buffer+pos, len, &done, 1000);
+@@ -1699,11 +1701,11 @@ static int ti_download_firmware(struct ti_device *tdev,
+ kfree(buffer);
+
+ if (status) {
+- dev_err(&dev->dev, "%s - error downloading firmware, %d\n", __FUNCTION__, status);
++ dev_err(&dev->dev, "%s - error downloading firmware, %d\n", __func__, status);
+ return status;
+ }
+
+- dbg("%s - download successful", __FUNCTION__);
++ dbg("%s - download successful", __func__);
+
+ return 0;
+ }
+diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
+index 2138ba8..a9934a3 100644
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -81,7 +81,7 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po
+ unsigned int i, j;
+ int good_spot;
+
+- dbg("%s %d", __FUNCTION__, num_ports);
++ dbg("%s %d", __func__, num_ports);
+
+ *minor = 0;
+ mutex_lock(&table_lock);
+@@ -101,7 +101,7 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po
+
+ *minor = i;
+ j = 0;
+- dbg("%s - minor base = %d", __FUNCTION__, *minor);
++ dbg("%s - minor base = %d", __func__, *minor);
+ for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) {
+ serial_table[i] = serial;
+ serial->port[j++]->number = i;
+@@ -117,7 +117,7 @@ static void return_serial(struct usb_serial *serial)
+ {
+ int i;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ if (serial == NULL)
+ return;
+@@ -135,7 +135,7 @@ static void destroy_serial(struct kref *kref)
+
+ serial = to_usb_serial(kref);
+
+- dbg("%s - %s", __FUNCTION__, serial->type->description);
++ dbg("%s - %s", __func__, serial->type->description);
+
+ serial->type->shutdown(serial);
+
+@@ -187,7 +187,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
+ unsigned int portNumber;
+ int retval;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ /* get the serial object associated with this tty pointer */
+ serial = usb_serial_get_by_index(tty->index);
+@@ -259,7 +259,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
+ if (!port)
+ return;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ mutex_lock(&port->mutex);
+
+@@ -299,11 +299,11 @@ static int serial_write (struct tty_struct * tty, const unsigned char *buf, int
+ if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED)
+ goto exit;
+
+- dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
++ dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
+
+ if (!port->open_count) {
+ retval = -EINVAL;
+- dbg("%s - port not opened", __FUNCTION__);
++ dbg("%s - port not opened", __func__);
+ goto exit;
+ }
+
+@@ -322,10 +322,10 @@ static int serial_write_room (struct tty_struct *tty)
+ if (!port)
+ goto exit;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (!port->open_count) {
+- dbg("%s - port not open", __FUNCTION__);
++ dbg("%s - port not open", __func__);
+ goto exit;
+ }
+
+@@ -344,10 +344,10 @@ static int serial_chars_in_buffer (struct tty_struct *tty)
+ if (!port)
+ goto exit;
+
+- dbg("%s = port %d", __FUNCTION__, port->number);
++ dbg("%s = port %d", __func__, port->number);
+
+ if (!port->open_count) {
+- dbg("%s - port not open", __FUNCTION__);
++ dbg("%s - port not open", __func__);
+ goto exit;
+ }
+
+@@ -365,10 +365,10 @@ static void serial_throttle (struct tty_struct * tty)
+ if (!port)
+ return;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (!port->open_count) {
+- dbg ("%s - port not open", __FUNCTION__);
++ dbg ("%s - port not open", __func__);
+ return;
+ }
+
+@@ -384,10 +384,10 @@ static void serial_unthrottle (struct tty_struct * tty)
+ if (!port)
+ return;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (!port->open_count) {
+- dbg("%s - port not open", __FUNCTION__);
++ dbg("%s - port not open", __func__);
+ return;
+ }
+
+@@ -401,13 +401,15 @@ static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned in
+ struct usb_serial_port *port = tty->driver_data;
+ int retval = -ENODEV;
+
++ lock_kernel();
+ if (!port)
+ goto exit;
+
+- dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
++ dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
+
++ /* Caution - port->open_count is BKL protected */
+ if (!port->open_count) {
+- dbg ("%s - port not open", __FUNCTION__);
++ dbg ("%s - port not open", __func__);
+ goto exit;
+ }
+
+@@ -416,8 +418,8 @@ static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned in
+ retval = port->serial->type->ioctl(port, file, cmd, arg);
+ else
+ retval = -ENOIOCTLCMD;
+-
+ exit:
++ unlock_kernel();
+ return retval;
+ }
+
+@@ -428,10 +430,10 @@ static void serial_set_termios (struct tty_struct *tty, struct ktermios * old)
+ if (!port)
+ return;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (!port->open_count) {
+- dbg("%s - port not open", __FUNCTION__);
++ dbg("%s - port not open", __func__);
+ return;
+ }
+
+@@ -446,19 +448,24 @@ static void serial_break (struct tty_struct *tty, int break_state)
+ {
+ struct usb_serial_port *port = tty->driver_data;
+
+- if (!port)
++ lock_kernel();
++ if (!port) {
++ unlock_kernel();
+ return;
++ }
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (!port->open_count) {
+- dbg("%s - port not open", __FUNCTION__);
++ dbg("%s - port not open", __func__);
++ unlock_kernel();
+ return;
+ }
+
+ /* pass on to the driver specific version of this function if it is available */
+ if (port->serial->type->break_ctl)
+ port->serial->type->break_ctl(port, break_state);
++ unlock_kernel();
+ }
+
+ static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
+@@ -469,7 +476,7 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int
+ off_t begin = 0;
+ char tmp[40];
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+ length += sprintf (page, "usbserinfo:1.0 driver:2.0\n");
+ for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) {
+ serial = usb_serial_get_by_index(i);
+@@ -515,10 +522,10 @@ static int serial_tiocmget (struct tty_struct *tty, struct file *file)
+ if (!port)
+ return -ENODEV;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (!port->open_count) {
+- dbg("%s - port not open", __FUNCTION__);
++ dbg("%s - port not open", __func__);
+ return -ENODEV;
+ }
+
+@@ -536,10 +543,10 @@ static int serial_tiocmset (struct tty_struct *tty, struct file *file,
+ if (!port)
+ return -ENODEV;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (!port->open_count) {
+- dbg("%s - port not open", __FUNCTION__);
++ dbg("%s - port not open", __func__);
+ return -ENODEV;
+ }
+
+@@ -565,7 +572,7 @@ static void usb_serial_port_work(struct work_struct *work)
+ container_of(work, struct usb_serial_port, work);
+ struct tty_struct *tty;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (!port)
+ return;
+@@ -581,7 +588,7 @@ static void port_release(struct device *dev)
+ {
+ struct usb_serial_port *port = to_usb_serial_port(dev);
+
+- dbg ("%s - %s", __FUNCTION__, dev->bus_id);
++ dbg ("%s - %s", __func__, dev->bus_id);
+ port_free(port);
+ }
+
+@@ -627,7 +634,7 @@ static struct usb_serial * create_serial (struct usb_device *dev,
+
+ serial = kzalloc(sizeof(*serial), GFP_KERNEL);
+ if (!serial) {
+- dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
++ dev_err(&dev->dev, "%s - out of memory\n", __func__);
+ return NULL;
+ }
+ serial->dev = usb_get_dev(dev);
+@@ -722,7 +729,7 @@ int usb_serial_probe(struct usb_interface *interface,
+ serial = create_serial (dev, interface, type);
+ if (!serial) {
+ unlock_kernel();
+- dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__);
++ dev_err(&interface->dev, "%s - out of memory\n", __func__);
+ return -ENOMEM;
+ }
+
+@@ -854,22 +861,6 @@ int usb_serial_probe(struct usb_interface *interface,
+ serial->num_interrupt_in = num_interrupt_in;
+ serial->num_interrupt_out = num_interrupt_out;
+
+-#if 0
+- /* check that the device meets the driver's requirements */
+- if ((type->num_interrupt_in != NUM_DONT_CARE &&
+- type->num_interrupt_in != num_interrupt_in)
+- || (type->num_interrupt_out != NUM_DONT_CARE &&
+- type->num_interrupt_out != num_interrupt_out)
+- || (type->num_bulk_in != NUM_DONT_CARE &&
+- type->num_bulk_in != num_bulk_in)
+- || (type->num_bulk_out != NUM_DONT_CARE &&
+- type->num_bulk_out != num_bulk_out)) {
+- dbg("wrong number of endpoints");
+- kfree(serial);
+- return -EIO;
+- }
+-#endif
+-
+ /* found all that we need */
+ dev_info(&interface->dev, "%s converter detected\n",
+ type->description);
+@@ -883,7 +874,7 @@ int usb_serial_probe(struct usb_interface *interface,
+ serial->num_port_pointers = max_endpoints;
+ unlock_kernel();
+
+- dbg("%s - setting up %d port structures for this device", __FUNCTION__, max_endpoints);
++ dbg("%s - setting up %d port structures for this device", __func__, max_endpoints);
+ for (i = 0; i < max_endpoints; ++i) {
+ port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
+ if (!port)
+@@ -1031,7 +1022,7 @@ int usb_serial_probe(struct usb_interface *interface,
+ port->dev.release = &port_release;
+
+ snprintf (&port->dev.bus_id[0], sizeof(port->dev.bus_id), "ttyUSB%d", port->number);
+- dbg ("%s - registering %s", __FUNCTION__, port->dev.bus_id);
++ dbg ("%s - registering %s", __func__, port->dev.bus_id);
+ retval = device_register(&port->dev);
+ if (retval)
+ dev_err(&port->dev, "Error registering port device, "
+@@ -1090,7 +1081,7 @@ void usb_serial_disconnect(struct usb_interface *interface)
+ struct usb_serial_port *port;
+
+ usb_serial_console_disconnect(serial);
+- dbg ("%s", __FUNCTION__);
++ dbg ("%s", __func__);
+
+ mutex_lock(&serial->disc_mutex);
+ usb_set_intfdata (interface, NULL);
+@@ -1174,7 +1165,7 @@ static int __init usb_serial_init(void)
+
+ result = bus_register(&usb_serial_bus_type);
+ if (result) {
+- err("%s - registering bus driver failed", __FUNCTION__);
++ err("%s - registering bus driver failed", __func__);
+ goto exit_bus;
+ }
+
+@@ -1188,24 +1179,26 @@ static int __init usb_serial_init(void)
+ usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+ usb_serial_tty_driver->init_termios = tty_std_termios;
+ usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
++ usb_serial_tty_driver->init_termios.c_ispeed = 9600;
++ usb_serial_tty_driver->init_termios.c_ospeed = 9600;
+ tty_set_operations(usb_serial_tty_driver, &serial_ops);
+ result = tty_register_driver(usb_serial_tty_driver);
+ if (result) {
+- err("%s - tty_register_driver failed", __FUNCTION__);
++ err("%s - tty_register_driver failed", __func__);
+ goto exit_reg_driver;
+ }
+
+ /* register the USB driver */
+ result = usb_register(&usb_serial_driver);
+ if (result < 0) {
+- err("%s - usb_register failed", __FUNCTION__);
++ err("%s - usb_register failed", __func__);
+ goto exit_tty;
+ }
+
+ /* register the generic driver, if we should */
+ result = usb_serial_generic_register(debug);
+ if (result < 0) {
+- err("%s - registering generic driver failed", __FUNCTION__);
++ err("%s - registering generic driver failed", __func__);
+ goto exit_generic;
+ }
+
+@@ -1223,7 +1216,7 @@ exit_reg_driver:
+ bus_unregister(&usb_serial_bus_type);
+
+ exit_bus:
+- err ("%s - returning with error %d", __FUNCTION__, result);
++ err ("%s - returning with error %d", __func__, result);
+ put_tty_driver(usb_serial_tty_driver);
+ return result;
+ }
+diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c
+index 257a5e4..f9fc926 100644
+--- a/drivers/usb/serial/usb_debug.c
++++ b/drivers/usb/serial/usb_debug.c
+@@ -35,9 +35,6 @@ static struct usb_serial_driver debug_device = {
+ .name = "debug",
+ },
+ .id_table = id_table,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_bulk_in = NUM_DONT_CARE,
+- .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 1,
+ };
+
+diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
+index c2b01f7..5fc2012 100644
+--- a/drivers/usb/serial/visor.c
++++ b/drivers/usb/serial/visor.c
+@@ -189,9 +189,6 @@ static struct usb_serial_driver handspring_device = {
+ .description = "Handspring Visor / Palm OS",
+ .usb_driver = &visor_driver,
+ .id_table = id_table,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_bulk_in = 2,
+- .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 2,
+ .open = visor_open,
+ .close = visor_close,
+@@ -219,9 +216,6 @@ static struct usb_serial_driver clie_5_device = {
+ .description = "Sony Clie 5.0",
+ .usb_driver = &visor_driver,
+ .id_table = clie_id_5_table,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_bulk_in = 2,
+- .num_bulk_out = 2,
+ .num_ports = 2,
+ .open = visor_open,
+ .close = visor_close,
+@@ -249,9 +243,6 @@ static struct usb_serial_driver clie_3_5_device = {
+ .description = "Sony Clie 3.5",
+ .usb_driver = &visor_driver,
+ .id_table = clie_id_3_5_table,
+- .num_interrupt_in = 0,
+- .num_bulk_in = 1,
+- .num_bulk_out = 1,
+ .num_ports = 1,
+ .open = visor_open,
+ .close = visor_close,
+@@ -290,7 +281,7 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
+ unsigned long flags;
+ int result = 0;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (!port->read_urb) {
+ /* this is needed for some brain dead Sony devices */
+@@ -322,16 +313,16 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
+ result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ if (result) {
+ dev_err(&port->dev, "%s - failed submitting read urb, error %d\n",
+- __FUNCTION__, result);
++ __func__, result);
+ goto exit;
+ }
+
+ if (port->interrupt_in_urb) {
+- dbg("%s - adding interrupt input for treo", __FUNCTION__);
++ dbg("%s - adding interrupt input for treo", __func__);
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ if (result)
+ dev_err(&port->dev, "%s - failed submitting interrupt urb, error %d\n",
+- __FUNCTION__, result);
++ __func__, result);
+ }
+ exit:
+ return result;
+@@ -343,7 +334,7 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
+ struct visor_private *priv = usb_get_serial_port_data(port);
+ unsigned char *transfer_buffer;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /* shutdown our urbs */
+ usb_kill_urb(port->read_urb);
+@@ -379,12 +370,12 @@ static int visor_write (struct usb_serial_port *port, const unsigned char *buf,
+ unsigned long flags;
+ int status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (priv->outstanding_urbs > URB_UPPER_LIMIT) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+- dbg("%s - write limit hit\n", __FUNCTION__);
++ dbg("%s - write limit hit\n", __func__);
+ return 0;
+ }
+ priv->outstanding_urbs++;
+@@ -406,7 +397,7 @@ static int visor_write (struct usb_serial_port *port, const unsigned char *buf,
+
+ memcpy (buffer, buf, count);
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
++ usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
+
+ usb_fill_bulk_urb (urb, serial->dev,
+ usb_sndbulkpipe (serial->dev,
+@@ -418,7 +409,7 @@ static int visor_write (struct usb_serial_port *port, const unsigned char *buf,
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (status) {
+ dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n",
+- __FUNCTION__, status);
++ __func__, status);
+ count = status;
+ goto error;
+ } else {
+@@ -449,7 +440,7 @@ static int visor_write_room (struct usb_serial_port *port)
+ struct visor_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /*
+ * We really can take anything the user throws at us
+@@ -460,7 +451,7 @@ static int visor_write_room (struct usb_serial_port *port)
+ spin_lock_irqsave(&priv->lock, flags);
+ if (priv->outstanding_urbs > URB_UPPER_LIMIT * 2 / 3) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+- dbg("%s - write limit hit\n", __FUNCTION__);
++ dbg("%s - write limit hit\n", __func__);
+ return 0;
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+@@ -471,13 +462,15 @@ static int visor_write_room (struct usb_serial_port *port)
+
+ static int visor_chars_in_buffer (struct usb_serial_port *port)
+ {
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ /*
+ * We can't really account for how much data we
+ * have sent out, but hasn't made it through to the
+ * device, so just tell the tty layer that everything
+ * is flushed.
++ *
++ * FIXME: Should walk outstanding_urbs
+ */
+ return 0;
+ }
+@@ -485,7 +478,7 @@ static int visor_chars_in_buffer (struct usb_serial_port *port)
+
+ static void visor_write_bulk_callback (struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct visor_private *priv = usb_get_serial_port_data(port);
+ int status = urb->status;
+ unsigned long flags;
+@@ -493,11 +486,11 @@ static void visor_write_bulk_callback (struct urb *urb)
+ /* free up the transfer buffer, as usb_free_urb() does not do this */
+ kfree (urb->transfer_buffer);
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (status)
+ dbg("%s - nonzero write bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ --priv->outstanding_urbs;
+@@ -509,7 +502,7 @@ static void visor_write_bulk_callback (struct urb *urb)
+
+ static void visor_read_bulk_callback (struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct visor_private *priv = usb_get_serial_port_data(port);
+ unsigned char *data = urb->transfer_buffer;
+ int status = urb->status;
+@@ -517,15 +510,15 @@ static void visor_read_bulk_callback (struct urb *urb)
+ int result;
+ int available_room;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++ usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+
+ tty = port->tty;
+ if (tty && urb->actual_length) {
+@@ -551,7 +544,7 @@ static void visor_read_bulk_callback (struct urb *urb)
+ visor_read_bulk_callback, port);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ if (result)
+- dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
++ dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
+ } else {
+ priv->actually_throttled = 1;
+ }
+@@ -560,7 +553,7 @@ static void visor_read_bulk_callback (struct urb *urb)
+
+ static void visor_read_int_callback (struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ int status = urb->status;
+ int result;
+
+@@ -573,11 +566,11 @@ static void visor_read_int_callback (struct urb *urb)
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ goto exit;
+ }
+
+@@ -588,14 +581,14 @@ static void visor_read_int_callback (struct urb *urb)
+ * Rumor has it this endpoint is used to notify when data
+ * is ready to be read from the bulk ones.
+ */
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
++ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, urb->transfer_buffer);
+
+ exit:
+ result = usb_submit_urb (urb, GFP_ATOMIC);
+ if (result)
+ dev_err(&urb->dev->dev, "%s - Error %d submitting interrupt urb\n",
+- __FUNCTION__, result);
++ __func__, result);
+ }
+
+ static void visor_throttle (struct usb_serial_port *port)
+@@ -603,7 +596,7 @@ static void visor_throttle (struct usb_serial_port *port)
+ struct visor_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->throttled = 1;
+ spin_unlock_irqrestore(&priv->lock, flags);
+@@ -616,7 +609,7 @@ static void visor_unthrottle (struct usb_serial_port *port)
+ unsigned long flags;
+ int result;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->throttled = 0;
+ priv->actually_throttled = 0;
+@@ -625,7 +618,7 @@ static void visor_unthrottle (struct usb_serial_port *port)
+ port->read_urb->dev = port->serial->dev;
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ if (result)
+- dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
++ dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
+ }
+
+ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_id *id)
+@@ -638,11 +631,11 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
+ int i;
+ int num_ports = 0;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ transfer_buffer = kmalloc (sizeof (*connection_info), GFP_KERNEL);
+ if (!transfer_buffer) {
+- dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __FUNCTION__,
++ dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __func__,
+ sizeof(*connection_info));
+ return -ENOMEM;
+ }
+@@ -655,7 +648,7 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
+ sizeof(*connection_info), 300);
+ if (retval < 0) {
+ dev_err(dev, "%s - error %d getting connection information\n",
+- __FUNCTION__, retval);
++ __func__, retval);
+ goto exit;
+ }
+
+@@ -715,7 +708,7 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
+ 0x02, 300);
+ if (retval < 0)
+ dev_err(dev, "%s - error %d getting bytes available request\n",
+- __FUNCTION__, retval);
++ __func__, retval);
+ retval = 0;
+
+ exit:
+@@ -731,11 +724,11 @@ static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_i
+ unsigned char *transfer_buffer;
+ int retval;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ transfer_buffer = kmalloc (sizeof (*connection_info), GFP_KERNEL);
+ if (!transfer_buffer) {
+- dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __FUNCTION__,
++ dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __func__,
+ sizeof(*connection_info));
+ return -ENOMEM;
+ }
+@@ -747,9 +740,9 @@ static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_i
+ sizeof (*connection_info), 300);
+ if (retval < 0)
+ dev_err(dev, "%s - error %d getting connection info\n",
+- __FUNCTION__, retval);
++ __func__, retval);
+ else
+- usb_serial_debug_data(debug, &serial->dev->dev, __FUNCTION__,
++ usb_serial_debug_data(debug, &serial->dev->dev, __func__,
+ retval, transfer_buffer);
+
+ kfree (transfer_buffer);
+@@ -762,7 +755,7 @@ static int visor_probe (struct usb_serial *serial, const struct usb_device_id *i
+ int retval = 0;
+ int (*startup) (struct usb_serial *serial, const struct usb_device_id *id);
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
+ err("active config #%d != 1 ??",
+@@ -816,7 +809,7 @@ static int clie_3_5_startup (struct usb_serial *serial)
+ int result;
+ u8 data;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ /*
+ * Note that PEG-300 series devices expect the following two calls.
+@@ -827,11 +820,11 @@ static int clie_3_5_startup (struct usb_serial *serial)
+ USB_REQ_GET_CONFIGURATION, USB_DIR_IN,
+ 0, 0, &data, 1, 3000);
+ if (result < 0) {
+- dev_err(dev, "%s: get config number failed: %d\n", __FUNCTION__, result);
++ dev_err(dev, "%s: get config number failed: %d\n", __func__, result);
+ return result;
+ }
+ if (result != 1) {
+- dev_err(dev, "%s: get config number bad return length: %d\n", __FUNCTION__, result);
++ dev_err(dev, "%s: get config number bad return length: %d\n", __func__, result);
+ return -EIO;
+ }
+
+@@ -841,11 +834,11 @@ static int clie_3_5_startup (struct usb_serial *serial)
+ USB_DIR_IN | USB_RECIP_INTERFACE,
+ 0, 0, &data, 1, 3000);
+ if (result < 0) {
+- dev_err(dev, "%s: get interface number failed: %d\n", __FUNCTION__, result);
++ dev_err(dev, "%s: get interface number failed: %d\n", __func__, result);
+ return result;
+ }
+ if (result != 1) {
+- dev_err(dev, "%s: get interface number bad return length: %d\n", __FUNCTION__, result);
++ dev_err(dev, "%s: get interface number bad return length: %d\n", __func__, result);
+ return -EIO;
+ }
+
+@@ -863,7 +856,7 @@ static int treo_attach (struct usb_serial *serial)
+ (serial->num_interrupt_in == 0))
+ goto generic_startup;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ /*
+ * It appears that Treos and Kyoceras want to use the
+@@ -894,7 +887,7 @@ generic_startup:
+
+ static int clie_5_attach (struct usb_serial *serial)
+ {
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ /* TH55 registers 2 ports.
+ Communication in from the UX50/TH55 uses bulk_in_endpointAddress from port 0
+@@ -918,7 +911,7 @@ static void visor_shutdown (struct usb_serial *serial)
+ struct visor_private *priv;
+ int i;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ for (i = 0; i < serial->num_ports; i++) {
+ priv = usb_get_serial_port_data(serial->port[i]);
+@@ -931,7 +924,7 @@ static void visor_shutdown (struct usb_serial *serial)
+
+ static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+ {
+- dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
++ dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
+
+ return -ENOIOCTLCMD;
+ }
+diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
+index 38726ef..e96bf86 100644
+--- a/drivers/usb/serial/whiteheat.c
++++ b/drivers/usb/serial/whiteheat.c
+@@ -164,9 +164,6 @@ static struct usb_serial_driver whiteheat_fake_device = {
+ .description = "Connect Tech - WhiteHEAT - (prerenumeration)",
+ .usb_driver = &whiteheat_driver,
+ .id_table = id_table_prerenumeration,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_bulk_in = NUM_DONT_CARE,
+- .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 1,
+ .probe = whiteheat_firmware_download,
+ .attach = whiteheat_firmware_attach,
+@@ -180,9 +177,6 @@ static struct usb_serial_driver whiteheat_device = {
+ .description = "Connect Tech - WhiteHEAT",
+ .usb_driver = &whiteheat_driver,
+ .id_table = id_table_std,
+- .num_interrupt_in = NUM_DONT_CARE,
+- .num_bulk_in = NUM_DONT_CARE,
+- .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 4,
+ .attach = whiteheat_attach,
+ .shutdown = whiteheat_shutdown,
+@@ -225,7 +219,7 @@ struct whiteheat_urb_wrap {
+ struct whiteheat_private {
+ spinlock_t lock;
+ __u8 flags;
+- __u8 mcr;
++ __u8 mcr; /* FIXME: no locking on mcr */
+ struct list_head rx_urbs_free;
+ struct list_head rx_urbs_submitted;
+ struct list_head rx_urb_q;
+@@ -288,7 +282,7 @@ static int whiteheat_firmware_download (struct usb_serial *serial, const struct
+ int response;
+ const struct whiteheat_hex_record *record;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ response = ezusb_set_reset (serial, 1);
+
+@@ -298,7 +292,7 @@ static int whiteheat_firmware_download (struct usb_serial *serial, const struct
+ (unsigned char *)record->data, record->data_size, 0xa0);
+ if (response < 0) {
+ err("%s - ezusb_writememory failed for loader (%d %04X %p %d)",
+- __FUNCTION__, response, record->address, record->data, record->data_size);
++ __func__, response, record->address, record->data, record->data_size);
+ break;
+ }
+ ++record;
+@@ -315,7 +309,7 @@ static int whiteheat_firmware_download (struct usb_serial *serial, const struct
+ (unsigned char *)record->data, record->data_size, 0xa3);
+ if (response < 0) {
+ err("%s - ezusb_writememory failed for first firmware step (%d %04X %p %d)",
+- __FUNCTION__, response, record->address, record->data, record->data_size);
++ __func__, response, record->address, record->data, record->data_size);
+ break;
+ }
+ ++record;
+@@ -329,7 +323,7 @@ static int whiteheat_firmware_download (struct usb_serial *serial, const struct
+ (unsigned char *)record->data, record->data_size, 0xa0);
+ if (response < 0) {
+ err("%s - ezusb_writememory failed for second firmware step (%d %04X %p %d)",
+- __FUNCTION__, response, record->address, record->data, record->data_size);
++ __func__, response, record->address, record->data, record->data_size);
+ break;
+ }
+ ++record;
+@@ -567,7 +561,7 @@ static void whiteheat_shutdown (struct usb_serial *serial)
+ struct list_head *tmp2;
+ int i;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ /* free up our private data for our command port */
+ command_port = serial->port[COMMAND_PORT];
+@@ -604,7 +598,7 @@ static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
+ int retval = 0;
+ struct ktermios old_term;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ retval = start_command_port(port->serial);
+ if (retval)
+@@ -637,14 +631,14 @@ static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
+ /* Start reading from the device */
+ retval = start_port_read(port);
+ if (retval) {
+- err("%s - failed submitting read urb, error %d", __FUNCTION__, retval);
++ err("%s - failed submitting read urb, error %d", __func__, retval);
+ firm_close(port);
+ stop_command_port(port->serial);
+ goto exit;
+ }
+
+ exit:
+- dbg("%s - exit, retval = %d", __FUNCTION__, retval);
++ dbg("%s - exit, retval = %d", __func__, retval);
+ return retval;
+ }
+
+@@ -657,7 +651,7 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
+ struct list_head *tmp;
+ struct list_head *tmp2;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ mutex_lock(&port->serial->disc_mutex);
+ /* filp is NULL when called from usb_serial_disconnect */
+@@ -732,10 +726,10 @@ static int whiteheat_write(struct usb_serial_port *port, const unsigned char *bu
+ unsigned long flags;
+ struct list_head *tmp;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (count == 0) {
+- dbg("%s - write request of 0 bytes", __FUNCTION__);
++ dbg("%s - write request of 0 bytes", __func__);
+ return (0);
+ }
+
+@@ -754,13 +748,13 @@ static int whiteheat_write(struct usb_serial_port *port, const unsigned char *bu
+ bytes = (count > port->bulk_out_size) ? port->bulk_out_size : count;
+ memcpy (urb->transfer_buffer, buf + sent, bytes);
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, bytes, urb->transfer_buffer);
++ usb_serial_debug_data(debug, &port->dev, __func__, bytes, urb->transfer_buffer);
+
+ urb->dev = serial->dev;
+ urb->transfer_buffer_length = bytes;
+ result = usb_submit_urb(urb, GFP_ATOMIC);
+ if (result) {
+- err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
++ err("%s - failed submitting write urb, error %d", __func__, result);
+ sent = result;
+ spin_lock_irqsave(&info->lock, flags);
+ list_add(tmp, &info->tx_urbs_free);
+@@ -786,7 +780,7 @@ static int whiteheat_write_room(struct usb_serial_port *port)
+ int room = 0;
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&info->lock, flags);
+ list_for_each(tmp, &info->tx_urbs_free)
+@@ -794,7 +788,7 @@ static int whiteheat_write_room(struct usb_serial_port *port)
+ spin_unlock_irqrestore(&info->lock, flags);
+ room *= port->bulk_out_size;
+
+- dbg("%s - returns %d", __FUNCTION__, room);
++ dbg("%s - returns %d", __func__, room);
+ return (room);
+ }
+
+@@ -804,7 +798,7 @@ static int whiteheat_tiocmget (struct usb_serial_port *port, struct file *file)
+ struct whiteheat_private *info = usb_get_serial_port_data(port);
+ unsigned int modem_signals = 0;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ firm_get_dtr_rts(port);
+ if (info->mcr & UART_MCR_DTR)
+@@ -821,7 +815,7 @@ static int whiteheat_tiocmset (struct usb_serial_port *port, struct file *file,
+ {
+ struct whiteheat_private *info = usb_get_serial_port_data(port);
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ if (set & TIOCM_RTS)
+ info->mcr |= UART_MCR_RTS;
+@@ -844,7 +838,7 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un
+ struct serial_struct serstruct;
+ void __user *user_arg = (void __user *)arg;
+
+- dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
++ dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
+
+ switch (cmd) {
+ case TIOCGSERIAL:
+@@ -886,7 +880,7 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un
+
+ static void whiteheat_set_termios(struct usb_serial_port *port, struct ktermios *old_termios)
+ {
+- dbg("%s -port %d", __FUNCTION__, port->number);
++ dbg("%s -port %d", __func__, port->number);
+ firm_setup_port(port);
+ }
+
+@@ -904,7 +898,7 @@ static int whiteheat_chars_in_buffer(struct usb_serial_port *port)
+ int chars = 0;
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&info->lock, flags);
+ list_for_each(tmp, &info->tx_urbs_submitted) {
+@@ -913,7 +907,7 @@ static int whiteheat_chars_in_buffer(struct usb_serial_port *port)
+ }
+ spin_unlock_irqrestore(&info->lock, flags);
+
+- dbg ("%s - returns %d", __FUNCTION__, chars);
++ dbg ("%s - returns %d", __func__, chars);
+ return chars;
+ }
+
+@@ -923,7 +917,7 @@ static void whiteheat_throttle (struct usb_serial_port *port)
+ struct whiteheat_private *info = usb_get_serial_port_data(port);
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&info->lock, flags);
+ info->flags |= THROTTLED;
+@@ -939,7 +933,7 @@ static void whiteheat_unthrottle (struct usb_serial_port *port)
+ int actually_throttled;
+ unsigned long flags;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock_irqsave(&info->lock, flags);
+ actually_throttled = info->flags & ACTUALLY_THROTTLED;
+@@ -960,7 +954,7 @@ static void command_port_write_callback(struct urb *urb)
+ {
+ int status = urb->status;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ if (status) {
+ dbg("nonzero urb status: %d", status);
+@@ -971,28 +965,28 @@ static void command_port_write_callback(struct urb *urb)
+
+ static void command_port_read_callback(struct urb *urb)
+ {
+- struct usb_serial_port *command_port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *command_port = urb->context;
+ struct whiteheat_command_private *command_info;
+ int status = urb->status;
+ unsigned char *data = urb->transfer_buffer;
+ int result;
+
+- dbg("%s", __FUNCTION__);
++ dbg("%s", __func__);
+
+ command_info = usb_get_serial_port_data(command_port);
+ if (!command_info) {
+- dbg ("%s - command_info is NULL, exiting.", __FUNCTION__);
++ dbg ("%s - command_info is NULL, exiting.", __func__);
+ return;
+ }
+ if (status) {
+- dbg("%s - nonzero urb status: %d", __FUNCTION__, status);
++ dbg("%s - nonzero urb status: %d", __func__, status);
+ if (status != -ENOENT)
+ command_info->command_finished = WHITEHEAT_CMD_FAILURE;
+ wake_up(&command_info->wait_command);
+ return;
+ }
+
+- usb_serial_debug_data(debug, &command_port->dev, __FUNCTION__, urb->actual_length, data);
++ usb_serial_debug_data(debug, &command_port->dev, __func__, urb->actual_length, data);
+
+ if (data[0] == WHITEHEAT_CMD_COMPLETE) {
+ command_info->command_finished = WHITEHEAT_CMD_COMPLETE;
+@@ -1002,38 +996,38 @@ static void command_port_read_callback(struct urb *urb)
+ wake_up(&command_info->wait_command);
+ } else if (data[0] == WHITEHEAT_EVENT) {
+ /* These are unsolicited reports from the firmware, hence no waiting command to wakeup */
+- dbg("%s - event received", __FUNCTION__);
++ dbg("%s - event received", __func__);
+ } else if (data[0] == WHITEHEAT_GET_DTR_RTS) {
+ memcpy(command_info->result_buffer, &data[1], urb->actual_length - 1);
+ command_info->command_finished = WHITEHEAT_CMD_COMPLETE;
+ wake_up(&command_info->wait_command);
+ } else {
+- dbg("%s - bad reply from firmware", __FUNCTION__);
++ dbg("%s - bad reply from firmware", __func__);
+ }
+
+ /* Continue trying to always read */
+ command_port->read_urb->dev = command_port->serial->dev;
+ result = usb_submit_urb(command_port->read_urb, GFP_ATOMIC);
+ if (result)
+- dbg("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
++ dbg("%s - failed resubmitting read urb, error %d", __func__, result);
+ }
+
+
+ static void whiteheat_read_callback(struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct whiteheat_urb_wrap *wrap;
+ unsigned char *data = urb->transfer_buffer;
+ struct whiteheat_private *info = usb_get_serial_port_data(port);
+ int status = urb->status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock(&info->lock);
+ wrap = urb_to_wrap(urb, &info->rx_urbs_submitted);
+ if (!wrap) {
+ spin_unlock(&info->lock);
+- err("%s - Not my urb!", __FUNCTION__);
++ err("%s - Not my urb!", __func__);
+ return;
+ }
+ list_del(&wrap->list);
+@@ -1041,14 +1035,14 @@ static void whiteheat_read_callback(struct urb *urb)
+
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ spin_lock(&info->lock);
+ list_add(&wrap->list, &info->rx_urbs_free);
+ spin_unlock(&info->lock);
+ return;
+ }
+
+- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
++ usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+
+ spin_lock(&info->lock);
+ list_add_tail(&wrap->list, &info->rx_urb_q);
+@@ -1065,18 +1059,18 @@ static void whiteheat_read_callback(struct urb *urb)
+
+ static void whiteheat_write_callback(struct urb *urb)
+ {
+- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial_port *port = urb->context;
+ struct whiteheat_private *info = usb_get_serial_port_data(port);
+ struct whiteheat_urb_wrap *wrap;
+ int status = urb->status;
+
+- dbg("%s - port %d", __FUNCTION__, port->number);
++ dbg("%s - port %d", __func__, port->number);
+
+ spin_lock(&info->lock);
+ wrap = urb_to_wrap(urb, &info->tx_urbs_submitted);
+ if (!wrap) {
+ spin_unlock(&info->lock);
+- err("%s - Not my urb!", __FUNCTION__);
++ err("%s - Not my urb!", __func__);
+ return;
+ }
+ list_move(&wrap->list, &info->tx_urbs_free);
+@@ -1084,7 +1078,7 @@ static void whiteheat_write_callback(struct urb *urb)
+
+ if (status) {
+ dbg("%s - nonzero write bulk status received: %d",
+- __FUNCTION__, status);
++ __func__, status);
+ return;
+ }
+
+@@ -1104,7 +1098,7 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *d
+ int retval = 0;
+ int t;
+
+- dbg("%s - command %d", __FUNCTION__, command);
++ dbg("%s - command %d", __func__, command);
+
+ command_port = port->serial->port[COMMAND_PORT];
+ command_info = usb_get_serial_port_data(command_port);
+@@ -1118,7 +1112,7 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *d
+ command_port->write_urb->dev = port->serial->dev;
+ retval = usb_submit_urb (command_port->write_urb, GFP_NOIO);
+ if (retval) {
+- dbg("%s - submit urb failed", __FUNCTION__);
++ dbg("%s - submit urb failed", __func__);
+ goto exit;
+ }
+
+@@ -1129,19 +1123,19 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *d
+ usb_kill_urb(command_port->write_urb);
+
+ if (command_info->command_finished == false) {
+- dbg("%s - command timed out.", __FUNCTION__);
++ dbg("%s - command timed out.", __func__);
+ retval = -ETIMEDOUT;
+ goto exit;
+ }
+
+ if (command_info->command_finished == WHITEHEAT_CMD_FAILURE) {
+- dbg("%s - command failed.", __FUNCTION__);
++ dbg("%s - command failed.", __func__);
+ retval = -EIO;
+ goto exit;
+ }
+
+ if (command_info->command_finished == WHITEHEAT_CMD_COMPLETE) {
+- dbg("%s - command completed.", __FUNCTION__);
++ dbg("%s - command completed.", __func__);
+ switch (command) {
+ case WHITEHEAT_GET_DTR_RTS:
+ info = usb_get_serial_port_data(port);
+@@ -1186,7 +1180,7 @@ static int firm_setup_port(struct usb_serial_port *port) {
+ default:
+ case CS8: port_settings.bits = 8; break;
+ }
+- dbg("%s - data bits = %d", __FUNCTION__, port_settings.bits);
++ dbg("%s - data bits = %d", __func__, port_settings.bits);
+
+ /* determine the parity */
+ if (cflag & PARENB)
+@@ -1202,21 +1196,21 @@ static int firm_setup_port(struct usb_serial_port *port) {
+ port_settings.parity = WHITEHEAT_PAR_EVEN;
+ else
+ port_settings.parity = WHITEHEAT_PAR_NONE;
+- dbg("%s - parity = %c", __FUNCTION__, port_settings.parity);
++ dbg("%s - parity = %c", __func__, port_settings.parity);
+
+ /* figure out the stop bits requested */
+ if (cflag & CSTOPB)
+ port_settings.stop = 2;
+ else
+ port_settings.stop = 1;
+- dbg("%s - stop bits = %d", __FUNCTION__, port_settings.stop);
++ dbg("%s - stop bits = %d", __func__, port_settings.stop);
+
+ /* figure out the flow control settings */
+ if (cflag & CRTSCTS)
+ port_settings.hflow = (WHITEHEAT_HFLOW_CTS | WHITEHEAT_HFLOW_RTS);
+ else
+ port_settings.hflow = WHITEHEAT_HFLOW_NONE;
+- dbg("%s - hardware flow control = %s %s %s %s", __FUNCTION__,
++ dbg("%s - hardware flow control = %s %s %s %s", __func__,
+ (port_settings.hflow & WHITEHEAT_HFLOW_CTS) ? "CTS" : "",
+ (port_settings.hflow & WHITEHEAT_HFLOW_RTS) ? "RTS" : "",
+ (port_settings.hflow & WHITEHEAT_HFLOW_DSR) ? "DSR" : "",
+@@ -1227,15 +1221,15 @@ static int firm_setup_port(struct usb_serial_port *port) {
+ port_settings.sflow = WHITEHEAT_SFLOW_RXTX;
+ else
+ port_settings.sflow = WHITEHEAT_SFLOW_NONE;
+- dbg("%s - software flow control = %c", __FUNCTION__, port_settings.sflow);
++ dbg("%s - software flow control = %c", __func__, port_settings.sflow);
+
+ port_settings.xon = START_CHAR(port->tty);
+ port_settings.xoff = STOP_CHAR(port->tty);
+- dbg("%s - XON = %2x, XOFF = %2x", __FUNCTION__, port_settings.xon, port_settings.xoff);
++ dbg("%s - XON = %2x, XOFF = %2x", __func__, port_settings.xon, port_settings.xoff);
+
+ /* get the baud rate wanted */
+ port_settings.baud = tty_get_baud_rate(port->tty);
+- dbg("%s - baud rate = %d", __FUNCTION__, port_settings.baud);
++ dbg("%s - baud rate = %d", __func__, port_settings.baud);
+
+ /* fixme: should set validated settings */
+ tty_encode_baud_rate(port->tty, port_settings.baud, port_settings.baud);
+@@ -1318,7 +1312,7 @@ static int start_command_port(struct usb_serial *serial)
+ command_port->read_urb->dev = serial->dev;
+ retval = usb_submit_urb(command_port->read_urb, GFP_KERNEL);
+ if (retval) {
+- err("%s - failed submitting read urb, error %d", __FUNCTION__, retval);
++ err("%s - failed submitting read urb, error %d", __func__, retval);
+ goto exit;
+ }
+ }
+@@ -1454,7 +1448,7 @@ static void rx_data_softint(struct work_struct *work)
+ urb->dev = port->serial->dev;
+ result = usb_submit_urb(urb, GFP_ATOMIC);
+ if (result) {
+- err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
++ err("%s - failed resubmitting read urb, error %d", __func__, result);
+ spin_lock_irqsave(&info->lock, flags);
+ list_add(tmp, &info->rx_urbs_free);
+ continue;
+diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
+index 7e53333..0f6d234 100644
+--- a/drivers/usb/storage/Kconfig
++++ b/drivers/usb/storage/Kconfig
+@@ -32,8 +32,8 @@ config USB_STORAGE_DEBUG
+ verbose debugging messages.
+
+ config USB_STORAGE_DATAFAB
+- bool "Datafab Compact Flash Reader support (EXPERIMENTAL)"
+- depends on USB_STORAGE && EXPERIMENTAL
++ bool "Datafab Compact Flash Reader support"
++ depends on USB_STORAGE
+ help
+ Support for certain Datafab CompactFlash readers.
+ Datafab has a web page at <http://www.datafabusa.com/>.
+@@ -69,8 +69,8 @@ config USB_STORAGE_DPCM
+ There is a web page at <http://www.ziocorp.com/products/>.
+
+ config USB_STORAGE_USBAT
+- bool "USBAT/USBAT02-based storage support (EXPERIMENTAL)"
+- depends on USB_STORAGE && EXPERIMENTAL
++ bool "USBAT/USBAT02-based storage support"
++ depends on USB_STORAGE
+ help
+ Say Y here to include additional code to support storage devices
+ based on the SCM/Shuttle USBAT/USBAT02 processors.
+@@ -90,30 +90,30 @@ config USB_STORAGE_USBAT
+ - Sandisk ImageMate SDDR-05b
+
+ config USB_STORAGE_SDDR09
+- bool "SanDisk SDDR-09 (and other SmartMedia) support (EXPERIMENTAL)"
+- depends on USB_STORAGE && EXPERIMENTAL
++ bool "SanDisk SDDR-09 (and other SmartMedia) support"
++ depends on USB_STORAGE
+ help
+ Say Y here to include additional code to support the Sandisk SDDR-09
+ SmartMedia reader in the USB Mass Storage driver.
+ Also works for the Microtech Zio! SmartMedia reader.
+
+ config USB_STORAGE_SDDR55
+- bool "SanDisk SDDR-55 SmartMedia support (EXPERIMENTAL)"
+- depends on USB_STORAGE && EXPERIMENTAL
++ bool "SanDisk SDDR-55 SmartMedia support"
++ depends on USB_STORAGE
+ help
+ Say Y here to include additional code to support the Sandisk SDDR-55
+ SmartMedia reader in the USB Mass Storage driver.
+
+ config USB_STORAGE_JUMPSHOT
+- bool "Lexar Jumpshot Compact Flash Reader (EXPERIMENTAL)"
+- depends on USB_STORAGE && EXPERIMENTAL
++ bool "Lexar Jumpshot Compact Flash Reader"
++ depends on USB_STORAGE
+ help
+ Say Y here to include additional code to support the Lexar Jumpshot
+ USB CompactFlash reader.
+
+ config USB_STORAGE_ALAUDA
+- bool "Olympus MAUSB-10/Fuji DPC-R1 support (EXPERIMENTAL)"
+- depends on USB_STORAGE && EXPERIMENTAL
++ bool "Olympus MAUSB-10/Fuji DPC-R1 support"
++ depends on USB_STORAGE
+ help
+ Say Y here to include additional code to support the Olympus MAUSB-10
+ and Fujifilm DPC-R1 USB Card reader/writer devices.
+@@ -122,8 +122,8 @@ config USB_STORAGE_ALAUDA
+ XD and SmartMedia cards.
+
+ config USB_STORAGE_ONETOUCH
+- bool "Support OneTouch Button on Maxtor Hard Drives (EXPERIMENTAL)"
+- depends on USB_STORAGE && INPUT_EVDEV && EXPERIMENTAL && !PM
++ bool "Support OneTouch Button on Maxtor Hard Drives"
++ depends on USB_STORAGE && INPUT_EVDEV
+ help
+ Say Y here to include additional code to support the Maxtor OneTouch
+ USB hard drive's onetouch button.
+@@ -145,6 +145,17 @@ config USB_STORAGE_KARMA
+ on the resulting scsi device node returns the Karma to normal
+ operation.
+
++config USB_STORAGE_CYPRESS_ATACB
++ bool "SAT emulation on Cypress USB/ATA Bridge with ATACB"
++ depends on USB_STORAGE
++ ---help---
++ Say Y here if you want to use SAT (ata pass through) on devices based
++ on the Cypress USB/ATA bridge supporting ATACB. This will allow you
++ to use tools to tune and monitor your drive (like hdparm or smartctl).
++
++ If you say no here your device will still work with the standard usb
++ mass storage class.
++
+ config USB_LIBUSUAL
+ bool "The shared table of common (or usual) storage devices"
+ depends on USB
+diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
+index 023969b..4c596c7 100644
+--- a/drivers/usb/storage/Makefile
++++ b/drivers/usb/storage/Makefile
+@@ -21,6 +21,7 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o
+ usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA) += karma.o
++usb-storage-obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += cypress_atacb.o
+
+ usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \
+ initializers.o $(usb-storage-obj-y)
+diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c
+new file mode 100644
+index 0000000..d88824b
+--- /dev/null
++++ b/drivers/usb/storage/cypress_atacb.c
+@@ -0,0 +1,200 @@
++/*
++ * Support for emulating SAT (ata pass through) on devices based
++ * on the Cypress USB/ATA bridge supporting ATACB.
++ *
++ * Copyright (c) 2008 Matthieu Castet (castet.matthieu at free.fr)
++ *
++ * 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, or (at your option) any
++ * later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <scsi/scsi.h>
++#include <scsi/scsi_cmnd.h>
++#include <scsi/scsi_eh.h>
++#include <linux/ata.h>
++
++#include "usb.h"
++#include "protocol.h"
++#include "scsiglue.h"
++#include "debug.h"
++
++/*
++ * ATACB is a protocol used on cypress usb<->ata bridge to
++ * send raw ATA command over mass storage
++ * There is a ATACB2 protocol that support LBA48 on newer chip.
++ * More info that be found on cy7c68310_8.pdf and cy7c68300c_8.pdf
++ * datasheet from cypress.com.
++ */
++void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us)
++{
++ unsigned char save_cmnd[MAX_COMMAND_SIZE];
++
++ if (likely(srb->cmnd[0] != ATA_16 && srb->cmnd[0] != ATA_12)) {
++ usb_stor_transparent_scsi_command(srb, us);
++ return;
++ }
++
++ memcpy(save_cmnd, srb->cmnd, sizeof(save_cmnd));
++ memset(srb->cmnd, 0, sizeof(srb->cmnd));
++
++ /* check if we support the command */
++ if (save_cmnd[1] >> 5) /* MULTIPLE_COUNT */
++ goto invalid_fld;
++ /* check protocol */
++ switch((save_cmnd[1] >> 1) & 0xf) {
++ case 3: /*no DATA */
++ case 4: /* PIO in */
++ case 5: /* PIO out */
++ break;
++ default:
++ goto invalid_fld;
++ }
++
++ /* first build the ATACB command */
++ srb->cmd_len = 16;
++
++ srb->cmnd[0] = 0x24; /* bVSCBSignature : vendor-specific command
++ this value can change, but most(all ?) manufacturers
++ keep the cypress default : 0x24 */
++ srb->cmnd[1] = 0x24; /* bVSCBSubCommand : 0x24 for ATACB */
++
++ srb->cmnd[3] = 0xff - 1; /* features, sector count, lba low, lba med
++ lba high, device, command are valid */
++ srb->cmnd[4] = 1; /* TransferBlockCount : 512 */
++
++ if (save_cmnd[0] == ATA_16) {
++ srb->cmnd[ 6] = save_cmnd[ 4]; /* features */
++ srb->cmnd[ 7] = save_cmnd[ 6]; /* sector count */
++ srb->cmnd[ 8] = save_cmnd[ 8]; /* lba low */
++ srb->cmnd[ 9] = save_cmnd[10]; /* lba med */
++ srb->cmnd[10] = save_cmnd[12]; /* lba high */
++ srb->cmnd[11] = save_cmnd[13]; /* device */
++ srb->cmnd[12] = save_cmnd[14]; /* command */
++
++ if (save_cmnd[1] & 0x01) {/* extended bit set for LBA48 */
++ /* this could be supported by atacb2 */
++ if (save_cmnd[3] || save_cmnd[5] || save_cmnd[7] || save_cmnd[9]
++ || save_cmnd[11])
++ goto invalid_fld;
++ }
++ }
++ else { /* ATA12 */
++ srb->cmnd[ 6] = save_cmnd[3]; /* features */
++ srb->cmnd[ 7] = save_cmnd[4]; /* sector count */
++ srb->cmnd[ 8] = save_cmnd[5]; /* lba low */
++ srb->cmnd[ 9] = save_cmnd[6]; /* lba med */
++ srb->cmnd[10] = save_cmnd[7]; /* lba high */
++ srb->cmnd[11] = save_cmnd[8]; /* device */
++ srb->cmnd[12] = save_cmnd[9]; /* command */
++
++ }
++ /* Filter SET_FEATURES - XFER MODE command */
++ if ((srb->cmnd[12] == ATA_CMD_SET_FEATURES)
++ && (srb->cmnd[6] == SETFEATURES_XFER))
++ goto invalid_fld;
++
++ if (srb->cmnd[12] == ATA_CMD_ID_ATA || srb->cmnd[12] == ATA_CMD_ID_ATAPI)
++ srb->cmnd[2] |= (1<<7); /* set IdentifyPacketDevice for these cmds */
++
++
++ usb_stor_transparent_scsi_command(srb, us);
++
++ /* if the device doesn't support ATACB
++ */
++ if (srb->result == SAM_STAT_CHECK_CONDITION &&
++ memcmp(srb->sense_buffer, usb_stor_sense_invalidCDB,
++ sizeof(usb_stor_sense_invalidCDB)) == 0) {
++ US_DEBUGP("cypress atacb not supported ???\n");
++ goto end;
++ }
++
++ /* if ck_cond flags is set, and there wasn't critical error,
++ * build the special sense
++ */
++ if ((srb->result != (DID_ERROR << 16) &&
++ srb->result != (DID_ABORT << 16)) &&
++ save_cmnd[2] & 0x20) {
++ struct scsi_eh_save ses;
++ unsigned char regs[8];
++ unsigned char *sb = srb->sense_buffer;
++ unsigned char *desc = sb + 8;
++ int tmp_result;
++
++ /* build the command for
++ * reading the ATA registers */
++ scsi_eh_prep_cmnd(srb, &ses, NULL, 0, 0);
++ srb->sdb.length = sizeof(regs);
++ sg_init_one(&ses.sense_sgl, regs, srb->sdb.length);
++ srb->sdb.table.sgl = &ses.sense_sgl;
++ srb->sc_data_direction = DMA_FROM_DEVICE;
++ srb->sdb.table.nents = 1;
++ /* we use the same command as before, but we set
++ * the read taskfile bit, for not executing atacb command,
++ * but reading register selected in srb->cmnd[4]
++ */
++ srb->cmnd[2] = 1;
++
++ usb_stor_transparent_scsi_command(srb, us);
++ tmp_result = srb->result;
++ scsi_eh_restore_cmnd(srb, &ses);
++ /* we fail to get registers, report invalid command */
++ if (tmp_result != SAM_STAT_GOOD)
++ goto invalid_fld;
++
++ /* build the sense */
++ memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
++
++ /* set sk, asc for a good command */
++ sb[1] = RECOVERED_ERROR;
++ sb[2] = 0; /* ATA PASS THROUGH INFORMATION AVAILABLE */
++ sb[3] = 0x1D;
++
++ /* XXX we should generate sk, asc, ascq from status and error
++ * regs
++ * (see 11.1 Error translation ATA device error to SCSI error map)
++ * and ata_to_sense_error from libata.
++ */
++
++ /* Sense data is current and format is descriptor. */
++ sb[0] = 0x72;
++ desc[0] = 0x09; /* ATA_RETURN_DESCRIPTOR */
++
++ /* set length of additional sense data */
++ sb[7] = 14;
++ desc[1] = 12;
++
++ /* Copy registers into sense buffer. */
++ desc[ 2] = 0x00;
++ desc[ 3] = regs[1]; /* features */
++ desc[ 5] = regs[2]; /* sector count */
++ desc[ 7] = regs[3]; /* lba low */
++ desc[ 9] = regs[4]; /* lba med */
++ desc[11] = regs[5]; /* lba high */
++ desc[12] = regs[6]; /* device */
++ desc[13] = regs[7]; /* command */
++
++ srb->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
++ }
++ goto end;
++invalid_fld:
++ srb->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
++
++ memcpy(srb->sense_buffer,
++ usb_stor_sense_invalidCDB,
++ sizeof(usb_stor_sense_invalidCDB));
++end:
++ memcpy(srb->cmnd, save_cmnd, sizeof(save_cmnd));
++ if (srb->cmnd[0] == ATA_12)
++ srb->cmd_len = 12;
++}
+diff --git a/drivers/usb/storage/cypress_atacb.h b/drivers/usb/storage/cypress_atacb.h
+new file mode 100644
+index 0000000..fbada89
+--- /dev/null
++++ b/drivers/usb/storage/cypress_atacb.h
+@@ -0,0 +1,25 @@
++/*
++ * Support for emulating SAT (ata pass through) on devices based
++ * on the Cypress USB/ATA bridge supporting ATACB.
++ *
++ * Copyright (c) 2008 Matthieu Castet (castet.matthieu at free.fr)
++ *
++ * 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, or (at your option) any
++ * later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef _CYPRESS_ATACB_H_
++#define _CYPRESS_ATACB_H_
++extern void cypress_atacb_passthrough(struct scsi_cmnd*, struct us_data*);
++#endif
+diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c
+index 55b9520..a28d491 100644
+--- a/drivers/usb/storage/libusual.c
++++ b/drivers/usb/storage/libusual.c
+@@ -9,6 +9,7 @@
+ #include <linux/usb_usual.h>
+ #include <linux/vmalloc.h>
+ #include <linux/kthread.h>
++#include <linux/mutex.h>
+
+ /*
+ */
+@@ -30,7 +31,7 @@ static atomic_t usu_bias = ATOMIC_INIT(USB_US_DEFAULT_BIAS);
+ #define BIAS_NAME_SIZE (sizeof("usb-storage"))
+ static const char *bias_names[3] = { "none", "usb-storage", "ub" };
+
+-static struct semaphore usu_init_notify;
++static DEFINE_MUTEX(usu_probe_mutex);
+ static DECLARE_COMPLETION(usu_end_notify);
+ static atomic_t total_threads = ATOMIC_INIT(0);
+
+@@ -178,10 +179,7 @@ static int usu_probe_thread(void *arg)
+ int rc;
+ unsigned long flags;
+
+- /* A completion does not work here because it's counted. */
+- down(&usu_init_notify);
+- up(&usu_init_notify);
+-
++ mutex_lock(&usu_probe_mutex);
+ rc = request_module(bias_names[type]);
+ spin_lock_irqsave(&usu_lock, flags);
+ if (rc == 0 && (st->fls & USU_MOD_FL_PRESENT) == 0) {
+@@ -194,6 +192,7 @@ static int usu_probe_thread(void *arg)
+ }
+ st->fls &= ~USU_MOD_FL_THREAD;
+ spin_unlock_irqrestore(&usu_lock, flags);
++ mutex_unlock(&usu_probe_mutex);
+
+ complete_and_exit(&usu_end_notify, 0);
+ }
+@@ -204,10 +203,9 @@ static int __init usb_usual_init(void)
+ {
+ int rc;
+
+- sema_init(&usu_init_notify, 0);
+-
++ mutex_lock(&usu_probe_mutex);
+ rc = usb_register(&usu_driver);
+- up(&usu_init_notify);
++ mutex_unlock(&usu_probe_mutex);
+ return rc;
+ }
+
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index 8c1e295..3fcde9f 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -73,6 +73,7 @@ static const char* host_info(struct Scsi_Host *host)
+ static int slave_alloc (struct scsi_device *sdev)
+ {
+ struct us_data *us = host_to_us(sdev->host);
++ struct usb_host_endpoint *bulk_in_ep;
+
+ /*
+ * Set the INQUIRY transfer length to 36. We don't use any of
+@@ -84,12 +85,13 @@ static int slave_alloc (struct scsi_device *sdev)
+ /* Scatter-gather buffers (all but the last) must have a length
+ * divisible by the bulk maxpacket size. Otherwise a data packet
+ * would end up being short, causing a premature end to the data
+- * transfer. Since high-speed bulk pipes have a maxpacket size
+- * of 512, we'll use that as the scsi device queue's DMA alignment
+- * mask. Guaranteeing proper alignment of the first buffer will
+- * have the desired effect because, except at the beginning and
+- * the end, scatter-gather buffers follow page boundaries. */
+- blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
++ * transfer. We'll use the maxpacket value of the bulk-IN pipe
++ * to set the SCSI device queue's DMA alignment mask.
++ */
++ bulk_in_ep = us->pusb_dev->ep_in[usb_pipeendpoint(us->recv_bulk_pipe)];
++ blk_queue_update_dma_alignment(sdev->request_queue,
++ le16_to_cpu(bulk_in_ep->desc.wMaxPacketSize) - 1);
++ /* wMaxPacketSize must be a power of 2 */
+
+ /*
+ * The UFI spec treates the Peripheral Qualifier bits in an
+@@ -132,7 +134,7 @@ static int slave_configure(struct scsi_device *sdev)
+ /* Disk-type devices use MODE SENSE(6) if the protocol
+ * (SubClass) is Transparent SCSI, otherwise they use
+ * MODE SENSE(10). */
+- if (us->subclass != US_SC_SCSI)
++ if (us->subclass != US_SC_SCSI && us->subclass != US_SC_CYP_ATACB)
+ sdev->use_10_for_ms = 1;
+
+ /* Many disks only accept MODE SENSE transfer lengths of
+@@ -226,12 +228,12 @@ static int queuecommand(struct scsi_cmnd *srb,
+ {
+ struct us_data *us = host_to_us(srb->device->host);
+
+- US_DEBUGP("%s called\n", __FUNCTION__);
++ US_DEBUGP("%s called\n", __func__);
+
+ /* check for state-transition errors */
+ if (us->srb != NULL) {
+ printk(KERN_ERR USB_STORAGE "Error in %s: us->srb = %p\n",
+- __FUNCTION__, us->srb);
++ __func__, us->srb);
+ return SCSI_MLQUEUE_HOST_BUSY;
+ }
+
+@@ -260,7 +262,7 @@ static int command_abort(struct scsi_cmnd *srb)
+ {
+ struct us_data *us = host_to_us(srb->device->host);
+
+- US_DEBUGP("%s called\n", __FUNCTION__);
++ US_DEBUGP("%s called\n", __func__);
+
+ /* us->srb together with the TIMED_OUT, RESETTING, and ABORTING
+ * bits are protected by the host lock. */
+@@ -297,7 +299,7 @@ static int device_reset(struct scsi_cmnd *srb)
+ struct us_data *us = host_to_us(srb->device->host);
+ int result;
+
+- US_DEBUGP("%s called\n", __FUNCTION__);
++ US_DEBUGP("%s called\n", __func__);
+
+ /* lock the device pointers and do the reset */
+ mutex_lock(&(us->dev_mutex));
+@@ -313,7 +315,7 @@ static int bus_reset(struct scsi_cmnd *srb)
+ struct us_data *us = host_to_us(srb->device->host);
+ int result;
+
+- US_DEBUGP("%s called\n", __FUNCTION__);
++ US_DEBUGP("%s called\n", __func__);
+ result = usb_stor_port_reset(us);
+ return result < 0 ? FAILED : SUCCESS;
+ }
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index bdd4334..6610d2d 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -110,7 +110,7 @@
+ */
+ static void usb_stor_blocking_completion(struct urb *urb)
+ {
+- struct completion *urb_done_ptr = (struct completion *)urb->context;
++ struct completion *urb_done_ptr = urb->context;
+
+ complete(urb_done_ptr);
+ }
+@@ -198,7 +198,7 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
+ int status;
+
+ US_DEBUGP("%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",
+- __FUNCTION__, request, requesttype,
++ __func__, request, requesttype,
+ value, index, size);
+
+ /* fill in the devrequest structure */
+@@ -250,7 +250,7 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
+ usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe),
+ usb_pipeout(pipe), 0);
+
+- US_DEBUGP("%s: result = %d\n", __FUNCTION__, result);
++ US_DEBUGP("%s: result = %d\n", __func__, result);
+ return result;
+ }
+
+@@ -332,7 +332,7 @@ int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
+ int result;
+
+ US_DEBUGP("%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",
+- __FUNCTION__, request, requesttype,
++ __func__, request, requesttype,
+ value, index, size);
+
+ /* fill in the devrequest structure */
+@@ -366,7 +366,7 @@ static int usb_stor_intr_transfer(struct us_data *us, void *buf,
+ unsigned int pipe = us->recv_intr_pipe;
+ unsigned int maxp;
+
+- US_DEBUGP("%s: xfer %u bytes\n", __FUNCTION__, length);
++ US_DEBUGP("%s: xfer %u bytes\n", __func__, length);
+
+ /* calculate the max packet size */
+ maxp = usb_maxpacket(us->pusb_dev, pipe, usb_pipeout(pipe));
+@@ -393,7 +393,7 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
+ {
+ int result;
+
+- US_DEBUGP("%s: xfer %u bytes\n", __FUNCTION__, length);
++ US_DEBUGP("%s: xfer %u bytes\n", __func__, length);
+
+ /* fill and submit the URB */
+ usb_fill_bulk_urb(us->current_urb, us->pusb_dev, pipe, buf, length,
+@@ -424,7 +424,7 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
+ return USB_STOR_XFER_ERROR;
+
+ /* initialize the scatter-gather request block */
+- US_DEBUGP("%s: xfer %u bytes, %d entries\n", __FUNCTION__,
++ US_DEBUGP("%s: xfer %u bytes, %d entries\n", __func__,
+ length, num_sg);
+ result = usb_sg_init(&us->current_sg, us->pusb_dev, pipe, 0,
+ sg, num_sg, length, GFP_NOIO);
+@@ -603,7 +603,8 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ scsi_eh_prep_cmnd(srb, &ses, NULL, 0, US_SENSE_SIZE);
+
+ /* FIXME: we must do the protocol translation here */
+- if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI)
++ if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI ||
++ us->subclass == US_SC_CYP_ATACB)
+ srb->cmd_len = 6;
+ else
+ srb->cmd_len = 12;
+@@ -700,7 +701,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
+ /* Stop the current URB transfer */
+ void usb_stor_stop_transport(struct us_data *us)
+ {
+- US_DEBUGP("%s called\n", __FUNCTION__);
++ US_DEBUGP("%s called\n", __func__);
+
+ /* If the state machine is blocked waiting for an URB,
+ * let's wake it up. The test_and_clear_bit() call
+@@ -1134,7 +1135,7 @@ static int usb_stor_reset_common(struct us_data *us,
+
+ int usb_stor_CB_reset(struct us_data *us)
+ {
+- US_DEBUGP("%s called\n", __FUNCTION__);
++ US_DEBUGP("%s called\n", __func__);
+
+ memset(us->iobuf, 0xFF, CB_RESET_CMD_SIZE);
+ us->iobuf[0] = SEND_DIAGNOSTIC;
+@@ -1149,7 +1150,7 @@ int usb_stor_CB_reset(struct us_data *us)
+ */
+ int usb_stor_Bulk_reset(struct us_data *us)
+ {
+- US_DEBUGP("%s called\n", __FUNCTION__);
++ US_DEBUGP("%s called\n", __func__);
+
+ return usb_stor_reset_common(us, US_BULK_RESET_REQUEST,
+ USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index 9125207..732bf52 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -1719,6 +1719,14 @@ UNUSUAL_DEV( 0xed06, 0x4500, 0x0001, 0x0001,
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_CAPACITY_HEURISTICS),
+
++#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB
++UNUSUAL_DEV( 0x04b4, 0x6830, 0x0000, 0x9999,
++ "Cypress",
++ "Cypress AT2LP",
++ US_SC_CYP_ATACB, US_PR_BULK, NULL,
++ 0),
++#endif
++
+ /* Control/Bulk transport for all SubClass values */
+ USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR),
+ USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR),
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index ac6114e..a856eff 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -101,6 +101,9 @@
+ #ifdef CONFIG_USB_STORAGE_KARMA
+ #include "karma.h"
+ #endif
++#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB
++#include "cypress_atacb.h"
++#endif
+
+ /* Some informational data */
+ MODULE_AUTHOR("Matthew Dharm <mdharm-usb at one-eyed-alien.net>");
+@@ -187,7 +190,7 @@ static int storage_suspend(struct usb_interface *iface, pm_message_t message)
+ /* Wait until no command is running */
+ mutex_lock(&us->dev_mutex);
+
+- US_DEBUGP("%s\n", __FUNCTION__);
++ US_DEBUGP("%s\n", __func__);
+ if (us->suspend_resume_hook)
+ (us->suspend_resume_hook)(us, US_SUSPEND);
+
+@@ -204,7 +207,7 @@ static int storage_resume(struct usb_interface *iface)
+
+ mutex_lock(&us->dev_mutex);
+
+- US_DEBUGP("%s\n", __FUNCTION__);
++ US_DEBUGP("%s\n", __func__);
+ if (us->suspend_resume_hook)
+ (us->suspend_resume_hook)(us, US_RESUME);
+
+@@ -216,7 +219,7 @@ static int storage_reset_resume(struct usb_interface *iface)
+ {
+ struct us_data *us = usb_get_intfdata(iface);
+
+- US_DEBUGP("%s\n", __FUNCTION__);
++ US_DEBUGP("%s\n", __func__);
+
+ /* Report the reset to the SCSI core */
+ usb_stor_report_bus_reset(us);
+@@ -237,7 +240,7 @@ static int storage_pre_reset(struct usb_interface *iface)
+ {
+ struct us_data *us = usb_get_intfdata(iface);
+
+- US_DEBUGP("%s\n", __FUNCTION__);
++ US_DEBUGP("%s\n", __func__);
+
+ /* Make sure no command runs during the reset */
+ mutex_lock(&us->dev_mutex);
+@@ -248,7 +251,7 @@ static int storage_post_reset(struct usb_interface *iface)
+ {
+ struct us_data *us = usb_get_intfdata(iface);
+
+- US_DEBUGP("%s\n", __FUNCTION__);
++ US_DEBUGP("%s\n", __func__);
+
+ /* Report the reset to the SCSI core */
+ usb_stor_report_bus_reset(us);
+@@ -434,7 +437,7 @@ SkipForAbort:
+ /* Associate our private data with the USB device */
+ static int associate_dev(struct us_data *us, struct usb_interface *intf)
+ {
+- US_DEBUGP("-- %s\n", __FUNCTION__);
++ US_DEBUGP("-- %s\n", __func__);
+
+ /* Fill in the device-related fields */
+ us->pusb_dev = interface_to_usbdev(intf);
+@@ -708,6 +711,13 @@ static int get_protocol(struct us_data *us)
+ break;
+ #endif
+
++#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB
++ case US_SC_CYP_ATACB:
++ us->protocol_name = "Transparent SCSI with Cypress ATACB";
++ us->proto_handler = cypress_atacb_passthrough;
++ break;
++#endif
++
+ default:
+ return -EIO;
+ }
+@@ -806,7 +816,7 @@ static int usb_stor_acquire_resources(struct us_data *us)
+ /* Release all our dynamic resources */
+ static void usb_stor_release_resources(struct us_data *us)
+ {
+- US_DEBUGP("-- %s\n", __FUNCTION__);
++ US_DEBUGP("-- %s\n", __func__);
+
+ /* Tell the control thread to exit. The SCSI host must
+ * already have been removed so it won't try to queue
+@@ -832,7 +842,7 @@ static void usb_stor_release_resources(struct us_data *us)
+ /* Dissociate from the USB device */
+ static void dissociate_dev(struct us_data *us)
+ {
+- US_DEBUGP("-- %s\n", __FUNCTION__);
++ US_DEBUGP("-- %s\n", __func__);
+
+ kfree(us->sensebuf);
+
+diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
+index c815a40..be76084 100644
+--- a/drivers/usb/usb-skeleton.c
++++ b/drivers/usb/usb-skeleton.c
+@@ -88,7 +88,7 @@ static int skel_open(struct inode *inode, struct file *file)
+ interface = usb_find_interface(&skel_driver, subminor);
+ if (!interface) {
+ err ("%s - error, can't find device for minor %d",
+- __FUNCTION__, subminor);
++ __func__, subminor);
+ retval = -ENODEV;
+ goto exit;
+ }
+@@ -212,7 +212,7 @@ static void skel_write_bulk_callback(struct urb *urb)
+ {
+ struct usb_skel *dev;
+
+- dev = (struct usb_skel *)urb->context;
++ dev = urb->context;
+
+ /* sync/async unlink faults aren't errors */
+ if (urb->status) {
+@@ -220,7 +220,7 @@ static void skel_write_bulk_callback(struct urb *urb)
+ urb->status == -ECONNRESET ||
+ urb->status == -ESHUTDOWN))
+ err("%s - nonzero write bulk status received: %d",
+- __FUNCTION__, urb->status);
++ __func__, urb->status);
+
+ spin_lock(&dev->err_lock);
+ dev->errors = urb->status;
+@@ -301,7 +301,7 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
+ retval = usb_submit_urb(urb, GFP_KERNEL);
+ mutex_unlock(&dev->io_mutex);
+ if (retval) {
+- err("%s - failed submitting write urb, error %d", __FUNCTION__, retval);
++ err("%s - failed submitting write urb, error %d", __func__, retval);
+ goto error_unanchor;
+ }
+
+diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
+index 1bd5fb3..e3dc8f8 100644
+--- a/drivers/video/Kconfig
++++ b/drivers/video/Kconfig
+@@ -1930,6 +1930,20 @@ config FB_VIRTUAL
+
+ If unsure, say N.
+
++config XEN_FBDEV_FRONTEND
++ tristate "Xen virtual frame buffer support"
++ depends on FB && XEN
++ select FB_SYS_FILLRECT
++ select FB_SYS_COPYAREA
++ select FB_SYS_IMAGEBLIT
++ select FB_SYS_FOPS
++ select FB_DEFERRED_IO
++ default y
++ help
++ This driver implements the front-end of the Xen virtual
++ frame buffer driver. It communicates with a back-end
++ in another domain.
++
+ source "drivers/video/omap/Kconfig"
+
+ source "drivers/video/backlight/Kconfig"
+diff --git a/drivers/video/Makefile b/drivers/video/Makefile
+index 11c0e5e..f172b9b 100644
+--- a/drivers/video/Makefile
++++ b/drivers/video/Makefile
+@@ -114,6 +114,7 @@ obj-$(CONFIG_FB_PS3) += ps3fb.o
+ obj-$(CONFIG_FB_SM501) += sm501fb.o
+ obj-$(CONFIG_FB_XILINX) += xilinxfb.o
+ obj-$(CONFIG_FB_OMAP) += omap/
++obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o
+
+ # Platform or fallback drivers go here
+ obj-$(CONFIG_FB_UVESA) += uvesafb.o
+diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
+index 97facb1..7576519 100644
+--- a/drivers/video/pxafb.c
++++ b/drivers/video/pxafb.c
+@@ -45,6 +45,7 @@
+ #include <asm/irq.h>
+ #include <asm/div64.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/bitfield.h>
+ #include <asm/arch/pxafb.h>
+
+diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
+new file mode 100644
+index 0000000..619a6f8
+--- /dev/null
++++ b/drivers/video/xen-fbfront.c
+@@ -0,0 +1,550 @@
++/*
++ * Xen para-virtual frame buffer device
++ *
++ * Copyright (C) 2005-2006 Anthony Liguori <aliguori at us.ibm.com>
++ * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster <armbru at redhat.com>
++ *
++ * Based on linux/drivers/video/q40fb.c
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file COPYING in the main directory of this archive for
++ * more details.
++ */
++
++/*
++ * TODO:
++ *
++ * Switch to grant tables when they become capable of dealing with the
++ * frame buffer.
++ */
++
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/fb.h>
++#include <linux/module.h>
++#include <linux/vmalloc.h>
++#include <linux/mm.h>
++#include <asm/xen/hypervisor.h>
++#include <xen/events.h>
++#include <xen/page.h>
++#include <xen/interface/io/fbif.h>
++#include <xen/interface/io/protocols.h>
++#include <xen/xenbus.h>
++
++struct xenfb_info {
++ unsigned char *fb;
++ struct fb_info *fb_info;
++ int x1, y1, x2, y2; /* dirty rectangle,
++ protected by dirty_lock */
++ spinlock_t dirty_lock;
++ int nr_pages;
++ int irq;
++ struct xenfb_page *page;
++ unsigned long *mfns;
++ int update_wanted; /* XENFB_TYPE_UPDATE wanted */
++
++ struct xenbus_device *xbdev;
++};
++
++static u32 xenfb_mem_len = XENFB_WIDTH * XENFB_HEIGHT * XENFB_DEPTH / 8;
++
++static int xenfb_remove(struct xenbus_device *);
++static void xenfb_init_shared_page(struct xenfb_info *);
++static int xenfb_connect_backend(struct xenbus_device *, struct xenfb_info *);
++static void xenfb_disconnect_backend(struct xenfb_info *);
++
++static void xenfb_do_update(struct xenfb_info *info,
++ int x, int y, int w, int h)
++{
++ union xenfb_out_event event;
++ u32 prod;
++
++ event.type = XENFB_TYPE_UPDATE;
++ event.update.x = x;
++ event.update.y = y;
++ event.update.width = w;
++ event.update.height = h;
++
++ prod = info->page->out_prod;
++ /* caller ensures !xenfb_queue_full() */
++ mb(); /* ensure ring space available */
++ XENFB_OUT_RING_REF(info->page, prod) = event;
++ wmb(); /* ensure ring contents visible */
++ info->page->out_prod = prod + 1;
++
++ notify_remote_via_irq(info->irq);
++}
++
++static int xenfb_queue_full(struct xenfb_info *info)
++{
++ u32 cons, prod;
++
++ prod = info->page->out_prod;
++ cons = info->page->out_cons;
++ return prod - cons == XENFB_OUT_RING_LEN;
++}
++
++static void xenfb_refresh(struct xenfb_info *info,
++ int x1, int y1, int w, int h)
++{
++ unsigned long flags;
++ int y2 = y1 + h - 1;
++ int x2 = x1 + w - 1;
++
++ if (!info->update_wanted)
++ return;
++
++ spin_lock_irqsave(&info->dirty_lock, flags);
++
++ /* Combine with dirty rectangle: */
++ if (info->y1 < y1)
++ y1 = info->y1;
++ if (info->y2 > y2)
++ y2 = info->y2;
++ if (info->x1 < x1)
++ x1 = info->x1;
++ if (info->x2 > x2)
++ x2 = info->x2;
++
++ if (xenfb_queue_full(info)) {
++ /* Can't send right now, stash it in the dirty rectangle */
++ info->x1 = x1;
++ info->x2 = x2;
++ info->y1 = y1;
++ info->y2 = y2;
++ spin_unlock_irqrestore(&info->dirty_lock, flags);
++ return;
++ }
++
++ /* Clear dirty rectangle: */
++ info->x1 = info->y1 = INT_MAX;
++ info->x2 = info->y2 = 0;
++
++ spin_unlock_irqrestore(&info->dirty_lock, flags);
++
++ if (x1 <= x2 && y1 <= y2)
++ xenfb_do_update(info, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
++}
++
++static void xenfb_deferred_io(struct fb_info *fb_info,
++ struct list_head *pagelist)
++{
++ struct xenfb_info *info = fb_info->par;
++ struct page *page;
++ unsigned long beg, end;
++ int y1, y2, miny, maxy;
++
++ miny = INT_MAX;
++ maxy = 0;
++ list_for_each_entry(page, pagelist, lru) {
++ beg = page->index << PAGE_SHIFT;
++ end = beg + PAGE_SIZE - 1;
++ y1 = beg / fb_info->fix.line_length;
++ y2 = end / fb_info->fix.line_length;
++ if (y2 >= fb_info->var.yres)
++ y2 = fb_info->var.yres - 1;
++ if (miny > y1)
++ miny = y1;
++ if (maxy < y2)
++ maxy = y2;
++ }
++ xenfb_refresh(info, 0, miny, fb_info->var.xres, maxy - miny + 1);
++}
++
++static struct fb_deferred_io xenfb_defio = {
++ .delay = HZ / 20,
++ .deferred_io = xenfb_deferred_io,
++};
++
++static int xenfb_setcolreg(unsigned regno, unsigned red, unsigned green,
++ unsigned blue, unsigned transp,
++ struct fb_info *info)
++{
++ u32 v;
++
++ if (regno > info->cmap.len)
++ return 1;
++
++#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
++ red = CNVT_TOHW(red, info->var.red.length);
++ green = CNVT_TOHW(green, info->var.green.length);
++ blue = CNVT_TOHW(blue, info->var.blue.length);
++ transp = CNVT_TOHW(transp, info->var.transp.length);
++#undef CNVT_TOHW
++
++ v = (red << info->var.red.offset) |
++ (green << info->var.green.offset) |
++ (blue << info->var.blue.offset);
++
++ switch (info->var.bits_per_pixel) {
++ case 16:
++ case 24:
++ case 32:
++ ((u32 *)info->pseudo_palette)[regno] = v;
++ break;
++ }
++
++ return 0;
++}
++
++static void xenfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
++{
++ struct xenfb_info *info = p->par;
++
++ sys_fillrect(p, rect);
++ xenfb_refresh(info, rect->dx, rect->dy, rect->width, rect->height);
++}
++
++static void xenfb_imageblit(struct fb_info *p, const struct fb_image *image)
++{
++ struct xenfb_info *info = p->par;
++
++ sys_imageblit(p, image);
++ xenfb_refresh(info, image->dx, image->dy, image->width, image->height);
++}
++
++static void xenfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
++{
++ struct xenfb_info *info = p->par;
++
++ sys_copyarea(p, area);
++ xenfb_refresh(info, area->dx, area->dy, area->width, area->height);
++}
++
++static ssize_t xenfb_write(struct fb_info *p, const char __user *buf,
++ size_t count, loff_t *ppos)
++{
++ struct xenfb_info *info = p->par;
++ ssize_t res;
++
++ res = fb_sys_write(p, buf, count, ppos);
++ xenfb_refresh(info, 0, 0, info->page->width, info->page->height);
++ return res;
++}
++
++static struct fb_ops xenfb_fb_ops = {
++ .owner = THIS_MODULE,
++ .fb_read = fb_sys_read,
++ .fb_write = xenfb_write,
++ .fb_setcolreg = xenfb_setcolreg,
++ .fb_fillrect = xenfb_fillrect,
++ .fb_copyarea = xenfb_copyarea,
++ .fb_imageblit = xenfb_imageblit,
++};
++
++static irqreturn_t xenfb_event_handler(int rq, void *dev_id)
++{
++ /*
++ * No in events recognized, simply ignore them all.
++ * If you need to recognize some, see xen-kbdfront's
++ * input_handler() for how to do that.
++ */
++ struct xenfb_info *info = dev_id;
++ struct xenfb_page *page = info->page;
++
++ if (page->in_cons != page->in_prod) {
++ info->page->in_cons = info->page->in_prod;
++ notify_remote_via_irq(info->irq);
++ }
++
++ /* Flush dirty rectangle: */
++ xenfb_refresh(info, INT_MAX, INT_MAX, -INT_MAX, -INT_MAX);
++
++ return IRQ_HANDLED;
++}
++
++static int __devinit xenfb_probe(struct xenbus_device *dev,
++ const struct xenbus_device_id *id)
++{
++ struct xenfb_info *info;
++ struct fb_info *fb_info;
++ int ret;
++
++ info = kzalloc(sizeof(*info), GFP_KERNEL);
++ if (info == NULL) {
++ xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
++ return -ENOMEM;
++ }
++ dev->dev.driver_data = info;
++ info->xbdev = dev;
++ info->irq = -1;
++ info->x1 = info->y1 = INT_MAX;
++ spin_lock_init(&info->dirty_lock);
++
++ info->fb = vmalloc(xenfb_mem_len);
++ if (info->fb == NULL)
++ goto error_nomem;
++ memset(info->fb, 0, xenfb_mem_len);
++
++ info->nr_pages = (xenfb_mem_len + PAGE_SIZE - 1) >> PAGE_SHIFT;
++
++ info->mfns = vmalloc(sizeof(unsigned long) * info->nr_pages);
++ if (!info->mfns)
++ goto error_nomem;
++
++ /* set up shared page */
++ info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
++ if (!info->page)
++ goto error_nomem;
++
++ xenfb_init_shared_page(info);
++
++ /* abusing framebuffer_alloc() to allocate pseudo_palette */
++ fb_info = framebuffer_alloc(sizeof(u32) * 256, NULL);
++ if (fb_info == NULL)
++ goto error_nomem;
++
++ /* complete the abuse: */
++ fb_info->pseudo_palette = fb_info->par;
++ fb_info->par = info;
++
++ fb_info->screen_base = info->fb;
++
++ fb_info->fbops = &xenfb_fb_ops;
++ fb_info->var.xres_virtual = fb_info->var.xres = info->page->width;
++ fb_info->var.yres_virtual = fb_info->var.yres = info->page->height;
++ fb_info->var.bits_per_pixel = info->page->depth;
++
++ fb_info->var.red = (struct fb_bitfield){16, 8, 0};
++ fb_info->var.green = (struct fb_bitfield){8, 8, 0};
++ fb_info->var.blue = (struct fb_bitfield){0, 8, 0};
++
++ fb_info->var.activate = FB_ACTIVATE_NOW;
++ fb_info->var.height = -1;
++ fb_info->var.width = -1;
++ fb_info->var.vmode = FB_VMODE_NONINTERLACED;
++
++ fb_info->fix.visual = FB_VISUAL_TRUECOLOR;
++ fb_info->fix.line_length = info->page->line_length;
++ fb_info->fix.smem_start = 0;
++ fb_info->fix.smem_len = xenfb_mem_len;
++ strcpy(fb_info->fix.id, "xen");
++ fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
++ fb_info->fix.accel = FB_ACCEL_NONE;
++
++ fb_info->flags = FBINFO_FLAG_DEFAULT;
++
++ ret = fb_alloc_cmap(&fb_info->cmap, 256, 0);
++ if (ret < 0) {
++ framebuffer_release(fb_info);
++ xenbus_dev_fatal(dev, ret, "fb_alloc_cmap");
++ goto error;
++ }
++
++ fb_info->fbdefio = &xenfb_defio;
++ fb_deferred_io_init(fb_info);
++
++ ret = register_framebuffer(fb_info);
++ if (ret) {
++ fb_deferred_io_cleanup(fb_info);
++ fb_dealloc_cmap(&fb_info->cmap);
++ framebuffer_release(fb_info);
++ xenbus_dev_fatal(dev, ret, "register_framebuffer");
++ goto error;
++ }
++ info->fb_info = fb_info;
++
++ ret = xenfb_connect_backend(dev, info);
++ if (ret < 0)
++ goto error;
++
++ return 0;
++
++ error_nomem:
++ ret = -ENOMEM;
++ xenbus_dev_fatal(dev, ret, "allocating device memory");
++ error:
++ xenfb_remove(dev);
++ return ret;
++}
++
++static int xenfb_resume(struct xenbus_device *dev)
++{
++ struct xenfb_info *info = dev->dev.driver_data;
++
++ xenfb_disconnect_backend(info);
++ xenfb_init_shared_page(info);
++ return xenfb_connect_backend(dev, info);
++}
++
++static int xenfb_remove(struct xenbus_device *dev)
++{
++ struct xenfb_info *info = dev->dev.driver_data;
++
++ xenfb_disconnect_backend(info);
++ if (info->fb_info) {
++ fb_deferred_io_cleanup(info->fb_info);
++ unregister_framebuffer(info->fb_info);
++ fb_dealloc_cmap(&info->fb_info->cmap);
++ framebuffer_release(info->fb_info);
++ }
++ free_page((unsigned long)info->page);
++ vfree(info->mfns);
++ vfree(info->fb);
++ kfree(info);
++
++ return 0;
++}
++
++static unsigned long vmalloc_to_mfn(void *address)
++{
++ return pfn_to_mfn(vmalloc_to_pfn(address));
++}
++
++static void xenfb_init_shared_page(struct xenfb_info *info)
++{
++ int i;
++
++ for (i = 0; i < info->nr_pages; i++)
++ info->mfns[i] = vmalloc_to_mfn(info->fb + i * PAGE_SIZE);
++
++ info->page->pd[0] = vmalloc_to_mfn(info->mfns);
++ info->page->pd[1] = 0;
++ info->page->width = XENFB_WIDTH;
++ info->page->height = XENFB_HEIGHT;
++ info->page->depth = XENFB_DEPTH;
++ info->page->line_length = (info->page->depth / 8) * info->page->width;
++ info->page->mem_length = xenfb_mem_len;
++ info->page->in_cons = info->page->in_prod = 0;
++ info->page->out_cons = info->page->out_prod = 0;
++}
++
++static int xenfb_connect_backend(struct xenbus_device *dev,
++ struct xenfb_info *info)
++{
++ int ret, evtchn;
++ struct xenbus_transaction xbt;
++
++ ret = xenbus_alloc_evtchn(dev, &evtchn);
++ if (ret)
++ return ret;
++ ret = bind_evtchn_to_irqhandler(evtchn, xenfb_event_handler,
++ 0, dev->devicetype, info);
++ if (ret < 0) {
++ xenbus_free_evtchn(dev, evtchn);
++ xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
++ return ret;
++ }
++ info->irq = ret;
++
++ again:
++ ret = xenbus_transaction_start(&xbt);
++ if (ret) {
++ xenbus_dev_fatal(dev, ret, "starting transaction");
++ return ret;
++ }
++ ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
++ virt_to_mfn(info->page));
++ if (ret)
++ goto error_xenbus;
++ ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
++ evtchn);
++ if (ret)
++ goto error_xenbus;
++ ret = xenbus_printf(xbt, dev->nodename, "protocol", "%s",
++ XEN_IO_PROTO_ABI_NATIVE);
++ if (ret)
++ goto error_xenbus;
++ ret = xenbus_printf(xbt, dev->nodename, "feature-update", "1");
++ if (ret)
++ goto error_xenbus;
++ ret = xenbus_transaction_end(xbt, 0);
++ if (ret) {
++ if (ret == -EAGAIN)
++ goto again;
++ xenbus_dev_fatal(dev, ret, "completing transaction");
++ return ret;
++ }
++
++ xenbus_switch_state(dev, XenbusStateInitialised);
++ return 0;
++
++ error_xenbus:
++ xenbus_transaction_end(xbt, 1);
++ xenbus_dev_fatal(dev, ret, "writing xenstore");
++ return ret;
++}
++
++static void xenfb_disconnect_backend(struct xenfb_info *info)
++{
++ if (info->irq >= 0)
++ unbind_from_irqhandler(info->irq, info);
++ info->irq = -1;
++}
++
++static void xenfb_backend_changed(struct xenbus_device *dev,
++ enum xenbus_state backend_state)
++{
++ struct xenfb_info *info = dev->dev.driver_data;
++ int val;
++
++ switch (backend_state) {
++ case XenbusStateInitialising:
++ case XenbusStateInitialised:
++ case XenbusStateUnknown:
++ case XenbusStateClosed:
++ break;
++
++ case XenbusStateInitWait:
++InitWait:
++ xenbus_switch_state(dev, XenbusStateConnected);
++ break;
++
++ case XenbusStateConnected:
++ /*
++ * Work around xenbus race condition: If backend goes
++ * through InitWait to Connected fast enough, we can
++ * get Connected twice here.
++ */
++ if (dev->state != XenbusStateConnected)
++ goto InitWait; /* no InitWait seen yet, fudge it */
++
++ if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
++ "request-update", "%d", &val) < 0)
++ val = 0;
++ if (val)
++ info->update_wanted = 1;
++ break;
++
++ case XenbusStateClosing:
++ xenbus_frontend_closed(dev);
++ break;
++ }
++}
++
++static struct xenbus_device_id xenfb_ids[] = {
++ { "vfb" },
++ { "" }
++};
++
++static struct xenbus_driver xenfb = {
++ .name = "vfb",
++ .owner = THIS_MODULE,
++ .ids = xenfb_ids,
++ .probe = xenfb_probe,
++ .remove = xenfb_remove,
++ .resume = xenfb_resume,
++ .otherend_changed = xenfb_backend_changed,
++};
++
++static int __init xenfb_init(void)
++{
++ if (!is_running_on_xen())
++ return -ENODEV;
++
++ /* Nothing to do if running in dom0. */
++ if (is_initial_xendomain())
++ return -ENODEV;
++
++ return xenbus_register_frontend(&xenfb);
++}
++
++static void __exit xenfb_cleanup(void)
++{
++ xenbus_unregister_driver(&xenfb);
++}
++
++module_init(xenfb_init);
++module_exit(xenfb_cleanup);
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/watchdog/sc1200wdt.c b/drivers/watchdog/sc1200wdt.c
+index 32ccd7c..35cddff 100644
+--- a/drivers/watchdog/sc1200wdt.c
++++ b/drivers/watchdog/sc1200wdt.c
+@@ -38,8 +38,8 @@
+ #include <linux/init.h>
+ #include <linux/pnp.h>
+ #include <linux/fs.h>
++#include <linux/semaphore.h>
+
+-#include <asm/semaphore.h>
+ #include <asm/io.h>
+ #include <asm/uaccess.h>
+
+diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
+new file mode 100644
+index 0000000..4b75a16
+--- /dev/null
++++ b/drivers/xen/Kconfig
+@@ -0,0 +1,19 @@
++config XEN_BALLOON
++ bool "Xen memory balloon driver"
++ depends on XEN
++ default y
++ help
++ The balloon driver allows the Xen domain to request more memory from
++ the system to expand the domain's memory allocation, or alternatively
++ return unneeded memory to the system.
++
++config XEN_SCRUB_PAGES
++ bool "Scrub pages before returning them to system"
++ depends on XEN_BALLOON
++ default y
++ help
++ Scrub pages before returning them to the system for reuse by
++ other domains. This makes sure that any confidential data
++ is not accidentally visible to other domains. Is it more
++ secure, but slightly less efficient.
++ If in doubt, say yes.
+diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
+index 56592f0..37af04f 100644
+--- a/drivers/xen/Makefile
++++ b/drivers/xen/Makefile
+@@ -1,2 +1,4 @@
+-obj-y += grant-table.o
++obj-y += grant-table.o features.o events.o
+ obj-y += xenbus/
++obj-$(CONFIG_XEN_XENCOMM) += xencomm.o
++obj-$(CONFIG_XEN_BALLOON) += balloon.o
+diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
+new file mode 100644
+index 0000000..ab25ba6
+--- /dev/null
++++ b/drivers/xen/balloon.c
+@@ -0,0 +1,712 @@
++/******************************************************************************
++ * balloon.c
++ *
++ * Xen balloon driver - enables returning/claiming memory to/from Xen.
++ *
++ * Copyright (c) 2003, B Dragovic
++ * Copyright (c) 2003-2004, M Williamson, K Fraser
++ * Copyright (c) 2005 Dan M. Smith, IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/errno.h>
++#include <linux/mm.h>
++#include <linux/bootmem.h>
++#include <linux/pagemap.h>
++#include <linux/highmem.h>
++#include <linux/mutex.h>
++#include <linux/highmem.h>
++#include <linux/list.h>
++#include <linux/sysdev.h>
++
++#include <asm/xen/hypervisor.h>
++#include <asm/page.h>
++#include <asm/pgalloc.h>
++#include <asm/pgtable.h>
++#include <asm/uaccess.h>
++#include <asm/tlb.h>
++
++#include <xen/interface/memory.h>
++#include <xen/balloon.h>
++#include <xen/xenbus.h>
++#include <xen/features.h>
++#include <xen/page.h>
++
++#define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10))
++
++#define BALLOON_CLASS_NAME "memory"
++
++struct balloon_stats {
++ /* We aim for 'current allocation' == 'target allocation'. */
++ unsigned long current_pages;
++ unsigned long target_pages;
++ /* We may hit the hard limit in Xen. If we do then we remember it. */
++ unsigned long hard_limit;
++ /*
++ * Drivers may alter the memory reservation independently, but they
++ * must inform the balloon driver so we avoid hitting the hard limit.
++ */
++ unsigned long driver_pages;
++ /* Number of pages in high- and low-memory balloons. */
++ unsigned long balloon_low;
++ unsigned long balloon_high;
++};
++
++static DEFINE_MUTEX(balloon_mutex);
++
++static struct sys_device balloon_sysdev;
++
++static int register_balloon(struct sys_device *sysdev);
++
++/*
++ * Protects atomic reservation decrease/increase against concurrent increases.
++ * Also protects non-atomic updates of current_pages and driver_pages, and
++ * balloon lists.
++ */
++static DEFINE_SPINLOCK(balloon_lock);
++
++static struct balloon_stats balloon_stats;
++
++/* We increase/decrease in batches which fit in a page */
++static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)];
++
++/* VM /proc information for memory */
++extern unsigned long totalram_pages;
++
++#ifdef CONFIG_HIGHMEM
++extern unsigned long totalhigh_pages;
++#define inc_totalhigh_pages() (totalhigh_pages++)
++#define dec_totalhigh_pages() (totalhigh_pages--)
++#else
++#define inc_totalhigh_pages() do {} while(0)
++#define dec_totalhigh_pages() do {} while(0)
++#endif
++
++/* List of ballooned pages, threaded through the mem_map array. */
++static LIST_HEAD(ballooned_pages);
++
++/* Main work function, always executed in process context. */
++static void balloon_process(struct work_struct *work);
++static DECLARE_WORK(balloon_worker, balloon_process);
++static struct timer_list balloon_timer;
++
++/* When ballooning out (allocating memory to return to Xen) we don't really
++ want the kernel to try too hard since that can trigger the oom killer. */
++#define GFP_BALLOON \
++ (GFP_HIGHUSER | __GFP_NOWARN | __GFP_NORETRY | __GFP_NOMEMALLOC)
++
++static void scrub_page(struct page *page)
++{
++#ifdef CONFIG_XEN_SCRUB_PAGES
++ if (PageHighMem(page)) {
++ void *v = kmap(page);
++ clear_page(v);
++ kunmap(v);
++ } else {
++ void *v = page_address(page);
++ clear_page(v);
++ }
++#endif
++}
++
++/* balloon_append: add the given page to the balloon. */
++static void balloon_append(struct page *page)
++{
++ /* Lowmem is re-populated first, so highmem pages go at list tail. */
++ if (PageHighMem(page)) {
++ list_add_tail(&page->lru, &ballooned_pages);
++ balloon_stats.balloon_high++;
++ dec_totalhigh_pages();
++ } else {
++ list_add(&page->lru, &ballooned_pages);
++ balloon_stats.balloon_low++;
++ }
++}
++
++/* balloon_retrieve: rescue a page from the balloon, if it is not empty. */
++static struct page *balloon_retrieve(void)
++{
++ struct page *page;
++
++ if (list_empty(&ballooned_pages))
++ return NULL;
++
++ page = list_entry(ballooned_pages.next, struct page, lru);
++ list_del(&page->lru);
++
++ if (PageHighMem(page)) {
++ balloon_stats.balloon_high--;
++ inc_totalhigh_pages();
++ }
++ else
++ balloon_stats.balloon_low--;
++
++ return page;
++}
++
++static struct page *balloon_first_page(void)
++{
++ if (list_empty(&ballooned_pages))
++ return NULL;
++ return list_entry(ballooned_pages.next, struct page, lru);
++}
++
++static struct page *balloon_next_page(struct page *page)
++{
++ struct list_head *next = page->lru.next;
++ if (next == &ballooned_pages)
++ return NULL;
++ return list_entry(next, struct page, lru);
++}
++
++static void balloon_alarm(unsigned long unused)
++{
++ schedule_work(&balloon_worker);
++}
++
++static unsigned long current_target(void)
++{
++ unsigned long target = min(balloon_stats.target_pages, balloon_stats.hard_limit);
++
++ target = min(target,
++ balloon_stats.current_pages +
++ balloon_stats.balloon_low +
++ balloon_stats.balloon_high);
++
++ return target;
++}
++
++static int increase_reservation(unsigned long nr_pages)
++{
++ unsigned long pfn, i, flags;
++ struct page *page;
++ long rc;
++ struct xen_memory_reservation reservation = {
++ .address_bits = 0,
++ .extent_order = 0,
++ .domid = DOMID_SELF
++ };
++
++ if (nr_pages > ARRAY_SIZE(frame_list))
++ nr_pages = ARRAY_SIZE(frame_list);
++
++ spin_lock_irqsave(&balloon_lock, flags);
++
++ page = balloon_first_page();
++ for (i = 0; i < nr_pages; i++) {
++ BUG_ON(page == NULL);
++ frame_list[i] = page_to_pfn(page);;
++ page = balloon_next_page(page);
++ }
++
++ reservation.extent_start = (unsigned long)frame_list;
++ reservation.nr_extents = nr_pages;
++ rc = HYPERVISOR_memory_op(
++ XENMEM_populate_physmap, &reservation);
++ if (rc < nr_pages) {
++ if (rc > 0) {
++ int ret;
++
++ /* We hit the Xen hard limit: reprobe. */
++ reservation.nr_extents = rc;
++ ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
++ &reservation);
++ BUG_ON(ret != rc);
++ }
++ if (rc >= 0)
++ balloon_stats.hard_limit = (balloon_stats.current_pages + rc -
++ balloon_stats.driver_pages);
++ goto out;
++ }
++
++ for (i = 0; i < nr_pages; i++) {
++ page = balloon_retrieve();
++ BUG_ON(page == NULL);
++
++ pfn = page_to_pfn(page);
++ BUG_ON(!xen_feature(XENFEAT_auto_translated_physmap) &&
++ phys_to_machine_mapping_valid(pfn));
++
++ set_phys_to_machine(pfn, frame_list[i]);
++
++ /* Link back into the page tables if not highmem. */
++ if (pfn < max_low_pfn) {
++ int ret;
++ ret = HYPERVISOR_update_va_mapping(
++ (unsigned long)__va(pfn << PAGE_SHIFT),
++ mfn_pte(frame_list[i], PAGE_KERNEL),
++ 0);
++ BUG_ON(ret);
++ }
++
++ /* Relinquish the page back to the allocator. */
++ ClearPageReserved(page);
++ init_page_count(page);
++ __free_page(page);
++ }
++
++ balloon_stats.current_pages += nr_pages;
++ totalram_pages = balloon_stats.current_pages;
++
++ out:
++ spin_unlock_irqrestore(&balloon_lock, flags);
++
++ return 0;
++}
++
++static int decrease_reservation(unsigned long nr_pages)
++{
++ unsigned long pfn, i, flags;
++ struct page *page;
++ int need_sleep = 0;
++ int ret;
++ struct xen_memory_reservation reservation = {
++ .address_bits = 0,
++ .extent_order = 0,
++ .domid = DOMID_SELF
++ };
++
++ if (nr_pages > ARRAY_SIZE(frame_list))
++ nr_pages = ARRAY_SIZE(frame_list);
++
++ for (i = 0; i < nr_pages; i++) {
++ if ((page = alloc_page(GFP_BALLOON)) == NULL) {
++ nr_pages = i;
++ need_sleep = 1;
++ break;
++ }
++
++ pfn = page_to_pfn(page);
++ frame_list[i] = pfn_to_mfn(pfn);
++
++ scrub_page(page);
++ }
++
++ /* Ensure that ballooned highmem pages don't have kmaps. */
++ kmap_flush_unused();
++ flush_tlb_all();
++
++ spin_lock_irqsave(&balloon_lock, flags);
++
++ /* No more mappings: invalidate P2M and add to balloon. */
++ for (i = 0; i < nr_pages; i++) {
++ pfn = mfn_to_pfn(frame_list[i]);
++ set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
++ balloon_append(pfn_to_page(pfn));
++ }
++
++ reservation.extent_start = (unsigned long)frame_list;
++ reservation.nr_extents = nr_pages;
++ ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
++ BUG_ON(ret != nr_pages);
++
++ balloon_stats.current_pages -= nr_pages;
++ totalram_pages = balloon_stats.current_pages;
++
++ spin_unlock_irqrestore(&balloon_lock, flags);
++
++ return need_sleep;
++}
++
++/*
++ * We avoid multiple worker processes conflicting via the balloon mutex.
++ * We may of course race updates of the target counts (which are protected
++ * by the balloon lock), or with changes to the Xen hard limit, but we will
++ * recover from these in time.
++ */
++static void balloon_process(struct work_struct *work)
++{
++ int need_sleep = 0;
++ long credit;
++
++ mutex_lock(&balloon_mutex);
++
++ do {
++ credit = current_target() - balloon_stats.current_pages;
++ if (credit > 0)
++ need_sleep = (increase_reservation(credit) != 0);
++ if (credit < 0)
++ need_sleep = (decrease_reservation(-credit) != 0);
++
++#ifndef CONFIG_PREEMPT
++ if (need_resched())
++ schedule();
++#endif
++ } while ((credit != 0) && !need_sleep);
++
++ /* Schedule more work if there is some still to be done. */
++ if (current_target() != balloon_stats.current_pages)
++ mod_timer(&balloon_timer, jiffies + HZ);
++
++ mutex_unlock(&balloon_mutex);
++}
++
++/* Resets the Xen limit, sets new target, and kicks off processing. */
++void balloon_set_new_target(unsigned long target)
++{
++ /* No need for lock. Not read-modify-write updates. */
++ balloon_stats.hard_limit = ~0UL;
++ balloon_stats.target_pages = target;
++ schedule_work(&balloon_worker);
++}
++
++static struct xenbus_watch target_watch =
++{
++ .node = "memory/target"
++};
++
++/* React to a change in the target key */
++static void watch_target(struct xenbus_watch *watch,
++ const char **vec, unsigned int len)
++{
++ unsigned long long new_target;
++ int err;
++
++ err = xenbus_scanf(XBT_NIL, "memory", "target", "%llu", &new_target);
++ if (err != 1) {
++ /* This is ok (for domain0 at least) - so just return */
++ return;
++ }
++
++ /* The given memory/target value is in KiB, so it needs converting to
++ * pages. PAGE_SHIFT converts bytes to pages, hence PAGE_SHIFT - 10.
++ */
++ balloon_set_new_target(new_target >> (PAGE_SHIFT - 10));
++}
++
++static int balloon_init_watcher(struct notifier_block *notifier,
++ unsigned long event,
++ void *data)
++{
++ int err;
++
++ err = register_xenbus_watch(&target_watch);
++ if (err)
++ printk(KERN_ERR "Failed to set balloon watcher\n");
++
++ return NOTIFY_DONE;
++}
++
++static struct notifier_block xenstore_notifier;
++
++static int __init balloon_init(void)
++{
++ unsigned long pfn;
++ struct page *page;
++
++ if (!is_running_on_xen())
++ return -ENODEV;
++
++ pr_info("xen_balloon: Initialising balloon driver.\n");
++
++ balloon_stats.current_pages = min(xen_start_info->nr_pages, max_pfn);
++ totalram_pages = balloon_stats.current_pages;
++ balloon_stats.target_pages = balloon_stats.current_pages;
++ balloon_stats.balloon_low = 0;
++ balloon_stats.balloon_high = 0;
++ balloon_stats.driver_pages = 0UL;
++ balloon_stats.hard_limit = ~0UL;
++
++ init_timer(&balloon_timer);
++ balloon_timer.data = 0;
++ balloon_timer.function = balloon_alarm;
++
++ register_balloon(&balloon_sysdev);
++
++ /* Initialise the balloon with excess memory space. */
++ for (pfn = xen_start_info->nr_pages; pfn < max_pfn; pfn++) {
++ page = pfn_to_page(pfn);
++ if (!PageReserved(page))
++ balloon_append(page);
++ }
++
++ target_watch.callback = watch_target;
++ xenstore_notifier.notifier_call = balloon_init_watcher;
++
++ register_xenstore_notifier(&xenstore_notifier);
++
++ return 0;
++}
++
++subsys_initcall(balloon_init);
++
++static void balloon_exit(void)
++{
++ /* XXX - release balloon here */
++ return;
++}
++
++module_exit(balloon_exit);
++
++static void balloon_update_driver_allowance(long delta)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&balloon_lock, flags);
++ balloon_stats.driver_pages += delta;
++ spin_unlock_irqrestore(&balloon_lock, flags);
++}
++
++static int dealloc_pte_fn(
++ pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
++{
++ unsigned long mfn = pte_mfn(*pte);
++ int ret;
++ struct xen_memory_reservation reservation = {
++ .nr_extents = 1,
++ .extent_order = 0,
++ .domid = DOMID_SELF
++ };
++ reservation.extent_start = (unsigned long)&mfn;
++ set_pte_at(&init_mm, addr, pte, __pte_ma(0ull));
++ set_phys_to_machine(__pa(addr) >> PAGE_SHIFT, INVALID_P2M_ENTRY);
++ ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
++ BUG_ON(ret != 1);
++ return 0;
++}
++
++static struct page **alloc_empty_pages_and_pagevec(int nr_pages)
++{
++ unsigned long vaddr, flags;
++ struct page *page, **pagevec;
++ int i, ret;
++
++ pagevec = kmalloc(sizeof(page) * nr_pages, GFP_KERNEL);
++ if (pagevec == NULL)
++ return NULL;
++
++ for (i = 0; i < nr_pages; i++) {
++ page = pagevec[i] = alloc_page(GFP_KERNEL);
++ if (page == NULL)
++ goto err;
++
++ vaddr = (unsigned long)page_address(page);
++
++ scrub_page(page);
++
++ spin_lock_irqsave(&balloon_lock, flags);
++
++ if (xen_feature(XENFEAT_auto_translated_physmap)) {
++ unsigned long gmfn = page_to_pfn(page);
++ struct xen_memory_reservation reservation = {
++ .nr_extents = 1,
++ .extent_order = 0,
++ .domid = DOMID_SELF
++ };
++ reservation.extent_start = (unsigned long)&gmfn;
++ ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
++ &reservation);
++ if (ret == 1)
++ ret = 0; /* success */
++ } else {
++ ret = apply_to_page_range(&init_mm, vaddr, PAGE_SIZE,
++ dealloc_pte_fn, NULL);
++ }
++
++ if (ret != 0) {
++ spin_unlock_irqrestore(&balloon_lock, flags);
++ __free_page(page);
++ goto err;
++ }
++
++ totalram_pages = --balloon_stats.current_pages;
++
++ spin_unlock_irqrestore(&balloon_lock, flags);
++ }
++
++ out:
++ schedule_work(&balloon_worker);
++ flush_tlb_all();
++ return pagevec;
++
++ err:
++ spin_lock_irqsave(&balloon_lock, flags);
++ while (--i >= 0)
++ balloon_append(pagevec[i]);
++ spin_unlock_irqrestore(&balloon_lock, flags);
++ kfree(pagevec);
++ pagevec = NULL;
++ goto out;
++}
++
++static void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages)
++{
++ unsigned long flags;
++ int i;
++
++ if (pagevec == NULL)
++ return;
++
++ spin_lock_irqsave(&balloon_lock, flags);
++ for (i = 0; i < nr_pages; i++) {
++ BUG_ON(page_count(pagevec[i]) != 1);
++ balloon_append(pagevec[i]);
++ }
++ spin_unlock_irqrestore(&balloon_lock, flags);
++
++ kfree(pagevec);
++
++ schedule_work(&balloon_worker);
++}
++
++static void balloon_release_driver_page(struct page *page)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&balloon_lock, flags);
++ balloon_append(page);
++ balloon_stats.driver_pages--;
++ spin_unlock_irqrestore(&balloon_lock, flags);
++
++ schedule_work(&balloon_worker);
++}
++
++
++#define BALLOON_SHOW(name, format, args...) \
++ static ssize_t show_##name(struct sys_device *dev, \
++ char *buf) \
++ { \
++ return sprintf(buf, format, ##args); \
++ } \
++ static SYSDEV_ATTR(name, S_IRUGO, show_##name, NULL)
++
++BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages));
++BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low));
++BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high));
++BALLOON_SHOW(hard_limit_kb,
++ (balloon_stats.hard_limit!=~0UL) ? "%lu\n" : "???\n",
++ (balloon_stats.hard_limit!=~0UL) ? PAGES2KB(balloon_stats.hard_limit) : 0);
++BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(balloon_stats.driver_pages));
++
++static ssize_t show_target_kb(struct sys_device *dev, char *buf)
++{
++ return sprintf(buf, "%lu\n", PAGES2KB(balloon_stats.target_pages));
++}
++
++static ssize_t store_target_kb(struct sys_device *dev,
++ const char *buf,
++ size_t count)
++{
++ char memstring[64], *endchar;
++ unsigned long long target_bytes;
++
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
++ if (count <= 1)
++ return -EBADMSG; /* runt */
++ if (count > sizeof(memstring))
++ return -EFBIG; /* too long */
++ strcpy(memstring, buf);
++
++ target_bytes = memparse(memstring, &endchar);
++ balloon_set_new_target(target_bytes >> PAGE_SHIFT);
++
++ return count;
++}
++
++static SYSDEV_ATTR(target_kb, S_IRUGO | S_IWUSR,
++ show_target_kb, store_target_kb);
++
++static struct sysdev_attribute *balloon_attrs[] = {
++ &attr_target_kb,
++};
++
++static struct attribute *balloon_info_attrs[] = {
++ &attr_current_kb.attr,
++ &attr_low_kb.attr,
++ &attr_high_kb.attr,
++ &attr_hard_limit_kb.attr,
++ &attr_driver_kb.attr,
++ NULL
++};
++
++static struct attribute_group balloon_info_group = {
++ .name = "info",
++ .attrs = balloon_info_attrs,
++};
++
++static struct sysdev_class balloon_sysdev_class = {
++ .name = BALLOON_CLASS_NAME,
++};
++
++static int register_balloon(struct sys_device *sysdev)
++{
++ int i, error;
++
++ error = sysdev_class_register(&balloon_sysdev_class);
++ if (error)
++ return error;
++
++ sysdev->id = 0;
++ sysdev->cls = &balloon_sysdev_class;
++
++ error = sysdev_register(sysdev);
++ if (error) {
++ sysdev_class_unregister(&balloon_sysdev_class);
++ return error;
++ }
++
++ for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++) {
++ error = sysdev_create_file(sysdev, balloon_attrs[i]);
++ if (error)
++ goto fail;
++ }
++
++ error = sysfs_create_group(&sysdev->kobj, &balloon_info_group);
++ if (error)
++ goto fail;
++
++ return 0;
++
++ fail:
++ while (--i >= 0)
++ sysdev_remove_file(sysdev, balloon_attrs[i]);
++ sysdev_unregister(sysdev);
++ sysdev_class_unregister(&balloon_sysdev_class);
++ return error;
++}
++
++static void unregister_balloon(struct sys_device *sysdev)
++{
++ int i;
++
++ sysfs_remove_group(&sysdev->kobj, &balloon_info_group);
++ for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++)
++ sysdev_remove_file(sysdev, balloon_attrs[i]);
++ sysdev_unregister(sysdev);
++ sysdev_class_unregister(&balloon_sysdev_class);
++}
++
++static void balloon_sysfs_exit(void)
++{
++ unregister_balloon(&balloon_sysdev);
++}
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/xen/events.c b/drivers/xen/events.c
+new file mode 100644
+index 0000000..4f0f22b
+--- /dev/null
++++ b/drivers/xen/events.c
+@@ -0,0 +1,674 @@
++/*
++ * Xen event channels
++ *
++ * Xen models interrupts with abstract event channels. Because each
++ * domain gets 1024 event channels, but NR_IRQ is not that large, we
++ * must dynamically map irqs<->event channels. The event channels
++ * interface with the rest of the kernel by defining a xen interrupt
++ * chip. When an event is recieved, it is mapped to an irq and sent
++ * through the normal interrupt processing path.
++ *
++ * There are four kinds of events which can be mapped to an event
++ * channel:
++ *
++ * 1. Inter-domain notifications. This includes all the virtual
++ * device events, since they're driven by front-ends in another domain
++ * (typically dom0).
++ * 2. VIRQs, typically used for timers. These are per-cpu events.
++ * 3. IPIs.
++ * 4. Hardware interrupts. Not supported at present.
++ *
++ * Jeremy Fitzhardinge <jeremy at xensource.com>, XenSource Inc, 2007
++ */
++
++#include <linux/linkage.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <linux/module.h>
++#include <linux/string.h>
++
++#include <asm/ptrace.h>
++#include <asm/irq.h>
++#include <asm/sync_bitops.h>
++#include <asm/xen/hypercall.h>
++#include <asm/xen/hypervisor.h>
++
++#include <xen/xen-ops.h>
++#include <xen/events.h>
++#include <xen/interface/xen.h>
++#include <xen/interface/event_channel.h>
++
++/*
++ * This lock protects updates to the following mapping and reference-count
++ * arrays. The lock does not need to be acquired to read the mapping tables.
++ */
++static DEFINE_SPINLOCK(irq_mapping_update_lock);
++
++/* IRQ <-> VIRQ mapping. */
++static DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS]) = {[0 ... NR_VIRQS-1] = -1};
++
++/* IRQ <-> IPI mapping */
++static DEFINE_PER_CPU(int, ipi_to_irq[XEN_NR_IPIS]) = {[0 ... XEN_NR_IPIS-1] = -1};
++
++/* Packed IRQ information: binding type, sub-type index, and event channel. */
++struct packed_irq
++{
++ unsigned short evtchn;
++ unsigned char index;
++ unsigned char type;
++};
++
++static struct packed_irq irq_info[NR_IRQS];
++
++/* Binding types. */
++enum {
++ IRQT_UNBOUND,
++ IRQT_PIRQ,
++ IRQT_VIRQ,
++ IRQT_IPI,
++ IRQT_EVTCHN
++};
++
++/* Convenient shorthand for packed representation of an unbound IRQ. */
++#define IRQ_UNBOUND mk_irq_info(IRQT_UNBOUND, 0, 0)
++
++static int evtchn_to_irq[NR_EVENT_CHANNELS] = {
++ [0 ... NR_EVENT_CHANNELS-1] = -1
++};
++static unsigned long cpu_evtchn_mask[NR_CPUS][NR_EVENT_CHANNELS/BITS_PER_LONG];
++static u8 cpu_evtchn[NR_EVENT_CHANNELS];
++
++/* Reference counts for bindings to IRQs. */
++static int irq_bindcount[NR_IRQS];
++
++/* Xen will never allocate port zero for any purpose. */
++#define VALID_EVTCHN(chn) ((chn) != 0)
++
++/*
++ * Force a proper event-channel callback from Xen after clearing the
++ * callback mask. We do this in a very simple manner, by making a call
++ * down into Xen. The pending flag will be checked by Xen on return.
++ */
++void force_evtchn_callback(void)
++{
++ (void)HYPERVISOR_xen_version(0, NULL);
++}
++EXPORT_SYMBOL_GPL(force_evtchn_callback);
++
++static struct irq_chip xen_dynamic_chip;
++
++/* Constructor for packed IRQ information. */
++static inline struct packed_irq mk_irq_info(u32 type, u32 index, u32 evtchn)
++{
++ return (struct packed_irq) { evtchn, index, type };
++}
++
++/*
++ * Accessors for packed IRQ information.
++ */
++static inline unsigned int evtchn_from_irq(int irq)
++{
++ return irq_info[irq].evtchn;
++}
++
++static inline unsigned int index_from_irq(int irq)
++{
++ return irq_info[irq].index;
++}
++
++static inline unsigned int type_from_irq(int irq)
++{
++ return irq_info[irq].type;
++}
++
++static inline unsigned long active_evtchns(unsigned int cpu,
++ struct shared_info *sh,
++ unsigned int idx)
++{
++ return (sh->evtchn_pending[idx] &
++ cpu_evtchn_mask[cpu][idx] &
++ ~sh->evtchn_mask[idx]);
++}
++
++static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
++{
++ int irq = evtchn_to_irq[chn];
++
++ BUG_ON(irq == -1);
++#ifdef CONFIG_SMP
++ irq_desc[irq].affinity = cpumask_of_cpu(cpu);
++#endif
++
++ __clear_bit(chn, cpu_evtchn_mask[cpu_evtchn[chn]]);
++ __set_bit(chn, cpu_evtchn_mask[cpu]);
++
++ cpu_evtchn[chn] = cpu;
++}
++
++static void init_evtchn_cpu_bindings(void)
++{
++#ifdef CONFIG_SMP
++ int i;
++ /* By default all event channels notify CPU#0. */
++ for (i = 0; i < NR_IRQS; i++)
++ irq_desc[i].affinity = cpumask_of_cpu(0);
++#endif
++
++ memset(cpu_evtchn, 0, sizeof(cpu_evtchn));
++ memset(cpu_evtchn_mask[0], ~0, sizeof(cpu_evtchn_mask[0]));
++}
++
++static inline unsigned int cpu_from_evtchn(unsigned int evtchn)
++{
++ return cpu_evtchn[evtchn];
++}
++
++static inline void clear_evtchn(int port)
++{
++ struct shared_info *s = HYPERVISOR_shared_info;
++ sync_clear_bit(port, &s->evtchn_pending[0]);
++}
++
++static inline void set_evtchn(int port)
++{
++ struct shared_info *s = HYPERVISOR_shared_info;
++ sync_set_bit(port, &s->evtchn_pending[0]);
++}
++
++
++/**
++ * notify_remote_via_irq - send event to remote end of event channel via irq
++ * @irq: irq of event channel to send event to
++ *
++ * Unlike notify_remote_via_evtchn(), this is safe to use across
++ * save/restore. Notifications on a broken connection are silently
++ * dropped.
++ */
++void notify_remote_via_irq(int irq)
++{
++ int evtchn = evtchn_from_irq(irq);
++
++ if (VALID_EVTCHN(evtchn))
++ notify_remote_via_evtchn(evtchn);
++}
++EXPORT_SYMBOL_GPL(notify_remote_via_irq);
++
++static void mask_evtchn(int port)
++{
++ struct shared_info *s = HYPERVISOR_shared_info;
++ sync_set_bit(port, &s->evtchn_mask[0]);
++}
++
++static void unmask_evtchn(int port)
++{
++ struct shared_info *s = HYPERVISOR_shared_info;
++ unsigned int cpu = get_cpu();
++
++ BUG_ON(!irqs_disabled());
++
++ /* Slow path (hypercall) if this is a non-local port. */
++ if (unlikely(cpu != cpu_from_evtchn(port))) {
++ struct evtchn_unmask unmask = { .port = port };
++ (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask);
++ } else {
++ struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu);
++
++ sync_clear_bit(port, &s->evtchn_mask[0]);
++
++ /*
++ * The following is basically the equivalent of
++ * 'hw_resend_irq'. Just like a real IO-APIC we 'lose
++ * the interrupt edge' if the channel is masked.
++ */
++ if (sync_test_bit(port, &s->evtchn_pending[0]) &&
++ !sync_test_and_set_bit(port / BITS_PER_LONG,
++ &vcpu_info->evtchn_pending_sel))
++ vcpu_info->evtchn_upcall_pending = 1;
++ }
++
++ put_cpu();
++}
++
++static int find_unbound_irq(void)
++{
++ int irq;
++
++ /* Only allocate from dynirq range */
++ for (irq = 0; irq < NR_IRQS; irq++)
++ if (irq_bindcount[irq] == 0)
++ break;
++
++ if (irq == NR_IRQS)
++ panic("No available IRQ to bind to: increase NR_IRQS!\n");
++
++ return irq;
++}
++
++int bind_evtchn_to_irq(unsigned int evtchn)
++{
++ int irq;
++
++ spin_lock(&irq_mapping_update_lock);
++
++ irq = evtchn_to_irq[evtchn];
++
++ if (irq == -1) {
++ irq = find_unbound_irq();
++
++ dynamic_irq_init(irq);
++ set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
++ handle_level_irq, "event");
++
++ evtchn_to_irq[evtchn] = irq;
++ irq_info[irq] = mk_irq_info(IRQT_EVTCHN, 0, evtchn);
++ }
++
++ irq_bindcount[irq]++;
++
++ spin_unlock(&irq_mapping_update_lock);
++
++ return irq;
++}
++EXPORT_SYMBOL_GPL(bind_evtchn_to_irq);
++
++static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
++{
++ struct evtchn_bind_ipi bind_ipi;
++ int evtchn, irq;
++
++ spin_lock(&irq_mapping_update_lock);
++
++ irq = per_cpu(ipi_to_irq, cpu)[ipi];
++ if (irq == -1) {
++ irq = find_unbound_irq();
++ if (irq < 0)
++ goto out;
++
++ dynamic_irq_init(irq);
++ set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
++ handle_level_irq, "ipi");
++
++ bind_ipi.vcpu = cpu;
++ if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi,
++ &bind_ipi) != 0)
++ BUG();
++ evtchn = bind_ipi.port;
++
++ evtchn_to_irq[evtchn] = irq;
++ irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn);
++
++ per_cpu(ipi_to_irq, cpu)[ipi] = irq;
++
++ bind_evtchn_to_cpu(evtchn, cpu);
++ }
++
++ irq_bindcount[irq]++;
++
++ out:
++ spin_unlock(&irq_mapping_update_lock);
++ return irq;
++}
++
++
++static int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
++{
++ struct evtchn_bind_virq bind_virq;
++ int evtchn, irq;
++
++ spin_lock(&irq_mapping_update_lock);
++
++ irq = per_cpu(virq_to_irq, cpu)[virq];
++
++ if (irq == -1) {
++ bind_virq.virq = virq;
++ bind_virq.vcpu = cpu;
++ if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
++ &bind_virq) != 0)
++ BUG();
++ evtchn = bind_virq.port;
++
++ irq = find_unbound_irq();
++
++ dynamic_irq_init(irq);
++ set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
++ handle_level_irq, "virq");
++
++ evtchn_to_irq[evtchn] = irq;
++ irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn);
++
++ per_cpu(virq_to_irq, cpu)[virq] = irq;
++
++ bind_evtchn_to_cpu(evtchn, cpu);
++ }
++
++ irq_bindcount[irq]++;
++
++ spin_unlock(&irq_mapping_update_lock);
++
++ return irq;
++}
++
++static void unbind_from_irq(unsigned int irq)
++{
++ struct evtchn_close close;
++ int evtchn = evtchn_from_irq(irq);
++
++ spin_lock(&irq_mapping_update_lock);
++
++ if (VALID_EVTCHN(evtchn) && (--irq_bindcount[irq] == 0)) {
++ close.port = evtchn;
++ if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
++ BUG();
++
++ switch (type_from_irq(irq)) {
++ case IRQT_VIRQ:
++ per_cpu(virq_to_irq, cpu_from_evtchn(evtchn))
++ [index_from_irq(irq)] = -1;
++ break;
++ default:
++ break;
++ }
++
++ /* Closed ports are implicitly re-bound to VCPU0. */
++ bind_evtchn_to_cpu(evtchn, 0);
++
++ evtchn_to_irq[evtchn] = -1;
++ irq_info[irq] = IRQ_UNBOUND;
++
++ dynamic_irq_init(irq);
++ }
++
++ spin_unlock(&irq_mapping_update_lock);
++}
++
++int bind_evtchn_to_irqhandler(unsigned int evtchn,
++ irq_handler_t handler,
++ unsigned long irqflags,
++ const char *devname, void *dev_id)
++{
++ unsigned int irq;
++ int retval;
++
++ irq = bind_evtchn_to_irq(evtchn);
++ retval = request_irq(irq, handler, irqflags, devname, dev_id);
++ if (retval != 0) {
++ unbind_from_irq(irq);
++ return retval;
++ }
++
++ return irq;
++}
++EXPORT_SYMBOL_GPL(bind_evtchn_to_irqhandler);
++
++int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu,
++ irq_handler_t handler,
++ unsigned long irqflags, const char *devname, void *dev_id)
++{
++ unsigned int irq;
++ int retval;
++
++ irq = bind_virq_to_irq(virq, cpu);
++ retval = request_irq(irq, handler, irqflags, devname, dev_id);
++ if (retval != 0) {
++ unbind_from_irq(irq);
++ return retval;
++ }
++
++ return irq;
++}
++EXPORT_SYMBOL_GPL(bind_virq_to_irqhandler);
++
++int bind_ipi_to_irqhandler(enum ipi_vector ipi,
++ unsigned int cpu,
++ irq_handler_t handler,
++ unsigned long irqflags,
++ const char *devname,
++ void *dev_id)
++{
++ int irq, retval;
++
++ irq = bind_ipi_to_irq(ipi, cpu);
++ if (irq < 0)
++ return irq;
++
++ retval = request_irq(irq, handler, irqflags, devname, dev_id);
++ if (retval != 0) {
++ unbind_from_irq(irq);
++ return retval;
++ }
++
++ return irq;
++}
++
++void unbind_from_irqhandler(unsigned int irq, void *dev_id)
++{
++ free_irq(irq, dev_id);
++ unbind_from_irq(irq);
++}
++EXPORT_SYMBOL_GPL(unbind_from_irqhandler);
++
++void xen_send_IPI_one(unsigned int cpu, enum ipi_vector vector)
++{
++ int irq = per_cpu(ipi_to_irq, cpu)[vector];
++ BUG_ON(irq < 0);
++ notify_remote_via_irq(irq);
++}
++
++irqreturn_t xen_debug_interrupt(int irq, void *dev_id)
++{
++ struct shared_info *sh = HYPERVISOR_shared_info;
++ int cpu = smp_processor_id();
++ int i;
++ unsigned long flags;
++ static DEFINE_SPINLOCK(debug_lock);
++
++ spin_lock_irqsave(&debug_lock, flags);
++
++ printk("vcpu %d\n ", cpu);
++
++ for_each_online_cpu(i) {
++ struct vcpu_info *v = per_cpu(xen_vcpu, i);
++ printk("%d: masked=%d pending=%d event_sel %08lx\n ", i,
++ (get_irq_regs() && i == cpu) ? xen_irqs_disabled(get_irq_regs()) : v->evtchn_upcall_mask,
++ v->evtchn_upcall_pending,
++ v->evtchn_pending_sel);
++ }
++ printk("pending:\n ");
++ for(i = ARRAY_SIZE(sh->evtchn_pending)-1; i >= 0; i--)
++ printk("%08lx%s", sh->evtchn_pending[i],
++ i % 8 == 0 ? "\n " : " ");
++ printk("\nmasks:\n ");
++ for(i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--)
++ printk("%08lx%s", sh->evtchn_mask[i],
++ i % 8 == 0 ? "\n " : " ");
++
++ printk("\nunmasked:\n ");
++ for(i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--)
++ printk("%08lx%s", sh->evtchn_pending[i] & ~sh->evtchn_mask[i],
++ i % 8 == 0 ? "\n " : " ");
++
++ printk("\npending list:\n");
++ for(i = 0; i < NR_EVENT_CHANNELS; i++) {
++ if (sync_test_bit(i, sh->evtchn_pending)) {
++ printk(" %d: event %d -> irq %d\n",
++ cpu_evtchn[i], i,
++ evtchn_to_irq[i]);
++ }
++ }
++
++ spin_unlock_irqrestore(&debug_lock, flags);
++
++ return IRQ_HANDLED;
++}
++
++
++/*
++ * Search the CPUs pending events bitmasks. For each one found, map
++ * the event number to an irq, and feed it into do_IRQ() for
++ * handling.
++ *
++ * Xen uses a two-level bitmap to speed searching. The first level is
++ * a bitset of words which contain pending event bits. The second
++ * level is a bitset of pending events themselves.
++ */
++void xen_evtchn_do_upcall(struct pt_regs *regs)
++{
++ int cpu = get_cpu();
++ struct shared_info *s = HYPERVISOR_shared_info;
++ struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu);
++ static DEFINE_PER_CPU(unsigned, nesting_count);
++ unsigned count;
++
++ do {
++ unsigned long pending_words;
++
++ vcpu_info->evtchn_upcall_pending = 0;
++
++ if (__get_cpu_var(nesting_count)++)
++ goto out;
++
++#ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */
++ /* Clear master flag /before/ clearing selector flag. */
++ rmb();
++#endif
++ pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0);
++ while (pending_words != 0) {
++ unsigned long pending_bits;
++ int word_idx = __ffs(pending_words);
++ pending_words &= ~(1UL << word_idx);
++
++ while ((pending_bits = active_evtchns(cpu, s, word_idx)) != 0) {
++ int bit_idx = __ffs(pending_bits);
++ int port = (word_idx * BITS_PER_LONG) + bit_idx;
++ int irq = evtchn_to_irq[port];
++
++ if (irq != -1)
++ xen_do_IRQ(irq, regs);
++ }
++ }
++
++ BUG_ON(!irqs_disabled());
++
++ count = __get_cpu_var(nesting_count);
++ __get_cpu_var(nesting_count) = 0;
++ } while(count != 1);
++
++out:
++ put_cpu();
++}
++
++/* Rebind an evtchn so that it gets delivered to a specific cpu */
++static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
++{
++ struct evtchn_bind_vcpu bind_vcpu;
++ int evtchn = evtchn_from_irq(irq);
++
++ if (!VALID_EVTCHN(evtchn))
++ return;
++
++ /* Send future instances of this interrupt to other vcpu. */
++ bind_vcpu.port = evtchn;
++ bind_vcpu.vcpu = tcpu;
++
++ /*
++ * If this fails, it usually just indicates that we're dealing with a
++ * virq or IPI channel, which don't actually need to be rebound. Ignore
++ * it, but don't do the xenlinux-level rebind in that case.
++ */
++ if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0)
++ bind_evtchn_to_cpu(evtchn, tcpu);
++}
++
++
++static void set_affinity_irq(unsigned irq, cpumask_t dest)
++{
++ unsigned tcpu = first_cpu(dest);
++ rebind_irq_to_cpu(irq, tcpu);
++}
++
++int resend_irq_on_evtchn(unsigned int irq)
++{
++ int masked, evtchn = evtchn_from_irq(irq);
++ struct shared_info *s = HYPERVISOR_shared_info;
++
++ if (!VALID_EVTCHN(evtchn))
++ return 1;
++
++ masked = sync_test_and_set_bit(evtchn, s->evtchn_mask);
++ sync_set_bit(evtchn, s->evtchn_pending);
++ if (!masked)
++ unmask_evtchn(evtchn);
++
++ return 1;
++}
++
++static void enable_dynirq(unsigned int irq)
++{
++ int evtchn = evtchn_from_irq(irq);
++
++ if (VALID_EVTCHN(evtchn))
++ unmask_evtchn(evtchn);
++}
++
++static void disable_dynirq(unsigned int irq)
++{
++ int evtchn = evtchn_from_irq(irq);
++
++ if (VALID_EVTCHN(evtchn))
++ mask_evtchn(evtchn);
++}
++
++static void ack_dynirq(unsigned int irq)
++{
++ int evtchn = evtchn_from_irq(irq);
++
++ move_native_irq(irq);
++
++ if (VALID_EVTCHN(evtchn))
++ clear_evtchn(evtchn);
++}
++
++static int retrigger_dynirq(unsigned int irq)
++{
++ int evtchn = evtchn_from_irq(irq);
++ struct shared_info *sh = HYPERVISOR_shared_info;
++ int ret = 0;
++
++ if (VALID_EVTCHN(evtchn)) {
++ int masked;
++
++ masked = sync_test_and_set_bit(evtchn, sh->evtchn_mask);
++ sync_set_bit(evtchn, sh->evtchn_pending);
++ if (!masked)
++ unmask_evtchn(evtchn);
++ ret = 1;
++ }
++
++ return ret;
++}
++
++static struct irq_chip xen_dynamic_chip __read_mostly = {
++ .name = "xen-dyn",
++ .mask = disable_dynirq,
++ .unmask = enable_dynirq,
++ .ack = ack_dynirq,
++ .set_affinity = set_affinity_irq,
++ .retrigger = retrigger_dynirq,
++};
++
++void __init xen_init_IRQ(void)
++{
++ int i;
++
++ init_evtchn_cpu_bindings();
++
++ /* No event channels are 'live' right now. */
++ for (i = 0; i < NR_EVENT_CHANNELS; i++)
++ mask_evtchn(i);
++
++ /* Dynamic IRQ space is currently unbound. Zero the refcnts. */
++ for (i = 0; i < NR_IRQS; i++)
++ irq_bindcount[i] = 0;
++
++ irq_ctx_init(smp_processor_id());
++}
+diff --git a/drivers/xen/features.c b/drivers/xen/features.c
+new file mode 100644
+index 0000000..0707714
+--- /dev/null
++++ b/drivers/xen/features.c
+@@ -0,0 +1,29 @@
++/******************************************************************************
++ * features.c
++ *
++ * Xen feature flags.
++ *
++ * Copyright (c) 2006, Ian Campbell, XenSource Inc.
++ */
++#include <linux/types.h>
++#include <linux/cache.h>
++#include <linux/module.h>
++#include <asm/xen/hypervisor.h>
++#include <xen/features.h>
++
++u8 xen_features[XENFEAT_NR_SUBMAPS * 32] __read_mostly;
++EXPORT_SYMBOL_GPL(xen_features);
++
++void xen_setup_features(void)
++{
++ struct xen_feature_info fi;
++ int i, j;
++
++ for (i = 0; i < XENFEAT_NR_SUBMAPS; i++) {
++ fi.submap_idx = i;
++ if (HYPERVISOR_xen_version(XENVER_get_features, &fi) < 0)
++ break;
++ for (j = 0; j < 32; j++)
++ xen_features[i * 32 + j] = !!(fi.submap & 1<<j);
++ }
++}
+diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
+index d85dc6d..52b6b41 100644
+--- a/drivers/xen/grant-table.c
++++ b/drivers/xen/grant-table.c
+@@ -439,24 +439,6 @@ static inline unsigned int max_nr_grant_frames(void)
+ return xen_max;
+ }
+
+-static int map_pte_fn(pte_t *pte, struct page *pmd_page,
+- unsigned long addr, void *data)
+-{
+- unsigned long **frames = (unsigned long **)data;
+-
+- set_pte_at(&init_mm, addr, pte, mfn_pte((*frames)[0], PAGE_KERNEL));
+- (*frames)++;
+- return 0;
+-}
+-
+-static int unmap_pte_fn(pte_t *pte, struct page *pmd_page,
+- unsigned long addr, void *data)
+-{
+-
+- set_pte_at(&init_mm, addr, pte, __pte(0));
+- return 0;
+-}
+-
+ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
+ {
+ struct gnttab_setup_table setup;
+@@ -470,7 +452,7 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
+
+ setup.dom = DOMID_SELF;
+ setup.nr_frames = nr_gframes;
+- setup.frame_list = frames;
++ set_xen_guest_handle(setup.frame_list, frames);
+
+ rc = HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
+ if (rc == -ENOSYS) {
+@@ -480,17 +462,9 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
+
+ BUG_ON(rc || setup.status);
+
+- if (shared == NULL) {
+- struct vm_struct *area;
+- area = alloc_vm_area(PAGE_SIZE * max_nr_grant_frames());
+- BUG_ON(area == NULL);
+- shared = area->addr;
+- }
+- rc = apply_to_page_range(&init_mm, (unsigned long)shared,
+- PAGE_SIZE * nr_gframes,
+- map_pte_fn, &frames);
++ rc = arch_gnttab_map_shared(frames, nr_gframes, max_nr_grant_frames(),
++ &shared);
+ BUG_ON(rc);
+- frames -= nr_gframes; /* adjust after map_pte_fn() */
+
+ kfree(frames);
+
+@@ -506,10 +480,7 @@ static int gnttab_resume(void)
+
+ static int gnttab_suspend(void)
+ {
+- apply_to_page_range(&init_mm, (unsigned long)shared,
+- PAGE_SIZE * nr_grant_frames,
+- unmap_pte_fn, NULL);
+-
++ arch_gnttab_unmap_shared(shared, nr_grant_frames);
+ return 0;
+ }
+
+diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
+index 9fd2f70..0f86b0f 100644
+--- a/drivers/xen/xenbus/xenbus_client.c
++++ b/drivers/xen/xenbus/xenbus_client.c
+@@ -399,7 +399,7 @@ int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr)
+
+ *vaddr = NULL;
+
+- area = alloc_vm_area(PAGE_SIZE);
++ area = xen_alloc_vm_area(PAGE_SIZE);
+ if (!area)
+ return -ENOMEM;
+
+@@ -409,7 +409,7 @@ int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr)
+ BUG();
+
+ if (op.status != GNTST_okay) {
+- free_vm_area(area);
++ xen_free_vm_area(area);
+ xenbus_dev_fatal(dev, op.status,
+ "mapping in shared page %d from domain %d",
+ gnt_ref, dev->otherend_id);
+@@ -508,7 +508,7 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr)
+ BUG();
+
+ if (op.status == GNTST_okay)
+- free_vm_area(area);
++ xen_free_vm_area(area);
+ else
+ xenbus_dev_error(dev, op.status,
+ "unmapping page at handle %d error %d",
+diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
+index 4750de3..57ceb53 100644
+--- a/drivers/xen/xenbus/xenbus_probe.c
++++ b/drivers/xen/xenbus/xenbus_probe.c
+@@ -88,6 +88,16 @@ int xenbus_match(struct device *_dev, struct device_driver *_drv)
+ return match_device(drv->ids, to_xenbus_device(_dev)) != NULL;
+ }
+
++static int xenbus_uevent(struct device *_dev, struct kobj_uevent_env *env)
++{
++ struct xenbus_device *dev = to_xenbus_device(_dev);
++
++ if (add_uevent_var(env, "MODALIAS=xen:%s", dev->devicetype))
++ return -ENOMEM;
++
++ return 0;
++}
++
+ /* device/<type>/<id> => <type>-<id> */
+ static int frontend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename)
+ {
+@@ -166,6 +176,7 @@ static struct xen_bus_type xenbus_frontend = {
+ .bus = {
+ .name = "xen",
+ .match = xenbus_match,
++ .uevent = xenbus_uevent,
+ .probe = xenbus_dev_probe,
+ .remove = xenbus_dev_remove,
+ .shutdown = xenbus_dev_shutdown,
+@@ -438,6 +449,12 @@ static ssize_t xendev_show_devtype(struct device *dev,
+ }
+ DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL);
+
++static ssize_t xendev_show_modalias(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ return sprintf(buf, "xen:%s\n", to_xenbus_device(dev)->devicetype);
++}
++DEVICE_ATTR(modalias, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_modalias, NULL);
+
+ int xenbus_probe_node(struct xen_bus_type *bus,
+ const char *type,
+@@ -492,10 +509,16 @@ int xenbus_probe_node(struct xen_bus_type *bus,
+
+ err = device_create_file(&xendev->dev, &dev_attr_devtype);
+ if (err)
+- goto fail_remove_file;
++ goto fail_remove_nodename;
++
++ err = device_create_file(&xendev->dev, &dev_attr_modalias);
++ if (err)
++ goto fail_remove_devtype;
+
+ return 0;
+-fail_remove_file:
++fail_remove_devtype:
++ device_remove_file(&xendev->dev, &dev_attr_devtype);
++fail_remove_nodename:
+ device_remove_file(&xendev->dev, &dev_attr_nodename);
+ fail_unregister:
+ device_unregister(&xendev->dev);
+@@ -846,6 +869,7 @@ static int is_disconnected_device(struct device *dev, void *data)
+ {
+ struct xenbus_device *xendev = to_xenbus_device(dev);
+ struct device_driver *drv = data;
++ struct xenbus_driver *xendrv;
+
+ /*
+ * A device with no driver will never connect. We care only about
+@@ -858,7 +882,9 @@ static int is_disconnected_device(struct device *dev, void *data)
+ if (drv && (dev->driver != drv))
+ return 0;
+
+- return (xendev->state != XenbusStateConnected);
++ xendrv = to_xenbus_driver(dev->driver);
++ return (xendev->state != XenbusStateConnected ||
++ (xendrv->is_ready && !xendrv->is_ready(xendev)));
+ }
+
+ static int exists_disconnected_device(struct device_driver *drv)
+diff --git a/drivers/xen/xencomm.c b/drivers/xen/xencomm.c
+new file mode 100644
+index 0000000..797cb4e
+--- /dev/null
++++ b/drivers/xen/xencomm.c
+@@ -0,0 +1,232 @@
++/*
++ * 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
++ *
++ * Copyright (C) IBM Corp. 2006
++ *
++ * Authors: Hollis Blanchard <hollisb at us.ibm.com>
++ */
++
++#include <linux/gfp.h>
++#include <linux/mm.h>
++#include <asm/page.h>
++#include <xen/xencomm.h>
++#include <xen/interface/xen.h>
++#ifdef __ia64__
++#include <asm/xen/xencomm.h> /* for is_kern_addr() */
++#endif
++
++#ifdef HAVE_XEN_PLATFORM_COMPAT_H
++#include <xen/platform-compat.h>
++#endif
++
++static int xencomm_init(struct xencomm_desc *desc,
++ void *buffer, unsigned long bytes)
++{
++ unsigned long recorded = 0;
++ int i = 0;
++
++ while ((recorded < bytes) && (i < desc->nr_addrs)) {
++ unsigned long vaddr = (unsigned long)buffer + recorded;
++ unsigned long paddr;
++ int offset;
++ int chunksz;
++
++ offset = vaddr % PAGE_SIZE; /* handle partial pages */
++ chunksz = min(PAGE_SIZE - offset, bytes - recorded);
++
++ paddr = xencomm_vtop(vaddr);
++ if (paddr == ~0UL) {
++ printk(KERN_DEBUG "%s: couldn't translate vaddr %lx\n",
++ __func__, vaddr);
++ return -EINVAL;
++ }
++
++ desc->address[i++] = paddr;
++ recorded += chunksz;
++ }
++
++ if (recorded < bytes) {
++ printk(KERN_DEBUG
++ "%s: could only translate %ld of %ld bytes\n",
++ __func__, recorded, bytes);
++ return -ENOSPC;
++ }
++
++ /* mark remaining addresses invalid (just for safety) */
++ while (i < desc->nr_addrs)
++ desc->address[i++] = XENCOMM_INVALID;
++
++ desc->magic = XENCOMM_MAGIC;
++
++ return 0;
++}
++
++static struct xencomm_desc *xencomm_alloc(gfp_t gfp_mask,
++ void *buffer, unsigned long bytes)
++{
++ struct xencomm_desc *desc;
++ unsigned long buffer_ulong = (unsigned long)buffer;
++ unsigned long start = buffer_ulong & PAGE_MASK;
++ unsigned long end = (buffer_ulong + bytes) | ~PAGE_MASK;
++ unsigned long nr_addrs = (end - start + 1) >> PAGE_SHIFT;
++ unsigned long size = sizeof(*desc) +
++ sizeof(desc->address[0]) * nr_addrs;
++
++ /*
++ * slab allocator returns at least sizeof(void*) aligned pointer.
++ * When sizeof(*desc) > sizeof(void*), struct xencomm_desc might
++ * cross page boundary.
++ */
++ if (sizeof(*desc) > sizeof(void *)) {
++ unsigned long order = get_order(size);
++ desc = (struct xencomm_desc *)__get_free_pages(gfp_mask,
++ order);
++ if (desc == NULL)
++ return NULL;
++
++ desc->nr_addrs =
++ ((PAGE_SIZE << order) - sizeof(struct xencomm_desc)) /
++ sizeof(*desc->address);
++ } else {
++ desc = kmalloc(size, gfp_mask);
++ if (desc == NULL)
++ return NULL;
++
++ desc->nr_addrs = nr_addrs;
++ }
++ return desc;
++}
++
++void xencomm_free(struct xencomm_handle *desc)
++{
++ if (desc && !((ulong)desc & XENCOMM_INLINE_FLAG)) {
++ struct xencomm_desc *desc__ = (struct xencomm_desc *)desc;
++ if (sizeof(*desc__) > sizeof(void *)) {
++ unsigned long size = sizeof(*desc__) +
++ sizeof(desc__->address[0]) * desc__->nr_addrs;
++ unsigned long order = get_order(size);
++ free_pages((unsigned long)__va(desc), order);
++ } else
++ kfree(__va(desc));
++ }
++}
++
++static int xencomm_create(void *buffer, unsigned long bytes,
++ struct xencomm_desc **ret, gfp_t gfp_mask)
++{
++ struct xencomm_desc *desc;
++ int rc;
++
++ pr_debug("%s: %p[%ld]\n", __func__, buffer, bytes);
++
++ if (bytes == 0) {
++ /* don't create a descriptor; Xen recognizes NULL. */
++ BUG_ON(buffer != NULL);
++ *ret = NULL;
++ return 0;
++ }
++
++ BUG_ON(buffer == NULL); /* 'bytes' is non-zero */
++
++ desc = xencomm_alloc(gfp_mask, buffer, bytes);
++ if (!desc) {
++ printk(KERN_DEBUG "%s failure\n", "xencomm_alloc");
++ return -ENOMEM;
++ }
++
++ rc = xencomm_init(desc, buffer, bytes);
++ if (rc) {
++ printk(KERN_DEBUG "%s failure: %d\n", "xencomm_init", rc);
++ xencomm_free((struct xencomm_handle *)__pa(desc));
++ return rc;
++ }
++
++ *ret = desc;
++ return 0;
++}
++
++/* check if memory address is within VMALLOC region */
++static int is_phys_contiguous(unsigned long addr)
++{
++ if (!is_kernel_addr(addr))
++ return 0;
++
++ return (addr < VMALLOC_START) || (addr >= VMALLOC_END);
++}
++
++static struct xencomm_handle *xencomm_create_inline(void *ptr)
++{
++ unsigned long paddr;
++
++ BUG_ON(!is_phys_contiguous((unsigned long)ptr));
++
++ paddr = (unsigned long)xencomm_pa(ptr);
++ BUG_ON(paddr & XENCOMM_INLINE_FLAG);
++ return (struct xencomm_handle *)(paddr | XENCOMM_INLINE_FLAG);
++}
++
++/* "mini" routine, for stack-based communications: */
++static int xencomm_create_mini(void *buffer,
++ unsigned long bytes, struct xencomm_mini *xc_desc,
++ struct xencomm_desc **ret)
++{
++ int rc = 0;
++ struct xencomm_desc *desc;
++ BUG_ON(((unsigned long)xc_desc) % sizeof(*xc_desc) != 0);
++
++ desc = (void *)xc_desc;
++
++ desc->nr_addrs = XENCOMM_MINI_ADDRS;
++
++ rc = xencomm_init(desc, buffer, bytes);
++ if (!rc)
++ *ret = desc;
++
++ return rc;
++}
++
++struct xencomm_handle *xencomm_map(void *ptr, unsigned long bytes)
++{
++ int rc;
++ struct xencomm_desc *desc;
++
++ if (is_phys_contiguous((unsigned long)ptr))
++ return xencomm_create_inline(ptr);
++
++ rc = xencomm_create(ptr, bytes, &desc, GFP_KERNEL);
++
++ if (rc || desc == NULL)
++ return NULL;
++
++ return xencomm_pa(desc);
++}
++
++struct xencomm_handle *__xencomm_map_no_alloc(void *ptr, unsigned long bytes,
++ struct xencomm_mini *xc_desc)
++{
++ int rc;
++ struct xencomm_desc *desc = NULL;
++
++ if (is_phys_contiguous((unsigned long)ptr))
++ return xencomm_create_inline(ptr);
++
++ rc = xencomm_create_mini(ptr, bytes, xc_desc,
++ &desc);
++
++ if (rc)
++ return NULL;
++
++ return xencomm_pa(desc);
++}
+diff --git a/fs/9p/fid.c b/fs/9p/fid.c
+index dfebdbe..3031e32 100644
+--- a/fs/9p/fid.c
++++ b/fs/9p/fid.c
+@@ -26,7 +26,6 @@
+ #include <linux/fs.h>
+ #include <linux/sched.h>
+ #include <linux/idr.h>
+-#include <asm/semaphore.h>
+ #include <net/9p/9p.h>
+ #include <net/9p/client.h>
+
+diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
+index 678c02f..a452ac6 100644
+--- a/fs/9p/vfs_super.c
++++ b/fs/9p/vfs_super.c
+@@ -224,12 +224,11 @@ static int v9fs_show_options(struct seq_file *m, struct vfsmount *mnt)
+ }
+
+ static void
+-v9fs_umount_begin(struct vfsmount *vfsmnt, int flags)
++v9fs_umount_begin(struct super_block *sb)
+ {
+- struct v9fs_session_info *v9ses = vfsmnt->mnt_sb->s_fs_info;
++ struct v9fs_session_info *v9ses = sb->s_fs_info;
+
+- if (flags & MNT_FORCE)
+- v9fs_session_cancel(v9ses);
++ v9fs_session_cancel(v9ses);
+ }
+
+ static const struct super_operations v9fs_super_ops = {
+diff --git a/fs/Kconfig b/fs/Kconfig
+index c509123..2e43d46 100644
+--- a/fs/Kconfig
++++ b/fs/Kconfig
+@@ -411,7 +411,7 @@ config JFS_STATISTICS
+ to be made available to the user in the /proc/fs/jfs/ directory.
+
+ config FS_POSIX_ACL
+-# Posix ACL utility routines (for now, only ext2/ext3/jfs/reiserfs)
++# Posix ACL utility routines (for now, only ext2/ext3/jfs/reiserfs/nfs4)
+ #
+ # NOTE: you can implement Posix ACLs without these helpers (XFS does).
+ # Never use this symbol for ifdefs.
+@@ -444,6 +444,32 @@ config OCFS2_FS
+ For more information on OCFS2, see the file
+ <file:Documentation/filesystems/ocfs2.txt>.
+
++config OCFS2_FS_O2CB
++ tristate "O2CB Kernelspace Clustering"
++ depends on OCFS2_FS
++ default y
++ help
++ OCFS2 includes a simple kernelspace clustering package, the OCFS2
++ Cluster Base. It only requires a very small userspace component
++ to configure it. This comes with the standard ocfs2-tools package.
++ O2CB is limited to maintaining a cluster for OCFS2 file systems.
++ It cannot manage any other cluster applications.
++
++ It is always safe to say Y here, as the clustering method is
++ run-time selectable.
++
++config OCFS2_FS_USERSPACE_CLUSTER
++ tristate "OCFS2 Userspace Clustering"
++ depends on OCFS2_FS && DLM
++ default y
++ help
++ This option will allow OCFS2 to use userspace clustering services
++ in conjunction with the DLM in fs/dlm. If you are using a
++ userspace cluster manager, say Y here.
++
++ It is safe to say Y, as the clustering method is run-time
++ selectable.
++
+ config OCFS2_DEBUG_MASKLOG
+ bool "OCFS2 logging support"
+ depends on OCFS2_FS
+@@ -663,6 +689,7 @@ config ZISOFS
+
+ config UDF_FS
+ tristate "UDF file system support"
++ select CRC_ITU_T
+ help
+ This is the new file system used on some CD-ROMs and DVDs. Say Y if
+ you intend to mount DVD discs or CDRW's written in packet mode, or
+@@ -1637,105 +1664,86 @@ config NFS_V4
+
+ If unsure, say N.
+
+-config NFS_DIRECTIO
+- bool "Allow direct I/O on NFS files"
+- depends on NFS_FS
+- help
+- This option enables applications to perform uncached I/O on files
+- in NFS file systems using the O_DIRECT open() flag. When O_DIRECT
+- is set for a file, its data is not cached in the system's page
+- cache. Data is moved to and from user-level application buffers
+- directly. Unlike local disk-based file systems, NFS O_DIRECT has
+- no alignment restrictions.
+-
+- Unless your program is designed to use O_DIRECT properly, you are
+- much better off allowing the NFS client to manage data caching for
+- you. Misusing O_DIRECT can cause poor server performance or network
+- storms. This kernel build option defaults OFF to avoid exposing
+- system administrators unwittingly to a potentially hazardous
+- feature.
+-
+- For more details on NFS O_DIRECT, see fs/nfs/direct.c.
+-
+- If unsure, say N. This reduces the size of the NFS client, and
+- causes open() to return EINVAL if a file residing in NFS is
+- opened with the O_DIRECT flag.
+-
+ config NFSD
+ tristate "NFS server support"
+ depends on INET
+ select LOCKD
+ select SUNRPC
+ select EXPORTFS
+- select NFSD_V2_ACL if NFSD_V3_ACL
+ select NFS_ACL_SUPPORT if NFSD_V2_ACL
+- select NFSD_TCP if NFSD_V4
+- select CRYPTO_MD5 if NFSD_V4
+- select CRYPTO if NFSD_V4
+- select FS_POSIX_ACL if NFSD_V4
+- select PROC_FS if NFSD_V4
+- select PROC_FS if SUNRPC_GSS
+- help
+- If you want your Linux box to act as an NFS *server*, so that other
+- computers on your local network which support NFS can access certain
+- directories on your box transparently, you have two options: you can
+- use the self-contained user space program nfsd, in which case you
+- should say N here, or you can say Y and use the kernel based NFS
+- server. The advantage of the kernel based solution is that it is
+- faster.
+-
+- In either case, you will need support software; the respective
+- locations are given in the file <file:Documentation/Changes> in the
+- NFS section.
+-
+- If you say Y here, you will get support for version 2 of the NFS
+- protocol (NFSv2). If you also want NFSv3, say Y to the next question
+- as well.
+-
+- Please read the NFS-HOWTO, available from
+- <http://www.tldp.org/docs.html#howto>.
+-
+- To compile the NFS server support as a module, choose M here: the
+- module will be called nfsd. If unsure, say N.
++ help
++ Choose Y here if you want to allow other computers to access
++ files residing on this system using Sun's Network File System
++ protocol. To compile the NFS server support as a module,
++ choose M here: the module will be called nfsd.
++
++ You may choose to use a user-space NFS server instead, in which
++ case you can choose N here.
++
++ To export local file systems using NFS, you also need to install
++ user space programs which can be found in the Linux nfs-utils
++ package, available from http://linux-nfs.org/. More detail about
++ the Linux NFS server implementation is available via the
++ exports(5) man page.
++
++ Below you can choose which versions of the NFS protocol are
++ available to clients mounting the NFS server on this system.
++ Support for NFS version 2 (RFC 1094) is always available when
++ CONFIG_NFSD is selected.
++
++ If unsure, say N.
+
+ config NFSD_V2_ACL
+ bool
+ depends on NFSD
+
+ config NFSD_V3
+- bool "Provide NFSv3 server support"
++ bool "NFS server support for NFS version 3"
+ depends on NFSD
+ help
+- If you would like to include the NFSv3 server as well as the NFSv2
+- server, say Y here. If unsure, say Y.
++ This option enables support in your system's NFS server for
++ version 3 of the NFS protocol (RFC 1813).
++
++ If unsure, say Y.
+
+ config NFSD_V3_ACL
+- bool "Provide server support for the NFSv3 ACL protocol extension"
++ bool "NFS server support for the NFSv3 ACL protocol extension"
+ depends on NFSD_V3
++ select NFSD_V2_ACL
+ help
+- Implement the NFSv3 ACL protocol extension for manipulating POSIX
+- Access Control Lists on exported file systems. NFS clients should
+- be compiled with the NFSv3 ACL protocol extension; see the
+- CONFIG_NFS_V3_ACL option. If unsure, say N.
++ Solaris NFS servers support an auxiliary NFSv3 ACL protocol that
++ never became an official part of the NFS version 3 protocol.
++ This protocol extension allows applications on NFS clients to
++ manipulate POSIX Access Control Lists on files residing on NFS
++ servers. NFS servers enforce POSIX ACLs on local files whether
++ this protocol is available or not.
++
++ This option enables support in your system's NFS server for the
++ NFSv3 ACL protocol extension allowing NFS clients to manipulate
++ POSIX ACLs on files exported by your system's NFS server. NFS
++ clients which support the Solaris NFSv3 ACL protocol can then
++ access and modify ACLs on your NFS server.
++
++ To store ACLs on your NFS server, you also need to enable ACL-
++ related CONFIG options for your local file systems of choice.
++
++ If unsure, say N.
+
+ config NFSD_V4
+- bool "Provide NFSv4 server support (EXPERIMENTAL)"
+- depends on NFSD && NFSD_V3 && EXPERIMENTAL
++ bool "NFS server support for NFS version 4 (EXPERIMENTAL)"
++ depends on NFSD && PROC_FS && EXPERIMENTAL
++ select NFSD_V3
++ select FS_POSIX_ACL
+ select RPCSEC_GSS_KRB5
+ help
+- If you would like to include the NFSv4 server as well as the NFSv2
+- and NFSv3 servers, say Y here. This feature is experimental, and
+- should only be used if you are interested in helping to test NFSv4.
+- If unsure, say N.
++ This option enables support in your system's NFS server for
++ version 4 of the NFS protocol (RFC 3530).
+
+-config NFSD_TCP
+- bool "Provide NFS server over TCP support"
+- depends on NFSD
+- default y
+- help
+- If you want your NFS server to support TCP connections, say Y here.
+- TCP connections usually perform better than the default UDP when
+- the network is lossy or congested. If unsure, say Y.
++ To export files using NFSv4, you need to install additional user
++ space programs which can be found in the Linux nfs-utils package,
++ available from http://linux-nfs.org/.
++
++ If unsure, say N.
+
+ config ROOT_NFS
+ bool "Root file system on NFS"
+@@ -1781,15 +1789,33 @@ config SUNRPC_XPRT_RDMA
+ tristate
+ depends on SUNRPC && INFINIBAND && EXPERIMENTAL
+ default SUNRPC && INFINIBAND
++ help
++ This option enables an RPC client transport capability that
++ allows the NFS client to mount servers via an RDMA-enabled
++ transport.
++
++ To compile RPC client RDMA transport support as a module,
++ choose M here: the module will be called xprtrdma.
++
++ If unsure, say N.
+
+ config SUNRPC_BIND34
+ bool "Support for rpcbind versions 3 & 4 (EXPERIMENTAL)"
+ depends on SUNRPC && EXPERIMENTAL
++ default n
+ help
+- Provides kernel support for querying rpcbind servers via versions 3
+- and 4 of the rpcbind protocol. The kernel automatically falls back
+- to version 2 if a remote rpcbind service does not support versions
+- 3 or 4.
++ RPC requests over IPv6 networks require support for larger
++ addresses when performing an RPC bind. Sun added support for
++ IPv6 addressing by creating two new versions of the rpcbind
++ protocol (RFC 1833).
++
++ This option enables support in the kernel RPC client for
++ querying rpcbind servers via versions 3 and 4 of the rpcbind
++ protocol. The kernel automatically falls back to version 2
++ if a remote rpcbind service does not support versions 3 or 4.
++ By themselves, these new versions do not provide support for
++ RPC over IPv6, but the new protocol versions are necessary to
++ support it.
+
+ If unsure, say N to get traditional behavior (version 2 rpcbind
+ requests only).
+@@ -1803,12 +1829,13 @@ config RPCSEC_GSS_KRB5
+ select CRYPTO_DES
+ select CRYPTO_CBC
+ help
+- Provides for secure RPC calls by means of a gss-api
+- mechanism based on Kerberos V5. This is required for
+- NFSv4.
++ Choose Y here to enable Secure RPC using the Kerberos version 5
++ GSS-API mechanism (RFC 1964).
+
+- Note: Requires an auxiliary userspace daemon which may be found on
+- http://www.citi.umich.edu/projects/nfsv4/
++ Secure RPC calls with Kerberos require an auxiliary user-space
++ daemon which may be found in the Linux nfs-utils package
++ available from http://linux-nfs.org/. In addition, user-space
++ Kerberos support should be installed.
+
+ If unsure, say N.
+
+@@ -1822,11 +1849,12 @@ config RPCSEC_GSS_SPKM3
+ select CRYPTO_CAST5
+ select CRYPTO_CBC
+ help
+- Provides for secure RPC calls by means of a gss-api
+- mechanism based on the SPKM3 public-key mechanism.
++ Choose Y here to enable Secure RPC using the SPKM3 public key
++ GSS-API mechansim (RFC 2025).
+
+- Note: Requires an auxiliary userspace daemon which may be found on
+- http://www.citi.umich.edu/projects/nfsv4/
++ Secure RPC calls with SPKM3 require an auxiliary userspace
++ daemon which may be found in the Linux nfs-utils package
++ available from http://linux-nfs.org/.
+
+ If unsure, say N.
+
+diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
+index b5c3b61..853845a 100644
+--- a/fs/Kconfig.binfmt
++++ b/fs/Kconfig.binfmt
+@@ -62,7 +62,7 @@ config BINFMT_SHARED_FLAT
+ config BINFMT_AOUT
+ tristate "Kernel support for a.out and ECOFF binaries"
+ depends on ARCH_SUPPORTS_AOUT && \
+- (X86_32 || ALPHA || ARM || M68K || SPARC32)
++ (X86_32 || ALPHA || ARM || M68K)
+ ---help---
+ A.out (Assembler.OUTput) is a set of formats for libraries and
+ executables used in the earliest versions of UNIX. Linux used
+diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
+index 5e1a4fb..9924581 100644
+--- a/fs/binfmt_elf.c
++++ b/fs/binfmt_elf.c
+@@ -543,7 +543,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+ unsigned long interp_load_addr = 0;
+ unsigned long start_code, end_code, start_data, end_data;
+ unsigned long reloc_func_desc = 0;
+- struct files_struct *files;
+ int executable_stack = EXSTACK_DEFAULT;
+ unsigned long def_flags = 0;
+ struct {
+@@ -593,20 +592,9 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+ goto out_free_ph;
+ }
+
+- files = current->files; /* Refcounted so ok */
+- retval = unshare_files();
+- if (retval < 0)
+- goto out_free_ph;
+- if (files == current->files) {
+- put_files_struct(files);
+- files = NULL;
+- }
+-
+- /* exec will make our files private anyway, but for the a.out
+- loader stuff we need to do it earlier */
+ retval = get_unused_fd();
+ if (retval < 0)
+- goto out_free_fh;
++ goto out_free_ph;
+ get_file(bprm->file);
+ fd_install(elf_exec_fileno = retval, bprm->file);
+
+@@ -728,12 +716,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+ if (retval)
+ goto out_free_dentry;
+
+- /* Discard our unneeded old files struct */
+- if (files) {
+- put_files_struct(files);
+- files = NULL;
+- }
+-
+ /* OK, This is the point of no return */
+ current->flags &= ~PF_FORKNOEXEC;
+ current->mm->def_flags = def_flags;
+@@ -1016,9 +998,6 @@ out_free_interp:
+ kfree(elf_interpreter);
+ out_free_file:
+ sys_close(elf_exec_fileno);
+-out_free_fh:
+- if (files)
+- reset_files_struct(current, files);
+ out_free_ph:
+ kfree(elf_phdata);
+ goto out;
+diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
+index b53c7e5..dbf0ac0 100644
+--- a/fs/binfmt_misc.c
++++ b/fs/binfmt_misc.c
+@@ -110,7 +110,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+ char *iname_addr = iname;
+ int retval;
+ int fd_binary = -1;
+- struct files_struct *files = NULL;
+
+ retval = -ENOEXEC;
+ if (!enabled)
+@@ -133,21 +132,13 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+
+ if (fmt->flags & MISC_FMT_OPEN_BINARY) {
+
+- files = current->files;
+- retval = unshare_files();
+- if (retval < 0)
+- goto _ret;
+- if (files == current->files) {
+- put_files_struct(files);
+- files = NULL;
+- }
+ /* if the binary should be opened on behalf of the
+ * interpreter than keep it open and assign descriptor
+ * to it */
+ fd_binary = get_unused_fd();
+ if (fd_binary < 0) {
+ retval = fd_binary;
+- goto _unshare;
++ goto _ret;
+ }
+ fd_install(fd_binary, bprm->file);
+
+@@ -205,10 +196,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+ if (retval < 0)
+ goto _error;
+
+- if (files) {
+- put_files_struct(files);
+- files = NULL;
+- }
+ _ret:
+ return retval;
+ _error:
+@@ -216,9 +203,6 @@ _error:
+ sys_close(fd_binary);
+ bprm->interp_flags = 0;
+ bprm->interp_data = 0;
+-_unshare:
+- if (files)
+- reset_files_struct(current, files);
+ goto _ret;
+ }
+
+diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c
+index 14c6352..fdc36bf 100644
+--- a/fs/binfmt_som.c
++++ b/fs/binfmt_som.c
+@@ -194,7 +194,6 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+ unsigned long som_entry;
+ struct som_hdr *som_ex;
+ struct som_exec_auxhdr *hpuxhdr;
+- struct files_struct *files;
+
+ /* Get the exec-header */
+ som_ex = (struct som_hdr *) bprm->buf;
+@@ -221,15 +220,6 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+ goto out_free;
+ }
+
+- files = current->files; /* Refcounted so ok */
+- retval = unshare_files();
+- if (retval < 0)
+- goto out_free;
+- if (files == current->files) {
+- put_files_struct(files);
+- files = NULL;
+- }
+-
+ retval = get_unused_fd();
+ if (retval < 0)
+ goto out_free;
+diff --git a/fs/bio.c b/fs/bio.c
+index 553b5b7..6e0b6f6 100644
+--- a/fs/bio.c
++++ b/fs/bio.c
+@@ -444,22 +444,27 @@ int bio_add_page(struct bio *bio, struct page *page, unsigned int len,
+
+ struct bio_map_data {
+ struct bio_vec *iovecs;
+- void __user *userptr;
++ int nr_sgvecs;
++ struct sg_iovec *sgvecs;
+ };
+
+-static void bio_set_map_data(struct bio_map_data *bmd, struct bio *bio)
++static void bio_set_map_data(struct bio_map_data *bmd, struct bio *bio,
++ struct sg_iovec *iov, int iov_count)
+ {
+ memcpy(bmd->iovecs, bio->bi_io_vec, sizeof(struct bio_vec) * bio->bi_vcnt);
++ memcpy(bmd->sgvecs, iov, sizeof(struct sg_iovec) * iov_count);
++ bmd->nr_sgvecs = iov_count;
+ bio->bi_private = bmd;
+ }
+
+ static void bio_free_map_data(struct bio_map_data *bmd)
+ {
+ kfree(bmd->iovecs);
++ kfree(bmd->sgvecs);
+ kfree(bmd);
+ }
+
+-static struct bio_map_data *bio_alloc_map_data(int nr_segs)
++static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count)
+ {
+ struct bio_map_data *bmd = kmalloc(sizeof(*bmd), GFP_KERNEL);
+
+@@ -467,13 +472,71 @@ static struct bio_map_data *bio_alloc_map_data(int nr_segs)
+ return NULL;
+
+ bmd->iovecs = kmalloc(sizeof(struct bio_vec) * nr_segs, GFP_KERNEL);
+- if (bmd->iovecs)
++ if (!bmd->iovecs) {
++ kfree(bmd);
++ return NULL;
++ }
++
++ bmd->sgvecs = kmalloc(sizeof(struct sg_iovec) * iov_count, GFP_KERNEL);
++ if (bmd->sgvecs)
+ return bmd;
+
++ kfree(bmd->iovecs);
+ kfree(bmd);
+ return NULL;
+ }
+
++static int __bio_copy_iov(struct bio *bio, struct sg_iovec *iov, int iov_count,
++ int uncopy)
++{
++ int ret = 0, i;
++ struct bio_vec *bvec;
++ int iov_idx = 0;
++ unsigned int iov_off = 0;
++ int read = bio_data_dir(bio) == READ;
++
++ __bio_for_each_segment(bvec, bio, i, 0) {
++ char *bv_addr = page_address(bvec->bv_page);
++ unsigned int bv_len = bvec->bv_len;
++
++ while (bv_len && iov_idx < iov_count) {
++ unsigned int bytes;
++ char *iov_addr;
++
++ bytes = min_t(unsigned int,
++ iov[iov_idx].iov_len - iov_off, bv_len);
++ iov_addr = iov[iov_idx].iov_base + iov_off;
++
++ if (!ret) {
++ if (!read && !uncopy)
++ ret = copy_from_user(bv_addr, iov_addr,
++ bytes);
++ if (read && uncopy)
++ ret = copy_to_user(iov_addr, bv_addr,
++ bytes);
++
++ if (ret)
++ ret = -EFAULT;
++ }
++
++ bv_len -= bytes;
++ bv_addr += bytes;
++ iov_addr += bytes;
++ iov_off += bytes;
++
++ if (iov[iov_idx].iov_len == iov_off) {
++ iov_idx++;
++ iov_off = 0;
++ }
++ }
++
++ if (uncopy)
++ __free_page(bvec->bv_page);
++ }
++
++ return ret;
++}
++
+ /**
+ * bio_uncopy_user - finish previously mapped bio
+ * @bio: bio being terminated
+@@ -484,55 +547,56 @@ static struct bio_map_data *bio_alloc_map_data(int nr_segs)
+ int bio_uncopy_user(struct bio *bio)
+ {
+ struct bio_map_data *bmd = bio->bi_private;
+- const int read = bio_data_dir(bio) == READ;
+- struct bio_vec *bvec;
+- int i, ret = 0;
++ int ret;
+
+- __bio_for_each_segment(bvec, bio, i, 0) {
+- char *addr = page_address(bvec->bv_page);
+- unsigned int len = bmd->iovecs[i].bv_len;
++ ret = __bio_copy_iov(bio, bmd->sgvecs, bmd->nr_sgvecs, 1);
+
+- if (read && !ret && copy_to_user(bmd->userptr, addr, len))
+- ret = -EFAULT;
+-
+- __free_page(bvec->bv_page);
+- bmd->userptr += len;
+- }
+ bio_free_map_data(bmd);
+ bio_put(bio);
+ return ret;
+ }
+
+ /**
+- * bio_copy_user - copy user data to bio
++ * bio_copy_user_iov - copy user data to bio
+ * @q: destination block queue
+- * @uaddr: start of user address
+- * @len: length in bytes
++ * @iov: the iovec.
++ * @iov_count: number of elements in the iovec
+ * @write_to_vm: bool indicating writing to pages or not
+ *
+ * Prepares and returns a bio for indirect user io, bouncing data
+ * to/from kernel pages as necessary. Must be paired with
+ * call bio_uncopy_user() on io completion.
+ */
+-struct bio *bio_copy_user(struct request_queue *q, unsigned long uaddr,
+- unsigned int len, int write_to_vm)
++struct bio *bio_copy_user_iov(struct request_queue *q, struct sg_iovec *iov,
++ int iov_count, int write_to_vm)
+ {
+- unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+- unsigned long start = uaddr >> PAGE_SHIFT;
+ struct bio_map_data *bmd;
+ struct bio_vec *bvec;
+ struct page *page;
+ struct bio *bio;
+ int i, ret;
++ int nr_pages = 0;
++ unsigned int len = 0;
+
+- bmd = bio_alloc_map_data(end - start);
++ for (i = 0; i < iov_count; i++) {
++ unsigned long uaddr;
++ unsigned long end;
++ unsigned long start;
++
++ uaddr = (unsigned long)iov[i].iov_base;
++ end = (uaddr + iov[i].iov_len + PAGE_SIZE - 1) >> PAGE_SHIFT;
++ start = uaddr >> PAGE_SHIFT;
++
++ nr_pages += end - start;
++ len += iov[i].iov_len;
++ }
++
++ bmd = bio_alloc_map_data(nr_pages, iov_count);
+ if (!bmd)
+ return ERR_PTR(-ENOMEM);
+
+- bmd->userptr = (void __user *) uaddr;
+-
+ ret = -ENOMEM;
+- bio = bio_alloc(GFP_KERNEL, end - start);
++ bio = bio_alloc(GFP_KERNEL, nr_pages);
+ if (!bio)
+ goto out_bmd;
+
+@@ -564,22 +628,12 @@ struct bio *bio_copy_user(struct request_queue *q, unsigned long uaddr,
+ * success
+ */
+ if (!write_to_vm) {
+- char __user *p = (char __user *) uaddr;
+-
+- /*
+- * for a write, copy in data to kernel pages
+- */
+- ret = -EFAULT;
+- bio_for_each_segment(bvec, bio, i) {
+- char *addr = page_address(bvec->bv_page);
+-
+- if (copy_from_user(addr, p, bvec->bv_len))
+- goto cleanup;
+- p += bvec->bv_len;
+- }
++ ret = __bio_copy_iov(bio, iov, iov_count, 0);
++ if (ret)
++ goto cleanup;
+ }
+
+- bio_set_map_data(bmd, bio);
++ bio_set_map_data(bmd, bio, iov, iov_count);
+ return bio;
+ cleanup:
+ bio_for_each_segment(bvec, bio, i)
+@@ -591,6 +645,28 @@ out_bmd:
+ return ERR_PTR(ret);
+ }
+
++/**
++ * bio_copy_user - copy user data to bio
++ * @q: destination block queue
++ * @uaddr: start of user address
++ * @len: length in bytes
++ * @write_to_vm: bool indicating writing to pages or not
++ *
++ * Prepares and returns a bio for indirect user io, bouncing data
++ * to/from kernel pages as necessary. Must be paired with
++ * call bio_uncopy_user() on io completion.
++ */
++struct bio *bio_copy_user(struct request_queue *q, unsigned long uaddr,
++ unsigned int len, int write_to_vm)
++{
++ struct sg_iovec iov;
++
++ iov.iov_base = (void __user *)uaddr;
++ iov.iov_len = len;
++
++ return bio_copy_user_iov(q, &iov, 1, write_to_vm);
++}
++
+ static struct bio *__bio_map_user_iov(struct request_queue *q,
+ struct block_device *bdev,
+ struct sg_iovec *iov, int iov_count,
+diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
+index dbd9146..05c9da6 100644
+--- a/fs/cifs/CHANGES
++++ b/fs/cifs/CHANGES
+@@ -8,7 +8,8 @@ of second share to disconnected server session (autoreconnect on this).
+ Add ability to modify cifs acls for handling chmod (when mounted with
+ cifsacl flag). Fix prefixpath path separator so we can handle mounts
+ with prefixpaths longer than one directory (one path component) when
+-mounted to Windows servers.
++mounted to Windows servers. Fix slow file open when cifsacl
++enabled.
+
+ Version 1.51
+ ------------
+diff --git a/fs/cifs/README b/fs/cifs/README
+index 5030622..621aa1a 100644
+--- a/fs/cifs/README
++++ b/fs/cifs/README
+@@ -3,7 +3,14 @@ features such as hierarchical dfs like namespace, hardlinks, locking and more.
+ It was designed to comply with the SNIA CIFS Technical Reference (which
+ supersedes the 1992 X/Open SMB Standard) as well as to perform best practice
+ practical interoperability with Windows 2000, Windows XP, Samba and equivalent
+-servers.
++servers. This code was developed in participation with the Protocol Freedom
++Information Foundation.
++
++Please see
++ http://protocolfreedom.org/ and
++ http://samba.org/samba/PFIF/
++for more details.
++
+
+ For questions or bug reports please contact:
+ sfrench at samba.org (sfrench at us.ibm.com)
+diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
+index 56c9240..95024c0 100644
+--- a/fs/cifs/cifs_dfs_ref.c
++++ b/fs/cifs/cifs_dfs_ref.c
+@@ -23,16 +23,28 @@
+ #include "dns_resolve.h"
+ #include "cifs_debug.h"
+
+-LIST_HEAD(cifs_dfs_automount_list);
++static LIST_HEAD(cifs_dfs_automount_list);
+
+-/*
+- * DFS functions
+-*/
++static void cifs_dfs_expire_automounts(struct work_struct *work);
++static DECLARE_DELAYED_WORK(cifs_dfs_automount_task,
++ cifs_dfs_expire_automounts);
++static int cifs_dfs_mountpoint_expiry_timeout = 500 * HZ;
++
++static void cifs_dfs_expire_automounts(struct work_struct *work)
++{
++ struct list_head *list = &cifs_dfs_automount_list;
++
++ mark_mounts_for_expiry(list);
++ if (!list_empty(list))
++ schedule_delayed_work(&cifs_dfs_automount_task,
++ cifs_dfs_mountpoint_expiry_timeout);
++}
+
+-void dfs_shrink_umount_helper(struct vfsmount *vfsmnt)
++void cifs_dfs_release_automount_timer(void)
+ {
+- mark_mounts_for_expiry(&cifs_dfs_automount_list);
+- mark_mounts_for_expiry(&cifs_dfs_automount_list);
++ BUG_ON(!list_empty(&cifs_dfs_automount_list));
++ cancel_delayed_work(&cifs_dfs_automount_task);
++ flush_scheduled_work();
+ }
+
+ /**
+@@ -261,10 +273,11 @@ static int add_mount_helper(struct vfsmount *newmnt, struct nameidata *nd,
+ err = do_add_mount(newmnt, nd, nd->path.mnt->mnt_flags, mntlist);
+ switch (err) {
+ case 0:
+- dput(nd->path.dentry);
+- mntput(nd->path.mnt);
++ path_put(&nd->path);
+ nd->path.mnt = newmnt;
+ nd->path.dentry = dget(newmnt->mnt_root);
++ schedule_delayed_work(&cifs_dfs_automount_task,
++ cifs_dfs_mountpoint_expiry_timeout);
+ break;
+ case -EBUSY:
+ /* someone else made a mount here whilst we were busy */
+diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
+index 1cb5b0a..e99d4fa 100644
+--- a/fs/cifs/cifsacl.c
++++ b/fs/cifs/cifsacl.c
+@@ -516,7 +516,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
+
+ /* Convert permission bits from mode to equivalent CIFS ACL */
+ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
+- int acl_len, struct inode *inode, __u64 nmode)
++ struct inode *inode, __u64 nmode)
+ {
+ int rc = 0;
+ __u32 dacloffset;
+@@ -692,14 +692,14 @@ void acl_to_uid_mode(struct inode *inode, const char *path, const __u16 *pfid)
+ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
+ {
+ int rc = 0;
+- __u32 acllen = 0;
++ __u32 secdesclen = 0;
+ struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
+ struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
+
+ cFYI(DBG2, ("set ACL from mode for %s", path));
+
+ /* Get the security descriptor */
+- pntsd = get_cifs_acl(&acllen, inode, path, NULL);
++ pntsd = get_cifs_acl(&secdesclen, inode, path, NULL);
+
+ /* Add three ACEs for owner, group, everyone getting rid of
+ other ACEs as chmod disables ACEs and set the security descriptor */
+@@ -709,20 +709,22 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
+ set security descriptor request security descriptor
+ parameters, and secuirty descriptor itself */
+
+- pnntsd = kmalloc(acllen, GFP_KERNEL);
++ secdesclen = secdesclen < DEFSECDESCLEN ?
++ DEFSECDESCLEN : secdesclen;
++ pnntsd = kmalloc(secdesclen, GFP_KERNEL);
+ if (!pnntsd) {
+ cERROR(1, ("Unable to allocate security descriptor"));
+ kfree(pntsd);
+ return (-ENOMEM);
+ }
+
+- rc = build_sec_desc(pntsd, pnntsd, acllen, inode, nmode);
++ rc = build_sec_desc(pntsd, pnntsd, inode, nmode);
+
+ cFYI(DBG2, ("build_sec_desc rc: %d", rc));
+
+ if (!rc) {
+ /* Set the security descriptor */
+- rc = set_cifs_acl(pnntsd, acllen, inode, path);
++ rc = set_cifs_acl(pnntsd, secdesclen, inode, path);
+ cFYI(DBG2, ("set_cifs_acl rc: %d", rc));
+ }
+
+diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h
+index 93a7c34..6c8096c 100644
+--- a/fs/cifs/cifsacl.h
++++ b/fs/cifs/cifsacl.h
+@@ -27,6 +27,7 @@
+ #define NUM_SUBAUTHS 5 /* number of sub authority fields */
+ #define NUM_WK_SIDS 7 /* number of well known sids */
+ #define SIDNAMELENGTH 20 /* long enough for the ones we care about */
++#define DEFSECDESCLEN 192 /* sec desc len contaiting a dacl with three aces */
+
+ #define READ_BIT 0x4
+ #define WRITE_BIT 0x2
+diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
+index a04b17e..39c2cbd 100644
+--- a/fs/cifs/cifsfs.c
++++ b/fs/cifs/cifsfs.c
+@@ -466,16 +466,11 @@ static struct quotactl_ops cifs_quotactl_ops = {
+ };
+ #endif
+
+-static void cifs_umount_begin(struct vfsmount *vfsmnt, int flags)
++static void cifs_umount_begin(struct super_block *sb)
+ {
+- struct cifs_sb_info *cifs_sb;
++ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct cifsTconInfo *tcon;
+
+- dfs_shrink_umount_helper(vfsmnt);
+-
+- if (!(flags & MNT_FORCE))
+- return;
+- cifs_sb = CIFS_SB(vfsmnt->mnt_sb);
+ if (cifs_sb == NULL)
+ return;
+
+@@ -1100,6 +1095,7 @@ exit_cifs(void)
+ cFYI(DBG2, ("exit_cifs"));
+ cifs_proc_clean();
+ #ifdef CONFIG_CIFS_DFS_UPCALL
++ cifs_dfs_release_automount_timer();
+ unregister_key_type(&key_type_dns_resolver);
+ #endif
+ #ifdef CONFIG_CIFS_UPCALL
+diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
+index 6897830..e1dd9f3 100644
+--- a/fs/cifs/cifsfs.h
++++ b/fs/cifs/cifsfs.h
+@@ -62,11 +62,9 @@ extern int cifs_setattr(struct dentry *, struct iattr *);
+
+ extern const struct inode_operations cifs_file_inode_ops;
+ extern const struct inode_operations cifs_symlink_inode_ops;
+-extern struct list_head cifs_dfs_automount_list;
+ extern struct inode_operations cifs_dfs_referral_inode_operations;
+
+
+-
+ /* Functions related to files and directories */
+ extern const struct file_operations cifs_file_ops;
+ extern const struct file_operations cifs_file_direct_ops; /* if directio mnt */
+diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
+index 47f7950..9f49c2f 100644
+--- a/fs/cifs/cifspdu.h
++++ b/fs/cifs/cifspdu.h
+@@ -1,7 +1,7 @@
+ /*
+ * fs/cifs/cifspdu.h
+ *
+- * Copyright (c) International Business Machines Corp., 2002,2007
++ * Copyright (c) International Business Machines Corp., 2002,2008
+ * Author(s): Steve French (sfrench at us.ibm.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+@@ -163,7 +163,10 @@
+ path names in response */
+ #define SMBFLG2_KNOWS_EAS cpu_to_le16(2)
+ #define SMBFLG2_SECURITY_SIGNATURE cpu_to_le16(4)
++#define SMBFLG2_COMPRESSED (8)
++#define SMBFLG2_SECURITY_SIGNATURE_REQUIRED (0x10)
+ #define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40)
++#define SMBFLG2_REPARSE_PATH (0x400)
+ #define SMBFLG2_EXT_SEC cpu_to_le16(0x800)
+ #define SMBFLG2_DFS cpu_to_le16(0x1000)
+ #define SMBFLG2_PAGING_IO cpu_to_le16(0x2000)
+@@ -305,7 +308,7 @@
+ #define FILE_SHARE_DELETE 0x00000004
+ #define FILE_SHARE_ALL 0x00000007
+
+-/* CreateDisposition flags */
++/* CreateDisposition flags, similar to CreateAction as well */
+ #define FILE_SUPERSEDE 0x00000000
+ #define FILE_OPEN 0x00000001
+ #define FILE_CREATE 0x00000002
+@@ -317,15 +320,25 @@
+ #define CREATE_NOT_FILE 0x00000001 /* if set must not be file */
+ #define CREATE_WRITE_THROUGH 0x00000002
+ #define CREATE_SEQUENTIAL 0x00000004
+-#define CREATE_SYNC_ALERT 0x00000010
+-#define CREATE_ASYNC_ALERT 0x00000020
++#define CREATE_NO_BUFFER 0x00000008 /* should not buffer on srv */
++#define CREATE_SYNC_ALERT 0x00000010 /* MBZ */
++#define CREATE_ASYNC_ALERT 0x00000020 /* MBZ */
+ #define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */
++#define CREATE_TREE_CONNECTION 0x00000080 /* should be zero */
++#define CREATE_COMPLETE_IF_OPLK 0x00000100 /* should be zero */
+ #define CREATE_NO_EA_KNOWLEDGE 0x00000200
+-#define CREATE_EIGHT_DOT_THREE 0x00000400
++#define CREATE_EIGHT_DOT_THREE 0x00000400 /* doc says this is obsolete
++ open for recovery flag - should
++ be zero */
+ #define CREATE_RANDOM_ACCESS 0x00000800
+ #define CREATE_DELETE_ON_CLOSE 0x00001000
+ #define CREATE_OPEN_BY_ID 0x00002000
++#define CREATE_OPEN_BACKUP_INTN 0x00004000
++#define CREATE_NO_COMPRESSION 0x00008000
++#define CREATE_RESERVE_OPFILTER 0x00100000 /* should be zero */
+ #define OPEN_REPARSE_POINT 0x00200000
++#define OPEN_NO_RECALL 0x00400000
++#define OPEN_FREE_SPACE_QUERY 0x00800000 /* should be zero */
+ #define CREATE_OPTIONS_MASK 0x007FFFFF
+ #define CREATE_OPTION_SPECIAL 0x20000000 /* system. NB not sent over wire */
+
+@@ -470,7 +483,7 @@ typedef struct lanman_neg_rsp {
+
+ typedef struct negotiate_rsp {
+ struct smb_hdr hdr; /* wct = 17 */
+- __le16 DialectIndex;
++ __le16 DialectIndex; /* 0xFFFF = no dialect acceptable */
+ __u8 SecurityMode;
+ __le16 MaxMpxCount;
+ __le16 MaxNumberVcs;
+@@ -516,10 +529,11 @@ typedef struct negotiate_rsp {
+ #define CAP_INFOLEVEL_PASSTHRU 0x00002000
+ #define CAP_LARGE_READ_X 0x00004000
+ #define CAP_LARGE_WRITE_X 0x00008000
++#define CAP_LWIO 0x00010000 /* support fctl_srv_req_resume_key */
+ #define CAP_UNIX 0x00800000
+-#define CAP_RESERVED 0x02000000
+-#define CAP_BULK_TRANSFER 0x20000000
+-#define CAP_COMPRESSED_DATA 0x40000000
++#define CAP_COMPRESSED_DATA 0x02000000
++#define CAP_DYNAMIC_REAUTH 0x20000000
++#define CAP_PERSISTENT_HANDLES 0x40000000
+ #define CAP_EXTENDED_SECURITY 0x80000000
+
+ typedef union smb_com_session_setup_andx {
+@@ -668,9 +682,7 @@ typedef struct smb_com_tconx_req {
+ } __attribute__((packed)) TCONX_REQ;
+
+ typedef struct smb_com_tconx_rsp {
+- struct smb_hdr hdr; /* wct = 3 note that Win2000 has sent wct = 7
+- in some cases on responses. Four unspecified
+- words followed OptionalSupport */
++ struct smb_hdr hdr; /* wct = 3 , not extended response */
+ __u8 AndXCommand;
+ __u8 AndXReserved;
+ __le16 AndXOffset;
+@@ -680,13 +692,48 @@ typedef struct smb_com_tconx_rsp {
+ /* STRING NativeFileSystem */
+ } __attribute__((packed)) TCONX_RSP;
+
++typedef struct smb_com_tconx_rsp_ext {
++ struct smb_hdr hdr; /* wct = 7, extended response */
++ __u8 AndXCommand;
++ __u8 AndXReserved;
++ __le16 AndXOffset;
++ __le16 OptionalSupport; /* see below */
++ __le32 MaximalShareAccessRights;
++ __le32 GuestMaximalShareAccessRights;
++ __u16 ByteCount;
++ unsigned char Service[1]; /* always ASCII, not Unicode */
++ /* STRING NativeFileSystem */
++} __attribute__((packed)) TCONX_RSP_EXT;
++
++
+ /* tree connect Flags */
+ #define DISCONNECT_TID 0x0001
++#define TCON_EXTENDED_SIGNATURES 0x0004
+ #define TCON_EXTENDED_SECINFO 0x0008
++
+ /* OptionalSupport bits */
+ #define SMB_SUPPORT_SEARCH_BITS 0x0001 /* "must have" directory search bits
+ (exclusive searches supported) */
+ #define SMB_SHARE_IS_IN_DFS 0x0002
++#define SMB_CSC_MASK 0x000C
++/* CSC flags defined as follows */
++#define SMB_CSC_CACHE_MANUAL_REINT 0x0000
++#define SMB_CSC_CACHE_AUTO_REINT 0x0004
++#define SMB_CSC_CACHE_VDO 0x0008
++#define SMB_CSC_NO_CACHING 0x000C
++
++#define SMB_UNIQUE_FILE_NAME 0x0010
++#define SMB_EXTENDED_SIGNATURES 0x0020
++
++/* services
++ *
++ * A: ie disk
++ * LPT1: ie printer
++ * IPC ie named pipe
++ * COMM
++ * ????? ie any type
++ *
++ */
+
+ typedef struct smb_com_logoff_andx_req {
+ struct smb_hdr hdr; /* wct = 2 */
+@@ -750,6 +797,17 @@ typedef struct smb_com_findclose_req {
+ #define COMM_DEV_TYPE 0x0004
+ #define UNKNOWN_TYPE 0xFFFF
+
++/* Device Type or File Status Flags */
++#define NO_EAS 0x0001
++#define NO_SUBSTREAMS 0x0002
++#define NO_REPARSETAG 0x0004
++/* following flags can apply if pipe */
++#define ICOUNT_MASK 0x00FF
++#define PIPE_READ_MODE 0x0100
++#define NAMED_PIPE_TYPE 0x0400
++#define PIPE_END_POINT 0x0800
++#define BLOCKING_NAMED_PIPE 0x8000
++
+ typedef struct smb_com_open_req { /* also handles create */
+ struct smb_hdr hdr; /* wct = 24 */
+ __u8 AndXCommand;
+@@ -758,7 +816,7 @@ typedef struct smb_com_open_req { /* also handles create */
+ __u8 Reserved; /* Must Be Zero */
+ __le16 NameLength;
+ __le32 OpenFlags;
+- __le32 RootDirectoryFid;
++ __u32 RootDirectoryFid;
+ __le32 DesiredAccess;
+ __le64 AllocationSize;
+ __le32 FileAttributes;
+@@ -801,6 +859,32 @@ typedef struct smb_com_open_rsp {
+ __u16 ByteCount; /* bct = 0 */
+ } __attribute__((packed)) OPEN_RSP;
+
++typedef struct smb_com_open_rsp_ext {
++ struct smb_hdr hdr; /* wct = 42 but meaningless due to MS bug? */
++ __u8 AndXCommand;
++ __u8 AndXReserved;
++ __le16 AndXOffset;
++ __u8 OplockLevel;
++ __u16 Fid;
++ __le32 CreateAction;
++ __le64 CreationTime;
++ __le64 LastAccessTime;
++ __le64 LastWriteTime;
++ __le64 ChangeTime;
++ __le32 FileAttributes;
++ __le64 AllocationSize;
++ __le64 EndOfFile;
++ __le16 FileType;
++ __le16 DeviceState;
++ __u8 DirectoryFlag;
++ __u8 VolumeGUID[16];
++ __u64 FileId; /* note no endian conversion - is opaque UniqueID */
++ __le32 MaximalAccessRights;
++ __le32 GuestMaximalAccessRights;
++ __u16 ByteCount; /* bct = 0 */
++} __attribute__((packed)) OPEN_RSP_EXT;
++
++
+ /* format of legacy open request */
+ typedef struct smb_com_openx_req {
+ struct smb_hdr hdr; /* wct = 15 */
+@@ -1703,6 +1787,12 @@ typedef struct smb_com_transaction2_fnext_rsp_parms {
+ #define SMB_QUERY_CIFS_UNIX_INFO 0x200
+ #define SMB_QUERY_POSIX_FS_INFO 0x201
+ #define SMB_QUERY_POSIX_WHO_AM_I 0x202
++#define SMB_REQUEST_TRANSPORT_ENCRYPTION 0x203
++#define SMB_QUERY_FS_PROXY 0x204 /* WAFS enabled. Returns structure
++ FILE_SYSTEM__UNIX_INFO to tell
++ whether new NTIOCTL available
++ (0xACE) for WAN friendly SMB
++ operations to be carried */
+ #define SMB_QUERY_LABEL_INFO 0x3ea
+ #define SMB_QUERY_FS_QUOTA_INFO 0x3ee
+ #define SMB_QUERY_FS_FULL_SIZE_INFO 0x3ef
+@@ -1959,7 +2049,10 @@ typedef struct {
+ #define CIFS_UNIX_LARGE_READ_CAP 0x00000040 /* support reads >128K (up
+ to 0xFFFF00 */
+ #define CIFS_UNIX_LARGE_WRITE_CAP 0x00000080
+-
++#define CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP 0x00000100 /* can do SPNEGO crypt */
++#define CIFS_UNIX_TRANPSORT_ENCRYPTION_MANDATORY_CAP 0x00000200 /* must do */
++#define CIFS_UNIX_PROXY_CAP 0x00000400 /* Proxy cap: 0xACE ioctl and
++ QFS PROXY call */
+ #ifdef CONFIG_CIFS_POSIX
+ /* Can not set pathnames cap yet until we send new posix create SMB since
+ otherwise server can treat such handles opened with older ntcreatex
+diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
+index 7e5e0e7..50f9fda 100644
+--- a/fs/cifs/cifsproto.h
++++ b/fs/cifs/cifsproto.h
+@@ -84,6 +84,7 @@ extern __u16 GetNextMid(struct TCP_Server_Info *server);
+ extern struct oplock_q_entry *AllocOplockQEntry(struct inode *, u16,
+ struct cifsTconInfo *);
+ extern void DeleteOplockQEntry(struct oplock_q_entry *);
++extern void DeleteTconOplockQEntries(struct cifsTconInfo *);
+ extern struct timespec cifs_NTtimeToUnix(u64 utc_nanoseconds_since_1601);
+ extern u64 cifs_UnixTimeToNT(struct timespec);
+ extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time);
+@@ -103,13 +104,7 @@ extern int mode_to_acl(struct inode *inode, const char *path, __u64);
+ extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
+ const char *);
+ extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
+-#ifdef CONFIG_CIFS_DFS_UPCALL
+-extern void dfs_shrink_umount_helper(struct vfsmount *vfsmnt);
+-#else
+-static inline void dfs_shrink_umount_helper(struct vfsmount *vfsmnt)
+-{
+-}
+-#endif /* DFS_UPCALL */
++extern void cifs_dfs_release_automount_timer(void);
+ void cifs_proc_init(void);
+ void cifs_proc_clean(void);
+
+diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
+index 30bbe44..4728fa9 100644
+--- a/fs/cifs/cifssmb.c
++++ b/fs/cifs/cifssmb.c
+@@ -165,17 +165,19 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
+ rc = CIFSTCon(0, tcon->ses, tcon->treeName,
+ tcon, nls_codepage);
+ up(&tcon->ses->sesSem);
+- /* tell server which Unix caps we support */
+- if (tcon->ses->capabilities & CAP_UNIX)
+- reset_cifs_unix_caps(0 /* no xid */,
+- tcon,
+- NULL /* we do not know sb */,
+- NULL /* no vol info */);
+ /* BB FIXME add code to check if wsize needs
+ update due to negotiated smb buffer size
+ shrinking */
+- if (rc == 0)
++ if (rc == 0) {
+ atomic_inc(&tconInfoReconnectCount);
++ /* tell server Unix caps we support */
++ if (tcon->ses->capabilities & CAP_UNIX)
++ reset_cifs_unix_caps(
++ 0 /* no xid */,
++ tcon,
++ NULL /* we do not know sb */,
++ NULL /* no vol info */);
++ }
+
+ cFYI(1, ("reconnect tcon rc = %d", rc));
+ /* Removed call to reopen open files here.
+@@ -310,17 +312,19 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
+ rc = CIFSTCon(0, tcon->ses, tcon->treeName,
+ tcon, nls_codepage);
+ up(&tcon->ses->sesSem);
+- /* tell server which Unix caps we support */
+- if (tcon->ses->capabilities & CAP_UNIX)
+- reset_cifs_unix_caps(0 /* no xid */,
+- tcon,
+- NULL /* do not know sb */,
+- NULL /* no vol info */);
+ /* BB FIXME add code to check if wsize needs
+ update due to negotiated smb buffer size
+ shrinking */
+- if (rc == 0)
++ if (rc == 0) {
+ atomic_inc(&tconInfoReconnectCount);
++ /* tell server Unix caps we support */
++ if (tcon->ses->capabilities & CAP_UNIX)
++ reset_cifs_unix_caps(
++ 0 /* no xid */,
++ tcon,
++ NULL /* do not know sb */,
++ NULL /* no vol info */);
++ }
+
+ cFYI(1, ("reconnect tcon rc = %d", rc));
+ /* Removed call to reopen open files here.
+diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
+index 8dbfa97..e171067 100644
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -3527,6 +3527,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
+ FreeXid(xid);
+ return 0;
+ }
++ DeleteTconOplockQEntries(cifs_sb->tcon);
+ tconInfoFree(cifs_sb->tcon);
+ if ((ses) && (ses->server)) {
+ /* save off task so we do not refer to ses later */
+diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
+index bc673c8..e1031b9 100644
+--- a/fs/cifs/inode.c
++++ b/fs/cifs/inode.c
+@@ -161,12 +161,14 @@ static void cifs_unix_info_to_inode(struct inode *inode,
+ spin_unlock(&inode->i_lock);
+ }
+
+-static const unsigned char *cifs_get_search_path(struct cifsTconInfo *pTcon,
+- const char *search_path)
++static const unsigned char *cifs_get_search_path(struct cifs_sb_info *cifs_sb,
++ const char *search_path)
+ {
+ int tree_len;
+ int path_len;
++ int i;
+ char *tmp_path;
++ struct cifsTconInfo *pTcon = cifs_sb->tcon;
+
+ if (!(pTcon->Flags & SMB_SHARE_IS_IN_DFS))
+ return search_path;
+@@ -180,6 +182,11 @@ static const unsigned char *cifs_get_search_path(struct cifsTconInfo *pTcon,
+ return search_path;
+
+ strncpy(tmp_path, pTcon->treeName, tree_len);
++ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
++ for (i = 0; i < tree_len; i++) {
++ if (tmp_path[i] == '\\')
++ tmp_path[i] = '/';
++ }
+ strncpy(tmp_path+tree_len, search_path, path_len);
+ tmp_path[tree_len+path_len] = 0;
+ return tmp_path;
+@@ -199,7 +206,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
+ pTcon = cifs_sb->tcon;
+ cFYI(1, ("Getting info on %s", search_path));
+
+- full_path = cifs_get_search_path(pTcon, search_path);
++ full_path = cifs_get_search_path(cifs_sb, search_path);
+
+ try_again_CIFSSMBUnixQPathInfo:
+ /* could have done a find first instead but this returns more info */
+@@ -402,7 +409,7 @@ int cifs_get_inode_info(struct inode **pinode,
+ return -ENOMEM;
+ pfindData = (FILE_ALL_INFO *)buf;
+
+- full_path = cifs_get_search_path(pTcon, search_path);
++ full_path = cifs_get_search_path(cifs_sb, search_path);
+
+ try_again_CIFSSMBQPathInfo:
+ /* could do find first instead but this returns more info */
+diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
+index 3612d6c..000ac50 100644
+--- a/fs/cifs/transport.c
++++ b/fs/cifs/transport.c
+@@ -142,6 +142,24 @@ void DeleteOplockQEntry(struct oplock_q_entry *oplockEntry)
+ kmem_cache_free(cifs_oplock_cachep, oplockEntry);
+ }
+
++
++void DeleteTconOplockQEntries(struct cifsTconInfo *tcon)
++{
++ struct oplock_q_entry *temp;
++
++ if (tcon == NULL)
++ return;
++
++ spin_lock(&GlobalMid_Lock);
++ list_for_each_entry(temp, &GlobalOplock_Q, qhead) {
++ if ((temp->tcon) && (temp->tcon == tcon)) {
++ list_del(&temp->qhead);
++ kmem_cache_free(cifs_oplock_cachep, temp);
++ }
++ }
++ spin_unlock(&GlobalMid_Lock);
++}
++
+ int
+ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
+ unsigned int smb_buf_length, struct sockaddr *sin)
+diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
+index 350680f..0c3b618 100644
+--- a/fs/cramfs/inode.c
++++ b/fs/cramfs/inode.c
+@@ -23,7 +23,6 @@
+ #include <linux/buffer_head.h>
+ #include <linux/vfs.h>
+ #include <linux/mutex.h>
+-#include <asm/semaphore.h>
+
+ #include <asm/uaccess.h>
+
+diff --git a/fs/dcache.c b/fs/dcache.c
+index 4345577..3ee588d 100644
+--- a/fs/dcache.c
++++ b/fs/dcache.c
+@@ -1746,12 +1746,21 @@ shouldnt_be_hashed:
+ goto shouldnt_be_hashed;
+ }
+
++static int prepend(char **buffer, int *buflen, const char *str,
++ int namelen)
++{
++ *buflen -= namelen;
++ if (*buflen < 0)
++ return -ENAMETOOLONG;
++ *buffer -= namelen;
++ memcpy(*buffer, str, namelen);
++ return 0;
++}
++
+ /**
+ * d_path - return the path of a dentry
+- * @dentry: dentry to report
+- * @vfsmnt: vfsmnt to which the dentry belongs
+- * @root: root dentry
+- * @rootmnt: vfsmnt to which the root dentry belongs
++ * @path: the dentry/vfsmount to report
++ * @root: root vfsmnt/dentry (may be modified by this function)
+ * @buffer: buffer to return value in
+ * @buflen: buffer length
+ *
+@@ -1761,23 +1770,22 @@ shouldnt_be_hashed:
+ * Returns the buffer or an error code if the path was too long.
+ *
+ * "buflen" should be positive. Caller holds the dcache_lock.
++ *
++ * If path is not reachable from the supplied root, then the value of
++ * root is changed (without modifying refcounts).
+ */
+-static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
+- struct path *root, char *buffer, int buflen)
++char *__d_path(const struct path *path, struct path *root,
++ char *buffer, int buflen)
+ {
++ struct dentry *dentry = path->dentry;
++ struct vfsmount *vfsmnt = path->mnt;
+ char * end = buffer+buflen;
+ char * retval;
+- int namelen;
+-
+- *--end = '\0';
+- buflen--;
+- if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
+- buflen -= 10;
+- end -= 10;
+- if (buflen < 0)
++
++ prepend(&end, &buflen, "\0", 1);
++ if (!IS_ROOT(dentry) && d_unhashed(dentry) &&
++ (prepend(&end, &buflen, " (deleted)", 10) != 0))
+ goto Elong;
+- memcpy(end, " (deleted)", 10);
+- }
+
+ if (buflen < 1)
+ goto Elong;
+@@ -1804,13 +1812,10 @@ static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
+ }
+ parent = dentry->d_parent;
+ prefetch(parent);
+- namelen = dentry->d_name.len;
+- buflen -= namelen + 1;
+- if (buflen < 0)
++ if ((prepend(&end, &buflen, dentry->d_name.name,
++ dentry->d_name.len) != 0) ||
++ (prepend(&end, &buflen, "/", 1) != 0))
+ goto Elong;
+- end -= namelen;
+- memcpy(end, dentry->d_name.name, namelen);
+- *--end = '/';
+ retval = end;
+ dentry = parent;
+ }
+@@ -1818,12 +1823,12 @@ static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
+ return retval;
+
+ global_root:
+- namelen = dentry->d_name.len;
+- buflen -= namelen;
+- if (buflen < 0)
++ retval += 1; /* hit the slash */
++ if (prepend(&retval, &buflen, dentry->d_name.name,
++ dentry->d_name.len) != 0)
+ goto Elong;
+- retval -= namelen-1; /* hit the slash */
+- memcpy(retval, dentry->d_name.name, namelen);
++ root->mnt = vfsmnt;
++ root->dentry = dentry;
+ return retval;
+ Elong:
+ return ERR_PTR(-ENAMETOOLONG);
+@@ -1846,6 +1851,7 @@ char *d_path(struct path *path, char *buf, int buflen)
+ {
+ char *res;
+ struct path root;
++ struct path tmp;
+
+ /*
+ * We have various synthetic filesystems that never get mounted. On
+@@ -1859,10 +1865,11 @@ char *d_path(struct path *path, char *buf, int buflen)
+
+ read_lock(¤t->fs->lock);
+ root = current->fs->root;
+- path_get(¤t->fs->root);
++ path_get(&root);
+ read_unlock(¤t->fs->lock);
+ spin_lock(&dcache_lock);
+- res = __d_path(path->dentry, path->mnt, &root, buf, buflen);
++ tmp = root;
++ res = __d_path(path, &tmp, buf, buflen);
+ spin_unlock(&dcache_lock);
+ path_put(&root);
+ return res;
+@@ -1890,6 +1897,48 @@ char *dynamic_dname(struct dentry *dentry, char *buffer, int buflen,
+ }
+
+ /*
++ * Write full pathname from the root of the filesystem into the buffer.
++ */
++char *dentry_path(struct dentry *dentry, char *buf, int buflen)
++{
++ char *end = buf + buflen;
++ char *retval;
++
++ spin_lock(&dcache_lock);
++ prepend(&end, &buflen, "\0", 1);
++ if (!IS_ROOT(dentry) && d_unhashed(dentry) &&
++ (prepend(&end, &buflen, "//deleted", 9) != 0))
++ goto Elong;
++ if (buflen < 1)
++ goto Elong;
++ /* Get '/' right */
++ retval = end-1;
++ *retval = '/';
++
++ for (;;) {
++ struct dentry *parent;
++ if (IS_ROOT(dentry))
++ break;
++
++ parent = dentry->d_parent;
++ prefetch(parent);
++
++ if ((prepend(&end, &buflen, dentry->d_name.name,
++ dentry->d_name.len) != 0) ||
++ (prepend(&end, &buflen, "/", 1) != 0))
++ goto Elong;
++
++ retval = end;
++ dentry = parent;
++ }
++ spin_unlock(&dcache_lock);
++ return retval;
++Elong:
++ spin_unlock(&dcache_lock);
++ return ERR_PTR(-ENAMETOOLONG);
++}
++
++/*
+ * NOTE! The user-level library version returns a
+ * character pointer. The kernel system call just
+ * returns the length of the buffer filled (which
+@@ -1918,9 +1967,9 @@ asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
+
+ read_lock(¤t->fs->lock);
+ pwd = current->fs->pwd;
+- path_get(¤t->fs->pwd);
++ path_get(&pwd);
+ root = current->fs->root;
+- path_get(¤t->fs->root);
++ path_get(&root);
+ read_unlock(¤t->fs->lock);
+
+ error = -ENOENT;
+@@ -1928,9 +1977,10 @@ asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
+ spin_lock(&dcache_lock);
+ if (pwd.dentry->d_parent == pwd.dentry || !d_unhashed(pwd.dentry)) {
+ unsigned long len;
++ struct path tmp = root;
+ char * cwd;
+
+- cwd = __d_path(pwd.dentry, pwd.mnt, &root, page, PAGE_SIZE);
++ cwd = __d_path(&pwd, &tmp, page, PAGE_SIZE);
+ spin_unlock(&dcache_lock);
+
+ error = PTR_ERR(cwd);
+diff --git a/fs/dlm/Makefile b/fs/dlm/Makefile
+index d248e60..ca1c912 100644
+--- a/fs/dlm/Makefile
++++ b/fs/dlm/Makefile
+@@ -10,6 +10,7 @@ dlm-y := ast.o \
+ midcomms.o \
+ netlink.o \
+ lowcomms.o \
++ plock.o \
+ rcom.o \
+ recover.o \
+ recoverd.o \
+diff --git a/fs/dlm/config.c b/fs/dlm/config.c
+index c3ad1df..eac23bd 100644
+--- a/fs/dlm/config.c
++++ b/fs/dlm/config.c
+@@ -114,7 +114,7 @@ struct cluster_attribute {
+ };
+
+ static ssize_t cluster_set(struct cluster *cl, unsigned int *cl_field,
+- unsigned int *info_field, int check_zero,
++ int *info_field, int check_zero,
+ const char *buf, size_t len)
+ {
+ unsigned int x;
+@@ -284,6 +284,7 @@ struct node {
+ struct list_head list; /* space->members */
+ int nodeid;
+ int weight;
++ int new;
+ };
+
+ static struct configfs_group_operations clusters_ops = {
+@@ -565,6 +566,7 @@ static struct config_item *make_node(struct config_group *g, const char *name)
+ config_item_init_type_name(&nd->item, name, &node_type);
+ nd->nodeid = -1;
+ nd->weight = 1; /* default weight of 1 if none is set */
++ nd->new = 1; /* set to 0 once it's been read by dlm_nodeid_list() */
+
+ mutex_lock(&sp->members_lock);
+ list_add(&nd->list, &sp->members);
+@@ -805,12 +807,13 @@ static void put_comm(struct comm *cm)
+ }
+
+ /* caller must free mem */
+-int dlm_nodeid_list(char *lsname, int **ids_out)
++int dlm_nodeid_list(char *lsname, int **ids_out, int *ids_count_out,
++ int **new_out, int *new_count_out)
+ {
+ struct space *sp;
+ struct node *nd;
+- int i = 0, rv = 0;
+- int *ids;
++ int i = 0, rv = 0, ids_count = 0, new_count = 0;
++ int *ids, *new;
+
+ sp = get_space(lsname);
+ if (!sp)
+@@ -818,23 +821,50 @@ int dlm_nodeid_list(char *lsname, int **ids_out)
+
+ mutex_lock(&sp->members_lock);
+ if (!sp->members_count) {
+- rv = 0;
++ rv = -EINVAL;
++ printk(KERN_ERR "dlm: zero members_count\n");
+ goto out;
+ }
+
+- ids = kcalloc(sp->members_count, sizeof(int), GFP_KERNEL);
++ ids_count = sp->members_count;
++
++ ids = kcalloc(ids_count, sizeof(int), GFP_KERNEL);
+ if (!ids) {
+ rv = -ENOMEM;
+ goto out;
+ }
+
+- rv = sp->members_count;
+- list_for_each_entry(nd, &sp->members, list)
++ list_for_each_entry(nd, &sp->members, list) {
+ ids[i++] = nd->nodeid;
++ if (nd->new)
++ new_count++;
++ }
++
++ if (ids_count != i)
++ printk(KERN_ERR "dlm: bad nodeid count %d %d\n", ids_count, i);
++
++ if (!new_count)
++ goto out_ids;
++
++ new = kcalloc(new_count, sizeof(int), GFP_KERNEL);
++ if (!new) {
++ kfree(ids);
++ rv = -ENOMEM;
++ goto out;
++ }
+
+- if (rv != i)
+- printk("bad nodeid count %d %d\n", rv, i);
++ i = 0;
++ list_for_each_entry(nd, &sp->members, list) {
++ if (nd->new) {
++ new[i++] = nd->nodeid;
++ nd->new = 0;
++ }
++ }
++ *new_count_out = new_count;
++ *new_out = new;
+
++ out_ids:
++ *ids_count_out = ids_count;
+ *ids_out = ids;
+ out:
+ mutex_unlock(&sp->members_lock);
+diff --git a/fs/dlm/config.h b/fs/dlm/config.h
+index a3170fe..4f1d6fc 100644
+--- a/fs/dlm/config.h
++++ b/fs/dlm/config.h
+@@ -35,7 +35,8 @@ extern struct dlm_config_info dlm_config;
+ int dlm_config_init(void);
+ void dlm_config_exit(void);
+ int dlm_node_weight(char *lsname, int nodeid);
+-int dlm_nodeid_list(char *lsname, int **ids_out);
++int dlm_nodeid_list(char *lsname, int **ids_out, int *ids_count_out,
++ int **new_out, int *new_count_out);
+ int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr);
+ int dlm_addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid);
+ int dlm_our_nodeid(void);
+diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
+index d30ea8b..5a7ac33 100644
+--- a/fs/dlm/dlm_internal.h
++++ b/fs/dlm/dlm_internal.h
+@@ -37,14 +37,11 @@
+ #include <linux/jhash.h>
+ #include <linux/miscdevice.h>
+ #include <linux/mutex.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+
+ #include <linux/dlm.h>
+ #include "config.h"
+
+-#define DLM_LOCKSPACE_LEN 64
+-
+ /* Size of the temp buffer midcomms allocates on the stack.
+ We try to make this large enough so most messages fit.
+ FIXME: should sctp make this unnecessary? */
+@@ -133,8 +130,10 @@ struct dlm_member {
+
+ struct dlm_recover {
+ struct list_head list;
+- int *nodeids;
++ int *nodeids; /* nodeids of all members */
+ int node_count;
++ int *new; /* nodeids of new members */
++ int new_count;
+ uint64_t seq;
+ };
+
+@@ -580,6 +579,8 @@ static inline int dlm_no_directory(struct dlm_ls *ls)
+ int dlm_netlink_init(void);
+ void dlm_netlink_exit(void);
+ void dlm_timeout_warn(struct dlm_lkb *lkb);
++int dlm_plock_init(void);
++void dlm_plock_exit(void);
+
+ #ifdef CONFIG_DLM_DEBUG
+ int dlm_register_debugfs(void);
+diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
+index 8f250ac..2d3d102 100644
+--- a/fs/dlm/lock.c
++++ b/fs/dlm/lock.c
+@@ -165,7 +165,7 @@ void dlm_print_lkb(struct dlm_lkb *lkb)
+ lkb->lkb_grmode, lkb->lkb_wait_type, lkb->lkb_ast_type);
+ }
+
+-void dlm_print_rsb(struct dlm_rsb *r)
++static void dlm_print_rsb(struct dlm_rsb *r)
+ {
+ printk(KERN_ERR "rsb: nodeid %d flags %lx first %x rlc %d name %s\n",
+ r->res_nodeid, r->res_flags, r->res_first_lkid,
+@@ -1956,8 +1956,7 @@ static void confirm_master(struct dlm_rsb *r, int error)
+ list_del_init(&lkb->lkb_rsb_lookup);
+ r->res_first_lkid = lkb->lkb_id;
+ _request_lock(r, lkb);
+- } else
+- r->res_nodeid = -1;
++ }
+ break;
+
+ default:
+diff --git a/fs/dlm/lock.h b/fs/dlm/lock.h
+index 05d9c82..88e93c8 100644
+--- a/fs/dlm/lock.h
++++ b/fs/dlm/lock.h
+@@ -13,7 +13,6 @@
+ #ifndef __LOCK_DOT_H__
+ #define __LOCK_DOT_H__
+
+-void dlm_print_rsb(struct dlm_rsb *r);
+ void dlm_dump_rsb(struct dlm_rsb *r);
+ void dlm_print_lkb(struct dlm_lkb *lkb);
+ void dlm_receive_message_saved(struct dlm_ls *ls, struct dlm_message *ms);
+diff --git a/fs/dlm/main.c b/fs/dlm/main.c
+index 58487fb..b80e0aa 100644
+--- a/fs/dlm/main.c
++++ b/fs/dlm/main.c
+@@ -46,10 +46,16 @@ static int __init init_dlm(void)
+ if (error)
+ goto out_user;
+
++ error = dlm_plock_init();
++ if (error)
++ goto out_netlink;
++
+ printk("DLM (built %s %s) installed\n", __DATE__, __TIME__);
+
+ return 0;
+
++ out_netlink:
++ dlm_netlink_exit();
+ out_user:
+ dlm_user_exit();
+ out_debug:
+@@ -66,6 +72,7 @@ static int __init init_dlm(void)
+
+ static void __exit exit_dlm(void)
+ {
++ dlm_plock_exit();
+ dlm_netlink_exit();
+ dlm_user_exit();
+ dlm_config_exit();
+diff --git a/fs/dlm/member.c b/fs/dlm/member.c
+index fa17f5a..26133f0 100644
+--- a/fs/dlm/member.c
++++ b/fs/dlm/member.c
+@@ -210,6 +210,23 @@ int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out)
+ }
+ }
+
++ /* Add an entry to ls_nodes_gone for members that were removed and
++ then added again, so that previous state for these nodes will be
++ cleared during recovery. */
++
++ for (i = 0; i < rv->new_count; i++) {
++ if (!dlm_is_member(ls, rv->new[i]))
++ continue;
++ log_debug(ls, "new nodeid %d is a re-added member", rv->new[i]);
++
++ memb = kzalloc(sizeof(struct dlm_member), GFP_KERNEL);
++ if (!memb)
++ return -ENOMEM;
++ memb->nodeid = rv->new[i];
++ list_add_tail(&memb->list, &ls->ls_nodes_gone);
++ neg++;
++ }
++
+ /* add new members to ls_nodes */
+
+ for (i = 0; i < rv->node_count; i++) {
+@@ -314,15 +331,16 @@ int dlm_ls_stop(struct dlm_ls *ls)
+ int dlm_ls_start(struct dlm_ls *ls)
+ {
+ struct dlm_recover *rv = NULL, *rv_old;
+- int *ids = NULL;
+- int error, count;
++ int *ids = NULL, *new = NULL;
++ int error, ids_count = 0, new_count = 0;
+
+ rv = kzalloc(sizeof(struct dlm_recover), GFP_KERNEL);
+ if (!rv)
+ return -ENOMEM;
+
+- error = count = dlm_nodeid_list(ls->ls_name, &ids);
+- if (error <= 0)
++ error = dlm_nodeid_list(ls->ls_name, &ids, &ids_count,
++ &new, &new_count);
++ if (error < 0)
+ goto fail;
+
+ spin_lock(&ls->ls_recover_lock);
+@@ -337,14 +355,19 @@ int dlm_ls_start(struct dlm_ls *ls)
+ }
+
+ rv->nodeids = ids;
+- rv->node_count = count;
++ rv->node_count = ids_count;
++ rv->new = new;
++ rv->new_count = new_count;
+ rv->seq = ++ls->ls_recover_seq;
+ rv_old = ls->ls_recover_args;
+ ls->ls_recover_args = rv;
+ spin_unlock(&ls->ls_recover_lock);
+
+ if (rv_old) {
++ log_error(ls, "unused recovery %llx %d",
++ (unsigned long long)rv_old->seq, rv_old->node_count);
+ kfree(rv_old->nodeids);
++ kfree(rv_old->new);
+ kfree(rv_old);
+ }
+
+@@ -354,6 +377,7 @@ int dlm_ls_start(struct dlm_ls *ls)
+ fail:
+ kfree(rv);
+ kfree(ids);
++ kfree(new);
+ return error;
+ }
+
+diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c
+new file mode 100644
+index 0000000..d6d6e37
+--- /dev/null
++++ b/fs/dlm/plock.c
+@@ -0,0 +1,439 @@
++/*
++ * Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved.
++ *
++ * This copyrighted material is made available to anyone wishing to use,
++ * modify, copy, or redistribute it subject to the terms and conditions
++ * of the GNU General Public License version 2.
++ */
++
++#include <linux/fs.h>
++#include <linux/miscdevice.h>
++#include <linux/poll.h>
++#include <linux/dlm.h>
++#include <linux/dlm_plock.h>
++
++#include "dlm_internal.h"
++#include "lockspace.h"
++
++static spinlock_t ops_lock;
++static struct list_head send_list;
++static struct list_head recv_list;
++static wait_queue_head_t send_wq;
++static wait_queue_head_t recv_wq;
++
++struct plock_op {
++ struct list_head list;
++ int done;
++ struct dlm_plock_info info;
++};
++
++struct plock_xop {
++ struct plock_op xop;
++ void *callback;
++ void *fl;
++ void *file;
++ struct file_lock flc;
++};
++
++
++static inline void set_version(struct dlm_plock_info *info)
++{
++ info->version[0] = DLM_PLOCK_VERSION_MAJOR;
++ info->version[1] = DLM_PLOCK_VERSION_MINOR;
++ info->version[2] = DLM_PLOCK_VERSION_PATCH;
++}
++
++static int check_version(struct dlm_plock_info *info)
++{
++ if ((DLM_PLOCK_VERSION_MAJOR != info->version[0]) ||
++ (DLM_PLOCK_VERSION_MINOR < info->version[1])) {
++ log_print("plock device version mismatch: "
++ "kernel (%u.%u.%u), user (%u.%u.%u)",
++ DLM_PLOCK_VERSION_MAJOR,
++ DLM_PLOCK_VERSION_MINOR,
++ DLM_PLOCK_VERSION_PATCH,
++ info->version[0],
++ info->version[1],
++ info->version[2]);
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static void send_op(struct plock_op *op)
++{
++ set_version(&op->info);
++ INIT_LIST_HEAD(&op->list);
++ spin_lock(&ops_lock);
++ list_add_tail(&op->list, &send_list);
++ spin_unlock(&ops_lock);
++ wake_up(&send_wq);
++}
++
++int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
++ int cmd, struct file_lock *fl)
++{
++ struct dlm_ls *ls;
++ struct plock_op *op;
++ struct plock_xop *xop;
++ int rv;
++
++ ls = dlm_find_lockspace_local(lockspace);
++ if (!ls)
++ return -EINVAL;
++
++ xop = kzalloc(sizeof(*xop), GFP_KERNEL);
++ if (!xop) {
++ rv = -ENOMEM;
++ goto out;
++ }
++
++ op = &xop->xop;
++ op->info.optype = DLM_PLOCK_OP_LOCK;
++ op->info.pid = fl->fl_pid;
++ op->info.ex = (fl->fl_type == F_WRLCK);
++ op->info.wait = IS_SETLKW(cmd);
++ op->info.fsid = ls->ls_global_id;
++ op->info.number = number;
++ op->info.start = fl->fl_start;
++ op->info.end = fl->fl_end;
++ if (fl->fl_lmops && fl->fl_lmops->fl_grant) {
++ /* fl_owner is lockd which doesn't distinguish
++ processes on the nfs client */
++ op->info.owner = (__u64) fl->fl_pid;
++ xop->callback = fl->fl_lmops->fl_grant;
++ locks_init_lock(&xop->flc);
++ locks_copy_lock(&xop->flc, fl);
++ xop->fl = fl;
++ xop->file = file;
++ } else {
++ op->info.owner = (__u64)(long) fl->fl_owner;
++ xop->callback = NULL;
++ }
++
++ send_op(op);
++
++ if (xop->callback == NULL)
++ wait_event(recv_wq, (op->done != 0));
++ else {
++ rv = -EINPROGRESS;
++ goto out;
++ }
++
++ spin_lock(&ops_lock);
++ if (!list_empty(&op->list)) {
++ log_error(ls, "dlm_posix_lock: op on list %llx",
++ (unsigned long long)number);
++ list_del(&op->list);
++ }
++ spin_unlock(&ops_lock);
++
++ rv = op->info.rv;
++
++ if (!rv) {
++ if (posix_lock_file_wait(file, fl) < 0)
++ log_error(ls, "dlm_posix_lock: vfs lock error %llx",
++ (unsigned long long)number);
++ }
++
++ kfree(xop);
++out:
++ dlm_put_lockspace(ls);
++ return rv;
++}
++EXPORT_SYMBOL_GPL(dlm_posix_lock);
++
++/* Returns failure iff a succesful lock operation should be canceled */
++static int dlm_plock_callback(struct plock_op *op)
++{
++ struct file *file;
++ struct file_lock *fl;
++ struct file_lock *flc;
++ int (*notify)(void *, void *, int) = NULL;
++ struct plock_xop *xop = (struct plock_xop *)op;
++ int rv = 0;
++
++ spin_lock(&ops_lock);
++ if (!list_empty(&op->list)) {
++ log_print("dlm_plock_callback: op on list %llx",
++ (unsigned long long)op->info.number);
++ list_del(&op->list);
++ }
++ spin_unlock(&ops_lock);
++
++ /* check if the following 2 are still valid or make a copy */
++ file = xop->file;
++ flc = &xop->flc;
++ fl = xop->fl;
++ notify = xop->callback;
++
++ if (op->info.rv) {
++ notify(flc, NULL, op->info.rv);
++ goto out;
++ }
++
++ /* got fs lock; bookkeep locally as well: */
++ flc->fl_flags &= ~FL_SLEEP;
++ if (posix_lock_file(file, flc, NULL)) {
++ /*
++ * This can only happen in the case of kmalloc() failure.
++ * The filesystem's own lock is the authoritative lock,
++ * so a failure to get the lock locally is not a disaster.
++ * As long as the fs cannot reliably cancel locks (especially
++ * in a low-memory situation), we're better off ignoring
++ * this failure than trying to recover.
++ */
++ log_print("dlm_plock_callback: vfs lock error %llx file %p fl %p",
++ (unsigned long long)op->info.number, file, fl);
++ }
++
++ rv = notify(flc, NULL, 0);
++ if (rv) {
++ /* XXX: We need to cancel the fs lock here: */
++ log_print("dlm_plock_callback: lock granted after lock request "
++ "failed; dangling lock!\n");
++ goto out;
++ }
++
++out:
++ kfree(xop);
++ return rv;
++}
++
++int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
++ struct file_lock *fl)
++{
++ struct dlm_ls *ls;
++ struct plock_op *op;
++ int rv;
++
++ ls = dlm_find_lockspace_local(lockspace);
++ if (!ls)
++ return -EINVAL;
++
++ op = kzalloc(sizeof(*op), GFP_KERNEL);
++ if (!op) {
++ rv = -ENOMEM;
++ goto out;
++ }
++
++ if (posix_lock_file_wait(file, fl) < 0)
++ log_error(ls, "dlm_posix_unlock: vfs unlock error %llx",
++ (unsigned long long)number);
++
++ op->info.optype = DLM_PLOCK_OP_UNLOCK;
++ op->info.pid = fl->fl_pid;
++ op->info.fsid = ls->ls_global_id;
++ op->info.number = number;
++ op->info.start = fl->fl_start;
++ op->info.end = fl->fl_end;
++ if (fl->fl_lmops && fl->fl_lmops->fl_grant)
++ op->info.owner = (__u64) fl->fl_pid;
++ else
++ op->info.owner = (__u64)(long) fl->fl_owner;
++
++ send_op(op);
++ wait_event(recv_wq, (op->done != 0));
++
++ spin_lock(&ops_lock);
++ if (!list_empty(&op->list)) {
++ log_error(ls, "dlm_posix_unlock: op on list %llx",
++ (unsigned long long)number);
++ list_del(&op->list);
++ }
++ spin_unlock(&ops_lock);
++
++ rv = op->info.rv;
++
++ if (rv == -ENOENT)
++ rv = 0;
++
++ kfree(op);
++out:
++ dlm_put_lockspace(ls);
++ return rv;
++}
++EXPORT_SYMBOL_GPL(dlm_posix_unlock);
++
++int dlm_posix_get(dlm_lockspace_t *lockspace, u64 number, struct file *file,
++ struct file_lock *fl)
++{
++ struct dlm_ls *ls;
++ struct plock_op *op;
++ int rv;
++
++ ls = dlm_find_lockspace_local(lockspace);
++ if (!ls)
++ return -EINVAL;
++
++ op = kzalloc(sizeof(*op), GFP_KERNEL);
++ if (!op) {
++ rv = -ENOMEM;
++ goto out;
++ }
++
++ op->info.optype = DLM_PLOCK_OP_GET;
++ op->info.pid = fl->fl_pid;
++ op->info.ex = (fl->fl_type == F_WRLCK);
++ op->info.fsid = ls->ls_global_id;
++ op->info.number = number;
++ op->info.start = fl->fl_start;
++ op->info.end = fl->fl_end;
++ if (fl->fl_lmops && fl->fl_lmops->fl_grant)
++ op->info.owner = (__u64) fl->fl_pid;
++ else
++ op->info.owner = (__u64)(long) fl->fl_owner;
++
++ send_op(op);
++ wait_event(recv_wq, (op->done != 0));
++
++ spin_lock(&ops_lock);
++ if (!list_empty(&op->list)) {
++ log_error(ls, "dlm_posix_get: op on list %llx",
++ (unsigned long long)number);
++ list_del(&op->list);
++ }
++ spin_unlock(&ops_lock);
++
++ /* info.rv from userspace is 1 for conflict, 0 for no-conflict,
++ -ENOENT if there are no locks on the file */
++
++ rv = op->info.rv;
++
++ fl->fl_type = F_UNLCK;
++ if (rv == -ENOENT)
++ rv = 0;
++ else if (rv > 0) {
++ fl->fl_type = (op->info.ex) ? F_WRLCK : F_RDLCK;
++ fl->fl_pid = op->info.pid;
++ fl->fl_start = op->info.start;
++ fl->fl_end = op->info.end;
++ rv = 0;
++ }
++
++ kfree(op);
++out:
++ dlm_put_lockspace(ls);
++ return rv;
++}
++EXPORT_SYMBOL_GPL(dlm_posix_get);
++
++/* a read copies out one plock request from the send list */
++static ssize_t dev_read(struct file *file, char __user *u, size_t count,
++ loff_t *ppos)
++{
++ struct dlm_plock_info info;
++ struct plock_op *op = NULL;
++
++ if (count < sizeof(info))
++ return -EINVAL;
++
++ spin_lock(&ops_lock);
++ if (!list_empty(&send_list)) {
++ op = list_entry(send_list.next, struct plock_op, list);
++ list_move(&op->list, &recv_list);
++ memcpy(&info, &op->info, sizeof(info));
++ }
++ spin_unlock(&ops_lock);
++
++ if (!op)
++ return -EAGAIN;
++
++ if (copy_to_user(u, &info, sizeof(info)))
++ return -EFAULT;
++ return sizeof(info);
++}
++
++/* a write copies in one plock result that should match a plock_op
++ on the recv list */
++static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
++ loff_t *ppos)
++{
++ struct dlm_plock_info info;
++ struct plock_op *op;
++ int found = 0;
++
++ if (count != sizeof(info))
++ return -EINVAL;
++
++ if (copy_from_user(&info, u, sizeof(info)))
++ return -EFAULT;
++
++ if (check_version(&info))
++ return -EINVAL;
++
++ spin_lock(&ops_lock);
++ list_for_each_entry(op, &recv_list, list) {
++ if (op->info.fsid == info.fsid && op->info.number == info.number &&
++ op->info.owner == info.owner) {
++ list_del_init(&op->list);
++ found = 1;
++ op->done = 1;
++ memcpy(&op->info, &info, sizeof(info));
++ break;
++ }
++ }
++ spin_unlock(&ops_lock);
++
++ if (found) {
++ struct plock_xop *xop;
++ xop = (struct plock_xop *)op;
++ if (xop->callback)
++ count = dlm_plock_callback(op);
++ else
++ wake_up(&recv_wq);
++ } else
++ log_print("dev_write no op %x %llx", info.fsid,
++ (unsigned long long)info.number);
++ return count;
++}
++
++static unsigned int dev_poll(struct file *file, poll_table *wait)
++{
++ unsigned int mask = 0;
++
++ poll_wait(file, &send_wq, wait);
++
++ spin_lock(&ops_lock);
++ if (!list_empty(&send_list))
++ mask = POLLIN | POLLRDNORM;
++ spin_unlock(&ops_lock);
++
++ return mask;
++}
++
++static const struct file_operations dev_fops = {
++ .read = dev_read,
++ .write = dev_write,
++ .poll = dev_poll,
++ .owner = THIS_MODULE
++};
++
++static struct miscdevice plock_dev_misc = {
++ .minor = MISC_DYNAMIC_MINOR,
++ .name = DLM_PLOCK_MISC_NAME,
++ .fops = &dev_fops
++};
++
++int dlm_plock_init(void)
++{
++ int rv;
++
++ spin_lock_init(&ops_lock);
++ INIT_LIST_HEAD(&send_list);
++ INIT_LIST_HEAD(&recv_list);
++ init_waitqueue_head(&send_wq);
++ init_waitqueue_head(&recv_wq);
++
++ rv = misc_register(&plock_dev_misc);
++ if (rv)
++ log_print("dlm_plock_init: misc_register failed %d", rv);
++ return rv;
++}
++
++void dlm_plock_exit(void)
++{
++ if (misc_deregister(&plock_dev_misc) < 0)
++ log_print("dlm_plock_exit: misc_deregister failed");
++}
++
+diff --git a/fs/dlm/recoverd.c b/fs/dlm/recoverd.c
+index 997f953..fd677c8 100644
+--- a/fs/dlm/recoverd.c
++++ b/fs/dlm/recoverd.c
+@@ -257,6 +257,7 @@ static void do_ls_recovery(struct dlm_ls *ls)
+ if (rv) {
+ ls_recover(ls, rv);
+ kfree(rv->nodeids);
++ kfree(rv->new);
+ kfree(rv);
+ }
+ }
+diff --git a/fs/exec.c b/fs/exec.c
+index 54a0a55..b152029 100644
+--- a/fs/exec.c
++++ b/fs/exec.c
+@@ -953,7 +953,6 @@ int flush_old_exec(struct linux_binprm * bprm)
+ {
+ char * name;
+ int i, ch, retval;
+- struct files_struct *files;
+ char tcomm[sizeof(current->comm)];
+
+ /*
+@@ -965,26 +964,15 @@ int flush_old_exec(struct linux_binprm * bprm)
+ goto out;
+
+ /*
+- * Make sure we have private file handles. Ask the
+- * fork helper to do the work for us and the exit
+- * helper to do the cleanup of the old one.
+- */
+- files = current->files; /* refcounted so safe to hold */
+- retval = unshare_files();
+- if (retval)
+- goto out;
+- /*
+ * Release all of the old mmap stuff
+ */
+ retval = exec_mmap(bprm->mm);
+ if (retval)
+- goto mmap_failed;
++ goto out;
+
+ bprm->mm = NULL; /* We're using it now */
+
+ /* This is the point of no return */
+- put_files_struct(files);
+-
+ current->sas_ss_sp = current->sas_ss_size = 0;
+
+ if (current->euid == current->uid && current->egid == current->gid)
+@@ -1034,8 +1022,6 @@ int flush_old_exec(struct linux_binprm * bprm)
+
+ return 0;
+
+-mmap_failed:
+- reset_files_struct(current, files);
+ out:
+ return retval;
+ }
+@@ -1283,12 +1269,17 @@ int do_execve(char * filename,
+ struct linux_binprm *bprm;
+ struct file *file;
+ unsigned long env_p;
++ struct files_struct *displaced;
+ int retval;
+
++ retval = unshare_files(&displaced);
++ if (retval)
++ goto out_ret;
++
+ retval = -ENOMEM;
+ bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
+ if (!bprm)
+- goto out_ret;
++ goto out_files;
+
+ file = open_exec(filename);
+ retval = PTR_ERR(file);
+@@ -1343,6 +1334,8 @@ int do_execve(char * filename,
+ security_bprm_free(bprm);
+ acct_update_integrals(current);
+ kfree(bprm);
++ if (displaced)
++ put_files_struct(displaced);
+ return retval;
+ }
+
+@@ -1363,6 +1356,9 @@ out_file:
+ out_kfree:
+ kfree(bprm);
+
++out_files:
++ if (displaced)
++ reset_files_struct(displaced);
+ out_ret:
+ return retval;
+ }
+diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
+index 5deb8b7..08f647d 100644
+--- a/fs/ext2/ialloc.c
++++ b/fs/ext2/ialloc.c
+@@ -253,7 +253,7 @@ static int find_group_dir(struct super_block *sb, struct inode *parent)
+ * it has too few free inodes left (min_inodes) or
+ * it has too few free blocks left (min_blocks) or
+ * it's already running too large debt (max_debt).
+- * Parent's group is prefered, if it doesn't satisfy these
++ * Parent's group is preferred, if it doesn't satisfy these
+ * conditions we search cyclically through the rest. If none
+ * of the groups look good we just look for a group with more
+ * free inodes than average (starting at parent's group).
+diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
+index c620068..b8a2990 100644
+--- a/fs/ext2/inode.c
++++ b/fs/ext2/inode.c
+@@ -239,7 +239,7 @@ no_block:
+ * @inode: owner
+ * @ind: descriptor of indirect block.
+ *
+- * This function returns the prefered place for block allocation.
++ * This function returns the preferred place for block allocation.
+ * It is used when heuristic for sequential allocation fails.
+ * Rules are:
+ * + if there is a block to the left of our position - allocate near it.
+@@ -283,7 +283,7 @@ static unsigned long ext2_find_near(struct inode *inode, Indirect *ind)
+ }
+
+ /**
+- * ext2_find_goal - find a prefered place for allocation.
++ * ext2_find_goal - find a preferred place for allocation.
+ * @inode: owner
+ * @block: block we want
+ * @partial: pointer to the last triple within a chain
+diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
+index b8ea11f..de876fa 100644
+--- a/fs/ext2/ioctl.c
++++ b/fs/ext2/ioctl.c
+@@ -12,6 +12,7 @@
+ #include <linux/time.h>
+ #include <linux/sched.h>
+ #include <linux/compat.h>
++#include <linux/mount.h>
+ #include <linux/smp_lock.h>
+ #include <asm/current.h>
+ #include <asm/uaccess.h>
+@@ -23,6 +24,7 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ struct ext2_inode_info *ei = EXT2_I(inode);
+ unsigned int flags;
+ unsigned short rsv_window_size;
++ int ret;
+
+ ext2_debug ("cmd = %u, arg = %lu\n", cmd, arg);
+
+@@ -34,14 +36,19 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ case EXT2_IOC_SETFLAGS: {
+ unsigned int oldflags;
+
+- if (IS_RDONLY(inode))
+- return -EROFS;
++ ret = mnt_want_write(filp->f_path.mnt);
++ if (ret)
++ return ret;
+
+- if (!is_owner_or_cap(inode))
+- return -EACCES;
++ if (!is_owner_or_cap(inode)) {
++ ret = -EACCES;
++ goto setflags_out;
++ }
+
+- if (get_user(flags, (int __user *) arg))
+- return -EFAULT;
++ if (get_user(flags, (int __user *) arg)) {
++ ret = -EFAULT;
++ goto setflags_out;
++ }
+
+ if (!S_ISDIR(inode->i_mode))
+ flags &= ~EXT2_DIRSYNC_FL;
+@@ -50,7 +57,8 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ /* Is it quota file? Do not allow user to mess with it */
+ if (IS_NOQUOTA(inode)) {
+ mutex_unlock(&inode->i_mutex);
+- return -EPERM;
++ ret = -EPERM;
++ goto setflags_out;
+ }
+ oldflags = ei->i_flags;
+
+@@ -63,7 +71,8 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) {
+ if (!capable(CAP_LINUX_IMMUTABLE)) {
+ mutex_unlock(&inode->i_mutex);
+- return -EPERM;
++ ret = -EPERM;
++ goto setflags_out;
+ }
+ }
+
+@@ -75,20 +84,26 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ ext2_set_inode_flags(inode);
+ inode->i_ctime = CURRENT_TIME_SEC;
+ mark_inode_dirty(inode);
+- return 0;
++setflags_out:
++ mnt_drop_write(filp->f_path.mnt);
++ return ret;
+ }
+ case EXT2_IOC_GETVERSION:
+ return put_user(inode->i_generation, (int __user *) arg);
+ case EXT2_IOC_SETVERSION:
+ if (!is_owner_or_cap(inode))
+ return -EPERM;
+- if (IS_RDONLY(inode))
+- return -EROFS;
+- if (get_user(inode->i_generation, (int __user *) arg))
+- return -EFAULT;
+- inode->i_ctime = CURRENT_TIME_SEC;
+- mark_inode_dirty(inode);
+- return 0;
++ ret = mnt_want_write(filp->f_path.mnt);
++ if (ret)
++ return ret;
++ if (get_user(inode->i_generation, (int __user *) arg)) {
++ ret = -EFAULT;
++ } else {
++ inode->i_ctime = CURRENT_TIME_SEC;
++ mark_inode_dirty(inode);
++ }
++ mnt_drop_write(filp->f_path.mnt);
++ return ret;
+ case EXT2_IOC_GETRSVSZ:
+ if (test_opt(inode->i_sb, RESERVATION)
+ && S_ISREG(inode->i_mode)
+@@ -102,15 +117,16 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode))
+ return -ENOTTY;
+
+- if (IS_RDONLY(inode))
+- return -EROFS;
+-
+- if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
++ if (!is_owner_or_cap(inode))
+ return -EACCES;
+
+ if (get_user(rsv_window_size, (int __user *)arg))
+ return -EFAULT;
+
++ ret = mnt_want_write(filp->f_path.mnt);
++ if (ret)
++ return ret;
++
+ if (rsv_window_size > EXT2_MAX_RESERVE_BLOCKS)
+ rsv_window_size = EXT2_MAX_RESERVE_BLOCKS;
+
+@@ -131,6 +147,7 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ rsv->rsv_goal_size = rsv_window_size;
+ }
+ mutex_unlock(&ei->truncate_mutex);
++ mnt_drop_write(filp->f_path.mnt);
+ return 0;
+ }
+ default:
+diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
+index 4f4020c..96dd557 100644
+--- a/fs/ext3/ialloc.c
++++ b/fs/ext3/ialloc.c
+@@ -239,7 +239,7 @@ static int find_group_dir(struct super_block *sb, struct inode *parent)
+ * it has too few free inodes left (min_inodes) or
+ * it has too few free blocks left (min_blocks) or
+ * it's already running too large debt (max_debt).
+- * Parent's group is prefered, if it doesn't satisfy these
++ * Parent's group is preferred, if it doesn't satisfy these
+ * conditions we search cyclically through the rest. If none
+ * of the groups look good we just look for a group with more
+ * free inodes than average (starting at parent's group).
+diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
+index eb95670..c683609 100644
+--- a/fs/ext3/inode.c
++++ b/fs/ext3/inode.c
+@@ -392,7 +392,7 @@ no_block:
+ * @inode: owner
+ * @ind: descriptor of indirect block.
+ *
+- * This function returns the prefered place for block allocation.
++ * This function returns the preferred place for block allocation.
+ * It is used when heuristic for sequential allocation fails.
+ * Rules are:
+ * + if there is a block to the left of our position - allocate near it.
+@@ -436,12 +436,12 @@ static ext3_fsblk_t ext3_find_near(struct inode *inode, Indirect *ind)
+ }
+
+ /**
+- * ext3_find_goal - find a prefered place for allocation.
++ * ext3_find_goal - find a preferred place for allocation.
+ * @inode: owner
+ * @block: block we want
+ * @partial: pointer to the last triple within a chain
+ *
+- * Normally this function find the prefered place for block allocation,
++ * Normally this function find the preferred place for block allocation,
+ * returns it.
+ */
+
+diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
+index 023a070..0d0c701 100644
+--- a/fs/ext3/ioctl.c
++++ b/fs/ext3/ioctl.c
+@@ -12,6 +12,7 @@
+ #include <linux/capability.h>
+ #include <linux/ext3_fs.h>
+ #include <linux/ext3_jbd.h>
++#include <linux/mount.h>
+ #include <linux/time.h>
+ #include <linux/compat.h>
+ #include <linux/smp_lock.h>
+@@ -38,14 +39,19 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+ unsigned int oldflags;
+ unsigned int jflag;
+
+- if (IS_RDONLY(inode))
+- return -EROFS;
++ err = mnt_want_write(filp->f_path.mnt);
++ if (err)
++ return err;
+
+- if (!is_owner_or_cap(inode))
+- return -EACCES;
++ if (!is_owner_or_cap(inode)) {
++ err = -EACCES;
++ goto flags_out;
++ }
+
+- if (get_user(flags, (int __user *) arg))
+- return -EFAULT;
++ if (get_user(flags, (int __user *) arg)) {
++ err = -EFAULT;
++ goto flags_out;
++ }
+
+ if (!S_ISDIR(inode->i_mode))
+ flags &= ~EXT3_DIRSYNC_FL;
+@@ -54,7 +60,8 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+ /* Is it quota file? Do not allow user to mess with it */
+ if (IS_NOQUOTA(inode)) {
+ mutex_unlock(&inode->i_mutex);
+- return -EPERM;
++ err = -EPERM;
++ goto flags_out;
+ }
+ oldflags = ei->i_flags;
+
+@@ -70,7 +77,8 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+ if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) {
+ if (!capable(CAP_LINUX_IMMUTABLE)) {
+ mutex_unlock(&inode->i_mutex);
+- return -EPERM;
++ err = -EPERM;
++ goto flags_out;
+ }
+ }
+
+@@ -81,7 +89,8 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+ if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) {
+ if (!capable(CAP_SYS_RESOURCE)) {
+ mutex_unlock(&inode->i_mutex);
+- return -EPERM;
++ err = -EPERM;
++ goto flags_out;
+ }
+ }
+
+@@ -89,7 +98,8 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+ handle = ext3_journal_start(inode, 1);
+ if (IS_ERR(handle)) {
+ mutex_unlock(&inode->i_mutex);
+- return PTR_ERR(handle);
++ err = PTR_ERR(handle);
++ goto flags_out;
+ }
+ if (IS_SYNC(inode))
+ handle->h_sync = 1;
+@@ -115,6 +125,8 @@ flags_err:
+ if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL))
+ err = ext3_change_inode_journal_flag(inode, jflag);
+ mutex_unlock(&inode->i_mutex);
++flags_out:
++ mnt_drop_write(filp->f_path.mnt);
+ return err;
+ }
+ case EXT3_IOC_GETVERSION:
+@@ -129,14 +141,18 @@ flags_err:
+
+ if (!is_owner_or_cap(inode))
+ return -EPERM;
+- if (IS_RDONLY(inode))
+- return -EROFS;
+- if (get_user(generation, (int __user *) arg))
+- return -EFAULT;
+-
++ err = mnt_want_write(filp->f_path.mnt);
++ if (err)
++ return err;
++ if (get_user(generation, (int __user *) arg)) {
++ err = -EFAULT;
++ goto setversion_out;
++ }
+ handle = ext3_journal_start(inode, 1);
+- if (IS_ERR(handle))
+- return PTR_ERR(handle);
++ if (IS_ERR(handle)) {
++ err = PTR_ERR(handle);
++ goto setversion_out;
++ }
+ err = ext3_reserve_inode_write(handle, inode, &iloc);
+ if (err == 0) {
+ inode->i_ctime = CURRENT_TIME_SEC;
+@@ -144,6 +160,8 @@ flags_err:
+ err = ext3_mark_iloc_dirty(handle, inode, &iloc);
+ }
+ ext3_journal_stop(handle);
++setversion_out:
++ mnt_drop_write(filp->f_path.mnt);
+ return err;
+ }
+ #ifdef CONFIG_JBD_DEBUG
+@@ -179,18 +197,24 @@ flags_err:
+ }
+ return -ENOTTY;
+ case EXT3_IOC_SETRSVSZ: {
++ int err;
+
+ if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode))
+ return -ENOTTY;
+
+- if (IS_RDONLY(inode))
+- return -EROFS;
++ err = mnt_want_write(filp->f_path.mnt);
++ if (err)
++ return err;
+
+- if (!is_owner_or_cap(inode))
+- return -EACCES;
++ if (!is_owner_or_cap(inode)) {
++ err = -EACCES;
++ goto setrsvsz_out;
++ }
+
+- if (get_user(rsv_window_size, (int __user *)arg))
+- return -EFAULT;
++ if (get_user(rsv_window_size, (int __user *)arg)) {
++ err = -EFAULT;
++ goto setrsvsz_out;
++ }
+
+ if (rsv_window_size > EXT3_MAX_RESERVE_BLOCKS)
+ rsv_window_size = EXT3_MAX_RESERVE_BLOCKS;
+@@ -208,7 +232,9 @@ flags_err:
+ rsv->rsv_goal_size = rsv_window_size;
+ }
+ mutex_unlock(&ei->truncate_mutex);
+- return 0;
++setrsvsz_out:
++ mnt_drop_write(filp->f_path.mnt);
++ return err;
+ }
+ case EXT3_IOC_GROUP_EXTEND: {
+ ext3_fsblk_t n_blocks_count;
+@@ -218,17 +244,20 @@ flags_err:
+ if (!capable(CAP_SYS_RESOURCE))
+ return -EPERM;
+
+- if (IS_RDONLY(inode))
+- return -EROFS;
+-
+- if (get_user(n_blocks_count, (__u32 __user *)arg))
+- return -EFAULT;
++ err = mnt_want_write(filp->f_path.mnt);
++ if (err)
++ return err;
+
++ if (get_user(n_blocks_count, (__u32 __user *)arg)) {
++ err = -EFAULT;
++ goto group_extend_out;
++ }
+ err = ext3_group_extend(sb, EXT3_SB(sb)->s_es, n_blocks_count);
+ journal_lock_updates(EXT3_SB(sb)->s_journal);
+ journal_flush(EXT3_SB(sb)->s_journal);
+ journal_unlock_updates(EXT3_SB(sb)->s_journal);
+-
++group_extend_out:
++ mnt_drop_write(filp->f_path.mnt);
+ return err;
+ }
+ case EXT3_IOC_GROUP_ADD: {
+@@ -239,18 +268,22 @@ flags_err:
+ if (!capable(CAP_SYS_RESOURCE))
+ return -EPERM;
+
+- if (IS_RDONLY(inode))
+- return -EROFS;
++ err = mnt_want_write(filp->f_path.mnt);
++ if (err)
++ return err;
+
+ if (copy_from_user(&input, (struct ext3_new_group_input __user *)arg,
+- sizeof(input)))
+- return -EFAULT;
++ sizeof(input))) {
++ err = -EFAULT;
++ goto group_add_out;
++ }
+
+ err = ext3_group_add(sb, &input);
+ journal_lock_updates(EXT3_SB(sb)->s_journal);
+ journal_flush(EXT3_SB(sb)->s_journal);
+ journal_unlock_updates(EXT3_SB(sb)->s_journal);
+-
++group_add_out:
++ mnt_drop_write(filp->f_path.mnt);
+ return err;
+ }
+
+diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
+index 8036b9b..486e46a 100644
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -305,7 +305,7 @@ static int find_group_dir(struct super_block *sb, struct inode *parent,
+ * it has too few free inodes left (min_inodes) or
+ * it has too few free blocks left (min_blocks) or
+ * it's already running too large debt (max_debt).
+- * Parent's group is prefered, if it doesn't satisfy these
++ * Parent's group is preferred, if it doesn't satisfy these
+ * conditions we search cyclically through the rest. If none
+ * of the groups look good we just look for a group with more
+ * free inodes than average (starting at parent's group).
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 945cbf6..8fab233 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -382,7 +382,7 @@ no_block:
+ * @inode: owner
+ * @ind: descriptor of indirect block.
+ *
+- * This function returns the prefered place for block allocation.
++ * This function returns the preferred place for block allocation.
+ * It is used when heuristic for sequential allocation fails.
+ * Rules are:
+ * + if there is a block to the left of our position - allocate near it.
+@@ -432,12 +432,12 @@ static ext4_fsblk_t ext4_find_near(struct inode *inode, Indirect *ind)
+ }
+
+ /**
+- * ext4_find_goal - find a prefered place for allocation.
++ * ext4_find_goal - find a preferred place for allocation.
+ * @inode: owner
+ * @block: block we want
+ * @partial: pointer to the last triple within a chain
+ *
+- * Normally this function find the prefered place for block allocation,
++ * Normally this function find the preferred place for block allocation,
+ * returns it.
+ */
+ static ext4_fsblk_t ext4_find_goal(struct inode *inode, ext4_lblk_t block,
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index 2ed7c37..25b13ed 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -15,6 +15,7 @@
+ #include <linux/time.h>
+ #include <linux/compat.h>
+ #include <linux/smp_lock.h>
++#include <linux/mount.h>
+ #include <asm/uaccess.h>
+
+ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+@@ -38,24 +39,25 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+ unsigned int oldflags;
+ unsigned int jflag;
+
+- if (IS_RDONLY(inode))
+- return -EROFS;
+-
+ if (!is_owner_or_cap(inode))
+ return -EACCES;
+
+ if (get_user(flags, (int __user *) arg))
+ return -EFAULT;
+
++ err = mnt_want_write(filp->f_path.mnt);
++ if (err)
++ return err;
++
+ if (!S_ISDIR(inode->i_mode))
+ flags &= ~EXT4_DIRSYNC_FL;
+
++ err = -EPERM;
+ mutex_lock(&inode->i_mutex);
+ /* Is it quota file? Do not allow user to mess with it */
+- if (IS_NOQUOTA(inode)) {
+- mutex_unlock(&inode->i_mutex);
+- return -EPERM;
+- }
++ if (IS_NOQUOTA(inode))
++ goto flags_out;
++
+ oldflags = ei->i_flags;
+
+ /* The JOURNAL_DATA flag is modifiable only by root */
+@@ -68,10 +70,8 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+ * This test looks nicer. Thanks to Pauline Middelink
+ */
+ if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) {
+- if (!capable(CAP_LINUX_IMMUTABLE)) {
+- mutex_unlock(&inode->i_mutex);
+- return -EPERM;
+- }
++ if (!capable(CAP_LINUX_IMMUTABLE))
++ goto flags_out;
+ }
+
+ /*
+@@ -79,17 +79,14 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+ * the relevant capability.
+ */
+ if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) {
+- if (!capable(CAP_SYS_RESOURCE)) {
+- mutex_unlock(&inode->i_mutex);
+- return -EPERM;
+- }
++ if (!capable(CAP_SYS_RESOURCE))
++ goto flags_out;
+ }
+
+-
+ handle = ext4_journal_start(inode, 1);
+ if (IS_ERR(handle)) {
+- mutex_unlock(&inode->i_mutex);
+- return PTR_ERR(handle);
++ err = PTR_ERR(handle);
++ goto flags_out;
+ }
+ if (IS_SYNC(inode))
+ handle->h_sync = 1;
+@@ -107,14 +104,14 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
+ err = ext4_mark_iloc_dirty(handle, inode, &iloc);
+ flags_err:
+ ext4_journal_stop(handle);
+- if (err) {
+- mutex_unlock(&inode->i_mutex);
+- return err;
+- }
++ if (err)
++ goto flags_out;
+
+ if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL))
+ err = ext4_change_inode_journal_flag(inode, jflag);
++flags_out:
+ mutex_unlock(&inode->i_mutex);
++ mnt_drop_write(filp->f_path.mnt);
+ return err;
+ }
+ case EXT4_IOC_GETVERSION:
+@@ -129,14 +126,20 @@ flags_err:
+
+ if (!is_owner_or_cap(inode))
+ return -EPERM;
+- if (IS_RDONLY(inode))
+- return -EROFS;
+- if (get_user(generation, (int __user *) arg))
+- return -EFAULT;
++
++ err = mnt_want_write(filp->f_path.mnt);
++ if (err)
++ return err;
++ if (get_user(generation, (int __user *) arg)) {
++ err = -EFAULT;
++ goto setversion_out;
++ }
+
+ handle = ext4_journal_start(inode, 1);
+- if (IS_ERR(handle))
+- return PTR_ERR(handle);
++ if (IS_ERR(handle)) {
++ err = PTR_ERR(handle);
++ goto setversion_out;
++ }
+ err = ext4_reserve_inode_write(handle, inode, &iloc);
+ if (err == 0) {
+ inode->i_ctime = ext4_current_time(inode);
+@@ -144,6 +147,8 @@ flags_err:
+ err = ext4_mark_iloc_dirty(handle, inode, &iloc);
+ }
+ ext4_journal_stop(handle);
++setversion_out:
++ mnt_drop_write(filp->f_path.mnt);
+ return err;
+ }
+ #ifdef CONFIG_JBD2_DEBUG
+@@ -179,19 +184,21 @@ flags_err:
+ }
+ return -ENOTTY;
+ case EXT4_IOC_SETRSVSZ: {
++ int err;
+
+ if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode))
+ return -ENOTTY;
+
+- if (IS_RDONLY(inode))
+- return -EROFS;
+-
+ if (!is_owner_or_cap(inode))
+ return -EACCES;
+
+ if (get_user(rsv_window_size, (int __user *)arg))
+ return -EFAULT;
+
++ err = mnt_want_write(filp->f_path.mnt);
++ if (err)
++ return err;
++
+ if (rsv_window_size > EXT4_MAX_RESERVE_BLOCKS)
+ rsv_window_size = EXT4_MAX_RESERVE_BLOCKS;
+
+@@ -208,6 +215,7 @@ flags_err:
+ rsv->rsv_goal_size = rsv_window_size;
+ }
+ up_write(&ei->i_data_sem);
++ mnt_drop_write(filp->f_path.mnt);
+ return 0;
+ }
+ case EXT4_IOC_GROUP_EXTEND: {
+@@ -218,16 +226,18 @@ flags_err:
+ if (!capable(CAP_SYS_RESOURCE))
+ return -EPERM;
+
+- if (IS_RDONLY(inode))
+- return -EROFS;
+-
+ if (get_user(n_blocks_count, (__u32 __user *)arg))
+ return -EFAULT;
+
++ err = mnt_want_write(filp->f_path.mnt);
++ if (err)
++ return err;
++
+ err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count);
+ jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
+ jbd2_journal_flush(EXT4_SB(sb)->s_journal);
+ jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
++ mnt_drop_write(filp->f_path.mnt);
+
+ return err;
+ }
+@@ -239,17 +249,19 @@ flags_err:
+ if (!capable(CAP_SYS_RESOURCE))
+ return -EPERM;
+
+- if (IS_RDONLY(inode))
+- return -EROFS;
+-
+ if (copy_from_user(&input, (struct ext4_new_group_input __user *)arg,
+ sizeof(input)))
+ return -EFAULT;
+
++ err = mnt_want_write(filp->f_path.mnt);
++ if (err)
++ return err;
++
+ err = ext4_group_add(sb, &input);
+ jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
+ jbd2_journal_flush(EXT4_SB(sb)->s_journal);
+ jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
++ mnt_drop_write(filp->f_path.mnt);
+
+ return err;
+ }
+diff --git a/fs/fat/file.c b/fs/fat/file.c
+index c614175..2a3bed9 100644
+--- a/fs/fat/file.c
++++ b/fs/fat/file.c
+@@ -8,6 +8,7 @@
+
+ #include <linux/capability.h>
+ #include <linux/module.h>
++#include <linux/mount.h>
+ #include <linux/time.h>
+ #include <linux/msdos_fs.h>
+ #include <linux/smp_lock.h>
+@@ -46,10 +47,9 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp,
+
+ mutex_lock(&inode->i_mutex);
+
+- if (IS_RDONLY(inode)) {
+- err = -EROFS;
+- goto up;
+- }
++ err = mnt_want_write(filp->f_path.mnt);
++ if (err)
++ goto up_no_drop_write;
+
+ /*
+ * ATTR_VOLUME and ATTR_DIR cannot be changed; this also
+@@ -105,7 +105,9 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp,
+
+ MSDOS_I(inode)->i_attrs = attr & ATTR_UNUSED;
+ mark_inode_dirty(inode);
+- up:
++up:
++ mnt_drop_write(filp->f_path.mnt);
++up_no_drop_write:
+ mutex_unlock(&inode->i_mutex);
+ return err;
+ }
+diff --git a/fs/fcntl.c b/fs/fcntl.c
+index e632da7..3f3ac63 100644
+--- a/fs/fcntl.c
++++ b/fs/fcntl.c
+@@ -55,14 +55,16 @@ static int get_close_on_exec(unsigned int fd)
+ * file_lock held for write.
+ */
+
+-static int locate_fd(struct files_struct *files,
+- struct file *file, unsigned int orig_start)
++static int locate_fd(unsigned int orig_start, int cloexec)
+ {
++ struct files_struct *files = current->files;
+ unsigned int newfd;
+ unsigned int start;
+ int error;
+ struct fdtable *fdt;
+
++ spin_lock(&files->file_lock);
++
+ error = -EINVAL;
+ if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
+ goto out;
+@@ -97,42 +99,28 @@ repeat:
+ if (error)
+ goto repeat;
+
+- /*
+- * We reacquired files_lock, so we are safe as long as
+- * we reacquire the fdtable pointer and use it while holding
+- * the lock, no one can free it during that time.
+- */
+ if (start <= files->next_fd)
+ files->next_fd = newfd + 1;
+
++ FD_SET(newfd, fdt->open_fds);
++ if (cloexec)
++ FD_SET(newfd, fdt->close_on_exec);
++ else
++ FD_CLR(newfd, fdt->close_on_exec);
+ error = newfd;
+-
++
+ out:
++ spin_unlock(&files->file_lock);
+ return error;
+ }
+
+ static int dupfd(struct file *file, unsigned int start, int cloexec)
+ {
+- struct files_struct * files = current->files;
+- struct fdtable *fdt;
+- int fd;
+-
+- spin_lock(&files->file_lock);
+- fd = locate_fd(files, file, start);
+- if (fd >= 0) {
+- /* locate_fd() may have expanded fdtable, load the ptr */
+- fdt = files_fdtable(files);
+- FD_SET(fd, fdt->open_fds);
+- if (cloexec)
+- FD_SET(fd, fdt->close_on_exec);
+- else
+- FD_CLR(fd, fdt->close_on_exec);
+- spin_unlock(&files->file_lock);
++ int fd = locate_fd(start, cloexec);
++ if (fd >= 0)
+ fd_install(fd, file);
+- } else {
+- spin_unlock(&files->file_lock);
++ else
+ fput(file);
+- }
+
+ return fd;
+ }
+diff --git a/fs/file_table.c b/fs/file_table.c
+index 986ff4e..7a0a9b8 100644
+--- a/fs/file_table.c
++++ b/fs/file_table.c
+@@ -42,6 +42,7 @@ static inline void file_free_rcu(struct rcu_head *head)
+ static inline void file_free(struct file *f)
+ {
+ percpu_counter_dec(&nr_files);
++ file_check_state(f);
+ call_rcu(&f->f_u.fu_rcuhead, file_free_rcu);
+ }
+
+@@ -199,6 +200,18 @@ int init_file(struct file *file, struct vfsmount *mnt, struct dentry *dentry,
+ file->f_mapping = dentry->d_inode->i_mapping;
+ file->f_mode = mode;
+ file->f_op = fop;
++
++ /*
++ * These mounts don't really matter in practice
++ * for r/o bind mounts. They aren't userspace-
++ * visible. We do this for consistency, and so
++ * that we can do debugging checks at __fput()
++ */
++ if ((mode & FMODE_WRITE) && !special_file(dentry->d_inode->i_mode)) {
++ file_take_write(file);
++ error = mnt_want_write(mnt);
++ WARN_ON(error);
++ }
+ return error;
+ }
+ EXPORT_SYMBOL(init_file);
+@@ -211,6 +224,31 @@ void fput(struct file *file)
+
+ EXPORT_SYMBOL(fput);
+
++/**
++ * drop_file_write_access - give up ability to write to a file
++ * @file: the file to which we will stop writing
++ *
++ * This is a central place which will give up the ability
++ * to write to @file, along with access to write through
++ * its vfsmount.
++ */
++void drop_file_write_access(struct file *file)
++{
++ struct vfsmount *mnt = file->f_path.mnt;
++ struct dentry *dentry = file->f_path.dentry;
++ struct inode *inode = dentry->d_inode;
++
++ put_write_access(inode);
++
++ if (special_file(inode->i_mode))
++ return;
++ if (file_check_writeable(file) != 0)
++ return;
++ mnt_drop_write(mnt);
++ file_release_write(file);
++}
++EXPORT_SYMBOL_GPL(drop_file_write_access);
++
+ /* __fput is called from task context when aio completion releases the last
+ * last use of a struct file *. Do not use otherwise.
+ */
+@@ -236,10 +274,10 @@ void __fput(struct file *file)
+ if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL))
+ cdev_put(inode->i_cdev);
+ fops_put(file->f_op);
+- if (file->f_mode & FMODE_WRITE)
+- put_write_access(inode);
+ put_pid(file->f_owner.pid);
+ file_kill(file);
++ if (file->f_mode & FMODE_WRITE)
++ drop_file_write_access(file);
+ file->f_path.dentry = NULL;
+ file->f_path.mnt = NULL;
+ file_free(file);
+diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
+index 033f7bd..4df34da 100644
+--- a/fs/fuse/inode.c
++++ b/fs/fuse/inode.c
+@@ -242,10 +242,9 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
+ return inode;
+ }
+
+-static void fuse_umount_begin(struct vfsmount *vfsmnt, int flags)
++static void fuse_umount_begin(struct super_block *sb)
+ {
+- if (flags & MNT_FORCE)
+- fuse_abort_conn(get_fuse_conn_super(vfsmnt->mnt_sb));
++ fuse_abort_conn(get_fuse_conn_super(sb));
+ }
+
+ static void fuse_send_destroy(struct fuse_conn *fc)
+diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig
+index de8e64c..7f7947e 100644
+--- a/fs/gfs2/Kconfig
++++ b/fs/gfs2/Kconfig
+@@ -1,6 +1,6 @@
+ config GFS2_FS
+ tristate "GFS2 file system support"
+- depends on EXPERIMENTAL
++ depends on EXPERIMENTAL && (64BIT || (LSF && LBD))
+ select FS_POSIX_ACL
+ select CRC32
+ help
+diff --git a/fs/gfs2/Makefile b/fs/gfs2/Makefile
+index 8fff110..e2350df 100644
+--- a/fs/gfs2/Makefile
++++ b/fs/gfs2/Makefile
+@@ -1,6 +1,6 @@
+ obj-$(CONFIG_GFS2_FS) += gfs2.o
+ gfs2-y := acl.o bmap.o daemon.o dir.o eaops.o eattr.o glock.o \
+- glops.o inode.o lm.o log.o lops.o locking.o main.o meta_io.o \
++ glops.o inode.o log.o lops.o locking.o main.o meta_io.o \
+ mount.o ops_address.o ops_dentry.o ops_export.o ops_file.o \
+ ops_fstype.o ops_inode.o ops_super.o quota.o \
+ recovery.o rgrp.o super.o sys.o trans.o util.o
+diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
+index 1047a8c..3e9bd46 100644
+--- a/fs/gfs2/acl.c
++++ b/fs/gfs2/acl.c
+@@ -116,7 +116,7 @@ static int acl_get(struct gfs2_inode *ip, int access, struct posix_acl **acl,
+ goto out;
+
+ er.er_data_len = GFS2_EA_DATA_LEN(el->el_ea);
+- er.er_data = kmalloc(er.er_data_len, GFP_KERNEL);
++ er.er_data = kmalloc(er.er_data_len, GFP_NOFS);
+ error = -ENOMEM;
+ if (!er.er_data)
+ goto out;
+@@ -222,7 +222,7 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip)
+ return error;
+ }
+
+- clone = posix_acl_clone(acl, GFP_KERNEL);
++ clone = posix_acl_clone(acl, GFP_NOFS);
+ error = -ENOMEM;
+ if (!clone)
+ goto out;
+@@ -272,7 +272,7 @@ int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr)
+ if (!acl)
+ return gfs2_setattr_simple(ip, attr);
+
+- clone = posix_acl_clone(acl, GFP_KERNEL);
++ clone = posix_acl_clone(acl, GFP_NOFS);
+ error = -ENOMEM;
+ if (!clone)
+ goto out;
+diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
+index e9456eb..c19184f 100644
+--- a/fs/gfs2/bmap.c
++++ b/fs/gfs2/bmap.c
+@@ -33,6 +33,7 @@
+ * keep it small.
+ */
+ struct metapath {
++ struct buffer_head *mp_bh[GFS2_MAX_META_HEIGHT];
+ __u16 mp_list[GFS2_MAX_META_HEIGHT];
+ };
+
+@@ -135,9 +136,10 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
+ /* Get a free block, fill it with the stuffed data,
+ and write it out to disk */
+
++ unsigned int n = 1;
++ block = gfs2_alloc_block(ip, &n);
+ if (isdir) {
+- block = gfs2_alloc_meta(ip);
+-
++ gfs2_trans_add_unrevoke(GFS2_SB(&ip->i_inode), block, 1);
+ error = gfs2_dir_get_new_buffer(ip, block, &bh);
+ if (error)
+ goto out_brelse;
+@@ -145,8 +147,6 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
+ dibh, sizeof(struct gfs2_dinode));
+ brelse(bh);
+ } else {
+- block = gfs2_alloc_data(ip);
+-
+ error = gfs2_unstuffer_page(ip, dibh, block, page);
+ if (error)
+ goto out_brelse;
+@@ -161,12 +161,11 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
+
+ if (ip->i_di.di_size) {
+ *(__be64 *)(di + 1) = cpu_to_be64(block);
+- ip->i_di.di_blocks++;
+- gfs2_set_inode_blocks(&ip->i_inode);
+- di->di_blocks = cpu_to_be64(ip->i_di.di_blocks);
++ gfs2_add_inode_blocks(&ip->i_inode, 1);
++ di->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode));
+ }
+
+- ip->i_di.di_height = 1;
++ ip->i_height = 1;
+ di->di_height = cpu_to_be16(1);
+
+ out_brelse:
+@@ -176,114 +175,13 @@ out:
+ return error;
+ }
+
+-/**
+- * calc_tree_height - Calculate the height of a metadata tree
+- * @ip: The GFS2 inode
+- * @size: The proposed size of the file
+- *
+- * Work out how tall a metadata tree needs to be in order to accommodate a
+- * file of a particular size. If size is less than the current size of
+- * the inode, then the current size of the inode is used instead of the
+- * supplied one.
+- *
+- * Returns: the height the tree should be
+- */
+-
+-static unsigned int calc_tree_height(struct gfs2_inode *ip, u64 size)
+-{
+- struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+- u64 *arr;
+- unsigned int max, height;
+-
+- if (ip->i_di.di_size > size)
+- size = ip->i_di.di_size;
+-
+- if (gfs2_is_dir(ip)) {
+- arr = sdp->sd_jheightsize;
+- max = sdp->sd_max_jheight;
+- } else {
+- arr = sdp->sd_heightsize;
+- max = sdp->sd_max_height;
+- }
+-
+- for (height = 0; height < max; height++)
+- if (arr[height] >= size)
+- break;
+-
+- return height;
+-}
+-
+-/**
+- * build_height - Build a metadata tree of the requested height
+- * @ip: The GFS2 inode
+- * @height: The height to build to
+- *
+- *
+- * Returns: errno
+- */
+-
+-static int build_height(struct inode *inode, unsigned height)
+-{
+- struct gfs2_inode *ip = GFS2_I(inode);
+- unsigned new_height = height - ip->i_di.di_height;
+- struct buffer_head *dibh;
+- struct buffer_head *blocks[GFS2_MAX_META_HEIGHT];
+- struct gfs2_dinode *di;
+- int error;
+- __be64 *bp;
+- u64 bn;
+- unsigned n;
+-
+- if (height <= ip->i_di.di_height)
+- return 0;
+-
+- error = gfs2_meta_inode_buffer(ip, &dibh);
+- if (error)
+- return error;
+-
+- for(n = 0; n < new_height; n++) {
+- bn = gfs2_alloc_meta(ip);
+- blocks[n] = gfs2_meta_new(ip->i_gl, bn);
+- gfs2_trans_add_bh(ip->i_gl, blocks[n], 1);
+- }
+-
+- n = 0;
+- bn = blocks[0]->b_blocknr;
+- if (new_height > 1) {
+- for(; n < new_height-1; n++) {
+- gfs2_metatype_set(blocks[n], GFS2_METATYPE_IN,
+- GFS2_FORMAT_IN);
+- gfs2_buffer_clear_tail(blocks[n],
+- sizeof(struct gfs2_meta_header));
+- bp = (__be64 *)(blocks[n]->b_data +
+- sizeof(struct gfs2_meta_header));
+- *bp = cpu_to_be64(blocks[n+1]->b_blocknr);
+- brelse(blocks[n]);
+- blocks[n] = NULL;
+- }
+- }
+- gfs2_metatype_set(blocks[n], GFS2_METATYPE_IN, GFS2_FORMAT_IN);
+- gfs2_buffer_copy_tail(blocks[n], sizeof(struct gfs2_meta_header),
+- dibh, sizeof(struct gfs2_dinode));
+- brelse(blocks[n]);
+- gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+- di = (struct gfs2_dinode *)dibh->b_data;
+- gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
+- *(__be64 *)(di + 1) = cpu_to_be64(bn);
+- ip->i_di.di_height += new_height;
+- ip->i_di.di_blocks += new_height;
+- gfs2_set_inode_blocks(&ip->i_inode);
+- di->di_height = cpu_to_be16(ip->i_di.di_height);
+- di->di_blocks = cpu_to_be64(ip->i_di.di_blocks);
+- brelse(dibh);
+- return error;
+-}
+
+ /**
+ * find_metapath - Find path through the metadata tree
+- * @ip: The inode pointer
++ * @sdp: The superblock
+ * @mp: The metapath to return the result in
+ * @block: The disk block to look up
++ * @height: The pre-calculated height of the metadata tree
+ *
+ * This routine returns a struct metapath structure that defines a path
+ * through the metadata of inode "ip" to get to block "block".
+@@ -338,21 +236,29 @@ static int build_height(struct inode *inode, unsigned height)
+ *
+ */
+
+-static void find_metapath(struct gfs2_inode *ip, u64 block,
+- struct metapath *mp)
++static void find_metapath(const struct gfs2_sbd *sdp, u64 block,
++ struct metapath *mp, unsigned int height)
+ {
+- struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+- u64 b = block;
+ unsigned int i;
+
+- for (i = ip->i_di.di_height; i--;)
+- mp->mp_list[i] = do_div(b, sdp->sd_inptrs);
++ for (i = height; i--;)
++ mp->mp_list[i] = do_div(block, sdp->sd_inptrs);
++
++}
+
++static inline unsigned int zero_metapath_length(const struct metapath *mp,
++ unsigned height)
++{
++ unsigned int i;
++ for (i = 0; i < height - 1; i++) {
++ if (mp->mp_list[i] != 0)
++ return i;
++ }
++ return height;
+ }
+
+ /**
+ * metapointer - Return pointer to start of metadata in a buffer
+- * @bh: The buffer
+ * @height: The metadata height (0 = dinode)
+ * @mp: The metapath
+ *
+@@ -361,93 +267,302 @@ static void find_metapath(struct gfs2_inode *ip, u64 block,
+ * metadata tree.
+ */
+
+-static inline __be64 *metapointer(struct buffer_head *bh, int *boundary,
+- unsigned int height, const struct metapath *mp)
++static inline __be64 *metapointer(unsigned int height, const struct metapath *mp)
+ {
++ struct buffer_head *bh = mp->mp_bh[height];
+ unsigned int head_size = (height > 0) ?
+ sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_dinode);
+- __be64 *ptr;
+- *boundary = 0;
+- ptr = ((__be64 *)(bh->b_data + head_size)) + mp->mp_list[height];
+- if (ptr + 1 == (__be64 *)(bh->b_data + bh->b_size))
+- *boundary = 1;
+- return ptr;
++ return ((__be64 *)(bh->b_data + head_size)) + mp->mp_list[height];
+ }
+
+ /**
+- * lookup_block - Get the next metadata block in metadata tree
+- * @ip: The GFS2 inode
+- * @bh: Buffer containing the pointers to metadata blocks
+- * @height: The height of the tree (0 = dinode)
++ * lookup_metapath - Walk the metadata tree to a specific point
++ * @ip: The inode
+ * @mp: The metapath
+- * @create: Non-zero if we may create a new meatdata block
+- * @new: Used to indicate if we did create a new metadata block
+- * @block: the returned disk block number
+ *
+- * Given a metatree, complete to a particular height, checks to see if the next
+- * height of the tree exists. If not the next height of the tree is created.
+- * The block number of the next height of the metadata tree is returned.
++ * Assumes that the inode's buffer has already been looked up and
++ * hooked onto mp->mp_bh[0] and that the metapath has been initialised
++ * by find_metapath().
++ *
++ * If this function encounters part of the tree which has not been
++ * allocated, it returns the current height of the tree at the point
++ * at which it found the unallocated block. Blocks which are found are
++ * added to the mp->mp_bh[] list.
+ *
++ * Returns: error or height of metadata tree
+ */
+
+-static int lookup_block(struct gfs2_inode *ip, struct buffer_head *bh,
+- unsigned int height, struct metapath *mp, int create,
+- int *new, u64 *block)
++static int lookup_metapath(struct gfs2_inode *ip, struct metapath *mp)
+ {
+- int boundary;
+- __be64 *ptr = metapointer(bh, &boundary, height, mp);
++ unsigned int end_of_metadata = ip->i_height - 1;
++ unsigned int x;
++ __be64 *ptr;
++ u64 dblock;
++ int ret;
+
+- if (*ptr) {
+- *block = be64_to_cpu(*ptr);
+- return boundary;
+- }
++ for (x = 0; x < end_of_metadata; x++) {
++ ptr = metapointer(x, mp);
++ dblock = be64_to_cpu(*ptr);
++ if (!dblock)
++ return x + 1;
+
+- *block = 0;
++ ret = gfs2_meta_indirect_buffer(ip, x+1, dblock, 0, &mp->mp_bh[x+1]);
++ if (ret)
++ return ret;
++ }
+
+- if (!create)
+- return 0;
++ return ip->i_height;
++}
+
+- if (height == ip->i_di.di_height - 1 && !gfs2_is_dir(ip))
+- *block = gfs2_alloc_data(ip);
+- else
+- *block = gfs2_alloc_meta(ip);
++static inline void release_metapath(struct metapath *mp)
++{
++ int i;
+
+- gfs2_trans_add_bh(ip->i_gl, bh, 1);
++ for (i = 0; i < GFS2_MAX_META_HEIGHT; i++) {
++ if (mp->mp_bh[i] == NULL)
++ break;
++ brelse(mp->mp_bh[i]);
++ }
++}
+
+- *ptr = cpu_to_be64(*block);
+- ip->i_di.di_blocks++;
+- gfs2_set_inode_blocks(&ip->i_inode);
++/**
++ * gfs2_extent_length - Returns length of an extent of blocks
++ * @start: Start of the buffer
++ * @len: Length of the buffer in bytes
++ * @ptr: Current position in the buffer
++ * @limit: Max extent length to return (0 = unlimited)
++ * @eob: Set to 1 if we hit "end of block"
++ *
++ * If the first block is zero (unallocated) it will return the number of
++ * unallocated blocks in the extent, otherwise it will return the number
++ * of contiguous blocks in the extent.
++ *
++ * Returns: The length of the extent (minimum of one block)
++ */
+
+- *new = 1;
+- return 0;
++static inline unsigned int gfs2_extent_length(void *start, unsigned int len, __be64 *ptr, unsigned limit, int *eob)
++{
++ const __be64 *end = (start + len);
++ const __be64 *first = ptr;
++ u64 d = be64_to_cpu(*ptr);
++
++ *eob = 0;
++ do {
++ ptr++;
++ if (ptr >= end)
++ break;
++ if (limit && --limit == 0)
++ break;
++ if (d)
++ d++;
++ } while(be64_to_cpu(*ptr) == d);
++ if (ptr >= end)
++ *eob = 1;
++ return (ptr - first);
+ }
+
+-static inline void bmap_lock(struct inode *inode, int create)
++static inline void bmap_lock(struct gfs2_inode *ip, int create)
+ {
+- struct gfs2_inode *ip = GFS2_I(inode);
+ if (create)
+ down_write(&ip->i_rw_mutex);
+ else
+ down_read(&ip->i_rw_mutex);
+ }
+
+-static inline void bmap_unlock(struct inode *inode, int create)
++static inline void bmap_unlock(struct gfs2_inode *ip, int create)
+ {
+- struct gfs2_inode *ip = GFS2_I(inode);
+ if (create)
+ up_write(&ip->i_rw_mutex);
+ else
+ up_read(&ip->i_rw_mutex);
+ }
+
++static inline __be64 *gfs2_indirect_init(struct metapath *mp,
++ struct gfs2_glock *gl, unsigned int i,
++ unsigned offset, u64 bn)
++{
++ __be64 *ptr = (__be64 *)(mp->mp_bh[i - 1]->b_data +
++ ((i > 1) ? sizeof(struct gfs2_meta_header) :
++ sizeof(struct gfs2_dinode)));
++ BUG_ON(i < 1);
++ BUG_ON(mp->mp_bh[i] != NULL);
++ mp->mp_bh[i] = gfs2_meta_new(gl, bn);
++ gfs2_trans_add_bh(gl, mp->mp_bh[i], 1);
++ gfs2_metatype_set(mp->mp_bh[i], GFS2_METATYPE_IN, GFS2_FORMAT_IN);
++ gfs2_buffer_clear_tail(mp->mp_bh[i], sizeof(struct gfs2_meta_header));
++ ptr += offset;
++ *ptr = cpu_to_be64(bn);
++ return ptr;
++}
++
++enum alloc_state {
++ ALLOC_DATA = 0,
++ ALLOC_GROW_DEPTH = 1,
++ ALLOC_GROW_HEIGHT = 2,
++ /* ALLOC_UNSTUFF = 3, TBD and rather complicated */
++};
++
++/**
++ * gfs2_bmap_alloc - Build a metadata tree of the requested height
++ * @inode: The GFS2 inode
++ * @lblock: The logical starting block of the extent
++ * @bh_map: This is used to return the mapping details
++ * @mp: The metapath
++ * @sheight: The starting height (i.e. whats already mapped)
++ * @height: The height to build to
++ * @maxlen: The max number of data blocks to alloc
++ *
++ * In this routine we may have to alloc:
++ * i) Indirect blocks to grow the metadata tree height
++ * ii) Indirect blocks to fill in lower part of the metadata tree
++ * iii) Data blocks
++ *
++ * The function is in two parts. The first part works out the total
++ * number of blocks which we need. The second part does the actual
++ * allocation asking for an extent at a time (if enough contiguous free
++ * blocks are available, there will only be one request per bmap call)
++ * and uses the state machine to initialise the blocks in order.
++ *
++ * Returns: errno on error
++ */
++
++static int gfs2_bmap_alloc(struct inode *inode, const sector_t lblock,
++ struct buffer_head *bh_map, struct metapath *mp,
++ const unsigned int sheight,
++ const unsigned int height,
++ const unsigned int maxlen)
++{
++ struct gfs2_inode *ip = GFS2_I(inode);
++ struct gfs2_sbd *sdp = GFS2_SB(inode);
++ struct buffer_head *dibh = mp->mp_bh[0];
++ u64 bn, dblock = 0;
++ unsigned n, i, blks, alloced = 0, iblks = 0, zmpl = 0;
++ unsigned dblks = 0;
++ unsigned ptrs_per_blk;
++ const unsigned end_of_metadata = height - 1;
++ int eob = 0;
++ enum alloc_state state;
++ __be64 *ptr;
++ __be64 zero_bn = 0;
++
++ BUG_ON(sheight < 1);
++ BUG_ON(dibh == NULL);
++
++ gfs2_trans_add_bh(ip->i_gl, dibh, 1);
++
++ if (height == sheight) {
++ struct buffer_head *bh;
++ /* Bottom indirect block exists, find unalloced extent size */
++ ptr = metapointer(end_of_metadata, mp);
++ bh = mp->mp_bh[end_of_metadata];
++ dblks = gfs2_extent_length(bh->b_data, bh->b_size, ptr, maxlen,
++ &eob);
++ BUG_ON(dblks < 1);
++ state = ALLOC_DATA;
++ } else {
++ /* Need to allocate indirect blocks */
++ ptrs_per_blk = height > 1 ? sdp->sd_inptrs : sdp->sd_diptrs;
++ dblks = min(maxlen, ptrs_per_blk - mp->mp_list[end_of_metadata]);
++ if (height == ip->i_height) {
++ /* Writing into existing tree, extend tree down */
++ iblks = height - sheight;
++ state = ALLOC_GROW_DEPTH;
++ } else {
++ /* Building up tree height */
++ state = ALLOC_GROW_HEIGHT;
++ iblks = height - ip->i_height;
++ zmpl = zero_metapath_length(mp, height);
++ iblks -= zmpl;
++ iblks += height;
++ }
++ }
++
++ /* start of the second part of the function (state machine) */
++
++ blks = dblks + iblks;
++ i = sheight;
++ do {
++ n = blks - alloced;
++ bn = gfs2_alloc_block(ip, &n);
++ alloced += n;
++ if (state != ALLOC_DATA || gfs2_is_jdata(ip))
++ gfs2_trans_add_unrevoke(sdp, bn, n);
++ switch (state) {
++ /* Growing height of tree */
++ case ALLOC_GROW_HEIGHT:
++ if (i == 1) {
++ ptr = (__be64 *)(dibh->b_data +
++ sizeof(struct gfs2_dinode));
++ zero_bn = *ptr;
++ }
++ for (; i - 1 < height - ip->i_height && n > 0; i++, n--)
++ gfs2_indirect_init(mp, ip->i_gl, i, 0, bn++);
++ if (i - 1 == height - ip->i_height) {
++ i--;
++ gfs2_buffer_copy_tail(mp->mp_bh[i],
++ sizeof(struct gfs2_meta_header),
++ dibh, sizeof(struct gfs2_dinode));
++ gfs2_buffer_clear_tail(dibh,
++ sizeof(struct gfs2_dinode) +
++ sizeof(__be64));
++ ptr = (__be64 *)(mp->mp_bh[i]->b_data +
++ sizeof(struct gfs2_meta_header));
++ *ptr = zero_bn;
++ state = ALLOC_GROW_DEPTH;
++ for(i = zmpl; i < height; i++) {
++ if (mp->mp_bh[i] == NULL)
++ break;
++ brelse(mp->mp_bh[i]);
++ mp->mp_bh[i] = NULL;
++ }
++ i = zmpl;
++ }
++ if (n == 0)
++ break;
++ /* Branching from existing tree */
++ case ALLOC_GROW_DEPTH:
++ if (i > 1 && i < height)
++ gfs2_trans_add_bh(ip->i_gl, mp->mp_bh[i-1], 1);
++ for (; i < height && n > 0; i++, n--)
++ gfs2_indirect_init(mp, ip->i_gl, i,
++ mp->mp_list[i-1], bn++);
++ if (i == height)
++ state = ALLOC_DATA;
++ if (n == 0)
++ break;
++ /* Tree complete, adding data blocks */
++ case ALLOC_DATA:
++ BUG_ON(n > dblks);
++ BUG_ON(mp->mp_bh[end_of_metadata] == NULL);
++ gfs2_trans_add_bh(ip->i_gl, mp->mp_bh[end_of_metadata], 1);
++ dblks = n;
++ ptr = metapointer(end_of_metadata, mp);
++ dblock = bn;
++ while (n-- > 0)
++ *ptr++ = cpu_to_be64(bn++);
++ break;
++ }
++ } while (state != ALLOC_DATA);
++
++ ip->i_height = height;
++ gfs2_add_inode_blocks(&ip->i_inode, alloced);
++ gfs2_dinode_out(ip, mp->mp_bh[0]->b_data);
++ map_bh(bh_map, inode->i_sb, dblock);
++ bh_map->b_size = dblks << inode->i_blkbits;
++ set_buffer_new(bh_map);
++ return 0;
++}
++
+ /**
+ * gfs2_block_map - Map a block from an inode to a disk block
+ * @inode: The inode
+ * @lblock: The logical block number
+ * @bh_map: The bh to be mapped
++ * @create: True if its ok to alloc blocks to satify the request
+ *
+- * Find the block number on the current device which corresponds to an
+- * inode's block. If the block had to be created, "new" will be set.
++ * Sets buffer_mapped() if successful, sets buffer_boundary() if a
++ * read of metadata will be required before the next block can be
++ * mapped. Sets buffer_new() if new blocks were allocated.
+ *
+ * Returns: errno
+ */
+@@ -457,97 +572,78 @@ int gfs2_block_map(struct inode *inode, sector_t lblock,
+ {
+ struct gfs2_inode *ip = GFS2_I(inode);
+ struct gfs2_sbd *sdp = GFS2_SB(inode);
+- struct buffer_head *bh;
+- unsigned int bsize;
+- unsigned int height;
+- unsigned int end_of_metadata;
+- unsigned int x;
+- int error = 0;
+- int new = 0;
+- u64 dblock = 0;
+- int boundary;
+- unsigned int maxlen = bh_map->b_size >> inode->i_blkbits;
+- struct metapath mp;
++ unsigned int bsize = sdp->sd_sb.sb_bsize;
++ const unsigned int maxlen = bh_map->b_size >> inode->i_blkbits;
++ const u64 *arr = sdp->sd_heightsize;
++ __be64 *ptr;
+ u64 size;
+- struct buffer_head *dibh = NULL;
++ struct metapath mp;
++ int ret;
++ int eob;
++ unsigned int len;
++ struct buffer_head *bh;
++ u8 height;
+
+ BUG_ON(maxlen == 0);
+
+- if (gfs2_assert_warn(sdp, !gfs2_is_stuffed(ip)))
+- return 0;
+-
+- bmap_lock(inode, create);
++ memset(mp.mp_bh, 0, sizeof(mp.mp_bh));
++ bmap_lock(ip, create);
+ clear_buffer_mapped(bh_map);
+ clear_buffer_new(bh_map);
+ clear_buffer_boundary(bh_map);
+- bsize = gfs2_is_dir(ip) ? sdp->sd_jbsize : sdp->sd_sb.sb_bsize;
+- size = (lblock + 1) * bsize;
+-
+- if (size > ip->i_di.di_size) {
+- height = calc_tree_height(ip, size);
+- if (ip->i_di.di_height < height) {
+- if (!create)
+- goto out_ok;
+-
+- error = build_height(inode, height);
+- if (error)
+- goto out_fail;
+- }
++ if (gfs2_is_dir(ip)) {
++ bsize = sdp->sd_jbsize;
++ arr = sdp->sd_jheightsize;
+ }
+
+- find_metapath(ip, lblock, &mp);
+- end_of_metadata = ip->i_di.di_height - 1;
+- error = gfs2_meta_inode_buffer(ip, &bh);
+- if (error)
+- goto out_fail;
+- dibh = bh;
+- get_bh(dibh);
++ ret = gfs2_meta_inode_buffer(ip, &mp.mp_bh[0]);
++ if (ret)
++ goto out;
+
+- for (x = 0; x < end_of_metadata; x++) {
+- lookup_block(ip, bh, x, &mp, create, &new, &dblock);
+- brelse(bh);
+- if (!dblock)
+- goto out_ok;
++ height = ip->i_height;
++ size = (lblock + 1) * bsize;
++ while (size > arr[height])
++ height++;
++ find_metapath(sdp, lblock, &mp, height);
++ ret = 1;
++ if (height > ip->i_height || gfs2_is_stuffed(ip))
++ goto do_alloc;
++ ret = lookup_metapath(ip, &mp);
++ if (ret < 0)
++ goto out;
++ if (ret != ip->i_height)
++ goto do_alloc;
++ ptr = metapointer(ip->i_height - 1, &mp);
++ if (*ptr == 0)
++ goto do_alloc;
++ map_bh(bh_map, inode->i_sb, be64_to_cpu(*ptr));
++ bh = mp.mp_bh[ip->i_height - 1];
++ len = gfs2_extent_length(bh->b_data, bh->b_size, ptr, maxlen, &eob);
++ bh_map->b_size = (len << inode->i_blkbits);
++ if (eob)
++ set_buffer_boundary(bh_map);
++ ret = 0;
++out:
++ release_metapath(&mp);
++ bmap_unlock(ip, create);
++ return ret;
+
+- error = gfs2_meta_indirect_buffer(ip, x+1, dblock, new, &bh);
+- if (error)
+- goto out_fail;
++do_alloc:
++ /* All allocations are done here, firstly check create flag */
++ if (!create) {
++ BUG_ON(gfs2_is_stuffed(ip));
++ ret = 0;
++ goto out;
+ }
+
+- boundary = lookup_block(ip, bh, end_of_metadata, &mp, create, &new, &dblock);
+- if (dblock) {
+- map_bh(bh_map, inode->i_sb, dblock);
+- if (boundary)
+- set_buffer_boundary(bh_map);
+- if (new) {
+- gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+- gfs2_dinode_out(ip, dibh->b_data);
+- set_buffer_new(bh_map);
+- goto out_brelse;
+- }
+- while(--maxlen && !buffer_boundary(bh_map)) {
+- u64 eblock;
+-
+- mp.mp_list[end_of_metadata]++;
+- boundary = lookup_block(ip, bh, end_of_metadata, &mp, 0, &new, &eblock);
+- if (eblock != ++dblock)
+- break;
+- bh_map->b_size += (1 << inode->i_blkbits);
+- if (boundary)
+- set_buffer_boundary(bh_map);
+- }
+- }
+-out_brelse:
+- brelse(bh);
+-out_ok:
+- error = 0;
+-out_fail:
+- if (dibh)
+- brelse(dibh);
+- bmap_unlock(inode, create);
+- return error;
++ /* At this point ret is the tree depth of already allocated blocks */
++ ret = gfs2_bmap_alloc(inode, lblock, bh_map, &mp, ret, height, maxlen);
++ goto out;
+ }
+
++/*
++ * Deprecated: do not use in new code
++ */
+ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen)
+ {
+ struct buffer_head bh = { .b_state = 0, .b_blocknr = 0 };
+@@ -558,7 +654,7 @@ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsi
+ BUG_ON(!dblock);
+ BUG_ON(!new);
+
+- bh.b_size = 1 << (inode->i_blkbits + 5);
++ bh.b_size = 1 << (inode->i_blkbits + (create ? 0 : 5));
+ ret = gfs2_block_map(inode, lblock, &bh, create);
+ *extlen = bh.b_size >> inode->i_blkbits;
+ *dblock = bh.b_blocknr;
+@@ -621,7 +717,7 @@ static int recursive_scan(struct gfs2_inode *ip, struct buffer_head *dibh,
+ if (error)
+ goto out;
+
+- if (height < ip->i_di.di_height - 1)
++ if (height < ip->i_height - 1)
+ for (; top < bottom; top++, first = 0) {
+ if (!*top)
+ continue;
+@@ -679,7 +775,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
+ sm->sm_first = 0;
+ }
+
+- metadata = (height != ip->i_di.di_height - 1);
++ metadata = (height != ip->i_height - 1);
+ if (metadata)
+ revokes = (height) ? sdp->sd_inptrs : sdp->sd_diptrs;
+
+@@ -713,7 +809,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
+ else
+ goto out; /* Nothing to do */
+
+- gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE, 0);
++ gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE);
+
+ for (x = 0; x < rlist.rl_rgrps; x++) {
+ struct gfs2_rgrpd *rgd;
+@@ -760,10 +856,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
+ }
+
+ *p = 0;
+- if (!ip->i_di.di_blocks)
+- gfs2_consist_inode(ip);
+- ip->i_di.di_blocks--;
+- gfs2_set_inode_blocks(&ip->i_inode);
++ gfs2_add_inode_blocks(&ip->i_inode, -1);
+ }
+ if (bstart) {
+ if (metadata)
+@@ -804,19 +897,16 @@ static int do_grow(struct gfs2_inode *ip, u64 size)
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+ struct gfs2_alloc *al;
+ struct buffer_head *dibh;
+- unsigned int h;
+ int error;
+
+ al = gfs2_alloc_get(ip);
++ if (!al)
++ return -ENOMEM;
+
+- error = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
++ error = gfs2_quota_lock_check(ip);
+ if (error)
+ goto out;
+
+- error = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid);
+- if (error)
+- goto out_gunlock_q;
+-
+ al->al_requested = sdp->sd_max_height + RES_DATA;
+
+ error = gfs2_inplace_reserve(ip);
+@@ -829,34 +919,25 @@ static int do_grow(struct gfs2_inode *ip, u64 size)
+ if (error)
+ goto out_ipres;
+
++ error = gfs2_meta_inode_buffer(ip, &dibh);
++ if (error)
++ goto out_end_trans;
++
+ if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) {
+ if (gfs2_is_stuffed(ip)) {
+ error = gfs2_unstuff_dinode(ip, NULL);
+ if (error)
+- goto out_end_trans;
+- }
+-
+- h = calc_tree_height(ip, size);
+- if (ip->i_di.di_height < h) {
+- down_write(&ip->i_rw_mutex);
+- error = build_height(&ip->i_inode, h);
+- up_write(&ip->i_rw_mutex);
+- if (error)
+- goto out_end_trans;
++ goto out_brelse;
+ }
+ }
+
+ ip->i_di.di_size = size;
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
+-
+- error = gfs2_meta_inode_buffer(ip, &dibh);
+- if (error)
+- goto out_end_trans;
+-
+ gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+ gfs2_dinode_out(ip, dibh->b_data);
+- brelse(dibh);
+
++out_brelse:
++ brelse(dibh);
+ out_end_trans:
+ gfs2_trans_end(sdp);
+ out_ipres:
+@@ -986,7 +1067,8 @@ out:
+
+ static int trunc_dealloc(struct gfs2_inode *ip, u64 size)
+ {
+- unsigned int height = ip->i_di.di_height;
++ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
++ unsigned int height = ip->i_height;
+ u64 lblock;
+ struct metapath mp;
+ int error;
+@@ -994,10 +1076,11 @@ static int trunc_dealloc(struct gfs2_inode *ip, u64 size)
+ if (!size)
+ lblock = 0;
+ else
+- lblock = (size - 1) >> GFS2_SB(&ip->i_inode)->sd_sb.sb_bsize_shift;
++ lblock = (size - 1) >> sdp->sd_sb.sb_bsize_shift;
+
+- find_metapath(ip, lblock, &mp);
+- gfs2_alloc_get(ip);
++ find_metapath(sdp, lblock, &mp, ip->i_height);
++ if (!gfs2_alloc_get(ip))
++ return -ENOMEM;
+
+ error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
+ if (error)
+@@ -1037,10 +1120,8 @@ static int trunc_end(struct gfs2_inode *ip)
+ goto out;
+
+ if (!ip->i_di.di_size) {
+- ip->i_di.di_height = 0;
+- ip->i_di.di_goal_meta =
+- ip->i_di.di_goal_data =
+- ip->i_no_addr;
++ ip->i_height = 0;
++ ip->i_goal = ip->i_no_addr;
+ gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
+ }
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
+@@ -1197,10 +1278,9 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
+ unsigned int len, int *alloc_required)
+ {
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+- u64 lblock, lblock_stop, dblock;
+- u32 extlen;
+- int new = 0;
+- int error = 0;
++ struct buffer_head bh;
++ unsigned int shift;
++ u64 lblock, lblock_stop, size;
+
+ *alloc_required = 0;
+
+@@ -1214,6 +1294,8 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
+ return 0;
+ }
+
++ *alloc_required = 1;
++ shift = sdp->sd_sb.sb_bsize_shift;
+ if (gfs2_is_dir(ip)) {
+ unsigned int bsize = sdp->sd_jbsize;
+ lblock = offset;
+@@ -1221,27 +1303,25 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
+ lblock_stop = offset + len + bsize - 1;
+ do_div(lblock_stop, bsize);
+ } else {
+- unsigned int shift = sdp->sd_sb.sb_bsize_shift;
+ u64 end_of_file = (ip->i_di.di_size + sdp->sd_sb.sb_bsize - 1) >> shift;
+ lblock = offset >> shift;
+ lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift;
+- if (lblock_stop > end_of_file) {
+- *alloc_required = 1;
++ if (lblock_stop > end_of_file)
+ return 0;
+- }
+ }
+
+- for (; lblock < lblock_stop; lblock += extlen) {
+- error = gfs2_extent_map(&ip->i_inode, lblock, &new, &dblock, &extlen);
+- if (error)
+- return error;
+-
+- if (!dblock) {
+- *alloc_required = 1;
++ size = (lblock_stop - lblock) << shift;
++ do {
++ bh.b_state = 0;
++ bh.b_size = size;
++ gfs2_block_map(&ip->i_inode, lblock, &bh, 0);
++ if (!buffer_mapped(&bh))
+ return 0;
+- }
+- }
++ size -= bh.b_size;
++ lblock += (bh.b_size >> ip->i_inode.i_blkbits);
++ } while(size > 0);
+
++ *alloc_required = 0;
+ return 0;
+ }
+
+diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
+index c347095..eed040d 100644
+--- a/fs/gfs2/dir.c
++++ b/fs/gfs2/dir.c
+@@ -159,6 +159,7 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf,
+ unsigned int o;
+ int copied = 0;
+ int error = 0;
++ int new = 0;
+
+ if (!size)
+ return 0;
+@@ -183,7 +184,6 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf,
+ while (copied < size) {
+ unsigned int amount;
+ struct buffer_head *bh;
+- int new = 0;
+
+ amount = size - copied;
+ if (amount > sdp->sd_sb.sb_bsize - o)
+@@ -757,7 +757,7 @@ static struct gfs2_dirent *gfs2_dirent_search(struct inode *inode,
+
+ if (ip->i_di.di_flags & GFS2_DIF_EXHASH) {
+ struct gfs2_leaf *leaf;
+- unsigned hsize = 1 << ip->i_di.di_depth;
++ unsigned hsize = 1 << ip->i_depth;
+ unsigned index;
+ u64 ln;
+ if (hsize * sizeof(u64) != ip->i_di.di_size) {
+@@ -765,7 +765,7 @@ static struct gfs2_dirent *gfs2_dirent_search(struct inode *inode,
+ return ERR_PTR(-EIO);
+ }
+
+- index = name->hash >> (32 - ip->i_di.di_depth);
++ index = name->hash >> (32 - ip->i_depth);
+ error = get_first_leaf(ip, index, &bh);
+ if (error)
+ return ERR_PTR(error);
+@@ -803,14 +803,15 @@ got_dent:
+ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh, u16 depth)
+ {
+ struct gfs2_inode *ip = GFS2_I(inode);
+- u64 bn = gfs2_alloc_meta(ip);
++ unsigned int n = 1;
++ u64 bn = gfs2_alloc_block(ip, &n);
+ struct buffer_head *bh = gfs2_meta_new(ip->i_gl, bn);
+ struct gfs2_leaf *leaf;
+ struct gfs2_dirent *dent;
+ struct qstr name = { .name = "", .len = 0, .hash = 0 };
+ if (!bh)
+ return NULL;
+-
++ gfs2_trans_add_unrevoke(GFS2_SB(inode), bn, 1);
+ gfs2_trans_add_bh(ip->i_gl, bh, 1);
+ gfs2_metatype_set(bh, GFS2_METATYPE_LF, GFS2_FORMAT_LF);
+ leaf = (struct gfs2_leaf *)bh->b_data;
+@@ -905,12 +906,11 @@ static int dir_make_exhash(struct inode *inode)
+ *lp = cpu_to_be64(bn);
+
+ dip->i_di.di_size = sdp->sd_sb.sb_bsize / 2;
+- dip->i_di.di_blocks++;
+- gfs2_set_inode_blocks(&dip->i_inode);
++ gfs2_add_inode_blocks(&dip->i_inode, 1);
+ dip->i_di.di_flags |= GFS2_DIF_EXHASH;
+
+ for (x = sdp->sd_hash_ptrs, y = -1; x; x >>= 1, y++) ;
+- dip->i_di.di_depth = y;
++ dip->i_depth = y;
+
+ gfs2_dinode_out(dip, dibh->b_data);
+
+@@ -941,7 +941,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
+ int x, moved = 0;
+ int error;
+
+- index = name->hash >> (32 - dip->i_di.di_depth);
++ index = name->hash >> (32 - dip->i_depth);
+ error = get_leaf_nr(dip, index, &leaf_no);
+ if (error)
+ return error;
+@@ -952,7 +952,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
+ return error;
+
+ oleaf = (struct gfs2_leaf *)obh->b_data;
+- if (dip->i_di.di_depth == be16_to_cpu(oleaf->lf_depth)) {
++ if (dip->i_depth == be16_to_cpu(oleaf->lf_depth)) {
+ brelse(obh);
+ return 1; /* can't split */
+ }
+@@ -967,10 +967,10 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
+ bn = nbh->b_blocknr;
+
+ /* Compute the start and len of leaf pointers in the hash table. */
+- len = 1 << (dip->i_di.di_depth - be16_to_cpu(oleaf->lf_depth));
++ len = 1 << (dip->i_depth - be16_to_cpu(oleaf->lf_depth));
+ half_len = len >> 1;
+ if (!half_len) {
+- printk(KERN_WARNING "di_depth %u lf_depth %u index %u\n", dip->i_di.di_depth, be16_to_cpu(oleaf->lf_depth), index);
++ printk(KERN_WARNING "i_depth %u lf_depth %u index %u\n", dip->i_depth, be16_to_cpu(oleaf->lf_depth), index);
+ gfs2_consist_inode(dip);
+ error = -EIO;
+ goto fail_brelse;
+@@ -997,7 +997,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
+ kfree(lp);
+
+ /* Compute the divider */
+- divider = (start + half_len) << (32 - dip->i_di.di_depth);
++ divider = (start + half_len) << (32 - dip->i_depth);
+
+ /* Copy the entries */
+ dirent_first(dip, obh, &dent);
+@@ -1021,13 +1021,13 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
+
+ new->de_inum = dent->de_inum; /* No endian worries */
+ new->de_type = dent->de_type; /* No endian worries */
+- nleaf->lf_entries = cpu_to_be16(be16_to_cpu(nleaf->lf_entries)+1);
++ be16_add_cpu(&nleaf->lf_entries, 1);
+
+ dirent_del(dip, obh, prev, dent);
+
+ if (!oleaf->lf_entries)
+ gfs2_consist_inode(dip);
+- oleaf->lf_entries = cpu_to_be16(be16_to_cpu(oleaf->lf_entries)-1);
++ be16_add_cpu(&oleaf->lf_entries, -1);
+
+ if (!prev)
+ prev = dent;
+@@ -1044,8 +1044,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
+ error = gfs2_meta_inode_buffer(dip, &dibh);
+ if (!gfs2_assert_withdraw(GFS2_SB(&dip->i_inode), !error)) {
+ gfs2_trans_add_bh(dip->i_gl, dibh, 1);
+- dip->i_di.di_blocks++;
+- gfs2_set_inode_blocks(&dip->i_inode);
++ gfs2_add_inode_blocks(&dip->i_inode, 1);
+ gfs2_dinode_out(dip, dibh->b_data);
+ brelse(dibh);
+ }
+@@ -1082,7 +1081,7 @@ static int dir_double_exhash(struct gfs2_inode *dip)
+ int x;
+ int error = 0;
+
+- hsize = 1 << dip->i_di.di_depth;
++ hsize = 1 << dip->i_depth;
+ if (hsize * sizeof(u64) != dip->i_di.di_size) {
+ gfs2_consist_inode(dip);
+ return -EIO;
+@@ -1090,7 +1089,7 @@ static int dir_double_exhash(struct gfs2_inode *dip)
+
+ /* Allocate both the "from" and "to" buffers in one big chunk */
+
+- buf = kcalloc(3, sdp->sd_hash_bsize, GFP_KERNEL | __GFP_NOFAIL);
++ buf = kcalloc(3, sdp->sd_hash_bsize, GFP_NOFS | __GFP_NOFAIL);
+
+ for (block = dip->i_di.di_size >> sdp->sd_hash_bsize_shift; block--;) {
+ error = gfs2_dir_read_data(dip, (char *)buf,
+@@ -1125,7 +1124,7 @@ static int dir_double_exhash(struct gfs2_inode *dip)
+
+ error = gfs2_meta_inode_buffer(dip, &dibh);
+ if (!gfs2_assert_withdraw(sdp, !error)) {
+- dip->i_di.di_depth++;
++ dip->i_depth++;
+ gfs2_dinode_out(dip, dibh->b_data);
+ brelse(dibh);
+ }
+@@ -1370,16 +1369,16 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
+ int error = 0;
+ unsigned depth = 0;
+
+- hsize = 1 << dip->i_di.di_depth;
++ hsize = 1 << dip->i_depth;
+ if (hsize * sizeof(u64) != dip->i_di.di_size) {
+ gfs2_consist_inode(dip);
+ return -EIO;
+ }
+
+ hash = gfs2_dir_offset2hash(*offset);
+- index = hash >> (32 - dip->i_di.di_depth);
++ index = hash >> (32 - dip->i_depth);
+
+- lp = kmalloc(sdp->sd_hash_bsize, GFP_KERNEL);
++ lp = kmalloc(sdp->sd_hash_bsize, GFP_NOFS);
+ if (!lp)
+ return -ENOMEM;
+
+@@ -1405,7 +1404,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
+ if (error)
+ break;
+
+- len = 1 << (dip->i_di.di_depth - depth);
++ len = 1 << (dip->i_depth - depth);
+ index = (index & ~(len - 1)) + len;
+ }
+
+@@ -1444,7 +1443,7 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
+
+ error = -ENOMEM;
+ /* 96 is max number of dirents which can be stuffed into an inode */
+- darr = kmalloc(96 * sizeof(struct gfs2_dirent *), GFP_KERNEL);
++ darr = kmalloc(96 * sizeof(struct gfs2_dirent *), GFP_NOFS);
+ if (darr) {
+ g.pdent = darr;
+ g.offset = 0;
+@@ -1549,7 +1548,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name)
+ u32 index;
+ u64 bn;
+
+- index = name->hash >> (32 - ip->i_di.di_depth);
++ index = name->hash >> (32 - ip->i_depth);
+ error = get_first_leaf(ip, index, &obh);
+ if (error)
+ return error;
+@@ -1579,8 +1578,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name)
+ if (error)
+ return error;
+ gfs2_trans_add_bh(ip->i_gl, bh, 1);
+- ip->i_di.di_blocks++;
+- gfs2_set_inode_blocks(&ip->i_inode);
++ gfs2_add_inode_blocks(&ip->i_inode, 1);
+ gfs2_dinode_out(ip, bh->b_data);
+ brelse(bh);
+ return 0;
+@@ -1616,7 +1614,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
+ dent->de_type = cpu_to_be16(type);
+ if (ip->i_di.di_flags & GFS2_DIF_EXHASH) {
+ leaf = (struct gfs2_leaf *)bh->b_data;
+- leaf->lf_entries = cpu_to_be16(be16_to_cpu(leaf->lf_entries) + 1);
++ be16_add_cpu(&leaf->lf_entries, 1);
+ }
+ brelse(bh);
+ error = gfs2_meta_inode_buffer(ip, &bh);
+@@ -1641,7 +1639,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
+ continue;
+ if (error < 0)
+ break;
+- if (ip->i_di.di_depth < GFS2_DIR_MAX_DEPTH) {
++ if (ip->i_depth < GFS2_DIR_MAX_DEPTH) {
+ error = dir_double_exhash(ip);
+ if (error)
+ break;
+@@ -1785,13 +1783,13 @@ static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data)
+ u64 leaf_no;
+ int error = 0;
+
+- hsize = 1 << dip->i_di.di_depth;
++ hsize = 1 << dip->i_depth;
+ if (hsize * sizeof(u64) != dip->i_di.di_size) {
+ gfs2_consist_inode(dip);
+ return -EIO;
+ }
+
+- lp = kmalloc(sdp->sd_hash_bsize, GFP_KERNEL);
++ lp = kmalloc(sdp->sd_hash_bsize, GFP_NOFS);
+ if (!lp)
+ return -ENOMEM;
+
+@@ -1817,7 +1815,7 @@ static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data)
+ if (error)
+ goto out;
+ leaf = (struct gfs2_leaf *)bh->b_data;
+- len = 1 << (dip->i_di.di_depth - be16_to_cpu(leaf->lf_depth));
++ len = 1 << (dip->i_depth - be16_to_cpu(leaf->lf_depth));
+ brelse(bh);
+
+ error = lc(dip, index, len, leaf_no, data);
+@@ -1866,15 +1864,18 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
+
+ memset(&rlist, 0, sizeof(struct gfs2_rgrp_list));
+
+- ht = kzalloc(size, GFP_KERNEL);
++ ht = kzalloc(size, GFP_NOFS);
+ if (!ht)
+ return -ENOMEM;
+
+- gfs2_alloc_get(dip);
++ if (!gfs2_alloc_get(dip)) {
++ error = -ENOMEM;
++ goto out;
++ }
+
+ error = gfs2_quota_hold(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
+ if (error)
+- goto out;
++ goto out_put;
+
+ error = gfs2_rindex_hold(sdp, &dip->i_alloc->al_ri_gh);
+ if (error)
+@@ -1894,7 +1895,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
+ l_blocks++;
+ }
+
+- gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE, 0);
++ gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE);
+
+ for (x = 0; x < rlist.rl_rgrps; x++) {
+ struct gfs2_rgrpd *rgd;
+@@ -1921,11 +1922,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
+ brelse(bh);
+
+ gfs2_free_meta(dip, blk, 1);
+-
+- if (!dip->i_di.di_blocks)
+- gfs2_consist_inode(dip);
+- dip->i_di.di_blocks--;
+- gfs2_set_inode_blocks(&dip->i_inode);
++ gfs2_add_inode_blocks(&dip->i_inode, -1);
+ }
+
+ error = gfs2_dir_write_data(dip, ht, index * sizeof(u64), size);
+@@ -1952,8 +1949,9 @@ out_rlist:
+ gfs2_glock_dq_uninit(&dip->i_alloc->al_ri_gh);
+ out_qs:
+ gfs2_quota_unhold(dip);
+-out:
++out_put:
+ gfs2_alloc_put(dip);
++out:
+ kfree(ht);
+ return error;
+ }
+diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c
+index bee9970..e3f76f4 100644
+--- a/fs/gfs2/eattr.c
++++ b/fs/gfs2/eattr.c
+@@ -277,10 +277,7 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,
+ }
+
+ *dataptrs = 0;
+- if (!ip->i_di.di_blocks)
+- gfs2_consist_inode(ip);
+- ip->i_di.di_blocks--;
+- gfs2_set_inode_blocks(&ip->i_inode);
++ gfs2_add_inode_blocks(&ip->i_inode, -1);
+ }
+ if (bstart)
+ gfs2_free_meta(ip, bstart, blen);
+@@ -321,6 +318,8 @@ static int ea_remove_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,
+ int error;
+
+ al = gfs2_alloc_get(ip);
++ if (!al)
++ return -ENOMEM;
+
+ error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
+ if (error)
+@@ -449,7 +448,7 @@ static int ea_get_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
+ unsigned int x;
+ int error = 0;
+
+- bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_KERNEL);
++ bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_NOFS);
+ if (!bh)
+ return -ENOMEM;
+
+@@ -582,10 +581,11 @@ static int ea_alloc_blk(struct gfs2_inode *ip, struct buffer_head **bhp)
+ {
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+ struct gfs2_ea_header *ea;
++ unsigned int n = 1;
+ u64 block;
+
+- block = gfs2_alloc_meta(ip);
+-
++ block = gfs2_alloc_block(ip, &n);
++ gfs2_trans_add_unrevoke(sdp, block, 1);
+ *bhp = gfs2_meta_new(ip->i_gl, block);
+ gfs2_trans_add_bh(ip->i_gl, *bhp, 1);
+ gfs2_metatype_set(*bhp, GFS2_METATYPE_EA, GFS2_FORMAT_EA);
+@@ -597,8 +597,7 @@ static int ea_alloc_blk(struct gfs2_inode *ip, struct buffer_head **bhp)
+ ea->ea_flags = GFS2_EAFLAG_LAST;
+ ea->ea_num_ptrs = 0;
+
+- ip->i_di.di_blocks++;
+- gfs2_set_inode_blocks(&ip->i_inode);
++ gfs2_add_inode_blocks(&ip->i_inode, 1);
+
+ return 0;
+ }
+@@ -642,15 +641,15 @@ static int ea_write(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
+ struct buffer_head *bh;
+ u64 block;
+ int mh_size = sizeof(struct gfs2_meta_header);
++ unsigned int n = 1;
+
+- block = gfs2_alloc_meta(ip);
+-
++ block = gfs2_alloc_block(ip, &n);
++ gfs2_trans_add_unrevoke(sdp, block, 1);
+ bh = gfs2_meta_new(ip->i_gl, block);
+ gfs2_trans_add_bh(ip->i_gl, bh, 1);
+ gfs2_metatype_set(bh, GFS2_METATYPE_ED, GFS2_FORMAT_ED);
+
+- ip->i_di.di_blocks++;
+- gfs2_set_inode_blocks(&ip->i_inode);
++ gfs2_add_inode_blocks(&ip->i_inode, 1);
+
+ copy = data_len > sdp->sd_jbsize ? sdp->sd_jbsize :
+ data_len;
+@@ -684,15 +683,13 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er,
+ int error;
+
+ al = gfs2_alloc_get(ip);
++ if (!al)
++ return -ENOMEM;
+
+- error = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
++ error = gfs2_quota_lock_check(ip);
+ if (error)
+ goto out;
+
+- error = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid);
+- if (error)
+- goto out_gunlock_q;
+-
+ al->al_requested = blks;
+
+ error = gfs2_inplace_reserve(ip);
+@@ -966,9 +963,9 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er,
+ gfs2_trans_add_bh(ip->i_gl, indbh, 1);
+ } else {
+ u64 blk;
+-
+- blk = gfs2_alloc_meta(ip);
+-
++ unsigned int n = 1;
++ blk = gfs2_alloc_block(ip, &n);
++ gfs2_trans_add_unrevoke(sdp, blk, 1);
+ indbh = gfs2_meta_new(ip->i_gl, blk);
+ gfs2_trans_add_bh(ip->i_gl, indbh, 1);
+ gfs2_metatype_set(indbh, GFS2_METATYPE_IN, GFS2_FORMAT_IN);
+@@ -978,8 +975,7 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er,
+ *eablk = cpu_to_be64(ip->i_di.di_eattr);
+ ip->i_di.di_eattr = blk;
+ ip->i_di.di_flags |= GFS2_DIF_EA_INDIRECT;
+- ip->i_di.di_blocks++;
+- gfs2_set_inode_blocks(&ip->i_inode);
++ gfs2_add_inode_blocks(&ip->i_inode, 1);
+
+ eablk++;
+ }
+@@ -1210,7 +1206,7 @@ static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip,
+ unsigned int x;
+ int error;
+
+- bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_KERNEL);
++ bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_NOFS);
+ if (!bh)
+ return -ENOMEM;
+
+@@ -1347,7 +1343,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip)
+ else
+ goto out;
+
+- gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE, 0);
++ gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE);
+
+ for (x = 0; x < rlist.rl_rgrps; x++) {
+ struct gfs2_rgrpd *rgd;
+@@ -1387,10 +1383,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip)
+ }
+
+ *eablk = 0;
+- if (!ip->i_di.di_blocks)
+- gfs2_consist_inode(ip);
+- ip->i_di.di_blocks--;
+- gfs2_set_inode_blocks(&ip->i_inode);
++ gfs2_add_inode_blocks(&ip->i_inode, -1);
+ }
+ if (bstart)
+ gfs2_free_meta(ip, bstart, blen);
+@@ -1442,10 +1435,7 @@ static int ea_dealloc_block(struct gfs2_inode *ip)
+ gfs2_free_meta(ip, ip->i_di.di_eattr, 1);
+
+ ip->i_di.di_eattr = 0;
+- if (!ip->i_di.di_blocks)
+- gfs2_consist_inode(ip);
+- ip->i_di.di_blocks--;
+- gfs2_set_inode_blocks(&ip->i_inode);
++ gfs2_add_inode_blocks(&ip->i_inode, -1);
+
+ error = gfs2_meta_inode_buffer(ip, &dibh);
+ if (!error) {
+@@ -1474,6 +1464,8 @@ int gfs2_ea_dealloc(struct gfs2_inode *ip)
+ int error;
+
+ al = gfs2_alloc_get(ip);
++ if (!al)
++ return -ENOMEM;
+
+ error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
+ if (error)
+diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
+index 7175a4d..d636b3e 100644
+--- a/fs/gfs2/glock.c
++++ b/fs/gfs2/glock.c
+@@ -1,6 +1,6 @@
+ /*
+ * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
+- * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
++ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+@@ -35,7 +35,6 @@
+ #include "glock.h"
+ #include "glops.h"
+ #include "inode.h"
+-#include "lm.h"
+ #include "lops.h"
+ #include "meta_io.h"
+ #include "quota.h"
+@@ -183,7 +182,8 @@ static void glock_free(struct gfs2_glock *gl)
+ struct gfs2_sbd *sdp = gl->gl_sbd;
+ struct inode *aspace = gl->gl_aspace;
+
+- gfs2_lm_put_lock(sdp, gl->gl_lock);
++ if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++ sdp->sd_lockstruct.ls_ops->lm_put_lock(gl->gl_lock);
+
+ if (aspace)
+ gfs2_aspace_put(aspace);
+@@ -197,7 +197,7 @@ static void glock_free(struct gfs2_glock *gl)
+ *
+ */
+
+-void gfs2_glock_hold(struct gfs2_glock *gl)
++static void gfs2_glock_hold(struct gfs2_glock *gl)
+ {
+ atomic_inc(&gl->gl_ref);
+ }
+@@ -293,6 +293,16 @@ static void glock_work_func(struct work_struct *work)
+ gfs2_glock_put(gl);
+ }
+
++static int gfs2_lm_get_lock(struct gfs2_sbd *sdp, struct lm_lockname *name,
++ void **lockp)
++{
++ int error = -EIO;
++ if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++ error = sdp->sd_lockstruct.ls_ops->lm_get_lock(
++ sdp->sd_lockstruct.ls_lockspace, name, lockp);
++ return error;
++}
++
+ /**
+ * gfs2_glock_get() - Get a glock, or create one if one doesn't exist
+ * @sdp: The GFS2 superblock
+@@ -338,8 +348,6 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
+ gl->gl_ip = 0;
+ gl->gl_ops = glops;
+ gl->gl_req_gh = NULL;
+- gl->gl_req_bh = NULL;
+- gl->gl_vn = 0;
+ gl->gl_stamp = jiffies;
+ gl->gl_tchange = jiffies;
+ gl->gl_object = NULL;
+@@ -595,11 +603,12 @@ static void run_queue(struct gfs2_glock *gl)
+ blocked = rq_mutex(gh);
+ } else if (test_bit(GLF_DEMOTE, &gl->gl_flags)) {
+ blocked = rq_demote(gl);
+- if (gl->gl_waiters2 && !blocked) {
++ if (test_bit(GLF_WAITERS2, &gl->gl_flags) &&
++ !blocked) {
+ set_bit(GLF_DEMOTE, &gl->gl_flags);
+ gl->gl_demote_state = LM_ST_UNLOCKED;
+ }
+- gl->gl_waiters2 = 0;
++ clear_bit(GLF_WAITERS2, &gl->gl_flags);
+ } else if (!list_empty(&gl->gl_waiters3)) {
+ gh = list_entry(gl->gl_waiters3.next,
+ struct gfs2_holder, gh_list);
+@@ -710,7 +719,7 @@ static void handle_callback(struct gfs2_glock *gl, unsigned int state,
+ } else if (gl->gl_demote_state != LM_ST_UNLOCKED &&
+ gl->gl_demote_state != state) {
+ if (test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags))
+- gl->gl_waiters2 = 1;
++ set_bit(GLF_WAITERS2, &gl->gl_flags);
+ else
+ gl->gl_demote_state = LM_ST_UNLOCKED;
+ }
+@@ -743,6 +752,43 @@ static void state_change(struct gfs2_glock *gl, unsigned int new_state)
+ }
+
+ /**
++ * drop_bh - Called after a lock module unlock completes
++ * @gl: the glock
++ * @ret: the return status
++ *
++ * Doesn't wake up the process waiting on the struct gfs2_holder (if any)
++ * Doesn't drop the reference on the glock the top half took out
++ *
++ */
++
++static void drop_bh(struct gfs2_glock *gl, unsigned int ret)
++{
++ struct gfs2_sbd *sdp = gl->gl_sbd;
++ struct gfs2_holder *gh = gl->gl_req_gh;
++
++ gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
++ gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
++ gfs2_assert_warn(sdp, !ret);
++
++ state_change(gl, LM_ST_UNLOCKED);
++
++ if (test_and_clear_bit(GLF_CONV_DEADLK, &gl->gl_flags)) {
++ spin_lock(&gl->gl_spin);
++ gh->gh_error = 0;
++ spin_unlock(&gl->gl_spin);
++ gfs2_glock_xmote_th(gl, gl->gl_req_gh);
++ gfs2_glock_put(gl);
++ return;
++ }
++
++ spin_lock(&gl->gl_spin);
++ gfs2_demote_wake(gl);
++ clear_bit(GLF_LOCK, &gl->gl_flags);
++ spin_unlock(&gl->gl_spin);
++ gfs2_glock_put(gl);
++}
++
++/**
+ * xmote_bh - Called after the lock module is done acquiring a lock
+ * @gl: The glock in question
+ * @ret: the int returned from the lock module
+@@ -754,25 +800,19 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
+ struct gfs2_sbd *sdp = gl->gl_sbd;
+ const struct gfs2_glock_operations *glops = gl->gl_ops;
+ struct gfs2_holder *gh = gl->gl_req_gh;
+- int prev_state = gl->gl_state;
+ int op_done = 1;
+
++ if (!gh && (ret & LM_OUT_ST_MASK) == LM_ST_UNLOCKED) {
++ drop_bh(gl, ret);
++ return;
++ }
++
+ gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
+ gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
+ gfs2_assert_warn(sdp, !(ret & LM_OUT_ASYNC));
+
+ state_change(gl, ret & LM_OUT_ST_MASK);
+
+- if (prev_state != LM_ST_UNLOCKED && !(ret & LM_OUT_CACHEABLE)) {
+- if (glops->go_inval)
+- glops->go_inval(gl, DIO_METADATA);
+- } else if (gl->gl_state == LM_ST_DEFERRED) {
+- /* We might not want to do this here.
+- Look at moving to the inode glops. */
+- if (glops->go_inval)
+- glops->go_inval(gl, 0);
+- }
+-
+ /* Deal with each possible exit condition */
+
+ if (!gh) {
+@@ -782,7 +822,6 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
+ } else {
+ spin_lock(&gl->gl_spin);
+ if (gl->gl_state != gl->gl_demote_state) {
+- gl->gl_req_bh = NULL;
+ spin_unlock(&gl->gl_spin);
+ gfs2_glock_drop_th(gl);
+ gfs2_glock_put(gl);
+@@ -793,6 +832,14 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
+ }
+ } else {
+ spin_lock(&gl->gl_spin);
++ if (ret & LM_OUT_CONV_DEADLK) {
++ gh->gh_error = 0;
++ set_bit(GLF_CONV_DEADLK, &gl->gl_flags);
++ spin_unlock(&gl->gl_spin);
++ gfs2_glock_drop_th(gl);
++ gfs2_glock_put(gl);
++ return;
++ }
+ list_del_init(&gh->gh_list);
+ gh->gh_error = -EIO;
+ if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+@@ -824,7 +871,6 @@ out:
+ if (op_done) {
+ spin_lock(&gl->gl_spin);
+ gl->gl_req_gh = NULL;
+- gl->gl_req_bh = NULL;
+ clear_bit(GLF_LOCK, &gl->gl_flags);
+ spin_unlock(&gl->gl_spin);
+ }
+@@ -835,6 +881,17 @@ out:
+ gfs2_holder_wake(gh);
+ }
+
++static unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock,
++ unsigned int cur_state, unsigned int req_state,
++ unsigned int flags)
++{
++ int ret = 0;
++ if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++ ret = sdp->sd_lockstruct.ls_ops->lm_lock(lock, cur_state,
++ req_state, flags);
++ return ret;
++}
++
+ /**
+ * gfs2_glock_xmote_th - Call into the lock module to acquire or change a glock
+ * @gl: The glock in question
+@@ -856,6 +913,8 @@ static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh)
+
+ if (glops->go_xmote_th)
+ glops->go_xmote_th(gl);
++ if (state == LM_ST_DEFERRED && glops->go_inval)
++ glops->go_inval(gl, DIO_METADATA);
+
+ gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
+ gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
+@@ -863,7 +922,6 @@ static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh)
+ gfs2_assert_warn(sdp, state != gl->gl_state);
+
+ gfs2_glock_hold(gl);
+- gl->gl_req_bh = xmote_bh;
+
+ lck_ret = gfs2_lm_lock(sdp, gl->gl_lock, gl->gl_state, state, lck_flags);
+
+@@ -876,49 +934,13 @@ static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh)
+ xmote_bh(gl, lck_ret);
+ }
+
+-/**
+- * drop_bh - Called after a lock module unlock completes
+- * @gl: the glock
+- * @ret: the return status
+- *
+- * Doesn't wake up the process waiting on the struct gfs2_holder (if any)
+- * Doesn't drop the reference on the glock the top half took out
+- *
+- */
+-
+-static void drop_bh(struct gfs2_glock *gl, unsigned int ret)
++static unsigned int gfs2_lm_unlock(struct gfs2_sbd *sdp, void *lock,
++ unsigned int cur_state)
+ {
+- struct gfs2_sbd *sdp = gl->gl_sbd;
+- const struct gfs2_glock_operations *glops = gl->gl_ops;
+- struct gfs2_holder *gh = gl->gl_req_gh;
+-
+- gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
+- gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
+- gfs2_assert_warn(sdp, !ret);
+-
+- state_change(gl, LM_ST_UNLOCKED);
+-
+- if (glops->go_inval)
+- glops->go_inval(gl, DIO_METADATA);
+-
+- if (gh) {
+- spin_lock(&gl->gl_spin);
+- list_del_init(&gh->gh_list);
+- gh->gh_error = 0;
+- spin_unlock(&gl->gl_spin);
+- }
+-
+- spin_lock(&gl->gl_spin);
+- gfs2_demote_wake(gl);
+- gl->gl_req_gh = NULL;
+- gl->gl_req_bh = NULL;
+- clear_bit(GLF_LOCK, &gl->gl_flags);
+- spin_unlock(&gl->gl_spin);
+-
+- gfs2_glock_put(gl);
+-
+- if (gh)
+- gfs2_holder_wake(gh);
++ int ret = 0;
++ if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++ ret = sdp->sd_lockstruct.ls_ops->lm_unlock(lock, cur_state);
++ return ret;
+ }
+
+ /**
+@@ -935,13 +957,14 @@ static void gfs2_glock_drop_th(struct gfs2_glock *gl)
+
+ if (glops->go_xmote_th)
+ glops->go_xmote_th(gl);
++ if (glops->go_inval)
++ glops->go_inval(gl, DIO_METADATA);
+
+ gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
+ gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
+ gfs2_assert_warn(sdp, gl->gl_state != LM_ST_UNLOCKED);
+
+ gfs2_glock_hold(gl);
+- gl->gl_req_bh = drop_bh;
+
+ ret = gfs2_lm_unlock(sdp, gl->gl_lock, gl->gl_state);
+
+@@ -964,16 +987,17 @@ static void gfs2_glock_drop_th(struct gfs2_glock *gl)
+ static void do_cancels(struct gfs2_holder *gh)
+ {
+ struct gfs2_glock *gl = gh->gh_gl;
++ struct gfs2_sbd *sdp = gl->gl_sbd;
+
+ spin_lock(&gl->gl_spin);
+
+ while (gl->gl_req_gh != gh &&
+ !test_bit(HIF_HOLDER, &gh->gh_iflags) &&
+ !list_empty(&gh->gh_list)) {
+- if (gl->gl_req_bh && !(gl->gl_req_gh &&
+- (gl->gl_req_gh->gh_flags & GL_NOCANCEL))) {
++ if (!(gl->gl_req_gh && (gl->gl_req_gh->gh_flags & GL_NOCANCEL))) {
+ spin_unlock(&gl->gl_spin);
+- gfs2_lm_cancel(gl->gl_sbd, gl->gl_lock);
++ if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++ sdp->sd_lockstruct.ls_ops->lm_cancel(gl->gl_lock);
+ msleep(100);
+ spin_lock(&gl->gl_spin);
+ } else {
+@@ -1041,7 +1065,6 @@ static int glock_wait_internal(struct gfs2_holder *gh)
+
+ spin_lock(&gl->gl_spin);
+ gl->gl_req_gh = NULL;
+- gl->gl_req_bh = NULL;
+ clear_bit(GLF_LOCK, &gl->gl_flags);
+ run_queue(gl);
+ spin_unlock(&gl->gl_spin);
+@@ -1428,6 +1451,14 @@ void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs)
+ gfs2_glock_dq_uninit(&ghs[x]);
+ }
+
++static int gfs2_lm_hold_lvb(struct gfs2_sbd *sdp, void *lock, char **lvbp)
++{
++ int error = -EIO;
++ if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++ error = sdp->sd_lockstruct.ls_ops->lm_hold_lvb(lock, lvbp);
++ return error;
++}
++
+ /**
+ * gfs2_lvb_hold - attach a LVB from a glock
+ * @gl: The glock in question
+@@ -1463,12 +1494,15 @@ int gfs2_lvb_hold(struct gfs2_glock *gl)
+
+ void gfs2_lvb_unhold(struct gfs2_glock *gl)
+ {
++ struct gfs2_sbd *sdp = gl->gl_sbd;
++
+ gfs2_glock_hold(gl);
+ gfs2_glmutex_lock(gl);
+
+ gfs2_assert(gl->gl_sbd, atomic_read(&gl->gl_lvb_count) > 0);
+ if (atomic_dec_and_test(&gl->gl_lvb_count)) {
+- gfs2_lm_unhold_lvb(gl->gl_sbd, gl->gl_lock, gl->gl_lvb);
++ if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++ sdp->sd_lockstruct.ls_ops->lm_unhold_lvb(gl->gl_lock, gl->gl_lvb);
+ gl->gl_lvb = NULL;
+ gfs2_glock_put(gl);
+ }
+@@ -1534,8 +1568,7 @@ void gfs2_glock_cb(void *cb_data, unsigned int type, void *data)
+ gl = gfs2_glock_find(sdp, &async->lc_name);
+ if (gfs2_assert_warn(sdp, gl))
+ return;
+- if (!gfs2_assert_warn(sdp, gl->gl_req_bh))
+- gl->gl_req_bh(gl, async->lc_ret);
++ xmote_bh(gl, async->lc_ret);
+ if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
+ gfs2_glock_put(gl);
+ up_read(&gfs2_umount_flush_sem);
+@@ -1594,10 +1627,10 @@ void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl)
+ gfs2_glock_hold(gl);
+ list_add(&gl->gl_reclaim, &sdp->sd_reclaim_list);
+ atomic_inc(&sdp->sd_reclaim_count);
+- }
+- spin_unlock(&sdp->sd_reclaim_lock);
+-
+- wake_up(&sdp->sd_reclaim_wq);
++ spin_unlock(&sdp->sd_reclaim_lock);
++ wake_up(&sdp->sd_reclaim_wq);
++ } else
++ spin_unlock(&sdp->sd_reclaim_lock);
+ }
+
+ /**
+@@ -1897,7 +1930,6 @@ static int dump_glock(struct glock_iter *gi, struct gfs2_glock *gl)
+ print_dbg(gi, " gl_owner = -1\n");
+ print_dbg(gi, " gl_ip = %lu\n", gl->gl_ip);
+ print_dbg(gi, " req_gh = %s\n", (gl->gl_req_gh) ? "yes" : "no");
+- print_dbg(gi, " req_bh = %s\n", (gl->gl_req_bh) ? "yes" : "no");
+ print_dbg(gi, " lvb_count = %d\n", atomic_read(&gl->gl_lvb_count));
+ print_dbg(gi, " object = %s\n", (gl->gl_object) ? "yes" : "no");
+ print_dbg(gi, " reclaim = %s\n",
+diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
+index 2f9c6d1..cdad3e6 100644
+--- a/fs/gfs2/glock.h
++++ b/fs/gfs2/glock.h
+@@ -32,24 +32,23 @@
+ #define GLR_TRYFAILED 13
+ #define GLR_CANCELED 14
+
+-static inline int gfs2_glock_is_locked_by_me(struct gfs2_glock *gl)
++static inline struct gfs2_holder *gfs2_glock_is_locked_by_me(struct gfs2_glock *gl)
+ {
+ struct gfs2_holder *gh;
+- int locked = 0;
+ struct pid *pid;
+
+ /* Look in glock's list of holders for one with current task as owner */
+ spin_lock(&gl->gl_spin);
+ pid = task_pid(current);
+ list_for_each_entry(gh, &gl->gl_holders, gh_list) {
+- if (gh->gh_owner_pid == pid) {
+- locked = 1;
+- break;
+- }
++ if (gh->gh_owner_pid == pid)
++ goto out;
+ }
++ gh = NULL;
++out:
+ spin_unlock(&gl->gl_spin);
+
+- return locked;
++ return gh;
+ }
+
+ static inline int gfs2_glock_is_held_excl(struct gfs2_glock *gl)
+@@ -79,7 +78,6 @@ static inline int gfs2_glock_is_blocking(struct gfs2_glock *gl)
+ int gfs2_glock_get(struct gfs2_sbd *sdp,
+ u64 number, const struct gfs2_glock_operations *glops,
+ int create, struct gfs2_glock **glp);
+-void gfs2_glock_hold(struct gfs2_glock *gl);
+ int gfs2_glock_put(struct gfs2_glock *gl);
+ void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags,
+ struct gfs2_holder *gh);
+diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
+index c663b7a..d31bada 100644
+--- a/fs/gfs2/glops.c
++++ b/fs/gfs2/glops.c
+@@ -1,6 +1,6 @@
+ /*
+ * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
+- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
++ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+@@ -126,7 +126,13 @@ static void meta_go_inval(struct gfs2_glock *gl, int flags)
+ return;
+
+ gfs2_meta_inval(gl);
+- gl->gl_vn++;
++ if (gl->gl_object == GFS2_I(gl->gl_sbd->sd_rindex))
++ gl->gl_sbd->sd_rindex_uptodate = 0;
++ else if (gl->gl_ops == &gfs2_rgrp_glops && gl->gl_object) {
++ struct gfs2_rgrpd *rgd = (struct gfs2_rgrpd *)gl->gl_object;
++
++ rgd->rd_flags &= ~GFS2_RDF_UPTODATE;
++ }
+ }
+
+ /**
+diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
+index 525dcae..9c2c0b9 100644
+--- a/fs/gfs2/incore.h
++++ b/fs/gfs2/incore.h
+@@ -1,6 +1,6 @@
+ /*
+ * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
+- * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
++ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+@@ -44,7 +44,6 @@ struct gfs2_log_header_host {
+
+ struct gfs2_log_operations {
+ void (*lo_add) (struct gfs2_sbd *sdp, struct gfs2_log_element *le);
+- void (*lo_incore_commit) (struct gfs2_sbd *sdp, struct gfs2_trans *tr);
+ void (*lo_before_commit) (struct gfs2_sbd *sdp);
+ void (*lo_after_commit) (struct gfs2_sbd *sdp, struct gfs2_ail *ai);
+ void (*lo_before_scan) (struct gfs2_jdesc *jd,
+@@ -70,7 +69,6 @@ struct gfs2_bitmap {
+ };
+
+ struct gfs2_rgrp_host {
+- u32 rg_flags;
+ u32 rg_free;
+ u32 rg_dinodes;
+ u64 rg_igeneration;
+@@ -87,17 +85,17 @@ struct gfs2_rgrpd {
+ u32 rd_data; /* num of data blocks in rgrp */
+ u32 rd_bitbytes; /* number of bytes in data bitmaps */
+ struct gfs2_rgrp_host rd_rg;
+- u64 rd_rg_vn;
+ struct gfs2_bitmap *rd_bits;
+ unsigned int rd_bh_count;
+ struct mutex rd_mutex;
+ u32 rd_free_clone;
+ struct gfs2_log_element rd_le;
+- u32 rd_last_alloc_data;
+- u32 rd_last_alloc_meta;
++ u32 rd_last_alloc;
+ struct gfs2_sbd *rd_sbd;
+- unsigned long rd_flags;
+-#define GFS2_RDF_CHECK 0x0001 /* Need to check for unlinked inodes */
++ unsigned char rd_flags;
++#define GFS2_RDF_CHECK 0x01 /* Need to check for unlinked inodes */
++#define GFS2_RDF_NOALLOC 0x02 /* rg prohibits allocation */
++#define GFS2_RDF_UPTODATE 0x04 /* rg is up to date */
+ };
+
+ enum gfs2_state_bits {
+@@ -168,6 +166,8 @@ enum {
+ GLF_DIRTY = 5,
+ GLF_DEMOTE_IN_PROGRESS = 6,
+ GLF_LFLUSH = 7,
++ GLF_WAITERS2 = 8,
++ GLF_CONV_DEADLK = 9,
+ };
+
+ struct gfs2_glock {
+@@ -187,18 +187,15 @@ struct gfs2_glock {
+ struct list_head gl_holders;
+ struct list_head gl_waiters1; /* HIF_MUTEX */
+ struct list_head gl_waiters3; /* HIF_PROMOTE */
+- int gl_waiters2; /* GIF_DEMOTE */
+
+ const struct gfs2_glock_operations *gl_ops;
+
+ struct gfs2_holder *gl_req_gh;
+- gfs2_glop_bh_t gl_req_bh;
+
+ void *gl_lock;
+ char *gl_lvb;
+ atomic_t gl_lvb_count;
+
+- u64 gl_vn;
+ unsigned long gl_stamp;
+ unsigned long gl_tchange;
+ void *gl_object;
+@@ -213,6 +210,8 @@ struct gfs2_glock {
+ struct delayed_work gl_work;
+ };
+
++#define GFS2_MIN_LVB_SIZE 32 /* Min size of LVB that gfs2 supports */
++
+ struct gfs2_alloc {
+ /* Quota stuff */
+
+@@ -241,14 +240,9 @@ enum {
+
+ struct gfs2_dinode_host {
+ u64 di_size; /* number of bytes in file */
+- u64 di_blocks; /* number of blocks in file */
+- u64 di_goal_meta; /* rgrp to alloc from next */
+- u64 di_goal_data; /* data block goal */
+ u64 di_generation; /* generation number for NFS */
+ u32 di_flags; /* GFS2_DIF_... */
+- u16 di_height; /* height of metadata */
+ /* These only apply to directories */
+- u16 di_depth; /* Number of bits in the table */
+ u32 di_entries; /* The number of entries in the directory */
+ u64 di_eattr; /* extended attribute block number */
+ };
+@@ -265,9 +259,10 @@ struct gfs2_inode {
+ struct gfs2_holder i_iopen_gh;
+ struct gfs2_holder i_gh; /* for prepare/commit_write only */
+ struct gfs2_alloc *i_alloc;
+- u64 i_last_rg_alloc;
+-
++ u64 i_goal; /* goal block for allocations */
+ struct rw_semaphore i_rw_mutex;
++ u8 i_height;
++ u8 i_depth;
+ };
+
+ /*
+@@ -490,9 +485,9 @@ struct gfs2_sbd {
+ u32 sd_qc_per_block;
+ u32 sd_max_dirres; /* Max blocks needed to add a directory entry */
+ u32 sd_max_height; /* Max height of a file's metadata tree */
+- u64 sd_heightsize[GFS2_MAX_META_HEIGHT];
++ u64 sd_heightsize[GFS2_MAX_META_HEIGHT + 1];
+ u32 sd_max_jheight; /* Max height of journaled file's meta tree */
+- u64 sd_jheightsize[GFS2_MAX_META_HEIGHT];
++ u64 sd_jheightsize[GFS2_MAX_META_HEIGHT + 1];
+
+ struct gfs2_args sd_args; /* Mount arguments */
+ struct gfs2_tune sd_tune; /* Filesystem tuning structure */
+@@ -533,7 +528,7 @@ struct gfs2_sbd {
+
+ /* Resource group stuff */
+
+- u64 sd_rindex_vn;
++ int sd_rindex_uptodate;
+ spinlock_t sd_rindex_spin;
+ struct mutex sd_rindex_mutex;
+ struct list_head sd_rindex_list;
+@@ -637,9 +632,6 @@ struct gfs2_sbd {
+
+ /* Counters */
+
+- atomic_t sd_glock_count;
+- atomic_t sd_glock_held_count;
+- atomic_t sd_inode_count;
+ atomic_t sd_reclaimed;
+
+ char sd_fsname[GFS2_FSNAME_LEN];
+diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
+index 37725ad..3a9ef52 100644
+--- a/fs/gfs2/inode.c
++++ b/fs/gfs2/inode.c
+@@ -1,6 +1,6 @@
+ /*
+ * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
+- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
++ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+@@ -149,7 +149,8 @@ void gfs2_set_iop(struct inode *inode)
+ } else if (S_ISLNK(mode)) {
+ inode->i_op = &gfs2_symlink_iops;
+ } else {
+- inode->i_op = &gfs2_dev_iops;
++ inode->i_op = &gfs2_file_iops;
++ init_special_inode(inode, inode->i_mode, inode->i_rdev);
+ }
+
+ unlock_new_inode(inode);
+@@ -248,12 +249,10 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
+ {
+ struct gfs2_dinode_host *di = &ip->i_di;
+ const struct gfs2_dinode *str = buf;
++ u16 height, depth;
+
+- if (ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)) {
+- if (gfs2_consist_inode(ip))
+- gfs2_dinode_print(ip);
+- return -EIO;
+- }
++ if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)))
++ goto corrupt;
+ ip->i_no_formal_ino = be64_to_cpu(str->di_num.no_formal_ino);
+ ip->i_inode.i_mode = be32_to_cpu(str->di_mode);
+ ip->i_inode.i_rdev = 0;
+@@ -275,8 +274,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
+ ip->i_inode.i_nlink = be32_to_cpu(str->di_nlink);
+ di->di_size = be64_to_cpu(str->di_size);
+ i_size_write(&ip->i_inode, di->di_size);
+- di->di_blocks = be64_to_cpu(str->di_blocks);
+- gfs2_set_inode_blocks(&ip->i_inode);
++ gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks));
+ ip->i_inode.i_atime.tv_sec = be64_to_cpu(str->di_atime);
+ ip->i_inode.i_atime.tv_nsec = be32_to_cpu(str->di_atime_nsec);
+ ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime);
+@@ -284,15 +282,20 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
+ ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime);
+ ip->i_inode.i_ctime.tv_nsec = be32_to_cpu(str->di_ctime_nsec);
+
+- di->di_goal_meta = be64_to_cpu(str->di_goal_meta);
+- di->di_goal_data = be64_to_cpu(str->di_goal_data);
++ ip->i_goal = be64_to_cpu(str->di_goal_meta);
+ di->di_generation = be64_to_cpu(str->di_generation);
+
+ di->di_flags = be32_to_cpu(str->di_flags);
+ gfs2_set_inode_flags(&ip->i_inode);
+- di->di_height = be16_to_cpu(str->di_height);
+-
+- di->di_depth = be16_to_cpu(str->di_depth);
++ height = be16_to_cpu(str->di_height);
++ if (unlikely(height > GFS2_MAX_META_HEIGHT))
++ goto corrupt;
++ ip->i_height = (u8)height;
++
++ depth = be16_to_cpu(str->di_depth);
++ if (unlikely(depth > GFS2_DIR_MAX_DEPTH))
++ goto corrupt;
++ ip->i_depth = (u8)depth;
+ di->di_entries = be32_to_cpu(str->di_entries);
+
+ di->di_eattr = be64_to_cpu(str->di_eattr);
+@@ -300,6 +303,10 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
+ gfs2_set_aops(&ip->i_inode);
+
+ return 0;
++corrupt:
++ if (gfs2_consist_inode(ip))
++ gfs2_dinode_print(ip);
++ return -EIO;
+ }
+
+ /**
+@@ -337,13 +344,15 @@ int gfs2_dinode_dealloc(struct gfs2_inode *ip)
+ struct gfs2_rgrpd *rgd;
+ int error;
+
+- if (ip->i_di.di_blocks != 1) {
++ if (gfs2_get_inode_blocks(&ip->i_inode) != 1) {
+ if (gfs2_consist_inode(ip))
+ gfs2_dinode_print(ip);
+ return -EIO;
+ }
+
+ al = gfs2_alloc_get(ip);
++ if (!al)
++ return -ENOMEM;
+
+ error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
+ if (error)
+@@ -487,7 +496,7 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
+ return dir;
+ }
+
+- if (gfs2_glock_is_locked_by_me(dip->i_gl) == 0) {
++ if (gfs2_glock_is_locked_by_me(dip->i_gl) == NULL) {
+ error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
+ if (error)
+ return ERR_PTR(error);
+@@ -818,7 +827,8 @@ static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
+ int error;
+
+ munge_mode_uid_gid(dip, &mode, &uid, &gid);
+- gfs2_alloc_get(dip);
++ if (!gfs2_alloc_get(dip))
++ return -ENOMEM;
+
+ error = gfs2_quota_lock(dip, uid, gid);
+ if (error)
+@@ -853,6 +863,8 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
+ int error;
+
+ al = gfs2_alloc_get(dip);
++ if (!al)
++ return -ENOMEM;
+
+ error = gfs2_quota_lock(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
+ if (error)
+@@ -1219,7 +1231,7 @@ int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len)
+
+ x = ip->i_di.di_size + 1;
+ if (x > *len) {
+- *buf = kmalloc(x, GFP_KERNEL);
++ *buf = kmalloc(x, GFP_NOFS);
+ if (!*buf) {
+ error = -ENOMEM;
+ goto out_brelse;
+@@ -1391,21 +1403,21 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
+ str->di_gid = cpu_to_be32(ip->i_inode.i_gid);
+ str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink);
+ str->di_size = cpu_to_be64(di->di_size);
+- str->di_blocks = cpu_to_be64(di->di_blocks);
++ str->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode));
+ str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
+ str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec);
+ str->di_ctime = cpu_to_be64(ip->i_inode.i_ctime.tv_sec);
+
+- str->di_goal_meta = cpu_to_be64(di->di_goal_meta);
+- str->di_goal_data = cpu_to_be64(di->di_goal_data);
++ str->di_goal_meta = cpu_to_be64(ip->i_goal);
++ str->di_goal_data = cpu_to_be64(ip->i_goal);
+ str->di_generation = cpu_to_be64(di->di_generation);
+
+ str->di_flags = cpu_to_be32(di->di_flags);
+- str->di_height = cpu_to_be16(di->di_height);
++ str->di_height = cpu_to_be16(ip->i_height);
+ str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) &&
+ !(ip->i_di.di_flags & GFS2_DIF_EXHASH) ?
+ GFS2_FORMAT_DE : 0);
+- str->di_depth = cpu_to_be16(di->di_depth);
++ str->di_depth = cpu_to_be16(ip->i_depth);
+ str->di_entries = cpu_to_be32(di->di_entries);
+
+ str->di_eattr = cpu_to_be64(di->di_eattr);
+@@ -1423,15 +1435,13 @@ void gfs2_dinode_print(const struct gfs2_inode *ip)
+ printk(KERN_INFO " no_addr = %llu\n",
+ (unsigned long long)ip->i_no_addr);
+ printk(KERN_INFO " di_size = %llu\n", (unsigned long long)di->di_size);
+- printk(KERN_INFO " di_blocks = %llu\n",
+- (unsigned long long)di->di_blocks);
+- printk(KERN_INFO " di_goal_meta = %llu\n",
+- (unsigned long long)di->di_goal_meta);
+- printk(KERN_INFO " di_goal_data = %llu\n",
+- (unsigned long long)di->di_goal_data);
++ printk(KERN_INFO " blocks = %llu\n",
++ (unsigned long long)gfs2_get_inode_blocks(&ip->i_inode));
++ printk(KERN_INFO " i_goal = %llu\n",
++ (unsigned long long)ip->i_goal);
+ printk(KERN_INFO " di_flags = 0x%.8X\n", di->di_flags);
+- printk(KERN_INFO " di_height = %u\n", di->di_height);
+- printk(KERN_INFO " di_depth = %u\n", di->di_depth);
++ printk(KERN_INFO " i_height = %u\n", ip->i_height);
++ printk(KERN_INFO " i_depth = %u\n", ip->i_depth);
+ printk(KERN_INFO " di_entries = %u\n", di->di_entries);
+ printk(KERN_INFO " di_eattr = %llu\n",
+ (unsigned long long)di->di_eattr);
+diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h
+index d446506..580da45 100644
+--- a/fs/gfs2/inode.h
++++ b/fs/gfs2/inode.h
+@@ -10,9 +10,11 @@
+ #ifndef __INODE_DOT_H__
+ #define __INODE_DOT_H__
+
++#include "util.h"
++
+ static inline int gfs2_is_stuffed(const struct gfs2_inode *ip)
+ {
+- return !ip->i_di.di_height;
++ return !ip->i_height;
+ }
+
+ static inline int gfs2_is_jdata(const struct gfs2_inode *ip)
+@@ -37,13 +39,25 @@ static inline int gfs2_is_dir(const struct gfs2_inode *ip)
+ return S_ISDIR(ip->i_inode.i_mode);
+ }
+
+-static inline void gfs2_set_inode_blocks(struct inode *inode)
++static inline void gfs2_set_inode_blocks(struct inode *inode, u64 blocks)
++{
++ inode->i_blocks = blocks <<
++ (GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT);
++}
++
++static inline u64 gfs2_get_inode_blocks(const struct inode *inode)
+ {
+- struct gfs2_inode *ip = GFS2_I(inode);
+- inode->i_blocks = ip->i_di.di_blocks <<
++ return inode->i_blocks >>
+ (GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT);
+ }
+
++static inline void gfs2_add_inode_blocks(struct inode *inode, s64 change)
++{
++ gfs2_assert(GFS2_SB(inode), (change >= 0 || inode->i_blocks > -change));
++ change *= (GFS2_SB(inode)->sd_sb.sb_bsize/GFS2_BASIC_BLOCK);
++ inode->i_blocks += change;
++}
++
+ static inline int gfs2_check_inum(const struct gfs2_inode *ip, u64 no_addr,
+ u64 no_formal_ino)
+ {
+diff --git a/fs/gfs2/lm.c b/fs/gfs2/lm.c
+deleted file mode 100644
+index cfcc39b..0000000
+--- a/fs/gfs2/lm.c
++++ /dev/null
+@@ -1,210 +0,0 @@
+-/*
+- * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
+- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+- *
+- * This copyrighted material is made available to anyone wishing to use,
+- * modify, copy, or redistribute it subject to the terms and conditions
+- * of the GNU General Public License version 2.
+- */
+-
+-#include <linux/slab.h>
+-#include <linux/spinlock.h>
+-#include <linux/completion.h>
+-#include <linux/buffer_head.h>
+-#include <linux/delay.h>
+-#include <linux/gfs2_ondisk.h>
+-#include <linux/lm_interface.h>
+-
+-#include "gfs2.h"
+-#include "incore.h"
+-#include "glock.h"
+-#include "lm.h"
+-#include "super.h"
+-#include "util.h"
+-
+-/**
+- * gfs2_lm_mount - mount a locking protocol
+- * @sdp: the filesystem
+- * @args: mount arguements
+- * @silent: if 1, don't complain if the FS isn't a GFS2 fs
+- *
+- * Returns: errno
+- */
+-
+-int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent)
+-{
+- char *proto = sdp->sd_proto_name;
+- char *table = sdp->sd_table_name;
+- int flags = 0;
+- int error;
+-
+- if (sdp->sd_args.ar_spectator)
+- flags |= LM_MFLAG_SPECTATOR;
+-
+- fs_info(sdp, "Trying to join cluster \"%s\", \"%s\"\n", proto, table);
+-
+- error = gfs2_mount_lockproto(proto, table, sdp->sd_args.ar_hostdata,
+- gfs2_glock_cb, sdp,
+- GFS2_MIN_LVB_SIZE, flags,
+- &sdp->sd_lockstruct, &sdp->sd_kobj);
+- if (error) {
+- fs_info(sdp, "can't mount proto=%s, table=%s, hostdata=%s\n",
+- proto, table, sdp->sd_args.ar_hostdata);
+- goto out;
+- }
+-
+- if (gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_lockspace) ||
+- gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_ops) ||
+- gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_lvb_size >=
+- GFS2_MIN_LVB_SIZE)) {
+- gfs2_unmount_lockproto(&sdp->sd_lockstruct);
+- goto out;
+- }
+-
+- if (sdp->sd_args.ar_spectator)
+- snprintf(sdp->sd_fsname, GFS2_FSNAME_LEN, "%s.s", table);
+- else
+- snprintf(sdp->sd_fsname, GFS2_FSNAME_LEN, "%s.%u", table,
+- sdp->sd_lockstruct.ls_jid);
+-
+- fs_info(sdp, "Joined cluster. Now mounting FS...\n");
+-
+- if ((sdp->sd_lockstruct.ls_flags & LM_LSFLAG_LOCAL) &&
+- !sdp->sd_args.ar_ignore_local_fs) {
+- sdp->sd_args.ar_localflocks = 1;
+- sdp->sd_args.ar_localcaching = 1;
+- }
+-
+-out:
+- return error;
+-}
+-
+-void gfs2_lm_others_may_mount(struct gfs2_sbd *sdp)
+-{
+- if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+- sdp->sd_lockstruct.ls_ops->lm_others_may_mount(
+- sdp->sd_lockstruct.ls_lockspace);
+-}
+-
+-void gfs2_lm_unmount(struct gfs2_sbd *sdp)
+-{
+- if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+- gfs2_unmount_lockproto(&sdp->sd_lockstruct);
+-}
+-
+-int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...)
+-{
+- va_list args;
+-
+- if (test_and_set_bit(SDF_SHUTDOWN, &sdp->sd_flags))
+- return 0;
+-
+- va_start(args, fmt);
+- vprintk(fmt, args);
+- va_end(args);
+-
+- fs_err(sdp, "about to withdraw this file system\n");
+- BUG_ON(sdp->sd_args.ar_debug);
+-
+- fs_err(sdp, "telling LM to withdraw\n");
+- gfs2_withdraw_lockproto(&sdp->sd_lockstruct);
+- fs_err(sdp, "withdrawn\n");
+- dump_stack();
+-
+- return -1;
+-}
+-
+-int gfs2_lm_get_lock(struct gfs2_sbd *sdp, struct lm_lockname *name,
+- void **lockp)
+-{
+- int error = -EIO;
+- if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+- error = sdp->sd_lockstruct.ls_ops->lm_get_lock(
+- sdp->sd_lockstruct.ls_lockspace, name, lockp);
+- return error;
+-}
+-
+-void gfs2_lm_put_lock(struct gfs2_sbd *sdp, void *lock)
+-{
+- if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+- sdp->sd_lockstruct.ls_ops->lm_put_lock(lock);
+-}
+-
+-unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock,
+- unsigned int cur_state, unsigned int req_state,
+- unsigned int flags)
+-{
+- int ret = 0;
+- if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+- ret = sdp->sd_lockstruct.ls_ops->lm_lock(lock, cur_state,
+- req_state, flags);
+- return ret;
+-}
+-
+-unsigned int gfs2_lm_unlock(struct gfs2_sbd *sdp, void *lock,
+- unsigned int cur_state)
+-{
+- int ret = 0;
+- if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+- ret = sdp->sd_lockstruct.ls_ops->lm_unlock(lock, cur_state);
+- return ret;
+-}
+-
+-void gfs2_lm_cancel(struct gfs2_sbd *sdp, void *lock)
+-{
+- if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+- sdp->sd_lockstruct.ls_ops->lm_cancel(lock);
+-}
+-
+-int gfs2_lm_hold_lvb(struct gfs2_sbd *sdp, void *lock, char **lvbp)
+-{
+- int error = -EIO;
+- if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+- error = sdp->sd_lockstruct.ls_ops->lm_hold_lvb(lock, lvbp);
+- return error;
+-}
+-
+-void gfs2_lm_unhold_lvb(struct gfs2_sbd *sdp, void *lock, char *lvb)
+-{
+- if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+- sdp->sd_lockstruct.ls_ops->lm_unhold_lvb(lock, lvb);
+-}
+-
+-int gfs2_lm_plock_get(struct gfs2_sbd *sdp, struct lm_lockname *name,
+- struct file *file, struct file_lock *fl)
+-{
+- int error = -EIO;
+- if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+- error = sdp->sd_lockstruct.ls_ops->lm_plock_get(
+- sdp->sd_lockstruct.ls_lockspace, name, file, fl);
+- return error;
+-}
+-
+-int gfs2_lm_plock(struct gfs2_sbd *sdp, struct lm_lockname *name,
+- struct file *file, int cmd, struct file_lock *fl)
+-{
+- int error = -EIO;
+- if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+- error = sdp->sd_lockstruct.ls_ops->lm_plock(
+- sdp->sd_lockstruct.ls_lockspace, name, file, cmd, fl);
+- return error;
+-}
+-
+-int gfs2_lm_punlock(struct gfs2_sbd *sdp, struct lm_lockname *name,
+- struct file *file, struct file_lock *fl)
+-{
+- int error = -EIO;
+- if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+- error = sdp->sd_lockstruct.ls_ops->lm_punlock(
+- sdp->sd_lockstruct.ls_lockspace, name, file, fl);
+- return error;
+-}
+-
+-void gfs2_lm_recovery_done(struct gfs2_sbd *sdp, unsigned int jid,
+- unsigned int message)
+-{
+- if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+- sdp->sd_lockstruct.ls_ops->lm_recovery_done(
+- sdp->sd_lockstruct.ls_lockspace, jid, message);
+-}
+-
+diff --git a/fs/gfs2/lm.h b/fs/gfs2/lm.h
+deleted file mode 100644
+index 21cdc30..0000000
+--- a/fs/gfs2/lm.h
++++ /dev/null
+@@ -1,42 +0,0 @@
+-/*
+- * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
+- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+- *
+- * This copyrighted material is made available to anyone wishing to use,
+- * modify, copy, or redistribute it subject to the terms and conditions
+- * of the GNU General Public License version 2.
+- */
+-
+-#ifndef __LM_DOT_H__
+-#define __LM_DOT_H__
+-
+-struct gfs2_sbd;
+-
+-#define GFS2_MIN_LVB_SIZE 32
+-
+-int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent);
+-void gfs2_lm_others_may_mount(struct gfs2_sbd *sdp);
+-void gfs2_lm_unmount(struct gfs2_sbd *sdp);
+-int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...)
+- __attribute__ ((format(printf, 2, 3)));
+-int gfs2_lm_get_lock(struct gfs2_sbd *sdp, struct lm_lockname *name,
+- void **lockp);
+-void gfs2_lm_put_lock(struct gfs2_sbd *sdp, void *lock);
+-unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock,
+- unsigned int cur_state, unsigned int req_state,
+- unsigned int flags);
+-unsigned int gfs2_lm_unlock(struct gfs2_sbd *sdp, void *lock,
+- unsigned int cur_state);
+-void gfs2_lm_cancel(struct gfs2_sbd *sdp, void *lock);
+-int gfs2_lm_hold_lvb(struct gfs2_sbd *sdp, void *lock, char **lvbp);
+-void gfs2_lm_unhold_lvb(struct gfs2_sbd *sdp, void *lock, char *lvb);
+-int gfs2_lm_plock_get(struct gfs2_sbd *sdp, struct lm_lockname *name,
+- struct file *file, struct file_lock *fl);
+-int gfs2_lm_plock(struct gfs2_sbd *sdp, struct lm_lockname *name,
+- struct file *file, int cmd, struct file_lock *fl);
+-int gfs2_lm_punlock(struct gfs2_sbd *sdp, struct lm_lockname *name,
+- struct file *file, struct file_lock *fl);
+-void gfs2_lm_recovery_done(struct gfs2_sbd *sdp, unsigned int jid,
+- unsigned int message);
+-
+-#endif /* __LM_DOT_H__ */
+diff --git a/fs/gfs2/locking/dlm/Makefile b/fs/gfs2/locking/dlm/Makefile
+index 89b93b6..2609bb6 100644
+--- a/fs/gfs2/locking/dlm/Makefile
++++ b/fs/gfs2/locking/dlm/Makefile
+@@ -1,3 +1,3 @@
+ obj-$(CONFIG_GFS2_FS_LOCKING_DLM) += lock_dlm.o
+-lock_dlm-y := lock.o main.o mount.o sysfs.o thread.o plock.o
++lock_dlm-y := lock.o main.o mount.o sysfs.o thread.o
+
+diff --git a/fs/gfs2/locking/dlm/lock.c b/fs/gfs2/locking/dlm/lock.c
+index 542a797..cf7ea8a 100644
+--- a/fs/gfs2/locking/dlm/lock.c
++++ b/fs/gfs2/locking/dlm/lock.c
+@@ -137,7 +137,8 @@ static inline unsigned int make_flags(struct gdlm_lock *lp,
+
+ /* Conversion deadlock avoidance by DLM */
+
+- if (!test_bit(LFL_FORCE_PROMOTE, &lp->flags) &&
++ if (!(lp->ls->fsflags & LM_MFLAG_CONV_NODROP) &&
++ !test_bit(LFL_FORCE_PROMOTE, &lp->flags) &&
+ !(lkf & DLM_LKF_NOQUEUE) &&
+ cur > DLM_LOCK_NL && req > DLM_LOCK_NL && cur != req)
+ lkf |= DLM_LKF_CONVDEADLK;
+@@ -164,7 +165,7 @@ static int gdlm_create_lp(struct gdlm_ls *ls, struct lm_lockname *name,
+ {
+ struct gdlm_lock *lp;
+
+- lp = kzalloc(sizeof(struct gdlm_lock), GFP_KERNEL);
++ lp = kzalloc(sizeof(struct gdlm_lock), GFP_NOFS);
+ if (!lp)
+ return -ENOMEM;
+
+@@ -382,7 +383,7 @@ static int gdlm_add_lvb(struct gdlm_lock *lp)
+ {
+ char *lvb;
+
+- lvb = kzalloc(GDLM_LVB_SIZE, GFP_KERNEL);
++ lvb = kzalloc(GDLM_LVB_SIZE, GFP_NOFS);
+ if (!lvb)
+ return -ENOMEM;
+
+diff --git a/fs/gfs2/locking/dlm/lock_dlm.h b/fs/gfs2/locking/dlm/lock_dlm.h
+index 9e8265d..a243cf6 100644
+--- a/fs/gfs2/locking/dlm/lock_dlm.h
++++ b/fs/gfs2/locking/dlm/lock_dlm.h
+@@ -25,6 +25,7 @@
+ #include <net/sock.h>
+
+ #include <linux/dlm.h>
++#include <linux/dlm_plock.h>
+ #include <linux/lm_interface.h>
+
+ /*
+@@ -173,15 +174,9 @@ void gdlm_cancel(void *);
+ int gdlm_hold_lvb(void *, char **);
+ void gdlm_unhold_lvb(void *, char *);
+
+-/* plock.c */
++/* mount.c */
++
++extern const struct lm_lockops gdlm_ops;
+
+-int gdlm_plock_init(void);
+-void gdlm_plock_exit(void);
+-int gdlm_plock(void *, struct lm_lockname *, struct file *, int,
+- struct file_lock *);
+-int gdlm_plock_get(void *, struct lm_lockname *, struct file *,
+- struct file_lock *);
+-int gdlm_punlock(void *, struct lm_lockname *, struct file *,
+- struct file_lock *);
+ #endif
+
+diff --git a/fs/gfs2/locking/dlm/main.c b/fs/gfs2/locking/dlm/main.c
+index a0e7eda..b9a03a7 100644
+--- a/fs/gfs2/locking/dlm/main.c
++++ b/fs/gfs2/locking/dlm/main.c
+@@ -11,8 +11,6 @@
+
+ #include "lock_dlm.h"
+
+-extern struct lm_lockops gdlm_ops;
+-
+ static int __init init_lock_dlm(void)
+ {
+ int error;
+@@ -30,13 +28,6 @@ static int __init init_lock_dlm(void)
+ return error;
+ }
+
+- error = gdlm_plock_init();
+- if (error) {
+- gdlm_sysfs_exit();
+- gfs2_unregister_lockproto(&gdlm_ops);
+- return error;
+- }
+-
+ printk(KERN_INFO
+ "Lock_DLM (built %s %s) installed\n", __DATE__, __TIME__);
+ return 0;
+@@ -44,7 +35,6 @@ static int __init init_lock_dlm(void)
+
+ static void __exit exit_lock_dlm(void)
+ {
+- gdlm_plock_exit();
+ gdlm_sysfs_exit();
+ gfs2_unregister_lockproto(&gdlm_ops);
+ }
+diff --git a/fs/gfs2/locking/dlm/mount.c b/fs/gfs2/locking/dlm/mount.c
+index f2efff4..470bdf6 100644
+--- a/fs/gfs2/locking/dlm/mount.c
++++ b/fs/gfs2/locking/dlm/mount.c
+@@ -236,6 +236,27 @@ static void gdlm_withdraw(void *lockspace)
+ gdlm_kobject_release(ls);
+ }
+
++static int gdlm_plock(void *lockspace, struct lm_lockname *name,
++ struct file *file, int cmd, struct file_lock *fl)
++{
++ struct gdlm_ls *ls = lockspace;
++ return dlm_posix_lock(ls->dlm_lockspace, name->ln_number, file, cmd, fl);
++}
++
++static int gdlm_punlock(void *lockspace, struct lm_lockname *name,
++ struct file *file, struct file_lock *fl)
++{
++ struct gdlm_ls *ls = lockspace;
++ return dlm_posix_unlock(ls->dlm_lockspace, name->ln_number, file, fl);
++}
++
++static int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
++ struct file *file, struct file_lock *fl)
++{
++ struct gdlm_ls *ls = lockspace;
++ return dlm_posix_get(ls->dlm_lockspace, name->ln_number, file, fl);
++}
++
+ const struct lm_lockops gdlm_ops = {
+ .lm_proto_name = "lock_dlm",
+ .lm_mount = gdlm_mount,
+diff --git a/fs/gfs2/locking/dlm/plock.c b/fs/gfs2/locking/dlm/plock.c
+deleted file mode 100644
+index 2ebd374..0000000
+--- a/fs/gfs2/locking/dlm/plock.c
++++ /dev/null
+@@ -1,406 +0,0 @@
+-/*
+- * Copyright (C) 2005 Red Hat, Inc. All rights reserved.
+- *
+- * This copyrighted material is made available to anyone wishing to use,
+- * modify, copy, or redistribute it subject to the terms and conditions
+- * of the GNU General Public License version 2.
+- */
+-
+-#include <linux/miscdevice.h>
+-#include <linux/lock_dlm_plock.h>
+-#include <linux/poll.h>
+-
+-#include "lock_dlm.h"
+-
+-
+-static spinlock_t ops_lock;
+-static struct list_head send_list;
+-static struct list_head recv_list;
+-static wait_queue_head_t send_wq;
+-static wait_queue_head_t recv_wq;
+-
+-struct plock_op {
+- struct list_head list;
+- int done;
+- struct gdlm_plock_info info;
+-};
+-
+-struct plock_xop {
+- struct plock_op xop;
+- void *callback;
+- void *fl;
+- void *file;
+- struct file_lock flc;
+-};
+-
+-
+-static inline void set_version(struct gdlm_plock_info *info)
+-{
+- info->version[0] = GDLM_PLOCK_VERSION_MAJOR;
+- info->version[1] = GDLM_PLOCK_VERSION_MINOR;
+- info->version[2] = GDLM_PLOCK_VERSION_PATCH;
+-}
+-
+-static int check_version(struct gdlm_plock_info *info)
+-{
+- if ((GDLM_PLOCK_VERSION_MAJOR != info->version[0]) ||
+- (GDLM_PLOCK_VERSION_MINOR < info->version[1])) {
+- log_error("plock device version mismatch: "
+- "kernel (%u.%u.%u), user (%u.%u.%u)",
+- GDLM_PLOCK_VERSION_MAJOR,
+- GDLM_PLOCK_VERSION_MINOR,
+- GDLM_PLOCK_VERSION_PATCH,
+- info->version[0],
+- info->version[1],
+- info->version[2]);
+- return -EINVAL;
+- }
+- return 0;
+-}
+-
+-static void send_op(struct plock_op *op)
+-{
+- set_version(&op->info);
+- INIT_LIST_HEAD(&op->list);
+- spin_lock(&ops_lock);
+- list_add_tail(&op->list, &send_list);
+- spin_unlock(&ops_lock);
+- wake_up(&send_wq);
+-}
+-
+-int gdlm_plock(void *lockspace, struct lm_lockname *name,
+- struct file *file, int cmd, struct file_lock *fl)
+-{
+- struct gdlm_ls *ls = lockspace;
+- struct plock_op *op;
+- struct plock_xop *xop;
+- int rv;
+-
+- xop = kzalloc(sizeof(*xop), GFP_KERNEL);
+- if (!xop)
+- return -ENOMEM;
+-
+- op = &xop->xop;
+- op->info.optype = GDLM_PLOCK_OP_LOCK;
+- op->info.pid = fl->fl_pid;
+- op->info.ex = (fl->fl_type == F_WRLCK);
+- op->info.wait = IS_SETLKW(cmd);
+- op->info.fsid = ls->id;
+- op->info.number = name->ln_number;
+- op->info.start = fl->fl_start;
+- op->info.end = fl->fl_end;
+- if (fl->fl_lmops && fl->fl_lmops->fl_grant) {
+- /* fl_owner is lockd which doesn't distinguish
+- processes on the nfs client */
+- op->info.owner = (__u64) fl->fl_pid;
+- xop->callback = fl->fl_lmops->fl_grant;
+- locks_init_lock(&xop->flc);
+- locks_copy_lock(&xop->flc, fl);
+- xop->fl = fl;
+- xop->file = file;
+- } else {
+- op->info.owner = (__u64)(long) fl->fl_owner;
+- xop->callback = NULL;
+- }
+-
+- send_op(op);
+-
+- if (xop->callback == NULL)
+- wait_event(recv_wq, (op->done != 0));
+- else
+- return -EINPROGRESS;
+-
+- spin_lock(&ops_lock);
+- if (!list_empty(&op->list)) {
+- printk(KERN_INFO "plock op on list\n");
+- list_del(&op->list);
+- }
+- spin_unlock(&ops_lock);
+-
+- rv = op->info.rv;
+-
+- if (!rv) {
+- if (posix_lock_file_wait(file, fl) < 0)
+- log_error("gdlm_plock: vfs lock error %x,%llx",
+- name->ln_type,
+- (unsigned long long)name->ln_number);
+- }
+-
+- kfree(xop);
+- return rv;
+-}
+-
+-/* Returns failure iff a succesful lock operation should be canceled */
+-static int gdlm_plock_callback(struct plock_op *op)
+-{
+- struct file *file;
+- struct file_lock *fl;
+- struct file_lock *flc;
+- int (*notify)(void *, void *, int) = NULL;
+- struct plock_xop *xop = (struct plock_xop *)op;
+- int rv = 0;
+-
+- spin_lock(&ops_lock);
+- if (!list_empty(&op->list)) {
+- printk(KERN_INFO "plock op on list\n");
+- list_del(&op->list);
+- }
+- spin_unlock(&ops_lock);
+-
+- /* check if the following 2 are still valid or make a copy */
+- file = xop->file;
+- flc = &xop->flc;
+- fl = xop->fl;
+- notify = xop->callback;
+-
+- if (op->info.rv) {
+- notify(flc, NULL, op->info.rv);
+- goto out;
+- }
+-
+- /* got fs lock; bookkeep locally as well: */
+- flc->fl_flags &= ~FL_SLEEP;
+- if (posix_lock_file(file, flc, NULL)) {
+- /*
+- * This can only happen in the case of kmalloc() failure.
+- * The filesystem's own lock is the authoritative lock,
+- * so a failure to get the lock locally is not a disaster.
+- * As long as GFS cannot reliably cancel locks (especially
+- * in a low-memory situation), we're better off ignoring
+- * this failure than trying to recover.
+- */
+- log_error("gdlm_plock: vfs lock error file %p fl %p",
+- file, fl);
+- }
+-
+- rv = notify(flc, NULL, 0);
+- if (rv) {
+- /* XXX: We need to cancel the fs lock here: */
+- printk("gfs2 lock granted after lock request failed;"
+- " dangling lock!\n");
+- goto out;
+- }
+-
+-out:
+- kfree(xop);
+- return rv;
+-}
+-
+-int gdlm_punlock(void *lockspace, struct lm_lockname *name,
+- struct file *file, struct file_lock *fl)
+-{
+- struct gdlm_ls *ls = lockspace;
+- struct plock_op *op;
+- int rv;
+-
+- op = kzalloc(sizeof(*op), GFP_KERNEL);
+- if (!op)
+- return -ENOMEM;
+-
+- if (posix_lock_file_wait(file, fl) < 0)
+- log_error("gdlm_punlock: vfs unlock error %x,%llx",
+- name->ln_type, (unsigned long long)name->ln_number);
+-
+- op->info.optype = GDLM_PLOCK_OP_UNLOCK;
+- op->info.pid = fl->fl_pid;
+- op->info.fsid = ls->id;
+- op->info.number = name->ln_number;
+- op->info.start = fl->fl_start;
+- op->info.end = fl->fl_end;
+- if (fl->fl_lmops && fl->fl_lmops->fl_grant)
+- op->info.owner = (__u64) fl->fl_pid;
+- else
+- op->info.owner = (__u64)(long) fl->fl_owner;
+-
+- send_op(op);
+- wait_event(recv_wq, (op->done != 0));
+-
+- spin_lock(&ops_lock);
+- if (!list_empty(&op->list)) {
+- printk(KERN_INFO "punlock op on list\n");
+- list_del(&op->list);
+- }
+- spin_unlock(&ops_lock);
+-
+- rv = op->info.rv;
+-
+- if (rv == -ENOENT)
+- rv = 0;
+-
+- kfree(op);
+- return rv;
+-}
+-
+-int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
+- struct file *file, struct file_lock *fl)
+-{
+- struct gdlm_ls *ls = lockspace;
+- struct plock_op *op;
+- int rv;
+-
+- op = kzalloc(sizeof(*op), GFP_KERNEL);
+- if (!op)
+- return -ENOMEM;
+-
+- op->info.optype = GDLM_PLOCK_OP_GET;
+- op->info.pid = fl->fl_pid;
+- op->info.ex = (fl->fl_type == F_WRLCK);
+- op->info.fsid = ls->id;
+- op->info.number = name->ln_number;
+- op->info.start = fl->fl_start;
+- op->info.end = fl->fl_end;
+- if (fl->fl_lmops && fl->fl_lmops->fl_grant)
+- op->info.owner = (__u64) fl->fl_pid;
+- else
+- op->info.owner = (__u64)(long) fl->fl_owner;
+-
+- send_op(op);
+- wait_event(recv_wq, (op->done != 0));
+-
+- spin_lock(&ops_lock);
+- if (!list_empty(&op->list)) {
+- printk(KERN_INFO "plock_get op on list\n");
+- list_del(&op->list);
+- }
+- spin_unlock(&ops_lock);
+-
+- /* info.rv from userspace is 1 for conflict, 0 for no-conflict,
+- -ENOENT if there are no locks on the file */
+-
+- rv = op->info.rv;
+-
+- fl->fl_type = F_UNLCK;
+- if (rv == -ENOENT)
+- rv = 0;
+- else if (rv > 0) {
+- fl->fl_type = (op->info.ex) ? F_WRLCK : F_RDLCK;
+- fl->fl_pid = op->info.pid;
+- fl->fl_start = op->info.start;
+- fl->fl_end = op->info.end;
+- rv = 0;
+- }
+-
+- kfree(op);
+- return rv;
+-}
+-
+-/* a read copies out one plock request from the send list */
+-static ssize_t dev_read(struct file *file, char __user *u, size_t count,
+- loff_t *ppos)
+-{
+- struct gdlm_plock_info info;
+- struct plock_op *op = NULL;
+-
+- if (count < sizeof(info))
+- return -EINVAL;
+-
+- spin_lock(&ops_lock);
+- if (!list_empty(&send_list)) {
+- op = list_entry(send_list.next, struct plock_op, list);
+- list_move(&op->list, &recv_list);
+- memcpy(&info, &op->info, sizeof(info));
+- }
+- spin_unlock(&ops_lock);
+-
+- if (!op)
+- return -EAGAIN;
+-
+- if (copy_to_user(u, &info, sizeof(info)))
+- return -EFAULT;
+- return sizeof(info);
+-}
+-
+-/* a write copies in one plock result that should match a plock_op
+- on the recv list */
+-static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
+- loff_t *ppos)
+-{
+- struct gdlm_plock_info info;
+- struct plock_op *op;
+- int found = 0;
+-
+- if (count != sizeof(info))
+- return -EINVAL;
+-
+- if (copy_from_user(&info, u, sizeof(info)))
+- return -EFAULT;
+-
+- if (check_version(&info))
+- return -EINVAL;
+-
+- spin_lock(&ops_lock);
+- list_for_each_entry(op, &recv_list, list) {
+- if (op->info.fsid == info.fsid && op->info.number == info.number &&
+- op->info.owner == info.owner) {
+- list_del_init(&op->list);
+- found = 1;
+- op->done = 1;
+- memcpy(&op->info, &info, sizeof(info));
+- break;
+- }
+- }
+- spin_unlock(&ops_lock);
+-
+- if (found) {
+- struct plock_xop *xop;
+- xop = (struct plock_xop *)op;
+- if (xop->callback)
+- count = gdlm_plock_callback(op);
+- else
+- wake_up(&recv_wq);
+- } else
+- printk(KERN_INFO "gdlm dev_write no op %x %llx\n", info.fsid,
+- (unsigned long long)info.number);
+- return count;
+-}
+-
+-static unsigned int dev_poll(struct file *file, poll_table *wait)
+-{
+- unsigned int mask = 0;
+-
+- poll_wait(file, &send_wq, wait);
+-
+- spin_lock(&ops_lock);
+- if (!list_empty(&send_list))
+- mask = POLLIN | POLLRDNORM;
+- spin_unlock(&ops_lock);
+-
+- return mask;
+-}
+-
+-static const struct file_operations dev_fops = {
+- .read = dev_read,
+- .write = dev_write,
+- .poll = dev_poll,
+- .owner = THIS_MODULE
+-};
+-
+-static struct miscdevice plock_dev_misc = {
+- .minor = MISC_DYNAMIC_MINOR,
+- .name = GDLM_PLOCK_MISC_NAME,
+- .fops = &dev_fops
+-};
+-
+-int gdlm_plock_init(void)
+-{
+- int rv;
+-
+- spin_lock_init(&ops_lock);
+- INIT_LIST_HEAD(&send_list);
+- INIT_LIST_HEAD(&recv_list);
+- init_waitqueue_head(&send_wq);
+- init_waitqueue_head(&recv_wq);
+-
+- rv = misc_register(&plock_dev_misc);
+- if (rv)
+- printk(KERN_INFO "gdlm_plock_init: misc_register failed %d",
+- rv);
+- return rv;
+-}
+-
+-void gdlm_plock_exit(void)
+-{
+- if (misc_deregister(&plock_dev_misc) < 0)
+- printk(KERN_INFO "gdlm_plock_exit: misc_deregister failed");
+-}
+-
+diff --git a/fs/gfs2/locking/dlm/sysfs.c b/fs/gfs2/locking/dlm/sysfs.c
+index a87b098..8479da4 100644
+--- a/fs/gfs2/locking/dlm/sysfs.c
++++ b/fs/gfs2/locking/dlm/sysfs.c
+@@ -12,8 +12,6 @@
+
+ #include "lock_dlm.h"
+
+-extern struct lm_lockops gdlm_ops;
+-
+ static ssize_t proto_name_show(struct gdlm_ls *ls, char *buf)
+ {
+ return sprintf(buf, "%s\n", gdlm_ops.lm_proto_name);
+diff --git a/fs/gfs2/locking/dlm/thread.c b/fs/gfs2/locking/dlm/thread.c
+index 521694f..e53db6f 100644
+--- a/fs/gfs2/locking/dlm/thread.c
++++ b/fs/gfs2/locking/dlm/thread.c
+@@ -135,7 +135,15 @@ static void process_complete(struct gdlm_lock *lp)
+ lp->lksb.sb_status, lp->lockname.ln_type,
+ (unsigned long long)lp->lockname.ln_number,
+ lp->flags);
+- return;
++ if (lp->lksb.sb_status == -EDEADLOCK &&
++ lp->ls->fsflags & LM_MFLAG_CONV_NODROP) {
++ lp->req = lp->cur;
++ acb.lc_ret |= LM_OUT_CONV_DEADLK;
++ if (lp->cur == DLM_LOCK_IV)
++ lp->lksb.sb_lkid = 0;
++ goto out;
++ } else
++ return;
+ }
+
+ /*
+diff --git a/fs/gfs2/locking/nolock/main.c b/fs/gfs2/locking/nolock/main.c
+index d3b8ce6..284a5ec 100644
+--- a/fs/gfs2/locking/nolock/main.c
++++ b/fs/gfs2/locking/nolock/main.c
+@@ -140,7 +140,7 @@ static int nolock_hold_lvb(void *lock, char **lvbp)
+ struct nolock_lockspace *nl = lock;
+ int error = 0;
+
+- *lvbp = kzalloc(nl->nl_lvb_size, GFP_KERNEL);
++ *lvbp = kzalloc(nl->nl_lvb_size, GFP_NOFS);
+ if (!*lvbp)
+ error = -ENOMEM;
+
+diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
+index 161ab6f..548264b 100644
+--- a/fs/gfs2/log.c
++++ b/fs/gfs2/log.c
+@@ -769,8 +769,8 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
+ sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm;
+ gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0);
+ reserved = calc_reserved(sdp);
++ gfs2_assert_withdraw(sdp, sdp->sd_log_blks_reserved + tr->tr_reserved >= reserved);
+ unused = sdp->sd_log_blks_reserved - reserved + tr->tr_reserved;
+- gfs2_assert_withdraw(sdp, unused >= 0);
+ atomic_add(unused, &sdp->sd_log_blks_free);
+ gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <=
+ sdp->sd_jdesc->jd_blocks);
+@@ -779,6 +779,21 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
+ gfs2_log_unlock(sdp);
+ }
+
++static void buf_lo_incore_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
++{
++ struct list_head *head = &tr->tr_list_buf;
++ struct gfs2_bufdata *bd;
++
++ gfs2_log_lock(sdp);
++ while (!list_empty(head)) {
++ bd = list_entry(head->next, struct gfs2_bufdata, bd_list_tr);
++ list_del_init(&bd->bd_list_tr);
++ tr->tr_num_buf--;
++ }
++ gfs2_log_unlock(sdp);
++ gfs2_assert_warn(sdp, !tr->tr_num_buf);
++}
++
+ /**
+ * gfs2_log_commit - Commit a transaction to the log
+ * @sdp: the filesystem
+@@ -790,7 +805,7 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
+ void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
+ {
+ log_refund(sdp, tr);
+- lops_incore_commit(sdp, tr);
++ buf_lo_incore_commit(sdp, tr);
+
+ sdp->sd_vfs->s_dirt = 1;
+ up_read(&sdp->sd_log_flush_lock);
+diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
+index fae59d6..4390f6f 100644
+--- a/fs/gfs2/lops.c
++++ b/fs/gfs2/lops.c
+@@ -152,21 +152,6 @@ out:
+ unlock_buffer(bd->bd_bh);
+ }
+
+-static void buf_lo_incore_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
+-{
+- struct list_head *head = &tr->tr_list_buf;
+- struct gfs2_bufdata *bd;
+-
+- gfs2_log_lock(sdp);
+- while (!list_empty(head)) {
+- bd = list_entry(head->next, struct gfs2_bufdata, bd_list_tr);
+- list_del_init(&bd->bd_list_tr);
+- tr->tr_num_buf--;
+- }
+- gfs2_log_unlock(sdp);
+- gfs2_assert_warn(sdp, !tr->tr_num_buf);
+-}
+-
+ static void buf_lo_before_commit(struct gfs2_sbd *sdp)
+ {
+ struct buffer_head *bh;
+@@ -419,8 +404,10 @@ static int revoke_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
+ blkno = be64_to_cpu(*(__be64 *)(bh->b_data + offset));
+
+ error = gfs2_revoke_add(sdp, blkno, start);
+- if (error < 0)
++ if (error < 0) {
++ brelse(bh);
+ return error;
++ }
+ else if (error)
+ sdp->sd_found_revokes++;
+
+@@ -737,7 +724,6 @@ static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
+
+ const struct gfs2_log_operations gfs2_buf_lops = {
+ .lo_add = buf_lo_add,
+- .lo_incore_commit = buf_lo_incore_commit,
+ .lo_before_commit = buf_lo_before_commit,
+ .lo_after_commit = buf_lo_after_commit,
+ .lo_before_scan = buf_lo_before_scan,
+@@ -763,7 +749,6 @@ const struct gfs2_log_operations gfs2_rg_lops = {
+
+ const struct gfs2_log_operations gfs2_databuf_lops = {
+ .lo_add = databuf_lo_add,
+- .lo_incore_commit = buf_lo_incore_commit,
+ .lo_before_commit = databuf_lo_before_commit,
+ .lo_after_commit = databuf_lo_after_commit,
+ .lo_scan_elements = databuf_lo_scan_elements,
+diff --git a/fs/gfs2/lops.h b/fs/gfs2/lops.h
+index 41a00df..3c0b273 100644
+--- a/fs/gfs2/lops.h
++++ b/fs/gfs2/lops.h
+@@ -1,6 +1,6 @@
+ /*
+ * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
+- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
++ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+@@ -57,15 +57,6 @@ static inline void lops_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
+ le->le_ops->lo_add(sdp, le);
+ }
+
+-static inline void lops_incore_commit(struct gfs2_sbd *sdp,
+- struct gfs2_trans *tr)
+-{
+- int x;
+- for (x = 0; gfs2_log_ops[x]; x++)
+- if (gfs2_log_ops[x]->lo_incore_commit)
+- gfs2_log_ops[x]->lo_incore_commit(sdp, tr);
+-}
+-
+ static inline void lops_before_commit(struct gfs2_sbd *sdp)
+ {
+ int x;
+diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c
+index 9c7765c..053e2eb 100644
+--- a/fs/gfs2/main.c
++++ b/fs/gfs2/main.c
+@@ -89,6 +89,12 @@ static int __init init_gfs2_fs(void)
+ if (!gfs2_bufdata_cachep)
+ goto fail;
+
++ gfs2_rgrpd_cachep = kmem_cache_create("gfs2_rgrpd",
++ sizeof(struct gfs2_rgrpd),
++ 0, 0, NULL);
++ if (!gfs2_rgrpd_cachep)
++ goto fail;
++
+ error = register_filesystem(&gfs2_fs_type);
+ if (error)
+ goto fail;
+@@ -108,6 +114,9 @@ fail_unregister:
+ fail:
+ gfs2_glock_exit();
+
++ if (gfs2_rgrpd_cachep)
++ kmem_cache_destroy(gfs2_rgrpd_cachep);
++
+ if (gfs2_bufdata_cachep)
+ kmem_cache_destroy(gfs2_bufdata_cachep);
+
+@@ -133,6 +142,7 @@ static void __exit exit_gfs2_fs(void)
+ unregister_filesystem(&gfs2_fs_type);
+ unregister_filesystem(&gfs2meta_fs_type);
+
++ kmem_cache_destroy(gfs2_rgrpd_cachep);
+ kmem_cache_destroy(gfs2_bufdata_cachep);
+ kmem_cache_destroy(gfs2_inode_cachep);
+ kmem_cache_destroy(gfs2_glock_cachep);
+diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
+index ac772b6..90a04a6 100644
+--- a/fs/gfs2/ops_address.c
++++ b/fs/gfs2/ops_address.c
+@@ -1,6 +1,6 @@
+ /*
+ * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
+- * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
++ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+@@ -21,7 +21,6 @@
+ #include <linux/gfs2_ondisk.h>
+ #include <linux/lm_interface.h>
+ #include <linux/backing-dev.h>
+-#include <linux/pagevec.h>
+
+ #include "gfs2.h"
+ #include "incore.h"
+@@ -104,11 +103,9 @@ static int gfs2_writepage_common(struct page *page,
+ loff_t i_size = i_size_read(inode);
+ pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT;
+ unsigned offset;
+- int ret = -EIO;
+
+ if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(ip->i_gl)))
+ goto out;
+- ret = 0;
+ if (current->journal_info)
+ goto redirty;
+ /* Is the page fully outside i_size? (truncate in progress) */
+@@ -280,7 +277,7 @@ static int gfs2_write_jdata_pagevec(struct address_space *mapping,
+ int i;
+ int ret;
+
+- ret = gfs2_trans_begin(sdp, nrblocks, 0);
++ ret = gfs2_trans_begin(sdp, nrblocks, nrblocks);
+ if (ret < 0)
+ return ret;
+
+@@ -510,23 +507,26 @@ static int __gfs2_readpage(void *file, struct page *page)
+ static int gfs2_readpage(struct file *file, struct page *page)
+ {
+ struct gfs2_inode *ip = GFS2_I(page->mapping->host);
+- struct gfs2_holder gh;
++ struct gfs2_holder *gh;
+ int error;
+
+- gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME|LM_FLAG_TRY_1CB, &gh);
+- error = gfs2_glock_nq_atime(&gh);
+- if (unlikely(error)) {
++ gh = gfs2_glock_is_locked_by_me(ip->i_gl);
++ if (!gh) {
++ gh = kmalloc(sizeof(struct gfs2_holder), GFP_NOFS);
++ if (!gh)
++ return -ENOBUFS;
++ gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, gh);
+ unlock_page(page);
+- goto out;
++ error = gfs2_glock_nq_atime(gh);
++ if (likely(error != 0))
++ goto out;
++ return AOP_TRUNCATED_PAGE;
+ }
+ error = __gfs2_readpage(file, page);
+- gfs2_glock_dq(&gh);
++ gfs2_glock_dq(gh);
+ out:
+- gfs2_holder_uninit(&gh);
+- if (error == GLR_TRYFAILED) {
+- yield();
+- return AOP_TRUNCATED_PAGE;
+- }
++ gfs2_holder_uninit(gh);
++ kfree(gh);
+ return error;
+ }
+
+@@ -648,15 +648,15 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
+
+ if (alloc_required) {
+ al = gfs2_alloc_get(ip);
++ if (!al) {
++ error = -ENOMEM;
++ goto out_unlock;
++ }
+
+- error = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
++ error = gfs2_quota_lock_check(ip);
+ if (error)
+ goto out_alloc_put;
+
+- error = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid);
+- if (error)
+- goto out_qunlock;
+-
+ al->al_requested = data_blocks + ind_blocks;
+ error = gfs2_inplace_reserve(ip);
+ if (error)
+@@ -828,7 +828,7 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
+ unsigned int to = from + len;
+ int ret;
+
+- BUG_ON(gfs2_glock_is_locked_by_me(ip->i_gl) == 0);
++ BUG_ON(gfs2_glock_is_locked_by_me(ip->i_gl) == NULL);
+
+ ret = gfs2_meta_inode_buffer(ip, &dibh);
+ if (unlikely(ret)) {
+diff --git a/fs/gfs2/ops_dentry.c b/fs/gfs2/ops_dentry.c
+index 793e334..4a5e676 100644
+--- a/fs/gfs2/ops_dentry.c
++++ b/fs/gfs2/ops_dentry.c
+@@ -43,7 +43,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
+ struct gfs2_holder d_gh;
+ struct gfs2_inode *ip = NULL;
+ int error;
+- int had_lock=0;
++ int had_lock = 0;
+
+ if (inode) {
+ if (is_bad_inode(inode))
+@@ -54,7 +54,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
+ if (sdp->sd_args.ar_localcaching)
+ goto valid;
+
+- had_lock = gfs2_glock_is_locked_by_me(dip->i_gl);
++ had_lock = (gfs2_glock_is_locked_by_me(dip->i_gl) != NULL);
+ if (!had_lock) {
+ error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
+ if (error)
+diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c
+index 334c7f8..990d9f4 100644
+--- a/fs/gfs2/ops_export.c
++++ b/fs/gfs2/ops_export.c
+@@ -204,8 +204,6 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb,
+ inode = gfs2_inode_lookup(sb, DT_UNKNOWN,
+ inum->no_addr,
+ 0, 0);
+- if (!inode)
+- goto fail;
+ if (IS_ERR(inode)) {
+ error = PTR_ERR(inode);
+ goto fail;
+diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
+index f4842f2..e1b7d52 100644
+--- a/fs/gfs2/ops_file.c
++++ b/fs/gfs2/ops_file.c
+@@ -30,7 +30,6 @@
+ #include "glock.h"
+ #include "glops.h"
+ #include "inode.h"
+-#include "lm.h"
+ #include "log.h"
+ #include "meta_io.h"
+ #include "quota.h"
+@@ -39,6 +38,7 @@
+ #include "util.h"
+ #include "eaops.h"
+ #include "ops_address.h"
++#include "ops_inode.h"
+
+ /**
+ * gfs2_llseek - seek to a location in a file
+@@ -369,12 +369,9 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page)
+ if (al == NULL)
+ goto out_unlock;
+
+- ret = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
++ ret = gfs2_quota_lock_check(ip);
+ if (ret)
+ goto out_alloc_put;
+- ret = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid);
+- if (ret)
+- goto out_quota_unlock;
+ al->al_requested = data_blocks + ind_blocks;
+ ret = gfs2_inplace_reserve(ip);
+ if (ret)
+@@ -596,6 +593,36 @@ static int gfs2_setlease(struct file *file, long arg, struct file_lock **fl)
+ return generic_setlease(file, arg, fl);
+ }
+
++static int gfs2_lm_plock_get(struct gfs2_sbd *sdp, struct lm_lockname *name,
++ struct file *file, struct file_lock *fl)
++{
++ int error = -EIO;
++ if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++ error = sdp->sd_lockstruct.ls_ops->lm_plock_get(
++ sdp->sd_lockstruct.ls_lockspace, name, file, fl);
++ return error;
++}
++
++static int gfs2_lm_plock(struct gfs2_sbd *sdp, struct lm_lockname *name,
++ struct file *file, int cmd, struct file_lock *fl)
++{
++ int error = -EIO;
++ if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++ error = sdp->sd_lockstruct.ls_ops->lm_plock(
++ sdp->sd_lockstruct.ls_lockspace, name, file, cmd, fl);
++ return error;
++}
++
++static int gfs2_lm_punlock(struct gfs2_sbd *sdp, struct lm_lockname *name,
++ struct file *file, struct file_lock *fl)
++{
++ int error = -EIO;
++ if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++ error = sdp->sd_lockstruct.ls_ops->lm_punlock(
++ sdp->sd_lockstruct.ls_lockspace, name, file, fl);
++ return error;
++}
++
+ /**
+ * gfs2_lock - acquire/release a posix lock on a file
+ * @file: the file pointer
+diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
+index 4bee6aa..ef9c6c4 100644
+--- a/fs/gfs2/ops_fstype.c
++++ b/fs/gfs2/ops_fstype.c
+@@ -1,6 +1,6 @@
+ /*
+ * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
+- * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
++ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+@@ -26,7 +26,6 @@
+ #include "glock.h"
+ #include "glops.h"
+ #include "inode.h"
+-#include "lm.h"
+ #include "mount.h"
+ #include "ops_fstype.h"
+ #include "ops_dentry.h"
+@@ -363,6 +362,13 @@ static int map_journal_extents(struct gfs2_sbd *sdp)
+ return rc;
+ }
+
++static void gfs2_lm_others_may_mount(struct gfs2_sbd *sdp)
++{
++ if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++ sdp->sd_lockstruct.ls_ops->lm_others_may_mount(
++ sdp->sd_lockstruct.ls_lockspace);
++}
++
+ static int init_journal(struct gfs2_sbd *sdp, int undo)
+ {
+ struct gfs2_holder ji_gh;
+@@ -542,7 +548,7 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo)
+ }
+ ip = GFS2_I(sdp->sd_rindex);
+ set_bit(GLF_STICKY, &ip->i_gl->gl_flags);
+- sdp->sd_rindex_vn = ip->i_gl->gl_vn - 1;
++ sdp->sd_rindex_uptodate = 0;
+
+ /* Read in the quota inode */
+ sdp->sd_quota_inode = gfs2_lookup_simple(sdp->sd_master_dir, "quota");
+@@ -705,6 +711,69 @@ fail:
+ }
+
+ /**
++ * gfs2_lm_mount - mount a locking protocol
++ * @sdp: the filesystem
++ * @args: mount arguements
++ * @silent: if 1, don't complain if the FS isn't a GFS2 fs
++ *
++ * Returns: errno
++ */
++
++static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent)
++{
++ char *proto = sdp->sd_proto_name;
++ char *table = sdp->sd_table_name;
++ int flags = LM_MFLAG_CONV_NODROP;
++ int error;
++
++ if (sdp->sd_args.ar_spectator)
++ flags |= LM_MFLAG_SPECTATOR;
++
++ fs_info(sdp, "Trying to join cluster \"%s\", \"%s\"\n", proto, table);
++
++ error = gfs2_mount_lockproto(proto, table, sdp->sd_args.ar_hostdata,
++ gfs2_glock_cb, sdp,
++ GFS2_MIN_LVB_SIZE, flags,
++ &sdp->sd_lockstruct, &sdp->sd_kobj);
++ if (error) {
++ fs_info(sdp, "can't mount proto=%s, table=%s, hostdata=%s\n",
++ proto, table, sdp->sd_args.ar_hostdata);
++ goto out;
++ }
++
++ if (gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_lockspace) ||
++ gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_ops) ||
++ gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_lvb_size >=
++ GFS2_MIN_LVB_SIZE)) {
++ gfs2_unmount_lockproto(&sdp->sd_lockstruct);
++ goto out;
++ }
++
++ if (sdp->sd_args.ar_spectator)
++ snprintf(sdp->sd_fsname, GFS2_FSNAME_LEN, "%s.s", table);
++ else
++ snprintf(sdp->sd_fsname, GFS2_FSNAME_LEN, "%s.%u", table,
++ sdp->sd_lockstruct.ls_jid);
++
++ fs_info(sdp, "Joined cluster. Now mounting FS...\n");
++
++ if ((sdp->sd_lockstruct.ls_flags & LM_LSFLAG_LOCAL) &&
++ !sdp->sd_args.ar_ignore_local_fs) {
++ sdp->sd_args.ar_localflocks = 1;
++ sdp->sd_args.ar_localcaching = 1;
++ }
++
++out:
++ return error;
++}
++
++void gfs2_lm_unmount(struct gfs2_sbd *sdp)
++{
++ if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++ gfs2_unmount_lockproto(&sdp->sd_lockstruct);
++}
++
++/**
+ * fill_super - Read in superblock
+ * @sb: The VFS superblock
+ * @data: Mount options
+@@ -874,7 +943,6 @@ static struct super_block* get_gfs2_sb(const char *dev_name)
+ {
+ struct kstat stat;
+ struct nameidata nd;
+- struct file_system_type *fstype;
+ struct super_block *sb = NULL, *s;
+ int error;
+
+@@ -886,8 +954,7 @@ static struct super_block* get_gfs2_sb(const char *dev_name)
+ }
+ error = vfs_getattr(nd.path.mnt, nd.path.dentry, &stat);
+
+- fstype = get_fs_type("gfs2");
+- list_for_each_entry(s, &fstype->fs_supers, s_instances) {
++ list_for_each_entry(s, &gfs2_fs_type.fs_supers, s_instances) {
+ if ((S_ISBLK(stat.mode) && s->s_dev == stat.rdev) ||
+ (S_ISDIR(stat.mode) &&
+ s == nd.path.dentry->d_inode->i_sb)) {
+@@ -931,7 +998,6 @@ static int gfs2_get_sb_meta(struct file_system_type *fs_type, int flags,
+ error = PTR_ERR(new);
+ goto error;
+ }
+- module_put(fs_type->owner);
+ new->s_flags = flags;
+ strlcpy(new->s_id, sb->s_id, sizeof(new->s_id));
+ sb_set_blocksize(new, sb->s_blocksize);
+diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
+index e874129..2686ad4 100644
+--- a/fs/gfs2/ops_inode.c
++++ b/fs/gfs2/ops_inode.c
+@@ -200,15 +200,15 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
+
+ if (alloc_required) {
+ struct gfs2_alloc *al = gfs2_alloc_get(dip);
++ if (!al) {
++ error = -ENOMEM;
++ goto out_gunlock;
++ }
+
+- error = gfs2_quota_lock(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
++ error = gfs2_quota_lock_check(dip);
+ if (error)
+ goto out_alloc;
+
+- error = gfs2_quota_check(dip, dip->i_inode.i_uid, dip->i_inode.i_gid);
+- if (error)
+- goto out_gunlock_q;
+-
+ al->al_requested = sdp->sd_max_dirres;
+
+ error = gfs2_inplace_reserve(dip);
+@@ -716,15 +716,15 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
+
+ if (alloc_required) {
+ struct gfs2_alloc *al = gfs2_alloc_get(ndip);
++ if (!al) {
++ error = -ENOMEM;
++ goto out_gunlock;
++ }
+
+- error = gfs2_quota_lock(ndip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
++ error = gfs2_quota_lock_check(ndip);
+ if (error)
+ goto out_alloc;
+
+- error = gfs2_quota_check(ndip, ndip->i_inode.i_uid, ndip->i_inode.i_gid);
+- if (error)
+- goto out_gunlock_q;
+-
+ al->al_requested = sdp->sd_max_dirres;
+
+ error = gfs2_inplace_reserve(ndip);
+@@ -898,7 +898,7 @@ static int gfs2_permission(struct inode *inode, int mask, struct nameidata *nd)
+ int error;
+ int unlock = 0;
+
+- if (gfs2_glock_is_locked_by_me(ip->i_gl) == 0) {
++ if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) {
+ error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
+ if (error)
+ return error;
+@@ -953,7 +953,8 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
+ if (!(attr->ia_valid & ATTR_GID) || ogid == ngid)
+ ogid = ngid = NO_QUOTA_CHANGE;
+
+- gfs2_alloc_get(ip);
++ if (!gfs2_alloc_get(ip))
++ return -ENOMEM;
+
+ error = gfs2_quota_lock(ip, nuid, ngid);
+ if (error)
+@@ -981,8 +982,9 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
+ brelse(dibh);
+
+ if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) {
+- gfs2_quota_change(ip, -ip->i_di.di_blocks, ouid, ogid);
+- gfs2_quota_change(ip, ip->i_di.di_blocks, nuid, ngid);
++ u64 blocks = gfs2_get_inode_blocks(&ip->i_inode);
++ gfs2_quota_change(ip, -blocks, ouid, ogid);
++ gfs2_quota_change(ip, blocks, nuid, ngid);
+ }
+
+ out_end_trans:
+@@ -1064,7 +1066,7 @@ static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ int error;
+ int unlock = 0;
+
+- if (gfs2_glock_is_locked_by_me(ip->i_gl) == 0) {
++ if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) {
+ error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh);
+ if (error)
+ return error;
+@@ -1148,16 +1150,6 @@ const struct inode_operations gfs2_file_iops = {
+ .removexattr = gfs2_removexattr,
+ };
+
+-const struct inode_operations gfs2_dev_iops = {
+- .permission = gfs2_permission,
+- .setattr = gfs2_setattr,
+- .getattr = gfs2_getattr,
+- .setxattr = gfs2_setxattr,
+- .getxattr = gfs2_getxattr,
+- .listxattr = gfs2_listxattr,
+- .removexattr = gfs2_removexattr,
+-};
+-
+ const struct inode_operations gfs2_dir_iops = {
+ .create = gfs2_create,
+ .lookup = gfs2_lookup,
+diff --git a/fs/gfs2/ops_inode.h b/fs/gfs2/ops_inode.h
+index fd8cee2..14b4b79 100644
+--- a/fs/gfs2/ops_inode.h
++++ b/fs/gfs2/ops_inode.h
+@@ -15,7 +15,6 @@
+ extern const struct inode_operations gfs2_file_iops;
+ extern const struct inode_operations gfs2_dir_iops;
+ extern const struct inode_operations gfs2_symlink_iops;
+-extern const struct inode_operations gfs2_dev_iops;
+ extern const struct file_operations gfs2_file_fops;
+ extern const struct file_operations gfs2_dir_fops;
+ extern const struct file_operations gfs2_file_fops_nolock;
+diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c
+index 5e52421..2278c68 100644
+--- a/fs/gfs2/ops_super.c
++++ b/fs/gfs2/ops_super.c
+@@ -25,7 +25,6 @@
+ #include "incore.h"
+ #include "glock.h"
+ #include "inode.h"
+-#include "lm.h"
+ #include "log.h"
+ #include "mount.h"
+ #include "ops_super.h"
+diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
+index a08dabd..56aaf91 100644
+--- a/fs/gfs2/quota.c
++++ b/fs/gfs2/quota.c
+@@ -94,7 +94,7 @@ static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id,
+ struct gfs2_quota_data *qd;
+ int error;
+
+- qd = kzalloc(sizeof(struct gfs2_quota_data), GFP_KERNEL);
++ qd = kzalloc(sizeof(struct gfs2_quota_data), GFP_NOFS);
+ if (!qd)
+ return -ENOMEM;
+
+@@ -616,16 +616,9 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
+ s64 value;
+ int err = -EIO;
+
+- if (gfs2_is_stuffed(ip)) {
+- struct gfs2_alloc *al = NULL;
+- al = gfs2_alloc_get(ip);
+- /* just request 1 blk */
+- al->al_requested = 1;
+- gfs2_inplace_reserve(ip);
++ if (gfs2_is_stuffed(ip))
+ gfs2_unstuff_dinode(ip, NULL);
+- gfs2_inplace_release(ip);
+- gfs2_alloc_put(ip);
+- }
++
+ page = grab_cache_page(mapping, index);
+ if (!page)
+ return -ENOMEM;
+@@ -690,14 +683,14 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
+ unsigned int qx, x;
+ struct gfs2_quota_data *qd;
+ loff_t offset;
+- unsigned int nalloc = 0;
++ unsigned int nalloc = 0, blocks;
+ struct gfs2_alloc *al = NULL;
+ int error;
+
+ gfs2_write_calc_reserv(ip, sizeof(struct gfs2_quota),
+ &data_blocks, &ind_blocks);
+
+- ghs = kcalloc(num_qd, sizeof(struct gfs2_holder), GFP_KERNEL);
++ ghs = kcalloc(num_qd, sizeof(struct gfs2_holder), GFP_NOFS);
+ if (!ghs)
+ return -ENOMEM;
+
+@@ -727,30 +720,33 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
+ nalloc++;
+ }
+
+- if (nalloc) {
+- al = gfs2_alloc_get(ip);
++ al = gfs2_alloc_get(ip);
++ if (!al) {
++ error = -ENOMEM;
++ goto out_gunlock;
++ }
++ /*
++ * 1 blk for unstuffing inode if stuffed. We add this extra
++ * block to the reservation unconditionally. If the inode
++ * doesn't need unstuffing, the block will be released to the
++ * rgrp since it won't be allocated during the transaction
++ */
++ al->al_requested = 1;
++ /* +1 in the end for block requested above for unstuffing */
++ blocks = num_qd * data_blocks + RES_DINODE + num_qd + 1;
+
+- al->al_requested = nalloc * (data_blocks + ind_blocks);
++ if (nalloc)
++ al->al_requested += nalloc * (data_blocks + ind_blocks);
++ error = gfs2_inplace_reserve(ip);
++ if (error)
++ goto out_alloc;
+
+- error = gfs2_inplace_reserve(ip);
+- if (error)
+- goto out_alloc;
+-
+- error = gfs2_trans_begin(sdp,
+- al->al_rgd->rd_length +
+- num_qd * data_blocks +
+- nalloc * ind_blocks +
+- RES_DINODE + num_qd +
+- RES_STATFS, 0);
+- if (error)
+- goto out_ipres;
+- } else {
+- error = gfs2_trans_begin(sdp,
+- num_qd * data_blocks +
+- RES_DINODE + num_qd, 0);
+- if (error)
+- goto out_gunlock;
+- }
++ if (nalloc)
++ blocks += al->al_rgd->rd_length + nalloc * ind_blocks + RES_STATFS;
++
++ error = gfs2_trans_begin(sdp, blocks, 0);
++ if (error)
++ goto out_ipres;
+
+ for (x = 0; x < num_qd; x++) {
+ qd = qda[x];
+@@ -769,11 +765,9 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
+ out_end_trans:
+ gfs2_trans_end(sdp);
+ out_ipres:
+- if (nalloc)
+- gfs2_inplace_release(ip);
++ gfs2_inplace_release(ip);
+ out_alloc:
+- if (nalloc)
+- gfs2_alloc_put(ip);
++ gfs2_alloc_put(ip);
+ out_gunlock:
+ gfs2_glock_dq_uninit(&i_gh);
+ out:
+@@ -1124,12 +1118,12 @@ int gfs2_quota_init(struct gfs2_sbd *sdp)
+ error = -ENOMEM;
+
+ sdp->sd_quota_bitmap = kcalloc(sdp->sd_quota_chunks,
+- sizeof(unsigned char *), GFP_KERNEL);
++ sizeof(unsigned char *), GFP_NOFS);
+ if (!sdp->sd_quota_bitmap)
+ return error;
+
+ for (x = 0; x < sdp->sd_quota_chunks; x++) {
+- sdp->sd_quota_bitmap[x] = kzalloc(PAGE_SIZE, GFP_KERNEL);
++ sdp->sd_quota_bitmap[x] = kzalloc(PAGE_SIZE, GFP_NOFS);
+ if (!sdp->sd_quota_bitmap[x])
+ goto fail;
+ }
+diff --git a/fs/gfs2/quota.h b/fs/gfs2/quota.h
+index a8be141..3b7f4b0 100644
+--- a/fs/gfs2/quota.h
++++ b/fs/gfs2/quota.h
+@@ -32,4 +32,21 @@ int gfs2_quota_init(struct gfs2_sbd *sdp);
+ void gfs2_quota_scan(struct gfs2_sbd *sdp);
+ void gfs2_quota_cleanup(struct gfs2_sbd *sdp);
+
++static inline int gfs2_quota_lock_check(struct gfs2_inode *ip)
++{
++ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
++ int ret;
++ if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
++ return 0;
++ ret = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
++ if (ret)
++ return ret;
++ if (sdp->sd_args.ar_quota != GFS2_QUOTA_ON)
++ return 0;
++ ret = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid);
++ if (ret)
++ gfs2_quota_unlock(ip);
++ return ret;
++}
++
+ #endif /* __QUOTA_DOT_H__ */
+diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
+index 6fb07d6..2888e4b 100644
+--- a/fs/gfs2/recovery.c
++++ b/fs/gfs2/recovery.c
+@@ -20,7 +20,6 @@
+ #include "bmap.h"
+ #include "glock.h"
+ #include "glops.h"
+-#include "lm.h"
+ #include "lops.h"
+ #include "meta_io.h"
+ #include "recovery.h"
+@@ -69,7 +68,7 @@ int gfs2_revoke_add(struct gfs2_sbd *sdp, u64 blkno, unsigned int where)
+ return 0;
+ }
+
+- rr = kmalloc(sizeof(struct gfs2_revoke_replay), GFP_KERNEL);
++ rr = kmalloc(sizeof(struct gfs2_revoke_replay), GFP_NOFS);
+ if (!rr)
+ return -ENOMEM;
+
+@@ -150,7 +149,7 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk,
+ struct gfs2_log_header_host *head)
+ {
+ struct buffer_head *bh;
+- struct gfs2_log_header_host lh;
++ struct gfs2_log_header_host uninitialized_var(lh);
+ const u32 nothing = 0;
+ u32 hash;
+ int error;
+@@ -425,6 +424,16 @@ static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header_host *hea
+ return error;
+ }
+
++
++static void gfs2_lm_recovery_done(struct gfs2_sbd *sdp, unsigned int jid,
++ unsigned int message)
++{
++ if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
++ sdp->sd_lockstruct.ls_ops->lm_recovery_done(
++ sdp->sd_lockstruct.ls_lockspace, jid, message);
++}
++
++
+ /**
+ * gfs2_recover_journal - recovery a given journal
+ * @jd: the struct gfs2_jdesc describing the journal
+diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
+index 3552110..7e8f0b1 100644
+--- a/fs/gfs2/rgrp.c
++++ b/fs/gfs2/rgrp.c
+@@ -1,6 +1,6 @@
+ /*
+ * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
+- * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
++ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+@@ -14,6 +14,7 @@
+ #include <linux/fs.h>
+ #include <linux/gfs2_ondisk.h>
+ #include <linux/lm_interface.h>
++#include <linux/prefetch.h>
+
+ #include "gfs2.h"
+ #include "incore.h"
+@@ -33,6 +34,16 @@
+ #define BFITNOENT ((u32)~0)
+ #define NO_BLOCK ((u64)~0)
+
++#if BITS_PER_LONG == 32
++#define LBITMASK (0x55555555UL)
++#define LBITSKIP55 (0x55555555UL)
++#define LBITSKIP00 (0x00000000UL)
++#else
++#define LBITMASK (0x5555555555555555UL)
++#define LBITSKIP55 (0x5555555555555555UL)
++#define LBITSKIP00 (0x0000000000000000UL)
++#endif
++
+ /*
+ * These routines are used by the resource group routines (rgrp.c)
+ * to keep track of block allocation. Each block is represented by two
+@@ -53,7 +64,8 @@ static const char valid_change[16] = {
+ };
+
+ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
+- unsigned char old_state, unsigned char new_state);
++ unsigned char old_state, unsigned char new_state,
++ unsigned int *n);
+
+ /**
+ * gfs2_setbit - Set a bit in the bitmaps
+@@ -64,26 +76,32 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
+ *
+ */
+
+-static void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buffer,
+- unsigned int buflen, u32 block,
+- unsigned char new_state)
++static inline void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buf1,
++ unsigned char *buf2, unsigned int offset,
++ unsigned int buflen, u32 block,
++ unsigned char new_state)
+ {
+- unsigned char *byte, *end, cur_state;
+- unsigned int bit;
++ unsigned char *byte1, *byte2, *end, cur_state;
++ const unsigned int bit = (block % GFS2_NBBY) * GFS2_BIT_SIZE;
+
+- byte = buffer + (block / GFS2_NBBY);
+- bit = (block % GFS2_NBBY) * GFS2_BIT_SIZE;
+- end = buffer + buflen;
++ byte1 = buf1 + offset + (block / GFS2_NBBY);
++ end = buf1 + offset + buflen;
+
+- gfs2_assert(rgd->rd_sbd, byte < end);
++ BUG_ON(byte1 >= end);
+
+- cur_state = (*byte >> bit) & GFS2_BIT_MASK;
++ cur_state = (*byte1 >> bit) & GFS2_BIT_MASK;
+
+- if (valid_change[new_state * 4 + cur_state]) {
+- *byte ^= cur_state << bit;
+- *byte |= new_state << bit;
+- } else
++ if (unlikely(!valid_change[new_state * 4 + cur_state])) {
+ gfs2_consist_rgrpd(rgd);
++ return;
++ }
++ *byte1 ^= (cur_state ^ new_state) << bit;
++
++ if (buf2) {
++ byte2 = buf2 + offset + (block / GFS2_NBBY);
++ cur_state = (*byte2 >> bit) & GFS2_BIT_MASK;
++ *byte2 ^= (cur_state ^ new_state) << bit;
++ }
+ }
+
+ /**
+@@ -94,10 +112,12 @@ static void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buffer,
+ *
+ */
+
+-static unsigned char gfs2_testbit(struct gfs2_rgrpd *rgd, unsigned char *buffer,
+- unsigned int buflen, u32 block)
++static inline unsigned char gfs2_testbit(struct gfs2_rgrpd *rgd,
++ const unsigned char *buffer,
++ unsigned int buflen, u32 block)
+ {
+- unsigned char *byte, *end, cur_state;
++ const unsigned char *byte, *end;
++ unsigned char cur_state;
+ unsigned int bit;
+
+ byte = buffer + (block / GFS2_NBBY);
+@@ -126,47 +146,66 @@ static unsigned char gfs2_testbit(struct gfs2_rgrpd *rgd, unsigned char *buffer,
+ * Return: the block number (bitmap buffer scope) that was found
+ */
+
+-static u32 gfs2_bitfit(unsigned char *buffer, unsigned int buflen, u32 goal,
+- unsigned char old_state)
++static u32 gfs2_bitfit(const u8 *buffer, unsigned int buflen, u32 goal,
++ u8 old_state)
+ {
+- unsigned char *byte;
+- u32 blk = goal;
+- unsigned int bit, bitlong;
+- unsigned long *plong, plong55;
+-
+- byte = buffer + (goal / GFS2_NBBY);
+- plong = (unsigned long *)(buffer + (goal / GFS2_NBBY));
+- bit = (goal % GFS2_NBBY) * GFS2_BIT_SIZE;
+- bitlong = bit;
+-#if BITS_PER_LONG == 32
+- plong55 = 0x55555555;
+-#else
+- plong55 = 0x5555555555555555;
+-#endif
+- while (byte < buffer + buflen) {
+-
+- if (bitlong == 0 && old_state == 0 && *plong == plong55) {
+- plong++;
+- byte += sizeof(unsigned long);
+- blk += sizeof(unsigned long) * GFS2_NBBY;
+- continue;
++ const u8 *byte, *start, *end;
++ int bit, startbit;
++ u32 g1, g2, misaligned;
++ unsigned long *plong;
++ unsigned long lskipval;
++
++ lskipval = (old_state & GFS2_BLKST_USED) ? LBITSKIP00 : LBITSKIP55;
++ g1 = (goal / GFS2_NBBY);
++ start = buffer + g1;
++ byte = start;
++ end = buffer + buflen;
++ g2 = ALIGN(g1, sizeof(unsigned long));
++ plong = (unsigned long *)(buffer + g2);
++ startbit = bit = (goal % GFS2_NBBY) * GFS2_BIT_SIZE;
++ misaligned = g2 - g1;
++ if (!misaligned)
++ goto ulong_aligned;
++/* parse the bitmap a byte at a time */
++misaligned:
++ while (byte < end) {
++ if (((*byte >> bit) & GFS2_BIT_MASK) == old_state) {
++ return goal +
++ (((byte - start) * GFS2_NBBY) +
++ ((bit - startbit) >> 1));
+ }
+- if (((*byte >> bit) & GFS2_BIT_MASK) == old_state)
+- return blk;
+ bit += GFS2_BIT_SIZE;
+- if (bit >= 8) {
++ if (bit >= GFS2_NBBY * GFS2_BIT_SIZE) {
+ bit = 0;
+ byte++;
++ misaligned--;
++ if (!misaligned) {
++ plong = (unsigned long *)byte;
++ goto ulong_aligned;
++ }
+ }
+- bitlong += GFS2_BIT_SIZE;
+- if (bitlong >= sizeof(unsigned long) * 8) {
+- bitlong = 0;
+- plong++;
+- }
+-
+- blk++;
+ }
++ return BFITNOENT;
+
++/* parse the bitmap a unsigned long at a time */
++ulong_aligned:
++ /* Stop at "end - 1" or else prefetch can go past the end and segfault.
++ We could "if" it but we'd lose some of the performance gained.
++ This way will only slow down searching the very last 4/8 bytes
++ depending on architecture. I've experimented with several ways
++ of writing this section such as using an else before the goto
++ but this one seems to be the fastest. */
++ while ((unsigned char *)plong < end - 1) {
++ prefetch(plong + 1);
++ if (((*plong) & LBITMASK) != lskipval)
++ break;
++ plong++;
++ }
++ if ((unsigned char *)plong < end) {
++ byte = (const u8 *)plong;
++ misaligned += sizeof(unsigned long) - 1;
++ goto misaligned;
++ }
+ return BFITNOENT;
+ }
+
+@@ -179,14 +218,14 @@ static u32 gfs2_bitfit(unsigned char *buffer, unsigned int buflen, u32 goal,
+ * Returns: The number of bits
+ */
+
+-static u32 gfs2_bitcount(struct gfs2_rgrpd *rgd, unsigned char *buffer,
+- unsigned int buflen, unsigned char state)
++static u32 gfs2_bitcount(struct gfs2_rgrpd *rgd, const u8 *buffer,
++ unsigned int buflen, u8 state)
+ {
+- unsigned char *byte = buffer;
+- unsigned char *end = buffer + buflen;
+- unsigned char state1 = state << 2;
+- unsigned char state2 = state << 4;
+- unsigned char state3 = state << 6;
++ const u8 *byte = buffer;
++ const u8 *end = buffer + buflen;
++ const u8 state1 = state << 2;
++ const u8 state2 = state << 4;
++ const u8 state3 = state << 6;
+ u32 count = 0;
+
+ for (; byte < end; byte++) {
+@@ -353,7 +392,7 @@ static void clear_rgrpdi(struct gfs2_sbd *sdp)
+ }
+
+ kfree(rgd->rd_bits);
+- kfree(rgd);
++ kmem_cache_free(gfs2_rgrpd_cachep, rgd);
+ }
+ }
+
+@@ -516,7 +555,7 @@ static int read_rindex_entry(struct gfs2_inode *ip,
+ return error;
+ }
+
+- rgd = kzalloc(sizeof(struct gfs2_rgrpd), GFP_NOFS);
++ rgd = kmem_cache_zalloc(gfs2_rgrpd_cachep, GFP_NOFS);
+ error = -ENOMEM;
+ if (!rgd)
+ return error;
+@@ -539,7 +578,7 @@ static int read_rindex_entry(struct gfs2_inode *ip,
+ return error;
+
+ rgd->rd_gl->gl_object = rgd;
+- rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1;
++ rgd->rd_flags &= ~GFS2_RDF_UPTODATE;
+ rgd->rd_flags |= GFS2_RDF_CHECK;
+ return error;
+ }
+@@ -575,7 +614,7 @@ static int gfs2_ri_update(struct gfs2_inode *ip)
+ }
+ }
+
+- sdp->sd_rindex_vn = ip->i_gl->gl_vn;
++ sdp->sd_rindex_uptodate = 1;
+ return 0;
+ }
+
+@@ -609,7 +648,7 @@ static int gfs2_ri_update_special(struct gfs2_inode *ip)
+ }
+ }
+
+- sdp->sd_rindex_vn = ip->i_gl->gl_vn;
++ sdp->sd_rindex_uptodate = 1;
+ return 0;
+ }
+
+@@ -642,9 +681,9 @@ int gfs2_rindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ri_gh)
+ return error;
+
+ /* Read new copy from disk if we don't have the latest */
+- if (sdp->sd_rindex_vn != gl->gl_vn) {
++ if (!sdp->sd_rindex_uptodate) {
+ mutex_lock(&sdp->sd_rindex_mutex);
+- if (sdp->sd_rindex_vn != gl->gl_vn) {
++ if (!sdp->sd_rindex_uptodate) {
+ error = gfs2_ri_update(ip);
+ if (error)
+ gfs2_glock_dq_uninit(ri_gh);
+@@ -655,21 +694,31 @@ int gfs2_rindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ri_gh)
+ return error;
+ }
+
+-static void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf)
++static void gfs2_rgrp_in(struct gfs2_rgrpd *rgd, const void *buf)
+ {
+ const struct gfs2_rgrp *str = buf;
++ struct gfs2_rgrp_host *rg = &rgd->rd_rg;
++ u32 rg_flags;
+
+- rg->rg_flags = be32_to_cpu(str->rg_flags);
++ rg_flags = be32_to_cpu(str->rg_flags);
++ if (rg_flags & GFS2_RGF_NOALLOC)
++ rgd->rd_flags |= GFS2_RDF_NOALLOC;
++ else
++ rgd->rd_flags &= ~GFS2_RDF_NOALLOC;
+ rg->rg_free = be32_to_cpu(str->rg_free);
+ rg->rg_dinodes = be32_to_cpu(str->rg_dinodes);
+ rg->rg_igeneration = be64_to_cpu(str->rg_igeneration);
+ }
+
+-static void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf)
++static void gfs2_rgrp_out(struct gfs2_rgrpd *rgd, void *buf)
+ {
+ struct gfs2_rgrp *str = buf;
++ struct gfs2_rgrp_host *rg = &rgd->rd_rg;
++ u32 rg_flags = 0;
+
+- str->rg_flags = cpu_to_be32(rg->rg_flags);
++ if (rgd->rd_flags & GFS2_RDF_NOALLOC)
++ rg_flags |= GFS2_RGF_NOALLOC;
++ str->rg_flags = cpu_to_be32(rg_flags);
+ str->rg_free = cpu_to_be32(rg->rg_free);
+ str->rg_dinodes = cpu_to_be32(rg->rg_dinodes);
+ str->__pad = cpu_to_be32(0);
+@@ -726,9 +775,9 @@ int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd)
+ }
+ }
+
+- if (rgd->rd_rg_vn != gl->gl_vn) {
+- gfs2_rgrp_in(&rgd->rd_rg, (rgd->rd_bits[0].bi_bh)->b_data);
+- rgd->rd_rg_vn = gl->gl_vn;
++ if (!(rgd->rd_flags & GFS2_RDF_UPTODATE)) {
++ gfs2_rgrp_in(rgd, (rgd->rd_bits[0].bi_bh)->b_data);
++ rgd->rd_flags |= GFS2_RDF_UPTODATE;
+ }
+
+ spin_lock(&sdp->sd_rindex_spin);
+@@ -840,7 +889,7 @@ static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al)
+ struct gfs2_sbd *sdp = rgd->rd_sbd;
+ int ret = 0;
+
+- if (rgd->rd_rg.rg_flags & GFS2_RGF_NOALLOC)
++ if (rgd->rd_flags & GFS2_RDF_NOALLOC)
+ return 0;
+
+ spin_lock(&sdp->sd_rindex_spin);
+@@ -866,13 +915,15 @@ static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked)
+ u32 goal = 0, block;
+ u64 no_addr;
+ struct gfs2_sbd *sdp = rgd->rd_sbd;
++ unsigned int n;
+
+ for(;;) {
+ if (goal >= rgd->rd_data)
+ break;
+ down_write(&sdp->sd_log_flush_lock);
++ n = 1;
+ block = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED,
+- GFS2_BLKST_UNLINKED);
++ GFS2_BLKST_UNLINKED, &n);
+ up_write(&sdp->sd_log_flush_lock);
+ if (block == BFITNOENT)
+ break;
+@@ -904,24 +955,20 @@ static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked)
+ static struct gfs2_rgrpd *recent_rgrp_first(struct gfs2_sbd *sdp,
+ u64 rglast)
+ {
+- struct gfs2_rgrpd *rgd = NULL;
++ struct gfs2_rgrpd *rgd;
+
+ spin_lock(&sdp->sd_rindex_spin);
+
+- if (list_empty(&sdp->sd_rindex_recent_list))
+- goto out;
+-
+- if (!rglast)
+- goto first;
+-
+- list_for_each_entry(rgd, &sdp->sd_rindex_recent_list, rd_recent) {
+- if (rgd->rd_addr == rglast)
+- goto out;
++ if (rglast) {
++ list_for_each_entry(rgd, &sdp->sd_rindex_recent_list, rd_recent) {
++ if (rgrp_contains_block(rgd, rglast))
++ goto out;
++ }
+ }
+-
+-first:
+- rgd = list_entry(sdp->sd_rindex_recent_list.next, struct gfs2_rgrpd,
+- rd_recent);
++ rgd = NULL;
++ if (!list_empty(&sdp->sd_rindex_recent_list))
++ rgd = list_entry(sdp->sd_rindex_recent_list.next,
++ struct gfs2_rgrpd, rd_recent);
+ out:
+ spin_unlock(&sdp->sd_rindex_spin);
+ return rgd;
+@@ -1067,7 +1114,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
+
+ /* Try recently successful rgrps */
+
+- rgd = recent_rgrp_first(sdp, ip->i_last_rg_alloc);
++ rgd = recent_rgrp_first(sdp, ip->i_goal);
+
+ while (rgd) {
+ rg_locked = 0;
+@@ -1151,8 +1198,6 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
+ }
+
+ out:
+- ip->i_last_rg_alloc = rgd->rd_addr;
+-
+ if (begin) {
+ recent_rgrp_add(rgd);
+ rgd = gfs2_rgrpd_get_next(rgd);
+@@ -1275,6 +1320,7 @@ unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block)
+ * @goal: the goal block within the RG (start here to search for avail block)
+ * @old_state: GFS2_BLKST_XXX the before-allocation state to find
+ * @new_state: GFS2_BLKST_XXX the after-allocation block state
++ * @n: The extent length
+ *
+ * Walk rgrp's bitmap to find bits that represent a block in @old_state.
+ * Add the found bitmap buffer to the transaction.
+@@ -1290,13 +1336,17 @@ unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block)
+ */
+
+ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
+- unsigned char old_state, unsigned char new_state)
++ unsigned char old_state, unsigned char new_state,
++ unsigned int *n)
+ {
+ struct gfs2_bitmap *bi = NULL;
+- u32 length = rgd->rd_length;
++ const u32 length = rgd->rd_length;
+ u32 blk = 0;
+ unsigned int buf, x;
++ const unsigned int elen = *n;
++ const u8 *buffer;
+
++ *n = 0;
+ /* Find bitmap block that contains bits for goal block */
+ for (buf = 0; buf < length; buf++) {
+ bi = rgd->rd_bits + buf;
+@@ -1317,12 +1367,11 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
+ for (x = 0; x <= length; x++) {
+ /* The GFS2_BLKST_UNLINKED state doesn't apply to the clone
+ bitmaps, so we must search the originals for that. */
++ buffer = bi->bi_bh->b_data + bi->bi_offset;
+ if (old_state != GFS2_BLKST_UNLINKED && bi->bi_clone)
+- blk = gfs2_bitfit(bi->bi_clone + bi->bi_offset,
+- bi->bi_len, goal, old_state);
+- else
+- blk = gfs2_bitfit(bi->bi_bh->b_data + bi->bi_offset,
+- bi->bi_len, goal, old_state);
++ buffer = bi->bi_clone + bi->bi_offset;
++
++ blk = gfs2_bitfit(buffer, bi->bi_len, goal, old_state);
+ if (blk != BFITNOENT)
+ break;
+
+@@ -1333,12 +1382,23 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
+ }
+
+ if (blk != BFITNOENT && old_state != new_state) {
++ *n = 1;
+ gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
+- gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset,
++ gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, bi->bi_offset,
+ bi->bi_len, blk, new_state);
+- if (bi->bi_clone)
+- gfs2_setbit(rgd, bi->bi_clone + bi->bi_offset,
+- bi->bi_len, blk, new_state);
++ goal = blk;
++ while (*n < elen) {
++ goal++;
++ if (goal >= (bi->bi_len * GFS2_NBBY))
++ break;
++ if (gfs2_testbit(rgd, buffer, bi->bi_len, goal) !=
++ GFS2_BLKST_FREE)
++ break;
++ gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone,
++ bi->bi_offset, bi->bi_len, goal,
++ new_state);
++ (*n)++;
++ }
+ }
+
+ return (blk == BFITNOENT) ? blk : (bi->bi_start * GFS2_NBBY) + blk;
+@@ -1393,7 +1453,7 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart,
+ bi->bi_len);
+ }
+ gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
+- gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset,
++ gfs2_setbit(rgd, bi->bi_bh->b_data, NULL, bi->bi_offset,
+ bi->bi_len, buf_blk, new_state);
+ }
+
+@@ -1401,13 +1461,13 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart,
+ }
+
+ /**
+- * gfs2_alloc_data - Allocate a data block
+- * @ip: the inode to allocate the data block for
++ * gfs2_alloc_block - Allocate a block
++ * @ip: the inode to allocate the block for
+ *
+ * Returns: the allocated block
+ */
+
+-u64 gfs2_alloc_data(struct gfs2_inode *ip)
++u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n)
+ {
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+ struct gfs2_alloc *al = ip->i_alloc;
+@@ -1415,77 +1475,31 @@ u64 gfs2_alloc_data(struct gfs2_inode *ip)
+ u32 goal, blk;
+ u64 block;
+
+- if (rgrp_contains_block(rgd, ip->i_di.di_goal_data))
+- goal = ip->i_di.di_goal_data - rgd->rd_data0;
++ if (rgrp_contains_block(rgd, ip->i_goal))
++ goal = ip->i_goal - rgd->rd_data0;
+ else
+- goal = rgd->rd_last_alloc_data;
++ goal = rgd->rd_last_alloc;
+
+- blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED);
++ blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED, n);
+ BUG_ON(blk == BFITNOENT);
+- rgd->rd_last_alloc_data = blk;
+
++ rgd->rd_last_alloc = blk;
+ block = rgd->rd_data0 + blk;
+- ip->i_di.di_goal_data = block;
++ ip->i_goal = block;
+
+- gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free);
+- rgd->rd_rg.rg_free--;
++ gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free >= *n);
++ rgd->rd_rg.rg_free -= *n;
+
+ gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
+- gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data);
++ gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
+
+- al->al_alloced++;
++ al->al_alloced += *n;
+
+- gfs2_statfs_change(sdp, 0, -1, 0);
+- gfs2_quota_change(ip, +1, ip->i_inode.i_uid, ip->i_inode.i_gid);
++ gfs2_statfs_change(sdp, 0, -*n, 0);
++ gfs2_quota_change(ip, *n, ip->i_inode.i_uid, ip->i_inode.i_gid);
+
+ spin_lock(&sdp->sd_rindex_spin);
+- rgd->rd_free_clone--;
+- spin_unlock(&sdp->sd_rindex_spin);
+-
+- return block;
+-}
+-
+-/**
+- * gfs2_alloc_meta - Allocate a metadata block
+- * @ip: the inode to allocate the metadata block for
+- *
+- * Returns: the allocated block
+- */
+-
+-u64 gfs2_alloc_meta(struct gfs2_inode *ip)
+-{
+- struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+- struct gfs2_alloc *al = ip->i_alloc;
+- struct gfs2_rgrpd *rgd = al->al_rgd;
+- u32 goal, blk;
+- u64 block;
+-
+- if (rgrp_contains_block(rgd, ip->i_di.di_goal_meta))
+- goal = ip->i_di.di_goal_meta - rgd->rd_data0;
+- else
+- goal = rgd->rd_last_alloc_meta;
+-
+- blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED);
+- BUG_ON(blk == BFITNOENT);
+- rgd->rd_last_alloc_meta = blk;
+-
+- block = rgd->rd_data0 + blk;
+- ip->i_di.di_goal_meta = block;
+-
+- gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free);
+- rgd->rd_rg.rg_free--;
+-
+- gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
+- gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data);
+-
+- al->al_alloced++;
+-
+- gfs2_statfs_change(sdp, 0, -1, 0);
+- gfs2_quota_change(ip, +1, ip->i_inode.i_uid, ip->i_inode.i_gid);
+- gfs2_trans_add_unrevoke(sdp, block);
+-
+- spin_lock(&sdp->sd_rindex_spin);
+- rgd->rd_free_clone--;
++ rgd->rd_free_clone -= *n;
+ spin_unlock(&sdp->sd_rindex_spin);
+
+ return block;
+@@ -1505,12 +1519,13 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation)
+ struct gfs2_rgrpd *rgd = al->al_rgd;
+ u32 blk;
+ u64 block;
++ unsigned int n = 1;
+
+- blk = rgblk_search(rgd, rgd->rd_last_alloc_meta,
+- GFS2_BLKST_FREE, GFS2_BLKST_DINODE);
++ blk = rgblk_search(rgd, rgd->rd_last_alloc,
++ GFS2_BLKST_FREE, GFS2_BLKST_DINODE, &n);
+ BUG_ON(blk == BFITNOENT);
+
+- rgd->rd_last_alloc_meta = blk;
++ rgd->rd_last_alloc = blk;
+
+ block = rgd->rd_data0 + blk;
+
+@@ -1519,12 +1534,12 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation)
+ rgd->rd_rg.rg_dinodes++;
+ *generation = rgd->rd_rg.rg_igeneration++;
+ gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
+- gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data);
++ gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
+
+ al->al_alloced++;
+
+ gfs2_statfs_change(sdp, 0, -1, +1);
+- gfs2_trans_add_unrevoke(sdp, block);
++ gfs2_trans_add_unrevoke(sdp, block, 1);
+
+ spin_lock(&sdp->sd_rindex_spin);
+ rgd->rd_free_clone--;
+@@ -1553,7 +1568,7 @@ void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
+ rgd->rd_rg.rg_free += blen;
+
+ gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
+- gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data);
++ gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
+
+ gfs2_trans_add_rg(rgd);
+
+@@ -1581,7 +1596,7 @@ void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen)
+ rgd->rd_rg.rg_free += blen;
+
+ gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
+- gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data);
++ gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
+
+ gfs2_trans_add_rg(rgd);
+
+@@ -1601,7 +1616,7 @@ void gfs2_unlink_di(struct inode *inode)
+ if (!rgd)
+ return;
+ gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
+- gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data);
++ gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
+ gfs2_trans_add_rg(rgd);
+ }
+
+@@ -1621,7 +1636,7 @@ static void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, u64 blkno)
+ rgd->rd_rg.rg_free++;
+
+ gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
+- gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data);
++ gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
+
+ gfs2_statfs_change(sdp, 0, +1, -1);
+ gfs2_trans_add_rg(rgd);
+@@ -1699,8 +1714,7 @@ void gfs2_rlist_add(struct gfs2_sbd *sdp, struct gfs2_rgrp_list *rlist,
+ *
+ */
+
+-void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state,
+- int flags)
++void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state)
+ {
+ unsigned int x;
+
+@@ -1708,7 +1722,7 @@ void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state,
+ GFP_NOFS | __GFP_NOFAIL);
+ for (x = 0; x < rlist->rl_rgrps; x++)
+ gfs2_holder_init(rlist->rl_rgd[x]->rd_gl,
+- state, flags,
++ state, 0,
+ &rlist->rl_ghs[x]);
+ }
+
+diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h
+index 149bb16..3181c7e 100644
+--- a/fs/gfs2/rgrp.h
++++ b/fs/gfs2/rgrp.h
+@@ -1,6 +1,6 @@
+ /*
+ * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
+- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
++ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+@@ -46,8 +46,7 @@ void gfs2_inplace_release(struct gfs2_inode *ip);
+
+ unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block);
+
+-u64 gfs2_alloc_data(struct gfs2_inode *ip);
+-u64 gfs2_alloc_meta(struct gfs2_inode *ip);
++u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n);
+ u64 gfs2_alloc_di(struct gfs2_inode *ip, u64 *generation);
+
+ void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen);
+@@ -64,8 +63,7 @@ struct gfs2_rgrp_list {
+
+ void gfs2_rlist_add(struct gfs2_sbd *sdp, struct gfs2_rgrp_list *rlist,
+ u64 block);
+-void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state,
+- int flags);
++void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state);
+ void gfs2_rlist_free(struct gfs2_rgrp_list *rlist);
+ u64 gfs2_ri_total(struct gfs2_sbd *sdp);
+
+diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
+index ef0562c..7aeacbc 100644
+--- a/fs/gfs2/super.c
++++ b/fs/gfs2/super.c
+@@ -210,7 +210,7 @@ int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector)
+ struct page *page;
+ struct bio *bio;
+
+- page = alloc_page(GFP_KERNEL);
++ page = alloc_page(GFP_NOFS);
+ if (unlikely(!page))
+ return -ENOBUFS;
+
+@@ -218,7 +218,7 @@ int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector)
+ ClearPageDirty(page);
+ lock_page(page);
+
+- bio = bio_alloc(GFP_KERNEL, 1);
++ bio = bio_alloc(GFP_NOFS, 1);
+ if (unlikely(!bio)) {
+ __free_page(page);
+ return -ENOBUFS;
+@@ -316,6 +316,7 @@ int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent)
+ sdp->sd_heightsize[x] = space;
+ }
+ sdp->sd_max_height = x;
++ sdp->sd_heightsize[x] = ~0;
+ gfs2_assert(sdp, sdp->sd_max_height <= GFS2_MAX_META_HEIGHT);
+
+ sdp->sd_jheightsize[0] = sdp->sd_sb.sb_bsize -
+@@ -334,6 +335,7 @@ int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent)
+ sdp->sd_jheightsize[x] = space;
+ }
+ sdp->sd_max_jheight = x;
++ sdp->sd_jheightsize[x] = ~0;
+ gfs2_assert(sdp, sdp->sd_max_jheight <= GFS2_MAX_META_HEIGHT);
+
+ return 0;
+diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h
+index 60a870e..44361ec 100644
+--- a/fs/gfs2/super.h
++++ b/fs/gfs2/super.h
+@@ -17,6 +17,7 @@ void gfs2_tune_init(struct gfs2_tune *gt);
+ int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent);
+ int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent);
+ int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector);
++void gfs2_lm_unmount(struct gfs2_sbd *sdp);
+
+ static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp)
+ {
+diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c
+index eaa3b7b..9ab9fc8 100644
+--- a/fs/gfs2/sys.c
++++ b/fs/gfs2/sys.c
+@@ -20,7 +20,6 @@
+
+ #include "gfs2.h"
+ #include "incore.h"
+-#include "lm.h"
+ #include "sys.h"
+ #include "super.h"
+ #include "glock.h"
+@@ -328,15 +327,9 @@ static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf) \
+ } \
+ static struct counters_attr counters_attr_##name = __ATTR_RO(name)
+
+-COUNTERS_ATTR(glock_count, "%u\n");
+-COUNTERS_ATTR(glock_held_count, "%u\n");
+-COUNTERS_ATTR(inode_count, "%u\n");
+ COUNTERS_ATTR(reclaimed, "%u\n");
+
+ static struct attribute *counters_attrs[] = {
+- &counters_attr_glock_count.attr,
+- &counters_attr_glock_held_count.attr,
+- &counters_attr_inode_count.attr,
+ &counters_attr_reclaimed.attr,
+ NULL,
+ };
+diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c
+index 73e5d92..f677b8a 100644
+--- a/fs/gfs2/trans.c
++++ b/fs/gfs2/trans.c
+@@ -146,30 +146,25 @@ void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
+ lops_add(sdp, &bd->bd_le);
+ }
+
+-void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno)
++void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len)
+ {
+- struct gfs2_bufdata *bd;
+- int found = 0;
++ struct gfs2_bufdata *bd, *tmp;
++ struct gfs2_trans *tr = current->journal_info;
++ unsigned int n = len;
+
+ gfs2_log_lock(sdp);
+-
+- list_for_each_entry(bd, &sdp->sd_log_le_revoke, bd_le.le_list) {
+- if (bd->bd_blkno == blkno) {
++ list_for_each_entry_safe(bd, tmp, &sdp->sd_log_le_revoke, bd_le.le_list) {
++ if ((bd->bd_blkno >= blkno) && (bd->bd_blkno < (blkno + len))) {
+ list_del_init(&bd->bd_le.le_list);
+ gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke);
+ sdp->sd_log_num_revoke--;
+- found = 1;
+- break;
++ kmem_cache_free(gfs2_bufdata_cachep, bd);
++ tr->tr_num_revoke_rm++;
++ if (--n == 0)
++ break;
+ }
+ }
+-
+ gfs2_log_unlock(sdp);
+-
+- if (found) {
+- struct gfs2_trans *tr = current->journal_info;
+- kmem_cache_free(gfs2_bufdata_cachep, bd);
+- tr->tr_num_revoke_rm++;
+- }
+ }
+
+ void gfs2_trans_add_rg(struct gfs2_rgrpd *rgd)
+diff --git a/fs/gfs2/trans.h b/fs/gfs2/trans.h
+index e826f0d..edf9d4b 100644
+--- a/fs/gfs2/trans.h
++++ b/fs/gfs2/trans.h
+@@ -32,7 +32,7 @@ void gfs2_trans_end(struct gfs2_sbd *sdp);
+
+ void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta);
+ void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd);
+-void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno);
++void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len);
+ void gfs2_trans_add_rg(struct gfs2_rgrpd *rgd);
+
+ #endif /* __TRANS_DOT_H__ */
+diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c
+index 424a077..d31e355 100644
+--- a/fs/gfs2/util.c
++++ b/fs/gfs2/util.c
+@@ -19,12 +19,12 @@
+ #include "gfs2.h"
+ #include "incore.h"
+ #include "glock.h"
+-#include "lm.h"
+ #include "util.h"
+
+ struct kmem_cache *gfs2_glock_cachep __read_mostly;
+ struct kmem_cache *gfs2_inode_cachep __read_mostly;
+ struct kmem_cache *gfs2_bufdata_cachep __read_mostly;
++struct kmem_cache *gfs2_rgrpd_cachep __read_mostly;
+
+ void gfs2_assert_i(struct gfs2_sbd *sdp)
+ {
+@@ -32,6 +32,28 @@ void gfs2_assert_i(struct gfs2_sbd *sdp)
+ sdp->sd_fsname);
+ }
+
++int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...)
++{
++ va_list args;
++
++ if (test_and_set_bit(SDF_SHUTDOWN, &sdp->sd_flags))
++ return 0;
++
++ va_start(args, fmt);
++ vprintk(fmt, args);
++ va_end(args);
++
++ fs_err(sdp, "about to withdraw this file system\n");
++ BUG_ON(sdp->sd_args.ar_debug);
++
++ fs_err(sdp, "telling LM to withdraw\n");
++ gfs2_withdraw_lockproto(&sdp->sd_lockstruct);
++ fs_err(sdp, "withdrawn\n");
++ dump_stack();
++
++ return -1;
++}
++
+ /**
+ * gfs2_assert_withdraw_i - Cause the machine to withdraw if @assertion is false
+ * Returns: -1 if this call withdrew the machine,
+diff --git a/fs/gfs2/util.h b/fs/gfs2/util.h
+index 28938a4..509c5d6 100644
+--- a/fs/gfs2/util.h
++++ b/fs/gfs2/util.h
+@@ -147,6 +147,7 @@ gfs2_io_error_bh_i((sdp), (bh), __FUNCTION__, __FILE__, __LINE__);
+ extern struct kmem_cache *gfs2_glock_cachep;
+ extern struct kmem_cache *gfs2_inode_cachep;
+ extern struct kmem_cache *gfs2_bufdata_cachep;
++extern struct kmem_cache *gfs2_rgrpd_cachep;
+
+ static inline unsigned int gfs2_tune_get_i(struct gfs2_tune *gt,
+ unsigned int *p)
+@@ -163,6 +164,7 @@ gfs2_tune_get_i(&(sdp)->sd_tune, &(sdp)->sd_tune.field)
+
+ void gfs2_icbit_munge(struct gfs2_sbd *sdp, unsigned char **bitmap,
+ unsigned int bit, int new_value);
++int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...);
+
+ #endif /* __UTIL_DOT_H__ */
+
+diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c
+index b60c0af..f457d2c 100644
+--- a/fs/hfsplus/ioctl.c
++++ b/fs/hfsplus/ioctl.c
+@@ -14,6 +14,7 @@
+
+ #include <linux/capability.h>
+ #include <linux/fs.h>
++#include <linux/mount.h>
+ #include <linux/sched.h>
+ #include <linux/xattr.h>
+ #include <asm/uaccess.h>
+@@ -35,25 +36,32 @@ int hfsplus_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+ flags |= FS_NODUMP_FL; /* EXT2_NODUMP_FL */
+ return put_user(flags, (int __user *)arg);
+ case HFSPLUS_IOC_EXT2_SETFLAGS: {
+- if (IS_RDONLY(inode))
+- return -EROFS;
+-
+- if (!is_owner_or_cap(inode))
+- return -EACCES;
+-
+- if (get_user(flags, (int __user *)arg))
+- return -EFAULT;
+-
++ int err = 0;
++ err = mnt_want_write(filp->f_path.mnt);
++ if (err)
++ return err;
++
++ if (!is_owner_or_cap(inode)) {
++ err = -EACCES;
++ goto setflags_out;
++ }
++ if (get_user(flags, (int __user *)arg)) {
++ err = -EFAULT;
++ goto setflags_out;
++ }
+ if (flags & (FS_IMMUTABLE_FL|FS_APPEND_FL) ||
+ HFSPLUS_I(inode).rootflags & (HFSPLUS_FLG_IMMUTABLE|HFSPLUS_FLG_APPEND)) {
+- if (!capable(CAP_LINUX_IMMUTABLE))
+- return -EPERM;
++ if (!capable(CAP_LINUX_IMMUTABLE)) {
++ err = -EPERM;
++ goto setflags_out;
++ }
+ }
+
+ /* don't silently ignore unsupported ext2 flags */
+- if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL))
+- return -EOPNOTSUPP;
+-
++ if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) {
++ err = -EOPNOTSUPP;
++ goto setflags_out;
++ }
+ if (flags & FS_IMMUTABLE_FL) { /* EXT2_IMMUTABLE_FL */
+ inode->i_flags |= S_IMMUTABLE;
+ HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_IMMUTABLE;
+@@ -75,7 +83,9 @@ int hfsplus_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+
+ inode->i_ctime = CURRENT_TIME_SEC;
+ mark_inode_dirty(inode);
+- return 0;
++setflags_out:
++ mnt_drop_write(filp->f_path.mnt);
++ return err;
+ }
+ default:
+ return -ENOTTY;
+diff --git a/fs/inode.c b/fs/inode.c
+index 53245ff..27ee1af 100644
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -1199,42 +1199,37 @@ void touch_atime(struct vfsmount *mnt, struct dentry *dentry)
+ struct inode *inode = dentry->d_inode;
+ struct timespec now;
+
+- if (inode->i_flags & S_NOATIME)
++ if (mnt_want_write(mnt))
+ return;
++ if (inode->i_flags & S_NOATIME)
++ goto out;
+ if (IS_NOATIME(inode))
+- return;
++ goto out;
+ if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode))
+- return;
++ goto out;
+
+- /*
+- * We may have a NULL vfsmount when coming from NFSD
+- */
+- if (mnt) {
+- if (mnt->mnt_flags & MNT_NOATIME)
+- return;
+- if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))
+- return;
+-
+- if (mnt->mnt_flags & MNT_RELATIME) {
+- /*
+- * With relative atime, only update atime if the
+- * previous atime is earlier than either the ctime or
+- * mtime.
+- */
+- if (timespec_compare(&inode->i_mtime,
+- &inode->i_atime) < 0 &&
+- timespec_compare(&inode->i_ctime,
+- &inode->i_atime) < 0)
+- return;
+- }
++ if (mnt->mnt_flags & MNT_NOATIME)
++ goto out;
++ if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))
++ goto out;
++ if (mnt->mnt_flags & MNT_RELATIME) {
++ /*
++ * With relative atime, only update atime if the previous
++ * atime is earlier than either the ctime or mtime.
++ */
++ if (timespec_compare(&inode->i_mtime, &inode->i_atime) < 0 &&
++ timespec_compare(&inode->i_ctime, &inode->i_atime) < 0)
++ goto out;
+ }
+
+ now = current_fs_time(inode->i_sb);
+ if (timespec_equal(&inode->i_atime, &now))
+- return;
++ goto out;
+
+ inode->i_atime = now;
+ mark_inode_dirty_sync(inode);
++out:
++ mnt_drop_write(mnt);
+ }
+ EXPORT_SYMBOL(touch_atime);
+
+@@ -1255,10 +1250,13 @@ void file_update_time(struct file *file)
+ struct inode *inode = file->f_path.dentry->d_inode;
+ struct timespec now;
+ int sync_it = 0;
++ int err;
+
+ if (IS_NOCMTIME(inode))
+ return;
+- if (IS_RDONLY(inode))
++
++ err = mnt_want_write(file->f_path.mnt);
++ if (err)
+ return;
+
+ now = current_fs_time(inode->i_sb);
+@@ -1279,6 +1277,7 @@ void file_update_time(struct file *file)
+
+ if (sync_it)
+ mark_inode_dirty_sync(inode);
++ mnt_drop_write(file->f_path.mnt);
+ }
+
+ EXPORT_SYMBOL(file_update_time);
+diff --git a/fs/internal.h b/fs/internal.h
+index 392e8cc..80aa9a0 100644
+--- a/fs/internal.h
++++ b/fs/internal.h
+@@ -43,3 +43,14 @@ extern void __init chrdev_init(void);
+ * namespace.c
+ */
+ extern int copy_mount_options(const void __user *, unsigned long *);
++
++extern void free_vfsmnt(struct vfsmount *);
++extern struct vfsmount *alloc_vfsmnt(const char *);
++extern struct vfsmount *__lookup_mnt(struct vfsmount *, struct dentry *, int);
++extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
++ struct vfsmount *);
++extern void release_mounts(struct list_head *);
++extern void umount_tree(struct vfsmount *, int, struct list_head *);
++extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int);
++
++extern void __init mnt_init(void);
+diff --git a/fs/jffs2/README.Locking b/fs/jffs2/README.Locking
+index d14d5a4..3ea3655 100644
+--- a/fs/jffs2/README.Locking
++++ b/fs/jffs2/README.Locking
+@@ -14,7 +14,7 @@ be fairly close.
+ alloc_sem
+ ---------
+
+-The alloc_sem is a per-filesystem semaphore, used primarily to ensure
++The alloc_sem is a per-filesystem mutex, used primarily to ensure
+ contiguous allocation of space on the medium. It is automatically
+ obtained during space allocations (jffs2_reserve_space()) and freed
+ upon write completion (jffs2_complete_reservation()). Note that
+@@ -41,10 +41,10 @@ if the wbuf is currently holding any data is permitted, though.
+ Ordering constraints: See f->sem.
+
+
+- File Semaphore f->sem
++ File Mutex f->sem
+ ---------------------
+
+-This is the JFFS2-internal equivalent of the inode semaphore i->i_sem.
++This is the JFFS2-internal equivalent of the inode mutex i->i_sem.
+ It protects the contents of the jffs2_inode_info private inode data,
+ including the linked list of node fragments (but see the notes below on
+ erase_completion_lock), etc.
+@@ -60,14 +60,14 @@ lead to deadlock, unless we played games with unlocking the i_sem
+ before calling the space allocation functions.
+
+ Instead of playing such games, we just have an extra internal
+-semaphore, which is obtained by the garbage collection code and also
++mutex, which is obtained by the garbage collection code and also
+ by the normal file system code _after_ allocation of space.
+
+ Ordering constraints:
+
+ 1. Never attempt to allocate space or lock alloc_sem with
+ any f->sem held.
+- 2. Never attempt to lock two file semaphores in one thread.
++ 2. Never attempt to lock two file mutexes in one thread.
+ No ordering rules have been made for doing so.
+
+
+@@ -86,8 +86,8 @@ a simple spin_lock() rather than spin_lock_bh().
+
+ Note that the per-inode list of physical nodes (f->nodes) is a special
+ case. Any changes to _valid_ nodes (i.e. ->flash_offset & 1 == 0) in
+-the list are protected by the file semaphore f->sem. But the erase
+-code may remove _obsolete_ nodes from the list while holding only the
++the list are protected by the file mutex f->sem. But the erase code
++may remove _obsolete_ nodes from the list while holding only the
+ erase_completion_lock. So you can walk the list only while holding the
+ erase_completion_lock, and can drop the lock temporarily mid-walk as
+ long as the pointer you're holding is to a _valid_ node, not an
+@@ -124,10 +124,10 @@ Ordering constraints:
+ erase_free_sem
+ --------------
+
+-This semaphore is only used by the erase code which frees obsolete
+-node references and the jffs2_garbage_collect_deletion_dirent()
+-function. The latter function on NAND flash must read _obsolete_ nodes
+-to determine whether the 'deletion dirent' under consideration can be
++This mutex is only used by the erase code which frees obsolete node
++references and the jffs2_garbage_collect_deletion_dirent() function.
++The latter function on NAND flash must read _obsolete_ nodes to
++determine whether the 'deletion dirent' under consideration can be
+ discarded or whether it is still required to show that an inode has
+ been unlinked. Because reading from the flash may sleep, the
+ erase_completion_lock cannot be held, so an alternative, more
+diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c
+index 722a6b6..d58f845 100644
+--- a/fs/jffs2/build.c
++++ b/fs/jffs2/build.c
+@@ -345,6 +345,7 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c)
+ INIT_LIST_HEAD(&c->dirty_list);
+ INIT_LIST_HEAD(&c->erasable_list);
+ INIT_LIST_HEAD(&c->erasing_list);
++ INIT_LIST_HEAD(&c->erase_checking_list);
+ INIT_LIST_HEAD(&c->erase_pending_list);
+ INIT_LIST_HEAD(&c->erasable_pending_wbuf_list);
+ INIT_LIST_HEAD(&c->erase_complete_list);
+diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c
+index 3a32c64..5544d31 100644
+--- a/fs/jffs2/debug.c
++++ b/fs/jffs2/debug.c
+@@ -62,9 +62,9 @@ __jffs2_dbg_acct_sanity_check(struct jffs2_sb_info *c,
+ void
+ __jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f)
+ {
+- down(&f->sem);
++ mutex_lock(&f->sem);
+ __jffs2_dbg_fragtree_paranoia_check_nolock(f);
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ }
+
+ void
+@@ -153,6 +153,139 @@ __jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c,
+ kfree(buf);
+ }
+
++void __jffs2_dbg_superblock_counts(struct jffs2_sb_info *c)
++{
++ struct jffs2_eraseblock *jeb;
++ uint32_t free = 0, dirty = 0, used = 0, wasted = 0,
++ erasing = 0, bad = 0, unchecked = 0;
++ int nr_counted = 0;
++ int dump = 0;
++
++ if (c->gcblock) {
++ nr_counted++;
++ free += c->gcblock->free_size;
++ dirty += c->gcblock->dirty_size;
++ used += c->gcblock->used_size;
++ wasted += c->gcblock->wasted_size;
++ unchecked += c->gcblock->unchecked_size;
++ }
++ if (c->nextblock) {
++ nr_counted++;
++ free += c->nextblock->free_size;
++ dirty += c->nextblock->dirty_size;
++ used += c->nextblock->used_size;
++ wasted += c->nextblock->wasted_size;
++ unchecked += c->nextblock->unchecked_size;
++ }
++ list_for_each_entry(jeb, &c->clean_list, list) {
++ nr_counted++;
++ free += jeb->free_size;
++ dirty += jeb->dirty_size;
++ used += jeb->used_size;
++ wasted += jeb->wasted_size;
++ unchecked += jeb->unchecked_size;
++ }
++ list_for_each_entry(jeb, &c->very_dirty_list, list) {
++ nr_counted++;
++ free += jeb->free_size;
++ dirty += jeb->dirty_size;
++ used += jeb->used_size;
++ wasted += jeb->wasted_size;
++ unchecked += jeb->unchecked_size;
++ }
++ list_for_each_entry(jeb, &c->dirty_list, list) {
++ nr_counted++;
++ free += jeb->free_size;
++ dirty += jeb->dirty_size;
++ used += jeb->used_size;
++ wasted += jeb->wasted_size;
++ unchecked += jeb->unchecked_size;
++ }
++ list_for_each_entry(jeb, &c->erasable_list, list) {
++ nr_counted++;
++ free += jeb->free_size;
++ dirty += jeb->dirty_size;
++ used += jeb->used_size;
++ wasted += jeb->wasted_size;
++ unchecked += jeb->unchecked_size;
++ }
++ list_for_each_entry(jeb, &c->erasable_pending_wbuf_list, list) {
++ nr_counted++;
++ free += jeb->free_size;
++ dirty += jeb->dirty_size;
++ used += jeb->used_size;
++ wasted += jeb->wasted_size;
++ unchecked += jeb->unchecked_size;
++ }
++ list_for_each_entry(jeb, &c->erase_pending_list, list) {
++ nr_counted++;
++ free += jeb->free_size;
++ dirty += jeb->dirty_size;
++ used += jeb->used_size;
++ wasted += jeb->wasted_size;
++ unchecked += jeb->unchecked_size;
++ }
++ list_for_each_entry(jeb, &c->free_list, list) {
++ nr_counted++;
++ free += jeb->free_size;
++ dirty += jeb->dirty_size;
++ used += jeb->used_size;
++ wasted += jeb->wasted_size;
++ unchecked += jeb->unchecked_size;
++ }
++ list_for_each_entry(jeb, &c->bad_used_list, list) {
++ nr_counted++;
++ free += jeb->free_size;
++ dirty += jeb->dirty_size;
++ used += jeb->used_size;
++ wasted += jeb->wasted_size;
++ unchecked += jeb->unchecked_size;
++ }
++
++ list_for_each_entry(jeb, &c->erasing_list, list) {
++ nr_counted++;
++ erasing += c->sector_size;
++ }
++ list_for_each_entry(jeb, &c->erase_checking_list, list) {
++ nr_counted++;
++ erasing += c->sector_size;
++ }
++ list_for_each_entry(jeb, &c->erase_complete_list, list) {
++ nr_counted++;
++ erasing += c->sector_size;
++ }
++ list_for_each_entry(jeb, &c->bad_list, list) {
++ nr_counted++;
++ bad += c->sector_size;
++ }
++
++#define check(sz) \
++ if (sz != c->sz##_size) { \
++ printk(KERN_WARNING #sz "_size mismatch counted 0x%x, c->" #sz "_size 0x%x\n", \
++ sz, c->sz##_size); \
++ dump = 1; \
++ }
++ check(free);
++ check(dirty);
++ check(used);
++ check(wasted);
++ check(unchecked);
++ check(bad);
++ check(erasing);
++#undef check
++
++ if (nr_counted != c->nr_blocks) {
++ printk(KERN_WARNING "%s counted only 0x%x blocks of 0x%x. Where are the others?\n",
++ __func__, nr_counted, c->nr_blocks);
++ dump = 1;
++ }
++
++ if (dump) {
++ __jffs2_dbg_dump_block_lists_nolock(c);
++ BUG();
++ }
++}
++
+ /*
+ * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'.
+ */
+@@ -229,6 +362,9 @@ __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
+ }
+ #endif
+
++ if (!(c->flags & (JFFS2_SB_FLAG_BUILDING|JFFS2_SB_FLAG_SCANNING)))
++ __jffs2_dbg_superblock_counts(c);
++
+ return;
+
+ error:
+@@ -268,7 +404,10 @@ __jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c,
+
+ printk(JFFS2_DBG);
+ for (ref = jeb->first_node; ; ref = ref_next(ref)) {
+- printk("%#08x(%#x)", ref_offset(ref), ref->__totlen);
++ printk("%#08x", ref_offset(ref));
++#ifdef TEST_TOTLEN
++ printk("(%x)", ref->__totlen);
++#endif
+ if (ref_next(ref))
+ printk("->");
+ else
+@@ -447,6 +586,21 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
+ }
+ }
+ }
++ if (list_empty(&c->erase_checking_list)) {
++ printk(JFFS2_DBG "erase_checking_list: empty\n");
++ } else {
++ struct list_head *this;
++
++ list_for_each(this, &c->erase_checking_list) {
++ struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
++
++ if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
++ printk(JFFS2_DBG "erase_checking_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
++ jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
++ jeb->unchecked_size, jeb->free_size);
++ }
++ }
++ }
+
+ if (list_empty(&c->erase_pending_list)) {
+ printk(JFFS2_DBG "erase_pending_list: empty\n");
+@@ -532,9 +686,9 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
+ void
+ __jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
+ {
+- down(&f->sem);
++ mutex_lock(&f->sem);
+ jffs2_dbg_dump_fragtree_nolock(f);
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ }
+
+ void
+diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h
+index 4130ada..9645275 100644
+--- a/fs/jffs2/debug.h
++++ b/fs/jffs2/debug.h
+@@ -38,6 +38,7 @@
+
+ #if CONFIG_JFFS2_FS_DEBUG > 1
+ #define JFFS2_DBG_FRAGTREE2_MESSAGES
++#define JFFS2_DBG_READINODE2_MESSAGES
+ #define JFFS2_DBG_MEMALLOC_MESSAGES
+ #endif
+
+@@ -115,6 +116,11 @@
+ #else
+ #define dbg_readinode(fmt, ...)
+ #endif
++#ifdef JFFS2_DBG_READINODE2_MESSAGES
++#define dbg_readinode2(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__)
++#else
++#define dbg_readinode2(fmt, ...)
++#endif
+
+ /* Fragtree build debugging messages */
+ #ifdef JFFS2_DBG_FRAGTREE_MESSAGES
+diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
+index f948f7e..c63e7a9 100644
+--- a/fs/jffs2/dir.c
++++ b/fs/jffs2/dir.c
+@@ -86,7 +86,7 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target,
+ dir_f = JFFS2_INODE_INFO(dir_i);
+ c = JFFS2_SB_INFO(dir_i->i_sb);
+
+- down(&dir_f->sem);
++ mutex_lock(&dir_f->sem);
+
+ /* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */
+ for (fd_list = dir_f->dents; fd_list && fd_list->nhash <= target->d_name.hash; fd_list = fd_list->next) {
+@@ -99,7 +99,7 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target,
+ }
+ if (fd)
+ ino = fd->ino;
+- up(&dir_f->sem);
++ mutex_unlock(&dir_f->sem);
+ if (ino) {
+ inode = jffs2_iget(dir_i->i_sb, ino);
+ if (IS_ERR(inode)) {
+@@ -146,7 +146,7 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ }
+
+ curofs=1;
+- down(&f->sem);
++ mutex_lock(&f->sem);
+ for (fd = f->dents; fd; fd = fd->next) {
+
+ curofs++;
+@@ -166,7 +166,7 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ break;
+ offset++;
+ }
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ out:
+ filp->f_pos = offset;
+ return 0;
+@@ -275,9 +275,9 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de
+ ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, dentry->d_name.name, dentry->d_name.len, now);
+
+ if (!ret) {
+- down(&f->sem);
++ mutex_lock(&f->sem);
+ old_dentry->d_inode->i_nlink = ++f->inocache->nlink;
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ d_instantiate(dentry, old_dentry->d_inode);
+ dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
+ atomic_inc(&old_dentry->d_inode->i_count);
+@@ -351,7 +351,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
+
+ if (IS_ERR(fn)) {
+ /* Eeek. Wave bye bye */
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ jffs2_complete_reservation(c);
+ jffs2_clear_inode(inode);
+ return PTR_ERR(fn);
+@@ -361,7 +361,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
+ f->target = kmalloc(targetlen + 1, GFP_KERNEL);
+ if (!f->target) {
+ printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1);
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ jffs2_complete_reservation(c);
+ jffs2_clear_inode(inode);
+ return -ENOMEM;
+@@ -374,7 +374,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
+ obsoleted by the first data write
+ */
+ f->metadata = fn;
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+
+ jffs2_complete_reservation(c);
+
+@@ -406,7 +406,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
+ }
+
+ dir_f = JFFS2_INODE_INFO(dir_i);
+- down(&dir_f->sem);
++ mutex_lock(&dir_f->sem);
+
+ rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+ rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
+@@ -429,7 +429,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
+ as if it were the final unlink() */
+ jffs2_complete_reservation(c);
+ jffs2_free_raw_dirent(rd);
+- up(&dir_f->sem);
++ mutex_unlock(&dir_f->sem);
+ jffs2_clear_inode(inode);
+ return PTR_ERR(fd);
+ }
+@@ -442,7 +442,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
+ one if necessary. */
+ jffs2_add_fd_to_list(c, fd, &dir_f->dents);
+
+- up(&dir_f->sem);
++ mutex_unlock(&dir_f->sem);
+ jffs2_complete_reservation(c);
+
+ d_instantiate(dentry, inode);
+@@ -507,7 +507,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
+
+ if (IS_ERR(fn)) {
+ /* Eeek. Wave bye bye */
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ jffs2_complete_reservation(c);
+ jffs2_clear_inode(inode);
+ return PTR_ERR(fn);
+@@ -516,7 +516,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
+ obsoleted by the first data write
+ */
+ f->metadata = fn;
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+
+ jffs2_complete_reservation(c);
+
+@@ -548,7 +548,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
+ }
+
+ dir_f = JFFS2_INODE_INFO(dir_i);
+- down(&dir_f->sem);
++ mutex_lock(&dir_f->sem);
+
+ rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+ rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
+@@ -571,7 +571,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
+ as if it were the final unlink() */
+ jffs2_complete_reservation(c);
+ jffs2_free_raw_dirent(rd);
+- up(&dir_f->sem);
++ mutex_unlock(&dir_f->sem);
+ jffs2_clear_inode(inode);
+ return PTR_ERR(fd);
+ }
+@@ -585,7 +585,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
+ one if necessary. */
+ jffs2_add_fd_to_list(c, fd, &dir_f->dents);
+
+- up(&dir_f->sem);
++ mutex_unlock(&dir_f->sem);
+ jffs2_complete_reservation(c);
+
+ d_instantiate(dentry, inode);
+@@ -673,7 +673,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
+
+ if (IS_ERR(fn)) {
+ /* Eeek. Wave bye bye */
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ jffs2_complete_reservation(c);
+ jffs2_clear_inode(inode);
+ return PTR_ERR(fn);
+@@ -682,7 +682,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
+ obsoleted by the first data write
+ */
+ f->metadata = fn;
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+
+ jffs2_complete_reservation(c);
+
+@@ -714,7 +714,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
+ }
+
+ dir_f = JFFS2_INODE_INFO(dir_i);
+- down(&dir_f->sem);
++ mutex_lock(&dir_f->sem);
+
+ rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+ rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
+@@ -740,7 +740,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
+ as if it were the final unlink() */
+ jffs2_complete_reservation(c);
+ jffs2_free_raw_dirent(rd);
+- up(&dir_f->sem);
++ mutex_unlock(&dir_f->sem);
+ jffs2_clear_inode(inode);
+ return PTR_ERR(fd);
+ }
+@@ -753,7 +753,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
+ one if necessary. */
+ jffs2_add_fd_to_list(c, fd, &dir_f->dents);
+
+- up(&dir_f->sem);
++ mutex_unlock(&dir_f->sem);
+ jffs2_complete_reservation(c);
+
+ d_instantiate(dentry, inode);
+@@ -780,14 +780,14 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
+ if (S_ISDIR(new_dentry->d_inode->i_mode)) {
+ struct jffs2_full_dirent *fd;
+
+- down(&victim_f->sem);
++ mutex_lock(&victim_f->sem);
+ for (fd = victim_f->dents; fd; fd = fd->next) {
+ if (fd->ino) {
+- up(&victim_f->sem);
++ mutex_unlock(&victim_f->sem);
+ return -ENOTEMPTY;
+ }
+ }
+- up(&victim_f->sem);
++ mutex_unlock(&victim_f->sem);
+ }
+ }
+
+@@ -816,9 +816,9 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
+ /* Don't oops if the victim was a dirent pointing to an
+ inode which didn't exist. */
+ if (victim_f->inocache) {
+- down(&victim_f->sem);
++ mutex_lock(&victim_f->sem);
+ victim_f->inocache->nlink--;
+- up(&victim_f->sem);
++ mutex_unlock(&victim_f->sem);
+ }
+ }
+
+@@ -836,11 +836,11 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
+ if (ret) {
+ /* Oh shit. We really ought to make a single node which can do both atomically */
+ struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode);
+- down(&f->sem);
++ mutex_lock(&f->sem);
+ inc_nlink(old_dentry->d_inode);
+ if (f->inocache)
+ f->inocache->nlink++;
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+
+ printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret);
+ /* Might as well let the VFS know */
+diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
+index a1db918..25a640e 100644
+--- a/fs/jffs2/erase.c
++++ b/fs/jffs2/erase.c
+@@ -50,14 +50,14 @@ static void jffs2_erase_block(struct jffs2_sb_info *c,
+ instr = kmalloc(sizeof(struct erase_info) + sizeof(struct erase_priv_struct), GFP_KERNEL);
+ if (!instr) {
+ printk(KERN_WARNING "kmalloc for struct erase_info in jffs2_erase_block failed. Refiling block for later\n");
+- down(&c->erase_free_sem);
++ mutex_lock(&c->erase_free_sem);
+ spin_lock(&c->erase_completion_lock);
+ list_move(&jeb->list, &c->erase_pending_list);
+ c->erasing_size -= c->sector_size;
+ c->dirty_size += c->sector_size;
+ jeb->dirty_size = c->sector_size;
+ spin_unlock(&c->erase_completion_lock);
+- up(&c->erase_free_sem);
++ mutex_unlock(&c->erase_free_sem);
+ return;
+ }
+
+@@ -84,14 +84,14 @@ static void jffs2_erase_block(struct jffs2_sb_info *c,
+ if (ret == -ENOMEM || ret == -EAGAIN) {
+ /* Erase failed immediately. Refile it on the list */
+ D1(printk(KERN_DEBUG "Erase at 0x%08x failed: %d. Refiling on erase_pending_list\n", jeb->offset, ret));
+- down(&c->erase_free_sem);
++ mutex_lock(&c->erase_free_sem);
+ spin_lock(&c->erase_completion_lock);
+ list_move(&jeb->list, &c->erase_pending_list);
+ c->erasing_size -= c->sector_size;
+ c->dirty_size += c->sector_size;
+ jeb->dirty_size = c->sector_size;
+ spin_unlock(&c->erase_completion_lock);
+- up(&c->erase_free_sem);
++ mutex_unlock(&c->erase_free_sem);
+ return;
+ }
+
+@@ -107,7 +107,7 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
+ {
+ struct jffs2_eraseblock *jeb;
+
+- down(&c->erase_free_sem);
++ mutex_lock(&c->erase_free_sem);
+
+ spin_lock(&c->erase_completion_lock);
+
+@@ -116,9 +116,9 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
+
+ if (!list_empty(&c->erase_complete_list)) {
+ jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list);
+- list_del(&jeb->list);
++ list_move(&jeb->list, &c->erase_checking_list);
+ spin_unlock(&c->erase_completion_lock);
+- up(&c->erase_free_sem);
++ mutex_unlock(&c->erase_free_sem);
+ jffs2_mark_erased_block(c, jeb);
+
+ if (!--count) {
+@@ -139,7 +139,7 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
+ jffs2_free_jeb_node_refs(c, jeb);
+ list_add(&jeb->list, &c->erasing_list);
+ spin_unlock(&c->erase_completion_lock);
+- up(&c->erase_free_sem);
++ mutex_unlock(&c->erase_free_sem);
+
+ jffs2_erase_block(c, jeb);
+
+@@ -149,12 +149,12 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
+
+ /* Be nice */
+ yield();
+- down(&c->erase_free_sem);
++ mutex_lock(&c->erase_free_sem);
+ spin_lock(&c->erase_completion_lock);
+ }
+
+ spin_unlock(&c->erase_completion_lock);
+- up(&c->erase_free_sem);
++ mutex_unlock(&c->erase_free_sem);
+ done:
+ D1(printk(KERN_DEBUG "jffs2_erase_pending_blocks completed\n"));
+ }
+@@ -162,11 +162,11 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
+ static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
+ {
+ D1(printk(KERN_DEBUG "Erase completed successfully at 0x%08x\n", jeb->offset));
+- down(&c->erase_free_sem);
++ mutex_lock(&c->erase_free_sem);
+ spin_lock(&c->erase_completion_lock);
+ list_move_tail(&jeb->list, &c->erase_complete_list);
+ spin_unlock(&c->erase_completion_lock);
+- up(&c->erase_free_sem);
++ mutex_unlock(&c->erase_free_sem);
+ /* Ensure that kupdated calls us again to mark them clean */
+ jffs2_erase_pending_trigger(c);
+ }
+@@ -180,26 +180,26 @@ static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock
+ failed too many times. */
+ if (!jffs2_write_nand_badblock(c, jeb, bad_offset)) {
+ /* We'd like to give this block another try. */
+- down(&c->erase_free_sem);
++ mutex_lock(&c->erase_free_sem);
+ spin_lock(&c->erase_completion_lock);
+ list_move(&jeb->list, &c->erase_pending_list);
+ c->erasing_size -= c->sector_size;
+ c->dirty_size += c->sector_size;
+ jeb->dirty_size = c->sector_size;
+ spin_unlock(&c->erase_completion_lock);
+- up(&c->erase_free_sem);
++ mutex_unlock(&c->erase_free_sem);
+ return;
+ }
+ }
+
+- down(&c->erase_free_sem);
++ mutex_lock(&c->erase_free_sem);
+ spin_lock(&c->erase_completion_lock);
+ c->erasing_size -= c->sector_size;
+ c->bad_size += c->sector_size;
+ list_move(&jeb->list, &c->bad_list);
+ c->nr_erasing_blocks--;
+ spin_unlock(&c->erase_completion_lock);
+- up(&c->erase_free_sem);
++ mutex_unlock(&c->erase_free_sem);
+ wake_up(&c->erase_wait);
+ }
+
+@@ -350,9 +350,11 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
+ break;
+ } while(--retlen);
+ c->mtd->unpoint(c->mtd, ebuf, jeb->offset, c->sector_size);
+- if (retlen)
++ if (retlen) {
+ printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08tx\n",
+ *wordebuf, jeb->offset + c->sector_size-retlen*sizeof(*wordebuf));
++ return -EIO;
++ }
+ return 0;
+ }
+ do_flash_read:
+@@ -373,10 +375,12 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
+ ret = c->mtd->read(c->mtd, ofs, readlen, &retlen, ebuf);
+ if (ret) {
+ printk(KERN_WARNING "Read of newly-erased block at 0x%08x failed: %d. Putting on bad_list\n", ofs, ret);
++ ret = -EIO;
+ goto fail;
+ }
+ if (retlen != readlen) {
+ printk(KERN_WARNING "Short read from newly-erased block at 0x%08x. Wanted %d, got %zd\n", ofs, readlen, retlen);
++ ret = -EIO;
+ goto fail;
+ }
+ for (i=0; i<readlen; i += sizeof(unsigned long)) {
+@@ -385,6 +389,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
+ if (*datum + 1) {
+ *bad_offset += i;
+ printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08x\n", *datum, *bad_offset);
++ ret = -EIO;
+ goto fail;
+ }
+ }
+@@ -419,9 +424,6 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
+ if (jffs2_write_nand_cleanmarker(c, jeb))
+ goto filebad;
+ }
+-
+- /* Everything else got zeroed before the erase */
+- jeb->free_size = c->sector_size;
+ } else {
+
+ struct kvec vecs[1];
+@@ -449,48 +451,50 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
+
+ goto filebad;
+ }
+-
+- /* Everything else got zeroed before the erase */
+- jeb->free_size = c->sector_size;
+- /* FIXME Special case for cleanmarker in empty block */
+- jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL);
+ }
++ /* Everything else got zeroed before the erase */
++ jeb->free_size = c->sector_size;
+
+- down(&c->erase_free_sem);
++ mutex_lock(&c->erase_free_sem);
+ spin_lock(&c->erase_completion_lock);
++
+ c->erasing_size -= c->sector_size;
+- c->free_size += jeb->free_size;
+- c->used_size += jeb->used_size;
++ c->free_size += c->sector_size;
+
+- jffs2_dbg_acct_sanity_check_nolock(c,jeb);
+- jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
++ /* Account for cleanmarker now, if it's in-band */
++ if (c->cleanmarker_size && !jffs2_cleanmarker_oob(c))
++ jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL);
+
+- list_add_tail(&jeb->list, &c->free_list);
++ list_move_tail(&jeb->list, &c->free_list);
+ c->nr_erasing_blocks--;
+ c->nr_free_blocks++;
++
++ jffs2_dbg_acct_sanity_check_nolock(c, jeb);
++ jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
++
+ spin_unlock(&c->erase_completion_lock);
+- up(&c->erase_free_sem);
++ mutex_unlock(&c->erase_free_sem);
+ wake_up(&c->erase_wait);
+ return;
+
+ filebad:
+- down(&c->erase_free_sem);
++ mutex_lock(&c->erase_free_sem);
+ spin_lock(&c->erase_completion_lock);
+ /* Stick it on a list (any list) so erase_failed can take it
+ right off again. Silly, but shouldn't happen often. */
+- list_add(&jeb->list, &c->erasing_list);
++ list_move(&jeb->list, &c->erasing_list);
+ spin_unlock(&c->erase_completion_lock);
+- up(&c->erase_free_sem);
++ mutex_unlock(&c->erase_free_sem);
+ jffs2_erase_failed(c, jeb, bad_offset);
+ return;
+
+ refile:
+ /* Stick it back on the list from whence it came and come back later */
+ jffs2_erase_pending_trigger(c);
+- down(&c->erase_free_sem);
++ mutex_lock(&c->erase_free_sem);
+ spin_lock(&c->erase_completion_lock);
+- list_add(&jeb->list, &c->erase_complete_list);
++ list_move(&jeb->list, &c->erase_complete_list);
+ spin_unlock(&c->erase_completion_lock);
+- up(&c->erase_free_sem);
++ mutex_unlock(&c->erase_free_sem);
+ return;
+ }
+diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
+index dcc2734..5e92034 100644
+--- a/fs/jffs2/file.c
++++ b/fs/jffs2/file.c
+@@ -115,9 +115,9 @@ static int jffs2_readpage (struct file *filp, struct page *pg)
+ struct jffs2_inode_info *f = JFFS2_INODE_INFO(pg->mapping->host);
+ int ret;
+
+- down(&f->sem);
++ mutex_lock(&f->sem);
+ ret = jffs2_do_readpage_unlock(pg->mapping->host, pg);
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ return ret;
+ }
+
+@@ -154,7 +154,7 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
+ if (ret)
+ goto out_page;
+
+- down(&f->sem);
++ mutex_lock(&f->sem);
+ memset(&ri, 0, sizeof(ri));
+
+ ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+@@ -181,7 +181,7 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
+ if (IS_ERR(fn)) {
+ ret = PTR_ERR(fn);
+ jffs2_complete_reservation(c);
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ goto out_page;
+ }
+ ret = jffs2_add_full_dnode_to_inode(c, f, fn);
+@@ -195,12 +195,12 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
+ jffs2_mark_node_obsolete(c, fn->raw);
+ jffs2_free_full_dnode(fn);
+ jffs2_complete_reservation(c);
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ goto out_page;
+ }
+ jffs2_complete_reservation(c);
+ inode->i_size = pageofs;
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ }
+
+ /*
+@@ -209,9 +209,9 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
+ * case of a short-copy.
+ */
+ if (!PageUptodate(pg)) {
+- down(&f->sem);
++ mutex_lock(&f->sem);
+ ret = jffs2_do_readpage_nolock(inode, pg);
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ if (ret)
+ goto out_page;
+ }
+diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
+index e26ea78..3eb1c84 100644
+--- a/fs/jffs2/fs.c
++++ b/fs/jffs2/fs.c
+@@ -36,6 +36,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
+ unsigned int ivalid;
+ uint32_t alloclen;
+ int ret;
++ int alloc_type = ALLOC_NORMAL;
+
+ D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino));
+
+@@ -50,20 +51,20 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
+ mdata = (char *)&dev;
+ D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen));
+ } else if (S_ISLNK(inode->i_mode)) {
+- down(&f->sem);
++ mutex_lock(&f->sem);
+ mdatalen = f->metadata->size;
+ mdata = kmalloc(f->metadata->size, GFP_USER);
+ if (!mdata) {
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ return -ENOMEM;
+ }
+ ret = jffs2_read_dnode(c, f, f->metadata, mdata, 0, mdatalen);
+ if (ret) {
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ kfree(mdata);
+ return ret;
+ }
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of symlink target\n", mdatalen));
+ }
+
+@@ -82,7 +83,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
+ kfree(mdata);
+ return ret;
+ }
+- down(&f->sem);
++ mutex_lock(&f->sem);
+ ivalid = iattr->ia_valid;
+
+ ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+@@ -115,6 +116,10 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
+ ri->compr = JFFS2_COMPR_ZERO;
+ ri->dsize = cpu_to_je32(iattr->ia_size - inode->i_size);
+ ri->offset = cpu_to_je32(inode->i_size);
++ } else if (ivalid & ATTR_SIZE && !iattr->ia_size) {
++ /* For truncate-to-zero, treat it as deletion because
++ it'll always be obsoleting all previous nodes */
++ alloc_type = ALLOC_DELETION;
+ }
+ ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
+ if (mdatalen)
+@@ -122,14 +127,14 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
+ else
+ ri->data_crc = cpu_to_je32(0);
+
+- new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, ALLOC_NORMAL);
++ new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, alloc_type);
+ if (S_ISLNK(inode->i_mode))
+ kfree(mdata);
+
+ if (IS_ERR(new_metadata)) {
+ jffs2_complete_reservation(c);
+ jffs2_free_raw_inode(ri);
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ return PTR_ERR(new_metadata);
+ }
+ /* It worked. Update the inode */
+@@ -149,6 +154,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
+ if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) {
+ jffs2_add_full_dnode_to_inode(c, f, new_metadata);
+ inode->i_size = iattr->ia_size;
++ inode->i_blocks = (inode->i_size + 511) >> 9;
+ f->metadata = NULL;
+ } else {
+ f->metadata = new_metadata;
+@@ -159,7 +165,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
+ }
+ jffs2_free_raw_inode(ri);
+
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ jffs2_complete_reservation(c);
+
+ /* We have to do the vmtruncate() without f->sem held, since
+@@ -167,8 +173,10 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
+ We are protected from a simultaneous write() extending i_size
+ back past iattr->ia_size, because do_truncate() holds the
+ generic inode semaphore. */
+- if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size)
+- vmtruncate(inode, iattr->ia_size);
++ if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) {
++ vmtruncate(inode, iattr->ia_size);
++ inode->i_blocks = (inode->i_size + 511) >> 9;
++ }
+
+ return 0;
+ }
+@@ -248,12 +256,12 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
+ c = JFFS2_SB_INFO(inode->i_sb);
+
+ jffs2_init_inode_info(f);
+- down(&f->sem);
++ mutex_lock(&f->sem);
+
+ ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node);
+
+ if (ret) {
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ iget_failed(inode);
+ return ERR_PTR(ret);
+ }
+@@ -330,7 +338,7 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
+ printk(KERN_WARNING "jffs2_read_inode(): Bogus imode %o for ino %lu\n", inode->i_mode, (unsigned long)inode->i_ino);
+ }
+
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+
+ D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n"));
+ unlock_new_inode(inode);
+@@ -339,7 +347,7 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
+ error_io:
+ ret = -EIO;
+ error:
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ jffs2_do_clear_inode(c, f);
+ iget_failed(inode);
+ return ERR_PTR(ret);
+@@ -380,9 +388,9 @@ int jffs2_remount_fs (struct super_block *sb, int *flags, char *data)
+ Flush the writebuffer, if neccecary, else we loose it */
+ if (!(sb->s_flags & MS_RDONLY)) {
+ jffs2_stop_garbage_collect_thread(c);
+- down(&c->alloc_sem);
++ mutex_lock(&c->alloc_sem);
+ jffs2_flush_wbuf_pad(c);
+- up(&c->alloc_sem);
++ mutex_unlock(&c->alloc_sem);
+ }
+
+ if (!(*flags & MS_RDONLY))
+@@ -429,7 +437,7 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i
+
+ f = JFFS2_INODE_INFO(inode);
+ jffs2_init_inode_info(f);
+- down(&f->sem);
++ mutex_lock(&f->sem);
+
+ memset(ri, 0, sizeof(*ri));
+ /* Set OS-specific defaults for new inodes */
+diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
+index 32ff037..bad0056 100644
+--- a/fs/jffs2/gc.c
++++ b/fs/jffs2/gc.c
+@@ -126,7 +126,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
+ int ret = 0, inum, nlink;
+ int xattr = 0;
+
+- if (down_interruptible(&c->alloc_sem))
++ if (mutex_lock_interruptible(&c->alloc_sem))
+ return -EINTR;
+
+ for (;;) {
+@@ -143,7 +143,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
+ c->unchecked_size);
+ jffs2_dbg_dump_block_lists_nolock(c);
+ spin_unlock(&c->erase_completion_lock);
+- up(&c->alloc_sem);
++ mutex_unlock(&c->alloc_sem);
+ return -ENOSPC;
+ }
+
+@@ -190,7 +190,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
+ made no progress in this case, but that should be OK */
+ c->checked_ino--;
+
+- up(&c->alloc_sem);
++ mutex_unlock(&c->alloc_sem);
+ sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
+ return 0;
+
+@@ -210,7 +210,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
+ printk(KERN_WARNING "Returned error for crccheck of ino #%u. Expect badness...\n", ic->ino);
+
+ jffs2_set_inocache_state(c, ic, INO_STATE_CHECKEDABSENT);
+- up(&c->alloc_sem);
++ mutex_unlock(&c->alloc_sem);
+ return ret;
+ }
+
+@@ -221,9 +221,15 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
+ jeb = jffs2_find_gc_block(c);
+
+ if (!jeb) {
+- D1 (printk(KERN_NOTICE "jffs2: Couldn't find erase block to garbage collect!\n"));
++ /* Couldn't find a free block. But maybe we can just erase one and make 'progress'? */
++ if (!list_empty(&c->erase_pending_list)) {
++ spin_unlock(&c->erase_completion_lock);
++ mutex_unlock(&c->alloc_sem);
++ return -EAGAIN;
++ }
++ D1(printk(KERN_NOTICE "jffs2: Couldn't find erase block to garbage collect!\n"));
+ spin_unlock(&c->erase_completion_lock);
+- up(&c->alloc_sem);
++ mutex_unlock(&c->alloc_sem);
+ return -EIO;
+ }
+
+@@ -232,7 +238,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
+ printk(KERN_DEBUG "Nextblock at %08x, used_size %08x, dirty_size %08x, wasted_size %08x, free_size %08x\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->wasted_size, c->nextblock->free_size));
+
+ if (!jeb->used_size) {
+- up(&c->alloc_sem);
++ mutex_unlock(&c->alloc_sem);
+ goto eraseit;
+ }
+
+@@ -248,7 +254,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
+ jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size);
+ jeb->gc_node = raw;
+ spin_unlock(&c->erase_completion_lock);
+- up(&c->alloc_sem);
++ mutex_unlock(&c->alloc_sem);
+ BUG();
+ }
+ }
+@@ -266,7 +272,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
+ /* Just mark it obsolete */
+ jffs2_mark_node_obsolete(c, raw);
+ }
+- up(&c->alloc_sem);
++ mutex_unlock(&c->alloc_sem);
+ goto eraseit_lock;
+ }
+
+@@ -334,7 +340,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
+ */
+ printk(KERN_CRIT "Inode #%u already in state %d in jffs2_garbage_collect_pass()!\n",
+ ic->ino, ic->state);
+- up(&c->alloc_sem);
++ mutex_unlock(&c->alloc_sem);
+ spin_unlock(&c->inocache_lock);
+ BUG();
+
+@@ -345,7 +351,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
+ the alloc_sem() (for marking nodes invalid) so we must
+ drop the alloc_sem before sleeping. */
+
+- up(&c->alloc_sem);
++ mutex_unlock(&c->alloc_sem);
+ D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() waiting for ino #%u in state %d\n",
+ ic->ino, ic->state));
+ sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
+@@ -416,7 +422,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
+ ret = -ENOSPC;
+ }
+ release_sem:
+- up(&c->alloc_sem);
++ mutex_unlock(&c->alloc_sem);
+
+ eraseit_lock:
+ /* If we've finished this block, start it erasing */
+@@ -445,7 +451,7 @@ static int jffs2_garbage_collect_live(struct jffs2_sb_info *c, struct jffs2_era
+ uint32_t start = 0, end = 0, nrfrags = 0;
+ int ret = 0;
+
+- down(&f->sem);
++ mutex_lock(&f->sem);
+
+ /* Now we have the lock for this inode. Check that it's still the one at the head
+ of the list. */
+@@ -525,7 +531,7 @@ static int jffs2_garbage_collect_live(struct jffs2_sb_info *c, struct jffs2_era
+ }
+ }
+ upnout:
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+
+ return ret;
+ }
+@@ -846,7 +852,7 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct
+ /* Prevent the erase code from nicking the obsolete node refs while
+ we're looking at them. I really don't like this extra lock but
+ can't see any alternative. Suggestions on a postcard to... */
+- down(&c->erase_free_sem);
++ mutex_lock(&c->erase_free_sem);
+
+ for (raw = f->inocache->nodes; raw != (void *)f->inocache; raw = raw->next_in_ino) {
+
+@@ -899,7 +905,7 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct
+ /* OK. The name really does match. There really is still an older node on
+ the flash which our deletion dirent obsoletes. So we have to write out
+ a new deletion dirent to replace it */
+- up(&c->erase_free_sem);
++ mutex_unlock(&c->erase_free_sem);
+
+ D1(printk(KERN_DEBUG "Deletion dirent at %08x still obsoletes real dirent \"%s\" at %08x for ino #%u\n",
+ ref_offset(fd->raw), fd->name, ref_offset(raw), je32_to_cpu(rd->ino)));
+@@ -908,7 +914,7 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct
+ return jffs2_garbage_collect_dirent(c, jeb, f, fd);
+ }
+
+- up(&c->erase_free_sem);
++ mutex_unlock(&c->erase_free_sem);
+ kfree(rd);
+ }
+
+@@ -1081,7 +1087,7 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras
+ return 0;
+ }
+
+-static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
++static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *orig_jeb,
+ struct jffs2_inode_info *f, struct jffs2_full_dnode *fn,
+ uint32_t start, uint32_t end)
+ {
+diff --git a/fs/jffs2/ioctl.c b/fs/jffs2/ioctl.c
+index f4d525b..e217721 100644
+--- a/fs/jffs2/ioctl.c
++++ b/fs/jffs2/ioctl.c
+@@ -10,6 +10,7 @@
+ */
+
+ #include <linux/fs.h>
++#include "nodelist.h"
+
+ int jffs2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+diff --git a/fs/jffs2/jffs2_fs_i.h b/fs/jffs2/jffs2_fs_i.h
+index 0b78fdc..31559f4 100644
+--- a/fs/jffs2/jffs2_fs_i.h
++++ b/fs/jffs2/jffs2_fs_i.h
+@@ -15,7 +15,7 @@
+ #include <linux/version.h>
+ #include <linux/rbtree.h>
+ #include <linux/posix_acl.h>
+-#include <asm/semaphore.h>
++#include <linux/mutex.h>
+
+ struct jffs2_inode_info {
+ /* We need an internal mutex similar to inode->i_mutex.
+@@ -24,7 +24,7 @@ struct jffs2_inode_info {
+ before letting GC proceed. Or we'd have to put ugliness
+ into the GC code so it didn't attempt to obtain the i_mutex
+ for the inode(s) which are already locked */
+- struct semaphore sem;
++ struct mutex sem;
+
+ /* The highest (datanode) version number used for this ino */
+ uint32_t highest_version;
+diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
+index 3a2197f..85ef6db 100644
+--- a/fs/jffs2/jffs2_fs_sb.h
++++ b/fs/jffs2/jffs2_fs_sb.h
+@@ -16,7 +16,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/workqueue.h>
+ #include <linux/completion.h>
+-#include <asm/semaphore.h>
++#include <linux/mutex.h>
+ #include <linux/timer.h>
+ #include <linux/wait.h>
+ #include <linux/list.h>
+@@ -44,7 +44,7 @@ struct jffs2_sb_info {
+ struct completion gc_thread_start; /* GC thread start completion */
+ struct completion gc_thread_exit; /* GC thread exit completion port */
+
+- struct semaphore alloc_sem; /* Used to protect all the following
++ struct mutex alloc_sem; /* Used to protect all the following
+ fields, and also to protect against
+ out-of-order writing of nodes. And GC. */
+ uint32_t cleanmarker_size; /* Size of an _inline_ CLEANMARKER
+@@ -87,6 +87,7 @@ struct jffs2_sb_info {
+ struct list_head erasable_list; /* Blocks which are completely dirty, and need erasing */
+ struct list_head erasable_pending_wbuf_list; /* Blocks which need erasing but only after the current wbuf is flushed */
+ struct list_head erasing_list; /* Blocks which are currently erasing */
++ struct list_head erase_checking_list; /* Blocks which are being checked and marked */
+ struct list_head erase_pending_list; /* Blocks which need erasing now */
+ struct list_head erase_complete_list; /* Blocks which are erased and need the clean marker written to them */
+ struct list_head free_list; /* Blocks which are free and ready to be used */
+@@ -104,7 +105,7 @@ struct jffs2_sb_info {
+ /* Sem to allow jffs2_garbage_collect_deletion_dirent to
+ drop the erase_completion_lock while it's holding a pointer
+ to an obsoleted node. I don't like this. Alternatives welcomed. */
+- struct semaphore erase_free_sem;
++ struct mutex erase_free_sem;
+
+ uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */
+
+diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
+index ec1aae9..8219df6 100644
+--- a/fs/jffs2/nodelist.h
++++ b/fs/jffs2/nodelist.h
+@@ -87,7 +87,7 @@ struct jffs2_raw_node_ref
+ xattr_ref or xattr_datum instead. The common part of those structures
+ has NULL in the first word. See jffs2_raw_ref_to_ic() below */
+ uint32_t flash_offset;
+-#define TEST_TOTLEN
++#undef TEST_TOTLEN
+ #ifdef TEST_TOTLEN
+ uint32_t __totlen; /* This may die; use ref_totlen(c, jeb, ) below */
+ #endif
+diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
+index a0313fa..9df8f3e 100644
+--- a/fs/jffs2/nodemgmt.c
++++ b/fs/jffs2/nodemgmt.c
+@@ -48,7 +48,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
+ minsize = PAD(minsize);
+
+ D1(printk(KERN_DEBUG "jffs2_reserve_space(): Requested 0x%x bytes\n", minsize));
+- down(&c->alloc_sem);
++ mutex_lock(&c->alloc_sem);
+
+ D1(printk(KERN_DEBUG "jffs2_reserve_space(): alloc sem got\n"));
+
+@@ -57,7 +57,6 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
+ /* this needs a little more thought (true <tglx> :)) */
+ while(ret == -EAGAIN) {
+ while(c->nr_free_blocks + c->nr_erasing_blocks < blocksneeded) {
+- int ret;
+ uint32_t dirty, avail;
+
+ /* calculate real dirty size
+@@ -82,7 +81,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
+ dirty, c->unchecked_size, c->sector_size));
+
+ spin_unlock(&c->erase_completion_lock);
+- up(&c->alloc_sem);
++ mutex_unlock(&c->alloc_sem);
+ return -ENOSPC;
+ }
+
+@@ -105,11 +104,11 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
+ D1(printk(KERN_DEBUG "max. available size 0x%08x < blocksneeded * sector_size 0x%08x, returning -ENOSPC\n",
+ avail, blocksneeded * c->sector_size));
+ spin_unlock(&c->erase_completion_lock);
+- up(&c->alloc_sem);
++ mutex_unlock(&c->alloc_sem);
+ return -ENOSPC;
+ }
+
+- up(&c->alloc_sem);
++ mutex_unlock(&c->alloc_sem);
+
+ D1(printk(KERN_DEBUG "Triggering GC pass. nr_free_blocks %d, nr_erasing_blocks %d, free_size 0x%08x, dirty_size 0x%08x, wasted_size 0x%08x, used_size 0x%08x, erasing_size 0x%08x, bad_size 0x%08x (total 0x%08x of 0x%08x)\n",
+ c->nr_free_blocks, c->nr_erasing_blocks, c->free_size, c->dirty_size, c->wasted_size, c->used_size, c->erasing_size, c->bad_size,
+@@ -117,7 +116,10 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
+ spin_unlock(&c->erase_completion_lock);
+
+ ret = jffs2_garbage_collect_pass(c);
+- if (ret)
++
++ if (ret == -EAGAIN)
++ jffs2_erase_pending_blocks(c, 1);
++ else if (ret)
+ return ret;
+
+ cond_resched();
+@@ -125,7 +127,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
+ if (signal_pending(current))
+ return -EINTR;
+
+- down(&c->alloc_sem);
++ mutex_lock(&c->alloc_sem);
+ spin_lock(&c->erase_completion_lock);
+ }
+
+@@ -138,7 +140,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
+ if (!ret)
+ ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
+ if (ret)
+- up(&c->alloc_sem);
++ mutex_unlock(&c->alloc_sem);
+ return ret;
+ }
+
+@@ -463,7 +465,7 @@ void jffs2_complete_reservation(struct jffs2_sb_info *c)
+ {
+ D1(printk(KERN_DEBUG "jffs2_complete_reservation()\n"));
+ jffs2_garbage_collect_trigger(c);
+- up(&c->alloc_sem);
++ mutex_unlock(&c->alloc_sem);
+ }
+
+ static inline int on_list(struct list_head *obj, struct list_head *head)
+@@ -512,7 +514,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
+ any jffs2_raw_node_refs. So we don't need to stop erases from
+ happening, or protect against people holding an obsolete
+ jffs2_raw_node_ref without the erase_completion_lock. */
+- down(&c->erase_free_sem);
++ mutex_lock(&c->erase_free_sem);
+ }
+
+ spin_lock(&c->erase_completion_lock);
+@@ -715,7 +717,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
+ }
+
+ out_erase_sem:
+- up(&c->erase_free_sem);
++ mutex_unlock(&c->erase_free_sem);
+ }
+
+ int jffs2_thread_should_wake(struct jffs2_sb_info *c)
+diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
+index e512a93..4cb4d76 100644
+--- a/fs/jffs2/readinode.c
++++ b/fs/jffs2/readinode.c
+@@ -825,8 +825,9 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
+ else // normal case...
+ tn->fn->size = je32_to_cpu(rd->dsize);
+
+- dbg_readinode("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n",
+- ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize);
++ dbg_readinode2("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n",
++ ref_offset(ref), je32_to_cpu(rd->version),
++ je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize);
+
+ ret = jffs2_add_tn_to_tree(c, rii, tn);
+
+@@ -836,13 +837,13 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
+ jffs2_free_tmp_dnode_info(tn);
+ return ret;
+ }
+-#ifdef JFFS2_DBG_READINODE_MESSAGES
+- dbg_readinode("After adding ver %d:\n", je32_to_cpu(rd->version));
++#ifdef JFFS2_DBG_READINODE2_MESSAGES
++ dbg_readinode2("After adding ver %d:\n", je32_to_cpu(rd->version));
+ tn = tn_first(&rii->tn_root);
+ while (tn) {
+- dbg_readinode("%p: v %d r 0x%x-0x%x ov %d\n",
+- tn, tn->version, tn->fn->ofs,
+- tn->fn->ofs+tn->fn->size, tn->overlapped);
++ dbg_readinode2("%p: v %d r 0x%x-0x%x ov %d\n",
++ tn, tn->version, tn->fn->ofs,
++ tn->fn->ofs+tn->fn->size, tn->overlapped);
+ tn = tn_next(tn);
+ }
+ #endif
+@@ -1193,7 +1194,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
+ JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n",
+ ret, retlen, sizeof(*latest_node));
+ /* FIXME: If this fails, there seems to be a memory leak. Find it. */
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ jffs2_do_clear_inode(c, f);
+ return ret?ret:-EIO;
+ }
+@@ -1202,7 +1203,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
+ if (crc != je32_to_cpu(latest_node->node_crc)) {
+ JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n",
+ f->inocache->ino, ref_offset(rii.latest_ref));
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ jffs2_do_clear_inode(c, f);
+ return -EIO;
+ }
+@@ -1242,7 +1243,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
+ f->target = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL);
+ if (!f->target) {
+ JFFS2_ERROR("can't allocate %d bytes of memory for the symlink target path cache\n", je32_to_cpu(latest_node->csize));
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ jffs2_do_clear_inode(c, f);
+ return -ENOMEM;
+ }
+@@ -1255,7 +1256,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
+ ret = -EIO;
+ kfree(f->target);
+ f->target = NULL;
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ jffs2_do_clear_inode(c, f);
+ return -ret;
+ }
+@@ -1273,14 +1274,14 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
+ if (f->metadata) {
+ JFFS2_ERROR("Argh. Special inode #%u with mode 0%o had metadata node\n",
+ f->inocache->ino, jemode_to_cpu(latest_node->mode));
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ jffs2_do_clear_inode(c, f);
+ return -EIO;
+ }
+ if (!frag_first(&f->fragtree)) {
+ JFFS2_ERROR("Argh. Special inode #%u with mode 0%o has no fragments\n",
+ f->inocache->ino, jemode_to_cpu(latest_node->mode));
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ jffs2_do_clear_inode(c, f);
+ return -EIO;
+ }
+@@ -1289,7 +1290,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
+ JFFS2_ERROR("Argh. Special inode #%u with mode 0x%x had more than one node\n",
+ f->inocache->ino, jemode_to_cpu(latest_node->mode));
+ /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ jffs2_do_clear_inode(c, f);
+ return -EIO;
+ }
+@@ -1379,12 +1380,13 @@ int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *i
+ if (!f)
+ return -ENOMEM;
+
+- init_MUTEX_LOCKED(&f->sem);
++ mutex_init(&f->sem);
++ mutex_lock(&f->sem);
+ f->inocache = ic;
+
+ ret = jffs2_do_read_inode_internal(c, f, &n);
+ if (!ret) {
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ jffs2_do_clear_inode(c, f);
+ }
+ kfree (f);
+@@ -1398,7 +1400,7 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
+
+ jffs2_clear_acl(f);
+ jffs2_xattr_delete_inode(c, f->inocache);
+- down(&f->sem);
++ mutex_lock(&f->sem);
+ deleted = f->inocache && !f->inocache->nlink;
+
+ if (f->inocache && f->inocache->state != INO_STATE_CHECKING)
+@@ -1430,5 +1432,5 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
+ jffs2_del_ino_cache(c, f->inocache);
+ }
+
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ }
+diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
+index 4677355..f3353df 100644
+--- a/fs/jffs2/super.c
++++ b/fs/jffs2/super.c
+@@ -47,7 +47,7 @@ static void jffs2_i_init_once(struct kmem_cache *cachep, void *foo)
+ {
+ struct jffs2_inode_info *ei = (struct jffs2_inode_info *) foo;
+
+- init_MUTEX(&ei->sem);
++ mutex_init(&ei->sem);
+ inode_init_once(&ei->vfs_inode);
+ }
+
+@@ -55,9 +55,9 @@ static int jffs2_sync_fs(struct super_block *sb, int wait)
+ {
+ struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
+
+- down(&c->alloc_sem);
++ mutex_lock(&c->alloc_sem);
+ jffs2_flush_wbuf_pad(c);
+- up(&c->alloc_sem);
++ mutex_unlock(&c->alloc_sem);
+ return 0;
+ }
+
+@@ -95,8 +95,8 @@ static int jffs2_fill_super(struct super_block *sb, void *data, int silent)
+
+ /* Initialize JFFS2 superblock locks, the further initialization will
+ * be done later */
+- init_MUTEX(&c->alloc_sem);
+- init_MUTEX(&c->erase_free_sem);
++ mutex_init(&c->alloc_sem);
++ mutex_init(&c->erase_free_sem);
+ init_waitqueue_head(&c->erase_wait);
+ init_waitqueue_head(&c->inocache_wq);
+ spin_lock_init(&c->erase_completion_lock);
+@@ -125,9 +125,9 @@ static void jffs2_put_super (struct super_block *sb)
+
+ D2(printk(KERN_DEBUG "jffs2: jffs2_put_super()\n"));
+
+- down(&c->alloc_sem);
++ mutex_lock(&c->alloc_sem);
+ jffs2_flush_wbuf_pad(c);
+- up(&c->alloc_sem);
++ mutex_unlock(&c->alloc_sem);
+
+ jffs2_sum_exit(c);
+
+diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
+index d1d4f27..8de52b6 100644
+--- a/fs/jffs2/wbuf.c
++++ b/fs/jffs2/wbuf.c
+@@ -578,8 +578,8 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
+ if (!jffs2_is_writebuffered(c))
+ return 0;
+
+- if (!down_trylock(&c->alloc_sem)) {
+- up(&c->alloc_sem);
++ if (mutex_trylock(&c->alloc_sem)) {
++ mutex_unlock(&c->alloc_sem);
+ printk(KERN_CRIT "jffs2_flush_wbuf() called with alloc_sem not locked!\n");
+ BUG();
+ }
+@@ -702,10 +702,10 @@ int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino)
+ if (!c->wbuf)
+ return 0;
+
+- down(&c->alloc_sem);
++ mutex_lock(&c->alloc_sem);
+ if (!jffs2_wbuf_pending_for_ino(c, ino)) {
+ D1(printk(KERN_DEBUG "Ino #%d not pending in wbuf. Returning\n", ino));
+- up(&c->alloc_sem);
++ mutex_unlock(&c->alloc_sem);
+ return 0;
+ }
+
+@@ -725,14 +725,14 @@ int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino)
+ } else while (old_wbuf_len &&
+ old_wbuf_ofs == c->wbuf_ofs) {
+
+- up(&c->alloc_sem);
++ mutex_unlock(&c->alloc_sem);
+
+ D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() calls gc pass\n"));
+
+ ret = jffs2_garbage_collect_pass(c);
+ if (ret) {
+ /* GC failed. Flush it with padding instead */
+- down(&c->alloc_sem);
++ mutex_lock(&c->alloc_sem);
+ down_write(&c->wbuf_sem);
+ ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING);
+ /* retry flushing wbuf in case jffs2_wbuf_recover
+@@ -742,12 +742,12 @@ int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino)
+ up_write(&c->wbuf_sem);
+ break;
+ }
+- down(&c->alloc_sem);
++ mutex_lock(&c->alloc_sem);
+ }
+
+ D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() ends...\n"));
+
+- up(&c->alloc_sem);
++ mutex_unlock(&c->alloc_sem);
+ return ret;
+ }
+
+@@ -1236,12 +1236,24 @@ int jffs2_dataflash_setup(struct jffs2_sb_info *c) {
+ if (!c->wbuf)
+ return -ENOMEM;
+
++#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
++ c->wbuf_verify = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
++ if (!c->wbuf_verify) {
++ kfree(c->oobbuf);
++ kfree(c->wbuf);
++ return -ENOMEM;
++ }
++#endif
++
+ printk(KERN_INFO "JFFS2 write-buffering enabled buffer (%d) erasesize (%d)\n", c->wbuf_pagesize, c->sector_size);
+
+ return 0;
+ }
+
+ void jffs2_dataflash_cleanup(struct jffs2_sb_info *c) {
++#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
++ kfree(c->wbuf_verify);
++#endif
+ kfree(c->wbuf);
+ }
+
+diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c
+index 776f13c..665fce9 100644
+--- a/fs/jffs2/write.c
++++ b/fs/jffs2/write.c
+@@ -137,12 +137,12 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
+ JFFS2_SUMMARY_INODE_SIZE);
+ } else {
+ /* Locking pain */
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ jffs2_complete_reservation(c);
+
+ ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &dummy,
+ alloc_mode, JFFS2_SUMMARY_INODE_SIZE);
+- down(&f->sem);
++ mutex_lock(&f->sem);
+ }
+
+ if (!ret) {
+@@ -285,12 +285,12 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
+ JFFS2_SUMMARY_DIRENT_SIZE(namelen));
+ } else {
+ /* Locking pain */
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ jffs2_complete_reservation(c);
+
+ ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &dummy,
+ alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
+- down(&f->sem);
++ mutex_lock(&f->sem);
+ }
+
+ if (!ret) {
+@@ -353,7 +353,7 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
+ D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret));
+ break;
+ }
+- down(&f->sem);
++ mutex_lock(&f->sem);
+ datalen = min_t(uint32_t, writelen, PAGE_CACHE_SIZE - (offset & (PAGE_CACHE_SIZE-1)));
+ cdatalen = min_t(uint32_t, alloclen - sizeof(*ri), datalen);
+
+@@ -381,7 +381,7 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
+
+ if (IS_ERR(fn)) {
+ ret = PTR_ERR(fn);
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ jffs2_complete_reservation(c);
+ if (!retried) {
+ /* Write error to be retried */
+@@ -403,11 +403,11 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
+ jffs2_mark_node_obsolete(c, fn->raw);
+ jffs2_free_full_dnode(fn);
+
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ jffs2_complete_reservation(c);
+ break;
+ }
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ jffs2_complete_reservation(c);
+ if (!datalen) {
+ printk(KERN_WARNING "Eep. We didn't actually write any data in jffs2_write_inode_range()\n");
+@@ -439,7 +439,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
+ JFFS2_SUMMARY_INODE_SIZE);
+ D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen));
+ if (ret) {
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ return ret;
+ }
+
+@@ -454,7 +454,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
+ if (IS_ERR(fn)) {
+ D1(printk(KERN_DEBUG "jffs2_write_dnode() failed\n"));
+ /* Eeek. Wave bye bye */
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ jffs2_complete_reservation(c);
+ return PTR_ERR(fn);
+ }
+@@ -463,7 +463,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
+ */
+ f->metadata = fn;
+
+- up(&f->sem);
++ mutex_unlock(&f->sem);
+ jffs2_complete_reservation(c);
+
+ ret = jffs2_init_security(&f->vfs_inode, &dir_f->vfs_inode);
+@@ -489,7 +489,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
+ return -ENOMEM;
+ }
+
+- down(&dir_f->sem);
++ mutex_lock(&dir_f->sem);
+
+ rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+ rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
+@@ -513,7 +513,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
+ /* dirent failed to write. Delete the inode normally
+ as if it were the final unlink() */
+ jffs2_complete_reservation(c);
+- up(&dir_f->sem);
++ mutex_unlock(&dir_f->sem);
+ return PTR_ERR(fd);
+ }
+
+@@ -522,7 +522,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
+ jffs2_add_fd_to_list(c, fd, &dir_f->dents);
+
+ jffs2_complete_reservation(c);
+- up(&dir_f->sem);
++ mutex_unlock(&dir_f->sem);
+
+ return 0;
+ }
+@@ -551,7 +551,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
+ return ret;
+ }
+
+- down(&dir_f->sem);
++ mutex_lock(&dir_f->sem);
+
+ /* Build a deletion node */
+ rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+@@ -574,21 +574,21 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
+
+ if (IS_ERR(fd)) {
+ jffs2_complete_reservation(c);
+- up(&dir_f->sem);
++ mutex_unlock(&dir_f->sem);
+ return PTR_ERR(fd);
+ }
+
+ /* File it. This will mark the old one obsolete. */
+ jffs2_add_fd_to_list(c, fd, &dir_f->dents);
+- up(&dir_f->sem);
++ mutex_unlock(&dir_f->sem);
+ } else {
+- struct jffs2_full_dirent *fd = dir_f->dents;
+ uint32_t nhash = full_name_hash(name, namelen);
+
++ fd = dir_f->dents;
+ /* We don't actually want to reserve any space, but we do
+ want to be holding the alloc_sem when we write to flash */
+- down(&c->alloc_sem);
+- down(&dir_f->sem);
++ mutex_lock(&c->alloc_sem);
++ mutex_lock(&dir_f->sem);
+
+ for (fd = dir_f->dents; fd; fd = fd->next) {
+ if (fd->nhash == nhash &&
+@@ -607,7 +607,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
+ break;
+ }
+ }
+- up(&dir_f->sem);
++ mutex_unlock(&dir_f->sem);
+ }
+
+ /* dead_f is NULL if this was a rename not a real unlink */
+@@ -615,7 +615,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
+ pointing to an inode which didn't exist. */
+ if (dead_f && dead_f->inocache) {
+
+- down(&dead_f->sem);
++ mutex_lock(&dead_f->sem);
+
+ if (S_ISDIR(OFNI_EDONI_2SFFJ(dead_f)->i_mode)) {
+ while (dead_f->dents) {
+@@ -639,7 +639,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
+
+ dead_f->inocache->nlink--;
+ /* NB: Caller must set inode nlink if appropriate */
+- up(&dead_f->sem);
++ mutex_unlock(&dead_f->sem);
+ }
+
+ jffs2_complete_reservation(c);
+@@ -666,7 +666,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint
+ return ret;
+ }
+
+- down(&dir_f->sem);
++ mutex_lock(&dir_f->sem);
+
+ /* Build a deletion node */
+ rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+@@ -691,7 +691,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint
+
+ if (IS_ERR(fd)) {
+ jffs2_complete_reservation(c);
+- up(&dir_f->sem);
++ mutex_unlock(&dir_f->sem);
+ return PTR_ERR(fd);
+ }
+
+@@ -699,7 +699,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint
+ jffs2_add_fd_to_list(c, fd, &dir_f->dents);
+
+ jffs2_complete_reservation(c);
+- up(&dir_f->sem);
++ mutex_unlock(&dir_f->sem);
+
+ return 0;
+ }
+diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c
+index a1f8e37..afe222b 100644
+--- a/fs/jfs/ioctl.c
++++ b/fs/jfs/ioctl.c
+@@ -8,6 +8,7 @@
+ #include <linux/fs.h>
+ #include <linux/ctype.h>
+ #include <linux/capability.h>
++#include <linux/mount.h>
+ #include <linux/time.h>
+ #include <linux/sched.h>
+ #include <asm/current.h>
+@@ -65,23 +66,30 @@ long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ return put_user(flags, (int __user *) arg);
+ case JFS_IOC_SETFLAGS: {
+ unsigned int oldflags;
++ int err;
+
+- if (IS_RDONLY(inode))
+- return -EROFS;
++ err = mnt_want_write(filp->f_path.mnt);
++ if (err)
++ return err;
+
+- if (!is_owner_or_cap(inode))
+- return -EACCES;
+-
+- if (get_user(flags, (int __user *) arg))
+- return -EFAULT;
++ if (!is_owner_or_cap(inode)) {
++ err = -EACCES;
++ goto setflags_out;
++ }
++ if (get_user(flags, (int __user *) arg)) {
++ err = -EFAULT;
++ goto setflags_out;
++ }
+
+ flags = jfs_map_ext2(flags, 1);
+ if (!S_ISDIR(inode->i_mode))
+ flags &= ~JFS_DIRSYNC_FL;
+
+ /* Is it quota file? Do not allow user to mess with it */
+- if (IS_NOQUOTA(inode))
+- return -EPERM;
++ if (IS_NOQUOTA(inode)) {
++ err = -EPERM;
++ goto setflags_out;
++ }
+
+ /* Lock against other parallel changes of flags */
+ mutex_lock(&inode->i_mutex);
+@@ -98,7 +106,8 @@ long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ (JFS_APPEND_FL | JFS_IMMUTABLE_FL))) {
+ if (!capable(CAP_LINUX_IMMUTABLE)) {
+ mutex_unlock(&inode->i_mutex);
+- return -EPERM;
++ err = -EPERM;
++ goto setflags_out;
+ }
+ }
+
+@@ -110,7 +119,9 @@ long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ mutex_unlock(&inode->i_mutex);
+ inode->i_ctime = CURRENT_TIME_SEC;
+ mark_inode_dirty(inode);
+- return 0;
++setflags_out:
++ mnt_drop_write(filp->f_path.mnt);
++ return err;
+ }
+ default:
+ return -ENOTTY;
+diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
+index e198506..2bc7d8a 100644
+--- a/fs/jfs/jfs_dmap.c
++++ b/fs/jfs/jfs_dmap.c
+@@ -2172,7 +2172,7 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
+ }
+
+ /* update the free count for this dmap */
+- dp->nfree = cpu_to_le32(le32_to_cpu(dp->nfree) - nblocks);
++ le32_add_cpu(&dp->nfree, -nblocks);
+
+ BMAP_LOCK(bmp);
+
+@@ -2316,7 +2316,7 @@ static int dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
+
+ /* update the free count for this dmap.
+ */
+- dp->nfree = cpu_to_le32(le32_to_cpu(dp->nfree) + nblocks);
++ le32_add_cpu(&dp->nfree, nblocks);
+
+ BMAP_LOCK(bmp);
+
+@@ -3226,7 +3226,7 @@ static int dbAllocDmapBU(struct bmap * bmp, struct dmap * dp, s64 blkno,
+ }
+
+ /* update the free count for this dmap */
+- dp->nfree = cpu_to_le32(le32_to_cpu(dp->nfree) - nblocks);
++ le32_add_cpu(&dp->nfree, -nblocks);
+
+ /* reconstruct summary tree */
+ dbInitDmapTree(dp);
+@@ -3660,9 +3660,8 @@ static int dbInitDmap(struct dmap * dp, s64 Blkno, int nblocks)
+ goto initTree;
+ }
+ } else {
+- dp->nblocks =
+- cpu_to_le32(le32_to_cpu(dp->nblocks) + nblocks);
+- dp->nfree = cpu_to_le32(le32_to_cpu(dp->nfree) + nblocks);
++ le32_add_cpu(&dp->nblocks, nblocks);
++ le32_add_cpu(&dp->nfree, nblocks);
+ }
+
+ /* word number containing start block number */
+diff --git a/fs/jfs/jfs_dmap.h b/fs/jfs/jfs_dmap.h
+index 11e6d47..1a6eb41 100644
+--- a/fs/jfs/jfs_dmap.h
++++ b/fs/jfs/jfs_dmap.h
+@@ -61,7 +61,7 @@
+ * determine the maximum free string for four (lower level) nodes
+ * of the tree.
+ */
+-static __inline signed char TREEMAX(signed char *cp)
++static inline signed char TREEMAX(signed char *cp)
+ {
+ signed char tmp1, tmp2;
+
+diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
+index 9bf29f7..734ec91 100644
+--- a/fs/jfs/jfs_imap.c
++++ b/fs/jfs/jfs_imap.c
+@@ -1019,8 +1019,7 @@ int diFree(struct inode *ip)
+ /* update the free inode counts at the iag, ag and
+ * map level.
+ */
+- iagp->nfreeinos =
+- cpu_to_le32(le32_to_cpu(iagp->nfreeinos) + 1);
++ le32_add_cpu(&iagp->nfreeinos, 1);
+ imap->im_agctl[agno].numfree += 1;
+ atomic_inc(&imap->im_numfree);
+
+@@ -1219,9 +1218,8 @@ int diFree(struct inode *ip)
+ /* update the number of free inodes and number of free extents
+ * for the iag.
+ */
+- iagp->nfreeinos = cpu_to_le32(le32_to_cpu(iagp->nfreeinos) -
+- (INOSPEREXT - 1));
+- iagp->nfreeexts = cpu_to_le32(le32_to_cpu(iagp->nfreeexts) + 1);
++ le32_add_cpu(&iagp->nfreeinos, -(INOSPEREXT - 1));
++ le32_add_cpu(&iagp->nfreeexts, 1);
+
+ /* update the number of free inodes and backed inodes
+ * at the ag and inode map level.
+@@ -2124,7 +2122,7 @@ static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino)
+ /* update the free inode count at the iag, ag, inode
+ * map levels.
+ */
+- iagp->nfreeinos = cpu_to_le32(le32_to_cpu(iagp->nfreeinos) - 1);
++ le32_add_cpu(&iagp->nfreeinos, -1);
+ imap->im_agctl[agno].numfree -= 1;
+ atomic_dec(&imap->im_numfree);
+
+@@ -2378,9 +2376,8 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
+ /* update the free inode and free extent counts for the
+ * iag.
+ */
+- iagp->nfreeinos = cpu_to_le32(le32_to_cpu(iagp->nfreeinos) +
+- (INOSPEREXT - 1));
+- iagp->nfreeexts = cpu_to_le32(le32_to_cpu(iagp->nfreeexts) - 1);
++ le32_add_cpu(&iagp->nfreeinos, (INOSPEREXT - 1));
++ le32_add_cpu(&iagp->nfreeexts, -1);
+
+ /* update the free and backed inode counts for the ag.
+ */
+diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c
+index a000aaa..5a61ebf 100644
+--- a/fs/jfs/jfs_xtree.c
++++ b/fs/jfs/jfs_xtree.c
+@@ -905,8 +905,7 @@ int xtInsert(tid_t tid, /* transaction id */
+ XT_PUTENTRY(xad, xflag, xoff, xlen, xaddr);
+
+ /* advance next available entry index */
+- p->header.nextindex =
+- cpu_to_le16(le16_to_cpu(p->header.nextindex) + 1);
++ le16_add_cpu(&p->header.nextindex, 1);
+
+ /* Don't log it if there are no links to the file */
+ if (!test_cflag(COMMIT_Nolink, ip)) {
+@@ -997,8 +996,7 @@ xtSplitUp(tid_t tid,
+ split->addr);
+
+ /* advance next available entry index */
+- sp->header.nextindex =
+- cpu_to_le16(le16_to_cpu(sp->header.nextindex) + 1);
++ le16_add_cpu(&sp->header.nextindex, 1);
+
+ /* Don't log it if there are no links to the file */
+ if (!test_cflag(COMMIT_Nolink, ip)) {
+@@ -1167,9 +1165,7 @@ xtSplitUp(tid_t tid,
+ JFS_SBI(ip->i_sb)->nbperpage, rcbn);
+
+ /* advance next available entry index. */
+- sp->header.nextindex =
+- cpu_to_le16(le16_to_cpu(sp->header.nextindex) +
+- 1);
++ le16_add_cpu(&sp->header.nextindex, 1);
+
+ /* Don't log it if there are no links to the file */
+ if (!test_cflag(COMMIT_Nolink, ip)) {
+@@ -1738,8 +1734,7 @@ int xtExtend(tid_t tid, /* transaction id */
+ XT_PUTENTRY(xad, XAD_NEW, xoff, len, xaddr);
+
+ /* advance next available entry index */
+- p->header.nextindex =
+- cpu_to_le16(le16_to_cpu(p->header.nextindex) + 1);
++ le16_add_cpu(&p->header.nextindex, 1);
+ }
+
+ /* get back old entry */
+@@ -1905,8 +1900,7 @@ printf("xtTailgate: xoff:0x%lx xlen:0x%x xaddr:0x%lx\n",
+ XT_PUTENTRY(xad, XAD_NEW, xoff, xlen, xaddr);
+
+ /* advance next available entry index */
+- p->header.nextindex =
+- cpu_to_le16(le16_to_cpu(p->header.nextindex) + 1);
++ le16_add_cpu(&p->header.nextindex, 1);
+ }
+
+ /* get back old XAD */
+@@ -2567,8 +2561,7 @@ int xtAppend(tid_t tid, /* transaction id */
+ XT_PUTENTRY(xad, xflag, xoff, xlen, xaddr);
+
+ /* advance next available entry index */
+- p->header.nextindex =
+- cpu_to_le16(le16_to_cpu(p->header.nextindex) + 1);
++ le16_add_cpu(&p->header.nextindex, 1);
+
+ xtlck->lwm.offset =
+ (xtlck->lwm.offset) ? min(index,(int) xtlck->lwm.offset) : index;
+@@ -2631,8 +2624,7 @@ int xtDelete(tid_t tid, struct inode *ip, s64 xoff, s32 xlen, int flag)
+ * delete the entry from the leaf page
+ */
+ nextindex = le16_to_cpu(p->header.nextindex);
+- p->header.nextindex =
+- cpu_to_le16(le16_to_cpu(p->header.nextindex) - 1);
++ le16_add_cpu(&p->header.nextindex, -1);
+
+ /*
+ * if the leaf page bocome empty, free the page
+@@ -2795,9 +2787,7 @@ xtDeleteUp(tid_t tid, struct inode *ip,
+ (nextindex - index -
+ 1) << L2XTSLOTSIZE);
+
+- p->header.nextindex =
+- cpu_to_le16(le16_to_cpu(p->header.nextindex) -
+- 1);
++ le16_add_cpu(&p->header.nextindex, -1);
+ jfs_info("xtDeleteUp(entry): 0x%lx[%d]",
+ (ulong) parent->bn, index);
+ }
+diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
+index b6b74a6..40b16f2 100644
+--- a/fs/lockd/clntproc.c
++++ b/fs/lockd/clntproc.c
+@@ -155,8 +155,6 @@ static void nlmclnt_release_lockargs(struct nlm_rqst *req)
+ int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl)
+ {
+ struct nlm_rqst *call;
+- sigset_t oldset;
+- unsigned long flags;
+ int status;
+
+ nlm_get_host(host);
+@@ -168,22 +166,6 @@ int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl)
+ /* Set up the argument struct */
+ nlmclnt_setlockargs(call, fl);
+
+- /* Keep the old signal mask */
+- spin_lock_irqsave(¤t->sighand->siglock, flags);
+- oldset = current->blocked;
+-
+- /* If we're cleaning up locks because the process is exiting,
+- * perform the RPC call asynchronously. */
+- if ((IS_SETLK(cmd) || IS_SETLKW(cmd))
+- && fl->fl_type == F_UNLCK
+- && (current->flags & PF_EXITING)) {
+- sigfillset(¤t->blocked); /* Mask all signals */
+- recalc_sigpending();
+-
+- call->a_flags = RPC_TASK_ASYNC;
+- }
+- spin_unlock_irqrestore(¤t->sighand->siglock, flags);
+-
+ if (IS_SETLK(cmd) || IS_SETLKW(cmd)) {
+ if (fl->fl_type != F_UNLCK) {
+ call->a_args.block = IS_SETLKW(cmd) ? 1 : 0;
+@@ -198,11 +180,6 @@ int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl)
+ fl->fl_ops->fl_release_private(fl);
+ fl->fl_ops = NULL;
+
+- spin_lock_irqsave(¤t->sighand->siglock, flags);
+- current->blocked = oldset;
+- recalc_sigpending();
+- spin_unlock_irqrestore(¤t->sighand->siglock, flags);
+-
+ dprintk("lockd: clnt proc returns %d\n", status);
+ return status;
+ }
+@@ -221,6 +198,7 @@ struct nlm_rqst *nlm_alloc_call(struct nlm_host *host)
+ for(;;) {
+ call = kzalloc(sizeof(*call), GFP_KERNEL);
+ if (call != NULL) {
++ atomic_set(&call->a_count, 1);
+ locks_init_lock(&call->a_args.lock.fl);
+ locks_init_lock(&call->a_res.lock.fl);
+ call->a_host = host;
+@@ -237,6 +215,8 @@ struct nlm_rqst *nlm_alloc_call(struct nlm_host *host)
+
+ void nlm_release_call(struct nlm_rqst *call)
+ {
++ if (!atomic_dec_and_test(&call->a_count))
++ return;
+ nlm_release_host(call->a_host);
+ nlmclnt_release_lockargs(call);
+ kfree(call);
+@@ -267,7 +247,7 @@ static int nlm_wait_on_grace(wait_queue_head_t *queue)
+ * Generic NLM call
+ */
+ static int
+-nlmclnt_call(struct nlm_rqst *req, u32 proc)
++nlmclnt_call(struct rpc_cred *cred, struct nlm_rqst *req, u32 proc)
+ {
+ struct nlm_host *host = req->a_host;
+ struct rpc_clnt *clnt;
+@@ -276,6 +256,7 @@ nlmclnt_call(struct nlm_rqst *req, u32 proc)
+ struct rpc_message msg = {
+ .rpc_argp = argp,
+ .rpc_resp = resp,
++ .rpc_cred = cred,
+ };
+ int status;
+
+@@ -343,10 +324,16 @@ in_grace_period:
+ /*
+ * Generic NLM call, async version.
+ */
+-static int __nlm_async_call(struct nlm_rqst *req, u32 proc, struct rpc_message *msg, const struct rpc_call_ops *tk_ops)
++static struct rpc_task *__nlm_async_call(struct nlm_rqst *req, u32 proc, struct rpc_message *msg, const struct rpc_call_ops *tk_ops)
+ {
+ struct nlm_host *host = req->a_host;
+ struct rpc_clnt *clnt;
++ struct rpc_task_setup task_setup_data = {
++ .rpc_message = msg,
++ .callback_ops = tk_ops,
++ .callback_data = req,
++ .flags = RPC_TASK_ASYNC,
++ };
+
+ dprintk("lockd: call procedure %d on %s (async)\n",
+ (int)proc, host->h_name);
+@@ -356,21 +343,36 @@ static int __nlm_async_call(struct nlm_rqst *req, u32 proc, struct rpc_message *
+ if (clnt == NULL)
+ goto out_err;
+ msg->rpc_proc = &clnt->cl_procinfo[proc];
++ task_setup_data.rpc_client = clnt;
+
+ /* bootstrap and kick off the async RPC call */
+- return rpc_call_async(clnt, msg, RPC_TASK_ASYNC, tk_ops, req);
++ return rpc_run_task(&task_setup_data);
+ out_err:
+ tk_ops->rpc_release(req);
+- return -ENOLCK;
++ return ERR_PTR(-ENOLCK);
+ }
+
++static int nlm_do_async_call(struct nlm_rqst *req, u32 proc, struct rpc_message *msg, const struct rpc_call_ops *tk_ops)
++{
++ struct rpc_task *task;
++
++ task = __nlm_async_call(req, proc, msg, tk_ops);
++ if (IS_ERR(task))
++ return PTR_ERR(task);
++ rpc_put_task(task);
++ return 0;
++}
++
++/*
++ * NLM asynchronous call.
++ */
+ int nlm_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops)
+ {
+ struct rpc_message msg = {
+ .rpc_argp = &req->a_args,
+ .rpc_resp = &req->a_res,
+ };
+- return __nlm_async_call(req, proc, &msg, tk_ops);
++ return nlm_do_async_call(req, proc, &msg, tk_ops);
+ }
+
+ int nlm_async_reply(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops)
+@@ -378,7 +380,33 @@ int nlm_async_reply(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *t
+ struct rpc_message msg = {
+ .rpc_argp = &req->a_res,
+ };
+- return __nlm_async_call(req, proc, &msg, tk_ops);
++ return nlm_do_async_call(req, proc, &msg, tk_ops);
++}
++
++/*
++ * NLM client asynchronous call.
++ *
++ * Note that although the calls are asynchronous, and are therefore
++ * guaranteed to complete, we still always attempt to wait for
++ * completion in order to be able to correctly track the lock
++ * state.
++ */
++static int nlmclnt_async_call(struct rpc_cred *cred, struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops)
++{
++ struct rpc_message msg = {
++ .rpc_argp = &req->a_args,
++ .rpc_resp = &req->a_res,
++ .rpc_cred = cred,
++ };
++ struct rpc_task *task;
++ int err;
++
++ task = __nlm_async_call(req, proc, &msg, tk_ops);
++ if (IS_ERR(task))
++ return PTR_ERR(task);
++ err = rpc_wait_for_completion_task(task);
++ rpc_put_task(task);
++ return err;
+ }
+
+ /*
+@@ -389,7 +417,7 @@ nlmclnt_test(struct nlm_rqst *req, struct file_lock *fl)
+ {
+ int status;
+
+- status = nlmclnt_call(req, NLMPROC_TEST);
++ status = nlmclnt_call(nfs_file_cred(fl->fl_file), req, NLMPROC_TEST);
+ if (status < 0)
+ goto out;
+
+@@ -480,10 +508,12 @@ static int do_vfs_lock(struct file_lock *fl)
+ static int
+ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
+ {
++ struct rpc_cred *cred = nfs_file_cred(fl->fl_file);
+ struct nlm_host *host = req->a_host;
+ struct nlm_res *resp = &req->a_res;
+ struct nlm_wait *block = NULL;
+ unsigned char fl_flags = fl->fl_flags;
++ unsigned char fl_type;
+ int status = -ENOLCK;
+
+ if (nsm_monitor(host) < 0) {
+@@ -493,18 +523,22 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
+ }
+ fl->fl_flags |= FL_ACCESS;
+ status = do_vfs_lock(fl);
++ fl->fl_flags = fl_flags;
+ if (status < 0)
+ goto out;
+
+ block = nlmclnt_prepare_block(host, fl);
+ again:
++ /*
++ * Initialise resp->status to a valid non-zero value,
++ * since 0 == nlm_lck_granted
++ */
++ resp->status = nlm_lck_blocked;
+ for(;;) {
+ /* Reboot protection */
+ fl->fl_u.nfs_fl.state = host->h_state;
+- status = nlmclnt_call(req, NLMPROC_LOCK);
++ status = nlmclnt_call(cred, req, NLMPROC_LOCK);
+ if (status < 0)
+- goto out_unblock;
+- if (!req->a_args.block)
+ break;
+ /* Did a reclaimer thread notify us of a server reboot? */
+ if (resp->status == nlm_lck_denied_grace_period)
+@@ -513,15 +547,22 @@ again:
+ break;
+ /* Wait on an NLM blocking lock */
+ status = nlmclnt_block(block, req, NLMCLNT_POLL_TIMEOUT);
+- /* if we were interrupted. Send a CANCEL request to the server
+- * and exit
+- */
+ if (status < 0)
+- goto out_unblock;
++ break;
+ if (resp->status != nlm_lck_blocked)
+ break;
+ }
+
++ /* if we were interrupted while blocking, then cancel the lock request
++ * and exit
++ */
++ if (resp->status == nlm_lck_blocked) {
++ if (!req->a_args.block)
++ goto out_unlock;
++ if (nlmclnt_cancel(host, req->a_args.block, fl) == 0)
++ goto out_unblock;
++ }
++
+ if (resp->status == nlm_granted) {
+ down_read(&host->h_rwsem);
+ /* Check whether or not the server has rebooted */
+@@ -530,20 +571,34 @@ again:
+ goto again;
+ }
+ /* Ensure the resulting lock will get added to granted list */
+- fl->fl_flags = fl_flags | FL_SLEEP;
++ fl->fl_flags |= FL_SLEEP;
+ if (do_vfs_lock(fl) < 0)
+ printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__);
+ up_read(&host->h_rwsem);
++ fl->fl_flags = fl_flags;
++ status = 0;
+ }
++ if (status < 0)
++ goto out_unlock;
+ status = nlm_stat_to_errno(resp->status);
+ out_unblock:
+ nlmclnt_finish_block(block);
+- /* Cancel the blocked request if it is still pending */
+- if (resp->status == nlm_lck_blocked)
+- nlmclnt_cancel(host, req->a_args.block, fl);
+ out:
+ nlm_release_call(req);
++ return status;
++out_unlock:
++ /* Fatal error: ensure that we remove the lock altogether */
++ dprintk("lockd: lock attempt ended in fatal error.\n"
++ " Attempting to unlock.\n");
++ nlmclnt_finish_block(block);
++ fl_type = fl->fl_type;
++ fl->fl_type = F_UNLCK;
++ down_read(&host->h_rwsem);
++ do_vfs_lock(fl);
++ up_read(&host->h_rwsem);
++ fl->fl_type = fl_type;
+ fl->fl_flags = fl_flags;
++ nlmclnt_async_call(cred, req, NLMPROC_UNLOCK, &nlmclnt_unlock_ops);
+ return status;
+ }
+
+@@ -567,8 +622,8 @@ nlmclnt_reclaim(struct nlm_host *host, struct file_lock *fl)
+ nlmclnt_setlockargs(req, fl);
+ req->a_args.reclaim = 1;
+
+- if ((status = nlmclnt_call(req, NLMPROC_LOCK)) >= 0
+- && req->a_res.status == nlm_granted)
++ status = nlmclnt_call(nfs_file_cred(fl->fl_file), req, NLMPROC_LOCK);
++ if (status >= 0 && req->a_res.status == nlm_granted)
+ return 0;
+
+ printk(KERN_WARNING "lockd: failed to reclaim lock for pid %d "
+@@ -598,7 +653,8 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
+ {
+ struct nlm_host *host = req->a_host;
+ struct nlm_res *resp = &req->a_res;
+- int status = 0;
++ int status;
++ unsigned char fl_flags = fl->fl_flags;
+
+ /*
+ * Note: the server is supposed to either grant us the unlock
+@@ -607,16 +663,17 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
+ */
+ fl->fl_flags |= FL_EXISTS;
+ down_read(&host->h_rwsem);
+- if (do_vfs_lock(fl) == -ENOENT) {
+- up_read(&host->h_rwsem);
++ status = do_vfs_lock(fl);
++ up_read(&host->h_rwsem);
++ fl->fl_flags = fl_flags;
++ if (status == -ENOENT) {
++ status = 0;
+ goto out;
+ }
+- up_read(&host->h_rwsem);
+-
+- if (req->a_flags & RPC_TASK_ASYNC)
+- return nlm_async_call(req, NLMPROC_UNLOCK, &nlmclnt_unlock_ops);
+
+- status = nlmclnt_call(req, NLMPROC_UNLOCK);
++ atomic_inc(&req->a_count);
++ status = nlmclnt_async_call(nfs_file_cred(fl->fl_file), req,
++ NLMPROC_UNLOCK, &nlmclnt_unlock_ops);
+ if (status < 0)
+ goto out;
+
+@@ -671,16 +728,10 @@ static const struct rpc_call_ops nlmclnt_unlock_ops = {
+ static int nlmclnt_cancel(struct nlm_host *host, int block, struct file_lock *fl)
+ {
+ struct nlm_rqst *req;
+- unsigned long flags;
+- sigset_t oldset;
+- int status;
++ int status;
+
+- /* Block all signals while setting up call */
+- spin_lock_irqsave(¤t->sighand->siglock, flags);
+- oldset = current->blocked;
+- sigfillset(¤t->blocked);
+- recalc_sigpending();
+- spin_unlock_irqrestore(¤t->sighand->siglock, flags);
++ dprintk("lockd: blocking lock attempt was interrupted by a signal.\n"
++ " Attempting to cancel lock.\n");
+
+ req = nlm_alloc_call(nlm_get_host(host));
+ if (!req)
+@@ -690,13 +741,12 @@ static int nlmclnt_cancel(struct nlm_host *host, int block, struct file_lock *fl
+ nlmclnt_setlockargs(req, fl);
+ req->a_args.block = block;
+
+- status = nlm_async_call(req, NLMPROC_CANCEL, &nlmclnt_cancel_ops);
+-
+- spin_lock_irqsave(¤t->sighand->siglock, flags);
+- current->blocked = oldset;
+- recalc_sigpending();
+- spin_unlock_irqrestore(¤t->sighand->siglock, flags);
+-
++ atomic_inc(&req->a_count);
++ status = nlmclnt_async_call(nfs_file_cred(fl->fl_file), req,
++ NLMPROC_CANCEL, &nlmclnt_cancel_ops);
++ if (status == 0 && req->a_res.status == nlm_lck_denied)
++ status = -ENOLCK;
++ nlm_release_call(req);
+ return status;
+ }
+
+diff --git a/fs/lockd/host.c b/fs/lockd/host.c
+index f1ef49f..a17664c 100644
+--- a/fs/lockd/host.c
++++ b/fs/lockd/host.c
+@@ -19,12 +19,11 @@
+
+
+ #define NLMDBG_FACILITY NLMDBG_HOSTCACHE
+-#define NLM_HOST_MAX 64
+ #define NLM_HOST_NRHASH 32
+ #define NLM_ADDRHASH(addr) (ntohl(addr) & (NLM_HOST_NRHASH-1))
+ #define NLM_HOST_REBIND (60 * HZ)
+-#define NLM_HOST_EXPIRE ((nrhosts > NLM_HOST_MAX)? 300 * HZ : 120 * HZ)
+-#define NLM_HOST_COLLECT ((nrhosts > NLM_HOST_MAX)? 120 * HZ : 60 * HZ)
++#define NLM_HOST_EXPIRE (300 * HZ)
++#define NLM_HOST_COLLECT (120 * HZ)
+
+ static struct hlist_head nlm_hosts[NLM_HOST_NRHASH];
+ static unsigned long next_gc;
+@@ -42,11 +41,12 @@ static struct nsm_handle * nsm_find(const struct sockaddr_in *sin,
+ /*
+ * Common host lookup routine for server & client
+ */
+-static struct nlm_host *
+-nlm_lookup_host(int server, const struct sockaddr_in *sin,
+- int proto, int version, const char *hostname,
+- unsigned int hostname_len,
+- const struct sockaddr_in *ssin)
++static struct nlm_host *nlm_lookup_host(int server,
++ const struct sockaddr_in *sin,
++ int proto, u32 version,
++ const char *hostname,
++ unsigned int hostname_len,
++ const struct sockaddr_in *ssin)
+ {
+ struct hlist_head *chain;
+ struct hlist_node *pos;
+@@ -55,7 +55,7 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin,
+ int hash;
+
+ dprintk("lockd: nlm_lookup_host("NIPQUAD_FMT"->"NIPQUAD_FMT
+- ", p=%d, v=%d, my role=%s, name=%.*s)\n",
++ ", p=%d, v=%u, my role=%s, name=%.*s)\n",
+ NIPQUAD(ssin->sin_addr.s_addr),
+ NIPQUAD(sin->sin_addr.s_addr), proto, version,
+ server? "server" : "client",
+@@ -142,9 +142,7 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin,
+ INIT_LIST_HEAD(&host->h_granted);
+ INIT_LIST_HEAD(&host->h_reclaim);
+
+- if (++nrhosts > NLM_HOST_MAX)
+- next_gc = 0;
+-
++ nrhosts++;
+ out:
+ mutex_unlock(&nlm_host_mutex);
+ return host;
+@@ -175,9 +173,10 @@ nlm_destroy_host(struct nlm_host *host)
+ /*
+ * Find an NLM server handle in the cache. If there is none, create it.
+ */
+-struct nlm_host *
+-nlmclnt_lookup_host(const struct sockaddr_in *sin, int proto, int version,
+- const char *hostname, unsigned int hostname_len)
++struct nlm_host *nlmclnt_lookup_host(const struct sockaddr_in *sin,
++ int proto, u32 version,
++ const char *hostname,
++ unsigned int hostname_len)
+ {
+ struct sockaddr_in ssin = {0};
+
+@@ -460,7 +459,7 @@ nlm_gc_hosts(void)
+ * Manage NSM handles
+ */
+ static LIST_HEAD(nsm_handles);
+-static DEFINE_MUTEX(nsm_mutex);
++static DEFINE_SPINLOCK(nsm_lock);
+
+ static struct nsm_handle *
+ __nsm_find(const struct sockaddr_in *sin,
+@@ -468,7 +467,7 @@ __nsm_find(const struct sockaddr_in *sin,
+ int create)
+ {
+ struct nsm_handle *nsm = NULL;
+- struct list_head *pos;
++ struct nsm_handle *pos;
+
+ if (!sin)
+ return NULL;
+@@ -482,38 +481,43 @@ __nsm_find(const struct sockaddr_in *sin,
+ return NULL;
+ }
+
+- mutex_lock(&nsm_mutex);
+- list_for_each(pos, &nsm_handles) {
+- nsm = list_entry(pos, struct nsm_handle, sm_link);
++retry:
++ spin_lock(&nsm_lock);
++ list_for_each_entry(pos, &nsm_handles, sm_link) {
+
+ if (hostname && nsm_use_hostnames) {
+- if (strlen(nsm->sm_name) != hostname_len
+- || memcmp(nsm->sm_name, hostname, hostname_len))
++ if (strlen(pos->sm_name) != hostname_len
++ || memcmp(pos->sm_name, hostname, hostname_len))
+ continue;
+- } else if (!nlm_cmp_addr(&nsm->sm_addr, sin))
++ } else if (!nlm_cmp_addr(&pos->sm_addr, sin))
+ continue;
+- atomic_inc(&nsm->sm_count);
+- goto out;
++ atomic_inc(&pos->sm_count);
++ kfree(nsm);
++ nsm = pos;
++ goto found;
+ }
+-
+- if (!create) {
+- nsm = NULL;
+- goto out;
++ if (nsm) {
++ list_add(&nsm->sm_link, &nsm_handles);
++ goto found;
+ }
++ spin_unlock(&nsm_lock);
++
++ if (!create)
++ return NULL;
+
+ nsm = kzalloc(sizeof(*nsm) + hostname_len + 1, GFP_KERNEL);
+- if (nsm != NULL) {
+- nsm->sm_addr = *sin;
+- nsm->sm_name = (char *) (nsm + 1);
+- memcpy(nsm->sm_name, hostname, hostname_len);
+- nsm->sm_name[hostname_len] = '\0';
+- atomic_set(&nsm->sm_count, 1);
++ if (nsm == NULL)
++ return NULL;
+
+- list_add(&nsm->sm_link, &nsm_handles);
+- }
++ nsm->sm_addr = *sin;
++ nsm->sm_name = (char *) (nsm + 1);
++ memcpy(nsm->sm_name, hostname, hostname_len);
++ nsm->sm_name[hostname_len] = '\0';
++ atomic_set(&nsm->sm_count, 1);
++ goto retry;
+
+-out:
+- mutex_unlock(&nsm_mutex);
++found:
++ spin_unlock(&nsm_lock);
+ return nsm;
+ }
+
+@@ -532,12 +536,9 @@ nsm_release(struct nsm_handle *nsm)
+ {
+ if (!nsm)
+ return;
+- if (atomic_dec_and_test(&nsm->sm_count)) {
+- mutex_lock(&nsm_mutex);
+- if (atomic_read(&nsm->sm_count) == 0) {
+- list_del(&nsm->sm_link);
+- kfree(nsm);
+- }
+- mutex_unlock(&nsm_mutex);
++ if (atomic_dec_and_lock(&nsm->sm_count, &nsm_lock)) {
++ list_del(&nsm->sm_link);
++ spin_unlock(&nsm_lock);
++ kfree(nsm);
+ }
+ }
+diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
+index 908b23f..e4d5635 100644
+--- a/fs/lockd/mon.c
++++ b/fs/lockd/mon.c
+@@ -18,6 +18,8 @@
+
+ #define NLMDBG_FACILITY NLMDBG_MONITOR
+
++#define XDR_ADDRBUF_LEN (20)
++
+ static struct rpc_clnt * nsm_create(void);
+
+ static struct rpc_program nsm_program;
+@@ -147,28 +149,55 @@ nsm_create(void)
+
+ /*
+ * XDR functions for NSM.
++ *
++ * See http://www.opengroup.org/ for details on the Network
++ * Status Monitor wire protocol.
+ */
+
+-static __be32 *
+-xdr_encode_common(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
++static __be32 *xdr_encode_nsm_string(__be32 *p, char *string)
+ {
+- char buffer[20], *name;
+-
+- /*
+- * Use the dotted-quad IP address of the remote host as
+- * identifier. Linux statd always looks up the canonical
+- * hostname first for whatever remote hostname it receives,
+- * so this works alright.
+- */
+- if (nsm_use_hostnames) {
+- name = argp->mon_name;
+- } else {
+- sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(argp->addr));
++ size_t len = strlen(string);
++
++ if (len > SM_MAXSTRLEN)
++ len = SM_MAXSTRLEN;
++ return xdr_encode_opaque(p, string, len);
++}
++
++/*
++ * "mon_name" specifies the host to be monitored.
++ *
++ * Linux uses a text version of the IP address of the remote
++ * host as the host identifier (the "mon_name" argument).
++ *
++ * Linux statd always looks up the canonical hostname first for
++ * whatever remote hostname it receives, so this works alright.
++ */
++static __be32 *xdr_encode_mon_name(__be32 *p, struct nsm_args *argp)
++{
++ char buffer[XDR_ADDRBUF_LEN + 1];
++ char *name = argp->mon_name;
++
++ if (!nsm_use_hostnames) {
++ snprintf(buffer, XDR_ADDRBUF_LEN,
++ NIPQUAD_FMT, NIPQUAD(argp->addr));
+ name = buffer;
+ }
+- if (!(p = xdr_encode_string(p, name))
+- || !(p = xdr_encode_string(p, utsname()->nodename)))
++
++ return xdr_encode_nsm_string(p, name);
++}
++
++/*
++ * The "my_id" argument specifies the hostname and RPC procedure
++ * to be called when the status manager receives notification
++ * (via the SM_NOTIFY call) that the state of host "mon_name"
++ * has changed.
++ */
++static __be32 *xdr_encode_my_id(__be32 *p, struct nsm_args *argp)
++{
++ p = xdr_encode_nsm_string(p, utsname()->nodename);
++ if (!p)
+ return ERR_PTR(-EIO);
++
+ *p++ = htonl(argp->prog);
+ *p++ = htonl(argp->vers);
+ *p++ = htonl(argp->proc);
+@@ -176,18 +205,48 @@ xdr_encode_common(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
+ return p;
+ }
+
+-static int
+-xdr_encode_mon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
++/*
++ * The "mon_id" argument specifies the non-private arguments
++ * of an SM_MON or SM_UNMON call.
++ */
++static __be32 *xdr_encode_mon_id(__be32 *p, struct nsm_args *argp)
+ {
+- p = xdr_encode_common(rqstp, p, argp);
+- if (IS_ERR(p))
+- return PTR_ERR(p);
++ p = xdr_encode_mon_name(p, argp);
++ if (!p)
++ return ERR_PTR(-EIO);
+
+- /* Surprise - there may even be room for an IPv6 address now */
++ return xdr_encode_my_id(p, argp);
++}
++
++/*
++ * The "priv" argument may contain private information required
++ * by the SM_MON call. This information will be supplied in the
++ * SM_NOTIFY call.
++ *
++ * Linux provides the raw IP address of the monitored host,
++ * left in network byte order.
++ */
++static __be32 *xdr_encode_priv(__be32 *p, struct nsm_args *argp)
++{
+ *p++ = argp->addr;
+ *p++ = 0;
+ *p++ = 0;
+ *p++ = 0;
++
++ return p;
++}
++
++static int
++xdr_encode_mon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
++{
++ p = xdr_encode_mon_id(p, argp);
++ if (IS_ERR(p))
++ return PTR_ERR(p);
++
++ p = xdr_encode_priv(p, argp);
++ if (IS_ERR(p))
++ return PTR_ERR(p);
++
+ rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p);
+ return 0;
+ }
+@@ -195,7 +254,7 @@ xdr_encode_mon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
+ static int
+ xdr_encode_unmon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp)
+ {
+- p = xdr_encode_common(rqstp, p, argp);
++ p = xdr_encode_mon_id(p, argp);
+ if (IS_ERR(p))
+ return PTR_ERR(p);
+ rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p);
+@@ -220,9 +279,11 @@ xdr_decode_stat(struct rpc_rqst *rqstp, __be32 *p, struct nsm_res *resp)
+ }
+
+ #define SM_my_name_sz (1+XDR_QUADLEN(SM_MAXSTRLEN))
+-#define SM_my_id_sz (3+1+SM_my_name_sz)
+-#define SM_mon_id_sz (1+XDR_QUADLEN(20)+SM_my_id_sz)
+-#define SM_mon_sz (SM_mon_id_sz+4)
++#define SM_my_id_sz (SM_my_name_sz+3)
++#define SM_mon_name_sz (1+XDR_QUADLEN(SM_MAXSTRLEN))
++#define SM_mon_id_sz (SM_mon_name_sz+SM_my_id_sz)
++#define SM_priv_sz (XDR_QUADLEN(SM_PRIV_SIZE))
++#define SM_mon_sz (SM_mon_id_sz+SM_priv_sz)
+ #define SM_monres_sz 2
+ #define SM_unmonres_sz 1
+
+diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
+index 1ed8bd4..2169af4 100644
+--- a/fs/lockd/svc.c
++++ b/fs/lockd/svc.c
+@@ -25,6 +25,7 @@
+ #include <linux/smp.h>
+ #include <linux/smp_lock.h>
+ #include <linux/mutex.h>
++#include <linux/kthread.h>
+ #include <linux/freezer.h>
+
+ #include <linux/sunrpc/types.h>
+@@ -48,14 +49,11 @@ EXPORT_SYMBOL(nlmsvc_ops);
+
+ static DEFINE_MUTEX(nlmsvc_mutex);
+ static unsigned int nlmsvc_users;
+-static pid_t nlmsvc_pid;
++static struct task_struct *nlmsvc_task;
+ static struct svc_serv *nlmsvc_serv;
+ int nlmsvc_grace_period;
+ unsigned long nlmsvc_timeout;
+
+-static DECLARE_COMPLETION(lockd_start_done);
+-static DECLARE_WAIT_QUEUE_HEAD(lockd_exit);
+-
+ /*
+ * These can be set at insmod time (useful for NFS as root filesystem),
+ * and also changed through the sysctl interface. -- Jamie Lokier, Aug 2003
+@@ -74,7 +72,9 @@ static const unsigned long nlm_timeout_min = 3;
+ static const unsigned long nlm_timeout_max = 20;
+ static const int nlm_port_min = 0, nlm_port_max = 65535;
+
++#ifdef CONFIG_SYSCTL
+ static struct ctl_table_header * nlm_sysctl_table;
++#endif
+
+ static unsigned long get_lockd_grace_period(void)
+ {
+@@ -111,35 +111,30 @@ static inline void clear_grace_period(void)
+ /*
+ * This is the lockd kernel thread
+ */
+-static void
+-lockd(struct svc_rqst *rqstp)
++static int
++lockd(void *vrqstp)
+ {
+- int err = 0;
++ int err = 0, preverr = 0;
++ struct svc_rqst *rqstp = vrqstp;
+ unsigned long grace_period_expire;
+
+- /* Lock module and set up kernel thread */
+- /* lockd_up is waiting for us to startup, so will
+- * be holding a reference to this module, so it
+- * is safe to just claim another reference
+- */
+- __module_get(THIS_MODULE);
+- lock_kernel();
+-
+- /*
+- * Let our maker know we're running.
+- */
+- nlmsvc_pid = current->pid;
+- nlmsvc_serv = rqstp->rq_server;
+- complete(&lockd_start_done);
+-
+- daemonize("lockd");
++ /* try_to_freeze() is called from svc_recv() */
+ set_freezable();
+
+- /* Process request with signals blocked, but allow SIGKILL. */
++ /* Allow SIGKILL to tell lockd to drop all of its locks */
+ allow_signal(SIGKILL);
+
+ dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n");
+
++ /*
++ * FIXME: it would be nice if lockd didn't spend its entire life
++ * running under the BKL. At the very least, it would be good to
++ * have someone clarify what it's intended to protect here. I've
++ * seen some handwavy posts about posix locking needing to be
++ * done under the BKL, but it's far from clear.
++ */
++ lock_kernel();
++
+ if (!nlm_timeout)
+ nlm_timeout = LOCKD_DFLT_TIMEO;
+ nlmsvc_timeout = nlm_timeout * HZ;
+@@ -148,10 +143,9 @@ lockd(struct svc_rqst *rqstp)
+
+ /*
+ * The main request loop. We don't terminate until the last
+- * NFS mount or NFS daemon has gone away, and we've been sent a
+- * signal, or else another process has taken over our job.
++ * NFS mount or NFS daemon has gone away.
+ */
+- while ((nlmsvc_users || !signalled()) && nlmsvc_pid == current->pid) {
++ while (!kthread_should_stop()) {
+ long timeout = MAX_SCHEDULE_TIMEOUT;
+ RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
+
+@@ -161,6 +155,7 @@ lockd(struct svc_rqst *rqstp)
+ nlmsvc_invalidate_all();
+ grace_period_expire = set_grace_period();
+ }
++ continue;
+ }
+
+ /*
+@@ -179,14 +174,20 @@ lockd(struct svc_rqst *rqstp)
+ * recvfrom routine.
+ */
+ err = svc_recv(rqstp, timeout);
+- if (err == -EAGAIN || err == -EINTR)
++ if (err == -EAGAIN || err == -EINTR) {
++ preverr = err;
+ continue;
++ }
+ if (err < 0) {
+- printk(KERN_WARNING
+- "lockd: terminating on error %d\n",
+- -err);
+- break;
++ if (err != preverr) {
++ printk(KERN_WARNING "%s: unexpected error "
++ "from svc_recv (%d)\n", __func__, err);
++ preverr = err;
++ }
++ schedule_timeout_interruptible(HZ);
++ continue;
+ }
++ preverr = err;
+
+ dprintk("lockd: request from %s\n",
+ svc_print_addr(rqstp, buf, sizeof(buf)));
+@@ -195,28 +196,19 @@ lockd(struct svc_rqst *rqstp)
+ }
+
+ flush_signals(current);
++ if (nlmsvc_ops)
++ nlmsvc_invalidate_all();
++ nlm_shutdown_hosts();
+
+- /*
+- * Check whether there's a new lockd process before
+- * shutting down the hosts and clearing the slot.
+- */
+- if (!nlmsvc_pid || current->pid == nlmsvc_pid) {
+- if (nlmsvc_ops)
+- nlmsvc_invalidate_all();
+- nlm_shutdown_hosts();
+- nlmsvc_pid = 0;
+- nlmsvc_serv = NULL;
+- } else
+- printk(KERN_DEBUG
+- "lockd: new process, skipping host shutdown\n");
+- wake_up(&lockd_exit);
++ unlock_kernel();
++
++ nlmsvc_task = NULL;
++ nlmsvc_serv = NULL;
+
+ /* Exit the RPC thread */
+ svc_exit_thread(rqstp);
+
+- /* Release module */
+- unlock_kernel();
+- module_put_and_exit(0);
++ return 0;
+ }
+
+ /*
+@@ -261,14 +253,15 @@ static int make_socks(struct svc_serv *serv, int proto)
+ int
+ lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
+ {
+- struct svc_serv * serv;
+- int error = 0;
++ struct svc_serv *serv;
++ struct svc_rqst *rqstp;
++ int error = 0;
+
+ mutex_lock(&nlmsvc_mutex);
+ /*
+ * Check whether we're already up and running.
+ */
+- if (nlmsvc_pid) {
++ if (nlmsvc_serv) {
+ if (proto)
+ error = make_socks(nlmsvc_serv, proto);
+ goto out;
+@@ -295,13 +288,28 @@ lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
+ /*
+ * Create the kernel thread and wait for it to start.
+ */
+- error = svc_create_thread(lockd, serv);
+- if (error) {
++ rqstp = svc_prepare_thread(serv, &serv->sv_pools[0]);
++ if (IS_ERR(rqstp)) {
++ error = PTR_ERR(rqstp);
++ printk(KERN_WARNING
++ "lockd_up: svc_rqst allocation failed, error=%d\n",
++ error);
++ goto destroy_and_out;
++ }
++
++ svc_sock_update_bufs(serv);
++ nlmsvc_serv = rqstp->rq_server;
++
++ nlmsvc_task = kthread_run(lockd, rqstp, serv->sv_name);
++ if (IS_ERR(nlmsvc_task)) {
++ error = PTR_ERR(nlmsvc_task);
++ nlmsvc_task = NULL;
++ nlmsvc_serv = NULL;
+ printk(KERN_WARNING
+- "lockd_up: create thread failed, error=%d\n", error);
++ "lockd_up: kthread_run failed, error=%d\n", error);
++ svc_exit_thread(rqstp);
+ goto destroy_and_out;
+ }
+- wait_for_completion(&lockd_start_done);
+
+ /*
+ * Note: svc_serv structures have an initial use count of 1,
+@@ -323,42 +331,28 @@ EXPORT_SYMBOL(lockd_up);
+ void
+ lockd_down(void)
+ {
+- static int warned;
+-
+ mutex_lock(&nlmsvc_mutex);
+ if (nlmsvc_users) {
+ if (--nlmsvc_users)
+ goto out;
+- } else
+- printk(KERN_WARNING "lockd_down: no users! pid=%d\n", nlmsvc_pid);
+-
+- if (!nlmsvc_pid) {
+- if (warned++ == 0)
+- printk(KERN_WARNING "lockd_down: no lockd running.\n");
+- goto out;
++ } else {
++ printk(KERN_ERR "lockd_down: no users! task=%p\n",
++ nlmsvc_task);
++ BUG();
+ }
+- warned = 0;
+
+- kill_proc(nlmsvc_pid, SIGKILL, 1);
+- /*
+- * Wait for the lockd process to exit, but since we're holding
+- * the lockd semaphore, we can't wait around forever ...
+- */
+- clear_thread_flag(TIF_SIGPENDING);
+- interruptible_sleep_on_timeout(&lockd_exit, HZ);
+- if (nlmsvc_pid) {
+- printk(KERN_WARNING
+- "lockd_down: lockd failed to exit, clearing pid\n");
+- nlmsvc_pid = 0;
++ if (!nlmsvc_task) {
++ printk(KERN_ERR "lockd_down: no lockd running.\n");
++ BUG();
+ }
+- spin_lock_irq(¤t->sighand->siglock);
+- recalc_sigpending();
+- spin_unlock_irq(¤t->sighand->siglock);
++ kthread_stop(nlmsvc_task);
+ out:
+ mutex_unlock(&nlmsvc_mutex);
+ }
+ EXPORT_SYMBOL(lockd_down);
+
++#ifdef CONFIG_SYSCTL
++
+ /*
+ * Sysctl parameters (same as module parameters, different interface).
+ */
+@@ -443,6 +437,8 @@ static ctl_table nlm_sysctl_root[] = {
+ { .ctl_name = 0 }
+ };
+
++#endif /* CONFIG_SYSCTL */
++
+ /*
+ * Module (and sysfs) parameters.
+ */
+@@ -516,15 +512,21 @@ module_param(nsm_use_hostnames, bool, 0644);
+
+ static int __init init_nlm(void)
+ {
++#ifdef CONFIG_SYSCTL
+ nlm_sysctl_table = register_sysctl_table(nlm_sysctl_root);
+ return nlm_sysctl_table ? 0 : -ENOMEM;
++#else
++ return 0;
++#endif
+ }
+
+ static void __exit exit_nlm(void)
+ {
+ /* FIXME: delete all NLM clients */
+ nlm_shutdown_hosts();
++#ifdef CONFIG_SYSCTL
+ unregister_sysctl_table(nlm_sysctl_table);
++#endif
+ }
+
+ module_init(init_nlm);
+diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
+index fe9bdb4..4d81553 100644
+--- a/fs/lockd/svclock.c
++++ b/fs/lockd/svclock.c
+@@ -29,6 +29,7 @@
+ #include <linux/sunrpc/svc.h>
+ #include <linux/lockd/nlm.h>
+ #include <linux/lockd/lockd.h>
++#include <linux/kthread.h>
+
+ #define NLMDBG_FACILITY NLMDBG_SVCLOCK
+
+@@ -226,8 +227,7 @@ failed:
+ }
+
+ /*
+- * Delete a block. If the lock was cancelled or the grant callback
+- * failed, unlock is set to 1.
++ * Delete a block.
+ * It is the caller's responsibility to check whether the file
+ * can be closed hereafter.
+ */
+@@ -632,7 +632,7 @@ nlmsvc_update_deferred_block(struct nlm_block *block, struct file_lock *conf,
+ block->b_flags |= B_TIMED_OUT;
+ if (conf) {
+ if (block->b_fl)
+- locks_copy_lock(block->b_fl, conf);
++ __locks_copy_lock(block->b_fl, conf);
+ }
+ }
+
+@@ -887,7 +887,7 @@ nlmsvc_retry_blocked(void)
+ unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
+ struct nlm_block *block;
+
+- while (!list_empty(&nlm_blocked)) {
++ while (!list_empty(&nlm_blocked) && !kthread_should_stop()) {
+ block = list_entry(nlm_blocked.next, struct nlm_block, b_list);
+
+ if (block->b_when == NLM_NEVER)
+diff --git a/fs/lockd/svcshare.c b/fs/lockd/svcshare.c
+index 068886d..b0ae070 100644
+--- a/fs/lockd/svcshare.c
++++ b/fs/lockd/svcshare.c
+@@ -71,7 +71,8 @@ nlmsvc_unshare_file(struct nlm_host *host, struct nlm_file *file,
+ struct nlm_share *share, **shpp;
+ struct xdr_netobj *oh = &argp->lock.oh;
+
+- for (shpp = &file->f_shares; (share = *shpp) != 0; shpp = &share->s_next) {
++ for (shpp = &file->f_shares; (share = *shpp) != NULL;
++ shpp = &share->s_next) {
+ if (share->s_host == host && nlm_cmp_owner(share, oh)) {
+ *shpp = share->s_next;
+ kfree(share);
+diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
+index dbbefbc..d1c48b5 100644
+--- a/fs/lockd/svcsubs.c
++++ b/fs/lockd/svcsubs.c
+@@ -18,6 +18,8 @@
+ #include <linux/lockd/lockd.h>
+ #include <linux/lockd/share.h>
+ #include <linux/lockd/sm_inter.h>
++#include <linux/module.h>
++#include <linux/mount.h>
+
+ #define NLMDBG_FACILITY NLMDBG_SVCSUBS
+
+@@ -194,6 +196,12 @@ again:
+ return 0;
+ }
+
++static int
++nlmsvc_always_match(void *dummy1, struct nlm_host *dummy2)
++{
++ return 1;
++}
++
+ /*
+ * Inspect a single file
+ */
+@@ -230,7 +238,8 @@ nlm_file_inuse(struct nlm_file *file)
+ * Loop over all files in the file table.
+ */
+ static int
+-nlm_traverse_files(struct nlm_host *host, nlm_host_match_fn_t match)
++nlm_traverse_files(void *data, nlm_host_match_fn_t match,
++ int (*is_failover_file)(void *data, struct nlm_file *file))
+ {
+ struct hlist_node *pos, *next;
+ struct nlm_file *file;
+@@ -239,12 +248,14 @@ nlm_traverse_files(struct nlm_host *host, nlm_host_match_fn_t match)
+ mutex_lock(&nlm_file_mutex);
+ for (i = 0; i < FILE_NRHASH; i++) {
+ hlist_for_each_entry_safe(file, pos, next, &nlm_files[i], f_list) {
++ if (is_failover_file && !is_failover_file(data, file))
++ continue;
+ file->f_count++;
+ mutex_unlock(&nlm_file_mutex);
+
+ /* Traverse locks, blocks and shares of this file
+ * and update file->f_locks count */
+- if (nlm_inspect_file(host, file, match))
++ if (nlm_inspect_file(data, file, match))
+ ret = 1;
+
+ mutex_lock(&nlm_file_mutex);
+@@ -303,21 +314,27 @@ nlm_release_file(struct nlm_file *file)
+ * Used by nlmsvc_invalidate_all
+ */
+ static int
+-nlmsvc_mark_host(struct nlm_host *host, struct nlm_host *dummy)
++nlmsvc_mark_host(void *data, struct nlm_host *dummy)
+ {
++ struct nlm_host *host = data;
++
+ host->h_inuse = 1;
+ return 0;
+ }
+
+ static int
+-nlmsvc_same_host(struct nlm_host *host, struct nlm_host *other)
++nlmsvc_same_host(void *data, struct nlm_host *other)
+ {
++ struct nlm_host *host = data;
++
+ return host == other;
+ }
+
+ static int
+-nlmsvc_is_client(struct nlm_host *host, struct nlm_host *dummy)
++nlmsvc_is_client(void *data, struct nlm_host *dummy)
+ {
++ struct nlm_host *host = data;
++
+ if (host->h_server) {
+ /* we are destroying locks even though the client
+ * hasn't asked us too, so don't unmonitor the
+@@ -337,7 +354,7 @@ void
+ nlmsvc_mark_resources(void)
+ {
+ dprintk("lockd: nlmsvc_mark_resources\n");
+- nlm_traverse_files(NULL, nlmsvc_mark_host);
++ nlm_traverse_files(NULL, nlmsvc_mark_host, NULL);
+ }
+
+ /*
+@@ -348,7 +365,7 @@ nlmsvc_free_host_resources(struct nlm_host *host)
+ {
+ dprintk("lockd: nlmsvc_free_host_resources\n");
+
+- if (nlm_traverse_files(host, nlmsvc_same_host)) {
++ if (nlm_traverse_files(host, nlmsvc_same_host, NULL)) {
+ printk(KERN_WARNING
+ "lockd: couldn't remove all locks held by %s\n",
+ host->h_name);
+@@ -368,5 +385,41 @@ nlmsvc_invalidate_all(void)
+ * turn, which is about as inefficient as it gets.
+ * Now we just do it once in nlm_traverse_files.
+ */
+- nlm_traverse_files(NULL, nlmsvc_is_client);
++ nlm_traverse_files(NULL, nlmsvc_is_client, NULL);
++}
++
++static int
++nlmsvc_match_sb(void *datap, struct nlm_file *file)
++{
++ struct super_block *sb = datap;
++
++ return sb == file->f_file->f_path.mnt->mnt_sb;
++}
++
++int
++nlmsvc_unlock_all_by_sb(struct super_block *sb)
++{
++ int ret;
++
++ ret = nlm_traverse_files(sb, nlmsvc_always_match, nlmsvc_match_sb);
++ return ret ? -EIO : 0;
++}
++EXPORT_SYMBOL_GPL(nlmsvc_unlock_all_by_sb);
++
++static int
++nlmsvc_match_ip(void *datap, struct nlm_host *host)
++{
++ __be32 *server_addr = datap;
++
++ return host->h_saddr.sin_addr.s_addr == *server_addr;
++}
++
++int
++nlmsvc_unlock_all_by_ip(__be32 server_addr)
++{
++ int ret;
++ ret = nlm_traverse_files(&server_addr, nlmsvc_match_ip, NULL);
++ return ret ? -EIO : 0;
++
+ }
++EXPORT_SYMBOL_GPL(nlmsvc_unlock_all_by_ip);
+diff --git a/fs/locks.c b/fs/locks.c
+index 43c0af2..44d9a6a 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -127,7 +127,6 @@
+ #include <linux/rcupdate.h>
+ #include <linux/pid_namespace.h>
+
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+
+ #define IS_POSIX(fl) (fl->fl_flags & FL_POSIX)
+@@ -225,7 +224,7 @@ static void locks_copy_private(struct file_lock *new, struct file_lock *fl)
+ /*
+ * Initialize a new lock from an existing file_lock structure.
+ */
+-static void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl)
++void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl)
+ {
+ new->fl_owner = fl->fl_owner;
+ new->fl_pid = fl->fl_pid;
+@@ -237,6 +236,7 @@ static void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl)
+ new->fl_ops = NULL;
+ new->fl_lmops = NULL;
+ }
++EXPORT_SYMBOL(__locks_copy_lock);
+
+ void locks_copy_lock(struct file_lock *new, struct file_lock *fl)
+ {
+@@ -834,7 +834,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str
+ if (!posix_locks_conflict(request, fl))
+ continue;
+ if (conflock)
+- locks_copy_lock(conflock, fl);
++ __locks_copy_lock(conflock, fl);
+ error = -EAGAIN;
+ if (!(request->fl_flags & FL_SLEEP))
+ goto out;
+@@ -1368,18 +1368,20 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
+
+ lease = *flp;
+
+- error = -EAGAIN;
+- if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
+- goto out;
+- if ((arg == F_WRLCK)
+- && ((atomic_read(&dentry->d_count) > 1)
+- || (atomic_read(&inode->i_count) > 1)))
+- goto out;
++ if (arg != F_UNLCK) {
++ error = -ENOMEM;
++ new_fl = locks_alloc_lock();
++ if (new_fl == NULL)
++ goto out;
+
+- error = -ENOMEM;
+- new_fl = locks_alloc_lock();
+- if (new_fl == NULL)
+- goto out;
++ error = -EAGAIN;
++ if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
++ goto out;
++ if ((arg == F_WRLCK)
++ && ((atomic_read(&dentry->d_count) > 1)
++ || (atomic_read(&inode->i_count) > 1)))
++ goto out;
++ }
+
+ /*
+ * At this point, we know that if there is an exclusive
+@@ -1405,6 +1407,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
+ rdlease_count++;
+ }
+
++ error = -EAGAIN;
+ if ((arg == F_RDLCK && (wrlease_count > 0)) ||
+ (arg == F_WRLCK && ((rdlease_count + wrlease_count) > 0)))
+ goto out;
+@@ -1491,8 +1494,7 @@ EXPORT_SYMBOL_GPL(vfs_setlease);
+ int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
+ {
+ struct file_lock fl, *flp = &fl;
+- struct dentry *dentry = filp->f_path.dentry;
+- struct inode *inode = dentry->d_inode;
++ struct inode *inode = filp->f_path.dentry->d_inode;
+ int error;
+
+ locks_init_lock(&fl);
+diff --git a/fs/namei.c b/fs/namei.c
+index 8cf9bb9..e179f71 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -1623,8 +1623,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
+ return -EACCES;
+
+ flag &= ~O_TRUNC;
+- } else if (IS_RDONLY(inode) && (acc_mode & MAY_WRITE))
+- return -EROFS;
++ }
+
+ error = vfs_permission(nd, acc_mode);
+ if (error)
+@@ -1677,7 +1676,12 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
+ return 0;
+ }
+
+-static int open_namei_create(struct nameidata *nd, struct path *path,
++/*
++ * Be careful about ever adding any more callers of this
++ * function. Its flags must be in the namei format, not
++ * what get passed to sys_open().
++ */
++static int __open_namei_create(struct nameidata *nd, struct path *path,
+ int flag, int mode)
+ {
+ int error;
+@@ -1696,26 +1700,56 @@ static int open_namei_create(struct nameidata *nd, struct path *path,
+ }
+
+ /*
+- * open_namei()
++ * Note that while the flag value (low two bits) for sys_open means:
++ * 00 - read-only
++ * 01 - write-only
++ * 10 - read-write
++ * 11 - special
++ * it is changed into
++ * 00 - no permissions needed
++ * 01 - read-permission
++ * 10 - write-permission
++ * 11 - read-write
++ * for the internal routines (ie open_namei()/follow_link() etc)
++ * This is more logical, and also allows the 00 "no perm needed"
++ * to be used for symlinks (where the permissions are checked
++ * later).
+ *
+- * namei for open - this is in fact almost the whole open-routine.
+- *
+- * Note that the low bits of "flag" aren't the same as in the open
+- * system call - they are 00 - no permissions needed
+- * 01 - read permission needed
+- * 10 - write permission needed
+- * 11 - read/write permissions needed
+- * which is a lot more logical, and also allows the "no perm" needed
+- * for symlinks (where the permissions are checked later).
+- * SMP-safe
++*/
++static inline int open_to_namei_flags(int flag)
++{
++ if ((flag+1) & O_ACCMODE)
++ flag++;
++ return flag;
++}
++
++static int open_will_write_to_fs(int flag, struct inode *inode)
++{
++ /*
++ * We'll never write to the fs underlying
++ * a device file.
++ */
++ if (special_file(inode->i_mode))
++ return 0;
++ return (flag & O_TRUNC);
++}
++
++/*
++ * Note that the low bits of the passed in "open_flag"
++ * are not the same as in the local variable "flag". See
++ * open_to_namei_flags() for more details.
+ */
+-int open_namei(int dfd, const char *pathname, int flag,
+- int mode, struct nameidata *nd)
++struct file *do_filp_open(int dfd, const char *pathname,
++ int open_flag, int mode)
+ {
++ struct file *filp;
++ struct nameidata nd;
+ int acc_mode, error;
+ struct path path;
+ struct dentry *dir;
+ int count = 0;
++ int will_write;
++ int flag = open_to_namei_flags(open_flag);
+
+ acc_mode = ACC_MODE(flag);
+
+@@ -1733,18 +1767,19 @@ int open_namei(int dfd, const char *pathname, int flag,
+ */
+ if (!(flag & O_CREAT)) {
+ error = path_lookup_open(dfd, pathname, lookup_flags(flag),
+- nd, flag);
++ &nd, flag);
+ if (error)
+- return error;
++ return ERR_PTR(error);
+ goto ok;
+ }
+
+ /*
+ * Create - we need to know the parent.
+ */
+- error = path_lookup_create(dfd,pathname,LOOKUP_PARENT,nd,flag,mode);
++ error = path_lookup_create(dfd, pathname, LOOKUP_PARENT,
++ &nd, flag, mode);
+ if (error)
+- return error;
++ return ERR_PTR(error);
+
+ /*
+ * We have the parent and last component. First of all, check
+@@ -1752,14 +1787,14 @@ int open_namei(int dfd, const char *pathname, int flag,
+ * will not do.
+ */
+ error = -EISDIR;
+- if (nd->last_type != LAST_NORM || nd->last.name[nd->last.len])
++ if (nd.last_type != LAST_NORM || nd.last.name[nd.last.len])
+ goto exit;
+
+- dir = nd->path.dentry;
+- nd->flags &= ~LOOKUP_PARENT;
++ dir = nd.path.dentry;
++ nd.flags &= ~LOOKUP_PARENT;
+ mutex_lock(&dir->d_inode->i_mutex);
+- path.dentry = lookup_hash(nd);
+- path.mnt = nd->path.mnt;
++ path.dentry = lookup_hash(&nd);
++ path.mnt = nd.path.mnt;
+
+ do_last:
+ error = PTR_ERR(path.dentry);
+@@ -1768,18 +1803,31 @@ do_last:
+ goto exit;
+ }
+
+- if (IS_ERR(nd->intent.open.file)) {
+- mutex_unlock(&dir->d_inode->i_mutex);
+- error = PTR_ERR(nd->intent.open.file);
+- goto exit_dput;
++ if (IS_ERR(nd.intent.open.file)) {
++ error = PTR_ERR(nd.intent.open.file);
++ goto exit_mutex_unlock;
+ }
+
+ /* Negative dentry, just create the file */
+ if (!path.dentry->d_inode) {
+- error = open_namei_create(nd, &path, flag, mode);
++ /*
++ * This write is needed to ensure that a
++ * ro->rw transition does not occur between
++ * the time when the file is created and when
++ * a permanent write count is taken through
++ * the 'struct file' in nameidata_to_filp().
++ */
++ error = mnt_want_write(nd.path.mnt);
+ if (error)
++ goto exit_mutex_unlock;
++ error = __open_namei_create(&nd, &path, flag, mode);
++ if (error) {
++ mnt_drop_write(nd.path.mnt);
+ goto exit;
+- return 0;
++ }
++ filp = nameidata_to_filp(&nd, open_flag);
++ mnt_drop_write(nd.path.mnt);
++ return filp;
+ }
+
+ /*
+@@ -1804,23 +1852,52 @@ do_last:
+ if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link)
+ goto do_link;
+
+- path_to_nameidata(&path, nd);
++ path_to_nameidata(&path, &nd);
+ error = -EISDIR;
+ if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode))
+ goto exit;
+ ok:
+- error = may_open(nd, acc_mode, flag);
+- if (error)
++ /*
++ * Consider:
++ * 1. may_open() truncates a file
++ * 2. a rw->ro mount transition occurs
++ * 3. nameidata_to_filp() fails due to
++ * the ro mount.
++ * That would be inconsistent, and should
++ * be avoided. Taking this mnt write here
++ * ensures that (2) can not occur.
++ */
++ will_write = open_will_write_to_fs(flag, nd.path.dentry->d_inode);
++ if (will_write) {
++ error = mnt_want_write(nd.path.mnt);
++ if (error)
++ goto exit;
++ }
++ error = may_open(&nd, acc_mode, flag);
++ if (error) {
++ if (will_write)
++ mnt_drop_write(nd.path.mnt);
+ goto exit;
+- return 0;
++ }
++ filp = nameidata_to_filp(&nd, open_flag);
++ /*
++ * It is now safe to drop the mnt write
++ * because the filp has had a write taken
++ * on its behalf.
++ */
++ if (will_write)
++ mnt_drop_write(nd.path.mnt);
++ return filp;
+
++exit_mutex_unlock:
++ mutex_unlock(&dir->d_inode->i_mutex);
+ exit_dput:
+- path_put_conditional(&path, nd);
++ path_put_conditional(&path, &nd);
+ exit:
+- if (!IS_ERR(nd->intent.open.file))
+- release_open_intent(nd);
+- path_put(&nd->path);
+- return error;
++ if (!IS_ERR(nd.intent.open.file))
++ release_open_intent(&nd);
++ path_put(&nd.path);
++ return ERR_PTR(error);
+
+ do_link:
+ error = -ELOOP;
+@@ -1836,43 +1913,60 @@ do_link:
+ * stored in nd->last.name and we will have to putname() it when we
+ * are done. Procfs-like symlinks just set LAST_BIND.
+ */
+- nd->flags |= LOOKUP_PARENT;
+- error = security_inode_follow_link(path.dentry, nd);
++ nd.flags |= LOOKUP_PARENT;
++ error = security_inode_follow_link(path.dentry, &nd);
+ if (error)
+ goto exit_dput;
+- error = __do_follow_link(&path, nd);
++ error = __do_follow_link(&path, &nd);
+ if (error) {
+ /* Does someone understand code flow here? Or it is only
+ * me so stupid? Anathema to whoever designed this non-sense
+ * with "intent.open".
+ */
+- release_open_intent(nd);
+- return error;
++ release_open_intent(&nd);
++ return ERR_PTR(error);
+ }
+- nd->flags &= ~LOOKUP_PARENT;
+- if (nd->last_type == LAST_BIND)
++ nd.flags &= ~LOOKUP_PARENT;
++ if (nd.last_type == LAST_BIND)
+ goto ok;
+ error = -EISDIR;
+- if (nd->last_type != LAST_NORM)
++ if (nd.last_type != LAST_NORM)
+ goto exit;
+- if (nd->last.name[nd->last.len]) {
+- __putname(nd->last.name);
++ if (nd.last.name[nd.last.len]) {
++ __putname(nd.last.name);
+ goto exit;
+ }
+ error = -ELOOP;
+ if (count++==32) {
+- __putname(nd->last.name);
++ __putname(nd.last.name);
+ goto exit;
+ }
+- dir = nd->path.dentry;
++ dir = nd.path.dentry;
+ mutex_lock(&dir->d_inode->i_mutex);
+- path.dentry = lookup_hash(nd);
+- path.mnt = nd->path.mnt;
+- __putname(nd->last.name);
++ path.dentry = lookup_hash(&nd);
++ path.mnt = nd.path.mnt;
++ __putname(nd.last.name);
+ goto do_last;
+ }
+
+ /**
++ * filp_open - open file and return file pointer
++ *
++ * @filename: path to open
++ * @flags: open flags as per the open(2) second argument
++ * @mode: mode for the new file if O_CREAT is set, else ignored
++ *
++ * This is the helper to open a file from kernelspace if you really
++ * have to. But in generally you should not do this, so please move
++ * along, nothing to see here..
++ */
++struct file *filp_open(const char *filename, int flags, int mode)
++{
++ return do_filp_open(AT_FDCWD, filename, flags, mode);
++}
++EXPORT_SYMBOL(filp_open);
++
++/**
+ * lookup_create - lookup a dentry, creating it if it doesn't exist
+ * @nd: nameidata info
+ * @is_dir: directory flag
+@@ -1945,6 +2039,23 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+ return error;
+ }
+
++static int may_mknod(mode_t mode)
++{
++ switch (mode & S_IFMT) {
++ case S_IFREG:
++ case S_IFCHR:
++ case S_IFBLK:
++ case S_IFIFO:
++ case S_IFSOCK:
++ case 0: /* zero mode translates to S_IFREG */
++ return 0;
++ case S_IFDIR:
++ return -EPERM;
++ default:
++ return -EINVAL;
++ }
++}
++
+ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode,
+ unsigned dev)
+ {
+@@ -1963,12 +2074,19 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode,
+ if (error)
+ goto out;
+ dentry = lookup_create(&nd, 0);
+- error = PTR_ERR(dentry);
+-
++ if (IS_ERR(dentry)) {
++ error = PTR_ERR(dentry);
++ goto out_unlock;
++ }
+ if (!IS_POSIXACL(nd.path.dentry->d_inode))
+ mode &= ~current->fs->umask;
+- if (!IS_ERR(dentry)) {
+- switch (mode & S_IFMT) {
++ error = may_mknod(mode);
++ if (error)
++ goto out_dput;
++ error = mnt_want_write(nd.path.mnt);
++ if (error)
++ goto out_dput;
++ switch (mode & S_IFMT) {
+ case 0: case S_IFREG:
+ error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd);
+ break;
+@@ -1979,14 +2097,11 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode,
+ case S_IFIFO: case S_IFSOCK:
+ error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0);
+ break;
+- case S_IFDIR:
+- error = -EPERM;
+- break;
+- default:
+- error = -EINVAL;
+- }
+- dput(dentry);
+ }
++ mnt_drop_write(nd.path.mnt);
++out_dput:
++ dput(dentry);
++out_unlock:
+ mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+ path_put(&nd.path);
+ out:
+@@ -2044,7 +2159,12 @@ asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode)
+
+ if (!IS_POSIXACL(nd.path.dentry->d_inode))
+ mode &= ~current->fs->umask;
++ error = mnt_want_write(nd.path.mnt);
++ if (error)
++ goto out_dput;
+ error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode);
++ mnt_drop_write(nd.path.mnt);
++out_dput:
+ dput(dentry);
+ out_unlock:
+ mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+@@ -2151,7 +2271,12 @@ static long do_rmdir(int dfd, const char __user *pathname)
+ error = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
+ goto exit2;
++ error = mnt_want_write(nd.path.mnt);
++ if (error)
++ goto exit3;
+ error = vfs_rmdir(nd.path.dentry->d_inode, dentry);
++ mnt_drop_write(nd.path.mnt);
++exit3:
+ dput(dentry);
+ exit2:
+ mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+@@ -2232,7 +2357,11 @@ static long do_unlinkat(int dfd, const char __user *pathname)
+ inode = dentry->d_inode;
+ if (inode)
+ atomic_inc(&inode->i_count);
++ error = mnt_want_write(nd.path.mnt);
++ if (error)
++ goto exit2;
+ error = vfs_unlink(nd.path.dentry->d_inode, dentry);
++ mnt_drop_write(nd.path.mnt);
+ exit2:
+ dput(dentry);
+ }
+@@ -2313,7 +2442,12 @@ asmlinkage long sys_symlinkat(const char __user *oldname,
+ if (IS_ERR(dentry))
+ goto out_unlock;
+
++ error = mnt_want_write(nd.path.mnt);
++ if (error)
++ goto out_dput;
+ error = vfs_symlink(nd.path.dentry->d_inode, dentry, from, S_IALLUGO);
++ mnt_drop_write(nd.path.mnt);
++out_dput:
+ dput(dentry);
+ out_unlock:
+ mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+@@ -2408,7 +2542,12 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
+ error = PTR_ERR(new_dentry);
+ if (IS_ERR(new_dentry))
+ goto out_unlock;
++ error = mnt_want_write(nd.path.mnt);
++ if (error)
++ goto out_dput;
+ error = vfs_link(old_nd.path.dentry, nd.path.dentry->d_inode, new_dentry);
++ mnt_drop_write(nd.path.mnt);
++out_dput:
+ dput(new_dentry);
+ out_unlock:
+ mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+@@ -2634,8 +2773,12 @@ static int do_rename(int olddfd, const char *oldname,
+ if (new_dentry == trap)
+ goto exit5;
+
++ error = mnt_want_write(oldnd.path.mnt);
++ if (error)
++ goto exit5;
+ error = vfs_rename(old_dir->d_inode, old_dentry,
+ new_dir->d_inode, new_dentry);
++ mnt_drop_write(oldnd.path.mnt);
+ exit5:
+ dput(new_dentry);
+ exit4:
+diff --git a/fs/namespace.c b/fs/namespace.c
+index 94f026e..f48f981 100644
+--- a/fs/namespace.c
++++ b/fs/namespace.c
+@@ -17,6 +17,7 @@
+ #include <linux/quotaops.h>
+ #include <linux/acct.h>
+ #include <linux/capability.h>
++#include <linux/cpumask.h>
+ #include <linux/module.h>
+ #include <linux/sysfs.h>
+ #include <linux/seq_file.h>
+@@ -26,6 +27,7 @@
+ #include <linux/mount.h>
+ #include <linux/ramfs.h>
+ #include <linux/log2.h>
++#include <linux/idr.h>
+ #include <asm/uaccess.h>
+ #include <asm/unistd.h>
+ #include "pnode.h"
+@@ -38,6 +40,8 @@
+ __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
+
+ static int event;
++static DEFINE_IDA(mnt_id_ida);
++static DEFINE_IDA(mnt_group_ida);
+
+ static struct list_head *mount_hashtable __read_mostly;
+ static struct kmem_cache *mnt_cache __read_mostly;
+@@ -55,10 +59,65 @@ static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
+ return tmp & (HASH_SIZE - 1);
+ }
+
++#define MNT_WRITER_UNDERFLOW_LIMIT -(1<<16)
++
++/* allocation is serialized by namespace_sem */
++static int mnt_alloc_id(struct vfsmount *mnt)
++{
++ int res;
++
++retry:
++ ida_pre_get(&mnt_id_ida, GFP_KERNEL);
++ spin_lock(&vfsmount_lock);
++ res = ida_get_new(&mnt_id_ida, &mnt->mnt_id);
++ spin_unlock(&vfsmount_lock);
++ if (res == -EAGAIN)
++ goto retry;
++
++ return res;
++}
++
++static void mnt_free_id(struct vfsmount *mnt)
++{
++ spin_lock(&vfsmount_lock);
++ ida_remove(&mnt_id_ida, mnt->mnt_id);
++ spin_unlock(&vfsmount_lock);
++}
++
++/*
++ * Allocate a new peer group ID
++ *
++ * mnt_group_ida is protected by namespace_sem
++ */
++static int mnt_alloc_group_id(struct vfsmount *mnt)
++{
++ if (!ida_pre_get(&mnt_group_ida, GFP_KERNEL))
++ return -ENOMEM;
++
++ return ida_get_new_above(&mnt_group_ida, 1, &mnt->mnt_group_id);
++}
++
++/*
++ * Release a peer group ID
++ */
++void mnt_release_group_id(struct vfsmount *mnt)
++{
++ ida_remove(&mnt_group_ida, mnt->mnt_group_id);
++ mnt->mnt_group_id = 0;
++}
++
+ struct vfsmount *alloc_vfsmnt(const char *name)
+ {
+ struct vfsmount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL);
+ if (mnt) {
++ int err;
++
++ err = mnt_alloc_id(mnt);
++ if (err) {
++ kmem_cache_free(mnt_cache, mnt);
++ return NULL;
++ }
++
+ atomic_set(&mnt->mnt_count, 1);
+ INIT_LIST_HEAD(&mnt->mnt_hash);
+ INIT_LIST_HEAD(&mnt->mnt_child);
+@@ -68,6 +127,7 @@ struct vfsmount *alloc_vfsmnt(const char *name)
+ INIT_LIST_HEAD(&mnt->mnt_share);
+ INIT_LIST_HEAD(&mnt->mnt_slave_list);
+ INIT_LIST_HEAD(&mnt->mnt_slave);
++ atomic_set(&mnt->__mnt_writers, 0);
+ if (name) {
+ int size = strlen(name) + 1;
+ char *newname = kmalloc(size, GFP_KERNEL);
+@@ -80,6 +140,263 @@ struct vfsmount *alloc_vfsmnt(const char *name)
+ return mnt;
+ }
+
++/*
++ * Most r/o checks on a fs are for operations that take
++ * discrete amounts of time, like a write() or unlink().
++ * We must keep track of when those operations start
++ * (for permission checks) and when they end, so that
++ * we can determine when writes are able to occur to
++ * a filesystem.
++ */
++/*
++ * __mnt_is_readonly: check whether a mount is read-only
++ * @mnt: the mount to check for its write status
++ *
++ * This shouldn't be used directly ouside of the VFS.
++ * It does not guarantee that the filesystem will stay
++ * r/w, just that it is right *now*. This can not and
++ * should not be used in place of IS_RDONLY(inode).
++ * mnt_want/drop_write() will _keep_ the filesystem
++ * r/w.
++ */
++int __mnt_is_readonly(struct vfsmount *mnt)
++{
++ if (mnt->mnt_flags & MNT_READONLY)
++ return 1;
++ if (mnt->mnt_sb->s_flags & MS_RDONLY)
++ return 1;
++ return 0;
++}
++EXPORT_SYMBOL_GPL(__mnt_is_readonly);
++
++struct mnt_writer {
++ /*
++ * If holding multiple instances of this lock, they
++ * must be ordered by cpu number.
++ */
++ spinlock_t lock;
++ struct lock_class_key lock_class; /* compiles out with !lockdep */
++ unsigned long count;
++ struct vfsmount *mnt;
++} ____cacheline_aligned_in_smp;
++static DEFINE_PER_CPU(struct mnt_writer, mnt_writers);
++
++static int __init init_mnt_writers(void)
++{
++ int cpu;
++ for_each_possible_cpu(cpu) {
++ struct mnt_writer *writer = &per_cpu(mnt_writers, cpu);
++ spin_lock_init(&writer->lock);
++ lockdep_set_class(&writer->lock, &writer->lock_class);
++ writer->count = 0;
++ }
++ return 0;
++}
++fs_initcall(init_mnt_writers);
++
++static void unlock_mnt_writers(void)
++{
++ int cpu;
++ struct mnt_writer *cpu_writer;
++
++ for_each_possible_cpu(cpu) {
++ cpu_writer = &per_cpu(mnt_writers, cpu);
++ spin_unlock(&cpu_writer->lock);
++ }
++}
++
++static inline void __clear_mnt_count(struct mnt_writer *cpu_writer)
++{
++ if (!cpu_writer->mnt)
++ return;
++ /*
++ * This is in case anyone ever leaves an invalid,
++ * old ->mnt and a count of 0.
++ */
++ if (!cpu_writer->count)
++ return;
++ atomic_add(cpu_writer->count, &cpu_writer->mnt->__mnt_writers);
++ cpu_writer->count = 0;
++}
++ /*
++ * must hold cpu_writer->lock
++ */
++static inline void use_cpu_writer_for_mount(struct mnt_writer *cpu_writer,
++ struct vfsmount *mnt)
++{
++ if (cpu_writer->mnt == mnt)
++ return;
++ __clear_mnt_count(cpu_writer);
++ cpu_writer->mnt = mnt;
++}
++
++/*
++ * Most r/o checks on a fs are for operations that take
++ * discrete amounts of time, like a write() or unlink().
++ * We must keep track of when those operations start
++ * (for permission checks) and when they end, so that
++ * we can determine when writes are able to occur to
++ * a filesystem.
++ */
++/**
++ * mnt_want_write - get write access to a mount
++ * @mnt: the mount on which to take a write
++ *
++ * This tells the low-level filesystem that a write is
++ * about to be performed to it, and makes sure that
++ * writes are allowed before returning success. When
++ * the write operation is finished, mnt_drop_write()
++ * must be called. This is effectively a refcount.
++ */
++int mnt_want_write(struct vfsmount *mnt)
++{
++ int ret = 0;
++ struct mnt_writer *cpu_writer;
++
++ cpu_writer = &get_cpu_var(mnt_writers);
++ spin_lock(&cpu_writer->lock);
++ if (__mnt_is_readonly(mnt)) {
++ ret = -EROFS;
++ goto out;
++ }
++ use_cpu_writer_for_mount(cpu_writer, mnt);
++ cpu_writer->count++;
++out:
++ spin_unlock(&cpu_writer->lock);
++ put_cpu_var(mnt_writers);
++ return ret;
++}
++EXPORT_SYMBOL_GPL(mnt_want_write);
++
++static void lock_mnt_writers(void)
++{
++ int cpu;
++ struct mnt_writer *cpu_writer;
++
++ for_each_possible_cpu(cpu) {
++ cpu_writer = &per_cpu(mnt_writers, cpu);
++ spin_lock(&cpu_writer->lock);
++ __clear_mnt_count(cpu_writer);
++ cpu_writer->mnt = NULL;
++ }
++}
++
++/*
++ * These per-cpu write counts are not guaranteed to have
++ * matched increments and decrements on any given cpu.
++ * A file open()ed for write on one cpu and close()d on
++ * another cpu will imbalance this count. Make sure it
++ * does not get too far out of whack.
++ */
++static void handle_write_count_underflow(struct vfsmount *mnt)
++{
++ if (atomic_read(&mnt->__mnt_writers) >=
++ MNT_WRITER_UNDERFLOW_LIMIT)
++ return;
++ /*
++ * It isn't necessary to hold all of the locks
++ * at the same time, but doing it this way makes
++ * us share a lot more code.
++ */
++ lock_mnt_writers();
++ /*
++ * vfsmount_lock is for mnt_flags.
++ */
++ spin_lock(&vfsmount_lock);
++ /*
++ * If coalescing the per-cpu writer counts did not
++ * get us back to a positive writer count, we have
++ * a bug.
++ */
++ if ((atomic_read(&mnt->__mnt_writers) < 0) &&
++ !(mnt->mnt_flags & MNT_IMBALANCED_WRITE_COUNT)) {
++ printk(KERN_DEBUG "leak detected on mount(%p) writers "
++ "count: %d\n",
++ mnt, atomic_read(&mnt->__mnt_writers));
++ WARN_ON(1);
++ /* use the flag to keep the dmesg spam down */
++ mnt->mnt_flags |= MNT_IMBALANCED_WRITE_COUNT;
++ }
++ spin_unlock(&vfsmount_lock);
++ unlock_mnt_writers();
++}
++
++/**
++ * mnt_drop_write - give up write access to a mount
++ * @mnt: the mount on which to give up write access
++ *
++ * Tells the low-level filesystem that we are done
++ * performing writes to it. Must be matched with
++ * mnt_want_write() call above.
++ */
++void mnt_drop_write(struct vfsmount *mnt)
++{
++ int must_check_underflow = 0;
++ struct mnt_writer *cpu_writer;
++
++ cpu_writer = &get_cpu_var(mnt_writers);
++ spin_lock(&cpu_writer->lock);
++
++ use_cpu_writer_for_mount(cpu_writer, mnt);
++ if (cpu_writer->count > 0) {
++ cpu_writer->count--;
++ } else {
++ must_check_underflow = 1;
++ atomic_dec(&mnt->__mnt_writers);
++ }
++
++ spin_unlock(&cpu_writer->lock);
++ /*
++ * Logically, we could call this each time,
++ * but the __mnt_writers cacheline tends to
++ * be cold, and makes this expensive.
++ */
++ if (must_check_underflow)
++ handle_write_count_underflow(mnt);
++ /*
++ * This could be done right after the spinlock
++ * is taken because the spinlock keeps us on
++ * the cpu, and disables preemption. However,
++ * putting it here bounds the amount that
++ * __mnt_writers can underflow. Without it,
++ * we could theoretically wrap __mnt_writers.
++ */
++ put_cpu_var(mnt_writers);
++}
++EXPORT_SYMBOL_GPL(mnt_drop_write);
++
++static int mnt_make_readonly(struct vfsmount *mnt)
++{
++ int ret = 0;
++
++ lock_mnt_writers();
++ /*
++ * With all the locks held, this value is stable
++ */
++ if (atomic_read(&mnt->__mnt_writers) > 0) {
++ ret = -EBUSY;
++ goto out;
++ }
++ /*
++ * nobody can do a successful mnt_want_write() with all
++ * of the counts in MNT_DENIED_WRITE and the locks held.
++ */
++ spin_lock(&vfsmount_lock);
++ if (!ret)
++ mnt->mnt_flags |= MNT_READONLY;
++ spin_unlock(&vfsmount_lock);
++out:
++ unlock_mnt_writers();
++ return ret;
++}
++
++static void __mnt_unmake_readonly(struct vfsmount *mnt)
++{
++ spin_lock(&vfsmount_lock);
++ mnt->mnt_flags &= ~MNT_READONLY;
++ spin_unlock(&vfsmount_lock);
++}
++
+ int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb)
+ {
+ mnt->mnt_sb = sb;
+@@ -92,6 +409,7 @@ EXPORT_SYMBOL(simple_set_mnt);
+ void free_vfsmnt(struct vfsmount *mnt)
+ {
+ kfree(mnt->mnt_devname);
++ mnt_free_id(mnt);
+ kmem_cache_free(mnt_cache, mnt);
+ }
+
+@@ -238,6 +556,17 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
+ struct vfsmount *mnt = alloc_vfsmnt(old->mnt_devname);
+
+ if (mnt) {
++ if (flag & (CL_SLAVE | CL_PRIVATE))
++ mnt->mnt_group_id = 0; /* not a peer of original */
++ else
++ mnt->mnt_group_id = old->mnt_group_id;
++
++ if ((flag & CL_MAKE_SHARED) && !mnt->mnt_group_id) {
++ int err = mnt_alloc_group_id(mnt);
++ if (err)
++ goto out_free;
++ }
++
+ mnt->mnt_flags = old->mnt_flags;
+ atomic_inc(&sb->s_active);
+ mnt->mnt_sb = sb;
+@@ -267,11 +596,44 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
+ }
+ }
+ return mnt;
++
++ out_free:
++ free_vfsmnt(mnt);
++ return NULL;
+ }
+
+ static inline void __mntput(struct vfsmount *mnt)
+ {
++ int cpu;
+ struct super_block *sb = mnt->mnt_sb;
++ /*
++ * We don't have to hold all of the locks at the
++ * same time here because we know that we're the
++ * last reference to mnt and that no new writers
++ * can come in.
++ */
++ for_each_possible_cpu(cpu) {
++ struct mnt_writer *cpu_writer = &per_cpu(mnt_writers, cpu);
++ if (cpu_writer->mnt != mnt)
++ continue;
++ spin_lock(&cpu_writer->lock);
++ atomic_add(cpu_writer->count, &mnt->__mnt_writers);
++ cpu_writer->count = 0;
++ /*
++ * Might as well do this so that no one
++ * ever sees the pointer and expects
++ * it to be valid.
++ */
++ cpu_writer->mnt = NULL;
++ spin_unlock(&cpu_writer->lock);
++ }
++ /*
++ * This probably indicates that somebody messed
++ * up a mnt_want/drop_write() pair. If this
++ * happens, the filesystem was probably unable
++ * to make r/w->r/o transitions.
++ */
++ WARN_ON(atomic_read(&mnt->__mnt_writers));
+ dput(mnt->mnt_root);
+ free_vfsmnt(mnt);
+ deactivate_super(sb);
+@@ -362,20 +724,21 @@ void save_mount_options(struct super_block *sb, char *options)
+ }
+ EXPORT_SYMBOL(save_mount_options);
+
++#ifdef CONFIG_PROC_FS
+ /* iterator */
+ static void *m_start(struct seq_file *m, loff_t *pos)
+ {
+- struct mnt_namespace *n = m->private;
++ struct proc_mounts *p = m->private;
+
+ down_read(&namespace_sem);
+- return seq_list_start(&n->list, *pos);
++ return seq_list_start(&p->ns->list, *pos);
+ }
+
+ static void *m_next(struct seq_file *m, void *v, loff_t *pos)
+ {
+- struct mnt_namespace *n = m->private;
++ struct proc_mounts *p = m->private;
+
+- return seq_list_next(v, &n->list, pos);
++ return seq_list_next(v, &p->ns->list, pos);
+ }
+
+ static void m_stop(struct seq_file *m, void *v)
+@@ -383,20 +746,30 @@ static void m_stop(struct seq_file *m, void *v)
+ up_read(&namespace_sem);
+ }
+
+-static int show_vfsmnt(struct seq_file *m, void *v)
++struct proc_fs_info {
++ int flag;
++ const char *str;
++};
++
++static void show_sb_opts(struct seq_file *m, struct super_block *sb)
+ {
+- struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list);
+- int err = 0;
+- static struct proc_fs_info {
+- int flag;
+- char *str;
+- } fs_info[] = {
++ static const struct proc_fs_info fs_info[] = {
+ { MS_SYNCHRONOUS, ",sync" },
+ { MS_DIRSYNC, ",dirsync" },
+ { MS_MANDLOCK, ",mand" },
+ { 0, NULL }
+ };
+- static struct proc_fs_info mnt_info[] = {
++ const struct proc_fs_info *fs_infop;
++
++ for (fs_infop = fs_info; fs_infop->flag; fs_infop++) {
++ if (sb->s_flags & fs_infop->flag)
++ seq_puts(m, fs_infop->str);
++ }
++}
++
++static void show_mnt_opts(struct seq_file *m, struct vfsmount *mnt)
++{
++ static const struct proc_fs_info mnt_info[] = {
+ { MNT_NOSUID, ",nosuid" },
+ { MNT_NODEV, ",nodev" },
+ { MNT_NOEXEC, ",noexec" },
+@@ -405,40 +778,108 @@ static int show_vfsmnt(struct seq_file *m, void *v)
+ { MNT_RELATIME, ",relatime" },
+ { 0, NULL }
+ };
+- struct proc_fs_info *fs_infop;
++ const struct proc_fs_info *fs_infop;
++
++ for (fs_infop = mnt_info; fs_infop->flag; fs_infop++) {
++ if (mnt->mnt_flags & fs_infop->flag)
++ seq_puts(m, fs_infop->str);
++ }
++}
++
++static void show_type(struct seq_file *m, struct super_block *sb)
++{
++ mangle(m, sb->s_type->name);
++ if (sb->s_subtype && sb->s_subtype[0]) {
++ seq_putc(m, '.');
++ mangle(m, sb->s_subtype);
++ }
++}
++
++static int show_vfsmnt(struct seq_file *m, void *v)
++{
++ struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list);
++ int err = 0;
+ struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
+
+ mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none");
+ seq_putc(m, ' ');
+ seq_path(m, &mnt_path, " \t\n\\");
+ seq_putc(m, ' ');
+- mangle(m, mnt->mnt_sb->s_type->name);
+- if (mnt->mnt_sb->s_subtype && mnt->mnt_sb->s_subtype[0]) {
+- seq_putc(m, '.');
+- mangle(m, mnt->mnt_sb->s_subtype);
+- }
+- seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? " ro" : " rw");
+- for (fs_infop = fs_info; fs_infop->flag; fs_infop++) {
+- if (mnt->mnt_sb->s_flags & fs_infop->flag)
+- seq_puts(m, fs_infop->str);
+- }
+- for (fs_infop = mnt_info; fs_infop->flag; fs_infop++) {
+- if (mnt->mnt_flags & fs_infop->flag)
+- seq_puts(m, fs_infop->str);
+- }
++ show_type(m, mnt->mnt_sb);
++ seq_puts(m, __mnt_is_readonly(mnt) ? " ro" : " rw");
++ show_sb_opts(m, mnt->mnt_sb);
++ show_mnt_opts(m, mnt);
+ if (mnt->mnt_sb->s_op->show_options)
+ err = mnt->mnt_sb->s_op->show_options(m, mnt);
+ seq_puts(m, " 0 0\n");
+ return err;
+ }
+
+-struct seq_operations mounts_op = {
++const struct seq_operations mounts_op = {
+ .start = m_start,
+ .next = m_next,
+ .stop = m_stop,
+ .show = show_vfsmnt
+ };
+
++static int show_mountinfo(struct seq_file *m, void *v)
++{
++ struct proc_mounts *p = m->private;
++ struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list);
++ struct super_block *sb = mnt->mnt_sb;
++ struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
++ struct path root = p->root;
++ int err = 0;
++
++ seq_printf(m, "%i %i %u:%u ", mnt->mnt_id, mnt->mnt_parent->mnt_id,
++ MAJOR(sb->s_dev), MINOR(sb->s_dev));
++ seq_dentry(m, mnt->mnt_root, " \t\n\\");
++ seq_putc(m, ' ');
++ seq_path_root(m, &mnt_path, &root, " \t\n\\");
++ if (root.mnt != p->root.mnt || root.dentry != p->root.dentry) {
++ /*
++ * Mountpoint is outside root, discard that one. Ugly,
++ * but less so than trying to do that in iterator in a
++ * race-free way (due to renames).
++ */
++ return SEQ_SKIP;
++ }
++ seq_puts(m, mnt->mnt_flags & MNT_READONLY ? " ro" : " rw");
++ show_mnt_opts(m, mnt);
++
++ /* Tagged fields ("foo:X" or "bar") */
++ if (IS_MNT_SHARED(mnt))
++ seq_printf(m, " shared:%i", mnt->mnt_group_id);
++ if (IS_MNT_SLAVE(mnt)) {
++ int master = mnt->mnt_master->mnt_group_id;
++ int dom = get_dominating_id(mnt, &p->root);
++ seq_printf(m, " master:%i", master);
++ if (dom && dom != master)
++ seq_printf(m, " propagate_from:%i", dom);
++ }
++ if (IS_MNT_UNBINDABLE(mnt))
++ seq_puts(m, " unbindable");
++
++ /* Filesystem specific data */
++ seq_puts(m, " - ");
++ show_type(m, sb);
++ seq_putc(m, ' ');
++ mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none");
++ seq_puts(m, sb->s_flags & MS_RDONLY ? " ro" : " rw");
++ show_sb_opts(m, sb);
++ if (sb->s_op->show_options)
++ err = sb->s_op->show_options(m, mnt);
++ seq_putc(m, '\n');
++ return err;
++}
++
++const struct seq_operations mountinfo_op = {
++ .start = m_start,
++ .next = m_next,
++ .stop = m_stop,
++ .show = show_mountinfo,
++};
++
+ static int show_vfsstat(struct seq_file *m, void *v)
+ {
+ struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list);
+@@ -459,7 +900,7 @@ static int show_vfsstat(struct seq_file *m, void *v)
+
+ /* file system type */
+ seq_puts(m, "with fstype ");
+- mangle(m, mnt->mnt_sb->s_type->name);
++ show_type(m, mnt->mnt_sb);
+
+ /* optional statistics */
+ if (mnt->mnt_sb->s_op->show_stats) {
+@@ -471,12 +912,13 @@ static int show_vfsstat(struct seq_file *m, void *v)
+ return err;
+ }
+
+-struct seq_operations mountstats_op = {
++const struct seq_operations mountstats_op = {
+ .start = m_start,
+ .next = m_next,
+ .stop = m_stop,
+ .show = show_vfsstat,
+ };
++#endif /* CONFIG_PROC_FS */
+
+ /**
+ * may_umount_tree - check if a mount tree is busy
+@@ -619,10 +1061,11 @@ static int do_umount(struct vfsmount *mnt, int flags)
+ * about for the moment.
+ */
+
+- lock_kernel();
+- if (sb->s_op->umount_begin)
+- sb->s_op->umount_begin(mnt, flags);
+- unlock_kernel();
++ if (flags & MNT_FORCE && sb->s_op->umount_begin) {
++ lock_kernel();
++ sb->s_op->umount_begin(sb);
++ unlock_kernel();
++ }
+
+ /*
+ * No sense to grab the lock for this test, but test itself looks
+@@ -801,23 +1244,50 @@ Enomem:
+ struct vfsmount *collect_mounts(struct vfsmount *mnt, struct dentry *dentry)
+ {
+ struct vfsmount *tree;
+- down_read(&namespace_sem);
++ down_write(&namespace_sem);
+ tree = copy_tree(mnt, dentry, CL_COPY_ALL | CL_PRIVATE);
+- up_read(&namespace_sem);
++ up_write(&namespace_sem);
+ return tree;
+ }
+
+ void drop_collected_mounts(struct vfsmount *mnt)
+ {
+ LIST_HEAD(umount_list);
+- down_read(&namespace_sem);
++ down_write(&namespace_sem);
+ spin_lock(&vfsmount_lock);
+ umount_tree(mnt, 0, &umount_list);
+ spin_unlock(&vfsmount_lock);
+- up_read(&namespace_sem);
++ up_write(&namespace_sem);
+ release_mounts(&umount_list);
+ }
+
++static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end)
++{
++ struct vfsmount *p;
++
++ for (p = mnt; p != end; p = next_mnt(p, mnt)) {
++ if (p->mnt_group_id && !IS_MNT_SHARED(p))
++ mnt_release_group_id(p);
++ }
++}
++
++static int invent_group_ids(struct vfsmount *mnt, bool recurse)
++{
++ struct vfsmount *p;
++
++ for (p = mnt; p; p = recurse ? next_mnt(p, mnt) : NULL) {
++ if (!p->mnt_group_id && !IS_MNT_SHARED(p)) {
++ int err = mnt_alloc_group_id(p);
++ if (err) {
++ cleanup_group_ids(mnt, p);
++ return err;
++ }
++ }
++ }
++
++ return 0;
++}
++
+ /*
+ * @source_mnt : mount tree to be attached
+ * @nd : place the mount tree @source_mnt is attached
+@@ -888,9 +1358,16 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt,
+ struct vfsmount *dest_mnt = path->mnt;
+ struct dentry *dest_dentry = path->dentry;
+ struct vfsmount *child, *p;
++ int err;
+
+- if (propagate_mnt(dest_mnt, dest_dentry, source_mnt, &tree_list))
+- return -EINVAL;
++ if (IS_MNT_SHARED(dest_mnt)) {
++ err = invent_group_ids(source_mnt, true);
++ if (err)
++ goto out;
++ }
++ err = propagate_mnt(dest_mnt, dest_dentry, source_mnt, &tree_list);
++ if (err)
++ goto out_cleanup_ids;
+
+ if (IS_MNT_SHARED(dest_mnt)) {
+ for (p = source_mnt; p; p = next_mnt(p, source_mnt))
+@@ -913,34 +1390,40 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt,
+ }
+ spin_unlock(&vfsmount_lock);
+ return 0;
++
++ out_cleanup_ids:
++ if (IS_MNT_SHARED(dest_mnt))
++ cleanup_group_ids(source_mnt, NULL);
++ out:
++ return err;
+ }
+
+-static int graft_tree(struct vfsmount *mnt, struct nameidata *nd)
++static int graft_tree(struct vfsmount *mnt, struct path *path)
+ {
+ int err;
+ if (mnt->mnt_sb->s_flags & MS_NOUSER)
+ return -EINVAL;
+
+- if (S_ISDIR(nd->path.dentry->d_inode->i_mode) !=
++ if (S_ISDIR(path->dentry->d_inode->i_mode) !=
+ S_ISDIR(mnt->mnt_root->d_inode->i_mode))
+ return -ENOTDIR;
+
+ err = -ENOENT;
+- mutex_lock(&nd->path.dentry->d_inode->i_mutex);
+- if (IS_DEADDIR(nd->path.dentry->d_inode))
++ mutex_lock(&path->dentry->d_inode->i_mutex);
++ if (IS_DEADDIR(path->dentry->d_inode))
+ goto out_unlock;
+
+- err = security_sb_check_sb(mnt, nd);
++ err = security_sb_check_sb(mnt, path);
+ if (err)
+ goto out_unlock;
+
+ err = -ENOENT;
+- if (IS_ROOT(nd->path.dentry) || !d_unhashed(nd->path.dentry))
+- err = attach_recursive_mnt(mnt, &nd->path, NULL);
++ if (IS_ROOT(path->dentry) || !d_unhashed(path->dentry))
++ err = attach_recursive_mnt(mnt, path, NULL);
+ out_unlock:
+- mutex_unlock(&nd->path.dentry->d_inode->i_mutex);
++ mutex_unlock(&path->dentry->d_inode->i_mutex);
+ if (!err)
+- security_sb_post_addmount(mnt, nd);
++ security_sb_post_addmount(mnt, path);
+ return err;
+ }
+
+@@ -953,6 +1436,7 @@ static noinline int do_change_type(struct nameidata *nd, int flag)
+ struct vfsmount *m, *mnt = nd->path.mnt;
+ int recurse = flag & MS_REC;
+ int type = flag & ~MS_REC;
++ int err = 0;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+@@ -961,12 +1445,20 @@ static noinline int do_change_type(struct nameidata *nd, int flag)
+ return -EINVAL;
+
+ down_write(&namespace_sem);
++ if (type == MS_SHARED) {
++ err = invent_group_ids(mnt, recurse);
++ if (err)
++ goto out_unlock;
++ }
++
+ spin_lock(&vfsmount_lock);
+ for (m = mnt; m; m = (recurse ? next_mnt(m, mnt) : NULL))
+ change_mnt_propagation(m, type);
+ spin_unlock(&vfsmount_lock);
++
++ out_unlock:
+ up_write(&namespace_sem);
+- return 0;
++ return err;
+ }
+
+ /*
+@@ -1004,7 +1496,7 @@ static noinline int do_loopback(struct nameidata *nd, char *old_name,
+ if (!mnt)
+ goto out;
+
+- err = graft_tree(mnt, nd);
++ err = graft_tree(mnt, &nd->path);
+ if (err) {
+ LIST_HEAD(umount_list);
+ spin_lock(&vfsmount_lock);
+@@ -1019,6 +1511,23 @@ out:
+ return err;
+ }
+
++static int change_mount_flags(struct vfsmount *mnt, int ms_flags)
++{
++ int error = 0;
++ int readonly_request = 0;
++
++ if (ms_flags & MS_RDONLY)
++ readonly_request = 1;
++ if (readonly_request == __mnt_is_readonly(mnt))
++ return 0;
++
++ if (readonly_request)
++ error = mnt_make_readonly(mnt);
++ else
++ __mnt_unmake_readonly(mnt);
++ return error;
++}
++
+ /*
+ * change filesystem flags. dir should be a physical root of filesystem.
+ * If you've mounted a non-root directory somewhere and want to do remount
+@@ -1041,7 +1550,10 @@ static noinline int do_remount(struct nameidata *nd, int flags, int mnt_flags,
+ return -EINVAL;
+
+ down_write(&sb->s_umount);
+- err = do_remount_sb(sb, flags, data, 0);
++ if (flags & MS_BIND)
++ err = change_mount_flags(nd->path.mnt, flags);
++ else
++ err = do_remount_sb(sb, flags, data, 0);
+ if (!err)
+ nd->path.mnt->mnt_flags = mnt_flags;
+ up_write(&sb->s_umount);
+@@ -1191,7 +1703,7 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd,
+ goto unlock;
+
+ newmnt->mnt_flags = mnt_flags;
+- if ((err = graft_tree(newmnt, nd)))
++ if ((err = graft_tree(newmnt, &nd->path)))
+ goto unlock;
+
+ if (fslist) /* add to the specified expiration list */
+@@ -1425,6 +1937,8 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
+ mnt_flags |= MNT_NODIRATIME;
+ if (flags & MS_RELATIME)
+ mnt_flags |= MNT_RELATIME;
++ if (flags & MS_RDONLY)
++ mnt_flags |= MNT_READONLY;
+
+ flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE |
+ MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT);
+@@ -1434,7 +1948,8 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
+ if (retval)
+ return retval;
+
+- retval = security_sb_mount(dev_name, &nd, type_page, flags, data_page);
++ retval = security_sb_mount(dev_name, &nd.path,
++ type_page, flags, data_page);
+ if (retval)
+ goto dput_out;
+
+@@ -1674,15 +2189,13 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
+ const char __user * put_old)
+ {
+ struct vfsmount *tmp;
+- struct nameidata new_nd, old_nd, user_nd;
+- struct path parent_path, root_parent;
++ struct nameidata new_nd, old_nd;
++ struct path parent_path, root_parent, root;
+ int error;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+- lock_kernel();
+-
+ error = __user_walk(new_root, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
+ &new_nd);
+ if (error)
+@@ -1695,14 +2208,14 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
+ if (error)
+ goto out1;
+
+- error = security_sb_pivotroot(&old_nd, &new_nd);
++ error = security_sb_pivotroot(&old_nd.path, &new_nd.path);
+ if (error) {
+ path_put(&old_nd.path);
+ goto out1;
+ }
+
+ read_lock(¤t->fs->lock);
+- user_nd.path = current->fs->root;
++ root = current->fs->root;
+ path_get(¤t->fs->root);
+ read_unlock(¤t->fs->lock);
+ down_write(&namespace_sem);
+@@ -1710,9 +2223,9 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
+ error = -EINVAL;
+ if (IS_MNT_SHARED(old_nd.path.mnt) ||
+ IS_MNT_SHARED(new_nd.path.mnt->mnt_parent) ||
+- IS_MNT_SHARED(user_nd.path.mnt->mnt_parent))
++ IS_MNT_SHARED(root.mnt->mnt_parent))
+ goto out2;
+- if (!check_mnt(user_nd.path.mnt))
++ if (!check_mnt(root.mnt))
+ goto out2;
+ error = -ENOENT;
+ if (IS_DEADDIR(new_nd.path.dentry->d_inode))
+@@ -1722,13 +2235,13 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
+ if (d_unhashed(old_nd.path.dentry) && !IS_ROOT(old_nd.path.dentry))
+ goto out2;
+ error = -EBUSY;
+- if (new_nd.path.mnt == user_nd.path.mnt ||
+- old_nd.path.mnt == user_nd.path.mnt)
++ if (new_nd.path.mnt == root.mnt ||
++ old_nd.path.mnt == root.mnt)
+ goto out2; /* loop, on the same file system */
+ error = -EINVAL;
+- if (user_nd.path.mnt->mnt_root != user_nd.path.dentry)
++ if (root.mnt->mnt_root != root.dentry)
+ goto out2; /* not a mountpoint */
+- if (user_nd.path.mnt->mnt_parent == user_nd.path.mnt)
++ if (root.mnt->mnt_parent == root.mnt)
+ goto out2; /* not attached */
+ if (new_nd.path.mnt->mnt_root != new_nd.path.dentry)
+ goto out2; /* not a mountpoint */
+@@ -1750,27 +2263,26 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
+ } else if (!is_subdir(old_nd.path.dentry, new_nd.path.dentry))
+ goto out3;
+ detach_mnt(new_nd.path.mnt, &parent_path);
+- detach_mnt(user_nd.path.mnt, &root_parent);
++ detach_mnt(root.mnt, &root_parent);
+ /* mount old root on put_old */
+- attach_mnt(user_nd.path.mnt, &old_nd.path);
++ attach_mnt(root.mnt, &old_nd.path);
+ /* mount new_root on / */
+ attach_mnt(new_nd.path.mnt, &root_parent);
+ touch_mnt_namespace(current->nsproxy->mnt_ns);
+ spin_unlock(&vfsmount_lock);
+- chroot_fs_refs(&user_nd.path, &new_nd.path);
+- security_sb_post_pivotroot(&user_nd, &new_nd);
++ chroot_fs_refs(&root, &new_nd.path);
++ security_sb_post_pivotroot(&root, &new_nd.path);
+ error = 0;
+ path_put(&root_parent);
+ path_put(&parent_path);
+ out2:
+ mutex_unlock(&old_nd.path.dentry->d_inode->i_mutex);
+ up_write(&namespace_sem);
+- path_put(&user_nd.path);
++ path_put(&root);
+ path_put(&old_nd.path);
+ out1:
+ path_put(&new_nd.path);
+ out0:
+- unlock_kernel();
+ return error;
+ out3:
+ spin_unlock(&vfsmount_lock);
+diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
+index c67b4bd..ad8f167 100644
+--- a/fs/ncpfs/ioctl.c
++++ b/fs/ncpfs/ioctl.c
+@@ -14,6 +14,7 @@
+ #include <linux/ioctl.h>
+ #include <linux/time.h>
+ #include <linux/mm.h>
++#include <linux/mount.h>
+ #include <linux/highuid.h>
+ #include <linux/smp_lock.h>
+ #include <linux/vmalloc.h>
+@@ -261,7 +262,7 @@ ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg)
+ }
+ #endif /* CONFIG_NCPFS_NLS */
+
+-int ncp_ioctl(struct inode *inode, struct file *filp,
++static int __ncp_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+ {
+ struct ncp_server *server = NCP_SERVER(inode);
+@@ -822,6 +823,57 @@ outrel:
+ return -EINVAL;
+ }
+
++static int ncp_ioctl_need_write(unsigned int cmd)
++{
++ switch (cmd) {
++ case NCP_IOC_GET_FS_INFO:
++ case NCP_IOC_GET_FS_INFO_V2:
++ case NCP_IOC_NCPREQUEST:
++ case NCP_IOC_SETDENTRYTTL:
++ case NCP_IOC_SIGN_INIT:
++ case NCP_IOC_LOCKUNLOCK:
++ case NCP_IOC_SET_SIGN_WANTED:
++ return 1;
++ case NCP_IOC_GETOBJECTNAME:
++ case NCP_IOC_SETOBJECTNAME:
++ case NCP_IOC_GETPRIVATEDATA:
++ case NCP_IOC_SETPRIVATEDATA:
++ case NCP_IOC_SETCHARSETS:
++ case NCP_IOC_GETCHARSETS:
++ case NCP_IOC_CONN_LOGGED_IN:
++ case NCP_IOC_GETDENTRYTTL:
++ case NCP_IOC_GETMOUNTUID2:
++ case NCP_IOC_SIGN_WANTED:
++ case NCP_IOC_GETROOT:
++ case NCP_IOC_SETROOT:
++ return 0;
++ default:
++ /* unkown IOCTL command, assume write */
++ return 1;
++ }
++}
++
++int ncp_ioctl(struct inode *inode, struct file *filp,
++ unsigned int cmd, unsigned long arg)
++{
++ int ret;
++
++ if (ncp_ioctl_need_write(cmd)) {
++ /*
++ * inside the ioctl(), any failures which
++ * are because of file_permission() are
++ * -EACCESS, so it seems consistent to keep
++ * that here.
++ */
++ if (mnt_want_write(filp->f_path.mnt))
++ return -EACCES;
++ }
++ ret = __ncp_ioctl(inode, filp, cmd, arg);
++ if (ncp_ioctl_need_write(cmd))
++ mnt_drop_write(filp->f_path.mnt);
++ return ret;
++}
++
+ #ifdef CONFIG_COMPAT
+ long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ {
+diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
+index df0f41e..ac6170c 100644
+--- a/fs/nfs/Makefile
++++ b/fs/nfs/Makefile
+@@ -5,7 +5,7 @@
+ obj-$(CONFIG_NFS_FS) += nfs.o
+
+ nfs-y := client.o dir.o file.o getroot.o inode.o super.o nfs2xdr.o \
+- pagelist.o proc.o read.o symlink.o unlink.o \
++ direct.o pagelist.o proc.o read.o symlink.o unlink.o \
+ write.o namespace.o mount_clnt.o
+ nfs-$(CONFIG_ROOT_NFS) += nfsroot.o
+ nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o
+@@ -14,5 +14,4 @@ nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
+ delegation.o idmap.o \
+ callback.o callback_xdr.o callback_proc.o \
+ nfs4namespace.o
+-nfs-$(CONFIG_NFS_DIRECTIO) += direct.o
+ nfs-$(CONFIG_SYSCTL) += sysctl.o
+diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
+index 66648dd..5606ae3 100644
+--- a/fs/nfs/callback.c
++++ b/fs/nfs/callback.c
+@@ -15,6 +15,7 @@
+ #include <linux/nfs_fs.h>
+ #include <linux/mutex.h>
+ #include <linux/freezer.h>
++#include <linux/kthread.h>
+
+ #include <net/inet_sock.h>
+
+@@ -27,9 +28,7 @@
+ struct nfs_callback_data {
+ unsigned int users;
+ struct svc_serv *serv;
+- pid_t pid;
+- struct completion started;
+- struct completion stopped;
++ struct task_struct *task;
+ };
+
+ static struct nfs_callback_data nfs_callback_info;
+@@ -57,48 +56,44 @@ module_param_call(callback_tcpport, param_set_port, param_get_int,
+ /*
+ * This is the callback kernel thread.
+ */
+-static void nfs_callback_svc(struct svc_rqst *rqstp)
++static int
++nfs_callback_svc(void *vrqstp)
+ {
+- int err;
++ int err, preverr = 0;
++ struct svc_rqst *rqstp = vrqstp;
+
+- __module_get(THIS_MODULE);
+- lock_kernel();
+-
+- nfs_callback_info.pid = current->pid;
+- daemonize("nfsv4-svc");
+- /* Process request with signals blocked, but allow SIGKILL. */
+- allow_signal(SIGKILL);
+ set_freezable();
+
+- complete(&nfs_callback_info.started);
+-
+- for(;;) {
+- if (signalled()) {
+- if (nfs_callback_info.users == 0)
+- break;
+- flush_signals(current);
+- }
++ /*
++ * FIXME: do we really need to run this under the BKL? If so, please
++ * add a comment about what it's intended to protect.
++ */
++ lock_kernel();
++ while (!kthread_should_stop()) {
+ /*
+ * Listen for a request on the socket
+ */
+ err = svc_recv(rqstp, MAX_SCHEDULE_TIMEOUT);
+- if (err == -EAGAIN || err == -EINTR)
++ if (err == -EAGAIN || err == -EINTR) {
++ preverr = err;
+ continue;
++ }
+ if (err < 0) {
+- printk(KERN_WARNING
+- "%s: terminating on error %d\n",
+- __FUNCTION__, -err);
+- break;
++ if (err != preverr) {
++ printk(KERN_WARNING "%s: unexpected error "
++ "from svc_recv (%d)\n", __func__, err);
++ preverr = err;
++ }
++ schedule_timeout_uninterruptible(HZ);
++ continue;
+ }
++ preverr = err;
+ svc_process(rqstp);
+ }
+-
+- flush_signals(current);
+- svc_exit_thread(rqstp);
+- nfs_callback_info.pid = 0;
+- complete(&nfs_callback_info.stopped);
+ unlock_kernel();
+- module_put_and_exit(0);
++ nfs_callback_info.task = NULL;
++ svc_exit_thread(rqstp);
++ return 0;
+ }
+
+ /*
+@@ -107,14 +102,13 @@ static void nfs_callback_svc(struct svc_rqst *rqstp)
+ int nfs_callback_up(void)
+ {
+ struct svc_serv *serv = NULL;
++ struct svc_rqst *rqstp;
+ int ret = 0;
+
+ lock_kernel();
+ mutex_lock(&nfs_callback_mutex);
+- if (nfs_callback_info.users++ || nfs_callback_info.pid != 0)
++ if (nfs_callback_info.users++ || nfs_callback_info.task != NULL)
+ goto out;
+- init_completion(&nfs_callback_info.started);
+- init_completion(&nfs_callback_info.stopped);
+ serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL);
+ ret = -ENOMEM;
+ if (!serv)
+@@ -127,15 +121,28 @@ int nfs_callback_up(void)
+ nfs_callback_tcpport = ret;
+ dprintk("Callback port = 0x%x\n", nfs_callback_tcpport);
+
+- ret = svc_create_thread(nfs_callback_svc, serv);
+- if (ret < 0)
++ rqstp = svc_prepare_thread(serv, &serv->sv_pools[0]);
++ if (IS_ERR(rqstp)) {
++ ret = PTR_ERR(rqstp);
+ goto out_err;
++ }
++
++ svc_sock_update_bufs(serv);
+ nfs_callback_info.serv = serv;
+- wait_for_completion(&nfs_callback_info.started);
++
++ nfs_callback_info.task = kthread_run(nfs_callback_svc, rqstp,
++ "nfsv4-svc");
++ if (IS_ERR(nfs_callback_info.task)) {
++ ret = PTR_ERR(nfs_callback_info.task);
++ nfs_callback_info.serv = NULL;
++ nfs_callback_info.task = NULL;
++ svc_exit_thread(rqstp);
++ goto out_err;
++ }
+ out:
+ /*
+ * svc_create creates the svc_serv with sv_nrthreads == 1, and then
+- * svc_create_thread increments that. So we need to call svc_destroy
++ * svc_prepare_thread increments that. So we need to call svc_destroy
+ * on both success and failure so that the refcount is 1 when the
+ * thread exits.
+ */
+@@ -152,19 +159,15 @@ out_err:
+ }
+
+ /*
+- * Kill the server process if it is not already up.
++ * Kill the server process if it is not already down.
+ */
+ void nfs_callback_down(void)
+ {
+ lock_kernel();
+ mutex_lock(&nfs_callback_mutex);
+ nfs_callback_info.users--;
+- do {
+- if (nfs_callback_info.users != 0 || nfs_callback_info.pid == 0)
+- break;
+- if (kill_proc(nfs_callback_info.pid, SIGKILL, 1) < 0)
+- break;
+- } while (wait_for_completion_timeout(&nfs_callback_info.stopped, 5*HZ) == 0);
++ if (nfs_callback_info.users == 0 && nfs_callback_info.task != NULL)
++ kthread_stop(nfs_callback_info.task);
+ mutex_unlock(&nfs_callback_mutex);
+ unlock_kernel();
+ }
+diff --git a/fs/nfs/client.c b/fs/nfs/client.c
+index c5c0175..f2f3b28 100644
+--- a/fs/nfs/client.c
++++ b/fs/nfs/client.c
+@@ -112,6 +112,7 @@ struct nfs_client_initdata {
+ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
+ {
+ struct nfs_client *clp;
++ struct rpc_cred *cred;
+
+ if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL)
+ goto error_0;
+@@ -150,6 +151,9 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
+ clp->cl_boot_time = CURRENT_TIME;
+ clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
+ #endif
++ cred = rpc_lookup_machine_cred();
++ if (!IS_ERR(cred))
++ clp->cl_machine_cred = cred;
+
+ return clp;
+
+@@ -170,6 +174,8 @@ static void nfs4_shutdown_client(struct nfs_client *clp)
+ BUG_ON(!RB_EMPTY_ROOT(&clp->cl_state_owners));
+ if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
+ nfs_idmap_delete(clp);
++
++ rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
+ #endif
+ }
+
+@@ -189,6 +195,9 @@ static void nfs_free_client(struct nfs_client *clp)
+ if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
+ nfs_callback_down();
+
++ if (clp->cl_machine_cred != NULL)
++ put_rpccred(clp->cl_machine_cred);
++
+ kfree(clp->cl_hostname);
+ kfree(clp);
+
+@@ -680,10 +689,22 @@ static int nfs_init_server(struct nfs_server *server,
+ if (error < 0)
+ goto error;
+
++ server->port = data->nfs_server.port;
++
+ error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]);
+ if (error < 0)
+ goto error;
+
++ /* Preserve the values of mount_server-related mount options */
++ if (data->mount_server.addrlen) {
++ memcpy(&server->mountd_address, &data->mount_server.address,
++ data->mount_server.addrlen);
++ server->mountd_addrlen = data->mount_server.addrlen;
++ }
++ server->mountd_version = data->mount_server.version;
++ server->mountd_port = data->mount_server.port;
++ server->mountd_protocol = data->mount_server.protocol;
++
+ server->namelen = data->namlen;
+ /* Create a client RPC handle for the NFSv3 ACL management interface */
+ nfs_init_server_aclclient(server);
+@@ -1062,6 +1083,8 @@ static int nfs4_init_server(struct nfs_server *server,
+ server->acdirmin = data->acdirmin * HZ;
+ server->acdirmax = data->acdirmax * HZ;
+
++ server->port = data->nfs_server.port;
++
+ error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]);
+
+ error:
+diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
+index 6cea747..f288b3e 100644
+--- a/fs/nfs/dir.c
++++ b/fs/nfs/dir.c
+@@ -967,7 +967,8 @@ static int is_atomic_open(struct inode *dir, struct nameidata *nd)
+ if (nd->flags & LOOKUP_DIRECTORY)
+ return 0;
+ /* Are we trying to write to a read only partition? */
+- if (IS_RDONLY(dir) && (nd->intent.open.flags & (O_CREAT|O_TRUNC|FMODE_WRITE)))
++ if (__mnt_is_readonly(nd->path.mnt) &&
++ (nd->intent.open.flags & (O_CREAT|O_TRUNC|FMODE_WRITE)))
+ return 0;
+ return 1;
+ }
+@@ -1966,7 +1967,7 @@ force_lookup:
+ if (!NFS_PROTO(inode)->access)
+ goto out_notsup;
+
+- cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
++ cred = rpc_lookup_cred();
+ if (!IS_ERR(cred)) {
+ res = nfs_do_access(inode, cred, mask);
+ put_rpccred(cred);
+diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
+index 16844f9..4757a2b 100644
+--- a/fs/nfs/direct.c
++++ b/fs/nfs/direct.c
+@@ -229,14 +229,20 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq)
+ static void nfs_direct_read_result(struct rpc_task *task, void *calldata)
+ {
+ struct nfs_read_data *data = calldata;
+- struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
+
+- if (nfs_readpage_result(task, data) != 0)
+- return;
++ nfs_readpage_result(task, data);
++}
++
++static void nfs_direct_read_release(void *calldata)
++{
++
++ struct nfs_read_data *data = calldata;
++ struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
++ int status = data->task.tk_status;
+
+ spin_lock(&dreq->lock);
+- if (unlikely(task->tk_status < 0)) {
+- dreq->error = task->tk_status;
++ if (unlikely(status < 0)) {
++ dreq->error = status;
+ spin_unlock(&dreq->lock);
+ } else {
+ dreq->count += data->res.count;
+@@ -249,11 +255,12 @@ static void nfs_direct_read_result(struct rpc_task *task, void *calldata)
+
+ if (put_dreq(dreq))
+ nfs_direct_complete(dreq);
++ nfs_readdata_release(calldata);
+ }
+
+ static const struct rpc_call_ops nfs_read_direct_ops = {
+ .rpc_call_done = nfs_direct_read_result,
+- .rpc_release = nfs_readdata_release,
++ .rpc_release = nfs_direct_read_release,
+ };
+
+ /*
+@@ -280,6 +287,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq,
+ .rpc_client = NFS_CLIENT(inode),
+ .rpc_message = &msg,
+ .callback_ops = &nfs_read_direct_ops,
++ .workqueue = nfsiod_workqueue,
+ .flags = RPC_TASK_ASYNC,
+ };
+ unsigned int pgbase;
+@@ -323,7 +331,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq,
+ data->inode = inode;
+ data->cred = msg.rpc_cred;
+ data->args.fh = NFS_FH(inode);
+- data->args.context = ctx;
++ data->args.context = get_nfs_open_context(ctx);
+ data->args.offset = pos;
+ data->args.pgbase = pgbase;
+ data->args.pages = data->pagevec;
+@@ -339,8 +347,9 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq,
+ NFS_PROTO(inode)->read_setup(data, &msg);
+
+ task = rpc_run_task(&task_setup_data);
+- if (!IS_ERR(task))
+- rpc_put_task(task);
++ if (IS_ERR(task))
++ break;
++ rpc_put_task(task);
+
+ dprintk("NFS: %5u initiated direct read call "
+ "(req %s/%Ld, %zu bytes @ offset %Lu)\n",
+@@ -446,6 +455,7 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
+ struct rpc_task_setup task_setup_data = {
+ .rpc_client = NFS_CLIENT(inode),
+ .callback_ops = &nfs_write_direct_ops,
++ .workqueue = nfsiod_workqueue,
+ .flags = RPC_TASK_ASYNC,
+ };
+
+@@ -499,27 +509,34 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
+ static void nfs_direct_commit_result(struct rpc_task *task, void *calldata)
+ {
+ struct nfs_write_data *data = calldata;
+- struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
+
+ /* Call the NFS version-specific code */
+- if (NFS_PROTO(data->inode)->commit_done(task, data) != 0)
+- return;
+- if (unlikely(task->tk_status < 0)) {
++ NFS_PROTO(data->inode)->commit_done(task, data);
++}
++
++static void nfs_direct_commit_release(void *calldata)
++{
++ struct nfs_write_data *data = calldata;
++ struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
++ int status = data->task.tk_status;
++
++ if (status < 0) {
+ dprintk("NFS: %5u commit failed with error %d.\n",
+- task->tk_pid, task->tk_status);
++ data->task.tk_pid, status);
+ dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
+ } else if (memcmp(&dreq->verf, &data->verf, sizeof(data->verf))) {
+- dprintk("NFS: %5u commit verify failed\n", task->tk_pid);
++ dprintk("NFS: %5u commit verify failed\n", data->task.tk_pid);
+ dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
+ }
+
+- dprintk("NFS: %5u commit returned %d\n", task->tk_pid, task->tk_status);
++ dprintk("NFS: %5u commit returned %d\n", data->task.tk_pid, status);
+ nfs_direct_write_complete(dreq, data->inode);
++ nfs_commitdata_release(calldata);
+ }
+
+ static const struct rpc_call_ops nfs_commit_direct_ops = {
+ .rpc_call_done = nfs_direct_commit_result,
+- .rpc_release = nfs_commit_release,
++ .rpc_release = nfs_direct_commit_release,
+ };
+
+ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
+@@ -537,6 +554,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
+ .rpc_message = &msg,
+ .callback_ops = &nfs_commit_direct_ops,
+ .callback_data = data,
++ .workqueue = nfsiod_workqueue,
+ .flags = RPC_TASK_ASYNC,
+ };
+
+@@ -546,6 +564,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
+ data->args.fh = NFS_FH(data->inode);
+ data->args.offset = 0;
+ data->args.count = 0;
++ data->args.context = get_nfs_open_context(dreq->ctx);
+ data->res.count = 0;
+ data->res.fattr = &data->fattr;
+ data->res.verf = &data->verf;
+@@ -585,7 +604,7 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode
+
+ static void nfs_alloc_commit_data(struct nfs_direct_req *dreq)
+ {
+- dreq->commit_data = nfs_commit_alloc();
++ dreq->commit_data = nfs_commitdata_alloc();
+ if (dreq->commit_data != NULL)
+ dreq->commit_data->req = (struct nfs_page *) dreq;
+ }
+@@ -606,11 +625,20 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode
+ static void nfs_direct_write_result(struct rpc_task *task, void *calldata)
+ {
+ struct nfs_write_data *data = calldata;
+- struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
+- int status = task->tk_status;
+
+ if (nfs_writeback_done(task, data) != 0)
+ return;
++}
++
++/*
++ * NB: Return the value of the first error return code. Subsequent
++ * errors after the first one are ignored.
++ */
++static void nfs_direct_write_release(void *calldata)
++{
++ struct nfs_write_data *data = calldata;
++ struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
++ int status = data->task.tk_status;
+
+ spin_lock(&dreq->lock);
+
+@@ -632,23 +660,13 @@ static void nfs_direct_write_result(struct rpc_task *task, void *calldata)
+ break;
+ case NFS_ODIRECT_DO_COMMIT:
+ if (memcmp(&dreq->verf, &data->verf, sizeof(dreq->verf))) {
+- dprintk("NFS: %5u write verify failed\n", task->tk_pid);
++ dprintk("NFS: %5u write verify failed\n", data->task.tk_pid);
+ dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
+ }
+ }
+ }
+ out_unlock:
+ spin_unlock(&dreq->lock);
+-}
+-
+-/*
+- * NB: Return the value of the first error return code. Subsequent
+- * errors after the first one are ignored.
+- */
+-static void nfs_direct_write_release(void *calldata)
+-{
+- struct nfs_write_data *data = calldata;
+- struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
+
+ if (put_dreq(dreq))
+ nfs_direct_write_complete(dreq, data->inode);
+@@ -682,6 +700,7 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq,
+ .rpc_client = NFS_CLIENT(inode),
+ .rpc_message = &msg,
+ .callback_ops = &nfs_write_direct_ops,
++ .workqueue = nfsiod_workqueue,
+ .flags = RPC_TASK_ASYNC,
+ };
+ size_t wsize = NFS_SERVER(inode)->wsize;
+@@ -728,7 +747,7 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq,
+ data->inode = inode;
+ data->cred = msg.rpc_cred;
+ data->args.fh = NFS_FH(inode);
+- data->args.context = ctx;
++ data->args.context = get_nfs_open_context(ctx);
+ data->args.offset = pos;
+ data->args.pgbase = pgbase;
+ data->args.pages = data->pagevec;
+@@ -745,8 +764,9 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq,
+ NFS_PROTO(inode)->write_setup(data, &msg);
+
+ task = rpc_run_task(&task_setup_data);
+- if (!IS_ERR(task))
+- rpc_put_task(task);
++ if (IS_ERR(task))
++ break;
++ rpc_put_task(task);
+
+ dprintk("NFS: %5u initiated direct write call "
+ "(req %s/%Ld, %zu bytes @ offset %Lu)\n",
+diff --git a/fs/nfs/file.c b/fs/nfs/file.c
+index 5d2e9d9..3536b01 100644
+--- a/fs/nfs/file.c
++++ b/fs/nfs/file.c
+@@ -238,10 +238,8 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
+ ssize_t result;
+ size_t count = iov_length(iov, nr_segs);
+
+-#ifdef CONFIG_NFS_DIRECTIO
+ if (iocb->ki_filp->f_flags & O_DIRECT)
+ return nfs_file_direct_read(iocb, iov, nr_segs, pos);
+-#endif
+
+ dfprintk(VFS, "nfs: read(%s/%s, %lu@%lu)\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name,
+@@ -387,9 +385,7 @@ const struct address_space_operations nfs_file_aops = {
+ .write_end = nfs_write_end,
+ .invalidatepage = nfs_invalidate_page,
+ .releasepage = nfs_release_page,
+-#ifdef CONFIG_NFS_DIRECTIO
+ .direct_IO = nfs_direct_IO,
+-#endif
+ .launder_page = nfs_launder_page,
+ };
+
+@@ -447,10 +443,8 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
+ ssize_t result;
+ size_t count = iov_length(iov, nr_segs);
+
+-#ifdef CONFIG_NFS_DIRECTIO
+ if (iocb->ki_filp->f_flags & O_DIRECT)
+ return nfs_file_direct_write(iocb, iov, nr_segs, pos);
+-#endif
+
+ dfprintk(VFS, "nfs: write(%s/%s(%ld), %lu@%Ld)\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name,
+@@ -576,17 +570,9 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl)
+
+ lock_kernel();
+ /* Use local locking if mounted with "-onolock" */
+- if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)) {
++ if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM))
+ status = NFS_PROTO(inode)->lock(filp, cmd, fl);
+- /* If we were signalled we still need to ensure that
+- * we clean up any state on the server. We therefore
+- * record the lock call as having succeeded in order to
+- * ensure that locks_remove_posix() cleans it out when
+- * the process exits.
+- */
+- if (status == -EINTR || status == -ERESTARTSYS)
+- do_vfs_lock(filp, fl);
+- } else
++ else
+ status = do_vfs_lock(filp, fl);
+ unlock_kernel();
+ if (status < 0)
+diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
+index 6f88d7c..5cb3345 100644
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -523,8 +523,12 @@ struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
+
+ static void __put_nfs_open_context(struct nfs_open_context *ctx, int wait)
+ {
+- struct inode *inode = ctx->path.dentry->d_inode;
++ struct inode *inode;
+
++ if (ctx == NULL)
++ return;
++
++ inode = ctx->path.dentry->d_inode;
+ if (!atomic_dec_and_lock(&ctx->count, &inode->i_lock))
+ return;
+ list_del(&ctx->list);
+@@ -610,7 +614,7 @@ int nfs_open(struct inode *inode, struct file *filp)
+ struct nfs_open_context *ctx;
+ struct rpc_cred *cred;
+
+- cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
++ cred = rpc_lookup_cred();
+ if (IS_ERR(cred))
+ return PTR_ERR(cred);
+ ctx = alloc_nfs_open_context(filp->f_path.mnt, filp->f_path.dentry, cred);
+@@ -1218,6 +1222,36 @@ static void nfs_destroy_inodecache(void)
+ kmem_cache_destroy(nfs_inode_cachep);
+ }
+
++struct workqueue_struct *nfsiod_workqueue;
++
++/*
++ * start up the nfsiod workqueue
++ */
++static int nfsiod_start(void)
++{
++ struct workqueue_struct *wq;
++ dprintk("RPC: creating workqueue nfsiod\n");
++ wq = create_singlethread_workqueue("nfsiod");
++ if (wq == NULL)
++ return -ENOMEM;
++ nfsiod_workqueue = wq;
++ return 0;
++}
++
++/*
++ * Destroy the nfsiod workqueue
++ */
++static void nfsiod_stop(void)
++{
++ struct workqueue_struct *wq;
++
++ wq = nfsiod_workqueue;
++ if (wq == NULL)
++ return;
++ nfsiod_workqueue = NULL;
++ destroy_workqueue(wq);
++}
++
+ /*
+ * Initialize NFS
+ */
+@@ -1225,6 +1259,10 @@ static int __init init_nfs_fs(void)
+ {
+ int err;
+
++ err = nfsiod_start();
++ if (err)
++ goto out6;
++
+ err = nfs_fs_proc_init();
+ if (err)
+ goto out5;
+@@ -1271,6 +1309,8 @@ out3:
+ out4:
+ nfs_fs_proc_exit();
+ out5:
++ nfsiod_stop();
++out6:
+ return err;
+ }
+
+@@ -1286,6 +1326,7 @@ static void __exit exit_nfs_fs(void)
+ #endif
+ unregister_nfs_fs();
+ nfs_fs_proc_exit();
++ nfsiod_stop();
+ }
+
+ /* Not quite true; I just maintain it */
+diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
+index 9319927..04ae867 100644
+--- a/fs/nfs/internal.h
++++ b/fs/nfs/internal.h
+@@ -46,9 +46,9 @@ struct nfs_parsed_mount_data {
+ struct sockaddr_storage address;
+ size_t addrlen;
+ char *hostname;
+- unsigned int version;
++ u32 version;
+ unsigned short port;
+- int protocol;
++ unsigned short protocol;
+ } mount_server;
+
+ struct {
+@@ -56,7 +56,8 @@ struct nfs_parsed_mount_data {
+ size_t addrlen;
+ char *hostname;
+ char *export_path;
+- int protocol;
++ unsigned short port;
++ unsigned short protocol;
+ } nfs_server;
+
+ struct security_mnt_opts lsm_opts;
+@@ -115,13 +116,8 @@ extern void nfs_destroy_readpagecache(void);
+ extern int __init nfs_init_writepagecache(void);
+ extern void nfs_destroy_writepagecache(void);
+
+-#ifdef CONFIG_NFS_DIRECTIO
+ extern int __init nfs_init_directcache(void);
+ extern void nfs_destroy_directcache(void);
+-#else
+-#define nfs_init_directcache() (0)
+-#define nfs_destroy_directcache() do {} while(0)
+-#endif
+
+ /* nfs2xdr.c */
+ extern int nfs_stat_to_errno(int);
+@@ -146,6 +142,7 @@ extern struct rpc_procinfo nfs4_procedures[];
+ extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask);
+
+ /* inode.c */
++extern struct workqueue_struct *nfsiod_workqueue;
+ extern struct inode *nfs_alloc_inode(struct super_block *sb);
+ extern void nfs_destroy_inode(struct inode *);
+ extern int nfs_write_inode(struct inode *,int);
+diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
+index 607f6eb..af4d0f1 100644
+--- a/fs/nfs/namespace.c
++++ b/fs/nfs/namespace.c
+@@ -20,7 +20,7 @@
+
+ static void nfs_expire_automounts(struct work_struct *work);
+
+-LIST_HEAD(nfs_automount_list);
++static LIST_HEAD(nfs_automount_list);
+ static DECLARE_DELAYED_WORK(nfs_automount_task, nfs_expire_automounts);
+ int nfs_mountpoint_expiry_timeout = 500 * HZ;
+
+diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
+index 1f7ea67..28bab67 100644
+--- a/fs/nfs/nfs2xdr.c
++++ b/fs/nfs/nfs2xdr.c
+@@ -267,7 +267,7 @@ nfs_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
+ int status;
+
+ if ((status = ntohl(*p++)))
+- return -nfs_stat_to_errno(status);
++ return nfs_stat_to_errno(status);
+ p = xdr_decode_fattr(p, res->fattr);
+
+ count = ntohl(*p++);
+@@ -428,11 +428,11 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy)
+ size_t hdrlen;
+ unsigned int pglen, recvd;
+ u32 len;
+- int status, nr;
++ int status, nr = 0;
+ __be32 *end, *entry, *kaddr;
+
+ if ((status = ntohl(*p++)))
+- return -nfs_stat_to_errno(status);
++ return nfs_stat_to_errno(status);
+
+ hdrlen = (u8 *) p - (u8 *) iov->iov_base;
+ if (iov->iov_len < hdrlen) {
+@@ -452,7 +452,12 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy)
+ kaddr = p = kmap_atomic(*page, KM_USER0);
+ end = (__be32 *)((char *)p + pglen);
+ entry = p;
+- for (nr = 0; *p++; nr++) {
++
++ /* Make sure the packet actually has a value_follows and EOF entry */
++ if ((entry + 1) > end)
++ goto short_pkt;
++
++ for (; *p++; nr++) {
+ if (p + 2 > end)
+ goto short_pkt;
+ p++; /* fileid */
+@@ -467,18 +472,32 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy)
+ goto short_pkt;
+ entry = p;
+ }
+- if (!nr && (entry[0] != 0 || entry[1] == 0))
+- goto short_pkt;
++
++ /*
++ * Apparently some server sends responses that are a valid size, but
++ * contain no entries, and have value_follows==0 and EOF==0. For
++ * those, just set the EOF marker.
++ */
++ if (!nr && entry[1] == 0) {
++ dprintk("NFS: readdir reply truncated!\n");
++ entry[1] = 1;
++ }
+ out:
+ kunmap_atomic(kaddr, KM_USER0);
+ return nr;
+ short_pkt:
++ /*
++ * When we get a short packet there are 2 possibilities. We can
++ * return an error, or fix up the response to look like a valid
++ * response and return what we have so far. If there are no
++ * entries and the packet was short, then return -EIO. If there
++ * are valid entries in the response, return them and pretend that
++ * the call was successful, but incomplete. The caller can retry the
++ * readdir starting at the last cookie.
++ */
+ entry[0] = entry[1] = 0;
+- /* truncate listing ? */
+- if (!nr) {
+- dprintk("NFS: readdir reply truncated!\n");
+- entry[1] = 1;
+- }
++ if (!nr)
++ nr = -errno_NFSERR_IO;
+ goto out;
+ err_unmap:
+ nr = -errno_NFSERR_IO;
+@@ -518,7 +537,7 @@ nfs_xdr_stat(struct rpc_rqst *req, __be32 *p, void *dummy)
+ int status;
+
+ if ((status = ntohl(*p++)) != 0)
+- status = -nfs_stat_to_errno(status);
++ status = nfs_stat_to_errno(status);
+ return status;
+ }
+
+@@ -532,7 +551,7 @@ nfs_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
+ int status;
+
+ if ((status = ntohl(*p++)))
+- return -nfs_stat_to_errno(status);
++ return nfs_stat_to_errno(status);
+ xdr_decode_fattr(p, fattr);
+ return 0;
+ }
+@@ -547,7 +566,7 @@ nfs_xdr_diropres(struct rpc_rqst *req, __be32 *p, struct nfs_diropok *res)
+ int status;
+
+ if ((status = ntohl(*p++)))
+- return -nfs_stat_to_errno(status);
++ return nfs_stat_to_errno(status);
+ p = xdr_decode_fhandle(p, res->fh);
+ xdr_decode_fattr(p, res->fattr);
+ return 0;
+@@ -585,7 +604,7 @@ nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy)
+ int status;
+
+ if ((status = ntohl(*p++)))
+- return -nfs_stat_to_errno(status);
++ return nfs_stat_to_errno(status);
+ /* Convert length of symlink */
+ len = ntohl(*p++);
+ if (len >= rcvbuf->page_len) {
+@@ -634,7 +653,7 @@ nfs_xdr_statfsres(struct rpc_rqst *req, __be32 *p, struct nfs2_fsstat *res)
+ int status;
+
+ if ((status = ntohl(*p++)))
+- return -nfs_stat_to_errno(status);
++ return nfs_stat_to_errno(status);
+
+ res->tsize = ntohl(*p++);
+ res->bsize = ntohl(*p++);
+@@ -653,39 +672,39 @@ static struct {
+ int errno;
+ } nfs_errtbl[] = {
+ { NFS_OK, 0 },
+- { NFSERR_PERM, EPERM },
+- { NFSERR_NOENT, ENOENT },
+- { NFSERR_IO, errno_NFSERR_IO },
+- { NFSERR_NXIO, ENXIO },
+-/* { NFSERR_EAGAIN, EAGAIN }, */
+- { NFSERR_ACCES, EACCES },
+- { NFSERR_EXIST, EEXIST },
+- { NFSERR_XDEV, EXDEV },
+- { NFSERR_NODEV, ENODEV },
+- { NFSERR_NOTDIR, ENOTDIR },
+- { NFSERR_ISDIR, EISDIR },
+- { NFSERR_INVAL, EINVAL },
+- { NFSERR_FBIG, EFBIG },
+- { NFSERR_NOSPC, ENOSPC },
+- { NFSERR_ROFS, EROFS },
+- { NFSERR_MLINK, EMLINK },
+- { NFSERR_NAMETOOLONG, ENAMETOOLONG },
+- { NFSERR_NOTEMPTY, ENOTEMPTY },
+- { NFSERR_DQUOT, EDQUOT },
+- { NFSERR_STALE, ESTALE },
+- { NFSERR_REMOTE, EREMOTE },
++ { NFSERR_PERM, -EPERM },
++ { NFSERR_NOENT, -ENOENT },
++ { NFSERR_IO, -errno_NFSERR_IO},
++ { NFSERR_NXIO, -ENXIO },
++/* { NFSERR_EAGAIN, -EAGAIN }, */
++ { NFSERR_ACCES, -EACCES },
++ { NFSERR_EXIST, -EEXIST },
++ { NFSERR_XDEV, -EXDEV },
++ { NFSERR_NODEV, -ENODEV },
++ { NFSERR_NOTDIR, -ENOTDIR },
++ { NFSERR_ISDIR, -EISDIR },
++ { NFSERR_INVAL, -EINVAL },
++ { NFSERR_FBIG, -EFBIG },
++ { NFSERR_NOSPC, -ENOSPC },
++ { NFSERR_ROFS, -EROFS },
++ { NFSERR_MLINK, -EMLINK },
++ { NFSERR_NAMETOOLONG, -ENAMETOOLONG },
++ { NFSERR_NOTEMPTY, -ENOTEMPTY },
++ { NFSERR_DQUOT, -EDQUOT },
++ { NFSERR_STALE, -ESTALE },
++ { NFSERR_REMOTE, -EREMOTE },
+ #ifdef EWFLUSH
+- { NFSERR_WFLUSH, EWFLUSH },
++ { NFSERR_WFLUSH, -EWFLUSH },
+ #endif
+- { NFSERR_BADHANDLE, EBADHANDLE },
+- { NFSERR_NOT_SYNC, ENOTSYNC },
+- { NFSERR_BAD_COOKIE, EBADCOOKIE },
+- { NFSERR_NOTSUPP, ENOTSUPP },
+- { NFSERR_TOOSMALL, ETOOSMALL },
+- { NFSERR_SERVERFAULT, ESERVERFAULT },
+- { NFSERR_BADTYPE, EBADTYPE },
+- { NFSERR_JUKEBOX, EJUKEBOX },
+- { -1, EIO }
++ { NFSERR_BADHANDLE, -EBADHANDLE },
++ { NFSERR_NOT_SYNC, -ENOTSYNC },
++ { NFSERR_BAD_COOKIE, -EBADCOOKIE },
++ { NFSERR_NOTSUPP, -ENOTSUPP },
++ { NFSERR_TOOSMALL, -ETOOSMALL },
++ { NFSERR_SERVERFAULT, -ESERVERFAULT },
++ { NFSERR_BADTYPE, -EBADTYPE },
++ { NFSERR_JUKEBOX, -EJUKEBOX },
++ { -1, -EIO }
+ };
+
+ /*
+diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
+index 3917e2f..11cddde 100644
+--- a/fs/nfs/nfs3xdr.c
++++ b/fs/nfs/nfs3xdr.c
+@@ -508,14 +508,14 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res
+ struct page **page;
+ size_t hdrlen;
+ u32 len, recvd, pglen;
+- int status, nr;
++ int status, nr = 0;
+ __be32 *entry, *end, *kaddr;
+
+ status = ntohl(*p++);
+ /* Decode post_op_attrs */
+ p = xdr_decode_post_op_attr(p, res->dir_attr);
+ if (status)
+- return -nfs_stat_to_errno(status);
++ return nfs_stat_to_errno(status);
+ /* Decode verifier cookie */
+ if (res->verf) {
+ res->verf[0] = *p++;
+@@ -542,7 +542,12 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res
+ kaddr = p = kmap_atomic(*page, KM_USER0);
+ end = (__be32 *)((char *)p + pglen);
+ entry = p;
+- for (nr = 0; *p++; nr++) {
++
++ /* Make sure the packet actually has a value_follows and EOF entry */
++ if ((entry + 1) > end)
++ goto short_pkt;
++
++ for (; *p++; nr++) {
+ if (p + 3 > end)
+ goto short_pkt;
+ p += 2; /* inode # */
+@@ -581,18 +586,32 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res
+ goto short_pkt;
+ entry = p;
+ }
+- if (!nr && (entry[0] != 0 || entry[1] == 0))
+- goto short_pkt;
++
++ /*
++ * Apparently some server sends responses that are a valid size, but
++ * contain no entries, and have value_follows==0 and EOF==0. For
++ * those, just set the EOF marker.
++ */
++ if (!nr && entry[1] == 0) {
++ dprintk("NFS: readdir reply truncated!\n");
++ entry[1] = 1;
++ }
+ out:
+ kunmap_atomic(kaddr, KM_USER0);
+ return nr;
+ short_pkt:
++ /*
++ * When we get a short packet there are 2 possibilities. We can
++ * return an error, or fix up the response to look like a valid
++ * response and return what we have so far. If there are no
++ * entries and the packet was short, then return -EIO. If there
++ * are valid entries in the response, return them and pretend that
++ * the call was successful, but incomplete. The caller can retry the
++ * readdir starting at the last cookie.
++ */
+ entry[0] = entry[1] = 0;
+- /* truncate listing ? */
+- if (!nr) {
+- dprintk("NFS: readdir reply truncated!\n");
+- entry[1] = 1;
+- }
++ if (!nr)
++ nr = -errno_NFSERR_IO;
+ goto out;
+ err_unmap:
+ nr = -errno_NFSERR_IO;
+@@ -732,7 +751,7 @@ nfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
+ int status;
+
+ if ((status = ntohl(*p++)))
+- return -nfs_stat_to_errno(status);
++ return nfs_stat_to_errno(status);
+ xdr_decode_fattr(p, fattr);
+ return 0;
+ }
+@@ -747,7 +766,7 @@ nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
+ int status;
+
+ if ((status = ntohl(*p++)))
+- status = -nfs_stat_to_errno(status);
++ status = nfs_stat_to_errno(status);
+ xdr_decode_wcc_data(p, fattr);
+ return status;
+ }
+@@ -767,7 +786,7 @@ nfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
+ int status;
+
+ if ((status = ntohl(*p++))) {
+- status = -nfs_stat_to_errno(status);
++ status = nfs_stat_to_errno(status);
+ } else {
+ if (!(p = xdr_decode_fhandle(p, res->fh)))
+ return -errno_NFSERR_IO;
+@@ -787,7 +806,7 @@ nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res)
+
+ p = xdr_decode_post_op_attr(p, res->fattr);
+ if (status)
+- return -nfs_stat_to_errno(status);
++ return nfs_stat_to_errno(status);
+ res->access = ntohl(*p++);
+ return 0;
+ }
+@@ -824,7 +843,7 @@ nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
+ p = xdr_decode_post_op_attr(p, fattr);
+
+ if (status != 0)
+- return -nfs_stat_to_errno(status);
++ return nfs_stat_to_errno(status);
+
+ /* Convert length of symlink */
+ len = ntohl(*p++);
+@@ -872,7 +891,7 @@ nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
+ p = xdr_decode_post_op_attr(p, res->fattr);
+
+ if (status != 0)
+- return -nfs_stat_to_errno(status);
++ return nfs_stat_to_errno(status);
+
+ /* Decode reply count and EOF flag. NFSv3 is somewhat redundant
+ * in that it puts the count both in the res struct and in the
+@@ -922,7 +941,7 @@ nfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
+ p = xdr_decode_wcc_data(p, res->fattr);
+
+ if (status != 0)
+- return -nfs_stat_to_errno(status);
++ return nfs_stat_to_errno(status);
+
+ res->count = ntohl(*p++);
+ res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);
+@@ -953,7 +972,7 @@ nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
+ res->fattr->valid = 0;
+ }
+ } else {
+- status = -nfs_stat_to_errno(status);
++ status = nfs_stat_to_errno(status);
+ }
+ p = xdr_decode_wcc_data(p, res->dir_attr);
+ return status;
+@@ -968,7 +987,7 @@ nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs3_renameres *res)
+ int status;
+
+ if ((status = ntohl(*p++)) != 0)
+- status = -nfs_stat_to_errno(status);
++ status = nfs_stat_to_errno(status);
+ p = xdr_decode_wcc_data(p, res->fromattr);
+ p = xdr_decode_wcc_data(p, res->toattr);
+ return status;
+@@ -983,7 +1002,7 @@ nfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res)
+ int status;
+
+ if ((status = ntohl(*p++)) != 0)
+- status = -nfs_stat_to_errno(status);
++ status = nfs_stat_to_errno(status);
+ p = xdr_decode_post_op_attr(p, res->fattr);
+ p = xdr_decode_wcc_data(p, res->dir_attr);
+ return status;
+@@ -1001,7 +1020,7 @@ nfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res)
+
+ p = xdr_decode_post_op_attr(p, res->fattr);
+ if (status != 0)
+- return -nfs_stat_to_errno(status);
++ return nfs_stat_to_errno(status);
+
+ p = xdr_decode_hyper(p, &res->tbytes);
+ p = xdr_decode_hyper(p, &res->fbytes);
+@@ -1026,7 +1045,7 @@ nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res)
+
+ p = xdr_decode_post_op_attr(p, res->fattr);
+ if (status != 0)
+- return -nfs_stat_to_errno(status);
++ return nfs_stat_to_errno(status);
+
+ res->rtmax = ntohl(*p++);
+ res->rtpref = ntohl(*p++);
+@@ -1054,7 +1073,7 @@ nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res)
+
+ p = xdr_decode_post_op_attr(p, res->fattr);
+ if (status != 0)
+- return -nfs_stat_to_errno(status);
++ return nfs_stat_to_errno(status);
+ res->max_link = ntohl(*p++);
+ res->max_namelen = ntohl(*p++);
+
+@@ -1073,7 +1092,7 @@ nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
+ status = ntohl(*p++);
+ p = xdr_decode_wcc_data(p, res->fattr);
+ if (status != 0)
+- return -nfs_stat_to_errno(status);
++ return nfs_stat_to_errno(status);
+
+ res->verf->verifier[0] = *p++;
+ res->verf->verifier[1] = *p++;
+@@ -1095,7 +1114,7 @@ nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p,
+ int err, base;
+
+ if (status != 0)
+- return -nfs_stat_to_errno(status);
++ return nfs_stat_to_errno(status);
+ p = xdr_decode_post_op_attr(p, res->fattr);
+ res->mask = ntohl(*p++);
+ if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
+@@ -1122,7 +1141,7 @@ nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
+ int status = ntohl(*p++);
+
+ if (status)
+- return -nfs_stat_to_errno(status);
++ return nfs_stat_to_errno(status);
+ xdr_decode_post_op_attr(p, fattr);
+ return 0;
+ }
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index 7ce0786..dbc0927 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -51,6 +51,7 @@
+
+ #include "nfs4_fs.h"
+ #include "delegation.h"
++#include "internal.h"
+ #include "iostat.h"
+
+ #define NFSDBG_FACILITY NFSDBG_PROC
+@@ -239,6 +240,8 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p)
+ {
+ p->o_res.f_attr = &p->f_attr;
+ p->o_res.dir_attr = &p->dir_attr;
++ p->o_res.seqid = p->o_arg.seqid;
++ p->c_res.seqid = p->c_arg.seqid;
+ p->o_res.server = p->o_arg.server;
+ nfs_fattr_init(&p->f_attr);
+ nfs_fattr_init(&p->dir_attr);
+@@ -729,7 +732,6 @@ static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
+ renew_lease(data->o_res.server, data->timestamp);
+ data->rpc_done = 1;
+ }
+- nfs_increment_open_seqid(data->rpc_status, data->c_arg.seqid);
+ }
+
+ static void nfs4_open_confirm_release(void *calldata)
+@@ -773,6 +775,7 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
+ .rpc_message = &msg,
+ .callback_ops = &nfs4_open_confirm_ops,
+ .callback_data = data,
++ .workqueue = nfsiod_workqueue,
+ .flags = RPC_TASK_ASYNC,
+ };
+ int status;
+@@ -858,7 +861,6 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata)
+ if (!(data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM))
+ nfs_confirm_seqid(&data->owner->so_seqid, 0);
+ }
+- nfs_increment_open_seqid(data->rpc_status, data->o_arg.seqid);
+ data->rpc_done = 1;
+ }
+
+@@ -910,6 +912,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
+ .rpc_message = &msg,
+ .callback_ops = &nfs4_open_ops,
+ .callback_data = data,
++ .workqueue = nfsiod_workqueue,
+ .flags = RPC_TASK_ASYNC,
+ };
+ int status;
+@@ -979,11 +982,8 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s
+ if (IS_ERR(opendata))
+ return PTR_ERR(opendata);
+ ret = nfs4_open_recover(opendata, state);
+- if (ret == -ESTALE) {
+- /* Invalidate the state owner so we don't ever use it again */
+- nfs4_drop_state_owner(state->owner);
++ if (ret == -ESTALE)
+ d_drop(ctx->path.dentry);
+- }
+ nfs4_opendata_put(opendata);
+ return ret;
+ }
+@@ -1226,7 +1226,6 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
+ /* hmm. we are done with the inode, and in the process of freeing
+ * the state_owner. we keep this around to process errors
+ */
+- nfs_increment_open_seqid(task->tk_status, calldata->arg.seqid);
+ switch (task->tk_status) {
+ case 0:
+ nfs_set_open_stateid(state, &calldata->res.stateid, 0);
+@@ -1315,6 +1314,7 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
+ .rpc_client = server->client,
+ .rpc_message = &msg,
+ .callback_ops = &nfs4_close_ops,
++ .workqueue = nfsiod_workqueue,
+ .flags = RPC_TASK_ASYNC,
+ };
+ int status = -ENOMEM;
+@@ -1332,6 +1332,7 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
+ goto out_free_calldata;
+ calldata->arg.bitmask = server->attr_bitmask;
+ calldata->res.fattr = &calldata->fattr;
++ calldata->res.seqid = calldata->arg.seqid;
+ calldata->res.server = server;
+ calldata->path.mnt = mntget(path->mnt);
+ calldata->path.dentry = dget(path->dentry);
+@@ -1404,7 +1405,7 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+ BUG_ON(nd->intent.open.flags & O_CREAT);
+ }
+
+- cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
++ cred = rpc_lookup_cred();
+ if (IS_ERR(cred))
+ return (struct dentry *)cred;
+ parent = dentry->d_parent;
+@@ -1439,7 +1440,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
+ struct rpc_cred *cred;
+ struct nfs4_state *state;
+
+- cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
++ cred = rpc_lookup_cred();
+ if (IS_ERR(cred))
+ return PTR_ERR(cred);
+ state = nfs4_do_open(dir, &path, openflags, NULL, cred);
+@@ -1656,7 +1657,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
+
+ nfs_fattr_init(fattr);
+
+- cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
++ cred = rpc_lookup_cred();
+ if (IS_ERR(cred))
+ return PTR_ERR(cred);
+
+@@ -1892,7 +1893,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
+ struct rpc_cred *cred;
+ int status = 0;
+
+- cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
++ cred = rpc_lookup_cred();
+ if (IS_ERR(cred)) {
+ status = PTR_ERR(cred);
+ goto out;
+@@ -2761,10 +2762,10 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)
+ case -NFS4ERR_STALE_CLIENTID:
+ case -NFS4ERR_STALE_STATEID:
+ case -NFS4ERR_EXPIRED:
+- rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL, NULL);
++ rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
+ nfs4_schedule_state_recovery(clp);
+ if (test_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) == 0)
+- rpc_wake_up_task(task);
++ rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
+ task->tk_status = 0;
+ return -EAGAIN;
+ case -NFS4ERR_DELAY:
+@@ -2884,7 +2885,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short po
+ RPC_DISPLAY_ADDR),
+ rpc_peeraddr2str(clp->cl_rpcclient,
+ RPC_DISPLAY_PROTO),
+- cred->cr_ops->cr_name,
++ clp->cl_rpcclient->cl_auth->au_ops->au_name,
+ clp->cl_id_uniquifier);
+ setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
+ sizeof(setclientid.sc_netid),
+@@ -3158,6 +3159,7 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
+ p->arg.fh = NFS_FH(inode);
+ p->arg.fl = &p->fl;
+ p->arg.seqid = seqid;
++ p->res.seqid = seqid;
+ p->arg.stateid = &lsp->ls_stateid;
+ p->lsp = lsp;
+ atomic_inc(&lsp->ls_count);
+@@ -3183,7 +3185,6 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
+
+ if (RPC_ASSASSINATED(task))
+ return;
+- nfs_increment_lock_seqid(task->tk_status, calldata->arg.seqid);
+ switch (task->tk_status) {
+ case 0:
+ memcpy(calldata->lsp->ls_stateid.data,
+@@ -3235,6 +3236,7 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl,
+ .rpc_client = NFS_CLIENT(lsp->ls_state->inode),
+ .rpc_message = &msg,
+ .callback_ops = &nfs4_locku_ops,
++ .workqueue = nfsiod_workqueue,
+ .flags = RPC_TASK_ASYNC,
+ };
+
+@@ -3261,6 +3263,7 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *
+ struct nfs4_lock_state *lsp;
+ struct rpc_task *task;
+ int status = 0;
++ unsigned char fl_flags = request->fl_flags;
+
+ status = nfs4_set_lock_state(state, request);
+ /* Unlock _before_ we do the RPC call */
+@@ -3284,6 +3287,7 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *
+ status = nfs4_wait_for_completion_rpc_task(task);
+ rpc_put_task(task);
+ out:
++ request->fl_flags = fl_flags;
+ return status;
+ }
+
+@@ -3320,6 +3324,7 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
+ p->arg.lock_stateid = &lsp->ls_stateid;
+ p->arg.lock_owner.clientid = server->nfs_client->cl_clientid;
+ p->arg.lock_owner.id = lsp->ls_id.id;
++ p->res.lock_seqid = p->arg.lock_seqid;
+ p->lsp = lsp;
+ atomic_inc(&lsp->ls_count);
+ p->ctx = get_nfs_open_context(ctx);
+@@ -3346,6 +3351,7 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
+ return;
+ data->arg.open_stateid = &state->stateid;
+ data->arg.new_lock_owner = 1;
++ data->res.open_seqid = data->arg.open_seqid;
+ } else
+ data->arg.new_lock_owner = 0;
+ data->timestamp = jiffies;
+@@ -3363,7 +3369,6 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata)
+ if (RPC_ASSASSINATED(task))
+ goto out;
+ if (data->arg.new_lock_owner != 0) {
+- nfs_increment_open_seqid(data->rpc_status, data->arg.open_seqid);
+ if (data->rpc_status == 0)
+ nfs_confirm_seqid(&data->lsp->ls_seqid, 0);
+ else
+@@ -3375,7 +3380,6 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata)
+ data->lsp->ls_flags |= NFS_LOCK_INITIALIZED;
+ renew_lease(NFS_SERVER(data->ctx->path.dentry->d_inode), data->timestamp);
+ }
+- nfs_increment_lock_seqid(data->rpc_status, data->arg.lock_seqid);
+ out:
+ dprintk("%s: done, ret = %d!\n", __FUNCTION__, data->rpc_status);
+ }
+@@ -3419,6 +3423,7 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
+ .rpc_client = NFS_CLIENT(state->inode),
+ .rpc_message = &msg,
+ .callback_ops = &nfs4_lock_ops,
++ .workqueue = nfsiod_workqueue,
+ .flags = RPC_TASK_ASYNC,
+ };
+ int ret;
+diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
+index b962397..46eb624 100644
+--- a/fs/nfs/nfs4state.c
++++ b/fs/nfs/nfs4state.c
+@@ -71,6 +71,29 @@ static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred)
+ return status;
+ }
+
++static struct rpc_cred *nfs4_get_machine_cred(struct nfs_client *clp)
++{
++ struct rpc_cred *cred = NULL;
++
++ spin_lock(&clp->cl_lock);
++ if (clp->cl_machine_cred != NULL)
++ cred = get_rpccred(clp->cl_machine_cred);
++ spin_unlock(&clp->cl_lock);
++ return cred;
++}
++
++static void nfs4_clear_machine_cred(struct nfs_client *clp)
++{
++ struct rpc_cred *cred;
++
++ spin_lock(&clp->cl_lock);
++ cred = clp->cl_machine_cred;
++ clp->cl_machine_cred = NULL;
++ spin_unlock(&clp->cl_lock);
++ if (cred != NULL)
++ put_rpccred(cred);
++}
++
+ struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp)
+ {
+ struct nfs4_state_owner *sp;
+@@ -91,13 +114,18 @@ static struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp)
+ {
+ struct nfs4_state_owner *sp;
+ struct rb_node *pos;
++ struct rpc_cred *cred;
+
++ cred = nfs4_get_machine_cred(clp);
++ if (cred != NULL)
++ goto out;
+ pos = rb_first(&clp->cl_state_owners);
+ if (pos != NULL) {
+ sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
+- return get_rpccred(sp->so_cred);
++ cred = get_rpccred(sp->so_cred);
+ }
+- return NULL;
++out:
++ return cred;
+ }
+
+ static void nfs_alloc_unique_id(struct rb_root *root, struct nfs_unique_id *new,
+@@ -292,8 +320,10 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct
+ spin_unlock(&clp->cl_lock);
+ if (sp == new)
+ get_rpccred(cred);
+- else
++ else {
++ rpc_destroy_wait_queue(&new->so_sequence.wait);
+ kfree(new);
++ }
+ return sp;
+ }
+
+@@ -310,6 +340,7 @@ void nfs4_put_state_owner(struct nfs4_state_owner *sp)
+ return;
+ nfs4_remove_state_owner(clp, sp);
+ spin_unlock(&clp->cl_lock);
++ rpc_destroy_wait_queue(&sp->so_sequence.wait);
+ put_rpccred(cred);
+ kfree(sp);
+ }
+@@ -529,6 +560,7 @@ static void nfs4_free_lock_state(struct nfs4_lock_state *lsp)
+ spin_lock(&clp->cl_lock);
+ nfs_free_unique_id(&clp->cl_lockowner_id, &lsp->ls_id);
+ spin_unlock(&clp->cl_lock);
++ rpc_destroy_wait_queue(&lsp->ls_sequence.wait);
+ kfree(lsp);
+ }
+
+@@ -731,7 +763,7 @@ int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task)
+ list_add_tail(&seqid->list, &sequence->list);
+ if (list_first_entry(&sequence->list, struct nfs_seqid, list) == seqid)
+ goto unlock;
+- rpc_sleep_on(&sequence->wait, task, NULL, NULL);
++ rpc_sleep_on(&sequence->wait, task, NULL);
+ status = -EAGAIN;
+ unlock:
+ spin_unlock(&sequence->lock);
+@@ -920,10 +952,10 @@ restart_loop:
+ if (cred != NULL) {
+ /* Yes there are: try to renew the old lease */
+ status = nfs4_proc_renew(clp, cred);
++ put_rpccred(cred);
+ switch (status) {
+ case 0:
+ case -NFS4ERR_CB_PATH_DOWN:
+- put_rpccred(cred);
+ goto out;
+ case -NFS4ERR_STALE_CLIENTID:
+ case -NFS4ERR_LEASE_MOVED:
+@@ -932,14 +964,19 @@ restart_loop:
+ } else {
+ /* "reboot" to ensure we clear all state on the server */
+ clp->cl_boot_time = CURRENT_TIME;
+- cred = nfs4_get_setclientid_cred(clp);
+ }
+ /* We're going to have to re-establish a clientid */
+ nfs4_state_mark_reclaim(clp);
+ status = -ENOENT;
++ cred = nfs4_get_setclientid_cred(clp);
+ if (cred != NULL) {
+ status = nfs4_init_client(clp, cred);
+ put_rpccred(cred);
++ /* Handle case where the user hasn't set up machine creds */
++ if (status == -EACCES && cred == clp->cl_machine_cred) {
++ nfs4_clear_machine_cred(clp);
++ goto restart_loop;
++ }
+ }
+ if (status)
+ goto out_error;
+diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
+index db1ed9c..5a2d649 100644
+--- a/fs/nfs/nfs4xdr.c
++++ b/fs/nfs/nfs4xdr.c
+@@ -110,7 +110,7 @@ static int nfs4_stat_to_errno(int);
+ #define decode_savefh_maxsz (op_decode_hdr_maxsz)
+ #define encode_restorefh_maxsz (op_encode_hdr_maxsz)
+ #define decode_restorefh_maxsz (op_decode_hdr_maxsz)
+-#define encode_fsinfo_maxsz (op_encode_hdr_maxsz + 2)
++#define encode_fsinfo_maxsz (encode_getattr_maxsz)
+ #define decode_fsinfo_maxsz (op_decode_hdr_maxsz + 11)
+ #define encode_renew_maxsz (op_encode_hdr_maxsz + 3)
+ #define decode_renew_maxsz (op_decode_hdr_maxsz)
+@@ -1191,8 +1191,8 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
+ attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
+ WRITE32(attrs[0] & readdir->bitmask[0]);
+ WRITE32(attrs[1] & readdir->bitmask[1]);
+- dprintk("%s: cookie = %Lu, verifier = 0x%x%x, bitmap = 0x%x%x\n",
+- __FUNCTION__,
++ dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n",
++ __func__,
+ (unsigned long long)readdir->cookie,
+ ((u32 *)readdir->verifier.data)[0],
+ ((u32 *)readdir->verifier.data)[1],
+@@ -2241,7 +2241,7 @@ static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
+ }
+ READ32(nfserr);
+ if (nfserr != NFS_OK)
+- return -nfs4_stat_to_errno(nfserr);
++ return nfs4_stat_to_errno(nfserr);
+ return 0;
+ }
+
+@@ -2291,7 +2291,7 @@ static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint3
+ bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS;
+ } else
+ bitmask[0] = bitmask[1] = 0;
+- dprintk("%s: bitmask=0x%x%x\n", __FUNCTION__, bitmask[0], bitmask[1]);
++ dprintk("%s: bitmask=%08x:%08x\n", __func__, bitmask[0], bitmask[1]);
+ return 0;
+ }
+
+@@ -3005,6 +3005,8 @@ static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res)
+ int status;
+
+ status = decode_op_hdr(xdr, OP_CLOSE);
++ if (status != -EIO)
++ nfs_increment_open_seqid(status, res->seqid);
+ if (status)
+ return status;
+ READ_BUF(NFS4_STATEID_SIZE);
+@@ -3296,11 +3298,17 @@ static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res)
+ int status;
+
+ status = decode_op_hdr(xdr, OP_LOCK);
++ if (status == -EIO)
++ goto out;
+ if (status == 0) {
+ READ_BUF(NFS4_STATEID_SIZE);
+ COPYMEM(res->stateid.data, NFS4_STATEID_SIZE);
+ } else if (status == -NFS4ERR_DENIED)
+- return decode_lock_denied(xdr, NULL);
++ status = decode_lock_denied(xdr, NULL);
++ if (res->open_seqid != NULL)
++ nfs_increment_open_seqid(status, res->open_seqid);
++ nfs_increment_lock_seqid(status, res->lock_seqid);
++out:
+ return status;
+ }
+
+@@ -3319,6 +3327,8 @@ static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res)
+ int status;
+
+ status = decode_op_hdr(xdr, OP_LOCKU);
++ if (status != -EIO)
++ nfs_increment_lock_seqid(status, res->seqid);
+ if (status == 0) {
+ READ_BUF(NFS4_STATEID_SIZE);
+ COPYMEM(res->stateid.data, NFS4_STATEID_SIZE);
+@@ -3384,6 +3394,8 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
+ int status;
+
+ status = decode_op_hdr(xdr, OP_OPEN);
++ if (status != -EIO)
++ nfs_increment_open_seqid(status, res->seqid);
+ if (status)
+ return status;
+ READ_BUF(NFS4_STATEID_SIZE);
+@@ -3416,6 +3428,8 @@ static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmre
+ int status;
+
+ status = decode_op_hdr(xdr, OP_OPEN_CONFIRM);
++ if (status != -EIO)
++ nfs_increment_open_seqid(status, res->seqid);
+ if (status)
+ return status;
+ READ_BUF(NFS4_STATEID_SIZE);
+@@ -3429,6 +3443,8 @@ static int decode_open_downgrade(struct xdr_stream *xdr, struct nfs_closeres *re
+ int status;
+
+ status = decode_op_hdr(xdr, OP_OPEN_DOWNGRADE);
++ if (status != -EIO)
++ nfs_increment_open_seqid(status, res->seqid);
+ if (status)
+ return status;
+ READ_BUF(NFS4_STATEID_SIZE);
+@@ -3481,7 +3497,7 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
+ size_t hdrlen;
+ u32 recvd, pglen = rcvbuf->page_len;
+ __be32 *end, *entry, *p, *kaddr;
+- unsigned int nr;
++ unsigned int nr = 0;
+ int status;
+
+ status = decode_op_hdr(xdr, OP_READDIR);
+@@ -3489,8 +3505,8 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
+ return status;
+ READ_BUF(8);
+ COPYMEM(readdir->verifier.data, 8);
+- dprintk("%s: verifier = 0x%x%x\n",
+- __FUNCTION__,
++ dprintk("%s: verifier = %08x:%08x\n",
++ __func__,
+ ((u32 *)readdir->verifier.data)[0],
+ ((u32 *)readdir->verifier.data)[1]);
+
+@@ -3505,7 +3521,12 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
+ kaddr = p = kmap_atomic(page, KM_USER0);
+ end = p + ((pglen + readdir->pgbase) >> 2);
+ entry = p;
+- for (nr = 0; *p++; nr++) {
++
++ /* Make sure the packet actually has a value_follows and EOF entry */
++ if ((entry + 1) > end)
++ goto short_pkt;
++
++ for (; *p++; nr++) {
+ u32 len, attrlen, xlen;
+ if (end - p < 3)
+ goto short_pkt;
+@@ -3532,20 +3553,32 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
+ p += attrlen; /* attributes */
+ entry = p;
+ }
+- if (!nr && (entry[0] != 0 || entry[1] == 0))
+- goto short_pkt;
++ /*
++ * Apparently some server sends responses that are a valid size, but
++ * contain no entries, and have value_follows==0 and EOF==0. For
++ * those, just set the EOF marker.
++ */
++ if (!nr && entry[1] == 0) {
++ dprintk("NFS: readdir reply truncated!\n");
++ entry[1] = 1;
++ }
+ out:
+ kunmap_atomic(kaddr, KM_USER0);
+ return 0;
+ short_pkt:
++ /*
++ * When we get a short packet there are 2 possibilities. We can
++ * return an error, or fix up the response to look like a valid
++ * response and return what we have so far. If there are no
++ * entries and the packet was short, then return -EIO. If there
++ * are valid entries in the response, return them and pretend that
++ * the call was successful, but incomplete. The caller can retry the
++ * readdir starting at the last cookie.
++ */
+ dprintk("%s: short packet at entry %d\n", __FUNCTION__, nr);
+ entry[0] = entry[1] = 0;
+- /* truncate listing ? */
+- if (!nr) {
+- dprintk("NFS: readdir reply truncated!\n");
+- entry[1] = 1;
+- }
+- goto out;
++ if (nr)
++ goto out;
+ err_unmap:
+ kunmap_atomic(kaddr, KM_USER0);
+ return -errno_NFSERR_IO;
+@@ -3727,7 +3760,7 @@ static int decode_setclientid(struct xdr_stream *xdr, struct nfs_client *clp)
+ READ_BUF(len);
+ return -NFSERR_CLID_INUSE;
+ } else
+- return -nfs4_stat_to_errno(nfserr);
++ return nfs4_stat_to_errno(nfserr);
+
+ return 0;
+ }
+@@ -4389,7 +4422,7 @@ static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs_fsinf
+ if (!status)
+ status = decode_fsinfo(&xdr, fsinfo);
+ if (!status)
+- status = -nfs4_stat_to_errno(hdr.status);
++ status = nfs4_stat_to_errno(hdr.status);
+ return status;
+ }
+
+@@ -4479,7 +4512,7 @@ static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, __be32 *p,
+ if (!status)
+ status = decode_setclientid(&xdr, clp);
+ if (!status)
+- status = -nfs4_stat_to_errno(hdr.status);
++ status = nfs4_stat_to_errno(hdr.status);
+ return status;
+ }
+
+@@ -4501,7 +4534,7 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str
+ if (!status)
+ status = decode_fsinfo(&xdr, fsinfo);
+ if (!status)
+- status = -nfs4_stat_to_errno(hdr.status);
++ status = nfs4_stat_to_errno(hdr.status);
+ return status;
+ }
+
+@@ -4611,42 +4644,42 @@ static struct {
+ int errno;
+ } nfs_errtbl[] = {
+ { NFS4_OK, 0 },
+- { NFS4ERR_PERM, EPERM },
+- { NFS4ERR_NOENT, ENOENT },
+- { NFS4ERR_IO, errno_NFSERR_IO },
+- { NFS4ERR_NXIO, ENXIO },
+- { NFS4ERR_ACCESS, EACCES },
+- { NFS4ERR_EXIST, EEXIST },
+- { NFS4ERR_XDEV, EXDEV },
+- { NFS4ERR_NOTDIR, ENOTDIR },
+- { NFS4ERR_ISDIR, EISDIR },
+- { NFS4ERR_INVAL, EINVAL },
+- { NFS4ERR_FBIG, EFBIG },
+- { NFS4ERR_NOSPC, ENOSPC },
+- { NFS4ERR_ROFS, EROFS },
+- { NFS4ERR_MLINK, EMLINK },
+- { NFS4ERR_NAMETOOLONG, ENAMETOOLONG },
+- { NFS4ERR_NOTEMPTY, ENOTEMPTY },
+- { NFS4ERR_DQUOT, EDQUOT },
+- { NFS4ERR_STALE, ESTALE },
+- { NFS4ERR_BADHANDLE, EBADHANDLE },
+- { NFS4ERR_BADOWNER, EINVAL },
+- { NFS4ERR_BADNAME, EINVAL },
+- { NFS4ERR_BAD_COOKIE, EBADCOOKIE },
+- { NFS4ERR_NOTSUPP, ENOTSUPP },
+- { NFS4ERR_TOOSMALL, ETOOSMALL },
+- { NFS4ERR_SERVERFAULT, ESERVERFAULT },
+- { NFS4ERR_BADTYPE, EBADTYPE },
+- { NFS4ERR_LOCKED, EAGAIN },
+- { NFS4ERR_RESOURCE, EREMOTEIO },
+- { NFS4ERR_SYMLINK, ELOOP },
+- { NFS4ERR_OP_ILLEGAL, EOPNOTSUPP },
+- { NFS4ERR_DEADLOCK, EDEADLK },
+- { NFS4ERR_WRONGSEC, EPERM }, /* FIXME: this needs
++ { NFS4ERR_PERM, -EPERM },
++ { NFS4ERR_NOENT, -ENOENT },
++ { NFS4ERR_IO, -errno_NFSERR_IO},
++ { NFS4ERR_NXIO, -ENXIO },
++ { NFS4ERR_ACCESS, -EACCES },
++ { NFS4ERR_EXIST, -EEXIST },
++ { NFS4ERR_XDEV, -EXDEV },
++ { NFS4ERR_NOTDIR, -ENOTDIR },
++ { NFS4ERR_ISDIR, -EISDIR },
++ { NFS4ERR_INVAL, -EINVAL },
++ { NFS4ERR_FBIG, -EFBIG },
++ { NFS4ERR_NOSPC, -ENOSPC },
++ { NFS4ERR_ROFS, -EROFS },
++ { NFS4ERR_MLINK, -EMLINK },
++ { NFS4ERR_NAMETOOLONG, -ENAMETOOLONG },
++ { NFS4ERR_NOTEMPTY, -ENOTEMPTY },
++ { NFS4ERR_DQUOT, -EDQUOT },
++ { NFS4ERR_STALE, -ESTALE },
++ { NFS4ERR_BADHANDLE, -EBADHANDLE },
++ { NFS4ERR_BADOWNER, -EINVAL },
++ { NFS4ERR_BADNAME, -EINVAL },
++ { NFS4ERR_BAD_COOKIE, -EBADCOOKIE },
++ { NFS4ERR_NOTSUPP, -ENOTSUPP },
++ { NFS4ERR_TOOSMALL, -ETOOSMALL },
++ { NFS4ERR_SERVERFAULT, -ESERVERFAULT },
++ { NFS4ERR_BADTYPE, -EBADTYPE },
++ { NFS4ERR_LOCKED, -EAGAIN },
++ { NFS4ERR_RESOURCE, -EREMOTEIO },
++ { NFS4ERR_SYMLINK, -ELOOP },
++ { NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP },
++ { NFS4ERR_DEADLOCK, -EDEADLK },
++ { NFS4ERR_WRONGSEC, -EPERM }, /* FIXME: this needs
+ * to be handled by a
+ * middle-layer.
+ */
+- { -1, EIO }
++ { -1, -EIO }
+ };
+
+ /*
+@@ -4663,14 +4696,14 @@ nfs4_stat_to_errno(int stat)
+ }
+ if (stat <= 10000 || stat > 10100) {
+ /* The server is looney tunes. */
+- return ESERVERFAULT;
++ return -ESERVERFAULT;
+ }
+ /* If we cannot translate the error, the recovery routines should
+ * handle it.
+ * Note: remaining NFSv4 error codes have values > 10000, so should
+ * not conflict with native Linux error codes.
+ */
+- return stat;
++ return -stat;
+ }
+
+ #define PROC(proc, argtype, restype) \
+diff --git a/fs/nfs/read.c b/fs/nfs/read.c
+index 5a70be5..16f57e0 100644
+--- a/fs/nfs/read.c
++++ b/fs/nfs/read.c
+@@ -58,22 +58,19 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
+ return p;
+ }
+
+-static void nfs_readdata_rcu_free(struct rcu_head *head)
++static void nfs_readdata_free(struct nfs_read_data *p)
+ {
+- struct nfs_read_data *p = container_of(head, struct nfs_read_data, task.u.tk_rcu);
+ if (p && (p->pagevec != &p->page_array[0]))
+ kfree(p->pagevec);
+ mempool_free(p, nfs_rdata_mempool);
+ }
+
+-static void nfs_readdata_free(struct nfs_read_data *rdata)
+-{
+- call_rcu_bh(&rdata->task.u.tk_rcu, nfs_readdata_rcu_free);
+-}
+-
+ void nfs_readdata_release(void *data)
+ {
+- nfs_readdata_free(data);
++ struct nfs_read_data *rdata = data;
++
++ put_nfs_open_context(rdata->args.context);
++ nfs_readdata_free(rdata);
+ }
+
+ static
+@@ -156,7 +153,7 @@ static void nfs_readpage_release(struct nfs_page *req)
+ /*
+ * Set up the NFS read request struct
+ */
+-static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
++static int nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
+ const struct rpc_call_ops *call_ops,
+ unsigned int count, unsigned int offset)
+ {
+@@ -174,6 +171,7 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
+ .rpc_message = &msg,
+ .callback_ops = call_ops,
+ .callback_data = data,
++ .workqueue = nfsiod_workqueue,
+ .flags = RPC_TASK_ASYNC | swap_flags,
+ };
+
+@@ -186,7 +184,7 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
+ data->args.pgbase = req->wb_pgbase + offset;
+ data->args.pages = data->pagevec;
+ data->args.count = count;
+- data->args.context = req->wb_context;
++ data->args.context = get_nfs_open_context(req->wb_context);
+
+ data->res.fattr = &data->fattr;
+ data->res.count = count;
+@@ -204,8 +202,10 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
+ (unsigned long long)data->args.offset);
+
+ task = rpc_run_task(&task_setup_data);
+- if (!IS_ERR(task))
+- rpc_put_task(task);
++ if (IS_ERR(task))
++ return PTR_ERR(task);
++ rpc_put_task(task);
++ return 0;
+ }
+
+ static void
+@@ -242,6 +242,7 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne
+ size_t rsize = NFS_SERVER(inode)->rsize, nbytes;
+ unsigned int offset;
+ int requests = 0;
++ int ret = 0;
+ LIST_HEAD(list);
+
+ nfs_list_remove_request(req);
+@@ -253,7 +254,6 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne
+ data = nfs_readdata_alloc(1);
+ if (!data)
+ goto out_bad;
+- INIT_LIST_HEAD(&data->pages);
+ list_add(&data->pages, &list);
+ requests++;
+ nbytes -= len;
+@@ -264,6 +264,8 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne
+ offset = 0;
+ nbytes = count;
+ do {
++ int ret2;
++
+ data = list_entry(list.next, struct nfs_read_data, pages);
+ list_del_init(&data->pages);
+
+@@ -271,13 +273,15 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne
+
+ if (nbytes < rsize)
+ rsize = nbytes;
+- nfs_read_rpcsetup(req, data, &nfs_read_partial_ops,
++ ret2 = nfs_read_rpcsetup(req, data, &nfs_read_partial_ops,
+ rsize, offset);
++ if (ret == 0)
++ ret = ret2;
+ offset += rsize;
+ nbytes -= rsize;
+ } while (nbytes != 0);
+
+- return 0;
++ return ret;
+
+ out_bad:
+ while (!list_empty(&list)) {
+@@ -295,12 +299,12 @@ static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned
+ struct nfs_page *req;
+ struct page **pages;
+ struct nfs_read_data *data;
++ int ret = -ENOMEM;
+
+ data = nfs_readdata_alloc(npages);
+ if (!data)
+ goto out_bad;
+
+- INIT_LIST_HEAD(&data->pages);
+ pages = data->pagevec;
+ while (!list_empty(head)) {
+ req = nfs_list_entry(head->next);
+@@ -311,11 +315,10 @@ static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned
+ }
+ req = nfs_list_entry(data->pages.next);
+
+- nfs_read_rpcsetup(req, data, &nfs_read_full_ops, count, 0);
+- return 0;
++ return nfs_read_rpcsetup(req, data, &nfs_read_full_ops, count, 0);
+ out_bad:
+ nfs_async_read_error(head);
+- return -ENOMEM;
++ return ret;
+ }
+
+ /*
+@@ -342,26 +345,25 @@ int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data)
+ return 0;
+ }
+
+-static int nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data)
++static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data)
+ {
+ struct nfs_readargs *argp = &data->args;
+ struct nfs_readres *resp = &data->res;
+
+ if (resp->eof || resp->count == argp->count)
+- return 0;
++ return;
+
+ /* This is a short read! */
+ nfs_inc_stats(data->inode, NFSIOS_SHORTREAD);
+ /* Has the server at least made some progress? */
+ if (resp->count == 0)
+- return 0;
++ return;
+
+ /* Yes, so retry the read at the end of the data */
+ argp->offset += resp->count;
+ argp->pgbase += resp->count;
+ argp->count -= resp->count;
+ rpc_restart_call(task);
+- return -EAGAIN;
+ }
+
+ /*
+@@ -370,29 +372,37 @@ static int nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data)
+ static void nfs_readpage_result_partial(struct rpc_task *task, void *calldata)
+ {
+ struct nfs_read_data *data = calldata;
+- struct nfs_page *req = data->req;
+- struct page *page = req->wb_page;
+
+ if (nfs_readpage_result(task, data) != 0)
+ return;
++ if (task->tk_status < 0)
++ return;
+
+- if (likely(task->tk_status >= 0)) {
+- nfs_readpage_truncate_uninitialised_page(data);
+- if (nfs_readpage_retry(task, data) != 0)
+- return;
+- }
+- if (unlikely(task->tk_status < 0))
++ nfs_readpage_truncate_uninitialised_page(data);
++ nfs_readpage_retry(task, data);
++}
++
++static void nfs_readpage_release_partial(void *calldata)
++{
++ struct nfs_read_data *data = calldata;
++ struct nfs_page *req = data->req;
++ struct page *page = req->wb_page;
++ int status = data->task.tk_status;
++
++ if (status < 0)
+ SetPageError(page);
++
+ if (atomic_dec_and_test(&req->wb_complete)) {
+ if (!PageError(page))
+ SetPageUptodate(page);
+ nfs_readpage_release(req);
+ }
++ nfs_readdata_release(calldata);
+ }
+
+ static const struct rpc_call_ops nfs_read_partial_ops = {
+ .rpc_call_done = nfs_readpage_result_partial,
+- .rpc_release = nfs_readdata_release,
++ .rpc_release = nfs_readpage_release_partial,
+ };
+
+ static void nfs_readpage_set_pages_uptodate(struct nfs_read_data *data)
+@@ -427,29 +437,35 @@ static void nfs_readpage_result_full(struct rpc_task *task, void *calldata)
+
+ if (nfs_readpage_result(task, data) != 0)
+ return;
++ if (task->tk_status < 0)
++ return;
+ /*
+ * Note: nfs_readpage_retry may change the values of
+ * data->args. In the multi-page case, we therefore need
+ * to ensure that we call nfs_readpage_set_pages_uptodate()
+ * first.
+ */
+- if (likely(task->tk_status >= 0)) {
+- nfs_readpage_truncate_uninitialised_page(data);
+- nfs_readpage_set_pages_uptodate(data);
+- if (nfs_readpage_retry(task, data) != 0)
+- return;
+- }
++ nfs_readpage_truncate_uninitialised_page(data);
++ nfs_readpage_set_pages_uptodate(data);
++ nfs_readpage_retry(task, data);
++}
++
++static void nfs_readpage_release_full(void *calldata)
++{
++ struct nfs_read_data *data = calldata;
++
+ while (!list_empty(&data->pages)) {
+ struct nfs_page *req = nfs_list_entry(data->pages.next);
+
+ nfs_list_remove_request(req);
+ nfs_readpage_release(req);
+ }
++ nfs_readdata_release(calldata);
+ }
+
+ static const struct rpc_call_ops nfs_read_full_ops = {
+ .rpc_call_done = nfs_readpage_result_full,
+- .rpc_release = nfs_readdata_release,
++ .rpc_release = nfs_readpage_release_full,
+ };
+
+ /*
+diff --git a/fs/nfs/super.c b/fs/nfs/super.c
+index f921902..fa220dc 100644
+--- a/fs/nfs/super.c
++++ b/fs/nfs/super.c
+@@ -198,7 +198,7 @@ static match_table_t nfs_secflavor_tokens = {
+ };
+
+
+-static void nfs_umount_begin(struct vfsmount *, int);
++static void nfs_umount_begin(struct super_block *);
+ static int nfs_statfs(struct dentry *, struct kstatfs *);
+ static int nfs_show_options(struct seq_file *, struct vfsmount *);
+ static int nfs_show_stats(struct seq_file *, struct vfsmount *);
+@@ -441,10 +441,52 @@ static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour)
+ return sec_flavours[i].str;
+ }
+
++static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss,
++ int showdefaults)
++{
++ struct sockaddr *sap = (struct sockaddr *)&nfss->mountd_address;
++
++ switch (sap->sa_family) {
++ case AF_INET: {
++ struct sockaddr_in *sin = (struct sockaddr_in *)sap;
++ seq_printf(m, ",mountaddr=" NIPQUAD_FMT,
++ NIPQUAD(sin->sin_addr.s_addr));
++ break;
++ }
++ case AF_INET6: {
++ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
++ seq_printf(m, ",mountaddr=" NIP6_FMT,
++ NIP6(sin6->sin6_addr));
++ break;
++ }
++ default:
++ if (showdefaults)
++ seq_printf(m, ",mountaddr=unspecified");
++ }
++
++ if (nfss->mountd_version || showdefaults)
++ seq_printf(m, ",mountvers=%u", nfss->mountd_version);
++ if (nfss->mountd_port || showdefaults)
++ seq_printf(m, ",mountport=%u", nfss->mountd_port);
++
++ switch (nfss->mountd_protocol) {
++ case IPPROTO_UDP:
++ seq_printf(m, ",mountproto=udp");
++ break;
++ case IPPROTO_TCP:
++ seq_printf(m, ",mountproto=tcp");
++ break;
++ default:
++ if (showdefaults)
++ seq_printf(m, ",mountproto=auto");
++ }
++}
++
+ /*
+ * Describe the mount options in force on this server representation
+ */
+-static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, int showdefaults)
++static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
++ int showdefaults)
+ {
+ static const struct proc_nfs_info {
+ int flag;
+@@ -452,6 +494,8 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
+ const char *nostr;
+ } nfs_info[] = {
+ { NFS_MOUNT_SOFT, ",soft", ",hard" },
++ { NFS_MOUNT_INTR, ",intr", ",nointr" },
++ { NFS_MOUNT_POSIX, ",posix", "" },
+ { NFS_MOUNT_NOCTO, ",nocto", "" },
+ { NFS_MOUNT_NOAC, ",noac", "" },
+ { NFS_MOUNT_NONLM, ",nolock", "" },
+@@ -462,18 +506,22 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
+ };
+ const struct proc_nfs_info *nfs_infop;
+ struct nfs_client *clp = nfss->nfs_client;
+-
+- seq_printf(m, ",vers=%d", clp->rpc_ops->version);
+- seq_printf(m, ",rsize=%d", nfss->rsize);
+- seq_printf(m, ",wsize=%d", nfss->wsize);
++ u32 version = clp->rpc_ops->version;
++
++ seq_printf(m, ",vers=%u", version);
++ seq_printf(m, ",rsize=%u", nfss->rsize);
++ seq_printf(m, ",wsize=%u", nfss->wsize);
++ if (nfss->bsize != 0)
++ seq_printf(m, ",bsize=%u", nfss->bsize);
++ seq_printf(m, ",namlen=%u", nfss->namelen);
+ if (nfss->acregmin != 3*HZ || showdefaults)
+- seq_printf(m, ",acregmin=%d", nfss->acregmin/HZ);
++ seq_printf(m, ",acregmin=%u", nfss->acregmin/HZ);
+ if (nfss->acregmax != 60*HZ || showdefaults)
+- seq_printf(m, ",acregmax=%d", nfss->acregmax/HZ);
++ seq_printf(m, ",acregmax=%u", nfss->acregmax/HZ);
+ if (nfss->acdirmin != 30*HZ || showdefaults)
+- seq_printf(m, ",acdirmin=%d", nfss->acdirmin/HZ);
++ seq_printf(m, ",acdirmin=%u", nfss->acdirmin/HZ);
+ if (nfss->acdirmax != 60*HZ || showdefaults)
+- seq_printf(m, ",acdirmax=%d", nfss->acdirmax/HZ);
++ seq_printf(m, ",acdirmax=%u", nfss->acdirmax/HZ);
+ for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) {
+ if (nfss->flags & nfs_infop->flag)
+ seq_puts(m, nfs_infop->str);
+@@ -482,9 +530,24 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
+ }
+ seq_printf(m, ",proto=%s",
+ rpc_peeraddr2str(nfss->client, RPC_DISPLAY_PROTO));
++ if (version == 4) {
++ if (nfss->port != NFS_PORT)
++ seq_printf(m, ",port=%u", nfss->port);
++ } else
++ if (nfss->port)
++ seq_printf(m, ",port=%u", nfss->port);
++
+ seq_printf(m, ",timeo=%lu", 10U * nfss->client->cl_timeout->to_initval / HZ);
+ seq_printf(m, ",retrans=%u", nfss->client->cl_timeout->to_retries);
+ seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor));
++
++ if (version != 4)
++ nfs_show_mountd_options(m, nfss, showdefaults);
++
++#ifdef CONFIG_NFS_V4
++ if (clp->rpc_ops->version == 4)
++ seq_printf(m, ",clientaddr=%s", clp->cl_ipaddr);
++#endif
+ }
+
+ /*
+@@ -529,10 +592,10 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
+
+ seq_printf(m, "\n\tcaps:\t");
+ seq_printf(m, "caps=0x%x", nfss->caps);
+- seq_printf(m, ",wtmult=%d", nfss->wtmult);
+- seq_printf(m, ",dtsize=%d", nfss->dtsize);
+- seq_printf(m, ",bsize=%d", nfss->bsize);
+- seq_printf(m, ",namelen=%d", nfss->namelen);
++ seq_printf(m, ",wtmult=%u", nfss->wtmult);
++ seq_printf(m, ",dtsize=%u", nfss->dtsize);
++ seq_printf(m, ",bsize=%u", nfss->bsize);
++ seq_printf(m, ",namlen=%u", nfss->namelen);
+
+ #ifdef CONFIG_NFS_V4
+ if (nfss->nfs_client->rpc_ops->version == 4) {
+@@ -546,9 +609,9 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
+ /*
+ * Display security flavor in effect for this mount
+ */
+- seq_printf(m, "\n\tsec:\tflavor=%d", auth->au_ops->au_flavor);
++ seq_printf(m, "\n\tsec:\tflavor=%u", auth->au_ops->au_flavor);
+ if (auth->au_flavor)
+- seq_printf(m, ",pseudoflavor=%d", auth->au_flavor);
++ seq_printf(m, ",pseudoflavor=%u", auth->au_flavor);
+
+ /*
+ * Display superblock I/O counters
+@@ -584,13 +647,11 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
+ * Begin unmount by attempting to remove all automounted mountpoints we added
+ * in response to xdev traversals and referrals
+ */
+-static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags)
++static void nfs_umount_begin(struct super_block *sb)
+ {
+- struct nfs_server *server = NFS_SB(vfsmnt->mnt_sb);
++ struct nfs_server *server = NFS_SB(sb);
+ struct rpc_clnt *rpc;
+
+- if (!(flags & MNT_FORCE))
+- return;
+ /* -EIO all pending I/O */
+ rpc = server->client_acl;
+ if (!IS_ERR(rpc))
+@@ -683,7 +744,6 @@ static int nfs_parse_mount_options(char *raw,
+ struct nfs_parsed_mount_data *mnt)
+ {
+ char *p, *string, *secdata;
+- unsigned short port = 0;
+ int rc;
+
+ if (!raw) {
+@@ -798,7 +858,7 @@ static int nfs_parse_mount_options(char *raw,
+ return 0;
+ if (option < 0 || option > 65535)
+ return 0;
+- port = option;
++ mnt->nfs_server.port = option;
+ break;
+ case Opt_rsize:
+ if (match_int(args, &mnt->rsize))
+@@ -1048,7 +1108,8 @@ static int nfs_parse_mount_options(char *raw,
+ }
+ }
+
+- nfs_set_port((struct sockaddr *)&mnt->nfs_server.address, port);
++ nfs_set_port((struct sockaddr *)&mnt->nfs_server.address,
++ mnt->nfs_server.port);
+
+ return 1;
+
+@@ -1169,7 +1230,9 @@ static int nfs_validate_mount_data(void *options,
+ args->acregmax = 60;
+ args->acdirmin = 30;
+ args->acdirmax = 60;
++ args->mount_server.port = 0; /* autobind unless user sets port */
+ args->mount_server.protocol = XPRT_TRANSPORT_UDP;
++ args->nfs_server.port = 0; /* autobind unless user sets port */
+ args->nfs_server.protocol = XPRT_TRANSPORT_TCP;
+
+ switch (data->version) {
+@@ -1208,7 +1271,6 @@ static int nfs_validate_mount_data(void *options,
+ args->flags = data->flags;
+ args->rsize = data->rsize;
+ args->wsize = data->wsize;
+- args->flags = data->flags;
+ args->timeo = data->timeo;
+ args->retrans = data->retrans;
+ args->acregmin = data->acregmin;
+@@ -1230,6 +1292,8 @@ static int nfs_validate_mount_data(void *options,
+ args->namlen = data->namlen;
+ args->bsize = data->bsize;
+ args->auth_flavors[0] = data->pseudoflavor;
++ if (!args->nfs_server.hostname)
++ goto out_nomem;
+
+ /*
+ * The legacy version 6 binary mount data from userspace has a
+@@ -1276,6 +1340,8 @@ static int nfs_validate_mount_data(void *options,
+ len = c - dev_name;
+ /* N.B. caller will free nfs_server.hostname in all cases */
+ args->nfs_server.hostname = kstrndup(dev_name, len, GFP_KERNEL);
++ if (!args->nfs_server.hostname)
++ goto out_nomem;
+
+ c++;
+ if (strlen(c) > NFS_MAXPATHLEN)
+@@ -1319,6 +1385,10 @@ out_v3_not_compiled:
+ return -EPROTONOSUPPORT;
+ #endif /* !CONFIG_NFS_V3 */
+
++out_nomem:
++ dfprintk(MOUNT, "NFS: not enough memory to handle mount options\n");
++ return -ENOMEM;
++
+ out_no_address:
+ dfprintk(MOUNT, "NFS: mount program didn't pass remote address\n");
+ return -EINVAL;
+@@ -1706,28 +1776,6 @@ static void nfs4_fill_super(struct super_block *sb)
+ }
+
+ /*
+- * If the user didn't specify a port, set the port number to
+- * the NFS version 4 default port.
+- */
+-static void nfs4_default_port(struct sockaddr *sap)
+-{
+- switch (sap->sa_family) {
+- case AF_INET: {
+- struct sockaddr_in *ap = (struct sockaddr_in *)sap;
+- if (ap->sin_port == 0)
+- ap->sin_port = htons(NFS_PORT);
+- break;
+- }
+- case AF_INET6: {
+- struct sockaddr_in6 *ap = (struct sockaddr_in6 *)sap;
+- if (ap->sin6_port == 0)
+- ap->sin6_port = htons(NFS_PORT);
+- break;
+- }
+- }
+-}
+-
+-/*
+ * Validate NFSv4 mount options
+ */
+ static int nfs4_validate_mount_data(void *options,
+@@ -1751,6 +1799,7 @@ static int nfs4_validate_mount_data(void *options,
+ args->acregmax = 60;
+ args->acdirmin = 30;
+ args->acdirmax = 60;
++ args->nfs_server.port = NFS_PORT; /* 2049 unless user set port= */
+ args->nfs_server.protocol = XPRT_TRANSPORT_TCP;
+
+ switch (data->version) {
+@@ -1767,9 +1816,6 @@ static int nfs4_validate_mount_data(void *options,
+ &args->nfs_server.address))
+ goto out_no_address;
+
+- nfs4_default_port((struct sockaddr *)
+- &args->nfs_server.address);
+-
+ switch (data->auth_flavourlen) {
+ case 0:
+ args->auth_flavors[0] = RPC_AUTH_UNIX;
+@@ -1827,9 +1873,6 @@ static int nfs4_validate_mount_data(void *options,
+ &args->nfs_server.address))
+ return -EINVAL;
+
+- nfs4_default_port((struct sockaddr *)
+- &args->nfs_server.address);
+-
+ switch (args->auth_flavor_len) {
+ case 0:
+ args->auth_flavors[0] = RPC_AUTH_UNIX;
+@@ -1852,12 +1895,16 @@ static int nfs4_validate_mount_data(void *options,
+ return -ENAMETOOLONG;
+ /* N.B. caller will free nfs_server.hostname in all cases */
+ args->nfs_server.hostname = kstrndup(dev_name, len, GFP_KERNEL);
++ if (!args->nfs_server.hostname)
++ goto out_nomem;
+
+ c++; /* step over the ':' */
+ len = strlen(c);
+ if (len > NFS4_MAXPATHLEN)
+ return -ENAMETOOLONG;
+ args->nfs_server.export_path = kstrndup(c, len, GFP_KERNEL);
++ if (!args->nfs_server.export_path)
++ goto out_nomem;
+
+ dprintk("NFS: MNTPATH: '%s'\n", args->nfs_server.export_path);
+
+@@ -1879,6 +1926,10 @@ out_inval_auth:
+ data->auth_flavourlen);
+ return -EINVAL;
+
++out_nomem:
++ dfprintk(MOUNT, "NFS4: not enough memory to handle mount options\n");
++ return -ENOMEM;
++
+ out_no_address:
+ dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n");
+ return -EINVAL;
+diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c
+index 83e865a..412738d 100644
+--- a/fs/nfs/symlink.c
++++ b/fs/nfs/symlink.c
+@@ -10,7 +10,6 @@
+ * nfs symlink handling code
+ */
+
+-#define NFS_NEED_XDR_TYPES
+ #include <linux/time.h>
+ #include <linux/errno.h>
+ #include <linux/sunrpc/clnt.h>
+diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
+index 7574153..3adf8b2 100644
+--- a/fs/nfs/unlink.c
++++ b/fs/nfs/unlink.c
+@@ -234,7 +234,7 @@ nfs_async_unlink(struct inode *dir, struct dentry *dentry)
+ if (data == NULL)
+ goto out;
+
+- data->cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
++ data->cred = rpc_lookup_cred();
+ if (IS_ERR(data->cred)) {
+ status = PTR_ERR(data->cred);
+ goto out_free;
+diff --git a/fs/nfs/write.c b/fs/nfs/write.c
+index bed6341..1ade11d 100644
+--- a/fs/nfs/write.c
++++ b/fs/nfs/write.c
+@@ -48,7 +48,7 @@ static struct kmem_cache *nfs_wdata_cachep;
+ static mempool_t *nfs_wdata_mempool;
+ static mempool_t *nfs_commit_mempool;
+
+-struct nfs_write_data *nfs_commit_alloc(void)
++struct nfs_write_data *nfs_commitdata_alloc(void)
+ {
+ struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, GFP_NOFS);
+
+@@ -59,19 +59,13 @@ struct nfs_write_data *nfs_commit_alloc(void)
+ return p;
+ }
+
+-static void nfs_commit_rcu_free(struct rcu_head *head)
++void nfs_commit_free(struct nfs_write_data *p)
+ {
+- struct nfs_write_data *p = container_of(head, struct nfs_write_data, task.u.tk_rcu);
+ if (p && (p->pagevec != &p->page_array[0]))
+ kfree(p->pagevec);
+ mempool_free(p, nfs_commit_mempool);
+ }
+
+-void nfs_commit_free(struct nfs_write_data *wdata)
+-{
+- call_rcu_bh(&wdata->task.u.tk_rcu, nfs_commit_rcu_free);
+-}
+-
+ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
+ {
+ struct nfs_write_data *p = mempool_alloc(nfs_wdata_mempool, GFP_NOFS);
+@@ -93,21 +87,18 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
+ return p;
+ }
+
+-static void nfs_writedata_rcu_free(struct rcu_head *head)
++static void nfs_writedata_free(struct nfs_write_data *p)
+ {
+- struct nfs_write_data *p = container_of(head, struct nfs_write_data, task.u.tk_rcu);
+ if (p && (p->pagevec != &p->page_array[0]))
+ kfree(p->pagevec);
+ mempool_free(p, nfs_wdata_mempool);
+ }
+
+-static void nfs_writedata_free(struct nfs_write_data *wdata)
++void nfs_writedata_release(void *data)
+ {
+- call_rcu_bh(&wdata->task.u.tk_rcu, nfs_writedata_rcu_free);
+-}
++ struct nfs_write_data *wdata = data;
+
+-void nfs_writedata_release(void *wdata)
+-{
++ put_nfs_open_context(wdata->args.context);
+ nfs_writedata_free(wdata);
+ }
+
+@@ -291,8 +282,6 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
+ spin_unlock(&inode->i_lock);
+ if (!nfs_pageio_add_request(pgio, req)) {
+ nfs_redirty_request(req);
+- nfs_end_page_writeback(page);
+- nfs_clear_page_tag_locked(req);
+ return pgio->pg_error;
+ }
+ return 0;
+@@ -366,15 +355,13 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
+ /*
+ * Insert a write request into an inode
+ */
+-static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
++static void nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
+ {
+ struct nfs_inode *nfsi = NFS_I(inode);
+ int error;
+
+ error = radix_tree_insert(&nfsi->nfs_page_tree, req->wb_index, req);
+- BUG_ON(error == -EEXIST);
+- if (error)
+- return error;
++ BUG_ON(error);
+ if (!nfsi->npages) {
+ igrab(inode);
+ if (nfs_have_delegation(inode, FMODE_WRITE))
+@@ -384,8 +371,8 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
+ set_page_private(req->wb_page, (unsigned long)req);
+ nfsi->npages++;
+ kref_get(&req->wb_kref);
+- radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
+- return 0;
++ radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index,
++ NFS_PAGE_TAG_LOCKED);
+ }
+
+ /*
+@@ -413,7 +400,7 @@ static void nfs_inode_remove_request(struct nfs_page *req)
+ }
+
+ static void
+-nfs_redirty_request(struct nfs_page *req)
++nfs_mark_request_dirty(struct nfs_page *req)
+ {
+ __set_page_dirty_nobuffers(req->wb_page);
+ }
+@@ -467,7 +454,7 @@ int nfs_reschedule_unstable_write(struct nfs_page *req)
+ return 1;
+ }
+ if (test_and_clear_bit(PG_NEED_RESCHED, &req->wb_flags)) {
+- nfs_redirty_request(req);
++ nfs_mark_request_dirty(req);
+ return 1;
+ }
+ return 0;
+@@ -597,6 +584,13 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
+ /* Loop over all inode entries and see if we find
+ * A request for the page we wish to update
+ */
++ if (new) {
++ if (radix_tree_preload(GFP_NOFS)) {
++ nfs_release_request(new);
++ return ERR_PTR(-ENOMEM);
++ }
++ }
++
+ spin_lock(&inode->i_lock);
+ req = nfs_page_find_request_locked(page);
+ if (req) {
+@@ -607,28 +601,27 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
+ error = nfs_wait_on_request(req);
+ nfs_release_request(req);
+ if (error < 0) {
+- if (new)
++ if (new) {
++ radix_tree_preload_end();
+ nfs_release_request(new);
++ }
+ return ERR_PTR(error);
+ }
+ continue;
+ }
+ spin_unlock(&inode->i_lock);
+- if (new)
++ if (new) {
++ radix_tree_preload_end();
+ nfs_release_request(new);
++ }
+ break;
+ }
+
+ if (new) {
+- int error;
+ nfs_lock_request_dontget(new);
+- error = nfs_inode_add_request(inode, new);
+- if (error) {
+- spin_unlock(&inode->i_lock);
+- nfs_unlock_request(new);
+- return ERR_PTR(error);
+- }
++ nfs_inode_add_request(inode, new);
+ spin_unlock(&inode->i_lock);
++ radix_tree_preload_end();
+ req = new;
+ goto zero_page;
+ }
+@@ -785,7 +778,7 @@ static int flush_task_priority(int how)
+ /*
+ * Set up the argument/result storage required for the RPC call.
+ */
+-static void nfs_write_rpcsetup(struct nfs_page *req,
++static int nfs_write_rpcsetup(struct nfs_page *req,
+ struct nfs_write_data *data,
+ const struct rpc_call_ops *call_ops,
+ unsigned int count, unsigned int offset,
+@@ -806,6 +799,7 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
+ .rpc_message = &msg,
+ .callback_ops = call_ops,
+ .callback_data = data,
++ .workqueue = nfsiod_workqueue,
+ .flags = flags,
+ .priority = priority,
+ };
+@@ -822,7 +816,7 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
+ data->args.pgbase = req->wb_pgbase + offset;
+ data->args.pages = data->pagevec;
+ data->args.count = count;
+- data->args.context = req->wb_context;
++ data->args.context = get_nfs_open_context(req->wb_context);
+ data->args.stable = NFS_UNSTABLE;
+ if (how & FLUSH_STABLE) {
+ data->args.stable = NFS_DATA_SYNC;
+@@ -847,8 +841,21 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
+ (unsigned long long)data->args.offset);
+
+ task = rpc_run_task(&task_setup_data);
+- if (!IS_ERR(task))
+- rpc_put_task(task);
++ if (IS_ERR(task))
++ return PTR_ERR(task);
++ rpc_put_task(task);
++ return 0;
++}
++
++/* If a nfs_flush_* function fails, it should remove reqs from @head and
++ * call this on each, which will prepare them to be retried on next
++ * writeback using standard nfs.
++ */
++static void nfs_redirty_request(struct nfs_page *req)
++{
++ nfs_mark_request_dirty(req);
++ nfs_end_page_writeback(req->wb_page);
++ nfs_clear_page_tag_locked(req);
+ }
+
+ /*
+@@ -863,6 +870,7 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned
+ size_t wsize = NFS_SERVER(inode)->wsize, nbytes;
+ unsigned int offset;
+ int requests = 0;
++ int ret = 0;
+ LIST_HEAD(list);
+
+ nfs_list_remove_request(req);
+@@ -884,6 +892,8 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned
+ offset = 0;
+ nbytes = count;
+ do {
++ int ret2;
++
+ data = list_entry(list.next, struct nfs_write_data, pages);
+ list_del_init(&data->pages);
+
+@@ -891,13 +901,15 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned
+
+ if (nbytes < wsize)
+ wsize = nbytes;
+- nfs_write_rpcsetup(req, data, &nfs_write_partial_ops,
++ ret2 = nfs_write_rpcsetup(req, data, &nfs_write_partial_ops,
+ wsize, offset, how);
++ if (ret == 0)
++ ret = ret2;
+ offset += wsize;
+ nbytes -= wsize;
+ } while (nbytes != 0);
+
+- return 0;
++ return ret;
+
+ out_bad:
+ while (!list_empty(&list)) {
+@@ -906,8 +918,6 @@ out_bad:
+ nfs_writedata_release(data);
+ }
+ nfs_redirty_request(req);
+- nfs_end_page_writeback(req->wb_page);
+- nfs_clear_page_tag_locked(req);
+ return -ENOMEM;
+ }
+
+@@ -940,16 +950,12 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned i
+ req = nfs_list_entry(data->pages.next);
+
+ /* Set up the argument struct */
+- nfs_write_rpcsetup(req, data, &nfs_write_full_ops, count, 0, how);
+-
+- return 0;
++ return nfs_write_rpcsetup(req, data, &nfs_write_full_ops, count, 0, how);
+ out_bad:
+ while (!list_empty(head)) {
+ req = nfs_list_entry(head->next);
+ nfs_list_remove_request(req);
+ nfs_redirty_request(req);
+- nfs_end_page_writeback(req->wb_page);
+- nfs_clear_page_tag_locked(req);
+ }
+ return -ENOMEM;
+ }
+@@ -972,7 +978,6 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata)
+ {
+ struct nfs_write_data *data = calldata;
+ struct nfs_page *req = data->req;
+- struct page *page = req->wb_page;
+
+ dprintk("NFS: write (%s/%Ld %d@%Ld)",
+ req->wb_context->path.dentry->d_inode->i_sb->s_id,
+@@ -980,13 +985,20 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata)
+ req->wb_bytes,
+ (long long)req_offset(req));
+
+- if (nfs_writeback_done(task, data) != 0)
+- return;
++ nfs_writeback_done(task, data);
++}
+
+- if (task->tk_status < 0) {
++static void nfs_writeback_release_partial(void *calldata)
++{
++ struct nfs_write_data *data = calldata;
++ struct nfs_page *req = data->req;
++ struct page *page = req->wb_page;
++ int status = data->task.tk_status;
++
++ if (status < 0) {
+ nfs_set_pageerror(page);
+- nfs_context_set_write_error(req->wb_context, task->tk_status);
+- dprintk(", error = %d\n", task->tk_status);
++ nfs_context_set_write_error(req->wb_context, status);
++ dprintk(", error = %d\n", status);
+ goto out;
+ }
+
+@@ -1011,11 +1023,12 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata)
+ out:
+ if (atomic_dec_and_test(&req->wb_complete))
+ nfs_writepage_release(req);
++ nfs_writedata_release(calldata);
+ }
+
+ static const struct rpc_call_ops nfs_write_partial_ops = {
+ .rpc_call_done = nfs_writeback_done_partial,
+- .rpc_release = nfs_writedata_release,
++ .rpc_release = nfs_writeback_release_partial,
+ };
+
+ /*
+@@ -1028,17 +1041,21 @@ static const struct rpc_call_ops nfs_write_partial_ops = {
+ static void nfs_writeback_done_full(struct rpc_task *task, void *calldata)
+ {
+ struct nfs_write_data *data = calldata;
+- struct nfs_page *req;
+- struct page *page;
+
+- if (nfs_writeback_done(task, data) != 0)
+- return;
++ nfs_writeback_done(task, data);
++}
++
++static void nfs_writeback_release_full(void *calldata)
++{
++ struct nfs_write_data *data = calldata;
++ int status = data->task.tk_status;
+
+ /* Update attributes as result of writeback. */
+ while (!list_empty(&data->pages)) {
+- req = nfs_list_entry(data->pages.next);
++ struct nfs_page *req = nfs_list_entry(data->pages.next);
++ struct page *page = req->wb_page;
++
+ nfs_list_remove_request(req);
+- page = req->wb_page;
+
+ dprintk("NFS: write (%s/%Ld %d@%Ld)",
+ req->wb_context->path.dentry->d_inode->i_sb->s_id,
+@@ -1046,10 +1063,10 @@ static void nfs_writeback_done_full(struct rpc_task *task, void *calldata)
+ req->wb_bytes,
+ (long long)req_offset(req));
+
+- if (task->tk_status < 0) {
++ if (status < 0) {
+ nfs_set_pageerror(page);
+- nfs_context_set_write_error(req->wb_context, task->tk_status);
+- dprintk(", error = %d\n", task->tk_status);
++ nfs_context_set_write_error(req->wb_context, status);
++ dprintk(", error = %d\n", status);
+ goto remove_request;
+ }
+
+@@ -1069,11 +1086,12 @@ remove_request:
+ next:
+ nfs_clear_page_tag_locked(req);
+ }
++ nfs_writedata_release(calldata);
+ }
+
+ static const struct rpc_call_ops nfs_write_full_ops = {
+ .rpc_call_done = nfs_writeback_done_full,
+- .rpc_release = nfs_writedata_release,
++ .rpc_release = nfs_writeback_release_full,
+ };
+
+
+@@ -1159,15 +1177,18 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
+
+
+ #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
+-void nfs_commit_release(void *wdata)
++void nfs_commitdata_release(void *data)
+ {
++ struct nfs_write_data *wdata = data;
++
++ put_nfs_open_context(wdata->args.context);
+ nfs_commit_free(wdata);
+ }
+
+ /*
+ * Set up the argument/result storage required for the RPC call.
+ */
+-static void nfs_commit_rpcsetup(struct list_head *head,
++static int nfs_commit_rpcsetup(struct list_head *head,
+ struct nfs_write_data *data,
+ int how)
+ {
+@@ -1187,6 +1208,7 @@ static void nfs_commit_rpcsetup(struct list_head *head,
+ .rpc_message = &msg,
+ .callback_ops = &nfs_commit_ops,
+ .callback_data = data,
++ .workqueue = nfsiod_workqueue,
+ .flags = flags,
+ .priority = priority,
+ };
+@@ -1203,6 +1225,7 @@ static void nfs_commit_rpcsetup(struct list_head *head,
+ /* Note: we always request a commit of the entire inode */
+ data->args.offset = 0;
+ data->args.count = 0;
++ data->args.context = get_nfs_open_context(first->wb_context);
+ data->res.count = 0;
+ data->res.fattr = &data->fattr;
+ data->res.verf = &data->verf;
+@@ -1214,8 +1237,10 @@ static void nfs_commit_rpcsetup(struct list_head *head,
+ dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid);
+
+ task = rpc_run_task(&task_setup_data);
+- if (!IS_ERR(task))
+- rpc_put_task(task);
++ if (IS_ERR(task))
++ return PTR_ERR(task);
++ rpc_put_task(task);
++ return 0;
+ }
+
+ /*
+@@ -1227,15 +1252,13 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how)
+ struct nfs_write_data *data;
+ struct nfs_page *req;
+
+- data = nfs_commit_alloc();
++ data = nfs_commitdata_alloc();
+
+ if (!data)
+ goto out_bad;
+
+ /* Set up the argument struct */
+- nfs_commit_rpcsetup(head, data, how);
+-
+- return 0;
++ return nfs_commit_rpcsetup(head, data, how);
+ out_bad:
+ while (!list_empty(head)) {
+ req = nfs_list_entry(head->next);
+@@ -1255,7 +1278,6 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how)
+ static void nfs_commit_done(struct rpc_task *task, void *calldata)
+ {
+ struct nfs_write_data *data = calldata;
+- struct nfs_page *req;
+
+ dprintk("NFS: %5u nfs_commit_done (status %d)\n",
+ task->tk_pid, task->tk_status);
+@@ -1263,6 +1285,13 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
+ /* Call the NFS version-specific code */
+ if (NFS_PROTO(data->inode)->commit_done(task, data) != 0)
+ return;
++}
++
++static void nfs_commit_release(void *calldata)
++{
++ struct nfs_write_data *data = calldata;
++ struct nfs_page *req;
++ int status = data->task.tk_status;
+
+ while (!list_empty(&data->pages)) {
+ req = nfs_list_entry(data->pages.next);
+@@ -1277,10 +1306,10 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
+ (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
+ req->wb_bytes,
+ (long long)req_offset(req));
+- if (task->tk_status < 0) {
+- nfs_context_set_write_error(req->wb_context, task->tk_status);
++ if (status < 0) {
++ nfs_context_set_write_error(req->wb_context, status);
+ nfs_inode_remove_request(req);
+- dprintk(", error = %d\n", task->tk_status);
++ dprintk(", error = %d\n", status);
+ goto next;
+ }
+
+@@ -1297,10 +1326,11 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
+ }
+ /* We have a mismatch. Write the page again */
+ dprintk(" mismatch\n");
+- nfs_redirty_request(req);
++ nfs_mark_request_dirty(req);
+ next:
+ nfs_clear_page_tag_locked(req);
+ }
++ nfs_commitdata_release(calldata);
+ }
+
+ static const struct rpc_call_ops nfs_commit_ops = {
+@@ -1487,18 +1517,19 @@ static int nfs_wb_page_priority(struct inode *inode, struct page *page,
+ };
+ int ret;
+
+- BUG_ON(!PageLocked(page));
+- if (clear_page_dirty_for_io(page)) {
+- ret = nfs_writepage_locked(page, &wbc);
++ do {
++ if (clear_page_dirty_for_io(page)) {
++ ret = nfs_writepage_locked(page, &wbc);
++ if (ret < 0)
++ goto out_error;
++ } else if (!PagePrivate(page))
++ break;
++ ret = nfs_sync_mapping_wait(page->mapping, &wbc, how);
+ if (ret < 0)
+- goto out;
+- }
+- if (!PagePrivate(page))
+- return 0;
+- ret = nfs_sync_mapping_wait(page->mapping, &wbc, how);
+- if (ret >= 0)
+- return 0;
+-out:
++ goto out_error;
++ } while (PagePrivate(page));
++ return 0;
++out_error:
+ __mark_inode_dirty(inode, I_DIRTY_PAGES);
+ return ret;
+ }
+diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
+index d13403e..294992e 100644
+--- a/fs/nfsd/auth.c
++++ b/fs/nfsd/auth.c
+@@ -10,6 +10,7 @@
+ #include <linux/sunrpc/svcauth.h>
+ #include <linux/nfsd/nfsd.h>
+ #include <linux/nfsd/export.h>
++#include "auth.h"
+
+ int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)
+ {
+diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
+index 8a6f7c9..33bfcf0 100644
+--- a/fs/nfsd/export.c
++++ b/fs/nfsd/export.c
+@@ -35,6 +35,7 @@
+ #include <linux/lockd/bind.h>
+ #include <linux/sunrpc/msg_prot.h>
+ #include <linux/sunrpc/gss_api.h>
++#include <net/ipv6.h>
+
+ #define NFSDDBG_FACILITY NFSDDBG_EXPORT
+
+@@ -1548,6 +1549,7 @@ exp_addclient(struct nfsctl_client *ncp)
+ {
+ struct auth_domain *dom;
+ int i, err;
++ struct in6_addr addr6;
+
+ /* First, consistency check. */
+ err = -EINVAL;
+@@ -1566,9 +1568,10 @@ exp_addclient(struct nfsctl_client *ncp)
+ goto out_unlock;
+
+ /* Insert client into hashtable. */
+- for (i = 0; i < ncp->cl_naddr; i++)
+- auth_unix_add_addr(ncp->cl_addrlist[i], dom);
+-
++ for (i = 0; i < ncp->cl_naddr; i++) {
++ ipv6_addr_set_v4mapped(ncp->cl_addrlist[i].s_addr, &addr6);
++ auth_unix_add_addr(&addr6, dom);
++ }
+ auth_unix_forget_old(dom);
+ auth_domain_put(dom);
+
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index aae2b29..562abf3 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -344,6 +344,21 @@ static struct rpc_version * nfs_cb_version[] = {
+ &nfs_cb_version4,
+ };
+
++static struct rpc_program cb_program;
++
++static struct rpc_stat cb_stats = {
++ .program = &cb_program
++};
++
++#define NFS4_CALLBACK 0x40000000
++static struct rpc_program cb_program = {
++ .name = "nfs4_cb",
++ .number = NFS4_CALLBACK,
++ .nrvers = ARRAY_SIZE(nfs_cb_version),
++ .version = nfs_cb_version,
++ .stats = &cb_stats,
++};
++
+ /* Reference counting, callback cleanup, etc., all look racy as heck.
+ * And why is cb_set an atomic? */
+
+@@ -358,13 +373,12 @@ static int do_probe_callback(void *data)
+ .to_maxval = (NFSD_LEASE_TIME/2) * HZ,
+ .to_exponential = 1,
+ };
+- struct rpc_program * program = &cb->cb_program;
+ struct rpc_create_args args = {
+ .protocol = IPPROTO_TCP,
+ .address = (struct sockaddr *)&addr,
+ .addrsize = sizeof(addr),
+ .timeout = &timeparms,
+- .program = program,
++ .program = &cb_program,
+ .version = nfs_cb_version[1]->number,
+ .authflavor = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */
+ .flags = (RPC_CLNT_CREATE_NOPING),
+@@ -382,16 +396,8 @@ static int do_probe_callback(void *data)
+ addr.sin_port = htons(cb->cb_port);
+ addr.sin_addr.s_addr = htonl(cb->cb_addr);
+
+- /* Initialize rpc_program */
+- program->name = "nfs4_cb";
+- program->number = cb->cb_prog;
+- program->nrvers = ARRAY_SIZE(nfs_cb_version);
+- program->version = nfs_cb_version;
+- program->stats = &cb->cb_stat;
+-
+ /* Initialize rpc_stat */
+- memset(program->stats, 0, sizeof(cb->cb_stat));
+- program->stats->program = program;
++ memset(args.program->stats, 0, sizeof(struct rpc_stat));
+
+ /* Create RPC client */
+ client = rpc_create(&args);
+diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
+index 996bd88..5b39842 100644
+--- a/fs/nfsd/nfs4idmap.c
++++ b/fs/nfsd/nfs4idmap.c
+@@ -202,7 +202,7 @@ static struct cache_detail idtoname_cache = {
+ .alloc = ent_alloc,
+ };
+
+-int
++static int
+ idtoname_parse(struct cache_detail *cd, char *buf, int buflen)
+ {
+ struct ent ent, *res;
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index c593db0..c309c88 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -658,14 +658,19 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ return status;
+ }
+ }
++ status = mnt_want_write(cstate->current_fh.fh_export->ex_path.mnt);
++ if (status)
++ return status;
+ status = nfs_ok;
+ if (setattr->sa_acl != NULL)
+ status = nfsd4_set_nfs4_acl(rqstp, &cstate->current_fh,
+ setattr->sa_acl);
+ if (status)
+- return status;
++ goto out;
+ status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr,
+ 0, (time_t)0);
++out:
++ mnt_drop_write(cstate->current_fh.fh_export->ex_path.mnt);
+ return status;
+ }
+
+diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
+index 1ff9062..145b3c8 100644
+--- a/fs/nfsd/nfs4recover.c
++++ b/fs/nfsd/nfs4recover.c
+@@ -46,6 +46,7 @@
+ #include <linux/scatterlist.h>
+ #include <linux/crypto.h>
+ #include <linux/sched.h>
++#include <linux/mount.h>
+
+ #define NFSDDBG_FACILITY NFSDDBG_PROC
+
+@@ -154,7 +155,11 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
+ dprintk("NFSD: nfsd4_create_clid_dir: DIRECTORY EXISTS\n");
+ goto out_put;
+ }
++ status = mnt_want_write(rec_dir.path.mnt);
++ if (status)
++ goto out_put;
+ status = vfs_mkdir(rec_dir.path.dentry->d_inode, dentry, S_IRWXU);
++ mnt_drop_write(rec_dir.path.mnt);
+ out_put:
+ dput(dentry);
+ out_unlock:
+@@ -313,12 +318,17 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
+ if (!rec_dir_init || !clp->cl_firststate)
+ return;
+
++ status = mnt_want_write(rec_dir.path.mnt);
++ if (status)
++ goto out;
+ clp->cl_firststate = 0;
+ nfs4_save_user(&uid, &gid);
+ status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1);
+ nfs4_reset_user(uid, gid);
+ if (status == 0)
+ nfsd4_sync_rec_dir();
++ mnt_drop_write(rec_dir.path.mnt);
++out:
+ if (status)
+ printk("NFSD: Failed to remove expired client state directory"
+ " %.*s\n", HEXDIR_LEN, clp->cl_recdir);
+@@ -347,13 +357,17 @@ nfsd4_recdir_purge_old(void) {
+
+ if (!rec_dir_init)
+ return;
++ status = mnt_want_write(rec_dir.path.mnt);
++ if (status)
++ goto out;
+ status = nfsd4_list_rec_dir(rec_dir.path.dentry, purge_old);
+ if (status == 0)
+ nfsd4_sync_rec_dir();
++ mnt_drop_write(rec_dir.path.mnt);
++out:
+ if (status)
+ printk("nfsd4: failed to purge old clients from recovery"
+ " directory %s\n", rec_dir.path.dentry->d_name.name);
+- return;
+ }
+
+ static int
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index bcb97d8..8799b87 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -41,6 +41,7 @@
+ #include <linux/sunrpc/svc.h>
+ #include <linux/nfsd/nfsd.h>
+ #include <linux/nfsd/cache.h>
++#include <linux/file.h>
+ #include <linux/mount.h>
+ #include <linux/workqueue.h>
+ #include <linux/smp_lock.h>
+@@ -1239,7 +1240,7 @@ static inline void
+ nfs4_file_downgrade(struct file *filp, unsigned int share_access)
+ {
+ if (share_access & NFS4_SHARE_ACCESS_WRITE) {
+- put_write_access(filp->f_path.dentry->d_inode);
++ drop_file_write_access(filp);
+ filp->f_mode = (filp->f_mode | FMODE_READ) & ~FMODE_WRITE;
+ }
+ }
+@@ -1638,6 +1639,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
+ locks_init_lock(&fl);
+ fl.fl_lmops = &nfsd_lease_mng_ops;
+ fl.fl_flags = FL_LEASE;
++ fl.fl_type = flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK;
+ fl.fl_end = OFFSET_MAX;
+ fl.fl_owner = (fl_owner_t)dp;
+ fl.fl_file = stp->st_vfs_file;
+@@ -1646,8 +1648,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
+ /* vfs_setlease checks to see if delegation should be handed out.
+ * the lock_manager callbacks fl_mylease and fl_change are used
+ */
+- if ((status = vfs_setlease(stp->st_vfs_file,
+- flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK, &flp))) {
++ if ((status = vfs_setlease(stp->st_vfs_file, fl.fl_type, &flp))) {
+ dprintk("NFSD: setlease failed [%d], no delegation\n", status);
+ unhash_delegation(dp);
+ flag = NFS4_OPEN_DELEGATE_NONE;
+@@ -1762,10 +1763,6 @@ out:
+ return status;
+ }
+
+-static struct workqueue_struct *laundry_wq;
+-static void laundromat_main(struct work_struct *);
+-static DECLARE_DELAYED_WORK(laundromat_work, laundromat_main);
+-
+ __be32
+ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ clientid_t *clid)
+@@ -1873,7 +1870,11 @@ nfs4_laundromat(void)
+ return clientid_val;
+ }
+
+-void
++static struct workqueue_struct *laundry_wq;
++static void laundromat_main(struct work_struct *);
++static DECLARE_DELAYED_WORK(laundromat_work, laundromat_main);
++
++static void
+ laundromat_main(struct work_struct *not_used)
+ {
+ time_t t;
+@@ -1974,6 +1975,26 @@ io_during_grace_disallowed(struct inode *inode, int flags)
+ && mandatory_lock(inode);
+ }
+
++static int check_stateid_generation(stateid_t *in, stateid_t *ref)
++{
++ /* If the client sends us a stateid from the future, it's buggy: */
++ if (in->si_generation > ref->si_generation)
++ return nfserr_bad_stateid;
++ /*
++ * The following, however, can happen. For example, if the
++ * client sends an open and some IO at the same time, the open
++ * may bump si_generation while the IO is still in flight.
++ * Thanks to hard links and renames, the client never knows what
++ * file an open will affect. So it could avoid that situation
++ * only by serializing all opens and IO from the same open
++ * owner. To recover from the old_stateid error, the client
++ * will just have to retry the IO:
++ */
++ if (in->si_generation < ref->si_generation)
++ return nfserr_old_stateid;
++ return nfs_ok;
++}
++
+ /*
+ * Checks for stateid operations
+ */
+@@ -2022,12 +2043,8 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ goto out;
+ stidp = &stp->st_stateid;
+ }
+- if (stateid->si_generation > stidp->si_generation)
+- goto out;
+-
+- /* OLD STATEID */
+- status = nfserr_old_stateid;
+- if (stateid->si_generation < stidp->si_generation)
++ status = check_stateid_generation(stateid, stidp);
++ if (status)
+ goto out;
+ if (stp) {
+ if ((status = nfs4_check_openmode(stp,flags)))
+@@ -2035,7 +2052,7 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
+ renew_client(stp->st_stateowner->so_client);
+ if (filpp)
+ *filpp = stp->st_vfs_file;
+- } else if (dp) {
++ } else {
+ if ((status = nfs4_check_delegmode(dp, flags)))
+ goto out;
+ renew_client(dp->dl_client);
+@@ -2064,6 +2081,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+ {
+ struct nfs4_stateid *stp;
+ struct nfs4_stateowner *sop;
++ __be32 status;
+
+ dprintk("NFSD: preprocess_seqid_op: seqid=%d "
+ "stateid = (%08x/%08x/%08x/%08x)\n", seqid,
+@@ -2126,7 +2144,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+ }
+ }
+
+- if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {
++ if (nfs4_check_fh(current_fh, stp)) {
+ dprintk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n");
+ return nfserr_bad_stateid;
+ }
+@@ -2149,15 +2167,9 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
+ " confirmed yet!\n");
+ return nfserr_bad_stateid;
+ }
+- if (stateid->si_generation > stp->st_stateid.si_generation) {
+- dprintk("NFSD: preprocess_seqid_op: future stateid?!\n");
+- return nfserr_bad_stateid;
+- }
+-
+- if (stateid->si_generation < stp->st_stateid.si_generation) {
+- dprintk("NFSD: preprocess_seqid_op: old stateid!\n");
+- return nfserr_old_stateid;
+- }
++ status = check_stateid_generation(stateid, &stp->st_stateid);
++ if (status)
++ return status;
+ renew_client(sop->so_client);
+ return nfs_ok;
+
+@@ -2193,7 +2205,7 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+
+ if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+ oc->oc_seqid, &oc->oc_req_stateid,
+- CHECK_FH | CONFIRM | OPEN_STATE,
++ CONFIRM | OPEN_STATE,
+ &oc->oc_stateowner, &stp, NULL)))
+ goto out;
+
+@@ -2264,7 +2276,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
+ if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+ od->od_seqid,
+ &od->od_stateid,
+- CHECK_FH | OPEN_STATE,
++ OPEN_STATE,
+ &od->od_stateowner, &stp, NULL)))
+ goto out;
+
+@@ -2317,7 +2329,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+ close->cl_seqid,
+ &close->cl_stateid,
+- CHECK_FH | OPEN_STATE | CLOSE_STATE,
++ OPEN_STATE | CLOSE_STATE,
+ &close->cl_stateowner, &stp, NULL)))
+ goto out;
+ status = nfs_ok;
+@@ -2622,7 +2634,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+ lock->lk_new_open_seqid,
+ &lock->lk_new_open_stateid,
+- CHECK_FH | OPEN_STATE,
++ OPEN_STATE,
+ &lock->lk_replay_owner, &open_stp,
+ lock);
+ if (status)
+@@ -2649,7 +2661,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+ lock->lk_old_lock_seqid,
+ &lock->lk_old_lock_stateid,
+- CHECK_FH | LOCK_STATE,
++ LOCK_STATE,
+ &lock->lk_replay_owner, &lock_stp, lock);
+ if (status)
+ goto out;
+@@ -2700,9 +2712,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ * Note: locks.c uses the BKL to protect the inode's lock list.
+ */
+
+- /* XXX?: Just to divert the locks_release_private at the start of
+- * locks_copy_lock: */
+- locks_init_lock(&conflock);
+ err = vfs_lock_file(filp, cmd, &file_lock, &conflock);
+ switch (-err) {
+ case 0: /* success! */
+@@ -2846,7 +2855,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+ if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+ locku->lu_seqid,
+ &locku->lu_stateid,
+- CHECK_FH | LOCK_STATE,
++ LOCK_STATE,
+ &locku->lu_stateowner, &stp, NULL)))
+ goto out;
+
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index 0e6a179..c513bbd 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -376,20 +376,6 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia
+ goto xdr_error;
+ }
+ }
+- if (bmval[1] & FATTR4_WORD1_TIME_METADATA) {
+- /* We require the high 32 bits of 'seconds' to be 0, and we ignore
+- all 32 bits of 'nseconds'. */
+- READ_BUF(12);
+- len += 12;
+- READ32(dummy32);
+- if (dummy32)
+- return nfserr_inval;
+- READ32(iattr->ia_ctime.tv_sec);
+- READ32(iattr->ia_ctime.tv_nsec);
+- if (iattr->ia_ctime.tv_nsec >= (u32)1000000000)
+- return nfserr_inval;
+- iattr->ia_valid |= ATTR_CTIME;
+- }
+ if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
+ READ_BUF(4);
+ len += 4;
+@@ -1867,6 +1853,15 @@ out_serverfault:
+ goto out;
+ }
+
++static inline int attributes_need_mount(u32 *bmval)
++{
++ if (bmval[0] & ~(FATTR4_WORD0_RDATTR_ERROR | FATTR4_WORD0_LEASE_TIME))
++ return 1;
++ if (bmval[1] & ~FATTR4_WORD1_MOUNTED_ON_FILEID)
++ return 1;
++ return 0;
++}
++
+ static __be32
+ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
+ const char *name, int namlen, __be32 *p, int *buflen)
+@@ -1888,9 +1883,7 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
+ * we will not follow the cross mount and will fill the attribtutes
+ * directly from the mountpoint dentry.
+ */
+- if (d_mountpoint(dentry) &&
+- (cd->rd_bmval[0] & ~FATTR4_WORD0_RDATTR_ERROR) == 0 &&
+- (cd->rd_bmval[1] & ~FATTR4_WORD1_MOUNTED_ON_FILEID) == 0)
++ if (d_mountpoint(dentry) && !attributes_need_mount(cd->rd_bmval))
+ ignore_crossmnt = 1;
+ else if (d_mountpoint(dentry)) {
+ int err;
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index 8516137..42f3820 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -22,6 +22,7 @@
+ #include <linux/seq_file.h>
+ #include <linux/pagemap.h>
+ #include <linux/init.h>
++#include <linux/inet.h>
+ #include <linux/string.h>
+ #include <linux/smp_lock.h>
+ #include <linux/ctype.h>
+@@ -35,8 +36,10 @@
+ #include <linux/nfsd/cache.h>
+ #include <linux/nfsd/xdr.h>
+ #include <linux/nfsd/syscall.h>
++#include <linux/lockd/lockd.h>
+
+ #include <asm/uaccess.h>
++#include <net/ipv6.h>
+
+ /*
+ * We have a single directory with 9 nodes in it.
+@@ -52,6 +55,8 @@ enum {
+ NFSD_Getfs,
+ NFSD_List,
+ NFSD_Fh,
++ NFSD_FO_UnlockIP,
++ NFSD_FO_UnlockFS,
+ NFSD_Threads,
+ NFSD_Pool_Threads,
+ NFSD_Versions,
+@@ -88,6 +93,9 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
+ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
+ #endif
+
++static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size);
++static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size);
++
+ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
+ [NFSD_Svc] = write_svc,
+ [NFSD_Add] = write_add,
+@@ -97,6 +105,8 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
+ [NFSD_Getfd] = write_getfd,
+ [NFSD_Getfs] = write_getfs,
+ [NFSD_Fh] = write_filehandle,
++ [NFSD_FO_UnlockIP] = failover_unlock_ip,
++ [NFSD_FO_UnlockFS] = failover_unlock_fs,
+ [NFSD_Threads] = write_threads,
+ [NFSD_Pool_Threads] = write_pool_threads,
+ [NFSD_Versions] = write_versions,
+@@ -149,7 +159,6 @@ static const struct file_operations transaction_ops = {
+ .release = simple_transaction_release,
+ };
+
+-extern struct seq_operations nfs_exports_op;
+ static int exports_open(struct inode *inode, struct file *file)
+ {
+ return seq_open(file, &nfs_exports_op);
+@@ -222,6 +231,7 @@ static ssize_t write_getfs(struct file *file, char *buf, size_t size)
+ struct auth_domain *clp;
+ int err = 0;
+ struct knfsd_fh *res;
++ struct in6_addr in6;
+
+ if (size < sizeof(*data))
+ return -EINVAL;
+@@ -236,7 +246,11 @@ static ssize_t write_getfs(struct file *file, char *buf, size_t size)
+ res = (struct knfsd_fh*)buf;
+
+ exp_readlock();
+- if (!(clp = auth_unix_lookup(sin->sin_addr)))
++
++ ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
++
++ clp = auth_unix_lookup(&in6);
++ if (!clp)
+ err = -EPERM;
+ else {
+ err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen);
+@@ -257,6 +271,7 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
+ int err = 0;
+ struct knfsd_fh fh;
+ char *res;
++ struct in6_addr in6;
+
+ if (size < sizeof(*data))
+ return -EINVAL;
+@@ -271,7 +286,11 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
+ res = buf;
+ sin = (struct sockaddr_in *)&data->gd_addr;
+ exp_readlock();
+- if (!(clp = auth_unix_lookup(sin->sin_addr)))
++
++ ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
++
++ clp = auth_unix_lookup(&in6);
++ if (!clp)
+ err = -EPERM;
+ else {
+ err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE);
+@@ -288,6 +307,58 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
+ return err;
+ }
+
++static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size)
++{
++ __be32 server_ip;
++ char *fo_path, c;
++ int b1, b2, b3, b4;
++
++ /* sanity check */
++ if (size == 0)
++ return -EINVAL;
++
++ if (buf[size-1] != '\n')
++ return -EINVAL;
++
++ fo_path = buf;
++ if (qword_get(&buf, fo_path, size) < 0)
++ return -EINVAL;
++
++ /* get ipv4 address */
++ if (sscanf(fo_path, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4)
++ return -EINVAL;
++ server_ip = htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
++
++ return nlmsvc_unlock_all_by_ip(server_ip);
++}
++
++static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size)
++{
++ struct nameidata nd;
++ char *fo_path;
++ int error;
++
++ /* sanity check */
++ if (size == 0)
++ return -EINVAL;
++
++ if (buf[size-1] != '\n')
++ return -EINVAL;
++
++ fo_path = buf;
++ if (qword_get(&buf, fo_path, size) < 0)
++ return -EINVAL;
++
++ error = path_lookup(fo_path, 0, &nd);
++ if (error)
++ return error;
++
++ error = nlmsvc_unlock_all_by_sb(nd.path.mnt->mnt_sb);
++
++ path_put(&nd.path);
++ return error;
++}
++
+ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
+ {
+ /* request is:
+@@ -347,8 +418,6 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
+ return mesg - buf;
+ }
+
+-extern int nfsd_nrthreads(void);
+-
+ static ssize_t write_threads(struct file *file, char *buf, size_t size)
+ {
+ /* if size > 0, look for a number of threads and call nfsd_svc
+@@ -371,10 +440,6 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
+ return strlen(buf);
+ }
+
+-extern int nfsd_nrpools(void);
+-extern int nfsd_get_nrthreads(int n, int *);
+-extern int nfsd_set_nrthreads(int n, int *);
+-
+ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
+ {
+ /* if size > 0, look for an array of number of threads per node
+@@ -696,6 +761,10 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
+ [NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR},
+ [NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR},
+ [NFSD_List] = {"exports", &exports_operations, S_IRUGO},
++ [NFSD_FO_UnlockIP] = {"unlock_ip",
++ &transaction_ops, S_IWUSR|S_IRUSR},
++ [NFSD_FO_UnlockFS] = {"unlock_filesystem",
++ &transaction_ops, S_IWUSR|S_IRUSR},
+ [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
+ [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
+ [NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR},
+diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
+index 3e6b3f4..100ae56 100644
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -113,6 +113,124 @@ static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
+ }
+
+ /*
++ * Use the given filehandle to look up the corresponding export and
++ * dentry. On success, the results are used to set fh_export and
++ * fh_dentry.
++ */
++static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
++{
++ struct knfsd_fh *fh = &fhp->fh_handle;
++ struct fid *fid = NULL, sfid;
++ struct svc_export *exp;
++ struct dentry *dentry;
++ int fileid_type;
++ int data_left = fh->fh_size/4;
++ __be32 error;
++
++ error = nfserr_stale;
++ if (rqstp->rq_vers > 2)
++ error = nfserr_badhandle;
++ if (rqstp->rq_vers == 4 && fh->fh_size == 0)
++ return nfserr_nofilehandle;
++
++ if (fh->fh_version == 1) {
++ int len;
++
++ if (--data_left < 0)
++ return error;
++ if (fh->fh_auth_type != 0)
++ return error;
++ len = key_len(fh->fh_fsid_type) / 4;
++ if (len == 0)
++ return error;
++ if (fh->fh_fsid_type == FSID_MAJOR_MINOR) {
++ /* deprecated, convert to type 3 */
++ len = key_len(FSID_ENCODE_DEV)/4;
++ fh->fh_fsid_type = FSID_ENCODE_DEV;
++ fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl(fh->fh_fsid[0]), ntohl(fh->fh_fsid[1])));
++ fh->fh_fsid[1] = fh->fh_fsid[2];
++ }
++ data_left -= len;
++ if (data_left < 0)
++ return error;
++ exp = rqst_exp_find(rqstp, fh->fh_fsid_type, fh->fh_auth);
++ fid = (struct fid *)(fh->fh_auth + len);
++ } else {
++ __u32 tfh[2];
++ dev_t xdev;
++ ino_t xino;
++
++ if (fh->fh_size != NFS_FHSIZE)
++ return error;
++ /* assume old filehandle format */
++ xdev = old_decode_dev(fh->ofh_xdev);
++ xino = u32_to_ino_t(fh->ofh_xino);
++ mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL);
++ exp = rqst_exp_find(rqstp, FSID_DEV, tfh);
++ }
++
++ error = nfserr_stale;
++ if (PTR_ERR(exp) == -ENOENT)
++ return error;
++
++ if (IS_ERR(exp))
++ return nfserrno(PTR_ERR(exp));
++
++ error = nfsd_setuser_and_check_port(rqstp, exp);
++ if (error)
++ goto out;
++
++ /*
++ * Look up the dentry using the NFS file handle.
++ */
++ error = nfserr_stale;
++ if (rqstp->rq_vers > 2)
++ error = nfserr_badhandle;
++
++ if (fh->fh_version != 1) {
++ sfid.i32.ino = fh->ofh_ino;
++ sfid.i32.gen = fh->ofh_generation;
++ sfid.i32.parent_ino = fh->ofh_dirino;
++ fid = &sfid;
++ data_left = 3;
++ if (fh->ofh_dirino == 0)
++ fileid_type = FILEID_INO32_GEN;
++ else
++ fileid_type = FILEID_INO32_GEN_PARENT;
++ } else
++ fileid_type = fh->fh_fileid_type;
++
++ if (fileid_type == FILEID_ROOT)
++ dentry = dget(exp->ex_path.dentry);
++ else {
++ dentry = exportfs_decode_fh(exp->ex_path.mnt, fid,
++ data_left, fileid_type,
++ nfsd_acceptable, exp);
++ }
++ if (dentry == NULL)
++ goto out;
++ if (IS_ERR(dentry)) {
++ if (PTR_ERR(dentry) != -EINVAL)
++ error = nfserrno(PTR_ERR(dentry));
++ goto out;
++ }
++
++ if (S_ISDIR(dentry->d_inode->i_mode) &&
++ (dentry->d_flags & DCACHE_DISCONNECTED)) {
++ printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n",
++ dentry->d_parent->d_name.name, dentry->d_name.name);
++ }
++
++ fhp->fh_dentry = dentry;
++ fhp->fh_export = exp;
++ nfsd_nr_verified++;
++ return 0;
++out:
++ exp_put(exp);
++ return error;
++}
++
++/*
+ * Perform sanity checks on the dentry in a client's file handle.
+ *
+ * Note that the file handle dentry may need to be freed even after
+@@ -124,115 +242,18 @@ static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
+ __be32
+ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
+ {
+- struct knfsd_fh *fh = &fhp->fh_handle;
+- struct svc_export *exp = NULL;
++ struct svc_export *exp;
+ struct dentry *dentry;
+- __be32 error = 0;
++ __be32 error;
+
+ dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
+
+ if (!fhp->fh_dentry) {
+- struct fid *fid = NULL, sfid;
+- int fileid_type;
+- int data_left = fh->fh_size/4;
+-
+- error = nfserr_stale;
+- if (rqstp->rq_vers > 2)
+- error = nfserr_badhandle;
+- if (rqstp->rq_vers == 4 && fh->fh_size == 0)
+- return nfserr_nofilehandle;
+-
+- if (fh->fh_version == 1) {
+- int len;
+- if (--data_left<0) goto out;
+- switch (fh->fh_auth_type) {
+- case 0: break;
+- default: goto out;
+- }
+- len = key_len(fh->fh_fsid_type) / 4;
+- if (len == 0) goto out;
+- if (fh->fh_fsid_type == FSID_MAJOR_MINOR) {
+- /* deprecated, convert to type 3 */
+- len = key_len(FSID_ENCODE_DEV)/4;
+- fh->fh_fsid_type = FSID_ENCODE_DEV;
+- fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl(fh->fh_fsid[0]), ntohl(fh->fh_fsid[1])));
+- fh->fh_fsid[1] = fh->fh_fsid[2];
+- }
+- if ((data_left -= len)<0) goto out;
+- exp = rqst_exp_find(rqstp, fh->fh_fsid_type,
+- fh->fh_auth);
+- fid = (struct fid *)(fh->fh_auth + len);
+- } else {
+- __u32 tfh[2];
+- dev_t xdev;
+- ino_t xino;
+- if (fh->fh_size != NFS_FHSIZE)
+- goto out;
+- /* assume old filehandle format */
+- xdev = old_decode_dev(fh->ofh_xdev);
+- xino = u32_to_ino_t(fh->ofh_xino);
+- mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL);
+- exp = rqst_exp_find(rqstp, FSID_DEV, tfh);
+- }
+-
+- error = nfserr_stale;
+- if (PTR_ERR(exp) == -ENOENT)
+- goto out;
+-
+- if (IS_ERR(exp)) {
+- error = nfserrno(PTR_ERR(exp));
+- goto out;
+- }
+-
+- error = nfsd_setuser_and_check_port(rqstp, exp);
++ error = nfsd_set_fh_dentry(rqstp, fhp);
+ if (error)
+ goto out;
+-
+- /*
+- * Look up the dentry using the NFS file handle.
+- */
+- error = nfserr_stale;
+- if (rqstp->rq_vers > 2)
+- error = nfserr_badhandle;
+-
+- if (fh->fh_version != 1) {
+- sfid.i32.ino = fh->ofh_ino;
+- sfid.i32.gen = fh->ofh_generation;
+- sfid.i32.parent_ino = fh->ofh_dirino;
+- fid = &sfid;
+- data_left = 3;
+- if (fh->ofh_dirino == 0)
+- fileid_type = FILEID_INO32_GEN;
+- else
+- fileid_type = FILEID_INO32_GEN_PARENT;
+- } else
+- fileid_type = fh->fh_fileid_type;
+-
+- if (fileid_type == FILEID_ROOT)
+- dentry = dget(exp->ex_path.dentry);
+- else {
+- dentry = exportfs_decode_fh(exp->ex_path.mnt, fid,
+- data_left, fileid_type,
+- nfsd_acceptable, exp);
+- }
+- if (dentry == NULL)
+- goto out;
+- if (IS_ERR(dentry)) {
+- if (PTR_ERR(dentry) != -EINVAL)
+- error = nfserrno(PTR_ERR(dentry));
+- goto out;
+- }
+-
+- if (S_ISDIR(dentry->d_inode->i_mode) &&
+- (dentry->d_flags & DCACHE_DISCONNECTED)) {
+- printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n",
+- dentry->d_parent->d_name.name, dentry->d_name.name);
+- }
+-
+- fhp->fh_dentry = dentry;
+- fhp->fh_export = exp;
+- nfsd_nr_verified++;
+- cache_get(&exp->h);
++ dentry = fhp->fh_dentry;
++ exp = fhp->fh_export;
+ } else {
+ /*
+ * just rechecking permissions
+@@ -242,7 +263,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
+ dprintk("nfsd: fh_verify - just checking\n");
+ dentry = fhp->fh_dentry;
+ exp = fhp->fh_export;
+- cache_get(&exp->h);
+ /*
+ * Set user creds for this exportpoint; necessary even
+ * in the "just checking" case because this may be a
+@@ -281,8 +301,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
+ access, ntohl(error));
+ }
+ out:
+- if (exp && !IS_ERR(exp))
+- exp_put(exp);
+ if (error == nfserr_stale)
+ nfsdstats.fh_stale++;
+ return error;
+diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
+index 9647b0f..941041f 100644
+--- a/fs/nfsd/nfssvc.c
++++ b/fs/nfsd/nfssvc.c
+@@ -244,7 +244,6 @@ static int nfsd_init_socks(int port)
+ if (error < 0)
+ return error;
+
+-#ifdef CONFIG_NFSD_TCP
+ error = lockd_up(IPPROTO_TCP);
+ if (error >= 0) {
+ error = svc_create_xprt(nfsd_serv, "tcp", port,
+@@ -254,7 +253,6 @@ static int nfsd_init_socks(int port)
+ }
+ if (error < 0)
+ return error;
+-#endif
+ return 0;
+ }
+
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index 46f59d5..a3a291f 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -264,7 +264,6 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
+ struct inode *inode;
+ int accmode = MAY_SATTR;
+ int ftype = 0;
+- int imode;
+ __be32 err;
+ int host_err;
+ int size_change = 0;
+@@ -360,25 +359,25 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
+ DQUOT_INIT(inode);
+ }
+
+- imode = inode->i_mode;
++ /* sanitize the mode change */
+ if (iap->ia_valid & ATTR_MODE) {
+ iap->ia_mode &= S_IALLUGO;
+- imode = iap->ia_mode |= (imode & ~S_IALLUGO);
+- /* if changing uid/gid revoke setuid/setgid in mode */
+- if ((iap->ia_valid & ATTR_UID) && iap->ia_uid != inode->i_uid) {
+- iap->ia_valid |= ATTR_KILL_PRIV;
++ iap->ia_mode |= (inode->i_mode & ~S_IALLUGO);
++ }
++
++ /* Revoke setuid/setgid on chown */
++ if (((iap->ia_valid & ATTR_UID) && iap->ia_uid != inode->i_uid) ||
++ ((iap->ia_valid & ATTR_GID) && iap->ia_gid != inode->i_gid)) {
++ iap->ia_valid |= ATTR_KILL_PRIV;
++ if (iap->ia_valid & ATTR_MODE) {
++ /* we're setting mode too, just clear the s*id bits */
+ iap->ia_mode &= ~S_ISUID;
++ if (iap->ia_mode & S_IXGRP)
++ iap->ia_mode &= ~S_ISGID;
++ } else {
++ /* set ATTR_KILL_* bits and let VFS handle it */
++ iap->ia_valid |= (ATTR_KILL_SUID | ATTR_KILL_SGID);
+ }
+- if ((iap->ia_valid & ATTR_GID) && iap->ia_gid != inode->i_gid)
+- iap->ia_mode &= ~S_ISGID;
+- } else {
+- /*
+- * Revoke setuid/setgid bit on chown/chgrp
+- */
+- if ((iap->ia_valid & ATTR_UID) && iap->ia_uid != inode->i_uid)
+- iap->ia_valid |= ATTR_KILL_SUID | ATTR_KILL_PRIV;
+- if ((iap->ia_valid & ATTR_GID) && iap->ia_gid != inode->i_gid)
+- iap->ia_valid |= ATTR_KILL_SGID;
+ }
+
+ /* Change the attributes. */
+@@ -988,7 +987,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+ * flushing the data to disk is handled separately below.
+ */
+
+- if (file->f_op->fsync == 0) {/* COMMIT3 cannot work */
++ if (!file->f_op->fsync) {/* COMMIT3 cannot work */
+ stable = 2;
+ *stablep = 2; /* FILE_SYNC */
+ }
+@@ -1152,7 +1151,7 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ }
+ #endif /* CONFIG_NFSD_V3 */
+
+-__be32
++static __be32
+ nfsd_create_setattr(struct svc_rqst *rqstp, struct svc_fh *resfhp,
+ struct iattr *iap)
+ {
+@@ -1255,23 +1254,35 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ err = 0;
+ switch (type) {
+ case S_IFREG:
++ host_err = mnt_want_write(fhp->fh_export->ex_path.mnt);
++ if (host_err)
++ goto out_nfserr;
+ host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
+ break;
+ case S_IFDIR:
++ host_err = mnt_want_write(fhp->fh_export->ex_path.mnt);
++ if (host_err)
++ goto out_nfserr;
+ host_err = vfs_mkdir(dirp, dchild, iap->ia_mode);
+ break;
+ case S_IFCHR:
+ case S_IFBLK:
+ case S_IFIFO:
+ case S_IFSOCK:
++ host_err = mnt_want_write(fhp->fh_export->ex_path.mnt);
++ if (host_err)
++ goto out_nfserr;
+ host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
+ break;
+ default:
+ printk("nfsd: bad file type %o in nfsd_create\n", type);
+ host_err = -EINVAL;
++ goto out_nfserr;
+ }
+- if (host_err < 0)
++ if (host_err < 0) {
++ mnt_drop_write(fhp->fh_export->ex_path.mnt);
+ goto out_nfserr;
++ }
+
+ if (EX_ISSYNC(fhp->fh_export)) {
+ err = nfserrno(nfsd_sync_dir(dentry));
+@@ -1282,6 +1293,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ err2 = nfsd_create_setattr(rqstp, resfhp, iap);
+ if (err2)
+ err = err2;
++ mnt_drop_write(fhp->fh_export->ex_path.mnt);
+ /*
+ * Update the file handle to get the new inode info.
+ */
+@@ -1359,6 +1371,9 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ v_atime = verifier[1]&0x7fffffff;
+ }
+
++ host_err = mnt_want_write(fhp->fh_export->ex_path.mnt);
++ if (host_err)
++ goto out_nfserr;
+ if (dchild->d_inode) {
+ err = 0;
+
+@@ -1390,12 +1405,15 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ case NFS3_CREATE_GUARDED:
+ err = nfserr_exist;
+ }
++ mnt_drop_write(fhp->fh_export->ex_path.mnt);
+ goto out;
+ }
+
+ host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
+- if (host_err < 0)
++ if (host_err < 0) {
++ mnt_drop_write(fhp->fh_export->ex_path.mnt);
+ goto out_nfserr;
++ }
+ if (created)
+ *created = 1;
+
+@@ -1420,6 +1438,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ if (err2)
+ err = err2;
+
++ mnt_drop_write(fhp->fh_export->ex_path.mnt);
+ /*
+ * Update the filehandle to get the new inode info.
+ */
+@@ -1522,6 +1541,10 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ if (iap && (iap->ia_valid & ATTR_MODE))
+ mode = iap->ia_mode & S_IALLUGO;
+
++ host_err = mnt_want_write(fhp->fh_export->ex_path.mnt);
++ if (host_err)
++ goto out_nfserr;
++
+ if (unlikely(path[plen] != 0)) {
+ char *path_alloced = kmalloc(plen+1, GFP_KERNEL);
+ if (path_alloced == NULL)
+@@ -1542,6 +1565,8 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ err = nfserrno(host_err);
+ fh_unlock(fhp);
+
++ mnt_drop_write(fhp->fh_export->ex_path.mnt);
++
+ cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp);
+ dput(dnew);
+ if (err==0) err = cerr;
+@@ -1592,6 +1617,11 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
+ dold = tfhp->fh_dentry;
+ dest = dold->d_inode;
+
++ host_err = mnt_want_write(tfhp->fh_export->ex_path.mnt);
++ if (host_err) {
++ err = nfserrno(host_err);
++ goto out_dput;
++ }
+ host_err = vfs_link(dold, dirp, dnew);
+ if (!host_err) {
+ if (EX_ISSYNC(ffhp->fh_export)) {
+@@ -1605,7 +1635,8 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
+ else
+ err = nfserrno(host_err);
+ }
+-
++ mnt_drop_write(tfhp->fh_export->ex_path.mnt);
++out_dput:
+ dput(dnew);
+ out_unlock:
+ fh_unlock(ffhp);
+@@ -1678,13 +1709,20 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
+ if (ndentry == trap)
+ goto out_dput_new;
+
+-#ifdef MSNFS
+- if ((ffhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
++ if (svc_msnfs(ffhp) &&
+ ((atomic_read(&odentry->d_count) > 1)
+ || (atomic_read(&ndentry->d_count) > 1))) {
+ host_err = -EPERM;
+- } else
+-#endif
++ goto out_dput_new;
++ }
++
++ host_err = -EXDEV;
++ if (ffhp->fh_export->ex_path.mnt != tfhp->fh_export->ex_path.mnt)
++ goto out_dput_new;
++ host_err = mnt_want_write(ffhp->fh_export->ex_path.mnt);
++ if (host_err)
++ goto out_dput_new;
++
+ host_err = vfs_rename(fdir, odentry, tdir, ndentry);
+ if (!host_err && EX_ISSYNC(tfhp->fh_export)) {
+ host_err = nfsd_sync_dir(tdentry);
+@@ -1692,6 +1730,8 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
+ host_err = nfsd_sync_dir(fdentry);
+ }
+
++ mnt_drop_write(ffhp->fh_export->ex_path.mnt);
++
+ out_dput_new:
+ dput(ndentry);
+ out_dput_old:
+@@ -1750,6 +1790,10 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
+ if (!type)
+ type = rdentry->d_inode->i_mode & S_IFMT;
+
++ host_err = mnt_want_write(fhp->fh_export->ex_path.mnt);
++ if (host_err)
++ goto out_nfserr;
++
+ if (type != S_IFDIR) { /* It's UNLINK */
+ #ifdef MSNFS
+ if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
+@@ -1765,10 +1809,12 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
+ dput(rdentry);
+
+ if (host_err)
+- goto out_nfserr;
++ goto out_drop;
+ if (EX_ISSYNC(fhp->fh_export))
+ host_err = nfsd_sync_dir(dentry);
+
++out_drop:
++ mnt_drop_write(fhp->fh_export->ex_path.mnt);
+ out_nfserr:
+ err = nfserrno(host_err);
+ out:
+@@ -1865,7 +1911,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
+ inode->i_mode,
+ IS_IMMUTABLE(inode)? " immut" : "",
+ IS_APPEND(inode)? " append" : "",
+- IS_RDONLY(inode)? " ro" : "");
++ __mnt_is_readonly(exp->ex_path.mnt)? " ro" : "");
+ dprintk(" owner %d/%d user %d/%d\n",
+ inode->i_uid, inode->i_gid, current->fsuid, current->fsgid);
+ #endif
+@@ -1876,7 +1922,8 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
+ */
+ if (!(acc & MAY_LOCAL_ACCESS))
+ if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) {
+- if (exp_rdonly(rqstp, exp) || IS_RDONLY(inode))
++ if (exp_rdonly(rqstp, exp) ||
++ __mnt_is_readonly(exp->ex_path.mnt))
+ return nfserr_rofs;
+ if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode))
+ return nfserr_perm;
+@@ -2039,6 +2086,9 @@ nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
+ } else
+ size = 0;
+
++ error = mnt_want_write(fhp->fh_export->ex_path.mnt);
++ if (error)
++ goto getout;
+ if (size)
+ error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0);
+ else {
+@@ -2050,6 +2100,7 @@ nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
+ error = 0;
+ }
+ }
++ mnt_drop_write(fhp->fh_export->ex_path.mnt);
+
+ getout:
+ kfree(value);
+diff --git a/fs/ocfs2/Makefile b/fs/ocfs2/Makefile
+index 4d4ce48..f6956de 100644
+--- a/fs/ocfs2/Makefile
++++ b/fs/ocfs2/Makefile
+@@ -2,7 +2,12 @@ EXTRA_CFLAGS += -Ifs/ocfs2
+
+ EXTRA_CFLAGS += -DCATCH_BH_JBD_RACES
+
+-obj-$(CONFIG_OCFS2_FS) += ocfs2.o
++obj-$(CONFIG_OCFS2_FS) += \
++ ocfs2.o \
++ ocfs2_stackglue.o
++
++obj-$(CONFIG_OCFS2_FS_O2CB) += ocfs2_stack_o2cb.o
++obj-$(CONFIG_OCFS2_FS_USERSPACE_CLUSTER) += ocfs2_stack_user.o
+
+ ocfs2-objs := \
+ alloc.o \
+@@ -31,5 +36,10 @@ ocfs2-objs := \
+ uptodate.o \
+ ver.o
+
++ocfs2_stackglue-objs := stackglue.o
++ocfs2_stack_o2cb-objs := stack_o2cb.o
++ocfs2_stack_user-objs := stack_user.o
++
++# cluster/ is always needed when OCFS2_FS for masklog support
+ obj-$(CONFIG_OCFS2_FS) += cluster/
+-obj-$(CONFIG_OCFS2_FS) += dlm/
++obj-$(CONFIG_OCFS2_FS_O2CB) += dlm/
+diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
+index 447206e..41f84c9 100644
+--- a/fs/ocfs2/alloc.c
++++ b/fs/ocfs2/alloc.c
+@@ -1029,8 +1029,7 @@ static void ocfs2_rotate_leaf(struct ocfs2_extent_list *el,
+ BUG_ON(!next_free);
+
+ /* The tree code before us didn't allow enough room in the leaf. */
+- if (el->l_next_free_rec == el->l_count && !has_empty)
+- BUG();
++ BUG_ON(el->l_next_free_rec == el->l_count && !has_empty);
+
+ /*
+ * The easiest way to approach this is to just remove the
+@@ -1450,6 +1449,8 @@ static void ocfs2_adjust_root_records(struct ocfs2_extent_list *root_el,
+ * - When our insert into the right path leaf is at the leftmost edge
+ * and requires an update of the path immediately to it's left. This
+ * can occur at the end of some types of rotation and appending inserts.
++ * - When we've adjusted the last extent record in the left path leaf and the
++ * 1st extent record in the right path leaf during cross extent block merge.
+ */
+ static void ocfs2_complete_edge_insert(struct inode *inode, handle_t *handle,
+ struct ocfs2_path *left_path,
+@@ -2712,24 +2713,147 @@ static void ocfs2_cleanup_merge(struct ocfs2_extent_list *el,
+ }
+ }
+
++static int ocfs2_get_right_path(struct inode *inode,
++ struct ocfs2_path *left_path,
++ struct ocfs2_path **ret_right_path)
++{
++ int ret;
++ u32 right_cpos;
++ struct ocfs2_path *right_path = NULL;
++ struct ocfs2_extent_list *left_el;
++
++ *ret_right_path = NULL;
++
++ /* This function shouldn't be called for non-trees. */
++ BUG_ON(left_path->p_tree_depth == 0);
++
++ left_el = path_leaf_el(left_path);
++ BUG_ON(left_el->l_next_free_rec != left_el->l_count);
++
++ ret = ocfs2_find_cpos_for_right_leaf(inode->i_sb, left_path,
++ &right_cpos);
++ if (ret) {
++ mlog_errno(ret);
++ goto out;
++ }
++
++ /* This function shouldn't be called for the rightmost leaf. */
++ BUG_ON(right_cpos == 0);
++
++ right_path = ocfs2_new_path(path_root_bh(left_path),
++ path_root_el(left_path));
++ if (!right_path) {
++ ret = -ENOMEM;
++ mlog_errno(ret);
++ goto out;
++ }
++
++ ret = ocfs2_find_path(inode, right_path, right_cpos);
++ if (ret) {
++ mlog_errno(ret);
++ goto out;
++ }
++
++ *ret_right_path = right_path;
++out:
++ if (ret)
++ ocfs2_free_path(right_path);
++ return ret;
++}
++
+ /*
+ * Remove split_rec clusters from the record at index and merge them
+- * onto the beginning of the record at index + 1.
++ * onto the beginning of the record "next" to it.
++ * For index < l_count - 1, the next means the extent rec at index + 1.
++ * For index == l_count - 1, the "next" means the 1st extent rec of the
++ * next extent block.
+ */
+-static int ocfs2_merge_rec_right(struct inode *inode, struct buffer_head *bh,
+- handle_t *handle,
+- struct ocfs2_extent_rec *split_rec,
+- struct ocfs2_extent_list *el, int index)
++static int ocfs2_merge_rec_right(struct inode *inode,
++ struct ocfs2_path *left_path,
++ handle_t *handle,
++ struct ocfs2_extent_rec *split_rec,
++ int index)
+ {
+- int ret;
++ int ret, next_free, i;
+ unsigned int split_clusters = le16_to_cpu(split_rec->e_leaf_clusters);
+ struct ocfs2_extent_rec *left_rec;
+ struct ocfs2_extent_rec *right_rec;
++ struct ocfs2_extent_list *right_el;
++ struct ocfs2_path *right_path = NULL;
++ int subtree_index = 0;
++ struct ocfs2_extent_list *el = path_leaf_el(left_path);
++ struct buffer_head *bh = path_leaf_bh(left_path);
++ struct buffer_head *root_bh = NULL;
+
+ BUG_ON(index >= le16_to_cpu(el->l_next_free_rec));
+-
+ left_rec = &el->l_recs[index];
+- right_rec = &el->l_recs[index + 1];
++
++ if (index == le16_to_cpu(el->l_next_free_rec - 1) &&
++ le16_to_cpu(el->l_next_free_rec) == le16_to_cpu(el->l_count)) {
++ /* we meet with a cross extent block merge. */
++ ret = ocfs2_get_right_path(inode, left_path, &right_path);
++ if (ret) {
++ mlog_errno(ret);
++ goto out;
++ }
++
++ right_el = path_leaf_el(right_path);
++ next_free = le16_to_cpu(right_el->l_next_free_rec);
++ BUG_ON(next_free <= 0);
++ right_rec = &right_el->l_recs[0];
++ if (ocfs2_is_empty_extent(right_rec)) {
++ BUG_ON(le16_to_cpu(next_free) <= 1);
++ right_rec = &right_el->l_recs[1];
++ }
++
++ BUG_ON(le32_to_cpu(left_rec->e_cpos) +
++ le16_to_cpu(left_rec->e_leaf_clusters) !=
++ le32_to_cpu(right_rec->e_cpos));
++
++ subtree_index = ocfs2_find_subtree_root(inode,
++ left_path, right_path);
++
++ ret = ocfs2_extend_rotate_transaction(handle, subtree_index,
++ handle->h_buffer_credits,
++ right_path);
++ if (ret) {
++ mlog_errno(ret);
++ goto out;
++ }
++
++ root_bh = left_path->p_node[subtree_index].bh;
++ BUG_ON(root_bh != right_path->p_node[subtree_index].bh);
++
++ ret = ocfs2_journal_access(handle, inode, root_bh,
++ OCFS2_JOURNAL_ACCESS_WRITE);
++ if (ret) {
++ mlog_errno(ret);
++ goto out;
++ }
++
++ for (i = subtree_index + 1;
++ i < path_num_items(right_path); i++) {
++ ret = ocfs2_journal_access(handle, inode,
++ right_path->p_node[i].bh,
++ OCFS2_JOURNAL_ACCESS_WRITE);
++ if (ret) {
++ mlog_errno(ret);
++ goto out;
++ }
++
++ ret = ocfs2_journal_access(handle, inode,
++ left_path->p_node[i].bh,
++ OCFS2_JOURNAL_ACCESS_WRITE);
++ if (ret) {
++ mlog_errno(ret);
++ goto out;
++ }
++ }
++
++ } else {
++ BUG_ON(index == le16_to_cpu(el->l_next_free_rec) - 1);
++ right_rec = &el->l_recs[index + 1];
++ }
+
+ ret = ocfs2_journal_access(handle, inode, bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+@@ -2751,30 +2875,156 @@ static int ocfs2_merge_rec_right(struct inode *inode, struct buffer_head *bh,
+ if (ret)
+ mlog_errno(ret);
+
++ if (right_path) {
++ ret = ocfs2_journal_dirty(handle, path_leaf_bh(right_path));
++ if (ret)
++ mlog_errno(ret);
++
++ ocfs2_complete_edge_insert(inode, handle, left_path,
++ right_path, subtree_index);
++ }
++out:
++ if (right_path)
++ ocfs2_free_path(right_path);
++ return ret;
++}
++
++static int ocfs2_get_left_path(struct inode *inode,
++ struct ocfs2_path *right_path,
++ struct ocfs2_path **ret_left_path)
++{
++ int ret;
++ u32 left_cpos;
++ struct ocfs2_path *left_path = NULL;
++
++ *ret_left_path = NULL;
++
++ /* This function shouldn't be called for non-trees. */
++ BUG_ON(right_path->p_tree_depth == 0);
++
++ ret = ocfs2_find_cpos_for_left_leaf(inode->i_sb,
++ right_path, &left_cpos);
++ if (ret) {
++ mlog_errno(ret);
++ goto out;
++ }
++
++ /* This function shouldn't be called for the leftmost leaf. */
++ BUG_ON(left_cpos == 0);
++
++ left_path = ocfs2_new_path(path_root_bh(right_path),
++ path_root_el(right_path));
++ if (!left_path) {
++ ret = -ENOMEM;
++ mlog_errno(ret);
++ goto out;
++ }
++
++ ret = ocfs2_find_path(inode, left_path, left_cpos);
++ if (ret) {
++ mlog_errno(ret);
++ goto out;
++ }
++
++ *ret_left_path = left_path;
+ out:
++ if (ret)
++ ocfs2_free_path(left_path);
+ return ret;
+ }
+
+ /*
+ * Remove split_rec clusters from the record at index and merge them
+- * onto the tail of the record at index - 1.
++ * onto the tail of the record "before" it.
++ * For index > 0, the "before" means the extent rec at index - 1.
++ *
++ * For index == 0, the "before" means the last record of the previous
++ * extent block. And there is also a situation that we may need to
++ * remove the rightmost leaf extent block in the right_path and change
++ * the right path to indicate the new rightmost path.
+ */
+-static int ocfs2_merge_rec_left(struct inode *inode, struct buffer_head *bh,
++static int ocfs2_merge_rec_left(struct inode *inode,
++ struct ocfs2_path *right_path,
+ handle_t *handle,
+ struct ocfs2_extent_rec *split_rec,
+- struct ocfs2_extent_list *el, int index)
++ struct ocfs2_cached_dealloc_ctxt *dealloc,
++ int index)
+ {
+- int ret, has_empty_extent = 0;
++ int ret, i, subtree_index = 0, has_empty_extent = 0;
+ unsigned int split_clusters = le16_to_cpu(split_rec->e_leaf_clusters);
+ struct ocfs2_extent_rec *left_rec;
+ struct ocfs2_extent_rec *right_rec;
++ struct ocfs2_extent_list *el = path_leaf_el(right_path);
++ struct buffer_head *bh = path_leaf_bh(right_path);
++ struct buffer_head *root_bh = NULL;
++ struct ocfs2_path *left_path = NULL;
++ struct ocfs2_extent_list *left_el;
+
+- BUG_ON(index <= 0);
++ BUG_ON(index < 0);
+
+- left_rec = &el->l_recs[index - 1];
+ right_rec = &el->l_recs[index];
+- if (ocfs2_is_empty_extent(&el->l_recs[0]))
+- has_empty_extent = 1;
++ if (index == 0) {
++ /* we meet with a cross extent block merge. */
++ ret = ocfs2_get_left_path(inode, right_path, &left_path);
++ if (ret) {
++ mlog_errno(ret);
++ goto out;
++ }
++
++ left_el = path_leaf_el(left_path);
++ BUG_ON(le16_to_cpu(left_el->l_next_free_rec) !=
++ le16_to_cpu(left_el->l_count));
++
++ left_rec = &left_el->l_recs[
++ le16_to_cpu(left_el->l_next_free_rec) - 1];
++ BUG_ON(le32_to_cpu(left_rec->e_cpos) +
++ le16_to_cpu(left_rec->e_leaf_clusters) !=
++ le32_to_cpu(split_rec->e_cpos));
++
++ subtree_index = ocfs2_find_subtree_root(inode,
++ left_path, right_path);
++
++ ret = ocfs2_extend_rotate_transaction(handle, subtree_index,
++ handle->h_buffer_credits,
++ left_path);
++ if (ret) {
++ mlog_errno(ret);
++ goto out;
++ }
++
++ root_bh = left_path->p_node[subtree_index].bh;
++ BUG_ON(root_bh != right_path->p_node[subtree_index].bh);
++
++ ret = ocfs2_journal_access(handle, inode, root_bh,
++ OCFS2_JOURNAL_ACCESS_WRITE);
++ if (ret) {
++ mlog_errno(ret);
++ goto out;
++ }
++
++ for (i = subtree_index + 1;
++ i < path_num_items(right_path); i++) {
++ ret = ocfs2_journal_access(handle, inode,
++ right_path->p_node[i].bh,
++ OCFS2_JOURNAL_ACCESS_WRITE);
++ if (ret) {
++ mlog_errno(ret);
++ goto out;
++ }
++
++ ret = ocfs2_journal_access(handle, inode,
++ left_path->p_node[i].bh,
++ OCFS2_JOURNAL_ACCESS_WRITE);
++ if (ret) {
++ mlog_errno(ret);
++ goto out;
++ }
++ }
++ } else {
++ left_rec = &el->l_recs[index - 1];
++ if (ocfs2_is_empty_extent(&el->l_recs[0]))
++ has_empty_extent = 1;
++ }
+
+ ret = ocfs2_journal_access(handle, inode, bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+@@ -2790,9 +3040,8 @@ static int ocfs2_merge_rec_left(struct inode *inode, struct buffer_head *bh,
+ *left_rec = *split_rec;
+
+ has_empty_extent = 0;
+- } else {
++ } else
+ le16_add_cpu(&left_rec->e_leaf_clusters, split_clusters);
+- }
+
+ le32_add_cpu(&right_rec->e_cpos, split_clusters);
+ le64_add_cpu(&right_rec->e_blkno,
+@@ -2805,13 +3054,44 @@ static int ocfs2_merge_rec_left(struct inode *inode, struct buffer_head *bh,
+ if (ret)
+ mlog_errno(ret);
+
++ if (left_path) {
++ ret = ocfs2_journal_dirty(handle, path_leaf_bh(left_path));
++ if (ret)
++ mlog_errno(ret);
++
++ /*
++ * In the situation that the right_rec is empty and the extent
++ * block is empty also, ocfs2_complete_edge_insert can't handle
++ * it and we need to delete the right extent block.
++ */
++ if (le16_to_cpu(right_rec->e_leaf_clusters) == 0 &&
++ le16_to_cpu(el->l_next_free_rec) == 1) {
++
++ ret = ocfs2_remove_rightmost_path(inode, handle,
++ right_path, dealloc);
++ if (ret) {
++ mlog_errno(ret);
++ goto out;
++ }
++
++ /* Now the rightmost extent block has been deleted.
++ * So we use the new rightmost path.
++ */
++ ocfs2_mv_path(right_path, left_path);
++ left_path = NULL;
++ } else
++ ocfs2_complete_edge_insert(inode, handle, left_path,
++ right_path, subtree_index);
++ }
+ out:
++ if (left_path)
++ ocfs2_free_path(left_path);
+ return ret;
+ }
+
+ static int ocfs2_try_to_merge_extent(struct inode *inode,
+ handle_t *handle,
+- struct ocfs2_path *left_path,
++ struct ocfs2_path *path,
+ int split_index,
+ struct ocfs2_extent_rec *split_rec,
+ struct ocfs2_cached_dealloc_ctxt *dealloc,
+@@ -2819,7 +3099,7 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
+
+ {
+ int ret = 0;
+- struct ocfs2_extent_list *el = path_leaf_el(left_path);
++ struct ocfs2_extent_list *el = path_leaf_el(path);
+ struct ocfs2_extent_rec *rec = &el->l_recs[split_index];
+
+ BUG_ON(ctxt->c_contig_type == CONTIG_NONE);
+@@ -2832,7 +3112,7 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
+ * extents - having more than one in a leaf is
+ * illegal.
+ */
+- ret = ocfs2_rotate_tree_left(inode, handle, left_path,
++ ret = ocfs2_rotate_tree_left(inode, handle, path,
+ dealloc);
+ if (ret) {
+ mlog_errno(ret);
+@@ -2847,7 +3127,6 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
+ * Left-right contig implies this.
+ */
+ BUG_ON(!ctxt->c_split_covers_rec);
+- BUG_ON(split_index == 0);
+
+ /*
+ * Since the leftright insert always covers the entire
+@@ -2858,9 +3137,14 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
+ * Since the adding of an empty extent shifts
+ * everything back to the right, there's no need to
+ * update split_index here.
++ *
++ * When the split_index is zero, we need to merge it to the
++ * prevoius extent block. It is more efficient and easier
++ * if we do merge_right first and merge_left later.
+ */
+- ret = ocfs2_merge_rec_left(inode, path_leaf_bh(left_path),
+- handle, split_rec, el, split_index);
++ ret = ocfs2_merge_rec_right(inode, path,
++ handle, split_rec,
++ split_index);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+@@ -2871,32 +3155,30 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
+ */
+ BUG_ON(!ocfs2_is_empty_extent(&el->l_recs[0]));
+
+- /*
+- * The left merge left us with an empty extent, remove
+- * it.
+- */
+- ret = ocfs2_rotate_tree_left(inode, handle, left_path, dealloc);
++ /* The merge left us with an empty extent, remove it. */
++ ret = ocfs2_rotate_tree_left(inode, handle, path, dealloc);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+- split_index--;
++
+ rec = &el->l_recs[split_index];
+
+ /*
+ * Note that we don't pass split_rec here on purpose -
+- * we've merged it into the left side.
++ * we've merged it into the rec already.
+ */
+- ret = ocfs2_merge_rec_right(inode, path_leaf_bh(left_path),
+- handle, rec, el, split_index);
++ ret = ocfs2_merge_rec_left(inode, path,
++ handle, rec,
++ dealloc,
++ split_index);
++
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+- BUG_ON(!ocfs2_is_empty_extent(&el->l_recs[0]));
+-
+- ret = ocfs2_rotate_tree_left(inode, handle, left_path,
++ ret = ocfs2_rotate_tree_left(inode, handle, path,
+ dealloc);
+ /*
+ * Error from this last rotate is not critical, so
+@@ -2915,8 +3197,9 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
+ */
+ if (ctxt->c_contig_type == CONTIG_RIGHT) {
+ ret = ocfs2_merge_rec_left(inode,
+- path_leaf_bh(left_path),
+- handle, split_rec, el,
++ path,
++ handle, split_rec,
++ dealloc,
+ split_index);
+ if (ret) {
+ mlog_errno(ret);
+@@ -2924,8 +3207,8 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
+ }
+ } else {
+ ret = ocfs2_merge_rec_right(inode,
+- path_leaf_bh(left_path),
+- handle, split_rec, el,
++ path,
++ handle, split_rec,
+ split_index);
+ if (ret) {
+ mlog_errno(ret);
+@@ -2938,7 +3221,7 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
+ * The merge may have left an empty extent in
+ * our leaf. Try to rotate it away.
+ */
+- ret = ocfs2_rotate_tree_left(inode, handle, left_path,
++ ret = ocfs2_rotate_tree_left(inode, handle, path,
+ dealloc);
+ if (ret)
+ mlog_errno(ret);
+@@ -3498,20 +3781,57 @@ out:
+ }
+
+ static enum ocfs2_contig_type
+-ocfs2_figure_merge_contig_type(struct inode *inode,
++ocfs2_figure_merge_contig_type(struct inode *inode, struct ocfs2_path *path,
+ struct ocfs2_extent_list *el, int index,
+ struct ocfs2_extent_rec *split_rec)
+ {
+- struct ocfs2_extent_rec *rec;
++ int status;
+ enum ocfs2_contig_type ret = CONTIG_NONE;
++ u32 left_cpos, right_cpos;
++ struct ocfs2_extent_rec *rec = NULL;
++ struct ocfs2_extent_list *new_el;
++ struct ocfs2_path *left_path = NULL, *right_path = NULL;
++ struct buffer_head *bh;
++ struct ocfs2_extent_block *eb;
++
++ if (index > 0) {
++ rec = &el->l_recs[index - 1];
++ } else if (path->p_tree_depth > 0) {
++ status = ocfs2_find_cpos_for_left_leaf(inode->i_sb,
++ path, &left_cpos);
++ if (status)
++ goto out;
++
++ if (left_cpos != 0) {
++ left_path = ocfs2_new_path(path_root_bh(path),
++ path_root_el(path));
++ if (!left_path)
++ goto out;
++
++ status = ocfs2_find_path(inode, left_path, left_cpos);
++ if (status)
++ goto out;
++
++ new_el = path_leaf_el(left_path);
++
++ if (le16_to_cpu(new_el->l_next_free_rec) !=
++ le16_to_cpu(new_el->l_count)) {
++ bh = path_leaf_bh(left_path);
++ eb = (struct ocfs2_extent_block *)bh->b_data;
++ OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb,
++ eb);
++ goto out;
++ }
++ rec = &new_el->l_recs[
++ le16_to_cpu(new_el->l_next_free_rec) - 1];
++ }
++ }
+
+ /*
+ * We're careful to check for an empty extent record here -
+ * the merge code will know what to do if it sees one.
+ */
+-
+- if (index > 0) {
+- rec = &el->l_recs[index - 1];
++ if (rec) {
+ if (index == 1 && ocfs2_is_empty_extent(rec)) {
+ if (split_rec->e_cpos == el->l_recs[index].e_cpos)
+ ret = CONTIG_RIGHT;
+@@ -3520,10 +3840,45 @@ ocfs2_figure_merge_contig_type(struct inode *inode,
+ }
+ }
+
+- if (index < (le16_to_cpu(el->l_next_free_rec) - 1)) {
++ rec = NULL;
++ if (index < (le16_to_cpu(el->l_next_free_rec) - 1))
++ rec = &el->l_recs[index + 1];
++ else if (le16_to_cpu(el->l_next_free_rec) == le16_to_cpu(el->l_count) &&
++ path->p_tree_depth > 0) {
++ status = ocfs2_find_cpos_for_right_leaf(inode->i_sb,
++ path, &right_cpos);
++ if (status)
++ goto out;
++
++ if (right_cpos == 0)
++ goto out;
++
++ right_path = ocfs2_new_path(path_root_bh(path),
++ path_root_el(path));
++ if (!right_path)
++ goto out;
++
++ status = ocfs2_find_path(inode, right_path, right_cpos);
++ if (status)
++ goto out;
++
++ new_el = path_leaf_el(right_path);
++ rec = &new_el->l_recs[0];
++ if (ocfs2_is_empty_extent(rec)) {
++ if (le16_to_cpu(new_el->l_next_free_rec) <= 1) {
++ bh = path_leaf_bh(right_path);
++ eb = (struct ocfs2_extent_block *)bh->b_data;
++ OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb,
++ eb);
++ goto out;
++ }
++ rec = &new_el->l_recs[1];
++ }
++ }
++
++ if (rec) {
+ enum ocfs2_contig_type contig_type;
+
+- rec = &el->l_recs[index + 1];
+ contig_type = ocfs2_extent_contig(inode, rec, split_rec);
+
+ if (contig_type == CONTIG_LEFT && ret == CONTIG_RIGHT)
+@@ -3532,6 +3887,12 @@ ocfs2_figure_merge_contig_type(struct inode *inode,
+ ret = contig_type;
+ }
+
++out:
++ if (left_path)
++ ocfs2_free_path(left_path);
++ if (right_path)
++ ocfs2_free_path(right_path);
++
+ return ret;
+ }
+
+@@ -3994,7 +4355,7 @@ static int __ocfs2_mark_extent_written(struct inode *inode,
+ goto out;
+ }
+
+- ctxt.c_contig_type = ocfs2_figure_merge_contig_type(inode, el,
++ ctxt.c_contig_type = ocfs2_figure_merge_contig_type(inode, path, el,
+ split_index,
+ split_rec);
+
+@@ -4788,6 +5149,8 @@ static void ocfs2_truncate_log_worker(struct work_struct *work)
+ status = ocfs2_flush_truncate_log(osb);
+ if (status < 0)
+ mlog_errno(status);
++ else
++ ocfs2_init_inode_steal_slot(osb);
+
+ mlog_exit(status);
+ }
+diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
+index 90383ed..17964c0 100644
+--- a/fs/ocfs2/aops.c
++++ b/fs/ocfs2/aops.c
+@@ -467,11 +467,11 @@ handle_t *ocfs2_start_walk_page_trans(struct inode *inode,
+ unsigned to)
+ {
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+- handle_t *handle = NULL;
++ handle_t *handle;
+ int ret = 0;
+
+ handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
+- if (!handle) {
++ if (IS_ERR(handle)) {
+ ret = -ENOMEM;
+ mlog_errno(ret);
+ goto out;
+@@ -487,7 +487,7 @@ handle_t *ocfs2_start_walk_page_trans(struct inode *inode,
+ }
+ out:
+ if (ret) {
+- if (handle)
++ if (!IS_ERR(handle))
+ ocfs2_commit_trans(osb, handle);
+ handle = ERR_PTR(ret);
+ }
+diff --git a/fs/ocfs2/cluster/Makefile b/fs/ocfs2/cluster/Makefile
+index cdd162f..bc8c5e7 100644
+--- a/fs/ocfs2/cluster/Makefile
++++ b/fs/ocfs2/cluster/Makefile
+@@ -1,4 +1,4 @@
+ obj-$(CONFIG_OCFS2_FS) += ocfs2_nodemanager.o
+
+ ocfs2_nodemanager-objs := heartbeat.o masklog.o sys.o nodemanager.o \
+- quorum.o tcp.o ver.o
++ quorum.o tcp.o netdebug.o ver.o
+diff --git a/fs/ocfs2/cluster/netdebug.c b/fs/ocfs2/cluster/netdebug.c
+new file mode 100644
+index 0000000..7bf3c0e
+--- /dev/null
++++ b/fs/ocfs2/cluster/netdebug.c
+@@ -0,0 +1,441 @@
++/* -*- mode: c; c-basic-offset: 8; -*-
++ * vim: noexpandtab sw=8 ts=8 sts=0:
++ *
++ * netdebug.c
++ *
++ * debug functionality for o2net
++ *
++ * Copyright (C) 2005, 2008 Oracle. 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 021110-1307, USA.
++ *
++ */
++
++#ifdef CONFIG_DEBUG_FS
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/slab.h>
++#include <linux/idr.h>
++#include <linux/kref.h>
++#include <linux/seq_file.h>
++#include <linux/debugfs.h>
++
++#include <linux/uaccess.h>
++
++#include "tcp.h"
++#include "nodemanager.h"
++#define MLOG_MASK_PREFIX ML_TCP
++#include "masklog.h"
++
++#include "tcp_internal.h"
++
++#define O2NET_DEBUG_DIR "o2net"
++#define SC_DEBUG_NAME "sock_containers"
++#define NST_DEBUG_NAME "send_tracking"
++
++static struct dentry *o2net_dentry;
++static struct dentry *sc_dentry;
++static struct dentry *nst_dentry;
++
++static DEFINE_SPINLOCK(o2net_debug_lock);
++
++static LIST_HEAD(sock_containers);
++static LIST_HEAD(send_tracking);
++
++void o2net_debug_add_nst(struct o2net_send_tracking *nst)
++{
++ spin_lock(&o2net_debug_lock);
++ list_add(&nst->st_net_debug_item, &send_tracking);
++ spin_unlock(&o2net_debug_lock);
++}
++
++void o2net_debug_del_nst(struct o2net_send_tracking *nst)
++{
++ spin_lock(&o2net_debug_lock);
++ if (!list_empty(&nst->st_net_debug_item))
++ list_del_init(&nst->st_net_debug_item);
++ spin_unlock(&o2net_debug_lock);
++}
++
++static struct o2net_send_tracking
++ *next_nst(struct o2net_send_tracking *nst_start)
++{
++ struct o2net_send_tracking *nst, *ret = NULL;
++
++ assert_spin_locked(&o2net_debug_lock);
++
++ list_for_each_entry(nst, &nst_start->st_net_debug_item,
++ st_net_debug_item) {
++ /* discover the head of the list */
++ if (&nst->st_net_debug_item == &send_tracking)
++ break;
++
++ /* use st_task to detect real nsts in the list */
++ if (nst->st_task != NULL) {
++ ret = nst;
++ break;
++ }
++ }
++
++ return ret;
++}
++
++static void *nst_seq_start(struct seq_file *seq, loff_t *pos)
++{
++ struct o2net_send_tracking *nst, *dummy_nst = seq->private;
++
++ spin_lock(&o2net_debug_lock);
++ nst = next_nst(dummy_nst);
++ spin_unlock(&o2net_debug_lock);
++
++ return nst;
++}
++
++static void *nst_seq_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++ struct o2net_send_tracking *nst, *dummy_nst = seq->private;
++
++ spin_lock(&o2net_debug_lock);
++ nst = next_nst(dummy_nst);
++ list_del_init(&dummy_nst->st_net_debug_item);
++ if (nst)
++ list_add(&dummy_nst->st_net_debug_item,
++ &nst->st_net_debug_item);
++ spin_unlock(&o2net_debug_lock);
++
++ return nst; /* unused, just needs to be null when done */
++}
++
++static int nst_seq_show(struct seq_file *seq, void *v)
++{
++ struct o2net_send_tracking *nst, *dummy_nst = seq->private;
++
++ spin_lock(&o2net_debug_lock);
++ nst = next_nst(dummy_nst);
++
++ if (nst != NULL) {
++ /* get_task_comm isn't exported. oh well. */
++ seq_printf(seq, "%p:\n"
++ " pid: %lu\n"
++ " tgid: %lu\n"
++ " process name: %s\n"
++ " node: %u\n"
++ " sc: %p\n"
++ " message id: %d\n"
++ " message type: %u\n"
++ " message key: 0x%08x\n"
++ " sock acquiry: %lu.%lu\n"
++ " send start: %lu.%lu\n"
++ " wait start: %lu.%lu\n",
++ nst, (unsigned long)nst->st_task->pid,
++ (unsigned long)nst->st_task->tgid,
++ nst->st_task->comm, nst->st_node,
++ nst->st_sc, nst->st_id, nst->st_msg_type,
++ nst->st_msg_key,
++ nst->st_sock_time.tv_sec, nst->st_sock_time.tv_usec,
++ nst->st_send_time.tv_sec, nst->st_send_time.tv_usec,
++ nst->st_status_time.tv_sec,
++ nst->st_status_time.tv_usec);
++ }
++
++ spin_unlock(&o2net_debug_lock);
++
++ return 0;
++}
++
++static void nst_seq_stop(struct seq_file *seq, void *v)
++{
++}
++
++static struct seq_operations nst_seq_ops = {
++ .start = nst_seq_start,
++ .next = nst_seq_next,
++ .stop = nst_seq_stop,
++ .show = nst_seq_show,
++};
++
++static int nst_fop_open(struct inode *inode, struct file *file)
++{
++ struct o2net_send_tracking *dummy_nst;
++ struct seq_file *seq;
++ int ret;
++
++ dummy_nst = kmalloc(sizeof(struct o2net_send_tracking), GFP_KERNEL);
++ if (dummy_nst == NULL) {
++ ret = -ENOMEM;
++ goto out;
++ }
++ dummy_nst->st_task = NULL;
++
++ ret = seq_open(file, &nst_seq_ops);
++ if (ret)
++ goto out;
++
++ seq = file->private_data;
++ seq->private = dummy_nst;
++ o2net_debug_add_nst(dummy_nst);
++
++ dummy_nst = NULL;
++
++out:
++ kfree(dummy_nst);
++ return ret;
++}
++
++static int nst_fop_release(struct inode *inode, struct file *file)
++{
++ struct seq_file *seq = file->private_data;
++ struct o2net_send_tracking *dummy_nst = seq->private;
++
++ o2net_debug_del_nst(dummy_nst);
++ return seq_release_private(inode, file);
++}
++
++static struct file_operations nst_seq_fops = {
++ .open = nst_fop_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = nst_fop_release,
++};
++
++void o2net_debug_add_sc(struct o2net_sock_container *sc)
++{
++ spin_lock(&o2net_debug_lock);
++ list_add(&sc->sc_net_debug_item, &sock_containers);
++ spin_unlock(&o2net_debug_lock);
++}
++
++void o2net_debug_del_sc(struct o2net_sock_container *sc)
++{
++ spin_lock(&o2net_debug_lock);
++ list_del_init(&sc->sc_net_debug_item);
++ spin_unlock(&o2net_debug_lock);
++}
++
++static struct o2net_sock_container
++ *next_sc(struct o2net_sock_container *sc_start)
++{
++ struct o2net_sock_container *sc, *ret = NULL;
++
++ assert_spin_locked(&o2net_debug_lock);
++
++ list_for_each_entry(sc, &sc_start->sc_net_debug_item,
++ sc_net_debug_item) {
++ /* discover the head of the list miscast as a sc */
++ if (&sc->sc_net_debug_item == &sock_containers)
++ break;
++
++ /* use sc_page to detect real scs in the list */
++ if (sc->sc_page != NULL) {
++ ret = sc;
++ break;
++ }
++ }
++
++ return ret;
++}
++
++static void *sc_seq_start(struct seq_file *seq, loff_t *pos)
++{
++ struct o2net_sock_container *sc, *dummy_sc = seq->private;
++
++ spin_lock(&o2net_debug_lock);
++ sc = next_sc(dummy_sc);
++ spin_unlock(&o2net_debug_lock);
++
++ return sc;
++}
++
++static void *sc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++ struct o2net_sock_container *sc, *dummy_sc = seq->private;
++
++ spin_lock(&o2net_debug_lock);
++ sc = next_sc(dummy_sc);
++ list_del_init(&dummy_sc->sc_net_debug_item);
++ if (sc)
++ list_add(&dummy_sc->sc_net_debug_item, &sc->sc_net_debug_item);
++ spin_unlock(&o2net_debug_lock);
++
++ return sc; /* unused, just needs to be null when done */
++}
++
++#define TV_SEC_USEC(TV) TV.tv_sec, TV.tv_usec
++
++static int sc_seq_show(struct seq_file *seq, void *v)
++{
++ struct o2net_sock_container *sc, *dummy_sc = seq->private;
++
++ spin_lock(&o2net_debug_lock);
++ sc = next_sc(dummy_sc);
++
++ if (sc != NULL) {
++ struct inet_sock *inet = NULL;
++
++ __be32 saddr = 0, daddr = 0;
++ __be16 sport = 0, dport = 0;
++
++ if (sc->sc_sock) {
++ inet = inet_sk(sc->sc_sock->sk);
++ /* the stack's structs aren't sparse endian clean */
++ saddr = (__force __be32)inet->saddr;
++ daddr = (__force __be32)inet->daddr;
++ sport = (__force __be16)inet->sport;
++ dport = (__force __be16)inet->dport;
++ }
++
++ /* XXX sigh, inet-> doesn't have sparse annotation so any
++ * use of it here generates a warning with -Wbitwise */
++ seq_printf(seq, "%p:\n"
++ " krefs: %d\n"
++ " sock: %u.%u.%u.%u:%u -> "
++ "%u.%u.%u.%u:%u\n"
++ " remote node: %s\n"
++ " page off: %zu\n"
++ " handshake ok: %u\n"
++ " timer: %lu.%lu\n"
++ " data ready: %lu.%lu\n"
++ " advance start: %lu.%lu\n"
++ " advance stop: %lu.%lu\n"
++ " func start: %lu.%lu\n"
++ " func stop: %lu.%lu\n"
++ " func key: %u\n"
++ " func type: %u\n",
++ sc,
++ atomic_read(&sc->sc_kref.refcount),
++ NIPQUAD(saddr), inet ? ntohs(sport) : 0,
++ NIPQUAD(daddr), inet ? ntohs(dport) : 0,
++ sc->sc_node->nd_name,
++ sc->sc_page_off,
++ sc->sc_handshake_ok,
++ TV_SEC_USEC(sc->sc_tv_timer),
++ TV_SEC_USEC(sc->sc_tv_data_ready),
++ TV_SEC_USEC(sc->sc_tv_advance_start),
++ TV_SEC_USEC(sc->sc_tv_advance_stop),
++ TV_SEC_USEC(sc->sc_tv_func_start),
++ TV_SEC_USEC(sc->sc_tv_func_stop),
++ sc->sc_msg_key,
++ sc->sc_msg_type);
++ }
++
++
++ spin_unlock(&o2net_debug_lock);
++
++ return 0;
++}
++
++static void sc_seq_stop(struct seq_file *seq, void *v)
++{
++}
++
++static struct seq_operations sc_seq_ops = {
++ .start = sc_seq_start,
++ .next = sc_seq_next,
++ .stop = sc_seq_stop,
++ .show = sc_seq_show,
++};
++
++static int sc_fop_open(struct inode *inode, struct file *file)
++{
++ struct o2net_sock_container *dummy_sc;
++ struct seq_file *seq;
++ int ret;
++
++ dummy_sc = kmalloc(sizeof(struct o2net_sock_container), GFP_KERNEL);
++ if (dummy_sc == NULL) {
++ ret = -ENOMEM;
++ goto out;
++ }
++ dummy_sc->sc_page = NULL;
++
++ ret = seq_open(file, &sc_seq_ops);
++ if (ret)
++ goto out;
++
++ seq = file->private_data;
++ seq->private = dummy_sc;
++ o2net_debug_add_sc(dummy_sc);
++
++ dummy_sc = NULL;
++
++out:
++ kfree(dummy_sc);
++ return ret;
++}
++
++static int sc_fop_release(struct inode *inode, struct file *file)
++{
++ struct seq_file *seq = file->private_data;
++ struct o2net_sock_container *dummy_sc = seq->private;
++
++ o2net_debug_del_sc(dummy_sc);
++ return seq_release_private(inode, file);
++}
++
++static struct file_operations sc_seq_fops = {
++ .open = sc_fop_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = sc_fop_release,
++};
++
++int o2net_debugfs_init(void)
++{
++ o2net_dentry = debugfs_create_dir(O2NET_DEBUG_DIR, NULL);
++ if (!o2net_dentry) {
++ mlog_errno(-ENOMEM);
++ goto bail;
++ }
++
++ nst_dentry = debugfs_create_file(NST_DEBUG_NAME, S_IFREG|S_IRUSR,
++ o2net_dentry, NULL,
++ &nst_seq_fops);
++ if (!nst_dentry) {
++ mlog_errno(-ENOMEM);
++ goto bail;
++ }
++
++ sc_dentry = debugfs_create_file(SC_DEBUG_NAME, S_IFREG|S_IRUSR,
++ o2net_dentry, NULL,
++ &sc_seq_fops);
++ if (!sc_dentry) {
++ mlog_errno(-ENOMEM);
++ goto bail;
++ }
++
++ return 0;
++bail:
++ if (sc_dentry)
++ debugfs_remove(sc_dentry);
++ if (nst_dentry)
++ debugfs_remove(nst_dentry);
++ if (o2net_dentry)
++ debugfs_remove(o2net_dentry);
++ return -ENOMEM;
++}
++
++void o2net_debugfs_exit(void)
++{
++ if (sc_dentry)
++ debugfs_remove(sc_dentry);
++ if (nst_dentry)
++ debugfs_remove(nst_dentry);
++ if (o2net_dentry)
++ debugfs_remove(o2net_dentry);
++}
++
++#endif /* CONFIG_DEBUG_FS */
+diff --git a/fs/ocfs2/cluster/nodemanager.c b/fs/ocfs2/cluster/nodemanager.c
+index 709fba2..cf9401e 100644
+--- a/fs/ocfs2/cluster/nodemanager.c
++++ b/fs/ocfs2/cluster/nodemanager.c
+@@ -959,7 +959,10 @@ static int __init init_o2nm(void)
+ cluster_print_version();
+
+ o2hb_init();
+- o2net_init();
++
++ ret = o2net_init();
++ if (ret)
++ goto out;
+
+ ocfs2_table_header = register_sysctl_table(ocfs2_root_table);
+ if (!ocfs2_table_header) {
+diff --git a/fs/ocfs2/cluster/sys.c b/fs/ocfs2/cluster/sys.c
+index 0c095ce..98429fd 100644
+--- a/fs/ocfs2/cluster/sys.c
++++ b/fs/ocfs2/cluster/sys.c
+@@ -57,6 +57,7 @@ static struct kset *o2cb_kset;
+ void o2cb_sys_shutdown(void)
+ {
+ mlog_sys_shutdown();
++ sysfs_remove_link(NULL, "o2cb");
+ kset_unregister(o2cb_kset);
+ }
+
+@@ -68,6 +69,14 @@ int o2cb_sys_init(void)
+ if (!o2cb_kset)
+ return -ENOMEM;
+
++ /*
++ * Create this symlink for backwards compatibility with old
++ * versions of ocfs2-tools which look for things in /sys/o2cb.
++ */
++ ret = sysfs_create_link(NULL, &o2cb_kset->kobj, "o2cb");
++ if (ret)
++ goto error;
++
+ ret = sysfs_create_group(&o2cb_kset->kobj, &o2cb_attr_group);
+ if (ret)
+ goto error;
+diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
+index b8057c5..1e44ad1 100644
+--- a/fs/ocfs2/cluster/tcp.c
++++ b/fs/ocfs2/cluster/tcp.c
+@@ -142,23 +142,65 @@ static void o2net_idle_timer(unsigned long data);
+ static void o2net_sc_postpone_idle(struct o2net_sock_container *sc);
+ static void o2net_sc_reset_idle_timer(struct o2net_sock_container *sc);
+
+-/*
+- * FIXME: These should use to_o2nm_cluster_from_node(), but we end up
+- * losing our parent link to the cluster during shutdown. This can be
+- * solved by adding a pre-removal callback to configfs, or passing
+- * around the cluster with the node. -jeffm
+- */
+-static inline int o2net_reconnect_delay(struct o2nm_node *node)
++static void o2net_init_nst(struct o2net_send_tracking *nst, u32 msgtype,
++ u32 msgkey, struct task_struct *task, u8 node)
++{
++#ifdef CONFIG_DEBUG_FS
++ INIT_LIST_HEAD(&nst->st_net_debug_item);
++ nst->st_task = task;
++ nst->st_msg_type = msgtype;
++ nst->st_msg_key = msgkey;
++ nst->st_node = node;
++#endif
++}
++
++static void o2net_set_nst_sock_time(struct o2net_send_tracking *nst)
++{
++#ifdef CONFIG_DEBUG_FS
++ do_gettimeofday(&nst->st_sock_time);
++#endif
++}
++
++static void o2net_set_nst_send_time(struct o2net_send_tracking *nst)
++{
++#ifdef CONFIG_DEBUG_FS
++ do_gettimeofday(&nst->st_send_time);
++#endif
++}
++
++static void o2net_set_nst_status_time(struct o2net_send_tracking *nst)
++{
++#ifdef CONFIG_DEBUG_FS
++ do_gettimeofday(&nst->st_status_time);
++#endif
++}
++
++static void o2net_set_nst_sock_container(struct o2net_send_tracking *nst,
++ struct o2net_sock_container *sc)
++{
++#ifdef CONFIG_DEBUG_FS
++ nst->st_sc = sc;
++#endif
++}
++
++static void o2net_set_nst_msg_id(struct o2net_send_tracking *nst, u32 msg_id)
++{
++#ifdef CONFIG_DEBUG_FS
++ nst->st_id = msg_id;
++#endif
++}
++
++static inline int o2net_reconnect_delay(void)
+ {
+ return o2nm_single_cluster->cl_reconnect_delay_ms;
+ }
+
+-static inline int o2net_keepalive_delay(struct o2nm_node *node)
++static inline int o2net_keepalive_delay(void)
+ {
+ return o2nm_single_cluster->cl_keepalive_delay_ms;
+ }
+
+-static inline int o2net_idle_timeout(struct o2nm_node *node)
++static inline int o2net_idle_timeout(void)
+ {
+ return o2nm_single_cluster->cl_idle_timeout_ms;
+ }
+@@ -296,6 +338,7 @@ static void sc_kref_release(struct kref *kref)
+ o2nm_node_put(sc->sc_node);
+ sc->sc_node = NULL;
+
++ o2net_debug_del_sc(sc);
+ kfree(sc);
+ }
+
+@@ -336,6 +379,7 @@ static struct o2net_sock_container *sc_alloc(struct o2nm_node *node)
+
+ ret = sc;
+ sc->sc_page = page;
++ o2net_debug_add_sc(sc);
+ sc = NULL;
+ page = NULL;
+
+@@ -399,8 +443,6 @@ static void o2net_set_nn_state(struct o2net_node *nn,
+ mlog_bug_on_msg(err && valid, "err %d valid %u\n", err, valid);
+ mlog_bug_on_msg(valid && !sc, "valid %u sc %p\n", valid, sc);
+
+- /* we won't reconnect after our valid conn goes away for
+- * this hb iteration.. here so it shows up in the logs */
+ if (was_valid && !valid && err == 0)
+ err = -ENOTCONN;
+
+@@ -430,11 +472,6 @@ static void o2net_set_nn_state(struct o2net_node *nn,
+
+ if (!was_valid && valid) {
+ o2quo_conn_up(o2net_num_from_nn(nn));
+- /* this is a bit of a hack. we only try reconnecting
+- * when heartbeating starts until we get a connection.
+- * if that connection then dies we don't try reconnecting.
+- * the only way to start connecting again is to down
+- * heartbeat and bring it back up. */
+ cancel_delayed_work(&nn->nn_connect_expired);
+ printk(KERN_INFO "o2net: %s " SC_NODEF_FMT "\n",
+ o2nm_this_node() > sc->sc_node->nd_num ?
+@@ -451,12 +488,24 @@ static void o2net_set_nn_state(struct o2net_node *nn,
+ /* delay if we're withing a RECONNECT_DELAY of the
+ * last attempt */
+ delay = (nn->nn_last_connect_attempt +
+- msecs_to_jiffies(o2net_reconnect_delay(NULL)))
++ msecs_to_jiffies(o2net_reconnect_delay()))
+ - jiffies;
+- if (delay > msecs_to_jiffies(o2net_reconnect_delay(NULL)))
++ if (delay > msecs_to_jiffies(o2net_reconnect_delay()))
+ delay = 0;
+ mlog(ML_CONN, "queueing conn attempt in %lu jiffies\n", delay);
+ queue_delayed_work(o2net_wq, &nn->nn_connect_work, delay);
++
++ /*
++ * Delay the expired work after idle timeout.
++ *
++ * We might have lots of failed connection attempts that run
++ * through here but we only cancel the connect_expired work when
++ * a connection attempt succeeds. So only the first enqueue of
++ * the connect_expired work will do anything. The rest will see
++ * that it's already queued and do nothing.
++ */
++ delay += msecs_to_jiffies(o2net_idle_timeout());
++ queue_delayed_work(o2net_wq, &nn->nn_connect_expired, delay);
+ }
+
+ /* keep track of the nn's sc ref for the caller */
+@@ -914,6 +963,9 @@ int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec,
+ struct o2net_status_wait nsw = {
+ .ns_node_item = LIST_HEAD_INIT(nsw.ns_node_item),
+ };
++ struct o2net_send_tracking nst;
++
++ o2net_init_nst(&nst, msg_type, key, current, target_node);
+
+ if (o2net_wq == NULL) {
+ mlog(0, "attempt to tx without o2netd running\n");
+@@ -939,6 +991,10 @@ int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec,
+ goto out;
+ }
+
++ o2net_debug_add_nst(&nst);
++
++ o2net_set_nst_sock_time(&nst);
++
+ ret = wait_event_interruptible(nn->nn_sc_wq,
+ o2net_tx_can_proceed(nn, &sc, &error));
+ if (!ret && error)
+@@ -946,6 +1002,8 @@ int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec,
+ if (ret)
+ goto out;
+
++ o2net_set_nst_sock_container(&nst, sc);
++
+ veclen = caller_veclen + 1;
+ vec = kmalloc(sizeof(struct kvec) * veclen, GFP_ATOMIC);
+ if (vec == NULL) {
+@@ -972,6 +1030,9 @@ int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec,
+ goto out;
+
+ msg->msg_num = cpu_to_be32(nsw.ns_id);
++ o2net_set_nst_msg_id(&nst, nsw.ns_id);
++
++ o2net_set_nst_send_time(&nst);
+
+ /* finally, convert the message header to network byte-order
+ * and send */
+@@ -986,6 +1047,7 @@ int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec,
+ }
+
+ /* wait on other node's handler */
++ o2net_set_nst_status_time(&nst);
+ wait_event(nsw.ns_wq, o2net_nsw_completed(nn, &nsw));
+
+ /* Note that we avoid overwriting the callers status return
+@@ -998,6 +1060,7 @@ int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec,
+ mlog(0, "woken, returning system status %d, user status %d\n",
+ ret, nsw.ns_status);
+ out:
++ o2net_debug_del_nst(&nst); /* must be before dropping sc and node */
+ if (sc)
+ sc_put(sc);
+ if (vec)
+@@ -1154,23 +1217,23 @@ static int o2net_check_handshake(struct o2net_sock_container *sc)
+ * but isn't. This can ultimately cause corruption.
+ */
+ if (be32_to_cpu(hand->o2net_idle_timeout_ms) !=
+- o2net_idle_timeout(sc->sc_node)) {
++ o2net_idle_timeout()) {
+ mlog(ML_NOTICE, SC_NODEF_FMT " uses a network idle timeout of "
+ "%u ms, but we use %u ms locally. disconnecting\n",
+ SC_NODEF_ARGS(sc),
+ be32_to_cpu(hand->o2net_idle_timeout_ms),
+- o2net_idle_timeout(sc->sc_node));
++ o2net_idle_timeout());
+ o2net_ensure_shutdown(nn, sc, -ENOTCONN);
+ return -1;
+ }
+
+ if (be32_to_cpu(hand->o2net_keepalive_delay_ms) !=
+- o2net_keepalive_delay(sc->sc_node)) {
++ o2net_keepalive_delay()) {
+ mlog(ML_NOTICE, SC_NODEF_FMT " uses a keepalive delay of "
+ "%u ms, but we use %u ms locally. disconnecting\n",
+ SC_NODEF_ARGS(sc),
+ be32_to_cpu(hand->o2net_keepalive_delay_ms),
+- o2net_keepalive_delay(sc->sc_node));
++ o2net_keepalive_delay());
+ o2net_ensure_shutdown(nn, sc, -ENOTCONN);
+ return -1;
+ }
+@@ -1193,6 +1256,7 @@ static int o2net_check_handshake(struct o2net_sock_container *sc)
+ * shut down already */
+ if (nn->nn_sc == sc) {
+ o2net_sc_reset_idle_timer(sc);
++ atomic_set(&nn->nn_timeout, 0);
+ o2net_set_nn_state(nn, sc, 1, 0);
+ }
+ spin_unlock(&nn->nn_lock);
+@@ -1347,12 +1411,11 @@ static void o2net_initialize_handshake(void)
+ {
+ o2net_hand->o2hb_heartbeat_timeout_ms = cpu_to_be32(
+ O2HB_MAX_WRITE_TIMEOUT_MS);
+- o2net_hand->o2net_idle_timeout_ms = cpu_to_be32(
+- o2net_idle_timeout(NULL));
++ o2net_hand->o2net_idle_timeout_ms = cpu_to_be32(o2net_idle_timeout());
+ o2net_hand->o2net_keepalive_delay_ms = cpu_to_be32(
+- o2net_keepalive_delay(NULL));
++ o2net_keepalive_delay());
+ o2net_hand->o2net_reconnect_delay_ms = cpu_to_be32(
+- o2net_reconnect_delay(NULL));
++ o2net_reconnect_delay());
+ }
+
+ /* ------------------------------------------------------------ */
+@@ -1391,14 +1454,15 @@ static void o2net_sc_send_keep_req(struct work_struct *work)
+ static void o2net_idle_timer(unsigned long data)
+ {
+ struct o2net_sock_container *sc = (struct o2net_sock_container *)data;
++ struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num);
+ struct timeval now;
+
+ do_gettimeofday(&now);
+
+ printk(KERN_INFO "o2net: connection to " SC_NODEF_FMT " has been idle for %u.%u "
+ "seconds, shutting it down.\n", SC_NODEF_ARGS(sc),
+- o2net_idle_timeout(sc->sc_node) / 1000,
+- o2net_idle_timeout(sc->sc_node) % 1000);
++ o2net_idle_timeout() / 1000,
++ o2net_idle_timeout() % 1000);
+ mlog(ML_NOTICE, "here are some times that might help debug the "
+ "situation: (tmr %ld.%ld now %ld.%ld dr %ld.%ld adv "
+ "%ld.%ld:%ld.%ld func (%08x:%u) %ld.%ld:%ld.%ld)\n",
+@@ -1413,6 +1477,12 @@ static void o2net_idle_timer(unsigned long data)
+ sc->sc_tv_func_start.tv_sec, (long) sc->sc_tv_func_start.tv_usec,
+ sc->sc_tv_func_stop.tv_sec, (long) sc->sc_tv_func_stop.tv_usec);
+
++ /*
++ * Initialize the nn_timeout so that the next connection attempt
++ * will continue in o2net_start_connect.
++ */
++ atomic_set(&nn->nn_timeout, 1);
++
+ o2net_sc_queue_work(sc, &sc->sc_shutdown_work);
+ }
+
+@@ -1420,10 +1490,10 @@ static void o2net_sc_reset_idle_timer(struct o2net_sock_container *sc)
+ {
+ o2net_sc_cancel_delayed_work(sc, &sc->sc_keepalive_work);
+ o2net_sc_queue_delayed_work(sc, &sc->sc_keepalive_work,
+- msecs_to_jiffies(o2net_keepalive_delay(sc->sc_node)));
++ msecs_to_jiffies(o2net_keepalive_delay()));
+ do_gettimeofday(&sc->sc_tv_timer);
+ mod_timer(&sc->sc_idle_timeout,
+- jiffies + msecs_to_jiffies(o2net_idle_timeout(sc->sc_node)));
++ jiffies + msecs_to_jiffies(o2net_idle_timeout()));
+ }
+
+ static void o2net_sc_postpone_idle(struct o2net_sock_container *sc)
+@@ -1447,6 +1517,7 @@ static void o2net_start_connect(struct work_struct *work)
+ struct socket *sock = NULL;
+ struct sockaddr_in myaddr = {0, }, remoteaddr = {0, };
+ int ret = 0, stop;
++ unsigned int timeout;
+
+ /* if we're greater we initiate tx, otherwise we accept */
+ if (o2nm_this_node() <= o2net_num_from_nn(nn))
+@@ -1466,8 +1537,17 @@ static void o2net_start_connect(struct work_struct *work)
+ }
+
+ spin_lock(&nn->nn_lock);
+- /* see if we already have one pending or have given up */
+- stop = (nn->nn_sc || nn->nn_persistent_error);
++ /*
++ * see if we already have one pending or have given up.
++ * For nn_timeout, it is set when we close the connection
++ * because of the idle time out. So it means that we have
++ * at least connected to that node successfully once,
++ * now try to connect to it again.
++ */
++ timeout = atomic_read(&nn->nn_timeout);
++ stop = (nn->nn_sc ||
++ (nn->nn_persistent_error &&
++ (nn->nn_persistent_error != -ENOTCONN || timeout == 0)));
+ spin_unlock(&nn->nn_lock);
+ if (stop)
+ goto out;
+@@ -1555,8 +1635,8 @@ static void o2net_connect_expired(struct work_struct *work)
+ mlog(ML_ERROR, "no connection established with node %u after "
+ "%u.%u seconds, giving up and returning errors.\n",
+ o2net_num_from_nn(nn),
+- o2net_idle_timeout(NULL) / 1000,
+- o2net_idle_timeout(NULL) % 1000);
++ o2net_idle_timeout() / 1000,
++ o2net_idle_timeout() % 1000);
+
+ o2net_set_nn_state(nn, NULL, 0, -ENOTCONN);
+ }
+@@ -1579,6 +1659,7 @@ void o2net_disconnect_node(struct o2nm_node *node)
+
+ /* don't reconnect until it's heartbeating again */
+ spin_lock(&nn->nn_lock);
++ atomic_set(&nn->nn_timeout, 0);
+ o2net_set_nn_state(nn, NULL, 0, -ENOTCONN);
+ spin_unlock(&nn->nn_lock);
+
+@@ -1610,20 +1691,15 @@ static void o2net_hb_node_up_cb(struct o2nm_node *node, int node_num,
+
+ /* ensure an immediate connect attempt */
+ nn->nn_last_connect_attempt = jiffies -
+- (msecs_to_jiffies(o2net_reconnect_delay(node)) + 1);
++ (msecs_to_jiffies(o2net_reconnect_delay()) + 1);
+
+ if (node_num != o2nm_this_node()) {
+- /* heartbeat doesn't work unless a local node number is
+- * configured and doing so brings up the o2net_wq, so we can
+- * use it.. */
+- queue_delayed_work(o2net_wq, &nn->nn_connect_expired,
+- msecs_to_jiffies(o2net_idle_timeout(node)));
+-
+ /* believe it or not, accept and node hearbeating testing
+ * can succeed for this node before we got here.. so
+ * only use set_nn_state to clear the persistent error
+ * if that hasn't already happened */
+ spin_lock(&nn->nn_lock);
++ atomic_set(&nn->nn_timeout, 0);
+ if (nn->nn_persistent_error)
+ o2net_set_nn_state(nn, NULL, 0, 0);
+ spin_unlock(&nn->nn_lock);
+@@ -1747,6 +1823,7 @@ static int o2net_accept_one(struct socket *sock)
+ new_sock = NULL;
+
+ spin_lock(&nn->nn_lock);
++ atomic_set(&nn->nn_timeout, 0);
+ o2net_set_nn_state(nn, sc, 0, 0);
+ spin_unlock(&nn->nn_lock);
+
+@@ -1922,6 +1999,9 @@ int o2net_init(void)
+
+ o2quo_init();
+
++ if (o2net_debugfs_init())
++ return -ENOMEM;
++
+ o2net_hand = kzalloc(sizeof(struct o2net_handshake), GFP_KERNEL);
+ o2net_keep_req = kzalloc(sizeof(struct o2net_msg), GFP_KERNEL);
+ o2net_keep_resp = kzalloc(sizeof(struct o2net_msg), GFP_KERNEL);
+@@ -1941,6 +2021,7 @@ int o2net_init(void)
+ for (i = 0; i < ARRAY_SIZE(o2net_nodes); i++) {
+ struct o2net_node *nn = o2net_nn_from_num(i);
+
++ atomic_set(&nn->nn_timeout, 0);
+ spin_lock_init(&nn->nn_lock);
+ INIT_DELAYED_WORK(&nn->nn_connect_work, o2net_start_connect);
+ INIT_DELAYED_WORK(&nn->nn_connect_expired,
+@@ -1962,4 +2043,5 @@ void o2net_exit(void)
+ kfree(o2net_hand);
+ kfree(o2net_keep_req);
+ kfree(o2net_keep_resp);
++ o2net_debugfs_exit();
+ }
+diff --git a/fs/ocfs2/cluster/tcp.h b/fs/ocfs2/cluster/tcp.h
+index f36f66a..a705d5d 100644
+--- a/fs/ocfs2/cluster/tcp.h
++++ b/fs/ocfs2/cluster/tcp.h
+@@ -117,4 +117,36 @@ int o2net_num_connected_peers(void);
+ int o2net_init(void);
+ void o2net_exit(void);
+
++struct o2net_send_tracking;
++struct o2net_sock_container;
++
++#ifdef CONFIG_DEBUG_FS
++int o2net_debugfs_init(void);
++void o2net_debugfs_exit(void);
++void o2net_debug_add_nst(struct o2net_send_tracking *nst);
++void o2net_debug_del_nst(struct o2net_send_tracking *nst);
++void o2net_debug_add_sc(struct o2net_sock_container *sc);
++void o2net_debug_del_sc(struct o2net_sock_container *sc);
++#else
++static int o2net_debugfs_init(void)
++{
++ return 0;
++}
++static void o2net_debugfs_exit(void)
++{
++}
++static void o2net_debug_add_nst(struct o2net_send_tracking *nst)
++{
++}
++static void o2net_debug_del_nst(struct o2net_send_tracking *nst)
++{
++}
++static void o2net_debug_add_sc(struct o2net_sock_container *sc)
++{
++}
++static void o2net_debug_del_sc(struct o2net_sock_container *sc)
++{
++}
++#endif /* CONFIG_DEBUG_FS */
++
+ #endif /* O2CLUSTER_TCP_H */
+diff --git a/fs/ocfs2/cluster/tcp_internal.h b/fs/ocfs2/cluster/tcp_internal.h
+index d25b9af..8d58cfe 100644
+--- a/fs/ocfs2/cluster/tcp_internal.h
++++ b/fs/ocfs2/cluster/tcp_internal.h
+@@ -95,6 +95,8 @@ struct o2net_node {
+ unsigned nn_sc_valid:1;
+ /* if this is set tx just returns it */
+ int nn_persistent_error;
++ /* It is only set to 1 after the idle time out. */
++ atomic_t nn_timeout;
+
+ /* threads waiting for an sc to arrive wait on the wq for generation
+ * to increase. it is increased when a connecting socket succeeds
+@@ -164,7 +166,9 @@ struct o2net_sock_container {
+ /* original handlers for the sockets */
+ void (*sc_state_change)(struct sock *sk);
+ void (*sc_data_ready)(struct sock *sk, int bytes);
+-
++#ifdef CONFIG_DEBUG_FS
++ struct list_head sc_net_debug_item;
++#endif
+ struct timeval sc_tv_timer;
+ struct timeval sc_tv_data_ready;
+ struct timeval sc_tv_advance_start;
+@@ -206,4 +210,24 @@ struct o2net_status_wait {
+ struct list_head ns_node_item;
+ };
+
++#ifdef CONFIG_DEBUG_FS
++/* just for state dumps */
++struct o2net_send_tracking {
++ struct list_head st_net_debug_item;
++ struct task_struct *st_task;
++ struct o2net_sock_container *st_sc;
++ u32 st_id;
++ u32 st_msg_type;
++ u32 st_msg_key;
++ u8 st_node;
++ struct timeval st_sock_time;
++ struct timeval st_send_time;
++ struct timeval st_status_time;
++};
++#else
++struct o2net_send_tracking {
++ u32 dummy;
++};
++#endif /* CONFIG_DEBUG_FS */
++
+ #endif /* O2CLUSTER_TCP_INTERNAL_H */
+diff --git a/fs/ocfs2/dlm/Makefile b/fs/ocfs2/dlm/Makefile
+index ce3f7c2..1903613 100644
+--- a/fs/ocfs2/dlm/Makefile
++++ b/fs/ocfs2/dlm/Makefile
+@@ -1,6 +1,6 @@
+ EXTRA_CFLAGS += -Ifs/ocfs2
+
+-obj-$(CONFIG_OCFS2_FS) += ocfs2_dlm.o ocfs2_dlmfs.o
++obj-$(CONFIG_OCFS2_FS_O2CB) += ocfs2_dlm.o ocfs2_dlmfs.o
+
+ ocfs2_dlm-objs := dlmdomain.o dlmdebug.o dlmthread.o dlmrecovery.o \
+ dlmmaster.o dlmast.o dlmconvert.o dlmlock.o dlmunlock.o dlmver.o
+diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h
+index dc8ea66..d5a86fb 100644
+--- a/fs/ocfs2/dlm/dlmcommon.h
++++ b/fs/ocfs2/dlm/dlmcommon.h
+@@ -49,6 +49,41 @@
+ /* Intended to make it easier for us to switch out hash functions */
+ #define dlm_lockid_hash(_n, _l) full_name_hash(_n, _l)
+
++enum dlm_mle_type {
++ DLM_MLE_BLOCK,
++ DLM_MLE_MASTER,
++ DLM_MLE_MIGRATION
++};
++
++struct dlm_lock_name {
++ u8 len;
++ u8 name[DLM_LOCKID_NAME_MAX];
++};
++
++struct dlm_master_list_entry {
++ struct list_head list;
++ struct list_head hb_events;
++ struct dlm_ctxt *dlm;
++ spinlock_t spinlock;
++ wait_queue_head_t wq;
++ atomic_t woken;
++ struct kref mle_refs;
++ int inuse;
++ unsigned long maybe_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
++ unsigned long vote_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
++ unsigned long response_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
++ unsigned long node_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
++ u8 master;
++ u8 new_master;
++ enum dlm_mle_type type;
++ struct o2hb_callback_func mle_hb_up;
++ struct o2hb_callback_func mle_hb_down;
++ union {
++ struct dlm_lock_resource *res;
++ struct dlm_lock_name name;
++ } u;
++};
++
+ enum dlm_ast_type {
+ DLM_AST = 0,
+ DLM_BAST,
+@@ -101,6 +136,7 @@ struct dlm_ctxt
+ struct list_head purge_list;
+ struct list_head pending_asts;
+ struct list_head pending_basts;
++ struct list_head tracking_list;
+ unsigned int purge_count;
+ spinlock_t spinlock;
+ spinlock_t ast_lock;
+@@ -122,6 +158,9 @@ struct dlm_ctxt
+ atomic_t remote_resources;
+ atomic_t unknown_resources;
+
++ struct dlm_debug_ctxt *dlm_debug_ctxt;
++ struct dentry *dlm_debugfs_subroot;
++
+ /* NOTE: Next three are protected by dlm_domain_lock */
+ struct kref dlm_refs;
+ enum dlm_ctxt_state dlm_state;
+@@ -270,6 +309,9 @@ struct dlm_lock_resource
+ struct list_head dirty;
+ struct list_head recovering; // dlm_recovery_ctxt.resources list
+
++ /* Added during init and removed during release */
++ struct list_head tracking; /* dlm->tracking_list */
++
+ /* unused lock resources have their last_used stamped and are
+ * put on a list for the dlm thread to run. */
+ unsigned long last_used;
+@@ -963,9 +1005,16 @@ static inline void __dlm_wait_on_lockres(struct dlm_lock_resource *res)
+ DLM_LOCK_RES_MIGRATING));
+ }
+
++/* create/destroy slab caches */
++int dlm_init_master_caches(void);
++void dlm_destroy_master_caches(void);
++
++int dlm_init_lock_cache(void);
++void dlm_destroy_lock_cache(void);
+
+ int dlm_init_mle_cache(void);
+ void dlm_destroy_mle_cache(void);
++
+ void dlm_hb_event_notify_attached(struct dlm_ctxt *dlm, int idx, int node_up);
+ int dlm_drop_lockres_ref(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res);
+diff --git a/fs/ocfs2/dlm/dlmdebug.c b/fs/ocfs2/dlm/dlmdebug.c
+index 64239b3..5f6d858 100644
+--- a/fs/ocfs2/dlm/dlmdebug.c
++++ b/fs/ocfs2/dlm/dlmdebug.c
+@@ -5,7 +5,7 @@
+ *
+ * debug functionality for the dlm
+ *
+- * Copyright (C) 2004 Oracle. All rights reserved.
++ * Copyright (C) 2004, 2008 Oracle. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+@@ -30,6 +30,7 @@
+ #include <linux/utsname.h>
+ #include <linux/sysctl.h>
+ #include <linux/spinlock.h>
++#include <linux/debugfs.h>
+
+ #include "cluster/heartbeat.h"
+ #include "cluster/nodemanager.h"
+@@ -37,17 +38,16 @@
+
+ #include "dlmapi.h"
+ #include "dlmcommon.h"
+-
+ #include "dlmdomain.h"
++#include "dlmdebug.h"
+
+ #define MLOG_MASK_PREFIX ML_DLM
+ #include "cluster/masklog.h"
+
++int stringify_lockname(const char *lockname, int locklen, char *buf, int len);
++
+ void dlm_print_one_lock_resource(struct dlm_lock_resource *res)
+ {
+- mlog(ML_NOTICE, "lockres: %.*s, owner=%u, state=%u\n",
+- res->lockname.len, res->lockname.name,
+- res->owner, res->state);
+ spin_lock(&res->spinlock);
+ __dlm_print_one_lock_resource(res);
+ spin_unlock(&res->spinlock);
+@@ -58,7 +58,7 @@ static void dlm_print_lockres_refmap(struct dlm_lock_resource *res)
+ int bit;
+ assert_spin_locked(&res->spinlock);
+
+- mlog(ML_NOTICE, " refmap nodes: [ ");
++ printk(" refmap nodes: [ ");
+ bit = 0;
+ while (1) {
+ bit = find_next_bit(res->refmap, O2NM_MAX_NODES, bit);
+@@ -70,63 +70,66 @@ static void dlm_print_lockres_refmap(struct dlm_lock_resource *res)
+ printk("], inflight=%u\n", res->inflight_locks);
+ }
+
++static void __dlm_print_lock(struct dlm_lock *lock)
++{
++ spin_lock(&lock->spinlock);
++
++ printk(" type=%d, conv=%d, node=%u, cookie=%u:%llu, "
++ "ref=%u, ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c), "
++ "pending=(conv=%c,lock=%c,cancel=%c,unlock=%c)\n",
++ lock->ml.type, lock->ml.convert_type, lock->ml.node,
++ dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),
++ dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),
++ atomic_read(&lock->lock_refs.refcount),
++ (list_empty(&lock->ast_list) ? 'y' : 'n'),
++ (lock->ast_pending ? 'y' : 'n'),
++ (list_empty(&lock->bast_list) ? 'y' : 'n'),
++ (lock->bast_pending ? 'y' : 'n'),
++ (lock->convert_pending ? 'y' : 'n'),
++ (lock->lock_pending ? 'y' : 'n'),
++ (lock->cancel_pending ? 'y' : 'n'),
++ (lock->unlock_pending ? 'y' : 'n'));
++
++ spin_unlock(&lock->spinlock);
++}
++
+ void __dlm_print_one_lock_resource(struct dlm_lock_resource *res)
+ {
+ struct list_head *iter2;
+ struct dlm_lock *lock;
++ char buf[DLM_LOCKID_NAME_MAX];
+
+ assert_spin_locked(&res->spinlock);
+
+- mlog(ML_NOTICE, "lockres: %.*s, owner=%u, state=%u\n",
+- res->lockname.len, res->lockname.name,
+- res->owner, res->state);
+- mlog(ML_NOTICE, " last used: %lu, on purge list: %s\n",
+- res->last_used, list_empty(&res->purge) ? "no" : "yes");
++ stringify_lockname(res->lockname.name, res->lockname.len,
++ buf, sizeof(buf) - 1);
++ printk("lockres: %s, owner=%u, state=%u\n",
++ buf, res->owner, res->state);
++ printk(" last used: %lu, refcnt: %u, on purge list: %s\n",
++ res->last_used, atomic_read(&res->refs.refcount),
++ list_empty(&res->purge) ? "no" : "yes");
++ printk(" on dirty list: %s, on reco list: %s, "
++ "migrating pending: %s\n",
++ list_empty(&res->dirty) ? "no" : "yes",
++ list_empty(&res->recovering) ? "no" : "yes",
++ res->migration_pending ? "yes" : "no");
++ printk(" inflight locks: %d, asts reserved: %d\n",
++ res->inflight_locks, atomic_read(&res->asts_reserved));
+ dlm_print_lockres_refmap(res);
+- mlog(ML_NOTICE, " granted queue: \n");
++ printk(" granted queue:\n");
+ list_for_each(iter2, &res->granted) {
+ lock = list_entry(iter2, struct dlm_lock, list);
+- spin_lock(&lock->spinlock);
+- mlog(ML_NOTICE, " type=%d, conv=%d, node=%u, "
+- "cookie=%u:%llu, ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c)\n",
+- lock->ml.type, lock->ml.convert_type, lock->ml.node,
+- dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),
+- dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),
+- list_empty(&lock->ast_list) ? 'y' : 'n',
+- lock->ast_pending ? 'y' : 'n',
+- list_empty(&lock->bast_list) ? 'y' : 'n',
+- lock->bast_pending ? 'y' : 'n');
+- spin_unlock(&lock->spinlock);
++ __dlm_print_lock(lock);
+ }
+- mlog(ML_NOTICE, " converting queue: \n");
++ printk(" converting queue:\n");
+ list_for_each(iter2, &res->converting) {
+ lock = list_entry(iter2, struct dlm_lock, list);
+- spin_lock(&lock->spinlock);
+- mlog(ML_NOTICE, " type=%d, conv=%d, node=%u, "
+- "cookie=%u:%llu, ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c)\n",
+- lock->ml.type, lock->ml.convert_type, lock->ml.node,
+- dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),
+- dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),
+- list_empty(&lock->ast_list) ? 'y' : 'n',
+- lock->ast_pending ? 'y' : 'n',
+- list_empty(&lock->bast_list) ? 'y' : 'n',
+- lock->bast_pending ? 'y' : 'n');
+- spin_unlock(&lock->spinlock);
++ __dlm_print_lock(lock);
+ }
+- mlog(ML_NOTICE, " blocked queue: \n");
++ printk(" blocked queue:\n");
+ list_for_each(iter2, &res->blocked) {
+ lock = list_entry(iter2, struct dlm_lock, list);
+- spin_lock(&lock->spinlock);
+- mlog(ML_NOTICE, " type=%d, conv=%d, node=%u, "
+- "cookie=%u:%llu, ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c)\n",
+- lock->ml.type, lock->ml.convert_type, lock->ml.node,
+- dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),
+- dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),
+- list_empty(&lock->ast_list) ? 'y' : 'n',
+- lock->ast_pending ? 'y' : 'n',
+- list_empty(&lock->bast_list) ? 'y' : 'n',
+- lock->bast_pending ? 'y' : 'n');
+- spin_unlock(&lock->spinlock);
++ __dlm_print_lock(lock);
+ }
+ }
+
+@@ -136,31 +139,6 @@ void dlm_print_one_lock(struct dlm_lock *lockid)
+ }
+ EXPORT_SYMBOL_GPL(dlm_print_one_lock);
+
+-#if 0
+-void dlm_dump_lock_resources(struct dlm_ctxt *dlm)
+-{
+- struct dlm_lock_resource *res;
+- struct hlist_node *iter;
+- struct hlist_head *bucket;
+- int i;
+-
+- mlog(ML_NOTICE, "struct dlm_ctxt: %s, node=%u, key=%u\n",
+- dlm->name, dlm->node_num, dlm->key);
+- if (!dlm || !dlm->name) {
+- mlog(ML_ERROR, "dlm=%p\n", dlm);
+- return;
+- }
+-
+- spin_lock(&dlm->spinlock);
+- for (i=0; i<DLM_HASH_BUCKETS; i++) {
+- bucket = dlm_lockres_hash(dlm, i);
+- hlist_for_each_entry(res, iter, bucket, hash_node)
+- dlm_print_one_lock_resource(res);
+- }
+- spin_unlock(&dlm->spinlock);
+-}
+-#endif /* 0 */
+-
+ static const char *dlm_errnames[] = {
+ [DLM_NORMAL] = "DLM_NORMAL",
+ [DLM_GRANTED] = "DLM_GRANTED",
+@@ -266,3 +244,792 @@ const char *dlm_errname(enum dlm_status err)
+ return dlm_errnames[err];
+ }
+ EXPORT_SYMBOL_GPL(dlm_errname);
++
++/* NOTE: This function converts a lockname into a string. It uses knowledge
++ * of the format of the lockname that should be outside the purview of the dlm.
++ * We are adding only to make dlm debugging slightly easier.
++ *
++ * For more on lockname formats, please refer to dlmglue.c and ocfs2_lockid.h.
++ */
++int stringify_lockname(const char *lockname, int locklen, char *buf, int len)
++{
++ int out = 0;
++ __be64 inode_blkno_be;
++
++#define OCFS2_DENTRY_LOCK_INO_START 18
++ if (*lockname == 'N') {
++ memcpy((__be64 *)&inode_blkno_be,
++ (char *)&lockname[OCFS2_DENTRY_LOCK_INO_START],
++ sizeof(__be64));
++ out += snprintf(buf + out, len - out, "%.*s%08x",
++ OCFS2_DENTRY_LOCK_INO_START - 1, lockname,
++ (unsigned int)be64_to_cpu(inode_blkno_be));
++ } else
++ out += snprintf(buf + out, len - out, "%.*s",
++ locklen, lockname);
++ return out;
++}
++
++static int stringify_nodemap(unsigned long *nodemap, int maxnodes,
++ char *buf, int len)
++{
++ int out = 0;
++ int i = -1;
++
++ while ((i = find_next_bit(nodemap, maxnodes, i + 1)) < maxnodes)
++ out += snprintf(buf + out, len - out, "%d ", i);
++
++ return out;
++}
++
++static int dump_mle(struct dlm_master_list_entry *mle, char *buf, int len)
++{
++ int out = 0;
++ unsigned int namelen;
++ const char *name;
++ char *mle_type;
++
++ if (mle->type != DLM_MLE_MASTER) {
++ namelen = mle->u.name.len;
++ name = mle->u.name.name;
++ } else {
++ namelen = mle->u.res->lockname.len;
++ name = mle->u.res->lockname.name;
++ }
++
++ if (mle->type == DLM_MLE_BLOCK)
++ mle_type = "BLK";
++ else if (mle->type == DLM_MLE_MASTER)
++ mle_type = "MAS";
++ else
++ mle_type = "MIG";
++
++ out += stringify_lockname(name, namelen, buf + out, len - out);
++ out += snprintf(buf + out, len - out,
++ "\t%3s\tmas=%3u\tnew=%3u\tevt=%1d\tuse=%1d\tref=%3d\n",
++ mle_type, mle->master, mle->new_master,
++ !list_empty(&mle->hb_events),
++ !!mle->inuse,
++ atomic_read(&mle->mle_refs.refcount));
++
++ out += snprintf(buf + out, len - out, "Maybe=");
++ out += stringify_nodemap(mle->maybe_map, O2NM_MAX_NODES,
++ buf + out, len - out);
++ out += snprintf(buf + out, len - out, "\n");
++
++ out += snprintf(buf + out, len - out, "Vote=");
++ out += stringify_nodemap(mle->vote_map, O2NM_MAX_NODES,
++ buf + out, len - out);
++ out += snprintf(buf + out, len - out, "\n");
++
++ out += snprintf(buf + out, len - out, "Response=");
++ out += stringify_nodemap(mle->response_map, O2NM_MAX_NODES,
++ buf + out, len - out);
++ out += snprintf(buf + out, len - out, "\n");
++
++ out += snprintf(buf + out, len - out, "Node=");
++ out += stringify_nodemap(mle->node_map, O2NM_MAX_NODES,
++ buf + out, len - out);
++ out += snprintf(buf + out, len - out, "\n");
++
++ out += snprintf(buf + out, len - out, "\n");
++
++ return out;
++}
++
++void dlm_print_one_mle(struct dlm_master_list_entry *mle)
++{
++ char *buf;
++
++ buf = (char *) get_zeroed_page(GFP_NOFS);
++ if (buf) {
++ dump_mle(mle, buf, PAGE_SIZE - 1);
++ free_page((unsigned long)buf);
++ }
++}
++
++#ifdef CONFIG_DEBUG_FS
++
++static struct dentry *dlm_debugfs_root = NULL;
++
++#define DLM_DEBUGFS_DIR "o2dlm"
++#define DLM_DEBUGFS_DLM_STATE "dlm_state"
++#define DLM_DEBUGFS_LOCKING_STATE "locking_state"
++#define DLM_DEBUGFS_MLE_STATE "mle_state"
++#define DLM_DEBUGFS_PURGE_LIST "purge_list"
++
++/* begin - utils funcs */
++static void dlm_debug_free(struct kref *kref)
++{
++ struct dlm_debug_ctxt *dc;
++
++ dc = container_of(kref, struct dlm_debug_ctxt, debug_refcnt);
++
++ kfree(dc);
++}
++
++void dlm_debug_put(struct dlm_debug_ctxt *dc)
++{
++ if (dc)
++ kref_put(&dc->debug_refcnt, dlm_debug_free);
++}
++
++static void dlm_debug_get(struct dlm_debug_ctxt *dc)
++{
++ kref_get(&dc->debug_refcnt);
++}
++
++static struct debug_buffer *debug_buffer_allocate(void)
++{
++ struct debug_buffer *db = NULL;
++
++ db = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL);
++ if (!db)
++ goto bail;
++
++ db->len = PAGE_SIZE;
++ db->buf = kmalloc(db->len, GFP_KERNEL);
++ if (!db->buf)
++ goto bail;
++
++ return db;
++bail:
++ kfree(db);
++ return NULL;
++}
++
++static ssize_t debug_buffer_read(struct file *file, char __user *buf,
++ size_t nbytes, loff_t *ppos)
++{
++ struct debug_buffer *db = file->private_data;
++
++ return simple_read_from_buffer(buf, nbytes, ppos, db->buf, db->len);
++}
++
++static loff_t debug_buffer_llseek(struct file *file, loff_t off, int whence)
++{
++ struct debug_buffer *db = file->private_data;
++ loff_t new = -1;
++
++ switch (whence) {
++ case 0:
++ new = off;
++ break;
++ case 1:
++ new = file->f_pos + off;
++ break;
++ }
++
++ if (new < 0 || new > db->len)
++ return -EINVAL;
++
++ return (file->f_pos = new);
++}
++
++static int debug_buffer_release(struct inode *inode, struct file *file)
++{
++ struct debug_buffer *db = (struct debug_buffer *)file->private_data;
++
++ if (db)
++ kfree(db->buf);
++ kfree(db);
++
++ return 0;
++}
++/* end - util funcs */
++
++/* begin - purge list funcs */
++static int debug_purgelist_print(struct dlm_ctxt *dlm, struct debug_buffer *db)
++{
++ struct dlm_lock_resource *res;
++ int out = 0;
++ unsigned long total = 0;
++
++ out += snprintf(db->buf + out, db->len - out,
++ "Dumping Purgelist for Domain: %s\n", dlm->name);
++
++ spin_lock(&dlm->spinlock);
++ list_for_each_entry(res, &dlm->purge_list, purge) {
++ ++total;
++ if (db->len - out < 100)
++ continue;
++ spin_lock(&res->spinlock);
++ out += stringify_lockname(res->lockname.name,
++ res->lockname.len,
++ db->buf + out, db->len - out);
++ out += snprintf(db->buf + out, db->len - out, "\t%ld\n",
++ (jiffies - res->last_used)/HZ);
++ spin_unlock(&res->spinlock);
++ }
++ spin_unlock(&dlm->spinlock);
++
++ out += snprintf(db->buf + out, db->len - out,
++ "Total on list: %ld\n", total);
++
++ return out;
++}
++
++static int debug_purgelist_open(struct inode *inode, struct file *file)
++{
++ struct dlm_ctxt *dlm = inode->i_private;
++ struct debug_buffer *db;
++
++ db = debug_buffer_allocate();
++ if (!db)
++ goto bail;
++
++ db->len = debug_purgelist_print(dlm, db);
++
++ file->private_data = db;
++
++ return 0;
++bail:
++ return -ENOMEM;
++}
++
++static struct file_operations debug_purgelist_fops = {
++ .open = debug_purgelist_open,
++ .release = debug_buffer_release,
++ .read = debug_buffer_read,
++ .llseek = debug_buffer_llseek,
++};
++/* end - purge list funcs */
++
++/* begin - debug mle funcs */
++static int debug_mle_print(struct dlm_ctxt *dlm, struct debug_buffer *db)
++{
++ struct dlm_master_list_entry *mle;
++ int out = 0;
++ unsigned long total = 0;
++
++ out += snprintf(db->buf + out, db->len - out,
++ "Dumping MLEs for Domain: %s\n", dlm->name);
++
++ spin_lock(&dlm->master_lock);
++ list_for_each_entry(mle, &dlm->master_list, list) {
++ ++total;
++ if (db->len - out < 200)
++ continue;
++ out += dump_mle(mle, db->buf + out, db->len - out);
++ }
++ spin_unlock(&dlm->master_lock);
++
++ out += snprintf(db->buf + out, db->len - out,
++ "Total on list: %ld\n", total);
++ return out;
++}
++
++static int debug_mle_open(struct inode *inode, struct file *file)
++{
++ struct dlm_ctxt *dlm = inode->i_private;
++ struct debug_buffer *db;
++
++ db = debug_buffer_allocate();
++ if (!db)
++ goto bail;
++
++ db->len = debug_mle_print(dlm, db);
++
++ file->private_data = db;
++
++ return 0;
++bail:
++ return -ENOMEM;
++}
++
++static struct file_operations debug_mle_fops = {
++ .open = debug_mle_open,
++ .release = debug_buffer_release,
++ .read = debug_buffer_read,
++ .llseek = debug_buffer_llseek,
++};
++
++/* end - debug mle funcs */
++
++/* begin - debug lockres funcs */
++static int dump_lock(struct dlm_lock *lock, int list_type, char *buf, int len)
++{
++ int out;
++
++#define DEBUG_LOCK_VERSION 1
++ spin_lock(&lock->spinlock);
++ out = snprintf(buf, len, "LOCK:%d,%d,%d,%d,%d,%d:%lld,%d,%d,%d,%d,%d,"
++ "%d,%d,%d,%d\n",
++ DEBUG_LOCK_VERSION,
++ list_type, lock->ml.type, lock->ml.convert_type,
++ lock->ml.node,
++ dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),
++ dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),
++ !list_empty(&lock->ast_list),
++ !list_empty(&lock->bast_list),
++ lock->ast_pending, lock->bast_pending,
++ lock->convert_pending, lock->lock_pending,
++ lock->cancel_pending, lock->unlock_pending,
++ atomic_read(&lock->lock_refs.refcount));
++ spin_unlock(&lock->spinlock);
++
++ return out;
++}
++
++static int dump_lockres(struct dlm_lock_resource *res, char *buf, int len)
++{
++ struct dlm_lock *lock;
++ int i;
++ int out = 0;
++
++ out += snprintf(buf + out, len - out, "NAME:");
++ out += stringify_lockname(res->lockname.name, res->lockname.len,
++ buf + out, len - out);
++ out += snprintf(buf + out, len - out, "\n");
++
++#define DEBUG_LRES_VERSION 1
++ out += snprintf(buf + out, len - out,
++ "LRES:%d,%d,%d,%ld,%d,%d,%d,%d,%d,%d,%d\n",
++ DEBUG_LRES_VERSION,
++ res->owner, res->state, res->last_used,
++ !list_empty(&res->purge),
++ !list_empty(&res->dirty),
++ !list_empty(&res->recovering),
++ res->inflight_locks, res->migration_pending,
++ atomic_read(&res->asts_reserved),
++ atomic_read(&res->refs.refcount));
++
++ /* refmap */
++ out += snprintf(buf + out, len - out, "RMAP:");
++ out += stringify_nodemap(res->refmap, O2NM_MAX_NODES,
++ buf + out, len - out);
++ out += snprintf(buf + out, len - out, "\n");
++
++ /* lvb */
++ out += snprintf(buf + out, len - out, "LVBX:");
++ for (i = 0; i < DLM_LVB_LEN; i++)
++ out += snprintf(buf + out, len - out,
++ "%02x", (unsigned char)res->lvb[i]);
++ out += snprintf(buf + out, len - out, "\n");
++
++ /* granted */
++ list_for_each_entry(lock, &res->granted, list)
++ out += dump_lock(lock, 0, buf + out, len - out);
++
++ /* converting */
++ list_for_each_entry(lock, &res->converting, list)
++ out += dump_lock(lock, 1, buf + out, len - out);
++
++ /* blocked */
++ list_for_each_entry(lock, &res->blocked, list)
++ out += dump_lock(lock, 2, buf + out, len - out);
++
++ out += snprintf(buf + out, len - out, "\n");
++
++ return out;
++}
++
++static void *lockres_seq_start(struct seq_file *m, loff_t *pos)
++{
++ struct debug_lockres *dl = m->private;
++ struct dlm_ctxt *dlm = dl->dl_ctxt;
++ struct dlm_lock_resource *res = NULL;
++
++ spin_lock(&dlm->spinlock);
++
++ if (dl->dl_res) {
++ list_for_each_entry(res, &dl->dl_res->tracking, tracking) {
++ if (dl->dl_res) {
++ dlm_lockres_put(dl->dl_res);
++ dl->dl_res = NULL;
++ }
++ if (&res->tracking == &dlm->tracking_list) {
++ mlog(0, "End of list found, %p\n", res);
++ dl = NULL;
++ break;
++ }
++ dlm_lockres_get(res);
++ dl->dl_res = res;
++ break;
++ }
++ } else {
++ if (!list_empty(&dlm->tracking_list)) {
++ list_for_each_entry(res, &dlm->tracking_list, tracking)
++ break;
++ dlm_lockres_get(res);
++ dl->dl_res = res;
++ } else
++ dl = NULL;
++ }
++
++ if (dl) {
++ spin_lock(&dl->dl_res->spinlock);
++ dump_lockres(dl->dl_res, dl->dl_buf, dl->dl_len - 1);
++ spin_unlock(&dl->dl_res->spinlock);
++ }
++
++ spin_unlock(&dlm->spinlock);
++
++ return dl;
++}
++
++static void lockres_seq_stop(struct seq_file *m, void *v)
++{
++}
++
++static void *lockres_seq_next(struct seq_file *m, void *v, loff_t *pos)
++{
++ return NULL;
++}
++
++static int lockres_seq_show(struct seq_file *s, void *v)
++{
++ struct debug_lockres *dl = (struct debug_lockres *)v;
++
++ seq_printf(s, "%s", dl->dl_buf);
++
++ return 0;
++}
++
++static struct seq_operations debug_lockres_ops = {
++ .start = lockres_seq_start,
++ .stop = lockres_seq_stop,
++ .next = lockres_seq_next,
++ .show = lockres_seq_show,
++};
++
++static int debug_lockres_open(struct inode *inode, struct file *file)
++{
++ struct dlm_ctxt *dlm = inode->i_private;
++ int ret = -ENOMEM;
++ struct seq_file *seq;
++ struct debug_lockres *dl = NULL;
++
++ dl = kzalloc(sizeof(struct debug_lockres), GFP_KERNEL);
++ if (!dl) {
++ mlog_errno(ret);
++ goto bail;
++ }
++
++ dl->dl_len = PAGE_SIZE;
++ dl->dl_buf = kmalloc(dl->dl_len, GFP_KERNEL);
++ if (!dl->dl_buf) {
++ mlog_errno(ret);
++ goto bail;
++ }
++
++ ret = seq_open(file, &debug_lockres_ops);
++ if (ret) {
++ mlog_errno(ret);
++ goto bail;
++ }
++
++ seq = (struct seq_file *) file->private_data;
++ seq->private = dl;
++
++ dlm_grab(dlm);
++ dl->dl_ctxt = dlm;
++
++ return 0;
++bail:
++ if (dl)
++ kfree(dl->dl_buf);
++ kfree(dl);
++ return ret;
++}
++
++static int debug_lockres_release(struct inode *inode, struct file *file)
++{
++ struct seq_file *seq = (struct seq_file *)file->private_data;
++ struct debug_lockres *dl = (struct debug_lockres *)seq->private;
++
++ if (dl->dl_res)
++ dlm_lockres_put(dl->dl_res);
++ dlm_put(dl->dl_ctxt);
++ kfree(dl->dl_buf);
++ return seq_release_private(inode, file);
++}
++
++static struct file_operations debug_lockres_fops = {
++ .open = debug_lockres_open,
++ .release = debug_lockres_release,
++ .read = seq_read,
++ .llseek = seq_lseek,
++};
++/* end - debug lockres funcs */
++
++/* begin - debug state funcs */
++static int debug_state_print(struct dlm_ctxt *dlm, struct debug_buffer *db)
++{
++ int out = 0;
++ struct dlm_reco_node_data *node;
++ char *state;
++ int lres, rres, ures, tres;
++
++ lres = atomic_read(&dlm->local_resources);
++ rres = atomic_read(&dlm->remote_resources);
++ ures = atomic_read(&dlm->unknown_resources);
++ tres = lres + rres + ures;
++
++ spin_lock(&dlm->spinlock);
++
++ switch (dlm->dlm_state) {
++ case DLM_CTXT_NEW:
++ state = "NEW"; break;
++ case DLM_CTXT_JOINED:
++ state = "JOINED"; break;
++ case DLM_CTXT_IN_SHUTDOWN:
++ state = "SHUTDOWN"; break;
++ case DLM_CTXT_LEAVING:
++ state = "LEAVING"; break;
++ default:
++ state = "UNKNOWN"; break;
++ }
++
++ /* Domain: xxxxxxxxxx Key: 0xdfbac769 */
++ out += snprintf(db->buf + out, db->len - out,
++ "Domain: %s Key: 0x%08x\n", dlm->name, dlm->key);
++
++ /* Thread Pid: xxx Node: xxx State: xxxxx */
++ out += snprintf(db->buf + out, db->len - out,
++ "Thread Pid: %d Node: %d State: %s\n",
++ dlm->dlm_thread_task->pid, dlm->node_num, state);
++
++ /* Number of Joins: xxx Joining Node: xxx */
++ out += snprintf(db->buf + out, db->len - out,
++ "Number of Joins: %d Joining Node: %d\n",
++ dlm->num_joins, dlm->joining_node);
++
++ /* Domain Map: xx xx xx */
++ out += snprintf(db->buf + out, db->len - out, "Domain Map: ");
++ out += stringify_nodemap(dlm->domain_map, O2NM_MAX_NODES,
++ db->buf + out, db->len - out);
++ out += snprintf(db->buf + out, db->len - out, "\n");
++
++ /* Live Map: xx xx xx */
++ out += snprintf(db->buf + out, db->len - out, "Live Map: ");
++ out += stringify_nodemap(dlm->live_nodes_map, O2NM_MAX_NODES,
++ db->buf + out, db->len - out);
++ out += snprintf(db->buf + out, db->len - out, "\n");
++
++ /* Mastered Resources Total: xxx Locally: xxx Remotely: ... */
++ out += snprintf(db->buf + out, db->len - out,
++ "Mastered Resources Total: %d Locally: %d "
++ "Remotely: %d Unknown: %d\n",
++ tres, lres, rres, ures);
++
++ /* Lists: Dirty=Empty Purge=InUse PendingASTs=Empty ... */
++ out += snprintf(db->buf + out, db->len - out,
++ "Lists: Dirty=%s Purge=%s PendingASTs=%s "
++ "PendingBASTs=%s Master=%s\n",
++ (list_empty(&dlm->dirty_list) ? "Empty" : "InUse"),
++ (list_empty(&dlm->purge_list) ? "Empty" : "InUse"),
++ (list_empty(&dlm->pending_asts) ? "Empty" : "InUse"),
++ (list_empty(&dlm->pending_basts) ? "Empty" : "InUse"),
++ (list_empty(&dlm->master_list) ? "Empty" : "InUse"));
++
++ /* Purge Count: xxx Refs: xxx */
++ out += snprintf(db->buf + out, db->len - out,
++ "Purge Count: %d Refs: %d\n", dlm->purge_count,
++ atomic_read(&dlm->dlm_refs.refcount));
++
++ /* Dead Node: xxx */
++ out += snprintf(db->buf + out, db->len - out,
++ "Dead Node: %d\n", dlm->reco.dead_node);
++
++ /* What about DLM_RECO_STATE_FINALIZE? */
++ if (dlm->reco.state == DLM_RECO_STATE_ACTIVE)
++ state = "ACTIVE";
++ else
++ state = "INACTIVE";
++
++ /* Recovery Pid: xxxx Master: xxx State: xxxx */
++ out += snprintf(db->buf + out, db->len - out,
++ "Recovery Pid: %d Master: %d State: %s\n",
++ dlm->dlm_reco_thread_task->pid,
++ dlm->reco.new_master, state);
++
++ /* Recovery Map: xx xx */
++ out += snprintf(db->buf + out, db->len - out, "Recovery Map: ");
++ out += stringify_nodemap(dlm->recovery_map, O2NM_MAX_NODES,
++ db->buf + out, db->len - out);
++ out += snprintf(db->buf + out, db->len - out, "\n");
++
++ /* Recovery Node State: */
++ out += snprintf(db->buf + out, db->len - out, "Recovery Node State:\n");
++ list_for_each_entry(node, &dlm->reco.node_data, list) {
++ switch (node->state) {
++ case DLM_RECO_NODE_DATA_INIT:
++ state = "INIT";
++ break;
++ case DLM_RECO_NODE_DATA_REQUESTING:
++ state = "REQUESTING";
++ break;
++ case DLM_RECO_NODE_DATA_DEAD:
++ state = "DEAD";
++ break;
++ case DLM_RECO_NODE_DATA_RECEIVING:
++ state = "RECEIVING";
++ break;
++ case DLM_RECO_NODE_DATA_REQUESTED:
++ state = "REQUESTED";
++ break;
++ case DLM_RECO_NODE_DATA_DONE:
++ state = "DONE";
++ break;
++ case DLM_RECO_NODE_DATA_FINALIZE_SENT:
++ state = "FINALIZE-SENT";
++ break;
++ default:
++ state = "BAD";
++ break;
++ }
++ out += snprintf(db->buf + out, db->len - out, "\t%u - %s\n",
++ node->node_num, state);
++ }
++
++ spin_unlock(&dlm->spinlock);
++
++ return out;
++}
++
++static int debug_state_open(struct inode *inode, struct file *file)
++{
++ struct dlm_ctxt *dlm = inode->i_private;
++ struct debug_buffer *db = NULL;
++
++ db = debug_buffer_allocate();
++ if (!db)
++ goto bail;
++
++ db->len = debug_state_print(dlm, db);
++
++ file->private_data = db;
++
++ return 0;
++bail:
++ return -ENOMEM;
++}
++
++static struct file_operations debug_state_fops = {
++ .open = debug_state_open,
++ .release = debug_buffer_release,
++ .read = debug_buffer_read,
++ .llseek = debug_buffer_llseek,
++};
++/* end - debug state funcs */
++
++/* files in subroot */
++int dlm_debug_init(struct dlm_ctxt *dlm)
++{
++ struct dlm_debug_ctxt *dc = dlm->dlm_debug_ctxt;
++
++ /* for dumping dlm_ctxt */
++ dc->debug_state_dentry = debugfs_create_file(DLM_DEBUGFS_DLM_STATE,
++ S_IFREG|S_IRUSR,
++ dlm->dlm_debugfs_subroot,
++ dlm, &debug_state_fops);
++ if (!dc->debug_state_dentry) {
++ mlog_errno(-ENOMEM);
++ goto bail;
++ }
++
++ /* for dumping lockres */
++ dc->debug_lockres_dentry =
++ debugfs_create_file(DLM_DEBUGFS_LOCKING_STATE,
++ S_IFREG|S_IRUSR,
++ dlm->dlm_debugfs_subroot,
++ dlm, &debug_lockres_fops);
++ if (!dc->debug_lockres_dentry) {
++ mlog_errno(-ENOMEM);
++ goto bail;
++ }
++
++ /* for dumping mles */
++ dc->debug_mle_dentry = debugfs_create_file(DLM_DEBUGFS_MLE_STATE,
++ S_IFREG|S_IRUSR,
++ dlm->dlm_debugfs_subroot,
++ dlm, &debug_mle_fops);
++ if (!dc->debug_mle_dentry) {
++ mlog_errno(-ENOMEM);
++ goto bail;
++ }
++
++ /* for dumping lockres on the purge list */
++ dc->debug_purgelist_dentry =
++ debugfs_create_file(DLM_DEBUGFS_PURGE_LIST,
++ S_IFREG|S_IRUSR,
++ dlm->dlm_debugfs_subroot,
++ dlm, &debug_purgelist_fops);
++ if (!dc->debug_purgelist_dentry) {
++ mlog_errno(-ENOMEM);
++ goto bail;
++ }
++
++ dlm_debug_get(dc);
++ return 0;
++
++bail:
++ dlm_debug_shutdown(dlm);
++ return -ENOMEM;
++}
++
++void dlm_debug_shutdown(struct dlm_ctxt *dlm)
++{
++ struct dlm_debug_ctxt *dc = dlm->dlm_debug_ctxt;
++
++ if (dc) {
++ if (dc->debug_purgelist_dentry)
++ debugfs_remove(dc->debug_purgelist_dentry);
++ if (dc->debug_mle_dentry)
++ debugfs_remove(dc->debug_mle_dentry);
++ if (dc->debug_lockres_dentry)
++ debugfs_remove(dc->debug_lockres_dentry);
++ if (dc->debug_state_dentry)
++ debugfs_remove(dc->debug_state_dentry);
++ dlm_debug_put(dc);
++ }
++}
++
++/* subroot - domain dir */
++int dlm_create_debugfs_subroot(struct dlm_ctxt *dlm)
++{
++ dlm->dlm_debugfs_subroot = debugfs_create_dir(dlm->name,
++ dlm_debugfs_root);
++ if (!dlm->dlm_debugfs_subroot) {
++ mlog_errno(-ENOMEM);
++ goto bail;
++ }
++
++ dlm->dlm_debug_ctxt = kzalloc(sizeof(struct dlm_debug_ctxt),
++ GFP_KERNEL);
++ if (!dlm->dlm_debug_ctxt) {
++ mlog_errno(-ENOMEM);
++ goto bail;
++ }
++ kref_init(&dlm->dlm_debug_ctxt->debug_refcnt);
++
++ return 0;
++bail:
++ dlm_destroy_debugfs_subroot(dlm);
++ return -ENOMEM;
++}
++
++void dlm_destroy_debugfs_subroot(struct dlm_ctxt *dlm)
++{
++ if (dlm->dlm_debugfs_subroot)
++ debugfs_remove(dlm->dlm_debugfs_subroot);
++}
++
++/* debugfs root */
++int dlm_create_debugfs_root(void)
++{
++ dlm_debugfs_root = debugfs_create_dir(DLM_DEBUGFS_DIR, NULL);
++ if (!dlm_debugfs_root) {
++ mlog_errno(-ENOMEM);
++ return -ENOMEM;
++ }
++ return 0;
++}
++
++void dlm_destroy_debugfs_root(void)
++{
++ if (dlm_debugfs_root)
++ debugfs_remove(dlm_debugfs_root);
++}
++#endif /* CONFIG_DEBUG_FS */
+diff --git a/fs/ocfs2/dlm/dlmdebug.h b/fs/ocfs2/dlm/dlmdebug.h
+new file mode 100644
+index 0000000..d34a62a
+--- /dev/null
++++ b/fs/ocfs2/dlm/dlmdebug.h
+@@ -0,0 +1,86 @@
++/* -*- mode: c; c-basic-offset: 8; -*-
++ * vim: noexpandtab sw=8 ts=8 sts=0:
++ *
++ * dlmdebug.h
++ *
++ * Copyright (C) 2008 Oracle. 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 021110-1307, USA.
++ *
++ */
++
++#ifndef DLMDEBUG_H
++#define DLMDEBUG_H
++
++void dlm_print_one_mle(struct dlm_master_list_entry *mle);
++
++#ifdef CONFIG_DEBUG_FS
++
++struct dlm_debug_ctxt {
++ struct kref debug_refcnt;
++ struct dentry *debug_state_dentry;
++ struct dentry *debug_lockres_dentry;
++ struct dentry *debug_mle_dentry;
++ struct dentry *debug_purgelist_dentry;
++};
++
++struct debug_buffer {
++ int len;
++ char *buf;
++};
++
++struct debug_lockres {
++ int dl_len;
++ char *dl_buf;
++ struct dlm_ctxt *dl_ctxt;
++ struct dlm_lock_resource *dl_res;
++};
++
++int dlm_debug_init(struct dlm_ctxt *dlm);
++void dlm_debug_shutdown(struct dlm_ctxt *dlm);
++
++int dlm_create_debugfs_subroot(struct dlm_ctxt *dlm);
++void dlm_destroy_debugfs_subroot(struct dlm_ctxt *dlm);
++
++int dlm_create_debugfs_root(void);
++void dlm_destroy_debugfs_root(void);
++
++#else
++
++static int dlm_debug_init(struct dlm_ctxt *dlm)
++{
++ return 0;
++}
++static void dlm_debug_shutdown(struct dlm_ctxt *dlm)
++{
++}
++static int dlm_create_debugfs_subroot(struct dlm_ctxt *dlm)
++{
++ return 0;
++}
++static void dlm_destroy_debugfs_subroot(struct dlm_ctxt *dlm)
++{
++}
++static int dlm_create_debugfs_root(void)
++{
++ return 0;
++}
++static void dlm_destroy_debugfs_root(void)
++{
++}
++
++#endif /* CONFIG_DEBUG_FS */
++#endif /* DLMDEBUG_H */
+diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
+index 0879d86..63f8125 100644
+--- a/fs/ocfs2/dlm/dlmdomain.c
++++ b/fs/ocfs2/dlm/dlmdomain.c
+@@ -33,6 +33,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/delay.h>
+ #include <linux/err.h>
++#include <linux/debugfs.h>
+
+ #include "cluster/heartbeat.h"
+ #include "cluster/nodemanager.h"
+@@ -40,8 +41,8 @@
+
+ #include "dlmapi.h"
+ #include "dlmcommon.h"
+-
+ #include "dlmdomain.h"
++#include "dlmdebug.h"
+
+ #include "dlmver.h"
+
+@@ -298,6 +299,8 @@ static int dlm_wait_on_domain_helper(const char *domain)
+
+ static void dlm_free_ctxt_mem(struct dlm_ctxt *dlm)
+ {
++ dlm_destroy_debugfs_subroot(dlm);
++
+ if (dlm->lockres_hash)
+ dlm_free_pagevec((void **)dlm->lockres_hash, DLM_HASH_PAGES);
+
+@@ -395,6 +398,7 @@ static void dlm_destroy_dlm_worker(struct dlm_ctxt *dlm)
+ static void dlm_complete_dlm_shutdown(struct dlm_ctxt *dlm)
+ {
+ dlm_unregister_domain_handlers(dlm);
++ dlm_debug_shutdown(dlm);
+ dlm_complete_thread(dlm);
+ dlm_complete_recovery_thread(dlm);
+ dlm_destroy_dlm_worker(dlm);
+@@ -644,6 +648,7 @@ int dlm_shutting_down(struct dlm_ctxt *dlm)
+ void dlm_unregister_domain(struct dlm_ctxt *dlm)
+ {
+ int leave = 0;
++ struct dlm_lock_resource *res;
+
+ spin_lock(&dlm_domain_lock);
+ BUG_ON(dlm->dlm_state != DLM_CTXT_JOINED);
+@@ -673,6 +678,15 @@ void dlm_unregister_domain(struct dlm_ctxt *dlm)
+ msleep(500);
+ mlog(0, "%s: more migration to do\n", dlm->name);
+ }
++
++ /* This list should be empty. If not, print remaining lockres */
++ if (!list_empty(&dlm->tracking_list)) {
++ mlog(ML_ERROR, "Following lockres' are still on the "
++ "tracking list:\n");
++ list_for_each_entry(res, &dlm->tracking_list, tracking)
++ dlm_print_one_lock_resource(res);
++ }
++
+ dlm_mark_domain_leaving(dlm);
+ dlm_leave_domain(dlm);
+ dlm_complete_dlm_shutdown(dlm);
+@@ -1405,6 +1419,12 @@ static int dlm_join_domain(struct dlm_ctxt *dlm)
+ goto bail;
+ }
+
++ status = dlm_debug_init(dlm);
++ if (status < 0) {
++ mlog_errno(status);
++ goto bail;
++ }
++
+ status = dlm_launch_thread(dlm);
+ if (status < 0) {
+ mlog_errno(status);
+@@ -1472,6 +1492,7 @@ bail:
+
+ if (status) {
+ dlm_unregister_domain_handlers(dlm);
++ dlm_debug_shutdown(dlm);
+ dlm_complete_thread(dlm);
+ dlm_complete_recovery_thread(dlm);
+ dlm_destroy_dlm_worker(dlm);
+@@ -1484,6 +1505,7 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain,
+ u32 key)
+ {
+ int i;
++ int ret;
+ struct dlm_ctxt *dlm = NULL;
+
+ dlm = kzalloc(sizeof(*dlm), GFP_KERNEL);
+@@ -1516,6 +1538,15 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain,
+ dlm->key = key;
+ dlm->node_num = o2nm_this_node();
+
++ ret = dlm_create_debugfs_subroot(dlm);
++ if (ret < 0) {
++ dlm_free_pagevec((void **)dlm->lockres_hash, DLM_HASH_PAGES);
++ kfree(dlm->name);
++ kfree(dlm);
++ dlm = NULL;
++ goto leave;
++ }
++
+ spin_lock_init(&dlm->spinlock);
+ spin_lock_init(&dlm->master_lock);
+ spin_lock_init(&dlm->ast_lock);
+@@ -1526,6 +1557,7 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain,
+ INIT_LIST_HEAD(&dlm->reco.node_data);
+ INIT_LIST_HEAD(&dlm->purge_list);
+ INIT_LIST_HEAD(&dlm->dlm_domain_handlers);
++ INIT_LIST_HEAD(&dlm->tracking_list);
+ dlm->reco.state = 0;
+
+ INIT_LIST_HEAD(&dlm->pending_asts);
+@@ -1816,21 +1848,49 @@ static int __init dlm_init(void)
+ dlm_print_version();
+
+ status = dlm_init_mle_cache();
+- if (status)
+- return -1;
++ if (status) {
++ mlog(ML_ERROR, "Could not create o2dlm_mle slabcache\n");
++ goto error;
++ }
++
++ status = dlm_init_master_caches();
++ if (status) {
++ mlog(ML_ERROR, "Could not create o2dlm_lockres and "
++ "o2dlm_lockname slabcaches\n");
++ goto error;
++ }
++
++ status = dlm_init_lock_cache();
++ if (status) {
++ mlog(ML_ERROR, "Count not create o2dlm_lock slabcache\n");
++ goto error;
++ }
+
+ status = dlm_register_net_handlers();
+ if (status) {
+- dlm_destroy_mle_cache();
+- return -1;
++ mlog(ML_ERROR, "Unable to register network handlers\n");
++ goto error;
+ }
+
++ status = dlm_create_debugfs_root();
++ if (status)
++ goto error;
++
+ return 0;
++error:
++ dlm_unregister_net_handlers();
++ dlm_destroy_lock_cache();
++ dlm_destroy_master_caches();
++ dlm_destroy_mle_cache();
++ return -1;
+ }
+
+ static void __exit dlm_exit (void)
+ {
++ dlm_destroy_debugfs_root();
+ dlm_unregister_net_handlers();
++ dlm_destroy_lock_cache();
++ dlm_destroy_master_caches();
+ dlm_destroy_mle_cache();
+ }
+
+diff --git a/fs/ocfs2/dlm/dlmlock.c b/fs/ocfs2/dlm/dlmlock.c
+index 52578d9..83a9f29 100644
+--- a/fs/ocfs2/dlm/dlmlock.c
++++ b/fs/ocfs2/dlm/dlmlock.c
+@@ -53,6 +53,8 @@
+ #define MLOG_MASK_PREFIX ML_DLM
+ #include "cluster/masklog.h"
+
++static struct kmem_cache *dlm_lock_cache = NULL;
++
+ static DEFINE_SPINLOCK(dlm_cookie_lock);
+ static u64 dlm_next_cookie = 1;
+
+@@ -64,6 +66,22 @@ static void dlm_init_lock(struct dlm_lock *newlock, int type,
+ static void dlm_lock_release(struct kref *kref);
+ static void dlm_lock_detach_lockres(struct dlm_lock *lock);
+
++int dlm_init_lock_cache(void)
++{
++ dlm_lock_cache = kmem_cache_create("o2dlm_lock",
++ sizeof(struct dlm_lock),
++ 0, SLAB_HWCACHE_ALIGN, NULL);
++ if (dlm_lock_cache == NULL)
++ return -ENOMEM;
++ return 0;
++}
++
++void dlm_destroy_lock_cache(void)
++{
++ if (dlm_lock_cache)
++ kmem_cache_destroy(dlm_lock_cache);
++}
++
+ /* Tell us whether we can grant a new lock request.
+ * locking:
+ * caller needs: res->spinlock
+@@ -353,7 +371,7 @@ static void dlm_lock_release(struct kref *kref)
+ mlog(0, "freeing kernel-allocated lksb\n");
+ kfree(lock->lksb);
+ }
+- kfree(lock);
++ kmem_cache_free(dlm_lock_cache, lock);
+ }
+
+ /* associate a lock with it's lockres, getting a ref on the lockres */
+@@ -412,7 +430,7 @@ struct dlm_lock * dlm_new_lock(int type, u8 node, u64 cookie,
+ struct dlm_lock *lock;
+ int kernel_allocated = 0;
+
+- lock = kzalloc(sizeof(*lock), GFP_NOFS);
++ lock = (struct dlm_lock *) kmem_cache_zalloc(dlm_lock_cache, GFP_NOFS);
+ if (!lock)
+ return NULL;
+
+diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
+index ea6b895..efc015c 100644
+--- a/fs/ocfs2/dlm/dlmmaster.c
++++ b/fs/ocfs2/dlm/dlmmaster.c
+@@ -48,47 +48,11 @@
+ #include "dlmapi.h"
+ #include "dlmcommon.h"
+ #include "dlmdomain.h"
++#include "dlmdebug.h"
+
+ #define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_MASTER)
+ #include "cluster/masklog.h"
+
+-enum dlm_mle_type {
+- DLM_MLE_BLOCK,
+- DLM_MLE_MASTER,
+- DLM_MLE_MIGRATION
+-};
+-
+-struct dlm_lock_name
+-{
+- u8 len;
+- u8 name[DLM_LOCKID_NAME_MAX];
+-};
+-
+-struct dlm_master_list_entry
+-{
+- struct list_head list;
+- struct list_head hb_events;
+- struct dlm_ctxt *dlm;
+- spinlock_t spinlock;
+- wait_queue_head_t wq;
+- atomic_t woken;
+- struct kref mle_refs;
+- int inuse;
+- unsigned long maybe_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+- unsigned long vote_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+- unsigned long response_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+- unsigned long node_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+- u8 master;
+- u8 new_master;
+- enum dlm_mle_type type;
+- struct o2hb_callback_func mle_hb_up;
+- struct o2hb_callback_func mle_hb_down;
+- union {
+- struct dlm_lock_resource *res;
+- struct dlm_lock_name name;
+- } u;
+-};
+-
+ static void dlm_mle_node_down(struct dlm_ctxt *dlm,
+ struct dlm_master_list_entry *mle,
+ struct o2nm_node *node,
+@@ -128,98 +92,10 @@ static inline int dlm_mle_equal(struct dlm_ctxt *dlm,
+ return 1;
+ }
+
+-#define dlm_print_nodemap(m) _dlm_print_nodemap(m,#m)
+-static void _dlm_print_nodemap(unsigned long *map, const char *mapname)
+-{
+- int i;
+- printk("%s=[ ", mapname);
+- for (i=0; i<O2NM_MAX_NODES; i++)
+- if (test_bit(i, map))
+- printk("%d ", i);
+- printk("]");
+-}
+-
+-static void dlm_print_one_mle(struct dlm_master_list_entry *mle)
+-{
+- int refs;
+- char *type;
+- char attached;
+- u8 master;
+- unsigned int namelen;
+- const char *name;
+- struct kref *k;
+- unsigned long *maybe = mle->maybe_map,
+- *vote = mle->vote_map,
+- *resp = mle->response_map,
+- *node = mle->node_map;
+-
+- k = &mle->mle_refs;
+- if (mle->type == DLM_MLE_BLOCK)
+- type = "BLK";
+- else if (mle->type == DLM_MLE_MASTER)
+- type = "MAS";
+- else
+- type = "MIG";
+- refs = atomic_read(&k->refcount);
+- master = mle->master;
+- attached = (list_empty(&mle->hb_events) ? 'N' : 'Y');
+-
+- if (mle->type != DLM_MLE_MASTER) {
+- namelen = mle->u.name.len;
+- name = mle->u.name.name;
+- } else {
+- namelen = mle->u.res->lockname.len;
+- name = mle->u.res->lockname.name;
+- }
+-
+- mlog(ML_NOTICE, "%.*s: %3s refs=%3d mas=%3u new=%3u evt=%c inuse=%d ",
+- namelen, name, type, refs, master, mle->new_master, attached,
+- mle->inuse);
+- dlm_print_nodemap(maybe);
+- printk(", ");
+- dlm_print_nodemap(vote);
+- printk(", ");
+- dlm_print_nodemap(resp);
+- printk(", ");
+- dlm_print_nodemap(node);
+- printk(", ");
+- printk("\n");
+-}
+-
+-#if 0
+-/* Code here is included but defined out as it aids debugging */
+-
+-static void dlm_dump_mles(struct dlm_ctxt *dlm)
+-{
+- struct dlm_master_list_entry *mle;
+-
+- mlog(ML_NOTICE, "dumping all mles for domain %s:\n", dlm->name);
+- spin_lock(&dlm->master_lock);
+- list_for_each_entry(mle, &dlm->master_list, list)
+- dlm_print_one_mle(mle);
+- spin_unlock(&dlm->master_lock);
+-}
+-
+-int dlm_dump_all_mles(const char __user *data, unsigned int len)
+-{
+- struct dlm_ctxt *dlm;
+-
+- spin_lock(&dlm_domain_lock);
+- list_for_each_entry(dlm, &dlm_domains, list) {
+- mlog(ML_NOTICE, "found dlm: %p, name=%s\n", dlm, dlm->name);
+- dlm_dump_mles(dlm);
+- }
+- spin_unlock(&dlm_domain_lock);
+- return len;
+-}
+-EXPORT_SYMBOL_GPL(dlm_dump_all_mles);
+-
+-#endif /* 0 */
+-
+-
++static struct kmem_cache *dlm_lockres_cache = NULL;
++static struct kmem_cache *dlm_lockname_cache = NULL;
+ static struct kmem_cache *dlm_mle_cache = NULL;
+
+-
+ static void dlm_mle_release(struct kref *kref);
+ static void dlm_init_mle(struct dlm_master_list_entry *mle,
+ enum dlm_mle_type type,
+@@ -507,7 +383,7 @@ static void dlm_mle_node_up(struct dlm_ctxt *dlm,
+
+ int dlm_init_mle_cache(void)
+ {
+- dlm_mle_cache = kmem_cache_create("dlm_mle_cache",
++ dlm_mle_cache = kmem_cache_create("o2dlm_mle",
+ sizeof(struct dlm_master_list_entry),
+ 0, SLAB_HWCACHE_ALIGN,
+ NULL);
+@@ -560,6 +436,35 @@ static void dlm_mle_release(struct kref *kref)
+ * LOCK RESOURCE FUNCTIONS
+ */
+
++int dlm_init_master_caches(void)
++{
++ dlm_lockres_cache = kmem_cache_create("o2dlm_lockres",
++ sizeof(struct dlm_lock_resource),
++ 0, SLAB_HWCACHE_ALIGN, NULL);
++ if (!dlm_lockres_cache)
++ goto bail;
++
++ dlm_lockname_cache = kmem_cache_create("o2dlm_lockname",
++ DLM_LOCKID_NAME_MAX, 0,
++ SLAB_HWCACHE_ALIGN, NULL);
++ if (!dlm_lockname_cache)
++ goto bail;
++
++ return 0;
++bail:
++ dlm_destroy_master_caches();
++ return -ENOMEM;
++}
++
++void dlm_destroy_master_caches(void)
++{
++ if (dlm_lockname_cache)
++ kmem_cache_destroy(dlm_lockname_cache);
++
++ if (dlm_lockres_cache)
++ kmem_cache_destroy(dlm_lockres_cache);
++}
++
+ static void dlm_set_lockres_owner(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ u8 owner)
+@@ -610,6 +515,14 @@ static void dlm_lockres_release(struct kref *kref)
+ mlog(0, "destroying lockres %.*s\n", res->lockname.len,
+ res->lockname.name);
+
++ if (!list_empty(&res->tracking))
++ list_del_init(&res->tracking);
++ else {
++ mlog(ML_ERROR, "Resource %.*s not on the Tracking list\n",
++ res->lockname.len, res->lockname.name);
++ dlm_print_one_lock_resource(res);
++ }
++
+ if (!hlist_unhashed(&res->hash_node) ||
+ !list_empty(&res->granted) ||
+ !list_empty(&res->converting) ||
+@@ -642,9 +555,9 @@ static void dlm_lockres_release(struct kref *kref)
+ BUG_ON(!list_empty(&res->recovering));
+ BUG_ON(!list_empty(&res->purge));
+
+- kfree(res->lockname.name);
++ kmem_cache_free(dlm_lockname_cache, (void *)res->lockname.name);
+
+- kfree(res);
++ kmem_cache_free(dlm_lockres_cache, res);
+ }
+
+ void dlm_lockres_put(struct dlm_lock_resource *res)
+@@ -677,6 +590,7 @@ static void dlm_init_lockres(struct dlm_ctxt *dlm,
+ INIT_LIST_HEAD(&res->dirty);
+ INIT_LIST_HEAD(&res->recovering);
+ INIT_LIST_HEAD(&res->purge);
++ INIT_LIST_HEAD(&res->tracking);
+ atomic_set(&res->asts_reserved, 0);
+ res->migration_pending = 0;
+ res->inflight_locks = 0;
+@@ -692,6 +606,8 @@ static void dlm_init_lockres(struct dlm_ctxt *dlm,
+
+ res->last_used = 0;
+
++ list_add_tail(&res->tracking, &dlm->tracking_list);
++
+ memset(res->lvb, 0, DLM_LVB_LEN);
+ memset(res->refmap, 0, sizeof(res->refmap));
+ }
+@@ -700,20 +616,28 @@ struct dlm_lock_resource *dlm_new_lockres(struct dlm_ctxt *dlm,
+ const char *name,
+ unsigned int namelen)
+ {
+- struct dlm_lock_resource *res;
++ struct dlm_lock_resource *res = NULL;
+
+- res = kmalloc(sizeof(struct dlm_lock_resource), GFP_NOFS);
++ res = (struct dlm_lock_resource *)
++ kmem_cache_zalloc(dlm_lockres_cache, GFP_NOFS);
+ if (!res)
+- return NULL;
++ goto error;
+
+- res->lockname.name = kmalloc(namelen, GFP_NOFS);
+- if (!res->lockname.name) {
+- kfree(res);
+- return NULL;
+- }
++ res->lockname.name = (char *)
++ kmem_cache_zalloc(dlm_lockname_cache, GFP_NOFS);
++ if (!res->lockname.name)
++ goto error;
+
+ dlm_init_lockres(dlm, res, name, namelen);
+ return res;
++
++error:
++ if (res && res->lockname.name)
++ kmem_cache_free(dlm_lockname_cache, (void *)res->lockname.name);
++
++ if (res)
++ kmem_cache_free(dlm_lockres_cache, res);
++ return NULL;
+ }
+
+ void __dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm,
+diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
+index 1f1873b..394d25a 100644
+--- a/fs/ocfs2/dlmglue.c
++++ b/fs/ocfs2/dlmglue.c
+@@ -27,18 +27,11 @@
+ #include <linux/slab.h>
+ #include <linux/highmem.h>
+ #include <linux/mm.h>
+-#include <linux/crc32.h>
+ #include <linux/kthread.h>
+ #include <linux/pagemap.h>
+ #include <linux/debugfs.h>
+ #include <linux/seq_file.h>
+
+-#include <cluster/heartbeat.h>
+-#include <cluster/nodemanager.h>
+-#include <cluster/tcp.h>
+-
+-#include <dlm/dlmapi.h>
+-
+ #define MLOG_MASK_PREFIX ML_DLM_GLUE
+ #include <cluster/masklog.h>
+
+@@ -53,6 +46,7 @@
+ #include "heartbeat.h"
+ #include "inode.h"
+ #include "journal.h"
++#include "stackglue.h"
+ #include "slot_map.h"
+ #include "super.h"
+ #include "uptodate.h"
+@@ -113,7 +107,8 @@ static void ocfs2_dump_meta_lvb_info(u64 level,
+ unsigned int line,
+ struct ocfs2_lock_res *lockres)
+ {
+- struct ocfs2_meta_lvb *lvb = (struct ocfs2_meta_lvb *) lockres->l_lksb.lvb;
++ struct ocfs2_meta_lvb *lvb =
++ (struct ocfs2_meta_lvb *)ocfs2_dlm_lvb(&lockres->l_lksb);
+
+ mlog(level, "LVB information for %s (called from %s:%u):\n",
+ lockres->l_name, function, line);
+@@ -259,31 +254,6 @@ static struct ocfs2_lock_res_ops ocfs2_flock_lops = {
+ .flags = 0,
+ };
+
+-/*
+- * This is the filesystem locking protocol version.
+- *
+- * Whenever the filesystem does new things with locks (adds or removes a
+- * lock, orders them differently, does different things underneath a lock),
+- * the version must be changed. The protocol is negotiated when joining
+- * the dlm domain. A node may join the domain if its major version is
+- * identical to all other nodes and its minor version is greater than
+- * or equal to all other nodes. When its minor version is greater than
+- * the other nodes, it will run at the minor version specified by the
+- * other nodes.
+- *
+- * If a locking change is made that will not be compatible with older
+- * versions, the major number must be increased and the minor version set
+- * to zero. If a change merely adds a behavior that can be disabled when
+- * speaking to older versions, the minor version must be increased. If a
+- * change adds a fully backwards compatible change (eg, LVB changes that
+- * are just ignored by older versions), the version does not need to be
+- * updated.
+- */
+-const struct dlm_protocol_version ocfs2_locking_protocol = {
+- .pv_major = OCFS2_LOCKING_PROTOCOL_MAJOR,
+- .pv_minor = OCFS2_LOCKING_PROTOCOL_MINOR,
+-};
+-
+ static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres)
+ {
+ return lockres->l_type == OCFS2_LOCK_TYPE_META ||
+@@ -316,7 +286,7 @@ static inline struct ocfs2_super *ocfs2_get_lockres_osb(struct ocfs2_lock_res *l
+ static int ocfs2_lock_create(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres,
+ int level,
+- int dlm_flags);
++ u32 dlm_flags);
+ static inline int ocfs2_may_continue_on_blocked_lock(struct ocfs2_lock_res *lockres,
+ int wanted);
+ static void ocfs2_cluster_unlock(struct ocfs2_super *osb,
+@@ -330,10 +300,9 @@ static void ocfs2_schedule_blocked_lock(struct ocfs2_super *osb,
+ 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, _stat, _lockres) do { \
+- mlog(ML_ERROR, "Dlm error \"%s\" while calling %s on " \
+- "resource %s: %s\n", dlm_errname(_stat), _func, \
+- _lockres->l_name, dlm_errmsg(_stat)); \
++#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); \
+ } while (0)
+ static int ocfs2_downconvert_thread(void *arg);
+ static void ocfs2_downconvert_on_unlock(struct ocfs2_super *osb,
+@@ -342,12 +311,13 @@ static int ocfs2_inode_lock_update(struct inode *inode,
+ struct buffer_head **bh);
+ static void ocfs2_drop_osb_locks(struct ocfs2_super *osb);
+ static inline int ocfs2_highest_compat_lock_level(int level);
+-static void ocfs2_prepare_downconvert(struct ocfs2_lock_res *lockres,
+- int new_level);
++static unsigned int ocfs2_prepare_downconvert(struct ocfs2_lock_res *lockres,
++ int new_level);
+ static int ocfs2_downconvert_lock(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres,
+ int new_level,
+- int lvb);
++ int lvb,
++ unsigned int generation);
+ static int ocfs2_prepare_cancel_convert(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres);
+ static int ocfs2_cancel_convert(struct ocfs2_super *osb,
+@@ -406,9 +376,9 @@ static void ocfs2_lock_res_init_common(struct ocfs2_super *osb,
+ res->l_ops = ops;
+ res->l_priv = priv;
+
+- res->l_level = LKM_IVMODE;
+- res->l_requested = LKM_IVMODE;
+- res->l_blocking = LKM_IVMODE;
++ res->l_level = DLM_LOCK_IV;
++ res->l_requested = DLM_LOCK_IV;
++ res->l_blocking = DLM_LOCK_IV;
+ res->l_action = OCFS2_AST_INVALID;
+ res->l_unlock_action = OCFS2_UNLOCK_INVALID;
+
+@@ -604,10 +574,10 @@ static inline void ocfs2_inc_holders(struct ocfs2_lock_res *lockres,
+ BUG_ON(!lockres);
+
+ switch(level) {
+- case LKM_EXMODE:
++ case DLM_LOCK_EX:
+ lockres->l_ex_holders++;
+ break;
+- case LKM_PRMODE:
++ case DLM_LOCK_PR:
+ lockres->l_ro_holders++;
+ break;
+ default:
+@@ -625,11 +595,11 @@ static inline void ocfs2_dec_holders(struct ocfs2_lock_res *lockres,
+ BUG_ON(!lockres);
+
+ switch(level) {
+- case LKM_EXMODE:
++ case DLM_LOCK_EX:
+ BUG_ON(!lockres->l_ex_holders);
+ lockres->l_ex_holders--;
+ break;
+- case LKM_PRMODE:
++ case DLM_LOCK_PR:
+ BUG_ON(!lockres->l_ro_holders);
+ lockres->l_ro_holders--;
+ break;
+@@ -644,12 +614,12 @@ static inline void ocfs2_dec_holders(struct ocfs2_lock_res *lockres,
+ * lock types are added. */
+ static inline int ocfs2_highest_compat_lock_level(int level)
+ {
+- int new_level = LKM_EXMODE;
++ int new_level = DLM_LOCK_EX;
+
+- if (level == LKM_EXMODE)
+- new_level = LKM_NLMODE;
+- else if (level == LKM_PRMODE)
+- new_level = LKM_PRMODE;
++ if (level == DLM_LOCK_EX)
++ new_level = DLM_LOCK_NL;
++ else if (level == DLM_LOCK_PR)
++ new_level = DLM_LOCK_PR;
+ return new_level;
+ }
+
+@@ -688,12 +658,12 @@ static inline void ocfs2_generic_handle_downconvert_action(struct ocfs2_lock_res
+ BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BUSY));
+ BUG_ON(!(lockres->l_flags & OCFS2_LOCK_ATTACHED));
+ BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BLOCKED));
+- BUG_ON(lockres->l_blocking <= LKM_NLMODE);
++ BUG_ON(lockres->l_blocking <= DLM_LOCK_NL);
+
+ lockres->l_level = lockres->l_requested;
+ if (lockres->l_level <=
+ ocfs2_highest_compat_lock_level(lockres->l_blocking)) {
+- lockres->l_blocking = LKM_NLMODE;
++ lockres->l_blocking = DLM_LOCK_NL;
+ lockres_clear_flags(lockres, OCFS2_LOCK_BLOCKED);
+ }
+ lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
+@@ -712,7 +682,7 @@ static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lo
+ * information is already up to data. Convert from NL to
+ * *anything* however should mark ourselves as needing an
+ * update */
+- if (lockres->l_level == LKM_NLMODE &&
++ if (lockres->l_level == DLM_LOCK_NL &&
+ lockres->l_ops->flags & LOCK_TYPE_REQUIRES_REFRESH)
+ lockres_or_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH);
+
+@@ -729,7 +699,7 @@ static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *loc
+ BUG_ON((!(lockres->l_flags & OCFS2_LOCK_BUSY)));
+ BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED);
+
+- if (lockres->l_requested > LKM_NLMODE &&
++ if (lockres->l_requested > DLM_LOCK_NL &&
+ !(lockres->l_flags & OCFS2_LOCK_LOCAL) &&
+ lockres->l_ops->flags & LOCK_TYPE_REQUIRES_REFRESH)
+ lockres_or_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH);
+@@ -767,6 +737,113 @@ static int ocfs2_generic_handle_bast(struct ocfs2_lock_res *lockres,
+ return needs_downconvert;
+ }
+
++/*
++ * OCFS2_LOCK_PENDING and l_pending_gen.
++ *
++ * Why does OCFS2_LOCK_PENDING exist? To close a race between setting
++ * OCFS2_LOCK_BUSY and calling ocfs2_dlm_lock(). See ocfs2_unblock_lock()
++ * for more details on the race.
++ *
++ * OCFS2_LOCK_PENDING closes the race quite nicely. However, it introduces
++ * a race on itself. In o2dlm, we can get the ast before ocfs2_dlm_lock()
++ * returns. The ast clears OCFS2_LOCK_BUSY, and must therefore clear
++ * OCFS2_LOCK_PENDING at the same time. When ocfs2_dlm_lock() returns,
++ * the caller is going to try to clear PENDING again. If nothing else is
++ * happening, __lockres_clear_pending() sees PENDING is unset and does
++ * nothing.
++ *
++ * But what if another path (eg downconvert thread) has just started a
++ * new locking action? The other path has re-set PENDING. Our path
++ * cannot clear PENDING, because that will re-open the original race
++ * window.
++ *
++ * [Example]
++ *
++ * ocfs2_meta_lock()
++ * ocfs2_cluster_lock()
++ * set BUSY
++ * set PENDING
++ * drop l_lock
++ * ocfs2_dlm_lock()
++ * ocfs2_locking_ast() ocfs2_downconvert_thread()
++ * clear PENDING ocfs2_unblock_lock()
++ * take_l_lock
++ * !BUSY
++ * ocfs2_prepare_downconvert()
++ * set BUSY
++ * set PENDING
++ * drop l_lock
++ * take l_lock
++ * clear PENDING
++ * drop l_lock
++ * <window>
++ * ocfs2_dlm_lock()
++ *
++ * So as you can see, we now have a window where l_lock is not held,
++ * PENDING is not set, and ocfs2_dlm_lock() has not been called.
++ *
++ * The core problem is that ocfs2_cluster_lock() has cleared the PENDING
++ * set by ocfs2_prepare_downconvert(). That wasn't nice.
++ *
++ * To solve this we introduce l_pending_gen. A call to
++ * lockres_clear_pending() will only do so when it is passed a generation
++ * number that matches the lockres. lockres_set_pending() will return the
++ * current generation number. When ocfs2_cluster_lock() goes to clear
++ * PENDING, it passes the generation it got from set_pending(). In our
++ * example above, the generation numbers will *not* match. Thus,
++ * ocfs2_cluster_lock() will not clear the PENDING set by
++ * ocfs2_prepare_downconvert().
++ */
++
++/* Unlocked version for ocfs2_locking_ast() */
++static void __lockres_clear_pending(struct ocfs2_lock_res *lockres,
++ unsigned int generation,
++ struct ocfs2_super *osb)
++{
++ assert_spin_locked(&lockres->l_lock);
++
++ /*
++ * The ast and locking functions can race us here. The winner
++ * will clear pending, the loser will not.
++ */
++ if (!(lockres->l_flags & OCFS2_LOCK_PENDING) ||
++ (lockres->l_pending_gen != generation))
++ return;
++
++ lockres_clear_flags(lockres, OCFS2_LOCK_PENDING);
++ lockres->l_pending_gen++;
++
++ /*
++ * The downconvert thread may have skipped us because we
++ * were PENDING. Wake it up.
++ */
++ if (lockres->l_flags & OCFS2_LOCK_BLOCKED)
++ ocfs2_wake_downconvert_thread(osb);
++}
++
++/* Locked version for callers of ocfs2_dlm_lock() */
++static void lockres_clear_pending(struct ocfs2_lock_res *lockres,
++ unsigned int generation,
++ struct ocfs2_super *osb)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&lockres->l_lock, flags);
++ __lockres_clear_pending(lockres, generation, osb);
++ spin_unlock_irqrestore(&lockres->l_lock, flags);
++}
++
++static unsigned int lockres_set_pending(struct ocfs2_lock_res *lockres)
++{
++ assert_spin_locked(&lockres->l_lock);
++ BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BUSY));
++
++ lockres_or_flags(lockres, OCFS2_LOCK_PENDING);
++
++ return lockres->l_pending_gen;
++}
++
++
+ static void ocfs2_blocking_ast(void *opaque, int level)
+ {
+ struct ocfs2_lock_res *lockres = opaque;
+@@ -774,7 +851,7 @@ static void ocfs2_blocking_ast(void *opaque, int level)
+ int needs_downconvert;
+ unsigned long flags;
+
+- BUG_ON(level <= LKM_NLMODE);
++ BUG_ON(level <= DLM_LOCK_NL);
+
+ mlog(0, "BAST fired for lockres %s, blocking %d, level %d type %s\n",
+ lockres->l_name, level, lockres->l_level,
+@@ -801,14 +878,22 @@ static void ocfs2_blocking_ast(void *opaque, int level)
+ static void ocfs2_locking_ast(void *opaque)
+ {
+ struct ocfs2_lock_res *lockres = opaque;
+- struct dlm_lockstatus *lksb = &lockres->l_lksb;
++ struct ocfs2_super *osb = ocfs2_get_lockres_osb(lockres);
+ unsigned long flags;
++ int status;
+
+ spin_lock_irqsave(&lockres->l_lock, flags);
+
+- if (lksb->status != DLM_NORMAL) {
+- mlog(ML_ERROR, "lockres %s: lksb status value of %u!\n",
+- lockres->l_name, lksb->status);
++ status = ocfs2_dlm_lock_status(&lockres->l_lksb);
++
++ if (status == -EAGAIN) {
++ lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
++ goto out;
++ }
++
++ if (status) {
++ mlog(ML_ERROR, "lockres %s: lksb status value of %d!\n",
++ lockres->l_name, status);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+ return;
+ }
+@@ -831,11 +916,23 @@ static void ocfs2_locking_ast(void *opaque)
+ lockres->l_unlock_action);
+ BUG();
+ }
+-
++out:
+ /* set it to something invalid so if we get called again we
+ * can catch it. */
+ lockres->l_action = OCFS2_AST_INVALID;
+
++ /* Did we try to cancel this lock? Clear that state */
++ if (lockres->l_unlock_action == OCFS2_UNLOCK_CANCEL_CONVERT)
++ lockres->l_unlock_action = OCFS2_UNLOCK_INVALID;
++
++ /*
++ * We may have beaten the locking functions here. We certainly
++ * know that dlm_lock() has been called :-)
++ * Because we can't have two lock calls in flight at once, we
++ * can use lockres->l_pending_gen.
++ */
++ __lockres_clear_pending(lockres, lockres->l_pending_gen, osb);
++
+ wake_up(&lockres->l_event);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+ }
+@@ -865,15 +962,15 @@ static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres,
+ static int ocfs2_lock_create(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres,
+ int level,
+- int dlm_flags)
++ u32 dlm_flags)
+ {
+ int ret = 0;
+- enum dlm_status status = DLM_NORMAL;
+ unsigned long flags;
++ unsigned int gen;
+
+ mlog_entry_void();
+
+- mlog(0, "lock %s, level = %d, flags = %d\n", lockres->l_name, level,
++ mlog(0, "lock %s, level = %d, flags = %u\n", lockres->l_name, level,
+ dlm_flags);
+
+ spin_lock_irqsave(&lockres->l_lock, flags);
+@@ -886,24 +983,23 @@ static int ocfs2_lock_create(struct ocfs2_super *osb,
+ lockres->l_action = OCFS2_AST_ATTACH;
+ lockres->l_requested = level;
+ lockres_or_flags(lockres, OCFS2_LOCK_BUSY);
++ gen = lockres_set_pending(lockres);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+- status = dlmlock(osb->dlm,
+- level,
+- &lockres->l_lksb,
+- dlm_flags,
+- lockres->l_name,
+- OCFS2_LOCK_ID_MAX_LEN - 1,
+- ocfs2_locking_ast,
+- lockres,
+- ocfs2_blocking_ast);
+- if (status != DLM_NORMAL) {
+- ocfs2_log_dlm_error("dlmlock", status, lockres);
+- ret = -EINVAL;
++ ret = ocfs2_dlm_lock(osb->cconn,
++ level,
++ &lockres->l_lksb,
++ dlm_flags,
++ lockres->l_name,
++ OCFS2_LOCK_ID_MAX_LEN - 1,
++ lockres);
++ lockres_clear_pending(lockres, gen, osb);
++ if (ret) {
++ ocfs2_log_dlm_error("ocfs2_dlm_lock", ret, lockres);
+ ocfs2_recover_from_dlm_error(lockres, 1);
+ }
+
+- mlog(0, "lock %s, successfull return from dlmlock\n", lockres->l_name);
++ mlog(0, "lock %s, return from ocfs2_dlm_lock\n", lockres->l_name);
+
+ bail:
+ mlog_exit(ret);
+@@ -1016,21 +1112,22 @@ static int ocfs2_wait_for_mask_interruptible(struct ocfs2_mask_waiter *mw,
+ static int ocfs2_cluster_lock(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres,
+ int level,
+- int lkm_flags,
++ u32 lkm_flags,
+ int arg_flags)
+ {
+ struct ocfs2_mask_waiter mw;
+- enum dlm_status status;
+ int wait, catch_signals = !(osb->s_mount_opt & OCFS2_MOUNT_NOINTR);
+ int ret = 0; /* gcc doesn't realize wait = 1 guarantees ret is set */
+ unsigned long flags;
++ unsigned int gen;
++ int noqueue_attempted = 0;
+
+ mlog_entry_void();
+
+ ocfs2_init_mask_waiter(&mw);
+
+ if (lockres->l_ops->flags & LOCK_TYPE_USES_LVB)
+- lkm_flags |= LKM_VALBLK;
++ lkm_flags |= DLM_LKF_VALBLK;
+
+ again:
+ wait = 0;
+@@ -1068,52 +1165,56 @@ again:
+ }
+
+ if (level > lockres->l_level) {
++ if (noqueue_attempted > 0) {
++ ret = -EAGAIN;
++ goto unlock;
++ }
++ if (lkm_flags & DLM_LKF_NOQUEUE)
++ noqueue_attempted = 1;
++
+ if (lockres->l_action != OCFS2_AST_INVALID)
+ mlog(ML_ERROR, "lockres %s has action %u pending\n",
+ lockres->l_name, lockres->l_action);
+
+ if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED)) {
+ lockres->l_action = OCFS2_AST_ATTACH;
+- lkm_flags &= ~LKM_CONVERT;
++ lkm_flags &= ~DLM_LKF_CONVERT;
+ } else {
+ lockres->l_action = OCFS2_AST_CONVERT;
+- lkm_flags |= LKM_CONVERT;
++ lkm_flags |= DLM_LKF_CONVERT;
+ }
+
+ lockres->l_requested = level;
+ lockres_or_flags(lockres, OCFS2_LOCK_BUSY);
++ gen = lockres_set_pending(lockres);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+- BUG_ON(level == LKM_IVMODE);
+- BUG_ON(level == LKM_NLMODE);
++ BUG_ON(level == DLM_LOCK_IV);
++ BUG_ON(level == DLM_LOCK_NL);
+
+ mlog(0, "lock %s, convert from %d to level = %d\n",
+ lockres->l_name, lockres->l_level, level);
+
+ /* call dlm_lock to upgrade lock now */
+- status = dlmlock(osb->dlm,
+- level,
+- &lockres->l_lksb,
+- lkm_flags,
+- lockres->l_name,
+- OCFS2_LOCK_ID_MAX_LEN - 1,
+- ocfs2_locking_ast,
+- lockres,
+- ocfs2_blocking_ast);
+- if (status != DLM_NORMAL) {
+- if ((lkm_flags & LKM_NOQUEUE) &&
+- (status == DLM_NOTQUEUED))
+- ret = -EAGAIN;
+- else {
+- ocfs2_log_dlm_error("dlmlock", status,
+- lockres);
+- ret = -EINVAL;
++ ret = ocfs2_dlm_lock(osb->cconn,
++ level,
++ &lockres->l_lksb,
++ lkm_flags,
++ lockres->l_name,
++ OCFS2_LOCK_ID_MAX_LEN - 1,
++ lockres);
++ lockres_clear_pending(lockres, gen, osb);
++ if (ret) {
++ if (!(lkm_flags & DLM_LKF_NOQUEUE) ||
++ (ret != -EAGAIN)) {
++ ocfs2_log_dlm_error("ocfs2_dlm_lock",
++ ret, lockres);
+ }
+ ocfs2_recover_from_dlm_error(lockres, 1);
+ goto out;
+ }
+
+- mlog(0, "lock %s, successfull return from dlmlock\n",
++ mlog(0, "lock %s, successfull return from ocfs2_dlm_lock\n",
+ lockres->l_name);
+
+ /* At this point we've gone inside the dlm and need to
+@@ -1177,9 +1278,9 @@ static int ocfs2_create_new_lock(struct ocfs2_super *osb,
+ int ex,
+ int local)
+ {
+- int level = ex ? LKM_EXMODE : LKM_PRMODE;
++ int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
+ unsigned long flags;
+- int lkm_flags = local ? LKM_LOCAL : 0;
++ u32 lkm_flags = local ? DLM_LKF_LOCAL : 0;
+
+ spin_lock_irqsave(&lockres->l_lock, flags);
+ BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED);
+@@ -1222,7 +1323,7 @@ int ocfs2_create_new_inode_locks(struct inode *inode)
+ }
+
+ /*
+- * We don't want to use LKM_LOCAL on a meta data lock as they
++ * We don't want to use DLM_LKF_LOCAL on a meta data lock as they
+ * don't use a generation in their lock names.
+ */
+ ret = ocfs2_create_new_lock(osb, &OCFS2_I(inode)->ip_inode_lockres, 1, 0);
+@@ -1261,7 +1362,7 @@ int ocfs2_rw_lock(struct inode *inode, int write)
+
+ lockres = &OCFS2_I(inode)->ip_rw_lockres;
+
+- level = write ? LKM_EXMODE : LKM_PRMODE;
++ level = write ? DLM_LOCK_EX : DLM_LOCK_PR;
+
+ status = ocfs2_cluster_lock(OCFS2_SB(inode->i_sb), lockres, level, 0,
+ 0);
+@@ -1274,7 +1375,7 @@ int ocfs2_rw_lock(struct inode *inode, int write)
+
+ void ocfs2_rw_unlock(struct inode *inode, int write)
+ {
+- int level = write ? LKM_EXMODE : LKM_PRMODE;
++ int level = write ? DLM_LOCK_EX : DLM_LOCK_PR;
+ struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_rw_lockres;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+@@ -1312,7 +1413,7 @@ int ocfs2_open_lock(struct inode *inode)
+ lockres = &OCFS2_I(inode)->ip_open_lockres;
+
+ status = ocfs2_cluster_lock(OCFS2_SB(inode->i_sb), lockres,
+- LKM_PRMODE, 0, 0);
++ DLM_LOCK_PR, 0, 0);
+ if (status < 0)
+ mlog_errno(status);
+
+@@ -1340,16 +1441,16 @@ int ocfs2_try_open_lock(struct inode *inode, int write)
+
+ lockres = &OCFS2_I(inode)->ip_open_lockres;
+
+- level = write ? LKM_EXMODE : LKM_PRMODE;
++ level = write ? DLM_LOCK_EX : DLM_LOCK_PR;
+
+ /*
+ * The file system may already holding a PRMODE/EXMODE open lock.
+- * Since we pass LKM_NOQUEUE, the request won't block waiting on
++ * Since we pass DLM_LKF_NOQUEUE, the request won't block waiting on
+ * other nodes and the -EAGAIN will indicate to the caller that
+ * this inode is still in use.
+ */
+ status = ocfs2_cluster_lock(OCFS2_SB(inode->i_sb), lockres,
+- level, LKM_NOQUEUE, 0);
++ level, DLM_LKF_NOQUEUE, 0);
+
+ out:
+ mlog_exit(status);
+@@ -1374,10 +1475,10 @@ void ocfs2_open_unlock(struct inode *inode)
+
+ if(lockres->l_ro_holders)
+ ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres,
+- LKM_PRMODE);
++ DLM_LOCK_PR);
+ if(lockres->l_ex_holders)
+ ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres,
+- LKM_EXMODE);
++ DLM_LOCK_EX);
+
+ out:
+ mlog_exit_void();
+@@ -1464,7 +1565,7 @@ int ocfs2_file_lock(struct file *file, int ex, int trylock)
+ ocfs2_init_mask_waiter(&mw);
+
+ if ((lockres->l_flags & OCFS2_LOCK_BUSY) ||
+- (lockres->l_level > LKM_NLMODE)) {
++ (lockres->l_level > DLM_LOCK_NL)) {
+ mlog(ML_ERROR,
+ "File lock \"%s\" has busy or locked state: flags: 0x%lx, "
+ "level: %u\n", lockres->l_name, lockres->l_flags,
+@@ -1503,14 +1604,12 @@ int ocfs2_file_lock(struct file *file, int ex, int trylock)
+ lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_BUSY, 0);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+- ret = dlmlock(osb->dlm, level, &lockres->l_lksb, lkm_flags,
+- lockres->l_name, OCFS2_LOCK_ID_MAX_LEN - 1,
+- ocfs2_locking_ast, lockres, ocfs2_blocking_ast);
+- if (ret != DLM_NORMAL) {
+- if (trylock && ret == DLM_NOTQUEUED)
+- ret = -EAGAIN;
+- else {
+- ocfs2_log_dlm_error("dlmlock", ret, lockres);
++ ret = ocfs2_dlm_lock(osb->cconn, level, &lockres->l_lksb, lkm_flags,
++ lockres->l_name, OCFS2_LOCK_ID_MAX_LEN - 1,
++ lockres);
++ if (ret) {
++ if (!trylock || (ret != -EAGAIN)) {
++ ocfs2_log_dlm_error("ocfs2_dlm_lock", ret, lockres);
+ ret = -EINVAL;
+ }
+
+@@ -1537,6 +1636,10 @@ int ocfs2_file_lock(struct file *file, int ex, int trylock)
+ * to just bubble sucess back up to the user.
+ */
+ ret = ocfs2_flock_handle_signal(lockres, level);
++ } else if (!ret && (level > lockres->l_level)) {
++ /* Trylock failed asynchronously */
++ BUG_ON(!trylock);
++ ret = -EAGAIN;
+ }
+
+ out:
+@@ -1549,6 +1652,7 @@ out:
+ void ocfs2_file_unlock(struct file *file)
+ {
+ int ret;
++ unsigned int gen;
+ unsigned long flags;
+ struct ocfs2_file_private *fp = file->private_data;
+ struct ocfs2_lock_res *lockres = &fp->fp_flock;
+@@ -1572,13 +1676,13 @@ void ocfs2_file_unlock(struct file *file)
+ * Fake a blocking ast for the downconvert code.
+ */
+ lockres_or_flags(lockres, OCFS2_LOCK_BLOCKED);
+- lockres->l_blocking = LKM_EXMODE;
++ lockres->l_blocking = DLM_LOCK_EX;
+
+- ocfs2_prepare_downconvert(lockres, LKM_NLMODE);
++ gen = ocfs2_prepare_downconvert(lockres, LKM_NLMODE);
+ lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_BUSY, 0);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+- ret = ocfs2_downconvert_lock(osb, lockres, LKM_NLMODE, 0);
++ ret = ocfs2_downconvert_lock(osb, lockres, LKM_NLMODE, 0, gen);
+ if (ret) {
+ mlog_errno(ret);
+ return;
+@@ -1601,11 +1705,11 @@ static void ocfs2_downconvert_on_unlock(struct ocfs2_super *osb,
+ * condition. */
+ if (lockres->l_flags & OCFS2_LOCK_BLOCKED) {
+ switch(lockres->l_blocking) {
+- case LKM_EXMODE:
++ case DLM_LOCK_EX:
+ if (!lockres->l_ex_holders && !lockres->l_ro_holders)
+ kick = 1;
+ break;
+- case LKM_PRMODE:
++ case DLM_LOCK_PR:
+ if (!lockres->l_ex_holders)
+ kick = 1;
+ break;
+@@ -1648,7 +1752,7 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode)
+
+ mlog_entry_void();
+
+- lvb = (struct ocfs2_meta_lvb *) lockres->l_lksb.lvb;
++ lvb = (struct ocfs2_meta_lvb *)ocfs2_dlm_lvb(&lockres->l_lksb);
+
+ /*
+ * Invalidate the LVB of a deleted inode - this way other
+@@ -1700,7 +1804,7 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode)
+
+ mlog_meta_lvb(0, lockres);
+
+- lvb = (struct ocfs2_meta_lvb *) lockres->l_lksb.lvb;
++ lvb = (struct ocfs2_meta_lvb *)ocfs2_dlm_lvb(&lockres->l_lksb);
+
+ /* We're safe here without the lockres lock... */
+ spin_lock(&oi->ip_lock);
+@@ -1735,7 +1839,8 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode)
+ static inline int ocfs2_meta_lvb_is_trustable(struct inode *inode,
+ struct ocfs2_lock_res *lockres)
+ {
+- struct ocfs2_meta_lvb *lvb = (struct ocfs2_meta_lvb *) lockres->l_lksb.lvb;
++ struct ocfs2_meta_lvb *lvb =
++ (struct ocfs2_meta_lvb *)ocfs2_dlm_lvb(&lockres->l_lksb);
+
+ if (lvb->lvb_version == OCFS2_LVB_VERSION
+ && be32_to_cpu(lvb->lvb_igeneration) == inode->i_generation)
+@@ -1923,7 +2028,8 @@ int ocfs2_inode_lock_full(struct inode *inode,
+ int ex,
+ int arg_flags)
+ {
+- int status, level, dlm_flags, acquired;
++ int status, level, acquired;
++ u32 dlm_flags;
+ struct ocfs2_lock_res *lockres = NULL;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ struct buffer_head *local_bh = NULL;
+@@ -1950,14 +2056,13 @@ int ocfs2_inode_lock_full(struct inode *inode,
+ goto local;
+
+ if (!(arg_flags & OCFS2_META_LOCK_RECOVERY))
+- wait_event(osb->recovery_event,
+- ocfs2_node_map_is_empty(osb, &osb->recovery_map));
++ ocfs2_wait_for_recovery(osb);
+
+ lockres = &OCFS2_I(inode)->ip_inode_lockres;
+- level = ex ? LKM_EXMODE : LKM_PRMODE;
++ level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
+ dlm_flags = 0;
+ if (arg_flags & OCFS2_META_LOCK_NOQUEUE)
+- dlm_flags |= LKM_NOQUEUE;
++ dlm_flags |= DLM_LKF_NOQUEUE;
+
+ status = ocfs2_cluster_lock(osb, lockres, level, dlm_flags, arg_flags);
+ if (status < 0) {
+@@ -1974,8 +2079,7 @@ int ocfs2_inode_lock_full(struct inode *inode,
+ * committed to owning this lock so we don't allow signals to
+ * abort the operation. */
+ if (!(arg_flags & OCFS2_META_LOCK_RECOVERY))
+- wait_event(osb->recovery_event,
+- ocfs2_node_map_is_empty(osb, &osb->recovery_map));
++ ocfs2_wait_for_recovery(osb);
+
+ local:
+ /*
+@@ -2109,7 +2213,7 @@ int ocfs2_inode_lock_atime(struct inode *inode,
+ void ocfs2_inode_unlock(struct inode *inode,
+ int ex)
+ {
+- int level = ex ? LKM_EXMODE : LKM_PRMODE;
++ int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
+ struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_inode_lockres;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+@@ -2130,10 +2234,8 @@ int ocfs2_super_lock(struct ocfs2_super *osb,
+ int ex)
+ {
+ int status = 0;
+- int level = ex ? LKM_EXMODE : LKM_PRMODE;
++ int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
+ struct ocfs2_lock_res *lockres = &osb->osb_super_lockres;
+- struct buffer_head *bh;
+- struct ocfs2_slot_info *si = osb->slot_info;
+
+ mlog_entry_void();
+
+@@ -2159,11 +2261,7 @@ int ocfs2_super_lock(struct ocfs2_super *osb,
+ goto bail;
+ }
+ if (status) {
+- bh = si->si_bh;
+- status = ocfs2_read_block(osb, bh->b_blocknr, &bh, 0,
+- si->si_inode);
+- if (status == 0)
+- ocfs2_update_slot_info(si);
++ status = ocfs2_refresh_slot_info(osb);
+
+ ocfs2_complete_lock_res_refresh(lockres, status);
+
+@@ -2178,7 +2276,7 @@ bail:
+ void ocfs2_super_unlock(struct ocfs2_super *osb,
+ int ex)
+ {
+- int level = ex ? LKM_EXMODE : LKM_PRMODE;
++ int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
+ struct ocfs2_lock_res *lockres = &osb->osb_super_lockres;
+
+ if (!ocfs2_mount_local(osb))
+@@ -2196,7 +2294,7 @@ int ocfs2_rename_lock(struct ocfs2_super *osb)
+ if (ocfs2_mount_local(osb))
+ return 0;
+
+- status = ocfs2_cluster_lock(osb, lockres, LKM_EXMODE, 0, 0);
++ status = ocfs2_cluster_lock(osb, lockres, DLM_LOCK_EX, 0, 0);
+ if (status < 0)
+ mlog_errno(status);
+
+@@ -2208,13 +2306,13 @@ void ocfs2_rename_unlock(struct ocfs2_super *osb)
+ struct ocfs2_lock_res *lockres = &osb->osb_rename_lockres;
+
+ if (!ocfs2_mount_local(osb))
+- ocfs2_cluster_unlock(osb, lockres, LKM_EXMODE);
++ ocfs2_cluster_unlock(osb, lockres, DLM_LOCK_EX);
+ }
+
+ int ocfs2_dentry_lock(struct dentry *dentry, int ex)
+ {
+ int ret;
+- int level = ex ? LKM_EXMODE : LKM_PRMODE;
++ int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
+ struct ocfs2_dentry_lock *dl = dentry->d_fsdata;
+ struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
+
+@@ -2235,7 +2333,7 @@ int ocfs2_dentry_lock(struct dentry *dentry, int ex)
+
+ void ocfs2_dentry_unlock(struct dentry *dentry, int ex)
+ {
+- int level = ex ? LKM_EXMODE : LKM_PRMODE;
++ int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
+ struct ocfs2_dentry_lock *dl = dentry->d_fsdata;
+ struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
+
+@@ -2400,7 +2498,7 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void *v)
+ lockres->l_blocking);
+
+ /* Dump the raw LVB */
+- lvb = lockres->l_lksb.lvb;
++ lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
+ for(i = 0; i < DLM_LVB_LEN; i++)
+ seq_printf(m, "0x%x\t", lvb[i]);
+
+@@ -2504,13 +2602,14 @@ static void ocfs2_dlm_shutdown_debug(struct ocfs2_super *osb)
+ int ocfs2_dlm_init(struct ocfs2_super *osb)
+ {
+ int status = 0;
+- u32 dlm_key;
+- struct dlm_ctxt *dlm = NULL;
++ struct ocfs2_cluster_connection *conn = NULL;
+
+ mlog_entry_void();
+
+- if (ocfs2_mount_local(osb))
++ if (ocfs2_mount_local(osb)) {
++ osb->node_num = 0;
+ goto local;
++ }
+
+ status = ocfs2_dlm_init_debug(osb);
+ if (status < 0) {
+@@ -2527,26 +2626,31 @@ int ocfs2_dlm_init(struct ocfs2_super *osb)
+ goto bail;
+ }
+
+- /* used by the dlm code to make message headers unique, each
+- * node in this domain must agree on this. */
+- dlm_key = crc32_le(0, osb->uuid_str, strlen(osb->uuid_str));
+-
+ /* for now, uuid == domain */
+- dlm = dlm_register_domain(osb->uuid_str, dlm_key,
+- &osb->osb_locking_proto);
+- if (IS_ERR(dlm)) {
+- status = PTR_ERR(dlm);
++ status = ocfs2_cluster_connect(osb->osb_cluster_stack,
++ osb->uuid_str,
++ strlen(osb->uuid_str),
++ ocfs2_do_node_down, osb,
++ &conn);
++ if (status) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+- dlm_register_eviction_cb(dlm, &osb->osb_eviction_cb);
++ status = ocfs2_cluster_this_node(&osb->node_num);
++ if (status < 0) {
++ mlog_errno(status);
++ mlog(ML_ERROR,
++ "could not find this host's node number\n");
++ ocfs2_cluster_disconnect(conn, 0);
++ goto bail;
++ }
+
+ local:
+ ocfs2_super_lock_res_init(&osb->osb_super_lockres, osb);
+ ocfs2_rename_lock_res_init(&osb->osb_rename_lockres, osb);
+
+- osb->dlm = dlm;
++ osb->cconn = conn;
+
+ status = 0;
+ bail:
+@@ -2560,14 +2664,19 @@ bail:
+ return status;
+ }
+
+-void ocfs2_dlm_shutdown(struct ocfs2_super *osb)
++void ocfs2_dlm_shutdown(struct ocfs2_super *osb,
++ int hangup_pending)
+ {
+ mlog_entry_void();
+
+- dlm_unregister_eviction_cb(&osb->osb_eviction_cb);
+-
+ ocfs2_drop_osb_locks(osb);
+
++ /*
++ * Now that we have dropped all locks and ocfs2_dismount_volume()
++ * has disabled recovery, the DLM won't be talking to us. It's
++ * safe to tear things down before disconnecting the cluster.
++ */
++
+ if (osb->dc_task) {
+ kthread_stop(osb->dc_task);
+ osb->dc_task = NULL;
+@@ -2576,15 +2685,15 @@ void ocfs2_dlm_shutdown(struct ocfs2_super *osb)
+ ocfs2_lock_res_free(&osb->osb_super_lockres);
+ ocfs2_lock_res_free(&osb->osb_rename_lockres);
+
+- dlm_unregister_domain(osb->dlm);
+- osb->dlm = NULL;
++ ocfs2_cluster_disconnect(osb->cconn, hangup_pending);
++ osb->cconn = NULL;
+
+ ocfs2_dlm_shutdown_debug(osb);
+
+ mlog_exit_void();
+ }
+
+-static void ocfs2_unlock_ast(void *opaque, enum dlm_status status)
++static void ocfs2_unlock_ast(void *opaque, int error)
+ {
+ struct ocfs2_lock_res *lockres = opaque;
+ unsigned long flags;
+@@ -2595,24 +2704,9 @@ static void ocfs2_unlock_ast(void *opaque, enum dlm_status status)
+ lockres->l_unlock_action);
+
+ spin_lock_irqsave(&lockres->l_lock, flags);
+- /* We tried to cancel a convert request, but it was already
+- * granted. All we want to do here is clear our unlock
+- * state. The wake_up call done at the bottom is redundant
+- * (ocfs2_prepare_cancel_convert doesn't sleep on this) but doesn't
+- * hurt anything anyway */
+- if (status == DLM_CANCELGRANT &&
+- lockres->l_unlock_action == OCFS2_UNLOCK_CANCEL_CONVERT) {
+- mlog(0, "Got cancelgrant for %s\n", lockres->l_name);
+-
+- /* We don't clear the busy flag in this case as it
+- * should have been cleared by the ast which the dlm
+- * has called. */
+- goto complete_unlock;
+- }
+-
+- if (status != DLM_NORMAL) {
+- mlog(ML_ERROR, "Dlm passes status %d for lock %s, "
+- "unlock_action %d\n", status, lockres->l_name,
++ if (error) {
++ mlog(ML_ERROR, "Dlm passes error %d for lock %s, "
++ "unlock_action %d\n", error, lockres->l_name,
+ lockres->l_unlock_action);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+ return;
+@@ -2624,14 +2718,13 @@ static void ocfs2_unlock_ast(void *opaque, enum dlm_status status)
+ lockres->l_action = OCFS2_AST_INVALID;
+ break;
+ case OCFS2_UNLOCK_DROP_LOCK:
+- lockres->l_level = LKM_IVMODE;
++ lockres->l_level = DLM_LOCK_IV;
+ break;
+ default:
+ BUG();
+ }
+
+ lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
+-complete_unlock:
+ lockres->l_unlock_action = OCFS2_UNLOCK_INVALID;
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+@@ -2643,16 +2736,16 @@ complete_unlock:
+ static int ocfs2_drop_lock(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres)
+ {
+- enum dlm_status status;
++ int ret;
+ unsigned long flags;
+- int lkm_flags = 0;
++ u32 lkm_flags = 0;
+
+ /* We didn't get anywhere near actually using this lockres. */
+ if (!(lockres->l_flags & OCFS2_LOCK_INITIALIZED))
+ goto out;
+
+ if (lockres->l_ops->flags & LOCK_TYPE_USES_LVB)
+- lkm_flags |= LKM_VALBLK;
++ lkm_flags |= DLM_LKF_VALBLK;
+
+ spin_lock_irqsave(&lockres->l_lock, flags);
+
+@@ -2678,7 +2771,7 @@ static int ocfs2_drop_lock(struct ocfs2_super *osb,
+
+ if (lockres->l_ops->flags & LOCK_TYPE_USES_LVB) {
+ if (lockres->l_flags & OCFS2_LOCK_ATTACHED &&
+- lockres->l_level == LKM_EXMODE &&
++ lockres->l_level == DLM_LOCK_EX &&
+ !(lockres->l_flags & OCFS2_LOCK_NEEDS_REFRESH))
+ lockres->l_ops->set_lvb(lockres);
+ }
+@@ -2707,15 +2800,15 @@ static int ocfs2_drop_lock(struct ocfs2_super *osb,
+
+ mlog(0, "lock %s\n", lockres->l_name);
+
+- status = dlmunlock(osb->dlm, &lockres->l_lksb, lkm_flags,
+- ocfs2_unlock_ast, lockres);
+- if (status != DLM_NORMAL) {
+- ocfs2_log_dlm_error("dlmunlock", status, lockres);
++ ret = ocfs2_dlm_unlock(osb->cconn, &lockres->l_lksb, lkm_flags,
++ lockres);
++ if (ret) {
++ ocfs2_log_dlm_error("ocfs2_dlm_unlock", ret, lockres);
+ mlog(ML_ERROR, "lockres flags: %lu\n", lockres->l_flags);
+- dlm_print_one_lock(lockres->l_lksb.lockid);
++ ocfs2_dlm_dump_lksb(&lockres->l_lksb);
+ BUG();
+ }
+- mlog(0, "lock %s, successfull return from dlmunlock\n",
++ mlog(0, "lock %s, successfull return from ocfs2_dlm_unlock\n",
+ lockres->l_name);
+
+ ocfs2_wait_on_busy_lock(lockres);
+@@ -2806,15 +2899,15 @@ int ocfs2_drop_inode_locks(struct inode *inode)
+ return status;
+ }
+
+-static void ocfs2_prepare_downconvert(struct ocfs2_lock_res *lockres,
+- int new_level)
++static unsigned int ocfs2_prepare_downconvert(struct ocfs2_lock_res *lockres,
++ int new_level)
+ {
+ assert_spin_locked(&lockres->l_lock);
+
+- BUG_ON(lockres->l_blocking <= LKM_NLMODE);
++ BUG_ON(lockres->l_blocking <= DLM_LOCK_NL);
+
+ if (lockres->l_level <= new_level) {
+- mlog(ML_ERROR, "lockres->l_level (%u) <= new_level (%u)\n",
++ mlog(ML_ERROR, "lockres->l_level (%d) <= new_level (%d)\n",
+ lockres->l_level, new_level);
+ BUG();
+ }
+@@ -2825,33 +2918,33 @@ static void ocfs2_prepare_downconvert(struct ocfs2_lock_res *lockres,
+ lockres->l_action = OCFS2_AST_DOWNCONVERT;
+ lockres->l_requested = new_level;
+ lockres_or_flags(lockres, OCFS2_LOCK_BUSY);
++ return lockres_set_pending(lockres);
+ }
+
+ static int ocfs2_downconvert_lock(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres,
+ int new_level,
+- int lvb)
++ int lvb,
++ unsigned int generation)
+ {
+- int ret, dlm_flags = LKM_CONVERT;
+- enum dlm_status status;
++ int ret;
++ u32 dlm_flags = DLM_LKF_CONVERT;
+
+ mlog_entry_void();
+
+ if (lvb)
+- dlm_flags |= LKM_VALBLK;
+-
+- status = dlmlock(osb->dlm,
+- new_level,
+- &lockres->l_lksb,
+- dlm_flags,
+- lockres->l_name,
+- OCFS2_LOCK_ID_MAX_LEN - 1,
+- ocfs2_locking_ast,
+- lockres,
+- ocfs2_blocking_ast);
+- if (status != DLM_NORMAL) {
+- ocfs2_log_dlm_error("dlmlock", status, lockres);
+- ret = -EINVAL;
++ dlm_flags |= DLM_LKF_VALBLK;
++
++ ret = ocfs2_dlm_lock(osb->cconn,
++ new_level,
++ &lockres->l_lksb,
++ dlm_flags,
++ lockres->l_name,
++ OCFS2_LOCK_ID_MAX_LEN - 1,
++ lockres);
++ lockres_clear_pending(lockres, generation, osb);
++ if (ret) {
++ ocfs2_log_dlm_error("ocfs2_dlm_lock", ret, lockres);
+ ocfs2_recover_from_dlm_error(lockres, 1);
+ goto bail;
+ }
+@@ -2862,7 +2955,7 @@ bail:
+ return ret;
+ }
+
+-/* returns 1 when the caller should unlock and call dlmunlock */
++/* returns 1 when the caller should unlock and call ocfs2_dlm_unlock */
+ static int ocfs2_prepare_cancel_convert(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres)
+ {
+@@ -2898,24 +2991,18 @@ static int ocfs2_cancel_convert(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres)
+ {
+ int ret;
+- enum dlm_status status;
+
+ mlog_entry_void();
+ mlog(0, "lock %s\n", lockres->l_name);
+
+- ret = 0;
+- status = dlmunlock(osb->dlm,
+- &lockres->l_lksb,
+- LKM_CANCEL,
+- ocfs2_unlock_ast,
+- lockres);
+- if (status != DLM_NORMAL) {
+- ocfs2_log_dlm_error("dlmunlock", status, lockres);
+- ret = -EINVAL;
++ ret = ocfs2_dlm_unlock(osb->cconn, &lockres->l_lksb,
++ DLM_LKF_CANCEL, lockres);
++ if (ret) {
++ ocfs2_log_dlm_error("ocfs2_dlm_unlock", ret, lockres);
+ ocfs2_recover_from_dlm_error(lockres, 0);
+ }
+
+- mlog(0, "lock %s return from dlmunlock\n", lockres->l_name);
++ mlog(0, "lock %s return from ocfs2_dlm_unlock\n", lockres->l_name);
+
+ mlog_exit(ret);
+ return ret;
+@@ -2930,6 +3017,7 @@ static int ocfs2_unblock_lock(struct ocfs2_super *osb,
+ int new_level;
+ int ret = 0;
+ int set_lvb = 0;
++ unsigned int gen;
+
+ mlog_entry_void();
+
+@@ -2939,6 +3027,32 @@ static int ocfs2_unblock_lock(struct ocfs2_super *osb,
+
+ recheck:
+ if (lockres->l_flags & OCFS2_LOCK_BUSY) {
++ /* XXX
++ * This is a *big* race. The OCFS2_LOCK_PENDING flag
++ * exists entirely for one reason - another thread has set
++ * OCFS2_LOCK_BUSY, but has *NOT* yet called dlm_lock().
++ *
++ * If we do ocfs2_cancel_convert() before the other thread
++ * calls dlm_lock(), our cancel will do nothing. We will
++ * get no ast, and we will have no way of knowing the
++ * cancel failed. Meanwhile, the other thread will call
++ * into dlm_lock() and wait...forever.
++ *
++ * Why forever? Because another node has asked for the
++ * lock first; that's why we're here in unblock_lock().
++ *
++ * The solution is OCFS2_LOCK_PENDING. When PENDING is
++ * set, we just requeue the unblock. Only when the other
++ * thread has called dlm_lock() and cleared PENDING will
++ * we then cancel their request.
++ *
++ * All callers of dlm_lock() must set OCFS2_DLM_PENDING
++ * at the same time they set OCFS2_DLM_BUSY. They must
++ * clear OCFS2_DLM_PENDING after dlm_lock() returns.
++ */
++ if (lockres->l_flags & OCFS2_LOCK_PENDING)
++ goto leave_requeue;
++
+ ctl->requeue = 1;
+ ret = ocfs2_prepare_cancel_convert(osb, lockres);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+@@ -2952,13 +3066,13 @@ recheck:
+
+ /* if we're blocking an exclusive and we have *any* holders,
+ * then requeue. */
+- if ((lockres->l_blocking == LKM_EXMODE)
++ if ((lockres->l_blocking == DLM_LOCK_EX)
+ && (lockres->l_ex_holders || lockres->l_ro_holders))
+ goto leave_requeue;
+
+ /* If it's a PR we're blocking, then only
+ * requeue if we've got any EX holders */
+- if (lockres->l_blocking == LKM_PRMODE &&
++ if (lockres->l_blocking == DLM_LOCK_PR &&
+ lockres->l_ex_holders)
+ goto leave_requeue;
+
+@@ -3005,7 +3119,7 @@ downconvert:
+ ctl->requeue = 0;
+
+ if (lockres->l_ops->flags & LOCK_TYPE_USES_LVB) {
+- if (lockres->l_level == LKM_EXMODE)
++ if (lockres->l_level == DLM_LOCK_EX)
+ set_lvb = 1;
+
+ /*
+@@ -3018,9 +3132,11 @@ downconvert:
+ lockres->l_ops->set_lvb(lockres);
+ }
+
+- ocfs2_prepare_downconvert(lockres, new_level);
++ gen = ocfs2_prepare_downconvert(lockres, new_level);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+- ret = ocfs2_downconvert_lock(osb, lockres, new_level, set_lvb);
++ ret = ocfs2_downconvert_lock(osb, lockres, new_level, set_lvb,
++ gen);
++
+ leave:
+ mlog_exit(ret);
+ return ret;
+@@ -3059,7 +3175,7 @@ static int ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres,
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
+ }
+ sync_mapping_buffers(mapping);
+- if (blocking == LKM_EXMODE) {
++ if (blocking == DLM_LOCK_EX) {
+ truncate_inode_pages(mapping, 0);
+ } else {
+ /* We only need to wait on the I/O if we're not also
+@@ -3080,8 +3196,8 @@ static int ocfs2_check_meta_downconvert(struct ocfs2_lock_res *lockres,
+ struct inode *inode = ocfs2_lock_res_inode(lockres);
+ int checkpointed = ocfs2_inode_fully_checkpointed(inode);
+
+- BUG_ON(new_level != LKM_NLMODE && new_level != LKM_PRMODE);
+- BUG_ON(lockres->l_level != LKM_EXMODE && !checkpointed);
++ BUG_ON(new_level != DLM_LOCK_NL && new_level != DLM_LOCK_PR);
++ BUG_ON(lockres->l_level != DLM_LOCK_EX && !checkpointed);
+
+ if (checkpointed)
+ return 1;
+@@ -3145,7 +3261,7 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres,
+ * valid. The downconvert code will retain a PR for this node,
+ * so there's no further work to do.
+ */
+- if (blocking == LKM_PRMODE)
++ if (blocking == DLM_LOCK_PR)
+ return UNBLOCK_CONTINUE;
+
+ /*
+@@ -3219,6 +3335,45 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres,
+ return UNBLOCK_CONTINUE_POST;
+ }
+
++/*
++ * This is the filesystem locking protocol. It provides the lock handling
++ * hooks for the underlying DLM. It has a maximum version number.
++ * The version number allows interoperability with systems running at
++ * the same major number and an equal or smaller minor number.
++ *
++ * Whenever the filesystem does new things with locks (adds or removes a
++ * lock, orders them differently, does different things underneath a lock),
++ * the version must be changed. The protocol is negotiated when joining
++ * the dlm domain. A node may join the domain if its major version is
++ * identical to all other nodes and its minor version is greater than
++ * or equal to all other nodes. When its minor version is greater than
++ * the other nodes, it will run at the minor version specified by the
++ * other nodes.
++ *
++ * If a locking change is made that will not be compatible with older
++ * versions, the major number must be increased and the minor version set
++ * to zero. If a change merely adds a behavior that can be disabled when
++ * speaking to older versions, the minor version must be increased. If a
++ * change adds a fully backwards compatible change (eg, LVB changes that
++ * are just ignored by older versions), the version does not need to be
++ * updated.
++ */
++static struct ocfs2_locking_protocol lproto = {
++ .lp_max_version = {
++ .pv_major = OCFS2_LOCKING_PROTOCOL_MAJOR,
++ .pv_minor = OCFS2_LOCKING_PROTOCOL_MINOR,
++ },
++ .lp_lock_ast = ocfs2_locking_ast,
++ .lp_blocking_ast = ocfs2_blocking_ast,
++ .lp_unlock_ast = ocfs2_unlock_ast,
++};
++
++void ocfs2_set_locking_protocol(void)
++{
++ ocfs2_stack_glue_set_locking_protocol(&lproto);
++}
++
++
+ static void ocfs2_process_blocked_lock(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres)
+ {
+diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h
+index e3cf902..2bb01f0 100644
+--- a/fs/ocfs2/dlmglue.h
++++ b/fs/ocfs2/dlmglue.h
+@@ -58,7 +58,7 @@ struct ocfs2_meta_lvb {
+ #define OCFS2_LOCK_NONBLOCK (0x04)
+
+ int ocfs2_dlm_init(struct ocfs2_super *osb);
+-void ocfs2_dlm_shutdown(struct ocfs2_super *osb);
++void ocfs2_dlm_shutdown(struct ocfs2_super *osb, int hangup_pending);
+ void ocfs2_lock_res_init_once(struct ocfs2_lock_res *res);
+ void ocfs2_inode_lock_res_init(struct ocfs2_lock_res *res,
+ enum ocfs2_lock_type type,
+@@ -114,5 +114,6 @@ void ocfs2_wake_downconvert_thread(struct ocfs2_super *osb);
+ struct ocfs2_dlm_debug *ocfs2_new_dlm_debug(void);
+ void ocfs2_put_dlm_debug(struct ocfs2_dlm_debug *dlm_debug);
+
+-extern const struct dlm_protocol_version ocfs2_locking_protocol;
++/* To set the locking protocol on module initialization */
++void ocfs2_set_locking_protocol(void);
+ #endif /* DLMGLUE_H */
+diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
+index ed5d523..9154c82 100644
+--- a/fs/ocfs2/file.c
++++ b/fs/ocfs2/file.c
+@@ -2242,7 +2242,7 @@ const struct file_operations ocfs2_fops = {
+ .open = ocfs2_file_open,
+ .aio_read = ocfs2_file_aio_read,
+ .aio_write = ocfs2_file_aio_write,
+- .ioctl = ocfs2_ioctl,
++ .unlocked_ioctl = ocfs2_ioctl,
+ #ifdef CONFIG_COMPAT
+ .compat_ioctl = ocfs2_compat_ioctl,
+ #endif
+@@ -2258,7 +2258,7 @@ const struct file_operations ocfs2_dops = {
+ .fsync = ocfs2_sync_file,
+ .release = ocfs2_dir_release,
+ .open = ocfs2_dir_open,
+- .ioctl = ocfs2_ioctl,
++ .unlocked_ioctl = ocfs2_ioctl,
+ #ifdef CONFIG_COMPAT
+ .compat_ioctl = ocfs2_compat_ioctl,
+ #endif
+diff --git a/fs/ocfs2/heartbeat.c b/fs/ocfs2/heartbeat.c
+index 0758daf..c6e7213 100644
+--- a/fs/ocfs2/heartbeat.c
++++ b/fs/ocfs2/heartbeat.c
+@@ -28,9 +28,6 @@
+ #include <linux/types.h>
+ #include <linux/slab.h>
+ #include <linux/highmem.h>
+-#include <linux/kmod.h>
+-
+-#include <dlm/dlmapi.h>
+
+ #define MLOG_MASK_PREFIX ML_SUPER
+ #include <cluster/masklog.h>
+@@ -48,7 +45,6 @@ static inline void __ocfs2_node_map_set_bit(struct ocfs2_node_map *map,
+ int bit);
+ static inline void __ocfs2_node_map_clear_bit(struct ocfs2_node_map *map,
+ int bit);
+-static inline int __ocfs2_node_map_is_empty(struct ocfs2_node_map *map);
+
+ /* special case -1 for now
+ * TODO: should *really* make sure the calling func never passes -1!! */
+@@ -62,23 +58,23 @@ static void ocfs2_node_map_init(struct ocfs2_node_map *map)
+ void ocfs2_init_node_maps(struct ocfs2_super *osb)
+ {
+ spin_lock_init(&osb->node_map_lock);
+- ocfs2_node_map_init(&osb->recovery_map);
+ ocfs2_node_map_init(&osb->osb_recovering_orphan_dirs);
+ }
+
+-static void ocfs2_do_node_down(int node_num,
+- struct ocfs2_super *osb)
++void ocfs2_do_node_down(int node_num, void *data)
+ {
++ struct ocfs2_super *osb = data;
++
+ BUG_ON(osb->node_num == node_num);
+
+ mlog(0, "ocfs2: node down event for %d\n", node_num);
+
+- if (!osb->dlm) {
++ if (!osb->cconn) {
+ /*
+- * No DLM means we're not even ready to participate yet.
+- * We check the slots after the DLM comes up, so we will
+- * notice the node death then. We can safely ignore it
+- * here.
++ * No cluster connection means we're not even ready to
++ * participate yet. We check the slots after the cluster
++ * comes up, so we will notice the node death then. We
++ * can safely ignore it here.
+ */
+ return;
+ }
+@@ -86,61 +82,6 @@ static void ocfs2_do_node_down(int node_num,
+ ocfs2_recovery_thread(osb, node_num);
+ }
+
+-/* Called from the dlm when it's about to evict a node. We may also
+- * get a heartbeat callback later. */
+-static void ocfs2_dlm_eviction_cb(int node_num,
+- void *data)
+-{
+- struct ocfs2_super *osb = (struct ocfs2_super *) data;
+- struct super_block *sb = osb->sb;
+-
+- mlog(ML_NOTICE, "device (%u,%u): dlm has evicted node %d\n",
+- MAJOR(sb->s_dev), MINOR(sb->s_dev), node_num);
+-
+- ocfs2_do_node_down(node_num, osb);
+-}
+-
+-void ocfs2_setup_hb_callbacks(struct ocfs2_super *osb)
+-{
+- /* Not exactly a heartbeat callback, but leads to essentially
+- * the same path so we set it up here. */
+- dlm_setup_eviction_cb(&osb->osb_eviction_cb,
+- ocfs2_dlm_eviction_cb,
+- osb);
+-}
+-
+-void ocfs2_stop_heartbeat(struct ocfs2_super *osb)
+-{
+- int ret;
+- char *argv[5], *envp[3];
+-
+- if (ocfs2_mount_local(osb))
+- return;
+-
+- if (!osb->uuid_str) {
+- /* This can happen if we don't get far enough in mount... */
+- mlog(0, "No UUID with which to stop heartbeat!\n\n");
+- return;
+- }
+-
+- argv[0] = (char *)o2nm_get_hb_ctl_path();
+- argv[1] = "-K";
+- argv[2] = "-u";
+- argv[3] = osb->uuid_str;
+- argv[4] = NULL;
+-
+- mlog(0, "Run: %s %s %s %s\n", argv[0], argv[1], argv[2], argv[3]);
+-
+- /* minimal command environment taken from cpu_run_sbin_hotplug */
+- envp[0] = "HOME=/";
+- envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+- envp[2] = NULL;
+-
+- ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
+- if (ret < 0)
+- mlog_errno(ret);
+-}
+-
+ static inline void __ocfs2_node_map_set_bit(struct ocfs2_node_map *map,
+ int bit)
+ {
+@@ -192,112 +133,3 @@ int ocfs2_node_map_test_bit(struct ocfs2_super *osb,
+ return ret;
+ }
+
+-static inline int __ocfs2_node_map_is_empty(struct ocfs2_node_map *map)
+-{
+- int bit;
+- bit = find_next_bit(map->map, map->num_nodes, 0);
+- if (bit < map->num_nodes)
+- return 0;
+- return 1;
+-}
+-
+-int ocfs2_node_map_is_empty(struct ocfs2_super *osb,
+- struct ocfs2_node_map *map)
+-{
+- int ret;
+- BUG_ON(map->num_nodes == 0);
+- spin_lock(&osb->node_map_lock);
+- ret = __ocfs2_node_map_is_empty(map);
+- spin_unlock(&osb->node_map_lock);
+- return ret;
+-}
+-
+-#if 0
+-
+-static void __ocfs2_node_map_dup(struct ocfs2_node_map *target,
+- struct ocfs2_node_map *from)
+-{
+- BUG_ON(from->num_nodes == 0);
+- ocfs2_node_map_init(target);
+- __ocfs2_node_map_set(target, from);
+-}
+-
+-/* returns 1 if bit is the only bit set in target, 0 otherwise */
+-int ocfs2_node_map_is_only(struct ocfs2_super *osb,
+- struct ocfs2_node_map *target,
+- int bit)
+-{
+- struct ocfs2_node_map temp;
+- int ret;
+-
+- spin_lock(&osb->node_map_lock);
+- __ocfs2_node_map_dup(&temp, target);
+- __ocfs2_node_map_clear_bit(&temp, bit);
+- ret = __ocfs2_node_map_is_empty(&temp);
+- spin_unlock(&osb->node_map_lock);
+-
+- return ret;
+-}
+-
+-static void __ocfs2_node_map_set(struct ocfs2_node_map *target,
+- struct ocfs2_node_map *from)
+-{
+- int num_longs, i;
+-
+- BUG_ON(target->num_nodes != from->num_nodes);
+- BUG_ON(target->num_nodes == 0);
+-
+- num_longs = BITS_TO_LONGS(target->num_nodes);
+- for (i = 0; i < num_longs; i++)
+- target->map[i] = from->map[i];
+-}
+-
+-#endif /* 0 */
+-
+-/* Returns whether the recovery bit was actually set - it may not be
+- * if a node is still marked as needing recovery */
+-int ocfs2_recovery_map_set(struct ocfs2_super *osb,
+- int num)
+-{
+- int set = 0;
+-
+- spin_lock(&osb->node_map_lock);
+-
+- if (!test_bit(num, osb->recovery_map.map)) {
+- __ocfs2_node_map_set_bit(&osb->recovery_map, num);
+- set = 1;
+- }
+-
+- spin_unlock(&osb->node_map_lock);
+-
+- return set;
+-}
+-
+-void ocfs2_recovery_map_clear(struct ocfs2_super *osb,
+- int num)
+-{
+- ocfs2_node_map_clear_bit(osb, &osb->recovery_map, num);
+-}
+-
+-int ocfs2_node_map_iterate(struct ocfs2_super *osb,
+- struct ocfs2_node_map *map,
+- int idx)
+-{
+- int i = idx;
+-
+- idx = O2NM_INVALID_NODE_NUM;
+- spin_lock(&osb->node_map_lock);
+- if ((i != O2NM_INVALID_NODE_NUM) &&
+- (i >= 0) &&
+- (i < map->num_nodes)) {
+- while(i < map->num_nodes) {
+- if (test_bit(i, map->map)) {
+- idx = i;
+- break;
+- }
+- i++;
+- }
+- }
+- spin_unlock(&osb->node_map_lock);
+- return idx;
+-}
+diff --git a/fs/ocfs2/heartbeat.h b/fs/ocfs2/heartbeat.h
+index eac63ae..74b9c5d 100644
+--- a/fs/ocfs2/heartbeat.h
++++ b/fs/ocfs2/heartbeat.h
+@@ -28,13 +28,10 @@
+
+ void ocfs2_init_node_maps(struct ocfs2_super *osb);
+
+-void ocfs2_setup_hb_callbacks(struct ocfs2_super *osb);
+-void ocfs2_stop_heartbeat(struct ocfs2_super *osb);
++void ocfs2_do_node_down(int node_num, void *data);
+
+ /* node map functions - used to keep track of mounted and in-recovery
+ * nodes. */
+-int ocfs2_node_map_is_empty(struct ocfs2_super *osb,
+- struct ocfs2_node_map *map);
+ void ocfs2_node_map_set_bit(struct ocfs2_super *osb,
+ struct ocfs2_node_map *map,
+ int bit);
+@@ -44,17 +41,5 @@ void ocfs2_node_map_clear_bit(struct ocfs2_super *osb,
+ int ocfs2_node_map_test_bit(struct ocfs2_super *osb,
+ struct ocfs2_node_map *map,
+ int bit);
+-int ocfs2_node_map_iterate(struct ocfs2_super *osb,
+- struct ocfs2_node_map *map,
+- int idx);
+-static inline int ocfs2_node_map_first_set_bit(struct ocfs2_super *osb,
+- struct ocfs2_node_map *map)
+-{
+- return ocfs2_node_map_iterate(osb, map, 0);
+-}
+-int ocfs2_recovery_map_set(struct ocfs2_super *osb,
+- int num);
+-void ocfs2_recovery_map_clear(struct ocfs2_super *osb,
+- int num);
+
+ #endif /* OCFS2_HEARTBEAT_H */
+diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c
+index 5177fba..7b142f0 100644
+--- a/fs/ocfs2/ioctl.c
++++ b/fs/ocfs2/ioctl.c
+@@ -7,6 +7,7 @@
+
+ #include <linux/fs.h>
+ #include <linux/mount.h>
++#include <linux/smp_lock.h>
+
+ #define MLOG_MASK_PREFIX ML_INODE
+ #include <cluster/masklog.h>
+@@ -59,10 +60,6 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
+ goto bail;
+ }
+
+- status = -EROFS;
+- if (IS_RDONLY(inode))
+- goto bail_unlock;
+-
+ status = -EACCES;
+ if (!is_owner_or_cap(inode))
+ goto bail_unlock;
+@@ -112,9 +109,9 @@ bail:
+ return status;
+ }
+
+-int ocfs2_ioctl(struct inode * inode, struct file * filp,
+- unsigned int cmd, unsigned long arg)
++long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ {
++ struct inode *inode = filp->f_path.dentry->d_inode;
+ unsigned int flags;
+ int new_clusters;
+ int status;
+@@ -133,8 +130,13 @@ int ocfs2_ioctl(struct inode * inode, struct file * filp,
+ if (get_user(flags, (int __user *) arg))
+ return -EFAULT;
+
+- return ocfs2_set_inode_attr(inode, flags,
++ status = mnt_want_write(filp->f_path.mnt);
++ if (status)
++ return status;
++ status = ocfs2_set_inode_attr(inode, flags,
+ OCFS2_FL_MODIFIABLE);
++ mnt_drop_write(filp->f_path.mnt);
++ return status;
+ case OCFS2_IOC_RESVSP:
+ case OCFS2_IOC_RESVSP64:
+ case OCFS2_IOC_UNRESVSP:
+@@ -168,9 +170,6 @@ int ocfs2_ioctl(struct inode * inode, struct file * filp,
+ #ifdef CONFIG_COMPAT
+ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
+ {
+- struct inode *inode = file->f_path.dentry->d_inode;
+- int ret;
+-
+ switch (cmd) {
+ case OCFS2_IOC32_GETFLAGS:
+ cmd = OCFS2_IOC_GETFLAGS;
+@@ -190,9 +189,6 @@ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
+ return -ENOIOCTLCMD;
+ }
+
+- lock_kernel();
+- ret = ocfs2_ioctl(inode, file, cmd, arg);
+- unlock_kernel();
+- return ret;
++ return ocfs2_ioctl(file, cmd, arg);
+ }
+ #endif
+diff --git a/fs/ocfs2/ioctl.h b/fs/ocfs2/ioctl.h
+index 4d6c4f4..cf9a5ee 100644
+--- a/fs/ocfs2/ioctl.h
++++ b/fs/ocfs2/ioctl.h
+@@ -10,8 +10,7 @@
+ #ifndef OCFS2_IOCTL_H
+ #define OCFS2_IOCTL_H
+
+-int ocfs2_ioctl(struct inode * inode, struct file * filp,
+- unsigned int cmd, unsigned long arg);
++long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg);
+
+ #endif /* OCFS2_IOCTL_H */
+diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
+index f31c7e8..9698338 100644
+--- a/fs/ocfs2/journal.c
++++ b/fs/ocfs2/journal.c
+@@ -64,6 +64,137 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb,
+ int slot);
+ static int ocfs2_commit_thread(void *arg);
+
++
++/*
++ * The recovery_list is a simple linked list of node numbers to recover.
++ * It is protected by the recovery_lock.
++ */
++
++struct ocfs2_recovery_map {
++ unsigned int rm_used;
++ unsigned int *rm_entries;
++};
++
++int ocfs2_recovery_init(struct ocfs2_super *osb)
++{
++ struct ocfs2_recovery_map *rm;
++
++ mutex_init(&osb->recovery_lock);
++ osb->disable_recovery = 0;
++ osb->recovery_thread_task = NULL;
++ init_waitqueue_head(&osb->recovery_event);
++
++ rm = kzalloc(sizeof(struct ocfs2_recovery_map) +
++ osb->max_slots * sizeof(unsigned int),
++ GFP_KERNEL);
++ if (!rm) {
++ mlog_errno(-ENOMEM);
++ return -ENOMEM;
++ }
++
++ rm->rm_entries = (unsigned int *)((char *)rm +
++ sizeof(struct ocfs2_recovery_map));
++ osb->recovery_map = rm;
++
++ return 0;
++}
++
++/* we can't grab the goofy sem lock from inside wait_event, so we use
++ * memory barriers to make sure that we'll see the null task before
++ * being woken up */
++static int ocfs2_recovery_thread_running(struct ocfs2_super *osb)
++{
++ mb();
++ return osb->recovery_thread_task != NULL;
++}
++
++void ocfs2_recovery_exit(struct ocfs2_super *osb)
++{
++ struct ocfs2_recovery_map *rm;
++
++ /* disable any new recovery threads and wait for any currently
++ * running ones to exit. Do this before setting the vol_state. */
++ mutex_lock(&osb->recovery_lock);
++ osb->disable_recovery = 1;
++ mutex_unlock(&osb->recovery_lock);
++ wait_event(osb->recovery_event, !ocfs2_recovery_thread_running(osb));
++
++ /* At this point, we know that no more recovery threads can be
++ * launched, so wait for any recovery completion work to
++ * complete. */
++ flush_workqueue(ocfs2_wq);
++
++ /*
++ * Now that recovery is shut down, and the osb is about to be
++ * freed, the osb_lock is not taken here.
++ */
++ rm = osb->recovery_map;
++ /* XXX: Should we bug if there are dirty entries? */
++
++ kfree(rm);
++}
++
++static int __ocfs2_recovery_map_test(struct ocfs2_super *osb,
++ unsigned int node_num)
++{
++ int i;
++ struct ocfs2_recovery_map *rm = osb->recovery_map;
++
++ assert_spin_locked(&osb->osb_lock);
++
++ for (i = 0; i < rm->rm_used; i++) {
++ if (rm->rm_entries[i] == node_num)
++ return 1;
++ }
++
++ return 0;
++}
++
++/* Behaves like test-and-set. Returns the previous value */
++static int ocfs2_recovery_map_set(struct ocfs2_super *osb,
++ unsigned int node_num)
++{
++ struct ocfs2_recovery_map *rm = osb->recovery_map;
++
++ spin_lock(&osb->osb_lock);
++ if (__ocfs2_recovery_map_test(osb, node_num)) {
++ spin_unlock(&osb->osb_lock);
++ return 1;
++ }
++
++ /* XXX: Can this be exploited? Not from o2dlm... */
++ BUG_ON(rm->rm_used >= osb->max_slots);
++
++ rm->rm_entries[rm->rm_used] = node_num;
++ rm->rm_used++;
++ spin_unlock(&osb->osb_lock);
++
++ return 0;
++}
++
++static void ocfs2_recovery_map_clear(struct ocfs2_super *osb,
++ unsigned int node_num)
++{
++ int i;
++ struct ocfs2_recovery_map *rm = osb->recovery_map;
++
++ spin_lock(&osb->osb_lock);
++
++ for (i = 0; i < rm->rm_used; i++) {
++ if (rm->rm_entries[i] == node_num)
++ break;
++ }
++
++ if (i < rm->rm_used) {
++ /* XXX: be careful with the pointer math */
++ memmove(&(rm->rm_entries[i]), &(rm->rm_entries[i + 1]),
++ (rm->rm_used - i - 1) * sizeof(unsigned int));
++ rm->rm_used--;
++ }
++
++ spin_unlock(&osb->osb_lock);
++}
++
+ static int ocfs2_commit_cache(struct ocfs2_super *osb)
+ {
+ int status = 0;
+@@ -586,8 +717,7 @@ int ocfs2_journal_load(struct ocfs2_journal *journal, int local)
+
+ mlog_entry_void();
+
+- if (!journal)
+- BUG();
++ BUG_ON(!journal);
+
+ osb = journal->j_osb;
+
+@@ -650,6 +780,23 @@ bail:
+ return status;
+ }
+
++static int ocfs2_recovery_completed(struct ocfs2_super *osb)
++{
++ int empty;
++ struct ocfs2_recovery_map *rm = osb->recovery_map;
++
++ spin_lock(&osb->osb_lock);
++ empty = (rm->rm_used == 0);
++ spin_unlock(&osb->osb_lock);
++
++ return empty;
++}
++
++void ocfs2_wait_for_recovery(struct ocfs2_super *osb)
++{
++ wait_event(osb->recovery_event, ocfs2_recovery_completed(osb));
++}
++
+ /*
+ * JBD Might read a cached version of another nodes journal file. We
+ * don't want this as this file changes often and we get no
+@@ -848,6 +995,7 @@ static int __ocfs2_recovery_thread(void *arg)
+ {
+ int status, node_num;
+ struct ocfs2_super *osb = arg;
++ struct ocfs2_recovery_map *rm = osb->recovery_map;
+
+ mlog_entry_void();
+
+@@ -863,26 +1011,29 @@ restart:
+ goto bail;
+ }
+
+- while(!ocfs2_node_map_is_empty(osb, &osb->recovery_map)) {
+- node_num = ocfs2_node_map_first_set_bit(osb,
+- &osb->recovery_map);
+- if (node_num == O2NM_INVALID_NODE_NUM) {
+- mlog(0, "Out of nodes to recover.\n");
+- break;
+- }
++ spin_lock(&osb->osb_lock);
++ while (rm->rm_used) {
++ /* It's always safe to remove entry zero, as we won't
++ * clear it until ocfs2_recover_node() has succeeded. */
++ node_num = rm->rm_entries[0];
++ spin_unlock(&osb->osb_lock);
+
+ status = ocfs2_recover_node(osb, node_num);
+- if (status < 0) {
++ if (!status) {
++ ocfs2_recovery_map_clear(osb, node_num);
++ } else {
+ mlog(ML_ERROR,
+ "Error %d recovering node %d on device (%u,%u)!\n",
+ status, node_num,
+ MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev));
+ mlog(ML_ERROR, "Volume requires unmount.\n");
+- continue;
+ }
+
+- ocfs2_recovery_map_clear(osb, node_num);
++ spin_lock(&osb->osb_lock);
+ }
++ spin_unlock(&osb->osb_lock);
++ mlog(0, "All nodes recovered\n");
++
+ ocfs2_super_unlock(osb, 1);
+
+ /* We always run recovery on our own orphan dir - the dead
+@@ -893,8 +1044,7 @@ restart:
+
+ bail:
+ mutex_lock(&osb->recovery_lock);
+- if (!status &&
+- !ocfs2_node_map_is_empty(osb, &osb->recovery_map)) {
++ if (!status && !ocfs2_recovery_completed(osb)) {
+ mutex_unlock(&osb->recovery_lock);
+ goto restart;
+ }
+@@ -924,8 +1074,8 @@ void ocfs2_recovery_thread(struct ocfs2_super *osb, int node_num)
+
+ /* People waiting on recovery will wait on
+ * the recovery map to empty. */
+- if (!ocfs2_recovery_map_set(osb, node_num))
+- mlog(0, "node %d already be in recovery.\n", node_num);
++ if (ocfs2_recovery_map_set(osb, node_num))
++ mlog(0, "node %d already in recovery map.\n", node_num);
+
+ mlog(0, "starting recovery thread...\n");
+
+@@ -1079,7 +1229,6 @@ static int ocfs2_recover_node(struct ocfs2_super *osb,
+ {
+ int status = 0;
+ int slot_num;
+- struct ocfs2_slot_info *si = osb->slot_info;
+ struct ocfs2_dinode *la_copy = NULL;
+ struct ocfs2_dinode *tl_copy = NULL;
+
+@@ -1092,8 +1241,8 @@ static int ocfs2_recover_node(struct ocfs2_super *osb,
+ * case we should've called ocfs2_journal_load instead. */
+ BUG_ON(osb->node_num == node_num);
+
+- slot_num = ocfs2_node_num_to_slot(si, node_num);
+- if (slot_num == OCFS2_INVALID_SLOT) {
++ slot_num = ocfs2_node_num_to_slot(osb, node_num);
++ if (slot_num == -ENOENT) {
+ status = 0;
+ mlog(0, "no slot for this node, so no recovery required.\n");
+ goto done;
+@@ -1123,8 +1272,7 @@ static int ocfs2_recover_node(struct ocfs2_super *osb,
+
+ /* Likewise, this would be a strange but ultimately not so
+ * harmful place to get an error... */
+- ocfs2_clear_slot(si, slot_num);
+- status = ocfs2_update_disk_slots(osb, si);
++ status = ocfs2_clear_slot(osb, slot_num);
+ if (status < 0)
+ mlog_errno(status);
+
+@@ -1184,23 +1332,24 @@ bail:
+ * slot info struct has been updated from disk. */
+ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb)
+ {
+- int status, i, node_num;
+- struct ocfs2_slot_info *si = osb->slot_info;
++ unsigned int node_num;
++ int status, i;
+
+ /* This is called with the super block cluster lock, so we
+ * know that the slot map can't change underneath us. */
+
+- spin_lock(&si->si_lock);
+- for(i = 0; i < si->si_num_slots; i++) {
++ spin_lock(&osb->osb_lock);
++ for (i = 0; i < osb->max_slots; i++) {
+ if (i == osb->slot_num)
+ continue;
+- if (ocfs2_is_empty_slot(si, i))
++
++ status = ocfs2_slot_to_node_num_locked(osb, i, &node_num);
++ if (status == -ENOENT)
+ continue;
+
+- node_num = si->si_global_node_nums[i];
+- if (ocfs2_node_map_test_bit(osb, &osb->recovery_map, node_num))
++ if (__ocfs2_recovery_map_test(osb, node_num))
+ continue;
+- spin_unlock(&si->si_lock);
++ spin_unlock(&osb->osb_lock);
+
+ /* Ok, we have a slot occupied by another node which
+ * is not in the recovery map. We trylock his journal
+@@ -1216,9 +1365,9 @@ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb)
+ goto bail;
+ }
+
+- spin_lock(&si->si_lock);
++ spin_lock(&osb->osb_lock);
+ }
+- spin_unlock(&si->si_lock);
++ spin_unlock(&osb->osb_lock);
+
+ status = 0;
+ bail:
+diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h
+index 220f3e8..db82be2 100644
+--- a/fs/ocfs2/journal.h
++++ b/fs/ocfs2/journal.h
+@@ -134,6 +134,10 @@ static inline void ocfs2_inode_set_new(struct ocfs2_super *osb,
+
+ /* Exported only for the journal struct init code in super.c. Do not call. */
+ void ocfs2_complete_recovery(struct work_struct *work);
++void ocfs2_wait_for_recovery(struct ocfs2_super *osb);
++
++int ocfs2_recovery_init(struct ocfs2_super *osb);
++void ocfs2_recovery_exit(struct ocfs2_super *osb);
+
+ /*
+ * Journal Control:
+diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c
+index ab83fd5..ce0dc14 100644
+--- a/fs/ocfs2/localalloc.c
++++ b/fs/ocfs2/localalloc.c
+@@ -447,6 +447,8 @@ out_mutex:
+ iput(main_bm_inode);
+
+ out:
++ if (!status)
++ ocfs2_init_inode_steal_slot(osb);
+ mlog_exit(status);
+ return status;
+ }
+@@ -523,6 +525,8 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
+ }
+
+ ac->ac_inode = local_alloc_inode;
++ /* We should never use localalloc from another slot */
++ ac->ac_alloc_slot = osb->slot_num;
+ ac->ac_which = OCFS2_AC_USE_LOCAL;
+ get_bh(osb->local_alloc_bh);
+ ac->ac_bh = osb->local_alloc_bh;
+diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
+index ae9ad95..d5d808f 100644
+--- a/fs/ocfs2/namei.c
++++ b/fs/ocfs2/namei.c
+@@ -424,7 +424,7 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
+ fe->i_fs_generation = cpu_to_le32(osb->fs_generation);
+ fe->i_blkno = cpu_to_le64(fe_blkno);
+ fe->i_suballoc_bit = cpu_to_le16(suballoc_bit);
+- fe->i_suballoc_slot = cpu_to_le16(osb->slot_num);
++ fe->i_suballoc_slot = cpu_to_le16(inode_ac->ac_alloc_slot);
+ fe->i_uid = cpu_to_le32(current->fsuid);
+ if (dir->i_mode & S_ISGID) {
+ fe->i_gid = cpu_to_le32(dir->i_gid);
+@@ -997,7 +997,7 @@ static int ocfs2_rename(struct inode *old_dir,
+ *
+ * And that's why, just like the VFS, we need a file system
+ * rename lock. */
+- if (old_dentry != new_dentry) {
++ if (old_dir != new_dir && S_ISDIR(old_inode->i_mode)) {
+ status = ocfs2_rename_lock(osb);
+ if (status < 0) {
+ mlog_errno(status);
+diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
+index 6546cef..3169237 100644
+--- a/fs/ocfs2/ocfs2.h
++++ b/fs/ocfs2/ocfs2.h
+@@ -36,11 +36,8 @@
+ #include <linux/mutex.h>
+ #include <linux/jbd.h>
+
+-#include "cluster/nodemanager.h"
+-#include "cluster/heartbeat.h"
+-#include "cluster/tcp.h"
+-
+-#include "dlm/dlmapi.h"
++/* For union ocfs2_dlm_lksb */
++#include "stackglue.h"
+
+ #include "ocfs2_fs.h"
+ #include "ocfs2_lockid.h"
+@@ -101,6 +98,9 @@ enum ocfs2_unlock_action {
+ * dropped. */
+ #define OCFS2_LOCK_QUEUED (0x00000100) /* queued for downconvert */
+ #define OCFS2_LOCK_NOCACHE (0x00000200) /* don't use a holder count */
++#define OCFS2_LOCK_PENDING (0x00000400) /* This lockres is pending a
++ call to dlm_lock. Only
++ exists with BUSY set. */
+
+ struct ocfs2_lock_res_ops;
+
+@@ -120,13 +120,14 @@ struct ocfs2_lock_res {
+ int l_level;
+ unsigned int l_ro_holders;
+ unsigned int l_ex_holders;
+- struct dlm_lockstatus l_lksb;
++ union ocfs2_dlm_lksb l_lksb;
+
+ /* used from AST/BAST funcs. */
+ enum ocfs2_ast_action l_action;
+ enum ocfs2_unlock_action l_unlock_action;
+ int l_requested;
+ int l_blocking;
++ unsigned int l_pending_gen;
+
+ wait_queue_head_t l_event;
+
+@@ -179,6 +180,8 @@ enum ocfs2_mount_options
+ #define OCFS2_DEFAULT_ATIME_QUANTUM 60
+
+ struct ocfs2_journal;
++struct ocfs2_slot_info;
++struct ocfs2_recovery_map;
+ struct ocfs2_super
+ {
+ struct task_struct *commit_task;
+@@ -190,7 +193,6 @@ struct ocfs2_super
+ struct ocfs2_slot_info *slot_info;
+
+ spinlock_t node_map_lock;
+- struct ocfs2_node_map recovery_map;
+
+ u64 root_blkno;
+ u64 system_dir_blkno;
+@@ -206,25 +208,29 @@ struct ocfs2_super
+ u32 s_feature_incompat;
+ u32 s_feature_ro_compat;
+
+- /* Protects s_next_generaion, osb_flags. Could protect more on
+- * osb as it's very short lived. */
++ /* Protects s_next_generation, osb_flags and s_inode_steal_slot.
++ * Could protect more on osb as it's very short lived.
++ */
+ spinlock_t osb_lock;
+ u32 s_next_generation;
+ unsigned long osb_flags;
++ s16 s_inode_steal_slot;
++ atomic_t s_num_inodes_stolen;
+
+ unsigned long s_mount_opt;
+ unsigned int s_atime_quantum;
+
+- u16 max_slots;
+- s16 node_num;
+- s16 slot_num;
+- s16 preferred_slot;
++ unsigned int max_slots;
++ unsigned int node_num;
++ int slot_num;
++ int preferred_slot;
+ int s_sectsize_bits;
+ int s_clustersize;
+ int s_clustersize_bits;
+
+ atomic_t vol_state;
+ struct mutex recovery_lock;
++ struct ocfs2_recovery_map *recovery_map;
+ struct task_struct *recovery_thread_task;
+ int disable_recovery;
+ wait_queue_head_t checkpoint_event;
+@@ -245,12 +251,11 @@ struct ocfs2_super
+ struct ocfs2_alloc_stats alloc_stats;
+ char dev_str[20]; /* "major,minor" of the device */
+
+- struct dlm_ctxt *dlm;
++ char osb_cluster_stack[OCFS2_STACK_LABEL_LEN + 1];
++ struct ocfs2_cluster_connection *cconn;
+ struct ocfs2_lock_res osb_super_lockres;
+ struct ocfs2_lock_res osb_rename_lockres;
+- struct dlm_eviction_cb osb_eviction_cb;
+ struct ocfs2_dlm_debug *osb_dlm_debug;
+- struct dlm_protocol_version osb_locking_proto;
+
+ struct dentry *osb_debug_root;
+
+@@ -367,11 +372,24 @@ static inline int ocfs2_is_soft_readonly(struct ocfs2_super *osb)
+ return ret;
+ }
+
++static inline int ocfs2_userspace_stack(struct ocfs2_super *osb)
++{
++ return (osb->s_feature_incompat &
++ OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK);
++}
++
+ static inline int ocfs2_mount_local(struct ocfs2_super *osb)
+ {
+ return (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT);
+ }
+
++static inline int ocfs2_uses_extended_slot_map(struct ocfs2_super *osb)
++{
++ return (osb->s_feature_incompat &
++ OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP);
++}
++
++
+ #define OCFS2_IS_VALID_DINODE(ptr) \
+ (!strcmp((ptr)->i_signature, OCFS2_INODE_SIGNATURE))
+
+@@ -522,6 +540,33 @@ static inline unsigned int ocfs2_pages_per_cluster(struct super_block *sb)
+ return pages_per_cluster;
+ }
+
++static inline void ocfs2_init_inode_steal_slot(struct ocfs2_super *osb)
++{
++ spin_lock(&osb->osb_lock);
++ osb->s_inode_steal_slot = OCFS2_INVALID_SLOT;
++ spin_unlock(&osb->osb_lock);
++ atomic_set(&osb->s_num_inodes_stolen, 0);
++}
++
++static inline void ocfs2_set_inode_steal_slot(struct ocfs2_super *osb,
++ s16 slot)
++{
++ spin_lock(&osb->osb_lock);
++ osb->s_inode_steal_slot = slot;
++ spin_unlock(&osb->osb_lock);
++}
++
++static inline s16 ocfs2_get_inode_steal_slot(struct ocfs2_super *osb)
++{
++ s16 slot;
++
++ spin_lock(&osb->osb_lock);
++ slot = osb->s_inode_steal_slot;
++ spin_unlock(&osb->osb_lock);
++
++ return slot;
++}
++
+ #define ocfs2_set_bit ext2_set_bit
+ #define ocfs2_clear_bit ext2_clear_bit
+ #define ocfs2_test_bit ext2_test_bit
+diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
+index 3633edd..52c4266 100644
+--- a/fs/ocfs2/ocfs2_fs.h
++++ b/fs/ocfs2/ocfs2_fs.h
+@@ -88,7 +88,9 @@
+ #define OCFS2_FEATURE_COMPAT_SUPP OCFS2_FEATURE_COMPAT_BACKUP_SB
+ #define OCFS2_FEATURE_INCOMPAT_SUPP (OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT \
+ | OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC \
+- | OCFS2_FEATURE_INCOMPAT_INLINE_DATA)
++ | OCFS2_FEATURE_INCOMPAT_INLINE_DATA \
++ | OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP \
++ | OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK)
+ #define OCFS2_FEATURE_RO_COMPAT_SUPP OCFS2_FEATURE_RO_COMPAT_UNWRITTEN
+
+ /*
+@@ -125,6 +127,21 @@
+ /* Support for data packed into inode blocks */
+ #define OCFS2_FEATURE_INCOMPAT_INLINE_DATA 0x0040
+
++/* Support for the extended slot map */
++#define OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP 0x100
++
++
++/*
++ * Support for alternate, userspace cluster stacks. If set, the superblock
++ * field s_cluster_info contains a tag for the alternate stack in use as
++ * well as the name of the cluster being joined.
++ * mount.ocfs2 must pass in a matching stack name.
++ *
++ * If not set, the classic stack will be used. This is compatbile with
++ * all older versions.
++ */
++#define OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK 0x0080
++
+ /*
+ * backup superblock flag is used to indicate that this volume
+ * has backup superblocks.
+@@ -267,6 +284,10 @@ struct ocfs2_new_group_input {
+ #define OCFS2_VOL_UUID_LEN 16
+ #define OCFS2_MAX_VOL_LABEL_LEN 64
+
++/* The alternate, userspace stack fields */
++#define OCFS2_STACK_LABEL_LEN 4
++#define OCFS2_CLUSTER_NAME_LEN 16
++
+ /* Journal limits (in bytes) */
+ #define OCFS2_MIN_JOURNAL_SIZE (4 * 1024 * 1024)
+
+@@ -475,6 +496,47 @@ struct ocfs2_extent_block
+ };
+
+ /*
++ * On disk slot map for OCFS2. This defines the contents of the "slot_map"
++ * system file. A slot is valid if it contains a node number >= 0. The
++ * value -1 (0xFFFF) is OCFS2_INVALID_SLOT. This marks a slot empty.
++ */
++struct ocfs2_slot_map {
++/*00*/ __le16 sm_slots[0];
++/*
++ * Actual on-disk size is one block. OCFS2_MAX_SLOTS is 255,
++ * 255 * sizeof(__le16) == 512B, within the 512B block minimum blocksize.
++ */
++};
++
++struct ocfs2_extended_slot {
++/*00*/ __u8 es_valid;
++ __u8 es_reserved1[3];
++ __le32 es_node_num;
++/*10*/
++};
++
++/*
++ * The extended slot map, used when OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP
++ * is set. It separates out the valid marker from the node number, and
++ * has room to grow. Unlike the old slot map, this format is defined by
++ * i_size.
++ */
++struct ocfs2_slot_map_extended {
++/*00*/ struct ocfs2_extended_slot se_slots[0];
++/*
++ * Actual size is i_size of the slot_map system file. It should
++ * match s_max_slots * sizeof(struct ocfs2_extended_slot)
++ */
++};
++
++struct ocfs2_cluster_info {
++/*00*/ __u8 ci_stack[OCFS2_STACK_LABEL_LEN];
++ __le32 ci_reserved;
++/*08*/ __u8 ci_cluster[OCFS2_CLUSTER_NAME_LEN];
++/*18*/
++};
++
++/*
+ * On disk superblock for OCFS2
+ * Note that it is contained inside an ocfs2_dinode, so all offsets
+ * are relative to the start of ocfs2_dinode.id2.
+@@ -506,7 +568,20 @@ struct ocfs2_super_block {
+ * group header */
+ /*50*/ __u8 s_label[OCFS2_MAX_VOL_LABEL_LEN]; /* Label for mounting, etc. */
+ /*90*/ __u8 s_uuid[OCFS2_VOL_UUID_LEN]; /* 128-bit uuid */
+-/*A0*/
++/*A0*/ struct ocfs2_cluster_info s_cluster_info; /* Selected userspace
++ stack. Only valid
++ with INCOMPAT flag. */
++/*B8*/ __le64 s_reserved2[17]; /* Fill out superblock */
++/*140*/
++
++ /*
++ * NOTE: As stated above, all offsets are relative to
++ * ocfs2_dinode.id2, which is at 0xC0 in the inode.
++ * 0xC0 + 0x140 = 0x200 or 512 bytes. A superblock must fit within
++ * our smallest blocksize, which is 512 bytes. To ensure this,
++ * we reserve the space in s_reserved2. Anything past s_reserved2
++ * will not be available on the smallest blocksize.
++ */
+ };
+
+ /*
+diff --git a/fs/ocfs2/ocfs2_lockid.h b/fs/ocfs2/ocfs2_lockid.h
+index 86f3e37..82c200f 100644
+--- a/fs/ocfs2/ocfs2_lockid.h
++++ b/fs/ocfs2/ocfs2_lockid.h
+@@ -100,7 +100,7 @@ static char *ocfs2_lock_type_strings[] = {
+ static inline const char *ocfs2_lock_type_string(enum ocfs2_lock_type type)
+ {
+ #ifdef __KERNEL__
+- mlog_bug_on_msg(type >= OCFS2_NUM_LOCK_TYPES, "%d\n", type);
++ BUG_ON(type >= OCFS2_NUM_LOCK_TYPES);
+ #endif
+ return ocfs2_lock_type_strings[type];
+ }
+diff --git a/fs/ocfs2/slot_map.c b/fs/ocfs2/slot_map.c
+index 3a50ce5..bb5ff89 100644
+--- a/fs/ocfs2/slot_map.c
++++ b/fs/ocfs2/slot_map.c
+@@ -42,81 +42,244 @@
+
+ #include "buffer_head_io.h"
+
+-static s16 __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si,
+- s16 global);
+-static void __ocfs2_fill_slot(struct ocfs2_slot_info *si,
+- s16 slot_num,
+- s16 node_num);
+-
+-/* post the slot information on disk into our slot_info struct. */
+-void ocfs2_update_slot_info(struct ocfs2_slot_info *si)
++
++struct ocfs2_slot {
++ int sl_valid;
++ unsigned int sl_node_num;
++};
++
++struct ocfs2_slot_info {
++ int si_extended;
++ int si_slots_per_block;
++ struct inode *si_inode;
++ unsigned int si_blocks;
++ struct buffer_head **si_bh;
++ unsigned int si_num_slots;
++ struct ocfs2_slot *si_slots;
++};
++
++
++static int __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si,
++ unsigned int node_num);
++
++static void ocfs2_invalidate_slot(struct ocfs2_slot_info *si,
++ int slot_num)
++{
++ BUG_ON((slot_num < 0) || (slot_num >= si->si_num_slots));
++ si->si_slots[slot_num].sl_valid = 0;
++}
++
++static void ocfs2_set_slot(struct ocfs2_slot_info *si,
++ int slot_num, unsigned int node_num)
++{
++ BUG_ON((slot_num < 0) || (slot_num >= si->si_num_slots));
++
++ si->si_slots[slot_num].sl_valid = 1;
++ si->si_slots[slot_num].sl_node_num = node_num;
++}
++
++/* This version is for the extended slot map */
++static void ocfs2_update_slot_info_extended(struct ocfs2_slot_info *si)
++{
++ int b, i, slotno;
++ struct ocfs2_slot_map_extended *se;
++
++ slotno = 0;
++ for (b = 0; b < si->si_blocks; b++) {
++ se = (struct ocfs2_slot_map_extended *)si->si_bh[b]->b_data;
++ for (i = 0;
++ (i < si->si_slots_per_block) &&
++ (slotno < si->si_num_slots);
++ i++, slotno++) {
++ if (se->se_slots[i].es_valid)
++ ocfs2_set_slot(si, slotno,
++ le32_to_cpu(se->se_slots[i].es_node_num));
++ else
++ ocfs2_invalidate_slot(si, slotno);
++ }
++ }
++}
++
++/*
++ * Post the slot information on disk into our slot_info struct.
++ * Must be protected by osb_lock.
++ */
++static void ocfs2_update_slot_info_old(struct ocfs2_slot_info *si)
+ {
+ int i;
+- __le16 *disk_info;
++ struct ocfs2_slot_map *sm;
+
+- /* we don't read the slot block here as ocfs2_super_lock
+- * should've made sure we have the most recent copy. */
+- spin_lock(&si->si_lock);
+- disk_info = (__le16 *) si->si_bh->b_data;
++ sm = (struct ocfs2_slot_map *)si->si_bh[0]->b_data;
+
+- for (i = 0; i < si->si_size; i++)
+- si->si_global_node_nums[i] = le16_to_cpu(disk_info[i]);
++ for (i = 0; i < si->si_num_slots; i++) {
++ if (le16_to_cpu(sm->sm_slots[i]) == (u16)OCFS2_INVALID_SLOT)
++ ocfs2_invalidate_slot(si, i);
++ else
++ ocfs2_set_slot(si, i, le16_to_cpu(sm->sm_slots[i]));
++ }
++}
+
+- spin_unlock(&si->si_lock);
++static void ocfs2_update_slot_info(struct ocfs2_slot_info *si)
++{
++ /*
++ * The slot data will have been refreshed when ocfs2_super_lock
++ * was taken.
++ */
++ if (si->si_extended)
++ ocfs2_update_slot_info_extended(si);
++ else
++ ocfs2_update_slot_info_old(si);
++}
++
++int ocfs2_refresh_slot_info(struct ocfs2_super *osb)
++{
++ int ret;
++ struct ocfs2_slot_info *si = osb->slot_info;
++
++ if (si == NULL)
++ return 0;
++
++ BUG_ON(si->si_blocks == 0);
++ BUG_ON(si->si_bh == NULL);
++
++ mlog(0, "Refreshing slot map, reading %u block(s)\n",
++ si->si_blocks);
++
++ /*
++ * We pass -1 as blocknr because we expect all of si->si_bh to
++ * be !NULL. Thus, ocfs2_read_blocks() will ignore blocknr. If
++ * this is not true, the read of -1 (UINT64_MAX) will fail.
++ */
++ ret = ocfs2_read_blocks(osb, -1, si->si_blocks, si->si_bh, 0,
++ si->si_inode);
++ if (ret == 0) {
++ spin_lock(&osb->osb_lock);
++ ocfs2_update_slot_info(si);
++ spin_unlock(&osb->osb_lock);
++ }
++
++ return ret;
+ }
+
+ /* post the our slot info stuff into it's destination bh and write it
+ * out. */
+-int ocfs2_update_disk_slots(struct ocfs2_super *osb,
+- struct ocfs2_slot_info *si)
++static void ocfs2_update_disk_slot_extended(struct ocfs2_slot_info *si,
++ int slot_num,
++ struct buffer_head **bh)
+ {
+- int status, i;
+- __le16 *disk_info = (__le16 *) si->si_bh->b_data;
++ int blkind = slot_num / si->si_slots_per_block;
++ int slotno = slot_num % si->si_slots_per_block;
++ struct ocfs2_slot_map_extended *se;
++
++ BUG_ON(blkind >= si->si_blocks);
++
++ se = (struct ocfs2_slot_map_extended *)si->si_bh[blkind]->b_data;
++ se->se_slots[slotno].es_valid = si->si_slots[slot_num].sl_valid;
++ if (si->si_slots[slot_num].sl_valid)
++ se->se_slots[slotno].es_node_num =
++ cpu_to_le32(si->si_slots[slot_num].sl_node_num);
++ *bh = si->si_bh[blkind];
++}
+
+- spin_lock(&si->si_lock);
+- for (i = 0; i < si->si_size; i++)
+- disk_info[i] = cpu_to_le16(si->si_global_node_nums[i]);
+- spin_unlock(&si->si_lock);
++static void ocfs2_update_disk_slot_old(struct ocfs2_slot_info *si,
++ int slot_num,
++ struct buffer_head **bh)
++{
++ int i;
++ struct ocfs2_slot_map *sm;
++
++ sm = (struct ocfs2_slot_map *)si->si_bh[0]->b_data;
++ for (i = 0; i < si->si_num_slots; i++) {
++ if (si->si_slots[i].sl_valid)
++ sm->sm_slots[i] =
++ cpu_to_le16(si->si_slots[i].sl_node_num);
++ else
++ sm->sm_slots[i] = cpu_to_le16(OCFS2_INVALID_SLOT);
++ }
++ *bh = si->si_bh[0];
++}
++
++static int ocfs2_update_disk_slot(struct ocfs2_super *osb,
++ struct ocfs2_slot_info *si,
++ int slot_num)
++{
++ int status;
++ struct buffer_head *bh;
++
++ spin_lock(&osb->osb_lock);
++ if (si->si_extended)
++ ocfs2_update_disk_slot_extended(si, slot_num, &bh);
++ else
++ ocfs2_update_disk_slot_old(si, slot_num, &bh);
++ spin_unlock(&osb->osb_lock);
+
+- status = ocfs2_write_block(osb, si->si_bh, si->si_inode);
++ status = ocfs2_write_block(osb, bh, si->si_inode);
+ if (status < 0)
+ mlog_errno(status);
+
+ return status;
+ }
+
+-/* try to find global node in the slot info. Returns
+- * OCFS2_INVALID_SLOT if nothing is found. */
+-static s16 __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si,
+- s16 global)
++/*
++ * Calculate how many bytes are needed by the slot map. Returns
++ * an error if the slot map file is too small.
++ */
++static int ocfs2_slot_map_physical_size(struct ocfs2_super *osb,
++ struct inode *inode,
++ unsigned long long *bytes)
+ {
+- int i;
+- s16 ret = OCFS2_INVALID_SLOT;
++ unsigned long long bytes_needed;
++
++ if (ocfs2_uses_extended_slot_map(osb)) {
++ bytes_needed = osb->max_slots *
++ sizeof(struct ocfs2_extended_slot);
++ } else {
++ bytes_needed = osb->max_slots * sizeof(__le16);
++ }
++ if (bytes_needed > i_size_read(inode)) {
++ mlog(ML_ERROR,
++ "Slot map file is too small! (size %llu, needed %llu)\n",
++ i_size_read(inode), bytes_needed);
++ return -ENOSPC;
++ }
++
++ *bytes = bytes_needed;
++ return 0;
++}
++
++/* try to find global node in the slot info. Returns -ENOENT
++ * if nothing is found. */
++static int __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si,
++ unsigned int node_num)
++{
++ int i, ret = -ENOENT;
+
+ for(i = 0; i < si->si_num_slots; i++) {
+- if (global == si->si_global_node_nums[i]) {
+- ret = (s16) i;
++ if (si->si_slots[i].sl_valid &&
++ (node_num == si->si_slots[i].sl_node_num)) {
++ ret = i;
+ break;
+ }
+ }
++
+ return ret;
+ }
+
+-static s16 __ocfs2_find_empty_slot(struct ocfs2_slot_info *si, s16 preferred)
++static int __ocfs2_find_empty_slot(struct ocfs2_slot_info *si,
++ int preferred)
+ {
+- int i;
+- s16 ret = OCFS2_INVALID_SLOT;
++ int i, ret = -ENOSPC;
+
+- if (preferred >= 0 && preferred < si->si_num_slots) {
+- if (OCFS2_INVALID_SLOT == si->si_global_node_nums[preferred]) {
++ if ((preferred >= 0) && (preferred < si->si_num_slots)) {
++ if (!si->si_slots[preferred].sl_valid) {
+ ret = preferred;
+ goto out;
+ }
+ }
+
+ for(i = 0; i < si->si_num_slots; i++) {
+- if (OCFS2_INVALID_SLOT == si->si_global_node_nums[i]) {
+- ret = (s16) i;
++ if (!si->si_slots[i].sl_valid) {
++ ret = i;
+ break;
+ }
+ }
+@@ -124,58 +287,155 @@ out:
+ return ret;
+ }
+
+-s16 ocfs2_node_num_to_slot(struct ocfs2_slot_info *si,
+- s16 global)
++int ocfs2_node_num_to_slot(struct ocfs2_super *osb, unsigned int node_num)
+ {
+- s16 ret;
++ int slot;
++ struct ocfs2_slot_info *si = osb->slot_info;
+
+- spin_lock(&si->si_lock);
+- ret = __ocfs2_node_num_to_slot(si, global);
+- spin_unlock(&si->si_lock);
+- return ret;
++ spin_lock(&osb->osb_lock);
++ slot = __ocfs2_node_num_to_slot(si, node_num);
++ spin_unlock(&osb->osb_lock);
++
++ return slot;
++}
++
++int ocfs2_slot_to_node_num_locked(struct ocfs2_super *osb, int slot_num,
++ unsigned int *node_num)
++{
++ struct ocfs2_slot_info *si = osb->slot_info;
++
++ assert_spin_locked(&osb->osb_lock);
++
++ BUG_ON(slot_num < 0);
++ BUG_ON(slot_num > osb->max_slots);
++
++ if (!si->si_slots[slot_num].sl_valid)
++ return -ENOENT;
++
++ *node_num = si->si_slots[slot_num].sl_node_num;
++ return 0;
+ }
+
+-static void __ocfs2_fill_slot(struct ocfs2_slot_info *si,
+- s16 slot_num,
+- s16 node_num)
++static void __ocfs2_free_slot_info(struct ocfs2_slot_info *si)
+ {
+- BUG_ON(slot_num == OCFS2_INVALID_SLOT);
+- BUG_ON(slot_num >= si->si_num_slots);
+- BUG_ON((node_num != O2NM_INVALID_NODE_NUM) &&
+- (node_num >= O2NM_MAX_NODES));
++ unsigned int i;
++
++ if (si == NULL)
++ return;
++
++ if (si->si_inode)
++ iput(si->si_inode);
++ if (si->si_bh) {
++ for (i = 0; i < si->si_blocks; i++) {
++ if (si->si_bh[i]) {
++ brelse(si->si_bh[i]);
++ si->si_bh[i] = NULL;
++ }
++ }
++ kfree(si->si_bh);
++ }
+
+- si->si_global_node_nums[slot_num] = node_num;
++ kfree(si);
+ }
+
+-void ocfs2_clear_slot(struct ocfs2_slot_info *si,
+- s16 slot_num)
++int ocfs2_clear_slot(struct ocfs2_super *osb, int slot_num)
+ {
+- spin_lock(&si->si_lock);
+- __ocfs2_fill_slot(si, slot_num, OCFS2_INVALID_SLOT);
+- spin_unlock(&si->si_lock);
++ struct ocfs2_slot_info *si = osb->slot_info;
++
++ if (si == NULL)
++ return 0;
++
++ spin_lock(&osb->osb_lock);
++ ocfs2_invalidate_slot(si, slot_num);
++ spin_unlock(&osb->osb_lock);
++
++ return ocfs2_update_disk_slot(osb, osb->slot_info, slot_num);
+ }
+
+-int ocfs2_init_slot_info(struct ocfs2_super *osb)
++static int ocfs2_map_slot_buffers(struct ocfs2_super *osb,
++ struct ocfs2_slot_info *si)
+ {
+- int status, i;
++ int status = 0;
+ u64 blkno;
++ unsigned long long blocks, bytes;
++ unsigned int i;
++ struct buffer_head *bh;
++
++ status = ocfs2_slot_map_physical_size(osb, si->si_inode, &bytes);
++ if (status)
++ goto bail;
++
++ blocks = ocfs2_blocks_for_bytes(si->si_inode->i_sb, bytes);
++ BUG_ON(blocks > UINT_MAX);
++ si->si_blocks = blocks;
++ if (!si->si_blocks)
++ goto bail;
++
++ if (si->si_extended)
++ si->si_slots_per_block =
++ (osb->sb->s_blocksize /
++ sizeof(struct ocfs2_extended_slot));
++ else
++ si->si_slots_per_block = osb->sb->s_blocksize / sizeof(__le16);
++
++ /* The size checks above should ensure this */
++ BUG_ON((osb->max_slots / si->si_slots_per_block) > blocks);
++
++ mlog(0, "Slot map needs %u buffers for %llu bytes\n",
++ si->si_blocks, bytes);
++
++ si->si_bh = kzalloc(sizeof(struct buffer_head *) * si->si_blocks,
++ GFP_KERNEL);
++ if (!si->si_bh) {
++ status = -ENOMEM;
++ mlog_errno(status);
++ goto bail;
++ }
++
++ for (i = 0; i < si->si_blocks; i++) {
++ status = ocfs2_extent_map_get_blocks(si->si_inode, i,
++ &blkno, NULL, NULL);
++ if (status < 0) {
++ mlog_errno(status);
++ goto bail;
++ }
++
++ mlog(0, "Reading slot map block %u at %llu\n", i,
++ (unsigned long long)blkno);
++
++ bh = NULL; /* Acquire a fresh bh */
++ status = ocfs2_read_block(osb, blkno, &bh, 0, si->si_inode);
++ if (status < 0) {
++ mlog_errno(status);
++ goto bail;
++ }
++
++ si->si_bh[i] = bh;
++ }
++
++bail:
++ return status;
++}
++
++int ocfs2_init_slot_info(struct ocfs2_super *osb)
++{
++ int status;
+ struct inode *inode = NULL;
+- struct buffer_head *bh = NULL;
+ struct ocfs2_slot_info *si;
+
+- si = kzalloc(sizeof(struct ocfs2_slot_info), GFP_KERNEL);
++ si = kzalloc(sizeof(struct ocfs2_slot_info) +
++ (sizeof(struct ocfs2_slot) * osb->max_slots),
++ GFP_KERNEL);
+ if (!si) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+- spin_lock_init(&si->si_lock);
++ si->si_extended = ocfs2_uses_extended_slot_map(osb);
+ si->si_num_slots = osb->max_slots;
+- si->si_size = OCFS2_MAX_SLOTS;
+-
+- for(i = 0; i < si->si_num_slots; i++)
+- si->si_global_node_nums[i] = OCFS2_INVALID_SLOT;
++ si->si_slots = (struct ocfs2_slot *)((char *)si +
++ sizeof(struct ocfs2_slot_info));
+
+ inode = ocfs2_get_system_file_inode(osb, SLOT_MAP_SYSTEM_INODE,
+ OCFS2_INVALID_SLOT);
+@@ -185,61 +445,53 @@ int ocfs2_init_slot_info(struct ocfs2_super *osb)
+ goto bail;
+ }
+
+- status = ocfs2_extent_map_get_blocks(inode, 0ULL, &blkno, NULL, NULL);
+- if (status < 0) {
+- mlog_errno(status);
+- goto bail;
+- }
+-
+- status = ocfs2_read_block(osb, blkno, &bh, 0, inode);
++ si->si_inode = inode;
++ status = ocfs2_map_slot_buffers(osb, si);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+- si->si_inode = inode;
+- si->si_bh = bh;
+- osb->slot_info = si;
++ osb->slot_info = (struct ocfs2_slot_info *)si;
+ bail:
+ if (status < 0 && si)
+- ocfs2_free_slot_info(si);
++ __ocfs2_free_slot_info(si);
+
+ return status;
+ }
+
+-void ocfs2_free_slot_info(struct ocfs2_slot_info *si)
++void ocfs2_free_slot_info(struct ocfs2_super *osb)
+ {
+- if (si->si_inode)
+- iput(si->si_inode);
+- if (si->si_bh)
+- brelse(si->si_bh);
+- kfree(si);
++ struct ocfs2_slot_info *si = osb->slot_info;
++
++ osb->slot_info = NULL;
++ __ocfs2_free_slot_info(si);
+ }
+
+ int ocfs2_find_slot(struct ocfs2_super *osb)
+ {
+ int status;
+- s16 slot;
++ int slot;
+ struct ocfs2_slot_info *si;
+
+ mlog_entry_void();
+
+ si = osb->slot_info;
+
++ spin_lock(&osb->osb_lock);
+ ocfs2_update_slot_info(si);
+
+- spin_lock(&si->si_lock);
+ /* search for ourselves first and take the slot if it already
+ * exists. Perhaps we need to mark this in a variable for our
+ * own journal recovery? Possibly not, though we certainly
+ * need to warn to the user */
+ slot = __ocfs2_node_num_to_slot(si, osb->node_num);
+- if (slot == OCFS2_INVALID_SLOT) {
++ if (slot < 0) {
+ /* if no slot yet, then just take 1st available
+ * one. */
+ slot = __ocfs2_find_empty_slot(si, osb->preferred_slot);
+- if (slot == OCFS2_INVALID_SLOT) {
+- spin_unlock(&si->si_lock);
++ if (slot < 0) {
++ spin_unlock(&osb->osb_lock);
+ mlog(ML_ERROR, "no free slots available!\n");
+ status = -EINVAL;
+ goto bail;
+@@ -248,13 +500,13 @@ int ocfs2_find_slot(struct ocfs2_super *osb)
+ mlog(ML_NOTICE, "slot %d is already allocated to this node!\n",
+ slot);
+
+- __ocfs2_fill_slot(si, slot, osb->node_num);
++ ocfs2_set_slot(si, slot, osb->node_num);
+ osb->slot_num = slot;
+- spin_unlock(&si->si_lock);
++ spin_unlock(&osb->osb_lock);
+
+ mlog(0, "taking node slot %d\n", osb->slot_num);
+
+- status = ocfs2_update_disk_slots(osb, si);
++ status = ocfs2_update_disk_slot(osb, si, osb->slot_num);
+ if (status < 0)
+ mlog_errno(status);
+
+@@ -265,27 +517,27 @@ bail:
+
+ void ocfs2_put_slot(struct ocfs2_super *osb)
+ {
+- int status;
++ int status, slot_num;
+ struct ocfs2_slot_info *si = osb->slot_info;
+
+ if (!si)
+ return;
+
++ spin_lock(&osb->osb_lock);
+ ocfs2_update_slot_info(si);
+
+- spin_lock(&si->si_lock);
+- __ocfs2_fill_slot(si, osb->slot_num, OCFS2_INVALID_SLOT);
++ slot_num = osb->slot_num;
++ ocfs2_invalidate_slot(si, osb->slot_num);
+ osb->slot_num = OCFS2_INVALID_SLOT;
+- spin_unlock(&si->si_lock);
++ spin_unlock(&osb->osb_lock);
+
+- status = ocfs2_update_disk_slots(osb, si);
++ status = ocfs2_update_disk_slot(osb, si, slot_num);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ bail:
+- osb->slot_info = NULL;
+- ocfs2_free_slot_info(si);
++ ocfs2_free_slot_info(osb);
+ }
+
+diff --git a/fs/ocfs2/slot_map.h b/fs/ocfs2/slot_map.h
+index 1025872..601c95f 100644
+--- a/fs/ocfs2/slot_map.h
++++ b/fs/ocfs2/slot_map.h
+@@ -27,38 +27,18 @@
+ #ifndef SLOTMAP_H
+ #define SLOTMAP_H
+
+-struct ocfs2_slot_info {
+- spinlock_t si_lock;
+-
+- struct inode *si_inode;
+- struct buffer_head *si_bh;
+- unsigned int si_num_slots;
+- unsigned int si_size;
+- s16 si_global_node_nums[OCFS2_MAX_SLOTS];
+-};
+-
+ int ocfs2_init_slot_info(struct ocfs2_super *osb);
+-void ocfs2_free_slot_info(struct ocfs2_slot_info *si);
++void ocfs2_free_slot_info(struct ocfs2_super *osb);
+
+ int ocfs2_find_slot(struct ocfs2_super *osb);
+ void ocfs2_put_slot(struct ocfs2_super *osb);
+
+-void ocfs2_update_slot_info(struct ocfs2_slot_info *si);
+-int ocfs2_update_disk_slots(struct ocfs2_super *osb,
+- struct ocfs2_slot_info *si);
+-
+-s16 ocfs2_node_num_to_slot(struct ocfs2_slot_info *si,
+- s16 global);
+-void ocfs2_clear_slot(struct ocfs2_slot_info *si,
+- s16 slot_num);
++int ocfs2_refresh_slot_info(struct ocfs2_super *osb);
+
+-static inline int ocfs2_is_empty_slot(struct ocfs2_slot_info *si,
+- int slot_num)
+-{
+- BUG_ON(slot_num == OCFS2_INVALID_SLOT);
+- assert_spin_locked(&si->si_lock);
++int ocfs2_node_num_to_slot(struct ocfs2_super *osb, unsigned int node_num);
++int ocfs2_slot_to_node_num_locked(struct ocfs2_super *osb, int slot_num,
++ unsigned int *node_num);
+
+- return si->si_global_node_nums[slot_num] == OCFS2_INVALID_SLOT;
+-}
++int ocfs2_clear_slot(struct ocfs2_super *osb, int slot_num);
+
+ #endif
+diff --git a/fs/ocfs2/stack_o2cb.c b/fs/ocfs2/stack_o2cb.c
+new file mode 100644
+index 0000000..ac1d74c
+--- /dev/null
++++ b/fs/ocfs2/stack_o2cb.c
+@@ -0,0 +1,420 @@
++/* -*- mode: c; c-basic-offset: 8; -*-
++ * vim: noexpandtab sw=8 ts=8 sts=0:
++ *
++ * stack_o2cb.c
++ *
++ * Code which interfaces ocfs2 with the o2cb stack.
++ *
++ * Copyright (C) 2007 Oracle. 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, version 2.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ */
++
++#include <linux/crc32.h>
++#include <linux/module.h>
++
++/* Needed for AOP_TRUNCATED_PAGE in mlog_errno() */
++#include <linux/fs.h>
++
++#include "cluster/masklog.h"
++#include "cluster/nodemanager.h"
++#include "cluster/heartbeat.h"
++
++#include "stackglue.h"
++
++struct o2dlm_private {
++ struct dlm_eviction_cb op_eviction_cb;
++};
++
++static struct ocfs2_stack_plugin o2cb_stack;
++
++/* These should be identical */
++#if (DLM_LOCK_IV != LKM_IVMODE)
++# error Lock modes do not match
++#endif
++#if (DLM_LOCK_NL != LKM_NLMODE)
++# error Lock modes do not match
++#endif
++#if (DLM_LOCK_CR != LKM_CRMODE)
++# error Lock modes do not match
++#endif
++#if (DLM_LOCK_CW != LKM_CWMODE)
++# error Lock modes do not match
++#endif
++#if (DLM_LOCK_PR != LKM_PRMODE)
++# error Lock modes do not match
++#endif
++#if (DLM_LOCK_PW != LKM_PWMODE)
++# error Lock modes do not match
++#endif
++#if (DLM_LOCK_EX != LKM_EXMODE)
++# error Lock modes do not match
++#endif
++static inline int mode_to_o2dlm(int mode)
++{
++ BUG_ON(mode > LKM_MAXMODE);
++
++ return mode;
++}
++
++#define map_flag(_generic, _o2dlm) \
++ if (flags & (_generic)) { \
++ flags &= ~(_generic); \
++ o2dlm_flags |= (_o2dlm); \
++ }
++static int flags_to_o2dlm(u32 flags)
++{
++ int o2dlm_flags = 0;
++
++ map_flag(DLM_LKF_NOQUEUE, LKM_NOQUEUE);
++ map_flag(DLM_LKF_CANCEL, LKM_CANCEL);
++ map_flag(DLM_LKF_CONVERT, LKM_CONVERT);
++ map_flag(DLM_LKF_VALBLK, LKM_VALBLK);
++ map_flag(DLM_LKF_IVVALBLK, LKM_INVVALBLK);
++ map_flag(DLM_LKF_ORPHAN, LKM_ORPHAN);
++ map_flag(DLM_LKF_FORCEUNLOCK, LKM_FORCE);
++ map_flag(DLM_LKF_TIMEOUT, LKM_TIMEOUT);
++ map_flag(DLM_LKF_LOCAL, LKM_LOCAL);
++
++ /* map_flag() should have cleared every flag passed in */
++ BUG_ON(flags != 0);
++
++ return o2dlm_flags;
++}
++#undef map_flag
++
++/*
++ * Map an o2dlm status to standard errno values.
++ *
++ * o2dlm only uses a handful of these, and returns even fewer to the
++ * caller. Still, we try to assign sane values to each error.
++ *
++ * The following value pairs have special meanings to dlmglue, thus
++ * the right hand side needs to stay unique - never duplicate the
++ * mapping elsewhere in the table!
++ *
++ * DLM_NORMAL: 0
++ * DLM_NOTQUEUED: -EAGAIN
++ * DLM_CANCELGRANT: -EBUSY
++ * DLM_CANCEL: -DLM_ECANCEL
++ */
++/* Keep in sync with dlmapi.h */
++static int status_map[] = {
++ [DLM_NORMAL] = 0, /* Success */
++ [DLM_GRANTED] = -EINVAL,
++ [DLM_DENIED] = -EACCES,
++ [DLM_DENIED_NOLOCKS] = -EACCES,
++ [DLM_WORKING] = -EACCES,
++ [DLM_BLOCKED] = -EINVAL,
++ [DLM_BLOCKED_ORPHAN] = -EINVAL,
++ [DLM_DENIED_GRACE_PERIOD] = -EACCES,
++ [DLM_SYSERR] = -ENOMEM, /* It is what it is */
++ [DLM_NOSUPPORT] = -EPROTO,
++ [DLM_CANCELGRANT] = -EBUSY, /* Cancel after grant */
++ [DLM_IVLOCKID] = -EINVAL,
++ [DLM_SYNC] = -EINVAL,
++ [DLM_BADTYPE] = -EINVAL,
++ [DLM_BADRESOURCE] = -EINVAL,
++ [DLM_MAXHANDLES] = -ENOMEM,
++ [DLM_NOCLINFO] = -EINVAL,
++ [DLM_NOLOCKMGR] = -EINVAL,
++ [DLM_NOPURGED] = -EINVAL,
++ [DLM_BADARGS] = -EINVAL,
++ [DLM_VOID] = -EINVAL,
++ [DLM_NOTQUEUED] = -EAGAIN, /* Trylock failed */
++ [DLM_IVBUFLEN] = -EINVAL,
++ [DLM_CVTUNGRANT] = -EPERM,
++ [DLM_BADPARAM] = -EINVAL,
++ [DLM_VALNOTVALID] = -EINVAL,
++ [DLM_REJECTED] = -EPERM,
++ [DLM_ABORT] = -EINVAL,
++ [DLM_CANCEL] = -DLM_ECANCEL, /* Successful cancel */
++ [DLM_IVRESHANDLE] = -EINVAL,
++ [DLM_DEADLOCK] = -EDEADLK,
++ [DLM_DENIED_NOASTS] = -EINVAL,
++ [DLM_FORWARD] = -EINVAL,
++ [DLM_TIMEOUT] = -ETIMEDOUT,
++ [DLM_IVGROUPID] = -EINVAL,
++ [DLM_VERS_CONFLICT] = -EOPNOTSUPP,
++ [DLM_BAD_DEVICE_PATH] = -ENOENT,
++ [DLM_NO_DEVICE_PERMISSION] = -EPERM,
++ [DLM_NO_CONTROL_DEVICE] = -ENOENT,
++ [DLM_RECOVERING] = -ENOTCONN,
++ [DLM_MIGRATING] = -ERESTART,
++ [DLM_MAXSTATS] = -EINVAL,
++};
++
++static int dlm_status_to_errno(enum dlm_status status)
++{
++ BUG_ON(status > (sizeof(status_map) / sizeof(status_map[0])));
++
++ return status_map[status];
++}
++
++static void o2dlm_lock_ast_wrapper(void *astarg)
++{
++ BUG_ON(o2cb_stack.sp_proto == NULL);
++
++ o2cb_stack.sp_proto->lp_lock_ast(astarg);
++}
++
++static void o2dlm_blocking_ast_wrapper(void *astarg, int level)
++{
++ BUG_ON(o2cb_stack.sp_proto == NULL);
++
++ o2cb_stack.sp_proto->lp_blocking_ast(astarg, level);
++}
++
++static void o2dlm_unlock_ast_wrapper(void *astarg, enum dlm_status status)
++{
++ int error = dlm_status_to_errno(status);
++
++ BUG_ON(o2cb_stack.sp_proto == NULL);
++
++ /*
++ * In o2dlm, you can get both the lock_ast() for the lock being
++ * granted and the unlock_ast() for the CANCEL failing. A
++ * successful cancel sends DLM_NORMAL here. If the
++ * lock grant happened before the cancel arrived, you get
++ * DLM_CANCELGRANT.
++ *
++ * There's no need for the double-ast. If we see DLM_CANCELGRANT,
++ * we just ignore it. We expect the lock_ast() to handle the
++ * granted lock.
++ */
++ if (status == DLM_CANCELGRANT)
++ return;
++
++ o2cb_stack.sp_proto->lp_unlock_ast(astarg, error);
++}
++
++static int o2cb_dlm_lock(struct ocfs2_cluster_connection *conn,
++ int mode,
++ union ocfs2_dlm_lksb *lksb,
++ u32 flags,
++ void *name,
++ unsigned int namelen,
++ void *astarg)
++{
++ enum dlm_status status;
++ int o2dlm_mode = mode_to_o2dlm(mode);
++ int o2dlm_flags = flags_to_o2dlm(flags);
++ int ret;
++
++ status = dlmlock(conn->cc_lockspace, o2dlm_mode, &lksb->lksb_o2dlm,
++ o2dlm_flags, name, namelen,
++ o2dlm_lock_ast_wrapper, astarg,
++ o2dlm_blocking_ast_wrapper);
++ ret = dlm_status_to_errno(status);
++ return ret;
++}
++
++static int o2cb_dlm_unlock(struct ocfs2_cluster_connection *conn,
++ union ocfs2_dlm_lksb *lksb,
++ u32 flags,
++ void *astarg)
++{
++ enum dlm_status status;
++ int o2dlm_flags = flags_to_o2dlm(flags);
++ int ret;
++
++ status = dlmunlock(conn->cc_lockspace, &lksb->lksb_o2dlm,
++ o2dlm_flags, o2dlm_unlock_ast_wrapper, astarg);
++ ret = dlm_status_to_errno(status);
++ return ret;
++}
++
++static int o2cb_dlm_lock_status(union ocfs2_dlm_lksb *lksb)
++{
++ return dlm_status_to_errno(lksb->lksb_o2dlm.status);
++}
++
++static void *o2cb_dlm_lvb(union ocfs2_dlm_lksb *lksb)
++{
++ return (void *)(lksb->lksb_o2dlm.lvb);
++}
++
++static void o2cb_dump_lksb(union ocfs2_dlm_lksb *lksb)
++{
++ dlm_print_one_lock(lksb->lksb_o2dlm.lockid);
++}
++
++/*
++ * Called from the dlm when it's about to evict a node. This is how the
++ * classic stack signals node death.
++ */
++static void o2dlm_eviction_cb(int node_num, void *data)
++{
++ struct ocfs2_cluster_connection *conn = data;
++
++ mlog(ML_NOTICE, "o2dlm has evicted node %d from group %.*s\n",
++ node_num, conn->cc_namelen, conn->cc_name);
++
++ conn->cc_recovery_handler(node_num, conn->cc_recovery_data);
++}
++
++static int o2cb_cluster_connect(struct ocfs2_cluster_connection *conn)
++{
++ int rc = 0;
++ u32 dlm_key;
++ struct dlm_ctxt *dlm;
++ struct o2dlm_private *priv;
++ struct dlm_protocol_version dlm_version;
++
++ BUG_ON(conn == NULL);
++ BUG_ON(o2cb_stack.sp_proto == NULL);
++
++ /* for now we only have one cluster/node, make sure we see it
++ * in the heartbeat universe */
++ if (!o2hb_check_local_node_heartbeating()) {
++ rc = -EINVAL;
++ goto out;
++ }
++
++ priv = kzalloc(sizeof(struct o2dlm_private), GFP_KERNEL);
++ if (!priv) {
++ rc = -ENOMEM;
++ goto out_free;
++ }
++
++ /* This just fills the structure in. It is safe to pass conn. */
++ dlm_setup_eviction_cb(&priv->op_eviction_cb, o2dlm_eviction_cb,
++ conn);
++
++ conn->cc_private = priv;
++
++ /* used by the dlm code to make message headers unique, each
++ * node in this domain must agree on this. */
++ dlm_key = crc32_le(0, conn->cc_name, conn->cc_namelen);
++ dlm_version.pv_major = conn->cc_version.pv_major;
++ dlm_version.pv_minor = conn->cc_version.pv_minor;
++
++ dlm = dlm_register_domain(conn->cc_name, dlm_key, &dlm_version);
++ if (IS_ERR(dlm)) {
++ rc = PTR_ERR(dlm);
++ mlog_errno(rc);
++ goto out_free;
++ }
++
++ conn->cc_version.pv_major = dlm_version.pv_major;
++ conn->cc_version.pv_minor = dlm_version.pv_minor;
++ conn->cc_lockspace = dlm;
++
++ dlm_register_eviction_cb(dlm, &priv->op_eviction_cb);
++
++out_free:
++ if (rc && conn->cc_private)
++ kfree(conn->cc_private);
++
++out:
++ return rc;
++}
++
++static int o2cb_cluster_disconnect(struct ocfs2_cluster_connection *conn,
++ int hangup_pending)
++{
++ struct dlm_ctxt *dlm = conn->cc_lockspace;
++ struct o2dlm_private *priv = conn->cc_private;
++
++ dlm_unregister_eviction_cb(&priv->op_eviction_cb);
++ conn->cc_private = NULL;
++ kfree(priv);
++
++ dlm_unregister_domain(dlm);
++ conn->cc_lockspace = NULL;
++
++ return 0;
++}
++
++static void o2hb_stop(const char *group)
++{
++ int ret;
++ char *argv[5], *envp[3];
++
++ argv[0] = (char *)o2nm_get_hb_ctl_path();
++ argv[1] = "-K";
++ argv[2] = "-u";
++ argv[3] = (char *)group;
++ argv[4] = NULL;
++
++ mlog(0, "Run: %s %s %s %s\n", argv[0], argv[1], argv[2], argv[3]);
++
++ /* minimal command environment taken from cpu_run_sbin_hotplug */
++ envp[0] = "HOME=/";
++ envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
++ envp[2] = NULL;
++
++ ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
++ if (ret < 0)
++ mlog_errno(ret);
++}
++
++/*
++ * Hangup is a hack for tools compatibility. Older ocfs2-tools software
++ * expects the filesystem to call "ocfs2_hb_ctl" during unmount. This
++ * happens regardless of whether the DLM got started, so we can't do it
++ * in ocfs2_cluster_disconnect(). We bring the o2hb_stop() function into
++ * the glue and provide a "hangup" API for super.c to call.
++ *
++ * Other stacks will eventually provide a NULL ->hangup() pointer.
++ */
++static void o2cb_cluster_hangup(const char *group, int grouplen)
++{
++ o2hb_stop(group);
++}
++
++static int o2cb_cluster_this_node(unsigned int *node)
++{
++ int node_num;
++
++ node_num = o2nm_this_node();
++ if (node_num == O2NM_INVALID_NODE_NUM)
++ return -ENOENT;
++
++ if (node_num >= O2NM_MAX_NODES)
++ return -EOVERFLOW;
++
++ *node = node_num;
++ return 0;
++}
++
++struct ocfs2_stack_operations o2cb_stack_ops = {
++ .connect = o2cb_cluster_connect,
++ .disconnect = o2cb_cluster_disconnect,
++ .hangup = o2cb_cluster_hangup,
++ .this_node = o2cb_cluster_this_node,
++ .dlm_lock = o2cb_dlm_lock,
++ .dlm_unlock = o2cb_dlm_unlock,
++ .lock_status = o2cb_dlm_lock_status,
++ .lock_lvb = o2cb_dlm_lvb,
++ .dump_lksb = o2cb_dump_lksb,
++};
++
++static struct ocfs2_stack_plugin o2cb_stack = {
++ .sp_name = "o2cb",
++ .sp_ops = &o2cb_stack_ops,
++ .sp_owner = THIS_MODULE,
++};
++
++static int __init o2cb_stack_init(void)
++{
++ return ocfs2_stack_glue_register(&o2cb_stack);
++}
++
++static void __exit o2cb_stack_exit(void)
++{
++ ocfs2_stack_glue_unregister(&o2cb_stack);
++}
++
++MODULE_AUTHOR("Oracle");
++MODULE_DESCRIPTION("ocfs2 driver for the classic o2cb stack");
++MODULE_LICENSE("GPL");
++module_init(o2cb_stack_init);
++module_exit(o2cb_stack_exit);
+diff --git a/fs/ocfs2/stack_user.c b/fs/ocfs2/stack_user.c
+new file mode 100644
+index 0000000..7428663
+--- /dev/null
++++ b/fs/ocfs2/stack_user.c
+@@ -0,0 +1,883 @@
++/* -*- mode: c; c-basic-offset: 8; -*-
++ * vim: noexpandtab sw=8 ts=8 sts=0:
++ *
++ * stack_user.c
++ *
++ * Code which interfaces ocfs2 with fs/dlm and a userspace stack.
++ *
++ * Copyright (C) 2007 Oracle. 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, version 2.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ */
++
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/miscdevice.h>
++#include <linux/mutex.h>
++#include <linux/reboot.h>
++#include <asm/uaccess.h>
++
++#include "ocfs2.h" /* For struct ocfs2_lock_res */
++#include "stackglue.h"
++
++
++/*
++ * The control protocol starts with a handshake. Until the handshake
++ * is complete, the control device will fail all write(2)s.
++ *
++ * The handshake is simple. First, the client reads until EOF. Each line
++ * of output is a supported protocol tag. All protocol tags are a single
++ * character followed by a two hex digit version number. Currently the
++ * only things supported is T01, for "Text-base version 0x01". Next, the
++ * client writes the version they would like to use, including the newline.
++ * Thus, the protocol tag is 'T01\n'. If the version tag written is
++ * unknown, -EINVAL is returned. Once the negotiation is complete, the
++ * client can start sending messages.
++ *
++ * The T01 protocol has three messages. First is the "SETN" message.
++ * It has the following syntax:
++ *
++ * SETN<space><8-char-hex-nodenum><newline>
++ *
++ * This is 14 characters.
++ *
++ * The "SETN" message must be the first message following the protocol.
++ * It tells ocfs2_control the local node number.
++ *
++ * Next comes the "SETV" message. It has the following syntax:
++ *
++ * SETV<space><2-char-hex-major><space><2-char-hex-minor><newline>
++ *
++ * This is 11 characters.
++ *
++ * The "SETV" message sets the filesystem locking protocol version as
++ * negotiated by the client. The client negotiates based on the maximum
++ * version advertised in /sys/fs/ocfs2/max_locking_protocol. The major
++ * number from the "SETV" message must match
++ * user_stack.sp_proto->lp_max_version.pv_major, and the minor number
++ * must be less than or equal to ...->lp_max_version.pv_minor.
++ *
++ * Once this information has been set, mounts will be allowed. From this
++ * point on, the "DOWN" message can be sent for node down notification.
++ * It has the following syntax:
++ *
++ * DOWN<space><32-char-cap-hex-uuid><space><8-char-hex-nodenum><newline>
++ *
++ * eg:
++ *
++ * DOWN 632A924FDD844190BDA93C0DF6B94899 00000001\n
++ *
++ * This is 47 characters.
++ */
++
++/*
++ * Whether or not the client has done the handshake.
++ * For now, we have just one protocol version.
++ */
++#define OCFS2_CONTROL_PROTO "T01\n"
++#define OCFS2_CONTROL_PROTO_LEN 4
++
++/* Handshake states */
++#define OCFS2_CONTROL_HANDSHAKE_INVALID (0)
++#define OCFS2_CONTROL_HANDSHAKE_READ (1)
++#define OCFS2_CONTROL_HANDSHAKE_PROTOCOL (2)
++#define OCFS2_CONTROL_HANDSHAKE_VALID (3)
++
++/* Messages */
++#define OCFS2_CONTROL_MESSAGE_OP_LEN 4
++#define OCFS2_CONTROL_MESSAGE_SETNODE_OP "SETN"
++#define OCFS2_CONTROL_MESSAGE_SETNODE_TOTAL_LEN 14
++#define OCFS2_CONTROL_MESSAGE_SETVERSION_OP "SETV"
++#define OCFS2_CONTROL_MESSAGE_SETVERSION_TOTAL_LEN 11
++#define OCFS2_CONTROL_MESSAGE_DOWN_OP "DOWN"
++#define OCFS2_CONTROL_MESSAGE_DOWN_TOTAL_LEN 47
++#define OCFS2_TEXT_UUID_LEN 32
++#define OCFS2_CONTROL_MESSAGE_VERNUM_LEN 2
++#define OCFS2_CONTROL_MESSAGE_NODENUM_LEN 8
++
++/*
++ * ocfs2_live_connection is refcounted because the filesystem and
++ * miscdevice sides can detach in different order. Let's just be safe.
++ */
++struct ocfs2_live_connection {
++ struct list_head oc_list;
++ struct ocfs2_cluster_connection *oc_conn;
++};
++
++struct ocfs2_control_private {
++ struct list_head op_list;
++ int op_state;
++ int op_this_node;
++ struct ocfs2_protocol_version op_proto;
++};
++
++/* SETN<space><8-char-hex-nodenum><newline> */
++struct ocfs2_control_message_setn {
++ char tag[OCFS2_CONTROL_MESSAGE_OP_LEN];
++ char space;
++ char nodestr[OCFS2_CONTROL_MESSAGE_NODENUM_LEN];
++ char newline;
++};
++
++/* SETV<space><2-char-hex-major><space><2-char-hex-minor><newline> */
++struct ocfs2_control_message_setv {
++ char tag[OCFS2_CONTROL_MESSAGE_OP_LEN];
++ char space1;
++ char major[OCFS2_CONTROL_MESSAGE_VERNUM_LEN];
++ char space2;
++ char minor[OCFS2_CONTROL_MESSAGE_VERNUM_LEN];
++ char newline;
++};
++
++/* DOWN<space><32-char-cap-hex-uuid><space><8-char-hex-nodenum><newline> */
++struct ocfs2_control_message_down {
++ char tag[OCFS2_CONTROL_MESSAGE_OP_LEN];
++ char space1;
++ char uuid[OCFS2_TEXT_UUID_LEN];
++ char space2;
++ char nodestr[OCFS2_CONTROL_MESSAGE_NODENUM_LEN];
++ char newline;
++};
++
++union ocfs2_control_message {
++ char tag[OCFS2_CONTROL_MESSAGE_OP_LEN];
++ struct ocfs2_control_message_setn u_setn;
++ struct ocfs2_control_message_setv u_setv;
++ struct ocfs2_control_message_down u_down;
++};
++
++static struct ocfs2_stack_plugin user_stack;
++
++static atomic_t ocfs2_control_opened;
++static int ocfs2_control_this_node = -1;
++static struct ocfs2_protocol_version running_proto;
++
++static LIST_HEAD(ocfs2_live_connection_list);
++static LIST_HEAD(ocfs2_control_private_list);
++static DEFINE_MUTEX(ocfs2_control_lock);
++
++static inline void ocfs2_control_set_handshake_state(struct file *file,
++ int state)
++{
++ struct ocfs2_control_private *p = file->private_data;
++ p->op_state = state;
++}
++
++static inline int ocfs2_control_get_handshake_state(struct file *file)
++{
++ struct ocfs2_control_private *p = file->private_data;
++ return p->op_state;
++}
++
++static struct ocfs2_live_connection *ocfs2_connection_find(const char *name)
++{
++ size_t len = strlen(name);
++ struct ocfs2_live_connection *c;
++
++ BUG_ON(!mutex_is_locked(&ocfs2_control_lock));
++
++ list_for_each_entry(c, &ocfs2_live_connection_list, oc_list) {
++ if ((c->oc_conn->cc_namelen == len) &&
++ !strncmp(c->oc_conn->cc_name, name, len))
++ return c;
++ }
++
++ return c;
++}
++
++/*
++ * ocfs2_live_connection structures are created underneath the ocfs2
++ * mount path. Since the VFS prevents multiple calls to
++ * fill_super(), we can't get dupes here.
++ */
++static int ocfs2_live_connection_new(struct ocfs2_cluster_connection *conn,
++ struct ocfs2_live_connection **c_ret)
++{
++ int rc = 0;
++ struct ocfs2_live_connection *c;
++
++ c = kzalloc(sizeof(struct ocfs2_live_connection), GFP_KERNEL);
++ if (!c)
++ return -ENOMEM;
++
++ mutex_lock(&ocfs2_control_lock);
++ c->oc_conn = conn;
++
++ if (atomic_read(&ocfs2_control_opened))
++ list_add(&c->oc_list, &ocfs2_live_connection_list);
++ else {
++ printk(KERN_ERR
++ "ocfs2: Userspace control daemon is not present\n");
++ rc = -ESRCH;
++ }
++
++ mutex_unlock(&ocfs2_control_lock);
++
++ if (!rc)
++ *c_ret = c;
++ else
++ kfree(c);
++
++ return rc;
++}
++
++/*
++ * This function disconnects the cluster connection from ocfs2_control.
++ * Afterwards, userspace can't affect the cluster connection.
++ */
++static void ocfs2_live_connection_drop(struct ocfs2_live_connection *c)
++{
++ mutex_lock(&ocfs2_control_lock);
++ list_del_init(&c->oc_list);
++ c->oc_conn = NULL;
++ mutex_unlock(&ocfs2_control_lock);
++
++ kfree(c);
++}
++
++static int ocfs2_control_cfu(void *target, size_t target_len,
++ const char __user *buf, size_t count)
++{
++ /* The T01 expects write(2) calls to have exactly one command */
++ if ((count != target_len) ||
++ (count > sizeof(union ocfs2_control_message)))
++ return -EINVAL;
++
++ if (copy_from_user(target, buf, target_len))
++ return -EFAULT;
++
++ return 0;
++}
++
++static ssize_t ocfs2_control_validate_protocol(struct file *file,
++ const char __user *buf,
++ size_t count)
++{
++ ssize_t ret;
++ char kbuf[OCFS2_CONTROL_PROTO_LEN];
++
++ ret = ocfs2_control_cfu(kbuf, OCFS2_CONTROL_PROTO_LEN,
++ buf, count);
++ if (ret)
++ return ret;
++
++ if (strncmp(kbuf, OCFS2_CONTROL_PROTO, OCFS2_CONTROL_PROTO_LEN))
++ return -EINVAL;
++
++ ocfs2_control_set_handshake_state(file,
++ OCFS2_CONTROL_HANDSHAKE_PROTOCOL);
++
++ return count;
++}
++
++static void ocfs2_control_send_down(const char *uuid,
++ int nodenum)
++{
++ struct ocfs2_live_connection *c;
++
++ mutex_lock(&ocfs2_control_lock);
++
++ c = ocfs2_connection_find(uuid);
++ if (c) {
++ BUG_ON(c->oc_conn == NULL);
++ c->oc_conn->cc_recovery_handler(nodenum,
++ c->oc_conn->cc_recovery_data);
++ }
++
++ mutex_unlock(&ocfs2_control_lock);
++}
++
++/*
++ * Called whenever configuration elements are sent to /dev/ocfs2_control.
++ * If all configuration elements are present, try to set the global
++ * values. If there is a problem, return an error. Skip any missing
++ * elements, and only bump ocfs2_control_opened when we have all elements
++ * and are successful.
++ */
++static int ocfs2_control_install_private(struct file *file)
++{
++ int rc = 0;
++ int set_p = 1;
++ struct ocfs2_control_private *p = file->private_data;
++
++ BUG_ON(p->op_state != OCFS2_CONTROL_HANDSHAKE_PROTOCOL);
++
++ mutex_lock(&ocfs2_control_lock);
++
++ if (p->op_this_node < 0) {
++ set_p = 0;
++ } else if ((ocfs2_control_this_node >= 0) &&
++ (ocfs2_control_this_node != p->op_this_node)) {
++ rc = -EINVAL;
++ goto out_unlock;
++ }
++
++ if (!p->op_proto.pv_major) {
++ set_p = 0;
++ } else if (!list_empty(&ocfs2_live_connection_list) &&
++ ((running_proto.pv_major != p->op_proto.pv_major) ||
++ (running_proto.pv_minor != p->op_proto.pv_minor))) {
++ rc = -EINVAL;
++ goto out_unlock;
++ }
++
++ if (set_p) {
++ ocfs2_control_this_node = p->op_this_node;
++ running_proto.pv_major = p->op_proto.pv_major;
++ running_proto.pv_minor = p->op_proto.pv_minor;
++ }
++
++out_unlock:
++ mutex_unlock(&ocfs2_control_lock);
++
++ if (!rc && set_p) {
++ /* We set the global values successfully */
++ atomic_inc(&ocfs2_control_opened);
++ ocfs2_control_set_handshake_state(file,
++ OCFS2_CONTROL_HANDSHAKE_VALID);
++ }
++
++ return rc;
++}
++
++static int ocfs2_control_get_this_node(void)
++{
++ int rc;
++
++ mutex_lock(&ocfs2_control_lock);
++ if (ocfs2_control_this_node < 0)
++ rc = -EINVAL;
++ else
++ rc = ocfs2_control_this_node;
++ mutex_unlock(&ocfs2_control_lock);
++
++ return rc;
++}
++
++static int ocfs2_control_do_setnode_msg(struct file *file,
++ struct ocfs2_control_message_setn *msg)
++{
++ long nodenum;
++ char *ptr = NULL;
++ struct ocfs2_control_private *p = file->private_data;
++
++ if (ocfs2_control_get_handshake_state(file) !=
++ OCFS2_CONTROL_HANDSHAKE_PROTOCOL)
++ return -EINVAL;
++
++ if (strncmp(msg->tag, OCFS2_CONTROL_MESSAGE_SETNODE_OP,
++ OCFS2_CONTROL_MESSAGE_OP_LEN))
++ return -EINVAL;
++
++ if ((msg->space != ' ') || (msg->newline != '\n'))
++ return -EINVAL;
++ msg->space = msg->newline = '\0';
++
++ nodenum = simple_strtol(msg->nodestr, &ptr, 16);
++ if (!ptr || *ptr)
++ return -EINVAL;
++
++ if ((nodenum == LONG_MIN) || (nodenum == LONG_MAX) ||
++ (nodenum > INT_MAX) || (nodenum < 0))
++ return -ERANGE;
++ p->op_this_node = nodenum;
++
++ return ocfs2_control_install_private(file);
++}
++
++static int ocfs2_control_do_setversion_msg(struct file *file,
++ struct ocfs2_control_message_setv *msg)
++ {
++ long major, minor;
++ char *ptr = NULL;
++ struct ocfs2_control_private *p = file->private_data;
++ struct ocfs2_protocol_version *max =
++ &user_stack.sp_proto->lp_max_version;
++
++ if (ocfs2_control_get_handshake_state(file) !=
++ OCFS2_CONTROL_HANDSHAKE_PROTOCOL)
++ return -EINVAL;
++
++ if (strncmp(msg->tag, OCFS2_CONTROL_MESSAGE_SETVERSION_OP,
++ OCFS2_CONTROL_MESSAGE_OP_LEN))
++ return -EINVAL;
++
++ if ((msg->space1 != ' ') || (msg->space2 != ' ') ||
++ (msg->newline != '\n'))
++ return -EINVAL;
++ msg->space1 = msg->space2 = msg->newline = '\0';
++
++ major = simple_strtol(msg->major, &ptr, 16);
++ if (!ptr || *ptr)
++ return -EINVAL;
++ minor = simple_strtol(msg->minor, &ptr, 16);
++ if (!ptr || *ptr)
++ return -EINVAL;
++
++ /*
++ * The major must be between 1 and 255, inclusive. The minor
++ * must be between 0 and 255, inclusive. The version passed in
++ * must be within the maximum version supported by the filesystem.
++ */
++ if ((major == LONG_MIN) || (major == LONG_MAX) ||
++ (major > (u8)-1) || (major < 1))
++ return -ERANGE;
++ if ((minor == LONG_MIN) || (minor == LONG_MAX) ||
++ (minor > (u8)-1) || (minor < 0))
++ return -ERANGE;
++ if ((major != max->pv_major) ||
++ (minor > max->pv_minor))
++ return -EINVAL;
++
++ p->op_proto.pv_major = major;
++ p->op_proto.pv_minor = minor;
++
++ return ocfs2_control_install_private(file);
++}
++
++static int ocfs2_control_do_down_msg(struct file *file,
++ struct ocfs2_control_message_down *msg)
++{
++ long nodenum;
++ char *p = NULL;
++
++ if (ocfs2_control_get_handshake_state(file) !=
++ OCFS2_CONTROL_HANDSHAKE_VALID)
++ return -EINVAL;
++
++ if (strncmp(msg->tag, OCFS2_CONTROL_MESSAGE_DOWN_OP,
++ OCFS2_CONTROL_MESSAGE_OP_LEN))
++ return -EINVAL;
++
++ if ((msg->space1 != ' ') || (msg->space2 != ' ') ||
++ (msg->newline != '\n'))
++ return -EINVAL;
++ msg->space1 = msg->space2 = msg->newline = '\0';
++
++ nodenum = simple_strtol(msg->nodestr, &p, 16);
++ if (!p || *p)
++ return -EINVAL;
++
++ if ((nodenum == LONG_MIN) || (nodenum == LONG_MAX) ||
++ (nodenum > INT_MAX) || (nodenum < 0))
++ return -ERANGE;
++
++ ocfs2_control_send_down(msg->uuid, nodenum);
++
++ return 0;
++}
++
++static ssize_t ocfs2_control_message(struct file *file,
++ const char __user *buf,
++ size_t count)
++{
++ ssize_t ret;
++ union ocfs2_control_message msg;
++
++ /* Try to catch padding issues */
++ WARN_ON(offsetof(struct ocfs2_control_message_down, uuid) !=
++ (sizeof(msg.u_down.tag) + sizeof(msg.u_down.space1)));
++
++ memset(&msg, 0, sizeof(union ocfs2_control_message));
++ ret = ocfs2_control_cfu(&msg, count, buf, count);
++ if (ret)
++ goto out;
++
++ if ((count == OCFS2_CONTROL_MESSAGE_SETNODE_TOTAL_LEN) &&
++ !strncmp(msg.tag, OCFS2_CONTROL_MESSAGE_SETNODE_OP,
++ OCFS2_CONTROL_MESSAGE_OP_LEN))
++ ret = ocfs2_control_do_setnode_msg(file, &msg.u_setn);
++ else if ((count == OCFS2_CONTROL_MESSAGE_SETVERSION_TOTAL_LEN) &&
++ !strncmp(msg.tag, OCFS2_CONTROL_MESSAGE_SETVERSION_OP,
++ OCFS2_CONTROL_MESSAGE_OP_LEN))
++ ret = ocfs2_control_do_setversion_msg(file, &msg.u_setv);
++ else if ((count == OCFS2_CONTROL_MESSAGE_DOWN_TOTAL_LEN) &&
++ !strncmp(msg.tag, OCFS2_CONTROL_MESSAGE_DOWN_OP,
++ OCFS2_CONTROL_MESSAGE_OP_LEN))
++ ret = ocfs2_control_do_down_msg(file, &msg.u_down);
++ else
++ ret = -EINVAL;
++
++out:
++ return ret ? ret : count;
++}
++
++static ssize_t ocfs2_control_write(struct file *file,
++ const char __user *buf,
++ size_t count,
++ loff_t *ppos)
++{
++ ssize_t ret;
++
++ switch (ocfs2_control_get_handshake_state(file)) {
++ case OCFS2_CONTROL_HANDSHAKE_INVALID:
++ ret = -EINVAL;
++ break;
++
++ case OCFS2_CONTROL_HANDSHAKE_READ:
++ ret = ocfs2_control_validate_protocol(file, buf,
++ count);
++ break;
++
++ case OCFS2_CONTROL_HANDSHAKE_PROTOCOL:
++ case OCFS2_CONTROL_HANDSHAKE_VALID:
++ ret = ocfs2_control_message(file, buf, count);
++ break;
++
++ default:
++ BUG();
++ ret = -EIO;
++ break;
++ }
++
++ return ret;
++}
++
++/*
++ * This is a naive version. If we ever have a new protocol, we'll expand
++ * it. Probably using seq_file.
++ */
++static ssize_t ocfs2_control_read(struct file *file,
++ char __user *buf,
++ size_t count,
++ loff_t *ppos)
++{
++ char *proto_string = OCFS2_CONTROL_PROTO;
++ size_t to_write = 0;
++
++ if (*ppos >= OCFS2_CONTROL_PROTO_LEN)
++ return 0;
++
++ to_write = OCFS2_CONTROL_PROTO_LEN - *ppos;
++ if (to_write > count)
++ to_write = count;
++ if (copy_to_user(buf, proto_string + *ppos, to_write))
++ return -EFAULT;
++
++ *ppos += to_write;
++
++ /* Have we read the whole protocol list? */
++ if (*ppos >= OCFS2_CONTROL_PROTO_LEN)
++ ocfs2_control_set_handshake_state(file,
++ OCFS2_CONTROL_HANDSHAKE_READ);
++
++ return to_write;
++}
++
++static int ocfs2_control_release(struct inode *inode, struct file *file)
++{
++ struct ocfs2_control_private *p = file->private_data;
++
++ mutex_lock(&ocfs2_control_lock);
++
++ if (ocfs2_control_get_handshake_state(file) !=
++ OCFS2_CONTROL_HANDSHAKE_VALID)
++ goto out;
++
++ if (atomic_dec_and_test(&ocfs2_control_opened)) {
++ if (!list_empty(&ocfs2_live_connection_list)) {
++ /* XXX: Do bad things! */
++ printk(KERN_ERR
++ "ocfs2: Unexpected release of ocfs2_control!\n"
++ " Loss of cluster connection requires "
++ "an emergency restart!\n");
++ emergency_restart();
++ }
++ /*
++ * Last valid close clears the node number and resets
++ * the locking protocol version
++ */
++ ocfs2_control_this_node = -1;
++ running_proto.pv_major = 0;
++ running_proto.pv_major = 0;
++ }
++
++out:
++ list_del_init(&p->op_list);
++ file->private_data = NULL;
++
++ mutex_unlock(&ocfs2_control_lock);
++
++ kfree(p);
++
++ return 0;
++}
++
++static int ocfs2_control_open(struct inode *inode, struct file *file)
++{
++ struct ocfs2_control_private *p;
++
++ p = kzalloc(sizeof(struct ocfs2_control_private), GFP_KERNEL);
++ if (!p)
++ return -ENOMEM;
++ p->op_this_node = -1;
++
++ mutex_lock(&ocfs2_control_lock);
++ file->private_data = p;
++ list_add(&p->op_list, &ocfs2_control_private_list);
++ mutex_unlock(&ocfs2_control_lock);
++
++ return 0;
++}
++
++static const struct file_operations ocfs2_control_fops = {
++ .open = ocfs2_control_open,
++ .release = ocfs2_control_release,
++ .read = ocfs2_control_read,
++ .write = ocfs2_control_write,
++ .owner = THIS_MODULE,
++};
++
++struct miscdevice ocfs2_control_device = {
++ .minor = MISC_DYNAMIC_MINOR,
++ .name = "ocfs2_control",
++ .fops = &ocfs2_control_fops,
++};
++
++static int ocfs2_control_init(void)
++{
++ int rc;
++
++ atomic_set(&ocfs2_control_opened, 0);
++
++ rc = misc_register(&ocfs2_control_device);
++ if (rc)
++ printk(KERN_ERR
++ "ocfs2: Unable to register ocfs2_control device "
++ "(errno %d)\n",
++ -rc);
++
++ return rc;
++}
++
++static void ocfs2_control_exit(void)
++{
++ int rc;
++
++ rc = misc_deregister(&ocfs2_control_device);
++ if (rc)
++ printk(KERN_ERR
++ "ocfs2: Unable to deregister ocfs2_control device "
++ "(errno %d)\n",
++ -rc);
++}
++
++static struct dlm_lksb *fsdlm_astarg_to_lksb(void *astarg)
++{
++ struct ocfs2_lock_res *res = astarg;
++ return &res->l_lksb.lksb_fsdlm;
++}
++
++static void fsdlm_lock_ast_wrapper(void *astarg)
++{
++ struct dlm_lksb *lksb = fsdlm_astarg_to_lksb(astarg);
++ int status = lksb->sb_status;
++
++ BUG_ON(user_stack.sp_proto == NULL);
++
++ /*
++ * For now we're punting on the issue of other non-standard errors
++ * where we can't tell if the unlock_ast or lock_ast should be called.
++ * The main "other error" that's possible is EINVAL which means the
++ * function was called with invalid args, which shouldn't be possible
++ * since the caller here is under our control. Other non-standard
++ * errors probably fall into the same category, or otherwise are fatal
++ * which means we can't carry on anyway.
++ */
++
++ if (status == -DLM_EUNLOCK || status == -DLM_ECANCEL)
++ user_stack.sp_proto->lp_unlock_ast(astarg, 0);
++ else
++ user_stack.sp_proto->lp_lock_ast(astarg);
++}
++
++static void fsdlm_blocking_ast_wrapper(void *astarg, int level)
++{
++ BUG_ON(user_stack.sp_proto == NULL);
++
++ user_stack.sp_proto->lp_blocking_ast(astarg, level);
++}
++
++static int user_dlm_lock(struct ocfs2_cluster_connection *conn,
++ int mode,
++ union ocfs2_dlm_lksb *lksb,
++ u32 flags,
++ void *name,
++ unsigned int namelen,
++ void *astarg)
++{
++ int ret;
++
++ if (!lksb->lksb_fsdlm.sb_lvbptr)
++ lksb->lksb_fsdlm.sb_lvbptr = (char *)lksb +
++ sizeof(struct dlm_lksb);
++
++ ret = dlm_lock(conn->cc_lockspace, mode, &lksb->lksb_fsdlm,
++ flags|DLM_LKF_NODLCKWT, name, namelen, 0,
++ fsdlm_lock_ast_wrapper, astarg,
++ fsdlm_blocking_ast_wrapper);
++ return ret;
++}
++
++static int user_dlm_unlock(struct ocfs2_cluster_connection *conn,
++ union ocfs2_dlm_lksb *lksb,
++ u32 flags,
++ void *astarg)
++{
++ int ret;
++
++ ret = dlm_unlock(conn->cc_lockspace, lksb->lksb_fsdlm.sb_lkid,
++ flags, &lksb->lksb_fsdlm, astarg);
++ return ret;
++}
++
++static int user_dlm_lock_status(union ocfs2_dlm_lksb *lksb)
++{
++ return lksb->lksb_fsdlm.sb_status;
++}
++
++static void *user_dlm_lvb(union ocfs2_dlm_lksb *lksb)
++{
++ return (void *)(lksb->lksb_fsdlm.sb_lvbptr);
++}
++
++static void user_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb)
++{
++}
++
++/*
++ * Compare a requested locking protocol version against the current one.
++ *
++ * If the major numbers are different, they are incompatible.
++ * If the current minor is greater than the request, they are incompatible.
++ * If the current minor is less than or equal to the request, they are
++ * compatible, and the requester should run at the current minor version.
++ */
++static int fs_protocol_compare(struct ocfs2_protocol_version *existing,
++ struct ocfs2_protocol_version *request)
++{
++ if (existing->pv_major != request->pv_major)
++ return 1;
++
++ if (existing->pv_minor > request->pv_minor)
++ return 1;
++
++ if (existing->pv_minor < request->pv_minor)
++ request->pv_minor = existing->pv_minor;
++
++ return 0;
++}
++
++static int user_cluster_connect(struct ocfs2_cluster_connection *conn)
++{
++ dlm_lockspace_t *fsdlm;
++ struct ocfs2_live_connection *control;
++ int rc = 0;
++
++ BUG_ON(conn == NULL);
++
++ rc = ocfs2_live_connection_new(conn, &control);
++ if (rc)
++ goto out;
++
++ /*
++ * running_proto must have been set before we allowed any mounts
++ * to proceed.
++ */
++ if (fs_protocol_compare(&running_proto, &conn->cc_version)) {
++ printk(KERN_ERR
++ "Unable to mount with fs locking protocol version "
++ "%u.%u because the userspace control daemon has "
++ "negotiated %u.%u\n",
++ conn->cc_version.pv_major, conn->cc_version.pv_minor,
++ running_proto.pv_major, running_proto.pv_minor);
++ rc = -EPROTO;
++ ocfs2_live_connection_drop(control);
++ goto out;
++ }
++
++ rc = dlm_new_lockspace(conn->cc_name, strlen(conn->cc_name),
++ &fsdlm, DLM_LSFL_FS, DLM_LVB_LEN);
++ if (rc) {
++ ocfs2_live_connection_drop(control);
++ goto out;
++ }
++
++ conn->cc_private = control;
++ conn->cc_lockspace = fsdlm;
++out:
++ return rc;
++}
++
++static int user_cluster_disconnect(struct ocfs2_cluster_connection *conn,
++ int hangup_pending)
++{
++ dlm_release_lockspace(conn->cc_lockspace, 2);
++ conn->cc_lockspace = NULL;
++ ocfs2_live_connection_drop(conn->cc_private);
++ conn->cc_private = NULL;
++ return 0;
++}
++
++static int user_cluster_this_node(unsigned int *this_node)
++{
++ int rc;
++
++ rc = ocfs2_control_get_this_node();
++ if (rc < 0)
++ return rc;
++
++ *this_node = rc;
++ return 0;
++}
++
++static struct ocfs2_stack_operations user_stack_ops = {
++ .connect = user_cluster_connect,
++ .disconnect = user_cluster_disconnect,
++ .this_node = user_cluster_this_node,
++ .dlm_lock = user_dlm_lock,
++ .dlm_unlock = user_dlm_unlock,
++ .lock_status = user_dlm_lock_status,
++ .lock_lvb = user_dlm_lvb,
++ .dump_lksb = user_dlm_dump_lksb,
++};
++
++static struct ocfs2_stack_plugin user_stack = {
++ .sp_name = "user",
++ .sp_ops = &user_stack_ops,
++ .sp_owner = THIS_MODULE,
++};
++
++
++static int __init user_stack_init(void)
++{
++ int rc;
++
++ rc = ocfs2_control_init();
++ if (!rc) {
++ rc = ocfs2_stack_glue_register(&user_stack);
++ if (rc)
++ ocfs2_control_exit();
++ }
++
++ return rc;
++}
++
++static void __exit user_stack_exit(void)
++{
++ ocfs2_stack_glue_unregister(&user_stack);
++ ocfs2_control_exit();
++}
++
++MODULE_AUTHOR("Oracle");
++MODULE_DESCRIPTION("ocfs2 driver for userspace cluster stacks");
++MODULE_LICENSE("GPL");
++module_init(user_stack_init);
++module_exit(user_stack_exit);
+diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c
+new file mode 100644
+index 0000000..119f60c
+--- /dev/null
++++ b/fs/ocfs2/stackglue.c
+@@ -0,0 +1,568 @@
++/* -*- mode: c; c-basic-offset: 8; -*-
++ * vim: noexpandtab sw=8 ts=8 sts=0:
++ *
++ * stackglue.c
++ *
++ * Code which implements an OCFS2 specific interface to underlying
++ * cluster stacks.
++ *
++ * Copyright (C) 2007 Oracle. 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, version 2.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ */
++
++#include <linux/list.h>
++#include <linux/spinlock.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/kmod.h>
++#include <linux/fs.h>
++#include <linux/kobject.h>
++#include <linux/sysfs.h>
++
++#include "ocfs2_fs.h"
++
++#include "stackglue.h"
++
++#define OCFS2_STACK_PLUGIN_O2CB "o2cb"
++#define OCFS2_STACK_PLUGIN_USER "user"
++
++static struct ocfs2_locking_protocol *lproto;
++static DEFINE_SPINLOCK(ocfs2_stack_lock);
++static LIST_HEAD(ocfs2_stack_list);
++static char cluster_stack_name[OCFS2_STACK_LABEL_LEN + 1];
++
++/*
++ * The stack currently in use. If not null, active_stack->sp_count > 0,
++ * the module is pinned, and the locking protocol cannot be changed.
++ */
++static struct ocfs2_stack_plugin *active_stack;
++
++static struct ocfs2_stack_plugin *ocfs2_stack_lookup(const char *name)
++{
++ struct ocfs2_stack_plugin *p;
++
++ assert_spin_locked(&ocfs2_stack_lock);
++
++ list_for_each_entry(p, &ocfs2_stack_list, sp_list) {
++ if (!strcmp(p->sp_name, name))
++ return p;
++ }
++
++ return NULL;
++}
++
++static int ocfs2_stack_driver_request(const char *stack_name,
++ const char *plugin_name)
++{
++ int rc;
++ struct ocfs2_stack_plugin *p;
++
++ spin_lock(&ocfs2_stack_lock);
++
++ /*
++ * If the stack passed by the filesystem isn't the selected one,
++ * we can't continue.
++ */
++ if (strcmp(stack_name, cluster_stack_name)) {
++ rc = -EBUSY;
++ goto out;
++ }
++
++ if (active_stack) {
++ /*
++ * If the active stack isn't the one we want, it cannot
++ * be selected right now.
++ */
++ if (!strcmp(active_stack->sp_name, plugin_name))
++ rc = 0;
++ else
++ rc = -EBUSY;
++ goto out;
++ }
++
++ p = ocfs2_stack_lookup(plugin_name);
++ if (!p || !try_module_get(p->sp_owner)) {
++ rc = -ENOENT;
++ goto out;
++ }
++
++ /* Ok, the stack is pinned */
++ p->sp_count++;
++ active_stack = p;
++
++ rc = 0;
++
++out:
++ spin_unlock(&ocfs2_stack_lock);
++ return rc;
++}
++
++/*
++ * This function looks up the appropriate stack and makes it active. If
++ * there is no stack, it tries to load it. It will fail if the stack still
++ * cannot be found. It will also fail if a different stack is in use.
++ */
++static int ocfs2_stack_driver_get(const char *stack_name)
++{
++ int rc;
++ char *plugin_name = OCFS2_STACK_PLUGIN_O2CB;
++
++ /*
++ * Classic stack does not pass in a stack name. This is
++ * compatible with older tools as well.
++ */
++ if (!stack_name || !*stack_name)
++ stack_name = OCFS2_STACK_PLUGIN_O2CB;
++
++ if (strlen(stack_name) != OCFS2_STACK_LABEL_LEN) {
++ printk(KERN_ERR
++ "ocfs2 passed an invalid cluster stack label: \"%s\"\n",
++ stack_name);
++ return -EINVAL;
++ }
++
++ /* Anything that isn't the classic stack is a user stack */
++ if (strcmp(stack_name, OCFS2_STACK_PLUGIN_O2CB))
++ plugin_name = OCFS2_STACK_PLUGIN_USER;
++
++ rc = ocfs2_stack_driver_request(stack_name, plugin_name);
++ if (rc == -ENOENT) {
++ request_module("ocfs2_stack_%s", plugin_name);
++ rc = ocfs2_stack_driver_request(stack_name, plugin_name);
++ }
++
++ if (rc == -ENOENT) {
++ printk(KERN_ERR
++ "ocfs2: Cluster stack driver \"%s\" cannot be found\n",
++ plugin_name);
++ } else if (rc == -EBUSY) {
++ printk(KERN_ERR
++ "ocfs2: A different cluster stack is in use\n");
++ }
++
++ return rc;
++}
++
++static void ocfs2_stack_driver_put(void)
++{
++ spin_lock(&ocfs2_stack_lock);
++ BUG_ON(active_stack == NULL);
++ BUG_ON(active_stack->sp_count == 0);
++
++ active_stack->sp_count--;
++ if (!active_stack->sp_count) {
++ module_put(active_stack->sp_owner);
++ active_stack = NULL;
++ }
++ spin_unlock(&ocfs2_stack_lock);
++}
++
++int ocfs2_stack_glue_register(struct ocfs2_stack_plugin *plugin)
++{
++ int rc;
++
++ spin_lock(&ocfs2_stack_lock);
++ if (!ocfs2_stack_lookup(plugin->sp_name)) {
++ plugin->sp_count = 0;
++ plugin->sp_proto = lproto;
++ list_add(&plugin->sp_list, &ocfs2_stack_list);
++ printk(KERN_INFO "ocfs2: Registered cluster interface %s\n",
++ plugin->sp_name);
++ rc = 0;
++ } else {
++ printk(KERN_ERR "ocfs2: Stack \"%s\" already registered\n",
++ plugin->sp_name);
++ rc = -EEXIST;
++ }
++ spin_unlock(&ocfs2_stack_lock);
++
++ return rc;
++}
++EXPORT_SYMBOL_GPL(ocfs2_stack_glue_register);
++
++void ocfs2_stack_glue_unregister(struct ocfs2_stack_plugin *plugin)
++{
++ struct ocfs2_stack_plugin *p;
++
++ spin_lock(&ocfs2_stack_lock);
++ p = ocfs2_stack_lookup(plugin->sp_name);
++ if (p) {
++ BUG_ON(p != plugin);
++ BUG_ON(plugin == active_stack);
++ BUG_ON(plugin->sp_count != 0);
++ list_del_init(&plugin->sp_list);
++ printk(KERN_INFO "ocfs2: Unregistered cluster interface %s\n",
++ plugin->sp_name);
++ } else {
++ printk(KERN_ERR "Stack \"%s\" is not registered\n",
++ plugin->sp_name);
++ }
++ spin_unlock(&ocfs2_stack_lock);
++}
++EXPORT_SYMBOL_GPL(ocfs2_stack_glue_unregister);
++
++void ocfs2_stack_glue_set_locking_protocol(struct ocfs2_locking_protocol *proto)
++{
++ struct ocfs2_stack_plugin *p;
++
++ BUG_ON(proto == NULL);
++
++ spin_lock(&ocfs2_stack_lock);
++ BUG_ON(active_stack != NULL);
++
++ lproto = proto;
++ list_for_each_entry(p, &ocfs2_stack_list, sp_list) {
++ p->sp_proto = lproto;
++ }
++
++ spin_unlock(&ocfs2_stack_lock);
++}
++EXPORT_SYMBOL_GPL(ocfs2_stack_glue_set_locking_protocol);
++
++
++/*
++ * The ocfs2_dlm_lock() and ocfs2_dlm_unlock() functions take
++ * "struct ocfs2_lock_res *astarg" instead of "void *astarg" because the
++ * underlying stack plugins need to pilfer the lksb off of the lock_res.
++ * If some other structure needs to be passed as an astarg, the plugins
++ * will need to be given a different avenue to the lksb.
++ */
++int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn,
++ int mode,
++ union ocfs2_dlm_lksb *lksb,
++ u32 flags,
++ void *name,
++ unsigned int namelen,
++ struct ocfs2_lock_res *astarg)
++{
++ BUG_ON(lproto == NULL);
++
++ return active_stack->sp_ops->dlm_lock(conn, mode, lksb, flags,
++ name, namelen, astarg);
++}
++EXPORT_SYMBOL_GPL(ocfs2_dlm_lock);
++
++int ocfs2_dlm_unlock(struct ocfs2_cluster_connection *conn,
++ union ocfs2_dlm_lksb *lksb,
++ u32 flags,
++ struct ocfs2_lock_res *astarg)
++{
++ BUG_ON(lproto == NULL);
++
++ return active_stack->sp_ops->dlm_unlock(conn, lksb, flags, astarg);
++}
++EXPORT_SYMBOL_GPL(ocfs2_dlm_unlock);
++
++int ocfs2_dlm_lock_status(union ocfs2_dlm_lksb *lksb)
++{
++ return active_stack->sp_ops->lock_status(lksb);
++}
++EXPORT_SYMBOL_GPL(ocfs2_dlm_lock_status);
++
++/*
++ * Why don't we cast to ocfs2_meta_lvb? The "clean" answer is that we
++ * don't cast at the glue level. The real answer is that the header
++ * ordering is nigh impossible.
++ */
++void *ocfs2_dlm_lvb(union ocfs2_dlm_lksb *lksb)
++{
++ return active_stack->sp_ops->lock_lvb(lksb);
++}
++EXPORT_SYMBOL_GPL(ocfs2_dlm_lvb);
++
++void ocfs2_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb)
++{
++ active_stack->sp_ops->dump_lksb(lksb);
++}
++EXPORT_SYMBOL_GPL(ocfs2_dlm_dump_lksb);
++
++int ocfs2_cluster_connect(const char *stack_name,
++ const char *group,
++ int grouplen,
++ void (*recovery_handler)(int node_num,
++ void *recovery_data),
++ void *recovery_data,
++ struct ocfs2_cluster_connection **conn)
++{
++ int rc = 0;
++ struct ocfs2_cluster_connection *new_conn;
++
++ BUG_ON(group == NULL);
++ BUG_ON(conn == NULL);
++ BUG_ON(recovery_handler == NULL);
++
++ if (grouplen > GROUP_NAME_MAX) {
++ rc = -EINVAL;
++ goto out;
++ }
++
++ new_conn = kzalloc(sizeof(struct ocfs2_cluster_connection),
++ GFP_KERNEL);
++ if (!new_conn) {
++ rc = -ENOMEM;
++ goto out;
++ }
++
++ memcpy(new_conn->cc_name, group, grouplen);
++ new_conn->cc_namelen = grouplen;
++ new_conn->cc_recovery_handler = recovery_handler;
++ new_conn->cc_recovery_data = recovery_data;
++
++ /* Start the new connection at our maximum compatibility level */
++ new_conn->cc_version = lproto->lp_max_version;
++
++ /* This will pin the stack driver if successful */
++ rc = ocfs2_stack_driver_get(stack_name);
++ if (rc)
++ goto out_free;
++
++ rc = active_stack->sp_ops->connect(new_conn);
++ if (rc) {
++ ocfs2_stack_driver_put();
++ goto out_free;
++ }
++
++ *conn = new_conn;
++
++out_free:
++ if (rc)
++ kfree(new_conn);
++
++out:
++ return rc;
++}
++EXPORT_SYMBOL_GPL(ocfs2_cluster_connect);
++
++/* If hangup_pending is 0, the stack driver will be dropped */
++int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn,
++ int hangup_pending)
++{
++ int ret;
++
++ BUG_ON(conn == NULL);
++
++ ret = active_stack->sp_ops->disconnect(conn, hangup_pending);
++
++ /* XXX Should we free it anyway? */
++ if (!ret) {
++ kfree(conn);
++ if (!hangup_pending)
++ ocfs2_stack_driver_put();
++ }
++
++ return ret;
++}
++EXPORT_SYMBOL_GPL(ocfs2_cluster_disconnect);
++
++void ocfs2_cluster_hangup(const char *group, int grouplen)
++{
++ BUG_ON(group == NULL);
++ BUG_ON(group[grouplen] != '\0');
++
++ if (active_stack->sp_ops->hangup)
++ active_stack->sp_ops->hangup(group, grouplen);
++
++ /* cluster_disconnect() was called with hangup_pending==1 */
++ ocfs2_stack_driver_put();
++}
++EXPORT_SYMBOL_GPL(ocfs2_cluster_hangup);
++
++int ocfs2_cluster_this_node(unsigned int *node)
++{
++ return active_stack->sp_ops->this_node(node);
++}
++EXPORT_SYMBOL_GPL(ocfs2_cluster_this_node);
++
++
++/*
++ * Sysfs bits
++ */
++
++static ssize_t ocfs2_max_locking_protocol_show(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ char *buf)
++{
++ ssize_t ret = 0;
++
++ spin_lock(&ocfs2_stack_lock);
++ if (lproto)
++ ret = snprintf(buf, PAGE_SIZE, "%u.%u\n",
++ lproto->lp_max_version.pv_major,
++ lproto->lp_max_version.pv_minor);
++ spin_unlock(&ocfs2_stack_lock);
++
++ return ret;
++}
++
++static struct kobj_attribute ocfs2_attr_max_locking_protocol =
++ __ATTR(max_locking_protocol, S_IFREG | S_IRUGO,
++ ocfs2_max_locking_protocol_show, NULL);
++
++static ssize_t ocfs2_loaded_cluster_plugins_show(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ char *buf)
++{
++ ssize_t ret = 0, total = 0, remain = PAGE_SIZE;
++ struct ocfs2_stack_plugin *p;
++
++ spin_lock(&ocfs2_stack_lock);
++ list_for_each_entry(p, &ocfs2_stack_list, sp_list) {
++ ret = snprintf(buf, remain, "%s\n",
++ p->sp_name);
++ if (ret < 0) {
++ total = ret;
++ break;
++ }
++ if (ret == remain) {
++ /* snprintf() didn't fit */
++ total = -E2BIG;
++ break;
++ }
++ total += ret;
++ remain -= ret;
++ }
++ spin_unlock(&ocfs2_stack_lock);
++
++ return total;
++}
++
++static struct kobj_attribute ocfs2_attr_loaded_cluster_plugins =
++ __ATTR(loaded_cluster_plugins, S_IFREG | S_IRUGO,
++ ocfs2_loaded_cluster_plugins_show, NULL);
++
++static ssize_t ocfs2_active_cluster_plugin_show(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ char *buf)
++{
++ ssize_t ret = 0;
++
++ spin_lock(&ocfs2_stack_lock);
++ if (active_stack) {
++ ret = snprintf(buf, PAGE_SIZE, "%s\n",
++ active_stack->sp_name);
++ if (ret == PAGE_SIZE)
++ ret = -E2BIG;
++ }
++ spin_unlock(&ocfs2_stack_lock);
++
++ return ret;
++}
++
++static struct kobj_attribute ocfs2_attr_active_cluster_plugin =
++ __ATTR(active_cluster_plugin, S_IFREG | S_IRUGO,
++ ocfs2_active_cluster_plugin_show, NULL);
++
++static ssize_t ocfs2_cluster_stack_show(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ char *buf)
++{
++ ssize_t ret;
++ spin_lock(&ocfs2_stack_lock);
++ ret = snprintf(buf, PAGE_SIZE, "%s\n", cluster_stack_name);
++ spin_unlock(&ocfs2_stack_lock);
++
++ return ret;
++}
++
++static ssize_t ocfs2_cluster_stack_store(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ const char *buf, size_t count)
++{
++ size_t len = count;
++ ssize_t ret;
++
++ if (len == 0)
++ return len;
++
++ if (buf[len - 1] == '\n')
++ len--;
++
++ if ((len != OCFS2_STACK_LABEL_LEN) ||
++ (strnlen(buf, len) != len))
++ return -EINVAL;
++
++ spin_lock(&ocfs2_stack_lock);
++ if (active_stack) {
++ if (!strncmp(buf, cluster_stack_name, len))
++ ret = count;
++ else
++ ret = -EBUSY;
++ } else {
++ memcpy(cluster_stack_name, buf, len);
++ ret = count;
++ }
++ spin_unlock(&ocfs2_stack_lock);
++
++ return ret;
++}
++
++
++static struct kobj_attribute ocfs2_attr_cluster_stack =
++ __ATTR(cluster_stack, S_IFREG | S_IRUGO | S_IWUSR,
++ ocfs2_cluster_stack_show,
++ ocfs2_cluster_stack_store);
++
++static struct attribute *ocfs2_attrs[] = {
++ &ocfs2_attr_max_locking_protocol.attr,
++ &ocfs2_attr_loaded_cluster_plugins.attr,
++ &ocfs2_attr_active_cluster_plugin.attr,
++ &ocfs2_attr_cluster_stack.attr,
++ NULL,
++};
++
++static struct attribute_group ocfs2_attr_group = {
++ .attrs = ocfs2_attrs,
++};
++
++static struct kset *ocfs2_kset;
++
++static void ocfs2_sysfs_exit(void)
++{
++ kset_unregister(ocfs2_kset);
++}
++
++static int ocfs2_sysfs_init(void)
++{
++ int ret;
++
++ ocfs2_kset = kset_create_and_add("ocfs2", NULL, fs_kobj);
++ if (!ocfs2_kset)
++ return -ENOMEM;
++
++ ret = sysfs_create_group(&ocfs2_kset->kobj, &ocfs2_attr_group);
++ if (ret)
++ goto error;
++
++ return 0;
++
++error:
++ kset_unregister(ocfs2_kset);
++ return ret;
++}
++
++static int __init ocfs2_stack_glue_init(void)
++{
++ strcpy(cluster_stack_name, OCFS2_STACK_PLUGIN_O2CB);
++
++ return ocfs2_sysfs_init();
++}
++
++static void __exit ocfs2_stack_glue_exit(void)
++{
++ lproto = NULL;
++ ocfs2_sysfs_exit();
++}
++
++MODULE_AUTHOR("Oracle");
++MODULE_DESCRIPTION("ocfs2 cluter stack glue layer");
++MODULE_LICENSE("GPL");
++module_init(ocfs2_stack_glue_init);
++module_exit(ocfs2_stack_glue_exit);
+diff --git a/fs/ocfs2/stackglue.h b/fs/ocfs2/stackglue.h
+new file mode 100644
+index 0000000..005e4f1
+--- /dev/null
++++ b/fs/ocfs2/stackglue.h
+@@ -0,0 +1,261 @@
++/* -*- mode: c; c-basic-offset: 8; -*-
++ * vim: noexpandtab sw=8 ts=8 sts=0:
++ *
++ * stackglue.h
++ *
++ * Glue to the underlying cluster stack.
++ *
++ * Copyright (C) 2007 Oracle. 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, version 2.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ */
++
++
++#ifndef STACKGLUE_H
++#define STACKGLUE_H
++
++#include <linux/types.h>
++#include <linux/list.h>
++#include <linux/dlmconstants.h>
++
++#include "dlm/dlmapi.h"
++#include <linux/dlm.h>
++
++/*
++ * dlmconstants.h does not have a LOCAL flag. We hope to remove it
++ * some day, but right now we need it. Let's fake it. This value is larger
++ * than any flag in dlmconstants.h.
++ */
++#define DLM_LKF_LOCAL 0x00100000
++
++/*
++ * This shadows DLM_LOCKSPACE_LEN in fs/dlm/dlm_internal.h. That probably
++ * wants to be in a public header.
++ */
++#define GROUP_NAME_MAX 64
++
++
++/*
++ * ocfs2_protocol_version changes when ocfs2 does something different in
++ * its inter-node behavior. See dlmglue.c for more information.
++ */
++struct ocfs2_protocol_version {
++ u8 pv_major;
++ u8 pv_minor;
++};
++
++/*
++ * The ocfs2_locking_protocol defines the handlers called on ocfs2's behalf.
++ */
++struct ocfs2_locking_protocol {
++ struct ocfs2_protocol_version lp_max_version;
++ void (*lp_lock_ast)(void *astarg);
++ void (*lp_blocking_ast)(void *astarg, int level);
++ void (*lp_unlock_ast)(void *astarg, int error);
++};
++
++
++/*
++ * The dlm_lockstatus struct includes lvb space, but the dlm_lksb struct only
++ * has a pointer to separately allocated lvb space. This struct exists only to
++ * include in the lksb union to make space for a combined dlm_lksb and lvb.
++ */
++struct fsdlm_lksb_plus_lvb {
++ struct dlm_lksb lksb;
++ char lvb[DLM_LVB_LEN];
++};
++
++/*
++ * A union of all lock status structures. We define it here so that the
++ * size of the union is known. Lock status structures are embedded in
++ * ocfs2 inodes.
++ */
++union ocfs2_dlm_lksb {
++ struct dlm_lockstatus lksb_o2dlm;
++ struct dlm_lksb lksb_fsdlm;
++ struct fsdlm_lksb_plus_lvb padding;
++};
++
++/*
++ * A cluster connection. Mostly opaque to ocfs2, the connection holds
++ * state for the underlying stack. ocfs2 does use cc_version to determine
++ * locking compatibility.
++ */
++struct ocfs2_cluster_connection {
++ char cc_name[GROUP_NAME_MAX];
++ int cc_namelen;
++ struct ocfs2_protocol_version cc_version;
++ void (*cc_recovery_handler)(int node_num, void *recovery_data);
++ void *cc_recovery_data;
++ void *cc_lockspace;
++ void *cc_private;
++};
++
++/*
++ * Each cluster stack implements the stack operations structure. Not used
++ * in the ocfs2 code, the stackglue code translates generic cluster calls
++ * into stack operations.
++ */
++struct ocfs2_stack_operations {
++ /*
++ * The fs code calls ocfs2_cluster_connect() to attach a new
++ * filesystem to the cluster stack. The ->connect() op is passed
++ * an ocfs2_cluster_connection with the name and recovery field
++ * filled in.
++ *
++ * The stack must set up any notification mechanisms and create
++ * the filesystem lockspace in the DLM. The lockspace should be
++ * stored on cc_lockspace. Any other information can be stored on
++ * cc_private.
++ *
++ * ->connect() must not return until it is guaranteed that
++ *
++ * - Node down notifications for the filesystem will be recieved
++ * and passed to conn->cc_recovery_handler().
++ * - Locking requests for the filesystem will be processed.
++ */
++ int (*connect)(struct ocfs2_cluster_connection *conn);
++
++ /*
++ * The fs code calls ocfs2_cluster_disconnect() when a filesystem
++ * no longer needs cluster services. All DLM locks have been
++ * dropped, and recovery notification is being ignored by the
++ * fs code. The stack must disengage from the DLM and discontinue
++ * recovery notification.
++ *
++ * Once ->disconnect() has returned, the connection structure will
++ * be freed. Thus, a stack must not return from ->disconnect()
++ * until it will no longer reference the conn pointer.
++ *
++ * If hangup_pending is zero, ocfs2_cluster_disconnect() will also
++ * be dropping the reference on the module.
++ */
++ int (*disconnect)(struct ocfs2_cluster_connection *conn,
++ int hangup_pending);
++
++ /*
++ * ocfs2_cluster_hangup() exists for compatibility with older
++ * ocfs2 tools. Only the classic stack really needs it. As such
++ * ->hangup() is not required of all stacks. See the comment by
++ * ocfs2_cluster_hangup() for more details.
++ *
++ * Note that ocfs2_cluster_hangup() can only be called if
++ * hangup_pending was passed to ocfs2_cluster_disconnect().
++ */
++ void (*hangup)(const char *group, int grouplen);
++
++ /*
++ * ->this_node() returns the cluster's unique identifier for the
++ * local node.
++ */
++ int (*this_node)(unsigned int *node);
++
++ /*
++ * Call the underlying dlm lock function. The ->dlm_lock()
++ * callback should convert the flags and mode as appropriate.
++ *
++ * ast and bast functions are not part of the call because the
++ * stack will likely want to wrap ast and bast calls before passing
++ * them to stack->sp_proto.
++ */
++ int (*dlm_lock)(struct ocfs2_cluster_connection *conn,
++ int mode,
++ union ocfs2_dlm_lksb *lksb,
++ u32 flags,
++ void *name,
++ unsigned int namelen,
++ void *astarg);
++
++ /*
++ * Call the underlying dlm unlock function. The ->dlm_unlock()
++ * function should convert the flags as appropriate.
++ *
++ * The unlock ast is not passed, as the stack will want to wrap
++ * it before calling stack->sp_proto->lp_unlock_ast().
++ */
++ int (*dlm_unlock)(struct ocfs2_cluster_connection *conn,
++ union ocfs2_dlm_lksb *lksb,
++ u32 flags,
++ void *astarg);
++
++ /*
++ * Return the status of the current lock status block. The fs
++ * code should never dereference the union. The ->lock_status()
++ * callback pulls out the stack-specific lksb, converts the status
++ * to a proper errno, and returns it.
++ */
++ int (*lock_status)(union ocfs2_dlm_lksb *lksb);
++
++ /*
++ * Pull the lvb pointer off of the stack-specific lksb.
++ */
++ void *(*lock_lvb)(union ocfs2_dlm_lksb *lksb);
++
++ /*
++ * This is an optoinal debugging hook. If provided, the
++ * stack can dump debugging information about this lock.
++ */
++ void (*dump_lksb)(union ocfs2_dlm_lksb *lksb);
++};
++
++/*
++ * Each stack plugin must describe itself by registering a
++ * ocfs2_stack_plugin structure. This is only seen by stackglue and the
++ * stack driver.
++ */
++struct ocfs2_stack_plugin {
++ char *sp_name;
++ struct ocfs2_stack_operations *sp_ops;
++ struct module *sp_owner;
++
++ /* These are managed by the stackglue code. */
++ struct list_head sp_list;
++ unsigned int sp_count;
++ struct ocfs2_locking_protocol *sp_proto;
++};
++
++
++/* Used by the filesystem */
++int ocfs2_cluster_connect(const char *stack_name,
++ const char *group,
++ int grouplen,
++ void (*recovery_handler)(int node_num,
++ void *recovery_data),
++ void *recovery_data,
++ struct ocfs2_cluster_connection **conn);
++int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn,
++ int hangup_pending);
++void ocfs2_cluster_hangup(const char *group, int grouplen);
++int ocfs2_cluster_this_node(unsigned int *node);
++
++struct ocfs2_lock_res;
++int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn,
++ int mode,
++ union ocfs2_dlm_lksb *lksb,
++ u32 flags,
++ void *name,
++ unsigned int namelen,
++ struct ocfs2_lock_res *astarg);
++int ocfs2_dlm_unlock(struct ocfs2_cluster_connection *conn,
++ union ocfs2_dlm_lksb *lksb,
++ u32 flags,
++ struct ocfs2_lock_res *astarg);
++
++int ocfs2_dlm_lock_status(union ocfs2_dlm_lksb *lksb);
++void *ocfs2_dlm_lvb(union ocfs2_dlm_lksb *lksb);
++void ocfs2_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb);
++
++void ocfs2_stack_glue_set_locking_protocol(struct ocfs2_locking_protocol *proto);
++
++
++/* Used by stack plugins */
++int ocfs2_stack_glue_register(struct ocfs2_stack_plugin *plugin);
++void ocfs2_stack_glue_unregister(struct ocfs2_stack_plugin *plugin);
++#endif /* STACKGLUE_H */
+diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
+index 72c198a..d2d278f 100644
+--- a/fs/ocfs2/suballoc.c
++++ b/fs/ocfs2/suballoc.c
+@@ -46,6 +46,11 @@
+
+ #include "buffer_head_io.h"
+
++#define NOT_ALLOC_NEW_GROUP 0
++#define ALLOC_NEW_GROUP 1
++
++#define OCFS2_MAX_INODES_TO_STEAL 1024
++
+ static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg);
+ static inline void ocfs2_debug_suballoc_inode(struct ocfs2_dinode *fe);
+ static inline u16 ocfs2_find_victim_chain(struct ocfs2_chain_list *cl);
+@@ -106,7 +111,7 @@ static inline void ocfs2_block_to_cluster_group(struct inode *inode,
+ u64 *bg_blkno,
+ u16 *bg_bit_off);
+
+-void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac)
++static void ocfs2_free_ac_resource(struct ocfs2_alloc_context *ac)
+ {
+ struct inode *inode = ac->ac_inode;
+
+@@ -117,9 +122,17 @@ void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac)
+ mutex_unlock(&inode->i_mutex);
+
+ iput(inode);
++ ac->ac_inode = NULL;
+ }
+- if (ac->ac_bh)
++ if (ac->ac_bh) {
+ brelse(ac->ac_bh);
++ ac->ac_bh = NULL;
++ }
++}
++
++void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac)
++{
++ ocfs2_free_ac_resource(ac);
+ kfree(ac);
+ }
+
+@@ -391,7 +404,8 @@ bail:
+ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb,
+ struct ocfs2_alloc_context *ac,
+ int type,
+- u32 slot)
++ u32 slot,
++ int alloc_new_group)
+ {
+ int status;
+ u32 bits_wanted = ac->ac_bits_wanted;
+@@ -420,6 +434,7 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb,
+ }
+
+ ac->ac_inode = alloc_inode;
++ ac->ac_alloc_slot = slot;
+
+ fe = (struct ocfs2_dinode *) bh->b_data;
+ if (!OCFS2_IS_VALID_DINODE(fe)) {
+@@ -446,6 +461,14 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb,
+ goto bail;
+ }
+
++ if (alloc_new_group != ALLOC_NEW_GROUP) {
++ mlog(0, "Alloc File %u Full: wanted=%u, free_bits=%u, "
++ "and we don't alloc a new group for it.\n",
++ slot, bits_wanted, free_bits);
++ status = -ENOSPC;
++ goto bail;
++ }
++
+ status = ocfs2_block_group_alloc(osb, alloc_inode, bh);
+ if (status < 0) {
+ if (status != -ENOSPC)
+@@ -490,7 +513,8 @@ int ocfs2_reserve_new_metadata(struct ocfs2_super *osb,
+ (*ac)->ac_group_search = ocfs2_block_group_search;
+
+ status = ocfs2_reserve_suballoc_bits(osb, (*ac),
+- EXTENT_ALLOC_SYSTEM_INODE, slot);
++ EXTENT_ALLOC_SYSTEM_INODE,
++ slot, ALLOC_NEW_GROUP);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+@@ -508,10 +532,42 @@ bail:
+ return status;
+ }
+
++static int ocfs2_steal_inode_from_other_nodes(struct ocfs2_super *osb,
++ struct ocfs2_alloc_context *ac)
++{
++ int i, status = -ENOSPC;
++ s16 slot = ocfs2_get_inode_steal_slot(osb);
++
++ /* Start to steal inodes from the first slot after ours. */
++ if (slot == OCFS2_INVALID_SLOT)
++ slot = osb->slot_num + 1;
++
++ for (i = 0; i < osb->max_slots; i++, slot++) {
++ if (slot == osb->max_slots)
++ slot = 0;
++
++ if (slot == osb->slot_num)
++ continue;
++
++ status = ocfs2_reserve_suballoc_bits(osb, ac,
++ INODE_ALLOC_SYSTEM_INODE,
++ slot, NOT_ALLOC_NEW_GROUP);
++ if (status >= 0) {
++ ocfs2_set_inode_steal_slot(osb, slot);
++ break;
++ }
++
++ ocfs2_free_ac_resource(ac);
++ }
++
++ return status;
++}
++
+ int ocfs2_reserve_new_inode(struct ocfs2_super *osb,
+ struct ocfs2_alloc_context **ac)
+ {
+ int status;
++ s16 slot = ocfs2_get_inode_steal_slot(osb);
+
+ *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
+ if (!(*ac)) {
+@@ -525,9 +581,43 @@ int ocfs2_reserve_new_inode(struct ocfs2_super *osb,
+
+ (*ac)->ac_group_search = ocfs2_block_group_search;
+
++ /*
++ * slot is set when we successfully steal inode from other nodes.
++ * It is reset in 3 places:
++ * 1. when we flush the truncate log
++ * 2. when we complete local alloc recovery.
++ * 3. when we successfully allocate from our own slot.
++ * After it is set, we will go on stealing inodes until we find the
++ * need to check our slots to see whether there is some space for us.
++ */
++ if (slot != OCFS2_INVALID_SLOT &&
++ atomic_read(&osb->s_num_inodes_stolen) < OCFS2_MAX_INODES_TO_STEAL)
++ goto inode_steal;
++
++ atomic_set(&osb->s_num_inodes_stolen, 0);
+ status = ocfs2_reserve_suballoc_bits(osb, *ac,
+ INODE_ALLOC_SYSTEM_INODE,
+- osb->slot_num);
++ osb->slot_num, ALLOC_NEW_GROUP);
++ if (status >= 0) {
++ status = 0;
++
++ /*
++ * Some inodes must be freed by us, so try to allocate
++ * from our own next time.
++ */
++ if (slot != OCFS2_INVALID_SLOT)
++ ocfs2_init_inode_steal_slot(osb);
++ goto bail;
++ } else if (status < 0 && status != -ENOSPC) {
++ mlog_errno(status);
++ goto bail;
++ }
++
++ ocfs2_free_ac_resource(*ac);
++
++inode_steal:
++ status = ocfs2_steal_inode_from_other_nodes(osb, *ac);
++ atomic_inc(&osb->s_num_inodes_stolen);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+@@ -557,7 +647,8 @@ int ocfs2_reserve_cluster_bitmap_bits(struct ocfs2_super *osb,
+
+ status = ocfs2_reserve_suballoc_bits(osb, ac,
+ GLOBAL_BITMAP_SYSTEM_INODE,
+- OCFS2_INVALID_SLOT);
++ OCFS2_INVALID_SLOT,
++ ALLOC_NEW_GROUP);
+ if (status < 0 && status != -ENOSPC) {
+ mlog_errno(status);
+ goto bail;
+diff --git a/fs/ocfs2/suballoc.h b/fs/ocfs2/suballoc.h
+index 8799033..544c600 100644
+--- a/fs/ocfs2/suballoc.h
++++ b/fs/ocfs2/suballoc.h
+@@ -36,6 +36,7 @@ typedef int (group_search_t)(struct inode *,
+ struct ocfs2_alloc_context {
+ struct inode *ac_inode; /* which bitmap are we allocating from? */
+ struct buffer_head *ac_bh; /* file entry bh */
++ u32 ac_alloc_slot; /* which slot are we allocating from? */
+ u32 ac_bits_wanted;
+ u32 ac_bits_given;
+ #define OCFS2_AC_USE_LOCAL 1
+diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
+index bec75af..df63ba2 100644
+--- a/fs/ocfs2/super.c
++++ b/fs/ocfs2/super.c
+@@ -40,8 +40,7 @@
+ #include <linux/crc32.h>
+ #include <linux/debugfs.h>
+ #include <linux/mount.h>
+-
+-#include <cluster/nodemanager.h>
++#include <linux/seq_file.h>
+
+ #define MLOG_MASK_PREFIX ML_SUPER
+ #include <cluster/masklog.h>
+@@ -88,6 +87,7 @@ struct mount_options
+ unsigned int atime_quantum;
+ signed short slot;
+ unsigned int localalloc_opt;
++ char cluster_stack[OCFS2_STACK_LABEL_LEN + 1];
+ };
+
+ static int ocfs2_parse_options(struct super_block *sb, char *options,
+@@ -109,7 +109,6 @@ static int ocfs2_sync_fs(struct super_block *sb, int wait);
+ static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb);
+ static int ocfs2_init_local_system_inodes(struct ocfs2_super *osb);
+ static void ocfs2_release_system_inodes(struct ocfs2_super *osb);
+-static int ocfs2_fill_local_node_info(struct ocfs2_super *osb);
+ static int ocfs2_check_volume(struct ocfs2_super *osb);
+ static int ocfs2_verify_volume(struct ocfs2_dinode *di,
+ struct buffer_head *bh,
+@@ -154,6 +153,7 @@ enum {
+ Opt_commit,
+ Opt_localalloc,
+ Opt_localflocks,
++ Opt_stack,
+ Opt_err,
+ };
+
+@@ -172,6 +172,7 @@ static match_table_t tokens = {
+ {Opt_commit, "commit=%u"},
+ {Opt_localalloc, "localalloc=%d"},
+ {Opt_localflocks, "localflocks"},
++ {Opt_stack, "cluster_stack=%s"},
+ {Opt_err, NULL}
+ };
+
+@@ -551,8 +552,17 @@ static int ocfs2_verify_heartbeat(struct ocfs2_super *osb)
+ }
+ }
+
++ if (ocfs2_userspace_stack(osb)) {
++ if (osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) {
++ mlog(ML_ERROR, "Userspace stack expected, but "
++ "o2cb heartbeat arguments passed to mount\n");
++ return -EINVAL;
++ }
++ }
++
+ if (!(osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL)) {
+- if (!ocfs2_mount_local(osb) && !ocfs2_is_hard_readonly(osb)) {
++ if (!ocfs2_mount_local(osb) && !ocfs2_is_hard_readonly(osb) &&
++ !ocfs2_userspace_stack(osb)) {
+ mlog(ML_ERROR, "Heartbeat has to be started to mount "
+ "a read-write clustered device.\n");
+ return -EINVAL;
+@@ -562,6 +572,35 @@ static int ocfs2_verify_heartbeat(struct ocfs2_super *osb)
+ return 0;
+ }
+
++/*
++ * If we're using a userspace stack, mount should have passed
++ * a name that matches the disk. If not, mount should not
++ * have passed a stack.
++ */
++static int ocfs2_verify_userspace_stack(struct ocfs2_super *osb,
++ struct mount_options *mopt)
++{
++ if (!ocfs2_userspace_stack(osb) && mopt->cluster_stack[0]) {
++ mlog(ML_ERROR,
++ "cluster stack passed to mount, but this filesystem "
++ "does not support it\n");
++ return -EINVAL;
++ }
++
++ if (ocfs2_userspace_stack(osb) &&
++ strncmp(osb->osb_cluster_stack, mopt->cluster_stack,
++ OCFS2_STACK_LABEL_LEN)) {
++ mlog(ML_ERROR,
++ "cluster stack passed to mount (\"%s\") does not "
++ "match the filesystem (\"%s\")\n",
++ mopt->cluster_stack,
++ osb->osb_cluster_stack);
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
+ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
+ {
+ struct dentry *root;
+@@ -579,15 +618,6 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
+ goto read_super_error;
+ }
+
+- /* for now we only have one cluster/node, make sure we see it
+- * in the heartbeat universe */
+- if (parsed_options.mount_opt & OCFS2_MOUNT_HB_LOCAL) {
+- if (!o2hb_check_local_node_heartbeating()) {
+- status = -EINVAL;
+- goto read_super_error;
+- }
+- }
+-
+ /* probe for superblock */
+ status = ocfs2_sb_probe(sb, &bh, §or_size);
+ if (status < 0) {
+@@ -609,6 +639,10 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
+ osb->osb_commit_interval = parsed_options.commit_interval;
+ osb->local_alloc_size = parsed_options.localalloc_opt;
+
++ status = ocfs2_verify_userspace_stack(osb, &parsed_options);
++ if (status)
++ goto read_super_error;
++
+ sb->s_magic = OCFS2_SUPER_MAGIC;
+
+ /* Hard readonly mode only if: bdev_read_only, MS_RDONLY,
+@@ -694,7 +728,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
+ if (ocfs2_mount_local(osb))
+ snprintf(nodestr, sizeof(nodestr), "local");
+ else
+- snprintf(nodestr, sizeof(nodestr), "%d", osb->node_num);
++ snprintf(nodestr, sizeof(nodestr), "%u", osb->node_num);
+
+ printk(KERN_INFO "ocfs2: Mounting device (%s) on (node %s, slot %d) "
+ "with %s data mode.\n",
+@@ -763,6 +797,7 @@ static int ocfs2_parse_options(struct super_block *sb,
+ mopt->atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM;
+ mopt->slot = OCFS2_INVALID_SLOT;
+ mopt->localalloc_opt = OCFS2_DEFAULT_LOCAL_ALLOC_SIZE;
++ mopt->cluster_stack[0] = '\0';
+
+ if (!options) {
+ status = 1;
+@@ -864,6 +899,25 @@ static int ocfs2_parse_options(struct super_block *sb,
+ if (!is_remount)
+ mopt->mount_opt |= OCFS2_MOUNT_LOCALFLOCKS;
+ break;
++ case Opt_stack:
++ /* Check both that the option we were passed
++ * is of the right length and that it is a proper
++ * string of the right length.
++ */
++ if (((args[0].to - args[0].from) !=
++ OCFS2_STACK_LABEL_LEN) ||
++ (strnlen(args[0].from,
++ OCFS2_STACK_LABEL_LEN) !=
++ OCFS2_STACK_LABEL_LEN)) {
++ mlog(ML_ERROR,
++ "Invalid cluster_stack option\n");
++ status = 0;
++ goto bail;
++ }
++ memcpy(mopt->cluster_stack, args[0].from,
++ OCFS2_STACK_LABEL_LEN);
++ mopt->cluster_stack[OCFS2_STACK_LABEL_LEN] = '\0';
++ break;
+ default:
+ mlog(ML_ERROR,
+ "Unrecognized mount option \"%s\" "
+@@ -922,6 +976,10 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
+ if (opts & OCFS2_MOUNT_LOCALFLOCKS)
+ seq_printf(s, ",localflocks,");
+
++ if (osb->osb_cluster_stack[0])
++ seq_printf(s, ",cluster_stack=%.*s", OCFS2_STACK_LABEL_LEN,
++ osb->osb_cluster_stack);
++
+ return 0;
+ }
+
+@@ -957,6 +1015,8 @@ static int __init ocfs2_init(void)
+ mlog(ML_ERROR, "Unable to create ocfs2 debugfs root.\n");
+ }
+
++ ocfs2_set_locking_protocol();
++
+ leave:
+ if (status < 0) {
+ ocfs2_free_mem_caches();
+@@ -1132,31 +1192,6 @@ static int ocfs2_get_sector(struct super_block *sb,
+ return 0;
+ }
+
+-/* ocfs2 1.0 only allows one cluster and node identity per kernel image. */
+-static int ocfs2_fill_local_node_info(struct ocfs2_super *osb)
+-{
+- int status;
+-
+- /* XXX hold a ref on the node while mounte? easy enough, if
+- * desirable. */
+- if (ocfs2_mount_local(osb))
+- osb->node_num = 0;
+- else
+- osb->node_num = o2nm_this_node();
+-
+- if (osb->node_num == O2NM_MAX_NODES) {
+- mlog(ML_ERROR, "could not find this host's node number\n");
+- status = -ENOENT;
+- goto bail;
+- }
+-
+- mlog(0, "I am node %d\n", osb->node_num);
+-
+- status = 0;
+-bail:
+- return status;
+-}
+-
+ static int ocfs2_mount_volume(struct super_block *sb)
+ {
+ int status = 0;
+@@ -1168,12 +1203,6 @@ static int ocfs2_mount_volume(struct super_block *sb)
+ if (ocfs2_is_hard_readonly(osb))
+ goto leave;
+
+- status = ocfs2_fill_local_node_info(osb);
+- if (status < 0) {
+- mlog_errno(status);
+- goto leave;
+- }
+-
+ status = ocfs2_dlm_init(osb);
+ if (status < 0) {
+ mlog_errno(status);
+@@ -1224,18 +1253,9 @@ leave:
+ return status;
+ }
+
+-/* we can't grab the goofy sem lock from inside wait_event, so we use
+- * memory barriers to make sure that we'll see the null task before
+- * being woken up */
+-static int ocfs2_recovery_thread_running(struct ocfs2_super *osb)
+-{
+- mb();
+- return osb->recovery_thread_task != NULL;
+-}
+-
+ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
+ {
+- int tmp;
++ int tmp, hangup_needed = 0;
+ struct ocfs2_super *osb = NULL;
+ char nodestr[8];
+
+@@ -1249,25 +1269,16 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
+
+ ocfs2_truncate_log_shutdown(osb);
+
+- /* disable any new recovery threads and wait for any currently
+- * running ones to exit. Do this before setting the vol_state. */
+- mutex_lock(&osb->recovery_lock);
+- osb->disable_recovery = 1;
+- mutex_unlock(&osb->recovery_lock);
+- wait_event(osb->recovery_event, !ocfs2_recovery_thread_running(osb));
+-
+- /* At this point, we know that no more recovery threads can be
+- * launched, so wait for any recovery completion work to
+- * complete. */
+- flush_workqueue(ocfs2_wq);
++ /* This will disable recovery and flush any recovery work. */
++ ocfs2_recovery_exit(osb);
+
+ ocfs2_journal_shutdown(osb);
+
+ ocfs2_sync_blockdev(sb);
+
+- /* No dlm means we've failed during mount, so skip all the
+- * steps which depended on that to complete. */
+- if (osb->dlm) {
++ /* No cluster connection means we've failed during mount, so skip
++ * all the steps which depended on that to complete. */
++ if (osb->cconn) {
+ tmp = ocfs2_super_lock(osb, 1);
+ if (tmp < 0) {
+ mlog_errno(tmp);
+@@ -1278,25 +1289,34 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
+ if (osb->slot_num != OCFS2_INVALID_SLOT)
+ ocfs2_put_slot(osb);
+
+- if (osb->dlm)
++ if (osb->cconn)
+ ocfs2_super_unlock(osb, 1);
+
+ ocfs2_release_system_inodes(osb);
+
+- if (osb->dlm)
+- ocfs2_dlm_shutdown(osb);
++ /*
++ * If we're dismounting due to mount error, mount.ocfs2 will clean
++ * up heartbeat. If we're a local mount, there is no heartbeat.
++ * If we failed before we got a uuid_str yet, we can't stop
++ * heartbeat. Otherwise, do it.
++ */
++ if (!mnt_err && !ocfs2_mount_local(osb) && osb->uuid_str)
++ hangup_needed = 1;
++
++ if (osb->cconn)
++ ocfs2_dlm_shutdown(osb, hangup_needed);
+
+ debugfs_remove(osb->osb_debug_root);
+
+- if (!mnt_err)
+- ocfs2_stop_heartbeat(osb);
++ if (hangup_needed)
++ ocfs2_cluster_hangup(osb->uuid_str, strlen(osb->uuid_str));
+
+ atomic_set(&osb->vol_state, VOLUME_DISMOUNTED);
+
+ if (ocfs2_mount_local(osb))
+ snprintf(nodestr, sizeof(nodestr), "local");
+ else
+- snprintf(nodestr, sizeof(nodestr), "%d", osb->node_num);
++ snprintf(nodestr, sizeof(nodestr), "%u", osb->node_num);
+
+ printk(KERN_INFO "ocfs2: Unmounting device (%s) on (node %s)\n",
+ osb->dev_str, nodestr);
+@@ -1355,7 +1375,6 @@ static int ocfs2_initialize_super(struct super_block *sb,
+ sb->s_fs_info = osb;
+ sb->s_op = &ocfs2_sops;
+ sb->s_export_op = &ocfs2_export_ops;
+- osb->osb_locking_proto = ocfs2_locking_protocol;
+ sb->s_time_gran = 1;
+ sb->s_flags |= MS_NOATIME;
+ /* this is needed to support O_LARGEFILE */
+@@ -1368,7 +1387,6 @@ static int ocfs2_initialize_super(struct super_block *sb,
+ osb->s_sectsize_bits = blksize_bits(sector_size);
+ BUG_ON(!osb->s_sectsize_bits);
+
+- init_waitqueue_head(&osb->recovery_event);
+ spin_lock_init(&osb->dc_task_lock);
+ init_waitqueue_head(&osb->dc_event);
+ osb->dc_work_sequence = 0;
+@@ -1376,6 +1394,7 @@ static int ocfs2_initialize_super(struct super_block *sb,
+ INIT_LIST_HEAD(&osb->blocked_lock_list);
+ osb->blocked_lock_count = 0;
+ spin_lock_init(&osb->osb_lock);
++ ocfs2_init_inode_steal_slot(osb);
+
+ atomic_set(&osb->alloc_stats.moves, 0);
+ atomic_set(&osb->alloc_stats.local_data, 0);
+@@ -1388,24 +1407,23 @@ static int ocfs2_initialize_super(struct super_block *sb,
+ snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u",
+ MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev));
+
+- mutex_init(&osb->recovery_lock);
+-
+- osb->disable_recovery = 0;
+- osb->recovery_thread_task = NULL;
++ status = ocfs2_recovery_init(osb);
++ if (status) {
++ mlog(ML_ERROR, "Unable to initialize recovery state\n");
++ mlog_errno(status);
++ goto bail;
++ }
+
+ init_waitqueue_head(&osb->checkpoint_event);
+ atomic_set(&osb->needs_checkpoint, 0);
+
+ osb->s_atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM;
+
+- osb->node_num = O2NM_INVALID_NODE_NUM;
+ osb->slot_num = OCFS2_INVALID_SLOT;
+
+ osb->local_alloc_state = OCFS2_LA_UNUSED;
+ osb->local_alloc_bh = NULL;
+
+- ocfs2_setup_hb_callbacks(osb);
+-
+ init_waitqueue_head(&osb->osb_mount_event);
+
+ osb->vol_label = kmalloc(OCFS2_MAX_VOL_LABEL_LEN, GFP_KERNEL);
+@@ -1455,6 +1473,25 @@ static int ocfs2_initialize_super(struct super_block *sb,
+ goto bail;
+ }
+
++ if (ocfs2_userspace_stack(osb)) {
++ memcpy(osb->osb_cluster_stack,
++ OCFS2_RAW_SB(di)->s_cluster_info.ci_stack,
++ OCFS2_STACK_LABEL_LEN);
++ osb->osb_cluster_stack[OCFS2_STACK_LABEL_LEN] = '\0';
++ if (strlen(osb->osb_cluster_stack) != OCFS2_STACK_LABEL_LEN) {
++ mlog(ML_ERROR,
++ "couldn't mount because of an invalid "
++ "cluster stack label (%s) \n",
++ osb->osb_cluster_stack);
++ status = -EINVAL;
++ goto bail;
++ }
++ } else {
++ /* The empty string is identical with classic tools that
++ * don't know about s_cluster_info. */
++ osb->osb_cluster_stack[0] = '\0';
++ }
++
+ get_random_bytes(&osb->s_next_generation, sizeof(u32));
+
+ /* FIXME
+@@ -1724,8 +1761,7 @@ static void ocfs2_delete_osb(struct ocfs2_super *osb)
+
+ /* This function assumes that the caller has the main osb resource */
+
+- if (osb->slot_info)
+- ocfs2_free_slot_info(osb->slot_info);
++ ocfs2_free_slot_info(osb);
+
+ kfree(osb->osb_orphan_wipes);
+ /* FIXME
+diff --git a/fs/open.c b/fs/open.c
+index 3fa4e4f..b70e766 100644
+--- a/fs/open.c
++++ b/fs/open.c
+@@ -244,21 +244,21 @@ static long do_sys_truncate(const char __user * path, loff_t length)
+ if (!S_ISREG(inode->i_mode))
+ goto dput_and_out;
+
+- error = vfs_permission(&nd, MAY_WRITE);
++ error = mnt_want_write(nd.path.mnt);
+ if (error)
+ goto dput_and_out;
+
+- error = -EROFS;
+- if (IS_RDONLY(inode))
+- goto dput_and_out;
++ error = vfs_permission(&nd, MAY_WRITE);
++ if (error)
++ goto mnt_drop_write_and_out;
+
+ error = -EPERM;
+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+- goto dput_and_out;
++ goto mnt_drop_write_and_out;
+
+ error = get_write_access(inode);
+ if (error)
+- goto dput_and_out;
++ goto mnt_drop_write_and_out;
+
+ /*
+ * Make sure that there are no leases. get_write_access() protects
+@@ -276,6 +276,8 @@ static long do_sys_truncate(const char __user * path, loff_t length)
+
+ put_write_and_out:
+ put_write_access(inode);
++mnt_drop_write_and_out:
++ mnt_drop_write(nd.path.mnt);
+ dput_and_out:
+ path_put(&nd.path);
+ out:
+@@ -457,8 +459,17 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
+ if(res || !(mode & S_IWOTH) ||
+ special_file(nd.path.dentry->d_inode->i_mode))
+ goto out_path_release;
+-
+- if(IS_RDONLY(nd.path.dentry->d_inode))
++ /*
++ * This is a rare case where using __mnt_is_readonly()
++ * is OK without a mnt_want/drop_write() pair. Since
++ * no actual write to the fs is performed here, we do
++ * not need to telegraph to that to anyone.
++ *
++ * By doing this, we accept that this access is
++ * inherently racy and know that the fs may change
++ * state before we even see this result.
++ */
++ if (__mnt_is_readonly(nd.path.mnt))
+ res = -EROFS;
+
+ out_path_release:
+@@ -567,12 +578,12 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
+
+ audit_inode(NULL, dentry);
+
+- err = -EROFS;
+- if (IS_RDONLY(inode))
++ err = mnt_want_write(file->f_path.mnt);
++ if (err)
+ goto out_putf;
+ err = -EPERM;
+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+- goto out_putf;
++ goto out_drop_write;
+ mutex_lock(&inode->i_mutex);
+ if (mode == (mode_t) -1)
+ mode = inode->i_mode;
+@@ -581,6 +592,8 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
+ err = notify_change(dentry, &newattrs);
+ mutex_unlock(&inode->i_mutex);
+
++out_drop_write:
++ mnt_drop_write(file->f_path.mnt);
+ out_putf:
+ fput(file);
+ out:
+@@ -600,13 +613,13 @@ asmlinkage long sys_fchmodat(int dfd, const char __user *filename,
+ goto out;
+ inode = nd.path.dentry->d_inode;
+
+- error = -EROFS;
+- if (IS_RDONLY(inode))
++ error = mnt_want_write(nd.path.mnt);
++ if (error)
+ goto dput_and_out;
+
+ error = -EPERM;
+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+- goto dput_and_out;
++ goto out_drop_write;
+
+ mutex_lock(&inode->i_mutex);
+ if (mode == (mode_t) -1)
+@@ -616,6 +629,8 @@ asmlinkage long sys_fchmodat(int dfd, const char __user *filename,
+ error = notify_change(nd.path.dentry, &newattrs);
+ mutex_unlock(&inode->i_mutex);
+
++out_drop_write:
++ mnt_drop_write(nd.path.mnt);
+ dput_and_out:
+ path_put(&nd.path);
+ out:
+@@ -638,9 +653,6 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
+ printk(KERN_ERR "chown_common: NULL inode\n");
+ goto out;
+ }
+- error = -EROFS;
+- if (IS_RDONLY(inode))
+- goto out;
+ error = -EPERM;
+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+ goto out;
+@@ -671,7 +683,12 @@ asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group)
+ error = user_path_walk(filename, &nd);
+ if (error)
+ goto out;
++ error = mnt_want_write(nd.path.mnt);
++ if (error)
++ goto out_release;
+ error = chown_common(nd.path.dentry, user, group);
++ mnt_drop_write(nd.path.mnt);
++out_release:
+ path_put(&nd.path);
+ out:
+ return error;
+@@ -691,7 +708,12 @@ asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user,
+ error = __user_walk_fd(dfd, filename, follow, &nd);
+ if (error)
+ goto out;
++ error = mnt_want_write(nd.path.mnt);
++ if (error)
++ goto out_release;
+ error = chown_common(nd.path.dentry, user, group);
++ mnt_drop_write(nd.path.mnt);
++out_release:
+ path_put(&nd.path);
+ out:
+ return error;
+@@ -705,7 +727,12 @@ asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group
+ error = user_path_walk_link(filename, &nd);
+ if (error)
+ goto out;
++ error = mnt_want_write(nd.path.mnt);
++ if (error)
++ goto out_release;
+ error = chown_common(nd.path.dentry, user, group);
++ mnt_drop_write(nd.path.mnt);
++out_release:
+ path_put(&nd.path);
+ out:
+ return error;
+@@ -722,14 +749,48 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
+ if (!file)
+ goto out;
+
++ error = mnt_want_write(file->f_path.mnt);
++ if (error)
++ goto out_fput;
+ dentry = file->f_path.dentry;
+ audit_inode(NULL, dentry);
+ error = chown_common(dentry, user, group);
++ mnt_drop_write(file->f_path.mnt);
++out_fput:
+ fput(file);
+ out:
+ return error;
+ }
+
++/*
++ * You have to be very careful that these write
++ * counts get cleaned up in error cases and
++ * upon __fput(). This should probably never
++ * be called outside of __dentry_open().
++ */
++static inline int __get_file_write_access(struct inode *inode,
++ struct vfsmount *mnt)
++{
++ int error;
++ error = get_write_access(inode);
++ if (error)
++ return error;
++ /*
++ * Do not take mount writer counts on
++ * special files since no writes to
++ * the mount itself will occur.
++ */
++ if (!special_file(inode->i_mode)) {
++ /*
++ * Balanced in __fput()
++ */
++ error = mnt_want_write(mnt);
++ if (error)
++ put_write_access(inode);
++ }
++ return error;
++}
++
+ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
+ int flags, struct file *f,
+ int (*open)(struct inode *, struct file *))
+@@ -742,9 +803,11 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
+ FMODE_PREAD | FMODE_PWRITE;
+ inode = dentry->d_inode;
+ if (f->f_mode & FMODE_WRITE) {
+- error = get_write_access(inode);
++ error = __get_file_write_access(inode, mnt);
+ if (error)
+ goto cleanup_file;
++ if (!special_file(inode->i_mode))
++ file_take_write(f);
+ }
+
+ f->f_mapping = inode->i_mapping;
+@@ -784,8 +847,19 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
+
+ cleanup_all:
+ fops_put(f->f_op);
+- if (f->f_mode & FMODE_WRITE)
++ if (f->f_mode & FMODE_WRITE) {
+ put_write_access(inode);
++ if (!special_file(inode->i_mode)) {
++ /*
++ * We don't consider this a real
++ * mnt_want/drop_write() pair
++ * because it all happenend right
++ * here, so just reset the state.
++ */
++ file_reset_write(f);
++ mnt_drop_write(mnt);
++ }
++ }
+ file_kill(f);
+ f->f_path.dentry = NULL;
+ f->f_path.mnt = NULL;
+@@ -796,43 +870,6 @@ cleanup_file:
+ return ERR_PTR(error);
+ }
+
+-/*
+- * Note that while the flag value (low two bits) for sys_open means:
+- * 00 - read-only
+- * 01 - write-only
+- * 10 - read-write
+- * 11 - special
+- * it is changed into
+- * 00 - no permissions needed
+- * 01 - read-permission
+- * 10 - write-permission
+- * 11 - read-write
+- * for the internal routines (ie open_namei()/follow_link() etc). 00 is
+- * used by symlinks.
+- */
+-static struct file *do_filp_open(int dfd, const char *filename, int flags,
+- int mode)
+-{
+- int namei_flags, error;
+- struct nameidata nd;
+-
+- namei_flags = flags;
+- if ((namei_flags+1) & O_ACCMODE)
+- namei_flags++;
+-
+- error = open_namei(dfd, filename, namei_flags, mode, &nd);
+- if (!error)
+- return nameidata_to_filp(&nd, flags);
+-
+- return ERR_PTR(error);
+-}
+-
+-struct file *filp_open(const char *filename, int flags, int mode)
+-{
+- return do_filp_open(AT_FDCWD, filename, flags, mode);
+-}
+-EXPORT_SYMBOL(filp_open);
+-
+ /**
+ * lookup_instantiate_filp - instantiates the open intent filp
+ * @nd: pointer to nameidata
+diff --git a/fs/partitions/check.c b/fs/partitions/check.c
+index 03f808c..6149e4b 100644
+--- a/fs/partitions/check.c
++++ b/fs/partitions/check.c
+@@ -473,6 +473,10 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
+ return 0;
+ if (IS_ERR(state)) /* I/O error reading the partition table */
+ return -EIO;
++
++ /* tell userspace that the media / partition table may have changed */
++ kobject_uevent(&disk->dev.kobj, KOBJ_CHANGE);
++
+ for (p = 1; p < state->limit; p++) {
+ sector_t size = state->parts[p].size;
+ sector_t from = state->parts[p].from;
+diff --git a/fs/pipe.c b/fs/pipe.c
+index 8be381b..f73492b 100644
+--- a/fs/pipe.c
++++ b/fs/pipe.c
+@@ -988,7 +988,10 @@ struct file *create_write_pipe(void)
+ return f;
+
+ err_dentry:
++ free_pipe_info(inode);
+ dput(dentry);
++ return ERR_PTR(err);
++
+ err_inode:
+ free_pipe_info(inode);
+ iput(inode);
+diff --git a/fs/pnode.c b/fs/pnode.c
+index 1d8f544..8d5f392 100644
+--- a/fs/pnode.c
++++ b/fs/pnode.c
+@@ -9,6 +9,7 @@
+ #include <linux/mnt_namespace.h>
+ #include <linux/mount.h>
+ #include <linux/fs.h>
++#include "internal.h"
+ #include "pnode.h"
+
+ /* return the next shared peer mount of @p */
+@@ -27,6 +28,57 @@ static inline struct vfsmount *next_slave(struct vfsmount *p)
+ return list_entry(p->mnt_slave.next, struct vfsmount, mnt_slave);
+ }
+
++/*
++ * Return true if path is reachable from root
++ *
++ * namespace_sem is held, and mnt is attached
++ */
++static bool is_path_reachable(struct vfsmount *mnt, struct dentry *dentry,
++ const struct path *root)
++{
++ while (mnt != root->mnt && mnt->mnt_parent != mnt) {
++ dentry = mnt->mnt_mountpoint;
++ mnt = mnt->mnt_parent;
++ }
++ return mnt == root->mnt && is_subdir(dentry, root->dentry);
++}
++
++static struct vfsmount *get_peer_under_root(struct vfsmount *mnt,
++ struct mnt_namespace *ns,
++ const struct path *root)
++{
++ struct vfsmount *m = mnt;
++
++ do {
++ /* Check the namespace first for optimization */
++ if (m->mnt_ns == ns && is_path_reachable(m, m->mnt_root, root))
++ return m;
++
++ m = next_peer(m);
++ } while (m != mnt);
++
++ return NULL;
++}
++
++/*
++ * Get ID of closest dominating peer group having a representative
++ * under the given root.
++ *
++ * Caller must hold namespace_sem
++ */
++int get_dominating_id(struct vfsmount *mnt, const struct path *root)
++{
++ struct vfsmount *m;
++
++ for (m = mnt->mnt_master; m != NULL; m = m->mnt_master) {
++ struct vfsmount *d = get_peer_under_root(m, mnt->mnt_ns, root);
++ if (d)
++ return d->mnt_group_id;
++ }
++
++ return 0;
++}
++
+ static int do_make_slave(struct vfsmount *mnt)
+ {
+ struct vfsmount *peer_mnt = mnt, *master = mnt->mnt_master;
+@@ -45,7 +97,11 @@ static int do_make_slave(struct vfsmount *mnt)
+ if (peer_mnt == mnt)
+ peer_mnt = NULL;
+ }
++ if (IS_MNT_SHARED(mnt) && list_empty(&mnt->mnt_share))
++ mnt_release_group_id(mnt);
++
+ list_del_init(&mnt->mnt_share);
++ mnt->mnt_group_id = 0;
+
+ if (peer_mnt)
+ master = peer_mnt;
+@@ -67,7 +123,6 @@ static int do_make_slave(struct vfsmount *mnt)
+ }
+ mnt->mnt_master = master;
+ CLEAR_MNT_SHARED(mnt);
+- INIT_LIST_HEAD(&mnt->mnt_slave_list);
+ return 0;
+ }
+
+@@ -211,8 +266,7 @@ int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry,
+ out:
+ spin_lock(&vfsmount_lock);
+ while (!list_empty(&tmp_list)) {
+- child = list_entry(tmp_list.next, struct vfsmount, mnt_hash);
+- list_del_init(&child->mnt_hash);
++ child = list_first_entry(&tmp_list, struct vfsmount, mnt_hash);
+ umount_tree(child, 0, &umount_list);
+ }
+ spin_unlock(&vfsmount_lock);
+diff --git a/fs/pnode.h b/fs/pnode.h
+index f249be2..958665d 100644
+--- a/fs/pnode.h
++++ b/fs/pnode.h
+@@ -35,4 +35,6 @@ int propagate_mnt(struct vfsmount *, struct dentry *, struct vfsmount *,
+ struct list_head *);
+ int propagate_umount(struct list_head *);
+ int propagate_mount_busy(struct vfsmount *, int);
++void mnt_release_group_id(struct vfsmount *);
++int get_dominating_id(struct vfsmount *mnt, const struct path *root);
+ #endif /* _LINUX_PNODE_H */
+diff --git a/fs/proc/base.c b/fs/proc/base.c
+index 81d7d14..c5e412a 100644
+--- a/fs/proc/base.c
++++ b/fs/proc/base.c
+@@ -502,17 +502,14 @@ static const struct inode_operations proc_def_inode_operations = {
+ .setattr = proc_setattr,
+ };
+
+-extern const struct seq_operations mounts_op;
+-struct proc_mounts {
+- struct seq_file m;
+- int event;
+-};
+-
+-static int mounts_open(struct inode *inode, struct file *file)
++static int mounts_open_common(struct inode *inode, struct file *file,
++ const struct seq_operations *op)
+ {
+ struct task_struct *task = get_proc_task(inode);
+ struct nsproxy *nsp;
+ struct mnt_namespace *ns = NULL;
++ struct fs_struct *fs = NULL;
++ struct path root;
+ struct proc_mounts *p;
+ int ret = -EINVAL;
+
+@@ -525,40 +522,61 @@ static int mounts_open(struct inode *inode, struct file *file)
+ get_mnt_ns(ns);
+ }
+ rcu_read_unlock();
+-
++ if (ns)
++ fs = get_fs_struct(task);
+ put_task_struct(task);
+ }
+
+- if (ns) {
+- ret = -ENOMEM;
+- p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);
+- if (p) {
+- file->private_data = &p->m;
+- ret = seq_open(file, &mounts_op);
+- if (!ret) {
+- p->m.private = ns;
+- p->event = ns->event;
+- return 0;
+- }
+- kfree(p);
+- }
+- put_mnt_ns(ns);
+- }
++ if (!ns)
++ goto err;
++ if (!fs)
++ goto err_put_ns;
++
++ read_lock(&fs->lock);
++ root = fs->root;
++ path_get(&root);
++ read_unlock(&fs->lock);
++ put_fs_struct(fs);
++
++ ret = -ENOMEM;
++ p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);
++ if (!p)
++ goto err_put_path;
++
++ file->private_data = &p->m;
++ ret = seq_open(file, op);
++ if (ret)
++ goto err_free;
++
++ p->m.private = p;
++ p->ns = ns;
++ p->root = root;
++ p->event = ns->event;
++
++ return 0;
++
++ err_free:
++ kfree(p);
++ err_put_path:
++ path_put(&root);
++ err_put_ns:
++ put_mnt_ns(ns);
++ err:
+ return ret;
+ }
+
+ static int mounts_release(struct inode *inode, struct file *file)
+ {
+- struct seq_file *m = file->private_data;
+- struct mnt_namespace *ns = m->private;
+- put_mnt_ns(ns);
++ struct proc_mounts *p = file->private_data;
++ path_put(&p->root);
++ put_mnt_ns(p->ns);
+ return seq_release(inode, file);
+ }
+
+ static unsigned mounts_poll(struct file *file, poll_table *wait)
+ {
+ struct proc_mounts *p = file->private_data;
+- struct mnt_namespace *ns = p->m.private;
++ struct mnt_namespace *ns = p->ns;
+ unsigned res = 0;
+
+ poll_wait(file, &ns->poll, wait);
+@@ -573,6 +591,11 @@ static unsigned mounts_poll(struct file *file, poll_table *wait)
+ return res;
+ }
+
++static int mounts_open(struct inode *inode, struct file *file)
++{
++ return mounts_open_common(inode, file, &mounts_op);
++}
++
+ static const struct file_operations proc_mounts_operations = {
+ .open = mounts_open,
+ .read = seq_read,
+@@ -581,38 +604,22 @@ static const struct file_operations proc_mounts_operations = {
+ .poll = mounts_poll,
+ };
+
+-extern const struct seq_operations mountstats_op;
+-static int mountstats_open(struct inode *inode, struct file *file)
++static int mountinfo_open(struct inode *inode, struct file *file)
+ {
+- int ret = seq_open(file, &mountstats_op);
+-
+- if (!ret) {
+- struct seq_file *m = file->private_data;
+- struct nsproxy *nsp;
+- struct mnt_namespace *mnt_ns = NULL;
+- struct task_struct *task = get_proc_task(inode);
+-
+- if (task) {
+- rcu_read_lock();
+- nsp = task_nsproxy(task);
+- if (nsp) {
+- mnt_ns = nsp->mnt_ns;
+- if (mnt_ns)
+- get_mnt_ns(mnt_ns);
+- }
+- rcu_read_unlock();
++ return mounts_open_common(inode, file, &mountinfo_op);
++}
+
+- put_task_struct(task);
+- }
++static const struct file_operations proc_mountinfo_operations = {
++ .open = mountinfo_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = mounts_release,
++ .poll = mounts_poll,
++};
+
+- if (mnt_ns)
+- m->private = mnt_ns;
+- else {
+- seq_release(inode, file);
+- ret = -EINVAL;
+- }
+- }
+- return ret;
++static int mountstats_open(struct inode *inode, struct file *file)
++{
++ return mounts_open_common(inode, file, &mountstats_op);
+ }
+
+ static const struct file_operations proc_mountstats_operations = {
+@@ -1626,7 +1633,6 @@ static int proc_readfd_common(struct file * filp, void * dirent,
+ unsigned int fd, ino;
+ int retval;
+ struct files_struct * files;
+- struct fdtable *fdt;
+
+ retval = -ENOENT;
+ if (!p)
+@@ -1649,9 +1655,8 @@ static int proc_readfd_common(struct file * filp, void * dirent,
+ if (!files)
+ goto out;
+ rcu_read_lock();
+- fdt = files_fdtable(files);
+ for (fd = filp->f_pos-2;
+- fd < fdt->max_fds;
++ fd < files_fdtable(files)->max_fds;
+ fd++, filp->f_pos++) {
+ char name[PROC_NUMBUF];
+ int len;
+@@ -2311,6 +2316,7 @@ static const struct pid_entry tgid_base_stuff[] = {
+ LNK("root", root),
+ LNK("exe", exe),
+ REG("mounts", S_IRUGO, mounts),
++ REG("mountinfo", S_IRUGO, mountinfo),
+ REG("mountstats", S_IRUSR, mountstats),
+ #ifdef CONFIG_PROC_PAGE_MONITOR
+ REG("clear_refs", S_IWUSR, clear_refs),
+@@ -2643,6 +2649,7 @@ static const struct pid_entry tid_base_stuff[] = {
+ LNK("root", root),
+ LNK("exe", exe),
+ REG("mounts", S_IRUGO, mounts),
++ REG("mountinfo", S_IRUGO, mountinfo),
+ #ifdef CONFIG_PROC_PAGE_MONITOR
+ REG("clear_refs", S_IWUSR, clear_refs),
+ REG("smaps", S_IRUGO, smaps),
+diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
+index 4caa5f7..13cd783 100644
+--- a/fs/proc/proc_net.c
++++ b/fs/proc/proc_net.c
+@@ -44,7 +44,9 @@ int seq_open_net(struct inode *ino, struct file *f,
+ put_net(net);
+ return -ENOMEM;
+ }
++#ifdef CONFIG_NET_NS
+ p->net = net;
++#endif
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(seq_open_net);
+@@ -52,12 +54,10 @@ EXPORT_SYMBOL_GPL(seq_open_net);
+ int seq_release_net(struct inode *ino, struct file *f)
+ {
+ struct seq_file *seq;
+- struct seq_net_private *p;
+
+ seq = f->private_data;
+- p = seq->private;
+
+- put_net(p->net);
++ put_net(seq_file_net(seq));
+ seq_release_private(ino, f);
+ return 0;
+ }
+diff --git a/fs/read_write.c b/fs/read_write.c
+index 49a9871..f0d1240 100644
+--- a/fs/read_write.c
++++ b/fs/read_write.c
+@@ -33,7 +33,7 @@ EXPORT_SYMBOL(generic_ro_fops);
+
+ loff_t generic_file_llseek(struct file *file, loff_t offset, int origin)
+ {
+- long long retval;
++ loff_t retval;
+ struct inode *inode = file->f_mapping->host;
+
+ mutex_lock(&inode->i_mutex);
+@@ -60,7 +60,7 @@ EXPORT_SYMBOL(generic_file_llseek);
+
+ loff_t remote_llseek(struct file *file, loff_t offset, int origin)
+ {
+- long long retval;
++ loff_t retval;
+
+ lock_kernel();
+ switch (origin) {
+@@ -91,7 +91,7 @@ EXPORT_SYMBOL(no_llseek);
+
+ loff_t default_llseek(struct file *file, loff_t offset, int origin)
+ {
+- long long retval;
++ loff_t retval;
+
+ lock_kernel();
+ switch (origin) {
+diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
+index e0f0f09..74363a7 100644
+--- a/fs/reiserfs/ioctl.c
++++ b/fs/reiserfs/ioctl.c
+@@ -4,6 +4,7 @@
+
+ #include <linux/capability.h>
+ #include <linux/fs.h>
++#include <linux/mount.h>
+ #include <linux/reiserfs_fs.h>
+ #include <linux/time.h>
+ #include <asm/uaccess.h>
+@@ -25,6 +26,7 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+ {
+ unsigned int flags;
++ int err = 0;
+
+ switch (cmd) {
+ case REISERFS_IOC_UNPACK:
+@@ -48,50 +50,67 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+ if (!reiserfs_attrs(inode->i_sb))
+ return -ENOTTY;
+
+- if (IS_RDONLY(inode))
+- return -EROFS;
++ err = mnt_want_write(filp->f_path.mnt);
++ if (err)
++ return err;
+
+- if (!is_owner_or_cap(inode))
+- return -EPERM;
+-
+- if (get_user(flags, (int __user *)arg))
+- return -EFAULT;
+-
+- /* Is it quota file? Do not allow user to mess with it. */
+- if (IS_NOQUOTA(inode))
+- return -EPERM;
++ if (!is_owner_or_cap(inode)) {
++ err = -EPERM;
++ goto setflags_out;
++ }
++ if (get_user(flags, (int __user *)arg)) {
++ err = -EFAULT;
++ goto setflags_out;
++ }
++ /*
++ * Is it quota file? Do not allow user to mess with it
++ */
++ if (IS_NOQUOTA(inode)) {
++ err = -EPERM;
++ goto setflags_out;
++ }
+ if (((flags ^ REISERFS_I(inode)->
+ i_attrs) & (REISERFS_IMMUTABLE_FL |
+ REISERFS_APPEND_FL))
+- && !capable(CAP_LINUX_IMMUTABLE))
+- return -EPERM;
+-
++ && !capable(CAP_LINUX_IMMUTABLE)) {
++ err = -EPERM;
++ goto setflags_out;
++ }
+ if ((flags & REISERFS_NOTAIL_FL) &&
+ S_ISREG(inode->i_mode)) {
+ int result;
+
+ result = reiserfs_unpack(inode, filp);
+- if (result)
+- return result;
++ if (result) {
++ err = result;
++ goto setflags_out;
++ }
+ }
+ sd_attrs_to_i_attrs(flags, inode);
+ REISERFS_I(inode)->i_attrs = flags;
+ inode->i_ctime = CURRENT_TIME_SEC;
+ mark_inode_dirty(inode);
+- return 0;
++setflags_out:
++ mnt_drop_write(filp->f_path.mnt);
++ return err;
+ }
+ case REISERFS_IOC_GETVERSION:
+ return put_user(inode->i_generation, (int __user *)arg);
+ case REISERFS_IOC_SETVERSION:
+ if (!is_owner_or_cap(inode))
+ return -EPERM;
+- if (IS_RDONLY(inode))
+- return -EROFS;
+- if (get_user(inode->i_generation, (int __user *)arg))
+- return -EFAULT;
++ err = mnt_want_write(filp->f_path.mnt);
++ if (err)
++ return err;
++ if (get_user(inode->i_generation, (int __user *)arg)) {
++ err = -EFAULT;
++ goto setversion_out;
++ }
+ inode->i_ctime = CURRENT_TIME_SEC;
+ mark_inode_dirty(inode);
+- return 0;
++setversion_out:
++ mnt_drop_write(filp->f_path.mnt);
++ return err;
+ default:
+ return -ENOTTY;
+ }
+diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
+index bb05a3e..060eb3f 100644
+--- a/fs/reiserfs/journal.c
++++ b/fs/reiserfs/journal.c
+@@ -38,7 +38,7 @@
+ #include <asm/system.h>
+
+ #include <linux/time.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+
+ #include <linux/vmalloc.h>
+ #include <linux/reiserfs_fs.h>
+diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
+index 344b9b9..d7c4935 100644
+--- a/fs/reiserfs/xattr.c
++++ b/fs/reiserfs/xattr.c
+@@ -44,7 +44,6 @@
+ #include <net/checksum.h>
+ #include <linux/smp_lock.h>
+ #include <linux/stat.h>
+-#include <asm/semaphore.h>
+
+ #define FL_READONLY 128
+ #define FL_DIR_SEM_HELD 256
+diff --git a/fs/select.c b/fs/select.c
+index 5633fe9..00f58c5 100644
+--- a/fs/select.c
++++ b/fs/select.c
+@@ -260,7 +260,7 @@ int do_select(int n, fd_set_bits *fds, s64 *timeout)
+ wait = NULL;
+ if (retval || !*timeout || signal_pending(current))
+ break;
+- if(table.error) {
++ if (table.error) {
+ retval = table.error;
+ break;
+ }
+diff --git a/fs/seq_file.c b/fs/seq_file.c
+index 8537702..3f54dbd 100644
+--- a/fs/seq_file.c
++++ b/fs/seq_file.c
+@@ -25,6 +25,7 @@
+ * into the buffer. In case of error ->start() and ->next() return
+ * ERR_PTR(error). In the end of sequence they return %NULL. ->show()
+ * returns 0 in case of success and negative number in case of error.
++ * Returning SEQ_SKIP means "discard this element and move on".
+ */
+ int seq_open(struct file *file, const struct seq_operations *op)
+ {
+@@ -114,8 +115,10 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
+ if (!p || IS_ERR(p))
+ break;
+ err = m->op->show(m, p);
+- if (err)
++ if (err < 0)
+ break;
++ if (unlikely(err))
++ m->count = 0;
+ if (m->count < m->size)
+ goto Fill;
+ m->op->stop(m, p);
+@@ -140,9 +143,10 @@ Fill:
+ break;
+ }
+ err = m->op->show(m, p);
+- if (err || m->count == m->size) {
++ if (m->count == m->size || err) {
+ m->count = offs;
+- break;
++ if (likely(err <= 0))
++ break;
+ }
+ pos = next;
+ }
+@@ -199,8 +203,12 @@ static int traverse(struct seq_file *m, loff_t offset)
+ if (IS_ERR(p))
+ break;
+ error = m->op->show(m, p);
+- if (error)
++ if (error < 0)
+ break;
++ if (unlikely(error)) {
++ error = 0;
++ m->count = 0;
++ }
+ if (m->count == m->size)
+ goto Eoverflow;
+ if (pos + m->count > offset) {
+@@ -239,7 +247,7 @@ Eoverflow:
+ loff_t seq_lseek(struct file *file, loff_t offset, int origin)
+ {
+ struct seq_file *m = (struct seq_file *)file->private_data;
+- long long retval = -EINVAL;
++ loff_t retval = -EINVAL;
+
+ mutex_lock(&m->lock);
+ m->version = file->f_version;
+@@ -342,28 +350,40 @@ int seq_printf(struct seq_file *m, const char *f, ...)
+ }
+ EXPORT_SYMBOL(seq_printf);
+
++static char *mangle_path(char *s, char *p, char *esc)
++{
++ while (s <= p) {
++ char c = *p++;
++ if (!c) {
++ return s;
++ } else if (!strchr(esc, c)) {
++ *s++ = c;
++ } else if (s + 4 > p) {
++ break;
++ } else {
++ *s++ = '\\';
++ *s++ = '0' + ((c & 0300) >> 6);
++ *s++ = '0' + ((c & 070) >> 3);
++ *s++ = '0' + (c & 07);
++ }
++ }
++ return NULL;
++}
++
++/*
++ * return the absolute path of 'dentry' residing in mount 'mnt'.
++ */
+ int seq_path(struct seq_file *m, struct path *path, char *esc)
+ {
+ if (m->count < m->size) {
+ char *s = m->buf + m->count;
+ char *p = d_path(path, s, m->size - m->count);
+ if (!IS_ERR(p)) {
+- while (s <= p) {
+- char c = *p++;
+- if (!c) {
+- p = m->buf + m->count;
+- m->count = s - m->buf;
+- return s - p;
+- } else if (!strchr(esc, c)) {
+- *s++ = c;
+- } else if (s + 4 > p) {
+- break;
+- } else {
+- *s++ = '\\';
+- *s++ = '0' + ((c & 0300) >> 6);
+- *s++ = '0' + ((c & 070) >> 3);
+- *s++ = '0' + (c & 07);
+- }
++ s = mangle_path(s, p, esc);
++ if (s) {
++ p = m->buf + m->count;
++ m->count = s - m->buf;
++ return s - p;
+ }
+ }
+ }
+@@ -372,6 +392,57 @@ int seq_path(struct seq_file *m, struct path *path, char *esc)
+ }
+ EXPORT_SYMBOL(seq_path);
+
++/*
++ * Same as seq_path, but relative to supplied root.
++ *
++ * root may be changed, see __d_path().
++ */
++int seq_path_root(struct seq_file *m, struct path *path, struct path *root,
++ char *esc)
++{
++ int err = -ENAMETOOLONG;
++ if (m->count < m->size) {
++ char *s = m->buf + m->count;
++ char *p;
++
++ spin_lock(&dcache_lock);
++ p = __d_path(path, root, s, m->size - m->count);
++ spin_unlock(&dcache_lock);
++ err = PTR_ERR(p);
++ if (!IS_ERR(p)) {
++ s = mangle_path(s, p, esc);
++ if (s) {
++ p = m->buf + m->count;
++ m->count = s - m->buf;
++ return 0;
++ }
++ }
++ }
++ m->count = m->size;
++ return err;
++}
++
++/*
++ * returns the path of the 'dentry' from the root of its filesystem.
++ */
++int seq_dentry(struct seq_file *m, struct dentry *dentry, char *esc)
++{
++ if (m->count < m->size) {
++ char *s = m->buf + m->count;
++ char *p = dentry_path(dentry, s, m->size - m->count);
++ if (!IS_ERR(p)) {
++ s = mangle_path(s, p, esc);
++ if (s) {
++ p = m->buf + m->count;
++ m->count = s - m->buf;
++ return s - p;
++ }
++ }
++ }
++ m->count = m->size;
++ return -1;
++}
++
+ static void *single_start(struct seq_file *p, loff_t *pos)
+ {
+ return NULL + (*pos == 0);
+diff --git a/fs/super.c b/fs/super.c
+index 09008db..4798350 100644
+--- a/fs/super.c
++++ b/fs/super.c
+@@ -37,7 +37,9 @@
+ #include <linux/idr.h>
+ #include <linux/kobject.h>
+ #include <linux/mutex.h>
++#include <linux/file.h>
+ #include <asm/uaccess.h>
++#include "internal.h"
+
+
+ LIST_HEAD(super_blocks);
+@@ -567,10 +569,29 @@ static void mark_files_ro(struct super_block *sb)
+ {
+ struct file *f;
+
++retry:
+ file_list_lock();
+ list_for_each_entry(f, &sb->s_files, f_u.fu_list) {
+- if (S_ISREG(f->f_path.dentry->d_inode->i_mode) && file_count(f))
+- f->f_mode &= ~FMODE_WRITE;
++ struct vfsmount *mnt;
++ if (!S_ISREG(f->f_path.dentry->d_inode->i_mode))
++ continue;
++ if (!file_count(f))
++ continue;
++ if (!(f->f_mode & FMODE_WRITE))
++ continue;
++ f->f_mode &= ~FMODE_WRITE;
++ if (file_check_writeable(f) != 0)
++ continue;
++ file_release_write(f);
++ mnt = mntget(f->f_path.mnt);
++ file_list_unlock();
++ /*
++ * This can sleep, so we can't hold
++ * the file_list_lock() spinlock.
++ */
++ mnt_drop_write(mnt);
++ mntput(mnt);
++ goto retry;
+ }
+ file_list_unlock();
+ }
+diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
+index 4948d9b..a1c3a1f 100644
+--- a/fs/sysfs/dir.c
++++ b/fs/sysfs/dir.c
+@@ -20,6 +20,7 @@
+ #include <linux/idr.h>
+ #include <linux/completion.h>
+ #include <linux/mutex.h>
++#include <linux/slab.h>
+ #include "sysfs.h"
+
+ DEFINE_MUTEX(sysfs_mutex);
+diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
+index baa663e..ade9a7e 100644
+--- a/fs/sysfs/file.c
++++ b/fs/sysfs/file.c
+@@ -13,6 +13,7 @@
+ #include <linux/module.h>
+ #include <linux/kobject.h>
+ #include <linux/kallsyms.h>
++#include <linux/slab.h>
+ #include <linux/namei.h>
+ #include <linux/poll.h>
+ #include <linux/list.h>
+@@ -128,7 +129,7 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+ ssize_t retval = 0;
+
+ mutex_lock(&buffer->mutex);
+- if (buffer->needs_read_fill) {
++ if (buffer->needs_read_fill || *ppos == 0) {
+ retval = fill_read_buffer(file->f_path.dentry,buffer);
+ if (retval)
+ goto out;
+@@ -409,8 +410,7 @@ static int sysfs_release(struct inode *inode, struct file *filp)
+ * return POLLERR|POLLPRI, and select will return the fd whether
+ * it is waiting for read, write, or exceptions.
+ * Once poll/select indicates that the value has changed, you
+- * need to close and re-open the file, as simply seeking and reading
+- * again will not get new data, or reset the state of 'poll'.
++ * need to close and re-open the file, or seek to 0 and read again.
+ * Reminder: this only works for attributes which actively support
+ * it, and it is not possible to test an attribute from userspace
+ * to see if it supports poll (Neither 'poll' nor 'select' return
+diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
+index 5f66c44..817f596 100644
+--- a/fs/sysfs/symlink.c
++++ b/fs/sysfs/symlink.c
+@@ -87,7 +87,14 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char
+
+ void sysfs_remove_link(struct kobject * kobj, const char * name)
+ {
+- sysfs_hash_and_remove(kobj->sd, name);
++ struct sysfs_dirent *parent_sd = NULL;
++
++ if (!kobj)
++ parent_sd = &sysfs_root;
++ else
++ parent_sd = kobj->sd;
++
++ sysfs_hash_and_remove(parent_sd, name);
+ }
+
+ static int sysfs_get_target_path(struct sysfs_dirent *parent_sd,
+diff --git a/fs/udf/Makefile b/fs/udf/Makefile
+index be845e7..0d4503f 100644
+--- a/fs/udf/Makefile
++++ b/fs/udf/Makefile
+@@ -6,4 +6,4 @@ obj-$(CONFIG_UDF_FS) += udf.o
+
+ udf-objs := balloc.o dir.o file.o ialloc.o inode.o lowlevel.o namei.o \
+ partition.o super.o truncate.o symlink.o fsync.o \
+- crc.o directory.o misc.o udftime.o unicode.o
++ directory.o misc.o udftime.o unicode.o
+diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c
+index f855dcb..1b809bd 100644
+--- a/fs/udf/balloc.c
++++ b/fs/udf/balloc.c
+@@ -149,8 +149,7 @@ static bool udf_add_free_space(struct udf_sb_info *sbi,
+ return false;
+
+ lvid = (struct logicalVolIntegrityDesc *)sbi->s_lvid_bh->b_data;
+- lvid->freeSpaceTable[partition] = cpu_to_le32(le32_to_cpu(
+- lvid->freeSpaceTable[partition]) + cnt);
++ le32_add_cpu(&lvid->freeSpaceTable[partition], cnt);
+ return true;
+ }
+
+@@ -589,10 +588,8 @@ static void udf_table_free_blocks(struct super_block *sb,
+ sptr = oepos.bh->b_data + epos.offset;
+ aed = (struct allocExtDesc *)
+ oepos.bh->b_data;
+- aed->lengthAllocDescs =
+- cpu_to_le32(le32_to_cpu(
+- aed->lengthAllocDescs) +
+- adsize);
++ le32_add_cpu(&aed->lengthAllocDescs,
++ adsize);
+ } else {
+ sptr = iinfo->i_ext.i_data +
+ epos.offset;
+@@ -645,9 +642,7 @@ static void udf_table_free_blocks(struct super_block *sb,
+ mark_inode_dirty(table);
+ } else {
+ aed = (struct allocExtDesc *)epos.bh->b_data;
+- aed->lengthAllocDescs =
+- cpu_to_le32(le32_to_cpu(
+- aed->lengthAllocDescs) + adsize);
++ le32_add_cpu(&aed->lengthAllocDescs, adsize);
+ udf_update_tag(epos.bh->b_data, epos.offset);
+ mark_buffer_dirty(epos.bh);
+ }
+diff --git a/fs/udf/crc.c b/fs/udf/crc.c
+deleted file mode 100644
+index b166129..0000000
+--- a/fs/udf/crc.c
++++ /dev/null
+@@ -1,172 +0,0 @@
+-/*
+- * crc.c
+- *
+- * PURPOSE
+- * Routines to generate, calculate, and test a 16-bit CRC.
+- *
+- * DESCRIPTION
+- * The CRC code was devised by Don P. Mitchell of AT&T Bell Laboratories
+- * and Ned W. Rhodes of Software Systems Group. It has been published in
+- * "Design and Validation of Computer Protocols", Prentice Hall,
+- * Englewood Cliffs, NJ, 1991, Chapter 3, ISBN 0-13-539925-4.
+- *
+- * Copyright is held by AT&T.
+- *
+- * AT&T gives permission for the free use of the CRC source code.
+- *
+- * COPYRIGHT
+- * This file is distributed under the terms of the GNU General Public
+- * License (GPL). Copies of the GPL can be obtained from:
+- * ftp://prep.ai.mit.edu/pub/gnu/GPL
+- * Each contributing author retains all rights to their own work.
+- */
+-
+-#include "udfdecl.h"
+-
+-static uint16_t crc_table[256] = {
+- 0x0000U, 0x1021U, 0x2042U, 0x3063U, 0x4084U, 0x50a5U, 0x60c6U, 0x70e7U,
+- 0x8108U, 0x9129U, 0xa14aU, 0xb16bU, 0xc18cU, 0xd1adU, 0xe1ceU, 0xf1efU,
+- 0x1231U, 0x0210U, 0x3273U, 0x2252U, 0x52b5U, 0x4294U, 0x72f7U, 0x62d6U,
+- 0x9339U, 0x8318U, 0xb37bU, 0xa35aU, 0xd3bdU, 0xc39cU, 0xf3ffU, 0xe3deU,
+- 0x2462U, 0x3443U, 0x0420U, 0x1401U, 0x64e6U, 0x74c7U, 0x44a4U, 0x5485U,
+- 0xa56aU, 0xb54bU, 0x8528U, 0x9509U, 0xe5eeU, 0xf5cfU, 0xc5acU, 0xd58dU,
+- 0x3653U, 0x2672U, 0x1611U, 0x0630U, 0x76d7U, 0x66f6U, 0x5695U, 0x46b4U,
+- 0xb75bU, 0xa77aU, 0x9719U, 0x8738U, 0xf7dfU, 0xe7feU, 0xd79dU, 0xc7bcU,
+- 0x48c4U, 0x58e5U, 0x6886U, 0x78a7U, 0x0840U, 0x1861U, 0x2802U, 0x3823U,
+- 0xc9ccU, 0xd9edU, 0xe98eU, 0xf9afU, 0x8948U, 0x9969U, 0xa90aU, 0xb92bU,
+- 0x5af5U, 0x4ad4U, 0x7ab7U, 0x6a96U, 0x1a71U, 0x0a50U, 0x3a33U, 0x2a12U,
+- 0xdbfdU, 0xcbdcU, 0xfbbfU, 0xeb9eU, 0x9b79U, 0x8b58U, 0xbb3bU, 0xab1aU,
+- 0x6ca6U, 0x7c87U, 0x4ce4U, 0x5cc5U, 0x2c22U, 0x3c03U, 0x0c60U, 0x1c41U,
+- 0xedaeU, 0xfd8fU, 0xcdecU, 0xddcdU, 0xad2aU, 0xbd0bU, 0x8d68U, 0x9d49U,
+- 0x7e97U, 0x6eb6U, 0x5ed5U, 0x4ef4U, 0x3e13U, 0x2e32U, 0x1e51U, 0x0e70U,
+- 0xff9fU, 0xefbeU, 0xdfddU, 0xcffcU, 0xbf1bU, 0xaf3aU, 0x9f59U, 0x8f78U,
+- 0x9188U, 0x81a9U, 0xb1caU, 0xa1ebU, 0xd10cU, 0xc12dU, 0xf14eU, 0xe16fU,
+- 0x1080U, 0x00a1U, 0x30c2U, 0x20e3U, 0x5004U, 0x4025U, 0x7046U, 0x6067U,
+- 0x83b9U, 0x9398U, 0xa3fbU, 0xb3daU, 0xc33dU, 0xd31cU, 0xe37fU, 0xf35eU,
+- 0x02b1U, 0x1290U, 0x22f3U, 0x32d2U, 0x4235U, 0x5214U, 0x6277U, 0x7256U,
+- 0xb5eaU, 0xa5cbU, 0x95a8U, 0x8589U, 0xf56eU, 0xe54fU, 0xd52cU, 0xc50dU,
+- 0x34e2U, 0x24c3U, 0x14a0U, 0x0481U, 0x7466U, 0x6447U, 0x5424U, 0x4405U,
+- 0xa7dbU, 0xb7faU, 0x8799U, 0x97b8U, 0xe75fU, 0xf77eU, 0xc71dU, 0xd73cU,
+- 0x26d3U, 0x36f2U, 0x0691U, 0x16b0U, 0x6657U, 0x7676U, 0x4615U, 0x5634U,
+- 0xd94cU, 0xc96dU, 0xf90eU, 0xe92fU, 0x99c8U, 0x89e9U, 0xb98aU, 0xa9abU,
+- 0x5844U, 0x4865U, 0x7806U, 0x6827U, 0x18c0U, 0x08e1U, 0x3882U, 0x28a3U,
+- 0xcb7dU, 0xdb5cU, 0xeb3fU, 0xfb1eU, 0x8bf9U, 0x9bd8U, 0xabbbU, 0xbb9aU,
+- 0x4a75U, 0x5a54U, 0x6a37U, 0x7a16U, 0x0af1U, 0x1ad0U, 0x2ab3U, 0x3a92U,
+- 0xfd2eU, 0xed0fU, 0xdd6cU, 0xcd4dU, 0xbdaaU, 0xad8bU, 0x9de8U, 0x8dc9U,
+- 0x7c26U, 0x6c07U, 0x5c64U, 0x4c45U, 0x3ca2U, 0x2c83U, 0x1ce0U, 0x0cc1U,
+- 0xef1fU, 0xff3eU, 0xcf5dU, 0xdf7cU, 0xaf9bU, 0xbfbaU, 0x8fd9U, 0x9ff8U,
+- 0x6e17U, 0x7e36U, 0x4e55U, 0x5e74U, 0x2e93U, 0x3eb2U, 0x0ed1U, 0x1ef0U
+-};
+-
+-/*
+- * udf_crc
+- *
+- * PURPOSE
+- * Calculate a 16-bit CRC checksum using ITU-T V.41 polynomial.
+- *
+- * DESCRIPTION
+- * The OSTA-UDF(tm) 1.50 standard states that using CRCs is mandatory.
+- * The polynomial used is: x^16 + x^12 + x^15 + 1
+- *
+- * PRE-CONDITIONS
+- * data Pointer to the data block.
+- * size Size of the data block.
+- *
+- * POST-CONDITIONS
+- * <return> CRC of the data block.
+- *
+- * HISTORY
+- * July 21, 1997 - Andrew E. Mileski
+- * Adapted from OSTA-UDF(tm) 1.50 standard.
+- */
+-uint16_t udf_crc(uint8_t *data, uint32_t size, uint16_t crc)
+-{
+- while (size--)
+- crc = crc_table[(crc >> 8 ^ *(data++)) & 0xffU] ^ (crc << 8);
+-
+- return crc;
+-}
+-
+-/****************************************************************************/
+-#if defined(TEST)
+-
+-/*
+- * PURPOSE
+- * Test udf_crc()
+- *
+- * HISTORY
+- * July 21, 1997 - Andrew E. Mileski
+- * Adapted from OSTA-UDF(tm) 1.50 standard.
+- */
+-
+-unsigned char bytes[] = { 0x70U, 0x6AU, 0x77U };
+-
+-int main(void)
+-{
+- unsigned short x;
+-
+- x = udf_crc(bytes, sizeof bytes);
+- printf("udf_crc: calculated = %4.4x, correct = %4.4x\n", x, 0x3299U);
+-
+- return 0;
+-}
+-
+-#endif /* defined(TEST) */
+-
+-/****************************************************************************/
+-#if defined(GENERATE)
+-
+-/*
+- * PURPOSE
+- * Generate a table for fast 16-bit CRC calculations (any polynomial).
+- *
+- * DESCRIPTION
+- * The ITU-T V.41 polynomial is 010041.
+- *
+- * HISTORY
+- * July 21, 1997 - Andrew E. Mileski
+- * Adapted from OSTA-UDF(tm) 1.50 standard.
+- */
+-
+-#include <stdio.h>
+-
+-int main(int argc, char **argv)
+-{
+- unsigned long crc, poly;
+- int n, i;
+-
+- /* Get the polynomial */
+- sscanf(argv[1], "%lo", &poly);
+- if (poly & 0xffff0000U) {
+- fprintf(stderr, "polynomial is too large\en");
+- exit(1);
+- }
+-
+- printf("/* CRC 0%o */\n", poly);
+-
+- /* Create a table */
+- printf("static unsigned short crc_table[256] = {\n");
+- for (n = 0; n < 256; n++) {
+- if (n % 8 == 0)
+- printf("\t");
+- crc = n << 8;
+- for (i = 0; i < 8; i++) {
+- if (crc & 0x8000U)
+- crc = (crc << 1) ^ poly;
+- else
+- crc <<= 1;
+- crc &= 0xFFFFU;
+- }
+- if (n == 255)
+- printf("0x%04xU ", crc);
+- else
+- printf("0x%04xU, ", crc);
+- if (n % 8 == 7)
+- printf("\n");
+- }
+- printf("};\n");
+-
+- return 0;
+-}
+-
+-#endif /* defined(GENERATE) */
+diff --git a/fs/udf/dir.c b/fs/udf/dir.c
+index 8d8643a..62dc270 100644
+--- a/fs/udf/dir.c
++++ b/fs/udf/dir.c
+@@ -39,13 +39,13 @@
+ static int do_udf_readdir(struct inode *dir, struct file *filp,
+ filldir_t filldir, void *dirent)
+ {
+- struct udf_fileident_bh fibh;
++ struct udf_fileident_bh fibh = { .sbh = NULL, .ebh = NULL};
+ struct fileIdentDesc *fi = NULL;
+ struct fileIdentDesc cfi;
+ int block, iblock;
+ loff_t nf_pos = (filp->f_pos - 1) << 2;
+ int flen;
+- char fname[UDF_NAME_LEN];
++ char *fname = NULL;
+ char *nameptr;
+ uint16_t liu;
+ uint8_t lfi;
+@@ -54,23 +54,32 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
+ kernel_lb_addr eloc;
+ uint32_t elen;
+ sector_t offset;
+- int i, num;
++ int i, num, ret = 0;
+ unsigned int dt_type;
+ struct extent_position epos = { NULL, 0, {0, 0} };
+ struct udf_inode_info *iinfo;
+
+ if (nf_pos >= size)
+- return 0;
++ goto out;
++
++ fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
++ if (!fname) {
++ ret = -ENOMEM;
++ goto out;
++ }
+
+ if (nf_pos == 0)
+ nf_pos = udf_ext0_offset(dir);
+
+ fibh.soffset = fibh.eoffset = nf_pos & (dir->i_sb->s_blocksize - 1);
+ iinfo = UDF_I(dir);
+- if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
+- fibh.sbh = fibh.ebh = NULL;
+- } else if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits,
+- &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30)) {
++ if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
++ if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits,
++ &epos, &eloc, &elen, &offset)
++ != (EXT_RECORDED_ALLOCATED >> 30)) {
++ ret = -ENOENT;
++ goto out;
++ }
+ block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
+ if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
+ if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
+@@ -83,8 +92,8 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
+ }
+
+ if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block))) {
+- brelse(epos.bh);
+- return -EIO;
++ ret = -EIO;
++ goto out;
+ }
+
+ if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9)) - 1))) {
+@@ -105,9 +114,6 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
+ brelse(bha[i]);
+ }
+ }
+- } else {
+- brelse(epos.bh);
+- return -ENOENT;
+ }
+
+ while (nf_pos < size) {
+@@ -115,13 +121,8 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
+
+ fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc,
+ &elen, &offset);
+- if (!fi) {
+- if (fibh.sbh != fibh.ebh)
+- brelse(fibh.ebh);
+- brelse(fibh.sbh);
+- brelse(epos.bh);
+- return 0;
+- }
++ if (!fi)
++ goto out;
+
+ liu = le16_to_cpu(cfi.lengthOfImpUse);
+ lfi = cfi.lengthFileIdent;
+@@ -167,53 +168,23 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
+ dt_type = DT_UNKNOWN;
+ }
+
+- if (flen) {
+- if (filldir(dirent, fname, flen, filp->f_pos, iblock, dt_type) < 0) {
+- if (fibh.sbh != fibh.ebh)
+- brelse(fibh.ebh);
+- brelse(fibh.sbh);
+- brelse(epos.bh);
+- return 0;
+- }
+- }
++ if (flen && filldir(dirent, fname, flen, filp->f_pos,
++ iblock, dt_type) < 0)
++ goto out;
+ } /* end while */
+
+ filp->f_pos = (nf_pos >> 2) + 1;
+
++out:
+ if (fibh.sbh != fibh.ebh)
+ brelse(fibh.ebh);
+ brelse(fibh.sbh);
+ brelse(epos.bh);
++ kfree(fname);
+
+- return 0;
++ return ret;
+ }
+
+-/*
+- * udf_readdir
+- *
+- * PURPOSE
+- * Read a directory entry.
+- *
+- * DESCRIPTION
+- * Optional - sys_getdents() will return -ENOTDIR if this routine is not
+- * available.
+- *
+- * Refer to sys_getdents() in fs/readdir.c
+- * sys_getdents() -> .
+- *
+- * PRE-CONDITIONS
+- * filp Pointer to directory file.
+- * buf Pointer to directory entry buffer.
+- * filldir Pointer to filldir function.
+- *
+- * POST-CONDITIONS
+- * <return> >=0 on success.
+- *
+- * HISTORY
+- * July 1, 1997 - Andrew E. Mileski
+- * Written, tested, and released.
+- */
+-
+ static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ {
+ struct inode *dir = filp->f_path.dentry->d_inode;
+diff --git a/fs/udf/ecma_167.h b/fs/udf/ecma_167.h
+index 5638771..a0974df 100644
+--- a/fs/udf/ecma_167.h
++++ b/fs/udf/ecma_167.h
+@@ -70,19 +70,6 @@ typedef struct {
+ uint8_t microseconds;
+ } __attribute__ ((packed)) timestamp;
+
+-typedef struct {
+- uint16_t typeAndTimezone;
+- int16_t year;
+- uint8_t month;
+- uint8_t day;
+- uint8_t hour;
+- uint8_t minute;
+- uint8_t second;
+- uint8_t centiseconds;
+- uint8_t hundredsOfMicroseconds;
+- uint8_t microseconds;
+-} __attribute__ ((packed)) kernel_timestamp;
+-
+ /* Type and Time Zone (ECMA 167r3 1/7.3.1) */
+ #define TIMESTAMP_TYPE_MASK 0xF000
+ #define TIMESTAMP_TYPE_CUT 0x0000
+diff --git a/fs/udf/file.c b/fs/udf/file.c
+index 97c71ae..0ed6e14 100644
+--- a/fs/udf/file.c
++++ b/fs/udf/file.c
+@@ -27,7 +27,6 @@
+
+ #include "udfdecl.h"
+ #include <linux/fs.h>
+-#include <linux/udf_fs.h>
+ #include <asm/uaccess.h>
+ #include <linux/kernel.h>
+ #include <linux/string.h> /* memset */
+@@ -144,40 +143,6 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ return retval;
+ }
+
+-/*
+- * udf_ioctl
+- *
+- * PURPOSE
+- * Issue an ioctl.
+- *
+- * DESCRIPTION
+- * Optional - sys_ioctl() will return -ENOTTY if this routine is not
+- * available, and the ioctl cannot be handled without filesystem help.
+- *
+- * sys_ioctl() handles these ioctls that apply only to regular files:
+- * FIBMAP [requires udf_block_map()], FIGETBSZ, FIONREAD
+- * These ioctls are also handled by sys_ioctl():
+- * FIOCLEX, FIONCLEX, FIONBIO, FIOASYNC
+- * All other ioctls are passed to the filesystem.
+- *
+- * Refer to sys_ioctl() in fs/ioctl.c
+- * sys_ioctl() -> .
+- *
+- * PRE-CONDITIONS
+- * inode Pointer to inode that ioctl was issued on.
+- * filp Pointer to file that ioctl was issued on.
+- * cmd The ioctl command.
+- * arg The ioctl argument [can be interpreted as a
+- * user-space pointer if desired].
+- *
+- * POST-CONDITIONS
+- * <return> Success (>=0) or an error code (<=0) that
+- * sys_ioctl() will return.
+- *
+- * HISTORY
+- * July 1, 1997 - Andrew E. Mileski
+- * Written, tested, and released.
+- */
+ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+ {
+@@ -225,18 +190,6 @@ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+ return result;
+ }
+
+-/*
+- * udf_release_file
+- *
+- * PURPOSE
+- * Called when all references to the file are closed
+- *
+- * DESCRIPTION
+- * Discard prealloced blocks
+- *
+- * HISTORY
+- *
+- */
+ static int udf_release_file(struct inode *inode, struct file *filp)
+ {
+ if (filp->f_mode & FMODE_WRITE) {
+diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c
+index 8436031..eb9cfa2 100644
+--- a/fs/udf/ialloc.c
++++ b/fs/udf/ialloc.c
+@@ -21,7 +21,6 @@
+ #include "udfdecl.h"
+ #include <linux/fs.h>
+ #include <linux/quotaops.h>
+-#include <linux/udf_fs.h>
+ #include <linux/sched.h>
+ #include <linux/slab.h>
+
+@@ -47,11 +46,9 @@ void udf_free_inode(struct inode *inode)
+ struct logicalVolIntegrityDescImpUse *lvidiu =
+ udf_sb_lvidiu(sbi);
+ if (S_ISDIR(inode->i_mode))
+- lvidiu->numDirs =
+- cpu_to_le32(le32_to_cpu(lvidiu->numDirs) - 1);
++ le32_add_cpu(&lvidiu->numDirs, -1);
+ else
+- lvidiu->numFiles =
+- cpu_to_le32(le32_to_cpu(lvidiu->numFiles) - 1);
++ le32_add_cpu(&lvidiu->numFiles, -1);
+
+ mark_buffer_dirty(sbi->s_lvid_bh);
+ }
+@@ -105,11 +102,9 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err)
+ lvhd = (struct logicalVolHeaderDesc *)
+ (lvid->logicalVolContentsUse);
+ if (S_ISDIR(mode))
+- lvidiu->numDirs =
+- cpu_to_le32(le32_to_cpu(lvidiu->numDirs) + 1);
++ le32_add_cpu(&lvidiu->numDirs, 1);
+ else
+- lvidiu->numFiles =
+- cpu_to_le32(le32_to_cpu(lvidiu->numFiles) + 1);
++ le32_add_cpu(&lvidiu->numFiles, 1);
+ iinfo->i_unique = uniqueID = le64_to_cpu(lvhd->uniqueID);
+ if (!(++uniqueID & 0x00000000FFFFFFFFUL))
+ uniqueID += 16;
+diff --git a/fs/udf/inode.c b/fs/udf/inode.c
+index 24cfa55..6e74b11 100644
+--- a/fs/udf/inode.c
++++ b/fs/udf/inode.c
+@@ -37,6 +37,7 @@
+ #include <linux/buffer_head.h>
+ #include <linux/writeback.h>
+ #include <linux/slab.h>
++#include <linux/crc-itu-t.h>
+
+ #include "udf_i.h"
+ #include "udf_sb.h"
+@@ -66,22 +67,7 @@ static void udf_update_extents(struct inode *,
+ struct extent_position *);
+ static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int);
+
+-/*
+- * udf_delete_inode
+- *
+- * PURPOSE
+- * Clean-up before the specified inode is destroyed.
+- *
+- * DESCRIPTION
+- * This routine is called when the kernel destroys an inode structure
+- * ie. when iput() finds i_count == 0.
+- *
+- * HISTORY
+- * July 1, 1997 - Andrew E. Mileski
+- * Written, tested, and released.
+- *
+- * Called at the last iput() if i_nlink is zero.
+- */
++
+ void udf_delete_inode(struct inode *inode)
+ {
+ truncate_inode_pages(&inode->i_data, 0);
+@@ -323,9 +309,6 @@ static int udf_get_block(struct inode *inode, sector_t block,
+
+ lock_kernel();
+
+- if (block < 0)
+- goto abort_negative;
+-
+ iinfo = UDF_I(inode);
+ if (block == iinfo->i_next_alloc_block + 1) {
+ iinfo->i_next_alloc_block++;
+@@ -347,10 +330,6 @@ static int udf_get_block(struct inode *inode, sector_t block,
+ abort:
+ unlock_kernel();
+ return err;
+-
+-abort_negative:
+- udf_warning(inode->i_sb, "udf_get_block", "block < 0");
+- goto abort;
+ }
+
+ static struct buffer_head *udf_getblk(struct inode *inode, long block,
+@@ -1116,42 +1095,36 @@ static void __udf_read_inode(struct inode *inode)
+ fe = (struct fileEntry *)bh->b_data;
+
+ if (fe->icbTag.strategyType == cpu_to_le16(4096)) {
+- struct buffer_head *ibh = NULL, *nbh = NULL;
+- struct indirectEntry *ie;
++ struct buffer_head *ibh;
+
+ ibh = udf_read_ptagged(inode->i_sb, iinfo->i_location, 1,
+ &ident);
+- if (ident == TAG_IDENT_IE) {
+- if (ibh) {
+- kernel_lb_addr loc;
+- ie = (struct indirectEntry *)ibh->b_data;
+-
+- loc = lelb_to_cpu(ie->indirectICB.extLocation);
+-
+- if (ie->indirectICB.extLength &&
+- (nbh = udf_read_ptagged(inode->i_sb, loc, 0,
+- &ident))) {
+- if (ident == TAG_IDENT_FE ||
+- ident == TAG_IDENT_EFE) {
+- memcpy(&iinfo->i_location,
+- &loc,
+- sizeof(kernel_lb_addr));
+- brelse(bh);
+- brelse(ibh);
+- brelse(nbh);
+- __udf_read_inode(inode);
+- return;
+- } else {
+- brelse(nbh);
+- brelse(ibh);
+- }
+- } else {
++ if (ident == TAG_IDENT_IE && ibh) {
++ struct buffer_head *nbh = NULL;
++ kernel_lb_addr loc;
++ struct indirectEntry *ie;
++
++ ie = (struct indirectEntry *)ibh->b_data;
++ loc = lelb_to_cpu(ie->indirectICB.extLocation);
++
++ if (ie->indirectICB.extLength &&
++ (nbh = udf_read_ptagged(inode->i_sb, loc, 0,
++ &ident))) {
++ if (ident == TAG_IDENT_FE ||
++ ident == TAG_IDENT_EFE) {
++ memcpy(&iinfo->i_location,
++ &loc,
++ sizeof(kernel_lb_addr));
++ brelse(bh);
+ brelse(ibh);
++ brelse(nbh);
++ __udf_read_inode(inode);
++ return;
+ }
++ brelse(nbh);
+ }
+- } else {
+- brelse(ibh);
+ }
++ brelse(ibh);
+ } else if (fe->icbTag.strategyType != cpu_to_le16(4)) {
+ printk(KERN_ERR "udf: unsupported strategy type: %d\n",
+ le16_to_cpu(fe->icbTag.strategyType));
+@@ -1168,8 +1141,6 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
+ {
+ struct fileEntry *fe;
+ struct extendedFileEntry *efe;
+- time_t convtime;
+- long convtime_usec;
+ int offset;
+ struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
+ struct udf_inode_info *iinfo = UDF_I(inode);
+@@ -1257,29 +1228,15 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
+ inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
+ (inode->i_sb->s_blocksize_bits - 9);
+
+- if (udf_stamp_to_time(&convtime, &convtime_usec,
+- lets_to_cpu(fe->accessTime))) {
+- inode->i_atime.tv_sec = convtime;
+- inode->i_atime.tv_nsec = convtime_usec * 1000;
+- } else {
++ if (!udf_disk_stamp_to_time(&inode->i_atime, fe->accessTime))
+ inode->i_atime = sbi->s_record_time;
+- }
+
+- if (udf_stamp_to_time(&convtime, &convtime_usec,
+- lets_to_cpu(fe->modificationTime))) {
+- inode->i_mtime.tv_sec = convtime;
+- inode->i_mtime.tv_nsec = convtime_usec * 1000;
+- } else {
++ if (!udf_disk_stamp_to_time(&inode->i_mtime,
++ fe->modificationTime))
+ inode->i_mtime = sbi->s_record_time;
+- }
+
+- if (udf_stamp_to_time(&convtime, &convtime_usec,
+- lets_to_cpu(fe->attrTime))) {
+- inode->i_ctime.tv_sec = convtime;
+- inode->i_ctime.tv_nsec = convtime_usec * 1000;
+- } else {
++ if (!udf_disk_stamp_to_time(&inode->i_ctime, fe->attrTime))
+ inode->i_ctime = sbi->s_record_time;
+- }
+
+ iinfo->i_unique = le64_to_cpu(fe->uniqueID);
+ iinfo->i_lenEAttr = le32_to_cpu(fe->lengthExtendedAttr);
+@@ -1289,37 +1246,18 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
+ inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) <<
+ (inode->i_sb->s_blocksize_bits - 9);
+
+- if (udf_stamp_to_time(&convtime, &convtime_usec,
+- lets_to_cpu(efe->accessTime))) {
+- inode->i_atime.tv_sec = convtime;
+- inode->i_atime.tv_nsec = convtime_usec * 1000;
+- } else {
++ if (!udf_disk_stamp_to_time(&inode->i_atime, efe->accessTime))
+ inode->i_atime = sbi->s_record_time;
+- }
+
+- if (udf_stamp_to_time(&convtime, &convtime_usec,
+- lets_to_cpu(efe->modificationTime))) {
+- inode->i_mtime.tv_sec = convtime;
+- inode->i_mtime.tv_nsec = convtime_usec * 1000;
+- } else {
++ if (!udf_disk_stamp_to_time(&inode->i_mtime,
++ efe->modificationTime))
+ inode->i_mtime = sbi->s_record_time;
+- }
+
+- if (udf_stamp_to_time(&convtime, &convtime_usec,
+- lets_to_cpu(efe->createTime))) {
+- iinfo->i_crtime.tv_sec = convtime;
+- iinfo->i_crtime.tv_nsec = convtime_usec * 1000;
+- } else {
++ if (!udf_disk_stamp_to_time(&iinfo->i_crtime, efe->createTime))
+ iinfo->i_crtime = sbi->s_record_time;
+- }
+
+- if (udf_stamp_to_time(&convtime, &convtime_usec,
+- lets_to_cpu(efe->attrTime))) {
+- inode->i_ctime.tv_sec = convtime;
+- inode->i_ctime.tv_nsec = convtime_usec * 1000;
+- } else {
++ if (!udf_disk_stamp_to_time(&inode->i_ctime, efe->attrTime))
+ inode->i_ctime = sbi->s_record_time;
+- }
+
+ iinfo->i_unique = le64_to_cpu(efe->uniqueID);
+ iinfo->i_lenEAttr = le32_to_cpu(efe->lengthExtendedAttr);
+@@ -1338,6 +1276,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
+ case ICBTAG_FILE_TYPE_REALTIME:
+ case ICBTAG_FILE_TYPE_REGULAR:
+ case ICBTAG_FILE_TYPE_UNDEF:
++ case ICBTAG_FILE_TYPE_VAT20:
+ if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
+ inode->i_data.a_ops = &udf_adinicb_aops;
+ else
+@@ -1363,6 +1302,15 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
+ inode->i_op = &page_symlink_inode_operations;
+ inode->i_mode = S_IFLNK | S_IRWXUGO;
+ break;
++ case ICBTAG_FILE_TYPE_MAIN:
++ udf_debug("METADATA FILE-----\n");
++ break;
++ case ICBTAG_FILE_TYPE_MIRROR:
++ udf_debug("METADATA MIRROR FILE-----\n");
++ break;
++ case ICBTAG_FILE_TYPE_BITMAP:
++ udf_debug("METADATA BITMAP FILE-----\n");
++ break;
+ default:
+ printk(KERN_ERR "udf: udf_fill_inode(ino %ld) failed unknown "
+ "file type=%d\n", inode->i_ino,
+@@ -1416,21 +1364,6 @@ static mode_t udf_convert_permissions(struct fileEntry *fe)
+ return mode;
+ }
+
+-/*
+- * udf_write_inode
+- *
+- * PURPOSE
+- * Write out the specified inode.
+- *
+- * DESCRIPTION
+- * This routine is called whenever an inode is synced.
+- * Currently this routine is just a placeholder.
+- *
+- * HISTORY
+- * July 1, 1997 - Andrew E. Mileski
+- * Written, tested, and released.
+- */
+-
+ int udf_write_inode(struct inode *inode, int sync)
+ {
+ int ret;
+@@ -1455,7 +1388,6 @@ static int udf_update_inode(struct inode *inode, int do_sync)
+ uint32_t udfperms;
+ uint16_t icbflags;
+ uint16_t crclen;
+- kernel_timestamp cpu_time;
+ int err = 0;
+ struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
+ unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
+@@ -1488,9 +1420,9 @@ static int udf_update_inode(struct inode *inode, int do_sync)
+ iinfo->i_location.
+ logicalBlockNum);
+ use->descTag.descCRCLength = cpu_to_le16(crclen);
+- use->descTag.descCRC = cpu_to_le16(udf_crc((char *)use +
+- sizeof(tag), crclen,
+- 0));
++ use->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)use +
++ sizeof(tag),
++ crclen));
+ use->descTag.tagChecksum = udf_tag_checksum(&use->descTag);
+
+ mark_buffer_dirty(bh);
+@@ -1558,12 +1490,9 @@ static int udf_update_inode(struct inode *inode, int do_sync)
+ (inode->i_blocks + (1 << (blocksize_bits - 9)) - 1) >>
+ (blocksize_bits - 9));
+
+- if (udf_time_to_stamp(&cpu_time, inode->i_atime))
+- fe->accessTime = cpu_to_lets(cpu_time);
+- if (udf_time_to_stamp(&cpu_time, inode->i_mtime))
+- fe->modificationTime = cpu_to_lets(cpu_time);
+- if (udf_time_to_stamp(&cpu_time, inode->i_ctime))
+- fe->attrTime = cpu_to_lets(cpu_time);
++ udf_time_to_disk_stamp(&fe->accessTime, inode->i_atime);
++ udf_time_to_disk_stamp(&fe->modificationTime, inode->i_mtime);
++ udf_time_to_disk_stamp(&fe->attrTime, inode->i_ctime);
+ memset(&(fe->impIdent), 0, sizeof(regid));
+ strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER);
+ fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
+@@ -1598,14 +1527,10 @@ static int udf_update_inode(struct inode *inode, int do_sync)
+ iinfo->i_crtime.tv_nsec > inode->i_ctime.tv_nsec))
+ iinfo->i_crtime = inode->i_ctime;
+
+- if (udf_time_to_stamp(&cpu_time, inode->i_atime))
+- efe->accessTime = cpu_to_lets(cpu_time);
+- if (udf_time_to_stamp(&cpu_time, inode->i_mtime))
+- efe->modificationTime = cpu_to_lets(cpu_time);
+- if (udf_time_to_stamp(&cpu_time, iinfo->i_crtime))
+- efe->createTime = cpu_to_lets(cpu_time);
+- if (udf_time_to_stamp(&cpu_time, inode->i_ctime))
+- efe->attrTime = cpu_to_lets(cpu_time);
++ udf_time_to_disk_stamp(&efe->accessTime, inode->i_atime);
++ udf_time_to_disk_stamp(&efe->modificationTime, inode->i_mtime);
++ udf_time_to_disk_stamp(&efe->createTime, iinfo->i_crtime);
++ udf_time_to_disk_stamp(&efe->attrTime, inode->i_ctime);
+
+ memset(&(efe->impIdent), 0, sizeof(regid));
+ strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER);
+@@ -1660,8 +1585,8 @@ static int udf_update_inode(struct inode *inode, int do_sync)
+ crclen += iinfo->i_lenEAttr + iinfo->i_lenAlloc -
+ sizeof(tag);
+ fe->descTag.descCRCLength = cpu_to_le16(crclen);
+- fe->descTag.descCRC = cpu_to_le16(udf_crc((char *)fe + sizeof(tag),
+- crclen, 0));
++ fe->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)fe + sizeof(tag),
++ crclen));
+ fe->descTag.tagChecksum = udf_tag_checksum(&fe->descTag);
+
+ /* write the data blocks */
+@@ -1778,9 +1703,7 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos,
+
+ if (epos->bh) {
+ aed = (struct allocExtDesc *)epos->bh->b_data;
+- aed->lengthAllocDescs =
+- cpu_to_le32(le32_to_cpu(
+- aed->lengthAllocDescs) + adsize);
++ le32_add_cpu(&aed->lengthAllocDescs, adsize);
+ } else {
+ iinfo->i_lenAlloc += adsize;
+ mark_inode_dirty(inode);
+@@ -1830,9 +1753,7 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos,
+ mark_inode_dirty(inode);
+ } else {
+ aed = (struct allocExtDesc *)epos->bh->b_data;
+- aed->lengthAllocDescs =
+- cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) +
+- adsize);
++ le32_add_cpu(&aed->lengthAllocDescs, adsize);
+ if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
+ UDF_SB(inode->i_sb)->s_udfrev >= 0x0201)
+ udf_update_tag(epos->bh->b_data,
+@@ -2046,9 +1967,7 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos,
+ mark_inode_dirty(inode);
+ } else {
+ aed = (struct allocExtDesc *)oepos.bh->b_data;
+- aed->lengthAllocDescs =
+- cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) -
+- (2 * adsize));
++ le32_add_cpu(&aed->lengthAllocDescs, -(2 * adsize));
+ if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
+ UDF_SB(inode->i_sb)->s_udfrev >= 0x0201)
+ udf_update_tag(oepos.bh->b_data,
+@@ -2065,9 +1984,7 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos,
+ mark_inode_dirty(inode);
+ } else {
+ aed = (struct allocExtDesc *)oepos.bh->b_data;
+- aed->lengthAllocDescs =
+- cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) -
+- adsize);
++ le32_add_cpu(&aed->lengthAllocDescs, -adsize);
+ if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
+ UDF_SB(inode->i_sb)->s_udfrev >= 0x0201)
+ udf_update_tag(oepos.bh->b_data,
+@@ -2095,11 +2012,6 @@ int8_t inode_bmap(struct inode *inode, sector_t block,
+ int8_t etype;
+ struct udf_inode_info *iinfo;
+
+- if (block < 0) {
+- printk(KERN_ERR "udf: inode_bmap: block < 0\n");
+- return -1;
+- }
+-
+ iinfo = UDF_I(inode);
+ pos->offset = 0;
+ pos->block = iinfo->i_location;
+diff --git a/fs/udf/lowlevel.c b/fs/udf/lowlevel.c
+index 579bae7..703843f 100644
+--- a/fs/udf/lowlevel.c
++++ b/fs/udf/lowlevel.c
+@@ -23,7 +23,6 @@
+ #include <linux/cdrom.h>
+ #include <asm/uaccess.h>
+
+-#include <linux/udf_fs.h>
+ #include "udf_sb.h"
+
+ unsigned int udf_get_last_session(struct super_block *sb)
+diff --git a/fs/udf/misc.c b/fs/udf/misc.c
+index a1d6da0..84bf0fd 100644
+--- a/fs/udf/misc.c
++++ b/fs/udf/misc.c
+@@ -23,8 +23,8 @@
+
+ #include <linux/fs.h>
+ #include <linux/string.h>
+-#include <linux/udf_fs.h>
+ #include <linux/buffer_head.h>
++#include <linux/crc-itu-t.h>
+
+ #include "udf_i.h"
+ #include "udf_sb.h"
+@@ -136,8 +136,8 @@ struct genericFormat *udf_add_extendedattr(struct inode *inode, uint32_t size,
+ /* rewrite CRC + checksum of eahd */
+ crclen = sizeof(struct extendedAttrHeaderDesc) - sizeof(tag);
+ eahd->descTag.descCRCLength = cpu_to_le16(crclen);
+- eahd->descTag.descCRC = cpu_to_le16(udf_crc((char *)eahd +
+- sizeof(tag), crclen, 0));
++ eahd->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)eahd +
++ sizeof(tag), crclen));
+ eahd->descTag.tagChecksum = udf_tag_checksum(&eahd->descTag);
+ iinfo->i_lenEAttr += size;
+ return (struct genericFormat *)&ea[offset];
+@@ -204,16 +204,15 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
+ {
+ tag *tag_p;
+ struct buffer_head *bh = NULL;
+- struct udf_sb_info *sbi = UDF_SB(sb);
+
+ /* Read the block */
+ if (block == 0xFFFFFFFF)
+ return NULL;
+
+- bh = udf_tread(sb, block + sbi->s_session);
++ bh = udf_tread(sb, block);
+ if (!bh) {
+ udf_debug("block=%d, location=%d: read failed\n",
+- block + sbi->s_session, location);
++ block, location);
+ return NULL;
+ }
+
+@@ -223,8 +222,7 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
+
+ if (location != le32_to_cpu(tag_p->tagLocation)) {
+ udf_debug("location mismatch block %u, tag %u != %u\n",
+- block + sbi->s_session,
+- le32_to_cpu(tag_p->tagLocation), location);
++ block, le32_to_cpu(tag_p->tagLocation), location);
+ goto error_out;
+ }
+
+@@ -244,13 +242,13 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
+
+ /* Verify the descriptor CRC */
+ if (le16_to_cpu(tag_p->descCRCLength) + sizeof(tag) > sb->s_blocksize ||
+- le16_to_cpu(tag_p->descCRC) == udf_crc(bh->b_data + sizeof(tag),
+- le16_to_cpu(tag_p->descCRCLength), 0))
++ le16_to_cpu(tag_p->descCRC) == crc_itu_t(0,
++ bh->b_data + sizeof(tag),
++ le16_to_cpu(tag_p->descCRCLength)))
+ return bh;
+
+- udf_debug("Crc failure block %d: crc = %d, crclen = %d\n",
+- block + sbi->s_session, le16_to_cpu(tag_p->descCRC),
+- le16_to_cpu(tag_p->descCRCLength));
++ udf_debug("Crc failure block %d: crc = %d, crclen = %d\n", block,
++ le16_to_cpu(tag_p->descCRC), le16_to_cpu(tag_p->descCRCLength));
+
+ error_out:
+ brelse(bh);
+@@ -270,7 +268,7 @@ void udf_update_tag(char *data, int length)
+ length -= sizeof(tag);
+
+ tptr->descCRCLength = cpu_to_le16(length);
+- tptr->descCRC = cpu_to_le16(udf_crc(data + sizeof(tag), length, 0));
++ tptr->descCRC = cpu_to_le16(crc_itu_t(0, data + sizeof(tag), length));
+ tptr->tagChecksum = udf_tag_checksum(tptr);
+ }
+
+diff --git a/fs/udf/namei.c b/fs/udf/namei.c
+index 112a5fb..ba5537d 100644
+--- a/fs/udf/namei.c
++++ b/fs/udf/namei.c
+@@ -31,6 +31,7 @@
+ #include <linux/smp_lock.h>
+ #include <linux/buffer_head.h>
+ #include <linux/sched.h>
++#include <linux/crc-itu-t.h>
+
+ static inline int udf_match(int len1, const char *name1, int len2,
+ const char *name2)
+@@ -97,25 +98,23 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
+ memset(fibh->ebh->b_data, 0x00, padlen + offset);
+ }
+
+- crc = udf_crc((uint8_t *)cfi + sizeof(tag),
+- sizeof(struct fileIdentDesc) - sizeof(tag), 0);
++ crc = crc_itu_t(0, (uint8_t *)cfi + sizeof(tag),
++ sizeof(struct fileIdentDesc) - sizeof(tag));
+
+ if (fibh->sbh == fibh->ebh) {
+- crc = udf_crc((uint8_t *)sfi->impUse,
++ crc = crc_itu_t(crc, (uint8_t *)sfi->impUse,
+ crclen + sizeof(tag) -
+- sizeof(struct fileIdentDesc), crc);
++ sizeof(struct fileIdentDesc));
+ } else if (sizeof(struct fileIdentDesc) >= -fibh->soffset) {
+- crc = udf_crc(fibh->ebh->b_data +
++ crc = crc_itu_t(crc, fibh->ebh->b_data +
+ sizeof(struct fileIdentDesc) +
+ fibh->soffset,
+ crclen + sizeof(tag) -
+- sizeof(struct fileIdentDesc),
+- crc);
++ sizeof(struct fileIdentDesc));
+ } else {
+- crc = udf_crc((uint8_t *)sfi->impUse,
+- -fibh->soffset - sizeof(struct fileIdentDesc),
+- crc);
+- crc = udf_crc(fibh->ebh->b_data, fibh->eoffset, crc);
++ crc = crc_itu_t(crc, (uint8_t *)sfi->impUse,
++ -fibh->soffset - sizeof(struct fileIdentDesc));
++ crc = crc_itu_t(crc, fibh->ebh->b_data, fibh->eoffset);
+ }
+
+ cfi->descTag.descCRC = cpu_to_le16(crc);
+@@ -149,7 +148,7 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
+ struct fileIdentDesc *fi = NULL;
+ loff_t f_pos;
+ int block, flen;
+- char fname[UDF_NAME_LEN];
++ char *fname = NULL;
+ char *nameptr;
+ uint8_t lfi;
+ uint16_t liu;
+@@ -163,12 +162,12 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
+ size = udf_ext0_offset(dir) + dir->i_size;
+ f_pos = udf_ext0_offset(dir);
+
++ fibh->sbh = fibh->ebh = NULL;
+ fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
+- if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
+- fibh->sbh = fibh->ebh = NULL;
+- else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits,
+- &epos, &eloc, &elen, &offset) ==
+- (EXT_RECORDED_ALLOCATED >> 30)) {
++ if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
++ if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos,
++ &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30))
++ goto out_err;
+ block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
+ if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
+ if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
+@@ -179,25 +178,19 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
+ offset = 0;
+
+ fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
+- if (!fibh->sbh) {
+- brelse(epos.bh);
+- return NULL;
+- }
+- } else {
+- brelse(epos.bh);
+- return NULL;
++ if (!fibh->sbh)
++ goto out_err;
+ }
+
++ fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
++ if (!fname)
++ goto out_err;
++
+ while (f_pos < size) {
+ fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc,
+ &elen, &offset);
+- if (!fi) {
+- if (fibh->sbh != fibh->ebh)
+- brelse(fibh->ebh);
+- brelse(fibh->sbh);
+- brelse(epos.bh);
+- return NULL;
+- }
++ if (!fi)
++ goto out_err;
+
+ liu = le16_to_cpu(cfi->lengthOfImpUse);
+ lfi = cfi->lengthFileIdent;
+@@ -237,53 +230,22 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
+
+ flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
+ if (flen && udf_match(flen, fname, dentry->d_name.len,
+- dentry->d_name.name)) {
+- brelse(epos.bh);
+- return fi;
+- }
++ dentry->d_name.name))
++ goto out_ok;
+ }
+
++out_err:
++ fi = NULL;
+ if (fibh->sbh != fibh->ebh)
+ brelse(fibh->ebh);
+ brelse(fibh->sbh);
++out_ok:
+ brelse(epos.bh);
++ kfree(fname);
+
+- return NULL;
++ return fi;
+ }
+
+-/*
+- * udf_lookup
+- *
+- * PURPOSE
+- * Look-up the inode for a given name.
+- *
+- * DESCRIPTION
+- * Required - lookup_dentry() will return -ENOTDIR if this routine is not
+- * available for a directory. The filesystem is useless if this routine is
+- * not available for at least the filesystem's root directory.
+- *
+- * This routine is passed an incomplete dentry - it must be completed by
+- * calling d_add(dentry, inode). If the name does not exist, then the
+- * specified inode must be set to null. An error should only be returned
+- * when the lookup fails for a reason other than the name not existing.
+- * Note that the directory inode semaphore is held during the call.
+- *
+- * Refer to lookup_dentry() in fs/namei.c
+- * lookup_dentry() -> lookup() -> real_lookup() -> .
+- *
+- * PRE-CONDITIONS
+- * dir Pointer to inode of parent directory.
+- * dentry Pointer to dentry to complete.
+- * nd Pointer to lookup nameidata
+- *
+- * POST-CONDITIONS
+- * <return> Zero on success.
+- *
+- * HISTORY
+- * July 1, 1997 - Andrew E. Mileski
+- * Written, tested, and released.
+- */
+-
+ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
+ struct nameidata *nd)
+ {
+@@ -336,11 +298,9 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
+ {
+ struct super_block *sb = dir->i_sb;
+ struct fileIdentDesc *fi = NULL;
+- char name[UDF_NAME_LEN], fname[UDF_NAME_LEN];
++ char *name = NULL;
+ int namelen;
+ loff_t f_pos;
+- int flen;
+- char *nameptr;
+ loff_t size = udf_ext0_offset(dir) + dir->i_size;
+ int nfidlen;
+ uint8_t lfi;
+@@ -352,16 +312,23 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
+ struct extent_position epos = {};
+ struct udf_inode_info *dinfo;
+
++ fibh->sbh = fibh->ebh = NULL;
++ name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
++ if (!name) {
++ *err = -ENOMEM;
++ goto out_err;
++ }
++
+ if (dentry) {
+ if (!dentry->d_name.len) {
+ *err = -EINVAL;
+- return NULL;
++ goto out_err;
+ }
+ namelen = udf_put_filename(sb, dentry->d_name.name, name,
+ dentry->d_name.len);
+ if (!namelen) {
+ *err = -ENAMETOOLONG;
+- return NULL;
++ goto out_err;
+ }
+ } else {
+ namelen = 0;
+@@ -373,11 +340,14 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
+
+ fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
+ dinfo = UDF_I(dir);
+- if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
+- fibh->sbh = fibh->ebh = NULL;
+- else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits,
+- &epos, &eloc, &elen, &offset) ==
+- (EXT_RECORDED_ALLOCATED >> 30)) {
++ if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
++ if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos,
++ &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) {
++ block = udf_get_lb_pblock(dir->i_sb,
++ dinfo->i_location, 0);
++ fibh->soffset = fibh->eoffset = sb->s_blocksize;
++ goto add;
++ }
+ block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
+ if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
+ if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
+@@ -389,17 +359,11 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
+
+ fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
+ if (!fibh->sbh) {
+- brelse(epos.bh);
+ *err = -EIO;
+- return NULL;
++ goto out_err;
+ }
+
+ block = dinfo->i_location.logicalBlockNum;
+- } else {
+- block = udf_get_lb_pblock(dir->i_sb, dinfo->i_location, 0);
+- fibh->sbh = fibh->ebh = NULL;
+- fibh->soffset = fibh->eoffset = sb->s_blocksize;
+- goto add;
+ }
+
+ while (f_pos < size) {
+@@ -407,41 +371,16 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
+ &elen, &offset);
+
+ if (!fi) {
+- if (fibh->sbh != fibh->ebh)
+- brelse(fibh->ebh);
+- brelse(fibh->sbh);
+- brelse(epos.bh);
+ *err = -EIO;
+- return NULL;
++ goto out_err;
+ }
+
+ liu = le16_to_cpu(cfi->lengthOfImpUse);
+ lfi = cfi->lengthFileIdent;
+
+- if (fibh->sbh == fibh->ebh)
+- nameptr = fi->fileIdent + liu;
+- else {
+- int poffset; /* Unpaded ending offset */
+-
+- poffset = fibh->soffset + sizeof(struct fileIdentDesc) +
+- liu + lfi;
+-
+- if (poffset >= lfi)
+- nameptr = (char *)(fibh->ebh->b_data +
+- poffset - lfi);
+- else {
+- nameptr = fname;
+- memcpy(nameptr, fi->fileIdent + liu,
+- lfi - poffset);
+- memcpy(nameptr + lfi - poffset,
+- fibh->ebh->b_data, poffset);
+- }
+- }
+-
+ if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) {
+ if (((sizeof(struct fileIdentDesc) +
+ liu + lfi + 3) & ~3) == nfidlen) {
+- brelse(epos.bh);
+ cfi->descTag.tagSerialNum = cpu_to_le16(1);
+ cfi->fileVersionNum = cpu_to_le16(1);
+ cfi->fileCharacteristics = 0;
+@@ -449,27 +388,13 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
+ cfi->lengthOfImpUse = cpu_to_le16(0);
+ if (!udf_write_fi(dir, cfi, fi, fibh, NULL,
+ name))
+- return fi;
++ goto out_ok;
+ else {
+ *err = -EIO;
+- return NULL;
++ goto out_err;
+ }
+ }
+ }
+-
+- if (!lfi || !dentry)
+- continue;
+-
+- flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
+- if (flen && udf_match(flen, fname, dentry->d_name.len,
+- dentry->d_name.name)) {
+- if (fibh->sbh != fibh->ebh)
+- brelse(fibh->ebh);
+- brelse(fibh->sbh);
+- brelse(epos.bh);
+- *err = -EEXIST;
+- return NULL;
+- }
+ }
+
+ add:
+@@ -496,7 +421,7 @@ add:
+ fibh->sbh = fibh->ebh =
+ udf_expand_dir_adinicb(dir, &block, err);
+ if (!fibh->sbh)
+- return NULL;
++ goto out_err;
+ epos.block = dinfo->i_location;
+ epos.offset = udf_file_entry_alloc_offset(dir);
+ /* Load extent udf_expand_dir_adinicb() has created */
+@@ -537,11 +462,8 @@ add:
+ dir->i_sb->s_blocksize_bits);
+ fibh->ebh = udf_bread(dir,
+ f_pos >> dir->i_sb->s_blocksize_bits, 1, err);
+- if (!fibh->ebh) {
+- brelse(epos.bh);
+- brelse(fibh->sbh);
+- return NULL;
+- }
++ if (!fibh->ebh)
++ goto out_err;
+
+ if (!fibh->soffset) {
+ if (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
+@@ -572,20 +494,25 @@ add:
+ cfi->lengthFileIdent = namelen;
+ cfi->lengthOfImpUse = cpu_to_le16(0);
+ if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) {
+- brelse(epos.bh);
+ dir->i_size += nfidlen;
+ if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
+ dinfo->i_lenAlloc += nfidlen;
+ mark_inode_dirty(dir);
+- return fi;
++ goto out_ok;
+ } else {
+- brelse(epos.bh);
+- if (fibh->sbh != fibh->ebh)
+- brelse(fibh->ebh);
+- brelse(fibh->sbh);
+ *err = -EIO;
+- return NULL;
++ goto out_err;
+ }
++
++out_err:
++ fi = NULL;
++ if (fibh->sbh != fibh->ebh)
++ brelse(fibh->ebh);
++ brelse(fibh->sbh);
++out_ok:
++ brelse(epos.bh);
++ kfree(name);
++ return fi;
+ }
+
+ static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi,
+@@ -940,7 +867,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
+ char *ea;
+ int err;
+ int block;
+- char name[UDF_NAME_LEN];
++ char *name = NULL;
+ int namelen;
+ struct buffer_head *bh;
+ struct udf_inode_info *iinfo;
+@@ -950,6 +877,12 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
+ if (!inode)
+ goto out;
+
++ name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
++ if (!name) {
++ err = -ENOMEM;
++ goto out_no_entry;
++ }
++
+ iinfo = UDF_I(inode);
+ inode->i_mode = S_IFLNK | S_IRWXUGO;
+ inode->i_data.a_ops = &udf_symlink_aops;
+@@ -1089,6 +1022,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
+ err = 0;
+
+ out:
++ kfree(name);
+ unlock_kernel();
+ return err;
+
+diff --git a/fs/udf/partition.c b/fs/udf/partition.c
+index fc53334..63610f0 100644
+--- a/fs/udf/partition.c
++++ b/fs/udf/partition.c
+@@ -24,7 +24,6 @@
+
+ #include <linux/fs.h>
+ #include <linux/string.h>
+-#include <linux/udf_fs.h>
+ #include <linux/slab.h>
+ #include <linux/buffer_head.h>
+
+@@ -55,11 +54,10 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block,
+ struct udf_sb_info *sbi = UDF_SB(sb);
+ struct udf_part_map *map;
+ struct udf_virtual_data *vdata;
+- struct udf_inode_info *iinfo;
++ struct udf_inode_info *iinfo = UDF_I(sbi->s_vat_inode);
+
+ map = &sbi->s_partmaps[partition];
+ vdata = &map->s_type_specific.s_virtual;
+- index = (sb->s_blocksize - vdata->s_start_offset) / sizeof(uint32_t);
+
+ if (block > vdata->s_num_entries) {
+ udf_debug("Trying to access block beyond end of VAT "
+@@ -67,6 +65,12 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block,
+ return 0xFFFFFFFF;
+ }
+
++ if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
++ loc = le32_to_cpu(((__le32 *)(iinfo->i_ext.i_data +
++ vdata->s_start_offset))[block]);
++ goto translate;
++ }
++ index = (sb->s_blocksize - vdata->s_start_offset) / sizeof(uint32_t);
+ if (block >= index) {
+ block -= index;
+ newblock = 1 + (block / (sb->s_blocksize / sizeof(uint32_t)));
+@@ -89,7 +93,7 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block,
+
+ brelse(bh);
+
+- iinfo = UDF_I(sbi->s_vat_inode);
++translate:
+ if (iinfo->i_location.partitionReferenceNum == partition) {
+ udf_debug("recursive call to udf_get_pblock!\n");
+ return 0xFFFFFFFF;
+@@ -263,3 +267,58 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
+
+ return 0;
+ }
++
++static uint32_t udf_try_read_meta(struct inode *inode, uint32_t block,
++ uint16_t partition, uint32_t offset)
++{
++ struct super_block *sb = inode->i_sb;
++ struct udf_part_map *map;
++ kernel_lb_addr eloc;
++ uint32_t elen;
++ sector_t ext_offset;
++ struct extent_position epos = {};
++ uint32_t phyblock;
++
++ if (inode_bmap(inode, block, &epos, &eloc, &elen, &ext_offset) !=
++ (EXT_RECORDED_ALLOCATED >> 30))
++ phyblock = 0xFFFFFFFF;
++ else {
++ map = &UDF_SB(sb)->s_partmaps[partition];
++ /* map to sparable/physical partition desc */
++ phyblock = udf_get_pblock(sb, eloc.logicalBlockNum,
++ map->s_partition_num, ext_offset + offset);
++ }
++
++ brelse(epos.bh);
++ return phyblock;
++}
++
++uint32_t udf_get_pblock_meta25(struct super_block *sb, uint32_t block,
++ uint16_t partition, uint32_t offset)
++{
++ struct udf_sb_info *sbi = UDF_SB(sb);
++ struct udf_part_map *map;
++ struct udf_meta_data *mdata;
++ uint32_t retblk;
++ struct inode *inode;
++
++ udf_debug("READING from METADATA\n");
++
++ map = &sbi->s_partmaps[partition];
++ mdata = &map->s_type_specific.s_metadata;
++ inode = mdata->s_metadata_fe ? : mdata->s_mirror_fe;
++
++ /* We shouldn't mount such media... */
++ BUG_ON(!inode);
++ retblk = udf_try_read_meta(inode, block, partition, offset);
++ if (retblk == 0xFFFFFFFF) {
++ udf_warning(sb, __func__, "error reading from METADATA, "
++ "trying to read from MIRROR");
++ inode = mdata->s_mirror_fe;
++ if (!inode)
++ return 0xFFFFFFFF;
++ retblk = udf_try_read_meta(inode, block, partition, offset);
++ }
++
++ return retblk;
++}
+diff --git a/fs/udf/super.c b/fs/udf/super.c
+index f3ac4ab..b564fc1 100644
+--- a/fs/udf/super.c
++++ b/fs/udf/super.c
+@@ -55,9 +55,10 @@
+ #include <linux/errno.h>
+ #include <linux/mount.h>
+ #include <linux/seq_file.h>
++#include <linux/bitmap.h>
++#include <linux/crc-itu-t.h>
+ #include <asm/byteorder.h>
+
+-#include <linux/udf_fs.h>
+ #include "udf_sb.h"
+ #include "udf_i.h"
+
+@@ -84,22 +85,19 @@ static void udf_write_super(struct super_block *);
+ static int udf_remount_fs(struct super_block *, int *, char *);
+ static int udf_check_valid(struct super_block *, int, int);
+ static int udf_vrs(struct super_block *sb, int silent);
+-static int udf_load_partition(struct super_block *, kernel_lb_addr *);
+-static int udf_load_logicalvol(struct super_block *, struct buffer_head *,
+- kernel_lb_addr *);
+ static void udf_load_logicalvolint(struct super_block *, kernel_extent_ad);
+ static void udf_find_anchor(struct super_block *);
+ static int udf_find_fileset(struct super_block *, kernel_lb_addr *,
+ kernel_lb_addr *);
+-static void udf_load_pvoldesc(struct super_block *, struct buffer_head *);
+ static void udf_load_fileset(struct super_block *, struct buffer_head *,
+ kernel_lb_addr *);
+-static int udf_load_partdesc(struct super_block *, struct buffer_head *);
+ static void udf_open_lvid(struct super_block *);
+ static void udf_close_lvid(struct super_block *);
+ static unsigned int udf_count_free(struct super_block *);
+ static int udf_statfs(struct dentry *, struct kstatfs *);
+ static int udf_show_options(struct seq_file *, struct vfsmount *);
++static void udf_error(struct super_block *sb, const char *function,
++ const char *fmt, ...);
+
+ struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct udf_sb_info *sbi)
+ {
+@@ -587,48 +585,10 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options)
+ return 0;
+ }
+
+-/*
+- * udf_set_blocksize
+- *
+- * PURPOSE
+- * Set the block size to be used in all transfers.
+- *
+- * DESCRIPTION
+- * To allow room for a DMA transfer, it is best to guess big when unsure.
+- * This routine picks 2048 bytes as the blocksize when guessing. This
+- * should be adequate until devices with larger block sizes become common.
+- *
+- * Note that the Linux kernel can currently only deal with blocksizes of
+- * 512, 1024, 2048, 4096, and 8192 bytes.
+- *
+- * PRE-CONDITIONS
+- * sb Pointer to _locked_ superblock.
+- *
+- * POST-CONDITIONS
+- * sb->s_blocksize Blocksize.
+- * sb->s_blocksize_bits log2 of blocksize.
+- * <return> 0 Blocksize is valid.
+- * <return> 1 Blocksize is invalid.
+- *
+- * HISTORY
+- * July 1, 1997 - Andrew E. Mileski
+- * Written, tested, and released.
+- */
+-static int udf_set_blocksize(struct super_block *sb, int bsize)
+-{
+- if (!sb_min_blocksize(sb, bsize)) {
+- udf_debug("Bad block size (%d)\n", bsize);
+- printk(KERN_ERR "udf: bad block size (%d)\n", bsize);
+- return 0;
+- }
+-
+- return sb->s_blocksize;
+-}
+-
+ static int udf_vrs(struct super_block *sb, int silent)
+ {
+ struct volStructDesc *vsd = NULL;
+- int sector = 32768;
++ loff_t sector = 32768;
+ int sectorsize;
+ struct buffer_head *bh = NULL;
+ int iso9660 = 0;
+@@ -649,7 +609,8 @@ static int udf_vrs(struct super_block *sb, int silent)
+ sector += (sbi->s_session << sb->s_blocksize_bits);
+
+ udf_debug("Starting at sector %u (%ld byte sectors)\n",
+- (sector >> sb->s_blocksize_bits), sb->s_blocksize);
++ (unsigned int)(sector >> sb->s_blocksize_bits),
++ sb->s_blocksize);
+ /* Process the sequence (if applicable) */
+ for (; !nsr02 && !nsr03; sector += sectorsize) {
+ /* Read a block */
+@@ -719,162 +680,140 @@ static int udf_vrs(struct super_block *sb, int silent)
+ }
+
+ /*
+- * udf_find_anchor
+- *
+- * PURPOSE
+- * Find an anchor volume descriptor.
+- *
+- * PRE-CONDITIONS
+- * sb Pointer to _locked_ superblock.
+- * lastblock Last block on media.
+- *
+- * POST-CONDITIONS
+- * <return> 1 if not found, 0 if ok
+- *
+- * HISTORY
+- * July 1, 1997 - Andrew E. Mileski
+- * Written, tested, and released.
++ * Check whether there is an anchor block in the given block
+ */
+-static void udf_find_anchor(struct super_block *sb)
++static int udf_check_anchor_block(struct super_block *sb, sector_t block,
++ bool varconv)
+ {
+- int lastblock;
+ struct buffer_head *bh = NULL;
++ tag *t;
+ uint16_t ident;
+ uint32_t location;
+- int i;
+- struct udf_sb_info *sbi;
+
+- sbi = UDF_SB(sb);
+- lastblock = sbi->s_last_block;
++ if (varconv) {
++ if (udf_fixed_to_variable(block) >=
++ sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits)
++ return 0;
++ bh = sb_bread(sb, udf_fixed_to_variable(block));
++ }
++ else
++ bh = sb_bread(sb, block);
+
+- if (lastblock) {
+- int varlastblock = udf_variable_to_fixed(lastblock);
+- int last[] = { lastblock, lastblock - 2,
+- lastblock - 150, lastblock - 152,
+- varlastblock, varlastblock - 2,
+- varlastblock - 150, varlastblock - 152 };
+-
+- lastblock = 0;
+-
+- /* Search for an anchor volume descriptor pointer */
+-
+- /* according to spec, anchor is in either:
+- * block 256
+- * lastblock-256
+- * lastblock
+- * however, if the disc isn't closed, it could be 512 */
+-
+- for (i = 0; !lastblock && i < ARRAY_SIZE(last); i++) {
+- ident = location = 0;
+- if (last[i] >= 0) {
+- bh = sb_bread(sb, last[i]);
+- if (bh) {
+- tag *t = (tag *)bh->b_data;
+- ident = le16_to_cpu(t->tagIdent);
+- location = le32_to_cpu(t->tagLocation);
+- brelse(bh);
+- }
+- }
++ if (!bh)
++ return 0;
+
+- if (ident == TAG_IDENT_AVDP) {
+- if (location == last[i] - sbi->s_session) {
+- lastblock = last[i] - sbi->s_session;
+- sbi->s_anchor[0] = lastblock;
+- sbi->s_anchor[1] = lastblock - 256;
+- } else if (location ==
+- udf_variable_to_fixed(last[i]) -
+- sbi->s_session) {
+- UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
+- lastblock =
+- udf_variable_to_fixed(last[i]) -
+- sbi->s_session;
+- sbi->s_anchor[0] = lastblock;
+- sbi->s_anchor[1] = lastblock - 256 -
+- sbi->s_session;
+- } else {
+- udf_debug("Anchor found at block %d, "
+- "location mismatch %d.\n",
+- last[i], location);
+- }
+- } else if (ident == TAG_IDENT_FE ||
+- ident == TAG_IDENT_EFE) {
+- lastblock = last[i];
+- sbi->s_anchor[3] = 512;
+- } else {
+- ident = location = 0;
+- if (last[i] >= 256) {
+- bh = sb_bread(sb, last[i] - 256);
+- if (bh) {
+- tag *t = (tag *)bh->b_data;
+- ident = le16_to_cpu(
+- t->tagIdent);
+- location = le32_to_cpu(
+- t->tagLocation);
+- brelse(bh);
+- }
+- }
++ t = (tag *)bh->b_data;
++ ident = le16_to_cpu(t->tagIdent);
++ location = le32_to_cpu(t->tagLocation);
++ brelse(bh);
++ if (ident != TAG_IDENT_AVDP)
++ return 0;
++ return location == block;
++}
+
+- if (ident == TAG_IDENT_AVDP &&
+- location == last[i] - 256 -
+- sbi->s_session) {
+- lastblock = last[i];
+- sbi->s_anchor[1] = last[i] - 256;
+- } else {
+- ident = location = 0;
+- if (last[i] >= 312 + sbi->s_session) {
+- bh = sb_bread(sb,
+- last[i] - 312 -
+- sbi->s_session);
+- if (bh) {
+- tag *t = (tag *)
+- bh->b_data;
+- ident = le16_to_cpu(
+- t->tagIdent);
+- location = le32_to_cpu(
+- t->tagLocation);
+- brelse(bh);
+- }
+- }
++/* Search for an anchor volume descriptor pointer */
++static sector_t udf_scan_anchors(struct super_block *sb, bool varconv,
++ sector_t lastblock)
++{
++ sector_t last[6];
++ int i;
++ struct udf_sb_info *sbi = UDF_SB(sb);
+
+- if (ident == TAG_IDENT_AVDP &&
+- location == udf_variable_to_fixed(last[i]) - 256) {
+- UDF_SET_FLAG(sb,
+- UDF_FLAG_VARCONV);
+- lastblock = udf_variable_to_fixed(last[i]);
+- sbi->s_anchor[1] = lastblock - 256;
+- }
+- }
+- }
++ last[0] = lastblock;
++ last[1] = last[0] - 1;
++ last[2] = last[0] + 1;
++ last[3] = last[0] - 2;
++ last[4] = last[0] - 150;
++ last[5] = last[0] - 152;
++
++ /* according to spec, anchor is in either:
++ * block 256
++ * lastblock-256
++ * lastblock
++ * however, if the disc isn't closed, it could be 512 */
++
++ for (i = 0; i < ARRAY_SIZE(last); i++) {
++ if (last[i] < 0)
++ continue;
++ if (last[i] >= sb->s_bdev->bd_inode->i_size >>
++ sb->s_blocksize_bits)
++ continue;
++
++ if (udf_check_anchor_block(sb, last[i], varconv)) {
++ sbi->s_anchor[0] = last[i];
++ sbi->s_anchor[1] = last[i] - 256;
++ return last[i];
+ }
+- }
+
+- if (!lastblock) {
+- /* We haven't found the lastblock. check 312 */
+- bh = sb_bread(sb, 312 + sbi->s_session);
+- if (bh) {
+- tag *t = (tag *)bh->b_data;
+- ident = le16_to_cpu(t->tagIdent);
+- location = le32_to_cpu(t->tagLocation);
+- brelse(bh);
++ if (last[i] < 256)
++ continue;
+
+- if (ident == TAG_IDENT_AVDP && location == 256)
+- UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
++ if (udf_check_anchor_block(sb, last[i] - 256, varconv)) {
++ sbi->s_anchor[1] = last[i] - 256;
++ return last[i];
+ }
+ }
+
++ if (udf_check_anchor_block(sb, sbi->s_session + 256, varconv)) {
++ sbi->s_anchor[0] = sbi->s_session + 256;
++ return last[0];
++ }
++ if (udf_check_anchor_block(sb, sbi->s_session + 512, varconv)) {
++ sbi->s_anchor[0] = sbi->s_session + 512;
++ return last[0];
++ }
++ return 0;
++}
++
++/*
++ * Find an anchor volume descriptor. The function expects sbi->s_lastblock to
++ * be the last block on the media.
++ *
++ * Return 1 if not found, 0 if ok
++ *
++ */
++static void udf_find_anchor(struct super_block *sb)
++{
++ sector_t lastblock;
++ struct buffer_head *bh = NULL;
++ uint16_t ident;
++ int i;
++ struct udf_sb_info *sbi = UDF_SB(sb);
++
++ lastblock = udf_scan_anchors(sb, 0, sbi->s_last_block);
++ if (lastblock)
++ goto check_anchor;
++
++ /* No anchor found? Try VARCONV conversion of block numbers */
++ /* Firstly, we try to not convert number of the last block */
++ lastblock = udf_scan_anchors(sb, 1,
++ udf_variable_to_fixed(sbi->s_last_block));
++ if (lastblock) {
++ UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
++ goto check_anchor;
++ }
++
++ /* Secondly, we try with converted number of the last block */
++ lastblock = udf_scan_anchors(sb, 1, sbi->s_last_block);
++ if (lastblock)
++ UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
++
++check_anchor:
++ /*
++ * Check located anchors and the anchor block supplied via
++ * mount options
++ */
+ for (i = 0; i < ARRAY_SIZE(sbi->s_anchor); i++) {
+- if (sbi->s_anchor[i]) {
+- bh = udf_read_tagged(sb, sbi->s_anchor[i],
+- sbi->s_anchor[i], &ident);
+- if (!bh)
++ if (!sbi->s_anchor[i])
++ continue;
++ bh = udf_read_tagged(sb, sbi->s_anchor[i],
++ sbi->s_anchor[i], &ident);
++ if (!bh)
++ sbi->s_anchor[i] = 0;
++ else {
++ brelse(bh);
++ if (ident != TAG_IDENT_AVDP)
+ sbi->s_anchor[i] = 0;
+- else {
+- brelse(bh);
+- if ((ident != TAG_IDENT_AVDP) &&
+- (i || (ident != TAG_IDENT_FE &&
+- ident != TAG_IDENT_EFE)))
+- sbi->s_anchor[i] = 0;
+- }
+ }
+ }
+
+@@ -971,27 +910,30 @@ static int udf_find_fileset(struct super_block *sb,
+ return 1;
+ }
+
+-static void udf_load_pvoldesc(struct super_block *sb, struct buffer_head *bh)
++static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
+ {
+ struct primaryVolDesc *pvoldesc;
+- time_t recording;
+- long recording_usec;
+ struct ustr instr;
+ struct ustr outstr;
++ struct buffer_head *bh;
++ uint16_t ident;
++
++ bh = udf_read_tagged(sb, block, block, &ident);
++ if (!bh)
++ return 1;
++ BUG_ON(ident != TAG_IDENT_PVD);
+
+ pvoldesc = (struct primaryVolDesc *)bh->b_data;
+
+- if (udf_stamp_to_time(&recording, &recording_usec,
+- lets_to_cpu(pvoldesc->recordingDateAndTime))) {
+- kernel_timestamp ts;
+- ts = lets_to_cpu(pvoldesc->recordingDateAndTime);
+- udf_debug("recording time %ld/%ld, %04u/%02u/%02u"
++ if (udf_disk_stamp_to_time(&UDF_SB(sb)->s_record_time,
++ pvoldesc->recordingDateAndTime)) {
++#ifdef UDFFS_DEBUG
++ timestamp *ts = &pvoldesc->recordingDateAndTime;
++ udf_debug("recording time %04u/%02u/%02u"
+ " %02u:%02u (%x)\n",
+- recording, recording_usec,
+- ts.year, ts.month, ts.day, ts.hour,
+- ts.minute, ts.typeAndTimezone);
+- UDF_SB(sb)->s_record_time.tv_sec = recording;
+- UDF_SB(sb)->s_record_time.tv_nsec = recording_usec * 1000;
++ le16_to_cpu(ts->year), ts->month, ts->day, ts->hour,
++ ts->minute, le16_to_cpu(ts->typeAndTimezone));
++#endif
+ }
+
+ if (!udf_build_ustr(&instr, pvoldesc->volIdent, 32))
+@@ -1005,6 +947,104 @@ static void udf_load_pvoldesc(struct super_block *sb, struct buffer_head *bh)
+ if (!udf_build_ustr(&instr, pvoldesc->volSetIdent, 128))
+ if (udf_CS0toUTF8(&outstr, &instr))
+ udf_debug("volSetIdent[] = '%s'\n", outstr.u_name);
++
++ brelse(bh);
++ return 0;
++}
++
++static int udf_load_metadata_files(struct super_block *sb, int partition)
++{
++ struct udf_sb_info *sbi = UDF_SB(sb);
++ struct udf_part_map *map;
++ struct udf_meta_data *mdata;
++ kernel_lb_addr addr;
++ int fe_error = 0;
++
++ map = &sbi->s_partmaps[partition];
++ mdata = &map->s_type_specific.s_metadata;
++
++ /* metadata address */
++ addr.logicalBlockNum = mdata->s_meta_file_loc;
++ addr.partitionReferenceNum = map->s_partition_num;
++
++ udf_debug("Metadata file location: block = %d part = %d\n",
++ addr.logicalBlockNum, addr.partitionReferenceNum);
++
++ mdata->s_metadata_fe = udf_iget(sb, addr);
++
++ if (mdata->s_metadata_fe == NULL) {
++ udf_warning(sb, __func__, "metadata inode efe not found, "
++ "will try mirror inode.");
++ fe_error = 1;
++ } else if (UDF_I(mdata->s_metadata_fe)->i_alloc_type !=
++ ICBTAG_FLAG_AD_SHORT) {
++ udf_warning(sb, __func__, "metadata inode efe does not have "
++ "short allocation descriptors!");
++ fe_error = 1;
++ iput(mdata->s_metadata_fe);
++ mdata->s_metadata_fe = NULL;
++ }
++
++ /* mirror file entry */
++ addr.logicalBlockNum = mdata->s_mirror_file_loc;
++ addr.partitionReferenceNum = map->s_partition_num;
++
++ udf_debug("Mirror metadata file location: block = %d part = %d\n",
++ addr.logicalBlockNum, addr.partitionReferenceNum);
++
++ mdata->s_mirror_fe = udf_iget(sb, addr);
++
++ if (mdata->s_mirror_fe == NULL) {
++ if (fe_error) {
++ udf_error(sb, __func__, "mirror inode efe not found "
++ "and metadata inode is missing too, exiting...");
++ goto error_exit;
++ } else
++ udf_warning(sb, __func__, "mirror inode efe not found,"
++ " but metadata inode is OK");
++ } else if (UDF_I(mdata->s_mirror_fe)->i_alloc_type !=
++ ICBTAG_FLAG_AD_SHORT) {
++ udf_warning(sb, __func__, "mirror inode efe does not have "
++ "short allocation descriptors!");
++ iput(mdata->s_mirror_fe);
++ mdata->s_mirror_fe = NULL;
++ if (fe_error)
++ goto error_exit;
++ }
++
++ /*
++ * bitmap file entry
++ * Note:
++ * Load only if bitmap file location differs from 0xFFFFFFFF (DCN-5102)
++ */
++ if (mdata->s_bitmap_file_loc != 0xFFFFFFFF) {
++ addr.logicalBlockNum = mdata->s_bitmap_file_loc;
++ addr.partitionReferenceNum = map->s_partition_num;
++
++ udf_debug("Bitmap file location: block = %d part = %d\n",
++ addr.logicalBlockNum, addr.partitionReferenceNum);
++
++ mdata->s_bitmap_fe = udf_iget(sb, addr);
++
++ if (mdata->s_bitmap_fe == NULL) {
++ if (sb->s_flags & MS_RDONLY)
++ udf_warning(sb, __func__, "bitmap inode efe "
++ "not found but it's ok since the disc"
++ " is mounted read-only");
++ else {
++ udf_error(sb, __func__, "bitmap inode efe not "
++ "found and attempted read-write mount");
++ goto error_exit;
++ }
++ }
++ }
++
++ udf_debug("udf_load_metadata_files Ok\n");
++
++ return 0;
++
++error_exit:
++ return 1;
+ }
+
+ static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh,
+@@ -1025,10 +1065,9 @@ static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh,
+ int udf_compute_nr_groups(struct super_block *sb, u32 partition)
+ {
+ struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition];
+- return (map->s_partition_len +
+- (sizeof(struct spaceBitmapDesc) << 3) +
+- (sb->s_blocksize * 8) - 1) /
+- (sb->s_blocksize * 8);
++ return DIV_ROUND_UP(map->s_partition_len +
++ (sizeof(struct spaceBitmapDesc) << 3),
++ sb->s_blocksize * 8);
+ }
+
+ static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index)
+@@ -1059,134 +1098,241 @@ static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index)
+ return bitmap;
+ }
+
+-static int udf_load_partdesc(struct super_block *sb, struct buffer_head *bh)
++static int udf_fill_partdesc_info(struct super_block *sb,
++ struct partitionDesc *p, int p_index)
++{
++ struct udf_part_map *map;
++ struct udf_sb_info *sbi = UDF_SB(sb);
++ struct partitionHeaderDesc *phd;
++
++ map = &sbi->s_partmaps[p_index];
++
++ map->s_partition_len = le32_to_cpu(p->partitionLength); /* blocks */
++ map->s_partition_root = le32_to_cpu(p->partitionStartingLocation);
++
++ if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_READ_ONLY))
++ map->s_partition_flags |= UDF_PART_FLAG_READ_ONLY;
++ if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_WRITE_ONCE))
++ map->s_partition_flags |= UDF_PART_FLAG_WRITE_ONCE;
++ if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_REWRITABLE))
++ map->s_partition_flags |= UDF_PART_FLAG_REWRITABLE;
++ if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_OVERWRITABLE))
++ map->s_partition_flags |= UDF_PART_FLAG_OVERWRITABLE;
++
++ udf_debug("Partition (%d type %x) starts at physical %d, "
++ "block length %d\n", p_index,
++ map->s_partition_type, map->s_partition_root,
++ map->s_partition_len);
++
++ if (strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR02) &&
++ strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR03))
++ return 0;
++
++ phd = (struct partitionHeaderDesc *)p->partitionContentsUse;
++ if (phd->unallocSpaceTable.extLength) {
++ kernel_lb_addr loc = {
++ .logicalBlockNum = le32_to_cpu(
++ phd->unallocSpaceTable.extPosition),
++ .partitionReferenceNum = p_index,
++ };
++
++ map->s_uspace.s_table = udf_iget(sb, loc);
++ if (!map->s_uspace.s_table) {
++ udf_debug("cannot load unallocSpaceTable (part %d)\n",
++ p_index);
++ return 1;
++ }
++ map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_TABLE;
++ udf_debug("unallocSpaceTable (part %d) @ %ld\n",
++ p_index, map->s_uspace.s_table->i_ino);
++ }
++
++ if (phd->unallocSpaceBitmap.extLength) {
++ struct udf_bitmap *bitmap = udf_sb_alloc_bitmap(sb, p_index);
++ if (!bitmap)
++ return 1;
++ map->s_uspace.s_bitmap = bitmap;
++ bitmap->s_extLength = le32_to_cpu(
++ phd->unallocSpaceBitmap.extLength);
++ bitmap->s_extPosition = le32_to_cpu(
++ phd->unallocSpaceBitmap.extPosition);
++ map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_BITMAP;
++ udf_debug("unallocSpaceBitmap (part %d) @ %d\n", p_index,
++ bitmap->s_extPosition);
++ }
++
++ if (phd->partitionIntegrityTable.extLength)
++ udf_debug("partitionIntegrityTable (part %d)\n", p_index);
++
++ if (phd->freedSpaceTable.extLength) {
++ kernel_lb_addr loc = {
++ .logicalBlockNum = le32_to_cpu(
++ phd->freedSpaceTable.extPosition),
++ .partitionReferenceNum = p_index,
++ };
++
++ map->s_fspace.s_table = udf_iget(sb, loc);
++ if (!map->s_fspace.s_table) {
++ udf_debug("cannot load freedSpaceTable (part %d)\n",
++ p_index);
++ return 1;
++ }
++
++ map->s_partition_flags |= UDF_PART_FLAG_FREED_TABLE;
++ udf_debug("freedSpaceTable (part %d) @ %ld\n",
++ p_index, map->s_fspace.s_table->i_ino);
++ }
++
++ if (phd->freedSpaceBitmap.extLength) {
++ struct udf_bitmap *bitmap = udf_sb_alloc_bitmap(sb, p_index);
++ if (!bitmap)
++ return 1;
++ map->s_fspace.s_bitmap = bitmap;
++ bitmap->s_extLength = le32_to_cpu(
++ phd->freedSpaceBitmap.extLength);
++ bitmap->s_extPosition = le32_to_cpu(
++ phd->freedSpaceBitmap.extPosition);
++ map->s_partition_flags |= UDF_PART_FLAG_FREED_BITMAP;
++ udf_debug("freedSpaceBitmap (part %d) @ %d\n", p_index,
++ bitmap->s_extPosition);
++ }
++ return 0;
++}
++
++static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)
++{
++ struct udf_sb_info *sbi = UDF_SB(sb);
++ struct udf_part_map *map = &sbi->s_partmaps[p_index];
++ kernel_lb_addr ino;
++ struct buffer_head *bh = NULL;
++ struct udf_inode_info *vati;
++ uint32_t pos;
++ struct virtualAllocationTable20 *vat20;
++
++ /* VAT file entry is in the last recorded block */
++ ino.partitionReferenceNum = type1_index;
++ ino.logicalBlockNum = sbi->s_last_block - map->s_partition_root;
++ sbi->s_vat_inode = udf_iget(sb, ino);
++ if (!sbi->s_vat_inode)
++ return 1;
++
++ if (map->s_partition_type == UDF_VIRTUAL_MAP15) {
++ map->s_type_specific.s_virtual.s_start_offset = 0;
++ map->s_type_specific.s_virtual.s_num_entries =
++ (sbi->s_vat_inode->i_size - 36) >> 2;
++ } else if (map->s_partition_type == UDF_VIRTUAL_MAP20) {
++ vati = UDF_I(sbi->s_vat_inode);
++ if (vati->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
++ pos = udf_block_map(sbi->s_vat_inode, 0);
++ bh = sb_bread(sb, pos);
++ if (!bh)
++ return 1;
++ vat20 = (struct virtualAllocationTable20 *)bh->b_data;
++ } else {
++ vat20 = (struct virtualAllocationTable20 *)
++ vati->i_ext.i_data;
++ }
++
++ map->s_type_specific.s_virtual.s_start_offset =
++ le16_to_cpu(vat20->lengthHeader);
++ map->s_type_specific.s_virtual.s_num_entries =
++ (sbi->s_vat_inode->i_size -
++ map->s_type_specific.s_virtual.
++ s_start_offset) >> 2;
++ brelse(bh);
++ }
++ return 0;
++}
++
++static int udf_load_partdesc(struct super_block *sb, sector_t block)
+ {
++ struct buffer_head *bh;
+ struct partitionDesc *p;
+- int i;
+ struct udf_part_map *map;
+- struct udf_sb_info *sbi;
++ struct udf_sb_info *sbi = UDF_SB(sb);
++ int i, type1_idx;
++ uint16_t partitionNumber;
++ uint16_t ident;
++ int ret = 0;
++
++ bh = udf_read_tagged(sb, block, block, &ident);
++ if (!bh)
++ return 1;
++ if (ident != TAG_IDENT_PD)
++ goto out_bh;
+
+ p = (struct partitionDesc *)bh->b_data;
+- sbi = UDF_SB(sb);
++ partitionNumber = le16_to_cpu(p->partitionNumber);
+
++ /* First scan for TYPE1, SPARABLE and METADATA partitions */
+ for (i = 0; i < sbi->s_partitions; i++) {
+ map = &sbi->s_partmaps[i];
+ udf_debug("Searching map: (%d == %d)\n",
+- map->s_partition_num,
+- le16_to_cpu(p->partitionNumber));
+- if (map->s_partition_num ==
+- le16_to_cpu(p->partitionNumber)) {
+- map->s_partition_len =
+- le32_to_cpu(p->partitionLength); /* blocks */
+- map->s_partition_root =
+- le32_to_cpu(p->partitionStartingLocation);
+- if (p->accessType ==
+- cpu_to_le32(PD_ACCESS_TYPE_READ_ONLY))
+- map->s_partition_flags |=
+- UDF_PART_FLAG_READ_ONLY;
+- if (p->accessType ==
+- cpu_to_le32(PD_ACCESS_TYPE_WRITE_ONCE))
+- map->s_partition_flags |=
+- UDF_PART_FLAG_WRITE_ONCE;
+- if (p->accessType ==
+- cpu_to_le32(PD_ACCESS_TYPE_REWRITABLE))
+- map->s_partition_flags |=
+- UDF_PART_FLAG_REWRITABLE;
+- if (p->accessType ==
+- cpu_to_le32(PD_ACCESS_TYPE_OVERWRITABLE))
+- map->s_partition_flags |=
+- UDF_PART_FLAG_OVERWRITABLE;
+-
+- if (!strcmp(p->partitionContents.ident,
+- PD_PARTITION_CONTENTS_NSR02) ||
+- !strcmp(p->partitionContents.ident,
+- PD_PARTITION_CONTENTS_NSR03)) {
+- struct partitionHeaderDesc *phd;
+-
+- phd = (struct partitionHeaderDesc *)
+- (p->partitionContentsUse);
+- if (phd->unallocSpaceTable.extLength) {
+- kernel_lb_addr loc = {
+- .logicalBlockNum = le32_to_cpu(phd->unallocSpaceTable.extPosition),
+- .partitionReferenceNum = i,
+- };
+-
+- map->s_uspace.s_table =
+- udf_iget(sb, loc);
+- if (!map->s_uspace.s_table) {
+- udf_debug("cannot load unallocSpaceTable (part %d)\n", i);
+- return 1;
+- }
+- map->s_partition_flags |=
+- UDF_PART_FLAG_UNALLOC_TABLE;
+- udf_debug("unallocSpaceTable (part %d) @ %ld\n",
+- i, map->s_uspace.s_table->i_ino);
+- }
+- if (phd->unallocSpaceBitmap.extLength) {
+- struct udf_bitmap *bitmap =
+- udf_sb_alloc_bitmap(sb, i);
+- map->s_uspace.s_bitmap = bitmap;
+- if (bitmap != NULL) {
+- bitmap->s_extLength =
+- le32_to_cpu(phd->unallocSpaceBitmap.extLength);
+- bitmap->s_extPosition =
+- le32_to_cpu(phd->unallocSpaceBitmap.extPosition);
+- map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_BITMAP;
+- udf_debug("unallocSpaceBitmap (part %d) @ %d\n",
+- i, bitmap->s_extPosition);
+- }
+- }
+- if (phd->partitionIntegrityTable.extLength)
+- udf_debug("partitionIntegrityTable (part %d)\n", i);
+- if (phd->freedSpaceTable.extLength) {
+- kernel_lb_addr loc = {
+- .logicalBlockNum = le32_to_cpu(phd->freedSpaceTable.extPosition),
+- .partitionReferenceNum = i,
+- };
+-
+- map->s_fspace.s_table =
+- udf_iget(sb, loc);
+- if (!map->s_fspace.s_table) {
+- udf_debug("cannot load freedSpaceTable (part %d)\n", i);
+- return 1;
+- }
+- map->s_partition_flags |=
+- UDF_PART_FLAG_FREED_TABLE;
+- udf_debug("freedSpaceTable (part %d) @ %ld\n",
+- i, map->s_fspace.s_table->i_ino);
+- }
+- if (phd->freedSpaceBitmap.extLength) {
+- struct udf_bitmap *bitmap =
+- udf_sb_alloc_bitmap(sb, i);
+- map->s_fspace.s_bitmap = bitmap;
+- if (bitmap != NULL) {
+- bitmap->s_extLength =
+- le32_to_cpu(phd->freedSpaceBitmap.extLength);
+- bitmap->s_extPosition =
+- le32_to_cpu(phd->freedSpaceBitmap.extPosition);
+- map->s_partition_flags |= UDF_PART_FLAG_FREED_BITMAP;
+- udf_debug("freedSpaceBitmap (part %d) @ %d\n",
+- i, bitmap->s_extPosition);
+- }
+- }
+- }
++ map->s_partition_num, partitionNumber);
++ if (map->s_partition_num == partitionNumber &&
++ (map->s_partition_type == UDF_TYPE1_MAP15 ||
++ map->s_partition_type == UDF_SPARABLE_MAP15))
+ break;
+- }
+ }
+- if (i == sbi->s_partitions)
++
++ if (i >= sbi->s_partitions) {
+ udf_debug("Partition (%d) not found in partition map\n",
+- le16_to_cpu(p->partitionNumber));
+- else
+- udf_debug("Partition (%d:%d type %x) starts at physical %d, "
+- "block length %d\n",
+- le16_to_cpu(p->partitionNumber), i,
+- map->s_partition_type,
+- map->s_partition_root,
+- map->s_partition_len);
+- return 0;
++ partitionNumber);
++ goto out_bh;
++ }
++
++ ret = udf_fill_partdesc_info(sb, p, i);
++
++ /*
++ * Now rescan for VIRTUAL or METADATA partitions when SPARABLE and
++ * PHYSICAL partitions are already set up
++ */
++ type1_idx = i;
++ for (i = 0; i < sbi->s_partitions; i++) {
++ map = &sbi->s_partmaps[i];
++
++ if (map->s_partition_num == partitionNumber &&
++ (map->s_partition_type == UDF_VIRTUAL_MAP15 ||
++ map->s_partition_type == UDF_VIRTUAL_MAP20 ||
++ map->s_partition_type == UDF_METADATA_MAP25))
++ break;
++ }
++
++ if (i >= sbi->s_partitions)
++ goto out_bh;
++
++ ret = udf_fill_partdesc_info(sb, p, i);
++ if (ret)
++ goto out_bh;
++
++ if (map->s_partition_type == UDF_METADATA_MAP25) {
++ ret = udf_load_metadata_files(sb, i);
++ if (ret) {
++ printk(KERN_ERR "UDF-fs: error loading MetaData "
++ "partition map %d\n", i);
++ goto out_bh;
++ }
++ } else {
++ ret = udf_load_vat(sb, i, type1_idx);
++ if (ret)
++ goto out_bh;
++ /*
++ * Mark filesystem read-only if we have a partition with
++ * virtual map since we don't handle writing to it (we
++ * overwrite blocks instead of relocating them).
++ */
++ sb->s_flags |= MS_RDONLY;
++ printk(KERN_NOTICE "UDF-fs: Filesystem marked read-only "
++ "because writing to pseudooverwrite partition is "
++ "not implemented.\n");
++ }
++out_bh:
++ /* In case loading failed, we handle cleanup in udf_fill_super */
++ brelse(bh);
++ return ret;
+ }
+
+-static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh,
++static int udf_load_logicalvol(struct super_block *sb, sector_t block,
+ kernel_lb_addr *fileset)
+ {
+ struct logicalVolDesc *lvd;
+@@ -1194,12 +1340,21 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh,
+ uint8_t type;
+ struct udf_sb_info *sbi = UDF_SB(sb);
+ struct genericPartitionMap *gpm;
++ uint16_t ident;
++ struct buffer_head *bh;
++ int ret = 0;
+
++ bh = udf_read_tagged(sb, block, block, &ident);
++ if (!bh)
++ return 1;
++ BUG_ON(ident != TAG_IDENT_LVD);
+ lvd = (struct logicalVolDesc *)bh->b_data;
+
+ i = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps));
+- if (i != 0)
+- return i;
++ if (i != 0) {
++ ret = i;
++ goto out_bh;
++ }
+
+ for (i = 0, offset = 0;
+ i < sbi->s_partitions && offset < le32_to_cpu(lvd->mapTableLength);
+@@ -1223,12 +1378,12 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh,
+ u16 suf =
+ le16_to_cpu(((__le16 *)upm2->partIdent.
+ identSuffix)[0]);
+- if (suf == 0x0150) {
++ if (suf < 0x0200) {
+ map->s_partition_type =
+ UDF_VIRTUAL_MAP15;
+ map->s_partition_func =
+ udf_get_pblock_virt15;
+- } else if (suf == 0x0200) {
++ } else {
+ map->s_partition_type =
+ UDF_VIRTUAL_MAP20;
+ map->s_partition_func =
+@@ -1238,7 +1393,6 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh,
+ UDF_ID_SPARABLE,
+ strlen(UDF_ID_SPARABLE))) {
+ uint32_t loc;
+- uint16_t ident;
+ struct sparingTable *st;
+ struct sparablePartitionMap *spm =
+ (struct sparablePartitionMap *)gpm;
+@@ -1256,22 +1410,64 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh,
+ map->s_type_specific.s_sparing.
+ s_spar_map[j] = bh2;
+
+- if (bh2 != NULL) {
+- st = (struct sparingTable *)
+- bh2->b_data;
+- if (ident != 0 || strncmp(
+- st->sparingIdent.ident,
+- UDF_ID_SPARING,
+- strlen(UDF_ID_SPARING))) {
+- brelse(bh2);
+- map->s_type_specific.
+- s_sparing.
+- s_spar_map[j] =
+- NULL;
+- }
++ if (bh2 == NULL)
++ continue;
++
++ st = (struct sparingTable *)bh2->b_data;
++ if (ident != 0 || strncmp(
++ st->sparingIdent.ident,
++ UDF_ID_SPARING,
++ strlen(UDF_ID_SPARING))) {
++ brelse(bh2);
++ map->s_type_specific.s_sparing.
++ s_spar_map[j] = NULL;
+ }
+ }
+ map->s_partition_func = udf_get_pblock_spar15;
++ } else if (!strncmp(upm2->partIdent.ident,
++ UDF_ID_METADATA,
++ strlen(UDF_ID_METADATA))) {
++ struct udf_meta_data *mdata =
++ &map->s_type_specific.s_metadata;
++ struct metadataPartitionMap *mdm =
++ (struct metadataPartitionMap *)
++ &(lvd->partitionMaps[offset]);
++ udf_debug("Parsing Logical vol part %d "
++ "type %d id=%s\n", i, type,
++ UDF_ID_METADATA);
++
++ map->s_partition_type = UDF_METADATA_MAP25;
++ map->s_partition_func = udf_get_pblock_meta25;
++
++ mdata->s_meta_file_loc =
++ le32_to_cpu(mdm->metadataFileLoc);
++ mdata->s_mirror_file_loc =
++ le32_to_cpu(mdm->metadataMirrorFileLoc);
++ mdata->s_bitmap_file_loc =
++ le32_to_cpu(mdm->metadataBitmapFileLoc);
++ mdata->s_alloc_unit_size =
++ le32_to_cpu(mdm->allocUnitSize);
++ mdata->s_align_unit_size =
++ le16_to_cpu(mdm->alignUnitSize);
++ mdata->s_dup_md_flag =
++ mdm->flags & 0x01;
++
++ udf_debug("Metadata Ident suffix=0x%x\n",
++ (le16_to_cpu(
++ ((__le16 *)
++ mdm->partIdent.identSuffix)[0])));
++ udf_debug("Metadata part num=%d\n",
++ le16_to_cpu(mdm->partitionNum));
++ udf_debug("Metadata part alloc unit size=%d\n",
++ le32_to_cpu(mdm->allocUnitSize));
++ udf_debug("Metadata file loc=%d\n",
++ le32_to_cpu(mdm->metadataFileLoc));
++ udf_debug("Mirror file loc=%d\n",
++ le32_to_cpu(mdm->metadataMirrorFileLoc));
++ udf_debug("Bitmap file loc=%d\n",
++ le32_to_cpu(mdm->metadataBitmapFileLoc));
++ udf_debug("Duplicate Flag: %d %d\n",
++ mdata->s_dup_md_flag, mdm->flags);
+ } else {
+ udf_debug("Unknown ident: %s\n",
+ upm2->partIdent.ident);
+@@ -1296,7 +1492,9 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh,
+ if (lvd->integritySeqExt.extLength)
+ udf_load_logicalvolint(sb, leea_to_cpu(lvd->integritySeqExt));
+
+- return 0;
++out_bh:
++ brelse(bh);
++ return ret;
+ }
+
+ /*
+@@ -1345,7 +1543,7 @@ static void udf_load_logicalvolint(struct super_block *sb, kernel_extent_ad loc)
+ * July 1, 1997 - Andrew E. Mileski
+ * Written, tested, and released.
+ */
+-static int udf_process_sequence(struct super_block *sb, long block,
++static noinline int udf_process_sequence(struct super_block *sb, long block,
+ long lastblock, kernel_lb_addr *fileset)
+ {
+ struct buffer_head *bh = NULL;
+@@ -1354,19 +1552,25 @@ static int udf_process_sequence(struct super_block *sb, long block,
+ struct generic_desc *gd;
+ struct volDescPtr *vdp;
+ int done = 0;
+- int i, j;
+ uint32_t vdsn;
+ uint16_t ident;
+ long next_s = 0, next_e = 0;
+
+ memset(vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH);
+
+- /* Read the main descriptor sequence */
++ /*
++ * Read the main descriptor sequence and find which descriptors
++ * are in it.
++ */
+ for (; (!done && block <= lastblock); block++) {
+
+ bh = udf_read_tagged(sb, block, block, &ident);
+- if (!bh)
+- break;
++ if (!bh) {
++ printk(KERN_ERR "udf: Block %Lu of volume descriptor "
++ "sequence is corrupted or we could not read "
++ "it.\n", (unsigned long long)block);
++ return 1;
++ }
+
+ /* Process each descriptor (ISO 13346 3/8.3-8.4) */
+ gd = (struct generic_desc *)bh->b_data;
+@@ -1432,41 +1636,31 @@ static int udf_process_sequence(struct super_block *sb, long block,
+ }
+ brelse(bh);
+ }
+- for (i = 0; i < VDS_POS_LENGTH; i++) {
+- if (vds[i].block) {
+- bh = udf_read_tagged(sb, vds[i].block, vds[i].block,
+- &ident);
+-
+- if (i == VDS_POS_PRIMARY_VOL_DESC) {
+- udf_load_pvoldesc(sb, bh);
+- } else if (i == VDS_POS_LOGICAL_VOL_DESC) {
+- if (udf_load_logicalvol(sb, bh, fileset)) {
+- brelse(bh);
+- return 1;
+- }
+- } else if (i == VDS_POS_PARTITION_DESC) {
+- struct buffer_head *bh2 = NULL;
+- if (udf_load_partdesc(sb, bh)) {
+- brelse(bh);
+- return 1;
+- }
+- for (j = vds[i].block + 1;
+- j < vds[VDS_POS_TERMINATING_DESC].block;
+- j++) {
+- bh2 = udf_read_tagged(sb, j, j, &ident);
+- gd = (struct generic_desc *)bh2->b_data;
+- if (ident == TAG_IDENT_PD)
+- if (udf_load_partdesc(sb,
+- bh2)) {
+- brelse(bh);
+- brelse(bh2);
+- return 1;
+- }
+- brelse(bh2);
+- }
+- }
+- brelse(bh);
+- }
++ /*
++ * Now read interesting descriptors again and process them
++ * in a suitable order
++ */
++ if (!vds[VDS_POS_PRIMARY_VOL_DESC].block) {
++ printk(KERN_ERR "udf: Primary Volume Descriptor not found!\n");
++ return 1;
++ }
++ if (udf_load_pvoldesc(sb, vds[VDS_POS_PRIMARY_VOL_DESC].block))
++ return 1;
++
++ if (vds[VDS_POS_LOGICAL_VOL_DESC].block && udf_load_logicalvol(sb,
++ vds[VDS_POS_LOGICAL_VOL_DESC].block, fileset))
++ return 1;
++
++ if (vds[VDS_POS_PARTITION_DESC].block) {
++ /*
++ * We rescan the whole descriptor sequence to find
++ * partition descriptor blocks and process them.
++ */
++ for (block = vds[VDS_POS_PARTITION_DESC].block;
++ block < vds[VDS_POS_TERMINATING_DESC].block;
++ block++)
++ if (udf_load_partdesc(sb, block))
++ return 1;
+ }
+
+ return 0;
+@@ -1478,6 +1672,7 @@ static int udf_process_sequence(struct super_block *sb, long block,
+ static int udf_check_valid(struct super_block *sb, int novrs, int silent)
+ {
+ long block;
++ struct udf_sb_info *sbi = UDF_SB(sb);
+
+ if (novrs) {
+ udf_debug("Validity check skipped because of novrs option\n");
+@@ -1485,27 +1680,22 @@ static int udf_check_valid(struct super_block *sb, int novrs, int silent)
+ }
+ /* Check that it is NSR02 compliant */
+ /* Process any "CD-ROM Volume Descriptor Set" (ECMA 167 2/8.3.1) */
+- else {
+- block = udf_vrs(sb, silent);
+- if (block == -1) {
+- struct udf_sb_info *sbi = UDF_SB(sb);
+- udf_debug("Failed to read byte 32768. Assuming open "
+- "disc. Skipping validity check\n");
+- if (!sbi->s_last_block)
+- sbi->s_last_block = udf_get_last_block(sb);
+- return 0;
+- } else
+- return !block;
+- }
++ block = udf_vrs(sb, silent);
++ if (block == -1)
++ udf_debug("Failed to read byte 32768. Assuming open "
++ "disc. Skipping validity check\n");
++ if (block && !sbi->s_last_block)
++ sbi->s_last_block = udf_get_last_block(sb);
++ return !block;
+ }
+
+-static int udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset)
++static int udf_load_sequence(struct super_block *sb, kernel_lb_addr *fileset)
+ {
+ struct anchorVolDescPtr *anchor;
+ uint16_t ident;
+ struct buffer_head *bh;
+ long main_s, main_e, reserve_s, reserve_e;
+- int i, j;
++ int i;
+ struct udf_sb_info *sbi;
+
+ if (!sb)
+@@ -1515,6 +1705,7 @@ static int udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset)
+ for (i = 0; i < ARRAY_SIZE(sbi->s_anchor); i++) {
+ if (!sbi->s_anchor[i])
+ continue;
++
+ bh = udf_read_tagged(sb, sbi->s_anchor[i], sbi->s_anchor[i],
+ &ident);
+ if (!bh)
+@@ -1553,76 +1744,6 @@ static int udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset)
+ }
+ udf_debug("Using anchor in block %d\n", sbi->s_anchor[i]);
+
+- for (i = 0; i < sbi->s_partitions; i++) {
+- kernel_lb_addr uninitialized_var(ino);
+- struct udf_part_map *map = &sbi->s_partmaps[i];
+- switch (map->s_partition_type) {
+- case UDF_VIRTUAL_MAP15:
+- case UDF_VIRTUAL_MAP20:
+- if (!sbi->s_last_block) {
+- sbi->s_last_block = udf_get_last_block(sb);
+- udf_find_anchor(sb);
+- }
+-
+- if (!sbi->s_last_block) {
+- udf_debug("Unable to determine Lastblock (For "
+- "Virtual Partition)\n");
+- return 1;
+- }
+-
+- for (j = 0; j < sbi->s_partitions; j++) {
+- struct udf_part_map *map2 = &sbi->s_partmaps[j];
+- if (j != i &&
+- map->s_volumeseqnum ==
+- map2->s_volumeseqnum &&
+- map->s_partition_num ==
+- map2->s_partition_num) {
+- ino.partitionReferenceNum = j;
+- ino.logicalBlockNum =
+- sbi->s_last_block -
+- map2->s_partition_root;
+- break;
+- }
+- }
+-
+- if (j == sbi->s_partitions)
+- return 1;
+-
+- sbi->s_vat_inode = udf_iget(sb, ino);
+- if (!sbi->s_vat_inode)
+- return 1;
+-
+- if (map->s_partition_type == UDF_VIRTUAL_MAP15) {
+- map->s_type_specific.s_virtual.s_start_offset =
+- udf_ext0_offset(sbi->s_vat_inode);
+- map->s_type_specific.s_virtual.s_num_entries =
+- (sbi->s_vat_inode->i_size - 36) >> 2;
+- } else if (map->s_partition_type == UDF_VIRTUAL_MAP20) {
+- uint32_t pos;
+- struct virtualAllocationTable20 *vat20;
+-
+- pos = udf_block_map(sbi->s_vat_inode, 0);
+- bh = sb_bread(sb, pos);
+- if (!bh)
+- return 1;
+- vat20 = (struct virtualAllocationTable20 *)
+- bh->b_data +
+- udf_ext0_offset(sbi->s_vat_inode);
+- map->s_type_specific.s_virtual.s_start_offset =
+- le16_to_cpu(vat20->lengthHeader) +
+- udf_ext0_offset(sbi->s_vat_inode);
+- map->s_type_specific.s_virtual.s_num_entries =
+- (sbi->s_vat_inode->i_size -
+- map->s_type_specific.s_virtual.
+- s_start_offset) >> 2;
+- brelse(bh);
+- }
+- map->s_partition_root = udf_get_pblock(sb, 0, i, 0);
+- map->s_partition_len =
+- sbi->s_partmaps[ino.partitionReferenceNum].
+- s_partition_len;
+- }
+- }
+ return 0;
+ }
+
+@@ -1630,65 +1751,61 @@ static void udf_open_lvid(struct super_block *sb)
+ {
+ struct udf_sb_info *sbi = UDF_SB(sb);
+ struct buffer_head *bh = sbi->s_lvid_bh;
+- if (bh) {
+- kernel_timestamp cpu_time;
+- struct logicalVolIntegrityDesc *lvid =
+- (struct logicalVolIntegrityDesc *)bh->b_data;
+- struct logicalVolIntegrityDescImpUse *lvidiu =
+- udf_sb_lvidiu(sbi);
++ struct logicalVolIntegrityDesc *lvid;
++ struct logicalVolIntegrityDescImpUse *lvidiu;
++ if (!bh)
++ return;
+
+- lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
+- lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
+- if (udf_time_to_stamp(&cpu_time, CURRENT_TIME))
+- lvid->recordingDateAndTime = cpu_to_lets(cpu_time);
+- lvid->integrityType = LVID_INTEGRITY_TYPE_OPEN;
++ lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
++ lvidiu = udf_sb_lvidiu(sbi);
+
+- lvid->descTag.descCRC = cpu_to_le16(
+- udf_crc((char *)lvid + sizeof(tag),
+- le16_to_cpu(lvid->descTag.descCRCLength),
+- 0));
++ lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
++ lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
++ udf_time_to_disk_stamp(&lvid->recordingDateAndTime,
++ CURRENT_TIME);
++ lvid->integrityType = LVID_INTEGRITY_TYPE_OPEN;
+
+- lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
+- mark_buffer_dirty(bh);
+- }
++ lvid->descTag.descCRC = cpu_to_le16(
++ crc_itu_t(0, (char *)lvid + sizeof(tag),
++ le16_to_cpu(lvid->descTag.descCRCLength)));
++
++ lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
++ mark_buffer_dirty(bh);
+ }
+
+ static void udf_close_lvid(struct super_block *sb)
+ {
+- kernel_timestamp cpu_time;
+ struct udf_sb_info *sbi = UDF_SB(sb);
+ struct buffer_head *bh = sbi->s_lvid_bh;
+ struct logicalVolIntegrityDesc *lvid;
++ struct logicalVolIntegrityDescImpUse *lvidiu;
+
+ if (!bh)
+ return;
+
+ lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
+
+- if (lvid->integrityType == LVID_INTEGRITY_TYPE_OPEN) {
+- struct logicalVolIntegrityDescImpUse *lvidiu =
+- udf_sb_lvidiu(sbi);
+- lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
+- lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
+- if (udf_time_to_stamp(&cpu_time, CURRENT_TIME))
+- lvid->recordingDateAndTime = cpu_to_lets(cpu_time);
+- if (UDF_MAX_WRITE_VERSION > le16_to_cpu(lvidiu->maxUDFWriteRev))
+- lvidiu->maxUDFWriteRev =
+- cpu_to_le16(UDF_MAX_WRITE_VERSION);
+- if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFReadRev))
+- lvidiu->minUDFReadRev = cpu_to_le16(sbi->s_udfrev);
+- if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFWriteRev))
+- lvidiu->minUDFWriteRev = cpu_to_le16(sbi->s_udfrev);
+- lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_CLOSE);
+-
+- lvid->descTag.descCRC = cpu_to_le16(
+- udf_crc((char *)lvid + sizeof(tag),
+- le16_to_cpu(lvid->descTag.descCRCLength),
+- 0));
+-
+- lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
+- mark_buffer_dirty(bh);
+- }
++ if (lvid->integrityType != LVID_INTEGRITY_TYPE_OPEN)
++ return;
++
++ lvidiu = udf_sb_lvidiu(sbi);
++ lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
++ lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
++ udf_time_to_disk_stamp(&lvid->recordingDateAndTime, CURRENT_TIME);
++ if (UDF_MAX_WRITE_VERSION > le16_to_cpu(lvidiu->maxUDFWriteRev))
++ lvidiu->maxUDFWriteRev = cpu_to_le16(UDF_MAX_WRITE_VERSION);
++ if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFReadRev))
++ lvidiu->minUDFReadRev = cpu_to_le16(sbi->s_udfrev);
++ if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFWriteRev))
++ lvidiu->minUDFWriteRev = cpu_to_le16(sbi->s_udfrev);
++ lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_CLOSE);
++
++ lvid->descTag.descCRC = cpu_to_le16(
++ crc_itu_t(0, (char *)lvid + sizeof(tag),
++ le16_to_cpu(lvid->descTag.descCRCLength)));
++
++ lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
++ mark_buffer_dirty(bh);
+ }
+
+ static void udf_sb_free_bitmap(struct udf_bitmap *bitmap)
+@@ -1708,22 +1825,35 @@ static void udf_sb_free_bitmap(struct udf_bitmap *bitmap)
+ vfree(bitmap);
+ }
+
+-/*
+- * udf_read_super
+- *
+- * PURPOSE
+- * Complete the specified super block.
+- *
+- * PRE-CONDITIONS
+- * sb Pointer to superblock to complete - never NULL.
+- * sb->s_dev Device to read suberblock from.
+- * options Pointer to mount options.
+- * silent Silent flag.
+- *
+- * HISTORY
+- * July 1, 1997 - Andrew E. Mileski
+- * Written, tested, and released.
+- */
++static void udf_free_partition(struct udf_part_map *map)
++{
++ int i;
++ struct udf_meta_data *mdata;
++
++ if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE)
++ iput(map->s_uspace.s_table);
++ if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE)
++ iput(map->s_fspace.s_table);
++ if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP)
++ udf_sb_free_bitmap(map->s_uspace.s_bitmap);
++ if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP)
++ udf_sb_free_bitmap(map->s_fspace.s_bitmap);
++ if (map->s_partition_type == UDF_SPARABLE_MAP15)
++ for (i = 0; i < 4; i++)
++ brelse(map->s_type_specific.s_sparing.s_spar_map[i]);
++ else if (map->s_partition_type == UDF_METADATA_MAP25) {
++ mdata = &map->s_type_specific.s_metadata;
++ iput(mdata->s_metadata_fe);
++ mdata->s_metadata_fe = NULL;
++
++ iput(mdata->s_mirror_fe);
++ mdata->s_mirror_fe = NULL;
++
++ iput(mdata->s_bitmap_fe);
++ mdata->s_bitmap_fe = NULL;
++ }
++}
++
+ static int udf_fill_super(struct super_block *sb, void *options, int silent)
+ {
+ int i;
+@@ -1776,8 +1906,11 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
+ sbi->s_nls_map = uopt.nls_map;
+
+ /* Set the block size for all transfers */
+- if (!udf_set_blocksize(sb, uopt.blocksize))
++ if (!sb_min_blocksize(sb, uopt.blocksize)) {
++ udf_debug("Bad block size (%d)\n", uopt.blocksize);
++ printk(KERN_ERR "udf: bad block size (%d)\n", uopt.blocksize);
+ goto error_out;
++ }
+
+ if (uopt.session == 0xFFFFFFFF)
+ sbi->s_session = udf_get_last_session(sb);
+@@ -1789,7 +1922,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
+ sbi->s_last_block = uopt.lastblock;
+ sbi->s_anchor[0] = sbi->s_anchor[1] = 0;
+ sbi->s_anchor[2] = uopt.anchor;
+- sbi->s_anchor[3] = 256;
+
+ if (udf_check_valid(sb, uopt.novrs, silent)) {
+ /* read volume recognition sequences */
+@@ -1806,7 +1938,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
+ sb->s_magic = UDF_SUPER_MAGIC;
+ sb->s_time_gran = 1000;
+
+- if (udf_load_partition(sb, &fileset)) {
++ if (udf_load_sequence(sb, &fileset)) {
+ printk(KERN_WARNING "UDF-fs: No partition found (1)\n");
+ goto error_out;
+ }
+@@ -1856,12 +1988,12 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
+ }
+
+ if (!silent) {
+- kernel_timestamp ts;
+- udf_time_to_stamp(&ts, sbi->s_record_time);
++ timestamp ts;
++ udf_time_to_disk_stamp(&ts, sbi->s_record_time);
+ udf_info("UDF: Mounting volume '%s', "
+ "timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
+- sbi->s_volume_ident, ts.year, ts.month, ts.day,
+- ts.hour, ts.minute, ts.typeAndTimezone);
++ sbi->s_volume_ident, le16_to_cpu(ts.year), ts.month, ts.day,
++ ts.hour, ts.minute, le16_to_cpu(ts.typeAndTimezone));
+ }
+ if (!(sb->s_flags & MS_RDONLY))
+ udf_open_lvid(sb);
+@@ -1890,21 +2022,9 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
+ error_out:
+ if (sbi->s_vat_inode)
+ iput(sbi->s_vat_inode);
+- if (sbi->s_partitions) {
+- struct udf_part_map *map = &sbi->s_partmaps[sbi->s_partition];
+- if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE)
+- iput(map->s_uspace.s_table);
+- if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE)
+- iput(map->s_fspace.s_table);
+- if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP)
+- udf_sb_free_bitmap(map->s_uspace.s_bitmap);
+- if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP)
+- udf_sb_free_bitmap(map->s_fspace.s_bitmap);
+- if (map->s_partition_type == UDF_SPARABLE_MAP15)
+- for (i = 0; i < 4; i++)
+- brelse(map->s_type_specific.s_sparing.
+- s_spar_map[i]);
+- }
++ if (sbi->s_partitions)
++ for (i = 0; i < sbi->s_partitions; i++)
++ udf_free_partition(&sbi->s_partmaps[i]);
+ #ifdef CONFIG_UDF_NLS
+ if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
+ unload_nls(sbi->s_nls_map);
+@@ -1920,8 +2040,8 @@ error_out:
+ return -EINVAL;
+ }
+
+-void udf_error(struct super_block *sb, const char *function,
+- const char *fmt, ...)
++static void udf_error(struct super_block *sb, const char *function,
++ const char *fmt, ...)
+ {
+ va_list args;
+
+@@ -1948,19 +2068,6 @@ void udf_warning(struct super_block *sb, const char *function,
+ sb->s_id, function, error_buf);
+ }
+
+-/*
+- * udf_put_super
+- *
+- * PURPOSE
+- * Prepare for destruction of the superblock.
+- *
+- * DESCRIPTION
+- * Called before the filesystem is unmounted.
+- *
+- * HISTORY
+- * July 1, 1997 - Andrew E. Mileski
+- * Written, tested, and released.
+- */
+ static void udf_put_super(struct super_block *sb)
+ {
+ int i;
+@@ -1969,21 +2076,9 @@ static void udf_put_super(struct super_block *sb)
+ sbi = UDF_SB(sb);
+ if (sbi->s_vat_inode)
+ iput(sbi->s_vat_inode);
+- if (sbi->s_partitions) {
+- struct udf_part_map *map = &sbi->s_partmaps[sbi->s_partition];
+- if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE)
+- iput(map->s_uspace.s_table);
+- if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE)
+- iput(map->s_fspace.s_table);
+- if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP)
+- udf_sb_free_bitmap(map->s_uspace.s_bitmap);
+- if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP)
+- udf_sb_free_bitmap(map->s_fspace.s_bitmap);
+- if (map->s_partition_type == UDF_SPARABLE_MAP15)
+- for (i = 0; i < 4; i++)
+- brelse(map->s_type_specific.s_sparing.
+- s_spar_map[i]);
+- }
++ if (sbi->s_partitions)
++ for (i = 0; i < sbi->s_partitions; i++)
++ udf_free_partition(&sbi->s_partmaps[i]);
+ #ifdef CONFIG_UDF_NLS
+ if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
+ unload_nls(sbi->s_nls_map);
+@@ -1996,19 +2091,6 @@ static void udf_put_super(struct super_block *sb)
+ sb->s_fs_info = NULL;
+ }
+
+-/*
+- * udf_stat_fs
+- *
+- * PURPOSE
+- * Return info about the filesystem.
+- *
+- * DESCRIPTION
+- * Called by sys_statfs()
+- *
+- * HISTORY
+- * July 1, 1997 - Andrew E. Mileski
+- * Written, tested, and released.
+- */
+ static int udf_statfs(struct dentry *dentry, struct kstatfs *buf)
+ {
+ struct super_block *sb = dentry->d_sb;
+@@ -2035,10 +2117,6 @@ static int udf_statfs(struct dentry *dentry, struct kstatfs *buf)
+ return 0;
+ }
+
+-static unsigned char udf_bitmap_lookup[16] = {
+- 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
+-};
+-
+ static unsigned int udf_count_free_bitmap(struct super_block *sb,
+ struct udf_bitmap *bitmap)
+ {
+@@ -2048,7 +2126,6 @@ static unsigned int udf_count_free_bitmap(struct super_block *sb,
+ int block = 0, newblock;
+ kernel_lb_addr loc;
+ uint32_t bytes;
+- uint8_t value;
+ uint8_t *ptr;
+ uint16_t ident;
+ struct spaceBitmapDesc *bm;
+@@ -2074,13 +2151,10 @@ static unsigned int udf_count_free_bitmap(struct super_block *sb,
+ ptr = (uint8_t *)bh->b_data;
+
+ while (bytes > 0) {
+- while ((bytes > 0) && (index < sb->s_blocksize)) {
+- value = ptr[index];
+- accum += udf_bitmap_lookup[value & 0x0f];
+- accum += udf_bitmap_lookup[value >> 4];
+- index++;
+- bytes--;
+- }
++ u32 cur_bytes = min_t(u32, bytes, sb->s_blocksize - index);
++ accum += bitmap_weight((const unsigned long *)(ptr + index),
++ cur_bytes * 8);
++ bytes -= cur_bytes;
+ if (bytes) {
+ brelse(bh);
+ newblock = udf_get_lb_pblock(sb, loc, ++block);
+diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c
+index 6ec9922..c3265e1 100644
+--- a/fs/udf/symlink.c
++++ b/fs/udf/symlink.c
+@@ -23,7 +23,6 @@
+ #include <asm/uaccess.h>
+ #include <linux/errno.h>
+ #include <linux/fs.h>
+-#include <linux/udf_fs.h>
+ #include <linux/time.h>
+ #include <linux/mm.h>
+ #include <linux/stat.h>
+diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c
+index fe61be1..65e19b4 100644
+--- a/fs/udf/truncate.c
++++ b/fs/udf/truncate.c
+@@ -22,7 +22,6 @@
+ #include "udfdecl.h"
+ #include <linux/fs.h>
+ #include <linux/mm.h>
+-#include <linux/udf_fs.h>
+ #include <linux/buffer_head.h>
+
+ #include "udf_i.h"
+@@ -180,6 +179,24 @@ void udf_discard_prealloc(struct inode *inode)
+ brelse(epos.bh);
+ }
+
++static void udf_update_alloc_ext_desc(struct inode *inode,
++ struct extent_position *epos,
++ u32 lenalloc)
++{
++ struct super_block *sb = inode->i_sb;
++ struct udf_sb_info *sbi = UDF_SB(sb);
++
++ struct allocExtDesc *aed = (struct allocExtDesc *) (epos->bh->b_data);
++ int len = sizeof(struct allocExtDesc);
++
++ aed->lengthAllocDescs = cpu_to_le32(lenalloc);
++ if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT) || sbi->s_udfrev >= 0x0201)
++ len += lenalloc;
++
++ udf_update_tag(epos->bh->b_data, len);
++ mark_buffer_dirty_inode(epos->bh, inode);
++}
++
+ void udf_truncate_extents(struct inode *inode)
+ {
+ struct extent_position epos;
+@@ -187,7 +204,6 @@ void udf_truncate_extents(struct inode *inode)
+ uint32_t elen, nelen = 0, indirect_ext_len = 0, lenalloc;
+ int8_t etype;
+ struct super_block *sb = inode->i_sb;
+- struct udf_sb_info *sbi = UDF_SB(sb);
+ sector_t first_block = inode->i_size >> sb->s_blocksize_bits, offset;
+ loff_t byte_offset;
+ int adsize;
+@@ -224,35 +240,15 @@ void udf_truncate_extents(struct inode *inode)
+ if (indirect_ext_len) {
+ /* We managed to free all extents in the
+ * indirect extent - free it too */
+- if (!epos.bh)
+- BUG();
++ BUG_ON(!epos.bh);
+ udf_free_blocks(sb, inode, epos.block,
+ 0, indirect_ext_len);
+- } else {
+- if (!epos.bh) {
+- iinfo->i_lenAlloc =
+- lenalloc;
+- mark_inode_dirty(inode);
+- } else {
+- struct allocExtDesc *aed =
+- (struct allocExtDesc *)
+- (epos.bh->b_data);
+- int len =
+- sizeof(struct allocExtDesc);
+-
+- aed->lengthAllocDescs =
+- cpu_to_le32(lenalloc);
+- if (!UDF_QUERY_FLAG(sb,
+- UDF_FLAG_STRICT) ||
+- sbi->s_udfrev >= 0x0201)
+- len += lenalloc;
+-
+- udf_update_tag(epos.bh->b_data,
+- len);
+- mark_buffer_dirty_inode(
+- epos.bh, inode);
+- }
+- }
++ } else if (!epos.bh) {
++ iinfo->i_lenAlloc = lenalloc;
++ mark_inode_dirty(inode);
++ } else
++ udf_update_alloc_ext_desc(inode,
++ &epos, lenalloc);
+ brelse(epos.bh);
+ epos.offset = sizeof(struct allocExtDesc);
+ epos.block = eloc;
+@@ -272,29 +268,14 @@ void udf_truncate_extents(struct inode *inode)
+ }
+
+ if (indirect_ext_len) {
+- if (!epos.bh)
+- BUG();
++ BUG_ON(!epos.bh);
+ udf_free_blocks(sb, inode, epos.block, 0,
+ indirect_ext_len);
+- } else {
+- if (!epos.bh) {
+- iinfo->i_lenAlloc = lenalloc;
+- mark_inode_dirty(inode);
+- } else {
+- struct allocExtDesc *aed =
+- (struct allocExtDesc *)(epos.bh->b_data);
+- aed->lengthAllocDescs = cpu_to_le32(lenalloc);
+- if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT) ||
+- sbi->s_udfrev >= 0x0201)
+- udf_update_tag(epos.bh->b_data,
+- lenalloc +
+- sizeof(struct allocExtDesc));
+- else
+- udf_update_tag(epos.bh->b_data,
+- sizeof(struct allocExtDesc));
+- mark_buffer_dirty_inode(epos.bh, inode);
+- }
+- }
++ } else if (!epos.bh) {
++ iinfo->i_lenAlloc = lenalloc;
++ mark_inode_dirty(inode);
++ } else
++ udf_update_alloc_ext_desc(inode, &epos, lenalloc);
+ } else if (inode->i_size) {
+ if (byte_offset) {
+ kernel_long_ad extent;
+diff --git a/fs/udf/udf_i.h b/fs/udf/udf_i.h
+index ccc52f1..4f86b1d 100644
+--- a/fs/udf/udf_i.h
++++ b/fs/udf/udf_i.h
+@@ -1,10 +1,32 @@
+-#ifndef __LINUX_UDF_I_H
+-#define __LINUX_UDF_I_H
++#ifndef _UDF_I_H
++#define _UDF_I_H
++
++struct udf_inode_info {
++ struct timespec i_crtime;
++ /* Physical address of inode */
++ kernel_lb_addr i_location;
++ __u64 i_unique;
++ __u32 i_lenEAttr;
++ __u32 i_lenAlloc;
++ __u64 i_lenExtents;
++ __u32 i_next_alloc_block;
++ __u32 i_next_alloc_goal;
++ unsigned i_alloc_type : 3;
++ unsigned i_efe : 1; /* extendedFileEntry */
++ unsigned i_use : 1; /* unallocSpaceEntry */
++ unsigned i_strat4096 : 1;
++ unsigned reserved : 26;
++ union {
++ short_ad *i_sad;
++ long_ad *i_lad;
++ __u8 *i_data;
++ } i_ext;
++ struct inode vfs_inode;
++};
+
+-#include <linux/udf_fs_i.h>
+ static inline struct udf_inode_info *UDF_I(struct inode *inode)
+ {
+ return list_entry(inode, struct udf_inode_info, vfs_inode);
+ }
+
+-#endif /* !defined(_LINUX_UDF_I_H) */
++#endif /* _UDF_I_H) */
+diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h
+index 737d1c6..1c1c514 100644
+--- a/fs/udf/udf_sb.h
++++ b/fs/udf/udf_sb.h
+@@ -1,10 +1,12 @@
+ #ifndef __LINUX_UDF_SB_H
+ #define __LINUX_UDF_SB_H
+
++#include <linux/mutex.h>
++
+ /* Since UDF 2.01 is ISO 13346 based... */
+ #define UDF_SUPER_MAGIC 0x15013346
+
+-#define UDF_MAX_READ_VERSION 0x0201
++#define UDF_MAX_READ_VERSION 0x0250
+ #define UDF_MAX_WRITE_VERSION 0x0201
+
+ #define UDF_FLAG_USE_EXTENDED_FE 0
+@@ -38,6 +40,111 @@
+ #define UDF_PART_FLAG_REWRITABLE 0x0040
+ #define UDF_PART_FLAG_OVERWRITABLE 0x0080
+
++#define UDF_MAX_BLOCK_LOADED 8
++
++#define UDF_TYPE1_MAP15 0x1511U
++#define UDF_VIRTUAL_MAP15 0x1512U
++#define UDF_VIRTUAL_MAP20 0x2012U
++#define UDF_SPARABLE_MAP15 0x1522U
++#define UDF_METADATA_MAP25 0x2511U
++
++#pragma pack(1) /* XXX(hch): Why? This file just defines in-core structures */
++
++struct udf_meta_data {
++ __u32 s_meta_file_loc;
++ __u32 s_mirror_file_loc;
++ __u32 s_bitmap_file_loc;
++ __u32 s_alloc_unit_size;
++ __u16 s_align_unit_size;
++ __u8 s_dup_md_flag;
++ struct inode *s_metadata_fe;
++ struct inode *s_mirror_fe;
++ struct inode *s_bitmap_fe;
++};
++
++struct udf_sparing_data {
++ __u16 s_packet_len;
++ struct buffer_head *s_spar_map[4];
++};
++
++struct udf_virtual_data {
++ __u32 s_num_entries;
++ __u16 s_start_offset;
++};
++
++struct udf_bitmap {
++ __u32 s_extLength;
++ __u32 s_extPosition;
++ __u16 s_nr_groups;
++ struct buffer_head **s_block_bitmap;
++};
++
++struct udf_part_map {
++ union {
++ struct udf_bitmap *s_bitmap;
++ struct inode *s_table;
++ } s_uspace;
++ union {
++ struct udf_bitmap *s_bitmap;
++ struct inode *s_table;
++ } s_fspace;
++ __u32 s_partition_root;
++ __u32 s_partition_len;
++ __u16 s_partition_type;
++ __u16 s_partition_num;
++ union {
++ struct udf_sparing_data s_sparing;
++ struct udf_virtual_data s_virtual;
++ struct udf_meta_data s_metadata;
++ } s_type_specific;
++ __u32 (*s_partition_func)(struct super_block *, __u32, __u16, __u32);
++ __u16 s_volumeseqnum;
++ __u16 s_partition_flags;
++};
++
++#pragma pack()
++
++struct udf_sb_info {
++ struct udf_part_map *s_partmaps;
++ __u8 s_volume_ident[32];
++
++ /* Overall info */
++ __u16 s_partitions;
++ __u16 s_partition;
++
++ /* Sector headers */
++ __s32 s_session;
++ __u32 s_anchor[3];
++ __u32 s_last_block;
++
++ struct buffer_head *s_lvid_bh;
++
++ /* Default permissions */
++ mode_t s_umask;
++ gid_t s_gid;
++ uid_t s_uid;
++
++ /* Root Info */
++ struct timespec s_record_time;
++
++ /* Fileset Info */
++ __u16 s_serial_number;
++
++ /* highest UDF revision we have recorded to this media */
++ __u16 s_udfrev;
++
++ /* Miscellaneous flags */
++ __u32 s_flags;
++
++ /* Encoding info */
++ struct nls_table *s_nls_map;
++
++ /* VAT inode */
++ struct inode *s_vat_inode;
++
++ struct mutex s_alloc_mutex;
++};
++
+ static inline struct udf_sb_info *UDF_SB(struct super_block *sb)
+ {
+ return sb->s_fs_info;
+diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
+index 681dc2b..f3f45d0 100644
+--- a/fs/udf/udfdecl.h
++++ b/fs/udf/udfdecl.h
+@@ -1,17 +1,37 @@
+ #ifndef __UDF_DECL_H
+ #define __UDF_DECL_H
+
+-#include <linux/udf_fs.h>
+ #include "ecma_167.h"
+ #include "osta_udf.h"
+
+ #include <linux/fs.h>
+ #include <linux/types.h>
+-#include <linux/udf_fs_i.h>
+-#include <linux/udf_fs_sb.h>
+ #include <linux/buffer_head.h>
++#include <linux/udf_fs_i.h>
+
++#include "udf_sb.h"
+ #include "udfend.h"
++#include "udf_i.h"
++
++#define UDF_PREALLOCATE
++#define UDF_DEFAULT_PREALLOC_BLOCKS 8
++
++#define UDFFS_DEBUG
++
++#ifdef UDFFS_DEBUG
++#define udf_debug(f, a...) \
++do { \
++ printk(KERN_DEBUG "UDF-fs DEBUG %s:%d:%s: ", \
++ __FILE__, __LINE__, __func__); \
++ printk(f, ##a); \
++} while (0)
++#else
++#define udf_debug(f, a...) /**/
++#endif
++
++#define udf_info(f, a...) \
++ printk(KERN_INFO "UDF-fs INFO " f, ##a);
++
+
+ #define udf_fixed_to_variable(x) ( ( ( (x) >> 5 ) * 39 ) + ( (x) & 0x0000001F ) )
+ #define udf_variable_to_fixed(x) ( ( ( (x) / 39 ) << 5 ) + ( (x) % 39 ) )
+@@ -23,16 +43,24 @@
+ #define UDF_NAME_LEN 256
+ #define UDF_PATH_LEN 1023
+
+-#define udf_file_entry_alloc_offset(inode)\
+- (UDF_I(inode)->i_use ?\
+- sizeof(struct unallocSpaceEntry) :\
+- ((UDF_I(inode)->i_efe ?\
+- sizeof(struct extendedFileEntry) :\
+- sizeof(struct fileEntry)) + UDF_I(inode)->i_lenEAttr))
+-
+-#define udf_ext0_offset(inode)\
+- (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB ?\
+- udf_file_entry_alloc_offset(inode) : 0)
++static inline size_t udf_file_entry_alloc_offset(struct inode *inode)
++{
++ struct udf_inode_info *iinfo = UDF_I(inode);
++ if (iinfo->i_use)
++ return sizeof(struct unallocSpaceEntry);
++ else if (iinfo->i_efe)
++ return sizeof(struct extendedFileEntry) + iinfo->i_lenEAttr;
++ else
++ return sizeof(struct fileEntry) + iinfo->i_lenEAttr;
++}
++
++static inline size_t udf_ext0_offset(struct inode *inode)
++{
++ if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
++ return udf_file_entry_alloc_offset(inode);
++ else
++ return 0;
++}
+
+ #define udf_get_lb_pblock(sb,loc,offset) udf_get_pblock((sb), (loc).logicalBlockNum, (loc).partitionReferenceNum, (offset))
+
+@@ -83,7 +111,6 @@ struct extent_position {
+ };
+
+ /* super.c */
+-extern void udf_error(struct super_block *, const char *, const char *, ...);
+ extern void udf_warning(struct super_block *, const char *, const char *, ...);
+
+ /* namei.c */
+@@ -150,6 +177,8 @@ extern uint32_t udf_get_pblock_virt20(struct super_block *, uint32_t, uint16_t,
+ uint32_t);
+ extern uint32_t udf_get_pblock_spar15(struct super_block *, uint32_t, uint16_t,
+ uint32_t);
++extern uint32_t udf_get_pblock_meta25(struct super_block *, uint32_t, uint16_t,
++ uint32_t);
+ extern int udf_relocate_blocks(struct super_block *, long, long *);
+
+ /* unicode.c */
+@@ -157,7 +186,7 @@ extern int udf_get_filename(struct super_block *, uint8_t *, uint8_t *, int);
+ extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *,
+ int);
+ extern int udf_build_ustr(struct ustr *, dstring *, int);
+-extern int udf_CS0toUTF8(struct ustr *, struct ustr *);
++extern int udf_CS0toUTF8(struct ustr *, const struct ustr *);
+
+ /* ialloc.c */
+ extern void udf_free_inode(struct inode *);
+@@ -191,11 +220,9 @@ extern struct fileIdentDesc *udf_get_fileident(void *buffer, int bufsize,
+ extern long_ad *udf_get_filelongad(uint8_t *, int, uint32_t *, int);
+ extern short_ad *udf_get_fileshortad(uint8_t *, int, uint32_t *, int);
+
+-/* crc.c */
+-extern uint16_t udf_crc(uint8_t *, uint32_t, uint16_t);
+-
+ /* udftime.c */
+-extern time_t *udf_stamp_to_time(time_t *, long *, kernel_timestamp);
+-extern kernel_timestamp *udf_time_to_stamp(kernel_timestamp *, struct timespec);
++extern struct timespec *udf_disk_stamp_to_time(struct timespec *dest,
++ timestamp src);
++extern timestamp *udf_time_to_disk_stamp(timestamp *dest, struct timespec src);
+
+ #endif /* __UDF_DECL_H */
+diff --git a/fs/udf/udfend.h b/fs/udf/udfend.h
+index c4bd120..489f52f 100644
+--- a/fs/udf/udfend.h
++++ b/fs/udf/udfend.h
+@@ -24,17 +24,6 @@ static inline lb_addr cpu_to_lelb(kernel_lb_addr in)
+ return out;
+ }
+
+-static inline kernel_timestamp lets_to_cpu(timestamp in)
+-{
+- kernel_timestamp out;
+-
+- memcpy(&out, &in, sizeof(timestamp));
+- out.typeAndTimezone = le16_to_cpu(in.typeAndTimezone);
+- out.year = le16_to_cpu(in.year);
+-
+- return out;
+-}
+-
+ static inline short_ad lesa_to_cpu(short_ad in)
+ {
+ short_ad out;
+@@ -85,15 +74,4 @@ static inline kernel_extent_ad leea_to_cpu(extent_ad in)
+ return out;
+ }
+
+-static inline timestamp cpu_to_lets(kernel_timestamp in)
+-{
+- timestamp out;
+-
+- memcpy(&out, &in, sizeof(timestamp));
+- out.typeAndTimezone = cpu_to_le16(in.typeAndTimezone);
+- out.year = cpu_to_le16(in.year);
+-
+- return out;
+-}
+-
+ #endif /* __UDF_ENDIAN_H */
+diff --git a/fs/udf/udftime.c b/fs/udf/udftime.c
+index ce59573..5f81165 100644
+--- a/fs/udf/udftime.c
++++ b/fs/udf/udftime.c
+@@ -85,39 +85,38 @@ extern struct timezone sys_tz;
+ #define SECS_PER_HOUR (60 * 60)
+ #define SECS_PER_DAY (SECS_PER_HOUR * 24)
+
+-time_t *udf_stamp_to_time(time_t *dest, long *dest_usec, kernel_timestamp src)
++struct timespec *udf_disk_stamp_to_time(struct timespec *dest, timestamp src)
+ {
+ int yday;
+- uint8_t type = src.typeAndTimezone >> 12;
++ u16 typeAndTimezone = le16_to_cpu(src.typeAndTimezone);
++ u16 year = le16_to_cpu(src.year);
++ uint8_t type = typeAndTimezone >> 12;
+ int16_t offset;
+
+ if (type == 1) {
+- offset = src.typeAndTimezone << 4;
++ offset = typeAndTimezone << 4;
+ /* sign extent offset */
+ offset = (offset >> 4);
+ if (offset == -2047) /* unspecified offset */
+ offset = 0;
+- } else {
++ } else
+ offset = 0;
+- }
+
+- if ((src.year < EPOCH_YEAR) ||
+- (src.year >= EPOCH_YEAR + MAX_YEAR_SECONDS)) {
+- *dest = -1;
+- *dest_usec = -1;
++ if ((year < EPOCH_YEAR) ||
++ (year >= EPOCH_YEAR + MAX_YEAR_SECONDS)) {
+ return NULL;
+ }
+- *dest = year_seconds[src.year - EPOCH_YEAR];
+- *dest -= offset * 60;
++ dest->tv_sec = year_seconds[year - EPOCH_YEAR];
++ dest->tv_sec -= offset * 60;
+
+- yday = ((__mon_yday[__isleap(src.year)][src.month - 1]) + src.day - 1);
+- *dest += (((yday * 24) + src.hour) * 60 + src.minute) * 60 + src.second;
+- *dest_usec = src.centiseconds * 10000 +
+- src.hundredsOfMicroseconds * 100 + src.microseconds;
++ yday = ((__mon_yday[__isleap(year)][src.month - 1]) + src.day - 1);
++ dest->tv_sec += (((yday * 24) + src.hour) * 60 + src.minute) * 60 + src.second;
++ dest->tv_nsec = 1000 * (src.centiseconds * 10000 +
++ src.hundredsOfMicroseconds * 100 + src.microseconds);
+ return dest;
+ }
+
+-kernel_timestamp *udf_time_to_stamp(kernel_timestamp *dest, struct timespec ts)
++timestamp *udf_time_to_disk_stamp(timestamp *dest, struct timespec ts)
+ {
+ long int days, rem, y;
+ const unsigned short int *ip;
+@@ -128,7 +127,7 @@ kernel_timestamp *udf_time_to_stamp(kernel_timestamp *dest, struct timespec ts)
+ if (!dest)
+ return NULL;
+
+- dest->typeAndTimezone = 0x1000 | (offset & 0x0FFF);
++ dest->typeAndTimezone = cpu_to_le16(0x1000 | (offset & 0x0FFF));
+
+ ts.tv_sec += offset * 60;
+ days = ts.tv_sec / SECS_PER_DAY;
+@@ -151,7 +150,7 @@ kernel_timestamp *udf_time_to_stamp(kernel_timestamp *dest, struct timespec ts)
+ - LEAPS_THRU_END_OF(y - 1));
+ y = yg;
+ }
+- dest->year = y;
++ dest->year = cpu_to_le16(y);
+ ip = __mon_yday[__isleap(y)];
+ for (y = 11; days < (long int)ip[y]; --y)
+ continue;
+diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c
+index e533b11..9fdf8c9 100644
+--- a/fs/udf/unicode.c
++++ b/fs/udf/unicode.c
+@@ -23,7 +23,7 @@
+ #include <linux/kernel.h>
+ #include <linux/string.h> /* for memset */
+ #include <linux/nls.h>
+-#include <linux/udf_fs.h>
++#include <linux/crc-itu-t.h>
+
+ #include "udf_sb.h"
+
+@@ -49,14 +49,16 @@ int udf_build_ustr(struct ustr *dest, dstring *ptr, int size)
+ {
+ int usesize;
+
+- if ((!dest) || (!ptr) || (!size))
++ if (!dest || !ptr || !size)
+ return -1;
++ BUG_ON(size < 2);
+
+- memset(dest, 0, sizeof(struct ustr));
+- usesize = (size > UDF_NAME_LEN) ? UDF_NAME_LEN : size;
++ usesize = min_t(size_t, ptr[size - 1], sizeof(dest->u_name));
++ usesize = min(usesize, size - 2);
+ dest->u_cmpID = ptr[0];
+- dest->u_len = ptr[size - 1];
+- memcpy(dest->u_name, ptr + 1, usesize - 1);
++ dest->u_len = usesize;
++ memcpy(dest->u_name, ptr + 1, usesize);
++ memset(dest->u_name + usesize, 0, sizeof(dest->u_name) - usesize);
+
+ return 0;
+ }
+@@ -83,9 +85,6 @@ static int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
+ * PURPOSE
+ * Convert OSTA Compressed Unicode to the UTF-8 equivalent.
+ *
+- * DESCRIPTION
+- * This routine is only called by udf_filldir().
+- *
+ * PRE-CONDITIONS
+ * utf Pointer to UTF-8 output buffer.
+ * ocu Pointer to OSTA Compressed Unicode input buffer
+@@ -99,43 +98,39 @@ static int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
+ * November 12, 1997 - Andrew E. Mileski
+ * Written, tested, and released.
+ */
+-int udf_CS0toUTF8(struct ustr *utf_o, struct ustr *ocu_i)
++int udf_CS0toUTF8(struct ustr *utf_o, const struct ustr *ocu_i)
+ {
+- uint8_t *ocu;
+- uint32_t c;
++ const uint8_t *ocu;
+ uint8_t cmp_id, ocu_len;
+ int i;
+
+- ocu = ocu_i->u_name;
+-
+ ocu_len = ocu_i->u_len;
+- cmp_id = ocu_i->u_cmpID;
+- utf_o->u_len = 0;
+-
+ if (ocu_len == 0) {
+ memset(utf_o, 0, sizeof(struct ustr));
+- utf_o->u_cmpID = 0;
+- utf_o->u_len = 0;
+ return 0;
+ }
+
+- if ((cmp_id != 8) && (cmp_id != 16)) {
++ cmp_id = ocu_i->u_cmpID;
++ if (cmp_id != 8 && cmp_id != 16) {
++ memset(utf_o, 0, sizeof(struct ustr));
+ printk(KERN_ERR "udf: unknown compression code (%d) stri=%s\n",
+ cmp_id, ocu_i->u_name);
+ return 0;
+ }
+
++ ocu = ocu_i->u_name;
++ utf_o->u_len = 0;
+ for (i = 0; (i < ocu_len) && (utf_o->u_len <= (UDF_NAME_LEN - 3));) {
+
+ /* Expand OSTA compressed Unicode to Unicode */
+- c = ocu[i++];
++ uint32_t c = ocu[i++];
+ if (cmp_id == 16)
+ c = (c << 8) | ocu[i++];
+
+ /* Compress Unicode to UTF-8 */
+- if (c < 0x80U) {
++ if (c < 0x80U)
+ utf_o->u_name[utf_o->u_len++] = (uint8_t)c;
+- } else if (c < 0x800U) {
++ else if (c < 0x800U) {
+ utf_o->u_name[utf_o->u_len++] =
+ (uint8_t)(0xc0 | (c >> 6));
+ utf_o->u_name[utf_o->u_len++] =
+@@ -255,35 +250,32 @@ error_out:
+ }
+
+ static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o,
+- struct ustr *ocu_i)
++ const struct ustr *ocu_i)
+ {
+- uint8_t *ocu;
+- uint32_t c;
++ const uint8_t *ocu;
+ uint8_t cmp_id, ocu_len;
+ int i;
+
+- ocu = ocu_i->u_name;
+
+ ocu_len = ocu_i->u_len;
+- cmp_id = ocu_i->u_cmpID;
+- utf_o->u_len = 0;
+-
+ if (ocu_len == 0) {
+ memset(utf_o, 0, sizeof(struct ustr));
+- utf_o->u_cmpID = 0;
+- utf_o->u_len = 0;
+ return 0;
+ }
+
+- if ((cmp_id != 8) && (cmp_id != 16)) {
++ cmp_id = ocu_i->u_cmpID;
++ if (cmp_id != 8 && cmp_id != 16) {
++ memset(utf_o, 0, sizeof(struct ustr));
+ printk(KERN_ERR "udf: unknown compression code (%d) stri=%s\n",
+ cmp_id, ocu_i->u_name);
+ return 0;
+ }
+
++ ocu = ocu_i->u_name;
++ utf_o->u_len = 0;
+ for (i = 0; (i < ocu_len) && (utf_o->u_len <= (UDF_NAME_LEN - 3));) {
+ /* Expand OSTA compressed Unicode to Unicode */
+- c = ocu[i++];
++ uint32_t c = ocu[i++];
+ if (cmp_id == 16)
+ c = (c << 8) | ocu[i++];
+
+@@ -463,7 +455,7 @@ static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName,
+ } else if (newIndex > 250)
+ newIndex = 250;
+ newName[newIndex++] = CRC_MARK;
+- valueCRC = udf_crc(fidName, fidNameLen, 0);
++ valueCRC = crc_itu_t(0, fidName, fidNameLen);
+ newName[newIndex++] = hexChar[(valueCRC & 0xf000) >> 12];
+ newName[newIndex++] = hexChar[(valueCRC & 0x0f00) >> 8];
+ newName[newIndex++] = hexChar[(valueCRC & 0x00f0) >> 4];
+diff --git a/fs/utimes.c b/fs/utimes.c
+index b18da9c..a2bef77 100644
+--- a/fs/utimes.c
++++ b/fs/utimes.c
+@@ -2,6 +2,7 @@
+ #include <linux/file.h>
+ #include <linux/fs.h>
+ #include <linux/linkage.h>
++#include <linux/mount.h>
+ #include <linux/namei.h>
+ #include <linux/sched.h>
+ #include <linux/stat.h>
+@@ -59,6 +60,7 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
+ struct inode *inode;
+ struct iattr newattrs;
+ struct file *f = NULL;
++ struct vfsmount *mnt;
+
+ error = -EINVAL;
+ if (times && (!nsec_valid(times[0].tv_nsec) ||
+@@ -79,18 +81,20 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
+ if (!f)
+ goto out;
+ dentry = f->f_path.dentry;
++ mnt = f->f_path.mnt;
+ } else {
+ error = __user_walk_fd(dfd, filename, (flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW, &nd);
+ if (error)
+ goto out;
+
+ dentry = nd.path.dentry;
++ mnt = nd.path.mnt;
+ }
+
+ inode = dentry->d_inode;
+
+- error = -EROFS;
+- if (IS_RDONLY(inode))
++ error = mnt_want_write(mnt);
++ if (error)
+ goto dput_and_out;
+
+ /* Don't worry, the checks are done in inode_change_ok() */
+@@ -98,7 +102,7 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
+ if (times) {
+ error = -EPERM;
+ if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+- goto dput_and_out;
++ goto mnt_drop_write_and_out;
+
+ if (times[0].tv_nsec == UTIME_OMIT)
+ newattrs.ia_valid &= ~ATTR_ATIME;
+@@ -118,22 +122,24 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
+ } else {
+ error = -EACCES;
+ if (IS_IMMUTABLE(inode))
+- goto dput_and_out;
++ goto mnt_drop_write_and_out;
+
+ if (!is_owner_or_cap(inode)) {
+ if (f) {
+ if (!(f->f_mode & FMODE_WRITE))
+- goto dput_and_out;
++ goto mnt_drop_write_and_out;
+ } else {
+ error = vfs_permission(&nd, MAY_WRITE);
+ if (error)
+- goto dput_and_out;
++ goto mnt_drop_write_and_out;
+ }
+ }
+ }
+ mutex_lock(&inode->i_mutex);
+ error = notify_change(dentry, &newattrs);
+ mutex_unlock(&inode->i_mutex);
++mnt_drop_write_and_out:
++ mnt_drop_write(mnt);
+ dput_and_out:
+ if (f)
+ fput(f);
+diff --git a/fs/xattr.c b/fs/xattr.c
+index 3acab16..89a942f 100644
+--- a/fs/xattr.c
++++ b/fs/xattr.c
+@@ -11,6 +11,7 @@
+ #include <linux/slab.h>
+ #include <linux/file.h>
+ #include <linux/xattr.h>
++#include <linux/mount.h>
+ #include <linux/namei.h>
+ #include <linux/security.h>
+ #include <linux/syscalls.h>
+@@ -32,8 +33,6 @@ xattr_permission(struct inode *inode, const char *name, int mask)
+ * filesystem or on an immutable / append-only inode.
+ */
+ if (mask & MAY_WRITE) {
+- if (IS_RDONLY(inode))
+- return -EROFS;
+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+ return -EPERM;
+ }
+@@ -262,7 +261,11 @@ sys_setxattr(char __user *path, char __user *name, void __user *value,
+ error = user_path_walk(path, &nd);
+ if (error)
+ return error;
+- error = setxattr(nd.path.dentry, name, value, size, flags);
++ error = mnt_want_write(nd.path.mnt);
++ if (!error) {
++ error = setxattr(nd.path.dentry, name, value, size, flags);
++ mnt_drop_write(nd.path.mnt);
++ }
+ path_put(&nd.path);
+ return error;
+ }
+@@ -277,7 +280,11 @@ sys_lsetxattr(char __user *path, char __user *name, void __user *value,
+ error = user_path_walk_link(path, &nd);
+ if (error)
+ return error;
+- error = setxattr(nd.path.dentry, name, value, size, flags);
++ error = mnt_want_write(nd.path.mnt);
++ if (!error) {
++ error = setxattr(nd.path.dentry, name, value, size, flags);
++ mnt_drop_write(nd.path.mnt);
++ }
+ path_put(&nd.path);
+ return error;
+ }
+@@ -295,7 +302,11 @@ sys_fsetxattr(int fd, char __user *name, void __user *value,
+ return error;
+ dentry = f->f_path.dentry;
+ audit_inode(NULL, dentry);
+- error = setxattr(dentry, name, value, size, flags);
++ error = mnt_want_write(f->f_path.mnt);
++ if (!error) {
++ error = setxattr(dentry, name, value, size, flags);
++ mnt_drop_write(f->f_path.mnt);
++ }
+ fput(f);
+ return error;
+ }
+@@ -482,7 +493,11 @@ sys_removexattr(char __user *path, char __user *name)
+ error = user_path_walk(path, &nd);
+ if (error)
+ return error;
+- error = removexattr(nd.path.dentry, name);
++ error = mnt_want_write(nd.path.mnt);
++ if (!error) {
++ error = removexattr(nd.path.dentry, name);
++ mnt_drop_write(nd.path.mnt);
++ }
+ path_put(&nd.path);
+ return error;
+ }
+@@ -496,7 +511,11 @@ sys_lremovexattr(char __user *path, char __user *name)
+ error = user_path_walk_link(path, &nd);
+ if (error)
+ return error;
+- error = removexattr(nd.path.dentry, name);
++ error = mnt_want_write(nd.path.mnt);
++ if (!error) {
++ error = removexattr(nd.path.dentry, name);
++ mnt_drop_write(nd.path.mnt);
++ }
+ path_put(&nd.path);
+ return error;
+ }
+@@ -513,7 +532,11 @@ sys_fremovexattr(int fd, char __user *name)
+ return error;
+ dentry = f->f_path.dentry;
+ audit_inode(NULL, dentry);
+- error = removexattr(dentry, name);
++ error = mnt_want_write(f->f_path.mnt);
++ if (!error) {
++ error = removexattr(dentry, name);
++ mnt_drop_write(f->f_path.mnt);
++ }
+ fput(f);
+ return error;
+ }
+diff --git a/fs/xfs/Kconfig b/fs/xfs/Kconfig
+index 35115bc..524021f 100644
+--- a/fs/xfs/Kconfig
++++ b/fs/xfs/Kconfig
+@@ -35,18 +35,6 @@ config XFS_QUOTA
+ with or without the generic quota support enabled (CONFIG_QUOTA) -
+ they are completely independent subsystems.
+
+-config XFS_SECURITY
+- bool "XFS Security Label support"
+- depends on XFS_FS
+- help
+- Security labels support alternative access control models
+- implemented by security modules like SELinux. This option
+- enables an extended attribute namespace for inode security
+- labels in the XFS filesystem.
+-
+- If you are not using a security module that requires using
+- extended attributes for inode security labels, say N.
+-
+ config XFS_POSIX_ACL
+ bool "XFS POSIX ACL support"
+ depends on XFS_FS
+diff --git a/fs/xfs/linux-2.6/kmem.c b/fs/xfs/linux-2.6/kmem.c
+index e040f1c..9b1bb17 100644
+--- a/fs/xfs/linux-2.6/kmem.c
++++ b/fs/xfs/linux-2.6/kmem.c
+@@ -37,7 +37,7 @@ kmem_alloc(size_t size, unsigned int __nocast flags)
+ #ifdef DEBUG
+ if (unlikely(!(flags & KM_LARGE) && (size > PAGE_SIZE))) {
+ printk(KERN_WARNING "Large %s attempt, size=%ld\n",
+- __FUNCTION__, (long)size);
++ __func__, (long)size);
+ dump_stack();
+ }
+ #endif
+@@ -52,7 +52,7 @@ kmem_alloc(size_t size, unsigned int __nocast flags)
+ if (!(++retries % 100))
+ printk(KERN_ERR "XFS: possible memory allocation "
+ "deadlock in %s (mode:0x%x)\n",
+- __FUNCTION__, lflags);
++ __func__, lflags);
+ congestion_wait(WRITE, HZ/50);
+ } while (1);
+ }
+@@ -129,7 +129,7 @@ kmem_zone_alloc(kmem_zone_t *zone, unsigned int __nocast flags)
+ if (!(++retries % 100))
+ printk(KERN_ERR "XFS: possible memory allocation "
+ "deadlock in %s (mode:0x%x)\n",
+- __FUNCTION__, lflags);
++ __func__, lflags);
+ congestion_wait(WRITE, HZ/50);
+ } while (1);
+ }
+diff --git a/fs/xfs/linux-2.6/sema.h b/fs/xfs/linux-2.6/sema.h
+index 2009e6d..3abe7e9 100644
+--- a/fs/xfs/linux-2.6/sema.h
++++ b/fs/xfs/linux-2.6/sema.h
+@@ -20,8 +20,8 @@
+
+ #include <linux/time.h>
+ #include <linux/wait.h>
++#include <linux/semaphore.h>
+ #include <asm/atomic.h>
+-#include <asm/semaphore.h>
+
+ /*
+ * sema_t structure just maps to struct semaphore in Linux kernel.
+diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
+index e051952..a55c3b2 100644
+--- a/fs/xfs/linux-2.6/xfs_aops.c
++++ b/fs/xfs/linux-2.6/xfs_aops.c
+@@ -243,8 +243,12 @@ xfs_end_bio_unwritten(
+ size_t size = ioend->io_size;
+
+ if (likely(!ioend->io_error)) {
+- if (!XFS_FORCED_SHUTDOWN(ip->i_mount))
+- xfs_iomap_write_unwritten(ip, offset, size);
++ if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
++ int error;
++ error = xfs_iomap_write_unwritten(ip, offset, size);
++ if (error)
++ ioend->io_error = error;
++ }
+ xfs_setfilesize(ioend);
+ }
+ xfs_destroy_ioend(ioend);
+@@ -1532,9 +1536,9 @@ xfs_vm_bmap(
+ struct xfs_inode *ip = XFS_I(inode);
+
+ xfs_itrace_entry(XFS_I(inode));
+- xfs_rwlock(ip, VRWLOCK_READ);
++ xfs_ilock(ip, XFS_IOLOCK_SHARED);
+ xfs_flush_pages(ip, (xfs_off_t)0, -1, 0, FI_REMAPF);
+- xfs_rwunlock(ip, VRWLOCK_READ);
++ xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+ return generic_block_bmap(mapping, block, xfs_get_blocks);
+ }
+
+diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
+index e347bfd..52f6846 100644
+--- a/fs/xfs/linux-2.6/xfs_buf.c
++++ b/fs/xfs/linux-2.6/xfs_buf.c
+@@ -400,7 +400,7 @@ _xfs_buf_lookup_pages(
+ printk(KERN_ERR
+ "XFS: possible memory allocation "
+ "deadlock in %s (mode:0x%x)\n",
+- __FUNCTION__, gfp_mask);
++ __func__, gfp_mask);
+
+ XFS_STATS_INC(xb_page_retries);
+ xfsbufd_wakeup(0, gfp_mask);
+@@ -598,7 +598,7 @@ xfs_buf_get_flags(
+ error = _xfs_buf_map_pages(bp, flags);
+ if (unlikely(error)) {
+ printk(KERN_WARNING "%s: failed to map pages\n",
+- __FUNCTION__);
++ __func__);
+ goto no_buffer;
+ }
+ }
+@@ -778,7 +778,7 @@ xfs_buf_get_noaddr(
+ error = _xfs_buf_map_pages(bp, XBF_MAPPED);
+ if (unlikely(error)) {
+ printk(KERN_WARNING "%s: failed to map pages\n",
+- __FUNCTION__);
++ __func__);
+ goto fail_free_mem;
+ }
+
+@@ -1060,7 +1060,7 @@ xfs_buf_iostart(
+ bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_ASYNC);
+ bp->b_flags |= flags & (XBF_DELWRI | XBF_ASYNC);
+ xfs_buf_delwri_queue(bp, 1);
+- return status;
++ return 0;
+ }
+
+ bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_ASYNC | XBF_DELWRI | \
+diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
+index a3d207d..841d788 100644
+--- a/fs/xfs/linux-2.6/xfs_buf.h
++++ b/fs/xfs/linux-2.6/xfs_buf.h
+@@ -387,11 +387,15 @@ static inline int XFS_bwrite(xfs_buf_t *bp)
+ return error;
+ }
+
+-static inline int xfs_bdwrite(void *mp, xfs_buf_t *bp)
++/*
++ * No error can be returned from xfs_buf_iostart for delwri
++ * buffers as they are queued and no I/O is issued.
++ */
++static inline void xfs_bdwrite(void *mp, xfs_buf_t *bp)
+ {
+ bp->b_strat = xfs_bdstrat_cb;
+ bp->b_fspriv3 = mp;
+- return xfs_buf_iostart(bp, XBF_DELWRI | XBF_ASYNC);
++ (void)xfs_buf_iostart(bp, XBF_DELWRI | XBF_ASYNC);
+ }
+
+ #define XFS_bdstrat(bp) xfs_buf_iorequest(bp)
+diff --git a/fs/xfs/linux-2.6/xfs_cred.h b/fs/xfs/linux-2.6/xfs_cred.h
+index e7f3da6..652721c 100644
+--- a/fs/xfs/linux-2.6/xfs_cred.h
++++ b/fs/xfs/linux-2.6/xfs_cred.h
+@@ -30,7 +30,7 @@ typedef struct cred {
+ extern struct cred *sys_cred;
+
+ /* this is a hack.. (assumes sys_cred is the only cred_t in the system) */
+-static __inline int capable_cred(cred_t *cr, int cid)
++static inline int capable_cred(cred_t *cr, int cid)
+ {
+ return (cr == sys_cred) ? 1 : capable(cid);
+ }
+diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c
+index ca4f66c..265f016 100644
+--- a/fs/xfs/linux-2.6/xfs_export.c
++++ b/fs/xfs/linux-2.6/xfs_export.c
+@@ -22,6 +22,7 @@
+ #include "xfs_trans.h"
+ #include "xfs_sb.h"
+ #include "xfs_ag.h"
++#include "xfs_dir2.h"
+ #include "xfs_dmapi.h"
+ #include "xfs_mount.h"
+ #include "xfs_export.h"
+@@ -30,8 +31,6 @@
+ #include "xfs_inode.h"
+ #include "xfs_vfsops.h"
+
+-static struct dentry dotdot = { .d_name.name = "..", .d_name.len = 2, };
+-
+ /*
+ * Note that we only accept fileids which are long enough rather than allow
+ * the parent generation number to default to zero. XFS considers zero a
+@@ -66,7 +65,7 @@ xfs_fs_encode_fh(
+ int len;
+
+ /* Directories don't need their parent encoded, they have ".." */
+- if (S_ISDIR(inode->i_mode))
++ if (S_ISDIR(inode->i_mode) || !connectable)
+ fileid_type = FILEID_INO32_GEN;
+ else
+ fileid_type = FILEID_INO32_GEN_PARENT;
+@@ -213,17 +212,16 @@ xfs_fs_get_parent(
+ struct dentry *child)
+ {
+ int error;
+- bhv_vnode_t *cvp;
++ struct xfs_inode *cip;
+ struct dentry *parent;
+
+- cvp = NULL;
+- error = xfs_lookup(XFS_I(child->d_inode), &dotdot, &cvp);
++ error = xfs_lookup(XFS_I(child->d_inode), &xfs_name_dotdot, &cip);
+ if (unlikely(error))
+ return ERR_PTR(-error);
+
+- parent = d_alloc_anon(vn_to_inode(cvp));
++ parent = d_alloc_anon(cip->i_vnode);
+ if (unlikely(!parent)) {
+- VN_RELE(cvp);
++ iput(cip->i_vnode);
+ return ERR_PTR(-ENOMEM);
+ }
+ return parent;
+diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
+index edab1ff..0590524 100644
+--- a/fs/xfs/linux-2.6/xfs_file.c
++++ b/fs/xfs/linux-2.6/xfs_file.c
+@@ -469,16 +469,11 @@ xfs_file_open_exec(
+ struct inode *inode)
+ {
+ struct xfs_mount *mp = XFS_M(inode->i_sb);
++ struct xfs_inode *ip = XFS_I(inode);
+
+- if (unlikely(mp->m_flags & XFS_MOUNT_DMAPI)) {
+- if (DM_EVENT_ENABLED(XFS_I(inode), DM_EVENT_READ)) {
+- bhv_vnode_t *vp = vn_from_inode(inode);
+-
+- return -XFS_SEND_DATA(mp, DM_EVENT_READ,
+- vp, 0, 0, 0, NULL);
+- }
+- }
+-
++ if (unlikely(mp->m_flags & XFS_MOUNT_DMAPI) &&
++ DM_EVENT_ENABLED(ip, DM_EVENT_READ))
++ return -XFS_SEND_DATA(mp, DM_EVENT_READ, ip, 0, 0, 0, NULL);
+ return 0;
+ }
+ #endif /* HAVE_FOP_OPEN_EXEC */
+diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.c b/fs/xfs/linux-2.6/xfs_fs_subr.c
+index ac6d34c..1eefe61 100644
+--- a/fs/xfs/linux-2.6/xfs_fs_subr.c
++++ b/fs/xfs/linux-2.6/xfs_fs_subr.c
+@@ -17,18 +17,7 @@
+ */
+ #include "xfs.h"
+ #include "xfs_vnodeops.h"
+-
+-/*
+- * The following six includes are needed so that we can include
+- * xfs_inode.h. What a mess..
+- */
+ #include "xfs_bmap_btree.h"
+-#include "xfs_inum.h"
+-#include "xfs_dir2.h"
+-#include "xfs_dir2_sf.h"
+-#include "xfs_attr_sf.h"
+-#include "xfs_dinode.h"
+-
+ #include "xfs_inode.h"
+
+ int fs_noerr(void) { return 0; }
+@@ -42,11 +31,10 @@ xfs_tosspages(
+ xfs_off_t last,
+ int fiopt)
+ {
+- bhv_vnode_t *vp = XFS_ITOV(ip);
+- struct inode *inode = vn_to_inode(vp);
++ struct address_space *mapping = ip->i_vnode->i_mapping;
+
+- if (VN_CACHED(vp))
+- truncate_inode_pages(inode->i_mapping, first);
++ if (mapping->nrpages)
++ truncate_inode_pages(mapping, first);
+ }
+
+ int
+@@ -56,15 +44,14 @@ xfs_flushinval_pages(
+ xfs_off_t last,
+ int fiopt)
+ {
+- bhv_vnode_t *vp = XFS_ITOV(ip);
+- struct inode *inode = vn_to_inode(vp);
++ struct address_space *mapping = ip->i_vnode->i_mapping;
+ int ret = 0;
+
+- if (VN_CACHED(vp)) {
++ if (mapping->nrpages) {
+ xfs_iflags_clear(ip, XFS_ITRUNCATED);
+- ret = filemap_write_and_wait(inode->i_mapping);
++ ret = filemap_write_and_wait(mapping);
+ if (!ret)
+- truncate_inode_pages(inode->i_mapping, first);
++ truncate_inode_pages(mapping, first);
+ }
+ return ret;
+ }
+@@ -77,17 +64,16 @@ xfs_flush_pages(
+ uint64_t flags,
+ int fiopt)
+ {
+- bhv_vnode_t *vp = XFS_ITOV(ip);
+- struct inode *inode = vn_to_inode(vp);
++ struct address_space *mapping = ip->i_vnode->i_mapping;
+ int ret = 0;
+ int ret2;
+
+- if (VN_DIRTY(vp)) {
++ if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
+ xfs_iflags_clear(ip, XFS_ITRUNCATED);
+- ret = filemap_fdatawrite(inode->i_mapping);
++ ret = filemap_fdatawrite(mapping);
+ if (flags & XFS_B_ASYNC)
+ return ret;
+- ret2 = filemap_fdatawait(inode->i_mapping);
++ ret2 = filemap_fdatawait(mapping);
+ if (!ret)
+ ret = ret2;
+ }
+diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
+index f34bd01..4ddb86b 100644
+--- a/fs/xfs/linux-2.6/xfs_ioctl.c
++++ b/fs/xfs/linux-2.6/xfs_ioctl.c
+@@ -535,8 +535,6 @@ xfs_attrmulti_attr_set(
+ char *kbuf;
+ int error = EFAULT;
+
+- if (IS_RDONLY(inode))
+- return -EROFS;
+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+ return EPERM;
+ if (len > XATTR_SIZE_MAX)
+@@ -562,8 +560,6 @@ xfs_attrmulti_attr_remove(
+ char *name,
+ __uint32_t flags)
+ {
+- if (IS_RDONLY(inode))
+- return -EROFS;
+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+ return EPERM;
+ return xfs_attr_remove(XFS_I(inode), name, flags);
+@@ -573,6 +569,7 @@ STATIC int
+ xfs_attrmulti_by_handle(
+ xfs_mount_t *mp,
+ void __user *arg,
++ struct file *parfilp,
+ struct inode *parinode)
+ {
+ int error;
+@@ -626,13 +623,21 @@ xfs_attrmulti_by_handle(
+ &ops[i].am_length, ops[i].am_flags);
+ break;
+ case ATTR_OP_SET:
++ ops[i].am_error = mnt_want_write(parfilp->f_path.mnt);
++ if (ops[i].am_error)
++ break;
+ ops[i].am_error = xfs_attrmulti_attr_set(inode,
+ attr_name, ops[i].am_attrvalue,
+ ops[i].am_length, ops[i].am_flags);
++ mnt_drop_write(parfilp->f_path.mnt);
+ break;
+ case ATTR_OP_REMOVE:
++ ops[i].am_error = mnt_want_write(parfilp->f_path.mnt);
++ if (ops[i].am_error)
++ break;
+ ops[i].am_error = xfs_attrmulti_attr_remove(inode,
+ attr_name, ops[i].am_flags);
++ mnt_drop_write(parfilp->f_path.mnt);
+ break;
+ default:
+ ops[i].am_error = EINVAL;
+@@ -651,314 +656,6 @@ xfs_attrmulti_by_handle(
+ return -error;
+ }
+
+-/* prototypes for a few of the stack-hungry cases that have
+- * their own functions. Functions are defined after their use
+- * so gcc doesn't get fancy and inline them with -03 */
+-
+-STATIC int
+-xfs_ioc_space(
+- struct xfs_inode *ip,
+- struct inode *inode,
+- struct file *filp,
+- int flags,
+- unsigned int cmd,
+- void __user *arg);
+-
+-STATIC int
+-xfs_ioc_bulkstat(
+- xfs_mount_t *mp,
+- unsigned int cmd,
+- void __user *arg);
+-
+-STATIC int
+-xfs_ioc_fsgeometry_v1(
+- xfs_mount_t *mp,
+- void __user *arg);
+-
+-STATIC int
+-xfs_ioc_fsgeometry(
+- xfs_mount_t *mp,
+- void __user *arg);
+-
+-STATIC int
+-xfs_ioc_xattr(
+- xfs_inode_t *ip,
+- struct file *filp,
+- unsigned int cmd,
+- void __user *arg);
+-
+-STATIC int
+-xfs_ioc_fsgetxattr(
+- xfs_inode_t *ip,
+- int attr,
+- void __user *arg);
+-
+-STATIC int
+-xfs_ioc_getbmap(
+- struct xfs_inode *ip,
+- int flags,
+- unsigned int cmd,
+- void __user *arg);
+-
+-STATIC int
+-xfs_ioc_getbmapx(
+- struct xfs_inode *ip,
+- void __user *arg);
+-
+-int
+-xfs_ioctl(
+- xfs_inode_t *ip,
+- struct file *filp,
+- int ioflags,
+- unsigned int cmd,
+- void __user *arg)
+-{
+- struct inode *inode = filp->f_path.dentry->d_inode;
+- xfs_mount_t *mp = ip->i_mount;
+- int error;
+-
+- xfs_itrace_entry(XFS_I(inode));
+- switch (cmd) {
+-
+- case XFS_IOC_ALLOCSP:
+- case XFS_IOC_FREESP:
+- case XFS_IOC_RESVSP:
+- case XFS_IOC_UNRESVSP:
+- case XFS_IOC_ALLOCSP64:
+- case XFS_IOC_FREESP64:
+- case XFS_IOC_RESVSP64:
+- case XFS_IOC_UNRESVSP64:
+- /*
+- * Only allow the sys admin to reserve space unless
+- * unwritten extents are enabled.
+- */
+- if (!xfs_sb_version_hasextflgbit(&mp->m_sb) &&
+- !capable(CAP_SYS_ADMIN))
+- return -EPERM;
+-
+- return xfs_ioc_space(ip, inode, filp, ioflags, cmd, arg);
+-
+- case XFS_IOC_DIOINFO: {
+- struct dioattr da;
+- xfs_buftarg_t *target =
+- XFS_IS_REALTIME_INODE(ip) ?
+- mp->m_rtdev_targp : mp->m_ddev_targp;
+-
+- da.d_mem = da.d_miniosz = 1 << target->bt_sshift;
+- da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1);
+-
+- if (copy_to_user(arg, &da, sizeof(da)))
+- return -XFS_ERROR(EFAULT);
+- return 0;
+- }
+-
+- case XFS_IOC_FSBULKSTAT_SINGLE:
+- case XFS_IOC_FSBULKSTAT:
+- case XFS_IOC_FSINUMBERS:
+- return xfs_ioc_bulkstat(mp, cmd, arg);
+-
+- case XFS_IOC_FSGEOMETRY_V1:
+- return xfs_ioc_fsgeometry_v1(mp, arg);
+-
+- case XFS_IOC_FSGEOMETRY:
+- return xfs_ioc_fsgeometry(mp, arg);
+-
+- case XFS_IOC_GETVERSION:
+- return put_user(inode->i_generation, (int __user *)arg);
+-
+- case XFS_IOC_FSGETXATTR:
+- return xfs_ioc_fsgetxattr(ip, 0, arg);
+- case XFS_IOC_FSGETXATTRA:
+- return xfs_ioc_fsgetxattr(ip, 1, arg);
+- case XFS_IOC_GETXFLAGS:
+- case XFS_IOC_SETXFLAGS:
+- case XFS_IOC_FSSETXATTR:
+- return xfs_ioc_xattr(ip, filp, cmd, arg);
+-
+- case XFS_IOC_FSSETDM: {
+- struct fsdmidata dmi;
+-
+- if (copy_from_user(&dmi, arg, sizeof(dmi)))
+- return -XFS_ERROR(EFAULT);
+-
+- error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask,
+- dmi.fsd_dmstate);
+- return -error;
+- }
+-
+- case XFS_IOC_GETBMAP:
+- case XFS_IOC_GETBMAPA:
+- return xfs_ioc_getbmap(ip, ioflags, cmd, arg);
+-
+- case XFS_IOC_GETBMAPX:
+- return xfs_ioc_getbmapx(ip, arg);
+-
+- case XFS_IOC_FD_TO_HANDLE:
+- case XFS_IOC_PATH_TO_HANDLE:
+- case XFS_IOC_PATH_TO_FSHANDLE:
+- return xfs_find_handle(cmd, arg);
+-
+- case XFS_IOC_OPEN_BY_HANDLE:
+- return xfs_open_by_handle(mp, arg, filp, inode);
+-
+- case XFS_IOC_FSSETDM_BY_HANDLE:
+- return xfs_fssetdm_by_handle(mp, arg, inode);
+-
+- case XFS_IOC_READLINK_BY_HANDLE:
+- return xfs_readlink_by_handle(mp, arg, inode);
+-
+- case XFS_IOC_ATTRLIST_BY_HANDLE:
+- return xfs_attrlist_by_handle(mp, arg, inode);
+-
+- case XFS_IOC_ATTRMULTI_BY_HANDLE:
+- return xfs_attrmulti_by_handle(mp, arg, inode);
+-
+- case XFS_IOC_SWAPEXT: {
+- error = xfs_swapext((struct xfs_swapext __user *)arg);
+- return -error;
+- }
+-
+- case XFS_IOC_FSCOUNTS: {
+- xfs_fsop_counts_t out;
+-
+- error = xfs_fs_counts(mp, &out);
+- if (error)
+- return -error;
+-
+- if (copy_to_user(arg, &out, sizeof(out)))
+- return -XFS_ERROR(EFAULT);
+- return 0;
+- }
+-
+- case XFS_IOC_SET_RESBLKS: {
+- xfs_fsop_resblks_t inout;
+- __uint64_t in;
+-
+- if (!capable(CAP_SYS_ADMIN))
+- return -EPERM;
+-
+- if (copy_from_user(&inout, arg, sizeof(inout)))
+- return -XFS_ERROR(EFAULT);
+-
+- /* input parameter is passed in resblks field of structure */
+- in = inout.resblks;
+- error = xfs_reserve_blocks(mp, &in, &inout);
+- if (error)
+- return -error;
+-
+- if (copy_to_user(arg, &inout, sizeof(inout)))
+- return -XFS_ERROR(EFAULT);
+- return 0;
+- }
+-
+- case XFS_IOC_GET_RESBLKS: {
+- xfs_fsop_resblks_t out;
+-
+- if (!capable(CAP_SYS_ADMIN))
+- return -EPERM;
+-
+- error = xfs_reserve_blocks(mp, NULL, &out);
+- if (error)
+- return -error;
+-
+- if (copy_to_user(arg, &out, sizeof(out)))
+- return -XFS_ERROR(EFAULT);
+-
+- return 0;
+- }
+-
+- case XFS_IOC_FSGROWFSDATA: {
+- xfs_growfs_data_t in;
+-
+- if (!capable(CAP_SYS_ADMIN))
+- return -EPERM;
+-
+- if (copy_from_user(&in, arg, sizeof(in)))
+- return -XFS_ERROR(EFAULT);
+-
+- error = xfs_growfs_data(mp, &in);
+- return -error;
+- }
+-
+- case XFS_IOC_FSGROWFSLOG: {
+- xfs_growfs_log_t in;
+-
+- if (!capable(CAP_SYS_ADMIN))
+- return -EPERM;
+-
+- if (copy_from_user(&in, arg, sizeof(in)))
+- return -XFS_ERROR(EFAULT);
+-
+- error = xfs_growfs_log(mp, &in);
+- return -error;
+- }
+-
+- case XFS_IOC_FSGROWFSRT: {
+- xfs_growfs_rt_t in;
+-
+- if (!capable(CAP_SYS_ADMIN))
+- return -EPERM;
+-
+- if (copy_from_user(&in, arg, sizeof(in)))
+- return -XFS_ERROR(EFAULT);
+-
+- error = xfs_growfs_rt(mp, &in);
+- return -error;
+- }
+-
+- case XFS_IOC_FREEZE:
+- if (!capable(CAP_SYS_ADMIN))
+- return -EPERM;
+-
+- if (inode->i_sb->s_frozen == SB_UNFROZEN)
+- freeze_bdev(inode->i_sb->s_bdev);
+- return 0;
+-
+- case XFS_IOC_THAW:
+- if (!capable(CAP_SYS_ADMIN))
+- return -EPERM;
+- if (inode->i_sb->s_frozen != SB_UNFROZEN)
+- thaw_bdev(inode->i_sb->s_bdev, inode->i_sb);
+- return 0;
+-
+- case XFS_IOC_GOINGDOWN: {
+- __uint32_t in;
+-
+- if (!capable(CAP_SYS_ADMIN))
+- return -EPERM;
+-
+- if (get_user(in, (__uint32_t __user *)arg))
+- return -XFS_ERROR(EFAULT);
+-
+- error = xfs_fs_goingdown(mp, in);
+- return -error;
+- }
+-
+- case XFS_IOC_ERROR_INJECTION: {
+- xfs_error_injection_t in;
+-
+- if (!capable(CAP_SYS_ADMIN))
+- return -EPERM;
+-
+- if (copy_from_user(&in, arg, sizeof(in)))
+- return -XFS_ERROR(EFAULT);
+-
+- error = xfs_errortag_add(in.errtag, mp);
+- return -error;
+- }
+-
+- case XFS_IOC_ERROR_CLEARALL:
+- if (!capable(CAP_SYS_ADMIN))
+- return -EPERM;
+-
+- error = xfs_errortag_clearall(mp, 1);
+- return -error;
+-
+- default:
+- return -ENOTTY;
+- }
+-}
+-
+ STATIC int
+ xfs_ioc_space(
+ struct xfs_inode *ip,
+@@ -1179,85 +876,85 @@ xfs_ioc_fsgetxattr(
+ }
+
+ STATIC int
+-xfs_ioc_xattr(
++xfs_ioc_fssetxattr(
+ xfs_inode_t *ip,
+ struct file *filp,
+- unsigned int cmd,
+ void __user *arg)
+ {
+ struct fsxattr fa;
+ struct bhv_vattr *vattr;
+- int error = 0;
++ int error;
+ int attr_flags;
+- unsigned int flags;
++
++ if (copy_from_user(&fa, arg, sizeof(fa)))
++ return -EFAULT;
+
+ vattr = kmalloc(sizeof(*vattr), GFP_KERNEL);
+ if (unlikely(!vattr))
+ return -ENOMEM;
+
+- switch (cmd) {
+- case XFS_IOC_FSSETXATTR: {
+- if (copy_from_user(&fa, arg, sizeof(fa))) {
+- error = -EFAULT;
+- break;
+- }
++ attr_flags = 0;
++ if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
++ attr_flags |= ATTR_NONBLOCK;
+
+- attr_flags = 0;
+- if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
+- attr_flags |= ATTR_NONBLOCK;
++ vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | XFS_AT_PROJID;
++ vattr->va_xflags = fa.fsx_xflags;
++ vattr->va_extsize = fa.fsx_extsize;
++ vattr->va_projid = fa.fsx_projid;
+
+- vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | XFS_AT_PROJID;
+- vattr->va_xflags = fa.fsx_xflags;
+- vattr->va_extsize = fa.fsx_extsize;
+- vattr->va_projid = fa.fsx_projid;
++ error = -xfs_setattr(ip, vattr, attr_flags, NULL);
++ if (!error)
++ vn_revalidate(XFS_ITOV(ip)); /* update flags */
++ kfree(vattr);
++ return 0;
++}
+
+- error = xfs_setattr(ip, vattr, attr_flags, NULL);
+- if (likely(!error))
+- vn_revalidate(XFS_ITOV(ip)); /* update flags */
+- error = -error;
+- break;
+- }
++STATIC int
++xfs_ioc_getxflags(
++ xfs_inode_t *ip,
++ void __user *arg)
++{
++ unsigned int flags;
+
+- case XFS_IOC_GETXFLAGS: {
+- flags = xfs_di2lxflags(ip->i_d.di_flags);
+- if (copy_to_user(arg, &flags, sizeof(flags)))
+- error = -EFAULT;
+- break;
+- }
++ flags = xfs_di2lxflags(ip->i_d.di_flags);
++ if (copy_to_user(arg, &flags, sizeof(flags)))
++ return -EFAULT;
++ return 0;
++}
+
+- case XFS_IOC_SETXFLAGS: {
+- if (copy_from_user(&flags, arg, sizeof(flags))) {
+- error = -EFAULT;
+- break;
+- }
++STATIC int
++xfs_ioc_setxflags(
++ xfs_inode_t *ip,
++ struct file *filp,
++ void __user *arg)
++{
++ struct bhv_vattr *vattr;
++ unsigned int flags;
++ int attr_flags;
++ int error;
+
+- if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
+- FS_NOATIME_FL | FS_NODUMP_FL | \
+- FS_SYNC_FL)) {
+- error = -EOPNOTSUPP;
+- break;
+- }
++ if (copy_from_user(&flags, arg, sizeof(flags)))
++ return -EFAULT;
+
+- attr_flags = 0;
+- if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
+- attr_flags |= ATTR_NONBLOCK;
++ if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
++ FS_NOATIME_FL | FS_NODUMP_FL | \
++ FS_SYNC_FL))
++ return -EOPNOTSUPP;
+
+- vattr->va_mask = XFS_AT_XFLAGS;
+- vattr->va_xflags = xfs_merge_ioc_xflags(flags,
+- xfs_ip2xflags(ip));
++ vattr = kmalloc(sizeof(*vattr), GFP_KERNEL);
++ if (unlikely(!vattr))
++ return -ENOMEM;
+
+- error = xfs_setattr(ip, vattr, attr_flags, NULL);
+- if (likely(!error))
+- vn_revalidate(XFS_ITOV(ip)); /* update flags */
+- error = -error;
+- break;
+- }
++ attr_flags = 0;
++ if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
++ attr_flags |= ATTR_NONBLOCK;
+
+- default:
+- error = -ENOTTY;
+- break;
+- }
++ vattr->va_mask = XFS_AT_XFLAGS;
++ vattr->va_xflags = xfs_merge_ioc_xflags(flags, xfs_ip2xflags(ip));
+
++ error = -xfs_setattr(ip, vattr, attr_flags, NULL);
++ if (likely(!error))
++ vn_revalidate(XFS_ITOV(ip)); /* update flags */
+ kfree(vattr);
+ return error;
+ }
+@@ -1332,3 +1029,259 @@ xfs_ioc_getbmapx(
+
+ return 0;
+ }
++
++int
++xfs_ioctl(
++ xfs_inode_t *ip,
++ struct file *filp,
++ int ioflags,
++ unsigned int cmd,
++ void __user *arg)
++{
++ struct inode *inode = filp->f_path.dentry->d_inode;
++ xfs_mount_t *mp = ip->i_mount;
++ int error;
++
++ xfs_itrace_entry(XFS_I(inode));
++ switch (cmd) {
++
++ case XFS_IOC_ALLOCSP:
++ case XFS_IOC_FREESP:
++ case XFS_IOC_RESVSP:
++ case XFS_IOC_UNRESVSP:
++ case XFS_IOC_ALLOCSP64:
++ case XFS_IOC_FREESP64:
++ case XFS_IOC_RESVSP64:
++ case XFS_IOC_UNRESVSP64:
++ /*
++ * Only allow the sys admin to reserve space unless
++ * unwritten extents are enabled.
++ */
++ if (!xfs_sb_version_hasextflgbit(&mp->m_sb) &&
++ !capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
++ return xfs_ioc_space(ip, inode, filp, ioflags, cmd, arg);
++
++ case XFS_IOC_DIOINFO: {
++ struct dioattr da;
++ xfs_buftarg_t *target =
++ XFS_IS_REALTIME_INODE(ip) ?
++ mp->m_rtdev_targp : mp->m_ddev_targp;
++
++ da.d_mem = da.d_miniosz = 1 << target->bt_sshift;
++ da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1);
++
++ if (copy_to_user(arg, &da, sizeof(da)))
++ return -XFS_ERROR(EFAULT);
++ return 0;
++ }
++
++ case XFS_IOC_FSBULKSTAT_SINGLE:
++ case XFS_IOC_FSBULKSTAT:
++ case XFS_IOC_FSINUMBERS:
++ return xfs_ioc_bulkstat(mp, cmd, arg);
++
++ case XFS_IOC_FSGEOMETRY_V1:
++ return xfs_ioc_fsgeometry_v1(mp, arg);
++
++ case XFS_IOC_FSGEOMETRY:
++ return xfs_ioc_fsgeometry(mp, arg);
++
++ case XFS_IOC_GETVERSION:
++ return put_user(inode->i_generation, (int __user *)arg);
++
++ case XFS_IOC_FSGETXATTR:
++ return xfs_ioc_fsgetxattr(ip, 0, arg);
++ case XFS_IOC_FSGETXATTRA:
++ return xfs_ioc_fsgetxattr(ip, 1, arg);
++ case XFS_IOC_FSSETXATTR:
++ return xfs_ioc_fssetxattr(ip, filp, arg);
++ case XFS_IOC_GETXFLAGS:
++ return xfs_ioc_getxflags(ip, arg);
++ case XFS_IOC_SETXFLAGS:
++ return xfs_ioc_setxflags(ip, filp, arg);
++
++ case XFS_IOC_FSSETDM: {
++ struct fsdmidata dmi;
++
++ if (copy_from_user(&dmi, arg, sizeof(dmi)))
++ return -XFS_ERROR(EFAULT);
++
++ error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask,
++ dmi.fsd_dmstate);
++ return -error;
++ }
++
++ case XFS_IOC_GETBMAP:
++ case XFS_IOC_GETBMAPA:
++ return xfs_ioc_getbmap(ip, ioflags, cmd, arg);
++
++ case XFS_IOC_GETBMAPX:
++ return xfs_ioc_getbmapx(ip, arg);
++
++ case XFS_IOC_FD_TO_HANDLE:
++ case XFS_IOC_PATH_TO_HANDLE:
++ case XFS_IOC_PATH_TO_FSHANDLE:
++ return xfs_find_handle(cmd, arg);
++
++ case XFS_IOC_OPEN_BY_HANDLE:
++ return xfs_open_by_handle(mp, arg, filp, inode);
++
++ case XFS_IOC_FSSETDM_BY_HANDLE:
++ return xfs_fssetdm_by_handle(mp, arg, inode);
++
++ case XFS_IOC_READLINK_BY_HANDLE:
++ return xfs_readlink_by_handle(mp, arg, inode);
++
++ case XFS_IOC_ATTRLIST_BY_HANDLE:
++ return xfs_attrlist_by_handle(mp, arg, inode);
++
++ case XFS_IOC_ATTRMULTI_BY_HANDLE:
++ return xfs_attrmulti_by_handle(mp, arg, filp, inode);
++
++ case XFS_IOC_SWAPEXT: {
++ error = xfs_swapext((struct xfs_swapext __user *)arg);
++ return -error;
++ }
++
++ case XFS_IOC_FSCOUNTS: {
++ xfs_fsop_counts_t out;
++
++ error = xfs_fs_counts(mp, &out);
++ if (error)
++ return -error;
++
++ if (copy_to_user(arg, &out, sizeof(out)))
++ return -XFS_ERROR(EFAULT);
++ return 0;
++ }
++
++ case XFS_IOC_SET_RESBLKS: {
++ xfs_fsop_resblks_t inout;
++ __uint64_t in;
++
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
++ if (copy_from_user(&inout, arg, sizeof(inout)))
++ return -XFS_ERROR(EFAULT);
++
++ /* input parameter is passed in resblks field of structure */
++ in = inout.resblks;
++ error = xfs_reserve_blocks(mp, &in, &inout);
++ if (error)
++ return -error;
++
++ if (copy_to_user(arg, &inout, sizeof(inout)))
++ return -XFS_ERROR(EFAULT);
++ return 0;
++ }
++
++ case XFS_IOC_GET_RESBLKS: {
++ xfs_fsop_resblks_t out;
++
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
++ error = xfs_reserve_blocks(mp, NULL, &out);
++ if (error)
++ return -error;
++
++ if (copy_to_user(arg, &out, sizeof(out)))
++ return -XFS_ERROR(EFAULT);
++
++ return 0;
++ }
++
++ case XFS_IOC_FSGROWFSDATA: {
++ xfs_growfs_data_t in;
++
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
++ if (copy_from_user(&in, arg, sizeof(in)))
++ return -XFS_ERROR(EFAULT);
++
++ error = xfs_growfs_data(mp, &in);
++ return -error;
++ }
++
++ case XFS_IOC_FSGROWFSLOG: {
++ xfs_growfs_log_t in;
++
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
++ if (copy_from_user(&in, arg, sizeof(in)))
++ return -XFS_ERROR(EFAULT);
++
++ error = xfs_growfs_log(mp, &in);
++ return -error;
++ }
++
++ case XFS_IOC_FSGROWFSRT: {
++ xfs_growfs_rt_t in;
++
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
++ if (copy_from_user(&in, arg, sizeof(in)))
++ return -XFS_ERROR(EFAULT);
++
++ error = xfs_growfs_rt(mp, &in);
++ return -error;
++ }
++
++ case XFS_IOC_FREEZE:
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
++ if (inode->i_sb->s_frozen == SB_UNFROZEN)
++ freeze_bdev(inode->i_sb->s_bdev);
++ return 0;
++
++ case XFS_IOC_THAW:
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++ if (inode->i_sb->s_frozen != SB_UNFROZEN)
++ thaw_bdev(inode->i_sb->s_bdev, inode->i_sb);
++ return 0;
++
++ case XFS_IOC_GOINGDOWN: {
++ __uint32_t in;
++
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
++ if (get_user(in, (__uint32_t __user *)arg))
++ return -XFS_ERROR(EFAULT);
++
++ error = xfs_fs_goingdown(mp, in);
++ return -error;
++ }
++
++ case XFS_IOC_ERROR_INJECTION: {
++ xfs_error_injection_t in;
++
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
++ if (copy_from_user(&in, arg, sizeof(in)))
++ return -XFS_ERROR(EFAULT);
++
++ error = xfs_errortag_add(in.errtag, mp);
++ return -error;
++ }
++
++ case XFS_IOC_ERROR_CLEARALL:
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
++ error = xfs_errortag_clearall(mp, 1);
++ return -error;
++
++ default:
++ return -ENOTTY;
++ }
++}
+diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
+index cc4abd3..a1237da 100644
+--- a/fs/xfs/linux-2.6/xfs_iops.c
++++ b/fs/xfs/linux-2.6/xfs_iops.c
+@@ -62,12 +62,11 @@ void
+ xfs_synchronize_atime(
+ xfs_inode_t *ip)
+ {
+- bhv_vnode_t *vp;
++ struct inode *inode = ip->i_vnode;
+
+- vp = XFS_ITOV_NULL(ip);
+- if (vp) {
+- ip->i_d.di_atime.t_sec = (__int32_t)vp->i_atime.tv_sec;
+- ip->i_d.di_atime.t_nsec = (__int32_t)vp->i_atime.tv_nsec;
++ if (inode) {
++ ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec;
++ ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec;
+ }
+ }
+
+@@ -80,11 +79,10 @@ void
+ xfs_mark_inode_dirty_sync(
+ xfs_inode_t *ip)
+ {
+- bhv_vnode_t *vp;
++ struct inode *inode = ip->i_vnode;
+
+- vp = XFS_ITOV_NULL(ip);
+- if (vp)
+- mark_inode_dirty_sync(vn_to_inode(vp));
++ if (inode)
++ mark_inode_dirty_sync(inode);
+ }
+
+ /*
+@@ -157,13 +155,6 @@ xfs_ichgtime_fast(
+ */
+ ASSERT((flags & XFS_ICHGTIME_ACC) == 0);
+
+- /*
+- * We're not supposed to change timestamps in readonly-mounted
+- * filesystems. Throw it away if anyone asks us.
+- */
+- if (unlikely(IS_RDONLY(inode)))
+- return;
+-
+ if (flags & XFS_ICHGTIME_MOD) {
+ tvp = &inode->i_mtime;
+ ip->i_d.di_mtime.t_sec = (__int32_t)tvp->tv_sec;
+@@ -215,66 +206,62 @@ xfs_validate_fields(
+ */
+ STATIC int
+ xfs_init_security(
+- bhv_vnode_t *vp,
++ struct inode *inode,
+ struct inode *dir)
+ {
+- struct inode *ip = vn_to_inode(vp);
++ struct xfs_inode *ip = XFS_I(inode);
+ size_t length;
+ void *value;
+ char *name;
+ int error;
+
+- error = security_inode_init_security(ip, dir, &name, &value, &length);
++ error = security_inode_init_security(inode, dir, &name,
++ &value, &length);
+ if (error) {
+ if (error == -EOPNOTSUPP)
+ return 0;
+ return -error;
+ }
+
+- error = xfs_attr_set(XFS_I(ip), name, value,
+- length, ATTR_SECURE);
++ error = xfs_attr_set(ip, name, value, length, ATTR_SECURE);
+ if (!error)
+- xfs_iflags_set(XFS_I(ip), XFS_IMODIFIED);
++ xfs_iflags_set(ip, XFS_IMODIFIED);
+
+ kfree(name);
+ kfree(value);
+ return error;
+ }
+
+-/*
+- * Determine whether a process has a valid fs_struct (kernel daemons
+- * like knfsd don't have an fs_struct).
+- *
+- * XXX(hch): nfsd is broken, better fix it instead.
+- */
+-STATIC_INLINE int
+-xfs_has_fs_struct(struct task_struct *task)
++static void
++xfs_dentry_to_name(
++ struct xfs_name *namep,
++ struct dentry *dentry)
+ {
+- return (task->fs != init_task.fs);
++ namep->name = dentry->d_name.name;
++ namep->len = dentry->d_name.len;
+ }
+
+ STATIC void
+ xfs_cleanup_inode(
+ struct inode *dir,
+- bhv_vnode_t *vp,
++ struct inode *inode,
+ struct dentry *dentry,
+ int mode)
+ {
+- struct dentry teardown = {};
++ struct xfs_name teardown;
+
+ /* Oh, the horror.
+ * If we can't add the ACL or we fail in
+ * xfs_init_security we must back out.
+ * ENOSPC can hit here, among other things.
+ */
+- teardown.d_inode = vn_to_inode(vp);
+- teardown.d_name = dentry->d_name;
++ xfs_dentry_to_name(&teardown, dentry);
+
+ if (S_ISDIR(mode))
+- xfs_rmdir(XFS_I(dir), &teardown);
++ xfs_rmdir(XFS_I(dir), &teardown, XFS_I(inode));
+ else
+- xfs_remove(XFS_I(dir), &teardown);
+- VN_RELE(vp);
++ xfs_remove(XFS_I(dir), &teardown, XFS_I(inode));
++ iput(inode);
+ }
+
+ STATIC int
+@@ -284,9 +271,10 @@ xfs_vn_mknod(
+ int mode,
+ dev_t rdev)
+ {
+- struct inode *ip;
+- bhv_vnode_t *vp = NULL, *dvp = vn_from_inode(dir);
++ struct inode *inode;
++ struct xfs_inode *ip = NULL;
+ xfs_acl_t *default_acl = NULL;
++ struct xfs_name name;
+ attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS;
+ int error;
+
+@@ -297,59 +285,67 @@ xfs_vn_mknod(
+ if (unlikely(!sysv_valid_dev(rdev) || MAJOR(rdev) & ~0x1ff))
+ return -EINVAL;
+
+- if (unlikely(test_default_acl && test_default_acl(dvp))) {
++ if (test_default_acl && test_default_acl(dir)) {
+ if (!_ACL_ALLOC(default_acl)) {
+ return -ENOMEM;
+ }
+- if (!_ACL_GET_DEFAULT(dvp, default_acl)) {
++ if (!_ACL_GET_DEFAULT(dir, default_acl)) {
+ _ACL_FREE(default_acl);
+ default_acl = NULL;
+ }
+ }
+
+- if (IS_POSIXACL(dir) && !default_acl && xfs_has_fs_struct(current))
++ xfs_dentry_to_name(&name, dentry);
++
++ if (IS_POSIXACL(dir) && !default_acl)
+ mode &= ~current->fs->umask;
+
+ switch (mode & S_IFMT) {
+- case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK:
++ case S_IFCHR:
++ case S_IFBLK:
++ case S_IFIFO:
++ case S_IFSOCK:
+ rdev = sysv_encode_dev(rdev);
+ case S_IFREG:
+- error = xfs_create(XFS_I(dir), dentry, mode, rdev, &vp, NULL);
++ error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip, NULL);
+ break;
+ case S_IFDIR:
+- error = xfs_mkdir(XFS_I(dir), dentry, mode, &vp, NULL);
++ error = xfs_mkdir(XFS_I(dir), &name, mode, &ip, NULL);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+
+- if (unlikely(!error)) {
+- error = xfs_init_security(vp, dir);
+- if (error)
+- xfs_cleanup_inode(dir, vp, dentry, mode);
+- }
++ if (unlikely(error))
++ goto out_free_acl;
+
+- if (unlikely(default_acl)) {
+- if (!error) {
+- error = _ACL_INHERIT(vp, mode, default_acl);
+- if (!error)
+- xfs_iflags_set(XFS_I(vp), XFS_IMODIFIED);
+- else
+- xfs_cleanup_inode(dir, vp, dentry, mode);
+- }
++ inode = ip->i_vnode;
++
++ error = xfs_init_security(inode, dir);
++ if (unlikely(error))
++ goto out_cleanup_inode;
++
++ if (default_acl) {
++ error = _ACL_INHERIT(inode, mode, default_acl);
++ if (unlikely(error))
++ goto out_cleanup_inode;
++ xfs_iflags_set(ip, XFS_IMODIFIED);
+ _ACL_FREE(default_acl);
+ }
+
+- if (likely(!error)) {
+- ASSERT(vp);
+- ip = vn_to_inode(vp);
+
+- if (S_ISDIR(mode))
+- xfs_validate_fields(ip);
+- d_instantiate(dentry, ip);
+- xfs_validate_fields(dir);
+- }
++ if (S_ISDIR(mode))
++ xfs_validate_fields(inode);
++ d_instantiate(dentry, inode);
++ xfs_validate_fields(dir);
++ return -error;
++
++ out_cleanup_inode:
++ xfs_cleanup_inode(dir, inode, dentry, mode);
++ out_free_acl:
++ if (default_acl)
++ _ACL_FREE(default_acl);
+ return -error;
+ }
+
+@@ -378,13 +374,15 @@ xfs_vn_lookup(
+ struct dentry *dentry,
+ struct nameidata *nd)
+ {
+- bhv_vnode_t *cvp;
++ struct xfs_inode *cip;
++ struct xfs_name name;
+ int error;
+
+ if (dentry->d_name.len >= MAXNAMELEN)
+ return ERR_PTR(-ENAMETOOLONG);
+
+- error = xfs_lookup(XFS_I(dir), dentry, &cvp);
++ xfs_dentry_to_name(&name, dentry);
++ error = xfs_lookup(XFS_I(dir), &name, &cip);
+ if (unlikely(error)) {
+ if (unlikely(error != ENOENT))
+ return ERR_PTR(-error);
+@@ -392,7 +390,7 @@ xfs_vn_lookup(
+ return NULL;
+ }
+
+- return d_splice_alias(vn_to_inode(cvp), dentry);
++ return d_splice_alias(cip->i_vnode, dentry);
+ }
+
+ STATIC int
+@@ -401,23 +399,24 @@ xfs_vn_link(
+ struct inode *dir,
+ struct dentry *dentry)
+ {
+- struct inode *ip; /* inode of guy being linked to */
+- bhv_vnode_t *vp; /* vp of name being linked */
++ struct inode *inode; /* inode of guy being linked to */
++ struct xfs_name name;
+ int error;
+
+- ip = old_dentry->d_inode; /* inode being linked to */
+- vp = vn_from_inode(ip);
++ inode = old_dentry->d_inode;
++ xfs_dentry_to_name(&name, dentry);
+
+- VN_HOLD(vp);
+- error = xfs_link(XFS_I(dir), vp, dentry);
++ igrab(inode);
++ error = xfs_link(XFS_I(dir), XFS_I(inode), &name);
+ if (unlikely(error)) {
+- VN_RELE(vp);
+- } else {
+- xfs_iflags_set(XFS_I(dir), XFS_IMODIFIED);
+- xfs_validate_fields(ip);
+- d_instantiate(dentry, ip);
++ iput(inode);
++ return -error;
+ }
+- return -error;
++
++ xfs_iflags_set(XFS_I(dir), XFS_IMODIFIED);
++ xfs_validate_fields(inode);
++ d_instantiate(dentry, inode);
++ return 0;
+ }
+
+ STATIC int
+@@ -426,11 +425,13 @@ xfs_vn_unlink(
+ struct dentry *dentry)
+ {
+ struct inode *inode;
++ struct xfs_name name;
+ int error;
+
+ inode = dentry->d_inode;
++ xfs_dentry_to_name(&name, dentry);
+
+- error = xfs_remove(XFS_I(dir), dentry);
++ error = xfs_remove(XFS_I(dir), &name, XFS_I(inode));
+ if (likely(!error)) {
+ xfs_validate_fields(dir); /* size needs update */
+ xfs_validate_fields(inode);
+@@ -444,29 +445,34 @@ xfs_vn_symlink(
+ struct dentry *dentry,
+ const char *symname)
+ {
+- struct inode *ip;
+- bhv_vnode_t *cvp; /* used to lookup symlink to put in dentry */
++ struct inode *inode;
++ struct xfs_inode *cip = NULL;
++ struct xfs_name name;
+ int error;
+ mode_t mode;
+
+- cvp = NULL;
+-
+ mode = S_IFLNK |
+ (irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO);
++ xfs_dentry_to_name(&name, dentry);
+
+- error = xfs_symlink(XFS_I(dir), dentry, (char *)symname, mode,
+- &cvp, NULL);
+- if (likely(!error && cvp)) {
+- error = xfs_init_security(cvp, dir);
+- if (likely(!error)) {
+- ip = vn_to_inode(cvp);
+- d_instantiate(dentry, ip);
+- xfs_validate_fields(dir);
+- xfs_validate_fields(ip);
+- } else {
+- xfs_cleanup_inode(dir, cvp, dentry, 0);
+- }
+- }
++ error = xfs_symlink(XFS_I(dir), &name, symname, mode, &cip, NULL);
++ if (unlikely(error))
++ goto out;
++
++ inode = cip->i_vnode;
++
++ error = xfs_init_security(inode, dir);
++ if (unlikely(error))
++ goto out_cleanup_inode;
++
++ d_instantiate(dentry, inode);
++ xfs_validate_fields(dir);
++ xfs_validate_fields(inode);
++ return 0;
++
++ out_cleanup_inode:
++ xfs_cleanup_inode(dir, inode, dentry, 0);
++ out:
+ return -error;
+ }
+
+@@ -476,9 +482,12 @@ xfs_vn_rmdir(
+ struct dentry *dentry)
+ {
+ struct inode *inode = dentry->d_inode;
++ struct xfs_name name;
+ int error;
+
+- error = xfs_rmdir(XFS_I(dir), dentry);
++ xfs_dentry_to_name(&name, dentry);
++
++ error = xfs_rmdir(XFS_I(dir), &name, XFS_I(inode));
+ if (likely(!error)) {
+ xfs_validate_fields(inode);
+ xfs_validate_fields(dir);
+@@ -494,12 +503,15 @@ xfs_vn_rename(
+ struct dentry *ndentry)
+ {
+ struct inode *new_inode = ndentry->d_inode;
+- bhv_vnode_t *tvp; /* target directory */
++ struct xfs_name oname;
++ struct xfs_name nname;
+ int error;
+
+- tvp = vn_from_inode(ndir);
++ xfs_dentry_to_name(&oname, odentry);
++ xfs_dentry_to_name(&nname, ndentry);
+
+- error = xfs_rename(XFS_I(odir), odentry, tvp, ndentry);
++ error = xfs_rename(XFS_I(odir), &oname, XFS_I(odentry->d_inode),
++ XFS_I(ndir), &nname);
+ if (likely(!error)) {
+ if (new_inode)
+ xfs_validate_fields(new_inode);
+@@ -700,11 +712,19 @@ xfs_vn_setattr(
+ return -error;
+ }
+
++/*
++ * block_truncate_page can return an error, but we can't propagate it
++ * at all here. Leave a complaint + stack trace in the syslog because
++ * this could be bad. If it is bad, we need to propagate the error further.
++ */
+ STATIC void
+ xfs_vn_truncate(
+ struct inode *inode)
+ {
+- block_truncate_page(inode->i_mapping, inode->i_size, xfs_get_blocks);
++ int error;
++ error = block_truncate_page(inode->i_mapping, inode->i_size,
++ xfs_get_blocks);
++ WARN_ON(error);
+ }
+
+ STATIC int
+diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
+index 3ca39c4..e514332 100644
+--- a/fs/xfs/linux-2.6/xfs_linux.h
++++ b/fs/xfs/linux-2.6/xfs_linux.h
+@@ -99,7 +99,6 @@
+ /*
+ * Feature macros (disable/enable)
+ */
+-#undef HAVE_REFCACHE /* reference cache not needed for NFS in 2.6 */
+ #define HAVE_SPLICE /* a splice(2) exists in 2.6, but not in 2.4 */
+ #ifdef CONFIG_SMP
+ #define HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */
+diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
+index 1663533..1ebd800 100644
+--- a/fs/xfs/linux-2.6/xfs_lrw.c
++++ b/fs/xfs/linux-2.6/xfs_lrw.c
+@@ -51,6 +51,7 @@
+ #include "xfs_vnodeops.h"
+
+ #include <linux/capability.h>
++#include <linux/mount.h>
+ #include <linux/writeback.h>
+
+
+@@ -176,7 +177,6 @@ xfs_read(
+ {
+ struct file *file = iocb->ki_filp;
+ struct inode *inode = file->f_mapping->host;
+- bhv_vnode_t *vp = XFS_ITOV(ip);
+ xfs_mount_t *mp = ip->i_mount;
+ size_t size = 0;
+ ssize_t ret = 0;
+@@ -228,11 +228,11 @@ xfs_read(
+ xfs_ilock(ip, XFS_IOLOCK_SHARED);
+
+ if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) {
+- bhv_vrwlock_t locktype = VRWLOCK_READ;
+ int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
++ int iolock = XFS_IOLOCK_SHARED;
+
+- ret = -XFS_SEND_DATA(mp, DM_EVENT_READ, vp, *offset, size,
+- dmflags, &locktype);
++ ret = -XFS_SEND_DATA(mp, DM_EVENT_READ, ip, *offset, size,
++ dmflags, &iolock);
+ if (ret) {
+ xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+ if (unlikely(ioflags & IO_ISDIRECT))
+@@ -242,7 +242,7 @@ xfs_read(
+ }
+
+ if (unlikely(ioflags & IO_ISDIRECT)) {
+- if (VN_CACHED(vp))
++ if (inode->i_mapping->nrpages)
+ ret = xfs_flushinval_pages(ip, (*offset & PAGE_CACHE_MASK),
+ -1, FI_REMAPF_LOCKED);
+ mutex_unlock(&inode->i_mutex);
+@@ -276,7 +276,6 @@ xfs_splice_read(
+ int flags,
+ int ioflags)
+ {
+- bhv_vnode_t *vp = XFS_ITOV(ip);
+ xfs_mount_t *mp = ip->i_mount;
+ ssize_t ret;
+
+@@ -287,11 +286,11 @@ xfs_splice_read(
+ xfs_ilock(ip, XFS_IOLOCK_SHARED);
+
+ if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) {
+- bhv_vrwlock_t locktype = VRWLOCK_READ;
++ int iolock = XFS_IOLOCK_SHARED;
+ int error;
+
+- error = XFS_SEND_DATA(mp, DM_EVENT_READ, vp, *ppos, count,
+- FILP_DELAY_FLAG(infilp), &locktype);
++ error = XFS_SEND_DATA(mp, DM_EVENT_READ, ip, *ppos, count,
++ FILP_DELAY_FLAG(infilp), &iolock);
+ if (error) {
+ xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+ return -error;
+@@ -317,7 +316,6 @@ xfs_splice_write(
+ int flags,
+ int ioflags)
+ {
+- bhv_vnode_t *vp = XFS_ITOV(ip);
+ xfs_mount_t *mp = ip->i_mount;
+ ssize_t ret;
+ struct inode *inode = outfilp->f_mapping->host;
+@@ -330,11 +328,11 @@ xfs_splice_write(
+ xfs_ilock(ip, XFS_IOLOCK_EXCL);
+
+ if (DM_EVENT_ENABLED(ip, DM_EVENT_WRITE) && !(ioflags & IO_INVIS)) {
+- bhv_vrwlock_t locktype = VRWLOCK_WRITE;
++ int iolock = XFS_IOLOCK_EXCL;
+ int error;
+
+- error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, vp, *ppos, count,
+- FILP_DELAY_FLAG(outfilp), &locktype);
++ error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, ip, *ppos, count,
++ FILP_DELAY_FLAG(outfilp), &iolock);
+ if (error) {
+ xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+ return -error;
+@@ -573,14 +571,12 @@ xfs_write(
+ struct file *file = iocb->ki_filp;
+ struct address_space *mapping = file->f_mapping;
+ struct inode *inode = mapping->host;
+- bhv_vnode_t *vp = XFS_ITOV(xip);
+ unsigned long segs = nsegs;
+ xfs_mount_t *mp;
+ ssize_t ret = 0, error = 0;
+ xfs_fsize_t isize, new_size;
+ int iolock;
+ int eventsent = 0;
+- bhv_vrwlock_t locktype;
+ size_t ocount = 0, count;
+ loff_t pos;
+ int need_i_mutex;
+@@ -607,11 +603,9 @@ xfs_write(
+ relock:
+ if (ioflags & IO_ISDIRECT) {
+ iolock = XFS_IOLOCK_SHARED;
+- locktype = VRWLOCK_WRITE_DIRECT;
+ need_i_mutex = 0;
+ } else {
+ iolock = XFS_IOLOCK_EXCL;
+- locktype = VRWLOCK_WRITE;
+ need_i_mutex = 1;
+ mutex_lock(&inode->i_mutex);
+ }
+@@ -634,9 +628,8 @@ start:
+ dmflags |= DM_FLAGS_IMUX;
+
+ xfs_iunlock(xip, XFS_ILOCK_EXCL);
+- error = XFS_SEND_DATA(xip->i_mount, DM_EVENT_WRITE, vp,
+- pos, count,
+- dmflags, &locktype);
++ error = XFS_SEND_DATA(xip->i_mount, DM_EVENT_WRITE, xip,
++ pos, count, dmflags, &iolock);
+ if (error) {
+ goto out_unlock_internal;
+ }
+@@ -664,10 +657,9 @@ start:
+ return XFS_ERROR(-EINVAL);
+ }
+
+- if (!need_i_mutex && (VN_CACHED(vp) || pos > xip->i_size)) {
++ if (!need_i_mutex && (mapping->nrpages || pos > xip->i_size)) {
+ xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
+ iolock = XFS_IOLOCK_EXCL;
+- locktype = VRWLOCK_WRITE;
+ need_i_mutex = 1;
+ mutex_lock(&inode->i_mutex);
+ xfs_ilock(xip, XFS_ILOCK_EXCL|iolock);
+@@ -679,10 +671,16 @@ start:
+ if (new_size > xip->i_size)
+ xip->i_new_size = new_size;
+
+- if (likely(!(ioflags & IO_INVIS))) {
++ /*
++ * We're not supposed to change timestamps in readonly-mounted
++ * filesystems. Throw it away if anyone asks us.
++ */
++ if (likely(!(ioflags & IO_INVIS) &&
++ !mnt_want_write(file->f_path.mnt))) {
+ file_update_time(file);
+ xfs_ichgtime_fast(xip, inode,
+ XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
++ mnt_drop_write(file->f_path.mnt);
+ }
+
+ /*
+@@ -727,7 +725,7 @@ retry:
+ current->backing_dev_info = mapping->backing_dev_info;
+
+ if ((ioflags & IO_ISDIRECT)) {
+- if (VN_CACHED(vp)) {
++ if (mapping->nrpages) {
+ WARN_ON(need_i_mutex == 0);
+ xfs_inval_cached_trace(xip, pos, -1,
+ (pos & PAGE_CACHE_MASK), -1);
+@@ -744,7 +742,6 @@ retry:
+ mutex_unlock(&inode->i_mutex);
+
+ iolock = XFS_IOLOCK_SHARED;
+- locktype = VRWLOCK_WRITE_DIRECT;
+ need_i_mutex = 0;
+ }
+
+@@ -781,15 +778,15 @@ retry:
+
+ if (ret == -ENOSPC &&
+ DM_EVENT_ENABLED(xip, DM_EVENT_NOSPACE) && !(ioflags & IO_INVIS)) {
+- xfs_rwunlock(xip, locktype);
++ xfs_iunlock(xip, iolock);
+ if (need_i_mutex)
+ mutex_unlock(&inode->i_mutex);
+- error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, vp,
+- DM_RIGHT_NULL, vp, DM_RIGHT_NULL, NULL, NULL,
++ error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, xip,
++ DM_RIGHT_NULL, xip, DM_RIGHT_NULL, NULL, NULL,
+ 0, 0, 0); /* Delay flag intentionally unused */
+ if (need_i_mutex)
+ mutex_lock(&inode->i_mutex);
+- xfs_rwlock(xip, locktype);
++ xfs_ilock(xip, iolock);
+ if (error)
+ goto out_unlock_internal;
+ pos = xip->i_size;
+@@ -817,7 +814,8 @@ retry:
+ /* Handle various SYNC-type writes */
+ if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) {
+ int error2;
+- xfs_rwunlock(xip, locktype);
++
++ xfs_iunlock(xip, iolock);
+ if (need_i_mutex)
+ mutex_unlock(&inode->i_mutex);
+ error2 = sync_page_range(inode, mapping, pos, ret);
+@@ -825,7 +823,7 @@ retry:
+ error = error2;
+ if (need_i_mutex)
+ mutex_lock(&inode->i_mutex);
+- xfs_rwlock(xip, locktype);
++ xfs_ilock(xip, iolock);
+ error2 = xfs_write_sync_logforce(mp, xip);
+ if (!error)
+ error = error2;
+@@ -846,7 +844,7 @@ retry:
+ xip->i_d.di_size = xip->i_size;
+ xfs_iunlock(xip, XFS_ILOCK_EXCL);
+ }
+- xfs_rwunlock(xip, locktype);
++ xfs_iunlock(xip, iolock);
+ out_unlock_mutex:
+ if (need_i_mutex)
+ mutex_unlock(&inode->i_mutex);
+@@ -884,28 +882,23 @@ xfs_bdstrat_cb(struct xfs_buf *bp)
+ }
+
+ /*
+- * Wrapper around bdstrat so that we can stop data
+- * from going to disk in case we are shutting down the filesystem.
+- * Typically user data goes thru this path; one of the exceptions
+- * is the superblock.
++ * Wrapper around bdstrat so that we can stop data from going to disk in case
++ * we are shutting down the filesystem. Typically user data goes thru this
++ * path; one of the exceptions is the superblock.
+ */
+-int
++void
+ xfsbdstrat(
+ struct xfs_mount *mp,
+ struct xfs_buf *bp)
+ {
+ ASSERT(mp);
+ if (!XFS_FORCED_SHUTDOWN(mp)) {
+- /* Grio redirection would go here
+- * if (XFS_BUF_IS_GRIO(bp)) {
+- */
+-
+ xfs_buf_iorequest(bp);
+- return 0;
++ return;
+ }
+
+ xfs_buftrace("XFSBDSTRAT IOERROR", bp);
+- return (xfs_bioerror_relse(bp));
++ xfs_bioerror_relse(bp);
+ }
+
+ /*
+diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
+index e200253..e1d498b 100644
+--- a/fs/xfs/linux-2.6/xfs_lrw.h
++++ b/fs/xfs/linux-2.6/xfs_lrw.h
+@@ -68,7 +68,8 @@ extern void xfs_inval_cached_trace(struct xfs_inode *,
+ #define xfs_inval_cached_trace(ip, offset, len, first, last)
+ #endif
+
+-extern int xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
++/* errors from xfsbdstrat() must be extracted from the buffer */
++extern void xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
+ extern int xfs_bdstrat_cb(struct xfs_buf *);
+ extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
+
+diff --git a/fs/xfs/linux-2.6/xfs_stats.h b/fs/xfs/linux-2.6/xfs_stats.h
+index 8ba7a2f..afd0b0d 100644
+--- a/fs/xfs/linux-2.6/xfs_stats.h
++++ b/fs/xfs/linux-2.6/xfs_stats.h
+@@ -144,8 +144,8 @@ extern void xfs_cleanup_procfs(void);
+ # define XFS_STATS_DEC(count)
+ # define XFS_STATS_ADD(count, inc)
+
+-static __inline void xfs_init_procfs(void) { };
+-static __inline void xfs_cleanup_procfs(void) { };
++static inline void xfs_init_procfs(void) { };
++static inline void xfs_cleanup_procfs(void) { };
+
+ #endif /* !CONFIG_PROC_FS */
+
+diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
+index 8831d95..865eb70 100644
+--- a/fs/xfs/linux-2.6/xfs_super.c
++++ b/fs/xfs/linux-2.6/xfs_super.c
+@@ -896,7 +896,8 @@ xfs_fs_write_inode(
+ struct inode *inode,
+ int sync)
+ {
+- int error = 0, flags = FLUSH_INODE;
++ int error = 0;
++ int flags = 0;
+
+ xfs_itrace_entry(XFS_I(inode));
+ if (sync) {
+@@ -934,7 +935,7 @@ xfs_fs_clear_inode(
+ xfs_inactive(ip);
+ xfs_iflags_clear(ip, XFS_IMODIFIED);
+ if (xfs_reclaim(ip))
+- panic("%s: cannot reclaim 0x%p\n", __FUNCTION__, inode);
++ panic("%s: cannot reclaim 0x%p\n", __func__, inode);
+ }
+
+ ASSERT(XFS_I(inode) == NULL);
+@@ -1027,8 +1028,7 @@ xfs_sync_worker(
+ int error;
+
+ if (!(mp->m_flags & XFS_MOUNT_RDONLY))
+- error = xfs_sync(mp, SYNC_FSDATA | SYNC_BDFLUSH | SYNC_ATTR |
+- SYNC_REFCACHE | SYNC_SUPER);
++ error = xfs_sync(mp, SYNC_FSDATA | SYNC_BDFLUSH | SYNC_ATTR);
+ mp->m_sync_seq++;
+ wake_up(&mp->m_wait_single_sync_task);
+ }
+@@ -1306,7 +1306,7 @@ xfs_fs_fill_super(
+ void *data,
+ int silent)
+ {
+- struct inode *rootvp;
++ struct inode *root;
+ struct xfs_mount *mp = NULL;
+ struct xfs_mount_args *args = xfs_args_allocate(sb, silent);
+ int error;
+@@ -1344,19 +1344,18 @@ xfs_fs_fill_super(
+ sb->s_time_gran = 1;
+ set_posix_acl_flag(sb);
+
+- rootvp = igrab(mp->m_rootip->i_vnode);
+- if (!rootvp) {
++ root = igrab(mp->m_rootip->i_vnode);
++ if (!root) {
+ error = ENOENT;
+ goto fail_unmount;
+ }
+-
+- sb->s_root = d_alloc_root(vn_to_inode(rootvp));
+- if (!sb->s_root) {
+- error = ENOMEM;
++ if (is_bad_inode(root)) {
++ error = EINVAL;
+ goto fail_vnrele;
+ }
+- if (is_bad_inode(sb->s_root->d_inode)) {
+- error = EINVAL;
++ sb->s_root = d_alloc_root(root);
++ if (!sb->s_root) {
++ error = ENOMEM;
+ goto fail_vnrele;
+ }
+
+@@ -1378,7 +1377,7 @@ fail_vnrele:
+ dput(sb->s_root);
+ sb->s_root = NULL;
+ } else {
+- VN_RELE(rootvp);
++ iput(root);
+ }
+
+ fail_unmount:
+diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h
+index 3efcf45..3efb7c6 100644
+--- a/fs/xfs/linux-2.6/xfs_super.h
++++ b/fs/xfs/linux-2.6/xfs_super.h
+@@ -50,13 +50,7 @@ extern void xfs_qm_exit(void);
+ # define set_posix_acl_flag(sb) do { } while (0)
+ #endif
+
+-#ifdef CONFIG_XFS_SECURITY
+-# define XFS_SECURITY_STRING "security attributes, "
+-# define ENOSECURITY 0
+-#else
+-# define XFS_SECURITY_STRING
+-# define ENOSECURITY EOPNOTSUPP
+-#endif
++#define XFS_SECURITY_STRING "security attributes, "
+
+ #ifdef CONFIG_XFS_RT
+ # define XFS_REALTIME_STRING "realtime, "
+diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h
+index 4da03a4..7e60c77 100644
+--- a/fs/xfs/linux-2.6/xfs_vfs.h
++++ b/fs/xfs/linux-2.6/xfs_vfs.h
+@@ -49,7 +49,6 @@ typedef struct bhv_vfs_sync_work {
+ #define SYNC_REFCACHE 0x0040 /* prune some of the nfs ref cache */
+ #define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */
+ #define SYNC_IOWAIT 0x0100 /* wait for all I/O to complete */
+-#define SYNC_SUPER 0x0200 /* flush superblock to disk */
+
+ /*
+ * When remounting a filesystem read-only or freezing the filesystem,
+diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
+index b5ea418..8b4d63c 100644
+--- a/fs/xfs/linux-2.6/xfs_vnode.h
++++ b/fs/xfs/linux-2.6/xfs_vnode.h
+@@ -23,8 +23,6 @@ struct bhv_vattr;
+ struct xfs_iomap;
+ struct attrlist_cursor_kern;
+
+-typedef struct dentry bhv_vname_t;
+-typedef __u64 bhv_vnumber_t;
+ typedef struct inode bhv_vnode_t;
+
+ #define VN_ISLNK(vp) S_ISLNK((vp)->i_mode)
+@@ -46,18 +44,6 @@ static inline struct inode *vn_to_inode(bhv_vnode_t *vnode)
+ }
+
+ /*
+- * Values for the vop_rwlock/rwunlock flags parameter.
+- */
+-typedef enum bhv_vrwlock {
+- VRWLOCK_NONE,
+- VRWLOCK_READ,
+- VRWLOCK_WRITE,
+- VRWLOCK_WRITE_DIRECT,
+- VRWLOCK_TRY_READ,
+- VRWLOCK_TRY_WRITE
+-} bhv_vrwlock_t;
+-
+-/*
+ * Return values for xfs_inactive. A return value of
+ * VN_INACTIVE_NOCACHE implies that the file system behavior
+ * has disassociated its state and bhv_desc_t from the vnode.
+@@ -73,12 +59,9 @@ typedef enum bhv_vrwlock {
+ #define IO_INVIS 0x00020 /* don't update inode timestamps */
+
+ /*
+- * Flags for vop_iflush call
++ * Flags for xfs_inode_flush
+ */
+ #define FLUSH_SYNC 1 /* wait for flush to complete */
+-#define FLUSH_INODE 2 /* flush the inode itself */
+-#define FLUSH_LOG 4 /* force the last log entry for
+- * this inode out to disk */
+
+ /*
+ * Flush/Invalidate options for vop_toss/flush/flushinval_pages.
+@@ -226,13 +209,6 @@ static inline bhv_vnode_t *vn_grab(bhv_vnode_t *vp)
+ }
+
+ /*
+- * Vname handling macros.
+- */
+-#define VNAME(dentry) ((char *) (dentry)->d_name.name)
+-#define VNAMELEN(dentry) ((dentry)->d_name.len)
+-#define VNAME_TO_VNODE(dentry) (vn_from_inode((dentry)->d_inode))
+-
+-/*
+ * Dealing with bad inodes
+ */
+ static inline int VN_BAD(bhv_vnode_t *vp)
+@@ -303,9 +279,9 @@ extern void xfs_itrace_hold(struct xfs_inode *, char *, int, inst_t *);
+ extern void _xfs_itrace_ref(struct xfs_inode *, char *, int, inst_t *);
+ extern void xfs_itrace_rele(struct xfs_inode *, char *, int, inst_t *);
+ #define xfs_itrace_entry(ip) \
+- _xfs_itrace_entry(ip, __FUNCTION__, (inst_t *)__return_address)
++ _xfs_itrace_entry(ip, __func__, (inst_t *)__return_address)
+ #define xfs_itrace_exit(ip) \
+- _xfs_itrace_exit(ip, __FUNCTION__, (inst_t *)__return_address)
++ _xfs_itrace_exit(ip, __func__, (inst_t *)__return_address)
+ #define xfs_itrace_exit_tag(ip, tag) \
+ _xfs_itrace_exit(ip, tag, (inst_t *)__return_address)
+ #define xfs_itrace_ref(ip) \
+diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
+index 665babc..631ebb3 100644
+--- a/fs/xfs/quota/xfs_dquot.c
++++ b/fs/xfs/quota/xfs_dquot.c
+@@ -1291,7 +1291,7 @@ xfs_qm_dqflush(
+ if (flags & XFS_QMOPT_DELWRI) {
+ xfs_bdwrite(mp, bp);
+ } else if (flags & XFS_QMOPT_ASYNC) {
+- xfs_bawrite(mp, bp);
++ error = xfs_bawrite(mp, bp);
+ } else {
+ error = xfs_bwrite(mp, bp);
+ }
+@@ -1439,9 +1439,7 @@ xfs_qm_dqpurge(
+ uint flags)
+ {
+ xfs_dqhash_t *thishash;
+- xfs_mount_t *mp;
+-
+- mp = dqp->q_mount;
++ xfs_mount_t *mp = dqp->q_mount;
+
+ ASSERT(XFS_QM_IS_MPLIST_LOCKED(mp));
+ ASSERT(XFS_DQ_IS_HASH_LOCKED(dqp->q_hash));
+@@ -1485,6 +1483,7 @@ xfs_qm_dqpurge(
+ * we're unmounting, we do care, so we flush it and wait.
+ */
+ if (XFS_DQ_IS_DIRTY(dqp)) {
++ int error;
+ xfs_dqtrace_entry(dqp, "DQPURGE ->DQFLUSH: DQDIRTY");
+ /* dqflush unlocks dqflock */
+ /*
+@@ -1495,7 +1494,10 @@ xfs_qm_dqpurge(
+ * We don't care about getting disk errors here. We need
+ * to purge this dquot anyway, so we go ahead regardless.
+ */
+- (void) xfs_qm_dqflush(dqp, XFS_QMOPT_SYNC);
++ error = xfs_qm_dqflush(dqp, XFS_QMOPT_SYNC);
++ if (error)
++ xfs_fs_cmn_err(CE_WARN, mp,
++ "xfs_qm_dqpurge: dquot %p flush failed", dqp);
+ xfs_dqflock(dqp);
+ }
+ ASSERT(dqp->q_pincount == 0);
+@@ -1580,12 +1582,18 @@ xfs_qm_dqflock_pushbuf_wait(
+ XFS_INCORE_TRYLOCK);
+ if (bp != NULL) {
+ if (XFS_BUF_ISDELAYWRITE(bp)) {
++ int error;
+ if (XFS_BUF_ISPINNED(bp)) {
+ xfs_log_force(dqp->q_mount,
+ (xfs_lsn_t)0,
+ XFS_LOG_FORCE);
+ }
+- xfs_bawrite(dqp->q_mount, bp);
++ error = xfs_bawrite(dqp->q_mount, bp);
++ if (error)
++ xfs_fs_cmn_err(CE_WARN, dqp->q_mount,
++ "xfs_qm_dqflock_pushbuf_wait: "
++ "pushbuf error %d on dqp %p, bp %p",
++ error, dqp, bp);
+ } else {
+ xfs_buf_relse(bp);
+ }
+diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c
+index 1800e8d..36e05ca 100644
+--- a/fs/xfs/quota/xfs_dquot_item.c
++++ b/fs/xfs/quota/xfs_dquot_item.c
+@@ -146,6 +146,7 @@ xfs_qm_dquot_logitem_push(
+ xfs_dq_logitem_t *logitem)
+ {
+ xfs_dquot_t *dqp;
++ int error;
+
+ dqp = logitem->qli_dquot;
+
+@@ -161,7 +162,11 @@ xfs_qm_dquot_logitem_push(
+ * lock without sleeping, then there must not have been
+ * anyone in the process of flushing the dquot.
+ */
+- xfs_qm_dqflush(dqp, XFS_B_DELWRI);
++ error = xfs_qm_dqflush(dqp, XFS_QMOPT_DELWRI);
++ if (error)
++ xfs_fs_cmn_err(CE_WARN, dqp->q_mount,
++ "xfs_qm_dquot_logitem_push: push error %d on dqp %p",
++ error, dqp);
+ xfs_dqunlock(dqp);
+ }
+
+@@ -262,11 +267,16 @@ xfs_qm_dquot_logitem_pushbuf(
+ XFS_LOG_FORCE);
+ }
+ if (dopush) {
++ int error;
+ #ifdef XFSRACEDEBUG
+ delay_for_intr();
+ delay(300);
+ #endif
+- xfs_bawrite(mp, bp);
++ error = xfs_bawrite(mp, bp);
++ if (error)
++ xfs_fs_cmn_err(CE_WARN, mp,
++ "xfs_qm_dquot_logitem_pushbuf: pushbuf error %d on qip %p, bp %p",
++ error, qip, bp);
+ } else {
+ xfs_buf_relse(bp);
+ }
+diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
+index 8e9c5ae..40ea564 100644
+--- a/fs/xfs/quota/xfs_qm.c
++++ b/fs/xfs/quota/xfs_qm.c
+@@ -304,8 +304,11 @@ xfs_qm_unmount_quotadestroy(
+ * necessary data structures like quotainfo. This is also responsible for
+ * running a quotacheck as necessary. We are guaranteed that the superblock
+ * is consistently read in at this point.
++ *
++ * If we fail here, the mount will continue with quota turned off. We don't
++ * need to inidicate success or failure at all.
+ */
+-int
++void
+ xfs_qm_mount_quotas(
+ xfs_mount_t *mp,
+ int mfsi_flags)
+@@ -313,7 +316,6 @@ xfs_qm_mount_quotas(
+ int error = 0;
+ uint sbf;
+
+-
+ /*
+ * If quotas on realtime volumes is not supported, we disable
+ * quotas immediately.
+@@ -332,7 +334,8 @@ xfs_qm_mount_quotas(
+ * Allocate the quotainfo structure inside the mount struct, and
+ * create quotainode(s), and change/rev superblock if necessary.
+ */
+- if ((error = xfs_qm_init_quotainfo(mp))) {
++ error = xfs_qm_init_quotainfo(mp);
++ if (error) {
+ /*
+ * We must turn off quotas.
+ */
+@@ -344,12 +347,11 @@ xfs_qm_mount_quotas(
+ * If any of the quotas are not consistent, do a quotacheck.
+ */
+ if (XFS_QM_NEED_QUOTACHECK(mp) &&
+- !(mfsi_flags & XFS_MFSI_NO_QUOTACHECK)) {
+- if ((error = xfs_qm_quotacheck(mp))) {
+- /* Quotacheck has failed and quotas have
+- * been disabled.
+- */
+- return XFS_ERROR(error);
++ !(mfsi_flags & XFS_MFSI_NO_QUOTACHECK)) {
++ error = xfs_qm_quotacheck(mp);
++ if (error) {
++ /* Quotacheck failed and disabled quotas. */
++ return;
+ }
+ }
+ /*
+@@ -357,12 +359,10 @@ xfs_qm_mount_quotas(
+ * quotachecked status, since we won't be doing accounting for
+ * that type anymore.
+ */
+- if (!XFS_IS_UQUOTA_ON(mp)) {
++ if (!XFS_IS_UQUOTA_ON(mp))
+ mp->m_qflags &= ~XFS_UQUOTA_CHKD;
+- }
+- if (!(XFS_IS_GQUOTA_ON(mp) || XFS_IS_PQUOTA_ON(mp))) {
++ if (!(XFS_IS_GQUOTA_ON(mp) || XFS_IS_PQUOTA_ON(mp)))
+ mp->m_qflags &= ~XFS_OQUOTA_CHKD;
+- }
+
+ write_changes:
+ /*
+@@ -392,7 +392,7 @@ xfs_qm_mount_quotas(
+ xfs_fs_cmn_err(CE_WARN, mp,
+ "Failed to initialize disk quotas.");
+ }
+- return XFS_ERROR(error);
++ return;
+ }
+
+ /*
+@@ -1438,7 +1438,7 @@ xfs_qm_qino_alloc(
+ }
+
+
+-STATIC int
++STATIC void
+ xfs_qm_reset_dqcounts(
+ xfs_mount_t *mp,
+ xfs_buf_t *bp,
+@@ -1478,8 +1478,6 @@ xfs_qm_reset_dqcounts(
+ ddq->d_rtbwarns = 0;
+ ddq = (xfs_disk_dquot_t *) ((xfs_dqblk_t *)ddq + 1);
+ }
+-
+- return 0;
+ }
+
+ STATIC int
+@@ -1520,7 +1518,7 @@ xfs_qm_dqiter_bufs(
+ if (error)
+ break;
+
+- (void) xfs_qm_reset_dqcounts(mp, bp, firstid, type);
++ xfs_qm_reset_dqcounts(mp, bp, firstid, type);
+ xfs_bdwrite(mp, bp);
+ /*
+ * goto the next block.
+@@ -1810,7 +1808,7 @@ xfs_qm_dqusage_adjust(
+ * Now release the inode. This will send it to 'inactive', and
+ * possibly even free blocks.
+ */
+- VN_RELE(XFS_ITOV(ip));
++ IRELE(ip);
+
+ /*
+ * Goto next inode.
+@@ -1880,6 +1878,14 @@ xfs_qm_quotacheck(
+ } while (! done);
+
+ /*
++ * We've made all the changes that we need to make incore.
++ * Flush them down to disk buffers if everything was updated
++ * successfully.
++ */
++ if (!error)
++ error = xfs_qm_dqflush_all(mp, XFS_QMOPT_DELWRI);
++
++ /*
+ * We can get this error if we couldn't do a dquot allocation inside
+ * xfs_qm_dqusage_adjust (via bulkstat). We don't care about the
+ * dirty dquots that might be cached, we just want to get rid of them
+@@ -1890,11 +1896,6 @@ xfs_qm_quotacheck(
+ xfs_qm_dqpurge_all(mp, XFS_QMOPT_QUOTALL | XFS_QMOPT_QUOTAOFF);
+ goto error_return;
+ }
+- /*
+- * We've made all the changes that we need to make incore.
+- * Now flush_them down to disk buffers.
+- */
+- xfs_qm_dqflush_all(mp, XFS_QMOPT_DELWRI);
+
+ /*
+ * We didn't log anything, because if we crashed, we'll have to
+@@ -1926,7 +1927,10 @@ xfs_qm_quotacheck(
+ ASSERT(mp->m_quotainfo != NULL);
+ ASSERT(xfs_Gqm != NULL);
+ xfs_qm_destroy_quotainfo(mp);
+- (void)xfs_mount_reset_sbqflags(mp);
++ if (xfs_mount_reset_sbqflags(mp)) {
++ cmn_err(CE_WARN, "XFS quotacheck %s: "
++ "Failed to reset quota flags.", mp->m_fsname);
++ }
+ } else {
+ cmn_err(CE_NOTE, "XFS quotacheck %s: Done.", mp->m_fsname);
+ }
+@@ -1968,7 +1972,7 @@ xfs_qm_init_quotainos(
+ if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
+ 0, 0, &gip, 0))) {
+ if (uip)
+- VN_RELE(XFS_ITOV(uip));
++ IRELE(uip);
+ return XFS_ERROR(error);
+ }
+ }
+@@ -1999,7 +2003,7 @@ xfs_qm_init_quotainos(
+ sbflags | XFS_SB_GQUOTINO, flags);
+ if (error) {
+ if (uip)
+- VN_RELE(XFS_ITOV(uip));
++ IRELE(uip);
+
+ return XFS_ERROR(error);
+ }
+@@ -2093,12 +2097,17 @@ xfs_qm_shake_freelist(
+ * dirty dquots.
+ */
+ if (XFS_DQ_IS_DIRTY(dqp)) {
++ int error;
+ xfs_dqtrace_entry(dqp, "DQSHAKE: DQDIRTY");
+ /*
+ * We flush it delayed write, so don't bother
+ * releasing the mplock.
+ */
+- (void) xfs_qm_dqflush(dqp, XFS_QMOPT_DELWRI);
++ error = xfs_qm_dqflush(dqp, XFS_QMOPT_DELWRI);
++ if (error) {
++ xfs_fs_cmn_err(CE_WARN, dqp->q_mount,
++ "xfs_qm_dqflush_all: dquot %p flush failed", dqp);
++ }
+ xfs_dqunlock(dqp); /* dqflush unlocks dqflock */
+ dqp = dqp->dq_flnext;
+ continue;
+@@ -2265,12 +2274,17 @@ xfs_qm_dqreclaim_one(void)
+ * dirty dquots.
+ */
+ if (XFS_DQ_IS_DIRTY(dqp)) {
++ int error;
+ xfs_dqtrace_entry(dqp, "DQRECLAIM: DQDIRTY");
+ /*
+ * We flush it delayed write, so don't bother
+ * releasing the freelist lock.
+ */
+- (void) xfs_qm_dqflush(dqp, XFS_QMOPT_DELWRI);
++ error = xfs_qm_dqflush(dqp, XFS_QMOPT_DELWRI);
++ if (error) {
++ xfs_fs_cmn_err(CE_WARN, dqp->q_mount,
++ "xfs_qm_dqreclaim: dquot %p flush failed", dqp);
++ }
+ xfs_dqunlock(dqp); /* dqflush unlocks dqflock */
+ continue;
+ }
+@@ -2378,9 +2392,9 @@ xfs_qm_write_sb_changes(
+ }
+
+ xfs_mod_sb(tp, flags);
+- (void) xfs_trans_commit(tp, 0);
++ error = xfs_trans_commit(tp, 0);
+
+- return 0;
++ return error;
+ }
+
+
+diff --git a/fs/xfs/quota/xfs_qm.h b/fs/xfs/quota/xfs_qm.h
+index baf537c..cd2300e 100644
+--- a/fs/xfs/quota/xfs_qm.h
++++ b/fs/xfs/quota/xfs_qm.h
+@@ -165,7 +165,7 @@ typedef struct xfs_dquot_acct {
+ #define XFS_QM_RELE(xqm) ((xqm)->qm_nrefs--)
+
+ extern void xfs_qm_destroy_quotainfo(xfs_mount_t *);
+-extern int xfs_qm_mount_quotas(xfs_mount_t *, int);
++extern void xfs_qm_mount_quotas(xfs_mount_t *, int);
+ extern int xfs_qm_quotacheck(xfs_mount_t *);
+ extern void xfs_qm_unmount_quotadestroy(xfs_mount_t *);
+ extern int xfs_qm_unmount_quotas(xfs_mount_t *);
+diff --git a/fs/xfs/quota/xfs_qm_stats.h b/fs/xfs/quota/xfs_qm_stats.h
+index a50ffab..5b964fc 100644
+--- a/fs/xfs/quota/xfs_qm_stats.h
++++ b/fs/xfs/quota/xfs_qm_stats.h
+@@ -45,8 +45,8 @@ extern void xfs_qm_cleanup_procfs(void);
+
+ # define XQM_STATS_INC(count) do { } while (0)
+
+-static __inline void xfs_qm_init_procfs(void) { };
+-static __inline void xfs_qm_cleanup_procfs(void) { };
++static inline void xfs_qm_init_procfs(void) { };
++static inline void xfs_qm_cleanup_procfs(void) { };
+
+ #endif
+
+diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
+index d2b8be7..8342823 100644
+--- a/fs/xfs/quota/xfs_qm_syscalls.c
++++ b/fs/xfs/quota/xfs_qm_syscalls.c
+@@ -279,9 +279,12 @@ xfs_qm_scall_quotaoff(
+
+ /*
+ * Write the LI_QUOTAOFF log record, and do SB changes atomically,
+- * and synchronously.
++ * and synchronously. If we fail to write, we should abort the
++ * operation as it cannot be recovered safely if we crash.
+ */
+- xfs_qm_log_quotaoff(mp, &qoffstart, flags);
++ error = xfs_qm_log_quotaoff(mp, &qoffstart, flags);
++ if (error)
++ goto out_error;
+
+ /*
+ * Next we clear the XFS_MOUNT_*DQ_ACTIVE bit(s) in the mount struct
+@@ -337,7 +340,12 @@ xfs_qm_scall_quotaoff(
+ * So, we have QUOTAOFF start and end logitems; the start
+ * logitem won't get overwritten until the end logitem appears...
+ */
+- xfs_qm_log_quotaoff_end(mp, qoffstart, flags);
++ error = xfs_qm_log_quotaoff_end(mp, qoffstart, flags);
++ if (error) {
++ /* We're screwed now. Shutdown is the only option. */
++ xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
++ goto out_error;
++ }
+
+ /*
+ * If quotas is completely disabled, close shop.
+@@ -361,6 +369,7 @@ xfs_qm_scall_quotaoff(
+ XFS_PURGE_INODE(XFS_QI_GQIP(mp));
+ XFS_QI_GQIP(mp) = NULL;
+ }
++out_error:
+ mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));
+
+ return (error);
+@@ -371,12 +380,11 @@ xfs_qm_scall_trunc_qfiles(
+ xfs_mount_t *mp,
+ uint flags)
+ {
+- int error;
++ int error = 0, error2 = 0;
+ xfs_inode_t *qip;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return XFS_ERROR(EPERM);
+- error = 0;
+ if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) {
+ qdprintk("qtrunc flags=%x m_qflags=%x\n", flags, mp->m_qflags);
+ return XFS_ERROR(EINVAL);
+@@ -384,22 +392,22 @@ xfs_qm_scall_trunc_qfiles(
+
+ if ((flags & XFS_DQ_USER) && mp->m_sb.sb_uquotino != NULLFSINO) {
+ error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino, 0, 0, &qip, 0);
+- if (! error) {
+- (void) xfs_truncate_file(mp, qip);
+- VN_RELE(XFS_ITOV(qip));
++ if (!error) {
++ error = xfs_truncate_file(mp, qip);
++ IRELE(qip);
+ }
+ }
+
+ if ((flags & (XFS_DQ_GROUP|XFS_DQ_PROJ)) &&
+ mp->m_sb.sb_gquotino != NULLFSINO) {
+- error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip, 0);
+- if (! error) {
+- (void) xfs_truncate_file(mp, qip);
+- VN_RELE(XFS_ITOV(qip));
++ error2 = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip, 0);
++ if (!error2) {
++ error2 = xfs_truncate_file(mp, qip);
++ IRELE(qip);
+ }
+ }
+
+- return (error);
++ return error ? error : error2;
+ }
+
+
+@@ -552,13 +560,13 @@ xfs_qm_scall_getqstat(
+ out->qs_uquota.qfs_nblks = uip->i_d.di_nblocks;
+ out->qs_uquota.qfs_nextents = uip->i_d.di_nextents;
+ if (tempuqip)
+- VN_RELE(XFS_ITOV(uip));
++ IRELE(uip);
+ }
+ if (gip) {
+ out->qs_gquota.qfs_nblks = gip->i_d.di_nblocks;
+ out->qs_gquota.qfs_nextents = gip->i_d.di_nextents;
+ if (tempgqip)
+- VN_RELE(XFS_ITOV(gip));
++ IRELE(gip);
+ }
+ if (mp->m_quotainfo) {
+ out->qs_incoredqs = XFS_QI_MPLNDQUOTS(mp);
+@@ -726,12 +734,12 @@ xfs_qm_scall_setqlim(
+ xfs_trans_log_dquot(tp, dqp);
+
+ xfs_dqtrace_entry(dqp, "Q_SETQLIM: COMMIT");
+- xfs_trans_commit(tp, 0);
++ error = xfs_trans_commit(tp, 0);
+ xfs_qm_dqprint(dqp);
+ xfs_qm_dqrele(dqp);
+ mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));
+
+- return (0);
++ return error;
+ }
+
+ STATIC int
+@@ -1095,7 +1103,7 @@ again:
+ * inactive code in hell.
+ */
+ if (vnode_refd)
+- VN_RELE(vp);
++ IRELE(ip);
+ XFS_MOUNT_ILOCK(mp);
+ /*
+ * If an inode was inserted or removed, we gotta
+diff --git a/fs/xfs/support/ktrace.c b/fs/xfs/support/ktrace.c
+index 129067c..0b75d30 100644
+--- a/fs/xfs/support/ktrace.c
++++ b/fs/xfs/support/ktrace.c
+@@ -24,7 +24,7 @@ static int ktrace_zentries;
+ void __init
+ ktrace_init(int zentries)
+ {
+- ktrace_zentries = zentries;
++ ktrace_zentries = roundup_pow_of_two(zentries);
+
+ ktrace_hdr_zone = kmem_zone_init(sizeof(ktrace_t),
+ "ktrace_hdr");
+@@ -47,13 +47,16 @@ ktrace_uninit(void)
+ * ktrace_alloc()
+ *
+ * Allocate a ktrace header and enough buffering for the given
+- * number of entries.
++ * number of entries. Round the number of entries up to a
++ * power of 2 so we can do fast masking to get the index from
++ * the atomic index counter.
+ */
+ ktrace_t *
+ ktrace_alloc(int nentries, unsigned int __nocast sleep)
+ {
+ ktrace_t *ktp;
+ ktrace_entry_t *ktep;
++ int entries;
+
+ ktp = (ktrace_t*)kmem_zone_alloc(ktrace_hdr_zone, sleep);
+
+@@ -70,11 +73,12 @@ ktrace_alloc(int nentries, unsigned int __nocast sleep)
+ /*
+ * Special treatment for buffers with the ktrace_zentries entries
+ */
+- if (nentries == ktrace_zentries) {
++ entries = roundup_pow_of_two(nentries);
++ if (entries == ktrace_zentries) {
+ ktep = (ktrace_entry_t*)kmem_zone_zalloc(ktrace_ent_zone,
+ sleep);
+ } else {
+- ktep = (ktrace_entry_t*)kmem_zalloc((nentries * sizeof(*ktep)),
++ ktep = (ktrace_entry_t*)kmem_zalloc((entries * sizeof(*ktep)),
+ sleep | KM_LARGE);
+ }
+
+@@ -91,8 +95,10 @@ ktrace_alloc(int nentries, unsigned int __nocast sleep)
+ }
+
+ ktp->kt_entries = ktep;
+- ktp->kt_nentries = nentries;
+- ktp->kt_index = 0;
++ ktp->kt_nentries = entries;
++ ASSERT(is_power_of_2(entries));
++ ktp->kt_index_mask = entries - 1;
++ atomic_set(&ktp->kt_index, 0);
+ ktp->kt_rollover = 0;
+ return ktp;
+ }
+@@ -151,8 +157,6 @@ ktrace_enter(
+ void *val14,
+ void *val15)
+ {
+- static DEFINE_SPINLOCK(wrap_lock);
+- unsigned long flags;
+ int index;
+ ktrace_entry_t *ktep;
+
+@@ -161,12 +165,8 @@ ktrace_enter(
+ /*
+ * Grab an entry by pushing the index up to the next one.
+ */
+- spin_lock_irqsave(&wrap_lock, flags);
+- index = ktp->kt_index;
+- if (++ktp->kt_index == ktp->kt_nentries)
+- ktp->kt_index = 0;
+- spin_unlock_irqrestore(&wrap_lock, flags);
+-
++ index = atomic_add_return(1, &ktp->kt_index);
++ index = (index - 1) & ktp->kt_index_mask;
+ if (!ktp->kt_rollover && index == ktp->kt_nentries - 1)
+ ktp->kt_rollover = 1;
+
+@@ -199,11 +199,12 @@ int
+ ktrace_nentries(
+ ktrace_t *ktp)
+ {
+- if (ktp == NULL) {
++ int index;
++ if (ktp == NULL)
+ return 0;
+- }
+
+- return (ktp->kt_rollover ? ktp->kt_nentries : ktp->kt_index);
++ index = atomic_read(&ktp->kt_index) & ktp->kt_index_mask;
++ return (ktp->kt_rollover ? ktp->kt_nentries : index);
+ }
+
+ /*
+@@ -228,7 +229,7 @@ ktrace_first(ktrace_t *ktp, ktrace_snap_t *ktsp)
+ int nentries;
+
+ if (ktp->kt_rollover)
+- index = ktp->kt_index;
++ index = atomic_read(&ktp->kt_index) & ktp->kt_index_mask;
+ else
+ index = 0;
+
+diff --git a/fs/xfs/support/ktrace.h b/fs/xfs/support/ktrace.h
+index 56e72b4..741d694 100644
+--- a/fs/xfs/support/ktrace.h
++++ b/fs/xfs/support/ktrace.h
+@@ -30,7 +30,8 @@ typedef struct ktrace_entry {
+ */
+ typedef struct ktrace {
+ int kt_nentries; /* number of entries in trace buf */
+- int kt_index; /* current index in entries */
++ atomic_t kt_index; /* current index in entries */
++ unsigned int kt_index_mask;
+ int kt_rollover;
+ ktrace_entry_t *kt_entries; /* buffer of entries */
+ } ktrace_t;
+diff --git a/fs/xfs/xfs.h b/fs/xfs/xfs.h
+index 540e4c9..765aaf6 100644
+--- a/fs/xfs/xfs.h
++++ b/fs/xfs/xfs.h
+@@ -22,7 +22,7 @@
+ #define STATIC
+ #define DEBUG 1
+ #define XFS_BUF_LOCK_TRACKING 1
+-/* #define QUOTADEBUG 1 */
++#define QUOTADEBUG 1
+ #endif
+
+ #ifdef CONFIG_XFS_TRACE
+diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
+index 7272fe3..8e130b9 100644
+--- a/fs/xfs/xfs_acl.c
++++ b/fs/xfs/xfs_acl.c
+@@ -307,12 +307,13 @@ xfs_acl_vset(
+
+ VN_HOLD(vp);
+ error = xfs_acl_allow_set(vp, kind);
+- if (error)
+- goto out;
+
+ /* Incoming ACL exists, set file mode based on its value */
+- if (kind == _ACL_TYPE_ACCESS)
+- xfs_acl_setmode(vp, xfs_acl, &basicperms);
++ if (!error && kind == _ACL_TYPE_ACCESS)
++ error = xfs_acl_setmode(vp, xfs_acl, &basicperms);
++
++ if (error)
++ goto out;
+
+ /*
+ * If we have more than std unix permissions, set up the actual attr.
+@@ -323,7 +324,7 @@ xfs_acl_vset(
+ if (!basicperms) {
+ xfs_acl_set_attr(vp, xfs_acl, kind, &error);
+ } else {
+- xfs_acl_vremove(vp, _ACL_TYPE_ACCESS);
++ error = -xfs_acl_vremove(vp, _ACL_TYPE_ACCESS);
+ }
+
+ out:
+@@ -707,7 +708,9 @@ xfs_acl_inherit(
+
+ memcpy(cacl, pdaclp, sizeof(xfs_acl_t));
+ xfs_acl_filter_mode(mode, cacl);
+- xfs_acl_setmode(vp, cacl, &basicperms);
++ error = xfs_acl_setmode(vp, cacl, &basicperms);
++ if (error)
++ goto out_error;
+
+ /*
+ * Set the Default and Access ACL on the file. The mode is already
+@@ -720,6 +723,7 @@ xfs_acl_inherit(
+ xfs_acl_set_attr(vp, pdaclp, _ACL_TYPE_DEFAULT, &error);
+ if (!error && !basicperms)
+ xfs_acl_set_attr(vp, cacl, _ACL_TYPE_ACCESS, &error);
++out_error:
+ _ACL_FREE(cacl);
+ return error;
+ }
+diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
+index bdbfbbe..1956f83 100644
+--- a/fs/xfs/xfs_alloc.c
++++ b/fs/xfs/xfs_alloc.c
+@@ -45,7 +45,7 @@
+ #define XFSA_FIXUP_BNO_OK 1
+ #define XFSA_FIXUP_CNT_OK 2
+
+-STATIC int
++STATIC void
+ xfs_alloc_search_busy(xfs_trans_t *tp,
+ xfs_agnumber_t agno,
+ xfs_agblock_t bno,
+@@ -55,24 +55,24 @@ xfs_alloc_search_busy(xfs_trans_t *tp,
+ ktrace_t *xfs_alloc_trace_buf;
+
+ #define TRACE_ALLOC(s,a) \
+- xfs_alloc_trace_alloc(__FUNCTION__, s, a, __LINE__)
++ xfs_alloc_trace_alloc(__func__, s, a, __LINE__)
+ #define TRACE_FREE(s,a,b,x,f) \
+- xfs_alloc_trace_free(__FUNCTION__, s, mp, a, b, x, f, __LINE__)
++ xfs_alloc_trace_free(__func__, s, mp, a, b, x, f, __LINE__)
+ #define TRACE_MODAGF(s,a,f) \
+- xfs_alloc_trace_modagf(__FUNCTION__, s, mp, a, f, __LINE__)
+-#define TRACE_BUSY(__FUNCTION__,s,ag,agb,l,sl,tp) \
+- xfs_alloc_trace_busy(__FUNCTION__, s, mp, ag, agb, l, sl, tp, XFS_ALLOC_KTRACE_BUSY, __LINE__)
+-#define TRACE_UNBUSY(__FUNCTION__,s,ag,sl,tp) \
+- xfs_alloc_trace_busy(__FUNCTION__, s, mp, ag, -1, -1, sl, tp, XFS_ALLOC_KTRACE_UNBUSY, __LINE__)
+-#define TRACE_BUSYSEARCH(__FUNCTION__,s,ag,agb,l,sl,tp) \
+- xfs_alloc_trace_busy(__FUNCTION__, s, mp, ag, agb, l, sl, tp, XFS_ALLOC_KTRACE_BUSYSEARCH, __LINE__)
++ xfs_alloc_trace_modagf(__func__, s, mp, a, f, __LINE__)
++#define TRACE_BUSY(__func__,s,ag,agb,l,sl,tp) \
++ xfs_alloc_trace_busy(__func__, s, mp, ag, agb, l, sl, tp, XFS_ALLOC_KTRACE_BUSY, __LINE__)
++#define TRACE_UNBUSY(__func__,s,ag,sl,tp) \
++ xfs_alloc_trace_busy(__func__, s, mp, ag, -1, -1, sl, tp, XFS_ALLOC_KTRACE_UNBUSY, __LINE__)
++#define TRACE_BUSYSEARCH(__func__,s,ag,agb,l,tp) \
++ xfs_alloc_trace_busy(__func__, s, mp, ag, agb, l, 0, tp, XFS_ALLOC_KTRACE_BUSYSEARCH, __LINE__)
+ #else
+ #define TRACE_ALLOC(s,a)
+ #define TRACE_FREE(s,a,b,x,f)
+ #define TRACE_MODAGF(s,a,f)
+ #define TRACE_BUSY(s,a,ag,agb,l,sl,tp)
+ #define TRACE_UNBUSY(fname,s,ag,sl,tp)
+-#define TRACE_BUSYSEARCH(fname,s,ag,agb,l,sl,tp)
++#define TRACE_BUSYSEARCH(fname,s,ag,agb,l,tp)
+ #endif /* XFS_ALLOC_TRACE */
+
+ /*
+@@ -93,7 +93,7 @@ STATIC int xfs_alloc_ag_vextent_small(xfs_alloc_arg_t *,
+ * Compute aligned version of the found extent.
+ * Takes alignment and min length into account.
+ */
+-STATIC int /* success (>= minlen) */
++STATIC void
+ xfs_alloc_compute_aligned(
+ xfs_agblock_t foundbno, /* starting block in found extent */
+ xfs_extlen_t foundlen, /* length in found extent */
+@@ -116,7 +116,6 @@ xfs_alloc_compute_aligned(
+ }
+ *resbno = bno;
+ *reslen = len;
+- return len >= minlen;
+ }
+
+ /*
+@@ -837,9 +836,9 @@ xfs_alloc_ag_vextent_near(
+ if ((error = xfs_alloc_get_rec(cnt_cur, <bno, <len, &i)))
+ goto error0;
+ XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+- if (!xfs_alloc_compute_aligned(ltbno, ltlen,
+- args->alignment, args->minlen,
+- <bnoa, <lena))
++ xfs_alloc_compute_aligned(ltbno, ltlen, args->alignment,
++ args->minlen, <bnoa, <lena);
++ if (ltlena < args->minlen)
+ continue;
+ args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen);
+ xfs_alloc_fix_len(args);
+@@ -958,9 +957,9 @@ xfs_alloc_ag_vextent_near(
+ if ((error = xfs_alloc_get_rec(bno_cur_lt, <bno, <len, &i)))
+ goto error0;
+ XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+- if (xfs_alloc_compute_aligned(ltbno, ltlen,
+- args->alignment, args->minlen,
+- <bnoa, <lena))
++ xfs_alloc_compute_aligned(ltbno, ltlen, args->alignment,
++ args->minlen, <bnoa, <lena);
++ if (ltlena >= args->minlen)
+ break;
+ if ((error = xfs_alloc_decrement(bno_cur_lt, 0, &i)))
+ goto error0;
+@@ -974,9 +973,9 @@ xfs_alloc_ag_vextent_near(
+ if ((error = xfs_alloc_get_rec(bno_cur_gt, >bno, >len, &i)))
+ goto error0;
+ XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+- if (xfs_alloc_compute_aligned(gtbno, gtlen,
+- args->alignment, args->minlen,
+- >bnoa, >lena))
++ xfs_alloc_compute_aligned(gtbno, gtlen, args->alignment,
++ args->minlen, >bnoa, >lena);
++ if (gtlena >= args->minlen)
+ break;
+ if ((error = xfs_alloc_increment(bno_cur_gt, 0, &i)))
+ goto error0;
+@@ -2562,9 +2561,10 @@ xfs_alloc_clear_busy(xfs_trans_t *tp,
+
+
+ /*
+- * returns non-zero if any of (agno,bno):len is in a busy list
++ * If we find the extent in the busy list, force the log out to get the
++ * extent out of the busy list so the caller can use it straight away.
+ */
+-STATIC int
++STATIC void
+ xfs_alloc_search_busy(xfs_trans_t *tp,
+ xfs_agnumber_t agno,
+ xfs_agblock_t bno,
+@@ -2572,7 +2572,6 @@ xfs_alloc_search_busy(xfs_trans_t *tp,
+ {
+ xfs_mount_t *mp;
+ xfs_perag_busy_t *bsy;
+- int n;
+ xfs_agblock_t uend, bend;
+ xfs_lsn_t lsn;
+ int cnt;
+@@ -2585,21 +2584,18 @@ xfs_alloc_search_busy(xfs_trans_t *tp,
+ uend = bno + len - 1;
+
+ /* search pagb_list for this slot, skipping open slots */
+- for (bsy = mp->m_perag[agno].pagb_list, n = 0;
+- cnt; bsy++, n++) {
++ for (bsy = mp->m_perag[agno].pagb_list; cnt; bsy++) {
+
+ /*
+ * (start1,length1) within (start2, length2)
+ */
+ if (bsy->busy_tp != NULL) {
+ bend = bsy->busy_start + bsy->busy_length - 1;
+- if ((bno > bend) ||
+- (uend < bsy->busy_start)) {
++ if ((bno > bend) || (uend < bsy->busy_start)) {
+ cnt--;
+ } else {
+ TRACE_BUSYSEARCH("xfs_alloc_search_busy",
+- "found1", agno, bno, len, n,
+- tp);
++ "found1", agno, bno, len, tp);
+ break;
+ }
+ }
+@@ -2610,15 +2606,12 @@ xfs_alloc_search_busy(xfs_trans_t *tp,
+ * transaction that freed the block
+ */
+ if (cnt) {
+- TRACE_BUSYSEARCH("xfs_alloc_search_busy", "found", agno, bno, len, n, tp);
++ TRACE_BUSYSEARCH("xfs_alloc_search_busy", "found", agno, bno, len, tp);
+ lsn = bsy->busy_tp->t_commit_lsn;
+ spin_unlock(&mp->m_perag[agno].pagb_lock);
+ xfs_log_force(mp, lsn, XFS_LOG_FORCE|XFS_LOG_SYNC);
+ } else {
+- TRACE_BUSYSEARCH("xfs_alloc_search_busy", "not-found", agno, bno, len, n, tp);
+- n = -1;
++ TRACE_BUSYSEARCH("xfs_alloc_search_busy", "not-found", agno, bno, len, tp);
+ spin_unlock(&mp->m_perag[agno].pagb_lock);
+ }
+-
+- return n;
+ }
+diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
+index e58f321..36d781e 100644
+--- a/fs/xfs/xfs_attr.c
++++ b/fs/xfs/xfs_attr.c
+@@ -2647,14 +2647,6 @@ attr_trusted_capable(
+ }
+
+ STATIC int
+-attr_secure_capable(
+- bhv_vnode_t *vp,
+- cred_t *cred)
+-{
+- return -ENOSECURITY;
+-}
+-
+-STATIC int
+ attr_system_set(
+ bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
+ {
+@@ -2724,7 +2716,7 @@ struct attrnames attr_secure = {
+ .attr_get = attr_generic_get,
+ .attr_set = attr_generic_set,
+ .attr_remove = attr_generic_remove,
+- .attr_capable = attr_secure_capable,
++ .attr_capable = (attrcapable_t)fs_noerr,
+ };
+
+ struct attrnames attr_user = {
+diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
+index 96ba6aa..303d41e 100644
+--- a/fs/xfs/xfs_attr_leaf.c
++++ b/fs/xfs/xfs_attr_leaf.c
+@@ -166,7 +166,7 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes)
+
+ if (!(mp->m_flags & XFS_MOUNT_ATTR2)) {
+ if (bytes <= XFS_IFORK_ASIZE(dp))
+- return mp->m_attroffset >> 3;
++ return dp->i_d.di_forkoff;
+ return 0;
+ }
+
+diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
+index 2def273..eb198c0 100644
+--- a/fs/xfs/xfs_bmap.c
++++ b/fs/xfs/xfs_bmap.c
+@@ -323,13 +323,13 @@ xfs_bmap_trace_pre_update(
+ int whichfork); /* data or attr fork */
+
+ #define XFS_BMAP_TRACE_DELETE(d,ip,i,c,w) \
+- xfs_bmap_trace_delete(__FUNCTION__,d,ip,i,c,w)
++ xfs_bmap_trace_delete(__func__,d,ip,i,c,w)
+ #define XFS_BMAP_TRACE_INSERT(d,ip,i,c,r1,r2,w) \
+- xfs_bmap_trace_insert(__FUNCTION__,d,ip,i,c,r1,r2,w)
++ xfs_bmap_trace_insert(__func__,d,ip,i,c,r1,r2,w)
+ #define XFS_BMAP_TRACE_POST_UPDATE(d,ip,i,w) \
+- xfs_bmap_trace_post_update(__FUNCTION__,d,ip,i,w)
++ xfs_bmap_trace_post_update(__func__,d,ip,i,w)
+ #define XFS_BMAP_TRACE_PRE_UPDATE(d,ip,i,w) \
+- xfs_bmap_trace_pre_update(__FUNCTION__,d,ip,i,w)
++ xfs_bmap_trace_pre_update(__func__,d,ip,i,w)
+ #else
+ #define XFS_BMAP_TRACE_DELETE(d,ip,i,c,w)
+ #define XFS_BMAP_TRACE_INSERT(d,ip,i,c,r1,r2,w)
+@@ -2402,7 +2402,7 @@ xfs_bmap_extsize_align(
+
+ #define XFS_ALLOC_GAP_UNITS 4
+
+-STATIC int
++STATIC void
+ xfs_bmap_adjacent(
+ xfs_bmalloca_t *ap) /* bmap alloc argument struct */
+ {
+@@ -2548,7 +2548,6 @@ xfs_bmap_adjacent(
+ ap->rval = gotbno;
+ }
+ #undef ISVALID
+- return 0;
+ }
+
+ STATIC int
+@@ -4154,16 +4153,21 @@ xfs_bmap_compute_maxlevels(
+ * number of leaf entries, is controlled by the type of di_nextents
+ * (a signed 32-bit number, xfs_extnum_t), or by di_anextents
+ * (a signed 16-bit number, xfs_aextnum_t).
++ *
++ * Note that we can no longer assume that if we are in ATTR1 that
++ * the fork offset of all the inodes will be (m_attroffset >> 3)
++ * because we could have mounted with ATTR2 and then mounted back
++ * with ATTR1, keeping the di_forkoff's fixed but probably at
++ * various positions. Therefore, for both ATTR1 and ATTR2
++ * we have to assume the worst case scenario of a minimum size
++ * available.
+ */
+ if (whichfork == XFS_DATA_FORK) {
+ maxleafents = MAXEXTNUM;
+- sz = (mp->m_flags & XFS_MOUNT_ATTR2) ?
+- XFS_BMDR_SPACE_CALC(MINDBTPTRS) : mp->m_attroffset;
++ sz = XFS_BMDR_SPACE_CALC(MINDBTPTRS);
+ } else {
+ maxleafents = MAXAEXTNUM;
+- sz = (mp->m_flags & XFS_MOUNT_ATTR2) ?
+- XFS_BMDR_SPACE_CALC(MINABTPTRS) :
+- mp->m_sb.sb_inodesize - mp->m_attroffset;
++ sz = XFS_BMDR_SPACE_CALC(MINABTPTRS);
+ }
+ maxrootrecs = (int)XFS_BTREE_BLOCK_MAXRECS(sz, xfs_bmdr, 0);
+ minleafrecs = mp->m_bmap_dmnr[0];
+@@ -5772,7 +5776,6 @@ xfs_getbmap(
+ int error; /* return value */
+ __int64_t fixlen; /* length for -1 case */
+ int i; /* extent number */
+- bhv_vnode_t *vp; /* corresponding vnode */
+ int lock; /* lock state */
+ xfs_bmbt_irec_t *map; /* buffer for user's data */
+ xfs_mount_t *mp; /* file system mount point */
+@@ -5789,7 +5792,6 @@ xfs_getbmap(
+ int bmapi_flags; /* flags for xfs_bmapi */
+ __int32_t oflags; /* getbmapx bmv_oflags field */
+
+- vp = XFS_ITOV(ip);
+ mp = ip->i_mount;
+
+ whichfork = interface & BMV_IF_ATTRFORK ? XFS_ATTR_FORK : XFS_DATA_FORK;
+@@ -5811,7 +5813,7 @@ xfs_getbmap(
+ if ((interface & BMV_IF_NO_DMAPI_READ) == 0 &&
+ DM_EVENT_ENABLED(ip, DM_EVENT_READ) &&
+ whichfork == XFS_DATA_FORK) {
+- error = XFS_SEND_DATA(mp, DM_EVENT_READ, vp, 0, 0, 0, NULL);
++ error = XFS_SEND_DATA(mp, DM_EVENT_READ, ip, 0, 0, 0, NULL);
+ if (error)
+ return XFS_ERROR(error);
+ }
+@@ -5869,6 +5871,10 @@ xfs_getbmap(
+ /* xfs_fsize_t last_byte = xfs_file_last_byte(ip); */
+ error = xfs_flush_pages(ip, (xfs_off_t)0,
+ -1, 0, FI_REMAPF);
++ if (error) {
++ xfs_iunlock(ip, XFS_IOLOCK_SHARED);
++ return error;
++ }
+ }
+
+ ASSERT(whichfork == XFS_ATTR_FORK || ip->i_delayed_blks == 0);
+@@ -6162,10 +6168,10 @@ xfs_check_block(
+ }
+ if (*thispa == *pp) {
+ cmn_err(CE_WARN, "%s: thispa(%d) == pp(%d) %Ld",
+- __FUNCTION__, j, i,
++ __func__, j, i,
+ (unsigned long long)be64_to_cpu(*thispa));
+ panic("%s: ptrs are equal in node\n",
+- __FUNCTION__);
++ __func__);
+ }
+ }
+ }
+@@ -6192,7 +6198,7 @@ xfs_bmap_check_leaf_extents(
+ xfs_mount_t *mp; /* file system mount structure */
+ __be64 *pp; /* pointer to block address */
+ xfs_bmbt_rec_t *ep; /* pointer to current extent */
+- xfs_bmbt_rec_t *lastp; /* pointer to previous extent */
++ xfs_bmbt_rec_t last = {0, 0}; /* last extent in prev block */
+ xfs_bmbt_rec_t *nextp; /* pointer to next extent */
+ int bp_release = 0;
+
+@@ -6262,7 +6268,6 @@ xfs_bmap_check_leaf_extents(
+ /*
+ * Loop over all leaf nodes checking that all extents are in the right order.
+ */
+- lastp = NULL;
+ for (;;) {
+ xfs_fsblock_t nextbno;
+ xfs_extnum_t num_recs;
+@@ -6283,18 +6288,16 @@ xfs_bmap_check_leaf_extents(
+ */
+
+ ep = XFS_BTREE_REC_ADDR(xfs_bmbt, block, 1);
++ if (i) {
++ xfs_btree_check_rec(XFS_BTNUM_BMAP, &last, ep);
++ }
+ for (j = 1; j < num_recs; j++) {
+ nextp = XFS_BTREE_REC_ADDR(xfs_bmbt, block, j + 1);
+- if (lastp) {
+- xfs_btree_check_rec(XFS_BTNUM_BMAP,
+- (void *)lastp, (void *)ep);
+- }
+- xfs_btree_check_rec(XFS_BTNUM_BMAP, (void *)ep,
+- (void *)(nextp));
+- lastp = ep;
++ xfs_btree_check_rec(XFS_BTNUM_BMAP, ep, nextp);
+ ep = nextp;
+ }
+
++ last = *ep;
+ i += num_recs;
+ if (bp_release) {
+ bp_release = 0;
+@@ -6325,13 +6328,13 @@ xfs_bmap_check_leaf_extents(
+ return;
+
+ error0:
+- cmn_err(CE_WARN, "%s: at error0", __FUNCTION__);
++ cmn_err(CE_WARN, "%s: at error0", __func__);
+ if (bp_release)
+ xfs_trans_brelse(NULL, bp);
+ error_norelse:
+ cmn_err(CE_WARN, "%s: BAD after btree leaves for %d extents",
+- __FUNCTION__, i);
+- panic("%s: CORRUPTED BTREE OR SOMETHING", __FUNCTION__);
++ __func__, i);
++ panic("%s: CORRUPTED BTREE OR SOMETHING", __func__);
+ return;
+ }
+ #endif
+diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
+index 87224b7..6ff70cd 100644
+--- a/fs/xfs/xfs_bmap.h
++++ b/fs/xfs/xfs_bmap.h
+@@ -151,7 +151,7 @@ xfs_bmap_trace_exlist(
+ xfs_extnum_t cnt, /* count of entries in list */
+ int whichfork); /* data or attr fork */
+ #define XFS_BMAP_TRACE_EXLIST(ip,c,w) \
+- xfs_bmap_trace_exlist(__FUNCTION__,ip,c,w)
++ xfs_bmap_trace_exlist(__func__,ip,c,w)
+ #else
+ #define XFS_BMAP_TRACE_EXLIST(ip,c,w)
+ #endif
+diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
+index bd18987..4f0e849 100644
+--- a/fs/xfs/xfs_bmap_btree.c
++++ b/fs/xfs/xfs_bmap_btree.c
+@@ -275,21 +275,21 @@ xfs_bmbt_trace_cursor(
+ }
+
+ #define XFS_BMBT_TRACE_ARGBI(c,b,i) \
+- xfs_bmbt_trace_argbi(__FUNCTION__, c, b, i, __LINE__)
++ xfs_bmbt_trace_argbi(__func__, c, b, i, __LINE__)
+ #define XFS_BMBT_TRACE_ARGBII(c,b,i,j) \
+- xfs_bmbt_trace_argbii(__FUNCTION__, c, b, i, j, __LINE__)
++ xfs_bmbt_trace_argbii(__func__, c, b, i, j, __LINE__)
+ #define XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j) \
+- xfs_bmbt_trace_argfffi(__FUNCTION__, c, o, b, i, j, __LINE__)
++ xfs_bmbt_trace_argfffi(__func__, c, o, b, i, j, __LINE__)
+ #define XFS_BMBT_TRACE_ARGI(c,i) \
+- xfs_bmbt_trace_argi(__FUNCTION__, c, i, __LINE__)
++ xfs_bmbt_trace_argi(__func__, c, i, __LINE__)
+ #define XFS_BMBT_TRACE_ARGIFK(c,i,f,s) \
+- xfs_bmbt_trace_argifk(__FUNCTION__, c, i, f, s, __LINE__)
++ xfs_bmbt_trace_argifk(__func__, c, i, f, s, __LINE__)
+ #define XFS_BMBT_TRACE_ARGIFR(c,i,f,r) \
+- xfs_bmbt_trace_argifr(__FUNCTION__, c, i, f, r, __LINE__)
++ xfs_bmbt_trace_argifr(__func__, c, i, f, r, __LINE__)
+ #define XFS_BMBT_TRACE_ARGIK(c,i,k) \
+- xfs_bmbt_trace_argik(__FUNCTION__, c, i, k, __LINE__)
++ xfs_bmbt_trace_argik(__func__, c, i, k, __LINE__)
+ #define XFS_BMBT_TRACE_CURSOR(c,s) \
+- xfs_bmbt_trace_cursor(__FUNCTION__, c, s, __LINE__)
++ xfs_bmbt_trace_cursor(__func__, c, s, __LINE__)
+ #else
+ #define XFS_BMBT_TRACE_ARGBI(c,b,i)
+ #define XFS_BMBT_TRACE_ARGBII(c,b,i,j)
+@@ -2027,6 +2027,24 @@ xfs_bmbt_increment(
+
+ /*
+ * Insert the current record at the point referenced by cur.
++ *
++ * A multi-level split of the tree on insert will invalidate the original
++ * cursor. It appears, however, that some callers assume that the cursor is
++ * always valid. Hence if we do a multi-level split we need to revalidate the
++ * cursor.
++ *
++ * When a split occurs, we will see a new cursor returned. Use that as a
++ * trigger to determine if we need to revalidate the original cursor. If we get
++ * a split, then use the original irec to lookup up the path of the record we
++ * just inserted.
++ *
++ * Note that the fact that the btree root is in the inode means that we can
++ * have the level of the tree change without a "split" occurring at the root
++ * level. What happens is that the root is migrated to an allocated block and
++ * the inode root is pointed to it. This means a single split can change the
++ * level of the tree (level 2 -> level 3) and invalidate the old cursor. Hence
++ * the level change should be accounted as a split so as to correctly trigger a
++ * revalidation of the old cursor.
+ */
+ int /* error */
+ xfs_bmbt_insert(
+@@ -2039,11 +2057,14 @@ xfs_bmbt_insert(
+ xfs_fsblock_t nbno;
+ xfs_btree_cur_t *ncur;
+ xfs_bmbt_rec_t nrec;
++ xfs_bmbt_irec_t oirec; /* original irec */
+ xfs_btree_cur_t *pcur;
++ int splits = 0;
+
+ XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
+ level = 0;
+ nbno = NULLFSBLOCK;
++ oirec = cur->bc_rec.b;
+ xfs_bmbt_disk_set_all(&nrec, &cur->bc_rec.b);
+ ncur = NULL;
+ pcur = cur;
+@@ -2052,11 +2073,13 @@ xfs_bmbt_insert(
+ &i))) {
+ if (pcur != cur)
+ xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR);
+- XFS_BMBT_TRACE_CURSOR(cur, ERROR);
+- return error;
++ goto error0;
+ }
+ XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+ if (pcur != cur && (ncur || nbno == NULLFSBLOCK)) {
++ /* allocating a new root is effectively a split */
++ if (cur->bc_nlevels != pcur->bc_nlevels)
++ splits++;
+ cur->bc_nlevels = pcur->bc_nlevels;
+ cur->bc_private.b.allocated +=
+ pcur->bc_private.b.allocated;
+@@ -2070,10 +2093,21 @@ xfs_bmbt_insert(
+ xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR);
+ }
+ if (ncur) {
++ splits++;
+ pcur = ncur;
+ ncur = NULL;
+ }
+ } while (nbno != NULLFSBLOCK);
++
++ if (splits > 1) {
++ /* revalidate the old cursor as we had a multi-level split */
++ error = xfs_bmbt_lookup_eq(cur, oirec.br_startoff,
++ oirec.br_startblock, oirec.br_blockcount, &i);
++ if (error)
++ goto error0;
++ ASSERT(i == 1);
++ }
++
+ XFS_BMBT_TRACE_CURSOR(cur, EXIT);
+ *stat = i;
+ return 0;
+diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
+index 63debd1..53a71c6 100644
+--- a/fs/xfs/xfs_buf_item.c
++++ b/fs/xfs/xfs_buf_item.c
+@@ -645,7 +645,12 @@ xfs_buf_item_push(
+ bp = bip->bli_buf;
+
+ if (XFS_BUF_ISDELAYWRITE(bp)) {
+- xfs_bawrite(bip->bli_item.li_mountp, bp);
++ int error;
++ error = xfs_bawrite(bip->bli_item.li_mountp, bp);
++ if (error)
++ xfs_fs_cmn_err(CE_WARN, bip->bli_item.li_mountp,
++ "xfs_buf_item_push: pushbuf error %d on bip %p, bp %p",
++ error, bip, bp);
+ } else {
+ xfs_buf_relse(bp);
+ }
+diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
+index e92e73f..7cb2652 100644
+--- a/fs/xfs/xfs_dir2.c
++++ b/fs/xfs/xfs_dir2.c
+@@ -44,6 +44,7 @@
+ #include "xfs_error.h"
+ #include "xfs_vnodeops.h"
+
++struct xfs_name xfs_name_dotdot = {"..", 2};
+
+ void
+ xfs_dir_mount(
+@@ -146,8 +147,7 @@ int
+ xfs_dir_createname(
+ xfs_trans_t *tp,
+ xfs_inode_t *dp,
+- char *name,
+- int namelen,
++ struct xfs_name *name,
+ xfs_ino_t inum, /* new entry inode number */
+ xfs_fsblock_t *first, /* bmap's firstblock */
+ xfs_bmap_free_t *flist, /* bmap's freeblock list */
+@@ -162,9 +162,9 @@ xfs_dir_createname(
+ return rval;
+ XFS_STATS_INC(xs_dir_create);
+
+- args.name = name;
+- args.namelen = namelen;
+- args.hashval = xfs_da_hashname(name, namelen);
++ args.name = name->name;
++ args.namelen = name->len;
++ args.hashval = xfs_da_hashname(name->name, name->len);
+ args.inumber = inum;
+ args.dp = dp;
+ args.firstblock = first;
+@@ -197,8 +197,7 @@ int
+ xfs_dir_lookup(
+ xfs_trans_t *tp,
+ xfs_inode_t *dp,
+- char *name,
+- int namelen,
++ struct xfs_name *name,
+ xfs_ino_t *inum) /* out: inode number */
+ {
+ xfs_da_args_t args;
+@@ -207,18 +206,14 @@ xfs_dir_lookup(
+
+ ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
+ XFS_STATS_INC(xs_dir_lookup);
++ memset(&args, 0, sizeof(xfs_da_args_t));
+
+- args.name = name;
+- args.namelen = namelen;
+- args.hashval = xfs_da_hashname(name, namelen);
+- args.inumber = 0;
++ args.name = name->name;
++ args.namelen = name->len;
++ args.hashval = xfs_da_hashname(name->name, name->len);
+ args.dp = dp;
+- args.firstblock = NULL;
+- args.flist = NULL;
+- args.total = 0;
+ args.whichfork = XFS_DATA_FORK;
+ args.trans = tp;
+- args.justcheck = args.addname = 0;
+ args.oknoent = 1;
+
+ if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
+@@ -247,8 +242,7 @@ int
+ xfs_dir_removename(
+ xfs_trans_t *tp,
+ xfs_inode_t *dp,
+- char *name,
+- int namelen,
++ struct xfs_name *name,
+ xfs_ino_t ino,
+ xfs_fsblock_t *first, /* bmap's firstblock */
+ xfs_bmap_free_t *flist, /* bmap's freeblock list */
+@@ -261,9 +255,9 @@ xfs_dir_removename(
+ ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
+ XFS_STATS_INC(xs_dir_remove);
+
+- args.name = name;
+- args.namelen = namelen;
+- args.hashval = xfs_da_hashname(name, namelen);
++ args.name = name->name;
++ args.namelen = name->len;
++ args.hashval = xfs_da_hashname(name->name, name->len);
+ args.inumber = ino;
+ args.dp = dp;
+ args.firstblock = first;
+@@ -329,8 +323,7 @@ int
+ xfs_dir_replace(
+ xfs_trans_t *tp,
+ xfs_inode_t *dp,
+- char *name, /* name of entry to replace */
+- int namelen,
++ struct xfs_name *name, /* name of entry to replace */
+ xfs_ino_t inum, /* new inode number */
+ xfs_fsblock_t *first, /* bmap's firstblock */
+ xfs_bmap_free_t *flist, /* bmap's freeblock list */
+@@ -345,9 +338,9 @@ xfs_dir_replace(
+ if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum)))
+ return rval;
+
+- args.name = name;
+- args.namelen = namelen;
+- args.hashval = xfs_da_hashname(name, namelen);
++ args.name = name->name;
++ args.namelen = name->len;
++ args.hashval = xfs_da_hashname(name->name, name->len);
+ args.inumber = inum;
+ args.dp = dp;
+ args.firstblock = first;
+@@ -374,28 +367,29 @@ xfs_dir_replace(
+
+ /*
+ * See if this entry can be added to the directory without allocating space.
++ * First checks that the caller couldn't reserve enough space (resblks = 0).
+ */
+ int
+ xfs_dir_canenter(
+ xfs_trans_t *tp,
+ xfs_inode_t *dp,
+- char *name, /* name of entry to add */
+- int namelen)
++ struct xfs_name *name, /* name of entry to add */
++ uint resblks)
+ {
+ xfs_da_args_t args;
+ int rval;
+ int v; /* type-checking value */
+
++ if (resblks)
++ return 0;
++
+ ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
++ memset(&args, 0, sizeof(xfs_da_args_t));
+
+- args.name = name;
+- args.namelen = namelen;
+- args.hashval = xfs_da_hashname(name, namelen);
+- args.inumber = 0;
++ args.name = name->name;
++ args.namelen = name->len;
++ args.hashval = xfs_da_hashname(name->name, name->len);
+ args.dp = dp;
+- args.firstblock = NULL;
+- args.flist = NULL;
+- args.total = 0;
+ args.whichfork = XFS_DATA_FORK;
+ args.trans = tp;
+ args.justcheck = args.addname = args.oknoent = 1;
+diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h
+index b265197..6392f93 100644
+--- a/fs/xfs/xfs_dir2.h
++++ b/fs/xfs/xfs_dir2.h
+@@ -59,6 +59,8 @@ typedef __uint32_t xfs_dir2_db_t;
+ */
+ typedef xfs_off_t xfs_dir2_off_t;
+
++extern struct xfs_name xfs_name_dotdot;
++
+ /*
+ * Generic directory interface routines
+ */
+@@ -68,21 +70,21 @@ extern int xfs_dir_isempty(struct xfs_inode *dp);
+ extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp,
+ struct xfs_inode *pdp);
+ extern int xfs_dir_createname(struct xfs_trans *tp, struct xfs_inode *dp,
+- char *name, int namelen, xfs_ino_t inum,
++ struct xfs_name *name, xfs_ino_t inum,
+ xfs_fsblock_t *first,
+ struct xfs_bmap_free *flist, xfs_extlen_t tot);
+ extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp,
+- char *name, int namelen, xfs_ino_t *inum);
++ struct xfs_name *name, xfs_ino_t *inum);
+ extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp,
+- char *name, int namelen, xfs_ino_t ino,
++ struct xfs_name *name, xfs_ino_t ino,
+ xfs_fsblock_t *first,
+ struct xfs_bmap_free *flist, xfs_extlen_t tot);
+ extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp,
+- char *name, int namelen, xfs_ino_t inum,
++ struct xfs_name *name, xfs_ino_t inum,
+ xfs_fsblock_t *first,
+ struct xfs_bmap_free *flist, xfs_extlen_t tot);
+ extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp,
+- char *name, int namelen);
++ struct xfs_name *name, uint resblks);
+ extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino);
+
+ /*
+diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c
+index eb03eab..3f3785b 100644
+--- a/fs/xfs/xfs_filestream.c
++++ b/fs/xfs/xfs_filestream.c
+@@ -73,7 +73,7 @@ xfs_filestreams_trace(
+ #define TRACE4(mp,t,a0,a1,a2,a3) TRACE6(mp,t,a0,a1,a2,a3,0,0)
+ #define TRACE5(mp,t,a0,a1,a2,a3,a4) TRACE6(mp,t,a0,a1,a2,a3,a4,0)
+ #define TRACE6(mp,t,a0,a1,a2,a3,a4,a5) \
+- xfs_filestreams_trace(mp, t, __FUNCTION__, __LINE__, \
++ xfs_filestreams_trace(mp, t, __func__, __LINE__, \
+ (__psunsigned_t)a0, (__psunsigned_t)a1, \
+ (__psunsigned_t)a2, (__psunsigned_t)a3, \
+ (__psunsigned_t)a4, (__psunsigned_t)a5)
+diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
+index 5a146cb..a64dfbd 100644
+--- a/fs/xfs/xfs_ialloc.c
++++ b/fs/xfs/xfs_ialloc.c
+@@ -107,6 +107,16 @@ xfs_ialloc_log_di(
+ /*
+ * Allocation group level functions.
+ */
++static inline int
++xfs_ialloc_cluster_alignment(
++ xfs_alloc_arg_t *args)
++{
++ if (xfs_sb_version_hasalign(&args->mp->m_sb) &&
++ args->mp->m_sb.sb_inoalignmt >=
++ XFS_B_TO_FSBT(args->mp, XFS_INODE_CLUSTER_SIZE(args->mp)))
++ return args->mp->m_sb.sb_inoalignmt;
++ return 1;
++}
+
+ /*
+ * Allocate new inodes in the allocation group specified by agbp.
+@@ -167,10 +177,24 @@ xfs_ialloc_ag_alloc(
+ args.mod = args.total = args.wasdel = args.isfl =
+ args.userdata = args.minalignslop = 0;
+ args.prod = 1;
+- args.alignment = 1;
++
+ /*
+- * Allow space for the inode btree to split.
++ * We need to take into account alignment here to ensure that
++ * we don't modify the free list if we fail to have an exact
++ * block. If we don't have an exact match, and every oher
++ * attempt allocation attempt fails, we'll end up cancelling
++ * a dirty transaction and shutting down.
++ *
++ * For an exact allocation, alignment must be 1,
++ * however we need to take cluster alignment into account when
++ * fixing up the freelist. Use the minalignslop field to
++ * indicate that extra blocks might be required for alignment,
++ * but not to use them in the actual exact allocation.
+ */
++ args.alignment = 1;
++ args.minalignslop = xfs_ialloc_cluster_alignment(&args) - 1;
++
++ /* Allow space for the inode btree to split. */
+ args.minleft = XFS_IN_MAXLEVELS(args.mp) - 1;
+ if ((error = xfs_alloc_vextent(&args)))
+ return error;
+@@ -191,13 +215,8 @@ xfs_ialloc_ag_alloc(
+ ASSERT(!(args.mp->m_flags & XFS_MOUNT_NOALIGN));
+ args.alignment = args.mp->m_dalign;
+ isaligned = 1;
+- } else if (xfs_sb_version_hasalign(&args.mp->m_sb) &&
+- args.mp->m_sb.sb_inoalignmt >=
+- XFS_B_TO_FSBT(args.mp,
+- XFS_INODE_CLUSTER_SIZE(args.mp)))
+- args.alignment = args.mp->m_sb.sb_inoalignmt;
+- else
+- args.alignment = 1;
++ } else
++ args.alignment = xfs_ialloc_cluster_alignment(&args);
+ /*
+ * Need to figure out where to allocate the inode blocks.
+ * Ideally they should be spaced out through the a.g.
+@@ -230,12 +249,7 @@ xfs_ialloc_ag_alloc(
+ args.agbno = be32_to_cpu(agi->agi_root);
+ args.fsbno = XFS_AGB_TO_FSB(args.mp,
+ be32_to_cpu(agi->agi_seqno), args.agbno);
+- if (xfs_sb_version_hasalign(&args.mp->m_sb) &&
+- args.mp->m_sb.sb_inoalignmt >=
+- XFS_B_TO_FSBT(args.mp, XFS_INODE_CLUSTER_SIZE(args.mp)))
+- args.alignment = args.mp->m_sb.sb_inoalignmt;
+- else
+- args.alignment = 1;
++ args.alignment = xfs_ialloc_cluster_alignment(&args);
+ if ((error = xfs_alloc_vextent(&args)))
+ return error;
+ }
+diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
+index 8e09b71..e657c51 100644
+--- a/fs/xfs/xfs_iget.c
++++ b/fs/xfs/xfs_iget.c
+@@ -78,7 +78,6 @@ xfs_iget_core(
+ xfs_inode_t *ip;
+ xfs_inode_t *iq;
+ int error;
+- xfs_icluster_t *icl, *new_icl = NULL;
+ unsigned long first_index, mask;
+ xfs_perag_t *pag;
+ xfs_agino_t agino;
+@@ -229,11 +228,9 @@ finish_inode:
+ }
+
+ /*
+- * This is a bit messy - we preallocate everything we _might_
+- * need before we pick up the ici lock. That way we don't have to
+- * juggle locks and go all the way back to the start.
++ * Preload the radix tree so we can insert safely under the
++ * write spinlock.
+ */
+- new_icl = kmem_zone_alloc(xfs_icluster_zone, KM_SLEEP);
+ if (radix_tree_preload(GFP_KERNEL)) {
+ xfs_idestroy(ip);
+ delay(1);
+@@ -242,17 +239,6 @@ finish_inode:
+ mask = ~(((XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog)) - 1);
+ first_index = agino & mask;
+ write_lock(&pag->pag_ici_lock);
+-
+- /*
+- * Find the cluster if it exists
+- */
+- icl = NULL;
+- if (radix_tree_gang_lookup(&pag->pag_ici_root, (void**)&iq,
+- first_index, 1)) {
+- if ((XFS_INO_TO_AGINO(mp, iq->i_ino) & mask) == first_index)
+- icl = iq->i_cluster;
+- }
+-
+ /*
+ * insert the new inode
+ */
+@@ -267,30 +253,13 @@ finish_inode:
+ }
+
+ /*
+- * These values _must_ be set before releasing ihlock!
++ * These values _must_ be set before releasing the radix tree lock!
+ */
+ ip->i_udquot = ip->i_gdquot = NULL;
+ xfs_iflags_set(ip, XFS_INEW);
+
+- ASSERT(ip->i_cluster == NULL);
+-
+- if (!icl) {
+- spin_lock_init(&new_icl->icl_lock);
+- INIT_HLIST_HEAD(&new_icl->icl_inodes);
+- icl = new_icl;
+- new_icl = NULL;
+- } else {
+- ASSERT(!hlist_empty(&icl->icl_inodes));
+- }
+- spin_lock(&icl->icl_lock);
+- hlist_add_head(&ip->i_cnode, &icl->icl_inodes);
+- ip->i_cluster = icl;
+- spin_unlock(&icl->icl_lock);
+-
+ write_unlock(&pag->pag_ici_lock);
+ radix_tree_preload_end();
+- if (new_icl)
+- kmem_zone_free(xfs_icluster_zone, new_icl);
+
+ /*
+ * Link ip to its mount and thread it on the mount's inode list.
+@@ -529,18 +498,6 @@ xfs_iextract(
+ xfs_put_perag(mp, pag);
+
+ /*
+- * Remove from cluster list
+- */
+- mp = ip->i_mount;
+- spin_lock(&ip->i_cluster->icl_lock);
+- hlist_del(&ip->i_cnode);
+- spin_unlock(&ip->i_cluster->icl_lock);
+-
+- /* was last inode in cluster? */
+- if (hlist_empty(&ip->i_cluster->icl_inodes))
+- kmem_zone_free(xfs_icluster_zone, ip->i_cluster);
+-
+- /*
+ * Remove from mount's inode list.
+ */
+ XFS_MOUNT_ILOCK(mp);
+diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
+index f43a6e0..ca12acb 100644
+--- a/fs/xfs/xfs_inode.c
++++ b/fs/xfs/xfs_inode.c
+@@ -55,7 +55,6 @@
+
+ kmem_zone_t *xfs_ifork_zone;
+ kmem_zone_t *xfs_inode_zone;
+-kmem_zone_t *xfs_icluster_zone;
+
+ /*
+ * Used in xfs_itruncate(). This is the maximum number of extents
+@@ -126,6 +125,90 @@ xfs_inobp_check(
+ #endif
+
+ /*
++ * Find the buffer associated with the given inode map
++ * We do basic validation checks on the buffer once it has been
++ * retrieved from disk.
++ */
++STATIC int
++xfs_imap_to_bp(
++ xfs_mount_t *mp,
++ xfs_trans_t *tp,
++ xfs_imap_t *imap,
++ xfs_buf_t **bpp,
++ uint buf_flags,
++ uint imap_flags)
++{
++ int error;
++ int i;
++ int ni;
++ xfs_buf_t *bp;
++
++ error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap->im_blkno,
++ (int)imap->im_len, buf_flags, &bp);
++ if (error) {
++ if (error != EAGAIN) {
++ cmn_err(CE_WARN,
++ "xfs_imap_to_bp: xfs_trans_read_buf()returned "
++ "an error %d on %s. Returning error.",
++ error, mp->m_fsname);
++ } else {
++ ASSERT(buf_flags & XFS_BUF_TRYLOCK);
++ }
++ return error;
++ }
++
++ /*
++ * Validate the magic number and version of every inode in the buffer
++ * (if DEBUG kernel) or the first inode in the buffer, otherwise.
++ */
++#ifdef DEBUG
++ ni = BBTOB(imap->im_len) >> mp->m_sb.sb_inodelog;
++#else /* usual case */
++ ni = 1;
++#endif
++
++ for (i = 0; i < ni; i++) {
++ int di_ok;
++ xfs_dinode_t *dip;
++
++ dip = (xfs_dinode_t *)xfs_buf_offset(bp,
++ (i << mp->m_sb.sb_inodelog));
++ di_ok = be16_to_cpu(dip->di_core.di_magic) == XFS_DINODE_MAGIC &&
++ XFS_DINODE_GOOD_VERSION(dip->di_core.di_version);
++ if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
++ XFS_ERRTAG_ITOBP_INOTOBP,
++ XFS_RANDOM_ITOBP_INOTOBP))) {
++ if (imap_flags & XFS_IMAP_BULKSTAT) {
++ xfs_trans_brelse(tp, bp);
++ return XFS_ERROR(EINVAL);
++ }
++ XFS_CORRUPTION_ERROR("xfs_imap_to_bp",
++ XFS_ERRLEVEL_HIGH, mp, dip);
++#ifdef DEBUG
++ cmn_err(CE_PANIC,
++ "Device %s - bad inode magic/vsn "
++ "daddr %lld #%d (magic=%x)",
++ XFS_BUFTARG_NAME(mp->m_ddev_targp),
++ (unsigned long long)imap->im_blkno, i,
++ be16_to_cpu(dip->di_core.di_magic));
++#endif
++ xfs_trans_brelse(tp, bp);
++ return XFS_ERROR(EFSCORRUPTED);
++ }
++ }
++
++ xfs_inobp_check(mp, bp);
++
++ /*
++ * Mark the buffer as an inode buffer now that it looks good
++ */
++ XFS_BUF_SET_VTYPE(bp, B_FS_INO);
++
++ *bpp = bp;
++ return 0;
++}
++
++/*
+ * This routine is called to map an inode number within a file
+ * system to the buffer containing the on-disk version of the
+ * inode. It returns a pointer to the buffer containing the
+@@ -147,72 +230,19 @@ xfs_inotobp(
+ xfs_buf_t **bpp,
+ int *offset)
+ {
+- int di_ok;
+ xfs_imap_t imap;
+ xfs_buf_t *bp;
+ int error;
+- xfs_dinode_t *dip;
+
+- /*
+- * Call the space management code to find the location of the
+- * inode on disk.
+- */
+ imap.im_blkno = 0;
+ error = xfs_imap(mp, tp, ino, &imap, XFS_IMAP_LOOKUP);
+- if (error != 0) {
+- cmn_err(CE_WARN,
+- "xfs_inotobp: xfs_imap() returned an "
+- "error %d on %s. Returning error.", error, mp->m_fsname);
++ if (error)
+ return error;
+- }
+
+- /*
+- * If the inode number maps to a block outside the bounds of the
+- * file system then return NULL rather than calling read_buf
+- * and panicing when we get an error from the driver.
+- */
+- if ((imap.im_blkno + imap.im_len) >
+- XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)) {
+- cmn_err(CE_WARN,
+- "xfs_inotobp: inode number (%llu + %d) maps to a block outside the bounds "
+- "of the file system %s. Returning EINVAL.",
+- (unsigned long long)imap.im_blkno,
+- imap.im_len, mp->m_fsname);
+- return XFS_ERROR(EINVAL);
+- }
+-
+- /*
+- * Read in the buffer. If tp is NULL, xfs_trans_read_buf() will
+- * default to just a read_buf() call.
+- */
+- error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap.im_blkno,
+- (int)imap.im_len, XFS_BUF_LOCK, &bp);
+-
+- if (error) {
+- cmn_err(CE_WARN,
+- "xfs_inotobp: xfs_trans_read_buf() returned an "
+- "error %d on %s. Returning error.", error, mp->m_fsname);
++ error = xfs_imap_to_bp(mp, tp, &imap, &bp, XFS_BUF_LOCK, 0);
++ if (error)
+ return error;
+- }
+- dip = (xfs_dinode_t *)xfs_buf_offset(bp, 0);
+- di_ok =
+- be16_to_cpu(dip->di_core.di_magic) == XFS_DINODE_MAGIC &&
+- XFS_DINODE_GOOD_VERSION(dip->di_core.di_version);
+- if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP,
+- XFS_RANDOM_ITOBP_INOTOBP))) {
+- XFS_CORRUPTION_ERROR("xfs_inotobp", XFS_ERRLEVEL_LOW, mp, dip);
+- xfs_trans_brelse(tp, bp);
+- cmn_err(CE_WARN,
+- "xfs_inotobp: XFS_TEST_ERROR() returned an "
+- "error on %s. Returning EFSCORRUPTED.", mp->m_fsname);
+- return XFS_ERROR(EFSCORRUPTED);
+- }
+
+- xfs_inobp_check(mp, bp);
+-
+- /*
+- * Set *dipp to point to the on-disk inode in the buffer.
+- */
+ *dipp = (xfs_dinode_t *)xfs_buf_offset(bp, imap.im_boffset);
+ *bpp = bp;
+ *offset = imap.im_boffset;
+@@ -248,46 +278,21 @@ xfs_itobp(
+ xfs_dinode_t **dipp,
+ xfs_buf_t **bpp,
+ xfs_daddr_t bno,
+- uint imap_flags)
++ uint imap_flags,
++ uint buf_flags)
+ {
+ xfs_imap_t imap;
+ xfs_buf_t *bp;
+ int error;
+- int i;
+- int ni;
+
+ if (ip->i_blkno == (xfs_daddr_t)0) {
+- /*
+- * Call the space management code to find the location of the
+- * inode on disk.
+- */
+ imap.im_blkno = bno;
+- if ((error = xfs_imap(mp, tp, ip->i_ino, &imap,
+- XFS_IMAP_LOOKUP | imap_flags)))
++ error = xfs_imap(mp, tp, ip->i_ino, &imap,
++ XFS_IMAP_LOOKUP | imap_flags);
++ if (error)
+ return error;
+
+ /*
+- * If the inode number maps to a block outside the bounds
+- * of the file system then return NULL rather than calling
+- * read_buf and panicing when we get an error from the
+- * driver.
+- */
+- if ((imap.im_blkno + imap.im_len) >
+- XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)) {
+-#ifdef DEBUG
+- xfs_fs_cmn_err(CE_ALERT, mp, "xfs_itobp: "
+- "(imap.im_blkno (0x%llx) "
+- "+ imap.im_len (0x%llx)) > "
+- " XFS_FSB_TO_BB(mp, "
+- "mp->m_sb.sb_dblocks) (0x%llx)",
+- (unsigned long long) imap.im_blkno,
+- (unsigned long long) imap.im_len,
+- XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks));
+-#endif /* DEBUG */
+- return XFS_ERROR(EINVAL);
+- }
+-
+- /*
+ * Fill in the fields in the inode that will be used to
+ * map the inode to its buffer from now on.
+ */
+@@ -305,76 +310,17 @@ xfs_itobp(
+ }
+ ASSERT(bno == 0 || bno == imap.im_blkno);
+
+- /*
+- * Read in the buffer. If tp is NULL, xfs_trans_read_buf() will
+- * default to just a read_buf() call.
+- */
+- error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap.im_blkno,
+- (int)imap.im_len, XFS_BUF_LOCK, &bp);
+- if (error) {
+-#ifdef DEBUG
+- xfs_fs_cmn_err(CE_ALERT, mp, "xfs_itobp: "
+- "xfs_trans_read_buf() returned error %d, "
+- "imap.im_blkno 0x%llx, imap.im_len 0x%llx",
+- error, (unsigned long long) imap.im_blkno,
+- (unsigned long long) imap.im_len);
+-#endif /* DEBUG */
++ error = xfs_imap_to_bp(mp, tp, &imap, &bp, buf_flags, imap_flags);
++ if (error)
+ return error;
+- }
+-
+- /*
+- * Validate the magic number and version of every inode in the buffer
+- * (if DEBUG kernel) or the first inode in the buffer, otherwise.
+- * No validation is done here in userspace (xfs_repair).
+- */
+-#if !defined(__KERNEL__)
+- ni = 0;
+-#elif defined(DEBUG)
+- ni = BBTOB(imap.im_len) >> mp->m_sb.sb_inodelog;
+-#else /* usual case */
+- ni = 1;
+-#endif
+-
+- for (i = 0; i < ni; i++) {
+- int di_ok;
+- xfs_dinode_t *dip;
+
+- dip = (xfs_dinode_t *)xfs_buf_offset(bp,
+- (i << mp->m_sb.sb_inodelog));
+- di_ok = be16_to_cpu(dip->di_core.di_magic) == XFS_DINODE_MAGIC &&
+- XFS_DINODE_GOOD_VERSION(dip->di_core.di_version);
+- if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
+- XFS_ERRTAG_ITOBP_INOTOBP,
+- XFS_RANDOM_ITOBP_INOTOBP))) {
+- if (imap_flags & XFS_IMAP_BULKSTAT) {
+- xfs_trans_brelse(tp, bp);
+- return XFS_ERROR(EINVAL);
+- }
+-#ifdef DEBUG
+- cmn_err(CE_ALERT,
+- "Device %s - bad inode magic/vsn "
+- "daddr %lld #%d (magic=%x)",
+- XFS_BUFTARG_NAME(mp->m_ddev_targp),
+- (unsigned long long)imap.im_blkno, i,
+- be16_to_cpu(dip->di_core.di_magic));
+-#endif
+- XFS_CORRUPTION_ERROR("xfs_itobp", XFS_ERRLEVEL_HIGH,
+- mp, dip);
+- xfs_trans_brelse(tp, bp);
+- return XFS_ERROR(EFSCORRUPTED);
+- }
++ if (!bp) {
++ ASSERT(buf_flags & XFS_BUF_TRYLOCK);
++ ASSERT(tp == NULL);
++ *bpp = NULL;
++ return EAGAIN;
+ }
+
+- xfs_inobp_check(mp, bp);
+-
+- /*
+- * Mark the buffer as an inode buffer now that it looks good
+- */
+- XFS_BUF_SET_VTYPE(bp, B_FS_INO);
+-
+- /*
+- * Set *dipp to point to the on-disk inode in the buffer.
+- */
+ *dipp = (xfs_dinode_t *)xfs_buf_offset(bp, imap.im_boffset);
+ *bpp = bp;
+ return 0;
+@@ -878,7 +824,7 @@ xfs_iread(
+ * return NULL as well. Set i_blkno to 0 so that xfs_itobp() will
+ * know that this is a new incore inode.
+ */
+- error = xfs_itobp(mp, tp, ip, &dip, &bp, bno, imap_flags);
++ error = xfs_itobp(mp, tp, ip, &dip, &bp, bno, imap_flags, XFS_BUF_LOCK);
+ if (error) {
+ kmem_zone_free(xfs_inode_zone, ip);
+ return error;
+@@ -1518,51 +1464,50 @@ xfs_itruncate_start(
+ }
+
+ /*
+- * Shrink the file to the given new_size. The new
+- * size must be smaller than the current size.
+- * This will free up the underlying blocks
+- * in the removed range after a call to xfs_itruncate_start()
+- * or xfs_atruncate_start().
++ * Shrink the file to the given new_size. The new size must be smaller than
++ * the current size. This will free up the underlying blocks in the removed
++ * range after a call to xfs_itruncate_start() or xfs_atruncate_start().
+ *
+- * The transaction passed to this routine must have made
+- * a permanent log reservation of at least XFS_ITRUNCATE_LOG_RES.
+- * This routine may commit the given transaction and
+- * start new ones, so make sure everything involved in
+- * the transaction is tidy before calling here.
+- * Some transaction will be returned to the caller to be
+- * committed. The incoming transaction must already include
+- * the inode, and both inode locks must be held exclusively.
+- * The inode must also be "held" within the transaction. On
+- * return the inode will be "held" within the returned transaction.
+- * This routine does NOT require any disk space to be reserved
+- * for it within the transaction.
++ * The transaction passed to this routine must have made a permanent log
++ * reservation of at least XFS_ITRUNCATE_LOG_RES. This routine may commit the
++ * given transaction and start new ones, so make sure everything involved in
++ * the transaction is tidy before calling here. Some transaction will be
++ * returned to the caller to be committed. The incoming transaction must
++ * already include the inode, and both inode locks must be held exclusively.
++ * The inode must also be "held" within the transaction. On return the inode
++ * will be "held" within the returned transaction. This routine does NOT
++ * require any disk space to be reserved for it within the transaction.
+ *
+- * The fork parameter must be either xfs_attr_fork or xfs_data_fork,
+- * and it indicates the fork which is to be truncated. For the
+- * attribute fork we only support truncation to size 0.
++ * The fork parameter must be either xfs_attr_fork or xfs_data_fork, and it
++ * indicates the fork which is to be truncated. For the attribute fork we only
++ * support truncation to size 0.
+ *
+- * We use the sync parameter to indicate whether or not the first
+- * transaction we perform might have to be synchronous. For the attr fork,
+- * it needs to be so if the unlink of the inode is not yet known to be
+- * permanent in the log. This keeps us from freeing and reusing the
+- * blocks of the attribute fork before the unlink of the inode becomes
+- * permanent.
++ * We use the sync parameter to indicate whether or not the first transaction
++ * we perform might have to be synchronous. For the attr fork, it needs to be
++ * so if the unlink of the inode is not yet known to be permanent in the log.
++ * This keeps us from freeing and reusing the blocks of the attribute fork
++ * before the unlink of the inode becomes permanent.
+ *
+- * For the data fork, we normally have to run synchronously if we're
+- * being called out of the inactive path or we're being called
+- * out of the create path where we're truncating an existing file.
+- * Either way, the truncate needs to be sync so blocks don't reappear
+- * in the file with altered data in case of a crash. wsync filesystems
+- * can run the first case async because anything that shrinks the inode
+- * has to run sync so by the time we're called here from inactive, the
+- * inode size is permanently set to 0.
++ * For the data fork, we normally have to run synchronously if we're being
++ * called out of the inactive path or we're being called out of the create path
++ * where we're truncating an existing file. Either way, the truncate needs to
++ * be sync so blocks don't reappear in the file with altered data in case of a
++ * crash. wsync filesystems can run the first case async because anything that
++ * shrinks the inode has to run sync so by the time we're called here from
++ * inactive, the inode size is permanently set to 0.
+ *
+- * Calls from the truncate path always need to be sync unless we're
+- * in a wsync filesystem and the file has already been unlinked.
++ * Calls from the truncate path always need to be sync unless we're in a wsync
++ * filesystem and the file has already been unlinked.
+ *
+- * The caller is responsible for correctly setting the sync parameter.
+- * It gets too hard for us to guess here which path we're being called
+- * out of just based on inode state.
++ * The caller is responsible for correctly setting the sync parameter. It gets
++ * too hard for us to guess here which path we're being called out of just
++ * based on inode state.
++ *
++ * If we get an error, we must return with the inode locked and linked into the
++ * current transaction. This keeps things simple for the higher level code,
++ * because it always knows that the inode is locked and held in the transaction
++ * that returns to it whether errors occur or not. We don't mark the inode
++ * dirty on error so that transactions can be easily aborted if possible.
+ */
+ int
+ xfs_itruncate_finish(
+@@ -1741,65 +1686,51 @@ xfs_itruncate_finish(
+ */
+ error = xfs_bmap_finish(tp, &free_list, &committed);
+ ntp = *tp;
++ if (committed) {
++ /* link the inode into the next xact in the chain */
++ xfs_trans_ijoin(ntp, ip,
++ XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
++ xfs_trans_ihold(ntp, ip);
++ }
++
+ if (error) {
+ /*
+- * If the bmap finish call encounters an error,
+- * return to the caller where the transaction
+- * can be properly aborted. We just need to
+- * make sure we're not holding any resources
+- * that we were not when we came in.
++ * If the bmap finish call encounters an error, return
++ * to the caller where the transaction can be properly
++ * aborted. We just need to make sure we're not
++ * holding any resources that we were not when we came
++ * in.
+ *
+- * Aborting from this point might lose some
+- * blocks in the file system, but oh well.
++ * Aborting from this point might lose some blocks in
++ * the file system, but oh well.
+ */
+ xfs_bmap_cancel(&free_list);
+- if (committed) {
+- /*
+- * If the passed in transaction committed
+- * in xfs_bmap_finish(), then we want to
+- * add the inode to this one before returning.
+- * This keeps things simple for the higher
+- * level code, because it always knows that
+- * the inode is locked and held in the
+- * transaction that returns to it whether
+- * errors occur or not. We don't mark the
+- * inode dirty so that this transaction can
+- * be easily aborted if possible.
+- */
+- xfs_trans_ijoin(ntp, ip,
+- XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
+- xfs_trans_ihold(ntp, ip);
+- }
+ return error;
+ }
+
+ if (committed) {
+ /*
+- * The first xact was committed,
+- * so add the inode to the new one.
+- * Mark it dirty so it will be logged
+- * and moved forward in the log as
+- * part of every commit.
++ * Mark the inode dirty so it will be logged and
++ * moved forward in the log as part of every commit.
+ */
+- xfs_trans_ijoin(ntp, ip,
+- XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
+- xfs_trans_ihold(ntp, ip);
+ xfs_trans_log_inode(ntp, ip, XFS_ILOG_CORE);
+ }
++
+ ntp = xfs_trans_dup(ntp);
+- (void) xfs_trans_commit(*tp, 0);
++ error = xfs_trans_commit(*tp, 0);
+ *tp = ntp;
+- error = xfs_trans_reserve(ntp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0,
+- XFS_TRANS_PERM_LOG_RES,
+- XFS_ITRUNCATE_LOG_COUNT);
+- /*
+- * Add the inode being truncated to the next chained
+- * transaction.
+- */
++
++ /* link the inode into the next transaction in the chain */
+ xfs_trans_ijoin(ntp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
+ xfs_trans_ihold(ntp, ip);
++
++ if (!error)
++ error = xfs_trans_reserve(ntp, 0,
++ XFS_ITRUNCATE_LOG_RES(mp), 0,
++ XFS_TRANS_PERM_LOG_RES,
++ XFS_ITRUNCATE_LOG_COUNT);
+ if (error)
+- return (error);
++ return error;
+ }
+ /*
+ * Only update the size in the case of the data fork, but
+@@ -1967,7 +1898,7 @@ xfs_iunlink(
+ * Here we put the head pointer into our next pointer,
+ * and then we fall through to point the head at us.
+ */
+- error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
++ error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0, XFS_BUF_LOCK);
+ if (error)
+ return error;
+
+@@ -2075,7 +2006,7 @@ xfs_iunlink_remove(
+ * of dealing with the buffer when there is no need to
+ * change it.
+ */
+- error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
++ error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0, XFS_BUF_LOCK);
+ if (error) {
+ cmn_err(CE_WARN,
+ "xfs_iunlink_remove: xfs_itobp() returned an error %d on %s. Returning error.",
+@@ -2137,7 +2068,7 @@ xfs_iunlink_remove(
+ * Now last_ibp points to the buffer previous to us on
+ * the unlinked list. Pull us from the list.
+ */
+- error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
++ error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0, XFS_BUF_LOCK);
+ if (error) {
+ cmn_err(CE_WARN,
+ "xfs_iunlink_remove: xfs_itobp() returned an error %d on %s. Returning error.",
+@@ -2172,13 +2103,6 @@ xfs_iunlink_remove(
+ return 0;
+ }
+
+-STATIC_INLINE int xfs_inode_clean(xfs_inode_t *ip)
+-{
+- return (((ip->i_itemp == NULL) ||
+- !(ip->i_itemp->ili_format.ilf_fields & XFS_ILOG_ALL)) &&
+- (ip->i_update_core == 0));
+-}
+-
+ STATIC void
+ xfs_ifree_cluster(
+ xfs_inode_t *free_ip,
+@@ -2400,7 +2324,7 @@ xfs_ifree(
+
+ xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+
+- error = xfs_itobp(ip->i_mount, tp, ip, &dip, &ibp, 0, 0);
++ error = xfs_itobp(ip->i_mount, tp, ip, &dip, &ibp, 0, 0, XFS_BUF_LOCK);
+ if (error)
+ return error;
+
+@@ -2678,14 +2602,31 @@ xfs_imap(
+ fsbno = imap->im_blkno ?
+ XFS_DADDR_TO_FSB(mp, imap->im_blkno) : NULLFSBLOCK;
+ error = xfs_dilocate(mp, tp, ino, &fsbno, &len, &off, flags);
+- if (error != 0) {
++ if (error)
+ return error;
+- }
++
+ imap->im_blkno = XFS_FSB_TO_DADDR(mp, fsbno);
+ imap->im_len = XFS_FSB_TO_BB(mp, len);
+ imap->im_agblkno = XFS_FSB_TO_AGBNO(mp, fsbno);
+ imap->im_ioffset = (ushort)off;
+ imap->im_boffset = (ushort)(off << mp->m_sb.sb_inodelog);
++
++ /*
++ * If the inode number maps to a block outside the bounds
++ * of the file system then return NULL rather than calling
++ * read_buf and panicing when we get an error from the
++ * driver.
++ */
++ if ((imap->im_blkno + imap->im_len) >
++ XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)) {
++ xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
++ "(imap->im_blkno (0x%llx) + imap->im_len (0x%llx)) > "
++ " XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks) (0x%llx)",
++ (unsigned long long) imap->im_blkno,
++ (unsigned long long) imap->im_len,
++ XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks));
++ return EINVAL;
++ }
+ return 0;
+ }
+
+@@ -2826,38 +2767,41 @@ xfs_iunpin(
+ }
+
+ /*
+- * This is called to wait for the given inode to be unpinned.
+- * It will sleep until this happens. The caller must have the
+- * inode locked in at least shared mode so that the buffer cannot
+- * be subsequently pinned once someone is waiting for it to be
+- * unpinned.
++ * This is called to unpin an inode. It can be directed to wait or to return
++ * immediately without waiting for the inode to be unpinned. The caller must
++ * have the inode locked in at least shared mode so that the buffer cannot be
++ * subsequently pinned once someone is waiting for it to be unpinned.
+ */
+ STATIC void
+-xfs_iunpin_wait(
+- xfs_inode_t *ip)
++__xfs_iunpin_wait(
++ xfs_inode_t *ip,
++ int wait)
+ {
+- xfs_inode_log_item_t *iip;
+- xfs_lsn_t lsn;
++ xfs_inode_log_item_t *iip = ip->i_itemp;
+
+ ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE | MR_ACCESS));
+-
+- if (atomic_read(&ip->i_pincount) == 0) {
++ if (atomic_read(&ip->i_pincount) == 0)
+ return;
+- }
+
+- iip = ip->i_itemp;
+- if (iip && iip->ili_last_lsn) {
+- lsn = iip->ili_last_lsn;
+- } else {
+- lsn = (xfs_lsn_t)0;
+- }
++ /* Give the log a push to start the unpinning I/O */
++ xfs_log_force(ip->i_mount, (iip && iip->ili_last_lsn) ?
++ iip->ili_last_lsn : 0, XFS_LOG_FORCE);
++ if (wait)
++ wait_event(ip->i_ipin_wait, (atomic_read(&ip->i_pincount) == 0));
++}
+
+- /*
+- * Give the log a push so we don't wait here too long.
+- */
+- xfs_log_force(ip->i_mount, lsn, XFS_LOG_FORCE);
++static inline void
++xfs_iunpin_wait(
++ xfs_inode_t *ip)
++{
++ __xfs_iunpin_wait(ip, 1);
++}
+
+- wait_event(ip->i_ipin_wait, (atomic_read(&ip->i_pincount) == 0));
++static inline void
++xfs_iunpin_nowait(
++ xfs_inode_t *ip)
++{
++ __xfs_iunpin_wait(ip, 0);
+ }
+
+
+@@ -2932,7 +2876,7 @@ xfs_iextents_copy(
+ * format indicates the current state of the fork.
+ */
+ /*ARGSUSED*/
+-STATIC int
++STATIC void
+ xfs_iflush_fork(
+ xfs_inode_t *ip,
+ xfs_dinode_t *dip,
+@@ -2953,16 +2897,16 @@ xfs_iflush_fork(
+ static const short extflag[2] =
+ { XFS_ILOG_DEXT, XFS_ILOG_AEXT };
+
+- if (iip == NULL)
+- return 0;
++ if (!iip)
++ return;
+ ifp = XFS_IFORK_PTR(ip, whichfork);
+ /*
+ * This can happen if we gave up in iformat in an error path,
+ * for the attribute fork.
+ */
+- if (ifp == NULL) {
++ if (!ifp) {
+ ASSERT(whichfork == XFS_ATTR_FORK);
+- return 0;
++ return;
+ }
+ cp = XFS_DFORK_PTR(dip, whichfork);
+ mp = ip->i_mount;
+@@ -3023,8 +2967,145 @@ xfs_iflush_fork(
+ ASSERT(0);
+ break;
+ }
++}
++
++STATIC int
++xfs_iflush_cluster(
++ xfs_inode_t *ip,
++ xfs_buf_t *bp)
++{
++ xfs_mount_t *mp = ip->i_mount;
++ xfs_perag_t *pag = xfs_get_perag(mp, ip->i_ino);
++ unsigned long first_index, mask;
++ int ilist_size;
++ xfs_inode_t **ilist;
++ xfs_inode_t *iq;
++ int nr_found;
++ int clcount = 0;
++ int bufwasdelwri;
++ int i;
++
++ ASSERT(pag->pagi_inodeok);
++ ASSERT(pag->pag_ici_init);
++
++ ilist_size = XFS_INODE_CLUSTER_SIZE(mp) * sizeof(xfs_inode_t *);
++ ilist = kmem_alloc(ilist_size, KM_MAYFAIL);
++ if (!ilist)
++ return 0;
++
++ mask = ~(((XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog)) - 1);
++ first_index = XFS_INO_TO_AGINO(mp, ip->i_ino) & mask;
++ read_lock(&pag->pag_ici_lock);
++ /* really need a gang lookup range call here */
++ nr_found = radix_tree_gang_lookup(&pag->pag_ici_root, (void**)ilist,
++ first_index,
++ XFS_INODE_CLUSTER_SIZE(mp));
++ if (nr_found == 0)
++ goto out_free;
++
++ for (i = 0; i < nr_found; i++) {
++ iq = ilist[i];
++ if (iq == ip)
++ continue;
++ /* if the inode lies outside this cluster, we're done. */
++ if ((XFS_INO_TO_AGINO(mp, iq->i_ino) & mask) != first_index)
++ break;
++ /*
++ * Do an un-protected check to see if the inode is dirty and
++ * is a candidate for flushing. These checks will be repeated
++ * later after the appropriate locks are acquired.
++ */
++ if (xfs_inode_clean(iq) && xfs_ipincount(iq) == 0)
++ continue;
++
++ /*
++ * Try to get locks. If any are unavailable or it is pinned,
++ * then this inode cannot be flushed and is skipped.
++ */
++
++ if (!xfs_ilock_nowait(iq, XFS_ILOCK_SHARED))
++ continue;
++ if (!xfs_iflock_nowait(iq)) {
++ xfs_iunlock(iq, XFS_ILOCK_SHARED);
++ continue;
++ }
++ if (xfs_ipincount(iq)) {
++ xfs_ifunlock(iq);
++ xfs_iunlock(iq, XFS_ILOCK_SHARED);
++ continue;
++ }
++
++ /*
++ * arriving here means that this inode can be flushed. First
++ * re-check that it's dirty before flushing.
++ */
++ if (!xfs_inode_clean(iq)) {
++ int error;
++ error = xfs_iflush_int(iq, bp);
++ if (error) {
++ xfs_iunlock(iq, XFS_ILOCK_SHARED);
++ goto cluster_corrupt_out;
++ }
++ clcount++;
++ } else {
++ xfs_ifunlock(iq);
++ }
++ xfs_iunlock(iq, XFS_ILOCK_SHARED);
++ }
++
++ if (clcount) {
++ XFS_STATS_INC(xs_icluster_flushcnt);
++ XFS_STATS_ADD(xs_icluster_flushinode, clcount);
++ }
+
++out_free:
++ read_unlock(&pag->pag_ici_lock);
++ kmem_free(ilist, ilist_size);
+ return 0;
++
++
++cluster_corrupt_out:
++ /*
++ * Corruption detected in the clustering loop. Invalidate the
++ * inode buffer and shut down the filesystem.
++ */
++ read_unlock(&pag->pag_ici_lock);
++ /*
++ * Clean up the buffer. If it was B_DELWRI, just release it --
++ * brelse can handle it with no problems. If not, shut down the
++ * filesystem before releasing the buffer.
++ */
++ bufwasdelwri = XFS_BUF_ISDELAYWRITE(bp);
++ if (bufwasdelwri)
++ xfs_buf_relse(bp);
++
++ xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
++
++ if (!bufwasdelwri) {
++ /*
++ * Just like incore_relse: if we have b_iodone functions,
++ * mark the buffer as an error and call them. Otherwise
++ * mark it as stale and brelse.
++ */
++ if (XFS_BUF_IODONE_FUNC(bp)) {
++ XFS_BUF_CLR_BDSTRAT_FUNC(bp);
++ XFS_BUF_UNDONE(bp);
++ XFS_BUF_STALE(bp);
++ XFS_BUF_SHUT(bp);
++ XFS_BUF_ERROR(bp,EIO);
++ xfs_biodone(bp);
++ } else {
++ XFS_BUF_STALE(bp);
++ xfs_buf_relse(bp);
++ }
++ }
++
++ /*
++ * Unlocks the flush lock
++ */
++ xfs_iflush_abort(iq);
++ kmem_free(ilist, ilist_size);
++ return XFS_ERROR(EFSCORRUPTED);
+ }
+
+ /*
+@@ -3046,11 +3127,7 @@ xfs_iflush(
+ xfs_dinode_t *dip;
+ xfs_mount_t *mp;
+ int error;
+- /* REFERENCED */
+- xfs_inode_t *iq;
+- int clcount; /* count of inodes clustered */
+- int bufwasdelwri;
+- struct hlist_node *entry;
++ int noblock = (flags == XFS_IFLUSH_ASYNC_NOBLOCK);
+ enum { INT_DELWRI = (1 << 0), INT_ASYNC = (1 << 1) };
+
+ XFS_STATS_INC(xs_iflush_count);
+@@ -3067,8 +3144,7 @@ xfs_iflush(
+ * If the inode isn't dirty, then just release the inode
+ * flush lock and do nothing.
+ */
+- if ((ip->i_update_core == 0) &&
+- ((iip == NULL) || !(iip->ili_format.ilf_fields & XFS_ILOG_ALL))) {
++ if (xfs_inode_clean(ip)) {
+ ASSERT((iip != NULL) ?
+ !(iip->ili_item.li_flags & XFS_LI_IN_AIL) : 1);
+ xfs_ifunlock(ip);
+@@ -3076,11 +3152,21 @@ xfs_iflush(
+ }
+
+ /*
+- * We can't flush the inode until it is unpinned, so
+- * wait for it. We know noone new can pin it, because
+- * we are holding the inode lock shared and you need
+- * to hold it exclusively to pin the inode.
++ * We can't flush the inode until it is unpinned, so wait for it if we
++ * are allowed to block. We know noone new can pin it, because we are
++ * holding the inode lock shared and you need to hold it exclusively to
++ * pin the inode.
++ *
++ * If we are not allowed to block, force the log out asynchronously so
++ * that when we come back the inode will be unpinned. If other inodes
++ * in the same cluster are dirty, they will probably write the inode
++ * out for us if they occur after the log force completes.
+ */
++ if (noblock && xfs_ipincount(ip)) {
++ xfs_iunpin_nowait(ip);
++ xfs_ifunlock(ip);
++ return EAGAIN;
++ }
+ xfs_iunpin_wait(ip);
+
+ /*
+@@ -3097,15 +3183,6 @@ xfs_iflush(
+ }
+
+ /*
+- * Get the buffer containing the on-disk inode.
+- */
+- error = xfs_itobp(mp, NULL, ip, &dip, &bp, 0, 0);
+- if (error) {
+- xfs_ifunlock(ip);
+- return error;
+- }
+-
+- /*
+ * Decide how buffer will be flushed out. This is done before
+ * the call to xfs_iflush_int because this field is zeroed by it.
+ */
+@@ -3121,6 +3198,7 @@ xfs_iflush(
+ case XFS_IFLUSH_DELWRI_ELSE_SYNC:
+ flags = 0;
+ break;
++ case XFS_IFLUSH_ASYNC_NOBLOCK:
+ case XFS_IFLUSH_ASYNC:
+ case XFS_IFLUSH_DELWRI_ELSE_ASYNC:
+ flags = INT_ASYNC;
+@@ -3140,6 +3218,7 @@ xfs_iflush(
+ case XFS_IFLUSH_DELWRI:
+ flags = INT_DELWRI;
+ break;
++ case XFS_IFLUSH_ASYNC_NOBLOCK:
+ case XFS_IFLUSH_ASYNC:
+ flags = INT_ASYNC;
+ break;
+@@ -3154,94 +3233,41 @@ xfs_iflush(
+ }
+
+ /*
+- * First flush out the inode that xfs_iflush was called with.
++ * Get the buffer containing the on-disk inode.
+ */
+- error = xfs_iflush_int(ip, bp);
+- if (error) {
+- goto corrupt_out;
++ error = xfs_itobp(mp, NULL, ip, &dip, &bp, 0, 0,
++ noblock ? XFS_BUF_TRYLOCK : XFS_BUF_LOCK);
++ if (error || !bp) {
++ xfs_ifunlock(ip);
++ return error;
+ }
+
+ /*
+- * inode clustering:
+- * see if other inodes can be gathered into this write
++ * First flush out the inode that xfs_iflush was called with.
+ */
+- spin_lock(&ip->i_cluster->icl_lock);
+- ip->i_cluster->icl_buf = bp;
+-
+- clcount = 0;
+- hlist_for_each_entry(iq, entry, &ip->i_cluster->icl_inodes, i_cnode) {
+- if (iq == ip)
+- continue;
+-
+- /*
+- * Do an un-protected check to see if the inode is dirty and
+- * is a candidate for flushing. These checks will be repeated
+- * later after the appropriate locks are acquired.
+- */
+- iip = iq->i_itemp;
+- if ((iq->i_update_core == 0) &&
+- ((iip == NULL) ||
+- !(iip->ili_format.ilf_fields & XFS_ILOG_ALL)) &&
+- xfs_ipincount(iq) == 0) {
+- continue;
+- }
+-
+- /*
+- * Try to get locks. If any are unavailable,
+- * then this inode cannot be flushed and is skipped.
+- */
+-
+- /* get inode locks (just i_lock) */
+- if (xfs_ilock_nowait(iq, XFS_ILOCK_SHARED)) {
+- /* get inode flush lock */
+- if (xfs_iflock_nowait(iq)) {
+- /* check if pinned */
+- if (xfs_ipincount(iq) == 0) {
+- /* arriving here means that
+- * this inode can be flushed.
+- * first re-check that it's
+- * dirty
+- */
+- iip = iq->i_itemp;
+- if ((iq->i_update_core != 0)||
+- ((iip != NULL) &&
+- (iip->ili_format.ilf_fields & XFS_ILOG_ALL))) {
+- clcount++;
+- error = xfs_iflush_int(iq, bp);
+- if (error) {
+- xfs_iunlock(iq,
+- XFS_ILOCK_SHARED);
+- goto cluster_corrupt_out;
+- }
+- } else {
+- xfs_ifunlock(iq);
+- }
+- } else {
+- xfs_ifunlock(iq);
+- }
+- }
+- xfs_iunlock(iq, XFS_ILOCK_SHARED);
+- }
+- }
+- spin_unlock(&ip->i_cluster->icl_lock);
+-
+- if (clcount) {
+- XFS_STATS_INC(xs_icluster_flushcnt);
+- XFS_STATS_ADD(xs_icluster_flushinode, clcount);
+- }
++ error = xfs_iflush_int(ip, bp);
++ if (error)
++ goto corrupt_out;
+
+ /*
+- * If the buffer is pinned then push on the log so we won't
++ * If the buffer is pinned then push on the log now so we won't
+ * get stuck waiting in the write for too long.
+ */
+- if (XFS_BUF_ISPINNED(bp)){
++ if (XFS_BUF_ISPINNED(bp))
+ xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE);
+- }
++
++ /*
++ * inode clustering:
++ * see if other inodes can be gathered into this write
++ */
++ error = xfs_iflush_cluster(ip, bp);
++ if (error)
++ goto cluster_corrupt_out;
+
+ if (flags & INT_DELWRI) {
+ xfs_bdwrite(mp, bp);
+ } else if (flags & INT_ASYNC) {
+- xfs_bawrite(mp, bp);
++ error = xfs_bawrite(mp, bp);
+ } else {
+ error = xfs_bwrite(mp, bp);
+ }
+@@ -3250,52 +3276,11 @@ xfs_iflush(
+ corrupt_out:
+ xfs_buf_relse(bp);
+ xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
+- xfs_iflush_abort(ip);
+- /*
+- * Unlocks the flush lock
+- */
+- return XFS_ERROR(EFSCORRUPTED);
+-
+ cluster_corrupt_out:
+- /* Corruption detected in the clustering loop. Invalidate the
+- * inode buffer and shut down the filesystem.
+- */
+- spin_unlock(&ip->i_cluster->icl_lock);
+-
+- /*
+- * Clean up the buffer. If it was B_DELWRI, just release it --
+- * brelse can handle it with no problems. If not, shut down the
+- * filesystem before releasing the buffer.
+- */
+- if ((bufwasdelwri= XFS_BUF_ISDELAYWRITE(bp))) {
+- xfs_buf_relse(bp);
+- }
+-
+- xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
+-
+- if(!bufwasdelwri) {
+- /*
+- * Just like incore_relse: if we have b_iodone functions,
+- * mark the buffer as an error and call them. Otherwise
+- * mark it as stale and brelse.
+- */
+- if (XFS_BUF_IODONE_FUNC(bp)) {
+- XFS_BUF_CLR_BDSTRAT_FUNC(bp);
+- XFS_BUF_UNDONE(bp);
+- XFS_BUF_STALE(bp);
+- XFS_BUF_SHUT(bp);
+- XFS_BUF_ERROR(bp,EIO);
+- xfs_biodone(bp);
+- } else {
+- XFS_BUF_STALE(bp);
+- xfs_buf_relse(bp);
+- }
+- }
+-
+- xfs_iflush_abort(iq);
+ /*
+ * Unlocks the flush lock
+ */
++ xfs_iflush_abort(ip);
+ return XFS_ERROR(EFSCORRUPTED);
+ }
+
+@@ -3325,8 +3310,7 @@ xfs_iflush_int(
+ * If the inode isn't dirty, then just release the inode
+ * flush lock and do nothing.
+ */
+- if ((ip->i_update_core == 0) &&
+- ((iip == NULL) || !(iip->ili_format.ilf_fields & XFS_ILOG_ALL))) {
++ if (xfs_inode_clean(ip)) {
+ xfs_ifunlock(ip);
+ return 0;
+ }
+@@ -3459,16 +3443,9 @@ xfs_iflush_int(
+ }
+ }
+
+- if (xfs_iflush_fork(ip, dip, iip, XFS_DATA_FORK, bp) == EFSCORRUPTED) {
+- goto corrupt_out;
+- }
+-
+- if (XFS_IFORK_Q(ip)) {
+- /*
+- * The only error from xfs_iflush_fork is on the data fork.
+- */
+- (void) xfs_iflush_fork(ip, dip, iip, XFS_ATTR_FORK, bp);
+- }
++ xfs_iflush_fork(ip, dip, iip, XFS_DATA_FORK, bp);
++ if (XFS_IFORK_Q(ip))
++ xfs_iflush_fork(ip, dip, iip, XFS_ATTR_FORK, bp);
+ xfs_inobp_check(mp, bp);
+
+ /*
+diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
+index bfcd72c..93c3769 100644
+--- a/fs/xfs/xfs_inode.h
++++ b/fs/xfs/xfs_inode.h
+@@ -133,19 +133,6 @@ typedef struct dm_attrs_s {
+ } dm_attrs_t;
+
+ /*
+- * This is the xfs inode cluster structure. This structure is used by
+- * xfs_iflush to find inodes that share a cluster and can be flushed to disk at
+- * the same time.
+- */
+-typedef struct xfs_icluster {
+- struct hlist_head icl_inodes; /* list of inodes on cluster */
+- xfs_daddr_t icl_blkno; /* starting block number of
+- * the cluster */
+- struct xfs_buf *icl_buf; /* the inode buffer */
+- spinlock_t icl_lock; /* inode list lock */
+-} xfs_icluster_t;
+-
+-/*
+ * This is the xfs in-core inode structure.
+ * Most of the on-disk inode is embedded in the i_d field.
+ *
+@@ -240,10 +227,6 @@ typedef struct xfs_inode {
+ atomic_t i_pincount; /* inode pin count */
+ wait_queue_head_t i_ipin_wait; /* inode pinning wait queue */
+ spinlock_t i_flags_lock; /* inode i_flags lock */
+-#ifdef HAVE_REFCACHE
+- struct xfs_inode **i_refcache; /* ptr to entry in ref cache */
+- struct xfs_inode *i_release; /* inode to unref */
+-#endif
+ /* Miscellaneous state. */
+ unsigned short i_flags; /* see defined flags below */
+ unsigned char i_update_core; /* timestamps/size is dirty */
+@@ -252,8 +235,6 @@ typedef struct xfs_inode {
+ unsigned int i_delayed_blks; /* count of delay alloc blks */
+
+ xfs_icdinode_t i_d; /* most of ondisk inode */
+- xfs_icluster_t *i_cluster; /* cluster list header */
+- struct hlist_node i_cnode; /* cluster link node */
+
+ xfs_fsize_t i_size; /* in-memory size */
+ xfs_fsize_t i_new_size; /* size when write completes */
+@@ -461,6 +442,7 @@ xfs_iflags_test_and_clear(xfs_inode_t *ip, unsigned short flags)
+ #define XFS_IFLUSH_SYNC 3
+ #define XFS_IFLUSH_ASYNC 4
+ #define XFS_IFLUSH_DELWRI 5
++#define XFS_IFLUSH_ASYNC_NOBLOCK 6
+
+ /*
+ * Flags for xfs_itruncate_start().
+@@ -515,7 +497,7 @@ int xfs_finish_reclaim_all(struct xfs_mount *, int);
+ */
+ int xfs_itobp(struct xfs_mount *, struct xfs_trans *,
+ xfs_inode_t *, struct xfs_dinode **, struct xfs_buf **,
+- xfs_daddr_t, uint);
++ xfs_daddr_t, uint, uint);
+ int xfs_iread(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
+ xfs_inode_t **, xfs_daddr_t, uint);
+ int xfs_iread_extents(struct xfs_trans *, xfs_inode_t *, int);
+@@ -597,7 +579,6 @@ void xfs_inobp_check(struct xfs_mount *, struct xfs_buf *);
+ #define xfs_inobp_check(mp, bp)
+ #endif /* DEBUG */
+
+-extern struct kmem_zone *xfs_icluster_zone;
+ extern struct kmem_zone *xfs_ifork_zone;
+ extern struct kmem_zone *xfs_inode_zone;
+ extern struct kmem_zone *xfs_ili_zone;
+diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
+index 2c775b4..93b5db4 100644
+--- a/fs/xfs/xfs_inode_item.c
++++ b/fs/xfs/xfs_inode_item.c
+@@ -40,6 +40,7 @@
+ #include "xfs_btree.h"
+ #include "xfs_ialloc.h"
+ #include "xfs_rw.h"
++#include "xfs_error.h"
+
+
+ kmem_zone_t *xfs_ili_zone; /* inode log item zone */
+@@ -813,7 +814,12 @@ xfs_inode_item_pushbuf(
+ XFS_LOG_FORCE);
+ }
+ if (dopush) {
+- xfs_bawrite(mp, bp);
++ int error;
++ error = xfs_bawrite(mp, bp);
++ if (error)
++ xfs_fs_cmn_err(CE_WARN, mp,
++ "xfs_inode_item_pushbuf: pushbuf error %d on iip %p, bp %p",
++ error, iip, bp);
+ } else {
+ xfs_buf_relse(bp);
+ }
+diff --git a/fs/xfs/xfs_inode_item.h b/fs/xfs/xfs_inode_item.h
+index bfe92ea..4051307 100644
+--- a/fs/xfs/xfs_inode_item.h
++++ b/fs/xfs/xfs_inode_item.h
+@@ -168,6 +168,14 @@ static inline int xfs_ilog_fext(int w)
+ return (w == XFS_DATA_FORK ? XFS_ILOG_DEXT : XFS_ILOG_AEXT);
+ }
+
++static inline int xfs_inode_clean(xfs_inode_t *ip)
++{
++ return (!ip->i_itemp ||
++ !(ip->i_itemp->ili_format.ilf_fields & XFS_ILOG_ALL)) &&
++ !ip->i_update_core;
++}
++
++
+ #ifdef __KERNEL__
+
+ extern void xfs_inode_item_init(struct xfs_inode *, struct xfs_mount *);
+diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
+index fde37f8..fb3cf11 100644
+--- a/fs/xfs/xfs_iomap.c
++++ b/fs/xfs/xfs_iomap.c
+@@ -802,8 +802,11 @@ xfs_iomap_write_allocate(
+ */
+ nimaps = 1;
+ end_fsb = XFS_B_TO_FSB(mp, ip->i_size);
+- xfs_bmap_last_offset(NULL, ip, &last_block,
+- XFS_DATA_FORK);
++ error = xfs_bmap_last_offset(NULL, ip, &last_block,
++ XFS_DATA_FORK);
++ if (error)
++ goto trans_cancel;
++
+ last_block = XFS_FILEOFF_MAX(last_block, end_fsb);
+ if ((map_start_fsb + count_fsb) > last_block) {
+ count_fsb = last_block - map_start_fsb;
+diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
+index f615e04..eb85bde 100644
+--- a/fs/xfs/xfs_itable.c
++++ b/fs/xfs/xfs_itable.c
+@@ -129,7 +129,7 @@ xfs_bulkstat_one_iget(
+ return error;
+ }
+
+-STATIC int
++STATIC void
+ xfs_bulkstat_one_dinode(
+ xfs_mount_t *mp, /* mount point for filesystem */
+ xfs_ino_t ino, /* inode number to get data for */
+@@ -198,8 +198,6 @@ xfs_bulkstat_one_dinode(
+ buf->bs_blocks = be64_to_cpu(dic->di_nblocks);
+ break;
+ }
+-
+- return 0;
+ }
+
+ STATIC int
+@@ -614,7 +612,8 @@ xfs_bulkstat(
+ xfs_buf_relse(bp);
+ error = xfs_itobp(mp, NULL, ip,
+ &dip, &bp, bno,
+- XFS_IMAP_BULKSTAT);
++ XFS_IMAP_BULKSTAT,
++ XFS_BUF_LOCK);
+ if (!error)
+ clustidx = ip->i_boffset / mp->m_sb.sb_inodesize;
+ kmem_zone_free(xfs_inode_zone, ip);
+diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
+index 31f2b04..afaee30 100644
+--- a/fs/xfs/xfs_log.c
++++ b/fs/xfs/xfs_log.c
+@@ -41,6 +41,7 @@
+ #include "xfs_inode.h"
+ #include "xfs_rw.h"
+
++kmem_zone_t *xfs_log_ticket_zone;
+
+ #define xlog_write_adv_cnt(ptr, len, off, bytes) \
+ { (ptr) += (bytes); \
+@@ -73,8 +74,6 @@ STATIC int xlog_state_get_iclog_space(xlog_t *log,
+ xlog_ticket_t *ticket,
+ int *continued_write,
+ int *logoffsetp);
+-STATIC void xlog_state_put_ticket(xlog_t *log,
+- xlog_ticket_t *tic);
+ STATIC int xlog_state_release_iclog(xlog_t *log,
+ xlog_in_core_t *iclog);
+ STATIC void xlog_state_switch_iclogs(xlog_t *log,
+@@ -101,7 +100,6 @@ STATIC void xlog_ungrant_log_space(xlog_t *log,
+
+
+ /* local ticket functions */
+-STATIC void xlog_state_ticket_alloc(xlog_t *log);
+ STATIC xlog_ticket_t *xlog_ticket_get(xlog_t *log,
+ int unit_bytes,
+ int count,
+@@ -330,7 +328,7 @@ xfs_log_done(xfs_mount_t *mp,
+ */
+ xlog_trace_loggrant(log, ticket, "xfs_log_done: (non-permanent)");
+ xlog_ungrant_log_space(log, ticket);
+- xlog_state_put_ticket(log, ticket);
++ xlog_ticket_put(log, ticket);
+ } else {
+ xlog_trace_loggrant(log, ticket, "xfs_log_done: (permanent)");
+ xlog_regrant_reserve_log_space(log, ticket);
+@@ -384,7 +382,27 @@ _xfs_log_force(
+ return xlog_state_sync_all(log, flags, log_flushed);
+ else
+ return xlog_state_sync(log, lsn, flags, log_flushed);
+-} /* xfs_log_force */
++} /* _xfs_log_force */
++
++/*
++ * Wrapper for _xfs_log_force(), to be used when caller doesn't care
++ * about errors or whether the log was flushed or not. This is the normal
++ * interface to use when trying to unpin items or move the log forward.
++ */
++void
++xfs_log_force(
++ xfs_mount_t *mp,
++ xfs_lsn_t lsn,
++ uint flags)
++{
++ int error;
++ error = _xfs_log_force(mp, lsn, flags, NULL);
++ if (error) {
++ xfs_fs_cmn_err(CE_WARN, mp, "xfs_log_force: "
++ "error %d returned.", error);
++ }
++}
++
+
+ /*
+ * Attaches a new iclog I/O completion callback routine during
+@@ -397,12 +415,10 @@ xfs_log_notify(xfs_mount_t *mp, /* mount of partition */
+ void *iclog_hndl, /* iclog to hang callback off */
+ xfs_log_callback_t *cb)
+ {
+- xlog_t *log = mp->m_log;
+ xlog_in_core_t *iclog = (xlog_in_core_t *)iclog_hndl;
+ int abortflg;
+
+- cb->cb_next = NULL;
+- spin_lock(&log->l_icloglock);
++ spin_lock(&iclog->ic_callback_lock);
+ abortflg = (iclog->ic_state & XLOG_STATE_IOERROR);
+ if (!abortflg) {
+ ASSERT_ALWAYS((iclog->ic_state == XLOG_STATE_ACTIVE) ||
+@@ -411,7 +427,7 @@ xfs_log_notify(xfs_mount_t *mp, /* mount of partition */
+ *(iclog->ic_callback_tail) = cb;
+ iclog->ic_callback_tail = &(cb->cb_next);
+ }
+- spin_unlock(&log->l_icloglock);
++ spin_unlock(&iclog->ic_callback_lock);
+ return abortflg;
+ } /* xfs_log_notify */
+
+@@ -471,6 +487,8 @@ xfs_log_reserve(xfs_mount_t *mp,
+ /* may sleep if need to allocate more tickets */
+ internal_ticket = xlog_ticket_get(log, unit_bytes, cnt,
+ client, flags);
++ if (!internal_ticket)
++ return XFS_ERROR(ENOMEM);
+ internal_ticket->t_trans_type = t_type;
+ *ticket = internal_ticket;
+ xlog_trace_loggrant(log, internal_ticket,
+@@ -636,7 +654,8 @@ xfs_log_unmount_write(xfs_mount_t *mp)
+ if (mp->m_flags & XFS_MOUNT_RDONLY)
+ return 0;
+
+- xfs_log_force(mp, 0, XFS_LOG_FORCE|XFS_LOG_SYNC);
++ error = _xfs_log_force(mp, 0, XFS_LOG_FORCE|XFS_LOG_SYNC, NULL);
++ ASSERT(error || !(XLOG_FORCED_SHUTDOWN(log)));
+
+ #ifdef DEBUG
+ first_iclog = iclog = log->l_iclog;
+@@ -675,10 +694,10 @@ xfs_log_unmount_write(xfs_mount_t *mp)
+
+ spin_lock(&log->l_icloglock);
+ iclog = log->l_iclog;
+- iclog->ic_refcnt++;
++ atomic_inc(&iclog->ic_refcnt);
+ spin_unlock(&log->l_icloglock);
+ xlog_state_want_sync(log, iclog);
+- (void) xlog_state_release_iclog(log, iclog);
++ error = xlog_state_release_iclog(log, iclog);
+
+ spin_lock(&log->l_icloglock);
+ if (!(iclog->ic_state == XLOG_STATE_ACTIVE ||
+@@ -695,7 +714,7 @@ xfs_log_unmount_write(xfs_mount_t *mp)
+ if (tic) {
+ xlog_trace_loggrant(log, tic, "unmount rec");
+ xlog_ungrant_log_space(log, tic);
+- xlog_state_put_ticket(log, tic);
++ xlog_ticket_put(log, tic);
+ }
+ } else {
+ /*
+@@ -713,11 +732,11 @@ xfs_log_unmount_write(xfs_mount_t *mp)
+ */
+ spin_lock(&log->l_icloglock);
+ iclog = log->l_iclog;
+- iclog->ic_refcnt++;
++ atomic_inc(&iclog->ic_refcnt);
+ spin_unlock(&log->l_icloglock);
+
+ xlog_state_want_sync(log, iclog);
+- (void) xlog_state_release_iclog(log, iclog);
++ error = xlog_state_release_iclog(log, iclog);
+
+ spin_lock(&log->l_icloglock);
+
+@@ -732,7 +751,7 @@ xfs_log_unmount_write(xfs_mount_t *mp)
+ }
+ }
+
+- return 0;
++ return error;
+ } /* xfs_log_unmount_write */
+
+ /*
+@@ -1210,7 +1229,6 @@ xlog_alloc_log(xfs_mount_t *mp,
+ spin_lock_init(&log->l_icloglock);
+ spin_lock_init(&log->l_grant_lock);
+ initnsema(&log->l_flushsema, 0, "ic-flush");
+- xlog_state_ticket_alloc(log); /* wait until after icloglock inited */
+
+ /* log record size must be multiple of BBSIZE; see xlog_rec_header_t */
+ ASSERT((XFS_BUF_SIZE(bp) & BBMASK) == 0);
+@@ -1240,9 +1258,9 @@ xlog_alloc_log(xfs_mount_t *mp,
+ XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
+ iclog->ic_bp = bp;
+ iclog->hic_data = bp->b_addr;
+-
++#ifdef DEBUG
+ log->l_iclog_bak[i] = (xfs_caddr_t)&(iclog->ic_header);
+-
++#endif
+ head = &iclog->ic_header;
+ memset(head, 0, sizeof(xlog_rec_header_t));
+ head->h_magicno = cpu_to_be32(XLOG_HEADER_MAGIC_NUM);
+@@ -1253,10 +1271,11 @@ xlog_alloc_log(xfs_mount_t *mp,
+ head->h_fmt = cpu_to_be32(XLOG_FMT);
+ memcpy(&head->h_fs_uuid, &mp->m_sb.sb_uuid, sizeof(uuid_t));
+
+-
+ iclog->ic_size = XFS_BUF_SIZE(bp) - log->l_iclog_hsize;
+ iclog->ic_state = XLOG_STATE_ACTIVE;
+ iclog->ic_log = log;
++ atomic_set(&iclog->ic_refcnt, 0);
++ spin_lock_init(&iclog->ic_callback_lock);
+ iclog->ic_callback_tail = &(iclog->ic_callback);
+ iclog->ic_datap = (char *)iclog->hic_data + log->l_iclog_hsize;
+
+@@ -1405,7 +1424,7 @@ xlog_sync(xlog_t *log,
+ int v2 = xfs_sb_version_haslogv2(&log->l_mp->m_sb);
+
+ XFS_STATS_INC(xs_log_writes);
+- ASSERT(iclog->ic_refcnt == 0);
++ ASSERT(atomic_read(&iclog->ic_refcnt) == 0);
+
+ /* Add for LR header */
+ count_init = log->l_iclog_hsize + iclog->ic_offset;
+@@ -1538,7 +1557,6 @@ STATIC void
+ xlog_dealloc_log(xlog_t *log)
+ {
+ xlog_in_core_t *iclog, *next_iclog;
+- xlog_ticket_t *tic, *next_tic;
+ int i;
+
+ iclog = log->l_iclog;
+@@ -1559,22 +1577,6 @@ xlog_dealloc_log(xlog_t *log)
+ spinlock_destroy(&log->l_icloglock);
+ spinlock_destroy(&log->l_grant_lock);
+
+- /* XXXsup take a look at this again. */
+- if ((log->l_ticket_cnt != log->l_ticket_tcnt) &&
+- !XLOG_FORCED_SHUTDOWN(log)) {
+- xfs_fs_cmn_err(CE_WARN, log->l_mp,
+- "xlog_dealloc_log: (cnt: %d, total: %d)",
+- log->l_ticket_cnt, log->l_ticket_tcnt);
+- /* ASSERT(log->l_ticket_cnt == log->l_ticket_tcnt); */
+-
+- } else {
+- tic = log->l_unmount_free;
+- while (tic) {
+- next_tic = tic->t_next;
+- kmem_free(tic, PAGE_SIZE);
+- tic = next_tic;
+- }
+- }
+ xfs_buf_free(log->l_xbuf);
+ #ifdef XFS_LOG_TRACE
+ if (log->l_trace != NULL) {
+@@ -1987,7 +1989,7 @@ xlog_state_clean_log(xlog_t *log)
+ if (iclog->ic_state == XLOG_STATE_DIRTY) {
+ iclog->ic_state = XLOG_STATE_ACTIVE;
+ iclog->ic_offset = 0;
+- iclog->ic_callback = NULL; /* don't need to free */
++ ASSERT(iclog->ic_callback == NULL);
+ /*
+ * If the number of ops in this iclog indicate it just
+ * contains the dummy transaction, we can
+@@ -2190,37 +2192,40 @@ xlog_state_do_callback(
+ be64_to_cpu(iclog->ic_header.h_lsn);
+ spin_unlock(&log->l_grant_lock);
+
+- /*
+- * Keep processing entries in the callback list
+- * until we come around and it is empty. We
+- * need to atomically see that the list is
+- * empty and change the state to DIRTY so that
+- * we don't miss any more callbacks being added.
+- */
+- spin_lock(&log->l_icloglock);
+ } else {
++ spin_unlock(&log->l_icloglock);
+ ioerrors++;
+ }
+- cb = iclog->ic_callback;
+
++ /*
++ * Keep processing entries in the callback list until
++ * we come around and it is empty. We need to
++ * atomically see that the list is empty and change the
++ * state to DIRTY so that we don't miss any more
++ * callbacks being added.
++ */
++ spin_lock(&iclog->ic_callback_lock);
++ cb = iclog->ic_callback;
+ while (cb) {
+ iclog->ic_callback_tail = &(iclog->ic_callback);
+ iclog->ic_callback = NULL;
+- spin_unlock(&log->l_icloglock);
++ spin_unlock(&iclog->ic_callback_lock);
+
+ /* perform callbacks in the order given */
+ for (; cb; cb = cb_next) {
+ cb_next = cb->cb_next;
+ cb->cb_func(cb->cb_arg, aborted);
+ }
+- spin_lock(&log->l_icloglock);
++ spin_lock(&iclog->ic_callback_lock);
+ cb = iclog->ic_callback;
+ }
+
+ loopdidcallbacks++;
+ funcdidcallbacks++;
+
++ spin_lock(&log->l_icloglock);
+ ASSERT(iclog->ic_callback == NULL);
++ spin_unlock(&iclog->ic_callback_lock);
+ if (!(iclog->ic_state & XLOG_STATE_IOERROR))
+ iclog->ic_state = XLOG_STATE_DIRTY;
+
+@@ -2241,7 +2246,7 @@ xlog_state_do_callback(
+ repeats = 0;
+ xfs_fs_cmn_err(CE_WARN, log->l_mp,
+ "%s: possible infinite loop (%d iterations)",
+- __FUNCTION__, flushcnt);
++ __func__, flushcnt);
+ }
+ } while (!ioerrors && loopdidcallbacks);
+
+@@ -2309,7 +2314,7 @@ xlog_state_done_syncing(
+
+ ASSERT(iclog->ic_state == XLOG_STATE_SYNCING ||
+ iclog->ic_state == XLOG_STATE_IOERROR);
+- ASSERT(iclog->ic_refcnt == 0);
++ ASSERT(atomic_read(&iclog->ic_refcnt) == 0);
+ ASSERT(iclog->ic_bwritecnt == 1 || iclog->ic_bwritecnt == 2);
+
+
+@@ -2391,7 +2396,7 @@ restart:
+ ASSERT(iclog->ic_state == XLOG_STATE_ACTIVE);
+ head = &iclog->ic_header;
+
+- iclog->ic_refcnt++; /* prevents sync */
++ atomic_inc(&iclog->ic_refcnt); /* prevents sync */
+ log_offset = iclog->ic_offset;
+
+ /* On the 1st write to an iclog, figure out lsn. This works
+@@ -2423,12 +2428,12 @@ restart:
+ xlog_state_switch_iclogs(log, iclog, iclog->ic_size);
+
+ /* If I'm the only one writing to this iclog, sync it to disk */
+- if (iclog->ic_refcnt == 1) {
++ if (atomic_read(&iclog->ic_refcnt) == 1) {
+ spin_unlock(&log->l_icloglock);
+ if ((error = xlog_state_release_iclog(log, iclog)))
+ return error;
+ } else {
+- iclog->ic_refcnt--;
++ atomic_dec(&iclog->ic_refcnt);
+ spin_unlock(&log->l_icloglock);
+ }
+ goto restart;
+@@ -2792,18 +2797,6 @@ xlog_ungrant_log_space(xlog_t *log,
+
+
+ /*
+- * Atomically put back used ticket.
+- */
+-STATIC void
+-xlog_state_put_ticket(xlog_t *log,
+- xlog_ticket_t *tic)
+-{
+- spin_lock(&log->l_icloglock);
+- xlog_ticket_put(log, tic);
+- spin_unlock(&log->l_icloglock);
+-} /* xlog_state_put_ticket */
+-
+-/*
+ * Flush iclog to disk if this is the last reference to the given iclog and
+ * the WANT_SYNC bit is set.
+ *
+@@ -2813,33 +2806,35 @@ xlog_state_put_ticket(xlog_t *log,
+ *
+ */
+ STATIC int
+-xlog_state_release_iclog(xlog_t *log,
+- xlog_in_core_t *iclog)
++xlog_state_release_iclog(
++ xlog_t *log,
++ xlog_in_core_t *iclog)
+ {
+ int sync = 0; /* do we sync? */
+
+- xlog_assign_tail_lsn(log->l_mp);
++ if (iclog->ic_state & XLOG_STATE_IOERROR)
++ return XFS_ERROR(EIO);
+
+- spin_lock(&log->l_icloglock);
++ ASSERT(atomic_read(&iclog->ic_refcnt) > 0);
++ if (!atomic_dec_and_lock(&iclog->ic_refcnt, &log->l_icloglock))
++ return 0;
+
+ if (iclog->ic_state & XLOG_STATE_IOERROR) {
+ spin_unlock(&log->l_icloglock);
+ return XFS_ERROR(EIO);
+ }
+-
+- ASSERT(iclog->ic_refcnt > 0);
+ ASSERT(iclog->ic_state == XLOG_STATE_ACTIVE ||
+ iclog->ic_state == XLOG_STATE_WANT_SYNC);
+
+- if (--iclog->ic_refcnt == 0 &&
+- iclog->ic_state == XLOG_STATE_WANT_SYNC) {
++ if (iclog->ic_state == XLOG_STATE_WANT_SYNC) {
++ /* update tail before writing to iclog */
++ xlog_assign_tail_lsn(log->l_mp);
+ sync++;
+ iclog->ic_state = XLOG_STATE_SYNCING;
+ iclog->ic_header.h_tail_lsn = cpu_to_be64(log->l_tail_lsn);
+ xlog_verify_tail_lsn(log, iclog, log->l_tail_lsn);
+ /* cycle incremented when incrementing curr_block */
+ }
+-
+ spin_unlock(&log->l_icloglock);
+
+ /*
+@@ -2849,11 +2844,9 @@ xlog_state_release_iclog(xlog_t *log,
+ * this iclog has consistent data, so we ignore IOERROR
+ * flags after this point.
+ */
+- if (sync) {
++ if (sync)
+ return xlog_sync(log, iclog);
+- }
+ return 0;
+-
+ } /* xlog_state_release_iclog */
+
+
+@@ -2953,7 +2946,8 @@ xlog_state_sync_all(xlog_t *log, uint flags, int *log_flushed)
+ * previous iclog and go to sleep.
+ */
+ if (iclog->ic_state == XLOG_STATE_DIRTY ||
+- (iclog->ic_refcnt == 0 && iclog->ic_offset == 0)) {
++ (atomic_read(&iclog->ic_refcnt) == 0
++ && iclog->ic_offset == 0)) {
+ iclog = iclog->ic_prev;
+ if (iclog->ic_state == XLOG_STATE_ACTIVE ||
+ iclog->ic_state == XLOG_STATE_DIRTY)
+@@ -2961,14 +2955,14 @@ xlog_state_sync_all(xlog_t *log, uint flags, int *log_flushed)
+ else
+ goto maybe_sleep;
+ } else {
+- if (iclog->ic_refcnt == 0) {
++ if (atomic_read(&iclog->ic_refcnt) == 0) {
+ /* We are the only one with access to this
+ * iclog. Flush it out now. There should
+ * be a roundoff of zero to show that someone
+ * has already taken care of the roundoff from
+ * the previous sync.
+ */
+- iclog->ic_refcnt++;
++ atomic_inc(&iclog->ic_refcnt);
+ lsn = be64_to_cpu(iclog->ic_header.h_lsn);
+ xlog_state_switch_iclogs(log, iclog, 0);
+ spin_unlock(&log->l_icloglock);
+@@ -3100,7 +3094,7 @@ try_again:
+ already_slept = 1;
+ goto try_again;
+ } else {
+- iclog->ic_refcnt++;
++ atomic_inc(&iclog->ic_refcnt);
+ xlog_state_switch_iclogs(log, iclog, 0);
+ spin_unlock(&log->l_icloglock);
+ if (xlog_state_release_iclog(log, iclog))
+@@ -3172,92 +3166,19 @@ xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog)
+ */
+
+ /*
+- * Algorithm doesn't take into account page size. ;-(
+- */
+-STATIC void
+-xlog_state_ticket_alloc(xlog_t *log)
+-{
+- xlog_ticket_t *t_list;
+- xlog_ticket_t *next;
+- xfs_caddr_t buf;
+- uint i = (PAGE_SIZE / sizeof(xlog_ticket_t)) - 2;
+-
+- /*
+- * The kmem_zalloc may sleep, so we shouldn't be holding the
+- * global lock. XXXmiken: may want to use zone allocator.
+- */
+- buf = (xfs_caddr_t) kmem_zalloc(PAGE_SIZE, KM_SLEEP);
+-
+- spin_lock(&log->l_icloglock);
+-
+- /* Attach 1st ticket to Q, so we can keep track of allocated memory */
+- t_list = (xlog_ticket_t *)buf;
+- t_list->t_next = log->l_unmount_free;
+- log->l_unmount_free = t_list++;
+- log->l_ticket_cnt++;
+- log->l_ticket_tcnt++;
+-
+- /* Next ticket becomes first ticket attached to ticket free list */
+- if (log->l_freelist != NULL) {
+- ASSERT(log->l_tail != NULL);
+- log->l_tail->t_next = t_list;
+- } else {
+- log->l_freelist = t_list;
+- }
+- log->l_ticket_cnt++;
+- log->l_ticket_tcnt++;
+-
+- /* Cycle through rest of alloc'ed memory, building up free Q */
+- for ( ; i > 0; i--) {
+- next = t_list + 1;
+- t_list->t_next = next;
+- t_list = next;
+- log->l_ticket_cnt++;
+- log->l_ticket_tcnt++;
+- }
+- t_list->t_next = NULL;
+- log->l_tail = t_list;
+- spin_unlock(&log->l_icloglock);
+-} /* xlog_state_ticket_alloc */
+-
+-
+-/*
+- * Put ticket into free list
+- *
+- * Assumption: log lock is held around this call.
++ * Free a used ticket.
+ */
+ STATIC void
+ xlog_ticket_put(xlog_t *log,
+ xlog_ticket_t *ticket)
+ {
+ sv_destroy(&ticket->t_sema);
+-
+- /*
+- * Don't think caching will make that much difference. It's
+- * more important to make debug easier.
+- */
+-#if 0
+- /* real code will want to use LIFO for caching */
+- ticket->t_next = log->l_freelist;
+- log->l_freelist = ticket;
+- /* no need to clear fields */
+-#else
+- /* When we debug, it is easier if tickets are cycled */
+- ticket->t_next = NULL;
+- if (log->l_tail) {
+- log->l_tail->t_next = ticket;
+- } else {
+- ASSERT(log->l_freelist == NULL);
+- log->l_freelist = ticket;
+- }
+- log->l_tail = ticket;
+-#endif /* DEBUG */
+- log->l_ticket_cnt++;
++ kmem_zone_free(xfs_log_ticket_zone, ticket);
+ } /* xlog_ticket_put */
+
+
+ /*
+- * Grab ticket off freelist or allocation some more
++ * Allocate and initialise a new log ticket.
+ */
+ STATIC xlog_ticket_t *
+ xlog_ticket_get(xlog_t *log,
+@@ -3269,21 +3190,9 @@ xlog_ticket_get(xlog_t *log,
+ xlog_ticket_t *tic;
+ uint num_headers;
+
+- alloc:
+- if (log->l_freelist == NULL)
+- xlog_state_ticket_alloc(log); /* potentially sleep */
+-
+- spin_lock(&log->l_icloglock);
+- if (log->l_freelist == NULL) {
+- spin_unlock(&log->l_icloglock);
+- goto alloc;
+- }
+- tic = log->l_freelist;
+- log->l_freelist = tic->t_next;
+- if (log->l_freelist == NULL)
+- log->l_tail = NULL;
+- log->l_ticket_cnt--;
+- spin_unlock(&log->l_icloglock);
++ tic = kmem_zone_zalloc(xfs_log_ticket_zone, KM_SLEEP|KM_MAYFAIL);
++ if (!tic)
++ return NULL;
+
+ /*
+ * Permanent reservations have up to 'cnt'-1 active log operations
+@@ -3611,8 +3520,8 @@ xfs_log_force_umount(
+ * before we mark the filesystem SHUTDOWN and wake
+ * everybody up to tell the bad news.
+ */
+- spin_lock(&log->l_grant_lock);
+ spin_lock(&log->l_icloglock);
++ spin_lock(&log->l_grant_lock);
+ mp->m_flags |= XFS_MOUNT_FS_SHUTDOWN;
+ XFS_BUF_DONE(mp->m_sb_bp);
+ /*
+diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h
+index 4cdac04..d1d678e 100644
+--- a/fs/xfs/xfs_log.h
++++ b/fs/xfs/xfs_log.h
+@@ -142,8 +142,9 @@ int _xfs_log_force(struct xfs_mount *mp,
+ xfs_lsn_t lsn,
+ uint flags,
+ int *log_forced);
+-#define xfs_log_force(mp, lsn, flags) \
+- _xfs_log_force(mp, lsn, flags, NULL);
++void xfs_log_force(struct xfs_mount *mp,
++ xfs_lsn_t lsn,
++ uint flags);
+ int xfs_log_mount(struct xfs_mount *mp,
+ struct xfs_buftarg *log_target,
+ xfs_daddr_t start_block,
+diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
+index c6244cc..8952a39 100644
+--- a/fs/xfs/xfs_log_priv.h
++++ b/fs/xfs/xfs_log_priv.h
+@@ -242,7 +242,7 @@ typedef struct xlog_res {
+
+ typedef struct xlog_ticket {
+ sv_t t_sema; /* sleep on this semaphore : 20 */
+- struct xlog_ticket *t_next; /* :4|8 */
++ struct xlog_ticket *t_next; /* :4|8 */
+ struct xlog_ticket *t_prev; /* :4|8 */
+ xlog_tid_t t_tid; /* transaction identifier : 4 */
+ int t_curr_res; /* current reservation in bytes : 4 */
+@@ -324,6 +324,19 @@ typedef struct xlog_rec_ext_header {
+ * - ic_offset is the current number of bytes written to in this iclog.
+ * - ic_refcnt is bumped when someone is writing to the log.
+ * - ic_state is the state of the iclog.
++ *
++ * Because of cacheline contention on large machines, we need to separate
++ * various resources onto different cachelines. To start with, make the
++ * structure cacheline aligned. The following fields can be contended on
++ * by independent processes:
++ *
++ * - ic_callback_*
++ * - ic_refcnt
++ * - fields protected by the global l_icloglock
++ *
++ * so we need to ensure that these fields are located in separate cachelines.
++ * We'll put all the read-only and l_icloglock fields in the first cacheline,
++ * and move everything else out to subsequent cachelines.
+ */
+ typedef struct xlog_iclog_fields {
+ sv_t ic_forcesema;
+@@ -332,17 +345,22 @@ typedef struct xlog_iclog_fields {
+ struct xlog_in_core *ic_prev;
+ struct xfs_buf *ic_bp;
+ struct log *ic_log;
+- xfs_log_callback_t *ic_callback;
+- xfs_log_callback_t **ic_callback_tail;
+-#ifdef XFS_LOG_TRACE
+- struct ktrace *ic_trace;
+-#endif
+ int ic_size;
+ int ic_offset;
+- int ic_refcnt;
+ int ic_bwritecnt;
+ ushort_t ic_state;
+ char *ic_datap; /* pointer to iclog data */
++#ifdef XFS_LOG_TRACE
++ struct ktrace *ic_trace;
++#endif
++
++ /* Callback structures need their own cacheline */
++ spinlock_t ic_callback_lock ____cacheline_aligned_in_smp;
++ xfs_log_callback_t *ic_callback;
++ xfs_log_callback_t **ic_callback_tail;
++
++ /* reference counts need their own cacheline */
++ atomic_t ic_refcnt ____cacheline_aligned_in_smp;
+ } xlog_iclog_fields_t;
+
+ typedef union xlog_in_core2 {
+@@ -366,6 +384,7 @@ typedef struct xlog_in_core {
+ #define ic_bp hic_fields.ic_bp
+ #define ic_log hic_fields.ic_log
+ #define ic_callback hic_fields.ic_callback
++#define ic_callback_lock hic_fields.ic_callback_lock
+ #define ic_callback_tail hic_fields.ic_callback_tail
+ #define ic_trace hic_fields.ic_trace
+ #define ic_size hic_fields.ic_size
+@@ -383,43 +402,46 @@ typedef struct xlog_in_core {
+ * that round off problems won't occur when releasing partial reservations.
+ */
+ typedef struct log {
++ /* The following fields don't need locking */
++ struct xfs_mount *l_mp; /* mount point */
++ struct xfs_buf *l_xbuf; /* extra buffer for log
++ * wrapping */
++ struct xfs_buftarg *l_targ; /* buftarg of log */
++ uint l_flags;
++ uint l_quotaoffs_flag; /* XFS_DQ_*, for QUOTAOFFs */
++ struct xfs_buf_cancel **l_buf_cancel_table;
++ int l_iclog_hsize; /* size of iclog header */
++ int l_iclog_heads; /* # of iclog header sectors */
++ uint l_sectbb_log; /* log2 of sector size in BBs */
++ uint l_sectbb_mask; /* sector size (in BBs)
++ * alignment mask */
++ int l_iclog_size; /* size of log in bytes */
++ int l_iclog_size_log; /* log power size of log */
++ int l_iclog_bufs; /* number of iclog buffers */
++ xfs_daddr_t l_logBBstart; /* start block of log */
++ int l_logsize; /* size of log in bytes */
++ int l_logBBsize; /* size of log in BB chunks */
++
+ /* The following block of fields are changed while holding icloglock */
+- sema_t l_flushsema; /* iclog flushing semaphore */
++ sema_t l_flushsema ____cacheline_aligned_in_smp;
++ /* iclog flushing semaphore */
+ int l_flushcnt; /* # of procs waiting on this
+ * sema */
+- int l_ticket_cnt; /* free ticket count */
+- int l_ticket_tcnt; /* total ticket count */
+ int l_covered_state;/* state of "covering disk
+ * log entries" */
+- xlog_ticket_t *l_freelist; /* free list of tickets */
+- xlog_ticket_t *l_unmount_free;/* kmem_free these addresses */
+- xlog_ticket_t *l_tail; /* free list of tickets */
+ xlog_in_core_t *l_iclog; /* head log queue */
+ spinlock_t l_icloglock; /* grab to change iclog state */
+ xfs_lsn_t l_tail_lsn; /* lsn of 1st LR with unflushed
+ * buffers */
+ xfs_lsn_t l_last_sync_lsn;/* lsn of last LR on disk */
+- struct xfs_mount *l_mp; /* mount point */
+- struct xfs_buf *l_xbuf; /* extra buffer for log
+- * wrapping */
+- struct xfs_buftarg *l_targ; /* buftarg of log */
+- xfs_daddr_t l_logBBstart; /* start block of log */
+- int l_logsize; /* size of log in bytes */
+- int l_logBBsize; /* size of log in BB chunks */
+ int l_curr_cycle; /* Cycle number of log writes */
+ int l_prev_cycle; /* Cycle number before last
+ * block increment */
+ int l_curr_block; /* current logical log block */
+ int l_prev_block; /* previous logical log block */
+- int l_iclog_size; /* size of log in bytes */
+- int l_iclog_size_log; /* log power size of log */
+- int l_iclog_bufs; /* number of iclog buffers */
+-
+- /* The following field are used for debugging; need to hold icloglock */
+- char *l_iclog_bak[XLOG_MAX_ICLOGS];
+
+ /* The following block of fields are changed while holding grant_lock */
+- spinlock_t l_grant_lock;
++ spinlock_t l_grant_lock ____cacheline_aligned_in_smp;
+ xlog_ticket_t *l_reserve_headq;
+ xlog_ticket_t *l_write_headq;
+ int l_grant_reserve_cycle;
+@@ -427,19 +449,16 @@ typedef struct log {
+ int l_grant_write_cycle;
+ int l_grant_write_bytes;
+
+- /* The following fields don't need locking */
+ #ifdef XFS_LOG_TRACE
+ struct ktrace *l_trace;
+ struct ktrace *l_grant_trace;
+ #endif
+- uint l_flags;
+- uint l_quotaoffs_flag; /* XFS_DQ_*, for QUOTAOFFs */
+- struct xfs_buf_cancel **l_buf_cancel_table;
+- int l_iclog_hsize; /* size of iclog header */
+- int l_iclog_heads; /* # of iclog header sectors */
+- uint l_sectbb_log; /* log2 of sector size in BBs */
+- uint l_sectbb_mask; /* sector size (in BBs)
+- * alignment mask */
++
++ /* The following field are used for debugging; need to hold icloglock */
++#ifdef DEBUG
++ char *l_iclog_bak[XLOG_MAX_ICLOGS];
++#endif
++
+ } xlog_t;
+
+ #define XLOG_FORCED_SHUTDOWN(log) ((log)->l_flags & XLOG_IO_ERROR)
+@@ -459,6 +478,8 @@ extern struct xfs_buf *xlog_get_bp(xlog_t *, int);
+ extern void xlog_put_bp(struct xfs_buf *);
+ extern int xlog_bread(xlog_t *, xfs_daddr_t, int, struct xfs_buf *);
+
++extern kmem_zone_t *xfs_log_ticket_zone;
++
+ /* iclog tracing */
+ #define XLOG_TRACE_GRAB_FLUSH 1
+ #define XLOG_TRACE_REL_FLUSH 2
+diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
+index b2b70eb..e65ab4a 100644
+--- a/fs/xfs/xfs_log_recover.c
++++ b/fs/xfs/xfs_log_recover.c
+@@ -46,6 +46,7 @@
+ #include "xfs_trans_priv.h"
+ #include "xfs_quota.h"
+ #include "xfs_rw.h"
++#include "xfs_utils.h"
+
+ STATIC int xlog_find_zeroed(xlog_t *, xfs_daddr_t *);
+ STATIC int xlog_clear_stale_blocks(xlog_t *, xfs_lsn_t);
+@@ -120,7 +121,8 @@ xlog_bread(
+ XFS_BUF_SET_TARGET(bp, log->l_mp->m_logdev_targp);
+
+ xfsbdstrat(log->l_mp, bp);
+- if ((error = xfs_iowait(bp)))
++ error = xfs_iowait(bp);
++ if (error)
+ xfs_ioerror_alert("xlog_bread", log->l_mp,
+ bp, XFS_BUF_ADDR(bp));
+ return error;
+@@ -191,7 +193,7 @@ xlog_header_check_dump(
+ {
+ int b;
+
+- cmn_err(CE_DEBUG, "%s: SB : uuid = ", __FUNCTION__);
++ cmn_err(CE_DEBUG, "%s: SB : uuid = ", __func__);
+ for (b = 0; b < 16; b++)
+ cmn_err(CE_DEBUG, "%02x", ((uchar_t *)&mp->m_sb.sb_uuid)[b]);
+ cmn_err(CE_DEBUG, ", fmt = %d\n", XLOG_FMT);
+@@ -1160,10 +1162,14 @@ xlog_write_log_records(
+ if (j == 0 && (start_block + endcount > ealign)) {
+ offset = XFS_BUF_PTR(bp);
+ balign = BBTOB(ealign - start_block);
+- XFS_BUF_SET_PTR(bp, offset + balign, BBTOB(sectbb));
+- if ((error = xlog_bread(log, ealign, sectbb, bp)))
++ error = XFS_BUF_SET_PTR(bp, offset + balign,
++ BBTOB(sectbb));
++ if (!error)
++ error = xlog_bread(log, ealign, sectbb, bp);
++ if (!error)
++ error = XFS_BUF_SET_PTR(bp, offset, bufblks);
++ if (error)
+ break;
+- XFS_BUF_SET_PTR(bp, offset, bufblks);
+ }
+
+ offset = xlog_align(log, start_block, endcount, bp);
+@@ -2280,7 +2286,9 @@ xlog_recover_do_inode_trans(
+ * invalidate the buffer when we write it out below.
+ */
+ imap.im_blkno = 0;
+- xfs_imap(log->l_mp, NULL, ino, &imap, 0);
++ error = xfs_imap(log->l_mp, NULL, ino, &imap, 0);
++ if (error)
++ goto error;
+ }
+
+ /*
+@@ -2964,7 +2972,7 @@ xlog_recover_process_data(
+ * Process an extent free intent item that was recovered from
+ * the log. We need to free the extents that it describes.
+ */
+-STATIC void
++STATIC int
+ xlog_recover_process_efi(
+ xfs_mount_t *mp,
+ xfs_efi_log_item_t *efip)
+@@ -2972,6 +2980,7 @@ xlog_recover_process_efi(
+ xfs_efd_log_item_t *efdp;
+ xfs_trans_t *tp;
+ int i;
++ int error = 0;
+ xfs_extent_t *extp;
+ xfs_fsblock_t startblock_fsb;
+
+@@ -2995,23 +3004,32 @@ xlog_recover_process_efi(
+ * free the memory associated with it.
+ */
+ xfs_efi_release(efip, efip->efi_format.efi_nextents);
+- return;
++ return XFS_ERROR(EIO);
+ }
+ }
+
+ tp = xfs_trans_alloc(mp, 0);
+- xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0, 0, 0);
++ error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0, 0, 0);
++ if (error)
++ goto abort_error;
+ efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents);
+
+ for (i = 0; i < efip->efi_format.efi_nextents; i++) {
+ extp = &(efip->efi_format.efi_extents[i]);
+- xfs_free_extent(tp, extp->ext_start, extp->ext_len);
++ error = xfs_free_extent(tp, extp->ext_start, extp->ext_len);
++ if (error)
++ goto abort_error;
+ xfs_trans_log_efd_extent(tp, efdp, extp->ext_start,
+ extp->ext_len);
+ }
+
+ efip->efi_flags |= XFS_EFI_RECOVERED;
+- xfs_trans_commit(tp, 0);
++ error = xfs_trans_commit(tp, 0);
++ return error;
++
++abort_error:
++ xfs_trans_cancel(tp, XFS_TRANS_ABORT);
++ return error;
+ }
+
+ /*
+@@ -3059,7 +3077,7 @@ xlog_recover_check_ail(
+ * everything already in the AIL, we stop processing as soon as
+ * we see something other than an EFI in the AIL.
+ */
+-STATIC void
++STATIC int
+ xlog_recover_process_efis(
+ xlog_t *log)
+ {
+@@ -3067,6 +3085,7 @@ xlog_recover_process_efis(
+ xfs_efi_log_item_t *efip;
+ int gen;
+ xfs_mount_t *mp;
++ int error = 0;
+
+ mp = log->l_mp;
+ spin_lock(&mp->m_ail_lock);
+@@ -3091,11 +3110,14 @@ xlog_recover_process_efis(
+ }
+
+ spin_unlock(&mp->m_ail_lock);
+- xlog_recover_process_efi(mp, efip);
++ error = xlog_recover_process_efi(mp, efip);
++ if (error)
++ return error;
+ spin_lock(&mp->m_ail_lock);
+ lip = xfs_trans_next_ail(mp, lip, &gen, NULL);
+ }
+ spin_unlock(&mp->m_ail_lock);
++ return error;
+ }
+
+ /*
+@@ -3115,21 +3137,18 @@ xlog_recover_clear_agi_bucket(
+ int error;
+
+ tp = xfs_trans_alloc(mp, XFS_TRANS_CLEAR_AGI_BUCKET);
+- xfs_trans_reserve(tp, 0, XFS_CLEAR_AGI_BUCKET_LOG_RES(mp), 0, 0, 0);
+-
+- error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
++ error = xfs_trans_reserve(tp, 0, XFS_CLEAR_AGI_BUCKET_LOG_RES(mp), 0, 0, 0);
++ if (!error)
++ error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
+ XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
+ XFS_FSS_TO_BB(mp, 1), 0, &agibp);
+- if (error) {
+- xfs_trans_cancel(tp, XFS_TRANS_ABORT);
+- return;
+- }
++ if (error)
++ goto out_abort;
+
++ error = EINVAL;
+ agi = XFS_BUF_TO_AGI(agibp);
+- if (be32_to_cpu(agi->agi_magicnum) != XFS_AGI_MAGIC) {
+- xfs_trans_cancel(tp, XFS_TRANS_ABORT);
+- return;
+- }
++ if (be32_to_cpu(agi->agi_magicnum) != XFS_AGI_MAGIC)
++ goto out_abort;
+
+ agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO);
+ offset = offsetof(xfs_agi_t, agi_unlinked) +
+@@ -3137,7 +3156,17 @@ xlog_recover_clear_agi_bucket(
+ xfs_trans_log_buf(tp, agibp, offset,
+ (offset + sizeof(xfs_agino_t) - 1));
+
+- (void) xfs_trans_commit(tp, 0);
++ error = xfs_trans_commit(tp, 0);
++ if (error)
++ goto out_error;
++ return;
++
++out_abort:
++ xfs_trans_cancel(tp, XFS_TRANS_ABORT);
++out_error:
++ xfs_fs_cmn_err(CE_WARN, mp, "xlog_recover_clear_agi_bucket: "
++ "failed to clear agi %d. Continuing.", agno);
++ return;
+ }
+
+ /*
+@@ -3214,7 +3243,8 @@ xlog_recover_process_iunlinks(
+ * next inode in the bucket.
+ */
+ error = xfs_itobp(mp, NULL, ip, &dip,
+- &ibp, 0, 0);
++ &ibp, 0, 0,
++ XFS_BUF_LOCK);
+ ASSERT(error || (dip != NULL));
+ }
+
+@@ -3247,7 +3277,7 @@ xlog_recover_process_iunlinks(
+ if (ip->i_d.di_mode == 0)
+ xfs_iput_new(ip, 0);
+ else
+- VN_RELE(XFS_ITOV(ip));
++ IRELE(ip);
+ } else {
+ /*
+ * We can't read in the inode
+@@ -3445,7 +3475,7 @@ xlog_valid_rec_header(
+ (!rhead->h_version ||
+ (be32_to_cpu(rhead->h_version) & (~XLOG_VERSION_OKBITS))))) {
+ xlog_warn("XFS: %s: unrecognised log version (%d).",
+- __FUNCTION__, be32_to_cpu(rhead->h_version));
++ __func__, be32_to_cpu(rhead->h_version));
+ return XFS_ERROR(EIO);
+ }
+
+@@ -3604,15 +3634,19 @@ xlog_do_recovery_pass(
+ * _first_, then the log start (LR header end)
+ * - order is important.
+ */
++ wrapped_hblks = hblks - split_hblks;
+ bufaddr = XFS_BUF_PTR(hbp);
+- XFS_BUF_SET_PTR(hbp,
++ error = XFS_BUF_SET_PTR(hbp,
+ bufaddr + BBTOB(split_hblks),
+ BBTOB(hblks - split_hblks));
+- wrapped_hblks = hblks - split_hblks;
+- error = xlog_bread(log, 0, wrapped_hblks, hbp);
++ if (!error)
++ error = xlog_bread(log, 0,
++ wrapped_hblks, hbp);
++ if (!error)
++ error = XFS_BUF_SET_PTR(hbp, bufaddr,
++ BBTOB(hblks));
+ if (error)
+ goto bread_err2;
+- XFS_BUF_SET_PTR(hbp, bufaddr, BBTOB(hblks));
+ if (!offset)
+ offset = xlog_align(log, 0,
+ wrapped_hblks, hbp);
+@@ -3664,13 +3698,18 @@ xlog_do_recovery_pass(
+ * - order is important.
+ */
+ bufaddr = XFS_BUF_PTR(dbp);
+- XFS_BUF_SET_PTR(dbp,
++ error = XFS_BUF_SET_PTR(dbp,
+ bufaddr + BBTOB(split_bblks),
+ BBTOB(bblks - split_bblks));
+- if ((error = xlog_bread(log, wrapped_hblks,
+- bblks - split_bblks, dbp)))
++ if (!error)
++ error = xlog_bread(log, wrapped_hblks,
++ bblks - split_bblks,
++ dbp);
++ if (!error)
++ error = XFS_BUF_SET_PTR(dbp, bufaddr,
++ h_size);
++ if (error)
+ goto bread_err2;
+- XFS_BUF_SET_PTR(dbp, bufaddr, h_size);
+ if (!offset)
+ offset = xlog_align(log, wrapped_hblks,
+ bblks - split_bblks, dbp);
+@@ -3826,7 +3865,8 @@ xlog_do_recover(
+ XFS_BUF_READ(bp);
+ XFS_BUF_UNASYNC(bp);
+ xfsbdstrat(log->l_mp, bp);
+- if ((error = xfs_iowait(bp))) {
++ error = xfs_iowait(bp);
++ if (error) {
+ xfs_ioerror_alert("xlog_do_recover",
+ log->l_mp, bp, XFS_BUF_ADDR(bp));
+ ASSERT(0);
+@@ -3917,7 +3957,14 @@ xlog_recover_finish(
+ * rather than accepting new requests.
+ */
+ if (log->l_flags & XLOG_RECOVERY_NEEDED) {
+- xlog_recover_process_efis(log);
++ int error;
++ error = xlog_recover_process_efis(log);
++ if (error) {
++ cmn_err(CE_ALERT,
++ "Failed to recover EFIs on filesystem: %s",
++ log->l_mp->m_fsname);
++ return error;
++ }
+ /*
+ * Sync the log to get all the EFIs out of the AIL.
+ * This isn't absolutely necessary, but it helps in
+diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
+index 8ed164e..2fec452 100644
+--- a/fs/xfs/xfs_mount.c
++++ b/fs/xfs/xfs_mount.c
+@@ -43,8 +43,9 @@
+ #include "xfs_rw.h"
+ #include "xfs_quota.h"
+ #include "xfs_fsops.h"
++#include "xfs_utils.h"
+
+-STATIC void xfs_mount_log_sb(xfs_mount_t *, __int64_t);
++STATIC int xfs_mount_log_sb(xfs_mount_t *, __int64_t);
+ STATIC int xfs_uuid_mount(xfs_mount_t *);
+ STATIC void xfs_uuid_unmount(xfs_mount_t *mp);
+ STATIC void xfs_unmountfs_wait(xfs_mount_t *);
+@@ -57,7 +58,7 @@ STATIC void xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t,
+ STATIC void xfs_icsb_sync_counters(xfs_mount_t *);
+ STATIC int xfs_icsb_modify_counters(xfs_mount_t *, xfs_sb_field_t,
+ int64_t, int);
+-STATIC int xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t);
++STATIC void xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t);
+
+ #else
+
+@@ -956,7 +957,6 @@ xfs_mountfs(
+ {
+ xfs_sb_t *sbp = &(mp->m_sb);
+ xfs_inode_t *rip;
+- bhv_vnode_t *rvp = NULL;
+ __uint64_t resblks;
+ __int64_t update_flags = 0LL;
+ uint quotamount, quotaflags;
+@@ -964,11 +964,6 @@ xfs_mountfs(
+ int uuid_mounted = 0;
+ int error = 0;
+
+- if (mp->m_sb_bp == NULL) {
+- error = xfs_readsb(mp, mfsi_flags);
+- if (error)
+- return error;
+- }
+ xfs_mount_common(mp, sbp);
+
+ /*
+@@ -1163,7 +1158,6 @@ xfs_mountfs(
+ }
+
+ ASSERT(rip != NULL);
+- rvp = XFS_ITOV(rip);
+
+ if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) {
+ cmn_err(CE_WARN, "XFS: corrupted root inode");
+@@ -1195,8 +1189,13 @@ xfs_mountfs(
+ /*
+ * If fs is not mounted readonly, then update the superblock changes.
+ */
+- if (update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY))
+- xfs_mount_log_sb(mp, update_flags);
++ if (update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) {
++ error = xfs_mount_log_sb(mp, update_flags);
++ if (error) {
++ cmn_err(CE_WARN, "XFS: failed to write sb changes");
++ goto error4;
++ }
++ }
+
+ /*
+ * Initialise the XFS quota management subsystem for this mount
+@@ -1233,12 +1232,15 @@ xfs_mountfs(
+ *
+ * We default to 5% or 1024 fsbs of space reserved, whichever is smaller.
+ * This may drive us straight to ENOSPC on mount, but that implies
+- * we were already there on the last unmount.
++ * we were already there on the last unmount. Warn if this occurs.
+ */
+ resblks = mp->m_sb.sb_dblocks;
+ do_div(resblks, 20);
+ resblks = min_t(__uint64_t, resblks, 1024);
+- xfs_reserve_blocks(mp, &resblks, NULL);
++ error = xfs_reserve_blocks(mp, &resblks, NULL);
++ if (error)
++ cmn_err(CE_WARN, "XFS: Unable to allocate reserve blocks. "
++ "Continuing without a reserve pool.");
+
+ return 0;
+
+@@ -1246,7 +1248,7 @@ xfs_mountfs(
+ /*
+ * Free up the root inode.
+ */
+- VN_RELE(rvp);
++ IRELE(rip);
+ error3:
+ xfs_log_unmount_dealloc(mp);
+ error2:
+@@ -1274,6 +1276,7 @@ int
+ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
+ {
+ __uint64_t resblks;
++ int error = 0;
+
+ /*
+ * We can potentially deadlock here if we have an inode cluster
+@@ -1317,9 +1320,15 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
+ * value does not matter....
+ */
+ resblks = 0;
+- xfs_reserve_blocks(mp, &resblks, NULL);
++ error = xfs_reserve_blocks(mp, &resblks, NULL);
++ if (error)
++ cmn_err(CE_WARN, "XFS: Unable to free reserved block pool. "
++ "Freespace may not be correct on next mount.");
+
+- xfs_log_sbcount(mp, 1);
++ error = xfs_log_sbcount(mp, 1);
++ if (error)
++ cmn_err(CE_WARN, "XFS: Unable to update superblock counters. "
++ "Freespace may not be correct on next mount.");
+ xfs_unmountfs_writesb(mp);
+ xfs_unmountfs_wait(mp); /* wait for async bufs */
+ xfs_log_unmount(mp); /* Done! No more fs ops. */
+@@ -1411,9 +1420,8 @@ xfs_log_sbcount(
+ xfs_mod_sb(tp, XFS_SB_IFREE | XFS_SB_ICOUNT | XFS_SB_FDBLOCKS);
+ if (sync)
+ xfs_trans_set_sync(tp);
+- xfs_trans_commit(tp, 0);
+-
+- return 0;
++ error = xfs_trans_commit(tp, 0);
++ return error;
+ }
+
+ STATIC void
+@@ -1462,7 +1470,6 @@ xfs_unmountfs_writesb(xfs_mount_t *mp)
+ XFS_BUF_UNASYNC(sbp);
+ ASSERT(XFS_BUF_TARGET(sbp) == mp->m_ddev_targp);
+ xfsbdstrat(mp, sbp);
+- /* Nevermind errors we might get here. */
+ error = xfs_iowait(sbp);
+ if (error)
+ xfs_ioerror_alert("xfs_unmountfs_writesb",
+@@ -1911,24 +1918,27 @@ xfs_uuid_unmount(
+ * be altered by the mount options, as well as any potential sb_features2
+ * fixup. Only the first superblock is updated.
+ */
+-STATIC void
++STATIC int
+ xfs_mount_log_sb(
+ xfs_mount_t *mp,
+ __int64_t fields)
+ {
+ xfs_trans_t *tp;
++ int error;
+
+ ASSERT(fields & (XFS_SB_UNIT | XFS_SB_WIDTH | XFS_SB_UUID |
+ XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2));
+
+ tp = xfs_trans_alloc(mp, XFS_TRANS_SB_UNIT);
+- if (xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
+- XFS_DEFAULT_LOG_COUNT)) {
++ error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
++ XFS_DEFAULT_LOG_COUNT);
++ if (error) {
+ xfs_trans_cancel(tp, 0);
+- return;
++ return error;
+ }
+ xfs_mod_sb(tp, fields);
+- xfs_trans_commit(tp, 0);
++ error = xfs_trans_commit(tp, 0);
++ return error;
+ }
+
+
+@@ -2189,7 +2199,7 @@ xfs_icsb_counter_disabled(
+ return test_bit(field, &mp->m_icsb_counters);
+ }
+
+-STATIC int
++STATIC void
+ xfs_icsb_disable_counter(
+ xfs_mount_t *mp,
+ xfs_sb_field_t field)
+@@ -2207,7 +2217,7 @@ xfs_icsb_disable_counter(
+ * the m_icsb_mutex.
+ */
+ if (xfs_icsb_counter_disabled(mp, field))
+- return 0;
++ return;
+
+ xfs_icsb_lock_all_counters(mp);
+ if (!test_and_set_bit(field, &mp->m_icsb_counters)) {
+@@ -2230,8 +2240,6 @@ xfs_icsb_disable_counter(
+ }
+
+ xfs_icsb_unlock_all_counters(mp);
+-
+- return 0;
+ }
+
+ STATIC void
+diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
+index 1d8a472..1ed5751 100644
+--- a/fs/xfs/xfs_mount.h
++++ b/fs/xfs/xfs_mount.h
+@@ -66,17 +66,17 @@ struct xfs_mru_cache;
+ * Prototypes and functions for the Data Migration subsystem.
+ */
+
+-typedef int (*xfs_send_data_t)(int, bhv_vnode_t *,
+- xfs_off_t, size_t, int, bhv_vrwlock_t *);
++typedef int (*xfs_send_data_t)(int, struct xfs_inode *,
++ xfs_off_t, size_t, int, int *);
+ typedef int (*xfs_send_mmap_t)(struct vm_area_struct *, uint);
+-typedef int (*xfs_send_destroy_t)(bhv_vnode_t *, dm_right_t);
++typedef int (*xfs_send_destroy_t)(struct xfs_inode *, dm_right_t);
+ typedef int (*xfs_send_namesp_t)(dm_eventtype_t, struct xfs_mount *,
+- bhv_vnode_t *,
+- dm_right_t, bhv_vnode_t *, dm_right_t,
+- char *, char *, mode_t, int, int);
++ struct xfs_inode *, dm_right_t,
++ struct xfs_inode *, dm_right_t,
++ const char *, const char *, mode_t, int, int);
+ typedef int (*xfs_send_mount_t)(struct xfs_mount *, dm_right_t,
+ char *, char *);
+-typedef void (*xfs_send_unmount_t)(struct xfs_mount *, bhv_vnode_t *,
++typedef void (*xfs_send_unmount_t)(struct xfs_mount *, struct xfs_inode *,
+ dm_right_t, mode_t, int, int);
+
+ typedef struct xfs_dmops {
+@@ -88,20 +88,20 @@ typedef struct xfs_dmops {
+ xfs_send_unmount_t xfs_send_unmount;
+ } xfs_dmops_t;
+
+-#define XFS_SEND_DATA(mp, ev,vp,off,len,fl,lock) \
+- (*(mp)->m_dm_ops->xfs_send_data)(ev,vp,off,len,fl,lock)
++#define XFS_SEND_DATA(mp, ev,ip,off,len,fl,lock) \
++ (*(mp)->m_dm_ops->xfs_send_data)(ev,ip,off,len,fl,lock)
+ #define XFS_SEND_MMAP(mp, vma,fl) \
+ (*(mp)->m_dm_ops->xfs_send_mmap)(vma,fl)
+-#define XFS_SEND_DESTROY(mp, vp,right) \
+- (*(mp)->m_dm_ops->xfs_send_destroy)(vp,right)
++#define XFS_SEND_DESTROY(mp, ip,right) \
++ (*(mp)->m_dm_ops->xfs_send_destroy)(ip,right)
+ #define XFS_SEND_NAMESP(mp, ev,b1,r1,b2,r2,n1,n2,mode,rval,fl) \
+ (*(mp)->m_dm_ops->xfs_send_namesp)(ev,NULL,b1,r1,b2,r2,n1,n2,mode,rval,fl)
+ #define XFS_SEND_PREUNMOUNT(mp,b1,r1,b2,r2,n1,n2,mode,rval,fl) \
+ (*(mp)->m_dm_ops->xfs_send_namesp)(DM_EVENT_PREUNMOUNT,mp,b1,r1,b2,r2,n1,n2,mode,rval,fl)
+ #define XFS_SEND_MOUNT(mp,right,path,name) \
+ (*(mp)->m_dm_ops->xfs_send_mount)(mp,right,path,name)
+-#define XFS_SEND_UNMOUNT(mp, vp,right,mode,rval,fl) \
+- (*(mp)->m_dm_ops->xfs_send_unmount)(mp,vp,right,mode,rval,fl)
++#define XFS_SEND_UNMOUNT(mp, ip,right,mode,rval,fl) \
++ (*(mp)->m_dm_ops->xfs_send_unmount)(mp,ip,right,mode,rval,fl)
+
+
+ /*
+@@ -220,7 +220,7 @@ extern void xfs_icsb_sync_counters_flags(struct xfs_mount *, int);
+ #endif
+
+ typedef struct xfs_ail {
+- xfs_ail_entry_t xa_ail;
++ struct list_head xa_ail;
+ uint xa_gen;
+ struct task_struct *xa_task;
+ xfs_lsn_t xa_target;
+@@ -401,7 +401,7 @@ typedef struct xfs_mount {
+
+ /*
+ * Allow large block sizes to be reported to userspace programs if the
+- * "largeio" mount option is used.
++ * "largeio" mount option is used.
+ *
+ * If compatibility mode is specified, simply return the basic unit of caching
+ * so that we don't get inefficient read/modify/write I/O from user apps.
+diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c
+index 7eb157a..ee37189 100644
+--- a/fs/xfs/xfs_rename.c
++++ b/fs/xfs/xfs_rename.c
+@@ -36,7 +36,6 @@
+ #include "xfs_bmap.h"
+ #include "xfs_error.h"
+ #include "xfs_quota.h"
+-#include "xfs_refcache.h"
+ #include "xfs_utils.h"
+ #include "xfs_trans_space.h"
+ #include "xfs_vnodeops.h"
+@@ -84,25 +83,23 @@ int xfs_rename_skip, xfs_rename_nskip;
+ */
+ STATIC int
+ xfs_lock_for_rename(
+- xfs_inode_t *dp1, /* old (source) directory inode */
+- xfs_inode_t *dp2, /* new (target) directory inode */
+- bhv_vname_t *vname1,/* old entry name */
+- bhv_vname_t *vname2,/* new entry name */
+- xfs_inode_t **ipp1, /* inode of old entry */
+- xfs_inode_t **ipp2, /* inode of new entry, if it
++ xfs_inode_t *dp1, /* in: old (source) directory inode */
++ xfs_inode_t *dp2, /* in: new (target) directory inode */
++ xfs_inode_t *ip1, /* in: inode of old entry */
++ struct xfs_name *name2, /* in: new entry name */
++ xfs_inode_t **ipp2, /* out: inode of new entry, if it
+ already exists, NULL otherwise. */
+- xfs_inode_t **i_tab,/* array of inode returned, sorted */
+- int *num_inodes) /* number of inodes in array */
++ xfs_inode_t **i_tab,/* out: array of inode returned, sorted */
++ int *num_inodes) /* out: number of inodes in array */
+ {
+- xfs_inode_t *ip1, *ip2, *temp;
++ xfs_inode_t *ip2 = NULL;
++ xfs_inode_t *temp;
+ xfs_ino_t inum1, inum2;
+ int error;
+ int i, j;
+ uint lock_mode;
+ int diff_dirs = (dp1 != dp2);
+
+- ip2 = NULL;
+-
+ /*
+ * First, find out the current inums of the entries so that we
+ * can determine the initial locking order. We'll have to
+@@ -110,27 +107,20 @@ xfs_lock_for_rename(
+ * to see if we still have the right inodes, directories, etc.
+ */
+ lock_mode = xfs_ilock_map_shared(dp1);
+- error = xfs_get_dir_entry(vname1, &ip1);
+- if (error) {
+- xfs_iunlock_map_shared(dp1, lock_mode);
+- return error;
+- }
++ IHOLD(ip1);
++ xfs_itrace_ref(ip1);
+
+ inum1 = ip1->i_ino;
+
+- ASSERT(ip1);
+- xfs_itrace_ref(ip1);
+-
+ /*
+ * Unlock dp1 and lock dp2 if they are different.
+ */
+-
+ if (diff_dirs) {
+ xfs_iunlock_map_shared(dp1, lock_mode);
+ lock_mode = xfs_ilock_map_shared(dp2);
+ }
+
+- error = xfs_dir_lookup_int(dp2, lock_mode, vname2, &inum2, &ip2);
++ error = xfs_dir_lookup_int(dp2, lock_mode, name2, &inum2, &ip2);
+ if (error == ENOENT) { /* target does not need to exist. */
+ inum2 = 0;
+ } else if (error) {
+@@ -162,6 +152,7 @@ xfs_lock_for_rename(
+ *num_inodes = 4;
+ i_tab[3] = ip2;
+ }
++ *ipp2 = i_tab[3];
+
+ /*
+ * Sort the elements via bubble sort. (Remember, there are at
+@@ -199,21 +190,6 @@ xfs_lock_for_rename(
+ xfs_lock_inodes(i_tab, *num_inodes, 0, XFS_ILOCK_SHARED);
+ }
+
+- /*
+- * Set the return value. Null out any unused entries in i_tab.
+- */
+- *ipp1 = *ipp2 = NULL;
+- for (i=0; i < *num_inodes; i++) {
+- if (i_tab[i]->i_ino == inum1) {
+- *ipp1 = i_tab[i];
+- }
+- if (i_tab[i]->i_ino == inum2) {
+- *ipp2 = i_tab[i];
+- }
+- }
+- for (;i < 4; i++) {
+- i_tab[i] = NULL;
+- }
+ return 0;
+ }
+
+@@ -223,13 +199,13 @@ xfs_lock_for_rename(
+ int
+ xfs_rename(
+ xfs_inode_t *src_dp,
+- bhv_vname_t *src_vname,
+- bhv_vnode_t *target_dir_vp,
+- bhv_vname_t *target_vname)
++ struct xfs_name *src_name,
++ xfs_inode_t *src_ip,
++ xfs_inode_t *target_dp,
++ struct xfs_name *target_name)
+ {
+- bhv_vnode_t *src_dir_vp = XFS_ITOV(src_dp);
+ xfs_trans_t *tp;
+- xfs_inode_t *target_dp, *src_ip, *target_ip;
++ xfs_inode_t *target_ip;
+ xfs_mount_t *mp = src_dp->i_mount;
+ int new_parent; /* moving to a new dir */
+ int src_is_directory; /* src_name is a directory */
+@@ -243,29 +219,16 @@ xfs_rename(
+ int spaceres;
+ int target_link_zero = 0;
+ int num_inodes;
+- char *src_name = VNAME(src_vname);
+- char *target_name = VNAME(target_vname);
+- int src_namelen = VNAMELEN(src_vname);
+- int target_namelen = VNAMELEN(target_vname);
+
+ xfs_itrace_entry(src_dp);
+- xfs_itrace_entry(xfs_vtoi(target_dir_vp));
+-
+- /*
+- * Find the XFS behavior descriptor for the target directory
+- * vnode since it was not handed to us.
+- */
+- target_dp = xfs_vtoi(target_dir_vp);
+- if (target_dp == NULL) {
+- return XFS_ERROR(EXDEV);
+- }
++ xfs_itrace_entry(target_dp);
+
+ if (DM_EVENT_ENABLED(src_dp, DM_EVENT_RENAME) ||
+ DM_EVENT_ENABLED(target_dp, DM_EVENT_RENAME)) {
+ error = XFS_SEND_NAMESP(mp, DM_EVENT_RENAME,
+- src_dir_vp, DM_RIGHT_NULL,
+- target_dir_vp, DM_RIGHT_NULL,
+- src_name, target_name,
++ src_dp, DM_RIGHT_NULL,
++ target_dp, DM_RIGHT_NULL,
++ src_name->name, target_name->name,
+ 0, 0, 0);
+ if (error) {
+ return error;
+@@ -282,10 +245,8 @@ xfs_rename(
+ * does not exist in the source directory.
+ */
+ tp = NULL;
+- error = xfs_lock_for_rename(src_dp, target_dp, src_vname,
+- target_vname, &src_ip, &target_ip, inodes,
+- &num_inodes);
+-
++ error = xfs_lock_for_rename(src_dp, target_dp, src_ip, target_name,
++ &target_ip, inodes, &num_inodes);
+ if (error) {
+ /*
+ * We have nothing locked, no inode references, and
+@@ -331,7 +292,7 @@ xfs_rename(
+ XFS_BMAP_INIT(&free_list, &first_block);
+ tp = xfs_trans_alloc(mp, XFS_TRANS_RENAME);
+ cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
+- spaceres = XFS_RENAME_SPACE_RES(mp, target_namelen);
++ spaceres = XFS_RENAME_SPACE_RES(mp, target_name->len);
+ error = xfs_trans_reserve(tp, spaceres, XFS_RENAME_LOG_RES(mp), 0,
+ XFS_TRANS_PERM_LOG_RES, XFS_RENAME_LOG_COUNT);
+ if (error == ENOSPC) {
+@@ -365,10 +326,10 @@ xfs_rename(
+ * them when they unlock the inodes. Also, we need to be careful
+ * not to add an inode to the transaction more than once.
+ */
+- VN_HOLD(src_dir_vp);
++ IHOLD(src_dp);
+ xfs_trans_ijoin(tp, src_dp, XFS_ILOCK_EXCL);
+ if (new_parent) {
+- VN_HOLD(target_dir_vp);
++ IHOLD(target_dp);
+ xfs_trans_ijoin(tp, target_dp, XFS_ILOCK_EXCL);
+ }
+ if ((src_ip != src_dp) && (src_ip != target_dp)) {
+@@ -389,9 +350,8 @@ xfs_rename(
+ * If there's no space reservation, check the entry will
+ * fit before actually inserting it.
+ */
+- if (spaceres == 0 &&
+- (error = xfs_dir_canenter(tp, target_dp, target_name,
+- target_namelen)))
++ error = xfs_dir_canenter(tp, target_dp, target_name, spaceres);
++ if (error)
+ goto error_return;
+ /*
+ * If target does not exist and the rename crosses
+@@ -399,8 +359,8 @@ xfs_rename(
+ * to account for the ".." reference from the new entry.
+ */
+ error = xfs_dir_createname(tp, target_dp, target_name,
+- target_namelen, src_ip->i_ino,
+- &first_block, &free_list, spaceres);
++ src_ip->i_ino, &first_block,
++ &free_list, spaceres);
+ if (error == ENOSPC)
+ goto error_return;
+ if (error)
+@@ -439,7 +399,7 @@ xfs_rename(
+ * name at the destination directory, remove it first.
+ */
+ error = xfs_dir_replace(tp, target_dp, target_name,
+- target_namelen, src_ip->i_ino,
++ src_ip->i_ino,
+ &first_block, &free_list, spaceres);
+ if (error)
+ goto abort_return;
+@@ -476,7 +436,8 @@ xfs_rename(
+ * Rewrite the ".." entry to point to the new
+ * directory.
+ */
+- error = xfs_dir_replace(tp, src_ip, "..", 2, target_dp->i_ino,
++ error = xfs_dir_replace(tp, src_ip, &xfs_name_dotdot,
++ target_dp->i_ino,
+ &first_block, &free_list, spaceres);
+ ASSERT(error != EEXIST);
+ if (error)
+@@ -512,8 +473,8 @@ xfs_rename(
+ goto abort_return;
+ }
+
+- error = xfs_dir_removename(tp, src_dp, src_name, src_namelen,
+- src_ip->i_ino, &first_block, &free_list, spaceres);
++ error = xfs_dir_removename(tp, src_dp, src_name, src_ip->i_ino,
++ &first_block, &free_list, spaceres);
+ if (error)
+ goto abort_return;
+ xfs_ichgtime(src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+@@ -580,10 +541,8 @@ xfs_rename(
+ * the vnode references.
+ */
+ error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
+- if (target_ip != NULL) {
+- xfs_refcache_purge_ip(target_ip);
++ if (target_ip != NULL)
+ IRELE(target_ip);
+- }
+ /*
+ * Let interposed file systems know about removed links.
+ */
+@@ -598,9 +557,9 @@ std_return:
+ if (DM_EVENT_ENABLED(src_dp, DM_EVENT_POSTRENAME) ||
+ DM_EVENT_ENABLED(target_dp, DM_EVENT_POSTRENAME)) {
+ (void) XFS_SEND_NAMESP (mp, DM_EVENT_POSTRENAME,
+- src_dir_vp, DM_RIGHT_NULL,
+- target_dir_vp, DM_RIGHT_NULL,
+- src_name, target_name,
++ src_dp, DM_RIGHT_NULL,
++ target_dp, DM_RIGHT_NULL,
++ src_name->name, target_name->name,
+ 0, error, 0);
+ }
+ return error;
+diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
+index 47082c0..a0dc6e5 100644
+--- a/fs/xfs/xfs_rtalloc.c
++++ b/fs/xfs/xfs_rtalloc.c
+@@ -44,6 +44,7 @@
+ #include "xfs_rw.h"
+ #include "xfs_inode_item.h"
+ #include "xfs_trans_space.h"
++#include "xfs_utils.h"
+
+
+ /*
+@@ -123,14 +124,14 @@ xfs_growfs_rt_alloc(
+ XFS_GROWRTALLOC_LOG_RES(mp), 0,
+ XFS_TRANS_PERM_LOG_RES,
+ XFS_DEFAULT_PERM_LOG_COUNT)))
+- goto error_exit;
++ goto error_cancel;
+ cancelflags = XFS_TRANS_RELEASE_LOG_RES;
+ /*
+ * Lock the inode.
+ */
+ if ((error = xfs_trans_iget(mp, tp, ino, 0,
+ XFS_ILOCK_EXCL, &ip)))
+- goto error_exit;
++ goto error_cancel;
+ XFS_BMAP_INIT(&flist, &firstblock);
+ /*
+ * Allocate blocks to the bitmap file.
+@@ -143,14 +144,16 @@ xfs_growfs_rt_alloc(
+ if (!error && nmap < 1)
+ error = XFS_ERROR(ENOSPC);
+ if (error)
+- goto error_exit;
++ goto error_cancel;
+ /*
+ * Free any blocks freed up in the transaction, then commit.
+ */
+ error = xfs_bmap_finish(&tp, &flist, &committed);
+ if (error)
+- goto error_exit;
+- xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
++ goto error_cancel;
++ error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
++ if (error)
++ goto error;
+ /*
+ * Now we need to clear the allocated blocks.
+ * Do this one block per transaction, to keep it simple.
+@@ -165,13 +168,13 @@ xfs_growfs_rt_alloc(
+ */
+ if ((error = xfs_trans_reserve(tp, 0,
+ XFS_GROWRTZERO_LOG_RES(mp), 0, 0, 0)))
+- goto error_exit;
++ goto error_cancel;
+ /*
+ * Lock the bitmap inode.
+ */
+ if ((error = xfs_trans_iget(mp, tp, ino, 0,
+ XFS_ILOCK_EXCL, &ip)))
+- goto error_exit;
++ goto error_cancel;
+ /*
+ * Get a buffer for the block.
+ */
+@@ -180,14 +183,16 @@ xfs_growfs_rt_alloc(
+ mp->m_bsize, 0);
+ if (bp == NULL) {
+ error = XFS_ERROR(EIO);
+- goto error_exit;
++ goto error_cancel;
+ }
+ memset(XFS_BUF_PTR(bp), 0, mp->m_sb.sb_blocksize);
+ xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
+ /*
+ * Commit the transaction.
+ */
+- xfs_trans_commit(tp, 0);
++ error = xfs_trans_commit(tp, 0);
++ if (error)
++ goto error;
+ }
+ /*
+ * Go on to the next extent, if any.
+@@ -195,8 +200,9 @@ xfs_growfs_rt_alloc(
+ oblocks = map.br_startoff + map.br_blockcount;
+ }
+ return 0;
+-error_exit:
++error_cancel:
+ xfs_trans_cancel(tp, cancelflags);
++error:
+ return error;
+ }
+
+@@ -1875,6 +1881,7 @@ xfs_growfs_rt(
+ xfs_trans_t *tp; /* transaction pointer */
+
+ sbp = &mp->m_sb;
++ cancelflags = 0;
+ /*
+ * Initial error checking.
+ */
+@@ -2041,13 +2048,15 @@ xfs_growfs_rt(
+ */
+ mp->m_rsumlevels = nrsumlevels;
+ mp->m_rsumsize = nrsumsize;
+- /*
+- * Commit the transaction.
+- */
+- xfs_trans_commit(tp, 0);
++
++ error = xfs_trans_commit(tp, 0);
++ if (error) {
++ tp = NULL;
++ break;
++ }
+ }
+
+- if (error)
++ if (error && tp)
+ xfs_trans_cancel(tp, cancelflags);
+
+ /*
+@@ -2278,7 +2287,7 @@ xfs_rtmount_inodes(
+ ASSERT(sbp->sb_rsumino != NULLFSINO);
+ error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, 0, &mp->m_rsumip, 0);
+ if (error) {
+- VN_RELE(XFS_ITOV(mp->m_rbmip));
++ IRELE(mp->m_rbmip);
+ return error;
+ }
+ ASSERT(mp->m_rsumip != NULL);
+diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c
+index cd3ece6..b0f31c0 100644
+--- a/fs/xfs/xfs_rw.c
++++ b/fs/xfs/xfs_rw.c
+@@ -126,11 +126,11 @@ xfs_write_sync_logforce(
+ * when we return.
+ */
+ if (iip && iip->ili_last_lsn) {
+- xfs_log_force(mp, iip->ili_last_lsn,
+- XFS_LOG_FORCE | XFS_LOG_SYNC);
++ error = _xfs_log_force(mp, iip->ili_last_lsn,
++ XFS_LOG_FORCE | XFS_LOG_SYNC, NULL);
+ } else if (xfs_ipincount(ip) > 0) {
+- xfs_log_force(mp, (xfs_lsn_t)0,
+- XFS_LOG_FORCE | XFS_LOG_SYNC);
++ error = _xfs_log_force(mp, (xfs_lsn_t)0,
++ XFS_LOG_FORCE | XFS_LOG_SYNC, NULL);
+ }
+
+ } else {
+diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
+index 7f40628..0804207 100644
+--- a/fs/xfs/xfs_trans.h
++++ b/fs/xfs/xfs_trans.h
+@@ -113,13 +113,8 @@ struct xfs_mount;
+ struct xfs_trans;
+ struct xfs_dquot_acct;
+
+-typedef struct xfs_ail_entry {
+- struct xfs_log_item *ail_forw; /* AIL forw pointer */
+- struct xfs_log_item *ail_back; /* AIL back pointer */
+-} xfs_ail_entry_t;
+-
+ typedef struct xfs_log_item {
+- xfs_ail_entry_t li_ail; /* AIL pointers */
++ struct list_head li_ail; /* AIL pointers */
+ xfs_lsn_t li_lsn; /* last on-disk lsn */
+ struct xfs_log_item_desc *li_desc; /* ptr to current desc*/
+ struct xfs_mount *li_mountp; /* ptr to fs mount */
+@@ -341,7 +336,6 @@ typedef struct xfs_trans {
+ unsigned int t_rtx_res; /* # of rt extents resvd */
+ unsigned int t_rtx_res_used; /* # of resvd rt extents used */
+ xfs_log_ticket_t t_ticket; /* log mgr ticket */
+- sema_t t_sema; /* sema for commit completion */
+ xfs_lsn_t t_lsn; /* log seq num of start of
+ * transaction. */
+ xfs_lsn_t t_commit_lsn; /* log seq num of end of
+diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
+index 76d470d..1f77c00 100644
+--- a/fs/xfs/xfs_trans_ail.c
++++ b/fs/xfs/xfs_trans_ail.c
+@@ -28,13 +28,13 @@
+ #include "xfs_trans_priv.h"
+ #include "xfs_error.h"
+
+-STATIC void xfs_ail_insert(xfs_ail_entry_t *, xfs_log_item_t *);
+-STATIC xfs_log_item_t * xfs_ail_delete(xfs_ail_entry_t *, xfs_log_item_t *);
+-STATIC xfs_log_item_t * xfs_ail_min(xfs_ail_entry_t *);
+-STATIC xfs_log_item_t * xfs_ail_next(xfs_ail_entry_t *, xfs_log_item_t *);
++STATIC void xfs_ail_insert(xfs_ail_t *, xfs_log_item_t *);
++STATIC xfs_log_item_t * xfs_ail_delete(xfs_ail_t *, xfs_log_item_t *);
++STATIC xfs_log_item_t * xfs_ail_min(xfs_ail_t *);
++STATIC xfs_log_item_t * xfs_ail_next(xfs_ail_t *, xfs_log_item_t *);
+
+ #ifdef DEBUG
+-STATIC void xfs_ail_check(xfs_ail_entry_t *, xfs_log_item_t *);
++STATIC void xfs_ail_check(xfs_ail_t *, xfs_log_item_t *);
+ #else
+ #define xfs_ail_check(a,l)
+ #endif /* DEBUG */
+@@ -57,7 +57,7 @@ xfs_trans_tail_ail(
+ xfs_log_item_t *lip;
+
+ spin_lock(&mp->m_ail_lock);
+- lip = xfs_ail_min(&(mp->m_ail.xa_ail));
++ lip = xfs_ail_min(&mp->m_ail);
+ if (lip == NULL) {
+ lsn = (xfs_lsn_t)0;
+ } else {
+@@ -91,7 +91,7 @@ xfs_trans_push_ail(
+ {
+ xfs_log_item_t *lip;
+
+- lip = xfs_ail_min(&mp->m_ail.xa_ail);
++ lip = xfs_ail_min(&mp->m_ail);
+ if (lip && !XFS_FORCED_SHUTDOWN(mp)) {
+ if (XFS_LSN_CMP(threshold_lsn, mp->m_ail.xa_target) > 0)
+ xfsaild_wakeup(mp, threshold_lsn);
+@@ -111,15 +111,17 @@ xfs_trans_first_push_ail(
+ {
+ xfs_log_item_t *lip;
+
+- lip = xfs_ail_min(&(mp->m_ail.xa_ail));
++ lip = xfs_ail_min(&mp->m_ail);
+ *gen = (int)mp->m_ail.xa_gen;
+ if (lsn == 0)
+ return lip;
+
+- while (lip && (XFS_LSN_CMP(lip->li_lsn, lsn) < 0))
+- lip = lip->li_ail.ail_forw;
++ list_for_each_entry(lip, &mp->m_ail.xa_ail, li_ail) {
++ if (XFS_LSN_CMP(lip->li_lsn, lsn) >= 0)
++ return lip;
++ }
+
+- return lip;
++ return NULL;
+ }
+
+ /*
+@@ -329,7 +331,7 @@ xfs_trans_unlocked_item(
+ * the call to xfs_log_move_tail() doesn't do anything if there's
+ * not enough free space to wake people up so we're safe calling it.
+ */
+- min_lip = xfs_ail_min(&mp->m_ail.xa_ail);
++ min_lip = xfs_ail_min(&mp->m_ail);
+
+ if (min_lip == lip)
+ xfs_log_move_tail(mp, 1);
+@@ -357,15 +359,13 @@ xfs_trans_update_ail(
+ xfs_log_item_t *lip,
+ xfs_lsn_t lsn) __releases(mp->m_ail_lock)
+ {
+- xfs_ail_entry_t *ailp;
+ xfs_log_item_t *dlip=NULL;
+ xfs_log_item_t *mlip; /* ptr to minimum lip */
+
+- ailp = &(mp->m_ail.xa_ail);
+- mlip = xfs_ail_min(ailp);
++ mlip = xfs_ail_min(&mp->m_ail);
+
+ if (lip->li_flags & XFS_LI_IN_AIL) {
+- dlip = xfs_ail_delete(ailp, lip);
++ dlip = xfs_ail_delete(&mp->m_ail, lip);
+ ASSERT(dlip == lip);
+ } else {
+ lip->li_flags |= XFS_LI_IN_AIL;
+@@ -373,11 +373,11 @@ xfs_trans_update_ail(
+
+ lip->li_lsn = lsn;
+
+- xfs_ail_insert(ailp, lip);
++ xfs_ail_insert(&mp->m_ail, lip);
+ mp->m_ail.xa_gen++;
+
+ if (mlip == dlip) {
+- mlip = xfs_ail_min(&(mp->m_ail.xa_ail));
++ mlip = xfs_ail_min(&mp->m_ail);
+ spin_unlock(&mp->m_ail_lock);
+ xfs_log_move_tail(mp, mlip->li_lsn);
+ } else {
+@@ -407,14 +407,12 @@ xfs_trans_delete_ail(
+ xfs_mount_t *mp,
+ xfs_log_item_t *lip) __releases(mp->m_ail_lock)
+ {
+- xfs_ail_entry_t *ailp;
+ xfs_log_item_t *dlip;
+ xfs_log_item_t *mlip;
+
+ if (lip->li_flags & XFS_LI_IN_AIL) {
+- ailp = &(mp->m_ail.xa_ail);
+- mlip = xfs_ail_min(ailp);
+- dlip = xfs_ail_delete(ailp, lip);
++ mlip = xfs_ail_min(&mp->m_ail);
++ dlip = xfs_ail_delete(&mp->m_ail, lip);
+ ASSERT(dlip == lip);
+
+
+@@ -423,7 +421,7 @@ xfs_trans_delete_ail(
+ mp->m_ail.xa_gen++;
+
+ if (mlip == dlip) {
+- mlip = xfs_ail_min(&(mp->m_ail.xa_ail));
++ mlip = xfs_ail_min(&mp->m_ail);
+ spin_unlock(&mp->m_ail_lock);
+ xfs_log_move_tail(mp, (mlip ? mlip->li_lsn : 0));
+ } else {
+@@ -440,7 +438,7 @@ xfs_trans_delete_ail(
+ else {
+ xfs_cmn_err(XFS_PTAG_AILDELETE, CE_ALERT, mp,
+ "%s: attempting to delete a log item that is not in the AIL",
+- __FUNCTION__);
++ __func__);
+ spin_unlock(&mp->m_ail_lock);
+ xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
+ }
+@@ -461,7 +459,7 @@ xfs_trans_first_ail(
+ {
+ xfs_log_item_t *lip;
+
+- lip = xfs_ail_min(&(mp->m_ail.xa_ail));
++ lip = xfs_ail_min(&mp->m_ail);
+ *gen = (int)mp->m_ail.xa_gen;
+
+ return lip;
+@@ -485,9 +483,9 @@ xfs_trans_next_ail(
+
+ ASSERT(mp && lip && gen);
+ if (mp->m_ail.xa_gen == *gen) {
+- nlip = xfs_ail_next(&(mp->m_ail.xa_ail), lip);
++ nlip = xfs_ail_next(&mp->m_ail, lip);
+ } else {
+- nlip = xfs_ail_min(&(mp->m_ail).xa_ail);
++ nlip = xfs_ail_min(&mp->m_ail);
+ *gen = (int)mp->m_ail.xa_gen;
+ if (restarts != NULL) {
+ XFS_STATS_INC(xs_push_ail_restarts);
+@@ -517,8 +515,7 @@ int
+ xfs_trans_ail_init(
+ xfs_mount_t *mp)
+ {
+- mp->m_ail.xa_ail.ail_forw = (xfs_log_item_t*)&mp->m_ail.xa_ail;
+- mp->m_ail.xa_ail.ail_back = (xfs_log_item_t*)&mp->m_ail.xa_ail;
++ INIT_LIST_HEAD(&mp->m_ail.xa_ail);
+ return xfsaild_start(mp);
+ }
+
+@@ -537,7 +534,7 @@ xfs_trans_ail_destroy(
+ */
+ STATIC void
+ xfs_ail_insert(
+- xfs_ail_entry_t *base,
++ xfs_ail_t *ailp,
+ xfs_log_item_t *lip)
+ /* ARGSUSED */
+ {
+@@ -546,27 +543,22 @@ xfs_ail_insert(
+ /*
+ * If the list is empty, just insert the item.
+ */
+- if (base->ail_back == (xfs_log_item_t*)base) {
+- base->ail_forw = lip;
+- base->ail_back = lip;
+- lip->li_ail.ail_forw = (xfs_log_item_t*)base;
+- lip->li_ail.ail_back = (xfs_log_item_t*)base;
++ if (list_empty(&ailp->xa_ail)) {
++ list_add(&lip->li_ail, &ailp->xa_ail);
+ return;
+ }
+
+- next_lip = base->ail_back;
+- while ((next_lip != (xfs_log_item_t*)base) &&
+- (XFS_LSN_CMP(next_lip->li_lsn, lip->li_lsn) > 0)) {
+- next_lip = next_lip->li_ail.ail_back;
++ list_for_each_entry_reverse(next_lip, &ailp->xa_ail, li_ail) {
++ if (XFS_LSN_CMP(next_lip->li_lsn, lip->li_lsn) <= 0)
++ break;
+ }
+- ASSERT((next_lip == (xfs_log_item_t*)base) ||
++
++ ASSERT((&next_lip->li_ail == &ailp->xa_ail) ||
+ (XFS_LSN_CMP(next_lip->li_lsn, lip->li_lsn) <= 0));
+- lip->li_ail.ail_forw = next_lip->li_ail.ail_forw;
+- lip->li_ail.ail_back = next_lip;
+- next_lip->li_ail.ail_forw = lip;
+- lip->li_ail.ail_forw->li_ail.ail_back = lip;
+
+- xfs_ail_check(base, lip);
++ list_add(&lip->li_ail, &next_lip->li_ail);
++
++ xfs_ail_check(ailp, lip);
+ return;
+ }
+
+@@ -576,15 +568,13 @@ xfs_ail_insert(
+ /*ARGSUSED*/
+ STATIC xfs_log_item_t *
+ xfs_ail_delete(
+- xfs_ail_entry_t *base,
++ xfs_ail_t *ailp,
+ xfs_log_item_t *lip)
+ /* ARGSUSED */
+ {
+- xfs_ail_check(base, lip);
+- lip->li_ail.ail_forw->li_ail.ail_back = lip->li_ail.ail_back;
+- lip->li_ail.ail_back->li_ail.ail_forw = lip->li_ail.ail_forw;
+- lip->li_ail.ail_forw = NULL;
+- lip->li_ail.ail_back = NULL;
++ xfs_ail_check(ailp, lip);
++
++ list_del(&lip->li_ail);
+
+ return lip;
+ }
+@@ -595,14 +585,13 @@ xfs_ail_delete(
+ */
+ STATIC xfs_log_item_t *
+ xfs_ail_min(
+- xfs_ail_entry_t *base)
++ xfs_ail_t *ailp)
+ /* ARGSUSED */
+ {
+- register xfs_log_item_t *forw = base->ail_forw;
+- if (forw == (xfs_log_item_t*)base) {
++ if (list_empty(&ailp->xa_ail))
+ return NULL;
+- }
+- return forw;
++
++ return list_first_entry(&ailp->xa_ail, xfs_log_item_t, li_ail);
+ }
+
+ /*
+@@ -612,15 +601,14 @@ xfs_ail_min(
+ */
+ STATIC xfs_log_item_t *
+ xfs_ail_next(
+- xfs_ail_entry_t *base,
++ xfs_ail_t *ailp,
+ xfs_log_item_t *lip)
+ /* ARGSUSED */
+ {
+- if (lip->li_ail.ail_forw == (xfs_log_item_t*)base) {
++ if (lip->li_ail.next == &ailp->xa_ail)
+ return NULL;
+- }
+- return lip->li_ail.ail_forw;
+
++ return list_first_entry(&lip->li_ail, xfs_log_item_t, li_ail);
+ }
+
+ #ifdef DEBUG
+@@ -629,57 +617,40 @@ xfs_ail_next(
+ */
+ STATIC void
+ xfs_ail_check(
+- xfs_ail_entry_t *base,
++ xfs_ail_t *ailp,
+ xfs_log_item_t *lip)
+ {
+ xfs_log_item_t *prev_lip;
+
+- prev_lip = base->ail_forw;
+- if (prev_lip == (xfs_log_item_t*)base) {
+- /*
+- * Make sure the pointers are correct when the list
+- * is empty.
+- */
+- ASSERT(base->ail_back == (xfs_log_item_t*)base);
++ if (list_empty(&ailp->xa_ail))
+ return;
+- }
+
+ /*
+ * Check the next and previous entries are valid.
+ */
+ ASSERT((lip->li_flags & XFS_LI_IN_AIL) != 0);
+- prev_lip = lip->li_ail.ail_back;
+- if (prev_lip != (xfs_log_item_t*)base) {
+- ASSERT(prev_lip->li_ail.ail_forw == lip);
++ prev_lip = list_entry(lip->li_ail.prev, xfs_log_item_t, li_ail);
++ if (&prev_lip->li_ail != &ailp->xa_ail)
+ ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) <= 0);
+- }
+- prev_lip = lip->li_ail.ail_forw;
+- if (prev_lip != (xfs_log_item_t*)base) {
+- ASSERT(prev_lip->li_ail.ail_back == lip);
++
++ prev_lip = list_entry(lip->li_ail.next, xfs_log_item_t, li_ail);
++ if (&prev_lip->li_ail != &ailp->xa_ail)
+ ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) >= 0);
+- }
+
+
+ #ifdef XFS_TRANS_DEBUG
+ /*
+- * Walk the list checking forward and backward pointers,
+- * lsn ordering, and that every entry has the XFS_LI_IN_AIL
+- * flag set. This is really expensive, so only do it when
+- * specifically debugging the transaction subsystem.
++ * Walk the list checking lsn ordering, and that every entry has the
++ * XFS_LI_IN_AIL flag set. This is really expensive, so only do it
++ * when specifically debugging the transaction subsystem.
+ */
+- prev_lip = (xfs_log_item_t*)base;
+- while (lip != (xfs_log_item_t*)base) {
+- if (prev_lip != (xfs_log_item_t*)base) {
+- ASSERT(prev_lip->li_ail.ail_forw == lip);
++ prev_lip = list_entry(&ailp->xa_ail, xfs_log_item_t, li_ail);
++ list_for_each_entry(lip, &ailp->xa_ail, li_ail) {
++ if (&prev_lip->li_ail != &ailp->xa_ail)
+ ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) <= 0);
+- }
+- ASSERT(lip->li_ail.ail_back == prev_lip);
+ ASSERT((lip->li_flags & XFS_LI_IN_AIL) != 0);
+ prev_lip = lip;
+- lip = lip->li_ail.ail_forw;
+ }
+- ASSERT(lip == (xfs_log_item_t*)base);
+- ASSERT(base->ail_back == prev_lip);
+ #endif /* XFS_TRANS_DEBUG */
+ }
+ #endif /* DEBUG */
+diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
+index 60b6b89..cb0c583 100644
+--- a/fs/xfs/xfs_trans_buf.c
++++ b/fs/xfs/xfs_trans_buf.c
+@@ -304,7 +304,8 @@ xfs_trans_read_buf(
+ if (tp == NULL) {
+ bp = xfs_buf_read_flags(target, blkno, len, flags | BUF_BUSY);
+ if (!bp)
+- return XFS_ERROR(ENOMEM);
++ return (flags & XFS_BUF_TRYLOCK) ?
++ EAGAIN : XFS_ERROR(ENOMEM);
+
+ if ((bp != NULL) && (XFS_BUF_GETERROR(bp) != 0)) {
+ xfs_ioerror_alert("xfs_trans_read_buf", mp,
+@@ -353,17 +354,15 @@ xfs_trans_read_buf(
+ ASSERT(!XFS_BUF_ISASYNC(bp));
+ XFS_BUF_READ(bp);
+ xfsbdstrat(tp->t_mountp, bp);
+- xfs_iowait(bp);
+- if (XFS_BUF_GETERROR(bp) != 0) {
++ error = xfs_iowait(bp);
++ if (error) {
+ xfs_ioerror_alert("xfs_trans_read_buf", mp,
+ bp, blkno);
+- error = XFS_BUF_GETERROR(bp);
+ xfs_buf_relse(bp);
+ /*
+- * We can gracefully recover from most
+- * read errors. Ones we can't are those
+- * that happen after the transaction's
+- * already dirty.
++ * We can gracefully recover from most read
++ * errors. Ones we can't are those that happen
++ * after the transaction's already dirty.
+ */
+ if (tp->t_flags & XFS_TRANS_DIRTY)
+ xfs_force_shutdown(tp->t_mountp,
+diff --git a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h
+index 5c89be4..0f51916 100644
+--- a/fs/xfs/xfs_types.h
++++ b/fs/xfs/xfs_types.h
+@@ -160,4 +160,9 @@ typedef enum {
+ XFS_BTNUM_MAX
+ } xfs_btnum_t;
+
++struct xfs_name {
++ const char *name;
++ int len;
++};
++
+ #endif /* __XFS_TYPES_H__ */
+diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c
+index 18a85e7..2b8dc7e 100644
+--- a/fs/xfs/xfs_utils.c
++++ b/fs/xfs/xfs_utils.c
+@@ -40,34 +40,12 @@
+ #include "xfs_itable.h"
+ #include "xfs_utils.h"
+
+-/*
+- * xfs_get_dir_entry is used to get a reference to an inode given
+- * its parent directory inode and the name of the file. It does
+- * not lock the child inode, and it unlocks the directory before
+- * returning. The directory's generation number is returned for
+- * use by a later call to xfs_lock_dir_and_entry.
+- */
+-int
+-xfs_get_dir_entry(
+- bhv_vname_t *dentry,
+- xfs_inode_t **ipp)
+-{
+- bhv_vnode_t *vp;
+-
+- vp = VNAME_TO_VNODE(dentry);
+-
+- *ipp = xfs_vtoi(vp);
+- if (!*ipp)
+- return XFS_ERROR(ENOENT);
+- VN_HOLD(vp);
+- return 0;
+-}
+
+ int
+ xfs_dir_lookup_int(
+ xfs_inode_t *dp,
+ uint lock_mode,
+- bhv_vname_t *dentry,
++ struct xfs_name *name,
+ xfs_ino_t *inum,
+ xfs_inode_t **ipp)
+ {
+@@ -75,7 +53,7 @@ xfs_dir_lookup_int(
+
+ xfs_itrace_entry(dp);
+
+- error = xfs_dir_lookup(NULL, dp, VNAME(dentry), VNAMELEN(dentry), inum);
++ error = xfs_dir_lookup(NULL, dp, name, inum);
+ if (!error) {
+ /*
+ * Unlock the directory. We do this because we can't
+diff --git a/fs/xfs/xfs_utils.h b/fs/xfs/xfs_utils.h
+index f857fcc..175b126 100644
+--- a/fs/xfs/xfs_utils.h
++++ b/fs/xfs/xfs_utils.h
+@@ -21,15 +21,14 @@
+ #define IRELE(ip) VN_RELE(XFS_ITOV(ip))
+ #define IHOLD(ip) VN_HOLD(XFS_ITOV(ip))
+
+-extern int xfs_get_dir_entry (bhv_vname_t *, xfs_inode_t **);
+-extern int xfs_dir_lookup_int (xfs_inode_t *, uint, bhv_vname_t *, xfs_ino_t *,
+- xfs_inode_t **);
+-extern int xfs_truncate_file (xfs_mount_t *, xfs_inode_t *);
+-extern int xfs_dir_ialloc (xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t,
++extern int xfs_dir_lookup_int(xfs_inode_t *, uint, struct xfs_name *,
++ xfs_ino_t *, xfs_inode_t **);
++extern int xfs_truncate_file(xfs_mount_t *, xfs_inode_t *);
++extern int xfs_dir_ialloc(xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t,
+ xfs_dev_t, cred_t *, prid_t, int,
+ xfs_inode_t **, int *);
+-extern int xfs_droplink (xfs_trans_t *, xfs_inode_t *);
+-extern int xfs_bumplink (xfs_trans_t *, xfs_inode_t *);
+-extern void xfs_bump_ino_vers2 (xfs_trans_t *, xfs_inode_t *);
++extern int xfs_droplink(xfs_trans_t *, xfs_inode_t *);
++extern int xfs_bumplink(xfs_trans_t *, xfs_inode_t *);
++extern void xfs_bump_ino_vers2(xfs_trans_t *, xfs_inode_t *);
+
+ #endif /* __XFS_UTILS_H__ */
+diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
+index 7094caf..fc48158 100644
+--- a/fs/xfs/xfs_vfsops.c
++++ b/fs/xfs/xfs_vfsops.c
+@@ -43,7 +43,6 @@
+ #include "xfs_error.h"
+ #include "xfs_bmap.h"
+ #include "xfs_rw.h"
+-#include "xfs_refcache.h"
+ #include "xfs_buf_item.h"
+ #include "xfs_log_priv.h"
+ #include "xfs_dir2_trace.h"
+@@ -56,6 +55,7 @@
+ #include "xfs_fsops.h"
+ #include "xfs_vnodeops.h"
+ #include "xfs_vfsops.h"
++#include "xfs_utils.h"
+
+
+ int __init
+@@ -69,15 +69,17 @@ xfs_init(void)
+ /*
+ * Initialize all of the zone allocators we use.
+ */
++ xfs_log_ticket_zone = kmem_zone_init(sizeof(xlog_ticket_t),
++ "xfs_log_ticket");
+ xfs_bmap_free_item_zone = kmem_zone_init(sizeof(xfs_bmap_free_item_t),
+- "xfs_bmap_free_item");
++ "xfs_bmap_free_item");
+ xfs_btree_cur_zone = kmem_zone_init(sizeof(xfs_btree_cur_t),
+- "xfs_btree_cur");
+- xfs_trans_zone = kmem_zone_init(sizeof(xfs_trans_t), "xfs_trans");
+- xfs_da_state_zone =
+- kmem_zone_init(sizeof(xfs_da_state_t), "xfs_da_state");
++ "xfs_btree_cur");
++ xfs_da_state_zone = kmem_zone_init(sizeof(xfs_da_state_t),
++ "xfs_da_state");
+ xfs_dabuf_zone = kmem_zone_init(sizeof(xfs_dabuf_t), "xfs_dabuf");
+ xfs_ifork_zone = kmem_zone_init(sizeof(xfs_ifork_t), "xfs_ifork");
++ xfs_trans_zone = kmem_zone_init(sizeof(xfs_trans_t), "xfs_trans");
+ xfs_acl_zone_init(xfs_acl_zone, "xfs_acl");
+ xfs_mru_cache_init();
+ xfs_filestream_init();
+@@ -113,9 +115,6 @@ xfs_init(void)
+ xfs_ili_zone =
+ kmem_zone_init_flags(sizeof(xfs_inode_log_item_t), "xfs_ili",
+ KM_ZONE_SPREAD, NULL);
+- xfs_icluster_zone =
+- kmem_zone_init_flags(sizeof(xfs_icluster_t), "xfs_icluster",
+- KM_ZONE_SPREAD, NULL);
+
+ /*
+ * Allocate global trace buffers.
+@@ -153,11 +152,9 @@ xfs_cleanup(void)
+ extern kmem_zone_t *xfs_inode_zone;
+ extern kmem_zone_t *xfs_efd_zone;
+ extern kmem_zone_t *xfs_efi_zone;
+- extern kmem_zone_t *xfs_icluster_zone;
+
+ xfs_cleanup_procfs();
+ xfs_sysctl_unregister();
+- xfs_refcache_destroy();
+ xfs_filestream_uninit();
+ xfs_mru_cache_uninit();
+ xfs_acl_zone_destroy(xfs_acl_zone);
+@@ -189,7 +186,6 @@ xfs_cleanup(void)
+ kmem_zone_destroy(xfs_efi_zone);
+ kmem_zone_destroy(xfs_ifork_zone);
+ kmem_zone_destroy(xfs_ili_zone);
+- kmem_zone_destroy(xfs_icluster_zone);
+ }
+
+ /*
+@@ -573,7 +569,7 @@ xfs_unmount(
+ #ifdef HAVE_DMAPI
+ if (mp->m_flags & XFS_MOUNT_DMAPI) {
+ error = XFS_SEND_PREUNMOUNT(mp,
+- rvp, DM_RIGHT_NULL, rvp, DM_RIGHT_NULL,
++ rip, DM_RIGHT_NULL, rip, DM_RIGHT_NULL,
+ NULL, NULL, 0, 0,
+ (mp->m_dmevmask & (1<<DM_EVENT_PREUNMOUNT))?
+ 0:DM_FLAGS_UNWANTED);
+@@ -584,11 +580,6 @@ xfs_unmount(
+ 0 : DM_FLAGS_UNWANTED;
+ }
+ #endif
+- /*
+- * First blow any referenced inode from this file system
+- * out of the reference cache, and delete the timer.
+- */
+- xfs_refcache_purge_mp(mp);
+
+ /*
+ * Blow away any referenced inode in the filestreams cache.
+@@ -607,7 +598,7 @@ xfs_unmount(
+ /*
+ * Drop the reference count
+ */
+- VN_RELE(rvp);
++ IRELE(rip);
+
+ /*
+ * If we're forcing a shutdown, typically because of a media error,
+@@ -629,7 +620,7 @@ out:
+ /* Note: mp structure must still exist for
+ * XFS_SEND_UNMOUNT() call.
+ */
+- XFS_SEND_UNMOUNT(mp, error == 0 ? rvp : NULL,
++ XFS_SEND_UNMOUNT(mp, error == 0 ? rip : NULL,
+ DM_RIGHT_NULL, 0, error, unmount_event_flags);
+ }
+ if (xfs_unmountfs_needed) {
+@@ -646,13 +637,12 @@ out:
+ return XFS_ERROR(error);
+ }
+
+-STATIC int
++STATIC void
+ xfs_quiesce_fs(
+ xfs_mount_t *mp)
+ {
+ int count = 0, pincount;
+
+- xfs_refcache_purge_mp(mp);
+ xfs_flush_buftarg(mp->m_ddev_targp, 0);
+ xfs_finish_reclaim_all(mp, 0);
+
+@@ -671,8 +661,6 @@ xfs_quiesce_fs(
+ count++;
+ }
+ } while (count < 2);
+-
+- return 0;
+ }
+
+ /*
+@@ -684,6 +672,8 @@ void
+ xfs_attr_quiesce(
+ xfs_mount_t *mp)
+ {
++ int error = 0;
++
+ /* wait for all modifications to complete */
+ while (atomic_read(&mp->m_active_trans) > 0)
+ delay(100);
+@@ -694,7 +684,11 @@ xfs_attr_quiesce(
+ ASSERT_ALWAYS(atomic_read(&mp->m_active_trans) == 0);
+
+ /* Push the superblock and write an unmount record */
+- xfs_log_sbcount(mp, 1);
++ error = xfs_log_sbcount(mp, 1);
++ if (error)
++ xfs_fs_cmn_err(CE_WARN, mp,
++ "xfs_attr_quiesce: failed to log sb changes. "
++ "Frozen image may not be consistent.");
+ xfs_log_unmount_write(mp);
+ xfs_unmountfs_writesb(mp);
+ }
+@@ -790,8 +784,8 @@ xfs_unmount_flush(
+ goto fscorrupt_out2;
+
+ if (rbmip) {
+- VN_RELE(XFS_ITOV(rbmip));
+- VN_RELE(XFS_ITOV(rsumip));
++ IRELE(rbmip);
++ IRELE(rsumip);
+ }
+
+ xfs_iunlock(rip, XFS_ILOCK_EXCL);
+@@ -1169,10 +1163,10 @@ xfs_sync_inodes(
+ * above, then wait until after we've unlocked
+ * the inode to release the reference. This is
+ * because we can be already holding the inode
+- * lock when VN_RELE() calls xfs_inactive().
++ * lock when IRELE() calls xfs_inactive().
+ *
+ * Make sure to drop the mount lock before calling
+- * VN_RELE() so that we don't trip over ourselves if
++ * IRELE() so that we don't trip over ourselves if
+ * we have to go for the mount lock again in the
+ * inactive code.
+ */
+@@ -1180,7 +1174,7 @@ xfs_sync_inodes(
+ IPOINTER_INSERT(ip, mp);
+ }
+
+- VN_RELE(vp);
++ IRELE(ip);
+
+ vnode_refed = B_FALSE;
+ }
+@@ -1323,30 +1317,8 @@ xfs_syncsub(
+ }
+
+ /*
+- * If this is the periodic sync, then kick some entries out of
+- * the reference cache. This ensures that idle entries are
+- * eventually kicked out of the cache.
+- */
+- if (flags & SYNC_REFCACHE) {
+- if (flags & SYNC_WAIT)
+- xfs_refcache_purge_mp(mp);
+- else
+- xfs_refcache_purge_some(mp);
+- }
+-
+- /*
+- * If asked, update the disk superblock with incore counter values if we
+- * are using non-persistent counters so that they don't get too far out
+- * of sync if we crash or get a forced shutdown. We don't want to force
+- * this to disk, just get a transaction into the iclogs....
+- */
+- if (flags & SYNC_SUPER)
+- xfs_log_sbcount(mp, 0);
+-
+- /*
+ * Now check to see if the log needs a "dummy" transaction.
+ */
+-
+ if (!(flags & SYNC_REMOUNT) && xfs_log_need_covered(mp)) {
+ xfs_trans_t *tp;
+ xfs_inode_t *ip;
+diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
+index 64c5953..6650601 100644
+--- a/fs/xfs/xfs_vnodeops.c
++++ b/fs/xfs/xfs_vnodeops.c
+@@ -48,7 +48,6 @@
+ #include "xfs_quota.h"
+ #include "xfs_utils.h"
+ #include "xfs_rtalloc.h"
+-#include "xfs_refcache.h"
+ #include "xfs_trans_space.h"
+ #include "xfs_log_priv.h"
+ #include "xfs_filestream.h"
+@@ -327,7 +326,7 @@ xfs_setattr(
+ if (DM_EVENT_ENABLED(ip, DM_EVENT_TRUNCATE) &&
+ !(flags & ATTR_DMI)) {
+ int dmflags = AT_DELAY_FLAG(flags) | DM_SEM_FLAG_WR;
+- code = XFS_SEND_DATA(mp, DM_EVENT_TRUNCATE, vp,
++ code = XFS_SEND_DATA(mp, DM_EVENT_TRUNCATE, ip,
+ vap->va_size, 0, dmflags, NULL);
+ if (code) {
+ lock_flags = 0;
+@@ -634,6 +633,15 @@ xfs_setattr(
+ * Truncate file. Must have write permission and not be a directory.
+ */
+ if (mask & XFS_AT_SIZE) {
++ /*
++ * Only change the c/mtime if we are changing the size
++ * or we are explicitly asked to change it. This handles
++ * the semantic difference between truncate() and ftruncate()
++ * as implemented in the VFS.
++ */
++ if (vap->va_size != ip->i_size || (mask & XFS_AT_CTIME))
++ timeflags |= XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG;
++
+ if (vap->va_size > ip->i_size) {
+ xfs_igrow_finish(tp, ip, vap->va_size,
+ !(flags & ATTR_DMI));
+@@ -662,10 +670,6 @@ xfs_setattr(
+ */
+ xfs_iflags_set(ip, XFS_ITRUNCATED);
+ }
+- /*
+- * Have to do this even if the file's size doesn't change.
+- */
+- timeflags |= XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG;
+ }
+
+ /*
+@@ -877,7 +881,7 @@ xfs_setattr(
+
+ if (DM_EVENT_ENABLED(ip, DM_EVENT_ATTRIBUTE) &&
+ !(flags & ATTR_DMI)) {
+- (void) XFS_SEND_NAMESP(mp, DM_EVENT_ATTRIBUTE, vp, DM_RIGHT_NULL,
++ (void) XFS_SEND_NAMESP(mp, DM_EVENT_ATTRIBUTE, ip, DM_RIGHT_NULL,
+ NULL, DM_RIGHT_NULL, NULL, NULL,
+ 0, 0, AT_DELAY_FLAG(flags));
+ }
+@@ -1443,28 +1447,22 @@ xfs_inactive_attrs(
+ tp = *tpp;
+ mp = ip->i_mount;
+ ASSERT(ip->i_d.di_forkoff != 0);
+- xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
++ error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
++ if (error)
++ goto error_unlock;
+
+ error = xfs_attr_inactive(ip);
+- if (error) {
+- *tpp = NULL;
+- xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+- return error; /* goto out */
+- }
++ if (error)
++ goto error_unlock;
+
+ tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
+ error = xfs_trans_reserve(tp, 0,
+ XFS_IFREE_LOG_RES(mp),
+ 0, XFS_TRANS_PERM_LOG_RES,
+ XFS_INACTIVE_LOG_COUNT);
+- if (error) {
+- ASSERT(XFS_FORCED_SHUTDOWN(mp));
+- xfs_trans_cancel(tp, 0);
+- *tpp = NULL;
+- xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+- return error;
+- }
++ if (error)
++ goto error_cancel;
+
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
+ xfs_trans_ijoin(tp, ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
+@@ -1475,6 +1473,14 @@ xfs_inactive_attrs(
+
+ *tpp = tp;
+ return 0;
++
++error_cancel:
++ ASSERT(XFS_FORCED_SHUTDOWN(mp));
++ xfs_trans_cancel(tp, 0);
++error_unlock:
++ *tpp = NULL;
++ xfs_iunlock(ip, XFS_IOLOCK_EXCL);
++ return error;
+ }
+
+ int
+@@ -1520,12 +1526,6 @@ xfs_release(
+ xfs_flush_pages(ip, 0, -1, XFS_B_ASYNC, FI_NONE);
+ }
+
+-#ifdef HAVE_REFCACHE
+- /* If we are in the NFS reference cache then don't do this now */
+- if (ip->i_refcache)
+- return 0;
+-#endif
+-
+ if (ip->i_d.di_nlink != 0) {
+ if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
+ ((ip->i_size > 0) || (VN_CACHED(vp) > 0 ||
+@@ -1588,9 +1588,8 @@ xfs_inactive(
+
+ mp = ip->i_mount;
+
+- if (ip->i_d.di_nlink == 0 && DM_EVENT_ENABLED(ip, DM_EVENT_DESTROY)) {
+- (void) XFS_SEND_DESTROY(mp, vp, DM_RIGHT_NULL);
+- }
++ if (ip->i_d.di_nlink == 0 && DM_EVENT_ENABLED(ip, DM_EVENT_DESTROY))
++ XFS_SEND_DESTROY(mp, ip, DM_RIGHT_NULL);
+
+ error = 0;
+
+@@ -1744,11 +1743,18 @@ xfs_inactive(
+ XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, XFS_TRANS_DQ_ICOUNT, -1);
+
+ /*
+- * Just ignore errors at this point. There is
+- * nothing we can do except to try to keep going.
++ * Just ignore errors at this point. There is nothing we can
++ * do except to try to keep going. Make sure it's not a silent
++ * error.
+ */
+- (void) xfs_bmap_finish(&tp, &free_list, &committed);
+- (void) xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
++ error = xfs_bmap_finish(&tp, &free_list, &committed);
++ if (error)
++ xfs_fs_cmn_err(CE_NOTE, mp, "xfs_inactive: "
++ "xfs_bmap_finish() returned error %d", error);
++ error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
++ if (error)
++ xfs_fs_cmn_err(CE_NOTE, mp, "xfs_inactive: "
++ "xfs_trans_commit() returned error %d", error);
+ }
+ /*
+ * Release the dquots held by inode, if any.
+@@ -1765,8 +1771,8 @@ xfs_inactive(
+ int
+ xfs_lookup(
+ xfs_inode_t *dp,
+- bhv_vname_t *dentry,
+- bhv_vnode_t **vpp)
++ struct xfs_name *name,
++ xfs_inode_t **ipp)
+ {
+ xfs_inode_t *ip;
+ xfs_ino_t e_inum;
+@@ -1779,9 +1785,9 @@ xfs_lookup(
+ return XFS_ERROR(EIO);
+
+ lock_mode = xfs_ilock_map_shared(dp);
+- error = xfs_dir_lookup_int(dp, lock_mode, dentry, &e_inum, &ip);
++ error = xfs_dir_lookup_int(dp, lock_mode, name, &e_inum, &ip);
+ if (!error) {
+- *vpp = XFS_ITOV(ip);
++ *ipp = ip;
+ xfs_itrace_ref(ip);
+ }
+ xfs_iunlock_map_shared(dp, lock_mode);
+@@ -1791,19 +1797,16 @@ xfs_lookup(
+ int
+ xfs_create(
+ xfs_inode_t *dp,
+- bhv_vname_t *dentry,
++ struct xfs_name *name,
+ mode_t mode,
+ xfs_dev_t rdev,
+- bhv_vnode_t **vpp,
++ xfs_inode_t **ipp,
+ cred_t *credp)
+ {
+- char *name = VNAME(dentry);
+- xfs_mount_t *mp = dp->i_mount;
+- bhv_vnode_t *dir_vp = XFS_ITOV(dp);
++ xfs_mount_t *mp = dp->i_mount;
+ xfs_inode_t *ip;
+- bhv_vnode_t *vp = NULL;
+ xfs_trans_t *tp;
+- int error;
++ int error;
+ xfs_bmap_free_t free_list;
+ xfs_fsblock_t first_block;
+ boolean_t unlock_dp_on_error = B_FALSE;
+@@ -1813,17 +1816,14 @@ xfs_create(
+ xfs_prid_t prid;
+ struct xfs_dquot *udqp, *gdqp;
+ uint resblks;
+- int namelen;
+
+- ASSERT(!*vpp);
++ ASSERT(!*ipp);
+ xfs_itrace_entry(dp);
+
+- namelen = VNAMELEN(dentry);
+-
+ if (DM_EVENT_ENABLED(dp, DM_EVENT_CREATE)) {
+ error = XFS_SEND_NAMESP(mp, DM_EVENT_CREATE,
+- dir_vp, DM_RIGHT_NULL, NULL,
+- DM_RIGHT_NULL, name, NULL,
++ dp, DM_RIGHT_NULL, NULL,
++ DM_RIGHT_NULL, name->name, NULL,
+ mode, 0, 0);
+
+ if (error)
+@@ -1855,7 +1855,7 @@ xfs_create(
+
+ tp = xfs_trans_alloc(mp, XFS_TRANS_CREATE);
+ cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
+- resblks = XFS_CREATE_SPACE_RES(mp, namelen);
++ resblks = XFS_CREATE_SPACE_RES(mp, name->len);
+ /*
+ * Initially assume that the file does not exist and
+ * reserve the resources for that case. If that is not
+@@ -1888,7 +1888,8 @@ xfs_create(
+ if (error)
+ goto error_return;
+
+- if (resblks == 0 && (error = xfs_dir_canenter(tp, dp, name, namelen)))
++ error = xfs_dir_canenter(tp, dp, name, resblks);
++ if (error)
+ goto error_return;
+ error = xfs_dir_ialloc(&tp, dp, mode, 1,
+ rdev, credp, prid, resblks > 0,
+@@ -1914,11 +1915,11 @@ xfs_create(
+ * the transaction cancel unlocking dp so don't do it explicitly in the
+ * error path.
+ */
+- VN_HOLD(dir_vp);
++ IHOLD(dp);
+ xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
+ unlock_dp_on_error = B_FALSE;
+
+- error = xfs_dir_createname(tp, dp, name, namelen, ip->i_ino,
++ error = xfs_dir_createname(tp, dp, name, ip->i_ino,
+ &first_block, &free_list, resblks ?
+ resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
+ if (error) {
+@@ -1952,7 +1953,6 @@ xfs_create(
+ * vnode to the caller, we bump the vnode ref count now.
+ */
+ IHOLD(ip);
+- vp = XFS_ITOV(ip);
+
+ error = xfs_bmap_finish(&tp, &free_list, &committed);
+ if (error) {
+@@ -1970,17 +1970,17 @@ xfs_create(
+ XFS_QM_DQRELE(mp, udqp);
+ XFS_QM_DQRELE(mp, gdqp);
+
+- *vpp = vp;
++ *ipp = ip;
+
+ /* Fallthrough to std_return with error = 0 */
+
+ std_return:
+- if ((*vpp || (error != 0 && dm_event_sent != 0)) &&
++ if ((*ipp || (error != 0 && dm_event_sent != 0)) &&
+ DM_EVENT_ENABLED(dp, DM_EVENT_POSTCREATE)) {
+ (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTCREATE,
+- dir_vp, DM_RIGHT_NULL,
+- *vpp ? vp:NULL,
+- DM_RIGHT_NULL, name, NULL,
++ dp, DM_RIGHT_NULL,
++ *ipp ? ip : NULL,
++ DM_RIGHT_NULL, name->name, NULL,
+ mode, error, 0);
+ }
+ return error;
+@@ -2272,46 +2272,32 @@ int remove_which_error_return = 0;
+ int
+ xfs_remove(
+ xfs_inode_t *dp,
+- bhv_vname_t *dentry)
++ struct xfs_name *name,
++ xfs_inode_t *ip)
+ {
+- bhv_vnode_t *dir_vp = XFS_ITOV(dp);
+- char *name = VNAME(dentry);
+ xfs_mount_t *mp = dp->i_mount;
+- xfs_inode_t *ip;
+ xfs_trans_t *tp = NULL;
+ int error = 0;
+ xfs_bmap_free_t free_list;
+ xfs_fsblock_t first_block;
+ int cancel_flags;
+ int committed;
+- int dm_di_mode = 0;
+ int link_zero;
+ uint resblks;
+- int namelen;
+
+ xfs_itrace_entry(dp);
+
+ if (XFS_FORCED_SHUTDOWN(mp))
+ return XFS_ERROR(EIO);
+
+- namelen = VNAMELEN(dentry);
+-
+- if (!xfs_get_dir_entry(dentry, &ip)) {
+- dm_di_mode = ip->i_d.di_mode;
+- IRELE(ip);
+- }
+-
+ if (DM_EVENT_ENABLED(dp, DM_EVENT_REMOVE)) {
+- error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE, dir_vp,
+- DM_RIGHT_NULL, NULL, DM_RIGHT_NULL,
+- name, NULL, dm_di_mode, 0, 0);
++ error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE, dp, DM_RIGHT_NULL,
++ NULL, DM_RIGHT_NULL, name->name, NULL,
++ ip->i_d.di_mode, 0, 0);
+ if (error)
+ return error;
+ }
+
+- /* From this point on, return through std_return */
+- ip = NULL;
+-
+ /*
+ * We need to get a reference to ip before we get our log
+ * reservation. The reason for this is that we cannot call
+@@ -2324,13 +2310,7 @@ xfs_remove(
+ * when we call xfs_iget. Instead we get an unlocked reference
+ * to the inode before getting our log reservation.
+ */
+- error = xfs_get_dir_entry(dentry, &ip);
+- if (error) {
+- REMOVE_DEBUG_TRACE(__LINE__);
+- goto std_return;
+- }
+-
+- dm_di_mode = ip->i_d.di_mode;
++ IHOLD(ip);
+
+ xfs_itrace_entry(ip);
+ xfs_itrace_ref(ip);
+@@ -2398,7 +2378,7 @@ xfs_remove(
+ * Entry must exist since we did a lookup in xfs_lock_dir_and_entry.
+ */
+ XFS_BMAP_INIT(&free_list, &first_block);
+- error = xfs_dir_removename(tp, dp, name, namelen, ip->i_ino,
++ error = xfs_dir_removename(tp, dp, name, ip->i_ino,
+ &first_block, &free_list, 0);
+ if (error) {
+ ASSERT(error != ENOENT);
+@@ -2449,14 +2429,6 @@ xfs_remove(
+ }
+
+ /*
+- * Before we drop our extra reference to the inode, purge it
+- * from the refcache if it is there. By waiting until afterwards
+- * to do the IRELE, we ensure that we won't go inactive in the
+- * xfs_refcache_purge_ip routine (although that would be OK).
+- */
+- xfs_refcache_purge_ip(ip);
+-
+- /*
+ * If we are using filestreams, kill the stream association.
+ * If the file is still open it may get a new one but that
+ * will get killed on last close in xfs_close() so we don't
+@@ -2472,9 +2444,9 @@ xfs_remove(
+ std_return:
+ if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
+ (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
+- dir_vp, DM_RIGHT_NULL,
++ dp, DM_RIGHT_NULL,
+ NULL, DM_RIGHT_NULL,
+- name, NULL, dm_di_mode, error, 0);
++ name->name, NULL, ip->i_d.di_mode, error, 0);
+ }
+ return error;
+
+@@ -2495,14 +2467,6 @@ xfs_remove(
+ cancel_flags |= XFS_TRANS_ABORT;
+ xfs_trans_cancel(tp, cancel_flags);
+
+- /*
+- * Before we drop our extra reference to the inode, purge it
+- * from the refcache if it is there. By waiting until afterwards
+- * to do the IRELE, we ensure that we won't go inactive in the
+- * xfs_refcache_purge_ip routine (although that would be OK).
+- */
+- xfs_refcache_purge_ip(ip);
+-
+ IRELE(ip);
+
+ goto std_return;
+@@ -2511,12 +2475,10 @@ xfs_remove(
+ int
+ xfs_link(
+ xfs_inode_t *tdp,
+- bhv_vnode_t *src_vp,
+- bhv_vname_t *dentry)
++ xfs_inode_t *sip,
++ struct xfs_name *target_name)
+ {
+- bhv_vnode_t *target_dir_vp = XFS_ITOV(tdp);
+ xfs_mount_t *mp = tdp->i_mount;
+- xfs_inode_t *sip = xfs_vtoi(src_vp);
+ xfs_trans_t *tp;
+ xfs_inode_t *ips[2];
+ int error;
+@@ -2525,23 +2487,20 @@ xfs_link(
+ int cancel_flags;
+ int committed;
+ int resblks;
+- char *target_name = VNAME(dentry);
+- int target_namelen;
+
+ xfs_itrace_entry(tdp);
+- xfs_itrace_entry(xfs_vtoi(src_vp));
++ xfs_itrace_entry(sip);
+
+- target_namelen = VNAMELEN(dentry);
+- ASSERT(!VN_ISDIR(src_vp));
++ ASSERT(!S_ISDIR(sip->i_d.di_mode));
+
+ if (XFS_FORCED_SHUTDOWN(mp))
+ return XFS_ERROR(EIO);
+
+ if (DM_EVENT_ENABLED(tdp, DM_EVENT_LINK)) {
+ error = XFS_SEND_NAMESP(mp, DM_EVENT_LINK,
+- target_dir_vp, DM_RIGHT_NULL,
+- src_vp, DM_RIGHT_NULL,
+- target_name, NULL, 0, 0, 0);
++ tdp, DM_RIGHT_NULL,
++ sip, DM_RIGHT_NULL,
++ target_name->name, NULL, 0, 0, 0);
+ if (error)
+ return error;
+ }
+@@ -2556,7 +2515,7 @@ xfs_link(
+
+ tp = xfs_trans_alloc(mp, XFS_TRANS_LINK);
+ cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
+- resblks = XFS_LINK_SPACE_RES(mp, target_namelen);
++ resblks = XFS_LINK_SPACE_RES(mp, target_name->len);
+ error = xfs_trans_reserve(tp, resblks, XFS_LINK_LOG_RES(mp), 0,
+ XFS_TRANS_PERM_LOG_RES, XFS_LINK_LOG_COUNT);
+ if (error == ENOSPC) {
+@@ -2584,8 +2543,8 @@ xfs_link(
+ * xfs_trans_cancel will both unlock the inodes and
+ * decrement the associated ref counts.
+ */
+- VN_HOLD(src_vp);
+- VN_HOLD(target_dir_vp);
++ IHOLD(sip);
++ IHOLD(tdp);
+ xfs_trans_ijoin(tp, sip, XFS_ILOCK_EXCL);
+ xfs_trans_ijoin(tp, tdp, XFS_ILOCK_EXCL);
+
+@@ -2608,15 +2567,14 @@ xfs_link(
+ goto error_return;
+ }
+
+- if (resblks == 0 &&
+- (error = xfs_dir_canenter(tp, tdp, target_name, target_namelen)))
++ error = xfs_dir_canenter(tp, tdp, target_name, resblks);
++ if (error)
+ goto error_return;
+
+ XFS_BMAP_INIT(&free_list, &first_block);
+
+- error = xfs_dir_createname(tp, tdp, target_name, target_namelen,
+- sip->i_ino, &first_block, &free_list,
+- resblks);
++ error = xfs_dir_createname(tp, tdp, target_name, sip->i_ino,
++ &first_block, &free_list, resblks);
+ if (error)
+ goto abort_return;
+ xfs_ichgtime(tdp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+@@ -2650,9 +2608,9 @@ xfs_link(
+ std_return:
+ if (DM_EVENT_ENABLED(sip, DM_EVENT_POSTLINK)) {
+ (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTLINK,
+- target_dir_vp, DM_RIGHT_NULL,
+- src_vp, DM_RIGHT_NULL,
+- target_name, NULL, 0, error, 0);
++ tdp, DM_RIGHT_NULL,
++ sip, DM_RIGHT_NULL,
++ target_name->name, NULL, 0, error, 0);
+ }
+ return error;
+
+@@ -2669,17 +2627,13 @@ std_return:
+ int
+ xfs_mkdir(
+ xfs_inode_t *dp,
+- bhv_vname_t *dentry,
++ struct xfs_name *dir_name,
+ mode_t mode,
+- bhv_vnode_t **vpp,
++ xfs_inode_t **ipp,
+ cred_t *credp)
+ {
+- bhv_vnode_t *dir_vp = XFS_ITOV(dp);
+- char *dir_name = VNAME(dentry);
+- int dir_namelen = VNAMELEN(dentry);
+ xfs_mount_t *mp = dp->i_mount;
+ xfs_inode_t *cdp; /* inode of created dir */
+- bhv_vnode_t *cvp; /* vnode of created dir */
+ xfs_trans_t *tp;
+ int cancel_flags;
+ int error;
+@@ -2700,8 +2654,8 @@ xfs_mkdir(
+
+ if (DM_EVENT_ENABLED(dp, DM_EVENT_CREATE)) {
+ error = XFS_SEND_NAMESP(mp, DM_EVENT_CREATE,
+- dir_vp, DM_RIGHT_NULL, NULL,
+- DM_RIGHT_NULL, dir_name, NULL,
++ dp, DM_RIGHT_NULL, NULL,
++ DM_RIGHT_NULL, dir_name->name, NULL,
+ mode, 0, 0);
+ if (error)
+ return error;
+@@ -2730,7 +2684,7 @@ xfs_mkdir(
+
+ tp = xfs_trans_alloc(mp, XFS_TRANS_MKDIR);
+ cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
+- resblks = XFS_MKDIR_SPACE_RES(mp, dir_namelen);
++ resblks = XFS_MKDIR_SPACE_RES(mp, dir_name->len);
+ error = xfs_trans_reserve(tp, resblks, XFS_MKDIR_LOG_RES(mp), 0,
+ XFS_TRANS_PERM_LOG_RES, XFS_MKDIR_LOG_COUNT);
+ if (error == ENOSPC) {
+@@ -2762,8 +2716,8 @@ xfs_mkdir(
+ if (error)
+ goto error_return;
+
+- if (resblks == 0 &&
+- (error = xfs_dir_canenter(tp, dp, dir_name, dir_namelen)))
++ error = xfs_dir_canenter(tp, dp, dir_name, resblks);
++ if (error)
+ goto error_return;
+ /*
+ * create the directory inode.
+@@ -2786,15 +2740,15 @@ xfs_mkdir(
+ * from here on will result in the transaction cancel
+ * unlocking dp so don't do it explicitly in the error path.
+ */
+- VN_HOLD(dir_vp);
++ IHOLD(dp);
+ xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
+ unlock_dp_on_error = B_FALSE;
+
+ XFS_BMAP_INIT(&free_list, &first_block);
+
+- error = xfs_dir_createname(tp, dp, dir_name, dir_namelen, cdp->i_ino,
+- &first_block, &free_list, resblks ?
+- resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
++ error = xfs_dir_createname(tp, dp, dir_name, cdp->i_ino,
++ &first_block, &free_list, resblks ?
++ resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
+ if (error) {
+ ASSERT(error != ENOSPC);
+ goto error1;
+@@ -2817,11 +2771,9 @@ xfs_mkdir(
+ if (error)
+ goto error2;
+
+- cvp = XFS_ITOV(cdp);
+-
+ created = B_TRUE;
+
+- *vpp = cvp;
++ *ipp = cdp;
+ IHOLD(cdp);
+
+ /*
+@@ -2858,10 +2810,10 @@ std_return:
+ if ((created || (error != 0 && dm_event_sent != 0)) &&
+ DM_EVENT_ENABLED(dp, DM_EVENT_POSTCREATE)) {
+ (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTCREATE,
+- dir_vp, DM_RIGHT_NULL,
+- created ? XFS_ITOV(cdp):NULL,
++ dp, DM_RIGHT_NULL,
++ created ? cdp : NULL,
+ DM_RIGHT_NULL,
+- dir_name, NULL,
++ dir_name->name, NULL,
+ mode, error, 0);
+ }
+ return error;
+@@ -2885,20 +2837,17 @@ std_return:
+ int
+ xfs_rmdir(
+ xfs_inode_t *dp,
+- bhv_vname_t *dentry)
++ struct xfs_name *name,
++ xfs_inode_t *cdp)
+ {
+ bhv_vnode_t *dir_vp = XFS_ITOV(dp);
+- char *name = VNAME(dentry);
+- int namelen = VNAMELEN(dentry);
+ xfs_mount_t *mp = dp->i_mount;
+- xfs_inode_t *cdp; /* child directory */
+ xfs_trans_t *tp;
+ int error;
+ xfs_bmap_free_t free_list;
+ xfs_fsblock_t first_block;
+ int cancel_flags;
+ int committed;
+- int dm_di_mode = S_IFDIR;
+ int last_cdp_link;
+ uint resblks;
+
+@@ -2907,24 +2856,15 @@ xfs_rmdir(
+ if (XFS_FORCED_SHUTDOWN(mp))
+ return XFS_ERROR(EIO);
+
+- if (!xfs_get_dir_entry(dentry, &cdp)) {
+- dm_di_mode = cdp->i_d.di_mode;
+- IRELE(cdp);
+- }
+-
+ if (DM_EVENT_ENABLED(dp, DM_EVENT_REMOVE)) {
+ error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE,
+- dir_vp, DM_RIGHT_NULL,
+- NULL, DM_RIGHT_NULL,
+- name, NULL, dm_di_mode, 0, 0);
++ dp, DM_RIGHT_NULL,
++ NULL, DM_RIGHT_NULL, name->name,
++ NULL, cdp->i_d.di_mode, 0, 0);
+ if (error)
+ return XFS_ERROR(error);
+ }
+
+- /* Return through std_return after this point. */
+-
+- cdp = NULL;
+-
+ /*
+ * We need to get a reference to cdp before we get our log
+ * reservation. The reason for this is that we cannot call
+@@ -2937,13 +2877,7 @@ xfs_rmdir(
+ * when we call xfs_iget. Instead we get an unlocked reference
+ * to the inode before getting our log reservation.
+ */
+- error = xfs_get_dir_entry(dentry, &cdp);
+- if (error) {
+- REMOVE_DEBUG_TRACE(__LINE__);
+- goto std_return;
+- }
+- mp = dp->i_mount;
+- dm_di_mode = cdp->i_d.di_mode;
++ IHOLD(cdp);
+
+ /*
+ * Get the dquots for the inodes.
+@@ -3020,7 +2954,7 @@ xfs_rmdir(
+ goto error_return;
+ }
+
+- error = xfs_dir_removename(tp, dp, name, namelen, cdp->i_ino,
++ error = xfs_dir_removename(tp, dp, name, cdp->i_ino,
+ &first_block, &free_list, resblks);
+ if (error)
+ goto error1;
+@@ -3098,9 +3032,9 @@ xfs_rmdir(
+ std_return:
+ if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) {
+ (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
+- dir_vp, DM_RIGHT_NULL,
++ dp, DM_RIGHT_NULL,
+ NULL, DM_RIGHT_NULL,
+- name, NULL, dm_di_mode,
++ name->name, NULL, cdp->i_d.di_mode,
+ error, 0);
+ }
+ return error;
+@@ -3118,13 +3052,12 @@ xfs_rmdir(
+ int
+ xfs_symlink(
+ xfs_inode_t *dp,
+- bhv_vname_t *dentry,
+- char *target_path,
++ struct xfs_name *link_name,
++ const char *target_path,
+ mode_t mode,
+- bhv_vnode_t **vpp,
++ xfs_inode_t **ipp,
+ cred_t *credp)
+ {
+- bhv_vnode_t *dir_vp = XFS_ITOV(dp);
+ xfs_mount_t *mp = dp->i_mount;
+ xfs_trans_t *tp;
+ xfs_inode_t *ip;
+@@ -3140,17 +3073,15 @@ xfs_symlink(
+ int nmaps;
+ xfs_bmbt_irec_t mval[SYMLINK_MAPS];
+ xfs_daddr_t d;
+- char *cur_chunk;
++ const char *cur_chunk;
+ int byte_cnt;
+ int n;
+ xfs_buf_t *bp;
+ xfs_prid_t prid;
+ struct xfs_dquot *udqp, *gdqp;
+ uint resblks;
+- char *link_name = VNAME(dentry);
+- int link_namelen;
+
+- *vpp = NULL;
++ *ipp = NULL;
+ error = 0;
+ ip = NULL;
+ tp = NULL;
+@@ -3160,44 +3091,17 @@ xfs_symlink(
+ if (XFS_FORCED_SHUTDOWN(mp))
+ return XFS_ERROR(EIO);
+
+- link_namelen = VNAMELEN(dentry);
+-
+ /*
+ * Check component lengths of the target path name.
+ */
+ pathlen = strlen(target_path);
+ if (pathlen >= MAXPATHLEN) /* total string too long */
+ return XFS_ERROR(ENAMETOOLONG);
+- if (pathlen >= MAXNAMELEN) { /* is any component too long? */
+- int len, total;
+- char *path;
+-
+- for (total = 0, path = target_path; total < pathlen;) {
+- /*
+- * Skip any slashes.
+- */
+- while(*path == '/') {
+- total++;
+- path++;
+- }
+-
+- /*
+- * Count up to the next slash or end of path.
+- * Error out if the component is bigger than MAXNAMELEN.
+- */
+- for(len = 0; *path != '/' && total < pathlen;total++, path++) {
+- if (++len >= MAXNAMELEN) {
+- error = ENAMETOOLONG;
+- return error;
+- }
+- }
+- }
+- }
+
+ if (DM_EVENT_ENABLED(dp, DM_EVENT_SYMLINK)) {
+- error = XFS_SEND_NAMESP(mp, DM_EVENT_SYMLINK, dir_vp,
++ error = XFS_SEND_NAMESP(mp, DM_EVENT_SYMLINK, dp,
+ DM_RIGHT_NULL, NULL, DM_RIGHT_NULL,
+- link_name, target_path, 0, 0, 0);
++ link_name->name, target_path, 0, 0, 0);
+ if (error)
+ return error;
+ }
+@@ -3229,7 +3133,7 @@ xfs_symlink(
+ fs_blocks = 0;
+ else
+ fs_blocks = XFS_B_TO_FSB(mp, pathlen);
+- resblks = XFS_SYMLINK_SPACE_RES(mp, link_namelen, fs_blocks);
++ resblks = XFS_SYMLINK_SPACE_RES(mp, link_name->len, fs_blocks);
+ error = xfs_trans_reserve(tp, resblks, XFS_SYMLINK_LOG_RES(mp), 0,
+ XFS_TRANS_PERM_LOG_RES, XFS_SYMLINK_LOG_COUNT);
+ if (error == ENOSPC && fs_blocks == 0) {
+@@ -3263,8 +3167,8 @@ xfs_symlink(
+ /*
+ * Check for ability to enter directory entry, if no space reserved.
+ */
+- if (resblks == 0 &&
+- (error = xfs_dir_canenter(tp, dp, link_name, link_namelen)))
++ error = xfs_dir_canenter(tp, dp, link_name, resblks);
++ if (error)
+ goto error_return;
+ /*
+ * Initialize the bmap freelist prior to calling either
+@@ -3289,7 +3193,7 @@ xfs_symlink(
+ * transaction cancel unlocking dp so don't do it explicitly in the
+ * error path.
+ */
+- VN_HOLD(dir_vp);
++ IHOLD(dp);
+ xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
+ unlock_dp_on_error = B_FALSE;
+
+@@ -3356,8 +3260,8 @@ xfs_symlink(
+ /*
+ * Create the directory entry for the symlink.
+ */
+- error = xfs_dir_createname(tp, dp, link_name, link_namelen, ip->i_ino,
+- &first_block, &free_list, resblks);
++ error = xfs_dir_createname(tp, dp, link_name, ip->i_ino,
++ &first_block, &free_list, resblks);
+ if (error)
+ goto error1;
+ xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+@@ -3399,19 +3303,14 @@ xfs_symlink(
+ std_return:
+ if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTSYMLINK)) {
+ (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTSYMLINK,
+- dir_vp, DM_RIGHT_NULL,
+- error ? NULL : XFS_ITOV(ip),
+- DM_RIGHT_NULL, link_name, target_path,
+- 0, error, 0);
++ dp, DM_RIGHT_NULL,
++ error ? NULL : ip,
++ DM_RIGHT_NULL, link_name->name,
++ target_path, 0, error, 0);
+ }
+
+- if (!error) {
+- bhv_vnode_t *vp;
+-
+- ASSERT(ip);
+- vp = XFS_ITOV(ip);
+- *vpp = vp;
+- }
++ if (!error)
++ *ipp = ip;
+ return error;
+
+ error2:
+@@ -3431,60 +3330,11 @@ std_return:
+ }
+
+ int
+-xfs_rwlock(
+- xfs_inode_t *ip,
+- bhv_vrwlock_t locktype)
+-{
+- if (S_ISDIR(ip->i_d.di_mode))
+- return 1;
+- if (locktype == VRWLOCK_WRITE) {
+- xfs_ilock(ip, XFS_IOLOCK_EXCL);
+- } else if (locktype == VRWLOCK_TRY_READ) {
+- return xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED);
+- } else if (locktype == VRWLOCK_TRY_WRITE) {
+- return xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL);
+- } else {
+- ASSERT((locktype == VRWLOCK_READ) ||
+- (locktype == VRWLOCK_WRITE_DIRECT));
+- xfs_ilock(ip, XFS_IOLOCK_SHARED);
+- }
+-
+- return 1;
+-}
+-
+-
+-void
+-xfs_rwunlock(
+- xfs_inode_t *ip,
+- bhv_vrwlock_t locktype)
+-{
+- if (S_ISDIR(ip->i_d.di_mode))
+- return;
+- if (locktype == VRWLOCK_WRITE) {
+- /*
+- * In the write case, we may have added a new entry to
+- * the reference cache. This might store a pointer to
+- * an inode to be released in this inode. If it is there,
+- * clear the pointer and release the inode after unlocking
+- * this one.
+- */
+- xfs_refcache_iunlock(ip, XFS_IOLOCK_EXCL);
+- } else {
+- ASSERT((locktype == VRWLOCK_READ) ||
+- (locktype == VRWLOCK_WRITE_DIRECT));
+- xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+- }
+- return;
+-}
+-
+-
+-int
+ xfs_inode_flush(
+ xfs_inode_t *ip,
+ int flags)
+ {
+ xfs_mount_t *mp = ip->i_mount;
+- xfs_inode_log_item_t *iip = ip->i_itemp;
+ int error = 0;
+
+ if (XFS_FORCED_SHUTDOWN(mp))
+@@ -3494,33 +3344,9 @@ xfs_inode_flush(
+ * Bypass inodes which have already been cleaned by
+ * the inode flush clustering code inside xfs_iflush
+ */
+- if ((ip->i_update_core == 0) &&
+- ((iip == NULL) || !(iip->ili_format.ilf_fields & XFS_ILOG_ALL)))
++ if (xfs_inode_clean(ip))
+ return 0;
+
+- if (flags & FLUSH_LOG) {
+- if (iip && iip->ili_last_lsn) {
+- xlog_t *log = mp->m_log;
+- xfs_lsn_t sync_lsn;
+- int log_flags = XFS_LOG_FORCE;
+-
+- spin_lock(&log->l_grant_lock);
+- sync_lsn = log->l_last_sync_lsn;
+- spin_unlock(&log->l_grant_lock);
+-
+- if ((XFS_LSN_CMP(iip->ili_last_lsn, sync_lsn) > 0)) {
+- if (flags & FLUSH_SYNC)
+- log_flags |= XFS_LOG_SYNC;
+- error = xfs_log_force(mp, iip->ili_last_lsn, log_flags);
+- if (error)
+- return error;
+- }
+-
+- if (ip->i_update_core == 0)
+- return 0;
+- }
+- }
+-
+ /*
+ * We make this non-blocking if the inode is contended,
+ * return EAGAIN to indicate to the caller that they
+@@ -3528,30 +3354,22 @@ xfs_inode_flush(
+ * blocking on inodes inside another operation right
+ * now, they get caught later by xfs_sync.
+ */
+- if (flags & FLUSH_INODE) {
+- int flush_flags;
+-
+- if (flags & FLUSH_SYNC) {
+- xfs_ilock(ip, XFS_ILOCK_SHARED);
+- xfs_iflock(ip);
+- } else if (xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) {
+- if (xfs_ipincount(ip) || !xfs_iflock_nowait(ip)) {
+- xfs_iunlock(ip, XFS_ILOCK_SHARED);
+- return EAGAIN;
+- }
+- } else {
++ if (flags & FLUSH_SYNC) {
++ xfs_ilock(ip, XFS_ILOCK_SHARED);
++ xfs_iflock(ip);
++ } else if (xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) {
++ if (xfs_ipincount(ip) || !xfs_iflock_nowait(ip)) {
++ xfs_iunlock(ip, XFS_ILOCK_SHARED);
+ return EAGAIN;
+ }
+-
+- if (flags & FLUSH_SYNC)
+- flush_flags = XFS_IFLUSH_SYNC;
+- else
+- flush_flags = XFS_IFLUSH_ASYNC;
+-
+- error = xfs_iflush(ip, flush_flags);
+- xfs_iunlock(ip, XFS_ILOCK_SHARED);
++ } else {
++ return EAGAIN;
+ }
+
++ error = xfs_iflush(ip, (flags & FLUSH_SYNC) ? XFS_IFLUSH_SYNC
++ : XFS_IFLUSH_ASYNC_NOBLOCK);
++ xfs_iunlock(ip, XFS_ILOCK_SHARED);
++
+ return error;
+ }
+
+@@ -3694,12 +3512,12 @@ xfs_finish_reclaim(
+ * We get the flush lock regardless, though, just to make sure
+ * we don't free it while it is being flushed.
+ */
+- if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
+- if (!locked) {
+- xfs_ilock(ip, XFS_ILOCK_EXCL);
+- xfs_iflock(ip);
+- }
++ if (!locked) {
++ xfs_ilock(ip, XFS_ILOCK_EXCL);
++ xfs_iflock(ip);
++ }
+
++ if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
+ if (ip->i_update_core ||
+ ((ip->i_itemp != NULL) &&
+ (ip->i_itemp->ili_format.ilf_fields != 0))) {
+@@ -3719,17 +3537,11 @@ xfs_finish_reclaim(
+ ASSERT(ip->i_update_core == 0);
+ ASSERT(ip->i_itemp == NULL ||
+ ip->i_itemp->ili_format.ilf_fields == 0);
+- xfs_iunlock(ip, XFS_ILOCK_EXCL);
+- } else if (locked) {
+- /*
+- * We are not interested in doing an iflush if we're
+- * in the process of shutting down the filesystem forcibly.
+- * So, just reclaim the inode.
+- */
+- xfs_ifunlock(ip);
+- xfs_iunlock(ip, XFS_ILOCK_EXCL);
+ }
+
++ xfs_ifunlock(ip);
++ xfs_iunlock(ip, XFS_ILOCK_EXCL);
++
+ reclaim:
+ xfs_ireclaim(ip);
+ return 0;
+@@ -3845,9 +3657,8 @@ xfs_alloc_file_space(
+ end_dmi_offset = offset+len;
+ if (end_dmi_offset > ip->i_size)
+ end_dmi_offset = ip->i_size;
+- error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, XFS_ITOV(ip),
+- offset, end_dmi_offset - offset,
+- 0, NULL);
++ error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, ip, offset,
++ end_dmi_offset - offset, 0, NULL);
+ if (error)
+ return error;
+ }
+@@ -3956,8 +3767,8 @@ dmapi_enospc_check:
+ if (error == ENOSPC && (attr_flags & ATTR_DMI) == 0 &&
+ DM_EVENT_ENABLED(ip, DM_EVENT_NOSPACE)) {
+ error = XFS_SEND_NAMESP(mp, DM_EVENT_NOSPACE,
+- XFS_ITOV(ip), DM_RIGHT_NULL,
+- XFS_ITOV(ip), DM_RIGHT_NULL,
++ ip, DM_RIGHT_NULL,
++ ip, DM_RIGHT_NULL,
+ NULL, NULL, 0, 0, 0); /* Delay flag intentionally unused */
+ if (error == 0)
+ goto retry; /* Maybe DMAPI app. has made space */
+@@ -4021,7 +3832,8 @@ xfs_zero_remaining_bytes(
+ XFS_BUF_READ(bp);
+ XFS_BUF_SET_ADDR(bp, XFS_FSB_TO_DB(ip, imap.br_startblock));
+ xfsbdstrat(mp, bp);
+- if ((error = xfs_iowait(bp))) {
++ error = xfs_iowait(bp);
++ if (error) {
+ xfs_ioerror_alert("xfs_zero_remaining_bytes(read)",
+ mp, bp, XFS_BUF_ADDR(bp));
+ break;
+@@ -4033,7 +3845,8 @@ xfs_zero_remaining_bytes(
+ XFS_BUF_UNREAD(bp);
+ XFS_BUF_WRITE(bp);
+ xfsbdstrat(mp, bp);
+- if ((error = xfs_iowait(bp))) {
++ error = xfs_iowait(bp);
++ if (error) {
+ xfs_ioerror_alert("xfs_zero_remaining_bytes(write)",
+ mp, bp, XFS_BUF_ADDR(bp));
+ break;
+@@ -4102,7 +3915,7 @@ xfs_free_file_space(
+ DM_EVENT_ENABLED(ip, DM_EVENT_WRITE)) {
+ if (end_dmi_offset > ip->i_size)
+ end_dmi_offset = ip->i_size;
+- error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, vp,
++ error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, ip,
+ offset, end_dmi_offset - offset,
+ AT_DELAY_FLAG(attr_flags), NULL);
+ if (error)
+diff --git a/fs/xfs/xfs_vnodeops.h b/fs/xfs/xfs_vnodeops.h
+index 4e3970f..24c5392 100644
+--- a/fs/xfs/xfs_vnodeops.h
++++ b/fs/xfs/xfs_vnodeops.h
+@@ -23,31 +23,32 @@ int xfs_fsync(struct xfs_inode *ip, int flag, xfs_off_t start,
+ xfs_off_t stop);
+ int xfs_release(struct xfs_inode *ip);
+ int xfs_inactive(struct xfs_inode *ip);
+-int xfs_lookup(struct xfs_inode *dp, bhv_vname_t *dentry,
+- bhv_vnode_t **vpp);
+-int xfs_create(struct xfs_inode *dp, bhv_vname_t *dentry, mode_t mode,
+- xfs_dev_t rdev, bhv_vnode_t **vpp, struct cred *credp);
+-int xfs_remove(struct xfs_inode *dp, bhv_vname_t *dentry);
+-int xfs_link(struct xfs_inode *tdp, bhv_vnode_t *src_vp,
+- bhv_vname_t *dentry);
+-int xfs_mkdir(struct xfs_inode *dp, bhv_vname_t *dentry,
+- mode_t mode, bhv_vnode_t **vpp, struct cred *credp);
+-int xfs_rmdir(struct xfs_inode *dp, bhv_vname_t *dentry);
++int xfs_lookup(struct xfs_inode *dp, struct xfs_name *name,
++ struct xfs_inode **ipp);
++int xfs_create(struct xfs_inode *dp, struct xfs_name *name, mode_t mode,
++ xfs_dev_t rdev, struct xfs_inode **ipp, struct cred *credp);
++int xfs_remove(struct xfs_inode *dp, struct xfs_name *name,
++ struct xfs_inode *ip);
++int xfs_link(struct xfs_inode *tdp, struct xfs_inode *sip,
++ struct xfs_name *target_name);
++int xfs_mkdir(struct xfs_inode *dp, struct xfs_name *dir_name,
++ mode_t mode, struct xfs_inode **ipp, struct cred *credp);
++int xfs_rmdir(struct xfs_inode *dp, struct xfs_name *name,
++ struct xfs_inode *cdp);
+ int xfs_readdir(struct xfs_inode *dp, void *dirent, size_t bufsize,
+ xfs_off_t *offset, filldir_t filldir);
+-int xfs_symlink(struct xfs_inode *dp, bhv_vname_t *dentry,
+- char *target_path, mode_t mode, bhv_vnode_t **vpp,
++int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name,
++ const char *target_path, mode_t mode, struct xfs_inode **ipp,
+ struct cred *credp);
+-int xfs_rwlock(struct xfs_inode *ip, bhv_vrwlock_t locktype);
+-void xfs_rwunlock(struct xfs_inode *ip, bhv_vrwlock_t locktype);
+ int xfs_inode_flush(struct xfs_inode *ip, int flags);
+ int xfs_set_dmattrs(struct xfs_inode *ip, u_int evmask, u_int16_t state);
+ int xfs_reclaim(struct xfs_inode *ip);
+ int xfs_change_file_space(struct xfs_inode *ip, int cmd,
+ xfs_flock64_t *bf, xfs_off_t offset,
+ struct cred *credp, int attr_flags);
+-int xfs_rename(struct xfs_inode *src_dp, bhv_vname_t *src_vname,
+- bhv_vnode_t *target_dir_vp, bhv_vname_t *target_vname);
++int xfs_rename(struct xfs_inode *src_dp, struct xfs_name *src_name,
++ struct xfs_inode *src_ip, struct xfs_inode *target_dp,
++ struct xfs_name *target_name);
+ int xfs_attr_get(struct xfs_inode *ip, const char *name, char *value,
+ int *valuelenp, int flags, cred_t *cred);
+ int xfs_attr_set(struct xfs_inode *dp, const char *name, char *value,
+diff --git a/include/asm-alpha/ide.h b/include/asm-alpha/ide.h
+index b7bf68d..f44129a 100644
+--- a/include/asm-alpha/ide.h
++++ b/include/asm-alpha/ide.h
+@@ -13,9 +13,6 @@
+
+ #ifdef __KERNEL__
+
+-
+-#define IDE_ARCH_OBSOLETE_DEFAULTS
+-
+ static inline int ide_default_irq(unsigned long base)
+ {
+ switch (base) {
+@@ -40,14 +37,6 @@ static inline unsigned long ide_default_io_base(int index)
+ }
+ }
+
+-#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */
+-
+-#ifdef CONFIG_PCI
+-#define ide_init_default_irq(base) (0)
+-#else
+-#define ide_init_default_irq(base) ide_default_irq(base)
+-#endif
+-
+ #include <asm-generic/ide_iops.h>
+
+ #endif /* __KERNEL__ */
+diff --git a/include/asm-alpha/semaphore.h b/include/asm-alpha/semaphore.h
+index f1e9278..d9b2034 100644
+--- a/include/asm-alpha/semaphore.h
++++ b/include/asm-alpha/semaphore.h
+@@ -1,149 +1 @@
+-#ifndef _ALPHA_SEMAPHORE_H
+-#define _ALPHA_SEMAPHORE_H
+-
+-/*
+- * SMP- and interrupt-safe semaphores..
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- * (C) Copyright 1996, 2000 Richard Henderson
+- */
+-
+-#include <asm/current.h>
+-#include <asm/system.h>
+-#include <asm/atomic.h>
+-#include <linux/compiler.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-struct semaphore {
+- atomic_t count;
+- wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n) \
+-{ \
+- .count = ATOMIC_INIT(n), \
+- .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+- struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init(struct semaphore *sem, int val)
+-{
+- /*
+- * Logically,
+- * *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+- * except that gcc produces better initializing by parts yet.
+- */
+-
+- atomic_set(&sem->count, val);
+- init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+- sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+- sema_init(sem, 0);
+-}
+-
+-extern void down(struct semaphore *);
+-extern void __down_failed(struct semaphore *);
+-extern int down_interruptible(struct semaphore *);
+-extern int __down_failed_interruptible(struct semaphore *);
+-extern int down_trylock(struct semaphore *);
+-extern void up(struct semaphore *);
+-extern void __up_wakeup(struct semaphore *);
+-
+-/*
+- * Hidden out of line code is fun, but extremely messy. Rely on newer
+- * compilers to do a respectable job with this. The contention cases
+- * are handled out of line in arch/alpha/kernel/semaphore.c.
+- */
+-
+-static inline void __down(struct semaphore *sem)
+-{
+- long count;
+- might_sleep();
+- count = atomic_dec_return(&sem->count);
+- if (unlikely(count < 0))
+- __down_failed(sem);
+-}
+-
+-static inline int __down_interruptible(struct semaphore *sem)
+-{
+- long count;
+- might_sleep();
+- count = atomic_dec_return(&sem->count);
+- if (unlikely(count < 0))
+- return __down_failed_interruptible(sem);
+- return 0;
+-}
+-
+-/*
+- * down_trylock returns 0 on success, 1 if we failed to get the lock.
+- */
+-
+-static inline int __down_trylock(struct semaphore *sem)
+-{
+- long ret;
+-
+- /* "Equivalent" C:
+-
+- do {
+- ret = ldl_l;
+- --ret;
+- if (ret < 0)
+- break;
+- ret = stl_c = ret;
+- } while (ret == 0);
+- */
+- __asm__ __volatile__(
+- "1: ldl_l %0,%1\n"
+- " subl %0,1,%0\n"
+- " blt %0,2f\n"
+- " stl_c %0,%1\n"
+- " beq %0,3f\n"
+- " mb\n"
+- "2:\n"
+- ".subsection 2\n"
+- "3: br 1b\n"
+- ".previous"
+- : "=&r" (ret), "=m" (sem->count)
+- : "m" (sem->count));
+-
+- return ret < 0;
+-}
+-
+-static inline void __up(struct semaphore *sem)
+-{
+- if (unlikely(atomic_inc_return(&sem->count) <= 0))
+- __up_wakeup(sem);
+-}
+-
+-#if !defined(CONFIG_DEBUG_SEMAPHORE)
+-extern inline void down(struct semaphore *sem)
+-{
+- __down(sem);
+-}
+-extern inline int down_interruptible(struct semaphore *sem)
+-{
+- return __down_interruptible(sem);
+-}
+-extern inline int down_trylock(struct semaphore *sem)
+-{
+- return __down_trylock(sem);
+-}
+-extern inline void up(struct semaphore *sem)
+-{
+- __up(sem);
+-}
+-#endif
+-
+-#endif
++#include <linux/semaphore.h>
+diff --git a/include/asm-alpha/topology.h b/include/asm-alpha/topology.h
+index 420ccde..149532e 100644
+--- a/include/asm-alpha/topology.h
++++ b/include/asm-alpha/topology.h
+@@ -41,8 +41,7 @@ static inline cpumask_t node_to_cpumask(int node)
+
+ #define pcibus_to_cpumask(bus) (cpu_online_map)
+
+-#else /* CONFIG_NUMA */
+-# include <asm-generic/topology.h>
+ #endif /* !CONFIG_NUMA */
++# include <asm-generic/topology.h>
+
+ #endif /* _ASM_ALPHA_TOPOLOGY_H */
+diff --git a/include/asm-arm/arch-at91/at91_ecc.h b/include/asm-arm/arch-at91/at91_ecc.h
+index ff93df5..1e5a8ca 100644
+--- a/include/asm-arm/arch-at91/at91_ecc.h
++++ b/include/asm-arm/arch-at91/at91_ecc.h
+@@ -13,26 +13,26 @@
+ #ifndef AT91_ECC_H
+ #define AT91_ECC_H
+
+-#define AT91_ECC_CR (AT91_ECC + 0x00) /* Control register */
++#define AT91_ECC_CR 0x00 /* Control register */
+ #define AT91_ECC_RST (1 << 0) /* Reset parity */
+
+-#define AT91_ECC_MR (AT91_ECC + 0x04) /* Mode register */
++#define AT91_ECC_MR 0x04 /* Mode register */
+ #define AT91_ECC_PAGESIZE (3 << 0) /* Page Size */
+ #define AT91_ECC_PAGESIZE_528 (0)
+ #define AT91_ECC_PAGESIZE_1056 (1)
+ #define AT91_ECC_PAGESIZE_2112 (2)
+ #define AT91_ECC_PAGESIZE_4224 (3)
+
+-#define AT91_ECC_SR (AT91_ECC + 0x08) /* Status register */
++#define AT91_ECC_SR 0x08 /* Status register */
+ #define AT91_ECC_RECERR (1 << 0) /* Recoverable Error */
+ #define AT91_ECC_ECCERR (1 << 1) /* ECC Single Bit Error */
+ #define AT91_ECC_MULERR (1 << 2) /* Multiple Errors */
+
+-#define AT91_ECC_PR (AT91_ECC + 0x0c) /* Parity register */
++#define AT91_ECC_PR 0x0c /* Parity register */
+ #define AT91_ECC_BITADDR (0xf << 0) /* Bit Error Address */
+ #define AT91_ECC_WORDADDR (0xfff << 4) /* Word Error Address */
+
+-#define AT91_ECC_NPR (AT91_ECC + 0x10) /* NParity register */
++#define AT91_ECC_NPR 0x10 /* NParity register */
+ #define AT91_ECC_NPARITY (0xffff << 0) /* NParity */
+
+ #endif
+diff --git a/include/asm-arm/arch-at91/at91_pmc.h b/include/asm-arm/arch-at91/at91_pmc.h
+index 52cd8e5..c2b13c2 100644
+--- a/include/asm-arm/arch-at91/at91_pmc.h
++++ b/include/asm-arm/arch-at91/at91_pmc.h
+@@ -76,10 +76,17 @@
+ #define AT91_PMC_PRES_32 (5 << 2)
+ #define AT91_PMC_PRES_64 (6 << 2)
+ #define AT91_PMC_MDIV (3 << 8) /* Master Clock Division */
+-#define AT91_PMC_MDIV_1 (0 << 8)
+-#define AT91_PMC_MDIV_2 (1 << 8)
+-#define AT91_PMC_MDIV_3 (2 << 8)
+-#define AT91_PMC_MDIV_4 (3 << 8)
++#define AT91RM9200_PMC_MDIV_1 (0 << 8) /* [AT91RM9200 only] */
++#define AT91RM9200_PMC_MDIV_2 (1 << 8)
++#define AT91RM9200_PMC_MDIV_3 (2 << 8)
++#define AT91RM9200_PMC_MDIV_4 (3 << 8)
++#define AT91SAM9_PMC_MDIV_1 (0 << 8) /* [SAM9,CAP9 only] */
++#define AT91SAM9_PMC_MDIV_2 (1 << 8)
++#define AT91SAM9_PMC_MDIV_4 (2 << 8)
++#define AT91SAM9_PMC_MDIV_6 (3 << 8)
++#define AT91_PMC_PDIV (1 << 12) /* Processor Clock Division [some SAM9 only] */
++#define AT91_PMC_PDIV_1 (0 << 12)
++#define AT91_PMC_PDIV_2 (1 << 12)
+
+ #define AT91_PMC_PCKR(n) (AT91_PMC + 0x40 + ((n) * 4)) /* Programmable Clock 0-3 Registers */
+
+diff --git a/include/asm-arm/arch-at91/at91_shdwc.h b/include/asm-arm/arch-at91/at91_shdwc.h
+index 01b433d..581fa41 100644
+--- a/include/asm-arm/arch-at91/at91_shdwc.h
++++ b/include/asm-arm/arch-at91/at91_shdwc.h
+@@ -24,10 +24,12 @@
+ #define AT91_SHDW_WKMODE0_LOW 2
+ #define AT91_SHDW_WKMODE0_ANYLEVEL 3
+ #define AT91_SHDW_CPTWK0 (0xf << 4) /* Counter On Wake Up 0 */
++#define AT91_SHDW_CPTWK0_(x) ((x) << 4)
+ #define AT91_SHDW_RTTWKEN (1 << 16) /* Real Time Timer Wake-up Enable */
+
+ #define AT91_SHDW_SR (AT91_SHDWC + 0x08) /* Shut Down Status Register */
+ #define AT91_SHDW_WAKEUP0 (1 << 0) /* Wake-up 0 Status */
+ #define AT91_SHDW_RTTWK (1 << 16) /* Real-time Timer Wake-up */
++#define AT91_SHDW_RTCWK (1 << 17) /* Real-time Clock Wake-up [SAM9RL] */
+
+ #endif
+diff --git a/include/asm-arm/arch-at91/at91cap9_ddrsdr.h b/include/asm-arm/arch-at91/at91cap9_ddrsdr.h
+new file mode 100644
+index 0000000..efdb23a
+--- /dev/null
++++ b/include/asm-arm/arch-at91/at91cap9_ddrsdr.h
+@@ -0,0 +1,100 @@
++/*
++ * include/asm-arm/arch-at91/at91cap9_ddrsdr.h
++ *
++ * DDR/SDR Controller (DDRSDRC) - System peripherals registers.
++ * Based on AT91CAP9 datasheet revision B.
++ *
++ * 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 AT91CAP9_DDRSDR_H
++#define AT91CAP9_DDRSDR_H
++
++#define AT91_DDRSDRC_MR (AT91_DDRSDRC + 0x00) /* Mode Register */
++#define AT91_DDRSDRC_MODE (0xf << 0) /* Command Mode */
++#define AT91_DDRSDRC_MODE_NORMAL 0
++#define AT91_DDRSDRC_MODE_NOP 1
++#define AT91_DDRSDRC_MODE_PRECHARGE 2
++#define AT91_DDRSDRC_MODE_LMR 3
++#define AT91_DDRSDRC_MODE_REFRESH 4
++#define AT91_DDRSDRC_MODE_EXT_LMR 5
++#define AT91_DDRSDRC_MODE_DEEP 6
++
++#define AT91_DDRSDRC_RTR (AT91_DDRSDRC + 0x04) /* Refresh Timer Register */
++#define AT91_DDRSDRC_COUNT (0xfff << 0) /* Refresh Timer Counter */
++
++#define AT91_DDRSDRC_CR (AT91_DDRSDRC + 0x08) /* Configuration Register */
++#define AT91_DDRSDRC_NC (3 << 0) /* Number of Column Bits */
++#define AT91_DDRSDRC_NC_SDR8 (0 << 0)
++#define AT91_DDRSDRC_NC_SDR9 (1 << 0)
++#define AT91_DDRSDRC_NC_SDR10 (2 << 0)
++#define AT91_DDRSDRC_NC_SDR11 (3 << 0)
++#define AT91_DDRSDRC_NC_DDR9 (0 << 0)
++#define AT91_DDRSDRC_NC_DDR10 (1 << 0)
++#define AT91_DDRSDRC_NC_DDR11 (2 << 0)
++#define AT91_DDRSDRC_NC_DDR12 (3 << 0)
++#define AT91_DDRSDRC_NR (3 << 2) /* Number of Row Bits */
++#define AT91_DDRSDRC_NR_11 (0 << 2)
++#define AT91_DDRSDRC_NR_12 (1 << 2)
++#define AT91_DDRSDRC_NR_13 (2 << 2)
++#define AT91_DDRSDRC_CAS (7 << 4) /* CAS Latency */
++#define AT91_DDRSDRC_CAS_2 (2 << 4)
++#define AT91_DDRSDRC_CAS_3 (3 << 4)
++#define AT91_DDRSDRC_CAS_25 (6 << 4)
++#define AT91_DDRSDRC_DLL (1 << 7) /* Reset DLL */
++#define AT91_DDRSDRC_DICDS (1 << 8) /* Output impedance control */
++
++#define AT91_DDRSDRC_T0PR (AT91_DDRSDRC + 0x0C) /* Timing 0 Register */
++#define AT91_DDRSDRC_TRAS (0xf << 0) /* Active to Precharge delay */
++#define AT91_DDRSDRC_TRCD (0xf << 4) /* Row to Column delay */
++#define AT91_DDRSDRC_TWR (0xf << 8) /* Write recovery delay */
++#define AT91_DDRSDRC_TRC (0xf << 12) /* Row cycle delay */
++#define AT91_DDRSDRC_TRP (0xf << 16) /* Row precharge delay */
++#define AT91_DDRSDRC_TRRD (0xf << 20) /* Active BankA to BankB */
++#define AT91_DDRSDRC_TWTR (1 << 24) /* Internal Write to Read delay */
++#define AT91_DDRSDRC_TMRD (0xf << 28) /* Load mode to active/refresh delay */
++
++#define AT91_DDRSDRC_T1PR (AT91_DDRSDRC + 0x10) /* Timing 1 Register */
++#define AT91_DDRSDRC_TRFC (0x1f << 0) /* Row Cycle Delay */
++#define AT91_DDRSDRC_TXSNR (0xff << 8) /* Exit self-refresh to non-read */
++#define AT91_DDRSDRC_TXSRD (0xff << 16) /* Exit self-refresh to read */
++#define AT91_DDRSDRC_TXP (0xf << 24) /* Exit power-down delay */
++
++#define AT91_DDRSDRC_LPR (AT91_DDRSDRC + 0x18) /* Low Power Register */
++#define AT91_DDRSDRC_LPCB (3 << 0) /* Low-power Configurations */
++#define AT91_DDRSDRC_LPCB_DISABLE 0
++#define AT91_DDRSDRC_LPCB_SELF_REFRESH 1
++#define AT91_DDRSDRC_LPCB_POWER_DOWN 2
++#define AT91_DDRSDRC_LPCB_DEEP_POWER_DOWN 3
++#define AT91_DDRSDRC_CLKFR (1 << 2) /* Clock Frozen */
++#define AT91_DDRSDRC_PASR (7 << 4) /* Partial Array Self Refresh */
++#define AT91_DDRSDRC_TCSR (3 << 8) /* Temperature Compensated Self Refresh */
++#define AT91_DDRSDRC_DS (3 << 10) /* Drive Strength */
++#define AT91_DDRSDRC_TIMEOUT (3 << 12) /* Time to define when Low Power Mode is enabled */
++#define AT91_DDRSDRC_TIMEOUT_0_CLK_CYCLES (0 << 12)
++#define AT91_DDRSDRC_TIMEOUT_64_CLK_CYCLES (1 << 12)
++#define AT91_DDRSDRC_TIMEOUT_128_CLK_CYCLES (2 << 12)
++
++#define AT91_DDRSDRC_MDR (AT91_DDRSDRC + 0x1C) /* Memory Device Register */
++#define AT91_DDRSDRC_MD (3 << 0) /* Memory Device Type */
++#define AT91_DDRSDRC_MD_SDR 0
++#define AT91_DDRSDRC_MD_LOW_POWER_SDR 1
++#define AT91_DDRSDRC_MD_DDR 2
++#define AT91_DDRSDRC_MD_LOW_POWER_DDR 3
++
++#define AT91_DDRSDRC_DLLR (AT91_DDRSDRC + 0x20) /* DLL Information Register */
++#define AT91_DDRSDRC_MDINC (1 << 0) /* Master Delay increment */
++#define AT91_DDRSDRC_MDDEC (1 << 1) /* Master Delay decrement */
++#define AT91_DDRSDRC_MDOVF (1 << 2) /* Master Delay Overflow */
++#define AT91_DDRSDRC_SDCOVF (1 << 3) /* Slave Delay Correction Overflow */
++#define AT91_DDRSDRC_SDCUDF (1 << 4) /* Slave Delay Correction Underflow */
++#define AT91_DDRSDRC_SDERF (1 << 5) /* Slave Delay Correction error */
++#define AT91_DDRSDRC_MDVAL (0xff << 8) /* Master Delay value */
++#define AT91_DDRSDRC_SDVAL (0xff << 16) /* Slave Delay value */
++#define AT91_DDRSDRC_SDCVAL (0xff << 24) /* Slave Delay Correction value */
++
++
++#endif
+diff --git a/include/asm-arm/arch-at91/at91sam926x_mc.h b/include/asm-arm/arch-at91/at91sam926x_mc.h
+deleted file mode 100644
+index d82631c..0000000
+--- a/include/asm-arm/arch-at91/at91sam926x_mc.h
++++ /dev/null
+@@ -1,141 +0,0 @@
+-/*
+- * include/asm-arm/arch-at91/at91sam926x_mc.h
+- *
+- * Memory Controllers (SMC, SDRAMC) - System peripherals registers.
+- * Based on AT91SAM9261 datasheet revision D.
+- *
+- * 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 AT91SAM926x_MC_H
+-#define AT91SAM926x_MC_H
+-
+-/* SDRAM Controller (SDRAMC) registers */
+-#define AT91_SDRAMC_MR (AT91_SDRAMC + 0x00) /* SDRAM Controller Mode Register */
+-#define AT91_SDRAMC_MODE (0xf << 0) /* Command Mode */
+-#define AT91_SDRAMC_MODE_NORMAL 0
+-#define AT91_SDRAMC_MODE_NOP 1
+-#define AT91_SDRAMC_MODE_PRECHARGE 2
+-#define AT91_SDRAMC_MODE_LMR 3
+-#define AT91_SDRAMC_MODE_REFRESH 4
+-#define AT91_SDRAMC_MODE_EXT_LMR 5
+-#define AT91_SDRAMC_MODE_DEEP 6
+-
+-#define AT91_SDRAMC_TR (AT91_SDRAMC + 0x04) /* SDRAM Controller Refresh Timer Register */
+-#define AT91_SDRAMC_COUNT (0xfff << 0) /* Refresh Timer Counter */
+-
+-#define AT91_SDRAMC_CR (AT91_SDRAMC + 0x08) /* SDRAM Controller Configuration Register */
+-#define AT91_SDRAMC_NC (3 << 0) /* Number of Column Bits */
+-#define AT91_SDRAMC_NC_8 (0 << 0)
+-#define AT91_SDRAMC_NC_9 (1 << 0)
+-#define AT91_SDRAMC_NC_10 (2 << 0)
+-#define AT91_SDRAMC_NC_11 (3 << 0)
+-#define AT91_SDRAMC_NR (3 << 2) /* Number of Row Bits */
+-#define AT91_SDRAMC_NR_11 (0 << 2)
+-#define AT91_SDRAMC_NR_12 (1 << 2)
+-#define AT91_SDRAMC_NR_13 (2 << 2)
+-#define AT91_SDRAMC_NB (1 << 4) /* Number of Banks */
+-#define AT91_SDRAMC_NB_2 (0 << 4)
+-#define AT91_SDRAMC_NB_4 (1 << 4)
+-#define AT91_SDRAMC_CAS (3 << 5) /* CAS Latency */
+-#define AT91_SDRAMC_CAS_1 (1 << 5)
+-#define AT91_SDRAMC_CAS_2 (2 << 5)
+-#define AT91_SDRAMC_CAS_3 (3 << 5)
+-#define AT91_SDRAMC_DBW (1 << 7) /* Data Bus Width */
+-#define AT91_SDRAMC_DBW_32 (0 << 7)
+-#define AT91_SDRAMC_DBW_16 (1 << 7)
+-#define AT91_SDRAMC_TWR (0xf << 8) /* Write Recovery Delay */
+-#define AT91_SDRAMC_TRC (0xf << 12) /* Row Cycle Delay */
+-#define AT91_SDRAMC_TRP (0xf << 16) /* Row Precharge Delay */
+-#define AT91_SDRAMC_TRCD (0xf << 20) /* Row to Column Delay */
+-#define AT91_SDRAMC_TRAS (0xf << 24) /* Active to Precharge Delay */
+-#define AT91_SDRAMC_TXSR (0xf << 28) /* Exit Self Refresh to Active Delay */
+-
+-#define AT91_SDRAMC_LPR (AT91_SDRAMC + 0x10) /* SDRAM Controller Low Power Register */
+-#define AT91_SDRAMC_LPCB (3 << 0) /* Low-power Configurations */
+-#define AT91_SDRAMC_LPCB_DISABLE 0
+-#define AT91_SDRAMC_LPCB_SELF_REFRESH 1
+-#define AT91_SDRAMC_LPCB_POWER_DOWN 2
+-#define AT91_SDRAMC_LPCB_DEEP_POWER_DOWN 3
+-#define AT91_SDRAMC_PASR (7 << 4) /* Partial Array Self Refresh */
+-#define AT91_SDRAMC_TCSR (3 << 8) /* Temperature Compensated Self Refresh */
+-#define AT91_SDRAMC_DS (3 << 10) /* Drive Strenght */
+-#define AT91_SDRAMC_TIMEOUT (3 << 12) /* Time to define when Low Power Mode is enabled */
+-#define AT91_SDRAMC_TIMEOUT_0_CLK_CYCLES (0 << 12)
+-#define AT91_SDRAMC_TIMEOUT_64_CLK_CYCLES (1 << 12)
+-#define AT91_SDRAMC_TIMEOUT_128_CLK_CYCLES (2 << 12)
+-
+-#define AT91_SDRAMC_IER (AT91_SDRAMC + 0x14) /* SDRAM Controller Interrupt Enable Register */
+-#define AT91_SDRAMC_IDR (AT91_SDRAMC + 0x18) /* SDRAM Controller Interrupt Disable Register */
+-#define AT91_SDRAMC_IMR (AT91_SDRAMC + 0x1C) /* SDRAM Controller Interrupt Mask Register */
+-#define AT91_SDRAMC_ISR (AT91_SDRAMC + 0x20) /* SDRAM Controller Interrupt Status Register */
+-#define AT91_SDRAMC_RES (1 << 0) /* Refresh Error Status */
+-
+-#define AT91_SDRAMC_MDR (AT91_SDRAMC + 0x24) /* SDRAM Memory Device Register */
+-#define AT91_SDRAMC_MD (3 << 0) /* Memory Device Type */
+-#define AT91_SDRAMC_MD_SDRAM 0
+-#define AT91_SDRAMC_MD_LOW_POWER_SDRAM 1
+-
+-
+-/* Static Memory Controller (SMC) registers */
+-#define AT91_SMC_SETUP(n) (AT91_SMC + 0x00 + ((n)*0x10)) /* Setup Register for CS n */
+-#define AT91_SMC_NWESETUP (0x3f << 0) /* NWE Setup Length */
+-#define AT91_SMC_NWESETUP_(x) ((x) << 0)
+-#define AT91_SMC_NCS_WRSETUP (0x3f << 8) /* NCS Setup Length in Write Access */
+-#define AT91_SMC_NCS_WRSETUP_(x) ((x) << 8)
+-#define AT91_SMC_NRDSETUP (0x3f << 16) /* NRD Setup Length */
+-#define AT91_SMC_NRDSETUP_(x) ((x) << 16)
+-#define AT91_SMC_NCS_RDSETUP (0x3f << 24) /* NCS Setup Length in Read Access */
+-#define AT91_SMC_NCS_RDSETUP_(x) ((x) << 24)
+-
+-#define AT91_SMC_PULSE(n) (AT91_SMC + 0x04 + ((n)*0x10)) /* Pulse Register for CS n */
+-#define AT91_SMC_NWEPULSE (0x7f << 0) /* NWE Pulse Length */
+-#define AT91_SMC_NWEPULSE_(x) ((x) << 0)
+-#define AT91_SMC_NCS_WRPULSE (0x7f << 8) /* NCS Pulse Length in Write Access */
+-#define AT91_SMC_NCS_WRPULSE_(x)((x) << 8)
+-#define AT91_SMC_NRDPULSE (0x7f << 16) /* NRD Pulse Length */
+-#define AT91_SMC_NRDPULSE_(x) ((x) << 16)
+-#define AT91_SMC_NCS_RDPULSE (0x7f << 24) /* NCS Pulse Length in Read Access */
+-#define AT91_SMC_NCS_RDPULSE_(x)((x) << 24)
+-
+-#define AT91_SMC_CYCLE(n) (AT91_SMC + 0x08 + ((n)*0x10)) /* Cycle Register for CS n */
+-#define AT91_SMC_NWECYCLE (0x1ff << 0 ) /* Total Write Cycle Length */
+-#define AT91_SMC_NWECYCLE_(x) ((x) << 0)
+-#define AT91_SMC_NRDCYCLE (0x1ff << 16) /* Total Read Cycle Length */
+-#define AT91_SMC_NRDCYCLE_(x) ((x) << 16)
+-
+-#define AT91_SMC_MODE(n) (AT91_SMC + 0x0c + ((n)*0x10)) /* Mode Register for CS n */
+-#define AT91_SMC_READMODE (1 << 0) /* Read Mode */
+-#define AT91_SMC_WRITEMODE (1 << 1) /* Write Mode */
+-#define AT91_SMC_EXNWMODE (3 << 4) /* NWAIT Mode */
+-#define AT91_SMC_EXNWMODE_DISABLE (0 << 4)
+-#define AT91_SMC_EXNWMODE_FROZEN (2 << 4)
+-#define AT91_SMC_EXNWMODE_READY (3 << 4)
+-#define AT91_SMC_BAT (1 << 8) /* Byte Access Type */
+-#define AT91_SMC_BAT_SELECT (0 << 8)
+-#define AT91_SMC_BAT_WRITE (1 << 8)
+-#define AT91_SMC_DBW (3 << 12) /* Data Bus Width */
+-#define AT91_SMC_DBW_8 (0 << 12)
+-#define AT91_SMC_DBW_16 (1 << 12)
+-#define AT91_SMC_DBW_32 (2 << 12)
+-#define AT91_SMC_TDF (0xf << 16) /* Data Float Time. */
+-#define AT91_SMC_TDF_(x) ((x) << 16)
+-#define AT91_SMC_TDFMODE (1 << 20) /* TDF Optimization - Enabled */
+-#define AT91_SMC_PMEN (1 << 24) /* Page Mode Enabled */
+-#define AT91_SMC_PS (3 << 28) /* Page Size */
+-#define AT91_SMC_PS_4 (0 << 28)
+-#define AT91_SMC_PS_8 (1 << 28)
+-#define AT91_SMC_PS_16 (2 << 28)
+-#define AT91_SMC_PS_32 (3 << 28)
+-
+-#if defined(AT91_SMC1) /* The AT91SAM9263 has 2 Static Memory contollers */
+-#define AT91_SMC1_SETUP(n) (AT91_SMC1 + 0x00 + ((n)*0x10)) /* Setup Register for CS n */
+-#define AT91_SMC1_PULSE(n) (AT91_SMC1 + 0x04 + ((n)*0x10)) /* Pulse Register for CS n */
+-#define AT91_SMC1_CYCLE(n) (AT91_SMC1 + 0x08 + ((n)*0x10)) /* Cycle Register for CS n */
+-#define AT91_SMC1_MODE(n) (AT91_SMC1 + 0x0c + ((n)*0x10)) /* Mode Register for CS n */
+-#endif
+-
+-#endif
+diff --git a/include/asm-arm/arch-at91/at91sam9_sdramc.h b/include/asm-arm/arch-at91/at91sam9_sdramc.h
+new file mode 100644
+index 0000000..d3b8b3d
+--- /dev/null
++++ b/include/asm-arm/arch-at91/at91sam9_sdramc.h
+@@ -0,0 +1,83 @@
++/*
++ * include/asm-arm/arch-at91/at91sam9_sdramc.h
++ *
++ * SDRAM Controllers (SDRAMC) - System peripherals registers.
++ * Based on AT91SAM9261 datasheet revision D.
++ *
++ * 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 AT91SAM9_SDRAMC_H
++#define AT91SAM9_SDRAMC_H
++
++/* SDRAM Controller (SDRAMC) registers */
++#define AT91_SDRAMC_MR (AT91_SDRAMC + 0x00) /* SDRAM Controller Mode Register */
++#define AT91_SDRAMC_MODE (0xf << 0) /* Command Mode */
++#define AT91_SDRAMC_MODE_NORMAL 0
++#define AT91_SDRAMC_MODE_NOP 1
++#define AT91_SDRAMC_MODE_PRECHARGE 2
++#define AT91_SDRAMC_MODE_LMR 3
++#define AT91_SDRAMC_MODE_REFRESH 4
++#define AT91_SDRAMC_MODE_EXT_LMR 5
++#define AT91_SDRAMC_MODE_DEEP 6
++
++#define AT91_SDRAMC_TR (AT91_SDRAMC + 0x04) /* SDRAM Controller Refresh Timer Register */
++#define AT91_SDRAMC_COUNT (0xfff << 0) /* Refresh Timer Counter */
++
++#define AT91_SDRAMC_CR (AT91_SDRAMC + 0x08) /* SDRAM Controller Configuration Register */
++#define AT91_SDRAMC_NC (3 << 0) /* Number of Column Bits */
++#define AT91_SDRAMC_NC_8 (0 << 0)
++#define AT91_SDRAMC_NC_9 (1 << 0)
++#define AT91_SDRAMC_NC_10 (2 << 0)
++#define AT91_SDRAMC_NC_11 (3 << 0)
++#define AT91_SDRAMC_NR (3 << 2) /* Number of Row Bits */
++#define AT91_SDRAMC_NR_11 (0 << 2)
++#define AT91_SDRAMC_NR_12 (1 << 2)
++#define AT91_SDRAMC_NR_13 (2 << 2)
++#define AT91_SDRAMC_NB (1 << 4) /* Number of Banks */
++#define AT91_SDRAMC_NB_2 (0 << 4)
++#define AT91_SDRAMC_NB_4 (1 << 4)
++#define AT91_SDRAMC_CAS (3 << 5) /* CAS Latency */
++#define AT91_SDRAMC_CAS_1 (1 << 5)
++#define AT91_SDRAMC_CAS_2 (2 << 5)
++#define AT91_SDRAMC_CAS_3 (3 << 5)
++#define AT91_SDRAMC_DBW (1 << 7) /* Data Bus Width */
++#define AT91_SDRAMC_DBW_32 (0 << 7)
++#define AT91_SDRAMC_DBW_16 (1 << 7)
++#define AT91_SDRAMC_TWR (0xf << 8) /* Write Recovery Delay */
++#define AT91_SDRAMC_TRC (0xf << 12) /* Row Cycle Delay */
++#define AT91_SDRAMC_TRP (0xf << 16) /* Row Precharge Delay */
++#define AT91_SDRAMC_TRCD (0xf << 20) /* Row to Column Delay */
++#define AT91_SDRAMC_TRAS (0xf << 24) /* Active to Precharge Delay */
++#define AT91_SDRAMC_TXSR (0xf << 28) /* Exit Self Refresh to Active Delay */
++
++#define AT91_SDRAMC_LPR (AT91_SDRAMC + 0x10) /* SDRAM Controller Low Power Register */
++#define AT91_SDRAMC_LPCB (3 << 0) /* Low-power Configurations */
++#define AT91_SDRAMC_LPCB_DISABLE 0
++#define AT91_SDRAMC_LPCB_SELF_REFRESH 1
++#define AT91_SDRAMC_LPCB_POWER_DOWN 2
++#define AT91_SDRAMC_LPCB_DEEP_POWER_DOWN 3
++#define AT91_SDRAMC_PASR (7 << 4) /* Partial Array Self Refresh */
++#define AT91_SDRAMC_TCSR (3 << 8) /* Temperature Compensated Self Refresh */
++#define AT91_SDRAMC_DS (3 << 10) /* Drive Strength */
++#define AT91_SDRAMC_TIMEOUT (3 << 12) /* Time to define when Low Power Mode is enabled */
++#define AT91_SDRAMC_TIMEOUT_0_CLK_CYCLES (0 << 12)
++#define AT91_SDRAMC_TIMEOUT_64_CLK_CYCLES (1 << 12)
++#define AT91_SDRAMC_TIMEOUT_128_CLK_CYCLES (2 << 12)
++
++#define AT91_SDRAMC_IER (AT91_SDRAMC + 0x14) /* SDRAM Controller Interrupt Enable Register */
++#define AT91_SDRAMC_IDR (AT91_SDRAMC + 0x18) /* SDRAM Controller Interrupt Disable Register */
++#define AT91_SDRAMC_IMR (AT91_SDRAMC + 0x1C) /* SDRAM Controller Interrupt Mask Register */
++#define AT91_SDRAMC_ISR (AT91_SDRAMC + 0x20) /* SDRAM Controller Interrupt Status Register */
++#define AT91_SDRAMC_RES (1 << 0) /* Refresh Error Status */
++
++#define AT91_SDRAMC_MDR (AT91_SDRAMC + 0x24) /* SDRAM Memory Device Register */
++#define AT91_SDRAMC_MD (3 << 0) /* Memory Device Type */
++#define AT91_SDRAMC_MD_SDRAM 0
++#define AT91_SDRAMC_MD_LOW_POWER_SDRAM 1
++
++
++#endif
+diff --git a/include/asm-arm/arch-at91/at91sam9_smc.h b/include/asm-arm/arch-at91/at91sam9_smc.h
+new file mode 100644
+index 0000000..9e49eed
+--- /dev/null
++++ b/include/asm-arm/arch-at91/at91sam9_smc.h
+@@ -0,0 +1,73 @@
++/*
++ * include/asm-arm/arch-at91/at91sam9_smc.h
++ *
++ * Static Memory Controllers (SMC) - System peripherals registers.
++ * Based on AT91SAM9261 datasheet revision D.
++ *
++ * 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 AT91SAM9_SMC_H
++#define AT91SAM9_SMC_H
++
++#define AT91_SMC_SETUP(n) (AT91_SMC + 0x00 + ((n)*0x10)) /* Setup Register for CS n */
++#define AT91_SMC_NWESETUP (0x3f << 0) /* NWE Setup Length */
++#define AT91_SMC_NWESETUP_(x) ((x) << 0)
++#define AT91_SMC_NCS_WRSETUP (0x3f << 8) /* NCS Setup Length in Write Access */
++#define AT91_SMC_NCS_WRSETUP_(x) ((x) << 8)
++#define AT91_SMC_NRDSETUP (0x3f << 16) /* NRD Setup Length */
++#define AT91_SMC_NRDSETUP_(x) ((x) << 16)
++#define AT91_SMC_NCS_RDSETUP (0x3f << 24) /* NCS Setup Length in Read Access */
++#define AT91_SMC_NCS_RDSETUP_(x) ((x) << 24)
++
++#define AT91_SMC_PULSE(n) (AT91_SMC + 0x04 + ((n)*0x10)) /* Pulse Register for CS n */
++#define AT91_SMC_NWEPULSE (0x7f << 0) /* NWE Pulse Length */
++#define AT91_SMC_NWEPULSE_(x) ((x) << 0)
++#define AT91_SMC_NCS_WRPULSE (0x7f << 8) /* NCS Pulse Length in Write Access */
++#define AT91_SMC_NCS_WRPULSE_(x)((x) << 8)
++#define AT91_SMC_NRDPULSE (0x7f << 16) /* NRD Pulse Length */
++#define AT91_SMC_NRDPULSE_(x) ((x) << 16)
++#define AT91_SMC_NCS_RDPULSE (0x7f << 24) /* NCS Pulse Length in Read Access */
++#define AT91_SMC_NCS_RDPULSE_(x)((x) << 24)
++
++#define AT91_SMC_CYCLE(n) (AT91_SMC + 0x08 + ((n)*0x10)) /* Cycle Register for CS n */
++#define AT91_SMC_NWECYCLE (0x1ff << 0 ) /* Total Write Cycle Length */
++#define AT91_SMC_NWECYCLE_(x) ((x) << 0)
++#define AT91_SMC_NRDCYCLE (0x1ff << 16) /* Total Read Cycle Length */
++#define AT91_SMC_NRDCYCLE_(x) ((x) << 16)
++
++#define AT91_SMC_MODE(n) (AT91_SMC + 0x0c + ((n)*0x10)) /* Mode Register for CS n */
++#define AT91_SMC_READMODE (1 << 0) /* Read Mode */
++#define AT91_SMC_WRITEMODE (1 << 1) /* Write Mode */
++#define AT91_SMC_EXNWMODE (3 << 4) /* NWAIT Mode */
++#define AT91_SMC_EXNWMODE_DISABLE (0 << 4)
++#define AT91_SMC_EXNWMODE_FROZEN (2 << 4)
++#define AT91_SMC_EXNWMODE_READY (3 << 4)
++#define AT91_SMC_BAT (1 << 8) /* Byte Access Type */
++#define AT91_SMC_BAT_SELECT (0 << 8)
++#define AT91_SMC_BAT_WRITE (1 << 8)
++#define AT91_SMC_DBW (3 << 12) /* Data Bus Width */
++#define AT91_SMC_DBW_8 (0 << 12)
++#define AT91_SMC_DBW_16 (1 << 12)
++#define AT91_SMC_DBW_32 (2 << 12)
++#define AT91_SMC_TDF (0xf << 16) /* Data Float Time. */
++#define AT91_SMC_TDF_(x) ((x) << 16)
++#define AT91_SMC_TDFMODE (1 << 20) /* TDF Optimization - Enabled */
++#define AT91_SMC_PMEN (1 << 24) /* Page Mode Enabled */
++#define AT91_SMC_PS (3 << 28) /* Page Size */
++#define AT91_SMC_PS_4 (0 << 28)
++#define AT91_SMC_PS_8 (1 << 28)
++#define AT91_SMC_PS_16 (2 << 28)
++#define AT91_SMC_PS_32 (3 << 28)
++
++#if defined(AT91_SMC1) /* The AT91SAM9263 has 2 Static Memory contollers */
++#define AT91_SMC1_SETUP(n) (AT91_SMC1 + 0x00 + ((n)*0x10)) /* Setup Register for CS n */
++#define AT91_SMC1_PULSE(n) (AT91_SMC1 + 0x04 + ((n)*0x10)) /* Pulse Register for CS n */
++#define AT91_SMC1_CYCLE(n) (AT91_SMC1 + 0x08 + ((n)*0x10)) /* Cycle Register for CS n */
++#define AT91_SMC1_MODE(n) (AT91_SMC1 + 0x0c + ((n)*0x10)) /* Mode Register for CS n */
++#endif
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/gpio.h b/include/asm-arm/arch-ep93xx/gpio.h
+index 9b1864b..186e7c7 100644
+--- a/include/asm-arm/arch-ep93xx/gpio.h
++++ b/include/asm-arm/arch-ep93xx/gpio.h
+@@ -101,30 +101,17 @@
+
+ /* new generic GPIO API - see Documentation/gpio.txt */
+
+-static inline int gpio_request(unsigned gpio, const char *label)
+-{
+- if (gpio > EP93XX_GPIO_LINE_MAX)
+- return -EINVAL;
+- return 0;
+-}
++#include <asm-generic/gpio.h>
+
+-static inline void gpio_free(unsigned gpio)
+-{
+-}
+-
+-int gpio_direction_input(unsigned gpio);
+-int gpio_direction_output(unsigned gpio, int value);
+-int gpio_get_value(unsigned gpio);
+-void gpio_set_value(unsigned gpio, int value);
+-
+-#include <asm-generic/gpio.h> /* cansleep wrappers */
++#define gpio_get_value __gpio_get_value
++#define gpio_set_value __gpio_set_value
++#define gpio_cansleep __gpio_cansleep
+
+ /*
+ * Map GPIO A0..A7 (0..7) to irq 64..71,
+ * B0..B7 (7..15) to irq 72..79, and
+ * F0..F7 (16..24) to irq 80..87.
+ */
+-
+ static inline int gpio_to_irq(unsigned gpio)
+ {
+ if (gpio <= EP93XX_GPIO_LINE_MAX_IRQ)
+diff --git a/include/asm-arm/arch-iop13xx/adma.h b/include/asm-arm/arch-iop13xx/adma.h
+index efd9a5e..90d14ee 100644
+--- a/include/asm-arm/arch-iop13xx/adma.h
++++ b/include/asm-arm/arch-iop13xx/adma.h
+@@ -454,11 +454,6 @@ static inline void iop_chan_append(struct iop_adma_chan *chan)
+ __raw_writel(adma_accr, ADMA_ACCR(chan));
+ }
+
+-static inline void iop_chan_idle(int busy, struct iop_adma_chan *chan)
+-{
+- do { } while (0);
+-}
+-
+ static inline u32 iop_chan_get_status(struct iop_adma_chan *chan)
+ {
+ return __raw_readl(ADMA_ACSR(chan));
+diff --git a/include/asm-arm/arch-ks8695/devices.h b/include/asm-arm/arch-ks8695/devices.h
+index b0364dc..7ad2c65 100644
+--- a/include/asm-arm/arch-ks8695/devices.h
++++ b/include/asm-arm/arch-ks8695/devices.h
+@@ -18,6 +18,11 @@ extern void __init ks8695_add_device_wan(void);
+ extern void __init ks8695_add_device_lan(void);
+ extern void __init ks8695_add_device_hpna(void);
+
++ /* LEDs */
++extern short ks8695_leds_cpu;
++extern short ks8695_leds_timer;
++extern void __init ks8695_init_leds(u8 cpu_led, u8 timer_led);
++
+ /* PCI */
+ #define KS8695_MODE_PCI 0
+ #define KS8695_MODE_MINIPCI 1
+diff --git a/include/asm-arm/arch-mxc/board-mx31ads.h b/include/asm-arm/arch-mxc/board-mx31ads.h
+index be29b83..8590127 100644
+--- a/include/asm-arm/arch-mxc/board-mx31ads.h
++++ b/include/asm-arm/arch-mxc/board-mx31ads.h
+@@ -11,107 +11,77 @@
+ #ifndef __ASM_ARCH_MXC_BOARD_MX31ADS_H__
+ #define __ASM_ARCH_MXC_BOARD_MX31ADS_H__
+
+-/*!
+- * @name PBC Controller parameters
+- */
+-/*! @{ */
+-/*!
+- * Base address of PBC controller
+- */
++/* Base address of PBC controller */
+ #define PBC_BASE_ADDRESS IO_ADDRESS(CS4_BASE_ADDR)
+ /* Offsets for the PBC Controller register */
+-/*!
+- * PBC Board status register offset
+- */
++
++/* PBC Board status register offset */
+ #define PBC_BSTAT 0x000002
+-/*!
+- * PBC Board control register 1 set address.
+- */
++
++/* PBC Board control register 1 set address */
+ #define PBC_BCTRL1_SET 0x000004
+-/*!
+- * PBC Board control register 1 clear address.
+- */
++
++/* PBC Board control register 1 clear address */
+ #define PBC_BCTRL1_CLEAR 0x000006
+-/*!
+- * PBC Board control register 2 set address.
+- */
++
++/* PBC Board control register 2 set address */
+ #define PBC_BCTRL2_SET 0x000008
+-/*!
+- * PBC Board control register 2 clear address.
+- */
++
++/* PBC Board control register 2 clear address */
+ #define PBC_BCTRL2_CLEAR 0x00000A
+-/*!
+- * PBC Board control register 3 set address.
+- */
++
++/* PBC Board control register 3 set address */
+ #define PBC_BCTRL3_SET 0x00000C
+-/*!
+- * PBC Board control register 3 clear address.
+- */
++
++/* PBC Board control register 3 clear address */
+ #define PBC_BCTRL3_CLEAR 0x00000E
+-/*!
+- * PBC Board control register 4 set address.
+- */
++
++/* PBC Board control register 4 set address */
+ #define PBC_BCTRL4_SET 0x000010
+-/*!
+- * PBC Board control register 4 clear address.
+- */
++
++/* PBC Board control register 4 clear address */
+ #define PBC_BCTRL4_CLEAR 0x000012
+-/*!
+- * PBC Board status register 1.
+- */
++
++/* PBC Board status register 1 */
+ #define PBC_BSTAT1 0x000014
+-/*!
+- * PBC Board interrupt status register.
+- */
++
++/* PBC Board interrupt status register */
+ #define PBC_INTSTATUS 0x000016
+-/*!
+- * PBC Board interrupt current status register.
+- */
++
++/* PBC Board interrupt current status register */
+ #define PBC_INTCURR_STATUS 0x000018
+-/*!
+- * PBC Interrupt mask register set address.
+- */
++
++/* PBC Interrupt mask register set address */
+ #define PBC_INTMASK_SET 0x00001A
+-/*!
+- * PBC Interrupt mask register clear address.
+- */
++
++/* PBC Interrupt mask register clear address */
+ #define PBC_INTMASK_CLEAR 0x00001C
+
+-/*!
+- * External UART A.
+- */
++/* External UART A */
+ #define PBC_SC16C652_UARTA 0x010000
+-/*!
+- * External UART B.
+- */
++
++/* External UART B */
+ #define PBC_SC16C652_UARTB 0x010010
+-/*!
+- * Ethernet Controller IO base address.
+- */
++
++/* Ethernet Controller IO base address */
+ #define PBC_CS8900A_IOBASE 0x020000
+-/*!
+- * Ethernet Controller Memory base address.
+- */
++
++/* Ethernet Controller Memory base address */
+ #define PBC_CS8900A_MEMBASE 0x021000
+-/*!
+- * Ethernet Controller DMA base address.
+- */
++
++/* Ethernet Controller DMA base address */
+ #define PBC_CS8900A_DMABASE 0x022000
+-/*!
+- * External chip select 0.
+- */
++
++/* External chip select 0 */
+ #define PBC_XCS0 0x040000
+-/*!
+- * LCD Display enable.
+- */
++
++/* LCD Display enable */
+ #define PBC_LCD_EN_B 0x060000
+-/*!
+- * Code test debug enable.
+- */
++
++/* Code test debug enable */
+ #define PBC_CODE_B 0x070000
+-/*!
+- * PSRAM memory select.
+- */
++
++/* PSRAM memory select */
+ #define PBC_PSRAM_B 0x5000000
+
+ #define PBC_INTSTATUS_REG (PBC_INTSTATUS + PBC_BASE_ADDRESS)
+@@ -139,4 +109,4 @@
+
+ #define MXC_MAX_EXP_IO_LINES 16
+
+-#endif /* __ASM_ARCH_MXC_BOARD_MX31ADS_H__ */
++#endif /* __ASM_ARCH_MXC_BOARD_MX31ADS_H__ */
+diff --git a/include/asm-arm/arch-mxc/dma.h b/include/asm-arm/arch-mxc/dma.h
+index 65e639d..c822d56 100644
+--- a/include/asm-arm/arch-mxc/dma.h
++++ b/include/asm-arm/arch-mxc/dma.h
+@@ -11,11 +11,4 @@
+ #ifndef __ASM_ARCH_MXC_DMA_H__
+ #define __ASM_ARCH_MXC_DMA_H__
+
+-/*!
+- * @file dma.h
+- * @brief This file contains Unified DMA API for all MXC platforms.
+- * The API is platform independent.
+- *
+- * @ingroup SDMA
+- */
+ #endif
+diff --git a/include/asm-arm/arch-mxc/hardware.h b/include/asm-arm/arch-mxc/hardware.h
+index 3c09b92..e87ff06 100644
+--- a/include/asm-arm/arch-mxc/hardware.h
++++ b/include/asm-arm/arch-mxc/hardware.h
+@@ -8,45 +8,24 @@
+ * published by the Free Software Foundation.
+ */
+
+-/*!
+- * @file hardware.h
+- * @brief This file contains the hardware definitions of the board.
+- *
+- * @ingroup System
+- */
+ #ifndef __ASM_ARCH_MXC_HARDWARE_H__
+ #define __ASM_ARCH_MXC_HARDWARE_H__
+
+ #include <asm/sizes.h>
+
+-#include <asm/arch/mx31.h>
++#ifdef CONFIG_ARCH_MX3
++# include <asm/arch/mx31.h>
++#endif
+
+ #include <asm/arch/mxc.h>
+
+-#define MXC_MAX_GPIO_LINES (GPIO_NUM_PIN * GPIO_PORT_NUM)
+-
+ /*
+ * ---------------------------------------------------------------------------
+ * Board specific defines
+ * ---------------------------------------------------------------------------
+ */
+-#define MXC_EXP_IO_BASE (MXC_GPIO_INT_BASE + MXC_MAX_GPIO_LINES)
+-
+-#include <asm/arch/board-mx31ads.h>
+-
+-#ifndef MXC_MAX_EXP_IO_LINES
+-#define MXC_MAX_EXP_IO_LINES 0
++#ifdef CONFIG_MACH_MX31ADS
++# include <asm/arch/board-mx31ads.h>
+ #endif
+
+-#define MXC_MAX_VIRTUAL_INTS 16
+-#define MXC_VIRTUAL_INTS_BASE (MXC_EXP_IO_BASE + MXC_MAX_EXP_IO_LINES)
+-#define MXC_SDIO1_CARD_IRQ MXC_VIRTUAL_INTS_BASE
+-#define MXC_SDIO2_CARD_IRQ (MXC_VIRTUAL_INTS_BASE + 1)
+-#define MXC_SDIO3_CARD_IRQ (MXC_VIRTUAL_INTS_BASE + 2)
+-
+-#define MXC_MAX_INTS (MXC_MAX_INT_LINES + \
+- MXC_MAX_GPIO_LINES + \
+- MXC_MAX_EXP_IO_LINES + \
+- MXC_MAX_VIRTUAL_INTS)
+-
+-#endif /* __ASM_ARCH_MXC_HARDWARE_H__ */
++#endif /* __ASM_ARCH_MXC_HARDWARE_H__ */
+diff --git a/include/asm-arm/arch-mxc/io.h b/include/asm-arm/arch-mxc/io.h
+index cf6c83a..65b6810 100644
+--- a/include/asm-arm/arch-mxc/io.h
++++ b/include/asm-arm/arch-mxc/io.h
+@@ -8,24 +8,13 @@
+ * published by the Free Software Foundation.
+ */
+
+-/*!
+- * @file io.h
+- * @brief This file contains some memory mapping macros.
+- * @note There is no real ISA or PCI buses. But have to define these macros
+- * for some drivers to compile.
+- *
+- * @ingroup System
+- */
+-
+ #ifndef __ASM_ARCH_MXC_IO_H__
+ #define __ASM_ARCH_MXC_IO_H__
+
+-/*! Allow IO space to be anywhere in the memory */
++/* Allow IO space to be anywhere in the memory */
+ #define IO_SPACE_LIMIT 0xffffffff
+
+-/*!
+- * io address mapping macro
+- */
++/* io address mapping macro */
+ #define __io(a) ((void __iomem *)(a))
+
+ #define __mem_pci(a) (a)
+diff --git a/include/asm-arm/arch-mxc/irqs.h b/include/asm-arm/arch-mxc/irqs.h
+index e4686c6..b2c5205 100644
+--- a/include/asm-arm/arch-mxc/irqs.h
++++ b/include/asm-arm/arch-mxc/irqs.h
+@@ -13,26 +13,17 @@
+
+ #include <asm/hardware.h>
+
+-/*!
+- * @file irqs.h
+- * @brief This file defines the number of normal interrupts and fast interrupts
+- *
+- * @ingroup Interrupt
+- */
+-
+ #define MXC_IRQ_TO_EXPIO(irq) ((irq) - MXC_EXP_IO_BASE)
+
+ #define MXC_IRQ_TO_GPIO(irq) ((irq) - MXC_GPIO_INT_BASE)
+ #define MXC_GPIO_TO_IRQ(x) (MXC_GPIO_INT_BASE + x)
+
+-/*!
+- * Number of normal interrupts
+- */
+-#define NR_IRQS MXC_MAX_INTS
++/* Number of normal interrupts */
++#define NR_IRQS (MXC_MAX_INT_LINES + \
++ MXC_MAX_GPIO_LINES + \
++ MXC_MAX_VIRTUAL_INTS)
+
+-/*!
+- * Number of fast interrupts
+- */
++/* Number of fast interrupts */
+ #define NR_FIQS MXC_MAX_INTS
+
+-#endif /* __ASM_ARCH_MXC_IRQS_H__ */
++#endif /* __ASM_ARCH_MXC_IRQS_H__ */
+diff --git a/include/asm-arm/arch-mxc/memory.h b/include/asm-arm/arch-mxc/memory.h
+index c89aac8..059f830 100644
+--- a/include/asm-arm/arch-mxc/memory.h
++++ b/include/asm-arm/arch-mxc/memory.h
+@@ -13,24 +13,17 @@
+
+ #include <asm/hardware.h>
+
+-/*!
+- * @file memory.h
+- * @brief This file contains macros needed by the Linux kernel and drivers.
+- *
+- * @ingroup Memory
+- */
+-
+-/*!
++/*
+ * Virtual view <-> DMA view memory address translations
+ * This macro is used to translate the virtual address to an address
+ * suitable to be passed to set_dma_addr()
+ */
+ #define __virt_to_bus(a) __virt_to_phys(a)
+
+-/*!
++/*
+ * Used to convert an address for DMA operations to an address that the
+ * kernel can use.
+ */
+ #define __bus_to_virt(a) __phys_to_virt(a)
+
+-#endif /* __ASM_ARCH_MXC_MEMORY_H__ */
++#endif /* __ASM_ARCH_MXC_MEMORY_H__ */
+diff --git a/include/asm-arm/arch-mxc/mx31.h b/include/asm-arm/arch-mxc/mx31.h
+index 85c49c9..36a1af4 100644
+--- a/include/asm-arm/arch-mxc/mx31.h
++++ b/include/asm-arm/arch-mxc/mx31.h
+@@ -317,6 +317,8 @@
+ #define MXC_MAX_INT_LINES 64
+
+ #define MXC_GPIO_INT_BASE MXC_MAX_INT_LINES
++#define MXC_MAX_GPIO_LINES (GPIO_NUM_PIN * GPIO_PORT_NUM)
++#define MXC_MAX_VIRTUAL_INTS 16
+
+ /*!
+ * Number of GPIO port as defined in the IC Spec
+@@ -329,7 +331,33 @@
+
+ #define PROD_SIGNATURE 0x1 /* For MX31 */
+
++/* silicon revisions specific to i.MX31 */
++#define CHIP_REV_1_0 0x10
++#define CHIP_REV_1_1 0x11
++#define CHIP_REV_1_2 0x12
++#define CHIP_REV_1_3 0x13
++#define CHIP_REV_2_0 0x20
++#define CHIP_REV_2_1 0x21
++#define CHIP_REV_2_2 0x22
++#define CHIP_REV_2_3 0x23
++#define CHIP_REV_3_0 0x30
++#define CHIP_REV_3_1 0x31
++#define CHIP_REV_3_2 0x32
++
+ #define SYSTEM_REV_MIN CHIP_REV_1_0
+ #define SYSTEM_REV_NUM 3
+
+-#endif /* __ASM_ARCH_MXC_MX31_H__ */
++#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
++
++/* this is a i.MX31 CPU */
++#define cpu_is_mx31() (1)
++
++extern unsigned int system_rev;
++
++static inline int mx31_revision(void)
++{
++ return system_rev;
++}
++#endif
++
++#endif /* __ASM_ARCH_MXC_MX31_H__ */
+diff --git a/include/asm-arm/arch-mxc/mxc.h b/include/asm-arm/arch-mxc/mxc.h
+index 0837f1f..146d3f6 100644
+--- a/include/asm-arm/arch-mxc/mxc.h
++++ b/include/asm-arm/arch-mxc/mxc.h
+@@ -15,6 +15,11 @@
+ #error "Do not include directly."
+ #endif
+
++/* clean up all things that are not used */
++#ifndef CONFIG_ARCH_MX3
++# define cpu_is_mx31() (0)
++#endif
++
+ /*
+ *****************************************
+ * GPT Register definitions *
+@@ -31,9 +36,7 @@
+ #define MXC_GPT_GPTICR2 IO_ADDRESS(GPT1_BASE_ADDR + 0x20)
+ #define MXC_GPT_GPTCNT IO_ADDRESS(GPT1_BASE_ADDR + 0x24)
+
+-/*!
+- * GPT Control register bit definitions
+- */
++/* GPT Control register bit definitions */
+ #define GPTCR_FO3 (1 << 31)
+ #define GPTCR_FO2 (1 << 30)
+ #define GPTCR_FO1 (1 << 29)
+@@ -146,4 +149,4 @@
+ #define IIM_PROD_REV_SH 3
+ #define IIM_PROD_REV_LEN 5
+
+-#endif /* __ASM_ARCH_MXC_H__ */
++#endif /* __ASM_ARCH_MXC_H__ */
+diff --git a/include/asm-arm/arch-mxc/system.h b/include/asm-arm/arch-mxc/system.h
+index 109956b..bbfc374 100644
+--- a/include/asm-arm/arch-mxc/system.h
++++ b/include/asm-arm/arch-mxc/system.h
+@@ -21,30 +21,14 @@
+ #ifndef __ASM_ARCH_MXC_SYSTEM_H__
+ #define __ASM_ARCH_MXC_SYSTEM_H__
+
+-/*!
+- * @file system.h
+- * @brief This file contains idle and reset functions.
+- *
+- * @ingroup System
+- */
+-
+-/*!
+- * This function puts the CPU into idle mode. It is called by default_idle()
+- * in process.c file.
+- */
+ static inline void arch_idle(void)
+ {
+ cpu_do_idle();
+ }
+
+-/*
+- * This function resets the system. It is called by machine_restart().
+- *
+- * @param mode indicates different kinds of resets
+- */
+ static inline void arch_reset(char mode)
+ {
+ cpu_reset(0);
+ }
+
+-#endif /* __ASM_ARCH_MXC_SYSTEM_H__ */
++#endif /* __ASM_ARCH_MXC_SYSTEM_H__ */
+diff --git a/include/asm-arm/arch-mxc/vmalloc.h b/include/asm-arm/arch-mxc/vmalloc.h
+index 83a73da..62d9762 100644
+--- a/include/asm-arm/arch-mxc/vmalloc.h
++++ b/include/asm-arm/arch-mxc/vmalloc.h
+@@ -20,17 +20,7 @@
+ #ifndef __ASM_ARCH_MXC_VMALLOC_H__
+ #define __ASM_ARCH_MXC_VMALLOC_H__
+
+-/*!
+- * @file vmalloc.h
+- *
+- * @brief This file contains platform specific macros for vmalloc.
+- *
+- * @ingroup System
+- */
+-
+-/*!
+- * vmalloc ending address
+- */
++/* vmalloc ending address */
+ #define VMALLOC_END 0xF4000000
+
+-#endif /* __ASM_ARCH_MXC_VMALLOC_H__ */
++#endif /* __ASM_ARCH_MXC_VMALLOC_H__ */
+diff --git a/include/asm-arm/arch-ns9xxx/board.h b/include/asm-arm/arch-ns9xxx/board.h
+index 716f34f..e57443b 100644
+--- a/include/asm-arm/arch-ns9xxx/board.h
++++ b/include/asm-arm/arch-ns9xxx/board.h
+@@ -1,7 +1,7 @@
+ /*
+ * include/asm-arm/arch-ns9xxx/board.h
+ *
+- * Copyright (C) 2006 by Digi International Inc.
++ * Copyright (C) 2006,2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+@@ -13,8 +13,30 @@
+
+ #include <asm/mach-types.h>
+
+-#define board_is_a9m9750dev() (machine_is_cc9p9360dev())
++#define board_is_a9m9750dev() (0 \
++ || machine_is_cc9p9360dev() \
++ || machine_is_cc9p9750dev() \
++ )
+
+-#define board_is_jscc9p9360() (machine_is_cc9p9360js())
++#define board_is_a9mvali() (0 \
++ || machine_is_cc9p9360val() \
++ || machine_is_cc9p9750val() \
++ )
++
++#define board_is_jscc9p9210() (0 \
++ || machine_is_cc9p9210js() \
++ )
++
++#define board_is_jscc9p9215() (0 \
++ || machine_is_cc9p9215js() \
++ )
++
++#define board_is_jscc9p9360() (0 \
++ || machine_is_cc9p9360js() \
++ )
++
++#define board_is_uncbas() (0 \
++ || machine_is_cc7ucamry() \
++ )
+
+ #endif /* ifndef __ASM_ARCH_BOARD_H */
+diff --git a/include/asm-arm/arch-ns9xxx/clock.h b/include/asm-arm/arch-ns9xxx/clock.h
+deleted file mode 100644
+index b943d3a..0000000
+--- a/include/asm-arm/arch-ns9xxx/clock.h
++++ /dev/null
+@@ -1,71 +0,0 @@
+-/*
+- * include/asm-arm/arch-ns9xxx/clock.h
+- *
+- * Copyright (C) 2007 by Digi International Inc.
+- * All rights reserved.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License version 2 as published by
+- * the Free Software Foundation.
+- */
+-#ifndef __ASM_ARCH_CLOCK_H
+-#define __ASM_ARCH_CLOCK_H
+-
+-#include <asm/arch-ns9xxx/regs-sys.h>
+-
+-#define CRYSTAL 29491200 /* Hz */
+-
+-/* The HRM calls this value f_vco */
+-static inline u32 ns9xxx_systemclock(void) __attribute__((const));
+-static inline u32 ns9xxx_systemclock(void)
+-{
+- u32 pll = __raw_readl(SYS_PLL);
+-
+- /*
+- * The system clock should be a multiple of HZ * TIMERCLOCKSELECT (in
+- * time.c).
+- *
+- * The following values are given:
+- * - TIMERCLOCKSELECT == 2^i for an i in {0 .. 6}
+- * - CRYSTAL == 29491200 == 2^17 * 3^2 * 5^2
+- * - ND in {0 .. 31}
+- * - FS in {0 .. 3}
+- *
+- * Assuming the worst, we consider:
+- * - TIMERCLOCKSELECT == 64
+- * - ND == 0
+- * - FS == 3
+- *
+- * So HZ should be a divisor of:
+- * (CRYSTAL * (ND + 1) >> FS) / TIMERCLOCKSELECT
+- * == (2^17 * 3^2 * 5^2 * 1 >> 3) / 64
+- * == 2^8 * 3^2 * 5^2
+- * == 57600
+- *
+- * Currently HZ is defined to be 100 for this platform.
+- *
+- * Fine.
+- */
+- return CRYSTAL * (REGGETIM(pll, SYS_PLL, ND) + 1)
+- >> REGGETIM(pll, SYS_PLL, FS);
+-}
+-
+-static inline u32 ns9xxx_cpuclock(void) __attribute__((const));
+-static inline u32 ns9xxx_cpuclock(void)
+-{
+- return ns9xxx_systemclock() / 2;
+-}
+-
+-static inline u32 ns9xxx_ahbclock(void) __attribute__((const));
+-static inline u32 ns9xxx_ahbclock(void)
+-{
+- return ns9xxx_systemclock() / 4;
+-}
+-
+-static inline u32 ns9xxx_bbusclock(void) __attribute__((const));
+-static inline u32 ns9xxx_bbusclock(void)
+-{
+- return ns9xxx_systemclock() / 8;
+-}
+-
+-#endif /* ifndef __ASM_ARCH_CLOCK_H */
+diff --git a/include/asm-arm/arch-ns9xxx/entry-macro.S b/include/asm-arm/arch-ns9xxx/entry-macro.S
+index 86aec87..89a21c5 100644
+--- a/include/asm-arm/arch-ns9xxx/entry-macro.S
++++ b/include/asm-arm/arch-ns9xxx/entry-macro.S
+@@ -1,7 +1,7 @@
+ /*
+ * include/asm-arm/arch-ns9xxx/entry-macro.S
+ *
+- * Copyright (C) 2006 by Digi International Inc.
++ * Copyright (C) 2006,2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+@@ -9,16 +9,16 @@
+ * the Free Software Foundation.
+ */
+ #include <asm/hardware.h>
+-#include <asm/arch-ns9xxx/regs-sys.h>
++#include <asm/arch-ns9xxx/regs-sys-common.h>
+
+ .macro get_irqnr_preamble, base, tmp
++ ldr \base, =SYS_ISRADDR
+ .endm
+
+ .macro arch_ret_to_user, tmp1, tmp2
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+- ldr \base, =SYS_ISRADDR
+ ldr \irqstat, [\base, #(SYS_ISA - SYS_ISRADDR)]
+ cmp \irqstat, #0
+ ldrne \irqnr, [\base]
+diff --git a/include/asm-arm/arch-ns9xxx/irqs.h b/include/asm-arm/arch-ns9xxx/irqs.h
+index 25d8d28..e83d48e 100644
+--- a/include/asm-arm/arch-ns9xxx/irqs.h
++++ b/include/asm-arm/arch-ns9xxx/irqs.h
+@@ -1,7 +1,7 @@
+ /*
+ * include/asm-arm/arch-ns9xxx/irqs.h
+ *
+- * Copyright (C) 2006 by Digi International Inc.
++ * Copyright (C) 2006,2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+@@ -11,38 +11,39 @@
+ #ifndef __ASM_ARCH_IRQS_H
+ #define __ASM_ARCH_IRQS_H
+
+-#define IRQ_WATCHDOG 0
+-#define IRQ_AHBBUSERR 1
+-#define IRQ_BBUSAGG 2
++/* NetSilicon 9360 */
++#define IRQ_NS9XXX_WATCHDOG 0
++#define IRQ_NS9XXX_AHBBUSERR 1
++#define IRQ_NS9360_BBUSAGG 2
+ /* irq 3 is reserved for NS9360 */
+-#define IRQ_ETHRX 4
+-#define IRQ_ETHTX 5
+-#define IRQ_ETHPHY 6
+-#define IRQ_LCD 7
+-#define IRQ_SERBRX 8
+-#define IRQ_SERBTX 9
+-#define IRQ_SERARX 10
+-#define IRQ_SERATX 11
+-#define IRQ_SERCRX 12
+-#define IRQ_SERCTX 13
+-#define IRQ_I2C 14
+-#define IRQ_BBUSDMA 15
+-#define IRQ_TIMER0 16
+-#define IRQ_TIMER1 17
+-#define IRQ_TIMER2 18
+-#define IRQ_TIMER3 19
+-#define IRQ_TIMER4 20
+-#define IRQ_TIMER5 21
+-#define IRQ_TIMER6 22
+-#define IRQ_TIMER7 23
+-#define IRQ_RTC 24
+-#define IRQ_USBHOST 25
+-#define IRQ_USBDEVICE 26
+-#define IRQ_IEEE1284 27
+-#define IRQ_EXT0 28
+-#define IRQ_EXT1 29
+-#define IRQ_EXT2 30
+-#define IRQ_EXT3 31
++#define IRQ_NS9XXX_ETHRX 4
++#define IRQ_NS9XXX_ETHTX 5
++#define IRQ_NS9XXX_ETHPHY 6
++#define IRQ_NS9360_LCD 7
++#define IRQ_NS9360_SERBRX 8
++#define IRQ_NS9360_SERBTX 9
++#define IRQ_NS9360_SERARX 10
++#define IRQ_NS9360_SERATX 11
++#define IRQ_NS9360_SERCRX 12
++#define IRQ_NS9360_SERCTX 13
++#define IRQ_NS9360_I2C 14
++#define IRQ_NS9360_BBUSDMA 15
++#define IRQ_NS9360_TIMER0 16
++#define IRQ_NS9360_TIMER1 17
++#define IRQ_NS9360_TIMER2 18
++#define IRQ_NS9360_TIMER3 19
++#define IRQ_NS9360_TIMER4 20
++#define IRQ_NS9360_TIMER5 21
++#define IRQ_NS9360_TIMER6 22
++#define IRQ_NS9360_TIMER7 23
++#define IRQ_NS9360_RTC 24
++#define IRQ_NS9360_USBHOST 25
++#define IRQ_NS9360_USBDEVICE 26
++#define IRQ_NS9360_IEEE1284 27
++#define IRQ_NS9XXX_EXT0 28
++#define IRQ_NS9XXX_EXT1 29
++#define IRQ_NS9XXX_EXT2 30
++#define IRQ_NS9XXX_EXT3 31
+
+ #define BBUS_IRQ(irq) (32 + irq)
+
+@@ -67,7 +68,7 @@
+ /*
+ * these Interrupts are specific for the a9m9750dev board.
+ * They are generated by an FPGA that interrupts the CPU on
+- * IRQ_EXT2
++ * IRQ_NS9360_EXT2
+ */
+ #define FPGA_IRQ(irq) (64 + irq)
+
+diff --git a/include/asm-arm/arch-ns9xxx/module.h b/include/asm-arm/arch-ns9xxx/module.h
+new file mode 100644
+index 0000000..ac08a31
+--- /dev/null
++++ b/include/asm-arm/arch-ns9xxx/module.h
+@@ -0,0 +1,60 @@
++/*
++ * include/asm-arm/arch-ns9xxx/module.h
++ *
++ * Copyright (C) 2007 by Digi International Inc.
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ */
++#ifndef __ASM_ARCH_MODULE_H
++#define __ASM_ARCH_MODULE_H
++
++#include <asm/mach-types.h>
++
++#define module_is_cc7ucamry() (0 \
++ || machine_is_cc7ucamry() \
++ )
++
++#define module_is_cc9c() (0 \
++ || machine_is_cc9c() \
++ )
++
++#define module_is_cc9p9210() (0 \
++ || machine_is_cc9p9210() \
++ || machine_is_cc9p9210js() \
++ )
++
++#define module_is_cc9p9215() (0 \
++ || machine_is_cc9p9215() \
++ || machine_is_cc9p9215js() \
++ )
++
++#define module_is_cc9p9360() (0 \
++ || machine_is_a9m9360() \
++ || machine_is_cc9p9360dev() \
++ || machine_is_cc9p9360js() \
++ || machine_is_cc9p9360val() \
++ )
++
++#define module_is_cc9p9750() (0 \
++ || machine_is_a9m9750() \
++ || machine_is_cc9p9750dev() \
++ || machine_is_cc9p9750js() \
++ || machine_is_cc9p9750val() \
++ )
++
++#define module_is_ccw9c() (0 \
++ || machine_is_ccw9c() \
++ )
++
++#define module_is_inc20otter() (0 \
++ || machine_is_inc20otter() \
++ )
++
++#define module_is_otter() (0 \
++ || machine_is_otter() \
++ )
++
++#endif /* ifndef __ASM_ARCH_MODULE_H */
+diff --git a/include/asm-arm/arch-ns9xxx/processor-ns9360.h b/include/asm-arm/arch-ns9xxx/processor-ns9360.h
+new file mode 100644
+index 0000000..f3aa6c5
+--- /dev/null
++++ b/include/asm-arm/arch-ns9xxx/processor-ns9360.h
+@@ -0,0 +1,32 @@
++/*
++ * include/asm-arm/arch-ns9xxx/processor-ns9360.h
++ *
++ * Copyright (C) 2007 by Digi International Inc.
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ */
++#ifndef __ASM_ARCH_PROCESSORNS9360_H
++#define __ASM_ARCH_PROCESSORNS9360_H
++
++#include <linux/init.h>
++
++void ns9360_reset(char mode);
++
++unsigned long ns9360_systemclock(void) __attribute__((const));
++
++static inline unsigned long ns9360_cpuclock(void) __attribute__((const));
++static inline unsigned long ns9360_cpuclock(void)
++{
++ return ns9360_systemclock() / 2;
++}
++
++void __init ns9360_map_io(void);
++
++extern struct sys_timer ns9360_timer;
++
++int ns9360_gpio_configure(unsigned gpio, int inv, int func);
++
++#endif /* ifndef __ASM_ARCH_PROCESSORNS9360_H */
+diff --git a/include/asm-arm/arch-ns9xxx/processor.h b/include/asm-arm/arch-ns9xxx/processor.h
+index 223e51b..f7b53b6 100644
+--- a/include/asm-arm/arch-ns9xxx/processor.h
++++ b/include/asm-arm/arch-ns9xxx/processor.h
+@@ -1,7 +1,7 @@
+ /*
+ * include/asm-arm/arch-ns9xxx/processor.h
+ *
+- * Copyright (C) 2006 by Digi International Inc.
++ * Copyright (C) 2006,2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+@@ -11,9 +11,32 @@
+ #ifndef __ASM_ARCH_PROCESSOR_H
+ #define __ASM_ARCH_PROCESSOR_H
+
+-#include <asm/mach-types.h>
++#include <asm/arch-ns9xxx/module.h>
+
+-#define processor_is_ns9360() (machine_is_cc9p9360dev() \
+- || machine_is_cc9p9360js())
++#define processor_is_ns9210() (0 \
++ || module_is_cc7ucamry() \
++ || module_is_cc9p9210() \
++ || module_is_inc20otter() \
++ || module_is_otter() \
++ )
++
++#define processor_is_ns9215() (0 \
++ || module_is_cc9p9215() \
++ )
++
++#define processor_is_ns9360() (0 \
++ || module_is_cc9p9360() \
++ || module_is_cc9c() \
++ || module_is_ccw9c() \
++ )
++
++#define processor_is_ns9750() (0 \
++ || module_is_cc9p9750() \
++ )
++
++#define processor_is_ns921x() (0 \
++ || processor_is_ns9210() \
++ || processor_is_ns9215() \
++ )
+
+ #endif /* ifndef __ASM_ARCH_PROCESSOR_H */
+diff --git a/include/asm-arm/arch-ns9xxx/regs-sys-common.h b/include/asm-arm/arch-ns9xxx/regs-sys-common.h
+new file mode 100644
+index 0000000..956c57c
+--- /dev/null
++++ b/include/asm-arm/arch-ns9xxx/regs-sys-common.h
+@@ -0,0 +1,31 @@
++/*
++ * include/asm-arm/arch-ns9xxx/regs-sys-common.h
++ *
++ * Copyright (C) 2007 by Digi International Inc.
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ */
++
++#ifndef __ASM_ARCH_REGSSYSCOMMON_H
++#define __ASM_ARCH_REGSSYSCOMMON_H
++#include <asm/hardware.h>
++
++/* Interrupt Vector Address Register Level x */
++#define SYS_IVA(x) __REG2(0xa09000c4, (x))
++
++/* Interrupt Configuration registers */
++#define SYS_IC(x) __REG2(0xa0900144, (x))
++
++/* ISRADDR */
++#define SYS_ISRADDR __REG(0xa0900164)
++
++/* Interrupt Status Active */
++#define SYS_ISA __REG(0xa0900168)
++
++/* Interrupt Status Raw */
++#define SYS_ISR __REG(0xa090016c)
++
++#endif /* ifndef __ASM_ARCH_REGSSYSCOMMON_H */
+diff --git a/include/asm-arm/arch-ns9xxx/regs-sys-ns9360.h b/include/asm-arm/arch-ns9xxx/regs-sys-ns9360.h
+new file mode 100644
+index 0000000..318b694
+--- /dev/null
++++ b/include/asm-arm/arch-ns9xxx/regs-sys-ns9360.h
+@@ -0,0 +1,148 @@
++/*
++ * include/asm-arm/arch-ns9xxx/regs-sys-ns9360.h
++ *
++ * Copyright (C) 2006,2007 by Digi International Inc.
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ */
++#ifndef __ASM_ARCH_REGSSYSNS9360_H
++#define __ASM_ARCH_REGSSYSNS9360_H
++
++#include <asm/hardware.h>
++
++/* System Control Module */
++
++/* AHB Arbiter Gen Configuration */
++#define SYS_AHBAGENCONF __REG(0xa0900000)
++
++/* BRC */
++#define SYS_BRC(x) __REG2(0xa0900004, (x))
++
++/* Timer x Reload Count register */
++#define SYS_TRC(x) __REG2(0xa0900044, (x))
++
++/* Timer x Read register */
++#define SYS_TR(x) __REG2(0xa0900084, (x))
++
++/* Timer Interrupt Status register */
++#define SYS_TIS __REG(0xa0900170)
++
++/* PLL Configuration register */
++#define SYS_PLL __REG(0xa0900188)
++
++/* PLL FS status */
++#define SYS_PLL_FS __REGBITS(24, 23)
++
++/* PLL ND status */
++#define SYS_PLL_ND __REGBITS(20, 16)
++
++/* PLL Configuration register: PLL SW change */
++#define SYS_PLL_SWC __REGBIT(15)
++#define SYS_PLL_SWC_NO __REGVAL(SYS_PLL_SWC, 0)
++#define SYS_PLL_SWC_YES __REGVAL(SYS_PLL_SWC, 1)
++
++/* Timer x Control register */
++#define SYS_TC(x) __REG2(0xa0900190, (x))
++
++/* Timer x Control register: Timer enable */
++#define SYS_TCx_TEN __REGBIT(15)
++#define SYS_TCx_TEN_DIS __REGVAL(SYS_TCx_TEN, 0)
++#define SYS_TCx_TEN_EN __REGVAL(SYS_TCx_TEN, 1)
++
++/* Timer x Control register: CPU debug mode */
++#define SYS_TCx_TDBG __REGBIT(10)
++#define SYS_TCx_TDBG_CONT __REGVAL(SYS_TCx_TDBG, 0)
++#define SYS_TCx_TDBG_STOP __REGVAL(SYS_TCx_TDBG, 1)
++
++/* Timer x Control register: Interrupt clear */
++#define SYS_TCx_INTC __REGBIT(9)
++#define SYS_TCx_INTC_UNSET __REGVAL(SYS_TCx_INTC, 0)
++#define SYS_TCx_INTC_SET __REGVAL(SYS_TCx_INTC, 1)
++
++/* Timer x Control register: Timer clock select */
++#define SYS_TCx_TLCS __REGBITS(8, 6)
++#define SYS_TCx_TLCS_CPU __REGVAL(SYS_TCx_TLCS, 0) /* CPU clock */
++#define SYS_TCx_TLCS_DIV2 __REGVAL(SYS_TCx_TLCS, 1) /* CPU clock / 2 */
++#define SYS_TCx_TLCS_DIV4 __REGVAL(SYS_TCx_TLCS, 2) /* CPU clock / 4 */
++#define SYS_TCx_TLCS_DIV8 __REGVAL(SYS_TCx_TLCS, 3) /* CPU clock / 8 */
++#define SYS_TCx_TLCS_DIV16 __REGVAL(SYS_TCx_TLCS, 4) /* CPU clock / 16 */
++#define SYS_TCx_TLCS_DIV32 __REGVAL(SYS_TCx_TLCS, 5) /* CPU clock / 32 */
++#define SYS_TCx_TLCS_DIV64 __REGVAL(SYS_TCx_TLCS, 6) /* CPU clock / 64 */
++#define SYS_TCx_TLCS_EXT __REGVAL(SYS_TCx_TLCS, 7)
++
++/* Timer x Control register: Timer mode */
++#define SYS_TCx_TM __REGBITS(5, 4)
++#define SYS_TCx_TM_IEE __REGVAL(SYS_TCx_TM, 0) /* Internal timer or external event */
++#define SYS_TCx_TM_ELL __REGVAL(SYS_TCx_TM, 1) /* External low-level, gated timer */
++#define SYS_TCx_TM_EHL __REGVAL(SYS_TCx_TM, 2) /* External high-level, gated timer */
++#define SYS_TCx_TM_CONCAT __REGVAL(SYS_TCx_TM, 3) /* Concatenate the lower timer. */
++
++/* Timer x Control register: Interrupt select */
++#define SYS_TCx_INTS __REGBIT(3)
++#define SYS_TCx_INTS_DIS __REGVAL(SYS_TCx_INTS, 0)
++#define SYS_TCx_INTS_EN __REGVAL(SYS_TCx_INTS, 1)
++
++/* Timer x Control register: Up/down select */
++#define SYS_TCx_UDS __REGBIT(2)
++#define SYS_TCx_UDS_UP __REGVAL(SYS_TCx_UDS, 0)
++#define SYS_TCx_UDS_DOWN __REGVAL(SYS_TCx_UDS, 1)
++
++/* Timer x Control register: 32- or 16-bit timer */
++#define SYS_TCx_TSZ __REGBIT(1)
++#define SYS_TCx_TSZ_16 __REGVAL(SYS_TCx_TSZ, 0)
++#define SYS_TCx_TSZ_32 __REGVAL(SYS_TCx_TSZ, 1)
++
++/* Timer x Control register: Reload enable */
++#define SYS_TCx_REN __REGBIT(0)
++#define SYS_TCx_REN_DIS __REGVAL(SYS_TCx_REN, 0)
++#define SYS_TCx_REN_EN __REGVAL(SYS_TCx_REN, 1)
++
++/* System Memory Chip Select x Dynamic Memory Base */
++#define SYS_SMCSDMB(x) __REG2(0xa09001d0, (x) << 1)
++
++/* System Memory Chip Select x Dynamic Memory Mask */
++#define SYS_SMCSDMM(x) __REG2(0xa09001d4, (x) << 1)
++
++/* System Memory Chip Select x Static Memory Base */
++#define SYS_SMCSSMB(x) __REG2(0xa09001f0, (x) << 1)
++
++/* System Memory Chip Select x Static Memory Base: Chip select x base */
++#define SYS_SMCSSMB_CSxB __REGBITS(31, 12)
++
++/* System Memory Chip Select x Static Memory Mask */
++#define SYS_SMCSSMM(x) __REG2(0xa09001f4, (x) << 1)
++
++/* System Memory Chip Select x Static Memory Mask: Chip select x mask */
++#define SYS_SMCSSMM_CSxM __REGBITS(31, 12)
++
++/* System Memory Chip Select x Static Memory Mask: Chip select x enable */
++#define SYS_SMCSSMM_CSEx __REGBIT(0)
++#define SYS_SMCSSMM_CSEx_DIS __REGVAL(SYS_SMCSSMM_CSEx, 0)
++#define SYS_SMCSSMM_CSEx_EN __REGVAL(SYS_SMCSSMM_CSEx, 1)
++
++/* General purpose, user-defined ID register */
++#define SYS_GENID __REG(0xa0900210)
++
++/* External Interrupt x Control register */
++#define SYS_EIC(x) __REG2(0xa0900214, (x))
++
++/* External Interrupt x Control register: Status */
++#define SYS_EIC_STS __REGBIT(3)
++
++/* External Interrupt x Control register: Clear */
++#define SYS_EIC_CLR __REGBIT(2)
++
++/* External Interrupt x Control register: Polarity */
++#define SYS_EIC_PLTY __REGBIT(1)
++#define SYS_EIC_PLTY_AH __REGVAL(SYS_EIC_PLTY, 0)
++#define SYS_EIC_PLTY_AL __REGVAL(SYS_EIC_PLTY, 1)
++
++/* External Interrupt x Control register: Level edge */
++#define SYS_EIC_LVEDG __REGBIT(0)
++#define SYS_EIC_LVEDG_LEVEL __REGVAL(SYS_EIC_LVEDG, 0)
++#define SYS_EIC_LVEDG_EDGE __REGVAL(SYS_EIC_LVEDG, 1)
++
++#endif /* ifndef __ASM_ARCH_REGSSYSNS9360_H */
+diff --git a/include/asm-arm/arch-ns9xxx/regs-sys.h b/include/asm-arm/arch-ns9xxx/regs-sys.h
+deleted file mode 100644
+index 749262f..0000000
+--- a/include/asm-arm/arch-ns9xxx/regs-sys.h
++++ /dev/null
+@@ -1,163 +0,0 @@
+-/*
+- * include/asm-arm/arch-ns9xxx/regs-sys.h
+- *
+- * Copyright (C) 2006 by Digi International Inc.
+- * All rights reserved.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License version 2 as published by
+- * the Free Software Foundation.
+- */
+-#ifndef __ASM_ARCH_REGSSYS_H
+-#define __ASM_ARCH_REGSSYS_H
+-
+-#include <asm/hardware.h>
+-
+-/* System Control Module */
+-
+-/* AHB Arbiter Gen Configuration */
+-#define SYS_AHBAGENCONF __REG(0xa0900000)
+-
+-/* BRC */
+-#define SYS_BRC(x) __REG2(0xa0900004, (x))
+-
+-/* Timer x Reload Count register */
+-#define SYS_TRC(x) __REG2(0xa0900044, (x))
+-
+-/* Timer x Read register */
+-#define SYS_TR(x) __REG2(0xa0900084, (x))
+-
+-/* Interrupt Vector Address Register Level x */
+-#define SYS_IVA(x) __REG2(0xa09000c4, (x))
+-
+-/* Interrupt Configuration registers */
+-#define SYS_IC(x) __REG2(0xa0900144, (x))
+-
+-/* ISRADDR */
+-#define SYS_ISRADDR __REG(0xa0900164)
+-
+-/* Interrupt Status Active */
+-#define SYS_ISA __REG(0xa0900168)
+-
+-/* Interrupt Status Raw */
+-#define SYS_ISR __REG(0xa090016c)
+-
+-/* Timer Interrupt Status register */
+-#define SYS_TIS __REG(0xa0900170)
+-
+-/* PLL Configuration register */
+-#define SYS_PLL __REG(0xa0900188)
+-
+-/* PLL FS status */
+-#define SYS_PLL_FS __REGBITS(24, 23)
+-
+-/* PLL ND status */
+-#define SYS_PLL_ND __REGBITS(20, 16)
+-
+-/* PLL Configuration register: PLL SW change */
+-#define SYS_PLL_SWC __REGBIT(15)
+-#define SYS_PLL_SWC_NO __REGVAL(SYS_PLL_SWC, 0)
+-#define SYS_PLL_SWC_YES __REGVAL(SYS_PLL_SWC, 1)
+-
+-/* Timer x Control register */
+-#define SYS_TC(x) __REG2(0xa0900190, (x))
+-
+-/* Timer x Control register: Timer enable */
+-#define SYS_TCx_TEN __REGBIT(15)
+-#define SYS_TCx_TEN_DIS __REGVAL(SYS_TCx_TEN, 0)
+-#define SYS_TCx_TEN_EN __REGVAL(SYS_TCx_TEN, 1)
+-
+-/* Timer x Control register: CPU debug mode */
+-#define SYS_TCx_TDBG __REGBIT(10)
+-#define SYS_TCx_TDBG_CONT __REGVAL(SYS_TCx_TDBG, 0)
+-#define SYS_TCx_TDBG_STOP __REGVAL(SYS_TCx_TDBG, 1)
+-
+-/* Timer x Control register: Interrupt clear */
+-#define SYS_TCx_INTC __REGBIT(9)
+-#define SYS_TCx_INTC_UNSET __REGVAL(SYS_TCx_INTC, 0)
+-#define SYS_TCx_INTC_SET __REGVAL(SYS_TCx_INTC, 1)
+-
+-/* Timer x Control register: Timer clock select */
+-#define SYS_TCx_TLCS __REGBITS(8, 6)
+-#define SYS_TCx_TLCS_CPU __REGVAL(SYS_TCx_TLCS, 0) /* CPU clock */
+-#define SYS_TCx_TLCS_DIV2 __REGVAL(SYS_TCx_TLCS, 1) /* CPU clock / 2 */
+-#define SYS_TCx_TLCS_DIV4 __REGVAL(SYS_TCx_TLCS, 2) /* CPU clock / 4 */
+-#define SYS_TCx_TLCS_DIV8 __REGVAL(SYS_TCx_TLCS, 3) /* CPU clock / 8 */
+-#define SYS_TCx_TLCS_DIV16 __REGVAL(SYS_TCx_TLCS, 4) /* CPU clock / 16 */
+-#define SYS_TCx_TLCS_DIV32 __REGVAL(SYS_TCx_TLCS, 5) /* CPU clock / 32 */
+-#define SYS_TCx_TLCS_DIV64 __REGVAL(SYS_TCx_TLCS, 6) /* CPU clock / 64 */
+-#define SYS_TCx_TLCS_EXT __REGVAL(SYS_TCx_TLCS, 7)
+-
+-/* Timer x Control register: Timer mode */
+-#define SYS_TCx_TM __REGBITS(5, 4)
+-#define SYS_TCx_TM_IEE __REGVAL(SYS_TCx_TM, 0) /* Internal timer or external event */
+-#define SYS_TCx_TM_ELL __REGVAL(SYS_TCx_TM, 1) /* External low-level, gated timer */
+-#define SYS_TCx_TM_EHL __REGVAL(SYS_TCx_TM, 2) /* External high-level, gated timer */
+-#define SYS_TCx_TM_CONCAT __REGVAL(SYS_TCx_TM, 3) /* Concatenate the lower timer. */
+-
+-/* Timer x Control register: Interrupt select */
+-#define SYS_TCx_INTS __REGBIT(3)
+-#define SYS_TCx_INTS_DIS __REGVAL(SYS_TCx_INTS, 0)
+-#define SYS_TCx_INTS_EN __REGVAL(SYS_TCx_INTS, 1)
+-
+-/* Timer x Control register: Up/down select */
+-#define SYS_TCx_UDS __REGBIT(2)
+-#define SYS_TCx_UDS_UP __REGVAL(SYS_TCx_UDS, 0)
+-#define SYS_TCx_UDS_DOWN __REGVAL(SYS_TCx_UDS, 1)
+-
+-/* Timer x Control register: 32- or 16-bit timer */
+-#define SYS_TCx_TSZ __REGBIT(1)
+-#define SYS_TCx_TSZ_16 __REGVAL(SYS_TCx_TSZ, 0)
+-#define SYS_TCx_TSZ_32 __REGVAL(SYS_TCx_TSZ, 1)
+-
+-/* Timer x Control register: Reload enable */
+-#define SYS_TCx_REN __REGBIT(0)
+-#define SYS_TCx_REN_DIS __REGVAL(SYS_TCx_REN, 0)
+-#define SYS_TCx_REN_EN __REGVAL(SYS_TCx_REN, 1)
+-
+-/* System Memory Chip Select x Dynamic Memory Base */
+-#define SYS_SMCSDMB(x) __REG2(0xa09001d0, (x) << 1)
+-
+-/* System Memory Chip Select x Dynamic Memory Mask */
+-#define SYS_SMCSDMM(x) __REG2(0xa09001d4, (x) << 1)
+-
+-/* System Memory Chip Select x Static Memory Base */
+-#define SYS_SMCSSMB(x) __REG2(0xa09001f0, (x) << 1)
+-
+-/* System Memory Chip Select x Static Memory Base: Chip select x base */
+-#define SYS_SMCSSMB_CSxB __REGBITS(31, 12)
+-
+-/* System Memory Chip Select x Static Memory Mask */
+-#define SYS_SMCSSMM(x) __REG2(0xa09001f4, (x) << 1)
+-
+-/* System Memory Chip Select x Static Memory Mask: Chip select x mask */
+-#define SYS_SMCSSMM_CSxM __REGBITS(31, 12)
+-
+-/* System Memory Chip Select x Static Memory Mask: Chip select x enable */
+-#define SYS_SMCSSMM_CSEx __REGBIT(0)
+-#define SYS_SMCSSMM_CSEx_DIS __REGVAL(SYS_SMCSSMM_CSEx, 0)
+-#define SYS_SMCSSMM_CSEx_EN __REGVAL(SYS_SMCSSMM_CSEx, 1)
+-
+-/* General purpose, user-defined ID register */
+-#define SYS_GENID __REG(0xa0900210)
+-
+-/* External Interrupt x Control register */
+-#define SYS_EIC(x) __REG2(0xa0900214, (x))
+-
+-/* External Interrupt x Control register: Status */
+-#define SYS_EIC_STS __REGBIT(3)
+-
+-/* External Interrupt x Control register: Clear */
+-#define SYS_EIC_CLR __REGBIT(2)
+-
+-/* External Interrupt x Control register: Polarity */
+-#define SYS_EIC_PLTY __REGBIT(1)
+-#define SYS_EIC_PLTY_AH __REGVAL(SYS_EIC_PLTY, 0)
+-#define SYS_EIC_PLTY_AL __REGVAL(SYS_EIC_PLTY, 1)
+-
+-/* External Interrupt x Control register: Level edge */
+-#define SYS_EIC_LVEDG __REGBIT(0)
+-#define SYS_EIC_LVEDG_LEVEL __REGVAL(SYS_EIC_LVEDG, 0)
+-#define SYS_EIC_LVEDG_EDGE __REGVAL(SYS_EIC_LVEDG, 1)
+-
+-#endif /* ifndef __ASM_ARCH_REGSSYS_H */
+diff --git a/include/asm-arm/arch-ns9xxx/system.h b/include/asm-arm/arch-ns9xxx/system.h
+index c1082bd..1348073 100644
+--- a/include/asm-arm/arch-ns9xxx/system.h
++++ b/include/asm-arm/arch-ns9xxx/system.h
+@@ -1,7 +1,7 @@
+ /*
+ * include/asm-arm/arch-ns9xxx/system.h
+ *
+- * Copyright (C) 2006 by Digi International Inc.
++ * Copyright (C) 2006,2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+@@ -12,8 +12,8 @@
+ #define __ASM_ARCH_SYSTEM_H
+
+ #include <asm/proc-fns.h>
+-#include <asm/arch-ns9xxx/regs-sys.h>
+-#include <asm/mach-types.h>
++#include <asm/arch-ns9xxx/processor.h>
++#include <asm/arch-ns9xxx/processor-ns9360.h>
+
+ static inline void arch_idle(void)
+ {
+@@ -22,11 +22,12 @@ static inline void arch_idle(void)
+
+ static inline void arch_reset(char mode)
+ {
+- u32 reg;
+-
+- reg = __raw_readl(SYS_PLL) >> 16;
+- REGSET(reg, SYS_PLL, SWC, YES);
+- __raw_writel(reg, SYS_PLL);
++#ifdef CONFIG_PROCESSOR_NS9360
++ if (processor_is_ns9360())
++ ns9360_reset(mode);
++ else
++#endif
++ BUG();
+
+ BUG();
+ }
+diff --git a/include/asm-arm/arch-ns9xxx/uncompress.h b/include/asm-arm/arch-ns9xxx/uncompress.h
+index 961ca7d..71066ba 100644
+--- a/include/asm-arm/arch-ns9xxx/uncompress.h
++++ b/include/asm-arm/arch-ns9xxx/uncompress.h
+@@ -11,20 +11,149 @@
+ #ifndef __ASM_ARCH_UNCOMPRESS_H
+ #define __ASM_ARCH_UNCOMPRESS_H
+
+-static void putc(char c)
++#include <asm/io.h>
++
++#define __REG(x) ((void __iomem __force *)(x))
++
++static void putc_dummy(char c, void __iomem *base)
+ {
+- volatile u8 *base = (volatile u8 *)0x40000000;
+- int t = 0x10000;
++ /* nothing */
++}
+
++static void putc_ns9360(char c, void __iomem *base)
++{
++ static int t = 0x10000;
++ do {
++ if (t)
++ --t;
++
++ if (__raw_readl(base + 8) & (1 << 3)) {
++ __raw_writeb(c, base + 16);
++ t = 0x10000;
++ break;
++ }
++ } while (t);
++}
++
++static void putc_a9m9750dev(char c, void __iomem *base)
++{
++ static int t = 0x10000;
++ do {
++ if (t)
++ --t;
++
++ if (__raw_readb(base + 5) & (1 << 5)) {
++ __raw_writeb(c, base);
++ t = 0x10000;
++ break;
++ }
++ } while (t);
++
++}
++
++static void putc_ns921x(char c, void __iomem *base)
++{
++ static int t = 0x10000;
+ do {
+- if (base[5] & 0x20) {
+- base[0] = c;
++ if (t)
++ --t;
++
++ if (!(__raw_readl(base) & (1 << 11))) {
++ __raw_writeb(c, base + 0x0028);
++ t = 0x10000;
+ break;
+ }
+- } while (--t);
++ } while (t);
+ }
+
+-#define arch_decomp_setup()
++#define MSCS __REG(0xA0900184)
++
++#define NS9360_UARTA __REG(0x90200040)
++#define NS9360_UARTB __REG(0x90200000)
++#define NS9360_UARTC __REG(0x90300000)
++#define NS9360_UARTD __REG(0x90300040)
++
++#define NS9360_UART_ENABLED(base) \
++ (__raw_readl(NS9360_UARTA) & (1 << 31))
++
++#define A9M9750DEV_UARTA __REG(0x40000000)
++
++#define NS921XSYS_CLOCK __REG(0xa090017c)
++#define NS921X_UARTA __REG(0x90010000)
++#define NS921X_UARTB __REG(0x90018000)
++#define NS921X_UARTC __REG(0x90020000)
++#define NS921X_UARTD __REG(0x90028000)
++
++#define NS921X_UART_ENABLED(base) \
++ (__raw_readl((base) + 0x1000) & (1 << 29))
++
++static void autodetect(void (**putc)(char, void __iomem *), void __iomem **base)
++{
++ if (((__raw_readl(MSCS) >> 16) & 0xfe) == 0x00) {
++ /* ns9360 or ns9750 */
++ if (NS9360_UART_ENABLED(NS9360_UARTA)) {
++ *putc = putc_ns9360;
++ *base = NS9360_UARTA;
++ return;
++ } else if (NS9360_UART_ENABLED(NS9360_UARTB)) {
++ *putc = putc_ns9360;
++ *base = NS9360_UARTB;
++ return;
++ } else if (NS9360_UART_ENABLED(NS9360_UARTC)) {
++ *putc = putc_ns9360;
++ *base = NS9360_UARTC;
++ return;
++ } else if (NS9360_UART_ENABLED(NS9360_UARTD)) {
++ *putc = putc_ns9360;
++ *base = NS9360_UARTD;
++ return;
++ } else if (__raw_readl(__REG(0xa09001f4)) == 0xfffff001) {
++ *putc = putc_a9m9750dev;
++ *base = A9M9750DEV_UARTA;
++ return;
++ }
++ } else if (((__raw_readl(MSCS) >> 16) & 0xfe) == 0x02) {
++ /* ns921x */
++ u32 clock = __raw_readl(NS921XSYS_CLOCK);
++
++ if ((clock & (1 << 1)) &&
++ NS921X_UART_ENABLED(NS921X_UARTA)) {
++ *putc = putc_ns921x;
++ *base = NS921X_UARTA;
++ return;
++ } else if ((clock & (1 << 2)) &&
++ NS921X_UART_ENABLED(NS921X_UARTB)) {
++ *putc = putc_ns921x;
++ *base = NS921X_UARTB;
++ return;
++ } else if ((clock & (1 << 3)) &&
++ NS921X_UART_ENABLED(NS921X_UARTC)) {
++ *putc = putc_ns921x;
++ *base = NS921X_UARTC;
++ return;
++ } else if ((clock & (1 << 4)) &&
++ NS921X_UART_ENABLED(NS921X_UARTD)) {
++ *putc = putc_ns921x;
++ *base = NS921X_UARTD;
++ return;
++ }
++ }
++
++ *putc = putc_dummy;
++}
++
++void (*myputc)(char, void __iomem *);
++void __iomem *base;
++
++static void putc(char c)
++{
++ myputc(c, base);
++}
++
++static void arch_decomp_setup(void)
++{
++ autodetect(&myputc, &base);
++}
+ #define arch_decomp_wdog()
+
+ static void flush(void)
+diff --git a/include/asm-arm/arch-omap/board-osk.h b/include/asm-arm/arch-omap/board-osk.h
+index 2b1a8a4..9492609 100644
+--- a/include/asm-arm/arch-omap/board-osk.h
++++ b/include/asm-arm/arch-omap/board-osk.h
+@@ -32,5 +32,16 @@
+ /* At OMAP5912 OSK the Ethernet is directly connected to CS1 */
+ #define OMAP_OSK_ETHR_START 0x04800300
+
++/* TPS65010 has four GPIOs. nPG and LED2 can be treated like GPIOs with
++ * alternate pin configurations for hardware-controlled blinking.
++ */
++#define OSK_TPS_GPIO_BASE (OMAP_MAX_GPIO_LINES + 16 /* MPUIO */)
++# define OSK_TPS_GPIO_USB_PWR_EN (OSK_TPS_GPIO_BASE + 0)
++# define OSK_TPS_GPIO_LED_D3 (OSK_TPS_GPIO_BASE + 1)
++# define OSK_TPS_GPIO_LAN_RESET (OSK_TPS_GPIO_BASE + 2)
++# define OSK_TPS_GPIO_DSP_PWR_EN (OSK_TPS_GPIO_BASE + 3)
++# define OSK_TPS_GPIO_LED_D9 (OSK_TPS_GPIO_BASE + 4)
++# define OSK_TPS_GPIO_LED_D2 (OSK_TPS_GPIO_BASE + 5)
++
+ #endif /* __ASM_ARCH_OMAP_OSK_H */
+
+diff --git a/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h
+index fa68810..57523bd 100644
+--- a/include/asm-arm/arch-omap/clock.h
++++ b/include/asm-arm/arch-omap/clock.h
+@@ -14,6 +14,35 @@
+ #define __ARCH_ARM_OMAP_CLOCK_H
+
+ struct module;
++struct clk;
++
++#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
++
++struct clksel_rate {
++ u8 div;
++ u32 val;
++ u8 flags;
++};
++
++struct clksel {
++ struct clk *parent;
++ const struct clksel_rate *rates;
++};
++
++struct dpll_data {
++ void __iomem *mult_div1_reg;
++ u32 mult_mask;
++ u32 div1_mask;
++# if defined(CONFIG_ARCH_OMAP3)
++ void __iomem *control_reg;
++ u32 enable_mask;
++ u8 auto_recal_bit;
++ u8 recal_en_bit;
++ u8 recal_st_bit;
++# endif
++};
++
++#endif
+
+ struct clk {
+ struct list_head node;
+@@ -25,8 +54,6 @@ struct clk {
+ __u32 flags;
+ void __iomem *enable_reg;
+ __u8 enable_bit;
+- __u8 rate_offset;
+- __u8 src_offset;
+ __s8 usecount;
+ void (*recalc)(struct clk *);
+ int (*set_rate)(struct clk *, unsigned long);
+@@ -34,6 +61,16 @@ struct clk {
+ void (*init)(struct clk *);
+ int (*enable)(struct clk *);
+ void (*disable)(struct clk *);
++#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
++ u8 fixed_div;
++ void __iomem *clksel_reg;
++ u32 clksel_mask;
++ const struct clksel *clksel;
++ const struct dpll_data *dpll_data;
++#else
++ __u8 rate_offset;
++ __u8 src_offset;
++#endif
+ };
+
+ struct clk_functions {
+@@ -54,10 +91,12 @@ extern int clk_init(struct clk_functions * custom_clocks);
+ extern int clk_register(struct clk *clk);
+ extern void clk_unregister(struct clk *clk);
+ extern void propagate_rate(struct clk *clk);
++extern void recalculate_root_clocks(void);
+ extern void followparent_recalc(struct clk * clk);
+ extern void clk_allow_idle(struct clk *clk);
+ extern void clk_deny_idle(struct clk *clk);
+ extern int clk_get_usecount(struct clk *clk);
++extern void clk_enable_init_clocks(void);
+
+ /* Clock flags */
+ #define RATE_CKCTL (1 << 0) /* Main fixed ratio clocks */
+@@ -71,21 +110,33 @@ extern int clk_get_usecount(struct clk *clk);
+ #define CLOCK_NO_IDLE_PARENT (1 << 8)
+ #define DELAYED_APP (1 << 9) /* Delay application of clock */
+ #define CONFIG_PARTICIPANT (1 << 10) /* Fundamental clock */
+-#define CM_MPU_SEL1 (1 << 11) /* Domain divider/source */
+-#define CM_DSP_SEL1 (1 << 12)
+-#define CM_GFX_SEL1 (1 << 13)
+-#define CM_MODEM_SEL1 (1 << 14)
+-#define CM_CORE_SEL1 (1 << 15) /* Sets divider for many */
+-#define CM_CORE_SEL2 (1 << 16) /* sets parent for GPT */
+-#define CM_WKUP_SEL1 (1 << 17)
+-#define CM_PLL_SEL1 (1 << 18)
+-#define CM_PLL_SEL2 (1 << 19)
+-#define CM_SYSCLKOUT_SEL1 (1 << 20)
++#define ENABLE_ON_INIT (1 << 11) /* Enable upon framework init */
++#define INVERT_ENABLE (1 << 12) /* 0 enables, 1 disables */
++/* bits 13-20 are currently free */
+ #define CLOCK_IN_OMAP310 (1 << 21)
+ #define CLOCK_IN_OMAP730 (1 << 22)
+ #define CLOCK_IN_OMAP1510 (1 << 23)
+ #define CLOCK_IN_OMAP16XX (1 << 24)
+ #define CLOCK_IN_OMAP242X (1 << 25)
+ #define CLOCK_IN_OMAP243X (1 << 26)
++#define CLOCK_IN_OMAP343X (1 << 27) /* clocks common to all 343X */
++#define PARENT_CONTROLS_CLOCK (1 << 28)
++#define CLOCK_IN_OMAP3430ES1 (1 << 29) /* 3430ES1 clocks only */
++#define CLOCK_IN_OMAP3430ES2 (1 << 30) /* 3430ES2 clocks only */
++
++/* Clksel_rate flags */
++#define DEFAULT_RATE (1 << 0)
++#define RATE_IN_242X (1 << 1)
++#define RATE_IN_243X (1 << 2)
++#define RATE_IN_343X (1 << 3) /* rates common to all 343X */
++#define RATE_IN_3430ES2 (1 << 4) /* 3430ES2 rates only */
++
++#define RATE_IN_24XX (RATE_IN_242X | RATE_IN_243X)
++
++
++/* CM_CLKSEL2_PLL.CORE_CLK_SRC options (24XX) */
++#define CORE_CLK_SRC_32K 0
++#define CORE_CLK_SRC_DPLL 1
++#define CORE_CLK_SRC_DPLL_X2 2
+
+ #endif
+diff --git a/include/asm-arm/arch-omap/control.h b/include/asm-arm/arch-omap/control.h
+new file mode 100644
+index 0000000..9944bb5
+--- /dev/null
++++ b/include/asm-arm/arch-omap/control.h
+@@ -0,0 +1,191 @@
++#ifndef __ASM_ARCH_CONTROL_H
++#define __ASM_ARCH_CONTROL_H
++
++/*
++ * include/asm-arm/arch-omap/control.h
++ *
++ * OMAP2/3 System Control Module definitions
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ * Copyright (C) 2007 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ *
++ * 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.
++ */
++
++#include <asm/arch/io.h>
++
++#define OMAP242X_CTRL_REGADDR(reg) \
++ (void __iomem *)IO_ADDRESS(OMAP242X_CTRL_BASE + (reg))
++#define OMAP243X_CTRL_REGADDR(reg) \
++ (void __iomem *)IO_ADDRESS(OMAP243X_CTRL_BASE + (reg))
++#define OMAP343X_CTRL_REGADDR(reg) \
++ (void __iomem *)IO_ADDRESS(OMAP343X_CTRL_BASE + (reg))
++
++/*
++ * As elsewhere, the "OMAP2_" prefix indicates that the macro is valid for
++ * OMAP24XX and OMAP34XX.
++ */
++
++/* Control submodule offsets */
++
++#define OMAP2_CONTROL_INTERFACE 0x000
++#define OMAP2_CONTROL_PADCONFS 0x030
++#define OMAP2_CONTROL_GENERAL 0x270
++#define OMAP343X_CONTROL_MEM_WKUP 0x600
++#define OMAP343X_CONTROL_PADCONFS_WKUP 0xa00
++#define OMAP343X_CONTROL_GENERAL_WKUP 0xa60
++
++/* Control register offsets - read/write with omap_ctrl_{read,write}{bwl}() */
++
++#define OMAP2_CONTROL_SYSCONFIG (OMAP2_CONTROL_INTERFACE + 0x10)
++
++/* CONTROL_GENERAL register offsets common to OMAP2 & 3 */
++#define OMAP2_CONTROL_DEVCONF0 (OMAP2_CONTROL_GENERAL + 0x0004)
++#define OMAP2_CONTROL_MSUSPENDMUX_0 (OMAP2_CONTROL_GENERAL + 0x0020)
++#define OMAP2_CONTROL_MSUSPENDMUX_1 (OMAP2_CONTROL_GENERAL + 0x0024)
++#define OMAP2_CONTROL_MSUSPENDMUX_2 (OMAP2_CONTROL_GENERAL + 0x0028)
++#define OMAP2_CONTROL_MSUSPENDMUX_3 (OMAP2_CONTROL_GENERAL + 0x002c)
++#define OMAP2_CONTROL_MSUSPENDMUX_4 (OMAP2_CONTROL_GENERAL + 0x0030)
++#define OMAP2_CONTROL_MSUSPENDMUX_5 (OMAP2_CONTROL_GENERAL + 0x0034)
++#define OMAP2_CONTROL_SEC_CTRL (OMAP2_CONTROL_GENERAL + 0x0040)
++#define OMAP2_CONTROL_RPUB_KEY_H_0 (OMAP2_CONTROL_GENERAL + 0x0090)
++#define OMAP2_CONTROL_RPUB_KEY_H_1 (OMAP2_CONTROL_GENERAL + 0x0094)
++#define OMAP2_CONTROL_RPUB_KEY_H_2 (OMAP2_CONTROL_GENERAL + 0x0098)
++#define OMAP2_CONTROL_RPUB_KEY_H_3 (OMAP2_CONTROL_GENERAL + 0x009c)
++
++/* 242x-only CONTROL_GENERAL register offsets */
++#define OMAP242X_CONTROL_DEVCONF OMAP2_CONTROL_DEVCONF0 /* match TRM */
++#define OMAP242X_CONTROL_OCM_RAM_PERM (OMAP2_CONTROL_GENERAL + 0x0068)
++
++/* 243x-only CONTROL_GENERAL register offsets */
++/* CONTROL_IVA2_BOOT{ADDR,MOD} are at the same place on 343x - noted below */
++#define OMAP243X_CONTROL_DEVCONF1 (OMAP2_CONTROL_GENERAL + 0x0078)
++#define OMAP243X_CONTROL_CSIRXFE (OMAP2_CONTROL_GENERAL + 0x007c)
++#define OMAP243X_CONTROL_IVA2_BOOTADDR (OMAP2_CONTROL_GENERAL + 0x0190)
++#define OMAP243X_CONTROL_IVA2_BOOTMOD (OMAP2_CONTROL_GENERAL + 0x0194)
++#define OMAP243X_CONTROL_IVA2_GEMCFG (OMAP2_CONTROL_GENERAL + 0x0198)
++
++/* 24xx-only CONTROL_GENERAL register offsets */
++#define OMAP24XX_CONTROL_DEBOBS (OMAP2_CONTROL_GENERAL + 0x0000)
++#define OMAP24XX_CONTROL_EMU_SUPPORT (OMAP2_CONTROL_GENERAL + 0x0008)
++#define OMAP24XX_CONTROL_SEC_TEST (OMAP2_CONTROL_GENERAL + 0x0044)
++#define OMAP24XX_CONTROL_PSA_CTRL (OMAP2_CONTROL_GENERAL + 0x0048)
++#define OMAP24XX_CONTROL_PSA_CMD (OMAP2_CONTROL_GENERAL + 0x004c)
++#define OMAP24XX_CONTROL_PSA_VALUE (OMAP2_CONTROL_GENERAL + 0x0050)
++#define OMAP24XX_CONTROL_SEC_EMU (OMAP2_CONTROL_GENERAL + 0x0060)
++#define OMAP24XX_CONTROL_SEC_TAP (OMAP2_CONTROL_GENERAL + 0x0064)
++#define OMAP24XX_CONTROL_OCM_PUB_RAM_ADD (OMAP2_CONTROL_GENERAL + 0x006c)
++#define OMAP24XX_CONTROL_EXT_SEC_RAM_START_ADD (OMAP2_CONTROL_GENERAL + 0x0070)
++#define OMAP24XX_CONTROL_EXT_SEC_RAM_STOP_ADD (OMAP2_CONTROL_GENERAL + 0x0074
++#define OMAP24XX_CONTROL_SEC_STATUS (OMAP2_CONTROL_GENERAL + 0x0080)
++#define OMAP24XX_CONTROL_SEC_ERR_STATUS (OMAP2_CONTROL_GENERAL + 0x0084)
++#define OMAP24XX_CONTROL_STATUS (OMAP2_CONTROL_GENERAL + 0x0088)
++#define OMAP24XX_CONTROL_GENERAL_PURPOSE_STATUS (OMAP2_CONTROL_GENERAL + 0x008c)
++#define OMAP24XX_CONTROL_RAND_KEY_0 (OMAP2_CONTROL_GENERAL + 0x00a0)
++#define OMAP24XX_CONTROL_RAND_KEY_1 (OMAP2_CONTROL_GENERAL + 0x00a4)
++#define OMAP24XX_CONTROL_RAND_KEY_2 (OMAP2_CONTROL_GENERAL + 0x00a8)
++#define OMAP24XX_CONTROL_RAND_KEY_3 (OMAP2_CONTROL_GENERAL + 0x00ac)
++#define OMAP24XX_CONTROL_CUST_KEY_0 (OMAP2_CONTROL_GENERAL + 0x00b0)
++#define OMAP24XX_CONTROL_CUST_KEY_1 (OMAP2_CONTROL_GENERAL + 0x00b4)
++#define OMAP24XX_CONTROL_TEST_KEY_0 (OMAP2_CONTROL_GENERAL + 0x00c0)
++#define OMAP24XX_CONTROL_TEST_KEY_1 (OMAP2_CONTROL_GENERAL + 0x00c4)
++#define OMAP24XX_CONTROL_TEST_KEY_2 (OMAP2_CONTROL_GENERAL + 0x00c8)
++#define OMAP24XX_CONTROL_TEST_KEY_3 (OMAP2_CONTROL_GENERAL + 0x00cc)
++#define OMAP24XX_CONTROL_TEST_KEY_4 (OMAP2_CONTROL_GENERAL + 0x00d0)
++#define OMAP24XX_CONTROL_TEST_KEY_5 (OMAP2_CONTROL_GENERAL + 0x00d4)
++#define OMAP24XX_CONTROL_TEST_KEY_6 (OMAP2_CONTROL_GENERAL + 0x00d8)
++#define OMAP24XX_CONTROL_TEST_KEY_7 (OMAP2_CONTROL_GENERAL + 0x00dc)
++#define OMAP24XX_CONTROL_TEST_KEY_8 (OMAP2_CONTROL_GENERAL + 0x00e0)
++#define OMAP24XX_CONTROL_TEST_KEY_9 (OMAP2_CONTROL_GENERAL + 0x00e4)
++
++/* 34xx-only CONTROL_GENERAL register offsets */
++#define OMAP343X_CONTROL_PADCONF_OFF (OMAP2_CONTROL_GENERAL + 0x0000)
++#define OMAP343X_CONTROL_MEM_DFTRW0 (OMAP2_CONTROL_GENERAL + 0x0008)
++#define OMAP343X_CONTROL_MEM_DFTRW1 (OMAP2_CONTROL_GENERAL + 0x000c)
++#define OMAP343X_CONTROL_DEVCONF1 (OMAP2_CONTROL_GENERAL + 0x0068)
++#define OMAP343X_CONTROL_CSIRXFE (OMAP2_CONTROL_GENERAL + 0x006c)
++#define OMAP343X_CONTROL_SEC_STATUS (OMAP2_CONTROL_GENERAL + 0x0070)
++#define OMAP343X_CONTROL_SEC_ERR_STATUS (OMAP2_CONTROL_GENERAL + 0x0074)
++#define OMAP343X_CONTROL_SEC_ERR_STATUS_DEBUG (OMAP2_CONTROL_GENERAL + 0x0078)
++#define OMAP343X_CONTROL_STATUS (OMAP2_CONTROL_GENERAL + 0x0080)
++#define OMAP343X_CONTROL_GENERAL_PURPOSE_STATUS (OMAP2_CONTROL_GENERAL + 0x0084)
++#define OMAP343X_CONTROL_RPUB_KEY_H_4 (OMAP2_CONTROL_GENERAL + 0x00a0)
++#define OMAP343X_CONTROL_RAND_KEY_0 (OMAP2_CONTROL_GENERAL + 0x00a8)
++#define OMAP343X_CONTROL_RAND_KEY_1 (OMAP2_CONTROL_GENERAL + 0x00ac)
++#define OMAP343X_CONTROL_RAND_KEY_2 (OMAP2_CONTROL_GENERAL + 0x00b0)
++#define OMAP343X_CONTROL_RAND_KEY_3 (OMAP2_CONTROL_GENERAL + 0x00b4)
++#define OMAP343X_CONTROL_TEST_KEY_0 (OMAP2_CONTROL_GENERAL + 0x00c8)
++#define OMAP343X_CONTROL_TEST_KEY_1 (OMAP2_CONTROL_GENERAL + 0x00cc)
++#define OMAP343X_CONTROL_TEST_KEY_2 (OMAP2_CONTROL_GENERAL + 0x00d0)
++#define OMAP343X_CONTROL_TEST_KEY_3 (OMAP2_CONTROL_GENERAL + 0x00d4)
++#define OMAP343X_CONTROL_TEST_KEY_4 (OMAP2_CONTROL_GENERAL + 0x00d8)
++#define OMAP343X_CONTROL_TEST_KEY_5 (OMAP2_CONTROL_GENERAL + 0x00dc)
++#define OMAP343X_CONTROL_TEST_KEY_6 (OMAP2_CONTROL_GENERAL + 0x00e0)
++#define OMAP343X_CONTROL_TEST_KEY_7 (OMAP2_CONTROL_GENERAL + 0x00e4)
++#define OMAP343X_CONTROL_TEST_KEY_8 (OMAP2_CONTROL_GENERAL + 0x00e8)
++#define OMAP343X_CONTROL_TEST_KEY_9 (OMAP2_CONTROL_GENERAL + 0x00ec)
++#define OMAP343X_CONTROL_TEST_KEY_10 (OMAP2_CONTROL_GENERAL + 0x00f0)
++#define OMAP343X_CONTROL_TEST_KEY_11 (OMAP2_CONTROL_GENERAL + 0x00f4)
++#define OMAP343X_CONTROL_TEST_KEY_12 (OMAP2_CONTROL_GENERAL + 0x00f8)
++#define OMAP343X_CONTROL_TEST_KEY_13 (OMAP2_CONTROL_GENERAL + 0x00fc)
++#define OMAP343X_CONTROL_IVA2_BOOTADDR (OMAP2_CONTROL_GENERAL + 0x0190)
++#define OMAP343X_CONTROL_IVA2_BOOTMOD (OMAP2_CONTROL_GENERAL + 0x0194)
++
++/*
++ * REVISIT: This list of registers is not comprehensive - there are more
++ * that should be added.
++ */
++
++/*
++ * Control module register bit defines - these should eventually go into
++ * their own regbits file. Some of these will be complicated, depending
++ * on the device type (general-purpose, emulator, test, secure, bad, other)
++ * and the security mode (secure, non-secure, don't care)
++ */
++/* CONTROL_DEVCONF0 bits */
++#define OMAP24XX_USBSTANDBYCTRL (1 << 15)
++#define OMAP2_MCBSP2_CLKS_MASK (1 << 6)
++#define OMAP2_MCBSP1_CLKS_MASK (1 << 2)
++
++/* CONTROL_DEVCONF1 bits */
++#define OMAP2_MCBSP5_CLKS_MASK (1 << 4) /* > 242x */
++#define OMAP2_MCBSP4_CLKS_MASK (1 << 2) /* > 242x */
++#define OMAP2_MCBSP3_CLKS_MASK (1 << 0) /* > 242x */
++
++/* CONTROL_STATUS bits */
++#define OMAP2_DEVICETYPE_MASK (0x7 << 8)
++#define OMAP2_SYSBOOT_5_MASK (1 << 5)
++#define OMAP2_SYSBOOT_4_MASK (1 << 4)
++#define OMAP2_SYSBOOT_3_MASK (1 << 3)
++#define OMAP2_SYSBOOT_2_MASK (1 << 2)
++#define OMAP2_SYSBOOT_1_MASK (1 << 1)
++#define OMAP2_SYSBOOT_0_MASK (1 << 0)
++
++#ifndef __ASSEMBLY__
++#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
++extern void omap_ctrl_base_set(u32 base);
++extern u32 omap_ctrl_base_get(void);
++extern u8 omap_ctrl_readb(u16 offset);
++extern u16 omap_ctrl_readw(u16 offset);
++extern u32 omap_ctrl_readl(u16 offset);
++extern void omap_ctrl_writeb(u8 val, u16 offset);
++extern void omap_ctrl_writew(u16 val, u16 offset);
++extern void omap_ctrl_writel(u32 val, u16 offset);
++#else
++#define omap_ctrl_base_set(x) WARN_ON(1)
++#define omap_ctrl_base_get() 0
++#define omap_ctrl_readb(x) 0
++#define omap_ctrl_readw(x) 0
++#define omap_ctrl_readl(x) 0
++#define omap_ctrl_writeb(x, y) WARN_ON(1)
++#define omap_ctrl_writew(x, y) WARN_ON(1)
++#define omap_ctrl_writel(x, y) WARN_ON(1)
++#endif
++#endif /* __ASSEMBLY__ */
++
++#endif /* __ASM_ARCH_CONTROL_H */
++
+diff --git a/include/asm-arm/arch-omap/entry-macro.S b/include/asm-arm/arch-omap/entry-macro.S
+index f6967c8..74cd572 100644
+--- a/include/asm-arm/arch-omap/entry-macro.S
++++ b/include/asm-arm/arch-omap/entry-macro.S
+@@ -68,7 +68,7 @@
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+- ldr \base, =VA_IC_BASE
++ ldr \base, =OMAP2_VA_IC_BASE
+ ldr \irqnr, [\base, #0x98] /* IRQ pending reg 1 */
+ cmp \irqnr, #0x0
+ bne 2222f
+diff --git a/include/asm-arm/arch-omap/gpio.h b/include/asm-arm/arch-omap/gpio.h
+index 164da09..86621a0 100644
+--- a/include/asm-arm/arch-omap/gpio.h
++++ b/include/asm-arm/arch-omap/gpio.h
+@@ -82,62 +82,35 @@ extern void omap_set_gpio_debounce_time(int gpio, int enable);
+
+ /*-------------------------------------------------------------------------*/
+
+-/* wrappers for "new style" GPIO calls. the old OMAP-specfic ones should
+- * eventually be removed (along with this errno.h inclusion), and maybe
+- * gpios should put MPUIOs last too.
++/* Wrappers for "new style" GPIO calls, using the new infrastructure
++ * which lets us plug in FPGA, I2C, and other implementations.
++ * *
++ * The original OMAP-specfic calls should eventually be removed.
+ */
+
+-#include <asm/errno.h>
+-
+-static inline int gpio_request(unsigned gpio, const char *label)
+-{
+- return omap_request_gpio(gpio);
+-}
+-
+-static inline void gpio_free(unsigned gpio)
+-{
+- omap_free_gpio(gpio);
+-}
+-
+-static inline int __gpio_set_direction(unsigned gpio, int is_input)
+-{
+- if (cpu_class_is_omap2()) {
+- if (gpio > OMAP_MAX_GPIO_LINES)
+- return -EINVAL;
+- } else {
+- if (gpio > (OMAP_MAX_GPIO_LINES + 16 /* MPUIO */))
+- return -EINVAL;
+- }
+- omap_set_gpio_direction(gpio, is_input);
+- return 0;
+-}
+-
+-static inline int gpio_direction_input(unsigned gpio)
+-{
+- return __gpio_set_direction(gpio, 1);
+-}
+-
+-static inline int gpio_direction_output(unsigned gpio, int value)
+-{
+- omap_set_gpio_dataout(gpio, value);
+- return __gpio_set_direction(gpio, 0);
+-}
++#include <linux/errno.h>
++#include <asm-generic/gpio.h>
+
+ static inline int gpio_get_value(unsigned gpio)
+ {
+- return omap_get_gpio_datain(gpio);
++ return __gpio_get_value(gpio);
+ }
+
+ static inline void gpio_set_value(unsigned gpio, int value)
+ {
+- omap_set_gpio_dataout(gpio, value);
++ __gpio_set_value(gpio, value);
+ }
+
+-#include <asm-generic/gpio.h> /* cansleep wrappers */
++static inline int gpio_cansleep(unsigned gpio)
++{
++ return __gpio_cansleep(gpio);
++}
+
+ static inline int gpio_to_irq(unsigned gpio)
+ {
+- return OMAP_GPIO_IRQ(gpio);
++ if (gpio < (OMAP_MAX_GPIO_LINES + 16))
++ return OMAP_GPIO_IRQ(gpio);
++ return -EINVAL;
+ }
+
+ static inline int irq_to_gpio(unsigned irq)
+diff --git a/include/asm-arm/arch-omap/io.h b/include/asm-arm/arch-omap/io.h
+index 289082d..160578e 100644
+--- a/include/asm-arm/arch-omap/io.h
++++ b/include/asm-arm/arch-omap/io.h
+@@ -80,6 +80,13 @@
+ #define OMAP243X_GPMC_PHYS OMAP243X_GPMC_BASE /* 0x49000000 */
+ #define OMAP243X_GPMC_VIRT 0xFE000000
+ #define OMAP243X_GPMC_SIZE SZ_1M
++#define OMAP243X_SDRC_PHYS OMAP243X_SDRC_BASE
++#define OMAP243X_SDRC_VIRT 0xFD000000
++#define OMAP243X_SDRC_SIZE SZ_1M
++#define OMAP243X_SMS_PHYS OMAP243X_SMS_BASE
++#define OMAP243X_SMS_VIRT 0xFC000000
++#define OMAP243X_SMS_SIZE SZ_1M
++
+ #endif
+
+ #define IO_OFFSET 0x90000000
+@@ -88,16 +95,73 @@
+ #define io_v2p(va) ((va) - IO_OFFSET) /* Works for L3 and L4 */
+
+ /* DSP */
+-#define DSP_MEM_24XX_PHYS OMAP24XX_DSP_MEM_BASE /* 0x58000000 */
++#define DSP_MEM_24XX_PHYS OMAP2420_DSP_MEM_BASE /* 0x58000000 */
+ #define DSP_MEM_24XX_VIRT 0xe0000000
+ #define DSP_MEM_24XX_SIZE 0x28000
+-#define DSP_IPI_24XX_PHYS OMAP24XX_DSP_IPI_BASE /* 0x59000000 */
++#define DSP_IPI_24XX_PHYS OMAP2420_DSP_IPI_BASE /* 0x59000000 */
+ #define DSP_IPI_24XX_VIRT 0xe1000000
+ #define DSP_IPI_24XX_SIZE SZ_4K
+-#define DSP_MMU_24XX_PHYS OMAP24XX_DSP_MMU_BASE /* 0x5a000000 */
++#define DSP_MMU_24XX_PHYS OMAP2420_DSP_MMU_BASE /* 0x5a000000 */
+ #define DSP_MMU_24XX_VIRT 0xe2000000
+ #define DSP_MMU_24XX_SIZE SZ_4K
+
++#elif defined(CONFIG_ARCH_OMAP3)
++
++/* We map both L3 and L4 on OMAP3 */
++#define L3_34XX_PHYS L3_34XX_BASE /* 0x68000000 */
++#define L3_34XX_VIRT 0xf8000000
++#define L3_34XX_SIZE SZ_1M /* 44kB of 128MB used, want 1MB sect */
++
++#define L4_34XX_PHYS L4_34XX_BASE /* 0x48000000 */
++#define L4_34XX_VIRT 0xd8000000
++#define L4_34XX_SIZE SZ_4M /* 1MB of 128MB used, want 1MB sect */
++
++/*
++ * Need to look at the Size 4M for L4.
++ * VPOM3430 was not working for Int controller
++ */
++
++#define L4_WK_34XX_PHYS L4_WK_34XX_BASE /* 0x48300000 */
++#define L4_WK_34XX_VIRT 0xd8300000
++#define L4_WK_34XX_SIZE SZ_1M
++
++#define L4_PER_34XX_PHYS L4_PER_34XX_BASE /* 0x49000000 */
++#define L4_PER_34XX_VIRT 0xd9000000
++#define L4_PER_34XX_SIZE SZ_1M
++
++#define L4_EMU_34XX_PHYS L4_EMU_34XX_BASE /* 0x54000000 */
++#define L4_EMU_34XX_VIRT 0xe4000000
++#define L4_EMU_34XX_SIZE SZ_64M
++
++#define OMAP34XX_GPMC_PHYS OMAP34XX_GPMC_BASE /* 0x6E000000 */
++#define OMAP34XX_GPMC_VIRT 0xFE000000
++#define OMAP34XX_GPMC_SIZE SZ_1M
++
++#define OMAP343X_SMS_PHYS OMAP343X_SMS_BASE /* 0x6C000000 */
++#define OMAP343X_SMS_VIRT 0xFC000000
++#define OMAP343X_SMS_SIZE SZ_1M
++
++#define OMAP343X_SDRC_PHYS OMAP343X_SDRC_BASE /* 0x6D000000 */
++#define OMAP343X_SDRC_VIRT 0xFD000000
++#define OMAP343X_SDRC_SIZE SZ_1M
++
++
++#define IO_OFFSET 0x90000000
++#define IO_ADDRESS(pa) ((pa) + IO_OFFSET)/* Works for L3 and L4 */
++#define io_p2v(pa) ((pa) + IO_OFFSET)/* Works for L3 and L4 */
++#define io_v2p(va) ((va) - IO_OFFSET)/* Works for L3 and L4 */
++
++/* DSP */
++#define DSP_MEM_34XX_PHYS OMAP34XX_DSP_MEM_BASE /* 0x58000000 */
++#define DSP_MEM_34XX_VIRT 0xe0000000
++#define DSP_MEM_34XX_SIZE 0x28000
++#define DSP_IPI_34XX_PHYS OMAP34XX_DSP_IPI_BASE /* 0x59000000 */
++#define DSP_IPI_34XX_VIRT 0xe1000000
++#define DSP_IPI_34XX_SIZE SZ_4K
++#define DSP_MMU_34XX_PHYS OMAP34XX_DSP_MMU_BASE /* 0x5a000000 */
++#define DSP_MMU_34XX_VIRT 0xe2000000
++#define DSP_MMU_34XX_SIZE SZ_4K
++
+ #endif
+
+ #ifndef __ASSEMBLER__
+diff --git a/include/asm-arm/arch-omap/mmc.h b/include/asm-arm/arch-omap/mmc.h
+index b70e37b..c9588f4 100644
+--- a/include/asm-arm/arch-omap/mmc.h
++++ b/include/asm-arm/arch-omap/mmc.h
+@@ -18,6 +18,8 @@
+ #define OMAP_MMC_MAX_SLOTS 2
+
+ struct omap_mmc_platform_data {
++ struct omap_mmc_conf conf;
++
+ unsigned enabled:1;
+ /* number of slots on board */
+ unsigned nr_slots:2;
+diff --git a/include/asm-arm/arch-omap/mux.h b/include/asm-arm/arch-omap/mux.h
+index b8fff50..ff9a5b5 100644
+--- a/include/asm-arm/arch-omap/mux.h
++++ b/include/asm-arm/arch-omap/mux.h
+@@ -4,9 +4,10 @@
+ * Table of the Omap register configurations for the FUNC_MUX and
+ * PULL_DWN combinations.
+ *
+- * Copyright (C) 2003 - 2005 Nokia Corporation
++ * Copyright (C) 2004 - 2008 Texas Instruments Inc.
++ * Copyright (C) 2003 - 2008 Nokia Corporation
+ *
+- * Written by Tony Lindgren <tony.lindgren at nokia.com>
++ * Written by Tony Lindgren
+ *
+ * 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
+@@ -27,14 +28,6 @@
+ * - W8 = ball
+ * - 1610 = 1510 or 1610, none if common for both 1510 and 1610
+ * - MMC2_DAT0 = function
+- *
+- * Change log:
+- * Added entry for the I2C interface. (02Feb 2004)
+- * Copyright (C) 2004 Texas Instruments
+- *
+- * Added entry for the keypad and uwire CS1. (09Mar 2004)
+- * Copyright (C) 2004 Texas Instruments
+- *
+ */
+
+ #ifndef __ASM_ARCH_MUX_H
+@@ -469,7 +462,12 @@ enum omap24xx_index {
+ AA8_242X_GPIO58,
+ Y20_24XX_GPIO60,
+ W4__24XX_GPIO74,
++ N15_24XX_GPIO85,
+ M15_24XX_GPIO92,
++ P20_24XX_GPIO93,
++ P18_24XX_GPIO95,
++ M18_24XX_GPIO96,
++ L14_24XX_GPIO97,
+ J15_24XX_GPIO99,
+ V14_24XX_GPIO117,
+ P14_24XX_GPIO125,
+@@ -494,8 +492,6 @@ enum omap24xx_index {
+ D3_242X_DMAREQ4,
+ E3_242X_DMAREQ5,
+
+- P20_24XX_TSC_IRQ,
+-
+ /* UART3 */
+ K15_24XX_UART3_TX,
+ K14_24XX_UART3_RX,
+@@ -557,13 +553,57 @@ enum omap24xx_index {
+ B3__24XX_KBR5,
+ AA4_24XX_KBC2,
+ B13_24XX_KBC6,
++
++ /* 2430 USB */
++ AD9_2430_USB0_PUEN,
++ Y11_2430_USB0_VP,
++ AD7_2430_USB0_VM,
++ AE7_2430_USB0_RCV,
++ AD4_2430_USB0_TXEN,
++ AF9_2430_USB0_SE0,
++ AE6_2430_USB0_DAT,
++ AD24_2430_USB1_SE0,
++ AB24_2430_USB1_RCV,
++ Y25_2430_USB1_TXEN,
++ AA26_2430_USB1_DAT,
++
++ /* 2430 HS-USB */
++ AD9_2430_USB0HS_DATA3,
++ Y11_2430_USB0HS_DATA4,
++ AD7_2430_USB0HS_DATA5,
++ AE7_2430_USB0HS_DATA6,
++ AD4_2430_USB0HS_DATA2,
++ AF9_2430_USB0HS_DATA0,
++ AE6_2430_USB0HS_DATA1,
++ AE8_2430_USB0HS_CLK,
++ AD8_2430_USB0HS_DIR,
++ AE5_2430_USB0HS_STP,
++ AE9_2430_USB0HS_NXT,
++ AC7_2430_USB0HS_DATA7,
++
++ /* 2430 McBSP */
++ AC10_2430_MCBSP2_FSX,
++ AD16_2430_MCBSP2_CLX,
++ AE13_2430_MCBSP2_DX,
++ AD13_2430_MCBSP2_DR,
++ AC10_2430_MCBSP2_FSX_OFF,
++ AD16_2430_MCBSP2_CLX_OFF,
++ AE13_2430_MCBSP2_DX_OFF,
++ AD13_2430_MCBSP2_DR_OFF,
++
++};
++
++struct omap_mux_cfg {
++ struct pin_config *pins;
++ unsigned long size;
++ int (*cfg_reg)(const struct pin_config *cfg);
+ };
+
+ #ifdef CONFIG_OMAP_MUX
+ /* setup pin muxing in Linux */
+ extern int omap1_mux_init(void);
+ extern int omap2_mux_init(void);
+-extern int omap_mux_register(struct pin_config * pins, unsigned long size);
++extern int omap_mux_register(struct omap_mux_cfg *);
+ extern int omap_cfg_reg(unsigned long reg_cfg);
+ #else
+ /* boot loader does it all (no warnings from CONFIG_OMAP_MUX_WARNINGS) */
+diff --git a/include/asm-arm/arch-omap/omap24xx.h b/include/asm-arm/arch-omap/omap24xx.h
+index 14c0f94..b9fcaae 100644
+--- a/include/asm-arm/arch-omap/omap24xx.h
++++ b/include/asm-arm/arch-omap/omap24xx.h
+@@ -1,3 +1,28 @@
++/*
++ * include/asm-arm/arch-omap/omap24xx.h
++ *
++ * This file contains the processor specific definitions
++ * of the TI OMAP24XX.
++ *
++ * Copyright (C) 2007 Texas Instruments.
++ * Copyright (C) 2007 Nokia Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ */
++
+ #ifndef __ASM_ARCH_OMAP24XX_H
+ #define __ASM_ARCH_OMAP24XX_H
+
+@@ -13,33 +38,70 @@
+
+ /* interrupt controller */
+ #define OMAP24XX_IC_BASE (L4_24XX_BASE + 0xfe000)
+-#define VA_IC_BASE IO_ADDRESS(OMAP24XX_IC_BASE)
+ #define OMAP24XX_IVA_INTC_BASE 0x40000000
+ #define IRQ_SIR_IRQ 0x0040
+
+-#ifdef CONFIG_ARCH_OMAP2420
+-#define OMAP24XX_32KSYNCT_BASE (L4_24XX_BASE + 0x4000)
+-#define OMAP24XX_PRCM_BASE (L4_24XX_BASE + 0x8000)
+-#define OMAP24XX_SDRC_BASE (L3_24XX_BASE + 0x9000)
+-#define OMAP242X_CONTROL_STATUS (L4_24XX_BASE + 0x2f8)
+-#endif
++#define OMAP2420_CTRL_BASE L4_24XX_BASE
++#define OMAP2420_32KSYNCT_BASE (L4_24XX_BASE + 0x4000)
++#define OMAP2420_PRCM_BASE (L4_24XX_BASE + 0x8000)
++#define OMAP2420_CM_BASE (L4_24XX_BASE + 0x8000)
++#define OMAP2420_PRM_BASE OMAP2420_CM_BASE
++#define OMAP2420_SDRC_BASE (L3_24XX_BASE + 0x9000)
++#define OMAP2420_SMS_BASE 0x68008000
+
+-#ifdef CONFIG_ARCH_OMAP2430
+-#define OMAP24XX_32KSYNCT_BASE (L4_WK_243X_BASE + 0x20000)
+-#define OMAP24XX_PRCM_BASE (L4_WK_243X_BASE + 0x6000)
+-#define OMAP24XX_SDRC_BASE (0x6D000000)
+-#define OMAP242X_CONTROL_STATUS (L4_24XX_BASE + 0x2f8)
++#define OMAP2430_32KSYNCT_BASE (L4_WK_243X_BASE + 0x20000)
++#define OMAP2430_PRCM_BASE (L4_WK_243X_BASE + 0x6000)
++#define OMAP2430_CM_BASE (L4_WK_243X_BASE + 0x6000)
++#define OMAP2430_PRM_BASE OMAP2430_CM_BASE
++
++#define OMAP243X_SMS_BASE 0x6C000000
++#define OMAP243X_SDRC_BASE 0x6D000000
+ #define OMAP243X_GPMC_BASE 0x6E000000
+-#endif
++#define OMAP243X_SCM_BASE (L4_WK_243X_BASE + 0x2000)
++#define OMAP243X_CTRL_BASE OMAP243X_SCM_BASE
++#define OMAP243X_HS_BASE (L4_24XX_BASE + 0x000ac000)
+
+ /* DSP SS */
+-#define OMAP24XX_DSP_BASE 0x58000000
+-#define OMAP24XX_DSP_MEM_BASE (OMAP24XX_DSP_BASE + 0x0)
+-#define OMAP24XX_DSP_IPI_BASE (OMAP24XX_DSP_BASE + 0x1000000)
+-#define OMAP24XX_DSP_MMU_BASE (OMAP24XX_DSP_BASE + 0x2000000)
++#define OMAP2420_DSP_BASE 0x58000000
++#define OMAP2420_DSP_MEM_BASE (OMAP2420_DSP_BASE + 0x0)
++#define OMAP2420_DSP_IPI_BASE (OMAP2420_DSP_BASE + 0x1000000)
++#define OMAP2420_DSP_MMU_BASE (OMAP2420_DSP_BASE + 0x2000000)
++
++#define OMAP243X_DSP_BASE 0x5C000000
++#define OMAP243X_DSP_MEM_BASE (OMAP243X_DSP_BASE + 0x0)
++#define OMAP243X_DSP_MMU_BASE (OMAP243X_DSP_BASE + 0x1000000)
+
+ /* Mailbox */
+ #define OMAP24XX_MAILBOX_BASE (L4_24XX_BASE + 0x94000)
+
++/* Camera */
++#define OMAP24XX_CAMERA_BASE (L4_24XX_BASE + 0x52000)
++
++/* Security */
++#define OMAP24XX_SEC_BASE (L4_24XX_BASE + 0xA0000)
++#define OMAP24XX_SEC_RNG_BASE (OMAP24XX_SEC_BASE + 0x0000)
++#define OMAP24XX_SEC_DES_BASE (OMAP24XX_SEC_BASE + 0x2000)
++#define OMAP24XX_SEC_SHA1MD5_BASE (OMAP24XX_SEC_BASE + 0x4000)
++#define OMAP24XX_SEC_AES_BASE (OMAP24XX_SEC_BASE + 0x6000)
++#define OMAP24XX_SEC_PKA_BASE (OMAP24XX_SEC_BASE + 0x8000)
++
++#if defined(CONFIG_ARCH_OMAP2420)
++
++#define OMAP2_32KSYNCT_BASE OMAP2420_32KSYNCT_BASE
++#define OMAP2_PRCM_BASE OMAP2420_PRCM_BASE
++#define OMAP2_CM_BASE OMAP2420_CM_BASE
++#define OMAP2_PRM_BASE OMAP2420_PRM_BASE
++#define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP24XX_IC_BASE)
++
++#elif defined(CONFIG_ARCH_OMAP2430)
++
++#define OMAP2_32KSYNCT_BASE OMAP2430_32KSYNCT_BASE
++#define OMAP2_PRCM_BASE OMAP2430_PRCM_BASE
++#define OMAP2_CM_BASE OMAP2430_CM_BASE
++#define OMAP2_PRM_BASE OMAP2430_PRM_BASE
++#define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP24XX_IC_BASE)
++
++#endif
++
+ #endif /* __ASM_ARCH_OMAP24XX_H */
+
+diff --git a/include/asm-arm/arch-omap/sdrc.h b/include/asm-arm/arch-omap/sdrc.h
+new file mode 100644
+index 0000000..673b396
+--- /dev/null
++++ b/include/asm-arm/arch-omap/sdrc.h
+@@ -0,0 +1,75 @@
++#ifndef ____ASM_ARCH_SDRC_H
++#define ____ASM_ARCH_SDRC_H
++
++/*
++ * OMAP2/3 SDRC/SMS register definitions
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ * Copyright (C) 2007 Nokia Corporation
++ *
++ * Written by Paul Walmsley
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <asm/arch/io.h>
++
++/* SDRC register offsets - read/write with sdrc_{read,write}_reg() */
++
++#define SDRC_SYSCONFIG 0x010
++#define SDRC_DLLA_CTRL 0x060
++#define SDRC_DLLA_STATUS 0x064
++#define SDRC_DLLB_CTRL 0x068
++#define SDRC_DLLB_STATUS 0x06C
++#define SDRC_POWER 0x070
++#define SDRC_MR_0 0x084
++#define SDRC_RFR_CTRL_0 0x0a4
++
++/*
++ * These values represent the number of memory clock cycles between
++ * autorefresh initiation. They assume 1 refresh per 64 ms (JEDEC), 8192
++ * rows per device, and include a subtraction of a 50 cycle window in the
++ * event that the autorefresh command is delayed due to other SDRC activity.
++ * The '| 1' sets the ARE field to send one autorefresh when the autorefresh
++ * counter reaches 0.
++ *
++ * These represent optimal values for common parts, it won't work for all.
++ * As long as you scale down, most parameters are still work, they just
++ * become sub-optimal. The RFR value goes in the opposite direction. If you
++ * don't adjust it down as your clock period increases the refresh interval
++ * will not be met. Setting all parameters for complete worst case may work,
++ * but may cut memory performance by 2x. Due to errata the DLLs need to be
++ * unlocked and their value needs run time calibration. A dynamic call is
++ * need for that as no single right value exists acorss production samples.
++ *
++ * Only the FULL speed values are given. Current code is such that rate
++ * changes must be made at DPLLoutx2. The actual value adjustment for low
++ * frequency operation will be handled by omap_set_performance()
++ *
++ * By having the boot loader boot up in the fastest L4 speed available likely
++ * will result in something which you can switch between.
++ */
++#define SDRC_RFR_CTRL_165MHz (0x00044c00 | 1)
++#define SDRC_RFR_CTRL_133MHz (0x0003de00 | 1)
++#define SDRC_RFR_CTRL_100MHz (0x0002da01 | 1)
++#define SDRC_RFR_CTRL_110MHz (0x0002da01 | 1) /* Need to calc */
++#define SDRC_RFR_CTRL_BYPASS (0x00005000 | 1) /* Need to calc */
++
++
++/*
++ * SMS register access
++ */
++
++
++#define OMAP242X_SMS_REGADDR(reg) (void __iomem *)IO_ADDRESS(OMAP2420_SMS_BASE + reg)
++#define OMAP243X_SMS_REGADDR(reg) (void __iomem *)IO_ADDRESS(OMAP243X_SMS_BASE + reg)
++#define OMAP343X_SMS_REGADDR(reg) (void __iomem *)IO_ADDRESS(OMAP343X_SMS_BASE + reg)
++
++/* SMS register offsets - read/write with sms_{read,write}_reg() */
++
++#define SMS_SYSCONFIG 0x010
++/* REVISIT: fill in other SMS registers here */
++
++#endif
+diff --git a/include/asm-arm/arch-omap/usb.h b/include/asm-arm/arch-omap/usb.h
+index 99ae9ea..2147d18 100644
+--- a/include/asm-arm/arch-omap/usb.h
++++ b/include/asm-arm/arch-omap/usb.h
+@@ -132,14 +132,11 @@
+ # define CONF_USB_PWRDN_DP_R (1 << 1)
+
+ /* OMAP2 */
+-#define CONTROL_DEVCONF_REG __REG32(L4_24XX_BASE + 0x0274)
+ # define USB_UNIDIR 0x0
+ # define USB_UNIDIR_TLL 0x1
+ # define USB_BIDIR 0x2
+ # define USB_BIDIR_TLL 0x3
+-# define USBT0WRMODEI(x) ((x) << 22)
+-# define USBT1WRMODEI(x) ((x) << 20)
+-# define USBT2WRMODEI(x) ((x) << 18)
++# define USBTXWRMODEI(port, x) ((x) << (22 - (port * 2)))
+ # define USBT2TLL5PI (1 << 17)
+ # define USB0PUENACTLOI (1 << 16)
+ # define USBSTANDBYCTRL (1 << 15)
+diff --git a/include/asm-arm/arch-orion/debug-macro.S b/include/asm-arm/arch-orion/debug-macro.S
+deleted file mode 100644
+index 2746220..0000000
+--- a/include/asm-arm/arch-orion/debug-macro.S
++++ /dev/null
+@@ -1,22 +0,0 @@
+-/*
+- * linux/include/asm-arm/arch-orion/debug-macro.S
+- *
+- * Debugging macro include header
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+-*/
+-
+-#include <asm/arch/orion.h>
+-
+- .macro addruart,rx
+- mrc p15, 0, \rx, c1, c0
+- tst \rx, #1 @ MMU enabled?
+- ldreq \rx, =ORION_REGS_PHYS_BASE
+- ldrne \rx, =ORION_REGS_VIRT_BASE
+- orr \rx, \rx, #0x00012000
+- .endm
+-
+-#define UART_SHIFT 2
+-#include <asm/hardware/debug-8250.S>
+diff --git a/include/asm-arm/arch-orion/dma.h b/include/asm-arm/arch-orion/dma.h
+deleted file mode 100644
+index 40a8c17..0000000
+--- a/include/asm-arm/arch-orion/dma.h
++++ /dev/null
+@@ -1 +0,0 @@
+-/* empty */
+diff --git a/include/asm-arm/arch-orion/entry-macro.S b/include/asm-arm/arch-orion/entry-macro.S
+deleted file mode 100644
+index cda096b..0000000
+--- a/include/asm-arm/arch-orion/entry-macro.S
++++ /dev/null
+@@ -1,31 +0,0 @@
+-/*
+- * include/asm-arm/arch-orion/entry-macro.S
+- *
+- * Low-level IRQ helper macros for Orion platforms
+- *
+- * This file is licensed under the terms of the GNU General Public
+- * License version 2. This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-
+-#include <asm/arch/orion.h>
+-
+- .macro disable_fiq
+- .endm
+-
+- .macro arch_ret_to_user, tmp1, tmp2
+- .endm
+-
+- .macro get_irqnr_preamble, base, tmp
+- ldr \base, =MAIN_IRQ_CAUSE
+- .endm
+-
+- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+- ldr \irqstat, [\base, #0] @ main cause
+- ldr \tmp, [\base, #(MAIN_IRQ_MASK - MAIN_IRQ_CAUSE)] @ main mask
+- mov \irqnr, #0 @ default irqnr
+- @ find cause bits that are unmasked
+- ands \irqstat, \irqstat, \tmp @ clear Z flag if any
+- clzne \irqnr, \irqstat @ calc irqnr
+- rsbne \irqnr, \irqnr, #31
+- .endm
+diff --git a/include/asm-arm/arch-orion/gpio.h b/include/asm-arm/arch-orion/gpio.h
+deleted file mode 100644
+index d66284f..0000000
+--- a/include/asm-arm/arch-orion/gpio.h
++++ /dev/null
+@@ -1,28 +0,0 @@
+-/*
+- * include/asm-arm/arch-orion/gpio.h
+- *
+- * This file is licensed under the terms of the GNU General Public
+- * License version 2. This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-
+-extern int gpio_request(unsigned pin, const char *label);
+-extern void gpio_free(unsigned pin);
+-extern int gpio_direction_input(unsigned pin);
+-extern int gpio_direction_output(unsigned pin, int value);
+-extern int gpio_get_value(unsigned pin);
+-extern void gpio_set_value(unsigned pin, int value);
+-extern void orion_gpio_set_blink(unsigned pin, int blink);
+-extern void gpio_display(void); /* debug */
+-
+-static inline int gpio_to_irq(int pin)
+-{
+- return pin + IRQ_ORION_GPIO_START;
+-}
+-
+-static inline int irq_to_gpio(int irq)
+-{
+- return irq - IRQ_ORION_GPIO_START;
+-}
+-
+-#include <asm-generic/gpio.h> /* cansleep wrappers */
+diff --git a/include/asm-arm/arch-orion/hardware.h b/include/asm-arm/arch-orion/hardware.h
+deleted file mode 100644
+index 65da374..0000000
+--- a/include/asm-arm/arch-orion/hardware.h
++++ /dev/null
+@@ -1,21 +0,0 @@
+-/*
+- * include/asm-arm/arch-orion/hardware.h
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#ifndef __ASM_ARCH_HARDWARE_H__
+-#define __ASM_ARCH_HARDWARE_H__
+-
+-#include "orion.h"
+-
+-#define pcibios_assign_all_busses() 1
+-
+-#define PCIBIOS_MIN_IO 0x00001000
+-#define PCIBIOS_MIN_MEM 0x01000000
+-#define PCIMEM_BASE ORION_PCIE_MEM_PHYS_BASE
+-
+-
+-#endif
+diff --git a/include/asm-arm/arch-orion/io.h b/include/asm-arm/arch-orion/io.h
+deleted file mode 100644
+index e0b8c39..0000000
+--- a/include/asm-arm/arch-orion/io.h
++++ /dev/null
+@@ -1,27 +0,0 @@
+-/*
+- * include/asm-arm/arch-orion/io.h
+- *
+- * Tzachi Perelstein <tzachi at marvell.com>
+- *
+- * This file is licensed under the terms of the GNU General Public
+- * License version 2. This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-
+-#ifndef __ASM_ARM_ARCH_IO_H
+-#define __ASM_ARM_ARCH_IO_H
+-
+-#include "orion.h"
+-
+-#define IO_SPACE_LIMIT 0xffffffff
+-#define IO_SPACE_REMAP ORION_PCI_SYS_IO_BASE
+-
+-static inline void __iomem *__io(unsigned long addr)
+-{
+- return (void __iomem *)addr;
+-}
+-
+-#define __io(a) __io(a)
+-#define __mem_pci(a) (a)
+-
+-#endif
+diff --git a/include/asm-arm/arch-orion/irqs.h b/include/asm-arm/arch-orion/irqs.h
+deleted file mode 100644
+index eea65ca..0000000
+--- a/include/asm-arm/arch-orion/irqs.h
++++ /dev/null
+@@ -1,61 +0,0 @@
+-/*
+- * include/asm-arm/arch-orion/irqs.h
+- *
+- * IRQ definitions for Orion SoC
+- *
+- * Maintainer: Tzachi Perelstein <tzachi at marvell.com>
+- *
+- * This file is licensed under the terms of the GNU General Public
+- * License version 2. This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-
+-#ifndef __ASM_ARCH_IRQS_H__
+-#define __ASM_ARCH_IRQS_H__
+-
+-#include "orion.h" /* need GPIO_MAX */
+-
+-/*
+- * Orion Main Interrupt Controller
+- */
+-#define IRQ_ORION_BRIDGE 0
+-#define IRQ_ORION_DOORBELL_H2C 1
+-#define IRQ_ORION_DOORBELL_C2H 2
+-#define IRQ_ORION_UART0 3
+-#define IRQ_ORION_UART1 4
+-#define IRQ_ORION_I2C 5
+-#define IRQ_ORION_GPIO_0_7 6
+-#define IRQ_ORION_GPIO_8_15 7
+-#define IRQ_ORION_GPIO_16_23 8
+-#define IRQ_ORION_GPIO_24_31 9
+-#define IRQ_ORION_PCIE0_ERR 10
+-#define IRQ_ORION_PCIE0_INT 11
+-#define IRQ_ORION_USB1_CTRL 12
+-#define IRQ_ORION_DEV_BUS_ERR 14
+-#define IRQ_ORION_PCI_ERR 15
+-#define IRQ_ORION_USB_BR_ERR 16
+-#define IRQ_ORION_USB0_CTRL 17
+-#define IRQ_ORION_ETH_RX 18
+-#define IRQ_ORION_ETH_TX 19
+-#define IRQ_ORION_ETH_MISC 20
+-#define IRQ_ORION_ETH_SUM 21
+-#define IRQ_ORION_ETH_ERR 22
+-#define IRQ_ORION_IDMA_ERR 23
+-#define IRQ_ORION_IDMA_0 24
+-#define IRQ_ORION_IDMA_1 25
+-#define IRQ_ORION_IDMA_2 26
+-#define IRQ_ORION_IDMA_3 27
+-#define IRQ_ORION_CESA 28
+-#define IRQ_ORION_SATA 29
+-#define IRQ_ORION_XOR0 30
+-#define IRQ_ORION_XOR1 31
+-
+-/*
+- * Orion General Purpose Pins
+- */
+-#define IRQ_ORION_GPIO_START 32
+-#define NR_GPIO_IRQS GPIO_MAX
+-
+-#define NR_IRQS (IRQ_ORION_GPIO_START + NR_GPIO_IRQS)
+-
+-#endif /* __ASM_ARCH_IRQS_H__ */
+diff --git a/include/asm-arm/arch-orion/memory.h b/include/asm-arm/arch-orion/memory.h
+deleted file mode 100644
+index d954dba..0000000
+--- a/include/asm-arm/arch-orion/memory.h
++++ /dev/null
+@@ -1,15 +0,0 @@
+-/*
+- * include/asm-arm/arch-orion/memory.h
+- *
+- * Marvell Orion memory definitions
+- */
+-
+-#ifndef __ASM_ARCH_MMU_H
+-#define __ASM_ARCH_MMU_H
+-
+-#define PHYS_OFFSET UL(0x00000000)
+-
+-#define __virt_to_bus(x) __virt_to_phys(x)
+-#define __bus_to_virt(x) __phys_to_virt(x)
+-
+-#endif
+diff --git a/include/asm-arm/arch-orion/orion.h b/include/asm-arm/arch-orion/orion.h
+deleted file mode 100644
+index 673a418..0000000
+--- a/include/asm-arm/arch-orion/orion.h
++++ /dev/null
+@@ -1,165 +0,0 @@
+-/*
+- * include/asm-arm/arch-orion/orion.h
+- *
+- * Generic definitions of Orion SoC flavors:
+- * Orion-1, Orion-NAS, Orion-VoIP, and Orion-2.
+- *
+- * Maintainer: Tzachi Perelstein <tzachi at marvell.com>
+- *
+- * This file is licensed under the terms of the GNU General Public
+- * License version 2. This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-
+-#ifndef __ASM_ARCH_ORION_H__
+-#define __ASM_ARCH_ORION_H__
+-
+-/*****************************************************************************
+- * Orion Address Map
+- *
+- * virt phys size
+- * fdd00000 f1000000 1M on-chip peripheral registers
+- * fde00000 f2000000 1M PCIe I/O space
+- * fdf00000 f2100000 1M PCI I/O space
+- * fe000000 f0000000 16M PCIe WA space (Orion-NAS only)
+- ****************************************************************************/
+-#define ORION_REGS_PHYS_BASE 0xf1000000
+-#define ORION_REGS_VIRT_BASE 0xfdd00000
+-#define ORION_REGS_SIZE SZ_1M
+-
+-#define ORION_PCIE_IO_PHYS_BASE 0xf2000000
+-#define ORION_PCIE_IO_VIRT_BASE 0xfde00000
+-#define ORION_PCIE_IO_BUS_BASE 0x00000000
+-#define ORION_PCIE_IO_SIZE SZ_1M
+-
+-#define ORION_PCI_IO_PHYS_BASE 0xf2100000
+-#define ORION_PCI_IO_VIRT_BASE 0xfdf00000
+-#define ORION_PCI_IO_BUS_BASE 0x00100000
+-#define ORION_PCI_IO_SIZE SZ_1M
+-
+-/* Relevant only for Orion-NAS */
+-#define ORION_PCIE_WA_PHYS_BASE 0xf0000000
+-#define ORION_PCIE_WA_VIRT_BASE 0xfe000000
+-#define ORION_PCIE_WA_SIZE SZ_16M
+-
+-#define ORION_PCIE_MEM_PHYS_BASE 0xe0000000
+-#define ORION_PCIE_MEM_SIZE SZ_128M
+-
+-#define ORION_PCI_MEM_PHYS_BASE 0xe8000000
+-#define ORION_PCI_MEM_SIZE SZ_128M
+-
+-/*******************************************************************************
+- * Supported Devices & Revisions
+- ******************************************************************************/
+-/* Orion-1 (88F5181) */
+-#define MV88F5181_DEV_ID 0x5181
+-#define MV88F5181_REV_B1 3
+-/* Orion-NAS (88F5182) */
+-#define MV88F5182_DEV_ID 0x5182
+-#define MV88F5182_REV_A2 2
+-/* Orion-2 (88F5281) */
+-#define MV88F5281_DEV_ID 0x5281
+-#define MV88F5281_REV_D1 5
+-#define MV88F5281_REV_D2 6
+-
+-/*******************************************************************************
+- * Orion Registers Map
+- ******************************************************************************/
+-#define ORION_DDR_VIRT_BASE (ORION_REGS_VIRT_BASE | 0x00000)
+-#define ORION_DDR_REG(x) (ORION_DDR_VIRT_BASE | (x))
+-
+-#define ORION_DEV_BUS_PHYS_BASE (ORION_REGS_PHYS_BASE | 0x10000)
+-#define ORION_DEV_BUS_VIRT_BASE (ORION_REGS_VIRT_BASE | 0x10000)
+-#define ORION_DEV_BUS_REG(x) (ORION_DEV_BUS_VIRT_BASE | (x))
+-#define I2C_PHYS_BASE (ORION_DEV_BUS_PHYS_BASE | 0x1000)
+-#define UART0_PHYS_BASE (ORION_DEV_BUS_PHYS_BASE | 0x2000)
+-#define UART0_VIRT_BASE (ORION_DEV_BUS_VIRT_BASE | 0x2000)
+-#define UART1_PHYS_BASE (ORION_DEV_BUS_PHYS_BASE | 0x2100)
+-#define UART1_VIRT_BASE (ORION_DEV_BUS_VIRT_BASE | 0x2100)
+-
+-#define ORION_BRIDGE_VIRT_BASE (ORION_REGS_VIRT_BASE | 0x20000)
+-#define ORION_BRIDGE_REG(x) (ORION_BRIDGE_VIRT_BASE | (x))
+-
+-#define ORION_PCI_VIRT_BASE (ORION_REGS_VIRT_BASE | 0x30000)
+-#define ORION_PCI_REG(x) (ORION_PCI_VIRT_BASE | (x))
+-
+-#define ORION_PCIE_VIRT_BASE (ORION_REGS_VIRT_BASE | 0x40000)
+-#define ORION_PCIE_REG(x) (ORION_PCIE_VIRT_BASE | (x))
+-
+-#define ORION_USB0_PHYS_BASE (ORION_REGS_PHYS_BASE | 0x50000)
+-#define ORION_USB0_VIRT_BASE (ORION_REGS_VIRT_BASE | 0x50000)
+-#define ORION_USB0_REG(x) (ORION_USB0_VIRT_BASE | (x))
+-
+-#define ORION_ETH_PHYS_BASE (ORION_REGS_PHYS_BASE | 0x70000)
+-#define ORION_ETH_VIRT_BASE (ORION_REGS_VIRT_BASE | 0x70000)
+-#define ORION_ETH_REG(x) (ORION_ETH_VIRT_BASE | (x))
+-
+-#define ORION_SATA_PHYS_BASE (ORION_REGS_PHYS_BASE | 0x80000)
+-#define ORION_SATA_VIRT_BASE (ORION_REGS_VIRT_BASE | 0x80000)
+-#define ORION_SATA_REG(x) (ORION_SATA_VIRT_BASE | (x))
+-
+-#define ORION_USB1_PHYS_BASE (ORION_REGS_PHYS_BASE | 0xa0000)
+-#define ORION_USB1_VIRT_BASE (ORION_REGS_VIRT_BASE | 0xa0000)
+-#define ORION_USB1_REG(x) (ORION_USB1_VIRT_BASE | (x))
+-
+-/*******************************************************************************
+- * Device Bus Registers
+- ******************************************************************************/
+-#define MPP_0_7_CTRL ORION_DEV_BUS_REG(0x000)
+-#define MPP_8_15_CTRL ORION_DEV_BUS_REG(0x004)
+-#define MPP_16_19_CTRL ORION_DEV_BUS_REG(0x050)
+-#define MPP_DEV_CTRL ORION_DEV_BUS_REG(0x008)
+-#define MPP_RESET_SAMPLE ORION_DEV_BUS_REG(0x010)
+-#define GPIO_OUT ORION_DEV_BUS_REG(0x100)
+-#define GPIO_IO_CONF ORION_DEV_BUS_REG(0x104)
+-#define GPIO_BLINK_EN ORION_DEV_BUS_REG(0x108)
+-#define GPIO_IN_POL ORION_DEV_BUS_REG(0x10c)
+-#define GPIO_DATA_IN ORION_DEV_BUS_REG(0x110)
+-#define GPIO_EDGE_CAUSE ORION_DEV_BUS_REG(0x114)
+-#define GPIO_EDGE_MASK ORION_DEV_BUS_REG(0x118)
+-#define GPIO_LEVEL_MASK ORION_DEV_BUS_REG(0x11c)
+-#define DEV_BANK_0_PARAM ORION_DEV_BUS_REG(0x45c)
+-#define DEV_BANK_1_PARAM ORION_DEV_BUS_REG(0x460)
+-#define DEV_BANK_2_PARAM ORION_DEV_BUS_REG(0x464)
+-#define DEV_BANK_BOOT_PARAM ORION_DEV_BUS_REG(0x46c)
+-#define DEV_BUS_CTRL ORION_DEV_BUS_REG(0x4c0)
+-#define DEV_BUS_INT_CAUSE ORION_DEV_BUS_REG(0x4d0)
+-#define DEV_BUS_INT_MASK ORION_DEV_BUS_REG(0x4d4)
+-#define GPIO_MAX 32
+-
+-/***************************************************************************
+- * Orion CPU Bridge Registers
+- **************************************************************************/
+-#define CPU_CONF ORION_BRIDGE_REG(0x100)
+-#define CPU_CTRL ORION_BRIDGE_REG(0x104)
+-#define CPU_RESET_MASK ORION_BRIDGE_REG(0x108)
+-#define CPU_SOFT_RESET ORION_BRIDGE_REG(0x10c)
+-#define POWER_MNG_CTRL_REG ORION_BRIDGE_REG(0x11C)
+-#define BRIDGE_CAUSE ORION_BRIDGE_REG(0x110)
+-#define BRIDGE_MASK ORION_BRIDGE_REG(0x114)
+-#define MAIN_IRQ_CAUSE ORION_BRIDGE_REG(0x200)
+-#define MAIN_IRQ_MASK ORION_BRIDGE_REG(0x204)
+-#define TIMER_CTRL ORION_BRIDGE_REG(0x300)
+-#define TIMER_VAL(x) ORION_BRIDGE_REG(0x314 + ((x) * 8))
+-#define TIMER_VAL_RELOAD(x) ORION_BRIDGE_REG(0x310 + ((x) * 8))
+-
+-#ifndef __ASSEMBLY__
+-
+-/*******************************************************************************
+- * Helpers to access Orion registers
+- ******************************************************************************/
+-#include <asm/types.h>
+-#include <asm/io.h>
+-
+-#define orion_read(r) __raw_readl(r)
+-#define orion_write(r, val) __raw_writel(val, r)
+-
+-/*
+- * These are not preempt safe. Locks, if needed, must be taken care by caller.
+- */
+-#define orion_setbits(r, mask) orion_write((r), orion_read(r) | (mask))
+-#define orion_clrbits(r, mask) orion_write((r), orion_read(r) & ~(mask))
+-
+-#endif /* __ASSEMBLY__ */
+-
+-#endif /* __ASM_ARCH_ORION_H__ */
+diff --git a/include/asm-arm/arch-orion/platform.h b/include/asm-arm/arch-orion/platform.h
+deleted file mode 100644
+index 143c38e..0000000
+--- a/include/asm-arm/arch-orion/platform.h
++++ /dev/null
+@@ -1,25 +0,0 @@
+-/*
+- * asm-arm/arch-orion/platform.h
+- *
+- * Tzachi Perelstein <tzachi at marvell.com>
+- *
+- * This file is licensed under the terms of the GNU General Public
+- * License version 2. This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-
+-#ifndef __ASM_ARCH_PLATFORM_H__
+-#define __ASM_ARCH_PLATFORM_H__
+-
+-/*
+- * Device bus NAND private data
+- */
+-struct orion_nand_data {
+- struct mtd_partition *parts;
+- u32 nr_parts;
+- u8 ale; /* address line number connected to ALE */
+- u8 cle; /* address line number connected to CLE */
+- u8 width; /* buswidth */
+-};
+-
+-#endif
+diff --git a/include/asm-arm/arch-orion/system.h b/include/asm-arm/arch-orion/system.h
+deleted file mode 100644
+index 17704c6..0000000
+--- a/include/asm-arm/arch-orion/system.h
++++ /dev/null
+@@ -1,31 +0,0 @@
+-/*
+- * include/asm-arm/arch-orion/system.h
+- *
+- * Tzachi Perelstein <tzachi at marvell.com>
+- *
+- * This file is licensed under the terms of the GNU General Public
+- * License version 2. This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-
+-#ifndef __ASM_ARCH_SYSTEM_H
+-#define __ASM_ARCH_SYSTEM_H
+-
+-#include <asm/arch/hardware.h>
+-#include <asm/arch/orion.h>
+-
+-static inline void arch_idle(void)
+-{
+- cpu_do_idle();
+-}
+-
+-static inline void arch_reset(char mode)
+-{
+- /*
+- * Enable and issue soft reset
+- */
+- orion_setbits(CPU_RESET_MASK, (1 << 2));
+- orion_setbits(CPU_SOFT_RESET, 1);
+-}
+-
+-#endif
+diff --git a/include/asm-arm/arch-orion/timex.h b/include/asm-arm/arch-orion/timex.h
+deleted file mode 100644
+index 26c2c91..0000000
+--- a/include/asm-arm/arch-orion/timex.h
++++ /dev/null
+@@ -1,12 +0,0 @@
+-/*
+- * include/asm-arm/arch-orion/timex.h
+- *
+- * Tzachi Perelstein <tzachi at marvell.com>
+- *
+- * This file is licensed under the terms of the GNU General Public
+- * License version 2. This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-
+-#define ORION_TCLK 166666667
+-#define CLOCK_TICK_RATE ORION_TCLK
+diff --git a/include/asm-arm/arch-orion/uncompress.h b/include/asm-arm/arch-orion/uncompress.h
+deleted file mode 100644
+index 59f4403..0000000
+--- a/include/asm-arm/arch-orion/uncompress.h
++++ /dev/null
+@@ -1,34 +0,0 @@
+-/*
+- * include/asm-arm/arch-orion/uncompress.h
+- *
+- * Tzachi Perelstein <tzachi at marvell.com>
+- *
+- * This file is licensed under the terms of the GNU General Public
+- * License version 2. This program is licensed "as is" without any
+- * warranty of any kind, whether express or implied.
+- */
+-
+-#include <asm/arch/orion.h>
+-
+-#define MV_UART_THR ((volatile unsigned char *)(UART0_PHYS_BASE + 0x0))
+-#define MV_UART_LSR ((volatile unsigned char *)(UART0_PHYS_BASE + 0x14))
+-
+-#define LSR_THRE 0x20
+-
+-static void putc(const char c)
+-{
+- int j = 0x1000;
+- while (--j && !(*MV_UART_LSR & LSR_THRE))
+- barrier();
+- *MV_UART_THR = c;
+-}
+-
+-static void flush(void)
+-{
+-}
+-
+-/*
+- * nothing to do
+- */
+-#define arch_decomp_setup()
+-#define arch_decomp_wdog()
+diff --git a/include/asm-arm/arch-orion/vmalloc.h b/include/asm-arm/arch-orion/vmalloc.h
+deleted file mode 100644
+index 9d58027..0000000
+--- a/include/asm-arm/arch-orion/vmalloc.h
++++ /dev/null
+@@ -1,5 +0,0 @@
+-/*
+- * include/asm-arm/arch-orion/vmalloc.h
+- */
+-
+-#define VMALLOC_END 0xfd800000
+diff --git a/include/asm-arm/arch-orion5x/debug-macro.S b/include/asm-arm/arch-orion5x/debug-macro.S
+new file mode 100644
+index 0000000..4f98f3b
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/debug-macro.S
+@@ -0,0 +1,22 @@
++/*
++ * include/asm-arm/arch-orion5x/debug-macro.S
++ *
++ * Debugging macro include header
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++*/
++
++#include <asm/arch/orion5x.h>
++
++ .macro addruart,rx
++ mrc p15, 0, \rx, c1, c0
++ tst \rx, #1 @ MMU enabled?
++ ldreq \rx, =ORION5X_REGS_PHYS_BASE
++ ldrne \rx, =ORION5X_REGS_VIRT_BASE
++ orr \rx, \rx, #0x00012000
++ .endm
++
++#define UART_SHIFT 2
++#include <asm/hardware/debug-8250.S>
+diff --git a/include/asm-arm/arch-orion5x/dma.h b/include/asm-arm/arch-orion5x/dma.h
+new file mode 100644
+index 0000000..40a8c17
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/dma.h
+@@ -0,0 +1 @@
++/* empty */
+diff --git a/include/asm-arm/arch-orion5x/entry-macro.S b/include/asm-arm/arch-orion5x/entry-macro.S
+new file mode 100644
+index 0000000..d8ef54c
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/entry-macro.S
+@@ -0,0 +1,31 @@
++/*
++ * include/asm-arm/arch-orion5x/entry-macro.S
++ *
++ * Low-level IRQ helper macros for Orion platforms
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#include <asm/arch/orion5x.h>
++
++ .macro disable_fiq
++ .endm
++
++ .macro arch_ret_to_user, tmp1, tmp2
++ .endm
++
++ .macro get_irqnr_preamble, base, tmp
++ ldr \base, =MAIN_IRQ_CAUSE
++ .endm
++
++ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
++ ldr \irqstat, [\base, #0] @ main cause
++ ldr \tmp, [\base, #(MAIN_IRQ_MASK - MAIN_IRQ_CAUSE)] @ main mask
++ mov \irqnr, #0 @ default irqnr
++ @ find cause bits that are unmasked
++ ands \irqstat, \irqstat, \tmp @ clear Z flag if any
++ clzne \irqnr, \irqstat @ calc irqnr
++ rsbne \irqnr, \irqnr, #31
++ .endm
+diff --git a/include/asm-arm/arch-orion5x/gpio.h b/include/asm-arm/arch-orion5x/gpio.h
+new file mode 100644
+index 0000000..c85e498
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/gpio.h
+@@ -0,0 +1,28 @@
++/*
++ * include/asm-arm/arch-orion5x/gpio.h
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++extern int gpio_request(unsigned pin, const char *label);
++extern void gpio_free(unsigned pin);
++extern int gpio_direction_input(unsigned pin);
++extern int gpio_direction_output(unsigned pin, int value);
++extern int gpio_get_value(unsigned pin);
++extern void gpio_set_value(unsigned pin, int value);
++extern void orion5x_gpio_set_blink(unsigned pin, int blink);
++extern void gpio_display(void); /* debug */
++
++static inline int gpio_to_irq(int pin)
++{
++ return pin + IRQ_ORION5X_GPIO_START;
++}
++
++static inline int irq_to_gpio(int irq)
++{
++ return irq - IRQ_ORION5X_GPIO_START;
++}
++
++#include <asm-generic/gpio.h> /* cansleep wrappers */
+diff --git a/include/asm-arm/arch-orion5x/hardware.h b/include/asm-arm/arch-orion5x/hardware.h
+new file mode 100644
+index 0000000..5d2d8e0
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/hardware.h
+@@ -0,0 +1,21 @@
++/*
++ * include/asm-arm/arch-orion5x/hardware.h
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __ASM_ARCH_HARDWARE_H
++#define __ASM_ARCH_HARDWARE_H
++
++#include "orion5x.h"
++
++#define pcibios_assign_all_busses() 1
++
++#define PCIBIOS_MIN_IO 0x00001000
++#define PCIBIOS_MIN_MEM 0x01000000
++#define PCIMEM_BASE ORION5X_PCIE_MEM_PHYS_BASE
++
++
++#endif
+diff --git a/include/asm-arm/arch-orion5x/io.h b/include/asm-arm/arch-orion5x/io.h
+new file mode 100644
+index 0000000..5148ab7
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/io.h
+@@ -0,0 +1,68 @@
++/*
++ * include/asm-arm/arch-orion5x/io.h
++ *
++ * Tzachi Perelstein <tzachi at marvell.com>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#ifndef __ASM_ARCH_IO_H
++#define __ASM_ARCH_IO_H
++
++#include "orion5x.h"
++
++#define IO_SPACE_LIMIT 0xffffffff
++#define IO_SPACE_REMAP ORION5X_PCI_SYS_IO_BASE
++
++static inline void __iomem *
++__arch_ioremap(unsigned long paddr, size_t size, unsigned int mtype)
++{
++ void __iomem *retval;
++
++ if (mtype == MT_DEVICE && size && paddr >= ORION5X_REGS_PHYS_BASE &&
++ paddr + size <= ORION5X_REGS_PHYS_BASE + ORION5X_REGS_SIZE) {
++ retval = (void __iomem *)ORION5X_REGS_VIRT_BASE +
++ (paddr - ORION5X_REGS_PHYS_BASE);
++ } else {
++ retval = __arm_ioremap(paddr, size, mtype);
++ }
++
++ return retval;
++}
++
++static inline void
++__arch_iounmap(void __iomem *addr)
++{
++ if (addr < (void __iomem *)ORION5X_REGS_VIRT_BASE ||
++ addr >= (void __iomem *)(ORION5X_REGS_VIRT_BASE + ORION5X_REGS_SIZE))
++ __iounmap(addr);
++}
++
++static inline void __iomem *__io(unsigned long addr)
++{
++ return (void __iomem *)addr;
++}
++
++#define __arch_ioremap(p, s, m) __arch_ioremap(p, s, m)
++#define __arch_iounmap(a) __arch_iounmap(a)
++#define __io(a) __io(a)
++#define __mem_pci(a) (a)
++
++
++/*****************************************************************************
++ * Helpers to access Orion registers
++ ****************************************************************************/
++#define orion5x_read(r) __raw_readl(r)
++#define orion5x_write(r, val) __raw_writel(val, r)
++
++/*
++ * These are not preempt-safe. Locks, if needed, must be taken
++ * care of by the caller.
++ */
++#define orion5x_setbits(r, mask) orion5x_write((r), orion5x_read(r) | (mask))
++#define orion5x_clrbits(r, mask) orion5x_write((r), orion5x_read(r) & ~(mask))
++
++
++#endif
+diff --git a/include/asm-arm/arch-orion5x/irqs.h b/include/asm-arm/arch-orion5x/irqs.h
+new file mode 100644
+index 0000000..abdd61a
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/irqs.h
+@@ -0,0 +1,62 @@
++/*
++ * include/asm-arm/arch-orion5x/irqs.h
++ *
++ * IRQ definitions for Orion SoC
++ *
++ * Maintainer: Tzachi Perelstein <tzachi at marvell.com>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#ifndef __ASM_ARCH_IRQS_H
++#define __ASM_ARCH_IRQS_H
++
++#include "orion5x.h" /* need GPIO_MAX */
++
++/*
++ * Orion Main Interrupt Controller
++ */
++#define IRQ_ORION5X_BRIDGE 0
++#define IRQ_ORION5X_DOORBELL_H2C 1
++#define IRQ_ORION5X_DOORBELL_C2H 2
++#define IRQ_ORION5X_UART0 3
++#define IRQ_ORION5X_UART1 4
++#define IRQ_ORION5X_I2C 5
++#define IRQ_ORION5X_GPIO_0_7 6
++#define IRQ_ORION5X_GPIO_8_15 7
++#define IRQ_ORION5X_GPIO_16_23 8
++#define IRQ_ORION5X_GPIO_24_31 9
++#define IRQ_ORION5X_PCIE0_ERR 10
++#define IRQ_ORION5X_PCIE0_INT 11
++#define IRQ_ORION5X_USB1_CTRL 12
++#define IRQ_ORION5X_DEV_BUS_ERR 14
++#define IRQ_ORION5X_PCI_ERR 15
++#define IRQ_ORION5X_USB_BR_ERR 16
++#define IRQ_ORION5X_USB0_CTRL 17
++#define IRQ_ORION5X_ETH_RX 18
++#define IRQ_ORION5X_ETH_TX 19
++#define IRQ_ORION5X_ETH_MISC 20
++#define IRQ_ORION5X_ETH_SUM 21
++#define IRQ_ORION5X_ETH_ERR 22
++#define IRQ_ORION5X_IDMA_ERR 23
++#define IRQ_ORION5X_IDMA_0 24
++#define IRQ_ORION5X_IDMA_1 25
++#define IRQ_ORION5X_IDMA_2 26
++#define IRQ_ORION5X_IDMA_3 27
++#define IRQ_ORION5X_CESA 28
++#define IRQ_ORION5X_SATA 29
++#define IRQ_ORION5X_XOR0 30
++#define IRQ_ORION5X_XOR1 31
++
++/*
++ * Orion General Purpose Pins
++ */
++#define IRQ_ORION5X_GPIO_START 32
++#define NR_GPIO_IRQS GPIO_MAX
++
++#define NR_IRQS (IRQ_ORION5X_GPIO_START + NR_GPIO_IRQS)
++
++
++#endif
+diff --git a/include/asm-arm/arch-orion5x/memory.h b/include/asm-arm/arch-orion5x/memory.h
+new file mode 100644
+index 0000000..80053a7
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/memory.h
+@@ -0,0 +1,16 @@
++/*
++ * include/asm-arm/arch-orion5x/memory.h
++ *
++ * Marvell Orion memory definitions
++ */
++
++#ifndef __ASM_ARCH_MEMORY_H
++#define __ASM_ARCH_MEMORY_H
++
++#define PHYS_OFFSET UL(0x00000000)
++
++#define __virt_to_bus(x) __virt_to_phys(x)
++#define __bus_to_virt(x) __phys_to_virt(x)
++
++
++#endif
+diff --git a/include/asm-arm/arch-orion5x/orion5x.h b/include/asm-arm/arch-orion5x/orion5x.h
+new file mode 100644
+index 0000000..206ddd7
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/orion5x.h
+@@ -0,0 +1,159 @@
++/*
++ * include/asm-arm/arch-orion5x/orion5x.h
++ *
++ * Generic definitions of Orion SoC flavors:
++ * Orion-1, Orion-NAS, Orion-VoIP, and Orion-2.
++ *
++ * Maintainer: Tzachi Perelstein <tzachi at marvell.com>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#ifndef __ASM_ARCH_ORION5X_H
++#define __ASM_ARCH_ORION5X_H
++
++/*****************************************************************************
++ * Orion Address Maps
++ *
++ * phys
++ * e0000000 PCIe MEM space
++ * e8000000 PCI MEM space
++ * f0000000 PCIe WA space (Orion-1/Orion-NAS only)
++ * f1000000 on-chip peripheral registers
++ * f2000000 PCIe I/O space
++ * f2100000 PCI I/O space
++ * f4000000 device bus mappings (boot)
++ * fa000000 device bus mappings (cs0)
++ * fa800000 device bus mappings (cs2)
++ * fc000000 device bus mappings (cs0/cs1)
++ *
++ * virt phys size
++ * fdd00000 f1000000 1M on-chip peripheral registers
++ * fde00000 f2000000 1M PCIe I/O space
++ * fdf00000 f2100000 1M PCI I/O space
++ * fe000000 f0000000 16M PCIe WA space (Orion-1/Orion-NAS only)
++ ****************************************************************************/
++#define ORION5X_REGS_PHYS_BASE 0xf1000000
++#define ORION5X_REGS_VIRT_BASE 0xfdd00000
++#define ORION5X_REGS_SIZE SZ_1M
++
++#define ORION5X_PCIE_IO_PHYS_BASE 0xf2000000
++#define ORION5X_PCIE_IO_VIRT_BASE 0xfde00000
++#define ORION5X_PCIE_IO_BUS_BASE 0x00000000
++#define ORION5X_PCIE_IO_SIZE SZ_1M
++
++#define ORION5X_PCI_IO_PHYS_BASE 0xf2100000
++#define ORION5X_PCI_IO_VIRT_BASE 0xfdf00000
++#define ORION5X_PCI_IO_BUS_BASE 0x00100000
++#define ORION5X_PCI_IO_SIZE SZ_1M
++
++/* Relevant only for Orion-1/Orion-NAS */
++#define ORION5X_PCIE_WA_PHYS_BASE 0xf0000000
++#define ORION5X_PCIE_WA_VIRT_BASE 0xfe000000
++#define ORION5X_PCIE_WA_SIZE SZ_16M
++
++#define ORION5X_PCIE_MEM_PHYS_BASE 0xe0000000
++#define ORION5X_PCIE_MEM_SIZE SZ_128M
++
++#define ORION5X_PCI_MEM_PHYS_BASE 0xe8000000
++#define ORION5X_PCI_MEM_SIZE SZ_128M
++
++/*******************************************************************************
++ * Supported Devices & Revisions
++ ******************************************************************************/
++/* Orion-1 (88F5181) */
++#define MV88F5181_DEV_ID 0x5181
++#define MV88F5181_REV_B1 3
++/* Orion-NAS (88F5182) */
++#define MV88F5182_DEV_ID 0x5182
++#define MV88F5182_REV_A2 2
++/* Orion-2 (88F5281) */
++#define MV88F5281_DEV_ID 0x5281
++#define MV88F5281_REV_D1 5
++#define MV88F5281_REV_D2 6
++
++/*******************************************************************************
++ * Orion Registers Map
++ ******************************************************************************/
++#define ORION5X_DDR_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0x00000)
++#define ORION5X_DDR_REG(x) (ORION5X_DDR_VIRT_BASE | (x))
++
++#define ORION5X_DEV_BUS_PHYS_BASE (ORION5X_REGS_PHYS_BASE | 0x10000)
++#define ORION5X_DEV_BUS_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0x10000)
++#define ORION5X_DEV_BUS_REG(x) (ORION5X_DEV_BUS_VIRT_BASE | (x))
++#define I2C_PHYS_BASE (ORION5X_DEV_BUS_PHYS_BASE | 0x1000)
++#define UART0_PHYS_BASE (ORION5X_DEV_BUS_PHYS_BASE | 0x2000)
++#define UART0_VIRT_BASE (ORION5X_DEV_BUS_VIRT_BASE | 0x2000)
++#define UART1_PHYS_BASE (ORION5X_DEV_BUS_PHYS_BASE | 0x2100)
++#define UART1_VIRT_BASE (ORION5X_DEV_BUS_VIRT_BASE | 0x2100)
++
++#define ORION5X_BRIDGE_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0x20000)
++#define ORION5X_BRIDGE_REG(x) (ORION5X_BRIDGE_VIRT_BASE | (x))
++#define TIMER_VIRT_BASE (ORION5X_BRIDGE_VIRT_BASE | 0x300)
++
++#define ORION5X_PCI_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0x30000)
++#define ORION5X_PCI_REG(x) (ORION5X_PCI_VIRT_BASE | (x))
++
++#define ORION5X_PCIE_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0x40000)
++#define ORION5X_PCIE_REG(x) (ORION5X_PCIE_VIRT_BASE | (x))
++
++#define ORION5X_USB0_PHYS_BASE (ORION5X_REGS_PHYS_BASE | 0x50000)
++#define ORION5X_USB0_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0x50000)
++#define ORION5X_USB0_REG(x) (ORION5X_USB0_VIRT_BASE | (x))
++
++#define ORION5X_ETH_PHYS_BASE (ORION5X_REGS_PHYS_BASE | 0x70000)
++#define ORION5X_ETH_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0x70000)
++#define ORION5X_ETH_REG(x) (ORION5X_ETH_VIRT_BASE | (x))
++
++#define ORION5X_SATA_PHYS_BASE (ORION5X_REGS_PHYS_BASE | 0x80000)
++#define ORION5X_SATA_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0x80000)
++#define ORION5X_SATA_REG(x) (ORION5X_SATA_VIRT_BASE | (x))
++
++#define ORION5X_USB1_PHYS_BASE (ORION5X_REGS_PHYS_BASE | 0xa0000)
++#define ORION5X_USB1_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0xa0000)
++#define ORION5X_USB1_REG(x) (ORION5X_USB1_VIRT_BASE | (x))
++
++/*******************************************************************************
++ * Device Bus Registers
++ ******************************************************************************/
++#define MPP_0_7_CTRL ORION5X_DEV_BUS_REG(0x000)
++#define MPP_8_15_CTRL ORION5X_DEV_BUS_REG(0x004)
++#define MPP_16_19_CTRL ORION5X_DEV_BUS_REG(0x050)
++#define MPP_DEV_CTRL ORION5X_DEV_BUS_REG(0x008)
++#define MPP_RESET_SAMPLE ORION5X_DEV_BUS_REG(0x010)
++#define GPIO_OUT ORION5X_DEV_BUS_REG(0x100)
++#define GPIO_IO_CONF ORION5X_DEV_BUS_REG(0x104)
++#define GPIO_BLINK_EN ORION5X_DEV_BUS_REG(0x108)
++#define GPIO_IN_POL ORION5X_DEV_BUS_REG(0x10c)
++#define GPIO_DATA_IN ORION5X_DEV_BUS_REG(0x110)
++#define GPIO_EDGE_CAUSE ORION5X_DEV_BUS_REG(0x114)
++#define GPIO_EDGE_MASK ORION5X_DEV_BUS_REG(0x118)
++#define GPIO_LEVEL_MASK ORION5X_DEV_BUS_REG(0x11c)
++#define DEV_BANK_0_PARAM ORION5X_DEV_BUS_REG(0x45c)
++#define DEV_BANK_1_PARAM ORION5X_DEV_BUS_REG(0x460)
++#define DEV_BANK_2_PARAM ORION5X_DEV_BUS_REG(0x464)
++#define DEV_BANK_BOOT_PARAM ORION5X_DEV_BUS_REG(0x46c)
++#define DEV_BUS_CTRL ORION5X_DEV_BUS_REG(0x4c0)
++#define DEV_BUS_INT_CAUSE ORION5X_DEV_BUS_REG(0x4d0)
++#define DEV_BUS_INT_MASK ORION5X_DEV_BUS_REG(0x4d4)
++#define GPIO_MAX 32
++
++/***************************************************************************
++ * Orion CPU Bridge Registers
++ **************************************************************************/
++#define CPU_CONF ORION5X_BRIDGE_REG(0x100)
++#define CPU_CTRL ORION5X_BRIDGE_REG(0x104)
++#define CPU_RESET_MASK ORION5X_BRIDGE_REG(0x108)
++#define CPU_SOFT_RESET ORION5X_BRIDGE_REG(0x10c)
++#define POWER_MNG_CTRL_REG ORION5X_BRIDGE_REG(0x11C)
++#define BRIDGE_CAUSE ORION5X_BRIDGE_REG(0x110)
++#define BRIDGE_MASK ORION5X_BRIDGE_REG(0x114)
++#define BRIDGE_INT_TIMER0 0x0002
++#define BRIDGE_INT_TIMER1 0x0004
++#define MAIN_IRQ_CAUSE ORION5X_BRIDGE_REG(0x200)
++#define MAIN_IRQ_MASK ORION5X_BRIDGE_REG(0x204)
++
++
++#endif
+diff --git a/include/asm-arm/arch-orion5x/system.h b/include/asm-arm/arch-orion5x/system.h
+new file mode 100644
+index 0000000..3f1d1e2
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/system.h
+@@ -0,0 +1,32 @@
++/*
++ * include/asm-arm/arch-orion5x/system.h
++ *
++ * Tzachi Perelstein <tzachi at marvell.com>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#ifndef __ASM_ARCH_SYSTEM_H
++#define __ASM_ARCH_SYSTEM_H
++
++#include <asm/arch/hardware.h>
++#include <asm/arch/orion5x.h>
++
++static inline void arch_idle(void)
++{
++ cpu_do_idle();
++}
++
++static inline void arch_reset(char mode)
++{
++ /*
++ * Enable and issue soft reset
++ */
++ orion5x_setbits(CPU_RESET_MASK, (1 << 2));
++ orion5x_setbits(CPU_SOFT_RESET, 1);
++}
++
++
++#endif
+diff --git a/include/asm-arm/arch-orion5x/timex.h b/include/asm-arm/arch-orion5x/timex.h
+new file mode 100644
+index 0000000..31c568e
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/timex.h
+@@ -0,0 +1,13 @@
++/*
++ * include/asm-arm/arch-orion5x/timex.h
++ *
++ * Tzachi Perelstein <tzachi at marvell.com>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#define CLOCK_TICK_RATE (100 * HZ)
++
++#define ORION5X_TCLK 166666667
+diff --git a/include/asm-arm/arch-orion5x/uncompress.h b/include/asm-arm/arch-orion5x/uncompress.h
+new file mode 100644
+index 0000000..5c13d4f
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/uncompress.h
+@@ -0,0 +1,34 @@
++/*
++ * include/asm-arm/arch-orion5x/uncompress.h
++ *
++ * Tzachi Perelstein <tzachi at marvell.com>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#include <asm/arch/orion5x.h>
++
++#define MV_UART_THR ((volatile unsigned char *)(UART0_PHYS_BASE + 0x0))
++#define MV_UART_LSR ((volatile unsigned char *)(UART0_PHYS_BASE + 0x14))
++
++#define LSR_THRE 0x20
++
++static void putc(const char c)
++{
++ int j = 0x1000;
++ while (--j && !(*MV_UART_LSR & LSR_THRE))
++ barrier();
++ *MV_UART_THR = c;
++}
++
++static void flush(void)
++{
++}
++
++/*
++ * nothing to do
++ */
++#define arch_decomp_setup()
++#define arch_decomp_wdog()
+diff --git a/include/asm-arm/arch-orion5x/vmalloc.h b/include/asm-arm/arch-orion5x/vmalloc.h
+new file mode 100644
+index 0000000..2b3061e
+--- /dev/null
++++ b/include/asm-arm/arch-orion5x/vmalloc.h
+@@ -0,0 +1,5 @@
++/*
++ * include/asm-arm/arch-orion5x/vmalloc.h
++ */
++
++#define VMALLOC_END 0xfd800000
+diff --git a/include/asm-arm/arch-pxa/camera.h b/include/asm-arm/arch-pxa/camera.h
+new file mode 100644
+index 0000000..39516ce
+--- /dev/null
++++ b/include/asm-arm/arch-pxa/camera.h
+@@ -0,0 +1,48 @@
++/*
++ camera.h - PXA camera driver header file
++
++ Copyright (C) 2003, Intel Corporation
++ Copyright (C) 2008, Guennadi Liakhovetski <kernel at pengutronix.de>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++*/
++
++#ifndef __ASM_ARCH_CAMERA_H_
++#define __ASM_ARCH_CAMERA_H_
++
++#define PXA_CAMERA_MASTER 1
++#define PXA_CAMERA_DATAWIDTH_4 2
++#define PXA_CAMERA_DATAWIDTH_5 4
++#define PXA_CAMERA_DATAWIDTH_8 8
++#define PXA_CAMERA_DATAWIDTH_9 0x10
++#define PXA_CAMERA_DATAWIDTH_10 0x20
++#define PXA_CAMERA_PCLK_EN 0x40
++#define PXA_CAMERA_MCLK_EN 0x80
++#define PXA_CAMERA_PCP 0x100
++#define PXA_CAMERA_HSP 0x200
++#define PXA_CAMERA_VSP 0x400
++
++struct pxacamera_platform_data {
++ int (*init)(struct device *);
++ int (*power)(struct device *, int);
++ int (*reset)(struct device *, int);
++
++ unsigned long flags;
++ unsigned long mclk_10khz;
++};
++
++extern void pxa_set_camera_info(struct pxacamera_platform_data *);
++
++#endif /* __ASM_ARCH_CAMERA_H_ */
+diff --git a/include/asm-arm/arch-pxa/gumstix.h b/include/asm-arm/arch-pxa/gumstix.h
+new file mode 100644
+index 0000000..6fa85c4
+--- /dev/null
++++ b/include/asm-arm/arch-pxa/gumstix.h
+@@ -0,0 +1,96 @@
++/*
++ * linux/include/asm-arm/arch-pxa/gumstix.h
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++
++/* BTRESET - Reset line to Bluetooth module, active low signal. */
++#define GPIO_GUMSTIX_BTRESET 7
++#define GPIO_GUMSTIX_BTRESET_MD (GPIO_GUMSTIX_BTRESET | GPIO_OUT)
++
++
++/*
++GPIOn - Input from MAX823 (or equiv), normalizing USB +5V into a clean
++interrupt signal for determining cable presence. On the original gumstix,
++this is GPIO81, and GPIO83 needs to be defined as well. On the gumstix F,
++this moves to GPIO17 and GPIO37. */
++
++/* GPIOx - Connects to USB D+ and used as a pull-up after GPIOn
++has detected a cable insertion; driven low otherwise. */
++
++#ifdef CONFIG_ARCH_GUMSTIX_ORIG
++
++#define GPIO_GUMSTIX_USB_GPIOn 81
++#define GPIO_GUMSTIX_USB_GPIOx 83
++
++#else
++
++#define GPIO_GUMSTIX_USB_GPIOn 35
++#define GPIO_GUMSTIX_USB_GPIOx 41
++
++#endif
++
++/* usb state change */
++#define GUMSTIX_USB_INTR_IRQ IRQ_GPIO(GPIO_GUMSTIX_USB_GPIOn)
++
++#define GPIO_GUMSTIX_USB_GPIOn_MD (GPIO_GUMSTIX_USB_GPIOn | GPIO_IN)
++#define GPIO_GUMSTIX_USB_GPIOx_CON_MD (GPIO_GUMSTIX_USB_GPIOx | GPIO_OUT)
++#define GPIO_GUMSTIX_USB_GPIOx_DIS_MD (GPIO_GUMSTIX_USB_GPIOx | GPIO_IN)
++
++/*
++ * SD/MMC definitions
++ */
++#define GUMSTIX_GPIO_nSD_WP 22 /* SD Write Protect */
++#define GUMSTIX_GPIO_nSD_DETECT 11 /* MMC/SD Card Detect */
++#define GUMSTIX_IRQ_GPIO_nSD_DETECT IRQ_GPIO(GUMSTIX_GPIO_nSD_DETECT)
++
++/*
++ * SMC Ethernet definitions
++ * ETH_RST provides a hardware reset line to the ethernet chip
++ * ETH is the IRQ line in from the ethernet chip to the PXA
++ */
++#define GPIO_GUMSTIX_ETH0_RST 80
++#define GPIO_GUMSTIX_ETH0_RST_MD (GPIO_GUMSTIX_ETH0_RST | GPIO_OUT)
++#define GPIO_GUMSTIX_ETH1_RST 52
++#define GPIO_GUMSTIX_ETH1_RST_MD (GPIO_GUMSTIX_ETH1_RST | GPIO_OUT)
++
++#define GPIO_GUMSTIX_ETH0 36
++#define GPIO_GUMSTIX_ETH0_MD (GPIO_GUMSTIX_ETH0 | GPIO_IN)
++#define GUMSTIX_ETH0_IRQ IRQ_GPIO(GPIO_GUMSTIX_ETH0)
++#define GPIO_GUMSTIX_ETH1 27
++#define GPIO_GUMSTIX_ETH1_MD (GPIO_GUMSTIX_ETH1 | GPIO_IN)
++#define GUMSTIX_ETH1_IRQ IRQ_GPIO(GPIO_GUMSTIX_ETH1)
++
++
++/* CF reset line */
++#define GPIO8_RESET 8
++
++/* CF slot 0 */
++#define GPIO4_nBVD1 4
++#define GPIO4_nSTSCHG GPIO4_nBVD1
++#define GPIO11_nCD 11
++#define GPIO26_PRDY_nBSY 26
++#define GUMSTIX_S0_nSTSCHG_IRQ IRQ_GPIO(GPIO4_nSTSCHG)
++#define GUMSTIX_S0_nCD_IRQ IRQ_GPIO(GPIO11_nCD)
++#define GUMSTIX_S0_PRDY_nBSY_IRQ IRQ_GPIO(GPIO26_PRDY_nBSY)
++
++/* CF slot 1 */
++#define GPIO18_nBVD1 18
++#define GPIO18_nSTSCHG GPIO18_nBVD1
++#define GPIO36_nCD 36
++#define GPIO27_PRDY_nBSY 27
++#define GUMSTIX_S1_nSTSCHG_IRQ IRQ_GPIO(GPIO18_nSTSCHG)
++#define GUMSTIX_S1_nCD_IRQ IRQ_GPIO(GPIO36_nCD)
++#define GUMSTIX_S1_PRDY_nBSY_IRQ IRQ_GPIO(GPIO27_PRDY_nBSY)
++
++/* CF GPIO line modes */
++#define GPIO4_nSTSCHG_MD (GPIO4_nSTSCHG | GPIO_IN)
++#define GPIO8_RESET_MD (GPIO8_RESET | GPIO_OUT)
++#define GPIO11_nCD_MD (GPIO11_nCD | GPIO_IN)
++#define GPIO18_nSTSCHG_MD (GPIO18_nSTSCHG | GPIO_IN)
++#define GPIO26_PRDY_nBSY_MD (GPIO26_PRDY_nBSY | GPIO_IN)
++#define GPIO27_PRDY_nBSY_MD (GPIO27_PRDY_nBSY | GPIO_IN)
++#define GPIO36_nCD_MD (GPIO36_nCD | GPIO_IN)
+diff --git a/include/asm-arm/arch-pxa/irda.h b/include/asm-arm/arch-pxa/irda.h
+index 748406f..99f4f42 100644
+--- a/include/asm-arm/arch-pxa/irda.h
++++ b/include/asm-arm/arch-pxa/irda.h
+@@ -10,6 +10,8 @@
+ struct pxaficp_platform_data {
+ int transceiver_cap;
+ void (*transceiver_mode)(struct device *dev, int mode);
++ int (*startup)(struct device *dev);
++ void (*shutdown)(struct device *dev);
+ };
+
+ extern void pxa_set_ficp_info(struct pxaficp_platform_data *info);
+diff --git a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h
+index c562b97..50c77ea 100644
+--- a/include/asm-arm/arch-pxa/irqs.h
++++ b/include/asm-arm/arch-pxa/irqs.h
+@@ -181,7 +181,8 @@
+ #elif defined(CONFIG_ARCH_LUBBOCK) || \
+ defined(CONFIG_MACH_LOGICPD_PXA270) || \
+ defined(CONFIG_MACH_MAINSTONE) || \
+- defined(CONFIG_MACH_PCM027)
++ defined(CONFIG_MACH_PCM027) || \
++ defined(CONFIG_MACH_MAGICIAN)
+ #define NR_IRQS (IRQ_BOARD_END)
+ #else
+ #define NR_IRQS (IRQ_BOARD_START)
+diff --git a/include/asm-arm/arch-pxa/magician.h b/include/asm-arm/arch-pxa/magician.h
+index 337f51f..b34fd56 100644
+--- a/include/asm-arm/arch-pxa/magician.h
++++ b/include/asm-arm/arch-pxa/magician.h
+@@ -12,7 +12,8 @@
+ #ifndef _MAGICIAN_H_
+ #define _MAGICIAN_H_
+
+-#include <asm/arch/pxa-regs.h>
++#include <asm/arch/irqs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+
+ /*
+ * PXA GPIOs
+@@ -34,6 +35,7 @@
+ #define GPIO48_MAGICIAN_UNKNOWN 48
+ #define GPIO56_MAGICIAN_UNKNOWN 56
+ #define GPIO57_MAGICIAN_CAM_RESET 57
++#define GPIO75_MAGICIAN_SAMSUNG_POWER 75
+ #define GPIO83_MAGICIAN_nIR_EN 83
+ #define GPIO86_MAGICIAN_GSM_RESET 86
+ #define GPIO87_MAGICIAN_GSM_SELECT 87
+@@ -81,6 +83,7 @@
+ #define GPIO48_MAGICIAN_UNKNOWN_MD (48 | GPIO_OUT)
+ #define GPIO56_MAGICIAN_UNKNOWN_MD (56 | GPIO_OUT)
+ #define GPIO57_MAGICIAN_CAM_RESET_MD (57 | GPIO_OUT)
++#define GPIO75_MAGICIAN_SAMSUNG_POWER_MD (75 | GPIO_OUT)
+ #define GPIO83_MAGICIAN_nIR_EN_MD (83 | GPIO_OUT)
+ #define GPIO86_MAGICIAN_GSM_RESET_MD (86 | GPIO_OUT)
+ #define GPIO87_MAGICIAN_GSM_SELECT_MD (87 | GPIO_OUT)
+@@ -108,4 +111,56 @@
+ #define GPIO119_MAGICIAN_UNKNOWN_MD (119 | GPIO_OUT)
+ #define GPIO120_MAGICIAN_UNKNOWN_MD (120 | GPIO_OUT)
+
++/*
++ * CPLD IRQs
++ */
++
++#define IRQ_MAGICIAN_SD (IRQ_BOARD_START + 0)
++#define IRQ_MAGICIAN_EP (IRQ_BOARD_START + 1)
++#define IRQ_MAGICIAN_BT (IRQ_BOARD_START + 2)
++#define IRQ_MAGICIAN_AC (IRQ_BOARD_START + 3)
++
++/*
++ * CPLD EGPIOs
++ */
++
++#define MAGICIAN_EGPIO_BASE 0x80 /* GPIO_BOARD_START */
++#define MAGICIAN_EGPIO(reg,bit) \
++ (MAGICIAN_EGPIO_BASE + 8*reg + bit)
++
++/* output */
++
++#define EGPIO_MAGICIAN_TOPPOLY_POWER MAGICIAN_EGPIO(0, 2)
++#define EGPIO_MAGICIAN_LED_POWER MAGICIAN_EGPIO(0, 5)
++#define EGPIO_MAGICIAN_GSM_RESET MAGICIAN_EGPIO(0, 6)
++#define EGPIO_MAGICIAN_LCD_POWER MAGICIAN_EGPIO(0, 7)
++#define EGPIO_MAGICIAN_SPK_POWER MAGICIAN_EGPIO(1, 0)
++#define EGPIO_MAGICIAN_EP_POWER MAGICIAN_EGPIO(1, 1)
++#define EGPIO_MAGICIAN_IN_SEL0 MAGICIAN_EGPIO(1, 2)
++#define EGPIO_MAGICIAN_IN_SEL1 MAGICIAN_EGPIO(1, 3)
++#define EGPIO_MAGICIAN_MIC_POWER MAGICIAN_EGPIO(1, 4)
++#define EGPIO_MAGICIAN_CODEC_RESET MAGICIAN_EGPIO(1, 5)
++#define EGPIO_MAGICIAN_CODEC_POWER MAGICIAN_EGPIO(1, 6)
++#define EGPIO_MAGICIAN_BL_POWER MAGICIAN_EGPIO(1, 7)
++#define EGPIO_MAGICIAN_SD_POWER MAGICIAN_EGPIO(2, 0)
++#define EGPIO_MAGICIAN_CARKIT_MIC MAGICIAN_EGPIO(2, 1)
++#define EGPIO_MAGICIAN_UNKNOWN_WAVEDEV_DLL MAGICIAN_EGPIO(2, 2)
++#define EGPIO_MAGICIAN_FLASH_VPP MAGICIAN_EGPIO(2, 3)
++#define EGPIO_MAGICIAN_BL_POWER2 MAGICIAN_EGPIO(2, 4)
++#define EGPIO_MAGICIAN_CHARGE_EN MAGICIAN_EGPIO(2, 5)
++#define EGPIO_MAGICIAN_GSM_POWER MAGICIAN_EGPIO(2, 7)
++
++/* input */
++
++#define EGPIO_MAGICIAN_CABLE_STATE_AC MAGICIAN_EGPIO(4, 0)
++#define EGPIO_MAGICIAN_CABLE_STATE_USB MAGICIAN_EGPIO(4, 1)
++
++#define EGPIO_MAGICIAN_BOARD_ID0 MAGICIAN_EGPIO(5, 0)
++#define EGPIO_MAGICIAN_BOARD_ID1 MAGICIAN_EGPIO(5, 1)
++#define EGPIO_MAGICIAN_BOARD_ID2 MAGICIAN_EGPIO(5, 2)
++#define EGPIO_MAGICIAN_LCD_SELECT MAGICIAN_EGPIO(5, 3)
++#define EGPIO_MAGICIAN_nSD_READONLY MAGICIAN_EGPIO(5, 4)
++
++#define EGPIO_MAGICIAN_EP_INSERT MAGICIAN_EGPIO(6, 1)
++
+ #endif /* _MAGICIAN_H_ */
+diff --git a/include/asm-arm/arch-pxa/mfp-pxa25x.h b/include/asm-arm/arch-pxa/mfp-pxa25x.h
+new file mode 100644
+index 0000000..0499323
+--- /dev/null
++++ b/include/asm-arm/arch-pxa/mfp-pxa25x.h
+@@ -0,0 +1,161 @@
++#ifndef __ASM_ARCH_MFP_PXA25X_H
++#define __ASM_ARCH_MFP_PXA25X_H
++
++#include <asm/arch/mfp.h>
++#include <asm/arch/mfp-pxa2xx.h>
++
++/* GPIO */
++#define GPIO2_GPIO MFP_CFG_IN(GPIO2, AF0)
++#define GPIO3_GPIO MFP_CFG_IN(GPIO3, AF0)
++#define GPIO4_GPIO MFP_CFG_IN(GPIO4, AF0)
++#define GPIO5_GPIO MFP_CFG_IN(GPIO5, AF0)
++#define GPIO6_GPIO MFP_CFG_IN(GPIO6, AF0)
++#define GPIO7_GPIO MFP_CFG_IN(GPIO7, AF0)
++#define GPIO8_GPIO MFP_CFG_IN(GPIO8, AF0)
++
++#define GPIO1_RST MFP_CFG_IN(GPIO1, AF1)
++
++/* Crystal and Clock Signals */
++#define GPIO10_RTCCLK MFP_CFG_OUT(GPIO10, AF1, DRIVE_LOW)
++#define GPIO70_RTC_CLK MFP_CFG_OUT(GPIO70, AF1, DRIVE_LOW)
++#define GPIO7_48MHz MFP_CFG_OUT(GPIO7, AF1, DRIVE_LOW)
++#define GPIO11_3_6MHz MFP_CFG_OUT(GPIO11, AF1, DRIVE_LOW)
++#define GPIO71_3_6MHz MFP_CFG_OUT(GPIO71, AF1, DRIVE_LOW)
++#define GPIO12_32KHz MFP_CFG_OUT(GPIO12, AF1, DRIVE_LOW)
++#define GPIO72_32kHz MFP_CFG_OUT(GPIO72, AF1, DRIVE_LOW)
++
++/* SDRAM and Static Memory I/O Signals */
++#define GPIO15_nCS_1 MFP_CFG_OUT(GPIO15, AF2, DRIVE_HIGH)
++#define GPIO78_nCS_2 MFP_CFG_OUT(GPIO78, AF2, DRIVE_HIGH)
++#define GPIO79_nCS_3 MFP_CFG_OUT(GPIO79, AF2, DRIVE_HIGH)
++#define GPIO80_nCS_4 MFP_CFG_OUT(GPIO80, AF2, DRIVE_HIGH)
++#define GPIO33_nCS_5 MFP_CFG_OUT(GPIO33, AF2, DRIVE_HIGH)
++
++/* Miscellaneous I/O and DMA Signals */
++#define GPIO18_RDY MFP_CFG_IN(GPIO18, AF1)
++#define GPIO20_DREQ_0 MFP_CFG_IN(GPIO20, AF1)
++#define GPIO19_DREQ_1 MFP_CFG_IN(GPIO19, AF1)
++
++/* Alternate Bus Master Mode I/O Signals */
++#define GPIO13_MBGNT MFP_CFG_OUT(GPIO13, AF2, DRIVE_LOW)
++#define GPIO73_MBGNT MFP_CFG_OUT(GPIO73, AF1, DRIVE_LOW)
++#define GPIO14_MBREQ MFP_CFG_IN(GPIO14, AF1)
++#define GPIO66_MBREQ MFP_CFG_IN(GPIO66, AF1)
++
++/* PC CARD */
++#define GPIO52_nPCE_1 MFP_CFG_OUT(GPIO52, AF2, DRIVE_HIGH)
++#define GPIO53_nPCE_2 MFP_CFG_OUT(GPIO53, AF2, DRIVE_HIGH)
++#define GPIO55_nPREG MFP_CFG_OUT(GPIO55, AF2, DRIVE_HIGH)
++#define GPIO50_nPIOR MFP_CFG_OUT(GPIO50, AF2, DRIVE_HIGH)
++#define GPIO51_nPIOW MFP_CFG_OUT(GPIO51, AF2, DRIVE_HIGH)
++#define GPIO49_nPWE MFP_CFG_OUT(GPIO49, AF2, DRIVE_HIGH)
++#define GPIO48_nPOE MFP_CFG_OUT(GPIO48, AF2, DRIVE_HIGH)
++#define GPIO57_nIOIS16 MFP_CFG_IN(GPIO57, AF1)
++#define GPIO56_nPWAIT MFP_CFG_IN(GPIO56, AF1)
++#define GPIO54_nPSKTSEL MFP_CFG_OUT(GPIO54, AF2, DRIVE_HIGH)
++
++/* FFUART */
++#define GPIO34_FFUART_RXD MFP_CFG_IN(GPIO34, AF1)
++#define GPIO35_FFUART_CTS MFP_CFG_IN(GPIO35, AF1)
++#define GPIO36_FFUART_DCD MFP_CFG_IN(GPIO36, AF1)
++#define GPIO37_FFUART_DSR MFP_CFG_IN(GPIO37, AF1)
++#define GPIO38_FFUART_RI MFP_CFG_IN(GPIO38, AF1)
++#define GPIO39_FFUART_TXD MFP_CFG_OUT(GPIO39, AF2, DRIVE_HIGH)
++#define GPIO40_FFUART_DTR MFP_CFG_OUT(GPIO40, AF2, DRIVE_HIGH)
++#define GPIO41_FFUART_RTS MFP_CFG_OUT(GPIO41, AF2, DRIVE_HIGH)
++
++/* BTUART */
++#define GPIO42_BTUART_RXD MFP_CFG_IN(GPIO42, AF1)
++#define GPIO43_BTUART_TXD MFP_CFG_OUT(GPIO43, AF2, DRIVE_HIGH)
++#define GPIO44_BTUART_CTS MFP_CFG_IN(GPIO44, AF1)
++#define GPIO45_BTUART_RTS MFP_CFG_OUT(GPIO45, AF2, DRIVE_HIGH)
++
++/* STUART */
++#define GPIO46_STUART_RXD MFP_CFG_IN(GPIO46, AF2)
++#define GPIO47_STUART_TXD MFP_CFG_OUT(GPIO47, AF1, DRIVE_HIGH)
++
++/* HWUART */
++#define GPIO42_HWUART_RXD MFP_CFG_IN(GPIO42, AF3)
++#define GPIO43_HWUART_TXD MFP_CFG_OUT(GPIO43, AF3, DRIVE_HIGH)
++#define GPIO44_HWUART_CTS MFP_CFG_IN(GPIO44, AF3)
++#define GPIO45_HWUART_RTS MFP_CFG_OUT(GPIO45, AF3, DRIVE_HIGH)
++#define GPIO48_HWUART_TXD MFP_CFG_OUT(GPIO48, AF1, DRIVE_HIGH)
++#define GPIO49_HWUART_RXD MFP_CFG_IN(GPIO49, AF1)
++#define GPIO50_HWUART_CTS MFP_CFG_IN(GPIO50, AF1)
++#define GPIO51_HWUART_RTS MFP_CFG_OUT(GPIO51, AF1, DRIVE_HIGH)
++
++/* FICP */
++#define GPIO46_FICP_RXD MFP_CFG_IN(GPIO46, AF1)
++#define GPIO47_FICP_TXD MFP_CFG_OUT(GPIO47, AF2, DRIVE_HIGH)
++
++/* PWM 0/1 */
++#define GPIO16_PWM0_OUT MFP_CFG_OUT(GPIO16, AF2, DRIVE_LOW)
++#define GPIO17_PWM1_OUT MFP_CFG_OUT(GPIO17, AF2, DRIVE_LOW)
++
++/* AC97 */
++#define GPIO28_AC97_BITCLK MFP_CFG_IN(GPIO28, AF1)
++#define GPIO29_AC97_SDATA_IN_0 MFP_CFG_IN(GPIO29, AF1)
++#define GPIO30_AC97_SDATA_OUT MFP_CFG_OUT(GPIO30, AF2, DRIVE_LOW)
++#define GPIO31_AC97_SYNC MFP_CFG_OUT(GPIO31, AF2, DRIVE_LOW)
++#define GPIO32_AC97_SDATA_IN_1 MFP_CFG_IN(GPIO32, AF1)
++
++/* I2S */
++#define GPIO28_I2S_BITCLK_IN MFP_CFG_IN(GPIO28, AF2)
++#define GPIO28_I2S_BITCLK_OUT MFP_CFG_OUT(GPIO28, AF1, DRIVE_LOW)
++#define GPIO29_I2S_SDATA_IN MFP_CFG_IN(GPIO29, AF2)
++#define GPIO30_I2S_SDATA_OUT MFP_CFG_OUT(GPIO30, AF1, DRIVE_LOW)
++#define GPIO31_I2S_SYNC MFP_CFG_OUT(GPIO31, AF1, DRIVE_LOW)
++#define GPIO32_I2S_SYSCLK MFP_CFG_OUT(GPIO32, AF1, DRIVE_LOW)
++
++/* SSP 1 */
++#define GPIO23_SSP1_SCLK MFP_CFG_OUT(GPIO23, AF2, DRIVE_LOW)
++#define GPIO24_SSP1_SFRM MFP_CFG_OUT(GPIO24, AF2, DRIVE_LOW)
++#define GPIO25_SSP1_TXD MFP_CFG_OUT(GPIO25, AF2, DRIVE_LOW)
++#define GPIO26_SSP1_RXD MFP_CFG_IN(GPIO26, AF1)
++#define GPIO27_SSP1_EXTCLK MFP_CFG_IN(GPIO27, AF1)
++
++/* SSP 2 - NSSP */
++#define GPIO81_SSP2_CLK_OUT MFP_CFG_OUT(GPIO81, AF1, DRIVE_LOW)
++#define GPIO81_SSP2_CLK_IN MFP_CFG_IN(GPIO81, AF1)
++#define GPIO82_SSP2_FRM_OUT MFP_CFG_OUT(GPIO82, AF1, DRIVE_LOW)
++#define GPIO82_SSP2_FRM_IN MFP_CFG_IN(GPIO82, AF1)
++#define GPIO83_SSP2_TXD MFP_CFG_OUT(GPIO83, AF1, DRIVE_LOW)
++#define GPIO83_SSP2_RXD MFP_CFG_IN(GPIO83, AF2)
++#define GPIO84_SSP2_TXD MFP_CFG_OUT(GPIO84, AF1, DRIVE_LOW)
++#define GPIO84_SSP2_RXD MFP_CFG_IN(GPIO84, AF2)
++
++/* MMC */
++#define GPIO6_MMC_CLK MFP_CFG_OUT(GPIO6, AF1, DRIVE_LOW)
++#define GPIO8_MMC_CS0 MFP_CFG_OUT(GPIO8, AF1, DRIVE_LOW)
++#define GPIO9_MMC_CS1 MFP_CFG_OUT(GPIO9, AF1, DRIVE_LOW)
++#define GPIO34_MMC_CS0 MFP_CFG_OUT(GPIO34, AF2, DRIVE_LOW)
++#define GPIO39_MMC_CS1 MFP_CFG_OUT(GPIO39, AF1, DRIVE_LOW)
++#define GPIO53_MMC_CLK MFP_CFG_OUT(GPIO53, AF1, DRIVE_LOW)
++#define GPIO54_MMC_CLK MFP_CFG_OUT(GPIO54, AF1, DRIVE_LOW)
++#define GPIO69_MMC_CLK MFP_CFG_OUT(GPIO69, AF1, DRIVE_LOW)
++#define GPIO67_MMC_CS0 MFP_CFG_OUT(GPIO67, AF1, DRIVE_LOW)
++#define GPIO68_MMC_CS1 MFP_CFG_OUT(GPIO68, AF1, DRIVE_LOW)
++
++/* LCD */
++#define GPIO58_LCD_LDD_0 MFP_CFG_OUT(GPIO58, AF2, DRIVE_LOW)
++#define GPIO59_LCD_LDD_1 MFP_CFG_OUT(GPIO59, AF2, DRIVE_LOW)
++#define GPIO60_LCD_LDD_2 MFP_CFG_OUT(GPIO60, AF2, DRIVE_LOW)
++#define GPIO61_LCD_LDD_3 MFP_CFG_OUT(GPIO61, AF2, DRIVE_LOW)
++#define GPIO62_LCD_LDD_4 MFP_CFG_OUT(GPIO62, AF2, DRIVE_LOW)
++#define GPIO63_LCD_LDD_5 MFP_CFG_OUT(GPIO63, AF2, DRIVE_LOW)
++#define GPIO64_LCD_LDD_6 MFP_CFG_OUT(GPIO64, AF2, DRIVE_LOW)
++#define GPIO65_LCD_LDD_7 MFP_CFG_OUT(GPIO65, AF2, DRIVE_LOW)
++#define GPIO66_LCD_LDD_8 MFP_CFG_OUT(GPIO66, AF2, DRIVE_LOW)
++#define GPIO67_LCD_LDD_9 MFP_CFG_OUT(GPIO67, AF2, DRIVE_LOW)
++#define GPIO68_LCD_LDD_10 MFP_CFG_OUT(GPIO68, AF2, DRIVE_LOW)
++#define GPIO69_LCD_LDD_11 MFP_CFG_OUT(GPIO69, AF2, DRIVE_LOW)
++#define GPIO70_LCD_LDD_12 MFP_CFG_OUT(GPIO70, AF2, DRIVE_LOW)
++#define GPIO71_LCD_LDD_13 MFP_CFG_OUT(GPIO71, AF2, DRIVE_LOW)
++#define GPIO72_LCD_LDD_14 MFP_CFG_OUT(GPIO72, AF2, DRIVE_LOW)
++#define GPIO73_LCD_LDD_15 MFP_CFG_OUT(GPIO73, AF2, DRIVE_LOW)
++#define GPIO74_LCD_FCLK MFP_CFG_OUT(GPIO74, AF2, DRIVE_LOW)
++#define GPIO75_LCD_LCLK MFP_CFG_OUT(GPIO75, AF2, DRIVE_LOW)
++#define GPIO76_LCD_PCLK MFP_CFG_OUT(GPIO76, AF2, DRIVE_LOW)
++#define GPIO77_LCD_ACBIAS MFP_CFG_OUT(GPIO77, AF2, DRIVE_LOW)
++
++#endif /* __ASM_ARCH_MFP_PXA25X_H */
+diff --git a/include/asm-arm/arch-pxa/mfp-pxa27x.h b/include/asm-arm/arch-pxa/mfp-pxa27x.h
+new file mode 100644
+index 0000000..eb6eaa1
+--- /dev/null
++++ b/include/asm-arm/arch-pxa/mfp-pxa27x.h
+@@ -0,0 +1,432 @@
++#ifndef __ASM_ARCH_MFP_PXA27X_H
++#define __ASM_ARCH_MFP_PXA27X_H
++
++/*
++ * NOTE: for those special-function bidirectional GPIOs, as described
++ * in the "PXA27x Developer's Manual" Section 24.4.2.1, only its input
++ * alternative is preserved, the direction is actually selected by the
++ * specific controller, and this should work in most cases.
++ */
++
++#include <asm/arch/mfp.h>
++#include <asm/arch/mfp-pxa2xx.h>
++
++/* GPIO */
++#define GPIO85_GPIO MFP_CFG_IN(GPIO85, AF0)
++#define GPIO86_GPIO MFP_CFG_IN(GPIO86, AF0)
++#define GPIO87_GPIO MFP_CFG_IN(GPIO87, AF0)
++#define GPIO88_GPIO MFP_CFG_IN(GPIO88, AF0)
++#define GPIO89_GPIO MFP_CFG_IN(GPIO89, AF0)
++#define GPIO90_GPIO MFP_CFG_IN(GPIO90, AF0)
++#define GPIO91_GPIO MFP_CFG_IN(GPIO91, AF0)
++#define GPIO92_GPIO MFP_CFG_IN(GPIO92, AF0)
++#define GPIO93_GPIO MFP_CFG_IN(GPIO93, AF0)
++#define GPIO94_GPIO MFP_CFG_IN(GPIO94, AF0)
++#define GPIO95_GPIO MFP_CFG_IN(GPIO95, AF0)
++#define GPIO96_GPIO MFP_CFG_IN(GPIO96, AF0)
++#define GPIO97_GPIO MFP_CFG_IN(GPIO97, AF0)
++#define GPIO98_GPIO MFP_CFG_IN(GPIO98, AF0)
++#define GPIO99_GPIO MFP_CFG_IN(GPIO99, AF0)
++#define GPIO100_GPIO MFP_CFG_IN(GPIO100, AF0)
++#define GPIO101_GPIO MFP_CFG_IN(GPIO101, AF0)
++#define GPIO102_GPIO MFP_CFG_IN(GPIO102, AF0)
++#define GPIO103_GPIO MFP_CFG_IN(GPIO103, AF0)
++#define GPIO104_GPIO MFP_CFG_IN(GPIO104, AF0)
++#define GPIO105_GPIO MFP_CFG_IN(GPIO105, AF0)
++#define GPIO106_GPIO MFP_CFG_IN(GPIO106, AF0)
++#define GPIO107_GPIO MFP_CFG_IN(GPIO107, AF0)
++#define GPIO108_GPIO MFP_CFG_IN(GPIO108, AF0)
++#define GPIO109_GPIO MFP_CFG_IN(GPIO109, AF0)
++#define GPIO110_GPIO MFP_CFG_IN(GPIO110, AF0)
++#define GPIO111_GPIO MFP_CFG_IN(GPIO111, AF0)
++#define GPIO112_GPIO MFP_CFG_IN(GPIO112, AF0)
++#define GPIO113_GPIO MFP_CFG_IN(GPIO113, AF0)
++#define GPIO114_GPIO MFP_CFG_IN(GPIO114, AF0)
++#define GPIO115_GPIO MFP_CFG_IN(GPIO115, AF0)
++#define GPIO116_GPIO MFP_CFG_IN(GPIO116, AF0)
++#define GPIO117_GPIO MFP_CFG_IN(GPIO117, AF0)
++#define GPIO118_GPIO MFP_CFG_IN(GPIO118, AF0)
++#define GPIO119_GPIO MFP_CFG_IN(GPIO119, AF0)
++#define GPIO120_GPIO MFP_CFG_IN(GPIO120, AF0)
++
++/* Crystal and Clock Signals */
++#define GPIO9_HZ_CLK MFP_CFG_OUT(GPIO9, AF1, DRIVE_LOW)
++#define GPIO10_HZ_CLK MFP_CFG_OUT(GPIO10, AF1, DRIVE_LOW)
++#define GPIO11_48_MHz MFP_CFG_OUT(GPIO11, AF3, DRIVE_LOW)
++#define GPIO12_48_MHz MFP_CFG_OUT(GPIO12, AF3, DRIVE_LOW)
++#define GPIO13_CLK_EXT MFP_CFG_IN(GPIO13, AF1)
++
++/* OS Timer Signals */
++#define GPIO11_EXT_SYNC_0 MFP_CFG_IN(GPIO11, AF1)
++#define GPIO12_EXT_SYNC_1 MFP_CFG_IN(GPIO12, AF1)
++#define GPIO9_CHOUT_0 MFP_CFG_OUT(GPIO9, AF3, DRIVE_LOW)
++#define GPIO10_CHOUT_1 MFP_CFG_OUT(GPIO10, AF3, DRIVE_LOW)
++#define GPIO11_CHOUT_0 MFP_CFG_OUT(GPIO11, AF1, DRIVE_LOW)
++#define GPIO12_CHOUT_1 MFP_CFG_OUT(GPIO12, AF1, DRIVE_LOW)
++
++/* SDRAM and Static Memory I/O Signals */
++#define GPIO20_nSDCS_2 MFP_CFG_OUT(GPIO20, AF1, DRIVE_HIGH)
++#define GPIO21_nSDCS_3 MFP_CFG_OUT(GPIO21, AF1, DRIVE_HIGH)
++#define GPIO15_nCS_1 MFP_CFG_OUT(GPIO15, AF2, DRIVE_HIGH)
++#define GPIO78_nCS_2 MFP_CFG_OUT(GPIO78, AF2, DRIVE_HIGH)
++#define GPIO79_nCS_3 MFP_CFG_OUT(GPIO79, AF2, DRIVE_HIGH)
++#define GPIO80_nCS_4 MFP_CFG_OUT(GPIO80, AF2, DRIVE_HIGH)
++#define GPIO33_nCS_5 MFP_CFG_OUT(GPIO33, AF2, DRIVE_HIGH)
++
++/* Miscellaneous I/O and DMA Signals */
++#define GPIO21_DVAL_0 MFP_CFG_OUT(GPIO21, AF2, DRIVE_HIGH)
++#define GPIO116_DVAL_0 MFP_CFG_OUT(GPIO116, AF1, DRIVE_HIGH)
++#define GPIO33_DVAL_1 MFP_CFG_OUT(GPIO33, AF1, DRIVE_HIGH)
++#define GPIO96_DVAL_1 MFP_CFG_OUT(GPIO96, AF2, DRIVE_HIGH)
++#define GPIO18_RDY MFP_CFG_IN(GPIO18, AF1)
++#define GPIO20_DREQ_0 MFP_CFG_IN(GPIO20, AF1)
++#define GPIO115_DREQ_0 MFP_CFG_IN(GPIO115, AF1)
++#define GPIO80_DREQ_1 MFP_CFG_IN(GPIO80, AF1)
++#define GPIO97_DREQ_1 MFP_CFG_IN(GPIO97, AF2)
++#define GPIO85_DREQ_2 MFP_CFG_IN(GPIO85, AF2)
++#define GPIO100_DREQ_2 MFP_CFG_IN(GPIO100, AF2)
++
++/* Alternate Bus Master Mode I/O Signals */
++#define GPIO20_MBREQ MFP_CFG_IN(GPIO20, AF2)
++#define GPIO80_MBREQ MFP_CFG_IN(GPIO80, AF2)
++#define GPIO96_MBREQ MFP_CFG_IN(GPIO96, AF2)
++#define GPIO115_MBREQ MFP_CFG_IN(GPIO115, AF3)
++#define GPIO21_MBGNT MFP_CFG_OUT(GPIO21, AF3, DRIVE_LOW)
++#define GPIO33_MBGNT MFP_CFG_OUT(GPIO33, AF3, DRIVE_LOW)
++#define GPIO97_MBGNT MFP_CFG_OUT(GPIO97, AF2, DRIVE_LOW)
++#define GPIO116_MBGNT MFP_CFG_OUT(GPIO116, AF3, DRIVE_LOW)
++
++/* PC CARD */
++#define GPIO15_nPCE_1 MFP_CFG_OUT(GPIO15, AF1, DRIVE_HIGH)
++#define GPIO85_nPCE_1 MFP_CFG_OUT(GPIO85, AF1, DRIVE_HIGH)
++#define GPIO86_nPCE_1 MFP_CFG_OUT(GPIO86, AF1, DRIVE_HIGH)
++#define GPIO102_nPCE_1 MFP_CFG_OUT(GPIO102, AF1, DRIVE_HIGH)
++#define GPIO54_nPCE_2 MFP_CFG_OUT(GPIO54, AF2, DRIVE_HIGH)
++#define GPIO78_nPCE_2 MFP_CFG_OUT(GPIO78, AF1, DRIVE_HIGH)
++#define GPIO87_nPCE_2 MFP_CFG_IN(GPIO87, AF1)
++#define GPIO55_nPREG MFP_CFG_OUT(GPIO55, AF2, DRIVE_HIGH)
++#define GPIO50_nPIOR MFP_CFG_OUT(GPIO50, AF2, DRIVE_HIGH)
++#define GPIO51_nPIOW MFP_CFG_OUT(GPIO51, AF2, DRIVE_HIGH)
++#define GPIO49_nPWE MFP_CFG_OUT(GPIO49, AF2, DRIVE_HIGH)
++#define GPIO48_nPOE MFP_CFG_OUT(GPIO48, AF2, DRIVE_HIGH)
++#define GPIO57_nIOIS16 MFP_CFG_IN(GPIO57, AF1)
++#define GPIO56_nPWAIT MFP_CFG_IN(GPIO56, AF1)
++#define GPIO79_PSKTSEL MFP_CFG_OUT(GPIO79, AF1, DRIVE_HIGH)
++
++/* I2C */
++#define GPIO117_I2C_SCL MFP_CFG_IN(GPIO117, AF1)
++#define GPIO118_I2C_SDA MFP_CFG_IN(GPIO118, AF1)
++
++/* FFUART */
++#define GPIO9_FFUART_CTS MFP_CFG_IN(GPIO9, AF3)
++#define GPIO26_FFUART_CTS MFP_CFG_IN(GPIO26, AF3)
++#define GPIO35_FFUART_CTS MFP_CFG_IN(GPIO35, AF1)
++#define GPIO100_FFUART_CTS MFP_CFG_IN(GPIO100, AF3)
++#define GPIO10_FFUART_DCD MFP_CFG_IN(GPIO10, AF1)
++#define GPIO36_FFUART_DCD MFP_CFG_IN(GPIO36, AF1)
++#define GPIO33_FFUART_DSR MFP_CFG_IN(GPIO33, AF2)
++#define GPIO37_FFUART_DSR MFP_CFG_IN(GPIO37, AF1)
++#define GPIO38_FFUART_RI MFP_CFG_IN(GPIO38, AF1)
++#define GPIO89_FFUART_RI MFP_CFG_IN(GPIO89, AF3)
++#define GPIO19_FFUART_RXD MFP_CFG_IN(GPIO19, AF3)
++#define GPIO33_FFUART_RXD MFP_CFG_IN(GPIO33, AF1)
++#define GPIO34_FFUART_RXD MFP_CFG_IN(GPIO34, AF1)
++#define GPIO41_FFUART_RXD MFP_CFG_IN(GPIO41, AF1)
++#define GPIO53_FFUART_RXD MFP_CFG_IN(GPIO53, AF1)
++#define GPIO85_FFUART_RXD MFP_CFG_IN(GPIO85, AF1)
++#define GPIO96_FFUART_RXD MFP_CFG_IN(GPIO96, AF3)
++#define GPIO102_FFUART_RXD MFP_CFG_IN(GPIO102, AF3)
++#define GPIO16_FFUART_TXD MFP_CFG_OUT(GPIO16, AF3, DRIVE_HIGH)
++#define GPIO37_FFUART_TXD MFP_CFG_OUT(GPIO37, AF3, DRIVE_HIGH)
++#define GPIO39_FFUART_TXD MFP_CFG_OUT(GPIO39, AF2, DRIVE_HIGH)
++#define GPIO83_FFUART_TXD MFP_CFG_OUT(GPIO83, AF2, DRIVE_HIGH)
++#define GPIO99_FFUART_TXD MFP_CFG_OUT(GPIO99, AF3, DRIVE_HIGH)
++#define GPIO27_FFUART_RTS MFP_CFG_OUT(GPIO27, AF3, DRIVE_HIGH)
++#define GPIO41_FFUART_RTS MFP_CFG_OUT(GPIO41, AF2, DRIVE_HIGH)
++#define GPIO83_FFUART_RTS MFP_CFG_OUT(GPIO83, AF3, DRIVE_HIGH)
++#define GPIO98_FFUART_RTS MFP_CFG_OUT(GPIO98, AF3, DRIVE_HIGH)
++#define GPIO40_FFUART_DTR MFP_CFG_OUT(GPIO40, AF2, DRIVE_HIGH)
++#define GPIO82_FFUART_DTR MFP_CFG_OUT(GPIO82, AF3, DRIVE_HIGH)
++
++/* BTUART */
++#define GPIO44_BTUART_CTS MFP_CFG_IN(GPIO44, AF1)
++#define GPIO42_BTUART_RXD MFP_CFG_IN(GPIO42, AF1)
++#define GPIO45_BTUART_RTS MFP_CFG_OUT(GPIO45, AF2, DRIVE_HIGH)
++#define GPIO43_BTUART_TXD MFP_CFG_OUT(GPIO43, AF2, DRIVE_HIGH)
++
++/* STUART */
++#define GPIO46_STUART_RXD MFP_CFG_IN(GPIO46, AF2)
++#define GPIO47_STUART_TXD MFP_CFG_OUT(GPIO47, AF1, DRIVE_HIGH)
++
++/* FICP */
++#define GPIO42_FICP_RXD MFP_CFG_IN(GPIO42, AF2)
++#define GPIO46_FICP_RXD MFP_CFG_IN(GPIO46, AF1)
++#define GPIO43_FICP_TXD MFP_CFG_OUT(GPIO43, AF1, DRIVE_HIGH)
++#define GPIO47_FICP_TXD MFP_CFG_OUT(GPIO47, AF2, DRIVE_HIGH)
++
++/* PWM 0/1/2/3 */
++#define GPIO11_PWM2_OUT MFP_CFG_OUT(GPIO11, AF2, DRIVE_LOW)
++#define GPIO12_PWM3_OUT MFP_CFG_OUT(GPIO12, AF2, DRIVE_LOW)
++#define GPIO16_PWM0_OUT MFP_CFG_OUT(GPIO16, AF2, DRIVE_LOW)
++#define GPIO17_PWM1_OUT MFP_CFG_OUT(GPIO17, AF2, DRIVE_LOW)
++#define GPIO38_PWM1_OUT MFP_CFG_OUT(GPIO38, AF3, DRIVE_LOW)
++#define GPIO46_PWM2_OUT MFP_CFG_OUT(GPIO46, AF2, DRIVE_LOW)
++#define GPIO47_PWM3_OUT MFP_CFG_OUT(GPIO47, AF3, DRIVE_LOW)
++#define GPIO79_PWM2_OUT MFP_CFG_OUT(GPIO79, AF3, DRIVE_LOW)
++#define GPIO80_PWM3_OUT MFP_CFG_OUT(GPIO80, AF3, DRIVE_LOW)
++#define GPIO115_PWM1_OUT MFP_CFG_OUT(GPIO115, AF3, DRIVE_LOW)
++
++/* AC97 */
++#define GPIO31_AC97_SYNC MFP_CFG_OUT(GPIO31, AF2, DRIVE_LOW)
++#define GPIO94_AC97_SYNC MFP_CFG_OUT(GPIO94, AF1, DRIVE_LOW)
++#define GPIO30_AC97_SDATA_OUT MFP_CFG_OUT(GPIO30, AF2, DRIVE_LOW)
++#define GPIO93_AC97_SDATA_OUT MFP_CFG_OUT(GPIO93, AF1, DRIVE_LOW)
++#define GPIO45_AC97_SYSCLK MFP_CFG_OUT(GPIO45, AF1, DRIVE_LOW)
++#define GPIO89_AC97_SYSCLK MFP_CFG_OUT(GPIO89, AF1, DRIVE_LOW)
++#define GPIO98_AC97_SYSCLK MFP_CFG_OUT(GPIO98, AF1, DRIVE_LOW)
++#define GPIO95_AC97_nRESET MFP_CFG_OUT(GPIO95, AF1, DRIVE_LOW)
++#define GPIO113_AC97_nRESET MFP_CFG_OUT(GPIO113, AF2, DRIVE_LOW)
++#define GPIO28_AC97_BITCLK MFP_CFG_IN(GPIO28, AF1)
++#define GPIO29_AC97_SDATA_IN_0 MFP_CFG_IN(GPIO29, AF1)
++#define GPIO116_AC97_SDATA_IN_0 MFP_CFG_IN(GPIO116, AF2)
++#define GPIO99_AC97_SDATA_IN_1 MFP_CFG_IN(GPIO99, AF2)
++
++/* I2S */
++#define GPIO28_I2S_BITCLK_IN MFP_CFG_IN(GPIO28, AF2)
++#define GPIO28_I2S_BITCLK_OUT MFP_CFG_OUT(GPIO28, AF1, DRIVE_LOW)
++#define GPIO29_I2S_SDATA_IN MFP_CFG_IN(GPIO29, AF2)
++#define GPIO30_I2S_SDATA_OUT MFP_CFG_OUT(GPIO30, AF1, DRIVE_LOW)
++#define GPIO31_I2S_SYNC MFP_CFG_OUT(GPIO31, AF1, DRIVE_LOW)
++#define GPIO113_I2S_SYSCLK MFP_CFG_OUT(GPIO113, AF1, DRIVE_LOW)
++
++/* SSP 1 */
++#define GPIO23_SSP1_SCLK MFP_CFG_OUT(GPIO23, AF2, DRIVE_LOW)
++#define GPIO29_SSP1_SCLK MFP_CFG_IN(GPIO29, AF3)
++#define GPIO27_SSP1_SYSCLK MFP_CFG_OUT(GPIO27, AF1, DRIVE_LOW)
++#define GPIO53_SSP1_SYSCLK MFP_CFG_OUT(GPIO53, AF3, DRIVE_LOW)
++#define GPIO24_SSP1_SFRM MFP_CFG_IN(GPIO24, AF2)
++#define GPIO28_SSP1_SFRM MFP_CFG_IN(GPIO28, AF3)
++#define GPIO25_SSP1_TXD MFP_CFG_OUT(GPIO25, AF2, DRIVE_LOW)
++#define GPIO57_SSP1_TXD MFP_CFG_OUT(GPIO57, AF3, DRIVE_LOW)
++#define GPIO26_SSP1_RXD MFP_CFG_IN(GPIO26, AF1)
++#define GPIO27_SSP1_SCLKEN MFP_CFG_IN(GPIO27, AF2)
++
++/* SSP 2 */
++#define GPIO19_SSP2_SCLK MFP_CFG_IN(GPIO19, AF1)
++#define GPIO22_SSP2_SCLK MFP_CFG_IN(GPIO22, AF3)
++#define GPIO29_SSP2_SCLK MFP_CFG_OUT(GPIO29, AF3, DRIVE_LOW)
++#define GPIO36_SSP2_SCLK MFP_CFG_IN(GPIO36, AF2)
++#define GPIO50_SSP2_SCLK MFP_CFG_IN(GPIO50, AF3)
++#define GPIO22_SSP2_SYSCLK MFP_CFG_OUT(GPIO22, AF2, DRIVE_LOW)
++#define GPIO14_SSP2_SFRM MFP_CFG_IN(GPIO14, AF2)
++#define GPIO37_SSP2_SFRM MFP_CFG_IN(GPIO37, AF2)
++#define GPIO87_SSP2_SFRM MFP_CFG_OUT(GPIO87, AF3, DRIVE_LOW)
++#define GPIO88_SSP2_SFRM MFP_CFG_IN(GPIO88, AF3)
++#define GPIO13_SSP2_TXD MFP_CFG_OUT(GPIO13, AF1, DRIVE_LOW)
++#define GPIO38_SSP2_TXD MFP_CFG_OUT(GPIO38, AF2, DRIVE_LOW)
++#define GPIO87_SSP2_TXD MFP_CFG_OUT(GPIO87, AF1, DRIVE_LOW)
++#define GPIO89_SSP2_TXD MFP_CFG_OUT(GPIO89, AF3, DRIVE_LOW)
++#define GPIO11_SSP2_RXD MFP_CFG_IN(GPIO11, AF2)
++#define GPIO29_SSP2_RXD MFP_CFG_OUT(GPIO29, AF1, DRIVE_LOW)
++#define GPIO40_SSP2_RXD MFP_CFG_IN(GPIO40, AF1)
++#define GPIO86_SSP2_RXD MFP_CFG_IN(GPIO86, AF1)
++#define GPIO88_SSP2_RXD MFP_CFG_IN(GPIO88, AF2)
++#define GPIO22_SSP2_EXTCLK MFP_CFG_IN(GPIO22, AF1)
++#define GPIO27_SSP2_EXTCLK MFP_CFG_IN(GPIO27, AF1)
++#define GPIO22_SSP2_SCLKEN MFP_CFG_IN(GPIO22, AF2)
++#define GPIO23_SSP2_SCLKEN MFP_CFG_IN(GPIO23, AF2)
++
++/* SSP 3 */
++#define GPIO34_SSP3_SCLK MFP_CFG_IN(GPIO34, AF3)
++#define GPIO40_SSP3_SCLK MFP_CFG_OUT(GPIO40, AF3, DRIVE_LOW)
++#define GPIO52_SSP3_SCLK MFP_CFG_IN(GPIO52, AF2)
++#define GPIO84_SSP3_SCLK MFP_CFG_IN(GPIO84, AF1)
++#define GPIO45_SSP3_SYSCLK MFP_CFG_OUT(GPIO45, AF3, DRIVE_LOW)
++#define GPIO35_SSP3_SFRM MFP_CFG_IN(GPIO35, AF3)
++#define GPIO39_SSP3_SFRM MFP_CFG_IN(GPIO39, AF3)
++#define GPIO83_SSP3_SFRM MFP_CFG_IN(GPIO83, AF1)
++#define GPIO35_SSP3_TXD MFP_CFG_OUT(GPIO35, AF3, DRIVE_LOW)
++#define GPIO38_SSP3_TXD MFP_CFG_OUT(GPIO38, AF1, DRIVE_LOW)
++#define GPIO81_SSP3_TXD MFP_CFG_OUT(GPIO81, AF1, DRIVE_LOW)
++#define GPIO41_SSP3_RXD MFP_CFG_IN(GPIO41, AF3)
++#define GPIO82_SSP3_RXD MFP_CFG_IN(GPIO82, AF1)
++#define GPIO89_SSP3_RXD MFP_CFG_IN(GPIO89, AF1)
++
++/* MMC */
++#define GPIO32_MMC_CLK MFP_CFG_OUT(GPIO32, AF2, DRIVE_LOW)
++#define GPIO92_MMC_DAT_0 MFP_CFG_IN(GPIO92, AF1)
++#define GPIO109_MMC_DAT_1 MFP_CFG_IN(GPIO109, AF1)
++#define GPIO110_MMC_DAT_2 MFP_CFG_IN(GPIO110, AF1)
++#define GPIO111_MMC_DAT_3 MFP_CFG_IN(GPIO111, AF1)
++#define GPIO112_MMC_CMD MFP_CFG_IN(GPIO112, AF1)
++
++/* LCD */
++#define GPIO58_LCD_LDD_0 MFP_CFG_OUT(GPIO58, AF2, DRIVE_LOW)
++#define GPIO59_LCD_LDD_1 MFP_CFG_OUT(GPIO59, AF2, DRIVE_LOW)
++#define GPIO60_LCD_LDD_2 MFP_CFG_OUT(GPIO60, AF2, DRIVE_LOW)
++#define GPIO61_LCD_LDD_3 MFP_CFG_OUT(GPIO61, AF2, DRIVE_LOW)
++#define GPIO62_LCD_LDD_4 MFP_CFG_OUT(GPIO62, AF2, DRIVE_LOW)
++#define GPIO63_LCD_LDD_5 MFP_CFG_OUT(GPIO63, AF2, DRIVE_LOW)
++#define GPIO64_LCD_LDD_6 MFP_CFG_OUT(GPIO64, AF2, DRIVE_LOW)
++#define GPIO65_LCD_LDD_7 MFP_CFG_OUT(GPIO65, AF2, DRIVE_LOW)
++#define GPIO66_LCD_LDD_8 MFP_CFG_OUT(GPIO66, AF2, DRIVE_LOW)
++#define GPIO67_LCD_LDD_9 MFP_CFG_OUT(GPIO67, AF2, DRIVE_LOW)
++#define GPIO68_LCD_LDD_10 MFP_CFG_OUT(GPIO68, AF2, DRIVE_LOW)
++#define GPIO69_LCD_LDD_11 MFP_CFG_OUT(GPIO69, AF2, DRIVE_LOW)
++#define GPIO70_LCD_LDD_12 MFP_CFG_OUT(GPIO70, AF2, DRIVE_LOW)
++#define GPIO71_LCD_LDD_13 MFP_CFG_OUT(GPIO71, AF2, DRIVE_LOW)
++#define GPIO72_LCD_LDD_14 MFP_CFG_OUT(GPIO72, AF2, DRIVE_LOW)
++#define GPIO73_LCD_LDD_15 MFP_CFG_OUT(GPIO73, AF2, DRIVE_LOW)
++#define GPIO86_LCD_LDD_16 MFP_CFG_OUT(GPIO86, AF2, DRIVE_LOW)
++#define GPIO87_LCD_LDD_17 MFP_CFG_OUT(GPIO87, AF2, DRIVE_LOW)
++#define GPIO74_LCD_FCLK MFP_CFG_OUT(GPIO74, AF2, DRIVE_LOW)
++#define GPIO75_LCD_LCLK MFP_CFG_OUT(GPIO75, AF2, DRIVE_LOW)
++#define GPIO76_LCD_PCLK MFP_CFG_OUT(GPIO76, AF2, DRIVE_LOW)
++#define GPIO77_LCD_BIAS MFP_CFG_OUT(GPIO77, AF2, DRIVE_LOW)
++#define GPIO14_LCD_VSYNC MFP_CFG_IN(GPIO14, AF1)
++#define GPIO19_LCD_CS MFP_CFG_OUT(GPIO19, AF2, DRIVE_LOW)
++
++/* Keypad */
++#define GPIO93_KP_DKIN_0 MFP_CFG_IN(GPIO93, AF1)
++#define GPIO94_KP_DKIN_1 MFP_CFG_IN(GPIO94, AF1)
++#define GPIO95_KP_DKIN_2 MFP_CFG_IN(GPIO95, AF1)
++#define GPIO96_KP_DKIN_3 MFP_CFG_IN(GPIO96, AF1)
++#define GPIO97_KP_DKIN_4 MFP_CFG_IN(GPIO97, AF1)
++#define GPIO98_KP_DKIN_5 MFP_CFG_IN(GPIO98, AF1)
++#define GPIO99_KP_DKIN_6 MFP_CFG_IN(GPIO99, AF1)
++#define GPIO13_KP_KDIN_7 MFP_CFG_IN(GPIO13, AF2)
++#define GPIO100_KP_MKIN_0 MFP_CFG_IN(GPIO100, AF1)
++#define GPIO101_KP_MKIN_1 MFP_CFG_IN(GPIO101, AF1)
++#define GPIO102_KP_MKIN_2 MFP_CFG_IN(GPIO102, AF1)
++#define GPIO34_KP_MKIN_3 MFP_CFG_IN(GPIO34, AF2)
++#define GPIO37_KP_MKIN_3 MFP_CFG_IN(GPIO37, AF3)
++#define GPIO97_KP_MKIN_3 MFP_CFG_IN(GPIO97, AF3)
++#define GPIO98_KP_MKIN_4 MFP_CFG_IN(GPIO98, AF3)
++#define GPIO38_KP_MKIN_4 MFP_CFG_IN(GPIO38, AF2)
++#define GPIO39_KP_MKIN_4 MFP_CFG_IN(GPIO39, AF1)
++#define GPIO16_KP_MKIN_5 MFP_CFG_IN(GPIO16, AF1)
++#define GPIO90_KP_MKIN_5 MFP_CFG_IN(GPIO90, AF1)
++#define GPIO99_KP_MKIN_5 MFP_CFG_IN(GPIO99, AF3)
++#define GPIO17_KP_MKIN_6 MFP_CFG_IN(GPIO17, AF1)
++#define GPIO91_KP_MKIN_6 MFP_CFG_IN(GPIO91, AF1)
++#define GPIO95_KP_MKIN_6 MFP_CFG_IN(GPIO95, AF3)
++#define GPIO13_KP_MKIN_7 MFP_CFG_IN(GPIO13, AF3)
++#define GPIO36_KP_MKIN_7 MFP_CFG_IN(GPIO36, AF3)
++#define GPIO103_KP_MKOUT_0 MFP_CFG_OUT(GPIO103, AF2, DRIVE_HIGH)
++#define GPIO104_KP_MKOUT_1 MFP_CFG_OUT(GPIO104, AF2, DRIVE_HIGH)
++#define GPIO105_KP_MKOUT_2 MFP_CFG_OUT(GPIO105, AF2, DRIVE_HIGH)
++#define GPIO106_KP_MKOUT_3 MFP_CFG_OUT(GPIO106, AF2, DRIVE_HIGH)
++#define GPIO107_KP_MKOUT_4 MFP_CFG_OUT(GPIO107, AF2, DRIVE_HIGH)
++#define GPIO108_KP_MKOUT_5 MFP_CFG_OUT(GPIO108, AF2, DRIVE_HIGH)
++#define GPIO35_KP_MKOUT_6 MFP_CFG_OUT(GPIO35, AF2, DRIVE_HIGH)
++#define GPIO22_KP_MKOUT_7 MFP_CFG_OUT(GPIO22, AF1, DRIVE_HIGH)
++#define GPIO40_KP_MKOUT_6 MFP_CFG_OUT(GPIO40, AF1, DRIVE_HIGH)
++#define GPIO41_KP_MKOUT_7 MFP_CFG_OUT(GPIO41, AF1, DRIVE_HIGH)
++#define GPIO96_KP_MKOUT_6 MFP_CFG_OUT(GPIO96, AF3, DRIVE_HIGH)
++
++/* USB P3 */
++#define GPIO10_USB_P3_5 MFP_CFG_IN(GPIO10, AF3)
++#define GPIO11_USB_P3_1 MFP_CFG_IN(GPIO11, AF3)
++#define GPIO30_USB_P3_2 MFP_CFG_OUT(GPIO30, AF3, DRIVE_LOW)
++#define GPIO31_USB_P3_6 MFP_CFG_OUT(GPIO31, AF3, DRIVE_LOW)
++#define GPIO56_USB_P3_4 MFP_CFG_OUT(GPIO56, AF1, DRIVE_LOW)
++#define GPIO86_USB_P3_5 MFP_CFG_IN(GPIO86, AF3)
++#define GPIO87_USB_P3_1 MFP_CFG_IN(GPIO87, AF3)
++#define GPIO90_USB_P3_5 MFP_CFG_IN(GPIO90, AF2)
++#define GPIO91_USB_P3_1 MFP_CFG_IN(GPIO91, AF2)
++#define GPIO113_USB_P3_3 MFP_CFG_IN(GPIO113, AF3)
++
++/* USB P2 */
++#define GPIO34_USB_P2_2 MFP_CFG_OUT(GPIO34, AF1, DRIVE_LOW)
++#define GPIO35_USB_P2_1 MFP_CFG_IN(GPIO35, AF2)
++#define GPIO36_USB_P2_4 MFP_CFG_OUT(GPIO36, AF1, DRIVE_LOW)
++#define GPIO37_USB_P2_8 MFP_CFG_OUT(GPIO37, AF1, DRIVE_LOW)
++#define GPIO38_USB_P2_3 MFP_CFG_IN(GPIO38, AF3)
++#define GPIO39_USB_P2_6 MFP_CFG_OUT(GPIO39, AF1, DRIVE_LOW)
++#define GPIO40_USB_P2_5 MFP_CFG_IN(GPIO40, AF3)
++#define GPIO41_USB_P2_7 MFP_CFG_IN(GPIO41, AF2)
++#define GPIO53_USB_P2_3 MFP_CFG_IN(GPIO53, AF2)
++
++/* USB Host Port 1/2 */
++#define GPIO88_USBH1_PWR MFP_CFG_IN(GPIO88, AF1)
++#define GPIO89_USBH1_PEN MFP_CFG_OUT(GPIO89, AF2, DRIVE_LOW)
++#define GPIO119_USBH2_PWR MFP_CFG_IN(GPIO119, AF1)
++#define GPIO120_USBH2_PEN MFP_CFG_OUT(GPIO120, AF2, DRIVE_LOW)
++
++/* QCI - default to Master Mode: CIF_FV/CIF_LV Direction In */
++#define GPIO115_CIF_DD_3 MFP_CFG_IN(GPIO115, AF2)
++#define GPIO116_CIF_DD_2 MFP_CFG_IN(GPIO116, AF1)
++#define GPIO12_CIF_DD_7 MFP_CFG_IN(GPIO12, AF2)
++#define GPIO17_CIF_DD_6 MFP_CFG_IN(GPIO17, AF2)
++#define GPIO23_CIF_MCLK MFP_CFG_OUT(GPIO23, AF1, DRIVE_LOW)
++#define GPIO24_CIF_FV MFP_CFG_IN(GPIO24, AF1)
++#define GPIO25_CIF_LV MFP_CFG_IN(GPIO25, AF1)
++#define GPIO26_CIF_PCLK MFP_CFG_IN(GPIO26, AF2)
++#define GPIO27_CIF_DD_0 MFP_CFG_IN(GPIO27, AF3)
++#define GPIO42_CIF_MCLK MFP_CFG_OUT(GPIO42, AF3, DRIVE_LOW)
++#define GPIO43_CIF_FV MFP_CFG_IN(GPIO43, AF3)
++#define GPIO44_CIF_LV MFP_CFG_IN(GPIO44, AF3)
++#define GPIO45_CIF_PCLK MFP_CFG_IN(GPIO45, AF3)
++#define GPIO47_CIF_DD_0 MFP_CFG_IN(GPIO47, AF1)
++#define GPIO48_CIF_DD_5 MFP_CFG_IN(GPIO48, AF1)
++#define GPIO50_CIF_DD_3 MFP_CFG_IN(GPIO50, AF1)
++#define GPIO51_CIF_DD_2 MFP_CFG_IN(GPIO51, AF1)
++#define GPIO52_CIF_DD_4 MFP_CFG_IN(GPIO52, AF1)
++#define GPIO53_CIF_MCLK MFP_CFG_OUT(GPIO53, AF2, DRIVE_LOW)
++#define GPIO54_CIF_PCLK MFP_CFG_IN(GPIO54, AF3)
++#define GPIO55_CIF_DD_1 MFP_CFG_IN(GPIO55, AF1)
++#define GPIO81_CIF_DD_0 MFP_CFG_IN(GPIO81, AF2)
++#define GPIO82_CIF_DD_5 MFP_CFG_IN(GPIO82, AF3)
++#define GPIO83_CIF_DD_4 MFP_CFG_IN(GPIO83, AF3)
++#define GPIO84_CIF_FV MFP_CFG_IN(GPIO84, AF3)
++#define GPIO85_CIF_LV MFP_CFG_IN(GPIO85, AF3)
++#define GPIO90_CIF_DD_4 MFP_CFG_IN(GPIO90, AF3)
++#define GPIO91_CIF_DD_5 MFP_CFG_IN(GPIO91, AF3)
++#define GPIO93_CIF_DD_6 MFP_CFG_IN(GPIO93, AF2)
++#define GPIO94_CIF_DD_5 MFP_CFG_IN(GPIO94, AF2)
++#define GPIO95_CIF_DD_4 MFP_CFG_IN(GPIO95, AF2)
++#define GPIO98_CIF_DD_0 MFP_CFG_IN(GPIO98, AF2)
++#define GPIO103_CIF_DD_3 MFP_CFG_IN(GPIO103, AF1)
++#define GPIO104_CIF_DD_2 MFP_CFG_IN(GPIO104, AF1)
++#define GPIO105_CIF_DD_1 MFP_CFG_IN(GPIO105, AF1)
++#define GPIO106_CIF_DD_9 MFP_CFG_IN(GPIO106, AF1)
++#define GPIO107_CIF_DD_8 MFP_CFG_IN(GPIO107, AF1)
++#define GPIO108_CIF_DD_7 MFP_CFG_IN(GPIO108, AF1)
++#define GPIO114_CIF_DD_1 MFP_CFG_IN(GPIO114, AF1)
++
++/* Universal Subscriber ID Interface */
++#define GPIO114_UVS0 MFP_CFG_OUT(GPIO114, AF2, DRIVE_LOW)
++#define GPIO115_nUVS1 MFP_CFG_OUT(GPIO115, AF2, DRIVE_LOW)
++#define GPIO116_nUVS2 MFP_CFG_OUT(GPIO116, AF2, DRIVE_LOW)
++#define GPIO14_UCLK MFP_CFG_OUT(GPIO14, AF3, DRIVE_LOW)
++#define GPIO91_UCLK MFP_CFG_OUT(GPIO91, AF2, DRIVE_LOW)
++#define GPIO19_nURST MFP_CFG_OUT(GPIO19, AF3, DRIVE_LOW)
++#define GPIO90_nURST MFP_CFG_OUT(GPIO90, AF2, DRIVE_LOW)
++#define GPIO116_UDET MFP_CFG_IN(GPIO116, AF3)
++#define GPIO114_UEN MFP_CFG_OUT(GPIO114, AF1, DRIVE_LOW)
++#define GPIO115_UEN MFP_CFG_OUT(GPIO115, AF1, DRIVE_LOW)
++
++/* Mobile Scalable Link (MSL) Interface */
++#define GPIO81_BB_OB_DAT_0 MFP_CFG_OUT(GPIO81, AF2, DRIVE_LOW)
++#define GPIO48_BB_OB_DAT_1 MFP_CFG_OUT(GPIO48, AF1, DRIVE_LOW)
++#define GPIO50_BB_OB_DAT_2 MFP_CFG_OUT(GPIO50, AF1, DRIVE_LOW)
++#define GPIO51_BB_OB_DAT_3 MFP_CFG_OUT(GPIO51, AF1, DRIVE_LOW)
++#define GPIO52_BB_OB_CLK MFP_CFG_OUT(GPIO52, AF1, DRIVE_LOW)
++#define GPIO53_BB_OB_STB MFP_CFG_OUT(GPIO53, AF1, DRIVE_LOW)
++#define GPIO54_BB_OB_WAIT MFP_CFG_IN(GPIO54, AF2)
++#define GPIO82_BB_IB_DAT_0 MFP_CFG_IN(GPIO82, AF2)
++#define GPIO55_BB_IB_DAT_1 MFP_CFG_IN(GPIO55, AF2)
++#define GPIO56_BB_IB_DAT_2 MFP_CFG_IN(GPIO56, AF2)
++#define GPIO57_BB_IB_DAT_3 MFP_CFG_IN(GPIO57, AF2)
++#define GPIO83_BB_IB_CLK MFP_CFG_IN(GPIO83, AF2)
++#define GPIO84_BB_IB_STB MFP_CFG_IN(GPIO84, AF2)
++#define GPIO85_BB_IB_WAIT MFP_CFG_OUT(GPIO85, AF2, DRIVE_LOW)
++
++/* Memory Stick Host Controller */
++#define GPIO92_MSBS MFP_CFG_OUT(GPIO92, AF2, DRIVE_LOW)
++#define GPIO109_MSSDIO MFP_CFG_IN(GPIO109, AF2)
++#define GPIO112_nMSINS MFP_CFG_IN(GPIO112, AF2)
++#define GPIO32_MSSCLK MFP_CFG_OUT(GPIO32, AF1, DRIVE_LOW)
++
++extern int keypad_set_wake(unsigned int on);
++#endif /* __ASM_ARCH_MFP_PXA27X_H */
+diff --git a/include/asm-arm/arch-pxa/mfp-pxa2xx.h b/include/asm-arm/arch-pxa/mfp-pxa2xx.h
+new file mode 100644
+index 0000000..db8d890
+--- /dev/null
++++ b/include/asm-arm/arch-pxa/mfp-pxa2xx.h
+@@ -0,0 +1,132 @@
++#ifndef __ASM_ARCH_MFP_PXA2XX_H
++#define __ASM_ARCH_MFP_PXA2XX_H
++
++#include <asm/arch/mfp.h>
++
++/*
++ * the following MFP_xxx bit definitions in mfp.h are re-used for pxa2xx:
++ *
++ * MFP_PIN(x)
++ * MFP_AFx
++ * MFP_LPM_DRIVE_{LOW, HIGH}
++ * MFP_LPM_EDGE_x
++ *
++ * other MFP_x bit definitions will be ignored
++ *
++ * and adds the below two bits specifically for pxa2xx:
++ *
++ * bit 23 - Input/Output (PXA2xx specific)
++ * bit 24 - Wakeup Enable(PXA2xx specific)
++ */
++
++#define MFP_DIR_IN (0x0 << 23)
++#define MFP_DIR_OUT (0x1 << 23)
++#define MFP_DIR_MASK (0x1 << 23)
++#define MFP_DIR(x) (((x) >> 23) & 0x1)
++
++#define MFP_LPM_CAN_WAKEUP (0x1 << 24)
++#define WAKEUP_ON_EDGE_RISE (MFP_LPM_CAN_WAKEUP | MFP_LPM_EDGE_RISE)
++#define WAKEUP_ON_EDGE_FALL (MFP_LPM_CAN_WAKEUP | MFP_LPM_EDGE_FALL)
++#define WAKEUP_ON_EDGE_BOTH (MFP_LPM_CAN_WAKEUP | MFP_LPM_EDGE_BOTH)
++
++/* specifically for enabling wakeup on keypad GPIOs */
++#define WAKEUP_ON_LEVEL_HIGH (MFP_LPM_CAN_WAKEUP)
++
++#define MFP_CFG_IN(pin, af) \
++ ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DIR_MASK)) |\
++ (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_DIR_IN))
++
++/* NOTE: pins configured as output _must_ provide a low power state,
++ * and this state should help to minimize the power dissipation.
++ */
++#define MFP_CFG_OUT(pin, af, state) \
++ ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DIR_MASK | MFP_LPM_STATE_MASK)) |\
++ (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_DIR_OUT | MFP_LPM_##state))
++
++/* Common configurations for pxa25x and pxa27x
++ *
++ * Note: pins configured as GPIO are always initialized to input
++ * so not to cause any side effect
++ */
++#define GPIO0_GPIO MFP_CFG_IN(GPIO0, AF0)
++#define GPIO1_GPIO MFP_CFG_IN(GPIO1, AF0)
++#define GPIO9_GPIO MFP_CFG_IN(GPIO9, AF0)
++#define GPIO10_GPIO MFP_CFG_IN(GPIO10, AF0)
++#define GPIO11_GPIO MFP_CFG_IN(GPIO11, AF0)
++#define GPIO12_GPIO MFP_CFG_IN(GPIO12, AF0)
++#define GPIO13_GPIO MFP_CFG_IN(GPIO13, AF0)
++#define GPIO14_GPIO MFP_CFG_IN(GPIO14, AF0)
++#define GPIO15_GPIO MFP_CFG_IN(GPIO15, AF0)
++#define GPIO16_GPIO MFP_CFG_IN(GPIO16, AF0)
++#define GPIO17_GPIO MFP_CFG_IN(GPIO17, AF0)
++#define GPIO18_GPIO MFP_CFG_IN(GPIO18, AF0)
++#define GPIO19_GPIO MFP_CFG_IN(GPIO19, AF0)
++#define GPIO20_GPIO MFP_CFG_IN(GPIO20, AF0)
++#define GPIO21_GPIO MFP_CFG_IN(GPIO21, AF0)
++#define GPIO22_GPIO MFP_CFG_IN(GPIO22, AF0)
++#define GPIO23_GPIO MFP_CFG_IN(GPIO23, AF0)
++#define GPIO24_GPIO MFP_CFG_IN(GPIO24, AF0)
++#define GPIO25_GPIO MFP_CFG_IN(GPIO25, AF0)
++#define GPIO26_GPIO MFP_CFG_IN(GPIO26, AF0)
++#define GPIO27_GPIO MFP_CFG_IN(GPIO27, AF0)
++#define GPIO28_GPIO MFP_CFG_IN(GPIO28, AF0)
++#define GPIO29_GPIO MFP_CFG_IN(GPIO29, AF0)
++#define GPIO30_GPIO MFP_CFG_IN(GPIO30, AF0)
++#define GPIO31_GPIO MFP_CFG_IN(GPIO31, AF0)
++#define GPIO32_GPIO MFP_CFG_IN(GPIO32, AF0)
++#define GPIO33_GPIO MFP_CFG_IN(GPIO33, AF0)
++#define GPIO34_GPIO MFP_CFG_IN(GPIO34, AF0)
++#define GPIO35_GPIO MFP_CFG_IN(GPIO35, AF0)
++#define GPIO36_GPIO MFP_CFG_IN(GPIO36, AF0)
++#define GPIO37_GPIO MFP_CFG_IN(GPIO37, AF0)
++#define GPIO38_GPIO MFP_CFG_IN(GPIO38, AF0)
++#define GPIO39_GPIO MFP_CFG_IN(GPIO39, AF0)
++#define GPIO40_GPIO MFP_CFG_IN(GPIO40, AF0)
++#define GPIO41_GPIO MFP_CFG_IN(GPIO41, AF0)
++#define GPIO42_GPIO MFP_CFG_IN(GPIO42, AF0)
++#define GPIO43_GPIO MFP_CFG_IN(GPIO43, AF0)
++#define GPIO44_GPIO MFP_CFG_IN(GPIO44, AF0)
++#define GPIO45_GPIO MFP_CFG_IN(GPIO45, AF0)
++#define GPIO46_GPIO MFP_CFG_IN(GPIO46, AF0)
++#define GPIO47_GPIO MFP_CFG_IN(GPIO47, AF0)
++#define GPIO48_GPIO MFP_CFG_IN(GPIO48, AF0)
++#define GPIO49_GPIO MFP_CFG_IN(GPIO49, AF0)
++#define GPIO50_GPIO MFP_CFG_IN(GPIO50, AF0)
++#define GPIO51_GPIO MFP_CFG_IN(GPIO51, AF0)
++#define GPIO52_GPIO MFP_CFG_IN(GPIO52, AF0)
++#define GPIO53_GPIO MFP_CFG_IN(GPIO53, AF0)
++#define GPIO54_GPIO MFP_CFG_IN(GPIO54, AF0)
++#define GPIO55_GPIO MFP_CFG_IN(GPIO55, AF0)
++#define GPIO56_GPIO MFP_CFG_IN(GPIO56, AF0)
++#define GPIO57_GPIO MFP_CFG_IN(GPIO57, AF0)
++#define GPIO58_GPIO MFP_CFG_IN(GPIO58, AF0)
++#define GPIO59_GPIO MFP_CFG_IN(GPIO59, AF0)
++#define GPIO60_GPIO MFP_CFG_IN(GPIO60, AF0)
++#define GPIO61_GPIO MFP_CFG_IN(GPIO61, AF0)
++#define GPIO62_GPIO MFP_CFG_IN(GPIO62, AF0)
++#define GPIO63_GPIO MFP_CFG_IN(GPIO63, AF0)
++#define GPIO64_GPIO MFP_CFG_IN(GPIO64, AF0)
++#define GPIO65_GPIO MFP_CFG_IN(GPIO65, AF0)
++#define GPIO66_GPIO MFP_CFG_IN(GPIO66, AF0)
++#define GPIO67_GPIO MFP_CFG_IN(GPIO67, AF0)
++#define GPIO68_GPIO MFP_CFG_IN(GPIO68, AF0)
++#define GPIO69_GPIO MFP_CFG_IN(GPIO69, AF0)
++#define GPIO70_GPIO MFP_CFG_IN(GPIO70, AF0)
++#define GPIO71_GPIO MFP_CFG_IN(GPIO71, AF0)
++#define GPIO72_GPIO MFP_CFG_IN(GPIO72, AF0)
++#define GPIO73_GPIO MFP_CFG_IN(GPIO73, AF0)
++#define GPIO74_GPIO MFP_CFG_IN(GPIO74, AF0)
++#define GPIO75_GPIO MFP_CFG_IN(GPIO75, AF0)
++#define GPIO76_GPIO MFP_CFG_IN(GPIO76, AF0)
++#define GPIO77_GPIO MFP_CFG_IN(GPIO77, AF0)
++#define GPIO78_GPIO MFP_CFG_IN(GPIO78, AF0)
++#define GPIO79_GPIO MFP_CFG_IN(GPIO79, AF0)
++#define GPIO80_GPIO MFP_CFG_IN(GPIO80, AF0)
++#define GPIO81_GPIO MFP_CFG_IN(GPIO81, AF0)
++#define GPIO82_GPIO MFP_CFG_IN(GPIO82, AF0)
++#define GPIO83_GPIO MFP_CFG_IN(GPIO83, AF0)
++#define GPIO84_GPIO MFP_CFG_IN(GPIO84, AF0)
++
++extern void pxa2xx_mfp_config(unsigned long *mfp_cfgs, int num);
++extern int gpio_set_wake(unsigned int gpio, unsigned int on);
++#endif /* __ASM_ARCH_MFP_PXA2XX_H */
+diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
+index 2357a73..a322012 100644
+--- a/include/asm-arm/arch-pxa/pxa-regs.h
++++ b/include/asm-arm/arch-pxa/pxa-regs.h
+@@ -1129,6 +1129,11 @@
+ #define ICPR __REG(0x40D00010) /* Interrupt Controller Pending Register */
+ #define ICCR __REG(0x40D00014) /* Interrupt Controller Control Register */
+
++#define ICIP2 __REG(0x40D0009C) /* Interrupt Controller IRQ Pending Register 2 */
++#define ICMR2 __REG(0x40D000A0) /* Interrupt Controller Mask Register 2 */
++#define ICLR2 __REG(0x40D000A4) /* Interrupt Controller Level Register 2 */
++#define ICFP2 __REG(0x40D000A8) /* Interrupt Controller FIQ Pending Register 2 */
++#define ICPR2 __REG(0x40D000AC) /* Interrupt Controller Pending Register 2 */
+
+ /*
+ * General Purpose I/O
+@@ -1200,12 +1205,6 @@
+
+ /* Interrupt Controller */
+
+-#define ICIP2 __REG(0x40D0009C) /* Interrupt Controller IRQ Pending Register 2 */
+-#define ICMR2 __REG(0x40D000A0) /* Interrupt Controller Mask Register 2 */
+-#define ICLR2 __REG(0x40D000A4) /* Interrupt Controller Level Register 2 */
+-#define ICFP2 __REG(0x40D000A8) /* Interrupt Controller FIQ Pending Register 2 */
+-#define ICPR2 __REG(0x40D000AC) /* Interrupt Controller Pending Register 2 */
+-
+ #define _GPLR(x) __REG2(0x40E00000, ((x) & 0x60) >> 3)
+ #define _GPDR(x) __REG2(0x40E0000C, ((x) & 0x60) >> 3)
+ #define _GPSR(x) __REG2(0x40E00018, ((x) & 0x60) >> 3)
+@@ -1237,267 +1236,6 @@
+
+ #endif
+
+-
+-/* GPIO alternate function assignments */
+-
+-#define GPIO1_RST 1 /* reset */
+-#define GPIO6_MMCCLK 6 /* MMC Clock */
+-#define GPIO7_48MHz 7 /* 48 MHz clock output */
+-#define GPIO8_MMCCS0 8 /* MMC Chip Select 0 */
+-#define GPIO9_MMCCS1 9 /* MMC Chip Select 1 */
+-#define GPIO10_RTCCLK 10 /* real time clock (1 Hz) */
+-#define GPIO11_3_6MHz 11 /* 3.6 MHz oscillator out */
+-#define GPIO12_32KHz 12 /* 32 kHz out */
+-#define GPIO13_MBGNT 13 /* memory controller grant */
+-#define GPIO14_MBREQ 14 /* alternate bus master request */
+-#define GPIO15_nCS_1 15 /* chip select 1 */
+-#define GPIO16_PWM0 16 /* PWM0 output */
+-#define GPIO17_PWM1 17 /* PWM1 output */
+-#define GPIO18_RDY 18 /* Ext. Bus Ready */
+-#define GPIO19_DREQ1 19 /* External DMA Request */
+-#define GPIO20_DREQ0 20 /* External DMA Request */
+-#define GPIO23_SCLK 23 /* SSP clock */
+-#define GPIO24_SFRM 24 /* SSP Frame */
+-#define GPIO25_STXD 25 /* SSP transmit */
+-#define GPIO26_SRXD 26 /* SSP receive */
+-#define GPIO27_SEXTCLK 27 /* SSP ext_clk */
+-#define GPIO28_BITCLK 28 /* AC97/I2S bit_clk */
+-#define GPIO29_SDATA_IN 29 /* AC97 Sdata_in0 / I2S Sdata_in */
+-#define GPIO30_SDATA_OUT 30 /* AC97/I2S Sdata_out */
+-#define GPIO31_SYNC 31 /* AC97/I2S sync */
+-#define GPIO32_SDATA_IN1 32 /* AC97 Sdata_in1 */
+-#define GPIO32_SYSCLK 32 /* I2S System Clock */
+-#define GPIO32_MMCCLK 32 /* MMC Clock (PXA270) */
+-#define GPIO33_nCS_5 33 /* chip select 5 */
+-#define GPIO34_FFRXD 34 /* FFUART receive */
+-#define GPIO34_MMCCS0 34 /* MMC Chip Select 0 */
+-#define GPIO35_FFCTS 35 /* FFUART Clear to send */
+-#define GPIO36_FFDCD 36 /* FFUART Data carrier detect */
+-#define GPIO37_FFDSR 37 /* FFUART data set ready */
+-#define GPIO38_FFRI 38 /* FFUART Ring Indicator */
+-#define GPIO39_MMCCS1 39 /* MMC Chip Select 1 */
+-#define GPIO39_FFTXD 39 /* FFUART transmit data */
+-#define GPIO40_FFDTR 40 /* FFUART data terminal Ready */
+-#define GPIO41_FFRTS 41 /* FFUART request to send */
+-#define GPIO42_BTRXD 42 /* BTUART receive data */
+-#define GPIO42_HWRXD 42 /* HWUART receive data */
+-#define GPIO43_BTTXD 43 /* BTUART transmit data */
+-#define GPIO43_HWTXD 43 /* HWUART transmit data */
+-#define GPIO44_BTCTS 44 /* BTUART clear to send */
+-#define GPIO44_HWCTS 44 /* HWUART clear to send */
+-#define GPIO45_BTRTS 45 /* BTUART request to send */
+-#define GPIO45_HWRTS 45 /* HWUART request to send */
+-#define GPIO45_AC97_SYSCLK 45 /* AC97 System Clock */
+-#define GPIO46_ICPRXD 46 /* ICP receive data */
+-#define GPIO46_STRXD 46 /* STD_UART receive data */
+-#define GPIO47_ICPTXD 47 /* ICP transmit data */
+-#define GPIO47_STTXD 47 /* STD_UART transmit data */
+-#define GPIO48_nPOE 48 /* Output Enable for Card Space */
+-#define GPIO49_nPWE 49 /* Write Enable for Card Space */
+-#define GPIO50_nPIOR 50 /* I/O Read for Card Space */
+-#define GPIO51_nPIOW 51 /* I/O Write for Card Space */
+-#define GPIO52_nPCE_1 52 /* Card Enable for Card Space */
+-#define GPIO53_nPCE_2 53 /* Card Enable for Card Space */
+-#define GPIO53_MMCCLK 53 /* MMC Clock */
+-#define GPIO54_MMCCLK 54 /* MMC Clock */
+-#define GPIO54_pSKTSEL 54 /* Socket Select for Card Space */
+-#define GPIO54_nPCE_2 54 /* Card Enable for Card Space (PXA27x) */
+-#define GPIO55_nPREG 55 /* Card Address bit 26 */
+-#define GPIO56_nPWAIT 56 /* Wait signal for Card Space */
+-#define GPIO57_nIOIS16 57 /* Bus Width select for I/O Card Space */
+-#define GPIO58_LDD_0 58 /* LCD data pin 0 */
+-#define GPIO59_LDD_1 59 /* LCD data pin 1 */
+-#define GPIO60_LDD_2 60 /* LCD data pin 2 */
+-#define GPIO61_LDD_3 61 /* LCD data pin 3 */
+-#define GPIO62_LDD_4 62 /* LCD data pin 4 */
+-#define GPIO63_LDD_5 63 /* LCD data pin 5 */
+-#define GPIO64_LDD_6 64 /* LCD data pin 6 */
+-#define GPIO65_LDD_7 65 /* LCD data pin 7 */
+-#define GPIO66_LDD_8 66 /* LCD data pin 8 */
+-#define GPIO66_MBREQ 66 /* alternate bus master req */
+-#define GPIO67_LDD_9 67 /* LCD data pin 9 */
+-#define GPIO67_MMCCS0 67 /* MMC Chip Select 0 */
+-#define GPIO68_LDD_10 68 /* LCD data pin 10 */
+-#define GPIO68_MMCCS1 68 /* MMC Chip Select 1 */
+-#define GPIO69_LDD_11 69 /* LCD data pin 11 */
+-#define GPIO69_MMCCLK 69 /* MMC_CLK */
+-#define GPIO70_LDD_12 70 /* LCD data pin 12 */
+-#define GPIO70_RTCCLK 70 /* Real Time clock (1 Hz) */
+-#define GPIO71_LDD_13 71 /* LCD data pin 13 */
+-#define GPIO71_3_6MHz 71 /* 3.6 MHz Oscillator clock */
+-#define GPIO72_LDD_14 72 /* LCD data pin 14 */
+-#define GPIO72_32kHz 72 /* 32 kHz clock */
+-#define GPIO73_LDD_15 73 /* LCD data pin 15 */
+-#define GPIO73_MBGNT 73 /* Memory controller grant */
+-#define GPIO74_LCD_FCLK 74 /* LCD Frame clock */
+-#define GPIO75_LCD_LCLK 75 /* LCD line clock */
+-#define GPIO76_LCD_PCLK 76 /* LCD Pixel clock */
+-#define GPIO77_LCD_ACBIAS 77 /* LCD AC Bias */
+-#define GPIO78_nCS_2 78 /* chip select 2 */
+-#define GPIO79_nCS_3 79 /* chip select 3 */
+-#define GPIO80_nCS_4 80 /* chip select 4 */
+-#define GPIO81_NSCLK 81 /* NSSP clock */
+-#define GPIO82_NSFRM 82 /* NSSP Frame */
+-#define GPIO83_NSTXD 83 /* NSSP transmit */
+-#define GPIO84_NSRXD 84 /* NSSP receive */
+-#define GPIO85_nPCE_1 85 /* Card Enable for Card Space (PXA27x) */
+-#define GPIO92_MMCDAT0 92 /* MMC DAT0 (PXA27x) */
+-#define GPIO102_nPCE_1 102 /* PCMCIA (PXA27x) */
+-#define GPIO109_MMCDAT1 109 /* MMC DAT1 (PXA27x) */
+-#define GPIO110_MMCDAT2 110 /* MMC DAT2 (PXA27x) */
+-#define GPIO110_MMCCS0 110 /* MMC Chip Select 0 (PXA27x) */
+-#define GPIO111_MMCDAT3 111 /* MMC DAT3 (PXA27x) */
+-#define GPIO111_MMCCS1 111 /* MMC Chip Select 1 (PXA27x) */
+-#define GPIO112_MMCCMD 112 /* MMC CMD (PXA27x) */
+-#define GPIO113_I2S_SYSCLK 113 /* I2S System Clock (PXA27x) */
+-#define GPIO113_AC97_RESET_N 113 /* AC97 NRESET on (PXA27x) */
+-
+-/* GPIO alternate function mode & direction */
+-
+-#define GPIO_IN 0x000
+-#define GPIO_OUT 0x080
+-#define GPIO_ALT_FN_1_IN 0x100
+-#define GPIO_ALT_FN_1_OUT 0x180
+-#define GPIO_ALT_FN_2_IN 0x200
+-#define GPIO_ALT_FN_2_OUT 0x280
+-#define GPIO_ALT_FN_3_IN 0x300
+-#define GPIO_ALT_FN_3_OUT 0x380
+-#define GPIO_MD_MASK_NR 0x07f
+-#define GPIO_MD_MASK_DIR 0x080
+-#define GPIO_MD_MASK_FN 0x300
+-#define GPIO_DFLT_LOW 0x400
+-#define GPIO_DFLT_HIGH 0x800
+-
+-#define GPIO1_RTS_MD ( 1 | GPIO_ALT_FN_1_IN)
+-#define GPIO6_MMCCLK_MD ( 6 | GPIO_ALT_FN_1_OUT)
+-#define GPIO7_48MHz_MD ( 7 | GPIO_ALT_FN_1_OUT)
+-#define GPIO8_MMCCS0_MD ( 8 | GPIO_ALT_FN_1_OUT)
+-#define GPIO9_MMCCS1_MD ( 9 | GPIO_ALT_FN_1_OUT)
+-#define GPIO10_RTCCLK_MD (10 | GPIO_ALT_FN_1_OUT)
+-#define GPIO11_3_6MHz_MD (11 | GPIO_ALT_FN_1_OUT)
+-#define GPIO12_32KHz_MD (12 | GPIO_ALT_FN_1_OUT)
+-#define GPIO13_MBGNT_MD (13 | GPIO_ALT_FN_2_OUT)
+-#define GPIO14_MBREQ_MD (14 | GPIO_ALT_FN_1_IN)
+-#define GPIO15_nCS_1_MD (15 | GPIO_ALT_FN_2_OUT)
+-#define GPIO16_PWM0_MD (16 | GPIO_ALT_FN_2_OUT)
+-#define GPIO17_PWM1_MD (17 | GPIO_ALT_FN_2_OUT)
+-#define GPIO18_RDY_MD (18 | GPIO_ALT_FN_1_IN)
+-#define GPIO19_DREQ1_MD (19 | GPIO_ALT_FN_1_IN)
+-#define GPIO20_DREQ0_MD (20 | GPIO_ALT_FN_1_IN)
+-#define GPIO23_SCLK_MD (23 | GPIO_ALT_FN_2_OUT)
+-#define GPIO24_SFRM_MD (24 | GPIO_ALT_FN_2_OUT)
+-#define GPIO25_STXD_MD (25 | GPIO_ALT_FN_2_OUT)
+-#define GPIO26_SRXD_MD (26 | GPIO_ALT_FN_1_IN)
+-#define GPIO27_SEXTCLK_MD (27 | GPIO_ALT_FN_1_IN)
+-#define GPIO28_BITCLK_AC97_MD (28 | GPIO_ALT_FN_1_IN)
+-#define GPIO28_BITCLK_IN_I2S_MD (28 | GPIO_ALT_FN_2_IN)
+-#define GPIO28_BITCLK_OUT_I2S_MD (28 | GPIO_ALT_FN_1_OUT)
+-#define GPIO29_SDATA_IN_AC97_MD (29 | GPIO_ALT_FN_1_IN)
+-#define GPIO29_SDATA_IN_I2S_MD (29 | GPIO_ALT_FN_2_IN)
+-#define GPIO30_SDATA_OUT_AC97_MD (30 | GPIO_ALT_FN_2_OUT)
+-#define GPIO30_SDATA_OUT_I2S_MD (30 | GPIO_ALT_FN_1_OUT)
+-#define GPIO31_SYNC_I2S_MD (31 | GPIO_ALT_FN_1_OUT)
+-#define GPIO31_SYNC_AC97_MD (31 | GPIO_ALT_FN_2_OUT)
+-#define GPIO32_SDATA_IN1_AC97_MD (32 | GPIO_ALT_FN_1_IN)
+-#define GPIO32_SYSCLK_I2S_MD (32 | GPIO_ALT_FN_1_OUT)
+-#define GPIO32_MMCCLK_MD ( 32 | GPIO_ALT_FN_2_OUT)
+-#define GPIO33_nCS_5_MD (33 | GPIO_ALT_FN_2_OUT)
+-#define GPIO34_FFRXD_MD (34 | GPIO_ALT_FN_1_IN)
+-#define GPIO34_MMCCS0_MD (34 | GPIO_ALT_FN_2_OUT)
+-#define GPIO35_FFCTS_MD (35 | GPIO_ALT_FN_1_IN)
+-#define GPIO36_FFDCD_MD (36 | GPIO_ALT_FN_1_IN)
+-#define GPIO37_FFDSR_MD (37 | GPIO_ALT_FN_1_IN)
+-#define GPIO38_FFRI_MD (38 | GPIO_ALT_FN_1_IN)
+-#define GPIO39_MMCCS1_MD (39 | GPIO_ALT_FN_1_OUT)
+-#define GPIO39_FFTXD_MD (39 | GPIO_ALT_FN_2_OUT)
+-#define GPIO40_FFDTR_MD (40 | GPIO_ALT_FN_2_OUT)
+-#define GPIO41_FFRTS_MD (41 | GPIO_ALT_FN_2_OUT)
+-#define GPIO42_BTRXD_MD (42 | GPIO_ALT_FN_1_IN)
+-#define GPIO42_HWRXD_MD (42 | GPIO_ALT_FN_3_IN)
+-#define GPIO43_BTTXD_MD (43 | GPIO_ALT_FN_2_OUT)
+-#define GPIO43_HWTXD_MD (43 | GPIO_ALT_FN_3_OUT)
+-#define GPIO44_BTCTS_MD (44 | GPIO_ALT_FN_1_IN)
+-#define GPIO44_HWCTS_MD (44 | GPIO_ALT_FN_3_IN)
+-#define GPIO45_BTRTS_MD (45 | GPIO_ALT_FN_2_OUT)
+-#define GPIO45_HWRTS_MD (45 | GPIO_ALT_FN_3_OUT)
+-#define GPIO45_SYSCLK_AC97_MD (45 | GPIO_ALT_FN_1_OUT)
+-#define GPIO46_ICPRXD_MD (46 | GPIO_ALT_FN_1_IN)
+-#define GPIO46_STRXD_MD (46 | GPIO_ALT_FN_2_IN)
+-#define GPIO47_ICPTXD_MD (47 | GPIO_ALT_FN_2_OUT)
+-#define GPIO47_STTXD_MD (47 | GPIO_ALT_FN_1_OUT)
+-#define GPIO48_nPOE_MD (48 | GPIO_ALT_FN_2_OUT)
+-#define GPIO48_HWTXD_MD (48 | GPIO_ALT_FN_1_OUT)
+-#define GPIO48_nPOE_MD (48 | GPIO_ALT_FN_2_OUT)
+-#define GPIO49_HWRXD_MD (49 | GPIO_ALT_FN_1_IN)
+-#define GPIO49_nPWE_MD (49 | GPIO_ALT_FN_2_OUT)
+-#define GPIO50_nPIOR_MD (50 | GPIO_ALT_FN_2_OUT)
+-#define GPIO50_HWCTS_MD (50 | GPIO_ALT_FN_1_IN)
+-#define GPIO51_HWRTS_MD (51 | GPIO_ALT_FN_1_OUT)
+-#define GPIO51_nPIOW_MD (51 | GPIO_ALT_FN_2_OUT)
+-#define GPIO52_nPCE_1_MD (52 | GPIO_ALT_FN_2_OUT)
+-#define GPIO53_nPCE_2_MD (53 | GPIO_ALT_FN_2_OUT)
+-#define GPIO53_MMCCLK_MD (53 | GPIO_ALT_FN_1_OUT)
+-#define GPIO54_MMCCLK_MD (54 | GPIO_ALT_FN_1_OUT)
+-#define GPIO54_nPCE_2_MD (54 | GPIO_ALT_FN_2_OUT)
+-#define GPIO54_pSKTSEL_MD (54 | GPIO_ALT_FN_2_OUT)
+-#define GPIO55_nPREG_MD (55 | GPIO_ALT_FN_2_OUT)
+-#define GPIO56_nPWAIT_MD (56 | GPIO_ALT_FN_1_IN)
+-#define GPIO57_nIOIS16_MD (57 | GPIO_ALT_FN_1_IN)
+-#define GPIO58_LDD_0_MD (58 | GPIO_ALT_FN_2_OUT)
+-#define GPIO59_LDD_1_MD (59 | GPIO_ALT_FN_2_OUT)
+-#define GPIO60_LDD_2_MD (60 | GPIO_ALT_FN_2_OUT)
+-#define GPIO61_LDD_3_MD (61 | GPIO_ALT_FN_2_OUT)
+-#define GPIO62_LDD_4_MD (62 | GPIO_ALT_FN_2_OUT)
+-#define GPIO63_LDD_5_MD (63 | GPIO_ALT_FN_2_OUT)
+-#define GPIO64_LDD_6_MD (64 | GPIO_ALT_FN_2_OUT)
+-#define GPIO65_LDD_7_MD (65 | GPIO_ALT_FN_2_OUT)
+-#define GPIO66_LDD_8_MD (66 | GPIO_ALT_FN_2_OUT)
+-#define GPIO66_MBREQ_MD (66 | GPIO_ALT_FN_1_IN)
+-#define GPIO67_LDD_9_MD (67 | GPIO_ALT_FN_2_OUT)
+-#define GPIO67_MMCCS0_MD (67 | GPIO_ALT_FN_1_OUT)
+-#define GPIO68_LDD_10_MD (68 | GPIO_ALT_FN_2_OUT)
+-#define GPIO68_MMCCS1_MD (68 | GPIO_ALT_FN_1_OUT)
+-#define GPIO69_LDD_11_MD (69 | GPIO_ALT_FN_2_OUT)
+-#define GPIO69_MMCCLK_MD (69 | GPIO_ALT_FN_1_OUT)
+-#define GPIO70_LDD_12_MD (70 | GPIO_ALT_FN_2_OUT)
+-#define GPIO70_RTCCLK_MD (70 | GPIO_ALT_FN_1_OUT)
+-#define GPIO71_LDD_13_MD (71 | GPIO_ALT_FN_2_OUT)
+-#define GPIO71_3_6MHz_MD (71 | GPIO_ALT_FN_1_OUT)
+-#define GPIO72_LDD_14_MD (72 | GPIO_ALT_FN_2_OUT)
+-#define GPIO72_32kHz_MD (72 | GPIO_ALT_FN_1_OUT)
+-#define GPIO73_LDD_15_MD (73 | GPIO_ALT_FN_2_OUT)
+-#define GPIO73_MBGNT_MD (73 | GPIO_ALT_FN_1_OUT)
+-#define GPIO74_LCD_FCLK_MD (74 | GPIO_ALT_FN_2_OUT)
+-#define GPIO75_LCD_LCLK_MD (75 | GPIO_ALT_FN_2_OUT)
+-#define GPIO76_LCD_PCLK_MD (76 | GPIO_ALT_FN_2_OUT)
+-#define GPIO77_LCD_ACBIAS_MD (77 | GPIO_ALT_FN_2_OUT)
+-#define GPIO78_nCS_2_MD (78 | GPIO_ALT_FN_2_OUT)
+-#define GPIO79_nCS_3_MD (79 | GPIO_ALT_FN_2_OUT)
+-#define GPIO79_pSKTSEL_MD (79 | GPIO_ALT_FN_1_OUT)
+-#define GPIO80_nCS_4_MD (80 | GPIO_ALT_FN_2_OUT)
+-#define GPIO81_NSSP_CLK_OUT (81 | GPIO_ALT_FN_1_OUT)
+-#define GPIO81_NSSP_CLK_IN (81 | GPIO_ALT_FN_1_IN)
+-#define GPIO82_NSSP_FRM_OUT (82 | GPIO_ALT_FN_1_OUT)
+-#define GPIO82_NSSP_FRM_IN (82 | GPIO_ALT_FN_1_IN)
+-#define GPIO83_NSSP_TX (83 | GPIO_ALT_FN_1_OUT)
+-#define GPIO83_NSSP_RX (83 | GPIO_ALT_FN_2_IN)
+-#define GPIO84_NSSP_TX (84 | GPIO_ALT_FN_1_OUT)
+-#define GPIO84_NSSP_RX (84 | GPIO_ALT_FN_2_IN)
+-#define GPIO85_nPCE_1_MD (85 | GPIO_ALT_FN_1_OUT)
+-#define GPIO92_MMCDAT0_MD (92 | GPIO_ALT_FN_1_OUT)
+-#define GPIO102_nPCE_1_MD (102 | GPIO_ALT_FN_1_OUT)
+-#define GPIO104_pSKTSEL_MD (104 | GPIO_ALT_FN_1_OUT)
+-#define GPIO109_MMCDAT1_MD (109 | GPIO_ALT_FN_1_OUT)
+-#define GPIO110_MMCDAT2_MD (110 | GPIO_ALT_FN_1_OUT)
+-#define GPIO110_MMCCS0_MD (110 | GPIO_ALT_FN_1_OUT)
+-#define GPIO111_MMCDAT3_MD (111 | GPIO_ALT_FN_1_OUT)
+-#define GPIO110_MMCCS1_MD (111 | GPIO_ALT_FN_1_OUT)
+-#define GPIO112_MMCCMD_MD (112 | GPIO_ALT_FN_1_OUT)
+-#define GPIO113_I2S_SYSCLK_MD (113 | GPIO_ALT_FN_1_OUT)
+-#define GPIO113_AC97_RESET_N_MD (113 | GPIO_ALT_FN_2_OUT)
+-#define GPIO117_I2CSCL_MD (117 | GPIO_ALT_FN_1_IN)
+-#define GPIO118_I2CSDA_MD (118 | GPIO_ALT_FN_1_IN)
+-
+ /*
+ * Power Manager
+ */
+@@ -1866,62 +1604,6 @@
+
+ #ifdef CONFIG_PXA27x
+
+-/*
+- * Keypad
+- */
+-#define KPC __REG(0x41500000) /* Keypad Interface Control register */
+-#define KPDK __REG(0x41500008) /* Keypad Interface Direct Key register */
+-#define KPREC __REG(0x41500010) /* Keypad Interface Rotary Encoder register */
+-#define KPMK __REG(0x41500018) /* Keypad Interface Matrix Key register */
+-#define KPAS __REG(0x41500020) /* Keypad Interface Automatic Scan register */
+-#define KPASMKP0 __REG(0x41500028) /* Keypad Interface Automatic Scan Multiple Key Presser register 0 */
+-#define KPASMKP1 __REG(0x41500030) /* Keypad Interface Automatic Scan Multiple Key Presser register 1 */
+-#define KPASMKP2 __REG(0x41500038) /* Keypad Interface Automatic Scan Multiple Key Presser register 2 */
+-#define KPASMKP3 __REG(0x41500040) /* Keypad Interface Automatic Scan Multiple Key Presser register 3 */
+-#define KPKDI __REG(0x41500048) /* Keypad Interface Key Debounce Interval register */
+-
+-#define KPC_AS (0x1 << 30) /* Automatic Scan bit */
+-#define KPC_ASACT (0x1 << 29) /* Automatic Scan on Activity */
+-#define KPC_MI (0x1 << 22) /* Matrix interrupt bit */
+-#define KPC_IMKP (0x1 << 21) /* Ignore Multiple Key Press */
+-#define KPC_MS7 (0x1 << 20) /* Matrix scan line 7 */
+-#define KPC_MS6 (0x1 << 19) /* Matrix scan line 6 */
+-#define KPC_MS5 (0x1 << 18) /* Matrix scan line 5 */
+-#define KPC_MS4 (0x1 << 17) /* Matrix scan line 4 */
+-#define KPC_MS3 (0x1 << 16) /* Matrix scan line 3 */
+-#define KPC_MS2 (0x1 << 15) /* Matrix scan line 2 */
+-#define KPC_MS1 (0x1 << 14) /* Matrix scan line 1 */
+-#define KPC_MS0 (0x1 << 13) /* Matrix scan line 0 */
+-#define KPC_MS_ALL (KPC_MS0 | KPC_MS1 | KPC_MS2 | KPC_MS3 | KPC_MS4 | KPC_MS5 | KPC_MS6 | KPC_MS7)
+-#define KPC_ME (0x1 << 12) /* Matrix Keypad Enable */
+-#define KPC_MIE (0x1 << 11) /* Matrix Interrupt Enable */
+-#define KPC_DK_DEB_SEL (0x1 << 9) /* Direct Keypad Debounce Select */
+-#define KPC_DI (0x1 << 5) /* Direct key interrupt bit */
+-#define KPC_RE_ZERO_DEB (0x1 << 4) /* Rotary Encoder Zero Debounce */
+-#define KPC_REE1 (0x1 << 3) /* Rotary Encoder1 Enable */
+-#define KPC_REE0 (0x1 << 2) /* Rotary Encoder0 Enable */
+-#define KPC_DE (0x1 << 1) /* Direct Keypad Enable */
+-#define KPC_DIE (0x1 << 0) /* Direct Keypad interrupt Enable */
+-
+-#define KPDK_DKP (0x1 << 31)
+-#define KPDK_DK7 (0x1 << 7)
+-#define KPDK_DK6 (0x1 << 6)
+-#define KPDK_DK5 (0x1 << 5)
+-#define KPDK_DK4 (0x1 << 4)
+-#define KPDK_DK3 (0x1 << 3)
+-#define KPDK_DK2 (0x1 << 2)
+-#define KPDK_DK1 (0x1 << 1)
+-#define KPDK_DK0 (0x1 << 0)
+-
+-#define KPREC_OF1 (0x1 << 31)
+-#define kPREC_UF1 (0x1 << 30)
+-#define KPREC_OF0 (0x1 << 15)
+-#define KPREC_UF0 (0x1 << 14)
+-
+-#define KPMK_MKP (0x1 << 31)
+-#define KPAS_SO (0x1 << 31)
+-#define KPASMKPx_SO (0x1 << 31)
+-
+ /* Camera Interface */
+ #define CICR0 __REG(0x50000000)
+ #define CICR1 __REG(0x50000004)
+@@ -1953,7 +1635,7 @@
+ #define CICR0_FOM (1 << 0) /* FIFO-overrun mask */
+
+ #define CICR1_TBIT (1 << 31) /* Transparency bit */
+-#define CICR1_RGBT_CONV (0x3 << 30) /* RGBT conversion mask */
++#define CICR1_RGBT_CONV (0x3 << 29) /* RGBT conversion mask */
+ #define CICR1_PPL (0x7ff << 15) /* Pixels per line mask */
+ #define CICR1_RGB_CONV (0x7 << 12) /* RGB conversion mask */
+ #define CICR1_RGB_F (1 << 11) /* RGB format */
+diff --git a/include/asm-arm/arch-pxa/pxa27x_keypad.h b/include/asm-arm/arch-pxa/pxa27x_keypad.h
+index 644f760..d5a48a9 100644
+--- a/include/asm-arm/arch-pxa/pxa27x_keypad.h
++++ b/include/asm-arm/arch-pxa/pxa27x_keypad.h
+@@ -53,4 +53,6 @@ struct pxa27x_keypad_platform_data {
+
+ #define KEY(row, col, val) (((row) << 28) | ((col) << 24) | (val))
+
++extern void pxa_set_keypad_info(struct pxa27x_keypad_platform_data *info);
++
+ #endif /* __ASM_ARCH_PXA27x_KEYPAD_H */
+diff --git a/include/asm-arm/arch-pxa/pxa2xx-gpio.h b/include/asm-arm/arch-pxa/pxa2xx-gpio.h
+new file mode 100644
+index 0000000..763313c
+--- /dev/null
++++ b/include/asm-arm/arch-pxa/pxa2xx-gpio.h
+@@ -0,0 +1,357 @@
++#ifndef __ASM_ARCH_PXA2XX_GPIO_H
++#define __ASM_ARCH_PXA2XX_GPIO_H
++
++/* GPIO alternate function assignments */
++
++#define GPIO1_RST 1 /* reset */
++#define GPIO6_MMCCLK 6 /* MMC Clock */
++#define GPIO7_48MHz 7 /* 48 MHz clock output */
++#define GPIO8_MMCCS0 8 /* MMC Chip Select 0 */
++#define GPIO9_MMCCS1 9 /* MMC Chip Select 1 */
++#define GPIO10_RTCCLK 10 /* real time clock (1 Hz) */
++#define GPIO11_3_6MHz 11 /* 3.6 MHz oscillator out */
++#define GPIO12_32KHz 12 /* 32 kHz out */
++#define GPIO12_CIF_DD_7 12 /* Camera data pin 7 */
++#define GPIO13_MBGNT 13 /* memory controller grant */
++#define GPIO14_MBREQ 14 /* alternate bus master request */
++#define GPIO15_nCS_1 15 /* chip select 1 */
++#define GPIO16_PWM0 16 /* PWM0 output */
++#define GPIO17_PWM1 17 /* PWM1 output */
++#define GPIO17_CIF_DD_6 17 /* Camera data pin 6 */
++#define GPIO18_RDY 18 /* Ext. Bus Ready */
++#define GPIO19_DREQ1 19 /* External DMA Request */
++#define GPIO20_DREQ0 20 /* External DMA Request */
++#define GPIO23_SCLK 23 /* SSP clock */
++#define GPIO23_CIF_MCLK 23 /* Camera Master Clock */
++#define GPIO24_SFRM 24 /* SSP Frame */
++#define GPIO24_CIF_FV 24 /* Camera frame start signal */
++#define GPIO25_STXD 25 /* SSP transmit */
++#define GPIO25_CIF_LV 25 /* Camera line start signal */
++#define GPIO26_SRXD 26 /* SSP receive */
++#define GPIO26_CIF_PCLK 26 /* Camera Pixel Clock */
++#define GPIO27_SEXTCLK 27 /* SSP ext_clk */
++#define GPIO27_CIF_DD_0 27 /* Camera data pin 0 */
++#define GPIO28_BITCLK 28 /* AC97/I2S bit_clk */
++#define GPIO29_SDATA_IN 29 /* AC97 Sdata_in0 / I2S Sdata_in */
++#define GPIO30_SDATA_OUT 30 /* AC97/I2S Sdata_out */
++#define GPIO31_SYNC 31 /* AC97/I2S sync */
++#define GPIO32_SDATA_IN1 32 /* AC97 Sdata_in1 */
++#define GPIO32_SYSCLK 32 /* I2S System Clock */
++#define GPIO32_MMCCLK 32 /* MMC Clock (PXA270) */
++#define GPIO33_nCS_5 33 /* chip select 5 */
++#define GPIO34_FFRXD 34 /* FFUART receive */
++#define GPIO34_MMCCS0 34 /* MMC Chip Select 0 */
++#define GPIO35_FFCTS 35 /* FFUART Clear to send */
++#define GPIO36_FFDCD 36 /* FFUART Data carrier detect */
++#define GPIO37_FFDSR 37 /* FFUART data set ready */
++#define GPIO38_FFRI 38 /* FFUART Ring Indicator */
++#define GPIO39_MMCCS1 39 /* MMC Chip Select 1 */
++#define GPIO39_FFTXD 39 /* FFUART transmit data */
++#define GPIO40_FFDTR 40 /* FFUART data terminal Ready */
++#define GPIO41_FFRTS 41 /* FFUART request to send */
++#define GPIO42_BTRXD 42 /* BTUART receive data */
++#define GPIO42_HWRXD 42 /* HWUART receive data */
++#define GPIO42_CIF_MCLK 42 /* Camera Master Clock */
++#define GPIO43_BTTXD 43 /* BTUART transmit data */
++#define GPIO43_HWTXD 43 /* HWUART transmit data */
++#define GPIO43_CIF_FV 43 /* Camera frame start signal */
++#define GPIO44_BTCTS 44 /* BTUART clear to send */
++#define GPIO44_HWCTS 44 /* HWUART clear to send */
++#define GPIO44_CIF_LV 44 /* Camera line start signal */
++#define GPIO45_BTRTS 45 /* BTUART request to send */
++#define GPIO45_HWRTS 45 /* HWUART request to send */
++#define GPIO45_AC97_SYSCLK 45 /* AC97 System Clock */
++#define GPIO45_CIF_PCLK 45 /* Camera Pixel Clock */
++#define GPIO46_ICPRXD 46 /* ICP receive data */
++#define GPIO46_STRXD 46 /* STD_UART receive data */
++#define GPIO47_ICPTXD 47 /* ICP transmit data */
++#define GPIO47_STTXD 47 /* STD_UART transmit data */
++#define GPIO47_CIF_DD_0 47 /* Camera data pin 0 */
++#define GPIO48_nPOE 48 /* Output Enable for Card Space */
++#define GPIO48_CIF_DD_5 48 /* Camera data pin 5 */
++#define GPIO49_nPWE 49 /* Write Enable for Card Space */
++#define GPIO50_nPIOR 50 /* I/O Read for Card Space */
++#define GPIO50_CIF_DD_3 50 /* Camera data pin 3 */
++#define GPIO51_nPIOW 51 /* I/O Write for Card Space */
++#define GPIO51_CIF_DD_2 51 /* Camera data pin 2 */
++#define GPIO52_nPCE_1 52 /* Card Enable for Card Space */
++#define GPIO52_CIF_DD_4 52 /* Camera data pin 4 */
++#define GPIO53_nPCE_2 53 /* Card Enable for Card Space */
++#define GPIO53_MMCCLK 53 /* MMC Clock */
++#define GPIO53_CIF_MCLK 53 /* Camera Master Clock */
++#define GPIO54_MMCCLK 54 /* MMC Clock */
++#define GPIO54_pSKTSEL 54 /* Socket Select for Card Space */
++#define GPIO54_nPCE_2 54 /* Card Enable for Card Space (PXA27x) */
++#define GPIO54_CIF_PCLK 54 /* Camera Pixel Clock */
++#define GPIO55_nPREG 55 /* Card Address bit 26 */
++#define GPIO55_CIF_DD_1 55 /* Camera data pin 1 */
++#define GPIO56_nPWAIT 56 /* Wait signal for Card Space */
++#define GPIO57_nIOIS16 57 /* Bus Width select for I/O Card Space */
++#define GPIO58_LDD_0 58 /* LCD data pin 0 */
++#define GPIO59_LDD_1 59 /* LCD data pin 1 */
++#define GPIO60_LDD_2 60 /* LCD data pin 2 */
++#define GPIO61_LDD_3 61 /* LCD data pin 3 */
++#define GPIO62_LDD_4 62 /* LCD data pin 4 */
++#define GPIO63_LDD_5 63 /* LCD data pin 5 */
++#define GPIO64_LDD_6 64 /* LCD data pin 6 */
++#define GPIO65_LDD_7 65 /* LCD data pin 7 */
++#define GPIO66_LDD_8 66 /* LCD data pin 8 */
++#define GPIO66_MBREQ 66 /* alternate bus master req */
++#define GPIO67_LDD_9 67 /* LCD data pin 9 */
++#define GPIO67_MMCCS0 67 /* MMC Chip Select 0 */
++#define GPIO68_LDD_10 68 /* LCD data pin 10 */
++#define GPIO68_MMCCS1 68 /* MMC Chip Select 1 */
++#define GPIO69_LDD_11 69 /* LCD data pin 11 */
++#define GPIO69_MMCCLK 69 /* MMC_CLK */
++#define GPIO70_LDD_12 70 /* LCD data pin 12 */
++#define GPIO70_RTCCLK 70 /* Real Time clock (1 Hz) */
++#define GPIO71_LDD_13 71 /* LCD data pin 13 */
++#define GPIO71_3_6MHz 71 /* 3.6 MHz Oscillator clock */
++#define GPIO72_LDD_14 72 /* LCD data pin 14 */
++#define GPIO72_32kHz 72 /* 32 kHz clock */
++#define GPIO73_LDD_15 73 /* LCD data pin 15 */
++#define GPIO73_MBGNT 73 /* Memory controller grant */
++#define GPIO74_LCD_FCLK 74 /* LCD Frame clock */
++#define GPIO75_LCD_LCLK 75 /* LCD line clock */
++#define GPIO76_LCD_PCLK 76 /* LCD Pixel clock */
++#define GPIO77_LCD_ACBIAS 77 /* LCD AC Bias */
++#define GPIO78_nCS_2 78 /* chip select 2 */
++#define GPIO79_nCS_3 79 /* chip select 3 */
++#define GPIO80_nCS_4 80 /* chip select 4 */
++#define GPIO81_NSCLK 81 /* NSSP clock */
++#define GPIO81_CIF_DD_0 81 /* Camera data pin 0 */
++#define GPIO82_NSFRM 82 /* NSSP Frame */
++#define GPIO82_CIF_DD_5 82 /* Camera data pin 5 */
++#define GPIO83_NSTXD 83 /* NSSP transmit */
++#define GPIO83_CIF_DD_4 83 /* Camera data pin 4 */
++#define GPIO84_NSRXD 84 /* NSSP receive */
++#define GPIO84_CIF_FV 84 /* Camera frame start signal */
++#define GPIO85_nPCE_1 85 /* Card Enable for Card Space (PXA27x) */
++#define GPIO85_CIF_LV 85 /* Camera line start signal */
++#define GPIO90_CIF_DD_4 90 /* Camera data pin 4 */
++#define GPIO91_CIF_DD_5 91 /* Camera data pin 5 */
++#define GPIO92_MMCDAT0 92 /* MMC DAT0 (PXA27x) */
++#define GPIO93_CIF_DD_6 93 /* Camera data pin 6 */
++#define GPIO94_CIF_DD_5 94 /* Camera data pin 5 */
++#define GPIO95_CIF_DD_4 95 /* Camera data pin 4 */
++#define GPIO98_CIF_DD_0 98 /* Camera data pin 0 */
++#define GPIO102_nPCE_1 102 /* PCMCIA (PXA27x) */
++#define GPIO103_CIF_DD_3 103 /* Camera data pin 3 */
++#define GPIO104_CIF_DD_2 104 /* Camera data pin 2 */
++#define GPIO105_CIF_DD_1 105 /* Camera data pin 1 */
++#define GPIO106_CIF_DD_9 106 /* Camera data pin 9 */
++#define GPIO107_CIF_DD_8 107 /* Camera data pin 8 */
++#define GPIO108_CIF_DD_7 108 /* Camera data pin 7 */
++#define GPIO109_MMCDAT1 109 /* MMC DAT1 (PXA27x) */
++#define GPIO110_MMCDAT2 110 /* MMC DAT2 (PXA27x) */
++#define GPIO110_MMCCS0 110 /* MMC Chip Select 0 (PXA27x) */
++#define GPIO111_MMCDAT3 111 /* MMC DAT3 (PXA27x) */
++#define GPIO111_MMCCS1 111 /* MMC Chip Select 1 (PXA27x) */
++#define GPIO112_MMCCMD 112 /* MMC CMD (PXA27x) */
++#define GPIO113_I2S_SYSCLK 113 /* I2S System Clock (PXA27x) */
++#define GPIO113_AC97_RESET_N 113 /* AC97 NRESET on (PXA27x) */
++#define GPIO114_CIF_DD_1 114 /* Camera data pin 1 */
++#define GPIO115_CIF_DD_3 115 /* Camera data pin 3 */
++#define GPIO116_CIF_DD_2 116 /* Camera data pin 2 */
++
++/* GPIO alternate function mode & direction */
++
++#define GPIO_IN 0x000
++#define GPIO_OUT 0x080
++#define GPIO_ALT_FN_1_IN 0x100
++#define GPIO_ALT_FN_1_OUT 0x180
++#define GPIO_ALT_FN_2_IN 0x200
++#define GPIO_ALT_FN_2_OUT 0x280
++#define GPIO_ALT_FN_3_IN 0x300
++#define GPIO_ALT_FN_3_OUT 0x380
++#define GPIO_MD_MASK_NR 0x07f
++#define GPIO_MD_MASK_DIR 0x080
++#define GPIO_MD_MASK_FN 0x300
++#define GPIO_DFLT_LOW 0x400
++#define GPIO_DFLT_HIGH 0x800
++
++#define GPIO1_RTS_MD ( 1 | GPIO_ALT_FN_1_IN)
++#define GPIO6_MMCCLK_MD ( 6 | GPIO_ALT_FN_1_OUT)
++#define GPIO7_48MHz_MD ( 7 | GPIO_ALT_FN_1_OUT)
++#define GPIO8_MMCCS0_MD ( 8 | GPIO_ALT_FN_1_OUT)
++#define GPIO9_MMCCS1_MD ( 9 | GPIO_ALT_FN_1_OUT)
++#define GPIO10_RTCCLK_MD (10 | GPIO_ALT_FN_1_OUT)
++#define GPIO11_3_6MHz_MD (11 | GPIO_ALT_FN_1_OUT)
++#define GPIO12_32KHz_MD (12 | GPIO_ALT_FN_1_OUT)
++#define GPIO12_CIF_DD_7_MD (12 | GPIO_ALT_FN_2_IN)
++#define GPIO13_MBGNT_MD (13 | GPIO_ALT_FN_2_OUT)
++#define GPIO14_MBREQ_MD (14 | GPIO_ALT_FN_1_IN)
++#define GPIO15_nCS_1_MD (15 | GPIO_ALT_FN_2_OUT)
++#define GPIO16_PWM0_MD (16 | GPIO_ALT_FN_2_OUT)
++#define GPIO17_PWM1_MD (17 | GPIO_ALT_FN_2_OUT)
++#define GPIO17_CIF_DD_6_MD (17 | GPIO_ALT_FN_2_IN)
++#define GPIO18_RDY_MD (18 | GPIO_ALT_FN_1_IN)
++#define GPIO19_DREQ1_MD (19 | GPIO_ALT_FN_1_IN)
++#define GPIO20_DREQ0_MD (20 | GPIO_ALT_FN_1_IN)
++#define GPIO23_CIF_MCLK_MD (23 | GPIO_ALT_FN_1_OUT)
++#define GPIO23_SCLK_MD (23 | GPIO_ALT_FN_2_OUT)
++#define GPIO24_CIF_FV_MD (24 | GPIO_ALT_FN_1_OUT)
++#define GPIO24_SFRM_MD (24 | GPIO_ALT_FN_2_OUT)
++#define GPIO25_CIF_LV_MD (25 | GPIO_ALT_FN_1_OUT)
++#define GPIO25_STXD_MD (25 | GPIO_ALT_FN_2_OUT)
++#define GPIO26_SRXD_MD (26 | GPIO_ALT_FN_1_IN)
++#define GPIO26_CIF_PCLK_MD (26 | GPIO_ALT_FN_2_IN)
++#define GPIO27_SEXTCLK_MD (27 | GPIO_ALT_FN_1_IN)
++#define GPIO27_CIF_DD_0_MD (27 | GPIO_ALT_FN_3_IN)
++#define GPIO28_BITCLK_AC97_MD (28 | GPIO_ALT_FN_1_IN)
++#define GPIO28_BITCLK_IN_I2S_MD (28 | GPIO_ALT_FN_2_IN)
++#define GPIO28_BITCLK_OUT_I2S_MD (28 | GPIO_ALT_FN_1_OUT)
++#define GPIO29_SDATA_IN_AC97_MD (29 | GPIO_ALT_FN_1_IN)
++#define GPIO29_SDATA_IN_I2S_MD (29 | GPIO_ALT_FN_2_IN)
++#define GPIO30_SDATA_OUT_AC97_MD (30 | GPIO_ALT_FN_2_OUT)
++#define GPIO30_SDATA_OUT_I2S_MD (30 | GPIO_ALT_FN_1_OUT)
++#define GPIO31_SYNC_I2S_MD (31 | GPIO_ALT_FN_1_OUT)
++#define GPIO31_SYNC_AC97_MD (31 | GPIO_ALT_FN_2_OUT)
++#define GPIO32_SDATA_IN1_AC97_MD (32 | GPIO_ALT_FN_1_IN)
++#define GPIO32_SYSCLK_I2S_MD (32 | GPIO_ALT_FN_1_OUT)
++#define GPIO32_MMCCLK_MD (32 | GPIO_ALT_FN_2_OUT)
++#define GPIO33_nCS_5_MD (33 | GPIO_ALT_FN_2_OUT)
++#define GPIO34_FFRXD_MD (34 | GPIO_ALT_FN_1_IN)
++#define GPIO34_MMCCS0_MD (34 | GPIO_ALT_FN_2_OUT)
++#define GPIO35_FFCTS_MD (35 | GPIO_ALT_FN_1_IN)
++#define GPIO35_KP_MKOUT6_MD (35 | GPIO_ALT_FN_2_OUT)
++#define GPIO36_FFDCD_MD (36 | GPIO_ALT_FN_1_IN)
++#define GPIO37_FFDSR_MD (37 | GPIO_ALT_FN_1_IN)
++#define GPIO38_FFRI_MD (38 | GPIO_ALT_FN_1_IN)
++#define GPIO39_MMCCS1_MD (39 | GPIO_ALT_FN_1_OUT)
++#define GPIO39_FFTXD_MD (39 | GPIO_ALT_FN_2_OUT)
++#define GPIO40_FFDTR_MD (40 | GPIO_ALT_FN_2_OUT)
++#define GPIO41_FFRTS_MD (41 | GPIO_ALT_FN_2_OUT)
++#define GPIO41_KP_MKOUT7_MD (41 | GPIO_ALT_FN_1_OUT)
++#define GPIO42_BTRXD_MD (42 | GPIO_ALT_FN_1_IN)
++#define GPIO42_HWRXD_MD (42 | GPIO_ALT_FN_3_IN)
++#define GPIO42_CIF_MCLK_MD (42 | GPIO_ALT_FN_3_OUT)
++#define GPIO43_BTTXD_MD (43 | GPIO_ALT_FN_2_OUT)
++#define GPIO43_HWTXD_MD (43 | GPIO_ALT_FN_3_OUT)
++#define GPIO43_CIF_FV_MD (43 | GPIO_ALT_FN_3_OUT)
++#define GPIO44_BTCTS_MD (44 | GPIO_ALT_FN_1_IN)
++#define GPIO44_HWCTS_MD (44 | GPIO_ALT_FN_3_IN)
++#define GPIO44_CIF_LV_MD (44 | GPIO_ALT_FN_3_OUT)
++#define GPIO45_CIF_PCLK_MD (45 | GPIO_ALT_FN_3_IN)
++#define GPIO45_BTRTS_MD (45 | GPIO_ALT_FN_2_OUT)
++#define GPIO45_HWRTS_MD (45 | GPIO_ALT_FN_3_OUT)
++#define GPIO45_SYSCLK_AC97_MD (45 | GPIO_ALT_FN_1_OUT)
++#define GPIO46_ICPRXD_MD (46 | GPIO_ALT_FN_1_IN)
++#define GPIO46_STRXD_MD (46 | GPIO_ALT_FN_2_IN)
++#define GPIO47_CIF_DD_0_MD (47 | GPIO_ALT_FN_1_IN)
++#define GPIO47_ICPTXD_MD (47 | GPIO_ALT_FN_2_OUT)
++#define GPIO47_STTXD_MD (47 | GPIO_ALT_FN_1_OUT)
++#define GPIO48_CIF_DD_5_MD (48 | GPIO_ALT_FN_1_IN)
++#define GPIO48_nPOE_MD (48 | GPIO_ALT_FN_2_OUT)
++#define GPIO48_HWTXD_MD (48 | GPIO_ALT_FN_1_OUT)
++#define GPIO48_nPOE_MD (48 | GPIO_ALT_FN_2_OUT)
++#define GPIO49_HWRXD_MD (49 | GPIO_ALT_FN_1_IN)
++#define GPIO49_nPWE_MD (49 | GPIO_ALT_FN_2_OUT)
++#define GPIO50_CIF_DD_3_MD (50 | GPIO_ALT_FN_1_IN)
++#define GPIO50_nPIOR_MD (50 | GPIO_ALT_FN_2_OUT)
++#define GPIO50_HWCTS_MD (50 | GPIO_ALT_FN_1_IN)
++#define GPIO50_CIF_DD_3_MD (50 | GPIO_ALT_FN_1_IN)
++#define GPIO51_CIF_DD_2_MD (51 | GPIO_ALT_FN_1_IN)
++#define GPIO51_nPIOW_MD (51 | GPIO_ALT_FN_2_OUT)
++#define GPIO51_HWRTS_MD (51 | GPIO_ALT_FN_1_OUT)
++#define GPIO51_CIF_DD_2_MD (51 | GPIO_ALT_FN_1_IN)
++#define GPIO52_nPCE_1_MD (52 | GPIO_ALT_FN_2_OUT)
++#define GPIO52_CIF_DD_4_MD (52 | GPIO_ALT_FN_1_IN)
++#define GPIO53_nPCE_2_MD (53 | GPIO_ALT_FN_2_OUT)
++#define GPIO53_MMCCLK_MD (53 | GPIO_ALT_FN_1_OUT)
++#define GPIO53_CIF_MCLK_MD (53 | GPIO_ALT_FN_2_OUT)
++#define GPIO54_MMCCLK_MD (54 | GPIO_ALT_FN_1_OUT)
++#define GPIO54_nPCE_2_MD (54 | GPIO_ALT_FN_2_OUT)
++#define GPIO54_pSKTSEL_MD (54 | GPIO_ALT_FN_2_OUT)
++#define GPIO54_CIF_PCLK_MD (54 | GPIO_ALT_FN_3_IN)
++#define GPIO55_nPREG_MD (55 | GPIO_ALT_FN_2_OUT)
++#define GPIO55_CIF_DD_1_MD (55 | GPIO_ALT_FN_1_IN)
++#define GPIO56_nPWAIT_MD (56 | GPIO_ALT_FN_1_IN)
++#define GPIO57_nIOIS16_MD (57 | GPIO_ALT_FN_1_IN)
++#define GPIO58_LDD_0_MD (58 | GPIO_ALT_FN_2_OUT)
++#define GPIO59_LDD_1_MD (59 | GPIO_ALT_FN_2_OUT)
++#define GPIO60_LDD_2_MD (60 | GPIO_ALT_FN_2_OUT)
++#define GPIO61_LDD_3_MD (61 | GPIO_ALT_FN_2_OUT)
++#define GPIO62_LDD_4_MD (62 | GPIO_ALT_FN_2_OUT)
++#define GPIO63_LDD_5_MD (63 | GPIO_ALT_FN_2_OUT)
++#define GPIO64_LDD_6_MD (64 | GPIO_ALT_FN_2_OUT)
++#define GPIO65_LDD_7_MD (65 | GPIO_ALT_FN_2_OUT)
++#define GPIO66_LDD_8_MD (66 | GPIO_ALT_FN_2_OUT)
++#define GPIO66_MBREQ_MD (66 | GPIO_ALT_FN_1_IN)
++#define GPIO67_LDD_9_MD (67 | GPIO_ALT_FN_2_OUT)
++#define GPIO67_MMCCS0_MD (67 | GPIO_ALT_FN_1_OUT)
++#define GPIO68_LDD_10_MD (68 | GPIO_ALT_FN_2_OUT)
++#define GPIO68_MMCCS1_MD (68 | GPIO_ALT_FN_1_OUT)
++#define GPIO69_LDD_11_MD (69 | GPIO_ALT_FN_2_OUT)
++#define GPIO69_MMCCLK_MD (69 | GPIO_ALT_FN_1_OUT)
++#define GPIO70_LDD_12_MD (70 | GPIO_ALT_FN_2_OUT)
++#define GPIO70_RTCCLK_MD (70 | GPIO_ALT_FN_1_OUT)
++#define GPIO71_LDD_13_MD (71 | GPIO_ALT_FN_2_OUT)
++#define GPIO71_3_6MHz_MD (71 | GPIO_ALT_FN_1_OUT)
++#define GPIO72_LDD_14_MD (72 | GPIO_ALT_FN_2_OUT)
++#define GPIO72_32kHz_MD (72 | GPIO_ALT_FN_1_OUT)
++#define GPIO73_LDD_15_MD (73 | GPIO_ALT_FN_2_OUT)
++#define GPIO73_MBGNT_MD (73 | GPIO_ALT_FN_1_OUT)
++#define GPIO74_LCD_FCLK_MD (74 | GPIO_ALT_FN_2_OUT)
++#define GPIO75_LCD_LCLK_MD (75 | GPIO_ALT_FN_2_OUT)
++#define GPIO76_LCD_PCLK_MD (76 | GPIO_ALT_FN_2_OUT)
++#define GPIO77_LCD_ACBIAS_MD (77 | GPIO_ALT_FN_2_OUT)
++#define GPIO78_nCS_2_MD (78 | GPIO_ALT_FN_2_OUT)
++#define GPIO78_nPCE_2_MD (78 | GPIO_ALT_FN_1_OUT)
++#define GPIO79_nCS_3_MD (79 | GPIO_ALT_FN_2_OUT)
++#define GPIO79_pSKTSEL_MD (79 | GPIO_ALT_FN_1_OUT)
++#define GPIO80_nCS_4_MD (80 | GPIO_ALT_FN_2_OUT)
++#define GPIO81_NSSP_CLK_OUT (81 | GPIO_ALT_FN_1_OUT)
++#define GPIO81_NSSP_CLK_IN (81 | GPIO_ALT_FN_1_IN)
++#define GPIO81_CIF_DD_0_MD (81 | GPIO_ALT_FN_2_IN)
++#define GPIO82_NSSP_FRM_OUT (82 | GPIO_ALT_FN_1_OUT)
++#define GPIO82_NSSP_FRM_IN (82 | GPIO_ALT_FN_1_IN)
++#define GPIO82_CIF_DD_5_MD (82 | GPIO_ALT_FN_3_IN)
++#define GPIO83_NSSP_TX (83 | GPIO_ALT_FN_1_OUT)
++#define GPIO83_NSSP_RX (83 | GPIO_ALT_FN_2_IN)
++#define GPIO83_CIF_DD_4_MD (83 | GPIO_ALT_FN_3_IN)
++#define GPIO84_NSSP_TX (84 | GPIO_ALT_FN_1_OUT)
++#define GPIO84_NSSP_RX (84 | GPIO_ALT_FN_2_IN)
++#define GPIO84_CIF_FV_MD (84 | GPIO_ALT_FN_3_IN)
++#define GPIO85_nPCE_1_MD (85 | GPIO_ALT_FN_1_OUT)
++#define GPIO85_CIF_LV_MD (85 | GPIO_ALT_FN_3_IN)
++#define GPIO86_nPCE_1_MD (86 | GPIO_ALT_FN_1_OUT)
++#define GPIO90_CIF_DD_4_MD (90 | GPIO_ALT_FN_3_IN)
++#define GPIO91_CIF_DD_5_MD (91 | GPIO_ALT_FN_3_IN)
++#define GPIO92_MMCDAT0_MD (92 | GPIO_ALT_FN_1_OUT)
++#define GPIO93_CIF_DD_6_MD (93 | GPIO_ALT_FN_2_IN)
++#define GPIO94_CIF_DD_5_MD (94 | GPIO_ALT_FN_2_IN)
++#define GPIO95_CIF_DD_4_MD (95 | GPIO_ALT_FN_2_IN)
++#define GPIO95_KP_MKIN6_MD (95 | GPIO_ALT_FN_3_IN)
++#define GPIO96_KP_DKIN3_MD (96 | GPIO_ALT_FN_1_IN)
++#define GPIO97_KP_MKIN3_MD (97 | GPIO_ALT_FN_3_IN)
++#define GPIO98_CIF_DD_0_MD (98 | GPIO_ALT_FN_2_IN)
++#define GPIO100_KP_MKIN0_MD (100 | GPIO_ALT_FN_1_IN)
++#define GPIO101_KP_MKIN1_MD (101 | GPIO_ALT_FN_1_IN)
++#define GPIO102_nPCE_1_MD (102 | GPIO_ALT_FN_1_OUT)
++#define GPIO102_KP_MKIN2_MD (102 | GPIO_ALT_FN_1_IN)
++#define GPIO103_CIF_DD_3_MD (103 | GPIO_ALT_FN_1_IN)
++#define GPIO103_KP_MKOUT0_MD (103 | GPIO_ALT_FN_2_OUT)
++#define GPIO104_CIF_DD_2_MD (104 | GPIO_ALT_FN_1_IN)
++#define GPIO104_pSKTSEL_MD (104 | GPIO_ALT_FN_1_OUT)
++#define GPIO104_KP_MKOUT1_MD (104 | GPIO_ALT_FN_2_OUT)
++#define GPIO105_CIF_DD_1_MD (105 | GPIO_ALT_FN_1_IN)
++#define GPIO105_KP_MKOUT2_MD (105 | GPIO_ALT_FN_2_OUT)
++#define GPIO106_CIF_DD_9_MD (106 | GPIO_ALT_FN_1_IN)
++#define GPIO106_KP_MKOUT3_MD (106 | GPIO_ALT_FN_2_OUT)
++#define GPIO107_CIF_DD_8_MD (107 | GPIO_ALT_FN_1_IN)
++#define GPIO107_KP_MKOUT4_MD (107 | GPIO_ALT_FN_2_OUT)
++#define GPIO108_CIF_DD_7_MD (108 | GPIO_ALT_FN_1_IN)
++#define GPIO108_KP_MKOUT5_MD (108 | GPIO_ALT_FN_2_OUT)
++#define GPIO109_MMCDAT1_MD (109 | GPIO_ALT_FN_1_OUT)
++#define GPIO110_MMCDAT2_MD (110 | GPIO_ALT_FN_1_OUT)
++#define GPIO110_MMCCS0_MD (110 | GPIO_ALT_FN_1_OUT)
++#define GPIO111_MMCDAT3_MD (111 | GPIO_ALT_FN_1_OUT)
++#define GPIO110_MMCCS1_MD (111 | GPIO_ALT_FN_1_OUT)
++#define GPIO112_MMCCMD_MD (112 | GPIO_ALT_FN_1_OUT)
++#define GPIO113_I2S_SYSCLK_MD (113 | GPIO_ALT_FN_1_OUT)
++#define GPIO113_AC97_RESET_N_MD (113 | GPIO_ALT_FN_2_OUT)
++#define GPIO117_I2CSCL_MD (117 | GPIO_ALT_FN_1_IN)
++#define GPIO118_I2CSDA_MD (118 | GPIO_ALT_FN_1_IN)
++
++#endif /* __ASM_ARCH_PXA2XX_GPIO_H */
+diff --git a/include/asm-arm/arch-pxa/pxa3xx-regs.h b/include/asm-arm/arch-pxa/pxa3xx-regs.h
+index 8e1b3ea..fe9364c 100644
+--- a/include/asm-arm/arch-pxa/pxa3xx-regs.h
++++ b/include/asm-arm/arch-pxa/pxa3xx-regs.h
+@@ -12,6 +12,15 @@
+
+ #ifndef __ASM_ARCH_PXA3XX_REGS_H
+ #define __ASM_ARCH_PXA3XX_REGS_H
++
++/*
++ * Oscillator Configuration Register (OSCC)
++ */
++#define OSCC __REG(0x41350000) /* Oscillator Configuration Register */
++
++#define OSCC_PEN (1 << 11) /* 13MHz POUT */
++
++
+ /*
+ * Service Power Management Unit (MPMU)
+ */
+diff --git a/include/asm-arm/arch-pxa/pxa3xx_nand.h b/include/asm-arm/arch-pxa/pxa3xx_nand.h
+new file mode 100644
+index 0000000..81a8937
+--- /dev/null
++++ b/include/asm-arm/arch-pxa/pxa3xx_nand.h
+@@ -0,0 +1,18 @@
++#ifndef __ASM_ARCH_PXA3XX_NAND_H
++#define __ASM_ARCH_PXA3XX_NAND_H
++
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++
++struct pxa3xx_nand_platform_data {
++
++ /* the data flash bus is shared between the Static Memory
++ * Controller and the Data Flash Controller, the arbiter
++ * controls the ownership of the bus
++ */
++ int enable_arbiter;
++
++ struct mtd_partition *parts;
++ unsigned int nr_parts;
++};
++#endif /* __ASM_ARCH_PXA3XX_NAND_H */
+diff --git a/include/asm-arm/arch-pxa/tosa.h b/include/asm-arm/arch-pxa/tosa.h
+index c05e4fa..c5b6fde 100644
+--- a/include/asm-arm/arch-pxa/tosa.h
++++ b/include/asm-arm/arch-pxa/tosa.h
+@@ -23,11 +23,12 @@
+ /*
+ * SCOOP2 internal GPIOs
+ */
++#define TOSA_SCOOP_GPIO_BASE NR_BUILTIN_GPIO
+ #define TOSA_SCOOP_PXA_VCORE1 SCOOP_GPCR_PA11
+ #define TOSA_SCOOP_TC6393_REST_IN SCOOP_GPCR_PA12
+-#define TOSA_SCOOP_IR_POWERDWN SCOOP_GPCR_PA13
+-#define TOSA_SCOOP_SD_WP SCOOP_GPCR_PA14
+-#define TOSA_SCOOP_PWR_ON SCOOP_GPCR_PA15
++#define TOSA_GPIO_IR_POWERDWN (TOSA_SCOOP_GPIO_BASE + 2)
++#define TOSA_GPIO_SD_WP (TOSA_SCOOP_GPIO_BASE + 3)
++#define TOSA_GPIO_PWR_ON (TOSA_SCOOP_GPIO_BASE + 4)
+ #define TOSA_SCOOP_AUD_PWR_ON SCOOP_GPCR_PA16
+ #define TOSA_SCOOP_BT_RESET SCOOP_GPCR_PA17
+ #define TOSA_SCOOP_BT_PWR_EN SCOOP_GPCR_PA18
+@@ -35,7 +36,7 @@
+
+ /* GPIO Direction 1 : output mode / 0:input mode */
+ #define TOSA_SCOOP_IO_DIR ( TOSA_SCOOP_PXA_VCORE1 | TOSA_SCOOP_TC6393_REST_IN | \
+- TOSA_SCOOP_IR_POWERDWN | TOSA_SCOOP_PWR_ON | TOSA_SCOOP_AUD_PWR_ON |\
++ TOSA_SCOOP_AUD_PWR_ON |\
+ TOSA_SCOOP_BT_RESET | TOSA_SCOOP_BT_PWR_EN )
+ /* GPIO out put level when init 1: Hi */
+ #define TOSA_SCOOP_IO_OUT ( TOSA_SCOOP_TC6393_REST_IN )
+@@ -43,23 +44,21 @@
+ /*
+ * SCOOP2 jacket GPIOs
+ */
+-#define TOSA_SCOOP_JC_BT_LED SCOOP_GPCR_PA11
+-#define TOSA_SCOOP_JC_NOTE_LED SCOOP_GPCR_PA12
+-#define TOSA_SCOOP_JC_CHRG_ERR_LED SCOOP_GPCR_PA13
+-#define TOSA_SCOOP_JC_USB_PULLUP SCOOP_GPCR_PA14
++#define TOSA_SCOOP_JC_GPIO_BASE (NR_BUILTIN_GPIO + 12)
++#define TOSA_GPIO_BT_LED (TOSA_SCOOP_JC_GPIO_BASE + 0)
++#define TOSA_GPIO_NOTE_LED (TOSA_SCOOP_JC_GPIO_BASE + 1)
++#define TOSA_GPIO_CHRG_ERR_LED (TOSA_SCOOP_JC_GPIO_BASE + 2)
++#define TOSA_GPIO_USB_PULLUP (TOSA_SCOOP_JC_GPIO_BASE + 3)
+ #define TOSA_SCOOP_JC_TC6393_SUSPEND SCOOP_GPCR_PA15
+ #define TOSA_SCOOP_JC_TC3693_L3V_ON SCOOP_GPCR_PA16
+ #define TOSA_SCOOP_JC_WLAN_DETECT SCOOP_GPCR_PA17
+-#define TOSA_SCOOP_JC_WLAN_LED SCOOP_GPCR_PA18
++#define TOSA_GPIO_WLAN_LED (TOSA_SCOOP_JC_GPIO_BASE + 7)
+ #define TOSA_SCOOP_JC_CARD_LIMIT_SEL SCOOP_GPCR_PA19
+
+ /* GPIO Direction 1 : output mode / 0:input mode */
+-#define TOSA_SCOOP_JC_IO_DIR ( TOSA_SCOOP_JC_BT_LED | TOSA_SCOOP_JC_NOTE_LED | \
+- TOSA_SCOOP_JC_CHRG_ERR_LED | TOSA_SCOOP_JC_USB_PULLUP | \
++#define TOSA_SCOOP_JC_IO_DIR ( \
+ TOSA_SCOOP_JC_TC6393_SUSPEND | TOSA_SCOOP_JC_TC3693_L3V_ON | \
+- TOSA_SCOOP_JC_WLAN_LED | TOSA_SCOOP_JC_CARD_LIMIT_SEL )
+-/* GPIO out put level when init 1: Hi */
+-#define TOSA_SCOOP_JC_IO_OUT ( 0 )
++ TOSA_SCOOP_JC_CARD_LIMIT_SEL )
+
+ /*
+ * Timing Generator
+@@ -74,15 +73,6 @@
+ #define TG_HPOSCTL 0x07
+
+ /*
+- * LED
+- */
+-#define TOSA_SCOOP_LED_BLUE TOSA_SCOOP_GPCR_PA11
+-#define TOSA_SCOOP_LED_GREEN TOSA_SCOOP_GPCR_PA12
+-#define TOSA_SCOOP_LED_ORANGE TOSA_SCOOP_GPCR_PA13
+-#define TOSA_SCOOP_LED_WLAN TOSA_SCOOP_GPCR_PA18
+-
+-
+-/*
+ * PXA GPIOs
+ */
+ #define TOSA_GPIO_POWERON (0)
+@@ -161,12 +151,8 @@
+
+ #define TOSA_IRQ_GPIO_MAIN_BAT_LOW IRQ_GPIO(TOSA_GPIO_MAIN_BAT_LOW)
+
+-extern struct platform_device tosascoop_jc_device;
+-extern struct platform_device tosascoop_device;
+-
+ #define TOSA_KEY_SYNC KEY_102ND /* ??? */
+
+-
+ #ifndef CONFIG_KEYBOARD_TOSA_USE_EXT_KEYCODES
+ #define TOSA_KEY_RECORD KEY_YEN
+ #define TOSA_KEY_ADDRESSBOOK KEY_KATAKANA
+diff --git a/include/asm-arm/arch-pxa/zylonite.h b/include/asm-arm/arch-pxa/zylonite.h
+index 5f717d6..4881b80 100644
+--- a/include/asm-arm/arch-pxa/zylonite.h
++++ b/include/asm-arm/arch-pxa/zylonite.h
+@@ -18,6 +18,8 @@ extern struct platform_mmc_slot zylonite_mmc_slot[];
+ extern int gpio_backlight;
+ extern int gpio_eth_irq;
+
++extern int wm9713_irq;
++
+ extern int lcd_id;
+ extern int lcd_orientation;
+
+diff --git a/include/asm-arm/arch-realview/board-eb.h b/include/asm-arm/arch-realview/board-eb.h
+index 3e437b7..206f7a7 100644
+--- a/include/asm-arm/arch-realview/board-eb.h
++++ b/include/asm-arm/arch-realview/board-eb.h
+@@ -26,6 +26,26 @@
+ /*
+ * RealView EB + ARM11MPCore peripheral addresses
+ */
++#define REALVIEW_EB_UART0_BASE 0x10009000 /* UART 0 */
++#define REALVIEW_EB_UART1_BASE 0x1000A000 /* UART 1 */
++#define REALVIEW_EB_UART2_BASE 0x1000B000 /* UART 2 */
++#define REALVIEW_EB_UART3_BASE 0x1000C000 /* UART 3 */
++#define REALVIEW_EB_SSP_BASE 0x1000D000 /* Synchronous Serial Port */
++#define REALVIEW_EB_WATCHDOG_BASE 0x10010000 /* watchdog interface */
++#define REALVIEW_EB_TIMER0_1_BASE 0x10011000 /* Timer 0 and 1 */
++#define REALVIEW_EB_TIMER2_3_BASE 0x10012000 /* Timer 2 and 3 */
++#define REALVIEW_EB_GPIO0_BASE 0x10013000 /* GPIO port 0 */
++#define REALVIEW_EB_RTC_BASE 0x10017000 /* Real Time Clock */
++#define REALVIEW_EB_CLCD_BASE 0x10020000 /* CLCD */
++#define REALVIEW_EB_GIC_CPU_BASE 0x10040000 /* Generic interrupt controller CPU interface */
++#define REALVIEW_EB_GIC_DIST_BASE 0x10041000 /* Generic interrupt controller distributor */
++#define REALVIEW_EB_SMC_BASE 0x10080000 /* Static memory controller */
++
++#define REALVIEW_EB_FLASH_BASE 0x40000000
++#define REALVIEW_EB_FLASH_SIZE SZ_64M
++#define REALVIEW_EB_ETH_BASE 0x4E000000 /* Ethernet */
++#define REALVIEW_EB_USB_BASE 0x4F000000 /* USB */
++
+ #ifdef CONFIG_REALVIEW_EB_ARM11MP_REVB
+ #define REALVIEW_EB11MP_SCU_BASE 0x10100000 /* SCU registers */
+ #define REALVIEW_EB11MP_GIC_CPU_BASE 0x10100100 /* Generic interrupt controller CPU interface */
+diff --git a/include/asm-arm/arch-realview/board-pb1176.h b/include/asm-arm/arch-realview/board-pb1176.h
+new file mode 100644
+index 0000000..48ce9c8
+--- /dev/null
++++ b/include/asm-arm/arch-realview/board-pb1176.h
+@@ -0,0 +1,152 @@
++/*
++ * include/asm-arm/arch-realview/board-pb1176.h
++ *
++ * Copyright (C) 2008 ARM Limited
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
++ * MA 02110-1301, USA.
++ */
++
++#ifndef __ASM_ARCH_BOARD_PB1176_H
++#define __ASM_ARCH_BOARD_PB1176_H
++
++#include <asm/arch/platform.h>
++
++/*
++ * Peripheral addresses
++ */
++#define REALVIEW_PB1176_SCTL_BASE 0x10100000 /* System controller */
++#define REALVIEW_PB1176_SMC_BASE 0x10111000 /* SMC */
++#define REALVIEW_PB1176_DMC_BASE 0x10109000 /* DMC configuration */
++#define REALVIEW_PB1176_SDRAM67_BASE 0x70000000 /* SDRAM banks 6 and 7 */
++#define REALVIEW_PB1176_FLASH_BASE 0x30000000
++#define REALVIEW_PB1176_FLASH_SIZE SZ_64M
++
++#define REALVIEW_PB1176_TIMER0_1_BASE 0x10104000 /* Timer 0 and 1 */
++#define REALVIEW_PB1176_TIMER2_3_BASE 0x10105000 /* Timer 2 and 3 */
++#define REALVIEW_PB1176_TIMER4_5_BASE 0x10106000 /* Timer 4 and 5 */
++#define REALVIEW_PB1176_WATCHDOG_BASE 0x10107000 /* watchdog interface */
++#define REALVIEW_PB1176_RTC_BASE 0x10108000 /* Real Time Clock */
++#define REALVIEW_PB1176_GPIO0_BASE 0x1010A000 /* GPIO port 0 */
++#define REALVIEW_PB1176_SSP_BASE 0x1010B000 /* Synchronous Serial Port */
++#define REALVIEW_PB1176_UART0_BASE 0x1010C000 /* UART 0 */
++#define REALVIEW_PB1176_UART1_BASE 0x1010D000 /* UART 1 */
++#define REALVIEW_PB1176_UART2_BASE 0x1010E000 /* UART 2 */
++#define REALVIEW_PB1176_UART3_BASE 0x1010F000 /* UART 3 */
++#define REALVIEW_PB1176_CLCD_BASE 0x10112000 /* CLCD */
++#define REALVIEW_PB1176_ETH_BASE 0x3A000000 /* Ethernet */
++#define REALVIEW_PB1176_USB_BASE 0x3B000000 /* USB */
++
++/*
++ * PCI regions
++ */
++#define REALVIEW_PB1176_PCI_BASE 0x60000000 /* PCI self config */
++#define REALVIEW_PB1176_PCI_CFG_BASE 0x61000000 /* PCI config */
++#define REALVIEW_PB1176_PCI_IO_BASE0 0x62000000 /* PCI IO region */
++#define REALVIEW_PB1176_PCI_MEM_BASE0 0x63000000 /* Memory region 1 */
++#define REALVIEW_PB1176_PCI_MEM_BASE1 0x64000000 /* Memory region 2 */
++#define REALVIEW_PB1176_PCI_MEM_BASE2 0x68000000 /* Memory region 3 */
++
++#define REALVIEW_PB1176_PCI_BASE_SIZE 0x01000000 /* 16MB */
++#define REALVIEW_PB1176_PCI_CFG_BASE_SIZE 0x01000000 /* 16MB */
++#define REALVIEW_PB1176_PCI_IO_BASE0_SIZE 0x01000000 /* 16MB */
++#define REALVIEW_PB1176_PCI_MEM_BASE0_SIZE 0x01000000 /* 16MB */
++#define REALVIEW_PB1176_PCI_MEM_BASE1_SIZE 0x04000000 /* 64MB */
++#define REALVIEW_PB1176_PCI_MEM_BASE2_SIZE 0x08000000 /* 128MB */
++
++#define REALVIEW_DC1176_GIC_CPU_BASE 0x10120000 /* GIC CPU interface, on devchip */
++#define REALVIEW_DC1176_GIC_DIST_BASE 0x10121000 /* GIC distributor, on devchip */
++#define REALVIEW_PB1176_GIC_CPU_BASE 0x10040000 /* GIC CPU interface, on FPGA */
++#define REALVIEW_PB1176_GIC_DIST_BASE 0x10041000 /* GIC distributor, on FPGA */
++#define REALVIEW_PB1176_L220_BASE 0x10110000 /* L220 registers */
++
++/*
++ * Irqs
++ */
++#define IRQ_DC1176_GIC_START 32
++#define IRQ_PB1176_GIC_START 64
++
++/*
++ * ARM1176 DevChip interrupt sources (primary GIC)
++ */
++#define IRQ_DC1176_WATCHDOG (IRQ_DC1176_GIC_START + 0) /* Watchdog timer */
++#define IRQ_DC1176_SOFTINT (IRQ_DC1176_GIC_START + 1) /* Software interrupt */
++#define IRQ_DC1176_COMMRx (IRQ_DC1176_GIC_START + 2) /* Debug Comm Rx interrupt */
++#define IRQ_DC1176_COMMTx (IRQ_DC1176_GIC_START + 3) /* Debug Comm Tx interrupt */
++#define IRQ_DC1176_TIMER0 (IRQ_DC1176_GIC_START + 8) /* Timer 0 */
++#define IRQ_DC1176_TIMER1 (IRQ_DC1176_GIC_START + 9) /* Timer 1 */
++#define IRQ_DC1176_TIMER2 (IRQ_DC1176_GIC_START + 10) /* Timer 2 */
++#define IRQ_DC1176_APC (IRQ_DC1176_GIC_START + 11)
++#define IRQ_DC1176_IEC (IRQ_DC1176_GIC_START + 12)
++#define IRQ_DC1176_L2CC (IRQ_DC1176_GIC_START + 13)
++#define IRQ_DC1176_RTC (IRQ_DC1176_GIC_START + 14)
++#define IRQ_DC1176_CLCD (IRQ_DC1176_GIC_START + 15) /* CLCD controller */
++#define IRQ_DC1176_UART0 (IRQ_DC1176_GIC_START + 18) /* UART 0 on development chip */
++#define IRQ_DC1176_UART1 (IRQ_DC1176_GIC_START + 19) /* UART 1 on development chip */
++#define IRQ_DC1176_UART2 (IRQ_DC1176_GIC_START + 20) /* UART 2 on development chip */
++#define IRQ_DC1176_UART3 (IRQ_DC1176_GIC_START + 21) /* UART 3 on development chip */
++
++#define IRQ_DC1176_PB_IRQ2 (IRQ_DC1176_GIC_START + 30) /* tile GIC */
++#define IRQ_DC1176_PB_IRQ1 (IRQ_DC1176_GIC_START + 31) /* main GIC */
++
++/*
++ * RealView PB1176 interrupt sources (secondary GIC)
++ */
++#define IRQ_PB1176_MMCI0A (IRQ_PB1176_GIC_START + 1) /* Multimedia Card 0A */
++#define IRQ_PB1176_MMCI0B (IRQ_PB1176_GIC_START + 2) /* Multimedia Card 0A */
++#define IRQ_PB1176_KMI0 (IRQ_PB1176_GIC_START + 3) /* Keyboard/Mouse port 0 */
++#define IRQ_PB1176_KMI1 (IRQ_PB1176_GIC_START + 4) /* Keyboard/Mouse port 1 */
++#define IRQ_PB1176_SCI (IRQ_PB1176_GIC_START + 5)
++#define IRQ_PB1176_UART4 (IRQ_PB1176_GIC_START + 6) /* UART 4 on baseboard */
++#define IRQ_PB1176_CHARLCD (IRQ_PB1176_GIC_START + 7) /* Character LCD */
++#define IRQ_PB1176_GPIO1 (IRQ_PB1176_GIC_START + 8)
++#define IRQ_PB1176_GPIO2 (IRQ_PB1176_GIC_START + 9)
++#define IRQ_PB1176_ETH (IRQ_PB1176_GIC_START + 10) /* Ethernet controller */
++#define IRQ_PB1176_USB (IRQ_PB1176_GIC_START + 11) /* USB controller */
++
++#define IRQ_PB1176_PISMO (IRQ_PB1176_GIC_START + 16)
++
++#define IRQ_PB1176_AACI (IRQ_PB1176_GIC_START + 19) /* Audio Codec */
++
++#define IRQ_PB1176_TIMER0_1 (IRQ_PB1176_GIC_START + 22)
++#define IRQ_PB1176_TIMER2_3 (IRQ_PB1176_GIC_START + 23)
++#define IRQ_PB1176_DMAC (IRQ_PB1176_GIC_START + 24) /* DMA controller */
++#define IRQ_PB1176_RTC (IRQ_PB1176_GIC_START + 25) /* Real Time Clock */
++
++#define IRQ_PB1176_GPIO0 -1
++#define IRQ_PB1176_SSP -1
++#define IRQ_PB1176_SCTL -1
++
++#define NR_GIC_PB1176 2
++
++/*
++ * Only define NR_IRQS if less than NR_IRQS_PB1176
++ */
++#define NR_IRQS_PB1176 (IRQ_DC1176_GIC_START + 96)
++
++#if defined(CONFIG_MACH_REALVIEW_PB1176)
++
++#if !defined(NR_IRQS) || (NR_IRQS < NR_IRQS_PB1176)
++#undef NR_IRQS
++#define NR_IRQS NR_IRQS_PB1176
++#endif
++
++#if !defined(MAX_GIC_NR) || (MAX_GIC_NR < NR_GIC_PB1176)
++#undef MAX_GIC_NR
++#define MAX_GIC_NR NR_GIC_PB1176
++#endif
++
++#endif /* CONFIG_MACH_REALVIEW_PB1176 */
++
++#endif /* __ASM_ARCH_BOARD_PB1176_H */
+diff --git a/include/asm-arm/arch-realview/board-pb11mp.h b/include/asm-arm/arch-realview/board-pb11mp.h
+new file mode 100644
+index 0000000..a1294d9
+--- /dev/null
++++ b/include/asm-arm/arch-realview/board-pb11mp.h
+@@ -0,0 +1,186 @@
++/*
++ * include/asm-arm/arch-realview/board-pb11mp.h
++ *
++ * Copyright (C) 2008 ARM Limited
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
++ * MA 02110-1301, USA.
++ */
++
++#ifndef __ASM_ARCH_BOARD_PB11MP_H
++#define __ASM_ARCH_BOARD_PB11MP_H
++
++#include <asm/arch/platform.h>
++
++/*
++ * Peripheral addresses
++ */
++#define REALVIEW_PB11MP_UART0_BASE 0x10009000 /* UART 0 */
++#define REALVIEW_PB11MP_UART1_BASE 0x1000A000 /* UART 1 */
++#define REALVIEW_PB11MP_UART2_BASE 0x1000B000 /* UART 2 */
++#define REALVIEW_PB11MP_UART3_BASE 0x1000C000 /* UART 3 */
++#define REALVIEW_PB11MP_SSP_BASE 0x1000D000 /* Synchronous Serial Port */
++#define REALVIEW_PB11MP_WATCHDOG0_BASE 0x1000F000 /* Watchdog 0 */
++#define REALVIEW_PB11MP_WATCHDOG_BASE 0x10010000 /* watchdog interface */
++#define REALVIEW_PB11MP_TIMER0_1_BASE 0x10011000 /* Timer 0 and 1 */
++#define REALVIEW_PB11MP_TIMER2_3_BASE 0x10012000 /* Timer 2 and 3 */
++#define REALVIEW_PB11MP_GPIO0_BASE 0x10013000 /* GPIO port 0 */
++#define REALVIEW_PB11MP_RTC_BASE 0x10017000 /* Real Time Clock */
++#define REALVIEW_PB11MP_TIMER4_5_BASE 0x10018000 /* Timer 4/5 */
++#define REALVIEW_PB11MP_TIMER6_7_BASE 0x10019000 /* Timer 6/7 */
++#define REALVIEW_PB11MP_SCTL_BASE 0x1001A000 /* System Controller */
++#define REALVIEW_PB11MP_CLCD_BASE 0x10020000 /* CLCD */
++#define REALVIEW_PB11MP_ONB_SRAM_BASE 0x10060000 /* On-board SRAM */
++#define REALVIEW_PB11MP_DMC_BASE 0x100E0000 /* DMC configuration */
++#define REALVIEW_PB11MP_SMC_BASE 0x100E1000 /* SMC configuration */
++#define REALVIEW_PB11MP_CAN_BASE 0x100E2000 /* CAN bus */
++#define REALVIEW_PB11MP_CF_BASE 0x18000000 /* Compact flash */
++#define REALVIEW_PB11MP_CF_MEM_BASE 0x18003000 /* SMC for Compact flash */
++#define REALVIEW_PB11MP_GIC_CPU_BASE 0x1E000000 /* Generic interrupt controller CPU interface */
++#define REALVIEW_PB11MP_FLASH0_BASE 0x40000000
++#define REALVIEW_PB11MP_FLASH0_SIZE SZ_64M
++#define REALVIEW_PB11MP_FLASH1_BASE 0x44000000
++#define REALVIEW_PB11MP_FLASH1_SIZE SZ_64M
++#define REALVIEW_PB11MP_ETH_BASE 0x4E000000 /* Ethernet */
++#define REALVIEW_PB11MP_USB_BASE 0x4F000000 /* USB */
++#define REALVIEW_PB11MP_GIC_DIST_BASE 0x1E001000 /* Generic interrupt controller distributor */
++#define REALVIEW_PB11MP_LT_BASE 0xC0000000 /* Logic Tile expansion */
++#define REALVIEW_PB11MP_SDRAM6_BASE 0x70000000 /* SDRAM bank 6 256MB */
++#define REALVIEW_PB11MP_SDRAM7_BASE 0x80000000 /* SDRAM bank 7 256MB */
++
++#define REALVIEW_PB11MP_SYS_PLD_CTRL1 0x74
++
++/*
++ * PB11MPCore PCI regions
++ */
++#define REALVIEW_PB11MP_PCI_BASE 0x90040000 /* PCI-X Unit base */
++#define REALVIEW_PB11MP_PCI_IO_BASE 0x90050000 /* IO Region on AHB */
++#define REALVIEW_PB11MP_PCI_MEM_BASE 0xA0000000 /* MEM Region on AHB */
++
++#define REALVIEW_PB11MP_PCI_BASE_SIZE 0x10000 /* 16 Kb */
++#define REALVIEW_PB11MP_PCI_IO_SIZE 0x1000 /* 4 Kb */
++#define REALVIEW_PB11MP_PCI_MEM_SIZE 0x20000000 /* 512 MB */
++
++/*
++ * Testchip peripheral and fpga gic regions
++ */
++#define REALVIEW_TC11MP_SCU_BASE 0x1F000000 /* IRQ, Test chip */
++#define REALVIEW_TC11MP_GIC_CPU_BASE 0x1F000100 /* Test chip interrupt controller CPU interface */
++#define REALVIEW_TC11MP_TWD_BASE 0x1F000700
++#define REALVIEW_TC11MP_TWD_SIZE 0x00000100
++#define REALVIEW_TC11MP_GIC_DIST_BASE 0x1F001000 /* Test chip interrupt controller distributor */
++#define REALVIEW_TC11MP_L220_BASE 0x1F002000 /* L220 registers */
++
++/*
++ * Irqs
++ */
++#define IRQ_TC11MP_GIC_START 32
++#define IRQ_PB11MP_GIC_START 64
++
++/*
++ * ARM11MPCore test chip interrupt sources (primary GIC on the test chip)
++ */
++#define IRQ_TC11MP_AACI (IRQ_TC11MP_GIC_START + 0)
++#define IRQ_TC11MP_TIMER0_1 (IRQ_TC11MP_GIC_START + 1)
++#define IRQ_TC11MP_TIMER2_3 (IRQ_TC11MP_GIC_START + 2)
++#define IRQ_TC11MP_USB (IRQ_TC11MP_GIC_START + 3)
++#define IRQ_TC11MP_UART0 (IRQ_TC11MP_GIC_START + 4)
++#define IRQ_TC11MP_UART1 (IRQ_TC11MP_GIC_START + 5)
++#define IRQ_TC11MP_RTC (IRQ_TC11MP_GIC_START + 6)
++#define IRQ_TC11MP_KMI0 (IRQ_TC11MP_GIC_START + 7)
++#define IRQ_TC11MP_KMI1 (IRQ_TC11MP_GIC_START + 8)
++#define IRQ_TC11MP_ETH (IRQ_TC11MP_GIC_START + 9)
++#define IRQ_TC11MP_PB_IRQ1 (IRQ_TC11MP_GIC_START + 10) /* main GIC */
++#define IRQ_TC11MP_PB_IRQ2 (IRQ_TC11MP_GIC_START + 11) /* tile GIC */
++#define IRQ_TC11MP_PB_FIQ1 (IRQ_TC11MP_GIC_START + 12) /* main GIC */
++#define IRQ_TC11MP_PB_FIQ2 (IRQ_TC11MP_GIC_START + 13) /* tile GIC */
++#define IRQ_TC11MP_MMCI0A (IRQ_TC11MP_GIC_START + 14)
++#define IRQ_TC11MP_MMCI0B (IRQ_TC11MP_GIC_START + 15)
++
++#define IRQ_TC11MP_PMU_CPU0 (IRQ_TC11MP_GIC_START + 17)
++#define IRQ_TC11MP_PMU_CPU1 (IRQ_TC11MP_GIC_START + 18)
++#define IRQ_TC11MP_PMU_CPU2 (IRQ_TC11MP_GIC_START + 19)
++#define IRQ_TC11MP_PMU_CPU3 (IRQ_TC11MP_GIC_START + 20)
++#define IRQ_TC11MP_PMU_SCU0 (IRQ_TC11MP_GIC_START + 21)
++#define IRQ_TC11MP_PMU_SCU1 (IRQ_TC11MP_GIC_START + 22)
++#define IRQ_TC11MP_PMU_SCU2 (IRQ_TC11MP_GIC_START + 23)
++#define IRQ_TC11MP_PMU_SCU3 (IRQ_TC11MP_GIC_START + 24)
++#define IRQ_TC11MP_PMU_SCU4 (IRQ_TC11MP_GIC_START + 25)
++#define IRQ_TC11MP_PMU_SCU5 (IRQ_TC11MP_GIC_START + 26)
++#define IRQ_TC11MP_PMU_SCU6 (IRQ_TC11MP_GIC_START + 27)
++#define IRQ_TC11MP_PMU_SCU7 (IRQ_TC11MP_GIC_START + 28)
++
++#define IRQ_TC11MP_L220_EVENT (IRQ_TC11MP_GIC_START + 29)
++#define IRQ_TC11MP_L220_SLAVE (IRQ_TC11MP_GIC_START + 30)
++#define IRQ_TC11MP_L220_DECODE (IRQ_TC11MP_GIC_START + 31)
++
++/*
++ * RealView PB11MPCore GIC interrupt sources (secondary GIC on the board)
++ */
++#define IRQ_PB11MP_WATCHDOG (IRQ_PB11MP_GIC_START + 0) /* Watchdog timer */
++#define IRQ_PB11MP_SOFT (IRQ_PB11MP_GIC_START + 1) /* Software interrupt */
++#define IRQ_PB11MP_COMMRx (IRQ_PB11MP_GIC_START + 2) /* Debug Comm Rx interrupt */
++#define IRQ_PB11MP_COMMTx (IRQ_PB11MP_GIC_START + 3) /* Debug Comm Tx interrupt */
++#define IRQ_PB11MP_GPIO0 (IRQ_PB11MP_GIC_START + 6) /* GPIO 0 */
++#define IRQ_PB11MP_GPIO1 (IRQ_PB11MP_GIC_START + 7) /* GPIO 1 */
++#define IRQ_PB11MP_GPIO2 (IRQ_PB11MP_GIC_START + 8) /* GPIO 2 */
++ /* 9 reserved */
++#define IRQ_PB11MP_RTC_GIC1 (IRQ_PB11MP_GIC_START + 10) /* Real Time Clock */
++#define IRQ_PB11MP_SSP (IRQ_PB11MP_GIC_START + 11) /* Synchronous Serial Port */
++#define IRQ_PB11MP_UART0_GIC1 (IRQ_PB11MP_GIC_START + 12) /* UART 0 on development chip */
++#define IRQ_PB11MP_UART1_GIC1 (IRQ_PB11MP_GIC_START + 13) /* UART 1 on development chip */
++#define IRQ_PB11MP_UART2 (IRQ_PB11MP_GIC_START + 14) /* UART 2 on development chip */
++#define IRQ_PB11MP_UART3 (IRQ_PB11MP_GIC_START + 15) /* UART 3 on development chip */
++#define IRQ_PB11MP_SCI (IRQ_PB11MP_GIC_START + 16) /* Smart Card Interface */
++#define IRQ_PB11MP_MMCI0A_GIC1 (IRQ_PB11MP_GIC_START + 17) /* Multimedia Card 0A */
++#define IRQ_PB11MP_MMCI0B_GIC1 (IRQ_PB11MP_GIC_START + 18) /* Multimedia Card 0B */
++#define IRQ_PB11MP_AACI_GIC1 (IRQ_PB11MP_GIC_START + 19) /* Audio Codec */
++#define IRQ_PB11MP_KMI0_GIC1 (IRQ_PB11MP_GIC_START + 20) /* Keyboard/Mouse port 0 */
++#define IRQ_PB11MP_KMI1_GIC1 (IRQ_PB11MP_GIC_START + 21) /* Keyboard/Mouse port 1 */
++#define IRQ_PB11MP_CHARLCD (IRQ_PB11MP_GIC_START + 22) /* Character LCD */
++#define IRQ_PB11MP_CLCD (IRQ_PB11MP_GIC_START + 23) /* CLCD controller */
++#define IRQ_PB11MP_DMAC (IRQ_PB11MP_GIC_START + 24) /* DMA controller */
++#define IRQ_PB11MP_PWRFAIL (IRQ_PB11MP_GIC_START + 25) /* Power failure */
++#define IRQ_PB11MP_PISMO (IRQ_PB11MP_GIC_START + 26) /* PISMO interface */
++#define IRQ_PB11MP_DoC (IRQ_PB11MP_GIC_START + 27) /* Disk on Chip memory controller */
++#define IRQ_PB11MP_ETH_GIC1 (IRQ_PB11MP_GIC_START + 28) /* Ethernet controller */
++#define IRQ_PB11MP_USB_GIC1 (IRQ_PB11MP_GIC_START + 29) /* USB controller */
++#define IRQ_PB11MP_TSPEN (IRQ_PB11MP_GIC_START + 30) /* Touchscreen pen */
++#define IRQ_PB11MP_TSKPAD (IRQ_PB11MP_GIC_START + 31) /* Touchscreen keypad */
++
++#define IRQ_PB11MP_SMC -1
++#define IRQ_PB11MP_SCTL -1
++
++#define NR_GIC_PB11MP 2
++
++/*
++ * Only define NR_IRQS if less than NR_IRQS_PB11MP
++ */
++#define NR_IRQS_PB11MP (IRQ_TC11MP_GIC_START + 96)
++
++#if defined(CONFIG_MACH_REALVIEW_PB11MP)
++
++#if !defined(NR_IRQS) || (NR_IRQS < NR_IRQS_PB11MP)
++#undef NR_IRQS
++#define NR_IRQS NR_IRQS_PB11MP
++#endif
++
++#if !defined(MAX_GIC_NR) || (MAX_GIC_NR < NR_GIC_PB11MP)
++#undef MAX_GIC_NR
++#define MAX_GIC_NR NR_GIC_PB11MP
++#endif
++
++#endif /* CONFIG_MACH_REALVIEW_PB11MP */
++
++#endif /* __ASM_ARCH_BOARD_PB11MP_H */
+diff --git a/include/asm-arm/arch-realview/debug-macro.S b/include/asm-arm/arch-realview/debug-macro.S
+index f17efc6..c8c860c 100644
+--- a/include/asm-arm/arch-realview/debug-macro.S
++++ b/include/asm-arm/arch-realview/debug-macro.S
+@@ -15,7 +15,7 @@
+ mrc p15, 0, \rx, c1, c0
+ tst \rx, #1 @ MMU enabled?
+ moveq \rx, #0x10000000
+- movne \rx, #0xf1000000 @ virtual base
++ movne \rx, #0xf0000000 @ virtual base
+ orr \rx, \rx, #0x00009000
+ .endm
+
+diff --git a/include/asm-arm/arch-realview/hardware.h b/include/asm-arm/arch-realview/hardware.h
+index bad8d7c..1ee8313 100644
+--- a/include/asm-arm/arch-realview/hardware.h
++++ b/include/asm-arm/arch-realview/hardware.h
+@@ -25,7 +25,7 @@
+ #include <asm/sizes.h>
+
+ /* macro to get at IO space when running virtually */
+-#define IO_ADDRESS(x) ((((x) & 0x0effffff) | (((x) >> 4) & 0x0f000000)) + 0xf0000000)
++#define IO_ADDRESS(x) (((x) & 0x0fffffff) + 0xf0000000)
+ #define __io_address(n) __io(IO_ADDRESS(n))
+
+ #endif
+diff --git a/include/asm-arm/arch-realview/irqs.h b/include/asm-arm/arch-realview/irqs.h
+index ad0c911..ccbac59 100644
+--- a/include/asm-arm/arch-realview/irqs.h
++++ b/include/asm-arm/arch-realview/irqs.h
+@@ -23,6 +23,8 @@
+ #define __ASM_ARCH_IRQS_H
+
+ #include <asm/arch/board-eb.h>
++#include <asm/arch/board-pb11mp.h>
++#include <asm/arch/board-pb1176.h>
+
+ #define IRQ_LOCALTIMER 29
+ #define IRQ_LOCALWDOG 30
+diff --git a/include/asm-arm/arch-realview/platform.h b/include/asm-arm/arch-realview/platform.h
+index 4fd351b..424c0aa 100644
+--- a/include/asm-arm/arch-realview/platform.h
++++ b/include/asm-arm/arch-realview/platform.h
+@@ -32,9 +32,6 @@
+ #define REALVIEW_SSRAM_BASE /* REALVIEW_SSMC_BASE ? */
+ #define REALVIEW_SSRAM_SIZE SZ_2M
+
+-#define REALVIEW_FLASH_BASE 0x40000000
+-#define REALVIEW_FLASH_SIZE SZ_64M
+-
+ /*
+ * SDRAM
+ */
+@@ -175,42 +172,20 @@
+ #define REALVIEW_INTREG_CARDINSERT 0x03 /* Signal insertion of MMC card */
+
+ /*
+- * REALVIEW peripheral addresses
++ * RealView common peripheral addresses
+ */
+ #define REALVIEW_SCTL_BASE 0x10001000 /* System controller */
+ #define REALVIEW_I2C_BASE 0x10002000 /* I2C control */
+- /* Reserved 0x10003000 */
+ #define REALVIEW_AACI_BASE 0x10004000 /* Audio */
+ #define REALVIEW_MMCI0_BASE 0x10005000 /* MMC interface */
+ #define REALVIEW_KMI0_BASE 0x10006000 /* KMI interface */
+ #define REALVIEW_KMI1_BASE 0x10007000 /* KMI 2nd interface */
+ #define REALVIEW_CHAR_LCD_BASE 0x10008000 /* Character LCD */
+-#define REALVIEW_UART0_BASE 0x10009000 /* UART 0 */
+-#define REALVIEW_UART1_BASE 0x1000A000 /* UART 1 */
+-#define REALVIEW_UART2_BASE 0x1000B000 /* UART 2 */
+-#define REALVIEW_UART3_BASE 0x1000C000 /* UART 3 */
+-#define REALVIEW_SSP_BASE 0x1000D000 /* Synchronous Serial Port */
+ #define REALVIEW_SCI_BASE 0x1000E000 /* Smart card controller */
+- /* Reserved 0x1000F000 */
+-#define REALVIEW_WATCHDOG_BASE 0x10010000 /* watchdog interface */
+-#define REALVIEW_TIMER0_1_BASE 0x10011000 /* Timer 0 and 1 */
+-#define REALVIEW_TIMER2_3_BASE 0x10012000 /* Timer 2 and 3 */
+-#define REALVIEW_GPIO0_BASE 0x10013000 /* GPIO port 0 */
+ #define REALVIEW_GPIO1_BASE 0x10014000 /* GPIO port 1 */
+ #define REALVIEW_GPIO2_BASE 0x10015000 /* GPIO port 2 */
+- /* Reserved 0x10016000 */
+-#define REALVIEW_RTC_BASE 0x10017000 /* Real Time Clock */
+ #define REALVIEW_DMC_BASE 0x10018000 /* DMC configuration */
+-#define REALVIEW_PCI_CORE_BASE 0x10019000 /* PCI configuration */
+- /* Reserved 0x1001A000 - 0x1001FFFF */
+-#define REALVIEW_CLCD_BASE 0x10020000 /* CLCD */
+ #define REALVIEW_DMAC_BASE 0x10030000 /* DMA controller */
+-#define REALVIEW_GIC_CPU_BASE 0x10040000 /* Generic interrupt controller CPU interface */
+-#define REALVIEW_GIC_DIST_BASE 0x10041000 /* Generic interrupt controller distributor */
+-#define REALVIEW_SMC_BASE 0x10080000 /* SMC */
+- /* Reserved 0x10090000 - 0x100EFFFF */
+-
+-#define REALVIEW_ETH_BASE 0x4E000000 /* Ethernet */
+
+ /* PCI space */
+ #define REALVIEW_PCI_BASE 0x41000000 /* PCI Interface */
+diff --git a/include/asm-arm/arch-realview/scu.h b/include/asm-arm/arch-realview/scu.h
+index 08b3db8..d55802d 100644
+--- a/include/asm-arm/arch-realview/scu.h
++++ b/include/asm-arm/arch-realview/scu.h
+@@ -1,8 +1,13 @@
+ #ifndef __ASMARM_ARCH_SCU_H
+ #define __ASMARM_ARCH_SCU_H
+
+-#include <asm/arch/board-eb.h>
+-
+-#define SCU_BASE REALVIEW_EB11MP_SCU_BASE
++/*
++ * SCU registers
++ */
++#define SCU_CTRL 0x00
++#define SCU_CONFIG 0x04
++#define SCU_CPU_STATUS 0x08
++#define SCU_INVALIDATE 0x0c
++#define SCU_FPGA_REVISION 0x10
+
+ #endif
+diff --git a/include/asm-arm/arch-realview/uncompress.h b/include/asm-arm/arch-realview/uncompress.h
+index 3d5c2db..4c905d7 100644
+--- a/include/asm-arm/arch-realview/uncompress.h
++++ b/include/asm-arm/arch-realview/uncompress.h
+@@ -18,28 +18,50 @@
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+ #include <asm/hardware.h>
++#include <asm/mach-types.h>
+
+-#include <asm/arch/platform.h>
++#include <asm/arch/board-eb.h>
++#include <asm/arch/board-pb11mp.h>
++#include <asm/arch/board-pb1176.h>
+
+-#define AMBA_UART_DR (*(volatile unsigned char *) (REALVIEW_UART0_BASE + 0x00))
+-#define AMBA_UART_LCRH (*(volatile unsigned char *) (REALVIEW_UART0_BASE + 0x2c))
+-#define AMBA_UART_CR (*(volatile unsigned char *) (REALVIEW_UART0_BASE + 0x30))
+-#define AMBA_UART_FR (*(volatile unsigned char *) (REALVIEW_UART0_BASE + 0x18))
++#define AMBA_UART_DR(base) (*(volatile unsigned char *)((base) + 0x00))
++#define AMBA_UART_LCRH(base) (*(volatile unsigned char *)((base) + 0x2c))
++#define AMBA_UART_CR(base) (*(volatile unsigned char *)((base) + 0x30))
++#define AMBA_UART_FR(base) (*(volatile unsigned char *)((base) + 0x18))
++
++/*
++ * Return the UART base address
++ */
++static inline unsigned long get_uart_base(void)
++{
++ if (machine_is_realview_eb())
++ return REALVIEW_EB_UART0_BASE;
++ else if (machine_is_realview_pb11mp())
++ return REALVIEW_PB11MP_UART0_BASE;
++ else if (machine_is_realview_pb1176())
++ return REALVIEW_PB1176_UART0_BASE;
++ else
++ return 0;
++}
+
+ /*
+ * This does not append a newline
+ */
+ static inline void putc(int c)
+ {
+- while (AMBA_UART_FR & (1 << 5))
++ unsigned long base = get_uart_base();
++
++ while (AMBA_UART_FR(base) & (1 << 5))
+ barrier();
+
+- AMBA_UART_DR = c;
++ AMBA_UART_DR(base) = c;
+ }
+
+ static inline void flush(void)
+ {
+- while (AMBA_UART_FR & (1 << 3))
++ unsigned long base = get_uart_base();
++
++ while (AMBA_UART_FR(base) & (1 << 3))
+ barrier();
+ }
+
+diff --git a/include/asm-arm/arch-s3c2410/regs-clock.h b/include/asm-arm/arch-s3c2410/regs-clock.h
+index dba9df9..ecae9e7 100644
+--- a/include/asm-arm/arch-s3c2410/regs-clock.h
++++ b/include/asm-arm/arch-s3c2410/regs-clock.h
+@@ -137,7 +137,7 @@ s3c2410_get_pll(unsigned int pllval, unsigned int baseclk)
+
+ #define S3C2412_CLKDIVN_PDIVN (1<<2)
+ #define S3C2412_CLKDIVN_HDIVN_MASK (3<<0)
+-#define S3C2421_CLKDIVN_ARMDIVN (1<<3)
++#define S3C2412_CLKDIVN_ARMDIVN (1<<3)
+ #define S3C2412_CLKDIVN_DVSEN (1<<4)
+ #define S3C2412_CLKDIVN_HALFHCLK (1<<5)
+ #define S3C2412_CLKDIVN_USB48DIV (1<<6)
+diff --git a/include/asm-arm/arch-s3c2410/regs-gpio.h b/include/asm-arm/arch-s3c2410/regs-gpio.h
+index 0ad75d7..497dd06 100644
+--- a/include/asm-arm/arch-s3c2410/regs-gpio.h
++++ b/include/asm-arm/arch-s3c2410/regs-gpio.h
+@@ -529,11 +529,13 @@
+ #define S3C2410_GPD14_INP (0x00 << 28)
+ #define S3C2410_GPD14_OUTP (0x01 << 28)
+ #define S3C2410_GPD14_VD22 (0x02 << 28)
++#define S3C2410_GPD14_nSS1 (0x03 << 28)
+
+ #define S3C2410_GPD15 S3C2410_GPIONO(S3C2410_GPIO_BANKD, 15)
+ #define S3C2410_GPD15_INP (0x00 << 30)
+ #define S3C2410_GPD15_OUTP (0x01 << 30)
+ #define S3C2410_GPD15_VD23 (0x02 << 30)
++#define S3C2410_GPD15_nSS0 (0x03 << 30)
+
+ #define S3C2410_GPD_PUPDIS(x) (1<<(x))
+
+@@ -801,12 +803,14 @@
+ #define S3C2410_GPG2_INP (0x00 << 4)
+ #define S3C2410_GPG2_OUTP (0x01 << 4)
+ #define S3C2410_GPG2_EINT10 (0x02 << 4)
++#define S3C2410_GPG2_nSS0 (0x03 << 4)
+ #define S3C2400_GPG2_CDCLK (0x02 << 4)
+
+ #define S3C2410_GPG3 S3C2410_GPIONO(S3C2410_GPIO_BANKG, 3)
+ #define S3C2410_GPG3_INP (0x00 << 6)
+ #define S3C2410_GPG3_OUTP (0x01 << 6)
+ #define S3C2410_GPG3_EINT11 (0x02 << 6)
++#define S3C2410_GPG3_nSS1 (0x03 << 6)
+ #define S3C2400_GPG3_I2SSDO (0x02 << 6)
+ #define S3C2400_GPG3_I2SSDI (0x03 << 6)
+
+diff --git a/include/asm-arm/arch-s3c2410/regs-s3c2412-mem.h b/include/asm-arm/arch-s3c2410/regs-s3c2412-mem.h
+new file mode 100644
+index 0000000..c8c793e
+--- /dev/null
++++ b/include/asm-arm/arch-s3c2410/regs-s3c2412-mem.h
+@@ -0,0 +1,29 @@
++/* linux/include/asm-arm/arch-s3c2410/regs-s3c2412-mem.h
++ *
++ * Copyright (c) 2008 Simtec Electronics
++ * Ben Dooks <ben at simtec.co.uk>
++ * http://armlinux.simtec.co.uk/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * S3C2412 memory register definitions
++*/
++
++#ifndef __ASM_ARM_REGS_S3C2412_MEM
++#define __ASM_ARM_REGS_S3C2412_MEM
++
++#ifndef S3C2412_MEMREG
++#define S3C2412_MEMREG(x) (S3C24XX_VA_MEMCTRL + (x))
++#endif
++
++#define S3C2412_BANKCFG S3C2412_MEMREG(0x00)
++#define S3C2412_BANKCON1 S3C2412_MEMREG(0x04)
++#define S3C2412_BANKCON2 S3C2412_MEMREG(0x08)
++#define S3C2412_BANKCON3 S3C2412_MEMREG(0x0C)
++
++#define S3C2412_REFRESH S3C2412_MEMREG(0x10)
++#define S3C2412_TIMEOUT S3C2412_MEMREG(0x14)
++
++#endif /* __ASM_ARM_REGS_S3C2412_MEM */
+diff --git a/include/asm-arm/arch-s3c2410/system-reset.h b/include/asm-arm/arch-s3c2410/system-reset.h
+new file mode 100644
+index 0000000..1615bce
+--- /dev/null
++++ b/include/asm-arm/arch-s3c2410/system-reset.h
+@@ -0,0 +1,64 @@
++/* linux/include/asm-arm/arch-s3c2410/system-reset.h
++ *
++ * Copyright (c) 2008 Simtec Electronics
++ * Ben Dooks <ben at simtec.co.uk>
++ *
++ * S3C2410 - System define for arch_reset() function
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++*/
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++
++#include <asm/plat-s3c/regs-watchdog.h>
++#include <asm/arch/regs-clock.h>
++
++#include <linux/clk.h>
++#include <linux/err.h>
++
++extern void (*s3c24xx_reset_hook)(void);
++
++static void
++arch_reset(char mode)
++{
++ struct clk *wdtclk;
++
++ if (mode == 's') {
++ cpu_reset(0);
++ }
++
++ if (s3c24xx_reset_hook)
++ s3c24xx_reset_hook();
++
++ printk("arch_reset: attempting watchdog reset\n");
++
++ __raw_writel(0, S3C2410_WTCON); /* disable watchdog, to be safe */
++
++ wdtclk = clk_get(NULL, "watchdog");
++ if (!IS_ERR(wdtclk)) {
++ clk_enable(wdtclk);
++ } else
++ printk(KERN_WARNING "%s: warning: cannot get watchdog clock\n", __func__);
++
++ /* put initial values into count and data */
++ __raw_writel(0x80, S3C2410_WTCNT);
++ __raw_writel(0x80, S3C2410_WTDAT);
++
++ /* set the watchdog to go and reset... */
++ __raw_writel(S3C2410_WTCON_ENABLE|S3C2410_WTCON_DIV16|S3C2410_WTCON_RSTEN |
++ S3C2410_WTCON_PRESCALE(0x20), S3C2410_WTCON);
++
++ /* wait for reset to assert... */
++ mdelay(500);
++
++ printk(KERN_ERR "Watchdog reset failed to assert reset\n");
++
++ /* delay to allow the serial port to show the message */
++ mdelay(50);
++
++ /* we'll take a jump through zero as a poor second */
++ cpu_reset(0);
++}
+diff --git a/include/asm-arm/arch-s3c2410/system.h b/include/asm-arm/arch-s3c2410/system.h
+index 14de4e5..ad25808 100644
+--- a/include/asm-arm/arch-s3c2410/system.h
++++ b/include/asm-arm/arch-s3c2410/system.h
+@@ -17,12 +17,8 @@
+ #include <asm/arch/idle.h>
+ #include <asm/arch/reset.h>
+
+-#include <asm/plat-s3c/regs-watchdog.h>
+ #include <asm/arch/regs-clock.h>
+
+-#include <linux/clk.h>
+-#include <linux/err.h>
+-
+ void (*s3c24xx_idle)(void);
+ void (*s3c24xx_reset_hook)(void);
+
+@@ -59,44 +55,4 @@ static void arch_idle(void)
+ s3c24xx_default_idle();
+ }
+
+-static void
+-arch_reset(char mode)
+-{
+- struct clk *wdtclk;
+-
+- if (mode == 's') {
+- cpu_reset(0);
+- }
+-
+- if (s3c24xx_reset_hook)
+- s3c24xx_reset_hook();
+-
+- printk("arch_reset: attempting watchdog reset\n");
+-
+- __raw_writel(0, S3C2410_WTCON); /* disable watchdog, to be safe */
+-
+- wdtclk = clk_get(NULL, "watchdog");
+- if (!IS_ERR(wdtclk)) {
+- clk_enable(wdtclk);
+- } else
+- printk(KERN_WARNING "%s: warning: cannot get watchdog clock\n", __func__);
+-
+- /* put initial values into count and data */
+- __raw_writel(0x80, S3C2410_WTCNT);
+- __raw_writel(0x80, S3C2410_WTDAT);
+-
+- /* set the watchdog to go and reset... */
+- __raw_writel(S3C2410_WTCON_ENABLE|S3C2410_WTCON_DIV16|S3C2410_WTCON_RSTEN |
+- S3C2410_WTCON_PRESCALE(0x20), S3C2410_WTCON);
+-
+- /* wait for reset to assert... */
+- mdelay(500);
+-
+- printk(KERN_ERR "Watchdog reset failed to assert reset\n");
+-
+- /* delay to allow the serial port to show the message */
+- mdelay(50);
+-
+- /* we'll take a jump through zero as a poor second */
+- cpu_reset(0);
+-}
++#include <asm/arch/system-reset.h>
+diff --git a/include/asm-arm/arch-sa1100/gpio.h b/include/asm-arm/arch-sa1100/gpio.h
+index e7a9d26..93d3395 100644
+--- a/include/asm-arm/arch-sa1100/gpio.h
++++ b/include/asm-arm/arch-sa1100/gpio.h
+@@ -26,35 +26,28 @@
+
+ #include <asm/hardware.h>
+ #include <asm/irq.h>
+-
+-static inline int gpio_request(unsigned gpio, const char *label)
+-{
+- return 0;
+-}
+-
+-static inline void gpio_free(unsigned gpio)
+-{
+- return;
+-}
+-
+-extern int gpio_direction_input(unsigned gpio);
+-extern int gpio_direction_output(unsigned gpio, int value);
+-
++#include <asm-generic/gpio.h>
+
+ static inline int gpio_get_value(unsigned gpio)
+ {
+- return GPLR & GPIO_GPIO(gpio);
++ if (__builtin_constant_p(gpio) && (gpio <= GPIO_MAX))
++ return GPLR & GPIO_GPIO(gpio);
++ else
++ return __gpio_get_value(gpio);
+ }
+
+ static inline void gpio_set_value(unsigned gpio, int value)
+ {
+- if (value)
+- GPSR = GPIO_GPIO(gpio);
++ if (__builtin_constant_p(gpio) && (gpio <= GPIO_MAX))
++ if (value)
++ GPSR = GPIO_GPIO(gpio);
++ else
++ GPCR = GPIO_GPIO(gpio);
+ else
+- GPCR = GPIO_GPIO(gpio);
++ __gpio_set_value(gpio, value);
+ }
+
+-#include <asm-generic/gpio.h> /* cansleep wrappers */
++#define gpio_cansleep __gpio_cansleep
+
+ static inline unsigned gpio_to_irq(unsigned gpio)
+ {
+diff --git a/include/asm-arm/cpu-multi32.h b/include/asm-arm/cpu-multi32.h
+index 715e18a..3479de9 100644
+--- a/include/asm-arm/cpu-multi32.h
++++ b/include/asm-arm/cpu-multi32.h
+@@ -21,6 +21,10 @@ extern struct processor {
+ */
+ void (*_data_abort)(unsigned long pc);
+ /*
++ * Retrieve prefetch fault address
++ */
++ unsigned long (*_prefetch_abort)(unsigned long lr);
++ /*
+ * Set up any processor specifics
+ */
+ void (*_proc_init)(void);
+diff --git a/include/asm-arm/glue.h b/include/asm-arm/glue.h
+index 22274ce..a97a182 100644
+--- a/include/asm-arm/glue.h
++++ b/include/asm-arm/glue.h
+@@ -40,83 +40,110 @@
+ * v6_early - ARMv6 generic early abort handler
+ * v7_early - ARMv7 generic early abort handler
+ */
+-#undef CPU_ABORT_HANDLER
+-#undef MULTI_ABORT
++#undef CPU_DABORT_HANDLER
++#undef MULTI_DABORT
+
+ #if defined(CONFIG_CPU_ARM610)
+-# ifdef CPU_ABORT_HANDLER
+-# define MULTI_ABORT 1
++# ifdef CPU_DABORT_HANDLER
++# define MULTI_DABORT 1
+ # else
+-# define CPU_ABORT_HANDLER cpu_arm6_data_abort
++# define CPU_DABORT_HANDLER cpu_arm6_data_abort
+ # endif
+ #endif
+
+ #if defined(CONFIG_CPU_ARM710)
+-# ifdef CPU_ABORT_HANDLER
+-# define MULTI_ABORT 1
++# ifdef CPU_DABORT_HANDLER
++# define MULTI_DABORT 1
+ # else
+-# define CPU_ABORT_HANDLER cpu_arm7_data_abort
++# define CPU_DABORT_HANDLER cpu_arm7_data_abort
+ # endif
+ #endif
+
+ #ifdef CONFIG_CPU_ABRT_LV4T
+-# ifdef CPU_ABORT_HANDLER
+-# define MULTI_ABORT 1
++# ifdef CPU_DABORT_HANDLER
++# define MULTI_DABORT 1
+ # else
+-# define CPU_ABORT_HANDLER v4t_late_abort
++# define CPU_DABORT_HANDLER v4t_late_abort
+ # endif
+ #endif
+
+ #ifdef CONFIG_CPU_ABRT_EV4
+-# ifdef CPU_ABORT_HANDLER
+-# define MULTI_ABORT 1
++# ifdef CPU_DABORT_HANDLER
++# define MULTI_DABORT 1
+ # else
+-# define CPU_ABORT_HANDLER v4_early_abort
++# define CPU_DABORT_HANDLER v4_early_abort
+ # endif
+ #endif
+
+ #ifdef CONFIG_CPU_ABRT_EV4T
+-# ifdef CPU_ABORT_HANDLER
+-# define MULTI_ABORT 1
++# ifdef CPU_DABORT_HANDLER
++# define MULTI_DABORT 1
+ # else
+-# define CPU_ABORT_HANDLER v4t_early_abort
++# define CPU_DABORT_HANDLER v4t_early_abort
+ # endif
+ #endif
+
+ #ifdef CONFIG_CPU_ABRT_EV5TJ
+-# ifdef CPU_ABORT_HANDLER
+-# define MULTI_ABORT 1
++# ifdef CPU_DABORT_HANDLER
++# define MULTI_DABORT 1
+ # else
+-# define CPU_ABORT_HANDLER v5tj_early_abort
++# define CPU_DABORT_HANDLER v5tj_early_abort
+ # endif
+ #endif
+
+ #ifdef CONFIG_CPU_ABRT_EV5T
+-# ifdef CPU_ABORT_HANDLER
+-# define MULTI_ABORT 1
++# ifdef CPU_DABORT_HANDLER
++# define MULTI_DABORT 1
+ # else
+-# define CPU_ABORT_HANDLER v5t_early_abort
++# define CPU_DABORT_HANDLER v5t_early_abort
+ # endif
+ #endif
+
+ #ifdef CONFIG_CPU_ABRT_EV6
+-# ifdef CPU_ABORT_HANDLER
+-# define MULTI_ABORT 1
++# ifdef CPU_DABORT_HANDLER
++# define MULTI_DABORT 1
+ # else
+-# define CPU_ABORT_HANDLER v6_early_abort
++# define CPU_DABORT_HANDLER v6_early_abort
+ # endif
+ #endif
+
+ #ifdef CONFIG_CPU_ABRT_EV7
+-# ifdef CPU_ABORT_HANDLER
+-# define MULTI_ABORT 1
++# ifdef CPU_DABORT_HANDLER
++# define MULTI_DABORT 1
+ # else
+-# define CPU_ABORT_HANDLER v7_early_abort
++# define CPU_DABORT_HANDLER v7_early_abort
+ # endif
+ #endif
+
+-#ifndef CPU_ABORT_HANDLER
++#ifndef CPU_DABORT_HANDLER
+ #error Unknown data abort handler type
+ #endif
+
++/*
++ * Prefetch abort handler. If the CPU has an IFAR use that, otherwise
++ * use the address of the aborted instruction
++ */
++#undef CPU_PABORT_HANDLER
++#undef MULTI_PABORT
++
++#ifdef CONFIG_CPU_PABRT_IFAR
++# ifdef CPU_PABORT_HANDLER
++# define MULTI_PABORT 1
++# else
++# define CPU_PABORT_HANDLER(reg, insn) mrc p15, 0, reg, cr6, cr0, 2
++# endif
++#endif
++
++#ifdef CONFIG_CPU_PABRT_NOIFAR
++# ifdef CPU_PABORT_HANDLER
++# define MULTI_PABORT 1
++# else
++# define CPU_PABORT_HANDLER(reg, insn) mov reg, insn
++# endif
++#endif
++
++#ifndef CPU_PABORT_HANDLER
++#error Unknown prefetch abort handler type
++#endif
++
+ #endif
+diff --git a/include/asm-arm/hardware/arm_scu.h b/include/asm-arm/hardware/arm_scu.h
+deleted file mode 100644
+index 7d28eb5..0000000
+--- a/include/asm-arm/hardware/arm_scu.h
++++ /dev/null
+@@ -1,15 +0,0 @@
+-#ifndef ASMARM_HARDWARE_ARM_SCU_H
+-#define ASMARM_HARDWARE_ARM_SCU_H
+-
+-#include <asm/arch/scu.h>
+-
+-/*
+- * SCU registers
+- */
+-#define SCU_CTRL 0x00
+-#define SCU_CONFIG 0x04
+-#define SCU_CPU_STATUS 0x08
+-#define SCU_INVALIDATE 0x0c
+-#define SCU_FPGA_REVISION 0x10
+-
+-#endif
+diff --git a/include/asm-arm/hardware/iop3xx-adma.h b/include/asm-arm/hardware/iop3xx-adma.h
+index 5c529e6..a32b86a 100644
+--- a/include/asm-arm/hardware/iop3xx-adma.h
++++ b/include/asm-arm/hardware/iop3xx-adma.h
+@@ -260,7 +260,7 @@ static inline int iop_chan_memset_slot_count(size_t len, int *slots_per_op)
+ static inline int iop3xx_aau_xor_slot_count(size_t len, int src_cnt,
+ int *slots_per_op)
+ {
+- const static int slot_count_table[] = { 0,
++ static const int slot_count_table[] = { 0,
+ 1, 1, 1, 1, /* 01 - 04 */
+ 2, 2, 2, 2, /* 05 - 08 */
+ 4, 4, 4, 4, /* 09 - 12 */
+@@ -369,7 +369,7 @@ static inline u32 iop_desc_get_byte_count(struct iop_adma_desc_slot *desc,
+ /* translate the src_idx to a descriptor word index */
+ static inline int __desc_idx(int src_idx)
+ {
+- const static int desc_idx_table[] = { 0, 0, 0, 0,
++ static const int desc_idx_table[] = { 0, 0, 0, 0,
+ 0, 1, 2, 3,
+ 5, 6, 7, 8,
+ 9, 10, 11, 12,
+@@ -767,20 +767,12 @@ static inline int iop_desc_get_zero_result(struct iop_adma_desc_slot *desc)
+ static inline void iop_chan_append(struct iop_adma_chan *chan)
+ {
+ u32 dma_chan_ctrl;
+- /* workaround dropped interrupts on 3xx */
+- mod_timer(&chan->cleanup_watchdog, jiffies + msecs_to_jiffies(3));
+
+ dma_chan_ctrl = __raw_readl(DMA_CCR(chan));
+ dma_chan_ctrl |= 0x2;
+ __raw_writel(dma_chan_ctrl, DMA_CCR(chan));
+ }
+
+-static inline void iop_chan_idle(int busy, struct iop_adma_chan *chan)
+-{
+- if (!busy)
+- del_timer(&chan->cleanup_watchdog);
+-}
+-
+ static inline u32 iop_chan_get_status(struct iop_adma_chan *chan)
+ {
+ return __raw_readl(DMA_CSR(chan));
+diff --git a/include/asm-arm/hardware/iop3xx.h b/include/asm-arm/hardware/iop3xx.h
+index ede377e..18f6937 100644
+--- a/include/asm-arm/hardware/iop3xx.h
++++ b/include/asm-arm/hardware/iop3xx.h
+@@ -29,6 +29,7 @@ extern void gpio_line_config(int line, int direction);
+ extern int gpio_line_get(int line);
+ extern void gpio_line_set(int line, int value);
+ extern int init_atu;
++extern int iop3xx_get_init_atu(void);
+ #endif
+
+
+@@ -112,14 +113,6 @@ extern int init_atu;
+ #define IOP3XX_INIT_ATU_DISABLE -1
+ #define IOP3XX_INIT_ATU_ENABLE 1
+
+-#ifdef CONFIG_IOP3XX_ATU
+-#define iop3xx_get_init_atu(x) (init_atu == IOP3XX_INIT_ATU_DEFAULT ?\
+- IOP3XX_INIT_ATU_ENABLE : init_atu)
+-#else
+-#define iop3xx_get_init_atu(x) (init_atu == IOP3XX_INIT_ATU_DEFAULT ?\
+- IOP3XX_INIT_ATU_DISABLE : init_atu)
+-#endif
+-
+ /* Messaging Unit */
+ #define IOP3XX_IMR0 (volatile u32 *)IOP3XX_REG_ADDR(0x0310)
+ #define IOP3XX_IMR1 (volatile u32 *)IOP3XX_REG_ADDR(0x0314)
+diff --git a/include/asm-arm/hardware/iop_adma.h b/include/asm-arm/hardware/iop_adma.h
+index ca8e71f..cb7e361 100644
+--- a/include/asm-arm/hardware/iop_adma.h
++++ b/include/asm-arm/hardware/iop_adma.h
+@@ -51,7 +51,6 @@ struct iop_adma_device {
+ * @common: common dmaengine channel object members
+ * @last_used: place holder for allocation to continue from where it left off
+ * @all_slots: complete domain of slots usable by the channel
+- * @cleanup_watchdog: workaround missed interrupts on iop3xx
+ * @slots_allocated: records the actual size of the descriptor slot pool
+ * @irq_tasklet: bottom half where iop_adma_slot_cleanup runs
+ */
+@@ -65,7 +64,6 @@ struct iop_adma_chan {
+ struct dma_chan common;
+ struct iop_adma_desc_slot *last_used;
+ struct list_head all_slots;
+- struct timer_list cleanup_watchdog;
+ int slots_allocated;
+ struct tasklet_struct irq_tasklet;
+ };
+diff --git a/include/asm-arm/hardware/scoop.h b/include/asm-arm/hardware/scoop.h
+index d37bf74..dfb8330 100644
+--- a/include/asm-arm/hardware/scoop.h
++++ b/include/asm-arm/hardware/scoop.h
+@@ -40,6 +40,7 @@ struct scoop_config {
+ unsigned short io_dir;
+ unsigned short suspend_clr;
+ unsigned short suspend_set;
++ int gpio_base;
+ };
+
+ /* Structure for linking scoop devices to PCMCIA sockets */
+@@ -62,7 +63,7 @@ struct scoop_pcmcia_config {
+ extern struct scoop_pcmcia_config *platform_scoop_config;
+
+ void reset_scoop(struct device *dev);
+-unsigned short set_scoop_gpio(struct device *dev, unsigned short bit);
+-unsigned short reset_scoop_gpio(struct device *dev, unsigned short bit);
++unsigned short __deprecated set_scoop_gpio(struct device *dev, unsigned short bit);
++unsigned short __deprecated reset_scoop_gpio(struct device *dev, unsigned short bit);
+ unsigned short read_scoop_reg(struct device *dev, unsigned short reg);
+ void write_scoop_reg(struct device *dev, unsigned short reg, unsigned short data);
+diff --git a/include/asm-arm/hwcap.h b/include/asm-arm/hwcap.h
+index 01a1391..81f4c89 100644
+--- a/include/asm-arm/hwcap.h
++++ b/include/asm-arm/hwcap.h
+@@ -15,6 +15,7 @@
+ #define HWCAP_JAVA 256
+ #define HWCAP_IWMMXT 512
+ #define HWCAP_CRUNCH 1024
++#define HWCAP_THUMBEE 2048
+
+ #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+ /*
+diff --git a/include/asm-arm/ide.h b/include/asm-arm/ide.h
+index f348fcf..88f4d23 100644
+--- a/include/asm-arm/ide.h
++++ b/include/asm-arm/ide.h
+@@ -17,14 +17,6 @@
+ #define MAX_HWIFS 4
+ #endif
+
+-#if !defined(CONFIG_ARCH_L7200)
+-# ifdef CONFIG_ARCH_CLPS7500
+-# define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */
+-# else
+-# define ide_default_io_ctl(base) (0)
+-# endif
+-#endif /* !ARCH_L7200 */
+-
+ #define __ide_mm_insw(port,addr,len) readsw(port,addr,len)
+ #define __ide_mm_insl(port,addr,len) readsl(port,addr,len)
+ #define __ide_mm_outsw(port,addr,len) writesw(port,addr,len)
+diff --git a/include/asm-arm/mach/pci.h b/include/asm-arm/mach/pci.h
+index 24621c4..9d4f6b5 100644
+--- a/include/asm-arm/mach/pci.h
++++ b/include/asm-arm/mach/pci.h
+@@ -55,6 +55,7 @@ void pci_common_init(struct hw_pci *);
+ extern int iop3xx_pci_setup(int nr, struct pci_sys_data *);
+ extern struct pci_bus *iop3xx_pci_scan_bus(int nr, struct pci_sys_data *);
+ extern void iop3xx_pci_preinit(void);
++extern void iop3xx_pci_preinit_cond(void);
+
+ extern int dc21285_setup(int nr, struct pci_sys_data *);
+ extern struct pci_bus *dc21285_scan_bus(int nr, struct pci_sys_data *);
+diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h
+index d9bfb39..9ba4d71 100644
+--- a/include/asm-arm/memory.h
++++ b/include/asm-arm/memory.h
+@@ -217,7 +217,10 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
+ #ifndef CONFIG_DISCONTIGMEM
+
+ #define ARCH_PFN_OFFSET PHYS_PFN_OFFSET
++
++#ifndef CONFIG_SPARSEMEM
+ #define pfn_valid(pfn) ((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr))
++#endif
+
+ #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+ #define virt_addr_valid(kaddr) ((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory)
+diff --git a/include/asm-arm/plat-orion/ehci-orion.h b/include/asm-arm/plat-orion/ehci-orion.h
+new file mode 100644
+index 0000000..7857056
+--- /dev/null
++++ b/include/asm-arm/plat-orion/ehci-orion.h
+@@ -0,0 +1,19 @@
++/*
++ * include/asm-arm/plat-orion/ehci-orion.h
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#ifndef __ASM_PLAT_ORION_EHCI_ORION_H
++#define __ASM_PLAT_ORION_EHCI_ORION_H
++
++#include <linux/mbus.h>
++
++struct orion_ehci_data {
++ struct mbus_dram_target_info *dram;
++};
++
++
++#endif
+diff --git a/include/asm-arm/plat-orion/irq.h b/include/asm-arm/plat-orion/irq.h
+new file mode 100644
+index 0000000..94aeed9
+--- /dev/null
++++ b/include/asm-arm/plat-orion/irq.h
+@@ -0,0 +1,17 @@
++/*
++ * include/asm-arm/plat-orion/irq.h
++ *
++ * Marvell Orion SoC IRQ handling.
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#ifndef __ASM_PLAT_ORION_IRQ_H
++#define __ASM_PLAT_ORION_IRQ_H
++
++void orion_irq_init(unsigned int irq_start, void __iomem *maskaddr);
++
++
++#endif
+diff --git a/include/asm-arm/plat-orion/orion_nand.h b/include/asm-arm/plat-orion/orion_nand.h
+new file mode 100644
+index 0000000..ffd3852
+--- /dev/null
++++ b/include/asm-arm/plat-orion/orion_nand.h
+@@ -0,0 +1,24 @@
++/*
++ * include/asm-arm/plat-orion/orion_nand.h
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#ifndef __ASM_PLAT_ORION_ORION_NAND_H
++#define __ASM_PLAT_ORION_ORION_NAND_H
++
++/*
++ * Device bus NAND private data
++ */
++struct orion_nand_data {
++ struct mtd_partition *parts;
++ u32 nr_parts;
++ u8 ale; /* address line number connected to ALE */
++ u8 cle; /* address line number connected to CLE */
++ u8 width; /* buswidth */
++};
++
++
++#endif
+diff --git a/include/asm-arm/plat-orion/pcie.h b/include/asm-arm/plat-orion/pcie.h
+new file mode 100644
+index 0000000..6434ac6
+--- /dev/null
++++ b/include/asm-arm/plat-orion/pcie.h
+@@ -0,0 +1,31 @@
++/*
++ * include/asm-arm/plat-orion/pcie.h
++ *
++ * Marvell Orion SoC PCIe handling.
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#ifndef __ASM_PLAT_ORION_PCIE_H
++#define __ASM_PLAT_ORION_PCIE_H
++
++u32 orion_pcie_dev_id(void __iomem *base);
++u32 orion_pcie_rev(void __iomem *base);
++int orion_pcie_link_up(void __iomem *base);
++int orion_pcie_get_local_bus_nr(void __iomem *base);
++void orion_pcie_set_local_bus_nr(void __iomem *base, int nr);
++void orion_pcie_setup(void __iomem *base,
++ struct mbus_dram_target_info *dram);
++int orion_pcie_rd_conf(void __iomem *base, struct pci_bus *bus,
++ u32 devfn, int where, int size, u32 *val);
++int orion_pcie_rd_conf_tlp(void __iomem *base, struct pci_bus *bus,
++ u32 devfn, int where, int size, u32 *val);
++int orion_pcie_rd_conf_wa(void __iomem *wa_base, struct pci_bus *bus,
++ u32 devfn, int where, int size, u32 *val);
++int orion_pcie_wr_conf(void __iomem *base, struct pci_bus *bus,
++ u32 devfn, int where, int size, u32 val);
++
++
++#endif
+diff --git a/include/asm-arm/plat-orion/time.h b/include/asm-arm/plat-orion/time.h
+new file mode 100644
+index 0000000..0e85cc8
+--- /dev/null
++++ b/include/asm-arm/plat-orion/time.h
+@@ -0,0 +1,17 @@
++/*
++ * include/asm-arm/plat-orion/time.h
++ *
++ * Marvell Orion SoC time handling.
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#ifndef __ASM_PLAT_ORION_TIME_H
++#define __ASM_PLAT_ORION_TIME_H
++
++void orion_time_init(unsigned int irq, unsigned int tclk);
++
++
++#endif
+diff --git a/include/asm-arm/plat-s3c/nand.h b/include/asm-arm/plat-s3c/nand.h
+index 8816f7f..ad6bbe9 100644
+--- a/include/asm-arm/plat-s3c/nand.h
++++ b/include/asm-arm/plat-s3c/nand.h
+@@ -22,11 +22,14 @@
+ */
+
+ struct s3c2410_nand_set {
++ unsigned int disable_ecc : 1;
++
+ int nr_chips;
+ int nr_partitions;
+ char *name;
+ int *nr_map;
+ struct mtd_partition *partitions;
++ struct nand_ecclayout *ecc_layout;
+ };
+
+ struct s3c2410_platform_nand {
+@@ -36,6 +39,8 @@ struct s3c2410_platform_nand {
+ int twrph0; /* active time for nWE/nOE */
+ int twrph1; /* time for release CLE/ALE from nWE/nOE inactive */
+
++ unsigned int ignore_unset_ecc : 1;
++
+ int nr_sets;
+ struct s3c2410_nand_set *sets;
+
+diff --git a/include/asm-arm/semaphore-helper.h b/include/asm-arm/semaphore-helper.h
+deleted file mode 100644
+index 1d7f198..0000000
+--- a/include/asm-arm/semaphore-helper.h
++++ /dev/null
+@@ -1,84 +0,0 @@
+-#ifndef ASMARM_SEMAPHORE_HELPER_H
+-#define ASMARM_SEMAPHORE_HELPER_H
+-
+-/*
+- * These two _must_ execute atomically wrt each other.
+- */
+-static inline void wake_one_more(struct semaphore * sem)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- if (atomic_read(&sem->count) <= 0)
+- sem->waking++;
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-}
+-
+-static inline int waking_non_zero(struct semaphore *sem)
+-{
+- unsigned long flags;
+- int ret = 0;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- if (sem->waking > 0) {
+- sem->waking--;
+- ret = 1;
+- }
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+- return ret;
+-}
+-
+-/*
+- * waking non zero interruptible
+- * 1 got the lock
+- * 0 go to sleep
+- * -EINTR interrupted
+- *
+- * We must undo the sem->count down_interruptible() increment while we are
+- * protected by the spinlock in order to make this atomic_inc() with the
+- * atomic_read() in wake_one_more(), otherwise we can race. -arca
+- */
+-static inline int waking_non_zero_interruptible(struct semaphore *sem,
+- struct task_struct *tsk)
+-{
+- unsigned long flags;
+- int ret = 0;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- if (sem->waking > 0) {
+- sem->waking--;
+- ret = 1;
+- } else if (signal_pending(tsk)) {
+- atomic_inc(&sem->count);
+- ret = -EINTR;
+- }
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+- return ret;
+-}
+-
+-/*
+- * waking_non_zero_try_lock:
+- * 1 failed to lock
+- * 0 got the lock
+- *
+- * We must undo the sem->count down_interruptible() increment while we are
+- * protected by the spinlock in order to make this atomic_inc() with the
+- * atomic_read() in wake_one_more(), otherwise we can race. -arca
+- */
+-static inline int waking_non_zero_trylock(struct semaphore *sem)
+-{
+- unsigned long flags;
+- int ret = 1;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- if (sem->waking <= 0)
+- atomic_inc(&sem->count);
+- else {
+- sem->waking--;
+- ret = 0;
+- }
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+- return ret;
+-}
+-
+-#endif
+diff --git a/include/asm-arm/semaphore.h b/include/asm-arm/semaphore.h
+index 1c8b441..d9b2034 100644
+--- a/include/asm-arm/semaphore.h
++++ b/include/asm-arm/semaphore.h
+@@ -1,98 +1 @@
+-/*
+- * linux/include/asm-arm/semaphore.h
+- */
+-#ifndef __ASM_ARM_SEMAPHORE_H
+-#define __ASM_ARM_SEMAPHORE_H
+-
+-#include <linux/linkage.h>
+-#include <linux/spinlock.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-#include <asm/atomic.h>
+-#include <asm/locks.h>
+-
+-struct semaphore {
+- atomic_t count;
+- int sleepers;
+- wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INIT(name, cnt) \
+-{ \
+- .count = ATOMIC_INIT(cnt), \
+- .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+- struct semaphore name = __SEMAPHORE_INIT(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init(struct semaphore *sem, int val)
+-{
+- atomic_set(&sem->count, val);
+- sem->sleepers = 0;
+- init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX(struct semaphore *sem)
+-{
+- sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED(struct semaphore *sem)
+-{
+- sema_init(sem, 0);
+-}
+-
+-/*
+- * special register calling convention
+- */
+-asmlinkage void __down_failed(void);
+-asmlinkage int __down_interruptible_failed(void);
+-asmlinkage int __down_trylock_failed(void);
+-asmlinkage void __up_wakeup(void);
+-
+-extern void __down(struct semaphore * sem);
+-extern int __down_interruptible(struct semaphore * sem);
+-extern int __down_trylock(struct semaphore * sem);
+-extern void __up(struct semaphore * sem);
+-
+-/*
+- * This is ugly, but we want the default case to fall through.
+- * "__down" is the actual routine that waits...
+- */
+-static inline void down(struct semaphore * sem)
+-{
+- might_sleep();
+- __down_op(sem, __down_failed);
+-}
+-
+-/*
+- * This is ugly, but we want the default case to fall through.
+- * "__down_interruptible" is the actual routine that waits...
+- */
+-static inline int down_interruptible (struct semaphore * sem)
+-{
+- might_sleep();
+- return __down_op_ret(sem, __down_interruptible_failed);
+-}
+-
+-static inline int down_trylock(struct semaphore *sem)
+-{
+- return __down_op_ret(sem, __down_trylock_failed);
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- * The default case (no contention) will result in NO
+- * jumps for both down() and up().
+- */
+-static inline void up(struct semaphore * sem)
+-{
+- __up_op(sem, __up_wakeup);
+-}
+-
+-#endif
++#include <linux/semaphore.h>
+diff --git a/include/asm-arm/sparsemem.h b/include/asm-arm/sparsemem.h
+new file mode 100644
+index 0000000..2771581
+--- /dev/null
++++ b/include/asm-arm/sparsemem.h
+@@ -0,0 +1,10 @@
++#ifndef ASMARM_SPARSEMEM_H
++#define ASMARM_SPARSEMEM_H
++
++#include <asm/memory.h>
++
++#define MAX_PHYSADDR_BITS 32
++#define MAX_PHYSMEM_BITS 32
++#define SECTION_SIZE_BITS NODE_MEM_SIZE_BITS
++
++#endif
+diff --git a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h
+index 4178435..f5a6647 100644
+--- a/include/asm-arm/thread_info.h
++++ b/include/asm-arm/thread_info.h
+@@ -62,6 +62,9 @@ struct thread_info {
+ struct crunch_state crunchstate;
+ union fp_state fpstate __attribute__((aligned(8)));
+ union vfp_state vfpstate;
++#ifdef CONFIG_ARM_THUMBEE
++ unsigned long thumbee_state; /* ThumbEE Handler Base register */
++#endif
+ struct restart_block restart_block;
+ };
+
+diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
+index 88e868b..7c57008 100644
+--- a/include/asm-arm/unistd.h
++++ b/include/asm-arm/unistd.h
+@@ -376,9 +376,11 @@
+ #define __NR_kexec_load (__NR_SYSCALL_BASE+347)
+ #define __NR_utimensat (__NR_SYSCALL_BASE+348)
+ #define __NR_signalfd (__NR_SYSCALL_BASE+349)
+-#define __NR_timerfd (__NR_SYSCALL_BASE+350)
++#define __NR_timerfd_create (__NR_SYSCALL_BASE+350)
+ #define __NR_eventfd (__NR_SYSCALL_BASE+351)
+ #define __NR_fallocate (__NR_SYSCALL_BASE+352)
++#define __NR_timerfd_settime (__NR_SYSCALL_BASE+353)
++#define __NR_timerfd_gettime (__NR_SYSCALL_BASE+354)
+
+ /*
+ * The following SWIs are ARM private.
+diff --git a/include/asm-avr32/arch-at32ap/board.h b/include/asm-avr32/arch-at32ap/board.h
+index 7597b0b..a4e2d28 100644
+--- a/include/asm-avr32/arch-at32ap/board.h
++++ b/include/asm-avr32/arch-at32ap/board.h
+@@ -38,9 +38,7 @@ struct platform_device *
+ at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
+ unsigned long fbmem_start, unsigned long fbmem_len);
+
+-struct usba_platform_data {
+- int vbus_pin;
+-};
++struct usba_platform_data;
+ struct platform_device *
+ at32_add_device_usba(unsigned int id, struct usba_platform_data *data);
+
+@@ -68,7 +66,10 @@ struct platform_device *at32_add_device_pwm(u32 mask);
+ struct platform_device *
+ at32_add_device_ssc(unsigned int id, unsigned int flags);
+
+-struct platform_device *at32_add_device_twi(unsigned int id);
++struct i2c_board_info;
++struct platform_device *at32_add_device_twi(unsigned int id,
++ struct i2c_board_info *b,
++ unsigned int n);
+ struct platform_device *at32_add_device_mci(unsigned int id);
+ struct platform_device *at32_add_device_ac97c(unsigned int id);
+ struct platform_device *at32_add_device_abdac(unsigned int id);
+diff --git a/include/asm-avr32/arch-at32ap/pm.h b/include/asm-avr32/arch-at32ap/pm.h
+new file mode 100644
+index 0000000..356e430
+--- /dev/null
++++ b/include/asm-avr32/arch-at32ap/pm.h
+@@ -0,0 +1,48 @@
++/*
++ * AVR32 AP Power Management.
++ *
++ * Copyright (C) 2008 Atmel Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __ASM_AVR32_ARCH_PM_H
++#define __ASM_AVR32_ARCH_PM_H
++
++/* Possible arguments to the "sleep" instruction */
++#define CPU_SLEEP_IDLE 0
++#define CPU_SLEEP_FROZEN 1
++#define CPU_SLEEP_STANDBY 2
++#define CPU_SLEEP_STOP 3
++#define CPU_SLEEP_STATIC 5
++
++#ifndef __ASSEMBLY__
++extern void cpu_enter_idle(void);
++
++extern bool disable_idle_sleep;
++
++static inline void cpu_disable_idle_sleep(void)
++{
++ disable_idle_sleep = true;
++}
++
++static inline void cpu_enable_idle_sleep(void)
++{
++ disable_idle_sleep = false;
++}
++
++static inline void cpu_idle_sleep(void)
++{
++ /*
++ * If we're using the COUNT and COMPARE registers for
++ * timekeeping, we can't use the IDLE state.
++ */
++ if (disable_idle_sleep)
++ cpu_relax();
++ else
++ cpu_enter_idle();
++}
++#endif
++
++#endif /* __ASM_AVR32_ARCH_PM_H */
+diff --git a/include/asm-avr32/arch-at32ap/time.h b/include/asm-avr32/arch-at32ap/time.h
+deleted file mode 100644
+index cc8a434..0000000
+--- a/include/asm-avr32/arch-at32ap/time.h
++++ /dev/null
+@@ -1,112 +0,0 @@
+-/*
+- * Copyright (C) 2007 Atmel Corporation
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#ifndef _ASM_AVR32_ARCH_AT32AP_TIME_H
+-#define _ASM_AVR32_ARCH_AT32AP_TIME_H
+-
+-#include <linux/platform_device.h>
+-
+-extern struct irqaction timer_irqaction;
+-extern struct platform_device at32_systc0_device;
+-extern void local_timer_interrupt(int irq, void *dev_id);
+-
+-#define TIMER_BCR 0x000000c0
+-#define TIMER_BCR_SYNC 0
+-#define TIMER_BMR 0x000000c4
+-#define TIMER_BMR_TC0XC0S 0
+-#define TIMER_BMR_TC1XC1S 2
+-#define TIMER_BMR_TC2XC2S 4
+-#define TIMER_CCR 0x00000000
+-#define TIMER_CCR_CLKDIS 1
+-#define TIMER_CCR_CLKEN 0
+-#define TIMER_CCR_SWTRG 2
+-#define TIMER_CMR 0x00000004
+-#define TIMER_CMR_ABETRG 10
+-#define TIMER_CMR_ACPA 16
+-#define TIMER_CMR_ACPC 18
+-#define TIMER_CMR_AEEVT 20
+-#define TIMER_CMR_ASWTRG 22
+-#define TIMER_CMR_BCPB 24
+-#define TIMER_CMR_BCPC 26
+-#define TIMER_CMR_BEEVT 28
+-#define TIMER_CMR_BSWTRG 30
+-#define TIMER_CMR_BURST 4
+-#define TIMER_CMR_CLKI 3
+-#define TIMER_CMR_CPCDIS 7
+-#define TIMER_CMR_CPCSTOP 6
+-#define TIMER_CMR_CPCTRG 14
+-#define TIMER_CMR_EEVT 10
+-#define TIMER_CMR_EEVTEDG 8
+-#define TIMER_CMR_ENETRG 12
+-#define TIMER_CMR_ETRGEDG 8
+-#define TIMER_CMR_LDBDIS 7
+-#define TIMER_CMR_LDBSTOP 6
+-#define TIMER_CMR_LDRA 16
+-#define TIMER_CMR_LDRB 18
+-#define TIMER_CMR_TCCLKS 0
+-#define TIMER_CMR_WAVE 15
+-#define TIMER_CMR_WAVSEL 13
+-#define TIMER_CV 0x00000010
+-#define TIMER_CV_CV 0
+-#define TIMER_IDR 0x00000028
+-#define TIMER_IDR_COVFS 0
+-#define TIMER_IDR_CPAS 2
+-#define TIMER_IDR_CPBS 3
+-#define TIMER_IDR_CPCS 4
+-#define TIMER_IDR_ETRGS 7
+-#define TIMER_IDR_LDRAS 5
+-#define TIMER_IDR_LDRBS 6
+-#define TIMER_IDR_LOVRS 1
+-#define TIMER_IER 0x00000024
+-#define TIMER_IER_COVFS 0
+-#define TIMER_IER_CPAS 2
+-#define TIMER_IER_CPBS 3
+-#define TIMER_IER_CPCS 4
+-#define TIMER_IER_ETRGS 7
+-#define TIMER_IER_LDRAS 5
+-#define TIMER_IER_LDRBS 6
+-#define TIMER_IER_LOVRS 1
+-#define TIMER_IMR 0x0000002c
+-#define TIMER_IMR_COVFS 0
+-#define TIMER_IMR_CPAS 2
+-#define TIMER_IMR_CPBS 3
+-#define TIMER_IMR_CPCS 4
+-#define TIMER_IMR_ETRGS 7
+-#define TIMER_IMR_LDRAS 5
+-#define TIMER_IMR_LDRBS 6
+-#define TIMER_IMR_LOVRS 1
+-#define TIMER_RA 0x00000014
+-#define TIMER_RA_RA 0
+-#define TIMER_RB 0x00000018
+-#define TIMER_RB_RB 0
+-#define TIMER_RC 0x0000001c
+-#define TIMER_RC_RC 0
+-#define TIMER_SR 0x00000020
+-#define TIMER_SR_CLKSTA 16
+-#define TIMER_SR_COVFS 0
+-#define TIMER_SR_CPAS 2
+-#define TIMER_SR_CPBS 3
+-#define TIMER_SR_CPCS 4
+-#define TIMER_SR_ETRGS 7
+-#define TIMER_SR_LDRAS 5
+-#define TIMER_SR_LDRBS 6
+-#define TIMER_SR_LOVRS 1
+-#define TIMER_SR_MTIOA 17
+-#define TIMER_SR_MTIOB 18
+-
+-/* Bit manipulation macros */
+-#define TIMER_BIT(name) (1 << TIMER_##name)
+-#define TIMER_BF(name,value) ((value) << TIMER_##name)
+-
+-/* Register access macros */
+-#define timer_read(port,instance,reg) \
+- __raw_readl(port + (0x40 * instance) + TIMER_##reg)
+-#define timer_write(port,instance,reg,value) \
+- __raw_writel((value), port + (0x40 * instance) + TIMER_##reg)
+-
+-#endif /* _ASM_AVR32_ARCH_AT32AP_TIME_H */
+diff --git a/include/asm-avr32/asm.h b/include/asm-avr32/asm.h
+index 515c761..a2c64f4 100644
+--- a/include/asm-avr32/asm.h
++++ b/include/asm-avr32/asm.h
+@@ -12,10 +12,10 @@
+ #include <asm/asm-offsets.h>
+ #include <asm/thread_info.h>
+
+-#define mask_interrupts ssrf SR_GM_BIT
+-#define mask_exceptions ssrf SR_EM_BIT
+-#define unmask_interrupts csrf SR_GM_BIT
+-#define unmask_exceptions csrf SR_EM_BIT
++#define mask_interrupts ssrf SYSREG_GM_OFFSET
++#define mask_exceptions ssrf SYSREG_EM_OFFSET
++#define unmask_interrupts csrf SYSREG_GM_OFFSET
++#define unmask_exceptions csrf SYSREG_EM_OFFSET
+
+ #ifdef CONFIG_FRAME_POINTER
+ .macro save_fp
+diff --git a/include/asm-avr32/intc.h b/include/asm-avr32/intc.h
+deleted file mode 100644
+index 1ac9ca7..0000000
+--- a/include/asm-avr32/intc.h
++++ /dev/null
+@@ -1,128 +0,0 @@
+-#ifndef __ASM_AVR32_INTC_H
+-#define __ASM_AVR32_INTC_H
+-
+-#include <linux/sysdev.h>
+-#include <linux/interrupt.h>
+-
+-struct irq_controller;
+-struct irqaction;
+-struct pt_regs;
+-
+-struct platform_device;
+-
+-/* Information about the internal interrupt controller */
+-struct intc_device {
+- /* ioremapped address of configuration block */
+- void __iomem *regs;
+-
+- /* the physical device */
+- struct platform_device *pdev;
+-
+- /* Number of interrupt lines per group. */
+- unsigned int irqs_per_group;
+-
+- /* The highest group ID + 1 */
+- unsigned int nr_groups;
+-
+- /*
+- * Bitfield indicating which groups are actually in use. The
+- * size of the array is
+- * ceil(group_max / (8 * sizeof(unsigned int))).
+- */
+- unsigned int group_mask[];
+-};
+-
+-struct irq_controller_class {
+- /*
+- * A short name identifying this kind of controller.
+- */
+- const char *typename;
+- /*
+- * Handle the IRQ. Must do any necessary acking and masking.
+- */
+- irqreturn_t (*handle)(int irq, void *dev_id, struct pt_regs *regs);
+- /*
+- * Register a new IRQ handler.
+- */
+- int (*setup)(struct irq_controller *ctrl, unsigned int irq,
+- struct irqaction *action);
+- /*
+- * Unregister a IRQ handler.
+- */
+- void (*free)(struct irq_controller *ctrl, unsigned int irq,
+- void *dev_id);
+- /*
+- * Mask the IRQ in the interrupt controller.
+- */
+- void (*mask)(struct irq_controller *ctrl, unsigned int irq);
+- /*
+- * Unmask the IRQ in the interrupt controller.
+- */
+- void (*unmask)(struct irq_controller *ctrl, unsigned int irq);
+- /*
+- * Set the type of the IRQ. See below for possible types.
+- * Return -EINVAL if a given type is not supported
+- */
+- int (*set_type)(struct irq_controller *ctrl, unsigned int irq,
+- unsigned int type);
+- /*
+- * Return the IRQ type currently set
+- */
+- unsigned int (*get_type)(struct irq_controller *ctrl, unsigned int irq);
+-};
+-
+-struct irq_controller {
+- struct irq_controller_class *class;
+- unsigned int irq_group;
+- unsigned int first_irq;
+- unsigned int nr_irqs;
+- struct list_head list;
+-};
+-
+-struct intc_group_desc {
+- struct irq_controller *ctrl;
+- irqreturn_t (*handle)(int, void *, struct pt_regs *);
+- unsigned long flags;
+- void *dev_id;
+- const char *devname;
+-};
+-
+-/*
+- * The internal interrupt controller. Defined in board/part-specific
+- * devices.c.
+- * TODO: Should probably be defined per-cpu.
+- */
+-extern struct intc_device intc;
+-
+-extern int request_internal_irq(unsigned int irq,
+- irqreturn_t (*handler)(int, void *, struct pt_regs *),
+- unsigned long irqflags,
+- const char *devname, void *dev_id);
+-extern void free_internal_irq(unsigned int irq);
+-
+-/* Only used by time_init() */
+-extern int setup_internal_irq(unsigned int irq, struct intc_group_desc *desc);
+-
+-/*
+- * Set interrupt priority for a given group. `group' can be found by
+- * using irq_to_group(irq). Priority can be from 0 (lowest) to 3
+- * (highest). Higher-priority interrupts will preempt lower-priority
+- * interrupts (unless interrupts are masked globally).
+- *
+- * This function does not check for conflicts within a group.
+- */
+-extern int intc_set_priority(unsigned int group,
+- unsigned int priority);
+-
+-/*
+- * Returns a bitmask of pending interrupts in a group.
+- */
+-extern unsigned long intc_get_pending(unsigned int group);
+-
+-/*
+- * Register a new external interrupt controller. Returns the first
+- * external IRQ number that is assigned to the new controller.
+- */
+-extern int intc_register_controller(struct irq_controller *ctrl);
+-
+-#endif /* __ASM_AVR32_INTC_H */
+diff --git a/include/asm-avr32/irq.h b/include/asm-avr32/irq.h
+index 9315724..c563b77 100644
+--- a/include/asm-avr32/irq.h
++++ b/include/asm-avr32/irq.h
+@@ -14,6 +14,11 @@
+ #ifndef __ASSEMBLER__
+ int nmi_enable(void);
+ void nmi_disable(void);
++
++/*
++ * Returns a bitmask of pending interrupts in a group.
++ */
++extern unsigned long intc_get_pending(unsigned int group);
+ #endif
+
+ #endif /* __ASM_AVR32_IOCTLS_H */
+diff --git a/include/asm-avr32/page.h b/include/asm-avr32/page.h
+index 5582968..cbbc5ca 100644
+--- a/include/asm-avr32/page.h
++++ b/include/asm-avr32/page.h
+@@ -8,13 +8,11 @@
+ #ifndef __ASM_AVR32_PAGE_H
+ #define __ASM_AVR32_PAGE_H
+
++#include <linux/const.h>
++
+ /* PAGE_SHIFT determines the page size */
+ #define PAGE_SHIFT 12
+-#ifdef __ASSEMBLY__
+-#define PAGE_SIZE (1 << PAGE_SHIFT)
+-#else
+-#define PAGE_SIZE (1UL << PAGE_SHIFT)
+-#endif
++#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
+ #define PAGE_MASK (~(PAGE_SIZE-1))
+ #define PTE_MASK PAGE_MASK
+
+diff --git a/include/asm-avr32/semaphore.h b/include/asm-avr32/semaphore.h
+index feaf1d4..d9b2034 100644
+--- a/include/asm-avr32/semaphore.h
++++ b/include/asm-avr32/semaphore.h
+@@ -1,108 +1 @@
+-/*
+- * SMP- and interrupt-safe semaphores.
+- *
+- * Copyright (C) 2006 Atmel Corporation
+- *
+- * Based on include/asm-i386/semaphore.h
+- * Copyright (C) 1996 Linus Torvalds
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-#ifndef __ASM_AVR32_SEMAPHORE_H
+-#define __ASM_AVR32_SEMAPHORE_H
+-
+-#include <linux/linkage.h>
+-
+-#include <asm/system.h>
+-#include <asm/atomic.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-struct semaphore {
+- atomic_t count;
+- int sleepers;
+- wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n) \
+-{ \
+- .count = ATOMIC_INIT(n), \
+- .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+- struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+- atomic_set(&sem->count, val);
+- sem->sleepers = 0;
+- init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+- sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+- sema_init(sem, 0);
+-}
+-
+-void __down(struct semaphore * sem);
+-int __down_interruptible(struct semaphore * sem);
+-void __up(struct semaphore * sem);
+-
+-/*
+- * This is ugly, but we want the default case to fall through.
+- * "__down_failed" is a special asm handler that calls the C
+- * routine that actually waits. See arch/i386/kernel/semaphore.c
+- */
+-static inline void down(struct semaphore * sem)
+-{
+- might_sleep();
+- if (unlikely(atomic_dec_return (&sem->count) < 0))
+- __down (sem);
+-}
+-
+-/*
+- * Interruptible try to acquire a semaphore. If we obtained
+- * it, return zero. If we were interrupted, returns -EINTR
+- */
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+- int ret = 0;
+-
+- might_sleep();
+- if (unlikely(atomic_dec_return (&sem->count) < 0))
+- ret = __down_interruptible (sem);
+- return ret;
+-}
+-
+-/*
+- * Non-blockingly attempt to down() a semaphore.
+- * Returns zero if we acquired it
+- */
+-static inline int down_trylock(struct semaphore * sem)
+-{
+- return atomic_dec_if_positive(&sem->count) < 0;
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- * The default case (no contention) will result in NO
+- * jumps for both down() and up().
+- */
+-static inline void up(struct semaphore * sem)
+-{
+- if (unlikely(atomic_inc_return (&sem->count) <= 0))
+- __up (sem);
+-}
+-
+-#endif /*__ASM_AVR32_SEMAPHORE_H */
++#include <linux/semaphore.h>
+diff --git a/include/asm-avr32/serial.h b/include/asm-avr32/serial.h
+new file mode 100644
+index 0000000..5ecaebc
+--- /dev/null
++++ b/include/asm-avr32/serial.h
+@@ -0,0 +1,13 @@
++#ifndef _ASM_SERIAL_H
++#define _ASM_SERIAL_H
++
++/*
++ * This assumes you have a 1.8432 MHz clock for your UART.
++ *
++ * It'd be nice if someone built a serial card with a 24.576 MHz
++ * clock, since the 16550A is capable of handling a top speed of 1.5
++ * megabits/second; but this requires the faster clock.
++ */
++#define BASE_BAUD (1843200 / 16)
++
++#endif /* _ASM_SERIAL_H */
+diff --git a/include/asm-avr32/xor.h b/include/asm-avr32/xor.h
+new file mode 100644
+index 0000000..99c87aa
+--- /dev/null
++++ b/include/asm-avr32/xor.h
+@@ -0,0 +1,6 @@
++#ifndef _ASM_XOR_H
++#define _ASM_XOR_H
++
++#include <asm-generic/xor.h>
++
++#endif
+diff --git a/include/asm-blackfin/.gitignore b/include/asm-blackfin/.gitignore
+new file mode 100644
+index 0000000..7858564
+--- /dev/null
++++ b/include/asm-blackfin/.gitignore
+@@ -0,0 +1 @@
+++mach
+diff --git a/include/asm-blackfin/bfin-global.h b/include/asm-blackfin/bfin-global.h
+index 5dba3a7..716df7c 100644
+--- a/include/asm-blackfin/bfin-global.h
++++ b/include/asm-blackfin/bfin-global.h
+@@ -112,20 +112,10 @@ extern void init_leds(void);
+
+ extern const char bfin_board_name[];
+ extern unsigned long wall_jiffies;
+-extern unsigned long ipdt_table[];
+-extern unsigned long dpdt_table[];
+-extern unsigned long icplb_table[];
+-extern unsigned long dcplb_table[];
+-
+-extern unsigned long ipdt_swapcount_table[];
+-extern unsigned long dpdt_swapcount_table[];
+-
+-extern unsigned long table_start, table_end;
+
+ extern unsigned long bfin_sic_iwr[];
+ extern u16 _bfin_swrst; /* shadow for Software Reset Register (SWRST) */
+ extern struct file_operations dpmc_fops;
+-extern char _start;
+ extern unsigned long _ramstart, _ramend, _rambase;
+ extern unsigned long memory_start, memory_end, physical_mem_end;
+ extern char _stext_l1[], _etext_l1[], _sdata_l1[], _edata_l1[], _sbss_l1[],
+diff --git a/include/asm-blackfin/bug.h b/include/asm-blackfin/bug.h
+index 41e53b2..6d3e11b 100644
+--- a/include/asm-blackfin/bug.h
++++ b/include/asm-blackfin/bug.h
+@@ -1,4 +1,17 @@
+ #ifndef _BLACKFIN_BUG_H
+ #define _BLACKFIN_BUG_H
++
++#ifdef CONFIG_BUG
++#define HAVE_ARCH_BUG
++
++#define BUG() do { \
++ dump_bfin_trace_buffer(); \
++ printk(KERN_EMERG "BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
++ panic("BUG!"); \
++} while (0)
++
++#endif
++
+ #include <asm-generic/bug.h>
++
+ #endif
+diff --git a/include/asm-blackfin/cplb.h b/include/asm-blackfin/cplb.h
+index 654375c..5b0da9a 100644
+--- a/include/asm-blackfin/cplb.h
++++ b/include/asm-blackfin/cplb.h
+@@ -74,32 +74,6 @@
+ #define ASYNC_MEMORY_CPLB_COVERAGE ((ASYNC_BANK0_SIZE + ASYNC_BANK1_SIZE + \
+ ASYNC_BANK2_SIZE + ASYNC_BANK3_SIZE) / SIZE_4M)
+
+-/*
+-* Number of required data CPLB switchtable entries
+-* MEMSIZE / 4 (we mostly install 4M page size CPLBs
+-* approx 16 for smaller 1MB page size CPLBs for allignment purposes
+-* 1 for L1 Data Memory
+-* possibly 1 for L2 Data Memory
+-* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
+-* 1 for ASYNC Memory
+-*/
+-
+-
+-#define MAX_SWITCH_D_CPLBS (((CONFIG_MEM_SIZE / 4) + 16 + 1 + 1 + 1 \
+- + ASYNC_MEMORY_CPLB_COVERAGE) * 2)
+-
+-/*
+-* Number of required instruction CPLB switchtable entries
+-* MEMSIZE / 4 (we mostly install 4M page size CPLBs
+-* approx 12 for smaller 1MB page size CPLBs for allignment purposes
+-* 1 for L1 Instruction Memory
+-* possibly 1 for L2 Instruction Memory
+-* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
+-*/
+-
+-#define MAX_SWITCH_I_CPLBS (((CONFIG_MEM_SIZE / 4) + 12 + 1 + 1 + 1) * 2)
+-
+-
+ #define CPLB_ENABLE_ICACHE_P 0
+ #define CPLB_ENABLE_DCACHE_P 1
+ #define CPLB_ENABLE_DCACHE2_P 2
+diff --git a/include/asm-blackfin/dma-mapping.h b/include/asm-blackfin/dma-mapping.h
+index 282fabc..1a13c2f 100644
+--- a/include/asm-blackfin/dma-mapping.h
++++ b/include/asm-blackfin/dma-mapping.h
+@@ -27,6 +27,14 @@ void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+ extern dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
+ enum dma_data_direction direction);
+
++static inline dma_addr_t
++dma_map_page(struct device *dev, struct page *page,
++ unsigned long offset, size_t size,
++ enum dma_data_direction dir)
++{
++ return dma_map_single(dev, page_address(page) + offset, size, dir);
++}
++
+ /*
+ * Unmap a single streaming mode DMA translation. The dma_addr and size
+ * must match what was provided for in a previous pci_map_single call. All
+@@ -38,6 +46,13 @@ extern dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
+ extern void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+ enum dma_data_direction direction);
+
++static inline void
++dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
++ enum dma_data_direction dir)
++{
++ dma_unmap_single(dev, dma_addr, size, dir);
++}
++
+ /*
+ * Map a set of buffers described by scatterlist in streaming
+ * mode for DMA. This is the scather-gather version of the
+diff --git a/include/asm-blackfin/dma.h b/include/asm-blackfin/dma.h
+index 5abaa2c..c0d5259 100644
+--- a/include/asm-blackfin/dma.h
++++ b/include/asm-blackfin/dma.h
+@@ -33,7 +33,6 @@
+ #include <linux/slab.h>
+ #include <asm/irq.h>
+ #include <asm/signal.h>
+-#include <asm/semaphore.h>
+
+ #include <linux/kernel.h>
+ #include <asm/mach/dma.h>
+@@ -192,4 +191,7 @@ void clear_dma_irqstat(unsigned int channel);
+ void *dma_memcpy(void *dest, const void *src, size_t count);
+ void *safe_dma_memcpy(void *dest, const void *src, size_t count);
+
++extern int channel2irq(unsigned int channel);
++extern struct dma_register *dma_io_base_addr[MAX_BLACKFIN_DMA_CHANNEL];
++
+ #endif
+diff --git a/include/asm-blackfin/gptimers.h b/include/asm-blackfin/gptimers.h
+index 4f318f1..0520d2a 100644
+--- a/include/asm-blackfin/gptimers.h
++++ b/include/asm-blackfin/gptimers.h
+@@ -22,6 +22,18 @@
+ # define TIMER0_GROUP_REG TIMER_ENABLE
+ #endif
+ /*
++ * BF54x: 11 timers (BF542: 8 timers):
++ */
++#if defined(BF548_FAMILY)
++# ifdef CONFIG_BF542
++# define MAX_BLACKFIN_GPTIMERS 8
++# else
++# define MAX_BLACKFIN_GPTIMERS 11
++# define TIMER8_GROUP_REG TIMER_ENABLE1
++# endif
++# define TIMER0_GROUP_REG TIMER_ENABLE0
++#endif
++/*
+ * BF561: 12 timers:
+ */
+ #if defined(CONFIG_BF561)
+@@ -44,40 +56,28 @@
+ #define TIMER0bit 0x0001 /* 0001b */
+ #define TIMER1bit 0x0002 /* 0010b */
+ #define TIMER2bit 0x0004 /* 0100b */
+-
+-#if (MAX_BLACKFIN_GPTIMERS > 3)
+-# define TIMER3bit 0x0008
+-# define TIMER4bit 0x0010
+-# define TIMER5bit 0x0020
+-# define TIMER6bit 0x0040
+-# define TIMER7bit 0x0080
+-#endif
+-
+-#if (MAX_BLACKFIN_GPTIMERS > 8)
+-# define TIMER8bit 0x0100
+-# define TIMER9bit 0x0200
+-# define TIMER10bit 0x0400
+-# define TIMER11bit 0x0800
+-#endif
++#define TIMER3bit 0x0008
++#define TIMER4bit 0x0010
++#define TIMER5bit 0x0020
++#define TIMER6bit 0x0040
++#define TIMER7bit 0x0080
++#define TIMER8bit 0x0100
++#define TIMER9bit 0x0200
++#define TIMER10bit 0x0400
++#define TIMER11bit 0x0800
+
+ #define TIMER0_id 0
+ #define TIMER1_id 1
+ #define TIMER2_id 2
+-
+-#if (MAX_BLACKFIN_GPTIMERS > 3)
+-# define TIMER3_id 3
+-# define TIMER4_id 4
+-# define TIMER5_id 5
+-# define TIMER6_id 6
+-# define TIMER7_id 7
+-#endif
+-
+-#if (MAX_BLACKFIN_GPTIMERS > 8)
+-# define TIMER8_id 8
+-# define TIMER9_id 9
+-# define TIMER10_id 10
+-# define TIMER11_id 11
+-#endif
++#define TIMER3_id 3
++#define TIMER4_id 4
++#define TIMER5_id 5
++#define TIMER6_id 6
++#define TIMER7_id 7
++#define TIMER8_id 8
++#define TIMER9_id 9
++#define TIMER10_id 10
++#define TIMER11_id 11
+
+ /* associated timers for ppi framesync: */
+
+@@ -124,45 +124,31 @@
+ /*
+ * Timer Status Register Bits
+ */
+-#define TIMER_STATUS_TIMIL0 0x0001
+-#define TIMER_STATUS_TIMIL1 0x0002
+-#define TIMER_STATUS_TIMIL2 0x0004
+-#if (MAX_BLACKFIN_GPTIMERS > 3)
+-# define TIMER_STATUS_TIMIL3 0x00000008
+-# define TIMER_STATUS_TIMIL4 0x00010000
+-# define TIMER_STATUS_TIMIL5 0x00020000
+-# define TIMER_STATUS_TIMIL6 0x00040000
+-# define TIMER_STATUS_TIMIL7 0x00080000
+-# if (MAX_BLACKFIN_GPTIMERS > 8)
+-# define TIMER_STATUS_TIMIL8 0x0001
+-# define TIMER_STATUS_TIMIL9 0x0002
+-# define TIMER_STATUS_TIMIL10 0x0004
+-# define TIMER_STATUS_TIMIL11 0x0008
+-# endif
+-# define TIMER_STATUS_INTR 0x000F000F
+-#else
+-# define TIMER_STATUS_INTR 0x0007 /* any timer interrupt */
+-#endif
+-
+-#define TIMER_STATUS_TOVF0 0x0010 /* timer 0 overflow error */
+-#define TIMER_STATUS_TOVF1 0x0020
+-#define TIMER_STATUS_TOVF2 0x0040
+-#if (MAX_BLACKFIN_GPTIMERS > 3)
+-# define TIMER_STATUS_TOVF3 0x00000080
+-# define TIMER_STATUS_TOVF4 0x00100000
+-# define TIMER_STATUS_TOVF5 0x00200000
+-# define TIMER_STATUS_TOVF6 0x00400000
+-# define TIMER_STATUS_TOVF7 0x00800000
+-# if (MAX_BLACKFIN_GPTIMERS > 8)
+-# define TIMER_STATUS_TOVF8 0x0010
+-# define TIMER_STATUS_TOVF9 0x0020
+-# define TIMER_STATUS_TOVF10 0x0040
+-# define TIMER_STATUS_TOVF11 0x0080
+-# endif
+-# define TIMER_STATUS_OFLOW 0x00F000F0
+-#else
+-# define TIMER_STATUS_OFLOW 0x0070 /* any timer overflow */
+-#endif
++#define TIMER_STATUS_TIMIL0 0x0001
++#define TIMER_STATUS_TIMIL1 0x0002
++#define TIMER_STATUS_TIMIL2 0x0004
++#define TIMER_STATUS_TIMIL3 0x00000008
++#define TIMER_STATUS_TIMIL4 0x00010000
++#define TIMER_STATUS_TIMIL5 0x00020000
++#define TIMER_STATUS_TIMIL6 0x00040000
++#define TIMER_STATUS_TIMIL7 0x00080000
++#define TIMER_STATUS_TIMIL8 0x0001
++#define TIMER_STATUS_TIMIL9 0x0002
++#define TIMER_STATUS_TIMIL10 0x0004
++#define TIMER_STATUS_TIMIL11 0x0008
++
++#define TIMER_STATUS_TOVF0 0x0010 /* timer 0 overflow error */
++#define TIMER_STATUS_TOVF1 0x0020
++#define TIMER_STATUS_TOVF2 0x0040
++#define TIMER_STATUS_TOVF3 0x00000080
++#define TIMER_STATUS_TOVF4 0x00100000
++#define TIMER_STATUS_TOVF5 0x00200000
++#define TIMER_STATUS_TOVF6 0x00400000
++#define TIMER_STATUS_TOVF7 0x00800000
++#define TIMER_STATUS_TOVF8 0x0010
++#define TIMER_STATUS_TOVF9 0x0020
++#define TIMER_STATUS_TOVF10 0x0040
++#define TIMER_STATUS_TOVF11 0x0080
+
+ /*
+ * Timer Slave Enable Status : write 1 to clear
+@@ -170,22 +156,16 @@
+ #define TIMER_STATUS_TRUN0 0x1000
+ #define TIMER_STATUS_TRUN1 0x2000
+ #define TIMER_STATUS_TRUN2 0x4000
+-#if (MAX_BLACKFIN_GPTIMERS > 3)
+-# define TIMER_STATUS_TRUN3 0x00008000
+-# define TIMER_STATUS_TRUN4 0x10000000
+-# define TIMER_STATUS_TRUN5 0x20000000
+-# define TIMER_STATUS_TRUN6 0x40000000
+-# define TIMER_STATUS_TRUN7 0x80000000
+-# define TIMER_STATUS_TRUN 0xF000F000
+-# if (MAX_BLACKFIN_GPTIMERS > 8)
+-# define TIMER_STATUS_TRUN8 0x1000
+-# define TIMER_STATUS_TRUN9 0x2000
+-# define TIMER_STATUS_TRUN10 0x4000
+-# define TIMER_STATUS_TRUN11 0x8000
+-# endif
+-#else
+-# define TIMER_STATUS_TRUN 0x7000
+-#endif
++#define TIMER_STATUS_TRUN3 0x00008000
++#define TIMER_STATUS_TRUN4 0x10000000
++#define TIMER_STATUS_TRUN5 0x20000000
++#define TIMER_STATUS_TRUN6 0x40000000
++#define TIMER_STATUS_TRUN7 0x80000000
++#define TIMER_STATUS_TRUN 0xF000F000
++#define TIMER_STATUS_TRUN8 0x1000
++#define TIMER_STATUS_TRUN9 0x2000
++#define TIMER_STATUS_TRUN10 0x4000
++#define TIMER_STATUS_TRUN11 0x8000
+
+ /* The actual gptimer API */
+
+diff --git a/include/asm-blackfin/ide.h b/include/asm-blackfin/ide.h
+index 121e272..5b88de1 100644
+--- a/include/asm-blackfin/ide.h
++++ b/include/asm-blackfin/ide.h
+@@ -19,10 +19,6 @@
+
+ #define MAX_HWIFS 1
+
+-/* Legacy ... BLK_DEV_IDECS */
+-#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */
+-
+-
+ #include <asm-generic/ide_iops.h>
+
+ /****************************************************************************/
+diff --git a/include/asm-blackfin/mach-bf527/anomaly.h b/include/asm-blackfin/mach-bf527/anomaly.h
+index a891204..735fa02 100644
+--- a/include/asm-blackfin/mach-bf527/anomaly.h
++++ b/include/asm-blackfin/mach-bf527/anomaly.h
+@@ -2,12 +2,12 @@
+ * File: include/asm-blackfin/mach-bf527/anomaly.h
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+- * Copyright (C) 2004-2007 Analog Devices Inc.
++ * Copyright (C) 2004-2008 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
+ */
+
+ /* This file shoule be up to date with:
+- * - Revision A, May 30, 2007; ADSP-BF527 Blackfin Processor Anomaly List
++ * - Revision C, 01/25/2008; ADSP-BF527 Blackfin Processor Anomaly List
+ */
+
+ #ifndef _MACH_ANOMALY_H_
+@@ -15,35 +15,85 @@
+
+ /* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot2 Not Supported */
+ #define ANOMALY_05000074 (1)
+-/* DMA_RUN Bit Is Not Valid after a Peripheral Receive Channel DMA Stops */
+-#define ANOMALY_05000119 (1)
+ /* Rx.H Cannot Be Used to Access 16-bit System MMR Registers */
+ #define ANOMALY_05000122 (1)
+ /* Spurious Hardware Error from an Access in the Shadow of a Conditional Branch */
+ #define ANOMALY_05000245 (1)
+ /* Sensitivity To Noise with Slow Input Edge Rates on External SPORT TX and RX Clocks */
+ #define ANOMALY_05000265 (1)
+-/* Memory-To-Memory DMA Source/Destination Descriptors Must Be in Same Memory Space */
+-#define ANOMALY_05000301 (1)
+-/* Errors When SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */
+-#define ANOMALY_05000312 (1)
+ /* Incorrect Access of OTP_STATUS During otp_write() Function */
+ #define ANOMALY_05000328 (1)
+ /* Disallowed Configuration Prevents Subsequent Allowed Configuration on Host DMA Port */
+ #define ANOMALY_05000337 (1)
+-/* TWI Does Not Operate Correctly Under Certain Signal Termination Conditions */
++/* Ethernet MAC MDIO Reads Do Not Meet IEEE Specification */
++#define ANOMALY_05000341 (1)
++/* TWI May Not Operate Correctly Under Certain Signal Termination Conditions */
+ #define ANOMALY_05000342 (1)
+-/* Boot ROM Kernel Incorrectly Alters Reset Value of USB Register */
++/* USB Calibration Value Is Not Initialized */
++#define ANOMALY_05000346 (1)
++/* Preboot Routine Incorrectly Alters Reset Value of USB Register */
+ #define ANOMALY_05000347 (1)
++/* Security Features Are Not Functional */
++#define ANOMALY_05000348 (__SILICON_REVISION__ < 1)
++/* Regulator Programming Blocked when Hibernate Wakeup Source Remains Active */
++#define ANOMALY_05000355 (1)
++/* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */
++#define ANOMALY_05000357 (1)
++/* Incorrect Revision Number in DSPID Register */
++#define ANOMALY_05000364 (__SILICON_REVISION__ > 0)
++/* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */
++#define ANOMALY_05000366 (1)
++/* New Feature: Higher Default CCLK Rate */
++#define ANOMALY_05000368 (1)
++/* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */
++#define ANOMALY_05000371 (1)
++/* Authentication Fails To Initiate */
++#define ANOMALY_05000376 (__SILICON_REVISION__ > 0)
++/* Data Read From L3 Memory by USB DMA May be Corrupted */
++#define ANOMALY_05000380 (1)
++/* USB Full-speed Mode not Fully Tested */
++#define ANOMALY_05000381 (1)
++/* New Feature: Boot from OTP Memory */
++#define ANOMALY_05000385 (1)
++/* New Feature: bfrom_SysControl() Routine */
++#define ANOMALY_05000386 (1)
++/* New Feature: Programmable Preboot Settings */
++#define ANOMALY_05000387 (1)
++/* Reset Vector Must Not Be in SDRAM Memory Space */
++#define ANOMALY_05000389 (1)
++/* New Feature: pTempCurrent Added to ADI_BOOT_DATA Structure */
++#define ANOMALY_05000392 (1)
++/* New Feature: dTempByteCount Value Increased in ADI_BOOT_DATA Structure */
++#define ANOMALY_05000393 (1)
++/* New Feature: Log Buffer Functionality */
++#define ANOMALY_05000394 (1)
++/* New Feature: Hook Routine Functionality */
++#define ANOMALY_05000395 (1)
++/* New Feature: Header Indirect Bit */
++#define ANOMALY_05000396 (1)
++/* New Feature: BK_ONES, BK_ZEROS, and BK_DATECODE Constants */
++#define ANOMALY_05000397 (1)
++/* New Feature: SWRESET, DFRESET and WDRESET Bits Added to SYSCR Register */
++#define ANOMALY_05000398 (1)
++/* New Feature: BCODE_NOBOOT Added to BCODE Field of SYSCR Register */
++#define ANOMALY_05000399 (1)
++/* PPI Data Signals D0 and D8 do not Tristate After Disabling PPI */
++#define ANOMALY_05000401 (1)
+
+ /* Anomalies that don't exist on this proc */
+-#define ANOMALY_05000323 (0)
+-#define ANOMALY_05000244 (0)
+-#define ANOMALY_05000198 (0)
+ #define ANOMALY_05000125 (0)
+ #define ANOMALY_05000158 (0)
+-#define ANOMALY_05000273 (0)
++#define ANOMALY_05000183 (0)
++#define ANOMALY_05000198 (0)
++#define ANOMALY_05000230 (0)
++#define ANOMALY_05000244 (0)
++#define ANOMALY_05000261 (0)
+ #define ANOMALY_05000263 (0)
++#define ANOMALY_05000266 (0)
++#define ANOMALY_05000273 (0)
+ #define ANOMALY_05000311 (0)
+-#define ANOMALY_05000230 (0)
++#define ANOMALY_05000312 (0)
++#define ANOMALY_05000323 (0)
++#define ANOMALY_05000363 (0)
++
+ #endif
+diff --git a/include/asm-blackfin/mach-bf527/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf527/bfin_serial_5xx.h
+index c0694ec..f0ab273 100644
+--- a/include/asm-blackfin/mach-bf527/bfin_serial_5xx.h
++++ b/include/asm-blackfin/mach-bf527/bfin_serial_5xx.h
+@@ -1,22 +1,38 @@
++/*
++ * file: include/asm-blackfin/mach-bf527/bfin_serial_5xx.h
++ * based on:
++ * author:
++ *
++ * created:
++ * description:
++ * blackfin serial driver head file
++ * rev:
++ *
++ * modified:
++ *
++ *
++ * bugs: enter bugs at http://blackfin.uclinux.org/
++ *
++ * this program is free software; you can redistribute it and/or modify
++ * it under the terms of the gnu general public license as published by
++ * the free software foundation; either version 2, 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; see the file copying.
++ * if not, write to the free software foundation,
++ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
++ */
++
+ #include <linux/serial.h>
+ #include <asm/dma.h>
+ #include <asm/portmux.h>
+
+-#define NR_PORTS 2
+-
+-#define OFFSET_THR 0x00 /* Transmit Holding register */
+-#define OFFSET_RBR 0x00 /* Receive Buffer register */
+-#define OFFSET_DLL 0x00 /* Divisor Latch (Low-Byte) */
+-#define OFFSET_IER 0x04 /* Interrupt Enable Register */
+-#define OFFSET_DLH 0x04 /* Divisor Latch (High-Byte) */
+-#define OFFSET_IIR 0x08 /* Interrupt Identification Register */
+-#define OFFSET_LCR 0x0C /* Line Control Register */
+-#define OFFSET_MCR 0x10 /* Modem Control Register */
+-#define OFFSET_LSR 0x14 /* Line Status Register */
+-#define OFFSET_MSR 0x18 /* Modem Status Register */
+-#define OFFSET_SCR 0x1C /* SCR Scratch Register */
+-#define OFFSET_GCTL 0x24 /* Global Control Register */
+-
+ #define UART_GET_CHAR(uart) bfin_read16(((uart)->port.membase + OFFSET_RBR))
+ #define UART_GET_DLL(uart) bfin_read16(((uart)->port.membase + OFFSET_DLL))
+ #define UART_GET_IER(uart) bfin_read16(((uart)->port.membase + OFFSET_IER))
+@@ -92,7 +108,7 @@ static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
+ bfin_write16(uart->port.membase + OFFSET_LSR, -1);
+ }
+
+-struct bfin_serial_port bfin_serial_ports[NR_PORTS];
++struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
+ struct bfin_serial_res {
+ unsigned long uart_base_addr;
+ int uart_irq;
+diff --git a/include/asm-blackfin/mach-bf527/bfin_sir.h b/include/asm-blackfin/mach-bf527/bfin_sir.h
+new file mode 100644
+index 0000000..0612d0c
+--- /dev/null
++++ b/include/asm-blackfin/mach-bf527/bfin_sir.h
+@@ -0,0 +1,133 @@
++/*
++ * Blackfin Infra-red Driver
++ *
++ * Copyright 2006-2008 Analog Devices Inc.
++ *
++ * Enter bugs at http://blackfin.uclinux.org/
++ *
++ * Licensed under the GPL-2 or later.
++ *
++ */
++
++#include <linux/serial.h>
++#include <asm/dma.h>
++#include <asm/portmux.h>
++
++#define SIR_UART_GET_CHAR(port) bfin_read16((port)->membase + OFFSET_RBR)
++#define SIR_UART_GET_DLL(port) bfin_read16((port)->membase + OFFSET_DLL)
++#define SIR_UART_GET_IER(port) bfin_read16((port)->membase + OFFSET_IER)
++#define SIR_UART_GET_DLH(port) bfin_read16((port)->membase + OFFSET_DLH)
++#define SIR_UART_GET_IIR(port) bfin_read16((port)->membase + OFFSET_IIR)
++#define SIR_UART_GET_LCR(port) bfin_read16((port)->membase + OFFSET_LCR)
++#define SIR_UART_GET_GCTL(port) bfin_read16((port)->membase + OFFSET_GCTL)
++
++#define SIR_UART_PUT_CHAR(port, v) bfin_write16(((port)->membase + OFFSET_THR), v)
++#define SIR_UART_PUT_DLL(port, v) bfin_write16(((port)->membase + OFFSET_DLL), v)
++#define SIR_UART_PUT_IER(port, v) bfin_write16(((port)->membase + OFFSET_IER), v)
++#define SIR_UART_PUT_DLH(port, v) bfin_write16(((port)->membase + OFFSET_DLH), v)
++#define SIR_UART_PUT_LCR(port, v) bfin_write16(((port)->membase + OFFSET_LCR), v)
++#define SIR_UART_PUT_GCTL(port, v) bfin_write16(((port)->membase + OFFSET_GCTL), v)
++
++#ifdef CONFIG_SIR_BFIN_DMA
++struct dma_rx_buf {
++ char *buf;
++ int head;
++ int tail;
++ };
++#endif /* CONFIG_SIR_BFIN_DMA */
++
++struct bfin_sir_port {
++ unsigned char __iomem *membase;
++ unsigned int irq;
++ unsigned int lsr;
++ unsigned long clk;
++ struct net_device *dev;
++#ifdef CONFIG_SIR_BFIN_DMA
++ int tx_done;
++ struct dma_rx_buf rx_dma_buf;
++ struct timer_list rx_dma_timer;
++ int rx_dma_nrows;
++#endif /* CONFIG_SIR_BFIN_DMA */
++ unsigned int tx_dma_channel;
++ unsigned int rx_dma_channel;
++};
++
++struct bfin_sir_port sir_ports[BFIN_UART_NR_PORTS];
++
++struct bfin_sir_port_res {
++ unsigned long base_addr;
++ int irq;
++ unsigned int rx_dma_channel;
++ unsigned int tx_dma_channel;
++};
++
++struct bfin_sir_port_res bfin_sir_port_resource[] = {
++#ifdef CONFIG_BFIN_SIR0
++ {
++ 0xFFC00400,
++ IRQ_UART0_RX,
++ CH_UART0_RX,
++ CH_UART0_TX,
++ },
++#endif
++#ifdef CONFIG_BFIN_SIR1
++ {
++ 0xFFC02000,
++ IRQ_UART1_RX,
++ CH_UART1_RX,
++ CH_UART1_TX,
++ },
++#endif
++};
++
++int nr_sirs = ARRAY_SIZE(bfin_sir_port_resource);
++
++struct bfin_sir_self {
++ struct bfin_sir_port *sir_port;
++ spinlock_t lock;
++ unsigned int open;
++ int speed;
++ int newspeed;
++
++ struct sk_buff *txskb;
++ struct sk_buff *rxskb;
++ struct net_device_stats stats;
++ struct device *dev;
++ struct irlap_cb *irlap;
++ struct qos_info qos;
++
++ iobuff_t tx_buff;
++ iobuff_t rx_buff;
++
++ struct work_struct work;
++ int mtt;
++};
++
++static inline unsigned int SIR_UART_GET_LSR(struct bfin_sir_port *port)
++{
++ unsigned int lsr = bfin_read16(port->membase + OFFSET_LSR);
++ port->lsr |= (lsr & (BI|FE|PE|OE));
++ return lsr | port->lsr;
++}
++
++static inline void SIR_UART_CLEAR_LSR(struct bfin_sir_port *port)
++{
++ port->lsr = 0;
++ bfin_read16(port->membase + OFFSET_LSR);
++}
++
++#define DRIVER_NAME "bfin_sir"
++
++static void bfin_sir_hw_init(void)
++{
++#ifdef CONFIG_BFIN_SIR0
++ peripheral_request(P_UART0_TX, DRIVER_NAME);
++ peripheral_request(P_UART0_RX, DRIVER_NAME);
++#endif
++
++#ifdef CONFIG_BFIN_SIR1
++ peripheral_request(P_UART1_TX, DRIVER_NAME);
++ peripheral_request(P_UART1_RX, DRIVER_NAME);
++#endif
++ SSYNC();
++}
+diff --git a/include/asm-blackfin/mach-bf527/blackfin.h b/include/asm-blackfin/mach-bf527/blackfin.h
+index 1bd07e3..2891727 100644
+--- a/include/asm-blackfin/mach-bf527/blackfin.h
++++ b/include/asm-blackfin/mach-bf527/blackfin.h
+@@ -64,6 +64,21 @@
+ #define STATUS_P1 0x02
+ #define STATUS_P0 0x01
+
++#define BFIN_UART_NR_PORTS 2
++
++#define OFFSET_THR 0x00 /* Transmit Holding register */
++#define OFFSET_RBR 0x00 /* Receive Buffer register */
++#define OFFSET_DLL 0x00 /* Divisor Latch (Low-Byte) */
++#define OFFSET_IER 0x04 /* Interrupt Enable Register */
++#define OFFSET_DLH 0x04 /* Divisor Latch (High-Byte) */
++#define OFFSET_IIR 0x08 /* Interrupt Identification Register */
++#define OFFSET_LCR 0x0C /* Line Control Register */
++#define OFFSET_MCR 0x10 /* Modem Control Register */
++#define OFFSET_LSR 0x14 /* Line Status Register */
++#define OFFSET_MSR 0x18 /* Modem Status Register */
++#define OFFSET_SCR 0x1C /* SCR Scratch Register */
++#define OFFSET_GCTL 0x24 /* Global Control Register */
++
+ /* DPMC*/
+ #define bfin_read_STOPCK_OFF() bfin_read_STOPCK()
+ #define bfin_write_STOPCK_OFF(val) bfin_write_STOPCK(val)
+diff --git a/include/asm-blackfin/mach-bf527/cdefBF52x_base.h b/include/asm-blackfin/mach-bf527/cdefBF52x_base.h
+index 3f4de5d..9dbdbec 100644
+--- a/include/asm-blackfin/mach-bf527/cdefBF52x_base.h
++++ b/include/asm-blackfin/mach-bf527/cdefBF52x_base.h
+@@ -29,18 +29,71 @@
+ */
+
+ #ifndef _CDEF_BF52X_H
++#define _CDEF_BF52X_H
++
++#include <asm/system.h>
++#include <asm/blackfin.h>
+
+ #include "defBF52x_base.h"
+
++/* Include core specific register pointer definitions */
++#include <asm/mach-common/cdef_LPBlackfin.h>
++
+ /* ==== begin from cdefBF534.h ==== */
+
+ /* Clock and System Control (0xFFC00000 - 0xFFC000FF) */
+ #define bfin_read_PLL_CTL() bfin_read16(PLL_CTL)
+-#define bfin_write_PLL_CTL(val) bfin_write16(PLL_CTL, val)
++/* Writing to PLL_CTL initiates a PLL relock sequence. */
++static __inline__ void bfin_write_PLL_CTL(unsigned int val)
++{
++ unsigned long flags, iwr0, iwr1;
++
++ if (val == bfin_read_PLL_CTL())
++ return;
++
++ local_irq_save(flags);
++ /* Enable the PLL Wakeup bit in SIC IWR */
++ iwr0 = bfin_read32(SIC_IWR0);
++ iwr1 = bfin_read32(SIC_IWR1);
++ /* Only allow PPL Wakeup) */
++ bfin_write32(SIC_IWR0, IWR_ENABLE(0));
++ bfin_write32(SIC_IWR1, 0);
++
++ bfin_write16(PLL_CTL, val);
++ SSYNC();
++ asm("IDLE;");
++
++ bfin_write32(SIC_IWR0, iwr0);
++ bfin_write32(SIC_IWR1, iwr1);
++ local_irq_restore(flags);
++}
+ #define bfin_read_PLL_DIV() bfin_read16(PLL_DIV)
+ #define bfin_write_PLL_DIV(val) bfin_write16(PLL_DIV, val)
+ #define bfin_read_VR_CTL() bfin_read16(VR_CTL)
+-#define bfin_write_VR_CTL(val) bfin_write16(VR_CTL, val)
++/* Writing to VR_CTL initiates a PLL relock sequence. */
++static __inline__ void bfin_write_VR_CTL(unsigned int val)
++{
++ unsigned long flags, iwr0, iwr1;
++
++ if (val == bfin_read_VR_CTL())
++ return;
++
++ local_irq_save(flags);
++ /* Enable the PLL Wakeup bit in SIC IWR */
++ iwr0 = bfin_read32(SIC_IWR0);
++ iwr1 = bfin_read32(SIC_IWR1);
++ /* Only allow PPL Wakeup) */
++ bfin_write32(SIC_IWR0, IWR_ENABLE(0));
++ bfin_write32(SIC_IWR1, 0);
++
++ bfin_write16(VR_CTL, val);
++ SSYNC();
++ asm("IDLE;");
++
++ bfin_write32(SIC_IWR0, iwr0);
++ bfin_write32(SIC_IWR1, iwr1);
++ local_irq_restore(flags);
++}
+ #define bfin_read_PLL_STAT() bfin_read16(PLL_STAT)
+ #define bfin_write_PLL_STAT(val) bfin_write16(PLL_STAT, val)
+ #define bfin_read_PLL_LOCKCNT() bfin_read16(PLL_LOCKCNT)
+@@ -873,39 +926,6 @@
+
+
+ /* Two-Wire Interface (0xFFC01400 - 0xFFC014FF) */
+-#define bfin_read_TWI_CLKDIV() bfin_read16(TWI_CLKDIV)
+-#define bfin_write_TWI_CLKDIV(val) bfin_write16(TWI_CLKDIV, val)
+-#define bfin_read_TWI_CONTROL() bfin_read16(TWI_CONTROL)
+-#define bfin_write_TWI_CONTROL(val) bfin_write16(TWI_CONTROL, val)
+-#define bfin_read_TWI_SLAVE_CTL() bfin_read16(TWI_SLAVE_CTL)
+-#define bfin_write_TWI_SLAVE_CTL(val) bfin_write16(TWI_SLAVE_CTL, val)
+-#define bfin_read_TWI_SLAVE_STAT() bfin_read16(TWI_SLAVE_STAT)
+-#define bfin_write_TWI_SLAVE_STAT(val) bfin_write16(TWI_SLAVE_STAT, val)
+-#define bfin_read_TWI_SLAVE_ADDR() bfin_read16(TWI_SLAVE_ADDR)
+-#define bfin_write_TWI_SLAVE_ADDR(val) bfin_write16(TWI_SLAVE_ADDR, val)
+-#define bfin_read_TWI_MASTER_CTL() bfin_read16(TWI_MASTER_CTL)
+-#define bfin_write_TWI_MASTER_CTL(val) bfin_write16(TWI_MASTER_CTL, val)
+-#define bfin_read_TWI_MASTER_STAT() bfin_read16(TWI_MASTER_STAT)
+-#define bfin_write_TWI_MASTER_STAT(val) bfin_write16(TWI_MASTER_STAT, val)
+-#define bfin_read_TWI_MASTER_ADDR() bfin_read16(TWI_MASTER_ADDR)
+-#define bfin_write_TWI_MASTER_ADDR(val) bfin_write16(TWI_MASTER_ADDR, val)
+-#define bfin_read_TWI_INT_STAT() bfin_read16(TWI_INT_STAT)
+-#define bfin_write_TWI_INT_STAT(val) bfin_write16(TWI_INT_STAT, val)
+-#define bfin_read_TWI_INT_MASK() bfin_read16(TWI_INT_MASK)
+-#define bfin_write_TWI_INT_MASK(val) bfin_write16(TWI_INT_MASK, val)
+-#define bfin_read_TWI_FIFO_CTL() bfin_read16(TWI_FIFO_CTL)
+-#define bfin_write_TWI_FIFO_CTL(val) bfin_write16(TWI_FIFO_CTL, val)
+-#define bfin_read_TWI_FIFO_STAT() bfin_read16(TWI_FIFO_STAT)
+-#define bfin_write_TWI_FIFO_STAT(val) bfin_write16(TWI_FIFO_STAT, val)
+-#define bfin_read_TWI_XMT_DATA8() bfin_read16(TWI_XMT_DATA8)
+-#define bfin_write_TWI_XMT_DATA8(val) bfin_write16(TWI_XMT_DATA8, val)
+-#define bfin_read_TWI_XMT_DATA16() bfin_read16(TWI_XMT_DATA16)
+-#define bfin_write_TWI_XMT_DATA16(val) bfin_write16(TWI_XMT_DATA16, val)
+-#define bfin_read_TWI_RCV_DATA8() bfin_read16(TWI_RCV_DATA8)
+-#define bfin_write_TWI_RCV_DATA8(val) bfin_write16(TWI_RCV_DATA8, val)
+-#define bfin_read_TWI_RCV_DATA16() bfin_read16(TWI_RCV_DATA16)
+-#define bfin_write_TWI_RCV_DATA16(val) bfin_write16(TWI_RCV_DATA16, val)
+-
+
+ /* General Purpose I/O Port G (0xFFC01500 - 0xFFC015FF) */
+ #define bfin_read_PORTGIO() bfin_read16(PORTGIO)
+diff --git a/include/asm-blackfin/mach-bf527/dma.h b/include/asm-blackfin/mach-bf527/dma.h
+index 2dfee12..49dd693 100644
+--- a/include/asm-blackfin/mach-bf527/dma.h
++++ b/include/asm-blackfin/mach-bf527/dma.h
+@@ -59,7 +59,4 @@
+ #define CH_NFC CH_EMAC_TX /* PPI receive/transmit or NFC */
+ #endif
+
+-extern int channel2irq(unsigned int channel);
+-extern struct dma_register *base_addr[];
+-
+ #endif
+diff --git a/include/asm-blackfin/mach-bf533/anomaly.h b/include/asm-blackfin/mach-bf533/anomaly.h
+index 98209d4..5a6dcc5 100644
+--- a/include/asm-blackfin/mach-bf533/anomaly.h
++++ b/include/asm-blackfin/mach-bf533/anomaly.h
+@@ -7,7 +7,7 @@
+ */
+
+ /* This file shoule be up to date with:
+- * - Revision B, 12/10/2007; ADSP-BF531/BF532/BF533 Blackfin Processor Anomaly List
++ * - Revision C, 02/08/2008; ADSP-BF531/BF532/BF533 Blackfin Processor Anomaly List
+ */
+
+ #ifndef _MACH_ANOMALY_H_
+@@ -251,10 +251,18 @@
+ #define ANOMALY_05000206 (__SILICON_REVISION__ < 3)
+ /* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */
+ #define ANOMALY_05000357 (1)
++/* UART Break Signal Issues */
++#define ANOMALY_05000363 (__SILICON_REVISION__ < 5)
+ /* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */
+ #define ANOMALY_05000366 (1)
+ /* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */
+ #define ANOMALY_05000371 (1)
++/* PPI Does Not Start Properly In Specific Mode */
++#define ANOMALY_05000400 (__SILICON_REVISION__ == 5)
++/* SSYNC Stalls Processor when Executed from Non-Cacheable Memory */
++#define ANOMALY_05000402 (__SILICON_REVISION__ == 5)
++/* Level-Sensitive External GPIO Wakeups May Cause Indefinite Stall */
++#define ANOMALY_05000403 (1)
+
+ /* Anomalies that don't exist on this proc */
+ #define ANOMALY_05000266 (0)
+diff --git a/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h
+index b6f513b..fbe88de 100644
+--- a/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h
++++ b/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h
+@@ -1,22 +1,38 @@
++/*
++ * file: include/asm-blackfin/mach-bf533/bfin_serial_5xx.h
++ * based on:
++ * author:
++ *
++ * created:
++ * description:
++ * blackfin serial driver head file
++ * rev:
++ *
++ * modified:
++ *
++ *
++ * bugs: enter bugs at http://blackfin.uclinux.org/
++ *
++ * this program is free software; you can redistribute it and/or modify
++ * it under the terms of the gnu general public license as published by
++ * the free software foundation; either version 2, 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; see the file copying.
++ * if not, write to the free software foundation,
++ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
++ */
++
+ #include <linux/serial.h>
+ #include <asm/dma.h>
+ #include <asm/portmux.h>
+
+-#define NR_PORTS 1
+-
+-#define OFFSET_THR 0x00 /* Transmit Holding register */
+-#define OFFSET_RBR 0x00 /* Receive Buffer register */
+-#define OFFSET_DLL 0x00 /* Divisor Latch (Low-Byte) */
+-#define OFFSET_IER 0x04 /* Interrupt Enable Register */
+-#define OFFSET_DLH 0x04 /* Divisor Latch (High-Byte) */
+-#define OFFSET_IIR 0x08 /* Interrupt Identification Register */
+-#define OFFSET_LCR 0x0C /* Line Control Register */
+-#define OFFSET_MCR 0x10 /* Modem Control Register */
+-#define OFFSET_LSR 0x14 /* Line Status Register */
+-#define OFFSET_MSR 0x18 /* Modem Status Register */
+-#define OFFSET_SCR 0x1C /* SCR Scratch Register */
+-#define OFFSET_GCTL 0x24 /* Global Control Register */
+-
+ #define UART_GET_CHAR(uart) bfin_read16(((uart)->port.membase + OFFSET_RBR))
+ #define UART_GET_DLL(uart) bfin_read16(((uart)->port.membase + OFFSET_DLL))
+ #define UART_GET_IER(uart) bfin_read16(((uart)->port.membase + OFFSET_IER))
+@@ -84,7 +100,7 @@ static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
+ bfin_write16(uart->port.membase + OFFSET_LSR, -1);
+ }
+
+-struct bfin_serial_port bfin_serial_ports[NR_PORTS];
++struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
+ struct bfin_serial_res {
+ unsigned long uart_base_addr;
+ int uart_irq;
+@@ -115,7 +131,7 @@ struct bfin_serial_res bfin_serial_resource[] = {
+
+ #define DRIVER_NAME "bfin-uart"
+
+-int nr_ports = NR_PORTS;
++int nr_ports = BFIN_UART_NR_PORTS;
+ static void bfin_serial_hw_init(struct bfin_serial_port *uart)
+ {
+
+diff --git a/include/asm-blackfin/mach-bf533/bfin_sir.h b/include/asm-blackfin/mach-bf533/bfin_sir.h
+new file mode 100644
+index 0000000..cefcf8b
+--- /dev/null
++++ b/include/asm-blackfin/mach-bf533/bfin_sir.h
+@@ -0,0 +1,120 @@
++/*
++ * Blackfin Infra-red Driver
++ *
++ * Copyright 2006-2008 Analog Devices Inc.
++ *
++ * Enter bugs at http://blackfin.uclinux.org/
++ *
++ * Licensed under the GPL-2 or later.
++ *
++ */
++
++#include <linux/serial.h>
++#include <asm/dma.h>
++#include <asm/portmux.h>
++
++#define SIR_UART_GET_CHAR(port) bfin_read16((port)->membase + OFFSET_RBR)
++#define SIR_UART_GET_DLL(port) bfin_read16((port)->membase + OFFSET_DLL)
++#define SIR_UART_GET_IER(port) bfin_read16((port)->membase + OFFSET_IER)
++#define SIR_UART_GET_DLH(port) bfin_read16((port)->membase + OFFSET_DLH)
++#define SIR_UART_GET_IIR(port) bfin_read16((port)->membase + OFFSET_IIR)
++#define SIR_UART_GET_LCR(port) bfin_read16((port)->membase + OFFSET_LCR)
++#define SIR_UART_GET_GCTL(port) bfin_read16((port)->membase + OFFSET_GCTL)
++
++#define SIR_UART_PUT_CHAR(port, v) bfin_write16(((port)->membase + OFFSET_THR), v)
++#define SIR_UART_PUT_DLL(port, v) bfin_write16(((port)->membase + OFFSET_DLL), v)
++#define SIR_UART_PUT_IER(port, v) bfin_write16(((port)->membase + OFFSET_IER), v)
++#define SIR_UART_PUT_DLH(port, v) bfin_write16(((port)->membase + OFFSET_DLH), v)
++#define SIR_UART_PUT_LCR(port, v) bfin_write16(((port)->membase + OFFSET_LCR), v)
++#define SIR_UART_PUT_GCTL(port, v) bfin_write16(((port)->membase + OFFSET_GCTL), v)
++
++#ifdef CONFIG_SIR_BFIN_DMA
++struct dma_rx_buf {
++ char *buf;
++ int head;
++ int tail;
++ };
++#endif /* CONFIG_SIR_BFIN_DMA */
++
++struct bfin_sir_port {
++ unsigned char __iomem *membase;
++ unsigned int irq;
++ unsigned int lsr;
++ unsigned long clk;
++ struct net_device *dev;
++#ifdef CONFIG_SIR_BFIN_DMA
++ int tx_done;
++ struct dma_rx_buf rx_dma_buf;
++ struct timer_list rx_dma_timer;
++ int rx_dma_nrows;
++#endif /* CONFIG_SIR_BFIN_DMA */
++ unsigned int tx_dma_channel;
++ unsigned int rx_dma_channel;
++};
++
++struct bfin_sir_port sir_ports[BFIN_UART_NR_PORTS];
++
++struct bfin_sir_port_res {
++ unsigned long base_addr;
++ int irq;
++ unsigned int rx_dma_channel;
++ unsigned int tx_dma_channel;
++};
++
++struct bfin_sir_port_res bfin_sir_port_resource[] = {
++#ifdef CONFIG_BFIN_SIR0
++ {
++ 0xFFC00400,
++ IRQ_UART_RX,
++ CH_UART_RX,
++ CH_UART_TX,
++ },
++#endif
++};
++
++int nr_sirs = ARRAY_SIZE(bfin_sir_port_resource);
++
++struct bfin_sir_self {
++ struct bfin_sir_port *sir_port;
++ spinlock_t lock;
++ unsigned int open;
++ int speed;
++ int newspeed;
++
++ struct sk_buff *txskb;
++ struct sk_buff *rxskb;
++ struct net_device_stats stats;
++ struct device *dev;
++ struct irlap_cb *irlap;
++ struct qos_info qos;
++
++ iobuff_t tx_buff;
++ iobuff_t rx_buff;
++
++ struct work_struct work;
++ int mtt;
++};
++
++static inline unsigned int SIR_UART_GET_LSR(struct bfin_sir_port *port)
++{
++ unsigned int lsr = bfin_read16(port->membase + OFFSET_LSR);
++ port->lsr |= (lsr & (BI|FE|PE|OE));
++ return lsr | port->lsr;
++}
++
++static inline void SIR_UART_CLEAR_LSR(struct bfin_sir_port *port)
++{
++ port->lsr = 0;
++ bfin_read16(port->membase + OFFSET_LSR);
++}
++
++#define DRIVER_NAME "bfin_sir"
++
++static void bfin_sir_hw_init(void)
++{
++#ifdef CONFIG_BFIN_SIR0
++ peripheral_request(P_UART0_TX, DRIVER_NAME);
++ peripheral_request(P_UART0_RX, DRIVER_NAME);
++#endif
++ SSYNC();
++}
+diff --git a/include/asm-blackfin/mach-bf533/blackfin.h b/include/asm-blackfin/mach-bf533/blackfin.h
+index f3b240a..d80971b 100644
+--- a/include/asm-blackfin/mach-bf533/blackfin.h
++++ b/include/asm-blackfin/mach-bf533/blackfin.h
+@@ -42,4 +42,19 @@
+ #include "cdefBF532.h"
+ #endif
+
++#define BFIN_UART_NR_PORTS 1
++
++#define OFFSET_THR 0x00 /* Transmit Holding register */
++#define OFFSET_RBR 0x00 /* Receive Buffer register */
++#define OFFSET_DLL 0x00 /* Divisor Latch (Low-Byte) */
++#define OFFSET_IER 0x04 /* Interrupt Enable Register */
++#define OFFSET_DLH 0x04 /* Divisor Latch (High-Byte) */
++#define OFFSET_IIR 0x08 /* Interrupt Identification Register */
++#define OFFSET_LCR 0x0C /* Line Control Register */
++#define OFFSET_MCR 0x10 /* Modem Control Register */
++#define OFFSET_LSR 0x14 /* Line Status Register */
++#define OFFSET_MSR 0x18 /* Modem Status Register */
++#define OFFSET_SCR 0x1C /* SCR Scratch Register */
++#define OFFSET_GCTL 0x24 /* Global Control Register */
++
+ #endif /* _MACH_BLACKFIN_H_ */
+diff --git a/include/asm-blackfin/mach-bf533/cdefBF532.h b/include/asm-blackfin/mach-bf533/cdefBF532.h
+index c803e14..1546554 100644
+--- a/include/asm-blackfin/mach-bf533/cdefBF532.h
++++ b/include/asm-blackfin/mach-bf533/cdefBF532.h
+@@ -43,7 +43,27 @@
+
+ /* Clock and System Control (0xFFC0 0400-0xFFC0 07FF) */
+ #define bfin_read_PLL_CTL() bfin_read16(PLL_CTL)
+-#define bfin_write_PLL_CTL(val) bfin_write16(PLL_CTL,val)
++/* Writing to PLL_CTL initiates a PLL relock sequence. */
++static __inline__ void bfin_write_PLL_CTL(unsigned int val)
++{
++ unsigned long flags, iwr;
++
++ if (val == bfin_read_PLL_CTL())
++ return;
++
++ local_irq_save(flags);
++ /* Enable the PLL Wakeup bit in SIC IWR */
++ iwr = bfin_read32(SIC_IWR);
++ /* Only allow PPL Wakeup) */
++ bfin_write32(SIC_IWR, IWR_ENABLE(0));
++
++ bfin_write16(PLL_CTL, val);
++ SSYNC();
++ asm("IDLE;");
++
++ bfin_write32(SIC_IWR, iwr);
++ local_irq_restore(flags);
++}
+ #define bfin_read_PLL_STAT() bfin_read16(PLL_STAT)
+ #define bfin_write_PLL_STAT(val) bfin_write16(PLL_STAT,val)
+ #define bfin_read_PLL_LOCKCNT() bfin_read16(PLL_LOCKCNT)
+@@ -57,6 +77,10 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ {
+ unsigned long flags, iwr;
+
++ if (val == bfin_read_VR_CTL())
++ return;
++
++ local_irq_save(flags);
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr = bfin_read32(SIC_IWR);
+ /* Only allow PPL Wakeup) */
+@@ -64,11 +88,10 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+
+ bfin_write16(VR_CTL, val);
+ SSYNC();
+-
+- local_irq_save(flags);
+ asm("IDLE;");
+- local_irq_restore(flags);
++
+ bfin_write32(SIC_IWR, iwr);
++ local_irq_restore(flags);
+ }
+
+ /* System Interrupt Controller (0xFFC0 0C00-0xFFC0 0FFF) */
+diff --git a/include/asm-blackfin/mach-bf533/defBF532.h b/include/asm-blackfin/mach-bf533/defBF532.h
+index 37134aa..17e1548 100644
+--- a/include/asm-blackfin/mach-bf533/defBF532.h
++++ b/include/asm-blackfin/mach-bf533/defBF532.h
+@@ -88,20 +88,25 @@
+ #define RTC_PREN 0xFFC00314 /* RTC Prescaler Enable Register (alternate macro) */
+
+ /* UART Controller (0xFFC00400 - 0xFFC004FF) */
+-#define UART_THR 0xFFC00400 /* Transmit Holding register */
+-#define UART_RBR 0xFFC00400 /* Receive Buffer register */
+-#define UART_DLL 0xFFC00400 /* Divisor Latch (Low-Byte) */
+-#define UART_IER 0xFFC00404 /* Interrupt Enable Register */
+-#define UART_DLH 0xFFC00404 /* Divisor Latch (High-Byte) */
+-#define UART_IIR 0xFFC00408 /* Interrupt Identification Register */
+-#define UART_LCR 0xFFC0040C /* Line Control Register */
+-#define UART_MCR 0xFFC00410 /* Modem Control Register */
+-#define UART_LSR 0xFFC00414 /* Line Status Register */
++
++/*
++ * Because include/linux/serial_reg.h have defined UART_*,
++ * So we define blackfin uart regs to BFIN_UART_*.
++ */
++#define BFIN_UART_THR 0xFFC00400 /* Transmit Holding register */
++#define BFIN_UART_RBR 0xFFC00400 /* Receive Buffer register */
++#define BFIN_UART_DLL 0xFFC00400 /* Divisor Latch (Low-Byte) */
++#define BFIN_UART_IER 0xFFC00404 /* Interrupt Enable Register */
++#define BFIN_UART_DLH 0xFFC00404 /* Divisor Latch (High-Byte) */
++#define BFIN_UART_IIR 0xFFC00408 /* Interrupt Identification Register */
++#define BFIN_UART_LCR 0xFFC0040C /* Line Control Register */
++#define BFIN_UART_MCR 0xFFC00410 /* Modem Control Register */
++#define BFIN_UART_LSR 0xFFC00414 /* Line Status Register */
+ #if 0
+-#define UART_MSR 0xFFC00418 /* Modem Status Register (UNUSED in ADSP-BF532) */
++#define BFIN_UART_MSR 0xFFC00418 /* Modem Status Register (UNUSED in ADSP-BF532) */
+ #endif
+-#define UART_SCR 0xFFC0041C /* SCR Scratch Register */
+-#define UART_GCTL 0xFFC00424 /* Global Control Register */
++#define BFIN_UART_SCR 0xFFC0041C /* SCR Scratch Register */
++#define BFIN_UART_GCTL 0xFFC00424 /* Global Control Register */
+
+ /* SPI Controller (0xFFC00500 - 0xFFC005FF) */
+ #define SPI0_REGBASE 0xFFC00500
+diff --git a/include/asm-blackfin/mach-bf533/dma.h b/include/asm-blackfin/mach-bf533/dma.h
+index 16c672c..bd9d5e9 100644
+--- a/include/asm-blackfin/mach-bf533/dma.h
++++ b/include/asm-blackfin/mach-bf533/dma.h
+@@ -51,7 +51,4 @@
+ #define CH_MEM_STREAM1_DEST 10 /* TX */
+ #define CH_MEM_STREAM1_SRC 11 /* RX */
+
+-extern int channel2irq(unsigned int channel);
+-extern struct dma_register *base_addr[];
+-
+ #endif
+diff --git a/include/asm-blackfin/mach-bf533/mem_init.h b/include/asm-blackfin/mach-bf533/mem_init.h
+index 1620dae..f8f3190 100644
+--- a/include/asm-blackfin/mach-bf533/mem_init.h
++++ b/include/asm-blackfin/mach-bf533/mem_init.h
+@@ -29,7 +29,8 @@
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+-#if (CONFIG_MEM_MT48LC16M16A2TG_75 || CONFIG_MEM_MT48LC64M4A2FB_7E || CONFIG_MEM_GENERIC_BOARD)
++#if (CONFIG_MEM_MT48LC16M16A2TG_75 || CONFIG_MEM_MT48LC64M4A2FB_7E || \
++ CONFIG_MEM_MT48LC32M16A2TG_75 || CONFIG_MEM_GENERIC_BOARD)
+ #if (CONFIG_SCLK_HZ > 119402985)
+ #define SDRAM_tRP TRP_2
+ #define SDRAM_tRP_num 2
+@@ -118,6 +119,13 @@
+ #define SDRAM_CL CL_3
+ #endif
+
++#if (CONFIG_MEM_MT48LC32M16A2TG_75)
++ /*SDRAM INFORMATION: */
++#define SDRAM_Tref 64 /* Refresh period in milliseconds */
++#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */
++#define SDRAM_CL CL_3
++#endif
++
+ #if (CONFIG_MEM_GENERIC_BOARD)
+ /*SDRAM INFORMATION: Modify this for your board */
+ #define SDRAM_Tref 64 /* Refresh period in milliseconds */
+diff --git a/include/asm-blackfin/mach-bf537/anomaly.h b/include/asm-blackfin/mach-bf537/anomaly.h
+index 746a794..a6b08fa 100644
+--- a/include/asm-blackfin/mach-bf537/anomaly.h
++++ b/include/asm-blackfin/mach-bf537/anomaly.h
+@@ -7,7 +7,7 @@
+ */
+
+ /* This file shoule be up to date with:
+- * - Revision A, 09/04/2007; ADSP-BF534/ADSP-BF536/ADSP-BF537 Blackfin Processor Anomaly List
++ * - Revision C, 02/08/2008; ADSP-BF534/ADSP-BF536/ADSP-BF537 Blackfin Processor Anomaly List
+ */
+
+ #ifndef _MACH_ANOMALY_H_
+@@ -132,10 +132,24 @@
+ #define ANOMALY_05000322 (1)
+ /* Ethernet MAC MDIO Reads Do Not Meet IEEE Specification */
+ #define ANOMALY_05000341 (__SILICON_REVISION__ >= 3)
++/* New Feature: UART Remains Enabled after UART Boot (Not Available on Older Silicon) */
++#define ANOMALY_05000350 (__SILICON_REVISION__ < 3)
++/* Regulator Programming Blocked when Hibernate Wakeup Source Remains Active */
++#define ANOMALY_05000355 (1)
+ /* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */
+ #define ANOMALY_05000357 (1)
+ /* DMAs that Go Urgent during Tight Core Writes to External Memory Are Blocked */
+ #define ANOMALY_05000359 (1)
++/* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */
++#define ANOMALY_05000366 (1)
++/* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */
++#define ANOMALY_05000371 (1)
++/* SSYNC Stalls Processor when Executed from Non-Cacheable Memory */
++#define ANOMALY_05000402 (__SILICON_REVISION__ >= 3)
++/* Level-Sensitive External GPIO Wakeups May Cause Indefinite Stall */
++#define ANOMALY_05000403 (1)
++
++
+
+ /* Anomalies that don't exist on this proc */
+ #define ANOMALY_05000125 (0)
+@@ -146,5 +160,6 @@
+ #define ANOMALY_05000266 (0)
+ #define ANOMALY_05000311 (0)
+ #define ANOMALY_05000323 (0)
++#define ANOMALY_05000363 (0)
+
+ #endif
+diff --git a/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h
+index 8fc672d..fd100a4 100644
+--- a/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h
++++ b/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h
+@@ -1,22 +1,38 @@
++/*
++ * file: include/asm-blackfin/mach-bf537/bfin_serial_5xx.h
++ * based on:
++ * author:
++ *
++ * created:
++ * description:
++ * blackfin serial driver header files
++ * rev:
++ *
++ * modified:
++ *
++ *
++ * bugs: enter bugs at http://blackfin.uclinux.org/
++ *
++ * this program is free software; you can redistribute it and/or modify
++ * it under the terms of the gnu general public license as published by
++ * the free software foundation; either version 2, 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; see the file copying.
++ * if not, write to the free software foundation,
++ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
++ */
++
+ #include <linux/serial.h>
+ #include <asm/dma.h>
+ #include <asm/portmux.h>
+
+-#define NR_PORTS 2
+-
+-#define OFFSET_THR 0x00 /* Transmit Holding register */
+-#define OFFSET_RBR 0x00 /* Receive Buffer register */
+-#define OFFSET_DLL 0x00 /* Divisor Latch (Low-Byte) */
+-#define OFFSET_IER 0x04 /* Interrupt Enable Register */
+-#define OFFSET_DLH 0x04 /* Divisor Latch (High-Byte) */
+-#define OFFSET_IIR 0x08 /* Interrupt Identification Register */
+-#define OFFSET_LCR 0x0C /* Line Control Register */
+-#define OFFSET_MCR 0x10 /* Modem Control Register */
+-#define OFFSET_LSR 0x14 /* Line Status Register */
+-#define OFFSET_MSR 0x18 /* Modem Status Register */
+-#define OFFSET_SCR 0x1C /* SCR Scratch Register */
+-#define OFFSET_GCTL 0x24 /* Global Control Register */
+-
+ #define UART_GET_CHAR(uart) bfin_read16(((uart)->port.membase + OFFSET_RBR))
+ #define UART_GET_DLL(uart) bfin_read16(((uart)->port.membase + OFFSET_DLL))
+ #define UART_GET_IER(uart) bfin_read16(((uart)->port.membase + OFFSET_IER))
+@@ -92,7 +108,7 @@ static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
+ bfin_write16(uart->port.membase + OFFSET_LSR, -1);
+ }
+
+-struct bfin_serial_port bfin_serial_ports[NR_PORTS];
++struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
+ struct bfin_serial_res {
+ unsigned long uart_base_addr;
+ int uart_irq;
+diff --git a/include/asm-blackfin/mach-bf537/bfin_sir.h b/include/asm-blackfin/mach-bf537/bfin_sir.h
+new file mode 100644
+index 0000000..0612d0c
+--- /dev/null
++++ b/include/asm-blackfin/mach-bf537/bfin_sir.h
+@@ -0,0 +1,133 @@
++/*
++ * Blackfin Infra-red Driver
++ *
++ * Copyright 2006-2008 Analog Devices Inc.
++ *
++ * Enter bugs at http://blackfin.uclinux.org/
++ *
++ * Licensed under the GPL-2 or later.
++ *
++ */
++
++#include <linux/serial.h>
++#include <asm/dma.h>
++#include <asm/portmux.h>
++
++#define SIR_UART_GET_CHAR(port) bfin_read16((port)->membase + OFFSET_RBR)
++#define SIR_UART_GET_DLL(port) bfin_read16((port)->membase + OFFSET_DLL)
++#define SIR_UART_GET_IER(port) bfin_read16((port)->membase + OFFSET_IER)
++#define SIR_UART_GET_DLH(port) bfin_read16((port)->membase + OFFSET_DLH)
++#define SIR_UART_GET_IIR(port) bfin_read16((port)->membase + OFFSET_IIR)
++#define SIR_UART_GET_LCR(port) bfin_read16((port)->membase + OFFSET_LCR)
++#define SIR_UART_GET_GCTL(port) bfin_read16((port)->membase + OFFSET_GCTL)
++
++#define SIR_UART_PUT_CHAR(port, v) bfin_write16(((port)->membase + OFFSET_THR), v)
++#define SIR_UART_PUT_DLL(port, v) bfin_write16(((port)->membase + OFFSET_DLL), v)
++#define SIR_UART_PUT_IER(port, v) bfin_write16(((port)->membase + OFFSET_IER), v)
++#define SIR_UART_PUT_DLH(port, v) bfin_write16(((port)->membase + OFFSET_DLH), v)
++#define SIR_UART_PUT_LCR(port, v) bfin_write16(((port)->membase + OFFSET_LCR), v)
++#define SIR_UART_PUT_GCTL(port, v) bfin_write16(((port)->membase + OFFSET_GCTL), v)
++
++#ifdef CONFIG_SIR_BFIN_DMA
++struct dma_rx_buf {
++ char *buf;
++ int head;
++ int tail;
++ };
++#endif /* CONFIG_SIR_BFIN_DMA */
++
++struct bfin_sir_port {
++ unsigned char __iomem *membase;
++ unsigned int irq;
++ unsigned int lsr;
++ unsigned long clk;
++ struct net_device *dev;
++#ifdef CONFIG_SIR_BFIN_DMA
++ int tx_done;
++ struct dma_rx_buf rx_dma_buf;
++ struct timer_list rx_dma_timer;
++ int rx_dma_nrows;
++#endif /* CONFIG_SIR_BFIN_DMA */
++ unsigned int tx_dma_channel;
++ unsigned int rx_dma_channel;
++};
++
++struct bfin_sir_port sir_ports[BFIN_UART_NR_PORTS];
++
++struct bfin_sir_port_res {
++ unsigned long base_addr;
++ int irq;
++ unsigned int rx_dma_channel;
++ unsigned int tx_dma_channel;
++};
++
++struct bfin_sir_port_res bfin_sir_port_resource[] = {
++#ifdef CONFIG_BFIN_SIR0
++ {
++ 0xFFC00400,
++ IRQ_UART0_RX,
++ CH_UART0_RX,
++ CH_UART0_TX,
++ },
++#endif
++#ifdef CONFIG_BFIN_SIR1
++ {
++ 0xFFC02000,
++ IRQ_UART1_RX,
++ CH_UART1_RX,
++ CH_UART1_TX,
++ },
++#endif
++};
++
++int nr_sirs = ARRAY_SIZE(bfin_sir_port_resource);
++
++struct bfin_sir_self {
++ struct bfin_sir_port *sir_port;
++ spinlock_t lock;
++ unsigned int open;
++ int speed;
++ int newspeed;
++
++ struct sk_buff *txskb;
++ struct sk_buff *rxskb;
++ struct net_device_stats stats;
++ struct device *dev;
++ struct irlap_cb *irlap;
++ struct qos_info qos;
++
++ iobuff_t tx_buff;
++ iobuff_t rx_buff;
++
++ struct work_struct work;
++ int mtt;
++};
++
++static inline unsigned int SIR_UART_GET_LSR(struct bfin_sir_port *port)
++{
++ unsigned int lsr = bfin_read16(port->membase + OFFSET_LSR);
++ port->lsr |= (lsr & (BI|FE|PE|OE));
++ return lsr | port->lsr;
++}
++
++static inline void SIR_UART_CLEAR_LSR(struct bfin_sir_port *port)
++{
++ port->lsr = 0;
++ bfin_read16(port->membase + OFFSET_LSR);
++}
++
++#define DRIVER_NAME "bfin_sir"
++
++static void bfin_sir_hw_init(void)
++{
++#ifdef CONFIG_BFIN_SIR0
++ peripheral_request(P_UART0_TX, DRIVER_NAME);
++ peripheral_request(P_UART0_RX, DRIVER_NAME);
++#endif
++
++#ifdef CONFIG_BFIN_SIR1
++ peripheral_request(P_UART1_TX, DRIVER_NAME);
++ peripheral_request(P_UART1_RX, DRIVER_NAME);
++#endif
++ SSYNC();
++}
+diff --git a/include/asm-blackfin/mach-bf537/blackfin.h b/include/asm-blackfin/mach-bf537/blackfin.h
+index 53fcfa3..cffc786 100644
+--- a/include/asm-blackfin/mach-bf537/blackfin.h
++++ b/include/asm-blackfin/mach-bf537/blackfin.h
+@@ -82,8 +82,6 @@
+ #define STATUS_P1 0x02
+ #define STATUS_P0 0x01
+
+-/* UART 0*/
+-
+ /* DMA Channnel */
+ #define bfin_read_CH_UART_RX() bfin_read_CH_UART0_RX()
+ #define bfin_write_CH_UART_RX(val) bfin_write_CH_UART0_RX(val)
+@@ -106,37 +104,52 @@
+ /* MMR Registers*/
+ #define bfin_read_UART_THR() bfin_read_UART0_THR()
+ #define bfin_write_UART_THR(val) bfin_write_UART0_THR(val)
+-#define UART_THR UART0_THR
++#define BFIN_UART_THR UART0_THR
+ #define bfin_read_UART_RBR() bfin_read_UART0_RBR()
+ #define bfin_write_UART_RBR(val) bfin_write_UART0_RBR(val)
+-#define UART_RBR UART0_RBR
++#define BFIN_UART_RBR UART0_RBR
+ #define bfin_read_UART_DLL() bfin_read_UART0_DLL()
+ #define bfin_write_UART_DLL(val) bfin_write_UART0_DLL(val)
+-#define UART_DLL UART0_DLL
++#define BFIN_UART_DLL UART0_DLL
+ #define bfin_read_UART_IER() bfin_read_UART0_IER()
+ #define bfin_write_UART_IER(val) bfin_write_UART0_IER(val)
+-#define UART_IER UART0_IER
++#define BFIN_UART_IER UART0_IER
+ #define bfin_read_UART_DLH() bfin_read_UART0_DLH()
+ #define bfin_write_UART_DLH(val) bfin_write_UART0_DLH(val)
+-#define UART_DLH UART0_DLH
++#define BFIN_UART_DLH UART0_DLH
+ #define bfin_read_UART_IIR() bfin_read_UART0_IIR()
+ #define bfin_write_UART_IIR(val) bfin_write_UART0_IIR(val)
+-#define UART_IIR UART0_IIR
++#define BFIN_UART_IIR UART0_IIR
+ #define bfin_read_UART_LCR() bfin_read_UART0_LCR()
+ #define bfin_write_UART_LCR(val) bfin_write_UART0_LCR(val)
+-#define UART_LCR UART0_LCR
++#define BFIN_UART_LCR UART0_LCR
+ #define bfin_read_UART_MCR() bfin_read_UART0_MCR()
+ #define bfin_write_UART_MCR(val) bfin_write_UART0_MCR(val)
+-#define UART_MCR UART0_MCR
++#define BFIN_UART_MCR UART0_MCR
+ #define bfin_read_UART_LSR() bfin_read_UART0_LSR()
+ #define bfin_write_UART_LSR(val) bfin_write_UART0_LSR(val)
+-#define UART_LSR UART0_LSR
++#define BFIN_UART_LSR UART0_LSR
+ #define bfin_read_UART_SCR() bfin_read_UART0_SCR()
+ #define bfin_write_UART_SCR(val) bfin_write_UART0_SCR(val)
+-#define UART_SCR UART0_SCR
++#define BFIN_UART_SCR UART0_SCR
+ #define bfin_read_UART_GCTL() bfin_read_UART0_GCTL()
+ #define bfin_write_UART_GCTL(val) bfin_write_UART0_GCTL(val)
+-#define UART_GCTL UART0_GCTL
++#define BFIN_UART_GCTL UART0_GCTL
++
++#define BFIN_UART_NR_PORTS 2
++
++#define OFFSET_THR 0x00 /* Transmit Holding register */
++#define OFFSET_RBR 0x00 /* Receive Buffer register */
++#define OFFSET_DLL 0x00 /* Divisor Latch (Low-Byte) */
++#define OFFSET_IER 0x04 /* Interrupt Enable Register */
++#define OFFSET_DLH 0x04 /* Divisor Latch (High-Byte) */
++#define OFFSET_IIR 0x08 /* Interrupt Identification Register */
++#define OFFSET_LCR 0x0C /* Line Control Register */
++#define OFFSET_MCR 0x10 /* Modem Control Register */
++#define OFFSET_LSR 0x14 /* Line Status Register */
++#define OFFSET_MSR 0x18 /* Modem Status Register */
++#define OFFSET_SCR 0x1C /* SCR Scratch Register */
++#define OFFSET_GCTL 0x24 /* Global Control Register */
+
+ /* DPMC*/
+ #define bfin_read_STOPCK_OFF() bfin_read_STOPCK()
+diff --git a/include/asm-blackfin/mach-bf537/cdefBF534.h b/include/asm-blackfin/mach-bf537/cdefBF534.h
+index 78227bc..82de526 100644
+--- a/include/asm-blackfin/mach-bf537/cdefBF534.h
++++ b/include/asm-blackfin/mach-bf537/cdefBF534.h
+@@ -44,7 +44,27 @@
+
+ /* Clock and System Control (0xFFC00000 - 0xFFC000FF) */
+ #define bfin_read_PLL_CTL() bfin_read16(PLL_CTL)
+-#define bfin_write_PLL_CTL(val) bfin_write16(PLL_CTL,val)
++/* Writing to PLL_CTL initiates a PLL relock sequence. */
++static __inline__ void bfin_write_PLL_CTL(unsigned int val)
++{
++ unsigned long flags, iwr;
++
++ if (val == bfin_read_PLL_CTL())
++ return;
++
++ local_irq_save(flags);
++ /* Enable the PLL Wakeup bit in SIC IWR */
++ iwr = bfin_read32(SIC_IWR);
++ /* Only allow PPL Wakeup) */
++ bfin_write32(SIC_IWR, IWR_ENABLE(0));
++
++ bfin_write16(PLL_CTL, val);
++ SSYNC();
++ asm("IDLE;");
++
++ bfin_write32(SIC_IWR, iwr);
++ local_irq_restore(flags);
++}
+ #define bfin_read_PLL_DIV() bfin_read16(PLL_DIV)
+ #define bfin_write_PLL_DIV(val) bfin_write16(PLL_DIV,val)
+ #define bfin_read_VR_CTL() bfin_read16(VR_CTL)
+@@ -53,6 +73,10 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ {
+ unsigned long flags, iwr;
+
++ if (val == bfin_read_VR_CTL())
++ return;
++
++ local_irq_save(flags);
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr = bfin_read32(SIC_IWR);
+ /* Only allow PPL Wakeup) */
+@@ -60,11 +84,10 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+
+ bfin_write16(VR_CTL, val);
+ SSYNC();
+-
+- local_irq_save(flags);
+ asm("IDLE;");
+- local_irq_restore(flags);
++
+ bfin_write32(SIC_IWR, iwr);
++ local_irq_restore(flags);
+ }
+ #define bfin_read_PLL_STAT() bfin_read16(PLL_STAT)
+ #define bfin_write_PLL_STAT(val) bfin_write16(PLL_STAT,val)
+@@ -858,39 +881,7 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ #define bfin_read_PPI_FRAME() bfin_read16(PPI_FRAME)
+ #define bfin_write_PPI_FRAME(val) bfin_write16(PPI_FRAME,val)
+
+-/* Two-Wire Interface (0xFFC01400 - 0xFFC014FF) */
+-#define bfin_read_TWI_CLKDIV() bfin_read16(TWI_CLKDIV)
+-#define bfin_write_TWI_CLKDIV(val) bfin_write16(TWI_CLKDIV,val)
+-#define bfin_read_TWI_CONTROL() bfin_read16(TWI_CONTROL)
+-#define bfin_write_TWI_CONTROL(val) bfin_write16(TWI_CONTROL,val)
+-#define bfin_read_TWI_SLAVE_CTL() bfin_read16(TWI_SLAVE_CTL)
+-#define bfin_write_TWI_SLAVE_CTL(val) bfin_write16(TWI_SLAVE_CTL,val)
+-#define bfin_read_TWI_SLAVE_STAT() bfin_read16(TWI_SLAVE_STAT)
+-#define bfin_write_TWI_SLAVE_STAT(val) bfin_write16(TWI_SLAVE_STAT,val)
+-#define bfin_read_TWI_SLAVE_ADDR() bfin_read16(TWI_SLAVE_ADDR)
+-#define bfin_write_TWI_SLAVE_ADDR(val) bfin_write16(TWI_SLAVE_ADDR,val)
+-#define bfin_read_TWI_MASTER_CTL() bfin_read16(TWI_MASTER_CTL)
+-#define bfin_write_TWI_MASTER_CTL(val) bfin_write16(TWI_MASTER_CTL,val)
+-#define bfin_read_TWI_MASTER_STAT() bfin_read16(TWI_MASTER_STAT)
+-#define bfin_write_TWI_MASTER_STAT(val) bfin_write16(TWI_MASTER_STAT,val)
+-#define bfin_read_TWI_MASTER_ADDR() bfin_read16(TWI_MASTER_ADDR)
+-#define bfin_write_TWI_MASTER_ADDR(val) bfin_write16(TWI_MASTER_ADDR,val)
+-#define bfin_read_TWI_INT_STAT() bfin_read16(TWI_INT_STAT)
+-#define bfin_write_TWI_INT_STAT(val) bfin_write16(TWI_INT_STAT,val)
+-#define bfin_read_TWI_INT_MASK() bfin_read16(TWI_INT_MASK)
+-#define bfin_write_TWI_INT_MASK(val) bfin_write16(TWI_INT_MASK,val)
+-#define bfin_read_TWI_FIFO_CTL() bfin_read16(TWI_FIFO_CTL)
+-#define bfin_write_TWI_FIFO_CTL(val) bfin_write16(TWI_FIFO_CTL,val)
+-#define bfin_read_TWI_FIFO_STAT() bfin_read16(TWI_FIFO_STAT)
+-#define bfin_write_TWI_FIFO_STAT(val) bfin_write16(TWI_FIFO_STAT,val)
+-#define bfin_read_TWI_XMT_DATA8() bfin_read16(TWI_XMT_DATA8)
+-#define bfin_write_TWI_XMT_DATA8(val) bfin_write16(TWI_XMT_DATA8,val)
+-#define bfin_read_TWI_XMT_DATA16() bfin_read16(TWI_XMT_DATA16)
+-#define bfin_write_TWI_XMT_DATA16(val) bfin_write16(TWI_XMT_DATA16,val)
+-#define bfin_read_TWI_RCV_DATA8() bfin_read16(TWI_RCV_DATA8)
+-#define bfin_write_TWI_RCV_DATA8(val) bfin_write16(TWI_RCV_DATA8,val)
+-#define bfin_read_TWI_RCV_DATA16() bfin_read16(TWI_RCV_DATA16)
+-#define bfin_write_TWI_RCV_DATA16(val) bfin_write16(TWI_RCV_DATA16,val)
++/* Two-Wire Interface (0xFFC01400 - 0xFFC014FF) */
+
+ /* General Purpose I/O Port G (0xFFC01500 - 0xFFC015FF) */
+ #define bfin_read_PORTGIO() bfin_read16(PORTGIO)
+diff --git a/include/asm-blackfin/mach-bf537/dma.h b/include/asm-blackfin/mach-bf537/dma.h
+index 0219919..7a96404 100644
+--- a/include/asm-blackfin/mach-bf537/dma.h
++++ b/include/asm-blackfin/mach-bf537/dma.h
+@@ -52,7 +52,4 @@
+ #define CH_MEM_STREAM1_DEST 14 /* TX */
+ #define CH_MEM_STREAM1_SRC 15 /* RX */
+
+-extern int channel2irq(unsigned int channel);
+-extern struct dma_register *base_addr[];
+-
+ #endif
+diff --git a/include/asm-blackfin/mach-bf548/anomaly.h b/include/asm-blackfin/mach-bf548/anomaly.h
+index 850dc12..49d3ceb 100644
+--- a/include/asm-blackfin/mach-bf548/anomaly.h
++++ b/include/asm-blackfin/mach-bf548/anomaly.h
+@@ -93,5 +93,6 @@
+ #define ANOMALY_05000273 (0)
+ #define ANOMALY_05000311 (0)
+ #define ANOMALY_05000323 (0)
++#define ANOMALY_05000363 (0)
+
+ #endif
+diff --git a/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h
+index 7e6339f..6547027 100644
+--- a/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h
++++ b/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h
+@@ -1,22 +1,38 @@
++/*
++ * file: include/asm-blackfin/mach-bf548/bfin_serial_5xx.h
++ * based on:
++ * author:
++ *
++ * created:
++ * description:
++ * blackfin serial driver head file
++ * rev:
++ *
++ * modified:
++ *
++ *
++ * bugs: enter bugs at http://blackfin.uclinux.org/
++ *
++ * this program is free software; you can redistribute it and/or modify
++ * it under the terms of the gnu general public license as published by
++ * the free software foundation; either version 2, 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; see the file copying.
++ * if not, write to the free software foundation,
++ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
++ */
++
+ #include <linux/serial.h>
+ #include <asm/dma.h>
+ #include <asm/portmux.h>
+
+-#define NR_PORTS 4
+-
+-#define OFFSET_DLL 0x00 /* Divisor Latch (Low-Byte) */
+-#define OFFSET_DLH 0x04 /* Divisor Latch (High-Byte) */
+-#define OFFSET_GCTL 0x08 /* Global Control Register */
+-#define OFFSET_LCR 0x0C /* Line Control Register */
+-#define OFFSET_MCR 0x10 /* Modem Control Register */
+-#define OFFSET_LSR 0x14 /* Line Status Register */
+-#define OFFSET_MSR 0x18 /* Modem Status Register */
+-#define OFFSET_SCR 0x1C /* SCR Scratch Register */
+-#define OFFSET_IER_SET 0x20 /* Set Interrupt Enable Register */
+-#define OFFSET_IER_CLEAR 0x24 /* Clear Interrupt Enable Register */
+-#define OFFSET_THR 0x28 /* Transmit Holding register */
+-#define OFFSET_RBR 0x2C /* Receive Buffer register */
+-
+ #define UART_GET_CHAR(uart) bfin_read16(((uart)->port.membase + OFFSET_RBR))
+ #define UART_GET_DLL(uart) bfin_read16(((uart)->port.membase + OFFSET_DLL))
+ #define UART_GET_DLH(uart) bfin_read16(((uart)->port.membase + OFFSET_DLH))
+@@ -80,7 +96,7 @@ struct bfin_serial_port {
+ #endif
+ };
+
+-struct bfin_serial_port bfin_serial_ports[NR_PORTS];
++struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
+ struct bfin_serial_res {
+ unsigned long uart_base_addr;
+ int uart_irq;
+diff --git a/include/asm-blackfin/mach-bf548/bfin_sir.h b/include/asm-blackfin/mach-bf548/bfin_sir.h
+new file mode 100644
+index 0000000..5e94271
+--- /dev/null
++++ b/include/asm-blackfin/mach-bf548/bfin_sir.h
+@@ -0,0 +1,149 @@
++/*
++ * Blackfin Infra-red Driver
++ *
++ * Copyright 2006-2008 Analog Devices Inc.
++ *
++ * Enter bugs at http://blackfin.uclinux.org/
++ *
++ * Licensed under the GPL-2 or later.
++ *
++ */
++
++#include <linux/serial.h>
++#include <asm/dma.h>
++#include <asm/portmux.h>
++
++#define SIR_UART_GET_CHAR(port) bfin_read16((port)->membase + OFFSET_RBR)
++#define SIR_UART_GET_DLL(port) bfin_read16((port)->membase + OFFSET_DLL)
++#define SIR_UART_GET_IER(port) bfin_read16((port)->membase + OFFSET_IER_SET)
++#define SIR_UART_GET_DLH(port) bfin_read16((port)->membase + OFFSET_DLH)
++#define SIR_UART_GET_LCR(port) bfin_read16((port)->membase + OFFSET_LCR)
++#define SIR_UART_GET_LSR(port) bfin_read16((port)->membase + OFFSET_LSR)
++#define SIR_UART_GET_GCTL(port) bfin_read16((port)->membase + OFFSET_GCTL)
++
++#define SIR_UART_PUT_CHAR(port, v) bfin_write16(((port)->membase + OFFSET_THR), v)
++#define SIR_UART_PUT_DLL(port, v) bfin_write16(((port)->membase + OFFSET_DLL), v)
++#define SIR_UART_SET_IER(port, v) bfin_write16(((port)->membase + OFFSET_IER_SET), v)
++#define SIR_UART_CLEAR_IER(port, v) bfin_write16(((port)->membase + OFFSET_IER_CLEAR), v)
++#define SIR_UART_PUT_DLH(port, v) bfin_write16(((port)->membase + OFFSET_DLH), v)
++#define SIR_UART_PUT_LSR(port, v) bfin_write16(((port)->membase + OFFSET_LSR), v)
++#define SIR_UART_PUT_LCR(port, v) bfin_write16(((port)->membase + OFFSET_LCR), v)
++#define SIR_UART_CLEAR_LSR(port) bfin_write16(((port)->membase + OFFSET_LSR), -1)
++#define SIR_UART_PUT_GCTL(port, v) bfin_write16(((port)->membase + OFFSET_GCTL), v)
++
++#ifdef CONFIG_SIR_BFIN_DMA
++struct dma_rx_buf {
++ char *buf;
++ int head;
++ int tail;
++ };
++#endif /* CONFIG_SIR_BFIN_DMA */
++
++struct bfin_sir_port {
++ unsigned char __iomem *membase;
++ unsigned int irq;
++ unsigned int lsr;
++ unsigned long clk;
++ struct net_device *dev;
++#ifdef CONFIG_SIR_BFIN_DMA
++ int tx_done;
++ struct dma_rx_buf rx_dma_buf;
++ struct timer_list rx_dma_timer;
++ int rx_dma_nrows;
++#endif /* CONFIG_SIR_BFIN_DMA */
++ unsigned int tx_dma_channel;
++ unsigned int rx_dma_channel;
++};
++
++struct bfin_sir_port sir_ports[BFIN_UART_NR_PORTS];
++
++struct bfin_sir_port_res {
++ unsigned long base_addr;
++ int irq;
++ unsigned int rx_dma_channel;
++ unsigned int tx_dma_channel;
++};
++
++struct bfin_sir_port_res bfin_sir_port_resource[] = {
++#ifdef CONFIG_BFIN_SIR0
++ {
++ 0xFFC00400,
++ IRQ_UART0_RX,
++ CH_UART0_RX,
++ CH_UART0_TX,
++ },
++#endif
++#ifdef CONFIG_BFIN_SIR1
++ {
++ 0xFFC02000,
++ IRQ_UART1_RX,
++ CH_UART1_RX,
++ CH_UART1_TX,
++ },
++#endif
++#ifdef CONFIG_BFIN_SIR2
++ {
++ 0xFFC02100,
++ IRQ_UART2_RX,
++ CH_UART2_RX,
++ CH_UART2_TX,
++ },
++#endif
++#ifdef CONFIG_BFIN_SIR3
++ {
++ 0xFFC03100,
++ IRQ_UART3_RX,
++ CH_UART3_RX,
++ CH_UART3_TX,
++ },
++#endif
++};
++
++int nr_sirs = ARRAY_SIZE(bfin_sir_port_resource);
++
++struct bfin_sir_self {
++ struct bfin_sir_port *sir_port;
++ spinlock_t lock;
++ unsigned int open;
++ int speed;
++ int newspeed;
++
++ struct sk_buff *txskb;
++ struct sk_buff *rxskb;
++ struct net_device_stats stats;
++ struct device *dev;
++ struct irlap_cb *irlap;
++ struct qos_info qos;
++
++ iobuff_t tx_buff;
++ iobuff_t rx_buff;
++
++ struct work_struct work;
++ int mtt;
++};
++
++#define DRIVER_NAME "bfin_sir"
++
++static void bfin_sir_hw_init(void)
++{
++#ifdef CONFIG_BFIN_SIR0
++ peripheral_request(P_UART0_TX, DRIVER_NAME);
++ peripheral_request(P_UART0_RX, DRIVER_NAME);
++#endif
++
++#ifdef CONFIG_BFIN_SIR1
++ peripheral_request(P_UART1_TX, DRIVER_NAME);
++ peripheral_request(P_UART1_RX, DRIVER_NAME);
++#endif
++
++#ifdef CONFIG_BFIN_SIR2
++ peripheral_request(P_UART2_TX, DRIVER_NAME);
++ peripheral_request(P_UART2_RX, DRIVER_NAME);
++#endif
++
++#ifdef CONFIG_BFIN_SIR3
++ peripheral_request(P_UART3_TX, DRIVER_NAME);
++ peripheral_request(P_UART3_RX, DRIVER_NAME);
++#endif
++ SSYNC();
++}
+diff --git a/include/asm-blackfin/mach-bf548/blackfin.h b/include/asm-blackfin/mach-bf548/blackfin.h
+index 3bd67da..d6ee74a 100644
+--- a/include/asm-blackfin/mach-bf548/blackfin.h
++++ b/include/asm-blackfin/mach-bf548/blackfin.h
+@@ -153,17 +153,33 @@
+ #define bfin_write_UART_SCR(val) bfin_write_UART1_SCR(val)
+ #define bfin_read_UART_GCTL() bfin_read_UART1_GCTL()
+ #define bfin_write_UART_GCTL(val) bfin_write_UART1_GCTL(val)
+-#define UART_THR UART1_THR
+-#define UART_RBR UART1_RBR
+-#define UART_DLL UART1_DLL
+-#define UART_IER UART1_IER
+-#define UART_DLH UART1_DLH
+-#define UART_IIR UART1_IIR
+-#define UART_LCR UART1_LCR
+-#define UART_MCR UART1_MCR
+-#define UART_LSR UART1_LSR
+-#define UART_SCR UART1_SCR
+-#define UART_GCTL UART1_GCTL
++
++#define BFIN_UART_THR UART1_THR
++#define BFIN_UART_RBR UART1_RBR
++#define BFIN_UART_DLL UART1_DLL
++#define BFIN_UART_IER UART1_IER
++#define BFIN_UART_DLH UART1_DLH
++#define BFIN_UART_IIR UART1_IIR
++#define BFIN_UART_LCR UART1_LCR
++#define BFIN_UART_MCR UART1_MCR
++#define BFIN_UART_LSR UART1_LSR
++#define BFIN_UART_SCR UART1_SCR
++#define BFIN_UART_GCTL UART1_GCTL
++
++#define BFIN_UART_NR_PORTS 4
++
++#define OFFSET_DLL 0x00 /* Divisor Latch (Low-Byte) */
++#define OFFSET_DLH 0x04 /* Divisor Latch (High-Byte) */
++#define OFFSET_GCTL 0x08 /* Global Control Register */
++#define OFFSET_LCR 0x0C /* Line Control Register */
++#define OFFSET_MCR 0x10 /* Modem Control Register */
++#define OFFSET_LSR 0x14 /* Line Status Register */
++#define OFFSET_MSR 0x18 /* Modem Status Register */
++#define OFFSET_SCR 0x1C /* SCR Scratch Register */
++#define OFFSET_IER_SET 0x20 /* Set Interrupt Enable Register */
++#define OFFSET_IER_CLEAR 0x24 /* Clear Interrupt Enable Register */
++#define OFFSET_THR 0x28 /* Transmit Holding register */
++#define OFFSET_RBR 0x2C /* Receive Buffer register */
+
+ /* PLL_DIV Masks */
+ #define CCLK_DIV1 CSEL_DIV1 /* CCLK = VCO / 1 */
+diff --git a/include/asm-blackfin/mach-bf548/cdefBF542.h b/include/asm-blackfin/mach-bf548/cdefBF542.h
+index 308b33a..60b9f77 100644
+--- a/include/asm-blackfin/mach-bf548/cdefBF542.h
++++ b/include/asm-blackfin/mach-bf548/cdefBF542.h
+@@ -123,12 +123,12 @@
+ #define bfin_write_SDH_DATA_LGTH(val) bfin_write16(SDH_DATA_LGTH, val)
+ #define bfin_read_SDH_DATA_CTL() bfin_read16(SDH_DATA_CTL)
+ #define bfin_write_SDH_DATA_CTL(val) bfin_write16(SDH_DATA_CTL, val)
+-#define bfin_read_SDH_DATA_CNT() fin_read16(SDH_DATA_CNT)
++#define bfin_read_SDH_DATA_CNT() bfin_read16(SDH_DATA_CNT)
+ #define bfin_write_SDH_DATA_CNT(val) bfin_write16(SDH_DATA_CNT, val)
+ #define bfin_read_SDH_STATUS() bfin_read32(SDH_STATUS)
+ #define bfin_write_SDH_STATUS(val) bfin_write32(SDH_STATUS, val)
+-#define bfin_read_SDH_STATUS_CLR() fin_read16(SDH_STATUS_CLR)
+-#define bfin_write_SDH_STATUS_CLR(val) fin_write16(SDH_STATUS_CLR, val)
++#define bfin_read_SDH_STATUS_CLR() bfin_read16(SDH_STATUS_CLR)
++#define bfin_write_SDH_STATUS_CLR(val) bfin_write16(SDH_STATUS_CLR, val)
+ #define bfin_read_SDH_MASK0() bfin_read32(SDH_MASK0)
+ #define bfin_write_SDH_MASK0(val) bfin_write32(SDH_MASK0, val)
+ #define bfin_read_SDH_MASK1() bfin_read32(SDH_MASK1)
+@@ -184,8 +184,8 @@
+ #define bfin_write_USB_FRAME(val) bfin_write16(USB_FRAME, val)
+ #define bfin_read_USB_INDEX() bfin_read16(USB_INDEX)
+ #define bfin_write_USB_INDEX(val) bfin_write16(USB_INDEX, val)
+-#define bfin_read_USB_TESTMODE() fin_read16(USB_TESTMODE)
+-#define bfin_write_USB_TESTMODE(val) fin_write16(USB_TESTMODE, val)
++#define bfin_read_USB_TESTMODE() bfin_read16(USB_TESTMODE)
++#define bfin_write_USB_TESTMODE(val) bfin_write16(USB_TESTMODE, val)
+ #define bfin_read_USB_GLOBINTR() bfin_read16(USB_GLOBINTR)
+ #define bfin_write_USB_GLOBINTR(val) bfin_write16(USB_GLOBINTR, val)
+ #define bfin_read_USB_GLOBAL_CTL() bfin_read16(USB_GLOBAL_CTL)
+@@ -244,7 +244,7 @@
+ #define bfin_read_USB_OTG_DEV_CTL() bfin_read16(USB_OTG_DEV_CTL)
+ #define bfin_write_USB_OTG_DEV_CTL(val) bfin_write16(USB_OTG_DEV_CTL, val)
+ #define bfin_read_USB_OTG_VBUS_IRQ() bfin_read16(USB_OTG_VBUS_IRQ)
+-#define bfin_write_USB_OTG_VBUS_IRQ(val) fin_write16(USB_OTG_VBUS_IRQ, val)
++#define bfin_write_USB_OTG_VBUS_IRQ(val) bfin_write16(USB_OTG_VBUS_IRQ, val)
+ #define bfin_read_USB_OTG_VBUS_MASK() bfin_read16(USB_OTG_VBUS_MASK)
+ #define bfin_write_USB_OTG_VBUS_MASK(val) bfin_write16(USB_OTG_VBUS_MASK, val)
+
+diff --git a/include/asm-blackfin/mach-bf548/cdefBF544.h b/include/asm-blackfin/mach-bf548/cdefBF544.h
+index 7a2d177..ea9b4ab 100644
+--- a/include/asm-blackfin/mach-bf548/cdefBF544.h
++++ b/include/asm-blackfin/mach-bf548/cdefBF544.h
+@@ -113,39 +113,6 @@
+
+ /* Two Wire Interface Registers (TWI1) */
+
+-#define bfin_read_TWI1_CLKDIV() bfin_read16(TWI1_CLKDIV)
+-#define bfin_write_TWI1_CLKDIV(val) bfin_write16(TWI1_CLKDIV, val)
+-#define bfin_read_TWI1_CONTROL() bfin_read16(TWI1_CONTROL)
+-#define bfin_write_TWI1_CONTROL(val) bfin_write16(TWI1_CONTROL, val)
+-#define bfin_read_TWI1_SLAVE_CTRL() bfin_read16(TWI1_SLAVE_CTRL)
+-#define bfin_write_TWI1_SLAVE_CTRL(val) bfin_write16(TWI1_SLAVE_CTRL, val)
+-#define bfin_read_TWI1_SLAVE_STAT() bfin_read16(TWI1_SLAVE_STAT)
+-#define bfin_write_TWI1_SLAVE_STAT(val) bfin_write16(TWI1_SLAVE_STAT, val)
+-#define bfin_read_TWI1_SLAVE_ADDR() bfin_read16(TWI1_SLAVE_ADDR)
+-#define bfin_write_TWI1_SLAVE_ADDR(val) bfin_write16(TWI1_SLAVE_ADDR, val)
+-#define bfin_read_TWI1_MASTER_CTRL() bfin_read16(TWI1_MASTER_CTRL)
+-#define bfin_write_TWI1_MASTER_CTRL(val) bfin_write16(TWI1_MASTER_CTRL, val)
+-#define bfin_read_TWI1_MASTER_STAT() bfin_read16(TWI1_MASTER_STAT)
+-#define bfin_write_TWI1_MASTER_STAT(val) bfin_write16(TWI1_MASTER_STAT, val)
+-#define bfin_read_TWI1_MASTER_ADDR() bfin_read16(TWI1_MASTER_ADDR)
+-#define bfin_write_TWI1_MASTER_ADDR(val) bfin_write16(TWI1_MASTER_ADDR, val)
+-#define bfin_read_TWI1_INT_STAT() bfin_read16(TWI1_INT_STAT)
+-#define bfin_write_TWI1_INT_STAT(val) bfin_write16(TWI1_INT_STAT, val)
+-#define bfin_read_TWI1_INT_MASK() bfin_read16(TWI1_INT_MASK)
+-#define bfin_write_TWI1_INT_MASK(val) bfin_write16(TWI1_INT_MASK, val)
+-#define bfin_read_TWI1_FIFO_CTRL() bfin_read16(TWI1_FIFO_CTRL)
+-#define bfin_write_TWI1_FIFO_CTRL(val) bfin_write16(TWI1_FIFO_CTRL, val)
+-#define bfin_read_TWI1_FIFO_STAT() bfin_read16(TWI1_FIFO_STAT)
+-#define bfin_write_TWI1_FIFO_STAT(val) bfin_write16(TWI1_FIFO_STAT, val)
+-#define bfin_read_TWI1_XMT_DATA8() bfin_read16(TWI1_XMT_DATA8)
+-#define bfin_write_TWI1_XMT_DATA8(val) bfin_write16(TWI1_XMT_DATA8, val)
+-#define bfin_read_TWI1_XMT_DATA16() bfin_read16(TWI1_XMT_DATA16)
+-#define bfin_write_TWI1_XMT_DATA16(val) bfin_write16(TWI1_XMT_DATA16, val)
+-#define bfin_read_TWI1_RCV_DATA8() bfin_read16(TWI1_RCV_DATA8)
+-#define bfin_write_TWI1_RCV_DATA8(val) bfin_write16(TWI1_RCV_DATA8, val)
+-#define bfin_read_TWI1_RCV_DATA16() bfin_read16(TWI1_RCV_DATA16)
+-#define bfin_write_TWI1_RCV_DATA16(val) bfin_write16(TWI1_RCV_DATA16, val)
+-
+ /* CAN Controller 1 Config 1 Registers */
+
+ #define bfin_read_CAN1_MC1() bfin_read16(CAN1_MC1)
+diff --git a/include/asm-blackfin/mach-bf548/cdefBF547.h b/include/asm-blackfin/mach-bf548/cdefBF547.h
+index d0a200b..ba71627 100644
+--- a/include/asm-blackfin/mach-bf548/cdefBF547.h
++++ b/include/asm-blackfin/mach-bf548/cdefBF547.h
+@@ -185,39 +185,6 @@
+
+ /* Two Wire Interface Registers (TWI1) */
+
+-#define bfin_read_TWI1_CLKDIV() bfin_read16(TWI1_CLKDIV)
+-#define bfin_write_TWI1_CLKDIV(val) bfin_write16(TWI1_CLKDIV, val)
+-#define bfin_read_TWI1_CONTROL() bfin_read16(TWI1_CONTROL)
+-#define bfin_write_TWI1_CONTROL(val) bfin_write16(TWI1_CONTROL, val)
+-#define bfin_read_TWI1_SLAVE_CTRL() bfin_read16(TWI1_SLAVE_CTRL)
+-#define bfin_write_TWI1_SLAVE_CTRL(val) bfin_write16(TWI1_SLAVE_CTRL, val)
+-#define bfin_read_TWI1_SLAVE_STAT() bfin_read16(TWI1_SLAVE_STAT)
+-#define bfin_write_TWI1_SLAVE_STAT(val) bfin_write16(TWI1_SLAVE_STAT, val)
+-#define bfin_read_TWI1_SLAVE_ADDR() bfin_read16(TWI1_SLAVE_ADDR)
+-#define bfin_write_TWI1_SLAVE_ADDR(val) bfin_write16(TWI1_SLAVE_ADDR, val)
+-#define bfin_read_TWI1_MASTER_CTRL() bfin_read16(TWI1_MASTER_CTRL)
+-#define bfin_write_TWI1_MASTER_CTRL(val) bfin_write16(TWI1_MASTER_CTRL, val)
+-#define bfin_read_TWI1_MASTER_STAT() bfin_read16(TWI1_MASTER_STAT)
+-#define bfin_write_TWI1_MASTER_STAT(val) bfin_write16(TWI1_MASTER_STAT, val)
+-#define bfin_read_TWI1_MASTER_ADDR() bfin_read16(TWI1_MASTER_ADDR)
+-#define bfin_write_TWI1_MASTER_ADDR(val) bfin_write16(TWI1_MASTER_ADDR, val)
+-#define bfin_read_TWI1_INT_STAT() bfin_read16(TWI1_INT_STAT)
+-#define bfin_write_TWI1_INT_STAT(val) bfin_write16(TWI1_INT_STAT, val)
+-#define bfin_read_TWI1_INT_MASK() bfin_read16(TWI1_INT_MASK)
+-#define bfin_write_TWI1_INT_MASK(val) bfin_write16(TWI1_INT_MASK, val)
+-#define bfin_read_TWI1_FIFO_CTRL() bfin_read16(TWI1_FIFO_CTRL)
+-#define bfin_write_TWI1_FIFO_CTRL(val) bfin_write16(TWI1_FIFO_CTRL, val)
+-#define bfin_read_TWI1_FIFO_STAT() bfin_read16(TWI1_FIFO_STAT)
+-#define bfin_write_TWI1_FIFO_STAT(val) bfin_write16(TWI1_FIFO_STAT, val)
+-#define bfin_read_TWI1_XMT_DATA8() bfin_read16(TWI1_XMT_DATA8)
+-#define bfin_write_TWI1_XMT_DATA8(val) bfin_write16(TWI1_XMT_DATA8, val)
+-#define bfin_read_TWI1_XMT_DATA16() bfin_read16(TWI1_XMT_DATA16)
+-#define bfin_write_TWI1_XMT_DATA16(val) bfin_write16(TWI1_XMT_DATA16, val)
+-#define bfin_read_TWI1_RCV_DATA8() bfin_read16(TWI1_RCV_DATA8)
+-#define bfin_write_TWI1_RCV_DATA8(val) bfin_write16(TWI1_RCV_DATA8, val)
+-#define bfin_read_TWI1_RCV_DATA16() bfin_read16(TWI1_RCV_DATA16)
+-#define bfin_write_TWI1_RCV_DATA16(val) bfin_write16(TWI1_RCV_DATA16, val)
+-
+ /* SPI2 Registers */
+
+ #define bfin_read_SPI2_CTL() bfin_read16(SPI2_CTL)
+diff --git a/include/asm-blackfin/mach-bf548/cdefBF548.h b/include/asm-blackfin/mach-bf548/cdefBF548.h
+index 674be02..ae971eb 100644
+--- a/include/asm-blackfin/mach-bf548/cdefBF548.h
++++ b/include/asm-blackfin/mach-bf548/cdefBF548.h
+@@ -185,39 +185,6 @@
+
+ /* Two Wire Interface Registers (TWI1) */
+
+-#define bfin_read_TWI1_CLKDIV() bfin_read16(TWI1_CLKDIV)
+-#define bfin_write_TWI1_CLKDIV(val) bfin_write16(TWI1_CLKDIV, val)
+-#define bfin_read_TWI1_CONTROL() bfin_read16(TWI1_CONTROL)
+-#define bfin_write_TWI1_CONTROL(val) bfin_write16(TWI1_CONTROL, val)
+-#define bfin_read_TWI1_SLAVE_CTRL() bfin_read16(TWI1_SLAVE_CTRL)
+-#define bfin_write_TWI1_SLAVE_CTRL(val) bfin_write16(TWI1_SLAVE_CTRL, val)
+-#define bfin_read_TWI1_SLAVE_STAT() bfin_read16(TWI1_SLAVE_STAT)
+-#define bfin_write_TWI1_SLAVE_STAT(val) bfin_write16(TWI1_SLAVE_STAT, val)
+-#define bfin_read_TWI1_SLAVE_ADDR() bfin_read16(TWI1_SLAVE_ADDR)
+-#define bfin_write_TWI1_SLAVE_ADDR(val) bfin_write16(TWI1_SLAVE_ADDR, val)
+-#define bfin_read_TWI1_MASTER_CTRL() bfin_read16(TWI1_MASTER_CTRL)
+-#define bfin_write_TWI1_MASTER_CTRL(val) bfin_write16(TWI1_MASTER_CTRL, val)
+-#define bfin_read_TWI1_MASTER_STAT() bfin_read16(TWI1_MASTER_STAT)
+-#define bfin_write_TWI1_MASTER_STAT(val) bfin_write16(TWI1_MASTER_STAT, val)
+-#define bfin_read_TWI1_MASTER_ADDR() bfin_read16(TWI1_MASTER_ADDR)
+-#define bfin_write_TWI1_MASTER_ADDR(val) bfin_write16(TWI1_MASTER_ADDR, val)
+-#define bfin_read_TWI1_INT_STAT() bfin_read16(TWI1_INT_STAT)
+-#define bfin_write_TWI1_INT_STAT(val) bfin_write16(TWI1_INT_STAT, val)
+-#define bfin_read_TWI1_INT_MASK() bfin_read16(TWI1_INT_MASK)
+-#define bfin_write_TWI1_INT_MASK(val) bfin_write16(TWI1_INT_MASK, val)
+-#define bfin_read_TWI1_FIFO_CTRL() bfin_read16(TWI1_FIFO_CTRL)
+-#define bfin_write_TWI1_FIFO_CTRL(val) bfin_write16(TWI1_FIFO_CTRL, val)
+-#define bfin_read_TWI1_FIFO_STAT() bfin_read16(TWI1_FIFO_STAT)
+-#define bfin_write_TWI1_FIFO_STAT(val) bfin_write16(TWI1_FIFO_STAT, val)
+-#define bfin_read_TWI1_XMT_DATA8() bfin_read16(TWI1_XMT_DATA8)
+-#define bfin_write_TWI1_XMT_DATA8(val) bfin_write16(TWI1_XMT_DATA8, val)
+-#define bfin_read_TWI1_XMT_DATA16() bfin_read16(TWI1_XMT_DATA16)
+-#define bfin_write_TWI1_XMT_DATA16(val) bfin_write16(TWI1_XMT_DATA16, val)
+-#define bfin_read_TWI1_RCV_DATA8() bfin_read16(TWI1_RCV_DATA8)
+-#define bfin_write_TWI1_RCV_DATA8(val) bfin_write16(TWI1_RCV_DATA8, val)
+-#define bfin_read_TWI1_RCV_DATA16() bfin_read16(TWI1_RCV_DATA16)
+-#define bfin_write_TWI1_RCV_DATA16(val) bfin_write16(TWI1_RCV_DATA16, val)
+-
+ /* SPI2 Registers */
+
+ #define bfin_read_SPI2_CTL() bfin_read16(SPI2_CTL)
+diff --git a/include/asm-blackfin/mach-bf548/cdefBF549.h b/include/asm-blackfin/mach-bf548/cdefBF549.h
+index 2ab5b7c..92d07d9 100644
+--- a/include/asm-blackfin/mach-bf548/cdefBF549.h
++++ b/include/asm-blackfin/mach-bf548/cdefBF549.h
+@@ -185,39 +185,6 @@
+
+ /* Two Wire Interface Registers (TWI1) */
+
+-#define bfin_read_TWI1_CLKDIV() bfin_read16(TWI1_CLKDIV)
+-#define bfin_write_TWI1_CLKDIV(val) bfin_write16(TWI1_CLKDIV, val)
+-#define bfin_read_TWI1_CONTROL() bfin_read16(TWI1_CONTROL)
+-#define bfin_write_TWI1_CONTROL(val) bfin_write16(TWI1_CONTROL, val)
+-#define bfin_read_TWI1_SLAVE_CTRL() bfin_read16(TWI1_SLAVE_CTRL)
+-#define bfin_write_TWI1_SLAVE_CTRL(val) bfin_write16(TWI1_SLAVE_CTRL, val)
+-#define bfin_read_TWI1_SLAVE_STAT() bfin_read16(TWI1_SLAVE_STAT)
+-#define bfin_write_TWI1_SLAVE_STAT(val) bfin_write16(TWI1_SLAVE_STAT, val)
+-#define bfin_read_TWI1_SLAVE_ADDR() bfin_read16(TWI1_SLAVE_ADDR)
+-#define bfin_write_TWI1_SLAVE_ADDR(val) bfin_write16(TWI1_SLAVE_ADDR, val)
+-#define bfin_read_TWI1_MASTER_CTRL() bfin_read16(TWI1_MASTER_CTRL)
+-#define bfin_write_TWI1_MASTER_CTRL(val) bfin_write16(TWI1_MASTER_CTRL, val)
+-#define bfin_read_TWI1_MASTER_STAT() bfin_read16(TWI1_MASTER_STAT)
+-#define bfin_write_TWI1_MASTER_STAT(val) bfin_write16(TWI1_MASTER_STAT, val)
+-#define bfin_read_TWI1_MASTER_ADDR() bfin_read16(TWI1_MASTER_ADDR)
+-#define bfin_write_TWI1_MASTER_ADDR(val) bfin_write16(TWI1_MASTER_ADDR, val)
+-#define bfin_read_TWI1_INT_STAT() bfin_read16(TWI1_INT_STAT)
+-#define bfin_write_TWI1_INT_STAT(val) bfin_write16(TWI1_INT_STAT, val)
+-#define bfin_read_TWI1_INT_MASK() bfin_read16(TWI1_INT_MASK)
+-#define bfin_write_TWI1_INT_MASK(val) bfin_write16(TWI1_INT_MASK, val)
+-#define bfin_read_TWI1_FIFO_CTRL() bfin_read16(TWI1_FIFO_CTRL)
+-#define bfin_write_TWI1_FIFO_CTRL(val) bfin_write16(TWI1_FIFO_CTRL, val)
+-#define bfin_read_TWI1_FIFO_STAT() bfin_read16(TWI1_FIFO_STAT)
+-#define bfin_write_TWI1_FIFO_STAT(val) bfin_write16(TWI1_FIFO_STAT, val)
+-#define bfin_read_TWI1_XMT_DATA8() bfin_read16(TWI1_XMT_DATA8)
+-#define bfin_write_TWI1_XMT_DATA8(val) bfin_write16(TWI1_XMT_DATA8, val)
+-#define bfin_read_TWI1_XMT_DATA16() bfin_read16(TWI1_XMT_DATA16)
+-#define bfin_write_TWI1_XMT_DATA16(val) bfin_write16(TWI1_XMT_DATA16, val)
+-#define bfin_read_TWI1_RCV_DATA8() bfin_read16(TWI1_RCV_DATA8)
+-#define bfin_write_TWI1_RCV_DATA8(val) bfin_write16(TWI1_RCV_DATA8, val)
+-#define bfin_read_TWI1_RCV_DATA16() bfin_read16(TWI1_RCV_DATA16)
+-#define bfin_write_TWI1_RCV_DATA16(val) bfin_write16(TWI1_RCV_DATA16, val)
+-
+ /* SPI2 Registers */
+
+ #define bfin_read_SPI2_CTL() bfin_read16(SPI2_CTL)
+@@ -1773,7 +1740,7 @@
+ #define bfin_read_USB_DMA5ADDRHIGH() bfin_read16(USB_DMA5ADDRHIGH)
+ #define bfin_write_USB_DMA5ADDRHIGH(val) bfin_write16(USB_DMA5ADDRHIGH, val)
+ #define bfin_read_USB_DMA5COUNTLOW() bfin_read16(USB_DMA5COUNTLOW)
+-#define bfin_write_USB_DMA5COUNTLOW(val) fin_write16(USB_DMA5COUNTLOW, val)
++#define bfin_write_USB_DMA5COUNTLOW(val) bfin_write16(USB_DMA5COUNTLOW, val)
+ #define bfin_read_USB_DMA5COUNTHIGH() bfin_read16(USB_DMA5COUNTHIGH)
+ #define bfin_write_USB_DMA5COUNTHIGH(val) bfin_write16(USB_DMA5COUNTHIGH, val)
+
+diff --git a/include/asm-blackfin/mach-bf548/cdefBF54x_base.h b/include/asm-blackfin/mach-bf548/cdefBF54x_base.h
+index 19ddcd8..57ac8cb 100644
+--- a/include/asm-blackfin/mach-bf548/cdefBF54x_base.h
++++ b/include/asm-blackfin/mach-bf548/cdefBF54x_base.h
+@@ -43,7 +43,33 @@
+ /* PLL Registers */
+
+ #define bfin_read_PLL_CTL() bfin_read16(PLL_CTL)
+-#define bfin_write_PLL_CTL(val) bfin_write16(PLL_CTL, val)
++/* Writing to PLL_CTL initiates a PLL relock sequence. */
++static __inline__ void bfin_write_PLL_CTL(unsigned int val)
++{
++ unsigned long flags, iwr0, iwr1, iwr2;
++
++ if (val == bfin_read_PLL_CTL())
++ return;
++
++ local_irq_save(flags);
++ /* Enable the PLL Wakeup bit in SIC IWR */
++ iwr0 = bfin_read32(SIC_IWR0);
++ iwr1 = bfin_read32(SIC_IWR1);
++ iwr2 = bfin_read32(SIC_IWR2);
++ /* Only allow PPL Wakeup) */
++ bfin_write32(SIC_IWR0, IWR_ENABLE(0));
++ bfin_write32(SIC_IWR1, 0);
++ bfin_write32(SIC_IWR2, 0);
++
++ bfin_write16(PLL_CTL, val);
++ SSYNC();
++ asm("IDLE;");
++
++ bfin_write32(SIC_IWR0, iwr0);
++ bfin_write32(SIC_IWR1, iwr1);
++ bfin_write32(SIC_IWR2, iwr2);
++ local_irq_restore(flags);
++}
+ #define bfin_read_PLL_DIV() bfin_read16(PLL_DIV)
+ #define bfin_write_PLL_DIV(val) bfin_write16(PLL_DIV, val)
+ #define bfin_read_VR_CTL() bfin_read16(VR_CTL)
+@@ -52,6 +78,10 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ {
+ unsigned long flags, iwr0, iwr1, iwr2;
+
++ if (val == bfin_read_VR_CTL())
++ return;
++
++ local_irq_save(flags);
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr0 = bfin_read32(SIC_IWR0);
+ iwr1 = bfin_read32(SIC_IWR1);
+@@ -63,13 +93,12 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+
+ bfin_write16(VR_CTL, val);
+ SSYNC();
+-
+- local_irq_save(flags);
+ asm("IDLE;");
+- local_irq_restore(flags);
++
+ bfin_write32(SIC_IWR0, iwr0);
+ bfin_write32(SIC_IWR1, iwr1);
+ bfin_write32(SIC_IWR2, iwr2);
++ local_irq_restore(flags);
+ }
+ #define bfin_read_PLL_STAT() bfin_read16(PLL_STAT)
+ #define bfin_write_PLL_STAT(val) bfin_write16(PLL_STAT, val)
+@@ -211,39 +240,6 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+
+ /* Two Wire Interface Registers (TWI0) */
+
+-#define bfin_read_TWI0_CLKDIV() bfin_read16(TWI0_CLKDIV)
+-#define bfin_write_TWI0_CLKDIV(val) bfin_write16(TWI0_CLKDIV, val)
+-#define bfin_read_TWI0_CONTROL() bfin_read16(TWI0_CONTROL)
+-#define bfin_write_TWI0_CONTROL(val) bfin_write16(TWI0_CONTROL, val)
+-#define bfin_read_TWI0_SLAVE_CTRL() bfin_read16(TWI0_SLAVE_CTRL)
+-#define bfin_write_TWI0_SLAVE_CTRL(val) bfin_write16(TWI0_SLAVE_CTRL, val)
+-#define bfin_read_TWI0_SLAVE_STAT() bfin_read16(TWI0_SLAVE_STAT)
+-#define bfin_write_TWI0_SLAVE_STAT(val) bfin_write16(TWI0_SLAVE_STAT, val)
+-#define bfin_read_TWI0_SLAVE_ADDR() bfin_read16(TWI0_SLAVE_ADDR)
+-#define bfin_write_TWI0_SLAVE_ADDR(val) bfin_write16(TWI0_SLAVE_ADDR, val)
+-#define bfin_read_TWI0_MASTER_CTRL() bfin_read16(TWI0_MASTER_CTRL)
+-#define bfin_write_TWI0_MASTER_CTRL(val) bfin_write16(TWI0_MASTER_CTRL, val)
+-#define bfin_read_TWI0_MASTER_STAT() bfin_read16(TWI0_MASTER_STAT)
+-#define bfin_write_TWI0_MASTER_STAT(val) bfin_write16(TWI0_MASTER_STAT, val)
+-#define bfin_read_TWI0_MASTER_ADDR() bfin_read16(TWI0_MASTER_ADDR)
+-#define bfin_write_TWI0_MASTER_ADDR(val) bfin_write16(TWI0_MASTER_ADDR, val)
+-#define bfin_read_TWI0_INT_STAT() bfin_read16(TWI0_INT_STAT)
+-#define bfin_write_TWI0_INT_STAT(val) bfin_write16(TWI0_INT_STAT, val)
+-#define bfin_read_TWI0_INT_MASK() bfin_read16(TWI0_INT_MASK)
+-#define bfin_write_TWI0_INT_MASK(val) bfin_write16(TWI0_INT_MASK, val)
+-#define bfin_read_TWI0_FIFO_CTRL() bfin_read16(TWI0_FIFO_CTRL)
+-#define bfin_write_TWI0_FIFO_CTRL(val) bfin_write16(TWI0_FIFO_CTRL, val)
+-#define bfin_read_TWI0_FIFO_STAT() bfin_read16(TWI0_FIFO_STAT)
+-#define bfin_write_TWI0_FIFO_STAT(val) bfin_write16(TWI0_FIFO_STAT, val)
+-#define bfin_read_TWI0_XMT_DATA8() bfin_read16(TWI0_XMT_DATA8)
+-#define bfin_write_TWI0_XMT_DATA8(val) bfin_write16(TWI0_XMT_DATA8, val)
+-#define bfin_read_TWI0_XMT_DATA16() bfin_read16(TWI0_XMT_DATA16)
+-#define bfin_write_TWI0_XMT_DATA16(val) bfin_write16(TWI0_XMT_DATA16, val)
+-#define bfin_read_TWI0_RCV_DATA8() bfin_read16(TWI0_RCV_DATA8)
+-#define bfin_write_TWI0_RCV_DATA8(val) bfin_write16(TWI0_RCV_DATA8, val)
+-#define bfin_read_TWI0_RCV_DATA16() bfin_read16(TWI0_RCV_DATA16)
+-#define bfin_write_TWI0_RCV_DATA16(val) bfin_write16(TWI0_RCV_DATA16, val)
+-
+ /* SPORT0 is not defined in the shared file because it is not available on the ADSP-BF542 and ADSP-BF544 bfin_read_()rocessors */
+
+ /* SPORT1 Registers */
+@@ -323,7 +319,7 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ #define bfin_read_EBIU_DDRQUE() bfin_read32(EBIU_DDRQUE)
+ #define bfin_write_EBIU_DDRQUE(val) bfin_write32(EBIU_DDRQUE, val)
+ #define bfin_read_EBIU_ERRADD() bfin_read32(EBIU_ERRADD)
+-#define bfin_write_EBIU_ERRADD(val) bfin_write32(EBIU_ERRADD)
++#define bfin_write_EBIU_ERRADD(val) bfin_write32(EBIU_ERRADD, val)
+ #define bfin_read_EBIU_ERRMST() bfin_read16(EBIU_ERRMST)
+ #define bfin_write_EBIU_ERRMST(val) bfin_write16(EBIU_ERRMST, val)
+ #define bfin_read_EBIU_RSTCTL() bfin_read16(EBIU_RSTCTL)
+@@ -392,23 +388,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 0 Registers */
+
+ #define bfin_read_DMA0_NEXT_DESC_PTR() bfin_read32(DMA0_NEXT_DESC_PTR)
+-#define bfin_write_DMA0_NEXT_DESC_PTR(val) bfin_write32(DMA0_NEXT_DESC_PTR)
++#define bfin_write_DMA0_NEXT_DESC_PTR(val) bfin_write32(DMA0_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA0_START_ADDR() bfin_read32(DMA0_START_ADDR)
+-#define bfin_write_DMA0_START_ADDR(val) bfin_write32(DMA0_START_ADDR)
++#define bfin_write_DMA0_START_ADDR(val) bfin_write32(DMA0_START_ADDR, val)
+ #define bfin_read_DMA0_CONFIG() bfin_read16(DMA0_CONFIG)
+ #define bfin_write_DMA0_CONFIG(val) bfin_write16(DMA0_CONFIG, val)
+ #define bfin_read_DMA0_X_COUNT() bfin_read16(DMA0_X_COUNT)
+ #define bfin_write_DMA0_X_COUNT(val) bfin_write16(DMA0_X_COUNT, val)
+ #define bfin_read_DMA0_X_MODIFY() bfin_read16(DMA0_X_MODIFY)
+-#define bfin_write_DMA0_X_MODIFY(val) bfin_write16(DMA0_X_MODIFY)
++#define bfin_write_DMA0_X_MODIFY(val) bfin_write16(DMA0_X_MODIFY, val)
+ #define bfin_read_DMA0_Y_COUNT() bfin_read16(DMA0_Y_COUNT)
+ #define bfin_write_DMA0_Y_COUNT(val) bfin_write16(DMA0_Y_COUNT, val)
+ #define bfin_read_DMA0_Y_MODIFY() bfin_read16(DMA0_Y_MODIFY)
+-#define bfin_write_DMA0_Y_MODIFY(val) bfin_write16(DMA0_Y_MODIFY)
++#define bfin_write_DMA0_Y_MODIFY(val) bfin_write16(DMA0_Y_MODIFY, val)
+ #define bfin_read_DMA0_CURR_DESC_PTR() bfin_read32(DMA0_CURR_DESC_PTR)
+-#define bfin_write_DMA0_CURR_DESC_PTR(val) bfin_write32(DMA0_CURR_DESC_PTR)
++#define bfin_write_DMA0_CURR_DESC_PTR(val) bfin_write32(DMA0_CURR_DESC_PTR, val)
+ #define bfin_read_DMA0_CURR_ADDR() bfin_read32(DMA0_CURR_ADDR)
+-#define bfin_write_DMA0_CURR_ADDR(val) bfin_write32(DMA0_CURR_ADDR)
++#define bfin_write_DMA0_CURR_ADDR(val) bfin_write32(DMA0_CURR_ADDR, val)
+ #define bfin_read_DMA0_IRQ_STATUS() bfin_read16(DMA0_IRQ_STATUS)
+ #define bfin_write_DMA0_IRQ_STATUS(val) bfin_write16(DMA0_IRQ_STATUS, val)
+ #define bfin_read_DMA0_PERIPHERAL_MAP() bfin_read16(DMA0_PERIPHERAL_MAP)
+@@ -421,23 +417,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 1 Registers */
+
+ #define bfin_read_DMA1_NEXT_DESC_PTR() bfin_read32(DMA1_NEXT_DESC_PTR)
+-#define bfin_write_DMA1_NEXT_DESC_PTR(val) bfin_write32(DMA1_NEXT_DESC_PTR)
++#define bfin_write_DMA1_NEXT_DESC_PTR(val) bfin_write32(DMA1_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA1_START_ADDR() bfin_read32(DMA1_START_ADDR)
+-#define bfin_write_DMA1_START_ADDR(val) bfin_write32(DMA1_START_ADDR)
++#define bfin_write_DMA1_START_ADDR(val) bfin_write32(DMA1_START_ADDR, val)
+ #define bfin_read_DMA1_CONFIG() bfin_read16(DMA1_CONFIG)
+ #define bfin_write_DMA1_CONFIG(val) bfin_write16(DMA1_CONFIG, val)
+ #define bfin_read_DMA1_X_COUNT() bfin_read16(DMA1_X_COUNT)
+ #define bfin_write_DMA1_X_COUNT(val) bfin_write16(DMA1_X_COUNT, val)
+ #define bfin_read_DMA1_X_MODIFY() bfin_read16(DMA1_X_MODIFY)
+-#define bfin_write_DMA1_X_MODIFY(val) bfin_write16(DMA1_X_MODIFY)
++#define bfin_write_DMA1_X_MODIFY(val) bfin_write16(DMA1_X_MODIFY, val)
+ #define bfin_read_DMA1_Y_COUNT() bfin_read16(DMA1_Y_COUNT)
+ #define bfin_write_DMA1_Y_COUNT(val) bfin_write16(DMA1_Y_COUNT, val)
+ #define bfin_read_DMA1_Y_MODIFY() bfin_read16(DMA1_Y_MODIFY)
+-#define bfin_write_DMA1_Y_MODIFY(val) bfin_write16(DMA1_Y_MODIFY)
++#define bfin_write_DMA1_Y_MODIFY(val) bfin_write16(DMA1_Y_MODIFY, val)
+ #define bfin_read_DMA1_CURR_DESC_PTR() bfin_read32(DMA1_CURR_DESC_PTR)
+-#define bfin_write_DMA1_CURR_DESC_PTR(val) bfin_write32(DMA1_CURR_DESC_PTR)
++#define bfin_write_DMA1_CURR_DESC_PTR(val) bfin_write32(DMA1_CURR_DESC_PTR, val)
+ #define bfin_read_DMA1_CURR_ADDR() bfin_read32(DMA1_CURR_ADDR)
+-#define bfin_write_DMA1_CURR_ADDR(val) bfin_write32(DMA1_CURR_ADDR)
++#define bfin_write_DMA1_CURR_ADDR(val) bfin_write32(DMA1_CURR_ADDR, val)
+ #define bfin_read_DMA1_IRQ_STATUS() bfin_read16(DMA1_IRQ_STATUS)
+ #define bfin_write_DMA1_IRQ_STATUS(val) bfin_write16(DMA1_IRQ_STATUS, val)
+ #define bfin_read_DMA1_PERIPHERAL_MAP() bfin_read16(DMA1_PERIPHERAL_MAP)
+@@ -450,23 +446,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 2 Registers */
+
+ #define bfin_read_DMA2_NEXT_DESC_PTR() bfin_read32(DMA2_NEXT_DESC_PTR)
+-#define bfin_write_DMA2_NEXT_DESC_PTR(val) bfin_write32(DMA2_NEXT_DESC_PTR)
++#define bfin_write_DMA2_NEXT_DESC_PTR(val) bfin_write32(DMA2_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA2_START_ADDR() bfin_read32(DMA2_START_ADDR)
+-#define bfin_write_DMA2_START_ADDR(val) bfin_write32(DMA2_START_ADDR)
++#define bfin_write_DMA2_START_ADDR(val) bfin_write32(DMA2_START_ADDR, val)
+ #define bfin_read_DMA2_CONFIG() bfin_read16(DMA2_CONFIG)
+ #define bfin_write_DMA2_CONFIG(val) bfin_write16(DMA2_CONFIG, val)
+ #define bfin_read_DMA2_X_COUNT() bfin_read16(DMA2_X_COUNT)
+ #define bfin_write_DMA2_X_COUNT(val) bfin_write16(DMA2_X_COUNT, val)
+ #define bfin_read_DMA2_X_MODIFY() bfin_read16(DMA2_X_MODIFY)
+-#define bfin_write_DMA2_X_MODIFY(val) bfin_write16(DMA2_X_MODIFY)
++#define bfin_write_DMA2_X_MODIFY(val) bfin_write16(DMA2_X_MODIFY, val)
+ #define bfin_read_DMA2_Y_COUNT() bfin_read16(DMA2_Y_COUNT)
+ #define bfin_write_DMA2_Y_COUNT(val) bfin_write16(DMA2_Y_COUNT, val)
+ #define bfin_read_DMA2_Y_MODIFY() bfin_read16(DMA2_Y_MODIFY)
+-#define bfin_write_DMA2_Y_MODIFY(val) bfin_write16(DMA2_Y_MODIFY)
++#define bfin_write_DMA2_Y_MODIFY(val) bfin_write16(DMA2_Y_MODIFY, val)
+ #define bfin_read_DMA2_CURR_DESC_PTR() bfin_read32(DMA2_CURR_DESC_PTR)
+-#define bfin_write_DMA2_CURR_DESC_PTR(val) bfin_write32(DMA2_CURR_DESC_PTR)
++#define bfin_write_DMA2_CURR_DESC_PTR(val) bfin_write32(DMA2_CURR_DESC_PTR, val)
+ #define bfin_read_DMA2_CURR_ADDR() bfin_read32(DMA2_CURR_ADDR)
+-#define bfin_write_DMA2_CURR_ADDR(val) bfin_write32(DMA2_CURR_ADDR)
++#define bfin_write_DMA2_CURR_ADDR(val) bfin_write32(DMA2_CURR_ADDR, val)
+ #define bfin_read_DMA2_IRQ_STATUS() bfin_read16(DMA2_IRQ_STATUS)
+ #define bfin_write_DMA2_IRQ_STATUS(val) bfin_write16(DMA2_IRQ_STATUS, val)
+ #define bfin_read_DMA2_PERIPHERAL_MAP() bfin_read16(DMA2_PERIPHERAL_MAP)
+@@ -479,23 +475,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 3 Registers */
+
+ #define bfin_read_DMA3_NEXT_DESC_PTR() bfin_read32(DMA3_NEXT_DESC_PTR)
+-#define bfin_write_DMA3_NEXT_DESC_PTR(val) bfin_write32(DMA3_NEXT_DESC_PTR)
++#define bfin_write_DMA3_NEXT_DESC_PTR(val) bfin_write32(DMA3_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA3_START_ADDR() bfin_read32(DMA3_START_ADDR)
+-#define bfin_write_DMA3_START_ADDR(val) bfin_write32(DMA3_START_ADDR)
++#define bfin_write_DMA3_START_ADDR(val) bfin_write32(DMA3_START_ADDR, val)
+ #define bfin_read_DMA3_CONFIG() bfin_read16(DMA3_CONFIG)
+ #define bfin_write_DMA3_CONFIG(val) bfin_write16(DMA3_CONFIG, val)
+ #define bfin_read_DMA3_X_COUNT() bfin_read16(DMA3_X_COUNT)
+ #define bfin_write_DMA3_X_COUNT(val) bfin_write16(DMA3_X_COUNT, val)
+ #define bfin_read_DMA3_X_MODIFY() bfin_read16(DMA3_X_MODIFY)
+-#define bfin_write_DMA3_X_MODIFY(val) bfin_write16(DMA3_X_MODIFY)
++#define bfin_write_DMA3_X_MODIFY(val) bfin_write16(DMA3_X_MODIFY, val)
+ #define bfin_read_DMA3_Y_COUNT() bfin_read16(DMA3_Y_COUNT)
+ #define bfin_write_DMA3_Y_COUNT(val) bfin_write16(DMA3_Y_COUNT, val)
+ #define bfin_read_DMA3_Y_MODIFY() bfin_read16(DMA3_Y_MODIFY)
+-#define bfin_write_DMA3_Y_MODIFY(val) bfin_write16(DMA3_Y_MODIFY)
++#define bfin_write_DMA3_Y_MODIFY(val) bfin_write16(DMA3_Y_MODIFY, val)
+ #define bfin_read_DMA3_CURR_DESC_PTR() bfin_read32(DMA3_CURR_DESC_PTR)
+-#define bfin_write_DMA3_CURR_DESC_PTR(val) bfin_write32(DMA3_CURR_DESC_PTR)
++#define bfin_write_DMA3_CURR_DESC_PTR(val) bfin_write32(DMA3_CURR_DESC_PTR, val)
+ #define bfin_read_DMA3_CURR_ADDR() bfin_read32(DMA3_CURR_ADDR)
+-#define bfin_write_DMA3_CURR_ADDR(val) bfin_write32(DMA3_CURR_ADDR)
++#define bfin_write_DMA3_CURR_ADDR(val) bfin_write32(DMA3_CURR_ADDR, val)
+ #define bfin_read_DMA3_IRQ_STATUS() bfin_read16(DMA3_IRQ_STATUS)
+ #define bfin_write_DMA3_IRQ_STATUS(val) bfin_write16(DMA3_IRQ_STATUS, val)
+ #define bfin_read_DMA3_PERIPHERAL_MAP() bfin_read16(DMA3_PERIPHERAL_MAP)
+@@ -508,23 +504,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 4 Registers */
+
+ #define bfin_read_DMA4_NEXT_DESC_PTR() bfin_read32(DMA4_NEXT_DESC_PTR)
+-#define bfin_write_DMA4_NEXT_DESC_PTR(val) bfin_write32(DMA4_NEXT_DESC_PTR)
++#define bfin_write_DMA4_NEXT_DESC_PTR(val) bfin_write32(DMA4_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA4_START_ADDR() bfin_read32(DMA4_START_ADDR)
+-#define bfin_write_DMA4_START_ADDR(val) bfin_write32(DMA4_START_ADDR)
++#define bfin_write_DMA4_START_ADDR(val) bfin_write32(DMA4_START_ADDR, val)
+ #define bfin_read_DMA4_CONFIG() bfin_read16(DMA4_CONFIG)
+ #define bfin_write_DMA4_CONFIG(val) bfin_write16(DMA4_CONFIG, val)
+ #define bfin_read_DMA4_X_COUNT() bfin_read16(DMA4_X_COUNT)
+ #define bfin_write_DMA4_X_COUNT(val) bfin_write16(DMA4_X_COUNT, val)
+ #define bfin_read_DMA4_X_MODIFY() bfin_read16(DMA4_X_MODIFY)
+-#define bfin_write_DMA4_X_MODIFY(val) bfin_write16(DMA4_X_MODIFY)
++#define bfin_write_DMA4_X_MODIFY(val) bfin_write16(DMA4_X_MODIFY, val)
+ #define bfin_read_DMA4_Y_COUNT() bfin_read16(DMA4_Y_COUNT)
+ #define bfin_write_DMA4_Y_COUNT(val) bfin_write16(DMA4_Y_COUNT, val)
+ #define bfin_read_DMA4_Y_MODIFY() bfin_read16(DMA4_Y_MODIFY)
+-#define bfin_write_DMA4_Y_MODIFY(val) bfin_write16(DMA4_Y_MODIFY)
++#define bfin_write_DMA4_Y_MODIFY(val) bfin_write16(DMA4_Y_MODIFY, val)
+ #define bfin_read_DMA4_CURR_DESC_PTR() bfin_read32(DMA4_CURR_DESC_PTR)
+-#define bfin_write_DMA4_CURR_DESC_PTR(val) bfin_write32(DMA4_CURR_DESC_PTR)
++#define bfin_write_DMA4_CURR_DESC_PTR(val) bfin_write32(DMA4_CURR_DESC_PTR, val)
+ #define bfin_read_DMA4_CURR_ADDR() bfin_read32(DMA4_CURR_ADDR)
+-#define bfin_write_DMA4_CURR_ADDR(val) bfin_write32(DMA4_CURR_ADDR)
++#define bfin_write_DMA4_CURR_ADDR(val) bfin_write32(DMA4_CURR_ADDR, val)
+ #define bfin_read_DMA4_IRQ_STATUS() bfin_read16(DMA4_IRQ_STATUS)
+ #define bfin_write_DMA4_IRQ_STATUS(val) bfin_write16(DMA4_IRQ_STATUS, val)
+ #define bfin_read_DMA4_PERIPHERAL_MAP() bfin_read16(DMA4_PERIPHERAL_MAP)
+@@ -537,23 +533,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 5 Registers */
+
+ #define bfin_read_DMA5_NEXT_DESC_PTR() bfin_read32(DMA5_NEXT_DESC_PTR)
+-#define bfin_write_DMA5_NEXT_DESC_PTR(val) bfin_write32(DMA5_NEXT_DESC_PTR)
++#define bfin_write_DMA5_NEXT_DESC_PTR(val) bfin_write32(DMA5_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA5_START_ADDR() bfin_read32(DMA5_START_ADDR)
+-#define bfin_write_DMA5_START_ADDR(val) bfin_write32(DMA5_START_ADDR)
++#define bfin_write_DMA5_START_ADDR(val) bfin_write32(DMA5_START_ADDR, val)
+ #define bfin_read_DMA5_CONFIG() bfin_read16(DMA5_CONFIG)
+ #define bfin_write_DMA5_CONFIG(val) bfin_write16(DMA5_CONFIG, val)
+ #define bfin_read_DMA5_X_COUNT() bfin_read16(DMA5_X_COUNT)
+ #define bfin_write_DMA5_X_COUNT(val) bfin_write16(DMA5_X_COUNT, val)
+ #define bfin_read_DMA5_X_MODIFY() bfin_read16(DMA5_X_MODIFY)
+-#define bfin_write_DMA5_X_MODIFY(val) bfin_write16(DMA5_X_MODIFY)
++#define bfin_write_DMA5_X_MODIFY(val) bfin_write16(DMA5_X_MODIFY, val)
+ #define bfin_read_DMA5_Y_COUNT() bfin_read16(DMA5_Y_COUNT)
+ #define bfin_write_DMA5_Y_COUNT(val) bfin_write16(DMA5_Y_COUNT, val)
+ #define bfin_read_DMA5_Y_MODIFY() bfin_read16(DMA5_Y_MODIFY)
+-#define bfin_write_DMA5_Y_MODIFY(val) bfin_write16(DMA5_Y_MODIFY)
++#define bfin_write_DMA5_Y_MODIFY(val) bfin_write16(DMA5_Y_MODIFY, val)
+ #define bfin_read_DMA5_CURR_DESC_PTR() bfin_read32(DMA5_CURR_DESC_PTR)
+-#define bfin_write_DMA5_CURR_DESC_PTR(val) bfin_write32(DMA5_CURR_DESC_PTR)
++#define bfin_write_DMA5_CURR_DESC_PTR(val) bfin_write32(DMA5_CURR_DESC_PTR, val)
+ #define bfin_read_DMA5_CURR_ADDR() bfin_read32(DMA5_CURR_ADDR)
+-#define bfin_write_DMA5_CURR_ADDR(val) bfin_write32(DMA5_CURR_ADDR)
++#define bfin_write_DMA5_CURR_ADDR(val) bfin_write32(DMA5_CURR_ADDR, val)
+ #define bfin_read_DMA5_IRQ_STATUS() bfin_read16(DMA5_IRQ_STATUS)
+ #define bfin_write_DMA5_IRQ_STATUS(val) bfin_write16(DMA5_IRQ_STATUS, val)
+ #define bfin_read_DMA5_PERIPHERAL_MAP() bfin_read16(DMA5_PERIPHERAL_MAP)
+@@ -566,23 +562,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 6 Registers */
+
+ #define bfin_read_DMA6_NEXT_DESC_PTR() bfin_read32(DMA6_NEXT_DESC_PTR)
+-#define bfin_write_DMA6_NEXT_DESC_PTR(val) bfin_write32(DMA6_NEXT_DESC_PTR)
++#define bfin_write_DMA6_NEXT_DESC_PTR(val) bfin_write32(DMA6_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA6_START_ADDR() bfin_read32(DMA6_START_ADDR)
+-#define bfin_write_DMA6_START_ADDR(val) bfin_write32(DMA6_START_ADDR)
++#define bfin_write_DMA6_START_ADDR(val) bfin_write32(DMA6_START_ADDR, val)
+ #define bfin_read_DMA6_CONFIG() bfin_read16(DMA6_CONFIG)
+ #define bfin_write_DMA6_CONFIG(val) bfin_write16(DMA6_CONFIG, val)
+ #define bfin_read_DMA6_X_COUNT() bfin_read16(DMA6_X_COUNT)
+ #define bfin_write_DMA6_X_COUNT(val) bfin_write16(DMA6_X_COUNT, val)
+ #define bfin_read_DMA6_X_MODIFY() bfin_read16(DMA6_X_MODIFY)
+-#define bfin_write_DMA6_X_MODIFY(val) bfin_write16(DMA6_X_MODIFY)
++#define bfin_write_DMA6_X_MODIFY(val) bfin_write16(DMA6_X_MODIFY, val)
+ #define bfin_read_DMA6_Y_COUNT() bfin_read16(DMA6_Y_COUNT)
+ #define bfin_write_DMA6_Y_COUNT(val) bfin_write16(DMA6_Y_COUNT, val)
+ #define bfin_read_DMA6_Y_MODIFY() bfin_read16(DMA6_Y_MODIFY)
+-#define bfin_write_DMA6_Y_MODIFY(val) bfin_write16(DMA6_Y_MODIFY)
++#define bfin_write_DMA6_Y_MODIFY(val) bfin_write16(DMA6_Y_MODIFY, val)
+ #define bfin_read_DMA6_CURR_DESC_PTR() bfin_read32(DMA6_CURR_DESC_PTR)
+-#define bfin_write_DMA6_CURR_DESC_PTR(val) bfin_write32(DMA6_CURR_DESC_PTR)
++#define bfin_write_DMA6_CURR_DESC_PTR(val) bfin_write32(DMA6_CURR_DESC_PTR, val)
+ #define bfin_read_DMA6_CURR_ADDR() bfin_read32(DMA6_CURR_ADDR)
+-#define bfin_write_DMA6_CURR_ADDR(val) bfin_write32(DMA6_CURR_ADDR)
++#define bfin_write_DMA6_CURR_ADDR(val) bfin_write32(DMA6_CURR_ADDR, val)
+ #define bfin_read_DMA6_IRQ_STATUS() bfin_read16(DMA6_IRQ_STATUS)
+ #define bfin_write_DMA6_IRQ_STATUS(val) bfin_write16(DMA6_IRQ_STATUS, val)
+ #define bfin_read_DMA6_PERIPHERAL_MAP() bfin_read16(DMA6_PERIPHERAL_MAP)
+@@ -595,23 +591,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 7 Registers */
+
+ #define bfin_read_DMA7_NEXT_DESC_PTR() bfin_read32(DMA7_NEXT_DESC_PTR)
+-#define bfin_write_DMA7_NEXT_DESC_PTR(val) bfin_write32(DMA7_NEXT_DESC_PTR)
++#define bfin_write_DMA7_NEXT_DESC_PTR(val) bfin_write32(DMA7_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA7_START_ADDR() bfin_read32(DMA7_START_ADDR)
+-#define bfin_write_DMA7_START_ADDR(val) bfin_write32(DMA7_START_ADDR)
++#define bfin_write_DMA7_START_ADDR(val) bfin_write32(DMA7_START_ADDR, val)
+ #define bfin_read_DMA7_CONFIG() bfin_read16(DMA7_CONFIG)
+ #define bfin_write_DMA7_CONFIG(val) bfin_write16(DMA7_CONFIG, val)
+ #define bfin_read_DMA7_X_COUNT() bfin_read16(DMA7_X_COUNT)
+ #define bfin_write_DMA7_X_COUNT(val) bfin_write16(DMA7_X_COUNT, val)
+ #define bfin_read_DMA7_X_MODIFY() bfin_read16(DMA7_X_MODIFY)
+-#define bfin_write_DMA7_X_MODIFY(val) bfin_write16(DMA7_X_MODIFY)
++#define bfin_write_DMA7_X_MODIFY(val) bfin_write16(DMA7_X_MODIFY, val)
+ #define bfin_read_DMA7_Y_COUNT() bfin_read16(DMA7_Y_COUNT)
+ #define bfin_write_DMA7_Y_COUNT(val) bfin_write16(DMA7_Y_COUNT, val)
+ #define bfin_read_DMA7_Y_MODIFY() bfin_read16(DMA7_Y_MODIFY)
+-#define bfin_write_DMA7_Y_MODIFY(val) bfin_write16(DMA7_Y_MODIFY)
++#define bfin_write_DMA7_Y_MODIFY(val) bfin_write16(DMA7_Y_MODIFY, val)
+ #define bfin_read_DMA7_CURR_DESC_PTR() bfin_read32(DMA7_CURR_DESC_PTR)
+-#define bfin_write_DMA7_CURR_DESC_PTR(val) bfin_write32(DMA7_CURR_DESC_PTR)
++#define bfin_write_DMA7_CURR_DESC_PTR(val) bfin_write32(DMA7_CURR_DESC_PTR, val)
+ #define bfin_read_DMA7_CURR_ADDR() bfin_read32(DMA7_CURR_ADDR)
+-#define bfin_write_DMA7_CURR_ADDR(val) bfin_write32(DMA7_CURR_ADDR)
++#define bfin_write_DMA7_CURR_ADDR(val) bfin_write32(DMA7_CURR_ADDR, val)
+ #define bfin_read_DMA7_IRQ_STATUS() bfin_read16(DMA7_IRQ_STATUS)
+ #define bfin_write_DMA7_IRQ_STATUS(val) bfin_write16(DMA7_IRQ_STATUS, val)
+ #define bfin_read_DMA7_PERIPHERAL_MAP() bfin_read16(DMA7_PERIPHERAL_MAP)
+@@ -624,23 +620,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 8 Registers */
+
+ #define bfin_read_DMA8_NEXT_DESC_PTR() bfin_read32(DMA8_NEXT_DESC_PTR)
+-#define bfin_write_DMA8_NEXT_DESC_PTR(val) bfin_write32(DMA8_NEXT_DESC_PTR)
++#define bfin_write_DMA8_NEXT_DESC_PTR(val) bfin_write32(DMA8_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA8_START_ADDR() bfin_read32(DMA8_START_ADDR)
+-#define bfin_write_DMA8_START_ADDR(val) bfin_write32(DMA8_START_ADDR)
++#define bfin_write_DMA8_START_ADDR(val) bfin_write32(DMA8_START_ADDR, val)
+ #define bfin_read_DMA8_CONFIG() bfin_read16(DMA8_CONFIG)
+ #define bfin_write_DMA8_CONFIG(val) bfin_write16(DMA8_CONFIG, val)
+ #define bfin_read_DMA8_X_COUNT() bfin_read16(DMA8_X_COUNT)
+ #define bfin_write_DMA8_X_COUNT(val) bfin_write16(DMA8_X_COUNT, val)
+ #define bfin_read_DMA8_X_MODIFY() bfin_read16(DMA8_X_MODIFY)
+-#define bfin_write_DMA8_X_MODIFY(val) bfin_write16(DMA8_X_MODIFY)
++#define bfin_write_DMA8_X_MODIFY(val) bfin_write16(DMA8_X_MODIFY, val)
+ #define bfin_read_DMA8_Y_COUNT() bfin_read16(DMA8_Y_COUNT)
+ #define bfin_write_DMA8_Y_COUNT(val) bfin_write16(DMA8_Y_COUNT, val)
+ #define bfin_read_DMA8_Y_MODIFY() bfin_read16(DMA8_Y_MODIFY)
+-#define bfin_write_DMA8_Y_MODIFY(val) bfin_write16(DMA8_Y_MODIFY)
++#define bfin_write_DMA8_Y_MODIFY(val) bfin_write16(DMA8_Y_MODIFY, val)
+ #define bfin_read_DMA8_CURR_DESC_PTR() bfin_read32(DMA8_CURR_DESC_PTR)
+-#define bfin_write_DMA8_CURR_DESC_PTR(val) bfin_write32(DMA8_CURR_DESC_PTR)
++#define bfin_write_DMA8_CURR_DESC_PTR(val) bfin_write32(DMA8_CURR_DESC_PTR, val)
+ #define bfin_read_DMA8_CURR_ADDR() bfin_read32(DMA8_CURR_ADDR)
+-#define bfin_write_DMA8_CURR_ADDR(val) bfin_write32(DMA8_CURR_ADDR)
++#define bfin_write_DMA8_CURR_ADDR(val) bfin_write32(DMA8_CURR_ADDR, val)
+ #define bfin_read_DMA8_IRQ_STATUS() bfin_read16(DMA8_IRQ_STATUS)
+ #define bfin_write_DMA8_IRQ_STATUS(val) bfin_write16(DMA8_IRQ_STATUS, val)
+ #define bfin_read_DMA8_PERIPHERAL_MAP() bfin_read16(DMA8_PERIPHERAL_MAP)
+@@ -653,23 +649,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 9 Registers */
+
+ #define bfin_read_DMA9_NEXT_DESC_PTR() bfin_read32(DMA9_NEXT_DESC_PTR)
+-#define bfin_write_DMA9_NEXT_DESC_PTR(val) bfin_write32(DMA9_NEXT_DESC_PTR)
++#define bfin_write_DMA9_NEXT_DESC_PTR(val) bfin_write32(DMA9_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA9_START_ADDR() bfin_read32(DMA9_START_ADDR)
+-#define bfin_write_DMA9_START_ADDR(val) bfin_write32(DMA9_START_ADDR)
++#define bfin_write_DMA9_START_ADDR(val) bfin_write32(DMA9_START_ADDR, val)
+ #define bfin_read_DMA9_CONFIG() bfin_read16(DMA9_CONFIG)
+ #define bfin_write_DMA9_CONFIG(val) bfin_write16(DMA9_CONFIG, val)
+ #define bfin_read_DMA9_X_COUNT() bfin_read16(DMA9_X_COUNT)
+ #define bfin_write_DMA9_X_COUNT(val) bfin_write16(DMA9_X_COUNT, val)
+ #define bfin_read_DMA9_X_MODIFY() bfin_read16(DMA9_X_MODIFY)
+-#define bfin_write_DMA9_X_MODIFY(val) bfin_write16(DMA9_X_MODIFY)
++#define bfin_write_DMA9_X_MODIFY(val) bfin_write16(DMA9_X_MODIFY, val)
+ #define bfin_read_DMA9_Y_COUNT() bfin_read16(DMA9_Y_COUNT)
+ #define bfin_write_DMA9_Y_COUNT(val) bfin_write16(DMA9_Y_COUNT, val)
+ #define bfin_read_DMA9_Y_MODIFY() bfin_read16(DMA9_Y_MODIFY)
+-#define bfin_write_DMA9_Y_MODIFY(val) bfin_write16(DMA9_Y_MODIFY)
++#define bfin_write_DMA9_Y_MODIFY(val) bfin_write16(DMA9_Y_MODIFY, val)
+ #define bfin_read_DMA9_CURR_DESC_PTR() bfin_read32(DMA9_CURR_DESC_PTR)
+-#define bfin_write_DMA9_CURR_DESC_PTR(val) bfin_write32(DMA9_CURR_DESC_PTR)
++#define bfin_write_DMA9_CURR_DESC_PTR(val) bfin_write32(DMA9_CURR_DESC_PTR, val)
+ #define bfin_read_DMA9_CURR_ADDR() bfin_read32(DMA9_CURR_ADDR)
+-#define bfin_write_DMA9_CURR_ADDR(val) bfin_write32(DMA9_CURR_ADDR)
++#define bfin_write_DMA9_CURR_ADDR(val) bfin_write32(DMA9_CURR_ADDR, val)
+ #define bfin_read_DMA9_IRQ_STATUS() bfin_read16(DMA9_IRQ_STATUS)
+ #define bfin_write_DMA9_IRQ_STATUS(val) bfin_write16(DMA9_IRQ_STATUS, val)
+ #define bfin_read_DMA9_PERIPHERAL_MAP() bfin_read16(DMA9_PERIPHERAL_MAP)
+@@ -682,23 +678,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 10 Registers */
+
+ #define bfin_read_DMA10_NEXT_DESC_PTR() bfin_read32(DMA10_NEXT_DESC_PTR)
+-#define bfin_write_DMA10_NEXT_DESC_PTR(val) bfin_write32(DMA10_NEXT_DESC_PTR)
++#define bfin_write_DMA10_NEXT_DESC_PTR(val) bfin_write32(DMA10_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA10_START_ADDR() bfin_read32(DMA10_START_ADDR)
+-#define bfin_write_DMA10_START_ADDR(val) bfin_write32(DMA10_START_ADDR)
++#define bfin_write_DMA10_START_ADDR(val) bfin_write32(DMA10_START_ADDR, val)
+ #define bfin_read_DMA10_CONFIG() bfin_read16(DMA10_CONFIG)
+ #define bfin_write_DMA10_CONFIG(val) bfin_write16(DMA10_CONFIG, val)
+ #define bfin_read_DMA10_X_COUNT() bfin_read16(DMA10_X_COUNT)
+ #define bfin_write_DMA10_X_COUNT(val) bfin_write16(DMA10_X_COUNT, val)
+ #define bfin_read_DMA10_X_MODIFY() bfin_read16(DMA10_X_MODIFY)
+-#define bfin_write_DMA10_X_MODIFY(val) bfin_write16(DMA10_X_MODIFY)
++#define bfin_write_DMA10_X_MODIFY(val) bfin_write16(DMA10_X_MODIFY, val)
+ #define bfin_read_DMA10_Y_COUNT() bfin_read16(DMA10_Y_COUNT)
+ #define bfin_write_DMA10_Y_COUNT(val) bfin_write16(DMA10_Y_COUNT, val)
+ #define bfin_read_DMA10_Y_MODIFY() bfin_read16(DMA10_Y_MODIFY)
+-#define bfin_write_DMA10_Y_MODIFY(val) bfin_write16(DMA10_Y_MODIFY)
++#define bfin_write_DMA10_Y_MODIFY(val) bfin_write16(DMA10_Y_MODIFY, val)
+ #define bfin_read_DMA10_CURR_DESC_PTR() bfin_read32(DMA10_CURR_DESC_PTR)
+-#define bfin_write_DMA10_CURR_DESC_PTR(val) bfin_write32(DMA10_CURR_DESC_PTR)
++#define bfin_write_DMA10_CURR_DESC_PTR(val) bfin_write32(DMA10_CURR_DESC_PTR, val)
+ #define bfin_read_DMA10_CURR_ADDR() bfin_read32(DMA10_CURR_ADDR)
+-#define bfin_write_DMA10_CURR_ADDR(val) bfin_write32(DMA10_CURR_ADDR)
++#define bfin_write_DMA10_CURR_ADDR(val) bfin_write32(DMA10_CURR_ADDR, val)
+ #define bfin_read_DMA10_IRQ_STATUS() bfin_read16(DMA10_IRQ_STATUS)
+ #define bfin_write_DMA10_IRQ_STATUS(val) bfin_write16(DMA10_IRQ_STATUS, val)
+ #define bfin_read_DMA10_PERIPHERAL_MAP() bfin_read16(DMA10_PERIPHERAL_MAP)
+@@ -711,23 +707,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 11 Registers */
+
+ #define bfin_read_DMA11_NEXT_DESC_PTR() bfin_read32(DMA11_NEXT_DESC_PTR)
+-#define bfin_write_DMA11_NEXT_DESC_PTR(val) bfin_write32(DMA11_NEXT_DESC_PTR)
++#define bfin_write_DMA11_NEXT_DESC_PTR(val) bfin_write32(DMA11_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA11_START_ADDR() bfin_read32(DMA11_START_ADDR)
+-#define bfin_write_DMA11_START_ADDR(val) bfin_write32(DMA11_START_ADDR)
++#define bfin_write_DMA11_START_ADDR(val) bfin_write32(DMA11_START_ADDR, val)
+ #define bfin_read_DMA11_CONFIG() bfin_read16(DMA11_CONFIG)
+ #define bfin_write_DMA11_CONFIG(val) bfin_write16(DMA11_CONFIG, val)
+ #define bfin_read_DMA11_X_COUNT() bfin_read16(DMA11_X_COUNT)
+ #define bfin_write_DMA11_X_COUNT(val) bfin_write16(DMA11_X_COUNT, val)
+ #define bfin_read_DMA11_X_MODIFY() bfin_read16(DMA11_X_MODIFY)
+-#define bfin_write_DMA11_X_MODIFY(val) bfin_write16(DMA11_X_MODIFY)
++#define bfin_write_DMA11_X_MODIFY(val) bfin_write16(DMA11_X_MODIFY, val)
+ #define bfin_read_DMA11_Y_COUNT() bfin_read16(DMA11_Y_COUNT)
+ #define bfin_write_DMA11_Y_COUNT(val) bfin_write16(DMA11_Y_COUNT, val)
+ #define bfin_read_DMA11_Y_MODIFY() bfin_read16(DMA11_Y_MODIFY)
+-#define bfin_write_DMA11_Y_MODIFY(val) bfin_write16(DMA11_Y_MODIFY)
++#define bfin_write_DMA11_Y_MODIFY(val) bfin_write16(DMA11_Y_MODIFY, val)
+ #define bfin_read_DMA11_CURR_DESC_PTR() bfin_read32(DMA11_CURR_DESC_PTR)
+-#define bfin_write_DMA11_CURR_DESC_PTR(val) bfin_write32(DMA11_CURR_DESC_PTR)
++#define bfin_write_DMA11_CURR_DESC_PTR(val) bfin_write32(DMA11_CURR_DESC_PTR, val)
+ #define bfin_read_DMA11_CURR_ADDR() bfin_read32(DMA11_CURR_ADDR)
+-#define bfin_write_DMA11_CURR_ADDR(val) bfin_write32(DMA11_CURR_ADDR)
++#define bfin_write_DMA11_CURR_ADDR(val) bfin_write32(DMA11_CURR_ADDR, val)
+ #define bfin_read_DMA11_IRQ_STATUS() bfin_read16(DMA11_IRQ_STATUS)
+ #define bfin_write_DMA11_IRQ_STATUS(val) bfin_write16(DMA11_IRQ_STATUS, val)
+ #define bfin_read_DMA11_PERIPHERAL_MAP() bfin_read16(DMA11_PERIPHERAL_MAP)
+@@ -740,7 +736,7 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* MDMA Stream 0 Registers */
+
+ #define bfin_read_MDMA_D0_NEXT_DESC_PTR() bfin_read32(MDMA_D0_NEXT_DESC_PTR)
+-#define bfin_write_MDMA_D0_NEXT_DESC_PTR(val) bfin_write32(MDMA_D0_NEXT_DESC_PTR)
++#define bfin_write_MDMA_D0_NEXT_DESC_PTR(val) bfin_write32(MDMA_D0_NEXT_DESC_PTR, val)
+ #define bfin_read_MDMA_D0_START_ADDR() bfin_read32(MDMA_D0_START_ADDR)
+ #define bfin_write_MDMA_D0_START_ADDR(val) bfin_write32(MDMA_D0_START_ADDR, val)
+ #define bfin_read_MDMA_D0_CONFIG() bfin_read16(MDMA_D0_CONFIG)
+@@ -803,11 +799,11 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ #define bfin_read_MDMA_D1_X_COUNT() bfin_read16(MDMA_D1_X_COUNT)
+ #define bfin_write_MDMA_D1_X_COUNT(val) bfin_write16(MDMA_D1_X_COUNT, val)
+ #define bfin_read_MDMA_D1_X_MODIFY() bfin_read16(MDMA_D1_X_MODIFY)
+-#define bfin_write_MDMA_D1_X_MODIFY(val) bfin_write16(MDMA_D1_X_MODIFY)
++#define bfin_write_MDMA_D1_X_MODIFY(val) bfin_write16(MDMA_D1_X_MODIFY, val)
+ #define bfin_read_MDMA_D1_Y_COUNT() bfin_read16(MDMA_D1_Y_COUNT)
+ #define bfin_write_MDMA_D1_Y_COUNT(val) bfin_write16(MDMA_D1_Y_COUNT, val)
+ #define bfin_read_MDMA_D1_Y_MODIFY() bfin_read16(MDMA_D1_Y_MODIFY)
+-#define bfin_write_MDMA_D1_Y_MODIFY(val) bfin_write16(MDMA_D1_Y_MODIFY)
++#define bfin_write_MDMA_D1_Y_MODIFY(val) bfin_write16(MDMA_D1_Y_MODIFY, val)
+ #define bfin_read_MDMA_D1_CURR_DESC_PTR() bfin_read32(MDMA_D1_CURR_DESC_PTR)
+ #define bfin_write_MDMA_D1_CURR_DESC_PTR(val) bfin_write32(MDMA_D1_CURR_DESC_PTR, val)
+ #define bfin_read_MDMA_D1_CURR_ADDR() bfin_read32(MDMA_D1_CURR_ADDR)
+@@ -829,11 +825,11 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ #define bfin_read_MDMA_S1_X_COUNT() bfin_read16(MDMA_S1_X_COUNT)
+ #define bfin_write_MDMA_S1_X_COUNT(val) bfin_write16(MDMA_S1_X_COUNT, val)
+ #define bfin_read_MDMA_S1_X_MODIFY() bfin_read16(MDMA_S1_X_MODIFY)
+-#define bfin_write_MDMA_S1_X_MODIFY(val) bfin_write16(MDMA_S1_X_MODIFY)
++#define bfin_write_MDMA_S1_X_MODIFY(val) bfin_write16(MDMA_S1_X_MODIFY, val)
+ #define bfin_read_MDMA_S1_Y_COUNT() bfin_read16(MDMA_S1_Y_COUNT)
+ #define bfin_write_MDMA_S1_Y_COUNT(val) bfin_write16(MDMA_S1_Y_COUNT, val)
+ #define bfin_read_MDMA_S1_Y_MODIFY() bfin_read16(MDMA_S1_Y_MODIFY)
+-#define bfin_write_MDMA_S1_Y_MODIFY(val) bfin_write16(MDMA_S1_Y_MODIFY)
++#define bfin_write_MDMA_S1_Y_MODIFY(val) bfin_write16(MDMA_S1_Y_MODIFY, val)
+ #define bfin_read_MDMA_S1_CURR_DESC_PTR() bfin_read32(MDMA_S1_CURR_DESC_PTR)
+ #define bfin_write_MDMA_S1_CURR_DESC_PTR(val) bfin_write32(MDMA_S1_CURR_DESC_PTR, val)
+ #define bfin_read_MDMA_S1_CURR_ADDR() bfin_read32(MDMA_S1_CURR_ADDR)
+@@ -1246,23 +1242,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 12 Registers */
+
+ #define bfin_read_DMA12_NEXT_DESC_PTR() bfin_read32(DMA12_NEXT_DESC_PTR)
+-#define bfin_write_DMA12_NEXT_DESC_PTR(val) bfin_write32(DMA12_NEXT_DESC_PTR)
++#define bfin_write_DMA12_NEXT_DESC_PTR(val) bfin_write32(DMA12_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA12_START_ADDR() bfin_read32(DMA12_START_ADDR)
+-#define bfin_write_DMA12_START_ADDR(val) bfin_write32(DMA12_START_ADDR)
++#define bfin_write_DMA12_START_ADDR(val) bfin_write32(DMA12_START_ADDR, val)
+ #define bfin_read_DMA12_CONFIG() bfin_read16(DMA12_CONFIG)
+ #define bfin_write_DMA12_CONFIG(val) bfin_write16(DMA12_CONFIG, val)
+ #define bfin_read_DMA12_X_COUNT() bfin_read16(DMA12_X_COUNT)
+ #define bfin_write_DMA12_X_COUNT(val) bfin_write16(DMA12_X_COUNT, val)
+ #define bfin_read_DMA12_X_MODIFY() bfin_read16(DMA12_X_MODIFY)
+-#define bfin_write_DMA12_X_MODIFY(val) bfin_write16(DMA12_X_MODIFY)
++#define bfin_write_DMA12_X_MODIFY(val) bfin_write16(DMA12_X_MODIFY, val)
+ #define bfin_read_DMA12_Y_COUNT() bfin_read16(DMA12_Y_COUNT)
+ #define bfin_write_DMA12_Y_COUNT(val) bfin_write16(DMA12_Y_COUNT, val)
+ #define bfin_read_DMA12_Y_MODIFY() bfin_read16(DMA12_Y_MODIFY)
+-#define bfin_write_DMA12_Y_MODIFY(val) bfin_write16(DMA12_Y_MODIFY)
++#define bfin_write_DMA12_Y_MODIFY(val) bfin_write16(DMA12_Y_MODIFY, val)
+ #define bfin_read_DMA12_CURR_DESC_PTR() bfin_read32(DMA12_CURR_DESC_PTR)
+-#define bfin_write_DMA12_CURR_DESC_PTR(val) bfin_write32(DMA12_CURR_DESC_PTR)
++#define bfin_write_DMA12_CURR_DESC_PTR(val) bfin_write32(DMA12_CURR_DESC_PTR, val)
+ #define bfin_read_DMA12_CURR_ADDR() bfin_read32(DMA12_CURR_ADDR)
+-#define bfin_write_DMA12_CURR_ADDR(val) bfin_write32(DMA12_CURR_ADDR)
++#define bfin_write_DMA12_CURR_ADDR(val) bfin_write32(DMA12_CURR_ADDR, val)
+ #define bfin_read_DMA12_IRQ_STATUS() bfin_read16(DMA12_IRQ_STATUS)
+ #define bfin_write_DMA12_IRQ_STATUS(val) bfin_write16(DMA12_IRQ_STATUS, val)
+ #define bfin_read_DMA12_PERIPHERAL_MAP() bfin_read16(DMA12_PERIPHERAL_MAP)
+@@ -1275,23 +1271,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 13 Registers */
+
+ #define bfin_read_DMA13_NEXT_DESC_PTR() bfin_read32(DMA13_NEXT_DESC_PTR)
+-#define bfin_write_DMA13_NEXT_DESC_PTR(val) bfin_write32(DMA13_NEXT_DESC_PTR)
++#define bfin_write_DMA13_NEXT_DESC_PTR(val) bfin_write32(DMA13_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA13_START_ADDR() bfin_read32(DMA13_START_ADDR)
+-#define bfin_write_DMA13_START_ADDR(val) bfin_write32(DMA13_START_ADDR)
++#define bfin_write_DMA13_START_ADDR(val) bfin_write32(DMA13_START_ADDR, val)
+ #define bfin_read_DMA13_CONFIG() bfin_read16(DMA13_CONFIG)
+ #define bfin_write_DMA13_CONFIG(val) bfin_write16(DMA13_CONFIG, val)
+ #define bfin_read_DMA13_X_COUNT() bfin_read16(DMA13_X_COUNT)
+ #define bfin_write_DMA13_X_COUNT(val) bfin_write16(DMA13_X_COUNT, val)
+ #define bfin_read_DMA13_X_MODIFY() bfin_read16(DMA13_X_MODIFY)
+-#define bfin_write_DMA13_X_MODIFY(val) bfin_write16(DMA13_X_MODIFY)
++#define bfin_write_DMA13_X_MODIFY(val) bfin_write16(DMA13_X_MODIFY, val)
+ #define bfin_read_DMA13_Y_COUNT() bfin_read16(DMA13_Y_COUNT)
+ #define bfin_write_DMA13_Y_COUNT(val) bfin_write16(DMA13_Y_COUNT, val)
+ #define bfin_read_DMA13_Y_MODIFY() bfin_read16(DMA13_Y_MODIFY)
+-#define bfin_write_DMA13_Y_MODIFY(val) bfin_write16(DMA13_Y_MODIFY)
++#define bfin_write_DMA13_Y_MODIFY(val) bfin_write16(DMA13_Y_MODIFY, val)
+ #define bfin_read_DMA13_CURR_DESC_PTR() bfin_read32(DMA13_CURR_DESC_PTR)
+-#define bfin_write_DMA13_CURR_DESC_PTR(val) bfin_write32(DMA13_CURR_DESC_PTR)
++#define bfin_write_DMA13_CURR_DESC_PTR(val) bfin_write32(DMA13_CURR_DESC_PTR, val)
+ #define bfin_read_DMA13_CURR_ADDR() bfin_read32(DMA13_CURR_ADDR)
+-#define bfin_write_DMA13_CURR_ADDR(val) bfin_write32(DMA13_CURR_ADDR)
++#define bfin_write_DMA13_CURR_ADDR(val) bfin_write32(DMA13_CURR_ADDR, val)
+ #define bfin_read_DMA13_IRQ_STATUS() bfin_read16(DMA13_IRQ_STATUS)
+ #define bfin_write_DMA13_IRQ_STATUS(val) bfin_write16(DMA13_IRQ_STATUS, val)
+ #define bfin_read_DMA13_PERIPHERAL_MAP() bfin_read16(DMA13_PERIPHERAL_MAP)
+@@ -1304,23 +1300,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 14 Registers */
+
+ #define bfin_read_DMA14_NEXT_DESC_PTR() bfin_read32(DMA14_NEXT_DESC_PTR)
+-#define bfin_write_DMA14_NEXT_DESC_PTR(val) bfin_write32(DMA14_NEXT_DESC_PTR)
++#define bfin_write_DMA14_NEXT_DESC_PTR(val) bfin_write32(DMA14_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA14_START_ADDR() bfin_read32(DMA14_START_ADDR)
+-#define bfin_write_DMA14_START_ADDR(val) bfin_write32(DMA14_START_ADDR)
++#define bfin_write_DMA14_START_ADDR(val) bfin_write32(DMA14_START_ADDR, val)
+ #define bfin_read_DMA14_CONFIG() bfin_read16(DMA14_CONFIG)
+ #define bfin_write_DMA14_CONFIG(val) bfin_write16(DMA14_CONFIG, val)
+ #define bfin_read_DMA14_X_COUNT() bfin_read16(DMA14_X_COUNT)
+ #define bfin_write_DMA14_X_COUNT(val) bfin_write16(DMA14_X_COUNT, val)
+ #define bfin_read_DMA14_X_MODIFY() bfin_read16(DMA14_X_MODIFY)
+-#define bfin_write_DMA14_X_MODIFY(val) bfin_write16(DMA14_X_MODIFY)
++#define bfin_write_DMA14_X_MODIFY(val) bfin_write16(DMA14_X_MODIFY, val)
+ #define bfin_read_DMA14_Y_COUNT() bfin_read16(DMA14_Y_COUNT)
+ #define bfin_write_DMA14_Y_COUNT(val) bfin_write16(DMA14_Y_COUNT, val)
+ #define bfin_read_DMA14_Y_MODIFY() bfin_read16(DMA14_Y_MODIFY)
+-#define bfin_write_DMA14_Y_MODIFY(val) bfin_write16(DMA14_Y_MODIFY)
++#define bfin_write_DMA14_Y_MODIFY(val) bfin_write16(DMA14_Y_MODIFY, val)
+ #define bfin_read_DMA14_CURR_DESC_PTR() bfin_read32(DMA14_CURR_DESC_PTR)
+-#define bfin_write_DMA14_CURR_DESC_PTR(val) bfin_write32(DMA14_CURR_DESC_PTR)
++#define bfin_write_DMA14_CURR_DESC_PTR(val) bfin_write32(DMA14_CURR_DESC_PTR, val)
+ #define bfin_read_DMA14_CURR_ADDR() bfin_read32(DMA14_CURR_ADDR)
+-#define bfin_write_DMA14_CURR_ADDR(val) bfin_write32(DMA14_CURR_ADDR)
++#define bfin_write_DMA14_CURR_ADDR(val) bfin_write32(DMA14_CURR_ADDR, val)
+ #define bfin_read_DMA14_IRQ_STATUS() bfin_read16(DMA14_IRQ_STATUS)
+ #define bfin_write_DMA14_IRQ_STATUS(val) bfin_write16(DMA14_IRQ_STATUS, val)
+ #define bfin_read_DMA14_PERIPHERAL_MAP() bfin_read16(DMA14_PERIPHERAL_MAP)
+@@ -1333,23 +1329,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 15 Registers */
+
+ #define bfin_read_DMA15_NEXT_DESC_PTR() bfin_read32(DMA15_NEXT_DESC_PTR)
+-#define bfin_write_DMA15_NEXT_DESC_PTR(val) bfin_write32(DMA15_NEXT_DESC_PTR)
++#define bfin_write_DMA15_NEXT_DESC_PTR(val) bfin_write32(DMA15_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA15_START_ADDR() bfin_read32(DMA15_START_ADDR)
+-#define bfin_write_DMA15_START_ADDR(val) bfin_write32(DMA15_START_ADDR)
++#define bfin_write_DMA15_START_ADDR(val) bfin_write32(DMA15_START_ADDR, val)
+ #define bfin_read_DMA15_CONFIG() bfin_read16(DMA15_CONFIG)
+ #define bfin_write_DMA15_CONFIG(val) bfin_write16(DMA15_CONFIG, val)
+ #define bfin_read_DMA15_X_COUNT() bfin_read16(DMA15_X_COUNT)
+ #define bfin_write_DMA15_X_COUNT(val) bfin_write16(DMA15_X_COUNT, val)
+ #define bfin_read_DMA15_X_MODIFY() bfin_read16(DMA15_X_MODIFY)
+-#define bfin_write_DMA15_X_MODIFY(val) bfin_write16(DMA15_X_MODIFY)
++#define bfin_write_DMA15_X_MODIFY(val) bfin_write16(DMA15_X_MODIFY, val)
+ #define bfin_read_DMA15_Y_COUNT() bfin_read16(DMA15_Y_COUNT)
+ #define bfin_write_DMA15_Y_COUNT(val) bfin_write16(DMA15_Y_COUNT, val)
+ #define bfin_read_DMA15_Y_MODIFY() bfin_read16(DMA15_Y_MODIFY)
+-#define bfin_write_DMA15_Y_MODIFY(val) bfin_write16(DMA15_Y_MODIFY)
++#define bfin_write_DMA15_Y_MODIFY(val) bfin_write16(DMA15_Y_MODIFY, val)
+ #define bfin_read_DMA15_CURR_DESC_PTR() bfin_read32(DMA15_CURR_DESC_PTR)
+-#define bfin_write_DMA15_CURR_DESC_PTR(val) bfin_write32(DMA15_CURR_DESC_PTR)
++#define bfin_write_DMA15_CURR_DESC_PTR(val) bfin_write32(DMA15_CURR_DESC_PTR, val)
+ #define bfin_read_DMA15_CURR_ADDR() bfin_read32(DMA15_CURR_ADDR)
+-#define bfin_write_DMA15_CURR_ADDR(val) bfin_write32(DMA15_CURR_ADDR)
++#define bfin_write_DMA15_CURR_ADDR(val) bfin_write32(DMA15_CURR_ADDR, val)
+ #define bfin_read_DMA15_IRQ_STATUS() bfin_read16(DMA15_IRQ_STATUS)
+ #define bfin_write_DMA15_IRQ_STATUS(val) bfin_write16(DMA15_IRQ_STATUS, val)
+ #define bfin_read_DMA15_PERIPHERAL_MAP() bfin_read16(DMA15_PERIPHERAL_MAP)
+@@ -1362,23 +1358,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 16 Registers */
+
+ #define bfin_read_DMA16_NEXT_DESC_PTR() bfin_read32(DMA16_NEXT_DESC_PTR)
+-#define bfin_write_DMA16_NEXT_DESC_PTR(val) bfin_write32(DMA16_NEXT_DESC_PTR)
++#define bfin_write_DMA16_NEXT_DESC_PTR(val) bfin_write32(DMA16_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA16_START_ADDR() bfin_read32(DMA16_START_ADDR)
+-#define bfin_write_DMA16_START_ADDR(val) bfin_write32(DMA16_START_ADDR)
++#define bfin_write_DMA16_START_ADDR(val) bfin_write32(DMA16_START_ADDR, val)
+ #define bfin_read_DMA16_CONFIG() bfin_read16(DMA16_CONFIG)
+ #define bfin_write_DMA16_CONFIG(val) bfin_write16(DMA16_CONFIG, val)
+ #define bfin_read_DMA16_X_COUNT() bfin_read16(DMA16_X_COUNT)
+ #define bfin_write_DMA16_X_COUNT(val) bfin_write16(DMA16_X_COUNT, val)
+ #define bfin_read_DMA16_X_MODIFY() bfin_read16(DMA16_X_MODIFY)
+-#define bfin_write_DMA16_X_MODIFY(val) bfin_write16(DMA16_X_MODIFY)
++#define bfin_write_DMA16_X_MODIFY(val) bfin_write16(DMA16_X_MODIFY, val)
+ #define bfin_read_DMA16_Y_COUNT() bfin_read16(DMA16_Y_COUNT)
+ #define bfin_write_DMA16_Y_COUNT(val) bfin_write16(DMA16_Y_COUNT, val)
+ #define bfin_read_DMA16_Y_MODIFY() bfin_read16(DMA16_Y_MODIFY)
+-#define bfin_write_DMA16_Y_MODIFY(val) bfin_write16(DMA16_Y_MODIFY)
++#define bfin_write_DMA16_Y_MODIFY(val) bfin_write16(DMA16_Y_MODIFY, val)
+ #define bfin_read_DMA16_CURR_DESC_PTR() bfin_read32(DMA16_CURR_DESC_PTR)
+-#define bfin_write_DMA16_CURR_DESC_PTR(val) bfin_write32(DMA16_CURR_DESC_PTR)
++#define bfin_write_DMA16_CURR_DESC_PTR(val) bfin_write32(DMA16_CURR_DESC_PTR, val)
+ #define bfin_read_DMA16_CURR_ADDR() bfin_read32(DMA16_CURR_ADDR)
+-#define bfin_write_DMA16_CURR_ADDR(val) bfin_write32(DMA16_CURR_ADDR)
++#define bfin_write_DMA16_CURR_ADDR(val) bfin_write32(DMA16_CURR_ADDR, val)
+ #define bfin_read_DMA16_IRQ_STATUS() bfin_read16(DMA16_IRQ_STATUS)
+ #define bfin_write_DMA16_IRQ_STATUS(val) bfin_write16(DMA16_IRQ_STATUS, val)
+ #define bfin_read_DMA16_PERIPHERAL_MAP() bfin_read16(DMA16_PERIPHERAL_MAP)
+@@ -1391,23 +1387,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 17 Registers */
+
+ #define bfin_read_DMA17_NEXT_DESC_PTR() bfin_read32(DMA17_NEXT_DESC_PTR)
+-#define bfin_write_DMA17_NEXT_DESC_PTR(val) bfin_write32(DMA17_NEXT_DESC_PTR)
++#define bfin_write_DMA17_NEXT_DESC_PTR(val) bfin_write32(DMA17_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA17_START_ADDR() bfin_read32(DMA17_START_ADDR)
+-#define bfin_write_DMA17_START_ADDR(val) bfin_write32(DMA17_START_ADDR)
++#define bfin_write_DMA17_START_ADDR(val) bfin_write32(DMA17_START_ADDR, val)
+ #define bfin_read_DMA17_CONFIG() bfin_read16(DMA17_CONFIG)
+ #define bfin_write_DMA17_CONFIG(val) bfin_write16(DMA17_CONFIG, val)
+ #define bfin_read_DMA17_X_COUNT() bfin_read16(DMA17_X_COUNT)
+ #define bfin_write_DMA17_X_COUNT(val) bfin_write16(DMA17_X_COUNT, val)
+ #define bfin_read_DMA17_X_MODIFY() bfin_read16(DMA17_X_MODIFY)
+-#define bfin_write_DMA17_X_MODIFY(val) bfin_write16(DMA17_X_MODIFY)
++#define bfin_write_DMA17_X_MODIFY(val) bfin_write16(DMA17_X_MODIFY, val)
+ #define bfin_read_DMA17_Y_COUNT() bfin_read16(DMA17_Y_COUNT)
+ #define bfin_write_DMA17_Y_COUNT(val) bfin_write16(DMA17_Y_COUNT, val)
+ #define bfin_read_DMA17_Y_MODIFY() bfin_read16(DMA17_Y_MODIFY)
+-#define bfin_write_DMA17_Y_MODIFY(val) bfin_write16(DMA17_Y_MODIFY)
++#define bfin_write_DMA17_Y_MODIFY(val) bfin_write16(DMA17_Y_MODIFY, val)
+ #define bfin_read_DMA17_CURR_DESC_PTR() bfin_read32(DMA17_CURR_DESC_PTR)
+-#define bfin_write_DMA17_CURR_DESC_PTR(val) bfin_write32(DMA17_CURR_DESC_PTR)
++#define bfin_write_DMA17_CURR_DESC_PTR(val) bfin_write32(DMA17_CURR_DESC_PTR, val)
+ #define bfin_read_DMA17_CURR_ADDR() bfin_read32(DMA17_CURR_ADDR)
+-#define bfin_write_DMA17_CURR_ADDR(val) bfin_write32(DMA17_CURR_ADDR)
++#define bfin_write_DMA17_CURR_ADDR(val) bfin_write32(DMA17_CURR_ADDR, val)
+ #define bfin_read_DMA17_IRQ_STATUS() bfin_read16(DMA17_IRQ_STATUS)
+ #define bfin_write_DMA17_IRQ_STATUS(val) bfin_write16(DMA17_IRQ_STATUS, val)
+ #define bfin_read_DMA17_PERIPHERAL_MAP() bfin_read16(DMA17_PERIPHERAL_MAP)
+@@ -1420,23 +1416,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 18 Registers */
+
+ #define bfin_read_DMA18_NEXT_DESC_PTR() bfin_read32(DMA18_NEXT_DESC_PTR)
+-#define bfin_write_DMA18_NEXT_DESC_PTR(val) bfin_write32(DMA18_NEXT_DESC_PTR)
++#define bfin_write_DMA18_NEXT_DESC_PTR(val) bfin_write32(DMA18_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA18_START_ADDR() bfin_read32(DMA18_START_ADDR)
+-#define bfin_write_DMA18_START_ADDR(val) bfin_write32(DMA18_START_ADDR)
++#define bfin_write_DMA18_START_ADDR(val) bfin_write32(DMA18_START_ADDR, val)
+ #define bfin_read_DMA18_CONFIG() bfin_read16(DMA18_CONFIG)
+ #define bfin_write_DMA18_CONFIG(val) bfin_write16(DMA18_CONFIG, val)
+ #define bfin_read_DMA18_X_COUNT() bfin_read16(DMA18_X_COUNT)
+ #define bfin_write_DMA18_X_COUNT(val) bfin_write16(DMA18_X_COUNT, val)
+ #define bfin_read_DMA18_X_MODIFY() bfin_read16(DMA18_X_MODIFY)
+-#define bfin_write_DMA18_X_MODIFY(val) bfin_write16(DMA18_X_MODIFY)
++#define bfin_write_DMA18_X_MODIFY(val) bfin_write16(DMA18_X_MODIFY, val)
+ #define bfin_read_DMA18_Y_COUNT() bfin_read16(DMA18_Y_COUNT)
+ #define bfin_write_DMA18_Y_COUNT(val) bfin_write16(DMA18_Y_COUNT, val)
+ #define bfin_read_DMA18_Y_MODIFY() bfin_read16(DMA18_Y_MODIFY)
+-#define bfin_write_DMA18_Y_MODIFY(val) bfin_write16(DMA18_Y_MODIFY)
++#define bfin_write_DMA18_Y_MODIFY(val) bfin_write16(DMA18_Y_MODIFY, val)
+ #define bfin_read_DMA18_CURR_DESC_PTR() bfin_read32(DMA18_CURR_DESC_PTR)
+-#define bfin_write_DMA18_CURR_DESC_PTR(val) bfin_write32(DMA18_CURR_DESC_PTR)
++#define bfin_write_DMA18_CURR_DESC_PTR(val) bfin_write32(DMA18_CURR_DESC_PTR, val)
+ #define bfin_read_DMA18_CURR_ADDR() bfin_read32(DMA18_CURR_ADDR)
+-#define bfin_write_DMA18_CURR_ADDR(val) bfin_write32(DMA18_CURR_ADDR)
++#define bfin_write_DMA18_CURR_ADDR(val) bfin_write32(DMA18_CURR_ADDR, val)
+ #define bfin_read_DMA18_IRQ_STATUS() bfin_read16(DMA18_IRQ_STATUS)
+ #define bfin_write_DMA18_IRQ_STATUS(val) bfin_write16(DMA18_IRQ_STATUS, val)
+ #define bfin_read_DMA18_PERIPHERAL_MAP() bfin_read16(DMA18_PERIPHERAL_MAP)
+@@ -1449,23 +1445,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 19 Registers */
+
+ #define bfin_read_DMA19_NEXT_DESC_PTR() bfin_read32(DMA19_NEXT_DESC_PTR)
+-#define bfin_write_DMA19_NEXT_DESC_PTR(val) bfin_write32(DMA19_NEXT_DESC_PTR)
++#define bfin_write_DMA19_NEXT_DESC_PTR(val) bfin_write32(DMA19_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA19_START_ADDR() bfin_read32(DMA19_START_ADDR)
+-#define bfin_write_DMA19_START_ADDR(val) bfin_write32(DMA19_START_ADDR)
++#define bfin_write_DMA19_START_ADDR(val) bfin_write32(DMA19_START_ADDR, val)
+ #define bfin_read_DMA19_CONFIG() bfin_read16(DMA19_CONFIG)
+ #define bfin_write_DMA19_CONFIG(val) bfin_write16(DMA19_CONFIG, val)
+ #define bfin_read_DMA19_X_COUNT() bfin_read16(DMA19_X_COUNT)
+ #define bfin_write_DMA19_X_COUNT(val) bfin_write16(DMA19_X_COUNT, val)
+ #define bfin_read_DMA19_X_MODIFY() bfin_read16(DMA19_X_MODIFY)
+-#define bfin_write_DMA19_X_MODIFY(val) bfin_write16(DMA19_X_MODIFY)
++#define bfin_write_DMA19_X_MODIFY(val) bfin_write16(DMA19_X_MODIFY, val)
+ #define bfin_read_DMA19_Y_COUNT() bfin_read16(DMA19_Y_COUNT)
+ #define bfin_write_DMA19_Y_COUNT(val) bfin_write16(DMA19_Y_COUNT, val)
+ #define bfin_read_DMA19_Y_MODIFY() bfin_read16(DMA19_Y_MODIFY)
+-#define bfin_write_DMA19_Y_MODIFY(val) bfin_write16(DMA19_Y_MODIFY)
++#define bfin_write_DMA19_Y_MODIFY(val) bfin_write16(DMA19_Y_MODIFY, val)
+ #define bfin_read_DMA19_CURR_DESC_PTR() bfin_read32(DMA19_CURR_DESC_PTR)
+-#define bfin_write_DMA19_CURR_DESC_PTR(val) bfin_write32(DMA19_CURR_DESC_PTR)
++#define bfin_write_DMA19_CURR_DESC_PTR(val) bfin_write32(DMA19_CURR_DESC_PTR, val)
+ #define bfin_read_DMA19_CURR_ADDR() bfin_read32(DMA19_CURR_ADDR)
+-#define bfin_write_DMA19_CURR_ADDR(val) bfin_write32(DMA19_CURR_ADDR)
++#define bfin_write_DMA19_CURR_ADDR(val) bfin_write32(DMA19_CURR_ADDR, val)
+ #define bfin_read_DMA19_IRQ_STATUS() bfin_read16(DMA19_IRQ_STATUS)
+ #define bfin_write_DMA19_IRQ_STATUS(val) bfin_write16(DMA19_IRQ_STATUS, val)
+ #define bfin_read_DMA19_PERIPHERAL_MAP() bfin_read16(DMA19_PERIPHERAL_MAP)
+@@ -1478,23 +1474,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 20 Registers */
+
+ #define bfin_read_DMA20_NEXT_DESC_PTR() bfin_read32(DMA20_NEXT_DESC_PTR)
+-#define bfin_write_DMA20_NEXT_DESC_PTR(val) bfin_write32(DMA20_NEXT_DESC_PTR)
++#define bfin_write_DMA20_NEXT_DESC_PTR(val) bfin_write32(DMA20_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA20_START_ADDR() bfin_read32(DMA20_START_ADDR)
+-#define bfin_write_DMA20_START_ADDR(val) bfin_write32(DMA20_START_ADDR)
++#define bfin_write_DMA20_START_ADDR(val) bfin_write32(DMA20_START_ADDR, val)
+ #define bfin_read_DMA20_CONFIG() bfin_read16(DMA20_CONFIG)
+ #define bfin_write_DMA20_CONFIG(val) bfin_write16(DMA20_CONFIG, val)
+ #define bfin_read_DMA20_X_COUNT() bfin_read16(DMA20_X_COUNT)
+ #define bfin_write_DMA20_X_COUNT(val) bfin_write16(DMA20_X_COUNT, val)
+ #define bfin_read_DMA20_X_MODIFY() bfin_read16(DMA20_X_MODIFY)
+-#define bfin_write_DMA20_X_MODIFY(val) bfin_write16(DMA20_X_MODIFY)
++#define bfin_write_DMA20_X_MODIFY(val) bfin_write16(DMA20_X_MODIFY, val)
+ #define bfin_read_DMA20_Y_COUNT() bfin_read16(DMA20_Y_COUNT)
+ #define bfin_write_DMA20_Y_COUNT(val) bfin_write16(DMA20_Y_COUNT, val)
+ #define bfin_read_DMA20_Y_MODIFY() bfin_read16(DMA20_Y_MODIFY)
+-#define bfin_write_DMA20_Y_MODIFY(val) bfin_write16(DMA20_Y_MODIFY)
++#define bfin_write_DMA20_Y_MODIFY(val) bfin_write16(DMA20_Y_MODIFY, val)
+ #define bfin_read_DMA20_CURR_DESC_PTR() bfin_read32(DMA20_CURR_DESC_PTR)
+-#define bfin_write_DMA20_CURR_DESC_PTR(val) bfin_write32(DMA20_CURR_DESC_PTR)
++#define bfin_write_DMA20_CURR_DESC_PTR(val) bfin_write32(DMA20_CURR_DESC_PTR, val)
+ #define bfin_read_DMA20_CURR_ADDR() bfin_read32(DMA20_CURR_ADDR)
+-#define bfin_write_DMA20_CURR_ADDR(val) bfin_write32(DMA20_CURR_ADDR)
++#define bfin_write_DMA20_CURR_ADDR(val) bfin_write32(DMA20_CURR_ADDR, val)
+ #define bfin_read_DMA20_IRQ_STATUS() bfin_read16(DMA20_IRQ_STATUS)
+ #define bfin_write_DMA20_IRQ_STATUS(val) bfin_write16(DMA20_IRQ_STATUS, val)
+ #define bfin_read_DMA20_PERIPHERAL_MAP() bfin_read16(DMA20_PERIPHERAL_MAP)
+@@ -1507,23 +1503,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 21 Registers */
+
+ #define bfin_read_DMA21_NEXT_DESC_PTR() bfin_read32(DMA21_NEXT_DESC_PTR)
+-#define bfin_write_DMA21_NEXT_DESC_PTR(val) bfin_write32(DMA21_NEXT_DESC_PTR)
++#define bfin_write_DMA21_NEXT_DESC_PTR(val) bfin_write32(DMA21_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA21_START_ADDR() bfin_read32(DMA21_START_ADDR)
+-#define bfin_write_DMA21_START_ADDR(val) bfin_write32(DMA21_START_ADDR)
++#define bfin_write_DMA21_START_ADDR(val) bfin_write32(DMA21_START_ADDR, val)
+ #define bfin_read_DMA21_CONFIG() bfin_read16(DMA21_CONFIG)
+ #define bfin_write_DMA21_CONFIG(val) bfin_write16(DMA21_CONFIG, val)
+ #define bfin_read_DMA21_X_COUNT() bfin_read16(DMA21_X_COUNT)
+ #define bfin_write_DMA21_X_COUNT(val) bfin_write16(DMA21_X_COUNT, val)
+ #define bfin_read_DMA21_X_MODIFY() bfin_read16(DMA21_X_MODIFY)
+-#define bfin_write_DMA21_X_MODIFY(val) bfin_write16(DMA21_X_MODIFY)
++#define bfin_write_DMA21_X_MODIFY(val) bfin_write16(DMA21_X_MODIFY, val)
+ #define bfin_read_DMA21_Y_COUNT() bfin_read16(DMA21_Y_COUNT)
+ #define bfin_write_DMA21_Y_COUNT(val) bfin_write16(DMA21_Y_COUNT, val)
+ #define bfin_read_DMA21_Y_MODIFY() bfin_read16(DMA21_Y_MODIFY)
+-#define bfin_write_DMA21_Y_MODIFY(val) bfin_write16(DMA21_Y_MODIFY)
++#define bfin_write_DMA21_Y_MODIFY(val) bfin_write16(DMA21_Y_MODIFY, val)
+ #define bfin_read_DMA21_CURR_DESC_PTR() bfin_read32(DMA21_CURR_DESC_PTR)
+-#define bfin_write_DMA21_CURR_DESC_PTR(val) bfin_write32(DMA21_CURR_DESC_PTR)
++#define bfin_write_DMA21_CURR_DESC_PTR(val) bfin_write32(DMA21_CURR_DESC_PTR, val)
+ #define bfin_read_DMA21_CURR_ADDR() bfin_read32(DMA21_CURR_ADDR)
+-#define bfin_write_DMA21_CURR_ADDR(val) bfin_write32(DMA21_CURR_ADDR)
++#define bfin_write_DMA21_CURR_ADDR(val) bfin_write32(DMA21_CURR_ADDR, val)
+ #define bfin_read_DMA21_IRQ_STATUS() bfin_read16(DMA21_IRQ_STATUS)
+ #define bfin_write_DMA21_IRQ_STATUS(val) bfin_write16(DMA21_IRQ_STATUS, val)
+ #define bfin_read_DMA21_PERIPHERAL_MAP() bfin_read16(DMA21_PERIPHERAL_MAP)
+@@ -1536,23 +1532,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 22 Registers */
+
+ #define bfin_read_DMA22_NEXT_DESC_PTR() bfin_read32(DMA22_NEXT_DESC_PTR)
+-#define bfin_write_DMA22_NEXT_DESC_PTR(val) bfin_write32(DMA22_NEXT_DESC_PTR)
++#define bfin_write_DMA22_NEXT_DESC_PTR(val) bfin_write32(DMA22_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA22_START_ADDR() bfin_read32(DMA22_START_ADDR)
+-#define bfin_write_DMA22_START_ADDR(val) bfin_write32(DMA22_START_ADDR)
++#define bfin_write_DMA22_START_ADDR(val) bfin_write32(DMA22_START_ADDR, val)
+ #define bfin_read_DMA22_CONFIG() bfin_read16(DMA22_CONFIG)
+ #define bfin_write_DMA22_CONFIG(val) bfin_write16(DMA22_CONFIG, val)
+ #define bfin_read_DMA22_X_COUNT() bfin_read16(DMA22_X_COUNT)
+ #define bfin_write_DMA22_X_COUNT(val) bfin_write16(DMA22_X_COUNT, val)
+ #define bfin_read_DMA22_X_MODIFY() bfin_read16(DMA22_X_MODIFY)
+-#define bfin_write_DMA22_X_MODIFY(val) bfin_write16(DMA22_X_MODIFY)
++#define bfin_write_DMA22_X_MODIFY(val) bfin_write16(DMA22_X_MODIFY, val)
+ #define bfin_read_DMA22_Y_COUNT() bfin_read16(DMA22_Y_COUNT)
+ #define bfin_write_DMA22_Y_COUNT(val) bfin_write16(DMA22_Y_COUNT, val)
+ #define bfin_read_DMA22_Y_MODIFY() bfin_read16(DMA22_Y_MODIFY)
+-#define bfin_write_DMA22_Y_MODIFY(val) bfin_write16(DMA22_Y_MODIFY)
++#define bfin_write_DMA22_Y_MODIFY(val) bfin_write16(DMA22_Y_MODIFY, val)
+ #define bfin_read_DMA22_CURR_DESC_PTR() bfin_read32(DMA22_CURR_DESC_PTR)
+-#define bfin_write_DMA22_CURR_DESC_PTR(val) bfin_write32(DMA22_CURR_DESC_PTR)
++#define bfin_write_DMA22_CURR_DESC_PTR(val) bfin_write32(DMA22_CURR_DESC_PTR, val)
+ #define bfin_read_DMA22_CURR_ADDR() bfin_read32(DMA22_CURR_ADDR)
+-#define bfin_write_DMA22_CURR_ADDR(val) bfin_write32(DMA22_CURR_ADDR)
++#define bfin_write_DMA22_CURR_ADDR(val) bfin_write32(DMA22_CURR_ADDR, val)
+ #define bfin_read_DMA22_IRQ_STATUS() bfin_read16(DMA22_IRQ_STATUS)
+ #define bfin_write_DMA22_IRQ_STATUS(val) bfin_write16(DMA22_IRQ_STATUS, val)
+ #define bfin_read_DMA22_PERIPHERAL_MAP() bfin_read16(DMA22_PERIPHERAL_MAP)
+@@ -1565,23 +1561,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* DMA Channel 23 Registers */
+
+ #define bfin_read_DMA23_NEXT_DESC_PTR() bfin_read32(DMA23_NEXT_DESC_PTR)
+-#define bfin_write_DMA23_NEXT_DESC_PTR(val) bfin_write32(DMA23_NEXT_DESC_PTR)
++#define bfin_write_DMA23_NEXT_DESC_PTR(val) bfin_write32(DMA23_NEXT_DESC_PTR, val)
+ #define bfin_read_DMA23_START_ADDR() bfin_read32(DMA23_START_ADDR)
+-#define bfin_write_DMA23_START_ADDR(val) bfin_write32(DMA23_START_ADDR)
++#define bfin_write_DMA23_START_ADDR(val) bfin_write32(DMA23_START_ADDR, val)
+ #define bfin_read_DMA23_CONFIG() bfin_read16(DMA23_CONFIG)
+ #define bfin_write_DMA23_CONFIG(val) bfin_write16(DMA23_CONFIG, val)
+ #define bfin_read_DMA23_X_COUNT() bfin_read16(DMA23_X_COUNT)
+ #define bfin_write_DMA23_X_COUNT(val) bfin_write16(DMA23_X_COUNT, val)
+ #define bfin_read_DMA23_X_MODIFY() bfin_read16(DMA23_X_MODIFY)
+-#define bfin_write_DMA23_X_MODIFY(val) bfin_write16(DMA23_X_MODIFY)
++#define bfin_write_DMA23_X_MODIFY(val) bfin_write16(DMA23_X_MODIFY, val)
+ #define bfin_read_DMA23_Y_COUNT() bfin_read16(DMA23_Y_COUNT)
+ #define bfin_write_DMA23_Y_COUNT(val) bfin_write16(DMA23_Y_COUNT, val)
+ #define bfin_read_DMA23_Y_MODIFY() bfin_read16(DMA23_Y_MODIFY)
+-#define bfin_write_DMA23_Y_MODIFY(val) bfin_write16(DMA23_Y_MODIFY)
++#define bfin_write_DMA23_Y_MODIFY(val) bfin_write16(DMA23_Y_MODIFY, val)
+ #define bfin_read_DMA23_CURR_DESC_PTR() bfin_read32(DMA23_CURR_DESC_PTR)
+-#define bfin_write_DMA23_CURR_DESC_PTR(val) bfin_write32(DMA23_CURR_DESC_PTR)
++#define bfin_write_DMA23_CURR_DESC_PTR(val) bfin_write32(DMA23_CURR_DESC_PTR, val)
+ #define bfin_read_DMA23_CURR_ADDR() bfin_read32(DMA23_CURR_ADDR)
+-#define bfin_write_DMA23_CURR_ADDR(val) bfin_write32(DMA23_CURR_ADDR)
++#define bfin_write_DMA23_CURR_ADDR(val) bfin_write32(DMA23_CURR_ADDR, val)
+ #define bfin_read_DMA23_IRQ_STATUS() bfin_read16(DMA23_IRQ_STATUS)
+ #define bfin_write_DMA23_IRQ_STATUS(val) bfin_write16(DMA23_IRQ_STATUS, val)
+ #define bfin_read_DMA23_PERIPHERAL_MAP() bfin_read16(DMA23_PERIPHERAL_MAP)
+@@ -1594,23 +1590,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* MDMA Stream 2 Registers */
+
+ #define bfin_read_MDMA_D2_NEXT_DESC_PTR() bfin_read32(MDMA_D2_NEXT_DESC_PTR)
+-#define bfin_write_MDMA_D2_NEXT_DESC_PTR(val) bfin_write32(MDMA_D2_NEXT_DESC_PTR)
++#define bfin_write_MDMA_D2_NEXT_DESC_PTR(val) bfin_write32(MDMA_D2_NEXT_DESC_PTR, val)
+ #define bfin_read_MDMA_D2_START_ADDR() bfin_read32(MDMA_D2_START_ADDR)
+-#define bfin_write_MDMA_D2_START_ADDR(val) bfin_write32(MDMA_D2_START_ADDR)
++#define bfin_write_MDMA_D2_START_ADDR(val) bfin_write32(MDMA_D2_START_ADDR, val)
+ #define bfin_read_MDMA_D2_CONFIG() bfin_read16(MDMA_D2_CONFIG)
+ #define bfin_write_MDMA_D2_CONFIG(val) bfin_write16(MDMA_D2_CONFIG, val)
+ #define bfin_read_MDMA_D2_X_COUNT() bfin_read16(MDMA_D2_X_COUNT)
+ #define bfin_write_MDMA_D2_X_COUNT(val) bfin_write16(MDMA_D2_X_COUNT, val)
+ #define bfin_read_MDMA_D2_X_MODIFY() bfin_read16(MDMA_D2_X_MODIFY)
+-#define bfin_write_MDMA_D2_X_MODIFY(val) bfin_write16(MDMA_D2_X_MODIFY)
++#define bfin_write_MDMA_D2_X_MODIFY(val) bfin_write16(MDMA_D2_X_MODIFY, val)
+ #define bfin_read_MDMA_D2_Y_COUNT() bfin_read16(MDMA_D2_Y_COUNT)
+ #define bfin_write_MDMA_D2_Y_COUNT(val) bfin_write16(MDMA_D2_Y_COUNT, val)
+ #define bfin_read_MDMA_D2_Y_MODIFY() bfin_read16(MDMA_D2_Y_MODIFY)
+-#define bfin_write_MDMA_D2_Y_MODIFY(val) bfin_write16(MDMA_D2_Y_MODIFY)
++#define bfin_write_MDMA_D2_Y_MODIFY(val) bfin_write16(MDMA_D2_Y_MODIFY, val)
+ #define bfin_read_MDMA_D2_CURR_DESC_PTR() bfin_read32(MDMA_D2_CURR_DESC_PTR)
+-#define bfin_write_MDMA_D2_CURR_DESC_PTR(val) bfin_write32(MDMA_D2_CURR_DESC_PTR)
++#define bfin_write_MDMA_D2_CURR_DESC_PTR(val) bfin_write32(MDMA_D2_CURR_DESC_PTR, val)
+ #define bfin_read_MDMA_D2_CURR_ADDR() bfin_read32(MDMA_D2_CURR_ADDR)
+-#define bfin_write_MDMA_D2_CURR_ADDR(val) bfin_write32(MDMA_D2_CURR_ADDR)
++#define bfin_write_MDMA_D2_CURR_ADDR(val) bfin_write32(MDMA_D2_CURR_ADDR, val)
+ #define bfin_read_MDMA_D2_IRQ_STATUS() bfin_read16(MDMA_D2_IRQ_STATUS)
+ #define bfin_write_MDMA_D2_IRQ_STATUS(val) bfin_write16(MDMA_D2_IRQ_STATUS, val)
+ #define bfin_read_MDMA_D2_PERIPHERAL_MAP() bfin_read16(MDMA_D2_PERIPHERAL_MAP)
+@@ -1620,23 +1616,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ #define bfin_read_MDMA_D2_CURR_Y_COUNT() bfin_read16(MDMA_D2_CURR_Y_COUNT)
+ #define bfin_write_MDMA_D2_CURR_Y_COUNT(val) bfin_write16(MDMA_D2_CURR_Y_COUNT, val)
+ #define bfin_read_MDMA_S2_NEXT_DESC_PTR() bfin_read32(MDMA_S2_NEXT_DESC_PTR)
+-#define bfin_write_MDMA_S2_NEXT_DESC_PTR(val) bfin_write32(MDMA_S2_NEXT_DESC_PTR)
++#define bfin_write_MDMA_S2_NEXT_DESC_PTR(val) bfin_write32(MDMA_S2_NEXT_DESC_PTR, val)
+ #define bfin_read_MDMA_S2_START_ADDR() bfin_read32(MDMA_S2_START_ADDR)
+-#define bfin_write_MDMA_S2_START_ADDR(val) bfin_write32(MDMA_S2_START_ADDR)
++#define bfin_write_MDMA_S2_START_ADDR(val) bfin_write32(MDMA_S2_START_ADDR, val)
+ #define bfin_read_MDMA_S2_CONFIG() bfin_read16(MDMA_S2_CONFIG)
+ #define bfin_write_MDMA_S2_CONFIG(val) bfin_write16(MDMA_S2_CONFIG, val)
+ #define bfin_read_MDMA_S2_X_COUNT() bfin_read16(MDMA_S2_X_COUNT)
+ #define bfin_write_MDMA_S2_X_COUNT(val) bfin_write16(MDMA_S2_X_COUNT, val)
+ #define bfin_read_MDMA_S2_X_MODIFY() bfin_read16(MDMA_S2_X_MODIFY)
+-#define bfin_write_MDMA_S2_X_MODIFY(val) bfin_write16(MDMA_S2_X_MODIFY)
++#define bfin_write_MDMA_S2_X_MODIFY(val) bfin_write16(MDMA_S2_X_MODIFY, val)
+ #define bfin_read_MDMA_S2_Y_COUNT() bfin_read16(MDMA_S2_Y_COUNT)
+ #define bfin_write_MDMA_S2_Y_COUNT(val) bfin_write16(MDMA_S2_Y_COUNT, val)
+ #define bfin_read_MDMA_S2_Y_MODIFY() bfin_read16(MDMA_S2_Y_MODIFY)
+-#define bfin_write_MDMA_S2_Y_MODIFY(val) bfin_write16(MDMA_S2_Y_MODIFY)
++#define bfin_write_MDMA_S2_Y_MODIFY(val) bfin_write16(MDMA_S2_Y_MODIFY, val)
+ #define bfin_read_MDMA_S2_CURR_DESC_PTR() bfin_read32(MDMA_S2_CURR_DESC_PTR)
+-#define bfin_write_MDMA_S2_CURR_DESC_PTR(val) bfin_write32(MDMA_S2_CURR_DESC_PTR)
++#define bfin_write_MDMA_S2_CURR_DESC_PTR(val) bfin_write32(MDMA_S2_CURR_DESC_PTR, val)
+ #define bfin_read_MDMA_S2_CURR_ADDR() bfin_read32(MDMA_S2_CURR_ADDR)
+-#define bfin_write_MDMA_S2_CURR_ADDR(val) bfin_write32(MDMA_S2_CURR_ADDR)
++#define bfin_write_MDMA_S2_CURR_ADDR(val) bfin_write32(MDMA_S2_CURR_ADDR, val)
+ #define bfin_read_MDMA_S2_IRQ_STATUS() bfin_read16(MDMA_S2_IRQ_STATUS)
+ #define bfin_write_MDMA_S2_IRQ_STATUS(val) bfin_write16(MDMA_S2_IRQ_STATUS, val)
+ #define bfin_read_MDMA_S2_PERIPHERAL_MAP() bfin_read16(MDMA_S2_PERIPHERAL_MAP)
+@@ -1649,23 +1645,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ /* MDMA Stream 3 Registers */
+
+ #define bfin_read_MDMA_D3_NEXT_DESC_PTR() bfin_read32(MDMA_D3_NEXT_DESC_PTR)
+-#define bfin_write_MDMA_D3_NEXT_DESC_PTR(val) bfin_write32(MDMA_D3_NEXT_DESC_PTR)
++#define bfin_write_MDMA_D3_NEXT_DESC_PTR(val) bfin_write32(MDMA_D3_NEXT_DESC_PTR, val)
+ #define bfin_read_MDMA_D3_START_ADDR() bfin_read32(MDMA_D3_START_ADDR)
+-#define bfin_write_MDMA_D3_START_ADDR(val) bfin_write32(MDMA_D3_START_ADDR)
++#define bfin_write_MDMA_D3_START_ADDR(val) bfin_write32(MDMA_D3_START_ADDR, val)
+ #define bfin_read_MDMA_D3_CONFIG() bfin_read16(MDMA_D3_CONFIG)
+ #define bfin_write_MDMA_D3_CONFIG(val) bfin_write16(MDMA_D3_CONFIG, val)
+ #define bfin_read_MDMA_D3_X_COUNT() bfin_read16(MDMA_D3_X_COUNT)
+ #define bfin_write_MDMA_D3_X_COUNT(val) bfin_write16(MDMA_D3_X_COUNT, val)
+ #define bfin_read_MDMA_D3_X_MODIFY() bfin_read16(MDMA_D3_X_MODIFY)
+-#define bfin_write_MDMA_D3_X_MODIFY(val) bfin_write16(MDMA_D3_X_MODIFY)
++#define bfin_write_MDMA_D3_X_MODIFY(val) bfin_write16(MDMA_D3_X_MODIFY, val)
+ #define bfin_read_MDMA_D3_Y_COUNT() bfin_read16(MDMA_D3_Y_COUNT)
+ #define bfin_write_MDMA_D3_Y_COUNT(val) bfin_write16(MDMA_D3_Y_COUNT, val)
+ #define bfin_read_MDMA_D3_Y_MODIFY() bfin_read16(MDMA_D3_Y_MODIFY)
+-#define bfin_write_MDMA_D3_Y_MODIFY(val) bfin_write16(MDMA_D3_Y_MODIFY)
++#define bfin_write_MDMA_D3_Y_MODIFY(val) bfin_write16(MDMA_D3_Y_MODIFY, val)
+ #define bfin_read_MDMA_D3_CURR_DESC_PTR() bfin_read32(MDMA_D3_CURR_DESC_PTR)
+-#define bfin_write_MDMA_D3_CURR_DESC_PTR(val) bfin_write32(MDMA_D3_CURR_DESC_PTR)
++#define bfin_write_MDMA_D3_CURR_DESC_PTR(val) bfin_write32(MDMA_D3_CURR_DESC_PTR, val)
+ #define bfin_read_MDMA_D3_CURR_ADDR() bfin_read32(MDMA_D3_CURR_ADDR)
+-#define bfin_write_MDMA_D3_CURR_ADDR(val) bfin_write32(MDMA_D3_CURR_ADDR)
++#define bfin_write_MDMA_D3_CURR_ADDR(val) bfin_write32(MDMA_D3_CURR_ADDR, val)
+ #define bfin_read_MDMA_D3_IRQ_STATUS() bfin_read16(MDMA_D3_IRQ_STATUS)
+ #define bfin_write_MDMA_D3_IRQ_STATUS(val) bfin_write16(MDMA_D3_IRQ_STATUS, val)
+ #define bfin_read_MDMA_D3_PERIPHERAL_MAP() bfin_read16(MDMA_D3_PERIPHERAL_MAP)
+@@ -1675,23 +1671,23 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ #define bfin_read_MDMA_D3_CURR_Y_COUNT() bfin_read16(MDMA_D3_CURR_Y_COUNT)
+ #define bfin_write_MDMA_D3_CURR_Y_COUNT(val) bfin_write16(MDMA_D3_CURR_Y_COUNT, val)
+ #define bfin_read_MDMA_S3_NEXT_DESC_PTR() bfin_read32(MDMA_S3_NEXT_DESC_PTR)
+-#define bfin_write_MDMA_S3_NEXT_DESC_PTR(val) bfin_write32(MDMA_S3_NEXT_DESC_PTR)
++#define bfin_write_MDMA_S3_NEXT_DESC_PTR(val) bfin_write32(MDMA_S3_NEXT_DESC_PTR, val)
+ #define bfin_read_MDMA_S3_START_ADDR() bfin_read32(MDMA_S3_START_ADDR)
+-#define bfin_write_MDMA_S3_START_ADDR(val) bfin_write32(MDMA_S3_START_ADDR)
++#define bfin_write_MDMA_S3_START_ADDR(val) bfin_write32(MDMA_S3_START_ADDR, val)
+ #define bfin_read_MDMA_S3_CONFIG() bfin_read16(MDMA_S3_CONFIG)
+ #define bfin_write_MDMA_S3_CONFIG(val) bfin_write16(MDMA_S3_CONFIG, val)
+ #define bfin_read_MDMA_S3_X_COUNT() bfin_read16(MDMA_S3_X_COUNT)
+ #define bfin_write_MDMA_S3_X_COUNT(val) bfin_write16(MDMA_S3_X_COUNT, val)
+ #define bfin_read_MDMA_S3_X_MODIFY() bfin_read16(MDMA_S3_X_MODIFY)
+-#define bfin_write_MDMA_S3_X_MODIFY(val) bfin_write16(MDMA_S3_X_MODIFY)
++#define bfin_write_MDMA_S3_X_MODIFY(val) bfin_write16(MDMA_S3_X_MODIFY, val)
+ #define bfin_read_MDMA_S3_Y_COUNT() bfin_read16(MDMA_S3_Y_COUNT)
+ #define bfin_write_MDMA_S3_Y_COUNT(val) bfin_write16(MDMA_S3_Y_COUNT, val)
+ #define bfin_read_MDMA_S3_Y_MODIFY() bfin_read16(MDMA_S3_Y_MODIFY)
+-#define bfin_write_MDMA_S3_Y_MODIFY(val) bfin_write16(MDMA_S3_Y_MODIFY)
++#define bfin_write_MDMA_S3_Y_MODIFY(val) bfin_write16(MDMA_S3_Y_MODIFY, val)
+ #define bfin_read_MDMA_S3_CURR_DESC_PTR() bfin_read32(MDMA_S3_CURR_DESC_PTR)
+-#define bfin_write_MDMA_S3_CURR_DESC_PTR(val) bfin_write32(MDMA_S3_CURR_DESC_PTR)
++#define bfin_write_MDMA_S3_CURR_DESC_PTR(val) bfin_write32(MDMA_S3_CURR_DESC_PTR, val)
+ #define bfin_read_MDMA_S3_CURR_ADDR() bfin_read32(MDMA_S3_CURR_ADDR)
+-#define bfin_write_MDMA_S3_CURR_ADDR(val) bfin_write32(MDMA_S3_CURR_ADDR)
++#define bfin_write_MDMA_S3_CURR_ADDR(val) bfin_write32(MDMA_S3_CURR_ADDR, val)
+ #define bfin_read_MDMA_S3_IRQ_STATUS() bfin_read16(MDMA_S3_IRQ_STATUS)
+ #define bfin_write_MDMA_S3_IRQ_STATUS(val) bfin_write16(MDMA_S3_IRQ_STATUS, val)
+ #define bfin_read_MDMA_S3_PERIPHERAL_MAP() bfin_read16(MDMA_S3_PERIPHERAL_MAP)
+diff --git a/include/asm-blackfin/mach-bf548/dma.h b/include/asm-blackfin/mach-bf548/dma.h
+index 46ff31f..36a2ef7 100644
+--- a/include/asm-blackfin/mach-bf548/dma.h
++++ b/include/asm-blackfin/mach-bf548/dma.h
+@@ -73,6 +73,4 @@
+
+ #define MAX_BLACKFIN_DMA_CHANNEL 32
+
+-extern int channel2irq(unsigned int channel);
+-extern struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL];
+ #endif
+diff --git a/include/asm-blackfin/mach-bf548/mem_init.h b/include/asm-blackfin/mach-bf548/mem_init.h
+index befc290..ab0b863 100644
+--- a/include/asm-blackfin/mach-bf548/mem_init.h
++++ b/include/asm-blackfin/mach-bf548/mem_init.h
+@@ -29,16 +29,19 @@
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+ #define MIN_DDR_SCLK(x) (x*(CONFIG_SCLK_HZ/1000/1000)/1000 + 1)
++#define MAX_DDR_SCLK(x) (x*(CONFIG_SCLK_HZ/1000/1000)/1000)
++#define DDR_CLK_HZ(x) (1000*1000*1000/x)
+
+ #if (CONFIG_MEM_MT46V32M16_6T)
+ #define DDR_SIZE DEVSZ_512
+ #define DDR_WIDTH DEVWD_16
++#define DDR_MAX_tCK 13
+
+ #define DDR_tRC DDR_TRC(MIN_DDR_SCLK(60))
+ #define DDR_tRAS DDR_TRAS(MIN_DDR_SCLK(42))
+ #define DDR_tRP DDR_TRP(MIN_DDR_SCLK(15))
+ #define DDR_tRFC DDR_TRFC(MIN_DDR_SCLK(72))
+-#define DDR_tREFI DDR_TREFI(MIN_DDR_SCLK(7800))
++#define DDR_tREFI DDR_TREFI(MAX_DDR_SCLK(7800))
+
+ #define DDR_tRCD DDR_TRCD(MIN_DDR_SCLK(15))
+ #define DDR_tWTR DDR_TWTR(1)
+@@ -49,12 +52,13 @@
+ #if (CONFIG_MEM_MT46V32M16_5B)
+ #define DDR_SIZE DEVSZ_512
+ #define DDR_WIDTH DEVWD_16
++#define DDR_MAX_tCK 13
+
+ #define DDR_tRC DDR_TRC(MIN_DDR_SCLK(55))
+ #define DDR_tRAS DDR_TRAS(MIN_DDR_SCLK(40))
+ #define DDR_tRP DDR_TRP(MIN_DDR_SCLK(15))
+ #define DDR_tRFC DDR_TRFC(MIN_DDR_SCLK(70))
+-#define DDR_tREFI DDR_TREFI(MIN_DDR_SCLK(7800))
++#define DDR_tREFI DDR_TREFI(MAX_DDR_SCLK(7800))
+
+ #define DDR_tRCD DDR_TRCD(MIN_DDR_SCLK(15))
+ #define DDR_tWTR DDR_TWTR(2)
+@@ -65,6 +69,7 @@
+ #if (CONFIG_MEM_GENERIC_BOARD)
+ #define DDR_SIZE DEVSZ_512
+ #define DDR_WIDTH DEVWD_16
++#define DDR_MAX_tCK 13
+
+ #define DDR_tRCD DDR_TRCD(3)
+ #define DDR_tWTR DDR_TWTR(2)
+@@ -77,14 +82,15 @@
+ #define DDR_tREFI DDR_TREFI(1288)
+ #endif
+
+-#if (CONFIG_SCLK_HZ <= 133333333)
+-#define DDR_CL CL_2
+-#elif (CONFIG_SCLK_HZ <= 166666666)
+-#define DDR_CL CL_2_5
++#if (CONFIG_SCLK_HZ < DDR_CLK_HZ(DDR_MAX_tCK))
++# error "CONFIG_SCLK_HZ is too small (<DDR_CLK_HZ(DDR_MAX_tCK) Hz)."
++#elif(CONFIG_SCLK_HZ <= 133333333)
++# define DDR_CL CL_2
+ #else
+-#define DDR_CL CL_3
++# error "CONFIG_SCLK_HZ is too large (>133333333 Hz)."
+ #endif
+
++
+ #define mem_DDRCTL0 (DDR_tRP | DDR_tRAS | DDR_tRC | DDR_tRFC | DDR_tREFI)
+ #define mem_DDRCTL1 (DDR_DATWIDTH | EXTBANK_1 | DDR_SIZE | DDR_WIDTH | DDR_tWTR \
+ | DDR_tMRD | DDR_tWR | DDR_tRCD)
+diff --git a/include/asm-blackfin/mach-bf561/anomaly.h b/include/asm-blackfin/mach-bf561/anomaly.h
+index 0c1d461..82157ca 100644
+--- a/include/asm-blackfin/mach-bf561/anomaly.h
++++ b/include/asm-blackfin/mach-bf561/anomaly.h
+@@ -7,7 +7,7 @@
+ */
+
+ /* This file shoule be up to date with:
+- * - Revision O, 11/15/2007; ADSP-BF561 Blackfin Processor Anomaly List
++ * - Revision P, 02/08/2008; ADSP-BF561 Blackfin Processor Anomaly List
+ */
+
+ #ifndef _MACH_ANOMALY_H_
+@@ -256,10 +256,14 @@
+ #define ANOMALY_05000357 (1)
+ /* Conflicting Column Address Widths Causes SDRAM Errors */
+ #define ANOMALY_05000362 (1)
++/* UART Break Signal Issues */
++#define ANOMALY_05000363 (__SILICON_REVISION__ < 5)
+ /* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */
+ #define ANOMALY_05000366 (1)
+ /* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */
+ #define ANOMALY_05000371 (1)
++/* Level-Sensitive External GPIO Wakeups May Cause Indefinite Stall */
++#define ANOMALY_05000403 (1)
+
+ /* Anomalies that don't exist on this proc */
+ #define ANOMALY_05000158 (0)
+diff --git a/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h
+index b6f513b..8a4e66d 100644
+--- a/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h
++++ b/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h
+@@ -1,22 +1,38 @@
++/*
++ * file: include/asm-blackfin/mach-bf561/bfin_serial_5xx.h
++ * based on:
++ * author:
++ *
++ * created:
++ * description:
++ * blackfin serial driver head file
++ * rev:
++ *
++ * modified:
++ *
++ *
++ * bugs: enter bugs at http://blackfin.uclinux.org/
++ *
++ * this program is free software; you can redistribute it and/or modify
++ * it under the terms of the gnu general public license as published by
++ * the free software foundation; either version 2, 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; see the file copying.
++ * if not, write to the free software foundation,
++ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
++ */
++
+ #include <linux/serial.h>
+ #include <asm/dma.h>
+ #include <asm/portmux.h>
+
+-#define NR_PORTS 1
+-
+-#define OFFSET_THR 0x00 /* Transmit Holding register */
+-#define OFFSET_RBR 0x00 /* Receive Buffer register */
+-#define OFFSET_DLL 0x00 /* Divisor Latch (Low-Byte) */
+-#define OFFSET_IER 0x04 /* Interrupt Enable Register */
+-#define OFFSET_DLH 0x04 /* Divisor Latch (High-Byte) */
+-#define OFFSET_IIR 0x08 /* Interrupt Identification Register */
+-#define OFFSET_LCR 0x0C /* Line Control Register */
+-#define OFFSET_MCR 0x10 /* Modem Control Register */
+-#define OFFSET_LSR 0x14 /* Line Status Register */
+-#define OFFSET_MSR 0x18 /* Modem Status Register */
+-#define OFFSET_SCR 0x1C /* SCR Scratch Register */
+-#define OFFSET_GCTL 0x24 /* Global Control Register */
+-
+ #define UART_GET_CHAR(uart) bfin_read16(((uart)->port.membase + OFFSET_RBR))
+ #define UART_GET_DLL(uart) bfin_read16(((uart)->port.membase + OFFSET_DLL))
+ #define UART_GET_IER(uart) bfin_read16(((uart)->port.membase + OFFSET_IER))
+@@ -84,7 +100,7 @@ static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
+ bfin_write16(uart->port.membase + OFFSET_LSR, -1);
+ }
+
+-struct bfin_serial_port bfin_serial_ports[NR_PORTS];
++struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
+ struct bfin_serial_res {
+ unsigned long uart_base_addr;
+ int uart_irq;
+@@ -115,7 +131,7 @@ struct bfin_serial_res bfin_serial_resource[] = {
+
+ #define DRIVER_NAME "bfin-uart"
+
+-int nr_ports = NR_PORTS;
++int nr_ports = BFIN_UART_NR_PORTS;
+ static void bfin_serial_hw_init(struct bfin_serial_port *uart)
+ {
+
+diff --git a/include/asm-blackfin/mach-bf561/bfin_sir.h b/include/asm-blackfin/mach-bf561/bfin_sir.h
+new file mode 100644
+index 0000000..cefcf8b
+--- /dev/null
++++ b/include/asm-blackfin/mach-bf561/bfin_sir.h
+@@ -0,0 +1,120 @@
++/*
++ * Blackfin Infra-red Driver
++ *
++ * Copyright 2006-2008 Analog Devices Inc.
++ *
++ * Enter bugs at http://blackfin.uclinux.org/
++ *
++ * Licensed under the GPL-2 or later.
++ *
++ */
++
++#include <linux/serial.h>
++#include <asm/dma.h>
++#include <asm/portmux.h>
++
++#define SIR_UART_GET_CHAR(port) bfin_read16((port)->membase + OFFSET_RBR)
++#define SIR_UART_GET_DLL(port) bfin_read16((port)->membase + OFFSET_DLL)
++#define SIR_UART_GET_IER(port) bfin_read16((port)->membase + OFFSET_IER)
++#define SIR_UART_GET_DLH(port) bfin_read16((port)->membase + OFFSET_DLH)
++#define SIR_UART_GET_IIR(port) bfin_read16((port)->membase + OFFSET_IIR)
++#define SIR_UART_GET_LCR(port) bfin_read16((port)->membase + OFFSET_LCR)
++#define SIR_UART_GET_GCTL(port) bfin_read16((port)->membase + OFFSET_GCTL)
++
++#define SIR_UART_PUT_CHAR(port, v) bfin_write16(((port)->membase + OFFSET_THR), v)
++#define SIR_UART_PUT_DLL(port, v) bfin_write16(((port)->membase + OFFSET_DLL), v)
++#define SIR_UART_PUT_IER(port, v) bfin_write16(((port)->membase + OFFSET_IER), v)
++#define SIR_UART_PUT_DLH(port, v) bfin_write16(((port)->membase + OFFSET_DLH), v)
++#define SIR_UART_PUT_LCR(port, v) bfin_write16(((port)->membase + OFFSET_LCR), v)
++#define SIR_UART_PUT_GCTL(port, v) bfin_write16(((port)->membase + OFFSET_GCTL), v)
++
++#ifdef CONFIG_SIR_BFIN_DMA
++struct dma_rx_buf {
++ char *buf;
++ int head;
++ int tail;
++ };
++#endif /* CONFIG_SIR_BFIN_DMA */
++
++struct bfin_sir_port {
++ unsigned char __iomem *membase;
++ unsigned int irq;
++ unsigned int lsr;
++ unsigned long clk;
++ struct net_device *dev;
++#ifdef CONFIG_SIR_BFIN_DMA
++ int tx_done;
++ struct dma_rx_buf rx_dma_buf;
++ struct timer_list rx_dma_timer;
++ int rx_dma_nrows;
++#endif /* CONFIG_SIR_BFIN_DMA */
++ unsigned int tx_dma_channel;
++ unsigned int rx_dma_channel;
++};
++
++struct bfin_sir_port sir_ports[BFIN_UART_NR_PORTS];
++
++struct bfin_sir_port_res {
++ unsigned long base_addr;
++ int irq;
++ unsigned int rx_dma_channel;
++ unsigned int tx_dma_channel;
++};
++
++struct bfin_sir_port_res bfin_sir_port_resource[] = {
++#ifdef CONFIG_BFIN_SIR0
++ {
++ 0xFFC00400,
++ IRQ_UART_RX,
++ CH_UART_RX,
++ CH_UART_TX,
++ },
++#endif
++};
++
++int nr_sirs = ARRAY_SIZE(bfin_sir_port_resource);
++
++struct bfin_sir_self {
++ struct bfin_sir_port *sir_port;
++ spinlock_t lock;
++ unsigned int open;
++ int speed;
++ int newspeed;
++
++ struct sk_buff *txskb;
++ struct sk_buff *rxskb;
++ struct net_device_stats stats;
++ struct device *dev;
++ struct irlap_cb *irlap;
++ struct qos_info qos;
++
++ iobuff_t tx_buff;
++ iobuff_t rx_buff;
++
++ struct work_struct work;
++ int mtt;
++};
++
++static inline unsigned int SIR_UART_GET_LSR(struct bfin_sir_port *port)
++{
++ unsigned int lsr = bfin_read16(port->membase + OFFSET_LSR);
++ port->lsr |= (lsr & (BI|FE|PE|OE));
++ return lsr | port->lsr;
++}
++
++static inline void SIR_UART_CLEAR_LSR(struct bfin_sir_port *port)
++{
++ port->lsr = 0;
++ bfin_read16(port->membase + OFFSET_LSR);
++}
++
++#define DRIVER_NAME "bfin_sir"
++
++static void bfin_sir_hw_init(void)
++{
++#ifdef CONFIG_BFIN_SIR0
++ peripheral_request(P_UART0_TX, DRIVER_NAME);
++ peripheral_request(P_UART0_RX, DRIVER_NAME);
++#endif
++ SSYNC();
++}
+diff --git a/include/asm-blackfin/mach-bf561/blackfin.h b/include/asm-blackfin/mach-bf561/blackfin.h
+index 3a16df2..0ea8666 100644
+--- a/include/asm-blackfin/mach-bf561/blackfin.h
++++ b/include/asm-blackfin/mach-bf561/blackfin.h
+@@ -69,5 +69,19 @@
+ #define bfin_read_SIC_ISR(x) bfin_read32(SICA_ISR0 + (x << 2))
+ #define bfin_write_SIC_ISR(x, val) bfin_write32((SICA_ISR0 + (x << 2)), val)
+
++#define BFIN_UART_NR_PORTS 1
++
++#define OFFSET_THR 0x00 /* Transmit Holding register */
++#define OFFSET_RBR 0x00 /* Receive Buffer register */
++#define OFFSET_DLL 0x00 /* Divisor Latch (Low-Byte) */
++#define OFFSET_IER 0x04 /* Interrupt Enable Register */
++#define OFFSET_DLH 0x04 /* Divisor Latch (High-Byte) */
++#define OFFSET_IIR 0x08 /* Interrupt Identification Register */
++#define OFFSET_LCR 0x0C /* Line Control Register */
++#define OFFSET_MCR 0x10 /* Modem Control Register */
++#define OFFSET_LSR 0x14 /* Line Status Register */
++#define OFFSET_MSR 0x18 /* Modem Status Register */
++#define OFFSET_SCR 0x1C /* SCR Scratch Register */
++#define OFFSET_GCTL 0x24 /* Global Control Register */
+
+ #endif /* _MACH_BLACKFIN_H_ */
+diff --git a/include/asm-blackfin/mach-bf561/cdefBF561.h b/include/asm-blackfin/mach-bf561/cdefBF561.h
+index 1bc8d2f..b07ffcc 100644
+--- a/include/asm-blackfin/mach-bf561/cdefBF561.h
++++ b/include/asm-blackfin/mach-bf561/cdefBF561.h
+@@ -47,7 +47,30 @@
+
+ /* Clock and System Control (0xFFC00000 - 0xFFC000FF) */
+ #define bfin_read_PLL_CTL() bfin_read16(PLL_CTL)
+-#define bfin_write_PLL_CTL(val) bfin_write16(PLL_CTL,val)
++/* Writing to PLL_CTL initiates a PLL relock sequence. */
++static __inline__ void bfin_write_PLL_CTL(unsigned int val)
++{
++ unsigned long flags, iwr0, iwr1;
++
++ if (val == bfin_read_PLL_CTL())
++ return;
++
++ local_irq_save(flags);
++ /* Enable the PLL Wakeup bit in SIC IWR */
++ iwr0 = bfin_read32(SICA_IWR0);
++ iwr1 = bfin_read32(SICA_IWR1);
++ /* Only allow PPL Wakeup) */
++ bfin_write32(SICA_IWR0, IWR_ENABLE(0));
++ bfin_write32(SICA_IWR1, 0);
++
++ bfin_write16(PLL_CTL, val);
++ SSYNC();
++ asm("IDLE;");
++
++ bfin_write32(SICA_IWR0, iwr0);
++ bfin_write32(SICA_IWR1, iwr1);
++ local_irq_restore(flags);
++}
+ #define bfin_read_PLL_DIV() bfin_read16(PLL_DIV)
+ #define bfin_write_PLL_DIV(val) bfin_write16(PLL_DIV,val)
+ #define bfin_read_VR_CTL() bfin_read16(VR_CTL)
+@@ -56,6 +79,10 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+ {
+ unsigned long flags, iwr0, iwr1;
+
++ if (val == bfin_read_VR_CTL())
++ return;
++
++ local_irq_save(flags);
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr0 = bfin_read32(SICA_IWR0);
+ iwr1 = bfin_read32(SICA_IWR1);
+@@ -65,12 +92,11 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
+
+ bfin_write16(VR_CTL, val);
+ SSYNC();
+-
+- local_irq_save(flags);
+ asm("IDLE;");
+- local_irq_restore(flags);
++
+ bfin_write32(SICA_IWR0, iwr0);
+ bfin_write32(SICA_IWR1, iwr1);
++ local_irq_restore(flags);
+ }
+ #define bfin_read_PLL_STAT() bfin_read16(PLL_STAT)
+ #define bfin_write_PLL_STAT(val) bfin_write16(PLL_STAT,val)
+diff --git a/include/asm-blackfin/mach-bf561/defBF561.h b/include/asm-blackfin/mach-bf561/defBF561.h
+index c3c0eb1..366c9b9 100644
+--- a/include/asm-blackfin/mach-bf561/defBF561.h
++++ b/include/asm-blackfin/mach-bf561/defBF561.h
+@@ -110,18 +110,23 @@
+ #define WDOGB_STAT 0xFFC01208 /* Watchdog Status register */
+
+ /* UART Controller (0xFFC00400 - 0xFFC004FF) */
+-#define UART_THR 0xFFC00400 /* Transmit Holding register */
+-#define UART_RBR 0xFFC00400 /* Receive Buffer register */
+-#define UART_DLL 0xFFC00400 /* Divisor Latch (Low-Byte) */
+-#define UART_IER 0xFFC00404 /* Interrupt Enable Register */
+-#define UART_DLH 0xFFC00404 /* Divisor Latch (High-Byte) */
+-#define UART_IIR 0xFFC00408 /* Interrupt Identification Register */
+-#define UART_LCR 0xFFC0040C /* Line Control Register */
+-#define UART_MCR 0xFFC00410 /* Modem Control Register */
+-#define UART_LSR 0xFFC00414 /* Line Status Register */
+-#define UART_MSR 0xFFC00418 /* Modem Status Register */
+-#define UART_SCR 0xFFC0041C /* SCR Scratch Register */
+-#define UART_GCTL 0xFFC00424 /* Global Control Register */
++
++/*
++ * Because include/linux/serial_reg.h have defined UART_*,
++ * So we define blackfin uart regs to BFIN_UART0_*.
++ */
++#define BFIN_UART_THR 0xFFC00400 /* Transmit Holding register */
++#define BFIN_UART_RBR 0xFFC00400 /* Receive Buffer register */
++#define BFIN_UART_DLL 0xFFC00400 /* Divisor Latch (Low-Byte) */
++#define BFIN_UART_IER 0xFFC00404 /* Interrupt Enable Register */
++#define BFIN_UART_DLH 0xFFC00404 /* Divisor Latch (High-Byte) */
++#define BFIN_UART_IIR 0xFFC00408 /* Interrupt Identification Register */
++#define BFIN_UART_LCR 0xFFC0040C /* Line Control Register */
++#define BFIN_UART_MCR 0xFFC00410 /* Modem Control Register */
++#define BFIN_UART_LSR 0xFFC00414 /* Line Status Register */
++#define BFIN_UART_MSR 0xFFC00418 /* Modem Status Register */
++#define BFIN_UART_SCR 0xFFC0041C /* SCR Scratch Register */
++#define BFIN_UART_GCTL 0xFFC00424 /* Global Control Register */
+
+ /* SPI Controller (0xFFC00500 - 0xFFC005FF) */
+ #define SPI0_REGBASE 0xFFC00500
+@@ -866,6 +871,8 @@
+ /* PLL_DIV Masks */
+ #define SCLK_DIV(x) (x) /* SCLK = VCO / x */
+
++#define CSEL 0x30 /* Core Select */
++#define SSEL 0xf /* System Select */
+ #define CCLK_DIV1 0x00000000 /* CCLK = VCO / 1 */
+ #define CCLK_DIV2 0x00000010 /* CCLK = VCO / 2 */
+ #define CCLK_DIV4 0x00000020 /* CCLK = VCO / 4 */
+diff --git a/include/asm-blackfin/mach-bf561/dma.h b/include/asm-blackfin/mach-bf561/dma.h
+index 766334b..21d9820 100644
+--- a/include/asm-blackfin/mach-bf561/dma.h
++++ b/include/asm-blackfin/mach-bf561/dma.h
+@@ -32,7 +32,4 @@
+ #define CH_IMEM_STREAM1_SRC 34
+ #define CH_IMEM_STREAM1_DEST 35
+
+-extern int channel2irq(unsigned int channel);
+-extern struct dma_register *base_addr[];
+-
+ #endif
+diff --git a/include/asm-blackfin/portmux.h b/include/asm-blackfin/portmux.h
+index 0d3f650..0807b28 100644
+--- a/include/asm-blackfin/portmux.h
++++ b/include/asm-blackfin/portmux.h
+@@ -17,8 +17,8 @@
+
+ int peripheral_request(unsigned short per, const char *label);
+ void peripheral_free(unsigned short per);
+-int peripheral_request_list(unsigned short per[], const char *label);
+-void peripheral_free_list(unsigned short per[]);
++int peripheral_request_list(const unsigned short per[], const char *label);
++void peripheral_free_list(const unsigned short per[]);
+
+ #include <asm/gpio.h>
+ #include <asm/mach/portmux.h>
+diff --git a/include/asm-blackfin/processor.h b/include/asm-blackfin/processor.h
+index 1033e5c..1c00407 100644
+--- a/include/asm-blackfin/processor.h
++++ b/include/asm-blackfin/processor.h
+@@ -26,9 +26,10 @@ static inline void wrusp(unsigned long usp)
+
+ /*
+ * User space process size: 1st byte beyond user address space.
++ * Fairly meaningless on nommu. Parts of user programs can be scattered
++ * in a lot of places, so just disable this by setting it to 0xFFFFFFFF.
+ */
+-extern unsigned long memory_end;
+-#define TASK_SIZE (memory_end)
++#define TASK_SIZE 0xFFFFFFFF
+
+ #ifdef __KERNEL__
+ #define STACK_TOP TASK_SIZE
+diff --git a/include/asm-blackfin/semaphore-helper.h b/include/asm-blackfin/semaphore-helper.h
+deleted file mode 100644
+index 9082b0d..0000000
+--- a/include/asm-blackfin/semaphore-helper.h
++++ /dev/null
+@@ -1,82 +0,0 @@
+-/* Based on M68K version, Lineo Inc. May 2001 */
+-
+-#ifndef _BFIN_SEMAPHORE_HELPER_H
+-#define _BFIN_SEMAPHORE_HELPER_H
+-
+-/*
+- * SMP- and interrupt-safe semaphores helper functions.
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- *
+- */
+-
+-#include <asm/errno.h>
+-
+-/*
+- * These two _must_ execute atomically wrt each other.
+- */
+-static inline void wake_one_more(struct semaphore *sem)
+-{
+- atomic_inc(&sem->waking);
+-}
+-
+-static inline int waking_non_zero(struct semaphore *sem)
+-{
+- int ret;
+- unsigned long flags = 0;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- ret = 0;
+- if (atomic_read(&sem->waking) > 0) {
+- atomic_dec(&sem->waking);
+- ret = 1;
+- }
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+- return ret;
+-}
+-
+-/*
+- * waking_non_zero_interruptible:
+- * 1 got the lock
+- * 0 go to sleep
+- * -EINTR interrupted
+- */
+-static inline int waking_non_zero_interruptible(struct semaphore *sem,
+- struct task_struct *tsk)
+-{
+- int ret = 0;
+- unsigned long flags = 0;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- if (atomic_read(&sem->waking) > 0) {
+- atomic_dec(&sem->waking);
+- ret = 1;
+- } else if (signal_pending(tsk)) {
+- atomic_inc(&sem->count);
+- ret = -EINTR;
+- }
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+- return ret;
+-}
+-
+-/*
+- * waking_non_zero_trylock:
+- * 1 failed to lock
+- * 0 got the lock
+- */
+-static inline int waking_non_zero_trylock(struct semaphore *sem)
+-{
+- int ret = 1;
+- unsigned long flags = 0;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- if (atomic_read(&sem->waking) > 0) {
+- atomic_dec(&sem->waking);
+- ret = 0;
+- } else
+- atomic_inc(&sem->count);
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+- return ret;
+-}
+-
+-#endif /* _BFIN_SEMAPHORE_HELPER_H */
+diff --git a/include/asm-blackfin/semaphore.h b/include/asm-blackfin/semaphore.h
+index 533f90f..d9b2034 100644
+--- a/include/asm-blackfin/semaphore.h
++++ b/include/asm-blackfin/semaphore.h
+@@ -1,105 +1 @@
+-#ifndef _BFIN_SEMAPHORE_H
+-#define _BFIN_SEMAPHORE_H
+-
+-#ifndef __ASSEMBLY__
+-
+-#include <linux/linkage.h>
+-#include <linux/wait.h>
+-#include <linux/spinlock.h>
+-#include <linux/rwsem.h>
+-#include <asm/atomic.h>
+-
+-/*
+- * Interrupt-safe semaphores..
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- *
+- * BFIN version by akbar hussain Lineo Inc April 2001
+- *
+- */
+-
+-struct semaphore {
+- atomic_t count;
+- int sleepers;
+- wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n) \
+-{ \
+- .count = ATOMIC_INIT(n), \
+- .sleepers = 0, \
+- .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+- struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init(struct semaphore *sem, int val)
+-{
+- *sem = (struct semaphore)__SEMAPHORE_INITIALIZER(*sem, val);
+-}
+-
+-static inline void init_MUTEX(struct semaphore *sem)
+-{
+- sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED(struct semaphore *sem)
+-{
+- sema_init(sem, 0);
+-}
+-
+-asmlinkage void __down(struct semaphore *sem);
+-asmlinkage int __down_interruptible(struct semaphore *sem);
+-asmlinkage int __down_trylock(struct semaphore *sem);
+-asmlinkage void __up(struct semaphore *sem);
+-
+-extern spinlock_t semaphore_wake_lock;
+-
+-/*
+- * This is ugly, but we want the default case to fall through.
+- * "down_failed" is a special asm handler that calls the C
+- * routine that actually waits.
+- */
+-static inline void down(struct semaphore *sem)
+-{
+- might_sleep();
+- if (atomic_dec_return(&sem->count) < 0)
+- __down(sem);
+-}
+-
+-static inline int down_interruptible(struct semaphore *sem)
+-{
+- int ret = 0;
+-
+- might_sleep();
+- if (atomic_dec_return(&sem->count) < 0)
+- ret = __down_interruptible(sem);
+- return (ret);
+-}
+-
+-static inline int down_trylock(struct semaphore *sem)
+-{
+- int ret = 0;
+-
+- if (atomic_dec_return(&sem->count) < 0)
+- ret = __down_trylock(sem);
+- return ret;
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- * The default case (no contention) will result in NO
+- * jumps for both down() and up().
+- */
+-static inline void up(struct semaphore *sem)
+-{
+- if (atomic_inc_return(&sem->count) <= 0)
+- __up(sem);
+-}
+-
+-#endif /* __ASSEMBLY__ */
+-#endif /* _BFIN_SEMAPHORE_H */
++#include <linux/semaphore.h>
+diff --git a/include/asm-blackfin/signal.h b/include/asm-blackfin/signal.h
+index 0250429..87951d2 100644
+--- a/include/asm-blackfin/signal.h
++++ b/include/asm-blackfin/signal.h
+@@ -143,7 +143,7 @@ struct sigaction {
+ #endif /* __KERNEL__ */
+
+ typedef struct sigaltstack {
+- void *ss_sp;
++ void __user *ss_sp;
+ int ss_flags;
+ size_t ss_size;
+ } stack_t;
+diff --git a/include/asm-blackfin/thread_info.h b/include/asm-blackfin/thread_info.h
+index 15b99cf..bc2fe5a 100644
+--- a/include/asm-blackfin/thread_info.h
++++ b/include/asm-blackfin/thread_info.h
+@@ -81,14 +81,11 @@ struct thread_info {
+ #define init_thread_info (init_thread_union.thread_info)
+ #define init_stack (init_thread_union.stack)
+
+-/* How to get the thread information struct from C */
+-
+-static inline struct thread_info *current_thread_info(void)
+- __attribute__ ((__const__));
+-
+-/* Given a task stack pointer, you can find it's task structure
+- * just by masking it to the 8K boundary.
++/* Given a task stack pointer, you can find its corresponding
++ * thread_info structure just by masking it to the THREAD_SIZE
++ * boundary (currently 8K as you can see above).
+ */
++__attribute_const__
+ static inline struct thread_info *current_thread_info(void)
+ {
+ struct thread_info *ti;
+diff --git a/include/asm-blackfin/time.h b/include/asm-blackfin/time.h
+new file mode 100644
+index 0000000..6e5859b
+--- /dev/null
++++ b/include/asm-blackfin/time.h
+@@ -0,0 +1,36 @@
++/*
++ * asm-blackfin/time.h:
++ *
++ * Copyright 2004-2008 Analog Devices Inc.
++ *
++ * Licensed under the GPL-2 or later.
++ */
++
++#ifndef _ASM_BLACKFIN_TIME_H
++#define _ASM_BLACKFIN_TIME_H
++
++/*
++ * The way that the Blackfin core timer works is:
++ * - CCLK is divided by a programmable 8-bit pre-scaler (TSCALE)
++ * - Every time TSCALE ticks, a 32bit is counted down (TCOUNT)
++ *
++ * If you take the fastest clock (1ns, or 1GHz to make the math work easier)
++ * 10ms is 10,000,000 clock ticks, which fits easy into a 32-bit counter
++ * (32 bit counter is 4,294,967,296ns or 4.2 seconds) so, we don't need
++ * to use TSCALE, and program it to zero (which is pass CCLK through).
++ * If you feel like using it, try to keep HZ * TIMESCALE to some
++ * value that divides easy (like power of 2).
++ */
++
++#ifndef CONFIG_CPU_FREQ
++#define TIME_SCALE 1
++#else
++/*
++ * Blackfin CPU frequency scaling supports max Core Clock 1, 1/2 and 1/4 .
++ * Whenever we change the Core Clock frequency changes we immediately
++ * adjust the Core Timer Presale Register. This way we don't lose time.
++ */
++#define TIME_SCALE 4
++#endif
++
++#endif
+diff --git a/include/asm-blackfin/timex.h b/include/asm-blackfin/timex.h
+index 8285901..22b0806 100644
+--- a/include/asm-blackfin/timex.h
++++ b/include/asm-blackfin/timex.h
+@@ -1,18 +1,23 @@
+-/* blackfin architecture timex specifications: Lineo Inc. 2001
++/*
++ * asm-blackfin/timex.h: cpu cycles!
+ *
+- * Based on: include/asm-m68knommu/timex.h
++ * Copyright 2004-2008 Analog Devices Inc.
++ *
++ * Licensed under the GPL-2 or later.
+ */
+
+-#ifndef _ASMBLACKFIN_TIMEX_H
+-#define _ASMBLACKFIN_TIMEX_H
++#ifndef _ASM_BLACKFIN_TIMEX_H
++#define _ASM_BLACKFIN_TIMEX_H
+
+ #define CLOCK_TICK_RATE 1000000 /* Underlying HZ */
+
+-typedef unsigned long cycles_t;
++typedef unsigned long long cycles_t;
+
+ static inline cycles_t get_cycles(void)
+ {
+- return 0;
++ unsigned long tmp, tmp2;
++ __asm__("%0 = cycles; %1 = cycles2;" : "=d"(tmp), "=d"(tmp2));
++ return tmp | ((cycles_t)tmp2 << 32);
+ }
+
+ #endif
+diff --git a/include/asm-blackfin/trace.h b/include/asm-blackfin/trace.h
+index ef18afb..312b596 100644
+--- a/include/asm-blackfin/trace.h
++++ b/include/asm-blackfin/trace.h
+@@ -62,14 +62,14 @@ extern unsigned long software_trace_buff[];
+ preg.L = LO(TBUFCTL); \
+ preg.H = HI(TBUFCTL); \
+ dreg = [preg]; \
+- [sp++] = dreg; \
++ [--sp] = dreg; \
+ dreg = 0x1; \
+ [preg] = dreg;
+
+ #define trace_buffer_restore(preg, dreg) \
+ preg.L = LO(TBUFCTL); \
+ preg.H = HI(TBUFCTL); \
+- dreg = [sp--]; \
++ dreg = [sp++]; \
+ [preg] = dreg;
+
+ #else /* CONFIG_DEBUG_BFIN_HWTRACE_ON */
+diff --git a/include/asm-blackfin/uaccess.h b/include/asm-blackfin/uaccess.h
+index 22a410b..d928b80 100644
+--- a/include/asm-blackfin/uaccess.h
++++ b/include/asm-blackfin/uaccess.h
+@@ -133,7 +133,7 @@ static inline int bad_user_access_length(void)
+ }
+
+ #define __put_user_bad() (printk(KERN_INFO "put_user_bad %s:%d %s\n",\
+- __FILE__, __LINE__, __FUNCTION__),\
++ __FILE__, __LINE__, __func__),\
+ bad_user_access_length(), (-EFAULT))
+
+ /*
+@@ -177,7 +177,7 @@ static inline int bad_user_access_length(void)
+ default: \
+ x = 0; \
+ printk(KERN_INFO "get_user_bad: %s:%d %s\n", \
+- __FILE__, __LINE__, __FUNCTION__); \
++ __FILE__, __LINE__, __func__); \
+ _err = __get_user_bad(); \
+ break; \
+ } \
+diff --git a/include/asm-blackfin/unistd.h b/include/asm-blackfin/unistd.h
+index c18a399..42955d0 100644
+--- a/include/asm-blackfin/unistd.h
++++ b/include/asm-blackfin/unistd.h
+@@ -265,14 +265,14 @@
+ /* 258 __NR_remap_file_pages */
+ #define __NR_set_tid_address 259
+ #define __NR_timer_create 260
+-#define __NR_timer_settime (__NR_timer_create+1)
+-#define __NR_timer_gettime (__NR_timer_create+2)
+-#define __NR_timer_getoverrun (__NR_timer_create+3)
+-#define __NR_timer_delete (__NR_timer_create+4)
+-#define __NR_clock_settime (__NR_timer_create+5)
+-#define __NR_clock_gettime (__NR_timer_create+6)
+-#define __NR_clock_getres (__NR_timer_create+7)
+-#define __NR_clock_nanosleep (__NR_timer_create+8)
++#define __NR_timer_settime 261
++#define __NR_timer_gettime 262
++#define __NR_timer_getoverrun 263
++#define __NR_timer_delete 264
++#define __NR_clock_settime 265
++#define __NR_clock_gettime 266
++#define __NR_clock_getres 267
++#define __NR_clock_nanosleep 268
+ #define __NR_statfs64 269
+ #define __NR_fstatfs64 270
+ #define __NR_tgkill 271
+@@ -283,11 +283,11 @@
+ /* 276 __NR_get_mempolicy */
+ /* 277 __NR_set_mempolicy */
+ #define __NR_mq_open 278
+-#define __NR_mq_unlink (__NR_mq_open+1)
+-#define __NR_mq_timedsend (__NR_mq_open+2)
+-#define __NR_mq_timedreceive (__NR_mq_open+3)
+-#define __NR_mq_notify (__NR_mq_open+4)
+-#define __NR_mq_getsetattr (__NR_mq_open+5)
++#define __NR_mq_unlink 279
++#define __NR_mq_timedsend 280
++#define __NR_mq_timedreceive 281
++#define __NR_mq_notify 282
++#define __NR_mq_getsetattr 283
+ #define __NR_kexec_load 284
+ #define __NR_waitid 285
+ #define __NR_add_key 286
+diff --git a/include/asm-cris/semaphore-helper.h b/include/asm-cris/semaphore-helper.h
+deleted file mode 100644
+index 27bfeca..0000000
+--- a/include/asm-cris/semaphore-helper.h
++++ /dev/null
+@@ -1,78 +0,0 @@
+-/* $Id: semaphore-helper.h,v 1.3 2001/03/26 15:00:33 orjanf Exp $
+- *
+- * SMP- and interrupt-safe semaphores helper functions. Generic versions, no
+- * optimizations whatsoever...
+- *
+- */
+-
+-#ifndef _ASM_SEMAPHORE_HELPER_H
+-#define _ASM_SEMAPHORE_HELPER_H
+-
+-#include <asm/atomic.h>
+-#include <linux/errno.h>
+-
+-#define read(a) ((a)->counter)
+-#define inc(a) (((a)->counter)++)
+-#define dec(a) (((a)->counter)--)
+-
+-#define count_inc(a) ((*(a))++)
+-
+-/*
+- * These two _must_ execute atomically wrt each other.
+- */
+-static inline void wake_one_more(struct semaphore * sem)
+-{
+- atomic_inc(&sem->waking);
+-}
+-
+-static inline int waking_non_zero(struct semaphore *sem)
+-{
+- unsigned long flags;
+- int ret = 0;
+-
+- local_irq_save(flags);
+- if (read(&sem->waking) > 0) {
+- dec(&sem->waking);
+- ret = 1;
+- }
+- local_irq_restore(flags);
+- return ret;
+-}
+-
+-static inline int waking_non_zero_interruptible(struct semaphore *sem,
+- struct task_struct *tsk)
+-{
+- int ret = 0;
+- unsigned long flags;
+-
+- local_irq_save(flags);
+- if (read(&sem->waking) > 0) {
+- dec(&sem->waking);
+- ret = 1;
+- } else if (signal_pending(tsk)) {
+- inc(&sem->count);
+- ret = -EINTR;
+- }
+- local_irq_restore(flags);
+- return ret;
+-}
+-
+-static inline int waking_non_zero_trylock(struct semaphore *sem)
+-{
+- int ret = 1;
+- unsigned long flags;
+-
+- local_irq_save(flags);
+- if (read(&sem->waking) <= 0)
+- inc(&sem->count);
+- else {
+- dec(&sem->waking);
+- ret = 0;
+- }
+- local_irq_restore(flags);
+- return ret;
+-}
+-
+-#endif /* _ASM_SEMAPHORE_HELPER_H */
+-
+-
+diff --git a/include/asm-cris/semaphore.h b/include/asm-cris/semaphore.h
+index 31a4ac4..d9b2034 100644
+--- a/include/asm-cris/semaphore.h
++++ b/include/asm-cris/semaphore.h
+@@ -1,133 +1 @@
+-/* $Id: semaphore.h,v 1.3 2001/05/08 13:54:09 bjornw Exp $ */
+-
+-/* On the i386 these are coded in asm, perhaps we should as well. Later.. */
+-
+-#ifndef _CRIS_SEMAPHORE_H
+-#define _CRIS_SEMAPHORE_H
+-
+-#define RW_LOCK_BIAS 0x01000000
+-
+-#include <linux/wait.h>
+-#include <linux/spinlock.h>
+-#include <linux/rwsem.h>
+-
+-#include <asm/system.h>
+-#include <asm/atomic.h>
+-
+-/*
+- * CRIS semaphores, implemented in C-only so far.
+- */
+-
+-struct semaphore {
+- atomic_t count;
+- atomic_t waking;
+- wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n) \
+-{ \
+- .count = ATOMIC_INIT(n), \
+- .waking = ATOMIC_INIT(0), \
+- .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+- struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init(struct semaphore *sem, int val)
+-{
+- *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+- sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+- sema_init(sem, 0);
+-}
+-
+-extern void __down(struct semaphore * sem);
+-extern int __down_interruptible(struct semaphore * sem);
+-extern int __down_trylock(struct semaphore * sem);
+-extern void __up(struct semaphore * sem);
+-
+-/* notice - we probably can do cli/sti here instead of saving */
+-
+-static inline void down(struct semaphore * sem)
+-{
+- unsigned long flags;
+- int failed;
+-
+- might_sleep();
+-
+- /* atomically decrement the semaphores count, and if its negative, we wait */
+- cris_atomic_save(sem, flags);
+- failed = --(sem->count.counter) < 0;
+- cris_atomic_restore(sem, flags);
+- if(failed) {
+- __down(sem);
+- }
+-}
+-
+-/*
+- * This version waits in interruptible state so that the waiting
+- * process can be killed. The down_interruptible routine
+- * returns negative for signalled and zero for semaphore acquired.
+- */
+-
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+- unsigned long flags;
+- int failed;
+-
+- might_sleep();
+-
+- /* atomically decrement the semaphores count, and if its negative, we wait */
+- cris_atomic_save(sem, flags);
+- failed = --(sem->count.counter) < 0;
+- cris_atomic_restore(sem, flags);
+- if(failed)
+- failed = __down_interruptible(sem);
+- return(failed);
+-}
+-
+-static inline int down_trylock(struct semaphore * sem)
+-{
+- unsigned long flags;
+- int failed;
+-
+- cris_atomic_save(sem, flags);
+- failed = --(sem->count.counter) < 0;
+- cris_atomic_restore(sem, flags);
+- if(failed)
+- failed = __down_trylock(sem);
+- return(failed);
+-
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- * The default case (no contention) will result in NO
+- * jumps for both down() and up().
+- */
+-static inline void up(struct semaphore * sem)
+-{
+- unsigned long flags;
+- int wakeup;
+-
+- /* atomically increment the semaphores count, and if it was negative, we wake people */
+- cris_atomic_save(sem, flags);
+- wakeup = ++(sem->count.counter) <= 0;
+- cris_atomic_restore(sem, flags);
+- if(wakeup) {
+- __up(sem);
+- }
+-}
+-
+-#endif
++#include <linux/semaphore.h>
+diff --git a/include/asm-frv/semaphore.h b/include/asm-frv/semaphore.h
+index d7aaa19..d9b2034 100644
+--- a/include/asm-frv/semaphore.h
++++ b/include/asm-frv/semaphore.h
+@@ -1,155 +1 @@
+-/* semaphore.h: semaphores for the FR-V
+- *
+- * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+- * Written by David Howells (dhowells at redhat.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.
+- */
+-#ifndef _ASM_SEMAPHORE_H
+-#define _ASM_SEMAPHORE_H
+-
+-#define RW_LOCK_BIAS 0x01000000
+-
+-#ifndef __ASSEMBLY__
+-
+-#include <linux/linkage.h>
+-#include <linux/wait.h>
+-#include <linux/spinlock.h>
+-#include <linux/rwsem.h>
+-
+-/*
+- * the semaphore definition
+- * - if counter is >0 then there are tokens available on the semaphore for down to collect
+- * - if counter is <=0 then there are no spare tokens, and anyone that wants one must wait
+- * - if wait_list is not empty, then there are processes waiting for the semaphore
+- */
+-struct semaphore {
+- unsigned counter;
+- spinlock_t wait_lock;
+- struct list_head wait_list;
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+- unsigned __magic;
+-#endif
+-};
+-
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+-# define __SEM_DEBUG_INIT(name) , (long)&(name).__magic
+-#else
+-# define __SEM_DEBUG_INIT(name)
+-#endif
+-
+-
+-#define __SEMAPHORE_INITIALIZER(name,count) \
+-{ count, SPIN_LOCK_UNLOCKED, LIST_HEAD_INIT((name).wait_list) __SEM_DEBUG_INIT(name) }
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+- struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+- *sem = (struct semaphore) __SEMAPHORE_INITIALIZER(*sem, val);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+- sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+- sema_init(sem, 0);
+-}
+-
+-extern void __down(struct semaphore *sem, unsigned long flags);
+-extern int __down_interruptible(struct semaphore *sem, unsigned long flags);
+-extern void __up(struct semaphore *sem);
+-
+-static inline void down(struct semaphore *sem)
+-{
+- unsigned long flags;
+-
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+- CHECK_MAGIC(sem->__magic);
+-#endif
+-
+- spin_lock_irqsave(&sem->wait_lock, flags);
+- if (likely(sem->counter > 0)) {
+- sem->counter--;
+- spin_unlock_irqrestore(&sem->wait_lock, flags);
+- }
+- else {
+- __down(sem, flags);
+- }
+-}
+-
+-static inline int down_interruptible(struct semaphore *sem)
+-{
+- unsigned long flags;
+- int ret = 0;
+-
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+- CHECK_MAGIC(sem->__magic);
+-#endif
+-
+- spin_lock_irqsave(&sem->wait_lock, flags);
+- if (likely(sem->counter > 0)) {
+- sem->counter--;
+- spin_unlock_irqrestore(&sem->wait_lock, flags);
+- }
+- else {
+- ret = __down_interruptible(sem, flags);
+- }
+- return ret;
+-}
+-
+-/*
+- * non-blockingly attempt to down() a semaphore.
+- * - returns zero if we acquired it
+- */
+-static inline int down_trylock(struct semaphore *sem)
+-{
+- unsigned long flags;
+- int success = 0;
+-
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+- CHECK_MAGIC(sem->__magic);
+-#endif
+-
+- spin_lock_irqsave(&sem->wait_lock, flags);
+- if (sem->counter > 0) {
+- sem->counter--;
+- success = 1;
+- }
+- spin_unlock_irqrestore(&sem->wait_lock, flags);
+- return !success;
+-}
+-
+-static inline void up(struct semaphore *sem)
+-{
+- unsigned long flags;
+-
+-#ifdef CONFIG_DEBUG_SEMAPHORE
+- CHECK_MAGIC(sem->__magic);
+-#endif
+-
+- spin_lock_irqsave(&sem->wait_lock, flags);
+- if (!list_empty(&sem->wait_list))
+- __up(sem);
+- else
+- sem->counter++;
+- spin_unlock_irqrestore(&sem->wait_lock, flags);
+-}
+-
+-static inline int sem_getcount(struct semaphore *sem)
+-{
+- return sem->counter;
+-}
+-
+-#endif /* __ASSEMBLY__ */
+-
+-#endif
++#include <linux/semaphore.h>
+diff --git a/include/asm-frv/system.h b/include/asm-frv/system.h
+index 30a67a9..cb307f8 100644
+--- a/include/asm-frv/system.h
++++ b/include/asm-frv/system.h
+@@ -197,11 +197,6 @@ do { \
+ do { var = (value); barrier(); } while (0)
+ #endif
+
+-#define HARD_RESET_NOW() \
+-do { \
+- cli(); \
+-} while(1)
+-
+ extern void die_if_kernel(const char *, ...) __attribute__((format(printf, 1, 2)));
+ extern void free_initmem(void);
+
+diff --git a/include/asm-frv/topology.h b/include/asm-frv/topology.h
+index abe7298..9427243 100644
+--- a/include/asm-frv/topology.h
++++ b/include/asm-frv/topology.h
+@@ -5,10 +5,8 @@
+
+ #error NUMA not supported yet
+
+-#else /* !CONFIG_NUMA */
++#endif /* CONFIG_NUMA */
+
+ #include <asm-generic/topology.h>
+
+-#endif /* CONFIG_NUMA */
+-
+ #endif /* _ASM_TOPOLOGY_H */
+diff --git a/include/asm-generic/iomap.h b/include/asm-generic/iomap.h
+index 67dc84c..76b0cc5 100644
+--- a/include/asm-generic/iomap.h
++++ b/include/asm-generic/iomap.h
+@@ -60,6 +60,10 @@ extern void iowrite32_rep(void __iomem *port, const void *buf, unsigned long cou
+ extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
+ extern void ioport_unmap(void __iomem *);
+
++#ifndef ARCH_HAS_IOREMAP_WC
++#define ioremap_wc ioremap_nocache
++#endif
++
+ /* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+ struct pci_dev;
+ extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
+diff --git a/include/asm-generic/topology.h b/include/asm-generic/topology.h
+index 342a2a0..a6aea79 100644
+--- a/include/asm-generic/topology.h
++++ b/include/asm-generic/topology.h
+@@ -27,6 +27,8 @@
+ #ifndef _ASM_GENERIC_TOPOLOGY_H
+ #define _ASM_GENERIC_TOPOLOGY_H
+
++#ifndef CONFIG_NUMA
++
+ /* Other architectures wishing to use this simple topology API should fill
+ in the below functions as appropriate in their own <asm/topology.h> file. */
+ #ifndef cpu_to_node
+@@ -52,4 +54,16 @@
+ )
+ #endif
+
++#endif /* CONFIG_NUMA */
++
++/* returns pointer to cpumask for specified node */
++#ifndef node_to_cpumask_ptr
++
++#define node_to_cpumask_ptr(v, node) \
++ cpumask_t _##v = node_to_cpumask(node), *v = &_##v
++
++#define node_to_cpumask_ptr_next(v, node) \
++ _##v = node_to_cpumask(node)
++#endif
++
+ #endif /* _ASM_GENERIC_TOPOLOGY_H */
+diff --git a/include/asm-h8300/semaphore-helper.h b/include/asm-h8300/semaphore-helper.h
+deleted file mode 100644
+index 4fea36b..0000000
+--- a/include/asm-h8300/semaphore-helper.h
++++ /dev/null
+@@ -1,85 +0,0 @@
+-#ifndef _H8300_SEMAPHORE_HELPER_H
+-#define _H8300_SEMAPHORE_HELPER_H
+-
+-/*
+- * SMP- and interrupt-safe semaphores helper functions.
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- *
+- * based on
+- * m68k version by Andreas Schwab
+- */
+-
+-#include <linux/errno.h>
+-
+-/*
+- * These two _must_ execute atomically wrt each other.
+- */
+-static inline void wake_one_more(struct semaphore * sem)
+-{
+- atomic_inc((atomic_t *)&sem->sleepers);
+-}
+-
+-static inline int waking_non_zero(struct semaphore *sem)
+-{
+- int ret;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- ret = 0;
+- if (sem->sleepers > 0) {
+- sem->sleepers--;
+- ret = 1;
+- }
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+- return ret;
+-}
+-
+-/*
+- * waking_non_zero_interruptible:
+- * 1 got the lock
+- * 0 go to sleep
+- * -EINTR interrupted
+- */
+-static inline int waking_non_zero_interruptible(struct semaphore *sem,
+- struct task_struct *tsk)
+-{
+- int ret;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- ret = 0;
+- if (sem->sleepers > 0) {
+- sem->sleepers--;
+- ret = 1;
+- } else if (signal_pending(tsk)) {
+- atomic_inc(&sem->count);
+- ret = -EINTR;
+- }
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+- return ret;
+-}
+-
+-/*
+- * waking_non_zero_trylock:
+- * 1 failed to lock
+- * 0 got the lock
+- */
+-static inline int waking_non_zero_trylock(struct semaphore *sem)
+-{
+- int ret;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- ret = 1;
+- if (sem->sleepers <= 0)
+- atomic_inc(&sem->count);
+- else {
+- sem->sleepers--;
+- ret = 0;
+- }
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+- return ret;
+-}
+-
+-#endif
+diff --git a/include/asm-h8300/semaphore.h b/include/asm-h8300/semaphore.h
+index f3ffff8..d9b2034 100644
+--- a/include/asm-h8300/semaphore.h
++++ b/include/asm-h8300/semaphore.h
+@@ -1,190 +1 @@
+-#ifndef _H8300_SEMAPHORE_H
+-#define _H8300_SEMAPHORE_H
+-
+-#define RW_LOCK_BIAS 0x01000000
+-
+-#ifndef __ASSEMBLY__
+-
+-#include <linux/linkage.h>
+-#include <linux/wait.h>
+-#include <linux/spinlock.h>
+-#include <linux/rwsem.h>
+-
+-#include <asm/system.h>
+-#include <asm/atomic.h>
+-
+-/*
+- * Interrupt-safe semaphores..
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- *
+- * H8/300 version by Yoshinori Sato
+- */
+-
+-
+-struct semaphore {
+- atomic_t count;
+- int sleepers;
+- wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n) \
+-{ \
+- .count = ATOMIC_INIT(n), \
+- .sleepers = 0, \
+- .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+- struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+- *sem = (struct semaphore)__SEMAPHORE_INITIALIZER(*sem, val);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+- sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+- sema_init(sem, 0);
+-}
+-
+-asmlinkage void __down_failed(void /* special register calling convention */);
+-asmlinkage int __down_failed_interruptible(void /* params in registers */);
+-asmlinkage int __down_failed_trylock(void /* params in registers */);
+-asmlinkage void __up_wakeup(void /* special register calling convention */);
+-
+-asmlinkage void __down(struct semaphore * sem);
+-asmlinkage int __down_interruptible(struct semaphore * sem);
+-asmlinkage int __down_trylock(struct semaphore * sem);
+-asmlinkage void __up(struct semaphore * sem);
+-
+-extern spinlock_t semaphore_wake_lock;
+-
+-/*
+- * This is ugly, but we want the default case to fall through.
+- * "down_failed" is a special asm handler that calls the C
+- * routine that actually waits. See arch/m68k/lib/semaphore.S
+- */
+-static inline void down(struct semaphore * sem)
+-{
+- register atomic_t *count asm("er0");
+-
+- might_sleep();
+-
+- count = &(sem->count);
+- __asm__ __volatile__(
+- "stc ccr,r3l\n\t"
+- "orc #0x80,ccr\n\t"
+- "mov.l %2, er1\n\t"
+- "dec.l #1,er1\n\t"
+- "mov.l er1,%0\n\t"
+- "bpl 1f\n\t"
+- "ldc r3l,ccr\n\t"
+- "mov.l %1,er0\n\t"
+- "jsr @___down\n\t"
+- "bra 2f\n"
+- "1:\n\t"
+- "ldc r3l,ccr\n"
+- "2:"
+- : "=m"(*count)
+- : "g"(sem),"m"(*count)
+- : "cc", "er1", "er2", "er3");
+-}
+-
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+- register atomic_t *count asm("er0");
+-
+- might_sleep();
+-
+- count = &(sem->count);
+- __asm__ __volatile__(
+- "stc ccr,r1l\n\t"
+- "orc #0x80,ccr\n\t"
+- "mov.l %3, er2\n\t"
+- "dec.l #1,er2\n\t"
+- "mov.l er2,%1\n\t"
+- "bpl 1f\n\t"
+- "ldc r1l,ccr\n\t"
+- "mov.l %2,er0\n\t"
+- "jsr @___down_interruptible\n\t"
+- "bra 2f\n"
+- "1:\n\t"
+- "ldc r1l,ccr\n\t"
+- "sub.l %0,%0\n\t"
+- "2:\n\t"
+- : "=r" (count),"=m" (*count)
+- : "g"(sem),"m"(*count)
+- : "cc", "er1", "er2", "er3");
+- return (int)count;
+-}
+-
+-static inline int down_trylock(struct semaphore * sem)
+-{
+- register atomic_t *count asm("er0");
+-
+- count = &(sem->count);
+- __asm__ __volatile__(
+- "stc ccr,r3l\n\t"
+- "orc #0x80,ccr\n\t"
+- "mov.l %3,er2\n\t"
+- "dec.l #1,er2\n\t"
+- "mov.l er2,%0\n\t"
+- "bpl 1f\n\t"
+- "ldc r3l,ccr\n\t"
+- "jmp @3f\n\t"
+- LOCK_SECTION_START(".align 2\n\t")
+- "3:\n\t"
+- "mov.l %2,er0\n\t"
+- "jsr @___down_trylock\n\t"
+- "jmp @2f\n\t"
+- LOCK_SECTION_END
+- "1:\n\t"
+- "ldc r3l,ccr\n\t"
+- "sub.l %1,%1\n"
+- "2:"
+- : "=m" (*count),"=r"(count)
+- : "g"(sem),"m"(*count)
+- : "cc", "er1","er2", "er3");
+- return (int)count;
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- * The default case (no contention) will result in NO
+- * jumps for both down() and up().
+- */
+-static inline void up(struct semaphore * sem)
+-{
+- register atomic_t *count asm("er0");
+-
+- count = &(sem->count);
+- __asm__ __volatile__(
+- "stc ccr,r3l\n\t"
+- "orc #0x80,ccr\n\t"
+- "mov.l %2,er1\n\t"
+- "inc.l #1,er1\n\t"
+- "mov.l er1,%0\n\t"
+- "ldc r3l,ccr\n\t"
+- "sub.l er2,er2\n\t"
+- "cmp.l er2,er1\n\t"
+- "bgt 1f\n\t"
+- "mov.l %1,er0\n\t"
+- "jsr @___up\n"
+- "1:"
+- : "=m"(*count)
+- : "g"(sem),"m"(*count)
+- : "cc", "er1", "er2", "er3");
+-}
+-
+-#endif /* __ASSEMBLY__ */
+-
+-#endif
++#include <linux/semaphore.h>
+diff --git a/include/asm-ia64/acpi.h b/include/asm-ia64/acpi.h
+index cd1cc39..fcfad32 100644
+--- a/include/asm-ia64/acpi.h
++++ b/include/asm-ia64/acpi.h
+@@ -35,6 +35,7 @@
+ #include <linux/init.h>
+ #include <linux/numa.h>
+ #include <asm/system.h>
++#include <asm/numa.h>
+
+ #define COMPILER_DEPENDENT_INT64 long
+ #define COMPILER_DEPENDENT_UINT64 unsigned long
+@@ -115,7 +116,11 @@ extern unsigned int is_cpu_cpei_target(unsigned int cpu);
+ extern void set_cpei_target_cpu(unsigned int cpu);
+ extern unsigned int get_cpei_target_cpu(void);
+ extern void prefill_possible_map(void);
++#ifdef CONFIG_ACPI_HOTPLUG_CPU
+ extern int additional_cpus;
++#else
++#define additional_cpus 0
++#endif
+
+ #ifdef CONFIG_ACPI_NUMA
+ #if MAX_NUMNODES > 256
+@@ -129,6 +134,34 @@ extern int __initdata nid_to_pxm_map[MAX_NUMNODES];
+
+ #define acpi_unlazy_tlb(x)
+
++#ifdef CONFIG_ACPI_NUMA
++extern cpumask_t early_cpu_possible_map;
++#define for_each_possible_early_cpu(cpu) \
++ for_each_cpu_mask((cpu), early_cpu_possible_map)
++
++static inline void per_cpu_scan_finalize(int min_cpus, int reserve_cpus)
++{
++ int low_cpu, high_cpu;
++ int cpu;
++ int next_nid = 0;
++
++ low_cpu = cpus_weight(early_cpu_possible_map);
++
++ high_cpu = max(low_cpu, min_cpus);
++ high_cpu = min(high_cpu + reserve_cpus, NR_CPUS);
++
++ for (cpu = low_cpu; cpu < high_cpu; cpu++) {
++ cpu_set(cpu, early_cpu_possible_map);
++ if (node_cpuid[cpu].nid == NUMA_NO_NODE) {
++ node_cpuid[cpu].nid = next_nid;
++ next_nid++;
++ if (next_nid >= num_online_nodes())
++ next_nid = 0;
++ }
++ }
++}
++#endif /* CONFIG_ACPI_NUMA */
++
+ #endif /*__KERNEL__*/
+
+ #endif /*_ASM_ACPI_H*/
+diff --git a/include/asm-ia64/cputime.h b/include/asm-ia64/cputime.h
+index 72400a7..f9abdec 100644
+--- a/include/asm-ia64/cputime.h
++++ b/include/asm-ia64/cputime.h
+@@ -1,6 +1,110 @@
++/*
++ * include/asm-ia64/cputime.h:
++ * Definitions for measuring cputime on ia64 machines.
++ *
++ * Based on <asm-powerpc/cputime.h>.
++ *
++ * Copyright (C) 2007 FUJITSU LIMITED
++ * Copyright (C) 2007 Hidetoshi Seto <seto.hidetoshi at jp.fujitsu.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.
++ *
++ * If we have CONFIG_VIRT_CPU_ACCOUNTING, we measure cpu time in nsec.
++ * Otherwise we measure cpu time in jiffies using the generic definitions.
++ */
++
+ #ifndef __IA64_CPUTIME_H
+ #define __IA64_CPUTIME_H
+
++#ifndef CONFIG_VIRT_CPU_ACCOUNTING
+ #include <asm-generic/cputime.h>
++#else
++
++#include <linux/time.h>
++#include <linux/jiffies.h>
++#include <asm/processor.h>
++
++typedef u64 cputime_t;
++typedef u64 cputime64_t;
++
++#define cputime_zero ((cputime_t)0)
++#define cputime_max ((~((cputime_t)0) >> 1) - 1)
++#define cputime_add(__a, __b) ((__a) + (__b))
++#define cputime_sub(__a, __b) ((__a) - (__b))
++#define cputime_div(__a, __n) ((__a) / (__n))
++#define cputime_halve(__a) ((__a) >> 1)
++#define cputime_eq(__a, __b) ((__a) == (__b))
++#define cputime_gt(__a, __b) ((__a) > (__b))
++#define cputime_ge(__a, __b) ((__a) >= (__b))
++#define cputime_lt(__a, __b) ((__a) < (__b))
++#define cputime_le(__a, __b) ((__a) <= (__b))
++
++#define cputime64_zero ((cputime64_t)0)
++#define cputime64_add(__a, __b) ((__a) + (__b))
++#define cputime64_sub(__a, __b) ((__a) - (__b))
++#define cputime_to_cputime64(__ct) (__ct)
++
++/*
++ * Convert cputime <-> jiffies (HZ)
++ */
++#define cputime_to_jiffies(__ct) ((__ct) / (NSEC_PER_SEC / HZ))
++#define jiffies_to_cputime(__jif) ((__jif) * (NSEC_PER_SEC / HZ))
++#define cputime64_to_jiffies64(__ct) ((__ct) / (NSEC_PER_SEC / HZ))
++#define jiffies64_to_cputime64(__jif) ((__jif) * (NSEC_PER_SEC / HZ))
++
++/*
++ * Convert cputime <-> milliseconds
++ */
++#define cputime_to_msecs(__ct) ((__ct) / NSEC_PER_MSEC)
++#define msecs_to_cputime(__msecs) ((__msecs) * NSEC_PER_MSEC)
++
++/*
++ * Convert cputime <-> seconds
++ */
++#define cputime_to_secs(__ct) ((__ct) / NSEC_PER_SEC)
++#define secs_to_cputime(__secs) ((__secs) * NSEC_PER_SEC)
++
++/*
++ * Convert cputime <-> timespec (nsec)
++ */
++static inline cputime_t timespec_to_cputime(const struct timespec *val)
++{
++ cputime_t ret = val->tv_sec * NSEC_PER_SEC;
++ return (ret + val->tv_nsec);
++}
++static inline void cputime_to_timespec(const cputime_t ct, struct timespec *val)
++{
++ val->tv_sec = ct / NSEC_PER_SEC;
++ val->tv_nsec = ct % NSEC_PER_SEC;
++}
++
++/*
++ * Convert cputime <-> timeval (msec)
++ */
++static inline cputime_t timeval_to_cputime(struct timeval *val)
++{
++ cputime_t ret = val->tv_sec * NSEC_PER_SEC;
++ return (ret + val->tv_usec * NSEC_PER_USEC);
++}
++static inline void cputime_to_timeval(const cputime_t ct, struct timeval *val)
++{
++ val->tv_sec = ct / NSEC_PER_SEC;
++ val->tv_usec = (ct % NSEC_PER_SEC) / NSEC_PER_USEC;
++}
++
++/*
++ * Convert cputime <-> clock (USER_HZ)
++ */
++#define cputime_to_clock_t(__ct) ((__ct) / (NSEC_PER_SEC / USER_HZ))
++#define clock_t_to_cputime(__x) ((__x) * (NSEC_PER_SEC / USER_HZ))
++
++/*
++ * Convert cputime64 to clock.
++ */
++#define cputime64_to_clock_t(__ct) cputime_to_clock_t((cputime_t)__ct)
+
++#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
+ #endif /* __IA64_CPUTIME_H */
+diff --git a/include/asm-ia64/elf.h b/include/asm-ia64/elf.h
+index f8e83ec..5e0c1a6 100644
+--- a/include/asm-ia64/elf.h
++++ b/include/asm-ia64/elf.h
+@@ -26,6 +26,7 @@
+ #define ELF_ARCH EM_IA_64
+
+ #define USE_ELF_CORE_DUMP
++#define CORE_DUMP_USE_REGSET
+
+ /* Least-significant four bits of ELF header's e_flags are OS-specific. The bits are
+ interpreted as follows by Linux: */
+@@ -154,6 +155,30 @@ extern void ia64_init_addr_space (void);
+ #define ELF_NGREG 128 /* we really need just 72 but let's leave some headroom... */
+ #define ELF_NFPREG 128 /* f0 and f1 could be omitted, but so what... */
+
++/* elf_gregset_t register offsets */
++#define ELF_GR_0_OFFSET 0
++#define ELF_NAT_OFFSET (32 * sizeof(elf_greg_t))
++#define ELF_PR_OFFSET (33 * sizeof(elf_greg_t))
++#define ELF_BR_0_OFFSET (34 * sizeof(elf_greg_t))
++#define ELF_CR_IIP_OFFSET (42 * sizeof(elf_greg_t))
++#define ELF_CFM_OFFSET (43 * sizeof(elf_greg_t))
++#define ELF_CR_IPSR_OFFSET (44 * sizeof(elf_greg_t))
++#define ELF_GR_OFFSET(i) (ELF_GR_0_OFFSET + i * sizeof(elf_greg_t))
++#define ELF_BR_OFFSET(i) (ELF_BR_0_OFFSET + i * sizeof(elf_greg_t))
++#define ELF_AR_RSC_OFFSET (45 * sizeof(elf_greg_t))
++#define ELF_AR_BSP_OFFSET (46 * sizeof(elf_greg_t))
++#define ELF_AR_BSPSTORE_OFFSET (47 * sizeof(elf_greg_t))
++#define ELF_AR_RNAT_OFFSET (48 * sizeof(elf_greg_t))
++#define ELF_AR_CCV_OFFSET (49 * sizeof(elf_greg_t))
++#define ELF_AR_UNAT_OFFSET (50 * sizeof(elf_greg_t))
++#define ELF_AR_FPSR_OFFSET (51 * sizeof(elf_greg_t))
++#define ELF_AR_PFS_OFFSET (52 * sizeof(elf_greg_t))
++#define ELF_AR_LC_OFFSET (53 * sizeof(elf_greg_t))
++#define ELF_AR_EC_OFFSET (54 * sizeof(elf_greg_t))
++#define ELF_AR_CSD_OFFSET (55 * sizeof(elf_greg_t))
++#define ELF_AR_SSD_OFFSET (56 * sizeof(elf_greg_t))
++#define ELF_AR_END_OFFSET (57 * sizeof(elf_greg_t))
++
+ typedef unsigned long elf_fpxregset_t;
+
+ typedef unsigned long elf_greg_t;
+@@ -183,12 +208,6 @@ extern void ia64_elf_core_copy_regs (struct pt_regs *src, elf_gregset_t dst);
+
+ struct task_struct;
+
+-extern int dump_task_regs(struct task_struct *, elf_gregset_t *);
+-extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *);
+-
+-#define ELF_CORE_COPY_TASK_REGS(tsk, elf_gregs) dump_task_regs(tsk, elf_gregs)
+-#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs)
+-
+ #define GATE_EHDR ((const struct elfhdr *) GATE_ADDR)
+
+ /* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */
+diff --git a/include/asm-ia64/ide.h b/include/asm-ia64/ide.h
+index 1ccf238..8fa3f8c 100644
+--- a/include/asm-ia64/ide.h
++++ b/include/asm-ia64/ide.h
+@@ -16,8 +16,6 @@
+
+ #include <linux/irq.h>
+
+-#define IDE_ARCH_OBSOLETE_DEFAULTS
+-
+ static inline int ide_default_irq(unsigned long base)
+ {
+ switch (base) {
+@@ -46,14 +44,6 @@ static inline unsigned long ide_default_io_base(int index)
+ }
+ }
+
+-#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */
+-
+-#ifdef CONFIG_PCI
+-#define ide_init_default_irq(base) (0)
+-#else
+-#define ide_init_default_irq(base) ide_default_irq(base)
+-#endif
+-
+ #include <asm-generic/ide_iops.h>
+
+ #endif /* __KERNEL__ */
+diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h
+index d03bf9f..ef71b57 100644
+--- a/include/asm-ia64/kprobes.h
++++ b/include/asm-ia64/kprobes.h
+@@ -30,8 +30,12 @@
+ #include <asm/break.h>
+
+ #define __ARCH_WANT_KPROBES_INSN_SLOT
+-#define MAX_INSN_SIZE 1
++#define MAX_INSN_SIZE 2 /* last half is for kprobe-booster */
+ #define BREAK_INST (long)(__IA64_BREAK_KPROBE << 6)
++#define NOP_M_INST (long)(1<<27)
++#define BRL_INST(i1, i2) ((long)((0xcL << 37) | /* brl */ \
++ (0x1L << 12) | /* many */ \
++ (((i1) & 1) << 36) | ((i2) << 13))) /* imm */
+
+ typedef union cmp_inst {
+ struct {
+@@ -112,6 +116,7 @@ struct arch_specific_insn {
+ #define INST_FLAG_FIX_RELATIVE_IP_ADDR 1
+ #define INST_FLAG_FIX_BRANCH_REG 2
+ #define INST_FLAG_BREAK_INST 4
++ #define INST_FLAG_BOOSTABLE 8
+ unsigned long inst_flag;
+ unsigned short target_br_reg;
+ unsigned short slot;
+diff --git a/include/asm-ia64/kregs.h b/include/asm-ia64/kregs.h
+index 7e55a58..aefcdfe 100644
+--- a/include/asm-ia64/kregs.h
++++ b/include/asm-ia64/kregs.h
+@@ -31,6 +31,9 @@
+ #define IA64_TR_PALCODE 1 /* itr1: maps PALcode as required by EFI */
+ #define IA64_TR_CURRENT_STACK 1 /* dtr1: maps kernel's memory- & register-stacks */
+
++#define IA64_TR_ALLOC_BASE 2 /* itr&dtr: Base of dynamic TR resource*/
++#define IA64_TR_ALLOC_MAX 32 /* Max number for dynamic use*/
++
+ /* Processor status register bits: */
+ #define IA64_PSR_BE_BIT 1
+ #define IA64_PSR_UP_BIT 2
+diff --git a/include/asm-ia64/mca.h b/include/asm-ia64/mca.h
+index f1663aa..18a4321 100644
+--- a/include/asm-ia64/mca.h
++++ b/include/asm-ia64/mca.h
+@@ -157,6 +157,7 @@ extern void ia64_mca_printk(const char * fmt, ...)
+ struct ia64_mca_notify_die {
+ struct ia64_sal_os_state *sos;
+ int *monarch_cpu;
++ int *data;
+ };
+
+ DECLARE_PER_CPU(u64, ia64_mca_pal_base);
+diff --git a/include/asm-ia64/meminit.h b/include/asm-ia64/meminit.h
+index f93308f..7245a57 100644
+--- a/include/asm-ia64/meminit.h
++++ b/include/asm-ia64/meminit.h
+@@ -35,6 +35,7 @@ extern void find_memory (void);
+ extern void reserve_memory (void);
+ extern void find_initrd (void);
+ extern int filter_rsvd_memory (unsigned long start, unsigned long end, void *arg);
++extern int filter_memory (unsigned long start, unsigned long end, void *arg);
+ extern unsigned long efi_memmap_init(unsigned long *s, unsigned long *e);
+ extern int find_max_min_low_pfn (unsigned long , unsigned long, void *);
+
+@@ -56,7 +57,7 @@ extern int reserve_elfcorehdr(unsigned long *start, unsigned long *end);
+
+ #define IGNORE_PFN0 1 /* XXX fix me: ignore pfn 0 until TLB miss handler is updated... */
+
+-extern int register_active_ranges(u64 start, u64 end, void *arg);
++extern int register_active_ranges(u64 start, u64 len, int nid);
+
+ #ifdef CONFIG_VIRTUAL_MEM_MAP
+ # define LARGE_GAP 0x40000000 /* Use virtual mem map if hole is > than this */
+diff --git a/include/asm-ia64/numa.h b/include/asm-ia64/numa.h
+index 6a8a27c..3499ff5 100644
+--- a/include/asm-ia64/numa.h
++++ b/include/asm-ia64/numa.h
+@@ -22,6 +22,8 @@
+
+ #include <asm/mmzone.h>
+
++#define NUMA_NO_NODE -1
++
+ extern u16 cpu_to_node_map[NR_CPUS] __cacheline_aligned;
+ extern cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned;
+ extern pg_data_t *pgdat_list[MAX_NUMNODES];
+diff --git a/include/asm-ia64/pal.h b/include/asm-ia64/pal.h
+index 8a695d3..67b0290 100644
+--- a/include/asm-ia64/pal.h
++++ b/include/asm-ia64/pal.h
+@@ -13,6 +13,7 @@
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999 Walt Drummond <drummond at valinux.com>
+ * Copyright (C) 1999 Srinivasa Prasad Thirumalachar <sprasad at sprasad.engr.sgi.com>
++ * Copyright (C) 2008 Silicon Graphics, Inc. (SGI)
+ *
+ * 99/10/01 davidm Make sure we pass zero for reserved parameters.
+ * 00/03/07 davidm Updated pal_cache_flush() to be in sync with PAL v2.6.
+@@ -73,6 +74,8 @@
+ #define PAL_CACHE_SHARED_INFO 43 /* returns information on caches shared by logical processor */
+ #define PAL_GET_HW_POLICY 48 /* Get current hardware resource sharing policy */
+ #define PAL_SET_HW_POLICY 49 /* Set current hardware resource sharing policy */
++#define PAL_VP_INFO 50 /* Information about virtual processor features */
++#define PAL_MC_HW_TRACKING 51 /* Hardware tracking status */
+
+ #define PAL_COPY_PAL 256 /* relocate PAL procedures and PAL PMI */
+ #define PAL_HALT_INFO 257 /* return the low power capabilities of processor */
+@@ -504,7 +507,8 @@ typedef struct pal_cache_check_info_s {
+ wiv : 1, /* Way field valid */
+ reserved2 : 1,
+ dp : 1, /* Data poisoned on MBE */
+- reserved3 : 8,
++ reserved3 : 6,
++ hlth : 2, /* Health indicator */
+
+ index : 20, /* Cache line index */
+ reserved4 : 2,
+@@ -542,7 +546,9 @@ typedef struct pal_tlb_check_info_s {
+ dtc : 1, /* Fail in data TC */
+ itc : 1, /* Fail in inst. TC */
+ op : 4, /* Cache operation */
+- reserved3 : 30,
++ reserved3 : 6,
++ hlth : 2, /* Health indicator */
++ reserved4 : 22,
+
+ is : 1, /* instruction set (1 == ia32) */
+ iv : 1, /* instruction set field valid */
+@@ -633,7 +639,8 @@ typedef struct pal_uarch_check_info_s {
+ way : 6, /* Way of structure */
+ wv : 1, /* way valid */
+ xv : 1, /* index valid */
+- reserved1 : 8,
++ reserved1 : 6,
++ hlth : 2, /* Health indicator */
+ index : 8, /* Index or set of the uarch
+ * structure that failed.
+ */
+@@ -1213,14 +1220,12 @@ ia64_pal_mc_drain (void)
+
+ /* Return the machine check dynamic processor state */
+ static inline s64
+-ia64_pal_mc_dynamic_state (u64 offset, u64 *size, u64 *pds)
++ia64_pal_mc_dynamic_state (u64 info_type, u64 dy_buffer, u64 *size)
+ {
+ struct ia64_pal_retval iprv;
+- PAL_CALL(iprv, PAL_MC_DYNAMIC_STATE, offset, 0, 0);
++ PAL_CALL(iprv, PAL_MC_DYNAMIC_STATE, info_type, dy_buffer, 0);
+ if (size)
+ *size = iprv.v0;
+- if (pds)
+- *pds = iprv.v1;
+ return iprv.status;
+ }
+
+@@ -1281,15 +1286,41 @@ ia64_pal_mc_expected (u64 expected, u64 *previous)
+ return iprv.status;
+ }
+
++typedef union pal_hw_tracking_u {
++ u64 pht_data;
++ struct {
++ u64 itc :4, /* Instruction cache tracking */
++ dct :4, /* Date cache tracking */
++ itt :4, /* Instruction TLB tracking */
++ ddt :4, /* Data TLB tracking */
++ reserved:48;
++ } pal_hw_tracking_s;
++} pal_hw_tracking_u_t;
++
++/*
++ * Hardware tracking status.
++ */
++static inline s64
++ia64_pal_mc_hw_tracking (u64 *status)
++{
++ struct ia64_pal_retval iprv;
++ PAL_CALL(iprv, PAL_MC_HW_TRACKING, 0, 0, 0);
++ if (status)
++ *status = iprv.v0;
++ return iprv.status;
++}
++
+ /* Register a platform dependent location with PAL to which it can save
+ * minimal processor state in the event of a machine check or initialization
+ * event.
+ */
+ static inline s64
+-ia64_pal_mc_register_mem (u64 physical_addr)
++ia64_pal_mc_register_mem (u64 physical_addr, u64 size, u64 *req_size)
+ {
+ struct ia64_pal_retval iprv;
+- PAL_CALL(iprv, PAL_MC_REGISTER_MEM, physical_addr, 0, 0);
++ PAL_CALL(iprv, PAL_MC_REGISTER_MEM, physical_addr, size, 0);
++ if (req_size)
++ *req_size = iprv.v0;
+ return iprv.status;
+ }
+
+@@ -1631,6 +1662,29 @@ ia64_pal_vm_summary (pal_vm_info_1_u_t *vm_info_1, pal_vm_info_2_u_t *vm_info_2)
+ return iprv.status;
+ }
+
++typedef union pal_vp_info_u {
++ u64 pvi_val;
++ struct {
++ u64 index: 48, /* virtual feature set info */
++ vmm_id: 16; /* feature set id */
++ } pal_vp_info_s;
++} pal_vp_info_u_t;
++
++/*
++ * Returns infomation about virtual processor features
++ */
++static inline s64
++ia64_pal_vp_info (u64 feature_set, u64 vp_buffer, u64 *vp_info, u64 *vmm_id)
++{
++ struct ia64_pal_retval iprv;
++ PAL_CALL(iprv, PAL_VP_INFO, feature_set, vp_buffer, 0);
++ if (vp_info)
++ *vp_info = iprv.v0;
++ if (vmm_id)
++ *vmm_id = iprv.v1;
++ return iprv.status;
++}
++
+ typedef union pal_itr_valid_u {
+ u64 piv_val;
+ struct {
+diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
+index e6204f1..ed70862 100644
+--- a/include/asm-ia64/pgtable.h
++++ b/include/asm-ia64/pgtable.h
+@@ -371,7 +371,7 @@ pgd_index (unsigned long address)
+ /* The offset in the 1-level directory is given by the 3 region bits
+ (61..63) and the level-1 bits. */
+ static inline pgd_t*
+-pgd_offset (struct mm_struct *mm, unsigned long address)
++pgd_offset (const struct mm_struct *mm, unsigned long address)
+ {
+ return mm->pgd + pgd_index(address);
+ }
+diff --git a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h
+index f4904db..89594b4 100644
+--- a/include/asm-ia64/sal.h
++++ b/include/asm-ia64/sal.h
+@@ -296,6 +296,9 @@ enum {
+ EFI_GUID(0xe429faf8, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
+ #define SAL_PLAT_BUS_ERR_SECT_GUID \
+ EFI_GUID(0xe429faf9, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81)
++#define PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID \
++ EFI_GUID(0x6cb0a200, 0x893a, 0x11da, 0x96, 0xd2, 0x0, 0x10, 0x83, 0xff, \
++ 0xca, 0x4d)
+
+ #define MAX_CACHE_ERRORS 6
+ #define MAX_TLB_ERRORS 6
+@@ -879,6 +882,24 @@ extern void ia64_jump_to_sal(struct sal_to_os_boot *);
+
+ extern void ia64_sal_handler_init(void *entry_point, void *gpval);
+
++#define PALO_MAX_TLB_PURGES 0xFFFF
++#define PALO_SIG "PALO"
++
++struct palo_table {
++ u8 signature[4]; /* Should be "PALO" */
++ u32 length;
++ u8 minor_revision;
++ u8 major_revision;
++ u8 checksum;
++ u8 reserved1[5];
++ u16 max_tlb_purges;
++ u8 reserved2[6];
++};
++
++#define NPTCG_FROM_PAL 0
++#define NPTCG_FROM_PALO 1
++#define NPTCG_FROM_KERNEL_PARAMETER 2
++
+ #endif /* __ASSEMBLY__ */
+
+ #endif /* _ASM_IA64_SAL_H */
+diff --git a/include/asm-ia64/semaphore.h b/include/asm-ia64/semaphore.h
+index d8393d1..d9b2034 100644
+--- a/include/asm-ia64/semaphore.h
++++ b/include/asm-ia64/semaphore.h
+@@ -1,99 +1 @@
+-#ifndef _ASM_IA64_SEMAPHORE_H
+-#define _ASM_IA64_SEMAPHORE_H
+-
+-/*
+- * Copyright (C) 1998-2000 Hewlett-Packard Co
+- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm at hpl.hp.com>
+- */
+-
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-#include <asm/atomic.h>
+-
+-struct semaphore {
+- atomic_t count;
+- int sleepers;
+- wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n) \
+-{ \
+- .count = ATOMIC_INIT(n), \
+- .sleepers = 0, \
+- .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+- struct semaphore name = __SEMAPHORE_INITIALIZER(name, count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name, 1)
+-
+-static inline void
+-sema_init (struct semaphore *sem, int val)
+-{
+- *sem = (struct semaphore) __SEMAPHORE_INITIALIZER(*sem, val);
+-}
+-
+-static inline void
+-init_MUTEX (struct semaphore *sem)
+-{
+- sema_init(sem, 1);
+-}
+-
+-static inline void
+-init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+- sema_init(sem, 0);
+-}
+-
+-extern void __down (struct semaphore * sem);
+-extern int __down_interruptible (struct semaphore * sem);
+-extern int __down_trylock (struct semaphore * sem);
+-extern void __up (struct semaphore * sem);
+-
+-/*
+- * Atomically decrement the semaphore's count. If it goes negative,
+- * block the calling thread in the TASK_UNINTERRUPTIBLE state.
+- */
+-static inline void
+-down (struct semaphore *sem)
+-{
+- might_sleep();
+- if (ia64_fetchadd(-1, &sem->count.counter, acq) < 1)
+- __down(sem);
+-}
+-
+-/*
+- * Atomically decrement the semaphore's count. If it goes negative,
+- * block the calling thread in the TASK_INTERRUPTIBLE state.
+- */
+-static inline int
+-down_interruptible (struct semaphore * sem)
+-{
+- int ret = 0;
+-
+- might_sleep();
+- if (ia64_fetchadd(-1, &sem->count.counter, acq) < 1)
+- ret = __down_interruptible(sem);
+- return ret;
+-}
+-
+-static inline int
+-down_trylock (struct semaphore *sem)
+-{
+- int ret = 0;
+-
+- if (ia64_fetchadd(-1, &sem->count.counter, acq) < 1)
+- ret = __down_trylock(sem);
+- return ret;
+-}
+-
+-static inline void
+-up (struct semaphore * sem)
+-{
+- if (ia64_fetchadd(1, &sem->count.counter, rel) <= -1)
+- __up(sem);
+-}
+-
+-#endif /* _ASM_IA64_SEMAPHORE_H */
++#include <linux/semaphore.h>
+diff --git a/include/asm-ia64/smp.h b/include/asm-ia64/smp.h
+index 4fa733d..ec5f355 100644
+--- a/include/asm-ia64/smp.h
++++ b/include/asm-ia64/smp.h
+@@ -38,6 +38,9 @@ ia64_get_lid (void)
+ return lid.f.id << 8 | lid.f.eid;
+ }
+
++extern int smp_call_function_mask(cpumask_t mask, void (*func)(void *),
++ void *info, int wait);
++
+ #define hard_smp_processor_id() ia64_get_lid()
+
+ #ifdef CONFIG_SMP
+diff --git a/include/asm-ia64/sn/nodepda.h b/include/asm-ia64/sn/nodepda.h
+index 6f6d69e..ee118b9 100644
+--- a/include/asm-ia64/sn/nodepda.h
++++ b/include/asm-ia64/sn/nodepda.h
+@@ -9,7 +9,6 @@
+ #define _ASM_IA64_SN_NODEPDA_H
+
+
+-#include <asm/semaphore.h>
+ #include <asm/irq.h>
+ #include <asm/sn/arch.h>
+ #include <asm/sn/intr.h>
+diff --git a/include/asm-ia64/sn/xp.h b/include/asm-ia64/sn/xp.h
+deleted file mode 100644
+index f7711b3..0000000
+--- a/include/asm-ia64/sn/xp.h
++++ /dev/null
+@@ -1,485 +0,0 @@
+-/*
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License. See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (C) 2004-2005 Silicon Graphics, Inc. All rights reserved.
+- */
+-
+-
+-/*
+- * External Cross Partition (XP) structures and defines.
+- */
+-
+-
+-#ifndef _ASM_IA64_SN_XP_H
+-#define _ASM_IA64_SN_XP_H
+-
+-
+-#include <linux/cache.h>
+-#include <linux/hardirq.h>
+-#include <linux/mutex.h>
+-#include <asm/sn/types.h>
+-#include <asm/sn/bte.h>
+-
+-
+-#ifdef USE_DBUG_ON
+-#define DBUG_ON(condition) BUG_ON(condition)
+-#else
+-#define DBUG_ON(condition)
+-#endif
+-
+-
+-/*
+- * Define the maximum number of logically defined partitions the system
+- * can support. It is constrained by the maximum number of hardware
+- * partitionable regions. The term 'region' in this context refers to the
+- * minimum number of nodes that can comprise an access protection grouping.
+- * The access protection is in regards to memory, IPI and IOI.
+- *
+- * The maximum number of hardware partitionable regions is equal to the
+- * maximum number of nodes in the entire system divided by the minimum number
+- * of nodes that comprise an access protection grouping.
+- */
+-#define XP_MAX_PARTITIONS 64
+-
+-
+-/*
+- * Define the number of u64s required to represent all the C-brick nasids
+- * as a bitmap. The cross-partition kernel modules deal only with
+- * C-brick nasids, thus the need for bitmaps which don't account for
+- * odd-numbered (non C-brick) nasids.
+- */
+-#define XP_MAX_PHYSNODE_ID (MAX_NUMALINK_NODES / 2)
+-#define XP_NASID_MASK_BYTES ((XP_MAX_PHYSNODE_ID + 7) / 8)
+-#define XP_NASID_MASK_WORDS ((XP_MAX_PHYSNODE_ID + 63) / 64)
+-
+-
+-/*
+- * Wrapper for bte_copy() that should it return a failure status will retry
+- * the bte_copy() once in the hope that the failure was due to a temporary
+- * aberration (i.e., the link going down temporarily).
+- *
+- * src - physical address of the source of the transfer.
+- * vdst - virtual address of the destination of the transfer.
+- * len - number of bytes to transfer from source to destination.
+- * mode - see bte_copy() for definition.
+- * notification - see bte_copy() for definition.
+- *
+- * Note: xp_bte_copy() should never be called while holding a spinlock.
+- */
+-static inline bte_result_t
+-xp_bte_copy(u64 src, u64 vdst, u64 len, u64 mode, void *notification)
+-{
+- bte_result_t ret;
+- u64 pdst = ia64_tpa(vdst);
+-
+-
+- /*
+- * Ensure that the physically mapped memory is contiguous.
+- *
+- * We do this by ensuring that the memory is from region 7 only.
+- * If the need should arise to use memory from one of the other
+- * regions, then modify the BUG_ON() statement to ensure that the
+- * memory from that region is always physically contiguous.
+- */
+- BUG_ON(REGION_NUMBER(vdst) != RGN_KERNEL);
+-
+- ret = bte_copy(src, pdst, len, mode, notification);
+- if ((ret != BTE_SUCCESS) && BTE_ERROR_RETRY(ret)) {
+- if (!in_interrupt()) {
+- cond_resched();
+- }
+- ret = bte_copy(src, pdst, len, mode, notification);
+- }
+-
+- return ret;
+-}
+-
+-
+-/*
+- * XPC establishes channel connections between the local partition and any
+- * other partition that is currently up. Over these channels, kernel-level
+- * `users' can communicate with their counterparts on the other partitions.
+- *
+- * The maxinum number of channels is limited to eight. For performance reasons,
+- * the internal cross partition structures require sixteen bytes per channel,
+- * and eight allows all of this interface-shared info to fit in one cache line.
+- *
+- * XPC_NCHANNELS reflects the total number of channels currently defined.
+- * If the need for additional channels arises, one can simply increase
+- * XPC_NCHANNELS accordingly. If the day should come where that number
+- * exceeds the MAXIMUM number of channels allowed (eight), then one will need
+- * to make changes to the XPC code to allow for this.
+- */
+-#define XPC_MEM_CHANNEL 0 /* memory channel number */
+-#define XPC_NET_CHANNEL 1 /* network channel number */
+-
+-#define XPC_NCHANNELS 2 /* #of defined channels */
+-#define XPC_MAX_NCHANNELS 8 /* max #of channels allowed */
+-
+-#if XPC_NCHANNELS > XPC_MAX_NCHANNELS
+-#error XPC_NCHANNELS exceeds MAXIMUM allowed.
+-#endif
+-
+-
+-/*
+- * The format of an XPC message is as follows:
+- *
+- * +-------+--------------------------------+
+- * | flags |////////////////////////////////|
+- * +-------+--------------------------------+
+- * | message # |
+- * +----------------------------------------+
+- * | payload (user-defined message) |
+- * | |
+- * :
+- * | |
+- * +----------------------------------------+
+- *
+- * The size of the payload is defined by the user via xpc_connect(). A user-
+- * defined message resides in the payload area.
+- *
+- * The user should have no dealings with the message header, but only the
+- * message's payload. When a message entry is allocated (via xpc_allocate())
+- * a pointer to the payload area is returned and not the actual beginning of
+- * the XPC message. The user then constructs a message in the payload area
+- * and passes that pointer as an argument on xpc_send() or xpc_send_notify().
+- *
+- * The size of a message entry (within a message queue) must be a cacheline
+- * sized multiple in order to facilitate the BTE transfer of messages from one
+- * message queue to another. A macro, XPC_MSG_SIZE(), is provided for the user
+- * that wants to fit as many msg entries as possible in a given memory size
+- * (e.g. a memory page).
+- */
+-struct xpc_msg {
+- u8 flags; /* FOR XPC INTERNAL USE ONLY */
+- u8 reserved[7]; /* FOR XPC INTERNAL USE ONLY */
+- s64 number; /* FOR XPC INTERNAL USE ONLY */
+-
+- u64 payload; /* user defined portion of message */
+-};
+-
+-
+-#define XPC_MSG_PAYLOAD_OFFSET (u64) (&((struct xpc_msg *)0)->payload)
+-#define XPC_MSG_SIZE(_payload_size) \
+- L1_CACHE_ALIGN(XPC_MSG_PAYLOAD_OFFSET + (_payload_size))
+-
+-
+-/*
+- * Define the return values and values passed to user's callout functions.
+- * (It is important to add new value codes at the end just preceding
+- * xpcUnknownReason, which must have the highest numerical value.)
+- */
+-enum xpc_retval {
+- xpcSuccess = 0,
+-
+- xpcNotConnected, /* 1: channel is not connected */
+- xpcConnected, /* 2: channel connected (opened) */
+- xpcRETIRED1, /* 3: (formerly xpcDisconnected) */
+-
+- xpcMsgReceived, /* 4: message received */
+- xpcMsgDelivered, /* 5: message delivered and acknowledged */
+-
+- xpcRETIRED2, /* 6: (formerly xpcTransferFailed) */
+-
+- xpcNoWait, /* 7: operation would require wait */
+- xpcRetry, /* 8: retry operation */
+- xpcTimeout, /* 9: timeout in xpc_allocate_msg_wait() */
+- xpcInterrupted, /* 10: interrupted wait */
+-
+- xpcUnequalMsgSizes, /* 11: message size disparity between sides */
+- xpcInvalidAddress, /* 12: invalid address */
+-
+- xpcNoMemory, /* 13: no memory available for XPC structures */
+- xpcLackOfResources, /* 14: insufficient resources for operation */
+- xpcUnregistered, /* 15: channel is not registered */
+- xpcAlreadyRegistered, /* 16: channel is already registered */
+-
+- xpcPartitionDown, /* 17: remote partition is down */
+- xpcNotLoaded, /* 18: XPC module is not loaded */
+- xpcUnloading, /* 19: this side is unloading XPC module */
+-
+- xpcBadMagic, /* 20: XPC MAGIC string not found */
+-
+- xpcReactivating, /* 21: remote partition was reactivated */
+-
+- xpcUnregistering, /* 22: this side is unregistering channel */
+- xpcOtherUnregistering, /* 23: other side is unregistering channel */
+-
+- xpcCloneKThread, /* 24: cloning kernel thread */
+- xpcCloneKThreadFailed, /* 25: cloning kernel thread failed */
+-
+- xpcNoHeartbeat, /* 26: remote partition has no heartbeat */
+-
+- xpcPioReadError, /* 27: PIO read error */
+- xpcPhysAddrRegFailed, /* 28: registration of phys addr range failed */
+-
+- xpcBteDirectoryError, /* 29: maps to BTEFAIL_DIR */
+- xpcBtePoisonError, /* 30: maps to BTEFAIL_POISON */
+- xpcBteWriteError, /* 31: maps to BTEFAIL_WERR */
+- xpcBteAccessError, /* 32: maps to BTEFAIL_ACCESS */
+- xpcBtePWriteError, /* 33: maps to BTEFAIL_PWERR */
+- xpcBtePReadError, /* 34: maps to BTEFAIL_PRERR */
+- xpcBteTimeOutError, /* 35: maps to BTEFAIL_TOUT */
+- xpcBteXtalkError, /* 36: maps to BTEFAIL_XTERR */
+- xpcBteNotAvailable, /* 37: maps to BTEFAIL_NOTAVAIL */
+- xpcBteUnmappedError, /* 38: unmapped BTEFAIL_ error */
+-
+- xpcBadVersion, /* 39: bad version number */
+- xpcVarsNotSet, /* 40: the XPC variables are not set up */
+- xpcNoRsvdPageAddr, /* 41: unable to get rsvd page's phys addr */
+- xpcInvalidPartid, /* 42: invalid partition ID */
+- xpcLocalPartid, /* 43: local partition ID */
+-
+- xpcOtherGoingDown, /* 44: other side going down, reason unknown */
+- xpcSystemGoingDown, /* 45: system is going down, reason unknown */
+- xpcSystemHalt, /* 46: system is being halted */
+- xpcSystemReboot, /* 47: system is being rebooted */
+- xpcSystemPoweroff, /* 48: system is being powered off */
+-
+- xpcDisconnecting, /* 49: channel disconnecting (closing) */
+-
+- xpcOpenCloseError, /* 50: channel open/close protocol error */
+-
+- xpcDisconnected, /* 51: channel disconnected (closed) */
+-
+- xpcBteSh2Start, /* 52: BTE CRB timeout */
+-
+- /* 53: 0x1 BTE Error Response Short */
+- xpcBteSh2RspShort = xpcBteSh2Start + BTEFAIL_SH2_RESP_SHORT,
+-
+- /* 54: 0x2 BTE Error Response Long */
+- xpcBteSh2RspLong = xpcBteSh2Start + BTEFAIL_SH2_RESP_LONG,
+-
+- /* 56: 0x4 BTE Error Response DSB */
+- xpcBteSh2RspDSB = xpcBteSh2Start + BTEFAIL_SH2_RESP_DSP,
+-
+- /* 60: 0x8 BTE Error Response Access */
+- xpcBteSh2RspAccess = xpcBteSh2Start + BTEFAIL_SH2_RESP_ACCESS,
+-
+- /* 68: 0x10 BTE Error CRB timeout */
+- xpcBteSh2CRBTO = xpcBteSh2Start + BTEFAIL_SH2_CRB_TO,
+-
+- /* 84: 0x20 BTE Error NACK limit */
+- xpcBteSh2NACKLimit = xpcBteSh2Start + BTEFAIL_SH2_NACK_LIMIT,
+-
+- /* 115: BTE end */
+- xpcBteSh2End = xpcBteSh2Start + BTEFAIL_SH2_ALL,
+-
+- xpcUnknownReason /* 116: unknown reason -- must be last in list */
+-};
+-
+-
+-/*
+- * Define the callout function types used by XPC to update the user on
+- * connection activity and state changes (via the user function registered by
+- * xpc_connect()) and to notify them of messages received and delivered (via
+- * the user function registered by xpc_send_notify()).
+- *
+- * The two function types are xpc_channel_func and xpc_notify_func and
+- * both share the following arguments, with the exception of "data", which
+- * only xpc_channel_func has.
+- *
+- * Arguments:
+- *
+- * reason - reason code. (See following table.)
+- * partid - partition ID associated with condition.
+- * ch_number - channel # associated with condition.
+- * data - pointer to optional data. (See following table.)
+- * key - pointer to optional user-defined value provided as the "key"
+- * argument to xpc_connect() or xpc_send_notify().
+- *
+- * In the following table the "Optional Data" column applies to callouts made
+- * to functions registered by xpc_connect(). A "NA" in that column indicates
+- * that this reason code can be passed to functions registered by
+- * xpc_send_notify() (i.e. they don't have data arguments).
+- *
+- * Also, the first three reason codes in the following table indicate
+- * success, whereas the others indicate failure. When a failure reason code
+- * is received, one can assume that the channel is not connected.
+- *
+- *
+- * Reason Code | Cause | Optional Data
+- * =====================+================================+=====================
+- * xpcConnected | connection has been established| max #of entries
+- * | to the specified partition on | allowed in message
+- * | the specified channel | queue
+- * ---------------------+--------------------------------+---------------------
+- * xpcMsgReceived | an XPC message arrived from | address of payload
+- * | the specified partition on the |
+- * | specified channel | [the user must call
+- * | | xpc_received() when
+- * | | finished with the
+- * | | payload]
+- * ---------------------+--------------------------------+---------------------
+- * xpcMsgDelivered | notification that the message | NA
+- * | was delivered to the intended |
+- * | recipient and that they have |
+- * | acknowledged its receipt by |
+- * | calling xpc_received() |
+- * =====================+================================+=====================
+- * xpcUnequalMsgSizes | can't connect to the specified | NULL
+- * | partition on the specified |
+- * | channel because of mismatched |
+- * | message sizes |
+- * ---------------------+--------------------------------+---------------------
+- * xpcNoMemory | insufficient memory avaiable | NULL
+- * | to allocate message queue |
+- * ---------------------+--------------------------------+---------------------
+- * xpcLackOfResources | lack of resources to create | NULL
+- * | the necessary kthreads to |
+- * | support the channel |
+- * ---------------------+--------------------------------+---------------------
+- * xpcUnregistering | this side's user has | NULL or NA
+- * | unregistered by calling |
+- * | xpc_disconnect() |
+- * ---------------------+--------------------------------+---------------------
+- * xpcOtherUnregistering| the other side's user has | NULL or NA
+- * | unregistered by calling |
+- * | xpc_disconnect() |
+- * ---------------------+--------------------------------+---------------------
+- * xpcNoHeartbeat | the other side's XPC is no | NULL or NA
+- * | longer heartbeating |
+- * | |
+- * ---------------------+--------------------------------+---------------------
+- * xpcUnloading | this side's XPC module is | NULL or NA
+- * | being unloaded |
+- * | |
+- * ---------------------+--------------------------------+---------------------
+- * xpcOtherUnloading | the other side's XPC module is | NULL or NA
+- * | is being unloaded |
+- * | |
+- * ---------------------+--------------------------------+---------------------
+- * xpcPioReadError | xp_nofault_PIOR() returned an | NULL or NA
+- * | error while sending an IPI |
+- * | |
+- * ---------------------+--------------------------------+---------------------
+- * xpcInvalidAddress | the address either received or | NULL or NA
+- * | sent by the specified partition|
+- * | is invalid |
+- * ---------------------+--------------------------------+---------------------
+- * xpcBteNotAvailable | attempt to pull data from the | NULL or NA
+- * xpcBtePoisonError | specified partition over the |
+- * xpcBteWriteError | specified channel via a |
+- * xpcBteAccessError | bte_copy() failed |
+- * xpcBteTimeOutError | |
+- * xpcBteXtalkError | |
+- * xpcBteDirectoryError | |
+- * xpcBteGenericError | |
+- * xpcBteUnmappedError | |
+- * ---------------------+--------------------------------+---------------------
+- * xpcUnknownReason | the specified channel to the | NULL or NA
+- * | specified partition was |
+- * | unavailable for unknown reasons|
+- * =====================+================================+=====================
+- */
+-
+-typedef void (*xpc_channel_func)(enum xpc_retval reason, partid_t partid,
+- int ch_number, void *data, void *key);
+-
+-typedef void (*xpc_notify_func)(enum xpc_retval reason, partid_t partid,
+- int ch_number, void *key);
+-
+-
+-/*
+- * The following is a registration entry. There is a global array of these,
+- * one per channel. It is used to record the connection registration made
+- * by the users of XPC. As long as a registration entry exists, for any
+- * partition that comes up, XPC will attempt to establish a connection on
+- * that channel. Notification that a connection has been made will occur via
+- * the xpc_channel_func function.
+- *
+- * The 'func' field points to the function to call when aynchronous
+- * notification is required for such events as: a connection established/lost,
+- * or an incoming message received, or an error condition encountered. A
+- * non-NULL 'func' field indicates that there is an active registration for
+- * the channel.
+- */
+-struct xpc_registration {
+- struct mutex mutex;
+- xpc_channel_func func; /* function to call */
+- void *key; /* pointer to user's key */
+- u16 nentries; /* #of msg entries in local msg queue */
+- u16 msg_size; /* message queue's message size */
+- u32 assigned_limit; /* limit on #of assigned kthreads */
+- u32 idle_limit; /* limit on #of idle kthreads */
+-} ____cacheline_aligned;
+-
+-
+-#define XPC_CHANNEL_REGISTERED(_c) (xpc_registrations[_c].func != NULL)
+-
+-
+-/* the following are valid xpc_allocate() flags */
+-#define XPC_WAIT 0 /* wait flag */
+-#define XPC_NOWAIT 1 /* no wait flag */
+-
+-
+-struct xpc_interface {
+- void (*connect)(int);
+- void (*disconnect)(int);
+- enum xpc_retval (*allocate)(partid_t, int, u32, void **);
+- enum xpc_retval (*send)(partid_t, int, void *);
+- enum xpc_retval (*send_notify)(partid_t, int, void *,
+- xpc_notify_func, void *);
+- void (*received)(partid_t, int, void *);
+- enum xpc_retval (*partid_to_nasids)(partid_t, void *);
+-};
+-
+-
+-extern struct xpc_interface xpc_interface;
+-
+-extern void xpc_set_interface(void (*)(int),
+- void (*)(int),
+- enum xpc_retval (*)(partid_t, int, u32, void **),
+- enum xpc_retval (*)(partid_t, int, void *),
+- enum xpc_retval (*)(partid_t, int, void *, xpc_notify_func,
+- void *),
+- void (*)(partid_t, int, void *),
+- enum xpc_retval (*)(partid_t, void *));
+-extern void xpc_clear_interface(void);
+-
+-
+-extern enum xpc_retval xpc_connect(int, xpc_channel_func, void *, u16,
+- u16, u32, u32);
+-extern void xpc_disconnect(int);
+-
+-static inline enum xpc_retval
+-xpc_allocate(partid_t partid, int ch_number, u32 flags, void **payload)
+-{
+- return xpc_interface.allocate(partid, ch_number, flags, payload);
+-}
+-
+-static inline enum xpc_retval
+-xpc_send(partid_t partid, int ch_number, void *payload)
+-{
+- return xpc_interface.send(partid, ch_number, payload);
+-}
+-
+-static inline enum xpc_retval
+-xpc_send_notify(partid_t partid, int ch_number, void *payload,
+- xpc_notify_func func, void *key)
+-{
+- return xpc_interface.send_notify(partid, ch_number, payload, func, key);
+-}
+-
+-static inline void
+-xpc_received(partid_t partid, int ch_number, void *payload)
+-{
+- return xpc_interface.received(partid, ch_number, payload);
+-}
+-
+-static inline enum xpc_retval
+-xpc_partid_to_nasids(partid_t partid, void *nasids)
+-{
+- return xpc_interface.partid_to_nasids(partid, nasids);
+-}
+-
+-
+-extern u64 xp_nofault_PIOR_target;
+-extern int xp_nofault_PIOR(void *);
+-extern int xp_error_PIOR(void);
+-
+-
+-#endif /* _ASM_IA64_SN_XP_H */
+-
+diff --git a/include/asm-ia64/sn/xpc.h b/include/asm-ia64/sn/xpc.h
+deleted file mode 100644
+index 3c0900a..0000000
+--- a/include/asm-ia64/sn/xpc.h
++++ /dev/null
+@@ -1,1267 +0,0 @@
+-/*
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License. See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (c) 2004-2007 Silicon Graphics, Inc. All Rights Reserved.
+- */
+-
+-
+-/*
+- * Cross Partition Communication (XPC) structures and macros.
+- */
+-
+-#ifndef _ASM_IA64_SN_XPC_H
+-#define _ASM_IA64_SN_XPC_H
+-
+-
+-#include <linux/interrupt.h>
+-#include <linux/sysctl.h>
+-#include <linux/device.h>
+-#include <linux/mutex.h>
+-#include <linux/completion.h>
+-#include <asm/pgtable.h>
+-#include <asm/processor.h>
+-#include <asm/sn/bte.h>
+-#include <asm/sn/clksupport.h>
+-#include <asm/sn/addrs.h>
+-#include <asm/sn/mspec.h>
+-#include <asm/sn/shub_mmr.h>
+-#include <asm/sn/xp.h>
+-
+-
+-/*
+- * XPC Version numbers consist of a major and minor number. XPC can always
+- * talk to versions with same major #, and never talk to versions with a
+- * different major #.
+- */
+-#define _XPC_VERSION(_maj, _min) (((_maj) << 4) | ((_min) & 0xf))
+-#define XPC_VERSION_MAJOR(_v) ((_v) >> 4)
+-#define XPC_VERSION_MINOR(_v) ((_v) & 0xf)
+-
+-
+-/*
+- * The next macros define word or bit representations for given
+- * C-brick nasid in either the SAL provided bit array representing
+- * nasids in the partition/machine or the AMO_t array used for
+- * inter-partition initiation communications.
+- *
+- * For SN2 machines, C-Bricks are alway even numbered NASIDs. As
+- * such, some space will be saved by insisting that nasid information
+- * passed from SAL always be packed for C-Bricks and the
+- * cross-partition interrupts use the same packing scheme.
+- */
+-#define XPC_NASID_W_INDEX(_n) (((_n) / 64) / 2)
+-#define XPC_NASID_B_INDEX(_n) (((_n) / 2) & (64 - 1))
+-#define XPC_NASID_IN_ARRAY(_n, _p) ((_p)[XPC_NASID_W_INDEX(_n)] & \
+- (1UL << XPC_NASID_B_INDEX(_n)))
+-#define XPC_NASID_FROM_W_B(_w, _b) (((_w) * 64 + (_b)) * 2)
+-
+-#define XPC_HB_DEFAULT_INTERVAL 5 /* incr HB every x secs */
+-#define XPC_HB_CHECK_DEFAULT_INTERVAL 20 /* check HB every x secs */
+-
+-/* define the process name of HB checker and the CPU it is pinned to */
+-#define XPC_HB_CHECK_THREAD_NAME "xpc_hb"
+-#define XPC_HB_CHECK_CPU 0
+-
+-/* define the process name of the discovery thread */
+-#define XPC_DISCOVERY_THREAD_NAME "xpc_discovery"
+-
+-
+-/*
+- * the reserved page
+- *
+- * SAL reserves one page of memory per partition for XPC. Though a full page
+- * in length (16384 bytes), its starting address is not page aligned, but it
+- * is cacheline aligned. The reserved page consists of the following:
+- *
+- * reserved page header
+- *
+- * The first cacheline of the reserved page contains the header
+- * (struct xpc_rsvd_page). Before SAL initialization has completed,
+- * SAL has set up the following fields of the reserved page header:
+- * SAL_signature, SAL_version, partid, and nasids_size. The other
+- * fields are set up by XPC. (xpc_rsvd_page points to the local
+- * partition's reserved page.)
+- *
+- * part_nasids mask
+- * mach_nasids mask
+- *
+- * SAL also sets up two bitmaps (or masks), one that reflects the actual
+- * nasids in this partition (part_nasids), and the other that reflects
+- * the actual nasids in the entire machine (mach_nasids). We're only
+- * interested in the even numbered nasids (which contain the processors
+- * and/or memory), so we only need half as many bits to represent the
+- * nasids. The part_nasids mask is located starting at the first cacheline
+- * following the reserved page header. The mach_nasids mask follows right
+- * after the part_nasids mask. The size in bytes of each mask is reflected
+- * by the reserved page header field 'nasids_size'. (Local partition's
+- * mask pointers are xpc_part_nasids and xpc_mach_nasids.)
+- *
+- * vars
+- * vars part
+- *
+- * Immediately following the mach_nasids mask are the XPC variables
+- * required by other partitions. First are those that are generic to all
+- * partitions (vars), followed on the next available cacheline by those
+- * which are partition specific (vars part). These are setup by XPC.
+- * (Local partition's vars pointers are xpc_vars and xpc_vars_part.)
+- *
+- * Note: Until vars_pa is set, the partition XPC code has not been initialized.
+- */
+-struct xpc_rsvd_page {
+- u64 SAL_signature; /* SAL: unique signature */
+- u64 SAL_version; /* SAL: version */
+- u8 partid; /* SAL: partition ID */
+- u8 version;
+- u8 pad1[6]; /* align to next u64 in cacheline */
+- volatile u64 vars_pa;
+- struct timespec stamp; /* time when reserved page was setup by XPC */
+- u64 pad2[9]; /* align to last u64 in cacheline */
+- u64 nasids_size; /* SAL: size of each nasid mask in bytes */
+-};
+-
+-#define XPC_RP_VERSION _XPC_VERSION(1,1) /* version 1.1 of the reserved page */
+-
+-#define XPC_SUPPORTS_RP_STAMP(_version) \
+- (_version >= _XPC_VERSION(1,1))
+-
+-/*
+- * compare stamps - the return value is:
+- *
+- * < 0, if stamp1 < stamp2
+- * = 0, if stamp1 == stamp2
+- * > 0, if stamp1 > stamp2
+- */
+-static inline int
+-xpc_compare_stamps(struct timespec *stamp1, struct timespec *stamp2)
+-{
+- int ret;
+-
+-
+- if ((ret = stamp1->tv_sec - stamp2->tv_sec) == 0) {
+- ret = stamp1->tv_nsec - stamp2->tv_nsec;
+- }
+- return ret;
+-}
+-
+-
+-/*
+- * Define the structures by which XPC variables can be exported to other
+- * partitions. (There are two: struct xpc_vars and struct xpc_vars_part)
+- */
+-
+-/*
+- * The following structure describes the partition generic variables
+- * needed by other partitions in order to properly initialize.
+- *
+- * struct xpc_vars version number also applies to struct xpc_vars_part.
+- * Changes to either structure and/or related functionality should be
+- * reflected by incrementing either the major or minor version numbers
+- * of struct xpc_vars.
+- */
+-struct xpc_vars {
+- u8 version;
+- u64 heartbeat;
+- u64 heartbeating_to_mask;
+- u64 heartbeat_offline; /* if 0, heartbeat should be changing */
+- int act_nasid;
+- int act_phys_cpuid;
+- u64 vars_part_pa;
+- u64 amos_page_pa; /* paddr of page of AMOs from MSPEC driver */
+- AMO_t *amos_page; /* vaddr of page of AMOs from MSPEC driver */
+-};
+-
+-#define XPC_V_VERSION _XPC_VERSION(3,1) /* version 3.1 of the cross vars */
+-
+-#define XPC_SUPPORTS_DISENGAGE_REQUEST(_version) \
+- (_version >= _XPC_VERSION(3,1))
+-
+-
+-static inline int
+-xpc_hb_allowed(partid_t partid, struct xpc_vars *vars)
+-{
+- return ((vars->heartbeating_to_mask & (1UL << partid)) != 0);
+-}
+-
+-static inline void
+-xpc_allow_hb(partid_t partid, struct xpc_vars *vars)
+-{
+- u64 old_mask, new_mask;
+-
+- do {
+- old_mask = vars->heartbeating_to_mask;
+- new_mask = (old_mask | (1UL << partid));
+- } while (cmpxchg(&vars->heartbeating_to_mask, old_mask, new_mask) !=
+- old_mask);
+-}
+-
+-static inline void
+-xpc_disallow_hb(partid_t partid, struct xpc_vars *vars)
+-{
+- u64 old_mask, new_mask;
+-
+- do {
+- old_mask = vars->heartbeating_to_mask;
+- new_mask = (old_mask & ~(1UL << partid));
+- } while (cmpxchg(&vars->heartbeating_to_mask, old_mask, new_mask) !=
+- old_mask);
+-}
+-
+-
+-/*
+- * The AMOs page consists of a number of AMO variables which are divided into
+- * four groups, The first two groups are used to identify an IRQ's sender.
+- * These two groups consist of 64 and 128 AMO variables respectively. The last
+- * two groups, consisting of just one AMO variable each, are used to identify
+- * the remote partitions that are currently engaged (from the viewpoint of
+- * the XPC running on the remote partition).
+- */
+-#define XPC_NOTIFY_IRQ_AMOS 0
+-#define XPC_ACTIVATE_IRQ_AMOS (XPC_NOTIFY_IRQ_AMOS + XP_MAX_PARTITIONS)
+-#define XPC_ENGAGED_PARTITIONS_AMO (XPC_ACTIVATE_IRQ_AMOS + XP_NASID_MASK_WORDS)
+-#define XPC_DISENGAGE_REQUEST_AMO (XPC_ENGAGED_PARTITIONS_AMO + 1)
+-
+-
+-/*
+- * The following structure describes the per partition specific variables.
+- *
+- * An array of these structures, one per partition, will be defined. As a
+- * partition becomes active XPC will copy the array entry corresponding to
+- * itself from that partition. It is desirable that the size of this
+- * structure evenly divide into a cacheline, such that none of the entries
+- * in this array crosses a cacheline boundary. As it is now, each entry
+- * occupies half a cacheline.
+- */
+-struct xpc_vars_part {
+- volatile u64 magic;
+-
+- u64 openclose_args_pa; /* physical address of open and close args */
+- u64 GPs_pa; /* physical address of Get/Put values */
+-
+- u64 IPI_amo_pa; /* physical address of IPI AMO_t structure */
+- int IPI_nasid; /* nasid of where to send IPIs */
+- int IPI_phys_cpuid; /* physical CPU ID of where to send IPIs */
+-
+- u8 nchannels; /* #of defined channels supported */
+-
+- u8 reserved[23]; /* pad to a full 64 bytes */
+-};
+-
+-/*
+- * The vars_part MAGIC numbers play a part in the first contact protocol.
+- *
+- * MAGIC1 indicates that the per partition specific variables for a remote
+- * partition have been initialized by this partition.
+- *
+- * MAGIC2 indicates that this partition has pulled the remote partititions
+- * per partition variables that pertain to this partition.
+- */
+-#define XPC_VP_MAGIC1 0x0053524156435058L /* 'XPCVARS\0'L (little endian) */
+-#define XPC_VP_MAGIC2 0x0073726176435058L /* 'XPCvars\0'L (little endian) */
+-
+-
+-/* the reserved page sizes and offsets */
+-
+-#define XPC_RP_HEADER_SIZE L1_CACHE_ALIGN(sizeof(struct xpc_rsvd_page))
+-#define XPC_RP_VARS_SIZE L1_CACHE_ALIGN(sizeof(struct xpc_vars))
+-
+-#define XPC_RP_PART_NASIDS(_rp) (u64 *) ((u8 *) _rp + XPC_RP_HEADER_SIZE)
+-#define XPC_RP_MACH_NASIDS(_rp) (XPC_RP_PART_NASIDS(_rp) + xp_nasid_mask_words)
+-#define XPC_RP_VARS(_rp) ((struct xpc_vars *) XPC_RP_MACH_NASIDS(_rp) + xp_nasid_mask_words)
+-#define XPC_RP_VARS_PART(_rp) (struct xpc_vars_part *) ((u8 *) XPC_RP_VARS(rp) + XPC_RP_VARS_SIZE)
+-
+-
+-/*
+- * Functions registered by add_timer() or called by kernel_thread() only
+- * allow for a single 64-bit argument. The following macros can be used to
+- * pack and unpack two (32-bit, 16-bit or 8-bit) arguments into or out from
+- * the passed argument.
+- */
+-#define XPC_PACK_ARGS(_arg1, _arg2) \
+- ((((u64) _arg1) & 0xffffffff) | \
+- ((((u64) _arg2) & 0xffffffff) << 32))
+-
+-#define XPC_UNPACK_ARG1(_args) (((u64) _args) & 0xffffffff)
+-#define XPC_UNPACK_ARG2(_args) ((((u64) _args) >> 32) & 0xffffffff)
+-
+-
+-
+-/*
+- * Define a Get/Put value pair (pointers) used with a message queue.
+- */
+-struct xpc_gp {
+- volatile s64 get; /* Get value */
+- volatile s64 put; /* Put value */
+-};
+-
+-#define XPC_GP_SIZE \
+- L1_CACHE_ALIGN(sizeof(struct xpc_gp) * XPC_NCHANNELS)
+-
+-
+-
+-/*
+- * Define a structure that contains arguments associated with opening and
+- * closing a channel.
+- */
+-struct xpc_openclose_args {
+- u16 reason; /* reason why channel is closing */
+- u16 msg_size; /* sizeof each message entry */
+- u16 remote_nentries; /* #of message entries in remote msg queue */
+- u16 local_nentries; /* #of message entries in local msg queue */
+- u64 local_msgqueue_pa; /* physical address of local message queue */
+-};
+-
+-#define XPC_OPENCLOSE_ARGS_SIZE \
+- L1_CACHE_ALIGN(sizeof(struct xpc_openclose_args) * XPC_NCHANNELS)
+-
+-
+-
+-/* struct xpc_msg flags */
+-
+-#define XPC_M_DONE 0x01 /* msg has been received/consumed */
+-#define XPC_M_READY 0x02 /* msg is ready to be sent */
+-#define XPC_M_INTERRUPT 0x04 /* send interrupt when msg consumed */
+-
+-
+-#define XPC_MSG_ADDRESS(_payload) \
+- ((struct xpc_msg *)((u8 *)(_payload) - XPC_MSG_PAYLOAD_OFFSET))
+-
+-
+-
+-/*
+- * Defines notify entry.
+- *
+- * This is used to notify a message's sender that their message was received
+- * and consumed by the intended recipient.
+- */
+-struct xpc_notify {
+- volatile u8 type; /* type of notification */
+-
+- /* the following two fields are only used if type == XPC_N_CALL */
+- xpc_notify_func func; /* user's notify function */
+- void *key; /* pointer to user's key */
+-};
+-
+-/* struct xpc_notify type of notification */
+-
+-#define XPC_N_CALL 0x01 /* notify function provided by user */
+-
+-
+-
+-/*
+- * Define the structure that manages all the stuff required by a channel. In
+- * particular, they are used to manage the messages sent across the channel.
+- *
+- * This structure is private to a partition, and is NOT shared across the
+- * partition boundary.
+- *
+- * There is an array of these structures for each remote partition. It is
+- * allocated at the time a partition becomes active. The array contains one
+- * of these structures for each potential channel connection to that partition.
+- *
+- * Each of these structures manages two message queues (circular buffers).
+- * They are allocated at the time a channel connection is made. One of
+- * these message queues (local_msgqueue) holds the locally created messages
+- * that are destined for the remote partition. The other of these message
+- * queues (remote_msgqueue) is a locally cached copy of the remote partition's
+- * own local_msgqueue.
+- *
+- * The following is a description of the Get/Put pointers used to manage these
+- * two message queues. Consider the local_msgqueue to be on one partition
+- * and the remote_msgqueue to be its cached copy on another partition. A
+- * description of what each of the lettered areas contains is included.
+- *
+- *
+- * local_msgqueue remote_msgqueue
+- *
+- * |/////////| |/////////|
+- * w_remote_GP.get --> +---------+ |/////////|
+- * | F | |/////////|
+- * remote_GP.get --> +---------+ +---------+ <-- local_GP->get
+- * | | | |
+- * | | | E |
+- * | | | |
+- * | | +---------+ <-- w_local_GP.get
+- * | B | |/////////|
+- * | | |////D////|
+- * | | |/////////|
+- * | | +---------+ <-- w_remote_GP.put
+- * | | |////C////|
+- * local_GP->put --> +---------+ +---------+ <-- remote_GP.put
+- * | | |/////////|
+- * | A | |/////////|
+- * | | |/////////|
+- * w_local_GP.put --> +---------+ |/////////|
+- * |/////////| |/////////|
+- *
+- *
+- * ( remote_GP.[get|put] are cached copies of the remote
+- * partition's local_GP->[get|put], and thus their values can
+- * lag behind their counterparts on the remote partition. )
+- *
+- *
+- * A - Messages that have been allocated, but have not yet been sent to the
+- * remote partition.
+- *
+- * B - Messages that have been sent, but have not yet been acknowledged by the
+- * remote partition as having been received.
+- *
+- * C - Area that needs to be prepared for the copying of sent messages, by
+- * the clearing of the message flags of any previously received messages.
+- *
+- * D - Area into which sent messages are to be copied from the remote
+- * partition's local_msgqueue and then delivered to their intended
+- * recipients. [ To allow for a multi-message copy, another pointer
+- * (next_msg_to_pull) has been added to keep track of the next message
+- * number needing to be copied (pulled). It chases after w_remote_GP.put.
+- * Any messages lying between w_local_GP.get and next_msg_to_pull have
+- * been copied and are ready to be delivered. ]
+- *
+- * E - Messages that have been copied and delivered, but have not yet been
+- * acknowledged by the recipient as having been received.
+- *
+- * F - Messages that have been acknowledged, but XPC has not yet notified the
+- * sender that the message was received by its intended recipient.
+- * This is also an area that needs to be prepared for the allocating of
+- * new messages, by the clearing of the message flags of the acknowledged
+- * messages.
+- */
+-struct xpc_channel {
+- partid_t partid; /* ID of remote partition connected */
+- spinlock_t lock; /* lock for updating this structure */
+- u32 flags; /* general flags */
+-
+- enum xpc_retval reason; /* reason why channel is disconnect'g */
+- int reason_line; /* line# disconnect initiated from */
+-
+- u16 number; /* channel # */
+-
+- u16 msg_size; /* sizeof each msg entry */
+- u16 local_nentries; /* #of msg entries in local msg queue */
+- u16 remote_nentries; /* #of msg entries in remote msg queue*/
+-
+- void *local_msgqueue_base; /* base address of kmalloc'd space */
+- struct xpc_msg *local_msgqueue; /* local message queue */
+- void *remote_msgqueue_base; /* base address of kmalloc'd space */
+- struct xpc_msg *remote_msgqueue;/* cached copy of remote partition's */
+- /* local message queue */
+- u64 remote_msgqueue_pa; /* phys addr of remote partition's */
+- /* local message queue */
+-
+- atomic_t references; /* #of external references to queues */
+-
+- atomic_t n_on_msg_allocate_wq; /* #on msg allocation wait queue */
+- wait_queue_head_t msg_allocate_wq; /* msg allocation wait queue */
+-
+- u8 delayed_IPI_flags; /* IPI flags received, but delayed */
+- /* action until channel disconnected */
+-
+- /* queue of msg senders who want to be notified when msg received */
+-
+- atomic_t n_to_notify; /* #of msg senders to notify */
+- struct xpc_notify *notify_queue;/* notify queue for messages sent */
+-
+- xpc_channel_func func; /* user's channel function */
+- void *key; /* pointer to user's key */
+-
+- struct mutex msg_to_pull_mutex; /* next msg to pull serialization */
+- struct completion wdisconnect_wait; /* wait for channel disconnect */
+-
+- struct xpc_openclose_args *local_openclose_args; /* args passed on */
+- /* opening or closing of channel */
+-
+- /* various flavors of local and remote Get/Put values */
+-
+- struct xpc_gp *local_GP; /* local Get/Put values */
+- struct xpc_gp remote_GP; /* remote Get/Put values */
+- struct xpc_gp w_local_GP; /* working local Get/Put values */
+- struct xpc_gp w_remote_GP; /* working remote Get/Put values */
+- s64 next_msg_to_pull; /* Put value of next msg to pull */
+-
+- /* kthread management related fields */
+-
+-// >>> rethink having kthreads_assigned_limit and kthreads_idle_limit; perhaps
+-// >>> allow the assigned limit be unbounded and let the idle limit be dynamic
+-// >>> dependent on activity over the last interval of time
+- atomic_t kthreads_assigned; /* #of kthreads assigned to channel */
+- u32 kthreads_assigned_limit; /* limit on #of kthreads assigned */
+- atomic_t kthreads_idle; /* #of kthreads idle waiting for work */
+- u32 kthreads_idle_limit; /* limit on #of kthreads idle */
+- atomic_t kthreads_active; /* #of kthreads actively working */
+- // >>> following field is temporary
+- u32 kthreads_created; /* total #of kthreads created */
+-
+- wait_queue_head_t idle_wq; /* idle kthread wait queue */
+-
+-} ____cacheline_aligned;
+-
+-
+-/* struct xpc_channel flags */
+-
+-#define XPC_C_WASCONNECTED 0x00000001 /* channel was connected */
+-
+-#define XPC_C_ROPENREPLY 0x00000002 /* remote open channel reply */
+-#define XPC_C_OPENREPLY 0x00000004 /* local open channel reply */
+-#define XPC_C_ROPENREQUEST 0x00000008 /* remote open channel request */
+-#define XPC_C_OPENREQUEST 0x00000010 /* local open channel request */
+-
+-#define XPC_C_SETUP 0x00000020 /* channel's msgqueues are alloc'd */
+-#define XPC_C_CONNECTEDCALLOUT 0x00000040 /* connected callout initiated */
+-#define XPC_C_CONNECTEDCALLOUT_MADE \
+- 0x00000080 /* connected callout completed */
+-#define XPC_C_CONNECTED 0x00000100 /* local channel is connected */
+-#define XPC_C_CONNECTING 0x00000200 /* channel is being connected */
+-
+-#define XPC_C_RCLOSEREPLY 0x00000400 /* remote close channel reply */
+-#define XPC_C_CLOSEREPLY 0x00000800 /* local close channel reply */
+-#define XPC_C_RCLOSEREQUEST 0x00001000 /* remote close channel request */
+-#define XPC_C_CLOSEREQUEST 0x00002000 /* local close channel request */
+-
+-#define XPC_C_DISCONNECTED 0x00004000 /* channel is disconnected */
+-#define XPC_C_DISCONNECTING 0x00008000 /* channel is being disconnected */
+-#define XPC_C_DISCONNECTINGCALLOUT \
+- 0x00010000 /* disconnecting callout initiated */
+-#define XPC_C_DISCONNECTINGCALLOUT_MADE \
+- 0x00020000 /* disconnecting callout completed */
+-#define XPC_C_WDISCONNECT 0x00040000 /* waiting for channel disconnect */
+-
+-
+-
+-/*
+- * Manages channels on a partition basis. There is one of these structures
+- * for each partition (a partition will never utilize the structure that
+- * represents itself).
+- */
+-struct xpc_partition {
+-
+- /* XPC HB infrastructure */
+-
+- u8 remote_rp_version; /* version# of partition's rsvd pg */
+- struct timespec remote_rp_stamp;/* time when rsvd pg was initialized */
+- u64 remote_rp_pa; /* phys addr of partition's rsvd pg */
+- u64 remote_vars_pa; /* phys addr of partition's vars */
+- u64 remote_vars_part_pa; /* phys addr of partition's vars part */
+- u64 last_heartbeat; /* HB at last read */
+- u64 remote_amos_page_pa; /* phys addr of partition's amos page */
+- int remote_act_nasid; /* active part's act/deact nasid */
+- int remote_act_phys_cpuid; /* active part's act/deact phys cpuid */
+- u32 act_IRQ_rcvd; /* IRQs since activation */
+- spinlock_t act_lock; /* protect updating of act_state */
+- u8 act_state; /* from XPC HB viewpoint */
+- u8 remote_vars_version; /* version# of partition's vars */
+- enum xpc_retval reason; /* reason partition is deactivating */
+- int reason_line; /* line# deactivation initiated from */
+- int reactivate_nasid; /* nasid in partition to reactivate */
+-
+- unsigned long disengage_request_timeout; /* timeout in jiffies */
+- struct timer_list disengage_request_timer;
+-
+-
+- /* XPC infrastructure referencing and teardown control */
+-
+- volatile u8 setup_state; /* infrastructure setup state */
+- wait_queue_head_t teardown_wq; /* kthread waiting to teardown infra */
+- atomic_t references; /* #of references to infrastructure */
+-
+-
+- /*
+- * NONE OF THE PRECEDING FIELDS OF THIS STRUCTURE WILL BE CLEARED WHEN
+- * XPC SETS UP THE NECESSARY INFRASTRUCTURE TO SUPPORT CROSS PARTITION
+- * COMMUNICATION. ALL OF THE FOLLOWING FIELDS WILL BE CLEARED. (THE
+- * 'nchannels' FIELD MUST BE THE FIRST OF THE FIELDS TO BE CLEARED.)
+- */
+-
+-
+- u8 nchannels; /* #of defined channels supported */
+- atomic_t nchannels_active; /* #of channels that are not DISCONNECTED */
+- atomic_t nchannels_engaged;/* #of channels engaged with remote part */
+- struct xpc_channel *channels;/* array of channel structures */
+-
+- void *local_GPs_base; /* base address of kmalloc'd space */
+- struct xpc_gp *local_GPs; /* local Get/Put values */
+- void *remote_GPs_base; /* base address of kmalloc'd space */
+- struct xpc_gp *remote_GPs;/* copy of remote partition's local Get/Put */
+- /* values */
+- u64 remote_GPs_pa; /* phys address of remote partition's local */
+- /* Get/Put values */
+-
+-
+- /* fields used to pass args when opening or closing a channel */
+-
+- void *local_openclose_args_base; /* base address of kmalloc'd space */
+- struct xpc_openclose_args *local_openclose_args; /* local's args */
+- void *remote_openclose_args_base; /* base address of kmalloc'd space */
+- struct xpc_openclose_args *remote_openclose_args; /* copy of remote's */
+- /* args */
+- u64 remote_openclose_args_pa; /* phys addr of remote's args */
+-
+-
+- /* IPI sending, receiving and handling related fields */
+-
+- int remote_IPI_nasid; /* nasid of where to send IPIs */
+- int remote_IPI_phys_cpuid; /* phys CPU ID of where to send IPIs */
+- AMO_t *remote_IPI_amo_va; /* address of remote IPI AMO_t structure */
+-
+- AMO_t *local_IPI_amo_va; /* address of IPI AMO_t structure */
+- u64 local_IPI_amo; /* IPI amo flags yet to be handled */
+- char IPI_owner[8]; /* IPI owner's name */
+- struct timer_list dropped_IPI_timer; /* dropped IPI timer */
+-
+- spinlock_t IPI_lock; /* IPI handler lock */
+-
+-
+- /* channel manager related fields */
+-
+- atomic_t channel_mgr_requests; /* #of requests to activate chan mgr */
+- wait_queue_head_t channel_mgr_wq; /* channel mgr's wait queue */
+-
+-} ____cacheline_aligned;
+-
+-
+-/* struct xpc_partition act_state values (for XPC HB) */
+-
+-#define XPC_P_INACTIVE 0x00 /* partition is not active */
+-#define XPC_P_ACTIVATION_REQ 0x01 /* created thread to activate */
+-#define XPC_P_ACTIVATING 0x02 /* activation thread started */
+-#define XPC_P_ACTIVE 0x03 /* xpc_partition_up() was called */
+-#define XPC_P_DEACTIVATING 0x04 /* partition deactivation initiated */
+-
+-
+-#define XPC_DEACTIVATE_PARTITION(_p, _reason) \
+- xpc_deactivate_partition(__LINE__, (_p), (_reason))
+-
+-
+-/* struct xpc_partition setup_state values */
+-
+-#define XPC_P_UNSET 0x00 /* infrastructure was never setup */
+-#define XPC_P_SETUP 0x01 /* infrastructure is setup */
+-#define XPC_P_WTEARDOWN 0x02 /* waiting to teardown infrastructure */
+-#define XPC_P_TORNDOWN 0x03 /* infrastructure is torndown */
+-
+-
+-
+-/*
+- * struct xpc_partition IPI_timer #of seconds to wait before checking for
+- * dropped IPIs. These occur whenever an IPI amo write doesn't complete until
+- * after the IPI was received.
+- */
+-#define XPC_P_DROPPED_IPI_WAIT (0.25 * HZ)
+-
+-
+-/* number of seconds to wait for other partitions to disengage */
+-#define XPC_DISENGAGE_REQUEST_DEFAULT_TIMELIMIT 90
+-
+-/* interval in seconds to print 'waiting disengagement' messages */
+-#define XPC_DISENGAGE_PRINTMSG_INTERVAL 10
+-
+-
+-#define XPC_PARTID(_p) ((partid_t) ((_p) - &xpc_partitions[0]))
+-
+-
+-
+-/* found in xp_main.c */
+-extern struct xpc_registration xpc_registrations[];
+-
+-
+-/* found in xpc_main.c */
+-extern struct device *xpc_part;
+-extern struct device *xpc_chan;
+-extern int xpc_disengage_request_timelimit;
+-extern int xpc_disengage_request_timedout;
+-extern irqreturn_t xpc_notify_IRQ_handler(int, void *);
+-extern void xpc_dropped_IPI_check(struct xpc_partition *);
+-extern void xpc_activate_partition(struct xpc_partition *);
+-extern void xpc_activate_kthreads(struct xpc_channel *, int);
+-extern void xpc_create_kthreads(struct xpc_channel *, int, int);
+-extern void xpc_disconnect_wait(int);
+-
+-
+-/* found in xpc_partition.c */
+-extern int xpc_exiting;
+-extern struct xpc_vars *xpc_vars;
+-extern struct xpc_rsvd_page *xpc_rsvd_page;
+-extern struct xpc_vars_part *xpc_vars_part;
+-extern struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1];
+-extern char *xpc_remote_copy_buffer;
+-extern void *xpc_remote_copy_buffer_base;
+-extern void *xpc_kmalloc_cacheline_aligned(size_t, gfp_t, void **);
+-extern struct xpc_rsvd_page *xpc_rsvd_page_init(void);
+-extern void xpc_allow_IPI_ops(void);
+-extern void xpc_restrict_IPI_ops(void);
+-extern int xpc_identify_act_IRQ_sender(void);
+-extern int xpc_partition_disengaged(struct xpc_partition *);
+-extern enum xpc_retval xpc_mark_partition_active(struct xpc_partition *);
+-extern void xpc_mark_partition_inactive(struct xpc_partition *);
+-extern void xpc_discovery(void);
+-extern void xpc_check_remote_hb(void);
+-extern void xpc_deactivate_partition(const int, struct xpc_partition *,
+- enum xpc_retval);
+-extern enum xpc_retval xpc_initiate_partid_to_nasids(partid_t, void *);
+-
+-
+-/* found in xpc_channel.c */
+-extern void xpc_initiate_connect(int);
+-extern void xpc_initiate_disconnect(int);
+-extern enum xpc_retval xpc_initiate_allocate(partid_t, int, u32, void **);
+-extern enum xpc_retval xpc_initiate_send(partid_t, int, void *);
+-extern enum xpc_retval xpc_initiate_send_notify(partid_t, int, void *,
+- xpc_notify_func, void *);
+-extern void xpc_initiate_received(partid_t, int, void *);
+-extern enum xpc_retval xpc_setup_infrastructure(struct xpc_partition *);
+-extern enum xpc_retval xpc_pull_remote_vars_part(struct xpc_partition *);
+-extern void xpc_process_channel_activity(struct xpc_partition *);
+-extern void xpc_connected_callout(struct xpc_channel *);
+-extern void xpc_deliver_msg(struct xpc_channel *);
+-extern void xpc_disconnect_channel(const int, struct xpc_channel *,
+- enum xpc_retval, unsigned long *);
+-extern void xpc_disconnect_callout(struct xpc_channel *, enum xpc_retval);
+-extern void xpc_partition_going_down(struct xpc_partition *, enum xpc_retval);
+-extern void xpc_teardown_infrastructure(struct xpc_partition *);
+-
+-
+-
+-static inline void
+-xpc_wakeup_channel_mgr(struct xpc_partition *part)
+-{
+- if (atomic_inc_return(&part->channel_mgr_requests) == 1) {
+- wake_up(&part->channel_mgr_wq);
+- }
+-}
+-
+-
+-
+-/*
+- * These next two inlines are used to keep us from tearing down a channel's
+- * msg queues while a thread may be referencing them.
+- */
+-static inline void
+-xpc_msgqueue_ref(struct xpc_channel *ch)
+-{
+- atomic_inc(&ch->references);
+-}
+-
+-static inline void
+-xpc_msgqueue_deref(struct xpc_channel *ch)
+-{
+- s32 refs = atomic_dec_return(&ch->references);
+-
+- DBUG_ON(refs < 0);
+- if (refs == 0) {
+- xpc_wakeup_channel_mgr(&xpc_partitions[ch->partid]);
+- }
+-}
+-
+-
+-
+-#define XPC_DISCONNECT_CHANNEL(_ch, _reason, _irqflgs) \
+- xpc_disconnect_channel(__LINE__, _ch, _reason, _irqflgs)
+-
+-
+-/*
+- * These two inlines are used to keep us from tearing down a partition's
+- * setup infrastructure while a thread may be referencing it.
+- */
+-static inline void
+-xpc_part_deref(struct xpc_partition *part)
+-{
+- s32 refs = atomic_dec_return(&part->references);
+-
+-
+- DBUG_ON(refs < 0);
+- if (refs == 0 && part->setup_state == XPC_P_WTEARDOWN) {
+- wake_up(&part->teardown_wq);
+- }
+-}
+-
+-static inline int
+-xpc_part_ref(struct xpc_partition *part)
+-{
+- int setup;
+-
+-
+- atomic_inc(&part->references);
+- setup = (part->setup_state == XPC_P_SETUP);
+- if (!setup) {
+- xpc_part_deref(part);
+- }
+- return setup;
+-}
+-
+-
+-
+-/*
+- * The following macro is to be used for the setting of the reason and
+- * reason_line fields in both the struct xpc_channel and struct xpc_partition
+- * structures.
+- */
+-#define XPC_SET_REASON(_p, _reason, _line) \
+- { \
+- (_p)->reason = _reason; \
+- (_p)->reason_line = _line; \
+- }
+-
+-
+-
+-/*
+- * This next set of inlines are used to keep track of when a partition is
+- * potentially engaged in accessing memory belonging to another partition.
+- */
+-
+-static inline void
+-xpc_mark_partition_engaged(struct xpc_partition *part)
+-{
+- unsigned long irq_flags;
+- AMO_t *amo = (AMO_t *) __va(part->remote_amos_page_pa +
+- (XPC_ENGAGED_PARTITIONS_AMO * sizeof(AMO_t)));
+-
+-
+- local_irq_save(irq_flags);
+-
+- /* set bit corresponding to our partid in remote partition's AMO */
+- FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_OR,
+- (1UL << sn_partition_id));
+- /*
+- * We must always use the nofault function regardless of whether we
+- * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
+- * didn't, we'd never know that the other partition is down and would
+- * keep sending IPIs and AMOs to it until the heartbeat times out.
+- */
+- (void) xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->
+- variable), xp_nofault_PIOR_target));
+-
+- local_irq_restore(irq_flags);
+-}
+-
+-static inline void
+-xpc_mark_partition_disengaged(struct xpc_partition *part)
+-{
+- unsigned long irq_flags;
+- AMO_t *amo = (AMO_t *) __va(part->remote_amos_page_pa +
+- (XPC_ENGAGED_PARTITIONS_AMO * sizeof(AMO_t)));
+-
+-
+- local_irq_save(irq_flags);
+-
+- /* clear bit corresponding to our partid in remote partition's AMO */
+- FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_AND,
+- ~(1UL << sn_partition_id));
+- /*
+- * We must always use the nofault function regardless of whether we
+- * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
+- * didn't, we'd never know that the other partition is down and would
+- * keep sending IPIs and AMOs to it until the heartbeat times out.
+- */
+- (void) xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->
+- variable), xp_nofault_PIOR_target));
+-
+- local_irq_restore(irq_flags);
+-}
+-
+-static inline void
+-xpc_request_partition_disengage(struct xpc_partition *part)
+-{
+- unsigned long irq_flags;
+- AMO_t *amo = (AMO_t *) __va(part->remote_amos_page_pa +
+- (XPC_DISENGAGE_REQUEST_AMO * sizeof(AMO_t)));
+-
+-
+- local_irq_save(irq_flags);
+-
+- /* set bit corresponding to our partid in remote partition's AMO */
+- FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_OR,
+- (1UL << sn_partition_id));
+- /*
+- * We must always use the nofault function regardless of whether we
+- * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
+- * didn't, we'd never know that the other partition is down and would
+- * keep sending IPIs and AMOs to it until the heartbeat times out.
+- */
+- (void) xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->
+- variable), xp_nofault_PIOR_target));
+-
+- local_irq_restore(irq_flags);
+-}
+-
+-static inline void
+-xpc_cancel_partition_disengage_request(struct xpc_partition *part)
+-{
+- unsigned long irq_flags;
+- AMO_t *amo = (AMO_t *) __va(part->remote_amos_page_pa +
+- (XPC_DISENGAGE_REQUEST_AMO * sizeof(AMO_t)));
+-
+-
+- local_irq_save(irq_flags);
+-
+- /* clear bit corresponding to our partid in remote partition's AMO */
+- FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_AND,
+- ~(1UL << sn_partition_id));
+- /*
+- * We must always use the nofault function regardless of whether we
+- * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
+- * didn't, we'd never know that the other partition is down and would
+- * keep sending IPIs and AMOs to it until the heartbeat times out.
+- */
+- (void) xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->
+- variable), xp_nofault_PIOR_target));
+-
+- local_irq_restore(irq_flags);
+-}
+-
+-static inline u64
+-xpc_partition_engaged(u64 partid_mask)
+-{
+- AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO;
+-
+-
+- /* return our partition's AMO variable ANDed with partid_mask */
+- return (FETCHOP_LOAD_OP(TO_AMO((u64) &amo->variable), FETCHOP_LOAD) &
+- partid_mask);
+-}
+-
+-static inline u64
+-xpc_partition_disengage_requested(u64 partid_mask)
+-{
+- AMO_t *amo = xpc_vars->amos_page + XPC_DISENGAGE_REQUEST_AMO;
+-
+-
+- /* return our partition's AMO variable ANDed with partid_mask */
+- return (FETCHOP_LOAD_OP(TO_AMO((u64) &amo->variable), FETCHOP_LOAD) &
+- partid_mask);
+-}
+-
+-static inline void
+-xpc_clear_partition_engaged(u64 partid_mask)
+-{
+- AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO;
+-
+-
+- /* clear bit(s) based on partid_mask in our partition's AMO */
+- FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_AND,
+- ~partid_mask);
+-}
+-
+-static inline void
+-xpc_clear_partition_disengage_request(u64 partid_mask)
+-{
+- AMO_t *amo = xpc_vars->amos_page + XPC_DISENGAGE_REQUEST_AMO;
+-
+-
+- /* clear bit(s) based on partid_mask in our partition's AMO */
+- FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_AND,
+- ~partid_mask);
+-}
+-
+-
+-
+-/*
+- * The following set of macros and inlines are used for the sending and
+- * receiving of IPIs (also known as IRQs). There are two flavors of IPIs,
+- * one that is associated with partition activity (SGI_XPC_ACTIVATE) and
+- * the other that is associated with channel activity (SGI_XPC_NOTIFY).
+- */
+-
+-static inline u64
+-xpc_IPI_receive(AMO_t *amo)
+-{
+- return FETCHOP_LOAD_OP(TO_AMO((u64) &amo->variable), FETCHOP_CLEAR);
+-}
+-
+-
+-static inline enum xpc_retval
+-xpc_IPI_send(AMO_t *amo, u64 flag, int nasid, int phys_cpuid, int vector)
+-{
+- int ret = 0;
+- unsigned long irq_flags;
+-
+-
+- local_irq_save(irq_flags);
+-
+- FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_OR, flag);
+- sn_send_IPI_phys(nasid, phys_cpuid, vector, 0);
+-
+- /*
+- * We must always use the nofault function regardless of whether we
+- * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
+- * didn't, we'd never know that the other partition is down and would
+- * keep sending IPIs and AMOs to it until the heartbeat times out.
+- */
+- ret = xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->variable),
+- xp_nofault_PIOR_target));
+-
+- local_irq_restore(irq_flags);
+-
+- return ((ret == 0) ? xpcSuccess : xpcPioReadError);
+-}
+-
+-
+-/*
+- * IPIs associated with SGI_XPC_ACTIVATE IRQ.
+- */
+-
+-/*
+- * Flag the appropriate AMO variable and send an IPI to the specified node.
+- */
+-static inline void
+-xpc_activate_IRQ_send(u64 amos_page_pa, int from_nasid, int to_nasid,
+- int to_phys_cpuid)
+-{
+- int w_index = XPC_NASID_W_INDEX(from_nasid);
+- int b_index = XPC_NASID_B_INDEX(from_nasid);
+- AMO_t *amos = (AMO_t *) __va(amos_page_pa +
+- (XPC_ACTIVATE_IRQ_AMOS * sizeof(AMO_t)));
+-
+-
+- (void) xpc_IPI_send(&amos[w_index], (1UL << b_index), to_nasid,
+- to_phys_cpuid, SGI_XPC_ACTIVATE);
+-}
+-
+-static inline void
+-xpc_IPI_send_activate(struct xpc_vars *vars)
+-{
+- xpc_activate_IRQ_send(vars->amos_page_pa, cnodeid_to_nasid(0),
+- vars->act_nasid, vars->act_phys_cpuid);
+-}
+-
+-static inline void
+-xpc_IPI_send_activated(struct xpc_partition *part)
+-{
+- xpc_activate_IRQ_send(part->remote_amos_page_pa, cnodeid_to_nasid(0),
+- part->remote_act_nasid, part->remote_act_phys_cpuid);
+-}
+-
+-static inline void
+-xpc_IPI_send_reactivate(struct xpc_partition *part)
+-{
+- xpc_activate_IRQ_send(xpc_vars->amos_page_pa, part->reactivate_nasid,
+- xpc_vars->act_nasid, xpc_vars->act_phys_cpuid);
+-}
+-
+-static inline void
+-xpc_IPI_send_disengage(struct xpc_partition *part)
+-{
+- xpc_activate_IRQ_send(part->remote_amos_page_pa, cnodeid_to_nasid(0),
+- part->remote_act_nasid, part->remote_act_phys_cpuid);
+-}
+-
+-
+-/*
+- * IPIs associated with SGI_XPC_NOTIFY IRQ.
+- */
+-
+-/*
+- * Send an IPI to the remote partition that is associated with the
+- * specified channel.
+- */
+-#define XPC_NOTIFY_IRQ_SEND(_ch, _ipi_f, _irq_f) \
+- xpc_notify_IRQ_send(_ch, _ipi_f, #_ipi_f, _irq_f)
+-
+-static inline void
+-xpc_notify_IRQ_send(struct xpc_channel *ch, u8 ipi_flag, char *ipi_flag_string,
+- unsigned long *irq_flags)
+-{
+- struct xpc_partition *part = &xpc_partitions[ch->partid];
+- enum xpc_retval ret;
+-
+-
+- if (likely(part->act_state != XPC_P_DEACTIVATING)) {
+- ret = xpc_IPI_send(part->remote_IPI_amo_va,
+- (u64) ipi_flag << (ch->number * 8),
+- part->remote_IPI_nasid,
+- part->remote_IPI_phys_cpuid,
+- SGI_XPC_NOTIFY);
+- dev_dbg(xpc_chan, "%s sent to partid=%d, channel=%d, ret=%d\n",
+- ipi_flag_string, ch->partid, ch->number, ret);
+- if (unlikely(ret != xpcSuccess)) {
+- if (irq_flags != NULL) {
+- spin_unlock_irqrestore(&ch->lock, *irq_flags);
+- }
+- XPC_DEACTIVATE_PARTITION(part, ret);
+- if (irq_flags != NULL) {
+- spin_lock_irqsave(&ch->lock, *irq_flags);
+- }
+- }
+- }
+-}
+-
+-
+-/*
+- * Make it look like the remote partition, which is associated with the
+- * specified channel, sent us an IPI. This faked IPI will be handled
+- * by xpc_dropped_IPI_check().
+- */
+-#define XPC_NOTIFY_IRQ_SEND_LOCAL(_ch, _ipi_f) \
+- xpc_notify_IRQ_send_local(_ch, _ipi_f, #_ipi_f)
+-
+-static inline void
+-xpc_notify_IRQ_send_local(struct xpc_channel *ch, u8 ipi_flag,
+- char *ipi_flag_string)
+-{
+- struct xpc_partition *part = &xpc_partitions[ch->partid];
+-
+-
+- FETCHOP_STORE_OP(TO_AMO((u64) &part->local_IPI_amo_va->variable),
+- FETCHOP_OR, ((u64) ipi_flag << (ch->number * 8)));
+- dev_dbg(xpc_chan, "%s sent local from partid=%d, channel=%d\n",
+- ipi_flag_string, ch->partid, ch->number);
+-}
+-
+-
+-/*
+- * The sending and receiving of IPIs includes the setting of an AMO variable
+- * to indicate the reason the IPI was sent. The 64-bit variable is divided
+- * up into eight bytes, ordered from right to left. Byte zero pertains to
+- * channel 0, byte one to channel 1, and so on. Each byte is described by
+- * the following IPI flags.
+- */
+-
+-#define XPC_IPI_CLOSEREQUEST 0x01
+-#define XPC_IPI_CLOSEREPLY 0x02
+-#define XPC_IPI_OPENREQUEST 0x04
+-#define XPC_IPI_OPENREPLY 0x08
+-#define XPC_IPI_MSGREQUEST 0x10
+-
+-
+-/* given an AMO variable and a channel#, get its associated IPI flags */
+-#define XPC_GET_IPI_FLAGS(_amo, _c) ((u8) (((_amo) >> ((_c) * 8)) & 0xff))
+-#define XPC_SET_IPI_FLAGS(_amo, _c, _f) (_amo) |= ((u64) (_f) << ((_c) * 8))
+-
+-#define XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(_amo) ((_amo) & __IA64_UL_CONST(0x0f0f0f0f0f0f0f0f))
+-#define XPC_ANY_MSG_IPI_FLAGS_SET(_amo) ((_amo) & __IA64_UL_CONST(0x1010101010101010))
+-
+-
+-static inline void
+-xpc_IPI_send_closerequest(struct xpc_channel *ch, unsigned long *irq_flags)
+-{
+- struct xpc_openclose_args *args = ch->local_openclose_args;
+-
+-
+- args->reason = ch->reason;
+-
+- XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_CLOSEREQUEST, irq_flags);
+-}
+-
+-static inline void
+-xpc_IPI_send_closereply(struct xpc_channel *ch, unsigned long *irq_flags)
+-{
+- XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_CLOSEREPLY, irq_flags);
+-}
+-
+-static inline void
+-xpc_IPI_send_openrequest(struct xpc_channel *ch, unsigned long *irq_flags)
+-{
+- struct xpc_openclose_args *args = ch->local_openclose_args;
+-
+-
+- args->msg_size = ch->msg_size;
+- args->local_nentries = ch->local_nentries;
+-
+- XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_OPENREQUEST, irq_flags);
+-}
+-
+-static inline void
+-xpc_IPI_send_openreply(struct xpc_channel *ch, unsigned long *irq_flags)
+-{
+- struct xpc_openclose_args *args = ch->local_openclose_args;
+-
+-
+- args->remote_nentries = ch->remote_nentries;
+- args->local_nentries = ch->local_nentries;
+- args->local_msgqueue_pa = __pa(ch->local_msgqueue);
+-
+- XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_OPENREPLY, irq_flags);
+-}
+-
+-static inline void
+-xpc_IPI_send_msgrequest(struct xpc_channel *ch)
+-{
+- XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_MSGREQUEST, NULL);
+-}
+-
+-static inline void
+-xpc_IPI_send_local_msgrequest(struct xpc_channel *ch)
+-{
+- XPC_NOTIFY_IRQ_SEND_LOCAL(ch, XPC_IPI_MSGREQUEST);
+-}
+-
+-
+-/*
+- * Memory for XPC's AMO variables is allocated by the MSPEC driver. These
+- * pages are located in the lowest granule. The lowest granule uses 4k pages
+- * for cached references and an alternate TLB handler to never provide a
+- * cacheable mapping for the entire region. This will prevent speculative
+- * reading of cached copies of our lines from being issued which will cause
+- * a PI FSB Protocol error to be generated by the SHUB. For XPC, we need 64
+- * AMO variables (based on XP_MAX_PARTITIONS) for message notification and an
+- * additional 128 AMO variables (based on XP_NASID_MASK_WORDS) for partition
+- * activation and 2 AMO variables for partition deactivation.
+- */
+-static inline AMO_t *
+-xpc_IPI_init(int index)
+-{
+- AMO_t *amo = xpc_vars->amos_page + index;
+-
+-
+- (void) xpc_IPI_receive(amo); /* clear AMO variable */
+- return amo;
+-}
+-
+-
+-
+-static inline enum xpc_retval
+-xpc_map_bte_errors(bte_result_t error)
+-{
+- if (error == BTE_SUCCESS)
+- return xpcSuccess;
+-
+- if (is_shub2()) {
+- if (BTE_VALID_SH2_ERROR(error))
+- return xpcBteSh2Start + error;
+- return xpcBteUnmappedError;
+- }
+- switch (error) {
+- case BTE_SUCCESS: return xpcSuccess;
+- case BTEFAIL_DIR: return xpcBteDirectoryError;
+- case BTEFAIL_POISON: return xpcBtePoisonError;
+- case BTEFAIL_WERR: return xpcBteWriteError;
+- case BTEFAIL_ACCESS: return xpcBteAccessError;
+- case BTEFAIL_PWERR: return xpcBtePWriteError;
+- case BTEFAIL_PRERR: return xpcBtePReadError;
+- case BTEFAIL_TOUT: return xpcBteTimeOutError;
+- case BTEFAIL_XTERR: return xpcBteXtalkError;
+- case BTEFAIL_NOTAVAIL: return xpcBteNotAvailable;
+- default: return xpcBteUnmappedError;
+- }
+-}
+-
+-
+-
+-/*
+- * Check to see if there is any channel activity to/from the specified
+- * partition.
+- */
+-static inline void
+-xpc_check_for_channel_activity(struct xpc_partition *part)
+-{
+- u64 IPI_amo;
+- unsigned long irq_flags;
+-
+-
+- IPI_amo = xpc_IPI_receive(part->local_IPI_amo_va);
+- if (IPI_amo == 0) {
+- return;
+- }
+-
+- spin_lock_irqsave(&part->IPI_lock, irq_flags);
+- part->local_IPI_amo |= IPI_amo;
+- spin_unlock_irqrestore(&part->IPI_lock, irq_flags);
+-
+- dev_dbg(xpc_chan, "received IPI from partid=%d, IPI_amo=0x%lx\n",
+- XPC_PARTID(part), IPI_amo);
+-
+- xpc_wakeup_channel_mgr(part);
+-}
+-
+-
+-#endif /* _ASM_IA64_SN_XPC_H */
+-
+diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h
+index 595112b..dff8128 100644
+--- a/include/asm-ia64/system.h
++++ b/include/asm-ia64/system.h
+@@ -210,6 +210,13 @@ struct task_struct;
+ extern void ia64_save_extra (struct task_struct *task);
+ extern void ia64_load_extra (struct task_struct *task);
+
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++extern void ia64_account_on_switch (struct task_struct *prev, struct task_struct *next);
++# define IA64_ACCOUNT_ON_SWITCH(p,n) ia64_account_on_switch(p,n)
++#else
++# define IA64_ACCOUNT_ON_SWITCH(p,n)
++#endif
++
+ #ifdef CONFIG_PERFMON
+ DECLARE_PER_CPU(unsigned long, pfm_syst_info);
+ # define PERFMON_IS_SYSWIDE() (__get_cpu_var(pfm_syst_info) & 0x1)
+@@ -222,6 +229,7 @@ extern void ia64_load_extra (struct task_struct *task);
+ || IS_IA32_PROCESS(task_pt_regs(t)) || PERFMON_IS_SYSWIDE())
+
+ #define __switch_to(prev,next,last) do { \
++ IA64_ACCOUNT_ON_SWITCH(prev, next); \
+ if (IA64_HAS_EXTRA_STATE(prev)) \
+ ia64_save_extra(prev); \
+ if (IA64_HAS_EXTRA_STATE(next)) \
+@@ -266,6 +274,10 @@ void cpu_idle_wait(void);
+
+ void default_idle(void);
+
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++extern void account_system_vtime(struct task_struct *);
++#endif
++
+ #endif /* __KERNEL__ */
+
+ #endif /* __ASSEMBLY__ */
+diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h
+index 93d83cb..6da8069 100644
+--- a/include/asm-ia64/thread_info.h
++++ b/include/asm-ia64/thread_info.h
+@@ -31,6 +31,12 @@ struct thread_info {
+ mm_segment_t addr_limit; /* user-level address space limit */
+ int preempt_count; /* 0=premptable, <0=BUG; will also serve as bh-counter */
+ struct restart_block restart_block;
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++ __u64 ac_stamp;
++ __u64 ac_leave;
++ __u64 ac_stime;
++ __u64 ac_utime;
++#endif
+ };
+
+ #define THREAD_SIZE KERNEL_STACK_SIZE
+@@ -62,9 +68,17 @@ struct thread_info {
+ #define task_stack_page(tsk) ((void *)(tsk))
+
+ #define __HAVE_THREAD_FUNCTIONS
++#ifdef CONFIG_VIRT_CPU_ACCOUNTING
++#define setup_thread_stack(p, org) \
++ *task_thread_info(p) = *task_thread_info(org); \
++ task_thread_info(p)->ac_stime = 0; \
++ task_thread_info(p)->ac_utime = 0; \
++ task_thread_info(p)->task = (p);
++#else
+ #define setup_thread_stack(p, org) \
+ *task_thread_info(p) = *task_thread_info(org); \
+ task_thread_info(p)->task = (p);
++#endif
+ #define end_of_stack(p) (unsigned long *)((void *)(p) + IA64_RBS_OFFSET)
+
+ #define __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
+diff --git a/include/asm-ia64/tlb.h b/include/asm-ia64/tlb.h
+index 26edcb7..20d8a39 100644
+--- a/include/asm-ia64/tlb.h
++++ b/include/asm-ia64/tlb.h
+@@ -64,6 +64,32 @@ struct mmu_gather {
+ struct page *pages[FREE_PTE_NR];
+ };
+
++struct ia64_tr_entry {
++ u64 ifa;
++ u64 itir;
++ u64 pte;
++ u64 rr;
++}; /*Record for tr entry!*/
++
++extern int ia64_itr_entry(u64 target_mask, u64 va, u64 pte, u64 log_size);
++extern void ia64_ptr_entry(u64 target_mask, int slot);
++
++extern struct ia64_tr_entry __per_cpu_idtrs[NR_CPUS][2][IA64_TR_ALLOC_MAX];
++
++/*
++ region register macros
++*/
++#define RR_TO_VE(val) (((val) >> 0) & 0x0000000000000001)
++#define RR_VE(val) (((val) & 0x0000000000000001) << 0)
++#define RR_VE_MASK 0x0000000000000001L
++#define RR_VE_SHIFT 0
++#define RR_TO_PS(val) (((val) >> 2) & 0x000000000000003f)
++#define RR_PS(val) (((val) & 0x000000000000003f) << 2)
++#define RR_PS_MASK 0x00000000000000fcL
++#define RR_PS_SHIFT 2
++#define RR_RID_MASK 0x00000000ffffff00L
++#define RR_TO_RID(val) ((val >> 8) & 0xffffff)
++
+ /* Users of the generic TLB shootdown code must declare this storage space. */
+ DECLARE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+diff --git a/include/asm-ia64/tlbflush.h b/include/asm-ia64/tlbflush.h
+index 7774a1c..3be25df 100644
+--- a/include/asm-ia64/tlbflush.h
++++ b/include/asm-ia64/tlbflush.h
+@@ -17,6 +17,7 @@
+ * Now for some TLB flushing routines. This is the kind of stuff that
+ * can be very expensive, so try to avoid them whenever possible.
+ */
++extern void setup_ptcg_sem(int max_purges, int from_palo);
+
+ /*
+ * Flush everything (kernel mapping may also have changed due to
+diff --git a/include/asm-ia64/topology.h b/include/asm-ia64/topology.h
+index 2d67b72..f2f72ef 100644
+--- a/include/asm-ia64/topology.h
++++ b/include/asm-ia64/topology.h
+@@ -93,7 +93,7 @@ void build_cpu_to_node_map(void);
+ .cache_nice_tries = 2, \
+ .busy_idx = 3, \
+ .idle_idx = 2, \
+- .newidle_idx = 0, /* unused */ \
++ .newidle_idx = 2, \
+ .wake_idx = 1, \
+ .forkexec_idx = 1, \
+ .flags = SD_LOAD_BALANCE \
+@@ -116,6 +116,11 @@ void build_cpu_to_node_map(void);
+ #define smt_capable() (smp_num_siblings > 1)
+ #endif
+
++#define pcibus_to_cpumask(bus) (pcibus_to_node(bus) == -1 ? \
++ CPU_MASK_ALL : \
++ node_to_cpumask(pcibus_to_node(bus)) \
++ )
++
+ #include <asm-generic/topology.h>
+
+ #endif /* _ASM_IA64_TOPOLOGY_H */
+diff --git a/include/asm-m32r/ide.h b/include/asm-m32r/ide.h
+index 5d2044e..1e7f647 100644
+--- a/include/asm-m32r/ide.h
++++ b/include/asm-m32r/ide.h
+@@ -23,8 +23,6 @@
+ # endif
+ #endif
+
+-#define IDE_ARCH_OBSOLETE_DEFAULTS
+-
+ static __inline__ int ide_default_irq(unsigned long base)
+ {
+ switch (base) {
+@@ -65,14 +63,6 @@ static __inline__ unsigned long ide_default_io_base(int index)
+ }
+ }
+
+-#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */
+-
+-#ifdef CONFIG_BLK_DEV_IDEPCI
+-#define ide_init_default_irq(base) (0)
+-#else
+-#define ide_init_default_irq(base) ide_default_irq(base)
+-#endif
+-
+ #include <asm-generic/ide_iops.h>
+
+ #endif /* __KERNEL__ */
+diff --git a/include/asm-m32r/semaphore.h b/include/asm-m32r/semaphore.h
+index b5bf95a..d9b2034 100644
+--- a/include/asm-m32r/semaphore.h
++++ b/include/asm-m32r/semaphore.h
+@@ -1,144 +1 @@
+-#ifndef _ASM_M32R_SEMAPHORE_H
+-#define _ASM_M32R_SEMAPHORE_H
+-
+-#include <linux/linkage.h>
+-
+-#ifdef __KERNEL__
+-
+-/*
+- * SMP- and interrupt-safe semaphores..
+- *
+- * Copyright (C) 1996 Linus Torvalds
+- * Copyright (C) 2004, 2006 Hirokazu Takata <takata at linux-m32r.org>
+- */
+-
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-#include <asm/assembler.h>
+-#include <asm/system.h>
+-#include <asm/atomic.h>
+-
+-struct semaphore {
+- atomic_t count;
+- int sleepers;
+- wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n) \
+-{ \
+- .count = ATOMIC_INIT(n), \
+- .sleepers = 0, \
+- .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+- struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+-/*
+- * *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+- *
+- * i'd rather use the more flexible initialization above, but sadly
+- * GCC 2.7.2.3 emits a bogus warning. EGCS doesnt. Oh well.
+- */
+- atomic_set(&sem->count, val);
+- sem->sleepers = 0;
+- init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+- sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+- sema_init(sem, 0);
+-}
+-
+-asmlinkage void __down_failed(void /* special register calling convention */);
+-asmlinkage int __down_failed_interruptible(void /* params in registers */);
+-asmlinkage int __down_failed_trylock(void /* params in registers */);
+-asmlinkage void __up_wakeup(void /* special register calling convention */);
+-
+-asmlinkage void __down(struct semaphore * sem);
+-asmlinkage int __down_interruptible(struct semaphore * sem);
+-asmlinkage int __down_trylock(struct semaphore * sem);
+-asmlinkage void __up(struct semaphore * sem);
+-
+-/*
+- * Atomically decrement the semaphore's count. If it goes negative,
+- * block the calling thread in the TASK_UNINTERRUPTIBLE state.
+- */
+-static inline void down(struct semaphore * sem)
+-{
+- might_sleep();
+- if (unlikely(atomic_dec_return(&sem->count) < 0))
+- __down(sem);
+-}
+-
+-/*
+- * Interruptible try to acquire a semaphore. If we obtained
+- * it, return zero. If we were interrupted, returns -EINTR
+- */
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+- int result = 0;
+-
+- might_sleep();
+- if (unlikely(atomic_dec_return(&sem->count) < 0))
+- result = __down_interruptible(sem);
+-
+- return result;
+-}
+-
+-/*
+- * Non-blockingly attempt to down() a semaphore.
+- * Returns zero if we acquired it
+- */
+-static inline int down_trylock(struct semaphore * sem)
+-{
+- unsigned long flags;
+- long count;
+- int result = 0;
+-
+- local_irq_save(flags);
+- __asm__ __volatile__ (
+- "# down_trylock \n\t"
+- DCACHE_CLEAR("%0", "r4", "%1")
+- M32R_LOCK" %0, @%1; \n\t"
+- "addi %0, #-1; \n\t"
+- M32R_UNLOCK" %0, @%1; \n\t"
+- : "=&r" (count)
+- : "r" (&sem->count)
+- : "memory"
+-#ifdef CONFIG_CHIP_M32700_TS1
+- , "r4"
+-#endif /* CONFIG_CHIP_M32700_TS1 */
+- );
+- local_irq_restore(flags);
+-
+- if (unlikely(count < 0))
+- result = __down_trylock(sem);
+-
+- return result;
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- * The default case (no contention) will result in NO
+- * jumps for both down() and up().
+- */
+-static inline void up(struct semaphore * sem)
+-{
+- if (unlikely(atomic_inc_return(&sem->count) <= 0))
+- __up(sem);
+-}
+-
+-#endif /* __KERNEL__ */
+-
+-#endif /* _ASM_M32R_SEMAPHORE_H */
++#include <linux/semaphore.h>
+diff --git a/include/asm-m68k/semaphore-helper.h b/include/asm-m68k/semaphore-helper.h
+deleted file mode 100644
+index eef30ba..0000000
+--- a/include/asm-m68k/semaphore-helper.h
++++ /dev/null
+@@ -1,142 +0,0 @@
+-#ifndef _M68K_SEMAPHORE_HELPER_H
+-#define _M68K_SEMAPHORE_HELPER_H
+-
+-/*
+- * SMP- and interrupt-safe semaphores helper functions.
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- *
+- * m68k version by Andreas Schwab
+- */
+-
+-#include <linux/errno.h>
+-
+-/*
+- * These two _must_ execute atomically wrt each other.
+- */
+-static inline void wake_one_more(struct semaphore * sem)
+-{
+- atomic_inc(&sem->waking);
+-}
+-
+-#ifndef CONFIG_RMW_INSNS
+-extern spinlock_t semaphore_wake_lock;
+-#endif
+-
+-static inline int waking_non_zero(struct semaphore *sem)
+-{
+- int ret;
+-#ifndef CONFIG_RMW_INSNS
+- unsigned long flags;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- ret = 0;
+- if (atomic_read(&sem->waking) > 0) {
+- atomic_dec(&sem->waking);
+- ret = 1;
+- }
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-#else
+- int tmp1, tmp2;
+-
+- __asm__ __volatile__
+- ("1: movel %1,%2\n"
+- " jle 2f\n"
+- " subql #1,%2\n"
+- " casl %1,%2,%3\n"
+- " jne 1b\n"
+- " moveq #1,%0\n"
+- "2:"
+- : "=d" (ret), "=d" (tmp1), "=d" (tmp2)
+- : "m" (sem->waking), "0" (0), "1" (sem->waking));
+-#endif
+-
+- return ret;
+-}
+-
+-/*
+- * waking_non_zero_interruptible:
+- * 1 got the lock
+- * 0 go to sleep
+- * -EINTR interrupted
+- */
+-static inline int waking_non_zero_interruptible(struct semaphore *sem,
+- struct task_struct *tsk)
+-{
+- int ret;
+-#ifndef CONFIG_RMW_INSNS
+- unsigned long flags;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- ret = 0;
+- if (atomic_read(&sem->waking) > 0) {
+- atomic_dec(&sem->waking);
+- ret = 1;
+- } else if (signal_pending(tsk)) {
+- atomic_inc(&sem->count);
+- ret = -EINTR;
+- }
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-#else
+- int tmp1, tmp2;
+-
+- __asm__ __volatile__
+- ("1: movel %1,%2\n"
+- " jle 2f\n"
+- " subql #1,%2\n"
+- " casl %1,%2,%3\n"
+- " jne 1b\n"
+- " moveq #1,%0\n"
+- " jra %a4\n"
+- "2:"
+- : "=d" (ret), "=d" (tmp1), "=d" (tmp2)
+- : "m" (sem->waking), "i" (&&next), "0" (0), "1" (sem->waking));
+- if (signal_pending(tsk)) {
+- atomic_inc(&sem->count);
+- ret = -EINTR;
+- }
+-next:
+-#endif
+-
+- return ret;
+-}
+-
+-/*
+- * waking_non_zero_trylock:
+- * 1 failed to lock
+- * 0 got the lock
+- */
+-static inline int waking_non_zero_trylock(struct semaphore *sem)
+-{
+- int ret;
+-#ifndef CONFIG_RMW_INSNS
+- unsigned long flags;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- ret = 1;
+- if (atomic_read(&sem->waking) > 0) {
+- atomic_dec(&sem->waking);
+- ret = 0;
+- } else
+- atomic_inc(&sem->count);
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+-#else
+- int tmp1, tmp2;
+-
+- __asm__ __volatile__
+- ("1: movel %1,%2\n"
+- " jle 2f\n"
+- " subql #1,%2\n"
+- " casl %1,%2,%3\n"
+- " jne 1b\n"
+- " moveq #0,%0\n"
+- "2:"
+- : "=d" (ret), "=d" (tmp1), "=d" (tmp2)
+- : "m" (sem->waking), "0" (1), "1" (sem->waking));
+- if (ret)
+- atomic_inc(&sem->count);
+-#endif
+- return ret;
+-}
+-
+-#endif
+diff --git a/include/asm-m68k/semaphore.h b/include/asm-m68k/semaphore.h
+index 64d6b11..d9b2034 100644
+--- a/include/asm-m68k/semaphore.h
++++ b/include/asm-m68k/semaphore.h
+@@ -1,163 +1 @@
+-#ifndef _M68K_SEMAPHORE_H
+-#define _M68K_SEMAPHORE_H
+-
+-#define RW_LOCK_BIAS 0x01000000
+-
+-#ifndef __ASSEMBLY__
+-
+-#include <linux/linkage.h>
+-#include <linux/wait.h>
+-#include <linux/spinlock.h>
+-#include <linux/rwsem.h>
+-#include <linux/stringify.h>
+-
+-#include <asm/system.h>
+-#include <asm/atomic.h>
+-
+-/*
+- * Interrupt-safe semaphores..
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- *
+- * m68k version by Andreas Schwab
+- */
+-
+-
+-struct semaphore {
+- atomic_t count;
+- atomic_t waking;
+- wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n) \
+-{ \
+- .count = ATOMIC_INIT(n), \
+- .waking = ATOMIC_INIT(0), \
+- .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+- struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init(struct semaphore *sem, int val)
+-{
+- *sem = (struct semaphore)__SEMAPHORE_INITIALIZER(*sem, val);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+- sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+- sema_init(sem, 0);
+-}
+-
+-asmlinkage void __down_failed(void /* special register calling convention */);
+-asmlinkage int __down_failed_interruptible(void /* params in registers */);
+-asmlinkage int __down_failed_trylock(void /* params in registers */);
+-asmlinkage void __up_wakeup(void /* special register calling convention */);
+-
+-asmlinkage void __down(struct semaphore * sem);
+-asmlinkage int __down_interruptible(struct semaphore * sem);
+-asmlinkage int __down_trylock(struct semaphore * sem);
+-asmlinkage void __up(struct semaphore * sem);
+-
+-/*
+- * This is ugly, but we want the default case to fall through.
+- * "down_failed" is a special asm handler that calls the C
+- * routine that actually waits. See arch/m68k/lib/semaphore.S
+- */
+-static inline void down(struct semaphore *sem)
+-{
+- register struct semaphore *sem1 __asm__ ("%a1") = sem;
+-
+- might_sleep();
+- __asm__ __volatile__(
+- "| atomic down operation\n\t"
+- "subql #1,%0@\n\t"
+- "jmi 2f\n\t"
+- "1:\n"
+- LOCK_SECTION_START(".even\n\t")
+- "2:\tpea 1b\n\t"
+- "jbra __down_failed\n"
+- LOCK_SECTION_END
+- : /* no outputs */
+- : "a" (sem1)
+- : "memory");
+-}
+-
+-static inline int down_interruptible(struct semaphore *sem)
+-{
+- register struct semaphore *sem1 __asm__ ("%a1") = sem;
+- register int result __asm__ ("%d0");
+-
+- might_sleep();
+- __asm__ __volatile__(
+- "| atomic interruptible down operation\n\t"
+- "subql #1,%1@\n\t"
+- "jmi 2f\n\t"
+- "clrl %0\n"
+- "1:\n"
+- LOCK_SECTION_START(".even\n\t")
+- "2:\tpea 1b\n\t"
+- "jbra __down_failed_interruptible\n"
+- LOCK_SECTION_END
+- : "=d" (result)
+- : "a" (sem1)
+- : "memory");
+- return result;
+-}
+-
+-static inline int down_trylock(struct semaphore *sem)
+-{
+- register struct semaphore *sem1 __asm__ ("%a1") = sem;
+- register int result __asm__ ("%d0");
+-
+- __asm__ __volatile__(
+- "| atomic down trylock operation\n\t"
+- "subql #1,%1@\n\t"
+- "jmi 2f\n\t"
+- "clrl %0\n"
+- "1:\n"
+- LOCK_SECTION_START(".even\n\t")
+- "2:\tpea 1b\n\t"
+- "jbra __down_failed_trylock\n"
+- LOCK_SECTION_END
+- : "=d" (result)
+- : "a" (sem1)
+- : "memory");
+- return result;
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- * The default case (no contention) will result in NO
+- * jumps for both down() and up().
+- */
+-static inline void up(struct semaphore *sem)
+-{
+- register struct semaphore *sem1 __asm__ ("%a1") = sem;
+-
+- __asm__ __volatile__(
+- "| atomic up operation\n\t"
+- "addql #1,%0@\n\t"
+- "jle 2f\n"
+- "1:\n"
+- LOCK_SECTION_START(".even\n\t")
+- "2:\t"
+- "pea 1b\n\t"
+- "jbra __up_wakeup\n"
+- LOCK_SECTION_END
+- : /* no outputs */
+- : "a" (sem1)
+- : "memory");
+-}
+-
+-#endif /* __ASSEMBLY__ */
+-
+-#endif
++#include <linux/semaphore.h>
+diff --git a/include/asm-m68knommu/semaphore-helper.h b/include/asm-m68knommu/semaphore-helper.h
+deleted file mode 100644
+index 43da7bc..0000000
+--- a/include/asm-m68knommu/semaphore-helper.h
++++ /dev/null
+@@ -1,82 +0,0 @@
+-#ifndef _M68K_SEMAPHORE_HELPER_H
+-#define _M68K_SEMAPHORE_HELPER_H
+-
+-/*
+- * SMP- and interrupt-safe semaphores helper functions.
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- *
+- * m68k version by Andreas Schwab
+- */
+-
+-
+-/*
+- * These two _must_ execute atomically wrt each other.
+- */
+-static inline void wake_one_more(struct semaphore * sem)
+-{
+- atomic_inc(&sem->waking);
+-}
+-
+-static inline int waking_non_zero(struct semaphore *sem)
+-{
+- int ret;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- ret = 0;
+- if (atomic_read(&sem->waking) > 0) {
+- atomic_dec(&sem->waking);
+- ret = 1;
+- }
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+- return ret;
+-}
+-
+-/*
+- * waking_non_zero_interruptible:
+- * 1 got the lock
+- * 0 go to sleep
+- * -EINTR interrupted
+- */
+-static inline int waking_non_zero_interruptible(struct semaphore *sem,
+- struct task_struct *tsk)
+-{
+- int ret;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- ret = 0;
+- if (atomic_read(&sem->waking) > 0) {
+- atomic_dec(&sem->waking);
+- ret = 1;
+- } else if (signal_pending(tsk)) {
+- atomic_inc(&sem->count);
+- ret = -EINTR;
+- }
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+- return ret;
+-}
+-
+-/*
+- * waking_non_zero_trylock:
+- * 1 failed to lock
+- * 0 got the lock
+- */
+-static inline int waking_non_zero_trylock(struct semaphore *sem)
+-{
+- int ret;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- ret = 1;
+- if (atomic_read(&sem->waking) > 0) {
+- atomic_dec(&sem->waking);
+- ret = 0;
+- } else
+- atomic_inc(&sem->count);
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+- return ret;
+-}
+-
+-#endif
+diff --git a/include/asm-m68knommu/semaphore.h b/include/asm-m68knommu/semaphore.h
+index 5779eb6..d9b2034 100644
+--- a/include/asm-m68knommu/semaphore.h
++++ b/include/asm-m68knommu/semaphore.h
+@@ -1,153 +1 @@
+-#ifndef _M68K_SEMAPHORE_H
+-#define _M68K_SEMAPHORE_H
+-
+-#define RW_LOCK_BIAS 0x01000000
+-
+-#ifndef __ASSEMBLY__
+-
+-#include <linux/linkage.h>
+-#include <linux/wait.h>
+-#include <linux/spinlock.h>
+-#include <linux/rwsem.h>
+-
+-#include <asm/system.h>
+-#include <asm/atomic.h>
+-
+-/*
+- * Interrupt-safe semaphores..
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- *
+- * m68k version by Andreas Schwab
+- */
+-
+-
+-struct semaphore {
+- atomic_t count;
+- atomic_t waking;
+- wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n) \
+-{ \
+- .count = ATOMIC_INIT(n), \
+- .waking = ATOMIC_INIT(0), \
+- .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+- struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+- *sem = (struct semaphore)__SEMAPHORE_INITIALIZER(*sem, val);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+- sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+- sema_init(sem, 0);
+-}
+-
+-asmlinkage void __down_failed(void /* special register calling convention */);
+-asmlinkage int __down_failed_interruptible(void /* params in registers */);
+-asmlinkage int __down_failed_trylock(void /* params in registers */);
+-asmlinkage void __up_wakeup(void /* special register calling convention */);
+-
+-asmlinkage void __down(struct semaphore * sem);
+-asmlinkage int __down_interruptible(struct semaphore * sem);
+-asmlinkage int __down_trylock(struct semaphore * sem);
+-asmlinkage void __up(struct semaphore * sem);
+-
+-extern spinlock_t semaphore_wake_lock;
+-
+-/*
+- * This is ugly, but we want the default case to fall through.
+- * "down_failed" is a special asm handler that calls the C
+- * routine that actually waits. See arch/m68k/lib/semaphore.S
+- */
+-static inline void down(struct semaphore * sem)
+-{
+- might_sleep();
+- __asm__ __volatile__(
+- "| atomic down operation\n\t"
+- "movel %0, %%a1\n\t"
+- "lea %%pc@(1f), %%a0\n\t"
+- "subql #1, %%a1@\n\t"
+- "jmi __down_failed\n"
+- "1:"
+- : /* no outputs */
+- : "g" (sem)
+- : "cc", "%a0", "%a1", "memory");
+-}
+-
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+- int ret;
+-
+- might_sleep();
+- __asm__ __volatile__(
+- "| atomic down operation\n\t"
+- "movel %1, %%a1\n\t"
+- "lea %%pc@(1f), %%a0\n\t"
+- "subql #1, %%a1@\n\t"
+- "jmi __down_failed_interruptible\n\t"
+- "clrl %%d0\n"
+- "1: movel %%d0, %0\n"
+- : "=d" (ret)
+- : "g" (sem)
+- : "cc", "%d0", "%a0", "%a1", "memory");
+- return(ret);
+-}
+-
+-static inline int down_trylock(struct semaphore * sem)
+-{
+- register struct semaphore *sem1 __asm__ ("%a1") = sem;
+- register int result __asm__ ("%d0");
+-
+- __asm__ __volatile__(
+- "| atomic down trylock operation\n\t"
+- "subql #1,%1@\n\t"
+- "jmi 2f\n\t"
+- "clrl %0\n"
+- "1:\n"
+- ".section .text.lock,\"ax\"\n"
+- ".even\n"
+- "2:\tpea 1b\n\t"
+- "jbra __down_failed_trylock\n"
+- ".previous"
+- : "=d" (result)
+- : "a" (sem1)
+- : "memory");
+- return result;
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- * The default case (no contention) will result in NO
+- * jumps for both down() and up().
+- */
+-static inline void up(struct semaphore * sem)
+-{
+- __asm__ __volatile__(
+- "| atomic up operation\n\t"
+- "movel %0, %%a1\n\t"
+- "lea %%pc@(1f), %%a0\n\t"
+- "addql #1, %%a1@\n\t"
+- "jle __up_wakeup\n"
+- "1:"
+- : /* no outputs */
+- : "g" (sem)
+- : "cc", "%a0", "%a1", "memory");
+-}
+-
+-#endif /* __ASSEMBLY__ */
+-
+-#endif
++#include <linux/semaphore.h>
+diff --git a/include/asm-mips/mach-generic/ide.h b/include/asm-mips/mach-generic/ide.h
+index 4ec2b93..0f6c251 100644
+--- a/include/asm-mips/mach-generic/ide.h
++++ b/include/asm-mips/mach-generic/ide.h
+@@ -27,8 +27,6 @@
+ # endif
+ #endif
+
+-#define IDE_ARCH_OBSOLETE_DEFAULTS
+-
+ static __inline__ int ide_probe_legacy(void)
+ {
+ #ifdef CONFIG_PCI
+@@ -98,14 +96,6 @@ static __inline__ unsigned long ide_default_io_base(int index)
+ }
+ }
+
+-#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */
+-
+-#ifdef CONFIG_BLK_DEV_IDEPCI
+-#define ide_init_default_irq(base) (0)
+-#else
+-#define ide_init_default_irq(base) ide_default_irq(base)
+-#endif
+-
+ /* MIPS port and memory-mapped I/O string operations. */
+ static inline void __ide_flush_prologue(void)
+ {
+diff --git a/include/asm-mips/semaphore.h b/include/asm-mips/semaphore.h
+index fdf8042..d9b2034 100644
+--- a/include/asm-mips/semaphore.h
++++ b/include/asm-mips/semaphore.h
+@@ -1,108 +1 @@
+-/*
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License. See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (C) 1996 Linus Torvalds
+- * Copyright (C) 1998, 99, 2000, 01, 04 Ralf Baechle
+- * Copyright (C) 1999, 2000, 01 Silicon Graphics, Inc.
+- * Copyright (C) 2000, 01 MIPS Technologies, Inc.
+- *
+- * In all honesty, little of the old MIPS code left - the PPC64 variant was
+- * just looking nice and portable so I ripped it. Credits to whoever wrote
+- * it.
+- */
+-#ifndef __ASM_SEMAPHORE_H
+-#define __ASM_SEMAPHORE_H
+-
+-/*
+- * Remove spinlock-based RW semaphores; RW semaphore definitions are
+- * now in rwsem.h and we use the generic lib/rwsem.c implementation.
+- * Rework semaphores to use atomic_dec_if_positive.
+- * -- Paul Mackerras (paulus at samba.org)
+- */
+-
+-#ifdef __KERNEL__
+-
+-#include <asm/atomic.h>
+-#include <asm/system.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-struct semaphore {
+- /*
+- * Note that any negative value of count is equivalent to 0,
+- * but additionally indicates that some process(es) might be
+- * sleeping on `wait'.
+- */
+- atomic_t count;
+- wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n) \
+-{ \
+- .count = ATOMIC_INIT(n), \
+- .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name, count) \
+- struct semaphore name = __SEMAPHORE_INITIALIZER(name, count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name, 1)
+-
+-static inline void sema_init(struct semaphore *sem, int val)
+-{
+- atomic_set(&sem->count, val);
+- init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX(struct semaphore *sem)
+-{
+- sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED(struct semaphore *sem)
+-{
+- sema_init(sem, 0);
+-}
+-
+-extern void __down(struct semaphore * sem);
+-extern int __down_interruptible(struct semaphore * sem);
+-extern void __up(struct semaphore * sem);
+-
+-static inline void down(struct semaphore * sem)
+-{
+- might_sleep();
+-
+- /*
+- * Try to get the semaphore, take the slow path if we fail.
+- */
+- if (unlikely(atomic_dec_return(&sem->count) < 0))
+- __down(sem);
+-}
+-
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+- int ret = 0;
+-
+- might_sleep();
+-
+- if (unlikely(atomic_dec_return(&sem->count) < 0))
+- ret = __down_interruptible(sem);
+- return ret;
+-}
+-
+-static inline int down_trylock(struct semaphore * sem)
+-{
+- return atomic_dec_if_positive(&sem->count) < 0;
+-}
+-
+-static inline void up(struct semaphore * sem)
+-{
+- if (unlikely(atomic_inc_return(&sem->count) <= 0))
+- __up(sem);
+-}
+-
+-#endif /* __KERNEL__ */
+-
+-#endif /* __ASM_SEMAPHORE_H */
++#include <linux/semaphore.h>
+diff --git a/include/asm-mn10300/semaphore.h b/include/asm-mn10300/semaphore.h
+index 5a9e1ad..d9b2034 100644
+--- a/include/asm-mn10300/semaphore.h
++++ b/include/asm-mn10300/semaphore.h
+@@ -1,169 +1 @@
+-/* MN10300 Semaphores
+- *
+- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+- * Written by David Howells (dhowells at redhat.com)
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public Licence
+- * as published by the Free Software Foundation; either version
+- * 2 of the Licence, or (at your option) any later version.
+- */
+-#ifndef _ASM_SEMAPHORE_H
+-#define _ASM_SEMAPHORE_H
+-
+-#ifndef __ASSEMBLY__
+-
+-#include <linux/linkage.h>
+-#include <linux/wait.h>
+-#include <linux/spinlock.h>
+-#include <linux/rwsem.h>
+-
+-#define SEMAPHORE_DEBUG 0
+-
+-/*
+- * the semaphore definition
+- * - if count is >0 then there are tokens available on the semaphore for down
+- * to collect
+- * - if count is <=0 then there are no spare tokens, and anyone that wants one
+- * must wait
+- * - if wait_list is not empty, then there are processes waiting for the
+- * semaphore
+- */
+-struct semaphore {
+- atomic_t count; /* it's not really atomic, it's
+- * just that certain modules
+- * expect to be able to access
+- * it directly */
+- spinlock_t wait_lock;
+- struct list_head wait_list;
+-#if SEMAPHORE_DEBUG
+- unsigned __magic;
+-#endif
+-};
+-
+-#if SEMAPHORE_DEBUG
+-# define __SEM_DEBUG_INIT(name) , (long)&(name).__magic
+-#else
+-# define __SEM_DEBUG_INIT(name)
+-#endif
+-
+-
+-#define __SEMAPHORE_INITIALIZER(name, init_count) \
+-{ \
+- .count = ATOMIC_INIT(init_count), \
+- .wait_lock = __SPIN_LOCK_UNLOCKED((name).wait_lock), \
+- .wait_list = LIST_HEAD_INIT((name).wait_list) \
+- __SEM_DEBUG_INIT(name) \
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+- struct semaphore name = __SEMAPHORE_INITIALIZER(name, count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name, 1)
+-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name, 0)
+-
+-static inline void sema_init(struct semaphore *sem, int val)
+-{
+- *sem = (struct semaphore) __SEMAPHORE_INITIALIZER(*sem, val);
+-}
+-
+-static inline void init_MUTEX(struct semaphore *sem)
+-{
+- sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED(struct semaphore *sem)
+-{
+- sema_init(sem, 0);
+-}
+-
+-extern void __down(struct semaphore *sem, unsigned long flags);
+-extern int __down_interruptible(struct semaphore *sem, unsigned long flags);
+-extern void __up(struct semaphore *sem);
+-
+-static inline void down(struct semaphore *sem)
+-{
+- unsigned long flags;
+- int count;
+-
+-#if SEMAPHORE_DEBUG
+- CHECK_MAGIC(sem->__magic);
+-#endif
+-
+- spin_lock_irqsave(&sem->wait_lock, flags);
+- count = atomic_read(&sem->count);
+- if (likely(count > 0)) {
+- atomic_set(&sem->count, count - 1);
+- spin_unlock_irqrestore(&sem->wait_lock, flags);
+- } else {
+- __down(sem, flags);
+- }
+-}
+-
+-static inline int down_interruptible(struct semaphore *sem)
+-{
+- unsigned long flags;
+- int count, ret = 0;
+-
+-#if SEMAPHORE_DEBUG
+- CHECK_MAGIC(sem->__magic);
+-#endif
+-
+- spin_lock_irqsave(&sem->wait_lock, flags);
+- count = atomic_read(&sem->count);
+- if (likely(count > 0)) {
+- atomic_set(&sem->count, count - 1);
+- spin_unlock_irqrestore(&sem->wait_lock, flags);
+- } else {
+- ret = __down_interruptible(sem, flags);
+- }
+- return ret;
+-}
+-
+-/*
+- * non-blockingly attempt to down() a semaphore.
+- * - returns zero if we acquired it
+- */
+-static inline int down_trylock(struct semaphore *sem)
+-{
+- unsigned long flags;
+- int count, success = 0;
+-
+-#if SEMAPHORE_DEBUG
+- CHECK_MAGIC(sem->__magic);
+-#endif
+-
+- spin_lock_irqsave(&sem->wait_lock, flags);
+- count = atomic_read(&sem->count);
+- if (likely(count > 0)) {
+- atomic_set(&sem->count, count - 1);
+- success = 1;
+- }
+- spin_unlock_irqrestore(&sem->wait_lock, flags);
+- return !success;
+-}
+-
+-static inline void up(struct semaphore *sem)
+-{
+- unsigned long flags;
+-
+-#if SEMAPHORE_DEBUG
+- CHECK_MAGIC(sem->__magic);
+-#endif
+-
+- spin_lock_irqsave(&sem->wait_lock, flags);
+- if (!list_empty(&sem->wait_list))
+- __up(sem);
+- else
+- atomic_set(&sem->count, atomic_read(&sem->count) + 1);
+- spin_unlock_irqrestore(&sem->wait_lock, flags);
+-}
+-
+-static inline int sem_getcount(struct semaphore *sem)
+-{
+- return atomic_read(&sem->count);
+-}
+-
+-#endif /* __ASSEMBLY__ */
+-
+-#endif
++#include <linux/semaphore.h>
+diff --git a/include/asm-parisc/ide.h b/include/asm-parisc/ide.h
+index be8760f..db0c944 100644
+--- a/include/asm-parisc/ide.h
++++ b/include/asm-parisc/ide.h
+@@ -17,8 +17,6 @@
+ #define MAX_HWIFS 2
+ #endif
+
+-#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */
+-
+ #define ide_request_irq(irq,hand,flg,dev,id) request_irq((irq),(hand),(flg),(dev),(id))
+ #define ide_free_irq(irq,dev_id) free_irq((irq), (dev_id))
+ #define ide_request_region(from,extent,name) request_region((from), (extent), (name))
+diff --git a/include/asm-parisc/semaphore-helper.h b/include/asm-parisc/semaphore-helper.h
+deleted file mode 100644
+index 387f7c1..0000000
+--- a/include/asm-parisc/semaphore-helper.h
++++ /dev/null
+@@ -1,89 +0,0 @@
+-#ifndef _ASM_PARISC_SEMAPHORE_HELPER_H
+-#define _ASM_PARISC_SEMAPHORE_HELPER_H
+-
+-/*
+- * SMP- and interrupt-safe semaphores helper functions.
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- * (C) Copyright 1999 Andrea Arcangeli
+- */
+-
+-/*
+- * These two _must_ execute atomically wrt each other.
+- *
+- * This is trivially done with load_locked/store_cond,
+- * which we have. Let the rest of the losers suck eggs.
+- */
+-static __inline__ void wake_one_more(struct semaphore * sem)
+-{
+- atomic_inc((atomic_t *)&sem->waking);
+-}
+-
+-static __inline__ int waking_non_zero(struct semaphore *sem)
+-{
+- unsigned long flags;
+- int ret = 0;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- if (sem->waking > 0) {
+- sem->waking--;
+- ret = 1;
+- }
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+- return ret;
+-}
+-
+-/*
+- * waking_non_zero_interruptible:
+- * 1 got the lock
+- * 0 go to sleep
+- * -EINTR interrupted
+- *
+- * We must undo the sem->count down_interruptible() increment while we are
+- * protected by the spinlock in order to make atomic this atomic_inc() with the
+- * atomic_read() in wake_one_more(), otherwise we can race. -arca
+- */
+-static __inline__ int waking_non_zero_interruptible(struct semaphore *sem,
+- struct task_struct *tsk)
+-{
+- unsigned long flags;
+- int ret = 0;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- if (sem->waking > 0) {
+- sem->waking--;
+- ret = 1;
+- } else if (signal_pending(tsk)) {
+- atomic_inc(&sem->count);
+- ret = -EINTR;
+- }
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+- return ret;
+-}
+-
+-/*
+- * waking_non_zero_trylock:
+- * 1 failed to lock
+- * 0 got the lock
+- *
+- * We must undo the sem->count down_trylock() increment while we are
+- * protected by the spinlock in order to make atomic this atomic_inc() with the
+- * atomic_read() in wake_one_more(), otherwise we can race. -arca
+- */
+-static __inline__ int waking_non_zero_trylock(struct semaphore *sem)
+-{
+- unsigned long flags;
+- int ret = 1;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- if (sem->waking <= 0)
+- atomic_inc(&sem->count);
+- else {
+- sem->waking--;
+- ret = 0;
+- }
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+- return ret;
+-}
+-
+-#endif /* _ASM_PARISC_SEMAPHORE_HELPER_H */
+diff --git a/include/asm-parisc/semaphore.h b/include/asm-parisc/semaphore.h
+index a16271c..d9b2034 100644
+--- a/include/asm-parisc/semaphore.h
++++ b/include/asm-parisc/semaphore.h
+@@ -1,145 +1 @@
+-/* SMP- and interrupt-safe semaphores.
+- * PA-RISC version by Matthew Wilcox
+- *
+- * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+- * Copyright (C) 1996 Linus Torvalds
+- * Copyright (C) 1999-2001 Matthew Wilcox < willy at debian d0T org >
+- * Copyright (C) 2000 Grant Grundler < grundler a debian org >
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-
+-#ifndef _ASM_PARISC_SEMAPHORE_H
+-#define _ASM_PARISC_SEMAPHORE_H
+-
+-#include <linux/spinlock.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-#include <asm/system.h>
+-
+-/*
+- * The `count' is initialised to the number of people who are allowed to
+- * take the lock. (Normally we want a mutex, so this is `1'). if
+- * `count' is positive, the lock can be taken. if it's 0, no-one is
+- * waiting on it. if it's -1, at least one task is waiting.
+- */
+-struct semaphore {
+- spinlock_t sentry;
+- int count;
+- wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n) \
+-{ \
+- .sentry = SPIN_LOCK_UNLOCKED, \
+- .count = n, \
+- .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+- struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+- *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+- sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+- sema_init(sem, 0);
+-}
+-
+-static inline int sem_getcount(struct semaphore *sem)
+-{
+- return sem->count;
+-}
+-
+-asmlinkage void __down(struct semaphore * sem);
+-asmlinkage int __down_interruptible(struct semaphore * sem);
+-asmlinkage void __up(struct semaphore * sem);
+-
+-/* Semaphores can be `tried' from irq context. So we have to disable
+- * interrupts while we're messing with the semaphore. Sorry.
+- */
+-
+-static inline void down(struct semaphore * sem)
+-{
+- might_sleep();
+- spin_lock_irq(&sem->sentry);
+- if (sem->count > 0) {
+- sem->count--;
+- } else {
+- __down(sem);
+- }
+- spin_unlock_irq(&sem->sentry);
+-}
+-
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+- int ret = 0;
+- might_sleep();
+- spin_lock_irq(&sem->sentry);
+- if (sem->count > 0) {
+- sem->count--;
+- } else {
+- ret = __down_interruptible(sem);
+- }
+- spin_unlock_irq(&sem->sentry);
+- return ret;
+-}
+-
+-/*
+- * down_trylock returns 0 on success, 1 if we failed to get the lock.
+- * May not sleep, but must preserve irq state
+- */
+-static inline int down_trylock(struct semaphore * sem)
+-{
+- unsigned long flags;
+- int count;
+-
+- spin_lock_irqsave(&sem->sentry, flags);
+- count = sem->count - 1;
+- if (count >= 0)
+- sem->count = count;
+- spin_unlock_irqrestore(&sem->sentry, flags);
+- return (count < 0);
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- */
+-static inline void up(struct semaphore * sem)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&sem->sentry, flags);
+- if (sem->count < 0) {
+- __up(sem);
+- } else {
+- sem->count++;
+- }
+- spin_unlock_irqrestore(&sem->sentry, flags);
+-}
+-
+-#endif /* _ASM_PARISC_SEMAPHORE_H */
++#include <linux/semaphore.h>
+diff --git a/include/asm-powerpc/Kbuild b/include/asm-powerpc/Kbuild
+index 5f640e5..7381916 100644
+--- a/include/asm-powerpc/Kbuild
++++ b/include/asm-powerpc/Kbuild
+@@ -1,5 +1,6 @@
+ include include/asm-generic/Kbuild.asm
+
++header-y += a.out.h
+ header-y += auxvec.h
+ header-y += ioctls.h
+ header-y += mman.h
+@@ -23,7 +24,6 @@ header-y += sigcontext.h
+ header-y += statfs.h
+ header-y += ps3fb.h
+
+-unifdef-y += a.out.h
+ unifdef-y += asm-compat.h
+ unifdef-y += bootx.h
+ unifdef-y += byteorder.h
+diff --git a/include/asm-powerpc/abs_addr.h b/include/asm-powerpc/abs_addr.h
+index 4aa2207..98324c5 100644
+--- a/include/asm-powerpc/abs_addr.h
++++ b/include/asm-powerpc/abs_addr.h
+@@ -12,10 +12,11 @@
+ * 2 of the License, or (at your option) any later version.
+ */
+
++#include <linux/lmb.h>
++
+ #include <asm/types.h>
+ #include <asm/page.h>
+ #include <asm/prom.h>
+-#include <asm/lmb.h>
+ #include <asm/firmware.h>
+
+ struct mschunks_map {
+diff --git a/include/asm-powerpc/bitops.h b/include/asm-powerpc/bitops.h
+index 220d9a7..a99a749 100644
+--- a/include/asm-powerpc/bitops.h
++++ b/include/asm-powerpc/bitops.h
+@@ -312,24 +312,26 @@ static __inline__ int fls(unsigned int x)
+ asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x));
+ return 32 - lz;
+ }
++
++/*
++ * 64-bit can do this using one cntlzd (count leading zeroes doubleword)
++ * instruction; for 32-bit we use the generic version, which does two
++ * 32-bit fls calls.
++ */
++#ifdef __powerpc64__
++static __inline__ int fls64(__u64 x)
++{
++ int lz;
++
++ asm ("cntlzd %0,%1" : "=r" (lz) : "r" (x));
++ return 64 - lz;
++}
++#else
+ #include <asm-generic/bitops/fls64.h>
++#endif /* __powerpc64__ */
+
+ #include <asm-generic/bitops/hweight.h>
+-
+-#define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0)
+-unsigned long find_next_zero_bit(const unsigned long *addr,
+- unsigned long size, unsigned long offset);
+-/**
+- * find_first_bit - find the first set bit in a memory region
+- * @addr: The address to start the search at
+- * @size: The maximum size to search
+- *
+- * Returns the bit-number of the first set bit, not the number of the byte
+- * containing a bit.
+- */
+-#define find_first_bit(addr, size) find_next_bit((addr), (size), 0)
+-unsigned long find_next_bit(const unsigned long *addr,
+- unsigned long size, unsigned long offset);
++#include <asm-generic/bitops/find.h>
+
+ /* Little-endian versions */
+
+diff --git a/include/asm-powerpc/cpm.h b/include/asm-powerpc/cpm.h
+index 77e39da..ede38ff 100644
+--- a/include/asm-powerpc/cpm.h
++++ b/include/asm-powerpc/cpm.h
+@@ -4,6 +4,20 @@
+ #include <linux/compiler.h>
+ #include <linux/types.h>
+
++/* Opcodes common to CPM1 and CPM2
++*/
++#define CPM_CR_INIT_TRX ((ushort)0x0000)
++#define CPM_CR_INIT_RX ((ushort)0x0001)
++#define CPM_CR_INIT_TX ((ushort)0x0002)
++#define CPM_CR_HUNT_MODE ((ushort)0x0003)
++#define CPM_CR_STOP_TX ((ushort)0x0004)
++#define CPM_CR_GRA_STOP_TX ((ushort)0x0005)
++#define CPM_CR_RESTART_TX ((ushort)0x0006)
++#define CPM_CR_CLOSE_RX_BD ((ushort)0x0007)
++#define CPM_CR_SET_GADDR ((ushort)0x0008)
++#define CPM_CR_SET_TIMER ((ushort)0x0008)
++#define CPM_CR_STOP_IDMA ((ushort)0x000b)
++
+ /* Buffer descriptors used by many of the CPM protocols. */
+ typedef struct cpm_buf_desc {
+ ushort cbd_sc; /* Status and Control */
+diff --git a/include/asm-powerpc/cpm1.h b/include/asm-powerpc/cpm1.h
+index b2ebd6a..3df4396 100644
+--- a/include/asm-powerpc/cpm1.h
++++ b/include/asm-powerpc/cpm1.h
+@@ -28,19 +28,6 @@
+ #define CPM_CR_CHAN ((ushort)0x00f0)
+ #define CPM_CR_FLG ((ushort)0x0001)
+
+-/* Some commands (there are more...later)
+-*/
+-#define CPM_CR_INIT_TRX ((ushort)0x0000)
+-#define CPM_CR_INIT_RX ((ushort)0x0001)
+-#define CPM_CR_INIT_TX ((ushort)0x0002)
+-#define CPM_CR_HUNT_MODE ((ushort)0x0003)
+-#define CPM_CR_STOP_TX ((ushort)0x0004)
+-#define CPM_CR_GRA_STOP_TX ((ushort)0x0005)
+-#define CPM_CR_RESTART_TX ((ushort)0x0006)
+-#define CPM_CR_CLOSE_RX_BD ((ushort)0x0007)
+-#define CPM_CR_SET_GADDR ((ushort)0x0008)
+-#define CPM_CR_SET_TIMER CPM_CR_SET_GADDR
+-
+ /* Channel numbers.
+ */
+ #define CPM_CR_CH_SCC1 ((ushort)0x0000)
+diff --git a/include/asm-powerpc/cpm2.h b/include/asm-powerpc/cpm2.h
+index b93a53e..4c85ed9 100644
+--- a/include/asm-powerpc/cpm2.h
++++ b/include/asm-powerpc/cpm2.h
+@@ -71,18 +71,9 @@
+
+ #define CPM_CR_FCC_PAGE(x) (x + 0x04)
+
+-/* Some opcodes (there are more...later)
++/* CPM2-specific opcodes (see cpm.h for common opcodes)
+ */
+-#define CPM_CR_INIT_TRX ((ushort)0x0000)
+-#define CPM_CR_INIT_RX ((ushort)0x0001)
+-#define CPM_CR_INIT_TX ((ushort)0x0002)
+-#define CPM_CR_HUNT_MODE ((ushort)0x0003)
+-#define CPM_CR_STOP_TX ((ushort)0x0004)
+-#define CPM_CR_GRA_STOP_TX ((ushort)0x0005)
+-#define CPM_CR_RESTART_TX ((ushort)0x0006)
+-#define CPM_CR_SET_GADDR ((ushort)0x0008)
+ #define CPM_CR_START_IDMA ((ushort)0x0009)
+-#define CPM_CR_STOP_IDMA ((ushort)0x000b)
+
+ #define mk_cr_cmd(PG, SBC, MCN, OP) \
+ ((PG << 26) | (SBC << 21) | (MCN << 6) | OP)
+diff --git a/include/asm-powerpc/cputhreads.h b/include/asm-powerpc/cputhreads.h
+index 8485c28..fb11b0c 100644
+--- a/include/asm-powerpc/cputhreads.h
++++ b/include/asm-powerpc/cputhreads.h
+@@ -35,7 +35,7 @@ static inline cpumask_t cpu_thread_mask_to_cores(cpumask_t threads)
+
+ res = CPU_MASK_NONE;
+ for (i = 0; i < NR_CPUS; i += threads_per_core) {
+- cpus_shift_right(tmp, threads_core_mask, i);
++ cpus_shift_left(tmp, threads_core_mask, i);
+ if (cpus_intersects(threads, tmp))
+ cpu_set(i, res);
+ }
+diff --git a/include/asm-powerpc/dcr-native.h b/include/asm-powerpc/dcr-native.h
+index be6c879..f8398ce 100644
+--- a/include/asm-powerpc/dcr-native.h
++++ b/include/asm-powerpc/dcr-native.h
+@@ -82,6 +82,19 @@ static inline void __mtdcri(int base_addr, int base_data, int reg,
+ spin_unlock_irqrestore(&dcr_ind_lock, flags);
+ }
+
++static inline void __dcri_clrset(int base_addr, int base_data, int reg,
++ unsigned clr, unsigned set)
++{
++ unsigned long flags;
++ unsigned int val;
++
++ spin_lock_irqsave(&dcr_ind_lock, flags);
++ __mtdcr(base_addr, reg);
++ val = (__mfdcr(base_data) & ~clr) | set;
++ __mtdcr(base_data, val);
++ spin_unlock_irqrestore(&dcr_ind_lock, flags);
++}
++
+ #define mfdcri(base, reg) __mfdcri(DCRN_ ## base ## _CONFIG_ADDR, \
+ DCRN_ ## base ## _CONFIG_DATA, \
+ reg)
+@@ -90,6 +103,10 @@ static inline void __mtdcri(int base_addr, int base_data, int reg,
+ DCRN_ ## base ## _CONFIG_DATA, \
+ reg, data)
+
++#define dcri_clrset(base, reg, clr, set) __dcri_clrset(DCRN_ ## base ## _CONFIG_ADDR, \
++ DCRN_ ## base ## _CONFIG_DATA, \
++ reg, clr, set)
++
+ #endif /* __ASSEMBLY__ */
+ #endif /* __KERNEL__ */
+ #endif /* _ASM_POWERPC_DCR_NATIVE_H */
+diff --git a/include/asm-powerpc/dcr-regs.h b/include/asm-powerpc/dcr-regs.h
+index 9f1fb98..29b0ece 100644
+--- a/include/asm-powerpc/dcr-regs.h
++++ b/include/asm-powerpc/dcr-regs.h
+@@ -68,4 +68,82 @@
+ #define SDR0_UART3 0x0123
+ #define SDR0_CUST0 0x4000
+
++/*
++ * All those DCR register addresses are offsets from the base address
++ * for the SRAM0 controller (e.g. 0x20 on 440GX). The base address is
++ * excluded here and configured in the device tree.
++ */
++#define DCRN_SRAM0_SB0CR 0x00
++#define DCRN_SRAM0_SB1CR 0x01
++#define DCRN_SRAM0_SB2CR 0x02
++#define DCRN_SRAM0_SB3CR 0x03
++#define SRAM_SBCR_BU_MASK 0x00000180
++#define SRAM_SBCR_BS_64KB 0x00000800
++#define SRAM_SBCR_BU_RO 0x00000080
++#define SRAM_SBCR_BU_RW 0x00000180
++#define DCRN_SRAM0_BEAR 0x04
++#define DCRN_SRAM0_BESR0 0x05
++#define DCRN_SRAM0_BESR1 0x06
++#define DCRN_SRAM0_PMEG 0x07
++#define DCRN_SRAM0_CID 0x08
++#define DCRN_SRAM0_REVID 0x09
++#define DCRN_SRAM0_DPC 0x0a
++#define SRAM_DPC_ENABLE 0x80000000
++
++/*
++ * All those DCR register addresses are offsets from the base address
++ * for the SRAM0 controller (e.g. 0x30 on 440GX). The base address is
++ * excluded here and configured in the device tree.
++ */
++#define DCRN_L2C0_CFG 0x00
++#define L2C_CFG_L2M 0x80000000
++#define L2C_CFG_ICU 0x40000000
++#define L2C_CFG_DCU 0x20000000
++#define L2C_CFG_DCW_MASK 0x1e000000
++#define L2C_CFG_TPC 0x01000000
++#define L2C_CFG_CPC 0x00800000
++#define L2C_CFG_FRAN 0x00200000
++#define L2C_CFG_SS_MASK 0x00180000
++#define L2C_CFG_SS_256 0x00000000
++#define L2C_CFG_CPIM 0x00040000
++#define L2C_CFG_TPIM 0x00020000
++#define L2C_CFG_LIM 0x00010000
++#define L2C_CFG_PMUX_MASK 0x00007000
++#define L2C_CFG_PMUX_SNP 0x00000000
++#define L2C_CFG_PMUX_IF 0x00001000
++#define L2C_CFG_PMUX_DF 0x00002000
++#define L2C_CFG_PMUX_DS 0x00003000
++#define L2C_CFG_PMIM 0x00000800
++#define L2C_CFG_TPEI 0x00000400
++#define L2C_CFG_CPEI 0x00000200
++#define L2C_CFG_NAM 0x00000100
++#define L2C_CFG_SMCM 0x00000080
++#define L2C_CFG_NBRM 0x00000040
++#define L2C_CFG_RDBW 0x00000008 /* only 460EX/GT */
++#define DCRN_L2C0_CMD 0x01
++#define L2C_CMD_CLR 0x80000000
++#define L2C_CMD_DIAG 0x40000000
++#define L2C_CMD_INV 0x20000000
++#define L2C_CMD_CCP 0x10000000
++#define L2C_CMD_CTE 0x08000000
++#define L2C_CMD_STRC 0x04000000
++#define L2C_CMD_STPC 0x02000000
++#define L2C_CMD_RPMC 0x01000000
++#define L2C_CMD_HCC 0x00800000
++#define DCRN_L2C0_ADDR 0x02
++#define DCRN_L2C0_DATA 0x03
++#define DCRN_L2C0_SR 0x04
++#define L2C_SR_CC 0x80000000
++#define L2C_SR_CPE 0x40000000
++#define L2C_SR_TPE 0x20000000
++#define L2C_SR_LRU 0x10000000
++#define L2C_SR_PCS 0x08000000
++#define DCRN_L2C0_REVID 0x05
++#define DCRN_L2C0_SNP0 0x06
++#define DCRN_L2C0_SNP1 0x07
++#define L2C_SNP_BA_MASK 0xffff0000
++#define L2C_SNP_SSR_MASK 0x0000f000
++#define L2C_SNP_SSR_32G 0x0000f000
++#define L2C_SNP_ESR 0x00000800
++
+ #endif /* __DCR_REGS_H__ */
+diff --git a/include/asm-powerpc/exception.h b/include/asm-powerpc/exception.h
+index 39abdb0..329148b 100644
+--- a/include/asm-powerpc/exception.h
++++ b/include/asm-powerpc/exception.h
+@@ -228,18 +228,18 @@ label##_pSeries: \
+ BEGIN_FW_FTR_SECTION; \
+ stb r11,PACAHARDIRQEN(r13); \
+ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \
++ TRACE_DISABLE_INTS; \
+ BEGIN_FW_FTR_SECTION; \
+ mfmsr r10; \
+ ori r10,r10,MSR_EE; \
+ mtmsrd r10,1; \
+ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
+-
+ #else
+ #define DISABLE_INTS \
+ li r11,0; \
+ stb r11,PACASOFTIRQEN(r13); \
+- stb r11,PACAHARDIRQEN(r13)
+-
++ stb r11,PACAHARDIRQEN(r13); \
++ TRACE_DISABLE_INTS
+ #endif /* CONFIG_PPC_ISERIES */
+
+ #define ENABLE_INTS \
+diff --git a/include/asm-powerpc/fixmap.h b/include/asm-powerpc/fixmap.h
+new file mode 100644
+index 0000000..8428b38
+--- /dev/null
++++ b/include/asm-powerpc/fixmap.h
+@@ -0,0 +1,106 @@
++/*
++ * fixmap.h: compile-time virtual memory allocation
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 1998 Ingo Molnar
++ *
++ * Copyright 2008 Freescale Semiconductor Inc.
++ * Port to powerpc added by Kumar Gala
++ */
++
++#ifndef _ASM_FIXMAP_H
++#define _ASM_FIXMAP_H
++
++extern unsigned long FIXADDR_TOP;
++
++#ifndef __ASSEMBLY__
++#include <linux/kernel.h>
++#include <asm/page.h>
++#ifdef CONFIG_HIGHMEM
++#include <linux/threads.h>
++#include <asm/kmap_types.h>
++#endif
++
++/*
++ * Here we define all the compile-time 'special' virtual
++ * addresses. The point is to have a constant address at
++ * compile time, but to set the physical address only
++ * in the boot process. We allocate these special addresses
++ * from the end of virtual memory (0xfffff000) backwards.
++ * Also this lets us do fail-safe vmalloc(), we
++ * can guarantee that these special addresses and
++ * vmalloc()-ed addresses never overlap.
++ *
++ * these 'compile-time allocated' memory buffers are
++ * fixed-size 4k pages. (or larger if used with an increment
++ * highger than 1) use fixmap_set(idx,phys) to associate
++ * physical memory with fixmap indices.
++ *
++ * TLB entries of such buffers will not be flushed across
++ * task switches.
++ */
++enum fixed_addresses {
++ FIX_HOLE,
++#ifdef CONFIG_HIGHMEM
++ FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
++ FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
++#endif
++ /* FIX_PCIE_MCFG, */
++ __end_of_fixed_addresses
++};
++
++extern void __set_fixmap (enum fixed_addresses idx,
++ phys_addr_t phys, pgprot_t flags);
++
++#define set_fixmap(idx, phys) \
++ __set_fixmap(idx, phys, PAGE_KERNEL)
++/*
++ * Some hardware wants to get fixmapped without caching.
++ */
++#define set_fixmap_nocache(idx, phys) \
++ __set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
++
++#define clear_fixmap(idx) \
++ __set_fixmap(idx, 0, __pgprot(0))
++
++#define __FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
++#define FIXADDR_START (FIXADDR_TOP - __FIXADDR_SIZE)
++
++#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
++#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
++
++extern void __this_fixmap_does_not_exist(void);
++
++/*
++ * 'index to address' translation. If anyone tries to use the idx
++ * directly without tranlation, we catch the bug with a NULL-deference
++ * kernel oops. Illegal ranges of incoming indices are caught too.
++ */
++static __always_inline unsigned long fix_to_virt(const unsigned int idx)
++{
++ /*
++ * this branch gets completely eliminated after inlining,
++ * except when someone tries to use fixaddr indices in an
++ * illegal way. (such as mixing up address types or using
++ * out-of-range indices).
++ *
++ * If it doesn't get removed, the linker will complain
++ * loudly with a reasonably clear error message..
++ */
++ if (idx >= __end_of_fixed_addresses)
++ __this_fixmap_does_not_exist();
++
++ return __fix_to_virt(idx);
++}
++
++static inline unsigned long virt_to_fix(const unsigned long vaddr)
++{
++ BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
++ return __virt_to_fix(vaddr);
++}
++
++#endif /* !__ASSEMBLY__ */
++#endif
+diff --git a/include/asm-powerpc/fsl_lbc.h b/include/asm-powerpc/fsl_lbc.h
+new file mode 100644
+index 0000000..303f548
+--- /dev/null
++++ b/include/asm-powerpc/fsl_lbc.h
+@@ -0,0 +1,311 @@
++/* Freescale Local Bus Controller
++ *
++ * Copyright (c) 2006-2007 Freescale Semiconductor
++ *
++ * Authors: Nick Spence <nick.spence at freescale.com>,
++ * Scott Wood <scottwood at freescale.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef __ASM_FSL_LBC_H
++#define __ASM_FSL_LBC_H
++
++#include <linux/types.h>
++#include <linux/spinlock.h>
++#include <asm/io.h>
++
++struct fsl_lbc_bank {
++ __be32 br; /**< Base Register */
++#define BR_BA 0xFFFF8000
++#define BR_BA_SHIFT 15
++#define BR_PS 0x00001800
++#define BR_PS_SHIFT 11
++#define BR_PS_8 0x00000800 /* Port Size 8 bit */
++#define BR_PS_16 0x00001000 /* Port Size 16 bit */
++#define BR_PS_32 0x00001800 /* Port Size 32 bit */
++#define BR_DECC 0x00000600
++#define BR_DECC_SHIFT 9
++#define BR_DECC_OFF 0x00000000 /* HW ECC checking and generation off */
++#define BR_DECC_CHK 0x00000200 /* HW ECC checking on, generation off */
++#define BR_DECC_CHK_GEN 0x00000400 /* HW ECC checking and generation on */
++#define BR_WP 0x00000100
++#define BR_WP_SHIFT 8
++#define BR_MSEL 0x000000E0
++#define BR_MSEL_SHIFT 5
++#define BR_MS_GPCM 0x00000000 /* GPCM */
++#define BR_MS_FCM 0x00000020 /* FCM */
++#define BR_MS_SDRAM 0x00000060 /* SDRAM */
++#define BR_MS_UPMA 0x00000080 /* UPMA */
++#define BR_MS_UPMB 0x000000A0 /* UPMB */
++#define BR_MS_UPMC 0x000000C0 /* UPMC */
++#define BR_V 0x00000001
++#define BR_V_SHIFT 0
++#define BR_RES ~(BR_BA|BR_PS|BR_DECC|BR_WP|BR_MSEL|BR_V)
++
++ __be32 or; /**< Base Register */
++#define OR0 0x5004
++#define OR1 0x500C
++#define OR2 0x5014
++#define OR3 0x501C
++#define OR4 0x5024
++#define OR5 0x502C
++#define OR6 0x5034
++#define OR7 0x503C
++
++#define OR_FCM_AM 0xFFFF8000
++#define OR_FCM_AM_SHIFT 15
++#define OR_FCM_BCTLD 0x00001000
++#define OR_FCM_BCTLD_SHIFT 12
++#define OR_FCM_PGS 0x00000400
++#define OR_FCM_PGS_SHIFT 10
++#define OR_FCM_CSCT 0x00000200
++#define OR_FCM_CSCT_SHIFT 9
++#define OR_FCM_CST 0x00000100
++#define OR_FCM_CST_SHIFT 8
++#define OR_FCM_CHT 0x00000080
++#define OR_FCM_CHT_SHIFT 7
++#define OR_FCM_SCY 0x00000070
++#define OR_FCM_SCY_SHIFT 4
++#define OR_FCM_SCY_1 0x00000010
++#define OR_FCM_SCY_2 0x00000020
++#define OR_FCM_SCY_3 0x00000030
++#define OR_FCM_SCY_4 0x00000040
++#define OR_FCM_SCY_5 0x00000050
++#define OR_FCM_SCY_6 0x00000060
++#define OR_FCM_SCY_7 0x00000070
++#define OR_FCM_RST 0x00000008
++#define OR_FCM_RST_SHIFT 3
++#define OR_FCM_TRLX 0x00000004
++#define OR_FCM_TRLX_SHIFT 2
++#define OR_FCM_EHTR 0x00000002
++#define OR_FCM_EHTR_SHIFT 1
++};
++
++struct fsl_lbc_regs {
++ struct fsl_lbc_bank bank[8];
++ u8 res0[0x28];
++ __be32 mar; /**< UPM Address Register */
++ u8 res1[0x4];
++ __be32 mamr; /**< UPMA Mode Register */
++#define MxMR_OP_NO (0 << 28) /**< normal operation */
++#define MxMR_OP_WA (1 << 28) /**< write array */
++#define MxMR_OP_RA (2 << 28) /**< read array */
++#define MxMR_OP_RP (3 << 28) /**< run pattern */
++#define MxMR_MAD 0x3f /**< machine address */
++ __be32 mbmr; /**< UPMB Mode Register */
++ __be32 mcmr; /**< UPMC Mode Register */
++ u8 res2[0x8];
++ __be32 mrtpr; /**< Memory Refresh Timer Prescaler Register */
++ __be32 mdr; /**< UPM Data Register */
++ u8 res3[0x4];
++ __be32 lsor; /**< Special Operation Initiation Register */
++ __be32 lsdmr; /**< SDRAM Mode Register */
++ u8 res4[0x8];
++ __be32 lurt; /**< UPM Refresh Timer */
++ __be32 lsrt; /**< SDRAM Refresh Timer */
++ u8 res5[0x8];
++ __be32 ltesr; /**< Transfer Error Status Register */
++#define LTESR_BM 0x80000000
++#define LTESR_FCT 0x40000000
++#define LTESR_PAR 0x20000000
++#define LTESR_WP 0x04000000
++#define LTESR_ATMW 0x00800000
++#define LTESR_ATMR 0x00400000
++#define LTESR_CS 0x00080000
++#define LTESR_CC 0x00000001
++#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
++ __be32 ltedr; /**< Transfer Error Disable Register */
++ __be32 lteir; /**< Transfer Error Interrupt Register */
++ __be32 lteatr; /**< Transfer Error Attributes Register */
++ __be32 ltear; /**< Transfer Error Address Register */
++ u8 res6[0xC];
++ __be32 lbcr; /**< Configuration Register */
++#define LBCR_LDIS 0x80000000
++#define LBCR_LDIS_SHIFT 31
++#define LBCR_BCTLC 0x00C00000
++#define LBCR_BCTLC_SHIFT 22
++#define LBCR_AHD 0x00200000
++#define LBCR_LPBSE 0x00020000
++#define LBCR_LPBSE_SHIFT 17
++#define LBCR_EPAR 0x00010000
++#define LBCR_EPAR_SHIFT 16
++#define LBCR_BMT 0x0000FF00
++#define LBCR_BMT_SHIFT 8
++#define LBCR_INIT 0x00040000
++ __be32 lcrr; /**< Clock Ratio Register */
++#define LCRR_DBYP 0x80000000
++#define LCRR_DBYP_SHIFT 31
++#define LCRR_BUFCMDC 0x30000000
++#define LCRR_BUFCMDC_SHIFT 28
++#define LCRR_ECL 0x03000000
++#define LCRR_ECL_SHIFT 24
++#define LCRR_EADC 0x00030000
++#define LCRR_EADC_SHIFT 16
++#define LCRR_CLKDIV 0x0000000F
++#define LCRR_CLKDIV_SHIFT 0
++ u8 res7[0x8];
++ __be32 fmr; /**< Flash Mode Register */
++#define FMR_CWTO 0x0000F000
++#define FMR_CWTO_SHIFT 12
++#define FMR_BOOT 0x00000800
++#define FMR_ECCM 0x00000100
++#define FMR_AL 0x00000030
++#define FMR_AL_SHIFT 4
++#define FMR_OP 0x00000003
++#define FMR_OP_SHIFT 0
++ __be32 fir; /**< Flash Instruction Register */
++#define FIR_OP0 0xF0000000
++#define FIR_OP0_SHIFT 28
++#define FIR_OP1 0x0F000000
++#define FIR_OP1_SHIFT 24
++#define FIR_OP2 0x00F00000
++#define FIR_OP2_SHIFT 20
++#define FIR_OP3 0x000F0000
++#define FIR_OP3_SHIFT 16
++#define FIR_OP4 0x0000F000
++#define FIR_OP4_SHIFT 12
++#define FIR_OP5 0x00000F00
++#define FIR_OP5_SHIFT 8
++#define FIR_OP6 0x000000F0
++#define FIR_OP6_SHIFT 4
++#define FIR_OP7 0x0000000F
++#define FIR_OP7_SHIFT 0
++#define FIR_OP_NOP 0x0 /* No operation and end of sequence */
++#define FIR_OP_CA 0x1 /* Issue current column address */
++#define FIR_OP_PA 0x2 /* Issue current block+page address */
++#define FIR_OP_UA 0x3 /* Issue user defined address */
++#define FIR_OP_CM0 0x4 /* Issue command from FCR[CMD0] */
++#define FIR_OP_CM1 0x5 /* Issue command from FCR[CMD1] */
++#define FIR_OP_CM2 0x6 /* Issue command from FCR[CMD2] */
++#define FIR_OP_CM3 0x7 /* Issue command from FCR[CMD3] */
++#define FIR_OP_WB 0x8 /* Write FBCR bytes from FCM buffer */
++#define FIR_OP_WS 0x9 /* Write 1 or 2 bytes from MDR[AS] */
++#define FIR_OP_RB 0xA /* Read FBCR bytes to FCM buffer */
++#define FIR_OP_RS 0xB /* Read 1 or 2 bytes to MDR[AS] */
++#define FIR_OP_CW0 0xC /* Wait then issue FCR[CMD0] */
++#define FIR_OP_CW1 0xD /* Wait then issue FCR[CMD1] */
++#define FIR_OP_RBW 0xE /* Wait then read FBCR bytes */
++#define FIR_OP_RSW 0xE /* Wait then read 1 or 2 bytes */
++ __be32 fcr; /**< Flash Command Register */
++#define FCR_CMD0 0xFF000000
++#define FCR_CMD0_SHIFT 24
++#define FCR_CMD1 0x00FF0000
++#define FCR_CMD1_SHIFT 16
++#define FCR_CMD2 0x0000FF00
++#define FCR_CMD2_SHIFT 8
++#define FCR_CMD3 0x000000FF
++#define FCR_CMD3_SHIFT 0
++ __be32 fbar; /**< Flash Block Address Register */
++#define FBAR_BLK 0x00FFFFFF
++ __be32 fpar; /**< Flash Page Address Register */
++#define FPAR_SP_PI 0x00007C00
++#define FPAR_SP_PI_SHIFT 10
++#define FPAR_SP_MS 0x00000200
++#define FPAR_SP_CI 0x000001FF
++#define FPAR_SP_CI_SHIFT 0
++#define FPAR_LP_PI 0x0003F000
++#define FPAR_LP_PI_SHIFT 12
++#define FPAR_LP_MS 0x00000800
++#define FPAR_LP_CI 0x000007FF
++#define FPAR_LP_CI_SHIFT 0
++ __be32 fbcr; /**< Flash Byte Count Register */
++#define FBCR_BC 0x00000FFF
++ u8 res11[0x8];
++ u8 res8[0xF00];
++};
++
++extern struct fsl_lbc_regs __iomem *fsl_lbc_regs;
++extern spinlock_t fsl_lbc_lock;
++
++/*
++ * FSL UPM routines
++ */
++struct fsl_upm {
++ __be32 __iomem *mxmr;
++ int width;
++};
++
++extern int fsl_lbc_find(phys_addr_t addr_base);
++extern int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm);
++
++/**
++ * fsl_upm_start_pattern - start UPM patterns execution
++ * @upm: pointer to the fsl_upm structure obtained via fsl_upm_find
++ * @pat_offset: UPM pattern offset for the command to be executed
++ *
++ * This routine programmes UPM so the next memory access that hits an UPM
++ * will trigger pattern execution, starting at pat_offset.
++ */
++static inline void fsl_upm_start_pattern(struct fsl_upm *upm, u8 pat_offset)
++{
++ clrsetbits_be32(upm->mxmr, MxMR_MAD, MxMR_OP_RP | pat_offset);
++}
++
++/**
++ * fsl_upm_end_pattern - end UPM patterns execution
++ * @upm: pointer to the fsl_upm structure obtained via fsl_upm_find
++ *
++ * This routine reverts UPM to normal operation mode.
++ */
++static inline void fsl_upm_end_pattern(struct fsl_upm *upm)
++{
++ clrbits32(upm->mxmr, MxMR_OP_RP);
++
++ while (in_be32(upm->mxmr) & MxMR_OP_RP)
++ cpu_relax();
++}
++
++/**
++ * fsl_upm_run_pattern - actually run an UPM pattern
++ * @upm: pointer to the fsl_upm structure obtained via fsl_upm_find
++ * @io_base: remapped pointer to where memory access should happen
++ * @mar: MAR register content during pattern execution
++ *
++ * This function triggers dummy write to the memory specified by the io_base,
++ * thus UPM pattern actually executed. Note that mar usage depends on the
++ * pre-programmed AMX bits in the UPM RAM.
++ */
++static inline int fsl_upm_run_pattern(struct fsl_upm *upm,
++ void __iomem *io_base, u32 mar)
++{
++ int ret = 0;
++ unsigned long flags;
++
++ spin_lock_irqsave(&fsl_lbc_lock, flags);
++
++ out_be32(&fsl_lbc_regs->mar, mar << (32 - upm->width));
++
++ switch (upm->width) {
++ case 8:
++ out_8(io_base, 0x0);
++ break;
++ case 16:
++ out_be16(io_base, 0x0);
++ break;
++ case 32:
++ out_be32(io_base, 0x0);
++ break;
++ default:
++ ret = -EINVAL;
++ break;
++ }
++
++ spin_unlock_irqrestore(&fsl_lbc_lock, flags);
++
++ return ret;
++}
++
++#endif /* __ASM_FSL_LBC_H */
+diff --git a/include/asm-powerpc/gpio.h b/include/asm-powerpc/gpio.h
+new file mode 100644
+index 0000000..77ad3a8
+--- /dev/null
++++ b/include/asm-powerpc/gpio.h
+@@ -0,0 +1,56 @@
++/*
++ * Generic GPIO API implementation for PowerPC.
++ *
++ * Copyright (c) 2007-2008 MontaVista Software, Inc.
++ *
++ * Author: Anton Vorontsov <avorontsov at ru.mvista.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.
++ */
++
++#ifndef __ASM_POWERPC_GPIO_H
++#define __ASM_POWERPC_GPIO_H
++
++#include <linux/errno.h>
++#include <asm-generic/gpio.h>
++
++#ifdef CONFIG_HAVE_GPIO_LIB
++
++/*
++ * We don't (yet) implement inlined/rapid versions for on-chip gpios.
++ * Just call gpiolib.
++ */
++static inline int gpio_get_value(unsigned int gpio)
++{
++ return __gpio_get_value(gpio);
++}
++
++static inline void gpio_set_value(unsigned int gpio, int value)
++{
++ __gpio_set_value(gpio, value);
++}
++
++static inline int gpio_cansleep(unsigned int gpio)
++{
++ return __gpio_cansleep(gpio);
++}
++
++/*
++ * Not implemented, yet.
++ */
++static inline int gpio_to_irq(unsigned int gpio)
++{
++ return -ENOSYS;
++}
++
++static inline int irq_to_gpio(unsigned int irq)
++{
++ return -EINVAL;
++}
++
++#endif /* CONFIG_HAVE_GPIO_LIB */
++
++#endif /* __ASM_POWERPC_GPIO_H */
+diff --git a/include/asm-powerpc/highmem.h b/include/asm-powerpc/highmem.h
+index f7b21ee..5d99b64 100644
+--- a/include/asm-powerpc/highmem.h
++++ b/include/asm-powerpc/highmem.h
+@@ -27,9 +27,7 @@
+ #include <asm/kmap_types.h>
+ #include <asm/tlbflush.h>
+ #include <asm/page.h>
+-
+-/* undef for production */
+-#define HIGHMEM_DEBUG 1
++#include <asm/fixmap.h>
+
+ extern pte_t *kmap_pte;
+ extern pgprot_t kmap_prot;
+@@ -40,14 +38,12 @@ extern pte_t *pkmap_page_table;
+ * easily, subsequent pte tables have to be allocated in one physical
+ * chunk of RAM.
+ */
+-#define PKMAP_BASE CONFIG_HIGHMEM_START
+ #define LAST_PKMAP (1 << PTE_SHIFT)
+ #define LAST_PKMAP_MASK (LAST_PKMAP-1)
++#define PKMAP_BASE ((FIXADDR_START - PAGE_SIZE*(LAST_PKMAP + 1)) & PMD_MASK)
+ #define PKMAP_NR(virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT)
+ #define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
+
+-#define KMAP_FIX_BEGIN (PKMAP_BASE + 0x00400000UL)
+-
+ extern void *kmap_high(struct page *page);
+ extern void kunmap_high(struct page *page);
+
+@@ -73,7 +69,7 @@ static inline void kunmap(struct page *page)
+ * be used in IRQ contexts, so in some (very limited) cases we need
+ * it.
+ */
+-static inline void *kmap_atomic(struct page *page, enum km_type type)
++static inline void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
+ {
+ unsigned int idx;
+ unsigned long vaddr;
+@@ -84,34 +80,39 @@ static inline void *kmap_atomic(struct page *page, enum km_type type)
+ return page_address(page);
+
+ idx = type + KM_TYPE_NR*smp_processor_id();
+- vaddr = KMAP_FIX_BEGIN + idx * PAGE_SIZE;
+-#ifdef HIGHMEM_DEBUG
+- BUG_ON(!pte_none(*(kmap_pte+idx)));
++ vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
++#ifdef CONFIG_DEBUG_HIGHMEM
++ BUG_ON(!pte_none(*(kmap_pte-idx)));
+ #endif
+- set_pte_at(&init_mm, vaddr, kmap_pte+idx, mk_pte(page, kmap_prot));
++ set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot));
+ flush_tlb_page(NULL, vaddr);
+
+ return (void*) vaddr;
+ }
+
++static inline void *kmap_atomic(struct page *page, enum km_type type)
++{
++ return kmap_atomic_prot(page, type, kmap_prot);
++}
++
+ static inline void kunmap_atomic(void *kvaddr, enum km_type type)
+ {
+-#ifdef HIGHMEM_DEBUG
++#ifdef CONFIG_DEBUG_HIGHMEM
+ unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
+- unsigned int idx = type + KM_TYPE_NR*smp_processor_id();
++ enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
+
+- if (vaddr < KMAP_FIX_BEGIN) { // FIXME
++ if (vaddr < __fix_to_virt(FIX_KMAP_END)) {
+ pagefault_enable();
+ return;
+ }
+
+- BUG_ON(vaddr != KMAP_FIX_BEGIN + idx * PAGE_SIZE);
++ BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
+
+ /*
+ * force other mappings to Oops if they'll try to access
+ * this pte without first remap it
+ */
+- pte_clear(&init_mm, vaddr, kmap_pte+idx);
++ pte_clear(&init_mm, vaddr, kmap_pte-idx);
+ flush_tlb_page(NULL, vaddr);
+ #endif
+ pagefault_enable();
+@@ -120,12 +121,14 @@ static inline void kunmap_atomic(void *kvaddr, enum km_type type)
+ static inline struct page *kmap_atomic_to_page(void *ptr)
+ {
+ unsigned long idx, vaddr = (unsigned long) ptr;
++ pte_t *pte;
+
+- if (vaddr < KMAP_FIX_BEGIN)
++ if (vaddr < FIXADDR_START)
+ return virt_to_page(ptr);
+
+- idx = (vaddr - KMAP_FIX_BEGIN) >> PAGE_SHIFT;
+- return pte_page(kmap_pte[idx]);
++ idx = virt_to_fix(vaddr);
++ pte = kmap_pte - (idx - FIX_KMAP_BEGIN);
++ return pte_page(*pte);
+ }
+
+ #define flush_cache_kmaps() flush_cache_all()
+diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h
+index a7b60bf..ad8c9f7 100644
+--- a/include/asm-powerpc/hw_irq.h
++++ b/include/asm-powerpc/hw_irq.h
+@@ -27,7 +27,7 @@ static inline unsigned long local_get_flags(void)
+ return flags;
+ }
+
+-static inline unsigned long local_irq_disable(void)
++static inline unsigned long raw_local_irq_disable(void)
+ {
+ unsigned long flags, zero;
+
+@@ -39,14 +39,15 @@ static inline unsigned long local_irq_disable(void)
+ return flags;
+ }
+
+-extern void local_irq_restore(unsigned long);
++extern void raw_local_irq_restore(unsigned long);
+ extern void iseries_handle_interrupts(void);
+
+-#define local_irq_enable() local_irq_restore(1)
+-#define local_save_flags(flags) ((flags) = local_get_flags())
+-#define local_irq_save(flags) ((flags) = local_irq_disable())
++#define raw_local_irq_enable() raw_local_irq_restore(1)
++#define raw_local_save_flags(flags) ((flags) = local_get_flags())
++#define raw_local_irq_save(flags) ((flags) = raw_local_irq_disable())
+
+-#define irqs_disabled() (local_get_flags() == 0)
++#define raw_irqs_disabled() (local_get_flags() == 0)
++#define raw_irqs_disabled_flags(flags) ((flags) == 0)
+
+ #define __hard_irq_enable() __mtmsrd(mfmsr() | MSR_EE, 1)
+ #define __hard_irq_disable() __mtmsrd(mfmsr() & ~MSR_EE, 1)
+diff --git a/include/asm-powerpc/ide.h b/include/asm-powerpc/ide.h
+index 6d50310..3d90bf7 100644
+--- a/include/asm-powerpc/ide.h
++++ b/include/asm-powerpc/ide.h
+@@ -31,39 +31,48 @@
+ #include <linux/hdreg.h>
+ #include <linux/ioport.h>
+
+-struct ide_machdep_calls {
+- int (*default_irq)(unsigned long base);
+- unsigned long (*default_io_base)(int index);
+- void (*ide_init_hwif)(hw_regs_t *hw,
+- unsigned long data_port,
+- unsigned long ctrl_port,
+- int *irq);
+-};
+-
+-extern struct ide_machdep_calls ppc_ide_md;
+-
+-#define IDE_ARCH_OBSOLETE_DEFAULTS
+-
++/* FIXME: use ide_platform host driver */
+ static __inline__ int ide_default_irq(unsigned long base)
+ {
+- if (ppc_ide_md.default_irq)
+- return ppc_ide_md.default_irq(base);
++#ifdef CONFIG_PPLUS
++ switch (base) {
++ case 0x1f0: return 14;
++ case 0x170: return 15;
++ }
++#endif
++#ifdef CONFIG_PPC_PREP
++ switch (base) {
++ case 0x1f0: return 13;
++ case 0x170: return 13;
++ case 0x1e8: return 11;
++ case 0x168: return 10;
++ case 0xfff0: return 14; /* MCP(N)750 ide0 */
++ case 0xffe0: return 15; /* MCP(N)750 ide1 */
++ }
++#endif
+ return 0;
+ }
+
++/* FIXME: use ide_platform host driver */
+ static __inline__ unsigned long ide_default_io_base(int index)
+ {
+- if (ppc_ide_md.default_io_base)
+- return ppc_ide_md.default_io_base(index);
++#ifdef CONFIG_PPLUS
++ switch (index) {
++ case 0: return 0x1f0;
++ case 1: return 0x170;
++ }
++#endif
++#ifdef CONFIG_PPC_PREP
++ switch (index) {
++ case 0: return 0x1f0;
++ case 1: return 0x170;
++ case 2: return 0x1e8;
++ case 3: return 0x168;
++ }
++#endif
+ return 0;
+ }
+
+-#ifdef CONFIG_PCI
+-#define ide_init_default_irq(base) (0)
+-#else
+-#define ide_init_default_irq(base) ide_default_irq(base)
+-#endif
+-
+ #ifdef CONFIG_BLK_DEV_MPC8xx_IDE
+ #define IDE_ARCH_ACK_INTR 1
+ #define ide_ack_intr(hwif) ((hwif)->ack_intr ? (hwif)->ack_intr(hwif) : 1)
+@@ -71,8 +80,6 @@ static __inline__ unsigned long ide_default_io_base(int index)
+
+ #endif /* __powerpc64__ */
+
+-#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */
+-
+ #endif /* __KERNEL__ */
+
+ #endif /* _ASM_POWERPC_IDE_H */
+diff --git a/include/asm-powerpc/immap_qe.h b/include/asm-powerpc/immap_qe.h
+index 82a4526..7b6f411 100644
+--- a/include/asm-powerpc/immap_qe.h
++++ b/include/asm-powerpc/immap_qe.h
+@@ -20,6 +20,7 @@
+ #ifdef __KERNEL__
+
+ #include <linux/kernel.h>
++#include <asm/io.h>
+
+ #define QE_IMMAP_SIZE (1024 * 1024) /* 1MB from 1MB+IMMR */
+
+@@ -468,7 +469,7 @@ struct qe_immap {
+ u8 res18[0xC0000]; /* 0x140000 - 0x200000 */
+ } __attribute__ ((packed));
+
+-extern struct qe_immap *qe_immr;
++extern struct qe_immap __iomem *qe_immr;
+ extern phys_addr_t get_qe_base(void);
+
+ static inline unsigned long immrbar_virt_to_phys(void *address)
+diff --git a/include/asm-powerpc/io-defs.h b/include/asm-powerpc/io-defs.h
+index 03691ab..44d7927 100644
+--- a/include/asm-powerpc/io-defs.h
++++ b/include/asm-powerpc/io-defs.h
+@@ -1,59 +1,60 @@
+ /* This file is meant to be include multiple times by other headers */
++/* last 2 argments are used by platforms/cell/io-workarounds.[ch] */
+
+-DEF_PCI_AC_RET(readb, u8, (const PCI_IO_ADDR addr), (addr))
+-DEF_PCI_AC_RET(readw, u16, (const PCI_IO_ADDR addr), (addr))
+-DEF_PCI_AC_RET(readl, u32, (const PCI_IO_ADDR addr), (addr))
+-DEF_PCI_AC_RET(readw_be, u16, (const PCI_IO_ADDR addr), (addr))
+-DEF_PCI_AC_RET(readl_be, u32, (const PCI_IO_ADDR addr), (addr))
+-DEF_PCI_AC_NORET(writeb, (u8 val, PCI_IO_ADDR addr), (val, addr))
+-DEF_PCI_AC_NORET(writew, (u16 val, PCI_IO_ADDR addr), (val, addr))
+-DEF_PCI_AC_NORET(writel, (u32 val, PCI_IO_ADDR addr), (val, addr))
+-DEF_PCI_AC_NORET(writew_be, (u16 val, PCI_IO_ADDR addr), (val, addr))
+-DEF_PCI_AC_NORET(writel_be, (u32 val, PCI_IO_ADDR addr), (val, addr))
++DEF_PCI_AC_RET(readb, u8, (const PCI_IO_ADDR addr), (addr), mem, addr)
++DEF_PCI_AC_RET(readw, u16, (const PCI_IO_ADDR addr), (addr), mem, addr)
++DEF_PCI_AC_RET(readl, u32, (const PCI_IO_ADDR addr), (addr), mem, addr)
++DEF_PCI_AC_RET(readw_be, u16, (const PCI_IO_ADDR addr), (addr), mem, addr)
++DEF_PCI_AC_RET(readl_be, u32, (const PCI_IO_ADDR addr), (addr), mem, addr)
++DEF_PCI_AC_NORET(writeb, (u8 val, PCI_IO_ADDR addr), (val, addr), mem, addr)
++DEF_PCI_AC_NORET(writew, (u16 val, PCI_IO_ADDR addr), (val, addr), mem, addr)
++DEF_PCI_AC_NORET(writel, (u32 val, PCI_IO_ADDR addr), (val, addr), mem, addr)
++DEF_PCI_AC_NORET(writew_be, (u16 val, PCI_IO_ADDR addr), (val, addr), mem, addr)
++DEF_PCI_AC_NORET(writel_be, (u32 val, PCI_IO_ADDR addr), (val, addr), mem, addr)
+
+ #ifdef __powerpc64__
+-DEF_PCI_AC_RET(readq, u64, (const PCI_IO_ADDR addr), (addr))
+-DEF_PCI_AC_RET(readq_be, u64, (const PCI_IO_ADDR addr), (addr))
+-DEF_PCI_AC_NORET(writeq, (u64 val, PCI_IO_ADDR addr), (val, addr))
+-DEF_PCI_AC_NORET(writeq_be, (u64 val, PCI_IO_ADDR addr), (val, addr))
++DEF_PCI_AC_RET(readq, u64, (const PCI_IO_ADDR addr), (addr), mem, addr)
++DEF_PCI_AC_RET(readq_be, u64, (const PCI_IO_ADDR addr), (addr), mem, addr)
++DEF_PCI_AC_NORET(writeq, (u64 val, PCI_IO_ADDR addr), (val, addr), mem, addr)
++DEF_PCI_AC_NORET(writeq_be, (u64 val, PCI_IO_ADDR addr), (val, addr), mem, addr)
+ #endif /* __powerpc64__ */
+
+-DEF_PCI_AC_RET(inb, u8, (unsigned long port), (port))
+-DEF_PCI_AC_RET(inw, u16, (unsigned long port), (port))
+-DEF_PCI_AC_RET(inl, u32, (unsigned long port), (port))
+-DEF_PCI_AC_NORET(outb, (u8 val, unsigned long port), (val, port))
+-DEF_PCI_AC_NORET(outw, (u16 val, unsigned long port), (val, port))
+-DEF_PCI_AC_NORET(outl, (u32 val, unsigned long port), (val, port))
++DEF_PCI_AC_RET(inb, u8, (unsigned long port), (port), pio, port)
++DEF_PCI_AC_RET(inw, u16, (unsigned long port), (port), pio, port)
++DEF_PCI_AC_RET(inl, u32, (unsigned long port), (port), pio, port)
++DEF_PCI_AC_NORET(outb, (u8 val, unsigned long port), (val, port), pio, port)
++DEF_PCI_AC_NORET(outw, (u16 val, unsigned long port), (val, port), pio, port)
++DEF_PCI_AC_NORET(outl, (u32 val, unsigned long port), (val, port), pio, port)
+
+-DEF_PCI_AC_NORET(readsb, (const PCI_IO_ADDR a, void *b, unsigned long c), \
+- (a, b, c))
+-DEF_PCI_AC_NORET(readsw, (const PCI_IO_ADDR a, void *b, unsigned long c), \
+- (a, b, c))
+-DEF_PCI_AC_NORET(readsl, (const PCI_IO_ADDR a, void *b, unsigned long c), \
+- (a, b, c))
+-DEF_PCI_AC_NORET(writesb, (PCI_IO_ADDR a, const void *b, unsigned long c), \
+- (a, b, c))
+-DEF_PCI_AC_NORET(writesw, (PCI_IO_ADDR a, const void *b, unsigned long c), \
+- (a, b, c))
+-DEF_PCI_AC_NORET(writesl, (PCI_IO_ADDR a, const void *b, unsigned long c), \
+- (a, b, c))
++DEF_PCI_AC_NORET(readsb, (const PCI_IO_ADDR a, void *b, unsigned long c),
++ (a, b, c), mem, a)
++DEF_PCI_AC_NORET(readsw, (const PCI_IO_ADDR a, void *b, unsigned long c),
++ (a, b, c), mem, a)
++DEF_PCI_AC_NORET(readsl, (const PCI_IO_ADDR a, void *b, unsigned long c),
++ (a, b, c), mem, a)
++DEF_PCI_AC_NORET(writesb, (PCI_IO_ADDR a, const void *b, unsigned long c),
++ (a, b, c), mem, a)
++DEF_PCI_AC_NORET(writesw, (PCI_IO_ADDR a, const void *b, unsigned long c),
++ (a, b, c), mem, a)
++DEF_PCI_AC_NORET(writesl, (PCI_IO_ADDR a, const void *b, unsigned long c),
++ (a, b, c), mem, a)
+
+-DEF_PCI_AC_NORET(insb, (unsigned long p, void *b, unsigned long c), \
+- (p, b, c))
+-DEF_PCI_AC_NORET(insw, (unsigned long p, void *b, unsigned long c), \
+- (p, b, c))
+-DEF_PCI_AC_NORET(insl, (unsigned long p, void *b, unsigned long c), \
+- (p, b, c))
+-DEF_PCI_AC_NORET(outsb, (unsigned long p, const void *b, unsigned long c), \
+- (p, b, c))
+-DEF_PCI_AC_NORET(outsw, (unsigned long p, const void *b, unsigned long c), \
+- (p, b, c))
+-DEF_PCI_AC_NORET(outsl, (unsigned long p, const void *b, unsigned long c), \
+- (p, b, c))
++DEF_PCI_AC_NORET(insb, (unsigned long p, void *b, unsigned long c),
++ (p, b, c), pio, p)
++DEF_PCI_AC_NORET(insw, (unsigned long p, void *b, unsigned long c),
++ (p, b, c), pio, p)
++DEF_PCI_AC_NORET(insl, (unsigned long p, void *b, unsigned long c),
++ (p, b, c), pio, p)
++DEF_PCI_AC_NORET(outsb, (unsigned long p, const void *b, unsigned long c),
++ (p, b, c), pio, p)
++DEF_PCI_AC_NORET(outsw, (unsigned long p, const void *b, unsigned long c),
++ (p, b, c), pio, p)
++DEF_PCI_AC_NORET(outsl, (unsigned long p, const void *b, unsigned long c),
++ (p, b, c), pio, p)
+
+-DEF_PCI_AC_NORET(memset_io, (PCI_IO_ADDR a, int c, unsigned long n), \
+- (a, c, n))
+-DEF_PCI_AC_NORET(memcpy_fromio,(void *d,const PCI_IO_ADDR s,unsigned long n), \
+- (d, s, n))
+-DEF_PCI_AC_NORET(memcpy_toio,(PCI_IO_ADDR d,const void *s,unsigned long n), \
+- (d, s, n))
++DEF_PCI_AC_NORET(memset_io, (PCI_IO_ADDR a, int c, unsigned long n),
++ (a, c, n), mem, a)
++DEF_PCI_AC_NORET(memcpy_fromio, (void *d, const PCI_IO_ADDR s, unsigned long n),
++ (d, s, n), mem, s)
++DEF_PCI_AC_NORET(memcpy_toio, (PCI_IO_ADDR d, const void *s, unsigned long n),
++ (d, s, n), mem, d)
+diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h
+index 7be26f6..afae069 100644
+--- a/include/asm-powerpc/io.h
++++ b/include/asm-powerpc/io.h
+@@ -458,8 +458,8 @@ __do_out_asm(_rec_outl, "stwbrx")
+ /* Structure containing all the hooks */
+ extern struct ppc_pci_io {
+
+-#define DEF_PCI_AC_RET(name, ret, at, al) ret (*name) at;
+-#define DEF_PCI_AC_NORET(name, at, al) void (*name) at;
++#define DEF_PCI_AC_RET(name, ret, at, al, space, aa) ret (*name) at;
++#define DEF_PCI_AC_NORET(name, at, al, space, aa) void (*name) at;
+
+ #include <asm/io-defs.h>
+
+@@ -469,7 +469,7 @@ extern struct ppc_pci_io {
+ } ppc_pci_io;
+
+ /* The inline wrappers */
+-#define DEF_PCI_AC_RET(name, ret, at, al) \
++#define DEF_PCI_AC_RET(name, ret, at, al, space, aa) \
+ static inline ret name at \
+ { \
+ if (DEF_PCI_HOOK(ppc_pci_io.name) != NULL) \
+@@ -477,7 +477,7 @@ static inline ret name at \
+ return __do_##name al; \
+ }
+
+-#define DEF_PCI_AC_NORET(name, at, al) \
++#define DEF_PCI_AC_NORET(name, at, al, space, aa) \
+ static inline void name at \
+ { \
+ if (DEF_PCI_HOOK(ppc_pci_io.name) != NULL) \
+diff --git a/include/asm-powerpc/irqflags.h b/include/asm-powerpc/irqflags.h
+index 7970cba..cc6fdba 100644
+--- a/include/asm-powerpc/irqflags.h
++++ b/include/asm-powerpc/irqflags.h
+@@ -2,30 +2,43 @@
+ * include/asm-powerpc/irqflags.h
+ *
+ * IRQ flags handling
+- *
+- * This file gets included from lowlevel asm headers too, to provide
+- * wrapped versions of the local_irq_*() APIs, based on the
+- * raw_local_irq_*() macros from the lowlevel headers.
+ */
+ #ifndef _ASM_IRQFLAGS_H
+ #define _ASM_IRQFLAGS_H
+
++#ifndef __ASSEMBLY__
+ /*
+ * Get definitions for raw_local_save_flags(x), etc.
+ */
+ #include <asm-powerpc/hw_irq.h>
+
++#else
++#ifdef CONFIG_TRACE_IRQFLAGS
+ /*
+- * Do the CPU's IRQ-state tracing from assembly code. We call a
+- * C function, so save all the C-clobbered registers:
++ * Most of the CPU's IRQ-state tracing is done from assembly code; we
++ * have to call a C function so call a wrapper that saves all the
++ * C-clobbered registers.
+ */
+-#ifdef CONFIG_TRACE_IRQFLAGS
+-
+-#error No support on PowerPC yet for CONFIG_TRACE_IRQFLAGS
+-
++#define TRACE_ENABLE_INTS bl .trace_hardirqs_on
++#define TRACE_DISABLE_INTS bl .trace_hardirqs_off
++#define TRACE_AND_RESTORE_IRQ_PARTIAL(en,skip) \
++ cmpdi en, 0; \
++ bne 95f; \
++ stb en,PACASOFTIRQEN(r13); \
++ bl .trace_hardirqs_off; \
++ b skip; \
++95: bl .trace_hardirqs_on; \
++ li en,1;
++#define TRACE_AND_RESTORE_IRQ(en) \
++ TRACE_AND_RESTORE_IRQ_PARTIAL(en,96f); \
++96: stb en,PACASOFTIRQEN(r13)
+ #else
+-# define TRACE_IRQS_ON
+-# define TRACE_IRQS_OFF
++#define TRACE_ENABLE_INTS
++#define TRACE_DISABLE_INTS
++#define TRACE_AND_RESTORE_IRQ_PARTIAL(en,skip)
++#define TRACE_AND_RESTORE_IRQ(en) \
++ stb en,PACASOFTIRQEN(r13)
++#endif
+ #endif
+
+ #endif
+diff --git a/include/asm-powerpc/iseries/alpaca.h b/include/asm-powerpc/iseries/alpaca.h
+new file mode 100644
+index 0000000..c0cce67
+--- /dev/null
++++ b/include/asm-powerpc/iseries/alpaca.h
+@@ -0,0 +1,31 @@
++/*
++ * Copyright © 2008 Stephen Rothwell IBM Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef _ASM_POWERPC_ISERIES_ALPACA_H
++#define _ASM_POWERPC_ISERIES_ALPACA_H
++
++/*
++ * This is the part of the paca that the iSeries hypervisor
++ * needs to be statically initialised. Immediately after boot
++ * we switch to the normal Linux paca.
++ */
++struct alpaca {
++ struct lppaca *lppaca_ptr; /* Pointer to LpPaca for PLIC */
++ const void *reg_save_ptr; /* Pointer to LpRegSave for PLIC */
++};
++
++#endif /* _ASM_POWERPC_ISERIES_ALPACA_H */
+diff --git a/include/asm-powerpc/iseries/it_lp_reg_save.h b/include/asm-powerpc/iseries/it_lp_reg_save.h
+deleted file mode 100644
+index 5403b75..0000000
+--- a/include/asm-powerpc/iseries/it_lp_reg_save.h
++++ /dev/null
+@@ -1,85 +0,0 @@
+-/*
+- * Copyright (C) 2001 Mike Corrigan IBM Corporation
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- */
+-#ifndef _ASM_POWERPC_ISERIES_IT_LP_REG_SAVE_H
+-#define _ASM_POWERPC_ISERIES_IT_LP_REG_SAVE_H
+-
+-/*
+- * This control block contains the data that is shared between PLIC
+- * and the OS
+- */
+-
+-struct ItLpRegSave {
+- u32 xDesc; // Eye catcher "LpRS" ebcdic 000-003
+- u16 xSize; // Size of this class 004-005
+- u8 xInUse; // Area is live 006-007
+- u8 xRsvd1[9]; // Reserved 007-00F
+-
+- u8 xFixedRegSave[352]; // Fixed Register Save Area 010-16F
+- u32 xCTRL; // Control Register 170-173
+- u32 xDEC; // Decrementer 174-177
+- u32 xFPSCR; // FP Status and Control Reg 178-17B
+- u32 xPVR; // Processor Version Number 17C-17F
+-
+- u64 xMMCR0; // Monitor Mode Control Reg 0 180-187
+- u32 xPMC1; // Perf Monitor Counter 1 188-18B
+- u32 xPMC2; // Perf Monitor Counter 2 18C-18F
+- u32 xPMC3; // Perf Monitor Counter 3 190-193
+- u32 xPMC4; // Perf Monitor Counter 4 194-197
+- u32 xPIR; // Processor ID Reg 198-19B
+-
+- u32 xMMCR1; // Monitor Mode Control Reg 1 19C-19F
+- u32 xMMCRA; // Monitor Mode Control Reg A 1A0-1A3
+- u32 xPMC5; // Perf Monitor Counter 5 1A4-1A7
+- u32 xPMC6; // Perf Monitor Counter 6 1A8-1AB
+- u32 xPMC7; // Perf Monitor Counter 7 1AC-1AF
+- u32 xPMC8; // Perf Monitor Counter 8 1B0-1B3
+- u32 xTSC; // Thread Switch Control 1B4-1B7
+- u32 xTST; // Thread Switch Timeout 1B8-1BB
+- u32 xRsvd; // Reserved 1BC-1BF
+-
+- u64 xACCR; // Address Compare Control Reg 1C0-1C7
+- u64 xIMR; // Instruction Match Register 1C8-1CF
+- u64 xSDR1; // Storage Description Reg 1 1D0-1D7
+- u64 xSPRG0; // Special Purpose Reg General0 1D8-1DF
+- u64 xSPRG1; // Special Purpose Reg General1 1E0-1E7
+- u64 xSPRG2; // Special Purpose Reg General2 1E8-1EF
+- u64 xSPRG3; // Special Purpose Reg General3 1F0-1F7
+- u64 xTB; // Time Base Register 1F8-1FF
+-
+- u64 xFPR[32]; // Floating Point Registers 200-2FF
+-
+- u64 xMSR; // Machine State Register 300-307
+- u64 xNIA; // Next Instruction Address 308-30F
+-
+- u64 xDABR; // Data Address Breakpoint Reg 310-317
+- u64 xIABR; // Inst Address Breakpoint Reg 318-31F
+-
+- u64 xHID0; // HW Implementation Dependent0 320-327
+-
+- u64 xHID4; // HW Implementation Dependent4 328-32F
+- u64 xSCOMd; // SCON Data Reg (SPRG4) 330-337
+- u64 xSCOMc; // SCON Command Reg (SPRG5) 338-33F
+- u64 xSDAR; // Sample Data Address Register 340-347
+- u64 xSIAR; // Sample Inst Address Register 348-34F
+-
+- u8 xRsvd3[176]; // Reserved 350-3FF
+-};
+-
+-extern struct ItLpRegSave iseries_reg_save[];
+-
+-#endif /* _ASM_POWERPC_ISERIES_IT_LP_REG_SAVE_H */
+diff --git a/include/asm-powerpc/kdump.h b/include/asm-powerpc/kdump.h
+index 10e8eb1..f6c93c7 100644
+--- a/include/asm-powerpc/kdump.h
++++ b/include/asm-powerpc/kdump.h
+@@ -11,16 +11,11 @@
+
+ #ifdef CONFIG_CRASH_DUMP
+
+-#define PHYSICAL_START KDUMP_KERNELBASE
+ #define KDUMP_TRAMPOLINE_START 0x0100
+ #define KDUMP_TRAMPOLINE_END 0x3000
+
+ #define KDUMP_MIN_TCE_ENTRIES 2048
+
+-#else /* !CONFIG_CRASH_DUMP */
+-
+-#define PHYSICAL_START 0x0
+-
+ #endif /* CONFIG_CRASH_DUMP */
+
+ #ifndef __ASSEMBLY__
+diff --git a/include/asm-powerpc/lmb.h b/include/asm-powerpc/lmb.h
+index 5d1dc48..6f5fdf0 100644
+--- a/include/asm-powerpc/lmb.h
++++ b/include/asm-powerpc/lmb.h
+@@ -1,81 +1,15 @@
+ #ifndef _ASM_POWERPC_LMB_H
+ #define _ASM_POWERPC_LMB_H
+-#ifdef __KERNEL__
+
+-/*
+- * Definitions for talking to the Open Firmware PROM on
+- * Power Macintosh computers.
+- *
+- * Copyright (C) 2001 Peter Bergner, IBM Corp.
+- *
+- * 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 <asm/udbg.h>
+
+-#include <linux/init.h>
+-#include <asm/prom.h>
++#define LMB_DBG(fmt...) udbg_printf(fmt)
+
+-#define MAX_LMB_REGIONS 128
++#ifdef CONFIG_PPC32
++extern phys_addr_t lowmem_end_addr;
++#define LMB_REAL_LIMIT lowmem_end_addr
++#else
++#define LMB_REAL_LIMIT 0
++#endif
+
+-struct lmb_property {
+- unsigned long base;
+- unsigned long size;
+-};
+-
+-struct lmb_region {
+- unsigned long cnt;
+- unsigned long size;
+- struct lmb_property region[MAX_LMB_REGIONS+1];
+-};
+-
+-struct lmb {
+- unsigned long debug;
+- unsigned long rmo_size;
+- struct lmb_region memory;
+- struct lmb_region reserved;
+-};
+-
+-extern struct lmb lmb;
+-
+-extern void __init lmb_init(void);
+-extern void __init lmb_analyze(void);
+-extern long __init lmb_add(unsigned long base, unsigned long size);
+-extern long __init lmb_reserve(unsigned long base, unsigned long size);
+-extern unsigned long __init lmb_alloc(unsigned long size, unsigned long align);
+-extern unsigned long __init lmb_alloc_base(unsigned long size,
+- unsigned long align, unsigned long max_addr);
+-extern unsigned long __init __lmb_alloc_base(unsigned long size,
+- unsigned long align, unsigned long max_addr);
+-extern unsigned long __init lmb_phys_mem_size(void);
+-extern unsigned long __init lmb_end_of_DRAM(void);
+-extern void __init lmb_enforce_memory_limit(unsigned long memory_limit);
+-extern int __init lmb_is_reserved(unsigned long addr);
+-
+-extern void lmb_dump_all(void);
+-
+-static inline unsigned long
+-lmb_size_bytes(struct lmb_region *type, unsigned long region_nr)
+-{
+- return type->region[region_nr].size;
+-}
+-static inline unsigned long
+-lmb_size_pages(struct lmb_region *type, unsigned long region_nr)
+-{
+- return lmb_size_bytes(type, region_nr) >> PAGE_SHIFT;
+-}
+-static inline unsigned long
+-lmb_start_pfn(struct lmb_region *type, unsigned long region_nr)
+-{
+- return type->region[region_nr].base >> PAGE_SHIFT;
+-}
+-static inline unsigned long
+-lmb_end_pfn(struct lmb_region *type, unsigned long region_nr)
+-{
+- return lmb_start_pfn(type, region_nr) +
+- lmb_size_pages(type, region_nr);
+-}
+-
+-#endif /* __KERNEL__ */
+ #endif /* _ASM_POWERPC_LMB_H */
+diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
+index 0872ec2..54ed64d 100644
+--- a/include/asm-powerpc/machdep.h
++++ b/include/asm-powerpc/machdep.h
+@@ -68,6 +68,8 @@ struct machdep_calls {
+ unsigned long vflags,
+ int psize, int ssize);
+ long (*hpte_remove)(unsigned long hpte_group);
++ void (*hpte_removebolted)(unsigned long ea,
++ int psize, int ssize);
+ void (*flush_hash_range)(unsigned long number, int local);
+
+ /* special for kexec, to be called in real mode, linar mapping is
+@@ -196,9 +198,6 @@ struct machdep_calls {
+ May be NULL. */
+ void (*init)(void);
+
+- void (*setup_io_mappings)(void);
+-
+- void (*early_serial_map)(void);
+ void (*kgdb_map_scc)(void);
+
+ /*
+diff --git a/include/asm-powerpc/macio.h b/include/asm-powerpc/macio.h
+index 3a6cb1a..079c06e 100644
+--- a/include/asm-powerpc/macio.h
++++ b/include/asm-powerpc/macio.h
+@@ -2,7 +2,7 @@
+ #define __MACIO_ASIC_H__
+ #ifdef __KERNEL__
+
+-#include <asm/of_device.h>
++#include <linux/of_device.h>
+
+ extern struct bus_type macio_bus_type;
+
+diff --git a/include/asm-powerpc/mediabay.h b/include/asm-powerpc/mediabay.h
+index de83fe1..df111c3 100644
+--- a/include/asm-powerpc/mediabay.h
++++ b/include/asm-powerpc/mediabay.h
+@@ -22,10 +22,14 @@ int check_media_bay(struct device_node *which_bay, int what);
+ /* Number of bays in the machine or 0 */
+ extern int media_bay_count;
+
++#ifdef CONFIG_BLK_DEV_IDE_PMAC
++#include <linux/ide.h>
++
+ int check_media_bay_by_base(unsigned long base, int what);
+ /* called by IDE PMAC host driver to register IDE controller for media bay */
+ int media_bay_set_ide_infos(struct device_node *which_bay, unsigned long base,
+- int irq, int index);
++ int irq, ide_hwif_t *hwif);
++#endif
+
+ #endif /* __KERNEL__ */
+ #endif /* _PPC_MEDIABAY_H */
+diff --git a/include/asm-powerpc/mmu-40x.h b/include/asm-powerpc/mmu-40x.h
+index 7d37f77..3d10867 100644
+--- a/include/asm-powerpc/mmu-40x.h
++++ b/include/asm-powerpc/mmu-40x.h
+@@ -53,8 +53,6 @@
+
+ #ifndef __ASSEMBLY__
+
+-typedef unsigned long phys_addr_t;
+-
+ typedef struct {
+ unsigned long id;
+ unsigned long vdso_base;
+diff --git a/include/asm-powerpc/mmu-44x.h b/include/asm-powerpc/mmu-44x.h
+index 62772ae..c8b02d9 100644
+--- a/include/asm-powerpc/mmu-44x.h
++++ b/include/asm-powerpc/mmu-44x.h
+@@ -53,8 +53,6 @@
+
+ #ifndef __ASSEMBLY__
+
+-typedef unsigned long long phys_addr_t;
+-
+ typedef struct {
+ unsigned long id;
+ unsigned long vdso_base;
+diff --git a/include/asm-powerpc/mmu-8xx.h b/include/asm-powerpc/mmu-8xx.h
+index 952bd88..9db877e 100644
+--- a/include/asm-powerpc/mmu-8xx.h
++++ b/include/asm-powerpc/mmu-8xx.h
+@@ -136,8 +136,6 @@
+ #define SPRN_M_TW 799
+
+ #ifndef __ASSEMBLY__
+-typedef unsigned long phys_addr_t;
+-
+ typedef struct {
+ unsigned long id;
+ unsigned long vdso_base;
+diff --git a/include/asm-powerpc/mmu-fsl-booke.h b/include/asm-powerpc/mmu-fsl-booke.h
+index 3758000..925d93c 100644
+--- a/include/asm-powerpc/mmu-fsl-booke.h
++++ b/include/asm-powerpc/mmu-fsl-booke.h
+@@ -73,12 +73,6 @@
+
+ #ifndef __ASSEMBLY__
+
+-#ifndef CONFIG_PHYS_64BIT
+-typedef unsigned long phys_addr_t;
+-#else
+-typedef unsigned long long phys_addr_t;
+-#endif
+-
+ typedef struct {
+ unsigned long id;
+ unsigned long vdso_base;
+diff --git a/include/asm-powerpc/mmu-hash32.h b/include/asm-powerpc/mmu-hash32.h
+index 4bd735b..6e21ca6 100644
+--- a/include/asm-powerpc/mmu-hash32.h
++++ b/include/asm-powerpc/mmu-hash32.h
+@@ -84,8 +84,6 @@ typedef struct {
+ unsigned long vdso_base;
+ } mm_context_t;
+
+-typedef unsigned long phys_addr_t;
+-
+ #endif /* !__ASSEMBLY__ */
+
+ #endif /* _ASM_POWERPC_MMU_HASH32_H_ */
+diff --git a/include/asm-powerpc/mmu-hash64.h b/include/asm-powerpc/mmu-hash64.h
+index 2864fa3..0dff767 100644
+--- a/include/asm-powerpc/mmu-hash64.h
++++ b/include/asm-powerpc/mmu-hash64.h
+@@ -469,9 +469,6 @@ static inline unsigned long get_vsid(unsigned long context, unsigned long ea,
+ VSID_MODULUS_256M)
+ #define KERNEL_VSID(ea) VSID_SCRAMBLE(GET_ESID(ea))
+
+-/* Physical address used by some IO functions */
+-typedef unsigned long phys_addr_t;
+-
+ #endif /* __ASSEMBLY__ */
+
+ #endif /* _ASM_POWERPC_MMU_HASH64_H_ */
+diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h
+index 748b35a..7b56444 100644
+--- a/include/asm-powerpc/paca.h
++++ b/include/asm-powerpc/paca.h
+@@ -42,10 +42,7 @@ struct task_struct;
+ * Defines the layout of the paca.
+ *
+ * This structure is not directly accessed by firmware or the service
+- * processor except for the first two pointers that point to the
+- * lppaca area and the ItLpRegSave area for this CPU. The lppaca
+- * object is currently contained within the PACA but it doesn't need
+- * to be.
++ * processor.
+ */
+ struct paca_struct {
+ /*
+@@ -55,14 +52,7 @@ struct paca_struct {
+ * avoid cacheline bouncing.
+ */
+
+- /*
+- * MAGIC: These first two pointers can't be moved - they're
+- * accessed by the firmware
+- */
+ struct lppaca *lppaca_ptr; /* Pointer to LpPaca for PLIC */
+-#ifdef CONFIG_PPC_ISERIES
+- void *reg_save_ptr; /* Pointer to LpRegSave for PLIC */
+-#endif /* CONFIG_PPC_ISERIES */
+
+ /*
+ * MAGIC: the spinlock functions in arch/powerpc/lib/locks.c
+@@ -118,6 +108,7 @@ struct paca_struct {
+ };
+
+ extern struct paca_struct paca[];
++extern void initialise_pacas(void);
+
+ #endif /* __KERNEL__ */
+ #endif /* _ASM_POWERPC_PACA_H */
+diff --git a/include/asm-powerpc/page.h b/include/asm-powerpc/page.h
+index df47bbb..cffdf0e 100644
+--- a/include/asm-powerpc/page.h
++++ b/include/asm-powerpc/page.h
+@@ -12,6 +12,7 @@
+
+ #include <asm/asm-compat.h>
+ #include <asm/kdump.h>
++#include <asm/types.h>
+
+ /*
+ * On PPC32 page size is 4K. For PPC64 we support either 4K or 64K software
+@@ -42,8 +43,23 @@
+ *
+ * The kdump dump kernel is one example where KERNELBASE != PAGE_OFFSET.
+ *
+- * To get a physical address from a virtual one you subtract PAGE_OFFSET,
+- * _not_ KERNELBASE.
++ * PAGE_OFFSET is the virtual address of the start of lowmem.
++ *
++ * PHYSICAL_START is the physical address of the start of the kernel.
++ *
++ * MEMORY_START is the physical address of the start of lowmem.
++ *
++ * KERNELBASE, PAGE_OFFSET, and PHYSICAL_START are all configurable on
++ * ppc32 and based on how they are set we determine MEMORY_START.
++ *
++ * For the linear mapping the following equation should be true:
++ * KERNELBASE - PAGE_OFFSET = PHYSICAL_START - MEMORY_START
++ *
++ * Also, KERNELBASE >= PAGE_OFFSET and PHYSICAL_START >= MEMORY_START
++ *
++ * There are two was to determine a physical address from a virtual one:
++ * va = pa + PAGE_OFFSET - MEMORY_START
++ * va = pa + KERNELBASE - PHYSICAL_START
+ *
+ * If you want to know something's offset from the start of the kernel you
+ * should subtract KERNELBASE.
+@@ -51,19 +67,33 @@
+ * If you want to test if something's a kernel address, use is_kernel_addr().
+ */
+
+-#define PAGE_OFFSET ASM_CONST(CONFIG_KERNEL_START)
+-#define KERNELBASE (PAGE_OFFSET + PHYSICAL_START)
++#define KERNELBASE ASM_CONST(CONFIG_KERNEL_START)
++#define PAGE_OFFSET ASM_CONST(CONFIG_PAGE_OFFSET)
++#define LOAD_OFFSET ASM_CONST((CONFIG_KERNEL_START-CONFIG_PHYSICAL_START))
++
++#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_FLATMEM)
++#ifndef __ASSEMBLY__
++extern phys_addr_t memstart_addr;
++extern phys_addr_t kernstart_addr;
++#endif
++#define PHYSICAL_START kernstart_addr
++#define MEMORY_START memstart_addr
++#else
++#define PHYSICAL_START ASM_CONST(CONFIG_PHYSICAL_START)
++#define MEMORY_START (PHYSICAL_START + PAGE_OFFSET - KERNELBASE)
++#endif
+
+ #ifdef CONFIG_FLATMEM
+-#define pfn_valid(pfn) ((pfn) < max_mapnr)
++#define ARCH_PFN_OFFSET (MEMORY_START >> PAGE_SHIFT)
++#define pfn_valid(pfn) ((pfn) >= ARCH_PFN_OFFSET && (pfn) < (ARCH_PFN_OFFSET + max_mapnr))
+ #endif
+
+ #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+ #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
+ #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+
+-#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET))
+-#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET)
++#define __va(x) ((void *)((unsigned long)(x) - PHYSICAL_START + KERNELBASE))
++#define __pa(x) ((unsigned long)(x) + PHYSICAL_START - KERNELBASE)
+
+ /*
+ * Unfortunately the PLT is in the BSS in the PPC32 ELF ABI,
+diff --git a/include/asm-powerpc/page_32.h b/include/asm-powerpc/page_32.h
+index 65ea19e..ebfae53 100644
+--- a/include/asm-powerpc/page_32.h
++++ b/include/asm-powerpc/page_32.h
+@@ -1,9 +1,13 @@
+ #ifndef _ASM_POWERPC_PAGE_32_H
+ #define _ASM_POWERPC_PAGE_32_H
+
+-#define VM_DATA_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS32
++#if defined(CONFIG_PHYSICAL_ALIGN) && (CONFIG_PHYSICAL_START != 0)
++#if (CONFIG_PHYSICAL_START % CONFIG_PHYSICAL_ALIGN) != 0
++#error "CONFIG_PHYSICAL_START must be a multiple of CONFIG_PHYSICAL_ALIGN"
++#endif
++#endif
+
+-#define PPC_MEMSTART 0
++#define VM_DATA_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS32
+
+ #ifdef CONFIG_NOT_COHERENT_CACHE
+ #define ARCH_KMALLOC_MINALIGN L1_CACHE_BYTES
+diff --git a/include/asm-powerpc/pasemi_dma.h b/include/asm-powerpc/pasemi_dma.h
+index b4526ff..19fd793 100644
+--- a/include/asm-powerpc/pasemi_dma.h
++++ b/include/asm-powerpc/pasemi_dma.h
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (C) 2006 PA Semi, Inc
++ * Copyright (C) 2006-2008 PA Semi, Inc
+ *
+ * Hardware register layout and descriptor formats for the on-board
+ * DMA engine on PA Semi PWRficient. Used by ethernet, function and security
+@@ -40,6 +40,11 @@ enum {
+ PAS_DMA_COM_TXSTA = 0x104, /* Transmit Status Register */
+ PAS_DMA_COM_RXCMD = 0x108, /* Receive Command Register */
+ PAS_DMA_COM_RXSTA = 0x10c, /* Receive Status Register */
++ PAS_DMA_COM_CFG = 0x114, /* Common config reg */
++ PAS_DMA_TXF_SFLG0 = 0x140, /* Set flags */
++ PAS_DMA_TXF_SFLG1 = 0x144, /* Set flags */
++ PAS_DMA_TXF_CFLG0 = 0x148, /* Set flags */
++ PAS_DMA_TXF_CFLG1 = 0x14c, /* Set flags */
+ };
+
+
+@@ -123,11 +128,16 @@ enum {
+ #define PAS_DMA_TXCHAN_TCMDSTA_DA 0x00000100
+ #define PAS_DMA_TXCHAN_CFG(c) (0x304+(c)*_PAS_DMA_TXCHAN_STRIDE)
+ #define PAS_DMA_TXCHAN_CFG_TY_IFACE 0x00000000 /* Type = interface */
++#define PAS_DMA_TXCHAN_CFG_TY_COPY 0x00000001 /* Type = copy only */
++#define PAS_DMA_TXCHAN_CFG_TY_FUNC 0x00000002 /* Type = function */
++#define PAS_DMA_TXCHAN_CFG_TY_XOR 0x00000003 /* Type = xor only */
+ #define PAS_DMA_TXCHAN_CFG_TATTR_M 0x0000003c
+ #define PAS_DMA_TXCHAN_CFG_TATTR_S 2
+ #define PAS_DMA_TXCHAN_CFG_TATTR(x) (((x) << PAS_DMA_TXCHAN_CFG_TATTR_S) & \
+ PAS_DMA_TXCHAN_CFG_TATTR_M)
+-#define PAS_DMA_TXCHAN_CFG_WT_M 0x000001c0
++#define PAS_DMA_TXCHAN_CFG_LPDQ 0x00000800
++#define PAS_DMA_TXCHAN_CFG_LPSQ 0x00000400
++#define PAS_DMA_TXCHAN_CFG_WT_M 0x000003c0
+ #define PAS_DMA_TXCHAN_CFG_WT_S 6
+ #define PAS_DMA_TXCHAN_CFG_WT(x) (((x) << PAS_DMA_TXCHAN_CFG_WT_S) & \
+ PAS_DMA_TXCHAN_CFG_WT_M)
+@@ -394,11 +404,62 @@ enum {
+ XCT_COPY_LLEN_M)
+ #define XCT_COPY_SE 0x0000000000000001ull
+
++/* Function descriptor fields */
++#define XCT_FUN_T 0x8000000000000000ull
++#define XCT_FUN_ST 0x4000000000000000ull
++#define XCT_FUN_RR_M 0x3000000000000000ull
++#define XCT_FUN_RR_NORES 0x0000000000000000ull
++#define XCT_FUN_RR_8BRES 0x1000000000000000ull
++#define XCT_FUN_RR_24BRES 0x2000000000000000ull
++#define XCT_FUN_RR_40BRES 0x3000000000000000ull
++#define XCT_FUN_I 0x0800000000000000ull
++#define XCT_FUN_O 0x0400000000000000ull
++#define XCT_FUN_E 0x0200000000000000ull
++#define XCT_FUN_FUN_M 0x01c0000000000000ull
++#define XCT_FUN_FUN_S 54
++#define XCT_FUN_FUN(x) ((((long)(x)) << XCT_FUN_FUN_S) & XCT_FUN_FUN_M)
++#define XCT_FUN_CRM_M 0x0038000000000000ull
++#define XCT_FUN_CRM_NOP 0x0000000000000000ull
++#define XCT_FUN_CRM_SIG 0x0008000000000000ull
++#define XCT_FUN_LLEN_M 0x0007ffff00000000ull
++#define XCT_FUN_LLEN_S 32
++#define XCT_FUN_LLEN(x) ((((long)(x)) << XCT_FUN_LLEN_S) & XCT_FUN_LLEN_M)
++#define XCT_FUN_SHL_M 0x00000000f8000000ull
++#define XCT_FUN_SHL_S 27
++#define XCT_FUN_SHL(x) ((((long)(x)) << XCT_FUN_SHL_S) & XCT_FUN_SHL_M)
++#define XCT_FUN_CHL_M 0x0000000007c00000ull
++#define XCT_FUN_HSZ_M 0x00000000003c0000ull
++#define XCT_FUN_ALG_M 0x0000000000038000ull
++#define XCT_FUN_HP 0x0000000000004000ull
++#define XCT_FUN_BCM_M 0x0000000000003800ull
++#define XCT_FUN_BCP_M 0x0000000000000600ull
++#define XCT_FUN_SIG_M 0x00000000000001f0ull
++#define XCT_FUN_SIG_TCP4 0x0000000000000140ull
++#define XCT_FUN_SIG_TCP6 0x0000000000000150ull
++#define XCT_FUN_SIG_UDP4 0x0000000000000160ull
++#define XCT_FUN_SIG_UDP6 0x0000000000000170ull
++#define XCT_FUN_A 0x0000000000000008ull
++#define XCT_FUN_C 0x0000000000000004ull
++#define XCT_FUN_AL2 0x0000000000000002ull
++#define XCT_FUN_SE 0x0000000000000001ull
++
++/* Function descriptor 8byte result fields */
++#define XCT_FUNRES_8B_CS_M 0x0000ffff00000000ull
++#define XCT_FUNRES_8B_CS_S 32
++#define XCT_FUNRES_8B_CRC_M 0x00000000ffffffffull
++#define XCT_FUNRES_8B_CRC_S 0
++
+ /* Control descriptor fields */
+ #define CTRL_CMD_T 0x8000000000000000ull
+ #define CTRL_CMD_META_EVT 0x2000000000000000ull
+ #define CTRL_CMD_O 0x0400000000000000ull
+-#define CTRL_CMD_REG_M 0x000000000000000full
++#define CTRL_CMD_ETYPE_M 0x0038000000000000ull
++#define CTRL_CMD_ETYPE_EXT 0x0000000000000000ull
++#define CTRL_CMD_ETYPE_WSET 0x0020000000000000ull
++#define CTRL_CMD_ETYPE_WCLR 0x0028000000000000ull
++#define CTRL_CMD_ETYPE_SET 0x0030000000000000ull
++#define CTRL_CMD_ETYPE_CLR 0x0038000000000000ull
++#define CTRL_CMD_REG_M 0x000000000000007full
+ #define CTRL_CMD_REG_S 0
+ #define CTRL_CMD_REG(x) ((((long)(x)) << CTRL_CMD_REG_S) & \
+ CTRL_CMD_REG_M)
+@@ -461,6 +522,16 @@ extern void *pasemi_dma_alloc_buf(struct pasemi_dmachan *chan, int size,
+ extern void pasemi_dma_free_buf(struct pasemi_dmachan *chan, int size,
+ dma_addr_t *handle);
+
++/* Routines to allocate flags (events) for channel syncronization */
++extern int pasemi_dma_alloc_flag(void);
++extern void pasemi_dma_free_flag(int flag);
++extern void pasemi_dma_set_flag(int flag);
++extern void pasemi_dma_clear_flag(int flag);
++
++/* Routines to allocate function engines */
++extern int pasemi_dma_alloc_fun(void);
++extern void pasemi_dma_free_fun(int fun);
++
+ /* Initialize the library, must be called before any other functions */
+ extern int pasemi_dma_init(void);
+
+diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h
+index e5802c6..b95d033 100644
+--- a/include/asm-powerpc/pci-bridge.h
++++ b/include/asm-powerpc/pci-bridge.h
+@@ -117,7 +117,7 @@ struct pci_controller {
+
+ #ifndef CONFIG_PPC64
+
+-static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
++static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
+ {
+ return bus->sysdata;
+ }
+@@ -235,7 +235,7 @@ extern void pcibios_fixup_new_pci_devices(struct pci_bus *bus);
+
+ extern int pcibios_remove_root_bus(struct pci_controller *phb);
+
+-static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
++static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
+ {
+ struct device_node *busdn = bus->sysdata;
+
+diff --git a/include/asm-powerpc/pgtable-ppc32.h b/include/asm-powerpc/pgtable-ppc32.h
+index 2c79f55..daea769 100644
+--- a/include/asm-powerpc/pgtable-ppc32.h
++++ b/include/asm-powerpc/pgtable-ppc32.h
+@@ -98,9 +98,6 @@ extern int icache_44x_need_flush;
+ #define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE)
+ #define FIRST_USER_ADDRESS 0
+
+-#define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
+-#define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
+-
+ #define pte_ERROR(e) \
+ printk("%s:%d: bad pte %llx.\n", __FILE__, __LINE__, \
+ (unsigned long long)pte_val(e))
+@@ -420,7 +417,8 @@ extern int icache_44x_need_flush;
+ #define _PAGE_IO (_PAGE_KERNEL | _PAGE_NO_CACHE | _PAGE_GUARDED)
+ #define _PAGE_RAM (_PAGE_KERNEL | _PAGE_HWEXEC)
+
+-#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) || defined(CONFIG_BDI_SWITCH)
++#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) || defined(CONFIG_BDI_SWITCH) ||\
++ defined(CONFIG_KPROBES)
+ /* We want the debuggers to be able to set breakpoints anywhere, so
+ * don't write protect the kernel text */
+ #define _PAGE_RAM_TEXT _PAGE_RAM
+@@ -692,7 +690,7 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+ #define pmd_page_vaddr(pmd) \
+ ((unsigned long) (pmd_val(pmd) & PAGE_MASK))
+ #define pmd_page(pmd) \
+- (mem_map + (__pa(pmd_val(pmd)) >> PAGE_SHIFT))
++ pfn_to_page((__pa(pmd_val(pmd)) >> PAGE_SHIFT))
+ #endif
+
+ /* to find an entry in a kernel page-table-directory */
+diff --git a/include/asm-powerpc/phyp_dump.h b/include/asm-powerpc/phyp_dump.h
+new file mode 100644
+index 0000000..fa74c6c
+--- /dev/null
++++ b/include/asm-powerpc/phyp_dump.h
+@@ -0,0 +1,47 @@
++/*
++ * Hypervisor-assisted dump
++ *
++ * Linas Vepstas, Manish Ahuja 2008
++ * Copyright 2008 IBM Corp.
++ *
++ * 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 _PPC64_PHYP_DUMP_H
++#define _PPC64_PHYP_DUMP_H
++
++#ifdef CONFIG_PHYP_DUMP
++
++/* The RMR region will be saved for later dumping
++ * whenever the kernel crashes. Set this to 256MB. */
++#define PHYP_DUMP_RMR_START 0x0
++#define PHYP_DUMP_RMR_END (1UL<<28)
++
++struct phyp_dump {
++ /* Memory that is reserved during very early boot. */
++ unsigned long init_reserve_start;
++ unsigned long init_reserve_size;
++ /* cmd line options during boot */
++ unsigned long reserve_bootvar;
++ unsigned long phyp_dump_at_boot;
++ /* Check status during boot if dump supported, active & present*/
++ unsigned long phyp_dump_configured;
++ unsigned long phyp_dump_is_active;
++ /* store cpu & hpte size */
++ unsigned long cpu_state_size;
++ unsigned long hpte_region_size;
++ /* previous scratch area values */
++ unsigned long reserved_scratch_addr;
++ unsigned long reserved_scratch_size;
++};
++
++extern struct phyp_dump *phyp_dump_info;
++
++int early_init_dt_scan_phyp_dump(unsigned long node,
++ const char *uname, int depth, void *data);
++
++#endif /* CONFIG_PHYP_DUMP */
++#endif /* _PPC64_PHYP_DUMP_H */
+diff --git a/include/asm-powerpc/pmi.h b/include/asm-powerpc/pmi.h
+index 2259d4c..e1dc090 100644
+--- a/include/asm-powerpc/pmi.h
++++ b/include/asm-powerpc/pmi.h
+@@ -29,8 +29,6 @@
+
+ #ifdef __KERNEL__
+
+-#include <asm/of_device.h>
+-
+ #define PMI_TYPE_FREQ_CHANGE 0x01
+ #define PMI_READ_TYPE 0
+ #define PMI_READ_DATA0 1
+diff --git a/include/asm-powerpc/ppc4xx.h b/include/asm-powerpc/ppc4xx.h
+new file mode 100644
+index 0000000..033039a
+--- /dev/null
++++ b/include/asm-powerpc/ppc4xx.h
+@@ -0,0 +1,18 @@
++/*
++ * PPC4xx Prototypes and definitions
++ *
++ * Copyright 2008 DENX Software Engineering, Stefan Roese <sr at denx.de>
++ *
++ * This 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 __ASM_POWERPC_PPC4xx_H__
++#define __ASM_POWERPC_PPC4xx_H__
++
++extern void ppc4xx_reset_system(char *cmd);
++
++#endif /* __ASM_POWERPC_PPC4xx_H__ */
+diff --git a/include/asm-powerpc/ps3.h b/include/asm-powerpc/ps3.h
+index 2b69367..9e8ed68 100644
+--- a/include/asm-powerpc/ps3.h
++++ b/include/asm-powerpc/ps3.h
+@@ -434,8 +434,11 @@ struct ps3_sys_manager_ops {
+ };
+
+ void ps3_sys_manager_register_ops(const struct ps3_sys_manager_ops *ops);
+-void ps3_sys_manager_power_off(void);
+-void ps3_sys_manager_restart(void);
++void __noreturn ps3_sys_manager_power_off(void);
++void __noreturn ps3_sys_manager_restart(void);
++void __noreturn ps3_sys_manager_halt(void);
++int ps3_sys_manager_get_wol(void);
++void ps3_sys_manager_set_wol(int state);
+
+ struct ps3_prealloc {
+ const char *name;
+diff --git a/include/asm-powerpc/ptrace.h b/include/asm-powerpc/ptrace.h
+index 891d689..39023dd 100644
+--- a/include/asm-powerpc/ptrace.h
++++ b/include/asm-powerpc/ptrace.h
+@@ -58,6 +58,11 @@ struct pt_regs {
+ #define __ARCH_WANT_COMPAT_SYS_PTRACE
+
+ #define STACK_FRAME_OVERHEAD 112 /* size of minimum stack frame */
++#define STACK_FRAME_LR_SAVE 2 /* Location of LR in stack frame */
++#define STACK_FRAME_REGS_MARKER ASM_CONST(0x7265677368657265)
++#define STACK_INT_FRAME_SIZE (sizeof(struct pt_regs) + \
++ STACK_FRAME_OVERHEAD + 288)
++#define STACK_FRAME_MARKER 12
+
+ /* Size of dummy stack frame allocated when calling signal handler. */
+ #define __SIGNAL_FRAMESIZE 128
+@@ -66,6 +71,10 @@ struct pt_regs {
+ #else /* __powerpc64__ */
+
+ #define STACK_FRAME_OVERHEAD 16 /* size of minimum stack frame */
++#define STACK_FRAME_LR_SAVE 1 /* Location of LR in stack frame */
++#define STACK_FRAME_REGS_MARKER ASM_CONST(0x72656773)
++#define STACK_INT_FRAME_SIZE (sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD)
++#define STACK_FRAME_MARKER 2
+
+ /* Size of stack frame allocated when calling signal handler. */
+ #define __SIGNAL_FRAMESIZE 64
+diff --git a/include/asm-powerpc/qe.h b/include/asm-powerpc/qe.h
+index 430dc77..c3be6e2 100644
+--- a/include/asm-powerpc/qe.h
++++ b/include/asm-powerpc/qe.h
+@@ -85,6 +85,7 @@ extern int par_io_data_set(u8 port, u8 pin, u8 val);
+ /* QE internal API */
+ int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input);
+ enum qe_clock qe_clock_source(const char *source);
++unsigned int qe_get_brg_clk(void);
+ int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier);
+ int qe_get_snum(void);
+ void qe_put_snum(u8 snum);
+@@ -92,7 +93,16 @@ unsigned long qe_muram_alloc(int size, int align);
+ int qe_muram_free(unsigned long offset);
+ unsigned long qe_muram_alloc_fixed(unsigned long offset, int size);
+ void qe_muram_dump(void);
+-void *qe_muram_addr(unsigned long offset);
++
++static inline void __iomem *qe_muram_addr(unsigned long offset)
++{
++ return (void __iomem *)&qe_immr->muram[offset];
++}
++
++static inline unsigned long qe_muram_offset(void __iomem *addr)
++{
++ return addr - (void __iomem *)qe_immr->muram;
++}
+
+ /* Structure that defines QE firmware binary files.
+ *
+diff --git a/include/asm-powerpc/rwsem.h b/include/asm-powerpc/rwsem.h
+index cefc147..a6cc93b 100644
+--- a/include/asm-powerpc/rwsem.h
++++ b/include/asm-powerpc/rwsem.h
+@@ -32,11 +32,20 @@ struct rw_semaphore {
+ #define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
+ spinlock_t wait_lock;
+ struct list_head wait_list;
++#ifdef CONFIG_DEBUG_LOCK_ALLOC
++ struct lockdep_map dep_map;
++#endif
+ };
+
++#ifdef CONFIG_DEBUG_LOCK_ALLOC
++# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
++#else
++# define __RWSEM_DEP_MAP_INIT(lockname)
++#endif
++
+ #define __RWSEM_INITIALIZER(name) \
+- { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
+- LIST_HEAD_INIT((name).wait_list) }
++ { RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait_lock), \
++ LIST_HEAD_INIT((name).wait_list) __RWSEM_DEP_MAP_INIT(name) }
+
+ #define DECLARE_RWSEM(name) \
+ struct rw_semaphore name = __RWSEM_INITIALIZER(name)
+@@ -46,12 +55,15 @@ extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
+ extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
+ extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
+
+-static inline void init_rwsem(struct rw_semaphore *sem)
+-{
+- sem->count = RWSEM_UNLOCKED_VALUE;
+- spin_lock_init(&sem->wait_lock);
+- INIT_LIST_HEAD(&sem->wait_list);
+-}
++extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
++ struct lock_class_key *key);
++
++#define init_rwsem(sem) \
++ do { \
++ static struct lock_class_key __key; \
++ \
++ __init_rwsem((sem), #sem, &__key); \
++ } while (0)
+
+ /*
+ * lock for reading
+@@ -78,7 +90,7 @@ static inline int __down_read_trylock(struct rw_semaphore *sem)
+ /*
+ * lock for writing
+ */
+-static inline void __down_write(struct rw_semaphore *sem)
++static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
+ {
+ int tmp;
+
+@@ -88,6 +100,11 @@ static inline void __down_write(struct rw_semaphore *sem)
+ rwsem_down_write_failed(sem);
+ }
+
++static inline void __down_write(struct rw_semaphore *sem)
++{
++ __down_write_nested(sem, 0);
++}
++
+ static inline int __down_write_trylock(struct rw_semaphore *sem)
+ {
+ int tmp;
+diff --git a/include/asm-powerpc/semaphore.h b/include/asm-powerpc/semaphore.h
+index 48dd32e..d9b2034 100644
+--- a/include/asm-powerpc/semaphore.h
++++ b/include/asm-powerpc/semaphore.h
+@@ -1,94 +1 @@
+-#ifndef _ASM_POWERPC_SEMAPHORE_H
+-#define _ASM_POWERPC_SEMAPHORE_H
+-
+-/*
+- * Remove spinlock-based RW semaphores; RW semaphore definitions are
+- * now in rwsem.h and we use the generic lib/rwsem.c implementation.
+- * Rework semaphores to use atomic_dec_if_positive.
+- * -- Paul Mackerras (paulus at samba.org)
+- */
+-
+-#ifdef __KERNEL__
+-
+-#include <asm/atomic.h>
+-#include <asm/system.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-struct semaphore {
+- /*
+- * Note that any negative value of count is equivalent to 0,
+- * but additionally indicates that some process(es) might be
+- * sleeping on `wait'.
+- */
+- atomic_t count;
+- wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n) \
+-{ \
+- .count = ATOMIC_INIT(n), \
+- .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name, count) \
+- struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name, 1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+- atomic_set(&sem->count, val);
+- init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+- sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+- sema_init(sem, 0);
+-}
+-
+-extern void __down(struct semaphore * sem);
+-extern int __down_interruptible(struct semaphore * sem);
+-extern void __up(struct semaphore * sem);
+-
+-static inline void down(struct semaphore * sem)
+-{
+- might_sleep();
+-
+- /*
+- * Try to get the semaphore, take the slow path if we fail.
+- */
+- if (unlikely(atomic_dec_return(&sem->count) < 0))
+- __down(sem);
+-}
+-
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+- int ret = 0;
+-
+- might_sleep();
+-
+- if (unlikely(atomic_dec_return(&sem->count) < 0))
+- ret = __down_interruptible(sem);
+- return ret;
+-}
+-
+-static inline int down_trylock(struct semaphore * sem)
+-{
+- return atomic_dec_if_positive(&sem->count) < 0;
+-}
+-
+-static inline void up(struct semaphore * sem)
+-{
+- if (unlikely(atomic_inc_return(&sem->count) <= 0))
+- __up(sem);
+-}
+-
+-#endif /* __KERNEL__ */
+-
+-#endif /* _ASM_POWERPC_SEMAPHORE_H */
++#include <linux/semaphore.h>
+diff --git a/include/asm-powerpc/sparsemem.h b/include/asm-powerpc/sparsemem.h
+index e8b493d..9aea8e9 100644
+--- a/include/asm-powerpc/sparsemem.h
++++ b/include/asm-powerpc/sparsemem.h
+@@ -15,6 +15,7 @@
+
+ #ifdef CONFIG_MEMORY_HOTPLUG
+ extern void create_section_mapping(unsigned long start, unsigned long end);
++extern int remove_section_mapping(unsigned long start, unsigned long end);
+ #ifdef CONFIG_NUMA
+ extern int hot_add_scn_to_nid(unsigned long scn_addr);
+ #else
+diff --git a/include/asm-powerpc/spinlock.h b/include/asm-powerpc/spinlock.h
+index cc4cfce..258c939 100644
+--- a/include/asm-powerpc/spinlock.h
++++ b/include/asm-powerpc/spinlock.h
+@@ -19,6 +19,7 @@
+ *
+ * (the type definitions are in asm/spinlock_types.h)
+ */
++#include <linux/irqflags.h>
+ #ifdef CONFIG_PPC64
+ #include <asm/paca.h>
+ #include <asm/hvcall.h>
+diff --git a/include/asm-powerpc/string.h b/include/asm-powerpc/string.h
+index aa40f92..e40010a 100644
+--- a/include/asm-powerpc/string.h
++++ b/include/asm-powerpc/string.h
+@@ -7,6 +7,7 @@
+ #define __HAVE_ARCH_STRNCPY
+ #define __HAVE_ARCH_STRLEN
+ #define __HAVE_ARCH_STRCMP
++#define __HAVE_ARCH_STRNCMP
+ #define __HAVE_ARCH_STRCAT
+ #define __HAVE_ARCH_MEMSET
+ #define __HAVE_ARCH_MEMCPY
+@@ -18,6 +19,7 @@ extern char * strcpy(char *,const char *);
+ extern char * strncpy(char *,const char *, __kernel_size_t);
+ extern __kernel_size_t strlen(const char *);
+ extern int strcmp(const char *,const char *);
++extern int strncmp(const char *, const char *, __kernel_size_t);
+ extern char * strcat(char *, const char *);
+ extern void * memset(void *,int,__kernel_size_t);
+ extern void * memcpy(void *,const void *,__kernel_size_t);
+diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h
+index 29552ff..fab1674 100644
+--- a/include/asm-powerpc/system.h
++++ b/include/asm-powerpc/system.h
+@@ -5,6 +5,7 @@
+ #define _ASM_POWERPC_SYSTEM_H
+
+ #include <linux/kernel.h>
++#include <linux/irqflags.h>
+
+ #include <asm/hw_irq.h>
+
+diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h
+index 40d5f98..d030f5c 100644
+--- a/include/asm-powerpc/thread_info.h
++++ b/include/asm-powerpc/thread_info.h
+@@ -80,12 +80,8 @@ struct thread_info {
+
+ #else /* THREAD_SHIFT < PAGE_SHIFT */
+
+-#ifdef CONFIG_DEBUG_STACK_USAGE
+-#define alloc_thread_info(tsk) kzalloc(THREAD_SIZE, GFP_KERNEL)
+-#else
+-#define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL)
+-#endif
+-#define free_thread_info(ti) kfree(ti)
++extern struct thread_info *alloc_thread_info(struct task_struct *tsk);
++extern void free_thread_info(struct thread_info *ti);
+
+ #endif /* THREAD_SHIFT < PAGE_SHIFT */
+
+diff --git a/include/asm-powerpc/topology.h b/include/asm-powerpc/topology.h
+index ca23b68..100c6fb 100644
+--- a/include/asm-powerpc/topology.h
++++ b/include/asm-powerpc/topology.h
+@@ -96,11 +96,10 @@ static inline void sysfs_remove_device_from_node(struct sys_device *dev,
+ {
+ }
+
++#endif /* CONFIG_NUMA */
+
+ #include <asm-generic/topology.h>
+
+-#endif /* CONFIG_NUMA */
+-
+ #ifdef CONFIG_SMP
+ #include <asm/cputable.h>
+ #define smt_capable() (cpu_has_feature(CPU_FTR_SMT))
+diff --git a/include/asm-powerpc/types.h b/include/asm-powerpc/types.h
+index 903fd19..c243a6a 100644
+--- a/include/asm-powerpc/types.h
++++ b/include/asm-powerpc/types.h
+@@ -84,6 +84,13 @@ typedef unsigned long long u64;
+
+ typedef __vector128 vector128;
+
++/* Physical address used by some IO functions */
++#if defined(CONFIG_PPC64) || defined(CONFIG_PHYS_64BIT)
++typedef u64 phys_addr_t;
++#else
++typedef u32 phys_addr_t;
++#endif
++
+ #ifdef __powerpc64__
+ typedef u64 dma_addr_t;
+ #else
+diff --git a/include/asm-ppc/mmu.h b/include/asm-ppc/mmu.h
+index d46b57b..d76ef09 100644
+--- a/include/asm-ppc/mmu.h
++++ b/include/asm-ppc/mmu.h
+@@ -15,10 +15,8 @@
+ * physical need a larger than native word size type. -Matt
+ */
+ #ifndef CONFIG_PHYS_64BIT
+-typedef unsigned long phys_addr_t;
+ #define PHYS_FMT "%.8lx"
+ #else
+-typedef unsigned long long phys_addr_t;
+ extern phys_addr_t fixup_bigphys_addr(phys_addr_t, phys_addr_t);
+ #define PHYS_FMT "%16Lx"
+ #endif
+diff --git a/include/asm-ppc/mpc8260.h b/include/asm-ppc/mpc8260.h
+index 23579d4..402ba15 100644
+--- a/include/asm-ppc/mpc8260.h
++++ b/include/asm-ppc/mpc8260.h
+@@ -35,10 +35,6 @@
+ #include <platforms/tqm8260.h>
+ #endif
+
+-#if defined(CONFIG_PQ2ADS) || defined (CONFIG_PQ2FADS)
+-#include <platforms/pq2ads.h>
+-#endif
+-
+ #ifdef CONFIG_PCI_8260
+ #include <syslib/m82xx_pci.h>
+ #endif
+diff --git a/include/asm-ppc/mpc8xx.h b/include/asm-ppc/mpc8xx.h
+index d3a2f2f..b9e3060 100644
+--- a/include/asm-ppc/mpc8xx.h
++++ b/include/asm-ppc/mpc8xx.h
+@@ -63,10 +63,6 @@
+ #include <platforms/lantec.h>
+ #endif
+
+-#if defined(CONFIG_MPC885ADS)
+-#include <platforms/mpc885ads.h>
+-#endif
+-
+ /* Currently, all 8xx boards that support a processor to PCI/ISA bridge
+ * use the same memory map.
+ */
+diff --git a/include/asm-ppc/ocp.h b/include/asm-ppc/ocp.h
+index 1379a4f..3909a2e 100644
+--- a/include/asm-ppc/ocp.h
++++ b/include/asm-ppc/ocp.h
+@@ -31,7 +31,6 @@
+
+ #include <asm/mmu.h>
+ #include <asm/ocp_ids.h>
+-#include <asm/semaphore.h>
+
+ #ifdef CONFIG_PPC_OCP
+
+diff --git a/include/asm-s390/cio.h b/include/asm-s390/cio.h
+index 123b557..0818ecd 100644
+--- a/include/asm-s390/cio.h
++++ b/include/asm-s390/cio.h
+@@ -397,6 +397,10 @@ struct cio_iplinfo {
+
+ extern int cio_get_iplinfo(struct cio_iplinfo *iplinfo);
+
++/* Function from drivers/s390/cio/chsc.c */
++int chsc_sstpc(void *page, unsigned int op, u16 ctrl);
++int chsc_sstpi(void *page, void *result, size_t size);
++
+ #endif
+
+ #endif
+diff --git a/include/asm-s390/cpu.h b/include/asm-s390/cpu.h
+index 352dde1..e5a6a9b 100644
+--- a/include/asm-s390/cpu.h
++++ b/include/asm-s390/cpu.h
+@@ -22,4 +22,12 @@ struct s390_idle_data {
+
+ DECLARE_PER_CPU(struct s390_idle_data, s390_idle);
+
++void s390_idle_leave(void);
++
++static inline void s390_idle_check(void)
++{
++ if ((&__get_cpu_var(s390_idle))->in_idle)
++ s390_idle_leave();
++}
++
+ #endif /* _ASM_S390_CPU_H_ */
+diff --git a/include/asm-s390/debug.h b/include/asm-s390/debug.h
+index c00dd2b..335baf4 100644
+--- a/include/asm-s390/debug.h
++++ b/include/asm-s390/debug.h
+@@ -73,6 +73,7 @@ typedef struct debug_info {
+ struct dentry* debugfs_entries[DEBUG_MAX_VIEWS];
+ struct debug_view* views[DEBUG_MAX_VIEWS];
+ char name[DEBUG_MAX_NAME_LEN];
++ mode_t mode;
+ } debug_info_t;
+
+ typedef int (debug_header_proc_t) (debug_info_t* id,
+@@ -122,6 +123,10 @@ debug_entry_t* debug_exception_common(debug_info_t* id, int level,
+ debug_info_t* debug_register(char* name, int pages, int nr_areas,
+ int buf_size);
+
++debug_info_t *debug_register_mode(char *name, int pages, int nr_areas,
++ int buf_size, mode_t mode, uid_t uid,
++ gid_t gid);
++
+ void debug_unregister(debug_info_t* id);
+
+ void debug_set_level(debug_info_t* id, int new_level);
+diff --git a/include/asm-s390/extmem.h b/include/asm-s390/extmem.h
+index c8802c9..33837d7 100644
+--- a/include/asm-s390/extmem.h
++++ b/include/asm-s390/extmem.h
+@@ -22,11 +22,12 @@
+ #define SEGMENT_SHARED 0
+ #define SEGMENT_EXCLUSIVE 1
+
+-extern int segment_load (char *name,int segtype,unsigned long *addr,unsigned long *length);
+-extern void segment_unload(char *name);
+-extern void segment_save(char *name);
+-extern int segment_type (char* name);
+-extern int segment_modify_shared (char *name, int do_nonshared);
++int segment_load (char *name, int segtype, unsigned long *addr, unsigned long *length);
++void segment_unload(char *name);
++void segment_save(char *name);
++int segment_type (char* name);
++int segment_modify_shared (char *name, int do_nonshared);
++void segment_warning(int rc, char *seg_name);
+
+ #endif
+ #endif
+diff --git a/include/asm-s390/hardirq.h b/include/asm-s390/hardirq.h
+index 31beb18..4b7cb96 100644
+--- a/include/asm-s390/hardirq.h
++++ b/include/asm-s390/hardirq.h
+@@ -32,6 +32,6 @@ typedef struct {
+
+ #define HARDIRQ_BITS 8
+
+-extern void account_ticks(u64 time);
++void clock_comparator_work(void);
+
+ #endif /* __ASM_HARDIRQ_H */
+diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h
+index 801a6fd..5de3efb 100644
+--- a/include/asm-s390/lowcore.h
++++ b/include/asm-s390/lowcore.h
+@@ -56,6 +56,8 @@
+ #define __LC_IO_INT_WORD 0x0C0
+ #define __LC_MCCK_CODE 0x0E8
+
++#define __LC_LAST_BREAK 0x110
++
+ #define __LC_RETURN_PSW 0x200
+
+ #define __LC_SAVE_AREA 0xC00
+@@ -80,7 +82,6 @@
+ #define __LC_CPUID 0xC60
+ #define __LC_CPUADDR 0xC68
+ #define __LC_IPLDEV 0xC7C
+-#define __LC_JIFFY_TIMER 0xC80
+ #define __LC_CURRENT 0xC90
+ #define __LC_INT_CLOCK 0xC98
+ #else /* __s390x__ */
+@@ -103,7 +104,6 @@
+ #define __LC_CPUID 0xD80
+ #define __LC_CPUADDR 0xD88
+ #define __LC_IPLDEV 0xDB8
+-#define __LC_JIFFY_TIMER 0xDC0
+ #define __LC_CURRENT 0xDD8
+ #define __LC_INT_CLOCK 0xDE8
+ #endif /* __s390x__ */
+@@ -276,7 +276,7 @@ struct _lowcore
+ /* entry.S sensitive area end */
+
+ /* SMP info area: defined by DJB */
+- __u64 jiffy_timer; /* 0xc80 */
++ __u64 clock_comparator; /* 0xc80 */
+ __u32 ext_call_fast; /* 0xc88 */
+ __u32 percpu_offset; /* 0xc8c */
+ __u32 current_task; /* 0xc90 */
+@@ -368,11 +368,12 @@ struct _lowcore
+ /* entry.S sensitive area end */
+
+ /* SMP info area: defined by DJB */
+- __u64 jiffy_timer; /* 0xdc0 */
++ __u64 clock_comparator; /* 0xdc0 */
+ __u64 ext_call_fast; /* 0xdc8 */
+ __u64 percpu_offset; /* 0xdd0 */
+ __u64 current_task; /* 0xdd8 */
+- __u64 softirq_pending; /* 0xde0 */
++ __u32 softirq_pending; /* 0xde0 */
++ __u32 pad_0x0de4; /* 0xde4 */
+ __u64 int_clock; /* 0xde8 */
+ __u8 pad12[0xe00-0xdf0]; /* 0xdf0 */
+
+diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
+index 51d8891..8eaf343 100644
+--- a/include/asm-s390/processor.h
++++ b/include/asm-s390/processor.h
+@@ -175,6 +175,13 @@ extern void task_show_regs(struct seq_file *m, struct task_struct *task);
+ extern void show_registers(struct pt_regs *regs);
+ extern void show_code(struct pt_regs *regs);
+ extern void show_trace(struct task_struct *task, unsigned long *sp);
++#ifdef CONFIG_64BIT
++extern void show_last_breaking_event(struct pt_regs *regs);
++#else
++static inline void show_last_breaking_event(struct pt_regs *regs)
++{
++}
++#endif
+
+ unsigned long get_wchan(struct task_struct *p);
+ #define task_pt_regs(tsk) ((struct pt_regs *) \
+diff --git a/include/asm-s390/semaphore.h b/include/asm-s390/semaphore.h
+index 0e7001a..d9b2034 100644
+--- a/include/asm-s390/semaphore.h
++++ b/include/asm-s390/semaphore.h
+@@ -1,107 +1 @@
+-/*
+- * include/asm-s390/semaphore.h
+- *
+- * S390 version
+- * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+- *
+- * Derived from "include/asm-i386/semaphore.h"
+- * (C) Copyright 1996 Linus Torvalds
+- */
+-
+-#ifndef _S390_SEMAPHORE_H
+-#define _S390_SEMAPHORE_H
+-
+-#include <asm/system.h>
+-#include <asm/atomic.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-struct semaphore {
+- /*
+- * Note that any negative value of count is equivalent to 0,
+- * but additionally indicates that some process(es) might be
+- * sleeping on `wait'.
+- */
+- atomic_t count;
+- wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name,count) \
+- { ATOMIC_INIT(count), __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) }
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+- struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+- atomic_set(&sem->count, val);
+- init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+- sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+- sema_init(sem, 0);
+-}
+-
+-asmlinkage void __down(struct semaphore * sem);
+-asmlinkage int __down_interruptible(struct semaphore * sem);
+-asmlinkage int __down_trylock(struct semaphore * sem);
+-asmlinkage void __up(struct semaphore * sem);
+-
+-static inline void down(struct semaphore * sem)
+-{
+- might_sleep();
+- if (atomic_dec_return(&sem->count) < 0)
+- __down(sem);
+-}
+-
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+- int ret = 0;
+-
+- might_sleep();
+- if (atomic_dec_return(&sem->count) < 0)
+- ret = __down_interruptible(sem);
+- return ret;
+-}
+-
+-static inline int down_trylock(struct semaphore * sem)
+-{
+- int old_val, new_val;
+-
+- /*
+- * This inline assembly atomically implements the equivalent
+- * to the following C code:
+- * old_val = sem->count.counter;
+- * if ((new_val = old_val) > 0)
+- * sem->count.counter = --new_val;
+- * In the ppc code this is called atomic_dec_if_positive.
+- */
+- asm volatile(
+- " l %0,0(%3)\n"
+- "0: ltr %1,%0\n"
+- " jle 1f\n"
+- " ahi %1,-1\n"
+- " cs %0,%1,0(%3)\n"
+- " jl 0b\n"
+- "1:"
+- : "=&d" (old_val), "=&d" (new_val), "=m" (sem->count.counter)
+- : "a" (&sem->count.counter), "m" (sem->count.counter)
+- : "cc", "memory");
+- return old_val <= 0;
+-}
+-
+-static inline void up(struct semaphore * sem)
+-{
+- if (atomic_inc_return(&sem->count) <= 0)
+- __up(sem);
+-}
+-
+-#endif
++#include <linux/semaphore.h>
+diff --git a/include/asm-s390/smp.h b/include/asm-s390/smp.h
+index c7b7432..6f3821a 100644
+--- a/include/asm-s390/smp.h
++++ b/include/asm-s390/smp.h
+@@ -90,6 +90,9 @@ extern void __cpu_die (unsigned int cpu);
+ extern void cpu_die (void) __attribute__ ((noreturn));
+ extern int __cpu_up (unsigned int cpu);
+
++extern struct mutex smp_cpu_state_mutex;
++extern int smp_cpu_polarization[];
++
+ extern int smp_call_function_mask(cpumask_t mask, void (*func)(void *),
+ void *info, int wait);
+ #endif
+diff --git a/include/asm-s390/sysinfo.h b/include/asm-s390/sysinfo.h
+new file mode 100644
+index 0000000..abe10ae
+--- /dev/null
++++ b/include/asm-s390/sysinfo.h
+@@ -0,0 +1,116 @@
++/*
++ * definition for store system information stsi
++ *
++ * Copyright IBM Corp. 2001,2008
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License (version 2 only)
++ * as published by the Free Software Foundation.
++ *
++ * Author(s): Ulrich Weigand <weigand at de.ibm.com>
++ * Christian Borntraeger <borntraeger at de.ibm.com>
++ */
++
++struct sysinfo_1_1_1 {
++ char reserved_0[32];
++ char manufacturer[16];
++ char type[4];
++ char reserved_1[12];
++ char model_capacity[16];
++ char sequence[16];
++ char plant[4];
++ char model[16];
++ char model_perm_cap[16];
++ char model_temp_cap[16];
++ char model_cap_rating[4];
++ char model_perm_cap_rating[4];
++ char model_temp_cap_rating[4];
++};
++
++struct sysinfo_1_2_1 {
++ char reserved_0[80];
++ char sequence[16];
++ char plant[4];
++ char reserved_1[2];
++ unsigned short cpu_address;
++};
++
++struct sysinfo_1_2_2 {
++ char format;
++ char reserved_0[1];
++ unsigned short acc_offset;
++ char reserved_1[24];
++ unsigned int secondary_capability;
++ unsigned int capability;
++ unsigned short cpus_total;
++ unsigned short cpus_configured;
++ unsigned short cpus_standby;
++ unsigned short cpus_reserved;
++ unsigned short adjustment[0];
++};
++
++struct sysinfo_1_2_2_extension {
++ unsigned int alt_capability;
++ unsigned short alt_adjustment[0];
++};
++
++struct sysinfo_2_2_1 {
++ char reserved_0[80];
++ char sequence[16];
++ char plant[4];
++ unsigned short cpu_id;
++ unsigned short cpu_address;
++};
++
++struct sysinfo_2_2_2 {
++ char reserved_0[32];
++ unsigned short lpar_number;
++ char reserved_1;
++ unsigned char characteristics;
++ unsigned short cpus_total;
++ unsigned short cpus_configured;
++ unsigned short cpus_standby;
++ unsigned short cpus_reserved;
++ char name[8];
++ unsigned int caf;
++ char reserved_2[16];
++ unsigned short cpus_dedicated;
++ unsigned short cpus_shared;
++};
++
++#define LPAR_CHAR_DEDICATED (1 << 7)
++#define LPAR_CHAR_SHARED (1 << 6)
++#define LPAR_CHAR_LIMITED (1 << 5)
++
++struct sysinfo_3_2_2 {
++ char reserved_0[31];
++ unsigned char count;
++ struct {
++ char reserved_0[4];
++ unsigned short cpus_total;
++ unsigned short cpus_configured;
++ unsigned short cpus_standby;
++ unsigned short cpus_reserved;
++ char name[8];
++ unsigned int caf;
++ char cpi[16];
++ char reserved_1[24];
++
++ } vm[8];
++};
++
++static inline int stsi(void *sysinfo, int fc, int sel1, int sel2)
++{
++ register int r0 asm("0") = (fc << 28) | sel1;
++ register int r1 asm("1") = sel2;
++
++ asm volatile(
++ " stsi 0(%2)\n"
++ "0: jz 2f\n"
++ "1: lhi %0,%3\n"
++ "2:\n"
++ EX_TABLE(0b, 1b)
++ : "+d" (r0) : "d" (r1), "a" (sysinfo), "K" (-ENOSYS)
++ : "cc", "memory");
++ return r0;
++}
+diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h
+index 15aba30..92098df 100644
+--- a/include/asm-s390/system.h
++++ b/include/asm-s390/system.h
+@@ -406,6 +406,8 @@ __set_psw_mask(unsigned long mask)
+ #define local_mcck_enable() __set_psw_mask(psw_kernel_bits)
+ #define local_mcck_disable() __set_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK)
+
++int stfle(unsigned long long *list, int doublewords);
++
+ #ifdef CONFIG_SMP
+
+ extern void smp_ctl_set_bit(int cr, int bit);
+diff --git a/include/asm-s390/timex.h b/include/asm-s390/timex.h
+index 98229db..d744c3d 100644
+--- a/include/asm-s390/timex.h
++++ b/include/asm-s390/timex.h
+@@ -62,16 +62,18 @@ static inline unsigned long long get_clock (void)
+ return clk;
+ }
+
+-static inline void get_clock_extended(void *dest)
++static inline unsigned long long get_clock_xt(void)
+ {
+- typedef struct { unsigned long long clk[2]; } __clock_t;
++ unsigned char clk[16];
+
+ #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
+- asm volatile("stcke %0" : "=Q" (*((__clock_t *)dest)) : : "cc");
++ asm volatile("stcke %0" : "=Q" (clk) : : "cc");
+ #else /* __GNUC__ */
+- asm volatile("stcke 0(%1)" : "=m" (*((__clock_t *)dest))
+- : "a" ((__clock_t *)dest) : "cc");
++ asm volatile("stcke 0(%1)" : "=m" (clk)
++ : "a" (clk) : "cc");
+ #endif /* __GNUC__ */
++
++ return *((unsigned long long *)&clk[1]);
+ }
+
+ static inline cycles_t get_cycles(void)
+@@ -81,5 +83,6 @@ static inline cycles_t get_cycles(void)
+
+ int get_sync_clock(unsigned long long *clock);
+ void init_cpu_timer(void);
++unsigned long long monotonic_clock(void);
+
+ #endif
+diff --git a/include/asm-s390/tlbflush.h b/include/asm-s390/tlbflush.h
+index 35fb4f9..9e57a93 100644
+--- a/include/asm-s390/tlbflush.h
++++ b/include/asm-s390/tlbflush.h
+@@ -13,12 +13,14 @@ static inline void __tlb_flush_local(void)
+ asm volatile("ptlb" : : : "memory");
+ }
+
++#ifdef CONFIG_SMP
+ /*
+ * Flush all tlb entries on all cpus.
+ */
++void smp_ptlb_all(void);
++
+ static inline void __tlb_flush_global(void)
+ {
+- extern void smp_ptlb_all(void);
+ register unsigned long reg2 asm("2");
+ register unsigned long reg3 asm("3");
+ register unsigned long reg4 asm("4");
+@@ -39,6 +41,25 @@ static inline void __tlb_flush_global(void)
+ : : "d" (reg2), "d" (reg3), "d" (reg4), "m" (dummy) : "cc" );
+ }
+
++static inline void __tlb_flush_full(struct mm_struct *mm)
++{
++ cpumask_t local_cpumask;
++
++ preempt_disable();
++ /*
++ * If the process only ran on the local cpu, do a local flush.
++ */
++ local_cpumask = cpumask_of_cpu(smp_processor_id());
++ if (cpus_equal(mm->cpu_vm_mask, local_cpumask))
++ __tlb_flush_local();
++ else
++ __tlb_flush_global();
++ preempt_enable();
++}
++#else
++#define __tlb_flush_full(mm) __tlb_flush_local()
++#endif
++
+ /*
+ * Flush all tlb entries of a page table on all cpus.
+ */
+@@ -51,8 +72,6 @@ static inline void __tlb_flush_idte(unsigned long asce)
+
+ static inline void __tlb_flush_mm(struct mm_struct * mm)
+ {
+- cpumask_t local_cpumask;
+-
+ if (unlikely(cpus_empty(mm->cpu_vm_mask)))
+ return;
+ /*
+@@ -69,16 +88,7 @@ static inline void __tlb_flush_mm(struct mm_struct * mm)
+ mm->context.asce_bits);
+ return;
+ }
+- preempt_disable();
+- /*
+- * If the process only ran on the local cpu, do a local flush.
+- */
+- local_cpumask = cpumask_of_cpu(smp_processor_id());
+- if (cpus_equal(mm->cpu_vm_mask, local_cpumask))
+- __tlb_flush_local();
+- else
+- __tlb_flush_global();
+- preempt_enable();
++ __tlb_flush_full(mm);
+ }
+
+ static inline void __tlb_flush_mm_cond(struct mm_struct * mm)
+diff --git a/include/asm-s390/topology.h b/include/asm-s390/topology.h
+index 613aa64..8e97b06 100644
+--- a/include/asm-s390/topology.h
++++ b/include/asm-s390/topology.h
+@@ -1,6 +1,29 @@
+ #ifndef _ASM_S390_TOPOLOGY_H
+ #define _ASM_S390_TOPOLOGY_H
+
++#include <linux/cpumask.h>
++
++#define mc_capable() (1)
++
++cpumask_t cpu_coregroup_map(unsigned int cpu);
++
++int topology_set_cpu_management(int fc);
++void topology_schedule_update(void);
++
++#define POLARIZATION_UNKNWN (-1)
++#define POLARIZATION_HRZ (0)
++#define POLARIZATION_VL (1)
++#define POLARIZATION_VM (2)
++#define POLARIZATION_VH (3)
++
++#ifdef CONFIG_SMP
++void s390_init_cpu_topology(void);
++#else
++static inline void s390_init_cpu_topology(void)
++{
++};
++#endif
++
+ #include <asm-generic/topology.h>
+
+ #endif /* _ASM_S390_TOPOLOGY_H */
+diff --git a/include/asm-sh/bugs.h b/include/asm-sh/bugs.h
+index cfda7d5..121b2ec 100644
+--- a/include/asm-sh/bugs.h
++++ b/include/asm-sh/bugs.h
+@@ -25,7 +25,7 @@ static void __init check_bugs(void)
+ case CPU_SH7619:
+ *p++ = '2';
+ break;
+- case CPU_SH7203 ... CPU_SH7263:
++ case CPU_SH7203 ... CPU_MXG:
+ *p++ = '2';
+ *p++ = 'a';
+ break;
+diff --git a/include/asm-sh/cpu-sh4/freq.h b/include/asm-sh/cpu-sh4/freq.h
+index ec028c6..da46e67 100644
+--- a/include/asm-sh/cpu-sh4/freq.h
++++ b/include/asm-sh/cpu-sh4/freq.h
+@@ -10,14 +10,14 @@
+ #ifndef __ASM_CPU_SH4_FREQ_H
+ #define __ASM_CPU_SH4_FREQ_H
+
+-#if defined(CONFIG_CPU_SUBTYPE_SH7722) || defined(CONFIG_CPU_SUBTYPE_SH7366)
++#if defined(CONFIG_CPU_SUBTYPE_SH7722) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7723) || \
++ defined(CONFIG_CPU_SUBTYPE_SH7366)
+ #define FRQCR 0xa4150000
+ #define VCLKCR 0xa4150004
+ #define SCLKACR 0xa4150008
+ #define SCLKBCR 0xa415000c
+-#if defined(CONFIG_CPU_SUBTYPE_SH7722)
+ #define IrDACLKCR 0xa4150010
+-#endif
+ #elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7780)
+ #define FRQCR 0xffc80000
+diff --git a/include/asm-sh/cpu-sh4/rtc.h b/include/asm-sh/cpu-sh4/rtc.h
+index f3d0f53..25b1e6a 100644
+--- a/include/asm-sh/cpu-sh4/rtc.h
++++ b/include/asm-sh/cpu-sh4/rtc.h
+@@ -1,7 +1,12 @@
+ #ifndef __ASM_SH_CPU_SH4_RTC_H
+ #define __ASM_SH_CPU_SH4_RTC_H
+
++#ifdef CONFIG_CPU_SUBTYPE_SH7723
++#define rtc_reg_size sizeof(u16)
++#else
+ #define rtc_reg_size sizeof(u32)
++#endif
++
+ #define RTC_BIT_INVERTED 0x40 /* bug on SH7750, SH7750S */
+ #define RTC_DEF_CAPABILITIES RTC_CAP_4_DIGIT_YEAR
+
+diff --git a/include/asm-sh/i2c-sh7760.h b/include/asm-sh/i2c-sh7760.h
+new file mode 100644
+index 0000000..2418211
+--- /dev/null
++++ b/include/asm-sh/i2c-sh7760.h
+@@ -0,0 +1,22 @@
++/*
++ * MMIO/IRQ and platform data for SH7760 I2C channels
++ */
++
++#ifndef _I2C_SH7760_H_
++#define _I2C_SH7760_H_
++
++#define SH7760_I2C_DEVNAME "sh7760-i2c"
++
++#define SH7760_I2C0_MMIO 0xFE140000
++#define SH7760_I2C0_MMIOEND 0xFE14003B
++#define SH7760_I2C0_IRQ 62
++
++#define SH7760_I2C1_MMIO 0xFE150000
++#define SH7760_I2C1_MMIOEND 0xFE15003B
++#define SH7760_I2C1_IRQ 63
++
++struct sh7760_i2c_platdata {
++ unsigned int speed_khz;
++};
++
++#endif
+diff --git a/include/asm-sh/ide.h b/include/asm-sh/ide.h
+index 9f8e914..58e0bdd 100644
+--- a/include/asm-sh/ide.h
++++ b/include/asm-sh/ide.h
+@@ -14,9 +14,6 @@
+
+ #ifdef __KERNEL__
+
+-
+-#define ide_default_io_ctl(base) (0)
+-
+ #include <asm-generic/ide_iops.h>
+
+ #endif /* __KERNEL__ */
+diff --git a/include/asm-sh/migor.h b/include/asm-sh/migor.h
+new file mode 100644
+index 0000000..2329363
+--- /dev/null
++++ b/include/asm-sh/migor.h
+@@ -0,0 +1,58 @@
++#ifndef __ASM_SH_MIGOR_H
++#define __ASM_SH_MIGOR_H
++
++/*
++ * linux/include/asm-sh/migor.h
++ *
++ * Copyright (C) 2008 Renesas Solutions
++ *
++ * Portions Copyright (C) 2007 Nobuhiro Iwamatsu
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ */
++#include <asm/addrspace.h>
++
++/* GPIO */
++#define MSTPCR0 0xa4150030
++#define MSTPCR1 0xa4150034
++#define MSTPCR2 0xa4150038
++
++#define PORT_PACR 0xa4050100
++#define PORT_PDCR 0xa4050106
++#define PORT_PECR 0xa4050108
++#define PORT_PHCR 0xa405010e
++#define PORT_PJCR 0xa4050110
++#define PORT_PKCR 0xa4050112
++#define PORT_PLCR 0xa4050114
++#define PORT_PMCR 0xa4050116
++#define PORT_PRCR 0xa405011c
++#define PORT_PWCR 0xa4050146
++#define PORT_PXCR 0xa4050148
++#define PORT_PYCR 0xa405014a
++#define PORT_PZCR 0xa405014c
++#define PORT_PADR 0xa4050120
++#define PORT_PWDR 0xa4050166
++
++#define PORT_HIZCRA 0xa4050158
++#define PORT_HIZCRC 0xa405015c
++
++#define PORT_MSELCRB 0xa4050182
++
++#define MSTPCR1 0xa4150034
++#define MSTPCR2 0xa4150038
++
++#define PORT_PSELA 0xa405014e
++#define PORT_PSELB 0xa4050150
++#define PORT_PSELC 0xa4050152
++#define PORT_PSELD 0xa4050154
++
++#define PORT_HIZCRA 0xa4050158
++#define PORT_HIZCRB 0xa405015a
++#define PORT_HIZCRC 0xa405015c
++
++#define BSC_CS6ABCR 0xfec1001c
++
++#endif /* __ASM_SH_MIGOR_H */
+diff --git a/include/asm-sh/mpc1211/pci.h b/include/asm-sh/mpc1211/pci.h
+index 5d3712c..d9162c5 100644
+--- a/include/asm-sh/mpc1211/pci.h
++++ b/include/asm-sh/mpc1211/pci.h
+@@ -24,8 +24,6 @@
+ #define PCI_PROBE_BIOS 1
+ #define PCI_PROBE_CONF1 2
+ #define PCI_PROBE_CONF2 4
+-#define PCI_NO_SORT 0x100
+-#define PCI_BIOS_SORT 0x200
+ #define PCI_NO_CHECKS 0x400
+ #define PCI_ASSIGN_ROMS 0x1000
+ #define PCI_BIOS_IRQ_SCAN 0x2000
+diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h
+index ec707b9..b7c7ce8 100644
+--- a/include/asm-sh/processor.h
++++ b/include/asm-sh/processor.h
+@@ -16,7 +16,7 @@ enum cpu_type {
+ CPU_SH7619,
+
+ /* SH-2A types */
+- CPU_SH7203, CPU_SH7206, CPU_SH7263,
++ CPU_SH7203, CPU_SH7206, CPU_SH7263, CPU_MXG,
+
+ /* SH-3 types */
+ CPU_SH7705, CPU_SH7706, CPU_SH7707,
+@@ -29,7 +29,8 @@ enum cpu_type {
+ CPU_SH7760, CPU_SH4_202, CPU_SH4_501,
+
+ /* SH-4A types */
+- CPU_SH7763, CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785, CPU_SHX3,
++ CPU_SH7763, CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785,
++ CPU_SH7723, CPU_SHX3,
+
+ /* SH4AL-DSP types */
+ CPU_SH7343, CPU_SH7722, CPU_SH7366,
+diff --git a/include/asm-sh/r7780rp.h b/include/asm-sh/r7780rp.h
+index 1770460..a33838f 100644
+--- a/include/asm-sh/r7780rp.h
++++ b/include/asm-sh/r7780rp.h
+@@ -55,11 +55,11 @@
+ #define PA_SCSPTR1 (PA_BCR+0x0524) /* SCIF1 Serial Port control */
+ #define PA_SCLSR1 (PA_BCR+0x0528) /* SCIF1 Line Status control */
+ #define PA_SCRER1 (PA_BCR+0x052c) /* SCIF1 Serial Error control */
+-#define PA_ICCR (PA_BCR+0x0600) /* Serial control */
+-#define PA_SAR (PA_BCR+0x0602) /* Serial Slave control */
+-#define PA_MDR (PA_BCR+0x0604) /* Serial Mode control */
+-#define PA_ADR1 (PA_BCR+0x0606) /* Serial Address1 control */
+-#define PA_DAR1 (PA_BCR+0x0646) /* Serial Data1 control */
++#define PA_SMCR (PA_BCR+0x0600) /* 2-wire Serial control */
++#define PA_SMSMADR (PA_BCR+0x0602) /* 2-wire Serial Slave control */
++#define PA_SMMR (PA_BCR+0x0604) /* 2-wire Serial Mode control */
++#define PA_SMSADR1 (PA_BCR+0x0606) /* 2-wire Serial Address1 control */
++#define PA_SMTRDR1 (PA_BCR+0x0646) /* 2-wire Serial Data1 control */
+ #define PA_VERREG (PA_BCR+0x0700) /* FPGA Version Register */
+ #define PA_POFF (PA_BCR+0x0800) /* System Power Off control */
+ #define PA_PMR (PA_BCR+0x0900) /* */
+@@ -107,11 +107,11 @@
+ #define PA_SCFCR (PA_BCR+0x040c) /* SCIF FIFO control */
+ #define PA_SCFDR (PA_BCR+0x040e) /* SCIF FIFO data control */
+ #define PA_SCLSR (PA_BCR+0x0412) /* SCIF Line Status control */
+-#define PA_ICCR (PA_BCR+0x0500) /* Serial control */
+-#define PA_SAR (PA_BCR+0x0502) /* Serial Slave control */
+-#define PA_MDR (PA_BCR+0x0504) /* Serial Mode control */
+-#define PA_ADR1 (PA_BCR+0x0506) /* Serial Address1 control */
+-#define PA_DAR1 (PA_BCR+0x0546) /* Serial Data1 control */
++#define PA_SMCR (PA_BCR+0x0500) /* 2-wire Serial control */
++#define PA_SMSMADR (PA_BCR+0x0502) /* 2-wire Serial Slave control */
++#define PA_SMMR (PA_BCR+0x0504) /* 2-wire Serial Mode control */
++#define PA_SMSADR1 (PA_BCR+0x0506) /* 2-wire Serial Address1 control */
++#define PA_SMTRDR1 (PA_BCR+0x0546) /* 2-wire Serial Data1 control */
+ #define PA_VERREG (PA_BCR+0x0600) /* FPGA Version Register */
+
+ #define PA_AX88796L 0xa5800400 /* AX88796L Area */
+@@ -190,6 +190,8 @@
+ #define IRQ_TP (HL_FPGA_IRQ_BASE + 12)
+ #define IRQ_RTC (HL_FPGA_IRQ_BASE + 13)
+ #define IRQ_TH_ALERT (HL_FPGA_IRQ_BASE + 14)
++#define IRQ_SCIF0 (HL_FPGA_IRQ_BASE + 15)
++#define IRQ_SCIF1 (HL_FPGA_IRQ_BASE + 16)
+
+ unsigned char *highlander_init_irq_r7780mp(void);
+ unsigned char *highlander_init_irq_r7780rp(void);
+diff --git a/include/asm-sh/se7721.h b/include/asm-sh/se7721.h
+new file mode 100644
+index 0000000..b957f60
+--- /dev/null
++++ b/include/asm-sh/se7721.h
+@@ -0,0 +1,70 @@
++/*
++ * Copyright (C) 2008 Renesas Solutions Corp.
++ *
++ * Hitachi UL SolutionEngine 7721 Support.
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ */
++
++#ifndef __ASM_SH_SE7721_H
++#define __ASM_SH_SE7721_H
++#include <asm/addrspace.h>
++
++/* Box specific addresses. */
++#define SE_AREA0_WIDTH 2 /* Area0: 32bit */
++#define PA_ROM 0xa0000000 /* EPROM */
++#define PA_ROM_SIZE 0x00200000 /* EPROM size 2M byte */
++#define PA_FROM 0xa1000000 /* Flash-ROM */
++#define PA_FROM_SIZE 0x01000000 /* Flash-ROM size 16M byte */
++#define PA_EXT1 0xa4000000
++#define PA_EXT1_SIZE 0x04000000
++#define PA_SDRAM 0xaC000000 /* SDRAM(Area3) 64MB */
++#define PA_SDRAM_SIZE 0x04000000
++
++#define PA_EXT4 0xb0000000
++#define PA_EXT4_SIZE 0x04000000
++
++#define PA_PERIPHERAL 0xB8000000
++
++#define PA_PCIC PA_PERIPHERAL
++#define PA_MRSHPC (PA_PERIPHERAL + 0x003fffe0)
++#define PA_MRSHPC_MW1 (PA_PERIPHERAL + 0x00400000)
++#define PA_MRSHPC_MW2 (PA_PERIPHERAL + 0x00500000)
++#define PA_MRSHPC_IO (PA_PERIPHERAL + 0x00600000)
++#define MRSHPC_OPTION (PA_MRSHPC + 6)
++#define MRSHPC_CSR (PA_MRSHPC + 8)
++#define MRSHPC_ISR (PA_MRSHPC + 10)
++#define MRSHPC_ICR (PA_MRSHPC + 12)
++#define MRSHPC_CPWCR (PA_MRSHPC + 14)
++#define MRSHPC_MW0CR1 (PA_MRSHPC + 16)
++#define MRSHPC_MW1CR1 (PA_MRSHPC + 18)
++#define MRSHPC_IOWCR1 (PA_MRSHPC + 20)
++#define MRSHPC_MW0CR2 (PA_MRSHPC + 22)
++#define MRSHPC_MW1CR2 (PA_MRSHPC + 24)
++#define MRSHPC_IOWCR2 (PA_MRSHPC + 26)
++#define MRSHPC_CDCR (PA_MRSHPC + 28)
++#define MRSHPC_PCIC_INFO (PA_MRSHPC + 30)
++
++#define PA_LED 0xB6800000 /* 8bit LED */
++#define PA_FPGA 0xB7000000 /* FPGA base address */
++
++#define MRSHPC_IRQ0 10
++
++#define FPGA_ILSR1 (PA_FPGA + 0x02)
++#define FPGA_ILSR2 (PA_FPGA + 0x03)
++#define FPGA_ILSR3 (PA_FPGA + 0x04)
++#define FPGA_ILSR4 (PA_FPGA + 0x05)
++#define FPGA_ILSR5 (PA_FPGA + 0x06)
++#define FPGA_ILSR6 (PA_FPGA + 0x07)
++#define FPGA_ILSR7 (PA_FPGA + 0x08)
++#define FPGA_ILSR8 (PA_FPGA + 0x09)
++
++void init_se7721_IRQ(void);
++
++#define __IO_PREFIX se7721
++#include <asm/io_generic.h>
++
++#endif /* __ASM_SH_SE7721_H */
+diff --git a/include/asm-sh/se7722.h b/include/asm-sh/se7722.h
+index e0e89fc..3690fe5 100644
+--- a/include/asm-sh/se7722.h
++++ b/include/asm-sh/se7722.h
+@@ -77,6 +77,8 @@
+ #define PORT_PSELA 0xA405014EUL
+ #define PORT_PYCR 0xA405014AUL
+ #define PORT_PZCR 0xA405014CUL
++#define PORT_HIZCRA 0xA4050158UL
++#define PORT_HIZCRC 0xA405015CUL
+
+ /* IRQ */
+ #define IRQ0_IRQ 32
+diff --git a/include/asm-sh/semaphore-helper.h b/include/asm-sh/semaphore-helper.h
+deleted file mode 100644
+index bd8230c..0000000
+--- a/include/asm-sh/semaphore-helper.h
++++ /dev/null
+@@ -1,89 +0,0 @@
+-#ifndef __ASM_SH_SEMAPHORE_HELPER_H
+-#define __ASM_SH_SEMAPHORE_HELPER_H
+-
+-/*
+- * SMP- and interrupt-safe semaphores helper functions.
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- * (C) Copyright 1999 Andrea Arcangeli
+- */
+-
+-/*
+- * These two _must_ execute atomically wrt each other.
+- *
+- * This is trivially done with load_locked/store_cond,
+- * which we have. Let the rest of the losers suck eggs.
+- */
+-static __inline__ void wake_one_more(struct semaphore * sem)
+-{
+- atomic_inc((atomic_t *)&sem->sleepers);
+-}
+-
+-static __inline__ int waking_non_zero(struct semaphore *sem)
+-{
+- unsigned long flags;
+- int ret = 0;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- if (sem->sleepers > 0) {
+- sem->sleepers--;
+- ret = 1;
+- }
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+- return ret;
+-}
+-
+-/*
+- * waking_non_zero_interruptible:
+- * 1 got the lock
+- * 0 go to sleep
+- * -EINTR interrupted
+- *
+- * We must undo the sem->count down_interruptible() increment while we are
+- * protected by the spinlock in order to make atomic this atomic_inc() with the
+- * atomic_read() in wake_one_more(), otherwise we can race. -arca
+- */
+-static __inline__ int waking_non_zero_interruptible(struct semaphore *sem,
+- struct task_struct *tsk)
+-{
+- unsigned long flags;
+- int ret = 0;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- if (sem->sleepers > 0) {
+- sem->sleepers--;
+- ret = 1;
+- } else if (signal_pending(tsk)) {
+- atomic_inc(&sem->count);
+- ret = -EINTR;
+- }
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+- return ret;
+-}
+-
+-/*
+- * waking_non_zero_trylock:
+- * 1 failed to lock
+- * 0 got the lock
+- *
+- * We must undo the sem->count down_trylock() increment while we are
+- * protected by the spinlock in order to make atomic this atomic_inc() with the
+- * atomic_read() in wake_one_more(), otherwise we can race. -arca
+- */
+-static __inline__ int waking_non_zero_trylock(struct semaphore *sem)
+-{
+- unsigned long flags;
+- int ret = 1;
+-
+- spin_lock_irqsave(&semaphore_wake_lock, flags);
+- if (sem->sleepers <= 0)
+- atomic_inc(&sem->count);
+- else {
+- sem->sleepers--;
+- ret = 0;
+- }
+- spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+- return ret;
+-}
+-
+-#endif /* __ASM_SH_SEMAPHORE_HELPER_H */
+diff --git a/include/asm-sh/semaphore.h b/include/asm-sh/semaphore.h
+index 9e5a37c..d9b2034 100644
+--- a/include/asm-sh/semaphore.h
++++ b/include/asm-sh/semaphore.h
+@@ -1,115 +1 @@
+-#ifndef __ASM_SH_SEMAPHORE_H
+-#define __ASM_SH_SEMAPHORE_H
+-
+-#include <linux/linkage.h>
+-
+-#ifdef __KERNEL__
+-/*
+- * SMP- and interrupt-safe semaphores.
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- *
+- * SuperH verison by Niibe Yutaka
+- * (Currently no asm implementation but generic C code...)
+- */
+-
+-#include <linux/spinlock.h>
+-#include <linux/rwsem.h>
+-#include <linux/wait.h>
+-
+-#include <asm/system.h>
+-#include <asm/atomic.h>
+-
+-struct semaphore {
+- atomic_t count;
+- int sleepers;
+- wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n) \
+-{ \
+- .count = ATOMIC_INIT(n), \
+- .sleepers = 0, \
+- .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+- struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+-/*
+- * *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+- *
+- * i'd rather use the more flexible initialization above, but sadly
+- * GCC 2.7.2.3 emits a bogus warning. EGCS doesn't. Oh well.
+- */
+- atomic_set(&sem->count, val);
+- sem->sleepers = 0;
+- init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+- sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+- sema_init(sem, 0);
+-}
+-
+-#if 0
+-asmlinkage void __down_failed(void /* special register calling convention */);
+-asmlinkage int __down_failed_interruptible(void /* params in registers */);
+-asmlinkage int __down_failed_trylock(void /* params in registers */);
+-asmlinkage void __up_wakeup(void /* special register calling convention */);
+-#endif
+-
+-asmlinkage void __down(struct semaphore * sem);
+-asmlinkage int __down_interruptible(struct semaphore * sem);
+-asmlinkage int __down_trylock(struct semaphore * sem);
+-asmlinkage void __up(struct semaphore * sem);
+-
+-extern spinlock_t semaphore_wake_lock;
+-
+-static inline void down(struct semaphore * sem)
+-{
+- might_sleep();
+- if (atomic_dec_return(&sem->count) < 0)
+- __down(sem);
+-}
+-
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+- int ret = 0;
+-
+- might_sleep();
+- if (atomic_dec_return(&sem->count) < 0)
+- ret = __down_interruptible(sem);
+- return ret;
+-}
+-
+-static inline int down_trylock(struct semaphore * sem)
+-{
+- int ret = 0;
+-
+- if (atomic_dec_return(&sem->count) < 0)
+- ret = __down_trylock(sem);
+- return ret;
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- */
+-static inline void up(struct semaphore * sem)
+-{
+- if (atomic_inc_return(&sem->count) <= 0)
+- __up(sem);
+-}
+-
+-#endif
+-#endif /* __ASM_SH_SEMAPHORE_H */
++#include <linux/semaphore.h>
+diff --git a/include/asm-sh/sh_keysc.h b/include/asm-sh/sh_keysc.h
+new file mode 100644
+index 0000000..b5a4dd5
+--- /dev/null
++++ b/include/asm-sh/sh_keysc.h
+@@ -0,0 +1,13 @@
++#ifndef __ASM_KEYSC_H__
++#define __ASM_KEYSC_H__
++
++#define SH_KEYSC_MAXKEYS 30
++
++struct sh_keysc_info {
++ enum { SH_KEYSC_MODE_1, SH_KEYSC_MODE_2, SH_KEYSC_MODE_3 } mode;
++ int scan_timing; /* 0 -> 7, see KYCR1, SCN[2:0] */
++ int delay;
++ int keycodes[SH_KEYSC_MAXKEYS];
++};
++
++#endif /* __ASM_KEYSC_H__ */
+diff --git a/include/asm-sh/system.h b/include/asm-sh/system.h
+index 5145aa2..e65b6b8 100644
+--- a/include/asm-sh/system.h
++++ b/include/asm-sh/system.h
+@@ -146,6 +146,8 @@ extern unsigned int instruction_size(unsigned int insn);
+
+ extern unsigned long cached_to_uncached;
+
++extern struct dentry *sh_debugfs_root;
++
+ /* XXX
+ * disable hlt during certain critical i/o operations
+ */
+diff --git a/include/asm-sh/topology.h b/include/asm-sh/topology.h
+index f402a3b..34cdb28 100644
+--- a/include/asm-sh/topology.h
++++ b/include/asm-sh/topology.h
+@@ -16,7 +16,7 @@
+ .cache_nice_tries = 2, \
+ .busy_idx = 3, \
+ .idle_idx = 2, \
+- .newidle_idx = 0, \
++ .newidle_idx = 2, \
+ .wake_idx = 1, \
+ .forkexec_idx = 1, \
+ .flags = SD_LOAD_BALANCE \
+diff --git a/include/asm-sh/uaccess_32.h b/include/asm-sh/uaccess_32.h
+index c0318b6..1e41fda 100644
+--- a/include/asm-sh/uaccess_32.h
++++ b/include/asm-sh/uaccess_32.h
+@@ -55,13 +55,10 @@ static inline void set_fs(mm_segment_t s)
+ * If we don't have an MMU (or if its disabled) the only thing we really have
+ * to look out for is if the address resides somewhere outside of what
+ * available RAM we have.
+- *
+- * TODO: This check could probably also stand to be restricted somewhat more..
+- * though it still does the Right Thing(tm) for the time being.
+ */
+ static inline int __access_ok(unsigned long addr, unsigned long size)
+ {
+- return ((addr >= memory_start) && ((addr + size) < memory_end));
++ return 1;
+ }
+ #else /* CONFIG_MMU */
+ #define __addr_ok(addr) \
+diff --git a/include/asm-sparc/Kbuild b/include/asm-sparc/Kbuild
+index c6a55cf..6712237 100644
+--- a/include/asm-sparc/Kbuild
++++ b/include/asm-sparc/Kbuild
+@@ -5,7 +5,6 @@ header-y += asi.h
+ header-y += bpp.h
+ header-y += jsflash.h
+ header-y += openpromio.h
+-header-y += pconf.h
+ header-y += reg.h
+ header-y += traps.h
+ header-y += vfc_ioctls.h
+diff --git a/include/asm-sparc/a.out-core.h b/include/asm-sparc/a.out-core.h
+deleted file mode 100644
+index e8fd338..0000000
+--- a/include/asm-sparc/a.out-core.h
++++ /dev/null
+@@ -1,52 +0,0 @@
+-/* a.out coredump register dumper
+- *
+- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+- * Written by David Howells (dhowells at redhat.com)
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public Licence
+- * as published by the Free Software Foundation; either version
+- * 2 of the Licence, or (at your option) any later version.
+- */
+-
+-#ifndef _ASM_A_OUT_CORE_H
+-#define _ASM_A_OUT_CORE_H
+-
+-#ifdef __KERNEL__
+-
+-#include <linux/user.h>
+-
+-/*
+- * fill in the user structure for an a.out core dump
+- */
+-static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump)
+-{
+- unsigned long first_stack_page;
+-
+- dump->magic = SUNOS_CORE_MAGIC;
+- dump->len = sizeof(struct user);
+- dump->regs.psr = regs->psr;
+- dump->regs.pc = regs->pc;
+- dump->regs.npc = regs->npc;
+- dump->regs.y = regs->y;
+- /* fuck me plenty */
+- memcpy(&dump->regs.regs[0], ®s->u_regs[1], (sizeof(unsigned long) * 15));
+- dump->uexec = current->thread.core_exec;
+- dump->u_tsize = (((unsigned long) current->mm->end_code) -
+- ((unsigned long) current->mm->start_code)) & ~(PAGE_SIZE - 1);
+- dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1)));
+- dump->u_dsize -= dump->u_tsize;
+- dump->u_dsize &= ~(PAGE_SIZE - 1);
+- first_stack_page = (regs->u_regs[UREG_FP] & ~(PAGE_SIZE - 1));
+- dump->u_ssize = (TASK_SIZE - first_stack_page) & ~(PAGE_SIZE - 1);
+- memcpy(&dump->fpu.fpstatus.fregs.regs[0], ¤t->thread.float_regs[0], (sizeof(unsigned long) * 32));
+- dump->fpu.fpstatus.fsr = current->thread.fsr;
+- dump->fpu.fpstatus.flags = dump->fpu.fpstatus.extra = 0;
+- dump->fpu.fpstatus.fpq_count = current->thread.fpqdepth;
+- memcpy(&dump->fpu.fpstatus.fpq[0], ¤t->thread.fpqueue[0],
+- ((sizeof(unsigned long) * 2) * 16));
+- dump->sigcode = 0;
+-}
+-
+-#endif /* __KERNEL__ */
+-#endif /* _ASM_A_OUT_CORE_H */
+diff --git a/include/asm-sparc/a.out.h b/include/asm-sparc/a.out.h
+deleted file mode 100644
+index 2f1c374..0000000
+--- a/include/asm-sparc/a.out.h
++++ /dev/null
+@@ -1,97 +0,0 @@
+-#ifndef __SPARC_A_OUT_H__
+-#define __SPARC_A_OUT_H__
+-
+-#define SPARC_PGSIZE 0x2000 /* Thanks to the sun4 architecture... */
+-#define SEGMENT_SIZE SPARC_PGSIZE /* whee... */
+-
+-#ifndef __ASSEMBLY__
+-
+-struct exec {
+- unsigned char a_dynamic:1; /* A __DYNAMIC is in this image */
+- unsigned char a_toolversion:7;
+- unsigned char a_machtype;
+- unsigned short a_info;
+- unsigned int a_text; /* length of text, in bytes */
+- unsigned int a_data; /* length of data, in bytes */
+- unsigned int a_bss; /* length of bss, in bytes */
+- unsigned int a_syms; /* length of symbol table, in bytes */
+- unsigned int a_entry; /* where program begins */
+- unsigned int a_trsize;
+- unsigned int a_drsize;
+-};
+-
+-#endif /* !__ASSEMBLY__ */
+-
+-/* Where in the file does the text information begin? */
+-#define N_TXTOFF(x) (N_MAGIC(x) == ZMAGIC ? 0 : sizeof (struct exec))
+-
+-/* Where do the Symbols start? */
+-#define N_SYMOFF(x) (N_TXTOFF(x) + (x).a_text + \
+- (x).a_data + (x).a_trsize + \
+- (x).a_drsize)
+-
+-/* Where does text segment go in memory after being loaded? */
+-#define N_TXTADDR(x) (unsigned long)(((N_MAGIC(x) == ZMAGIC) && \
+- ((x).a_entry < SPARC_PGSIZE)) ? \
+- 0 : SPARC_PGSIZE)
+-
+-/* And same for the data segment.. */
+-#define N_DATADDR(x) (N_MAGIC(x)==OMAGIC ? \
+- (N_TXTADDR(x) + (x).a_text) \
+- : (unsigned long) (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
+-
+-#define N_TRSIZE(a) ((a).a_trsize)
+-#define N_DRSIZE(a) ((a).a_drsize)
+-#define N_SYMSIZE(a) ((a).a_syms)
+-
+-#ifndef __ASSEMBLY__
+-
+-/*
+- * Sparc relocation types
+- */
+-enum reloc_type
+-{
+- RELOC_8,
+- RELOC_16,
+- RELOC_32, /* simplest relocs */
+- RELOC_DISP8,
+- RELOC_DISP16,
+- RELOC_DISP32, /* Disp's (pc-rel) */
+- RELOC_WDISP30,
+- RELOC_WDISP22, /* SR word disp's */
+- RELOC_HI22,
+- RELOC_22, /* SR 22-bit relocs */
+- RELOC_13,
+- RELOC_LO10, /* SR 13&10-bit relocs */
+- RELOC_SFA_BASE,
+- RELOC_SFA_OFF13, /* SR S.F.A. relocs */
+- RELOC_BASE10,
+- RELOC_BASE13,
+- RELOC_BASE22, /* base_relative pic */
+- RELOC_PC10,
+- RELOC_PC22, /* special pc-rel pic */
+- RELOC_JMP_TBL, /* jmp_tbl_rel in pic */
+- RELOC_SEGOFF16, /* ShLib offset-in-seg */
+- RELOC_GLOB_DAT,
+- RELOC_JMP_SLOT,
+- RELOC_RELATIVE /* rtld relocs */
+-};
+-
+-/*
+- * Format of a relocation datum.
+- */
+-struct relocation_info /* used when header.a_machtype == M_SPARC */
+-{
+- unsigned int r_address; /* relocation addr */
+- unsigned int r_index:24; /* segment index or symbol index */
+- unsigned int r_extern:1; /* if F, r_index==SEG#; if T, SYM idx */
+- unsigned int r_pad:2; /* <unused> */
+- enum reloc_type r_type:5; /* type of relocation to perform */
+- int r_addend; /* addend for relocation value */
+-};
+-
+-#define N_RELOCATION_INFO_DECLARED 1
+-
+-#endif /* !(__ASSEMBLY__) */
+-
+-#endif /* __SPARC_A_OUT_H__ */
+diff --git a/include/asm-sparc/device.h b/include/asm-sparc/device.h
+index 680e51d..19790eb 100644
+--- a/include/asm-sparc/device.h
++++ b/include/asm-sparc/device.h
+@@ -16,6 +16,8 @@ struct dev_archdata {
+
+ struct device_node *prom_node;
+ struct of_device *op;
++
++ int numa_node;
+ };
+
+ #endif /* _ASM_SPARC_DEVICE_H */
+diff --git a/include/asm-sparc/floppy.h b/include/asm-sparc/floppy.h
+index dbe7a58..d3978e0 100644
+--- a/include/asm-sparc/floppy.h
++++ b/include/asm-sparc/floppy.h
+@@ -280,7 +280,7 @@ static inline void sun_fd_enable_dma(void)
+
+ /* Our low-level entry point in arch/sparc/kernel/entry.S */
+ extern int sparc_floppy_request_irq(int irq, unsigned long flags,
+- irqreturn_t (*irq_handler)(int irq, void *));
++ irq_handler_t irq_handler);
+
+ static int sun_fd_request_irq(void)
+ {
+diff --git a/include/asm-sparc/head.h b/include/asm-sparc/head.h
+index 1a03c28..fcdba51 100644
+--- a/include/asm-sparc/head.h
++++ b/include/asm-sparc/head.h
+@@ -46,45 +46,12 @@
+ b linux_sparc_syscall; \
+ rd %psr, %l0;
+
+-/* Software trap for SunOS4.1.x system calls. */
+-#define SUNOS_SYSCALL_TRAP \
+- rd %psr, %l0; \
+- sethi %hi(sunos_sys_table), %l7; \
+- b linux_sparc_syscall; \
+- or %l7, %lo(sunos_sys_table), %l7;
+-
+-#define SUNOS_NO_SYSCALL_TRAP \
+- b sunos_syscall; \
+- rd %psr, %l0; \
+- nop; \
+- nop;
+-
+-/* Software trap for Slowaris system calls. */
+-#define SOLARIS_SYSCALL_TRAP \
+- b solaris_syscall; \
+- rd %psr, %l0; \
+- nop; \
+- nop;
+-
+-#define INDIRECT_SOLARIS_SYSCALL(x) \
+- mov x, %g1; \
+- b solaris_syscall; \
+- rd %psr, %l0; \
+- nop;
+-
+ #define BREAKPOINT_TRAP \
+ b breakpoint_trap; \
+ rd %psr,%l0; \
+ nop; \
+ nop;
+
+-/* Software trap for Sparc-netbsd system calls. */
+-#define NETBSD_SYSCALL_TRAP \
+- sethi %hi(sys_call_table), %l7; \
+- or %l7, %lo(sys_call_table), %l7; \
+- b bsd_syscall; \
+- rd %psr, %l0;
+-
+ /* The Get Condition Codes software trap for userland. */
+ #define GETCC_TRAP \
+ b getcc_trap_handler; mov %psr, %l0; nop; nop;
+diff --git a/include/asm-sparc/ide.h b/include/asm-sparc/ide.h
+index 4076cb5..afd1736 100644
+--- a/include/asm-sparc/ide.h
++++ b/include/asm-sparc/ide.h
+@@ -17,8 +17,6 @@
+ #undef MAX_HWIFS
+ #define MAX_HWIFS 2
+
+-#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */
+-
+ #define __ide_insl(data_reg, buffer, wcount) \
+ __ide_insw(data_reg, buffer, (wcount)<<1)
+ #define __ide_outsl(data_reg, buffer, wcount) \
+diff --git a/include/asm-sparc/ioctls.h b/include/asm-sparc/ioctls.h
+index 058c206..3f4d008 100644
+--- a/include/asm-sparc/ioctls.h
++++ b/include/asm-sparc/ioctls.h
+@@ -43,8 +43,6 @@
+ #define __TIOCSETX _IOW('t', 34, int) /* SunOS Specific */
+ #define __TIOCGETX _IOR('t', 35, int) /* SunOS Specific */
+ #define TIOCCONS _IO('t', 36)
+-#define __TIOCSSIZE _IOW('t', 37, struct sunos_ttysize) /* SunOS Specific */
+-#define __TIOCGSIZE _IOR('t', 38, struct sunos_ttysize) /* SunOS Specific */
+ #define TIOCGSOFTCAR _IOR('t', 100, int)
+ #define TIOCSSOFTCAR _IOW('t', 101, int)
+ #define __TIOCUCNTL _IOW('t', 102, int) /* SunOS Specific */
+diff --git a/include/asm-sparc/mman.h b/include/asm-sparc/mman.h
+index b7dc40b..e18be98 100644
+--- a/include/asm-sparc/mman.h
++++ b/include/asm-sparc/mman.h
+@@ -22,19 +22,6 @@
+ #define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
+ #define MAP_NONBLOCK 0x10000 /* do not block on IO */
+
+-/* XXX Need to add flags to SunOS's mctl, mlockall, and madvise system
+- * XXX calls.
+- */
+-
+-/* SunOS sys_mctl() stuff... */
+-#define MC_SYNC 1 /* Sync pages in memory with storage (usu. a file) */
+-#define MC_LOCK 2 /* Lock pages into core ram, do not allow swapping of them */
+-#define MC_UNLOCK 3 /* Unlock pages locked via previous mctl() with MC_LOCK arg */
+-#define MC_LOCKAS 5 /* Lock an entire address space of the calling process */
+-#define MC_UNLOCKAS 6 /* Unlock entire address space of calling process */
+-
+-#define MADV_FREE 0x5 /* (Solaris) contents can be freed */
+-
+ #ifdef __KERNEL__
+ #ifndef __ASSEMBLY__
+ #define arch_mmap_check sparc_mmap_check
+diff --git a/include/asm-sparc/namei.h b/include/asm-sparc/namei.h
+index f2461e8..618344d 100644
+--- a/include/asm-sparc/namei.h
++++ b/include/asm-sparc/namei.h
+@@ -8,19 +8,6 @@
+ #ifndef __SPARC_NAMEI_H
+ #define __SPARC_NAMEI_H
+
+-#define SPARC_BSD_EMUL "/usr/gnemul/sunos/"
+-#define SPARC_SOL_EMUL "/usr/gnemul/solaris/"
+-
+-static inline char * __emul_prefix(void)
+-{
+- switch (current->personality) {
+- case PER_SUNOS:
+- return SPARC_BSD_EMUL;
+- case PER_SVR4:
+- return SPARC_SOL_EMUL;
+- default:
+- return NULL;
+- }
+-}
++#define __emul_prefix() NULL
+
+ #endif /* __SPARC_NAMEI_H */
+diff --git a/include/asm-sparc/pconf.h b/include/asm-sparc/pconf.h
+deleted file mode 100644
+index d73c1f1..0000000
+--- a/include/asm-sparc/pconf.h
++++ /dev/null
+@@ -1,25 +0,0 @@
+-/* $Id: pconf.h,v 1.3 1996/04/25 06:13:25 davem Exp $
+- * pconf.h: pathconf() and fpathconf() defines for SunOS
+- * system call compatibility.
+- *
+- * Copyright (C) 1995 David S. Miller (davem at caip.rutgers.edu)
+- */
+-
+-#ifndef _SPARC_PCONF_H
+-#define _SPARC_PCONF_H
+-
+-#include <linux/fs.h>
+-#include <linux/limits.h>
+-
+-#define _PCONF_LINK 1 /* Max number of links to an object */
+-#define _PCONF_CANON 2 /* TTY input buffer line size */
+-#define _PCONF_INPUT 3 /* Biggest packet a tty can imbibe at once */
+-#define _PCONF_NAME 4 /* Filename length max */
+-#define _PCONF_PATH 5 /* Max size of a pathname */
+-#define _PCONF_PIPE 6 /* Buffer size for a pipe */
+-#define _PCONF_CHRESTRICT 7 /* Can only root chown files? */
+-#define _PCONF_NOTRUNC 8 /* Are pathnames truncated if too big? */
+-#define _PCONF_VDISABLE 9 /* Magic char to disable special tty chars */
+-#define _PCONF_MAXPCONF 9
+-
+-#endif /* !(_SPARC_PCONF_H) */
+diff --git a/include/asm-sparc/processor.h b/include/asm-sparc/processor.h
+index 40b1e41..e300697 100644
+--- a/include/asm-sparc/processor.h
++++ b/include/asm-sparc/processor.h
+@@ -13,8 +13,6 @@
+ */
+ #define current_text_addr() ({ void *pc; __asm__("sethi %%hi(1f), %0; or %0, %%lo(1f), %0;\n1:" : "=r" (pc)); pc; })
+
+-#include <linux/a.out.h>
+-
+ #include <asm/psr.h>
+ #include <asm/ptrace.h>
+ #include <asm/head.h>
+@@ -67,7 +65,6 @@ struct thread_struct {
+ struct fpq fpqueue[16];
+ unsigned long flags;
+ mm_segment_t current_ds;
+- struct exec core_exec; /* just what it says. */
+ int new_signal;
+ };
+
+diff --git a/include/asm-sparc/prom.h b/include/asm-sparc/prom.h
+index df5dc44..fd55522 100644
+--- a/include/asm-sparc/prom.h
++++ b/include/asm-sparc/prom.h
+@@ -77,6 +77,11 @@ extern int of_getintprop_default(struct device_node *np,
+ const char *name,
+ int def);
+ extern int of_find_in_proplist(const char *list, const char *match, int len);
++#ifdef CONFIG_NUMA
++extern int of_node_to_nid(struct device_node *dp);
++#else
++#define of_node_to_nid(dp) (-1)
++#endif
+
+ extern void prom_build_devicetree(void);
+
+diff --git a/include/asm-sparc/semaphore.h b/include/asm-sparc/semaphore.h
+index 8018f9f..d9b2034 100644
+--- a/include/asm-sparc/semaphore.h
++++ b/include/asm-sparc/semaphore.h
+@@ -1,192 +1 @@
+-#ifndef _SPARC_SEMAPHORE_H
+-#define _SPARC_SEMAPHORE_H
+-
+-/* Dinky, good for nothing, just barely irq safe, Sparc semaphores. */
+-
+-#ifdef __KERNEL__
+-
+-#include <asm/atomic.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-struct semaphore {
+- atomic24_t count;
+- int sleepers;
+- wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n) \
+-{ \
+- .count = ATOMIC24_INIT(n), \
+- .sleepers = 0, \
+- .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+- struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+- atomic24_set(&sem->count, val);
+- sem->sleepers = 0;
+- init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+- sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+- sema_init(sem, 0);
+-}
+-
+-extern void __down(struct semaphore * sem);
+-extern int __down_interruptible(struct semaphore * sem);
+-extern int __down_trylock(struct semaphore * sem);
+-extern void __up(struct semaphore * sem);
+-
+-static inline void down(struct semaphore * sem)
+-{
+- register volatile int *ptr asm("g1");
+- register int increment asm("g2");
+-
+- might_sleep();
+-
+- ptr = &(sem->count.counter);
+- increment = 1;
+-
+- __asm__ __volatile__(
+- "mov %%o7, %%g4\n\t"
+- "call ___atomic24_sub\n\t"
+- " add %%o7, 8, %%o7\n\t"
+- "tst %%g2\n\t"
+- "bl 2f\n\t"
+- " nop\n"
+- "1:\n\t"
+- ".subsection 2\n"
+- "2:\n\t"
+- "save %%sp, -64, %%sp\n\t"
+- "mov %%g1, %%l1\n\t"
+- "mov %%g5, %%l5\n\t"
+- "call %3\n\t"
+- " mov %%g1, %%o0\n\t"
+- "mov %%l1, %%g1\n\t"
+- "ba 1b\n\t"
+- " restore %%l5, %%g0, %%g5\n\t"
+- ".previous\n"
+- : "=&r" (increment)
+- : "0" (increment), "r" (ptr), "i" (__down)
+- : "g3", "g4", "g7", "memory", "cc");
+-}
+-
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+- register volatile int *ptr asm("g1");
+- register int increment asm("g2");
+-
+- might_sleep();
+-
+- ptr = &(sem->count.counter);
+- increment = 1;
+-
+- __asm__ __volatile__(
+- "mov %%o7, %%g4\n\t"
+- "call ___atomic24_sub\n\t"
+- " add %%o7, 8, %%o7\n\t"
+- "tst %%g2\n\t"
+- "bl 2f\n\t"
+- " clr %%g2\n"
+- "1:\n\t"
+- ".subsection 2\n"
+- "2:\n\t"
+- "save %%sp, -64, %%sp\n\t"
+- "mov %%g1, %%l1\n\t"
+- "mov %%g5, %%l5\n\t"
+- "call %3\n\t"
+- " mov %%g1, %%o0\n\t"
+- "mov %%l1, %%g1\n\t"
+- "mov %%l5, %%g5\n\t"
+- "ba 1b\n\t"
+- " restore %%o0, %%g0, %%g2\n\t"
+- ".previous\n"
+- : "=&r" (increment)
+- : "0" (increment), "r" (ptr), "i" (__down_interruptible)
+- : "g3", "g4", "g7", "memory", "cc");
+-
+- return increment;
+-}
+-
+-static inline int down_trylock(struct semaphore * sem)
+-{
+- register volatile int *ptr asm("g1");
+- register int increment asm("g2");
+-
+- ptr = &(sem->count.counter);
+- increment = 1;
+-
+- __asm__ __volatile__(
+- "mov %%o7, %%g4\n\t"
+- "call ___atomic24_sub\n\t"
+- " add %%o7, 8, %%o7\n\t"
+- "tst %%g2\n\t"
+- "bl 2f\n\t"
+- " clr %%g2\n"
+- "1:\n\t"
+- ".subsection 2\n"
+- "2:\n\t"
+- "save %%sp, -64, %%sp\n\t"
+- "mov %%g1, %%l1\n\t"
+- "mov %%g5, %%l5\n\t"
+- "call %3\n\t"
+- " mov %%g1, %%o0\n\t"
+- "mov %%l1, %%g1\n\t"
+- "mov %%l5, %%g5\n\t"
+- "ba 1b\n\t"
+- " restore %%o0, %%g0, %%g2\n\t"
+- ".previous\n"
+- : "=&r" (increment)
+- : "0" (increment), "r" (ptr), "i" (__down_trylock)
+- : "g3", "g4", "g7", "memory", "cc");
+-
+- return increment;
+-}
+-
+-static inline void up(struct semaphore * sem)
+-{
+- register volatile int *ptr asm("g1");
+- register int increment asm("g2");
+-
+- ptr = &(sem->count.counter);
+- increment = 1;
+-
+- __asm__ __volatile__(
+- "mov %%o7, %%g4\n\t"
+- "call ___atomic24_add\n\t"
+- " add %%o7, 8, %%o7\n\t"
+- "tst %%g2\n\t"
+- "ble 2f\n\t"
+- " nop\n"
+- "1:\n\t"
+- ".subsection 2\n"
+- "2:\n\t"
+- "save %%sp, -64, %%sp\n\t"
+- "mov %%g1, %%l1\n\t"
+- "mov %%g5, %%l5\n\t"
+- "call %3\n\t"
+- " mov %%g1, %%o0\n\t"
+- "mov %%l1, %%g1\n\t"
+- "ba 1b\n\t"
+- " restore %%l5, %%g0, %%g5\n\t"
+- ".previous\n"
+- : "=&r" (increment)
+- : "0" (increment), "r" (ptr), "i" (__up)
+- : "g3", "g4", "g7", "memory", "cc");
+-}
+-
+-#endif /* __KERNEL__ */
+-
+-#endif /* !(_SPARC_SEMAPHORE_H) */
++#include <linux/semaphore.h>
+diff --git a/include/asm-sparc/socket.h b/include/asm-sparc/socket.h
+index 2e2bd0b..a00e15d 100644
+--- a/include/asm-sparc/socket.h
++++ b/include/asm-sparc/socket.h
+@@ -24,9 +24,6 @@
+ #define SO_SNDTIMEO 0x4000
+ #define SO_ACCEPTCONN 0x8000
+
+-/* wha!??? */
+-#define SO_DONTLINGER (~SO_LINGER) /* Older SunOS compat. hack */
+-
+ #define SO_SNDBUF 0x1001
+ #define SO_RCVBUF 0x1002
+ #define SO_SNDBUFFORCE 0x100a
+diff --git a/include/asm-sparc/solerrno.h b/include/asm-sparc/solerrno.h
+deleted file mode 100644
+index 8abce7e..0000000
+--- a/include/asm-sparc/solerrno.h
++++ /dev/null
+@@ -1,132 +0,0 @@
+-/* $Id: solerrno.h,v 1.5 1996/04/25 06:13:32 davem Exp $
+- * solerrno.h: Solaris error return codes for compatibility.
+- *
+- * Copyright (C) 1995 David S. Miller (davem at caip.rutgers.edu)
+- */
+-
+-#ifndef _SPARC_SOLERRNO_H
+-#define _SPARC_SOLERRNO_H
+-
+-#define SOL_EPERM 1 /* Required superuser access perms */
+-#define SOL_ENOENT 2 /* File or directory does not exist */
+-#define SOL_ESRCH 3 /* Process did not exist */
+-#define SOL_EINTR 4 /* System call was interrupted */
+-#define SOL_EIO 5 /* An i/o error occurred */
+-#define SOL_ENXIO 6 /* Device or Address does not exist */
+-#define SOL_E2BIG 7 /* Too many arguments were given */
+-#define SOL_ENOEXEC 8 /* Header of executable was munged */
+-#define SOL_EBADF 9 /* Bogus file number */
+-#define SOL_ECHILD 10 /* No children of process exist */
+-#define SOL_EAGAIN 11 /* beep beep, "try again later" */
+-#define SOL_ENOMEM 12 /* No memory available */
+-#define SOL_EACCES 13 /* Access not allowed */
+-#define SOL_EFAULT 14 /* Address passed was invalid */
+-#define SOL_ENOTBLK 15 /* blkdev op on non-block device */
+-#define SOL_EBUSY 16 /* Mounted device was busy */
+-#define SOL_EEXIST 17 /* File specified already exists */
+-#define SOL_EXDEV 18 /* Link request across diff devices */
+-#define SOL_ENODEV 19 /* Device does not exist on system */
+-#define SOL_ENOTDIR 20 /* Dir operation on non-directory */
+-#define SOL_EISDIR 21 /* File was of directory type */
+-#define SOL_EINVAL 22 /* Argument passed was invalid */
+-#define SOL_ENFILE 23 /* No more room in file table */
+-#define SOL_EMFILE 24 /* Proc has too many files open */
+-#define SOL_ENOTTY 25 /* Ioctl was invalid for req device */
+-#define SOL_ETXTBSY 26 /* Text file in busy state */
+-#define SOL_EFBIG 27 /* Too big of a file for operation */
+-#define SOL_ENOSPC 28 /* Disk is full */
+-#define SOL_ESPIPE 29 /* Seek attempted on non-seeking dev*/
+-#define SOL_EROFS 30 /* Write attempted on read-only fs */
+-#define SOL_EMLINK 31 /* Too many links in file search */
+-#define SOL_EPIPE 32 /* Call a plumber */
+-#define SOL_EDOM 33 /* Argument was out of fct domain */
+-#define SOL_ERANGE 34 /* Could not represent math result */
+-#define SOL_ENOMSG 35 /* Message of req type doesn't exist */
+-#define SOL_EIDRM 36 /* Identifier has been removed */
+-#define SOL_ECHRNG 37 /* Req channel number out of range */
+-#define SOL_EL2NSYNC 38 /* Could not sync at run level 2 */
+-#define SOL_EL3HLT 39 /* Halted at run level 3 */
+-#define SOL_EL3RST 40 /* Reset at run level 3 */
+-#define SOL_ELNRNG 41 /* Out of range link number */
+-#define SOL_EUNATCH 42 /* Driver for protocol not attached */
+-#define SOL_ENOCSI 43 /* CSI structure not around */
+-#define SOL_EL2HLT 44 /* Halted at run level 2 */
+-#define SOL_EDEADLK 45 /* Deadlock condition detected */
+-#define SOL_ENOLCK 46 /* Record locks unavailable */
+-#define SOL_ECANCELED 47 /* Cancellation of oper. happened */
+-#define SOL_ENOTSUP 48 /* Attempt of unsupported operation */
+-#define SOL_EDQUOT 49 /* Users disk quota exceeded */
+-#define SOL_EBADE 50 /* Invalid exchange */
+-#define SOL_EBADR 51 /* Request descriptor was invalid */
+-#define SOL_EXFULL 52 /* Full exchange */
+-#define SOL_ENOANO 53 /* ano does not exist */
+-#define SOL_EBADRQC 54 /* Req code was invalid */
+-#define SOL_EBADSLT 55 /* Bad slot number */
+-#define SOL_EDEADLOCK 56 /* Deadlock in fs error */
+-#define SOL_EBFONT 57 /* Font file format invalid */
+-/* YOW, I LOVE SYSV STREAMS!!!! */
+-#define SOL_ENOSTR 60 /* Stream-op on non-stream dev */
+-#define SOL_ENODATA 61 /* No data avail at this time */
+-#define SOL_ETIME 62 /* Expiration of time occurred */
+-#define SOL_ENOSR 63 /* Streams resources exhausted */
+-#define SOL_ENONET 64 /* No network connected */
+-#define SOL_ENOPKG 65 /* Non-installed package */
+-#define SOL_EREMOTE 66 /* Object was on remote machine */
+-#define SOL_ENOLINK 67 /* Cut link */
+-#define SOL_EADV 68 /* Error in advertise */
+-#define SOL_ESRMNT 69 /* Some magic srmount problem */
+-#define SOL_ECOMM 70 /* During send, comm error occurred */
+-#define SOL_EPROTO 71 /* Protocol botch */
+-#define SOL_EMULTIHOP 74 /* Multihop attempted */
+-#define SOL_EBADMSG 77 /* Message was unreadable */
+-#define SOL_ENAMETOOLONG 78 /* Too long of a path name */
+-#define SOL_EOVERFLOW 79 /* Data type too small for datum */
+-#define SOL_ENOTUNIQ 80 /* Logical name was not unique */
+-#define SOL_EBADFD 81 /* Op cannot be performed on fd */
+-#define SOL_EREMCHG 82 /* Remote address is now different */
+-#define SOL_ELIBACC 83 /* Shared lib could not be accessed */
+-#define SOL_ELIBBAD 84 /* ShLib is corrupted in some way */
+-#define SOL_ELIBSCN 85 /* A.out ShLib problems */
+-#define SOL_ELIBMAX 86 /* Exceeded ShLib linkage limit */
+-#define SOL_ELIBEXEC 87 /* Execution of ShLib attempted */
+-#define SOL_EILSEQ 88 /* Bad byte sequence found */
+-#define SOL_ENOSYS 89 /* Invalid filesystem operation */
+-#define SOL_ELOOP 90 /* Detected loop in symbolic links */
+-#define SOL_ERESTART 91 /* System call is restartable */
+-#define SOL_ESTRPIPE 92 /* Do not sleep in head of stream */
+-#define SOL_ENOTEMPTY 93 /* Rmdir of non-empty directory */
+-#define SOL_EUSERS 94 /* Over abundance of users for ufs */
+-#define SOL_ENOTSOCK 95 /* Sock-op on non-sock */
+-#define SOL_EDESTADDRREQ 96 /* No dest addr given, but needed */
+-#define SOL_EMSGSIZE 97 /* Msg too big */
+-#define SOL_EPROTOTYPE 98 /* Bad socket protocol */
+-#define SOL_ENOPROTOOPT 99 /* Unavailable protocol */
+-#define SOL_EPROTONOSUPPORT 120 /* Unsupported protocol */
+-#define SOL_ESOCKTNOSUPPORT 121 /* Unsupported socket type */
+-#define SOL_EOPNOTSUPP 122 /* Unsupported sock-op */
+-#define SOL_EPFNOSUPPORT 123 /* Unsupported protocol family */
+-#define SOL_EAFNOSUPPORT 124 /* Unsup addr family for protocol */
+-#define SOL_EADDRINUSE 125 /* Req addr is already in use */
+-#define SOL_EADDRNOTAVAIL 126 /* Req addr not available right now */
+-#define SOL_ENETDOWN 127 /* Your subnet is on fire */
+-#define SOL_ENETUNREACH 128 /* Someone playing with gateway and */
+- /* did not tell you he was going to */
+-#define SOL_ENETRESET 129 /* Buy less-buggy ethernet cards */
+-#define SOL_ECONNABORTED 130 /* Aborted connection due to sw */
+-#define SOL_ECONNRESET 131 /* Your peers reset your connection */
+-#define SOL_ENOBUFS 132 /* No buffer space available */
+-#define SOL_EISCONN 133 /* Connect on already connected */
+- /* socket attempted */
+-#define SOL_ENOTCONN 134 /* Comm on non-connected socket */
+-#define SOL_ESHUTDOWN 143 /* Op attempted after sock-shutdown */
+-#define SOL_ETOOMANYREFS 144 /* Reference limit exceeded */
+-#define SOL_ETIMEDOUT 145 /* Timed out connection */
+-#define SOL_ECONNREFUSED 146 /* Connection refused by remote host*/
+-#define SOL_EHOSTDOWN 147 /* Remote host is up in flames */
+-#define SOL_EHOSTUNREACH 148 /* Make a left at Easton Ave..... */
+-#define SOL_EWOULDBLOCK EAGAIN /* Just an alias */
+-#define SOL_EALREADY 149 /* Operation is already occurring */
+-#define SOL_EINPROGRESS 150 /* Operation is happening now */
+-#define SOL_ESTALE 151 /* Fungus growth on NFS file handle */
+-
+-#endif /* !(_SPARC_SOLERRNO_H) */
+diff --git a/include/asm-sparc/svr4.h b/include/asm-sparc/svr4.h
+deleted file mode 100644
+index da1f1c9..0000000
+--- a/include/asm-sparc/svr4.h
++++ /dev/null
+@@ -1,119 +0,0 @@
+-/* Solaris/SPARC constants and definitions --
+- * (C) 1996 Miguel de Icaza
+- *
+- * This file is not meant to be included by user level applications
+- * but the solaris syscall emulator
+- */
+-
+-#ifndef _SPARC_SVR4_H
+-#define _SPARC_SVR4_H
+-
+-/* Signals as used by svr4 */
+-typedef struct { /* signal set type */
+- ulong sigbits[4];
+-} svr4_sigset_t;
+-
+-/* Values for siginfo.code */
+-#define SVR4_SINOINFO 32767
+-/* Siginfo, sucker expects bunch of information on those parameters */
+-typedef union {
+- char total_size [128];
+- struct {
+- int signo;
+- int code;
+- int error;
+- union {
+- } data;
+- } siginfo;
+-} svr4_siginfo_t;
+-
+-/* Context definition */
+-
+-/* Location of the user stored registers into a greg_t */
+-enum {
+- SVR4_PSR, SVR4_PC, SVR4_NPC, SVR4_Y,
+- SVR4_G1, SVR4_G2, SVR4_G3, SVR4_G4,
+- SVR4_G5, SVR4_G6, SVR4_G7, SVR4_O0,
+- SVR4_O1, SVR4_O2, SVR4_O3, SVR4_O4,
+- SVR4_O5, SVR4_O6, SVR4_O7
+-};
+-
+-/* sizeof (regs) / sizeof (greg_t), defined in the ABI */
+-#define SVR4_NREGS 19
+-#define SVR4_MAXWIN 31
+-
+-typedef struct {
+- uint rwin_lo[8];
+- uint rwin_in[8];
+-} svr4_rwindow_t;
+-
+-typedef struct {
+- int count;
+- int __user *winptr [SVR4_MAXWIN]; /* pointer to the windows */
+- svr4_rwindow_t win[SVR4_MAXWIN]; /* the windows */
+-} svr4_gwindows_t;
+-
+-typedef int svr4_gregset_t[SVR4_NREGS];
+-
+-typedef struct {
+- double fpu_regs[32];
+- void *fp_q;
+- unsigned fp_fsr;
+- u_char fp_nqel;
+- u_char fp_nqsize;
+- u_char inuse; /* if fpu is in use */
+-} svr4_fregset_t;
+-
+-typedef struct {
+- uint id; /* if this holds "xrs" string => ptr is valid */
+- caddr_t ptr;
+-} svr4_xrs_t;
+-
+-/* Machine dependent context */
+-typedef struct {
+- svr4_gregset_t greg; /* registers 0..19 (see top) */
+- svr4_gwindows_t __user *gwin; /* may point to register windows */
+- svr4_fregset_t freg; /* floating point registers */
+- svr4_xrs_t xrs; /* mhm? */
+- long pad[19];
+-} svr4_mcontext_t;
+-
+-/* flags for stack_t.flags */
+-enum svr4_stack_flags {
+- SVR4_SS_ONSTACK,
+- SVR4_SS_DISABLE,
+-};
+-
+-/* signal stack exection place, unsupported */
+-typedef struct svr4_stack_t {
+- char __user *sp;
+- int size;
+- int flags;
+-} svr4_stack_t;
+-
+-/* Context used by getcontext and setcontext */
+-typedef struct svr4_ucontext_t {
+- u_long flags; /* context flags, indicate what is loaded */
+- struct svr4_ucontext *link;
+- svr4_sigset_t sigmask;
+- svr4_stack_t stack;
+- svr4_mcontext_t mcontext;
+- long pad[23];
+-} svr4_ucontext_t;
+-
+-/* windows hold the windows as they were at signal time,
+- * ucontext->mcontext holds a pointer to them.
+- * addresses for uc and si are passed as parameters to svr4 signal
+- * handler
+- */
+-
+-/* This is the signal frame that is passed to the signal handler */
+-typedef struct {
+- svr4_gwindows_t gw; /* windows */
+- svr4_ucontext_t uc; /* machine context */
+- svr4_siginfo_t si; /* siginfo */
+-} svr4_signal_frame_t;
+-
+-#define SVR4_SF_ALIGNED (((sizeof (svr4_signal_frame_t) + 7) & (~7)))
+-
+-#endif /* include control */
+diff --git a/include/asm-sparc/termios.h b/include/asm-sparc/termios.h
+index 4333232..733d405 100644
+--- a/include/asm-sparc/termios.h
++++ b/include/asm-sparc/termios.h
+@@ -33,11 +33,6 @@ struct ltchars {
+ };
+ #endif /* __KERNEL__ */
+
+-struct sunos_ttysize {
+- int st_lines; /* Lines on the terminal */
+- int st_columns; /* Columns on the terminal */
+-};
+-
+ struct winsize {
+ unsigned short ws_row;
+ unsigned short ws_col;
+diff --git a/include/asm-sparc/user.h b/include/asm-sparc/user.h
+index b5f1abf..3400ea8 100644
+--- a/include/asm-sparc/user.h
++++ b/include/asm-sparc/user.h
+@@ -1,60 +1,6 @@
+-/* $Id: user.h,v 1.5 1998/02/23 01:49:22 rth Exp $
+- * asm-sparc/user.h: Core file definitions for the Sparc.
+- *
+- * Keep in sync with reg.h. Actually, we could get rid of this
+- * one, since we won't a.out core dump that much anyways - miguel.
+- * Copyright (C) 1995 (davem at caip.rutgers.edu)
+- */
+ #ifndef _SPARC_USER_H
+ #define _SPARC_USER_H
+
+-#include <asm/a.out.h>
+-struct sunos_regs {
+- unsigned long psr, pc, npc, y;
+- unsigned long regs[15];
+-};
+-
+-struct sunos_fpqueue {
+- unsigned long *addr;
+- unsigned long inst;
+-};
+-
+-struct sunos_fp {
+- union {
+- unsigned long regs[32];
+- double reg_dbls[16];
+- } fregs;
+- unsigned long fsr;
+- unsigned long flags;
+- unsigned long extra;
+- unsigned long fpq_count;
+- struct sunos_fpqueue fpq[16];
+-};
+-
+-struct sunos_fpu {
+- struct sunos_fp fpstatus;
+-};
+-
+-/* The SunOS core file header layout. */
+-struct user {
+- unsigned long magic;
+- unsigned long len;
+- struct sunos_regs regs;
+- struct exec uexec;
+- int signal;
+- size_t u_tsize; /* all of these in bytes! */
+- size_t u_dsize;
+- size_t u_ssize;
+- char u_comm[17];
+- struct sunos_fpu fpu;
+- unsigned long sigcode; /* Special sigcontext subcode, if any */
+-};
+-
+-#define NBPG 0x2000
+-#define UPAGES 1
+-#define HOST_TEXT_START_ADDR (u.start_code)
+-#define HOST_DATA_START_ADDR (u.uexec.a_data)
+-#define HOST_STACK_END_ADDR (- u.u_ssize * NBPG)
+-#define SUNOS_CORE_MAGIC 0x080456
++/* Nothing to define. */
+
+ #endif /* !(_SPARC_USER_H) */
+diff --git a/include/asm-sparc64/Kbuild b/include/asm-sparc64/Kbuild
+index a90dc82..dce1cf9 100644
+--- a/include/asm-sparc64/Kbuild
++++ b/include/asm-sparc64/Kbuild
+@@ -12,7 +12,6 @@ header-y += display7seg.h
+ header-y += envctrl.h
+ header-y += openprom.h
+ header-y += openpromio.h
+-header-y += pconf.h
+ header-y += psrcompat.h
+ header-y += pstate.h
+ header-y += reg.h
+diff --git a/include/asm-sparc64/a.out-core.h b/include/asm-sparc64/a.out-core.h
+deleted file mode 100644
+index 3499b3c..0000000
+--- a/include/asm-sparc64/a.out-core.h
++++ /dev/null
+@@ -1,31 +0,0 @@
+-/* a.out coredump register dumper
+- *
+- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+- * Written by David Howells (dhowells at redhat.com)
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public Licence
+- * as published by the Free Software Foundation; either version
+- * 2 of the Licence, or (at your option) any later version.
+- */
+-
+-#ifndef _ASM_A_OUT_CORE_H
+-#define _ASM_A_OUT_CORE_H
+-
+-#ifdef __KERNEL__
+-
+-#include <linux/user.h>
+-
+-/*
+- * fill in the user structure for an a.out core dump
+- */
+-static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump)
+-{
+- /* Only should be used for SunOS and ancient a.out
+- * SparcLinux binaries... Not worth implementing.
+- */
+- memset(dump, 0, sizeof(struct user));
+-}
+-
+-#endif /* __KERNEL__ */
+-#endif /* _ASM_A_OUT_CORE_H */
+diff --git a/include/asm-sparc64/a.out.h b/include/asm-sparc64/a.out.h
+deleted file mode 100644
+index 44208c2..0000000
+--- a/include/asm-sparc64/a.out.h
++++ /dev/null
+@@ -1 +0,0 @@
+-#include <asm-sparc/a.out.h>
+diff --git a/include/asm-sparc64/ide.h b/include/asm-sparc64/ide.h
+index ac7eb21..c5fdabe 100644
+--- a/include/asm-sparc64/ide.h
++++ b/include/asm-sparc64/ide.h
+@@ -24,8 +24,6 @@
+ # endif
+ #endif
+
+-#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */
+-
+ #define __ide_insl(data_reg, buffer, wcount) \
+ __ide_insw(data_reg, buffer, (wcount)<<1)
+ #define __ide_outsl(data_reg, buffer, wcount) \
+diff --git a/include/asm-sparc64/ioctls.h b/include/asm-sparc64/ioctls.h
+index 083c9a0..c1be406 100644
+--- a/include/asm-sparc64/ioctls.h
++++ b/include/asm-sparc64/ioctls.h
+@@ -44,8 +44,6 @@
+ #define __TIOCSETX _IOW('t', 34, int) /* SunOS Specific */
+ #define __TIOCGETX _IOR('t', 35, int) /* SunOS Specific */
+ #define TIOCCONS _IO('t', 36)
+-#define __TIOCSSIZE _IOW('t', 37, struct sunos_ttysize) /* SunOS Specific */
+-#define __TIOCGSIZE _IOR('t', 38, struct sunos_ttysize) /* SunOS Specific */
+ #define TIOCGSOFTCAR _IOR('t', 100, int)
+ #define TIOCSSOFTCAR _IOW('t', 101, int)
+ #define __TIOCUCNTL _IOW('t', 102, int) /* SunOS Specific */
+diff --git a/include/asm-sparc64/iommu.h b/include/asm-sparc64/iommu.h
+index 46325dd..d7b9afc 100644
+--- a/include/asm-sparc64/iommu.h
++++ b/include/asm-sparc64/iommu.h
+@@ -56,6 +56,7 @@ struct strbuf {
+ };
+
+ extern int iommu_table_init(struct iommu *iommu, int tsbsize,
+- u32 dma_offset, u32 dma_addr_mask);
++ u32 dma_offset, u32 dma_addr_mask,
++ int numa_node);
+
+ #endif /* !(_SPARC64_IOMMU_H) */
+diff --git a/include/asm-sparc64/lmb.h b/include/asm-sparc64/lmb.h
+new file mode 100644
+index 0000000..6a352cb
+--- /dev/null
++++ b/include/asm-sparc64/lmb.h
+@@ -0,0 +1,10 @@
++#ifndef _SPARC64_LMB_H
++#define _SPARC64_LMB_H
++
++#include <asm/oplib.h>
++
++#define LMB_DBG(fmt...) prom_printf(fmt)
++
++#define LMB_REAL_LIMIT 0
++
++#endif /* !(_SPARC64_LMB_H) */
+diff --git a/include/asm-sparc64/mman.h b/include/asm-sparc64/mman.h
+index 8cc1860..e584563 100644
+--- a/include/asm-sparc64/mman.h
++++ b/include/asm-sparc64/mman.h
+@@ -22,19 +22,6 @@
+ #define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
+ #define MAP_NONBLOCK 0x10000 /* do not block on IO */
+
+-/* XXX Need to add flags to SunOS's mctl, mlockall, and madvise system
+- * XXX calls.
+- */
+-
+-/* SunOS sys_mctl() stuff... */
+-#define MC_SYNC 1 /* Sync pages in memory with storage (usu. a file) */
+-#define MC_LOCK 2 /* Lock pages into core ram, do not allow swapping of them */
+-#define MC_UNLOCK 3 /* Unlock pages locked via previous mctl() with MC_LOCK arg */
+-#define MC_LOCKAS 5 /* Lock an entire address space of the calling process */
+-#define MC_UNLOCKAS 6 /* Unlock entire address space of calling process */
+-
+-#define MADV_FREE 0x5 /* (Solaris) contents can be freed */
+-
+ #ifdef __KERNEL__
+ #ifndef __ASSEMBLY__
+ #define arch_mmap_check sparc64_mmap_check
+diff --git a/include/asm-sparc64/mmzone.h b/include/asm-sparc64/mmzone.h
+new file mode 100644
+index 0000000..ebf5986
+--- /dev/null
++++ b/include/asm-sparc64/mmzone.h
+@@ -0,0 +1,17 @@
++#ifndef _SPARC64_MMZONE_H
++#define _SPARC64_MMZONE_H
++
++#ifdef CONFIG_NEED_MULTIPLE_NODES
++
++extern struct pglist_data *node_data[];
++
++#define NODE_DATA(nid) (node_data[nid])
++#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn)
++#define node_end_pfn(nid) (NODE_DATA(nid)->node_end_pfn)
++
++extern int numa_cpu_lookup_table[];
++extern cpumask_t numa_cpumask_lookup_table[];
++
++#endif /* CONFIG_NEED_MULTIPLE_NODES */
++
++#endif /* _SPARC64_MMZONE_H */
+diff --git a/include/asm-sparc64/namei.h b/include/asm-sparc64/namei.h
+index ccda19e..275161f 100644
+--- a/include/asm-sparc64/namei.h
++++ b/include/asm-sparc64/namei.h
+@@ -8,19 +8,6 @@
+ #ifndef __SPARC64_NAMEI_H
+ #define __SPARC64_NAMEI_H
+
+-#define SPARC_BSD_EMUL "/usr/gnemul/sunos/"
+-#define SPARC_SOL_EMUL "/usr/gnemul/solaris/"
+-
+-static inline char * __emul_prefix(void)
+-{
+- switch (current->personality) {
+- case PER_SUNOS:
+- return SPARC_BSD_EMUL;
+- case PER_SVR4:
+- return SPARC_SOL_EMUL;
+- default:
+- return NULL;
+- }
+-}
++#define __emul_prefix() NULL
+
+ #endif /* __SPARC64_NAMEI_H */
+diff --git a/include/asm-sparc64/numnodes.h b/include/asm-sparc64/numnodes.h
+deleted file mode 100644
+index 017e7e7..0000000
+--- a/include/asm-sparc64/numnodes.h
++++ /dev/null
+@@ -1,6 +0,0 @@
+-#ifndef _SPARC64_NUMNODES_H
+-#define _SPARC64_NUMNODES_H
+-
+-#define NODES_SHIFT 0
+-
+-#endif /* !(_SPARC64_NUMNODES_H) */
+diff --git a/include/asm-sparc64/pconf.h b/include/asm-sparc64/pconf.h
+deleted file mode 100644
+index aad106a..0000000
+--- a/include/asm-sparc64/pconf.h
++++ /dev/null
+@@ -1,25 +0,0 @@
+-/* $Id: pconf.h,v 1.1 1996/12/02 00:09:10 davem Exp $
+- * pconf.h: pathconf() and fpathconf() defines for SunOS
+- * system call compatibility.
+- *
+- * Copyright (C) 1995, 1996 David S. Miller (davem at caip.rutgers.edu)
+- */
+-
+-#ifndef _SPARC64_PCONF_H
+-#define _SPARC64_PCONF_H
+-
+-#include <linux/fs.h>
+-#include <linux/limits.h>
+-
+-#define _PCONF_LINK 1 /* Max number of links to an object */
+-#define _PCONF_CANON 2 /* TTY input buffer line size */
+-#define _PCONF_INPUT 3 /* Biggest packet a tty can imbibe at once */
+-#define _PCONF_NAME 4 /* Filename length max */
+-#define _PCONF_PATH 5 /* Max size of a pathname */
+-#define _PCONF_PIPE 6 /* Buffer size for a pipe */
+-#define _PCONF_CHRESTRICT 7 /* Can only root chown files? */
+-#define _PCONF_NOTRUNC 8 /* Are pathnames truncated if too big? */
+-#define _PCONF_VDISABLE 9 /* Magic char to disable special tty chars */
+-#define _PCONF_MAXPCONF 9
+-
+-#endif /* !(_SPARC64_PCONF_H) */
+diff --git a/include/asm-sparc64/ptrace.h b/include/asm-sparc64/ptrace.h
+index 6da1978..b4b951d 100644
+--- a/include/asm-sparc64/ptrace.h
++++ b/include/asm-sparc64/ptrace.h
+@@ -8,6 +8,8 @@
+ * stack during a system call and basically all traps.
+ */
+
++#define PT_REGS_MAGIC 0x57ac6c00
++
+ #ifndef __ASSEMBLY__
+
+ struct pt_regs {
+@@ -16,7 +18,19 @@ struct pt_regs {
+ unsigned long tpc;
+ unsigned long tnpc;
+ unsigned int y;
+- unsigned int fprs;
++
++ /* We encode a magic number, PT_REGS_MAGIC, along
++ * with the %tt (trap type) register value at trap
++ * entry time. The magic number allows us to identify
++ * accurately a trap stack frame in the stack
++ * unwinder, and the %tt value allows us to test
++ * things like "in a system call" etc. for an arbitray
++ * process.
++ *
++ * The PT_REGS_MAGIC is choosen such that it can be
++ * loaded completely using just a sethi instruction.
++ */
++ unsigned int magic;
+ };
+
+ struct pt_regs32 {
+@@ -147,7 +161,7 @@ extern void __show_regs(struct pt_regs *);
+ #define PT_V9_TPC 0x88
+ #define PT_V9_TNPC 0x90
+ #define PT_V9_Y 0x98
+-#define PT_V9_FPRS 0x9c
++#define PT_V9_MAGIC 0x9c
+ #define PT_TSTATE PT_V9_TSTATE
+ #define PT_TPC PT_V9_TPC
+ #define PT_TNPC PT_V9_TNPC
+diff --git a/include/asm-sparc64/semaphore.h b/include/asm-sparc64/semaphore.h
+index 7f7c0c4..d9b2034 100644
+--- a/include/asm-sparc64/semaphore.h
++++ b/include/asm-sparc64/semaphore.h
+@@ -1,53 +1 @@
+-#ifndef _SPARC64_SEMAPHORE_H
+-#define _SPARC64_SEMAPHORE_H
+-
+-/* These are actually reasonable on the V9.
+- *
+- * See asm-ppc/semaphore.h for implementation commentary,
+- * only sparc64 specific issues are commented here.
+- */
+-#ifdef __KERNEL__
+-
+-#include <asm/atomic.h>
+-#include <asm/system.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-struct semaphore {
+- atomic_t count;
+- wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, count) \
+- { ATOMIC_INIT(count), \
+- __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) }
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name, count) \
+- struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name, 1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+- atomic_set(&sem->count, val);
+- init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+- sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+- sema_init(sem, 0);
+-}
+-
+-extern void up(struct semaphore *sem);
+-extern void down(struct semaphore *sem);
+-extern int down_trylock(struct semaphore *sem);
+-extern int down_interruptible(struct semaphore *sem);
+-
+-#endif /* __KERNEL__ */
+-
+-#endif /* !(_SPARC64_SEMAPHORE_H) */
++#include <linux/semaphore.h>
+diff --git a/include/asm-sparc64/socket.h b/include/asm-sparc64/socket.h
+index 44a625a..8cf071f 100644
+--- a/include/asm-sparc64/socket.h
++++ b/include/asm-sparc64/socket.h
+@@ -24,9 +24,6 @@
+ #define SO_SNDTIMEO 0x4000
+ #define SO_ACCEPTCONN 0x8000
+
+-/* wha!??? */
+-#define SO_DONTLINGER (~SO_LINGER) /* Older SunOS compat. hack */
+-
+ #define SO_SNDBUF 0x1001
+ #define SO_RCVBUF 0x1002
+ #define SO_SNDBUFFORCE 0x100a
+diff --git a/include/asm-sparc64/solerrno.h b/include/asm-sparc64/solerrno.h
+deleted file mode 100644
+index a2ea6fc..0000000
+--- a/include/asm-sparc64/solerrno.h
++++ /dev/null
+@@ -1,132 +0,0 @@
+-/* $Id: solerrno.h,v 1.1 1996/12/26 14:22:40 davem Exp $
+- * solerrno.h: Solaris error return codes for compatibility.
+- *
+- * Copyright (C) 1996 David S. Miller (davem at caip.rutgers.edu)
+- */
+-
+-#ifndef _SPARC64_SOLERRNO_H
+-#define _SPARC64_SOLERRNO_H
+-
+-#define SOL_EPERM 1 /* Required superuser access perms */
+-#define SOL_ENOENT 2 /* File or directory does not exist */
+-#define SOL_ESRCH 3 /* Process did not exist */
+-#define SOL_EINTR 4 /* System call was interrupted */
+-#define SOL_EIO 5 /* An i/o error occurred */
+-#define SOL_ENXIO 6 /* Device or Address does not exist */
+-#define SOL_E2BIG 7 /* Too many arguments were given */
+-#define SOL_ENOEXEC 8 /* Header of executable was munged */
+-#define SOL_EBADF 9 /* Bogus file number */
+-#define SOL_ECHILD 10 /* No children of process exist */
+-#define SOL_EAGAIN 11 /* beep beep, "try again later" */
+-#define SOL_ENOMEM 12 /* No memory available */
+-#define SOL_EACCES 13 /* Access not allowed */
+-#define SOL_EFAULT 14 /* Address passed was invalid */
+-#define SOL_ENOTBLK 15 /* blkdev op on non-block device */
+-#define SOL_EBUSY 16 /* Mounted device was busy */
+-#define SOL_EEXIST 17 /* File specified already exists */
+-#define SOL_EXDEV 18 /* Link request across diff devices */
+-#define SOL_ENODEV 19 /* Device does not exist on system */
+-#define SOL_ENOTDIR 20 /* Dir operation on non-directory */
+-#define SOL_EISDIR 21 /* File was of directory type */
+-#define SOL_EINVAL 22 /* Argument passed was invalid */
+-#define SOL_ENFILE 23 /* No more room in file table */
+-#define SOL_EMFILE 24 /* Proc has too many files open */
+-#define SOL_ENOTTY 25 /* Ioctl was invalid for req device */
+-#define SOL_ETXTBSY 26 /* Text file in busy state */
+-#define SOL_EFBIG 27 /* Too big of a file for operation */
+-#define SOL_ENOSPC 28 /* Disk is full */
+-#define SOL_ESPIPE 29 /* Seek attempted on non-seeking dev*/
+-#define SOL_EROFS 30 /* Write attempted on read-only fs */
+-#define SOL_EMLINK 31 /* Too many links in file search */
+-#define SOL_EPIPE 32 /* Call a plumber */
+-#define SOL_EDOM 33 /* Argument was out of fct domain */
+-#define SOL_ERANGE 34 /* Could not represent math result */
+-#define SOL_ENOMSG 35 /* Message of req type doesn't exist */
+-#define SOL_EIDRM 36 /* Identifier has been removed */
+-#define SOL_ECHRNG 37 /* Req channel number out of range */
+-#define SOL_EL2NSYNC 38 /* Could not sync at run level 2 */
+-#define SOL_EL3HLT 39 /* Halted at run level 3 */
+-#define SOL_EL3RST 40 /* Reset at run level 3 */
+-#define SOL_ELNRNG 41 /* Out of range link number */
+-#define SOL_EUNATCH 42 /* Driver for protocol not attached */
+-#define SOL_ENOCSI 43 /* CSI structure not around */
+-#define SOL_EL2HLT 44 /* Halted at run level 2 */
+-#define SOL_EDEADLK 45 /* Deadlock condition detected */
+-#define SOL_ENOLCK 46 /* Record locks unavailable */
+-#define SOL_ECANCELED 47 /* Cancellation of oper. happened */
+-#define SOL_ENOTSUP 48 /* Attempt of unsupported operation */
+-#define SOL_EDQUOT 49 /* Users disk quota exceeded */
+-#define SOL_EBADE 50 /* Invalid exchange */
+-#define SOL_EBADR 51 /* Request descriptor was invalid */
+-#define SOL_EXFULL 52 /* Full exchange */
+-#define SOL_ENOANO 53 /* ano does not exist */
+-#define SOL_EBADRQC 54 /* Req code was invalid */
+-#define SOL_EBADSLT 55 /* Bad slot number */
+-#define SOL_EDEADLOCK 56 /* Deadlock in fs error */
+-#define SOL_EBFONT 57 /* Font file format invalid */
+-/* YOW, I LOVE SYSV STREAMS!!!! */
+-#define SOL_ENOSTR 60 /* Stream-op on non-stream dev */
+-#define SOL_ENODATA 61 /* No data avail at this time */
+-#define SOL_ETIME 62 /* Expiration of time occurred */
+-#define SOL_ENOSR 63 /* Streams resources exhausted */
+-#define SOL_ENONET 64 /* No network connected */
+-#define SOL_ENOPKG 65 /* Non-installed package */
+-#define SOL_EREMOTE 66 /* Object was on remote machine */
+-#define SOL_ENOLINK 67 /* Cut link */
+-#define SOL_EADV 68 /* Error in advertise */
+-#define SOL_ESRMNT 69 /* Some magic srmount problem */
+-#define SOL_ECOMM 70 /* During send, comm error occurred */
+-#define SOL_EPROTO 71 /* Protocol botch */
+-#define SOL_EMULTIHOP 74 /* Multihop attempted */
+-#define SOL_EBADMSG 77 /* Message was unreadable */
+-#define SOL_ENAMETOOLONG 78 /* Too long of a path name */
+-#define SOL_EOVERFLOW 79 /* Data type too small for datum */
+-#define SOL_ENOTUNIQ 80 /* Logical name was not unique */
+-#define SOL_EBADFD 81 /* Op cannot be performed on fd */
+-#define SOL_EREMCHG 82 /* Remote address is now different */
+-#define SOL_ELIBACC 83 /* Shared lib could not be accessed */
+-#define SOL_ELIBBAD 84 /* ShLib is corrupted in some way */
+-#define SOL_ELIBSCN 85 /* A.out ShLib problems */
+-#define SOL_ELIBMAX 86 /* Exceeded ShLib linkage limit */
+-#define SOL_ELIBEXEC 87 /* Execution of ShLib attempted */
+-#define SOL_EILSEQ 88 /* Bad byte sequence found */
+-#define SOL_ENOSYS 89 /* Invalid filesystem operation */
+-#define SOL_ELOOP 90 /* Detected loop in symbolic links */
+-#define SOL_ERESTART 91 /* System call is restartable */
+-#define SOL_ESTRPIPE 92 /* Do not sleep in head of stream */
+-#define SOL_ENOTEMPTY 93 /* Rmdir of non-empty directory */
+-#define SOL_EUSERS 94 /* Over abundance of users for ufs */
+-#define SOL_ENOTSOCK 95 /* Sock-op on non-sock */
+-#define SOL_EDESTADDRREQ 96 /* No dest addr given, but needed */
+-#define SOL_EMSGSIZE 97 /* Msg too big */
+-#define SOL_EPROTOTYPE 98 /* Bad socket protocol */
+-#define SOL_ENOPROTOOPT 99 /* Unavailable protocol */
+-#define SOL_EPROTONOSUPPORT 120 /* Unsupported protocol */
+-#define SOL_ESOCKTNOSUPPORT 121 /* Unsupported socket type */
+-#define SOL_EOPNOTSUPP 122 /* Unsupported sock-op */
+-#define SOL_EPFNOSUPPORT 123 /* Unsupported protocol family */
+-#define SOL_EAFNOSUPPORT 124 /* Unsup addr family for protocol */
+-#define SOL_EADDRINUSE 125 /* Req addr is already in use */
+-#define SOL_EADDRNOTAVAIL 126 /* Req addr not available right now */
+-#define SOL_ENETDOWN 127 /* Your subnet is on fire */
+-#define SOL_ENETUNREACH 128 /* Someone playing with gateway and */
+- /* did not tell you he was going to */
+-#define SOL_ENETRESET 129 /* Buy less-buggy ethernet cards */
+-#define SOL_ECONNABORTED 130 /* Aborted connection due to sw */
+-#define SOL_ECONNRESET 131 /* Your peers reset your connection */
+-#define SOL_ENOBUFS 132 /* No buffer space available */
+-#define SOL_EISCONN 133 /* Connect on already connected */
+- /* socket attempted */
+-#define SOL_ENOTCONN 134 /* Comm on non-connected socket */
+-#define SOL_ESHUTDOWN 143 /* Op attempted after sock-shutdown */
+-#define SOL_ETOOMANYREFS 144 /* Reference limit exceeded */
+-#define SOL_ETIMEDOUT 145 /* Timed out connection */
+-#define SOL_ECONNREFUSED 146 /* Connection refused by remote host*/
+-#define SOL_EHOSTDOWN 147 /* Remote host is up in flames */
+-#define SOL_EHOSTUNREACH 148 /* Make a left at Easton Ave..... */
+-#define SOL_EWOULDBLOCK EAGAIN /* Just an alias */
+-#define SOL_EALREADY 149 /* Operation is already occurring */
+-#define SOL_EINPROGRESS 150 /* Operation is happening now */
+-#define SOL_ESTALE 151 /* Fungus growth on NFS file handle */
+-
+-#endif /* !(_SPARC64_SOLERRNO_H) */
+diff --git a/include/asm-sparc64/sparsemem.h b/include/asm-sparc64/sparsemem.h
+index 77bcd2b..b99d4e4 100644
+--- a/include/asm-sparc64/sparsemem.h
++++ b/include/asm-sparc64/sparsemem.h
+@@ -3,7 +3,7 @@
+
+ #ifdef __KERNEL__
+
+-#define SECTION_SIZE_BITS 31
++#define SECTION_SIZE_BITS 30
+ #define MAX_PHYSADDR_BITS 42
+ #define MAX_PHYSMEM_BITS 42
+
+diff --git a/include/asm-sparc64/svr4.h b/include/asm-sparc64/svr4.h
+deleted file mode 100644
+index c96d5f1..0000000
+--- a/include/asm-sparc64/svr4.h
++++ /dev/null
+@@ -1,120 +0,0 @@
+-/* Solaris/SPARC constants and definitions --
+- * (C) 1996 Miguel de Icaza
+- *
+- * This file is not meant to be included by user level applications
+- * but the solaris syscall emulator
+- */
+-
+-#ifndef _SPARC64_SVR4_H
+-#define _SPARC64_SVR4_H
+-
+-/* Signals as used by svr4 */
+-typedef struct { /* signal set type */
+- uint sigbits[4];
+-} svr4_sigset_t;
+-
+-/* Values for siginfo.code */
+-#define SVR4_SINOINFO 32767
+-/* Siginfo, sucker expects bunch of information on those parameters */
+-typedef union {
+- char total_size [128];
+- struct {
+- int signo;
+- int code;
+- int error;
+- union {
+- } data;
+- } siginfo;
+-} svr4_siginfo_t;
+-
+-/* Context definition */
+-
+-/* Location of the user stored registers into a greg_t */
+-enum {
+- SVR4_PSR, SVR4_PC, SVR4_NPC, SVR4_Y,
+- SVR4_G1, SVR4_G2, SVR4_G3, SVR4_G4,
+- SVR4_G5, SVR4_G6, SVR4_G7, SVR4_O0,
+- SVR4_O1, SVR4_O2, SVR4_O3, SVR4_O4,
+- SVR4_O5, SVR4_O6, SVR4_O7
+-};
+-
+-/* sizeof (regs) / sizeof (greg_t), defined in the ABI */
+-#define SVR4_NREGS 19
+-#define SVR4_MAXWIN 31
+-
+-typedef struct {
+- u32 rwin_lo[8];
+- u32 rwin_in[8];
+-} svr4_rwindow_t;
+-
+-typedef struct {
+- int count;
+- u32 winptr [SVR4_MAXWIN]; /* pointer to the windows */
+-
+- svr4_rwindow_t win[SVR4_MAXWIN]; /* the windows */
+-} svr4_gwindows_t;
+-
+-typedef int svr4_gregset_t[SVR4_NREGS];
+-
+-typedef struct {
+- u64 fpu_regs[32];
+- u32 fp_q;
+- u32 fp_fsr;
+- u_char fp_nqel;
+- u_char fp_nqsize;
+- u_char inuse; /* if fpu is in use */
+-} svr4_fregset_t;
+-
+-typedef struct {
+- u32 id; /* if this holds "xrs" string => ptr is valid */
+- u32 ptr;
+-} svr4_xrs_t;
+-
+-/* Machine dependent context */
+-typedef struct {
+- svr4_gregset_t greg; /* registers 0..19 (see top) */
+- u32 gwin; /* may point to register windows */
+- svr4_fregset_t freg; /* floating point registers */
+- svr4_xrs_t xrs; /* mhm? */
+- int pad[19];
+-} svr4_mcontext_t;
+-
+-/* flags for stack_t.flags */
+-enum svr4_stack_flags {
+- SVR4_SS_ONSTACK,
+- SVR4_SS_DISABLE,
+-};
+-
+-/* signal stack execution place, unsupported */
+-typedef struct svr4_stack_t {
+- u32 sp;
+- int size;
+- int flags;
+-} svr4_stack_t;
+-
+-/* Context used by getcontext and setcontext */
+-typedef struct svr4_ucontext_t {
+- u32 flags; /* context flags, indicate what is loaded */
+- u32 link;
+- svr4_sigset_t sigmask;
+- svr4_stack_t stack;
+- svr4_mcontext_t mcontext;
+- int pad[23];
+-} svr4_ucontext_t;
+-
+-/* windows hold the windows as they were at signal time,
+- * ucontext->mcontext holds a pointer to them.
+- * addresses for uc and si are passed as parameters to svr4 signal
+- * handler
+- */
+-
+-/* This is the signal frame that is passed to the signal handler */
+-typedef struct {
+- svr4_gwindows_t gw; /* windows */
+- svr4_ucontext_t uc; /* machine context */
+- svr4_siginfo_t si; /* siginfo */
+-} svr4_signal_frame_t;
+-
+-#define SVR4_SF_ALIGNED (((sizeof (svr4_signal_frame_t) + 7) & (~7)))
+-
+-#endif /* include control */
+diff --git a/include/asm-sparc64/termios.h b/include/asm-sparc64/termios.h
+index ef52721..cacbea1 100644
+--- a/include/asm-sparc64/termios.h
++++ b/include/asm-sparc64/termios.h
+@@ -33,11 +33,6 @@ struct ltchars {
+ };
+ #endif /* __KERNEL__ */
+
+-struct sunos_ttysize {
+- int st_lines; /* Lines on the terminal */
+- int st_columns; /* Columns on the terminal */
+-};
+-
+ struct winsize {
+ unsigned short ws_row;
+ unsigned short ws_col;
+diff --git a/include/asm-sparc64/topology.h b/include/asm-sparc64/topology.h
+index c6b5570..001c040 100644
+--- a/include/asm-sparc64/topology.h
++++ b/include/asm-sparc64/topology.h
+@@ -1,6 +1,77 @@
+ #ifndef _ASM_SPARC64_TOPOLOGY_H
+ #define _ASM_SPARC64_TOPOLOGY_H
+
++#ifdef CONFIG_NUMA
++
++#include <asm/mmzone.h>
++
++static inline int cpu_to_node(int cpu)
++{
++ return numa_cpu_lookup_table[cpu];
++}
++
++#define parent_node(node) (node)
++
++static inline cpumask_t node_to_cpumask(int node)
++{
++ return numa_cpumask_lookup_table[node];
++}
++
++/* Returns a pointer to the cpumask of CPUs on Node 'node'. */
++#define node_to_cpumask_ptr(v, node) \
++ cpumask_t *v = &(numa_cpumask_lookup_table[node])
++
++#define node_to_cpumask_ptr_next(v, node) \
++ v = &(numa_cpumask_lookup_table[node])
++
++static inline int node_to_first_cpu(int node)
++{
++ cpumask_t tmp;
++ tmp = node_to_cpumask(node);
++ return first_cpu(tmp);
++}
++
++struct pci_bus;
++#ifdef CONFIG_PCI
++extern int pcibus_to_node(struct pci_bus *pbus);
++#else
++static inline int pcibus_to_node(struct pci_bus *pbus)
++{
++ return -1;
++}
++#endif
++
++#define pcibus_to_cpumask(bus) \
++ (pcibus_to_node(bus) == -1 ? \
++ CPU_MASK_ALL : \
++ node_to_cpumask(pcibus_to_node(bus)))
++
++#define SD_NODE_INIT (struct sched_domain) { \
++ .min_interval = 8, \
++ .max_interval = 32, \
++ .busy_factor = 32, \
++ .imbalance_pct = 125, \
++ .cache_nice_tries = 2, \
++ .busy_idx = 3, \
++ .idle_idx = 2, \
++ .newidle_idx = 0, \
++ .wake_idx = 1, \
++ .forkexec_idx = 1, \
++ .flags = SD_LOAD_BALANCE \
++ | SD_BALANCE_FORK \
++ | SD_BALANCE_EXEC \
++ | SD_SERIALIZE \
++ | SD_WAKE_BALANCE, \
++ .last_balance = jiffies, \
++ .balance_interval = 1, \
++}
++
++#else /* CONFIG_NUMA */
++
++#include <asm-generic/topology.h>
++
++#endif /* !(CONFIG_NUMA) */
++
+ #ifdef CONFIG_SMP
+ #define topology_physical_package_id(cpu) (cpu_data(cpu).proc_id)
+ #define topology_core_id(cpu) (cpu_data(cpu).core_id)
+@@ -10,8 +81,6 @@
+ #define smt_capable() (sparc64_multi_core)
+ #endif /* CONFIG_SMP */
+
+-#include <asm-generic/topology.h>
+-
+ #define cpu_coregroup_map(cpu) (cpu_core_map[cpu])
+
+ #endif /* _ASM_SPARC64_TOPOLOGY_H */
+diff --git a/include/asm-sparc64/ttable.h b/include/asm-sparc64/ttable.h
+index bbb9c8f..d3cc4ef 100644
+--- a/include/asm-sparc64/ttable.h
++++ b/include/asm-sparc64/ttable.h
+@@ -28,7 +28,7 @@
+ call routine; \
+ add %sp, PTREGS_OFF, %o0; \
+ ba,pt %xcc, rtrap; \
+- clr %l6; \
++ nop; \
+ nop;
+
+ #define TRAP_7INSNS(routine) \
+@@ -38,7 +38,7 @@
+ call routine; \
+ add %sp, PTREGS_OFF, %o0; \
+ ba,pt %xcc, rtrap; \
+- clr %l6;
++ nop;
+
+ #define TRAP_SAVEFPU(routine) \
+ sethi %hi(109f), %g7; \
+@@ -47,7 +47,7 @@
+ call routine; \
+ add %sp, PTREGS_OFF, %o0; \
+ ba,pt %xcc, rtrap; \
+- clr %l6; \
++ nop; \
+ nop;
+
+ #define TRAP_NOSAVE(routine) \
+@@ -67,7 +67,7 @@
+ call routine; \
+ add %sp, PTREGS_OFF, %o0; \
+ ba,pt %xcc, rtrap; \
+- clr %l6; \
++ nop; \
+ nop;
+
+ #define TRAP_ARG(routine, arg) \
+@@ -78,7 +78,7 @@
+ call routine; \
+ mov arg, %o1; \
+ ba,pt %xcc, rtrap; \
+- clr %l6;
++ nop;
+
+ #define TRAPTL1_ARG(routine, arg) \
+ sethi %hi(109f), %g7; \
+@@ -88,7 +88,7 @@
+ call routine; \
+ mov arg, %o1; \
+ ba,pt %xcc, rtrap; \
+- clr %l6;
++ nop;
+
+ #define SYSCALL_TRAP(routine, systbl) \
+ sethi %hi(109f), %g7; \
+@@ -99,14 +99,6 @@
+ or %l7, %lo(systbl), %l7; \
+ nop; nop;
+
+-#define INDIRECT_SOLARIS_SYSCALL(num) \
+- sethi %hi(109f), %g7; \
+- ba,pt %xcc, etrap; \
+-109: or %g7, %lo(109b), %g7; \
+- ba,pt %xcc, tl0_solaris + 0xc; \
+- mov num, %g1; \
+- nop;nop;nop;
+-
+ #define TRAP_UTRAP(handler,lvl) \
+ mov handler, %g3; \
+ ba,pt %xcc, utrap_trap; \
+@@ -117,11 +109,6 @@
+ nop; \
+ nop;
+
+-#ifdef CONFIG_SUNOS_EMUL
+-#define SUNOS_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall32, sunos_sys_table)
+-#else
+-#define SUNOS_SYSCALL_TRAP TRAP(sunos_syscall)
+-#endif
+ #ifdef CONFIG_COMPAT
+ #define LINUX_32BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall32, sys_call_table32)
+ #else
+@@ -130,11 +117,6 @@
+ #define LINUX_64BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall, sys_call_table64)
+ #define GETCC_TRAP TRAP(getcc)
+ #define SETCC_TRAP TRAP(setcc)
+-#ifdef CONFIG_SOLARIS_EMUL
+-#define SOLARIS_SYSCALL_TRAP TRAP(solaris_sparc_syscall)
+-#else
+-#define SOLARIS_SYSCALL_TRAP TRAP(solaris_syscall)
+-#endif
+ #define BREAKPOINT_TRAP TRAP(breakpoint_trap)
+
+ #ifdef CONFIG_TRACE_IRQFLAGS
+@@ -184,7 +166,7 @@
+ ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1; \
+ add %l1, 4, %l2; \
+ stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC]; \
+- ba,pt %xcc, rtrap_clr_l6; \
++ ba,pt %xcc, rtrap; \
+ stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC];
+
+ #ifdef CONFIG_KPROBES
+diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
+index 77559da..13be445 100644
+--- a/include/asm-sparc64/unistd.h
++++ b/include/asm-sparc64/unistd.h
+@@ -338,16 +338,6 @@
+ #define NR_SYSCALLS 317
+
+ #ifdef __KERNEL__
+-/* sysconf options, for SunOS compatibility */
+-#define _SC_ARG_MAX 1
+-#define _SC_CHILD_MAX 2
+-#define _SC_CLK_TCK 3
+-#define _SC_NGROUPS_MAX 4
+-#define _SC_OPEN_MAX 5
+-#define _SC_JOB_CONTROL 6
+-#define _SC_SAVED_IDS 7
+-#define _SC_VERSION 8
+-
+ #define __ARCH_WANT_IPC_PARSE_VERSION
+ #define __ARCH_WANT_OLD_READDIR
+ #define __ARCH_WANT_STAT64
+diff --git a/include/asm-sparc64/user.h b/include/asm-sparc64/user.h
+index 02b1389..29fc6e9 100644
+--- a/include/asm-sparc64/user.h
++++ b/include/asm-sparc64/user.h
+@@ -1,60 +1 @@
+-/* $Id: user.h,v 1.1 1996/12/26 14:22:44 davem Exp $
+- * asm-sparc64/user.h: Core file definitions for the Sparc.
+- *
+- * Keep in sync with reg.h. Actually, we could get rid of this
+- * one, since we won't a.out core dump that much anyways - miguel.
+- * Copyright (C) 1995 (davem at caip.rutgers.edu)
+- */
+-#ifndef _SPARC64_USER_H
+-#define _SPARC64_USER_H
+-
+-#include <linux/a.out.h>
+-struct sunos_regs {
+- unsigned int psr, pc, npc, y;
+- unsigned int regs[15];
+-};
+-
+-struct sunos_fpqueue {
+- unsigned int *addr;
+- unsigned int inst;
+-};
+-
+-struct sunos_fp {
+- union {
+- unsigned int regs[32];
+- double reg_dbls[16];
+- } fregs;
+- unsigned int fsr;
+- unsigned int flags;
+- unsigned int extra;
+- unsigned int fpq_count;
+- struct sunos_fpqueue fpq[16];
+-};
+-
+-struct sunos_fpu {
+- struct sunos_fp fpstatus;
+-};
+-
+-/* The SunOS core file header layout. */
+-struct user {
+- unsigned int magic;
+- unsigned int len;
+- struct sunos_regs regs;
+- struct exec uexec;
+- int signal;
+- size_t u_tsize; /* all of these in bytes! */
+- size_t u_dsize;
+- size_t u_ssize;
+- char u_comm[17];
+- struct sunos_fpu fpu;
+- unsigned int sigcode; /* Special sigcontext subcode, if any */
+-};
+-
+-#define NBPG PAGE_SIZE /* XXX 4096 maybe? */
+-#define UPAGES 1
+-#define HOST_TEXT_START_ADDR (u.start_code)
+-#define HOST_DATA_START_ADDR (u.start_data)
+-#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
+-#define SUNOS_CORE_MAGIC 0x080456
+-
+-#endif /* !(_SPARC64_USER_H) */
++#include <asm-sparc/user.h>
+diff --git a/include/asm-um/semaphore.h b/include/asm-um/semaphore.h
+index ff13c34..d9b2034 100644
+--- a/include/asm-um/semaphore.h
++++ b/include/asm-um/semaphore.h
+@@ -1,6 +1 @@
+-#ifndef __UM_SEMAPHORE_H
+-#define __UM_SEMAPHORE_H
+-
+-#include "asm/arch/semaphore.h"
+-
+-#endif
++#include <linux/semaphore.h>
+diff --git a/include/asm-v850/semaphore.h b/include/asm-v850/semaphore.h
+index 10ed0cc..d9b2034 100644
+--- a/include/asm-v850/semaphore.h
++++ b/include/asm-v850/semaphore.h
+@@ -1,84 +1 @@
+-#ifndef __V850_SEMAPHORE_H__
+-#define __V850_SEMAPHORE_H__
+-
+-#include <linux/linkage.h>
+-#include <linux/spinlock.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-#include <asm/atomic.h>
+-
+-struct semaphore {
+- atomic_t count;
+- int sleepers;
+- wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name,count) \
+- { ATOMIC_INIT (count), 0, \
+- __WAIT_QUEUE_HEAD_INITIALIZER ((name).wait) }
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+- struct semaphore name = __SEMAPHORE_INITIALIZER (name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC (name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+- *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+- sema_init (sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+- sema_init (sem, 0);
+-}
+-
+-/*
+- * special register calling convention
+- */
+-asmlinkage void __down_failed (void);
+-asmlinkage int __down_interruptible_failed (void);
+-asmlinkage int __down_trylock_failed (void);
+-asmlinkage void __up_wakeup (void);
+-
+-extern void __down (struct semaphore * sem);
+-extern int __down_interruptible (struct semaphore * sem);
+-extern int __down_trylock (struct semaphore * sem);
+-extern void __up (struct semaphore * sem);
+-
+-static inline void down (struct semaphore * sem)
+-{
+- might_sleep();
+- if (atomic_dec_return (&sem->count) < 0)
+- __down (sem);
+-}
+-
+-static inline int down_interruptible (struct semaphore * sem)
+-{
+- int ret = 0;
+- might_sleep();
+- if (atomic_dec_return (&sem->count) < 0)
+- ret = __down_interruptible (sem);
+- return ret;
+-}
+-
+-static inline int down_trylock (struct semaphore *sem)
+-{
+- int ret = 0;
+- if (atomic_dec_return (&sem->count) < 0)
+- ret = __down_trylock (sem);
+- return ret;
+-}
+-
+-static inline void up (struct semaphore * sem)
+-{
+- if (atomic_inc_return (&sem->count) <= 0)
+- __up (sem);
+-}
+-
+-#endif /* __V850_SEMAPHORE_H__ */
++#include <linux/semaphore.h>
+diff --git a/include/asm-x86/Kbuild b/include/asm-x86/Kbuild
+index 3b8160a..1e35545 100644
+--- a/include/asm-x86/Kbuild
++++ b/include/asm-x86/Kbuild
+@@ -10,6 +10,7 @@ header-y += prctl.h
+ header-y += ptrace-abi.h
+ header-y += sigcontext32.h
+ header-y += ucontext.h
++header-y += processor-flags.h
+
+ unifdef-y += e820.h
+ unifdef-y += ist.h
+diff --git a/include/asm-x86/a.out-core.h b/include/asm-x86/a.out-core.h
+index d2b6e11..714207a 100644
+--- a/include/asm-x86/a.out-core.h
++++ b/include/asm-x86/a.out-core.h
+@@ -29,8 +29,9 @@ static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump)
+ dump->magic = CMAGIC;
+ dump->start_code = 0;
+ dump->start_stack = regs->sp & ~(PAGE_SIZE - 1);
+- dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
+- dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
++ dump->u_tsize = ((unsigned long)current->mm->end_code) >> PAGE_SHIFT;
++ dump->u_dsize = ((unsigned long)(current->mm->brk + (PAGE_SIZE - 1)))
++ >> PAGE_SHIFT;
+ dump->u_dsize -= dump->u_tsize;
+ dump->u_ssize = 0;
+ dump->u_debugreg[0] = current->thread.debugreg0;
+@@ -43,7 +44,8 @@ static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump)
+ dump->u_debugreg[7] = current->thread.debugreg7;
+
+ if (dump->start_stack < TASK_SIZE)
+- dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
++ dump->u_ssize = ((unsigned long)(TASK_SIZE - dump->start_stack))
++ >> PAGE_SHIFT;
+
+ dump->regs.bx = regs->bx;
+ dump->regs.cx = regs->cx;
+@@ -55,7 +57,7 @@ static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump)
+ dump->regs.ds = (u16)regs->ds;
+ dump->regs.es = (u16)regs->es;
+ dump->regs.fs = (u16)regs->fs;
+- savesegment(gs,gs);
++ savesegment(gs, gs);
+ dump->regs.orig_ax = regs->orig_ax;
+ dump->regs.ip = regs->ip;
+ dump->regs.cs = (u16)regs->cs;
+@@ -63,7 +65,7 @@ static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump)
+ dump->regs.sp = regs->sp;
+ dump->regs.ss = (u16)regs->ss;
+
+- dump->u_fpvalid = dump_fpu (regs, &dump->i387);
++ dump->u_fpvalid = dump_fpu(regs, &dump->i387);
+ }
+
+ #endif /* CONFIG_X86_32 */
+diff --git a/include/asm-x86/acpi.h b/include/asm-x86/acpi.h
+index 7a72d6a..14411c9 100644
+--- a/include/asm-x86/acpi.h
++++ b/include/asm-x86/acpi.h
+@@ -67,16 +67,16 @@ int __acpi_release_global_lock(unsigned int *lock);
+ */
+ #define ACPI_DIV_64_BY_32(n_hi, n_lo, d32, q32, r32) \
+ asm("divl %2;" \
+- :"=a"(q32), "=d"(r32) \
+- :"r"(d32), \
++ : "=a"(q32), "=d"(r32) \
++ : "r"(d32), \
+ "0"(n_lo), "1"(n_hi))
+
+
+ #define ACPI_SHIFT_RIGHT_64(n_hi, n_lo) \
+ asm("shrl $1,%2 ;" \
+ "rcrl $1,%3;" \
+- :"=r"(n_hi), "=r"(n_lo) \
+- :"0"(n_hi), "1"(n_lo))
++ : "=r"(n_hi), "=r"(n_lo) \
++ : "0"(n_hi), "1"(n_lo))
+
+ #ifdef CONFIG_ACPI
+ extern int acpi_lapic;
+diff --git a/include/asm-x86/alternative.h b/include/asm-x86/alternative.h
+index d8bacf3..1f6a9ca 100644
+--- a/include/asm-x86/alternative.h
++++ b/include/asm-x86/alternative.h
+@@ -66,8 +66,8 @@ extern void alternatives_smp_module_del(struct module *mod);
+ extern void alternatives_smp_switch(int smp);
+ #else
+ static inline void alternatives_smp_module_add(struct module *mod, char *name,
+- void *locks, void *locks_end,
+- void *text, void *text_end) {}
++ void *locks, void *locks_end,
++ void *text, void *text_end) {}
+ static inline void alternatives_smp_module_del(struct module *mod) {}
+ static inline void alternatives_smp_switch(int smp) {}
+ #endif /* CONFIG_SMP */
+@@ -148,14 +148,34 @@ struct paravirt_patch_site;
+ void apply_paravirt(struct paravirt_patch_site *start,
+ struct paravirt_patch_site *end);
+ #else
+-static inline void
+-apply_paravirt(struct paravirt_patch_site *start,
+- struct paravirt_patch_site *end)
++static inline void apply_paravirt(struct paravirt_patch_site *start,
++ struct paravirt_patch_site *end)
+ {}
+ #define __parainstructions NULL
+ #define __parainstructions_end NULL
+ #endif
+
+-extern void text_poke(void *addr, unsigned char *opcode, int len);
++extern void add_nops(void *insns, unsigned int len);
++
++/*
++ * Clear and restore the kernel write-protection flag on the local CPU.
++ * Allows the kernel to edit read-only pages.
++ * Side-effect: any interrupt handler running between save and restore will have
++ * the ability to write to read-only pages.
++ *
++ * Warning:
++ * Code patching in the UP case is safe if NMIs and MCE handlers are stopped and
++ * no thread can be preempted in the instructions being modified (no iret to an
++ * invalid instruction possible) or if the instructions are changed from a
++ * consistent state to another consistent state atomically.
++ * More care must be taken when modifying code in the SMP case because of
++ * Intel's errata.
++ * On the local CPU you need to be protected again NMI or MCE handlers seeing an
++ * inconsistent instruction while you patch.
++ * The _early version expects the memory to already be RW.
++ */
++
++extern void *text_poke(void *addr, const void *opcode, size_t len);
++extern void *text_poke_early(void *addr, const void *opcode, size_t len);
+
+ #endif /* _ASM_X86_ALTERNATIVE_H */
+diff --git a/include/asm-x86/apic.h b/include/asm-x86/apic.h
+index bcfc07f..be9639a 100644
+--- a/include/asm-x86/apic.h
++++ b/include/asm-x86/apic.h
+@@ -44,7 +44,6 @@ extern int apic_runs_main_timer;
+ extern int ioapic_force;
+ extern int disable_apic;
+ extern int disable_apic_timer;
+-extern unsigned boot_cpu_id;
+
+ /*
+ * Basic functions accessing APICs.
+@@ -59,6 +58,8 @@ extern unsigned boot_cpu_id;
+ #define setup_secondary_clock setup_secondary_APIC_clock
+ #endif
+
++extern int is_vsmp_box(void);
++
+ static inline void native_apic_write(unsigned long reg, u32 v)
+ {
+ *((volatile u32 *)(APIC_BASE + reg)) = v;
+@@ -66,7 +67,7 @@ static inline void native_apic_write(unsigned long reg, u32 v)
+
+ static inline void native_apic_write_atomic(unsigned long reg, u32 v)
+ {
+- (void) xchg((u32*)(APIC_BASE + reg), v);
++ (void)xchg((u32 *)(APIC_BASE + reg), v);
+ }
+
+ static inline u32 native_apic_read(unsigned long reg)
+@@ -123,7 +124,7 @@ extern void enable_NMI_through_LVT0(void);
+ * On 32bit this is mach-xxx local
+ */
+ #ifdef CONFIG_X86_64
+-extern void setup_apic_routing(void);
++extern void early_init_lapic_mapping(void);
+ #endif
+
+ extern u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask);
+diff --git a/include/asm-x86/apicdef.h b/include/asm-x86/apicdef.h
+index 550af7a..6b9008c 100644
+--- a/include/asm-x86/apicdef.h
++++ b/include/asm-x86/apicdef.h
+@@ -12,17 +12,15 @@
+
+ #define APIC_ID 0x20
+
+-#ifdef CONFIG_X86_64
+-# define APIC_ID_MASK (0xFFu<<24)
+-# define GET_APIC_ID(x) (((x)>>24)&0xFFu)
+-# define SET_APIC_ID(x) (((x)<<24))
+-#endif
+-
+ #define APIC_LVR 0x30
+ #define APIC_LVR_MASK 0xFF00FF
+-#define GET_APIC_VERSION(x) ((x)&0xFFu)
+-#define GET_APIC_MAXLVT(x) (((x)>>16)&0xFFu)
+-#define APIC_INTEGRATED(x) ((x)&0xF0u)
++#define GET_APIC_VERSION(x) ((x) & 0xFFu)
++#define GET_APIC_MAXLVT(x) (((x) >> 16) & 0xFFu)
++#ifdef CONFIG_X86_32
++# define APIC_INTEGRATED(x) ((x) & 0xF0u)
++#else
++# define APIC_INTEGRATED(x) (1)
++#endif
+ #define APIC_XAPIC(x) ((x) >= 0x14)
+ #define APIC_TASKPRI 0x80
+ #define APIC_TPRI_MASK 0xFFu
+@@ -33,16 +31,16 @@
+ #define APIC_EIO_ACK 0x0
+ #define APIC_RRR 0xC0
+ #define APIC_LDR 0xD0
+-#define APIC_LDR_MASK (0xFFu<<24)
+-#define GET_APIC_LOGICAL_ID(x) (((x)>>24)&0xFFu)
+-#define SET_APIC_LOGICAL_ID(x) (((x)<<24))
++#define APIC_LDR_MASK (0xFFu << 24)
++#define GET_APIC_LOGICAL_ID(x) (((x) >> 24) & 0xFFu)
++#define SET_APIC_LOGICAL_ID(x) (((x) << 24))
+ #define APIC_ALL_CPUS 0xFFu
+ #define APIC_DFR 0xE0
+ #define APIC_DFR_CLUSTER 0x0FFFFFFFul
+ #define APIC_DFR_FLAT 0xFFFFFFFFul
+ #define APIC_SPIV 0xF0
+-#define APIC_SPIV_FOCUS_DISABLED (1<<9)
+-#define APIC_SPIV_APIC_ENABLED (1<<8)
++#define APIC_SPIV_FOCUS_DISABLED (1 << 9)
++#define APIC_SPIV_APIC_ENABLED (1 << 8)
+ #define APIC_ISR 0x100
+ #define APIC_ISR_NR 0x8 /* Number of 32 bit ISR registers. */
+ #define APIC_TMR 0x180
+@@ -78,27 +76,27 @@
+ #define APIC_DM_EXTINT 0x00700
+ #define APIC_VECTOR_MASK 0x000FF
+ #define APIC_ICR2 0x310
+-#define GET_APIC_DEST_FIELD(x) (((x)>>24)&0xFF)
+-#define SET_APIC_DEST_FIELD(x) ((x)<<24)
++#define GET_APIC_DEST_FIELD(x) (((x) >> 24) & 0xFF)
++#define SET_APIC_DEST_FIELD(x) ((x) << 24)
+ #define APIC_LVTT 0x320
+ #define APIC_LVTTHMR 0x330
+ #define APIC_LVTPC 0x340
+ #define APIC_LVT0 0x350
+-#define APIC_LVT_TIMER_BASE_MASK (0x3<<18)
+-#define GET_APIC_TIMER_BASE(x) (((x)>>18)&0x3)
+-#define SET_APIC_TIMER_BASE(x) (((x)<<18))
++#define APIC_LVT_TIMER_BASE_MASK (0x3 << 18)
++#define GET_APIC_TIMER_BASE(x) (((x) >> 18) & 0x3)
++#define SET_APIC_TIMER_BASE(x) (((x) << 18))
+ #define APIC_TIMER_BASE_CLKIN 0x0
+ #define APIC_TIMER_BASE_TMBASE 0x1
+ #define APIC_TIMER_BASE_DIV 0x2
+-#define APIC_LVT_TIMER_PERIODIC (1<<17)
+-#define APIC_LVT_MASKED (1<<16)
+-#define APIC_LVT_LEVEL_TRIGGER (1<<15)
+-#define APIC_LVT_REMOTE_IRR (1<<14)
+-#define APIC_INPUT_POLARITY (1<<13)
+-#define APIC_SEND_PENDING (1<<12)
++#define APIC_LVT_TIMER_PERIODIC (1 << 17)
++#define APIC_LVT_MASKED (1 << 16)
++#define APIC_LVT_LEVEL_TRIGGER (1 << 15)
++#define APIC_LVT_REMOTE_IRR (1 << 14)
++#define APIC_INPUT_POLARITY (1 << 13)
++#define APIC_SEND_PENDING (1 << 12)
+ #define APIC_MODE_MASK 0x700
+-#define GET_APIC_DELIVERY_MODE(x) (((x)>>8)&0x7)
+-#define SET_APIC_DELIVERY_MODE(x, y) (((x)&~0x700)|((y)<<8))
++#define GET_APIC_DELIVERY_MODE(x) (((x) >> 8) & 0x7)
++#define SET_APIC_DELIVERY_MODE(x, y) (((x) & ~0x700) | ((y) << 8))
+ #define APIC_MODE_FIXED 0x0
+ #define APIC_MODE_NMI 0x4
+ #define APIC_MODE_EXTINT 0x7
+@@ -107,7 +105,7 @@
+ #define APIC_TMICT 0x380
+ #define APIC_TMCCT 0x390
+ #define APIC_TDCR 0x3E0
+-#define APIC_TDR_DIV_TMBASE (1<<2)
++#define APIC_TDR_DIV_TMBASE (1 << 2)
+ #define APIC_TDR_DIV_1 0xB
+ #define APIC_TDR_DIV_2 0x0
+ #define APIC_TDR_DIV_4 0x1
+@@ -117,14 +115,14 @@
+ #define APIC_TDR_DIV_64 0x9
+ #define APIC_TDR_DIV_128 0xA
+ #define APIC_EILVT0 0x500
+-#define APIC_EILVT_NR_AMD_K8 1 /* Number of extended interrupts */
++#define APIC_EILVT_NR_AMD_K8 1 /* # of extended interrupts */
+ #define APIC_EILVT_NR_AMD_10H 4
+-#define APIC_EILVT_LVTOFF(x) (((x)>>4)&0xF)
++#define APIC_EILVT_LVTOFF(x) (((x) >> 4) & 0xF)
+ #define APIC_EILVT_MSG_FIX 0x0
+ #define APIC_EILVT_MSG_SMI 0x2
+ #define APIC_EILVT_MSG_NMI 0x4
+ #define APIC_EILVT_MSG_EXT 0x7
+-#define APIC_EILVT_MASKED (1<<16)
++#define APIC_EILVT_MASKED (1 << 16)
+ #define APIC_EILVT1 0x510
+ #define APIC_EILVT2 0x520
+ #define APIC_EILVT3 0x530
+@@ -135,7 +133,7 @@
+ # define MAX_IO_APICS 64
+ #else
+ # define MAX_IO_APICS 128
+-# define MAX_LOCAL_APIC 256
++# define MAX_LOCAL_APIC 32768
+ #endif
+
+ /*
+@@ -408,6 +406,9 @@ struct local_apic {
+
+ #undef u32
+
+-#define BAD_APICID 0xFFu
+-
++#ifdef CONFIG_X86_32
++ #define BAD_APICID 0xFFu
++#else
++ #define BAD_APICID 0xFFFFu
++#endif
+ #endif
+diff --git a/include/asm-x86/atomic_32.h b/include/asm-x86/atomic_32.h
+index 437aac8..21a4825 100644
+--- a/include/asm-x86/atomic_32.h
++++ b/include/asm-x86/atomic_32.h
+@@ -15,138 +15,133 @@
+ * on us. We need to use _exactly_ the address the user gave us,
+ * not some alias that contains the same information.
+ */
+-typedef struct { int counter; } atomic_t;
++typedef struct {
++ int counter;
++} atomic_t;
+
+ #define ATOMIC_INIT(i) { (i) }
+
+ /**
+ * atomic_read - read atomic variable
+ * @v: pointer of type atomic_t
+- *
++ *
+ * Atomically reads the value of @v.
+- */
++ */
+ #define atomic_read(v) ((v)->counter)
+
+ /**
+ * atomic_set - set atomic variable
+ * @v: pointer of type atomic_t
+ * @i: required value
+- *
++ *
+ * Atomically sets the value of @v to @i.
+- */
+-#define atomic_set(v,i) (((v)->counter) = (i))
++ */
++#define atomic_set(v, i) (((v)->counter) = (i))
+
+ /**
+ * atomic_add - add integer to atomic variable
+ * @i: integer value to add
+ * @v: pointer of type atomic_t
+- *
++ *
+ * Atomically adds @i to @v.
+ */
+-static __inline__ void atomic_add(int i, atomic_t *v)
++static inline void atomic_add(int i, atomic_t *v)
+ {
+- __asm__ __volatile__(
+- LOCK_PREFIX "addl %1,%0"
+- :"+m" (v->counter)
+- :"ir" (i));
++ asm volatile(LOCK_PREFIX "addl %1,%0"
++ : "+m" (v->counter)
++ : "ir" (i));
+ }
+
+ /**
+ * atomic_sub - subtract integer from atomic variable
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+- *
++ *
+ * Atomically subtracts @i from @v.
+ */
+-static __inline__ void atomic_sub(int i, atomic_t *v)
++static inline void atomic_sub(int i, atomic_t *v)
+ {
+- __asm__ __volatile__(
+- LOCK_PREFIX "subl %1,%0"
+- :"+m" (v->counter)
+- :"ir" (i));
++ asm volatile(LOCK_PREFIX "subl %1,%0"
++ : "+m" (v->counter)
++ : "ir" (i));
+ }
+
+ /**
+ * atomic_sub_and_test - subtract value from variable and test result
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+- *
++ *
+ * Atomically subtracts @i from @v and returns
+ * true if the result is zero, or false for all
+ * other cases.
+ */
+-static __inline__ int atomic_sub_and_test(int i, atomic_t *v)
++static inline int atomic_sub_and_test(int i, atomic_t *v)
+ {
+ unsigned char c;
+
+- __asm__ __volatile__(
+- LOCK_PREFIX "subl %2,%0; sete %1"
+- :"+m" (v->counter), "=qm" (c)
+- :"ir" (i) : "memory");
++ asm volatile(LOCK_PREFIX "subl %2,%0; sete %1"
++ : "+m" (v->counter), "=qm" (c)
++ : "ir" (i) : "memory");
+ return c;
+ }
+
+ /**
+ * atomic_inc - increment atomic variable
+ * @v: pointer of type atomic_t
+- *
++ *
+ * Atomically increments @v by 1.
+- */
+-static __inline__ void atomic_inc(atomic_t *v)
++ */
++static inline void atomic_inc(atomic_t *v)
+ {
+- __asm__ __volatile__(
+- LOCK_PREFIX "incl %0"
+- :"+m" (v->counter));
++ asm volatile(LOCK_PREFIX "incl %0"
++ : "+m" (v->counter));
+ }
+
+ /**
+ * atomic_dec - decrement atomic variable
+ * @v: pointer of type atomic_t
+- *
++ *
+ * Atomically decrements @v by 1.
+- */
+-static __inline__ void atomic_dec(atomic_t *v)
++ */
++static inline void atomic_dec(atomic_t *v)
+ {
+- __asm__ __volatile__(
+- LOCK_PREFIX "decl %0"
+- :"+m" (v->counter));
++ asm volatile(LOCK_PREFIX "decl %0"
++ : "+m" (v->counter));
+ }
+
+ /**
+ * atomic_dec_and_test - decrement and test
+ * @v: pointer of type atomic_t
+- *
++ *
+ * Atomically decrements @v by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.
+- */
+-static __inline__ int atomic_dec_and_test(atomic_t *v)
++ */
++static inline int atomic_dec_and_test(atomic_t *v)
+ {
+ unsigned char c;
+
+- __asm__ __volatile__(
+- LOCK_PREFIX "decl %0; sete %1"
+- :"+m" (v->counter), "=qm" (c)
+- : : "memory");
++ asm volatile(LOCK_PREFIX "decl %0; sete %1"
++ : "+m" (v->counter), "=qm" (c)
++ : : "memory");
+ return c != 0;
+ }
+
+ /**
+- * atomic_inc_and_test - increment and test
++ * atomic_inc_and_test - increment and test
+ * @v: pointer of type atomic_t
+- *
++ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+- */
+-static __inline__ int atomic_inc_and_test(atomic_t *v)
++ */
++static inline int atomic_inc_and_test(atomic_t *v)
+ {
+ unsigned char c;
+
+- __asm__ __volatile__(
+- LOCK_PREFIX "incl %0; sete %1"
+- :"+m" (v->counter), "=qm" (c)
+- : : "memory");
++ asm volatile(LOCK_PREFIX "incl %0; sete %1"
++ : "+m" (v->counter), "=qm" (c)
++ : : "memory");
+ return c != 0;
+ }
+
+@@ -154,19 +149,18 @@ static __inline__ int atomic_inc_and_test(atomic_t *v)
+ * atomic_add_negative - add and test if negative
+ * @v: pointer of type atomic_t
+ * @i: integer value to add
+- *
++ *
+ * Atomically adds @i to @v and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.
+- */
+-static __inline__ int atomic_add_negative(int i, atomic_t *v)
++ */
++static inline int atomic_add_negative(int i, atomic_t *v)
+ {
+ unsigned char c;
+
+- __asm__ __volatile__(
+- LOCK_PREFIX "addl %2,%0; sets %1"
+- :"+m" (v->counter), "=qm" (c)
+- :"ir" (i) : "memory");
++ asm volatile(LOCK_PREFIX "addl %2,%0; sets %1"
++ : "+m" (v->counter), "=qm" (c)
++ : "ir" (i) : "memory");
+ return c;
+ }
+
+@@ -177,20 +171,19 @@ static __inline__ int atomic_add_negative(int i, atomic_t *v)
+ *
+ * Atomically adds @i to @v and returns @i + @v
+ */
+-static __inline__ int atomic_add_return(int i, atomic_t *v)
++static inline int atomic_add_return(int i, atomic_t *v)
+ {
+ int __i;
+ #ifdef CONFIG_M386
+ unsigned long flags;
+- if(unlikely(boot_cpu_data.x86 <= 3))
++ if (unlikely(boot_cpu_data.x86 <= 3))
+ goto no_xadd;
+ #endif
+ /* Modern 486+ processor */
+ __i = i;
+- __asm__ __volatile__(
+- LOCK_PREFIX "xaddl %0, %1"
+- :"+r" (i), "+m" (v->counter)
+- : : "memory");
++ asm volatile(LOCK_PREFIX "xaddl %0, %1"
++ : "+r" (i), "+m" (v->counter)
++ : : "memory");
+ return i + __i;
+
+ #ifdef CONFIG_M386
+@@ -210,9 +203,9 @@ no_xadd: /* Legacy 386 processor */
+ *
+ * Atomically subtracts @i from @v and returns @v - @i
+ */
+-static __inline__ int atomic_sub_return(int i, atomic_t *v)
++static inline int atomic_sub_return(int i, atomic_t *v)
+ {
+- return atomic_add_return(-i,v);
++ return atomic_add_return(-i, v);
+ }
+
+ #define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
+@@ -227,7 +220,7 @@ static __inline__ int atomic_sub_return(int i, atomic_t *v)
+ * Atomically adds @a to @v, so long as @v was not already @u.
+ * Returns non-zero if @v was not @u, and zero otherwise.
+ */
+-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
++static inline int atomic_add_unless(atomic_t *v, int a, int u)
+ {
+ int c, old;
+ c = atomic_read(v);
+@@ -244,17 +237,17 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+
+ #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+
+-#define atomic_inc_return(v) (atomic_add_return(1,v))
+-#define atomic_dec_return(v) (atomic_sub_return(1,v))
++#define atomic_inc_return(v) (atomic_add_return(1, v))
++#define atomic_dec_return(v) (atomic_sub_return(1, v))
+
+ /* These are x86-specific, used by some header files */
+-#define atomic_clear_mask(mask, addr) \
+-__asm__ __volatile__(LOCK_PREFIX "andl %0,%1" \
+-: : "r" (~(mask)),"m" (*addr) : "memory")
++#define atomic_clear_mask(mask, addr) \
++ asm volatile(LOCK_PREFIX "andl %0,%1" \
++ : : "r" (~(mask)), "m" (*(addr)) : "memory")
+
+-#define atomic_set_mask(mask, addr) \
+-__asm__ __volatile__(LOCK_PREFIX "orl %0,%1" \
+-: : "r" (mask),"m" (*(addr)) : "memory")
++#define atomic_set_mask(mask, addr) \
++ asm volatile(LOCK_PREFIX "orl %0,%1" \
++ : : "r" (mask), "m" (*(addr)) : "memory")
+
+ /* Atomic operations are already serializing on x86 */
+ #define smp_mb__before_atomic_dec() barrier()
+diff --git a/include/asm-x86/atomic_64.h b/include/asm-x86/atomic_64.h
+index 2d20a7a..3e0cd7d 100644
+--- a/include/asm-x86/atomic_64.h
++++ b/include/asm-x86/atomic_64.h
+@@ -22,140 +22,135 @@
+ * on us. We need to use _exactly_ the address the user gave us,
+ * not some alias that contains the same information.
+ */
+-typedef struct { int counter; } atomic_t;
++typedef struct {
++ int counter;
++} atomic_t;
+
+ #define ATOMIC_INIT(i) { (i) }
+
+ /**
+ * atomic_read - read atomic variable
+ * @v: pointer of type atomic_t
+- *
++ *
+ * Atomically reads the value of @v.
+- */
++ */
+ #define atomic_read(v) ((v)->counter)
+
+ /**
+ * atomic_set - set atomic variable
+ * @v: pointer of type atomic_t
+ * @i: required value
+- *
++ *
+ * Atomically sets the value of @v to @i.
+- */
+-#define atomic_set(v,i) (((v)->counter) = (i))
++ */
++#define atomic_set(v, i) (((v)->counter) = (i))
+
+ /**
+ * atomic_add - add integer to atomic variable
+ * @i: integer value to add
+ * @v: pointer of type atomic_t
+- *
++ *
+ * Atomically adds @i to @v.
+ */
+-static __inline__ void atomic_add(int i, atomic_t *v)
++static inline void atomic_add(int i, atomic_t *v)
+ {
+- __asm__ __volatile__(
+- LOCK_PREFIX "addl %1,%0"
+- :"=m" (v->counter)
+- :"ir" (i), "m" (v->counter));
++ asm volatile(LOCK_PREFIX "addl %1,%0"
++ : "=m" (v->counter)
++ : "ir" (i), "m" (v->counter));
+ }
+
+ /**
+ * atomic_sub - subtract the atomic variable
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+- *
++ *
+ * Atomically subtracts @i from @v.
+ */
+-static __inline__ void atomic_sub(int i, atomic_t *v)
++static inline void atomic_sub(int i, atomic_t *v)
+ {
+- __asm__ __volatile__(
+- LOCK_PREFIX "subl %1,%0"
+- :"=m" (v->counter)
+- :"ir" (i), "m" (v->counter));
++ asm volatile(LOCK_PREFIX "subl %1,%0"
++ : "=m" (v->counter)
++ : "ir" (i), "m" (v->counter));
+ }
+
+ /**
+ * atomic_sub_and_test - subtract value from variable and test result
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+- *
++ *
+ * Atomically subtracts @i from @v and returns
+ * true if the result is zero, or false for all
+ * other cases.
+ */
+-static __inline__ int atomic_sub_and_test(int i, atomic_t *v)
++static inline int atomic_sub_and_test(int i, atomic_t *v)
+ {
+ unsigned char c;
+
+- __asm__ __volatile__(
+- LOCK_PREFIX "subl %2,%0; sete %1"
+- :"=m" (v->counter), "=qm" (c)
+- :"ir" (i), "m" (v->counter) : "memory");
++ asm volatile(LOCK_PREFIX "subl %2,%0; sete %1"
++ : "=m" (v->counter), "=qm" (c)
++ : "ir" (i), "m" (v->counter) : "memory");
+ return c;
+ }
+
+ /**
+ * atomic_inc - increment atomic variable
+ * @v: pointer of type atomic_t
+- *
++ *
+ * Atomically increments @v by 1.
+- */
+-static __inline__ void atomic_inc(atomic_t *v)
++ */
++static inline void atomic_inc(atomic_t *v)
+ {
+- __asm__ __volatile__(
+- LOCK_PREFIX "incl %0"
+- :"=m" (v->counter)
+- :"m" (v->counter));
++ asm volatile(LOCK_PREFIX "incl %0"
++ : "=m" (v->counter)
++ : "m" (v->counter));
+ }
+
+ /**
+ * atomic_dec - decrement atomic variable
+ * @v: pointer of type atomic_t
+- *
++ *
+ * Atomically decrements @v by 1.
+- */
+-static __inline__ void atomic_dec(atomic_t *v)
++ */
++static inline void atomic_dec(atomic_t *v)
+ {
+- __asm__ __volatile__(
+- LOCK_PREFIX "decl %0"
+- :"=m" (v->counter)
+- :"m" (v->counter));
++ asm volatile(LOCK_PREFIX "decl %0"
++ : "=m" (v->counter)
++ : "m" (v->counter));
+ }
+
+ /**
+ * atomic_dec_and_test - decrement and test
+ * @v: pointer of type atomic_t
+- *
++ *
+ * Atomically decrements @v by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.
+- */
+-static __inline__ int atomic_dec_and_test(atomic_t *v)
++ */
++static inline int atomic_dec_and_test(atomic_t *v)
+ {
+ unsigned char c;
+
+- __asm__ __volatile__(
+- LOCK_PREFIX "decl %0; sete %1"
+- :"=m" (v->counter), "=qm" (c)
+- :"m" (v->counter) : "memory");
++ asm volatile(LOCK_PREFIX "decl %0; sete %1"
++ : "=m" (v->counter), "=qm" (c)
++ : "m" (v->counter) : "memory");
+ return c != 0;
+ }
+
+ /**
+- * atomic_inc_and_test - increment and test
++ * atomic_inc_and_test - increment and test
+ * @v: pointer of type atomic_t
+- *
++ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+- */
+-static __inline__ int atomic_inc_and_test(atomic_t *v)
++ */
++static inline int atomic_inc_and_test(atomic_t *v)
+ {
+ unsigned char c;
+
+- __asm__ __volatile__(
+- LOCK_PREFIX "incl %0; sete %1"
+- :"=m" (v->counter), "=qm" (c)
+- :"m" (v->counter) : "memory");
++ asm volatile(LOCK_PREFIX "incl %0; sete %1"
++ : "=m" (v->counter), "=qm" (c)
++ : "m" (v->counter) : "memory");
+ return c != 0;
+ }
+
+@@ -163,19 +158,18 @@ static __inline__ int atomic_inc_and_test(atomic_t *v)
+ * atomic_add_negative - add and test if negative
+ * @i: integer value to add
+ * @v: pointer of type atomic_t
+- *
++ *
+ * Atomically adds @i to @v and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.
+- */
+-static __inline__ int atomic_add_negative(int i, atomic_t *v)
++ */
++static inline int atomic_add_negative(int i, atomic_t *v)
+ {
+ unsigned char c;
+
+- __asm__ __volatile__(
+- LOCK_PREFIX "addl %2,%0; sets %1"
+- :"=m" (v->counter), "=qm" (c)
+- :"ir" (i), "m" (v->counter) : "memory");
++ asm volatile(LOCK_PREFIX "addl %2,%0; sets %1"
++ : "=m" (v->counter), "=qm" (c)
++ : "ir" (i), "m" (v->counter) : "memory");
+ return c;
+ }
+
+@@ -186,27 +180,28 @@ static __inline__ int atomic_add_negative(int i, atomic_t *v)
+ *
+ * Atomically adds @i to @v and returns @i + @v
+ */
+-static __inline__ int atomic_add_return(int i, atomic_t *v)
++static inline int atomic_add_return(int i, atomic_t *v)
+ {
+ int __i = i;
+- __asm__ __volatile__(
+- LOCK_PREFIX "xaddl %0, %1"
+- :"+r" (i), "+m" (v->counter)
+- : : "memory");
++ asm volatile(LOCK_PREFIX "xaddl %0, %1"
++ : "+r" (i), "+m" (v->counter)
++ : : "memory");
+ return i + __i;
+ }
+
+-static __inline__ int atomic_sub_return(int i, atomic_t *v)
++static inline int atomic_sub_return(int i, atomic_t *v)
+ {
+- return atomic_add_return(-i,v);
++ return atomic_add_return(-i, v);
+ }
+
+-#define atomic_inc_return(v) (atomic_add_return(1,v))
+-#define atomic_dec_return(v) (atomic_sub_return(1,v))
++#define atomic_inc_return(v) (atomic_add_return(1, v))
++#define atomic_dec_return(v) (atomic_sub_return(1, v))
+
+ /* An 64bit atomic type */
+
+-typedef struct { long counter; } atomic64_t;
++typedef struct {
++ long counter;
++} atomic64_t;
+
+ #define ATOMIC64_INIT(i) { (i) }
+
+@@ -226,7 +221,7 @@ typedef struct { long counter; } atomic64_t;
+ *
+ * Atomically sets the value of @v to @i.
+ */
+-#define atomic64_set(v,i) (((v)->counter) = (i))
++#define atomic64_set(v, i) (((v)->counter) = (i))
+
+ /**
+ * atomic64_add - add integer to atomic64 variable
+@@ -235,12 +230,11 @@ typedef struct { long counter; } atomic64_t;
+ *
+ * Atomically adds @i to @v.
+ */
+-static __inline__ void atomic64_add(long i, atomic64_t *v)
++static inline void atomic64_add(long i, atomic64_t *v)
+ {
+- __asm__ __volatile__(
+- LOCK_PREFIX "addq %1,%0"
+- :"=m" (v->counter)
+- :"ir" (i), "m" (v->counter));
++ asm volatile(LOCK_PREFIX "addq %1,%0"
++ : "=m" (v->counter)
++ : "ir" (i), "m" (v->counter));
+ }
+
+ /**
+@@ -250,12 +244,11 @@ static __inline__ void atomic64_add(long i, atomic64_t *v)
+ *
+ * Atomically subtracts @i from @v.
+ */
+-static __inline__ void atomic64_sub(long i, atomic64_t *v)
++static inline void atomic64_sub(long i, atomic64_t *v)
+ {
+- __asm__ __volatile__(
+- LOCK_PREFIX "subq %1,%0"
+- :"=m" (v->counter)
+- :"ir" (i), "m" (v->counter));
++ asm volatile(LOCK_PREFIX "subq %1,%0"
++ : "=m" (v->counter)
++ : "ir" (i), "m" (v->counter));
+ }
+
+ /**
+@@ -267,14 +260,13 @@ static __inline__ void atomic64_sub(long i, atomic64_t *v)
+ * true if the result is zero, or false for all
+ * other cases.
+ */
+-static __inline__ int atomic64_sub_and_test(long i, atomic64_t *v)
++static inline int atomic64_sub_and_test(long i, atomic64_t *v)
+ {
+ unsigned char c;
+
+- __asm__ __volatile__(
+- LOCK_PREFIX "subq %2,%0; sete %1"
+- :"=m" (v->counter), "=qm" (c)
+- :"ir" (i), "m" (v->counter) : "memory");
++ asm volatile(LOCK_PREFIX "subq %2,%0; sete %1"
++ : "=m" (v->counter), "=qm" (c)
++ : "ir" (i), "m" (v->counter) : "memory");
+ return c;
+ }
+
+@@ -284,12 +276,11 @@ static __inline__ int atomic64_sub_and_test(long i, atomic64_t *v)
+ *
+ * Atomically increments @v by 1.
+ */
+-static __inline__ void atomic64_inc(atomic64_t *v)
++static inline void atomic64_inc(atomic64_t *v)
+ {
+- __asm__ __volatile__(
+- LOCK_PREFIX "incq %0"
+- :"=m" (v->counter)
+- :"m" (v->counter));
++ asm volatile(LOCK_PREFIX "incq %0"
++ : "=m" (v->counter)
++ : "m" (v->counter));
+ }
+
+ /**
+@@ -298,12 +289,11 @@ static __inline__ void atomic64_inc(atomic64_t *v)
+ *
+ * Atomically decrements @v by 1.
+ */
+-static __inline__ void atomic64_dec(atomic64_t *v)
++static inline void atomic64_dec(atomic64_t *v)
+ {
+- __asm__ __volatile__(
+- LOCK_PREFIX "decq %0"
+- :"=m" (v->counter)
+- :"m" (v->counter));
++ asm volatile(LOCK_PREFIX "decq %0"
++ : "=m" (v->counter)
++ : "m" (v->counter));
+ }
+
+ /**
+@@ -314,14 +304,13 @@ static __inline__ void atomic64_dec(atomic64_t *v)
+ * returns true if the result is 0, or false for all other
+ * cases.
+ */
+-static __inline__ int atomic64_dec_and_test(atomic64_t *v)
++static inline int atomic64_dec_and_test(atomic64_t *v)
+ {
+ unsigned char c;
+
+- __asm__ __volatile__(
+- LOCK_PREFIX "decq %0; sete %1"
+- :"=m" (v->counter), "=qm" (c)
+- :"m" (v->counter) : "memory");
++ asm volatile(LOCK_PREFIX "decq %0; sete %1"
++ : "=m" (v->counter), "=qm" (c)
++ : "m" (v->counter) : "memory");
+ return c != 0;
+ }
+
+@@ -333,14 +322,13 @@ static __inline__ int atomic64_dec_and_test(atomic64_t *v)
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+-static __inline__ int atomic64_inc_and_test(atomic64_t *v)
++static inline int atomic64_inc_and_test(atomic64_t *v)
+ {
+ unsigned char c;
+
+- __asm__ __volatile__(
+- LOCK_PREFIX "incq %0; sete %1"
+- :"=m" (v->counter), "=qm" (c)
+- :"m" (v->counter) : "memory");
++ asm volatile(LOCK_PREFIX "incq %0; sete %1"
++ : "=m" (v->counter), "=qm" (c)
++ : "m" (v->counter) : "memory");
+ return c != 0;
+ }
+
+@@ -353,14 +341,13 @@ static __inline__ int atomic64_inc_and_test(atomic64_t *v)
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.
+ */
+-static __inline__ int atomic64_add_negative(long i, atomic64_t *v)
++static inline int atomic64_add_negative(long i, atomic64_t *v)
+ {
+ unsigned char c;
+
+- __asm__ __volatile__(
+- LOCK_PREFIX "addq %2,%0; sets %1"
+- :"=m" (v->counter), "=qm" (c)
+- :"ir" (i), "m" (v->counter) : "memory");
++ asm volatile(LOCK_PREFIX "addq %2,%0; sets %1"
++ : "=m" (v->counter), "=qm" (c)
++ : "ir" (i), "m" (v->counter) : "memory");
+ return c;
+ }
+
+@@ -371,29 +358,28 @@ static __inline__ int atomic64_add_negative(long i, atomic64_t *v)
+ *
+ * Atomically adds @i to @v and returns @i + @v
+ */
+-static __inline__ long atomic64_add_return(long i, atomic64_t *v)
++static inline long atomic64_add_return(long i, atomic64_t *v)
+ {
+ long __i = i;
+- __asm__ __volatile__(
+- LOCK_PREFIX "xaddq %0, %1;"
+- :"+r" (i), "+m" (v->counter)
+- : : "memory");
++ asm volatile(LOCK_PREFIX "xaddq %0, %1;"
++ : "+r" (i), "+m" (v->counter)
++ : : "memory");
+ return i + __i;
+ }
+
+-static __inline__ long atomic64_sub_return(long i, atomic64_t *v)
++static inline long atomic64_sub_return(long i, atomic64_t *v)
+ {
+- return atomic64_add_return(-i,v);
++ return atomic64_add_return(-i, v);
+ }
+
+-#define atomic64_inc_return(v) (atomic64_add_return(1,v))
+-#define atomic64_dec_return(v) (atomic64_sub_return(1,v))
++#define atomic64_inc_return(v) (atomic64_add_return(1, (v)))
++#define atomic64_dec_return(v) (atomic64_sub_return(1, (v)))
+
+-#define atomic64_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
++#define atomic64_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
+ #define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
+
+-#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
+-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
++#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
++#define atomic_xchg(v, new) (xchg(&((v)->counter), (new)))
+
+ /**
+ * atomic_add_unless - add unless the number is a given value
+@@ -404,7 +390,7 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t *v)
+ * Atomically adds @a to @v, so long as it was not @u.
+ * Returns non-zero if @v was not @u, and zero otherwise.
+ */
+-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
++static inline int atomic_add_unless(atomic_t *v, int a, int u)
+ {
+ int c, old;
+ c = atomic_read(v);
+@@ -430,7 +416,7 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+ * Atomically adds @a to @v, so long as it was not @u.
+ * Returns non-zero if @v was not @u, and zero otherwise.
+ */
+-static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
++static inline int atomic64_add_unless(atomic64_t *v, long a, long u)
+ {
+ long c, old;
+ c = atomic64_read(v);
+@@ -448,13 +434,14 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
+ #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+
+ /* These are x86-specific, used by some header files */
+-#define atomic_clear_mask(mask, addr) \
+-__asm__ __volatile__(LOCK_PREFIX "andl %0,%1" \
+-: : "r" (~(mask)),"m" (*addr) : "memory")
+-
+-#define atomic_set_mask(mask, addr) \
+-__asm__ __volatile__(LOCK_PREFIX "orl %0,%1" \
+-: : "r" ((unsigned)mask),"m" (*(addr)) : "memory")
++#define atomic_clear_mask(mask, addr) \
++ asm volatile(LOCK_PREFIX "andl %0,%1" \
++ : : "r" (~(mask)), "m" (*(addr)) : "memory")
++
++#define atomic_set_mask(mask, addr) \
++ asm volatile(LOCK_PREFIX "orl %0,%1" \
++ : : "r" ((unsigned)(mask)), "m" (*(addr)) \
++ : "memory")
+
+ /* Atomic operations are already serializing on x86 */
+ #define smp_mb__before_atomic_dec() barrier()
+diff --git a/include/asm-x86/bios_ebda.h b/include/asm-x86/bios_ebda.h
+new file mode 100644
+index 0000000..b4a46b7
+--- /dev/null
++++ b/include/asm-x86/bios_ebda.h
+@@ -0,0 +1,17 @@
++#ifndef _MACH_BIOS_EBDA_H
++#define _MACH_BIOS_EBDA_H
++
++#include <asm/io.h>
++
++/*
++ * there is a real-mode segmented pointer pointing to the
++ * 4K EBDA area at 0x40E.
++ */
++static inline unsigned int get_bios_ebda(void)
++{
++ unsigned int address = *(unsigned short *)phys_to_virt(0x40E);
++ address <<= 4;
++ return address; /* 0 means none */
++}
++
++#endif /* _MACH_BIOS_EBDA_H */
+diff --git a/include/asm-x86/bitops.h b/include/asm-x86/bitops.h
+index 1a23ce1..1ae7b27 100644
+--- a/include/asm-x86/bitops.h
++++ b/include/asm-x86/bitops.h
+@@ -23,10 +23,13 @@
+ #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1)
+ /* Technically wrong, but this avoids compilation errors on some gcc
+ versions. */
+-#define ADDR "=m" (*(volatile long *) addr)
++#define ADDR "=m" (*(volatile long *)addr)
++#define BIT_ADDR "=m" (((volatile int *)addr)[nr >> 5])
+ #else
+ #define ADDR "+m" (*(volatile long *) addr)
++#define BIT_ADDR "+m" (((volatile int *)addr)[nr >> 5])
+ #endif
++#define BASE_ADDR "m" (*(volatile int *)addr)
+
+ /**
+ * set_bit - Atomically set a bit in memory
+@@ -45,9 +48,7 @@
+ */
+ static inline void set_bit(int nr, volatile void *addr)
+ {
+- asm volatile(LOCK_PREFIX "bts %1,%0"
+- : ADDR
+- : "Ir" (nr) : "memory");
++ asm volatile(LOCK_PREFIX "bts %1,%0" : ADDR : "Ir" (nr) : "memory");
+ }
+
+ /**
+@@ -79,9 +80,7 @@ static inline void __set_bit(int nr, volatile void *addr)
+ */
+ static inline void clear_bit(int nr, volatile void *addr)
+ {
+- asm volatile(LOCK_PREFIX "btr %1,%0"
+- : ADDR
+- : "Ir" (nr));
++ asm volatile(LOCK_PREFIX "btr %1,%2" : BIT_ADDR : "Ir" (nr), BASE_ADDR);
+ }
+
+ /*
+@@ -100,7 +99,7 @@ static inline void clear_bit_unlock(unsigned nr, volatile void *addr)
+
+ static inline void __clear_bit(int nr, volatile void *addr)
+ {
+- asm volatile("btr %1,%0" : ADDR : "Ir" (nr));
++ asm volatile("btr %1,%2" : BIT_ADDR : "Ir" (nr), BASE_ADDR);
+ }
+
+ /*
+@@ -135,7 +134,7 @@ static inline void __clear_bit_unlock(unsigned nr, volatile void *addr)
+ */
+ static inline void __change_bit(int nr, volatile void *addr)
+ {
+- asm volatile("btc %1,%0" : ADDR : "Ir" (nr));
++ asm volatile("btc %1,%2" : BIT_ADDR : "Ir" (nr), BASE_ADDR);
+ }
+
+ /**
+@@ -149,8 +148,7 @@ static inline void __change_bit(int nr, volatile void *addr)
+ */
+ static inline void change_bit(int nr, volatile void *addr)
+ {
+- asm volatile(LOCK_PREFIX "btc %1,%0"
+- : ADDR : "Ir" (nr));
++ asm volatile(LOCK_PREFIX "btc %1,%2" : BIT_ADDR : "Ir" (nr), BASE_ADDR);
+ }
+
+ /**
+@@ -166,9 +164,7 @@ static inline int test_and_set_bit(int nr, volatile void *addr)
+ int oldbit;
+
+ asm volatile(LOCK_PREFIX "bts %2,%1\n\t"
+- "sbb %0,%0"
+- : "=r" (oldbit), ADDR
+- : "Ir" (nr) : "memory");
++ "sbb %0,%0" : "=r" (oldbit), ADDR : "Ir" (nr) : "memory");
+
+ return oldbit;
+ }
+@@ -198,10 +194,9 @@ static inline int __test_and_set_bit(int nr, volatile void *addr)
+ {
+ int oldbit;
+
+- asm("bts %2,%1\n\t"
+- "sbb %0,%0"
+- : "=r" (oldbit), ADDR
+- : "Ir" (nr));
++ asm volatile("bts %2,%3\n\t"
++ "sbb %0,%0"
++ : "=r" (oldbit), BIT_ADDR : "Ir" (nr), BASE_ADDR);
+ return oldbit;
+ }
+
+@@ -219,8 +214,7 @@ static inline int test_and_clear_bit(int nr, volatile void *addr)
+
+ asm volatile(LOCK_PREFIX "btr %2,%1\n\t"
+ "sbb %0,%0"
+- : "=r" (oldbit), ADDR
+- : "Ir" (nr) : "memory");
++ : "=r" (oldbit), ADDR : "Ir" (nr) : "memory");
+
+ return oldbit;
+ }
+@@ -238,10 +232,9 @@ static inline int __test_and_clear_bit(int nr, volatile void *addr)
+ {
+ int oldbit;
+
+- asm volatile("btr %2,%1\n\t"
++ asm volatile("btr %2,%3\n\t"
+ "sbb %0,%0"
+- : "=r" (oldbit), ADDR
+- : "Ir" (nr));
++ : "=r" (oldbit), BIT_ADDR : "Ir" (nr), BASE_ADDR);
+ return oldbit;
+ }
+
+@@ -250,10 +243,9 @@ static inline int __test_and_change_bit(int nr, volatile void *addr)
+ {
+ int oldbit;
+
+- asm volatile("btc %2,%1\n\t"
++ asm volatile("btc %2,%3\n\t"
+ "sbb %0,%0"
+- : "=r" (oldbit), ADDR
+- : "Ir" (nr) : "memory");
++ : "=r" (oldbit), BIT_ADDR : "Ir" (nr), BASE_ADDR);
+
+ return oldbit;
+ }
+@@ -272,8 +264,7 @@ static inline int test_and_change_bit(int nr, volatile void *addr)
+
+ asm volatile(LOCK_PREFIX "btc %2,%1\n\t"
+ "sbb %0,%0"
+- : "=r" (oldbit), ADDR
+- : "Ir" (nr) : "memory");
++ : "=r" (oldbit), ADDR : "Ir" (nr) : "memory");
+
+ return oldbit;
+ }
+@@ -288,10 +279,11 @@ static inline int variable_test_bit(int nr, volatile const void *addr)
+ {
+ int oldbit;
+
+- asm volatile("bt %2,%1\n\t"
++ asm volatile("bt %2,%3\n\t"
+ "sbb %0,%0"
+ : "=r" (oldbit)
+- : "m" (*(unsigned long *)addr), "Ir" (nr));
++ : "m" (((volatile const int *)addr)[nr >> 5]),
++ "Ir" (nr), BASE_ADDR);
+
+ return oldbit;
+ }
+@@ -310,6 +302,8 @@ static int test_bit(int nr, const volatile unsigned long *addr);
+ constant_test_bit((nr),(addr)) : \
+ variable_test_bit((nr),(addr)))
+
++#undef BASE_ADDR
++#undef BIT_ADDR
+ #undef ADDR
+
+ #ifdef CONFIG_X86_32
+diff --git a/include/asm-x86/bitops_32.h b/include/asm-x86/bitops_32.h
+index e4d75fc..2513a81 100644
+--- a/include/asm-x86/bitops_32.h
++++ b/include/asm-x86/bitops_32.h
+@@ -20,20 +20,22 @@ static inline int find_first_zero_bit(const unsigned long *addr, unsigned size)
+
+ if (!size)
+ return 0;
+- /* This looks at memory. Mark it volatile to tell gcc not to move it around */
+- __asm__ __volatile__(
+- "movl $-1,%%eax\n\t"
+- "xorl %%edx,%%edx\n\t"
+- "repe; scasl\n\t"
+- "je 1f\n\t"
+- "xorl -4(%%edi),%%eax\n\t"
+- "subl $4,%%edi\n\t"
+- "bsfl %%eax,%%edx\n"
+- "1:\tsubl %%ebx,%%edi\n\t"
+- "shll $3,%%edi\n\t"
+- "addl %%edi,%%edx"
+- :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
+- :"1" ((size + 31) >> 5), "2" (addr), "b" (addr) : "memory");
++ /* This looks at memory.
++ * Mark it volatile to tell gcc not to move it around
++ */
++ asm volatile("movl $-1,%%eax\n\t"
++ "xorl %%edx,%%edx\n\t"
++ "repe; scasl\n\t"
++ "je 1f\n\t"
++ "xorl -4(%%edi),%%eax\n\t"
++ "subl $4,%%edi\n\t"
++ "bsfl %%eax,%%edx\n"
++ "1:\tsubl %%ebx,%%edi\n\t"
++ "shll $3,%%edi\n\t"
++ "addl %%edi,%%edx"
++ : "=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
++ : "1" ((size + 31) >> 5), "2" (addr),
++ "b" (addr) : "memory");
+ return res;
+ }
+
+@@ -75,7 +77,7 @@ static inline unsigned find_first_bit(const unsigned long *addr, unsigned size)
+ unsigned long val = *addr++;
+ if (val)
+ return __ffs(val) + x;
+- x += (sizeof(*addr)<<3);
++ x += sizeof(*addr) << 3;
+ }
+ return x;
+ }
+@@ -152,10 +154,10 @@ static inline int fls(int x)
+
+ #include <asm-generic/bitops/ext2-non-atomic.h>
+
+-#define ext2_set_bit_atomic(lock, nr, addr) \
+- test_and_set_bit((nr), (unsigned long *)addr)
+-#define ext2_clear_bit_atomic(lock, nr, addr) \
+- test_and_clear_bit((nr), (unsigned long *)addr)
++#define ext2_set_bit_atomic(lock, nr, addr) \
++ test_and_set_bit((nr), (unsigned long *)(addr))
++#define ext2_clear_bit_atomic(lock, nr, addr) \
++ test_and_clear_bit((nr), (unsigned long *)(addr))
+
+ #include <asm-generic/bitops/minix.h>
+
+diff --git a/include/asm-x86/bitops_64.h b/include/asm-x86/bitops_64.h
+index aaf1519..365f820 100644
+--- a/include/asm-x86/bitops_64.h
++++ b/include/asm-x86/bitops_64.h
+@@ -17,35 +17,35 @@ static inline long __scanbit(unsigned long val, unsigned long max)
+ return val;
+ }
+
+-#define find_first_bit(addr,size) \
+-((__builtin_constant_p(size) && (size) <= BITS_PER_LONG ? \
+- (__scanbit(*(unsigned long *)addr,(size))) : \
+- find_first_bit(addr,size)))
+-
+ #define find_next_bit(addr,size,off) \
+ ((__builtin_constant_p(size) && (size) <= BITS_PER_LONG ? \
+ ((off) + (__scanbit((*(unsigned long *)addr) >> (off),(size)-(off)))) : \
+ find_next_bit(addr,size,off)))
+
+-#define find_first_zero_bit(addr,size) \
+-((__builtin_constant_p(size) && (size) <= BITS_PER_LONG ? \
+- (__scanbit(~*(unsigned long *)addr,(size))) : \
+- find_first_zero_bit(addr,size)))
+-
+ #define find_next_zero_bit(addr,size,off) \
+ ((__builtin_constant_p(size) && (size) <= BITS_PER_LONG ? \
+ ((off)+(__scanbit(~(((*(unsigned long *)addr)) >> (off)),(size)-(off)))) : \
+ find_next_zero_bit(addr,size,off)))
+
+-static inline void set_bit_string(unsigned long *bitmap, unsigned long i,
+- int len)
+-{
+- unsigned long end = i + len;
++#define find_first_bit(addr, size) \
++ ((__builtin_constant_p((size)) && (size) <= BITS_PER_LONG \
++ ? (__scanbit(*(unsigned long *)(addr), (size))) \
++ : find_first_bit((addr), (size))))
++
++#define find_first_zero_bit(addr, size) \
++ ((__builtin_constant_p((size)) && (size) <= BITS_PER_LONG \
++ ? (__scanbit(~*(unsigned long *)(addr), (size))) \
++ : find_first_zero_bit((addr), (size))))
++
++static inline void set_bit_string(unsigned long *bitmap, unsigned long i,
++ int len)
++{
++ unsigned long end = i + len;
+ while (i < end) {
+- __set_bit(i, bitmap);
++ __set_bit(i, bitmap);
+ i++;
+ }
+-}
++}
+
+ /**
+ * ffz - find first zero in word.
+@@ -150,10 +150,10 @@ static inline int fls(int x)
+
+ #include <asm-generic/bitops/ext2-non-atomic.h>
+
+-#define ext2_set_bit_atomic(lock,nr,addr) \
+- test_and_set_bit((nr),(unsigned long*)addr)
+-#define ext2_clear_bit_atomic(lock,nr,addr) \
+- test_and_clear_bit((nr),(unsigned long*)addr)
++#define ext2_set_bit_atomic(lock, nr, addr) \
++ test_and_set_bit((nr), (unsigned long *)(addr))
++#define ext2_clear_bit_atomic(lock, nr, addr) \
++ test_and_clear_bit((nr), (unsigned long *)(addr))
+
+ #include <asm-generic/bitops/minix.h>
+
+diff --git a/include/asm-x86/boot.h b/include/asm-x86/boot.h
+index ed8affb..2faed7e 100644
+--- a/include/asm-x86/boot.h
++++ b/include/asm-x86/boot.h
+@@ -17,4 +17,12 @@
+ + (CONFIG_PHYSICAL_ALIGN - 1)) \
+ & ~(CONFIG_PHYSICAL_ALIGN - 1))
+
++#ifdef CONFIG_X86_64
++#define BOOT_HEAP_SIZE 0x7000
++#define BOOT_STACK_SIZE 0x4000
++#else
++#define BOOT_HEAP_SIZE 0x4000
++#define BOOT_STACK_SIZE 0x1000
++#endif
++
+ #endif /* _ASM_BOOT_H */
+diff --git a/include/asm-x86/bug.h b/include/asm-x86/bug.h
+index 8d477a2..b69aa64 100644
+--- a/include/asm-x86/bug.h
++++ b/include/asm-x86/bug.h
+@@ -12,25 +12,25 @@
+ # define __BUG_C0 "2:\t.quad 1b, %c0\n"
+ #endif
+
+-#define BUG() \
+- do { \
+- asm volatile("1:\tud2\n" \
+- ".pushsection __bug_table,\"a\"\n" \
+- __BUG_C0 \
+- "\t.word %c1, 0\n" \
+- "\t.org 2b+%c2\n" \
+- ".popsection" \
+- : : "i" (__FILE__), "i" (__LINE__), \
+- "i" (sizeof(struct bug_entry))); \
+- for(;;) ; \
+- } while(0)
++#define BUG() \
++do { \
++ asm volatile("1:\tud2\n" \
++ ".pushsection __bug_table,\"a\"\n" \
++ __BUG_C0 \
++ "\t.word %c1, 0\n" \
++ "\t.org 2b+%c2\n" \
++ ".popsection" \
++ : : "i" (__FILE__), "i" (__LINE__), \
++ "i" (sizeof(struct bug_entry))); \
++ for (;;) ; \
++} while (0)
+
+ #else
+-#define BUG() \
+- do { \
+- asm volatile("ud2"); \
+- for(;;) ; \
+- } while(0)
++#define BUG() \
++do { \
++ asm volatile("ud2"); \
++ for (;;) ; \
++} while (0)
+ #endif
+
+ #endif /* !CONFIG_BUG */
+diff --git a/include/asm-x86/byteorder.h b/include/asm-x86/byteorder.h
+index fe2f2e5..e02ae2d 100644
+--- a/include/asm-x86/byteorder.h
++++ b/include/asm-x86/byteorder.h
+@@ -8,50 +8,59 @@
+
+ #ifdef __i386__
+
+-static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
++static inline __attribute_const__ __u32 ___arch__swab32(__u32 x)
+ {
+ #ifdef CONFIG_X86_BSWAP
+- __asm__("bswap %0" : "=r" (x) : "0" (x));
++ asm("bswap %0" : "=r" (x) : "0" (x));
+ #else
+- __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
+- "rorl $16,%0\n\t" /* swap words */
+- "xchgb %b0,%h0" /* swap higher bytes */
+- :"=q" (x)
+- : "0" (x));
++ asm("xchgb %b0,%h0\n\t" /* swap lower bytes */
++ "rorl $16,%0\n\t" /* swap words */
++ "xchgb %b0,%h0" /* swap higher bytes */
++ : "=q" (x)
++ : "0" (x));
+ #endif
+ return x;
+ }
+
+-static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 val)
++static inline __attribute_const__ __u64 ___arch__swab64(__u64 val)
+ {
+ union {
+- struct { __u32 a,b; } s;
++ struct {
++ __u32 a;
++ __u32 b;
++ } s;
+ __u64 u;
+ } v;
+ v.u = val;
+ #ifdef CONFIG_X86_BSWAP
+- __asm__("bswapl %0 ; bswapl %1 ; xchgl %0,%1"
++ asm("bswapl %0 ; bswapl %1 ; xchgl %0,%1"
+ : "=r" (v.s.a), "=r" (v.s.b)
+ : "0" (v.s.a), "1" (v.s.b));
+ #else
+ v.s.a = ___arch__swab32(v.s.a);
+ v.s.b = ___arch__swab32(v.s.b);
+- __asm__("xchgl %0,%1" : "=r" (v.s.a), "=r" (v.s.b) : "0" (v.s.a), "1" (v.s.b));
++ asm("xchgl %0,%1"
++ : "=r" (v.s.a), "=r" (v.s.b)
++ : "0" (v.s.a), "1" (v.s.b));
+ #endif
+ return v.u;
+ }
+
+ #else /* __i386__ */
+
+-static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 x)
++static inline __attribute_const__ __u64 ___arch__swab64(__u64 x)
+ {
+- __asm__("bswapq %0" : "=r" (x) : "0" (x));
++ asm("bswapq %0"
++ : "=r" (x)
++ : "0" (x));
+ return x;
+ }
+
+-static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
++static inline __attribute_const__ __u32 ___arch__swab32(__u32 x)
+ {
+- __asm__("bswapl %0" : "=r" (x) : "0" (x));
++ asm("bswapl %0"
++ : "=r" (x)
++ : "0" (x));
+ return x;
+ }
+
+diff --git a/include/asm-x86/cacheflush.h b/include/asm-x86/cacheflush.h
+index 5396c21..f4c0ab5 100644
+--- a/include/asm-x86/cacheflush.h
++++ b/include/asm-x86/cacheflush.h
+@@ -14,33 +14,85 @@
+ #define flush_dcache_mmap_lock(mapping) do { } while (0)
+ #define flush_dcache_mmap_unlock(mapping) do { } while (0)
+ #define flush_icache_range(start, end) do { } while (0)
+-#define flush_icache_page(vma,pg) do { } while (0)
+-#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
++#define flush_icache_page(vma, pg) do { } while (0)
++#define flush_icache_user_range(vma, pg, adr, len) do { } while (0)
+ #define flush_cache_vmap(start, end) do { } while (0)
+ #define flush_cache_vunmap(start, end) do { } while (0)
+
+-#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
+- memcpy(dst, src, len)
+-#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
+- memcpy(dst, src, len)
++#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy((dst), (src), (len))
++#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy((dst), (src), (len))
+
+-int __deprecated_for_modules change_page_attr(struct page *page, int numpages,
+- pgprot_t prot);
+
+-int set_pages_uc(struct page *page, int numpages);
+-int set_pages_wb(struct page *page, int numpages);
+-int set_pages_x(struct page *page, int numpages);
+-int set_pages_nx(struct page *page, int numpages);
+-int set_pages_ro(struct page *page, int numpages);
+-int set_pages_rw(struct page *page, int numpages);
++/*
++ * The set_memory_* API can be used to change various attributes of a virtual
++ * address range. The attributes include:
++ * Cachability : UnCached, WriteCombining, WriteBack
++ * Executability : eXeutable, NoteXecutable
++ * Read/Write : ReadOnly, ReadWrite
++ * Presence : NotPresent
++ *
++ * Within a catagory, the attributes are mutually exclusive.
++ *
++ * The implementation of this API will take care of various aspects that
++ * are associated with changing such attributes, such as:
++ * - Flushing TLBs
++ * - Flushing CPU caches
++ * - Making sure aliases of the memory behind the mapping don't violate
++ * coherency rules as defined by the CPU in the system.
++ *
++ * What this API does not do:
++ * - Provide exclusion between various callers - including callers that
++ * operation on other mappings of the same physical page
++ * - Restore default attributes when a page is freed
++ * - Guarantee that mappings other than the requested one are
++ * in any state, other than that these do not violate rules for
++ * the CPU you have. Do not depend on any effects on other mappings,
++ * CPUs other than the one you have may have more relaxed rules.
++ * The caller is required to take care of these.
++ */
+
++int _set_memory_uc(unsigned long addr, int numpages);
++int _set_memory_wc(unsigned long addr, int numpages);
++int _set_memory_wb(unsigned long addr, int numpages);
+ int set_memory_uc(unsigned long addr, int numpages);
++int set_memory_wc(unsigned long addr, int numpages);
+ int set_memory_wb(unsigned long addr, int numpages);
+ int set_memory_x(unsigned long addr, int numpages);
+ int set_memory_nx(unsigned long addr, int numpages);
+ int set_memory_ro(unsigned long addr, int numpages);
+ int set_memory_rw(unsigned long addr, int numpages);
+ int set_memory_np(unsigned long addr, int numpages);
++int set_memory_4k(unsigned long addr, int numpages);
++
++/*
++ * For legacy compatibility with the old APIs, a few functions
++ * are provided that work on a "struct page".
++ * These functions operate ONLY on the 1:1 kernel mapping of the
++ * memory that the struct page represents, and internally just
++ * call the set_memory_* function. See the description of the
++ * set_memory_* function for more details on conventions.
++ *
++ * These APIs should be considered *deprecated* and are likely going to
++ * be removed in the future.
++ * The reason for this is the implicit operation on the 1:1 mapping only,
++ * making this not a generally useful API.
++ *
++ * Specifically, many users of the old APIs had a virtual address,
++ * called virt_to_page() or vmalloc_to_page() on that address to
++ * get a struct page* that the old API required.
++ * To convert these cases, use set_memory_*() on the original
++ * virtual address, do not use these functions.
++ */
++
++int set_pages_uc(struct page *page, int numpages);
++int set_pages_wb(struct page *page, int numpages);
++int set_pages_x(struct page *page, int numpages);
++int set_pages_nx(struct page *page, int numpages);
++int set_pages_ro(struct page *page, int numpages);
++int set_pages_rw(struct page *page, int numpages);
++
+
+ void clflush_cache_range(void *addr, unsigned int size);
+
+diff --git a/include/asm-x86/checksum_32.h b/include/asm-x86/checksum_32.h
+index 75194ab..52bbb0d 100644
+--- a/include/asm-x86/checksum_32.h
++++ b/include/asm-x86/checksum_32.h
+@@ -28,7 +28,8 @@ asmlinkage __wsum csum_partial(const void *buff, int len, __wsum sum);
+ */
+
+ asmlinkage __wsum csum_partial_copy_generic(const void *src, void *dst,
+- int len, __wsum sum, int *src_err_ptr, int *dst_err_ptr);
++ int len, __wsum sum,
++ int *src_err_ptr, int *dst_err_ptr);
+
+ /*
+ * Note: when you get a NULL pointer exception here this means someone
+@@ -37,20 +38,20 @@ asmlinkage __wsum csum_partial_copy_generic(const void *src, void *dst,
+ * If you use these functions directly please don't forget the
+ * access_ok().
+ */
+-static __inline__
+-__wsum csum_partial_copy_nocheck (const void *src, void *dst,
+- int len, __wsum sum)
++static inline __wsum csum_partial_copy_nocheck(const void *src, void *dst,
++ int len, __wsum sum)
+ {
+- return csum_partial_copy_generic ( src, dst, len, sum, NULL, NULL);
++ return csum_partial_copy_generic(src, dst, len, sum, NULL, NULL);
+ }
+
+-static __inline__
+-__wsum csum_partial_copy_from_user(const void __user *src, void *dst,
+- int len, __wsum sum, int *err_ptr)
++static inline __wsum csum_partial_copy_from_user(const void __user *src,
++ void *dst,
++ int len, __wsum sum,
++ int *err_ptr)
+ {
+ might_sleep();
+ return csum_partial_copy_generic((__force void *)src, dst,
+- len, sum, err_ptr, NULL);
++ len, sum, err_ptr, NULL);
+ }
+
+ /*
+@@ -64,30 +65,29 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+ {
+ unsigned int sum;
+
+- __asm__ __volatile__(
+- "movl (%1), %0 ;\n"
+- "subl $4, %2 ;\n"
+- "jbe 2f ;\n"
+- "addl 4(%1), %0 ;\n"
+- "adcl 8(%1), %0 ;\n"
+- "adcl 12(%1), %0 ;\n"
+-"1: adcl 16(%1), %0 ;\n"
+- "lea 4(%1), %1 ;\n"
+- "decl %2 ;\n"
+- "jne 1b ;\n"
+- "adcl $0, %0 ;\n"
+- "movl %0, %2 ;\n"
+- "shrl $16, %0 ;\n"
+- "addw %w2, %w0 ;\n"
+- "adcl $0, %0 ;\n"
+- "notl %0 ;\n"
+-"2: ;\n"
++ asm volatile("movl (%1), %0 ;\n"
++ "subl $4, %2 ;\n"
++ "jbe 2f ;\n"
++ "addl 4(%1), %0 ;\n"
++ "adcl 8(%1), %0 ;\n"
++ "adcl 12(%1), %0;\n"
++ "1: adcl 16(%1), %0 ;\n"
++ "lea 4(%1), %1 ;\n"
++ "decl %2 ;\n"
++ "jne 1b ;\n"
++ "adcl $0, %0 ;\n"
++ "movl %0, %2 ;\n"
++ "shrl $16, %0 ;\n"
++ "addw %w2, %w0 ;\n"
++ "adcl $0, %0 ;\n"
++ "notl %0 ;\n"
++ "2: ;\n"
+ /* Since the input registers which are loaded with iph and ihl
+ are modified, we must also specify them as outputs, or gcc
+ will assume they contain their original values. */
+- : "=r" (sum), "=r" (iph), "=r" (ihl)
+- : "1" (iph), "2" (ihl)
+- : "memory");
++ : "=r" (sum), "=r" (iph), "=r" (ihl)
++ : "1" (iph), "2" (ihl)
++ : "memory");
+ return (__force __sum16)sum;
+ }
+
+@@ -97,29 +97,27 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+
+ static inline __sum16 csum_fold(__wsum sum)
+ {
+- __asm__(
+- "addl %1, %0 ;\n"
+- "adcl $0xffff, %0 ;\n"
+- : "=r" (sum)
+- : "r" ((__force u32)sum << 16),
+- "0" ((__force u32)sum & 0xffff0000)
+- );
++ asm("addl %1, %0 ;\n"
++ "adcl $0xffff, %0 ;\n"
++ : "=r" (sum)
++ : "r" ((__force u32)sum << 16),
++ "0" ((__force u32)sum & 0xffff0000));
+ return (__force __sum16)(~(__force u32)sum >> 16);
+ }
+
+ static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
+- unsigned short len,
+- unsigned short proto,
+- __wsum sum)
++ unsigned short len,
++ unsigned short proto,
++ __wsum sum)
+ {
+- __asm__(
+- "addl %1, %0 ;\n"
+- "adcl %2, %0 ;\n"
+- "adcl %3, %0 ;\n"
+- "adcl $0, %0 ;\n"
+- : "=r" (sum)
+- : "g" (daddr), "g"(saddr), "g"((len + proto) << 8), "0"(sum));
+- return sum;
++ asm("addl %1, %0 ;\n"
++ "adcl %2, %0 ;\n"
++ "adcl %3, %0 ;\n"
++ "adcl $0, %0 ;\n"
++ : "=r" (sum)
++ : "g" (daddr), "g"(saddr),
++ "g" ((len + proto) << 8), "0" (sum));
++ return sum;
+ }
+
+ /*
+@@ -127,11 +125,11 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
+ * returns a 16-bit checksum, already complemented
+ */
+ static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+- unsigned short len,
+- unsigned short proto,
+- __wsum sum)
++ unsigned short len,
++ unsigned short proto,
++ __wsum sum)
+ {
+- return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
++ return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
+ }
+
+ /*
+@@ -141,30 +139,29 @@ static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+
+ static inline __sum16 ip_compute_csum(const void *buff, int len)
+ {
+- return csum_fold (csum_partial(buff, len, 0));
++ return csum_fold(csum_partial(buff, len, 0));
+ }
+
+ #define _HAVE_ARCH_IPV6_CSUM
+-static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+- const struct in6_addr *daddr,
+- __u32 len, unsigned short proto,
+- __wsum sum)
++static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
++ const struct in6_addr *daddr,
++ __u32 len, unsigned short proto,
++ __wsum sum)
+ {
+- __asm__(
+- "addl 0(%1), %0 ;\n"
+- "adcl 4(%1), %0 ;\n"
+- "adcl 8(%1), %0 ;\n"
+- "adcl 12(%1), %0 ;\n"
+- "adcl 0(%2), %0 ;\n"
+- "adcl 4(%2), %0 ;\n"
+- "adcl 8(%2), %0 ;\n"
+- "adcl 12(%2), %0 ;\n"
+- "adcl %3, %0 ;\n"
+- "adcl %4, %0 ;\n"
+- "adcl $0, %0 ;\n"
+- : "=&r" (sum)
+- : "r" (saddr), "r" (daddr),
+- "r"(htonl(len)), "r"(htonl(proto)), "0"(sum));
++ asm("addl 0(%1), %0 ;\n"
++ "adcl 4(%1), %0 ;\n"
++ "adcl 8(%1), %0 ;\n"
++ "adcl 12(%1), %0 ;\n"
++ "adcl 0(%2), %0 ;\n"
++ "adcl 4(%2), %0 ;\n"
++ "adcl 8(%2), %0 ;\n"
++ "adcl 12(%2), %0 ;\n"
++ "adcl %3, %0 ;\n"
++ "adcl %4, %0 ;\n"
++ "adcl $0, %0 ;\n"
++ : "=&r" (sum)
++ : "r" (saddr), "r" (daddr),
++ "r" (htonl(len)), "r" (htonl(proto)), "0" (sum));
+
+ return csum_fold(sum);
+ }
+@@ -173,14 +170,15 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ * Copy and checksum to user
+ */
+ #define HAVE_CSUM_COPY_USER
+-static __inline__ __wsum csum_and_copy_to_user(const void *src,
+- void __user *dst,
+- int len, __wsum sum,
+- int *err_ptr)
++static inline __wsum csum_and_copy_to_user(const void *src,
++ void __user *dst,
++ int len, __wsum sum,
++ int *err_ptr)
+ {
+ might_sleep();
+ if (access_ok(VERIFY_WRITE, dst, len))
+- return csum_partial_copy_generic(src, (__force void *)dst, len, sum, NULL, err_ptr);
++ return csum_partial_copy_generic(src, (__force void *)dst,
++ len, sum, NULL, err_ptr);
+
+ if (len)
+ *err_ptr = -EFAULT;
+diff --git a/include/asm-x86/checksum_64.h b/include/asm-x86/checksum_64.h
+index e5f7999..8bd861c 100644
+--- a/include/asm-x86/checksum_64.h
++++ b/include/asm-x86/checksum_64.h
+@@ -1,33 +1,31 @@
+ #ifndef _X86_64_CHECKSUM_H
+ #define _X86_64_CHECKSUM_H
+
+-/*
+- * Checksums for x86-64
+- * Copyright 2002 by Andi Kleen, SuSE Labs
++/*
++ * Checksums for x86-64
++ * Copyright 2002 by Andi Kleen, SuSE Labs
+ * with some code from asm-x86/checksum.h
+- */
++ */
+
+ #include <linux/compiler.h>
+ #include <asm/uaccess.h>
+ #include <asm/byteorder.h>
+
+-/**
++/**
+ * csum_fold - Fold and invert a 32bit checksum.
+ * sum: 32bit unfolded sum
+- *
++ *
+ * Fold a 32bit running checksum to 16bit and invert it. This is usually
+ * the last step before putting a checksum into a packet.
+ * Make sure not to mix with 64bit checksums.
+ */
+ static inline __sum16 csum_fold(__wsum sum)
+ {
+- __asm__(
+- " addl %1,%0\n"
+- " adcl $0xffff,%0"
+- : "=r" (sum)
+- : "r" ((__force u32)sum << 16),
+- "0" ((__force u32)sum & 0xffff0000)
+- );
++ asm(" addl %1,%0\n"
++ " adcl $0xffff,%0"
++ : "=r" (sum)
++ : "r" ((__force u32)sum << 16),
++ "0" ((__force u32)sum & 0xffff0000));
+ return (__force __sum16)(~(__force u32)sum >> 16);
+ }
+
+@@ -43,46 +41,46 @@ static inline __sum16 csum_fold(__wsum sum)
+ * ip_fast_csum - Compute the IPv4 header checksum efficiently.
+ * iph: ipv4 header
+ * ihl: length of header / 4
+- */
++ */
+ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+ {
+ unsigned int sum;
+
+- asm( " movl (%1), %0\n"
+- " subl $4, %2\n"
+- " jbe 2f\n"
+- " addl 4(%1), %0\n"
+- " adcl 8(%1), %0\n"
+- " adcl 12(%1), %0\n"
+- "1: adcl 16(%1), %0\n"
+- " lea 4(%1), %1\n"
+- " decl %2\n"
+- " jne 1b\n"
+- " adcl $0, %0\n"
+- " movl %0, %2\n"
+- " shrl $16, %0\n"
+- " addw %w2, %w0\n"
+- " adcl $0, %0\n"
+- " notl %0\n"
+- "2:"
++ asm(" movl (%1), %0\n"
++ " subl $4, %2\n"
++ " jbe 2f\n"
++ " addl 4(%1), %0\n"
++ " adcl 8(%1), %0\n"
++ " adcl 12(%1), %0\n"
++ "1: adcl 16(%1), %0\n"
++ " lea 4(%1), %1\n"
++ " decl %2\n"
++ " jne 1b\n"
++ " adcl $0, %0\n"
++ " movl %0, %2\n"
++ " shrl $16, %0\n"
++ " addw %w2, %w0\n"
++ " adcl $0, %0\n"
++ " notl %0\n"
++ "2:"
+ /* Since the input registers which are loaded with iph and ihl
+ are modified, we must also specify them as outputs, or gcc
+ will assume they contain their original values. */
+- : "=r" (sum), "=r" (iph), "=r" (ihl)
+- : "1" (iph), "2" (ihl)
+- : "memory");
++ : "=r" (sum), "=r" (iph), "=r" (ihl)
++ : "1" (iph), "2" (ihl)
++ : "memory");
+ return (__force __sum16)sum;
+ }
+
+-/**
++/**
+ * csum_tcpup_nofold - Compute an IPv4 pseudo header checksum.
+ * @saddr: source address
+ * @daddr: destination address
+ * @len: length of packet
+ * @proto: ip protocol of packet
+- * @sum: initial sum to be added in (32bit unfolded)
+- *
+- * Returns the pseudo header checksum the input data. Result is
++ * @sum: initial sum to be added in (32bit unfolded)
++ *
++ * Returns the pseudo header checksum the input data. Result is
+ * 32bit unfolded.
+ */
+ static inline __wsum
+@@ -93,32 +91,32 @@ csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
+ " adcl %2, %0\n"
+ " adcl %3, %0\n"
+ " adcl $0, %0\n"
+- : "=r" (sum)
++ : "=r" (sum)
+ : "g" (daddr), "g" (saddr),
+ "g" ((len + proto)<<8), "0" (sum));
+- return sum;
++ return sum;
+ }
+
+
+-/**
++/**
+ * csum_tcpup_magic - Compute an IPv4 pseudo header checksum.
+ * @saddr: source address
+ * @daddr: destination address
+ * @len: length of packet
+ * @proto: ip protocol of packet
+- * @sum: initial sum to be added in (32bit unfolded)
+- *
++ * @sum: initial sum to be added in (32bit unfolded)
++ *
+ * Returns the 16bit pseudo header checksum the input data already
+ * complemented and ready to be filled in.
+ */
+-static inline __sum16
+-csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+- unsigned short len, unsigned short proto, __wsum sum)
++static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
++ unsigned short len,
++ unsigned short proto, __wsum sum)
+ {
+- return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
++ return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
+ }
+
+-/**
++/**
+ * csum_partial - Compute an internet checksum.
+ * @buff: buffer to be checksummed
+ * @len: length of buffer.
+@@ -127,7 +125,7 @@ csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+ * Returns the 32bit unfolded internet checksum of the buffer.
+ * Before filling it in it needs to be csum_fold()'ed.
+ * buff should be aligned to a 64bit boundary if possible.
+- */
++ */
+ extern __wsum csum_partial(const void *buff, int len, __wsum sum);
+
+ #define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER 1
+@@ -136,23 +134,22 @@ extern __wsum csum_partial(const void *buff, int len, __wsum sum);
+
+ /* Do not call this directly. Use the wrappers below */
+ extern __wsum csum_partial_copy_generic(const void *src, const void *dst,
+- int len,
+- __wsum sum,
+- int *src_err_ptr, int *dst_err_ptr);
++ int len, __wsum sum,
++ int *src_err_ptr, int *dst_err_ptr);
+
+
+ extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst,
+- int len, __wsum isum, int *errp);
++ int len, __wsum isum, int *errp);
+ extern __wsum csum_partial_copy_to_user(const void *src, void __user *dst,
+- int len, __wsum isum, int *errp);
+-extern __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len,
+- __wsum sum);
++ int len, __wsum isum, int *errp);
++extern __wsum csum_partial_copy_nocheck(const void *src, void *dst,
++ int len, __wsum sum);
+
+ /* Old names. To be removed. */
+ #define csum_and_copy_to_user csum_partial_copy_to_user
+ #define csum_and_copy_from_user csum_partial_copy_from_user
+
+-/**
++/**
+ * ip_compute_csum - Compute an 16bit IP checksum.
+ * @buff: buffer address.
+ * @len: length of buffer.
+@@ -170,7 +167,7 @@ extern __sum16 ip_compute_csum(const void *buff, int len);
+ * @proto: protocol of packet
+ * @sum: initial sum (32bit unfolded) to be added in
+ *
+- * Computes an IPv6 pseudo header checksum. This sum is added the checksum
++ * Computes an IPv6 pseudo header checksum. This sum is added the checksum
+ * into UDP/TCP packets and contains some link layer information.
+ * Returns the unfolded 32bit checksum.
+ */
+@@ -185,11 +182,10 @@ csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr,
+ static inline unsigned add32_with_carry(unsigned a, unsigned b)
+ {
+ asm("addl %2,%0\n\t"
+- "adcl $0,%0"
+- : "=r" (a)
++ "adcl $0,%0"
++ : "=r" (a)
+ : "0" (a), "r" (b));
+ return a;
+ }
+
+ #endif
+-
+diff --git a/include/asm-x86/cmpxchg_32.h b/include/asm-x86/cmpxchg_32.h
+index 959fad0..bf5a69d 100644
+--- a/include/asm-x86/cmpxchg_32.h
++++ b/include/asm-x86/cmpxchg_32.h
+@@ -8,9 +8,12 @@
+ * you need to test for the feature in boot_cpu_data.
+ */
+
+-#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
++#define xchg(ptr, v) \
++ ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), sizeof(*(ptr))))
+
+-struct __xchg_dummy { unsigned long a[100]; };
++struct __xchg_dummy {
++ unsigned long a[100];
++};
+ #define __xg(x) ((struct __xchg_dummy *)(x))
+
+ /*
+@@ -27,72 +30,74 @@ struct __xchg_dummy { unsigned long a[100]; };
+ * of the instruction set reference 24319102.pdf. We need
+ * the reader side to see the coherent 64bit value.
+ */
+-static inline void __set_64bit (unsigned long long * ptr,
+- unsigned int low, unsigned int high)
++static inline void __set_64bit(unsigned long long *ptr,
++ unsigned int low, unsigned int high)
+ {
+- __asm__ __volatile__ (
+- "\n1:\t"
+- "movl (%0), %%eax\n\t"
+- "movl 4(%0), %%edx\n\t"
+- LOCK_PREFIX "cmpxchg8b (%0)\n\t"
+- "jnz 1b"
+- : /* no outputs */
+- : "D"(ptr),
+- "b"(low),
+- "c"(high)
+- : "ax","dx","memory");
++ asm volatile("\n1:\t"
++ "movl (%0), %%eax\n\t"
++ "movl 4(%0), %%edx\n\t"
++ LOCK_PREFIX "cmpxchg8b (%0)\n\t"
++ "jnz 1b"
++ : /* no outputs */
++ : "D"(ptr),
++ "b"(low),
++ "c"(high)
++ : "ax", "dx", "memory");
+ }
+
+-static inline void __set_64bit_constant (unsigned long long *ptr,
+- unsigned long long value)
++static inline void __set_64bit_constant(unsigned long long *ptr,
++ unsigned long long value)
+ {
+- __set_64bit(ptr,(unsigned int)(value), (unsigned int)((value)>>32ULL));
++ __set_64bit(ptr, (unsigned int)value, (unsigned int)(value >> 32));
+ }
+-#define ll_low(x) *(((unsigned int*)&(x))+0)
+-#define ll_high(x) *(((unsigned int*)&(x))+1)
+
+-static inline void __set_64bit_var (unsigned long long *ptr,
+- unsigned long long value)
++#define ll_low(x) *(((unsigned int *)&(x)) + 0)
++#define ll_high(x) *(((unsigned int *)&(x)) + 1)
++
++static inline void __set_64bit_var(unsigned long long *ptr,
++ unsigned long long value)
+ {
+- __set_64bit(ptr,ll_low(value), ll_high(value));
++ __set_64bit(ptr, ll_low(value), ll_high(value));
+ }
+
+-#define set_64bit(ptr,value) \
+-(__builtin_constant_p(value) ? \
+- __set_64bit_constant(ptr, value) : \
+- __set_64bit_var(ptr, value) )
++#define set_64bit(ptr, value) \
++ (__builtin_constant_p((value)) \
++ ? __set_64bit_constant((ptr), (value)) \
++ : __set_64bit_var((ptr), (value)))
+
+-#define _set_64bit(ptr,value) \
+-(__builtin_constant_p(value) ? \
+- __set_64bit(ptr, (unsigned int)(value), (unsigned int)((value)>>32ULL) ) : \
+- __set_64bit(ptr, ll_low(value), ll_high(value)) )
++#define _set_64bit(ptr, value) \
++ (__builtin_constant_p(value) \
++ ? __set_64bit(ptr, (unsigned int)(value), \
++ (unsigned int)((value) >> 32)) \
++ : __set_64bit(ptr, ll_low((value)), ll_high((value))))
+
+ /*
+ * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
+ * Note 2: xchg has side effect, so that attribute volatile is necessary,
+ * but generally the primitive is invalid, *ptr is output argument. --ANK
+ */
+-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
++static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
++ int size)
+ {
+ switch (size) {
+- case 1:
+- __asm__ __volatile__("xchgb %b0,%1"
+- :"=q" (x)
+- :"m" (*__xg(ptr)), "0" (x)
+- :"memory");
+- break;
+- case 2:
+- __asm__ __volatile__("xchgw %w0,%1"
+- :"=r" (x)
+- :"m" (*__xg(ptr)), "0" (x)
+- :"memory");
+- break;
+- case 4:
+- __asm__ __volatile__("xchgl %0,%1"
+- :"=r" (x)
+- :"m" (*__xg(ptr)), "0" (x)
+- :"memory");
+- break;
++ case 1:
++ asm volatile("xchgb %b0,%1"
++ : "=q" (x)
++ : "m" (*__xg(ptr)), "0" (x)
++ : "memory");
++ break;
++ case 2:
++ asm volatile("xchgw %w0,%1"
++ : "=r" (x)
++ : "m" (*__xg(ptr)), "0" (x)
++ : "memory");
++ break;
++ case 4:
++ asm volatile("xchgl %0,%1"
++ : "=r" (x)
++ : "m" (*__xg(ptr)), "0" (x)
++ : "memory");
++ break;
+ }
+ return x;
+ }
+@@ -105,24 +110,27 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
+
+ #ifdef CONFIG_X86_CMPXCHG
+ #define __HAVE_ARCH_CMPXCHG 1
+-#define cmpxchg(ptr, o, n) \
+- ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \
+- (unsigned long)(n), sizeof(*(ptr))))
+-#define sync_cmpxchg(ptr, o, n) \
+- ((__typeof__(*(ptr)))__sync_cmpxchg((ptr), (unsigned long)(o), \
+- (unsigned long)(n), sizeof(*(ptr))))
+-#define cmpxchg_local(ptr, o, n) \
+- ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
+- (unsigned long)(n), sizeof(*(ptr))))
++#define cmpxchg(ptr, o, n) \
++ ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \
++ (unsigned long)(n), \
++ sizeof(*(ptr))))
++#define sync_cmpxchg(ptr, o, n) \
++ ((__typeof__(*(ptr)))__sync_cmpxchg((ptr), (unsigned long)(o), \
++ (unsigned long)(n), \
++ sizeof(*(ptr))))
++#define cmpxchg_local(ptr, o, n) \
++ ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
++ (unsigned long)(n), \
++ sizeof(*(ptr))))
+ #endif
+
+ #ifdef CONFIG_X86_CMPXCHG64
+-#define cmpxchg64(ptr, o, n) \
+- ((__typeof__(*(ptr)))__cmpxchg64((ptr), (unsigned long long)(o), \
+- (unsigned long long)(n)))
+-#define cmpxchg64_local(ptr, o, n) \
+- ((__typeof__(*(ptr)))__cmpxchg64_local((ptr), (unsigned long long)(o),\
+- (unsigned long long)(n)))
++#define cmpxchg64(ptr, o, n) \
++ ((__typeof__(*(ptr)))__cmpxchg64((ptr), (unsigned long long)(o), \
++ (unsigned long long)(n)))
++#define cmpxchg64_local(ptr, o, n) \
++ ((__typeof__(*(ptr)))__cmpxchg64_local((ptr), (unsigned long long)(o), \
++ (unsigned long long)(n)))
+ #endif
+
+ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+@@ -131,22 +139,22 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+ unsigned long prev;
+ switch (size) {
+ case 1:
+- __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
+- : "=a"(prev)
+- : "q"(new), "m"(*__xg(ptr)), "0"(old)
+- : "memory");
++ asm volatile(LOCK_PREFIX "cmpxchgb %b1,%2"
++ : "=a"(prev)
++ : "q"(new), "m"(*__xg(ptr)), "0"(old)
++ : "memory");
+ return prev;
+ case 2:
+- __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
+- : "=a"(prev)
+- : "r"(new), "m"(*__xg(ptr)), "0"(old)
+- : "memory");
++ asm volatile(LOCK_PREFIX "cmpxchgw %w1,%2"
++ : "=a"(prev)
++ : "r"(new), "m"(*__xg(ptr)), "0"(old)
++ : "memory");
+ return prev;
+ case 4:
+- __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
+- : "=a"(prev)
+- : "r"(new), "m"(*__xg(ptr)), "0"(old)
+- : "memory");
++ asm volatile(LOCK_PREFIX "cmpxchgl %1,%2"
++ : "=a"(prev)
++ : "r"(new), "m"(*__xg(ptr)), "0"(old)
++ : "memory");
+ return prev;
+ }
+ return old;
+@@ -158,85 +166,88 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+ * isn't.
+ */
+ static inline unsigned long __sync_cmpxchg(volatile void *ptr,
+- unsigned long old,
+- unsigned long new, int size)
++ unsigned long old,
++ unsigned long new, int size)
+ {
+ unsigned long prev;
+ switch (size) {
+ case 1:
+- __asm__ __volatile__("lock; cmpxchgb %b1,%2"
+- : "=a"(prev)
+- : "q"(new), "m"(*__xg(ptr)), "0"(old)
+- : "memory");
++ asm volatile("lock; cmpxchgb %b1,%2"
++ : "=a"(prev)
++ : "q"(new), "m"(*__xg(ptr)), "0"(old)
++ : "memory");
+ return prev;
+ case 2:
+- __asm__ __volatile__("lock; cmpxchgw %w1,%2"
+- : "=a"(prev)
+- : "r"(new), "m"(*__xg(ptr)), "0"(old)
+- : "memory");
++ asm volatile("lock; cmpxchgw %w1,%2"
++ : "=a"(prev)
++ : "r"(new), "m"(*__xg(ptr)), "0"(old)
++ : "memory");
+ return prev;
+ case 4:
+- __asm__ __volatile__("lock; cmpxchgl %1,%2"
+- : "=a"(prev)
+- : "r"(new), "m"(*__xg(ptr)), "0"(old)
+- : "memory");
++ asm volatile("lock; cmpxchgl %1,%2"
++ : "=a"(prev)
++ : "r"(new), "m"(*__xg(ptr)), "0"(old)
++ : "memory");
+ return prev;
+ }
+ return old;
+ }
+
+ static inline unsigned long __cmpxchg_local(volatile void *ptr,
+- unsigned long old, unsigned long new, int size)
++ unsigned long old,
++ unsigned long new, int size)
+ {
+ unsigned long prev;
+ switch (size) {
+ case 1:
+- __asm__ __volatile__("cmpxchgb %b1,%2"
+- : "=a"(prev)
+- : "q"(new), "m"(*__xg(ptr)), "0"(old)
+- : "memory");
++ asm volatile("cmpxchgb %b1,%2"
++ : "=a"(prev)
++ : "q"(new), "m"(*__xg(ptr)), "0"(old)
++ : "memory");
+ return prev;
+ case 2:
+- __asm__ __volatile__("cmpxchgw %w1,%2"
+- : "=a"(prev)
+- : "r"(new), "m"(*__xg(ptr)), "0"(old)
+- : "memory");
++ asm volatile("cmpxchgw %w1,%2"
++ : "=a"(prev)
++ : "r"(new), "m"(*__xg(ptr)), "0"(old)
++ : "memory");
+ return prev;
+ case 4:
+- __asm__ __volatile__("cmpxchgl %1,%2"
+- : "=a"(prev)
+- : "r"(new), "m"(*__xg(ptr)), "0"(old)
+- : "memory");
++ asm volatile("cmpxchgl %1,%2"
++ : "=a"(prev)
++ : "r"(new), "m"(*__xg(ptr)), "0"(old)
++ : "memory");
+ return prev;
+ }
+ return old;
+ }
+
+ static inline unsigned long long __cmpxchg64(volatile void *ptr,
+- unsigned long long old, unsigned long long new)
++ unsigned long long old,
++ unsigned long long new)
+ {
+ unsigned long long prev;
+- __asm__ __volatile__(LOCK_PREFIX "cmpxchg8b %3"
+- : "=A"(prev)
+- : "b"((unsigned long)new),
+- "c"((unsigned long)(new >> 32)),
+- "m"(*__xg(ptr)),
+- "0"(old)
+- : "memory");
++ asm volatile(LOCK_PREFIX "cmpxchg8b %3"
++ : "=A"(prev)
++ : "b"((unsigned long)new),
++ "c"((unsigned long)(new >> 32)),
++ "m"(*__xg(ptr)),
++ "0"(old)
++ : "memory");
+ return prev;
+ }
+
+ static inline unsigned long long __cmpxchg64_local(volatile void *ptr,
+- unsigned long long old, unsigned long long new)
++ unsigned long long old,
++ unsigned long long new)
+ {
+ unsigned long long prev;
+- __asm__ __volatile__("cmpxchg8b %3"
+- : "=A"(prev)
+- : "b"((unsigned long)new),
+- "c"((unsigned long)(new >> 32)),
+- "m"(*__xg(ptr)),
+- "0"(old)
+- : "memory");
++ asm volatile("cmpxchg8b %3"
++ : "=A"(prev)
++ : "b"((unsigned long)new),
++ "c"((unsigned long)(new >> 32)),
++ "m"(*__xg(ptr)),
++ "0"(old)
++ : "memory");
+ return prev;
+ }
+
+@@ -252,7 +263,7 @@ extern unsigned long cmpxchg_386_u16(volatile void *, u16, u16);
+ extern unsigned long cmpxchg_386_u32(volatile void *, u32, u32);
+
+ static inline unsigned long cmpxchg_386(volatile void *ptr, unsigned long old,
+- unsigned long new, int size)
++ unsigned long new, int size)
+ {
+ switch (size) {
+ case 1:
+diff --git a/include/asm-x86/cmpxchg_64.h b/include/asm-x86/cmpxchg_64.h
+index 56f5b41..d9b26b9 100644
+--- a/include/asm-x86/cmpxchg_64.h
++++ b/include/asm-x86/cmpxchg_64.h
+@@ -3,7 +3,8 @@
+
+ #include <asm/alternative.h> /* Provides LOCK_PREFIX */
+
+-#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
++#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), \
++ (ptr), sizeof(*(ptr))))
+
+ #define __xg(x) ((volatile long *)(x))
+
+@@ -19,33 +20,34 @@ static inline void set_64bit(volatile unsigned long *ptr, unsigned long val)
+ * Note 2: xchg has side effect, so that attribute volatile is necessary,
+ * but generally the primitive is invalid, *ptr is output argument. --ANK
+ */
+-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
++static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
++ int size)
+ {
+ switch (size) {
+- case 1:
+- __asm__ __volatile__("xchgb %b0,%1"
+- :"=q" (x)
+- :"m" (*__xg(ptr)), "0" (x)
+- :"memory");
+- break;
+- case 2:
+- __asm__ __volatile__("xchgw %w0,%1"
+- :"=r" (x)
+- :"m" (*__xg(ptr)), "0" (x)
+- :"memory");
+- break;
+- case 4:
+- __asm__ __volatile__("xchgl %k0,%1"
+- :"=r" (x)
+- :"m" (*__xg(ptr)), "0" (x)
+- :"memory");
+- break;
+- case 8:
+- __asm__ __volatile__("xchgq %0,%1"
+- :"=r" (x)
+- :"m" (*__xg(ptr)), "0" (x)
+- :"memory");
+- break;
++ case 1:
++ asm volatile("xchgb %b0,%1"
++ : "=q" (x)
++ : "m" (*__xg(ptr)), "0" (x)
++ : "memory");
++ break;
++ case 2:
++ asm volatile("xchgw %w0,%1"
++ : "=r" (x)
++ : "m" (*__xg(ptr)), "0" (x)
++ : "memory");
++ break;
++ case 4:
++ asm volatile("xchgl %k0,%1"
++ : "=r" (x)
++ : "m" (*__xg(ptr)), "0" (x)
++ : "memory");
++ break;
++ case 8:
++ asm volatile("xchgq %0,%1"
++ : "=r" (x)
++ : "m" (*__xg(ptr)), "0" (x)
++ : "memory");
++ break;
+ }
+ return x;
+ }
+@@ -64,61 +66,62 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+ unsigned long prev;
+ switch (size) {
+ case 1:
+- __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
+- : "=a"(prev)
+- : "q"(new), "m"(*__xg(ptr)), "0"(old)
+- : "memory");
++ asm volatile(LOCK_PREFIX "cmpxchgb %b1,%2"
++ : "=a"(prev)
++ : "q"(new), "m"(*__xg(ptr)), "0"(old)
++ : "memory");
+ return prev;
+ case 2:
+- __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
+- : "=a"(prev)
+- : "r"(new), "m"(*__xg(ptr)), "0"(old)
+- : "memory");
++ asm volatile(LOCK_PREFIX "cmpxchgw %w1,%2"
++ : "=a"(prev)
++ : "r"(new), "m"(*__xg(ptr)), "0"(old)
++ : "memory");
+ return prev;
+ case 4:
+- __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %k1,%2"
+- : "=a"(prev)
+- : "r"(new), "m"(*__xg(ptr)), "0"(old)
+- : "memory");
++ asm volatile(LOCK_PREFIX "cmpxchgl %k1,%2"
++ : "=a"(prev)
++ : "r"(new), "m"(*__xg(ptr)), "0"(old)
++ : "memory");
+ return prev;
+ case 8:
+- __asm__ __volatile__(LOCK_PREFIX "cmpxchgq %1,%2"
+- : "=a"(prev)
+- : "r"(new), "m"(*__xg(ptr)), "0"(old)
+- : "memory");
++ asm volatile(LOCK_PREFIX "cmpxchgq %1,%2"
++ : "=a"(prev)
++ : "r"(new), "m"(*__xg(ptr)), "0"(old)
++ : "memory");
+ return prev;
+ }
+ return old;
+ }
+
+ static inline unsigned long __cmpxchg_local(volatile void *ptr,
+- unsigned long old, unsigned long new, int size)
++ unsigned long old,
++ unsigned long new, int size)
+ {
+ unsigned long prev;
+ switch (size) {
+ case 1:
+- __asm__ __volatile__("cmpxchgb %b1,%2"
+- : "=a"(prev)
+- : "q"(new), "m"(*__xg(ptr)), "0"(old)
+- : "memory");
++ asm volatile("cmpxchgb %b1,%2"
++ : "=a"(prev)
++ : "q"(new), "m"(*__xg(ptr)), "0"(old)
++ : "memory");
+ return prev;
+ case 2:
+- __asm__ __volatile__("cmpxchgw %w1,%2"
+- : "=a"(prev)
+- : "r"(new), "m"(*__xg(ptr)), "0"(old)
+- : "memory");
++ asm volatile("cmpxchgw %w1,%2"
++ : "=a"(prev)
++ : "r"(new), "m"(*__xg(ptr)), "0"(old)
++ : "memory");
+ return prev;
+ case 4:
+- __asm__ __volatile__("cmpxchgl %k1,%2"
+- : "=a"(prev)
+- : "r"(new), "m"(*__xg(ptr)), "0"(old)
+- : "memory");
++ asm volatile("cmpxchgl %k1,%2"
++ : "=a"(prev)
++ : "r"(new), "m"(*__xg(ptr)), "0"(old)
++ : "memory");
+ return prev;
+ case 8:
+- __asm__ __volatile__("cmpxchgq %1,%2"
+- : "=a"(prev)
+- : "r"(new), "m"(*__xg(ptr)), "0"(old)
+- : "memory");
++ asm volatile("cmpxchgq %1,%2"
++ : "=a"(prev)
++ : "r"(new), "m"(*__xg(ptr)), "0"(old)
++ : "memory");
+ return prev;
+ }
+ return old;
+@@ -126,19 +129,20 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr,
+
+ #define cmpxchg(ptr, o, n) \
+ ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \
+- (unsigned long)(n), sizeof(*(ptr))))
++ (unsigned long)(n), sizeof(*(ptr))))
+ #define cmpxchg64(ptr, o, n) \
+- ({ \
++({ \
+ BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
+ cmpxchg((ptr), (o), (n)); \
+- })
++})
+ #define cmpxchg_local(ptr, o, n) \
+ ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
+- (unsigned long)(n), sizeof(*(ptr))))
++ (unsigned long)(n), \
++ sizeof(*(ptr))))
+ #define cmpxchg64_local(ptr, o, n) \
+- ({ \
++({ \
+ BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
+ cmpxchg_local((ptr), (o), (n)); \
+- })
++})
+
+ #endif
+diff --git a/include/asm-x86/compat.h b/include/asm-x86/compat.h
+index d3e8f3e..1793ac3 100644
+--- a/include/asm-x86/compat.h
++++ b/include/asm-x86/compat.h
+@@ -204,7 +204,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
+ return (u32)(unsigned long)uptr;
+ }
+
+-static __inline__ void __user *compat_alloc_user_space(long len)
++static inline void __user *compat_alloc_user_space(long len)
+ {
+ struct pt_regs *regs = task_pt_regs(current);
+ return (void __user *)regs->sp - len;
+diff --git a/include/asm-x86/cpufeature.h b/include/asm-x86/cpufeature.h
+index 065e929..0d609c8 100644
+--- a/include/asm-x86/cpufeature.h
++++ b/include/asm-x86/cpufeature.h
+@@ -120,6 +120,9 @@
+ extern const char * const x86_cap_flags[NCAPINTS*32];
+ extern const char * const x86_power_flags[32];
+
++#define test_cpu_cap(c, bit) \
++ test_bit(bit, (unsigned long *)((c)->x86_capability))
++
+ #define cpu_has(c, bit) \
+ (__builtin_constant_p(bit) && \
+ ( (((bit)>>5)==0 && (1UL<<((bit)&31) & REQUIRED_MASK0)) || \
+@@ -131,7 +134,8 @@ extern const char * const x86_power_flags[32];
+ (((bit)>>5)==6 && (1UL<<((bit)&31) & REQUIRED_MASK6)) || \
+ (((bit)>>5)==7 && (1UL<<((bit)&31) & REQUIRED_MASK7)) ) \
+ ? 1 : \
+- test_bit(bit, (unsigned long *)((c)->x86_capability)))
++ test_cpu_cap(c, bit))
++
+ #define boot_cpu_has(bit) cpu_has(&boot_cpu_data, bit)
+
+ #define set_cpu_cap(c, bit) set_bit(bit, (unsigned long *)((c)->x86_capability))
+@@ -181,6 +185,8 @@ extern const char * const x86_power_flags[32];
+ #define cpu_has_clflush boot_cpu_has(X86_FEATURE_CLFLSH)
+ #define cpu_has_bts boot_cpu_has(X86_FEATURE_BTS)
+ #define cpu_has_gbpages boot_cpu_has(X86_FEATURE_GBPAGES)
++#define cpu_has_arch_perfmon boot_cpu_has(X86_FEATURE_ARCH_PERFMON)
++#define cpu_has_pat boot_cpu_has(X86_FEATURE_PAT)
+
+ #if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64)
+ # define cpu_has_invlpg 1
+diff --git a/include/asm-x86/current_32.h b/include/asm-x86/current_32.h
+index d352485..5af9bdb 100644
+--- a/include/asm-x86/current_32.h
++++ b/include/asm-x86/current_32.h
+@@ -11,7 +11,7 @@ static __always_inline struct task_struct *get_current(void)
+ {
+ return x86_read_percpu(current_task);
+ }
+-
++
+ #define current get_current()
+
+ #endif /* !(_I386_CURRENT_H) */
+diff --git a/include/asm-x86/current_64.h b/include/asm-x86/current_64.h
+index bc8adec..2d368ed 100644
+--- a/include/asm-x86/current_64.h
++++ b/include/asm-x86/current_64.h
+@@ -1,23 +1,23 @@
+ #ifndef _X86_64_CURRENT_H
+ #define _X86_64_CURRENT_H
+
+-#if !defined(__ASSEMBLY__)
++#if !defined(__ASSEMBLY__)
+ struct task_struct;
+
+ #include <asm/pda.h>
+
+-static inline struct task_struct *get_current(void)
+-{
+- struct task_struct *t = read_pda(pcurrent);
++static inline struct task_struct *get_current(void)
++{
++ struct task_struct *t = read_pda(pcurrent);
+ return t;
+-}
++}
+
+ #define current get_current()
+
+ #else
+
+ #ifndef ASM_OFFSET_H
+-#include <asm/asm-offsets.h>
++#include <asm/asm-offsets.h>
+ #endif
+
+ #define GET_CURRENT(reg) movq %gs:(pda_pcurrent),reg
+diff --git a/include/asm-x86/desc.h b/include/asm-x86/desc.h
+index 5b6a05d..268a012 100644
+--- a/include/asm-x86/desc.h
++++ b/include/asm-x86/desc.h
+@@ -62,8 +62,8 @@ static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
+ }
+
+ static inline void pack_gate(gate_desc *gate, unsigned char type,
+- unsigned long base, unsigned dpl, unsigned flags, unsigned short seg)
+-
++ unsigned long base, unsigned dpl, unsigned flags,
++ unsigned short seg)
+ {
+ gate->a = (seg << 16) | (base & 0xffff);
+ gate->b = (base & 0xffff0000) |
+@@ -84,22 +84,23 @@ static inline int desc_empty(const void *ptr)
+ #define load_TR_desc() native_load_tr_desc()
+ #define load_gdt(dtr) native_load_gdt(dtr)
+ #define load_idt(dtr) native_load_idt(dtr)
+-#define load_tr(tr) __asm__ __volatile("ltr %0"::"m" (tr))
+-#define load_ldt(ldt) __asm__ __volatile("lldt %0"::"m" (ldt))
++#define load_tr(tr) asm volatile("ltr %0"::"m" (tr))
++#define load_ldt(ldt) asm volatile("lldt %0"::"m" (ldt))
+
+ #define store_gdt(dtr) native_store_gdt(dtr)
+ #define store_idt(dtr) native_store_idt(dtr)
+ #define store_tr(tr) (tr = native_store_tr())
+-#define store_ldt(ldt) __asm__ ("sldt %0":"=m" (ldt))
++#define store_ldt(ldt) asm("sldt %0":"=m" (ldt))
+
+ #define load_TLS(t, cpu) native_load_tls(t, cpu)
+ #define set_ldt native_set_ldt
+
+-#define write_ldt_entry(dt, entry, desc) \
+- native_write_ldt_entry(dt, entry, desc)
+-#define write_gdt_entry(dt, entry, desc, type) \
+- native_write_gdt_entry(dt, entry, desc, type)
+-#define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
++#define write_ldt_entry(dt, entry, desc) \
++ native_write_ldt_entry(dt, entry, desc)
++#define write_gdt_entry(dt, entry, desc, type) \
++ native_write_gdt_entry(dt, entry, desc, type)
++#define write_idt_entry(dt, entry, g) \
++ native_write_idt_entry(dt, entry, g)
+ #endif
+
+ static inline void native_write_idt_entry(gate_desc *idt, int entry,
+@@ -138,8 +139,8 @@ static inline void pack_descriptor(struct desc_struct *desc, unsigned long base,
+ {
+ desc->a = ((base & 0xffff) << 16) | (limit & 0xffff);
+ desc->b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
+- (limit & 0x000f0000) | ((type & 0xff) << 8) |
+- ((flags & 0xf) << 20);
++ (limit & 0x000f0000) | ((type & 0xff) << 8) |
++ ((flags & 0xf) << 20);
+ desc->p = 1;
+ }
+
+@@ -159,7 +160,6 @@ static inline void set_tssldt_descriptor(void *d, unsigned long addr,
+ desc->base2 = (PTR_MIDDLE(addr) >> 8) & 0xFF;
+ desc->base3 = PTR_HIGH(addr);
+ #else
+-
+ pack_descriptor((struct desc_struct *)d, addr, size, 0x80 | type, 0);
+ #endif
+ }
+@@ -177,7 +177,8 @@ static inline void __set_tss_desc(unsigned cpu, unsigned int entry, void *addr)
+ * last valid byte
+ */
+ set_tssldt_descriptor(&tss, (unsigned long)addr, DESC_TSS,
+- IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
++ IO_BITMAP_OFFSET + IO_BITMAP_BYTES +
++ sizeof(unsigned long) - 1);
+ write_gdt_entry(d, entry, &tss, DESC_TSS);
+ }
+
+@@ -186,7 +187,7 @@ static inline void __set_tss_desc(unsigned cpu, unsigned int entry, void *addr)
+ static inline void native_set_ldt(const void *addr, unsigned int entries)
+ {
+ if (likely(entries == 0))
+- __asm__ __volatile__("lldt %w0"::"q" (0));
++ asm volatile("lldt %w0"::"q" (0));
+ else {
+ unsigned cpu = smp_processor_id();
+ ldt_desc ldt;
+@@ -195,7 +196,7 @@ static inline void native_set_ldt(const void *addr, unsigned int entries)
+ DESC_LDT, entries * sizeof(ldt) - 1);
+ write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT,
+ &ldt, DESC_LDT);
+- __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
++ asm volatile("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
+ }
+ }
+
+@@ -240,15 +241,15 @@ static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)
+ gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i];
+ }
+
+-#define _LDT_empty(info) (\
+- (info)->base_addr == 0 && \
+- (info)->limit == 0 && \
+- (info)->contents == 0 && \
+- (info)->read_exec_only == 1 && \
+- (info)->seg_32bit == 0 && \
+- (info)->limit_in_pages == 0 && \
+- (info)->seg_not_present == 1 && \
+- (info)->useable == 0)
++#define _LDT_empty(info) \
++ ((info)->base_addr == 0 && \
++ (info)->limit == 0 && \
++ (info)->contents == 0 && \
++ (info)->read_exec_only == 1 && \
++ (info)->seg_32bit == 0 && \
++ (info)->limit_in_pages == 0 && \
++ (info)->seg_not_present == 1 && \
++ (info)->useable == 0)
+
+ #ifdef CONFIG_X86_64
+ #define LDT_empty(info) (_LDT_empty(info) && ((info)->lm == 0))
+@@ -287,7 +288,7 @@ static inline unsigned long get_desc_limit(const struct desc_struct *desc)
+ }
+
+ static inline void _set_gate(int gate, unsigned type, void *addr,
+- unsigned dpl, unsigned ist, unsigned seg)
++ unsigned dpl, unsigned ist, unsigned seg)
+ {
+ gate_desc s;
+ pack_gate(&s, type, (unsigned long)addr, dpl, ist, seg);
+@@ -370,10 +371,10 @@ static inline void set_system_gate_ist(int n, void *addr, unsigned ist)
+ * Will read the base address of GDT_ENTRY_ESPFIX_SS and put it into %eax.
+ */
+ #define GET_DESC_BASE(idx, gdt, base, lo_w, lo_b, hi_b) \
+- movb idx*8+4(gdt), lo_b; \
+- movb idx*8+7(gdt), hi_b; \
+- shll $16, base; \
+- movw idx*8+2(gdt), lo_w;
++ movb idx * 8 + 4(gdt), lo_b; \
++ movb idx * 8 + 7(gdt), hi_b; \
++ shll $16, base; \
++ movw idx * 8 + 2(gdt), lo_w;
+
+
+ #endif /* __ASSEMBLY__ */
+diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h
+index e33f078..eccb4ea 100644
+--- a/include/asm-x86/desc_defs.h
++++ b/include/asm-x86/desc_defs.h
+@@ -18,17 +18,19 @@
+ * incrementally. We keep the signature as a struct, rather than an union,
+ * so we can get rid of it transparently in the future -- glommer
+ */
+-// 8 byte segment descriptor
++/* 8 byte segment descriptor */
+ struct desc_struct {
+ union {
+- struct { unsigned int a, b; };
++ struct {
++ unsigned int a;
++ unsigned int b;
++ };
+ struct {
+ u16 limit0;
+ u16 base0;
+ unsigned base1: 8, type: 4, s: 1, dpl: 2, p: 1;
+ unsigned limit: 4, avl: 1, l: 1, d: 1, g: 1, base2: 8;
+ };
+-
+ };
+ } __attribute__((packed));
+
+@@ -39,7 +41,7 @@ enum {
+ GATE_TASK = 0x5,
+ };
+
+-// 16byte gate
++/* 16byte gate */
+ struct gate_struct64 {
+ u16 offset_low;
+ u16 segment;
+@@ -56,10 +58,10 @@ struct gate_struct64 {
+ enum {
+ DESC_TSS = 0x9,
+ DESC_LDT = 0x2,
+- DESCTYPE_S = 0x10, /* !system */
++ DESCTYPE_S = 0x10, /* !system */
+ };
+
+-// LDT or TSS descriptor in the GDT. 16 bytes.
++/* LDT or TSS descriptor in the GDT. 16 bytes. */
+ struct ldttss_desc64 {
+ u16 limit0;
+ u16 base0;
+@@ -84,7 +86,6 @@ struct desc_ptr {
+ unsigned long address;
+ } __attribute__((packed)) ;
+
+-
+ #endif /* !__ASSEMBLY__ */
+
+ #endif
+diff --git a/include/asm-x86/div64.h b/include/asm-x86/div64.h
+index e98d16e..0dbf8bf 100644
+--- a/include/asm-x86/div64.h
++++ b/include/asm-x86/div64.h
+@@ -17,18 +17,20 @@
+ * This ends up being the most efficient "calling
+ * convention" on x86.
+ */
+-#define do_div(n,base) ({ \
+- unsigned long __upper, __low, __high, __mod, __base; \
+- __base = (base); \
+- asm("":"=a" (__low), "=d" (__high):"A" (n)); \
+- __upper = __high; \
+- if (__high) { \
+- __upper = __high % (__base); \
+- __high = __high / (__base); \
+- } \
+- asm("divl %2":"=a" (__low), "=d" (__mod):"rm" (__base), "0" (__low), "1" (__upper)); \
+- asm("":"=A" (n):"a" (__low),"d" (__high)); \
+- __mod; \
++#define do_div(n, base) \
++({ \
++ unsigned long __upper, __low, __high, __mod, __base; \
++ __base = (base); \
++ asm("":"=a" (__low), "=d" (__high) : "A" (n)); \
++ __upper = __high; \
++ if (__high) { \
++ __upper = __high % (__base); \
++ __high = __high / (__base); \
++ } \
++ asm("divl %2":"=a" (__low), "=d" (__mod) \
++ : "rm" (__base), "0" (__low), "1" (__upper)); \
++ asm("":"=A" (n) : "a" (__low), "d" (__high)); \
++ __mod; \
+ })
+
+ /*
+@@ -37,14 +39,13 @@
+ *
+ * Warning, this will do an exception if X overflows.
+ */
+-#define div_long_long_rem(a,b,c) div_ll_X_l_rem(a,b,c)
++#define div_long_long_rem(a, b, c) div_ll_X_l_rem(a, b, c)
+
+-static inline long
+-div_ll_X_l_rem(long long divs, long div, long *rem)
++static inline long div_ll_X_l_rem(long long divs, long div, long *rem)
+ {
+ long dum2;
+- __asm__("divl %2":"=a"(dum2), "=d"(*rem)
+- : "rm"(div), "A"(divs));
++ asm("divl %2":"=a"(dum2), "=d"(*rem)
++ : "rm"(div), "A"(divs));
+
+ return dum2;
+
+diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h
+index 58f790f..a1a4dc7 100644
+--- a/include/asm-x86/dma-mapping.h
++++ b/include/asm-x86/dma-mapping.h
+@@ -1,5 +1,237 @@
++#ifndef _ASM_DMA_MAPPING_H_
++#define _ASM_DMA_MAPPING_H_
++
++/*
++ * IOMMU interface. See Documentation/DMA-mapping.txt and DMA-API.txt for
++ * documentation.
++ */
++
++#include <linux/scatterlist.h>
++#include <asm/io.h>
++#include <asm/swiotlb.h>
++
++extern dma_addr_t bad_dma_address;
++extern int iommu_merge;
++extern struct device fallback_dev;
++extern int panic_on_overflow;
++extern int forbid_dac;
++extern int force_iommu;
++
++struct dma_mapping_ops {
++ int (*mapping_error)(dma_addr_t dma_addr);
++ void* (*alloc_coherent)(struct device *dev, size_t size,
++ dma_addr_t *dma_handle, gfp_t gfp);
++ void (*free_coherent)(struct device *dev, size_t size,
++ void *vaddr, dma_addr_t dma_handle);
++ dma_addr_t (*map_single)(struct device *hwdev, phys_addr_t ptr,
++ size_t size, int direction);
++ /* like map_single, but doesn't check the device mask */
++ dma_addr_t (*map_simple)(struct device *hwdev, phys_addr_t ptr,
++ size_t size, int direction);
++ void (*unmap_single)(struct device *dev, dma_addr_t addr,
++ size_t size, int direction);
++ void (*sync_single_for_cpu)(struct device *hwdev,
++ dma_addr_t dma_handle, size_t size,
++ int direction);
++ void (*sync_single_for_device)(struct device *hwdev,
++ dma_addr_t dma_handle, size_t size,
++ int direction);
++ void (*sync_single_range_for_cpu)(struct device *hwdev,
++ dma_addr_t dma_handle, unsigned long offset,
++ size_t size, int direction);
++ void (*sync_single_range_for_device)(struct device *hwdev,
++ dma_addr_t dma_handle, unsigned long offset,
++ size_t size, int direction);
++ void (*sync_sg_for_cpu)(struct device *hwdev,
++ struct scatterlist *sg, int nelems,
++ int direction);
++ void (*sync_sg_for_device)(struct device *hwdev,
++ struct scatterlist *sg, int nelems,
++ int direction);
++ int (*map_sg)(struct device *hwdev, struct scatterlist *sg,
++ int nents, int direction);
++ void (*unmap_sg)(struct device *hwdev,
++ struct scatterlist *sg, int nents,
++ int direction);
++ int (*dma_supported)(struct device *hwdev, u64 mask);
++ int is_phys;
++};
++
++extern const struct dma_mapping_ops *dma_ops;
++
++static inline int dma_mapping_error(dma_addr_t dma_addr)
++{
++ if (dma_ops->mapping_error)
++ return dma_ops->mapping_error(dma_addr);
++
++ return (dma_addr == bad_dma_address);
++}
++
++#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
++#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
++
++void *dma_alloc_coherent(struct device *dev, size_t size,
++ dma_addr_t *dma_handle, gfp_t flag);
++
++void dma_free_coherent(struct device *dev, size_t size,
++ void *vaddr, dma_addr_t dma_handle);
++
++
++extern int dma_supported(struct device *hwdev, u64 mask);
++extern int dma_set_mask(struct device *dev, u64 mask);
++
++static inline dma_addr_t
++dma_map_single(struct device *hwdev, void *ptr, size_t size,
++ int direction)
++{
++ BUG_ON(!valid_dma_direction(direction));
++ return dma_ops->map_single(hwdev, virt_to_phys(ptr), size, direction);
++}
++
++static inline void
++dma_unmap_single(struct device *dev, dma_addr_t addr, size_t size,
++ int direction)
++{
++ BUG_ON(!valid_dma_direction(direction));
++ if (dma_ops->unmap_single)
++ dma_ops->unmap_single(dev, addr, size, direction);
++}
++
++static inline int
++dma_map_sg(struct device *hwdev, struct scatterlist *sg,
++ int nents, int direction)
++{
++ BUG_ON(!valid_dma_direction(direction));
++ return dma_ops->map_sg(hwdev, sg, nents, direction);
++}
++
++static inline void
++dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
++ int direction)
++{
++ BUG_ON(!valid_dma_direction(direction));
++ if (dma_ops->unmap_sg)
++ dma_ops->unmap_sg(hwdev, sg, nents, direction);
++}
++
++static inline void
++dma_sync_single_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
++ size_t size, int direction)
++{
++ BUG_ON(!valid_dma_direction(direction));
++ if (dma_ops->sync_single_for_cpu)
++ dma_ops->sync_single_for_cpu(hwdev, dma_handle, size,
++ direction);
++ flush_write_buffers();
++}
++
++static inline void
++dma_sync_single_for_device(struct device *hwdev, dma_addr_t dma_handle,
++ size_t size, int direction)
++{
++ BUG_ON(!valid_dma_direction(direction));
++ if (dma_ops->sync_single_for_device)
++ dma_ops->sync_single_for_device(hwdev, dma_handle, size,
++ direction);
++ flush_write_buffers();
++}
++
++static inline void
++dma_sync_single_range_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
++ unsigned long offset, size_t size, int direction)
++{
++ BUG_ON(!valid_dma_direction(direction));
++ if (dma_ops->sync_single_range_for_cpu)
++ dma_ops->sync_single_range_for_cpu(hwdev, dma_handle, offset,
++ size, direction);
++
++ flush_write_buffers();
++}
++
++static inline void
++dma_sync_single_range_for_device(struct device *hwdev, dma_addr_t dma_handle,
++ unsigned long offset, size_t size,
++ int direction)
++{
++ BUG_ON(!valid_dma_direction(direction));
++ if (dma_ops->sync_single_range_for_device)
++ dma_ops->sync_single_range_for_device(hwdev, dma_handle,
++ offset, size, direction);
++
++ flush_write_buffers();
++}
++
++static inline void
++dma_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg,
++ int nelems, int direction)
++{
++ BUG_ON(!valid_dma_direction(direction));
++ if (dma_ops->sync_sg_for_cpu)
++ dma_ops->sync_sg_for_cpu(hwdev, sg, nelems, direction);
++ flush_write_buffers();
++}
++
++static inline void
++dma_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
++ int nelems, int direction)
++{
++ BUG_ON(!valid_dma_direction(direction));
++ if (dma_ops->sync_sg_for_device)
++ dma_ops->sync_sg_for_device(hwdev, sg, nelems, direction);
++
++ flush_write_buffers();
++}
++
++static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
++ size_t offset, size_t size,
++ int direction)
++{
++ BUG_ON(!valid_dma_direction(direction));
++ return dma_ops->map_single(dev, page_to_phys(page)+offset,
++ size, direction);
++}
++
++static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
++ size_t size, int direction)
++{
++ dma_unmap_single(dev, addr, size, direction);
++}
++
++static inline void
++dma_cache_sync(struct device *dev, void *vaddr, size_t size,
++ enum dma_data_direction dir)
++{
++ flush_write_buffers();
++}
++
++static inline int dma_get_cache_alignment(void)
++{
++ /* no easy way to get cache size on all x86, so return the
++ * maximum possible, to be safe */
++ return boot_cpu_data.x86_clflush_size;
++}
++
++#define dma_is_consistent(d, h) (1)
++
+ #ifdef CONFIG_X86_32
+-# include "dma-mapping_32.h"
+-#else
+-# include "dma-mapping_64.h"
++# define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
++struct dma_coherent_mem {
++ void *virt_base;
++ u32 device_base;
++ int size;
++ int flags;
++ unsigned long *bitmap;
++};
++
++extern int
++dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
++ dma_addr_t device_addr, size_t size, int flags);
++
++extern void
++dma_release_declared_memory(struct device *dev);
++
++extern void *
++dma_mark_declared_memory_occupied(struct device *dev,
++ dma_addr_t device_addr, size_t size);
++#endif /* CONFIG_X86_32 */
+ #endif
+diff --git a/include/asm-x86/dma-mapping_32.h b/include/asm-x86/dma-mapping_32.h
+deleted file mode 100644
+index 55f01bd..0000000
+--- a/include/asm-x86/dma-mapping_32.h
++++ /dev/null
+@@ -1,187 +0,0 @@
+-#ifndef _ASM_I386_DMA_MAPPING_H
+-#define _ASM_I386_DMA_MAPPING_H
+-
+-#include <linux/mm.h>
+-#include <linux/scatterlist.h>
+-
+-#include <asm/cache.h>
+-#include <asm/io.h>
+-#include <asm/bug.h>
+-
+-#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+-#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+-
+-void *dma_alloc_coherent(struct device *dev, size_t size,
+- dma_addr_t *dma_handle, gfp_t flag);
+-
+-void dma_free_coherent(struct device *dev, size_t size,
+- void *vaddr, dma_addr_t dma_handle);
+-
+-static inline dma_addr_t
+-dma_map_single(struct device *dev, void *ptr, size_t size,
+- enum dma_data_direction direction)
+-{
+- BUG_ON(!valid_dma_direction(direction));
+- WARN_ON(size == 0);
+- flush_write_buffers();
+- return virt_to_phys(ptr);
+-}
+-
+-static inline void
+-dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+- enum dma_data_direction direction)
+-{
+- BUG_ON(!valid_dma_direction(direction));
+-}
+-
+-static inline int
+-dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
+- enum dma_data_direction direction)
+-{
+- struct scatterlist *sg;
+- int i;
+-
+- BUG_ON(!valid_dma_direction(direction));
+- WARN_ON(nents == 0 || sglist[0].length == 0);
+-
+- for_each_sg(sglist, sg, nents, i) {
+- BUG_ON(!sg_page(sg));
+-
+- sg->dma_address = sg_phys(sg);
+- }
+-
+- flush_write_buffers();
+- return nents;
+-}
+-
+-static inline dma_addr_t
+-dma_map_page(struct device *dev, struct page *page, unsigned long offset,
+- size_t size, enum dma_data_direction direction)
+-{
+- BUG_ON(!valid_dma_direction(direction));
+- return page_to_phys(page) + offset;
+-}
+-
+-static inline void
+-dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+- enum dma_data_direction direction)
+-{
+- BUG_ON(!valid_dma_direction(direction));
+-}
+-
+-
+-static inline void
+-dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+- enum dma_data_direction direction)
+-{
+- BUG_ON(!valid_dma_direction(direction));
+-}
+-
+-static inline void
+-dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
+- enum dma_data_direction direction)
+-{
+-}
+-
+-static inline void
+-dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
+- enum dma_data_direction direction)
+-{
+- flush_write_buffers();
+-}
+-
+-static inline void
+-dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
+- unsigned long offset, size_t size,
+- enum dma_data_direction direction)
+-{
+-}
+-
+-static inline void
+-dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
+- unsigned long offset, size_t size,
+- enum dma_data_direction direction)
+-{
+- flush_write_buffers();
+-}
+-
+-static inline void
+-dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
+- enum dma_data_direction direction)
+-{
+-}
+-
+-static inline void
+-dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
+- enum dma_data_direction direction)
+-{
+- flush_write_buffers();
+-}
+-
+-static inline int
+-dma_mapping_error(dma_addr_t dma_addr)
+-{
+- return 0;
+-}
+-
+-extern int forbid_dac;
+-
+-static inline int
+-dma_supported(struct device *dev, u64 mask)
+-{
+- /*
+- * we fall back to GFP_DMA when the mask isn't all 1s,
+- * so we can't guarantee allocations that must be
+- * within a tighter range than GFP_DMA..
+- */
+- if(mask < 0x00ffffff)
+- return 0;
+-
+- /* Work around chipset bugs */
+- if (forbid_dac > 0 && mask > 0xffffffffULL)
+- return 0;
+-
+- return 1;
+-}
+-
+-static inline int
+-dma_set_mask(struct device *dev, u64 mask)
+-{
+- if(!dev->dma_mask || !dma_supported(dev, mask))
+- return -EIO;
+-
+- *dev->dma_mask = mask;
+-
+- return 0;
+-}
+-
+-static inline int
+-dma_get_cache_alignment(void)
+-{
+- /* no easy way to get cache size on all x86, so return the
+- * maximum possible, to be safe */
+- return (1 << INTERNODE_CACHE_SHIFT);
+-}
+-
+-#define dma_is_consistent(d, h) (1)
+-
+-static inline void
+-dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+- enum dma_data_direction direction)
+-{
+- flush_write_buffers();
+-}
+-
+-#define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
+-extern int
+-dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+- dma_addr_t device_addr, size_t size, int flags);
+-
+-extern void
+-dma_release_declared_memory(struct device *dev);
+-
+-extern void *
+-dma_mark_declared_memory_occupied(struct device *dev,
+- dma_addr_t device_addr, size_t size);
+-
+-#endif
+diff --git a/include/asm-x86/dma-mapping_64.h b/include/asm-x86/dma-mapping_64.h
+deleted file mode 100644
+index ecd0f61..0000000
+--- a/include/asm-x86/dma-mapping_64.h
++++ /dev/null
+@@ -1,202 +0,0 @@
+-#ifndef _X8664_DMA_MAPPING_H
+-#define _X8664_DMA_MAPPING_H 1
+-
+-/*
+- * IOMMU interface. See Documentation/DMA-mapping.txt and DMA-API.txt for
+- * documentation.
+- */
+-
+-#include <linux/scatterlist.h>
+-#include <asm/io.h>
+-#include <asm/swiotlb.h>
+-
+-struct dma_mapping_ops {
+- int (*mapping_error)(dma_addr_t dma_addr);
+- void* (*alloc_coherent)(struct device *dev, size_t size,
+- dma_addr_t *dma_handle, gfp_t gfp);
+- void (*free_coherent)(struct device *dev, size_t size,
+- void *vaddr, dma_addr_t dma_handle);
+- dma_addr_t (*map_single)(struct device *hwdev, void *ptr,
+- size_t size, int direction);
+- /* like map_single, but doesn't check the device mask */
+- dma_addr_t (*map_simple)(struct device *hwdev, char *ptr,
+- size_t size, int direction);
+- void (*unmap_single)(struct device *dev, dma_addr_t addr,
+- size_t size, int direction);
+- void (*sync_single_for_cpu)(struct device *hwdev,
+- dma_addr_t dma_handle, size_t size,
+- int direction);
+- void (*sync_single_for_device)(struct device *hwdev,
+- dma_addr_t dma_handle, size_t size,
+- int direction);
+- void (*sync_single_range_for_cpu)(struct device *hwdev,
+- dma_addr_t dma_handle, unsigned long offset,
+- size_t size, int direction);
+- void (*sync_single_range_for_device)(struct device *hwdev,
+- dma_addr_t dma_handle, unsigned long offset,
+- size_t size, int direction);
+- void (*sync_sg_for_cpu)(struct device *hwdev,
+- struct scatterlist *sg, int nelems,
+- int direction);
+- void (*sync_sg_for_device)(struct device *hwdev,
+- struct scatterlist *sg, int nelems,
+- int direction);
+- int (*map_sg)(struct device *hwdev, struct scatterlist *sg,
+- int nents, int direction);
+- void (*unmap_sg)(struct device *hwdev,
+- struct scatterlist *sg, int nents,
+- int direction);
+- int (*dma_supported)(struct device *hwdev, u64 mask);
+- int is_phys;
+-};
+-
+-extern dma_addr_t bad_dma_address;
+-extern const struct dma_mapping_ops* dma_ops;
+-extern int iommu_merge;
+-
+-static inline int dma_mapping_error(dma_addr_t dma_addr)
+-{
+- if (dma_ops->mapping_error)
+- return dma_ops->mapping_error(dma_addr);
+-
+- return (dma_addr == bad_dma_address);
+-}
+-
+-#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+-#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+-
+-#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+-#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+-
+-extern void *dma_alloc_coherent(struct device *dev, size_t size,
+- dma_addr_t *dma_handle, gfp_t gfp);
+-extern void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+- dma_addr_t dma_handle);
+-
+-static inline dma_addr_t
+-dma_map_single(struct device *hwdev, void *ptr, size_t size,
+- int direction)
+-{
+- BUG_ON(!valid_dma_direction(direction));
+- return dma_ops->map_single(hwdev, ptr, size, direction);
+-}
+-
+-static inline void
+-dma_unmap_single(struct device *dev, dma_addr_t addr,size_t size,
+- int direction)
+-{
+- BUG_ON(!valid_dma_direction(direction));
+- dma_ops->unmap_single(dev, addr, size, direction);
+-}
+-
+-#define dma_map_page(dev,page,offset,size,dir) \
+- dma_map_single((dev), page_address(page)+(offset), (size), (dir))
+-
+-#define dma_unmap_page dma_unmap_single
+-
+-static inline void
+-dma_sync_single_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
+- size_t size, int direction)
+-{
+- BUG_ON(!valid_dma_direction(direction));
+- if (dma_ops->sync_single_for_cpu)
+- dma_ops->sync_single_for_cpu(hwdev, dma_handle, size,
+- direction);
+- flush_write_buffers();
+-}
+-
+-static inline void
+-dma_sync_single_for_device(struct device *hwdev, dma_addr_t dma_handle,
+- size_t size, int direction)
+-{
+- BUG_ON(!valid_dma_direction(direction));
+- if (dma_ops->sync_single_for_device)
+- dma_ops->sync_single_for_device(hwdev, dma_handle, size,
+- direction);
+- flush_write_buffers();
+-}
+-
+-static inline void
+-dma_sync_single_range_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
+- unsigned long offset, size_t size, int direction)
+-{
+- BUG_ON(!valid_dma_direction(direction));
+- if (dma_ops->sync_single_range_for_cpu) {
+- dma_ops->sync_single_range_for_cpu(hwdev, dma_handle, offset, size, direction);
+- }
+-
+- flush_write_buffers();
+-}
+-
+-static inline void
+-dma_sync_single_range_for_device(struct device *hwdev, dma_addr_t dma_handle,
+- unsigned long offset, size_t size, int direction)
+-{
+- BUG_ON(!valid_dma_direction(direction));
+- if (dma_ops->sync_single_range_for_device)
+- dma_ops->sync_single_range_for_device(hwdev, dma_handle,
+- offset, size, direction);
+-
+- flush_write_buffers();
+-}
+-
+-static inline void
+-dma_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg,
+- int nelems, int direction)
+-{
+- BUG_ON(!valid_dma_direction(direction));
+- if (dma_ops->sync_sg_for_cpu)
+- dma_ops->sync_sg_for_cpu(hwdev, sg, nelems, direction);
+- flush_write_buffers();
+-}
+-
+-static inline void
+-dma_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
+- int nelems, int direction)
+-{
+- BUG_ON(!valid_dma_direction(direction));
+- if (dma_ops->sync_sg_for_device) {
+- dma_ops->sync_sg_for_device(hwdev, sg, nelems, direction);
+- }
+-
+- flush_write_buffers();
+-}
+-
+-static inline int
+-dma_map_sg(struct device *hwdev, struct scatterlist *sg, int nents, int direction)
+-{
+- BUG_ON(!valid_dma_direction(direction));
+- return dma_ops->map_sg(hwdev, sg, nents, direction);
+-}
+-
+-static inline void
+-dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
+- int direction)
+-{
+- BUG_ON(!valid_dma_direction(direction));
+- dma_ops->unmap_sg(hwdev, sg, nents, direction);
+-}
+-
+-extern int dma_supported(struct device *hwdev, u64 mask);
+-
+-/* same for gart, swiotlb, and nommu */
+-static inline int dma_get_cache_alignment(void)
+-{
+- return boot_cpu_data.x86_clflush_size;
+-}
+-
+-#define dma_is_consistent(d, h) 1
+-
+-extern int dma_set_mask(struct device *dev, u64 mask);
+-
+-static inline void
+-dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+- enum dma_data_direction dir)
+-{
+- flush_write_buffers();
+-}
+-
+-extern struct device fallback_dev;
+-extern int panic_on_overflow;
+-
+-#endif /* _X8664_DMA_MAPPING_H */
+diff --git a/include/asm-x86/dma.h b/include/asm-x86/dma.h
+index e9733ce..ca1098a 100644
+--- a/include/asm-x86/dma.h
++++ b/include/asm-x86/dma.h
+@@ -12,7 +12,6 @@
+ #include <asm/io.h> /* need byte IO */
+ #include <linux/delay.h>
+
+-
+ #ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER
+ #define dma_outb outb_p
+ #else
+@@ -74,15 +73,15 @@
+ #ifdef CONFIG_X86_32
+
+ /* The maximum address that we can perform a DMA transfer to on this platform */
+-#define MAX_DMA_ADDRESS (PAGE_OFFSET+0x1000000)
++#define MAX_DMA_ADDRESS (PAGE_OFFSET + 0x1000000)
+
+ #else
+
+ /* 16MB ISA DMA zone */
+-#define MAX_DMA_PFN ((16*1024*1024) >> PAGE_SHIFT)
++#define MAX_DMA_PFN ((16 * 1024 * 1024) >> PAGE_SHIFT)
+
+ /* 4GB broken PCI/AGP hardware bus master zone */
+-#define MAX_DMA32_PFN ((4UL*1024*1024*1024) >> PAGE_SHIFT)
++#define MAX_DMA32_PFN ((4UL * 1024 * 1024 * 1024) >> PAGE_SHIFT)
+
+ /* Compat define for old dma zone */
+ #define MAX_DMA_ADDRESS ((unsigned long)__va(MAX_DMA_PFN << PAGE_SHIFT))
+@@ -154,20 +153,20 @@
+
+ extern spinlock_t dma_spin_lock;
+
+-static __inline__ unsigned long claim_dma_lock(void)
++static inline unsigned long claim_dma_lock(void)
+ {
+ unsigned long flags;
+ spin_lock_irqsave(&dma_spin_lock, flags);
+ return flags;
+ }
+
+-static __inline__ void release_dma_lock(unsigned long flags)
++static inline void release_dma_lock(unsigned long flags)
+ {
+ spin_unlock_irqrestore(&dma_spin_lock, flags);
+ }
+
+ /* enable/disable a specific DMA channel */
+-static __inline__ void enable_dma(unsigned int dmanr)
++static inline void enable_dma(unsigned int dmanr)
+ {
+ if (dmanr <= 3)
+ dma_outb(dmanr, DMA1_MASK_REG);
+@@ -175,7 +174,7 @@ static __inline__ void enable_dma(unsigned int dmanr)
+ dma_outb(dmanr & 3, DMA2_MASK_REG);
+ }
+
+-static __inline__ void disable_dma(unsigned int dmanr)
++static inline void disable_dma(unsigned int dmanr)
+ {
+ if (dmanr <= 3)
+ dma_outb(dmanr | 4, DMA1_MASK_REG);
+@@ -190,7 +189,7 @@ static __inline__ void disable_dma(unsigned int dmanr)
+ * --- In order to do that, the DMA routines below should ---
+ * --- only be used while holding the DMA lock ! ---
+ */
+-static __inline__ void clear_dma_ff(unsigned int dmanr)
++static inline void clear_dma_ff(unsigned int dmanr)
+ {
+ if (dmanr <= 3)
+ dma_outb(0, DMA1_CLEAR_FF_REG);
+@@ -199,7 +198,7 @@ static __inline__ void clear_dma_ff(unsigned int dmanr)
+ }
+
+ /* set mode (above) for a specific DMA channel */
+-static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
++static inline void set_dma_mode(unsigned int dmanr, char mode)
+ {
+ if (dmanr <= 3)
+ dma_outb(mode | dmanr, DMA1_MODE_REG);
+@@ -212,7 +211,7 @@ static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
+ * the lower 16 bits of the DMA current address register, but a 64k boundary
+ * may have been crossed.
+ */
+-static __inline__ void set_dma_page(unsigned int dmanr, char pagenr)
++static inline void set_dma_page(unsigned int dmanr, char pagenr)
+ {
+ switch (dmanr) {
+ case 0:
+@@ -243,15 +242,15 @@ static __inline__ void set_dma_page(unsigned int dmanr, char pagenr)
+ /* Set transfer address & page bits for specific DMA channel.
+ * Assumes dma flipflop is clear.
+ */
+-static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)
++static inline void set_dma_addr(unsigned int dmanr, unsigned int a)
+ {
+ set_dma_page(dmanr, a>>16);
+ if (dmanr <= 3) {
+ dma_outb(a & 0xff, ((dmanr & 3) << 1) + IO_DMA1_BASE);
+ dma_outb((a >> 8) & 0xff, ((dmanr & 3) << 1) + IO_DMA1_BASE);
+ } else {
+- dma_outb((a >> 1) & 0xff, ((dmanr & 3) << 2) + IO_DMA2_BASE);
+- dma_outb((a >> 9) & 0xff, ((dmanr & 3) << 2) + IO_DMA2_BASE);
++ dma_outb((a >> 1) & 0xff, ((dmanr & 3) << 2) + IO_DMA2_BASE);
++ dma_outb((a >> 9) & 0xff, ((dmanr & 3) << 2) + IO_DMA2_BASE);
+ }
+ }
+
+@@ -264,18 +263,18 @@ static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)
+ * Assumes dma flip-flop is clear.
+ * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7.
+ */
+-static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
++static inline void set_dma_count(unsigned int dmanr, unsigned int count)
+ {
+ count--;
+ if (dmanr <= 3) {
+- dma_outb(count & 0xff, ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE);
+- dma_outb((count >> 8) & 0xff,
+- ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE);
++ dma_outb(count & 0xff, ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE);
++ dma_outb((count >> 8) & 0xff,
++ ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE);
+ } else {
+- dma_outb((count >> 1) & 0xff,
+- ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE);
+- dma_outb((count >> 9) & 0xff,
+- ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE);
++ dma_outb((count >> 1) & 0xff,
++ ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE);
++ dma_outb((count >> 9) & 0xff,
++ ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE);
+ }
+ }
+
+@@ -288,7 +287,7 @@ static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
+ *
+ * Assumes DMA flip-flop is clear.
+ */
+-static __inline__ int get_dma_residue(unsigned int dmanr)
++static inline int get_dma_residue(unsigned int dmanr)
+ {
+ unsigned int io_port;
+ /* using short to get 16-bit wrap around */
+diff --git a/include/asm-x86/dwarf2_64.h b/include/asm-x86/dwarf2_64.h
+index eedc085..c950519 100644
+--- a/include/asm-x86/dwarf2_64.h
++++ b/include/asm-x86/dwarf2_64.h
+@@ -1,16 +1,15 @@
+ #ifndef _DWARF2_H
+ #define _DWARF2_H 1
+
+-
+ #ifndef __ASSEMBLY__
+ #warning "asm/dwarf2.h should be only included in pure assembly files"
+ #endif
+
+-/*
++/*
+ Macros for dwarf2 CFI unwind table entries.
+- See "as.info" for details on these pseudo ops. Unfortunately
+- they are only supported in very new binutils, so define them
+- away for older version.
++ See "as.info" for details on these pseudo ops. Unfortunately
++ they are only supported in very new binutils, so define them
++ away for older version.
+ */
+
+ #ifdef CONFIG_AS_CFI
+diff --git a/include/asm-x86/e820_32.h b/include/asm-x86/e820_32.h
+index e7207a6..a9f7c6e 100644
+--- a/include/asm-x86/e820_32.h
++++ b/include/asm-x86/e820_32.h
+@@ -24,7 +24,7 @@ extern void update_e820(void);
+ extern int e820_all_mapped(unsigned long start, unsigned long end,
+ unsigned type);
+ extern int e820_any_mapped(u64 start, u64 end, unsigned type);
+-extern void find_max_pfn(void);
++extern void propagate_e820_map(void);
+ extern void register_bootmem_low_pages(unsigned long max_low_pfn);
+ extern void add_memory_region(unsigned long long start,
+ unsigned long long size, int type);
+@@ -34,8 +34,8 @@ extern void e820_register_memory(void);
+ extern void limit_regions(unsigned long long size);
+ extern void print_memory_map(char *who);
+ extern void init_iomem_resources(struct resource *code_resource,
+- struct resource *data_resource,
+- struct resource *bss_resource);
++ struct resource *data_resource,
++ struct resource *bss_resource);
+
+ #if defined(CONFIG_PM) && defined(CONFIG_HIBERNATION)
+ extern void e820_mark_nosave_regions(void);
+diff --git a/include/asm-x86/e820_64.h b/include/asm-x86/e820_64.h
+index 22ede73..f478c57 100644
+--- a/include/asm-x86/e820_64.h
++++ b/include/asm-x86/e820_64.h
+@@ -14,20 +14,24 @@
+ #include <linux/ioport.h>
+
+ #ifndef __ASSEMBLY__
+-extern unsigned long find_e820_area(unsigned long start, unsigned long end,
+- unsigned size, unsigned long align);
+-extern void add_memory_region(unsigned long start, unsigned long size,
++extern unsigned long find_e820_area(unsigned long start, unsigned long end,
++ unsigned long size, unsigned long align);
++extern unsigned long find_e820_area_size(unsigned long start,
++ unsigned long *sizep,
++ unsigned long align);
++extern void add_memory_region(unsigned long start, unsigned long size,
+ int type);
+ extern void update_memory_range(u64 start, u64 size, unsigned old_type,
+ unsigned new_type);
+ extern void setup_memory_region(void);
+-extern void contig_e820_setup(void);
++extern void contig_e820_setup(void);
+ extern unsigned long e820_end_of_ram(void);
+-extern void e820_reserve_resources(struct resource *code_resource,
+- struct resource *data_resource, struct resource *bss_resource);
++extern void e820_reserve_resources(void);
+ extern void e820_mark_nosave_regions(void);
+-extern int e820_any_mapped(unsigned long start, unsigned long end, unsigned type);
+-extern int e820_all_mapped(unsigned long start, unsigned long end, unsigned type);
++extern int e820_any_mapped(unsigned long start, unsigned long end,
++ unsigned type);
++extern int e820_all_mapped(unsigned long start, unsigned long end,
++ unsigned type);
+ extern int e820_any_non_reserved(unsigned long start, unsigned long end);
+ extern int is_memory_any_valid(unsigned long start, unsigned long end);
+ extern int e820_all_non_reserved(unsigned long start, unsigned long end);
+@@ -35,8 +39,8 @@ extern int is_memory_all_valid(unsigned long start, unsigned long end);
+ extern unsigned long e820_hole_size(unsigned long start, unsigned long end);
+
+ extern void e820_setup_gap(void);
+-extern void e820_register_active_regions(int nid,
+- unsigned long start_pfn, unsigned long end_pfn);
++extern void e820_register_active_regions(int nid, unsigned long start_pfn,
++ unsigned long end_pfn);
+
+ extern void finish_e820_parsing(void);
+
+diff --git a/include/asm-x86/edac.h b/include/asm-x86/edac.h
+index cf3200a..a8088f6 100644
+--- a/include/asm-x86/edac.h
++++ b/include/asm-x86/edac.h
+@@ -3,7 +3,7 @@
+
+ /* ECC atomic, DMA, SMP and interrupt safe scrub function */
+
+-static __inline__ void atomic_scrub(void *va, u32 size)
++static inline void atomic_scrub(void *va, u32 size)
+ {
+ u32 i, *virt_addr = va;
+
+@@ -12,7 +12,7 @@ static __inline__ void atomic_scrub(void *va, u32 size)
+ * are interrupt, DMA and SMP safe.
+ */
+ for (i = 0; i < size / 4; i++, virt_addr++)
+- __asm__ __volatile__("lock; addl $0, %0"::"m"(*virt_addr));
++ asm volatile("lock; addl $0, %0"::"m" (*virt_addr));
+ }
+
+ #endif
+diff --git a/include/asm-x86/efi.h b/include/asm-x86/efi.h
+index ea9734b..d53004b 100644
+--- a/include/asm-x86/efi.h
++++ b/include/asm-x86/efi.h
+@@ -20,7 +20,7 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...);
+ */
+
+ #define efi_call_virt(f, args...) \
+- ((efi_##f##_t __attribute__((regparm(0)))*)efi.systab->runtime->f)(args)
++ ((efi_##f##_t __attribute__((regparm(0)))*)efi.systab->runtime->f)(args)
+
+ #define efi_call_virt0(f) efi_call_virt(f)
+ #define efi_call_virt1(f, a1) efi_call_virt(f, a1)
+diff --git a/include/asm-x86/elf.h b/include/asm-x86/elf.h
+index fb62f99..8f232dc 100644
+--- a/include/asm-x86/elf.h
++++ b/include/asm-x86/elf.h
+@@ -11,7 +11,7 @@
+
+ typedef unsigned long elf_greg_t;
+
+-#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
++#define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t))
+ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+ typedef struct user_i387_struct elf_fpregset_t;
+@@ -82,8 +82,9 @@ extern unsigned int vdso_enabled;
+ #define elf_check_arch_ia32(x) \
+ (((x)->e_machine == EM_386) || ((x)->e_machine == EM_486))
+
+-#ifdef CONFIG_X86_32
+ #include <asm/processor.h>
++
++#ifdef CONFIG_X86_32
+ #include <asm/system.h> /* for savesegment */
+ #include <asm/desc.h>
+
+@@ -99,10 +100,11 @@ extern unsigned int vdso_enabled;
+ We might as well make sure everything else is cleared too (except for %esp),
+ just to make things more deterministic.
+ */
+-#define ELF_PLAT_INIT(_r, load_addr) do { \
+- _r->bx = 0; _r->cx = 0; _r->dx = 0; \
+- _r->si = 0; _r->di = 0; _r->bp = 0; \
+- _r->ax = 0; \
++#define ELF_PLAT_INIT(_r, load_addr) \
++ do { \
++ _r->bx = 0; _r->cx = 0; _r->dx = 0; \
++ _r->si = 0; _r->di = 0; _r->bp = 0; \
++ _r->ax = 0; \
+ } while (0)
+
+ /*
+@@ -110,24 +112,25 @@ extern unsigned int vdso_enabled;
+ * now struct_user_regs, they are different)
+ */
+
+-#define ELF_CORE_COPY_REGS(pr_reg, regs) do { \
+- pr_reg[0] = regs->bx; \
+- pr_reg[1] = regs->cx; \
+- pr_reg[2] = regs->dx; \
+- pr_reg[3] = regs->si; \
+- pr_reg[4] = regs->di; \
+- pr_reg[5] = regs->bp; \
+- pr_reg[6] = regs->ax; \
+- pr_reg[7] = regs->ds & 0xffff; \
+- pr_reg[8] = regs->es & 0xffff; \
+- pr_reg[9] = regs->fs & 0xffff; \
+- savesegment(gs, pr_reg[10]); \
+- pr_reg[11] = regs->orig_ax; \
+- pr_reg[12] = regs->ip; \
+- pr_reg[13] = regs->cs & 0xffff; \
+- pr_reg[14] = regs->flags; \
+- pr_reg[15] = regs->sp; \
+- pr_reg[16] = regs->ss & 0xffff; \
++#define ELF_CORE_COPY_REGS(pr_reg, regs) \
++do { \
++ pr_reg[0] = regs->bx; \
++ pr_reg[1] = regs->cx; \
++ pr_reg[2] = regs->dx; \
++ pr_reg[3] = regs->si; \
++ pr_reg[4] = regs->di; \
++ pr_reg[5] = regs->bp; \
++ pr_reg[6] = regs->ax; \
++ pr_reg[7] = regs->ds & 0xffff; \
++ pr_reg[8] = regs->es & 0xffff; \
++ pr_reg[9] = regs->fs & 0xffff; \
++ savesegment(gs, pr_reg[10]); \
++ pr_reg[11] = regs->orig_ax; \
++ pr_reg[12] = regs->ip; \
++ pr_reg[13] = regs->cs & 0xffff; \
++ pr_reg[14] = regs->flags; \
++ pr_reg[15] = regs->sp; \
++ pr_reg[16] = regs->ss & 0xffff; \
+ } while (0);
+
+ #define ELF_PLATFORM (utsname()->machine)
+@@ -135,12 +138,10 @@ extern unsigned int vdso_enabled;
+
+ #else /* CONFIG_X86_32 */
+
+-#include <asm/processor.h>
+-
+ /*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+-#define elf_check_arch(x) \
++#define elf_check_arch(x) \
+ ((x)->e_machine == EM_X86_64)
+
+ #define compat_elf_check_arch(x) elf_check_arch_ia32(x)
+@@ -169,24 +170,30 @@ static inline void elf_common_init(struct thread_struct *t,
+ t->ds = t->es = ds;
+ }
+
+-#define ELF_PLAT_INIT(_r, load_addr) do { \
+- elf_common_init(¤t->thread, _r, 0); \
+- clear_thread_flag(TIF_IA32); \
++#define ELF_PLAT_INIT(_r, load_addr) \
++do { \
++ elf_common_init(¤t->thread, _r, 0); \
++ clear_thread_flag(TIF_IA32); \
+ } while (0)
+
+-#define COMPAT_ELF_PLAT_INIT(regs, load_addr) \
++#define COMPAT_ELF_PLAT_INIT(regs, load_addr) \
+ elf_common_init(¤t->thread, regs, __USER_DS)
+-#define compat_start_thread(regs, ip, sp) do { \
+- start_ia32_thread(regs, ip, sp); \
+- set_fs(USER_DS); \
+- } while (0)
+-#define COMPAT_SET_PERSONALITY(ex, ibcs2) do { \
+- if (test_thread_flag(TIF_IA32)) \
+- clear_thread_flag(TIF_ABI_PENDING); \
+- else \
+- set_thread_flag(TIF_ABI_PENDING); \
+- current->personality |= force_personality32; \
+- } while (0)
++
++#define compat_start_thread(regs, ip, sp) \
++do { \
++ start_ia32_thread(regs, ip, sp); \
++ set_fs(USER_DS); \
++} while (0)
++
++#define COMPAT_SET_PERSONALITY(ex, ibcs2) \
++do { \
++ if (test_thread_flag(TIF_IA32)) \
++ clear_thread_flag(TIF_ABI_PENDING); \
++ else \
++ set_thread_flag(TIF_ABI_PENDING); \
++ current->personality |= force_personality32; \
++} while (0)
++
+ #define COMPAT_ELF_PLATFORM ("i686")
+
+ /*
+@@ -195,7 +202,8 @@ static inline void elf_common_init(struct thread_struct *t,
+ * getting dumped.
+ */
+
+-#define ELF_CORE_COPY_REGS(pr_reg, regs) do { \
++#define ELF_CORE_COPY_REGS(pr_reg, regs) \
++do { \
+ unsigned v; \
+ (pr_reg)[0] = (regs)->r15; \
+ (pr_reg)[1] = (regs)->r14; \
+@@ -269,10 +277,12 @@ extern int force_personality32;
+
+ struct task_struct;
+
+-#define ARCH_DLINFO_IA32(vdso_enabled) \
+-do if (vdso_enabled) { \
++#define ARCH_DLINFO_IA32(vdso_enabled) \
++do { \
++ if (vdso_enabled) { \
+ NEW_AUX_ENT(AT_SYSINFO, VDSO_ENTRY); \
+ NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_CURRENT_BASE); \
++ } \
+ } while (0)
+
+ #ifdef CONFIG_X86_32
+@@ -290,9 +300,11 @@ do if (vdso_enabled) { \
+ /* 1GB for 64bit, 8MB for 32bit */
+ #define STACK_RND_MASK (test_thread_flag(TIF_IA32) ? 0x7ff : 0x3fffff)
+
+-#define ARCH_DLINFO \
+-do if (vdso_enabled) { \
+- NEW_AUX_ENT(AT_SYSINFO_EHDR,(unsigned long)current->mm->context.vdso);\
++#define ARCH_DLINFO \
++do { \
++ if (vdso_enabled) \
++ NEW_AUX_ENT(AT_SYSINFO_EHDR, \
++ (unsigned long)current->mm->context.vdso); \
+ } while (0)
+
+ #define AT_SYSINFO 32
+@@ -305,8 +317,8 @@ do if (vdso_enabled) { \
+
+ #define VDSO_CURRENT_BASE ((unsigned long)current->mm->context.vdso)
+
+-#define VDSO_ENTRY \
+- ((unsigned long) VDSO32_SYMBOL(VDSO_CURRENT_BASE, vsyscall))
++#define VDSO_ENTRY \
++ ((unsigned long)VDSO32_SYMBOL(VDSO_CURRENT_BASE, vsyscall))
+
+ struct linux_binprm;
+
+diff --git a/include/asm-x86/fixmap.h b/include/asm-x86/fixmap.h
+index 382eb27..5bd2069 100644
+--- a/include/asm-x86/fixmap.h
++++ b/include/asm-x86/fixmap.h
+@@ -1,5 +1,13 @@
++#ifndef _ASM_FIXMAP_H
++#define _ASM_FIXMAP_H
++
+ #ifdef CONFIG_X86_32
+ # include "fixmap_32.h"
+ #else
+ # include "fixmap_64.h"
+ #endif
++
++#define clear_fixmap(idx) \
++ __set_fixmap(idx, 0, __pgprot(0))
++
++#endif
+diff --git a/include/asm-x86/fixmap_32.h b/include/asm-x86/fixmap_32.h
+index a7404d5..4b96148 100644
+--- a/include/asm-x86/fixmap_32.h
++++ b/include/asm-x86/fixmap_32.h
+@@ -10,8 +10,8 @@
+ * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
+ */
+
+-#ifndef _ASM_FIXMAP_H
+-#define _ASM_FIXMAP_H
++#ifndef _ASM_FIXMAP_32_H
++#define _ASM_FIXMAP_32_H
+
+
+ /* used by vmalloc.c, vsyscall.lds.S.
+@@ -99,8 +99,7 @@ enum fixed_addresses {
+ */
+ #define NR_FIX_BTMAPS 64
+ #define FIX_BTMAPS_NESTING 4
+- FIX_BTMAP_END =
+- __end_of_permanent_fixed_addresses + 512 -
++ FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 512 -
+ (__end_of_permanent_fixed_addresses & 511),
+ FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_NESTING - 1,
+ FIX_WP_TEST,
+@@ -110,20 +109,17 @@ enum fixed_addresses {
+ __end_of_fixed_addresses
+ };
+
+-extern void __set_fixmap (enum fixed_addresses idx,
+- unsigned long phys, pgprot_t flags);
++extern void __set_fixmap(enum fixed_addresses idx,
++ unsigned long phys, pgprot_t flags);
+ extern void reserve_top_address(unsigned long reserve);
+
+-#define set_fixmap(idx, phys) \
+- __set_fixmap(idx, phys, PAGE_KERNEL)
++#define set_fixmap(idx, phys) \
++ __set_fixmap(idx, phys, PAGE_KERNEL)
+ /*
+ * Some hardware wants to get fixmapped without caching.
+ */
+-#define set_fixmap_nocache(idx, phys) \
+- __set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
+-
+-#define clear_fixmap(idx) \
+- __set_fixmap(idx, 0, __pgprot(0))
++#define set_fixmap_nocache(idx, phys) \
++ __set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
+
+ #define FIXADDR_TOP ((unsigned long)__FIXADDR_TOP)
+
+@@ -156,7 +152,7 @@ static __always_inline unsigned long fix_to_virt(const unsigned int idx)
+ if (idx >= __end_of_fixed_addresses)
+ __this_fixmap_does_not_exist();
+
+- return __fix_to_virt(idx);
++ return __fix_to_virt(idx);
+ }
+
+ static inline unsigned long virt_to_fix(const unsigned long vaddr)
+diff --git a/include/asm-x86/fixmap_64.h b/include/asm-x86/fixmap_64.h
+index 70ddb21..355d26a 100644
+--- a/include/asm-x86/fixmap_64.h
++++ b/include/asm-x86/fixmap_64.h
+@@ -8,8 +8,8 @@
+ * Copyright (C) 1998 Ingo Molnar
+ */
+
+-#ifndef _ASM_FIXMAP_H
+-#define _ASM_FIXMAP_H
++#ifndef _ASM_FIXMAP_64_H
++#define _ASM_FIXMAP_64_H
+
+ #include <linux/kernel.h>
+ #include <asm/apicdef.h>
+@@ -34,32 +34,34 @@
+
+ enum fixed_addresses {
+ VSYSCALL_LAST_PAGE,
+- VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
++ VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE
++ + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
+ VSYSCALL_HPET,
+ FIX_DBGP_BASE,
+ FIX_EARLYCON_MEM_BASE,
+ FIX_HPET_BASE,
+ FIX_APIC_BASE, /* local (CPU) APIC) -- required for SMP or not */
+ FIX_IO_APIC_BASE_0,
+- FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1,
++ FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS - 1,
+ FIX_EFI_IO_MAP_LAST_PAGE,
+- FIX_EFI_IO_MAP_FIRST_PAGE = FIX_EFI_IO_MAP_LAST_PAGE+MAX_EFI_IO_PAGES-1,
++ FIX_EFI_IO_MAP_FIRST_PAGE = FIX_EFI_IO_MAP_LAST_PAGE
++ + MAX_EFI_IO_PAGES - 1,
+ #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
+ FIX_OHCI1394_BASE,
+ #endif
+ __end_of_fixed_addresses
+ };
+
+-extern void __set_fixmap (enum fixed_addresses idx,
+- unsigned long phys, pgprot_t flags);
++extern void __set_fixmap(enum fixed_addresses idx,
++ unsigned long phys, pgprot_t flags);
+
+-#define set_fixmap(idx, phys) \
+- __set_fixmap(idx, phys, PAGE_KERNEL)
++#define set_fixmap(idx, phys) \
++ __set_fixmap(idx, phys, PAGE_KERNEL)
+ /*
+ * Some hardware wants to get fixmapped without caching.
+ */
+-#define set_fixmap_nocache(idx, phys) \
+- __set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
++#define set_fixmap_nocache(idx, phys) \
++ __set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
+
+ #define FIXADDR_TOP (VSYSCALL_END-PAGE_SIZE)
+ #define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
+diff --git a/include/asm-x86/floppy.h b/include/asm-x86/floppy.h
+index a48d715..dbe82a5 100644
+--- a/include/asm-x86/floppy.h
++++ b/include/asm-x86/floppy.h
+@@ -20,20 +20,21 @@
+ * driver otherwise. It doesn't matter much for performance anyway, as most
+ * floppy accesses go through the track buffer.
+ */
+-#define _CROSS_64KB(a,s,vdma) \
+-(!(vdma) && ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64))
++#define _CROSS_64KB(a, s, vdma) \
++ (!(vdma) && \
++ ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64))
+
+-#define CROSS_64KB(a,s) _CROSS_64KB(a,s,use_virtual_dma & 1)
++#define CROSS_64KB(a, s) _CROSS_64KB(a, s, use_virtual_dma & 1)
+
+
+-#define SW fd_routine[use_virtual_dma&1]
++#define SW fd_routine[use_virtual_dma & 1]
+ #define CSW fd_routine[can_use_virtual_dma & 1]
+
+
+ #define fd_inb(port) inb_p(port)
+-#define fd_outb(value,port) outb_p(value,port)
++#define fd_outb(value, port) outb_p(value, port)
+
+-#define fd_request_dma() CSW._request_dma(FLOPPY_DMA,"floppy")
++#define fd_request_dma() CSW._request_dma(FLOPPY_DMA, "floppy")
+ #define fd_free_dma() CSW._free_dma(FLOPPY_DMA)
+ #define fd_enable_irq() enable_irq(FLOPPY_IRQ)
+ #define fd_disable_irq() disable_irq(FLOPPY_IRQ)
+@@ -52,64 +53,64 @@ static int doing_pdma;
+
+ static irqreturn_t floppy_hardint(int irq, void *dev_id)
+ {
+- register unsigned char st;
++ unsigned char st;
+
+ #undef TRACE_FLPY_INT
+
+ #ifdef TRACE_FLPY_INT
+- static int calls=0;
+- static int bytes=0;
+- static int dma_wait=0;
++ static int calls;
++ static int bytes;
++ static int dma_wait;
+ #endif
+ if (!doing_pdma)
+ return floppy_interrupt(irq, dev_id);
+
+ #ifdef TRACE_FLPY_INT
+- if(!calls)
++ if (!calls)
+ bytes = virtual_dma_count;
+ #endif
+
+ {
+- register int lcount;
+- register char *lptr;
++ int lcount;
++ char *lptr;
+
+ st = 1;
+- for(lcount=virtual_dma_count, lptr=virtual_dma_addr;
+- lcount; lcount--, lptr++) {
+- st=inb(virtual_dma_port+4) & 0xa0 ;
+- if(st != 0xa0)
++ for (lcount = virtual_dma_count, lptr = virtual_dma_addr;
++ lcount; lcount--, lptr++) {
++ st = inb(virtual_dma_port + 4) & 0xa0;
++ if (st != 0xa0)
+ break;
+- if(virtual_dma_mode)
+- outb_p(*lptr, virtual_dma_port+5);
++ if (virtual_dma_mode)
++ outb_p(*lptr, virtual_dma_port + 5);
+ else
+- *lptr = inb_p(virtual_dma_port+5);
++ *lptr = inb_p(virtual_dma_port + 5);
+ }
+ virtual_dma_count = lcount;
+ virtual_dma_addr = lptr;
+- st = inb(virtual_dma_port+4);
++ st = inb(virtual_dma_port + 4);
+ }
+
+ #ifdef TRACE_FLPY_INT
+ calls++;
+ #endif
+- if(st == 0x20)
++ if (st == 0x20)
+ return IRQ_HANDLED;
+- if(!(st & 0x20)) {
++ if (!(st & 0x20)) {
+ virtual_dma_residue += virtual_dma_count;
+- virtual_dma_count=0;
++ virtual_dma_count = 0;
+ #ifdef TRACE_FLPY_INT
+ printk("count=%x, residue=%x calls=%d bytes=%d dma_wait=%d\n",
+ virtual_dma_count, virtual_dma_residue, calls, bytes,
+ dma_wait);
+ calls = 0;
+- dma_wait=0;
++ dma_wait = 0;
+ #endif
+ doing_pdma = 0;
+ floppy_interrupt(irq, dev_id);
+ return IRQ_HANDLED;
+ }
+ #ifdef TRACE_FLPY_INT
+- if(!virtual_dma_count)
++ if (!virtual_dma_count)
+ dma_wait++;
+ #endif
+ return IRQ_HANDLED;
+@@ -117,14 +118,14 @@ static irqreturn_t floppy_hardint(int irq, void *dev_id)
+
+ static void fd_disable_dma(void)
+ {
+- if(! (can_use_virtual_dma & 1))
++ if (!(can_use_virtual_dma & 1))
+ disable_dma(FLOPPY_DMA);
+ doing_pdma = 0;
+ virtual_dma_residue += virtual_dma_count;
+- virtual_dma_count=0;
++ virtual_dma_count = 0;
+ }
+
+-static int vdma_request_dma(unsigned int dmanr, const char * device_id)
++static int vdma_request_dma(unsigned int dmanr, const char *device_id)
+ {
+ return 0;
+ }
+@@ -142,7 +143,7 @@ static int vdma_get_dma_residue(unsigned int dummy)
+
+ static int fd_request_irq(void)
+ {
+- if(can_use_virtual_dma)
++ if (can_use_virtual_dma)
+ return request_irq(FLOPPY_IRQ, floppy_hardint,
+ IRQF_DISABLED, "floppy", NULL);
+ else
+@@ -152,13 +153,13 @@ static int fd_request_irq(void)
+
+ static unsigned long dma_mem_alloc(unsigned long size)
+ {
+- return __get_dma_pages(GFP_KERNEL|__GFP_NORETRY,get_order(size));
++ return __get_dma_pages(GFP_KERNEL|__GFP_NORETRY, get_order(size));
+ }
+
+
+ static unsigned long vdma_mem_alloc(unsigned long size)
+ {
+- return (unsigned long) vmalloc(size);
++ return (unsigned long)vmalloc(size);
+
+ }
+
+@@ -166,7 +167,7 @@ static unsigned long vdma_mem_alloc(unsigned long size)
+
+ static void _fd_dma_mem_free(unsigned long addr, unsigned long size)
+ {
+- if((unsigned long) addr >= (unsigned long) high_memory)
++ if ((unsigned long)addr >= (unsigned long)high_memory)
+ vfree((void *)addr);
+ else
+ free_pages(addr, get_order(size));
+@@ -176,10 +177,10 @@ static void _fd_dma_mem_free(unsigned long addr, unsigned long size)
+
+ static void _fd_chose_dma_mode(char *addr, unsigned long size)
+ {
+- if(can_use_virtual_dma == 2) {
+- if((unsigned long) addr >= (unsigned long) high_memory ||
+- isa_virt_to_bus(addr) >= 0x1000000 ||
+- _CROSS_64KB(addr, size, 0))
++ if (can_use_virtual_dma == 2) {
++ if ((unsigned long)addr >= (unsigned long)high_memory ||
++ isa_virt_to_bus(addr) >= 0x1000000 ||
++ _CROSS_64KB(addr, size, 0))
+ use_virtual_dma = 1;
+ else
+ use_virtual_dma = 0;
+@@ -195,7 +196,7 @@ static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io)
+ {
+ doing_pdma = 1;
+ virtual_dma_port = io;
+- virtual_dma_mode = (mode == DMA_MODE_WRITE);
++ virtual_dma_mode = (mode == DMA_MODE_WRITE);
+ virtual_dma_addr = addr;
+ virtual_dma_count = size;
+ virtual_dma_residue = 0;
+@@ -213,18 +214,18 @@ static int hard_dma_setup(char *addr, unsigned long size, int mode, int io)
+ /* actual, physical DMA */
+ doing_pdma = 0;
+ clear_dma_ff(FLOPPY_DMA);
+- set_dma_mode(FLOPPY_DMA,mode);
+- set_dma_addr(FLOPPY_DMA,isa_virt_to_bus(addr));
+- set_dma_count(FLOPPY_DMA,size);
++ set_dma_mode(FLOPPY_DMA, mode);
++ set_dma_addr(FLOPPY_DMA, isa_virt_to_bus(addr));
++ set_dma_count(FLOPPY_DMA, size);
+ enable_dma(FLOPPY_DMA);
+ return 0;
+ }
+
+ static struct fd_routine_l {
+- int (*_request_dma)(unsigned int dmanr, const char * device_id);
++ int (*_request_dma)(unsigned int dmanr, const char *device_id);
+ void (*_free_dma)(unsigned int dmanr);
+ int (*_get_dma_residue)(unsigned int dummy);
+- unsigned long (*_dma_mem_alloc) (unsigned long size);
++ unsigned long (*_dma_mem_alloc)(unsigned long size);
+ int (*_dma_setup)(char *addr, unsigned long size, int mode, int io);
+ } fd_routine[] = {
+ {
+@@ -252,7 +253,8 @@ static int FDC2 = -1;
+ * is needed to prevent corrupted CMOS RAM in case "insmod floppy"
+ * coincides with another rtc CMOS user. Paul G.
+ */
+-#define FLOPPY0_TYPE ({ \
++#define FLOPPY0_TYPE \
++({ \
+ unsigned long flags; \
+ unsigned char val; \
+ spin_lock_irqsave(&rtc_lock, flags); \
+@@ -261,7 +263,8 @@ static int FDC2 = -1;
+ val; \
+ })
+
+-#define FLOPPY1_TYPE ({ \
++#define FLOPPY1_TYPE \
++({ \
+ unsigned long flags; \
+ unsigned char val; \
+ spin_lock_irqsave(&rtc_lock, flags); \
+diff --git a/include/asm-x86/futex.h b/include/asm-x86/futex.h
+index c9952ea..ac0fbf2 100644
+--- a/include/asm-x86/futex.h
++++ b/include/asm-x86/futex.h
+@@ -12,35 +12,32 @@
+ #include <asm/uaccess.h>
+
+ #define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg) \
+- __asm__ __volatile( \
+-"1: " insn "\n" \
+-"2: .section .fixup,\"ax\"\n \
+-3: mov %3, %1\n \
+- jmp 2b\n \
+- .previous\n" \
+- _ASM_EXTABLE(1b,3b) \
+- : "=r" (oldval), "=r" (ret), "+m" (*uaddr) \
+- : "i" (-EFAULT), "0" (oparg), "1" (0))
++ asm volatile("1:\t" insn "\n" \
++ "2:\t.section .fixup,\"ax\"\n" \
++ "3:\tmov\t%3, %1\n" \
++ "\tjmp\t2b\n" \
++ "\t.previous\n" \
++ _ASM_EXTABLE(1b, 3b) \
++ : "=r" (oldval), "=r" (ret), "+m" (*uaddr) \
++ : "i" (-EFAULT), "0" (oparg), "1" (0))
+
+ #define __futex_atomic_op2(insn, ret, oldval, uaddr, oparg) \
+- __asm__ __volatile( \
+-"1: movl %2, %0\n \
+- movl %0, %3\n" \
+- insn "\n" \
+-"2: lock; cmpxchgl %3, %2\n \
+- jnz 1b\n \
+-3: .section .fixup,\"ax\"\n \
+-4: mov %5, %1\n \
+- jmp 3b\n \
+- .previous\n" \
+- _ASM_EXTABLE(1b,4b) \
+- _ASM_EXTABLE(2b,4b) \
+- : "=&a" (oldval), "=&r" (ret), "+m" (*uaddr), \
+- "=&r" (tem) \
+- : "r" (oparg), "i" (-EFAULT), "1" (0))
+-
+-static inline int
+-futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
++ asm volatile("1:\tmovl %2, %0\n" \
++ "\tmovl\t%0, %3\n" \
++ "\t" insn "\n" \
++ "2:\tlock; cmpxchgl %3, %2\n" \
++ "\tjnz\t1b\n" \
++ "3:\t.section .fixup,\"ax\"\n" \
++ "4:\tmov\t%5, %1\n" \
++ "\tjmp\t3b\n" \
++ "\t.previous\n" \
++ _ASM_EXTABLE(1b, 4b) \
++ _ASM_EXTABLE(2b, 4b) \
++ : "=&a" (oldval), "=&r" (ret), \
++ "+m" (*uaddr), "=&r" (tem) \
++ : "r" (oparg), "i" (-EFAULT), "1" (0))
++
++static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+ {
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+@@ -87,20 +84,33 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+
+ if (!ret) {
+ switch (cmp) {
+- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+- default: ret = -ENOSYS;
++ case FUTEX_OP_CMP_EQ:
++ ret = (oldval == cmparg);
++ break;
++ case FUTEX_OP_CMP_NE:
++ ret = (oldval != cmparg);
++ break;
++ case FUTEX_OP_CMP_LT:
++ ret = (oldval < cmparg);
++ break;
++ case FUTEX_OP_CMP_GE:
++ ret = (oldval >= cmparg);
++ break;
++ case FUTEX_OP_CMP_LE:
++ ret = (oldval <= cmparg);
++ break;
++ case FUTEX_OP_CMP_GT:
++ ret = (oldval > cmparg);
++ break;
++ default:
++ ret = -ENOSYS;
+ }
+ }
+ return ret;
+ }
+
+-static inline int
+-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
++static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
++ int newval)
+ {
+
+ #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_BSWAP)
+@@ -112,16 +122,15 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+ return -EFAULT;
+
+- __asm__ __volatile__(
+- "1: lock; cmpxchgl %3, %1 \n"
+- "2: .section .fixup, \"ax\" \n"
+- "3: mov %2, %0 \n"
+- " jmp 2b \n"
+- " .previous \n"
+- _ASM_EXTABLE(1b,3b)
+- : "=a" (oldval), "+m" (*uaddr)
+- : "i" (-EFAULT), "r" (newval), "0" (oldval)
+- : "memory"
++ asm volatile("1:\tlock; cmpxchgl %3, %1\n"
++ "2:\t.section .fixup, \"ax\"\n"
++ "3:\tmov %2, %0\n"
++ "\tjmp 2b\n"
++ "\t.previous\n"
++ _ASM_EXTABLE(1b, 3b)
++ : "=a" (oldval), "+m" (*uaddr)
++ : "i" (-EFAULT), "r" (newval), "0" (oldval)
++ : "memory"
+ );
+
+ return oldval;
+diff --git a/include/asm-x86/genapic_32.h b/include/asm-x86/genapic_32.h
+index 33e3ffe..b02ea6e 100644
+--- a/include/asm-x86/genapic_32.h
++++ b/include/asm-x86/genapic_32.h
+@@ -14,23 +14,22 @@
+ * Copyright 2003 Andi Kleen, SuSE Labs.
+ */
+
+-struct mpc_config_translation;
+ struct mpc_config_bus;
+ struct mp_config_table;
+ struct mpc_config_processor;
+
+-struct genapic {
+- char *name;
+- int (*probe)(void);
++struct genapic {
++ char *name;
++ int (*probe)(void);
+
+ int (*apic_id_registered)(void);
+ cpumask_t (*target_cpus)(void);
+ int int_delivery_mode;
+- int int_dest_mode;
++ int int_dest_mode;
+ int ESR_DISABLE;
+ int apic_destination_logical;
+ unsigned long (*check_apicid_used)(physid_mask_t bitmap, int apicid);
+- unsigned long (*check_apicid_present)(int apicid);
++ unsigned long (*check_apicid_present)(int apicid);
+ int no_balance_irq;
+ int no_ioapic_check;
+ void (*init_apic_ldr)(void);
+@@ -38,28 +37,21 @@ struct genapic {
+
+ void (*setup_apic_routing)(void);
+ int (*multi_timer_check)(int apic, int irq);
+- int (*apicid_to_node)(int logical_apicid);
++ int (*apicid_to_node)(int logical_apicid);
+ int (*cpu_to_logical_apicid)(int cpu);
+ int (*cpu_present_to_apicid)(int mps_cpu);
+ physid_mask_t (*apicid_to_cpu_present)(int phys_apicid);
+- int (*mpc_apic_id)(struct mpc_config_processor *m,
+- struct mpc_config_translation *t);
+- void (*setup_portio_remap)(void);
++ void (*setup_portio_remap)(void);
+ int (*check_phys_apicid_present)(int boot_cpu_physical_apicid);
+ void (*enable_apic_mode)(void);
+ u32 (*phys_pkg_id)(u32 cpuid_apic, int index_msb);
+
+ /* mpparse */
+- void (*mpc_oem_bus_info)(struct mpc_config_bus *, char *,
+- struct mpc_config_translation *);
+- void (*mpc_oem_pci_bus)(struct mpc_config_bus *,
+- struct mpc_config_translation *);
+-
+ /* When one of the next two hooks returns 1 the genapic
+- is switched to this. Essentially they are additional probe
++ is switched to this. Essentially they are additional probe
+ functions. */
+- int (*mps_oem_check)(struct mp_config_table *mpc, char *oem,
+- char *productid);
++ int (*mps_oem_check)(struct mp_config_table *mpc, char *oem,
++ char *productid);
+ int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id);
+
+ unsigned (*get_apic_id)(unsigned long x);
+@@ -72,7 +64,7 @@ struct genapic {
+ void (*send_IPI_allbutself)(int vector);
+ void (*send_IPI_all)(int vector);
+ #endif
+-};
++};
+
+ #define APICFUNC(x) .x = x,
+
+@@ -85,43 +77,47 @@ struct genapic {
+ #define IPIFUNC(x)
+ #endif
+
+-#define APIC_INIT(aname, aprobe) { \
+- .name = aname, \
+- .probe = aprobe, \
+- .int_delivery_mode = INT_DELIVERY_MODE, \
+- .int_dest_mode = INT_DEST_MODE, \
+- .no_balance_irq = NO_BALANCE_IRQ, \
+- .ESR_DISABLE = esr_disable, \
+- .apic_destination_logical = APIC_DEST_LOGICAL, \
+- APICFUNC(apic_id_registered) \
+- APICFUNC(target_cpus) \
+- APICFUNC(check_apicid_used) \
+- APICFUNC(check_apicid_present) \
+- APICFUNC(init_apic_ldr) \
+- APICFUNC(ioapic_phys_id_map) \
+- APICFUNC(setup_apic_routing) \
+- APICFUNC(multi_timer_check) \
+- APICFUNC(apicid_to_node) \
+- APICFUNC(cpu_to_logical_apicid) \
+- APICFUNC(cpu_present_to_apicid) \
+- APICFUNC(apicid_to_cpu_present) \
+- APICFUNC(mpc_apic_id) \
+- APICFUNC(setup_portio_remap) \
+- APICFUNC(check_phys_apicid_present) \
+- APICFUNC(mpc_oem_bus_info) \
+- APICFUNC(mpc_oem_pci_bus) \
+- APICFUNC(mps_oem_check) \
+- APICFUNC(get_apic_id) \
+- .apic_id_mask = APIC_ID_MASK, \
+- APICFUNC(cpu_mask_to_apicid) \
+- APICFUNC(acpi_madt_oem_check) \
+- IPIFUNC(send_IPI_mask) \
+- IPIFUNC(send_IPI_allbutself) \
+- IPIFUNC(send_IPI_all) \
+- APICFUNC(enable_apic_mode) \
+- APICFUNC(phys_pkg_id) \
+- }
++#define APIC_INIT(aname, aprobe) \
++{ \
++ .name = aname, \
++ .probe = aprobe, \
++ .int_delivery_mode = INT_DELIVERY_MODE, \
++ .int_dest_mode = INT_DEST_MODE, \
++ .no_balance_irq = NO_BALANCE_IRQ, \
++ .ESR_DISABLE = esr_disable, \
++ .apic_destination_logical = APIC_DEST_LOGICAL, \
++ APICFUNC(apic_id_registered) \
++ APICFUNC(target_cpus) \
++ APICFUNC(check_apicid_used) \
++ APICFUNC(check_apicid_present) \
++ APICFUNC(init_apic_ldr) \
++ APICFUNC(ioapic_phys_id_map) \
++ APICFUNC(setup_apic_routing) \
++ APICFUNC(multi_timer_check) \
++ APICFUNC(apicid_to_node) \
++ APICFUNC(cpu_to_logical_apicid) \
++ APICFUNC(cpu_present_to_apicid) \
++ APICFUNC(apicid_to_cpu_present) \
++ APICFUNC(setup_portio_remap) \
++ APICFUNC(check_phys_apicid_present) \
++ APICFUNC(mps_oem_check) \
++ APICFUNC(get_apic_id) \
++ .apic_id_mask = APIC_ID_MASK, \
++ APICFUNC(cpu_mask_to_apicid) \
++ APICFUNC(acpi_madt_oem_check) \
++ IPIFUNC(send_IPI_mask) \
++ IPIFUNC(send_IPI_allbutself) \
++ IPIFUNC(send_IPI_all) \
++ APICFUNC(enable_apic_mode) \
++ APICFUNC(phys_pkg_id) \
++}
+
+ extern struct genapic *genapic;
+
++enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC};
++#define get_uv_system_type() UV_NONE
++#define is_uv_system() 0
++#define uv_wakeup_secondary(a, b) 1
++
++
+ #endif
+diff --git a/include/asm-x86/genapic_64.h b/include/asm-x86/genapic_64.h
+index d7e516c..1de931b 100644
+--- a/include/asm-x86/genapic_64.h
++++ b/include/asm-x86/genapic_64.h
+@@ -33,5 +33,15 @@ extern struct genapic *genapic;
+
+ extern struct genapic apic_flat;
+ extern struct genapic apic_physflat;
++extern int acpi_madt_oem_check(char *, char *);
++
++enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC};
++extern enum uv_system_type get_uv_system_type(void);
++extern int is_uv_system(void);
++
++extern struct genapic apic_x2apic_uv_x;
++DECLARE_PER_CPU(int, x2apic_extra_bits);
++extern void uv_cpu_init(void);
++extern int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip);
+
+ #endif
+diff --git a/include/asm-x86/geode.h b/include/asm-x86/geode.h
+index 9e72800..9870cc1 100644
+--- a/include/asm-x86/geode.h
++++ b/include/asm-x86/geode.h
+@@ -167,7 +167,7 @@ static inline int is_geode(void)
+ /* MFGPTs */
+
+ #define MFGPT_MAX_TIMERS 8
+-#define MFGPT_TIMER_ANY -1
++#define MFGPT_TIMER_ANY (-1)
+
+ #define MFGPT_DOMAIN_WORKING 1
+ #define MFGPT_DOMAIN_STANDBY 2
+diff --git a/include/asm-x86/highmem.h b/include/asm-x86/highmem.h
+index 479767c..e153f3b 100644
+--- a/include/asm-x86/highmem.h
++++ b/include/asm-x86/highmem.h
+@@ -8,7 +8,7 @@
+ * Gerhard.Wichert at pdb.siemens.de
+ *
+ *
+- * Redesigned the x86 32-bit VM architecture to deal with
++ * Redesigned the x86 32-bit VM architecture to deal with
+ * up to 16 Terabyte physical memory. With current x86 CPUs
+ * we now support up to 64 Gigabytes physical RAM.
+ *
+diff --git a/include/asm-x86/hw_irq_64.h b/include/asm-x86/hw_irq_64.h
+index 312a58d..0062ef3 100644
+--- a/include/asm-x86/hw_irq_64.h
++++ b/include/asm-x86/hw_irq_64.h
+@@ -36,7 +36,7 @@
+ * cleanup after irq migration.
+ */
+ #define IRQ_MOVE_CLEANUP_VECTOR FIRST_EXTERNAL_VECTOR
+-
++
+ /*
+ * Vectors 0x30-0x3f are used for ISA interrupts.
+ */
+@@ -159,13 +159,12 @@ extern atomic_t irq_mis_count;
+ * SMP has a few special interrupts for IPI messages
+ */
+
+-#define BUILD_IRQ(nr) \
+-asmlinkage void IRQ_NAME(nr); \
+-__asm__( \
+-"\n.p2align\n" \
+-"IRQ" #nr "_interrupt:\n\t" \
+- "push $~(" #nr ") ; " \
+- "jmp common_interrupt");
++#define BUILD_IRQ(nr) \
++ asmlinkage void IRQ_NAME(nr); \
++ asm("\n.p2align\n" \
++ "IRQ" #nr "_interrupt:\n\t" \
++ "push $~(" #nr ") ; " \
++ "jmp common_interrupt");
+
+ #define platform_legacy_irq(irq) ((irq) < 16)
+
+diff --git a/include/asm-x86/hypertransport.h b/include/asm-x86/hypertransport.h
+index c16c6ff..d2bbd23 100644
+--- a/include/asm-x86/hypertransport.h
++++ b/include/asm-x86/hypertransport.h
+@@ -8,12 +8,14 @@
+ #define HT_IRQ_LOW_BASE 0xf8000000
+
+ #define HT_IRQ_LOW_VECTOR_SHIFT 16
+-#define HT_IRQ_LOW_VECTOR_MASK 0x00ff0000
+-#define HT_IRQ_LOW_VECTOR(v) (((v) << HT_IRQ_LOW_VECTOR_SHIFT) & HT_IRQ_LOW_VECTOR_MASK)
++#define HT_IRQ_LOW_VECTOR_MASK 0x00ff0000
++#define HT_IRQ_LOW_VECTOR(v) \
++ (((v) << HT_IRQ_LOW_VECTOR_SHIFT) & HT_IRQ_LOW_VECTOR_MASK)
+
+ #define HT_IRQ_LOW_DEST_ID_SHIFT 8
+-#define HT_IRQ_LOW_DEST_ID_MASK 0x0000ff00
+-#define HT_IRQ_LOW_DEST_ID(v) (((v) << HT_IRQ_LOW_DEST_ID_SHIFT) & HT_IRQ_LOW_DEST_ID_MASK)
++#define HT_IRQ_LOW_DEST_ID_MASK 0x0000ff00
++#define HT_IRQ_LOW_DEST_ID(v) \
++ (((v) << HT_IRQ_LOW_DEST_ID_SHIFT) & HT_IRQ_LOW_DEST_ID_MASK)
+
+ #define HT_IRQ_LOW_DM_PHYSICAL 0x0000000
+ #define HT_IRQ_LOW_DM_LOGICAL 0x0000040
+@@ -36,7 +38,8 @@
+
+
+ #define HT_IRQ_HIGH_DEST_ID_SHIFT 0
+-#define HT_IRQ_HIGH_DEST_ID_MASK 0x00ffffff
+-#define HT_IRQ_HIGH_DEST_ID(v) ((((v) >> 8) << HT_IRQ_HIGH_DEST_ID_SHIFT) & HT_IRQ_HIGH_DEST_ID_MASK)
++#define HT_IRQ_HIGH_DEST_ID_MASK 0x00ffffff
++#define HT_IRQ_HIGH_DEST_ID(v) \
++ ((((v) >> 8) << HT_IRQ_HIGH_DEST_ID_SHIFT) & HT_IRQ_HIGH_DEST_ID_MASK)
+
+ #endif /* ASM_HYPERTRANSPORT_H */
+diff --git a/include/asm-x86/i387.h b/include/asm-x86/i387.h
+index f377b76..da2adb4 100644
+--- a/include/asm-x86/i387.h
++++ b/include/asm-x86/i387.h
+@@ -21,8 +21,9 @@
+
+ extern void fpu_init(void);
+ extern void mxcsr_feature_mask_init(void);
+-extern void init_fpu(struct task_struct *child);
++extern int init_fpu(struct task_struct *child);
+ extern asmlinkage void math_state_restore(void);
++extern void init_thread_xstate(void);
+
+ extern user_regset_active_fn fpregs_active, xfpregs_active;
+ extern user_regset_get_fn fpregs_get, xfpregs_get, fpregs_soft_get;
+@@ -41,7 +42,7 @@ static inline void tolerant_fwait(void)
+ {
+ asm volatile("1: fwait\n"
+ "2:\n"
+- _ASM_EXTABLE(1b,2b));
++ _ASM_EXTABLE(1b, 2b));
+ }
+
+ static inline int restore_fpu_checking(struct i387_fxsave_struct *fx)
+@@ -54,7 +55,7 @@ static inline int restore_fpu_checking(struct i387_fxsave_struct *fx)
+ "3: movl $-1,%[err]\n"
+ " jmp 2b\n"
+ ".previous\n"
+- _ASM_EXTABLE(1b,3b)
++ _ASM_EXTABLE(1b, 3b)
+ : [err] "=r" (err)
+ #if 0 /* See comment in __save_init_fpu() below. */
+ : [fx] "r" (fx), "m" (*fx), "0" (0));
+@@ -76,11 +77,11 @@ static inline int restore_fpu_checking(struct i387_fxsave_struct *fx)
+ static inline void clear_fpu_state(struct i387_fxsave_struct *fx)
+ {
+ if (unlikely(fx->swd & X87_FSW_ES))
+- asm volatile("fnclex");
++ asm volatile("fnclex");
+ alternative_input(ASM_NOP8 ASM_NOP2,
+- " emms\n" /* clear stack tags */
+- " fildl %%gs:0", /* load to clear state */
+- X86_FEATURE_FXSAVE_LEAK);
++ " emms\n" /* clear stack tags */
++ " fildl %%gs:0", /* load to clear state */
++ X86_FEATURE_FXSAVE_LEAK);
+ }
+
+ static inline int save_i387_checking(struct i387_fxsave_struct __user *fx)
+@@ -93,14 +94,15 @@ static inline int save_i387_checking(struct i387_fxsave_struct __user *fx)
+ "3: movl $-1,%[err]\n"
+ " jmp 2b\n"
+ ".previous\n"
+- _ASM_EXTABLE(1b,3b)
++ _ASM_EXTABLE(1b, 3b)
+ : [err] "=r" (err), "=m" (*fx)
+ #if 0 /* See comment in __fxsave_clear() below. */
+ : [fx] "r" (fx), "0" (0));
+ #else
+ : [fx] "cdaSDb" (fx), "0" (0));
+ #endif
+- if (unlikely(err) && __clear_user(fx, sizeof(struct i387_fxsave_struct)))
++ if (unlikely(err) &&
++ __clear_user(fx, sizeof(struct i387_fxsave_struct)))
+ err = -EFAULT;
+ /* No need to clear here because the caller clears USED_MATH */
+ return err;
+@@ -116,24 +118,22 @@ static inline void __save_init_fpu(struct task_struct *tsk)
+ /* Using "fxsaveq %0" would be the ideal choice, but is only supported
+ starting with gas 2.16. */
+ __asm__ __volatile__("fxsaveq %0"
+- : "=m" (tsk->thread.i387.fxsave));
++ : "=m" (tsk->thread.xstate->fxsave));
+ #elif 0
+ /* Using, as a workaround, the properly prefixed form below isn't
+ accepted by any binutils version so far released, complaining that
+ the same type of prefix is used twice if an extended register is
+ needed for addressing (fix submitted to mainline 2005-11-21). */
+ __asm__ __volatile__("rex64/fxsave %0"
+- : "=m" (tsk->thread.i387.fxsave));
++ : "=m" (tsk->thread.xstate->fxsave));
+ #else
+ /* This, however, we can work around by forcing the compiler to select
+ an addressing mode that doesn't require extended registers. */
+- __asm__ __volatile__("rex64/fxsave %P2(%1)"
+- : "=m" (tsk->thread.i387.fxsave)
+- : "cdaSDb" (tsk),
+- "i" (offsetof(__typeof__(*tsk),
+- thread.i387.fxsave)));
++ __asm__ __volatile__("rex64/fxsave (%1)"
++ : "=m" (tsk->thread.xstate->fxsave)
++ : "cdaSDb" (&tsk->thread.xstate->fxsave));
+ #endif
+- clear_fpu_state(&tsk->thread.i387.fxsave);
++ clear_fpu_state(&tsk->thread.xstate->fxsave);
+ task_thread_info(tsk)->status &= ~TS_USEDFPU;
+ }
+
+@@ -147,7 +147,7 @@ static inline int save_i387(struct _fpstate __user *buf)
+ int err = 0;
+
+ BUILD_BUG_ON(sizeof(struct user_i387_struct) !=
+- sizeof(tsk->thread.i387.fxsave));
++ sizeof(tsk->thread.xstate->fxsave));
+
+ if ((unsigned long)buf % 16)
+ printk("save_i387: bad fpstate %p\n", buf);
+@@ -156,12 +156,14 @@ static inline int save_i387(struct _fpstate __user *buf)
+ return 0;
+ clear_used_math(); /* trigger finit */
+ if (task_thread_info(tsk)->status & TS_USEDFPU) {
+- err = save_i387_checking((struct i387_fxsave_struct __user *)buf);
+- if (err) return err;
++ err = save_i387_checking((struct i387_fxsave_struct __user *)
++ buf);
++ if (err)
++ return err;
+ task_thread_info(tsk)->status &= ~TS_USEDFPU;
+ stts();
+ } else {
+- if (__copy_to_user(buf, &tsk->thread.i387.fxsave,
++ if (__copy_to_user(buf, &tsk->thread.xstate->fxsave,
+ sizeof(struct i387_fxsave_struct)))
+ return -1;
+ }
+@@ -198,7 +200,7 @@ static inline void restore_fpu(struct task_struct *tsk)
+ "nop ; frstor %1",
+ "fxrstor %1",
+ X86_FEATURE_FXSR,
+- "m" ((tsk)->thread.i387.fxsave));
++ "m" (tsk->thread.xstate->fxsave));
+ }
+
+ /* We need a safe address that is cheap to find and that is already
+@@ -222,8 +224,8 @@ static inline void __save_init_fpu(struct task_struct *tsk)
+ "fxsave %[fx]\n"
+ "bt $7,%[fsw] ; jnc 1f ; fnclex\n1:",
+ X86_FEATURE_FXSR,
+- [fx] "m" (tsk->thread.i387.fxsave),
+- [fsw] "m" (tsk->thread.i387.fxsave.swd) : "memory");
++ [fx] "m" (tsk->thread.xstate->fxsave),
++ [fsw] "m" (tsk->thread.xstate->fxsave.swd) : "memory");
+ /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
+ is pending. Clear the x87 state here by setting it to fixed
+ values. safe_address is a random variable that should be in L1 */
+@@ -324,25 +326,25 @@ static inline void clear_fpu(struct task_struct *tsk)
+ static inline unsigned short get_fpu_cwd(struct task_struct *tsk)
+ {
+ if (cpu_has_fxsr) {
+- return tsk->thread.i387.fxsave.cwd;
++ return tsk->thread.xstate->fxsave.cwd;
+ } else {
+- return (unsigned short)tsk->thread.i387.fsave.cwd;
++ return (unsigned short)tsk->thread.xstate->fsave.cwd;
+ }
+ }
+
+ static inline unsigned short get_fpu_swd(struct task_struct *tsk)
+ {
+ if (cpu_has_fxsr) {
+- return tsk->thread.i387.fxsave.swd;
++ return tsk->thread.xstate->fxsave.swd;
+ } else {
+- return (unsigned short)tsk->thread.i387.fsave.swd;
++ return (unsigned short)tsk->thread.xstate->fsave.swd;
+ }
+ }
+
+ static inline unsigned short get_fpu_mxcsr(struct task_struct *tsk)
+ {
+ if (cpu_has_xmm) {
+- return tsk->thread.i387.fxsave.mxcsr;
++ return tsk->thread.xstate->fxsave.mxcsr;
+ } else {
+ return MXCSR_DEFAULT;
+ }
+diff --git a/include/asm-x86/i8259.h b/include/asm-x86/i8259.h
+index 67c319e..45d4df3 100644
+--- a/include/asm-x86/i8259.h
++++ b/include/asm-x86/i8259.h
+@@ -1,9 +1,11 @@
+ #ifndef __ASM_I8259_H__
+ #define __ASM_I8259_H__
+
++#include <linux/delay.h>
++
+ extern unsigned int cached_irq_mask;
+
+-#define __byte(x,y) (((unsigned char *) &(y))[x])
++#define __byte(x, y) (((unsigned char *)&(y))[x])
+ #define cached_master_mask (__byte(0, cached_irq_mask))
+ #define cached_slave_mask (__byte(1, cached_irq_mask))
+
+@@ -29,7 +31,28 @@ extern void enable_8259A_irq(unsigned int irq);
+ extern void disable_8259A_irq(unsigned int irq);
+ extern unsigned int startup_8259A_irq(unsigned int irq);
+
+-#define inb_pic inb_p
+-#define outb_pic outb_p
++/* the PIC may need a careful delay on some platforms, hence specific calls */
++static inline unsigned char inb_pic(unsigned int port)
++{
++ unsigned char value = inb(port);
++
++ /*
++ * delay for some accesses to PIC on motherboard or in chipset
++ * must be at least one microsecond, so be safe here:
++ */
++ udelay(2);
++
++ return value;
++}
++
++static inline void outb_pic(unsigned char value, unsigned int port)
++{
++ outb(value, port);
++ /*
++ * delay for some accesses to PIC on motherboard or in chipset
++ * must be at least one microsecond, so be safe here:
++ */
++ udelay(2);
++}
+
+ #endif /* __ASM_I8259_H__ */
+diff --git a/include/asm-x86/ia32.h b/include/asm-x86/ia32.h
+index aa97332..55d3abe 100644
+--- a/include/asm-x86/ia32.h
++++ b/include/asm-x86/ia32.h
+@@ -14,19 +14,19 @@
+
+ /* signal.h */
+ struct sigaction32 {
+- unsigned int sa_handler; /* Really a pointer, but need to deal
+- with 32 bits */
+- unsigned int sa_flags;
+- unsigned int sa_restorer; /* Another 32 bit pointer */
+- compat_sigset_t sa_mask; /* A 32 bit mask */
++ unsigned int sa_handler; /* Really a pointer, but need to deal
++ with 32 bits */
++ unsigned int sa_flags;
++ unsigned int sa_restorer; /* Another 32 bit pointer */
++ compat_sigset_t sa_mask; /* A 32 bit mask */
+ };
+
+ struct old_sigaction32 {
+- unsigned int sa_handler; /* Really a pointer, but need to deal
+- with 32 bits */
+- compat_old_sigset_t sa_mask; /* A 32 bit mask */
+- unsigned int sa_flags;
+- unsigned int sa_restorer; /* Another 32 bit pointer */
++ unsigned int sa_handler; /* Really a pointer, but need to deal
++ with 32 bits */
++ compat_old_sigset_t sa_mask; /* A 32 bit mask */
++ unsigned int sa_flags;
++ unsigned int sa_restorer; /* Another 32 bit pointer */
+ };
+
+ typedef struct sigaltstack_ia32 {
+@@ -65,7 +65,7 @@ struct stat64 {
+ long long st_size;
+ unsigned int st_blksize;
+
+- long long st_blocks;/* Number 512-byte blocks allocated. */
++ long long st_blocks;/* Number 512-byte blocks allocated */
+
+ unsigned st_atime;
+ unsigned st_atime_nsec;
+@@ -77,13 +77,13 @@ struct stat64 {
+ unsigned long long st_ino;
+ } __attribute__((packed));
+
+-typedef struct compat_siginfo{
++typedef struct compat_siginfo {
+ int si_signo;
+ int si_errno;
+ int si_code;
+
+ union {
+- int _pad[((128/sizeof(int)) - 3)];
++ int _pad[((128 / sizeof(int)) - 3)];
+
+ /* kill() */
+ struct {
+@@ -129,28 +129,26 @@ typedef struct compat_siginfo{
+ } _sifields;
+ } compat_siginfo_t;
+
+-struct sigframe32
+-{
+- u32 pretcode;
+- int sig;
+- struct sigcontext_ia32 sc;
+- struct _fpstate_ia32 fpstate;
+- unsigned int extramask[_COMPAT_NSIG_WORDS-1];
++struct sigframe32 {
++ u32 pretcode;
++ int sig;
++ struct sigcontext_ia32 sc;
++ struct _fpstate_ia32 fpstate;
++ unsigned int extramask[_COMPAT_NSIG_WORDS-1];
+ };
+
+-struct rt_sigframe32
+-{
+- u32 pretcode;
+- int sig;
+- u32 pinfo;
+- u32 puc;
+- compat_siginfo_t info;
+- struct ucontext_ia32 uc;
+- struct _fpstate_ia32 fpstate;
++struct rt_sigframe32 {
++ u32 pretcode;
++ int sig;
++ u32 pinfo;
++ u32 puc;
++ compat_siginfo_t info;
++ struct ucontext_ia32 uc;
++ struct _fpstate_ia32 fpstate;
+ };
+
+ struct ustat32 {
+- __u32 f_tfree;
++ __u32 f_tfree;
+ compat_ino_t f_tinode;
+ char f_fname[6];
+ char f_fpack[6];
+@@ -168,5 +166,5 @@ extern void ia32_pick_mmap_layout(struct mm_struct *mm);
+ #endif
+
+ #endif /* !CONFIG_IA32_SUPPORT */
+-
+-#endif
++
++#endif
+diff --git a/include/asm-x86/ide.h b/include/asm-x86/ide.h
+index c2552d8..cf9c98e 100644
+--- a/include/asm-x86/ide.h
++++ b/include/asm-x86/ide.h
+@@ -20,8 +20,6 @@
+ # endif
+ #endif
+
+-#define IDE_ARCH_OBSOLETE_DEFAULTS
+-
+ static __inline__ int ide_default_irq(unsigned long base)
+ {
+ switch (base) {
+@@ -60,14 +58,6 @@ static __inline__ unsigned long ide_default_io_base(int index)
+ }
+ }
+
+-#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */
+-
+-#ifdef CONFIG_BLK_DEV_IDEPCI
+-#define ide_init_default_irq(base) (0)
+-#else
+-#define ide_init_default_irq(base) ide_default_irq(base)
+-#endif
+-
+ #include <asm-generic/ide_iops.h>
+
+ #endif /* __KERNEL__ */
+diff --git a/include/asm-x86/io.h b/include/asm-x86/io.h
+index 5a58b17..d5b11f6 100644
+--- a/include/asm-x86/io.h
++++ b/include/asm-x86/io.h
+@@ -1,5 +1,19 @@
++#ifndef _ASM_X86_IO_H
++#define _ASM_X86_IO_H
++
++#define ARCH_HAS_IOREMAP_WC
++
+ #ifdef CONFIG_X86_32
+ # include "io_32.h"
+ #else
+ # include "io_64.h"
+ #endif
++
++extern void *xlate_dev_mem_ptr(unsigned long phys);
++extern void unxlate_dev_mem_ptr(unsigned long phys, void *addr);
++
++extern int ioremap_change_attr(unsigned long vaddr, unsigned long size,
++ unsigned long prot_val);
++extern void __iomem *ioremap_wc(unsigned long offset, unsigned long size);
++
++#endif /* _ASM_X86_IO_H */
+diff --git a/include/asm-x86/io_32.h b/include/asm-x86/io_32.h
+index d4d8fbd..6e73467 100644
+--- a/include/asm-x86/io_32.h
++++ b/include/asm-x86/io_32.h
+@@ -49,12 +49,6 @@
+ #include <linux/vmalloc.h>
+
+ /*
+- * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+- * access
+- */
+-#define xlate_dev_mem_ptr(p) __va(p)
+-
+-/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+ #define xlate_dev_kmem_ptr(p) p
+@@ -65,14 +59,14 @@
+ *
+ * The returned physical address is the physical (CPU) mapping for
+ * the memory address given. It is only valid to use this function on
+- * addresses directly mapped or allocated via kmalloc.
++ * addresses directly mapped or allocated via kmalloc.
+ *
+ * This function does not give bus mappings for DMA transfers. In
+ * almost all conceivable cases a device driver should not be using
+ * this function
+ */
+-
+-static inline unsigned long virt_to_phys(volatile void * address)
++
++static inline unsigned long virt_to_phys(volatile void *address)
+ {
+ return __pa(address);
+ }
+@@ -90,7 +84,7 @@ static inline unsigned long virt_to_phys(volatile void * address)
+ * this function
+ */
+
+-static inline void * phys_to_virt(unsigned long address)
++static inline void *phys_to_virt(unsigned long address)
+ {
+ return __va(address);
+ }
+@@ -169,16 +163,19 @@ extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys);
+
+ static inline unsigned char readb(const volatile void __iomem *addr)
+ {
+- return *(volatile unsigned char __force *) addr;
++ return *(volatile unsigned char __force *)addr;
+ }
++
+ static inline unsigned short readw(const volatile void __iomem *addr)
+ {
+- return *(volatile unsigned short __force *) addr;
++ return *(volatile unsigned short __force *)addr;
+ }
++
+ static inline unsigned int readl(const volatile void __iomem *addr)
+ {
+ return *(volatile unsigned int __force *) addr;
+ }
++
+ #define readb_relaxed(addr) readb(addr)
+ #define readw_relaxed(addr) readw(addr)
+ #define readl_relaxed(addr) readl(addr)
+@@ -188,15 +185,17 @@ static inline unsigned int readl(const volatile void __iomem *addr)
+
+ static inline void writeb(unsigned char b, volatile void __iomem *addr)
+ {
+- *(volatile unsigned char __force *) addr = b;
++ *(volatile unsigned char __force *)addr = b;
+ }
++
+ static inline void writew(unsigned short b, volatile void __iomem *addr)
+ {
+- *(volatile unsigned short __force *) addr = b;
++ *(volatile unsigned short __force *)addr = b;
+ }
++
+ static inline void writel(unsigned int b, volatile void __iomem *addr)
+ {
+- *(volatile unsigned int __force *) addr = b;
++ *(volatile unsigned int __force *)addr = b;
+ }
+ #define __raw_writeb writeb
+ #define __raw_writew writew
+@@ -239,12 +238,12 @@ memcpy_toio(volatile void __iomem *dst, const void *src, int count)
+ * 1. Out of order aware processors
+ * 2. Accidentally out of order processors (PPro errata #51)
+ */
+-
++
+ #if defined(CONFIG_X86_OOSTORE) || defined(CONFIG_X86_PPRO_FENCE)
+
+ static inline void flush_write_buffers(void)
+ {
+- __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory");
++ asm volatile("lock; addl $0,0(%%esp)": : :"memory");
+ }
+
+ #else
+@@ -264,7 +263,8 @@ extern void io_delay_init(void);
+ #include <asm/paravirt.h>
+ #else
+
+-static inline void slow_down_io(void) {
++static inline void slow_down_io(void)
++{
+ native_io_delay();
+ #ifdef REALLY_SLOW_IO
+ native_io_delay();
+@@ -275,51 +275,74 @@ static inline void slow_down_io(void) {
+
+ #endif
+
+-#define __BUILDIO(bwl,bw,type) \
+-static inline void out##bwl(unsigned type value, int port) { \
+- out##bwl##_local(value, port); \
+-} \
+-static inline unsigned type in##bwl(int port) { \
+- return in##bwl##_local(port); \
++#define __BUILDIO(bwl, bw, type) \
++static inline void out##bwl(unsigned type value, int port) \
++{ \
++ out##bwl##_local(value, port); \
++} \
++ \
++static inline unsigned type in##bwl(int port) \
++{ \
++ return in##bwl##_local(port); \
+ }
+
+-#define BUILDIO(bwl,bw,type) \
+-static inline void out##bwl##_local(unsigned type value, int port) { \
+- __asm__ __volatile__("out" #bwl " %" #bw "0, %w1" : : "a"(value), "Nd"(port)); \
+-} \
+-static inline unsigned type in##bwl##_local(int port) { \
+- unsigned type value; \
+- __asm__ __volatile__("in" #bwl " %w1, %" #bw "0" : "=a"(value) : "Nd"(port)); \
+- return value; \
+-} \
+-static inline void out##bwl##_local_p(unsigned type value, int port) { \
+- out##bwl##_local(value, port); \
+- slow_down_io(); \
+-} \
+-static inline unsigned type in##bwl##_local_p(int port) { \
+- unsigned type value = in##bwl##_local(port); \
+- slow_down_io(); \
+- return value; \
+-} \
+-__BUILDIO(bwl,bw,type) \
+-static inline void out##bwl##_p(unsigned type value, int port) { \
+- out##bwl(value, port); \
+- slow_down_io(); \
+-} \
+-static inline unsigned type in##bwl##_p(int port) { \
+- unsigned type value = in##bwl(port); \
+- slow_down_io(); \
+- return value; \
+-} \
+-static inline void outs##bwl(int port, const void *addr, unsigned long count) { \
+- __asm__ __volatile__("rep; outs" #bwl : "+S"(addr), "+c"(count) : "d"(port)); \
+-} \
+-static inline void ins##bwl(int port, void *addr, unsigned long count) { \
+- __asm__ __volatile__("rep; ins" #bwl : "+D"(addr), "+c"(count) : "d"(port)); \
++#define BUILDIO(bwl, bw, type) \
++static inline void out##bwl##_local(unsigned type value, int port) \
++{ \
++ asm volatile("out" #bwl " %" #bw "0, %w1" \
++ : : "a"(value), "Nd"(port)); \
++} \
++ \
++static inline unsigned type in##bwl##_local(int port) \
++{ \
++ unsigned type value; \
++ asm volatile("in" #bwl " %w1, %" #bw "0" \
++ : "=a"(value) : "Nd"(port)); \
++ return value; \
++} \
++ \
++static inline void out##bwl##_local_p(unsigned type value, int port) \
++{ \
++ out##bwl##_local(value, port); \
++ slow_down_io(); \
++} \
++ \
++static inline unsigned type in##bwl##_local_p(int port) \
++{ \
++ unsigned type value = in##bwl##_local(port); \
++ slow_down_io(); \
++ return value; \
++} \
++ \
++__BUILDIO(bwl, bw, type) \
++ \
++static inline void out##bwl##_p(unsigned type value, int port) \
++{ \
++ out##bwl(value, port); \
++ slow_down_io(); \
++} \
++ \
++static inline unsigned type in##bwl##_p(int port) \
++{ \
++ unsigned type value = in##bwl(port); \
++ slow_down_io(); \
++ return value; \
++} \
++ \
++static inline void outs##bwl(int port, const void *addr, unsigned long count) \
++{ \
++ asm volatile("rep; outs" #bwl \
++ : "+S"(addr), "+c"(count) : "d"(port)); \
++} \
++ \
++static inline void ins##bwl(int port, void *addr, unsigned long count) \
++{ \
++ asm volatile("rep; ins" #bwl \
++ : "+D"(addr), "+c"(count) : "d"(port)); \
+ }
+
+-BUILDIO(b,b,char)
+-BUILDIO(w,w,short)
+-BUILDIO(l,,int)
++BUILDIO(b, b, char)
++BUILDIO(w, w, short)
++BUILDIO(l, , int)
+
+ #endif
+diff --git a/include/asm-x86/io_64.h b/include/asm-x86/io_64.h
+index db0be20..0930bed 100644
+--- a/include/asm-x86/io_64.h
++++ b/include/asm-x86/io_64.h
+@@ -58,60 +58,75 @@ static inline void slow_down_io(void)
+ /*
+ * Talk about misusing macros..
+ */
+-#define __OUT1(s,x) \
++#define __OUT1(s, x) \
+ static inline void out##s(unsigned x value, unsigned short port) {
+
+-#define __OUT2(s,s1,s2) \
+-__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1"
++#define __OUT2(s, s1, s2) \
++asm volatile ("out" #s " %" s1 "0,%" s2 "1"
+
+ #ifndef REALLY_SLOW_IO
+ #define REALLY_SLOW_IO
+ #define UNSET_REALLY_SLOW_IO
+ #endif
+
+-#define __OUT(s,s1,x) \
+-__OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } \
+-__OUT1(s##_p, x) __OUT2(s, s1, "w") : : "a" (value), "Nd" (port)); \
+- slow_down_io(); }
++#define __OUT(s, s1, x) \
++ __OUT1(s, x) __OUT2(s, s1, "w") : : "a" (value), "Nd" (port)); \
++ } \
++ __OUT1(s##_p, x) __OUT2(s, s1, "w") : : "a" (value), "Nd" (port)); \
++ slow_down_io(); \
++}
+
+-#define __IN1(s) \
+-static inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v;
++#define __IN1(s) \
++static inline RETURN_TYPE in##s(unsigned short port) \
++{ \
++ RETURN_TYPE _v;
+
+-#define __IN2(s,s1,s2) \
+-__asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0"
++#define __IN2(s, s1, s2) \
++ asm volatile ("in" #s " %" s2 "1,%" s1 "0"
+
+-#define __IN(s,s1,i...) \
+-__IN1(s) __IN2(s, s1, "w") : "=a" (_v) : "Nd" (port), ##i); return _v; } \
+-__IN1(s##_p) __IN2(s, s1, "w") : "=a" (_v) : "Nd" (port), ##i); \
+- slow_down_io(); return _v; }
++#define __IN(s, s1, i...) \
++ __IN1(s) __IN2(s, s1, "w") : "=a" (_v) : "Nd" (port), ##i); \
++ return _v; \
++ } \
++ __IN1(s##_p) __IN2(s, s1, "w") : "=a" (_v) : "Nd" (port), ##i); \
++ slow_down_io(); \
++ return _v; }
+
+ #ifdef UNSET_REALLY_SLOW_IO
+ #undef REALLY_SLOW_IO
+ #endif
+
+-#define __INS(s) \
+-static inline void ins##s(unsigned short port, void * addr, unsigned long count) \
+-{ __asm__ __volatile__ ("rep ; ins" #s \
+-: "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
++#define __INS(s) \
++static inline void ins##s(unsigned short port, void *addr, \
++ unsigned long count) \
++{ \
++ asm volatile ("rep ; ins" #s \
++ : "=D" (addr), "=c" (count) \
++ : "d" (port), "0" (addr), "1" (count)); \
++}
+
+-#define __OUTS(s) \
+-static inline void outs##s(unsigned short port, const void * addr, unsigned long count) \
+-{ __asm__ __volatile__ ("rep ; outs" #s \
+-: "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
++#define __OUTS(s) \
++static inline void outs##s(unsigned short port, const void *addr, \
++ unsigned long count) \
++{ \
++ asm volatile ("rep ; outs" #s \
++ : "=S" (addr), "=c" (count) \
++ : "d" (port), "0" (addr), "1" (count)); \
++}
+
+ #define RETURN_TYPE unsigned char
+-__IN(b,"")
++__IN(b, "")
+ #undef RETURN_TYPE
+ #define RETURN_TYPE unsigned short
+-__IN(w,"")
++__IN(w, "")
+ #undef RETURN_TYPE
+ #define RETURN_TYPE unsigned int
+-__IN(l,"")
++__IN(l, "")
+ #undef RETURN_TYPE
+
+-__OUT(b,"b",char)
+-__OUT(w,"w",short)
+-__OUT(l,,int)
++__OUT(b, "b", char)
++__OUT(w, "w", short)
++__OUT(l, , int)
+
+ __INS(b)
+ __INS(w)
+@@ -132,12 +147,12 @@ __OUTS(l)
+ * Change virtual addresses to physical addresses and vv.
+ * These are pretty trivial
+ */
+-static inline unsigned long virt_to_phys(volatile void * address)
++static inline unsigned long virt_to_phys(volatile void *address)
+ {
+ return __pa(address);
+ }
+
+-static inline void * phys_to_virt(unsigned long address)
++static inline void *phys_to_virt(unsigned long address)
+ {
+ return __va(address);
+ }
+@@ -200,18 +215,22 @@ static inline __u8 __readb(const volatile void __iomem *addr)
+ {
+ return *(__force volatile __u8 *)addr;
+ }
++
+ static inline __u16 __readw(const volatile void __iomem *addr)
+ {
+ return *(__force volatile __u16 *)addr;
+ }
++
+ static __always_inline __u32 __readl(const volatile void __iomem *addr)
+ {
+ return *(__force volatile __u32 *)addr;
+ }
++
+ static inline __u64 __readq(const volatile void __iomem *addr)
+ {
+ return *(__force volatile __u64 *)addr;
+ }
++
+ #define readb(x) __readb(x)
+ #define readw(x) __readw(x)
+ #define readl(x) __readl(x)
+@@ -231,37 +250,44 @@ static inline void __writel(__u32 b, volatile void __iomem *addr)
+ {
+ *(__force volatile __u32 *)addr = b;
+ }
++
+ static inline void __writeq(__u64 b, volatile void __iomem *addr)
+ {
+ *(__force volatile __u64 *)addr = b;
+ }
++
+ static inline void __writeb(__u8 b, volatile void __iomem *addr)
+ {
+ *(__force volatile __u8 *)addr = b;
+ }
++
+ static inline void __writew(__u16 b, volatile void __iomem *addr)
+ {
+ *(__force volatile __u16 *)addr = b;
+ }
+-#define writeq(val,addr) __writeq((val),(addr))
+-#define writel(val,addr) __writel((val),(addr))
+-#define writew(val,addr) __writew((val),(addr))
+-#define writeb(val,addr) __writeb((val),(addr))
++
++#define writeq(val, addr) __writeq((val), (addr))
++#define writel(val, addr) __writel((val), (addr))
++#define writew(val, addr) __writew((val), (addr))
++#define writeb(val, addr) __writeb((val), (addr))
+ #define __raw_writeb writeb
+ #define __raw_writew writew
+ #define __raw_writel writel
+ #define __raw_writeq writeq
+
+-void __memcpy_fromio(void*,unsigned long,unsigned);
+-void __memcpy_toio(unsigned long,const void*,unsigned);
++void __memcpy_fromio(void *, unsigned long, unsigned);
++void __memcpy_toio(unsigned long, const void *, unsigned);
+
+-static inline void memcpy_fromio(void *to, const volatile void __iomem *from, unsigned len)
++static inline void memcpy_fromio(void *to, const volatile void __iomem *from,
++ unsigned len)
+ {
+- __memcpy_fromio(to,(unsigned long)from,len);
++ __memcpy_fromio(to, (unsigned long)from, len);
+ }
+-static inline void memcpy_toio(volatile void __iomem *to, const void *from, unsigned len)
++
++static inline void memcpy_toio(volatile void __iomem *to, const void *from,
++ unsigned len)
+ {
+- __memcpy_toio((unsigned long)to,from,len);
++ __memcpy_toio((unsigned long)to, from, len);
+ }
+
+ void memset_io(volatile void __iomem *a, int b, size_t c);
+@@ -276,18 +302,12 @@ void memset_io(volatile void __iomem *a, int b, size_t c);
+ */
+ #define __ISA_IO_base ((char __iomem *)(PAGE_OFFSET))
+
+-#define flush_write_buffers()
++#define flush_write_buffers()
+
+ extern int iommu_bio_merge;
+ #define BIO_VMERGE_BOUNDARY iommu_bio_merge
+
+ /*
+- * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+- * access
+- */
+-#define xlate_dev_mem_ptr(p) __va(p)
+-
+-/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+ #define xlate_dev_kmem_ptr(p) p
+diff --git a/include/asm-x86/io_apic.h b/include/asm-x86/io_apic.h
+index 0f5b3fe..d593e14 100644
+--- a/include/asm-x86/io_apic.h
++++ b/include/asm-x86/io_apic.h
+@@ -1,7 +1,7 @@
+ #ifndef __ASM_IO_APIC_H
+ #define __ASM_IO_APIC_H
+
+-#include <asm/types.h>
++#include <linux/types.h>
+ #include <asm/mpspec.h>
+ #include <asm/apicdef.h>
+
+@@ -110,6 +110,15 @@ extern int nr_ioapic_registers[MAX_IO_APICS];
+ * MP-BIOS irq configuration table structures:
+ */
+
++#define MP_MAX_IOAPIC_PIN 127
++
++struct mp_ioapic_routing {
++ int apic_id;
++ int gsi_base;
++ int gsi_end;
++ DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
++};
++
+ /* I/O APIC entries */
+ extern struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
+
+@@ -146,7 +155,6 @@ extern int io_apic_get_version(int ioapic);
+ extern int io_apic_get_redir_entries(int ioapic);
+ extern int io_apic_set_pci_routing(int ioapic, int pin, int irq,
+ int edge_level, int active_high_low);
+-extern int timer_uses_ioapic_pin_0;
+ #endif /* CONFIG_ACPI */
+
+ extern int (*ioapic_renumber_irq)(int ioapic, int irq);
+diff --git a/include/asm-x86/ioctls.h b/include/asm-x86/ioctls.h
+index 93c894d..c0c338b 100644
+--- a/include/asm-x86/ioctls.h
++++ b/include/asm-x86/ioctls.h
+@@ -47,12 +47,13 @@
+ #define TIOCSBRK 0x5427 /* BSD compatibility */
+ #define TIOCCBRK 0x5428 /* BSD compatibility */
+ #define TIOCGSID 0x5429 /* Return the session ID of FD */
+-#define TCGETS2 _IOR('T',0x2A, struct termios2)
+-#define TCSETS2 _IOW('T',0x2B, struct termios2)
+-#define TCSETSW2 _IOW('T',0x2C, struct termios2)
+-#define TCSETSF2 _IOW('T',0x2D, struct termios2)
+-#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
+-#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
++#define TCGETS2 _IOR('T', 0x2A, struct termios2)
++#define TCSETS2 _IOW('T', 0x2B, struct termios2)
++#define TCSETSW2 _IOW('T', 0x2C, struct termios2)
++#define TCSETSF2 _IOW('T', 0x2D, struct termios2)
++#define TIOCGPTN _IOR('T', 0x30, unsigned int)
++ /* Get Pty Number (of pty-mux device) */
++#define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */
+
+ #define FIONCLEX 0x5450
+ #define FIOCLEX 0x5451
+diff --git a/include/asm-x86/ipcbuf.h b/include/asm-x86/ipcbuf.h
+index 2adf8b3..ee678fd 100644
+--- a/include/asm-x86/ipcbuf.h
++++ b/include/asm-x86/ipcbuf.h
+@@ -11,8 +11,7 @@
+ * - 2 miscellaneous 32-bit values
+ */
+
+-struct ipc64_perm
+-{
++struct ipc64_perm {
+ __kernel_key_t key;
+ __kernel_uid32_t uid;
+ __kernel_gid32_t gid;
+diff --git a/include/asm-x86/ipi.h b/include/asm-x86/ipi.h
+index 6d011bd..ecc80f3 100644
+--- a/include/asm-x86/ipi.h
++++ b/include/asm-x86/ipi.h
+@@ -27,7 +27,8 @@
+ * We use 'broadcast', CPU->CPU IPIs and self-IPIs too.
+ */
+
+-static inline unsigned int __prepare_ICR (unsigned int shortcut, int vector, unsigned int dest)
++static inline unsigned int __prepare_ICR(unsigned int shortcut, int vector,
++ unsigned int dest)
+ {
+ unsigned int icr = shortcut | dest;
+
+@@ -42,12 +43,13 @@ static inline unsigned int __prepare_ICR (unsigned int shortcut, int vector, uns
+ return icr;
+ }
+
+-static inline int __prepare_ICR2 (unsigned int mask)
++static inline int __prepare_ICR2(unsigned int mask)
+ {
+ return SET_APIC_DEST_FIELD(mask);
+ }
+
+-static inline void __send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest)
++static inline void __send_IPI_shortcut(unsigned int shortcut, int vector,
++ unsigned int dest)
+ {
+ /*
+ * Subtle. In the case of the 'never do double writes' workaround
+@@ -78,7 +80,8 @@ static inline void __send_IPI_shortcut(unsigned int shortcut, int vector, unsign
+ * This is used to send an IPI with no shorthand notation (the destination is
+ * specified in bits 56 to 63 of the ICR).
+ */
+-static inline void __send_IPI_dest_field(unsigned int mask, int vector, unsigned int dest)
++static inline void __send_IPI_dest_field(unsigned int mask, int vector,
++ unsigned int dest)
+ {
+ unsigned long cfg;
+
+diff --git a/include/asm-x86/irq_32.h b/include/asm-x86/irq_32.h
+index aca9c96..0b79f31 100644
+--- a/include/asm-x86/irq_32.h
++++ b/include/asm-x86/irq_32.h
+@@ -15,7 +15,7 @@
+ #include "irq_vectors.h"
+ #include <asm/thread_info.h>
+
+-static __inline__ int irq_canonicalize(int irq)
++static inline int irq_canonicalize(int irq)
+ {
+ return ((irq == 2) ? 9 : irq);
+ }
+diff --git a/include/asm-x86/irq_64.h b/include/asm-x86/irq_64.h
+index 5006c6e..083d35a 100644
+--- a/include/asm-x86/irq_64.h
++++ b/include/asm-x86/irq_64.h
+@@ -31,10 +31,10 @@
+
+ #define FIRST_SYSTEM_VECTOR 0xef /* duplicated in hw_irq.h */
+
+-#define NR_IRQS (NR_VECTORS + (32 *NR_CPUS))
++#define NR_IRQS (NR_VECTORS + (32 * NR_CPUS))
+ #define NR_IRQ_VECTORS NR_IRQS
+
+-static __inline__ int irq_canonicalize(int irq)
++static inline int irq_canonicalize(int irq)
+ {
+ return ((irq == 2) ? 9 : irq);
+ }
+diff --git a/include/asm-x86/irqflags.h b/include/asm-x86/irqflags.h
+index 0e22924..c242527 100644
+--- a/include/asm-x86/irqflags.h
++++ b/include/asm-x86/irqflags.h
+@@ -12,25 +12,21 @@ static inline unsigned long native_save_fl(void)
+ {
+ unsigned long flags;
+
+- __asm__ __volatile__(
+- "# __raw_save_flags\n\t"
+- "pushf ; pop %0"
+- : "=g" (flags)
+- : /* no input */
+- : "memory"
+- );
++ asm volatile("# __raw_save_flags\n\t"
++ "pushf ; pop %0"
++ : "=g" (flags)
++ : /* no input */
++ : "memory");
+
+ return flags;
+ }
+
+ static inline void native_restore_fl(unsigned long flags)
+ {
+- __asm__ __volatile__(
+- "push %0 ; popf"
+- : /* no output */
+- :"g" (flags)
+- :"memory", "cc"
+- );
++ asm volatile("push %0 ; popf"
++ : /* no output */
++ :"g" (flags)
++ :"memory", "cc");
+ }
+
+ static inline void native_irq_disable(void)
+@@ -70,26 +66,6 @@ static inline void raw_local_irq_restore(unsigned long flags)
+ native_restore_fl(flags);
+ }
+
+-#ifdef CONFIG_X86_VSMP
+-
+-/*
+- * Interrupt control for the VSMP architecture:
+- */
+-
+-static inline void raw_local_irq_disable(void)
+-{
+- unsigned long flags = __raw_local_save_flags();
+- raw_local_irq_restore((flags & ~X86_EFLAGS_IF) | X86_EFLAGS_AC);
+-}
+-
+-static inline void raw_local_irq_enable(void)
+-{
+- unsigned long flags = __raw_local_save_flags();
+- raw_local_irq_restore((flags | X86_EFLAGS_IF) & (~X86_EFLAGS_AC));
+-}
+-
+-#else
+-
+ static inline void raw_local_irq_disable(void)
+ {
+ native_irq_disable();
+@@ -100,8 +76,6 @@ static inline void raw_local_irq_enable(void)
+ native_irq_enable();
+ }
+
+-#endif
+-
+ /*
+ * Used in the idle loop; sti takes one instruction cycle
+ * to complete:
+@@ -153,23 +127,16 @@ static inline unsigned long __raw_local_irq_save(void)
+ #endif /* CONFIG_PARAVIRT */
+
+ #ifndef __ASSEMBLY__
+-#define raw_local_save_flags(flags) \
+- do { (flags) = __raw_local_save_flags(); } while (0)
++#define raw_local_save_flags(flags) \
++ do { (flags) = __raw_local_save_flags(); } while (0)
+
+-#define raw_local_irq_save(flags) \
+- do { (flags) = __raw_local_irq_save(); } while (0)
++#define raw_local_irq_save(flags) \
++ do { (flags) = __raw_local_irq_save(); } while (0)
+
+-#ifdef CONFIG_X86_VSMP
+-static inline int raw_irqs_disabled_flags(unsigned long flags)
+-{
+- return !(flags & X86_EFLAGS_IF) || (flags & X86_EFLAGS_AC);
+-}
+-#else
+ static inline int raw_irqs_disabled_flags(unsigned long flags)
+ {
+ return !(flags & X86_EFLAGS_IF);
+ }
+-#endif
+
+ static inline int raw_irqs_disabled(void)
+ {
+diff --git a/include/asm-x86/kdebug.h b/include/asm-x86/kdebug.h
+index 99dcbaf..96651bb 100644
+--- a/include/asm-x86/kdebug.h
++++ b/include/asm-x86/kdebug.h
+@@ -20,15 +20,16 @@ enum die_val {
+ DIE_CALL,
+ DIE_NMI_IPI,
+ DIE_PAGE_FAULT,
++ DIE_NMIUNKNOWN,
+ };
+
+ extern void printk_address(unsigned long address, int reliable);
+-extern void die(const char *,struct pt_regs *,long);
++extern void die(const char *, struct pt_regs *,long);
+ extern int __must_check __die(const char *, struct pt_regs *, long);
+ extern void show_registers(struct pt_regs *regs);
+ extern void __show_registers(struct pt_regs *, int all);
+ extern void show_trace(struct task_struct *t, struct pt_regs *regs,
+- unsigned long *sp, unsigned long bp);
++ unsigned long *sp, unsigned long bp);
+ extern void __show_regs(struct pt_regs *regs);
+ extern void show_regs(struct pt_regs *regs);
+ extern unsigned long oops_begin(void);
+diff --git a/include/asm-x86/kexec.h b/include/asm-x86/kexec.h
+index c90d3c7..8f855a1 100644
+--- a/include/asm-x86/kexec.h
++++ b/include/asm-x86/kexec.h
+@@ -94,10 +94,9 @@ static inline void crash_fixup_ss_esp(struct pt_regs *newregs,
+ {
+ #ifdef CONFIG_X86_32
+ newregs->sp = (unsigned long)&(oldregs->sp);
+- __asm__ __volatile__(
+- "xorl %%eax, %%eax\n\t"
+- "movw %%ss, %%ax\n\t"
+- :"=a"(newregs->ss));
++ asm volatile("xorl %%eax, %%eax\n\t"
++ "movw %%ss, %%ax\n\t"
++ :"=a"(newregs->ss));
+ #endif
+ }
+
+@@ -114,39 +113,39 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
+ crash_fixup_ss_esp(newregs, oldregs);
+ } else {
+ #ifdef CONFIG_X86_32
+- __asm__ __volatile__("movl %%ebx,%0" : "=m"(newregs->bx));
+- __asm__ __volatile__("movl %%ecx,%0" : "=m"(newregs->cx));
+- __asm__ __volatile__("movl %%edx,%0" : "=m"(newregs->dx));
+- __asm__ __volatile__("movl %%esi,%0" : "=m"(newregs->si));
+- __asm__ __volatile__("movl %%edi,%0" : "=m"(newregs->di));
+- __asm__ __volatile__("movl %%ebp,%0" : "=m"(newregs->bp));
+- __asm__ __volatile__("movl %%eax,%0" : "=m"(newregs->ax));
+- __asm__ __volatile__("movl %%esp,%0" : "=m"(newregs->sp));
+- __asm__ __volatile__("movl %%ss, %%eax;" :"=a"(newregs->ss));
+- __asm__ __volatile__("movl %%cs, %%eax;" :"=a"(newregs->cs));
+- __asm__ __volatile__("movl %%ds, %%eax;" :"=a"(newregs->ds));
+- __asm__ __volatile__("movl %%es, %%eax;" :"=a"(newregs->es));
+- __asm__ __volatile__("pushfl; popl %0" :"=m"(newregs->flags));
++ asm volatile("movl %%ebx,%0" : "=m"(newregs->bx));
++ asm volatile("movl %%ecx,%0" : "=m"(newregs->cx));
++ asm volatile("movl %%edx,%0" : "=m"(newregs->dx));
++ asm volatile("movl %%esi,%0" : "=m"(newregs->si));
++ asm volatile("movl %%edi,%0" : "=m"(newregs->di));
++ asm volatile("movl %%ebp,%0" : "=m"(newregs->bp));
++ asm volatile("movl %%eax,%0" : "=m"(newregs->ax));
++ asm volatile("movl %%esp,%0" : "=m"(newregs->sp));
++ asm volatile("movl %%ss, %%eax;" :"=a"(newregs->ss));
++ asm volatile("movl %%cs, %%eax;" :"=a"(newregs->cs));
++ asm volatile("movl %%ds, %%eax;" :"=a"(newregs->ds));
++ asm volatile("movl %%es, %%eax;" :"=a"(newregs->es));
++ asm volatile("pushfl; popl %0" :"=m"(newregs->flags));
+ #else
+- __asm__ __volatile__("movq %%rbx,%0" : "=m"(newregs->bx));
+- __asm__ __volatile__("movq %%rcx,%0" : "=m"(newregs->cx));
+- __asm__ __volatile__("movq %%rdx,%0" : "=m"(newregs->dx));
+- __asm__ __volatile__("movq %%rsi,%0" : "=m"(newregs->si));
+- __asm__ __volatile__("movq %%rdi,%0" : "=m"(newregs->di));
+- __asm__ __volatile__("movq %%rbp,%0" : "=m"(newregs->bp));
+- __asm__ __volatile__("movq %%rax,%0" : "=m"(newregs->ax));
+- __asm__ __volatile__("movq %%rsp,%0" : "=m"(newregs->sp));
+- __asm__ __volatile__("movq %%r8,%0" : "=m"(newregs->r8));
+- __asm__ __volatile__("movq %%r9,%0" : "=m"(newregs->r9));
+- __asm__ __volatile__("movq %%r10,%0" : "=m"(newregs->r10));
+- __asm__ __volatile__("movq %%r11,%0" : "=m"(newregs->r11));
+- __asm__ __volatile__("movq %%r12,%0" : "=m"(newregs->r12));
+- __asm__ __volatile__("movq %%r13,%0" : "=m"(newregs->r13));
+- __asm__ __volatile__("movq %%r14,%0" : "=m"(newregs->r14));
+- __asm__ __volatile__("movq %%r15,%0" : "=m"(newregs->r15));
+- __asm__ __volatile__("movl %%ss, %%eax;" :"=a"(newregs->ss));
+- __asm__ __volatile__("movl %%cs, %%eax;" :"=a"(newregs->cs));
+- __asm__ __volatile__("pushfq; popq %0" :"=m"(newregs->flags));
++ asm volatile("movq %%rbx,%0" : "=m"(newregs->bx));
++ asm volatile("movq %%rcx,%0" : "=m"(newregs->cx));
++ asm volatile("movq %%rdx,%0" : "=m"(newregs->dx));
++ asm volatile("movq %%rsi,%0" : "=m"(newregs->si));
++ asm volatile("movq %%rdi,%0" : "=m"(newregs->di));
++ asm volatile("movq %%rbp,%0" : "=m"(newregs->bp));
++ asm volatile("movq %%rax,%0" : "=m"(newregs->ax));
++ asm volatile("movq %%rsp,%0" : "=m"(newregs->sp));
++ asm volatile("movq %%r8,%0" : "=m"(newregs->r8));
++ asm volatile("movq %%r9,%0" : "=m"(newregs->r9));
++ asm volatile("movq %%r10,%0" : "=m"(newregs->r10));
++ asm volatile("movq %%r11,%0" : "=m"(newregs->r11));
++ asm volatile("movq %%r12,%0" : "=m"(newregs->r12));
++ asm volatile("movq %%r13,%0" : "=m"(newregs->r13));
++ asm volatile("movq %%r14,%0" : "=m"(newregs->r14));
++ asm volatile("movq %%r15,%0" : "=m"(newregs->r15));
++ asm volatile("movl %%ss, %%eax;" :"=a"(newregs->ss));
++ asm volatile("movl %%cs, %%eax;" :"=a"(newregs->cs));
++ asm volatile("pushfq; popq %0" :"=m"(newregs->flags));
+ #endif
+ newregs->ip = (unsigned long)current_text_addr();
+ }
+diff --git a/include/asm-x86/kgdb.h b/include/asm-x86/kgdb.h
+new file mode 100644
+index 0000000..484c475
+--- /dev/null
++++ b/include/asm-x86/kgdb.h
+@@ -0,0 +1,81 @@
++#ifndef _ASM_KGDB_H_
++#define _ASM_KGDB_H_
++
++/*
++ * Copyright (C) 2001-2004 Amit S. Kale
++ * Copyright (C) 2008 Wind River Systems, Inc.
++ */
++
++/*
++ * BUFMAX defines the maximum number of characters in inbound/outbound
++ * buffers at least NUMREGBYTES*2 are needed for register packets
++ * Longer buffer is needed to list all threads
++ */
++#define BUFMAX 1024
++
++/*
++ * Note that this register image is in a different order than
++ * the register image that Linux produces at interrupt time.
++ *
++ * Linux's register image is defined by struct pt_regs in ptrace.h.
++ * Just why GDB uses a different order is a historical mystery.
++ */
++#ifdef CONFIG_X86_32
++enum regnames {
++ GDB_AX, /* 0 */
++ GDB_CX, /* 1 */
++ GDB_DX, /* 2 */
++ GDB_BX, /* 3 */
++ GDB_SP, /* 4 */
++ GDB_BP, /* 5 */
++ GDB_SI, /* 6 */
++ GDB_DI, /* 7 */
++ GDB_PC, /* 8 also known as eip */
++ GDB_PS, /* 9 also known as eflags */
++ GDB_CS, /* 10 */
++ GDB_SS, /* 11 */
++ GDB_DS, /* 12 */
++ GDB_ES, /* 13 */
++ GDB_FS, /* 14 */
++ GDB_GS, /* 15 */
++};
++#else /* ! CONFIG_X86_32 */
++enum regnames {
++ GDB_AX, /* 0 */
++ GDB_DX, /* 1 */
++ GDB_CX, /* 2 */
++ GDB_BX, /* 3 */
++ GDB_SI, /* 4 */
++ GDB_DI, /* 5 */
++ GDB_BP, /* 6 */
++ GDB_SP, /* 7 */
++ GDB_R8, /* 8 */
++ GDB_R9, /* 9 */
++ GDB_R10, /* 10 */
++ GDB_R11, /* 11 */
++ GDB_R12, /* 12 */
++ GDB_R13, /* 13 */
++ GDB_R14, /* 14 */
++ GDB_R15, /* 15 */
++ GDB_PC, /* 16 */
++ GDB_PS, /* 17 */
++};
++#endif /* CONFIG_X86_32 */
++
++/*
++ * Number of bytes of registers:
++ */
++#ifdef CONFIG_X86_32
++# define NUMREGBYTES 64
++#else
++# define NUMREGBYTES ((GDB_PS+1)*8)
++#endif
++
++static inline void arch_kgdb_breakpoint(void)
++{
++ asm(" int $3");
++}
++#define BREAK_INSTR_SIZE 1
++#define CACHE_FLUSH_IS_SAFE 1
++
++#endif /* _ASM_KGDB_H_ */
+diff --git a/include/asm-x86/kprobes.h b/include/asm-x86/kprobes.h
+index 61ad7b5..54980b0 100644
+--- a/include/asm-x86/kprobes.h
++++ b/include/asm-x86/kprobes.h
+@@ -35,12 +35,12 @@ typedef u8 kprobe_opcode_t;
+ #define RELATIVEJUMP_INSTRUCTION 0xe9
+ #define MAX_INSN_SIZE 16
+ #define MAX_STACK_SIZE 64
+-#define MIN_STACK_SIZE(ADDR) (((MAX_STACK_SIZE) < \
+- (((unsigned long)current_thread_info()) + THREAD_SIZE \
+- - (unsigned long)(ADDR))) \
+- ? (MAX_STACK_SIZE) \
+- : (((unsigned long)current_thread_info()) + THREAD_SIZE \
+- - (unsigned long)(ADDR)))
++#define MIN_STACK_SIZE(ADDR) \
++ (((MAX_STACK_SIZE) < (((unsigned long)current_thread_info()) + \
++ THREAD_SIZE - (unsigned long)(ADDR))) \
++ ? (MAX_STACK_SIZE) \
++ : (((unsigned long)current_thread_info()) + \
++ THREAD_SIZE - (unsigned long)(ADDR)))
+
+ #define flush_insn_slot(p) do { } while (0)
+
+diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h
+index 4702b04..68ee390 100644
+--- a/include/asm-x86/kvm_host.h
++++ b/include/asm-x86/kvm_host.h
+@@ -22,15 +22,16 @@
+
+ #define CR3_PAE_RESERVED_BITS ((X86_CR3_PWT | X86_CR3_PCD) - 1)
+ #define CR3_NONPAE_RESERVED_BITS ((PAGE_SIZE-1) & ~(X86_CR3_PWT | X86_CR3_PCD))
+-#define CR3_L_MODE_RESERVED_BITS (CR3_NONPAE_RESERVED_BITS|0xFFFFFF0000000000ULL)
++#define CR3_L_MODE_RESERVED_BITS (CR3_NONPAE_RESERVED_BITS | \
++ 0xFFFFFF0000000000ULL)
+
+-#define KVM_GUEST_CR0_MASK \
++#define KVM_GUEST_CR0_MASK \
+ (X86_CR0_PG | X86_CR0_PE | X86_CR0_WP | X86_CR0_NE \
+ | X86_CR0_NW | X86_CR0_CD)
+-#define KVM_VM_CR0_ALWAYS_ON \
++#define KVM_VM_CR0_ALWAYS_ON \
+ (X86_CR0_PG | X86_CR0_PE | X86_CR0_WP | X86_CR0_NE | X86_CR0_TS \
+ | X86_CR0_MP)
+-#define KVM_GUEST_CR4_MASK \
++#define KVM_GUEST_CR4_MASK \
+ (X86_CR4_VME | X86_CR4_PSE | X86_CR4_PAE | X86_CR4_PGE | X86_CR4_VMXE)
+ #define KVM_PMODE_VM_CR4_ALWAYS_ON (X86_CR4_PAE | X86_CR4_VMXE)
+ #define KVM_RMODE_VM_CR4_ALWAYS_ON (X86_CR4_VME | X86_CR4_PAE | X86_CR4_VMXE)
+@@ -133,12 +134,12 @@ struct kvm_pte_chain {
+ union kvm_mmu_page_role {
+ unsigned word;
+ struct {
+- unsigned glevels : 4;
+- unsigned level : 4;
+- unsigned quadrant : 2;
+- unsigned pad_for_nice_hex_output : 6;
+- unsigned metaphysical : 1;
+- unsigned access : 3;
++ unsigned glevels:4;
++ unsigned level:4;
++ unsigned quadrant:2;
++ unsigned pad_for_nice_hex_output:6;
++ unsigned metaphysical:1;
++ unsigned access:3;
+ };
+ };
+
+@@ -606,6 +607,7 @@ static inline void kvm_inject_gp(struct kvm_vcpu *vcpu, u32 error_code)
+ #define TSS_BASE_SIZE 0x68
+ #define TSS_IOPB_SIZE (65536 / 8)
+ #define TSS_REDIRECTION_SIZE (256 / 8)
+-#define RMODE_TSS_SIZE (TSS_BASE_SIZE + TSS_REDIRECTION_SIZE + TSS_IOPB_SIZE + 1)
++#define RMODE_TSS_SIZE \
++ (TSS_BASE_SIZE + TSS_REDIRECTION_SIZE + TSS_IOPB_SIZE + 1)
+
+ #endif
+diff --git a/include/asm-x86/kvm_x86_emulate.h b/include/asm-x86/kvm_x86_emulate.h
+index 7db91b9..d6337f9 100644
+--- a/include/asm-x86/kvm_x86_emulate.h
++++ b/include/asm-x86/kvm_x86_emulate.h
+@@ -68,10 +68,10 @@ struct x86_emulate_ops {
+ * @val: [OUT] Value read from memory, zero-extended to 'u_long'.
+ * @bytes: [IN ] Number of bytes to read from memory.
+ */
+- int (*read_emulated) (unsigned long addr,
+- void *val,
+- unsigned int bytes,
+- struct kvm_vcpu *vcpu);
++ int (*read_emulated)(unsigned long addr,
++ void *val,
++ unsigned int bytes,
++ struct kvm_vcpu *vcpu);
+
+ /*
+ * write_emulated: Read bytes from emulated/special memory area.
+@@ -80,10 +80,10 @@ struct x86_emulate_ops {
+ * required).
+ * @bytes: [IN ] Number of bytes to write to memory.
+ */
+- int (*write_emulated) (unsigned long addr,
+- const void *val,
+- unsigned int bytes,
+- struct kvm_vcpu *vcpu);
++ int (*write_emulated)(unsigned long addr,
++ const void *val,
++ unsigned int bytes,
++ struct kvm_vcpu *vcpu);
+
+ /*
+ * cmpxchg_emulated: Emulate an atomic (LOCKed) CMPXCHG operation on an
+@@ -93,11 +93,11 @@ struct x86_emulate_ops {
+ * @new: [IN ] Value to write to @addr.
+ * @bytes: [IN ] Number of bytes to access using CMPXCHG.
+ */
+- int (*cmpxchg_emulated) (unsigned long addr,
+- const void *old,
+- const void *new,
+- unsigned int bytes,
+- struct kvm_vcpu *vcpu);
++ int (*cmpxchg_emulated)(unsigned long addr,
++ const void *old,
++ const void *new,
++ unsigned int bytes,
++ struct kvm_vcpu *vcpu);
+
+ };
+
+@@ -143,7 +143,7 @@ struct x86_emulate_ctxt {
+ /* Register state before/after emulation. */
+ struct kvm_vcpu *vcpu;
+
+- /* Linear faulting address (if emulating a page-faulting instruction). */
++ /* Linear faulting address (if emulating a page-faulting instruction) */
+ unsigned long eflags;
+
+ /* Emulated execution mode, represented by an X86EMUL_MODE value. */
+diff --git a/include/asm-x86/lguest.h b/include/asm-x86/lguest.h
+index 9b17571..be4a724 100644
+--- a/include/asm-x86/lguest.h
++++ b/include/asm-x86/lguest.h
+@@ -34,8 +34,7 @@ extern const char lgstart_iret[], lgend_iret[];
+ extern void lguest_iret(void);
+ extern void lguest_init(void);
+
+-struct lguest_regs
+-{
++struct lguest_regs {
+ /* Manually saved part. */
+ unsigned long eax, ebx, ecx, edx;
+ unsigned long esi, edi, ebp;
+@@ -51,8 +50,7 @@ struct lguest_regs
+ };
+
+ /* This is a guest-specific page (mapped ro) into the guest. */
+-struct lguest_ro_state
+-{
++struct lguest_ro_state {
+ /* Host information we need to restore when we switch back. */
+ u32 host_cr3;
+ struct desc_ptr host_idt_desc;
+@@ -67,8 +65,7 @@ struct lguest_ro_state
+ struct desc_struct guest_gdt[GDT_ENTRIES];
+ };
+
+-struct lg_cpu_arch
+-{
++struct lg_cpu_arch {
+ /* The GDT entries copied into lguest_ro_state when running. */
+ struct desc_struct gdt[GDT_ENTRIES];
+
+@@ -85,7 +82,7 @@ static inline void lguest_set_ts(void)
+
+ cr0 = read_cr0();
+ if (!(cr0 & 8))
+- write_cr0(cr0|8);
++ write_cr0(cr0 | 8);
+ }
+
+ /* Full 4G segment descriptors, suitable for CS and DS. */
+diff --git a/include/asm-x86/lguest_hcall.h b/include/asm-x86/lguest_hcall.h
+index f239e70..a3241f2 100644
+--- a/include/asm-x86/lguest_hcall.h
++++ b/include/asm-x86/lguest_hcall.h
+@@ -46,7 +46,7 @@ hcall(unsigned long call,
+ {
+ /* "int" is the Intel instruction to trigger a trap. */
+ asm volatile("int $" __stringify(LGUEST_TRAP_ENTRY)
+- /* The call in %eax (aka "a") might be overwritten */
++ /* The call in %eax (aka "a") might be overwritten */
+ : "=a"(call)
+ /* The arguments are in %eax, %edx, %ebx & %ecx */
+ : "a"(call), "d"(arg1), "b"(arg2), "c"(arg3)
+@@ -62,8 +62,7 @@ hcall(unsigned long call,
+ #define LGUEST_IRQS (NR_IRQS < 32 ? NR_IRQS: 32)
+
+ #define LHCALL_RING_SIZE 64
+-struct hcall_args
+-{
++struct hcall_args {
+ /* These map directly onto eax, ebx, ecx, edx in struct lguest_regs */
+ unsigned long arg0, arg2, arg3, arg1;
+ };
+diff --git a/include/asm-x86/linkage.h b/include/asm-x86/linkage.h
+index c048353..64e444f 100644
+--- a/include/asm-x86/linkage.h
++++ b/include/asm-x86/linkage.h
+@@ -1,6 +1,9 @@
+ #ifndef __ASM_LINKAGE_H
+ #define __ASM_LINKAGE_H
+
++#undef notrace
++#define notrace __attribute__((no_instrument_function))
++
+ #ifdef CONFIG_X86_64
+ #define __ALIGN .p2align 4,,15
+ #define __ALIGN_STR ".p2align 4,,15"
+diff --git a/include/asm-x86/local.h b/include/asm-x86/local.h
+index f852c62..330a724 100644
+--- a/include/asm-x86/local.h
++++ b/include/asm-x86/local.h
+@@ -18,32 +18,28 @@ typedef struct {
+
+ static inline void local_inc(local_t *l)
+ {
+- __asm__ __volatile__(
+- _ASM_INC "%0"
+- :"+m" (l->a.counter));
++ asm volatile(_ASM_INC "%0"
++ : "+m" (l->a.counter));
+ }
+
+ static inline void local_dec(local_t *l)
+ {
+- __asm__ __volatile__(
+- _ASM_DEC "%0"
+- :"+m" (l->a.counter));
++ asm volatile(_ASM_DEC "%0"
++ : "+m" (l->a.counter));
+ }
+
+ static inline void local_add(long i, local_t *l)
+ {
+- __asm__ __volatile__(
+- _ASM_ADD "%1,%0"
+- :"+m" (l->a.counter)
+- :"ir" (i));
++ asm volatile(_ASM_ADD "%1,%0"
++ : "+m" (l->a.counter)
++ : "ir" (i));
+ }
+
+ static inline void local_sub(long i, local_t *l)
+ {
+- __asm__ __volatile__(
+- _ASM_SUB "%1,%0"
+- :"+m" (l->a.counter)
+- :"ir" (i));
++ asm volatile(_ASM_SUB "%1,%0"
++ : "+m" (l->a.counter)
++ : "ir" (i));
+ }
+
+ /**
+@@ -59,10 +55,9 @@ static inline int local_sub_and_test(long i, local_t *l)
+ {
+ unsigned char c;
+
+- __asm__ __volatile__(
+- _ASM_SUB "%2,%0; sete %1"
+- :"+m" (l->a.counter), "=qm" (c)
+- :"ir" (i) : "memory");
++ asm volatile(_ASM_SUB "%2,%0; sete %1"
++ : "+m" (l->a.counter), "=qm" (c)
++ : "ir" (i) : "memory");
+ return c;
+ }
+
+@@ -78,10 +73,9 @@ static inline int local_dec_and_test(local_t *l)
+ {
+ unsigned char c;
+
+- __asm__ __volatile__(
+- _ASM_DEC "%0; sete %1"
+- :"+m" (l->a.counter), "=qm" (c)
+- : : "memory");
++ asm volatile(_ASM_DEC "%0; sete %1"
++ : "+m" (l->a.counter), "=qm" (c)
++ : : "memory");
+ return c != 0;
+ }
+
+@@ -97,10 +91,9 @@ static inline int local_inc_and_test(local_t *l)
+ {
+ unsigned char c;
+
+- __asm__ __volatile__(
+- _ASM_INC "%0; sete %1"
+- :"+m" (l->a.counter), "=qm" (c)
+- : : "memory");
++ asm volatile(_ASM_INC "%0; sete %1"
++ : "+m" (l->a.counter), "=qm" (c)
++ : : "memory");
+ return c != 0;
+ }
+
+@@ -117,10 +110,9 @@ static inline int local_add_negative(long i, local_t *l)
+ {
+ unsigned char c;
+
+- __asm__ __volatile__(
+- _ASM_ADD "%2,%0; sets %1"
+- :"+m" (l->a.counter), "=qm" (c)
+- :"ir" (i) : "memory");
++ asm volatile(_ASM_ADD "%2,%0; sets %1"
++ : "+m" (l->a.counter), "=qm" (c)
++ : "ir" (i) : "memory");
+ return c;
+ }
+
+@@ -141,10 +133,9 @@ static inline long local_add_return(long i, local_t *l)
+ #endif
+ /* Modern 486+ processor */
+ __i = i;
+- __asm__ __volatile__(
+- _ASM_XADD "%0, %1;"
+- :"+r" (i), "+m" (l->a.counter)
+- : : "memory");
++ asm volatile(_ASM_XADD "%0, %1;"
++ : "+r" (i), "+m" (l->a.counter)
++ : : "memory");
+ return i + __i;
+
+ #ifdef CONFIG_M386
+@@ -182,11 +173,11 @@ static inline long local_sub_return(long i, local_t *l)
+ #define local_add_unless(l, a, u) \
+ ({ \
+ long c, old; \
+- c = local_read(l); \
++ c = local_read((l)); \
+ for (;;) { \
+ if (unlikely(c == (u))) \
+ break; \
+- old = local_cmpxchg((l), c, c + (a)); \
++ old = local_cmpxchg((l), c, c + (a)); \
+ if (likely(old == c)) \
+ break; \
+ c = old; \
+@@ -214,26 +205,30 @@ static inline long local_sub_return(long i, local_t *l)
+
+ /* Need to disable preemption for the cpu local counters otherwise we could
+ still access a variable of a previous CPU in a non atomic way. */
+-#define cpu_local_wrap_v(l) \
+- ({ local_t res__; \
+- preempt_disable(); \
+- res__ = (l); \
+- preempt_enable(); \
+- res__; })
++#define cpu_local_wrap_v(l) \
++({ \
++ local_t res__; \
++ preempt_disable(); \
++ res__ = (l); \
++ preempt_enable(); \
++ res__; \
++})
+ #define cpu_local_wrap(l) \
+- ({ preempt_disable(); \
+- l; \
+- preempt_enable(); }) \
+-
+-#define cpu_local_read(l) cpu_local_wrap_v(local_read(&__get_cpu_var(l)))
+-#define cpu_local_set(l, i) cpu_local_wrap(local_set(&__get_cpu_var(l), (i)))
+-#define cpu_local_inc(l) cpu_local_wrap(local_inc(&__get_cpu_var(l)))
+-#define cpu_local_dec(l) cpu_local_wrap(local_dec(&__get_cpu_var(l)))
+-#define cpu_local_add(i, l) cpu_local_wrap(local_add((i), &__get_cpu_var(l)))
+-#define cpu_local_sub(i, l) cpu_local_wrap(local_sub((i), &__get_cpu_var(l)))
+-
+-#define __cpu_local_inc(l) cpu_local_inc(l)
+-#define __cpu_local_dec(l) cpu_local_dec(l)
++({ \
++ preempt_disable(); \
++ (l); \
++ preempt_enable(); \
++}) \
++
++#define cpu_local_read(l) cpu_local_wrap_v(local_read(&__get_cpu_var((l))))
++#define cpu_local_set(l, i) cpu_local_wrap(local_set(&__get_cpu_var((l)), (i)))
++#define cpu_local_inc(l) cpu_local_wrap(local_inc(&__get_cpu_var((l))))
++#define cpu_local_dec(l) cpu_local_wrap(local_dec(&__get_cpu_var((l))))
++#define cpu_local_add(i, l) cpu_local_wrap(local_add((i), &__get_cpu_var((l))))
++#define cpu_local_sub(i, l) cpu_local_wrap(local_sub((i), &__get_cpu_var((l))))
++
++#define __cpu_local_inc(l) cpu_local_inc((l))
++#define __cpu_local_dec(l) cpu_local_dec((l))
+ #define __cpu_local_add(i, l) cpu_local_add((i), (l))
+ #define __cpu_local_sub(i, l) cpu_local_sub((i), (l))
+
+diff --git a/include/asm-x86/mach-bigsmp/mach_apic.h b/include/asm-x86/mach-bigsmp/mach_apic.h
+index 6df235e..8327907 100644
+--- a/include/asm-x86/mach-bigsmp/mach_apic.h
++++ b/include/asm-x86/mach-bigsmp/mach_apic.h
+@@ -1,10 +1,7 @@
+ #ifndef __ASM_MACH_APIC_H
+ #define __ASM_MACH_APIC_H
+
+-
+-extern u8 bios_cpu_apicid[];
+-
+-#define xapic_phys_to_log_apicid(cpu) (bios_cpu_apicid[cpu])
++#define xapic_phys_to_log_apicid(cpu) (per_cpu(x86_bios_cpu_apicid, cpu))
+ #define esr_disable (1)
+
+ static inline int apic_id_registered(void)
+@@ -90,7 +87,7 @@ static inline int apicid_to_node(int logical_apicid)
+ static inline int cpu_present_to_apicid(int mps_cpu)
+ {
+ if (mps_cpu < NR_CPUS)
+- return (int) bios_cpu_apicid[mps_cpu];
++ return (int) per_cpu(x86_bios_cpu_apicid, mps_cpu);
+
+ return BAD_APICID;
+ }
+@@ -109,17 +106,6 @@ static inline int cpu_to_logical_apicid(int cpu)
+ return cpu_physical_id(cpu);
+ }
+
+-static inline int mpc_apic_id(struct mpc_config_processor *m,
+- struct mpc_config_translation *translation_record)
+-{
+- printk("Processor #%d %u:%u APIC version %d\n",
+- m->mpc_apicid,
+- (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8,
+- (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4,
+- m->mpc_apicver);
+- return m->mpc_apicid;
+-}
+-
+ static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map)
+ {
+ /* For clustered we don't have a good way to do this yet - hack */
+diff --git a/include/asm-x86/mach-default/bios_ebda.h b/include/asm-x86/mach-default/bios_ebda.h
+deleted file mode 100644
+index 9cbd9a6..0000000
+--- a/include/asm-x86/mach-default/bios_ebda.h
++++ /dev/null
+@@ -1,15 +0,0 @@
+-#ifndef _MACH_BIOS_EBDA_H
+-#define _MACH_BIOS_EBDA_H
+-
+-/*
+- * there is a real-mode segmented pointer pointing to the
+- * 4K EBDA area at 0x40E.
+- */
+-static inline unsigned int get_bios_ebda(void)
+-{
+- unsigned int address = *(unsigned short *)phys_to_virt(0x40E);
+- address <<= 4;
+- return address; /* 0 means none */
+-}
+-
+-#endif /* _MACH_BIOS_EBDA_H */
+diff --git a/include/asm-x86/mach-default/mach_apic.h b/include/asm-x86/mach-default/mach_apic.h
+index e3c2c10..0a6634f 100644
+--- a/include/asm-x86/mach-default/mach_apic.h
++++ b/include/asm-x86/mach-default/mach_apic.h
+@@ -1,6 +1,8 @@
+ #ifndef __ASM_MACH_APIC_H
+ #define __ASM_MACH_APIC_H
+
++#ifdef CONFIG_X86_LOCAL_APIC
++
+ #include <mach_apicdef.h>
+ #include <asm/smp.h>
+
+@@ -14,24 +16,25 @@ static inline cpumask_t target_cpus(void)
+ return cpumask_of_cpu(0);
+ #endif
+ }
+-#define TARGET_CPUS (target_cpus())
+
+ #define NO_BALANCE_IRQ (0)
+ #define esr_disable (0)
+
++#ifdef CONFIG_X86_64
++#include <asm/genapic.h>
++#define INT_DELIVERY_MODE (genapic->int_delivery_mode)
++#define INT_DEST_MODE (genapic->int_dest_mode)
++#define TARGET_CPUS (genapic->target_cpus())
++#define apic_id_registered (genapic->apic_id_registered)
++#define init_apic_ldr (genapic->init_apic_ldr)
++#define cpu_mask_to_apicid (genapic->cpu_mask_to_apicid)
++#define phys_pkg_id (genapic->phys_pkg_id)
++#define vector_allocation_domain (genapic->vector_allocation_domain)
++extern void setup_apic_routing(void);
++#else
+ #define INT_DELIVERY_MODE dest_LowestPrio
+ #define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */
+-
+-static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid)
+-{
+- return physid_isset(apicid, bitmap);
+-}
+-
+-static inline unsigned long check_apicid_present(int bit)
+-{
+- return physid_isset(bit, phys_cpu_present_map);
+-}
+-
++#define TARGET_CPUS (target_cpus())
+ /*
+ * Set up the logical destination ID.
+ *
+@@ -49,23 +52,51 @@ static inline void init_apic_ldr(void)
+ apic_write_around(APIC_LDR, val);
+ }
+
+-static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map)
++static inline int apic_id_registered(void)
+ {
+- return phys_map;
++ return physid_isset(GET_APIC_ID(read_apic_id()), phys_cpu_present_map);
++}
++
++static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
++{
++ return cpus_addr(cpumask)[0];
++}
++
++static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb)
++{
++ return cpuid_apic >> index_msb;
+ }
+
+ static inline void setup_apic_routing(void)
+ {
++#ifdef CONFIG_X86_IO_APIC
+ printk("Enabling APIC mode: %s. Using %d I/O APICs\n",
+ "Flat", nr_ioapics);
++#endif
+ }
+
+-static inline int multi_timer_check(int apic, int irq)
++static inline int apicid_to_node(int logical_apicid)
+ {
+ return 0;
+ }
++#endif
+
+-static inline int apicid_to_node(int logical_apicid)
++static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid)
++{
++ return physid_isset(apicid, bitmap);
++}
++
++static inline unsigned long check_apicid_present(int bit)
++{
++ return physid_isset(bit, phys_cpu_present_map);
++}
++
++static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map)
++{
++ return phys_map;
++}
++
++static inline int multi_timer_check(int apic, int irq)
+ {
+ return 0;
+ }
+@@ -78,8 +109,13 @@ static inline int cpu_to_logical_apicid(int cpu)
+
+ static inline int cpu_present_to_apicid(int mps_cpu)
+ {
++#ifdef CONFIG_X86_64
++ if (cpu_present(mps_cpu))
++ return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu);
++#else
+ if (mps_cpu < get_physical_broadcast())
+ return mps_cpu;
++#endif
+ else
+ return BAD_APICID;
+ }
+@@ -89,17 +125,6 @@ static inline physid_mask_t apicid_to_cpu_present(int phys_apicid)
+ return physid_mask_of_physid(phys_apicid);
+ }
+
+-static inline int mpc_apic_id(struct mpc_config_processor *m,
+- struct mpc_config_translation *translation_record)
+-{
+- printk("Processor #%d %u:%u APIC version %d\n",
+- m->mpc_apicid,
+- (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8,
+- (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4,
+- m->mpc_apicver);
+- return m->mpc_apicid;
+-}
+-
+ static inline void setup_portio_remap(void)
+ {
+ }
+@@ -109,23 +134,9 @@ static inline int check_phys_apicid_present(int boot_cpu_physical_apicid)
+ return physid_isset(boot_cpu_physical_apicid, phys_cpu_present_map);
+ }
+
+-static inline int apic_id_registered(void)
+-{
+- return physid_isset(GET_APIC_ID(apic_read(APIC_ID)), phys_cpu_present_map);
+-}
+-
+-static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
+-{
+- return cpus_addr(cpumask)[0];
+-}
+-
+ static inline void enable_apic_mode(void)
+ {
+ }
+
+-static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb)
+-{
+- return cpuid_apic >> index_msb;
+-}
+-
++#endif /* CONFIG_X86_LOCAL_APIC */
+ #endif /* __ASM_MACH_APIC_H */
+diff --git a/include/asm-x86/mach-default/mach_apicdef.h b/include/asm-x86/mach-default/mach_apicdef.h
+index ae98413..e4b29ba 100644
+--- a/include/asm-x86/mach-default/mach_apicdef.h
++++ b/include/asm-x86/mach-default/mach_apicdef.h
+@@ -3,10 +3,14 @@
+
+ #include <asm/apic.h>
+
++#ifdef CONFIG_X86_64
++#define APIC_ID_MASK (0xFFu<<24)
++#define GET_APIC_ID(x) (((x)>>24)&0xFFu)
++#define SET_APIC_ID(x) (((x)<<24))
++#else
+ #define APIC_ID_MASK (0xF<<24)
+-
+ static inline unsigned get_apic_id(unsigned long x)
+-{
++{
+ unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR));
+ if (APIC_XAPIC(ver))
+ return (((x)>>24)&0xFF);
+@@ -15,5 +19,6 @@ static inline unsigned get_apic_id(unsigned long x)
+ }
+
+ #define GET_APIC_ID(x) get_apic_id(x)
++#endif
+
+ #endif
+diff --git a/include/asm-x86/mach-default/mach_ipi.h b/include/asm-x86/mach-default/mach_ipi.h
+index 0dba244..be32336 100644
+--- a/include/asm-x86/mach-default/mach_ipi.h
++++ b/include/asm-x86/mach-default/mach_ipi.h
+@@ -9,10 +9,15 @@ void __send_IPI_shortcut(unsigned int shortcut, int vector);
+
+ extern int no_broadcast;
+
++#ifdef CONFIG_X86_64
++#include <asm/genapic.h>
++#define send_IPI_mask (genapic->send_IPI_mask)
++#else
+ static inline void send_IPI_mask(cpumask_t mask, int vector)
+ {
+ send_IPI_mask_bitmask(mask, vector);
+ }
++#endif
+
+ static inline void __local_send_IPI_allbutself(int vector)
+ {
+@@ -33,6 +38,10 @@ static inline void __local_send_IPI_all(int vector)
+ __send_IPI_shortcut(APIC_DEST_ALLINC, vector);
+ }
+
++#ifdef CONFIG_X86_64
++#define send_IPI_allbutself (genapic->send_IPI_allbutself)
++#define send_IPI_all (genapic->send_IPI_all)
++#else
+ static inline void send_IPI_allbutself(int vector)
+ {
+ /*
+@@ -50,5 +59,6 @@ static inline void send_IPI_all(int vector)
+ {
+ __local_send_IPI_all(vector);
+ }
++#endif
+
+ #endif /* __ASM_MACH_IPI_H */
+diff --git a/include/asm-x86/mach-default/mach_mpparse.h b/include/asm-x86/mach-default/mach_mpparse.h
+index 1d38324..d141085 100644
+--- a/include/asm-x86/mach-default/mach_mpparse.h
++++ b/include/asm-x86/mach-default/mach_mpparse.h
+@@ -1,17 +1,6 @@
+ #ifndef __ASM_MACH_MPPARSE_H
+ #define __ASM_MACH_MPPARSE_H
+
+-static inline void mpc_oem_bus_info(struct mpc_config_bus *m, char *name,
+- struct mpc_config_translation *translation)
+-{
+-// Dprintk("Bus #%d is %s\n", m->mpc_busid, name);
+-}
+-
+-static inline void mpc_oem_pci_bus(struct mpc_config_bus *m,
+- struct mpc_config_translation *translation)
+-{
+-}
+-
+ static inline int mps_oem_check(struct mp_config_table *mpc, char *oem,
+ char *productid)
+ {
+diff --git a/include/asm-x86/mach-default/mach_reboot.h b/include/asm-x86/mach-default/mach_reboot.h
+deleted file mode 100644
+index 6adee6a..0000000
+--- a/include/asm-x86/mach-default/mach_reboot.h
++++ /dev/null
+@@ -1,61 +0,0 @@
+-/*
+- * arch/i386/mach-generic/mach_reboot.h
+- *
+- * Machine specific reboot functions for generic.
+- * Split out from reboot.c by Osamu Tomita <tomita at cinet.co.jp>
+- */
+-#ifndef _MACH_REBOOT_H
+-#define _MACH_REBOOT_H
+-
+-static inline void kb_wait(void)
+-{
+- int i;
+-
+- for (i = 0; i < 0x10000; i++)
+- if ((inb_p(0x64) & 0x02) == 0)
+- break;
+-}
+-
+-static inline void mach_reboot(void)
+-{
+- int i;
+-
+- /* old method, works on most machines */
+- for (i = 0; i < 10; i++) {
+- kb_wait();
+- udelay(50);
+- outb(0xfe, 0x64); /* pulse reset low */
+- udelay(50);
+- }
+-
+- /* New method: sets the "System flag" which, when set, indicates
+- * successful completion of the keyboard controller self-test (Basic
+- * Assurance Test, BAT). This is needed for some machines with no
+- * keyboard plugged in. This read-modify-write sequence sets only the
+- * system flag
+- */
+- for (i = 0; i < 10; i++) {
+- int cmd;
+-
+- outb(0x20, 0x64); /* read Controller Command Byte */
+- udelay(50);
+- kb_wait();
+- udelay(50);
+- cmd = inb(0x60);
+- udelay(50);
+- kb_wait();
+- udelay(50);
+- outb(0x60, 0x64); /* write Controller Command Byte */
+- udelay(50);
+- kb_wait();
+- udelay(50);
+- outb(cmd | 0x14, 0x60); /* set "System flag" and "Keyboard Disabled" */
+- udelay(50);
+- kb_wait();
+- udelay(50);
+- outb(0xfe, 0x64); /* pulse reset low */
+- udelay(50);
+- }
+-}
+-
+-#endif /* !_MACH_REBOOT_H */
+diff --git a/include/asm-x86/mach-default/smpboot_hooks.h b/include/asm-x86/mach-default/smpboot_hooks.h
+index 7f45f63..56d0e1f 100644
+--- a/include/asm-x86/mach-default/smpboot_hooks.h
++++ b/include/asm-x86/mach-default/smpboot_hooks.h
+@@ -33,7 +33,7 @@ static inline void smpboot_restore_warm_reset_vector(void)
+ *((volatile long *) phys_to_virt(0x467)) = 0;
+ }
+
+-static inline void smpboot_setup_io_apic(void)
++static inline void __init smpboot_setup_io_apic(void)
+ {
+ /*
+ * Here we can be sure that there is an IO-APIC in the system. Let's
+@@ -41,4 +41,11 @@ static inline void smpboot_setup_io_apic(void)
+ */
+ if (!skip_ioapic_setup && nr_ioapics)
+ setup_IO_APIC();
++ else
++ nr_ioapics = 0;
++}
++
++static inline void smpboot_clear_io_apic(void)
++{
++ nr_ioapics = 0;
+ }
+diff --git a/include/asm-x86/mach-es7000/mach_apic.h b/include/asm-x86/mach-es7000/mach_apic.h
+index d23011f..fbc8ad2 100644
+--- a/include/asm-x86/mach-es7000/mach_apic.h
++++ b/include/asm-x86/mach-es7000/mach_apic.h
+@@ -1,9 +1,7 @@
+ #ifndef __ASM_MACH_APIC_H
+ #define __ASM_MACH_APIC_H
+
+-extern u8 bios_cpu_apicid[];
+-
+-#define xapic_phys_to_log_apicid(cpu) (bios_cpu_apicid[cpu])
++#define xapic_phys_to_log_apicid(cpu) per_cpu(x86_bios_cpu_apicid, cpu)
+ #define esr_disable (1)
+
+ static inline int apic_id_registered(void)
+@@ -80,7 +78,7 @@ extern void enable_apic_mode(void);
+ extern int apic_version [MAX_APICS];
+ static inline void setup_apic_routing(void)
+ {
+- int apic = bios_cpu_apicid[smp_processor_id()];
++ int apic = per_cpu(x86_bios_cpu_apicid, smp_processor_id());
+ printk("Enabling APIC mode: %s. Using %d I/O APICs, target cpus %lx\n",
+ (apic_version[apic] == 0x14) ?
+ "Physical Cluster" : "Logical Cluster", nr_ioapics, cpus_addr(TARGET_CPUS)[0]);
+@@ -102,7 +100,7 @@ static inline int cpu_present_to_apicid(int mps_cpu)
+ if (!mps_cpu)
+ return boot_cpu_physical_apicid;
+ else if (mps_cpu < NR_CPUS)
+- return (int) bios_cpu_apicid[mps_cpu];
++ return (int) per_cpu(x86_bios_cpu_apicid, mps_cpu);
+ else
+ return BAD_APICID;
+ }
+@@ -129,16 +127,6 @@ static inline int cpu_to_logical_apicid(int cpu)
+ #endif
+ }
+
+-static inline int mpc_apic_id(struct mpc_config_processor *m, struct mpc_config_translation *unused)
+-{
+- printk("Processor #%d %u:%u APIC version %d\n",
+- m->mpc_apicid,
+- (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8,
+- (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4,
+- m->mpc_apicver);
+- return (m->mpc_apicid);
+-}
+-
+ static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map)
+ {
+ /* For clustered we don't have a good way to do this yet - hack */
+@@ -153,7 +141,7 @@ static inline void setup_portio_remap(void)
+ extern unsigned int boot_cpu_physical_apicid;
+ static inline int check_phys_apicid_present(int cpu_physical_apicid)
+ {
+- boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
++ boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
+ return (1);
+ }
+
+diff --git a/include/asm-x86/mach-es7000/mach_mpparse.h b/include/asm-x86/mach-es7000/mach_mpparse.h
+index 52ee75c..ef26d35 100644
+--- a/include/asm-x86/mach-es7000/mach_mpparse.h
++++ b/include/asm-x86/mach-es7000/mach_mpparse.h
+@@ -3,17 +3,6 @@
+
+ #include <linux/acpi.h>
+
+-static inline void mpc_oem_bus_info(struct mpc_config_bus *m, char *name,
+- struct mpc_config_translation *translation)
+-{
+- Dprintk("Bus #%d is %s\n", m->mpc_busid, name);
+-}
+-
+-static inline void mpc_oem_pci_bus(struct mpc_config_bus *m,
+- struct mpc_config_translation *translation)
+-{
+-}
+-
+ extern int parse_unisys_oem (char *oemptr);
+ extern int find_unisys_acpi_oem_table(unsigned long *oem_addr);
+ extern void setup_unisys(void);
+diff --git a/include/asm-x86/mach-generic/mach_apic.h b/include/asm-x86/mach-generic/mach_apic.h
+index a236e70..6eff343 100644
+--- a/include/asm-x86/mach-generic/mach_apic.h
++++ b/include/asm-x86/mach-generic/mach_apic.h
+@@ -19,7 +19,6 @@
+ #define cpu_to_logical_apicid (genapic->cpu_to_logical_apicid)
+ #define cpu_present_to_apicid (genapic->cpu_present_to_apicid)
+ #define apicid_to_cpu_present (genapic->apicid_to_cpu_present)
+-#define mpc_apic_id (genapic->mpc_apic_id)
+ #define setup_portio_remap (genapic->setup_portio_remap)
+ #define check_apicid_present (genapic->check_apicid_present)
+ #define check_phys_apicid_present (genapic->check_phys_apicid_present)
+diff --git a/include/asm-x86/mach-generic/mach_mpparse.h b/include/asm-x86/mach-generic/mach_mpparse.h
+index dbd9fce..0d0b5ba 100644
+--- a/include/asm-x86/mach-generic/mach_mpparse.h
++++ b/include/asm-x86/mach-generic/mach_mpparse.h
+@@ -1,11 +1,6 @@
+ #ifndef _MACH_MPPARSE_H
+ #define _MACH_MPPARSE_H 1
+
+-#include <asm/genapic.h>
+-
+-#define mpc_oem_bus_info (genapic->mpc_oem_bus_info)
+-#define mpc_oem_pci_bus (genapic->mpc_oem_pci_bus)
+-
+ int mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid);
+ int acpi_madt_oem_check(char *oem_id, char *oem_table_id);
+
+diff --git a/include/asm-x86/mach-numaq/mach_apic.h b/include/asm-x86/mach-numaq/mach_apic.h
+index 3b637fa..75a56e5 100644
+--- a/include/asm-x86/mach-numaq/mach_apic.h
++++ b/include/asm-x86/mach-numaq/mach_apic.h
+@@ -95,6 +95,16 @@ static inline physid_mask_t apicid_to_cpu_present(int logical_apicid)
+ return physid_mask_of_physid(cpu + 4*node);
+ }
+
++struct mpc_config_translation {
++ unsigned char mpc_type;
++ unsigned char trans_len;
++ unsigned char trans_type;
++ unsigned char trans_quad;
++ unsigned char trans_global;
++ unsigned char trans_local;
++ unsigned short trans_reserved;
++};
++
+ static inline int mpc_apic_id(struct mpc_config_processor *m,
+ struct mpc_config_translation *translation_record)
+ {
+diff --git a/include/asm-x86/mach-numaq/mach_mpparse.h b/include/asm-x86/mach-numaq/mach_mpparse.h
+index 51bbac8..459b124 100644
+--- a/include/asm-x86/mach-numaq/mach_mpparse.h
++++ b/include/asm-x86/mach-numaq/mach_mpparse.h
+@@ -1,25 +1,10 @@
+ #ifndef __ASM_MACH_MPPARSE_H
+ #define __ASM_MACH_MPPARSE_H
+
+-static inline void mpc_oem_bus_info(struct mpc_config_bus *m, char *name,
+- struct mpc_config_translation *translation)
+-{
+- int quad = translation->trans_quad;
+- int local = translation->trans_local;
+-
+- mp_bus_id_to_node[m->mpc_busid] = quad;
+- mp_bus_id_to_local[m->mpc_busid] = local;
+- printk("Bus #%d is %s (node %d)\n", m->mpc_busid, name, quad);
+-}
+-
+-static inline void mpc_oem_pci_bus(struct mpc_config_bus *m,
+- struct mpc_config_translation *translation)
+-{
+- int quad = translation->trans_quad;
+- int local = translation->trans_local;
+-
+- quad_local_to_mp_bus_id[quad][local] = m->mpc_busid;
+-}
++extern void mpc_oem_bus_info(struct mpc_config_bus *m, char *name,
++ struct mpc_config_translation *translation);
++extern void mpc_oem_pci_bus(struct mpc_config_bus *m,
++ struct mpc_config_translation *translation);
+
+ /* Hook from generic ACPI tables.c */
+ static inline void acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+diff --git a/include/asm-x86/mach-summit/mach_apic.h b/include/asm-x86/mach-summit/mach_apic.h
+index 062c97f..1f76c2e 100644
+--- a/include/asm-x86/mach-summit/mach_apic.h
++++ b/include/asm-x86/mach-summit/mach_apic.h
+@@ -40,7 +40,6 @@ static inline unsigned long check_apicid_present(int bit)
+
+ #define apicid_cluster(apicid) ((apicid) & XAPIC_DEST_CLUSTER_MASK)
+
+-extern u8 bios_cpu_apicid[];
+ extern u8 cpu_2_logical_apicid[];
+
+ static inline void init_apic_ldr(void)
+@@ -110,7 +109,7 @@ static inline int cpu_to_logical_apicid(int cpu)
+ static inline int cpu_present_to_apicid(int mps_cpu)
+ {
+ if (mps_cpu < NR_CPUS)
+- return (int)bios_cpu_apicid[mps_cpu];
++ return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu);
+ else
+ return BAD_APICID;
+ }
+@@ -126,17 +125,6 @@ static inline physid_mask_t apicid_to_cpu_present(int apicid)
+ return physid_mask_of_physid(0);
+ }
+
+-static inline int mpc_apic_id(struct mpc_config_processor *m,
+- struct mpc_config_translation *translation_record)
+-{
+- printk("Processor #%d %u:%u APIC version %d\n",
+- m->mpc_apicid,
+- (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8,
+- (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4,
+- m->mpc_apicver);
+- return m->mpc_apicid;
+-}
+-
+ static inline void setup_portio_remap(void)
+ {
+ }
+diff --git a/include/asm-x86/mach-summit/mach_mpparse.h b/include/asm-x86/mach-summit/mach_mpparse.h
+index c252053..fdf5917 100644
+--- a/include/asm-x86/mach-summit/mach_mpparse.h
++++ b/include/asm-x86/mach-summit/mach_mpparse.h
+@@ -12,17 +12,6 @@ extern void setup_summit(void);
+ #define setup_summit() {}
+ #endif
+
+-static inline void mpc_oem_bus_info(struct mpc_config_bus *m, char *name,
+- struct mpc_config_translation *translation)
+-{
+- Dprintk("Bus #%d is %s\n", m->mpc_busid, name);
+-}
+-
+-static inline void mpc_oem_pci_bus(struct mpc_config_bus *m,
+- struct mpc_config_translation *translation)
+-{
+-}
+-
+ static inline int mps_oem_check(struct mp_config_table *mpc, char *oem,
+ char *productid)
+ {
+diff --git a/include/asm-x86/mach-visws/mach_apic.h b/include/asm-x86/mach-visws/mach_apic.h
+index efac6f0..a9ef33a 100644
+--- a/include/asm-x86/mach-visws/mach_apic.h
++++ b/include/asm-x86/mach-visws/mach_apic.h
+@@ -23,7 +23,7 @@
+
+ static inline int apic_id_registered(void)
+ {
+- return physid_isset(GET_APIC_ID(apic_read(APIC_ID)), phys_cpu_present_map);
++ return physid_isset(GET_APIC_ID(read_apic_id()), phys_cpu_present_map);
+ }
+
+ /*
+diff --git a/include/asm-x86/mach-visws/smpboot_hooks.h b/include/asm-x86/mach-visws/smpboot_hooks.h
+index d926471..c9b83e3 100644
+--- a/include/asm-x86/mach-visws/smpboot_hooks.h
++++ b/include/asm-x86/mach-visws/smpboot_hooks.h
+@@ -22,3 +22,7 @@ static inline void smpboot_restore_warm_reset_vector(void)
+ static inline void smpboot_setup_io_apic(void)
+ {
+ }
++
++static inline void smpboot_clear_io_apic(void)
++{
++}
+diff --git a/include/asm-x86/mach_apic.h b/include/asm-x86/mach_apic.h
+deleted file mode 100644
+index 7b7115a..0000000
+--- a/include/asm-x86/mach_apic.h
++++ /dev/null
+@@ -1,29 +0,0 @@
+-#ifndef __ASM_MACH_APIC_H
+-#define __ASM_MACH_APIC_H
+-
+-/*
+- * Copyright 2004 James Cleverdon, IBM.
+- * Subject to the GNU Public License, v.2
+- *
+- * Generic APIC sub-arch defines.
+- *
+- * Hacked for x86-64 by James Cleverdon from i386 architecture code by
+- * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
+- * James Cleverdon.
+- */
+-
+-#include <asm/genapic.h>
+-
+-#define INT_DELIVERY_MODE (genapic->int_delivery_mode)
+-#define INT_DEST_MODE (genapic->int_dest_mode)
+-#define TARGET_CPUS (genapic->target_cpus())
+-#define vector_allocation_domain (genapic->vector_allocation_domain)
+-#define apic_id_registered (genapic->apic_id_registered)
+-#define init_apic_ldr (genapic->init_apic_ldr)
+-#define send_IPI_mask (genapic->send_IPI_mask)
+-#define send_IPI_allbutself (genapic->send_IPI_allbutself)
+-#define send_IPI_all (genapic->send_IPI_all)
+-#define cpu_mask_to_apicid (genapic->cpu_mask_to_apicid)
+-#define phys_pkg_id (genapic->phys_pkg_id)
+-
+-#endif /* __ASM_MACH_APIC_H */
+diff --git a/include/asm-x86/mc146818rtc.h b/include/asm-x86/mc146818rtc.h
+index cdd9f96..daf1ccd 100644
+--- a/include/asm-x86/mc146818rtc.h
++++ b/include/asm-x86/mc146818rtc.h
+@@ -42,7 +42,7 @@ extern volatile unsigned long cmos_lock;
+ static inline void lock_cmos(unsigned char reg)
+ {
+ unsigned long new;
+- new = ((smp_processor_id()+1) << 8) | reg;
++ new = ((smp_processor_id() + 1) << 8) | reg;
+ for (;;) {
+ if (cmos_lock) {
+ cpu_relax();
+@@ -57,22 +57,26 @@ static inline void unlock_cmos(void)
+ {
+ cmos_lock = 0;
+ }
++
+ static inline int do_i_have_lock_cmos(void)
+ {
+- return (cmos_lock >> 8) == (smp_processor_id()+1);
++ return (cmos_lock >> 8) == (smp_processor_id() + 1);
+ }
++
+ static inline unsigned char current_lock_cmos_reg(void)
+ {
+ return cmos_lock & 0xff;
+ }
+-#define lock_cmos_prefix(reg) \
++
++#define lock_cmos_prefix(reg) \
+ do { \
+ unsigned long cmos_flags; \
+ local_irq_save(cmos_flags); \
+ lock_cmos(reg)
+-#define lock_cmos_suffix(reg) \
+- unlock_cmos(); \
+- local_irq_restore(cmos_flags); \
++
++#define lock_cmos_suffix(reg) \
++ unlock_cmos(); \
++ local_irq_restore(cmos_flags); \
+ } while (0)
+ #else
+ #define lock_cmos_prefix(reg) do {} while (0)
+diff --git a/include/asm-x86/mca_dma.h b/include/asm-x86/mca_dma.h
+index fbb1f3b..c3dca6e 100644
+--- a/include/asm-x86/mca_dma.h
++++ b/include/asm-x86/mca_dma.h
+@@ -12,18 +12,18 @@
+ * count by 2 when using 16-bit dma; that is not handled by these functions.
+ *
+ * Ramen Noodles are yummy.
+- *
+- * 1998 Tymm Twillman <tymm at computer.org>
++ *
++ * 1998 Tymm Twillman <tymm at computer.org>
+ */
+
+ /*
+- * Registers that are used by the DMA controller; FN is the function register
++ * Registers that are used by the DMA controller; FN is the function register
+ * (tell the controller what to do) and EXE is the execution register (how
+ * to do it)
+ */
+
+ #define MCA_DMA_REG_FN 0x18
+-#define MCA_DMA_REG_EXE 0x1A
++#define MCA_DMA_REG_EXE 0x1A
+
+ /*
+ * Functions that the DMA controller can do
+@@ -43,9 +43,9 @@
+
+ /*
+ * Modes (used by setting MCA_DMA_FN_MODE in the function register)
+- *
++ *
+ * Note that the MODE_READ is read from memory (write to device), and
+- * MODE_WRITE is vice-versa.
++ * MODE_WRITE is vice-versa.
+ */
+
+ #define MCA_DMA_MODE_XFER 0x04 /* read by default */
+@@ -63,7 +63,7 @@
+ * IRQ context.
+ */
+
+-static __inline__ void mca_enable_dma(unsigned int dmanr)
++static inline void mca_enable_dma(unsigned int dmanr)
+ {
+ outb(MCA_DMA_FN_RESET_MASK | dmanr, MCA_DMA_REG_FN);
+ }
+@@ -76,7 +76,7 @@ static __inline__ void mca_enable_dma(unsigned int dmanr)
+ * IRQ context.
+ */
+
+-static __inline__ void mca_disable_dma(unsigned int dmanr)
++static inline void mca_disable_dma(unsigned int dmanr)
+ {
+ outb(MCA_DMA_FN_MASK | dmanr, MCA_DMA_REG_FN);
+ }
+@@ -87,10 +87,10 @@ static __inline__ void mca_disable_dma(unsigned int dmanr)
+ * @a: 24bit bus address
+ *
+ * Load the address register in the DMA controller. This has a 24bit
+- * limitation (16Mb).
++ * limitation (16Mb).
+ */
+
+-static __inline__ void mca_set_dma_addr(unsigned int dmanr, unsigned int a)
++static inline void mca_set_dma_addr(unsigned int dmanr, unsigned int a)
+ {
+ outb(MCA_DMA_FN_SET_ADDR | dmanr, MCA_DMA_REG_FN);
+ outb(a & 0xff, MCA_DMA_REG_EXE);
+@@ -106,14 +106,14 @@ static __inline__ void mca_set_dma_addr(unsigned int dmanr, unsigned int a)
+ * limitation (16Mb). The return is a bus address.
+ */
+
+-static __inline__ unsigned int mca_get_dma_addr(unsigned int dmanr)
++static inline unsigned int mca_get_dma_addr(unsigned int dmanr)
+ {
+ unsigned int addr;
+
+ outb(MCA_DMA_FN_GET_ADDR | dmanr, MCA_DMA_REG_FN);
+ addr = inb(MCA_DMA_REG_EXE);
+ addr |= inb(MCA_DMA_REG_EXE) << 8;
+- addr |= inb(MCA_DMA_REG_EXE) << 16;
++ addr |= inb(MCA_DMA_REG_EXE) << 16;
+
+ return addr;
+ }
+@@ -127,7 +127,7 @@ static __inline__ unsigned int mca_get_dma_addr(unsigned int dmanr)
+ * Setting a count of zero will not do what you expect.
+ */
+
+-static __inline__ void mca_set_dma_count(unsigned int dmanr, unsigned int count)
++static inline void mca_set_dma_count(unsigned int dmanr, unsigned int count)
+ {
+ count--; /* transfers one more than count -- correct for this */
+
+@@ -144,7 +144,7 @@ static __inline__ void mca_set_dma_count(unsigned int dmanr, unsigned int count)
+ * on this DMA channel.
+ */
+
+-static __inline__ unsigned int mca_get_dma_residue(unsigned int dmanr)
++static inline unsigned int mca_get_dma_residue(unsigned int dmanr)
+ {
+ unsigned short count;
+
+@@ -164,12 +164,12 @@ static __inline__ unsigned int mca_get_dma_residue(unsigned int dmanr)
+ * with an I/O port target.
+ */
+
+-static __inline__ void mca_set_dma_io(unsigned int dmanr, unsigned int io_addr)
++static inline void mca_set_dma_io(unsigned int dmanr, unsigned int io_addr)
+ {
+ /*
+ * DMA from a port address -- set the io address
+ */
+-
++
+ outb(MCA_DMA_FN_SET_IO | dmanr, MCA_DMA_REG_FN);
+ outb(io_addr & 0xff, MCA_DMA_REG_EXE);
+ outb((io_addr >> 8) & 0xff, MCA_DMA_REG_EXE);
+@@ -192,7 +192,7 @@ static __inline__ void mca_set_dma_io(unsigned int dmanr, unsigned int io_addr)
+ * %MCA_DMA_MODE_16 to do 16bit transfers.
+ */
+
+-static __inline__ void mca_set_dma_mode(unsigned int dmanr, unsigned int mode)
++static inline void mca_set_dma_mode(unsigned int dmanr, unsigned int mode)
+ {
+ outb(MCA_DMA_FN_SET_MODE | dmanr, MCA_DMA_REG_FN);
+ outb(mode, MCA_DMA_REG_EXE);
+diff --git a/include/asm-x86/mmu.h b/include/asm-x86/mmu.h
+index efa962c..00e8867 100644
+--- a/include/asm-x86/mmu.h
++++ b/include/asm-x86/mmu.h
+@@ -10,10 +10,10 @@
+ *
+ * cpu_vm_mask is used to optimize ldt flushing.
+ */
+-typedef struct {
++typedef struct {
+ void *ldt;
+ #ifdef CONFIG_X86_64
+- rwlock_t ldtlock;
++ rwlock_t ldtlock;
+ #endif
+ int size;
+ struct mutex lock;
+diff --git a/include/asm-x86/mmu_context_32.h b/include/asm-x86/mmu_context_32.h
+index 8198d1c..9756ae0 100644
+--- a/include/asm-x86/mmu_context_32.h
++++ b/include/asm-x86/mmu_context_32.h
+@@ -62,7 +62,7 @@ static inline void switch_mm(struct mm_struct *prev,
+ BUG_ON(per_cpu(cpu_tlbstate, cpu).active_mm != next);
+
+ if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) {
+- /* We were in lazy tlb mode and leave_mm disabled
++ /* We were in lazy tlb mode and leave_mm disabled
+ * tlb flush IPI delivery. We must reload %cr3.
+ */
+ load_cr3(next->pgd);
+@@ -75,10 +75,10 @@ static inline void switch_mm(struct mm_struct *prev,
+ #define deactivate_mm(tsk, mm) \
+ asm("movl %0,%%gs": :"r" (0));
+
+-#define activate_mm(prev, next) \
+- do { \
+- paravirt_activate_mm(prev, next); \
+- switch_mm((prev),(next),NULL); \
+- } while(0);
++#define activate_mm(prev, next) \
++do { \
++ paravirt_activate_mm((prev), (next)); \
++ switch_mm((prev), (next), NULL); \
++} while (0);
+
+ #endif
+diff --git a/include/asm-x86/mmu_context_64.h b/include/asm-x86/mmu_context_64.h
+index ad6dc82..ca44c71 100644
+--- a/include/asm-x86/mmu_context_64.h
++++ b/include/asm-x86/mmu_context_64.h
+@@ -20,12 +20,12 @@ void destroy_context(struct mm_struct *mm);
+ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+ {
+ #ifdef CONFIG_SMP
+- if (read_pda(mmu_state) == TLBSTATE_OK)
++ if (read_pda(mmu_state) == TLBSTATE_OK)
+ write_pda(mmu_state, TLBSTATE_LAZY);
+ #endif
+ }
+
+-static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
++static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+ struct task_struct *tsk)
+ {
+ unsigned cpu = smp_processor_id();
+@@ -39,7 +39,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+ cpu_set(cpu, next->cpu_vm_mask);
+ load_cr3(next->pgd);
+
+- if (unlikely(next->context.ldt != prev->context.ldt))
++ if (unlikely(next->context.ldt != prev->context.ldt))
+ load_LDT_nolock(&next->context);
+ }
+ #ifdef CONFIG_SMP
+@@ -48,7 +48,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+ if (read_pda(active_mm) != next)
+ BUG();
+ if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) {
+- /* We were in lazy tlb mode and leave_mm disabled
++ /* We were in lazy tlb mode and leave_mm disabled
+ * tlb flush IPI delivery. We must reload CR3
+ * to make sure to use no freed page tables.
+ */
+@@ -59,13 +59,14 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+ #endif
+ }
+
+-#define deactivate_mm(tsk,mm) do { \
+- load_gs_index(0); \
+- asm volatile("movl %0,%%fs"::"r"(0)); \
+-} while(0)
++#define deactivate_mm(tsk, mm) \
++do { \
++ load_gs_index(0); \
++ asm volatile("movl %0,%%fs"::"r"(0)); \
++} while (0)
+
+-#define activate_mm(prev, next) \
+- switch_mm((prev),(next),NULL)
++#define activate_mm(prev, next) \
++ switch_mm((prev), (next), NULL)
+
+
+ #endif
+diff --git a/include/asm-x86/mmx.h b/include/asm-x86/mmx.h
+index 46b71da..9408812 100644
+--- a/include/asm-x86/mmx.h
++++ b/include/asm-x86/mmx.h
+@@ -6,7 +6,7 @@
+ */
+
+ #include <linux/types.h>
+-
++
+ extern void *_mmx_memcpy(void *to, const void *from, size_t size);
+ extern void mmx_clear_page(void *page);
+ extern void mmx_copy_page(void *to, void *from);
+diff --git a/include/asm-x86/mmzone_32.h b/include/asm-x86/mmzone_32.h
+index 274a595..cb2cad0 100644
+--- a/include/asm-x86/mmzone_32.h
++++ b/include/asm-x86/mmzone_32.h
+@@ -18,7 +18,7 @@ extern struct pglist_data *node_data[];
+ #include <asm/srat.h>
+ #endif
+
+-extern int get_memcfg_numa_flat(void );
++extern int get_memcfg_numa_flat(void);
+ /*
+ * This allows any one NUMA architecture to be compiled
+ * for, and still fall back to the flat function if it
+@@ -129,7 +129,7 @@ static inline int pfn_valid(int pfn)
+ struct pglist_data __maybe_unused \
+ *__alloc_bootmem_node__pgdat = (pgdat); \
+ __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, \
+- __pa(MAX_DMA_ADDRESS)) \
++ __pa(MAX_DMA_ADDRESS)); \
+ })
+ #define alloc_bootmem_low_pages_node(pgdat, x) \
+ ({ \
+diff --git a/include/asm-x86/mmzone_64.h b/include/asm-x86/mmzone_64.h
+index ebaf966..594bd0d 100644
+--- a/include/asm-x86/mmzone_64.h
++++ b/include/asm-x86/mmzone_64.h
+@@ -7,7 +7,7 @@
+
+ #ifdef CONFIG_NUMA
+
+-#define VIRTUAL_BUG_ON(x)
++#define VIRTUAL_BUG_ON(x)
+
+ #include <asm/smp.h>
+
+@@ -16,7 +16,7 @@ struct memnode {
+ int shift;
+ unsigned int mapsize;
+ s16 *map;
+- s16 embedded_map[64-8];
++ s16 embedded_map[64 - 8];
+ } ____cacheline_aligned; /* total size = 128 bytes */
+ extern struct memnode memnode;
+ #define memnode_shift memnode.shift
+@@ -25,27 +25,27 @@ extern struct memnode memnode;
+
+ extern struct pglist_data *node_data[];
+
+-static inline __attribute__((pure)) int phys_to_nid(unsigned long addr)
+-{
+- unsigned nid;
++static inline __attribute__((pure)) int phys_to_nid(unsigned long addr)
++{
++ unsigned nid;
+ VIRTUAL_BUG_ON(!memnodemap);
+ VIRTUAL_BUG_ON((addr >> memnode_shift) >= memnodemapsize);
+- nid = memnodemap[addr >> memnode_shift];
+- VIRTUAL_BUG_ON(nid >= MAX_NUMNODES || !node_data[nid]);
+- return nid;
+-}
++ nid = memnodemap[addr >> memnode_shift];
++ VIRTUAL_BUG_ON(nid >= MAX_NUMNODES || !node_data[nid]);
++ return nid;
++}
+
+ #define NODE_DATA(nid) (node_data[nid])
+
+ #define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn)
+-#define node_end_pfn(nid) (NODE_DATA(nid)->node_start_pfn + \
++#define node_end_pfn(nid) (NODE_DATA(nid)->node_start_pfn + \
+ NODE_DATA(nid)->node_spanned_pages)
+
+ extern int early_pfn_to_nid(unsigned long pfn);
+
+ #ifdef CONFIG_NUMA_EMU
+-#define FAKE_NODE_MIN_SIZE (64*1024*1024)
+-#define FAKE_NODE_MIN_HASH_MASK (~(FAKE_NODE_MIN_SIZE - 1uL))
++#define FAKE_NODE_MIN_SIZE (64 * 1024 * 1024)
++#define FAKE_NODE_MIN_HASH_MASK (~(FAKE_NODE_MIN_SIZE - 1UL))
+ #endif
+
+ #endif
+diff --git a/include/asm-x86/mpspec.h b/include/asm-x86/mpspec.h
+index 781ad74..57a991b 100644
+--- a/include/asm-x86/mpspec.h
++++ b/include/asm-x86/mpspec.h
+@@ -1,16 +1,13 @@
+ #ifndef _AM_X86_MPSPEC_H
+ #define _AM_X86_MPSPEC_H
+
++#include <linux/init.h>
++
+ #include <asm/mpspec_def.h>
+
+ #ifdef CONFIG_X86_32
+ #include <mach_mpspec.h>
+
+-extern int mp_bus_id_to_type[MAX_MP_BUSSES];
+-extern int mp_bus_id_to_node[MAX_MP_BUSSES];
+-extern int mp_bus_id_to_local[MAX_MP_BUSSES];
+-extern int quad_local_to_mp_bus_id[NR_CPUS/4][4];
+-
+ extern unsigned int def_to_bigsmp;
+ extern int apic_version[MAX_APICS];
+ extern u8 apicid_2_node[];
+@@ -24,27 +21,30 @@ extern int pic_mode;
+ /* Each PCI slot may be a combo card with its own bus. 4 IRQ pins per slot. */
+ #define MAX_IRQ_SOURCES (MAX_MP_BUSSES * 4)
+
+-extern DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
++extern void early_find_smp_config(void);
++extern void early_get_smp_config(void);
+
+ #endif
+
++#if defined(CONFIG_MCA) || defined(CONFIG_EISA)
++extern int mp_bus_id_to_type[MAX_MP_BUSSES];
++#endif
++
++extern DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
++
+ extern int mp_bus_id_to_pci_bus[MAX_MP_BUSSES];
+
+ extern unsigned int boot_cpu_physical_apicid;
+ extern int smp_found_config;
+-extern int nr_ioapics;
+-extern int mp_irq_entries;
+-extern struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
+ extern int mpc_default_type;
+ extern unsigned long mp_lapic_addr;
+
+ extern void find_smp_config(void);
+ extern void get_smp_config(void);
+
++void __cpuinit generic_processor_info(int apicid, int version);
+ #ifdef CONFIG_ACPI
+-extern void mp_register_lapic(u8 id, u8 enabled);
+-extern void mp_register_lapic_address(u64 address);
+-extern void mp_register_ioapic(u8 id, u32 address, u32 gsi_base);
++extern void mp_register_ioapic(int id, u32 address, u32 gsi_base);
+ extern void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
+ u32 gsi);
+ extern void mp_config_acpi_legacy_irqs(void);
+@@ -53,8 +53,7 @@ extern int mp_register_gsi(u32 gsi, int edge_level, int active_high_low);
+
+ #define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_APICS)
+
+-struct physid_mask
+-{
++struct physid_mask {
+ unsigned long mask[PHYSID_ARRAY_SIZE];
+ };
+
+@@ -63,34 +62,34 @@ typedef struct physid_mask physid_mask_t;
+ #define physid_set(physid, map) set_bit(physid, (map).mask)
+ #define physid_clear(physid, map) clear_bit(physid, (map).mask)
+ #define physid_isset(physid, map) test_bit(physid, (map).mask)
+-#define physid_test_and_set(physid, map) \
++#define physid_test_and_set(physid, map) \
+ test_and_set_bit(physid, (map).mask)
+
+-#define physids_and(dst, src1, src2) \
++#define physids_and(dst, src1, src2) \
+ bitmap_and((dst).mask, (src1).mask, (src2).mask, MAX_APICS)
+
+-#define physids_or(dst, src1, src2) \
++#define physids_or(dst, src1, src2) \
+ bitmap_or((dst).mask, (src1).mask, (src2).mask, MAX_APICS)
+
+-#define physids_clear(map) \
++#define physids_clear(map) \
+ bitmap_zero((map).mask, MAX_APICS)
+
+-#define physids_complement(dst, src) \
++#define physids_complement(dst, src) \
+ bitmap_complement((dst).mask, (src).mask, MAX_APICS)
+
+-#define physids_empty(map) \
++#define physids_empty(map) \
+ bitmap_empty((map).mask, MAX_APICS)
+
+-#define physids_equal(map1, map2) \
++#define physids_equal(map1, map2) \
+ bitmap_equal((map1).mask, (map2).mask, MAX_APICS)
+
+-#define physids_weight(map) \
++#define physids_weight(map) \
+ bitmap_weight((map).mask, MAX_APICS)
+
+-#define physids_shift_right(d, s, n) \
++#define physids_shift_right(d, s, n) \
+ bitmap_shift_right((d).mask, (s).mask, n, MAX_APICS)
+
+-#define physids_shift_left(d, s, n) \
++#define physids_shift_left(d, s, n) \
+ bitmap_shift_left((d).mask, (s).mask, n, MAX_APICS)
+
+ #define physids_coerce(map) ((map).mask[0])
+diff --git a/include/asm-x86/mpspec_def.h b/include/asm-x86/mpspec_def.h
+index 3504617..dc6ef85 100644
+--- a/include/asm-x86/mpspec_def.h
++++ b/include/asm-x86/mpspec_def.h
+@@ -11,7 +11,7 @@
+ * information is.
+ */
+
+-#define SMP_MAGIC_IDENT (('_'<<24)|('P'<<16)|('M'<<8)|'_')
++#define SMP_MAGIC_IDENT (('_'<<24) | ('P'<<16) | ('M'<<8) | '_')
+
+ #ifdef CONFIG_X86_32
+ # define MAX_MPC_ENTRY 1024
+@@ -23,8 +23,7 @@
+ # define MAX_APICS 255
+ #endif
+
+-struct intel_mp_floating
+-{
++struct intel_mp_floating {
+ char mpf_signature[4]; /* "_MP_" */
+ unsigned int mpf_physptr; /* Configuration table address */
+ unsigned char mpf_length; /* Our length (paragraphs) */
+@@ -39,14 +38,13 @@ struct intel_mp_floating
+
+ #define MPC_SIGNATURE "PCMP"
+
+-struct mp_config_table
+-{
++struct mp_config_table {
+ char mpc_signature[4];
+ unsigned short mpc_length; /* Size of table */
+- char mpc_spec; /* 0x01 */
+- char mpc_checksum;
+- char mpc_oem[8];
+- char mpc_productid[12];
++ char mpc_spec; /* 0x01 */
++ char mpc_checksum;
++ char mpc_oem[8];
++ char mpc_productid[12];
+ unsigned int mpc_oemptr; /* 0 if not present */
+ unsigned short mpc_oemsize; /* 0 if not present */
+ unsigned short mpc_oemcount;
+@@ -71,8 +69,7 @@ struct mp_config_table
+ #define CPU_MODEL_MASK 0x00F0
+ #define CPU_FAMILY_MASK 0x0F00
+
+-struct mpc_config_processor
+-{
++struct mpc_config_processor {
+ unsigned char mpc_type;
+ unsigned char mpc_apicid; /* Local APIC number */
+ unsigned char mpc_apicver; /* Its versions */
+@@ -82,8 +79,7 @@ struct mpc_config_processor
+ unsigned int mpc_reserved[2];
+ };
+
+-struct mpc_config_bus
+-{
++struct mpc_config_bus {
+ unsigned char mpc_type;
+ unsigned char mpc_busid;
+ unsigned char mpc_bustype[6];
+@@ -111,8 +107,7 @@ struct mpc_config_bus
+
+ #define MPC_APIC_USABLE 0x01
+
+-struct mpc_config_ioapic
+-{
++struct mpc_config_ioapic {
+ unsigned char mpc_type;
+ unsigned char mpc_apicid;
+ unsigned char mpc_apicver;
+@@ -120,8 +115,7 @@ struct mpc_config_ioapic
+ unsigned int mpc_apicaddr;
+ };
+
+-struct mpc_config_intsrc
+-{
++struct mpc_config_intsrc {
+ unsigned char mpc_type;
+ unsigned char mpc_irqtype;
+ unsigned short mpc_irqflag;
+@@ -144,8 +138,7 @@ enum mp_irq_source_types {
+
+ #define MP_APIC_ALL 0xFF
+
+-struct mpc_config_lintsrc
+-{
++struct mpc_config_lintsrc {
+ unsigned char mpc_type;
+ unsigned char mpc_irqtype;
+ unsigned short mpc_irqflag;
+@@ -157,8 +150,7 @@ struct mpc_config_lintsrc
+
+ #define MPC_OEM_SIGNATURE "_OEM"
+
+-struct mp_config_oemtable
+-{
++struct mp_config_oemtable {
+ char oem_signature[4];
+ unsigned short oem_length; /* Size of table */
+ char oem_rev; /* 0x01 */
+@@ -166,17 +158,6 @@ struct mp_config_oemtable
+ char mpc_oem[8];
+ };
+
+-struct mpc_config_translation
+-{
+- unsigned char mpc_type;
+- unsigned char trans_len;
+- unsigned char trans_type;
+- unsigned char trans_quad;
+- unsigned char trans_global;
+- unsigned char trans_local;
+- unsigned short trans_reserved;
+-};
+-
+ /*
+ * Default configurations
+ *
+@@ -196,4 +177,3 @@ enum mp_bustype {
+ MP_BUS_MCA,
+ };
+ #endif
+-
+diff --git a/include/asm-x86/msidef.h b/include/asm-x86/msidef.h
+index 5b8acdd..296f29c 100644
+--- a/include/asm-x86/msidef.h
++++ b/include/asm-x86/msidef.h
+@@ -11,7 +11,8 @@
+
+ #define MSI_DATA_VECTOR_SHIFT 0
+ #define MSI_DATA_VECTOR_MASK 0x000000ff
+-#define MSI_DATA_VECTOR(v) (((v) << MSI_DATA_VECTOR_SHIFT) & MSI_DATA_VECTOR_MASK)
++#define MSI_DATA_VECTOR(v) (((v) << MSI_DATA_VECTOR_SHIFT) & \
++ MSI_DATA_VECTOR_MASK)
+
+ #define MSI_DATA_DELIVERY_MODE_SHIFT 8
+ #define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_MODE_SHIFT)
+@@ -37,11 +38,14 @@
+ #define MSI_ADDR_DEST_MODE_LOGICAL (1 << MSI_ADDR_DEST_MODE_SHIFT)
+
+ #define MSI_ADDR_REDIRECTION_SHIFT 3
+-#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT) /* dedicated cpu */
+-#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT) /* lowest priority */
++#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT)
++ /* dedicated cpu */
++#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT)
++ /* lowest priority */
+
+ #define MSI_ADDR_DEST_ID_SHIFT 12
+ #define MSI_ADDR_DEST_ID_MASK 0x00ffff0
+-#define MSI_ADDR_DEST_ID(dest) (((dest) << MSI_ADDR_DEST_ID_SHIFT) & MSI_ADDR_DEST_ID_MASK)
++#define MSI_ADDR_DEST_ID(dest) (((dest) << MSI_ADDR_DEST_ID_SHIFT) & \
++ MSI_ADDR_DEST_ID_MASK)
+
+ #endif /* ASM_MSIDEF_H */
+diff --git a/include/asm-x86/msr-index.h b/include/asm-x86/msr-index.h
+index fae118a..09413ad 100644
+--- a/include/asm-x86/msr-index.h
++++ b/include/asm-x86/msr-index.h
+@@ -57,6 +57,8 @@
+ #define MSR_MTRRfix4K_F8000 0x0000026f
+ #define MSR_MTRRdefType 0x000002ff
+
++#define MSR_IA32_CR_PAT 0x00000277
++
+ #define MSR_IA32_DEBUGCTLMSR 0x000001d9
+ #define MSR_IA32_LASTBRANCHFROMIP 0x000001db
+ #define MSR_IA32_LASTBRANCHTOIP 0x000001dc
+@@ -83,6 +85,7 @@
+ /* AMD64 MSRs. Not complete. See the architecture manual for a more
+ complete list. */
+
++#define MSR_AMD64_NB_CFG 0xc001001f
+ #define MSR_AMD64_IBSFETCHCTL 0xc0011030
+ #define MSR_AMD64_IBSFETCHLINAD 0xc0011031
+ #define MSR_AMD64_IBSFETCHPHYSAD 0xc0011032
+@@ -109,6 +112,7 @@
+ #define MSR_K8_SYSCFG 0xc0010010
+ #define MSR_K8_HWCR 0xc0010015
+ #define MSR_K8_ENABLE_C1E 0xc0010055
++#define MSR_K8_TSEG_ADDR 0xc0010112
+ #define K8_MTRRFIXRANGE_DRAM_ENABLE 0x00040000 /* MtrrFixDramEn bit */
+ #define K8_MTRRFIXRANGE_DRAM_MODIFY 0x00080000 /* MtrrFixDramModEn bit */
+ #define K8_MTRR_RDMEM_WRMEM_MASK 0x18181818 /* Mask: RdMem|WrMem */
+diff --git a/include/asm-x86/msr.h b/include/asm-x86/msr.h
+index 3ca29eb..3707650 100644
+--- a/include/asm-x86/msr.h
++++ b/include/asm-x86/msr.h
+@@ -16,8 +16,8 @@
+ static inline unsigned long long native_read_tscp(unsigned int *aux)
+ {
+ unsigned long low, high;
+- asm volatile (".byte 0x0f,0x01,0xf9"
+- : "=a" (low), "=d" (high), "=c" (*aux));
++ asm volatile(".byte 0x0f,0x01,0xf9"
++ : "=a" (low), "=d" (high), "=c" (*aux));
+ return low | ((u64)high >> 32);
+ }
+
+@@ -29,7 +29,7 @@ static inline unsigned long long native_read_tscp(unsigned int *aux)
+ */
+ #ifdef CONFIG_X86_64
+ #define DECLARE_ARGS(val, low, high) unsigned low, high
+-#define EAX_EDX_VAL(val, low, high) (low | ((u64)(high) << 32))
++#define EAX_EDX_VAL(val, low, high) ((low) | ((u64)(high) << 32))
+ #define EAX_EDX_ARGS(val, low, high) "a" (low), "d" (high)
+ #define EAX_EDX_RET(val, low, high) "=a" (low), "=d" (high)
+ #else
+@@ -57,7 +57,7 @@ static inline unsigned long long native_read_msr_safe(unsigned int msr,
+ ".section .fixup,\"ax\"\n\t"
+ "3: mov %3,%0 ; jmp 1b\n\t"
+ ".previous\n\t"
+- _ASM_EXTABLE(2b,3b)
++ _ASM_EXTABLE(2b, 3b)
+ : "=r" (*err), EAX_EDX_RET(val, low, high)
+ : "c" (msr), "i" (-EFAULT));
+ return EAX_EDX_VAL(val, low, high);
+@@ -78,10 +78,10 @@ static inline int native_write_msr_safe(unsigned int msr,
+ ".section .fixup,\"ax\"\n\t"
+ "3: mov %4,%0 ; jmp 1b\n\t"
+ ".previous\n\t"
+- _ASM_EXTABLE(2b,3b)
++ _ASM_EXTABLE(2b, 3b)
+ : "=a" (err)
+ : "c" (msr), "0" (low), "d" (high),
+- "i" (-EFAULT));
++ "i" (-EFAULT));
+ return err;
+ }
+
+@@ -116,23 +116,23 @@ static inline unsigned long long native_read_pmc(int counter)
+ * pointer indirection), this allows gcc to optimize better
+ */
+
+-#define rdmsr(msr,val1,val2) \
+- do { \
+- u64 __val = native_read_msr(msr); \
+- (val1) = (u32)__val; \
+- (val2) = (u32)(__val >> 32); \
+- } while(0)
++#define rdmsr(msr, val1, val2) \
++do { \
++ u64 __val = native_read_msr((msr)); \
++ (val1) = (u32)__val; \
++ (val2) = (u32)(__val >> 32); \
++} while (0)
+
+ static inline void wrmsr(unsigned msr, unsigned low, unsigned high)
+ {
+ native_write_msr(msr, low, high);
+ }
+
+-#define rdmsrl(msr,val) \
+- ((val) = native_read_msr(msr))
++#define rdmsrl(msr, val) \
++ ((val) = native_read_msr((msr)))
+
+ #define wrmsrl(msr, val) \
+- native_write_msr(msr, (u32)((u64)(val)), (u32)((u64)(val) >> 32))
++ native_write_msr((msr), (u32)((u64)(val)), (u32)((u64)(val) >> 32))
+
+ /* wrmsr with exception handling */
+ static inline int wrmsr_safe(unsigned msr, unsigned low, unsigned high)
+@@ -141,14 +141,22 @@ static inline int wrmsr_safe(unsigned msr, unsigned low, unsigned high)
+ }
+
+ /* rdmsr with exception handling */
+-#define rdmsr_safe(msr,p1,p2) \
+- ({ \
+- int __err; \
+- u64 __val = native_read_msr_safe(msr, &__err); \
+- (*p1) = (u32)__val; \
+- (*p2) = (u32)(__val >> 32); \
+- __err; \
+- })
++#define rdmsr_safe(msr, p1, p2) \
++({ \
++ int __err; \
++ u64 __val = native_read_msr_safe((msr), &__err); \
++ (*p1) = (u32)__val; \
++ (*p2) = (u32)(__val >> 32); \
++ __err; \
++})
++
++static inline int rdmsrl_safe(unsigned msr, unsigned long long *p)
++{
++ int err;
++
++ *p = native_read_msr_safe(msr, &err);
++ return err;
++}
+
+ #define rdtscl(low) \
+ ((low) = (u32)native_read_tsc())
+@@ -156,35 +164,37 @@ static inline int wrmsr_safe(unsigned msr, unsigned low, unsigned high)
+ #define rdtscll(val) \
+ ((val) = native_read_tsc())
+
+-#define rdpmc(counter,low,high) \
+- do { \
+- u64 _l = native_read_pmc(counter); \
+- (low) = (u32)_l; \
+- (high) = (u32)(_l >> 32); \
+- } while(0)
++#define rdpmc(counter, low, high) \
++do { \
++ u64 _l = native_read_pmc((counter)); \
++ (low) = (u32)_l; \
++ (high) = (u32)(_l >> 32); \
++} while (0)
+
+-#define rdtscp(low, high, aux) \
+- do { \
+- unsigned long long _val = native_read_tscp(&(aux)); \
+- (low) = (u32)_val; \
+- (high) = (u32)(_val >> 32); \
+- } while (0)
++#define rdtscp(low, high, aux) \
++do { \
++ unsigned long long _val = native_read_tscp(&(aux)); \
++ (low) = (u32)_val; \
++ (high) = (u32)(_val >> 32); \
++} while (0)
+
+ #define rdtscpll(val, aux) (val) = native_read_tscp(&(aux))
+
+ #endif /* !CONFIG_PARAVIRT */
+
+
+-#define checking_wrmsrl(msr,val) wrmsr_safe(msr,(u32)(val),(u32)((val)>>32))
++#define checking_wrmsrl(msr, val) wrmsr_safe((msr), (u32)(val), \
++ (u32)((val) >> 32))
+
+-#define write_tsc(val1,val2) wrmsr(0x10, val1, val2)
++#define write_tsc(val1, val2) wrmsr(0x10, (val1), (val2))
+
+-#define write_rdtscp_aux(val) wrmsr(0xc0000103, val, 0)
++#define write_rdtscp_aux(val) wrmsr(0xc0000103, (val), 0)
+
+ #ifdef CONFIG_SMP
+ void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
+ void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
+ int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
++
+ int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
+ #else /* CONFIG_SMP */
+ static inline void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
+@@ -195,7 +205,8 @@ static inline void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
+ {
+ wrmsr(msr_no, l, h);
+ }
+-static inline int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
++static inline int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no,
++ u32 *l, u32 *h)
+ {
+ return rdmsr_safe(msr_no, l, h);
+ }
+diff --git a/include/asm-x86/mtrr.h b/include/asm-x86/mtrr.h
+index 319d065..a69a01a 100644
+--- a/include/asm-x86/mtrr.h
++++ b/include/asm-x86/mtrr.h
+@@ -28,8 +28,7 @@
+
+ #define MTRR_IOCTL_BASE 'M'
+
+-struct mtrr_sentry
+-{
++struct mtrr_sentry {
+ unsigned long base; /* Base address */
+ unsigned int size; /* Size of region */
+ unsigned int type; /* Type of region */
+@@ -41,8 +40,7 @@ struct mtrr_sentry
+ will break. */
+
+ #ifdef __i386__
+-struct mtrr_gentry
+-{
++struct mtrr_gentry {
+ unsigned int regnum; /* Register number */
+ unsigned long base; /* Base address */
+ unsigned int size; /* Size of region */
+@@ -51,8 +49,7 @@ struct mtrr_gentry
+
+ #else /* __i386__ */
+
+-struct mtrr_gentry
+-{
++struct mtrr_gentry {
+ unsigned long base; /* Base address */
+ unsigned int size; /* Size of region */
+ unsigned int regnum; /* Register number */
+@@ -86,38 +83,45 @@ struct mtrr_gentry
+
+ /* The following functions are for use by other drivers */
+ # ifdef CONFIG_MTRR
++extern u8 mtrr_type_lookup(u64 addr, u64 end);
+ extern void mtrr_save_fixed_ranges(void *);
+ extern void mtrr_save_state(void);
+-extern int mtrr_add (unsigned long base, unsigned long size,
+- unsigned int type, bool increment);
+-extern int mtrr_add_page (unsigned long base, unsigned long size,
+- unsigned int type, bool increment);
+-extern int mtrr_del (int reg, unsigned long base, unsigned long size);
+-extern int mtrr_del_page (int reg, unsigned long base, unsigned long size);
++extern int mtrr_add(unsigned long base, unsigned long size,
++ unsigned int type, bool increment);
++extern int mtrr_add_page(unsigned long base, unsigned long size,
++ unsigned int type, bool increment);
++extern int mtrr_del(int reg, unsigned long base, unsigned long size);
++extern int mtrr_del_page(int reg, unsigned long base, unsigned long size);
+ extern void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi);
+ extern void mtrr_ap_init(void);
+ extern void mtrr_bp_init(void);
+ extern int mtrr_trim_uncached_memory(unsigned long end_pfn);
++extern int amd_special_default_mtrr(void);
+ # else
++static inline u8 mtrr_type_lookup(u64 addr, u64 end)
++{
++ /*
++ * Return no-MTRRs:
++ */
++ return 0xff;
++}
+ #define mtrr_save_fixed_ranges(arg) do {} while (0)
+ #define mtrr_save_state() do {} while (0)
+-static __inline__ int mtrr_add (unsigned long base, unsigned long size,
+- unsigned int type, bool increment)
++static inline int mtrr_add(unsigned long base, unsigned long size,
++ unsigned int type, bool increment)
+ {
+ return -ENODEV;
+ }
+-static __inline__ int mtrr_add_page (unsigned long base, unsigned long size,
++static inline int mtrr_add_page(unsigned long base, unsigned long size,
+ unsigned int type, bool increment)
+ {
+ return -ENODEV;
+ }
+-static __inline__ int mtrr_del (int reg, unsigned long base,
+- unsigned long size)
++static inline int mtrr_del(int reg, unsigned long base, unsigned long size)
+ {
+ return -ENODEV;
+ }
+-static __inline__ int mtrr_del_page (int reg, unsigned long base,
+- unsigned long size)
++static inline int mtrr_del_page(int reg, unsigned long base, unsigned long size)
+ {
+ return -ENODEV;
+ }
+@@ -125,7 +129,9 @@ static inline int mtrr_trim_uncached_memory(unsigned long end_pfn)
+ {
+ return 0;
+ }
+-static __inline__ void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi) {;}
++static inline void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi)
++{
++}
+
+ #define mtrr_ap_init() do {} while (0)
+ #define mtrr_bp_init() do {} while (0)
+@@ -134,15 +140,13 @@ static __inline__ void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi) {;}
+ #ifdef CONFIG_COMPAT
+ #include <linux/compat.h>
+
+-struct mtrr_sentry32
+-{
++struct mtrr_sentry32 {
+ compat_ulong_t base; /* Base address */
+ compat_uint_t size; /* Size of region */
+ compat_uint_t type; /* Type of region */
+ };
+
+-struct mtrr_gentry32
+-{
++struct mtrr_gentry32 {
+ compat_ulong_t regnum; /* Register number */
+ compat_uint_t base; /* Base address */
+ compat_uint_t size; /* Size of region */
+@@ -151,16 +155,17 @@ struct mtrr_gentry32
+
+ #define MTRR_IOCTL_BASE 'M'
+
+-#define MTRRIOC32_ADD_ENTRY _IOW(MTRR_IOCTL_BASE, 0, struct mtrr_sentry32)
+-#define MTRRIOC32_SET_ENTRY _IOW(MTRR_IOCTL_BASE, 1, struct mtrr_sentry32)
+-#define MTRRIOC32_DEL_ENTRY _IOW(MTRR_IOCTL_BASE, 2, struct mtrr_sentry32)
+-#define MTRRIOC32_GET_ENTRY _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry32)
+-#define MTRRIOC32_KILL_ENTRY _IOW(MTRR_IOCTL_BASE, 4, struct mtrr_sentry32)
+-#define MTRRIOC32_ADD_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 5, struct mtrr_sentry32)
+-#define MTRRIOC32_SET_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 6, struct mtrr_sentry32)
+-#define MTRRIOC32_DEL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 7, struct mtrr_sentry32)
+-#define MTRRIOC32_GET_PAGE_ENTRY _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry32)
+-#define MTRRIOC32_KILL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 9, struct mtrr_sentry32)
++#define MTRRIOC32_ADD_ENTRY _IOW(MTRR_IOCTL_BASE, 0, struct mtrr_sentry32)
++#define MTRRIOC32_SET_ENTRY _IOW(MTRR_IOCTL_BASE, 1, struct mtrr_sentry32)
++#define MTRRIOC32_DEL_ENTRY _IOW(MTRR_IOCTL_BASE, 2, struct mtrr_sentry32)
++#define MTRRIOC32_GET_ENTRY _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry32)
++#define MTRRIOC32_KILL_ENTRY _IOW(MTRR_IOCTL_BASE, 4, struct mtrr_sentry32)
++#define MTRRIOC32_ADD_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 5, struct mtrr_sentry32)
++#define MTRRIOC32_SET_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 6, struct mtrr_sentry32)
++#define MTRRIOC32_DEL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 7, struct mtrr_sentry32)
++#define MTRRIOC32_GET_PAGE_ENTRY _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry32)
++#define MTRRIOC32_KILL_PAGE_ENTRY \
++ _IOW(MTRR_IOCTL_BASE, 9, struct mtrr_sentry32)
+ #endif /* CONFIG_COMPAT */
+
+ #endif /* __KERNEL__ */
+diff --git a/include/asm-x86/mutex_32.h b/include/asm-x86/mutex_32.h
+index bbeefb9..73e928e 100644
+--- a/include/asm-x86/mutex_32.h
++++ b/include/asm-x86/mutex_32.h
+@@ -9,7 +9,7 @@
+ #ifndef _ASM_MUTEX_H
+ #define _ASM_MUTEX_H
+
+-#include "asm/alternative.h"
++#include <asm/alternative.h>
+
+ /**
+ * __mutex_fastpath_lock - try to take the lock by moving the count
+@@ -21,22 +21,20 @@
+ * wasn't 1 originally. This function MUST leave the value lower than 1
+ * even when the "1" assertion wasn't true.
+ */
+-#define __mutex_fastpath_lock(count, fail_fn) \
+-do { \
+- unsigned int dummy; \
+- \
+- typecheck(atomic_t *, count); \
++#define __mutex_fastpath_lock(count, fail_fn) \
++do { \
++ unsigned int dummy; \
++ \
++ typecheck(atomic_t *, count); \
+ typecheck_fn(void (*)(atomic_t *), fail_fn); \
+- \
+- __asm__ __volatile__( \
+- LOCK_PREFIX " decl (%%eax) \n" \
+- " jns 1f \n" \
+- " call "#fail_fn" \n" \
+- "1: \n" \
+- \
+- :"=a" (dummy) \
+- : "a" (count) \
+- : "memory", "ecx", "edx"); \
++ \
++ asm volatile(LOCK_PREFIX " decl (%%eax)\n" \
++ " jns 1f \n" \
++ " call " #fail_fn "\n" \
++ "1:\n" \
++ : "=a" (dummy) \
++ : "a" (count) \
++ : "memory", "ecx", "edx"); \
+ } while (0)
+
+
+@@ -50,8 +48,8 @@ do { \
+ * wasn't 1 originally. This function returns 0 if the fastpath succeeds,
+ * or anything the slow path function returns
+ */
+-static inline int
+-__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
++static inline int __mutex_fastpath_lock_retval(atomic_t *count,
++ int (*fail_fn)(atomic_t *))
+ {
+ if (unlikely(atomic_dec_return(count) < 0))
+ return fail_fn(count);
+@@ -72,22 +70,20 @@ __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
+ * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs
+ * to return 0 otherwise.
+ */
+-#define __mutex_fastpath_unlock(count, fail_fn) \
+-do { \
+- unsigned int dummy; \
+- \
+- typecheck(atomic_t *, count); \
++#define __mutex_fastpath_unlock(count, fail_fn) \
++do { \
++ unsigned int dummy; \
++ \
++ typecheck(atomic_t *, count); \
+ typecheck_fn(void (*)(atomic_t *), fail_fn); \
+- \
+- __asm__ __volatile__( \
+- LOCK_PREFIX " incl (%%eax) \n" \
+- " jg 1f \n" \
+- " call "#fail_fn" \n" \
+- "1: \n" \
+- \
+- :"=a" (dummy) \
+- : "a" (count) \
+- : "memory", "ecx", "edx"); \
++ \
++ asm volatile(LOCK_PREFIX " incl (%%eax)\n" \
++ " jg 1f\n" \
++ " call " #fail_fn "\n" \
++ "1:\n" \
++ : "=a" (dummy) \
++ : "a" (count) \
++ : "memory", "ecx", "edx"); \
+ } while (0)
+
+ #define __mutex_slowpath_needs_to_unlock() 1
+@@ -104,8 +100,8 @@ do { \
+ * Additionally, if the value was < 0 originally, this function must not leave
+ * it to 0 on failure.
+ */
+-static inline int
+-__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
++static inline int __mutex_fastpath_trylock(atomic_t *count,
++ int (*fail_fn)(atomic_t *))
+ {
+ /*
+ * We have two variants here. The cmpxchg based one is the best one
+diff --git a/include/asm-x86/mutex_64.h b/include/asm-x86/mutex_64.h
+index 6c2949a..f3fae9b 100644
+--- a/include/asm-x86/mutex_64.h
++++ b/include/asm-x86/mutex_64.h
+@@ -16,23 +16,21 @@
+ *
+ * Atomically decrements @v and calls <fail_fn> if the result is negative.
+ */
+-#define __mutex_fastpath_lock(v, fail_fn) \
+-do { \
+- unsigned long dummy; \
+- \
+- typecheck(atomic_t *, v); \
+- typecheck_fn(void (*)(atomic_t *), fail_fn); \
+- \
+- __asm__ __volatile__( \
+- LOCK_PREFIX " decl (%%rdi) \n" \
+- " jns 1f \n" \
+- " call "#fail_fn" \n" \
+- "1:" \
+- \
+- :"=D" (dummy) \
+- : "D" (v) \
+- : "rax", "rsi", "rdx", "rcx", \
+- "r8", "r9", "r10", "r11", "memory"); \
++#define __mutex_fastpath_lock(v, fail_fn) \
++do { \
++ unsigned long dummy; \
++ \
++ typecheck(atomic_t *, v); \
++ typecheck_fn(void (*)(atomic_t *), fail_fn); \
++ \
++ asm volatile(LOCK_PREFIX " decl (%%rdi)\n" \
++ " jns 1f \n" \
++ " call " #fail_fn "\n" \
++ "1:" \
++ : "=D" (dummy) \
++ : "D" (v) \
++ : "rax", "rsi", "rdx", "rcx", \
++ "r8", "r9", "r10", "r11", "memory"); \
+ } while (0)
+
+ /**
+@@ -45,9 +43,8 @@ do { \
+ * it wasn't 1 originally. This function returns 0 if the fastpath succeeds,
+ * or anything the slow path function returns
+ */
+-static inline int
+-__mutex_fastpath_lock_retval(atomic_t *count,
+- int (*fail_fn)(atomic_t *))
++static inline int __mutex_fastpath_lock_retval(atomic_t *count,
++ int (*fail_fn)(atomic_t *))
+ {
+ if (unlikely(atomic_dec_return(count) < 0))
+ return fail_fn(count);
+@@ -62,23 +59,21 @@ __mutex_fastpath_lock_retval(atomic_t *count,
+ *
+ * Atomically increments @v and calls <fail_fn> if the result is nonpositive.
+ */
+-#define __mutex_fastpath_unlock(v, fail_fn) \
+-do { \
+- unsigned long dummy; \
+- \
+- typecheck(atomic_t *, v); \
+- typecheck_fn(void (*)(atomic_t *), fail_fn); \
+- \
+- __asm__ __volatile__( \
+- LOCK_PREFIX " incl (%%rdi) \n" \
+- " jg 1f \n" \
+- " call "#fail_fn" \n" \
+- "1: " \
+- \
+- :"=D" (dummy) \
+- : "D" (v) \
+- : "rax", "rsi", "rdx", "rcx", \
+- "r8", "r9", "r10", "r11", "memory"); \
++#define __mutex_fastpath_unlock(v, fail_fn) \
++do { \
++ unsigned long dummy; \
++ \
++ typecheck(atomic_t *, v); \
++ typecheck_fn(void (*)(atomic_t *), fail_fn); \
++ \
++ asm volatile(LOCK_PREFIX " incl (%%rdi)\n" \
++ " jg 1f\n" \
++ " call " #fail_fn "\n" \
++ "1:" \
++ : "=D" (dummy) \
++ : "D" (v) \
++ : "rax", "rsi", "rdx", "rcx", \
++ "r8", "r9", "r10", "r11", "memory"); \
+ } while (0)
+
+ #define __mutex_slowpath_needs_to_unlock() 1
+@@ -93,8 +88,8 @@ do { \
+ * if it wasn't 1 originally. [the fallback function is never used on
+ * x86_64, because all x86_64 CPUs have a CMPXCHG instruction.]
+ */
+-static inline int
+-__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
++static inline int __mutex_fastpath_trylock(atomic_t *count,
++ int (*fail_fn)(atomic_t *))
+ {
+ if (likely(atomic_cmpxchg(count, 1, 0) == 1))
+ return 1;
+diff --git a/include/asm-x86/nmi.h b/include/asm-x86/nmi.h
+index 53ccac1..1e36302 100644
+--- a/include/asm-x86/nmi.h
++++ b/include/asm-x86/nmi.h
+@@ -1,5 +1,93 @@
+-#ifdef CONFIG_X86_32
+-# include "nmi_32.h"
++#ifndef _ASM_X86_NMI_H_
++#define _ASM_X86_NMI_H_
++
++#include <linux/pm.h>
++#include <asm/irq.h>
++#include <asm/io.h>
++
++#ifdef ARCH_HAS_NMI_WATCHDOG
++
++/**
++ * do_nmi_callback
++ *
++ * Check to see if a callback exists and execute it. Return 1
++ * if the handler exists and was handled successfully.
++ */
++int do_nmi_callback(struct pt_regs *regs, int cpu);
++
++#ifdef CONFIG_PM
++
++/** Replace the PM callback routine for NMI. */
++struct pm_dev *set_nmi_pm_callback(pm_callback callback);
++
++/** Unset the PM callback routine back to the default. */
++void unset_nmi_pm_callback(struct pm_dev *dev);
++
+ #else
+-# include "nmi_64.h"
++
++static inline struct pm_dev *set_nmi_pm_callback(pm_callback callback)
++{
++ return 0;
++}
++
++static inline void unset_nmi_pm_callback(struct pm_dev *dev)
++{
++}
++
++#endif /* CONFIG_PM */
++
++#ifdef CONFIG_X86_64
++extern void default_do_nmi(struct pt_regs *);
++extern void die_nmi(char *str, struct pt_regs *regs, int do_panic);
++extern void nmi_watchdog_default(void);
++#else
++#define nmi_watchdog_default() do {} while (0)
++#endif
++
++extern int check_nmi_watchdog(void);
++extern int nmi_watchdog_enabled;
++extern int unknown_nmi_panic;
++extern int avail_to_resrv_perfctr_nmi_bit(unsigned int);
++extern int avail_to_resrv_perfctr_nmi(unsigned int);
++extern int reserve_perfctr_nmi(unsigned int);
++extern void release_perfctr_nmi(unsigned int);
++extern int reserve_evntsel_nmi(unsigned int);
++extern void release_evntsel_nmi(unsigned int);
++
++extern void setup_apic_nmi_watchdog(void *);
++extern void stop_apic_nmi_watchdog(void *);
++extern void disable_timer_nmi_watchdog(void);
++extern void enable_timer_nmi_watchdog(void);
++extern int nmi_watchdog_tick(struct pt_regs *regs, unsigned reason);
++
++extern atomic_t nmi_active;
++extern unsigned int nmi_watchdog;
++#define NMI_DISABLED -1
++#define NMI_NONE 0
++#define NMI_IO_APIC 1
++#define NMI_LOCAL_APIC 2
++#define NMI_INVALID 3
++#define NMI_DEFAULT NMI_DISABLED
++
++struct ctl_table;
++struct file;
++extern int proc_nmi_enabled(struct ctl_table *, int , struct file *,
++ void __user *, size_t *, loff_t *);
++extern int unknown_nmi_panic;
++
++void __trigger_all_cpu_backtrace(void);
++#define trigger_all_cpu_backtrace() __trigger_all_cpu_backtrace()
++
++#endif
++
++void lapic_watchdog_stop(void);
++int lapic_watchdog_init(unsigned nmi_hz);
++int lapic_wd_event(unsigned nmi_hz);
++unsigned lapic_adjust_nmi_hz(unsigned hz);
++int lapic_watchdog_ok(void);
++void disable_lapic_nmi_watchdog(void);
++void enable_lapic_nmi_watchdog(void);
++void stop_nmi(void);
++void restart_nmi(void);
++
+ #endif
+diff --git a/include/asm-x86/nmi_32.h b/include/asm-x86/nmi_32.h
+deleted file mode 100644
+index 7206c7e..0000000
+--- a/include/asm-x86/nmi_32.h
++++ /dev/null
+@@ -1,61 +0,0 @@
+-#ifndef ASM_NMI_H
+-#define ASM_NMI_H
+-
+-#include <linux/pm.h>
+-#include <asm/irq.h>
+-
+-#ifdef ARCH_HAS_NMI_WATCHDOG
+-
+-/**
+- * do_nmi_callback
+- *
+- * Check to see if a callback exists and execute it. Return 1
+- * if the handler exists and was handled successfully.
+- */
+-int do_nmi_callback(struct pt_regs *regs, int cpu);
+-
+-extern int nmi_watchdog_enabled;
+-extern int avail_to_resrv_perfctr_nmi_bit(unsigned int);
+-extern int avail_to_resrv_perfctr_nmi(unsigned int);
+-extern int reserve_perfctr_nmi(unsigned int);
+-extern void release_perfctr_nmi(unsigned int);
+-extern int reserve_evntsel_nmi(unsigned int);
+-extern void release_evntsel_nmi(unsigned int);
+-
+-extern void setup_apic_nmi_watchdog (void *);
+-extern void stop_apic_nmi_watchdog (void *);
+-extern void disable_timer_nmi_watchdog(void);
+-extern void enable_timer_nmi_watchdog(void);
+-extern int nmi_watchdog_tick (struct pt_regs * regs, unsigned reason);
+-
+-extern atomic_t nmi_active;
+-extern unsigned int nmi_watchdog;
+-#define NMI_DISABLED -1
+-#define NMI_NONE 0
+-#define NMI_IO_APIC 1
+-#define NMI_LOCAL_APIC 2
+-#define NMI_INVALID 3
+-#define NMI_DEFAULT NMI_DISABLED
+-
+-struct ctl_table;
+-struct file;
+-extern int proc_nmi_enabled(struct ctl_table *, int , struct file *,
+- void __user *, size_t *, loff_t *);
+-extern int unknown_nmi_panic;
+-
+-void __trigger_all_cpu_backtrace(void);
+-#define trigger_all_cpu_backtrace() __trigger_all_cpu_backtrace()
+-
+-#endif
+-
+-void lapic_watchdog_stop(void);
+-int lapic_watchdog_init(unsigned nmi_hz);
+-int lapic_wd_event(unsigned nmi_hz);
+-unsigned lapic_adjust_nmi_hz(unsigned hz);
+-int lapic_watchdog_ok(void);
+-void disable_lapic_nmi_watchdog(void);
+-void enable_lapic_nmi_watchdog(void);
+-void stop_nmi(void);
+-void restart_nmi(void);
+-
+-#endif /* ASM_NMI_H */
+diff --git a/include/asm-x86/nmi_64.h b/include/asm-x86/nmi_64.h
+deleted file mode 100644
+index 2eeb74e..0000000
+--- a/include/asm-x86/nmi_64.h
++++ /dev/null
+@@ -1,90 +0,0 @@
+-#ifndef ASM_NMI_H
+-#define ASM_NMI_H
+-
+-#include <linux/pm.h>
+-#include <asm/io.h>
+-
+-/**
+- * do_nmi_callback
+- *
+- * Check to see if a callback exists and execute it. Return 1
+- * if the handler exists and was handled successfully.
+- */
+-int do_nmi_callback(struct pt_regs *regs, int cpu);
+-
+-#ifdef CONFIG_PM
+-
+-/** Replace the PM callback routine for NMI. */
+-struct pm_dev * set_nmi_pm_callback(pm_callback callback);
+-
+-/** Unset the PM callback routine back to the default. */
+-void unset_nmi_pm_callback(struct pm_dev * dev);
+-
+-#else
+-
+-static inline struct pm_dev * set_nmi_pm_callback(pm_callback callback)
+-{
+- return 0;
+-}
+-
+-static inline void unset_nmi_pm_callback(struct pm_dev * dev)
+-{
+-}
+-
+-#endif /* CONFIG_PM */
+-
+-extern void default_do_nmi(struct pt_regs *);
+-extern void die_nmi(char *str, struct pt_regs *regs, int do_panic);
+-
+-#define get_nmi_reason() inb(0x61)
+-
+-extern int unknown_nmi_panic;
+-extern int nmi_watchdog_enabled;
+-
+-extern int check_nmi_watchdog(void);
+-extern int avail_to_resrv_perfctr_nmi_bit(unsigned int);
+-extern int avail_to_resrv_perfctr_nmi(unsigned int);
+-extern int reserve_perfctr_nmi(unsigned int);
+-extern void release_perfctr_nmi(unsigned int);
+-extern int reserve_evntsel_nmi(unsigned int);
+-extern void release_evntsel_nmi(unsigned int);
+-
+-extern void setup_apic_nmi_watchdog (void *);
+-extern void stop_apic_nmi_watchdog (void *);
+-extern void disable_timer_nmi_watchdog(void);
+-extern void enable_timer_nmi_watchdog(void);
+-extern int nmi_watchdog_tick (struct pt_regs * regs, unsigned reason);
+-
+-extern void nmi_watchdog_default(void);
+-
+-extern atomic_t nmi_active;
+-extern unsigned int nmi_watchdog;
+-#define NMI_DISABLED -1
+-#define NMI_NONE 0
+-#define NMI_IO_APIC 1
+-#define NMI_LOCAL_APIC 2
+-#define NMI_INVALID 3
+-#define NMI_DEFAULT NMI_DISABLED
+-
+-struct ctl_table;
+-struct file;
+-extern int proc_nmi_enabled(struct ctl_table *, int , struct file *,
+- void __user *, size_t *, loff_t *);
+-
+-extern int unknown_nmi_panic;
+-
+-void __trigger_all_cpu_backtrace(void);
+-#define trigger_all_cpu_backtrace() __trigger_all_cpu_backtrace()
+-
+-
+-void lapic_watchdog_stop(void);
+-int lapic_watchdog_init(unsigned nmi_hz);
+-int lapic_wd_event(unsigned nmi_hz);
+-unsigned lapic_adjust_nmi_hz(unsigned hz);
+-int lapic_watchdog_ok(void);
+-void disable_lapic_nmi_watchdog(void);
+-void enable_lapic_nmi_watchdog(void);
+-void stop_nmi(void);
+-void restart_nmi(void);
+-
+-#endif /* ASM_NMI_H */
+diff --git a/include/asm-x86/nops.h b/include/asm-x86/nops.h
+index b3930ae..ad0bedd 100644
+--- a/include/asm-x86/nops.h
++++ b/include/asm-x86/nops.h
+@@ -5,6 +5,8 @@
+
+ /* generic versions from gas
+ 1: nop
++ the following instructions are NOT nops in 64-bit mode,
++ for 64-bit mode use K8 or P6 nops instead
+ 2: movl %esi,%esi
+ 3: leal 0x00(%esi),%esi
+ 4: leal 0x00(,%esi,1),%esi
+diff --git a/include/asm-x86/numa_64.h b/include/asm-x86/numa_64.h
+index 15fe07c..22e87c9 100644
+--- a/include/asm-x86/numa_64.h
++++ b/include/asm-x86/numa_64.h
+@@ -1,14 +1,16 @@
+-#ifndef _ASM_X8664_NUMA_H
++#ifndef _ASM_X8664_NUMA_H
+ #define _ASM_X8664_NUMA_H 1
+
+ #include <linux/nodemask.h>
+ #include <asm/apicdef.h>
+
+ struct bootnode {
+- u64 start,end;
++ u64 start;
++ u64 end;
+ };
+
+-extern int compute_hash_shift(struct bootnode *nodes, int numnodes);
++extern int compute_hash_shift(struct bootnode *nodes, int numblks,
++ int *nodeids);
+
+ #define ZONE_ALIGN (1UL << (MAX_ORDER+PAGE_SHIFT))
+
+diff --git a/include/asm-x86/numaq.h b/include/asm-x86/numaq.h
+index 38f710d..94b86c3 100644
+--- a/include/asm-x86/numaq.h
++++ b/include/asm-x86/numaq.h
+@@ -3,7 +3,7 @@
+ *
+ * Copyright (C) 2002, IBM Corp.
+ *
+- * All rights reserved.
++ * 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
+@@ -33,7 +33,8 @@ extern int get_memcfg_numaq(void);
+ /*
+ * SYS_CFG_DATA_PRIV_ADDR, struct eachquadmem, and struct sys_cfg_data are the
+ */
+-#define SYS_CFG_DATA_PRIV_ADDR 0x0009d000 /* place for scd in private quad space */
++#define SYS_CFG_DATA_PRIV_ADDR 0x0009d000 /* place for scd in private
++ quad space */
+
+ /*
+ * Communication area for each processor on lynxer-processor tests.
+@@ -139,7 +140,7 @@ struct sys_cfg_data {
+ unsigned int low_shrd_mem_base; /* 0 or 512MB or 1GB */
+ unsigned int low_shrd_mem_quad_offset; /* 0,128M,256M,512M,1G */
+ /* may not be totally populated */
+- unsigned int split_mem_enbl; /* 0 for no low shared memory */
++ unsigned int split_mem_enbl; /* 0 for no low shared memory */
+ unsigned int mmio_sz; /* Size of total system memory mapped I/O */
+ /* (in MB). */
+ unsigned int quad_spin_lock; /* Spare location used for quad */
+@@ -152,7 +153,7 @@ struct sys_cfg_data {
+ /*
+ * memory configuration area for each quad
+ */
+- struct eachquadmem eq[MAX_NUMNODES]; /* indexed by quad id */
++ struct eachquadmem eq[MAX_NUMNODES]; /* indexed by quad id */
+ };
+
+ static inline unsigned long *get_zholes_size(int nid)
+diff --git a/include/asm-x86/page.h b/include/asm-x86/page.h
+index a05b289..b381f4a 100644
+--- a/include/asm-x86/page.h
++++ b/include/asm-x86/page.h
+@@ -33,10 +33,8 @@
+
+ #ifdef CONFIG_X86_64
+ #include <asm/page_64.h>
+-#define max_pfn_mapped end_pfn_map
+ #else
+ #include <asm/page_32.h>
+-#define max_pfn_mapped max_low_pfn
+ #endif /* CONFIG_X86_64 */
+
+ #define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
+@@ -49,6 +47,9 @@
+ #ifndef __ASSEMBLY__
+
+ extern int page_is_ram(unsigned long pagenr);
++extern int devmem_is_allowed(unsigned long pagenr);
++
++extern unsigned long max_pfn_mapped;
+
+ struct page;
+
+diff --git a/include/asm-x86/page_32.h b/include/asm-x86/page_32.h
+index 5f7257f..424e82f 100644
+--- a/include/asm-x86/page_32.h
++++ b/include/asm-x86/page_32.h
+@@ -47,7 +47,10 @@ typedef unsigned long pgdval_t;
+ typedef unsigned long pgprotval_t;
+ typedef unsigned long phys_addr_t;
+
+-typedef union { pteval_t pte, pte_low; } pte_t;
++typedef union {
++ pteval_t pte;
++ pteval_t pte_low;
++} pte_t;
+
+ #endif /* __ASSEMBLY__ */
+ #endif /* CONFIG_X86_PAE */
+@@ -61,7 +64,7 @@ typedef struct page *pgtable_t;
+ #endif
+
+ #ifndef __ASSEMBLY__
+-#define __phys_addr(x) ((x)-PAGE_OFFSET)
++#define __phys_addr(x) ((x) - PAGE_OFFSET)
+ #define __phys_reloc_hide(x) RELOC_HIDE((x), 0)
+
+ #ifdef CONFIG_FLATMEM
+@@ -78,7 +81,7 @@ extern unsigned int __VMALLOC_RESERVE;
+ extern int sysctl_legacy_va_layout;
+
+ #define VMALLOC_RESERVE ((unsigned long)__VMALLOC_RESERVE)
+-#define MAXMEM (-__PAGE_OFFSET-__VMALLOC_RESERVE)
++#define MAXMEM (-__PAGE_OFFSET - __VMALLOC_RESERVE)
+
+ #ifdef CONFIG_X86_USE_3DNOW
+ #include <asm/mmx.h>
+diff --git a/include/asm-x86/page_64.h b/include/asm-x86/page_64.h
+index 1435460..6ea7285 100644
+--- a/include/asm-x86/page_64.h
++++ b/include/asm-x86/page_64.h
+@@ -5,7 +5,7 @@
+
+ #define THREAD_ORDER 1
+ #define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER)
+-#define CURRENT_MASK (~(THREAD_SIZE-1))
++#define CURRENT_MASK (~(THREAD_SIZE - 1))
+
+ #define EXCEPTION_STACK_ORDER 0
+ #define EXCEPTION_STKSZ (PAGE_SIZE << EXCEPTION_STACK_ORDER)
+@@ -48,10 +48,10 @@
+ #define __VIRTUAL_MASK_SHIFT 48
+
+ /*
+- * Kernel image size is limited to 128 MB (see level2_kernel_pgt in
++ * Kernel image size is limited to 512 MB (see level2_kernel_pgt in
+ * arch/x86/kernel/head_64.S), and it is mapped here:
+ */
+-#define KERNEL_IMAGE_SIZE (128*1024*1024)
++#define KERNEL_IMAGE_SIZE (512 * 1024 * 1024)
+ #define KERNEL_IMAGE_START _AC(0xffffffff80000000, UL)
+
+ #ifndef __ASSEMBLY__
+@@ -59,7 +59,6 @@ void clear_page(void *page);
+ void copy_page(void *to, void *from);
+
+ extern unsigned long end_pfn;
+-extern unsigned long end_pfn_map;
+ extern unsigned long phys_base;
+
+ extern unsigned long __phys_addr(unsigned long);
+@@ -81,6 +80,9 @@ typedef struct { pteval_t pte; } pte_t;
+
+ #define vmemmap ((struct page *)VMEMMAP_START)
+
++extern unsigned long init_memory_mapping(unsigned long start,
++ unsigned long end);
++
+ #endif /* !__ASSEMBLY__ */
+
+ #ifdef CONFIG_FLATMEM
+diff --git a/include/asm-x86/param.h b/include/asm-x86/param.h
+index c996ec4..6f0d042 100644
+--- a/include/asm-x86/param.h
++++ b/include/asm-x86/param.h
+@@ -3,8 +3,8 @@
+
+ #ifdef __KERNEL__
+ # define HZ CONFIG_HZ /* Internal kernel timer frequency */
+-# define USER_HZ 100 /* .. some user interfaces are in "ticks" */
+-# define CLOCKS_PER_SEC (USER_HZ) /* like times() */
++# define USER_HZ 100 /* some user interfaces are */
++# define CLOCKS_PER_SEC (USER_HZ) /* in "ticks" like times() */
+ #endif
+
+ #ifndef HZ
+diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h
+index d6236eb..0f13b94 100644
+--- a/include/asm-x86/paravirt.h
++++ b/include/asm-x86/paravirt.h
+@@ -220,18 +220,21 @@ struct pv_mmu_ops {
+ unsigned long va);
+
+ /* Hooks for allocating/releasing pagetable pages */
+- void (*alloc_pt)(struct mm_struct *mm, u32 pfn);
+- void (*alloc_pd)(struct mm_struct *mm, u32 pfn);
+- void (*alloc_pd_clone)(u32 pfn, u32 clonepfn, u32 start, u32 count);
+- void (*release_pt)(u32 pfn);
+- void (*release_pd)(u32 pfn);
++ void (*alloc_pte)(struct mm_struct *mm, u32 pfn);
++ void (*alloc_pmd)(struct mm_struct *mm, u32 pfn);
++ void (*alloc_pmd_clone)(u32 pfn, u32 clonepfn, u32 start, u32 count);
++ void (*alloc_pud)(struct mm_struct *mm, u32 pfn);
++ void (*release_pte)(u32 pfn);
++ void (*release_pmd)(u32 pfn);
++ void (*release_pud)(u32 pfn);
+
+ /* Pagetable manipulation functions */
+ void (*set_pte)(pte_t *ptep, pte_t pteval);
+ void (*set_pte_at)(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pteval);
+ void (*set_pmd)(pmd_t *pmdp, pmd_t pmdval);
+- void (*pte_update)(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
++ void (*pte_update)(struct mm_struct *mm, unsigned long addr,
++ pte_t *ptep);
+ void (*pte_update_defer)(struct mm_struct *mm,
+ unsigned long addr, pte_t *ptep);
+
+@@ -246,7 +249,8 @@ struct pv_mmu_ops {
+ void (*set_pte_atomic)(pte_t *ptep, pte_t pteval);
+ void (*set_pte_present)(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte);
+- void (*pte_clear)(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
++ void (*pte_clear)(struct mm_struct *mm, unsigned long addr,
++ pte_t *ptep);
+ void (*pmd_clear)(pmd_t *pmdp);
+
+ #endif /* CONFIG_X86_PAE */
+@@ -274,8 +278,7 @@ struct pv_mmu_ops {
+ /* This contains all the paravirt structures: we get a convenient
+ * number for each function using the offset which we use to indicate
+ * what to patch. */
+-struct paravirt_patch_template
+-{
++struct paravirt_patch_template {
+ struct pv_init_ops pv_init_ops;
+ struct pv_time_ops pv_time_ops;
+ struct pv_cpu_ops pv_cpu_ops;
+@@ -660,43 +663,56 @@ static inline int paravirt_write_msr(unsigned msr, unsigned low, unsigned high)
+ }
+
+ /* These should all do BUG_ON(_err), but our headers are too tangled. */
+-#define rdmsr(msr,val1,val2) do { \
++#define rdmsr(msr, val1, val2) \
++do { \
+ int _err; \
+ u64 _l = paravirt_read_msr(msr, &_err); \
+ val1 = (u32)_l; \
+ val2 = _l >> 32; \
+-} while(0)
++} while (0)
+
+-#define wrmsr(msr,val1,val2) do { \
++#define wrmsr(msr, val1, val2) \
++do { \
+ paravirt_write_msr(msr, val1, val2); \
+-} while(0)
++} while (0)
+
+-#define rdmsrl(msr,val) do { \
++#define rdmsrl(msr, val) \
++do { \
+ int _err; \
+ val = paravirt_read_msr(msr, &_err); \
+-} while(0)
++} while (0)
+
+-#define wrmsrl(msr,val) wrmsr(msr, (u32)((u64)(val)), ((u64)(val))>>32)
+-#define wrmsr_safe(msr,a,b) paravirt_write_msr(msr, a, b)
++#define wrmsrl(msr, val) wrmsr(msr, (u32)((u64)(val)), ((u64)(val))>>32)
++#define wrmsr_safe(msr, a, b) paravirt_write_msr(msr, a, b)
+
+ /* rdmsr with exception handling */
+-#define rdmsr_safe(msr,a,b) ({ \
++#define rdmsr_safe(msr, a, b) \
++({ \
+ int _err; \
+ u64 _l = paravirt_read_msr(msr, &_err); \
+ (*a) = (u32)_l; \
+ (*b) = _l >> 32; \
+- _err; })
++ _err; \
++})
+
++static inline int rdmsrl_safe(unsigned msr, unsigned long long *p)
++{
++ int err;
++
++ *p = paravirt_read_msr(msr, &err);
++ return err;
++}
+
+ static inline u64 paravirt_read_tsc(void)
+ {
+ return PVOP_CALL0(u64, pv_cpu_ops.read_tsc);
+ }
+
+-#define rdtscl(low) do { \
++#define rdtscl(low) \
++do { \
+ u64 _l = paravirt_read_tsc(); \
+ low = (int)_l; \
+-} while(0)
++} while (0)
+
+ #define rdtscll(val) (val = paravirt_read_tsc())
+
+@@ -711,11 +727,12 @@ static inline unsigned long long paravirt_read_pmc(int counter)
+ return PVOP_CALL1(u64, pv_cpu_ops.read_pmc, counter);
+ }
+
+-#define rdpmc(counter,low,high) do { \
++#define rdpmc(counter, low, high) \
++do { \
+ u64 _l = paravirt_read_pmc(counter); \
+ low = (u32)_l; \
+ high = _l >> 32; \
+-} while(0)
++} while (0)
+
+ static inline unsigned long long paravirt_rdtscp(unsigned int *aux)
+ {
+@@ -794,7 +811,8 @@ static inline void set_iopl_mask(unsigned mask)
+ }
+
+ /* The paravirtualized I/O functions */
+-static inline void slow_down_io(void) {
++static inline void slow_down_io(void)
++{
+ pv_cpu_ops.io_delay();
+ #ifdef REALLY_SLOW_IO
+ pv_cpu_ops.io_delay();
+@@ -894,28 +912,37 @@ static inline void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
+ PVOP_VCALL3(pv_mmu_ops.flush_tlb_others, &cpumask, mm, va);
+ }
+
+-static inline void paravirt_alloc_pt(struct mm_struct *mm, unsigned pfn)
++static inline void paravirt_alloc_pte(struct mm_struct *mm, unsigned pfn)
+ {
+- PVOP_VCALL2(pv_mmu_ops.alloc_pt, mm, pfn);
++ PVOP_VCALL2(pv_mmu_ops.alloc_pte, mm, pfn);
+ }
+-static inline void paravirt_release_pt(unsigned pfn)
++static inline void paravirt_release_pte(unsigned pfn)
+ {
+- PVOP_VCALL1(pv_mmu_ops.release_pt, pfn);
++ PVOP_VCALL1(pv_mmu_ops.release_pte, pfn);
+ }
+
+-static inline void paravirt_alloc_pd(struct mm_struct *mm, unsigned pfn)
++static inline void paravirt_alloc_pmd(struct mm_struct *mm, unsigned pfn)
++{
++ PVOP_VCALL2(pv_mmu_ops.alloc_pmd, mm, pfn);
++}
++
++static inline void paravirt_alloc_pmd_clone(unsigned pfn, unsigned clonepfn,
++ unsigned start, unsigned count)
++{
++ PVOP_VCALL4(pv_mmu_ops.alloc_pmd_clone, pfn, clonepfn, start, count);
++}
++static inline void paravirt_release_pmd(unsigned pfn)
+ {
+- PVOP_VCALL2(pv_mmu_ops.alloc_pd, mm, pfn);
++ PVOP_VCALL1(pv_mmu_ops.release_pmd, pfn);
+ }
+
+-static inline void paravirt_alloc_pd_clone(unsigned pfn, unsigned clonepfn,
+- unsigned start, unsigned count)
++static inline void paravirt_alloc_pud(struct mm_struct *mm, unsigned pfn)
+ {
+- PVOP_VCALL4(pv_mmu_ops.alloc_pd_clone, pfn, clonepfn, start, count);
++ PVOP_VCALL2(pv_mmu_ops.alloc_pud, mm, pfn);
+ }
+-static inline void paravirt_release_pd(unsigned pfn)
++static inline void paravirt_release_pud(unsigned pfn)
+ {
+- PVOP_VCALL1(pv_mmu_ops.release_pd, pfn);
++ PVOP_VCALL1(pv_mmu_ops.release_pud, pfn);
+ }
+
+ #ifdef CONFIG_HIGHPTE
+diff --git a/include/asm-x86/parport.h b/include/asm-x86/parport.h
+index 019cbca..3c4ffeb 100644
+--- a/include/asm-x86/parport.h
++++ b/include/asm-x86/parport.h
+@@ -1,10 +1,10 @@
+ #ifndef _ASM_X86_PARPORT_H
+ #define _ASM_X86_PARPORT_H
+
+-static int __devinit parport_pc_find_isa_ports (int autoirq, int autodma);
+-static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma)
++static int __devinit parport_pc_find_isa_ports(int autoirq, int autodma);
++static int __devinit parport_pc_find_nonpci_ports(int autoirq, int autodma)
+ {
+- return parport_pc_find_isa_ports (autoirq, autodma);
++ return parport_pc_find_isa_ports(autoirq, autodma);
+ }
+
+ #endif /* _ASM_X86_PARPORT_H */
+diff --git a/include/asm-x86/pat.h b/include/asm-x86/pat.h
+new file mode 100644
+index 0000000..8b822b5
+--- /dev/null
++++ b/include/asm-x86/pat.h
+@@ -0,0 +1,16 @@
++
++#ifndef _ASM_PAT_H
++#define _ASM_PAT_H 1
++
++#include <linux/types.h>
++
++extern int pat_wc_enabled;
++
++extern void pat_init(void);
++
++extern int reserve_memtype(u64 start, u64 end,
++ unsigned long req_type, unsigned long *ret_type);
++extern int free_memtype(u64 start, u64 end);
++
++#endif
++
+diff --git a/include/asm-x86/pci-direct.h b/include/asm-x86/pci-direct.h
+index 6823fa4..5b21485 100644
+--- a/include/asm-x86/pci-direct.h
++++ b/include/asm-x86/pci-direct.h
+@@ -4,7 +4,7 @@
+ #include <linux/types.h>
+
+ /* Direct PCI access. This is used for PCI accesses in early boot before
+- the PCI subsystem works. */
++ the PCI subsystem works. */
+
+ extern u32 read_pci_config(u8 bus, u8 slot, u8 func, u8 offset);
+ extern u8 read_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset);
+diff --git a/include/asm-x86/pci.h b/include/asm-x86/pci.h
+index c61190c..ddd8e24 100644
+--- a/include/asm-x86/pci.h
++++ b/include/asm-x86/pci.h
+@@ -8,14 +8,13 @@
+ #include <asm/scatterlist.h>
+ #include <asm/io.h>
+
+-
+ #ifdef __KERNEL__
+
+ struct pci_sysdata {
+ int domain; /* PCI domain */
+ int node; /* NUMA node */
+ #ifdef CONFIG_X86_64
+- void* iommu; /* IOMMU private data */
++ void *iommu; /* IOMMU private data */
+ #endif
+ };
+
+@@ -52,7 +51,7 @@ extern unsigned long pci_mem_start;
+ #define PCIBIOS_MIN_CARDBUS_IO 0x4000
+
+ void pcibios_config_init(void);
+-struct pci_bus * pcibios_scan_root(int bus);
++struct pci_bus *pcibios_scan_root(int bus);
+
+ void pcibios_set_master(struct pci_dev *dev);
+ void pcibios_penalize_isa_irq(int irq, int active);
+@@ -62,7 +61,8 @@ int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq);
+
+ #define HAVE_PCI_MMAP
+ extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+- enum pci_mmap_state mmap_state, int write_combine);
++ enum pci_mmap_state mmap_state,
++ int write_combine);
+
+
+ #ifdef CONFIG_PCI
+diff --git a/include/asm-x86/pci_64.h b/include/asm-x86/pci_64.h
+index 3746903..f330234 100644
+--- a/include/asm-x86/pci_64.h
++++ b/include/asm-x86/pci_64.h
+@@ -1,12 +1,10 @@
+ #ifndef __x8664_PCI_H
+ #define __x8664_PCI_H
+
+-
+ #ifdef __KERNEL__
+
+-
+ #ifdef CONFIG_CALGARY_IOMMU
+-static inline void* pci_iommu(struct pci_bus *bus)
++static inline void *pci_iommu(struct pci_bus *bus)
+ {
+ struct pci_sysdata *sd = bus->sysdata;
+ return sd->iommu;
+@@ -19,12 +17,12 @@ static inline void set_pci_iommu(struct pci_bus *bus, void *val)
+ }
+ #endif /* CONFIG_CALGARY_IOMMU */
+
++extern int (*pci_config_read)(int seg, int bus, int dev, int fn,
++ int reg, int len, u32 *value);
++extern int (*pci_config_write)(int seg, int bus, int dev, int fn,
++ int reg, int len, u32 value);
+
+-extern int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value);
+-extern int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value);
+-
+-
+-
++extern void dma32_reserve_bootmem(void);
+ extern void pci_iommu_alloc(void);
+
+ /* The PCI address space does equal the physical memory
+@@ -65,5 +63,4 @@ extern void pci_iommu_alloc(void);
+
+ #endif /* __KERNEL__ */
+
+-
+ #endif /* __x8664_PCI_H */
+diff --git a/include/asm-x86/pda.h b/include/asm-x86/pda.h
+index c0305bf..101fb9e 100644
+--- a/include/asm-x86/pda.h
++++ b/include/asm-x86/pda.h
+@@ -22,7 +22,6 @@ struct x8664_pda {
+ offset 40!!! */
+ #endif
+ char *irqstackptr;
+- unsigned int nodenumber; /* number of current node */
+ unsigned int __softirq_pending;
+ unsigned int __nmi_count; /* number of NMI on this CPUs */
+ short mmu_state;
+@@ -58,34 +57,36 @@ extern struct x8664_pda _proxy_pda;
+
+ #define pda_offset(field) offsetof(struct x8664_pda, field)
+
+-#define pda_to_op(op, field, val) do { \
+- typedef typeof(_proxy_pda.field) T__; \
+- if (0) { T__ tmp__; tmp__ = (val); } /* type checking */ \
+- switch (sizeof(_proxy_pda.field)) { \
+- case 2: \
+- asm(op "w %1,%%gs:%c2" : \
+- "+m" (_proxy_pda.field) : \
+- "ri" ((T__)val), \
+- "i"(pda_offset(field))); \
+- break; \
+- case 4: \
+- asm(op "l %1,%%gs:%c2" : \
+- "+m" (_proxy_pda.field) : \
+- "ri" ((T__)val), \
+- "i" (pda_offset(field))); \
+- break; \
+- case 8: \
+- asm(op "q %1,%%gs:%c2": \
+- "+m" (_proxy_pda.field) : \
+- "ri" ((T__)val), \
+- "i"(pda_offset(field))); \
+- break; \
+- default: \
+- __bad_pda_field(); \
+- } \
+- } while (0)
++#define pda_to_op(op, field, val) \
++do { \
++ typedef typeof(_proxy_pda.field) T__; \
++ if (0) { T__ tmp__; tmp__ = (val); } /* type checking */ \
++ switch (sizeof(_proxy_pda.field)) { \
++ case 2: \
++ asm(op "w %1,%%gs:%c2" : \
++ "+m" (_proxy_pda.field) : \
++ "ri" ((T__)val), \
++ "i"(pda_offset(field))); \
++ break; \
++ case 4: \
++ asm(op "l %1,%%gs:%c2" : \
++ "+m" (_proxy_pda.field) : \
++ "ri" ((T__)val), \
++ "i" (pda_offset(field))); \
++ break; \
++ case 8: \
++ asm(op "q %1,%%gs:%c2": \
++ "+m" (_proxy_pda.field) : \
++ "ri" ((T__)val), \
++ "i"(pda_offset(field))); \
++ break; \
++ default: \
++ __bad_pda_field(); \
++ } \
++} while (0)
+
+-#define pda_from_op(op,field) ({ \
++#define pda_from_op(op, field) \
++({ \
+ typeof(_proxy_pda.field) ret__; \
+ switch (sizeof(_proxy_pda.field)) { \
+ case 2: \
+@@ -93,23 +94,24 @@ extern struct x8664_pda _proxy_pda;
+ "=r" (ret__) : \
+ "i" (pda_offset(field)), \
+ "m" (_proxy_pda.field)); \
+- break; \
++ break; \
+ case 4: \
+ asm(op "l %%gs:%c1,%0": \
+ "=r" (ret__): \
+ "i" (pda_offset(field)), \
+ "m" (_proxy_pda.field)); \
+- break; \
++ break; \
+ case 8: \
+ asm(op "q %%gs:%c1,%0": \
+ "=r" (ret__) : \
+ "i" (pda_offset(field)), \
+ "m" (_proxy_pda.field)); \
+- break; \
++ break; \
+ default: \
+ __bad_pda_field(); \
+- } \
+- ret__; })
++ } \
++ ret__; \
++})
+
+ #define read_pda(field) pda_from_op("mov", field)
+ #define write_pda(field, val) pda_to_op("mov", field, val)
+@@ -118,12 +120,13 @@ extern struct x8664_pda _proxy_pda;
+ #define or_pda(field, val) pda_to_op("or", field, val)
+
+ /* This is not atomic against other CPUs -- CPU preemption needs to be off */
+-#define test_and_clear_bit_pda(bit, field) ({ \
+- int old__; \
+- asm volatile("btr %2,%%gs:%c3\n\tsbbl %0,%0" \
+- : "=r" (old__), "+m" (_proxy_pda.field) \
+- : "dIr" (bit), "i" (pda_offset(field)) : "memory"); \
+- old__; \
++#define test_and_clear_bit_pda(bit, field) \
++({ \
++ int old__; \
++ asm volatile("btr %2,%%gs:%c3\n\tsbbl %0,%0" \
++ : "=r" (old__), "+m" (_proxy_pda.field) \
++ : "dIr" (bit), "i" (pda_offset(field)) : "memory");\
++ old__; \
+ })
+
+ #endif
+diff --git a/include/asm-x86/percpu.h b/include/asm-x86/percpu.h
+index 0dec00f..736fc3b 100644
+--- a/include/asm-x86/percpu.h
++++ b/include/asm-x86/percpu.h
+@@ -85,58 +85,62 @@ DECLARE_PER_CPU(unsigned long, this_cpu_off);
+ * don't give an lvalue though). */
+ extern void __bad_percpu_size(void);
+
+-#define percpu_to_op(op,var,val) \
+- do { \
+- typedef typeof(var) T__; \
+- if (0) { T__ tmp__; tmp__ = (val); } \
+- switch (sizeof(var)) { \
+- case 1: \
+- asm(op "b %1,"__percpu_seg"%0" \
+- : "+m" (var) \
+- :"ri" ((T__)val)); \
+- break; \
+- case 2: \
+- asm(op "w %1,"__percpu_seg"%0" \
+- : "+m" (var) \
+- :"ri" ((T__)val)); \
+- break; \
+- case 4: \
+- asm(op "l %1,"__percpu_seg"%0" \
+- : "+m" (var) \
+- :"ri" ((T__)val)); \
+- break; \
+- default: __bad_percpu_size(); \
+- } \
+- } while (0)
+-
+-#define percpu_from_op(op,var) \
+- ({ \
+- typeof(var) ret__; \
+- switch (sizeof(var)) { \
+- case 1: \
+- asm(op "b "__percpu_seg"%1,%0" \
+- : "=r" (ret__) \
+- : "m" (var)); \
+- break; \
+- case 2: \
+- asm(op "w "__percpu_seg"%1,%0" \
+- : "=r" (ret__) \
+- : "m" (var)); \
+- break; \
+- case 4: \
+- asm(op "l "__percpu_seg"%1,%0" \
+- : "=r" (ret__) \
+- : "m" (var)); \
+- break; \
+- default: __bad_percpu_size(); \
+- } \
+- ret__; })
++#define percpu_to_op(op, var, val) \
++do { \
++ typedef typeof(var) T__; \
++ if (0) { \
++ T__ tmp__; \
++ tmp__ = (val); \
++ } \
++ switch (sizeof(var)) { \
++ case 1: \
++ asm(op "b %1,"__percpu_seg"%0" \
++ : "+m" (var) \
++ : "ri" ((T__)val)); \
++ break; \
++ case 2: \
++ asm(op "w %1,"__percpu_seg"%0" \
++ : "+m" (var) \
++ : "ri" ((T__)val)); \
++ break; \
++ case 4: \
++ asm(op "l %1,"__percpu_seg"%0" \
++ : "+m" (var) \
++ : "ri" ((T__)val)); \
++ break; \
++ default: __bad_percpu_size(); \
++ } \
++} while (0)
++
++#define percpu_from_op(op, var) \
++({ \
++ typeof(var) ret__; \
++ switch (sizeof(var)) { \
++ case 1: \
++ asm(op "b "__percpu_seg"%1,%0" \
++ : "=r" (ret__) \
++ : "m" (var)); \
++ break; \
++ case 2: \
++ asm(op "w "__percpu_seg"%1,%0" \
++ : "=r" (ret__) \
++ : "m" (var)); \
++ break; \
++ case 4: \
++ asm(op "l "__percpu_seg"%1,%0" \
++ : "=r" (ret__) \
++ : "m" (var)); \
++ break; \
++ default: __bad_percpu_size(); \
++ } \
++ ret__; \
++})
+
+ #define x86_read_percpu(var) percpu_from_op("mov", per_cpu__##var)
+-#define x86_write_percpu(var,val) percpu_to_op("mov", per_cpu__##var, val)
+-#define x86_add_percpu(var,val) percpu_to_op("add", per_cpu__##var, val)
+-#define x86_sub_percpu(var,val) percpu_to_op("sub", per_cpu__##var, val)
+-#define x86_or_percpu(var,val) percpu_to_op("or", per_cpu__##var, val)
++#define x86_write_percpu(var, val) percpu_to_op("mov", per_cpu__##var, val)
++#define x86_add_percpu(var, val) percpu_to_op("add", per_cpu__##var, val)
++#define x86_sub_percpu(var, val) percpu_to_op("sub", per_cpu__##var, val)
++#define x86_or_percpu(var, val) percpu_to_op("or", per_cpu__##var, val)
+ #endif /* !__ASSEMBLY__ */
+ #endif /* !CONFIG_X86_64 */
+ #endif /* _ASM_X86_PERCPU_H_ */
+diff --git a/include/asm-x86/pgalloc.h b/include/asm-x86/pgalloc.h
+index 5886eed..91e4641 100644
+--- a/include/asm-x86/pgalloc.h
++++ b/include/asm-x86/pgalloc.h
+@@ -1,5 +1,110 @@
+-#ifdef CONFIG_X86_32
+-# include "pgalloc_32.h"
++#ifndef _ASM_X86_PGALLOC_H
++#define _ASM_X86_PGALLOC_H
++
++#include <linux/threads.h>
++#include <linux/mm.h> /* for struct page */
++#include <linux/pagemap.h>
++
++#ifdef CONFIG_PARAVIRT
++#include <asm/paravirt.h>
+ #else
+-# include "pgalloc_64.h"
++static inline void paravirt_alloc_pte(struct mm_struct *mm, unsigned long pfn) {}
++static inline void paravirt_alloc_pmd(struct mm_struct *mm, unsigned long pfn) {}
++static inline void paravirt_alloc_pmd_clone(unsigned long pfn, unsigned long clonepfn,
++ unsigned long start, unsigned long count) {}
++static inline void paravirt_alloc_pud(struct mm_struct *mm, unsigned long pfn) {}
++static inline void paravirt_release_pte(unsigned long pfn) {}
++static inline void paravirt_release_pmd(unsigned long pfn) {}
++static inline void paravirt_release_pud(unsigned long pfn) {}
+ #endif
++
++/*
++ * Allocate and free page tables.
++ */
++extern pgd_t *pgd_alloc(struct mm_struct *);
++extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
++
++extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
++extern pgtable_t pte_alloc_one(struct mm_struct *, unsigned long);
++
++/* Should really implement gc for free page table pages. This could be
++ done with a reference count in struct page. */
++
++static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
++{
++ BUG_ON((unsigned long)pte & (PAGE_SIZE-1));
++ free_page((unsigned long)pte);
++}
++
++static inline void pte_free(struct mm_struct *mm, struct page *pte)
++{
++ __free_page(pte);
++}
++
++extern void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte);
++
++static inline void pmd_populate_kernel(struct mm_struct *mm,
++ pmd_t *pmd, pte_t *pte)
++{
++ paravirt_alloc_pte(mm, __pa(pte) >> PAGE_SHIFT);
++ set_pmd(pmd, __pmd(__pa(pte) | _PAGE_TABLE));
++}
++
++static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
++ struct page *pte)
++{
++ unsigned long pfn = page_to_pfn(pte);
++
++ paravirt_alloc_pte(mm, pfn);
++ set_pmd(pmd, __pmd(((pteval_t)pfn << PAGE_SHIFT) | _PAGE_TABLE));
++}
++
++#define pmd_pgtable(pmd) pmd_page(pmd)
++
++#if PAGETABLE_LEVELS > 2
++static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
++{
++ return (pmd_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
++}
++
++static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
++{
++ BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
++ free_page((unsigned long)pmd);
++}
++
++extern void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd);
++
++#ifdef CONFIG_X86_PAE
++extern void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd);
++#else /* !CONFIG_X86_PAE */
++static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
++{
++ paravirt_alloc_pmd(mm, __pa(pmd) >> PAGE_SHIFT);
++ set_pud(pud, __pud(_PAGE_TABLE | __pa(pmd)));
++}
++#endif /* CONFIG_X86_PAE */
++
++#if PAGETABLE_LEVELS > 3
++static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
++{
++ paravirt_alloc_pud(mm, __pa(pud) >> PAGE_SHIFT);
++ set_pgd(pgd, __pgd(_PAGE_TABLE | __pa(pud)));
++}
++
++static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
++{
++ return (pud_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
++}
++
++static inline void pud_free(struct mm_struct *mm, pud_t *pud)
++{
++ BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
++ free_page((unsigned long)pud);
++}
++
++extern void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud);
++#endif /* PAGETABLE_LEVELS > 3 */
++#endif /* PAGETABLE_LEVELS > 2 */
++
++#endif /* _ASM_X86_PGALLOC_H */
+diff --git a/include/asm-x86/pgalloc_32.h b/include/asm-x86/pgalloc_32.h
+deleted file mode 100644
+index 6bea6e5..0000000
+--- a/include/asm-x86/pgalloc_32.h
++++ /dev/null
+@@ -1,95 +0,0 @@
+-#ifndef _I386_PGALLOC_H
+-#define _I386_PGALLOC_H
+-
+-#include <linux/threads.h>
+-#include <linux/mm.h> /* for struct page */
+-#include <linux/pagemap.h>
+-#include <asm/tlb.h>
+-#include <asm-generic/tlb.h>
+-
+-#ifdef CONFIG_PARAVIRT
+-#include <asm/paravirt.h>
+-#else
+-#define paravirt_alloc_pt(mm, pfn) do { } while (0)
+-#define paravirt_alloc_pd(mm, pfn) do { } while (0)
+-#define paravirt_alloc_pd_clone(pfn, clonepfn, start, count) do { } while (0)
+-#define paravirt_release_pt(pfn) do { } while (0)
+-#define paravirt_release_pd(pfn) do { } while (0)
+-#endif
+-
+-static inline void pmd_populate_kernel(struct mm_struct *mm,
+- pmd_t *pmd, pte_t *pte)
+-{
+- paravirt_alloc_pt(mm, __pa(pte) >> PAGE_SHIFT);
+- set_pmd(pmd, __pmd(__pa(pte) | _PAGE_TABLE));
+-}
+-
+-static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte)
+-{
+- unsigned long pfn = page_to_pfn(pte);
+-
+- paravirt_alloc_pt(mm, pfn);
+- set_pmd(pmd, __pmd(((pteval_t)pfn << PAGE_SHIFT) | _PAGE_TABLE));
+-}
+-#define pmd_pgtable(pmd) pmd_page(pmd)
+-
+-/*
+- * Allocate and free page tables.
+- */
+-extern pgd_t *pgd_alloc(struct mm_struct *);
+-extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
+-
+-extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
+-extern pgtable_t pte_alloc_one(struct mm_struct *, unsigned long);
+-
+-static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+-{
+- free_page((unsigned long)pte);
+-}
+-
+-static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
+-{
+- pgtable_page_dtor(pte);
+- __free_page(pte);
+-}
+-
+-
+-extern void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte);
+-
+-#ifdef CONFIG_X86_PAE
+-/*
+- * In the PAE case we free the pmds as part of the pgd.
+- */
+-static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
+-{
+- return (pmd_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
+-}
+-
+-static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+-{
+- BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
+- free_page((unsigned long)pmd);
+-}
+-
+-extern void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd);
+-
+-static inline void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd)
+-{
+- paravirt_alloc_pd(mm, __pa(pmd) >> PAGE_SHIFT);
+-
+- /* Note: almost everything apart from _PAGE_PRESENT is
+- reserved at the pmd (PDPT) level. */
+- set_pud(pudp, __pud(__pa(pmd) | _PAGE_PRESENT));
+-
+- /*
+- * According to Intel App note "TLBs, Paging-Structure Caches,
+- * and Their Invalidation", April 2007, document 317080-001,
+- * section 8.1: in PAE mode we explicitly have to flush the
+- * TLB via cr3 if the top-level pgd is changed...
+- */
+- if (mm == current->active_mm)
+- write_cr3(read_cr3());
+-}
+-#endif /* CONFIG_X86_PAE */
+-
+-#endif /* _I386_PGALLOC_H */
+diff --git a/include/asm-x86/pgalloc_64.h b/include/asm-x86/pgalloc_64.h
+deleted file mode 100644
+index 8d67223..0000000
+--- a/include/asm-x86/pgalloc_64.h
++++ /dev/null
+@@ -1,133 +0,0 @@
+-#ifndef _X86_64_PGALLOC_H
+-#define _X86_64_PGALLOC_H
+-
+-#include <asm/pda.h>
+-#include <linux/threads.h>
+-#include <linux/mm.h>
+-
+-#define pmd_populate_kernel(mm, pmd, pte) \
+- set_pmd(pmd, __pmd(_PAGE_TABLE | __pa(pte)))
+-#define pud_populate(mm, pud, pmd) \
+- set_pud(pud, __pud(_PAGE_TABLE | __pa(pmd)))
+-#define pgd_populate(mm, pgd, pud) \
+- set_pgd(pgd, __pgd(_PAGE_TABLE | __pa(pud)))
+-
+-#define pmd_pgtable(pmd) pmd_page(pmd)
+-
+-static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte)
+-{
+- set_pmd(pmd, __pmd(_PAGE_TABLE | (page_to_pfn(pte) << PAGE_SHIFT)));
+-}
+-
+-static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+-{
+- BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
+- free_page((unsigned long)pmd);
+-}
+-
+-static inline pmd_t *pmd_alloc_one (struct mm_struct *mm, unsigned long addr)
+-{
+- return (pmd_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
+-}
+-
+-static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
+-{
+- return (pud_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
+-}
+-
+-static inline void pud_free(struct mm_struct *mm, pud_t *pud)
+-{
+- BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
+- free_page((unsigned long)pud);
+-}
+-
+-static inline void pgd_list_add(pgd_t *pgd)
+-{
+- struct page *page = virt_to_page(pgd);
+- unsigned long flags;
+-
+- spin_lock_irqsave(&pgd_lock, flags);
+- list_add(&page->lru, &pgd_list);
+- spin_unlock_irqrestore(&pgd_lock, flags);
+-}
+-
+-static inline void pgd_list_del(pgd_t *pgd)
+-{
+- struct page *page = virt_to_page(pgd);
+- unsigned long flags;
+-
+- spin_lock_irqsave(&pgd_lock, flags);
+- list_del(&page->lru);
+- spin_unlock_irqrestore(&pgd_lock, flags);
+-}
+-
+-static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+-{
+- unsigned boundary;
+- pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
+- if (!pgd)
+- return NULL;
+- pgd_list_add(pgd);
+- /*
+- * Copy kernel pointers in from init.
+- * Could keep a freelist or slab cache of those because the kernel
+- * part never changes.
+- */
+- boundary = pgd_index(__PAGE_OFFSET);
+- memset(pgd, 0, boundary * sizeof(pgd_t));
+- memcpy(pgd + boundary,
+- init_level4_pgt + boundary,
+- (PTRS_PER_PGD - boundary) * sizeof(pgd_t));
+- return pgd;
+-}
+-
+-static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+-{
+- BUG_ON((unsigned long)pgd & (PAGE_SIZE-1));
+- pgd_list_del(pgd);
+- free_page((unsigned long)pgd);
+-}
+-
+-static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+-{
+- return (pte_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
+-}
+-
+-static inline pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
+-{
+- struct page *page;
+- void *p;
+-
+- p = (void *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
+- if (!p)
+- return NULL;
+- page = virt_to_page(p);
+- pgtable_page_ctor(page);
+- return page;
+-}
+-
+-/* Should really implement gc for free page table pages. This could be
+- done with a reference count in struct page. */
+-
+-static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+-{
+- BUG_ON((unsigned long)pte & (PAGE_SIZE-1));
+- free_page((unsigned long)pte);
+-}
+-
+-static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
+-{
+- pgtable_page_dtor(pte);
+- __free_page(pte);
+-}
+-
+-#define __pte_free_tlb(tlb,pte) \
+-do { \
+- pgtable_page_dtor((pte)); \
+- tlb_remove_page((tlb), (pte)); \
+-} while (0)
+-
+-#define __pmd_free_tlb(tlb,x) tlb_remove_page((tlb),virt_to_page(x))
+-#define __pud_free_tlb(tlb,x) tlb_remove_page((tlb),virt_to_page(x))
+-
+-#endif /* _X86_64_PGALLOC_H */
+diff --git a/include/asm-x86/pgtable-2level.h b/include/asm-x86/pgtable-2level.h
+index 701404f..46bc52c 100644
+--- a/include/asm-x86/pgtable-2level.h
++++ b/include/asm-x86/pgtable-2level.h
+@@ -26,7 +26,8 @@ static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte)
+ native_set_pte(ptep, pte);
+ }
+
+-static inline void native_set_pte_present(struct mm_struct *mm, unsigned long addr,
++static inline void native_set_pte_present(struct mm_struct *mm,
++ unsigned long addr,
+ pte_t *ptep, pte_t pte)
+ {
+ native_set_pte(ptep, pte);
+@@ -37,7 +38,8 @@ static inline void native_pmd_clear(pmd_t *pmdp)
+ native_set_pmd(pmdp, __pmd(0));
+ }
+
+-static inline void native_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *xp)
++static inline void native_pte_clear(struct mm_struct *mm,
++ unsigned long addr, pte_t *xp)
+ {
+ *xp = native_make_pte(0);
+ }
+@@ -61,16 +63,18 @@ static inline pte_t native_ptep_get_and_clear(pte_t *xp)
+ */
+ #define PTE_FILE_MAX_BITS 29
+
+-#define pte_to_pgoff(pte) \
+- ((((pte).pte_low >> 1) & 0x1f ) + (((pte).pte_low >> 8) << 5 ))
++#define pte_to_pgoff(pte) \
++ ((((pte).pte_low >> 1) & 0x1f) + (((pte).pte_low >> 8) << 5))
+
+-#define pgoff_to_pte(off) \
+- ((pte_t) { .pte_low = (((off) & 0x1f) << 1) + (((off) >> 5) << 8) + _PAGE_FILE })
++#define pgoff_to_pte(off) \
++ ((pte_t) { .pte_low = (((off) & 0x1f) << 1) + \
++ (((off) >> 5) << 8) + _PAGE_FILE })
+
+ /* Encode and de-code a swap entry */
+ #define __swp_type(x) (((x).val >> 1) & 0x1f)
+ #define __swp_offset(x) ((x).val >> 8)
+-#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) })
++#define __swp_entry(type, offset) \
++ ((swp_entry_t) { ((type) << 1) | ((offset) << 8) })
+ #define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_low })
+ #define __swp_entry_to_pte(x) ((pte_t) { .pte = (x).val })
+
+diff --git a/include/asm-x86/pgtable-3level.h b/include/asm-x86/pgtable-3level.h
+index 1d763ee..8b4a9d4 100644
+--- a/include/asm-x86/pgtable-3level.h
++++ b/include/asm-x86/pgtable-3level.h
+@@ -8,22 +8,26 @@
+ * Copyright (C) 1999 Ingo Molnar <mingo at redhat.com>
+ */
+
+-#define pte_ERROR(e) \
+- printk("%s:%d: bad pte %p(%08lx%08lx).\n", __FILE__, __LINE__, &(e), (e).pte_high, (e).pte_low)
+-#define pmd_ERROR(e) \
+- printk("%s:%d: bad pmd %p(%016Lx).\n", __FILE__, __LINE__, &(e), pmd_val(e))
+-#define pgd_ERROR(e) \
+- printk("%s:%d: bad pgd %p(%016Lx).\n", __FILE__, __LINE__, &(e), pgd_val(e))
+-
++#define pte_ERROR(e) \
++ printk("%s:%d: bad pte %p(%08lx%08lx).\n", \
++ __FILE__, __LINE__, &(e), (e).pte_high, (e).pte_low)
++#define pmd_ERROR(e) \
++ printk("%s:%d: bad pmd %p(%016Lx).\n", \
++ __FILE__, __LINE__, &(e), pmd_val(e))
++#define pgd_ERROR(e) \
++ printk("%s:%d: bad pgd %p(%016Lx).\n", \
++ __FILE__, __LINE__, &(e), pgd_val(e))
+
+ static inline int pud_none(pud_t pud)
+ {
+ return pud_val(pud) == 0;
+ }
++
+ static inline int pud_bad(pud_t pud)
+ {
+ return (pud_val(pud) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER)) != 0;
+ }
++
+ static inline int pud_present(pud_t pud)
+ {
+ return pud_val(pud) & _PAGE_PRESENT;
+@@ -48,7 +52,8 @@ static inline void native_set_pte(pte_t *ptep, pte_t pte)
+ * we are justified in merely clearing the PTE present bit, followed
+ * by a set. The ordering here is important.
+ */
+-static inline void native_set_pte_present(struct mm_struct *mm, unsigned long addr,
++static inline void native_set_pte_present(struct mm_struct *mm,
++ unsigned long addr,
+ pte_t *ptep, pte_t pte)
+ {
+ ptep->pte_low = 0;
+@@ -60,15 +65,17 @@ static inline void native_set_pte_present(struct mm_struct *mm, unsigned long ad
+
+ static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte)
+ {
+- set_64bit((unsigned long long *)(ptep),native_pte_val(pte));
++ set_64bit((unsigned long long *)(ptep), native_pte_val(pte));
+ }
++
+ static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd)
+ {
+- set_64bit((unsigned long long *)(pmdp),native_pmd_val(pmd));
++ set_64bit((unsigned long long *)(pmdp), native_pmd_val(pmd));
+ }
++
+ static inline void native_set_pud(pud_t *pudp, pud_t pud)
+ {
+- set_64bit((unsigned long long *)(pudp),native_pud_val(pud));
++ set_64bit((unsigned long long *)(pudp), native_pud_val(pud));
+ }
+
+ /*
+@@ -76,7 +83,8 @@ static inline void native_set_pud(pud_t *pudp, pud_t pud)
+ * entry, so clear the bottom half first and enforce ordering with a compiler
+ * barrier.
+ */
+-static inline void native_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
++static inline void native_pte_clear(struct mm_struct *mm, unsigned long addr,
++ pte_t *ptep)
+ {
+ ptep->pte_low = 0;
+ smp_wmb();
+@@ -107,20 +115,19 @@ static inline void pud_clear(pud_t *pudp)
+ * current pgd to avoid unnecessary TLB flushes.
+ */
+ pgd = read_cr3();
+- if (__pa(pudp) >= pgd && __pa(pudp) < (pgd + sizeof(pgd_t)*PTRS_PER_PGD))
++ if (__pa(pudp) >= pgd && __pa(pudp) <
++ (pgd + sizeof(pgd_t)*PTRS_PER_PGD))
+ write_cr3(pgd);
+ }
+
+-#define pud_page(pud) \
+-((struct page *) __va(pud_val(pud) & PAGE_MASK))
++#define pud_page(pud) ((struct page *) __va(pud_val(pud) & PAGE_MASK))
+
+-#define pud_page_vaddr(pud) \
+-((unsigned long) __va(pud_val(pud) & PAGE_MASK))
++#define pud_page_vaddr(pud) ((unsigned long) __va(pud_val(pud) & PAGE_MASK))
+
+
+ /* Find an entry in the second-level page table.. */
+-#define pmd_offset(pud, address) ((pmd_t *) pud_page(*(pud)) + \
+- pmd_index(address))
++#define pmd_offset(pud, address) ((pmd_t *)pud_page(*(pud)) + \
++ pmd_index(address))
+
+ #ifdef CONFIG_SMP
+ static inline pte_t native_ptep_get_and_clear(pte_t *ptep)
+@@ -161,7 +168,8 @@ static inline unsigned long pte_pfn(pte_t pte)
+ * put the 32 bits of offset into the high part.
+ */
+ #define pte_to_pgoff(pte) ((pte).pte_high)
+-#define pgoff_to_pte(off) ((pte_t) { { .pte_low = _PAGE_FILE, .pte_high = (off) } })
++#define pgoff_to_pte(off) \
++ ((pte_t) { { .pte_low = _PAGE_FILE, .pte_high = (off) } })
+ #define PTE_FILE_MAX_BITS 32
+
+ /* Encode and de-code a swap entry */
+diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h
+index 9cf472a..a496d63 100644
+--- a/include/asm-x86/pgtable.h
++++ b/include/asm-x86/pgtable.h
+@@ -1,16 +1,15 @@
+ #ifndef _ASM_X86_PGTABLE_H
+ #define _ASM_X86_PGTABLE_H
+
+-#define USER_PTRS_PER_PGD ((TASK_SIZE-1)/PGDIR_SIZE+1)
+ #define FIRST_USER_ADDRESS 0
+
+-#define _PAGE_BIT_PRESENT 0
+-#define _PAGE_BIT_RW 1
+-#define _PAGE_BIT_USER 2
+-#define _PAGE_BIT_PWT 3
+-#define _PAGE_BIT_PCD 4
+-#define _PAGE_BIT_ACCESSED 5
+-#define _PAGE_BIT_DIRTY 6
++#define _PAGE_BIT_PRESENT 0 /* is present */
++#define _PAGE_BIT_RW 1 /* writeable */
++#define _PAGE_BIT_USER 2 /* userspace addressable */
++#define _PAGE_BIT_PWT 3 /* page write through */
++#define _PAGE_BIT_PCD 4 /* page cache disabled */
++#define _PAGE_BIT_ACCESSED 5 /* was accessed (raised by CPU) */
++#define _PAGE_BIT_DIRTY 6 /* was written to (raised by CPU) */
+ #define _PAGE_BIT_FILE 6
+ #define _PAGE_BIT_PSE 7 /* 4 MB (or 2MB) page */
+ #define _PAGE_BIT_PAT 7 /* on 4KB pages */
+@@ -48,24 +47,39 @@
+ #endif
+
+ /* If _PAGE_PRESENT is clear, we use these: */
+-#define _PAGE_FILE _PAGE_DIRTY /* nonlinear file mapping, saved PTE; unset:swap */
++#define _PAGE_FILE _PAGE_DIRTY /* nonlinear file mapping,
++ * saved PTE; unset:swap */
+ #define _PAGE_PROTNONE _PAGE_PSE /* if the user mapped it with PROT_NONE;
+ pte_present gives true */
+
+-#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
+-#define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
++#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | \
++ _PAGE_ACCESSED | _PAGE_DIRTY)
++#define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | \
++ _PAGE_DIRTY)
+
+ #define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
+
+-#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
+-#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
++#define _PAGE_CACHE_MASK (_PAGE_PCD | _PAGE_PWT)
++#define _PAGE_CACHE_WB (0)
++#define _PAGE_CACHE_WC (_PAGE_PWT)
++#define _PAGE_CACHE_UC_MINUS (_PAGE_PCD)
++#define _PAGE_CACHE_UC (_PAGE_PCD | _PAGE_PWT)
+
+-#define PAGE_SHARED_EXEC __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
+-#define PAGE_COPY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
+-#define PAGE_COPY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
++#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
++#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | \
++ _PAGE_ACCESSED | _PAGE_NX)
++
++#define PAGE_SHARED_EXEC __pgprot(_PAGE_PRESENT | _PAGE_RW | \
++ _PAGE_USER | _PAGE_ACCESSED)
++#define PAGE_COPY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | \
++ _PAGE_ACCESSED | _PAGE_NX)
++#define PAGE_COPY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | \
++ _PAGE_ACCESSED)
+ #define PAGE_COPY PAGE_COPY_NOEXEC
+-#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
+-#define PAGE_READONLY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
++#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | \
++ _PAGE_ACCESSED | _PAGE_NX)
++#define PAGE_READONLY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | \
++ _PAGE_ACCESSED)
+
+ #ifdef CONFIG_X86_32
+ #define _PAGE_KERNEL_EXEC \
+@@ -84,6 +98,7 @@ extern pteval_t __PAGE_KERNEL, __PAGE_KERNEL_EXEC;
+ #define __PAGE_KERNEL_RO (__PAGE_KERNEL & ~_PAGE_RW)
+ #define __PAGE_KERNEL_RX (__PAGE_KERNEL_EXEC & ~_PAGE_RW)
+ #define __PAGE_KERNEL_EXEC_NOCACHE (__PAGE_KERNEL_EXEC | _PAGE_PCD | _PAGE_PWT)
++#define __PAGE_KERNEL_WC (__PAGE_KERNEL | _PAGE_CACHE_WC)
+ #define __PAGE_KERNEL_NOCACHE (__PAGE_KERNEL | _PAGE_PCD | _PAGE_PWT)
+ #define __PAGE_KERNEL_UC_MINUS (__PAGE_KERNEL | _PAGE_PCD)
+ #define __PAGE_KERNEL_VSYSCALL (__PAGE_KERNEL_RX | _PAGE_USER)
+@@ -101,6 +116,7 @@ extern pteval_t __PAGE_KERNEL, __PAGE_KERNEL_EXEC;
+ #define PAGE_KERNEL_RO MAKE_GLOBAL(__PAGE_KERNEL_RO)
+ #define PAGE_KERNEL_EXEC MAKE_GLOBAL(__PAGE_KERNEL_EXEC)
+ #define PAGE_KERNEL_RX MAKE_GLOBAL(__PAGE_KERNEL_RX)
++#define PAGE_KERNEL_WC MAKE_GLOBAL(__PAGE_KERNEL_WC)
+ #define PAGE_KERNEL_NOCACHE MAKE_GLOBAL(__PAGE_KERNEL_NOCACHE)
+ #define PAGE_KERNEL_UC_MINUS MAKE_GLOBAL(__PAGE_KERNEL_UC_MINUS)
+ #define PAGE_KERNEL_EXEC_NOCACHE MAKE_GLOBAL(__PAGE_KERNEL_EXEC_NOCACHE)
+@@ -134,7 +150,7 @@ extern pteval_t __PAGE_KERNEL, __PAGE_KERNEL_EXEC;
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+-extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
++extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
+ #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+
+ extern spinlock_t pgd_lock;
+@@ -144,30 +160,101 @@ extern struct list_head pgd_list;
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+-static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
+-static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
+-static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
+-static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
+-static inline int pte_huge(pte_t pte) { return pte_val(pte) & _PAGE_PSE; }
+-static inline int pte_global(pte_t pte) { return pte_val(pte) & _PAGE_GLOBAL; }
+-static inline int pte_exec(pte_t pte) { return !(pte_val(pte) & _PAGE_NX); }
+-
+-static inline int pmd_large(pmd_t pte) {
+- return (pmd_val(pte) & (_PAGE_PSE|_PAGE_PRESENT)) ==
+- (_PAGE_PSE|_PAGE_PRESENT);
++static inline int pte_dirty(pte_t pte)
++{
++ return pte_val(pte) & _PAGE_DIRTY;
++}
++
++static inline int pte_young(pte_t pte)
++{
++ return pte_val(pte) & _PAGE_ACCESSED;
++}
++
++static inline int pte_write(pte_t pte)
++{
++ return pte_val(pte) & _PAGE_RW;
++}
++
++static inline int pte_file(pte_t pte)
++{
++ return pte_val(pte) & _PAGE_FILE;
++}
++
++static inline int pte_huge(pte_t pte)
++{
++ return pte_val(pte) & _PAGE_PSE;
++}
++
++static inline int pte_global(pte_t pte)
++{
++ return pte_val(pte) & _PAGE_GLOBAL;
++}
++
++static inline int pte_exec(pte_t pte)
++{
++ return !(pte_val(pte) & _PAGE_NX);
++}
++
++static inline int pmd_large(pmd_t pte)
++{
++ return (pmd_val(pte) & (_PAGE_PSE | _PAGE_PRESENT)) ==
++ (_PAGE_PSE | _PAGE_PRESENT);
++}
++
++static inline pte_t pte_mkclean(pte_t pte)
++{
++ return __pte(pte_val(pte) & ~(pteval_t)_PAGE_DIRTY);
++}
++
++static inline pte_t pte_mkold(pte_t pte)
++{
++ return __pte(pte_val(pte) & ~(pteval_t)_PAGE_ACCESSED);
++}
++
++static inline pte_t pte_wrprotect(pte_t pte)
++{
++ return __pte(pte_val(pte) & ~(pteval_t)_PAGE_RW);
+ }
+
+-static inline pte_t pte_mkclean(pte_t pte) { return __pte(pte_val(pte) & ~(pteval_t)_PAGE_DIRTY); }
+-static inline pte_t pte_mkold(pte_t pte) { return __pte(pte_val(pte) & ~(pteval_t)_PAGE_ACCESSED); }
+-static inline pte_t pte_wrprotect(pte_t pte) { return __pte(pte_val(pte) & ~(pteval_t)_PAGE_RW); }
+-static inline pte_t pte_mkexec(pte_t pte) { return __pte(pte_val(pte) & ~(pteval_t)_PAGE_NX); }
+-static inline pte_t pte_mkdirty(pte_t pte) { return __pte(pte_val(pte) | _PAGE_DIRTY); }
+-static inline pte_t pte_mkyoung(pte_t pte) { return __pte(pte_val(pte) | _PAGE_ACCESSED); }
+-static inline pte_t pte_mkwrite(pte_t pte) { return __pte(pte_val(pte) | _PAGE_RW); }
+-static inline pte_t pte_mkhuge(pte_t pte) { return __pte(pte_val(pte) | _PAGE_PSE); }
+-static inline pte_t pte_clrhuge(pte_t pte) { return __pte(pte_val(pte) & ~(pteval_t)_PAGE_PSE); }
+-static inline pte_t pte_mkglobal(pte_t pte) { return __pte(pte_val(pte) | _PAGE_GLOBAL); }
+-static inline pte_t pte_clrglobal(pte_t pte) { return __pte(pte_val(pte) & ~(pteval_t)_PAGE_GLOBAL); }
++static inline pte_t pte_mkexec(pte_t pte)
++{
++ return __pte(pte_val(pte) & ~(pteval_t)_PAGE_NX);
++}
++
++static inline pte_t pte_mkdirty(pte_t pte)
++{
++ return __pte(pte_val(pte) | _PAGE_DIRTY);
++}
++
++static inline pte_t pte_mkyoung(pte_t pte)
++{
++ return __pte(pte_val(pte) | _PAGE_ACCESSED);
++}
++
++static inline pte_t pte_mkwrite(pte_t pte)
++{
++ return __pte(pte_val(pte) | _PAGE_RW);
++}
++
++static inline pte_t pte_mkhuge(pte_t pte)
++{
++ return __pte(pte_val(pte) | _PAGE_PSE);
++}
++
++static inline pte_t pte_clrhuge(pte_t pte)
++{
++ return __pte(pte_val(pte) & ~(pteval_t)_PAGE_PSE);
++}
++
++static inline pte_t pte_mkglobal(pte_t pte)
++{
++ return __pte(pte_val(pte) | _PAGE_GLOBAL);
++}
++
++static inline pte_t pte_clrglobal(pte_t pte)
++{
++ return __pte(pte_val(pte) & ~(pteval_t)_PAGE_GLOBAL);
++}
+
+ extern pteval_t __supported_pte_mask;
+
+@@ -201,6 +288,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+
+ #define canon_pgprot(p) __pgprot(pgprot_val(p) & __supported_pte_mask)
+
++#ifndef __ASSEMBLY__
++#define __HAVE_PHYS_MEM_ACCESS_PROT
++struct file;
++pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
++ unsigned long size, pgprot_t vma_prot);
++int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
++ unsigned long size, pgprot_t *vma_prot);
++#endif
++
+ #ifdef CONFIG_PARAVIRT
+ #include <asm/paravirt.h>
+ #else /* !CONFIG_PARAVIRT */
+@@ -242,6 +338,9 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+ # include "pgtable_64.h"
+ #endif
+
++#define KERNEL_PGD_BOUNDARY pgd_index(PAGE_OFFSET)
++#define KERNEL_PGD_PTRS (PTRS_PER_PGD - KERNEL_PGD_BOUNDARY)
++
+ #ifndef __ASSEMBLY__
+
+ enum {
+@@ -301,40 +400,21 @@ static inline void native_set_pte_at(struct mm_struct *mm, unsigned long addr,
+ * bit at the same time.
+ */
+ #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+-#define ptep_set_access_flags(vma, address, ptep, entry, dirty) \
+-({ \
+- int __changed = !pte_same(*(ptep), entry); \
+- if (__changed && dirty) { \
+- *ptep = entry; \
+- pte_update_defer((vma)->vm_mm, (address), (ptep)); \
+- flush_tlb_page(vma, address); \
+- } \
+- __changed; \
+-})
++extern int ptep_set_access_flags(struct vm_area_struct *vma,
++ unsigned long address, pte_t *ptep,
++ pte_t entry, int dirty);
+
+ #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+-#define ptep_test_and_clear_young(vma, addr, ptep) ({ \
+- int __ret = 0; \
+- if (pte_young(*(ptep))) \
+- __ret = test_and_clear_bit(_PAGE_BIT_ACCESSED, \
+- &(ptep)->pte); \
+- if (__ret) \
+- pte_update((vma)->vm_mm, addr, ptep); \
+- __ret; \
+-})
++extern int ptep_test_and_clear_young(struct vm_area_struct *vma,
++ unsigned long addr, pte_t *ptep);
+
+ #define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
+-#define ptep_clear_flush_young(vma, address, ptep) \
+-({ \
+- int __young; \
+- __young = ptep_test_and_clear_young((vma), (address), (ptep)); \
+- if (__young) \
+- flush_tlb_page(vma, address); \
+- __young; \
+-})
++extern int ptep_clear_flush_young(struct vm_area_struct *vma,
++ unsigned long address, pte_t *ptep);
+
+ #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+-static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
++static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
++ pte_t *ptep)
+ {
+ pte_t pte = native_ptep_get_and_clear(ptep);
+ pte_update(mm, addr, ptep);
+@@ -342,7 +422,9 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+ }
+
+ #define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
+-static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long addr, pte_t *ptep, int full)
++static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm,
++ unsigned long addr, pte_t *ptep,
++ int full)
+ {
+ pte_t pte;
+ if (full) {
+@@ -358,12 +440,29 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long
+ }
+
+ #define __HAVE_ARCH_PTEP_SET_WRPROTECT
+-static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
++static inline void ptep_set_wrprotect(struct mm_struct *mm,
++ unsigned long addr, pte_t *ptep)
+ {
+ clear_bit(_PAGE_BIT_RW, (unsigned long *)&ptep->pte);
+ pte_update(mm, addr, ptep);
+ }
+
++/*
++ * clone_pgd_range(pgd_t *dst, pgd_t *src, int count);
++ *
++ * dst - pointer to pgd range anwhere on a pgd page
++ * src - ""
++ * count - the number of pgds to copy.
++ *
++ * dst and src can be on the same page, but the range must not overlap,
++ * and must not cross a page boundary.
++ */
++static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
++{
++ memcpy(dst, src, count * sizeof(pgd_t));
++}
++
++
+ #include <asm-generic/pgtable.h>
+ #endif /* __ASSEMBLY__ */
+
+diff --git a/include/asm-x86/pgtable_32.h b/include/asm-x86/pgtable_32.h
+index 4e6a0fc..577ab79 100644
+--- a/include/asm-x86/pgtable_32.h
++++ b/include/asm-x86/pgtable_32.h
+@@ -40,16 +40,13 @@ void paging_init(void);
+ #ifdef CONFIG_X86_PAE
+ # include <asm/pgtable-3level-defs.h>
+ # define PMD_SIZE (1UL << PMD_SHIFT)
+-# define PMD_MASK (~(PMD_SIZE-1))
++# define PMD_MASK (~(PMD_SIZE - 1))
+ #else
+ # include <asm/pgtable-2level-defs.h>
+ #endif
+
+ #define PGDIR_SIZE (1UL << PGDIR_SHIFT)
+-#define PGDIR_MASK (~(PGDIR_SIZE-1))
+-
+-#define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
+-#define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
++#define PGDIR_MASK (~(PGDIR_SIZE - 1))
+
+ /* Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+@@ -58,21 +55,22 @@ void paging_init(void);
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+-#define VMALLOC_OFFSET (8*1024*1024)
+-#define VMALLOC_START (((unsigned long) high_memory + \
+- 2*VMALLOC_OFFSET-1) & ~(VMALLOC_OFFSET-1))
++#define VMALLOC_OFFSET (8 * 1024 * 1024)
++#define VMALLOC_START (((unsigned long)high_memory + 2 * VMALLOC_OFFSET - 1) \
++ & ~(VMALLOC_OFFSET - 1))
+ #ifdef CONFIG_X86_PAE
+ #define LAST_PKMAP 512
+ #else
+ #define LAST_PKMAP 1024
+ #endif
+
+-#define PKMAP_BASE ((FIXADDR_BOOT_START - PAGE_SIZE*(LAST_PKMAP + 1)) & PMD_MASK)
++#define PKMAP_BASE ((FIXADDR_BOOT_START - PAGE_SIZE * (LAST_PKMAP + 1)) \
++ & PMD_MASK)
+
+ #ifdef CONFIG_HIGHMEM
+-# define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE)
++# define VMALLOC_END (PKMAP_BASE - 2 * PAGE_SIZE)
+ #else
+-# define VMALLOC_END (FIXADDR_START-2*PAGE_SIZE)
++# define VMALLOC_END (FIXADDR_START - 2 * PAGE_SIZE)
+ #endif
+
+ /*
+@@ -88,10 +86,16 @@ extern unsigned long pg0[];
+ #define pte_present(x) ((x).pte_low & (_PAGE_PRESENT | _PAGE_PROTNONE))
+
+ /* To avoid harmful races, pmd_none(x) should check only the lower when PAE */
+-#define pmd_none(x) (!(unsigned long)pmd_val(x))
+-#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
+-#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
++#define pmd_none(x) (!(unsigned long)pmd_val((x)))
++#define pmd_present(x) (pmd_val((x)) & _PAGE_PRESENT)
++
++extern int pmd_bad(pmd_t pmd);
+
++#define pmd_bad_v1(x) \
++ (_KERNPG_TABLE != (pmd_val((x)) & ~(PAGE_MASK | _PAGE_USER)))
++#define pmd_bad_v2(x) \
++ (_KERNPG_TABLE != (pmd_val((x)) & ~(PAGE_MASK | _PAGE_USER | \
++ _PAGE_PSE | _PAGE_NX)))
+
+ #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
+
+@@ -102,32 +106,18 @@ extern unsigned long pg0[];
+ #endif
+
+ /*
+- * clone_pgd_range(pgd_t *dst, pgd_t *src, int count);
+- *
+- * dst - pointer to pgd range anwhere on a pgd page
+- * src - ""
+- * count - the number of pgds to copy.
+- *
+- * dst and src can be on the same page, but the range must not overlap,
+- * and must not cross a page boundary.
+- */
+-static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
+-{
+- memcpy(dst, src, count * sizeof(pgd_t));
+-}
+-
+-/*
+- * Macro to mark a page protection value as "uncacheable". On processors which do not support
+- * it, this is a no-op.
++ * Macro to mark a page protection value as "uncacheable".
++ * On processors which do not support it, this is a no-op.
+ */
+-#define pgprot_noncached(prot) ((boot_cpu_data.x86 > 3) \
+- ? (__pgprot(pgprot_val(prot) | _PAGE_PCD | _PAGE_PWT)) : (prot))
++#define pgprot_noncached(prot) \
++ ((boot_cpu_data.x86 > 3) \
++ ? (__pgprot(pgprot_val(prot) | _PAGE_PCD | _PAGE_PWT)) \
++ : (prot))
+
+ /*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+-
+ #define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
+
+ /*
+@@ -136,20 +126,20 @@ static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
+ * this macro returns the index of the entry in the pgd page which would
+ * control the given virtual address
+ */
+-#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+-#define pgd_index_k(addr) pgd_index(addr)
++#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
++#define pgd_index_k(addr) pgd_index((addr))
+
+ /*
+ * pgd_offset() returns a (pgd_t *)
+ * pgd_index() is used get the offset into the pgd page's array of pgd_t's;
+ */
+-#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
++#define pgd_offset(mm, address) ((mm)->pgd + pgd_index((address)))
+
+ /*
+ * a shortcut which implies the use of the kernel's pgd, instead
+ * of a process's
+ */
+-#define pgd_offset_k(address) pgd_offset(&init_mm, address)
++#define pgd_offset_k(address) pgd_offset(&init_mm, (address))
+
+ static inline int pud_large(pud_t pud) { return 0; }
+
+@@ -159,8 +149,8 @@ static inline int pud_large(pud_t pud) { return 0; }
+ * this macro returns the index of the entry in the pmd page which would
+ * control the given virtual address
+ */
+-#define pmd_index(address) \
+- (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
++#define pmd_index(address) \
++ (((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
+
+ /*
+ * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE]
+@@ -168,54 +158,56 @@ static inline int pud_large(pud_t pud) { return 0; }
+ * this macro returns the index of the entry in the pte page which would
+ * control the given virtual address
+ */
+-#define pte_index(address) \
+- (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+-#define pte_offset_kernel(dir, address) \
+- ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(address))
++#define pte_index(address) \
++ (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
++#define pte_offset_kernel(dir, address) \
++ ((pte_t *)pmd_page_vaddr(*(dir)) + pte_index((address)))
+
+-#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
++#define pmd_page(pmd) (pfn_to_page(pmd_val((pmd)) >> PAGE_SHIFT))
+
+-#define pmd_page_vaddr(pmd) \
+- ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
++#define pmd_page_vaddr(pmd) \
++ ((unsigned long)__va(pmd_val((pmd)) & PAGE_MASK))
+
+ #if defined(CONFIG_HIGHPTE)
+-#define pte_offset_map(dir, address) \
+- ((pte_t *)kmap_atomic_pte(pmd_page(*(dir)),KM_PTE0) + pte_index(address))
+-#define pte_offset_map_nested(dir, address) \
+- ((pte_t *)kmap_atomic_pte(pmd_page(*(dir)),KM_PTE1) + pte_index(address))
+-#define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0)
+-#define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1)
++#define pte_offset_map(dir, address) \
++ ((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), KM_PTE0) + \
++ pte_index((address)))
++#define pte_offset_map_nested(dir, address) \
++ ((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), KM_PTE1) + \
++ pte_index((address)))
++#define pte_unmap(pte) kunmap_atomic((pte), KM_PTE0)
++#define pte_unmap_nested(pte) kunmap_atomic((pte), KM_PTE1)
+ #else
+-#define pte_offset_map(dir, address) \
+- ((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address))
+-#define pte_offset_map_nested(dir, address) pte_offset_map(dir, address)
++#define pte_offset_map(dir, address) \
++ ((pte_t *)page_address(pmd_page(*(dir))) + pte_index((address)))
++#define pte_offset_map_nested(dir, address) pte_offset_map((dir), (address))
+ #define pte_unmap(pte) do { } while (0)
+ #define pte_unmap_nested(pte) do { } while (0)
+ #endif
+
+ /* Clear a kernel PTE and flush it from the TLB */
+-#define kpte_clear_flush(ptep, vaddr) \
+-do { \
+- pte_clear(&init_mm, vaddr, ptep); \
+- __flush_tlb_one(vaddr); \
++#define kpte_clear_flush(ptep, vaddr) \
++do { \
++ pte_clear(&init_mm, (vaddr), (ptep)); \
++ __flush_tlb_one((vaddr)); \
+ } while (0)
+
+ /*
+ * The i386 doesn't have any external MMU info: the kernel page
+ * tables contain all the necessary information.
+ */
+-#define update_mmu_cache(vma,address,pte) do { } while (0)
++#define update_mmu_cache(vma, address, pte) do { } while (0)
+
+-void native_pagetable_setup_start(pgd_t *base);
+-void native_pagetable_setup_done(pgd_t *base);
++extern void native_pagetable_setup_start(pgd_t *base);
++extern void native_pagetable_setup_done(pgd_t *base);
+
+ #ifndef CONFIG_PARAVIRT
+-static inline void paravirt_pagetable_setup_start(pgd_t *base)
++static inline void __init paravirt_pagetable_setup_start(pgd_t *base)
+ {
+ native_pagetable_setup_start(base);
+ }
+
+-static inline void paravirt_pagetable_setup_done(pgd_t *base)
++static inline void __init paravirt_pagetable_setup_done(pgd_t *base)
+ {
+ native_pagetable_setup_done(base);
+ }
+@@ -233,7 +225,7 @@ static inline void paravirt_pagetable_setup_done(pgd_t *base)
+ #define kern_addr_valid(kaddr) (0)
+ #endif
+
+-#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+- remap_pfn_range(vma, vaddr, pfn, size, prot)
++#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
++ remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+ #endif /* _I386_PGTABLE_H */
+diff --git a/include/asm-x86/pgtable_64.h b/include/asm-x86/pgtable_64.h
+index 0a0b77b..a3bbf87 100644
+--- a/include/asm-x86/pgtable_64.h
++++ b/include/asm-x86/pgtable_64.h
+@@ -24,7 +24,7 @@ extern void paging_init(void);
+
+ #endif /* !__ASSEMBLY__ */
+
+-#define SHARED_KERNEL_PMD 1
++#define SHARED_KERNEL_PMD 0
+
+ /*
+ * PGDIR_SHIFT determines what a top-level page table entry can map
+@@ -52,14 +52,18 @@ extern void paging_init(void);
+
+ #ifndef __ASSEMBLY__
+
+-#define pte_ERROR(e) \
+- printk("%s:%d: bad pte %p(%016lx).\n", __FILE__, __LINE__, &(e), pte_val(e))
+-#define pmd_ERROR(e) \
+- printk("%s:%d: bad pmd %p(%016lx).\n", __FILE__, __LINE__, &(e), pmd_val(e))
+-#define pud_ERROR(e) \
+- printk("%s:%d: bad pud %p(%016lx).\n", __FILE__, __LINE__, &(e), pud_val(e))
+-#define pgd_ERROR(e) \
+- printk("%s:%d: bad pgd %p(%016lx).\n", __FILE__, __LINE__, &(e), pgd_val(e))
++#define pte_ERROR(e) \
++ printk("%s:%d: bad pte %p(%016lx).\n", \
++ __FILE__, __LINE__, &(e), pte_val(e))
++#define pmd_ERROR(e) \
++ printk("%s:%d: bad pmd %p(%016lx).\n", \
++ __FILE__, __LINE__, &(e), pmd_val(e))
++#define pud_ERROR(e) \
++ printk("%s:%d: bad pud %p(%016lx).\n", \
++ __FILE__, __LINE__, &(e), pud_val(e))
++#define pgd_ERROR(e) \
++ printk("%s:%d: bad pgd %p(%016lx).\n", \
++ __FILE__, __LINE__, &(e), pgd_val(e))
+
+ #define pgd_none(x) (!pgd_val(x))
+ #define pud_none(x) (!pud_val(x))
+@@ -87,7 +91,8 @@ static inline pte_t native_ptep_get_and_clear(pte_t *xp)
+ #ifdef CONFIG_SMP
+ return native_make_pte(xchg(&xp->pte, 0));
+ #else
+- /* native_local_ptep_get_and_clear, but duplicated because of cyclic dependency */
++ /* native_local_ptep_get_and_clear,
++ but duplicated because of cyclic dependency */
+ pte_t ret = *xp;
+ native_pte_clear(NULL, 0, xp);
+ return ret;
+@@ -119,7 +124,7 @@ static inline void native_set_pgd(pgd_t *pgdp, pgd_t pgd)
+ *pgdp = pgd;
+ }
+
+-static inline void native_pgd_clear(pgd_t * pgd)
++static inline void native_pgd_clear(pgd_t *pgd)
+ {
+ native_set_pgd(pgd, native_make_pgd(0));
+ }
+@@ -128,19 +133,19 @@ static inline void native_pgd_clear(pgd_t * pgd)
+
+ #endif /* !__ASSEMBLY__ */
+
+-#define PMD_SIZE (_AC(1,UL) << PMD_SHIFT)
+-#define PMD_MASK (~(PMD_SIZE-1))
+-#define PUD_SIZE (_AC(1,UL) << PUD_SHIFT)
+-#define PUD_MASK (~(PUD_SIZE-1))
+-#define PGDIR_SIZE (_AC(1,UL) << PGDIR_SHIFT)
+-#define PGDIR_MASK (~(PGDIR_SIZE-1))
++#define PMD_SIZE (_AC(1, UL) << PMD_SHIFT)
++#define PMD_MASK (~(PMD_SIZE - 1))
++#define PUD_SIZE (_AC(1, UL) << PUD_SHIFT)
++#define PUD_MASK (~(PUD_SIZE - 1))
++#define PGDIR_SIZE (_AC(1, UL) << PGDIR_SHIFT)
++#define PGDIR_MASK (~(PGDIR_SIZE - 1))
+
+
+-#define MAXMEM _AC(0x3fffffffffff, UL)
++#define MAXMEM _AC(0x00003fffffffffff, UL)
+ #define VMALLOC_START _AC(0xffffc20000000000, UL)
+ #define VMALLOC_END _AC(0xffffe1ffffffffff, UL)
+ #define VMEMMAP_START _AC(0xffffe20000000000, UL)
+-#define MODULES_VADDR _AC(0xffffffff88000000, UL)
++#define MODULES_VADDR _AC(0xffffffffa0000000, UL)
+ #define MODULES_END _AC(0xfffffffffff00000, UL)
+ #define MODULES_LEN (MODULES_END - MODULES_VADDR)
+
+@@ -153,26 +158,28 @@ static inline unsigned long pgd_bad(pgd_t pgd)
+
+ static inline unsigned long pud_bad(pud_t pud)
+ {
+- return pud_val(pud) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER);
++ return pud_val(pud) &
++ ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER | _PAGE_PSE | _PAGE_NX);
+ }
+
+ static inline unsigned long pmd_bad(pmd_t pmd)
+ {
+- return pmd_val(pmd) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER);
++ return pmd_val(pmd) &
++ ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER | _PAGE_PSE | _PAGE_NX);
+ }
+
+-#define pte_none(x) (!pte_val(x))
+-#define pte_present(x) (pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE))
++#define pte_none(x) (!pte_val((x)))
++#define pte_present(x) (pte_val((x)) & (_PAGE_PRESENT | _PAGE_PROTNONE))
+
+-#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) /* FIXME: is this right? */
+-#define pte_page(x) pfn_to_page(pte_pfn(x))
+-#define pte_pfn(x) ((pte_val(x) & __PHYSICAL_MASK) >> PAGE_SHIFT)
++#define pages_to_mb(x) ((x) >> (20 - PAGE_SHIFT)) /* FIXME: is this right? */
++#define pte_page(x) pfn_to_page(pte_pfn((x)))
++#define pte_pfn(x) ((pte_val((x)) & __PHYSICAL_MASK) >> PAGE_SHIFT)
+
+ /*
+ * Macro to mark a page protection value as "uncacheable".
+ */
+-#define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_PCD | _PAGE_PWT))
+-
++#define pgprot_noncached(prot) \
++ (__pgprot(pgprot_val((prot)) | _PAGE_PCD | _PAGE_PWT))
+
+ /*
+ * Conversion functions: convert a page and protection to a page entry,
+@@ -182,75 +189,81 @@ static inline unsigned long pmd_bad(pmd_t pmd)
+ /*
+ * Level 4 access.
+ */
+-#define pgd_page_vaddr(pgd) ((unsigned long) __va((unsigned long)pgd_val(pgd) & PTE_MASK))
+-#define pgd_page(pgd) (pfn_to_page(pgd_val(pgd) >> PAGE_SHIFT))
+-#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+-#define pgd_offset(mm, addr) ((mm)->pgd + pgd_index(addr))
+-#define pgd_offset_k(address) (init_level4_pgt + pgd_index(address))
++#define pgd_page_vaddr(pgd) \
++ ((unsigned long)__va((unsigned long)pgd_val((pgd)) & PTE_MASK))
++#define pgd_page(pgd) (pfn_to_page(pgd_val((pgd)) >> PAGE_SHIFT))
++#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
++#define pgd_offset(mm, address) ((mm)->pgd + pgd_index((address)))
++#define pgd_offset_k(address) (init_level4_pgt + pgd_index((address)))
+ #define pgd_present(pgd) (pgd_val(pgd) & _PAGE_PRESENT)
+ static inline int pgd_large(pgd_t pgd) { return 0; }
+ #define mk_kernel_pgd(address) ((pgd_t){ (address) | _KERNPG_TABLE })
+
+ /* PUD - Level3 access */
+ /* to find an entry in a page-table-directory. */
+-#define pud_page_vaddr(pud) ((unsigned long) __va(pud_val(pud) & PHYSICAL_PAGE_MASK))
+-#define pud_page(pud) (pfn_to_page(pud_val(pud) >> PAGE_SHIFT))
+-#define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
+-#define pud_offset(pgd, address) ((pud_t *) pgd_page_vaddr(*(pgd)) + pud_index(address))
+-#define pud_present(pud) (pud_val(pud) & _PAGE_PRESENT)
++#define pud_page_vaddr(pud) \
++ ((unsigned long)__va(pud_val((pud)) & PHYSICAL_PAGE_MASK))
++#define pud_page(pud) (pfn_to_page(pud_val((pud)) >> PAGE_SHIFT))
++#define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))
++#define pud_offset(pgd, address) \
++ ((pud_t *)pgd_page_vaddr(*(pgd)) + pud_index((address)))
++#define pud_present(pud) (pud_val((pud)) & _PAGE_PRESENT)
+
+ static inline int pud_large(pud_t pte)
+ {
+- return (pud_val(pte) & (_PAGE_PSE|_PAGE_PRESENT)) ==
+- (_PAGE_PSE|_PAGE_PRESENT);
++ return (pud_val(pte) & (_PAGE_PSE | _PAGE_PRESENT)) ==
++ (_PAGE_PSE | _PAGE_PRESENT);
+ }
+
+ /* PMD - Level 2 access */
+-#define pmd_page_vaddr(pmd) ((unsigned long) __va(pmd_val(pmd) & PTE_MASK))
+-#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
+-
+-#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
+-#define pmd_offset(dir, address) ((pmd_t *) pud_page_vaddr(*(dir)) + \
+- pmd_index(address))
+-#define pmd_none(x) (!pmd_val(x))
+-#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
+-#define pfn_pmd(nr,prot) (__pmd(((nr) << PAGE_SHIFT) | pgprot_val(prot)))
+-#define pmd_pfn(x) ((pmd_val(x) & __PHYSICAL_MASK) >> PAGE_SHIFT)
+-
+-#define pte_to_pgoff(pte) ((pte_val(pte) & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT)
+-#define pgoff_to_pte(off) ((pte_t) { .pte = ((off) << PAGE_SHIFT) | _PAGE_FILE })
++#define pmd_page_vaddr(pmd) ((unsigned long) __va(pmd_val((pmd)) & PTE_MASK))
++#define pmd_page(pmd) (pfn_to_page(pmd_val((pmd)) >> PAGE_SHIFT))
++
++#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
++#define pmd_offset(dir, address) ((pmd_t *)pud_page_vaddr(*(dir)) + \
++ pmd_index(address))
++#define pmd_none(x) (!pmd_val((x)))
++#define pmd_present(x) (pmd_val((x)) & _PAGE_PRESENT)
++#define pfn_pmd(nr, prot) (__pmd(((nr) << PAGE_SHIFT) | pgprot_val((prot))))
++#define pmd_pfn(x) ((pmd_val((x)) & __PHYSICAL_MASK) >> PAGE_SHIFT)
++
++#define pte_to_pgoff(pte) ((pte_val((pte)) & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT)
++#define pgoff_to_pte(off) ((pte_t) { .pte = ((off) << PAGE_SHIFT) | \
++ _PAGE_FILE })
+ #define PTE_FILE_MAX_BITS __PHYSICAL_MASK_SHIFT
+
+ /* PTE - Level 1 access. */
+
+ /* page, protection -> pte */
+-#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
+-
+-#define pte_index(address) \
+- (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
++#define mk_pte(page, pgprot) pfn_pte(page_to_pfn((page)), (pgprot))
++
++#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+ #define pte_offset_kernel(dir, address) ((pte_t *) pmd_page_vaddr(*(dir)) + \
+- pte_index(address))
++ pte_index((address)))
+
+ /* x86-64 always has all page tables mapped. */
+-#define pte_offset_map(dir,address) pte_offset_kernel(dir,address)
+-#define pte_offset_map_nested(dir,address) pte_offset_kernel(dir,address)
++#define pte_offset_map(dir, address) pte_offset_kernel((dir), (address))
++#define pte_offset_map_nested(dir, address) pte_offset_kernel((dir), (address))
+ #define pte_unmap(pte) /* NOP */
+-#define pte_unmap_nested(pte) /* NOP */
++#define pte_unmap_nested(pte) /* NOP */
++
++#define update_mmu_cache(vma, address, pte) do { } while (0)
+
+-#define update_mmu_cache(vma,address,pte) do { } while (0)
++extern int direct_gbpages;
+
+ /* Encode and de-code a swap entry */
+ #define __swp_type(x) (((x).val >> 1) & 0x3f)
+ #define __swp_offset(x) ((x).val >> 8)
+-#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) })
+-#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
++#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 1) | \
++ ((offset) << 8) })
++#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val((pte)) })
+ #define __swp_entry_to_pte(x) ((pte_t) { .pte = (x).val })
+
+-extern int kern_addr_valid(unsigned long addr);
++extern int kern_addr_valid(unsigned long addr);
+ extern void cleanup_highmap(void);
+
+-#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+- remap_pfn_range(vma, vaddr, pfn, size, prot)
++#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
++ remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+ #define HAVE_ARCH_UNMAPPED_AREA
+ #define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
+@@ -263,8 +276,10 @@ extern void cleanup_highmap(void);
+
+ /* fs/proc/kcore.c */
+ #define kc_vaddr_to_offset(v) ((v) & __VIRTUAL_MASK)
+-#define kc_offset_to_vaddr(o) \
+- (((o) & (1UL << (__VIRTUAL_MASK_SHIFT-1))) ? ((o) | (~__VIRTUAL_MASK)) : (o))
++#define kc_offset_to_vaddr(o) \
++ (((o) & (1UL << (__VIRTUAL_MASK_SHIFT - 1))) \
++ ? ((o) | ~__VIRTUAL_MASK) \
++ : (o))
+
+ #define __HAVE_ARCH_PTE_SAME
+ #endif /* !__ASSEMBLY__ */
+diff --git a/include/asm-x86/posix_types_32.h b/include/asm-x86/posix_types_32.h
+index 015e539..b031efd 100644
+--- a/include/asm-x86/posix_types_32.h
++++ b/include/asm-x86/posix_types_32.h
+@@ -45,32 +45,39 @@ typedef struct {
+ #if defined(__KERNEL__)
+
+ #undef __FD_SET
+-#define __FD_SET(fd,fdsetp) \
+- __asm__ __volatile__("btsl %1,%0": \
+- "+m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd)))
++#define __FD_SET(fd,fdsetp) \
++ asm volatile("btsl %1,%0": \
++ "+m" (*(__kernel_fd_set *)(fdsetp)) \
++ : "r" ((int)(fd)))
+
+ #undef __FD_CLR
+-#define __FD_CLR(fd,fdsetp) \
+- __asm__ __volatile__("btrl %1,%0": \
+- "+m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd)))
++#define __FD_CLR(fd,fdsetp) \
++ asm volatile("btrl %1,%0": \
++ "+m" (*(__kernel_fd_set *)(fdsetp)) \
++ : "r" ((int) (fd)))
+
+ #undef __FD_ISSET
+-#define __FD_ISSET(fd,fdsetp) (__extension__ ({ \
+- unsigned char __result; \
+- __asm__ __volatile__("btl %1,%2 ; setb %0" \
+- :"=q" (__result) :"r" ((int) (fd)), \
+- "m" (*(__kernel_fd_set *) (fdsetp))); \
+- __result; }))
++#define __FD_ISSET(fd,fdsetp) \
++ (__extension__ \
++ ({ \
++ unsigned char __result; \
++ asm volatile("btl %1,%2 ; setb %0" \
++ : "=q" (__result) \
++ : "r" ((int)(fd)), \
++ "m" (*(__kernel_fd_set *)(fdsetp))); \
++ __result; \
++}))
+
+ #undef __FD_ZERO
+-#define __FD_ZERO(fdsetp) \
+-do { \
+- int __d0, __d1; \
+- __asm__ __volatile__("cld ; rep ; stosl" \
+- :"=m" (*(__kernel_fd_set *) (fdsetp)), \
+- "=&c" (__d0), "=&D" (__d1) \
+- :"a" (0), "1" (__FDSET_LONGS), \
+- "2" ((__kernel_fd_set *) (fdsetp)) : "memory"); \
++#define __FD_ZERO(fdsetp) \
++do { \
++ int __d0, __d1; \
++ asm volatile("cld ; rep ; stosl" \
++ : "=m" (*(__kernel_fd_set *)(fdsetp)), \
++ "=&c" (__d0), "=&D" (__d1) \
++ : "a" (0), "1" (__FDSET_LONGS), \
++ "2" ((__kernel_fd_set *)(fdsetp)) \
++ : "memory"); \
+ } while (0)
+
+ #endif /* defined(__KERNEL__) */
+diff --git a/include/asm-x86/posix_types_64.h b/include/asm-x86/posix_types_64.h
+index 9926aa4..d6624c9 100644
+--- a/include/asm-x86/posix_types_64.h
++++ b/include/asm-x86/posix_types_64.h
+@@ -46,7 +46,7 @@ typedef unsigned long __kernel_old_dev_t;
+ #ifdef __KERNEL__
+
+ #undef __FD_SET
+-static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
++static inline void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
+ {
+ unsigned long _tmp = fd / __NFDBITS;
+ unsigned long _rem = fd % __NFDBITS;
+@@ -54,7 +54,7 @@ static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
+ }
+
+ #undef __FD_CLR
+-static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
++static inline void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
+ {
+ unsigned long _tmp = fd / __NFDBITS;
+ unsigned long _rem = fd % __NFDBITS;
+@@ -62,7 +62,7 @@ static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
+ }
+
+ #undef __FD_ISSET
+-static __inline__ int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
++static inline int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
+ {
+ unsigned long _tmp = fd / __NFDBITS;
+ unsigned long _rem = fd % __NFDBITS;
+@@ -74,36 +74,36 @@ static __inline__ int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
+ * for 256 and 1024-bit fd_sets respectively)
+ */
+ #undef __FD_ZERO
+-static __inline__ void __FD_ZERO(__kernel_fd_set *p)
++static inline void __FD_ZERO(__kernel_fd_set *p)
+ {
+ unsigned long *tmp = p->fds_bits;
+ int i;
+
+ if (__builtin_constant_p(__FDSET_LONGS)) {
+ switch (__FDSET_LONGS) {
+- case 32:
+- tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+- tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
+- tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
+- tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
+- tmp[16] = 0; tmp[17] = 0; tmp[18] = 0; tmp[19] = 0;
+- tmp[20] = 0; tmp[21] = 0; tmp[22] = 0; tmp[23] = 0;
+- tmp[24] = 0; tmp[25] = 0; tmp[26] = 0; tmp[27] = 0;
+- tmp[28] = 0; tmp[29] = 0; tmp[30] = 0; tmp[31] = 0;
+- return;
+- case 16:
+- tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+- tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
+- tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
+- tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
+- return;
+- case 8:
+- tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+- tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
+- return;
+- case 4:
+- tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+- return;
++ case 32:
++ tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
++ tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
++ tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
++ tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
++ tmp[16] = 0; tmp[17] = 0; tmp[18] = 0; tmp[19] = 0;
++ tmp[20] = 0; tmp[21] = 0; tmp[22] = 0; tmp[23] = 0;
++ tmp[24] = 0; tmp[25] = 0; tmp[26] = 0; tmp[27] = 0;
++ tmp[28] = 0; tmp[29] = 0; tmp[30] = 0; tmp[31] = 0;
++ return;
++ case 16:
++ tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
++ tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
++ tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
++ tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
++ return;
++ case 8:
++ tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
++ tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
++ return;
++ case 4:
++ tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
++ return;
+ }
+ }
+ i = __FDSET_LONGS;
+diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h
+index 45a2f0a..117343b 100644
+--- a/include/asm-x86/processor.h
++++ b/include/asm-x86/processor.h
+@@ -3,8 +3,7 @@
+
+ #include <asm/processor-flags.h>
+
+-/* migration helpers, for KVM - will be removed in 2.6.25: */
+-#include <asm/vm86.h>
++/* migration helper, for KVM - will be removed in 2.6.25: */
+ #define Xgt_desc_struct desc_ptr
+
+ /* Forward declaration, a strange C thing */
+@@ -24,6 +23,7 @@ struct mm_struct;
+ #include <asm/msr.h>
+ #include <asm/desc_defs.h>
+ #include <asm/nops.h>
++
+ #include <linux/personality.h>
+ #include <linux/cpumask.h>
+ #include <linux/cache.h>
+@@ -37,16 +37,18 @@ struct mm_struct;
+ static inline void *current_text_addr(void)
+ {
+ void *pc;
+- asm volatile("mov $1f,%0\n1:":"=r" (pc));
++
++ asm volatile("mov $1f, %0; 1:":"=r" (pc));
++
+ return pc;
+ }
+
+ #ifdef CONFIG_X86_VSMP
+-#define ARCH_MIN_TASKALIGN (1 << INTERNODE_CACHE_SHIFT)
+-#define ARCH_MIN_MMSTRUCT_ALIGN (1 << INTERNODE_CACHE_SHIFT)
++# define ARCH_MIN_TASKALIGN (1 << INTERNODE_CACHE_SHIFT)
++# define ARCH_MIN_MMSTRUCT_ALIGN (1 << INTERNODE_CACHE_SHIFT)
+ #else
+-#define ARCH_MIN_TASKALIGN 16
+-#define ARCH_MIN_MMSTRUCT_ALIGN 0
++# define ARCH_MIN_TASKALIGN 16
++# define ARCH_MIN_MMSTRUCT_ALIGN 0
+ #endif
+
+ /*
+@@ -56,69 +58,81 @@ static inline void *current_text_addr(void)
+ */
+
+ struct cpuinfo_x86 {
+- __u8 x86; /* CPU family */
+- __u8 x86_vendor; /* CPU vendor */
+- __u8 x86_model;
+- __u8 x86_mask;
++ __u8 x86; /* CPU family */
++ __u8 x86_vendor; /* CPU vendor */
++ __u8 x86_model;
++ __u8 x86_mask;
+ #ifdef CONFIG_X86_32
+- char wp_works_ok; /* It doesn't on 386's */
+- char hlt_works_ok; /* Problems on some 486Dx4's and old 386's */
+- char hard_math;
+- char rfu;
+- char fdiv_bug;
+- char f00f_bug;
+- char coma_bug;
+- char pad0;
++ char wp_works_ok; /* It doesn't on 386's */
++
++ /* Problems on some 486Dx4's and old 386's: */
++ char hlt_works_ok;
++ char hard_math;
++ char rfu;
++ char fdiv_bug;
++ char f00f_bug;
++ char coma_bug;
++ char pad0;
+ #else
+- /* number of 4K pages in DTLB/ITLB combined(in pages)*/
+- int x86_tlbsize;
+- __u8 x86_virt_bits, x86_phys_bits;
+- /* cpuid returned core id bits */
+- __u8 x86_coreid_bits;
+- /* Max extended CPUID function supported */
+- __u32 extended_cpuid_level;
++ /* Number of 4K pages in DTLB/ITLB combined(in pages): */
++ int x86_tlbsize;
++ __u8 x86_virt_bits;
++ __u8 x86_phys_bits;
++ /* CPUID returned core id bits: */
++ __u8 x86_coreid_bits;
++ /* Max extended CPUID function supported: */
++ __u32 extended_cpuid_level;
+ #endif
+- int cpuid_level; /* Maximum supported CPUID level, -1=no CPUID */
+- __u32 x86_capability[NCAPINTS];
+- char x86_vendor_id[16];
+- char x86_model_id[64];
+- int x86_cache_size; /* in KB - valid for CPUS which support this
+- call */
+- int x86_cache_alignment; /* In bytes */
+- int x86_power;
+- unsigned long loops_per_jiffy;
++ /* Maximum supported CPUID level, -1=no CPUID: */
++ int cpuid_level;
++ __u32 x86_capability[NCAPINTS];
++ char x86_vendor_id[16];
++ char x86_model_id[64];
++ /* in KB - valid for CPUS which support this call: */
++ int x86_cache_size;
++ int x86_cache_alignment; /* In bytes */
++ int x86_power;
++ unsigned long loops_per_jiffy;
+ #ifdef CONFIG_SMP
+- cpumask_t llc_shared_map; /* cpus sharing the last level cache */
++ /* cpus sharing the last level cache: */
++ cpumask_t llc_shared_map;
+ #endif
+- u16 x86_max_cores; /* cpuid returned max cores value */
+- u16 apicid;
+- u16 x86_clflush_size;
++ /* cpuid returned max cores value: */
++ u16 x86_max_cores;
++ u16 apicid;
++ u16 initial_apicid;
++ u16 x86_clflush_size;
+ #ifdef CONFIG_SMP
+- u16 booted_cores; /* number of cores as seen by OS */
+- u16 phys_proc_id; /* Physical processor id. */
+- u16 cpu_core_id; /* Core id */
+- u16 cpu_index; /* index into per_cpu list */
++ /* number of cores as seen by the OS: */
++ u16 booted_cores;
++ /* Physical processor id: */
++ u16 phys_proc_id;
++ /* Core id: */
++ u16 cpu_core_id;
++ /* Index into per_cpu list: */
++ u16 cpu_index;
+ #endif
+ } __attribute__((__aligned__(SMP_CACHE_BYTES)));
+
+-#define X86_VENDOR_INTEL 0
+-#define X86_VENDOR_CYRIX 1
+-#define X86_VENDOR_AMD 2
+-#define X86_VENDOR_UMC 3
+-#define X86_VENDOR_NEXGEN 4
+-#define X86_VENDOR_CENTAUR 5
+-#define X86_VENDOR_TRANSMETA 7
+-#define X86_VENDOR_NSC 8
+-#define X86_VENDOR_NUM 9
+-#define X86_VENDOR_UNKNOWN 0xff
++#define X86_VENDOR_INTEL 0
++#define X86_VENDOR_CYRIX 1
++#define X86_VENDOR_AMD 2
++#define X86_VENDOR_UMC 3
++#define X86_VENDOR_CENTAUR 5
++#define X86_VENDOR_TRANSMETA 7
++#define X86_VENDOR_NSC 8
++#define X86_VENDOR_NUM 9
++
++#define X86_VENDOR_UNKNOWN 0xff
+
+ /*
+ * capabilities of CPUs
+ */
+-extern struct cpuinfo_x86 boot_cpu_data;
+-extern struct cpuinfo_x86 new_cpu_data;
+-extern struct tss_struct doublefault_tss;
+-extern __u32 cleared_cpu_caps[NCAPINTS];
++extern struct cpuinfo_x86 boot_cpu_data;
++extern struct cpuinfo_x86 new_cpu_data;
++
++extern struct tss_struct doublefault_tss;
++extern __u32 cleared_cpu_caps[NCAPINTS];
+
+ #ifdef CONFIG_SMP
+ DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info);
+@@ -129,7 +143,18 @@ DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info);
+ #define current_cpu_data boot_cpu_data
+ #endif
+
+-void cpu_detect(struct cpuinfo_x86 *c);
++static inline int hlt_works(int cpu)
++{
++#ifdef CONFIG_X86_32
++ return cpu_data(cpu).hlt_works_ok;
++#else
++ return 1;
++#endif
++}
++
++#define cache_line_size() (boot_cpu_data.x86_cache_alignment)
++
++extern void cpu_detect(struct cpuinfo_x86 *c);
+
+ extern void identify_cpu(struct cpuinfo_x86 *);
+ extern void identify_boot_cpu(void);
+@@ -146,15 +171,15 @@ static inline void detect_ht(struct cpuinfo_x86 *c) {}
+ #endif
+
+ static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
+- unsigned int *ecx, unsigned int *edx)
++ unsigned int *ecx, unsigned int *edx)
+ {
+ /* ecx is often an input as well as an output. */
+- __asm__("cpuid"
+- : "=a" (*eax),
+- "=b" (*ebx),
+- "=c" (*ecx),
+- "=d" (*edx)
+- : "0" (*eax), "2" (*ecx));
++ asm("cpuid"
++ : "=a" (*eax),
++ "=b" (*ebx),
++ "=c" (*ecx),
++ "=d" (*edx)
++ : "0" (*eax), "2" (*ecx));
+ }
+
+ static inline void load_cr3(pgd_t *pgdir)
+@@ -165,54 +190,67 @@ static inline void load_cr3(pgd_t *pgdir)
+ #ifdef CONFIG_X86_32
+ /* This is the TSS defined by the hardware. */
+ struct x86_hw_tss {
+- unsigned short back_link, __blh;
+- unsigned long sp0;
+- unsigned short ss0, __ss0h;
+- unsigned long sp1;
+- unsigned short ss1, __ss1h; /* ss1 caches MSR_IA32_SYSENTER_CS */
+- unsigned long sp2;
+- unsigned short ss2, __ss2h;
+- unsigned long __cr3;
+- unsigned long ip;
+- unsigned long flags;
+- unsigned long ax, cx, dx, bx;
+- unsigned long sp, bp, si, di;
+- unsigned short es, __esh;
+- unsigned short cs, __csh;
+- unsigned short ss, __ssh;
+- unsigned short ds, __dsh;
+- unsigned short fs, __fsh;
+- unsigned short gs, __gsh;
+- unsigned short ldt, __ldth;
+- unsigned short trace, io_bitmap_base;
++ unsigned short back_link, __blh;
++ unsigned long sp0;
++ unsigned short ss0, __ss0h;
++ unsigned long sp1;
++ /* ss1 caches MSR_IA32_SYSENTER_CS: */
++ unsigned short ss1, __ss1h;
++ unsigned long sp2;
++ unsigned short ss2, __ss2h;
++ unsigned long __cr3;
++ unsigned long ip;
++ unsigned long flags;
++ unsigned long ax;
++ unsigned long cx;
++ unsigned long dx;
++ unsigned long bx;
++ unsigned long sp;
++ unsigned long bp;
++ unsigned long si;
++ unsigned long di;
++ unsigned short es, __esh;
++ unsigned short cs, __csh;
++ unsigned short ss, __ssh;
++ unsigned short ds, __dsh;
++ unsigned short fs, __fsh;
++ unsigned short gs, __gsh;
++ unsigned short ldt, __ldth;
++ unsigned short trace;
++ unsigned short io_bitmap_base;
++
+ } __attribute__((packed));
+ #else
+ struct x86_hw_tss {
+- u32 reserved1;
+- u64 sp0;
+- u64 sp1;
+- u64 sp2;
+- u64 reserved2;
+- u64 ist[7];
+- u32 reserved3;
+- u32 reserved4;
+- u16 reserved5;
+- u16 io_bitmap_base;
++ u32 reserved1;
++ u64 sp0;
++ u64 sp1;
++ u64 sp2;
++ u64 reserved2;
++ u64 ist[7];
++ u32 reserved3;
++ u32 reserved4;
++ u16 reserved5;
++ u16 io_bitmap_base;
++
+ } __attribute__((packed)) ____cacheline_aligned;
+ #endif
+
+ /*
+- * Size of io_bitmap.
++ * IO-bitmap sizes:
+ */
+-#define IO_BITMAP_BITS 65536
+-#define IO_BITMAP_BYTES (IO_BITMAP_BITS/8)
+-#define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long))
+-#define IO_BITMAP_OFFSET offsetof(struct tss_struct, io_bitmap)
+-#define INVALID_IO_BITMAP_OFFSET 0x8000
+-#define INVALID_IO_BITMAP_OFFSET_LAZY 0x9000
++#define IO_BITMAP_BITS 65536
++#define IO_BITMAP_BYTES (IO_BITMAP_BITS/8)
++#define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long))
++#define IO_BITMAP_OFFSET offsetof(struct tss_struct, io_bitmap)
++#define INVALID_IO_BITMAP_OFFSET 0x8000
++#define INVALID_IO_BITMAP_OFFSET_LAZY 0x9000
+
+ struct tss_struct {
+- struct x86_hw_tss x86_tss;
++ /*
++ * The hardware state:
++ */
++ struct x86_hw_tss x86_tss;
+
+ /*
+ * The extra 1 is there because the CPU will access an
+@@ -220,135 +258,164 @@ struct tss_struct {
+ * bitmap. The extra byte must be all 1 bits, and must
+ * be within the limit.
+ */
+- unsigned long io_bitmap[IO_BITMAP_LONGS + 1];
++ unsigned long io_bitmap[IO_BITMAP_LONGS + 1];
+ /*
+ * Cache the current maximum and the last task that used the bitmap:
+ */
+- unsigned long io_bitmap_max;
+- struct thread_struct *io_bitmap_owner;
++ unsigned long io_bitmap_max;
++ struct thread_struct *io_bitmap_owner;
++
+ /*
+- * pads the TSS to be cacheline-aligned (size is 0x100)
++ * Pad the TSS to be cacheline-aligned (size is 0x100):
+ */
+- unsigned long __cacheline_filler[35];
++ unsigned long __cacheline_filler[35];
+ /*
+- * .. and then another 0x100 bytes for emergency kernel stack
++ * .. and then another 0x100 bytes for the emergency kernel stack:
+ */
+- unsigned long stack[64];
++ unsigned long stack[64];
++
+ } __attribute__((packed));
+
+ DECLARE_PER_CPU(struct tss_struct, init_tss);
+
+-/* Save the original ist values for checking stack pointers during debugging */
++/*
++ * Save the original ist values for checking stack pointers during debugging
++ */
+ struct orig_ist {
+- unsigned long ist[7];
++ unsigned long ist[7];
+ };
+
+ #define MXCSR_DEFAULT 0x1f80
+
+ struct i387_fsave_struct {
+- u32 cwd;
+- u32 swd;
+- u32 twd;
+- u32 fip;
+- u32 fcs;
+- u32 foo;
+- u32 fos;
+- u32 st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */
+- u32 status; /* software status information */
++ u32 cwd; /* FPU Control Word */
++ u32 swd; /* FPU Status Word */
++ u32 twd; /* FPU Tag Word */
++ u32 fip; /* FPU IP Offset */
++ u32 fcs; /* FPU IP Selector */
++ u32 foo; /* FPU Operand Pointer Offset */
++ u32 fos; /* FPU Operand Pointer Selector */
++
++ /* 8*10 bytes for each FP-reg = 80 bytes: */
++ u32 st_space[20];
++
++ /* Software status information [not touched by FSAVE ]: */
++ u32 status;
+ };
+
+ struct i387_fxsave_struct {
+- u16 cwd;
+- u16 swd;
+- u16 twd;
+- u16 fop;
++ u16 cwd; /* Control Word */
++ u16 swd; /* Status Word */
++ u16 twd; /* Tag Word */
++ u16 fop; /* Last Instruction Opcode */
+ union {
+ struct {
+- u64 rip;
+- u64 rdp;
++ u64 rip; /* Instruction Pointer */
++ u64 rdp; /* Data Pointer */
+ };
+ struct {
+- u32 fip;
+- u32 fcs;
+- u32 foo;
+- u32 fos;
++ u32 fip; /* FPU IP Offset */
++ u32 fcs; /* FPU IP Selector */
++ u32 foo; /* FPU Operand Offset */
++ u32 fos; /* FPU Operand Selector */
+ };
+ };
+- u32 mxcsr;
+- u32 mxcsr_mask;
+- u32 st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */
+- u32 xmm_space[64]; /* 16*16 bytes for each XMM-reg = 256 bytes */
+- u32 padding[24];
++ u32 mxcsr; /* MXCSR Register State */
++ u32 mxcsr_mask; /* MXCSR Mask */
++
++ /* 8*16 bytes for each FP-reg = 128 bytes: */
++ u32 st_space[32];
++
++ /* 16*16 bytes for each XMM-reg = 256 bytes: */
++ u32 xmm_space[64];
++
++ u32 padding[24];
++
+ } __attribute__((aligned(16)));
+
+ struct i387_soft_struct {
+- u32 cwd;
+- u32 swd;
+- u32 twd;
+- u32 fip;
+- u32 fcs;
+- u32 foo;
+- u32 fos;
+- u32 st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */
+- u8 ftop, changed, lookahead, no_update, rm, alimit;
+- struct info *info;
+- u32 entry_eip;
++ u32 cwd;
++ u32 swd;
++ u32 twd;
++ u32 fip;
++ u32 fcs;
++ u32 foo;
++ u32 fos;
++ /* 8*10 bytes for each FP-reg = 80 bytes: */
++ u32 st_space[20];
++ u8 ftop;
++ u8 changed;
++ u8 lookahead;
++ u8 no_update;
++ u8 rm;
++ u8 alimit;
++ struct info *info;
++ u32 entry_eip;
+ };
+
+-union i387_union {
++union thread_xstate {
+ struct i387_fsave_struct fsave;
+ struct i387_fxsave_struct fxsave;
+- struct i387_soft_struct soft;
++ struct i387_soft_struct soft;
+ };
+
+-#ifdef CONFIG_X86_32
+-DECLARE_PER_CPU(u8, cpu_llc_id);
+-#else
++#ifdef CONFIG_X86_64
+ DECLARE_PER_CPU(struct orig_ist, orig_ist);
+ #endif
+
+ extern void print_cpu_info(struct cpuinfo_x86 *);
++extern unsigned int xstate_size;
++extern void free_thread_xstate(struct task_struct *);
++extern struct kmem_cache *task_xstate_cachep;
+ extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
+ extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
+ extern unsigned short num_cache_leaves;
+
+ struct thread_struct {
+-/* cached TLS descriptors. */
+- struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
+- unsigned long sp0;
+- unsigned long sp;
++ /* Cached TLS descriptors: */
++ struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
++ unsigned long sp0;
++ unsigned long sp;
+ #ifdef CONFIG_X86_32
+- unsigned long sysenter_cs;
++ unsigned long sysenter_cs;
+ #else
+- unsigned long usersp; /* Copy from PDA */
+- unsigned short es, ds, fsindex, gsindex;
++ unsigned long usersp; /* Copy from PDA */
++ unsigned short es;
++ unsigned short ds;
++ unsigned short fsindex;
++ unsigned short gsindex;
+ #endif
+- unsigned long ip;
+- unsigned long fs;
+- unsigned long gs;
+-/* Hardware debugging registers */
+- unsigned long debugreg0;
+- unsigned long debugreg1;
+- unsigned long debugreg2;
+- unsigned long debugreg3;
+- unsigned long debugreg6;
+- unsigned long debugreg7;
+-/* fault info */
+- unsigned long cr2, trap_no, error_code;
+-/* floating point info */
+- union i387_union i387 __attribute__((aligned(16)));;
++ unsigned long ip;
++ unsigned long fs;
++ unsigned long gs;
++ /* Hardware debugging registers: */
++ unsigned long debugreg0;
++ unsigned long debugreg1;
++ unsigned long debugreg2;
++ unsigned long debugreg3;
++ unsigned long debugreg6;
++ unsigned long debugreg7;
++ /* Fault info: */
++ unsigned long cr2;
++ unsigned long trap_no;
++ unsigned long error_code;
++ /* floating point and extended processor state */
++ union thread_xstate *xstate;
+ #ifdef CONFIG_X86_32
+-/* virtual 86 mode info */
++ /* Virtual 86 mode info */
+ struct vm86_struct __user *vm86_info;
+ unsigned long screen_bitmap;
+- unsigned long v86flags, v86mask, saved_sp0;
+- unsigned int saved_fs, saved_gs;
++ unsigned long v86flags;
++ unsigned long v86mask;
++ unsigned long saved_sp0;
++ unsigned int saved_fs;
++ unsigned int saved_gs;
+ #endif
+-/* IO permissions */
+- unsigned long *io_bitmap_ptr;
+- unsigned long iopl;
+-/* max allowed port in the bitmap, in bytes: */
+- unsigned io_bitmap_max;
++ /* IO permissions: */
++ unsigned long *io_bitmap_ptr;
++ unsigned long iopl;
++ /* Max allowed port in the bitmap, in bytes: */
++ unsigned io_bitmap_max;
+ /* MSR_IA32_DEBUGCTLMSR value to switch in if TIF_DEBUGCTLMSR is set. */
+ unsigned long debugctlmsr;
+ /* Debug Store - if not 0 points to a DS Save Area configuration;
+@@ -358,21 +425,27 @@ struct thread_struct {
+
+ static inline unsigned long native_get_debugreg(int regno)
+ {
+- unsigned long val = 0; /* Damn you, gcc! */
++ unsigned long val = 0; /* Damn you, gcc! */
+
+ switch (regno) {
+ case 0:
+- asm("mov %%db0, %0" :"=r" (val)); break;
++ asm("mov %%db0, %0" :"=r" (val));
++ break;
+ case 1:
+- asm("mov %%db1, %0" :"=r" (val)); break;
++ asm("mov %%db1, %0" :"=r" (val));
++ break;
+ case 2:
+- asm("mov %%db2, %0" :"=r" (val)); break;
++ asm("mov %%db2, %0" :"=r" (val));
++ break;
+ case 3:
+- asm("mov %%db3, %0" :"=r" (val)); break;
++ asm("mov %%db3, %0" :"=r" (val));
++ break;
+ case 6:
+- asm("mov %%db6, %0" :"=r" (val)); break;
++ asm("mov %%db6, %0" :"=r" (val));
++ break;
+ case 7:
+- asm("mov %%db7, %0" :"=r" (val)); break;
++ asm("mov %%db7, %0" :"=r" (val));
++ break;
+ default:
+ BUG();
+ }
+@@ -383,22 +456,22 @@ static inline void native_set_debugreg(int regno, unsigned long value)
+ {
+ switch (regno) {
+ case 0:
+- asm("mov %0,%%db0" : /* no output */ :"r" (value));
++ asm("mov %0, %%db0" ::"r" (value));
+ break;
+ case 1:
+- asm("mov %0,%%db1" : /* no output */ :"r" (value));
++ asm("mov %0, %%db1" ::"r" (value));
+ break;
+ case 2:
+- asm("mov %0,%%db2" : /* no output */ :"r" (value));
++ asm("mov %0, %%db2" ::"r" (value));
+ break;
+ case 3:
+- asm("mov %0,%%db3" : /* no output */ :"r" (value));
++ asm("mov %0, %%db3" ::"r" (value));
+ break;
+ case 6:
+- asm("mov %0,%%db6" : /* no output */ :"r" (value));
++ asm("mov %0, %%db6" ::"r" (value));
+ break;
+ case 7:
+- asm("mov %0,%%db7" : /* no output */ :"r" (value));
++ asm("mov %0, %%db7" ::"r" (value));
+ break;
+ default:
+ BUG();
+@@ -412,23 +485,24 @@ static inline void native_set_iopl_mask(unsigned mask)
+ {
+ #ifdef CONFIG_X86_32
+ unsigned int reg;
+- __asm__ __volatile__ ("pushfl;"
+- "popl %0;"
+- "andl %1, %0;"
+- "orl %2, %0;"
+- "pushl %0;"
+- "popfl"
+- : "=&r" (reg)
+- : "i" (~X86_EFLAGS_IOPL), "r" (mask));
++
++ asm volatile ("pushfl;"
++ "popl %0;"
++ "andl %1, %0;"
++ "orl %2, %0;"
++ "pushl %0;"
++ "popfl"
++ : "=&r" (reg)
++ : "i" (~X86_EFLAGS_IOPL), "r" (mask));
+ #endif
+ }
+
+-static inline void native_load_sp0(struct tss_struct *tss,
+- struct thread_struct *thread)
++static inline void
++native_load_sp0(struct tss_struct *tss, struct thread_struct *thread)
+ {
+ tss->x86_tss.sp0 = thread->sp0;
+ #ifdef CONFIG_X86_32
+- /* Only happens when SEP is enabled, no need to test "SEP"arately */
++ /* Only happens when SEP is enabled, no need to test "SEP"arately: */
+ if (unlikely(tss->x86_tss.ss1 != thread->sysenter_cs)) {
+ tss->x86_tss.ss1 = thread->sysenter_cs;
+ wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
+@@ -446,8 +520,8 @@ static inline void native_swapgs(void)
+ #ifdef CONFIG_PARAVIRT
+ #include <asm/paravirt.h>
+ #else
+-#define __cpuid native_cpuid
+-#define paravirt_enabled() 0
++#define __cpuid native_cpuid
++#define paravirt_enabled() 0
+
+ /*
+ * These special macros can be used to get or set a debugging register
+@@ -473,11 +547,12 @@ static inline void load_sp0(struct tss_struct *tss,
+ * enable), so that any CPU's that boot up
+ * after us can get the correct flags.
+ */
+-extern unsigned long mmu_cr4_features;
++extern unsigned long mmu_cr4_features;
+
+ static inline void set_in_cr4(unsigned long mask)
+ {
+ unsigned cr4;
++
+ mmu_cr4_features |= mask;
+ cr4 = read_cr4();
+ cr4 |= mask;
+@@ -487,6 +562,7 @@ static inline void set_in_cr4(unsigned long mask)
+ static inline void clear_in_cr4(unsigned long mask)
+ {
+ unsigned cr4;
++
+ mmu_cr4_features &= ~mask;
+ cr4 = read_cr4();
+ cr4 &= ~mask;
+@@ -494,42 +570,42 @@ static inline void clear_in_cr4(unsigned long mask)
+ }
+
+ struct microcode_header {
+- unsigned int hdrver;
+- unsigned int rev;
+- unsigned int date;
+- unsigned int sig;
+- unsigned int cksum;
+- unsigned int ldrver;
+- unsigned int pf;
+- unsigned int datasize;
+- unsigned int totalsize;
+- unsigned int reserved[3];
++ unsigned int hdrver;
++ unsigned int rev;
++ unsigned int date;
++ unsigned int sig;
++ unsigned int cksum;
++ unsigned int ldrver;
++ unsigned int pf;
++ unsigned int datasize;
++ unsigned int totalsize;
++ unsigned int reserved[3];
+ };
+
+ struct microcode {
+- struct microcode_header hdr;
+- unsigned int bits[0];
++ struct microcode_header hdr;
++ unsigned int bits[0];
+ };
+
+-typedef struct microcode microcode_t;
+-typedef struct microcode_header microcode_header_t;
++typedef struct microcode microcode_t;
++typedef struct microcode_header microcode_header_t;
+
+ /* microcode format is extended from prescott processors */
+ struct extended_signature {
+- unsigned int sig;
+- unsigned int pf;
+- unsigned int cksum;
++ unsigned int sig;
++ unsigned int pf;
++ unsigned int cksum;
+ };
+
+ struct extended_sigtable {
+- unsigned int count;
+- unsigned int cksum;
+- unsigned int reserved[3];
++ unsigned int count;
++ unsigned int cksum;
++ unsigned int reserved[3];
+ struct extended_signature sigs[0];
+ };
+
+ typedef struct {
+- unsigned long seg;
++ unsigned long seg;
+ } mm_segment_t;
+
+
+@@ -541,7 +617,7 @@ extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+ /* Free all resources held by a thread. */
+ extern void release_thread(struct task_struct *);
+
+-/* Prepare to copy thread state - unlazy all lazy status */
++/* Prepare to copy thread state - unlazy all lazy state */
+ extern void prepare_to_copy(struct task_struct *tsk);
+
+ unsigned long get_wchan(struct task_struct *p);
+@@ -578,118 +654,137 @@ static inline unsigned int cpuid_eax(unsigned int op)
+ unsigned int eax, ebx, ecx, edx;
+
+ cpuid(op, &eax, &ebx, &ecx, &edx);
++
+ return eax;
+ }
++
+ static inline unsigned int cpuid_ebx(unsigned int op)
+ {
+ unsigned int eax, ebx, ecx, edx;
+
+ cpuid(op, &eax, &ebx, &ecx, &edx);
++
+ return ebx;
+ }
++
+ static inline unsigned int cpuid_ecx(unsigned int op)
+ {
+ unsigned int eax, ebx, ecx, edx;
+
+ cpuid(op, &eax, &ebx, &ecx, &edx);
++
+ return ecx;
+ }
++
+ static inline unsigned int cpuid_edx(unsigned int op)
+ {
+ unsigned int eax, ebx, ecx, edx;
+
+ cpuid(op, &eax, &ebx, &ecx, &edx);
++
+ return edx;
+ }
+
+ /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
+ static inline void rep_nop(void)
+ {
+- __asm__ __volatile__("rep;nop": : :"memory");
++ asm volatile("rep; nop" ::: "memory");
++}
++
++static inline void cpu_relax(void)
++{
++ rep_nop();
+ }
+
+-/* Stop speculative execution */
++/* Stop speculative execution: */
+ static inline void sync_core(void)
+ {
+ int tmp;
++
+ asm volatile("cpuid" : "=a" (tmp) : "0" (1)
+- : "ebx", "ecx", "edx", "memory");
++ : "ebx", "ecx", "edx", "memory");
+ }
+
+-#define cpu_relax() rep_nop()
+-
+ static inline void __monitor(const void *eax, unsigned long ecx,
+- unsigned long edx)
++ unsigned long edx)
+ {
+- /* "monitor %eax,%ecx,%edx;" */
+- asm volatile(
+- ".byte 0x0f,0x01,0xc8;"
+- : :"a" (eax), "c" (ecx), "d"(edx));
++ /* "monitor %eax, %ecx, %edx;" */
++ asm volatile(".byte 0x0f, 0x01, 0xc8;"
++ :: "a" (eax), "c" (ecx), "d"(edx));
+ }
+
+ static inline void __mwait(unsigned long eax, unsigned long ecx)
+ {
+- /* "mwait %eax,%ecx;" */
+- asm volatile(
+- ".byte 0x0f,0x01,0xc9;"
+- : :"a" (eax), "c" (ecx));
++ /* "mwait %eax, %ecx;" */
++ asm volatile(".byte 0x0f, 0x01, 0xc9;"
++ :: "a" (eax), "c" (ecx));
+ }
+
+ static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
+ {
+- /* "mwait %eax,%ecx;" */
+- asm volatile(
+- "sti; .byte 0x0f,0x01,0xc9;"
+- : :"a" (eax), "c" (ecx));
++ /* "mwait %eax, %ecx;" */
++ asm volatile("sti; .byte 0x0f, 0x01, 0xc9;"
++ :: "a" (eax), "c" (ecx));
+ }
+
+ extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
+
+-extern int force_mwait;
++extern int force_mwait;
+
+ extern void select_idle_routine(const struct cpuinfo_x86 *c);
+
+-extern unsigned long boot_option_idle_override;
++extern unsigned long boot_option_idle_override;
+
+ extern void enable_sep_cpu(void);
+ extern int sysenter_setup(void);
+
+ /* Defined in head.S */
+-extern struct desc_ptr early_gdt_descr;
++extern struct desc_ptr early_gdt_descr;
+
+ extern void cpu_set_gdt(int);
+ extern void switch_to_new_gdt(void);
+ extern void cpu_init(void);
+ extern void init_gdt(int cpu);
+
+-/* from system description table in BIOS. Mostly for MCA use, but
+- * others may find it useful. */
+-extern unsigned int machine_id;
+-extern unsigned int machine_submodel_id;
+-extern unsigned int BIOS_revision;
++static inline void update_debugctlmsr(unsigned long debugctlmsr)
++{
++#ifndef CONFIG_X86_DEBUGCTLMSR
++ if (boot_cpu_data.x86 < 6)
++ return;
++#endif
++ wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr);
++}
++
++/*
++ * from system description table in BIOS. Mostly for MCA use, but
++ * others may find it useful:
++ */
++extern unsigned int machine_id;
++extern unsigned int machine_submodel_id;
++extern unsigned int BIOS_revision;
+
+-/* Boot loader type from the setup header */
+-extern int bootloader_type;
++/* Boot loader type from the setup header: */
++extern int bootloader_type;
+
+-extern char ignore_fpu_irq;
+-#define cache_line_size() (boot_cpu_data.x86_cache_alignment)
++extern char ignore_fpu_irq;
+
+ #define HAVE_ARCH_PICK_MMAP_LAYOUT 1
+ #define ARCH_HAS_PREFETCHW
+ #define ARCH_HAS_SPINLOCK_PREFETCH
+
+ #ifdef CONFIG_X86_32
+-#define BASE_PREFETCH ASM_NOP4
+-#define ARCH_HAS_PREFETCH
++# define BASE_PREFETCH ASM_NOP4
++# define ARCH_HAS_PREFETCH
+ #else
+-#define BASE_PREFETCH "prefetcht0 (%1)"
++# define BASE_PREFETCH "prefetcht0 (%1)"
+ #endif
+
+-/* Prefetch instructions for Pentium III and AMD Athlon */
+-/* It's not worth to care about 3dnow! prefetches for the K6
+- because they are microcoded there and very slow.
+- However we don't do prefetches for pre XP Athlons currently
+- That should be fixed. */
++/*
++ * Prefetch instructions for Pentium III (+) and AMD Athlon (+)
++ *
++ * It's not worth to care about 3dnow prefetches for the K6
++ * because they are microcoded there and very slow.
++ */
+ static inline void prefetch(const void *x)
+ {
+ alternative_input(BASE_PREFETCH,
+@@ -698,8 +793,11 @@ static inline void prefetch(const void *x)
+ "r" (x));
+ }
+
+-/* 3dnow! prefetch to get an exclusive cache line. Useful for
+- spinlocks to avoid one state transition in the cache coherency protocol. */
++/*
++ * 3dnow prefetch to get an exclusive cache line.
++ * Useful for spinlocks to avoid one state transition in the
++ * cache coherency protocol:
++ */
+ static inline void prefetchw(const void *x)
+ {
+ alternative_input(BASE_PREFETCH,
+@@ -708,21 +806,25 @@ static inline void prefetchw(const void *x)
+ "r" (x));
+ }
+
+-#define spin_lock_prefetch(x) prefetchw(x)
++static inline void spin_lock_prefetch(const void *x)
++{
++ prefetchw(x);
++}
++
+ #ifdef CONFIG_X86_32
+ /*
+ * User space process size: 3GB (default).
+ */
+-#define TASK_SIZE (PAGE_OFFSET)
+-#define STACK_TOP TASK_SIZE
+-#define STACK_TOP_MAX STACK_TOP
+-
+-#define INIT_THREAD { \
+- .sp0 = sizeof(init_stack) + (long)&init_stack, \
+- .vm86_info = NULL, \
+- .sysenter_cs = __KERNEL_CS, \
+- .io_bitmap_ptr = NULL, \
+- .fs = __KERNEL_PERCPU, \
++#define TASK_SIZE PAGE_OFFSET
++#define STACK_TOP TASK_SIZE
++#define STACK_TOP_MAX STACK_TOP
++
++#define INIT_THREAD { \
++ .sp0 = sizeof(init_stack) + (long)&init_stack, \
++ .vm86_info = NULL, \
++ .sysenter_cs = __KERNEL_CS, \
++ .io_bitmap_ptr = NULL, \
++ .fs = __KERNEL_PERCPU, \
+ }
+
+ /*
+@@ -731,28 +833,15 @@ static inline void prefetchw(const void *x)
+ * permission bitmap. The extra byte must be all 1 bits, and must
+ * be within the limit.
+ */
+-#define INIT_TSS { \
+- .x86_tss = { \
++#define INIT_TSS { \
++ .x86_tss = { \
+ .sp0 = sizeof(init_stack) + (long)&init_stack, \
+- .ss0 = __KERNEL_DS, \
+- .ss1 = __KERNEL_CS, \
+- .io_bitmap_base = INVALID_IO_BITMAP_OFFSET, \
+- }, \
+- .io_bitmap = { [0 ... IO_BITMAP_LONGS] = ~0 }, \
+-}
+-
+-#define start_thread(regs, new_eip, new_esp) do { \
+- __asm__("movl %0,%%gs": :"r" (0)); \
+- regs->fs = 0; \
+- set_fs(USER_DS); \
+- regs->ds = __USER_DS; \
+- regs->es = __USER_DS; \
+- regs->ss = __USER_DS; \
+- regs->cs = __USER_CS; \
+- regs->ip = new_eip; \
+- regs->sp = new_esp; \
+-} while (0)
+-
++ .ss0 = __KERNEL_DS, \
++ .ss1 = __KERNEL_CS, \
++ .io_bitmap_base = INVALID_IO_BITMAP_OFFSET, \
++ }, \
++ .io_bitmap = { [0 ... IO_BITMAP_LONGS] = ~0 }, \
++}
+
+ extern unsigned long thread_saved_pc(struct task_struct *tsk);
+
+@@ -780,24 +869,24 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk);
+ __regs__ - 1; \
+ })
+
+-#define KSTK_ESP(task) (task_pt_regs(task)->sp)
++#define KSTK_ESP(task) (task_pt_regs(task)->sp)
+
+ #else
+ /*
+ * User space process size. 47bits minus one guard page.
+ */
+-#define TASK_SIZE64 (0x800000000000UL - 4096)
++#define TASK_SIZE64 ((1UL << 47) - PAGE_SIZE)
+
+ /* This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+-#define IA32_PAGE_OFFSET ((current->personality & ADDR_LIMIT_3GB) ? \
+- 0xc0000000 : 0xFFFFe000)
++#define IA32_PAGE_OFFSET ((current->personality & ADDR_LIMIT_3GB) ? \
++ 0xc0000000 : 0xFFFFe000)
+
+-#define TASK_SIZE (test_thread_flag(TIF_IA32) ? \
+- IA32_PAGE_OFFSET : TASK_SIZE64)
+-#define TASK_SIZE_OF(child) ((test_tsk_thread_flag(child, TIF_IA32)) ? \
+- IA32_PAGE_OFFSET : TASK_SIZE64)
++#define TASK_SIZE (test_thread_flag(TIF_IA32) ? \
++ IA32_PAGE_OFFSET : TASK_SIZE64)
++#define TASK_SIZE_OF(child) ((test_tsk_thread_flag(child, TIF_IA32)) ? \
++ IA32_PAGE_OFFSET : TASK_SIZE64)
+
+ #define STACK_TOP TASK_SIZE
+ #define STACK_TOP_MAX TASK_SIZE64
+@@ -810,33 +899,32 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk);
+ .x86_tss.sp0 = (unsigned long)&init_stack + sizeof(init_stack) \
+ }
+
+-#define start_thread(regs, new_rip, new_rsp) do { \
+- asm volatile("movl %0,%%fs; movl %0,%%es; movl %0,%%ds": :"r" (0)); \
+- load_gs_index(0); \
+- (regs)->ip = (new_rip); \
+- (regs)->sp = (new_rsp); \
+- write_pda(oldrsp, (new_rsp)); \
+- (regs)->cs = __USER_CS; \
+- (regs)->ss = __USER_DS; \
+- (regs)->flags = 0x200; \
+- set_fs(USER_DS); \
+-} while (0)
+-
+ /*
+ * Return saved PC of a blocked thread.
+ * What is this good for? it will be always the scheduler or ret_from_fork.
+ */
+-#define thread_saved_pc(t) (*(unsigned long *)((t)->thread.sp - 8))
++#define thread_saved_pc(t) (*(unsigned long *)((t)->thread.sp - 8))
+
+-#define task_pt_regs(tsk) ((struct pt_regs *)(tsk)->thread.sp0 - 1)
+-#define KSTK_ESP(tsk) -1 /* sorry. doesn't work for syscall. */
++#define task_pt_regs(tsk) ((struct pt_regs *)(tsk)->thread.sp0 - 1)
++#define KSTK_ESP(tsk) -1 /* sorry. doesn't work for syscall. */
+ #endif /* CONFIG_X86_64 */
+
+-/* This decides where the kernel will search for a free chunk of vm
++extern void start_thread(struct pt_regs *regs, unsigned long new_ip,
++ unsigned long new_sp);
++
++/*
++ * This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+ #define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3))
+
+-#define KSTK_EIP(task) (task_pt_regs(task)->ip)
++#define KSTK_EIP(task) (task_pt_regs(task)->ip)
++
++/* Get/set a process' ability to use the timestamp counter instruction */
++#define GET_TSC_CTL(adr) get_tsc_mode((adr))
++#define SET_TSC_CTL(val) set_tsc_mode((val))
++
++extern int get_tsc_mode(unsigned long adr);
++extern int set_tsc_mode(unsigned int val);
+
+ #endif
+diff --git a/include/asm-x86/proto.h b/include/asm-x86/proto.h
+index 68563c0..1e17bcc 100644
+--- a/include/asm-x86/proto.h
++++ b/include/asm-x86/proto.h
+@@ -7,8 +7,6 @@
+
+ extern void early_idt_handler(void);
+
+-extern void init_memory_mapping(unsigned long start, unsigned long end);
+-
+ extern void system_call(void);
+ extern void syscall_init(void);
+
+@@ -26,7 +24,7 @@ extern int reboot_force;
+
+ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr);
+
+-#define round_up(x,y) (((x) + (y) - 1) & ~((y)-1))
+-#define round_down(x,y) ((x) & ~((y)-1))
++#define round_up(x, y) (((x) + (y) - 1) & ~((y) - 1))
++#define round_down(x, y) ((x) & ~((y) - 1))
+
+ #endif
+diff --git a/include/asm-x86/ptrace.h b/include/asm-x86/ptrace.h
+index d9e04b4..9f922b0 100644
+--- a/include/asm-x86/ptrace.h
++++ b/include/asm-x86/ptrace.h
+@@ -36,23 +36,23 @@ struct pt_regs {
+ #else /* __KERNEL__ */
+
+ struct pt_regs {
+- long bx;
+- long cx;
+- long dx;
+- long si;
+- long di;
+- long bp;
+- long ax;
+- int ds;
+- int es;
+- int fs;
++ unsigned long bx;
++ unsigned long cx;
++ unsigned long dx;
++ unsigned long si;
++ unsigned long di;
++ unsigned long bp;
++ unsigned long ax;
++ unsigned long ds;
++ unsigned long es;
++ unsigned long fs;
+ /* int gs; */
+- long orig_ax;
+- long ip;
+- int cs;
+- long flags;
+- long sp;
+- int ss;
++ unsigned long orig_ax;
++ unsigned long ip;
++ unsigned long cs;
++ unsigned long flags;
++ unsigned long sp;
++ unsigned long ss;
+ };
+
+ #include <asm/vm86.h>
+@@ -140,12 +140,16 @@ extern unsigned long
+ convert_ip_to_linear(struct task_struct *child, struct pt_regs *regs);
+
+ #ifdef CONFIG_X86_32
+-extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code);
++extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
++ int error_code);
+ #else
+ void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
+ #endif
+
+-#define regs_return_value(regs) ((regs)->ax)
++static inline unsigned long regs_return_value(struct pt_regs *regs)
++{
++ return regs->ax;
++}
+
+ /*
+ * user_mode_vm(regs) determines whether a register set came from user mode.
+@@ -166,8 +170,8 @@ static inline int user_mode(struct pt_regs *regs)
+ static inline int user_mode_vm(struct pt_regs *regs)
+ {
+ #ifdef CONFIG_X86_32
+- return ((regs->cs & SEGMENT_RPL_MASK) |
+- (regs->flags & VM_MASK)) >= USER_RPL;
++ return ((regs->cs & SEGMENT_RPL_MASK) | (regs->flags & X86_VM_MASK)) >=
++ USER_RPL;
+ #else
+ return user_mode(regs);
+ #endif
+@@ -176,7 +180,7 @@ static inline int user_mode_vm(struct pt_regs *regs)
+ static inline int v8086_mode(struct pt_regs *regs)
+ {
+ #ifdef CONFIG_X86_32
+- return (regs->flags & VM_MASK);
++ return (regs->flags & X86_VM_MASK);
+ #else
+ return 0; /* No V86 mode support in long mode */
+ #endif
+@@ -227,6 +231,8 @@ extern int do_get_thread_area(struct task_struct *p, int idx,
+ extern int do_set_thread_area(struct task_struct *p, int idx,
+ struct user_desc __user *info, int can_allocate);
+
++#define __ARCH_WANT_COMPAT_SYS_PTRACE
++
+ #endif /* __KERNEL__ */
+
+ #endif /* !__ASSEMBLY__ */
+diff --git a/include/asm-x86/reboot.h b/include/asm-x86/reboot.h
+index e9e3ffc..6b5233b 100644
+--- a/include/asm-x86/reboot.h
++++ b/include/asm-x86/reboot.h
+@@ -3,8 +3,7 @@
+
+ struct pt_regs;
+
+-struct machine_ops
+-{
++struct machine_ops {
+ void (*restart)(char *cmd);
+ void (*halt)(void);
+ void (*power_off)(void);
+diff --git a/include/asm-x86/resume-trace.h b/include/asm-x86/resume-trace.h
+index 46f725b..2557514 100644
+--- a/include/asm-x86/resume-trace.h
++++ b/include/asm-x86/resume-trace.h
+@@ -3,16 +3,17 @@
+
+ #include <asm/asm.h>
+
+-#define TRACE_RESUME(user) do { \
++#define TRACE_RESUME(user) \
++do { \
+ if (pm_trace_enabled) { \
+ void *tracedata; \
+ asm volatile(_ASM_MOV_UL " $1f,%0\n" \
+- ".section .tracedata,\"a\"\n" \
+- "1:\t.word %c1\n\t" \
+- _ASM_PTR " %c2\n" \
+- ".previous" \
+- :"=r" (tracedata) \
+- : "i" (__LINE__), "i" (__FILE__)); \
++ ".section .tracedata,\"a\"\n" \
++ "1:\t.word %c1\n\t" \
++ _ASM_PTR " %c2\n" \
++ ".previous" \
++ :"=r" (tracedata) \
++ : "i" (__LINE__), "i" (__FILE__)); \
+ generate_resume_trace(tracedata, user); \
+ } \
+ } while (0)
+diff --git a/include/asm-x86/rio.h b/include/asm-x86/rio.h
+index 97cdcc9..c9448bd 100644
+--- a/include/asm-x86/rio.h
++++ b/include/asm-x86/rio.h
+@@ -11,64 +11,53 @@
+ #define RIO_TABLE_VERSION 3
+
+ struct rio_table_hdr {
+- u8 version; /* Version number of this data structure */
+- u8 num_scal_dev; /* # of Scalability devices */
+- u8 num_rio_dev; /* # of RIO I/O devices */
++ u8 version; /* Version number of this data structure */
++ u8 num_scal_dev; /* # of Scalability devices */
++ u8 num_rio_dev; /* # of RIO I/O devices */
+ } __attribute__((packed));
+
+ struct scal_detail {
+- u8 node_id; /* Scalability Node ID */
+- u32 CBAR; /* Address of 1MB register space */
+- u8 port0node; /* Node ID port connected to: 0xFF=None */
+- u8 port0port; /* Port num port connected to: 0,1,2, or */
+- /* 0xFF=None */
+- u8 port1node; /* Node ID port connected to: 0xFF = None */
+- u8 port1port; /* Port num port connected to: 0,1,2, or */
+- /* 0xFF=None */
+- u8 port2node; /* Node ID port connected to: 0xFF = None */
+- u8 port2port; /* Port num port connected to: 0,1,2, or */
+- /* 0xFF=None */
+- u8 chassis_num; /* 1 based Chassis number (1 = boot node) */
++ u8 node_id; /* Scalability Node ID */
++ u32 CBAR; /* Address of 1MB register space */
++ u8 port0node; /* Node ID port connected to: 0xFF=None */
++ u8 port0port; /* Port num port connected to: 0,1,2, or */
++ /* 0xFF=None */
++ u8 port1node; /* Node ID port connected to: 0xFF = None */
++ u8 port1port; /* Port num port connected to: 0,1,2, or */
++ /* 0xFF=None */
++ u8 port2node; /* Node ID port connected to: 0xFF = None */
++ u8 port2port; /* Port num port connected to: 0,1,2, or */
++ /* 0xFF=None */
++ u8 chassis_num; /* 1 based Chassis number (1 = boot node) */
+ } __attribute__((packed));
+
+ struct rio_detail {
+- u8 node_id; /* RIO Node ID */
+- u32 BBAR; /* Address of 1MB register space */
+- u8 type; /* Type of device */
+- u8 owner_id; /* Node ID of Hurricane that owns this */
+- /* node */
+- u8 port0node; /* Node ID port connected to: 0xFF=None */
+- u8 port0port; /* Port num port connected to: 0,1,2, or */
+- /* 0xFF=None */
+- u8 port1node; /* Node ID port connected to: 0xFF=None */
+- u8 port1port; /* Port num port connected to: 0,1,2, or */
+- /* 0xFF=None */
+- u8 first_slot; /* Lowest slot number below this Calgary */
+- u8 status; /* Bit 0 = 1 : the XAPIC is used */
+- /* = 0 : the XAPIC is not used, ie: */
+- /* ints fwded to another XAPIC */
+- /* Bits1:7 Reserved */
+- u8 WP_index; /* instance index - lower ones have */
+- /* lower slot numbers/PCI bus numbers */
+- u8 chassis_num; /* 1 based Chassis number */
++ u8 node_id; /* RIO Node ID */
++ u32 BBAR; /* Address of 1MB register space */
++ u8 type; /* Type of device */
++ u8 owner_id; /* Node ID of Hurricane that owns this */
++ /* node */
++ u8 port0node; /* Node ID port connected to: 0xFF=None */
++ u8 port0port; /* Port num port connected to: 0,1,2, or */
++ /* 0xFF=None */
++ u8 port1node; /* Node ID port connected to: 0xFF=None */
++ u8 port1port; /* Port num port connected to: 0,1,2, or */
++ /* 0xFF=None */
++ u8 first_slot; /* Lowest slot number below this Calgary */
++ u8 status; /* Bit 0 = 1 : the XAPIC is used */
++ /* = 0 : the XAPIC is not used, ie: */
++ /* ints fwded to another XAPIC */
++ /* Bits1:7 Reserved */
++ u8 WP_index; /* instance index - lower ones have */
++ /* lower slot numbers/PCI bus numbers */
++ u8 chassis_num; /* 1 based Chassis number */
+ } __attribute__((packed));
+
+ enum {
+- HURR_SCALABILTY = 0, /* Hurricane Scalability info */
+- HURR_RIOIB = 2, /* Hurricane RIOIB info */
+- COMPAT_CALGARY = 4, /* Compatibility Calgary */
+- ALT_CALGARY = 5, /* Second Planar Calgary */
++ HURR_SCALABILTY = 0, /* Hurricane Scalability info */
++ HURR_RIOIB = 2, /* Hurricane RIOIB info */
++ COMPAT_CALGARY = 4, /* Compatibility Calgary */
++ ALT_CALGARY = 5, /* Second Planar Calgary */
+ };
+
+-/*
+- * there is a real-mode segmented pointer pointing to the
+- * 4K EBDA area at 0x40E.
+- */
+-static inline unsigned long get_bios_ebda(void)
+-{
+- unsigned long address = *(unsigned short *)phys_to_virt(0x40EUL);
+- address <<= 4;
+- return address;
+-}
+-
+ #endif /* __ASM_RIO_H */
+diff --git a/include/asm-x86/rwsem.h b/include/asm-x86/rwsem.h
+index 520a379..750f2a3 100644
+--- a/include/asm-x86/rwsem.h
++++ b/include/asm-x86/rwsem.h
+@@ -56,14 +56,16 @@ extern asmregparm struct rw_semaphore *
+ /*
+ * the semaphore definition
+ */
+-struct rw_semaphore {
+- signed long count;
++
+ #define RWSEM_UNLOCKED_VALUE 0x00000000
+ #define RWSEM_ACTIVE_BIAS 0x00000001
+ #define RWSEM_ACTIVE_MASK 0x0000ffff
+ #define RWSEM_WAITING_BIAS (-0x00010000)
+ #define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
+ #define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
++
++struct rw_semaphore {
++ signed long count;
+ spinlock_t wait_lock;
+ struct list_head wait_list;
+ #ifdef CONFIG_DEBUG_LOCK_ALLOC
+@@ -78,11 +80,13 @@ struct rw_semaphore {
+ #endif
+
+
+-#define __RWSEM_INITIALIZER(name) \
+-{ RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait_lock), \
+- LIST_HEAD_INIT((name).wait_list) __RWSEM_DEP_MAP_INIT(name) }
++#define __RWSEM_INITIALIZER(name) \
++{ \
++ RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait_lock), \
++ LIST_HEAD_INIT((name).wait_list) __RWSEM_DEP_MAP_INIT(name) \
++}
+
+-#define DECLARE_RWSEM(name) \
++#define DECLARE_RWSEM(name) \
+ struct rw_semaphore name = __RWSEM_INITIALIZER(name)
+
+ extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
+@@ -100,16 +104,16 @@ do { \
+ */
+ static inline void __down_read(struct rw_semaphore *sem)
+ {
+- __asm__ __volatile__(
+- "# beginning down_read\n\t"
+-LOCK_PREFIX " incl (%%eax)\n\t" /* adds 0x00000001, returns the old value */
+- " jns 1f\n"
+- " call call_rwsem_down_read_failed\n"
+- "1:\n\t"
+- "# ending down_read\n\t"
+- : "+m" (sem->count)
+- : "a" (sem)
+- : "memory", "cc");
++ asm volatile("# beginning down_read\n\t"
++ LOCK_PREFIX " incl (%%eax)\n\t"
++ /* adds 0x00000001, returns the old value */
++ " jns 1f\n"
++ " call call_rwsem_down_read_failed\n"
++ "1:\n\t"
++ "# ending down_read\n\t"
++ : "+m" (sem->count)
++ : "a" (sem)
++ : "memory", "cc");
+ }
+
+ /*
+@@ -118,21 +122,20 @@ LOCK_PREFIX " incl (%%eax)\n\t" /* adds 0x00000001, returns the old value
+ static inline int __down_read_trylock(struct rw_semaphore *sem)
+ {
+ __s32 result, tmp;
+- __asm__ __volatile__(
+- "# beginning __down_read_trylock\n\t"
+- " movl %0,%1\n\t"
+- "1:\n\t"
+- " movl %1,%2\n\t"
+- " addl %3,%2\n\t"
+- " jle 2f\n\t"
+-LOCK_PREFIX " cmpxchgl %2,%0\n\t"
+- " jnz 1b\n\t"
+- "2:\n\t"
+- "# ending __down_read_trylock\n\t"
+- : "+m" (sem->count), "=&a" (result), "=&r" (tmp)
+- : "i" (RWSEM_ACTIVE_READ_BIAS)
+- : "memory", "cc");
+- return result>=0 ? 1 : 0;
++ asm volatile("# beginning __down_read_trylock\n\t"
++ " movl %0,%1\n\t"
++ "1:\n\t"
++ " movl %1,%2\n\t"
++ " addl %3,%2\n\t"
++ " jle 2f\n\t"
++ LOCK_PREFIX " cmpxchgl %2,%0\n\t"
++ " jnz 1b\n\t"
++ "2:\n\t"
++ "# ending __down_read_trylock\n\t"
++ : "+m" (sem->count), "=&a" (result), "=&r" (tmp)
++ : "i" (RWSEM_ACTIVE_READ_BIAS)
++ : "memory", "cc");
++ return result >= 0 ? 1 : 0;
+ }
+
+ /*
+@@ -143,17 +146,18 @@ static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
+ int tmp;
+
+ tmp = RWSEM_ACTIVE_WRITE_BIAS;
+- __asm__ __volatile__(
+- "# beginning down_write\n\t"
+-LOCK_PREFIX " xadd %%edx,(%%eax)\n\t" /* subtract 0x0000ffff, returns the old value */
+- " testl %%edx,%%edx\n\t" /* was the count 0 before? */
+- " jz 1f\n"
+- " call call_rwsem_down_write_failed\n"
+- "1:\n"
+- "# ending down_write"
+- : "+m" (sem->count), "=d" (tmp)
+- : "a" (sem), "1" (tmp)
+- : "memory", "cc");
++ asm volatile("# beginning down_write\n\t"
++ LOCK_PREFIX " xadd %%edx,(%%eax)\n\t"
++ /* subtract 0x0000ffff, returns the old value */
++ " testl %%edx,%%edx\n\t"
++ /* was the count 0 before? */
++ " jz 1f\n"
++ " call call_rwsem_down_write_failed\n"
++ "1:\n"
++ "# ending down_write"
++ : "+m" (sem->count), "=d" (tmp)
++ : "a" (sem), "1" (tmp)
++ : "memory", "cc");
+ }
+
+ static inline void __down_write(struct rw_semaphore *sem)
+@@ -167,7 +171,7 @@ static inline void __down_write(struct rw_semaphore *sem)
+ static inline int __down_write_trylock(struct rw_semaphore *sem)
+ {
+ signed long ret = cmpxchg(&sem->count,
+- RWSEM_UNLOCKED_VALUE,
++ RWSEM_UNLOCKED_VALUE,
+ RWSEM_ACTIVE_WRITE_BIAS);
+ if (ret == RWSEM_UNLOCKED_VALUE)
+ return 1;
+@@ -180,16 +184,16 @@ static inline int __down_write_trylock(struct rw_semaphore *sem)
+ static inline void __up_read(struct rw_semaphore *sem)
+ {
+ __s32 tmp = -RWSEM_ACTIVE_READ_BIAS;
+- __asm__ __volatile__(
+- "# beginning __up_read\n\t"
+-LOCK_PREFIX " xadd %%edx,(%%eax)\n\t" /* subtracts 1, returns the old value */
+- " jns 1f\n\t"
+- " call call_rwsem_wake\n"
+- "1:\n"
+- "# ending __up_read\n"
+- : "+m" (sem->count), "=d" (tmp)
+- : "a" (sem), "1" (tmp)
+- : "memory", "cc");
++ asm volatile("# beginning __up_read\n\t"
++ LOCK_PREFIX " xadd %%edx,(%%eax)\n\t"
++ /* subtracts 1, returns the old value */
++ " jns 1f\n\t"
++ " call call_rwsem_wake\n"
++ "1:\n"
++ "# ending __up_read\n"
++ : "+m" (sem->count), "=d" (tmp)
++ : "a" (sem), "1" (tmp)
++ : "memory", "cc");
+ }
+
+ /*
+@@ -197,17 +201,18 @@ LOCK_PREFIX " xadd %%edx,(%%eax)\n\t" /* subtracts 1, returns the old valu
+ */
+ static inline void __up_write(struct rw_semaphore *sem)
+ {
+- __asm__ __volatile__(
+- "# beginning __up_write\n\t"
+- " movl %2,%%edx\n\t"
+-LOCK_PREFIX " xaddl %%edx,(%%eax)\n\t" /* tries to transition 0xffff0001 -> 0x00000000 */
+- " jz 1f\n"
+- " call call_rwsem_wake\n"
+- "1:\n\t"
+- "# ending __up_write\n"
+- : "+m" (sem->count)
+- : "a" (sem), "i" (-RWSEM_ACTIVE_WRITE_BIAS)
+- : "memory", "cc", "edx");
++ asm volatile("# beginning __up_write\n\t"
++ " movl %2,%%edx\n\t"
++ LOCK_PREFIX " xaddl %%edx,(%%eax)\n\t"
++ /* tries to transition
++ 0xffff0001 -> 0x00000000 */
++ " jz 1f\n"
++ " call call_rwsem_wake\n"
++ "1:\n\t"
++ "# ending __up_write\n"
++ : "+m" (sem->count)
++ : "a" (sem), "i" (-RWSEM_ACTIVE_WRITE_BIAS)
++ : "memory", "cc", "edx");
+ }
+
+ /*
+@@ -215,16 +220,16 @@ LOCK_PREFIX " xaddl %%edx,(%%eax)\n\t" /* tries to transition 0xffff0001 ->
+ */
+ static inline void __downgrade_write(struct rw_semaphore *sem)
+ {
+- __asm__ __volatile__(
+- "# beginning __downgrade_write\n\t"
+-LOCK_PREFIX " addl %2,(%%eax)\n\t" /* transitions 0xZZZZ0001 -> 0xYYYY0001 */
+- " jns 1f\n\t"
+- " call call_rwsem_downgrade_wake\n"
+- "1:\n\t"
+- "# ending __downgrade_write\n"
+- : "+m" (sem->count)
+- : "a" (sem), "i" (-RWSEM_WAITING_BIAS)
+- : "memory", "cc");
++ asm volatile("# beginning __downgrade_write\n\t"
++ LOCK_PREFIX " addl %2,(%%eax)\n\t"
++ /* transitions 0xZZZZ0001 -> 0xYYYY0001 */
++ " jns 1f\n\t"
++ " call call_rwsem_downgrade_wake\n"
++ "1:\n\t"
++ "# ending __downgrade_write\n"
++ : "+m" (sem->count)
++ : "a" (sem), "i" (-RWSEM_WAITING_BIAS)
++ : "memory", "cc");
+ }
+
+ /*
+@@ -232,10 +237,9 @@ LOCK_PREFIX " addl %2,(%%eax)\n\t" /* transitions 0xZZZZ0001 -> 0xYYYY0001
+ */
+ static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
+ {
+- __asm__ __volatile__(
+-LOCK_PREFIX "addl %1,%0"
+- : "+m" (sem->count)
+- : "ir" (delta));
++ asm volatile(LOCK_PREFIX "addl %1,%0"
++ : "+m" (sem->count)
++ : "ir" (delta));
+ }
+
+ /*
+@@ -245,12 +249,11 @@ static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
+ {
+ int tmp = delta;
+
+- __asm__ __volatile__(
+-LOCK_PREFIX "xadd %0,%1"
+- : "+r" (tmp), "+m" (sem->count)
+- : : "memory");
++ asm volatile(LOCK_PREFIX "xadd %0,%1"
++ : "+r" (tmp), "+m" (sem->count)
++ : : "memory");
+
+- return tmp+delta;
++ return tmp + delta;
+ }
+
+ static inline int rwsem_is_locked(struct rw_semaphore *sem)
+diff --git a/include/asm-x86/scatterlist.h b/include/asm-x86/scatterlist.h
+index d13c197..c043206 100644
+--- a/include/asm-x86/scatterlist.h
++++ b/include/asm-x86/scatterlist.h
+@@ -11,9 +11,7 @@ struct scatterlist {
+ unsigned int offset;
+ unsigned int length;
+ dma_addr_t dma_address;
+-#ifdef CONFIG_X86_64
+ unsigned int dma_length;
+-#endif
+ };
+
+ #define ARCH_HAS_SG_CHAIN
+diff --git a/include/asm-x86/segment.h b/include/asm-x86/segment.h
+index 23f0535..ed5131d 100644
+--- a/include/asm-x86/segment.h
++++ b/include/asm-x86/segment.h
+@@ -191,13 +191,14 @@
+ #define SEGMENT_TI_MASK 0x4
+
+ #define IDT_ENTRIES 256
++#define NUM_EXCEPTION_VECTORS 32
+ #define GDT_SIZE (GDT_ENTRIES * 8)
+ #define GDT_ENTRY_TLS_ENTRIES 3
+ #define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES * 8)
+
+ #ifdef __KERNEL__
+ #ifndef __ASSEMBLY__
+-extern const char early_idt_handlers[IDT_ENTRIES][10];
++extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS][10];
+ #endif
+ #endif
+
+diff --git a/include/asm-x86/semaphore.h b/include/asm-x86/semaphore.h
+index 572c0b6..d9b2034 100644
+--- a/include/asm-x86/semaphore.h
++++ b/include/asm-x86/semaphore.h
+@@ -1,5 +1 @@
+-#ifdef CONFIG_X86_32
+-# include "semaphore_32.h"
+-#else
+-# include "semaphore_64.h"
+-#endif
++#include <linux/semaphore.h>
+diff --git a/include/asm-x86/semaphore_32.h b/include/asm-x86/semaphore_32.h
+deleted file mode 100644
+index ac96d38..0000000
+--- a/include/asm-x86/semaphore_32.h
++++ /dev/null
+@@ -1,175 +0,0 @@
+-#ifndef _I386_SEMAPHORE_H
+-#define _I386_SEMAPHORE_H
+-
+-#include <linux/linkage.h>
+-
+-#ifdef __KERNEL__
+-
+-/*
+- * SMP- and interrupt-safe semaphores..
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- *
+- * Modified 1996-12-23 by Dave Grothe <dave at gcom.com> to fix bugs in
+- * the original code and to make semaphore waits
+- * interruptible so that processes waiting on
+- * semaphores can be killed.
+- * Modified 1999-02-14 by Andrea Arcangeli, split the sched.c helper
+- * functions in asm/sempahore-helper.h while fixing a
+- * potential and subtle race discovered by Ulrich Schmid
+- * in down_interruptible(). Since I started to play here I
+- * also implemented the `trylock' semaphore operation.
+- * 1999-07-02 Artur Skawina <skawina at geocities.com>
+- * Optimized "0(ecx)" -> "(ecx)" (the assembler does not
+- * do this). Changed calling sequences from push/jmp to
+- * traditional call/ret.
+- * Modified 2001-01-01 Andreas Franck <afranck at gmx.de>
+- * Some hacks to ensure compatibility with recent
+- * GCC snapshots, to avoid stack corruption when compiling
+- * with -fomit-frame-pointer. It's not sure if this will
+- * be fixed in GCC, as our previous implementation was a
+- * bit dubious.
+- *
+- * If you would like to see an analysis of this implementation, please
+- * ftp to gcom.com and download the file
+- * /pub/linux/src/semaphore/semaphore-2.0.24.tar.gz.
+- *
+- */
+-
+-#include <asm/system.h>
+-#include <asm/atomic.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-struct semaphore {
+- atomic_t count;
+- int sleepers;
+- wait_queue_head_t wait;
+-};
+-
+-
+-#define __SEMAPHORE_INITIALIZER(name, n) \
+-{ \
+- .count = ATOMIC_INIT(n), \
+- .sleepers = 0, \
+- .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+- struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+-/*
+- * *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+- *
+- * i'd rather use the more flexible initialization above, but sadly
+- * GCC 2.7.2.3 emits a bogus warning. EGCS doesn't. Oh well.
+- */
+- atomic_set(&sem->count, val);
+- sem->sleepers = 0;
+- init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+- sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+- sema_init(sem, 0);
+-}
+-
+-extern asmregparm void __down_failed(atomic_t *count_ptr);
+-extern asmregparm int __down_failed_interruptible(atomic_t *count_ptr);
+-extern asmregparm int __down_failed_trylock(atomic_t *count_ptr);
+-extern asmregparm void __up_wakeup(atomic_t *count_ptr);
+-
+-/*
+- * This is ugly, but we want the default case to fall through.
+- * "__down_failed" is a special asm handler that calls the C
+- * routine that actually waits. See arch/i386/kernel/semaphore.c
+- */
+-static inline void down(struct semaphore * sem)
+-{
+- might_sleep();
+- __asm__ __volatile__(
+- "# atomic down operation\n\t"
+- LOCK_PREFIX "decl %0\n\t" /* --sem->count */
+- "jns 2f\n"
+- "\tlea %0,%%eax\n\t"
+- "call __down_failed\n"
+- "2:"
+- :"+m" (sem->count)
+- :
+- :"memory","ax");
+-}
+-
+-/*
+- * Interruptible try to acquire a semaphore. If we obtained
+- * it, return zero. If we were interrupted, returns -EINTR
+- */
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+- int result;
+-
+- might_sleep();
+- __asm__ __volatile__(
+- "# atomic interruptible down operation\n\t"
+- "xorl %0,%0\n\t"
+- LOCK_PREFIX "decl %1\n\t" /* --sem->count */
+- "jns 2f\n\t"
+- "lea %1,%%eax\n\t"
+- "call __down_failed_interruptible\n"
+- "2:"
+- :"=&a" (result), "+m" (sem->count)
+- :
+- :"memory");
+- return result;
+-}
+-
+-/*
+- * Non-blockingly attempt to down() a semaphore.
+- * Returns zero if we acquired it
+- */
+-static inline int down_trylock(struct semaphore * sem)
+-{
+- int result;
+-
+- __asm__ __volatile__(
+- "# atomic interruptible down operation\n\t"
+- "xorl %0,%0\n\t"
+- LOCK_PREFIX "decl %1\n\t" /* --sem->count */
+- "jns 2f\n\t"
+- "lea %1,%%eax\n\t"
+- "call __down_failed_trylock\n\t"
+- "2:\n"
+- :"=&a" (result), "+m" (sem->count)
+- :
+- :"memory");
+- return result;
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- */
+-static inline void up(struct semaphore * sem)
+-{
+- __asm__ __volatile__(
+- "# atomic up operation\n\t"
+- LOCK_PREFIX "incl %0\n\t" /* ++sem->count */
+- "jg 1f\n\t"
+- "lea %0,%%eax\n\t"
+- "call __up_wakeup\n"
+- "1:"
+- :"+m" (sem->count)
+- :
+- :"memory","ax");
+-}
+-
+-#endif
+-#endif
+diff --git a/include/asm-x86/semaphore_64.h b/include/asm-x86/semaphore_64.h
+deleted file mode 100644
+index 7969430..0000000
+--- a/include/asm-x86/semaphore_64.h
++++ /dev/null
+@@ -1,180 +0,0 @@
+-#ifndef _X86_64_SEMAPHORE_H
+-#define _X86_64_SEMAPHORE_H
+-
+-#include <linux/linkage.h>
+-
+-#ifdef __KERNEL__
+-
+-/*
+- * SMP- and interrupt-safe semaphores..
+- *
+- * (C) Copyright 1996 Linus Torvalds
+- *
+- * Modified 1996-12-23 by Dave Grothe <dave at gcom.com> to fix bugs in
+- * the original code and to make semaphore waits
+- * interruptible so that processes waiting on
+- * semaphores can be killed.
+- * Modified 1999-02-14 by Andrea Arcangeli, split the sched.c helper
+- * functions in asm/sempahore-helper.h while fixing a
+- * potential and subtle race discovered by Ulrich Schmid
+- * in down_interruptible(). Since I started to play here I
+- * also implemented the `trylock' semaphore operation.
+- * 1999-07-02 Artur Skawina <skawina at geocities.com>
+- * Optimized "0(ecx)" -> "(ecx)" (the assembler does not
+- * do this). Changed calling sequences from push/jmp to
+- * traditional call/ret.
+- * Modified 2001-01-01 Andreas Franck <afranck at gmx.de>
+- * Some hacks to ensure compatibility with recent
+- * GCC snapshots, to avoid stack corruption when compiling
+- * with -fomit-frame-pointer. It's not sure if this will
+- * be fixed in GCC, as our previous implementation was a
+- * bit dubious.
+- *
+- * If you would like to see an analysis of this implementation, please
+- * ftp to gcom.com and download the file
+- * /pub/linux/src/semaphore/semaphore-2.0.24.tar.gz.
+- *
+- */
+-
+-#include <asm/system.h>
+-#include <asm/atomic.h>
+-#include <asm/rwlock.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-#include <linux/stringify.h>
+-
+-struct semaphore {
+- atomic_t count;
+- int sleepers;
+- wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name, n) \
+-{ \
+- .count = ATOMIC_INIT(n), \
+- .sleepers = 0, \
+- .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+- struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+-/*
+- * *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+- *
+- * i'd rather use the more flexible initialization above, but sadly
+- * GCC 2.7.2.3 emits a bogus warning. EGCS doesn't. Oh well.
+- */
+- atomic_set(&sem->count, val);
+- sem->sleepers = 0;
+- init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+- sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+- sema_init(sem, 0);
+-}
+-
+-asmlinkage void __down_failed(void /* special register calling convention */);
+-asmlinkage int __down_failed_interruptible(void /* params in registers */);
+-asmlinkage int __down_failed_trylock(void /* params in registers */);
+-asmlinkage void __up_wakeup(void /* special register calling convention */);
+-
+-asmlinkage void __down(struct semaphore * sem);
+-asmlinkage int __down_interruptible(struct semaphore * sem);
+-asmlinkage int __down_trylock(struct semaphore * sem);
+-asmlinkage void __up(struct semaphore * sem);
+-
+-/*
+- * This is ugly, but we want the default case to fall through.
+- * "__down_failed" is a special asm handler that calls the C
+- * routine that actually waits. See arch/x86_64/kernel/semaphore.c
+- */
+-static inline void down(struct semaphore * sem)
+-{
+- might_sleep();
+-
+- __asm__ __volatile__(
+- "# atomic down operation\n\t"
+- LOCK_PREFIX "decl %0\n\t" /* --sem->count */
+- "jns 1f\n\t"
+- "call __down_failed\n"
+- "1:"
+- :"=m" (sem->count)
+- :"D" (sem)
+- :"memory");
+-}
+-
+-/*
+- * Interruptible try to acquire a semaphore. If we obtained
+- * it, return zero. If we were interrupted, returns -EINTR
+- */
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+- int result;
+-
+- might_sleep();
+-
+- __asm__ __volatile__(
+- "# atomic interruptible down operation\n\t"
+- "xorl %0,%0\n\t"
+- LOCK_PREFIX "decl %1\n\t" /* --sem->count */
+- "jns 2f\n\t"
+- "call __down_failed_interruptible\n"
+- "2:\n"
+- :"=&a" (result), "=m" (sem->count)
+- :"D" (sem)
+- :"memory");
+- return result;
+-}
+-
+-/*
+- * Non-blockingly attempt to down() a semaphore.
+- * Returns zero if we acquired it
+- */
+-static inline int down_trylock(struct semaphore * sem)
+-{
+- int result;
+-
+- __asm__ __volatile__(
+- "# atomic interruptible down operation\n\t"
+- "xorl %0,%0\n\t"
+- LOCK_PREFIX "decl %1\n\t" /* --sem->count */
+- "jns 2f\n\t"
+- "call __down_failed_trylock\n\t"
+- "2:\n"
+- :"=&a" (result), "=m" (sem->count)
+- :"D" (sem)
+- :"memory","cc");
+- return result;
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- * The default case (no contention) will result in NO
+- * jumps for both down() and up().
+- */
+-static inline void up(struct semaphore * sem)
+-{
+- __asm__ __volatile__(
+- "# atomic up operation\n\t"
+- LOCK_PREFIX "incl %0\n\t" /* ++sem->count */
+- "jg 1f\n\t"
+- "call __up_wakeup\n"
+- "1:"
+- :"=m" (sem->count)
+- :"D" (sem)
+- :"memory");
+-}
+-#endif /* __KERNEL__ */
+-#endif
+diff --git a/include/asm-x86/setup.h b/include/asm-x86/setup.h
+index 071e054..fa6763a 100644
+--- a/include/asm-x86/setup.h
++++ b/include/asm-x86/setup.h
+@@ -4,6 +4,10 @@
+ #define COMMAND_LINE_SIZE 2048
+
+ #ifndef __ASSEMBLY__
++
++/* Interrupt control for vSMPowered x86_64 systems */
++void vsmp_init(void);
++
+ char *machine_specific_memory_setup(void);
+ #ifndef CONFIG_PARAVIRT
+ #define paravirt_post_allocator_init() do {} while (0)
+@@ -51,8 +55,8 @@ struct e820entry;
+ char * __init machine_specific_memory_setup(void);
+ char *memory_setup(void);
+
+-int __init copy_e820_map(struct e820entry * biosmap, int nr_map);
+-int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map);
++int __init copy_e820_map(struct e820entry *biosmap, int nr_map);
++int __init sanitize_e820_map(struct e820entry *biosmap, char *pnr_map);
+ void __init add_memory_region(unsigned long long start,
+ unsigned long long size, int type);
+
+diff --git a/include/asm-x86/sigcontext.h b/include/asm-x86/sigcontext.h
+index d743947..2f9c884 100644
+--- a/include/asm-x86/sigcontext.h
++++ b/include/asm-x86/sigcontext.h
+@@ -79,7 +79,7 @@ struct sigcontext {
+ unsigned long flags;
+ unsigned long sp_at_signal;
+ unsigned short ss, __ssh;
+- struct _fpstate __user * fpstate;
++ struct _fpstate __user *fpstate;
+ unsigned long oldmask;
+ unsigned long cr2;
+ };
+@@ -107,7 +107,7 @@ struct sigcontext {
+ unsigned long eflags;
+ unsigned long esp_at_signal;
+ unsigned short ss, __ssh;
+- struct _fpstate __user * fpstate;
++ struct _fpstate __user *fpstate;
+ unsigned long oldmask;
+ unsigned long cr2;
+ };
+@@ -121,7 +121,8 @@ struct sigcontext {
+ struct _fpstate {
+ __u16 cwd;
+ __u16 swd;
+- __u16 twd; /* Note this is not the same as the 32bit/x87/FSAVE twd */
++ __u16 twd; /* Note this is not the same as the
++ 32bit/x87/FSAVE twd */
+ __u16 fop;
+ __u64 rip;
+ __u64 rdp;
+diff --git a/include/asm-x86/sigcontext32.h b/include/asm-x86/sigcontext32.h
+index 6ffab4f..57a9686 100644
+--- a/include/asm-x86/sigcontext32.h
++++ b/include/asm-x86/sigcontext32.h
+@@ -26,7 +26,7 @@ struct _fpstate_ia32 {
+ __u32 cw;
+ __u32 sw;
+ __u32 tag; /* not compatible to 64bit twd */
+- __u32 ipoff;
++ __u32 ipoff;
+ __u32 cssel;
+ __u32 dataoff;
+ __u32 datasel;
+@@ -39,7 +39,7 @@ struct _fpstate_ia32 {
+ __u32 mxcsr;
+ __u32 reserved;
+ struct _fpxreg _fxsr_st[8];
+- struct _xmmreg _xmm[8]; /* It's actually 16 */
++ struct _xmmreg _xmm[8]; /* It's actually 16 */
+ __u32 padding[56];
+ };
+
+diff --git a/include/asm-x86/signal.h b/include/asm-x86/signal.h
+index aee7eca..f15186d 100644
+--- a/include/asm-x86/signal.h
++++ b/include/asm-x86/signal.h
+@@ -185,61 +185,61 @@ typedef struct sigaltstack {
+
+ #define __HAVE_ARCH_SIG_BITOPS
+
+-#define sigaddset(set,sig) \
+- (__builtin_constantp(sig) ? \
+- __const_sigaddset((set),(sig)) : \
+- __gen_sigaddset((set),(sig)))
++#define sigaddset(set,sig) \
++ (__builtin_constantp(sig) \
++ ? __const_sigaddset((set), (sig)) \
++ : __gen_sigaddset((set), (sig)))
+
+-static __inline__ void __gen_sigaddset(sigset_t *set, int _sig)
++static inline void __gen_sigaddset(sigset_t *set, int _sig)
+ {
+- __asm__("btsl %1,%0" : "+m"(*set) : "Ir"(_sig - 1) : "cc");
++ asm("btsl %1,%0" : "+m"(*set) : "Ir"(_sig - 1) : "cc");
+ }
+
+-static __inline__ void __const_sigaddset(sigset_t *set, int _sig)
++static inline void __const_sigaddset(sigset_t *set, int _sig)
+ {
+ unsigned long sig = _sig - 1;
+ set->sig[sig / _NSIG_BPW] |= 1 << (sig % _NSIG_BPW);
+ }
+
+-#define sigdelset(set,sig) \
+- (__builtin_constant_p(sig) ? \
+- __const_sigdelset((set),(sig)) : \
+- __gen_sigdelset((set),(sig)))
++#define sigdelset(set, sig) \
++ (__builtin_constant_p(sig) \
++ ? __const_sigdelset((set), (sig)) \
++ : __gen_sigdelset((set), (sig)))
+
+
+-static __inline__ void __gen_sigdelset(sigset_t *set, int _sig)
++static inline void __gen_sigdelset(sigset_t *set, int _sig)
+ {
+- __asm__("btrl %1,%0" : "+m"(*set) : "Ir"(_sig - 1) : "cc");
++ asm("btrl %1,%0" : "+m"(*set) : "Ir"(_sig - 1) : "cc");
+ }
+
+-static __inline__ void __const_sigdelset(sigset_t *set, int _sig)
++static inline void __const_sigdelset(sigset_t *set, int _sig)
+ {
+ unsigned long sig = _sig - 1;
+ set->sig[sig / _NSIG_BPW] &= ~(1 << (sig % _NSIG_BPW));
+ }
+
+-static __inline__ int __const_sigismember(sigset_t *set, int _sig)
++static inline int __const_sigismember(sigset_t *set, int _sig)
+ {
+ unsigned long sig = _sig - 1;
+ return 1 & (set->sig[sig / _NSIG_BPW] >> (sig % _NSIG_BPW));
+ }
+
+-static __inline__ int __gen_sigismember(sigset_t *set, int _sig)
++static inline int __gen_sigismember(sigset_t *set, int _sig)
+ {
+ int ret;
+- __asm__("btl %2,%1\n\tsbbl %0,%0"
+- : "=r"(ret) : "m"(*set), "Ir"(_sig-1) : "cc");
++ asm("btl %2,%1\n\tsbbl %0,%0"
++ : "=r"(ret) : "m"(*set), "Ir"(_sig-1) : "cc");
+ return ret;
+ }
+
+-#define sigismember(set,sig) \
+- (__builtin_constant_p(sig) ? \
+- __const_sigismember((set),(sig)) : \
+- __gen_sigismember((set),(sig)))
++#define sigismember(set, sig) \
++ (__builtin_constant_p(sig) \
++ ? __const_sigismember((set), (sig)) \
++ : __gen_sigismember((set), (sig)))
+
+-static __inline__ int sigfindinword(unsigned long word)
++static inline int sigfindinword(unsigned long word)
+ {
+- __asm__("bsfl %1,%0" : "=r"(word) : "rm"(word) : "cc");
++ asm("bsfl %1,%0" : "=r"(word) : "rm"(word) : "cc");
+ return word;
+ }
+
+diff --git a/include/asm-x86/smp.h b/include/asm-x86/smp.h
+index f2e8319..1ebaa5c 100644
+--- a/include/asm-x86/smp.h
++++ b/include/asm-x86/smp.h
+@@ -1,5 +1,208 @@
+-#ifdef CONFIG_X86_32
+-# include "smp_32.h"
++#ifndef _ASM_X86_SMP_H_
++#define _ASM_X86_SMP_H_
++#ifndef __ASSEMBLY__
++#include <linux/cpumask.h>
++#include <linux/init.h>
++#include <asm/percpu.h>
++
++/*
++ * We need the APIC definitions automatically as part of 'smp.h'
++ */
++#ifdef CONFIG_X86_LOCAL_APIC
++# include <asm/mpspec.h>
++# include <asm/apic.h>
++# ifdef CONFIG_X86_IO_APIC
++# include <asm/io_apic.h>
++# endif
++#endif
++#include <asm/pda.h>
++#include <asm/thread_info.h>
++
++extern cpumask_t cpu_callout_map;
++extern cpumask_t cpu_initialized;
++extern cpumask_t cpu_callin_map;
++
++extern void (*mtrr_hook)(void);
++extern void zap_low_mappings(void);
++
++extern int smp_num_siblings;
++extern unsigned int num_processors;
++extern cpumask_t cpu_initialized;
++
++#ifdef CONFIG_SMP
++extern u16 x86_cpu_to_apicid_init[];
++extern u16 x86_bios_cpu_apicid_init[];
++extern void *x86_cpu_to_apicid_early_ptr;
++extern void *x86_bios_cpu_apicid_early_ptr;
+ #else
+-# include "smp_64.h"
++#define x86_cpu_to_apicid_early_ptr NULL
++#define x86_bios_cpu_apicid_early_ptr NULL
++#endif
++
++DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
++DECLARE_PER_CPU(cpumask_t, cpu_core_map);
++DECLARE_PER_CPU(u16, cpu_llc_id);
++DECLARE_PER_CPU(u16, x86_cpu_to_apicid);
++DECLARE_PER_CPU(u16, x86_bios_cpu_apicid);
++
++/* Static state in head.S used to set up a CPU */
++extern struct {
++ void *sp;
++ unsigned short ss;
++} stack_start;
++
++struct smp_ops {
++ void (*smp_prepare_boot_cpu)(void);
++ void (*smp_prepare_cpus)(unsigned max_cpus);
++ int (*cpu_up)(unsigned cpu);
++ void (*smp_cpus_done)(unsigned max_cpus);
++
++ void (*smp_send_stop)(void);
++ void (*smp_send_reschedule)(int cpu);
++ int (*smp_call_function_mask)(cpumask_t mask,
++ void (*func)(void *info), void *info,
++ int wait);
++};
++
++/* Globals due to paravirt */
++extern void set_cpu_sibling_map(int cpu);
++
++#ifdef CONFIG_SMP
++#ifndef CONFIG_PARAVIRT
++#define startup_ipi_hook(phys_apicid, start_eip, start_esp) do { } while (0)
++#endif
++extern struct smp_ops smp_ops;
++
++static inline void smp_send_stop(void)
++{
++ smp_ops.smp_send_stop();
++}
++
++static inline void smp_prepare_boot_cpu(void)
++{
++ smp_ops.smp_prepare_boot_cpu();
++}
++
++static inline void smp_prepare_cpus(unsigned int max_cpus)
++{
++ smp_ops.smp_prepare_cpus(max_cpus);
++}
++
++static inline void smp_cpus_done(unsigned int max_cpus)
++{
++ smp_ops.smp_cpus_done(max_cpus);
++}
++
++static inline int __cpu_up(unsigned int cpu)
++{
++ return smp_ops.cpu_up(cpu);
++}
++
++static inline void smp_send_reschedule(int cpu)
++{
++ smp_ops.smp_send_reschedule(cpu);
++}
++
++static inline int smp_call_function_mask(cpumask_t mask,
++ void (*func) (void *info), void *info,
++ int wait)
++{
++ return smp_ops.smp_call_function_mask(mask, func, info, wait);
++}
++
++void native_smp_prepare_boot_cpu(void);
++void native_smp_prepare_cpus(unsigned int max_cpus);
++void native_smp_cpus_done(unsigned int max_cpus);
++int native_cpu_up(unsigned int cpunum);
++
++extern int __cpu_disable(void);
++extern void __cpu_die(unsigned int cpu);
++
++extern void prefill_possible_map(void);
++
++void smp_store_cpu_info(int id);
++#define cpu_physical_id(cpu) per_cpu(x86_cpu_to_apicid, cpu)
++
++/* We don't mark CPUs online until __cpu_up(), so we need another measure */
++static inline int num_booting_cpus(void)
++{
++ return cpus_weight(cpu_callout_map);
++}
++#endif /* CONFIG_SMP */
++
++extern unsigned disabled_cpus __cpuinitdata;
++
++#ifdef CONFIG_X86_32_SMP
++/*
++ * This function is needed by all SMP systems. It must _always_ be valid
++ * from the initial startup. We map APIC_BASE very early in page_setup(),
++ * so this is correct in the x86 case.
++ */
++DECLARE_PER_CPU(int, cpu_number);
++#define raw_smp_processor_id() (x86_read_percpu(cpu_number))
++extern int safe_smp_processor_id(void);
++
++#elif defined(CONFIG_X86_64_SMP)
++#define raw_smp_processor_id() read_pda(cpunumber)
++
++#define stack_smp_processor_id() \
++({ \
++ struct thread_info *ti; \
++ __asm__("andq %%rsp,%0; ":"=r" (ti) : "0" (CURRENT_MASK)); \
++ ti->cpu; \
++})
++#define safe_smp_processor_id() smp_processor_id()
++
++#else /* !CONFIG_X86_32_SMP && !CONFIG_X86_64_SMP */
++#define cpu_physical_id(cpu) boot_cpu_physical_apicid
++#define safe_smp_processor_id() 0
++#define stack_smp_processor_id() 0
++#endif
++
++#ifdef CONFIG_X86_LOCAL_APIC
++
++static inline int logical_smp_processor_id(void)
++{
++ /* we don't want to mark this access volatile - bad code generation */
++ return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR));
++}
++
++#ifndef CONFIG_X86_64
++static inline unsigned int read_apic_id(void)
++{
++ return *(u32 *)(APIC_BASE + APIC_ID);
++}
++#else
++extern unsigned int read_apic_id(void);
++#endif
++
++
++# ifdef APIC_DEFINITION
++extern int hard_smp_processor_id(void);
++# else
++# include <mach_apicdef.h>
++static inline int hard_smp_processor_id(void)
++{
++ /* we don't want to mark this access volatile - bad code generation */
++ return GET_APIC_ID(read_apic_id());
++}
++# endif /* APIC_DEFINITION */
++
++#else /* CONFIG_X86_LOCAL_APIC */
++
++# ifndef CONFIG_SMP
++# define hard_smp_processor_id() 0
++# endif
++
++#endif /* CONFIG_X86_LOCAL_APIC */
++
++#ifdef CONFIG_HOTPLUG_CPU
++extern void cpu_exit_clear(void);
++extern void cpu_uninit(void);
++#endif
++
++extern void smp_alloc_memory(void);
++extern void lock_ipi_call_lock(void);
++extern void unlock_ipi_call_lock(void);
++#endif /* __ASSEMBLY__ */
+ #endif
+diff --git a/include/asm-x86/smp_32.h b/include/asm-x86/smp_32.h
+deleted file mode 100644
+index 56152e3..0000000
+--- a/include/asm-x86/smp_32.h
++++ /dev/null
+@@ -1,165 +0,0 @@
+-#ifndef __ASM_SMP_H
+-#define __ASM_SMP_H
+-
+-#ifndef __ASSEMBLY__
+-#include <linux/cpumask.h>
+-#include <linux/init.h>
+-
+-/*
+- * We need the APIC definitions automatically as part of 'smp.h'
+- */
+-#ifdef CONFIG_X86_LOCAL_APIC
+-# include <asm/mpspec.h>
+-# include <asm/apic.h>
+-# ifdef CONFIG_X86_IO_APIC
+-# include <asm/io_apic.h>
+-# endif
+-#endif
+-
+-extern cpumask_t cpu_callout_map;
+-extern cpumask_t cpu_callin_map;
+-
+-extern int smp_num_siblings;
+-extern unsigned int num_processors;
+-
+-extern void smp_alloc_memory(void);
+-extern void lock_ipi_call_lock(void);
+-extern void unlock_ipi_call_lock(void);
+-
+-extern void (*mtrr_hook) (void);
+-extern void zap_low_mappings (void);
+-
+-extern u8 __initdata x86_cpu_to_apicid_init[];
+-extern void *x86_cpu_to_apicid_early_ptr;
+-
+-DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
+-DECLARE_PER_CPU(cpumask_t, cpu_core_map);
+-DECLARE_PER_CPU(u8, cpu_llc_id);
+-DECLARE_PER_CPU(u8, x86_cpu_to_apicid);
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-extern void cpu_exit_clear(void);
+-extern void cpu_uninit(void);
+-extern void remove_siblinginfo(int cpu);
+-#endif
+-
+-/* Globals due to paravirt */
+-extern void set_cpu_sibling_map(int cpu);
+-
+-struct smp_ops
+-{
+- void (*smp_prepare_boot_cpu)(void);
+- void (*smp_prepare_cpus)(unsigned max_cpus);
+- int (*cpu_up)(unsigned cpu);
+- void (*smp_cpus_done)(unsigned max_cpus);
+-
+- void (*smp_send_stop)(void);
+- void (*smp_send_reschedule)(int cpu);
+- int (*smp_call_function_mask)(cpumask_t mask,
+- void (*func)(void *info), void *info,
+- int wait);
+-};
+-
+-#ifdef CONFIG_SMP
+-extern struct smp_ops smp_ops;
+-
+-static inline void smp_prepare_boot_cpu(void)
+-{
+- smp_ops.smp_prepare_boot_cpu();
+-}
+-static inline void smp_prepare_cpus(unsigned int max_cpus)
+-{
+- smp_ops.smp_prepare_cpus(max_cpus);
+-}
+-static inline int __cpu_up(unsigned int cpu)
+-{
+- return smp_ops.cpu_up(cpu);
+-}
+-static inline void smp_cpus_done(unsigned int max_cpus)
+-{
+- smp_ops.smp_cpus_done(max_cpus);
+-}
+-
+-static inline void smp_send_stop(void)
+-{
+- smp_ops.smp_send_stop();
+-}
+-static inline void smp_send_reschedule(int cpu)
+-{
+- smp_ops.smp_send_reschedule(cpu);
+-}
+-static inline int smp_call_function_mask(cpumask_t mask,
+- void (*func) (void *info), void *info,
+- int wait)
+-{
+- return smp_ops.smp_call_function_mask(mask, func, info, wait);
+-}
+-
+-void native_smp_prepare_boot_cpu(void);
+-void native_smp_prepare_cpus(unsigned int max_cpus);
+-int native_cpu_up(unsigned int cpunum);
+-void native_smp_cpus_done(unsigned int max_cpus);
+-
+-#ifndef CONFIG_PARAVIRT
+-#define startup_ipi_hook(phys_apicid, start_eip, start_esp) do { } while (0)
+-#endif
+-
+-extern int __cpu_disable(void);
+-extern void __cpu_die(unsigned int cpu);
+-
+-/*
+- * This function is needed by all SMP systems. It must _always_ be valid
+- * from the initial startup. We map APIC_BASE very early in page_setup(),
+- * so this is correct in the x86 case.
+- */
+-DECLARE_PER_CPU(int, cpu_number);
+-#define raw_smp_processor_id() (x86_read_percpu(cpu_number))
+-
+-#define cpu_physical_id(cpu) per_cpu(x86_cpu_to_apicid, cpu)
+-
+-extern int safe_smp_processor_id(void);
+-
+-void __cpuinit smp_store_cpu_info(int id);
+-
+-/* We don't mark CPUs online until __cpu_up(), so we need another measure */
+-static inline int num_booting_cpus(void)
+-{
+- return cpus_weight(cpu_callout_map);
+-}
+-
+-#else /* CONFIG_SMP */
+-
+-#define safe_smp_processor_id() 0
+-#define cpu_physical_id(cpu) boot_cpu_physical_apicid
+-
+-#endif /* !CONFIG_SMP */
+-
+-#ifdef CONFIG_X86_LOCAL_APIC
+-
+-static __inline int logical_smp_processor_id(void)
+-{
+- /* we don't want to mark this access volatile - bad code generation */
+- return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR));
+-}
+-
+-# ifdef APIC_DEFINITION
+-extern int hard_smp_processor_id(void);
+-# else
+-# include <mach_apicdef.h>
+-static inline int hard_smp_processor_id(void)
+-{
+- /* we don't want to mark this access volatile - bad code generation */
+- return GET_APIC_ID(*(u32 *)(APIC_BASE + APIC_ID));
+-}
+-# endif /* APIC_DEFINITION */
+-
+-#else /* CONFIG_X86_LOCAL_APIC */
+-
+-# ifndef CONFIG_SMP
+-# define hard_smp_processor_id() 0
+-# endif
+-
+-#endif /* CONFIG_X86_LOCAL_APIC */
+-
+-#endif /* !ASSEMBLY */
+-#endif
+diff --git a/include/asm-x86/smp_64.h b/include/asm-x86/smp_64.h
+deleted file mode 100644
+index e0a7551..0000000
+--- a/include/asm-x86/smp_64.h
++++ /dev/null
+@@ -1,101 +0,0 @@
+-#ifndef __ASM_SMP_H
+-#define __ASM_SMP_H
+-
+-#include <linux/cpumask.h>
+-#include <linux/init.h>
+-
+-/*
+- * We need the APIC definitions automatically as part of 'smp.h'
+- */
+-#include <asm/apic.h>
+-#include <asm/io_apic.h>
+-#include <asm/mpspec.h>
+-#include <asm/pda.h>
+-#include <asm/thread_info.h>
+-
+-extern cpumask_t cpu_callout_map;
+-extern cpumask_t cpu_initialized;
+-
+-extern int smp_num_siblings;
+-extern unsigned int num_processors;
+-
+-extern void smp_alloc_memory(void);
+-extern void lock_ipi_call_lock(void);
+-extern void unlock_ipi_call_lock(void);
+-
+-extern int smp_call_function_mask(cpumask_t mask, void (*func)(void *),
+- void *info, int wait);
+-
+-extern u16 __initdata x86_cpu_to_apicid_init[];
+-extern u16 __initdata x86_bios_cpu_apicid_init[];
+-extern void *x86_cpu_to_apicid_early_ptr;
+-extern void *x86_bios_cpu_apicid_early_ptr;
+-
+-DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
+-DECLARE_PER_CPU(cpumask_t, cpu_core_map);
+-DECLARE_PER_CPU(u16, cpu_llc_id);
+-DECLARE_PER_CPU(u16, x86_cpu_to_apicid);
+-DECLARE_PER_CPU(u16, x86_bios_cpu_apicid);
+-
+-static inline int cpu_present_to_apicid(int mps_cpu)
+-{
+- if (cpu_present(mps_cpu))
+- return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu);
+- else
+- return BAD_APICID;
+-}
+-
+-#ifdef CONFIG_SMP
+-
+-#define SMP_TRAMPOLINE_BASE 0x6000
+-
+-extern int __cpu_disable(void);
+-extern void __cpu_die(unsigned int cpu);
+-extern void prefill_possible_map(void);
+-extern unsigned __cpuinitdata disabled_cpus;
+-
+-#define raw_smp_processor_id() read_pda(cpunumber)
+-#define cpu_physical_id(cpu) per_cpu(x86_cpu_to_apicid, cpu)
+-
+-#define stack_smp_processor_id() \
+- ({ \
+- struct thread_info *ti; \
+- __asm__("andq %%rsp,%0; ":"=r" (ti) : "0" (CURRENT_MASK)); \
+- ti->cpu; \
+-})
+-
+-/*
+- * On x86 all CPUs are mapped 1:1 to the APIC space. This simplifies
+- * scheduling and IPI sending and compresses data structures.
+- */
+-static inline int num_booting_cpus(void)
+-{
+- return cpus_weight(cpu_callout_map);
+-}
+-
+-extern void smp_send_reschedule(int cpu);
+-
+-#else /* CONFIG_SMP */
+-
+-extern unsigned int boot_cpu_id;
+-#define cpu_physical_id(cpu) boot_cpu_id
+-#define stack_smp_processor_id() 0
+-
+-#endif /* !CONFIG_SMP */
+-
+-#define safe_smp_processor_id() smp_processor_id()
+-
+-static __inline int logical_smp_processor_id(void)
+-{
+- /* we don't want to mark this access volatile - bad code generation */
+- return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR));
+-}
+-
+-static inline int hard_smp_processor_id(void)
+-{
+- /* we don't want to mark this access volatile - bad code generation */
+- return GET_APIC_ID(*(u32 *)(APIC_BASE + APIC_ID));
+-}
+-
+-#endif
+-
+diff --git a/include/asm-x86/sparsemem.h b/include/asm-x86/sparsemem.h
+index fa58cd5..9bd48b0 100644
+--- a/include/asm-x86/sparsemem.h
++++ b/include/asm-x86/sparsemem.h
+@@ -16,7 +16,7 @@
+
+ #ifdef CONFIG_X86_32
+ # ifdef CONFIG_X86_PAE
+-# define SECTION_SIZE_BITS 30
++# define SECTION_SIZE_BITS 29
+ # define MAX_PHYSADDR_BITS 36
+ # define MAX_PHYSMEM_BITS 36
+ # else
+@@ -26,8 +26,8 @@
+ # endif
+ #else /* CONFIG_X86_32 */
+ # define SECTION_SIZE_BITS 27 /* matt - 128 is convenient right now */
+-# define MAX_PHYSADDR_BITS 40
+-# define MAX_PHYSMEM_BITS 40
++# define MAX_PHYSADDR_BITS 44
++# define MAX_PHYSMEM_BITS 44
+ #endif
+
+ #endif /* CONFIG_SPARSEMEM */
+diff --git a/include/asm-x86/spinlock.h b/include/asm-x86/spinlock.h
+index 23804c1..bc6376f 100644
+--- a/include/asm-x86/spinlock.h
++++ b/include/asm-x86/spinlock.h
+@@ -78,11 +78,11 @@ static inline int __raw_spin_is_contended(raw_spinlock_t *lock)
+ return (((tmp >> 8) & 0xff) - (tmp & 0xff)) > 1;
+ }
+
+-static inline void __raw_spin_lock(raw_spinlock_t *lock)
++static __always_inline void __raw_spin_lock(raw_spinlock_t *lock)
+ {
+ short inc = 0x0100;
+
+- __asm__ __volatile__ (
++ asm volatile (
+ LOCK_PREFIX "xaddw %w0, %1\n"
+ "1:\t"
+ "cmpb %h0, %b0\n\t"
+@@ -92,42 +92,40 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
+ /* don't need lfence here, because loads are in-order */
+ "jmp 1b\n"
+ "2:"
+- :"+Q" (inc), "+m" (lock->slock)
++ : "+Q" (inc), "+m" (lock->slock)
+ :
+- :"memory", "cc");
++ : "memory", "cc");
+ }
+
+ #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+
+-static inline int __raw_spin_trylock(raw_spinlock_t *lock)
++static __always_inline int __raw_spin_trylock(raw_spinlock_t *lock)
+ {
+ int tmp;
+ short new;
+
+- asm volatile(
+- "movw %2,%w0\n\t"
+- "cmpb %h0,%b0\n\t"
+- "jne 1f\n\t"
+- "movw %w0,%w1\n\t"
+- "incb %h1\n\t"
+- "lock ; cmpxchgw %w1,%2\n\t"
+- "1:"
+- "sete %b1\n\t"
+- "movzbl %b1,%0\n\t"
+- :"=&a" (tmp), "=Q" (new), "+m" (lock->slock)
+- :
+- : "memory", "cc");
++ asm volatile("movw %2,%w0\n\t"
++ "cmpb %h0,%b0\n\t"
++ "jne 1f\n\t"
++ "movw %w0,%w1\n\t"
++ "incb %h1\n\t"
++ "lock ; cmpxchgw %w1,%2\n\t"
++ "1:"
++ "sete %b1\n\t"
++ "movzbl %b1,%0\n\t"
++ : "=&a" (tmp), "=Q" (new), "+m" (lock->slock)
++ :
++ : "memory", "cc");
+
+ return tmp;
+ }
+
+-static inline void __raw_spin_unlock(raw_spinlock_t *lock)
++static __always_inline void __raw_spin_unlock(raw_spinlock_t *lock)
+ {
+- __asm__ __volatile__(
+- UNLOCK_LOCK_PREFIX "incb %0"
+- :"+m" (lock->slock)
+- :
+- :"memory", "cc");
++ asm volatile(UNLOCK_LOCK_PREFIX "incb %0"
++ : "+m" (lock->slock)
++ :
++ : "memory", "cc");
+ }
+ #else
+ static inline int __raw_spin_is_locked(raw_spinlock_t *lock)
+@@ -144,60 +142,57 @@ static inline int __raw_spin_is_contended(raw_spinlock_t *lock)
+ return (((tmp >> 16) & 0xffff) - (tmp & 0xffff)) > 1;
+ }
+
+-static inline void __raw_spin_lock(raw_spinlock_t *lock)
++static __always_inline void __raw_spin_lock(raw_spinlock_t *lock)
+ {
+ int inc = 0x00010000;
+ int tmp;
+
+- __asm__ __volatile__ (
+- "lock ; xaddl %0, %1\n"
+- "movzwl %w0, %2\n\t"
+- "shrl $16, %0\n\t"
+- "1:\t"
+- "cmpl %0, %2\n\t"
+- "je 2f\n\t"
+- "rep ; nop\n\t"
+- "movzwl %1, %2\n\t"
+- /* don't need lfence here, because loads are in-order */
+- "jmp 1b\n"
+- "2:"
+- :"+Q" (inc), "+m" (lock->slock), "=r" (tmp)
+- :
+- :"memory", "cc");
++ asm volatile("lock ; xaddl %0, %1\n"
++ "movzwl %w0, %2\n\t"
++ "shrl $16, %0\n\t"
++ "1:\t"
++ "cmpl %0, %2\n\t"
++ "je 2f\n\t"
++ "rep ; nop\n\t"
++ "movzwl %1, %2\n\t"
++ /* don't need lfence here, because loads are in-order */
++ "jmp 1b\n"
++ "2:"
++ : "+Q" (inc), "+m" (lock->slock), "=r" (tmp)
++ :
++ : "memory", "cc");
+ }
+
+ #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+
+-static inline int __raw_spin_trylock(raw_spinlock_t *lock)
++static __always_inline int __raw_spin_trylock(raw_spinlock_t *lock)
+ {
+ int tmp;
+ int new;
+
+- asm volatile(
+- "movl %2,%0\n\t"
+- "movl %0,%1\n\t"
+- "roll $16, %0\n\t"
+- "cmpl %0,%1\n\t"
+- "jne 1f\n\t"
+- "addl $0x00010000, %1\n\t"
+- "lock ; cmpxchgl %1,%2\n\t"
+- "1:"
+- "sete %b1\n\t"
+- "movzbl %b1,%0\n\t"
+- :"=&a" (tmp), "=r" (new), "+m" (lock->slock)
+- :
+- : "memory", "cc");
++ asm volatile("movl %2,%0\n\t"
++ "movl %0,%1\n\t"
++ "roll $16, %0\n\t"
++ "cmpl %0,%1\n\t"
++ "jne 1f\n\t"
++ "addl $0x00010000, %1\n\t"
++ "lock ; cmpxchgl %1,%2\n\t"
++ "1:"
++ "sete %b1\n\t"
++ "movzbl %b1,%0\n\t"
++ : "=&a" (tmp), "=r" (new), "+m" (lock->slock)
++ :
++ : "memory", "cc");
+
+ return tmp;
+ }
+
+-static inline void __raw_spin_unlock(raw_spinlock_t *lock)
++static __always_inline void __raw_spin_unlock(raw_spinlock_t *lock)
+ {
+- __asm__ __volatile__(
+- UNLOCK_LOCK_PREFIX "incw %0"
+- :"+m" (lock->slock)
+- :
+- :"memory", "cc");
++ asm volatile(UNLOCK_LOCK_PREFIX "incw %0"
++ : "+m" (lock->slock)
++ :
++ : "memory", "cc");
+ }
+ #endif
+
+diff --git a/include/asm-x86/srat.h b/include/asm-x86/srat.h
+index 165ab4b..f4bba13 100644
+--- a/include/asm-x86/srat.h
++++ b/include/asm-x86/srat.h
+@@ -1,5 +1,5 @@
+ /*
+- * Some of the code in this file has been gleaned from the 64 bit
++ * Some of the code in this file has been gleaned from the 64 bit
+ * discontigmem support code base.
+ *
+ * Copyright (C) 2002, IBM Corp.
+diff --git a/include/asm-x86/string_32.h b/include/asm-x86/string_32.h
+index c5d13a8..b49369a 100644
+--- a/include/asm-x86/string_32.h
++++ b/include/asm-x86/string_32.h
+@@ -3,7 +3,7 @@
+
+ #ifdef __KERNEL__
+
+-/* Let gcc decide wether to inline or use the out of line functions */
++/* Let gcc decide whether to inline or use the out of line functions */
+
+ #define __HAVE_ARCH_STRCPY
+ extern char *strcpy(char *dest, const char *src);
+diff --git a/include/asm-x86/string_64.h b/include/asm-x86/string_64.h
+index e583da7..52b5ab3 100644
+--- a/include/asm-x86/string_64.h
++++ b/include/asm-x86/string_64.h
+@@ -3,26 +3,24 @@
+
+ #ifdef __KERNEL__
+
+-/* Written 2002 by Andi Kleen */
++/* Written 2002 by Andi Kleen */
+
+-/* Only used for special circumstances. Stolen from i386/string.h */
+-static __always_inline void *
+-__inline_memcpy(void * to, const void * from, size_t n)
++/* Only used for special circumstances. Stolen from i386/string.h */
++static __always_inline void *__inline_memcpy(void *to, const void *from, size_t n)
+ {
+-unsigned long d0, d1, d2;
+-__asm__ __volatile__(
+- "rep ; movsl\n\t"
+- "testb $2,%b4\n\t"
+- "je 1f\n\t"
+- "movsw\n"
+- "1:\ttestb $1,%b4\n\t"
+- "je 2f\n\t"
+- "movsb\n"
+- "2:"
+- : "=&c" (d0), "=&D" (d1), "=&S" (d2)
+- :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
+- : "memory");
+-return (to);
++ unsigned long d0, d1, d2;
++ asm volatile("rep ; movsl\n\t"
++ "testb $2,%b4\n\t"
++ "je 1f\n\t"
++ "movsw\n"
++ "1:\ttestb $1,%b4\n\t"
++ "je 2f\n\t"
++ "movsb\n"
++ "2:"
++ : "=&c" (d0), "=&D" (d1), "=&S" (d2)
++ : "0" (n / 4), "q" (n), "1" ((long)to), "2" ((long)from)
++ : "memory");
++ return to;
+ }
+
+ /* Even with __builtin_ the compiler may decide to use the out of line
+@@ -32,28 +30,30 @@ return (to);
+ #if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4
+ extern void *memcpy(void *to, const void *from, size_t len);
+ #else
+-extern void *__memcpy(void *to, const void *from, size_t len);
+-#define memcpy(dst,src,len) \
+- ({ size_t __len = (len); \
+- void *__ret; \
+- if (__builtin_constant_p(len) && __len >= 64) \
+- __ret = __memcpy((dst),(src),__len); \
+- else \
+- __ret = __builtin_memcpy((dst),(src),__len); \
+- __ret; })
++extern void *__memcpy(void *to, const void *from, size_t len);
++#define memcpy(dst, src, len) \
++({ \
++ size_t __len = (len); \
++ void *__ret; \
++ if (__builtin_constant_p(len) && __len >= 64) \
++ __ret = __memcpy((dst), (src), __len); \
++ else \
++ __ret = __builtin_memcpy((dst), (src), __len); \
++ __ret; \
++})
+ #endif
+
+ #define __HAVE_ARCH_MEMSET
+ void *memset(void *s, int c, size_t n);
+
+ #define __HAVE_ARCH_MEMMOVE
+-void * memmove(void * dest,const void *src,size_t count);
++void *memmove(void *dest, const void *src, size_t count);
+
+-int memcmp(const void * cs,const void * ct,size_t count);
+-size_t strlen(const char * s);
+-char *strcpy(char * dest,const char *src);
+-char *strcat(char * dest, const char * src);
+-int strcmp(const char * cs,const char * ct);
++int memcmp(const void *cs, const void *ct, size_t count);
++size_t strlen(const char *s);
++char *strcpy(char *dest, const char *src);
++char *strcat(char *dest, const char *src);
++int strcmp(const char *cs, const char *ct);
+
+ #endif /* __KERNEL__ */
+
+diff --git a/include/asm-x86/suspend_32.h b/include/asm-x86/suspend_32.h
+index 1bbda3a..24e1c08 100644
+--- a/include/asm-x86/suspend_32.h
++++ b/include/asm-x86/suspend_32.h
+@@ -10,7 +10,7 @@ static inline int arch_prepare_suspend(void) { return 0; }
+
+ /* image of the saved processor state */
+ struct saved_context {
+- u16 es, fs, gs, ss;
++ u16 es, fs, gs, ss;
+ unsigned long cr0, cr2, cr3, cr4;
+ struct desc_ptr gdt;
+ struct desc_ptr idt;
+@@ -32,11 +32,11 @@ extern unsigned long saved_edi;
+ static inline void acpi_save_register_state(unsigned long return_point)
+ {
+ saved_eip = return_point;
+- asm volatile ("movl %%esp,%0" : "=m" (saved_esp));
+- asm volatile ("movl %%ebp,%0" : "=m" (saved_ebp));
+- asm volatile ("movl %%ebx,%0" : "=m" (saved_ebx));
+- asm volatile ("movl %%edi,%0" : "=m" (saved_edi));
+- asm volatile ("movl %%esi,%0" : "=m" (saved_esi));
++ asm volatile("movl %%esp,%0" : "=m" (saved_esp));
++ asm volatile("movl %%ebp,%0" : "=m" (saved_ebp));
++ asm volatile("movl %%ebx,%0" : "=m" (saved_ebx));
++ asm volatile("movl %%edi,%0" : "=m" (saved_edi));
++ asm volatile("movl %%esi,%0" : "=m" (saved_esi));
+ }
+
+ #define acpi_restore_register_state() do {} while (0)
+diff --git a/include/asm-x86/suspend_64.h b/include/asm-x86/suspend_64.h
+index 2eb92cb..dc3262b 100644
+--- a/include/asm-x86/suspend_64.h
++++ b/include/asm-x86/suspend_64.h
+@@ -9,8 +9,7 @@
+ #include <asm/desc.h>
+ #include <asm/i387.h>
+
+-static inline int
+-arch_prepare_suspend(void)
++static inline int arch_prepare_suspend(void)
+ {
+ return 0;
+ }
+@@ -25,7 +24,7 @@ arch_prepare_suspend(void)
+ */
+ struct saved_context {
+ struct pt_regs regs;
+- u16 ds, es, fs, gs, ss;
++ u16 ds, es, fs, gs, ss;
+ unsigned long gs_base, gs_kernel_base, fs_base;
+ unsigned long cr0, cr2, cr3, cr4, cr8;
+ unsigned long efer;
+diff --git a/include/asm-x86/swiotlb.h b/include/asm-x86/swiotlb.h
+index f9c5895..f5d9e74 100644
+--- a/include/asm-x86/swiotlb.h
++++ b/include/asm-x86/swiotlb.h
+@@ -8,15 +8,15 @@
+ extern dma_addr_t swiotlb_map_single(struct device *hwdev, void *ptr,
+ size_t size, int dir);
+ extern void *swiotlb_alloc_coherent(struct device *hwdev, size_t size,
+- dma_addr_t *dma_handle, gfp_t flags);
++ dma_addr_t *dma_handle, gfp_t flags);
+ extern void swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr,
+- size_t size, int dir);
++ size_t size, int dir);
+ extern void swiotlb_sync_single_for_cpu(struct device *hwdev,
+- dma_addr_t dev_addr,
+- size_t size, int dir);
++ dma_addr_t dev_addr,
++ size_t size, int dir);
+ extern void swiotlb_sync_single_for_device(struct device *hwdev,
+- dma_addr_t dev_addr,
+- size_t size, int dir);
++ dma_addr_t dev_addr,
++ size_t size, int dir);
+ extern void swiotlb_sync_single_range_for_cpu(struct device *hwdev,
+ dma_addr_t dev_addr,
+ unsigned long offset,
+@@ -26,18 +26,18 @@ extern void swiotlb_sync_single_range_for_device(struct device *hwdev,
+ unsigned long offset,
+ size_t size, int dir);
+ extern void swiotlb_sync_sg_for_cpu(struct device *hwdev,
+- struct scatterlist *sg, int nelems,
+- int dir);
++ struct scatterlist *sg, int nelems,
++ int dir);
+ extern void swiotlb_sync_sg_for_device(struct device *hwdev,
+- struct scatterlist *sg, int nelems,
+- int dir);
++ struct scatterlist *sg, int nelems,
++ int dir);
+ extern int swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg,
+- int nents, int direction);
++ int nents, int direction);
+ extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg,
+- int nents, int direction);
++ int nents, int direction);
+ extern int swiotlb_dma_mapping_error(dma_addr_t dma_addr);
+-extern void swiotlb_free_coherent (struct device *hwdev, size_t size,
+- void *vaddr, dma_addr_t dma_handle);
++extern void swiotlb_free_coherent(struct device *hwdev, size_t size,
++ void *vaddr, dma_addr_t dma_handle);
+ extern int swiotlb_dma_supported(struct device *hwdev, u64 mask);
+ extern void swiotlb_init(void);
+
+diff --git a/include/asm-x86/sync_bitops.h b/include/asm-x86/sync_bitops.h
+index 6b775c9..b47a1d0 100644
+--- a/include/asm-x86/sync_bitops.h
++++ b/include/asm-x86/sync_bitops.h
+@@ -13,7 +13,7 @@
+ * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
+ */
+
+-#define ADDR (*(volatile long *) addr)
++#define ADDR (*(volatile long *)addr)
+
+ /**
+ * sync_set_bit - Atomically set a bit in memory
+@@ -26,12 +26,12 @@
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+-static inline void sync_set_bit(int nr, volatile unsigned long * addr)
++static inline void sync_set_bit(int nr, volatile unsigned long *addr)
+ {
+- __asm__ __volatile__("lock; btsl %1,%0"
+- :"+m" (ADDR)
+- :"Ir" (nr)
+- : "memory");
++ asm volatile("lock; btsl %1,%0"
++ : "+m" (ADDR)
++ : "Ir" (nr)
++ : "memory");
+ }
+
+ /**
+@@ -44,12 +44,12 @@ static inline void sync_set_bit(int nr, volatile unsigned long * addr)
+ * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
+ * in order to ensure changes are visible on other processors.
+ */
+-static inline void sync_clear_bit(int nr, volatile unsigned long * addr)
++static inline void sync_clear_bit(int nr, volatile unsigned long *addr)
+ {
+- __asm__ __volatile__("lock; btrl %1,%0"
+- :"+m" (ADDR)
+- :"Ir" (nr)
+- : "memory");
++ asm volatile("lock; btrl %1,%0"
++ : "+m" (ADDR)
++ : "Ir" (nr)
++ : "memory");
+ }
+
+ /**
+@@ -61,12 +61,12 @@ static inline void sync_clear_bit(int nr, volatile unsigned long * addr)
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+-static inline void sync_change_bit(int nr, volatile unsigned long * addr)
++static inline void sync_change_bit(int nr, volatile unsigned long *addr)
+ {
+- __asm__ __volatile__("lock; btcl %1,%0"
+- :"+m" (ADDR)
+- :"Ir" (nr)
+- : "memory");
++ asm volatile("lock; btcl %1,%0"
++ : "+m" (ADDR)
++ : "Ir" (nr)
++ : "memory");
+ }
+
+ /**
+@@ -77,13 +77,13 @@ static inline void sync_change_bit(int nr, volatile unsigned long * addr)
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+-static inline int sync_test_and_set_bit(int nr, volatile unsigned long * addr)
++static inline int sync_test_and_set_bit(int nr, volatile unsigned long *addr)
+ {
+ int oldbit;
+
+- __asm__ __volatile__("lock; btsl %2,%1\n\tsbbl %0,%0"
+- :"=r" (oldbit),"+m" (ADDR)
+- :"Ir" (nr) : "memory");
++ asm volatile("lock; btsl %2,%1\n\tsbbl %0,%0"
++ : "=r" (oldbit), "+m" (ADDR)
++ : "Ir" (nr) : "memory");
+ return oldbit;
+ }
+
+@@ -95,13 +95,13 @@ static inline int sync_test_and_set_bit(int nr, volatile unsigned long * addr)
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+-static inline int sync_test_and_clear_bit(int nr, volatile unsigned long * addr)
++static inline int sync_test_and_clear_bit(int nr, volatile unsigned long *addr)
+ {
+ int oldbit;
+
+- __asm__ __volatile__("lock; btrl %2,%1\n\tsbbl %0,%0"
+- :"=r" (oldbit),"+m" (ADDR)
+- :"Ir" (nr) : "memory");
++ asm volatile("lock; btrl %2,%1\n\tsbbl %0,%0"
++ : "=r" (oldbit), "+m" (ADDR)
++ : "Ir" (nr) : "memory");
+ return oldbit;
+ }
+
+@@ -113,36 +113,17 @@ static inline int sync_test_and_clear_bit(int nr, volatile unsigned long * addr)
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+-static inline int sync_test_and_change_bit(int nr, volatile unsigned long* addr)
++static inline int sync_test_and_change_bit(int nr, volatile unsigned long *addr)
+ {
+ int oldbit;
+
+- __asm__ __volatile__("lock; btcl %2,%1\n\tsbbl %0,%0"
+- :"=r" (oldbit),"+m" (ADDR)
+- :"Ir" (nr) : "memory");
++ asm volatile("lock; btcl %2,%1\n\tsbbl %0,%0"
++ : "=r" (oldbit), "+m" (ADDR)
++ : "Ir" (nr) : "memory");
+ return oldbit;
+ }
+
+-static __always_inline int sync_constant_test_bit(int nr, const volatile unsigned long *addr)
+-{
+- return ((1UL << (nr & 31)) &
+- (((const volatile unsigned int *)addr)[nr >> 5])) != 0;
+-}
+-
+-static inline int sync_var_test_bit(int nr, const volatile unsigned long * addr)
+-{
+- int oldbit;
+-
+- __asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0"
+- :"=r" (oldbit)
+- :"m" (ADDR),"Ir" (nr));
+- return oldbit;
+-}
+-
+-#define sync_test_bit(nr,addr) \
+- (__builtin_constant_p(nr) ? \
+- sync_constant_test_bit((nr),(addr)) : \
+- sync_var_test_bit((nr),(addr)))
++#define sync_test_bit(nr, addr) test_bit(nr, addr)
+
+ #undef ADDR
+
+diff --git a/include/asm-x86/system.h b/include/asm-x86/system.h
+index 9cff02f..a2f04cd 100644
+--- a/include/asm-x86/system.h
++++ b/include/asm-x86/system.h
+@@ -27,22 +27,44 @@ struct task_struct *__switch_to(struct task_struct *prev,
+ * Saving eflags is important. It switches not only IOPL between tasks,
+ * it also protects other tasks from NT leaking through sysenter etc.
+ */
+-#define switch_to(prev, next, last) do { \
+- unsigned long esi, edi; \
+- asm volatile("pushfl\n\t" /* Save flags */ \
+- "pushl %%ebp\n\t" \
+- "movl %%esp,%0\n\t" /* save ESP */ \
+- "movl %5,%%esp\n\t" /* restore ESP */ \
+- "movl $1f,%1\n\t" /* save EIP */ \
+- "pushl %6\n\t" /* restore EIP */ \
+- "jmp __switch_to\n" \
++#define switch_to(prev, next, last) \
++do { \
++ /* \
++ * Context-switching clobbers all registers, so we clobber \
++ * them explicitly, via unused output variables. \
++ * (EAX and EBP is not listed because EBP is saved/restored \
++ * explicitly for wchan access and EAX is the return value of \
++ * __switch_to()) \
++ */ \
++ unsigned long ebx, ecx, edx, esi, edi; \
++ \
++ asm volatile("pushfl\n\t" /* save flags */ \
++ "pushl %%ebp\n\t" /* save EBP */ \
++ "movl %%esp,%[prev_sp]\n\t" /* save ESP */ \
++ "movl %[next_sp],%%esp\n\t" /* restore ESP */ \
++ "movl $1f,%[prev_ip]\n\t" /* save EIP */ \
++ "pushl %[next_ip]\n\t" /* restore EIP */ \
++ "jmp __switch_to\n" /* regparm call */ \
+ "1:\t" \
+- "popl %%ebp\n\t" \
+- "popfl" \
+- :"=m" (prev->thread.sp), "=m" (prev->thread.ip), \
+- "=a" (last), "=S" (esi), "=D" (edi) \
+- :"m" (next->thread.sp), "m" (next->thread.ip), \
+- "2" (prev), "d" (next)); \
++ "popl %%ebp\n\t" /* restore EBP */ \
++ "popfl\n" /* restore flags */ \
++ \
++ /* output parameters */ \
++ : [prev_sp] "=m" (prev->thread.sp), \
++ [prev_ip] "=m" (prev->thread.ip), \
++ "=a" (last), \
++ \
++ /* clobbered output registers: */ \
++ "=b" (ebx), "=c" (ecx), "=d" (edx), \
++ "=S" (esi), "=D" (edi) \
++ \
++ /* input parameters: */ \
++ : [next_sp] "m" (next->thread.sp), \
++ [next_ip] "m" (next->thread.ip), \
++ \
++ /* regparm parameters for __switch_to(): */ \
++ [prev] "a" (prev), \
++ [next] "d" (next)); \
+ } while (0)
+
+ /*
+@@ -122,35 +144,34 @@ extern void load_gs_index(unsigned);
+ */
+ #define loadsegment(seg, value) \
+ asm volatile("\n" \
+- "1:\t" \
+- "movl %k0,%%" #seg "\n" \
+- "2:\n" \
+- ".section .fixup,\"ax\"\n" \
+- "3:\t" \
+- "movl %k1, %%" #seg "\n\t" \
+- "jmp 2b\n" \
+- ".previous\n" \
+- _ASM_EXTABLE(1b,3b) \
+- : :"r" (value), "r" (0))
++ "1:\t" \
++ "movl %k0,%%" #seg "\n" \
++ "2:\n" \
++ ".section .fixup,\"ax\"\n" \
++ "3:\t" \
++ "movl %k1, %%" #seg "\n\t" \
++ "jmp 2b\n" \
++ ".previous\n" \
++ _ASM_EXTABLE(1b,3b) \
++ : :"r" (value), "r" (0))
+
+
+ /*
+ * Save a segment register away
+ */
+-#define savesegment(seg, value) \
++#define savesegment(seg, value) \
+ asm volatile("mov %%" #seg ",%0":"=rm" (value))
+
+ static inline unsigned long get_limit(unsigned long segment)
+ {
+ unsigned long __limit;
+- __asm__("lsll %1,%0"
+- :"=r" (__limit):"r" (segment));
+- return __limit+1;
++ asm("lsll %1,%0" : "=r" (__limit) : "r" (segment));
++ return __limit + 1;
+ }
+
+ static inline void native_clts(void)
+ {
+- asm volatile ("clts");
++ asm volatile("clts");
+ }
+
+ /*
+@@ -165,43 +186,43 @@ static unsigned long __force_order;
+ static inline unsigned long native_read_cr0(void)
+ {
+ unsigned long val;
+- asm volatile("mov %%cr0,%0\n\t" :"=r" (val), "=m" (__force_order));
++ asm volatile("mov %%cr0,%0\n\t" : "=r" (val), "=m" (__force_order));
+ return val;
+ }
+
+ static inline void native_write_cr0(unsigned long val)
+ {
+- asm volatile("mov %0,%%cr0": :"r" (val), "m" (__force_order));
++ asm volatile("mov %0,%%cr0": : "r" (val), "m" (__force_order));
+ }
+
+ static inline unsigned long native_read_cr2(void)
+ {
+ unsigned long val;
+- asm volatile("mov %%cr2,%0\n\t" :"=r" (val), "=m" (__force_order));
++ asm volatile("mov %%cr2,%0\n\t" : "=r" (val), "=m" (__force_order));
+ return val;
+ }
+
+ static inline void native_write_cr2(unsigned long val)
+ {
+- asm volatile("mov %0,%%cr2": :"r" (val), "m" (__force_order));
++ asm volatile("mov %0,%%cr2": : "r" (val), "m" (__force_order));
+ }
+
+ static inline unsigned long native_read_cr3(void)
+ {
+ unsigned long val;
+- asm volatile("mov %%cr3,%0\n\t" :"=r" (val), "=m" (__force_order));
++ asm volatile("mov %%cr3,%0\n\t" : "=r" (val), "=m" (__force_order));
+ return val;
+ }
+
+ static inline void native_write_cr3(unsigned long val)
+ {
+- asm volatile("mov %0,%%cr3": :"r" (val), "m" (__force_order));
++ asm volatile("mov %0,%%cr3": : "r" (val), "m" (__force_order));
+ }
+
+ static inline unsigned long native_read_cr4(void)
+ {
+ unsigned long val;
+- asm volatile("mov %%cr4,%0\n\t" :"=r" (val), "=m" (__force_order));
++ asm volatile("mov %%cr4,%0\n\t" : "=r" (val), "=m" (__force_order));
+ return val;
+ }
+
+@@ -213,7 +234,7 @@ static inline unsigned long native_read_cr4_safe(void)
+ #ifdef CONFIG_X86_32
+ asm volatile("1: mov %%cr4, %0\n"
+ "2:\n"
+- _ASM_EXTABLE(1b,2b)
++ _ASM_EXTABLE(1b, 2b)
+ : "=r" (val), "=m" (__force_order) : "0" (0));
+ #else
+ val = native_read_cr4();
+@@ -223,7 +244,7 @@ static inline unsigned long native_read_cr4_safe(void)
+
+ static inline void native_write_cr4(unsigned long val)
+ {
+- asm volatile("mov %0,%%cr4": :"r" (val), "m" (__force_order));
++ asm volatile("mov %0,%%cr4": : "r" (val), "m" (__force_order));
+ }
+
+ #ifdef CONFIG_X86_64
+@@ -244,6 +265,7 @@ static inline void native_wbinvd(void)
+ {
+ asm volatile("wbinvd": : :"memory");
+ }
++
+ #ifdef CONFIG_PARAVIRT
+ #include <asm/paravirt.h>
+ #else
+@@ -276,7 +298,7 @@ static inline void clflush(volatile void *__p)
+ asm volatile("clflush %0" : "+m" (*(volatile char __force *)__p));
+ }
+
+-#define nop() __asm__ __volatile__ ("nop")
++#define nop() asm volatile ("nop")
+
+ void disable_hlt(void);
+ void enable_hlt(void);
+@@ -296,16 +318,7 @@ void default_idle(void);
+ */
+ #ifdef CONFIG_X86_32
+ /*
+- * For now, "wmb()" doesn't actually do anything, as all
+- * Intel CPU's follow what Intel calls a *Processor Order*,
+- * in which all writes are seen in the program order even
+- * outside the CPU.
+- *
+- * I expect future Intel CPU's to have a weaker ordering,
+- * but I'd also expect them to finally get their act together
+- * and add some real memory barriers if so.
+- *
+- * Some non intel clones support out of order store. wmb() ceases to be a
++ * Some non-Intel clones support out of order store. wmb() ceases to be a
+ * nop for these.
+ */
+ #define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
+@@ -384,7 +397,7 @@ void default_idle(void);
+ # define smp_wmb() barrier()
+ #endif
+ #define smp_read_barrier_depends() read_barrier_depends()
+-#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
++#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
+ #else
+ #define smp_mb() barrier()
+ #define smp_rmb() barrier()
+diff --git a/include/asm-x86/tce.h b/include/asm-x86/tce.h
+index cd955d3..b1a4ea0 100644
+--- a/include/asm-x86/tce.h
++++ b/include/asm-x86/tce.h
+@@ -39,7 +39,7 @@ struct iommu_table;
+ #define TCE_RPN_MASK 0x0000fffffffff000ULL
+
+ extern void tce_build(struct iommu_table *tbl, unsigned long index,
+- unsigned int npages, unsigned long uaddr, int direction);
++ unsigned int npages, unsigned long uaddr, int direction);
+ extern void tce_free(struct iommu_table *tbl, long index, unsigned int npages);
+ extern void * __init alloc_tce_table(void);
+ extern void __init free_tce_table(void *tbl);
+diff --git a/include/asm-x86/thread_info.h b/include/asm-x86/thread_info.h
+index d5fd12f..77244f1 100644
+--- a/include/asm-x86/thread_info.h
++++ b/include/asm-x86/thread_info.h
+@@ -1,5 +1,14 @@
++#ifndef _ASM_X86_THREAD_INFO_H
+ #ifdef CONFIG_X86_32
+ # include "thread_info_32.h"
+ #else
+ # include "thread_info_64.h"
+ #endif
++
++#ifndef __ASSEMBLY__
++extern void arch_task_cache_init(void);
++extern void free_thread_info(struct thread_info *ti);
++extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
++#define arch_task_cache_init arch_task_cache_init
++#endif
++#endif /* _ASM_X86_THREAD_INFO_H */
+diff --git a/include/asm-x86/thread_info_32.h b/include/asm-x86/thread_info_32.h
+index 5bd5082..5318599 100644
+--- a/include/asm-x86/thread_info_32.h
++++ b/include/asm-x86/thread_info_32.h
+@@ -20,7 +20,8 @@
+ * low level task data that entry.S needs immediate access to
+ * - this struct should fit entirely inside of one cache line
+ * - this struct shares the supervisor stack pages
+- * - if the contents of this structure are changed, the assembly constants must also be changed
++ * - if the contents of this structure are changed,
++ * the assembly constants must also be changed
+ */
+ #ifndef __ASSEMBLY__
+
+@@ -30,18 +31,16 @@ struct thread_info {
+ unsigned long flags; /* low level flags */
+ unsigned long status; /* thread-synchronous flags */
+ __u32 cpu; /* current CPU */
+- int preempt_count; /* 0 => preemptable, <0 => BUG */
+-
+-
++ int preempt_count; /* 0 => preemptable,
++ <0 => BUG */
+ mm_segment_t addr_limit; /* thread address space:
+- 0-0xBFFFFFFF for user-thead
+- 0-0xFFFFFFFF for kernel-thread
++ 0-0xBFFFFFFF user-thread
++ 0-0xFFFFFFFF kernel-thread
+ */
+ void *sysenter_return;
+ struct restart_block restart_block;
+-
+- unsigned long previous_esp; /* ESP of the previous stack in case
+- of nested (IRQ) stacks
++ unsigned long previous_esp; /* ESP of the previous stack in
++ case of nested (IRQ) stacks
+ */
+ __u8 supervisor_stack[0];
+ };
+@@ -90,24 +89,23 @@ register unsigned long current_stack_pointer asm("esp") __used;
+ /* how to get the thread information struct from C */
+ static inline struct thread_info *current_thread_info(void)
+ {
+- return (struct thread_info *)(current_stack_pointer & ~(THREAD_SIZE - 1));
++ return (struct thread_info *)
++ (current_stack_pointer & ~(THREAD_SIZE - 1));
+ }
+
+ /* thread information allocation */
+ #ifdef CONFIG_DEBUG_STACK_USAGE
+-#define alloc_thread_info(tsk) ((struct thread_info *) \
+- __get_free_pages(GFP_KERNEL| __GFP_ZERO, get_order(THREAD_SIZE)))
++#define alloc_thread_info(tsk) ((struct thread_info *) \
++ __get_free_pages(GFP_KERNEL | __GFP_ZERO, get_order(THREAD_SIZE)))
+ #else
+-#define alloc_thread_info(tsk) ((struct thread_info *) \
++#define alloc_thread_info(tsk) ((struct thread_info *) \
+ __get_free_pages(GFP_KERNEL, get_order(THREAD_SIZE)))
+ #endif
+
+-#define free_thread_info(info) free_pages((unsigned long)(info), get_order(THREAD_SIZE))
+-
+ #else /* !__ASSEMBLY__ */
+
+ /* how to get the thread information struct from ASM */
+-#define GET_THREAD_INFO(reg) \
++#define GET_THREAD_INFO(reg) \
+ movl $-THREAD_SIZE, reg; \
+ andl %esp, reg
+
+@@ -119,14 +117,16 @@ static inline struct thread_info *current_thread_info(void)
+
+ /*
+ * thread information flags
+- * - these are process state flags that various assembly files may need to access
++ * - these are process state flags that various
++ * assembly files may need to access
+ * - pending work-to-be-done flags are in LSW
+ * - other flags in MSW
+ */
+ #define TIF_SYSCALL_TRACE 0 /* syscall trace active */
+ #define TIF_SIGPENDING 1 /* signal pending */
+ #define TIF_NEED_RESCHED 2 /* rescheduling necessary */
+-#define TIF_SINGLESTEP 3 /* restore singlestep on return to user mode */
++#define TIF_SINGLESTEP 3 /* restore singlestep on return to
++ user mode */
+ #define TIF_IRET 4 /* return with iret */
+ #define TIF_SYSCALL_EMU 5 /* syscall emulation active */
+ #define TIF_SYSCALL_AUDIT 6 /* syscall auditing active */
+@@ -143,36 +143,36 @@ static inline struct thread_info *current_thread_info(void)
+ #define TIF_DS_AREA_MSR 23 /* uses thread_struct.ds_area_msr */
+ #define TIF_BTS_TRACE_TS 24 /* record scheduling event timestamps */
+
+-#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
+-#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
+-#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
+-#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
+-#define _TIF_IRET (1<<TIF_IRET)
+-#define _TIF_SYSCALL_EMU (1<<TIF_SYSCALL_EMU)
+-#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
+-#define _TIF_SECCOMP (1<<TIF_SECCOMP)
+-#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
+-#define _TIF_HRTICK_RESCHED (1<<TIF_HRTICK_RESCHED)
+-#define _TIF_DEBUG (1<<TIF_DEBUG)
+-#define _TIF_IO_BITMAP (1<<TIF_IO_BITMAP)
+-#define _TIF_FREEZE (1<<TIF_FREEZE)
+-#define _TIF_NOTSC (1<<TIF_NOTSC)
+-#define _TIF_FORCED_TF (1<<TIF_FORCED_TF)
+-#define _TIF_DEBUGCTLMSR (1<<TIF_DEBUGCTLMSR)
+-#define _TIF_DS_AREA_MSR (1<<TIF_DS_AREA_MSR)
+-#define _TIF_BTS_TRACE_TS (1<<TIF_BTS_TRACE_TS)
++#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
++#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
++#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
++#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
++#define _TIF_IRET (1 << TIF_IRET)
++#define _TIF_SYSCALL_EMU (1 << TIF_SYSCALL_EMU)
++#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
++#define _TIF_SECCOMP (1 << TIF_SECCOMP)
++#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
++#define _TIF_HRTICK_RESCHED (1 << TIF_HRTICK_RESCHED)
++#define _TIF_DEBUG (1 << TIF_DEBUG)
++#define _TIF_IO_BITMAP (1 << TIF_IO_BITMAP)
++#define _TIF_FREEZE (1 << TIF_FREEZE)
++#define _TIF_NOTSC (1 << TIF_NOTSC)
++#define _TIF_FORCED_TF (1 << TIF_FORCED_TF)
++#define _TIF_DEBUGCTLMSR (1 << TIF_DEBUGCTLMSR)
++#define _TIF_DS_AREA_MSR (1 << TIF_DS_AREA_MSR)
++#define _TIF_BTS_TRACE_TS (1 << TIF_BTS_TRACE_TS)
+
+ /* work to do on interrupt/exception return */
+-#define _TIF_WORK_MASK \
+- (0x0000FFFF & ~(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
+- _TIF_SECCOMP | _TIF_SYSCALL_EMU))
++#define _TIF_WORK_MASK \
++ (0x0000FFFF & ~(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
++ _TIF_SECCOMP | _TIF_SYSCALL_EMU))
+ /* work to do on any return to u-space */
+ #define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP)
+
+ /* flags to check in __switch_to() */
+-#define _TIF_WORK_CTXSW \
+- (_TIF_IO_BITMAP | _TIF_NOTSC | _TIF_DEBUGCTLMSR | \
+- _TIF_DS_AREA_MSR | _TIF_BTS_TRACE_TS)
++#define _TIF_WORK_CTXSW \
++ (_TIF_IO_BITMAP | _TIF_NOTSC | _TIF_DEBUGCTLMSR | \
++ _TIF_DS_AREA_MSR | _TIF_BTS_TRACE_TS)
+ #define _TIF_WORK_CTXSW_PREV _TIF_WORK_CTXSW
+ #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW | _TIF_DEBUG)
+
+@@ -184,8 +184,10 @@ static inline struct thread_info *current_thread_info(void)
+ * ever touches our thread-synchronous status, so we don't
+ * have to worry about atomic accesses.
+ */
+-#define TS_USEDFPU 0x0001 /* FPU was used by this task this quantum (SMP) */
+-#define TS_POLLING 0x0002 /* True if in idle loop and not sleeping */
++#define TS_USEDFPU 0x0001 /* FPU was used by this task
++ this quantum (SMP) */
++#define TS_POLLING 0x0002 /* True if in idle loop
++ and not sleeping */
+
+ #define tsk_is_polling(t) (task_thread_info(t)->status & TS_POLLING)
+
+diff --git a/include/asm-x86/thread_info_64.h b/include/asm-x86/thread_info_64.h
+index 6c9b214..ed664e8 100644
+--- a/include/asm-x86/thread_info_64.h
++++ b/include/asm-x86/thread_info_64.h
+@@ -29,9 +29,9 @@ struct thread_info {
+ __u32 flags; /* low level flags */
+ __u32 status; /* thread synchronous flags */
+ __u32 cpu; /* current CPU */
+- int preempt_count; /* 0 => preemptable, <0 => BUG */
+-
+- mm_segment_t addr_limit;
++ int preempt_count; /* 0 => preemptable,
++ <0 => BUG */
++ mm_segment_t addr_limit;
+ struct restart_block restart_block;
+ #ifdef CONFIG_IA32_EMULATION
+ void __user *sysenter_return;
+@@ -61,17 +61,17 @@ struct thread_info {
+ #define init_stack (init_thread_union.stack)
+
+ static inline struct thread_info *current_thread_info(void)
+-{
++{
+ struct thread_info *ti;
+ ti = (void *)(read_pda(kernelstack) + PDA_STACKOFFSET - THREAD_SIZE);
+- return ti;
++ return ti;
+ }
+
+ /* do not use in interrupt context */
+ static inline struct thread_info *stack_thread_info(void)
+ {
+ struct thread_info *ti;
+- __asm__("andq %%rsp,%0; ":"=r" (ti) : "0" (~(THREAD_SIZE - 1)));
++ asm("andq %%rsp,%0; " : "=r" (ti) : "0" (~(THREAD_SIZE - 1)));
+ return ti;
+ }
+
+@@ -82,10 +82,8 @@ static inline struct thread_info *stack_thread_info(void)
+ #define THREAD_FLAGS GFP_KERNEL
+ #endif
+
+-#define alloc_thread_info(tsk) \
+- ((struct thread_info *) __get_free_pages(THREAD_FLAGS, THREAD_ORDER))
+-
+-#define free_thread_info(ti) free_pages((unsigned long) (ti), THREAD_ORDER)
++#define alloc_thread_info(tsk) \
++ ((struct thread_info *)__get_free_pages(THREAD_FLAGS, THREAD_ORDER))
+
+ #else /* !__ASSEMBLY__ */
+
+@@ -98,7 +96,8 @@ static inline struct thread_info *stack_thread_info(void)
+
+ /*
+ * thread information flags
+- * - these are process state flags that various assembly files may need to access
++ * - these are process state flags that various assembly files
++ * may need to access
+ * - pending work-to-be-done flags are in LSW
+ * - other flags in MSW
+ * Warning: layout of LSW is hardcoded in entry.S
+@@ -114,7 +113,7 @@ static inline struct thread_info *stack_thread_info(void)
+ #define TIF_MCE_NOTIFY 10 /* notify userspace of an MCE */
+ #define TIF_HRTICK_RESCHED 11 /* reprogram hrtick timer */
+ /* 16 free */
+-#define TIF_IA32 17 /* 32bit process */
++#define TIF_IA32 17 /* 32bit process */
+ #define TIF_FORK 18 /* ret_from_fork */
+ #define TIF_ABI_PENDING 19
+ #define TIF_MEMDIE 20
+@@ -125,40 +124,43 @@ static inline struct thread_info *stack_thread_info(void)
+ #define TIF_DEBUGCTLMSR 25 /* uses thread_struct.debugctlmsr */
+ #define TIF_DS_AREA_MSR 26 /* uses thread_struct.ds_area_msr */
+ #define TIF_BTS_TRACE_TS 27 /* record scheduling event timestamps */
+-
+-#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
+-#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
+-#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
+-#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
+-#define _TIF_IRET (1<<TIF_IRET)
+-#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
+-#define _TIF_SECCOMP (1<<TIF_SECCOMP)
+-#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
+-#define _TIF_MCE_NOTIFY (1<<TIF_MCE_NOTIFY)
+-#define _TIF_HRTICK_RESCHED (1<<TIF_HRTICK_RESCHED)
+-#define _TIF_IA32 (1<<TIF_IA32)
+-#define _TIF_FORK (1<<TIF_FORK)
+-#define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING)
+-#define _TIF_DEBUG (1<<TIF_DEBUG)
+-#define _TIF_IO_BITMAP (1<<TIF_IO_BITMAP)
+-#define _TIF_FREEZE (1<<TIF_FREEZE)
+-#define _TIF_FORCED_TF (1<<TIF_FORCED_TF)
+-#define _TIF_DEBUGCTLMSR (1<<TIF_DEBUGCTLMSR)
+-#define _TIF_DS_AREA_MSR (1<<TIF_DS_AREA_MSR)
+-#define _TIF_BTS_TRACE_TS (1<<TIF_BTS_TRACE_TS)
++#define TIF_NOTSC 28 /* TSC is not accessible in userland */
++
++#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
++#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
++#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
++#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
++#define _TIF_IRET (1 << TIF_IRET)
++#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
++#define _TIF_SECCOMP (1 << TIF_SECCOMP)
++#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
++#define _TIF_MCE_NOTIFY (1 << TIF_MCE_NOTIFY)
++#define _TIF_HRTICK_RESCHED (1 << TIF_HRTICK_RESCHED)
++#define _TIF_IA32 (1 << TIF_IA32)
++#define _TIF_FORK (1 << TIF_FORK)
++#define _TIF_ABI_PENDING (1 << TIF_ABI_PENDING)
++#define _TIF_DEBUG (1 << TIF_DEBUG)
++#define _TIF_IO_BITMAP (1 << TIF_IO_BITMAP)
++#define _TIF_FREEZE (1 << TIF_FREEZE)
++#define _TIF_FORCED_TF (1 << TIF_FORCED_TF)
++#define _TIF_DEBUGCTLMSR (1 << TIF_DEBUGCTLMSR)
++#define _TIF_DS_AREA_MSR (1 << TIF_DS_AREA_MSR)
++#define _TIF_BTS_TRACE_TS (1 << TIF_BTS_TRACE_TS)
++#define _TIF_NOTSC (1 << TIF_NOTSC)
+
+ /* work to do on interrupt/exception return */
+-#define _TIF_WORK_MASK \
+- (0x0000FFFF & ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP|_TIF_SECCOMP))
++#define _TIF_WORK_MASK \
++ (0x0000FFFF & \
++ ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP|_TIF_SECCOMP))
+ /* work to do on any return to user space */
+ #define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP)
+
+-#define _TIF_DO_NOTIFY_MASK \
++#define _TIF_DO_NOTIFY_MASK \
+ (_TIF_SIGPENDING|_TIF_SINGLESTEP|_TIF_MCE_NOTIFY|_TIF_HRTICK_RESCHED)
+
+ /* flags to check in __switch_to() */
+-#define _TIF_WORK_CTXSW \
+- (_TIF_IO_BITMAP|_TIF_DEBUGCTLMSR|_TIF_DS_AREA_MSR|_TIF_BTS_TRACE_TS)
++#define _TIF_WORK_CTXSW \
++ (_TIF_IO_BITMAP|_TIF_DEBUGCTLMSR|_TIF_DS_AREA_MSR|_TIF_BTS_TRACE_TS|_TIF_NOTSC)
+ #define _TIF_WORK_CTXSW_PREV _TIF_WORK_CTXSW
+ #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW|_TIF_DEBUG)
+
+@@ -171,9 +173,11 @@ static inline struct thread_info *stack_thread_info(void)
+ * ever touches our thread-synchronous status, so we don't
+ * have to worry about atomic accesses.
+ */
+-#define TS_USEDFPU 0x0001 /* FPU was used by this task this quantum (SMP) */
++#define TS_USEDFPU 0x0001 /* FPU was used by this task
++ this quantum (SMP) */
+ #define TS_COMPAT 0x0002 /* 32bit syscall active */
+-#define TS_POLLING 0x0004 /* true if in idle loop and not sleeping */
++#define TS_POLLING 0x0004 /* true if in idle loop
++ and not sleeping */
+
+ #define tsk_is_polling(t) (task_thread_info(t)->status & TS_POLLING)
+
+diff --git a/include/asm-x86/tlbflush.h b/include/asm-x86/tlbflush.h
+index 3998709..0c0674d 100644
+--- a/include/asm-x86/tlbflush.h
++++ b/include/asm-x86/tlbflush.h
+@@ -32,7 +32,7 @@ static inline void __native_flush_tlb_global(void)
+
+ static inline void __native_flush_tlb_single(unsigned long addr)
+ {
+- __asm__ __volatile__("invlpg (%0)" ::"r" (addr) : "memory");
++ asm volatile("invlpg (%0)" ::"r" (addr) : "memory");
+ }
+
+ static inline void __flush_tlb_all(void)
+@@ -134,8 +134,7 @@ void native_flush_tlb_others(const cpumask_t *cpumask, struct mm_struct *mm,
+ #define TLBSTATE_LAZY 2
+
+ #ifdef CONFIG_X86_32
+-struct tlb_state
+-{
++struct tlb_state {
+ struct mm_struct *active_mm;
+ int state;
+ char __cacheline_padding[L1_CACHE_BYTES-8];
+diff --git a/include/asm-x86/topology.h b/include/asm-x86/topology.h
+index 8af05a9..2207326 100644
+--- a/include/asm-x86/topology.h
++++ b/include/asm-x86/topology.h
+@@ -32,13 +32,18 @@
+ /* Mappings between logical cpu number and node number */
+ #ifdef CONFIG_X86_32
+ extern int cpu_to_node_map[];
+-
+ #else
++/* Returns the number of the current Node. */
++#define numa_node_id() (early_cpu_to_node(raw_smp_processor_id()))
++#endif
++
+ DECLARE_PER_CPU(int, x86_cpu_to_node_map);
++
++#ifdef CONFIG_SMP
+ extern int x86_cpu_to_node_map_init[];
+ extern void *x86_cpu_to_node_map_early_ptr;
+-/* Returns the number of the current Node. */
+-#define numa_node_id() (early_cpu_to_node(raw_smp_processor_id()))
++#else
++#define x86_cpu_to_node_map_early_ptr NULL
+ #endif
+
+ extern cpumask_t node_to_cpumask_map[];
+@@ -54,6 +59,8 @@ static inline int cpu_to_node(int cpu)
+ }
+
+ #else /* CONFIG_X86_64 */
++
++#ifdef CONFIG_SMP
+ static inline int early_cpu_to_node(int cpu)
+ {
+ int *cpu_to_node_map = x86_cpu_to_node_map_early_ptr;
+@@ -65,22 +72,33 @@ static inline int early_cpu_to_node(int cpu)
+ else
+ return NUMA_NO_NODE;
+ }
++#else
++#define early_cpu_to_node(cpu) cpu_to_node(cpu)
++#endif
+
+ static inline int cpu_to_node(int cpu)
+ {
+ #ifdef CONFIG_DEBUG_PER_CPU_MAPS
+ if (x86_cpu_to_node_map_early_ptr) {
+ printk("KERN_NOTICE cpu_to_node(%d): usage too early!\n",
+- (int)cpu);
++ (int)cpu);
+ dump_stack();
+ return ((int *)x86_cpu_to_node_map_early_ptr)[cpu];
+ }
+ #endif
+- if (per_cpu_offset(cpu))
+- return per_cpu(x86_cpu_to_node_map, cpu);
+- else
+- return NUMA_NO_NODE;
++ return per_cpu(x86_cpu_to_node_map, cpu);
+ }
++
++#ifdef CONFIG_NUMA
++
++/* Returns a pointer to the cpumask of CPUs on Node 'node'. */
++#define node_to_cpumask_ptr(v, node) \
++ cpumask_t *v = &(node_to_cpumask_map[node])
++
++#define node_to_cpumask_ptr_next(v, node) \
++ v = &(node_to_cpumask_map[node])
++#endif
++
+ #endif /* CONFIG_X86_64 */
+
+ /*
+@@ -129,17 +147,13 @@ extern unsigned long node_remap_size[];
+
+ # define SD_CACHE_NICE_TRIES 2
+ # define SD_IDLE_IDX 2
+-# define SD_NEWIDLE_IDX 0
++# define SD_NEWIDLE_IDX 2
+ # define SD_FORKEXEC_IDX 1
+
+ #endif
+
+ /* sched_domains SD_NODE_INIT for NUMAQ machines */
+ #define SD_NODE_INIT (struct sched_domain) { \
+- .span = CPU_MASK_NONE, \
+- .parent = NULL, \
+- .child = NULL, \
+- .groups = NULL, \
+ .min_interval = 8, \
+ .max_interval = 32, \
+ .busy_factor = 32, \
+@@ -157,7 +171,6 @@ extern unsigned long node_remap_size[];
+ | SD_WAKE_BALANCE, \
+ .last_balance = jiffies, \
+ .balance_interval = 1, \
+- .nr_balance_failed = 0, \
+ }
+
+ #ifdef CONFIG_X86_64_ACPI_NUMA
+@@ -167,10 +180,10 @@ extern int __node_distance(int, int);
+
+ #else /* CONFIG_NUMA */
+
+-#include <asm-generic/topology.h>
+-
+ #endif
+
++#include <asm-generic/topology.h>
++
+ extern cpumask_t cpu_coregroup_map(int cpu);
+
+ #ifdef ENABLE_TOPO_DEFINES
+diff --git a/include/asm-x86/trampoline.h b/include/asm-x86/trampoline.h
+new file mode 100644
+index 0000000..b156b08
+--- /dev/null
++++ b/include/asm-x86/trampoline.h
+@@ -0,0 +1,21 @@
++#ifndef __TRAMPOLINE_HEADER
++#define __TRAMPOLINE_HEADER
++
++#ifndef __ASSEMBLY__
++
++/*
++ * Trampoline 80x86 program as an array.
++ */
++extern const unsigned char trampoline_data [];
++extern const unsigned char trampoline_end [];
++extern unsigned char *trampoline_base;
++
++extern unsigned long init_rsp;
++extern unsigned long initial_code;
++
++#define TRAMPOLINE_BASE 0x6000
++extern unsigned long setup_trampoline(void);
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* __TRAMPOLINE_HEADER */
+diff --git a/include/asm-x86/tsc.h b/include/asm-x86/tsc.h
+index 7d3e27f..d2d8eb5 100644
+--- a/include/asm-x86/tsc.h
++++ b/include/asm-x86/tsc.h
+@@ -42,7 +42,7 @@ static inline cycles_t vget_cycles(void)
+ if (!cpu_has_tsc)
+ return 0;
+ #endif
+- return (cycles_t) __native_read_tsc();
++ return (cycles_t)__native_read_tsc();
+ }
+
+ extern void tsc_init(void);
+diff --git a/include/asm-x86/uaccess_32.h b/include/asm-x86/uaccess_32.h
+index fcc570e..8e7595c 100644
+--- a/include/asm-x86/uaccess_32.h
++++ b/include/asm-x86/uaccess_32.h
+@@ -32,7 +32,7 @@
+ #define get_fs() (current_thread_info()->addr_limit)
+ #define set_fs(x) (current_thread_info()->addr_limit = (x))
+
+-#define segment_eq(a,b) ((a).seg == (b).seg)
++#define segment_eq(a, b) ((a).seg == (b).seg)
+
+ /*
+ * movsl can be slow when source and dest are not both 8-byte aligned
+@@ -43,7 +43,9 @@ extern struct movsl_mask {
+ } ____cacheline_aligned_in_smp movsl_mask;
+ #endif
+
+-#define __addr_ok(addr) ((unsigned long __force)(addr) < (current_thread_info()->addr_limit.seg))
++#define __addr_ok(addr) \
++ ((unsigned long __force)(addr) < \
++ (current_thread_info()->addr_limit.seg))
+
+ /*
+ * Test whether a block of memory is a valid user space address.
+@@ -54,13 +56,16 @@ extern struct movsl_mask {
+ *
+ * This needs 33-bit arithmetic. We have a carry...
+ */
+-#define __range_ok(addr,size) ({ \
+- unsigned long flag,roksum; \
+- __chk_user_ptr(addr); \
+- asm("addl %3,%1 ; sbbl %0,%0; cmpl %1,%4; sbbl $0,%0" \
+- :"=&r" (flag), "=r" (roksum) \
+- :"1" (addr),"g" ((int)(size)),"rm" (current_thread_info()->addr_limit.seg)); \
+- flag; })
++#define __range_ok(addr, size) \
++({ \
++ unsigned long flag, roksum; \
++ __chk_user_ptr(addr); \
++ asm("addl %3,%1 ; sbbl %0,%0; cmpl %1,%4; sbbl $0,%0" \
++ :"=&r" (flag), "=r" (roksum) \
++ :"1" (addr), "g" ((int)(size)), \
++ "rm" (current_thread_info()->addr_limit.seg)); \
++ flag; \
++})
+
+ /**
+ * access_ok: - Checks if a user space pointer is valid
+@@ -81,7 +86,7 @@ extern struct movsl_mask {
+ * checks that the pointer is in the user space range - after calling
+ * this function, memory access functions may still return -EFAULT.
+ */
+-#define access_ok(type,addr,size) (likely(__range_ok(addr,size) == 0))
++#define access_ok(type, addr, size) (likely(__range_ok(addr, size) == 0))
+
+ /*
+ * The exception table consists of pairs of addresses: the first is the
+@@ -96,8 +101,7 @@ extern struct movsl_mask {
+ * on our cache or tlb entries.
+ */
+
+-struct exception_table_entry
+-{
++struct exception_table_entry {
+ unsigned long insn, fixup;
+ };
+
+@@ -122,13 +126,15 @@ extern void __get_user_1(void);
+ extern void __get_user_2(void);
+ extern void __get_user_4(void);
+
+-#define __get_user_x(size,ret,x,ptr) \
+- __asm__ __volatile__("call __get_user_" #size \
+- :"=a" (ret),"=d" (x) \
+- :"0" (ptr))
++#define __get_user_x(size, ret, x, ptr) \
++ asm volatile("call __get_user_" #size \
++ :"=a" (ret),"=d" (x) \
++ :"0" (ptr))
++
+
++/* Careful: we have to cast the result to the type of the pointer
++ * for sign reasons */
+
+-/* Careful: we have to cast the result to the type of the pointer for sign reasons */
+ /**
+ * get_user: - Get a simple variable from user space.
+ * @x: Variable to store result.
+@@ -146,15 +152,24 @@ extern void __get_user_4(void);
+ * Returns zero on success, or -EFAULT on error.
+ * On error, the variable @x is set to zero.
+ */
+-#define get_user(x,ptr) \
+-({ int __ret_gu; \
++#define get_user(x, ptr) \
++({ \
++ int __ret_gu; \
+ unsigned long __val_gu; \
+ __chk_user_ptr(ptr); \
+- switch(sizeof (*(ptr))) { \
+- case 1: __get_user_x(1,__ret_gu,__val_gu,ptr); break; \
+- case 2: __get_user_x(2,__ret_gu,__val_gu,ptr); break; \
+- case 4: __get_user_x(4,__ret_gu,__val_gu,ptr); break; \
+- default: __get_user_x(X,__ret_gu,__val_gu,ptr); break; \
++ switch (sizeof(*(ptr))) { \
++ case 1: \
++ __get_user_x(1, __ret_gu, __val_gu, ptr); \
++ break; \
++ case 2: \
++ __get_user_x(2, __ret_gu, __val_gu, ptr); \
++ break; \
++ case 4: \
++ __get_user_x(4, __ret_gu, __val_gu, ptr); \
++ break; \
++ default: \
++ __get_user_x(X, __ret_gu, __val_gu, ptr); \
++ break; \
+ } \
+ (x) = (__typeof__(*(ptr)))__val_gu; \
+ __ret_gu; \
+@@ -171,11 +186,25 @@ extern void __put_user_2(void);
+ extern void __put_user_4(void);
+ extern void __put_user_8(void);
+
+-#define __put_user_1(x, ptr) __asm__ __volatile__("call __put_user_1":"=a" (__ret_pu):"0" ((typeof(*(ptr)))(x)), "c" (ptr))
+-#define __put_user_2(x, ptr) __asm__ __volatile__("call __put_user_2":"=a" (__ret_pu):"0" ((typeof(*(ptr)))(x)), "c" (ptr))
+-#define __put_user_4(x, ptr) __asm__ __volatile__("call __put_user_4":"=a" (__ret_pu):"0" ((typeof(*(ptr)))(x)), "c" (ptr))
+-#define __put_user_8(x, ptr) __asm__ __volatile__("call __put_user_8":"=a" (__ret_pu):"A" ((typeof(*(ptr)))(x)), "c" (ptr))
+-#define __put_user_X(x, ptr) __asm__ __volatile__("call __put_user_X":"=a" (__ret_pu):"c" (ptr))
++#define __put_user_1(x, ptr) \
++ asm volatile("call __put_user_1" : "=a" (__ret_pu) \
++ : "0" ((typeof(*(ptr)))(x)), "c" (ptr))
++
++#define __put_user_2(x, ptr) \
++ asm volatile("call __put_user_2" : "=a" (__ret_pu) \
++ : "0" ((typeof(*(ptr)))(x)), "c" (ptr))
++
++#define __put_user_4(x, ptr) \
++ asm volatile("call __put_user_4" : "=a" (__ret_pu) \
++ : "0" ((typeof(*(ptr)))(x)), "c" (ptr))
++
++#define __put_user_8(x, ptr) \
++ asm volatile("call __put_user_8" : "=a" (__ret_pu) \
++ : "A" ((typeof(*(ptr)))(x)), "c" (ptr))
++
++#define __put_user_X(x, ptr) \
++ asm volatile("call __put_user_X" : "=a" (__ret_pu) \
++ : "c" (ptr))
+
+ /**
+ * put_user: - Write a simple value into user space.
+@@ -195,32 +224,43 @@ extern void __put_user_8(void);
+ */
+ #ifdef CONFIG_X86_WP_WORKS_OK
+
+-#define put_user(x,ptr) \
+-({ int __ret_pu; \
++#define put_user(x, ptr) \
++({ \
++ int __ret_pu; \
+ __typeof__(*(ptr)) __pu_val; \
+ __chk_user_ptr(ptr); \
+ __pu_val = x; \
+- switch(sizeof(*(ptr))) { \
+- case 1: __put_user_1(__pu_val, ptr); break; \
+- case 2: __put_user_2(__pu_val, ptr); break; \
+- case 4: __put_user_4(__pu_val, ptr); break; \
+- case 8: __put_user_8(__pu_val, ptr); break; \
+- default:__put_user_X(__pu_val, ptr); break; \
++ switch (sizeof(*(ptr))) { \
++ case 1: \
++ __put_user_1(__pu_val, ptr); \
++ break; \
++ case 2: \
++ __put_user_2(__pu_val, ptr); \
++ break; \
++ case 4: \
++ __put_user_4(__pu_val, ptr); \
++ break; \
++ case 8: \
++ __put_user_8(__pu_val, ptr); \
++ break; \
++ default: \
++ __put_user_X(__pu_val, ptr); \
++ break; \
+ } \
+ __ret_pu; \
+ })
+
+ #else
+-#define put_user(x,ptr) \
++#define put_user(x, ptr) \
+ ({ \
+- int __ret_pu; \
+- __typeof__(*(ptr)) __pus_tmp = x; \
+- __ret_pu=0; \
+- if(unlikely(__copy_to_user_ll(ptr, &__pus_tmp, \
+- sizeof(*(ptr))) != 0)) \
+- __ret_pu=-EFAULT; \
+- __ret_pu; \
+- })
++ int __ret_pu; \
++ __typeof__(*(ptr))__pus_tmp = x; \
++ __ret_pu = 0; \
++ if (unlikely(__copy_to_user_ll(ptr, &__pus_tmp, \
++ sizeof(*(ptr))) != 0)) \
++ __ret_pu = -EFAULT; \
++ __ret_pu; \
++})
+
+
+ #endif
+@@ -245,8 +285,8 @@ extern void __put_user_8(void);
+ * Returns zero on success, or -EFAULT on error.
+ * On error, the variable @x is set to zero.
+ */
+-#define __get_user(x,ptr) \
+- __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
++#define __get_user(x, ptr) \
++ __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
+
+
+ /**
+@@ -268,54 +308,62 @@ extern void __put_user_8(void);
+ *
+ * Returns zero on success, or -EFAULT on error.
+ */
+-#define __put_user(x,ptr) \
+- __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
++#define __put_user(x, ptr) \
++ __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
+
+-#define __put_user_nocheck(x,ptr,size) \
++#define __put_user_nocheck(x, ptr, size) \
+ ({ \
+ long __pu_err; \
+- __put_user_size((x),(ptr),(size),__pu_err,-EFAULT); \
++ __put_user_size((x), (ptr), (size), __pu_err, -EFAULT); \
+ __pu_err; \
+ })
+
+
+-#define __put_user_u64(x, addr, err) \
+- __asm__ __volatile__( \
+- "1: movl %%eax,0(%2)\n" \
+- "2: movl %%edx,4(%2)\n" \
+- "3:\n" \
+- ".section .fixup,\"ax\"\n" \
+- "4: movl %3,%0\n" \
+- " jmp 3b\n" \
+- ".previous\n" \
+- _ASM_EXTABLE(1b,4b) \
+- _ASM_EXTABLE(2b,4b) \
+- : "=r"(err) \
+- : "A" (x), "r" (addr), "i"(-EFAULT), "0"(err))
++#define __put_user_u64(x, addr, err) \
++ asm volatile("1: movl %%eax,0(%2)\n" \
++ "2: movl %%edx,4(%2)\n" \
++ "3:\n" \
++ ".section .fixup,\"ax\"\n" \
++ "4: movl %3,%0\n" \
++ " jmp 3b\n" \
++ ".previous\n" \
++ _ASM_EXTABLE(1b, 4b) \
++ _ASM_EXTABLE(2b, 4b) \
++ : "=r" (err) \
++ : "A" (x), "r" (addr), "i" (-EFAULT), "0" (err))
+
+ #ifdef CONFIG_X86_WP_WORKS_OK
+
+-#define __put_user_size(x,ptr,size,retval,errret) \
++#define __put_user_size(x, ptr, size, retval, errret) \
+ do { \
+ retval = 0; \
+ __chk_user_ptr(ptr); \
+ switch (size) { \
+- case 1: __put_user_asm(x,ptr,retval,"b","b","iq",errret);break; \
+- case 2: __put_user_asm(x,ptr,retval,"w","w","ir",errret);break; \
+- case 4: __put_user_asm(x,ptr,retval,"l","","ir",errret); break; \
+- case 8: __put_user_u64((__typeof__(*ptr))(x),ptr,retval); break;\
+- default: __put_user_bad(); \
++ case 1: \
++ __put_user_asm(x, ptr, retval, "b", "b", "iq", errret); \
++ break; \
++ case 2: \
++ __put_user_asm(x, ptr, retval, "w", "w", "ir", errret); \
++ break; \
++ case 4: \
++ __put_user_asm(x, ptr, retval, "l", "", "ir", errret); \
++ break; \
++ case 8: \
++ __put_user_u64((__typeof__(*ptr))(x), ptr, retval); \
++ break; \
++ default: \
++ __put_user_bad(); \
+ } \
+ } while (0)
+
+ #else
+
+-#define __put_user_size(x,ptr,size,retval,errret) \
++#define __put_user_size(x, ptr, size, retval, errret) \
+ do { \
+- __typeof__(*(ptr)) __pus_tmp = x; \
++ __typeof__(*(ptr))__pus_tmp = x; \
+ retval = 0; \
+ \
+- if(unlikely(__copy_to_user_ll(ptr, &__pus_tmp, size) != 0)) \
++ if (unlikely(__copy_to_user_ll(ptr, &__pus_tmp, size) != 0)) \
+ retval = errret; \
+ } while (0)
+
+@@ -329,65 +377,70 @@ struct __large_struct { unsigned long buf[100]; };
+ * aliasing issues.
+ */
+ #define __put_user_asm(x, addr, err, itype, rtype, ltype, errret) \
+- __asm__ __volatile__( \
+- "1: mov"itype" %"rtype"1,%2\n" \
+- "2:\n" \
+- ".section .fixup,\"ax\"\n" \
+- "3: movl %3,%0\n" \
+- " jmp 2b\n" \
+- ".previous\n" \
+- _ASM_EXTABLE(1b,3b) \
+- : "=r"(err) \
+- : ltype (x), "m"(__m(addr)), "i"(errret), "0"(err))
+-
+-
+-#define __get_user_nocheck(x,ptr,size) \
+-({ \
+- long __gu_err; \
+- unsigned long __gu_val; \
+- __get_user_size(__gu_val,(ptr),(size),__gu_err,-EFAULT);\
+- (x) = (__typeof__(*(ptr)))__gu_val; \
+- __gu_err; \
++ asm volatile("1: mov"itype" %"rtype"1,%2\n" \
++ "2:\n" \
++ ".section .fixup,\"ax\"\n" \
++ "3: movl %3,%0\n" \
++ " jmp 2b\n" \
++ ".previous\n" \
++ _ASM_EXTABLE(1b, 3b) \
++ : "=r"(err) \
++ : ltype (x), "m" (__m(addr)), "i" (errret), "0" (err))
++
++
++#define __get_user_nocheck(x, ptr, size) \
++({ \
++ long __gu_err; \
++ unsigned long __gu_val; \
++ __get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT); \
++ (x) = (__typeof__(*(ptr)))__gu_val; \
++ __gu_err; \
+ })
+
+ extern long __get_user_bad(void);
+
+-#define __get_user_size(x,ptr,size,retval,errret) \
++#define __get_user_size(x, ptr, size, retval, errret) \
+ do { \
+ retval = 0; \
+ __chk_user_ptr(ptr); \
+ switch (size) { \
+- case 1: __get_user_asm(x,ptr,retval,"b","b","=q",errret);break; \
+- case 2: __get_user_asm(x,ptr,retval,"w","w","=r",errret);break; \
+- case 4: __get_user_asm(x,ptr,retval,"l","","=r",errret);break; \
+- default: (x) = __get_user_bad(); \
++ case 1: \
++ __get_user_asm(x, ptr, retval, "b", "b", "=q", errret); \
++ break; \
++ case 2: \
++ __get_user_asm(x, ptr, retval, "w", "w", "=r", errret); \
++ break; \
++ case 4: \
++ __get_user_asm(x, ptr, retval, "l", "", "=r", errret); \
++ break; \
++ default: \
++ (x) = __get_user_bad(); \
+ } \
+ } while (0)
+
+ #define __get_user_asm(x, addr, err, itype, rtype, ltype, errret) \
+- __asm__ __volatile__( \
+- "1: mov"itype" %2,%"rtype"1\n" \
+- "2:\n" \
+- ".section .fixup,\"ax\"\n" \
+- "3: movl %3,%0\n" \
+- " xor"itype" %"rtype"1,%"rtype"1\n" \
+- " jmp 2b\n" \
+- ".previous\n" \
+- _ASM_EXTABLE(1b,3b) \
+- : "=r"(err), ltype (x) \
+- : "m"(__m(addr)), "i"(errret), "0"(err))
+-
+-
+-unsigned long __must_check __copy_to_user_ll(void __user *to,
+- const void *from, unsigned long n);
+-unsigned long __must_check __copy_from_user_ll(void *to,
+- const void __user *from, unsigned long n);
+-unsigned long __must_check __copy_from_user_ll_nozero(void *to,
+- const void __user *from, unsigned long n);
+-unsigned long __must_check __copy_from_user_ll_nocache(void *to,
+- const void __user *from, unsigned long n);
+-unsigned long __must_check __copy_from_user_ll_nocache_nozero(void *to,
+- const void __user *from, unsigned long n);
++ asm volatile("1: mov"itype" %2,%"rtype"1\n" \
++ "2:\n" \
++ ".section .fixup,\"ax\"\n" \
++ "3: movl %3,%0\n" \
++ " xor"itype" %"rtype"1,%"rtype"1\n" \
++ " jmp 2b\n" \
++ ".previous\n" \
++ _ASM_EXTABLE(1b, 3b) \
++ : "=r" (err), ltype (x) \
++ : "m" (__m(addr)), "i" (errret), "0" (err))
++
++
++unsigned long __must_check __copy_to_user_ll
++ (void __user *to, const void *from, unsigned long n);
++unsigned long __must_check __copy_from_user_ll
++ (void *to, const void __user *from, unsigned long n);
++unsigned long __must_check __copy_from_user_ll_nozero
++ (void *to, const void __user *from, unsigned long n);
++unsigned long __must_check __copy_from_user_ll_nocache
++ (void *to, const void __user *from, unsigned long n);
++unsigned long __must_check __copy_from_user_ll_nocache_nozero
++ (void *to, const void __user *from, unsigned long n);
+
+ /**
+ * __copy_to_user_inatomic: - Copy a block of data into user space, with less checking.
+@@ -416,13 +469,16 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
+
+ switch (n) {
+ case 1:
+- __put_user_size(*(u8 *)from, (u8 __user *)to, 1, ret, 1);
++ __put_user_size(*(u8 *)from, (u8 __user *)to,
++ 1, ret, 1);
+ return ret;
+ case 2:
+- __put_user_size(*(u16 *)from, (u16 __user *)to, 2, ret, 2);
++ __put_user_size(*(u16 *)from, (u16 __user *)to,
++ 2, ret, 2);
+ return ret;
+ case 4:
+- __put_user_size(*(u32 *)from, (u32 __user *)to, 4, ret, 4);
++ __put_user_size(*(u32 *)from, (u32 __user *)to,
++ 4, ret, 4);
+ return ret;
+ }
+ }
+@@ -545,19 +601,21 @@ static __always_inline unsigned long __copy_from_user_nocache(void *to,
+ }
+
+ static __always_inline unsigned long
+-__copy_from_user_inatomic_nocache(void *to, const void __user *from, unsigned long n)
++__copy_from_user_inatomic_nocache(void *to, const void __user *from,
++ unsigned long n)
+ {
+ return __copy_from_user_ll_nocache_nozero(to, from, n);
+ }
+
+ unsigned long __must_check copy_to_user(void __user *to,
+- const void *from, unsigned long n);
++ const void *from, unsigned long n);
+ unsigned long __must_check copy_from_user(void *to,
+- const void __user *from, unsigned long n);
++ const void __user *from,
++ unsigned long n);
+ long __must_check strncpy_from_user(char *dst, const char __user *src,
+- long count);
++ long count);
+ long __must_check __strncpy_from_user(char *dst,
+- const char __user *src, long count);
++ const char __user *src, long count);
+
+ /**
+ * strlen_user: - Get the size of a string in user space.
+diff --git a/include/asm-x86/uaccess_64.h b/include/asm-x86/uaccess_64.h
+index b87eb4b..b8a2f43 100644
+--- a/include/asm-x86/uaccess_64.h
++++ b/include/asm-x86/uaccess_64.h
+@@ -29,23 +29,27 @@
+ #define get_fs() (current_thread_info()->addr_limit)
+ #define set_fs(x) (current_thread_info()->addr_limit = (x))
+
+-#define segment_eq(a,b) ((a).seg == (b).seg)
++#define segment_eq(a, b) ((a).seg == (b).seg)
+
+-#define __addr_ok(addr) (!((unsigned long)(addr) & (current_thread_info()->addr_limit.seg)))
++#define __addr_ok(addr) (!((unsigned long)(addr) & \
++ (current_thread_info()->addr_limit.seg)))
+
+ /*
+ * Uhhuh, this needs 65-bit arithmetic. We have a carry..
+ */
+-#define __range_not_ok(addr,size) ({ \
+- unsigned long flag,roksum; \
+- __chk_user_ptr(addr); \
+- asm("# range_ok\n\r" \
+- "addq %3,%1 ; sbbq %0,%0 ; cmpq %1,%4 ; sbbq $0,%0" \
+- :"=&r" (flag), "=r" (roksum) \
+- :"1" (addr),"g" ((long)(size)),"g" (current_thread_info()->addr_limit.seg)); \
+- flag; })
++#define __range_not_ok(addr, size) \
++({ \
++ unsigned long flag, roksum; \
++ __chk_user_ptr(addr); \
++ asm("# range_ok\n\r" \
++ "addq %3,%1 ; sbbq %0,%0 ; cmpq %1,%4 ; sbbq $0,%0" \
++ : "=&r" (flag), "=r" (roksum) \
++ : "1" (addr), "g" ((long)(size)), \
++ "g" (current_thread_info()->addr_limit.seg)); \
++ flag; \
++})
+
+-#define access_ok(type, addr, size) (__range_not_ok(addr,size) == 0)
++#define access_ok(type, addr, size) (__range_not_ok(addr, size) == 0)
+
+ /*
+ * The exception table consists of pairs of addresses: the first is the
+@@ -60,8 +64,7 @@
+ * on our cache or tlb entries.
+ */
+
+-struct exception_table_entry
+-{
++struct exception_table_entry {
+ unsigned long insn, fixup;
+ };
+
+@@ -84,23 +87,36 @@ extern int fixup_exception(struct pt_regs *regs);
+ * accesses to the same area of user memory).
+ */
+
+-#define __get_user_x(size,ret,x,ptr) \
+- asm volatile("call __get_user_" #size \
+- :"=a" (ret),"=d" (x) \
+- :"c" (ptr) \
+- :"r8")
++#define __get_user_x(size, ret, x, ptr) \
++ asm volatile("call __get_user_" #size \
++ : "=a" (ret),"=d" (x) \
++ : "c" (ptr) \
++ : "r8")
++
++/* Careful: we have to cast the result to the type of the pointer
++ * for sign reasons */
+
+-/* Careful: we have to cast the result to the type of the pointer for sign reasons */
+-#define get_user(x,ptr) \
+-({ unsigned long __val_gu; \
+- int __ret_gu; \
++#define get_user(x, ptr) \
++({ \
++ unsigned long __val_gu; \
++ int __ret_gu; \
+ __chk_user_ptr(ptr); \
+- switch(sizeof (*(ptr))) { \
+- case 1: __get_user_x(1,__ret_gu,__val_gu,ptr); break; \
+- case 2: __get_user_x(2,__ret_gu,__val_gu,ptr); break; \
+- case 4: __get_user_x(4,__ret_gu,__val_gu,ptr); break; \
+- case 8: __get_user_x(8,__ret_gu,__val_gu,ptr); break; \
+- default: __get_user_bad(); break; \
++ switch (sizeof(*(ptr))) { \
++ case 1: \
++ __get_user_x(1, __ret_gu, __val_gu, ptr); \
++ break; \
++ case 2: \
++ __get_user_x(2, __ret_gu, __val_gu, ptr); \
++ break; \
++ case 4: \
++ __get_user_x(4, __ret_gu, __val_gu, ptr); \
++ break; \
++ case 8: \
++ __get_user_x(8, __ret_gu, __val_gu, ptr); \
++ break; \
++ default: \
++ __get_user_bad(); \
++ break; \
+ } \
+ (x) = (__force typeof(*(ptr)))__val_gu; \
+ __ret_gu; \
+@@ -112,55 +128,73 @@ extern void __put_user_4(void);
+ extern void __put_user_8(void);
+ extern void __put_user_bad(void);
+
+-#define __put_user_x(size,ret,x,ptr) \
+- asm volatile("call __put_user_" #size \
+- :"=a" (ret) \
+- :"c" (ptr),"d" (x) \
+- :"r8")
++#define __put_user_x(size, ret, x, ptr) \
++ asm volatile("call __put_user_" #size \
++ :"=a" (ret) \
++ :"c" (ptr),"d" (x) \
++ :"r8")
+
+-#define put_user(x,ptr) \
+- __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
++#define put_user(x, ptr) \
++ __put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
+
+-#define __get_user(x,ptr) \
+- __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+-#define __put_user(x,ptr) \
+- __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
++#define __get_user(x, ptr) \
++ __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
++#define __put_user(x, ptr) \
++ __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
+
+ #define __get_user_unaligned __get_user
+ #define __put_user_unaligned __put_user
+
+-#define __put_user_nocheck(x,ptr,size) \
++#define __put_user_nocheck(x, ptr, size) \
+ ({ \
+ int __pu_err; \
+- __put_user_size((x),(ptr),(size),__pu_err); \
++ __put_user_size((x), (ptr), (size), __pu_err); \
+ __pu_err; \
+ })
+
+
+-#define __put_user_check(x,ptr,size) \
+-({ \
+- int __pu_err; \
+- typeof(*(ptr)) __user *__pu_addr = (ptr); \
+- switch (size) { \
+- case 1: __put_user_x(1,__pu_err,x,__pu_addr); break; \
+- case 2: __put_user_x(2,__pu_err,x,__pu_addr); break; \
+- case 4: __put_user_x(4,__pu_err,x,__pu_addr); break; \
+- case 8: __put_user_x(8,__pu_err,x,__pu_addr); break; \
+- default: __put_user_bad(); \
+- } \
+- __pu_err; \
++#define __put_user_check(x, ptr, size) \
++({ \
++ int __pu_err; \
++ typeof(*(ptr)) __user *__pu_addr = (ptr); \
++ switch (size) { \
++ case 1: \
++ __put_user_x(1, __pu_err, x, __pu_addr); \
++ break; \
++ case 2: \
++ __put_user_x(2, __pu_err, x, __pu_addr); \
++ break; \
++ case 4: \
++ __put_user_x(4, __pu_err, x, __pu_addr); \
++ break; \
++ case 8: \
++ __put_user_x(8, __pu_err, x, __pu_addr); \
++ break; \
++ default: \
++ __put_user_bad(); \
++ } \
++ __pu_err; \
+ })
+
+-#define __put_user_size(x,ptr,size,retval) \
++#define __put_user_size(x, ptr, size, retval) \
+ do { \
+ retval = 0; \
+ __chk_user_ptr(ptr); \
+ switch (size) { \
+- case 1: __put_user_asm(x,ptr,retval,"b","b","iq",-EFAULT); break;\
+- case 2: __put_user_asm(x,ptr,retval,"w","w","ir",-EFAULT); break;\
+- case 4: __put_user_asm(x,ptr,retval,"l","k","ir",-EFAULT); break;\
+- case 8: __put_user_asm(x,ptr,retval,"q","","Zr",-EFAULT); break;\
+- default: __put_user_bad(); \
++ case 1: \
++ __put_user_asm(x, ptr, retval, "b", "b", "iq", -EFAULT);\
++ break; \
++ case 2: \
++ __put_user_asm(x, ptr, retval, "w", "w", "ir", -EFAULT);\
++ break; \
++ case 4: \
++ __put_user_asm(x, ptr, retval, "l", "k", "ir", -EFAULT);\
++ break; \
++ case 8: \
++ __put_user_asm(x, ptr, retval, "q", "", "Zr", -EFAULT); \
++ break; \
++ default: \
++ __put_user_bad(); \
+ } \
+ } while (0)
+
+@@ -174,23 +208,22 @@ struct __large_struct { unsigned long buf[100]; };
+ * aliasing issues.
+ */
+ #define __put_user_asm(x, addr, err, itype, rtype, ltype, errno) \
+- asm volatile( \
+- "1: mov"itype" %"rtype"1,%2\n" \
+- "2:\n" \
+- ".section .fixup,\"ax\"\n" \
+- "3: mov %3,%0\n" \
+- " jmp 2b\n" \
+- ".previous\n" \
+- _ASM_EXTABLE(1b,3b) \
+- : "=r"(err) \
+- : ltype (x), "m"(__m(addr)), "i"(errno), "0"(err))
+-
+-
+-#define __get_user_nocheck(x,ptr,size) \
++ asm volatile("1: mov"itype" %"rtype"1,%2\n" \
++ "2:\n" \
++ ".section .fixup, \"ax\"\n" \
++ "3: mov %3,%0\n" \
++ " jmp 2b\n" \
++ ".previous\n" \
++ _ASM_EXTABLE(1b, 3b) \
++ : "=r"(err) \
++ : ltype (x), "m" (__m(addr)), "i" (errno), "0" (err))
++
++
++#define __get_user_nocheck(x, ptr, size) \
+ ({ \
+ int __gu_err; \
+ unsigned long __gu_val; \
+- __get_user_size(__gu_val,(ptr),(size),__gu_err); \
++ __get_user_size(__gu_val, (ptr), (size), __gu_err); \
+ (x) = (__force typeof(*(ptr)))__gu_val; \
+ __gu_err; \
+ })
+@@ -201,31 +234,39 @@ extern int __get_user_4(void);
+ extern int __get_user_8(void);
+ extern int __get_user_bad(void);
+
+-#define __get_user_size(x,ptr,size,retval) \
++#define __get_user_size(x, ptr, size, retval) \
+ do { \
+ retval = 0; \
+ __chk_user_ptr(ptr); \
+ switch (size) { \
+- case 1: __get_user_asm(x,ptr,retval,"b","b","=q",-EFAULT); break;\
+- case 2: __get_user_asm(x,ptr,retval,"w","w","=r",-EFAULT); break;\
+- case 4: __get_user_asm(x,ptr,retval,"l","k","=r",-EFAULT); break;\
+- case 8: __get_user_asm(x,ptr,retval,"q","","=r",-EFAULT); break;\
+- default: (x) = __get_user_bad(); \
++ case 1: \
++ __get_user_asm(x, ptr, retval, "b", "b", "=q", -EFAULT);\
++ break; \
++ case 2: \
++ __get_user_asm(x, ptr, retval, "w", "w", "=r", -EFAULT);\
++ break; \
++ case 4: \
++ __get_user_asm(x, ptr, retval, "l", "k", "=r", -EFAULT);\
++ break; \
++ case 8: \
++ __get_user_asm(x, ptr, retval, "q", "", "=r", -EFAULT); \
++ break; \
++ default: \
++ (x) = __get_user_bad(); \
+ } \
+ } while (0)
+
+ #define __get_user_asm(x, addr, err, itype, rtype, ltype, errno) \
+- asm volatile( \
+- "1: mov"itype" %2,%"rtype"1\n" \
+- "2:\n" \
+- ".section .fixup,\"ax\"\n" \
+- "3: mov %3,%0\n" \
+- " xor"itype" %"rtype"1,%"rtype"1\n" \
+- " jmp 2b\n" \
+- ".previous\n" \
+- _ASM_EXTABLE(1b,3b) \
+- : "=r"(err), ltype (x) \
+- : "m"(__m(addr)), "i"(errno), "0"(err))
++ asm volatile("1: mov"itype" %2,%"rtype"1\n" \
++ "2:\n" \
++ ".section .fixup, \"ax\"\n" \
++ "3: mov %3,%0\n" \
++ " xor"itype" %"rtype"1,%"rtype"1\n" \
++ " jmp 2b\n" \
++ ".previous\n" \
++ _ASM_EXTABLE(1b, 3b) \
++ : "=r" (err), ltype (x) \
++ : "m" (__m(addr)), "i"(errno), "0"(err))
+
+ /*
+ * Copy To/From Userspace
+@@ -244,110 +285,142 @@ copy_in_user(void __user *to, const void __user *from, unsigned len);
+
+ static __always_inline __must_check
+ int __copy_from_user(void *dst, const void __user *src, unsigned size)
+-{
++{
+ int ret = 0;
+ if (!__builtin_constant_p(size))
+- return copy_user_generic(dst,(__force void *)src,size);
+- switch (size) {
+- case 1:__get_user_asm(*(u8*)dst,(u8 __user *)src,ret,"b","b","=q",1);
++ return copy_user_generic(dst, (__force void *)src, size);
++ switch (size) {
++ case 1:__get_user_asm(*(u8 *)dst, (u8 __user *)src,
++ ret, "b", "b", "=q", 1);
+ return ret;
+- case 2:__get_user_asm(*(u16*)dst,(u16 __user *)src,ret,"w","w","=r",2);
++ case 2:__get_user_asm(*(u16 *)dst, (u16 __user *)src,
++ ret, "w", "w", "=r", 2);
+ return ret;
+- case 4:__get_user_asm(*(u32*)dst,(u32 __user *)src,ret,"l","k","=r",4);
++ case 4:__get_user_asm(*(u32 *)dst, (u32 __user *)src,
++ ret, "l", "k", "=r", 4);
++ return ret;
++ case 8:__get_user_asm(*(u64 *)dst, (u64 __user *)src,
++ ret, "q", "", "=r", 8);
+ return ret;
+- case 8:__get_user_asm(*(u64*)dst,(u64 __user *)src,ret,"q","","=r",8);
+- return ret;
+ case 10:
+- __get_user_asm(*(u64*)dst,(u64 __user *)src,ret,"q","","=r",16);
+- if (unlikely(ret)) return ret;
+- __get_user_asm(*(u16*)(8+(char*)dst),(u16 __user *)(8+(char __user *)src),ret,"w","w","=r",2);
+- return ret;
++ __get_user_asm(*(u64 *)dst, (u64 __user *)src,
++ ret, "q", "", "=r", 16);
++ if (unlikely(ret))
++ return ret;
++ __get_user_asm(*(u16 *)(8 + (char *)dst),
++ (u16 __user *)(8 + (char __user *)src),
++ ret, "w", "w", "=r", 2);
++ return ret;
+ case 16:
+- __get_user_asm(*(u64*)dst,(u64 __user *)src,ret,"q","","=r",16);
+- if (unlikely(ret)) return ret;
+- __get_user_asm(*(u64*)(8+(char*)dst),(u64 __user *)(8+(char __user *)src),ret,"q","","=r",8);
+- return ret;
++ __get_user_asm(*(u64 *)dst, (u64 __user *)src,
++ ret, "q", "", "=r", 16);
++ if (unlikely(ret))
++ return ret;
++ __get_user_asm(*(u64 *)(8 + (char *)dst),
++ (u64 __user *)(8 + (char __user *)src),
++ ret, "q", "", "=r", 8);
++ return ret;
+ default:
+- return copy_user_generic(dst,(__force void *)src,size);
++ return copy_user_generic(dst, (__force void *)src, size);
+ }
+-}
++}
+
+ static __always_inline __must_check
+ int __copy_to_user(void __user *dst, const void *src, unsigned size)
+-{
++{
+ int ret = 0;
+ if (!__builtin_constant_p(size))
+- return copy_user_generic((__force void *)dst,src,size);
+- switch (size) {
+- case 1:__put_user_asm(*(u8*)src,(u8 __user *)dst,ret,"b","b","iq",1);
++ return copy_user_generic((__force void *)dst, src, size);
++ switch (size) {
++ case 1:__put_user_asm(*(u8 *)src, (u8 __user *)dst,
++ ret, "b", "b", "iq", 1);
+ return ret;
+- case 2:__put_user_asm(*(u16*)src,(u16 __user *)dst,ret,"w","w","ir",2);
++ case 2:__put_user_asm(*(u16 *)src, (u16 __user *)dst,
++ ret, "w", "w", "ir", 2);
+ return ret;
+- case 4:__put_user_asm(*(u32*)src,(u32 __user *)dst,ret,"l","k","ir",4);
++ case 4:__put_user_asm(*(u32 *)src, (u32 __user *)dst,
++ ret, "l", "k", "ir", 4);
++ return ret;
++ case 8:__put_user_asm(*(u64 *)src, (u64 __user *)dst,
++ ret, "q", "", "ir", 8);
+ return ret;
+- case 8:__put_user_asm(*(u64*)src,(u64 __user *)dst,ret,"q","","ir",8);
+- return ret;
+ case 10:
+- __put_user_asm(*(u64*)src,(u64 __user *)dst,ret,"q","","ir",10);
+- if (unlikely(ret)) return ret;
++ __put_user_asm(*(u64 *)src, (u64 __user *)dst,
++ ret, "q", "", "ir", 10);
++ if (unlikely(ret))
++ return ret;
+ asm("":::"memory");
+- __put_user_asm(4[(u16*)src],4+(u16 __user *)dst,ret,"w","w","ir",2);
+- return ret;
++ __put_user_asm(4[(u16 *)src], 4 + (u16 __user *)dst,
++ ret, "w", "w", "ir", 2);
++ return ret;
+ case 16:
+- __put_user_asm(*(u64*)src,(u64 __user *)dst,ret,"q","","ir",16);
+- if (unlikely(ret)) return ret;
++ __put_user_asm(*(u64 *)src, (u64 __user *)dst,
++ ret, "q", "", "ir", 16);
++ if (unlikely(ret))
++ return ret;
+ asm("":::"memory");
+- __put_user_asm(1[(u64*)src],1+(u64 __user *)dst,ret,"q","","ir",8);
+- return ret;
++ __put_user_asm(1[(u64 *)src], 1 + (u64 __user *)dst,
++ ret, "q", "", "ir", 8);
++ return ret;
+ default:
+- return copy_user_generic((__force void *)dst,src,size);
++ return copy_user_generic((__force void *)dst, src, size);
+ }
+-}
++}
+
+ static __always_inline __must_check
+ int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
+-{
++{
+ int ret = 0;
+ if (!__builtin_constant_p(size))
+- return copy_user_generic((__force void *)dst,(__force void *)src,size);
+- switch (size) {
+- case 1: {
++ return copy_user_generic((__force void *)dst,
++ (__force void *)src, size);
++ switch (size) {
++ case 1: {
+ u8 tmp;
+- __get_user_asm(tmp,(u8 __user *)src,ret,"b","b","=q",1);
++ __get_user_asm(tmp, (u8 __user *)src,
++ ret, "b", "b", "=q", 1);
+ if (likely(!ret))
+- __put_user_asm(tmp,(u8 __user *)dst,ret,"b","b","iq",1);
++ __put_user_asm(tmp, (u8 __user *)dst,
++ ret, "b", "b", "iq", 1);
+ return ret;
+ }
+- case 2: {
++ case 2: {
+ u16 tmp;
+- __get_user_asm(tmp,(u16 __user *)src,ret,"w","w","=r",2);
++ __get_user_asm(tmp, (u16 __user *)src,
++ ret, "w", "w", "=r", 2);
+ if (likely(!ret))
+- __put_user_asm(tmp,(u16 __user *)dst,ret,"w","w","ir",2);
++ __put_user_asm(tmp, (u16 __user *)dst,
++ ret, "w", "w", "ir", 2);
+ return ret;
+ }
+
+- case 4: {
++ case 4: {
+ u32 tmp;
+- __get_user_asm(tmp,(u32 __user *)src,ret,"l","k","=r",4);
++ __get_user_asm(tmp, (u32 __user *)src,
++ ret, "l", "k", "=r", 4);
+ if (likely(!ret))
+- __put_user_asm(tmp,(u32 __user *)dst,ret,"l","k","ir",4);
++ __put_user_asm(tmp, (u32 __user *)dst,
++ ret, "l", "k", "ir", 4);
+ return ret;
+ }
+- case 8: {
++ case 8: {
+ u64 tmp;
+- __get_user_asm(tmp,(u64 __user *)src,ret,"q","","=r",8);
++ __get_user_asm(tmp, (u64 __user *)src,
++ ret, "q", "", "=r", 8);
+ if (likely(!ret))
+- __put_user_asm(tmp,(u64 __user *)dst,ret,"q","","ir",8);
++ __put_user_asm(tmp, (u64 __user *)dst,
++ ret, "q", "", "ir", 8);
+ return ret;
+ }
+ default:
+- return copy_user_generic((__force void *)dst,(__force void *)src,size);
++ return copy_user_generic((__force void *)dst,
++ (__force void *)src, size);
+ }
+-}
++}
+
+-__must_check long
++__must_check long
+ strncpy_from_user(char *dst, const char __user *src, long count);
+-__must_check long
++__must_check long
+ __strncpy_from_user(char *dst, const char __user *src, long count);
+ __must_check long strnlen_user(const char __user *str, long n);
+ __must_check long __strnlen_user(const char __user *str, long n);
+@@ -355,7 +428,8 @@ __must_check long strlen_user(const char __user *str);
+ __must_check unsigned long clear_user(void __user *mem, unsigned long len);
+ __must_check unsigned long __clear_user(void __user *mem, unsigned long len);
+
+-__must_check long __copy_from_user_inatomic(void *dst, const void __user *src, unsigned size);
++__must_check long __copy_from_user_inatomic(void *dst, const void __user *src,
++ unsigned size);
+
+ static __must_check __always_inline int
+ __copy_to_user_inatomic(void __user *dst, const void *src, unsigned size)
+@@ -364,15 +438,19 @@ __copy_to_user_inatomic(void __user *dst, const void *src, unsigned size)
+ }
+
+ #define ARCH_HAS_NOCACHE_UACCESS 1
+-extern long __copy_user_nocache(void *dst, const void __user *src, unsigned size, int zerorest);
++extern long __copy_user_nocache(void *dst, const void __user *src,
++ unsigned size, int zerorest);
+
+-static inline int __copy_from_user_nocache(void *dst, const void __user *src, unsigned size)
++static inline int __copy_from_user_nocache(void *dst, const void __user *src,
++ unsigned size)
+ {
+ might_sleep();
+ return __copy_user_nocache(dst, src, size, 1);
+ }
+
+-static inline int __copy_from_user_inatomic_nocache(void *dst, const void __user *src, unsigned size)
++static inline int __copy_from_user_inatomic_nocache(void *dst,
++ const void __user *src,
++ unsigned size)
+ {
+ return __copy_user_nocache(dst, src, size, 0);
+ }
+diff --git a/include/asm-x86/unaligned.h b/include/asm-x86/unaligned.h
+index 913598d..d270ffe 100644
+--- a/include/asm-x86/unaligned.h
++++ b/include/asm-x86/unaligned.h
+@@ -32,6 +32,6 @@
+ *
+ * Note that unaligned accesses can be very expensive on some architectures.
+ */
+-#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
++#define put_unaligned(val, ptr) ((void)(*(ptr) = (val)))
+
+ #endif /* _ASM_X86_UNALIGNED_H */
+diff --git a/include/asm-x86/unistd_32.h b/include/asm-x86/unistd_32.h
+index 984123a..8317d94 100644
+--- a/include/asm-x86/unistd_32.h
++++ b/include/asm-x86/unistd_32.h
+@@ -81,7 +81,7 @@
+ #define __NR_sigpending 73
+ #define __NR_sethostname 74
+ #define __NR_setrlimit 75
+-#define __NR_getrlimit 76 /* Back compatible 2Gig limited rlimit */
++#define __NR_getrlimit 76 /* Back compatible 2Gig limited rlimit */
+ #define __NR_getrusage 77
+ #define __NR_gettimeofday 78
+ #define __NR_settimeofday 79
+diff --git a/include/asm-x86/unistd_64.h b/include/asm-x86/unistd_64.h
+index 3883ceb..fe26e36 100644
+--- a/include/asm-x86/unistd_64.h
++++ b/include/asm-x86/unistd_64.h
+@@ -2,7 +2,7 @@
+ #define _ASM_X86_64_UNISTD_H_
+
+ #ifndef __SYSCALL
+-#define __SYSCALL(a,b)
++#define __SYSCALL(a, b)
+ #endif
+
+ /*
+diff --git a/include/asm-x86/user32.h b/include/asm-x86/user32.h
+index f769872..a3d9100 100644
+--- a/include/asm-x86/user32.h
++++ b/include/asm-x86/user32.h
+@@ -1,7 +1,8 @@
+ #ifndef USER32_H
+ #define USER32_H 1
+
+-/* IA32 compatible user structures for ptrace. These should be used for 32bit coredumps too. */
++/* IA32 compatible user structures for ptrace.
++ * These should be used for 32bit coredumps too. */
+
+ struct user_i387_ia32_struct {
+ u32 cwd;
+@@ -42,9 +43,9 @@ struct user_regs_struct32 {
+ };
+
+ struct user32 {
+- struct user_regs_struct32 regs; /* Where the registers are actually stored */
++ struct user_regs_struct32 regs; /* Where the registers are actually stored */
+ int u_fpvalid; /* True if math co-processor being used. */
+- /* for this mess. Not yet used. */
++ /* for this mess. Not yet used. */
+ struct user_i387_ia32_struct i387; /* Math Co-processor registers. */
+ /* The rest of this junk is to help gdb figure out what goes where */
+ __u32 u_tsize; /* Text segment size (pages). */
+diff --git a/include/asm-x86/user_32.h b/include/asm-x86/user_32.h
+index 6157da6..d6e51ed 100644
+--- a/include/asm-x86/user_32.h
++++ b/include/asm-x86/user_32.h
+@@ -100,10 +100,10 @@ struct user_regs_struct {
+ struct user{
+ /* We start with the registers, to mimic the way that "memory" is returned
+ from the ptrace(3,...) function. */
+- struct user_regs_struct regs; /* Where the registers are actually stored */
++ struct user_regs_struct regs; /* Where the registers are actually stored */
+ /* ptrace does not yet supply these. Someday.... */
+ int u_fpvalid; /* True if math co-processor being used. */
+- /* for this mess. Not yet used. */
++ /* for this mess. Not yet used. */
+ struct user_i387_struct i387; /* Math Co-processor registers. */
+ /* The rest of this junk is to help gdb figure out what goes where */
+ unsigned long int u_tsize; /* Text segment size (pages). */
+@@ -118,7 +118,7 @@ struct user{
+ int reserved; /* No longer used */
+ unsigned long u_ar0; /* Used by gdb to help find the values for */
+ /* the registers. */
+- struct user_i387_struct* u_fpstate; /* Math Co-processor pointer. */
++ struct user_i387_struct *u_fpstate; /* Math Co-processor pointer. */
+ unsigned long magic; /* To uniquely identify a core file */
+ char u_comm[32]; /* User command that was responsible */
+ int u_debugreg[8];
+diff --git a/include/asm-x86/user_64.h b/include/asm-x86/user_64.h
+index 9636164..6037b63 100644
+--- a/include/asm-x86/user_64.h
++++ b/include/asm-x86/user_64.h
+@@ -45,12 +45,13 @@
+ */
+
+ /* This matches the 64bit FXSAVE format as defined by AMD. It is the same
+- as the 32bit format defined by Intel, except that the selector:offset pairs for
+- data and eip are replaced with flat 64bit pointers. */
++ as the 32bit format defined by Intel, except that the selector:offset pairs
++ for data and eip are replaced with flat 64bit pointers. */
+ struct user_i387_struct {
+ unsigned short cwd;
+ unsigned short swd;
+- unsigned short twd; /* Note this is not the same as the 32bit/x87/FSAVE twd */
++ unsigned short twd; /* Note this is not the same as
++ the 32bit/x87/FSAVE twd */
+ unsigned short fop;
+ __u64 rip;
+ __u64 rdp;
+@@ -97,13 +98,14 @@ struct user_regs_struct {
+ /* When the kernel dumps core, it starts by dumping the user struct -
+ this will be used by gdb to figure out where the data and stack segments
+ are within the file, and what virtual addresses to use. */
+-struct user{
++
++struct user {
+ /* We start with the registers, to mimic the way that "memory" is returned
+ from the ptrace(3,...) function. */
+- struct user_regs_struct regs; /* Where the registers are actually stored */
++ struct user_regs_struct regs; /* Where the registers are actually stored */
+ /* ptrace does not yet supply these. Someday.... */
+ int u_fpvalid; /* True if math co-processor being used. */
+- /* for this mess. Not yet used. */
++ /* for this mess. Not yet used. */
+ int pad0;
+ struct user_i387_struct i387; /* Math Co-processor registers. */
+ /* The rest of this junk is to help gdb figure out what goes where */
+@@ -120,7 +122,7 @@ struct user{
+ int pad1;
+ unsigned long u_ar0; /* Used by gdb to help find the values for */
+ /* the registers. */
+- struct user_i387_struct* u_fpstate; /* Math Co-processor pointer. */
++ struct user_i387_struct *u_fpstate; /* Math Co-processor pointer. */
+ unsigned long magic; /* To uniquely identify a core file */
+ char u_comm[32]; /* User command that was responsible */
+ unsigned long u_debugreg[8];
+diff --git a/include/asm-x86/uv/uv_hub.h b/include/asm-x86/uv/uv_hub.h
+new file mode 100644
+index 0000000..26b9240
+--- /dev/null
++++ b/include/asm-x86/uv/uv_hub.h
+@@ -0,0 +1,284 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * SGI UV architectural definitions
++ *
++ * Copyright (C) 2007 Silicon Graphics, Inc. All rights reserved.
++ */
++
++#ifndef __ASM_X86_UV_HUB_H__
++#define __ASM_X86_UV_HUB_H__
++
++#include <linux/numa.h>
++#include <linux/percpu.h>
++#include <asm/types.h>
++#include <asm/percpu.h>
++
++
++/*
++ * Addressing Terminology
++ *
++ * NASID - network ID of a router, Mbrick or Cbrick. Nasid values of
++ * routers always have low bit of 1, C/MBricks have low bit
++ * equal to 0. Most addressing macros that target UV hub chips
++ * right shift the NASID by 1 to exclude the always-zero bit.
++ *
++ * SNASID - NASID right shifted by 1 bit.
++ *
++ *
++ * Memory/UV-HUB Processor Socket Address Format:
++ * +--------+---------------+---------------------+
++ * |00..0000| SNASID | NodeOffset |
++ * +--------+---------------+---------------------+
++ * <--- N bits --->|<--------M bits ----->
++ *
++ * M number of node offset bits (35 .. 40)
++ * N number of SNASID bits (0 .. 10)
++ *
++ * Note: M + N cannot currently exceed 44 (x86_64) or 46 (IA64).
++ * The actual values are configuration dependent and are set at
++ * boot time
++ *
++ * APICID format
++ * NOTE!!!!!! This is the current format of the APICID. However, code
++ * should assume that this will change in the future. Use functions
++ * in this file for all APICID bit manipulations and conversion.
++ *
++ * 1111110000000000
++ * 5432109876543210
++ * nnnnnnnnnnlc0cch
++ * sssssssssss
++ *
++ * n = snasid bits
++ * l = socket number on board
++ * c = core
++ * h = hyperthread
++ * s = bits that are in the socket CSR
++ *
++ * Note: Processor only supports 12 bits in the APICID register. The ACPI
++ * tables hold all 16 bits. Software needs to be aware of this.
++ *
++ * Unless otherwise specified, all references to APICID refer to
++ * the FULL value contained in ACPI tables, not the subset in the
++ * processor APICID register.
++ */
++
++
++/*
++ * Maximum number of bricks in all partitions and in all coherency domains.
++ * This is the total number of bricks accessible in the numalink fabric. It
++ * includes all C & M bricks. Routers are NOT included.
++ *
++ * This value is also the value of the maximum number of non-router NASIDs
++ * in the numalink fabric.
++ *
++ * NOTE: a brick may be 1 or 2 OS nodes. Don't get these confused.
++ */
++#define UV_MAX_NUMALINK_BLADES 16384
++
++/*
++ * Maximum number of C/Mbricks within a software SSI (hardware may support
++ * more).
++ */
++#define UV_MAX_SSI_BLADES 256
++
++/*
++ * The largest possible NASID of a C or M brick (+ 2)
++ */
++#define UV_MAX_NASID_VALUE (UV_MAX_NUMALINK_NODES * 2)
++
++/*
++ * The following defines attributes of the HUB chip. These attributes are
++ * frequently referenced and are kept in the per-cpu data areas of each cpu.
++ * They are kept together in a struct to minimize cache misses.
++ */
++struct uv_hub_info_s {
++ unsigned long global_mmr_base;
++ unsigned short local_nasid;
++ unsigned short gnode_upper;
++ unsigned short coherency_domain_number;
++ unsigned short numa_blade_id;
++ unsigned char blade_processor_id;
++ unsigned char m_val;
++ unsigned char n_val;
++};
++DECLARE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
++#define uv_hub_info (&__get_cpu_var(__uv_hub_info))
++#define uv_cpu_hub_info(cpu) (&per_cpu(__uv_hub_info, cpu))
++
++/*
++ * Local & Global MMR space macros.
++ * Note: macros are intended to be used ONLY by inline functions
++ * in this file - not by other kernel code.
++ */
++#define UV_SNASID(n) ((n) >> 1)
++#define UV_NASID(n) ((n) << 1)
++
++#define UV_LOCAL_MMR_BASE 0xf4000000UL
++#define UV_GLOBAL_MMR32_BASE 0xf8000000UL
++#define UV_GLOBAL_MMR64_BASE (uv_hub_info->global_mmr_base)
++
++#define UV_GLOBAL_MMR32_SNASID_MASK 0x3ff
++#define UV_GLOBAL_MMR32_SNASID_SHIFT 15
++#define UV_GLOBAL_MMR64_SNASID_SHIFT 26
++
++#define UV_GLOBAL_MMR32_NASID_BITS(n) \
++ (((UV_SNASID(n) & UV_GLOBAL_MMR32_SNASID_MASK)) << \
++ (UV_GLOBAL_MMR32_SNASID_SHIFT))
++
++#define UV_GLOBAL_MMR64_NASID_BITS(n) \
++ ((unsigned long)UV_SNASID(n) << UV_GLOBAL_MMR64_SNASID_SHIFT)
++
++#define UV_APIC_NASID_SHIFT 6
++
++/*
++ * Extract a NASID from an APICID (full apicid, not processor subset)
++ */
++static inline int uv_apicid_to_nasid(int apicid)
++{
++ return (UV_NASID(apicid >> UV_APIC_NASID_SHIFT));
++}
++
++/*
++ * Access global MMRs using the low memory MMR32 space. This region supports
++ * faster MMR access but not all MMRs are accessible in this space.
++ */
++static inline unsigned long *uv_global_mmr32_address(int nasid,
++ unsigned long offset)
++{
++ return __va(UV_GLOBAL_MMR32_BASE |
++ UV_GLOBAL_MMR32_NASID_BITS(nasid) | offset);
++}
++
++static inline void uv_write_global_mmr32(int nasid, unsigned long offset,
++ unsigned long val)
++{
++ *uv_global_mmr32_address(nasid, offset) = val;
++}
++
++static inline unsigned long uv_read_global_mmr32(int nasid,
++ unsigned long offset)
++{
++ return *uv_global_mmr32_address(nasid, offset);
++}
++
++/*
++ * Access Global MMR space using the MMR space located at the top of physical
++ * memory.
++ */
++static inline unsigned long *uv_global_mmr64_address(int nasid,
++ unsigned long offset)
++{
++ return __va(UV_GLOBAL_MMR64_BASE |
++ UV_GLOBAL_MMR64_NASID_BITS(nasid) | offset);
++}
++
++static inline void uv_write_global_mmr64(int nasid, unsigned long offset,
++ unsigned long val)
++{
++ *uv_global_mmr64_address(nasid, offset) = val;
++}
++
++static inline unsigned long uv_read_global_mmr64(int nasid,
++ unsigned long offset)
++{
++ return *uv_global_mmr64_address(nasid, offset);
++}
++
++/*
++ * Access node local MMRs. Faster than using global space but only local MMRs
++ * are accessible.
++ */
++static inline unsigned long *uv_local_mmr_address(unsigned long offset)
++{
++ return __va(UV_LOCAL_MMR_BASE | offset);
++}
++
++static inline unsigned long uv_read_local_mmr(unsigned long offset)
++{
++ return *uv_local_mmr_address(offset);
++}
++
++static inline void uv_write_local_mmr(unsigned long offset, unsigned long val)
++{
++ *uv_local_mmr_address(offset) = val;
++}
++
++/*
++ * Structures and definitions for converting between cpu, node, and blade
++ * numbers.
++ */
++struct uv_blade_info {
++ unsigned short nr_posible_cpus;
++ unsigned short nr_online_cpus;
++ unsigned short nasid;
++};
++struct uv_blade_info *uv_blade_info;
++extern short *uv_node_to_blade;
++extern short *uv_cpu_to_blade;
++extern short uv_possible_blades;
++
++/* Blade-local cpu number of current cpu. Numbered 0 .. <# cpus on the blade> */
++static inline int uv_blade_processor_id(void)
++{
++ return uv_hub_info->blade_processor_id;
++}
++
++/* Blade number of current cpu. Numnbered 0 .. <#blades -1> */
++static inline int uv_numa_blade_id(void)
++{
++ return uv_hub_info->numa_blade_id;
++}
++
++/* Convert a cpu number to the the UV blade number */
++static inline int uv_cpu_to_blade_id(int cpu)
++{
++ return uv_cpu_to_blade[cpu];
++}
++
++/* Convert linux node number to the UV blade number */
++static inline int uv_node_to_blade_id(int nid)
++{
++ return uv_node_to_blade[nid];
++}
++
++/* Convert a blade id to the NASID of the blade */
++static inline int uv_blade_to_nasid(int bid)
++{
++ return uv_blade_info[bid].nasid;
++}
++
++/* Determine the number of possible cpus on a blade */
++static inline int uv_blade_nr_possible_cpus(int bid)
++{
++ return uv_blade_info[bid].nr_posible_cpus;
++}
++
++/* Determine the number of online cpus on a blade */
++static inline int uv_blade_nr_online_cpus(int bid)
++{
++ return uv_blade_info[bid].nr_online_cpus;
++}
++
++/* Convert a cpu id to the NASID of the blade containing the cpu */
++static inline int uv_cpu_to_nasid(int cpu)
++{
++ return uv_blade_info[uv_cpu_to_blade_id(cpu)].nasid;
++}
++
++/* Convert a node number to the NASID of the blade */
++static inline int uv_node_to_nasid(int nid)
++{
++ return uv_blade_info[uv_node_to_blade_id(nid)].nasid;
++}
++
++/* Maximum possible number of blades */
++static inline int uv_num_possible_blades(void)
++{
++ return uv_possible_blades;
++}
++
++#endif /* __ASM_X86_UV_HUB__ */
++
+diff --git a/include/asm-x86/uv/uv_mmrs.h b/include/asm-x86/uv/uv_mmrs.h
+new file mode 100644
+index 0000000..3b69fe6
+--- /dev/null
++++ b/include/asm-x86/uv/uv_mmrs.h
+@@ -0,0 +1,373 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * SGI UV MMR definitions
++ *
++ * Copyright (C) 2007-2008 Silicon Graphics, Inc. All rights reserved.
++ */
++
++#ifndef __ASM_X86_UV_MMRS__
++#define __ASM_X86_UV_MMRS__
++
++/*
++ * AUTO GENERATED - Do not edit
++ */
++
++ #define UV_MMR_ENABLE (1UL << 63)
++
++/* ========================================================================= */
++/* UVH_IPI_INT */
++/* ========================================================================= */
++#define UVH_IPI_INT 0x60500UL
++#define UVH_IPI_INT_32 0x0360
++
++#define UVH_IPI_INT_VECTOR_SHFT 0
++#define UVH_IPI_INT_VECTOR_MASK 0x00000000000000ffUL
++#define UVH_IPI_INT_DELIVERY_MODE_SHFT 8
++#define UVH_IPI_INT_DELIVERY_MODE_MASK 0x0000000000000700UL
++#define UVH_IPI_INT_DESTMODE_SHFT 11
++#define UVH_IPI_INT_DESTMODE_MASK 0x0000000000000800UL
++#define UVH_IPI_INT_APIC_ID_SHFT 16
++#define UVH_IPI_INT_APIC_ID_MASK 0x0000ffffffff0000UL
++#define UVH_IPI_INT_SEND_SHFT 63
++#define UVH_IPI_INT_SEND_MASK 0x8000000000000000UL
++
++union uvh_ipi_int_u {
++ unsigned long v;
++ struct uvh_ipi_int_s {
++ unsigned long vector_ : 8; /* RW */
++ unsigned long delivery_mode : 3; /* RW */
++ unsigned long destmode : 1; /* RW */
++ unsigned long rsvd_12_15 : 4; /* */
++ unsigned long apic_id : 32; /* RW */
++ unsigned long rsvd_48_62 : 15; /* */
++ unsigned long send : 1; /* WP */
++ } s;
++};
++
++/* ========================================================================= */
++/* UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST */
++/* ========================================================================= */
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST 0x320050UL
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_32 0x009f0
++
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_ADDRESS_SHFT 4
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_ADDRESS_MASK 0x000007fffffffff0UL
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_NODE_ID_SHFT 49
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_NODE_ID_MASK 0x7ffe000000000000UL
++
++union uvh_lb_bau_intd_payload_queue_first_u {
++ unsigned long v;
++ struct uvh_lb_bau_intd_payload_queue_first_s {
++ unsigned long rsvd_0_3: 4; /* */
++ unsigned long address : 39; /* RW */
++ unsigned long rsvd_43_48: 6; /* */
++ unsigned long node_id : 14; /* RW */
++ unsigned long rsvd_63 : 1; /* */
++ } s;
++};
++
++/* ========================================================================= */
++/* UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST */
++/* ========================================================================= */
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST 0x320060UL
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_32 0x009f8
++
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_ADDRESS_SHFT 4
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_ADDRESS_MASK 0x000007fffffffff0UL
++
++union uvh_lb_bau_intd_payload_queue_last_u {
++ unsigned long v;
++ struct uvh_lb_bau_intd_payload_queue_last_s {
++ unsigned long rsvd_0_3: 4; /* */
++ unsigned long address : 39; /* RW */
++ unsigned long rsvd_43_63: 21; /* */
++ } s;
++};
++
++/* ========================================================================= */
++/* UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL */
++/* ========================================================================= */
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL 0x320070UL
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_32 0x00a00
++
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_ADDRESS_SHFT 4
++#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_ADDRESS_MASK 0x000007fffffffff0UL
++
++union uvh_lb_bau_intd_payload_queue_tail_u {
++ unsigned long v;
++ struct uvh_lb_bau_intd_payload_queue_tail_s {
++ unsigned long rsvd_0_3: 4; /* */
++ unsigned long address : 39; /* RW */
++ unsigned long rsvd_43_63: 21; /* */
++ } s;
++};
++
++/* ========================================================================= */
++/* UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE */
++/* ========================================================================= */
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE 0x320080UL
++
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_0_SHFT 0
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_0_MASK 0x0000000000000001UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_1_SHFT 1
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_1_MASK 0x0000000000000002UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_2_SHFT 2
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_2_MASK 0x0000000000000004UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_3_SHFT 3
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_3_MASK 0x0000000000000008UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_4_SHFT 4
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_4_MASK 0x0000000000000010UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_5_SHFT 5
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_5_MASK 0x0000000000000020UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_6_SHFT 6
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_6_MASK 0x0000000000000040UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_7_SHFT 7
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_7_MASK 0x0000000000000080UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_0_SHFT 8
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_0_MASK 0x0000000000000100UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_1_SHFT 9
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_1_MASK 0x0000000000000200UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_2_SHFT 10
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_2_MASK 0x0000000000000400UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_3_SHFT 11
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_3_MASK 0x0000000000000800UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_4_SHFT 12
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_4_MASK 0x0000000000001000UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_5_SHFT 13
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_5_MASK 0x0000000000002000UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_6_SHFT 14
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_6_MASK 0x0000000000004000UL
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_7_SHFT 15
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_7_MASK 0x0000000000008000UL
++union uvh_lb_bau_intd_software_acknowledge_u {
++ unsigned long v;
++ struct uvh_lb_bau_intd_software_acknowledge_s {
++ unsigned long pending_0 : 1; /* RW, W1C */
++ unsigned long pending_1 : 1; /* RW, W1C */
++ unsigned long pending_2 : 1; /* RW, W1C */
++ unsigned long pending_3 : 1; /* RW, W1C */
++ unsigned long pending_4 : 1; /* RW, W1C */
++ unsigned long pending_5 : 1; /* RW, W1C */
++ unsigned long pending_6 : 1; /* RW, W1C */
++ unsigned long pending_7 : 1; /* RW, W1C */
++ unsigned long timeout_0 : 1; /* RW, W1C */
++ unsigned long timeout_1 : 1; /* RW, W1C */
++ unsigned long timeout_2 : 1; /* RW, W1C */
++ unsigned long timeout_3 : 1; /* RW, W1C */
++ unsigned long timeout_4 : 1; /* RW, W1C */
++ unsigned long timeout_5 : 1; /* RW, W1C */
++ unsigned long timeout_6 : 1; /* RW, W1C */
++ unsigned long timeout_7 : 1; /* RW, W1C */
++ unsigned long rsvd_16_63: 48; /* */
++ } s;
++};
++
++/* ========================================================================= */
++/* UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS */
++/* ========================================================================= */
++#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS 0x0000000000320088UL
++
++/* ========================================================================= */
++/* UVH_LB_BAU_SB_ACTIVATION_CONTROL */
++/* ========================================================================= */
++#define UVH_LB_BAU_SB_ACTIVATION_CONTROL 0x320020UL
++#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_32 0x009d8
++
++#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INDEX_SHFT 0
++#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INDEX_MASK 0x000000000000003fUL
++#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_PUSH_SHFT 62
++#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_PUSH_MASK 0x4000000000000000UL
++#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INIT_SHFT 63
++#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INIT_MASK 0x8000000000000000UL
++
++union uvh_lb_bau_sb_activation_control_u {
++ unsigned long v;
++ struct uvh_lb_bau_sb_activation_control_s {
++ unsigned long index : 6; /* RW */
++ unsigned long rsvd_6_61: 56; /* */
++ unsigned long push : 1; /* WP */
++ unsigned long init : 1; /* WP */
++ } s;
++};
++
++/* ========================================================================= */
++/* UVH_LB_BAU_SB_ACTIVATION_STATUS_0 */
++/* ========================================================================= */
++#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0 0x320030UL
++#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0_32 0x009e0
++
++#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0_STATUS_SHFT 0
++#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0_STATUS_MASK 0xffffffffffffffffUL
++
++union uvh_lb_bau_sb_activation_status_0_u {
++ unsigned long v;
++ struct uvh_lb_bau_sb_activation_status_0_s {
++ unsigned long status : 64; /* RW */
++ } s;
++};
++
++/* ========================================================================= */
++/* UVH_LB_BAU_SB_ACTIVATION_STATUS_1 */
++/* ========================================================================= */
++#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1 0x320040UL
++#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1_32 0x009e8
++
++#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1_STATUS_SHFT 0
++#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1_STATUS_MASK 0xffffffffffffffffUL
++
++union uvh_lb_bau_sb_activation_status_1_u {
++ unsigned long v;
++ struct uvh_lb_bau_sb_activation_status_1_s {
++ unsigned long status : 64; /* RW */
++ } s;
++};
++
++/* ========================================================================= */
++/* UVH_LB_BAU_SB_DESCRIPTOR_BASE */
++/* ========================================================================= */
++#define UVH_LB_BAU_SB_DESCRIPTOR_BASE 0x320010UL
++#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_32 0x009d0
++
++#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_PAGE_ADDRESS_SHFT 12
++#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_PAGE_ADDRESS_MASK 0x000007fffffff000UL
++#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_NODE_ID_SHFT 49
++#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_NODE_ID_MASK 0x7ffe000000000000UL
++
++union uvh_lb_bau_sb_descriptor_base_u {
++ unsigned long v;
++ struct uvh_lb_bau_sb_descriptor_base_s {
++ unsigned long rsvd_0_11 : 12; /* */
++ unsigned long page_address : 31; /* RW */
++ unsigned long rsvd_43_48 : 6; /* */
++ unsigned long node_id : 14; /* RW */
++ unsigned long rsvd_63 : 1; /* */
++ } s;
++};
++
++/* ========================================================================= */
++/* UVH_NODE_ID */
++/* ========================================================================= */
++#define UVH_NODE_ID 0x0UL
++
++#define UVH_NODE_ID_FORCE1_SHFT 0
++#define UVH_NODE_ID_FORCE1_MASK 0x0000000000000001UL
++#define UVH_NODE_ID_MANUFACTURER_SHFT 1
++#define UVH_NODE_ID_MANUFACTURER_MASK 0x0000000000000ffeUL
++#define UVH_NODE_ID_PART_NUMBER_SHFT 12
++#define UVH_NODE_ID_PART_NUMBER_MASK 0x000000000ffff000UL
++#define UVH_NODE_ID_REVISION_SHFT 28
++#define UVH_NODE_ID_REVISION_MASK 0x00000000f0000000UL
++#define UVH_NODE_ID_NODE_ID_SHFT 32
++#define UVH_NODE_ID_NODE_ID_MASK 0x00007fff00000000UL
++#define UVH_NODE_ID_NODES_PER_BIT_SHFT 48
++#define UVH_NODE_ID_NODES_PER_BIT_MASK 0x007f000000000000UL
++#define UVH_NODE_ID_NI_PORT_SHFT 56
++#define UVH_NODE_ID_NI_PORT_MASK 0x0f00000000000000UL
++
++union uvh_node_id_u {
++ unsigned long v;
++ struct uvh_node_id_s {
++ unsigned long force1 : 1; /* RO */
++ unsigned long manufacturer : 11; /* RO */
++ unsigned long part_number : 16; /* RO */
++ unsigned long revision : 4; /* RO */
++ unsigned long node_id : 15; /* RW */
++ unsigned long rsvd_47 : 1; /* */
++ unsigned long nodes_per_bit : 7; /* RW */
++ unsigned long rsvd_55 : 1; /* */
++ unsigned long ni_port : 4; /* RO */
++ unsigned long rsvd_60_63 : 4; /* */
++ } s;
++};
++
++/* ========================================================================= */
++/* UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR */
++/* ========================================================================= */
++#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR 0x1600010UL
++
++#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT 28
++#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffff0000000UL
++#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_GR4_SHFT 46
++#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_GR4_MASK 0x0000400000000000UL
++#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_SHFT 52
++#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_MASK 0x00f0000000000000UL
++#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63
++#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
++
++union uvh_rh_gam_gru_overlay_config_mmr_u {
++ unsigned long v;
++ struct uvh_rh_gam_gru_overlay_config_mmr_s {
++ unsigned long rsvd_0_27: 28; /* */
++ unsigned long base : 18; /* RW */
++ unsigned long gr4 : 1; /* RW */
++ unsigned long rsvd_47_51: 5; /* */
++ unsigned long n_gru : 4; /* RW */
++ unsigned long rsvd_56_62: 7; /* */
++ unsigned long enable : 1; /* RW */
++ } s;
++};
++
++/* ========================================================================= */
++/* UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR */
++/* ========================================================================= */
++#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR 0x1600028UL
++
++#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_SHFT 26
++#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffffc000000UL
++#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_DUAL_HUB_SHFT 46
++#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_DUAL_HUB_MASK 0x0000400000000000UL
++#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63
++#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
++
++union uvh_rh_gam_mmr_overlay_config_mmr_u {
++ unsigned long v;
++ struct uvh_rh_gam_mmr_overlay_config_mmr_s {
++ unsigned long rsvd_0_25: 26; /* */
++ unsigned long base : 20; /* RW */
++ unsigned long dual_hub : 1; /* RW */
++ unsigned long rsvd_47_62: 16; /* */
++ unsigned long enable : 1; /* RW */
++ } s;
++};
++
++/* ========================================================================= */
++/* UVH_RTC */
++/* ========================================================================= */
++#define UVH_RTC 0x28000UL
++
++#define UVH_RTC_REAL_TIME_CLOCK_SHFT 0
++#define UVH_RTC_REAL_TIME_CLOCK_MASK 0x00ffffffffffffffUL
++
++union uvh_rtc_u {
++ unsigned long v;
++ struct uvh_rtc_s {
++ unsigned long real_time_clock : 56; /* RW */
++ unsigned long rsvd_56_63 : 8; /* */
++ } s;
++};
++
++/* ========================================================================= */
++/* UVH_SI_ADDR_MAP_CONFIG */
++/* ========================================================================= */
++#define UVH_SI_ADDR_MAP_CONFIG 0xc80000UL
++
++#define UVH_SI_ADDR_MAP_CONFIG_M_SKT_SHFT 0
++#define UVH_SI_ADDR_MAP_CONFIG_M_SKT_MASK 0x000000000000003fUL
++#define UVH_SI_ADDR_MAP_CONFIG_N_SKT_SHFT 8
++#define UVH_SI_ADDR_MAP_CONFIG_N_SKT_MASK 0x0000000000000f00UL
++
++union uvh_si_addr_map_config_u {
++ unsigned long v;
++ struct uvh_si_addr_map_config_s {
++ unsigned long m_skt : 6; /* RW */
++ unsigned long rsvd_6_7: 2; /* */
++ unsigned long n_skt : 4; /* RW */
++ unsigned long rsvd_12_63: 52; /* */
++ } s;
++};
++
++
++#endif /* __ASM_X86_UV_MMRS__ */
+diff --git a/include/asm-x86/vdso.h b/include/asm-x86/vdso.h
+index 629bcb6..86e085e 100644
+--- a/include/asm-x86/vdso.h
++++ b/include/asm-x86/vdso.h
+@@ -8,9 +8,11 @@ extern const char VDSO64_PRELINK[];
+ * Given a pointer to the vDSO image, find the pointer to VDSO64_name
+ * as that symbol is defined in the vDSO sources or linker script.
+ */
+-#define VDSO64_SYMBOL(base, name) ({ \
+- extern const char VDSO64_##name[]; \
+- (void *) (VDSO64_##name - VDSO64_PRELINK + (unsigned long) (base)); })
++#define VDSO64_SYMBOL(base, name) \
++({ \
++ extern const char VDSO64_##name[]; \
++ (void *)(VDSO64_##name - VDSO64_PRELINK + (unsigned long)(base)); \
++})
+ #endif
+
+ #if defined CONFIG_X86_32 || defined CONFIG_COMPAT
+@@ -20,9 +22,18 @@ extern const char VDSO32_PRELINK[];
+ * Given a pointer to the vDSO image, find the pointer to VDSO32_name
+ * as that symbol is defined in the vDSO sources or linker script.
+ */
+-#define VDSO32_SYMBOL(base, name) ({ \
+- extern const char VDSO32_##name[]; \
+- (void *) (VDSO32_##name - VDSO32_PRELINK + (unsigned long) (base)); })
++#define VDSO32_SYMBOL(base, name) \
++({ \
++ extern const char VDSO32_##name[]; \
++ (void *)(VDSO32_##name - VDSO32_PRELINK + (unsigned long)(base)); \
++})
+ #endif
+
++/*
++ * These symbols are defined with the addresses in the vsyscall page.
++ * See vsyscall-sigreturn.S.
++ */
++extern void __user __kernel_sigreturn;
++extern void __user __kernel_rt_sigreturn;
++
+ #endif /* asm-x86/vdso.h */
+diff --git a/include/asm-x86/vga.h b/include/asm-x86/vga.h
+index 0ecf68a..0ccf804 100644
+--- a/include/asm-x86/vga.h
++++ b/include/asm-x86/vga.h
+@@ -12,9 +12,9 @@
+ * access the videoram directly without any black magic.
+ */
+
+-#define VGA_MAP_MEM(x,s) (unsigned long)phys_to_virt(x)
++#define VGA_MAP_MEM(x, s) (unsigned long)phys_to_virt(x)
+
+ #define vga_readb(x) (*(x))
+-#define vga_writeb(x,y) (*(y) = (x))
++#define vga_writeb(x, y) (*(y) = (x))
+
+ #endif
+diff --git a/include/asm-x86/vm86.h b/include/asm-x86/vm86.h
+index c92fe4a..074b357 100644
+--- a/include/asm-x86/vm86.h
++++ b/include/asm-x86/vm86.h
+@@ -12,19 +12,13 @@
+ * Linus
+ */
+
+-#define TF_MASK 0x00000100
+-#define IF_MASK 0x00000200
+-#define IOPL_MASK 0x00003000
+-#define NT_MASK 0x00004000
++#include <asm/processor-flags.h>
++
+ #ifdef CONFIG_VM86
+-#define VM_MASK 0x00020000
++#define X86_VM_MASK X86_EFLAGS_VM
+ #else
+-#define VM_MASK 0 /* ignored */
++#define X86_VM_MASK 0 /* No VM86 support */
+ #endif
+-#define AC_MASK 0x00040000
+-#define VIF_MASK 0x00080000 /* virtual interrupt flag */
+-#define VIP_MASK 0x00100000 /* virtual interrupt pending */
+-#define ID_MASK 0x00200000
+
+ #define BIOSSEG 0x0f000
+
+@@ -42,9 +36,11 @@
+ #define VM86_ARG(retval) ((retval) >> 8)
+
+ #define VM86_SIGNAL 0 /* return due to signal */
+-#define VM86_UNKNOWN 1 /* unhandled GP fault - IO-instruction or similar */
++#define VM86_UNKNOWN 1 /* unhandled GP fault
++ - IO-instruction or similar */
+ #define VM86_INTx 2 /* int3/int x instruction (ARG = x) */
+-#define VM86_STI 3 /* sti/popf/iret instruction enabled virtual interrupts */
++#define VM86_STI 3 /* sti/popf/iret instruction enabled
++ virtual interrupts */
+
+ /*
+ * Additional return values when invoking new vm86()
+@@ -205,7 +201,8 @@ void release_vm86_irqs(struct task_struct *);
+ #define handle_vm86_fault(a, b)
+ #define release_vm86_irqs(a)
+
+-static inline int handle_vm86_trap(struct kernel_vm86_regs *a, long b, int c) {
++static inline int handle_vm86_trap(struct kernel_vm86_regs *a, long b, int c)
++{
+ return 0;
+ }
+
+diff --git a/include/asm-x86/vmi.h b/include/asm-x86/vmi.h
+index eb8bd89..b7c0dea 100644
+--- a/include/asm-x86/vmi.h
++++ b/include/asm-x86/vmi.h
+@@ -155,9 +155,9 @@
+
+ #ifndef __ASSEMBLY__
+ struct vmi_relocation_info {
+- unsigned char *eip;
+- unsigned char type;
+- unsigned char reserved[3];
++ unsigned char *eip;
++ unsigned char type;
++ unsigned char reserved[3];
+ };
+ #endif
+
+@@ -173,53 +173,53 @@ struct vmi_relocation_info {
+ #ifndef __ASSEMBLY__
+
+ struct vrom_header {
+- u16 rom_signature; // option ROM signature
+- u8 rom_length; // ROM length in 512 byte chunks
+- u8 rom_entry[4]; // 16-bit code entry point
+- u8 rom_pad0; // 4-byte align pad
+- u32 vrom_signature; // VROM identification signature
+- u8 api_version_min;// Minor version of API
+- u8 api_version_maj;// Major version of API
+- u8 jump_slots; // Number of jump slots
+- u8 reserved1; // Reserved for expansion
+- u32 virtual_top; // Hypervisor virtual address start
+- u16 reserved2; // Reserved for expansion
+- u16 license_offs; // Offset to License string
+- u16 pci_header_offs;// Offset to PCI OPROM header
+- u16 pnp_header_offs;// Offset to PnP OPROM header
+- u32 rom_pad3; // PnP reserverd / VMI reserved
+- u8 reserved[96]; // Reserved for headers
+- char vmi_init[8]; // VMI_Init jump point
+- char get_reloc[8]; // VMI_GetRelocationInfo jump point
++ u16 rom_signature; /* option ROM signature */
++ u8 rom_length; /* ROM length in 512 byte chunks */
++ u8 rom_entry[4]; /* 16-bit code entry point */
++ u8 rom_pad0; /* 4-byte align pad */
++ u32 vrom_signature; /* VROM identification signature */
++ u8 api_version_min;/* Minor version of API */
++ u8 api_version_maj;/* Major version of API */
++ u8 jump_slots; /* Number of jump slots */
++ u8 reserved1; /* Reserved for expansion */
++ u32 virtual_top; /* Hypervisor virtual address start */
++ u16 reserved2; /* Reserved for expansion */
++ u16 license_offs; /* Offset to License string */
++ u16 pci_header_offs;/* Offset to PCI OPROM header */
++ u16 pnp_header_offs;/* Offset to PnP OPROM header */
++ u32 rom_pad3; /* PnP reserverd / VMI reserved */
++ u8 reserved[96]; /* Reserved for headers */
++ char vmi_init[8]; /* VMI_Init jump point */
++ char get_reloc[8]; /* VMI_GetRelocationInfo jump point */
+ } __attribute__((packed));
+
+ struct pnp_header {
+- char sig[4];
+- char rev;
+- char size;
+- short next;
+- short res;
+- long devID;
+- unsigned short manufacturer_offset;
+- unsigned short product_offset;
++ char sig[4];
++ char rev;
++ char size;
++ short next;
++ short res;
++ long devID;
++ unsigned short manufacturer_offset;
++ unsigned short product_offset;
+ } __attribute__((packed));
+
+ struct pci_header {
+- char sig[4];
+- short vendorID;
+- short deviceID;
+- short vpdData;
+- short size;
+- char rev;
+- char class;
+- char subclass;
+- char interface;
+- short chunks;
+- char rom_version_min;
+- char rom_version_maj;
+- char codetype;
+- char lastRom;
+- short reserved;
++ char sig[4];
++ short vendorID;
++ short deviceID;
++ short vpdData;
++ short size;
++ char rev;
++ char class;
++ char subclass;
++ char interface;
++ short chunks;
++ char rom_version_min;
++ char rom_version_maj;
++ char codetype;
++ char lastRom;
++ short reserved;
+ } __attribute__((packed));
+
+ /* Function prototypes for bootstrapping */
+diff --git a/include/asm-x86/voyager.h b/include/asm-x86/voyager.h
+index 91a9932..9c811d2 100644
+--- a/include/asm-x86/voyager.h
++++ b/include/asm-x86/voyager.h
+@@ -91,8 +91,7 @@
+ #define VOYAGER_WRITE_CONFIG 0x2
+ #define VOYAGER_BYPASS 0xff
+
+-typedef struct voyager_asic
+-{
++typedef struct voyager_asic {
+ __u8 asic_addr; /* ASIC address; Level 4 */
+ __u8 asic_type; /* ASIC type */
+ __u8 asic_id; /* ASIC id */
+@@ -113,7 +112,7 @@ typedef struct voyager_module {
+ __u16 largest_reg; /* Largest register in the scan path */
+ __u16 smallest_reg; /* Smallest register in the scan path */
+ voyager_asic_t *asic; /* First ASIC in scan path (CAT_I) */
+- struct voyager_module *submodule; /* Submodule pointer */
++ struct voyager_module *submodule; /* Submodule pointer */
+ struct voyager_module *next; /* Next module in linked list */
+ } voyager_module_t;
+
+@@ -135,7 +134,7 @@ typedef struct voyager_eeprom_hdr {
+ __u16 cct_offset;
+ __u16 log_length; /* length of err log */
+ __u16 xsum_end; /* offset to end of
+- checksum */
++ checksum */
+ __u8 reserved[4];
+ __u8 sflag; /* starting sentinal */
+ __u8 part_number[13]; /* prom part number */
+@@ -148,7 +147,8 @@ typedef struct voyager_eeprom_hdr {
+
+
+
+-#define VOYAGER_EPROM_SIZE_OFFSET ((__u16)(&(((voyager_eprom_hdr_t *)0)->ee_size)))
++#define VOYAGER_EPROM_SIZE_OFFSET \
++ ((__u16)(&(((voyager_eprom_hdr_t *)0)->ee_size)))
+ #define VOYAGER_XSUM_END_OFFSET 0x2a
+
+ /* the following three definitions are for internal table layouts
+@@ -199,7 +199,7 @@ typedef struct voyager_asic_data_table {
+ #define VOYAGER_WCBIC_TOM_L 0x4
+ #define VOYAGER_WCBIC_TOM_H 0x5
+
+-/* register defines for Voyager Memory Contol (VMC)
++/* register defines for Voyager Memory Contol (VMC)
+ * these are present on L4 machines only */
+ #define VOYAGER_VMC1 0x81
+ #define VOYAGER_VMC2 0x91
+@@ -334,7 +334,7 @@ typedef struct {
+
+ struct QuadDescription {
+ __u8 Type; /* for type 0 (DYADIC or MONADIC) all fields
+- * will be zero except for slot */
++ * will be zero except for slot */
+ __u8 StructureVersion;
+ __u32 CPI_BaseAddress;
+ __u32 LARC_BankSize;
+@@ -342,7 +342,7 @@ struct QuadDescription {
+ __u8 Slot; /* Processor slots 1 - 4 */
+ } __attribute__((packed));
+
+-struct ProcBoardInfo {
++struct ProcBoardInfo {
+ __u8 Type;
+ __u8 StructureVersion;
+ __u8 NumberOfBoards;
+@@ -382,19 +382,30 @@ struct CPU_Info {
+ * packed in it by our friend the compiler.
+ */
+ typedef struct {
+- __u8 Mailbox_SUS; /* Written to by SUS to give commands/response to the OS */
+- __u8 Mailbox_OS; /* Written to by the OS to give commands/response to SUS */
+- __u8 SUS_MailboxVersion; /* Tells the OS which iteration of the interface SUS supports */
+- __u8 OS_MailboxVersion; /* Tells SUS which iteration of the interface the OS supports */
+- __u32 OS_Flags; /* Flags set by the OS as info for SUS */
+- __u32 SUS_Flags; /* Flags set by SUS as info for the OS */
+- __u32 WatchDogPeriod; /* Watchdog period (in seconds) which the DP uses to see if the OS is dead */
++ __u8 Mailbox_SUS; /* Written to by SUS to give
++ commands/response to the OS */
++ __u8 Mailbox_OS; /* Written to by the OS to give
++ commands/response to SUS */
++ __u8 SUS_MailboxVersion; /* Tells the OS which iteration of the
++ interface SUS supports */
++ __u8 OS_MailboxVersion; /* Tells SUS which iteration of the
++ interface the OS supports */
++ __u32 OS_Flags; /* Flags set by the OS as info for
++ SUS */
++ __u32 SUS_Flags; /* Flags set by SUS as info
++ for the OS */
++ __u32 WatchDogPeriod; /* Watchdog period (in seconds) which
++ the DP uses to see if the OS
++ is dead */
+ __u32 WatchDogCount; /* Updated by the OS on every tic. */
+- __u32 MemoryFor_SUS_ErrorLog; /* Flat 32 bit address which tells SUS where to stuff the SUS error log on a dump */
+- MC_SlotInformation_t MC_SlotInfo[NUMBER_OF_MC_BUSSES*SLOTS_PER_MC_BUS]; /* Storage for MCA POS data */
++ __u32 MemoryFor_SUS_ErrorLog; /* Flat 32 bit address which tells SUS
++ where to stuff the SUS error log
++ on a dump */
++ MC_SlotInformation_t MC_SlotInfo[NUMBER_OF_MC_BUSSES*SLOTS_PER_MC_BUS];
++ /* Storage for MCA POS data */
+ /* All new SECOND_PASS_INTERFACE fields added from this point */
+- struct ProcBoardInfo *BoardData;
+- struct CPU_Info *CPU_Data;
++ struct ProcBoardInfo *BoardData;
++ struct CPU_Info *CPU_Data;
+ /* All new fields must be added from this point */
+ } Voyager_KernelSUS_Mbox_t;
+
+@@ -478,7 +489,7 @@ struct voyager_SUS {
+ __u32 SUS_errorlog;
+ /* lots of system configuration stuff under here */
+ };
+-
++
+ /* Variables exported by voyager_smp */
+ extern __u32 voyager_extended_vic_processors;
+ extern __u32 voyager_allowed_boot_processors;
+diff --git a/include/asm-x86/xen/events.h b/include/asm-x86/xen/events.h
+new file mode 100644
+index 0000000..596312a
+--- /dev/null
++++ b/include/asm-x86/xen/events.h
+@@ -0,0 +1,22 @@
++#ifndef __XEN_EVENTS_H
++#define __XEN_EVENTS_H
++
++enum ipi_vector {
++ XEN_RESCHEDULE_VECTOR,
++ XEN_CALL_FUNCTION_VECTOR,
++
++ XEN_NR_IPIS,
++};
++
++static inline int xen_irqs_disabled(struct pt_regs *regs)
++{
++ return raw_irqs_disabled_flags(regs->flags);
++}
++
++static inline void xen_do_IRQ(int irq, struct pt_regs *regs)
++{
++ regs->orig_ax = ~irq;
++ do_IRQ(regs);
++}
++
++#endif /* __XEN_EVENTS_H */
+diff --git a/include/asm-x86/xen/grant_table.h b/include/asm-x86/xen/grant_table.h
+new file mode 100644
+index 0000000..2444d45
+--- /dev/null
++++ b/include/asm-x86/xen/grant_table.h
+@@ -0,0 +1,7 @@
++#ifndef __XEN_GRANT_TABLE_H
++#define __XEN_GRANT_TABLE_H
++
++#define xen_alloc_vm_area(size) alloc_vm_area(size)
++#define xen_free_vm_area(area) free_vm_area(area)
++
++#endif /* __XEN_GRANT_TABLE_H */
+diff --git a/include/asm-x86/xen/hypercall.h b/include/asm-x86/xen/hypercall.h
+index bc0ee7d..c2ccd99 100644
+--- a/include/asm-x86/xen/hypercall.h
++++ b/include/asm-x86/xen/hypercall.h
+@@ -164,6 +164,12 @@ HYPERVISOR_set_callbacks(unsigned long event_selector,
+ }
+
+ static inline int
++HYPERVISOR_callback_op(int cmd, void *arg)
++{
++ return _hypercall2(int, callback_op, cmd, arg);
++}
++
++static inline int
+ HYPERVISOR_fpu_taskswitch(int set)
+ {
+ return _hypercall1(int, fpu_taskswitch, set);
+diff --git a/include/asm-x86/xen/interface.h b/include/asm-x86/xen/interface.h
+index 165c396..6227000 100644
+--- a/include/asm-x86/xen/interface.h
++++ b/include/asm-x86/xen/interface.h
+@@ -22,6 +22,30 @@
+ #define DEFINE_GUEST_HANDLE(name) __DEFINE_GUEST_HANDLE(name, name)
+ #define GUEST_HANDLE(name) __guest_handle_ ## name
+
++#ifdef __XEN__
++#if defined(__i386__)
++#define set_xen_guest_handle(hnd, val) \
++ do { \
++ if (sizeof(hnd) == 8) \
++ *(uint64_t *)&(hnd) = 0; \
++ (hnd).p = val; \
++ } while (0)
++#elif defined(__x86_64__)
++#define set_xen_guest_handle(hnd, val) do { (hnd).p = val; } while (0)
++#endif
++#else
++#if defined(__i386__)
++#define set_xen_guest_handle(hnd, val) \
++ do { \
++ if (sizeof(hnd) == 8) \
++ *(uint64_t *)&(hnd) = 0; \
++ (hnd) = val; \
++ } while (0)
++#elif defined(__x86_64__)
++#define set_xen_guest_handle(hnd, val) do { (hnd) = val; } while (0)
++#endif
++#endif
++
+ #ifndef __ASSEMBLY__
+ /* Guest handles for primitive C types. */
+ __DEFINE_GUEST_HANDLE(uchar, unsigned char);
+@@ -171,6 +195,10 @@ struct arch_vcpu_info {
+ unsigned long pad[5]; /* sizeof(struct vcpu_info) == 64 */
+ };
+
++struct xen_callback {
++ unsigned long cs;
++ unsigned long eip;
++};
+ #endif /* !__ASSEMBLY__ */
+
+ /*
+diff --git a/include/asm-x86/xen/page.h b/include/asm-x86/xen/page.h
+new file mode 100644
+index 0000000..0179930
+--- /dev/null
++++ b/include/asm-x86/xen/page.h
+@@ -0,0 +1,168 @@
++#ifndef __XEN_PAGE_H
++#define __XEN_PAGE_H
++
++#include <linux/pfn.h>
++
++#include <asm/uaccess.h>
++#include <asm/pgtable.h>
++
++#include <xen/features.h>
++
++/* Xen machine address */
++typedef struct xmaddr {
++ phys_addr_t maddr;
++} xmaddr_t;
++
++/* Xen pseudo-physical address */
++typedef struct xpaddr {
++ phys_addr_t paddr;
++} xpaddr_t;
++
++#define XMADDR(x) ((xmaddr_t) { .maddr = (x) })
++#define XPADDR(x) ((xpaddr_t) { .paddr = (x) })
++
++/**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
++#define INVALID_P2M_ENTRY (~0UL)
++#define FOREIGN_FRAME_BIT (1UL<<31)
++#define FOREIGN_FRAME(m) ((m) | FOREIGN_FRAME_BIT)
++
++extern unsigned long *phys_to_machine_mapping;
++
++static inline unsigned long pfn_to_mfn(unsigned long pfn)
++{
++ if (xen_feature(XENFEAT_auto_translated_physmap))
++ return pfn;
++
++ return phys_to_machine_mapping[(unsigned int)(pfn)] &
++ ~FOREIGN_FRAME_BIT;
++}
++
++static inline int phys_to_machine_mapping_valid(unsigned long pfn)
++{
++ if (xen_feature(XENFEAT_auto_translated_physmap))
++ return 1;
++
++ return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
++}
++
++static inline unsigned long mfn_to_pfn(unsigned long mfn)
++{
++ unsigned long pfn;
++
++ if (xen_feature(XENFEAT_auto_translated_physmap))
++ return mfn;
++
++#if 0
++ if (unlikely((mfn >> machine_to_phys_order) != 0))
++ return max_mapnr;
++#endif
++
++ pfn = 0;
++ /*
++ * The array access can fail (e.g., device space beyond end of RAM).
++ * In such cases it doesn't matter what we return (we return garbage),
++ * but we must handle the fault without crashing!
++ */
++ __get_user(pfn, &machine_to_phys_mapping[mfn]);
++
++ return pfn;
++}
++
++static inline xmaddr_t phys_to_machine(xpaddr_t phys)
++{
++ unsigned offset = phys.paddr & ~PAGE_MASK;
++ return XMADDR(PFN_PHYS((u64)pfn_to_mfn(PFN_DOWN(phys.paddr))) | offset);
++}
++
++static inline xpaddr_t machine_to_phys(xmaddr_t machine)
++{
++ unsigned offset = machine.maddr & ~PAGE_MASK;
++ return XPADDR(PFN_PHYS((u64)mfn_to_pfn(PFN_DOWN(machine.maddr))) | offset);
++}
++
++/*
++ * We detect special mappings in one of two ways:
++ * 1. If the MFN is an I/O page then Xen will set the m2p entry
++ * to be outside our maximum possible pseudophys range.
++ * 2. If the MFN belongs to a different domain then we will certainly
++ * not have MFN in our p2m table. Conversely, if the page is ours,
++ * then we'll have p2m(m2p(MFN))==MFN.
++ * If we detect a special mapping then it doesn't have a 'struct page'.
++ * We force !pfn_valid() by returning an out-of-range pointer.
++ *
++ * NB. These checks require that, for any MFN that is not in our reservation,
++ * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if
++ * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN.
++ * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety.
++ *
++ * NB2. When deliberately mapping foreign pages into the p2m table, you *must*
++ * use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we
++ * require. In all the cases we care about, the FOREIGN_FRAME bit is
++ * masked (e.g., pfn_to_mfn()) so behaviour there is correct.
++ */
++static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
++{
++ extern unsigned long max_mapnr;
++ unsigned long pfn = mfn_to_pfn(mfn);
++ if ((pfn < max_mapnr)
++ && !xen_feature(XENFEAT_auto_translated_physmap)
++ && (phys_to_machine_mapping[pfn] != mfn))
++ return max_mapnr; /* force !pfn_valid() */
++ return pfn;
++}
++
++static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
++{
++ if (xen_feature(XENFEAT_auto_translated_physmap)) {
++ BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
++ return;
++ }
++ phys_to_machine_mapping[pfn] = mfn;
++}
++
++/* VIRT <-> MACHINE conversion */
++#define virt_to_machine(v) (phys_to_machine(XPADDR(__pa(v))))
++#define virt_to_mfn(v) (pfn_to_mfn(PFN_DOWN(__pa(v))))
++#define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT))
++
++static inline unsigned long pte_mfn(pte_t pte)
++{
++ return (pte.pte & ~_PAGE_NX) >> PAGE_SHIFT;
++}
++
++static inline pte_t mfn_pte(unsigned long page_nr, pgprot_t pgprot)
++{
++ pte_t pte;
++
++ pte.pte = ((phys_addr_t)page_nr << PAGE_SHIFT) |
++ (pgprot_val(pgprot) & __supported_pte_mask);
++
++ return pte;
++}
++
++static inline pteval_t pte_val_ma(pte_t pte)
++{
++ return pte.pte;
++}
++
++static inline pte_t __pte_ma(pteval_t x)
++{
++ return (pte_t) { .pte = x };
++}
++
++#ifdef CONFIG_X86_PAE
++#define pmd_val_ma(v) ((v).pmd)
++#define pud_val_ma(v) ((v).pgd.pgd)
++#define __pmd_ma(x) ((pmd_t) { (x) } )
++#else /* !X86_PAE */
++#define pmd_val_ma(v) ((v).pud.pgd.pgd)
++#endif /* CONFIG_X86_PAE */
++
++#define pgd_val_ma(x) ((x).pgd)
++
++
++xmaddr_t arbitrary_virt_to_machine(unsigned long address);
++void make_lowmem_page_readonly(void *vaddr);
++void make_lowmem_page_readwrite(void *vaddr);
++
++#endif /* __XEN_PAGE_H */
+diff --git a/include/asm-x86/xor_32.h b/include/asm-x86/xor_32.h
+index a41ef1b..067b5c1 100644
+--- a/include/asm-x86/xor_32.h
++++ b/include/asm-x86/xor_32.h
+@@ -16,12 +16,12 @@
+ * Copyright (C) 1998 Ingo Molnar.
+ */
+
+-#define LD(x,y) " movq 8*("#x")(%1), %%mm"#y" ;\n"
+-#define ST(x,y) " movq %%mm"#y", 8*("#x")(%1) ;\n"
+-#define XO1(x,y) " pxor 8*("#x")(%2), %%mm"#y" ;\n"
+-#define XO2(x,y) " pxor 8*("#x")(%3), %%mm"#y" ;\n"
+-#define XO3(x,y) " pxor 8*("#x")(%4), %%mm"#y" ;\n"
+-#define XO4(x,y) " pxor 8*("#x")(%5), %%mm"#y" ;\n"
++#define LD(x, y) " movq 8*("#x")(%1), %%mm"#y" ;\n"
++#define ST(x, y) " movq %%mm"#y", 8*("#x")(%1) ;\n"
++#define XO1(x, y) " pxor 8*("#x")(%2), %%mm"#y" ;\n"
++#define XO2(x, y) " pxor 8*("#x")(%3), %%mm"#y" ;\n"
++#define XO3(x, y) " pxor 8*("#x")(%4), %%mm"#y" ;\n"
++#define XO4(x, y) " pxor 8*("#x")(%5), %%mm"#y" ;\n"
+
+ #include <asm/i387.h>
+
+@@ -32,24 +32,24 @@ xor_pII_mmx_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
+
+ kernel_fpu_begin();
+
+- __asm__ __volatile__ (
++ asm volatile(
+ #undef BLOCK
+-#define BLOCK(i) \
+- LD(i,0) \
+- LD(i+1,1) \
+- LD(i+2,2) \
+- LD(i+3,3) \
+- XO1(i,0) \
+- ST(i,0) \
+- XO1(i+1,1) \
+- ST(i+1,1) \
+- XO1(i+2,2) \
+- ST(i+2,2) \
+- XO1(i+3,3) \
+- ST(i+3,3)
++#define BLOCK(i) \
++ LD(i, 0) \
++ LD(i + 1, 1) \
++ LD(i + 2, 2) \
++ LD(i + 3, 3) \
++ XO1(i, 0) \
++ ST(i, 0) \
++ XO1(i+1, 1) \
++ ST(i+1, 1) \
++ XO1(i + 2, 2) \
++ ST(i + 2, 2) \
++ XO1(i + 3, 3) \
++ ST(i + 3, 3)
+
+ " .align 32 ;\n"
+- " 1: ;\n"
++ " 1: ;\n"
+
+ BLOCK(0)
+ BLOCK(4)
+@@ -76,25 +76,25 @@ xor_pII_mmx_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+
+ kernel_fpu_begin();
+
+- __asm__ __volatile__ (
++ asm volatile(
+ #undef BLOCK
+-#define BLOCK(i) \
+- LD(i,0) \
+- LD(i+1,1) \
+- LD(i+2,2) \
+- LD(i+3,3) \
+- XO1(i,0) \
+- XO1(i+1,1) \
+- XO1(i+2,2) \
+- XO1(i+3,3) \
+- XO2(i,0) \
+- ST(i,0) \
+- XO2(i+1,1) \
+- ST(i+1,1) \
+- XO2(i+2,2) \
+- ST(i+2,2) \
+- XO2(i+3,3) \
+- ST(i+3,3)
++#define BLOCK(i) \
++ LD(i, 0) \
++ LD(i + 1, 1) \
++ LD(i + 2, 2) \
++ LD(i + 3, 3) \
++ XO1(i, 0) \
++ XO1(i + 1, 1) \
++ XO1(i + 2, 2) \
++ XO1(i + 3, 3) \
++ XO2(i, 0) \
++ ST(i, 0) \
++ XO2(i + 1, 1) \
++ ST(i + 1, 1) \
++ XO2(i + 2, 2) \
++ ST(i + 2, 2) \
++ XO2(i + 3, 3) \
++ ST(i + 3, 3)
+
+ " .align 32 ;\n"
+ " 1: ;\n"
+@@ -125,29 +125,29 @@ xor_pII_mmx_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+
+ kernel_fpu_begin();
+
+- __asm__ __volatile__ (
++ asm volatile(
+ #undef BLOCK
+-#define BLOCK(i) \
+- LD(i,0) \
+- LD(i+1,1) \
+- LD(i+2,2) \
+- LD(i+3,3) \
+- XO1(i,0) \
+- XO1(i+1,1) \
+- XO1(i+2,2) \
+- XO1(i+3,3) \
+- XO2(i,0) \
+- XO2(i+1,1) \
+- XO2(i+2,2) \
+- XO2(i+3,3) \
+- XO3(i,0) \
+- ST(i,0) \
+- XO3(i+1,1) \
+- ST(i+1,1) \
+- XO3(i+2,2) \
+- ST(i+2,2) \
+- XO3(i+3,3) \
+- ST(i+3,3)
++#define BLOCK(i) \
++ LD(i, 0) \
++ LD(i + 1, 1) \
++ LD(i + 2, 2) \
++ LD(i + 3, 3) \
++ XO1(i, 0) \
++ XO1(i + 1, 1) \
++ XO1(i + 2, 2) \
++ XO1(i + 3, 3) \
++ XO2(i, 0) \
++ XO2(i + 1, 1) \
++ XO2(i + 2, 2) \
++ XO2(i + 3, 3) \
++ XO3(i, 0) \
++ ST(i, 0) \
++ XO3(i + 1, 1) \
++ ST(i + 1, 1) \
++ XO3(i + 2, 2) \
++ ST(i + 2, 2) \
++ XO3(i + 3, 3) \
++ ST(i + 3, 3)
+
+ " .align 32 ;\n"
+ " 1: ;\n"
+@@ -186,35 +186,35 @@ xor_pII_mmx_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ because we modify p4 and p5 there, but we can't mark them
+ as read/write, otherwise we'd overflow the 10-asm-operands
+ limit of GCC < 3.1. */
+- __asm__ ("" : "+r" (p4), "+r" (p5));
++ asm("" : "+r" (p4), "+r" (p5));
+
+- __asm__ __volatile__ (
++ asm volatile(
+ #undef BLOCK
+-#define BLOCK(i) \
+- LD(i,0) \
+- LD(i+1,1) \
+- LD(i+2,2) \
+- LD(i+3,3) \
+- XO1(i,0) \
+- XO1(i+1,1) \
+- XO1(i+2,2) \
+- XO1(i+3,3) \
+- XO2(i,0) \
+- XO2(i+1,1) \
+- XO2(i+2,2) \
+- XO2(i+3,3) \
+- XO3(i,0) \
+- XO3(i+1,1) \
+- XO3(i+2,2) \
+- XO3(i+3,3) \
+- XO4(i,0) \
+- ST(i,0) \
+- XO4(i+1,1) \
+- ST(i+1,1) \
+- XO4(i+2,2) \
+- ST(i+2,2) \
+- XO4(i+3,3) \
+- ST(i+3,3)
++#define BLOCK(i) \
++ LD(i, 0) \
++ LD(i + 1, 1) \
++ LD(i + 2, 2) \
++ LD(i + 3, 3) \
++ XO1(i, 0) \
++ XO1(i + 1, 1) \
++ XO1(i + 2, 2) \
++ XO1(i + 3, 3) \
++ XO2(i, 0) \
++ XO2(i + 1, 1) \
++ XO2(i + 2, 2) \
++ XO2(i + 3, 3) \
++ XO3(i, 0) \
++ XO3(i + 1, 1) \
++ XO3(i + 2, 2) \
++ XO3(i + 3, 3) \
++ XO4(i, 0) \
++ ST(i, 0) \
++ XO4(i + 1, 1) \
++ ST(i + 1, 1) \
++ XO4(i + 2, 2) \
++ ST(i + 2, 2) \
++ XO4(i + 3, 3) \
++ ST(i + 3, 3)
+
+ " .align 32 ;\n"
+ " 1: ;\n"
+@@ -233,13 +233,13 @@ xor_pII_mmx_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ " jnz 1b ;\n"
+ : "+r" (lines),
+ "+r" (p1), "+r" (p2), "+r" (p3)
+- : "r" (p4), "r" (p5)
++ : "r" (p4), "r" (p5)
+ : "memory");
+
+ /* p4 and p5 were modified, and now the variables are dead.
+ Clobber them just to be sure nobody does something stupid
+ like assuming they have some legal value. */
+- __asm__ ("" : "=r" (p4), "=r" (p5));
++ asm("" : "=r" (p4), "=r" (p5));
+
+ kernel_fpu_end();
+ }
+@@ -259,7 +259,7 @@ xor_p5_mmx_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
+
+ kernel_fpu_begin();
+
+- __asm__ __volatile__ (
++ asm volatile(
+ " .align 32 ;\n"
+ " 1: ;\n"
+ " movq (%1), %%mm0 ;\n"
+@@ -286,7 +286,7 @@ xor_p5_mmx_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
+ " pxor 56(%2), %%mm7 ;\n"
+ " movq %%mm6, 48(%1) ;\n"
+ " movq %%mm7, 56(%1) ;\n"
+-
++
+ " addl $64, %1 ;\n"
+ " addl $64, %2 ;\n"
+ " decl %0 ;\n"
+@@ -307,7 +307,7 @@ xor_p5_mmx_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+
+ kernel_fpu_begin();
+
+- __asm__ __volatile__ (
++ asm volatile(
+ " .align 32,0x90 ;\n"
+ " 1: ;\n"
+ " movq (%1), %%mm0 ;\n"
+@@ -342,7 +342,7 @@ xor_p5_mmx_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ " pxor 56(%3), %%mm7 ;\n"
+ " movq %%mm6, 48(%1) ;\n"
+ " movq %%mm7, 56(%1) ;\n"
+-
++
+ " addl $64, %1 ;\n"
+ " addl $64, %2 ;\n"
+ " addl $64, %3 ;\n"
+@@ -364,7 +364,7 @@ xor_p5_mmx_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+
+ kernel_fpu_begin();
+
+- __asm__ __volatile__ (
++ asm volatile(
+ " .align 32,0x90 ;\n"
+ " 1: ;\n"
+ " movq (%1), %%mm0 ;\n"
+@@ -407,7 +407,7 @@ xor_p5_mmx_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ " pxor 56(%4), %%mm7 ;\n"
+ " movq %%mm6, 48(%1) ;\n"
+ " movq %%mm7, 56(%1) ;\n"
+-
++
+ " addl $64, %1 ;\n"
+ " addl $64, %2 ;\n"
+ " addl $64, %3 ;\n"
+@@ -436,9 +436,9 @@ xor_p5_mmx_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ because we modify p4 and p5 there, but we can't mark them
+ as read/write, otherwise we'd overflow the 10-asm-operands
+ limit of GCC < 3.1. */
+- __asm__ ("" : "+r" (p4), "+r" (p5));
++ asm("" : "+r" (p4), "+r" (p5));
+
+- __asm__ __volatile__ (
++ asm volatile(
+ " .align 32,0x90 ;\n"
+ " 1: ;\n"
+ " movq (%1), %%mm0 ;\n"
+@@ -489,7 +489,7 @@ xor_p5_mmx_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ " pxor 56(%5), %%mm7 ;\n"
+ " movq %%mm6, 48(%1) ;\n"
+ " movq %%mm7, 56(%1) ;\n"
+-
++
+ " addl $64, %1 ;\n"
+ " addl $64, %2 ;\n"
+ " addl $64, %3 ;\n"
+@@ -505,7 +505,7 @@ xor_p5_mmx_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ /* p4 and p5 were modified, and now the variables are dead.
+ Clobber them just to be sure nobody does something stupid
+ like assuming they have some legal value. */
+- __asm__ ("" : "=r" (p4), "=r" (p5));
++ asm("" : "=r" (p4), "=r" (p5));
+
+ kernel_fpu_end();
+ }
+@@ -531,11 +531,12 @@ static struct xor_block_template xor_block_p5_mmx = {
+ * Copyright (C) 1999 Zach Brown (with obvious credit due Ingo)
+ */
+
+-#define XMMS_SAVE do { \
++#define XMMS_SAVE \
++do { \
+ preempt_disable(); \
+ cr0 = read_cr0(); \
+ clts(); \
+- __asm__ __volatile__ ( \
++ asm volatile( \
+ "movups %%xmm0,(%0) ;\n\t" \
+ "movups %%xmm1,0x10(%0) ;\n\t" \
+ "movups %%xmm2,0x20(%0) ;\n\t" \
+@@ -543,10 +544,11 @@ static struct xor_block_template xor_block_p5_mmx = {
+ : \
+ : "r" (xmm_save) \
+ : "memory"); \
+-} while(0)
++} while (0)
+
+-#define XMMS_RESTORE do { \
+- __asm__ __volatile__ ( \
++#define XMMS_RESTORE \
++do { \
++ asm volatile( \
+ "sfence ;\n\t" \
+ "movups (%0),%%xmm0 ;\n\t" \
+ "movups 0x10(%0),%%xmm1 ;\n\t" \
+@@ -557,76 +559,76 @@ static struct xor_block_template xor_block_p5_mmx = {
+ : "memory"); \
+ write_cr0(cr0); \
+ preempt_enable(); \
+-} while(0)
++} while (0)
+
+ #define ALIGN16 __attribute__((aligned(16)))
+
+ #define OFFS(x) "16*("#x")"
+ #define PF_OFFS(x) "256+16*("#x")"
+ #define PF0(x) " prefetchnta "PF_OFFS(x)"(%1) ;\n"
+-#define LD(x,y) " movaps "OFFS(x)"(%1), %%xmm"#y" ;\n"
+-#define ST(x,y) " movaps %%xmm"#y", "OFFS(x)"(%1) ;\n"
++#define LD(x, y) " movaps "OFFS(x)"(%1), %%xmm"#y" ;\n"
++#define ST(x, y) " movaps %%xmm"#y", "OFFS(x)"(%1) ;\n"
+ #define PF1(x) " prefetchnta "PF_OFFS(x)"(%2) ;\n"
+ #define PF2(x) " prefetchnta "PF_OFFS(x)"(%3) ;\n"
+ #define PF3(x) " prefetchnta "PF_OFFS(x)"(%4) ;\n"
+ #define PF4(x) " prefetchnta "PF_OFFS(x)"(%5) ;\n"
+ #define PF5(x) " prefetchnta "PF_OFFS(x)"(%6) ;\n"
+-#define XO1(x,y) " xorps "OFFS(x)"(%2), %%xmm"#y" ;\n"
+-#define XO2(x,y) " xorps "OFFS(x)"(%3), %%xmm"#y" ;\n"
+-#define XO3(x,y) " xorps "OFFS(x)"(%4), %%xmm"#y" ;\n"
+-#define XO4(x,y) " xorps "OFFS(x)"(%5), %%xmm"#y" ;\n"
+-#define XO5(x,y) " xorps "OFFS(x)"(%6), %%xmm"#y" ;\n"
++#define XO1(x, y) " xorps "OFFS(x)"(%2), %%xmm"#y" ;\n"
++#define XO2(x, y) " xorps "OFFS(x)"(%3), %%xmm"#y" ;\n"
++#define XO3(x, y) " xorps "OFFS(x)"(%4), %%xmm"#y" ;\n"
++#define XO4(x, y) " xorps "OFFS(x)"(%5), %%xmm"#y" ;\n"
++#define XO5(x, y) " xorps "OFFS(x)"(%6), %%xmm"#y" ;\n"
+
+
+ static void
+ xor_sse_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
+ {
+- unsigned long lines = bytes >> 8;
++ unsigned long lines = bytes >> 8;
+ char xmm_save[16*4] ALIGN16;
+ int cr0;
+
+ XMMS_SAVE;
+
+- __asm__ __volatile__ (
++ asm volatile(
+ #undef BLOCK
+-#define BLOCK(i) \
+- LD(i,0) \
+- LD(i+1,1) \
++#define BLOCK(i) \
++ LD(i, 0) \
++ LD(i + 1, 1) \
+ PF1(i) \
+- PF1(i+2) \
+- LD(i+2,2) \
+- LD(i+3,3) \
+- PF0(i+4) \
+- PF0(i+6) \
+- XO1(i,0) \
+- XO1(i+1,1) \
+- XO1(i+2,2) \
+- XO1(i+3,3) \
+- ST(i,0) \
+- ST(i+1,1) \
+- ST(i+2,2) \
+- ST(i+3,3) \
++ PF1(i + 2) \
++ LD(i + 2, 2) \
++ LD(i + 3, 3) \
++ PF0(i + 4) \
++ PF0(i + 6) \
++ XO1(i, 0) \
++ XO1(i + 1, 1) \
++ XO1(i + 2, 2) \
++ XO1(i + 3, 3) \
++ ST(i, 0) \
++ ST(i + 1, 1) \
++ ST(i + 2, 2) \
++ ST(i + 3, 3) \
+
+
+ PF0(0)
+ PF0(2)
+
+ " .align 32 ;\n"
+- " 1: ;\n"
++ " 1: ;\n"
+
+ BLOCK(0)
+ BLOCK(4)
+ BLOCK(8)
+ BLOCK(12)
+
+- " addl $256, %1 ;\n"
+- " addl $256, %2 ;\n"
+- " decl %0 ;\n"
+- " jnz 1b ;\n"
++ " addl $256, %1 ;\n"
++ " addl $256, %2 ;\n"
++ " decl %0 ;\n"
++ " jnz 1b ;\n"
+ : "+r" (lines),
+ "+r" (p1), "+r" (p2)
+ :
+- : "memory");
++ : "memory");
+
+ XMMS_RESTORE;
+ }
+@@ -635,59 +637,59 @@ static void
+ xor_sse_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ unsigned long *p3)
+ {
+- unsigned long lines = bytes >> 8;
++ unsigned long lines = bytes >> 8;
+ char xmm_save[16*4] ALIGN16;
+ int cr0;
+
+ XMMS_SAVE;
+
+- __asm__ __volatile__ (
++ asm volatile(
+ #undef BLOCK
+ #define BLOCK(i) \
+ PF1(i) \
+- PF1(i+2) \
++ PF1(i + 2) \
+ LD(i,0) \
+- LD(i+1,1) \
+- LD(i+2,2) \
+- LD(i+3,3) \
++ LD(i + 1, 1) \
++ LD(i + 2, 2) \
++ LD(i + 3, 3) \
+ PF2(i) \
+- PF2(i+2) \
+- PF0(i+4) \
+- PF0(i+6) \
++ PF2(i + 2) \
++ PF0(i + 4) \
++ PF0(i + 6) \
+ XO1(i,0) \
+- XO1(i+1,1) \
+- XO1(i+2,2) \
+- XO1(i+3,3) \
++ XO1(i + 1, 1) \
++ XO1(i + 2, 2) \
++ XO1(i + 3, 3) \
+ XO2(i,0) \
+- XO2(i+1,1) \
+- XO2(i+2,2) \
+- XO2(i+3,3) \
++ XO2(i + 1, 1) \
++ XO2(i + 2, 2) \
++ XO2(i + 3, 3) \
+ ST(i,0) \
+- ST(i+1,1) \
+- ST(i+2,2) \
+- ST(i+3,3) \
++ ST(i + 1, 1) \
++ ST(i + 2, 2) \
++ ST(i + 3, 3) \
+
+
+ PF0(0)
+ PF0(2)
+
+ " .align 32 ;\n"
+- " 1: ;\n"
++ " 1: ;\n"
+
+ BLOCK(0)
+ BLOCK(4)
+ BLOCK(8)
+ BLOCK(12)
+
+- " addl $256, %1 ;\n"
+- " addl $256, %2 ;\n"
+- " addl $256, %3 ;\n"
+- " decl %0 ;\n"
+- " jnz 1b ;\n"
++ " addl $256, %1 ;\n"
++ " addl $256, %2 ;\n"
++ " addl $256, %3 ;\n"
++ " decl %0 ;\n"
++ " jnz 1b ;\n"
+ : "+r" (lines),
+ "+r" (p1), "+r"(p2), "+r"(p3)
+ :
+- : "memory" );
++ : "memory" );
+
+ XMMS_RESTORE;
+ }
+@@ -696,66 +698,66 @@ static void
+ xor_sse_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ unsigned long *p3, unsigned long *p4)
+ {
+- unsigned long lines = bytes >> 8;
++ unsigned long lines = bytes >> 8;
+ char xmm_save[16*4] ALIGN16;
+ int cr0;
+
+ XMMS_SAVE;
+
+- __asm__ __volatile__ (
++ asm volatile(
+ #undef BLOCK
+ #define BLOCK(i) \
+ PF1(i) \
+- PF1(i+2) \
++ PF1(i + 2) \
+ LD(i,0) \
+- LD(i+1,1) \
+- LD(i+2,2) \
+- LD(i+3,3) \
++ LD(i + 1, 1) \
++ LD(i + 2, 2) \
++ LD(i + 3, 3) \
+ PF2(i) \
+- PF2(i+2) \
++ PF2(i + 2) \
+ XO1(i,0) \
+- XO1(i+1,1) \
+- XO1(i+2,2) \
+- XO1(i+3,3) \
++ XO1(i + 1, 1) \
++ XO1(i + 2, 2) \
++ XO1(i + 3, 3) \
+ PF3(i) \
+- PF3(i+2) \
+- PF0(i+4) \
+- PF0(i+6) \
++ PF3(i + 2) \
++ PF0(i + 4) \
++ PF0(i + 6) \
+ XO2(i,0) \
+- XO2(i+1,1) \
+- XO2(i+2,2) \
+- XO2(i+3,3) \
++ XO2(i + 1, 1) \
++ XO2(i + 2, 2) \
++ XO2(i + 3, 3) \
+ XO3(i,0) \
+- XO3(i+1,1) \
+- XO3(i+2,2) \
+- XO3(i+3,3) \
++ XO3(i + 1, 1) \
++ XO3(i + 2, 2) \
++ XO3(i + 3, 3) \
+ ST(i,0) \
+- ST(i+1,1) \
+- ST(i+2,2) \
+- ST(i+3,3) \
++ ST(i + 1, 1) \
++ ST(i + 2, 2) \
++ ST(i + 3, 3) \
+
+
+ PF0(0)
+ PF0(2)
+
+ " .align 32 ;\n"
+- " 1: ;\n"
++ " 1: ;\n"
+
+ BLOCK(0)
+ BLOCK(4)
+ BLOCK(8)
+ BLOCK(12)
+
+- " addl $256, %1 ;\n"
+- " addl $256, %2 ;\n"
+- " addl $256, %3 ;\n"
+- " addl $256, %4 ;\n"
+- " decl %0 ;\n"
+- " jnz 1b ;\n"
++ " addl $256, %1 ;\n"
++ " addl $256, %2 ;\n"
++ " addl $256, %3 ;\n"
++ " addl $256, %4 ;\n"
++ " decl %0 ;\n"
++ " jnz 1b ;\n"
+ : "+r" (lines),
+ "+r" (p1), "+r" (p2), "+r" (p3), "+r" (p4)
+ :
+- : "memory" );
++ : "memory" );
+
+ XMMS_RESTORE;
+ }
+@@ -764,7 +766,7 @@ static void
+ xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ unsigned long *p3, unsigned long *p4, unsigned long *p5)
+ {
+- unsigned long lines = bytes >> 8;
++ unsigned long lines = bytes >> 8;
+ char xmm_save[16*4] ALIGN16;
+ int cr0;
+
+@@ -776,65 +778,65 @@ xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ because we modify p4 and p5 there, but we can't mark them
+ as read/write, otherwise we'd overflow the 10-asm-operands
+ limit of GCC < 3.1. */
+- __asm__ ("" : "+r" (p4), "+r" (p5));
++ asm("" : "+r" (p4), "+r" (p5));
+
+- __asm__ __volatile__ (
++ asm volatile(
+ #undef BLOCK
+ #define BLOCK(i) \
+ PF1(i) \
+- PF1(i+2) \
++ PF1(i + 2) \
+ LD(i,0) \
+- LD(i+1,1) \
+- LD(i+2,2) \
+- LD(i+3,3) \
++ LD(i + 1, 1) \
++ LD(i + 2, 2) \
++ LD(i + 3, 3) \
+ PF2(i) \
+- PF2(i+2) \
++ PF2(i + 2) \
+ XO1(i,0) \
+- XO1(i+1,1) \
+- XO1(i+2,2) \
+- XO1(i+3,3) \
++ XO1(i + 1, 1) \
++ XO1(i + 2, 2) \
++ XO1(i + 3, 3) \
+ PF3(i) \
+- PF3(i+2) \
++ PF3(i + 2) \
+ XO2(i,0) \
+- XO2(i+1,1) \
+- XO2(i+2,2) \
+- XO2(i+3,3) \
++ XO2(i + 1, 1) \
++ XO2(i + 2, 2) \
++ XO2(i + 3, 3) \
+ PF4(i) \
+- PF4(i+2) \
+- PF0(i+4) \
+- PF0(i+6) \
++ PF4(i + 2) \
++ PF0(i + 4) \
++ PF0(i + 6) \
+ XO3(i,0) \
+- XO3(i+1,1) \
+- XO3(i+2,2) \
+- XO3(i+3,3) \
++ XO3(i + 1, 1) \
++ XO3(i + 2, 2) \
++ XO3(i + 3, 3) \
+ XO4(i,0) \
+- XO4(i+1,1) \
+- XO4(i+2,2) \
+- XO4(i+3,3) \
++ XO4(i + 1, 1) \
++ XO4(i + 2, 2) \
++ XO4(i + 3, 3) \
+ ST(i,0) \
+- ST(i+1,1) \
+- ST(i+2,2) \
+- ST(i+3,3) \
++ ST(i + 1, 1) \
++ ST(i + 2, 2) \
++ ST(i + 3, 3) \
+
+
+ PF0(0)
+ PF0(2)
+
+ " .align 32 ;\n"
+- " 1: ;\n"
++ " 1: ;\n"
+
+ BLOCK(0)
+ BLOCK(4)
+ BLOCK(8)
+ BLOCK(12)
+
+- " addl $256, %1 ;\n"
+- " addl $256, %2 ;\n"
+- " addl $256, %3 ;\n"
+- " addl $256, %4 ;\n"
+- " addl $256, %5 ;\n"
+- " decl %0 ;\n"
+- " jnz 1b ;\n"
++ " addl $256, %1 ;\n"
++ " addl $256, %2 ;\n"
++ " addl $256, %3 ;\n"
++ " addl $256, %4 ;\n"
++ " addl $256, %5 ;\n"
++ " decl %0 ;\n"
++ " jnz 1b ;\n"
+ : "+r" (lines),
+ "+r" (p1), "+r" (p2), "+r" (p3)
+ : "r" (p4), "r" (p5)
+@@ -843,17 +845,17 @@ xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ /* p4 and p5 were modified, and now the variables are dead.
+ Clobber them just to be sure nobody does something stupid
+ like assuming they have some legal value. */
+- __asm__ ("" : "=r" (p4), "=r" (p5));
++ asm("" : "=r" (p4), "=r" (p5));
+
+ XMMS_RESTORE;
+ }
+
+ static struct xor_block_template xor_block_pIII_sse = {
+- .name = "pIII_sse",
+- .do_2 = xor_sse_2,
+- .do_3 = xor_sse_3,
+- .do_4 = xor_sse_4,
+- .do_5 = xor_sse_5,
++ .name = "pIII_sse",
++ .do_2 = xor_sse_2,
++ .do_3 = xor_sse_3,
++ .do_4 = xor_sse_4,
++ .do_5 = xor_sse_5,
+ };
+
+ /* Also try the generic routines. */
+@@ -861,21 +863,21 @@ static struct xor_block_template xor_block_pIII_sse = {
+
+ #undef XOR_TRY_TEMPLATES
+ #define XOR_TRY_TEMPLATES \
+- do { \
+- xor_speed(&xor_block_8regs); \
+- xor_speed(&xor_block_8regs_p); \
+- xor_speed(&xor_block_32regs); \
+- xor_speed(&xor_block_32regs_p); \
+- if (cpu_has_xmm) \
+- xor_speed(&xor_block_pIII_sse); \
+- if (cpu_has_mmx) { \
+- xor_speed(&xor_block_pII_mmx); \
+- xor_speed(&xor_block_p5_mmx); \
+- } \
+- } while (0)
++do { \
++ xor_speed(&xor_block_8regs); \
++ xor_speed(&xor_block_8regs_p); \
++ xor_speed(&xor_block_32regs); \
++ xor_speed(&xor_block_32regs_p); \
++ if (cpu_has_xmm) \
++ xor_speed(&xor_block_pIII_sse); \
++ if (cpu_has_mmx) { \
++ xor_speed(&xor_block_pII_mmx); \
++ xor_speed(&xor_block_p5_mmx); \
++ } \
++} while (0)
+
+ /* We force the use of the SSE xor block because it can write around L2.
+ We may also be able to load into the L1 only depending on how the cpu
+ deals with a load to a line that is being prefetched. */
+-#define XOR_SELECT_TEMPLATE(FASTEST) \
++#define XOR_SELECT_TEMPLATE(FASTEST) \
+ (cpu_has_xmm ? &xor_block_pIII_sse : FASTEST)
+diff --git a/include/asm-x86/xor_64.h b/include/asm-x86/xor_64.h
+index 1eee7fc..24957e3 100644
+--- a/include/asm-x86/xor_64.h
++++ b/include/asm-x86/xor_64.h
+@@ -24,20 +24,23 @@
+ */
+
+ /*
+- * x86-64 changes / gcc fixes from Andi Kleen.
++ * x86-64 changes / gcc fixes from Andi Kleen.
+ * Copyright 2002 Andi Kleen, SuSE Labs.
+ *
+ * This hasn't been optimized for the hammer yet, but there are likely
+ * no advantages to be gotten from x86-64 here anyways.
+ */
+
+-typedef struct { unsigned long a,b; } __attribute__((aligned(16))) xmm_store_t;
++typedef struct {
++ unsigned long a, b;
++} __attribute__((aligned(16))) xmm_store_t;
+
+-/* Doesn't use gcc to save the XMM registers, because there is no easy way to
++/* Doesn't use gcc to save the XMM registers, because there is no easy way to
+ tell it to do a clts before the register saving. */
+-#define XMMS_SAVE do { \
++#define XMMS_SAVE \
++do { \
+ preempt_disable(); \
+- asm volatile ( \
++ asm volatile( \
+ "movq %%cr0,%0 ;\n\t" \
+ "clts ;\n\t" \
+ "movups %%xmm0,(%1) ;\n\t" \
+@@ -47,10 +50,11 @@ typedef struct { unsigned long a,b; } __attribute__((aligned(16))) xmm_store_t;
+ : "=&r" (cr0) \
+ : "r" (xmm_save) \
+ : "memory"); \
+-} while(0)
++} while (0)
+
+-#define XMMS_RESTORE do { \
+- asm volatile ( \
++#define XMMS_RESTORE \
++do { \
++ asm volatile( \
+ "sfence ;\n\t" \
+ "movups (%1),%%xmm0 ;\n\t" \
+ "movups 0x10(%1),%%xmm1 ;\n\t" \
+@@ -61,72 +65,72 @@ typedef struct { unsigned long a,b; } __attribute__((aligned(16))) xmm_store_t;
+ : "r" (cr0), "r" (xmm_save) \
+ : "memory"); \
+ preempt_enable(); \
+-} while(0)
++} while (0)
+
+ #define OFFS(x) "16*("#x")"
+ #define PF_OFFS(x) "256+16*("#x")"
+ #define PF0(x) " prefetchnta "PF_OFFS(x)"(%[p1]) ;\n"
+-#define LD(x,y) " movaps "OFFS(x)"(%[p1]), %%xmm"#y" ;\n"
+-#define ST(x,y) " movaps %%xmm"#y", "OFFS(x)"(%[p1]) ;\n"
++#define LD(x, y) " movaps "OFFS(x)"(%[p1]), %%xmm"#y" ;\n"
++#define ST(x, y) " movaps %%xmm"#y", "OFFS(x)"(%[p1]) ;\n"
+ #define PF1(x) " prefetchnta "PF_OFFS(x)"(%[p2]) ;\n"
+ #define PF2(x) " prefetchnta "PF_OFFS(x)"(%[p3]) ;\n"
+ #define PF3(x) " prefetchnta "PF_OFFS(x)"(%[p4]) ;\n"
+ #define PF4(x) " prefetchnta "PF_OFFS(x)"(%[p5]) ;\n"
+ #define PF5(x) " prefetchnta "PF_OFFS(x)"(%[p6]) ;\n"
+-#define XO1(x,y) " xorps "OFFS(x)"(%[p2]), %%xmm"#y" ;\n"
+-#define XO2(x,y) " xorps "OFFS(x)"(%[p3]), %%xmm"#y" ;\n"
+-#define XO3(x,y) " xorps "OFFS(x)"(%[p4]), %%xmm"#y" ;\n"
+-#define XO4(x,y) " xorps "OFFS(x)"(%[p5]), %%xmm"#y" ;\n"
+-#define XO5(x,y) " xorps "OFFS(x)"(%[p6]), %%xmm"#y" ;\n"
++#define XO1(x, y) " xorps "OFFS(x)"(%[p2]), %%xmm"#y" ;\n"
++#define XO2(x, y) " xorps "OFFS(x)"(%[p3]), %%xmm"#y" ;\n"
++#define XO3(x, y) " xorps "OFFS(x)"(%[p4]), %%xmm"#y" ;\n"
++#define XO4(x, y) " xorps "OFFS(x)"(%[p5]), %%xmm"#y" ;\n"
++#define XO5(x, y) " xorps "OFFS(x)"(%[p6]), %%xmm"#y" ;\n"
+
+
+ static void
+ xor_sse_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
+ {
+- unsigned int lines = bytes >> 8;
++ unsigned int lines = bytes >> 8;
+ unsigned long cr0;
+ xmm_store_t xmm_save[4];
+
+ XMMS_SAVE;
+
+- asm volatile (
++ asm volatile(
+ #undef BLOCK
+ #define BLOCK(i) \
+- LD(i,0) \
+- LD(i+1,1) \
++ LD(i, 0) \
++ LD(i + 1, 1) \
+ PF1(i) \
+- PF1(i+2) \
+- LD(i+2,2) \
+- LD(i+3,3) \
+- PF0(i+4) \
+- PF0(i+6) \
+- XO1(i,0) \
+- XO1(i+1,1) \
+- XO1(i+2,2) \
+- XO1(i+3,3) \
+- ST(i,0) \
+- ST(i+1,1) \
+- ST(i+2,2) \
+- ST(i+3,3) \
++ PF1(i + 2) \
++ LD(i + 2, 2) \
++ LD(i + 3, 3) \
++ PF0(i + 4) \
++ PF0(i + 6) \
++ XO1(i, 0) \
++ XO1(i + 1, 1) \
++ XO1(i + 2, 2) \
++ XO1(i + 3, 3) \
++ ST(i, 0) \
++ ST(i + 1, 1) \
++ ST(i + 2, 2) \
++ ST(i + 3, 3) \
+
+
+ PF0(0)
+ PF0(2)
+
+ " .align 32 ;\n"
+- " 1: ;\n"
++ " 1: ;\n"
+
+ BLOCK(0)
+ BLOCK(4)
+ BLOCK(8)
+ BLOCK(12)
+
+- " addq %[inc], %[p1] ;\n"
+- " addq %[inc], %[p2] ;\n"
++ " addq %[inc], %[p1] ;\n"
++ " addq %[inc], %[p2] ;\n"
+ " decl %[cnt] ; jnz 1b"
+ : [p1] "+r" (p1), [p2] "+r" (p2), [cnt] "+r" (lines)
+- : [inc] "r" (256UL)
+- : "memory");
++ : [inc] "r" (256UL)
++ : "memory");
+
+ XMMS_RESTORE;
+ }
+@@ -141,52 +145,52 @@ xor_sse_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+
+ XMMS_SAVE;
+
+- __asm__ __volatile__ (
++ asm volatile(
+ #undef BLOCK
+ #define BLOCK(i) \
+ PF1(i) \
+- PF1(i+2) \
+- LD(i,0) \
+- LD(i+1,1) \
+- LD(i+2,2) \
+- LD(i+3,3) \
++ PF1(i + 2) \
++ LD(i, 0) \
++ LD(i + 1, 1) \
++ LD(i + 2, 2) \
++ LD(i + 3, 3) \
+ PF2(i) \
+- PF2(i+2) \
+- PF0(i+4) \
+- PF0(i+6) \
+- XO1(i,0) \
+- XO1(i+1,1) \
+- XO1(i+2,2) \
+- XO1(i+3,3) \
+- XO2(i,0) \
+- XO2(i+1,1) \
+- XO2(i+2,2) \
+- XO2(i+3,3) \
+- ST(i,0) \
+- ST(i+1,1) \
+- ST(i+2,2) \
+- ST(i+3,3) \
++ PF2(i + 2) \
++ PF0(i + 4) \
++ PF0(i + 6) \
++ XO1(i, 0) \
++ XO1(i + 1, 1) \
++ XO1(i + 2, 2) \
++ XO1(i + 3, 3) \
++ XO2(i, 0) \
++ XO2(i + 1, 1) \
++ XO2(i + 2, 2) \
++ XO2(i + 3, 3) \
++ ST(i, 0) \
++ ST(i + 1, 1) \
++ ST(i + 2, 2) \
++ ST(i + 3, 3) \
+
+
+ PF0(0)
+ PF0(2)
+
+ " .align 32 ;\n"
+- " 1: ;\n"
++ " 1: ;\n"
+
+ BLOCK(0)
+ BLOCK(4)
+ BLOCK(8)
+ BLOCK(12)
+
+- " addq %[inc], %[p1] ;\n"
+- " addq %[inc], %[p2] ;\n"
+- " addq %[inc], %[p3] ;\n"
++ " addq %[inc], %[p1] ;\n"
++ " addq %[inc], %[p2] ;\n"
++ " addq %[inc], %[p3] ;\n"
+ " decl %[cnt] ; jnz 1b"
+ : [cnt] "+r" (lines),
+ [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3)
+ : [inc] "r" (256UL)
+- : "memory");
++ : "memory");
+ XMMS_RESTORE;
+ }
+
+@@ -195,64 +199,64 @@ xor_sse_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ unsigned long *p3, unsigned long *p4)
+ {
+ unsigned int lines = bytes >> 8;
+- xmm_store_t xmm_save[4];
++ xmm_store_t xmm_save[4];
+ unsigned long cr0;
+
+ XMMS_SAVE;
+
+- __asm__ __volatile__ (
++ asm volatile(
+ #undef BLOCK
+ #define BLOCK(i) \
+ PF1(i) \
+- PF1(i+2) \
+- LD(i,0) \
+- LD(i+1,1) \
+- LD(i+2,2) \
+- LD(i+3,3) \
++ PF1(i + 2) \
++ LD(i, 0) \
++ LD(i + 1, 1) \
++ LD(i + 2, 2) \
++ LD(i + 3, 3) \
+ PF2(i) \
+- PF2(i+2) \
+- XO1(i,0) \
+- XO1(i+1,1) \
+- XO1(i+2,2) \
+- XO1(i+3,3) \
++ PF2(i + 2) \
++ XO1(i, 0) \
++ XO1(i + 1, 1) \
++ XO1(i + 2, 2) \
++ XO1(i + 3, 3) \
+ PF3(i) \
+- PF3(i+2) \
+- PF0(i+4) \
+- PF0(i+6) \
+- XO2(i,0) \
+- XO2(i+1,1) \
+- XO2(i+2,2) \
+- XO2(i+3,3) \
+- XO3(i,0) \
+- XO3(i+1,1) \
+- XO3(i+2,2) \
+- XO3(i+3,3) \
+- ST(i,0) \
+- ST(i+1,1) \
+- ST(i+2,2) \
+- ST(i+3,3) \
++ PF3(i + 2) \
++ PF0(i + 4) \
++ PF0(i + 6) \
++ XO2(i, 0) \
++ XO2(i + 1, 1) \
++ XO2(i + 2, 2) \
++ XO2(i + 3, 3) \
++ XO3(i, 0) \
++ XO3(i + 1, 1) \
++ XO3(i + 2, 2) \
++ XO3(i + 3, 3) \
++ ST(i, 0) \
++ ST(i + 1, 1) \
++ ST(i + 2, 2) \
++ ST(i + 3, 3) \
+
+
+ PF0(0)
+ PF0(2)
+
+ " .align 32 ;\n"
+- " 1: ;\n"
++ " 1: ;\n"
+
+ BLOCK(0)
+ BLOCK(4)
+ BLOCK(8)
+ BLOCK(12)
+
+- " addq %[inc], %[p1] ;\n"
+- " addq %[inc], %[p2] ;\n"
+- " addq %[inc], %[p3] ;\n"
+- " addq %[inc], %[p4] ;\n"
++ " addq %[inc], %[p1] ;\n"
++ " addq %[inc], %[p2] ;\n"
++ " addq %[inc], %[p3] ;\n"
++ " addq %[inc], %[p4] ;\n"
+ " decl %[cnt] ; jnz 1b"
+ : [cnt] "+c" (lines),
+ [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3), [p4] "+r" (p4)
+ : [inc] "r" (256UL)
+- : "memory" );
++ : "memory" );
+
+ XMMS_RESTORE;
+ }
+@@ -261,70 +265,70 @@ static void
+ xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ unsigned long *p3, unsigned long *p4, unsigned long *p5)
+ {
+- unsigned int lines = bytes >> 8;
++ unsigned int lines = bytes >> 8;
+ xmm_store_t xmm_save[4];
+ unsigned long cr0;
+
+ XMMS_SAVE;
+
+- __asm__ __volatile__ (
++ asm volatile(
+ #undef BLOCK
+ #define BLOCK(i) \
+ PF1(i) \
+- PF1(i+2) \
+- LD(i,0) \
+- LD(i+1,1) \
+- LD(i+2,2) \
+- LD(i+3,3) \
++ PF1(i + 2) \
++ LD(i, 0) \
++ LD(i + 1, 1) \
++ LD(i + 2, 2) \
++ LD(i + 3, 3) \
+ PF2(i) \
+- PF2(i+2) \
+- XO1(i,0) \
+- XO1(i+1,1) \
+- XO1(i+2,2) \
+- XO1(i+3,3) \
++ PF2(i + 2) \
++ XO1(i, 0) \
++ XO1(i + 1, 1) \
++ XO1(i + 2, 2) \
++ XO1(i + 3, 3) \
+ PF3(i) \
+- PF3(i+2) \
+- XO2(i,0) \
+- XO2(i+1,1) \
+- XO2(i+2,2) \
+- XO2(i+3,3) \
++ PF3(i + 2) \
++ XO2(i, 0) \
++ XO2(i + 1, 1) \
++ XO2(i + 2, 2) \
++ XO2(i + 3, 3) \
+ PF4(i) \
+- PF4(i+2) \
+- PF0(i+4) \
+- PF0(i+6) \
+- XO3(i,0) \
+- XO3(i+1,1) \
+- XO3(i+2,2) \
+- XO3(i+3,3) \
+- XO4(i,0) \
+- XO4(i+1,1) \
+- XO4(i+2,2) \
+- XO4(i+3,3) \
+- ST(i,0) \
+- ST(i+1,1) \
+- ST(i+2,2) \
+- ST(i+3,3) \
++ PF4(i + 2) \
++ PF0(i + 4) \
++ PF0(i + 6) \
++ XO3(i, 0) \
++ XO3(i + 1, 1) \
++ XO3(i + 2, 2) \
++ XO3(i + 3, 3) \
++ XO4(i, 0) \
++ XO4(i + 1, 1) \
++ XO4(i + 2, 2) \
++ XO4(i + 3, 3) \
++ ST(i, 0) \
++ ST(i + 1, 1) \
++ ST(i + 2, 2) \
++ ST(i + 3, 3) \
+
+
+ PF0(0)
+ PF0(2)
+
+ " .align 32 ;\n"
+- " 1: ;\n"
++ " 1: ;\n"
+
+ BLOCK(0)
+ BLOCK(4)
+ BLOCK(8)
+ BLOCK(12)
+
+- " addq %[inc], %[p1] ;\n"
+- " addq %[inc], %[p2] ;\n"
+- " addq %[inc], %[p3] ;\n"
+- " addq %[inc], %[p4] ;\n"
+- " addq %[inc], %[p5] ;\n"
++ " addq %[inc], %[p1] ;\n"
++ " addq %[inc], %[p2] ;\n"
++ " addq %[inc], %[p3] ;\n"
++ " addq %[inc], %[p4] ;\n"
++ " addq %[inc], %[p5] ;\n"
+ " decl %[cnt] ; jnz 1b"
+ : [cnt] "+c" (lines),
+- [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3), [p4] "+r" (p4),
++ [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3), [p4] "+r" (p4),
+ [p5] "+r" (p5)
+ : [inc] "r" (256UL)
+ : "memory");
+@@ -333,18 +337,18 @@ xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ }
+
+ static struct xor_block_template xor_block_sse = {
+- .name = "generic_sse",
+- .do_2 = xor_sse_2,
+- .do_3 = xor_sse_3,
+- .do_4 = xor_sse_4,
+- .do_5 = xor_sse_5,
++ .name = "generic_sse",
++ .do_2 = xor_sse_2,
++ .do_3 = xor_sse_3,
++ .do_4 = xor_sse_4,
++ .do_5 = xor_sse_5,
+ };
+
+ #undef XOR_TRY_TEMPLATES
+-#define XOR_TRY_TEMPLATES \
+- do { \
+- xor_speed(&xor_block_sse); \
+- } while (0)
++#define XOR_TRY_TEMPLATES \
++do { \
++ xor_speed(&xor_block_sse); \
++} while (0)
+
+ /* We force the use of the SSE xor block because it can write around L2.
+ We may also be able to load into the L1 only depending on how the cpu
+diff --git a/include/asm-xtensa/semaphore.h b/include/asm-xtensa/semaphore.h
+index 3e04167..d9b2034 100644
+--- a/include/asm-xtensa/semaphore.h
++++ b/include/asm-xtensa/semaphore.h
+@@ -1,99 +1 @@
+-/*
+- * linux/include/asm-xtensa/semaphore.h
+- *
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License. See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (C) 2001 - 2005 Tensilica Inc.
+- */
+-
+-#ifndef _XTENSA_SEMAPHORE_H
+-#define _XTENSA_SEMAPHORE_H
+-
+-#include <asm/atomic.h>
+-#include <asm/system.h>
+-#include <linux/wait.h>
+-#include <linux/rwsem.h>
+-
+-struct semaphore {
+- atomic_t count;
+- int sleepers;
+- wait_queue_head_t wait;
+-};
+-
+-#define __SEMAPHORE_INITIALIZER(name,n) \
+-{ \
+- .count = ATOMIC_INIT(n), \
+- .sleepers = 0, \
+- .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+-}
+-
+-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+- struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+-
+-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+-
+-static inline void sema_init (struct semaphore *sem, int val)
+-{
+- atomic_set(&sem->count, val);
+- sem->sleepers = 0;
+- init_waitqueue_head(&sem->wait);
+-}
+-
+-static inline void init_MUTEX (struct semaphore *sem)
+-{
+- sema_init(sem, 1);
+-}
+-
+-static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+-{
+- sema_init(sem, 0);
+-}
+-
+-asmlinkage void __down(struct semaphore * sem);
+-asmlinkage int __down_interruptible(struct semaphore * sem);
+-asmlinkage int __down_trylock(struct semaphore * sem);
+-asmlinkage void __up(struct semaphore * sem);
+-
+-extern spinlock_t semaphore_wake_lock;
+-
+-static inline void down(struct semaphore * sem)
+-{
+- might_sleep();
+-
+- if (atomic_sub_return(1, &sem->count) < 0)
+- __down(sem);
+-}
+-
+-static inline int down_interruptible(struct semaphore * sem)
+-{
+- int ret = 0;
+-
+- might_sleep();
+-
+- if (atomic_sub_return(1, &sem->count) < 0)
+- ret = __down_interruptible(sem);
+- return ret;
+-}
+-
+-static inline int down_trylock(struct semaphore * sem)
+-{
+- int ret = 0;
+-
+- if (atomic_sub_return(1, &sem->count) < 0)
+- ret = __down_trylock(sem);
+- return ret;
+-}
+-
+-/*
+- * Note! This is subtle. We jump to wake people up only if
+- * the semaphore was negative (== somebody was waiting on it).
+- */
+-static inline void up(struct semaphore * sem)
+-{
+- if (atomic_add_return(1, &sem->count) <= 0)
+- __up(sem);
+-}
+-
+-#endif /* _XTENSA_SEMAPHORE_H */
++#include <linux/semaphore.h>
+diff --git a/include/crypto/aes.h b/include/crypto/aes.h
+index d480b76..40008d6 100644
+--- a/include/crypto/aes.h
++++ b/include/crypto/aes.h
+@@ -14,11 +14,13 @@
+ #define AES_KEYSIZE_192 24
+ #define AES_KEYSIZE_256 32
+ #define AES_BLOCK_SIZE 16
++#define AES_MAX_KEYLENGTH (15 * 16)
++#define AES_MAX_KEYLENGTH_U32 (AES_MAX_KEYLENGTH / sizeof(u32))
+
+ struct crypto_aes_ctx {
+ u32 key_length;
+- u32 key_enc[60];
+- u32 key_dec[60];
++ u32 key_enc[AES_MAX_KEYLENGTH_U32];
++ u32 key_dec[AES_MAX_KEYLENGTH_U32];
+ };
+
+ extern u32 crypto_ft_tab[4][256];
+@@ -28,4 +30,6 @@ extern u32 crypto_il_tab[4][256];
+
+ int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ unsigned int key_len);
++int crypto_aes_expand_key(struct crypto_aes_ctx *ctx, const u8 *in_key,
++ unsigned int key_len);
+ #endif
+diff --git a/include/keys/rxrpc-type.h b/include/keys/rxrpc-type.h
+index 4ea429b..7609365 100644
+--- a/include/keys/rxrpc-type.h
++++ b/include/keys/rxrpc-type.h
+@@ -21,4 +21,4 @@ extern struct key_type key_type_rxrpc;
+
+ extern struct key *rxrpc_get_null_key(const char *);
+
+-#endif /* _KEYS_USER_TYPE_H */
++#endif /* _KEYS_RXRPC_TYPE_H */
+diff --git a/include/linux/Kbuild b/include/linux/Kbuild
+index cedbbd8..bda6f04 100644
+--- a/include/linux/Kbuild
++++ b/include/linux/Kbuild
+@@ -100,7 +100,7 @@ header-y += ixjuser.h
+ header-y += jffs2.h
+ header-y += keyctl.h
+ header-y += limits.h
+-header-y += lock_dlm_plock.h
++header-y += dlm_plock.h
+ header-y += magic.h
+ header-y += major.h
+ header-y += matroxfb.h
+@@ -150,6 +150,7 @@ header-y += tiocl.h
+ header-y += tipc.h
+ header-y += tipc_config.h
+ header-y += toshiba.h
++header-y += udf_fs_i.h
+ header-y += ultrasound.h
+ header-y += un.h
+ header-y += utime.h
+@@ -209,8 +210,9 @@ unifdef-y += hayesesp.h
+ unifdef-y += hdlcdrv.h
+ unifdef-y += hdlc.h
+ unifdef-y += hdreg.h
+-unifdef-y += hdsmart.h
++unifdef-y += hid.h
+ unifdef-y += hiddev.h
++unifdef-y += hidraw.h
+ unifdef-y += hpet.h
+ unifdef-y += i2c.h
+ unifdef-y += i2c-dev.h
+@@ -231,7 +233,6 @@ unifdef-y += if_pppol2tp.h
+ unifdef-y += if_pppox.h
+ unifdef-y += if_tr.h
+ unifdef-y += if_vlan.h
+-unifdef-y += if_wanpipe.h
+ unifdef-y += igmp.h
+ unifdef-y += inet_diag.h
+ unifdef-y += in.h
+@@ -261,6 +262,7 @@ unifdef-y += mempolicy.h
+ unifdef-y += mii.h
+ unifdef-y += mman.h
+ unifdef-y += mroute.h
++unifdef-y += mroute6.h
+ unifdef-y += msdos_fs.h
+ unifdef-y += msg.h
+ unifdef-y += nbd.h
+@@ -289,6 +291,7 @@ unifdef-y += parport.h
+ unifdef-y += patchkey.h
+ unifdef-y += pci.h
+ unifdef-y += personality.h
++unifdef-y += pim.h
+ unifdef-y += pktcdvd.h
+ unifdef-y += pmu.h
+ unifdef-y += poll.h
+@@ -333,7 +336,6 @@ unifdef-y += time.h
+ unifdef-y += timex.h
+ unifdef-y += tty.h
+ unifdef-y += types.h
+-unifdef-y += udf_fs_i.h
+ unifdef-y += udp.h
+ unifdef-y += uinput.h
+ unifdef-y += uio.h
+diff --git a/include/linux/aer.h b/include/linux/aer.h
+index bcf236d..f251814 100644
+--- a/include/linux/aer.h
++++ b/include/linux/aer.h
+@@ -13,7 +13,6 @@ extern int pci_enable_pcie_error_reporting(struct pci_dev *dev);
+ extern int pci_find_aer_capability(struct pci_dev *dev);
+ extern int pci_disable_pcie_error_reporting(struct pci_dev *dev);
+ extern int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev);
+-extern int pci_cleanup_aer_correct_error_status(struct pci_dev *dev);
+ #else
+ static inline int pci_enable_pcie_error_reporting(struct pci_dev *dev)
+ {
+@@ -31,10 +30,6 @@ static inline int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
+ {
+ return -EINVAL;
+ }
+-static inline int pci_cleanup_aer_correct_error_status(struct pci_dev *dev)
+-{
+- return -EINVAL;
+-}
+ #endif
+
+ #endif //_AER_H_
+diff --git a/include/linux/arcdevice.h b/include/linux/arcdevice.h
+index fde6758..a191607 100644
+--- a/include/linux/arcdevice.h
++++ b/include/linux/arcdevice.h
+@@ -283,8 +283,8 @@ struct arcnet_local {
+ int next_buf, first_free_buf;
+
+ /* network "reconfiguration" handling */
+- time_t first_recon, /* time of "first" RECON message to count */
+- last_recon; /* time of most recent RECON */
++ unsigned long first_recon; /* time of "first" RECON message to count */
++ unsigned long last_recon; /* time of most recent RECON */
+ int num_recons; /* number of RECONs between first and last. */
+ bool network_down; /* do we think the network is down? */
+
+diff --git a/include/linux/ata_platform.h b/include/linux/ata_platform.h
+index b856a2a..9a26c83 100644
+--- a/include/linux/ata_platform.h
++++ b/include/linux/ata_platform.h
+@@ -27,7 +27,10 @@ extern int __devexit __pata_platform_remove(struct device *dev);
+ /*
+ * Marvell SATA private data
+ */
++struct mbus_dram_target_info;
++
+ struct mv_sata_platform_data {
++ struct mbus_dram_target_info *dram;
+ int n_ports; /* number of sata ports */
+ };
+
+diff --git a/include/linux/atalk.h b/include/linux/atalk.h
+index ced8a1e..e9ebac2 100644
+--- a/include/linux/atalk.h
++++ b/include/linux/atalk.h
+@@ -85,8 +85,6 @@ static inline struct atalk_sock *at_sk(struct sock *sk)
+ return (struct atalk_sock *)sk;
+ }
+
+-#include <asm/byteorder.h>
+-
+ struct ddpehdr {
+ __be16 deh_len_hops; /* lower 10 bits are length, next 4 - hops */
+ __be16 deh_sum;
+diff --git a/include/linux/atmel_tc.h b/include/linux/atmel_tc.h
+new file mode 100644
+index 0000000..53ba65e
+--- /dev/null
++++ b/include/linux/atmel_tc.h
+@@ -0,0 +1,252 @@
++/*
++ * Timer/Counter Unit (TC) registers.
++ *
++ * 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 ATMEL_TC_H
++#define ATMEL_TC_H
++
++#include <linux/compiler.h>
++#include <linux/list.h>
++
++/*
++ * Many 32-bit Atmel SOCs include one or more TC blocks, each of which holds
++ * three general-purpose 16-bit timers. These timers share one register bank.
++ * Depending on the SOC, each timer may have its own clock and IRQ, or those
++ * may be shared by the whole TC block.
++ *
++ * These TC blocks may have up to nine external pins: TCLK0..2 signals for
++ * clocks or clock gates, and per-timer TIOA and TIOB signals used for PWM
++ * or triggering. Those pins need to be set up for use with the TC block,
++ * else they will be used as GPIOs or for a different controller.
++ *
++ * Although we expect each TC block to have a platform_device node, those
++ * nodes are not what drivers bind to. Instead, they ask for a specific
++ * TC block, by number ... which is a common approach on systems with many
++ * timers. Then they use clk_get() and platform_get_irq() to get clock and
++ * IRQ resources.
++ */
++
++struct clk;
++
++/**
++ * struct atmel_tc - information about a Timer/Counter Block
++ * @pdev: physical device
++ * @iomem: resource associated with the I/O register
++ * @regs: mapping through which the I/O registers can be accessed
++ * @irq: irq for each of the three channels
++ * @clk: internal clock source for each of the three channels
++ * @node: list node, for tclib internal use
++ *
++ * On some platforms, each TC channel has its own clocks and IRQs,
++ * while on others, all TC channels share the same clock and IRQ.
++ * Drivers should clk_enable() all the clocks they need even though
++ * all the entries in @clk may point to the same physical clock.
++ * Likewise, drivers should request irqs independently for each
++ * channel, but they must use IRQF_SHARED in case some of the entries
++ * in @irq are actually the same IRQ.
++ */
++struct atmel_tc {
++ struct platform_device *pdev;
++ struct resource *iomem;
++ void __iomem *regs;
++ int irq[3];
++ struct clk *clk[3];
++ struct list_head node;
++};
++
++extern struct atmel_tc *atmel_tc_alloc(unsigned block, const char *name);
++extern void atmel_tc_free(struct atmel_tc *tc);
++
++/* platform-specific ATMEL_TC_TIMER_CLOCKx divisors (0 means 32KiHz) */
++extern const u8 atmel_tc_divisors[5];
++
++
++/*
++ * Two registers have block-wide controls. These are: configuring the three
++ * "external" clocks (or event sources) used by the timer channels; and
++ * synchronizing the timers by resetting them all at once.
++ *
++ * "External" can mean "external to chip" using the TCLK0, TCLK1, or TCLK2
++ * signals. Or, it can mean "external to timer", using the TIOA output from
++ * one of the other two timers that's being run in waveform mode.
++ */
++
++#define ATMEL_TC_BCR 0xc0 /* TC Block Control Register */
++#define ATMEL_TC_SYNC (1 << 0) /* synchronize timers */
++
++#define ATMEL_TC_BMR 0xc4 /* TC Block Mode Register */
++#define ATMEL_TC_TC0XC0S (3 << 0) /* external clock 0 source */
++#define ATMEL_TC_TC0XC0S_TCLK0 (0 << 0)
++#define ATMEL_TC_TC0XC0S_NONE (1 << 0)
++#define ATMEL_TC_TC0XC0S_TIOA1 (2 << 0)
++#define ATMEL_TC_TC0XC0S_TIOA2 (3 << 0)
++#define ATMEL_TC_TC1XC1S (3 << 2) /* external clock 1 source */
++#define ATMEL_TC_TC1XC1S_TCLK1 (0 << 2)
++#define ATMEL_TC_TC1XC1S_NONE (1 << 2)
++#define ATMEL_TC_TC1XC1S_TIOA0 (2 << 2)
++#define ATMEL_TC_TC1XC1S_TIOA2 (3 << 2)
++#define ATMEL_TC_TC2XC2S (3 << 4) /* external clock 2 source */
++#define ATMEL_TC_TC2XC2S_TCLK2 (0 << 4)
++#define ATMEL_TC_TC2XC2S_NONE (1 << 4)
++#define ATMEL_TC_TC2XC2S_TIOA0 (2 << 4)
++#define ATMEL_TC_TC2XC2S_TIOA1 (3 << 4)
++
++
++/*
++ * Each TC block has three "channels", each with one counter and controls.
++ *
++ * Note that the semantics of ATMEL_TC_TIMER_CLOCKx (input clock selection
++ * when it's not "external") is silicon-specific. AT91 platforms use one
++ * set of definitions; AVR32 platforms use a different set. Don't hard-wire
++ * such knowledge into your code, use the global "atmel_tc_divisors" ...
++ * where index N is the divisor for clock N+1, else zero to indicate it uses
++ * the 32 KiHz clock.
++ *
++ * The timers can be chained in various ways, and operated in "waveform"
++ * generation mode (including PWM) or "capture" mode (to time events). In
++ * both modes, behavior can be configured in many ways.
++ *
++ * Each timer has two I/O pins, TIOA and TIOB. Waveform mode uses TIOA as a
++ * PWM output, and TIOB as either another PWM or as a trigger. Capture mode
++ * uses them only as inputs.
++ */
++#define ATMEL_TC_CHAN(idx) ((idx)*0x40)
++#define ATMEL_TC_REG(idx, reg) (ATMEL_TC_CHAN(idx) + ATMEL_TC_ ## reg)
++
++#define ATMEL_TC_CCR 0x00 /* Channel Control Register */
++#define ATMEL_TC_CLKEN (1 << 0) /* clock enable */
++#define ATMEL_TC_CLKDIS (1 << 1) /* clock disable */
++#define ATMEL_TC_SWTRG (1 << 2) /* software trigger */
++
++#define ATMEL_TC_CMR 0x04 /* Channel Mode Register */
++
++/* Both modes share some CMR bits */
++#define ATMEL_TC_TCCLKS (7 << 0) /* clock source */
++#define ATMEL_TC_TIMER_CLOCK1 (0 << 0)
++#define ATMEL_TC_TIMER_CLOCK2 (1 << 0)
++#define ATMEL_TC_TIMER_CLOCK3 (2 << 0)
++#define ATMEL_TC_TIMER_CLOCK4 (3 << 0)
++#define ATMEL_TC_TIMER_CLOCK5 (4 << 0)
++#define ATMEL_TC_XC0 (5 << 0)
++#define ATMEL_TC_XC1 (6 << 0)
++#define ATMEL_TC_XC2 (7 << 0)
++#define ATMEL_TC_CLKI (1 << 3) /* clock invert */
++#define ATMEL_TC_BURST (3 << 4) /* clock gating */
++#define ATMEL_TC_GATE_NONE (0 << 4)
++#define ATMEL_TC_GATE_XC0 (1 << 4)
++#define ATMEL_TC_GATE_XC1 (2 << 4)
++#define ATMEL_TC_GATE_XC2 (3 << 4)
++#define ATMEL_TC_WAVE (1 << 15) /* true = Waveform mode */
++
++/* CAPTURE mode CMR bits */
++#define ATMEL_TC_LDBSTOP (1 << 6) /* counter stops on RB load */
++#define ATMEL_TC_LDBDIS (1 << 7) /* counter disable on RB load */
++#define ATMEL_TC_ETRGEDG (3 << 8) /* external trigger edge */
++#define ATMEL_TC_ETRGEDG_NONE (0 << 8)
++#define ATMEL_TC_ETRGEDG_RISING (1 << 8)
++#define ATMEL_TC_ETRGEDG_FALLING (2 << 8)
++#define ATMEL_TC_ETRGEDG_BOTH (3 << 8)
++#define ATMEL_TC_ABETRG (1 << 10) /* external trigger is TIOA? */
++#define ATMEL_TC_CPCTRG (1 << 14) /* RC compare trigger enable */
++#define ATMEL_TC_LDRA (3 << 16) /* RA loading edge (of TIOA) */
++#define ATMEL_TC_LDRA_NONE (0 << 16)
++#define ATMEL_TC_LDRA_RISING (1 << 16)
++#define ATMEL_TC_LDRA_FALLING (2 << 16)
++#define ATMEL_TC_LDRA_BOTH (3 << 16)
++#define ATMEL_TC_LDRB (3 << 18) /* RB loading edge (of TIOA) */
++#define ATMEL_TC_LDRB_NONE (0 << 18)
++#define ATMEL_TC_LDRB_RISING (1 << 18)
++#define ATMEL_TC_LDRB_FALLING (2 << 18)
++#define ATMEL_TC_LDRB_BOTH (3 << 18)
++
++/* WAVEFORM mode CMR bits */
++#define ATMEL_TC_CPCSTOP (1 << 6) /* RC compare stops counter */
++#define ATMEL_TC_CPCDIS (1 << 7) /* RC compare disables counter */
++#define ATMEL_TC_EEVTEDG (3 << 8) /* external event edge */
++#define ATMEL_TC_EEVTEDG_NONE (0 << 8)
++#define ATMEL_TC_EEVTEDG_RISING (1 << 8)
++#define ATMEL_TC_EEVTEDG_FALLING (2 << 8)
++#define ATMEL_TC_EEVTEDG_BOTH (3 << 8)
++#define ATMEL_TC_EEVT (3 << 10) /* external event source */
++#define ATMEL_TC_EEVT_TIOB (0 << 10)
++#define ATMEL_TC_EEVT_XC0 (1 << 10)
++#define ATMEL_TC_EEVT_XC1 (2 << 10)
++#define ATMEL_TC_EEVT_XC2 (3 << 10)
++#define ATMEL_TC_ENETRG (1 << 12) /* external event is trigger */
++#define ATMEL_TC_WAVESEL (3 << 13) /* waveform type */
++#define ATMEL_TC_WAVESEL_UP (0 << 13)
++#define ATMEL_TC_WAVESEL_UPDOWN (1 << 13)
++#define ATMEL_TC_WAVESEL_UP_AUTO (2 << 13)
++#define ATMEL_TC_WAVESEL_UPDOWN_AUTO (3 << 13)
++#define ATMEL_TC_ACPA (3 << 16) /* RA compare changes TIOA */
++#define ATMEL_TC_ACPA_NONE (0 << 16)
++#define ATMEL_TC_ACPA_SET (1 << 16)
++#define ATMEL_TC_ACPA_CLEAR (2 << 16)
++#define ATMEL_TC_ACPA_TOGGLE (3 << 16)
++#define ATMEL_TC_ACPC (3 << 18) /* RC compare changes TIOA */
++#define ATMEL_TC_ACPC_NONE (0 << 18)
++#define ATMEL_TC_ACPC_SET (1 << 18)
++#define ATMEL_TC_ACPC_CLEAR (2 << 18)
++#define ATMEL_TC_ACPC_TOGGLE (3 << 18)
++#define ATMEL_TC_AEEVT (3 << 20) /* external event changes TIOA */
++#define ATMEL_TC_AEEVT_NONE (0 << 20)
++#define ATMEL_TC_AEEVT_SET (1 << 20)
++#define ATMEL_TC_AEEVT_CLEAR (2 << 20)
++#define ATMEL_TC_AEEVT_TOGGLE (3 << 20)
++#define ATMEL_TC_ASWTRG (3 << 22) /* software trigger changes TIOA */
++#define ATMEL_TC_ASWTRG_NONE (0 << 22)
++#define ATMEL_TC_ASWTRG_SET (1 << 22)
++#define ATMEL_TC_ASWTRG_CLEAR (2 << 22)
++#define ATMEL_TC_ASWTRG_TOGGLE (3 << 22)
++#define ATMEL_TC_BCPB (3 << 24) /* RB compare changes TIOB */
++#define ATMEL_TC_BCPB_NONE (0 << 24)
++#define ATMEL_TC_BCPB_SET (1 << 24)
++#define ATMEL_TC_BCPB_CLEAR (2 << 24)
++#define ATMEL_TC_BCPB_TOGGLE (3 << 24)
++#define ATMEL_TC_BCPC (3 << 26) /* RC compare changes TIOB */
++#define ATMEL_TC_BCPC_NONE (0 << 26)
++#define ATMEL_TC_BCPC_SET (1 << 26)
++#define ATMEL_TC_BCPC_CLEAR (2 << 26)
++#define ATMEL_TC_BCPC_TOGGLE (3 << 26)
++#define ATMEL_TC_BEEVT (3 << 28) /* external event changes TIOB */
++#define ATMEL_TC_BEEVT_NONE (0 << 28)
++#define ATMEL_TC_BEEVT_SET (1 << 28)
++#define ATMEL_TC_BEEVT_CLEAR (2 << 28)
++#define ATMEL_TC_BEEVT_TOGGLE (3 << 28)
++#define ATMEL_TC_BSWTRG (3 << 30) /* software trigger changes TIOB */
++#define ATMEL_TC_BSWTRG_NONE (0 << 30)
++#define ATMEL_TC_BSWTRG_SET (1 << 30)
++#define ATMEL_TC_BSWTRG_CLEAR (2 << 30)
++#define ATMEL_TC_BSWTRG_TOGGLE (3 << 30)
++
++#define ATMEL_TC_CV 0x10 /* counter Value */
++#define ATMEL_TC_RA 0x14 /* register A */
++#define ATMEL_TC_RB 0x18 /* register B */
++#define ATMEL_TC_RC 0x1c /* register C */
++
++#define ATMEL_TC_SR 0x20 /* status (read-only) */
++/* Status-only flags */
++#define ATMEL_TC_CLKSTA (1 << 16) /* clock enabled */
++#define ATMEL_TC_MTIOA (1 << 17) /* TIOA mirror */
++#define ATMEL_TC_MTIOB (1 << 18) /* TIOB mirror */
++
++#define ATMEL_TC_IER 0x24 /* interrupt enable (write-only) */
++#define ATMEL_TC_IDR 0x28 /* interrupt disable (write-only) */
++#define ATMEL_TC_IMR 0x2c /* interrupt mask (read-only) */
++
++/* Status and IRQ flags */
++#define ATMEL_TC_COVFS (1 << 0) /* counter overflow */
++#define ATMEL_TC_LOVRS (1 << 1) /* load overrun */
++#define ATMEL_TC_CPAS (1 << 2) /* RA compare */
++#define ATMEL_TC_CPBS (1 << 3) /* RB compare */
++#define ATMEL_TC_CPCS (1 << 4) /* RC compare */
++#define ATMEL_TC_LDRAS (1 << 5) /* RA loading */
++#define ATMEL_TC_LDRBS (1 << 6) /* RB loading */
++#define ATMEL_TC_ETRGS (1 << 7) /* external trigger */
++
++#endif
+diff --git a/include/linux/attribute_container.h b/include/linux/attribute_container.h
+index f558233..794ad74 100644
+--- a/include/linux/attribute_container.h
++++ b/include/linux/attribute_container.h
+@@ -1,5 +1,5 @@
+ /*
+- * class_container.h - a generic container for all classes
++ * attribute_container.h - a generic container for all classes
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+@@ -18,7 +18,7 @@ struct attribute_container {
+ struct klist containers;
+ struct class *class;
+ struct attribute_group *grp;
+- struct class_device_attribute **attrs;
++ struct device_attribute **attrs;
+ int (*match)(struct attribute_container *, struct device *);
+ #define ATTRIBUTE_CONTAINER_NO_CLASSDEVS 0x01
+ unsigned long flags;
+@@ -37,35 +37,35 @@ attribute_container_set_no_classdevs(struct attribute_container *atc)
+ }
+
+ int attribute_container_register(struct attribute_container *cont);
+-int attribute_container_unregister(struct attribute_container *cont);
++int __must_check attribute_container_unregister(struct attribute_container *cont);
+ void attribute_container_create_device(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *,
+- struct class_device *));
++ struct device *));
+ void attribute_container_add_device(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *,
+- struct class_device *));
++ struct device *));
+ void attribute_container_remove_device(struct device *dev,
+ void (*fn)(struct attribute_container *,
+ struct device *,
+- struct class_device *));
++ struct device *));
+ void attribute_container_device_trigger(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *,
+- struct class_device *));
++ struct device *));
+ void attribute_container_trigger(struct device *dev,
+ int (*fn)(struct attribute_container *,
+ struct device *));
+-int attribute_container_add_attrs(struct class_device *classdev);
+-int attribute_container_add_class_device(struct class_device *classdev);
++int attribute_container_add_attrs(struct device *classdev);
++int attribute_container_add_class_device(struct device *classdev);
+ int attribute_container_add_class_device_adapter(struct attribute_container *cont,
+ struct device *dev,
+- struct class_device *classdev);
+-void attribute_container_remove_attrs(struct class_device *classdev);
+-void attribute_container_class_device_del(struct class_device *classdev);
+-struct attribute_container *attribute_container_classdev_to_container(struct class_device *);
+-struct class_device *attribute_container_find_class_device(struct attribute_container *, struct device *);
+-struct class_device_attribute **attribute_container_classdev_to_attrs(const struct class_device *classdev);
++ struct device *classdev);
++void attribute_container_remove_attrs(struct device *classdev);
++void attribute_container_class_device_del(struct device *classdev);
++struct attribute_container *attribute_container_classdev_to_container(struct device *);
++struct device *attribute_container_find_class_device(struct attribute_container *, struct device *);
++struct device_attribute **attribute_container_classdev_to_attrs(const struct device *classdev);
+
+ #endif
+diff --git a/include/linux/audit.h b/include/linux/audit.h
+index 2af9ec0..4ccb048 100644
+--- a/include/linux/audit.h
++++ b/include/linux/audit.h
+@@ -353,6 +353,33 @@ struct netlink_skb_parms;
+ struct linux_binprm;
+ struct mq_attr;
+ struct mqstat;
++struct audit_watch;
++struct audit_tree;
++
++struct audit_krule {
++ int vers_ops;
++ u32 flags;
++ u32 listnr;
++ u32 action;
++ u32 mask[AUDIT_BITMASK_SIZE];
++ u32 buflen; /* for data alloc on list rules */
++ u32 field_count;
++ char *filterkey; /* ties events to rules */
++ struct audit_field *fields;
++ struct audit_field *arch_f; /* quick access to arch field */
++ struct audit_field *inode_f; /* quick access to an inode field */
++ struct audit_watch *watch; /* associated watch */
++ struct audit_tree *tree; /* associated watched tree */
++ struct list_head rlist; /* entry in audit_{watch,tree}.rules list */
++};
++
++struct audit_field {
++ u32 type;
++ u32 val;
++ u32 op;
++ char *lsm_str;
++ void *lsm_rule;
++};
+
+ #define AUDITSC_INVALID 0
+ #define AUDITSC_SUCCESS 1
+@@ -536,6 +563,8 @@ extern void audit_log_d_path(struct audit_buffer *ab,
+ const char *prefix,
+ struct path *path);
+ extern void audit_log_lost(const char *message);
++extern int audit_update_lsm_rules(void);
++
+ /* Private API (for audit.c only) */
+ extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
+ extern int audit_filter_type(int type);
+diff --git a/include/linux/bio.h b/include/linux/bio.h
+index 4c59bdc..d259690 100644
+--- a/include/linux/bio.h
++++ b/include/linux/bio.h
+@@ -327,6 +327,8 @@ extern struct bio *bio_map_kern(struct request_queue *, void *, unsigned int,
+ extern void bio_set_pages_dirty(struct bio *bio);
+ extern void bio_check_pages_dirty(struct bio *bio);
+ extern struct bio *bio_copy_user(struct request_queue *, unsigned long, unsigned int, int);
++extern struct bio *bio_copy_user_iov(struct request_queue *, struct sg_iovec *,
++ int, int);
+ extern int bio_uncopy_user(struct bio *);
+ void zero_fill_bio(struct bio *bio);
+
+diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
+index acad110..1dbe074 100644
+--- a/include/linux/bitmap.h
++++ b/include/linux/bitmap.h
+@@ -108,6 +108,7 @@ extern int __bitmap_weight(const unsigned long *bitmap, int bits);
+
+ extern int bitmap_scnprintf(char *buf, unsigned int len,
+ const unsigned long *src, int nbits);
++extern int bitmap_scnprintf_len(unsigned int len);
+ extern int __bitmap_parse(const char *buf, unsigned int buflen, int is_user,
+ unsigned long *dst, int nbits);
+ extern int bitmap_parse_user(const char __user *ubuf, unsigned int ulen,
+diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
+index 6f79d40..c5065e3 100644
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -112,6 +112,7 @@ enum rq_flag_bits {
+ __REQ_RW_SYNC, /* request is sync (O_DIRECT) */
+ __REQ_ALLOCED, /* request came from our alloc pool */
+ __REQ_RW_META, /* metadata io request */
++ __REQ_COPY_USER, /* contains copies of user pages */
+ __REQ_NR_BITS, /* stops here */
+ };
+
+@@ -133,6 +134,7 @@ enum rq_flag_bits {
+ #define REQ_RW_SYNC (1 << __REQ_RW_SYNC)
+ #define REQ_ALLOCED (1 << __REQ_ALLOCED)
+ #define REQ_RW_META (1 << __REQ_RW_META)
++#define REQ_COPY_USER (1 << __REQ_COPY_USER)
+
+ #define BLK_MAX_CDB 16
+
+@@ -533,8 +535,13 @@ extern unsigned long blk_max_low_pfn, blk_max_pfn;
+ * BLK_BOUNCE_ANY : don't bounce anything
+ * BLK_BOUNCE_ISA : bounce pages above ISA DMA boundary
+ */
++
++#if BITS_PER_LONG == 32
+ #define BLK_BOUNCE_HIGH ((u64)blk_max_low_pfn << PAGE_SHIFT)
+-#define BLK_BOUNCE_ANY ((u64)blk_max_pfn << PAGE_SHIFT)
++#else
++#define BLK_BOUNCE_HIGH -1ULL
++#endif
++#define BLK_BOUNCE_ANY (-1ULL)
+ #define BLK_BOUNCE_ISA (ISA_DMA_THRESHOLD)
+
+ /*
+diff --git a/include/linux/bsg.h b/include/linux/bsg.h
+index 60e377b..e8406c5 100644
+--- a/include/linux/bsg.h
++++ b/include/linux/bsg.h
+@@ -55,7 +55,7 @@ struct sg_io_v4 {
+
+ #if defined(CONFIG_BLK_DEV_BSG)
+ struct bsg_class_device {
+- struct class_device *class_dev;
++ struct device *class_dev;
+ struct device *dev;
+ int minor;
+ struct request_queue *queue;
+diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h
+index a5cd204..5db265e 100644
+--- a/include/linux/cdrom.h
++++ b/include/linux/cdrom.h
+@@ -910,6 +910,7 @@ struct mode_page_header {
+ #ifdef __KERNEL__
+ #include <linux/fs.h> /* not really needed, later.. */
+ #include <linux/device.h>
++#include <linux/list.h>
+
+ struct packet_command
+ {
+@@ -934,7 +935,7 @@ struct packet_command
+ /* Uniform cdrom data structures for cdrom.c */
+ struct cdrom_device_info {
+ struct cdrom_device_ops *ops; /* link to device_ops */
+- struct cdrom_device_info *next; /* next device_info for this major */
++ struct list_head list; /* linked list of all device_info */
+ struct gendisk *disk; /* matching block layer disk */
+ void *handle; /* driver-dependent data */
+ /* specifications */
+@@ -994,7 +995,7 @@ extern int cdrom_ioctl(struct file *file, struct cdrom_device_info *cdi,
+ extern int cdrom_media_changed(struct cdrom_device_info *);
+
+ extern int register_cdrom(struct cdrom_device_info *cdi);
+-extern int unregister_cdrom(struct cdrom_device_info *cdi);
++extern void unregister_cdrom(struct cdrom_device_info *cdi);
+
+ typedef struct {
+ int data;
+diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
+index 85778a4..3509447 100644
+--- a/include/linux/clocksource.h
++++ b/include/linux/clocksource.h
+@@ -216,6 +216,7 @@ static inline void clocksource_calculate_interval(struct clocksource *c,
+ /* used to install a new clocksource */
+ extern int clocksource_register(struct clocksource*);
+ extern void clocksource_unregister(struct clocksource*);
++extern void clocksource_touch_watchdog(void);
+ extern struct clocksource* clocksource_get_next(void);
+ extern void clocksource_change_rating(struct clocksource *cs, int rating);
+ extern void clocksource_resume(void);
+diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
+index fe23792..b2fd754 100644
+--- a/include/linux/compiler-gcc.h
++++ b/include/linux/compiler-gcc.h
+@@ -28,9 +28,16 @@
+ #define __must_be_array(a) \
+ BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(typeof(a), typeof(&a[0])))
+
+-#define inline inline __attribute__((always_inline))
+-#define __inline__ __inline__ __attribute__((always_inline))
+-#define __inline __inline __attribute__((always_inline))
++/*
++ * Force always-inline if the user requests it so via the .config:
++ */
++#if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \
++ !defined(CONFIG_OPTIMIZE_INLINING) && (__GNUC__ >= 4)
++# define inline inline __attribute__((always_inline))
++# define __inline__ __inline__ __attribute__((always_inline))
++# define __inline __inline __attribute__((always_inline))
++#endif
++
+ #define __deprecated __attribute__((deprecated))
+ #define __packed __attribute__((packed))
+ #define __weak __attribute__((weak))
+diff --git a/include/linux/cpu.h b/include/linux/cpu.h
+index 0be8d65..f212fa9 100644
+--- a/include/linux/cpu.h
++++ b/include/linux/cpu.h
+@@ -23,7 +23,6 @@
+ #include <linux/node.h>
+ #include <linux/compiler.h>
+ #include <linux/cpumask.h>
+-#include <asm/semaphore.h>
+ #include <linux/mutex.h>
+
+ struct cpu {
+diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
+index 7047f58..259c805 100644
+--- a/include/linux/cpumask.h
++++ b/include/linux/cpumask.h
+@@ -222,8 +222,13 @@ int __next_cpu(int n, const cpumask_t *srcp);
+ #define next_cpu(n, src) ({ (void)(src); 1; })
+ #endif
+
++#ifdef CONFIG_HAVE_CPUMASK_OF_CPU_MAP
++extern cpumask_t *cpumask_of_cpu_map;
++#define cpumask_of_cpu(cpu) (cpumask_of_cpu_map[cpu])
++
++#else
+ #define cpumask_of_cpu(cpu) \
+-({ \
++(*({ \
+ typeof(_unused_cpumask_arg_) m; \
+ if (sizeof(m) == sizeof(unsigned long)) { \
+ m.bits[0] = 1UL<<(cpu); \
+@@ -231,8 +236,9 @@ int __next_cpu(int n, const cpumask_t *srcp);
+ cpus_clear(m); \
+ cpu_set((cpu), m); \
+ } \
+- m; \
+-})
++ &m; \
++}))
++#endif
+
+ #define CPU_MASK_LAST_WORD BITMAP_LAST_WORD_MASK(NR_CPUS)
+
+@@ -243,6 +249,8 @@ int __next_cpu(int n, const cpumask_t *srcp);
+ [BITS_TO_LONGS(NR_CPUS)-1] = CPU_MASK_LAST_WORD \
+ } }
+
++#define CPU_MASK_ALL_PTR (&CPU_MASK_ALL)
++
+ #else
+
+ #define CPU_MASK_ALL \
+@@ -251,6 +259,10 @@ int __next_cpu(int n, const cpumask_t *srcp);
+ [BITS_TO_LONGS(NR_CPUS)-1] = CPU_MASK_LAST_WORD \
+ } }
+
++/* cpu_mask_all is in init/main.c */
++extern cpumask_t cpu_mask_all;
++#define CPU_MASK_ALL_PTR (&cpu_mask_all)
++
+ #endif
+
+ #define CPU_MASK_NONE \
+@@ -273,6 +285,13 @@ static inline int __cpumask_scnprintf(char *buf, int len,
+ return bitmap_scnprintf(buf, len, srcp->bits, nbits);
+ }
+
++#define cpumask_scnprintf_len(len) \
++ __cpumask_scnprintf_len((len))
++static inline int __cpumask_scnprintf_len(int len)
++{
++ return bitmap_scnprintf_len(len);
++}
++
+ #define cpumask_parse_user(ubuf, ulen, dst) \
+ __cpumask_parse_user((ubuf), (ulen), &(dst), NR_CPUS)
+ static inline int __cpumask_parse_user(const char __user *buf, int len,
+diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
+index 0a26be3..726761e 100644
+--- a/include/linux/cpuset.h
++++ b/include/linux/cpuset.h
+@@ -20,8 +20,8 @@ extern int number_of_cpusets; /* How many cpusets are defined in system? */
+ extern int cpuset_init_early(void);
+ extern int cpuset_init(void);
+ extern void cpuset_init_smp(void);
+-extern cpumask_t cpuset_cpus_allowed(struct task_struct *p);
+-extern cpumask_t cpuset_cpus_allowed_locked(struct task_struct *p);
++extern void cpuset_cpus_allowed(struct task_struct *p, cpumask_t *mask);
++extern void cpuset_cpus_allowed_locked(struct task_struct *p, cpumask_t *mask);
+ extern nodemask_t cpuset_mems_allowed(struct task_struct *p);
+ #define cpuset_current_mems_allowed (current->mems_allowed)
+ void cpuset_init_current_mems_allowed(void);
+@@ -84,13 +84,14 @@ static inline int cpuset_init_early(void) { return 0; }
+ static inline int cpuset_init(void) { return 0; }
+ static inline void cpuset_init_smp(void) {}
+
+-static inline cpumask_t cpuset_cpus_allowed(struct task_struct *p)
++static inline void cpuset_cpus_allowed(struct task_struct *p, cpumask_t *mask)
+ {
+- return cpu_possible_map;
++ *mask = cpu_possible_map;
+ }
+-static inline cpumask_t cpuset_cpus_allowed_locked(struct task_struct *p)
++static inline void cpuset_cpus_allowed_locked(struct task_struct *p,
++ cpumask_t *mask)
+ {
+- return cpu_possible_map;
++ *mask = cpu_possible_map;
+ }
+
+ static inline nodemask_t cpuset_mems_allowed(struct task_struct *p)
+diff --git a/include/linux/crypto.h b/include/linux/crypto.h
+index 5e02d1b..425824b 100644
+--- a/include/linux/crypto.h
++++ b/include/linux/crypto.h
+@@ -317,14 +317,7 @@ int crypto_unregister_alg(struct crypto_alg *alg);
+ /*
+ * Algorithm query interface.
+ */
+-#ifdef CONFIG_CRYPTO
+ int crypto_has_alg(const char *name, u32 type, u32 mask);
+-#else
+-static inline int crypto_has_alg(const char *name, u32 type, u32 mask)
+-{
+- return 0;
+-}
+-#endif
+
+ /*
+ * Transforms: user-instantiated objects which encapsulate algorithms
+diff --git a/include/linux/dcache.h b/include/linux/dcache.h
+index 6bd6460..cfb1627 100644
+--- a/include/linux/dcache.h
++++ b/include/linux/dcache.h
+@@ -301,7 +301,9 @@ extern int d_validate(struct dentry *, struct dentry *);
+ */
+ extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
+
++extern char *__d_path(const struct path *path, struct path *root, char *, int);
+ extern char *d_path(struct path *, char *, int);
++extern char *dentry_path(struct dentry *, char *, int);
+
+ /* Allocation counts.. */
+
+@@ -359,7 +361,6 @@ static inline int d_mountpoint(struct dentry *dentry)
+ }
+
+ extern struct vfsmount *lookup_mnt(struct vfsmount *, struct dentry *);
+-extern struct vfsmount *__lookup_mnt(struct vfsmount *, struct dentry *, int);
+ extern struct dentry *lookup_create(struct nameidata *nd, int is_dir);
+
+ extern int sysctl_vfs_cache_pressure;
+diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
+index cb78457..ad3b787 100644
+--- a/include/linux/device-mapper.h
++++ b/include/linux/device-mapper.h
+@@ -1,6 +1,6 @@
+ /*
+ * Copyright (C) 2001 Sistina Software (UK) Limited.
+- * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
++ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the LGPL.
+ */
+@@ -10,6 +10,8 @@
+
+ #ifdef __KERNEL__
+
++#include <linux/bio.h>
++
+ struct dm_target;
+ struct dm_table;
+ struct dm_dev;
+@@ -250,11 +252,97 @@ void dm_table_event(struct dm_table *t);
+ */
+ int dm_swap_table(struct mapped_device *md, struct dm_table *t);
+
++/*-----------------------------------------------------------------
++ * Macros.
++ *---------------------------------------------------------------*/
++#define DM_NAME "device-mapper"
++
++#define DMERR(f, arg...) \
++ printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
++#define DMERR_LIMIT(f, arg...) \
++ do { \
++ if (printk_ratelimit()) \
++ printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " \
++ f "\n", ## arg); \
++ } while (0)
++
++#define DMWARN(f, arg...) \
++ printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
++#define DMWARN_LIMIT(f, arg...) \
++ do { \
++ if (printk_ratelimit()) \
++ printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " \
++ f "\n", ## arg); \
++ } while (0)
++
++#define DMINFO(f, arg...) \
++ printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
++#define DMINFO_LIMIT(f, arg...) \
++ do { \
++ if (printk_ratelimit()) \
++ printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f \
++ "\n", ## arg); \
++ } while (0)
++
++#ifdef CONFIG_DM_DEBUG
++# define DMDEBUG(f, arg...) \
++ printk(KERN_DEBUG DM_NAME ": " DM_MSG_PREFIX " DEBUG: " f "\n", ## arg)
++# define DMDEBUG_LIMIT(f, arg...) \
++ do { \
++ if (printk_ratelimit()) \
++ printk(KERN_DEBUG DM_NAME ": " DM_MSG_PREFIX ": " f \
++ "\n", ## arg); \
++ } while (0)
++#else
++# define DMDEBUG(f, arg...) do {} while (0)
++# define DMDEBUG_LIMIT(f, arg...) do {} while (0)
++#endif
++
++#define DMEMIT(x...) sz += ((sz >= maxlen) ? \
++ 0 : scnprintf(result + sz, maxlen - sz, x))
++
++#define SECTOR_SHIFT 9
++
++/*
++ * Definitions of return values from target end_io function.
++ */
++#define DM_ENDIO_INCOMPLETE 1
++#define DM_ENDIO_REQUEUE 2
++
++/*
++ * Definitions of return values from target map function.
++ */
++#define DM_MAPIO_SUBMITTED 0
++#define DM_MAPIO_REMAPPED 1
++#define DM_MAPIO_REQUEUE DM_ENDIO_REQUEUE
++
++/*
++ * Ceiling(n / sz)
++ */
++#define dm_div_up(n, sz) (((n) + (sz) - 1) / (sz))
++
++#define dm_sector_div_up(n, sz) ( \
++{ \
++ sector_t _r = ((n) + (sz) - 1); \
++ sector_div(_r, (sz)); \
++ _r; \
++} \
++)
++
+ /*
+- * Prepare a table for a device that will error all I/O.
+- * To make it active, call dm_suspend(), dm_swap_table() then dm_resume().
++ * ceiling(n / size) * size
+ */
+-int dm_create_error_table(struct dm_table **result, struct mapped_device *md);
++#define dm_round_up(n, sz) (dm_div_up((n), (sz)) * (sz))
++
++static inline sector_t to_sector(unsigned long n)
++{
++ return (n >> SECTOR_SHIFT);
++}
++
++static inline unsigned long to_bytes(sector_t n)
++{
++ return (n << SECTOR_SHIFT);
++}
+
+ #endif /* __KERNEL__ */
+ #endif /* _LINUX_DEVICE_MAPPER_H */
+diff --git a/include/linux/device.h b/include/linux/device.h
+index 2258d89..1a06026 100644
+--- a/include/linux/device.h
++++ b/include/linux/device.h
+@@ -20,7 +20,7 @@
+ #include <linux/types.h>
+ #include <linux/module.h>
+ #include <linux/pm.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+ #include <asm/atomic.h>
+ #include <asm/device.h>
+
+@@ -429,7 +429,6 @@ struct device {
+ struct kobject kobj;
+ char bus_id[BUS_ID_SIZE]; /* position on parent bus */
+ struct device_type *type;
+- unsigned is_registered:1;
+ unsigned uevent_suppress:1;
+
+ struct semaphore sem; /* semaphore to synchronize calls to
+@@ -475,6 +474,9 @@ struct device {
+ void (*release)(struct device *dev);
+ };
+
++/* Get the wakeup routines, which depend on struct device */
++#include <linux/pm_wakeup.h>
++
+ #ifdef CONFIG_NUMA
+ static inline int dev_to_node(struct device *dev)
+ {
+@@ -506,7 +508,7 @@ static inline void dev_set_drvdata(struct device *dev, void *data)
+
+ static inline int device_is_registered(struct device *dev)
+ {
+- return dev->is_registered;
++ return dev->kobj.state_in_sysfs;
+ }
+
+ void driver_init(void);
+@@ -543,20 +545,6 @@ extern struct device *device_create(struct class *cls, struct device *parent,
+ dev_t devt, const char *fmt, ...)
+ __attribute__((format(printf, 4, 5)));
+ extern void device_destroy(struct class *cls, dev_t devt);
+-#ifdef CONFIG_PM_SLEEP
+-extern void destroy_suspended_device(struct class *cls, dev_t devt);
+-extern void device_pm_schedule_removal(struct device *);
+-#else /* !CONFIG_PM_SLEEP */
+-static inline void destroy_suspended_device(struct class *cls, dev_t devt)
+-{
+- device_destroy(cls, devt);
+-}
+-
+-static inline void device_pm_schedule_removal(struct device *dev)
+-{
+- device_unregister(dev);
+-}
+-#endif /* !CONFIG_PM_SLEEP */
+
+ /*
+ * Platform "fixup" functions - allow the platform to have their say
+@@ -608,21 +596,16 @@ extern const char *dev_driver_string(struct device *dev);
+ #define dev_dbg(dev, format, arg...) \
+ dev_printk(KERN_DEBUG , dev , format , ## arg)
+ #else
+-static inline int __attribute__ ((format (printf, 2, 3)))
+-dev_dbg(struct device *dev, const char *fmt, ...)
+-{
+- return 0;
+-}
++#define dev_dbg(dev, format, arg...) \
++ ({ if (0) dev_printk(KERN_DEBUG, dev, format, ##arg); 0; })
+ #endif
+
+ #ifdef VERBOSE_DEBUG
+ #define dev_vdbg dev_dbg
+ #else
+-static inline int __attribute__ ((format (printf, 2, 3)))
+-dev_vdbg(struct device *dev, const char *fmt, ...)
+-{
+- return 0;
+-}
++
++#define dev_vdbg(dev, format, arg...) \
++ ({ if (0) dev_printk(KERN_DEBUG, dev, format, ##arg); 0; })
+ #endif
+
+ /* Create alias, so I can be autoloaded. */
+diff --git a/include/linux/dlm.h b/include/linux/dlm.h
+index c743fbc..203a025 100644
+--- a/include/linux/dlm.h
++++ b/include/linux/dlm.h
+@@ -21,10 +21,7 @@
+
+ /* Lock levels and flags are here */
+ #include <linux/dlmconstants.h>
+-
+-
+-#define DLM_RESNAME_MAXLEN 64
+-
++#include <linux/types.h>
+
+ typedef void dlm_lockspace_t;
+
+@@ -63,7 +60,7 @@ typedef void dlm_lockspace_t;
+
+ struct dlm_lksb {
+ int sb_status;
+- uint32_t sb_lkid;
++ __u32 sb_lkid;
+ char sb_flags;
+ char * sb_lvbptr;
+ };
+diff --git a/include/linux/dlm_device.h b/include/linux/dlm_device.h
+index 9642277..c603450 100644
+--- a/include/linux/dlm_device.h
++++ b/include/linux/dlm_device.h
+@@ -11,10 +11,16 @@
+ *******************************************************************************
+ ******************************************************************************/
+
++#ifndef _LINUX_DLM_DEVICE_H
++#define _LINUX_DLM_DEVICE_H
++
+ /* This is the device interface for dlm, most users will use a library
+ * interface.
+ */
+
++#include <linux/dlm.h>
++#include <linux/types.h>
++
+ #define DLM_USER_LVB_LEN 32
+
+ /* Version of the device interface */
+@@ -94,10 +100,9 @@ struct dlm_lock_result {
+ #define DLM_USER_PURGE 6
+ #define DLM_USER_DEADLOCK 7
+
+-/* Arbitrary length restriction */
+-#define MAX_LS_NAME_LEN 64
+-
+ /* Lockspace flags */
+ #define DLM_USER_LSFLG_AUTOFREE 1
+ #define DLM_USER_LSFLG_FORCEFREE 2
+
++#endif
++
+diff --git a/include/linux/dlm_plock.h b/include/linux/dlm_plock.h
+new file mode 100644
+index 0000000..18d5fdb
+--- /dev/null
++++ b/include/linux/dlm_plock.h
+@@ -0,0 +1,50 @@
++/*
++ * Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved.
++ *
++ * This copyrighted material is made available to anyone wishing to use,
++ * modify, copy, or redistribute it subject to the terms and conditions
++ * of the GNU General Public License v.2.
++ */
++
++#ifndef __DLM_PLOCK_DOT_H__
++#define __DLM_PLOCK_DOT_H__
++
++#define DLM_PLOCK_MISC_NAME "dlm_plock"
++
++#define DLM_PLOCK_VERSION_MAJOR 1
++#define DLM_PLOCK_VERSION_MINOR 1
++#define DLM_PLOCK_VERSION_PATCH 0
++
++enum {
++ DLM_PLOCK_OP_LOCK = 1,
++ DLM_PLOCK_OP_UNLOCK,
++ DLM_PLOCK_OP_GET,
++};
++
++struct dlm_plock_info {
++ __u32 version[3];
++ __u8 optype;
++ __u8 ex;
++ __u8 wait;
++ __u8 pad;
++ __u32 pid;
++ __s32 nodeid;
++ __s32 rv;
++ __u32 fsid;
++ __u64 number;
++ __u64 start;
++ __u64 end;
++ __u64 owner;
++};
++
++#ifdef __KERNEL__
++int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
++ int cmd, struct file_lock *fl);
++int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
++ struct file_lock *fl);
++int dlm_posix_get(dlm_lockspace_t *lockspace, u64 number, struct file *file,
++ struct file_lock *fl);
++#endif /* __KERNEL__ */
++
++#endif
++
+diff --git a/include/linux/dlmconstants.h b/include/linux/dlmconstants.h
+index fddb3d3..47bf08d 100644
+--- a/include/linux/dlmconstants.h
++++ b/include/linux/dlmconstants.h
+@@ -18,6 +18,10 @@
+ * Constants used by DLM interface.
+ */
+
++#define DLM_LOCKSPACE_LEN 64
++#define DLM_RESNAME_MAXLEN 64
++
++
+ /*
+ * Lock Modes
+ */
+diff --git a/include/linux/dm-dirty-log.h b/include/linux/dm-dirty-log.h
+new file mode 100644
+index 0000000..600c5fb
+--- /dev/null
++++ b/include/linux/dm-dirty-log.h
+@@ -0,0 +1,131 @@
++/*
++ * Copyright (C) 2003 Sistina Software
++ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
++ *
++ * Device-Mapper dirty region log.
++ *
++ * This file is released under the LGPL.
++ */
++
++#ifndef _LINUX_DM_DIRTY_LOG
++#define _LINUX_DM_DIRTY_LOG
++
++#ifdef __KERNEL__
++
++#include <linux/types.h>
++#include <linux/device-mapper.h>
++
++typedef sector_t region_t;
++
++struct dm_dirty_log_type;
++
++struct dm_dirty_log {
++ struct dm_dirty_log_type *type;
++ void *context;
++};
++
++struct dm_dirty_log_type {
++ const char *name;
++ struct module *module;
++
++ int (*ctr)(struct dm_dirty_log *log, struct dm_target *ti,
++ unsigned argc, char **argv);
++ void (*dtr)(struct dm_dirty_log *log);
++
++ /*
++ * There are times when we don't want the log to touch
++ * the disk.
++ */
++ int (*presuspend)(struct dm_dirty_log *log);
++ int (*postsuspend)(struct dm_dirty_log *log);
++ int (*resume)(struct dm_dirty_log *log);
++
++ /*
++ * Retrieves the smallest size of region that the log can
++ * deal with.
++ */
++ uint32_t (*get_region_size)(struct dm_dirty_log *log);
++
++ /*
++ * A predicate to say whether a region is clean or not.
++ * May block.
++ */
++ int (*is_clean)(struct dm_dirty_log *log, region_t region);
++
++ /*
++ * Returns: 0, 1, -EWOULDBLOCK, < 0
++ *
++ * A predicate function to check the area given by
++ * [sector, sector + len) is in sync.
++ *
++ * If -EWOULDBLOCK is returned the state of the region is
++ * unknown, typically this will result in a read being
++ * passed to a daemon to deal with, since a daemon is
++ * allowed to block.
++ */
++ int (*in_sync)(struct dm_dirty_log *log, region_t region,
++ int can_block);
++
++ /*
++ * Flush the current log state (eg, to disk). This
++ * function may block.
++ */
++ int (*flush)(struct dm_dirty_log *log);
++
++ /*
++ * Mark an area as clean or dirty. These functions may
++ * block, though for performance reasons blocking should
++ * be extremely rare (eg, allocating another chunk of
++ * memory for some reason).
++ */
++ void (*mark_region)(struct dm_dirty_log *log, region_t region);
++ void (*clear_region)(struct dm_dirty_log *log, region_t region);
++
++ /*
++ * Returns: <0 (error), 0 (no region), 1 (region)
++ *
++ * The mirrord will need perform recovery on regions of
++ * the mirror that are in the NOSYNC state. This
++ * function asks the log to tell the caller about the
++ * next region that this machine should recover.
++ *
++ * Do not confuse this function with 'in_sync()', one
++ * tells you if an area is synchronised, the other
++ * assigns recovery work.
++ */
++ int (*get_resync_work)(struct dm_dirty_log *log, region_t *region);
++
++ /*
++ * This notifies the log that the resync status of a region
++ * has changed. It also clears the region from the recovering
++ * list (if present).
++ */
++ void (*set_region_sync)(struct dm_dirty_log *log,
++ region_t region, int in_sync);
++
++ /*
++ * Returns the number of regions that are in sync.
++ */
++ region_t (*get_sync_count)(struct dm_dirty_log *log);
++
++ /*
++ * Support function for mirror status requests.
++ */
++ int (*status)(struct dm_dirty_log *log, status_type_t status_type,
++ char *result, unsigned maxlen);
++};
++
++int dm_dirty_log_type_register(struct dm_dirty_log_type *type);
++int dm_dirty_log_type_unregister(struct dm_dirty_log_type *type);
++
++/*
++ * Make sure you use these two functions, rather than calling
++ * type->constructor/destructor() directly.
++ */
++struct dm_dirty_log *dm_dirty_log_create(const char *type_name,
++ struct dm_target *ti,
++ unsigned argc, char **argv);
++void dm_dirty_log_destroy(struct dm_dirty_log *log);
++
++#endif /* __KERNEL__ */
++#endif /* _LINUX_DM_DIRTY_LOG_H */
+diff --git a/include/linux/dm-io.h b/include/linux/dm-io.h
+new file mode 100644
+index 0000000..b6bf17e
+--- /dev/null
++++ b/include/linux/dm-io.h
+@@ -0,0 +1,85 @@
++/*
++ * Copyright (C) 2003 Sistina Software
++ * Copyright (C) 2004 - 2008 Red Hat, Inc. All rights reserved.
++ *
++ * Device-Mapper low-level I/O.
++ *
++ * This file is released under the GPL.
++ */
++
++#ifndef _LINUX_DM_IO_H
++#define _LINUX_DM_IO_H
++
++#ifdef __KERNEL__
++
++#include <linux/types.h>
++
++struct dm_io_region {
++ struct block_device *bdev;
++ sector_t sector;
++ sector_t count; /* If this is zero the region is ignored. */
++};
++
++struct page_list {
++ struct page_list *next;
++ struct page *page;
++};
++
++typedef void (*io_notify_fn)(unsigned long error, void *context);
++
++enum dm_io_mem_type {
++ DM_IO_PAGE_LIST,/* Page list */
++ DM_IO_BVEC, /* Bio vector */
++ DM_IO_VMA, /* Virtual memory area */
++ DM_IO_KMEM, /* Kernel memory */
++};
++
++struct dm_io_memory {
++ enum dm_io_mem_type type;
++
++ union {
++ struct page_list *pl;
++ struct bio_vec *bvec;
++ void *vma;
++ void *addr;
++ } ptr;
++
++ unsigned offset;
++};
++
++struct dm_io_notify {
++ io_notify_fn fn; /* Callback for asynchronous requests */
++ void *context; /* Passed to callback */
++};
++
++/*
++ * IO request structure
++ */
++struct dm_io_client;
++struct dm_io_request {
++ int bi_rw; /* READ|WRITE - not READA */
++ struct dm_io_memory mem; /* Memory to use for io */
++ struct dm_io_notify notify; /* Synchronous if notify.fn is NULL */
++ struct dm_io_client *client; /* Client memory handler */
++};
++
++/*
++ * For async io calls, users can alternatively use the dm_io() function below
++ * and dm_io_client_create() to create private mempools for the client.
++ *
++ * Create/destroy may block.
++ */
++struct dm_io_client *dm_io_client_create(unsigned num_pages);
++int dm_io_client_resize(unsigned num_pages, struct dm_io_client *client);
++void dm_io_client_destroy(struct dm_io_client *client);
++
++/*
++ * IO interface using private per-client pools.
++ * Each bit in the optional 'sync_error_bits' bitset indicates whether an
++ * error occurred doing io to the corresponding region.
++ */
++int dm_io(struct dm_io_request *io_req, unsigned num_regions,
++ struct dm_io_region *region, unsigned long *sync_error_bits);
++
++#endif /* __KERNEL__ */
++#endif /* _LINUX_DM_IO_H */
+diff --git a/include/linux/dm-kcopyd.h b/include/linux/dm-kcopyd.h
+new file mode 100644
+index 0000000..5db2163
+--- /dev/null
++++ b/include/linux/dm-kcopyd.h
+@@ -0,0 +1,47 @@
++/*
++ * Copyright (C) 2001 - 2003 Sistina Software
++ * Copyright (C) 2004 - 2008 Red Hat, Inc. All rights reserved.
++ *
++ * kcopyd provides a simple interface for copying an area of one
++ * block-device to one or more other block-devices, either synchronous
++ * or with an asynchronous completion notification.
++ *
++ * This file is released under the GPL.
++ */
++
++#ifndef _LINUX_DM_KCOPYD_H
++#define _LINUX_DM_KCOPYD_H
++
++#ifdef __KERNEL__
++
++#include <linux/dm-io.h>
++
++/* FIXME: make this configurable */
++#define DM_KCOPYD_MAX_REGIONS 8
++
++#define DM_KCOPYD_IGNORE_ERROR 1
++
++/*
++ * To use kcopyd you must first create a dm_kcopyd_client object.
++ */
++struct dm_kcopyd_client;
++int dm_kcopyd_client_create(unsigned num_pages,
++ struct dm_kcopyd_client **result);
++void dm_kcopyd_client_destroy(struct dm_kcopyd_client *kc);
++
++/*
++ * Submit a copy job to kcopyd. This is built on top of the
++ * previous three fns.
++ *
++ * read_err is a boolean,
++ * write_err is a bitset, with 1 bit for each destination region
++ */
++typedef void (*dm_kcopyd_notify_fn)(int read_err, unsigned long write_err,
++ void *context);
++
++int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
++ unsigned num_dests, struct dm_io_region *dests,
++ unsigned flags, dm_kcopyd_notify_fn fn, void *context);
++
++#endif /* __KERNEL__ */
++#endif /* _LINUX_DM_KCOPYD_H */
+diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
+index 34d4406..d08a5c5 100644
+--- a/include/linux/dmaengine.h
++++ b/include/linux/dmaengine.h
+@@ -95,12 +95,17 @@ enum dma_transaction_type {
+ #define DMA_TX_TYPE_END (DMA_INTERRUPT + 1)
+
+ /**
+- * enum dma_prep_flags - DMA flags to augment operation preparation
++ * enum dma_ctrl_flags - DMA flags to augment operation preparation,
++ * control completion, and communicate status.
+ * @DMA_PREP_INTERRUPT - trigger an interrupt (callback) upon completion of
+ * this transaction
++ * @DMA_CTRL_ACK - the descriptor cannot be reused until the client
++ * acknowledges receipt, i.e. has has a chance to establish any
++ * dependency chains
+ */
+-enum dma_prep_flags {
++enum dma_ctrl_flags {
+ DMA_PREP_INTERRUPT = (1 << 0),
++ DMA_CTRL_ACK = (1 << 1),
+ };
+
+ /**
+@@ -211,8 +216,8 @@ typedef void (*dma_async_tx_callback)(void *dma_async_param);
+ * ---dma generic offload fields---
+ * @cookie: tracking cookie for this transaction, set to -EBUSY if
+ * this tx is sitting on a dependency list
+- * @ack: the descriptor can not be reused until the client acknowledges
+- * receipt, i.e. has has a chance to establish any dependency chains
++ * @flags: flags to augment operation preparation, control completion, and
++ * communicate status
+ * @phys: physical address of the descriptor
+ * @tx_list: driver common field for operations that require multiple
+ * descriptors
+@@ -221,23 +226,20 @@ typedef void (*dma_async_tx_callback)(void *dma_async_param);
+ * @callback: routine to call after this operation is complete
+ * @callback_param: general parameter to pass to the callback routine
+ * ---async_tx api specific fields---
+- * @depend_list: at completion this list of transactions are submitted
+- * @depend_node: allow this transaction to be executed after another
+- * transaction has completed, possibly on another channel
++ * @next: at completion submit this descriptor
+ * @parent: pointer to the next level up in the dependency chain
+- * @lock: protect the dependency list
++ * @lock: protect the parent and next pointers
+ */
+ struct dma_async_tx_descriptor {
+ dma_cookie_t cookie;
+- int ack;
++ enum dma_ctrl_flags flags; /* not a 'long' to pack with cookie */
+ dma_addr_t phys;
+ struct list_head tx_list;
+ struct dma_chan *chan;
+ dma_cookie_t (*tx_submit)(struct dma_async_tx_descriptor *tx);
+ dma_async_tx_callback callback;
+ void *callback_param;
+- struct list_head depend_list;
+- struct list_head depend_node;
++ struct dma_async_tx_descriptor *next;
+ struct dma_async_tx_descriptor *parent;
+ spinlock_t lock;
+ };
+@@ -261,7 +263,6 @@ struct dma_async_tx_descriptor {
+ * @device_prep_dma_zero_sum: prepares a zero_sum operation
+ * @device_prep_dma_memset: prepares a memset operation
+ * @device_prep_dma_interrupt: prepares an end of chain interrupt operation
+- * @device_dependency_added: async_tx notifies the channel about new deps
+ * @device_issue_pending: push pending transactions to hardware
+ */
+ struct dma_device {
+@@ -294,9 +295,8 @@ struct dma_device {
+ struct dma_chan *chan, dma_addr_t dest, int value, size_t len,
+ unsigned long flags);
+ struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)(
+- struct dma_chan *chan);
++ struct dma_chan *chan, unsigned long flags);
+
+- void (*device_dependency_added)(struct dma_chan *chan);
+ enum dma_status (*device_is_tx_complete)(struct dma_chan *chan,
+ dma_cookie_t cookie, dma_cookie_t *last,
+ dma_cookie_t *used);
+@@ -321,7 +321,13 @@ void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx,
+ static inline void
+ async_tx_ack(struct dma_async_tx_descriptor *tx)
+ {
+- tx->ack = 1;
++ tx->flags |= DMA_CTRL_ACK;
++}
++
++static inline int
++async_tx_test_ack(struct dma_async_tx_descriptor *tx)
++{
++ return tx->flags & DMA_CTRL_ACK;
+ }
+
+ #define first_dma_cap(mask) __first_dma_cap(&(mask))
+@@ -398,7 +404,7 @@ static inline enum dma_status dma_async_is_tx_complete(struct dma_chan *chan,
+ * @last_used: last cookie value handed out
+ *
+ * dma_async_is_complete() is used in dma_async_memcpy_complete()
+- * the test logic is seperated for lightweight testing of multiple cookies
++ * the test logic is separated for lightweight testing of multiple cookies
+ */
+ static inline enum dma_status dma_async_is_complete(dma_cookie_t cookie,
+ dma_cookie_t last_complete, dma_cookie_t last_used)
+diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
+index c6a2353..402fb7a 100644
+--- a/include/linux/dvb/dmx.h
++++ b/include/linux/dvb/dmx.h
+@@ -39,9 +39,10 @@ typedef enum
+ DMX_OUT_DECODER, /* Streaming directly to decoder. */
+ DMX_OUT_TAP, /* Output going to a memory buffer */
+ /* (to be retrieved via the read command).*/
+- DMX_OUT_TS_TAP /* Output multiplexed into a new TS */
++ DMX_OUT_TS_TAP, /* Output multiplexed into a new TS */
+ /* (to be retrieved by reading from the */
+ /* logical DVR device). */
++ DMX_OUT_TSDEMUX_TAP /* Like TS_TAP but retrieved from the DMX device */
+ } dmx_output_t;
+
+
+diff --git a/include/linux/efi.h b/include/linux/efi.h
+index 14813b5..a5f359a 100644
+--- a/include/linux/efi.h
++++ b/include/linux/efi.h
+@@ -18,6 +18,7 @@
+ #include <linux/proc_fs.h>
+ #include <linux/rtc.h>
+ #include <linux/ioport.h>
++#include <linux/pfn.h>
+
+ #include <asm/page.h>
+ #include <asm/system.h>
+@@ -394,4 +395,10 @@ struct efi_generic_dev_path {
+ u16 length;
+ } __attribute ((packed));
+
++static inline void memrange_efi_to_native(u64 *addr, u64 *npages)
++{
++ *npages = PFN_UP(*addr + (*npages<<EFI_PAGE_SHIFT)) - PFN_DOWN(*addr);
++ *addr &= PAGE_MASK;
++}
++
+ #endif /* _LINUX_EFI_H */
+diff --git a/include/linux/enclosure.h b/include/linux/enclosure.h
+index a5978f1..4332442 100644
+--- a/include/linux/enclosure.h
++++ b/include/linux/enclosure.h
+@@ -82,7 +82,8 @@ struct enclosure_component_callbacks {
+
+ struct enclosure_component {
+ void *scratch;
+- struct class_device cdev;
++ struct device cdev;
++ struct device *dev;
+ enum enclosure_component_type type;
+ int number;
+ int fault;
+@@ -94,20 +95,20 @@ struct enclosure_component {
+ struct enclosure_device {
+ void *scratch;
+ struct list_head node;
+- struct class_device cdev;
++ struct device edev;
+ struct enclosure_component_callbacks *cb;
+ int components;
+ struct enclosure_component component[0];
+ };
+
+ static inline struct enclosure_device *
+-to_enclosure_device(struct class_device *dev)
++to_enclosure_device(struct device *dev)
+ {
+- return container_of(dev, struct enclosure_device, cdev);
++ return container_of(dev, struct enclosure_device, edev);
+ }
+
+ static inline struct enclosure_component *
+-to_enclosure_component(struct class_device *dev)
++to_enclosure_component(struct device *dev)
+ {
+ return container_of(dev, struct enclosure_component, cdev);
+ }
+diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
+index adcbb05..de8387b 100644
+--- a/include/linux/exportfs.h
++++ b/include/linux/exportfs.h
+@@ -43,7 +43,7 @@ struct fid {
+ u32 parent_ino;
+ u32 parent_gen;
+ } i32;
+- __u32 raw[6];
++ __u32 raw[0];
+ };
+ };
+
+diff --git a/include/linux/file.h b/include/linux/file.h
+index 7239baa..69baf5a 100644
+--- a/include/linux/file.h
++++ b/include/linux/file.h
+@@ -61,6 +61,7 @@ extern struct kmem_cache *filp_cachep;
+
+ extern void __fput(struct file *);
+ extern void fput(struct file *);
++extern void drop_file_write_access(struct file *file);
+
+ struct file_operations;
+ struct vfsmount;
+@@ -116,7 +117,8 @@ struct task_struct;
+
+ struct files_struct *get_files_struct(struct task_struct *);
+ void put_files_struct(struct files_struct *fs);
+-void reset_files_struct(struct task_struct *, struct files_struct *);
++void reset_files_struct(struct files_struct *);
++int unshare_files(struct files_struct **);
+
+ extern struct kmem_cache *files_cachep;
+
+diff --git a/include/linux/filter.h b/include/linux/filter.h
+index ddfa037..b6ea9aa 100644
+--- a/include/linux/filter.h
++++ b/include/linux/filter.h
+@@ -37,21 +37,6 @@ struct sock_fprog /* Required for SO_ATTACH_FILTER. */
+ struct sock_filter __user *filter;
+ };
+
+-#ifdef __KERNEL__
+-struct sk_filter
+-{
+- atomic_t refcnt;
+- unsigned int len; /* Number of filter blocks */
+- struct rcu_head rcu;
+- struct sock_filter insns[0];
+-};
+-
+-static inline unsigned int sk_filter_len(struct sk_filter *fp)
+-{
+- return fp->len*sizeof(struct sock_filter) + sizeof(*fp);
+-}
+-#endif
+-
+ /*
+ * Instruction classes
+ */
+@@ -136,15 +121,31 @@ static inline unsigned int sk_filter_len(struct sk_filter *fp)
+ #define SKF_AD_PROTOCOL 0
+ #define SKF_AD_PKTTYPE 4
+ #define SKF_AD_IFINDEX 8
+-#define SKF_AD_MAX 12
++#define SKF_AD_NLATTR 12
++#define SKF_AD_MAX 16
+ #define SKF_NET_OFF (-0x100000)
+ #define SKF_LL_OFF (-0x200000)
+
+ #ifdef __KERNEL__
++struct sk_filter
++{
++ atomic_t refcnt;
++ unsigned int len; /* Number of filter blocks */
++ struct rcu_head rcu;
++ struct sock_filter insns[0];
++};
++
++static inline unsigned int sk_filter_len(const struct sk_filter *fp)
++{
++ return fp->len * sizeof(struct sock_filter) + sizeof(*fp);
++}
++
+ struct sk_buff;
+ struct sock;
+
+-extern unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen);
++extern int sk_filter(struct sock *sk, struct sk_buff *skb);
++extern unsigned int sk_run_filter(struct sk_buff *skb,
++ struct sock_filter *filter, int flen);
+ extern int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);
+ extern int sk_detach_filter(struct sock *sk);
+ extern int sk_chk_filter(struct sock_filter *filter, int flen);
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index b84b848..d6d7c52 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -287,9 +287,9 @@ extern int dir_notify_enable;
+ #include <linux/pid.h>
+ #include <linux/mutex.h>
+ #include <linux/capability.h>
++#include <linux/semaphore.h>
+
+ #include <asm/atomic.h>
+-#include <asm/semaphore.h>
+ #include <asm/byteorder.h>
+
+ struct export_operations;
+@@ -305,7 +305,6 @@ struct vfsmount;
+
+ extern void __init inode_init(void);
+ extern void __init inode_init_early(void);
+-extern void __init mnt_init(void);
+ extern void __init files_init(unsigned long);
+
+ struct buffer_head;
+@@ -776,6 +775,9 @@ static inline int ra_has_index(struct file_ra_state *ra, pgoff_t index)
+ index < ra->start + ra->size);
+ }
+
++#define FILE_MNT_WRITE_TAKEN 1
++#define FILE_MNT_WRITE_RELEASED 2
++
+ struct file {
+ /*
+ * fu_list becomes invalid after file_free is called and queued via
+@@ -810,6 +812,9 @@ struct file {
+ spinlock_t f_ep_lock;
+ #endif /* #ifdef CONFIG_EPOLL */
+ struct address_space *f_mapping;
++#ifdef CONFIG_DEBUG_WRITECOUNT
++ unsigned long f_mnt_write_state;
++#endif
+ };
+ extern spinlock_t files_lock;
+ #define file_list_lock() spin_lock(&files_lock);
+@@ -818,6 +823,49 @@ extern spinlock_t files_lock;
+ #define get_file(x) atomic_inc(&(x)->f_count)
+ #define file_count(x) atomic_read(&(x)->f_count)
+
++#ifdef CONFIG_DEBUG_WRITECOUNT
++static inline void file_take_write(struct file *f)
++{
++ WARN_ON(f->f_mnt_write_state != 0);
++ f->f_mnt_write_state = FILE_MNT_WRITE_TAKEN;
++}
++static inline void file_release_write(struct file *f)
++{
++ f->f_mnt_write_state |= FILE_MNT_WRITE_RELEASED;
++}
++static inline void file_reset_write(struct file *f)
++{
++ f->f_mnt_write_state = 0;
++}
++static inline void file_check_state(struct file *f)
++{
++ /*
++ * At this point, either both or neither of these bits
++ * should be set.
++ */
++ WARN_ON(f->f_mnt_write_state == FILE_MNT_WRITE_TAKEN);
++ WARN_ON(f->f_mnt_write_state == FILE_MNT_WRITE_RELEASED);
++}
++static inline int file_check_writeable(struct file *f)
++{
++ if (f->f_mnt_write_state == FILE_MNT_WRITE_TAKEN)
++ return 0;
++ printk(KERN_WARNING "writeable file with no "
++ "mnt_want_write()\n");
++ WARN_ON(1);
++ return -EINVAL;
++}
++#else /* !CONFIG_DEBUG_WRITECOUNT */
++static inline void file_take_write(struct file *filp) {}
++static inline void file_release_write(struct file *filp) {}
++static inline void file_reset_write(struct file *filp) {}
++static inline void file_check_state(struct file *filp) {}
++static inline int file_check_writeable(struct file *filp)
++{
++ return 0;
++}
++#endif /* CONFIG_DEBUG_WRITECOUNT */
++
+ #define MAX_NON_LFS ((1UL<<31) - 1)
+
+ /* Page cache limit. The filesystems should put that into their s_maxbytes
+@@ -925,6 +973,7 @@ extern int do_sync_mapping_range(struct address_space *mapping, loff_t offset,
+ /* fs/locks.c */
+ extern void locks_init_lock(struct file_lock *);
+ extern void locks_copy_lock(struct file_lock *, struct file_lock *);
++extern void __locks_copy_lock(struct file_lock *, const struct file_lock *);
+ extern void locks_remove_posix(struct file *, fl_owner_t);
+ extern void locks_remove_flock(struct file *);
+ extern void posix_test_lock(struct file *, struct file_lock *);
+@@ -1260,7 +1309,7 @@ struct super_operations {
+ int (*statfs) (struct dentry *, struct kstatfs *);
+ int (*remount_fs) (struct super_block *, int *, char *);
+ void (*clear_inode) (struct inode *);
+- void (*umount_begin) (struct vfsmount *, int);
++ void (*umount_begin) (struct super_block *);
+
+ int (*show_options)(struct seq_file *, struct vfsmount *);
+ int (*show_stats)(struct seq_file *, struct vfsmount *);
+@@ -1487,12 +1536,7 @@ extern struct vfsmount *kern_mount_data(struct file_system_type *, void *data);
+ #define kern_mount(type) kern_mount_data(type, NULL)
+ extern int may_umount_tree(struct vfsmount *);
+ extern int may_umount(struct vfsmount *);
+-extern void umount_tree(struct vfsmount *, int, struct list_head *);
+-extern void release_mounts(struct list_head *);
+ extern long do_mount(char *, char *, char *, unsigned long, void *);
+-extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int);
+-extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
+- struct vfsmount *);
+ extern struct vfsmount *collect_mounts(struct vfsmount *, struct dentry *);
+ extern void drop_collected_mounts(struct vfsmount *);
+
+@@ -1735,7 +1779,8 @@ extern struct file *create_read_pipe(struct file *f);
+ extern struct file *create_write_pipe(void);
+ extern void free_write_pipe(struct file *);
+
+-extern int open_namei(int dfd, const char *, int, int, struct nameidata *);
++extern struct file *do_filp_open(int dfd, const char *pathname,
++ int open_flag, int mode);
+ extern int may_open(struct nameidata *, int, int);
+
+ extern int kernel_read(struct file *, unsigned long, char *, unsigned long);
+@@ -1989,9 +2034,6 @@ static inline ino_t parent_ino(struct dentry *dentry)
+ return res;
+ }
+
+-/* kernel/fork.c */
+-extern int unshare_files(void);
+-
+ /* Transaction based IO helpers */
+
+ /*
+diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
+index 1831b19..2cad5c6 100644
+--- a/include/linux/fsl_devices.h
++++ b/include/linux/fsl_devices.h
+@@ -50,7 +50,7 @@ struct gianfar_platform_data {
+ u32 device_flags;
+ /* board specific information */
+ u32 board_flags;
+- u32 bus_id;
++ char bus_id[MII_BUS_ID_SIZE];
+ u32 phy_id;
+ u8 mac_addr[6];
+ phy_interface_t interface;
+diff --git a/include/linux/hdreg.h b/include/linux/hdreg.h
+index e38e759..c37e924 100644
+--- a/include/linux/hdreg.h
++++ b/include/linux/hdreg.h
+@@ -422,9 +422,11 @@ struct hd_geometry {
+ #define HDIO_SET_NOWERR 0x0325 /* change ignore-write-error flag */
+ #define HDIO_SET_DMA 0x0326 /* change use-dma flag */
+ #define HDIO_SET_PIO_MODE 0x0327 /* reconfig interface to new speed */
++#ifndef __KERNEL__
+ #define HDIO_SCAN_HWIF 0x0328 /* register and (re)scan interface */
+-#define HDIO_SET_NICE 0x0329 /* set nice flags */
+ #define HDIO_UNREGISTER_HWIF 0x032a /* unregister interface */
++#endif
++#define HDIO_SET_NICE 0x0329 /* set nice flags */
+ #define HDIO_SET_WCACHE 0x032b /* change write cache enable-disable */
+ #define HDIO_SET_ACOUSTIC 0x032c /* change acoustic behavior */
+ #define HDIO_SET_BUSSTATE 0x032d /* set the bus state of the hwif */
+diff --git a/include/linux/hdsmart.h b/include/linux/hdsmart.h
+deleted file mode 100644
+index 4f4faf9..0000000
+--- a/include/linux/hdsmart.h
++++ /dev/null
+@@ -1,126 +0,0 @@
+-/*
+- * linux/include/linux/hdsmart.h
+- *
+- * Copyright (C) 1999-2000 Michael Cornwell <cornwell at acm.org>
+- * Copyright (C) 2000 Andre Hedrick <andre at linux-ide.org>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2, or (at your option)
+- * any later version.
+- *
+- * You should have received a copy of the GNU General Public License
+- * (for example /usr/src/linux/COPYING); if not, write to the Free
+- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#ifndef _LINUX_HDSMART_H
+-#define _LINUX_HDSMART_H
+-
+-#ifndef __KERNEL__
+-#define OFFLINE_FULL_SCAN 0
+-#define SHORT_SELF_TEST 1
+-#define EXTEND_SELF_TEST 2
+-#define SHORT_CAPTIVE_SELF_TEST 129
+-#define EXTEND_CAPTIVE_SELF_TEST 130
+-
+-/* smart_attribute is the vendor specific in SFF-8035 spec */
+-typedef struct ata_smart_attribute_s {
+- unsigned char id;
+- unsigned short status_flag;
+- unsigned char normalized;
+- unsigned char worse_normal;
+- unsigned char raw[6];
+- unsigned char reserv;
+-} __attribute__ ((packed)) ata_smart_attribute_t;
+-
+-/* smart_values is format of the read drive Atrribute command */
+-typedef struct ata_smart_values_s {
+- unsigned short revnumber;
+- ata_smart_attribute_t vendor_attributes [30];
+- unsigned char offline_data_collection_status;
+- unsigned char self_test_exec_status;
+- unsigned short total_time_to_complete_off_line;
+- unsigned char vendor_specific_366;
+- unsigned char offline_data_collection_capability;
+- unsigned short smart_capability;
+- unsigned char errorlog_capability;
+- unsigned char vendor_specific_371;
+- unsigned char short_test_completion_time;
+- unsigned char extend_test_completion_time;
+- unsigned char reserved_374_385 [12];
+- unsigned char vendor_specific_386_509 [125];
+- unsigned char chksum;
+-} __attribute__ ((packed)) ata_smart_values_t;
+-
+-/* Smart Threshold data structures */
+-/* Vendor attribute of SMART Threshold */
+-typedef struct ata_smart_threshold_entry_s {
+- unsigned char id;
+- unsigned char normalized_threshold;
+- unsigned char reserved[10];
+-} __attribute__ ((packed)) ata_smart_threshold_entry_t;
+-
+-/* Format of Read SMART THreshold Command */
+-typedef struct ata_smart_thresholds_s {
+- unsigned short revnumber;
+- ata_smart_threshold_entry_t thres_entries[30];
+- unsigned char reserved[149];
+- unsigned char chksum;
+-} __attribute__ ((packed)) ata_smart_thresholds_t;
+-
+-typedef struct ata_smart_errorlog_command_struct_s {
+- unsigned char devicecontrolreg;
+- unsigned char featuresreg;
+- unsigned char sector_count;
+- unsigned char sector_number;
+- unsigned char cylinder_low;
+- unsigned char cylinder_high;
+- unsigned char drive_head;
+- unsigned char commandreg;
+- unsigned int timestamp;
+-} __attribute__ ((packed)) ata_smart_errorlog_command_struct_t;
+-
+-typedef struct ata_smart_errorlog_error_struct_s {
+- unsigned char error_condition;
+- unsigned char extended_error[14];
+- unsigned char state;
+- unsigned short timestamp;
+-} __attribute__ ((packed)) ata_smart_errorlog_error_struct_t;
+-
+-typedef struct ata_smart_errorlog_struct_s {
+- ata_smart_errorlog_command_struct_t commands[6];
+- ata_smart_errorlog_error_struct_t error_struct;
+-} __attribute__ ((packed)) ata_smart_errorlog_struct_t;
+-
+-typedef struct ata_smart_errorlog_s {
+- unsigned char revnumber;
+- unsigned char error_log_pointer;
+- ata_smart_errorlog_struct_t errorlog_struct[5];
+- unsigned short ata_error_count;
+- unsigned short non_fatal_count;
+- unsigned short drive_timeout_count;
+- unsigned char reserved[53];
+- unsigned char chksum;
+-} __attribute__ ((packed)) ata_smart_errorlog_t;
+-
+-typedef struct ata_smart_selftestlog_struct_s {
+- unsigned char selftestnumber;
+- unsigned char selfteststatus;
+- unsigned short timestamp;
+- unsigned char selftestfailurecheckpoint;
+- unsigned int lbafirstfailure;
+- unsigned char vendorspecific[15];
+-} __attribute__ ((packed)) ata_smart_selftestlog_struct_t;
+-
+-typedef struct ata_smart_selftestlog_s {
+- unsigned short revnumber;
+- ata_smart_selftestlog_struct_t selftest_struct[21];
+- unsigned char vendorspecific[2];
+- unsigned char mostrecenttest;
+- unsigned char resevered[2];
+- unsigned char chksum;
+-} __attribute__ ((packed)) ata_smart_selftestlog_t;
+-#endif /* __KERNEL__ */
+-
+-#endif /* _LINUX_HDSMART_H */
+diff --git a/include/linux/hid.h b/include/linux/hid.h
+index 74ff575..d951ec4 100644
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -284,6 +284,7 @@ struct hid_item {
+ #define HID_QUIRK_2WHEEL_MOUSE_HACK_B8 0x02000000
+ #define HID_QUIRK_HWHEEL_WHEEL_INVERT 0x04000000
+ #define HID_QUIRK_MICROSOFT_KEYS 0x08000000
++#define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000
+
+ /*
+ * Separate quirks for runtime report descriptor fixup
+@@ -296,6 +297,8 @@ struct hid_item {
+ #define HID_QUIRK_RDESC_MACBOOK_JIS 0x00000010
+ #define HID_QUIRK_RDESC_BUTTON_CONSUMER 0x00000020
+ #define HID_QUIRK_RDESC_SAMSUNG_REMOTE 0x00000040
++#define HID_QUIRK_RDESC_MICROSOFT_RECV_1028 0x00000080
++#define HID_QUIRK_RDESC_SUNPLUS_WDESKTOP 0x00000100
+
+ /*
+ * This is the global environment of the parser. This information is
+@@ -320,7 +323,7 @@ struct hid_global {
+ * This is the local environment. It is persistent up the next main-item.
+ */
+
+-#define HID_MAX_USAGES 8192
++#define HID_MAX_USAGES 12288
+ #define HID_DEFAULT_NUM_COLLECTIONS 16
+
+ struct hid_local {
+@@ -421,6 +424,7 @@ struct hid_control_fifo {
+ #define HID_RESET_PENDING 4
+ #define HID_SUSPENDED 5
+ #define HID_CLEAR_HALT 6
++#define HID_DISCONNECTED 7
+
+ struct hid_input {
+ struct list_head list;
+@@ -452,8 +456,6 @@ struct hid_device { /* device report descriptor */
+ void *hidraw;
+ int minor; /* Hiddev minor number */
+
+- wait_queue_head_t wait; /* For sleeping */
+-
+ int open; /* is the device open by anyone? */
+ char name[128]; /* Device name */
+ char phys[64]; /* Device physical location */
+@@ -530,14 +532,12 @@ int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int
+ int hidinput_mapping_quirks(struct hid_usage *, struct input_dev *, unsigned long **, int *);
+ int hidinput_event_quirks(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
+ int hidinput_apple_event(struct hid_device *, struct input_dev *, struct hid_usage *, __s32);
+-void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt);
+ void hid_output_report(struct hid_report *report, __u8 *data);
+ void hid_free_device(struct hid_device *device);
+ struct hid_device *hid_parse_report(__u8 *start, unsigned size);
+
+ /* HID quirks API */
+ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct);
+-int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct, const u32 quirks);
+ int usbhid_quirks_init(char **quirks_param);
+ void usbhid_quirks_exit(void);
+ void usbhid_fixup_report_descriptor(const u16, const u16, char *, unsigned, char **);
+@@ -546,6 +546,7 @@ void usbhid_fixup_report_descriptor(const u16, const u16, char *, unsigned, char
+ int hid_ff_init(struct hid_device *hid);
+
+ int hid_lgff_init(struct hid_device *hid);
++int hid_lg2ff_init(struct hid_device *hid);
+ int hid_plff_init(struct hid_device *hid);
+ int hid_tmff_init(struct hid_device *hid);
+ int hid_zpff_init(struct hid_device *hid);
+@@ -566,7 +567,11 @@ static inline int hid_ff_init(struct hid_device *hid) { return -1; }
+ #define dbg_hid_line(format, arg...) if (hid_debug) \
+ printk(format, ## arg)
+ #else
+-#define dbg_hid(format, arg...) do {} while (0)
++static inline int __attribute__((format(printf, 1, 2)))
++dbg_hid(const char *fmt, ...)
++{
++ return 0;
++}
+ #define dbg_hid_line dbg_hid
+ #endif
+
+diff --git a/include/linux/hidraw.h b/include/linux/hidraw.h
+index 0536f29..dbb5c8c 100644
+--- a/include/linux/hidraw.h
++++ b/include/linux/hidraw.h
+@@ -16,6 +16,7 @@
+ */
+
+ #include <linux/hid.h>
++#include <linux/types.h>
+
+ struct hidraw_report_descriptor {
+ __u32 size;
+diff --git a/include/linux/hil_mlc.h b/include/linux/hil_mlc.h
+index 8df29ca..394a840 100644
+--- a/include/linux/hil_mlc.h
++++ b/include/linux/hil_mlc.h
+@@ -34,7 +34,7 @@
+ #include <linux/hil.h>
+ #include <linux/time.h>
+ #include <linux/interrupt.h>
+-#include <asm/semaphore.h>
++#include <linux/semaphore.h>
+ #include <linux/serio.h>
+ #include <linux/list.h>
+
+diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
+index 1ad56a7..56f3236 100644
+--- a/include/linux/hrtimer.h
++++ b/include/linux/hrtimer.h
+@@ -173,7 +173,6 @@ struct hrtimer_clock_base {
+ * struct hrtimer_cpu_base - the per cpu clock bases
+ * @lock: lock protecting the base and associated clock bases
+ * and timers
+- * @lock_key: the lock_class_key for use with lockdep
+ * @clock_base: array of clock bases for this cpu
+ * @curr_timer: the timer which is executing a callback right now
+ * @expires_next: absolute time of the next event which was scheduled
+@@ -189,7 +188,6 @@ struct hrtimer_clock_base {
+ */
+ struct hrtimer_cpu_base {
+ spinlock_t lock;
+- struct lock_class_key lock_key;
+ struct hrtimer_clock_base clock_base[HRTIMER_MAX_CLOCK_BASES];
+ struct list_head cb_pending;
+ #ifdef CONFIG_HIGH_RES_TIMERS
+diff --git a/include/linux/hw_random.h b/include/linux/hw_random.h
+index 4213182..85d1191 100644
+--- a/include/linux/hw_random.h
++++ b/include/linux/hw_random.h
+@@ -44,15 +44,7 @@ struct hwrng {
+ /** Register a new Hardware Random Number Generator driver. */
+ extern int hwrng_register(struct hwrng *rng);
+ /** Unregister a Hardware Random Number Generator driver. */
+-extern void __hwrng_unregister(struct hwrng *rng, bool suspended);
+-static inline void hwrng_unregister(struct hwrng *rng)
+-{
+- __hwrng_unregister(rng, false);
+-}
+-static inline void hwrng_unregister_suspended(struct hwrng *rng)
+-{
+- __hwrng_unregister(rng, true);
+-}
++extern void hwrng_unregister(struct hwrng *rng);
+
+ #endif /* __KERNEL__ */
+ #endif /* LINUX_HWRANDOM_H_ */
+diff --git a/include/linux/i2c-algo-pca.h b/include/linux/i2c-algo-pca.h
+index fce47c0..adcb3dc 100644
+--- a/include/linux/i2c-algo-pca.h
++++ b/include/linux/i2c-algo-pca.h
+@@ -1,14 +1,41 @@
+ #ifndef _LINUX_I2C_ALGO_PCA_H
+ #define _LINUX_I2C_ALGO_PCA_H
+
++/* Clock speeds for the bus */
++#define I2C_PCA_CON_330kHz 0x00
++#define I2C_PCA_CON_288kHz 0x01
++#define I2C_PCA_CON_217kHz 0x02
++#define I2C_PCA_CON_146kHz 0x03
++#define I2C_PCA_CON_88kHz 0x04
++#define I2C_PCA_CON_59kHz 0x05
++#define I2C_PCA_CON_44kHz 0x06
++#define I2C_PCA_CON_36kHz 0x07
++
++/* PCA9564 registers */
++#define I2C_PCA_STA 0x00 /* STATUS Read Only */
++#define I2C_PCA_TO 0x00 /* TIMEOUT Write Only */
++#define I2C_PCA_DAT 0x01 /* DATA Read/Write */
++#define I2C_PCA_ADR 0x02 /* OWN ADR Read/Write */
++#define I2C_PCA_CON 0x03 /* CONTROL Read/Write */
++
++#define I2C_PCA_CON_AA 0x80 /* Assert Acknowledge */
++#define I2C_PCA_CON_ENSIO 0x40 /* Enable */
++#define I2C_PCA_CON_STA 0x20 /* Start */
++#define I2C_PCA_CON_STO 0x10 /* Stop */
++#define I2C_PCA_CON_SI 0x08 /* Serial Interrupt */
++#define I2C_PCA_CON_CR 0x07 /* Clock Rate (MASK) */
++
+ struct i2c_algo_pca_data {
+- int (*get_own) (struct i2c_algo_pca_data *adap); /* Obtain own address */
+- int (*get_clock) (struct i2c_algo_pca_data *adap);
+- void (*write_byte) (struct i2c_algo_pca_data *adap, int reg, int val);
+- int (*read_byte) (struct i2c_algo_pca_data *adap, int reg);
+- int (*wait_for_interrupt) (struct i2c_algo_pca_data *adap);
++ void *data; /* private low level data */
++ void (*write_byte) (void *data, int reg, int val);
++ int (*read_byte) (void *data, int reg);
++ int (*wait_for_completion) (void *data);
++ void (*reset_chip) (void *data);
++ /* i2c_clock values are defined in linux/i2c-algo-pca.h */
++ unsigned int i2c_clock;
+ };
+
+ int i2c_pca_add_bus(struct i2c_adapter *);
++int i2c_pca_add_numbered_bus(struct i2c_adapter *);
+
+ #endif /* _LINUX_I2C_ALGO_PCA_H */
+diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
+index b979112..32eb8bb 100644
+--- a/include/linux/i2c-id.h
++++ b/include/linux/i2c-id.h
+@@ -125,6 +125,7 @@
+ #define I2C_HW_B_CX2341X 0x010020 /* Conexant CX2341X MPEG encoder cards */
+ #define I2C_HW_B_INTELFB 0x010021 /* intel framebuffer driver */
+ #define I2C_HW_B_CX23885 0x010022 /* conexant 23885 based tv cards (bus1) */
++#define I2C_HW_B_AU0828 0x010023 /* auvitek au0828 usb bridge */
+
+ /* --- PCF 8584 based algorithms */
+ #define I2C_HW_P_ELEK 0x020002 /* Elektor ISA Bus inteface card */
+diff --git a/include/linux/i2c-pca-platform.h b/include/linux/i2c-pca-platform.h
+new file mode 100644
+index 0000000..3d19187
+--- /dev/null
++++ b/include/linux/i2c-pca-platform.h
+@@ -0,0 +1,12 @@
++#ifndef I2C_PCA9564_PLATFORM_H
++#define I2C_PCA9564_PLATFORM_H
++
++struct i2c_pca9564_pf_platform_data {
++ int gpio; /* pin to reset chip. driver will work when
++ * not supplied (negative value), but it
++ * cannot exit some error conditions then */
++ int i2c_clock_speed; /* values are defined in linux/i2c-algo-pca.h */
++ int timeout; /* timeout = this value * 10us */
++};
++
++#endif /* I2C_PCA9564_PLATFORM_H */
+diff --git a/include/linux/i2c/tps65010.h b/include/linux/i2c/tps65010.h
+index 7021635..918c535 100644
+--- a/include/linux/i2c/tps65010.h
++++ b/include/linux/i2c/tps65010.h
+@@ -152,5 +152,35 @@ extern int tps65010_config_vregs1(unsigned value);
+ */
+ extern int tps65013_set_low_pwr(unsigned mode);
+
++
++struct i2c_client;
++
++/**
++ * struct tps65010_board - packages GPIO and LED lines
++ * @base: the GPIO number to assign to GPIO-1
++ * @outmask: bit (N-1) is set to allow GPIO-N to be used as an
++ * (open drain) output
++ * @setup: optional callback issued once the GPIOs are valid
++ * @teardown: optional callback issued before the GPIOs are invalidated
++ * @context: optional parameter passed to setup() and teardown()
++ *
++ * Board data may be used to package the GPIO (and LED) lines for use
++ * in by the generic GPIO and LED frameworks. The first four GPIOs
++ * starting at gpio_base are GPIO1..GPIO4. The next two are LED1/nPG
++ * and LED2 (with hardware blinking capability, not currently exposed).
++ *
++ * The @setup callback may be used with the kind of board-specific glue
++ * which hands the (now-valid) GPIOs to other drivers, or which puts
++ * devices in their initial states using these GPIOs.
++ */
++struct tps65010_board {
++ int base;
++ unsigned outmask;
++
++ int (*setup)(struct i2c_client *client, void *context);
++ int (*teardown)(struct i2c_client *client, void *context);
++ void *context;
++};
++
+ #endif /* __LINUX_I2C_TPS65010_H */
+
+diff --git a/include/linux/i2o.h b/include/linux/i2o.h
+index 7da5b98..e92170d 100644
+--- a/include/linux/i2o.h
++++ b/include/linux/i2o.h
+@@ -33,9 +33,9 @@
+ #include <linux/mempool.h>
+ #include <linux/mutex.h>
+ #include <linux/scatterlist.h>
++#include <linux/semaphore.h> /* Needed for MUTEX init macros */
+
+ #include <asm/io.h>
+-#include <asm/semaphore.h> /* Needed for MUTEX init macros */
+
+ /* message queue empty */
+ #define I2O_QUEUE_EMPTY 0xffffffff
+diff --git a/include/linux/icmpv6.h b/include/linux/icmpv6.h
+index 7c5e981..0306744 100644
+--- a/include/linux/icmpv6.h
++++ b/include/linux/icmpv6.h
+@@ -176,12 +176,21 @@ extern void icmpv6_send(struct sk_buff *skb,
+ __u32 info,
+ struct net_device *dev);
+
+-extern int icmpv6_init(struct net_proto_family *ops);
++extern int icmpv6_init(void);
+ extern int icmpv6_err_convert(int type, int code,
+ int *err);
+ extern void icmpv6_cleanup(void);
+ extern void icmpv6_param_prob(struct sk_buff *skb,
+ int code, int pos);
++
++struct flowi;
++struct in6_addr;
++extern void icmpv6_flow_init(struct sock *sk,
++ struct flowi *fl,
++ u8 type,
++ const struct in6_addr *saddr,
++ const struct in6_addr *daddr,
++ int oif);
+ #endif
+
+ #endif
+diff --git a/include/linux/ide.h b/include/linux/ide.h
+index bc26b2f..f20410d 100644
+--- a/include/linux/ide.h
++++ b/include/linux/ide.h
+@@ -23,7 +23,6 @@
+ #include <asm/byteorder.h>
+ #include <asm/system.h>
+ #include <asm/io.h>
+-#include <asm/semaphore.h>
+ #include <asm/mutex.h>
+
+ #if defined(CONFIG_CRIS) || defined(CONFIG_FRV)
+@@ -82,24 +81,10 @@ typedef unsigned char byte; /* used everywhere */
+
+ #define IDE_FEATURE_OFFSET IDE_ERROR_OFFSET
+ #define IDE_COMMAND_OFFSET IDE_STATUS_OFFSET
+-
+-#define IDE_DATA_REG (HWIF(drive)->io_ports[IDE_DATA_OFFSET])
+-#define IDE_ERROR_REG (HWIF(drive)->io_ports[IDE_ERROR_OFFSET])
+-#define IDE_NSECTOR_REG (HWIF(drive)->io_ports[IDE_NSECTOR_OFFSET])
+-#define IDE_SECTOR_REG (HWIF(drive)->io_ports[IDE_SECTOR_OFFSET])
+-#define IDE_LCYL_REG (HWIF(drive)->io_ports[IDE_LCYL_OFFSET])
+-#define IDE_HCYL_REG (HWIF(drive)->io_ports[IDE_HCYL_OFFSET])
+-#define IDE_SELECT_REG (HWIF(drive)->io_ports[IDE_SELECT_OFFSET])
+-#define IDE_STATUS_REG (HWIF(drive)->io_ports[IDE_STATUS_OFFSET])
+-#define IDE_CONTROL_REG (HWIF(drive)->io_ports[IDE_CONTROL_OFFSET])
+-#define IDE_IRQ_REG (HWIF(drive)->io_ports[IDE_IRQ_OFFSET])
+-
+-#define IDE_FEATURE_REG IDE_ERROR_REG
+-#define IDE_COMMAND_REG IDE_STATUS_REG
+-#define IDE_ALTSTATUS_REG IDE_CONTROL_REG
+-#define IDE_IREASON_REG IDE_NSECTOR_REG
+-#define IDE_BCOUNTL_REG IDE_LCYL_REG
+-#define IDE_BCOUNTH_REG IDE_HCYL_REG
++#define IDE_ALTSTATUS_OFFSET IDE_CONTROL_OFFSET
++#define IDE_IREASON_OFFSET IDE_NSECTOR_OFFSET
++#define IDE_BCOUNTL_OFFSET IDE_LCYL_OFFSET
++#define IDE_BCOUNTH_OFFSET IDE_HCYL_OFFSET
+
+ #define OK_STAT(stat,good,bad) (((stat)&((good)|(bad)))==(good))
+ #define BAD_R_STAT (BUSY_STAT | ERR_STAT)
+@@ -169,7 +154,7 @@ enum { ide_unknown, ide_generic, ide_pci,
+ ide_rz1000, ide_trm290,
+ ide_cmd646, ide_cy82c693, ide_4drives,
+ ide_pmac, ide_etrax100, ide_acorn,
+- ide_au1xxx, ide_palm3710, ide_forced
++ ide_au1xxx, ide_palm3710
+ };
+
+ typedef u8 hwif_chipset_t;
+@@ -185,15 +170,9 @@ typedef struct hw_regs_s {
+ struct device *dev;
+ } hw_regs_t;
+
+-struct hwif_s * ide_find_port(unsigned long);
+-struct hwif_s *ide_deprecated_find_port(unsigned long);
+ void ide_init_port_data(struct hwif_s *, unsigned int);
+ void ide_init_port_hw(struct hwif_s *, hw_regs_t *);
+
+-struct ide_drive_s;
+-int ide_register_hw(hw_regs_t *, void (*)(struct ide_drive_s *),
+- struct hwif_s **);
+-
+ static inline void ide_std_init_ports(hw_regs_t *hw,
+ unsigned long io_addr,
+ unsigned long ctl_addr)
+@@ -213,45 +192,6 @@ static inline void ide_std_init_ports(hw_regs_t *hw,
+ #define MAX_HWIFS CONFIG_IDE_MAX_HWIFS
+ #endif
+
+-/* needed on alpha, x86/x86_64, ia64, mips, ppc32 and sh */
+-#ifndef IDE_ARCH_OBSOLETE_DEFAULTS
+-# define ide_default_io_base(index) (0)
+-# define ide_default_irq(base) (0)
+-# define ide_init_default_irq(base) (0)
+-#endif
+-
+-#ifdef CONFIG_IDE_ARCH_OBSOLETE_INIT
+-static inline void ide_init_hwif_ports(hw_regs_t *hw,
+- unsigned long io_addr,
+- unsigned long ctl_addr,
+- int *irq)
+-{
+- if (!ctl_addr)
+- ide_std_init_ports(hw, io_addr, ide_default_io_ctl(io_addr));
+- else
+- ide_std_init_ports(hw, io_addr, ctl_addr);
+-
+- if (irq)
+- *irq = 0;
+-
+- hw->io_ports[IDE_IRQ_OFFSET] = 0;
+-
+-#ifdef CONFIG_PPC32
+- if (ppc_ide_md.ide_init_hwif)
+- ppc_ide_md.ide_init_hwif(hw, io_addr, ctl_addr, irq);
+-#endif
+-}
+-#else
+-static inline void ide_init_hwif_ports(hw_regs_t *hw,
+- unsigned long io_addr,
+- unsigned long ctl_addr,
+- int *irq)
+-{
+- if (io_addr || ctl_addr)
+- printk(KERN_WARNING "%s: must not be called\n", __FUNCTION__);
+-}
+-#endif /* CONFIG_IDE_ARCH_OBSOLETE_INIT */
+-
+ /* Currently only m68k, apus and m8xx need it */
+ #ifndef IDE_ARCH_ACK_INTR
+ # define ide_ack_intr(hwif) (1)
+@@ -406,7 +346,7 @@ typedef struct ide_drive_s {
+ u8 wcache; /* status of write cache */
+ u8 acoustic; /* acoustic management */
+ u8 media; /* disk, cdrom, tape, floppy, ... */
+- u8 ctl; /* "normal" value for IDE_CONTROL_REG */
++ u8 ctl; /* "normal" value for Control register */
+ u8 ready_stat; /* min status value for drive ready */
+ u8 mult_count; /* current multiple sector setting */
+ u8 mult_req; /* requested multiple sector setting */
+@@ -507,8 +447,6 @@ typedef struct hwif_s {
+ void (*maskproc)(ide_drive_t *, int);
+ /* check host's drive quirk list */
+ void (*quirkproc)(ide_drive_t *);
+- /* driver soft-power interface */
+- int (*busproc)(ide_drive_t *, int);
+ #endif
+ u8 (*mdma_filter)(ide_drive_t *);
+ u8 (*udma_filter)(ide_drive_t *);
+@@ -578,15 +516,15 @@ typedef struct hwif_s {
+
+ unsigned noprobe : 1; /* don't probe for this interface */
+ unsigned present : 1; /* this interface exists */
+- unsigned hold : 1; /* this interface is always present */
+ unsigned serialized : 1; /* serialized all channel operation */
+ unsigned sharing_irq: 1; /* 1 = sharing irq with another hwif */
+ unsigned reset : 1; /* reset after probe */
+ unsigned sg_mapped : 1; /* sg_table and sg_nents are ready */
+ unsigned mmio : 1; /* host uses MMIO */
+- unsigned straight8 : 1; /* Alan's straight 8 check */
+
+- struct device gendev;
++ struct device gendev;
++ struct device *portdev;
++
+ struct completion gendev_rel_comp; /* To deal with device release() */
+
+ void *hwif_data; /* extra hwif data */
+@@ -647,6 +585,68 @@ int set_io_32bit(ide_drive_t *, int);
+ int set_pio_mode(ide_drive_t *, int);
+ int set_using_dma(ide_drive_t *, int);
+
++/* ATAPI packet command flags */
++enum {
++ /* set when an error is considered normal - no retry (ide-tape) */
++ PC_FLAG_ABORT = (1 << 0),
++ PC_FLAG_SUPPRESS_ERROR = (1 << 1),
++ PC_FLAG_WAIT_FOR_DSC = (1 << 2),
++ PC_FLAG_DMA_OK = (1 << 3),
++ PC_FLAG_DMA_RECOMMENDED = (1 << 4),
++ PC_FLAG_DMA_IN_PROGRESS = (1 << 5),
++ PC_FLAG_DMA_ERROR = (1 << 6),
++ PC_FLAG_WRITING = (1 << 7),
++ /* command timed out */
++ PC_FLAG_TIMEDOUT = (1 << 8),
++};
++
++struct ide_atapi_pc {
++ /* actual packet bytes */
++ u8 c[12];
++ /* incremented on each retry */
++ int retries;
++ int error;
++
++ /* bytes to transfer */
++ int req_xfer;
++ /* bytes actually transferred */
++ int xferred;
++
++ /* data buffer */
++ u8 *buf;
++ /* current buffer position */
++ u8 *cur_pos;
++ int buf_size;
++ /* missing/available data on the current buffer */
++ int b_count;
++
++ /* the corresponding request */
++ struct request *rq;
++
++ unsigned long flags;
++
++ /*
++ * those are more or less driver-specific and some of them are subject
++ * to change/removal later.
++ */
++ u8 pc_buf[256];
++ void (*idefloppy_callback) (ide_drive_t *);
++ ide_startstop_t (*idetape_callback) (ide_drive_t *);
++
++ /* idetape only */
++ struct idetape_bh *bh;
++ char *b_data;
++
++ /* idescsi only for now */
++ struct scatterlist *sg;
++ unsigned int sg_cnt;
++
++ struct scsi_cmnd *scsi_cmd;
++ void (*done) (struct scsi_cmnd *);
++
++ unsigned long timeout;
++};
++
+ #ifdef CONFIG_IDE_PROC_FS
+ /*
+ * configurable drive settings
+@@ -691,6 +691,7 @@ void proc_ide_create(void);
+ void proc_ide_destroy(void);
+ void ide_proc_register_port(ide_hwif_t *);
+ void ide_proc_port_register_devices(ide_hwif_t *);
++void ide_proc_unregister_device(ide_drive_t *);
+ void ide_proc_unregister_port(ide_hwif_t *);
+ void ide_proc_register_driver(ide_drive_t *, ide_driver_t *);
+ void ide_proc_unregister_driver(ide_drive_t *, ide_driver_t *);
+@@ -724,6 +725,7 @@ static inline void proc_ide_create(void) { ; }
+ static inline void proc_ide_destroy(void) { ; }
+ static inline void ide_proc_register_port(ide_hwif_t *hwif) { ; }
+ static inline void ide_proc_port_register_devices(ide_hwif_t *hwif) { ; }
++static inline void ide_proc_unregister_device(ide_drive_t *drive) { ; }
+ static inline void ide_proc_unregister_port(ide_hwif_t *hwif) { ; }
+ static inline void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver) { ; }
+ static inline void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver) { ; }
+@@ -805,6 +807,13 @@ extern ide_hwif_t ide_hwifs[]; /* master data repository */
+ #endif
+ extern int noautodma;
+
++ide_hwif_t *ide_find_port_slot(const struct ide_port_info *);
++
++static inline ide_hwif_t *ide_find_port(void)
++{
++ return ide_find_port_slot(NULL);
++}
++
+ extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs);
+ int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq,
+ int uptodate, int nr_sectors);
+@@ -990,7 +999,6 @@ extern void do_ide_request(struct request_queue *);
+ void ide_init_disk(struct gendisk *, ide_drive_t *);
+
+ #ifdef CONFIG_IDEPCI_PCIBUS_ORDER
+-extern int ide_scan_direction;
+ extern int __ide_pci_register_driver(struct pci_driver *driver, struct module *owner, const char *mod_name);
+ #define ide_pci_register_driver(d) __ide_pci_register_driver(d, THIS_MODULE, KBUILD_MODNAME)
+ #else
+@@ -1024,8 +1032,8 @@ enum {
+ IDE_HFLAG_SINGLE = (1 << 1),
+ /* don't use legacy PIO blacklist */
+ IDE_HFLAG_PIO_NO_BLACKLIST = (1 << 2),
+- /* don't use conservative PIO "downgrade" */
+- IDE_HFLAG_PIO_NO_DOWNGRADE = (1 << 3),
++ /* set for the second port of QD65xx */
++ IDE_HFLAG_QD_2ND_PORT = (1 << 3),
+ /* use PIO8/9 for prefetch off/on */
+ IDE_HFLAG_ABUSE_PREFETCH = (1 << 4),
+ /* use PIO6/7 for fast-devsel off/on */
+@@ -1047,8 +1055,8 @@ enum {
+ IDE_HFLAG_VDMA = (1 << 11),
+ /* ATAPI DMA is unsupported */
+ IDE_HFLAG_NO_ATAPI_DMA = (1 << 12),
+- /* set if host is a "bootable" controller */
+- IDE_HFLAG_BOOTABLE = (1 << 13),
++ /* set if host is a "non-bootable" controller */
++ IDE_HFLAG_NON_BOOTABLE = (1 << 13),
+ /* host doesn't support DMA */
+ IDE_HFLAG_NO_DMA = (1 << 14),
+ /* check if host is PCI IDE device before allowing DMA */
+@@ -1076,8 +1084,6 @@ enum {
+ /* unmask IRQs */
+ IDE_HFLAG_UNMASK_IRQS = (1 << 25),
+ IDE_HFLAG_ABUSE_SET_DMA_MODE = (1 << 26),
+- /* host is CY82C693 */
+- IDE_HFLAG_CY82C693 = (1 << 27),
+ /* force host out of "simplex" mode */
+ IDE_HFLAG_CLEAR_SIMPLEX = (1 << 28),
+ /* DSC overlap is unsupported */
+@@ -1089,9 +1095,9 @@ enum {
+ };
+
+ #ifdef CONFIG_BLK_DEV_OFFBOARD
+-# define IDE_HFLAG_OFF_BOARD IDE_HFLAG_BOOTABLE
+-#else
+ # define IDE_HFLAG_OFF_BOARD 0
++#else
++# define IDE_HFLAG_OFF_BOARD IDE_HFLAG_NON_BOOTABLE
+ #endif
+
+ struct ide_port_info {
+@@ -1195,7 +1201,7 @@ static inline void ide_acpi_set_state(ide_hwif_t *hwif, int on) {}
+ void ide_remove_port_from_hwgroup(ide_hwif_t *);
+ extern int ide_hwif_request_regions(ide_hwif_t *hwif);
+ extern void ide_hwif_release_regions(ide_hwif_t* hwif);
+-void ide_unregister(unsigned int, int, int);
++void ide_unregister(unsigned int);
+
+ void ide_register_region(struct gendisk *);
+ void ide_unregister_region(struct gendisk *);
+@@ -1204,6 +1210,8 @@ void ide_undecoded_slave(ide_drive_t *);
+
+ int ide_device_add_all(u8 *idx, const struct ide_port_info *);
+ int ide_device_add(u8 idx[4], const struct ide_port_info *);
++void ide_port_unregister_devices(ide_hwif_t *);
++void ide_port_scan(ide_hwif_t *);
+
+ static inline void *ide_get_hwifdata (ide_hwif_t * hwif)
+ {
+@@ -1279,6 +1287,7 @@ extern struct mutex ide_cfg_mtx;
+ #define local_irq_set(flags) do { local_save_flags((flags)); local_irq_enable_in_hardirq(); } while (0)
+
+ extern struct bus_type ide_bus_type;
++extern struct class *ide_port_class;
+
+ /* check if CACHE FLUSH (EXT) command is supported (bits defined in ATA-6) */
+ #define ide_id_has_flush_cache(id) ((id)->cfs_enable_2 & 0x3000)
+@@ -1307,7 +1316,10 @@ static inline ide_drive_t *ide_get_paired_drive(ide_drive_t *drive)
+
+ static inline void ide_set_irq(ide_drive_t *drive, int on)
+ {
+- drive->hwif->OUTB(drive->ctl | (on ? 0 : 2), IDE_CONTROL_REG);
++ ide_hwif_t *hwif = drive->hwif;
++
++ hwif->OUTB(drive->ctl | (on ? 0 : 2),
++ hwif->io_ports[IDE_CONTROL_OFFSET]);
+ }
+
+ static inline u8 ide_read_status(ide_drive_t *drive)
+@@ -1331,4 +1343,26 @@ static inline u8 ide_read_error(ide_drive_t *drive)
+ return hwif->INB(hwif->io_ports[IDE_ERROR_OFFSET]);
+ }
+
++/*
++ * Too bad. The drive wants to send us data which we are not ready to accept.
++ * Just throw it away.
++ */
++static inline void ide_atapi_discard_data(ide_drive_t *drive, unsigned bcount)
++{
++ ide_hwif_t *hwif = drive->hwif;
++
++ /* FIXME: use ->atapi_input_bytes */
++ while (bcount--)
++ (void)hwif->INB(hwif->io_ports[IDE_DATA_OFFSET]);
++}
++
++static inline void ide_atapi_write_zeros(ide_drive_t *drive, unsigned bcount)
++{
++ ide_hwif_t *hwif = drive->hwif;
++
++ /* FIXME: use ->atapi_output_bytes */
++ while (bcount--)
++ hwif->OUTB(0, hwif->io_ports[IDE_DATA_OFFSET]);
++}
++
+ #endif /* _IDE_H */
+diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
+index f577c8f..529f301 100644
+--- a/include/linux/ieee80211.h
++++ b/include/linux/ieee80211.h
+@@ -97,6 +97,7 @@
+ #define IEEE80211_MAX_FRAME_LEN 2352
+
+ #define IEEE80211_MAX_SSID_LEN 32
++#define IEEE80211_MAX_MESH_ID_LEN 32
+
+ struct ieee80211_hdr {
+ __le16 frame_control;
+@@ -109,6 +110,16 @@ struct ieee80211_hdr {
+ } __attribute__ ((packed));
+
+
++struct ieee80211s_hdr {
++ u8 flags;
++ u8 ttl;
++ u8 seqnum[3];
++ u8 eaddr1[6];
++ u8 eaddr2[6];
++ u8 eaddr3[6];
++} __attribute__ ((packed));
++
++
+ struct ieee80211_mgmt {
+ __le16 frame_control;
+ __le16 duration;
+@@ -206,6 +217,23 @@ struct ieee80211_mgmt {
+ __le16 params;
+ __le16 reason_code;
+ } __attribute__((packed)) delba;
++ struct{
++ u8 action_code;
++ /* capab_info for open and confirm,
++ * reason for close
++ */
++ __le16 aux;
++ /* Followed in plink_confirm by status
++ * code, AID and supported rates,
++ * and directly by supported rates in
++ * plink_open and plink_close
++ */
++ u8 variable[0];
++ } __attribute__((packed)) plink_action;
++ struct{
++ u8 action_code;
++ u8 variable[0];
++ } __attribute__((packed)) mesh_action;
+ } u;
+ } __attribute__ ((packed)) action;
+ } u;
+@@ -437,6 +465,19 @@ enum ieee80211_eid {
+ WLAN_EID_TS_DELAY = 43,
+ WLAN_EID_TCLAS_PROCESSING = 44,
+ WLAN_EID_QOS_CAPA = 46,
++ /* 802.11s
++ *
++ * All mesh EID numbers are pending IEEE 802.11 ANA approval.
++ * The numbers have been incremented from those suggested in
++ * 802.11s/D2.0 so that MESH_CONFIG does not conflict with
++ * EXT_SUPP_RATES.
++ */
++ WLAN_EID_MESH_CONFIG = 51,
++ WLAN_EID_MESH_ID = 52,
++ WLAN_EID_PEER_LINK = 55,
++ WLAN_EID_PREQ = 68,
++ WLAN_EID_PREP = 69,
++ WLAN_EID_PERR = 70,
+ /* 802.11h */
+ WLAN_EID_PWR_CONSTRAINT = 32,
+ WLAN_EID_PWR_CAPABILITY = 33,
+diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h
+index 296e8e8..4d34018 100644
+--- a/include/linux/if_arp.h
++++ b/include/linux/if_arp.h
+@@ -156,6 +156,12 @@ static inline struct arphdr *arp_hdr(const struct sk_buff *skb)
+ {
+ return (struct arphdr *)skb_network_header(skb);
+ }
++
++static inline int arp_hdr_len(struct net_device *dev)
++{
++ /* ARP header, plus 2 device addresses, plus 2 IP addresses. */
++ return sizeof(struct arphdr) + (dev->addr_len + sizeof(u32)) * 2;
++}
+ #endif
+
+ #endif /* _LINUX_IF_ARP_H */
+diff --git a/include/linux/if_pppox.h b/include/linux/if_pppox.h
+index 40743e0..6fb7f17 100644
+--- a/include/linux/if_pppox.h
++++ b/include/linux/if_pppox.h
+@@ -24,7 +24,6 @@
+ #include <linux/if_ether.h>
+ #include <linux/if.h>
+ #include <linux/netdevice.h>
+-#include <asm/semaphore.h>
+ #include <linux/ppp_channel.h>
+ #endif /* __KERNEL__ */
+ #include <linux/if_pppol2tp.h>
+diff --git a/include/linux/if_tunnel.h b/include/linux/if_tunnel.h
+index 228eb4e..f1fbe9c 100644
+--- a/include/linux/if_tunnel.h
++++ b/include/linux/if_tunnel.h
+@@ -7,6 +7,10 @@
+ #define SIOCADDTUNNEL (SIOCDEVPRIVATE + 1)
+ #define SIOCDELTUNNEL (SIOCDEVPRIVATE + 2)
+ #define SIOCCHGTUNNEL (SIOCDEVPRIVATE + 3)
++#define SIOCGETPRL (SIOCDEVPRIVATE + 4)
++#define SIOCADDPRL (SIOCDEVPRIVATE + 5)
++#define SIOCDELPRL (SIOCDEVPRIVATE + 6)
++#define SIOCCHGPRL (SIOCDEVPRIVATE + 7)
+
+ #define GRE_CSUM __constant_htons(0x8000)
+ #define GRE_ROUTING __constant_htons(0x4000)
+@@ -17,9 +21,6 @@
+ #define GRE_FLAGS __constant_htons(0x00F8)
+ #define GRE_VERSION __constant_htons(0x0007)
+
+-/* i_flags values for SIT mode */
+-#define SIT_ISATAP 0x0001
+-
+ struct ip_tunnel_parm
+ {
+ char name[IFNAMSIZ];
+@@ -31,4 +32,19 @@ struct ip_tunnel_parm
+ struct iphdr iph;
+ };
+
++/* SIT-mode i_flags */
++#define SIT_ISATAP 0x0001
++
++struct ip_tunnel_prl {
++ __be32 addr;
++ __u16 flags;
++ __u16 __reserved;
++ __u32 datalen;
++ __u32 __reserved2;
++ void __user *data;
++};
++
++/* PRL flags */
++#define PRL_DEFAULT 0x0001
++
+ #endif /* _IF_TUNNEL_H_ */
+diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
+index 79504b2..15ace02 100644
+--- a/include/linux/if_vlan.h
++++ b/include/linux/if_vlan.h
+@@ -81,7 +81,9 @@ extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *));
+ #define VLAN_GROUP_ARRAY_PART_LEN (VLAN_GROUP_ARRAY_LEN/VLAN_GROUP_ARRAY_SPLIT_PARTS)
+
+ struct vlan_group {
+- int real_dev_ifindex; /* The ifindex of the ethernet(like) device the vlan is attached to. */
++ struct net_device *real_dev; /* The ethernet(like) device
++ * the vlan is attached to.
++ */
+ unsigned int nr_vlans;
+ struct hlist_node hlist; /* linked list */
+ struct net_device **vlan_devices_arrays[VLAN_GROUP_ARRAY_SPLIT_PARTS];
+@@ -93,7 +95,7 @@ static inline struct net_device *vlan_group_get_device(struct vlan_group *vg,
+ {
+ struct net_device **array;
+ array = vg->vlan_devices_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN];
+- return array[vlan_id % VLAN_GROUP_ARRAY_PART_LEN];
++ return array ? array[vlan_id % VLAN_GROUP_ARRAY_PART_LEN] : NULL;
+ }
+
+ static inline void vlan_group_set_device(struct vlan_group *vg,
+diff --git a/include/linux/if_wanpipe.h b/include/linux/if_wanpipe.h
+deleted file mode 100644
+index e594ca6..0000000
+--- a/include/linux/if_wanpipe.h
++++ /dev/null
+@@ -1,124 +0,0 @@
+-/*****************************************************************************
+-* if_wanpipe.h Header file for the Sangoma AF_WANPIPE Socket
+-*
+-* Author: Nenad Corbic
+-*
+-* Copyright: (c) 2000 Sangoma Technologies Inc.
+-*
+-* 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.
+-* ============================================================================
+-*
+-* Jan 28, 2000 Nenad Corbic Initial Version
+-*
+-*****************************************************************************/
+-
+-#ifndef __LINUX_IF_WAN_PACKET_H
+-#define __LINUX_IF_WAN_PACKET_H
+-
+-struct wan_sockaddr_ll
+-{
+- unsigned short sll_family;
+- unsigned short sll_protocol;
+- int sll_ifindex;
+- unsigned short sll_hatype;
+- unsigned char sll_pkttype;
+- unsigned char sll_halen;
+- unsigned char sll_addr[8];
+- unsigned char sll_device[14];
+- unsigned char sll_card[14];
+-};
+-
+-typedef struct
+-{
+- unsigned char free;
+- unsigned char state_sk;
+- int rcvbuf;
+- int sndbuf;
+- int rmem;
+- int wmem;
+- int sk_count;
+- unsigned char bound;
+- char name[14];
+- unsigned char d_state;
+- unsigned char svc;
+- unsigned short lcn;
+- unsigned char mbox;
+- unsigned char cmd_busy;
+- unsigned char command;
+- unsigned poll;
+- unsigned poll_cnt;
+- int rblock;
+-} wan_debug_hdr_t;
+-
+-#define MAX_NUM_DEBUG 10
+-#define X25_PROT 0x16
+-#define PVC_PROT 0x17
+-
+-typedef struct
+-{
+- wan_debug_hdr_t debug[MAX_NUM_DEBUG];
+-}wan_debug_t;
+-
+-#define SIOC_WANPIPE_GET_CALL_DATA (SIOCPROTOPRIVATE + 0)
+-#define SIOC_WANPIPE_SET_CALL_DATA (SIOCPROTOPRIVATE + 1)
+-#define SIOC_WANPIPE_ACCEPT_CALL (SIOCPROTOPRIVATE + 2)
+-#define SIOC_WANPIPE_CLEAR_CALL (SIOCPROTOPRIVATE + 3)
+-#define SIOC_WANPIPE_RESET_CALL (SIOCPROTOPRIVATE + 4)
+-#define SIOC_WANPIPE_DEBUG (SIOCPROTOPRIVATE + 5)
+-#define SIOC_WANPIPE_SET_NONBLOCK (SIOCPROTOPRIVATE + 6)
+-#define SIOC_WANPIPE_CHECK_TX (SIOCPROTOPRIVATE + 7)
+-#define SIOC_WANPIPE_SOCK_STATE (SIOCPROTOPRIVATE + 8)
+-
+-/* Packet types */
+-
+-#define WAN_PACKET_HOST 0 /* To us */
+-#define WAN_PACKET_BROADCAST 1 /* To all */
+-#define WAN_PACKET_MULTICAST 2 /* To group */
+-#define WAN_PACKET_OTHERHOST 3 /* To someone else */
+-#define WAN_PACKET_OUTGOING 4 /* Outgoing of any type */
+-/* These ones are invisible by user level */
+-#define WAN_PACKET_LOOPBACK 5 /* MC/BRD frame looped back */
+-#define WAN_PACKET_FASTROUTE 6 /* Fastrouted frame */
+-
+-
+-/* X25 specific */
+-#define WAN_PACKET_DATA 7
+-#define WAN_PACKET_CMD 8
+-#define WAN_PACKET_ASYNC 9
+-#define WAN_PACKET_ERR 10
+-
+-/* Packet socket options */
+-
+-#define WAN_PACKET_ADD_MEMBERSHIP 1
+-#define WAN_PACKET_DROP_MEMBERSHIP 2
+-
+-#define WAN_PACKET_MR_MULTICAST 0
+-#define WAN_PACKET_MR_PROMISC 1
+-#define WAN_PACKET_MR_ALLMULTI 2
+-
+-#ifdef __KERNEL__
+-
+-/* Private wanpipe socket structures. */
+-struct wanpipe_opt
+-{
+- void *mbox; /* Mail box */
+- void *card; /* Card bouded to */
+- struct net_device *dev; /* Bounded device */
+- unsigned short lcn; /* Binded LCN */
+- unsigned char svc; /* 0=pvc, 1=svc */
+- unsigned char timer; /* flag for delayed transmit*/
+- struct timer_list tx_timer;
+- unsigned poll_cnt;
+- unsigned char force; /* Used to force sock release */
+- atomic_t packet_sent;
+- unsigned short num;
+-};
+-
+-#define wp_sk(__sk) ((struct wanpipe_opt *)(__sk)->sk_protinfo)
+-
+-#endif
+-
+-#endif
+diff --git a/include/linux/igmp.h b/include/linux/igmp.h
+index f510e7e..f5a1a0d 100644
+--- a/include/linux/igmp.h
++++ b/include/linux/igmp.h
+@@ -80,27 +80,6 @@ struct igmpv3_query {
+ __be32 srcs[0];
+ };
+
+-#ifdef __KERNEL__
+-#include <linux/skbuff.h>
+-
+-static inline struct igmphdr *igmp_hdr(const struct sk_buff *skb)
+-{
+- return (struct igmphdr *)skb_transport_header(skb);
+-}
+-
+-static inline struct igmpv3_report *
+- igmpv3_report_hdr(const struct sk_buff *skb)
+-{
+- return (struct igmpv3_report *)skb_transport_header(skb);
+-}
+-
+-static inline struct igmpv3_query *
+- igmpv3_query_hdr(const struct sk_buff *skb)
+-{
+- return (struct igmpv3_query *)skb_transport_header(skb);
+-}
+-#endif
+-
+ #define IGMP_HOST_MEMBERSHIP_QUERY 0x11 /* From RFC1112 */
+ #define IGMP_HOST_MEMBERSHIP_REPORT 0x12 /* Ditto */
+ #define IGMP_DVMRP 0x13 /* DVMRP routing */
+@@ -151,6 +130,23 @@ static inline struct igmpv3_query *
+ #include <linux/timer.h>
+ #include <linux/in.h>
+
++static inline struct igmphdr *igmp_hdr(const struct sk_buff *skb)
++{
++ return (struct igmphdr *)skb_transport_header(skb);
++}
++
++static inline struct igmpv3_report *
++ igmpv3_report_hdr(const struct sk_buff *skb)
++{
++ return (struct igmpv3_report *)skb_transport_header(skb);
++}
++
++static inline struct igmpv3_query *
++ igmpv3_query_hdr(const struct sk_buff *skb)
++{
++ return (struct igmpv3_query *)skb_transport_header(skb);
++}
++
+ extern int sysctl_igmp_max_memberships;
+ extern int sysctl_igmp_max_msf;
+
+diff --git a/include/linux/in6.h b/include/linux/in6.h
+index 2a61c82..bc49204 100644
+--- a/include/linux/in6.h
++++ b/include/linux/in6.h
+@@ -48,6 +48,14 @@ extern const struct in6_addr in6addr_any;
+ #define IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } }
+ extern const struct in6_addr in6addr_loopback;
+ #define IN6ADDR_LOOPBACK_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } }
++#ifdef __KERNEL__
++extern const struct in6_addr in6addr_linklocal_allnodes;
++#define IN6ADDR_LINKLOCAL_ALLNODES_INIT \
++ { { { 0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } }
++extern const struct in6_addr in6addr_linklocal_allrouters;
++#define IN6ADDR_LINKLOCAL_ALLROUTERS_INIT \
++ { { { 0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2 } } }
++#endif
+
+ struct sockaddr_in6 {
+ unsigned short int sin6_family; /* AF_INET6 */
+@@ -249,4 +257,30 @@ struct in6_flowlabel_req
+ * IP6T_SO_GET_REVISION_TARGET 69
+ */
+
++/* RFC5014: Source address selection */
++#define IPV6_ADDR_PREFERENCES 72
++
++#define IPV6_PREFER_SRC_TMP 0x0001
++#define IPV6_PREFER_SRC_PUBLIC 0x0002
++#define IPV6_PREFER_SRC_PUBTMP_DEFAULT 0x0100
++#define IPV6_PREFER_SRC_COA 0x0004
++#define IPV6_PREFER_SRC_HOME 0x0400
++#define IPV6_PREFER_SRC_CGA 0x0008
++#define IPV6_PREFER_SRC_NONCGA 0x0800
++
++/*
++ * Multicast Routing:
++ * see include/linux/mroute6.h.
++ *
++ * MRT6_INIT 200
++ * MRT6_DONE 201
++ * MRT6_ADD_MIF 202
++ * MRT6_DEL_MIF 203
++ * MRT6_ADD_MFC 204
++ * MRT6_DEL_MFC 205
++ * MRT6_VERSION 206
++ * MRT6_ASSERT 207
++ * MRT6_PIM 208
++ * (reserved) 209
++ */
+ #endif
+diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
+index fc4e3db..7009b0c 100644
+--- a/include/linux/inetdevice.h
++++ b/include/linux/inetdevice.h
+@@ -70,13 +70,13 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev)
+ ipv4_devconf_set((in_dev), NET_IPV4_CONF_ ## attr, (val))
+
+ #define IN_DEV_ANDCONF(in_dev, attr) \
+- (IPV4_DEVCONF_ALL(in_dev->dev->nd_net, attr) && \
++ (IPV4_DEVCONF_ALL(dev_net(in_dev->dev), attr) && \
+ IN_DEV_CONF_GET((in_dev), attr))
+ #define IN_DEV_ORCONF(in_dev, attr) \
+- (IPV4_DEVCONF_ALL(in_dev->dev->nd_net, attr) || \
++ (IPV4_DEVCONF_ALL(dev_net(in_dev->dev), attr) || \
+ IN_DEV_CONF_GET((in_dev), attr))
+ #define IN_DEV_MAXCONF(in_dev, attr) \
+- (max(IPV4_DEVCONF_ALL(in_dev->dev->nd_net, attr), \
++ (max(IPV4_DEVCONF_ALL(dev_net(in_dev->dev), attr), \
+ IN_DEV_CONF_GET((in_dev), attr)))
+
+ #define IN_DEV_FORWARD(in_dev) IN_DEV_CONF_GET((in_dev), FORWARDING)
+@@ -129,7 +129,7 @@ extern int unregister_inetaddr_notifier(struct notifier_block *nb);
+
+ extern struct net_device *ip_dev_find(struct net *net, __be32 addr);
+ extern int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b);
+-extern int devinet_ioctl(unsigned int cmd, void __user *);
++extern int devinet_ioctl(struct net *net, unsigned int cmd, void __user *);
+ extern void devinet_init(void);
+ extern struct in_device *inetdev_by_index(struct net *, int);
+ extern __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope);
+diff --git a/include/linux/init_task.h b/include/linux/init_task.h
+index 1f74e1d..37a6f5b 100644
+--- a/include/linux/init_task.h
++++ b/include/linux/init_task.h
+@@ -151,6 +151,9 @@ extern struct group_info init_groups;
+ .cpus_allowed = CPU_MASK_ALL, \
+ .mm = NULL, \
+ .active_mm = &init_mm, \
++ .se = { \
++ .group_node = LIST_HEAD_INIT(tsk.se.group_node), \
++ }, \
+ .rt = { \
+ .run_list = LIST_HEAD_INIT(tsk.rt.run_list), \
+ .time_slice = HZ, \
+diff --git a/include/linux/input.h b/include/linux/input.h
+index cae2c35..28a094f 100644
+--- a/include/linux/input.h
++++ b/include/linux/input.h
+@@ -1025,10 +1025,6 @@ struct ff_effect {
+ * @node: used to place the device onto input_dev_list
+ */
+ struct input_dev {
+- /* private: */
+- void *private; /* do not use */
+- /* public: */
+-
+ const char *name;
+ const char *phys;
+ const char *uniq;
+@@ -1238,12 +1234,12 @@ static inline void input_put_device(struct input_dev *dev)
+
+ static inline void *input_get_drvdata(struct input_dev *dev)
+ {
+- return dev->private;
++ return dev_get_drvdata(&dev->dev);
+ }
+
+ static inline void input_set_drvdata(struct input_dev *dev, void *data)
+ {
+- dev->private = data;
++ dev_set_drvdata(&dev->dev, data);
+ }
+
+ int __must_check input_register_device(struct input_dev *);
+diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
+index f8ab4ce..b5fef13 100644
+--- a/include/linux/interrupt.h
++++ b/include/linux/interrupt.h
+@@ -102,6 +102,25 @@ extern void disable_irq_nosync(unsigned int irq);
+ extern void disable_irq(unsigned int irq);
+ extern void enable_irq(unsigned int irq);
+
++#if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_HARDIRQS)
++
++extern int irq_set_affinity(unsigned int irq, cpumask_t cpumask);
++extern int irq_can_set_affinity(unsigned int irq);
++
++#else /* CONFIG_SMP */
++
++static inline int irq_set_affinity(unsigned int irq, cpumask_t cpumask)
++{
++ return -EINVAL;
++}
++
++static inline int irq_can_set_affinity(unsigned int irq)
++{
++ return 0;
++}
++
++#endif /* CONFIG_SMP && CONFIG_GENERIC_HARDIRQS */
++
+ #ifdef CONFIG_GENERIC_HARDIRQS
+ /*
+ * Special lockdep variants of irq disabling/enabling.
+diff --git a/include/linux/ioport.h b/include/linux/ioport.h
+index 605d237..d5d40a9 100644
+--- a/include/linux/ioport.h
++++ b/include/linux/ioport.h
+@@ -44,7 +44,9 @@ struct resource_list {
+ #define IORESOURCE_CACHEABLE 0x00004000
+ #define IORESOURCE_RANGELENGTH 0x00008000
+ #define IORESOURCE_SHADOWABLE 0x00010000
+-#define IORESOURCE_BUS_HAS_VGA 0x00080000
++
++#define IORESOURCE_SIZEALIGN 0x00020000 /* size indicates alignment */
++#define IORESOURCE_STARTALIGN 0x00040000 /* start field is alignment */
+
+ #define IORESOURCE_DISABLED 0x10000000
+ #define IORESOURCE_UNSET 0x20000000
+@@ -110,6 +112,7 @@ extern int allocate_resource(struct resource *root, struct resource *new,
+ void *alignf_data);
+ int adjust_resource(struct resource *res, resource_size_t start,
+ resource_size_t size);
++resource_size_t resource_alignment(struct resource *res);
+
+ /* Convenience shorthand with allocation */
+ #define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name))
+diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
+index 134c8e5..10b666b 100644
+--- a/include/linux/ipv6.h
++++ b/include/linux/ipv6.h
+@@ -160,6 +160,9 @@ struct ipv6_devconf {
+ #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
+ __s32 optimistic_dad;
+ #endif
++#ifdef CONFIG_IPV6_MROUTE
++ __s32 mc_forwarding;
++#endif
+ void *sysctl;
+ };
+
+@@ -190,6 +193,7 @@ enum {
+ DEVCONF_PROXY_NDP,
+ DEVCONF_OPTIMISTIC_DAD,
+ DEVCONF_ACCEPT_SOURCE_ROUTE,
++ DEVCONF_MC_FORWARDING,
+ DEVCONF_MAX
+ };
+
+@@ -230,6 +234,7 @@ struct inet6_skb_parm {
+ #endif
+
+ #define IP6SKB_XFRM_TRANSFORMED 1
++#define IP6SKB_FORWARDED 2
+ };
+
+ #define IP6CB(skb) ((struct inet6_skb_parm*)((skb)->cb))
+@@ -274,8 +279,29 @@ struct ipv6_pinfo {
+
+ __be32 flow_label;
+ __u32 frag_size;
+- __s16 hop_limit;
+- __s16 mcast_hops;
++
++ /*
++ * Packed in 16bits.
++ * Omit one shift by by putting the signed field at MSB.
++ */
++#if defined(__BIG_ENDIAN_BITFIELD)
++ __s16 hop_limit:9;
++ __u16 __unused_1:7;
++#else
++ __u16 __unused_1:7;
++ __s16 hop_limit:9;
++#endif
++
++#if defined(__BIG_ENDIAN_BITFIELD)
++ /* Packed in 16bits. */
++ __s16 mcast_hops:9;
++ __u16 __unused_2:6,
++ mc_loop:1;
++#else
++ __u16 mc_loop:1,
++ __unused_2:6;
++ __s16 mcast_hops:9;
++#endif
+ int mcast_oif;
+
+ /* pktoption flags */
+@@ -298,11 +324,14 @@ struct ipv6_pinfo {
+ } rxopt;
+
+ /* sockopt flags */
+- __u8 mc_loop:1,
+- recverr:1,
++ __u8 recverr:1,
+ sndflow:1,
+ pmtudisc:2,
+- ipv6only:1;
++ ipv6only:1,
++ srcprefs:3; /* 001: prefer temporary address
++ * 010: prefer public address
++ * 100: prefer care-of address
++ */
+ __u8 tclass;
+
+ __u32 dst_cookie;
+@@ -315,9 +344,8 @@ struct ipv6_pinfo {
+ struct sk_buff *pktoptions;
+ struct {
+ struct ipv6_txoptions *opt;
+- struct rt6_info *rt;
+- int hop_limit;
+- int tclass;
++ u8 hop_limit;
++ u8 tclass;
+ } cork;
+ };
+
+@@ -458,7 +486,7 @@ static inline struct raw6_sock *raw6_sk(const struct sock *sk)
+ #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
+
+ #define INET6_MATCH(__sk, __net, __hash, __saddr, __daddr, __ports, __dif)\
+- (((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net)) && \
++ (((__sk)->sk_hash == (__hash)) && sock_net((__sk)) == (__net) && \
+ ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports)) && \
+ ((__sk)->sk_family == AF_INET6) && \
+ ipv6_addr_equal(&inet6_sk(__sk)->daddr, (__saddr)) && \
+@@ -466,7 +494,7 @@ static inline struct raw6_sock *raw6_sk(const struct sock *sk)
+ (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+
+ #define INET6_TW_MATCH(__sk, __net, __hash, __saddr, __daddr, __ports, __dif) \
+- (((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net)) && \
++ (((__sk)->sk_hash == (__hash)) && sock_net((__sk)) == (__net) && \
+ (*((__portpair *)&(inet_twsk(__sk)->tw_dport)) == (__ports)) && \
+ ((__sk)->sk_family == PF_INET6) && \
+ (ipv6_addr_equal(&inet6_twsk(__sk)->tw_v6_daddr, (__saddr))) && \
+diff --git a/include/linux/irq.h b/include/linux/irq.h
+index 176e5e7..1883a85 100644
+--- a/include/linux/irq.h
++++ b/include/linux/irq.h
+@@ -228,21 +228,11 @@ static inline void set_pending_irq(unsigned int irq, cpumask_t mask)
+
+ #endif /* CONFIG_GENERIC_PENDING_IRQ */
+
+-extern int irq_set_affinity(unsigned int irq, cpumask_t cpumask);
+-extern int irq_can_set_affinity(unsigned int irq);
+-
+ #else /* CONFIG_SMP */
+
+ #define move_native_irq(x)
+ #define move_masked_irq(x)
+
+-static inline int irq_set_affinity(unsigned int irq, cpumask_t cpumask)
+-{
+- return -EINVAL;
+-}
+-
+-static inline int irq_can_set_affinity(unsigned int irq) { return 0; }
+-
+ #endif /* CONFIG_SMP */
+
+ #ifdef CONFIG_IRQBALANCE
+diff --git a/include/linux/irqflags.h b/include/linux/irqflags.h
+index 412e025..e600c4e 100644
+--- a/include/linux/irqflags.h
++++ b/include/linux/irqflags.h
+@@ -84,10 +84,10 @@
+
+ #define irqs_disabled() \
+ ({ \
+- unsigned long flags; \
++ unsigned long _flags; \
+ \
+- raw_local_save_flags(flags); \
+- raw_irqs_disabled_flags(flags); \
++ raw_local_save_flags(_flags); \
++ raw_irqs_disabled_flags(_flags); \
+ })
+
+ #define irqs_disabled_flags(flags) raw_irqs_disabled_flags(flags)
+diff --git a/include/linux/iscsi_ibft.h b/include/linux/iscsi_ibft.h
+new file mode 100644
+index 0000000..6092487
+--- /dev/null
++++ b/include/linux/iscsi_ibft.h
+@@ -0,0 +1,50 @@
++/*
++ * Copyright 2007 Red Hat, Inc.
++ * by Peter Jones <pjones at redhat.com>
++ * Copyright 2007 IBM, Inc.
++ * by Konrad Rzeszutek <konradr at linux.vnet.ibm.com>
++ * Copyright 2008
++ * by Konrad Rzeszutek <ketuzsezr at darnok.org>
++ *
++ * This code exposes the iSCSI Boot Format Table to userland via sysfs.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License v2.0 as published by
++ * the Free Software Foundation
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++#ifndef ISCSI_IBFT_H
++#define ISCSI_IBFT_H
++
++struct ibft_table_header {
++ char signature[4];
++ u32 length;
++ u8 revision;
++ u8 checksum;
++ char oem_id[6];
++ char oem_table_id[8];
++ char reserved[24];
++} __attribute__((__packed__));
++
++/*
++ * Logical location of iSCSI Boot Format Table.
++ * If the value is NULL there is no iBFT on the machine.
++ */
++extern struct ibft_table_header *ibft_addr;
++
++/*
++ * Routine used to find and reserve the iSCSI Boot Format Table. The
++ * mapped address is set in the ibft_addr variable.
++ */
++#ifdef CONFIG_ISCSI_IBFT_FIND
++extern void __init reserve_ibft_region(void);
++#else
++static inline void reserve_ibft_region(void) { }
++#endif
++
++#endif /* ISCSI_IBFT_H */
+diff --git a/include/linux/isdn.h b/include/linux/isdn.h
+index 9cb2855..44cd663 100644
+--- a/include/linux/isdn.h
++++ b/include/linux/isdn.h
+@@ -16,14 +16,8 @@
+
+ #include <linux/ioctl.h>
+
+-#ifdef CONFIG_COBALT_MICRO_SERVER
+-/* Save memory */
+-#define ISDN_MAX_DRIVERS 2
+-#define ISDN_MAX_CHANNELS 8
+-#else
+ #define ISDN_MAX_DRIVERS 32
+ #define ISDN_MAX_CHANNELS 64
+-#endif
+
+ /* New ioctl-codes */
+ #define IIOCNETAIF _IO('I',1)
+diff --git a/include/linux/jbd.h b/include/linux/jbd.h
+index 423f582..07a9b52 100644
+--- a/include/linux/jbd.h
++++ b/include/linux/jbd.h
+@@ -32,8 +32,6 @@
+ #include <linux/timer.h>
+ #include <linux/lockdep.h>
+
+-#include <asm/semaphore.h>
+-
+ #define journal_oom_retry 1
+
+ /*
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index 2cbf6fd..05e2b30 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -30,8 +30,6 @@
+ #include <linux/bit_spinlock.h>
+ #include <linux/mutex.h>
+ #include <linux/timer.h>
+-
+-#include <asm/semaphore.h>
+ #endif
+
+ #define journal_oom_retry 1
+diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
+index e0b5b68..33ef710 100644
+--- a/include/linux/jiffies.h
++++ b/include/linux/jiffies.h
+@@ -36,7 +36,7 @@
+ #elif HZ >= 6144 && HZ < 12288
+ # define SHIFT_HZ 13
+ #else
+-# error You lose.
++# error Invalid value of HZ.
+ #endif
+
+ /* LATCH is used in the interval timer and ftape setup. */
+@@ -135,6 +135,22 @@ static inline u64 get_jiffies_64(void)
+ #define time_before_eq64(a,b) time_after_eq64(b,a)
+
+ /*
++ * These four macros compare jiffies and 'a' for convenience.
++ */
++
++/* time_is_before_jiffies(a) return true if a is before jiffies */
++#define time_is_before_jiffies(a) time_after(jiffies, a)
++
++/* time_is_after_jiffies(a) return true if a is after jiffies */
++#define time_is_after_jiffies(a) time_before(jiffies, a)
++
++/* time_is_before_eq_jiffies(a) return true if a is before or equal to jiffies*/
++#define time_is_before_eq_jiffies(a) time_after_eq(jiffies, a)
++
++/* time_is_after_eq_jiffies(a) return true if a is after or equal to jiffies*/
++#define time_is_after_eq_jiffies(a) time_before_eq(jiffies, a)
++
++/*
+ * Have the 32 bit jiffies value wrap 5 minutes after boot
+ * so jiffies wrap bugs show up earlier.
+ */
+diff --git a/include/linux/kernel.h b/include/linux/kernel.h
+index 2df44e7..cd6d02c 100644
+--- a/include/linux/kernel.h
++++ b/include/linux/kernel.h
+@@ -293,10 +293,8 @@ extern void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
+ #define pr_debug(fmt, arg...) \
+ printk(KERN_DEBUG fmt, ##arg)
+ #else
+-static inline int __attribute__ ((format (printf, 1, 2))) pr_debug(const char * fmt, ...)
+-{
+- return 0;
+-}
++#define pr_debug(fmt, arg...) \
++ ({ if (0) printk(KERN_DEBUG fmt, ##arg); 0; })
+ #endif
+
+ /*
+diff --git a/include/linux/kernelcapi.h b/include/linux/kernelcapi.h
+index 8c4350a..a53e932 100644
+--- a/include/linux/kernelcapi.h
++++ b/include/linux/kernelcapi.h
+@@ -48,7 +48,6 @@ typedef struct kcapi_carddef {
+ #include <linux/list.h>
+ #include <linux/skbuff.h>
+ #include <linux/workqueue.h>
+-#include <asm/semaphore.h>
+
+ #define KCI_CONTRUP 0 /* arg: struct capi_profile */
+ #define KCI_CONTRDOWN 1 /* arg: NULL */
+diff --git a/include/linux/keyboard.h b/include/linux/keyboard.h
+index 65c2d70..a3c984d 100644
+--- a/include/linux/keyboard.h
++++ b/include/linux/keyboard.h
+@@ -33,6 +33,7 @@ struct keyboard_notifier_param {
+ struct vc_data *vc; /* VC on which the keyboard press was done */
+ int down; /* Pressure of the key? */
+ int shift; /* Current shift mask */
++ int ledstate; /* Current led state */
+ unsigned int value; /* keycode, unicode value or keysym */
+ };
+
+diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h
+new file mode 100644
+index 0000000..9757b1a
+--- /dev/null
++++ b/include/linux/kgdb.h
+@@ -0,0 +1,281 @@
++/*
++ * This provides the callbacks and functions that KGDB needs to share between
++ * the core, I/O and arch-specific portions.
++ *
++ * Author: Amit Kale <amitkale at linsyssoft.com> and
++ * Tom Rini <trini at kernel.crashing.org>
++ *
++ * 2001-2004 (c) Amit S. Kale and 2003-2005 (c) MontaVista Software, Inc.
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++#ifndef _KGDB_H_
++#define _KGDB_H_
++
++#include <linux/serial_8250.h>
++#include <linux/linkage.h>
++#include <linux/init.h>
++
++#include <asm/atomic.h>
++#include <asm/kgdb.h>
++
++struct pt_regs;
++
++/**
++ * kgdb_skipexception - (optional) exit kgdb_handle_exception early
++ * @exception: Exception vector number
++ * @regs: Current &struct pt_regs.
++ *
++ * On some architectures it is required to skip a breakpoint
++ * exception when it occurs after a breakpoint has been removed.
++ * This can be implemented in the architecture specific portion of
++ * for kgdb.
++ */
++extern int kgdb_skipexception(int exception, struct pt_regs *regs);
++
++/**
++ * kgdb_post_primary_code - (optional) Save error vector/code numbers.
++ * @regs: Original pt_regs.
++ * @e_vector: Original error vector.
++ * @err_code: Original error code.
++ *
++ * This is usually needed on architectures which support SMP and
++ * KGDB. This function is called after all the secondary cpus have
++ * been put to a know spin state and the primary CPU has control over
++ * KGDB.
++ */
++extern void kgdb_post_primary_code(struct pt_regs *regs, int e_vector,
++ int err_code);
++
++/**
++ * kgdb_disable_hw_debug - (optional) Disable hardware debugging hook
++ * @regs: Current &struct pt_regs.
++ *
++ * This function will be called if the particular architecture must
++ * disable hardware debugging while it is processing gdb packets or
++ * handling exception.
++ */
++extern void kgdb_disable_hw_debug(struct pt_regs *regs);
++
++struct tasklet_struct;
++struct task_struct;
++struct uart_port;
++
++/**
++ * kgdb_breakpoint - compiled in breakpoint
++ *
++ * This will be impelmented a static inline per architecture. This
++ * function is called by the kgdb core to execute an architecture
++ * specific trap to cause kgdb to enter the exception processing.
++ *
++ */
++void kgdb_breakpoint(void);
++
++extern int kgdb_connected;
++
++extern atomic_t kgdb_setting_breakpoint;
++extern atomic_t kgdb_cpu_doing_single_step;
++
++extern struct task_struct *kgdb_usethread;
++extern struct task_struct *kgdb_contthread;
++
++enum kgdb_bptype {
++ BP_BREAKPOINT = 0,
++ BP_HARDWARE_BREAKPOINT,
++ BP_WRITE_WATCHPOINT,
++ BP_READ_WATCHPOINT,
++ BP_ACCESS_WATCHPOINT
++};
++
++enum kgdb_bpstate {
++ BP_UNDEFINED = 0,
++ BP_REMOVED,
++ BP_SET,
++ BP_ACTIVE
++};
++
++struct kgdb_bkpt {
++ unsigned long bpt_addr;
++ unsigned char saved_instr[BREAK_INSTR_SIZE];
++ enum kgdb_bptype type;
++ enum kgdb_bpstate state;
++};
++
++#ifndef KGDB_MAX_BREAKPOINTS
++# define KGDB_MAX_BREAKPOINTS 1000
++#endif
++
++#define KGDB_HW_BREAKPOINT 1
++
++/*
++ * Functions each KGDB-supporting architecture must provide:
++ */
++
++/**
++ * kgdb_arch_init - Perform any architecture specific initalization.
++ *
++ * This function will handle the initalization of any architecture
++ * specific callbacks.
++ */
++extern int kgdb_arch_init(void);
++
++/**
++ * kgdb_arch_exit - Perform any architecture specific uninitalization.
++ *
++ * This function will handle the uninitalization of any architecture
++ * specific callbacks, for dynamic registration and unregistration.
++ */
++extern void kgdb_arch_exit(void);
++
++/**
++ * pt_regs_to_gdb_regs - Convert ptrace regs to GDB regs
++ * @gdb_regs: A pointer to hold the registers in the order GDB wants.
++ * @regs: The &struct pt_regs of the current process.
++ *
++ * Convert the pt_regs in @regs into the format for registers that
++ * GDB expects, stored in @gdb_regs.
++ */
++extern void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs);
++
++/**
++ * sleeping_thread_to_gdb_regs - Convert ptrace regs to GDB regs
++ * @gdb_regs: A pointer to hold the registers in the order GDB wants.
++ * @p: The &struct task_struct of the desired process.
++ *
++ * Convert the register values of the sleeping process in @p to
++ * the format that GDB expects.
++ * This function is called when kgdb does not have access to the
++ * &struct pt_regs and therefore it should fill the gdb registers
++ * @gdb_regs with what has been saved in &struct thread_struct
++ * thread field during switch_to.
++ */
++extern void
++sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p);
++
++/**
++ * gdb_regs_to_pt_regs - Convert GDB regs to ptrace regs.
++ * @gdb_regs: A pointer to hold the registers we've received from GDB.
++ * @regs: A pointer to a &struct pt_regs to hold these values in.
++ *
++ * Convert the GDB regs in @gdb_regs into the pt_regs, and store them
++ * in @regs.
++ */
++extern void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs);
++
++/**
++ * kgdb_arch_handle_exception - Handle architecture specific GDB packets.
++ * @vector: The error vector of the exception that happened.
++ * @signo: The signal number of the exception that happened.
++ * @err_code: The error code of the exception that happened.
++ * @remcom_in_buffer: The buffer of the packet we have read.
++ * @remcom_out_buffer: The buffer of %BUFMAX bytes to write a packet into.
++ * @regs: The &struct pt_regs of the current process.
++ *
++ * This function MUST handle the 'c' and 's' command packets,
++ * as well packets to set / remove a hardware breakpoint, if used.
++ * If there are additional packets which the hardware needs to handle,
++ * they are handled here. The code should return -1 if it wants to
++ * process more packets, and a %0 or %1 if it wants to exit from the
++ * kgdb callback.
++ */
++extern int
++kgdb_arch_handle_exception(int vector, int signo, int err_code,
++ char *remcom_in_buffer,
++ char *remcom_out_buffer,
++ struct pt_regs *regs);
++
++/**
++ * kgdb_roundup_cpus - Get other CPUs into a holding pattern
++ * @flags: Current IRQ state
++ *
++ * On SMP systems, we need to get the attention of the other CPUs
++ * and get them be in a known state. This should do what is needed
++ * to get the other CPUs to call kgdb_wait(). Note that on some arches,
++ * the NMI approach is not used for rounding up all the CPUs. For example,
++ * in case of MIPS, smp_call_function() is used to roundup CPUs. In
++ * this case, we have to make sure that interrupts are enabled before
++ * calling smp_call_function(). The argument to this function is
++ * the flags that will be used when restoring the interrupts. There is
++ * local_irq_save() call before kgdb_roundup_cpus().
++ *
++ * On non-SMP systems, this is not called.
++ */
++extern void kgdb_roundup_cpus(unsigned long flags);
++
++/* Optional functions. */
++extern int kgdb_validate_break_address(unsigned long addr);
++extern int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr);
++extern int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle);
++
++/**
++ * struct kgdb_arch - Describe architecture specific values.
++ * @gdb_bpt_instr: The instruction to trigger a breakpoint.
++ * @flags: Flags for the breakpoint, currently just %KGDB_HW_BREAKPOINT.
++ * @set_breakpoint: Allow an architecture to specify how to set a software
++ * breakpoint.
++ * @remove_breakpoint: Allow an architecture to specify how to remove a
++ * software breakpoint.
++ * @set_hw_breakpoint: Allow an architecture to specify how to set a hardware
++ * breakpoint.
++ * @remove_hw_breakpoint: Allow an architecture to specify how to remove a
++ * hardware breakpoint.
++ * @remove_all_hw_break: Allow an architecture to specify how to remove all
++ * hardware breakpoints.
++ * @correct_hw_break: Allow an architecture to specify how to correct the
++ * hardware debug registers.
++ */
++struct kgdb_arch {
++ unsigned char gdb_bpt_instr[BREAK_INSTR_SIZE];
++ unsigned long flags;
++
++ int (*set_breakpoint)(unsigned long, char *);
++ int (*remove_breakpoint)(unsigned long, char *);
++ int (*set_hw_breakpoint)(unsigned long, int, enum kgdb_bptype);
++ int (*remove_hw_breakpoint)(unsigned long, int, enum kgdb_bptype);
++ void (*remove_all_hw_break)(void);
++ void (*correct_hw_break)(void);
++};
++
++/**
++ * struct kgdb_io - Describe the interface for an I/O driver to talk with KGDB.
++ * @name: Name of the I/O driver.
++ * @read_char: Pointer to a function that will return one char.
++ * @write_char: Pointer to a function that will write one char.
++ * @flush: Pointer to a function that will flush any pending writes.
++ * @init: Pointer to a function that will initialize the device.
++ * @pre_exception: Pointer to a function that will do any prep work for
++ * the I/O driver.
++ * @post_exception: Pointer to a function that will do any cleanup work
++ * for the I/O driver.
++ */
++struct kgdb_io {
++ const char *name;
++ int (*read_char) (void);
++ void (*write_char) (u8);
++ void (*flush) (void);
++ int (*init) (void);
++ void (*pre_exception) (void);
++ void (*post_exception) (void);
++};
++
++extern struct kgdb_arch arch_kgdb_ops;
++
++extern int kgdb_register_io_module(struct kgdb_io *local_kgdb_io_ops);
++extern void kgdb_unregister_io_module(struct kgdb_io *local_kgdb_io_ops);
++
++extern int kgdb_hex2long(char **ptr, long *long_val);
++extern int kgdb_mem2hex(char *mem, char *buf, int count);
++extern int kgdb_hex2mem(char *buf, char *mem, int count);
++
++extern int kgdb_isremovedbreak(unsigned long addr);
++
++extern int
++kgdb_handle_exception(int ex_vector, int signo, int err_code,
++ struct pt_regs *regs);
++extern int kgdb_nmicallback(int cpu, void *regs);
++
++extern int kgdb_single_step;
++extern atomic_t kgdb_active;
++
++#endif /* _KGDB_H_ */
+diff --git a/include/linux/ktime.h b/include/linux/ktime.h
+index 2cd7fa7..ce59832 100644
+--- a/include/linux/ktime.h
++++ b/include/linux/ktime.h
+@@ -327,4 +327,10 @@ extern void ktime_get_ts(struct timespec *ts);
+ /* Get the real (wall-) time in timespec format: */
+ #define ktime_get_real_ts(ts) getnstimeofday(ts)
+
++static inline ktime_t ns_to_ktime(u64 ns)
++{
++ static const ktime_t ktime_zero = { .tv64 = 0 };
++ return ktime_add_ns(ktime_zero, ns);
++}
++
+ #endif
+diff --git a/include/linux/leds.h b/include/linux/leds.h
+index 0201f6f..519df72 100644
+--- a/include/linux/leds.h
++++ b/include/linux/leds.h
+@@ -35,8 +35,11 @@ struct led_classdev {
+ #define LED_SUSPENDED (1 << 0)
+
+ /* Set LED brightness level */
++ /* Must not sleep, use a workqueue if needed */
+ void (*brightness_set)(struct led_classdev *led_cdev,
+ enum led_brightness brightness);
++ /* Get LED brightness level */
++ enum led_brightness (*brightness_get)(struct led_classdev *led_cdev);
+
+ /* Activate hardware accelerated blink */
+ int (*blink_set)(struct led_classdev *led_cdev,
+@@ -59,15 +62,7 @@ struct led_classdev {
+
+ extern int led_classdev_register(struct device *parent,
+ struct led_classdev *led_cdev);
+-extern void __led_classdev_unregister(struct led_classdev *led_cdev, bool sus);
+-static inline void led_classdev_unregister(struct led_classdev *lcd)
+-{
+- __led_classdev_unregister(lcd, false);
+-}
+-static inline void led_classdev_unregister_suspended(struct led_classdev *lcd)
+-{
+- __led_classdev_unregister(lcd, true);
+-}
++extern void led_classdev_unregister(struct led_classdev *lcd);
+ extern void led_classdev_suspend(struct led_classdev *led_cdev);
+ extern void led_classdev_resume(struct led_classdev *led_cdev);
+
+@@ -134,6 +129,9 @@ struct gpio_led {
+ struct gpio_led_platform_data {
+ int num_leds;
+ struct gpio_led *leds;
++ int (*gpio_blink_set)(unsigned gpio,
++ unsigned long *delay_on,
++ unsigned long *delay_off);
+ };
+
+
+diff --git a/include/linux/libata.h b/include/linux/libata.h
+index 37ee881..395a523 100644
+--- a/include/linux/libata.h
++++ b/include/linux/libata.h
+@@ -122,6 +122,8 @@ enum {
+
+ ATAPI_MAX_DRAIN = 16 << 10,
+
++ ATA_ALL_DEVICES = (1 << ATA_MAX_DEVICES) - 1,
++
+ ATA_SHT_EMULATED = 1,
+ ATA_SHT_CMD_PER_LUN = 1,
+ ATA_SHT_THIS_ID = -1,
+@@ -163,9 +165,6 @@ enum {
+ ATA_DEV_NONE = 9, /* no device */
+
+ /* struct ata_link flags */
+- ATA_LFLAG_HRST_TO_RESUME = (1 << 0), /* hardreset to resume link */
+- ATA_LFLAG_SKIP_D2H_BSY = (1 << 1), /* can't wait for the first D2H
+- * Register FIS clearing BSY */
+ ATA_LFLAG_NO_SRST = (1 << 2), /* avoid softreset */
+ ATA_LFLAG_ASSUME_ATA = (1 << 3), /* assume ATA class */
+ ATA_LFLAG_ASSUME_SEMB = (1 << 4), /* assume SEMB class */
+@@ -225,6 +224,7 @@ enum {
+ ATA_QCFLAG_RESULT_TF = (1 << 4), /* result TF requested */
+ ATA_QCFLAG_CLEAR_EXCL = (1 << 5), /* clear excl_link on completion */
+ ATA_QCFLAG_QUIET = (1 << 6), /* don't report device error */
++ ATA_QCFLAG_RETRY = (1 << 7), /* retry after failure */
+
+ ATA_QCFLAG_FAILED = (1 << 16), /* cmd failed and is owned by EH */
+ ATA_QCFLAG_SENSE_VALID = (1 << 17), /* sense data valid */
+@@ -249,6 +249,25 @@ enum {
+ */
+ ATA_TMOUT_FF_WAIT = 4 * HZ / 5,
+
++ /* Spec mandates to wait for ">= 2ms" before checking status
++ * after reset. We wait 150ms, because that was the magic
++ * delay used for ATAPI devices in Hale Landis's ATADRVR, for
++ * the period of time between when the ATA command register is
++ * written, and then status is checked. Because waiting for
++ * "a while" before checking status is fine, post SRST, we
++ * perform this magic delay here as well.
++ *
++ * Old drivers/ide uses the 2mS rule and then waits for ready.
++ */
++ ATA_WAIT_AFTER_RESET_MSECS = 150,
++
++ /* If PMP is supported, we have to do follow-up SRST. As some
++ * PMPs don't send D2H Reg FIS after hardreset, LLDs are
++ * advised to wait only for the following duration before
++ * doing SRST.
++ */
++ ATA_TMOUT_PMP_SRST_WAIT = 1 * HZ,
++
+ /* ATA bus states */
+ BUS_UNKNOWN = 0,
+ BUS_DMA = 1,
+@@ -292,17 +311,16 @@ enum {
+
+ /* reset / recovery action types */
+ ATA_EH_REVALIDATE = (1 << 0),
+- ATA_EH_SOFTRESET = (1 << 1),
+- ATA_EH_HARDRESET = (1 << 2),
++ ATA_EH_SOFTRESET = (1 << 1), /* meaningful only in ->prereset */
++ ATA_EH_HARDRESET = (1 << 2), /* meaningful only in ->prereset */
++ ATA_EH_RESET = ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
+ ATA_EH_ENABLE_LINK = (1 << 3),
+ ATA_EH_LPM = (1 << 4), /* link power management action */
+
+- ATA_EH_RESET_MASK = ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
+ ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE,
+
+ /* ata_eh_info->flags */
+ ATA_EHI_HOTPLUGGED = (1 << 0), /* could have been hotplugged */
+- ATA_EHI_RESUME_LINK = (1 << 1), /* resume link (reset modifier) */
+ ATA_EHI_NO_AUTOPSY = (1 << 2), /* no autopsy */
+ ATA_EHI_QUIET = (1 << 3), /* be quiet */
+
+@@ -313,7 +331,6 @@ enum {
+ ATA_EHI_POST_SETMODE = (1 << 20), /* revaildating after setmode */
+
+ ATA_EHI_DID_RESET = ATA_EHI_DID_SOFTRESET | ATA_EHI_DID_HARDRESET,
+- ATA_EHI_RESET_MODIFIER_MASK = ATA_EHI_RESUME_LINK,
+
+ /* max tries if error condition is still set after ->error_handler */
+ ATA_EH_MAX_TRIES = 5,
+@@ -352,6 +369,22 @@ enum {
+ ATAPI_READ_CD = 2, /* READ CD [MSF] */
+ ATAPI_PASS_THRU = 3, /* SAT pass-thru */
+ ATAPI_MISC = 4, /* the rest */
++
++ /* Timing constants */
++ ATA_TIMING_SETUP = (1 << 0),
++ ATA_TIMING_ACT8B = (1 << 1),
++ ATA_TIMING_REC8B = (1 << 2),
++ ATA_TIMING_CYC8B = (1 << 3),
++ ATA_TIMING_8BIT = ATA_TIMING_ACT8B | ATA_TIMING_REC8B |
++ ATA_TIMING_CYC8B,
++ ATA_TIMING_ACTIVE = (1 << 4),
++ ATA_TIMING_RECOVER = (1 << 5),
++ ATA_TIMING_CYCLE = (1 << 6),
++ ATA_TIMING_UDMA = (1 << 7),
++ ATA_TIMING_ALL = ATA_TIMING_SETUP | ATA_TIMING_ACT8B |
++ ATA_TIMING_REC8B | ATA_TIMING_CYC8B |
++ ATA_TIMING_ACTIVE | ATA_TIMING_RECOVER |
++ ATA_TIMING_CYCLE | ATA_TIMING_UDMA,
+ };
+
+ enum ata_xfer_mask {
+@@ -410,8 +443,9 @@ enum link_pm {
+ MAX_PERFORMANCE,
+ MEDIUM_POWER,
+ };
+-extern struct class_device_attribute class_device_attr_link_power_management_policy;
++extern struct device_attribute dev_attr_link_power_management_policy;
+
++#ifdef CONFIG_ATA_SFF
+ struct ata_ioports {
+ void __iomem *cmd_addr;
+ void __iomem *data_addr;
+@@ -429,6 +463,7 @@ struct ata_ioports {
+ void __iomem *bmdma_addr;
+ void __iomem *scr_addr;
+ };
++#endif /* CONFIG_ATA_SFF */
+
+ struct ata_host {
+ spinlock_t lock;
+@@ -436,7 +471,7 @@ struct ata_host {
+ void __iomem * const *iomap;
+ unsigned int n_ports;
+ void *private_data;
+- const struct ata_port_operations *ops;
++ struct ata_port_operations *ops;
+ unsigned long flags;
+ #ifdef CONFIG_ATA_ACPI
+ acpi_handle acpi_handle;
+@@ -605,7 +640,7 @@ struct ata_link {
+
+ struct ata_port {
+ struct Scsi_Host *scsi_host; /* our co-allocated scsi host */
+- const struct ata_port_operations *ops;
++ struct ata_port_operations *ops;
+ spinlock_t *lock;
+ unsigned long flags; /* ATA_FLAG_xxx */
+ unsigned int pflags; /* ATA_PFLAG_xxx */
+@@ -615,7 +650,9 @@ struct ata_port {
+ struct ata_prd *prd; /* our SG list */
+ dma_addr_t prd_dma; /* and its DMA mapping */
+
++#ifdef CONFIG_ATA_SFF
+ struct ata_ioports ioaddr; /* ATA cmd/ctl/dma register blocks */
++#endif /* CONFIG_ATA_SFF */
+
+ u8 ctl; /* cache of ATA control register */
+ u8 last_ctl; /* Cache last written value */
+@@ -667,81 +704,108 @@ struct ata_port {
+ u8 sector_buf[ATA_SECT_SIZE]; /* owned by EH */
+ };
+
+-struct ata_port_operations {
+- void (*dev_config) (struct ata_device *);
+-
+- void (*set_piomode) (struct ata_port *, struct ata_device *);
+- void (*set_dmamode) (struct ata_port *, struct ata_device *);
+- unsigned long (*mode_filter) (struct ata_device *, unsigned long);
+-
+- void (*tf_load) (struct ata_port *ap, const struct ata_taskfile *tf);
+- void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
+-
+- void (*exec_command)(struct ata_port *ap, const struct ata_taskfile *tf);
+- u8 (*check_status)(struct ata_port *ap);
+- u8 (*check_altstatus)(struct ata_port *ap);
+- void (*dev_select)(struct ata_port *ap, unsigned int device);
+-
+- void (*phy_reset) (struct ata_port *ap); /* obsolete */
+- int (*set_mode) (struct ata_link *link, struct ata_device **r_failed_dev);
+-
+- int (*cable_detect) (struct ata_port *ap);
+-
+- int (*check_atapi_dma) (struct ata_queued_cmd *qc);
+-
+- void (*bmdma_setup) (struct ata_queued_cmd *qc);
+- void (*bmdma_start) (struct ata_queued_cmd *qc);
+-
+- unsigned int (*data_xfer) (struct ata_device *dev, unsigned char *buf,
+- unsigned int buflen, int rw);
+-
+- int (*qc_defer) (struct ata_queued_cmd *qc);
+- void (*qc_prep) (struct ata_queued_cmd *qc);
+- unsigned int (*qc_issue) (struct ata_queued_cmd *qc);
+-
+- /* port multiplier */
+- void (*pmp_attach) (struct ata_port *ap);
+- void (*pmp_detach) (struct ata_port *ap);
++/* The following initializer overrides a method to NULL whether one of
++ * its parent has the method defined or not. This is equivalent to
++ * ERR_PTR(-ENOENT). Unfortunately, ERR_PTR doesn't render a constant
++ * expression and thus can't be used as an initializer.
++ */
++#define ATA_OP_NULL (void *)(unsigned long)(-ENOENT)
+
+- /* Error handlers. ->error_handler overrides ->eng_timeout and
+- * indicates that new-style EH is in place.
++struct ata_port_operations {
++ /*
++ * Command execution
+ */
+- void (*eng_timeout) (struct ata_port *ap); /* obsolete */
+-
+- void (*freeze) (struct ata_port *ap);
+- void (*thaw) (struct ata_port *ap);
+- void (*error_handler) (struct ata_port *ap);
+- void (*post_internal_cmd) (struct ata_queued_cmd *qc);
+-
+- irq_handler_t irq_handler;
+- void (*irq_clear) (struct ata_port *);
+- u8 (*irq_on) (struct ata_port *);
+-
+- int (*scr_read) (struct ata_port *ap, unsigned int sc_reg, u32 *val);
+- int (*scr_write) (struct ata_port *ap, unsigned int sc_reg, u32 val);
++ int (*qc_defer)(struct ata_queued_cmd *qc);
++ int (*check_atapi_dma)(struct ata_queued_cmd *qc);
++ void (*qc_prep)(struct ata_queued_cmd *qc);
++ unsigned int (*qc_issue)(struct ata_queued_cmd *qc);
++ bool (*qc_fill_rtf)(struct ata_queued_cmd *qc);
++
++ /*
++ * Configuration and exception handling
++ */
++ int (*cable_detect)(struct ata_port *ap);
++ unsigned long (*mode_filter)(struct ata_device *dev, unsigned long xfer_mask);
++ void (*set_piomode)(struct ata_port *ap, struct ata_device *dev);
++ void (*set_dmamode)(struct ata_port *ap, struct ata_device *dev);
++ int (*set_mode)(struct ata_link *link, struct ata_device **r_failed_dev);
++
++ void (*dev_config)(struct ata_device *dev);
++
++ void (*freeze)(struct ata_port *ap);
++ void (*thaw)(struct ata_port *ap);
++ ata_prereset_fn_t prereset;
++ ata_reset_fn_t softreset;
++ ata_reset_fn_t hardreset;
++ ata_postreset_fn_t postreset;
++ ata_prereset_fn_t pmp_prereset;
++ ata_reset_fn_t pmp_softreset;
++ ata_reset_fn_t pmp_hardreset;
++ ata_postreset_fn_t pmp_postreset;
++ void (*error_handler)(struct ata_port *ap);
++ void (*post_internal_cmd)(struct ata_queued_cmd *qc);
++
++ /*
++ * Optional features
++ */
++ int (*scr_read)(struct ata_port *ap, unsigned int sc_reg, u32 *val);
++ int (*scr_write)(struct ata_port *ap, unsigned int sc_reg, u32 val);
++ void (*pmp_attach)(struct ata_port *ap);
++ void (*pmp_detach)(struct ata_port *ap);
++ int (*enable_pm)(struct ata_port *ap, enum link_pm policy);
++ void (*disable_pm)(struct ata_port *ap);
++
++ /*
++ * Start, stop, suspend and resume
++ */
++ int (*port_suspend)(struct ata_port *ap, pm_message_t mesg);
++ int (*port_resume)(struct ata_port *ap);
++ int (*port_start)(struct ata_port *ap);
++ void (*port_stop)(struct ata_port *ap);
++ void (*host_stop)(struct ata_host *host);
++
++#ifdef CONFIG_ATA_SFF
++ /*
++ * SFF / taskfile oriented ops
++ */
++ void (*sff_dev_select)(struct ata_port *ap, unsigned int device);
++ u8 (*sff_check_status)(struct ata_port *ap);
++ u8 (*sff_check_altstatus)(struct ata_port *ap);
++ void (*sff_tf_load)(struct ata_port *ap, const struct ata_taskfile *tf);
++ void (*sff_tf_read)(struct ata_port *ap, struct ata_taskfile *tf);
++ void (*sff_exec_command)(struct ata_port *ap,
++ const struct ata_taskfile *tf);
++ unsigned int (*sff_data_xfer)(struct ata_device *dev,
++ unsigned char *buf, unsigned int buflen, int rw);
++ u8 (*sff_irq_on)(struct ata_port *);
++ void (*sff_irq_clear)(struct ata_port *);
+
+- int (*port_suspend) (struct ata_port *ap, pm_message_t mesg);
+- int (*port_resume) (struct ata_port *ap);
+- int (*enable_pm) (struct ata_port *ap, enum link_pm policy);
+- void (*disable_pm) (struct ata_port *ap);
+- int (*port_start) (struct ata_port *ap);
+- void (*port_stop) (struct ata_port *ap);
++ void (*bmdma_setup)(struct ata_queued_cmd *qc);
++ void (*bmdma_start)(struct ata_queued_cmd *qc);
++ void (*bmdma_stop)(struct ata_queued_cmd *qc);
++ u8 (*bmdma_status)(struct ata_port *ap);
++#endif /* CONFIG_ATA_SFF */
+
+- void (*host_stop) (struct ata_host *host);
++ /*
++ * Obsolete
++ */
++ void (*phy_reset)(struct ata_port *ap);
++ void (*eng_timeout)(struct ata_port *ap);
+
+- void (*bmdma_stop) (struct ata_queued_cmd *qc);
+- u8 (*bmdma_status) (struct ata_port *ap);
++ /*
++ * ->inherits must be the last field and all the preceding
++ * fields must be pointers.
++ */
++ const struct ata_port_operations *inherits;
+ };
+
+ struct ata_port_info {
+- struct scsi_host_template *sht;
+ unsigned long flags;
+ unsigned long link_flags;
+ unsigned long pio_mask;
+ unsigned long mwdma_mask;
+ unsigned long udma_mask;
+- const struct ata_port_operations *port_ops;
+- irq_handler_t irq_handler;
++ struct ata_port_operations *port_ops;
+ void *private_data;
+ };
+
+@@ -759,11 +823,14 @@ struct ata_timing {
+
+ #define FIT(v, vmin, vmax) max_t(short, min_t(short, v, vmax), vmin)
+
++/*
++ * Core layer - drivers/ata/libata-core.c
++ */
+ extern const unsigned long sata_deb_timing_normal[];
+ extern const unsigned long sata_deb_timing_hotplug[];
+ extern const unsigned long sata_deb_timing_long[];
+
+-extern const struct ata_port_operations ata_dummy_port_ops;
++extern struct ata_port_operations ata_dummy_port_ops;
+ extern const struct ata_port_info ata_dummy_port_info;
+
+ static inline const unsigned long *
+@@ -780,24 +847,22 @@ static inline int ata_port_is_dummy(struct ata_port *ap)
+ return ap->ops == &ata_dummy_port_ops;
+ }
+
+-extern void sata_print_link_status(struct ata_link *link);
+ extern void ata_port_probe(struct ata_port *);
+-extern void ata_bus_reset(struct ata_port *ap);
+ extern int sata_set_spd(struct ata_link *link);
++extern int ata_std_prereset(struct ata_link *link, unsigned long deadline);
++extern int ata_wait_after_reset(struct ata_link *link, unsigned long deadline,
++ int (*check_ready)(struct ata_link *link));
+ extern int sata_link_debounce(struct ata_link *link,
+ const unsigned long *params, unsigned long deadline);
+ extern int sata_link_resume(struct ata_link *link, const unsigned long *params,
+ unsigned long deadline);
+-extern int ata_std_prereset(struct ata_link *link, unsigned long deadline);
+-extern int ata_std_softreset(struct ata_link *link, unsigned int *classes,
+- unsigned long deadline);
+ extern int sata_link_hardreset(struct ata_link *link,
+- const unsigned long *timing, unsigned long deadline);
++ const unsigned long *timing, unsigned long deadline,
++ bool *online, int (*check_ready)(struct ata_link *));
+ extern int sata_std_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline);
+ extern void ata_std_postreset(struct ata_link *link, unsigned int *classes);
+ extern void ata_port_disable(struct ata_port *);
+-extern void ata_std_ports(struct ata_ioports *ioaddr);
+
+ extern struct ata_host *ata_host_alloc(struct device *dev, int max_ports);
+ extern struct ata_host *ata_host_alloc_pinfo(struct device *dev,
+@@ -810,7 +875,7 @@ extern int ata_host_activate(struct ata_host *host, int irq,
+ struct scsi_host_template *sht);
+ extern void ata_host_detach(struct ata_host *host);
+ extern void ata_host_init(struct ata_host *, struct device *,
+- unsigned long, const struct ata_port_operations *);
++ unsigned long, struct ata_port_operations *);
+ extern int ata_scsi_detect(struct scsi_host_template *sht);
+ extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
+ extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
+@@ -823,7 +888,6 @@ extern void ata_sas_port_stop(struct ata_port *ap);
+ extern int ata_sas_slave_configure(struct scsi_device *, struct ata_port *);
+ extern int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *),
+ struct ata_port *ap);
+-extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
+ extern int sata_scr_valid(struct ata_link *link);
+ extern int sata_scr_read(struct ata_link *link, int reg, u32 *val);
+ extern int sata_scr_write(struct ata_link *link, int reg, u32 val);
+@@ -835,21 +899,9 @@ extern int ata_host_suspend(struct ata_host *host, pm_message_t mesg);
+ extern void ata_host_resume(struct ata_host *host);
+ #endif
+ extern int ata_ratelimit(void);
+-extern int ata_busy_sleep(struct ata_port *ap,
+- unsigned long timeout_pat, unsigned long timeout);
+-extern void ata_wait_after_reset(struct ata_port *ap, unsigned long deadline);
+-extern int ata_wait_ready(struct ata_port *ap, unsigned long deadline);
+ extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
+ unsigned long interval_msec,
+ unsigned long timeout_msec);
+-extern unsigned int ata_dev_try_classify(struct ata_device *dev, int present,
+- u8 *r_err);
+-
+-/*
+- * Default driver ops implementations
+- */
+-extern void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf);
+-extern void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
+ extern int atapi_cmd_type(u8 opcode);
+ extern void ata_tf_to_fis(const struct ata_taskfile *tf,
+ u8 pmp, int is_cmd, u8 *fis);
+@@ -864,23 +916,9 @@ extern unsigned long ata_xfer_mode2mask(u8 xfer_mode);
+ extern int ata_xfer_mode2shift(unsigned long xfer_mode);
+ extern const char *ata_mode_string(unsigned long xfer_mask);
+ extern unsigned long ata_id_xfermask(const u16 *id);
+-extern void ata_noop_dev_select(struct ata_port *ap, unsigned int device);
+-extern void ata_std_dev_select(struct ata_port *ap, unsigned int device);
+-extern u8 ata_check_status(struct ata_port *ap);
+-extern u8 ata_altstatus(struct ata_port *ap);
+-extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf);
+ extern int ata_port_start(struct ata_port *ap);
+-extern int ata_sff_port_start(struct ata_port *ap);
+-extern irqreturn_t ata_interrupt(int irq, void *dev_instance);
+-extern unsigned int ata_data_xfer(struct ata_device *dev,
+- unsigned char *buf, unsigned int buflen, int rw);
+-extern unsigned int ata_data_xfer_noirq(struct ata_device *dev,
+- unsigned char *buf, unsigned int buflen, int rw);
+ extern int ata_std_qc_defer(struct ata_queued_cmd *qc);
+-extern void ata_dumb_qc_prep(struct ata_queued_cmd *qc);
+-extern void ata_qc_prep(struct ata_queued_cmd *qc);
+ extern void ata_noop_qc_prep(struct ata_queued_cmd *qc);
+-extern unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc);
+ extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
+ unsigned int n_elem);
+ extern unsigned int ata_dev_classify(const struct ata_taskfile *tf);
+@@ -889,24 +927,8 @@ extern void ata_id_string(const u16 *id, unsigned char *s,
+ unsigned int ofs, unsigned int len);
+ extern void ata_id_c_string(const u16 *id, unsigned char *s,
+ unsigned int ofs, unsigned int len);
+-extern void ata_bmdma_setup(struct ata_queued_cmd *qc);
+-extern void ata_bmdma_start(struct ata_queued_cmd *qc);
+-extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
+-extern u8 ata_bmdma_status(struct ata_port *ap);
+-extern void ata_bmdma_irq_clear(struct ata_port *ap);
+-extern void ata_bmdma_freeze(struct ata_port *ap);
+-extern void ata_bmdma_thaw(struct ata_port *ap);
+-extern void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+- ata_reset_fn_t softreset,
+- ata_reset_fn_t hardreset,
+- ata_postreset_fn_t postreset);
+-extern void ata_bmdma_error_handler(struct ata_port *ap);
+-extern void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc);
+-extern int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
+- u8 status, int in_wq);
+ extern void ata_qc_complete(struct ata_queued_cmd *qc);
+-extern int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active,
+- void (*finish_qc)(struct ata_queued_cmd *));
++extern int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active);
+ extern void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
+ void (*done)(struct scsi_cmnd *));
+ extern int ata_std_bios_param(struct scsi_device *sdev,
+@@ -918,7 +940,6 @@ extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
+ int queue_depth);
+ extern struct ata_device *ata_dev_pair(struct ata_device *adev);
+ extern int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev);
+-extern u8 ata_irq_on(struct ata_port *ap);
+
+ extern int ata_cable_40wire(struct ata_port *ap);
+ extern int ata_cable_80wire(struct ata_port *ap);
+@@ -926,10 +947,7 @@ extern int ata_cable_sata(struct ata_port *ap);
+ extern int ata_cable_ignore(struct ata_port *ap);
+ extern int ata_cable_unknown(struct ata_port *ap);
+
+-/*
+- * Timing helpers
+- */
+-
++/* Timing helpers */
+ extern unsigned int ata_pio_need_iordy(const struct ata_device *);
+ extern const struct ata_timing *ata_timing_find_mode(u8 xfer_mode);
+ extern int ata_timing_compute(struct ata_device *, unsigned short,
+@@ -939,24 +957,31 @@ extern void ata_timing_merge(const struct ata_timing *,
+ unsigned int);
+ extern u8 ata_timing_cycle2mode(unsigned int xfer_shift, int cycle);
+
+-enum {
+- ATA_TIMING_SETUP = (1 << 0),
+- ATA_TIMING_ACT8B = (1 << 1),
+- ATA_TIMING_REC8B = (1 << 2),
+- ATA_TIMING_CYC8B = (1 << 3),
+- ATA_TIMING_8BIT = ATA_TIMING_ACT8B | ATA_TIMING_REC8B |
+- ATA_TIMING_CYC8B,
+- ATA_TIMING_ACTIVE = (1 << 4),
+- ATA_TIMING_RECOVER = (1 << 5),
+- ATA_TIMING_CYCLE = (1 << 6),
+- ATA_TIMING_UDMA = (1 << 7),
+- ATA_TIMING_ALL = ATA_TIMING_SETUP | ATA_TIMING_ACT8B |
+- ATA_TIMING_REC8B | ATA_TIMING_CYC8B |
+- ATA_TIMING_ACTIVE | ATA_TIMING_RECOVER |
+- ATA_TIMING_CYCLE | ATA_TIMING_UDMA,
++/* PCI */
++#ifdef CONFIG_PCI
++struct pci_dev;
++
++struct pci_bits {
++ unsigned int reg; /* PCI config register to read */
++ unsigned int width; /* 1 (8 bit), 2 (16 bit), 4 (32 bit) */
++ unsigned long mask;
++ unsigned long val;
+ };
+
+-/* libata-acpi.c */
++extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits);
++extern void ata_pci_remove_one(struct pci_dev *pdev);
++
++#ifdef CONFIG_PM
++extern void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t mesg);
++extern int __must_check ata_pci_device_do_resume(struct pci_dev *pdev);
++extern int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
++extern int ata_pci_device_resume(struct pci_dev *pdev);
++#endif /* CONFIG_PM */
++#endif /* CONFIG_PCI */
++
++/*
++ * ACPI - drivers/ata/libata-acpi.c
++ */
+ #ifdef CONFIG_ATA_ACPI
+ static inline const struct ata_acpi_gtm *ata_acpi_init_gtm(struct ata_port *ap)
+ {
+@@ -1000,56 +1025,8 @@ static inline int ata_acpi_cbl_80wire(struct ata_port *ap,
+ }
+ #endif
+
+-#ifdef CONFIG_PCI
+-struct pci_dev;
+-
+-extern int ata_pci_init_one(struct pci_dev *pdev,
+- const struct ata_port_info * const * ppi);
+-extern void ata_pci_remove_one(struct pci_dev *pdev);
+-#ifdef CONFIG_PM
+-extern void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t mesg);
+-extern int __must_check ata_pci_device_do_resume(struct pci_dev *pdev);
+-extern int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
+-extern int ata_pci_device_resume(struct pci_dev *pdev);
+-#endif
+-extern int ata_pci_clear_simplex(struct pci_dev *pdev);
+-
+-struct pci_bits {
+- unsigned int reg; /* PCI config register to read */
+- unsigned int width; /* 1 (8 bit), 2 (16 bit), 4 (32 bit) */
+- unsigned long mask;
+- unsigned long val;
+-};
+-
+-extern int ata_pci_init_sff_host(struct ata_host *host);
+-extern int ata_pci_init_bmdma(struct ata_host *host);
+-extern int ata_pci_prepare_sff_host(struct pci_dev *pdev,
+- const struct ata_port_info * const * ppi,
+- struct ata_host **r_host);
+-extern int ata_pci_activate_sff_host(struct ata_host *host,
+- irq_handler_t irq_handler,
+- struct scsi_host_template *sht);
+-extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits);
+-extern unsigned long ata_pci_default_filter(struct ata_device *dev,
+- unsigned long xfer_mask);
+-#endif /* CONFIG_PCI */
+-
+-/*
+- * PMP
+- */
+-extern int sata_pmp_qc_defer_cmd_switch(struct ata_queued_cmd *qc);
+-extern int sata_pmp_std_prereset(struct ata_link *link, unsigned long deadline);
+-extern int sata_pmp_std_hardreset(struct ata_link *link, unsigned int *class,
+- unsigned long deadline);
+-extern void sata_pmp_std_postreset(struct ata_link *link, unsigned int *class);
+-extern void sata_pmp_do_eh(struct ata_port *ap,
+- ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
+- ata_reset_fn_t hardreset, ata_postreset_fn_t postreset,
+- ata_prereset_fn_t pmp_prereset, ata_reset_fn_t pmp_softreset,
+- ata_reset_fn_t pmp_hardreset, ata_postreset_fn_t pmp_postreset);
+-
+ /*
+- * EH
++ * EH - drivers/ata/libata-eh.c
+ */
+ extern void ata_port_schedule_eh(struct ata_port *ap);
+ extern int ata_link_abort(struct ata_link *link);
+@@ -1066,6 +1043,92 @@ extern void ata_eh_qc_retry(struct ata_queued_cmd *qc);
+ extern void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+ ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
+ ata_postreset_fn_t postreset);
++extern void ata_std_error_handler(struct ata_port *ap);
++
++/*
++ * Base operations to inherit from and initializers for sht
++ *
++ * Operations
++ *
++ * base : Common to all libata drivers.
++ * sata : SATA controllers w/ native interface.
++ * pmp : SATA controllers w/ PMP support.
++ * sff : SFF ATA controllers w/o BMDMA support.
++ * bmdma : SFF ATA controllers w/ BMDMA support.
++ *
++ * sht initializers
++ *
++ * BASE : Common to all libata drivers. The user must set
++ * sg_tablesize and dma_boundary.
++ * PIO : SFF ATA controllers w/ only PIO support.
++ * BMDMA : SFF ATA controllers w/ BMDMA support. sg_tablesize and
++ * dma_boundary are set to BMDMA limits.
++ * NCQ : SATA controllers supporting NCQ. The user must set
++ * sg_tablesize, dma_boundary and can_queue.
++ */
++extern const struct ata_port_operations ata_base_port_ops;
++extern const struct ata_port_operations sata_port_ops;
++
++#define ATA_BASE_SHT(drv_name) \
++ .module = THIS_MODULE, \
++ .name = drv_name, \
++ .ioctl = ata_scsi_ioctl, \
++ .queuecommand = ata_scsi_queuecmd, \
++ .can_queue = ATA_DEF_QUEUE, \
++ .this_id = ATA_SHT_THIS_ID, \
++ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, \
++ .emulated = ATA_SHT_EMULATED, \
++ .use_clustering = ATA_SHT_USE_CLUSTERING, \
++ .proc_name = drv_name, \
++ .slave_configure = ata_scsi_slave_config, \
++ .slave_destroy = ata_scsi_slave_destroy, \
++ .bios_param = ata_std_bios_param
++
++#define ATA_NCQ_SHT(drv_name) \
++ ATA_BASE_SHT(drv_name), \
++ .change_queue_depth = ata_scsi_change_queue_depth
++
++/*
++ * PMP helpers
++ */
++#ifdef CONFIG_SATA_PMP
++static inline bool sata_pmp_supported(struct ata_port *ap)
++{
++ return ap->flags & ATA_FLAG_PMP;
++}
++
++static inline bool sata_pmp_attached(struct ata_port *ap)
++{
++ return ap->nr_pmp_links != 0;
++}
++
++static inline int ata_is_host_link(const struct ata_link *link)
++{
++ return link == &link->ap->link;
++}
++#else /* CONFIG_SATA_PMP */
++static inline bool sata_pmp_supported(struct ata_port *ap)
++{
++ return false;
++}
++
++static inline bool sata_pmp_attached(struct ata_port *ap)
++{
++ return false;
++}
++
++static inline int ata_is_host_link(const struct ata_link *link)
++{
++ return 1;
++}
++#endif /* CONFIG_SATA_PMP */
++
++static inline int sata_srst_pmp(struct ata_link *link)
++{
++ if (sata_pmp_supported(link->ap) && ata_is_host_link(link))
++ return SATA_PMP_CTRL_PORT;
++ return link->pmp;
++}
+
+ /*
+ * printk helpers
+@@ -1074,7 +1137,7 @@ extern void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+ printk("%sata%u: "fmt, lv, (ap)->print_id , ##args)
+
+ #define ata_link_printk(link, lv, fmt, args...) do { \
+- if ((link)->ap->nr_pmp_links) \
++ if (sata_pmp_attached((link)->ap)) \
+ printk("%sata%u.%02u: "fmt, lv, (link)->ap->print_id, \
+ (link)->pmp , ##args); \
+ else \
+@@ -1094,18 +1157,11 @@ extern void ata_ehi_push_desc(struct ata_eh_info *ehi, const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+ extern void ata_ehi_clear_desc(struct ata_eh_info *ehi);
+
+-static inline void ata_ehi_schedule_probe(struct ata_eh_info *ehi)
+-{
+- ehi->flags |= ATA_EHI_RESUME_LINK;
+- ehi->action |= ATA_EH_SOFTRESET;
+- ehi->probe_mask |= (1 << ATA_MAX_DEVICES) - 1;
+-}
+-
+ static inline void ata_ehi_hotplugged(struct ata_eh_info *ehi)
+ {
+- ata_ehi_schedule_probe(ehi);
++ ehi->probe_mask |= (1 << ATA_MAX_DEVICES) - 1;
+ ehi->flags |= ATA_EHI_HOTPLUGGED;
+- ehi->action |= ATA_EH_ENABLE_LINK;
++ ehi->action |= ATA_EH_RESET | ATA_EH_ENABLE_LINK;
+ ehi->err_mask |= AC_ERR_ATA_BUS;
+ }
+
+@@ -1126,7 +1182,7 @@ static inline unsigned int ata_tag_valid(unsigned int tag)
+
+ static inline unsigned int ata_tag_internal(unsigned int tag)
+ {
+- return tag == ATA_MAX_QUEUE - 1;
++ return tag == ATA_TAG_INTERNAL;
+ }
+
+ /*
+@@ -1167,11 +1223,6 @@ static inline unsigned int ata_dev_absent(const struct ata_device *dev)
+ /*
+ * link helpers
+ */
+-static inline int ata_is_host_link(const struct ata_link *link)
+-{
+- return link == &link->ap->link;
+-}
+-
+ static inline int ata_link_max_devices(const struct ata_link *link)
+ {
+ if (ata_is_host_link(link) && link->ap->flags & ATA_FLAG_SLAVE_POSS)
+@@ -1186,7 +1237,7 @@ static inline int ata_link_active(struct ata_link *link)
+
+ static inline struct ata_link *ata_port_first_link(struct ata_port *ap)
+ {
+- if (ap->nr_pmp_links)
++ if (sata_pmp_attached(ap))
+ return ap->pmp_link;
+ return &ap->link;
+ }
+@@ -1195,8 +1246,8 @@ static inline struct ata_link *ata_port_next_link(struct ata_link *link)
+ {
+ struct ata_port *ap = link->ap;
+
+- if (link == &ap->link) {
+- if (!ap->nr_pmp_links)
++ if (ata_is_host_link(link)) {
++ if (!sata_pmp_attached(ap))
+ return NULL;
+ return ap->pmp_link;
+ }
+@@ -1222,11 +1273,6 @@ static inline struct ata_link *ata_port_next_link(struct ata_link *link)
+ for ((dev) = (link)->device + ata_link_max_devices(link) - 1; \
+ (dev) >= (link)->device || ((dev) = NULL); (dev)--)
+
+-static inline u8 ata_chk_status(struct ata_port *ap)
+-{
+- return ap->ops->check_status(ap);
+-}
+-
+ /**
+ * ata_ncq_enabled - Test whether NCQ is enabled
+ * @dev: ATA device to test for
+@@ -1243,74 +1289,6 @@ static inline int ata_ncq_enabled(struct ata_device *dev)
+ ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ;
+ }
+
+-/**
+- * ata_pause - Flush writes and pause 400 nanoseconds.
+- * @ap: Port to wait for.
+- *
+- * LOCKING:
+- * Inherited from caller.
+- */
+-
+-static inline void ata_pause(struct ata_port *ap)
+-{
+- ata_altstatus(ap);
+- ndelay(400);
+-}
+-
+-
+-/**
+- * ata_busy_wait - Wait for a port status register
+- * @ap: Port to wait for.
+- * @bits: bits that must be clear
+- * @max: number of 10uS waits to perform
+- *
+- * Waits up to max*10 microseconds for the selected bits in the port's
+- * status register to be cleared.
+- * Returns final value of status register.
+- *
+- * LOCKING:
+- * Inherited from caller.
+- */
+-
+-static inline u8 ata_busy_wait(struct ata_port *ap, unsigned int bits,
+- unsigned int max)
+-{
+- u8 status;
+-
+- do {
+- udelay(10);
+- status = ata_chk_status(ap);
+- max--;
+- } while (status != 0xff && (status & bits) && (max > 0));
+-
+- return status;
+-}
+-
+-
+-/**
+- * ata_wait_idle - Wait for a port to be idle.
+- * @ap: Port to wait for.
+- *
+- * Waits up to 10ms for port's BUSY and DRQ signals to clear.
+- * Returns final value of status register.
+- *
+- * LOCKING:
+- * Inherited from caller.
+- */
+-
+-static inline u8 ata_wait_idle(struct ata_port *ap)
+-{
+- u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+-
+-#ifdef ATA_DEBUG
+- if (status != 0xff && (status & (ATA_BUSY | ATA_DRQ)))
+- ata_port_printk(ap, KERN_DEBUG, "abnormal Status 0x%X\n",
+- status);
+-#endif
+-
+- return status;
+-}
+-
+ static inline void ata_qc_set_polling(struct ata_queued_cmd *qc)
+ {
+ qc->tf.ctl |= ATA_NIEN;
+@@ -1403,4 +1381,171 @@ static inline struct ata_port *ata_shost_to_port(struct Scsi_Host *host)
+ return *(struct ata_port **)&host->hostdata[0];
+ }
+
++
++/**************************************************************************
++ * PMP - drivers/ata/libata-pmp.c
++ */
++#ifdef CONFIG_SATA_PMP
++
++extern const struct ata_port_operations sata_pmp_port_ops;
++
++extern int sata_pmp_qc_defer_cmd_switch(struct ata_queued_cmd *qc);
++extern void sata_pmp_error_handler(struct ata_port *ap);
++
++#else /* CONFIG_SATA_PMP */
++
++#define sata_pmp_port_ops sata_port_ops
++#define sata_pmp_qc_defer_cmd_switch ata_std_qc_defer
++#define sata_pmp_error_handler ata_std_error_handler
++
++#endif /* CONFIG_SATA_PMP */
++
++
++/**************************************************************************
++ * SFF - drivers/ata/libata-sff.c
++ */
++#ifdef CONFIG_ATA_SFF
++
++extern const struct ata_port_operations ata_sff_port_ops;
++extern const struct ata_port_operations ata_bmdma_port_ops;
++
++/* PIO only, sg_tablesize and dma_boundary limits can be removed */
++#define ATA_PIO_SHT(drv_name) \
++ ATA_BASE_SHT(drv_name), \
++ .sg_tablesize = LIBATA_MAX_PRD, \
++ .dma_boundary = ATA_DMA_BOUNDARY
++
++#define ATA_BMDMA_SHT(drv_name) \
++ ATA_BASE_SHT(drv_name), \
++ .sg_tablesize = LIBATA_MAX_PRD, \
++ .dma_boundary = ATA_DMA_BOUNDARY
++
++extern void ata_sff_qc_prep(struct ata_queued_cmd *qc);
++extern void ata_sff_dumb_qc_prep(struct ata_queued_cmd *qc);
++extern void ata_sff_dev_select(struct ata_port *ap, unsigned int device);
++extern u8 ata_sff_check_status(struct ata_port *ap);
++extern u8 ata_sff_altstatus(struct ata_port *ap);
++extern int ata_sff_busy_sleep(struct ata_port *ap,
++ unsigned long timeout_pat, unsigned long timeout);
++extern int ata_sff_wait_ready(struct ata_link *link, unsigned long deadline);
++extern void ata_sff_tf_load(struct ata_port *ap, const struct ata_taskfile *tf);
++extern void ata_sff_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
++extern void ata_sff_exec_command(struct ata_port *ap,
++ const struct ata_taskfile *tf);
++extern unsigned int ata_sff_data_xfer(struct ata_device *dev,
++ unsigned char *buf, unsigned int buflen, int rw);
++extern unsigned int ata_sff_data_xfer_noirq(struct ata_device *dev,
++ unsigned char *buf, unsigned int buflen, int rw);
++extern u8 ata_sff_irq_on(struct ata_port *ap);
++extern void ata_sff_irq_clear(struct ata_port *ap);
++extern int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
++ u8 status, int in_wq);
++extern unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc);
++extern bool ata_sff_qc_fill_rtf(struct ata_queued_cmd *qc);
++extern unsigned int ata_sff_host_intr(struct ata_port *ap,
++ struct ata_queued_cmd *qc);
++extern irqreturn_t ata_sff_interrupt(int irq, void *dev_instance);
++extern void ata_sff_freeze(struct ata_port *ap);
++extern void ata_sff_thaw(struct ata_port *ap);
++extern int ata_sff_prereset(struct ata_link *link, unsigned long deadline);
++extern unsigned int ata_sff_dev_classify(struct ata_device *dev, int present,
++ u8 *r_err);
++extern int ata_sff_wait_after_reset(struct ata_link *link, unsigned int devmask,
++ unsigned long deadline);
++extern int ata_sff_softreset(struct ata_link *link, unsigned int *classes,
++ unsigned long deadline);
++extern int sata_sff_hardreset(struct ata_link *link, unsigned int *class,
++ unsigned long deadline);
++extern void ata_sff_postreset(struct ata_link *link, unsigned int *classes);
++extern void ata_sff_error_handler(struct ata_port *ap);
++extern void ata_sff_post_internal_cmd(struct ata_queued_cmd *qc);
++extern int ata_sff_port_start(struct ata_port *ap);
++extern void ata_sff_std_ports(struct ata_ioports *ioaddr);
++extern unsigned long ata_bmdma_mode_filter(struct ata_device *dev,
++ unsigned long xfer_mask);
++extern void ata_bmdma_setup(struct ata_queued_cmd *qc);
++extern void ata_bmdma_start(struct ata_queued_cmd *qc);
++extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
++extern u8 ata_bmdma_status(struct ata_port *ap);
++extern void ata_bus_reset(struct ata_port *ap);
++
++#ifdef CONFIG_PCI
++extern int ata_pci_bmdma_clear_simplex(struct pci_dev *pdev);
++extern int ata_pci_bmdma_init(struct ata_host *host);
++extern int ata_pci_sff_init_host(struct ata_host *host);
++extern int ata_pci_sff_prepare_host(struct pci_dev *pdev,
++ const struct ata_port_info * const * ppi,
++ struct ata_host **r_host);
++extern int ata_pci_sff_activate_host(struct ata_host *host,
++ irq_handler_t irq_handler,
++ struct scsi_host_template *sht);
++extern int ata_pci_sff_init_one(struct pci_dev *pdev,
++ const struct ata_port_info * const * ppi,
++ struct scsi_host_template *sht, void *host_priv);
++#endif /* CONFIG_PCI */
++
++/**
++ * ata_sff_pause - Flush writes and pause 400 nanoseconds.
++ * @ap: Port to wait for.
++ *
++ * LOCKING:
++ * Inherited from caller.
++ */
++static inline void ata_sff_pause(struct ata_port *ap)
++{
++ ata_sff_altstatus(ap);
++ ndelay(400);
++}
++
++/**
++ * ata_sff_busy_wait - Wait for a port status register
++ * @ap: Port to wait for.
++ * @bits: bits that must be clear
++ * @max: number of 10uS waits to perform
++ *
++ * Waits up to max*10 microseconds for the selected bits in the port's
++ * status register to be cleared.
++ * Returns final value of status register.
++ *
++ * LOCKING:
++ * Inherited from caller.
++ */
++static inline u8 ata_sff_busy_wait(struct ata_port *ap, unsigned int bits,
++ unsigned int max)
++{
++ u8 status;
++
++ do {
++ udelay(10);
++ status = ap->ops->sff_check_status(ap);
++ max--;
++ } while (status != 0xff && (status & bits) && (max > 0));
++
++ return status;
++}
++
++/**
++ * ata_wait_idle - Wait for a port to be idle.
++ * @ap: Port to wait for.
++ *
++ * Waits up to 10ms for port's BUSY and DRQ signals to clear.
++ * Returns final value of status register.
++ *
++ * LOCKING:
++ * Inherited from caller.
++ */
++static inline u8 ata_wait_idle(struct ata_port *ap)
++{
++ u8 status = ata_sff_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
++
++#ifdef ATA_DEBUG
++ if (status != 0xff && (status & (ATA_BUSY | ATA_DRQ)))
++ ata_port_printk(ap, KERN_DEBUG, "abnormal Status 0x%X\n",
++ status);
++#endif
++
++ return status;
++}
++#endif /* CONFIG_ATA_SFF */
++
+ #endif /* __LINUX_LIBATA_H__ */
+diff --git a/include/linux/list.h b/include/linux/list.h
+index 75ce2cb..dac16f9 100644
+--- a/include/linux/list.h
++++ b/include/linux/list.h
+@@ -631,31 +631,14 @@ static inline void list_splice_init_rcu(struct list_head *list,
+ * as long as the traversal is guarded by rcu_read_lock().
+ */
+ #define list_for_each_rcu(pos, head) \
+- for (pos = (head)->next; \
+- prefetch(rcu_dereference(pos)->next), pos != (head); \
+- pos = pos->next)
++ for (pos = rcu_dereference((head)->next); \
++ prefetch(pos->next), pos != (head); \
++ pos = rcu_dereference(pos->next))
+
+ #define __list_for_each_rcu(pos, head) \
+- for (pos = (head)->next; \
+- rcu_dereference(pos) != (head); \
+- pos = pos->next)
+-
+-/**
+- * list_for_each_safe_rcu
+- * @pos: the &struct list_head to use as a loop cursor.
+- * @n: another &struct list_head to use as temporary storage
+- * @head: the head for your list.
+- *
+- * Iterate over an rcu-protected list, safe against removal of list entry.
+- *
+- * This list-traversal primitive may safely run concurrently with
+- * the _rcu list-mutation primitives such as list_add_rcu()
+- * as long as the traversal is guarded by rcu_read_lock().
+- */
+-#define list_for_each_safe_rcu(pos, n, head) \
+- for (pos = (head)->next; \
+- n = rcu_dereference(pos)->next, pos != (head); \
+- pos = n)
++ for (pos = rcu_dereference((head)->next); \
++ pos != (head); \
++ pos = rcu_dereference(pos->next))
+
+ /**
+ * list_for_each_entry_rcu - iterate over rcu list of given type
+@@ -668,10 +651,9 @@ static inline void list_splice_init_rcu(struct list_head *list,
+ * as long as the traversal is guarded by rcu_read_lock().
+ */
+ #define list_for_each_entry_rcu(pos, head, member) \
+- for (pos = list_entry((head)->next, typeof(*pos), member); \
+- prefetch(rcu_dereference(pos)->member.next), \
+- &pos->member != (head); \
+- pos = list_entry(pos->member.next, typeof(*pos), member))
++ for (pos = list_entry(rcu_dereference((head)->next), typeof(*pos), member); \
++ prefetch(pos->member.next), &pos->member != (head); \
++ pos = list_entry(rcu_dereference(pos->member.next), typeof(*pos), member))
+
+
+ /**
+@@ -686,9 +668,9 @@ static inline void list_splice_init_rcu(struct list_head *list,
+ * as long as the traversal is guarded by rcu_read_lock().
+ */
+ #define list_for_each_continue_rcu(pos, head) \
+- for ((pos) = (pos)->next; \
+- prefetch(rcu_dereference((pos))->next), (pos) != (head); \
+- (pos) = (pos)->next)
++ for ((pos) = rcu_dereference((pos)->next); \
++ prefetch((pos)->next), (pos) != (head); \
++ (pos) = rcu_dereference((pos)->next))
+
+ /*
+ * Double linked lists with a single pointer list head.
+@@ -986,10 +968,10 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
+ * as long as the traversal is guarded by rcu_read_lock().
+ */
+ #define hlist_for_each_entry_rcu(tpos, pos, head, member) \
+- for (pos = (head)->first; \
+- rcu_dereference(pos) && ({ prefetch(pos->next); 1;}) && \
++ for (pos = rcu_dereference((head)->first); \
++ pos && ({ prefetch(pos->next); 1;}) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+- pos = pos->next)
++ pos = rcu_dereference(pos->next))
+
+ #else
+ #warning "don't include kernel headers in userspace"
+diff --git a/include/linux/lm_interface.h b/include/linux/lm_interface.h
+index 1418fdc..f274997 100644
+--- a/include/linux/lm_interface.h
++++ b/include/linux/lm_interface.h
+@@ -21,9 +21,15 @@ typedef void (*lm_callback_t) (void *ptr, unsigned int type, void *data);
+ * modify the filesystem. The lock module shouldn't assign a journal to the FS
+ * mount. It shouldn't send recovery callbacks to the FS mount. If the node
+ * dies or withdraws, all locks can be wiped immediately.
++ *
++ * LM_MFLAG_CONV_NODROP
++ * Do not allow the dlm to internally resolve conversion deadlocks by demoting
++ * the lock to unlocked and then reacquiring it in the requested mode. Instead,
++ * it should cancel the request and return LM_OUT_CONV_DEADLK.
+ */
+
+ #define LM_MFLAG_SPECTATOR 0x00000001
++#define LM_MFLAG_CONV_NODROP 0x00000002
+
+ /*
+ * lm_lockstruct flags
+@@ -110,6 +116,9 @@ typedef void (*lm_callback_t) (void *ptr, unsigned int type, void *data);
+ *
+ * LM_OUT_ASYNC
+ * The result of the request will be returned in an LM_CB_ASYNC callback.
++ *
++ * LM_OUT_CONV_DEADLK
++ * The lock request was canceled do to a conversion deadlock.
+ */
+
+ #define LM_OUT_ST_MASK 0x00000003
+@@ -117,6 +126,7 @@ typedef void (*lm_callback_t) (void *ptr, unsigned int type, void *data);
+ #define LM_OUT_CANCELED 0x00000008
+ #define LM_OUT_ASYNC 0x00000080
+ #define LM_OUT_ERROR 0x00000100
++#define LM_OUT_CONV_DEADLK 0x00000200
+
+ /*
+ * lm_callback_t types
+diff --git a/include/linux/lmb.h b/include/linux/lmb.h
+new file mode 100644
+index 0000000..271153d
+--- /dev/null
++++ b/include/linux/lmb.h
+@@ -0,0 +1,85 @@
++#ifndef _LINUX_LMB_H
++#define _LINUX_LMB_H
++#ifdef __KERNEL__
++
++/*
++ * Logical memory blocks.
++ *
++ * Copyright (C) 2001 Peter Bergner, IBM Corp.
++ *
++ * 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/init.h>
++#include <linux/mm.h>
++
++#define MAX_LMB_REGIONS 128
++
++struct lmb_property {
++ u64 base;
++ u64 size;
++};
++
++struct lmb_region {
++ unsigned long cnt;
++ u64 size;
++ struct lmb_property region[MAX_LMB_REGIONS+1];
++};
++
++struct lmb {
++ unsigned long debug;
++ u64 rmo_size;
++ struct lmb_region memory;
++ struct lmb_region reserved;
++};
++
++extern struct lmb lmb;
++
++extern void __init lmb_init(void);
++extern void __init lmb_analyze(void);
++extern long __init lmb_add(u64 base, u64 size);
++extern long __init lmb_reserve(u64 base, u64 size);
++extern u64 __init lmb_alloc_nid(u64 size, u64 align, int nid,
++ u64 (*nid_range)(u64, u64, int *));
++extern u64 __init lmb_alloc(u64 size, u64 align);
++extern u64 __init lmb_alloc_base(u64 size,
++ u64, u64 max_addr);
++extern u64 __init __lmb_alloc_base(u64 size,
++ u64 align, u64 max_addr);
++extern u64 __init lmb_phys_mem_size(void);
++extern u64 __init lmb_end_of_DRAM(void);
++extern void __init lmb_enforce_memory_limit(u64 memory_limit);
++extern int __init lmb_is_reserved(u64 addr);
++
++extern void lmb_dump_all(void);
++
++static inline u64
++lmb_size_bytes(struct lmb_region *type, unsigned long region_nr)
++{
++ return type->region[region_nr].size;
++}
++static inline u64
++lmb_size_pages(struct lmb_region *type, unsigned long region_nr)
++{
++ return lmb_size_bytes(type, region_nr) >> PAGE_SHIFT;
++}
++static inline u64
++lmb_start_pfn(struct lmb_region *type, unsigned long region_nr)
++{
++ return type->region[region_nr].base >> PAGE_SHIFT;
++}
++static inline u64
++lmb_end_pfn(struct lmb_region *type, unsigned long region_nr)
++{
++ return lmb_start_pfn(type, region_nr) +
++ lmb_size_pages(type, region_nr);
++}
++
++#include <asm/lmb.h>
++
++#endif /* __KERNEL__ */
++
++#endif /* _LINUX_LMB_H */
+diff --git a/include/linux/lock_dlm_plock.h b/include/linux/lock_dlm_plock.h
+deleted file mode 100644
+index fc34151..0000000
+--- a/include/linux/lock_dlm_plock.h
++++ /dev/null
+@@ -1,41 +0,0 @@
+-/*
+- * Copyright (C) 2005 Red Hat, Inc. All rights reserved.
+- *
+- * This copyrighted material is made available to anyone wishing to use,
+- * modify, copy, or redistribute it subject to the terms and conditions
+- * of the GNU General Public License v.2.
+- */
+-
+-#ifndef __LOCK_DLM_PLOCK_DOT_H__
+-#define __LOCK_DLM_PLOCK_DOT_H__
+-
+-#define GDLM_PLOCK_MISC_NAME "lock_dlm_plock"
+-
+-#define GDLM_PLOCK_VERSION_MAJOR 1
+-#define GDLM_PLOCK_VERSION_MINOR 1
+-#define GDLM_PLOCK_VERSION_PATCH 0
+-
+-enum {
+- GDLM_PLOCK_OP_LOCK = 1,
+- GDLM_PLOCK_OP_UNLOCK,
+- GDLM_PLOCK_OP_GET,
+-};
+-
+-struct gdlm_plock_info {
+- __u32 version[3];
+- __u8 optype;
+- __u8 ex;
+- __u8 wait;
+- __u8 pad;
+- __u32 pid;
+- __s32 nodeid;
+- __s32 rv;
+- __u32 fsid;
+- __u64 number;
+- __u64 start;
+- __u64 end;
+- __u64 owner;
+-};
+-
+-#endif
+-
+diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
+index 4babb2a..102d928 100644
+--- a/include/linux/lockd/lockd.h
++++ b/include/linux/lockd/lockd.h
+@@ -91,6 +91,7 @@ struct nlm_wait;
+ */
+ #define NLMCLNT_OHSIZE ((__NEW_UTS_LEN) + 10u)
+ struct nlm_rqst {
++ atomic_t a_count;
+ unsigned int a_flags; /* initial RPC task flags */
+ struct nlm_host * a_host; /* host handle */
+ struct nlm_args a_args; /* arguments */
+@@ -173,8 +174,10 @@ void nlmclnt_next_cookie(struct nlm_cookie *);
+ /*
+ * Host cache
+ */
+-struct nlm_host *nlmclnt_lookup_host(const struct sockaddr_in *, int, int,
+- const char *, unsigned int);
++struct nlm_host *nlmclnt_lookup_host(const struct sockaddr_in *sin,
++ int proto, u32 version,
++ const char *hostname,
++ unsigned int hostname_len);
+ struct nlm_host *nlmsvc_lookup_host(struct svc_rqst *, const char *,
+ unsigned int);
+ struct rpc_clnt * nlm_bind_host(struct nlm_host *);
+@@ -191,7 +194,7 @@ void nsm_release(struct nsm_handle *);
+ * This is used in garbage collection and resource reclaim
+ * A return value != 0 means destroy the lock/block/share
+ */
+-typedef int (*nlm_host_match_fn_t)(struct nlm_host *cur, struct nlm_host *ref);
++typedef int (*nlm_host_match_fn_t)(void *cur, struct nlm_host *ref);
+
+ /*
+ * Server-side lock handling
+@@ -217,8 +220,13 @@ void nlmsvc_mark_resources(void);
+ void nlmsvc_free_host_resources(struct nlm_host *);
+ void nlmsvc_invalidate_all(void);
+
+-static __inline__ struct inode *
+-nlmsvc_file_inode(struct nlm_file *file)
++/*
++ * Cluster failover support
++ */
++int nlmsvc_unlock_all_by_sb(struct super_block *sb);
++int nlmsvc_unlock_all_by_ip(__be32 server_addr);
++
++static inline struct inode *nlmsvc_file_inode(struct nlm_file *file)
+ {
+ return file->f_file->f_path.dentry->d_inode;
+ }
+@@ -226,8 +234,8 @@ nlmsvc_file_inode(struct nlm_file *file)
+ /*
+ * Compare two host addresses (needs modifying for ipv6)
+ */
+-static __inline__ int
+-nlm_cmp_addr(const struct sockaddr_in *sin1, const struct sockaddr_in *sin2)
++static inline int nlm_cmp_addr(const struct sockaddr_in *sin1,
++ const struct sockaddr_in *sin2)
+ {
+ return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr;
+ }
+@@ -236,8 +244,8 @@ nlm_cmp_addr(const struct sockaddr_in *sin1, const struct sockaddr_in *sin2)
+ * Compare two NLM locks.
+ * When the second lock is of type F_UNLCK, this acts like a wildcard.
+ */
+-static __inline__ int
+-nlm_compare_locks(const struct file_lock *fl1, const struct file_lock *fl2)
++static inline int nlm_compare_locks(const struct file_lock *fl1,
++ const struct file_lock *fl2)
+ {
+ return fl1->fl_pid == fl2->fl_pid
+ && fl1->fl_owner == fl2->fl_owner
+diff --git a/include/linux/lockd/sm_inter.h b/include/linux/lockd/sm_inter.h
+index 22a6458..5a5448b 100644
+--- a/include/linux/lockd/sm_inter.h
++++ b/include/linux/lockd/sm_inter.h
+@@ -19,6 +19,7 @@
+ #define SM_NOTIFY 6
+
+ #define SM_MAXSTRLEN 1024
++#define SM_PRIV_SIZE 16
+
+ /*
+ * Arguments for all calls to statd
+diff --git a/include/linux/mbus.h b/include/linux/mbus.h
+new file mode 100644
+index 0000000..c11ff29
+--- /dev/null
++++ b/include/linux/mbus.h
+@@ -0,0 +1,36 @@
++/*
++ * Marvell MBUS common definitions.
++ *
++ * Copyright (C) 2008 Marvell Semiconductor
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#ifndef __LINUX_MBUS_H
++#define __LINUX_MBUS_H
++
++struct mbus_dram_target_info
++{
++ /*
++ * The 4-bit MBUS target ID of the DRAM controller.
++ */
++ u8 mbus_dram_target_id;
++
++ /*
++ * The base address, size, and MBUS attribute ID for each
++ * of the possible DRAM chip selects. Peripherals are
++ * required to support at least 4 decode windows.
++ */
++ int num_cs;
++ struct mbus_dram_window {
++ u8 cs_index;
++ u8 mbus_attr;
++ u32 base;
++ u32 size;
++ } cs[4];
++};
++
++
++#endif
+diff --git a/include/linux/memory.h b/include/linux/memory.h
+index 33f0ff0..f80e0e3 100644
+--- a/include/linux/memory.h
++++ b/include/linux/memory.h
+@@ -18,8 +18,7 @@
+ #include <linux/sysdev.h>
+ #include <linux/node.h>
+ #include <linux/compiler.h>
+-
+-#include <asm/semaphore.h>
++#include <linux/mutex.h>
+
+ struct memory_block {
+ unsigned long phys_index;
+@@ -30,7 +29,7 @@ struct memory_block {
+ * created long after the critical areas during
+ * initialization.
+ */
+- struct semaphore state_sem;
++ struct mutex state_mutex;
+ int phys_device; /* to which fru does this belong? */
+ void *hw; /* optional pointer to fw/hw data */
+ int (*phys_callback)(struct memory_block *);
+diff --git a/include/linux/memstick.h b/include/linux/memstick.h
+index 3e686ec..37a5cdb 100644
+--- a/include/linux/memstick.h
++++ b/include/linux/memstick.h
+@@ -276,7 +276,7 @@ struct memstick_host {
+ #define MEMSTICK_CAP_PAR8 4
+
+ struct work_struct media_checker;
+- struct class_device cdev;
++ struct device dev;
+
+ struct memstick_dev *card;
+ unsigned int retries;
+diff --git a/include/linux/meye.h b/include/linux/meye.h
+index 39fd9c8..12010ac 100644
+--- a/include/linux/meye.h
++++ b/include/linux/meye.h
+@@ -58,7 +58,7 @@ struct meye_params {
+
+ /* V4L2 private controls */
+ #define V4L2_CID_AGC V4L2_CID_PRIVATE_BASE
+-#define V4L2_CID_SHARPNESS (V4L2_CID_PRIVATE_BASE + 1)
++#define V4L2_CID_MEYE_SHARPNESS (V4L2_CID_PRIVATE_BASE + 1)
+ #define V4L2_CID_PICTURE (V4L2_CID_PRIVATE_BASE + 2)
+ #define V4L2_CID_JPEGQUAL (V4L2_CID_PRIVATE_BASE + 3)
+ #define V4L2_CID_FRAMERATE (V4L2_CID_PRIVATE_BASE + 4)
+diff --git a/include/linux/mfd/htc-egpio.h b/include/linux/mfd/htc-egpio.h
+new file mode 100644
+index 0000000..b4201c9
+--- /dev/null
++++ b/include/linux/mfd/htc-egpio.h
+@@ -0,0 +1,57 @@
++/*
++ * HTC simple EGPIO irq and gpio extender
++ */
++
++#ifndef __HTC_EGPIO_H__
++#define __HTC_EGPIO_H__
++
++#include <linux/gpio.h>
++
++/* Descriptive values for all-in or all-out htc_egpio_chip descriptors. */
++#define HTC_EGPIO_OUTPUT (~0)
++#define HTC_EGPIO_INPUT 0
++
++/**
++ * struct htc_egpio_chip - descriptor to create gpio_chip for register range
++ * @reg_start: index of first register
++ * @gpio_base: gpio number of first pin in this register range
++ * @num_gpios: number of gpios in this register range, max BITS_PER_LONG
++ * (number of registers = DIV_ROUND_UP(num_gpios, reg_width))
++ * @direction: bitfield, '0' = input, '1' = output,
++ */
++struct htc_egpio_chip {
++ int reg_start;
++ int gpio_base;
++ int num_gpios;
++ unsigned long direction;
++ unsigned long initial_values;
++};
++
++/**
++ * struct htc_egpio_platform_data - description provided by the arch
++ * @irq_base: beginning of available IRQs (eg, IRQ_BOARD_START)
++ * @num_irqs: number of irqs
++ * @reg_width: number of bits per register, either 8 or 16 bit
++ * @bus_width: alignment of the registers, either 16 or 32 bit
++ * @invert_acks: set if chip requires writing '0' to ack an irq, instead of '1'
++ * @ack_register: location of the irq/ack register
++ * @chip: pointer to array of htc_egpio_chip descriptors
++ * @num_chips: number of egpio chip descriptors
++ */
++struct htc_egpio_platform_data {
++ int bus_width;
++ int reg_width;
++
++ int irq_base;
++ int num_irqs;
++ int invert_acks;
++ int ack_register;
++
++ struct htc_egpio_chip *chip;
++ int num_chips;
++};
++
++/* Determine the wakeup irq, to be called during early resume */
++extern int htc_egpio_get_wakeup_irq(struct device *dev);
++
++#endif
+diff --git a/include/linux/mfd/htc-pasic3.h b/include/linux/mfd/htc-pasic3.h
+new file mode 100644
+index 0000000..b4294f1
+--- /dev/null
++++ b/include/linux/mfd/htc-pasic3.h
+@@ -0,0 +1,55 @@
++/*
++ * HTC PASIC3 driver - LEDs and DS1WM
++ *
++ * Copyright (c) 2007 Philipp Zabel <philipp.zabel at gmail.com>
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file COPYING in the main directory of this archive for
++ * more details.
++ *
++ */
++
++#ifndef __PASIC3_H
++#define __PASIC3_H
++
++#include <linux/platform_device.h>
++#include <linux/leds.h>
++
++extern void pasic3_write_register(struct device *dev, u32 reg, u8 val);
++extern u8 pasic3_read_register(struct device *dev, u32 reg);
++
++/*
++ * mask for registers 0x20,0x21,0x22
++ */
++#define PASIC3_MASK_LED0 0x04
++#define PASIC3_MASK_LED1 0x08
++#define PASIC3_MASK_LED2 0x40
++
++/*
++ * bits in register 0x06
++ */
++#define PASIC3_BIT2_LED0 0x08
++#define PASIC3_BIT2_LED1 0x10
++#define PASIC3_BIT2_LED2 0x20
++
++struct pasic3_led {
++ struct led_classdev led;
++ unsigned int hw_num;
++ unsigned int bit2;
++ unsigned int mask;
++ struct pasic3_leds_machinfo *pdata;
++};
++
++struct pasic3_leds_machinfo {
++ unsigned int num_leds;
++ unsigned int power_gpio;
++ struct pasic3_led *leds;
++};
++
++struct pasic3_platform_data {
++ struct pasic3_leds_machinfo *led_pdata;
++ unsigned int bus_shift;
++ unsigned int clock_rate;
++};
++
++#endif
+diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h
+index 24b30b9..26433ec 100644
+--- a/include/linux/miscdevice.h
++++ b/include/linux/miscdevice.h
+@@ -43,15 +43,7 @@ struct miscdevice {
+ };
+
+ extern int misc_register(struct miscdevice * misc);
+-extern int __misc_deregister(struct miscdevice *misc, bool suspended);
+-static inline int misc_deregister(struct miscdevice *misc)
+-{
+- return __misc_deregister(misc, false);
+-}
+-static inline int misc_deregister_suspended(struct miscdevice *misc)
+-{
+- return __misc_deregister(misc, true);
+-}
++extern int misc_deregister(struct miscdevice *misc);
+
+ #define MODULE_ALIAS_MISCDEV(minor) \
+ MODULE_ALIAS("char-major-" __stringify(MISC_MAJOR) \
+diff --git a/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h
+index 7d1eaa9..77323a7 100644
+--- a/include/linux/mlx4/cmd.h
++++ b/include/linux/mlx4/cmd.h
+@@ -81,7 +81,7 @@ enum {
+ MLX4_CMD_SW2HW_CQ = 0x16,
+ MLX4_CMD_HW2SW_CQ = 0x17,
+ MLX4_CMD_QUERY_CQ = 0x18,
+- MLX4_CMD_RESIZE_CQ = 0x2c,
++ MLX4_CMD_MODIFY_CQ = 0x2c,
+
+ /* SRQ commands */
+ MLX4_CMD_SW2HW_SRQ = 0x35,
+diff --git a/include/linux/mlx4/cq.h b/include/linux/mlx4/cq.h
+index 0181e0a..071cf96 100644
+--- a/include/linux/mlx4/cq.h
++++ b/include/linux/mlx4/cq.h
+@@ -45,11 +45,11 @@ struct mlx4_cqe {
+ u8 sl;
+ u8 reserved1;
+ __be16 rlid;
+- u32 reserved2;
++ __be32 ipoib_status;
+ __be32 byte_cnt;
+ __be16 wqe_index;
+ __be16 checksum;
+- u8 reserved3[3];
++ u8 reserved2[3];
+ u8 owner_sr_opcode;
+ };
+
+@@ -85,6 +85,16 @@ enum {
+ MLX4_CQE_SYNDROME_REMOTE_ABORTED_ERR = 0x22,
+ };
+
++enum {
++ MLX4_CQE_IPOIB_STATUS_IPV4 = 1 << 22,
++ MLX4_CQE_IPOIB_STATUS_IPV4F = 1 << 23,
++ MLX4_CQE_IPOIB_STATUS_IPV6 = 1 << 24,
++ MLX4_CQE_IPOIB_STATUS_IPV4OPT = 1 << 25,
++ MLX4_CQE_IPOIB_STATUS_TCP = 1 << 26,
++ MLX4_CQE_IPOIB_STATUS_UDP = 1 << 27,
++ MLX4_CQE_IPOIB_STATUS_IPOK = 1 << 28,
++};
++
+ static inline void mlx4_cq_arm(struct mlx4_cq *cq, u32 cmd,
+ void __iomem *uar_page,
+ spinlock_t *doorbell_lock)
+@@ -120,4 +130,9 @@ enum {
+ MLX4_CQ_DB_REQ_NOT = 2 << 24
+ };
+
++int mlx4_cq_modify(struct mlx4_dev *dev, struct mlx4_cq *cq,
++ u16 count, u16 period);
++int mlx4_cq_resize(struct mlx4_dev *dev, struct mlx4_cq *cq,
++ int entries, struct mlx4_mtt *mtt);
++
+ #endif /* MLX4_CQ_H */
+diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
+index 6cdf813..ff7df1a 100644
+--- a/include/linux/mlx4/device.h
++++ b/include/linux/mlx4/device.h
+@@ -186,6 +186,7 @@ struct mlx4_caps {
+ u32 flags;
+ u16 stat_rate_support;
+ u8 port_width_cap[MLX4_MAX_PORTS + 1];
++ int max_gso_sz;
+ };
+
+ struct mlx4_buf_list {
+diff --git a/include/linux/mlx4/driver.h b/include/linux/mlx4/driver.h
+index 1b835ca..53c5fdb 100644
+--- a/include/linux/mlx4/driver.h
++++ b/include/linux/mlx4/driver.h
+@@ -48,8 +48,7 @@ struct mlx4_interface {
+ void * (*add) (struct mlx4_dev *dev);
+ void (*remove)(struct mlx4_dev *dev, void *context);
+ void (*event) (struct mlx4_dev *dev, void *context,
+- enum mlx4_dev_event event, int subtype,
+- int port);
++ enum mlx4_dev_event event, int port);
+ struct list_head list;
+ };
+
+diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h
+index 09a2230..a5e43fe 100644
+--- a/include/linux/mlx4/qp.h
++++ b/include/linux/mlx4/qp.h
+@@ -158,10 +158,12 @@ struct mlx4_qp_context {
+ #define MLX4_FW_VER_WQE_CTRL_NEC mlx4_fw_ver(2, 2, 232)
+
+ enum {
+- MLX4_WQE_CTRL_NEC = 1 << 29,
+- MLX4_WQE_CTRL_FENCE = 1 << 6,
+- MLX4_WQE_CTRL_CQ_UPDATE = 3 << 2,
+- MLX4_WQE_CTRL_SOLICITED = 1 << 1,
++ MLX4_WQE_CTRL_NEC = 1 << 29,
++ MLX4_WQE_CTRL_FENCE = 1 << 6,
++ MLX4_WQE_CTRL_CQ_UPDATE = 3 << 2,
++ MLX4_WQE_CTRL_SOLICITED = 1 << 1,
++ MLX4_WQE_CTRL_IP_CSUM = 1 << 4,
++ MLX4_WQE_CTRL_TCP_UDP_CSUM = 1 << 5,
+ };
+
+ struct mlx4_wqe_ctrl_seg {
+@@ -217,6 +219,11 @@ struct mlx4_wqe_datagram_seg {
+ __be32 reservd[2];
+ };
+
++struct mlx4_lso_seg {
++ __be32 mss_hdr_size;
++ __be32 header[0];
++};
++
+ struct mlx4_wqe_bind_seg {
+ __be32 flags1;
+ __be32 flags2;
+diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
+index 8d8d197..9f274a6 100644
+--- a/include/linux/mmzone.h
++++ b/include/linux/mmzone.h
+@@ -699,7 +699,6 @@ extern char numa_zonelist_order[];
+ extern struct pglist_data contig_page_data;
+ #define NODE_DATA(nid) (&contig_page_data)
+ #define NODE_MEM_MAP(nid) mem_map
+-#define MAX_NODES_SHIFT 1
+
+ #else /* CONFIG_NEED_MULTIPLE_NODES */
+
+diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h
+index 8eed44f..830bbcd 100644
+--- a/include/linux/mnt_namespace.h
++++ b/include/linux/mnt_namespace.h
+@@ -5,6 +5,7 @@
+ #include <linux/mount.h>
+ #include <linux/sched.h>
+ #include <linux/nsproxy.h>
++#include <linux/seq_file.h>
+
+ struct mnt_namespace {
+ atomic_t count;
+@@ -14,6 +15,13 @@ struct mnt_namespace {
+ int event;
+ };
+
++struct proc_mounts {
++ struct seq_file m; /* must be the first element */
++ struct mnt_namespace *ns;
++ struct path root;
++ int event;
++};
++
+ extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
+ struct fs_struct *);
+ extern void __put_mnt_ns(struct mnt_namespace *ns);
+@@ -37,5 +45,9 @@ static inline void get_mnt_ns(struct mnt_namespace *ns)
+ atomic_inc(&ns->count);
+ }
+
++extern const struct seq_operations mounts_op;
++extern const struct seq_operations mountinfo_op;
++extern const struct seq_operations mountstats_op;
++
+ #endif
+ #endif
+diff --git a/include/linux/mount.h b/include/linux/mount.h
+index 5ee2df2..b4836d5 100644
+--- a/include/linux/mount.h
++++ b/include/linux/mount.h
+@@ -14,6 +14,7 @@
+
+ #include <linux/types.h>
+ #include <linux/list.h>
++#include <linux/nodemask.h>
+ #include <linux/spinlock.h>
+ #include <asm/atomic.h>
+
+@@ -28,8 +29,10 @@ struct mnt_namespace;
+ #define MNT_NOATIME 0x08
+ #define MNT_NODIRATIME 0x10
+ #define MNT_RELATIME 0x20
++#define MNT_READONLY 0x40 /* does the user want this to be r/o? */
+
+ #define MNT_SHRINKABLE 0x100
++#define MNT_IMBALANCED_WRITE_COUNT 0x200 /* just for debugging */
+
+ #define MNT_SHARED 0x1000 /* if the vfsmount is a shared mount */
+ #define MNT_UNBINDABLE 0x2000 /* if the vfsmount is a unbindable mount */
+@@ -53,6 +56,8 @@ struct vfsmount {
+ struct list_head mnt_slave; /* slave list entry */
+ struct vfsmount *mnt_master; /* slave is on master->mnt_slave_list */
+ struct mnt_namespace *mnt_ns; /* containing namespace */
++ int mnt_id; /* mount identifier */
++ int mnt_group_id; /* peer group identifier */
+ /*
+ * We put mnt_count & mnt_expiry_mark at the end of struct vfsmount
+ * to let these frequently modified fields in a separate cache line
+@@ -62,6 +67,11 @@ struct vfsmount {
+ int mnt_expiry_mark; /* true if marked for expiry */
+ int mnt_pinned;
+ int mnt_ghosts;
++ /*
++ * This value is not stable unless all of the mnt_writers[] spinlocks
++ * are held, and all mnt_writer[]s on this mount have 0 as their ->count
++ */
++ atomic_t __mnt_writers;
+ };
+
+ static inline struct vfsmount *mntget(struct vfsmount *mnt)
+@@ -71,9 +81,12 @@ static inline struct vfsmount *mntget(struct vfsmount *mnt)
+ return mnt;
+ }
+
++extern int mnt_want_write(struct vfsmount *mnt);
++extern void mnt_drop_write(struct vfsmount *mnt);
+ extern void mntput_no_expire(struct vfsmount *mnt);
+ extern void mnt_pin(struct vfsmount *mnt);
+ extern void mnt_unpin(struct vfsmount *mnt);
++extern int __mnt_is_readonly(struct vfsmount *mnt);
+
+ static inline void mntput(struct vfsmount *mnt)
+ {
+@@ -83,8 +96,6 @@ static inline void mntput(struct vfsmount *mnt)
+ }
+ }
+
+-extern void free_vfsmnt(struct vfsmount *mnt);
+-extern struct vfsmount *alloc_vfsmnt(const char *name);
+ extern struct vfsmount *do_kern_mount(const char *fstype, int flags,
+ const char *name, void *data);
+
+diff --git a/include/linux/mroute.h b/include/linux/mroute.h
+index 35a8277..de4decf 100644
+--- a/include/linux/mroute.h
++++ b/include/linux/mroute.h
+@@ -2,7 +2,11 @@
+ #define __LINUX_MROUTE_H
+
+ #include <linux/sockios.h>
++#include <linux/types.h>
++#ifdef __KERNEL__
+ #include <linux/in.h>
++#endif
++#include <linux/pim.h>
+
+ /*
+ * Based on the MROUTING 3.5 defines primarily to keep
+@@ -210,27 +214,6 @@ struct mfc_cache
+ #define IGMPMSG_WHOLEPKT 3 /* For PIM Register processing */
+
+ #ifdef __KERNEL__
+-
+-#define PIM_V1_VERSION __constant_htonl(0x10000000)
+-#define PIM_V1_REGISTER 1
+-
+-#define PIM_VERSION 2
+-#define PIM_REGISTER 1
+-
+-#define PIM_NULL_REGISTER __constant_htonl(0x40000000)
+-
+-/* PIMv2 register message header layout (ietf-draft-idmr-pimvsm-v2-00.ps */
+-
+-struct pimreghdr
+-{
+- __u8 type;
+- __u8 reserved;
+- __be16 csum;
+- __be32 flags;
+-};
+-
+-extern int pim_rcv_v1(struct sk_buff *);
+-
+ struct rtmsg;
+ extern int ipmr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait);
+ #endif
+diff --git a/include/linux/mroute6.h b/include/linux/mroute6.h
+new file mode 100644
+index 0000000..e798959
+--- /dev/null
++++ b/include/linux/mroute6.h
+@@ -0,0 +1,228 @@
++#ifndef __LINUX_MROUTE6_H
++#define __LINUX_MROUTE6_H
++
++#include <linux/types.h>
++#include <linux/sockios.h>
++
++/*
++ * Based on the MROUTING 3.5 defines primarily to keep
++ * source compatibility with BSD.
++ *
++ * See the pim6sd code for the original history.
++ *
++ * Protocol Independent Multicast (PIM) data structures included
++ * Carlos Picoto (cap at di.fc.ul.pt)
++ *
++ */
++
++#define MRT6_BASE 200
++#define MRT6_INIT (MRT6_BASE) /* Activate the kernel mroute code */
++#define MRT6_DONE (MRT6_BASE+1) /* Shutdown the kernel mroute */
++#define MRT6_ADD_MIF (MRT6_BASE+2) /* Add a virtual interface */
++#define MRT6_DEL_MIF (MRT6_BASE+3) /* Delete a virtual interface */
++#define MRT6_ADD_MFC (MRT6_BASE+4) /* Add a multicast forwarding entry */
++#define MRT6_DEL_MFC (MRT6_BASE+5) /* Delete a multicast forwarding entry */
++#define MRT6_VERSION (MRT6_BASE+6) /* Get the kernel multicast version */
++#define MRT6_ASSERT (MRT6_BASE+7) /* Activate PIM assert mode */
++#define MRT6_PIM (MRT6_BASE+8) /* enable PIM code */
++
++#define SIOCGETMIFCNT_IN6 SIOCPROTOPRIVATE /* IP protocol privates */
++#define SIOCGETSGCNT_IN6 (SIOCPROTOPRIVATE+1)
++#define SIOCGETRPF (SIOCPROTOPRIVATE+2)
++
++#define MAXMIFS 32
++typedef unsigned long mifbitmap_t; /* User mode code depends on this lot */
++typedef unsigned short mifi_t;
++#define ALL_MIFS ((mifi_t)(-1))
++
++#ifndef IF_SETSIZE
++#define IF_SETSIZE 256
++#endif
++
++typedef __u32 if_mask;
++#define NIFBITS (sizeof(if_mask) * 8) /* bits per mask */
++
++#if !defined(__KERNEL__) && !defined(DIV_ROUND_UP)
++#define DIV_ROUND_UP(x,y) (((x) + ((y) - 1)) / (y))
++#endif
++
++typedef struct if_set {
++ if_mask ifs_bits[DIV_ROUND_UP(IF_SETSIZE, NIFBITS)];
++} if_set;
++
++#define IF_SET(n, p) ((p)->ifs_bits[(n)/NIFBITS] |= (1 << ((n) % NIFBITS)))
++#define IF_CLR(n, p) ((p)->ifs_bits[(n)/NIFBITS] &= ~(1 << ((n) % NIFBITS)))
++#define IF_ISSET(n, p) ((p)->ifs_bits[(n)/NIFBITS] & (1 << ((n) % NIFBITS)))
++#define IF_COPY(f, t) bcopy(f, t, sizeof(*(f)))
++#define IF_ZERO(p) bzero(p, sizeof(*(p)))
++
++/*
++ * Passed by mrouted for an MRT_ADD_MIF - again we use the
++ * mrouted 3.6 structures for compatibility
++ */
++
++struct mif6ctl {
++ mifi_t mif6c_mifi; /* Index of MIF */
++ unsigned char mif6c_flags; /* MIFF_ flags */
++ unsigned char vifc_threshold; /* ttl limit */
++ u_short mif6c_pifi; /* the index of the physical IF */
++ unsigned int vifc_rate_limit; /* Rate limiter values (NI) */
++};
++
++#define MIFF_REGISTER 0x1 /* register vif */
++
++/*
++ * Cache manipulation structures for mrouted and PIMd
++ */
++
++struct mf6cctl
++{
++ struct sockaddr_in6 mf6cc_origin; /* Origin of mcast */
++ struct sockaddr_in6 mf6cc_mcastgrp; /* Group in question */
++ mifi_t mf6cc_parent; /* Where it arrived */
++ struct if_set mf6cc_ifset; /* Where it is going */
++};
++
++/*
++ * Group count retrieval for pim6sd
++ */
++
++struct sioc_sg_req6
++{
++ struct sockaddr_in6 src;
++ struct sockaddr_in6 grp;
++ unsigned long pktcnt;
++ unsigned long bytecnt;
++ unsigned long wrong_if;
++};
++
++/*
++ * To get vif packet counts
++ */
++
++struct sioc_mif_req6
++{
++ mifi_t mifi; /* Which iface */
++ unsigned long icount; /* In packets */
++ unsigned long ocount; /* Out packets */
++ unsigned long ibytes; /* In bytes */
++ unsigned long obytes; /* Out bytes */
++};
++
++/*
++ * That's all usermode folks
++ */
++
++#ifdef __KERNEL__
++
++#include <linux/skbuff.h> /* for struct sk_buff_head */
++
++#ifdef CONFIG_IPV6_MROUTE
++static inline int ip6_mroute_opt(int opt)
++{
++ return (opt >= MRT6_BASE) && (opt <= MRT6_BASE + 10);
++}
++#else
++static inline int ip6_mroute_opt(int opt)
++{
++ return 0;
++}
++#endif
++
++struct sock;
++
++extern int ip6_mroute_setsockopt(struct sock *, int, char __user *, int);
++extern int ip6_mroute_getsockopt(struct sock *, int, char __user *, int __user *);
++extern int ip6_mr_input(struct sk_buff *skb);
++extern int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg);
++extern void ip6_mr_init(void);
++
++struct mif_device
++{
++ struct net_device *dev; /* Device we are using */
++ unsigned long bytes_in,bytes_out;
++ unsigned long pkt_in,pkt_out; /* Statistics */
++ unsigned long rate_limit; /* Traffic shaping (NI) */
++ unsigned char threshold; /* TTL threshold */
++ unsigned short flags; /* Control flags */
++ int link; /* Physical interface index */
++};
++
++#define VIFF_STATIC 0x8000
++
++struct mfc6_cache
++{
++ struct mfc6_cache *next; /* Next entry on cache line */
++ struct in6_addr mf6c_mcastgrp; /* Group the entry belongs to */
++ struct in6_addr mf6c_origin; /* Source of packet */
++ mifi_t mf6c_parent; /* Source interface */
++ int mfc_flags; /* Flags on line */
++
++ union {
++ struct {
++ unsigned long expires;
++ struct sk_buff_head unresolved; /* Unresolved buffers */
++ } unres;
++ struct {
++ unsigned long last_assert;
++ int minvif;
++ int maxvif;
++ unsigned long bytes;
++ unsigned long pkt;
++ unsigned long wrong_if;
++ unsigned char ttls[MAXMIFS]; /* TTL thresholds */
++ } res;
++ } mfc_un;
++};
++
++#define MFC_STATIC 1
++#define MFC_NOTIFY 2
++
++#define MFC6_LINES 64
++
++#define MFC6_HASH(a, g) (((__force u32)(a)->s6_addr32[0] ^ \
++ (__force u32)(a)->s6_addr32[1] ^ \
++ (__force u32)(a)->s6_addr32[2] ^ \
++ (__force u32)(a)->s6_addr32[3] ^ \
++ (__force u32)(g)->s6_addr32[0] ^ \
++ (__force u32)(g)->s6_addr32[1] ^ \
++ (__force u32)(g)->s6_addr32[2] ^ \
++ (__force u32)(g)->s6_addr32[3]) % MFC6_LINES)
++
++#define MFC_ASSERT_THRESH (3*HZ) /* Maximal freq. of asserts */
++
++#endif
++
++#ifdef __KERNEL__
++struct rtmsg;
++extern int ip6mr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait);
++
++#ifdef CONFIG_IPV6_MROUTE
++extern struct sock *mroute6_socket;
++extern int ip6mr_sk_done(struct sock *sk);
++#else
++#define mroute6_socket NULL
++static inline int ip6mr_sk_done(struct sock *sk) { return 0; }
++#endif
++#endif
++
++/*
++ * Structure used to communicate from kernel to multicast router.
++ * We'll overlay the structure onto an MLD header (not an IPv6 heder like igmpmsg{}
++ * used for IPv4 implementation). This is because this structure will be passed via an
++ * IPv6 raw socket, on wich an application will only receiver the payload i.e the data after
++ * the IPv6 header and all the extension headers. (See section 3 of RFC 3542)
++ */
++
++struct mrt6msg {
++#define MRT6MSG_NOCACHE 1
++#define MRT6MSG_WRONGMIF 2
++#define MRT6MSG_WHOLEPKT 3 /* used for use level encap */
++ __u8 im6_mbz; /* must be zero */
++ __u8 im6_msgtype; /* what type of message */
++ __u16 im6_mif; /* mif rec'd on */
++ __u32 im6_pad; /* padding for 64 bit arch */
++ struct in6_addr im6_src, im6_dst;
++};
++
++#endif
+diff --git a/include/linux/mtd/inftl.h b/include/linux/mtd/inftl.h
+index 6977780..85fd041 100644
+--- a/include/linux/mtd/inftl.h
++++ b/include/linux/mtd/inftl.h
+@@ -57,6 +57,11 @@ extern char inftlmountrev[];
+ void INFTL_dumptables(struct INFTLrecord *s);
+ void INFTL_dumpVUchains(struct INFTLrecord *s);
+
++int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
++ size_t *retlen, uint8_t *buf);
++int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
++ size_t *retlen, uint8_t *buf);
++
+ #endif /* __KERNEL__ */
+
+ #endif /* __MTD_INFTL_H__ */
+diff --git a/include/linux/mtd/nftl.h b/include/linux/mtd/nftl.h
+index bcf2fb3..001eec5 100644
+--- a/include/linux/mtd/nftl.h
++++ b/include/linux/mtd/nftl.h
+@@ -43,6 +43,11 @@ struct NFTLrecord {
+ int NFTL_mount(struct NFTLrecord *s);
+ int NFTL_formatblock(struct NFTLrecord *s, int block);
+
++int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
++ size_t *retlen, uint8_t *buf);
++int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
++ size_t *retlen, uint8_t *buf);
++
+ #ifndef NFTL_MAJOR
+ #define NFTL_MAJOR 93
+ #endif
+diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
+index fd0a260..9aa2a91 100644
+--- a/include/linux/mtd/onenand.h
++++ b/include/linux/mtd/onenand.h
+@@ -187,4 +187,7 @@ struct onenand_manufacturers {
+ char *name;
+ };
+
++int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
++ struct mtd_oob_ops *ops);
++
+ #endif /* __LINUX_MTD_ONENAND_H */
+diff --git a/include/linux/mtd/plat-ram.h b/include/linux/mtd/plat-ram.h
+index 9667863..0e37ad0 100644
+--- a/include/linux/mtd/plat-ram.h
++++ b/include/linux/mtd/plat-ram.h
+@@ -21,8 +21,9 @@
+ #define PLATRAM_RW (1)
+
+ struct platdata_mtd_ram {
+- char *mapname;
+- char **probes;
++ const char *mapname;
++ const char **map_probes;
++ const char **probes;
+ struct mtd_partition *partitions;
+ int nr_partitions;
+ int bankwidth;
+diff --git a/include/linux/mtio.h b/include/linux/mtio.h
+index 6f8d2d4..ef01d6a 100644
+--- a/include/linux/mtio.h
++++ b/include/linux/mtio.h
+@@ -192,6 +192,7 @@ struct mtpos {
+ #define MT_ST_SCSI2LOGICAL 0x800
+ #define MT_ST_SYSV 0x1000
+ #define MT_ST_NOWAIT 0x2000
++#define MT_ST_SILI 0x4000
+
+ /* The mode parameters to be controlled. Parameter chosen with bits 20-28 */
+ #define MT_ST_CLEAR_DEFAULT 0xfffff
+diff --git a/include/linux/net.h b/include/linux/net.h
+index c414d90..71f7dd5 100644
+--- a/include/linux/net.h
++++ b/include/linux/net.h
+@@ -19,6 +19,7 @@
+ #define _LINUX_NET_H
+
+ #include <linux/wait.h>
++#include <linux/socket.h>
+ #include <asm/socket.h>
+
+ struct poll_table_struct;
+@@ -26,7 +27,7 @@ struct pipe_inode_info;
+ struct inode;
+ struct net;
+
+-#define NPROTO 34 /* should be enough for now.. */
++#define NPROTO AF_MAX
+
+ #define SYS_SOCKET 1 /* sys_socket(2) */
+ #define SYS_BIND 2 /* sys_bind(2) */
+diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
+index ee81906..7c1d446 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -710,8 +710,10 @@ struct net_device
+ void (*poll_controller)(struct net_device *dev);
+ #endif
+
++#ifdef CONFIG_NET_NS
+ /* Network namespace this network device is inside */
+ struct net *nd_net;
++#endif
+
+ /* bridge stuff */
+ struct net_bridge_port *br_port;
+@@ -726,6 +728,10 @@ struct net_device
+ /* rtnetlink link ops */
+ const struct rtnl_link_ops *rtnl_link_ops;
+
++ /* for setting kernel sock attribute on TCP connection setup */
++#define GSO_MAX_SIZE 65536
++ unsigned int gso_max_size;
++
+ /* The TX queue control structures */
+ unsigned int egress_subqueue_count;
+ struct net_device_subqueue egress_subqueue[1];
+@@ -735,6 +741,28 @@ struct net_device
+ #define NETDEV_ALIGN 32
+ #define NETDEV_ALIGN_CONST (NETDEV_ALIGN - 1)
+
++/*
++ * Net namespace inlines
++ */
++static inline
++struct net *dev_net(const struct net_device *dev)
++{
++#ifdef CONFIG_NET_NS
++ return dev->nd_net;
++#else
++ return &init_net;
++#endif
++}
++
++static inline
++void dev_net_set(struct net_device *dev, struct net *net)
++{
++#ifdef CONFIG_NET_NS
++ release_net(dev->nd_net);
++ dev->nd_net = hold_net(net);
++#endif
++}
++
+ /**
+ * netdev_priv - access network device private data
+ * @dev: network device
+@@ -811,7 +839,7 @@ static inline struct net_device *next_net_device(struct net_device *dev)
+ struct list_head *lh;
+ struct net *net;
+
+- net = dev->nd_net;
++ net = dev_net(dev);
+ lh = dev->dev_list.next;
+ return lh == &net->dev_base_head ? NULL : net_device_entry(lh);
+ }
+@@ -1479,6 +1507,12 @@ static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
+ unlikely(skb->ip_summed != CHECKSUM_PARTIAL));
+ }
+
++static inline void netif_set_gso_max_size(struct net_device *dev,
++ unsigned int size)
++{
++ dev->gso_max_size = size;
++}
++
+ /* On bonding slaves other than the currently active slave, suppress
+ * duplicates except for 802.3ad ETH_P_SLOW, alb non-mcast/bcast, and
+ * ARP on active-backup slaves with arp_validate enabled.
+diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
+index f0680c2..e4c6659 100644
+--- a/include/linux/netfilter.h
++++ b/include/linux/netfilter.h
+@@ -6,11 +6,13 @@
+ #include <linux/types.h>
+ #include <linux/skbuff.h>
+ #include <linux/net.h>
++#include <linux/netdevice.h>
+ #include <linux/if.h>
+ #include <linux/in.h>
+ #include <linux/in6.h>
+ #include <linux/wait.h>
+ #include <linux/list.h>
++#include <net/net_namespace.h>
+ #endif
+ #include <linux/compiler.h>
+
+@@ -61,13 +63,21 @@ union nf_inet_addr {
+ #ifdef __KERNEL__
+ #ifdef CONFIG_NETFILTER
+
++static inline int nf_inet_addr_cmp(const union nf_inet_addr *a1,
++ const union nf_inet_addr *a2)
++{
++ return a1->all[0] == a2->all[0] &&
++ a1->all[1] == a2->all[1] &&
++ a1->all[2] == a2->all[2] &&
++ a1->all[3] == a2->all[3];
++}
++
+ extern void netfilter_init(void);
+
+ /* Largest hook number + 1 */
+ #define NF_MAX_HOOKS 8
+
+ struct sk_buff;
+-struct net_device;
+
+ typedef unsigned int nf_hookfn(unsigned int hooknum,
+ struct sk_buff *skb,
+@@ -224,6 +234,11 @@ struct nf_afinfo {
+ unsigned short family;
+ __sum16 (*checksum)(struct sk_buff *skb, unsigned int hook,
+ unsigned int dataoff, u_int8_t protocol);
++ __sum16 (*checksum_partial)(struct sk_buff *skb,
++ unsigned int hook,
++ unsigned int dataoff,
++ unsigned int len,
++ u_int8_t protocol);
+ int (*route)(struct dst_entry **dst, struct flowi *fl);
+ void (*saveroute)(const struct sk_buff *skb,
+ struct nf_queue_entry *entry);
+@@ -253,6 +268,23 @@ nf_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff,
+ return csum;
+ }
+
++static inline __sum16
++nf_checksum_partial(struct sk_buff *skb, unsigned int hook,
++ unsigned int dataoff, unsigned int len,
++ u_int8_t protocol, unsigned short family)
++{
++ const struct nf_afinfo *afinfo;
++ __sum16 csum = 0;
++
++ rcu_read_lock();
++ afinfo = nf_get_afinfo(family);
++ if (afinfo)
++ csum = afinfo->checksum_partial(skb, hook, dataoff, len,
++ protocol);
++ rcu_read_unlock();
++ return csum;
++}
++
+ extern int nf_register_afinfo(const struct nf_afinfo *afinfo);
+ extern void nf_unregister_afinfo(const struct nf_afinfo *afinfo);
+
+@@ -311,5 +343,56 @@ extern void (*nf_ct_destroy)(struct nf_conntrack *);
+ static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {}
+ #endif
+
++static inline struct net *nf_pre_routing_net(const struct net_device *in,
++ const struct net_device *out)
++{
++#ifdef CONFIG_NET_NS
++ return in->nd_net;
++#else
++ return &init_net;
++#endif
++}
++
++static inline struct net *nf_local_in_net(const struct net_device *in,
++ const struct net_device *out)
++{
++#ifdef CONFIG_NET_NS
++ return in->nd_net;
++#else
++ return &init_net;
++#endif
++}
++
++static inline struct net *nf_forward_net(const struct net_device *in,
++ const struct net_device *out)
++{
++#ifdef CONFIG_NET_NS
++ BUG_ON(in->nd_net != out->nd_net);
++ return in->nd_net;
++#else
++ return &init_net;
++#endif
++}
++
++static inline struct net *nf_local_out_net(const struct net_device *in,
++ const struct net_device *out)
++{
++#ifdef CONFIG_NET_NS
++ return out->nd_net;
++#else
++ return &init_net;
++#endif
++}
++
++static inline struct net *nf_post_routing_net(const struct net_device *in,
++ const struct net_device *out)
++{
++#ifdef CONFIG_NET_NS
++ return out->nd_net;
++#else
++ return &init_net;
++#endif
++}
++
+ #endif /*__KERNEL__*/
+ #endif /*__LINUX_NETFILTER_H*/
+diff --git a/include/linux/netfilter/nf_conntrack_dccp.h b/include/linux/netfilter/nf_conntrack_dccp.h
+new file mode 100644
+index 0000000..40dcc82
+--- /dev/null
++++ b/include/linux/netfilter/nf_conntrack_dccp.h
+@@ -0,0 +1,40 @@
++#ifndef _NF_CONNTRACK_DCCP_H
++#define _NF_CONNTRACK_DCCP_H
++
++/* Exposed to userspace over nfnetlink */
++enum ct_dccp_states {
++ CT_DCCP_NONE,
++ CT_DCCP_REQUEST,
++ CT_DCCP_RESPOND,
++ CT_DCCP_PARTOPEN,
++ CT_DCCP_OPEN,
++ CT_DCCP_CLOSEREQ,
++ CT_DCCP_CLOSING,
++ CT_DCCP_TIMEWAIT,
++ CT_DCCP_IGNORE,
++ CT_DCCP_INVALID,
++ __CT_DCCP_MAX
++};
++#define CT_DCCP_MAX (__CT_DCCP_MAX - 1)
++
++enum ct_dccp_roles {
++ CT_DCCP_ROLE_CLIENT,
++ CT_DCCP_ROLE_SERVER,
++ __CT_DCCP_ROLE_MAX
++};
++#define CT_DCCP_ROLE_MAX (__CT_DCCP_ROLE_MAX - 1)
++
++#ifdef __KERNEL__
++#include <net/netfilter/nf_conntrack_tuple.h>
++
++struct nf_ct_dccp {
++ u_int8_t role[IP_CT_DIR_MAX];
++ u_int8_t state;
++ u_int8_t last_pkt;
++ u_int8_t last_dir;
++ u_int64_t handshake_seq;
++};
++
++#endif /* __KERNEL__ */
++
++#endif /* _NF_CONNTRACK_DCCP_H */
+diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h
+index 8e5ce1c..5da04e5 100644
+--- a/include/linux/netfilter/nf_conntrack_sip.h
++++ b/include/linux/netfilter/nf_conntrack_sip.h
+@@ -5,37 +5,164 @@
+ #define SIP_PORT 5060
+ #define SIP_TIMEOUT 3600
+
+-enum sip_header_pos {
+- POS_REG_REQ_URI,
+- POS_REQ_URI,
+- POS_FROM,
+- POS_TO,
+- POS_VIA,
+- POS_CONTACT,
+- POS_CONTENT,
+- POS_MEDIA,
+- POS_OWNER_IP4,
+- POS_CONNECTION_IP4,
+- POS_OWNER_IP6,
+- POS_CONNECTION_IP6,
+- POS_SDP_HEADER,
++struct nf_ct_sip_master {
++ unsigned int register_cseq;
++};
++
++enum sip_expectation_classes {
++ SIP_EXPECT_SIGNALLING,
++ SIP_EXPECT_AUDIO,
++ SIP_EXPECT_VIDEO,
++ __SIP_EXPECT_MAX
++};
++#define SIP_EXPECT_MAX (__SIP_EXPECT_MAX - 1)
++
++struct sdp_media_type {
++ const char *name;
++ unsigned int len;
++ enum sip_expectation_classes class;
++};
++
++#define SDP_MEDIA_TYPE(__name, __class) \
++{ \
++ .name = (__name), \
++ .len = sizeof(__name) - 1, \
++ .class = (__class), \
++}
++
++struct sip_handler {
++ const char *method;
++ unsigned int len;
++ int (*request)(struct sk_buff *skb,
++ const char **dptr, unsigned int *datalen,
++ unsigned int cseq);
++ int (*response)(struct sk_buff *skb,
++ const char **dptr, unsigned int *datalen,
++ unsigned int cseq, unsigned int code);
++};
++
++#define SIP_HANDLER(__method, __request, __response) \
++{ \
++ .method = (__method), \
++ .len = sizeof(__method) - 1, \
++ .request = (__request), \
++ .response = (__response), \
++}
++
++struct sip_header {
++ const char *name;
++ const char *cname;
++ const char *search;
++ unsigned int len;
++ unsigned int clen;
++ unsigned int slen;
++ int (*match_len)(const struct nf_conn *ct,
++ const char *dptr, const char *limit,
++ int *shift);
++};
++
++#define __SIP_HDR(__name, __cname, __search, __match) \
++{ \
++ .name = (__name), \
++ .len = sizeof(__name) - 1, \
++ .cname = (__cname), \
++ .clen = (__cname) ? sizeof(__cname) - 1 : 0, \
++ .search = (__search), \
++ .slen = (__search) ? sizeof(__search) - 1 : 0, \
++ .match_len = (__match), \
++}
++
++#define SIP_HDR(__name, __cname, __search, __match) \
++ __SIP_HDR(__name, __cname, __search, __match)
++
++#define SDP_HDR(__name, __search, __match) \
++ __SIP_HDR(__name, NULL, __search, __match)
++
++enum sip_header_types {
++ SIP_HDR_CSEQ,
++ SIP_HDR_FROM,
++ SIP_HDR_TO,
++ SIP_HDR_CONTACT,
++ SIP_HDR_VIA,
++ SIP_HDR_EXPIRES,
++ SIP_HDR_CONTENT_LENGTH,
++};
++
++enum sdp_header_types {
++ SDP_HDR_UNSPEC,
++ SDP_HDR_VERSION,
++ SDP_HDR_OWNER_IP4,
++ SDP_HDR_CONNECTION_IP4,
++ SDP_HDR_OWNER_IP6,
++ SDP_HDR_CONNECTION_IP6,
++ SDP_HDR_MEDIA,
+ };
+
+ extern unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb,
+- enum ip_conntrack_info ctinfo,
+- struct nf_conn *ct,
+- const char **dptr);
+-extern unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb,
+- enum ip_conntrack_info ctinfo,
+- struct nf_conntrack_expect *exp,
+- const char *dptr);
+-
+-extern int ct_sip_get_info(const struct nf_conn *ct, const char *dptr,
+- size_t dlen, unsigned int *matchoff,
+- unsigned int *matchlen, enum sip_header_pos pos);
+-extern int ct_sip_lnlen(const char *line, const char *limit);
+-extern const char *ct_sip_search(const char *needle, const char *haystack,
+- size_t needle_len, size_t haystack_len,
+- int case_sensitive);
++ const char **dptr,
++ unsigned int *datalen);
++extern unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb,
++ const char **dptr,
++ unsigned int *datalen,
++ struct nf_conntrack_expect *exp,
++ unsigned int matchoff,
++ unsigned int matchlen);
++extern unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb,
++ const char **dptr,
++ unsigned int dataoff,
++ unsigned int *datalen,
++ enum sdp_header_types type,
++ enum sdp_header_types term,
++ const union nf_inet_addr *addr);
++extern unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb,
++ const char **dptr,
++ unsigned int *datalen,
++ unsigned int matchoff,
++ unsigned int matchlen,
++ u_int16_t port);
++extern unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb,
++ const char **dptr,
++ unsigned int dataoff,
++ unsigned int *datalen,
++ const union nf_inet_addr *addr);
++extern unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb,
++ const char **dptr,
++ unsigned int *datalen,
++ struct nf_conntrack_expect *rtp_exp,
++ struct nf_conntrack_expect *rtcp_exp,
++ unsigned int mediaoff,
++ unsigned int medialen,
++ union nf_inet_addr *rtp_addr);
++
++extern int ct_sip_parse_request(const struct nf_conn *ct,
++ const char *dptr, unsigned int datalen,
++ unsigned int *matchoff, unsigned int *matchlen,
++ union nf_inet_addr *addr, __be16 *port);
++extern int ct_sip_get_header(const struct nf_conn *ct, const char *dptr,
++ unsigned int dataoff, unsigned int datalen,
++ enum sip_header_types type,
++ unsigned int *matchoff, unsigned int *matchlen);
++extern int ct_sip_parse_header_uri(const struct nf_conn *ct, const char *dptr,
++ unsigned int *dataoff, unsigned int datalen,
++ enum sip_header_types type, int *in_header,
++ unsigned int *matchoff, unsigned int *matchlen,
++ union nf_inet_addr *addr, __be16 *port);
++extern int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr,
++ unsigned int dataoff, unsigned int datalen,
++ const char *name,
++ unsigned int *matchoff, unsigned int *matchlen,
++ union nf_inet_addr *addr);
++extern int ct_sip_parse_numerical_param(const struct nf_conn *ct, const char *dptr,
++ unsigned int off, unsigned int datalen,
++ const char *name,
++ unsigned int *matchoff, unsigned int *matchen,
++ unsigned int *val);
++
++extern int ct_sip_get_sdp_header(const struct nf_conn *ct, const char *dptr,
++ unsigned int dataoff, unsigned int datalen,
++ enum sdp_header_types type,
++ enum sdp_header_types term,
++ unsigned int *matchoff, unsigned int *matchlen);
++
+ #endif /* __KERNEL__ */
+ #endif /* __NF_CONNTRACK_SIP_H__ */
+diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h
+index e3e1533..0a383ac 100644
+--- a/include/linux/netfilter/nfnetlink_conntrack.h
++++ b/include/linux/netfilter/nfnetlink_conntrack.h
+@@ -80,6 +80,7 @@ enum ctattr_l4proto {
+ enum ctattr_protoinfo {
+ CTA_PROTOINFO_UNSPEC,
+ CTA_PROTOINFO_TCP,
++ CTA_PROTOINFO_DCCP,
+ __CTA_PROTOINFO_MAX
+ };
+ #define CTA_PROTOINFO_MAX (__CTA_PROTOINFO_MAX - 1)
+@@ -95,6 +96,13 @@ enum ctattr_protoinfo_tcp {
+ };
+ #define CTA_PROTOINFO_TCP_MAX (__CTA_PROTOINFO_TCP_MAX - 1)
+
++enum ctattr_protoinfo_dccp {
++ CTA_PROTOINFO_DCCP_UNSPEC,
++ CTA_PROTOINFO_DCCP_STATE,
++ __CTA_PROTOINFO_DCCP_MAX,
++};
++#define CTA_PROTOINFO_DCCP_MAX (__CTA_PROTOINFO_DCCP_MAX - 1)
++
+ enum ctattr_counters {
+ CTA_COUNTERS_UNSPEC,
+ CTA_COUNTERS_PACKETS, /* old 64bit counters */
+diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
+index b2c62cc..2326296 100644
+--- a/include/linux/netfilter/x_tables.h
++++ b/include/linux/netfilter/x_tables.h
+@@ -430,13 +430,13 @@ extern int xt_compat_add_offset(int af, unsigned int offset, short delta);
+ extern void xt_compat_flush_offsets(int af);
+ extern short xt_compat_calc_jump(int af, unsigned int offset);
+
+-extern int xt_compat_match_offset(struct xt_match *match);
++extern int xt_compat_match_offset(const struct xt_match *match);
+ extern int xt_compat_match_from_user(struct xt_entry_match *m,
+ void **dstptr, unsigned int *size);
+ extern int xt_compat_match_to_user(struct xt_entry_match *m,
+ void __user **dstptr, unsigned int *size);
+
+-extern int xt_compat_target_offset(struct xt_target *target);
++extern int xt_compat_target_offset(const struct xt_target *target);
+ extern void xt_compat_target_from_user(struct xt_entry_target *t,
+ void **dstptr, unsigned int *size);
+ extern int xt_compat_target_to_user(struct xt_entry_target *t,
+diff --git a/include/linux/netfilter/xt_sctp.h b/include/linux/netfilter/xt_sctp.h
+index dd5a4fd..32000ba 100644
+--- a/include/linux/netfilter/xt_sctp.h
++++ b/include/linux/netfilter/xt_sctp.h
+@@ -37,68 +37,54 @@ struct xt_sctp_info {
+
+ #define SCTP_CHUNKMAP_SET(chunkmap, type) \
+ do { \
+- chunkmap[type / bytes(u_int32_t)] |= \
++ (chunkmap)[type / bytes(u_int32_t)] |= \
+ 1 << (type % bytes(u_int32_t)); \
+ } while (0)
+
+ #define SCTP_CHUNKMAP_CLEAR(chunkmap, type) \
+ do { \
+- chunkmap[type / bytes(u_int32_t)] &= \
++ (chunkmap)[type / bytes(u_int32_t)] &= \
+ ~(1 << (type % bytes(u_int32_t))); \
+ } while (0)
+
+ #define SCTP_CHUNKMAP_IS_SET(chunkmap, type) \
+ ({ \
+- (chunkmap[type / bytes (u_int32_t)] & \
++ ((chunkmap)[type / bytes (u_int32_t)] & \
+ (1 << (type % bytes (u_int32_t)))) ? 1: 0; \
+ })
+
+-#define SCTP_CHUNKMAP_RESET(chunkmap) \
+- do { \
+- int i; \
+- for (i = 0; i < ARRAY_SIZE(chunkmap); i++) \
+- chunkmap[i] = 0; \
+- } while (0)
+-
+-#define SCTP_CHUNKMAP_SET_ALL(chunkmap) \
+- do { \
+- int i; \
+- for (i = 0; i < ARRAY_SIZE(chunkmap); i++) \
+- chunkmap[i] = ~0; \
+- } while (0)
+-
+-#define SCTP_CHUNKMAP_COPY(destmap, srcmap) \
+- do { \
+- int i; \
+- for (i = 0; i < ARRAY_SIZE(srcmap); i++) \
+- destmap[i] = srcmap[i]; \
+- } while (0)
+-
+-#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap) \
+-({ \
+- int i; \
+- int flag = 1; \
+- for (i = 0; i < ARRAY_SIZE(chunkmap); i++) { \
+- if (chunkmap[i]) { \
+- flag = 0; \
+- break; \
+- } \
+- } \
+- flag; \
+-})
+-
+-#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap) \
+-({ \
+- int i; \
+- int flag = 1; \
+- for (i = 0; i < ARRAY_SIZE(chunkmap); i++) { \
+- if (chunkmap[i] != ~0) { \
+- flag = 0; \
+- break; \
+- } \
+- } \
+- flag; \
+-})
++#define SCTP_CHUNKMAP_RESET(chunkmap) \
++ memset((chunkmap), 0, sizeof(chunkmap))
++
++#define SCTP_CHUNKMAP_SET_ALL(chunkmap) \
++ memset((chunkmap), ~0U, sizeof(chunkmap))
++
++#define SCTP_CHUNKMAP_COPY(destmap, srcmap) \
++ memcpy((destmap), (srcmap), sizeof(srcmap))
++
++#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap) \
++ __sctp_chunkmap_is_clear((chunkmap), ARRAY_SIZE(chunkmap))
++static inline bool
++__sctp_chunkmap_is_clear(const u_int32_t *chunkmap, unsigned int n)
++{
++ unsigned int i;
++ for (i = 0; i < n; ++i)
++ if (chunkmap[i])
++ return false;
++ return true;
++}
++
++#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap) \
++ __sctp_chunkmap_is_all_set((chunkmap), ARRAY_SIZE(chunkmap))
++static inline bool
++__sctp_chunkmap_is_all_set(const u_int32_t *chunkmap, unsigned int n)
++{
++ unsigned int i;
++ for (i = 0; i < n; ++i)
++ if (chunkmap[i] != ~0U)
++ return false;
++ return true;
++}
+
+ #endif /* _XT_SCTP_H_ */
+
+diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
+index db223ca..dd9c97f 100644
+--- a/include/linux/netfilter_arp/arp_tables.h
++++ b/include/linux/netfilter_arp/arp_tables.h
+@@ -23,8 +23,6 @@
+
+ #define ARPT_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
+ #define ARPT_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN
+-#define arpt_target xt_target
+-#define arpt_table xt_table
+
+ #define ARPT_DEV_ADDR_LEN_MAX 16
+
+@@ -266,20 +264,15 @@ struct arpt_error
+ .target.errorname = "ERROR", \
+ }
+
+-#define arpt_register_target(tgt) \
+-({ (tgt)->family = NF_ARP; \
+- xt_register_target(tgt); })
+-#define arpt_unregister_target(tgt) xt_unregister_target(tgt)
+-
+-extern struct arpt_table *arpt_register_table(struct net *net,
+- struct arpt_table *table,
+- const struct arpt_replace *repl);
+-extern void arpt_unregister_table(struct arpt_table *table);
++extern struct xt_table *arpt_register_table(struct net *net,
++ struct xt_table *table,
++ const struct arpt_replace *repl);
++extern void arpt_unregister_table(struct xt_table *table);
+ extern unsigned int arpt_do_table(struct sk_buff *skb,
+ unsigned int hook,
+ const struct net_device *in,
+ const struct net_device *out,
+- struct arpt_table *table);
++ struct xt_table *table);
+
+ #define ARPT_ALIGN(s) XT_ALIGN(s)
+
+diff --git a/include/linux/netfilter_bridge/ebt_nflog.h b/include/linux/netfilter_bridge/ebt_nflog.h
+new file mode 100644
+index 0000000..0528178
+--- /dev/null
++++ b/include/linux/netfilter_bridge/ebt_nflog.h
+@@ -0,0 +1,21 @@
++#ifndef __LINUX_BRIDGE_EBT_NFLOG_H
++#define __LINUX_BRIDGE_EBT_NFLOG_H
++
++#define EBT_NFLOG_MASK 0x0
++
++#define EBT_NFLOG_PREFIX_SIZE 64
++#define EBT_NFLOG_WATCHER "nflog"
++
++#define EBT_NFLOG_DEFAULT_GROUP 0x1
++#define EBT_NFLOG_DEFAULT_THRESHOLD 1
++
++struct ebt_nflog_info {
++ u_int32_t len;
++ u_int16_t group;
++ u_int16_t threshold;
++ u_int16_t flags;
++ u_int16_t pad;
++ char prefix[EBT_NFLOG_PREFIX_SIZE];
++};
++
++#endif /* __LINUX_BRIDGE_EBT_NFLOG_H */
+diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
+index 9a10092..650318b 100644
+--- a/include/linux/netfilter_ipv4.h
++++ b/include/linux/netfilter_ipv4.h
+@@ -62,8 +62,6 @@ enum nf_ip_hook_priorities {
+ NF_IP_PRI_FILTER = 0,
+ NF_IP_PRI_NAT_SRC = 100,
+ NF_IP_PRI_SELINUX_LAST = 225,
+- NF_IP_PRI_CONNTRACK_HELPER = INT_MAX - 2,
+- NF_IP_PRI_NAT_SEQ_ADJUST = INT_MAX - 1,
+ NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX,
+ NF_IP_PRI_LAST = INT_MAX,
+ };
+diff --git a/include/linux/nfs3.h b/include/linux/nfs3.h
+index 7f11fa5..539f3b5 100644
+--- a/include/linux/nfs3.h
++++ b/include/linux/nfs3.h
+@@ -96,7 +96,7 @@ struct nfs3_fh {
+ #define MOUNTPROC3_UMNTALL 4
+
+
+-#if defined(__KERNEL__) || defined(NFS_NEED_KERNEL_TYPES)
++#if defined(__KERNEL__)
+
+ /* Number of 32bit words in post_op_attr */
+ #define NFS3_POST_OP_ATTR_WORDS 22
+diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
+index f4a0e4c..27d6a8d 100644
+--- a/include/linux/nfs_fs.h
++++ b/include/linux/nfs_fs.h
+@@ -430,7 +430,6 @@ extern void nfs_unregister_sysctl(void);
+ /*
+ * linux/fs/nfs/namespace.c
+ */
+-extern struct list_head nfs_automount_list;
+ extern const struct inode_operations nfs_mountpoint_inode_operations;
+ extern const struct inode_operations nfs_referral_inode_operations;
+ extern int nfs_mountpoint_expiry_timeout;
+@@ -466,9 +465,9 @@ extern int nfs_wb_page(struct inode *inode, struct page* page);
+ extern int nfs_wb_page_cancel(struct inode *inode, struct page* page);
+ #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
+ extern int nfs_commit_inode(struct inode *, int);
+-extern struct nfs_write_data *nfs_commit_alloc(void);
++extern struct nfs_write_data *nfs_commitdata_alloc(void);
+ extern void nfs_commit_free(struct nfs_write_data *wdata);
+-extern void nfs_commit_release(void *wdata);
++extern void nfs_commitdata_release(void *wdata);
+ #else
+ static inline int
+ nfs_commit_inode(struct inode *inode, int how)
+diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
+index 3423c67..c9beacd 100644
+--- a/include/linux/nfs_fs_sb.h
++++ b/include/linux/nfs_fs_sb.h
+@@ -32,6 +32,8 @@ struct nfs_client {
+ const struct nfs_rpc_ops *rpc_ops; /* NFS protocol vector */
+ int cl_proto; /* Network transport protocol */
+
++ struct rpc_cred *cl_machine_cred;
++
+ #ifdef CONFIG_NFS_V4
+ u64 cl_clientid; /* constant */
+ nfs4_verifier cl_confirm;
+@@ -93,6 +95,7 @@ struct nfs_server {
+ unsigned int wpages; /* write size (in pages) */
+ unsigned int wtmult; /* server disk block size */
+ unsigned int dtsize; /* readdir size */
++ unsigned short port; /* "port=" setting */
+ unsigned int bsize; /* server block size */
+ unsigned int acregmin; /* attr cache timeouts */
+ unsigned int acregmax;
+@@ -117,6 +120,13 @@ struct nfs_server {
+
+ atomic_t active; /* Keep trace of any activity to this server */
+ wait_queue_head_t active_wq; /* Wait for any activity to stop */
++
++ /* mountd-related mount options */
++ struct sockaddr_storage mountd_address;
++ size_t mountd_addrlen;
++ u32 mountd_version;
++ unsigned short mountd_port;
++ unsigned short mountd_protocol;
+ };
+
+ /* Server capabilities */
+diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
+index f301d0b..24263bb 100644
+--- a/include/linux/nfs_xdr.h
++++ b/include/linux/nfs_xdr.h
+@@ -140,6 +140,7 @@ struct nfs_openres {
+ __u32 rflags;
+ struct nfs_fattr * f_attr;
+ struct nfs_fattr * dir_attr;
++ struct nfs_seqid * seqid;
+ const struct nfs_server *server;
+ int delegation_type;
+ nfs4_stateid delegation;
+@@ -159,6 +160,7 @@ struct nfs_open_confirmargs {
+
+ struct nfs_open_confirmres {
+ nfs4_stateid stateid;
++ struct nfs_seqid * seqid;
+ };
+
+ /*
+@@ -175,6 +177,7 @@ struct nfs_closeargs {
+ struct nfs_closeres {
+ nfs4_stateid stateid;
+ struct nfs_fattr * fattr;
++ struct nfs_seqid * seqid;
+ const struct nfs_server *server;
+ };
+ /*
+@@ -199,7 +202,9 @@ struct nfs_lock_args {
+ };
+
+ struct nfs_lock_res {
+- nfs4_stateid stateid;
++ nfs4_stateid stateid;
++ struct nfs_seqid * lock_seqid;
++ struct nfs_seqid * open_seqid;
+ };
+
+ struct nfs_locku_args {
+@@ -210,7 +215,8 @@ struct nfs_locku_args {
+ };
+
+ struct nfs_locku_res {
+- nfs4_stateid stateid;
++ nfs4_stateid stateid;
++ struct nfs_seqid * seqid;
+ };
+
+ struct nfs_lockt_args {
+diff --git a/include/linux/nfsd/Kbuild b/include/linux/nfsd/Kbuild
+index e726fc3..fc97204 100644
+--- a/include/linux/nfsd/Kbuild
++++ b/include/linux/nfsd/Kbuild
+@@ -1,6 +1,6 @@
+ unifdef-y += const.h
++unifdef-y += debug.h
+ unifdef-y += export.h
++unifdef-y += nfsfh.h
+ unifdef-y += stats.h
+ unifdef-y += syscall.h
+-unifdef-y += nfsfh.h
+-unifdef-y += debug.h
+diff --git a/include/linux/nfsd/cache.h b/include/linux/nfsd/cache.h
+index 7b5d784..04b355c 100644
+--- a/include/linux/nfsd/cache.h
++++ b/include/linux/nfsd/cache.h
+@@ -10,7 +10,6 @@
+ #ifndef NFSCACHE_H
+ #define NFSCACHE_H
+
+-#ifdef __KERNEL__
+ #include <linux/in.h>
+ #include <linux/uio.h>
+
+@@ -77,5 +76,4 @@ void nfsd_reply_cache_shutdown(void);
+ int nfsd_cache_lookup(struct svc_rqst *, int);
+ void nfsd_cache_update(struct svc_rqst *, int, __be32 *);
+
+-#endif /* __KERNEL__ */
+ #endif /* NFSCACHE_H */
+diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
+index 8caf4c4..41d30c9 100644
+--- a/include/linux/nfsd/nfsd.h
++++ b/include/linux/nfsd/nfsd.h
+@@ -27,7 +27,6 @@
+ #define NFSD_VERSION "0.5"
+ #define NFSD_SUPPORTED_MINOR_VERSION 0
+
+-#ifdef __KERNEL__
+ /*
+ * Special flags for nfsd_permission. These must be different from MAY_READ,
+ * MAY_WRITE, and MAY_EXEC.
+@@ -56,12 +55,20 @@ extern struct svc_program nfsd_program;
+ extern struct svc_version nfsd_version2, nfsd_version3,
+ nfsd_version4;
+ extern struct svc_serv *nfsd_serv;
++
++extern struct seq_operations nfs_exports_op;
++
+ /*
+ * Function prototypes.
+ */
+ int nfsd_svc(unsigned short port, int nrservs);
+ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp);
+
++int nfsd_nrthreads(void);
++int nfsd_nrpools(void);
++int nfsd_get_nrthreads(int n, int *);
++int nfsd_set_nrthreads(int n, int *);
++
+ /* nfsd/vfs.c */
+ int fh_lock_parent(struct svc_fh *, struct dentry *);
+ int nfsd_racache_init(int);
+@@ -322,10 +329,8 @@ extern struct timeval nfssvc_boot;
+ (FATTR4_WORD0_SIZE | FATTR4_WORD0_ACL )
+ #define NFSD_WRITEABLE_ATTRS_WORD1 \
+ (FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP \
+- | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_METADATA | FATTR4_WORD1_TIME_MODIFY_SET)
++ | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET)
+
+ #endif /* CONFIG_NFSD_V4 */
+
+-#endif /* __KERNEL__ */
+-
+ #endif /* LINUX_NFSD_NFSD_H */
+diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
+index 9fecf90..ea6517e 100644
+--- a/include/linux/nl80211.h
++++ b/include/linux/nl80211.h
+@@ -78,6 +78,18 @@
+ * or, if no MAC address given, all stations, on the interface identified
+ * by %NL80211_ATTR_IFINDEX.
+ *
++ * @NL80211_CMD_GET_MPATH: Get mesh path attributes for mesh path to
++ * destination %NL80211_ATTR_MAC on the interface identified by
++ * %NL80211_ATTR_IFINDEX.
++ * @NL80211_CMD_SET_MPATH: Set mesh path attributes for mesh path to
++ * destination %NL80211_ATTR_MAC on the interface identified by
++ * %NL80211_ATTR_IFINDEX.
++ * @NL80211_CMD_NEW_PATH: Add a mesh path with given attributes to the
++ * the interface identified by %NL80211_ATTR_IFINDEX.
++ * @NL80211_CMD_DEL_PATH: Remove a mesh path identified by %NL80211_ATTR_MAC
++ * or, if no MAC address given, all mesh paths, on the interface identified
++ * by %NL80211_ATTR_IFINDEX.
++ *
+ * @NL80211_CMD_MAX: highest used command number
+ * @__NL80211_CMD_AFTER_LAST: internal use
+ */
+@@ -112,6 +124,11 @@ enum nl80211_commands {
+
+ /* add commands here */
+
++ NL80211_CMD_GET_MPATH,
++ NL80211_CMD_SET_MPATH,
++ NL80211_CMD_NEW_MPATH,
++ NL80211_CMD_DEL_MPATH,
++
+ /* used to define NL80211_CMD_MAX below */
+ __NL80211_CMD_AFTER_LAST,
+ NL80211_CMD_MAX = __NL80211_CMD_AFTER_LAST - 1
+@@ -157,9 +174,23 @@ enum nl80211_commands {
+ * restriction (at most %NL80211_MAX_SUPP_RATES).
+ * @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station
+ * to, or the AP interface the station was originally added to to.
+- * @NL80211_ATTR_STA_STATS: statistics for a station, part of station info
++ * @NL80211_ATTR_STA_INFO: information about a station, part of station info
+ * given for %NL80211_CMD_GET_STATION, nested attribute containing
+- * info as possible, see &enum nl80211_sta_stats.
++ * info as possible, see &enum nl80211_sta_info.
++ *
++ * @NL80211_ATTR_WIPHY_BANDS: Information about an operating bands,
++ * consisting of a nested array.
++ *
++ * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes).
++ * @NL80211_ATTR_PLINK_ACTION: action to perform on the mesh peer link.
++ * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path.
++ * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path
++ * info given for %NL80211_CMD_GET_MPATH, nested attribute described at
++ * &enum nl80211_mpath_info.
++ *
++ *
++ * @NL80211_ATTR_MNTR_FLAGS: flags, nested element with NLA_FLAG attributes of
++ * &enum nl80211_mntr_flags.
+ *
+ * @NL80211_ATTR_MAX: highest attribute number currently defined
+ * @__NL80211_ATTR_AFTER_LAST: internal use
+@@ -193,10 +224,19 @@ enum nl80211_attrs {
+ NL80211_ATTR_STA_LISTEN_INTERVAL,
+ NL80211_ATTR_STA_SUPPORTED_RATES,
+ NL80211_ATTR_STA_VLAN,
+- NL80211_ATTR_STA_STATS,
++ NL80211_ATTR_STA_INFO,
++
++ NL80211_ATTR_WIPHY_BANDS,
++
++ NL80211_ATTR_MNTR_FLAGS,
+
+ /* add attributes here, update the policy in nl80211.c */
+
++ NL80211_ATTR_MESH_ID,
++ NL80211_ATTR_STA_PLINK_ACTION,
++ NL80211_ATTR_MPATH_NEXT_HOP,
++ NL80211_ATTR_MPATH_INFO,
++
+ __NL80211_ATTR_AFTER_LAST,
+ NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
+ };
+@@ -213,6 +253,7 @@ enum nl80211_attrs {
+ * @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points
+ * @NL80211_IFTYPE_WDS: wireless distribution interface
+ * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames
++ * @NL80211_IFTYPE_MESH_POINT: mesh point
+ * @NL80211_IFTYPE_MAX: highest interface type number currently defined
+ * @__NL80211_IFTYPE_AFTER_LAST: internal use
+ *
+@@ -228,6 +269,7 @@ enum nl80211_iftype {
+ NL80211_IFTYPE_AP_VLAN,
+ NL80211_IFTYPE_WDS,
+ NL80211_IFTYPE_MONITOR,
++ NL80211_IFTYPE_MESH_POINT,
+
+ /* keep last */
+ __NL80211_IFTYPE_AFTER_LAST,
+@@ -257,27 +299,167 @@ enum nl80211_sta_flags {
+ };
+
+ /**
+- * enum nl80211_sta_stats - station statistics
++ * enum nl80211_sta_info - station information
+ *
+- * These attribute types are used with %NL80211_ATTR_STA_STATS
++ * These attribute types are used with %NL80211_ATTR_STA_INFO
+ * when getting information about a station.
+ *
+- * @__NL80211_STA_STAT_INVALID: attribute number 0 is reserved
+- * @NL80211_STA_STAT_INACTIVE_TIME: time since last activity (u32, msecs)
+- * @NL80211_STA_STAT_RX_BYTES: total received bytes (u32, from this station)
+- * @NL80211_STA_STAT_TX_BYTES: total transmitted bytes (u32, to this station)
+- * @__NL80211_STA_STAT_AFTER_LAST: internal
+- * @NL80211_STA_STAT_MAX: highest possible station stats attribute
++ * @__NL80211_STA_INFO_INVALID: attribute number 0 is reserved
++ * @NL80211_STA_INFO_INACTIVE_TIME: time since last activity (u32, msecs)
++ * @NL80211_STA_INFO_RX_BYTES: total received bytes (u32, from this station)
++ * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
++ * @__NL80211_STA_INFO_AFTER_LAST: internal
++ * @NL80211_STA_INFO_MAX: highest possible station info attribute
++ */
++enum nl80211_sta_info {
++ __NL80211_STA_INFO_INVALID,
++ NL80211_STA_INFO_INACTIVE_TIME,
++ NL80211_STA_INFO_RX_BYTES,
++ NL80211_STA_INFO_TX_BYTES,
++ NL80211_STA_INFO_LLID,
++ NL80211_STA_INFO_PLID,
++ NL80211_STA_INFO_PLINK_STATE,
++
++ /* keep last */
++ __NL80211_STA_INFO_AFTER_LAST,
++ NL80211_STA_INFO_MAX = __NL80211_STA_INFO_AFTER_LAST - 1
++};
++
++/**
++ * enum nl80211_mpath_flags - nl80211 mesh path flags
++ *
++ * @NL80211_MPATH_FLAG_ACTIVE: the mesh path is active
++ * @NL80211_MPATH_FLAG_RESOLVING: the mesh path discovery process is running
++ * @NL80211_MPATH_FLAG_DSN_VALID: the mesh path contains a valid DSN
++ * @NL80211_MPATH_FLAG_FIXED: the mesh path has been manually set
++ * @NL80211_MPATH_FLAG_RESOLVED: the mesh path discovery process succeeded
++ */
++enum nl80211_mpath_flags {
++ NL80211_MPATH_FLAG_ACTIVE = 1<<0,
++ NL80211_MPATH_FLAG_RESOLVING = 1<<1,
++ NL80211_MPATH_FLAG_DSN_VALID = 1<<2,
++ NL80211_MPATH_FLAG_FIXED = 1<<3,
++ NL80211_MPATH_FLAG_RESOLVED = 1<<4,
++};
++
++/**
++ * enum nl80211_mpath_info - mesh path information
++ *
++ * These attribute types are used with %NL80211_ATTR_MPATH_INFO when getting
++ * information about a mesh path.
++ *
++ * @__NL80211_MPATH_INFO_INVALID: attribute number 0 is reserved
++ * @NL80211_ATTR_MPATH_FRAME_QLEN: number of queued frames for this destination
++ * @NL80211_ATTR_MPATH_DSN: destination sequence number
++ * @NL80211_ATTR_MPATH_METRIC: metric (cost) of this mesh path
++ * @NL80211_ATTR_MPATH_EXPTIME: expiration time for the path, in msec from now
++ * @NL80211_ATTR_MPATH_FLAGS: mesh path flags, enumerated in
++ * &enum nl80211_mpath_flags;
++ * @NL80211_ATTR_MPATH_DISCOVERY_TIMEOUT: total path discovery timeout, in msec
++ * @NL80211_ATTR_MPATH_DISCOVERY_RETRIES: mesh path discovery retries
++ */
++enum nl80211_mpath_info {
++ __NL80211_MPATH_INFO_INVALID,
++ NL80211_MPATH_INFO_FRAME_QLEN,
++ NL80211_MPATH_INFO_DSN,
++ NL80211_MPATH_INFO_METRIC,
++ NL80211_MPATH_INFO_EXPTIME,
++ NL80211_MPATH_INFO_FLAGS,
++ NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
++ NL80211_MPATH_INFO_DISCOVERY_RETRIES,
++
++ /* keep last */
++ __NL80211_MPATH_INFO_AFTER_LAST,
++ NL80211_MPATH_INFO_MAX = __NL80211_MPATH_INFO_AFTER_LAST - 1
++};
++
++/**
++ * enum nl80211_band_attr - band attributes
++ * @__NL80211_BAND_ATTR_INVALID: attribute number 0 is reserved
++ * @NL80211_BAND_ATTR_FREQS: supported frequencies in this band,
++ * an array of nested frequency attributes
++ * @NL80211_BAND_ATTR_RATES: supported bitrates in this band,
++ * an array of nested bitrate attributes
++ */
++enum nl80211_band_attr {
++ __NL80211_BAND_ATTR_INVALID,
++ NL80211_BAND_ATTR_FREQS,
++ NL80211_BAND_ATTR_RATES,
++
++ /* keep last */
++ __NL80211_BAND_ATTR_AFTER_LAST,
++ NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1
++};
++
++/**
++ * enum nl80211_frequency_attr - frequency attributes
++ * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz
++ * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current
++ * regulatory domain.
++ * @NL80211_FREQUENCY_ATTR_PASSIVE_SCAN: Only passive scanning is
++ * permitted on this channel in current regulatory domain.
++ * @NL80211_FREQUENCY_ATTR_NO_IBSS: IBSS networks are not permitted
++ * on this channel in current regulatory domain.
++ * @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory
++ * on this channel in current regulatory domain.
++ */
++enum nl80211_frequency_attr {
++ __NL80211_FREQUENCY_ATTR_INVALID,
++ NL80211_FREQUENCY_ATTR_FREQ,
++ NL80211_FREQUENCY_ATTR_DISABLED,
++ NL80211_FREQUENCY_ATTR_PASSIVE_SCAN,
++ NL80211_FREQUENCY_ATTR_NO_IBSS,
++ NL80211_FREQUENCY_ATTR_RADAR,
++
++ /* keep last */
++ __NL80211_FREQUENCY_ATTR_AFTER_LAST,
++ NL80211_FREQUENCY_ATTR_MAX = __NL80211_FREQUENCY_ATTR_AFTER_LAST - 1
++};
++
++/**
++ * enum nl80211_bitrate_attr - bitrate attributes
++ * @NL80211_BITRATE_ATTR_RATE: Bitrate in units of 100 kbps
++ * @NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE: Short preamble supported
++ * in 2.4 GHz band.
++ */
++enum nl80211_bitrate_attr {
++ __NL80211_BITRATE_ATTR_INVALID,
++ NL80211_BITRATE_ATTR_RATE,
++ NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE,
++
++ /* keep last */
++ __NL80211_BITRATE_ATTR_AFTER_LAST,
++ NL80211_BITRATE_ATTR_MAX = __NL80211_BITRATE_ATTR_AFTER_LAST - 1
++};
++
++/**
++ * enum nl80211_mntr_flags - monitor configuration flags
++ *
++ * Monitor configuration flags.
++ *
++ * @__NL80211_MNTR_FLAG_INVALID: reserved
++ *
++ * @NL80211_MNTR_FLAG_FCSFAIL: pass frames with bad FCS
++ * @NL80211_MNTR_FLAG_PLCPFAIL: pass frames with bad PLCP
++ * @NL80211_MNTR_FLAG_CONTROL: pass control frames
++ * @NL80211_MNTR_FLAG_OTHER_BSS: disable BSSID filtering
++ * @NL80211_MNTR_FLAG_COOK_FRAMES: report frames after processing.
++ * overrides all other flags.
++ *
++ * @__NL80211_MNTR_FLAG_AFTER_LAST: internal use
++ * @NL80211_MNTR_FLAG_MAX: highest possible monitor flag
+ */
+-enum nl80211_sta_stats {
+- __NL80211_STA_STAT_INVALID,
+- NL80211_STA_STAT_INACTIVE_TIME,
+- NL80211_STA_STAT_RX_BYTES,
+- NL80211_STA_STAT_TX_BYTES,
++enum nl80211_mntr_flags {
++ __NL80211_MNTR_FLAG_INVALID,
++ NL80211_MNTR_FLAG_FCSFAIL,
++ NL80211_MNTR_FLAG_PLCPFAIL,
++ NL80211_MNTR_FLAG_CONTROL,
++ NL80211_MNTR_FLAG_OTHER_BSS,
++ NL80211_MNTR_FLAG_COOK_FRAMES,
+
+ /* keep last */
+- __NL80211_STA_STAT_AFTER_LAST,
+- NL80211_STA_STAT_MAX = __NL80211_STA_STAT_AFTER_LAST - 1
++ __NL80211_MNTR_FLAG_AFTER_LAST,
++ NL80211_MNTR_FLAG_MAX = __NL80211_MNTR_FLAG_AFTER_LAST - 1
+ };
+
+ #endif /* __LINUX_NL80211_H */
+diff --git a/include/linux/of.h b/include/linux/of.h
+index 6981016..59a61bd 100644
+--- a/include/linux/of.h
++++ b/include/linux/of.h
+@@ -62,6 +62,7 @@ extern struct property *of_find_property(const struct device_node *np,
+ int *lenp);
+ extern int of_device_is_compatible(const struct device_node *device,
+ const char *);
++extern int of_device_is_available(const struct device_node *device);
+ extern const void *of_get_property(const struct device_node *node,
+ const char *name,
+ int *lenp);
+diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h
+new file mode 100644
+index 0000000..2ee97e9
+--- /dev/null
++++ b/include/linux/of_gpio.h
+@@ -0,0 +1,69 @@
++/*
++ * OF helpers for the GPIO API
++ *
++ * Copyright (c) 2007-2008 MontaVista Software, Inc.
++ *
++ * Author: Anton Vorontsov <avorontsov at ru.mvista.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.
++ */
++
++#ifndef __LINUX_OF_GPIO_H
++#define __LINUX_OF_GPIO_H
++
++#include <linux/errno.h>
++#include <asm/gpio.h>
++
++#ifdef CONFIG_OF_GPIO
++
++/*
++ * Generic OF GPIO chip
++ */
++struct of_gpio_chip {
++ struct gpio_chip gc;
++ int gpio_cells;
++ int (*xlate)(struct of_gpio_chip *of_gc, struct device_node *np,
++ const void *gpio_spec);
++};
++
++static inline struct of_gpio_chip *to_of_gpio_chip(struct gpio_chip *gc)
++{
++ return container_of(gc, struct of_gpio_chip, gc);
++}
++
++/*
++ * OF GPIO chip for memory mapped banks
++ */
++struct of_mm_gpio_chip {
++ struct of_gpio_chip of_gc;
++ void (*save_regs)(struct of_mm_gpio_chip *mm_gc);
++ void __iomem *regs;
++};
++
++static inline struct of_mm_gpio_chip *to_of_mm_gpio_chip(struct gpio_chip *gc)
++{
++ struct of_gpio_chip *of_gc = to_of_gpio_chip(gc);
++
++ return container_of(of_gc, struct of_mm_gpio_chip, of_gc);
++}
++
++extern int of_get_gpio(struct device_node *np, int index);
++extern int of_mm_gpiochip_add(struct device_node *np,
++ struct of_mm_gpio_chip *mm_gc);
++extern int of_gpio_simple_xlate(struct of_gpio_chip *of_gc,
++ struct device_node *np,
++ const void *gpio_spec);
++#else
++
++/* Drivers may not strictly depend on the GPIO support, so let them link. */
++static inline int of_get_gpio(struct device_node *np, int index)
++{
++ return -ENOSYS;
++}
++
++#endif /* CONFIG_OF_GPIO */
++
++#endif /* __LINUX_OF_GPIO_H */
+diff --git a/include/linux/of_i2c.h b/include/linux/of_i2c.h
+new file mode 100644
+index 0000000..2e5a967
+--- /dev/null
++++ b/include/linux/of_i2c.h
+@@ -0,0 +1,24 @@
++/*
++ * Generic I2C API implementation for PowerPC.
++ *
++ * Copyright (c) 2008 Jochen Friedrich <jochen at scram.de>
++ *
++ * 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 __LINUX_OF_I2C_H
++#define __LINUX_OF_I2C_H
++
++#include <linux/i2c.h>
++
++#ifdef CONFIG_OF_I2C
++
++void of_register_i2c_devices(struct i2c_adapter *adap,
++ struct device_node *adap_node);
++
++#endif /* CONFIG_OF_I2C */
++
++#endif /* __LINUX_OF_I2C_H */
+diff --git a/include/linux/parport.h b/include/linux/parport.h
+index d1ad546..dcb9e01 100644
+--- a/include/linux/parport.h
++++ b/include/linux/parport.h
+@@ -101,9 +101,9 @@ typedef enum {
+ #include <linux/spinlock.h>
+ #include <linux/wait.h>
+ #include <linux/irqreturn.h>
++#include <linux/semaphore.h>
+ #include <asm/system.h>
+ #include <asm/ptrace.h>
+-#include <asm/semaphore.h>
+
+ /* Define this later. */
+ struct parport;
+diff --git a/include/linux/pci-aspm.h b/include/linux/pci-aspm.h
+new file mode 100644
+index 0000000..a1a1e61
+--- /dev/null
++++ b/include/linux/pci-aspm.h
+@@ -0,0 +1,56 @@
++/*
++ * aspm.h
++ *
++ * PCI Express ASPM defines and function prototypes
++ *
++ * Copyright (C) 2007 Intel Corp.
++ * Zhang Yanmin (yanmin.zhang at intel.com)
++ * Shaohua Li (shaohua.li at intel.com)
++ *
++ * For more information, please consult the following manuals (look at
++ * http://www.pcisig.com/ for how to get them):
++ *
++ * PCI Express Specification
++ */
++
++#ifndef LINUX_ASPM_H
++#define LINUX_ASPM_H
++
++#include <linux/pci.h>
++
++#define PCIE_LINK_STATE_L0S 1
++#define PCIE_LINK_STATE_L1 2
++#define PCIE_LINK_STATE_CLKPM 4
++
++#ifdef CONFIG_PCIEASPM
++extern void pcie_aspm_init_link_state(struct pci_dev *pdev);
++extern void pcie_aspm_exit_link_state(struct pci_dev *pdev);
++extern void pcie_aspm_pm_state_change(struct pci_dev *pdev);
++extern void pci_disable_link_state(struct pci_dev *pdev, int state);
++#else
++static inline void pcie_aspm_init_link_state(struct pci_dev *pdev)
++{
++}
++static inline void pcie_aspm_exit_link_state(struct pci_dev *pdev)
++{
++}
++static inline void pcie_aspm_pm_state_change(struct pci_dev *pdev)
++{
++}
++static inline void pci_disable_link_state(struct pci_dev *pdev, int state)
++{
++}
++#endif
++
++#ifdef CONFIG_PCIEASPM_DEBUG /* this depends on CONFIG_PCIEASPM */
++extern void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev);
++extern void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev);
++#else
++static inline void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev)
++{
++}
++static inline void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
++{
++}
++#endif
++#endif /* LINUX_ASPM_H */
+diff --git a/include/linux/pci.h b/include/linux/pci.h
+index ea760e5..2924913 100644
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -20,6 +20,8 @@
+ /* Include the pci register defines */
+ #include <linux/pci_regs.h>
+
++struct pci_vpd;
++
+ /*
+ * The PCI interface treats multi-function devices as independent
+ * devices. The slot/function address of each device is encoded
+@@ -128,11 +130,11 @@ struct pci_cap_saved_state {
+ u32 data[0];
+ };
+
++struct pcie_link_state;
+ /*
+ * The pci_dev structure is used to describe PCI devices.
+ */
+ struct pci_dev {
+- struct list_head global_list; /* node in list of all PCI devices */
+ struct list_head bus_list; /* node in per-bus list */
+ struct pci_bus *bus; /* bus this device is on */
+ struct pci_bus *subordinate; /* bus this device bridges to */
+@@ -165,6 +167,10 @@ struct pci_dev {
+ this is D0-D3, D0 being fully functional,
+ and D3 being off. */
+
++#ifdef CONFIG_PCIEASPM
++ struct pcie_link_state *link_state; /* ASPM link state. */
++#endif
++
+ pci_channel_state_t error_state; /* current connectivity state */
+ struct device dev; /* Generic device interface */
+
+@@ -181,6 +187,7 @@ struct pci_dev {
+ unsigned int transparent:1; /* Transparent PCI bridge */
+ unsigned int multifunction:1;/* Part of multi-function device */
+ /* keep track of device state */
++ unsigned int is_added:1;
+ unsigned int is_busmaster:1; /* device is busmaster */
+ unsigned int no_msi:1; /* device may not use msi */
+ unsigned int no_d1d2:1; /* only allow d0 or d3 */
+@@ -201,11 +208,11 @@ struct pci_dev {
+ #ifdef CONFIG_PCI_MSI
+ struct list_head msi_list;
+ #endif
++ struct pci_vpd *vpd;
+ };
+
+ extern struct pci_dev *alloc_pci_dev(void);
+
+-#define pci_dev_g(n) list_entry(n, struct pci_dev, global_list)
+ #define pci_dev_b(n) list_entry(n, struct pci_dev, bus_list)
+ #define to_pci_dev(n) container_of(n, struct pci_dev, dev)
+ #define for_each_pci_dev(d) while ((d = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, d)) != NULL)
+@@ -449,7 +456,6 @@ extern struct bus_type pci_bus_type;
+ /* Do NOT directly access these two variables, unless you are arch specific pci
+ * code, or pci core code. */
+ extern struct list_head pci_root_buses; /* list of all known PCI buses */
+-extern struct list_head pci_devices; /* list of all devices */
+ /* Some device drivers need know if pci is initiated */
+ extern int no_pci_devices(void);
+
+@@ -517,17 +523,13 @@ struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
+
+ struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
+ struct pci_dev *from);
+-struct pci_dev *pci_get_device_reverse(unsigned int vendor, unsigned int device,
+- struct pci_dev *from);
+-
+ struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,
+ unsigned int ss_vendor, unsigned int ss_device,
+- struct pci_dev *from);
++ const struct pci_dev *from);
+ struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn);
+ struct pci_dev *pci_get_bus_and_slot(unsigned int bus, unsigned int devfn);
+ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from);
+ int pci_dev_present(const struct pci_device_id *ids);
+-const struct pci_device_id *pci_find_present(const struct pci_device_id *ids);
+
+ int pci_bus_read_config_byte(struct pci_bus *bus, unsigned int devfn,
+ int where, u8 *val);
+@@ -601,7 +603,6 @@ int pcie_get_readrq(struct pci_dev *dev);
+ int pcie_set_readrq(struct pci_dev *dev, int rq);
+ void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno);
+ int __must_check pci_assign_resource(struct pci_dev *dev, int i);
+-int __must_check pci_assign_resource_fixed(struct pci_dev *dev, int i);
+ int pci_select_bars(struct pci_dev *dev, unsigned long flags);
+
+ /* ROM control related routines */
+@@ -626,6 +627,7 @@ int pci_claim_resource(struct pci_dev *, int);
+ void pci_assign_unassigned_resources(void);
+ void pdev_enable_device(struct pci_dev *);
+ void pdev_sort_resources(struct pci_dev *, struct resource_list *);
++int pci_enable_resources(struct pci_dev *, int mask);
+ void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),
+ int (*)(struct pci_dev *, u8, u8));
+ #define HAVE_PCI_REQ_REGIONS 2
+@@ -793,18 +795,11 @@ static inline struct pci_dev *pci_get_device(unsigned int vendor,
+ return NULL;
+ }
+
+-static inline struct pci_dev *pci_get_device_reverse(unsigned int vendor,
+- unsigned int device,
+- struct pci_dev *from)
+-{
+- return NULL;
+-}
+-
+ static inline struct pci_dev *pci_get_subsys(unsigned int vendor,
+ unsigned int device,
+ unsigned int ss_vendor,
+ unsigned int ss_device,
+- struct pci_dev *from)
++ const struct pci_dev *from)
+ {
+ return NULL;
+ }
+@@ -817,7 +812,6 @@ static inline struct pci_dev *pci_get_class(unsigned int class,
+
+ #define pci_dev_present(ids) (0)
+ #define no_pci_devices() (1)
+-#define pci_find_present(ids) (NULL)
+ #define pci_dev_put(dev) do { } while (0)
+
+ static inline void pci_set_master(struct pci_dev *dev)
+diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h
+index c1914a8..c0c1223 100644
+--- a/include/linux/pci_regs.h
++++ b/include/linux/pci_regs.h
+@@ -395,9 +395,17 @@
+ #define PCI_EXP_DEVSTA_AUXPD 0x10 /* AUX Power Detected */
+ #define PCI_EXP_DEVSTA_TRPND 0x20 /* Transactions Pending */
+ #define PCI_EXP_LNKCAP 12 /* Link Capabilities */
++#define PCI_EXP_LNKCAP_ASPMS 0xc00 /* ASPM Support */
++#define PCI_EXP_LNKCAP_L0SEL 0x7000 /* L0s Exit Latency */
++#define PCI_EXP_LNKCAP_L1EL 0x38000 /* L1 Exit Latency */
++#define PCI_EXP_LNKCAP_CLKPM 0x40000 /* L1 Clock Power Management */
+ #define PCI_EXP_LNKCTL 16 /* Link Control */
++#define PCI_EXP_LNKCTL_RL 0x20 /* Retrain Link */
++#define PCI_EXP_LNKCTL_CCC 0x40 /* Common Clock COnfiguration */
+ #define PCI_EXP_LNKCTL_CLKREQ_EN 0x100 /* Enable clkreq */
+ #define PCI_EXP_LNKSTA 18 /* Link Status */
++#define PCI_EXP_LNKSTA_LT 0x800 /* Link Training */
++#define PCI_EXP_LNKSTA_SLC 0x1000 /* Slot Clock Configuration */
+ #define PCI_EXP_SLTCAP 20 /* Slot Capabilities */
+ #define PCI_EXP_SLTCTL 24 /* Slot Control */
+ #define PCI_EXP_SLTSTA 26 /* Slot Status */
+diff --git a/include/linux/pcounter.h b/include/linux/pcounter.h
+deleted file mode 100644
+index a82d9f2..0000000
+--- a/include/linux/pcounter.h
++++ /dev/null
+@@ -1,74 +0,0 @@
+-#ifndef __LINUX_PCOUNTER_H
+-#define __LINUX_PCOUNTER_H
+-/*
+- * Using a dynamic percpu 'int' variable has a cost :
+- * 1) Extra dereference
+- * Current per_cpu_ptr() implementation uses an array per 'percpu variable'.
+- * 2) memory cost of NR_CPUS*(32+sizeof(void *)) instead of num_possible_cpus()*4
+- *
+- * This pcounter implementation is an abstraction to be able to use
+- * either a static or a dynamic per cpu variable.
+- * One dynamic per cpu variable gets a fast & cheap implementation, we can
+- * change pcounter implementation too.
+- */
+-struct pcounter {
+-#ifdef CONFIG_SMP
+- void (*add)(struct pcounter *self, int inc);
+- int (*getval)(const struct pcounter *self, int cpu);
+- int *per_cpu_values;
+-#else
+- int val;
+-#endif
+-};
+-
+-#ifdef CONFIG_SMP
+-#include <linux/percpu.h>
+-
+-#define DEFINE_PCOUNTER(NAME) \
+-static DEFINE_PER_CPU(int, NAME##_pcounter_values); \
+-static void NAME##_pcounter_add(struct pcounter *self, int val) \
+-{ \
+- __get_cpu_var(NAME##_pcounter_values) += val; \
+-} \
+-static int NAME##_pcounter_getval(const struct pcounter *self, int cpu) \
+-{ \
+- return per_cpu(NAME##_pcounter_values, cpu); \
+-} \
+-
+-#define PCOUNTER_MEMBER_INITIALIZER(NAME, MEMBER) \
+- MEMBER = { \
+- .add = NAME##_pcounter_add, \
+- .getval = NAME##_pcounter_getval, \
+- }
+-
+-
+-static inline void pcounter_add(struct pcounter *self, int inc)
+-{
+- self->add(self, inc);
+-}
+-
+-extern int pcounter_getval(const struct pcounter *self);
+-extern int pcounter_alloc(struct pcounter *self);
+-extern void pcounter_free(struct pcounter *self);
+-
+-
+-#else /* CONFIG_SMP */
+-
+-static inline void pcounter_add(struct pcounter *self, int inc)
+-{
+- self->val += inc;
+-}
+-
+-static inline int pcounter_getval(const struct pcounter *self)
+-{
+- return self->val;
+-}
+-
+-#define DEFINE_PCOUNTER(NAME)
+-#define PCOUNTER_MEMBER_INITIALIZER(NAME, MEMBER)
+-#define pcounter_alloc(self) 0
+-#define pcounter_free(self)
+-
+-#endif /* CONFIG_SMP */
+-
+-#endif /* __LINUX_PCOUNTER_H */
+diff --git a/include/linux/phy.h b/include/linux/phy.h
+index 5e43ae7..02df20f 100644
+--- a/include/linux/phy.h
++++ b/include/linux/phy.h
+@@ -39,7 +39,8 @@
+ SUPPORTED_1000baseT_Half | \
+ SUPPORTED_1000baseT_Full)
+
+-/* Set phydev->irq to PHY_POLL if interrupts are not supported,
++/*
++ * Set phydev->irq to PHY_POLL if interrupts are not supported,
+ * or not desired for this PHY. Set to PHY_IGNORE_INTERRUPT if
+ * the attached driver handles the interrupt
+ */
+@@ -63,8 +64,6 @@ typedef enum {
+ PHY_INTERFACE_MODE_RTBI
+ } phy_interface_t;
+
+-#define MII_BUS_MAX 4
+-
+
+ #define PHY_INIT_TIMEOUT 100000
+ #define PHY_STATE_TIME 1
+@@ -74,20 +73,30 @@ typedef enum {
+ #define PHY_MAX_ADDR 32
+
+ /* Used when trying to connect to a specific phy (mii bus id:phy device id) */
+-#define PHY_ID_FMT "%x:%02x"
++#define PHY_ID_FMT "%s:%02x"
++
++/*
++ * Need to be a little smaller than phydev->dev.bus_id to leave room
++ * for the ":%02x"
++ */
++#define MII_BUS_ID_SIZE (BUS_ID_SIZE - 3)
+
+-/* The Bus class for PHYs. Devices which provide access to
+- * PHYs should register using this structure */
++/*
++ * The Bus class for PHYs. Devices which provide access to
++ * PHYs should register using this structure
++ */
+ struct mii_bus {
+ const char *name;
+- int id;
++ char id[MII_BUS_ID_SIZE];
+ void *priv;
+ int (*read)(struct mii_bus *bus, int phy_id, int regnum);
+ int (*write)(struct mii_bus *bus, int phy_id, int regnum, u16 val);
+ int (*reset)(struct mii_bus *bus);
+
+- /* A lock to ensure that only one thing can read/write
+- * the MDIO bus at a time */
++ /*
++ * A lock to ensure that only one thing can read/write
++ * the MDIO bus at a time
++ */
+ struct mutex mdio_lock;
+
+ struct device *dev;
+@@ -98,8 +107,10 @@ struct mii_bus {
+ /* Phy addresses to be ignored when probing */
+ u32 phy_mask;
+
+- /* Pointer to an array of interrupts, each PHY's
+- * interrupt at the index matching its address */
++ /*
++ * Pointer to an array of interrupts, each PHY's
++ * interrupt at the index matching its address
++ */
+ int *irq;
+ };
+
+@@ -251,7 +262,8 @@ struct phy_device {
+ /* Bus address of the PHY (0-32) */
+ int addr;
+
+- /* forced speed & duplex (no autoneg)
++ /*
++ * forced speed & duplex (no autoneg)
+ * partner speed & duplex & pause (autoneg)
+ */
+ int speed;
+@@ -274,8 +286,10 @@ struct phy_device {
+
+ int link_timeout;
+
+- /* Interrupt number for this PHY
+- * -1 means no interrupt */
++ /*
++ * Interrupt number for this PHY
++ * -1 means no interrupt
++ */
+ int irq;
+
+ /* private data pointer */
+@@ -325,22 +339,28 @@ struct phy_driver {
+ u32 features;
+ u32 flags;
+
+- /* Called to initialize the PHY,
+- * including after a reset */
++ /*
++ * Called to initialize the PHY,
++ * including after a reset
++ */
+ int (*config_init)(struct phy_device *phydev);
+
+- /* Called during discovery. Used to set
+- * up device-specific structures, if any */
++ /*
++ * Called during discovery. Used to set
++ * up device-specific structures, if any
++ */
+ int (*probe)(struct phy_device *phydev);
+
+ /* PHY Power Management */
+ int (*suspend)(struct phy_device *phydev);
+ int (*resume)(struct phy_device *phydev);
+
+- /* Configures the advertisement and resets
++ /*
++ * Configures the advertisement and resets
+ * autonegotiation if phydev->autoneg is on,
+ * forces the speed to the current settings in phydev
+- * if phydev->autoneg is off */
++ * if phydev->autoneg is off
++ */
+ int (*config_aneg)(struct phy_device *phydev);
+
+ /* Determines the negotiated speed and duplex */
+@@ -359,14 +379,27 @@ struct phy_driver {
+ };
+ #define to_phy_driver(d) container_of(d, struct phy_driver, driver)
+
++#define PHY_ANY_ID "MATCH ANY PHY"
++#define PHY_ANY_UID 0xffffffff
++
++/* A Structure for boards to register fixups with the PHY Lib */
++struct phy_fixup {
++ struct list_head list;
++ char bus_id[BUS_ID_SIZE];
++ u32 phy_uid;
++ u32 phy_uid_mask;
++ int (*run)(struct phy_device *phydev);
++};
++
+ int phy_read(struct phy_device *phydev, u16 regnum);
+ int phy_write(struct phy_device *phydev, u16 regnum, u16 val);
++int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id);
+ struct phy_device* get_phy_device(struct mii_bus *bus, int addr);
+ int phy_clear_interrupt(struct phy_device *phydev);
+ int phy_config_interrupt(struct phy_device *phydev, u32 interrupts);
+ struct phy_device * phy_attach(struct net_device *dev,
+- const char *phy_id, u32 flags, phy_interface_t interface);
+-struct phy_device * phy_connect(struct net_device *dev, const char *phy_id,
++ const char *bus_id, u32 flags, phy_interface_t interface);
++struct phy_device * phy_connect(struct net_device *dev, const char *bus_id,
+ void (*handler)(struct net_device *), u32 flags,
+ phy_interface_t interface);
+ void phy_disconnect(struct phy_device *phydev);
+@@ -406,5 +439,13 @@ void phy_print_status(struct phy_device *phydev);
+ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id);
+ void phy_device_free(struct phy_device *phydev);
+
++int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask,
++ int (*run)(struct phy_device *));
++int phy_register_fixup_for_id(const char *bus_id,
++ int (*run)(struct phy_device *));
++int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask,
++ int (*run)(struct phy_device *));
++int phy_scan_fixups(struct phy_device *phydev);
++
+ extern struct bus_type mdio_bus_type;
+ #endif /* __PHY_H */
+diff --git a/include/linux/pim.h b/include/linux/pim.h
+new file mode 100644
+index 0000000..236ffd3
+--- /dev/null
++++ b/include/linux/pim.h
+@@ -0,0 +1,45 @@
++#ifndef __LINUX_PIM_H
++#define __LINUX_PIM_H
++
++#include <asm/byteorder.h>
++
++#ifndef __KERNEL__
++struct pim {
++#if defined(__LITTLE_ENDIAN_BITFIELD)
++ __u8 pim_type:4, /* PIM message type */
++ pim_ver:4; /* PIM version */
++#elif defined(__BIG_ENDIAN_BITFIELD)
++ __u8 pim_ver:4; /* PIM version */
++ pim_type:4; /* PIM message type */
++#endif
++ __u8 pim_rsv; /* Reserved */
++ __be16 pim_cksum; /* Checksum */
++};
++
++#define PIM_MINLEN 8
++#endif
++
++/* Message types - V1 */
++#define PIM_V1_VERSION __constant_htonl(0x10000000)
++#define PIM_V1_REGISTER 1
++
++/* Message types - V2 */
++#define PIM_VERSION 2
++#define PIM_REGISTER 1
++
++#if defined(__KERNEL__)
++#define PIM_NULL_REGISTER __constant_htonl(0x40000000)
++
++/* PIMv2 register message header layout (ietf-draft-idmr-pimvsm-v2-00.ps */
++struct pimreghdr
++{
++ __u8 type;
++ __u8 reserved;
++ __be16 csum;
++ __be32 flags;
++};
++
++struct sk_buff;
++extern int pim_rcv_v1(struct sk_buff *);
++#endif
++#endif
+diff --git a/include/linux/pm.h b/include/linux/pm.h
+index 015b735..1de72cb 100644
+--- a/include/linux/pm.h
++++ b/include/linux/pm.h
+@@ -183,8 +183,9 @@ typedef struct pm_message {
+ struct dev_pm_info {
+ pm_message_t power_state;
+ unsigned can_wakeup:1;
+-#ifdef CONFIG_PM_SLEEP
+ unsigned should_wakeup:1;
++ bool sleeping:1; /* Owned by the PM core */
++#ifdef CONFIG_PM_SLEEP
+ struct list_head entry;
+ #endif
+ };
+@@ -197,11 +198,6 @@ extern void device_resume(void);
+ extern int device_suspend(pm_message_t state);
+ extern int device_prepare_suspend(pm_message_t state);
+
+-#define device_set_wakeup_enable(dev,val) \
+- ((dev)->power.should_wakeup = !!(val))
+-#define device_may_wakeup(dev) \
+- (device_can_wakeup(dev) && (dev)->power.should_wakeup)
+-
+ extern void __suspend_report_result(const char *function, void *fn, int ret);
+
+ #define suspend_report_result(fn, ret) \
+@@ -209,20 +205,6 @@ extern void __suspend_report_result(const char *function, void *fn, int ret);
+ __suspend_report_result(__FUNCTION__, fn, ret); \
+ } while (0)
+
+-/*
+- * Platform hook to activate device wakeup capability, if that's not already
+- * handled by enable_irq_wake() etc.
+- * Returns zero on success, else negative errno
+- */
+-extern int (*platform_enable_wakeup)(struct device *dev, int is_on);
+-
+-static inline int call_platform_enable_wakeup(struct device *dev, int is_on)
+-{
+- if (platform_enable_wakeup)
+- return (*platform_enable_wakeup)(dev, is_on);
+- return 0;
+-}
+-
+ #else /* !CONFIG_PM_SLEEP */
+
+ static inline int device_suspend(pm_message_t state)
+@@ -230,29 +212,10 @@ static inline int device_suspend(pm_message_t state)
+ return 0;
+ }
+
+-#define device_set_wakeup_enable(dev,val) do{}while(0)
+-#define device_may_wakeup(dev) (0)
+-
+-#define suspend_report_result(fn, ret) do { } while (0)
+-
+-static inline int call_platform_enable_wakeup(struct device *dev, int is_on)
+-{
+- return 0;
+-}
++#define suspend_report_result(fn, ret) do {} while (0)
+
+ #endif /* !CONFIG_PM_SLEEP */
+
+-/* changes to device_may_wakeup take effect on the next pm state change.
+- * by default, devices should wakeup if they can.
+- */
+-#define device_can_wakeup(dev) \
+- ((dev)->power.can_wakeup)
+-#define device_init_wakeup(dev,val) \
+- do { \
+- device_can_wakeup(dev) = !!(val); \
+- device_set_wakeup_enable(dev,val); \
+- } while(0)
+-
+ /*
+ * Global Power Management flags
+ * Used to keep APM and ACPI from both being active
+diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h
+new file mode 100644
+index 0000000..f0d0b2c
+--- /dev/null
++++ b/include/linux/pm_wakeup.h
+@@ -0,0 +1,90 @@
++/*
++ * pm_wakeup.h - Power management wakeup interface
++ *
++ * Copyright (C) 2008 Alan Stern
++ *
++ * 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 _LINUX_PM_WAKEUP_H
++#define _LINUX_PM_WAKEUP_H
++
++#ifndef _DEVICE_H_
++# error "please don't include this file directly"
++#endif
++
++#ifdef CONFIG_PM
++
++/* changes to device_may_wakeup take effect on the next pm state change.
++ * by default, devices should wakeup if they can.
++ */
++static inline void device_init_wakeup(struct device *dev, int val)
++{
++ dev->power.can_wakeup = dev->power.should_wakeup = !!val;
++}
++
++static inline int device_can_wakeup(struct device *dev)
++{
++ return dev->power.can_wakeup;
++}
++
++static inline void device_set_wakeup_enable(struct device *dev, int val)
++{
++ dev->power.should_wakeup = !!val;
++}
++
++static inline int device_may_wakeup(struct device *dev)
++{
++ return dev->power.can_wakeup & dev->power.should_wakeup;
++}
++
++/*
++ * Platform hook to activate device wakeup capability, if that's not already
++ * handled by enable_irq_wake() etc.
++ * Returns zero on success, else negative errno
++ */
++extern int (*platform_enable_wakeup)(struct device *dev, int is_on);
++
++static inline int call_platform_enable_wakeup(struct device *dev, int is_on)
++{
++ if (platform_enable_wakeup)
++ return (*platform_enable_wakeup)(dev, is_on);
++ return 0;
++}
++
++#else /* !CONFIG_PM */
++
++/* For some reason the next two routines work even without CONFIG_PM */
++static inline void device_init_wakeup(struct device *dev, int val)
++{
++ dev->power.can_wakeup = !!val;
++}
++
++static inline int device_can_wakeup(struct device *dev)
++{
++ return dev->power.can_wakeup;
++}
++
++#define device_set_wakeup_enable(dev, val) do {} while (0)
++#define device_may_wakeup(dev) 0
++
++static inline int call_platform_enable_wakeup(struct device *dev, int is_on)
++{
++ return 0;
++}
++
++#endif /* !CONFIG_PM */
++
++#endif /* _LINUX_PM_WAKEUP_H */
+diff --git a/include/linux/prctl.h b/include/linux/prctl.h
+index 3800639..5c80b19 100644
+--- a/include/linux/prctl.h
++++ b/include/linux/prctl.h
+@@ -67,4 +67,10 @@
+ #define PR_CAPBSET_READ 23
+ #define PR_CAPBSET_DROP 24
+
++/* Get/set the process' ability to use the timestamp counter instruction */
++#define PR_GET_TSC 25
++#define PR_SET_TSC 26
++# define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */
++# define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */
++
+ #endif /* _LINUX_PRCTL_H */
+diff --git a/include/linux/quota.h b/include/linux/quota.h
+index 6e0393a..eb560d0 100644
+--- a/include/linux/quota.h
++++ b/include/linux/quota.h
+@@ -160,14 +160,18 @@ enum {
+
+
+ #ifdef __KERNEL__
+-#include <linux/spinlock.h>
+-#include <linux/rwsem.h>
++#include <linux/list.h>
+ #include <linux/mutex.h>
++#include <linux/rwsem.h>
++#include <linux/spinlock.h>
++#include <linux/wait.h>
+
+ #include <linux/dqblk_xfs.h>
+ #include <linux/dqblk_v1.h>
+ #include <linux/dqblk_v2.h>
+
++#include <asm/atomic.h>
++
+ extern spinlock_t dq_data_lock;
+
+ /* Maximal numbers of writes for quota operation (insert/delete/update)
+diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h
+index fbaeda7..8ab630b 100644
+--- a/include/linux/raid/md.h
++++ b/include/linux/raid/md.h
+@@ -19,7 +19,6 @@
+ #define _MD_H
+
+ #include <linux/blkdev.h>
+-#include <asm/semaphore.h>
+ #include <linux/major.h>
+ #include <linux/ioctl.h>
+ #include <linux/types.h>
+diff --git a/include/linux/raid_class.h b/include/linux/raid_class.h
+index d22ad39..6b537f1 100644
+--- a/include/linux/raid_class.h
++++ b/include/linux/raid_class.h
+@@ -53,20 +53,20 @@ struct raid_data {
+ #define DEFINE_RAID_ATTRIBUTE(type, attr) \
+ static inline void \
+ raid_set_##attr(struct raid_template *r, struct device *dev, type value) { \
+- struct class_device *cdev = \
++ struct device *device = \
+ attribute_container_find_class_device(&r->raid_attrs.ac, dev);\
+ struct raid_data *rd; \
+- BUG_ON(!cdev); \
+- rd = class_get_devdata(cdev); \
++ BUG_ON(!device); \
++ rd = dev_get_drvdata(device); \
+ rd->attr = value; \
+ } \
+ static inline type \
+ raid_get_##attr(struct raid_template *r, struct device *dev) { \
+- struct class_device *cdev = \
++ struct device *device = \
+ attribute_container_find_class_device(&r->raid_attrs.ac, dev);\
+ struct raid_data *rd; \
+- BUG_ON(!cdev); \
+- rd = class_get_devdata(cdev); \
++ BUG_ON(!device); \
++ rd = dev_get_drvdata(device); \
+ return rd->attr; \
+ }
+
+diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
+index b9e1740..44c81c7 100644
+--- a/include/linux/rtnetlink.h
++++ b/include/linux/rtnetlink.h
+@@ -740,13 +740,13 @@ extern void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change);
+ extern void rtnl_lock(void);
+ extern void rtnl_unlock(void);
+ extern int rtnl_trylock(void);
++extern int rtnl_is_locked(void);
+
+ extern void rtnetlink_init(void);
+ extern void __rtnl_unlock(void);
+
+ #define ASSERT_RTNL() do { \
+- if (unlikely(rtnl_trylock())) { \
+- rtnl_unlock(); \
++ if (unlikely(!rtnl_is_locked())) { \
+ printk(KERN_ERR "RTNL: assertion failed at %s (%d)\n", \
+ __FILE__, __LINE__); \
+ dump_stack(); \
+diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
+index a3d567a..71fc813 100644
+--- a/include/linux/scatterlist.h
++++ b/include/linux/scatterlist.h
+@@ -213,6 +213,11 @@ int __sg_alloc_table(struct sg_table *, unsigned int, unsigned int, gfp_t,
+ sg_alloc_fn *);
+ int sg_alloc_table(struct sg_table *, unsigned int, gfp_t);
+
++size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents,
++ void *buf, size_t buflen);
++size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
++ void *buf, size_t buflen);
++
+ /*
+ * Maximum number of entries that will be allocated in one piece, if
+ * a list larger than this is required then chaining will be utilized.
+diff --git a/include/linux/sched.h b/include/linux/sched.h
+index 6a1e7af..d0bd970 100644
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -61,7 +61,6 @@ struct sched_param {
+ #include <linux/mm_types.h>
+
+ #include <asm/system.h>
+-#include <asm/semaphore.h>
+ #include <asm/page.h>
+ #include <asm/ptrace.h>
+ #include <asm/cputime.h>
+@@ -704,6 +703,7 @@ enum cpu_idle_type {
+ #define SD_POWERSAVINGS_BALANCE 256 /* Balance for power savings */
+ #define SD_SHARE_PKG_RESOURCES 512 /* Domain members share cpu pkg resources */
+ #define SD_SERIALIZE 1024 /* Only a single load balancing instance */
++#define SD_WAKE_IDLE_FAR 2048 /* Gain latency sacrificing cache hit */
+
+ #define BALANCE_FOR_MC_POWER \
+ (sched_smt_power_savings ? SD_POWERSAVINGS_BALANCE : 0)
+@@ -733,12 +733,31 @@ struct sched_group {
+ u32 reciprocal_cpu_power;
+ };
+
++enum sched_domain_level {
++ SD_LV_NONE = 0,
++ SD_LV_SIBLING,
++ SD_LV_MC,
++ SD_LV_CPU,
++ SD_LV_NODE,
++ SD_LV_ALLNODES,
++ SD_LV_MAX
++};
++
++struct sched_domain_attr {
++ int relax_domain_level;
++};
++
++#define SD_ATTR_INIT (struct sched_domain_attr) { \
++ .relax_domain_level = -1, \
++}
++
+ struct sched_domain {
+ /* These fields must be setup */
+ struct sched_domain *parent; /* top domain must be null terminated */
+ struct sched_domain *child; /* bottom domain must be null terminated */
+ struct sched_group *groups; /* the balancing groups of the domain */
+ cpumask_t span; /* span of all CPUs in this domain */
++ int first_cpu; /* cache of the first cpu in this domain */
+ unsigned long min_interval; /* Minimum balance interval ms */
+ unsigned long max_interval; /* Maximum balance interval ms */
+ unsigned int busy_factor; /* less balancing by factor if busy */
+@@ -750,6 +769,7 @@ struct sched_domain {
+ unsigned int wake_idx;
+ unsigned int forkexec_idx;
+ int flags; /* See SD_* */
++ enum sched_domain_level level;
+
+ /* Runtime fields. */
+ unsigned long last_balance; /* init to jiffies. units in jiffies */
+@@ -789,7 +809,8 @@ struct sched_domain {
+ #endif
+ };
+
+-extern void partition_sched_domains(int ndoms_new, cpumask_t *doms_new);
++extern void partition_sched_domains(int ndoms_new, cpumask_t *doms_new,
++ struct sched_domain_attr *dattr_new);
+ extern int arch_reinit_sched_domains(void);
+
+ #endif /* CONFIG_SMP */
+@@ -889,7 +910,8 @@ struct sched_class {
+ void (*set_curr_task) (struct rq *rq);
+ void (*task_tick) (struct rq *rq, struct task_struct *p, int queued);
+ void (*task_new) (struct rq *rq, struct task_struct *p);
+- void (*set_cpus_allowed)(struct task_struct *p, cpumask_t *newmask);
++ void (*set_cpus_allowed)(struct task_struct *p,
++ const cpumask_t *newmask);
+
+ void (*join_domain)(struct rq *rq);
+ void (*leave_domain)(struct rq *rq);
+@@ -923,6 +945,7 @@ struct load_weight {
+ struct sched_entity {
+ struct load_weight load; /* for load-balancing */
+ struct rb_node run_node;
++ struct list_head group_node;
+ unsigned int on_rq;
+
+ u64 exec_start;
+@@ -982,6 +1005,7 @@ struct sched_rt_entity {
+ unsigned long timeout;
+ int nr_cpus_allowed;
+
++ struct sched_rt_entity *back;
+ #ifdef CONFIG_RT_GROUP_SCHED
+ struct sched_rt_entity *parent;
+ /* rq on which this entity is (to be) queued: */
+@@ -1502,15 +1526,21 @@ static inline void put_task_struct(struct task_struct *t)
+ #define used_math() tsk_used_math(current)
+
+ #ifdef CONFIG_SMP
+-extern int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask);
++extern int set_cpus_allowed_ptr(struct task_struct *p,
++ const cpumask_t *new_mask);
+ #else
+-static inline int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask)
++static inline int set_cpus_allowed_ptr(struct task_struct *p,
++ const cpumask_t *new_mask)
+ {
+- if (!cpu_isset(0, new_mask))
++ if (!cpu_isset(0, *new_mask))
+ return -EINVAL;
+ return 0;
+ }
+ #endif
++static inline int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask)
++{
++ return set_cpus_allowed_ptr(p, &new_mask);
++}
+
+ extern unsigned long long sched_clock(void);
+
+@@ -1551,7 +1581,6 @@ static inline void wake_up_idle_cpu(int cpu) { }
+ extern unsigned int sysctl_sched_latency;
+ extern unsigned int sysctl_sched_min_granularity;
+ extern unsigned int sysctl_sched_wakeup_granularity;
+-extern unsigned int sysctl_sched_batch_wakeup_granularity;
+ extern unsigned int sysctl_sched_child_runs_first;
+ extern unsigned int sysctl_sched_features;
+ extern unsigned int sysctl_sched_migration_cost;
+@@ -1564,6 +1593,10 @@ int sched_nr_latency_handler(struct ctl_table *table, int write,
+ extern unsigned int sysctl_sched_rt_period;
+ extern int sysctl_sched_rt_runtime;
+
++int sched_rt_handler(struct ctl_table *table, int write,
++ struct file *filp, void __user *buffer, size_t *lenp,
++ loff_t *ppos);
++
+ extern unsigned int sysctl_sched_compat_yield;
+
+ #ifdef CONFIG_RT_MUTEXES
+@@ -1893,6 +1926,8 @@ static inline unsigned long *end_of_stack(struct task_struct *p)
+
+ #endif
+
++extern void thread_info_cache_init(void);
++
+ /* set thread flags in other task's structures
+ * - see asm/thread_info.h for TIF_xxxx flags available
+ */
+@@ -2031,7 +2066,7 @@ static inline void arch_pick_mmap_layout(struct mm_struct *mm)
+ }
+ #endif
+
+-extern long sched_setaffinity(pid_t pid, cpumask_t new_mask);
++extern long sched_setaffinity(pid_t pid, const cpumask_t *new_mask);
+ extern long sched_getaffinity(pid_t pid, cpumask_t *mask);
+
+ extern int sched_mc_power_savings, sched_smt_power_savings;
+@@ -2041,8 +2076,11 @@ extern void normalize_rt_tasks(void);
+ #ifdef CONFIG_GROUP_SCHED
+
+ extern struct task_group init_task_group;
++#ifdef CONFIG_USER_SCHED
++extern struct task_group root_task_group;
++#endif
+
+-extern struct task_group *sched_create_group(void);
++extern struct task_group *sched_create_group(struct task_group *parent);
+ extern void sched_destroy_group(struct task_group *tg);
+ extern void sched_move_task(struct task_struct *tsk);
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+@@ -2053,6 +2091,9 @@ extern unsigned long sched_group_shares(struct task_group *tg);
+ extern int sched_group_set_rt_runtime(struct task_group *tg,
+ long rt_runtime_us);
+ extern long sched_group_rt_runtime(struct task_group *tg);
++extern int sched_group_set_rt_period(struct task_group *tg,
++ long rt_period_us);
++extern long sched_group_rt_period(struct task_group *tg);
+ #endif
+ #endif
+
+diff --git a/include/linux/security.h b/include/linux/security.h
+index c673dfd..53a3453 100644
+--- a/include/linux/security.h
++++ b/include/linux/security.h
+@@ -36,7 +36,11 @@
+
+ extern unsigned securebits;
+
++/* Maximum number of letters for an LSM name string */
++#define SECURITY_NAME_MAX 10
++
+ struct ctl_table;
++struct audit_krule;
+
+ /*
+ * These functions are in security/capability.c and are used
+@@ -136,6 +140,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ /**
+ * struct security_operations - main security structure
+ *
++ * Security module identifier.
++ *
++ * @name:
++ * A string that acts as a unique identifeir for the LSM with max number
++ * of characters = SECURITY_NAME_MAX.
++ *
+ * Security hooks for program execution operations.
+ *
+ * @bprm_alloc_security:
+@@ -220,7 +230,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * loopback/bind mount (@flags & MS_BIND), @dev_name identifies the
+ * pathname of the object being mounted.
+ * @dev_name contains the name for object being mounted.
+- * @nd contains the nameidata structure for mount point object.
++ * @path contains the path for mount point object.
+ * @type contains the filesystem type.
+ * @flags contains the mount flags.
+ * @data contains the filesystem-specific data.
+@@ -239,7 +249,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * Check permission before the device with superblock @mnt->sb is mounted
+ * on the mount point named by @nd.
+ * @mnt contains the vfsmount for device being mounted.
+- * @nd contains the nameidata object for the mount point.
++ * @path contains the path for the mount point.
+ * Return 0 if permission is granted.
+ * @sb_umount:
+ * Check permission before the @mnt file system is unmounted.
+@@ -268,16 +278,16 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * This hook is called any time a mount is successfully grafetd to
+ * the tree.
+ * @mnt contains the mounted filesystem.
+- * @mountpoint_nd contains the nameidata structure for the mount point.
++ * @mountpoint contains the path for the mount point.
+ * @sb_pivotroot:
+ * Check permission before pivoting the root filesystem.
+- * @old_nd contains the nameidata structure for the new location of the current root (put_old).
+- * @new_nd contains the nameidata structure for the new root (new_root).
++ * @old_path contains the path for the new location of the current root (put_old).
++ * @new_path contains the path for the new root (new_root).
+ * Return 0 if permission is granted.
+ * @sb_post_pivotroot:
+ * Update module state after a successful pivot.
+- * @old_nd contains the nameidata structure for the old root.
+- * @new_nd contains the nameidata structure for the new root.
++ * @old_path contains the path for the old root.
++ * @new_path contains the path for the new root.
+ * @sb_get_mnt_opts:
+ * Get the security relevant mount options used for a superblock
+ * @sb the superblock to get security mount options from
+@@ -468,6 +478,11 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * @dentry is the dentry being changed.
+ * Return 0 on success. If error is returned, then the operation
+ * causing setuid bit removal is failed.
++ * @inode_getsecid:
++ * Get the secid associated with the node.
++ * @inode contains a pointer to the inode.
++ * @secid contains a pointer to the location where result will be saved.
++ * In case of failure, @secid will be set to zero.
+ *
+ * Security hooks for file operations
+ *
+@@ -636,6 +651,8 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * @task_getsecid:
+ * Retrieve the security identifier of the process @p.
+ * @p contains the task_struct for the process and place is into @secid.
++ * In case of failure, @secid will be set to zero.
++ *
+ * @task_setgroups:
+ * Check permission before setting the supplementary group set of the
+ * current process.
+@@ -910,24 +927,24 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * Security hooks for XFRM operations.
+ *
+ * @xfrm_policy_alloc_security:
+- * @xp contains the xfrm_policy being added to Security Policy Database
+- * used by the XFRM system.
++ * @ctxp is a pointer to the xfrm_sec_ctx being added to Security Policy
++ * Database used by the XFRM system.
+ * @sec_ctx contains the security context information being provided by
+ * the user-level policy update program (e.g., setkey).
+ * Allocate a security structure to the xp->security field; the security
+ * field is initialized to NULL when the xfrm_policy is allocated.
+ * Return 0 if operation was successful (memory to allocate, legal context)
+ * @xfrm_policy_clone_security:
+- * @old contains an existing xfrm_policy in the SPD.
+- * @new contains a new xfrm_policy being cloned from old.
+- * Allocate a security structure to the new->security field
+- * that contains the information from the old->security field.
++ * @old_ctx contains an existing xfrm_sec_ctx.
++ * @new_ctxp contains a new xfrm_sec_ctx being cloned from old.
++ * Allocate a security structure in new_ctxp that contains the
++ * information from the old_ctx structure.
+ * Return 0 if operation was successful (memory to allocate).
+ * @xfrm_policy_free_security:
+- * @xp contains the xfrm_policy
++ * @ctx contains the xfrm_sec_ctx
+ * Deallocate xp->security.
+ * @xfrm_policy_delete_security:
+- * @xp contains the xfrm_policy.
++ * @ctx contains the xfrm_sec_ctx.
+ * Authorize deletion of xp->security.
+ * @xfrm_state_alloc_security:
+ * @x contains the xfrm_state being added to the Security Association
+@@ -947,7 +964,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * @x contains the xfrm_state.
+ * Authorize deletion of x->security.
+ * @xfrm_policy_lookup:
+- * @xp contains the xfrm_policy for which the access control is being
++ * @ctx contains the xfrm_sec_ctx for which the access control is being
+ * checked.
+ * @fl_secid contains the flow security label that is used to authorize
+ * access to the policy xp.
+@@ -997,6 +1014,11 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * @ipcp contains the kernel IPC permission structure
+ * @flag contains the desired (requested) permission set
+ * Return 0 if permission is granted.
++ * @ipc_getsecid:
++ * Get the secid associated with the ipc object.
++ * @ipcp contains the kernel IPC permission structure.
++ * @secid contains a pointer to the location where result will be saved.
++ * In case of failure, @secid will be set to zero.
+ *
+ * Security hooks for individual messages held in System V IPC message queues
+ * @msg_msg_alloc_security:
+@@ -1223,9 +1245,42 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+ * @secdata contains the security context.
+ * @seclen contains the length of the security context.
+ *
++ * Security hooks for Audit
++ *
++ * @audit_rule_init:
++ * Allocate and initialize an LSM audit rule structure.
++ * @field contains the required Audit action. Fields flags are defined in include/linux/audit.h
++ * @op contains the operator the rule uses.
++ * @rulestr contains the context where the rule will be applied to.
++ * @lsmrule contains a pointer to receive the result.
++ * Return 0 if @lsmrule has been successfully set,
++ * -EINVAL in case of an invalid rule.
++ *
++ * @audit_rule_known:
++ * Specifies whether given @rule contains any fields related to current LSM.
++ * @rule contains the audit rule of interest.
++ * Return 1 in case of relation found, 0 otherwise.
++ *
++ * @audit_rule_match:
++ * Determine if given @secid matches a rule previously approved
++ * by @audit_rule_known.
++ * @secid contains the security id in question.
++ * @field contains the field which relates to current LSM.
++ * @op contains the operator that will be used for matching.
++ * @rule points to the audit rule that will be checked against.
++ * @actx points to the audit context associated with the check.
++ * Return 1 if secid matches the rule, 0 if it does not, -ERRNO on failure.
++ *
++ * @audit_rule_free:
++ * Deallocate the LSM audit rule structure previously allocated by
++ * audit_rule_init.
++ * @rule contains the allocated rule
++ *
+ * This is the main security structure.
+ */
+ struct security_operations {
++ char name[SECURITY_NAME_MAX + 1];
++
+ int (*ptrace) (struct task_struct * parent, struct task_struct * child);
+ int (*capget) (struct task_struct * target,
+ kernel_cap_t * effective,
+@@ -1260,20 +1315,20 @@ struct security_operations {
+ int (*sb_copy_data)(char *orig, char *copy);
+ int (*sb_kern_mount) (struct super_block *sb, void *data);
+ int (*sb_statfs) (struct dentry *dentry);
+- int (*sb_mount) (char *dev_name, struct nameidata * nd,
++ int (*sb_mount) (char *dev_name, struct path *path,
+ char *type, unsigned long flags, void *data);
+- int (*sb_check_sb) (struct vfsmount * mnt, struct nameidata * nd);
++ int (*sb_check_sb) (struct vfsmount * mnt, struct path *path);
+ int (*sb_umount) (struct vfsmount * mnt, int flags);
+ void (*sb_umount_close) (struct vfsmount * mnt);
+ void (*sb_umount_busy) (struct vfsmount * mnt);
+ void (*sb_post_remount) (struct vfsmount * mnt,
+ unsigned long flags, void *data);
+ void (*sb_post_addmount) (struct vfsmount * mnt,
+- struct nameidata * mountpoint_nd);
+- int (*sb_pivotroot) (struct nameidata * old_nd,
+- struct nameidata * new_nd);
+- void (*sb_post_pivotroot) (struct nameidata * old_nd,
+- struct nameidata * new_nd);
++ struct path *mountpoint);
++ int (*sb_pivotroot) (struct path *old_path,
++ struct path *new_path);
++ void (*sb_post_pivotroot) (struct path *old_path,
++ struct path *new_path);
+ int (*sb_get_mnt_opts) (const struct super_block *sb,
+ struct security_mnt_opts *opts);
+ int (*sb_set_mnt_opts) (struct super_block *sb,
+@@ -1317,6 +1372,7 @@ struct security_operations {
+ int (*inode_getsecurity)(const struct inode *inode, const char *name, void **buffer, bool alloc);
+ int (*inode_setsecurity)(struct inode *inode, const char *name, const void *value, size_t size, int flags);
+ int (*inode_listsecurity)(struct inode *inode, char *buffer, size_t buffer_size);
++ void (*inode_getsecid)(const struct inode *inode, u32 *secid);
+
+ int (*file_permission) (struct file * file, int mask);
+ int (*file_alloc_security) (struct file * file);
+@@ -1369,6 +1425,7 @@ struct security_operations {
+ void (*task_to_inode)(struct task_struct *p, struct inode *inode);
+
+ int (*ipc_permission) (struct kern_ipc_perm * ipcp, short flag);
++ void (*ipc_getsecid) (struct kern_ipc_perm *ipcp, u32 *secid);
+
+ int (*msg_msg_alloc_security) (struct msg_msg * msg);
+ void (*msg_msg_free_security) (struct msg_msg * msg);
+@@ -1454,17 +1511,17 @@ struct security_operations {
+ #endif /* CONFIG_SECURITY_NETWORK */
+
+ #ifdef CONFIG_SECURITY_NETWORK_XFRM
+- int (*xfrm_policy_alloc_security) (struct xfrm_policy *xp,
++ int (*xfrm_policy_alloc_security) (struct xfrm_sec_ctx **ctxp,
+ struct xfrm_user_sec_ctx *sec_ctx);
+- int (*xfrm_policy_clone_security) (struct xfrm_policy *old, struct xfrm_policy *new);
+- void (*xfrm_policy_free_security) (struct xfrm_policy *xp);
+- int (*xfrm_policy_delete_security) (struct xfrm_policy *xp);
++ int (*xfrm_policy_clone_security) (struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctx);
++ void (*xfrm_policy_free_security) (struct xfrm_sec_ctx *ctx);
++ int (*xfrm_policy_delete_security) (struct xfrm_sec_ctx *ctx);
+ int (*xfrm_state_alloc_security) (struct xfrm_state *x,
+ struct xfrm_user_sec_ctx *sec_ctx,
+ u32 secid);
+ void (*xfrm_state_free_security) (struct xfrm_state *x);
+ int (*xfrm_state_delete_security) (struct xfrm_state *x);
+- int (*xfrm_policy_lookup)(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
++ int (*xfrm_policy_lookup)(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir);
+ int (*xfrm_state_pol_flow_match)(struct xfrm_state *x,
+ struct xfrm_policy *xp, struct flowi *fl);
+ int (*xfrm_decode_session)(struct sk_buff *skb, u32 *secid, int ckall);
+@@ -1480,10 +1537,18 @@ struct security_operations {
+
+ #endif /* CONFIG_KEYS */
+
++#ifdef CONFIG_AUDIT
++ int (*audit_rule_init)(u32 field, u32 op, char *rulestr, void **lsmrule);
++ int (*audit_rule_known)(struct audit_krule *krule);
++ int (*audit_rule_match)(u32 secid, u32 field, u32 op, void *lsmrule,
++ struct audit_context *actx);
++ void (*audit_rule_free)(void *lsmrule);
++#endif /* CONFIG_AUDIT */
+ };
+
+ /* prototypes */
+ extern int security_init (void);
++extern int security_module_enable(struct security_operations *ops);
+ extern int register_security (struct security_operations *ops);
+ extern int mod_reg_security (const char *name, struct security_operations *ops);
+ extern struct dentry *securityfs_create_file(const char *name, mode_t mode,
+@@ -1528,16 +1593,16 @@ void security_sb_free(struct super_block *sb);
+ int security_sb_copy_data(char *orig, char *copy);
+ int security_sb_kern_mount(struct super_block *sb, void *data);
+ int security_sb_statfs(struct dentry *dentry);
+-int security_sb_mount(char *dev_name, struct nameidata *nd,
++int security_sb_mount(char *dev_name, struct path *path,
+ char *type, unsigned long flags, void *data);
+-int security_sb_check_sb(struct vfsmount *mnt, struct nameidata *nd);
++int security_sb_check_sb(struct vfsmount *mnt, struct path *path);
+ int security_sb_umount(struct vfsmount *mnt, int flags);
+ void security_sb_umount_close(struct vfsmount *mnt);
+ void security_sb_umount_busy(struct vfsmount *mnt);
+ void security_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *data);
+-void security_sb_post_addmount(struct vfsmount *mnt, struct nameidata *mountpoint_nd);
+-int security_sb_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd);
+-void security_sb_post_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd);
++void security_sb_post_addmount(struct vfsmount *mnt, struct path *mountpoint);
++int security_sb_pivotroot(struct path *old_path, struct path *new_path);
++void security_sb_post_pivotroot(struct path *old_path, struct path *new_path);
+ int security_sb_get_mnt_opts(const struct super_block *sb,
+ struct security_mnt_opts *opts);
+ int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts);
+@@ -1578,6 +1643,7 @@ int security_inode_killpriv(struct dentry *dentry);
+ int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc);
+ int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags);
+ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size);
++void security_inode_getsecid(const struct inode *inode, u32 *secid);
+ int security_file_permission(struct file *file, int mask);
+ int security_file_alloc(struct file *file);
+ void security_file_free(struct file *file);
+@@ -1622,6 +1688,7 @@ int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
+ void security_task_reparent_to_init(struct task_struct *p);
+ void security_task_to_inode(struct task_struct *p, struct inode *inode);
+ int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag);
++void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid);
+ int security_msg_msg_alloc(struct msg_msg *msg);
+ void security_msg_msg_free(struct msg_msg *msg);
+ int security_msg_queue_alloc(struct msg_queue *msq);
+@@ -1805,7 +1872,7 @@ static inline int security_sb_statfs (struct dentry *dentry)
+ return 0;
+ }
+
+-static inline int security_sb_mount (char *dev_name, struct nameidata *nd,
++static inline int security_sb_mount (char *dev_name, struct path *path,
+ char *type, unsigned long flags,
+ void *data)
+ {
+@@ -1813,7 +1880,7 @@ static inline int security_sb_mount (char *dev_name, struct nameidata *nd,
+ }
+
+ static inline int security_sb_check_sb (struct vfsmount *mnt,
+- struct nameidata *nd)
++ struct path *path)
+ {
+ return 0;
+ }
+@@ -1834,17 +1901,17 @@ static inline void security_sb_post_remount (struct vfsmount *mnt,
+ { }
+
+ static inline void security_sb_post_addmount (struct vfsmount *mnt,
+- struct nameidata *mountpoint_nd)
++ struct path *mountpoint)
+ { }
+
+-static inline int security_sb_pivotroot (struct nameidata *old_nd,
+- struct nameidata *new_nd)
++static inline int security_sb_pivotroot (struct path *old_path,
++ struct path *new_path)
+ {
+ return 0;
+ }
+
+-static inline void security_sb_post_pivotroot (struct nameidata *old_nd,
+- struct nameidata *new_nd)
++static inline void security_sb_post_pivotroot (struct path *old_path,
++ struct path *new_path)
+ { }
+ static inline int security_sb_get_mnt_opts(const struct super_block *sb,
+ struct security_mnt_opts *opts)
+@@ -2022,6 +2089,11 @@ static inline int security_inode_listsecurity(struct inode *inode, char *buffer,
+ return 0;
+ }
+
++static inline void security_inode_getsecid(const struct inode *inode, u32 *secid)
++{
++ *secid = 0;
++}
++
+ static inline int security_file_permission (struct file *file, int mask)
+ {
+ return 0;
+@@ -2137,7 +2209,9 @@ static inline int security_task_getsid (struct task_struct *p)
+ }
+
+ static inline void security_task_getsecid (struct task_struct *p, u32 *secid)
+-{ }
++{
++ *secid = 0;
++}
+
+ static inline int security_task_setgroups (struct group_info *group_info)
+ {
+@@ -2216,6 +2290,11 @@ static inline int security_ipc_permission (struct kern_ipc_perm *ipcp,
+ return 0;
+ }
+
++static inline void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
++{
++ *secid = 0;
++}
++
+ static inline int security_msg_msg_alloc (struct msg_msg * msg)
+ {
+ return 0;
+@@ -2562,16 +2641,16 @@ static inline void security_inet_conn_established(struct sock *sk,
+
+ #ifdef CONFIG_SECURITY_NETWORK_XFRM
+
+-int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx);
+-int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new);
+-void security_xfrm_policy_free(struct xfrm_policy *xp);
+-int security_xfrm_policy_delete(struct xfrm_policy *xp);
++int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx);
++int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctxp);
++void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx);
++int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx);
+ int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx);
+ int security_xfrm_state_alloc_acquire(struct xfrm_state *x,
+ struct xfrm_sec_ctx *polsec, u32 secid);
+ int security_xfrm_state_delete(struct xfrm_state *x);
+ void security_xfrm_state_free(struct xfrm_state *x);
+-int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
++int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir);
+ int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
+ struct xfrm_policy *xp, struct flowi *fl);
+ int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid);
+@@ -2579,21 +2658,21 @@ void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl);
+
+ #else /* CONFIG_SECURITY_NETWORK_XFRM */
+
+-static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx)
++static inline int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx)
+ {
+ return 0;
+ }
+
+-static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
++static inline int security_xfrm_policy_clone(struct xfrm_sec_ctx *old, struct xfrm_sec_ctx **new_ctxp)
+ {
+ return 0;
+ }
+
+-static inline void security_xfrm_policy_free(struct xfrm_policy *xp)
++static inline void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
+ {
+ }
+
+-static inline int security_xfrm_policy_delete(struct xfrm_policy *xp)
++static inline int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
+ {
+ return 0;
+ }
+@@ -2619,7 +2698,7 @@ static inline int security_xfrm_state_delete(struct xfrm_state *x)
+ return 0;
+ }
+
+-static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir)
++static inline int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
+ {
+ return 0;
+ }
+@@ -2672,5 +2751,38 @@ static inline int security_key_permission(key_ref_t key_ref,
+ #endif
+ #endif /* CONFIG_KEYS */
+
++#ifdef CONFIG_AUDIT
++#ifdef CONFIG_SECURITY
++int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule);
++int security_audit_rule_known(struct audit_krule *krule);
++int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
++ struct audit_context *actx);
++void security_audit_rule_free(void *lsmrule);
++
++#else
++
++static inline int security_audit_rule_init(u32 field, u32 op, char *rulestr,
++ void **lsmrule)
++{
++ return 0;
++}
++
++static inline int security_audit_rule_known(struct audit_krule *krule)
++{
++ return 0;
++}
++
++static inline int security_audit_rule_match(u32 secid, u32 field, u32 op,
++ void *lsmrule, struct audit_context *actx)
++{
++ return 0;
++}
++
++static inline void security_audit_rule_free(void *lsmrule)
++{ }
++
++#endif /* CONFIG_SECURITY */
++#endif /* CONFIG_AUDIT */
++
+ #endif /* ! __LINUX_SECURITY_H */
+
+diff --git a/include/linux/selinux.h b/include/linux/selinux.h
+index 8c2cc4c..20f965d 100644
+--- a/include/linux/selinux.h
++++ b/include/linux/selinux.h
+@@ -16,99 +16,11 @@
+
+ struct selinux_audit_rule;
+ struct audit_context;
+-struct inode;
+ struct kern_ipc_perm;
+
+ #ifdef CONFIG_SECURITY_SELINUX
+
+ /**
+- * selinux_audit_rule_init - alloc/init an selinux audit rule structure.
+- * @field: the field this rule refers to
+- * @op: the operater the rule uses
+- * @rulestr: the text "target" of the rule
+- * @rule: pointer to the new rule structure returned via this
+- *
+- * Returns 0 if successful, -errno if not. On success, the rule structure
+- * will be allocated internally. The caller must free this structure with
+- * selinux_audit_rule_free() after use.
+- */
+-int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
+- struct selinux_audit_rule **rule);
+-
+-/**
+- * selinux_audit_rule_free - free an selinux audit rule structure.
+- * @rule: pointer to the audit rule to be freed
+- *
+- * This will free all memory associated with the given rule.
+- * If @rule is NULL, no operation is performed.
+- */
+-void selinux_audit_rule_free(struct selinux_audit_rule *rule);
+-
+-/**
+- * selinux_audit_rule_match - determine if a context ID matches a rule.
+- * @sid: the context ID to check
+- * @field: the field this rule refers to
+- * @op: the operater the rule uses
+- * @rule: pointer to the audit rule to check against
+- * @actx: the audit context (can be NULL) associated with the check
+- *
+- * Returns 1 if the context id matches the rule, 0 if it does not, and
+- * -errno on failure.
+- */
+-int selinux_audit_rule_match(u32 sid, u32 field, u32 op,
+- struct selinux_audit_rule *rule,
+- struct audit_context *actx);
+-
+-/**
+- * selinux_audit_set_callback - set the callback for policy reloads.
+- * @callback: the function to call when the policy is reloaded
+- *
+- * This sets the function callback function that will update the rules
+- * upon policy reloads. This callback should rebuild all existing rules
+- * using selinux_audit_rule_init().
+- */
+-void selinux_audit_set_callback(int (*callback)(void));
+-
+-/**
+- * selinux_sid_to_string - map a security context ID to a string
+- * @sid: security context ID to be converted.
+- * @ctx: address of context string to be returned
+- * @ctxlen: length of returned context string.
+- *
+- * Returns 0 if successful, -errno if not. On success, the context
+- * string will be allocated internally, and the caller must call
+- * kfree() on it after use.
+- */
+-int selinux_sid_to_string(u32 sid, char **ctx, u32 *ctxlen);
+-
+-/**
+- * selinux_get_inode_sid - get the inode's security context ID
+- * @inode: inode structure to get the sid from.
+- * @sid: pointer to security context ID to be filled in.
+- *
+- * Returns nothing
+- */
+-void selinux_get_inode_sid(const struct inode *inode, u32 *sid);
+-
+-/**
+- * selinux_get_ipc_sid - get the ipc security context ID
+- * @ipcp: ipc structure to get the sid from.
+- * @sid: pointer to security context ID to be filled in.
+- *
+- * Returns nothing
+- */
+-void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid);
+-
+-/**
+- * selinux_get_task_sid - return the SID of task
+- * @tsk: the task whose SID will be returned
+- * @sid: pointer to security context ID to be filled in.
+- *
+- * Returns nothing
+- */
+-void selinux_get_task_sid(struct task_struct *tsk, u32 *sid);
+-
+-/**
+ * selinux_string_to_sid - map a security context string to a security ID
+ * @str: the security context string to be mapped
+ * @sid: ID value returned via this.
+@@ -151,52 +63,6 @@ void selinux_secmark_refcount_inc(void);
+ void selinux_secmark_refcount_dec(void);
+ #else
+
+-static inline int selinux_audit_rule_init(u32 field, u32 op,
+- char *rulestr,
+- struct selinux_audit_rule **rule)
+-{
+- return -EOPNOTSUPP;
+-}
+-
+-static inline void selinux_audit_rule_free(struct selinux_audit_rule *rule)
+-{
+- return;
+-}
+-
+-static inline int selinux_audit_rule_match(u32 sid, u32 field, u32 op,
+- struct selinux_audit_rule *rule,
+- struct audit_context *actx)
+-{
+- return 0;
+-}
+-
+-static inline void selinux_audit_set_callback(int (*callback)(void))
+-{
+- return;
+-}
+-
+-static inline int selinux_sid_to_string(u32 sid, char **ctx, u32 *ctxlen)
+-{
+- *ctx = NULL;
+- *ctxlen = 0;
+- return 0;
+-}
+-
+-static inline void selinux_get_inode_sid(const struct inode *inode, u32 *sid)
+-{
+- *sid = 0;
+-}
+-
+-static inline void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid)
+-{
+- *sid = 0;
+-}
+-
+-static inline void selinux_get_task_sid(struct task_struct *tsk, u32 *sid)
+-{
+- *sid = 0;
+-}
+-
+ static inline int selinux_string_to_sid(const char *str, u32 *sid)
+ {
+ *sid = 0;
+diff --git a/include/linux/semaphore.h b/include/linux/semaphore.h
+new file mode 100644
+index 0000000..9cae64b
+--- /dev/null
++++ b/include/linux/semaphore.h
+@@ -0,0 +1,51 @@
++/*
++ * Copyright (c) 2008 Intel Corporation
++ * Author: Matthew Wilcox <willy at linux.intel.com>
++ *
++ * Distributed under the terms of the GNU GPL, version 2
++ *
++ * Please see kernel/semaphore.c for documentation of these functions
++ */
++#ifndef __LINUX_SEMAPHORE_H
++#define __LINUX_SEMAPHORE_H
++
++#include <linux/list.h>
++#include <linux/spinlock.h>
++
++/* Please don't access any members of this structure directly */
++struct semaphore {
++ spinlock_t lock;
++ unsigned int count;
++ struct list_head wait_list;
++};
++
++#define __SEMAPHORE_INITIALIZER(name, n) \
++{ \
++ .lock = __SPIN_LOCK_UNLOCKED((name).lock), \
++ .count = n, \
++ .wait_list = LIST_HEAD_INIT((name).wait_list), \
++}
++
++#define __DECLARE_SEMAPHORE_GENERIC(name, count) \
++ struct semaphore name = __SEMAPHORE_INITIALIZER(name, count)
++
++#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name, 1)
++
++static inline void sema_init(struct semaphore *sem, int val)
++{
++ static struct lock_class_key __key;
++ *sem = (struct semaphore) __SEMAPHORE_INITIALIZER(*sem, val);
++ lockdep_init_map(&sem->lock.dep_map, "semaphore->lock", &__key, 0);
++}
++
++#define init_MUTEX(sem) sema_init(sem, 1)
++#define init_MUTEX_LOCKED(sem) sema_init(sem, 0)
++
++extern void down(struct semaphore *sem);
++extern int __must_check down_interruptible(struct semaphore *sem);
++extern int __must_check down_killable(struct semaphore *sem);
++extern int __must_check down_trylock(struct semaphore *sem);
++extern int __must_check down_timeout(struct semaphore *sem, long jiffies);
++extern void up(struct semaphore *sem);
++
++#endif /* __LINUX_SEMAPHORE_H */
+diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h
+index 67c2563..5b5369c 100644
+--- a/include/linux/seq_file.h
++++ b/include/linux/seq_file.h
+@@ -10,6 +10,7 @@ struct seq_operations;
+ struct file;
+ struct path;
+ struct inode;
++struct dentry;
+
+ struct seq_file {
+ char *buf;
+@@ -30,6 +31,8 @@ struct seq_operations {
+ int (*show) (struct seq_file *m, void *v);
+ };
+
++#define SEQ_SKIP 1
++
+ int seq_open(struct file *, const struct seq_operations *);
+ ssize_t seq_read(struct file *, char __user *, size_t, loff_t *);
+ loff_t seq_lseek(struct file *, loff_t, int);
+@@ -42,6 +45,9 @@ int seq_printf(struct seq_file *, const char *, ...)
+ __attribute__ ((format (printf,2,3)));
+
+ int seq_path(struct seq_file *, struct path *, char *);
++int seq_dentry(struct seq_file *, struct dentry *, char *);
++int seq_path_root(struct seq_file *m, struct path *path, struct path *root,
++ char *esc);
+
+ int single_open(struct file *, int (*)(struct seq_file *, void *), void *);
+ int single_release(struct inode *, struct file *);
+@@ -62,18 +68,5 @@ extern struct list_head *seq_list_start_head(struct list_head *head,
+ extern struct list_head *seq_list_next(void *v, struct list_head *head,
+ loff_t *ppos);
+
+-struct net;
+-struct seq_net_private {
+- struct net *net;
+-};
+-
+-int seq_open_net(struct inode *, struct file *,
+- const struct seq_operations *, int);
+-int seq_release_net(struct inode *, struct file *);
+-static inline struct net *seq_file_net(struct seq_file *seq)
+-{
+- return ((struct seq_net_private *)seq->private)->net;
+-}
+-
+ #endif
+ #endif
+diff --git a/include/linux/seq_file_net.h b/include/linux/seq_file_net.h
+new file mode 100644
+index 0000000..4ac5254
+--- /dev/null
++++ b/include/linux/seq_file_net.h
+@@ -0,0 +1,27 @@
++#ifndef __SEQ_FILE_NET_H__
++#define __SEQ_FILE_NET_H__
++
++#include <linux/seq_file.h>
++
++struct net;
++extern struct net init_net;
++
++struct seq_net_private {
++#ifdef CONFIG_NET_NS
++ struct net *net;
++#endif
++};
++
++int seq_open_net(struct inode *, struct file *,
++ const struct seq_operations *, int);
++int seq_release_net(struct inode *, struct file *);
++static inline struct net *seq_file_net(struct seq_file *seq)
++{
++#ifdef CONFIG_NET_NS
++ return ((struct seq_net_private *)seq->private)->net;
++#else
++ return &init_net;
++#endif
++}
++
++#endif
+diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
+index 26e4925..632205c 100644
+--- a/include/linux/seqlock.h
++++ b/include/linux/seqlock.h
+@@ -85,23 +85,29 @@ static inline int write_tryseqlock(seqlock_t *sl)
+ /* Start of read calculation -- fetch last complete writer token */
+ static __always_inline unsigned read_seqbegin(const seqlock_t *sl)
+ {
+- unsigned ret = sl->sequence;
++ unsigned ret;
++
++repeat:
++ ret = sl->sequence;
+ smp_rmb();
++ if (unlikely(ret & 1)) {
++ cpu_relax();
++ goto repeat;
++ }
++
+ return ret;
+ }
+
+-/* Test if reader processed invalid data.
+- * If initial values is odd,
+- * then writer had already started when section was entered
+- * If sequence value changed
+- * then writer changed data while in section
+- *
+- * Using xor saves one conditional branch.
++/*
++ * Test if reader processed invalid data.
++ *
++ * If sequence value changed then writer changed data while in section.
+ */
+-static __always_inline int read_seqretry(const seqlock_t *sl, unsigned iv)
++static __always_inline int read_seqretry(const seqlock_t *sl, unsigned start)
+ {
+ smp_rmb();
+- return (iv & 1) | (sl->sequence ^ iv);
++
++ return (sl->sequence != start);
+ }
+
+
+@@ -122,20 +128,26 @@ typedef struct seqcount {
+ /* Start of read using pointer to a sequence counter only. */
+ static inline unsigned read_seqcount_begin(const seqcount_t *s)
+ {
+- unsigned ret = s->sequence;
++ unsigned ret;
++
++repeat:
++ ret = s->sequence;
+ smp_rmb();
++ if (unlikely(ret & 1)) {
++ cpu_relax();
++ goto repeat;
++ }
+ return ret;
+ }
+
+-/* Test if reader processed invalid data.
+- * Equivalent to: iv is odd or sequence number has changed.
+- * (iv & 1) || (*s != iv)
+- * Using xor saves one conditional branch.
++/*
++ * Test if reader processed invalid data because sequence number has changed.
+ */
+-static inline int read_seqcount_retry(const seqcount_t *s, unsigned iv)
++static inline int read_seqcount_retry(const seqcount_t *s, unsigned start)
+ {
+ smp_rmb();
+- return (iv & 1) | (s->sequence ^ iv);
++
++ return s->sequence != start;
+ }
+
+
+diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
+index 289942f..7cb094a 100644
+--- a/include/linux/serial_core.h
++++ b/include/linux/serial_core.h
+@@ -213,6 +213,10 @@ struct uart_ops {
+ void (*config_port)(struct uart_port *, int);
+ int (*verify_port)(struct uart_port *, struct serial_struct *);
+ int (*ioctl)(struct uart_port *, unsigned int, unsigned long);
++#ifdef CONFIG_CONSOLE_POLL
++ void (*poll_put_char)(struct uart_port *, unsigned char);
++ int (*poll_get_char)(struct uart_port *);
++#endif
+ };
+
+ #define UART_CONFIG_TYPE (1 << 0)
+diff --git a/include/linux/serio.h b/include/linux/serio.h
+index 9f38250..95674d9 100644
+--- a/include/linux/serio.h
++++ b/include/linux/serio.h
+@@ -211,5 +211,6 @@ static inline void serio_unpin_driver(struct serio *serio)
+ #define SERIO_TOUCHWIN 0x33
+ #define SERIO_TAOSEVM 0x34
+ #define SERIO_FUJITSU 0x35
++#define SERIO_ZHENHUA 0x36
+
+ #endif
+diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
+index bbd8d00..299ec4b 100644
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -242,6 +242,7 @@ typedef unsigned char *sk_buff_data_t;
+ * @queue_mapping: Queue mapping for multiqueue devices
+ * @tc_index: Traffic control index
+ * @tc_verd: traffic control verdict
++ * @ndisc_nodetype: router type (from link layer)
+ * @dma_cookie: a cookie to one of several possible DMA operations
+ * done by skb DMA functions
+ * @secmark: security marking
+@@ -256,7 +257,10 @@ struct sk_buff {
+ ktime_t tstamp;
+ struct net_device *dev;
+
+- struct dst_entry *dst;
++ union {
++ struct dst_entry *dst;
++ struct rtable *rtable;
++ };
+ struct sec_path *sp;
+
+ /*
+@@ -310,7 +314,10 @@ struct sk_buff {
+ __u16 tc_verd; /* traffic control verdict */
+ #endif
+ #endif
+- /* 2 byte hole */
++#ifdef CONFIG_IPV6_NDISC_NODETYPE
++ __u8 ndisc_nodetype:2;
++#endif
++ /* 14 bit hole */
+
+ #ifdef CONFIG_NET_DMA
+ dma_cookie_t dma_cookie;
+@@ -657,11 +664,21 @@ static inline void skb_queue_head_init_class(struct sk_buff_head *list,
+ }
+
+ /*
+- * Insert an sk_buff at the start of a list.
++ * Insert an sk_buff on a list.
+ *
+ * The "__skb_xxxx()" functions are the non-atomic ones that
+ * can only be called with interrupts disabled.
+ */
++extern void skb_insert(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list);
++static inline void __skb_insert(struct sk_buff *newsk,
++ struct sk_buff *prev, struct sk_buff *next,
++ struct sk_buff_head *list)
++{
++ newsk->next = next;
++ newsk->prev = prev;
++ next->prev = prev->next = newsk;
++ list->qlen++;
++}
+
+ /**
+ * __skb_queue_after - queue a buffer at the list head
+@@ -678,13 +695,17 @@ static inline void __skb_queue_after(struct sk_buff_head *list,
+ struct sk_buff *prev,
+ struct sk_buff *newsk)
+ {
+- struct sk_buff *next;
+- list->qlen++;
++ __skb_insert(newsk, prev, prev->next, list);
++}
+
+- next = prev->next;
+- newsk->next = next;
+- newsk->prev = prev;
+- next->prev = prev->next = newsk;
++extern void skb_append(struct sk_buff *old, struct sk_buff *newsk,
++ struct sk_buff_head *list);
++
++static inline void __skb_queue_before(struct sk_buff_head *list,
++ struct sk_buff *next,
++ struct sk_buff *newsk)
++{
++ __skb_insert(newsk, next->prev, next, list);
+ }
+
+ /**
+@@ -718,66 +739,7 @@ extern void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk);
+ static inline void __skb_queue_tail(struct sk_buff_head *list,
+ struct sk_buff *newsk)
+ {
+- struct sk_buff *prev, *next;
+-
+- list->qlen++;
+- next = (struct sk_buff *)list;
+- prev = next->prev;
+- newsk->next = next;
+- newsk->prev = prev;
+- next->prev = prev->next = newsk;
+-}
+-
+-
+-/**
+- * __skb_dequeue - remove from the head of the queue
+- * @list: list to dequeue from
+- *
+- * Remove the head of the list. This function does not take any locks
+- * so must be used with appropriate locks held only. The head item is
+- * returned or %NULL if the list is empty.
+- */
+-extern struct sk_buff *skb_dequeue(struct sk_buff_head *list);
+-static inline struct sk_buff *__skb_dequeue(struct sk_buff_head *list)
+-{
+- struct sk_buff *next, *prev, *result;
+-
+- prev = (struct sk_buff *) list;
+- next = prev->next;
+- result = NULL;
+- if (next != prev) {
+- result = next;
+- next = next->next;
+- list->qlen--;
+- next->prev = prev;
+- prev->next = next;
+- result->next = result->prev = NULL;
+- }
+- return result;
+-}
+-
+-
+-/*
+- * Insert a packet on a list.
+- */
+-extern void skb_insert(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list);
+-static inline void __skb_insert(struct sk_buff *newsk,
+- struct sk_buff *prev, struct sk_buff *next,
+- struct sk_buff_head *list)
+-{
+- newsk->next = next;
+- newsk->prev = prev;
+- next->prev = prev->next = newsk;
+- list->qlen++;
+-}
+-
+-/*
+- * Place a packet after a given packet in a list.
+- */
+-extern void skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list);
+-static inline void __skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list)
+-{
+- __skb_insert(newsk, old, old->next, list);
++ __skb_queue_before(list, (struct sk_buff *)list, newsk);
+ }
+
+ /*
+@@ -797,8 +759,22 @@ static inline void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list)
+ prev->next = next;
+ }
+
+-
+-/* XXX: more streamlined implementation */
++/**
++ * __skb_dequeue - remove from the head of the queue
++ * @list: list to dequeue from
++ *
++ * Remove the head of the list. This function does not take any locks
++ * so must be used with appropriate locks held only. The head item is
++ * returned or %NULL if the list is empty.
++ */
++extern struct sk_buff *skb_dequeue(struct sk_buff_head *list);
++static inline struct sk_buff *__skb_dequeue(struct sk_buff_head *list)
++{
++ struct sk_buff *skb = skb_peek(list);
++ if (skb)
++ __skb_unlink(skb, list);
++ return skb;
++}
+
+ /**
+ * __skb_dequeue_tail - remove from the tail of the queue
+@@ -889,6 +865,7 @@ static inline void skb_set_tail_pointer(struct sk_buff *skb, const int offset)
+ /*
+ * Add data to an sk_buff
+ */
++extern unsigned char *skb_put(struct sk_buff *skb, unsigned int len);
+ static inline unsigned char *__skb_put(struct sk_buff *skb, unsigned int len)
+ {
+ unsigned char *tmp = skb_tail_pointer(skb);
+@@ -898,26 +875,7 @@ static inline unsigned char *__skb_put(struct sk_buff *skb, unsigned int len)
+ return tmp;
+ }
+
+-/**
+- * skb_put - add data to a buffer
+- * @skb: buffer to use
+- * @len: amount of data to add
+- *
+- * This function extends the used data area of the buffer. If this would
+- * exceed the total buffer size the kernel will panic. A pointer to the
+- * first byte of the extra data is returned.
+- */
+-static inline unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
+-{
+- unsigned char *tmp = skb_tail_pointer(skb);
+- SKB_LINEAR_ASSERT(skb);
+- skb->tail += len;
+- skb->len += len;
+- if (unlikely(skb->tail > skb->end))
+- skb_over_panic(skb, len, current_text_addr());
+- return tmp;
+-}
+-
++extern unsigned char *skb_push(struct sk_buff *skb, unsigned int len);
+ static inline unsigned char *__skb_push(struct sk_buff *skb, unsigned int len)
+ {
+ skb->data -= len;
+@@ -925,24 +883,7 @@ static inline unsigned char *__skb_push(struct sk_buff *skb, unsigned int len)
+ return skb->data;
+ }
+
+-/**
+- * skb_push - add data to the start of a buffer
+- * @skb: buffer to use
+- * @len: amount of data to add
+- *
+- * This function extends the used data area of the buffer at the buffer
+- * start. If this would exceed the total buffer headroom the kernel will
+- * panic. A pointer to the first byte of the extra data is returned.
+- */
+-static inline unsigned char *skb_push(struct sk_buff *skb, unsigned int len)
+-{
+- skb->data -= len;
+- skb->len += len;
+- if (unlikely(skb->data<skb->head))
+- skb_under_panic(skb, len, current_text_addr());
+- return skb->data;
+-}
+-
++extern unsigned char *skb_pull(struct sk_buff *skb, unsigned int len);
+ static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len)
+ {
+ skb->len -= len;
+@@ -950,21 +891,6 @@ static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len)
+ return skb->data += len;
+ }
+
+-/**
+- * skb_pull - remove data from the start of a buffer
+- * @skb: buffer to use
+- * @len: amount of data to remove
+- *
+- * This function removes data from the start of a buffer, returning
+- * the memory to the headroom. A pointer to the next data in the buffer
+- * is returned. Once the data has been pulled future pushes will overwrite
+- * the old data.
+- */
+-static inline unsigned char *skb_pull(struct sk_buff *skb, unsigned int len)
+-{
+- return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len);
+-}
+-
+ extern unsigned char *__pskb_pull_tail(struct sk_buff *skb, int delta);
+
+ static inline unsigned char *__pskb_pull(struct sk_buff *skb, unsigned int len)
+@@ -1205,21 +1131,7 @@ static inline void __skb_trim(struct sk_buff *skb, unsigned int len)
+ skb_set_tail_pointer(skb, len);
+ }
+
+-/**
+- * skb_trim - remove end from a buffer
+- * @skb: buffer to alter
+- * @len: new length
+- *
+- * Cut the length of a buffer down by removing data from the tail. If
+- * the buffer is already under the length specified it is not modified.
+- * The skb must be linear.
+- */
+-static inline void skb_trim(struct sk_buff *skb, unsigned int len)
+-{
+- if (skb->len > len)
+- __skb_trim(skb, len);
+-}
+-
++extern void skb_trim(struct sk_buff *skb, unsigned int len);
+
+ static inline int __pskb_trim(struct sk_buff *skb, unsigned int len)
+ {
+@@ -1302,22 +1214,7 @@ static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
+ return skb;
+ }
+
+-/**
+- * dev_alloc_skb - allocate an skbuff for receiving
+- * @length: length to allocate
+- *
+- * Allocate a new &sk_buff and assign it a usage count of one. The
+- * buffer has unspecified headroom built in. Users should allocate
+- * the headroom they think they need without accounting for the
+- * built in space. The built in space is used for optimisations.
+- *
+- * %NULL is returned if there is no free memory. Although this function
+- * allocates memory it can be called from an interrupt.
+- */
+-static inline struct sk_buff *dev_alloc_skb(unsigned int length)
+-{
+- return __dev_alloc_skb(length, GFP_ATOMIC);
+-}
++extern struct sk_buff *dev_alloc_skb(unsigned int length);
+
+ extern struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
+ unsigned int length, gfp_t gfp_mask);
+diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
+index b00c1c7..79d59c9 100644
+--- a/include/linux/slub_def.h
++++ b/include/linux/slub_def.h
+@@ -45,9 +45,9 @@ struct kmem_cache_cpu {
+ struct kmem_cache_node {
+ spinlock_t list_lock; /* Protect partial list and nr_partial */
+ unsigned long nr_partial;
+- atomic_long_t nr_slabs;
+ struct list_head partial;
+ #ifdef CONFIG_SLUB_DEBUG
++ atomic_long_t nr_slabs;
+ struct list_head full;
+ #endif
+ };
+diff --git a/include/linux/smc91x.h b/include/linux/smc91x.h
+new file mode 100644
+index 0000000..8e0556b
+--- /dev/null
++++ b/include/linux/smc91x.h
+@@ -0,0 +1,13 @@
++#ifndef __SMC91X_H__
++#define __SMC91X_H__
++
++#define SMC91X_USE_8BIT (1 << 0)
++#define SMC91X_USE_16BIT (1 << 1)
++#define SMC91X_USE_32BIT (1 << 2)
++
++struct smc91x_platdata {
++ unsigned long flags;
++ unsigned long irq_flags; /* IRQF_... */
++};
++
++#endif /* __SMC91X_H__ */
+diff --git a/include/linux/spi/ads7846.h b/include/linux/spi/ads7846.h
+index 334d314..daf7440 100644
+--- a/include/linux/spi/ads7846.h
++++ b/include/linux/spi/ads7846.h
+@@ -14,7 +14,8 @@ enum ads7846_filter {
+ struct ads7846_platform_data {
+ u16 model; /* 7843, 7845, 7846. */
+ u16 vref_delay_usecs; /* 0 for external vref; etc */
+- int keep_vref_on:1; /* set to keep vref on for differential
++ u16 vref_mv; /* external vref value, milliVolts */
++ bool keep_vref_on; /* set to keep vref on for differential
+ * measurements as well */
+
+ /* Settling time of the analog signals; a function of Vcc and the
+diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
+index 1129ee0..d311a09 100644
+--- a/include/linux/spinlock.h
++++ b/include/linux/spinlock.h
+@@ -296,43 +296,6 @@ do { \
+ })
+
+ /*
+- * Locks two spinlocks l1 and l2.
+- * l1_first indicates if spinlock l1 should be taken first.
+- */
+-static inline void double_spin_lock(spinlock_t *l1, spinlock_t *l2,
+- bool l1_first)
+- __acquires(l1)
+- __acquires(l2)
+-{
+- if (l1_first) {
+- spin_lock(l1);
+- spin_lock(l2);
+- } else {
+- spin_lock(l2);
+- spin_lock(l1);
+- }
+-}
+-
+-/*
+- * Unlocks two spinlocks l1 and l2.
+- * l1_taken_first indicates if spinlock l1 was taken first and therefore
+- * should be released after spinlock l2.
+- */
+-static inline void double_spin_unlock(spinlock_t *l1, spinlock_t *l2,
+- bool l1_taken_first)
+- __releases(l1)
+- __releases(l2)
+-{
+- if (l1_taken_first) {
+- spin_unlock(l2);
+- spin_unlock(l1);
+- } else {
+- spin_unlock(l1);
+- spin_unlock(l2);
+- }
+-}
+-
+-/*
+ * Pull the atomic_t declaration:
+ * (asm-mips/atomic.h needs above definitions)
+ */
+diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
+index db53def..50dfd0d 100644
+--- a/include/linux/ssb/ssb.h
++++ b/include/linux/ssb/ssb.h
+@@ -72,10 +72,18 @@ struct ssb_device;
+ /* Lowlevel read/write operations on the device MMIO.
+ * Internal, don't use that outside of ssb. */
+ struct ssb_bus_ops {
++ u8 (*read8)(struct ssb_device *dev, u16 offset);
+ u16 (*read16)(struct ssb_device *dev, u16 offset);
+ u32 (*read32)(struct ssb_device *dev, u16 offset);
++ void (*write8)(struct ssb_device *dev, u16 offset, u8 value);
+ void (*write16)(struct ssb_device *dev, u16 offset, u16 value);
+ void (*write32)(struct ssb_device *dev, u16 offset, u32 value);
++#ifdef CONFIG_SSB_BLOCKIO
++ void (*block_read)(struct ssb_device *dev, void *buffer,
++ size_t count, u16 offset, u8 reg_width);
++ void (*block_write)(struct ssb_device *dev, const void *buffer,
++ size_t count, u16 offset, u8 reg_width);
++#endif
+ };
+
+
+@@ -247,9 +255,9 @@ struct ssb_bus {
+ /* Pointer to the PCMCIA device (only if bustype == SSB_BUSTYPE_PCMCIA). */
+ struct pcmcia_device *host_pcmcia;
+
+-#ifdef CONFIG_SSB_PCIHOST
++#ifdef CONFIG_SSB_SPROM
+ /* Mutex to protect the SPROM writing. */
+- struct mutex pci_sprom_mutex;
++ struct mutex sprom_mutex;
+ #endif
+
+ /* ID information about the Chip. */
+@@ -262,9 +270,6 @@ struct ssb_bus {
+ struct ssb_device devices[SSB_MAX_NR_CORES];
+ u8 nr_devices;
+
+- /* Reference count. Number of suspended devices. */
+- u8 suspend_cnt;
+-
+ /* Software ID number for this bus. */
+ unsigned int busnumber;
+
+@@ -336,6 +341,13 @@ extern int ssb_bus_pcmciabus_register(struct ssb_bus *bus,
+
+ extern void ssb_bus_unregister(struct ssb_bus *bus);
+
++/* Suspend a SSB bus.
++ * Call this from the parent bus suspend routine. */
++extern int ssb_bus_suspend(struct ssb_bus *bus);
++/* Resume a SSB bus.
++ * Call this from the parent bus resume routine. */
++extern int ssb_bus_resume(struct ssb_bus *bus);
++
+ extern u32 ssb_clockspeed(struct ssb_bus *bus);
+
+ /* Is the device enabled in hardware? */
+@@ -348,6 +360,10 @@ void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags);
+
+
+ /* Device MMIO register read/write functions. */
++static inline u8 ssb_read8(struct ssb_device *dev, u16 offset)
++{
++ return dev->ops->read8(dev, offset);
++}
+ static inline u16 ssb_read16(struct ssb_device *dev, u16 offset)
+ {
+ return dev->ops->read16(dev, offset);
+@@ -356,6 +372,10 @@ static inline u32 ssb_read32(struct ssb_device *dev, u16 offset)
+ {
+ return dev->ops->read32(dev, offset);
+ }
++static inline void ssb_write8(struct ssb_device *dev, u16 offset, u8 value)
++{
++ dev->ops->write8(dev, offset, value);
++}
+ static inline void ssb_write16(struct ssb_device *dev, u16 offset, u16 value)
+ {
+ dev->ops->write16(dev, offset, value);
+@@ -364,6 +384,19 @@ static inline void ssb_write32(struct ssb_device *dev, u16 offset, u32 value)
+ {
+ dev->ops->write32(dev, offset, value);
+ }
++#ifdef CONFIG_SSB_BLOCKIO
++static inline void ssb_block_read(struct ssb_device *dev, void *buffer,
++ size_t count, u16 offset, u8 reg_width)
++{
++ dev->ops->block_read(dev, buffer, count, offset, reg_width);
++}
++
++static inline void ssb_block_write(struct ssb_device *dev, const void *buffer,
++ size_t count, u16 offset, u8 reg_width)
++{
++ dev->ops->block_write(dev, buffer, count, offset, reg_width);
++}
++#endif /* CONFIG_SSB_BLOCKIO */
+
+
+ /* Translation (routing) bits that need to be ORed to DMA
+@@ -416,5 +449,12 @@ extern int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl);
+ extern u32 ssb_admatch_base(u32 adm);
+ extern u32 ssb_admatch_size(u32 adm);
+
++/* PCI device mapping and fixup routines.
++ * Called from the architecture pcibios init code.
++ * These are only available on SSB_EMBEDDED configurations. */
++#ifdef CONFIG_SSB_EMBEDDED
++int ssb_pcibios_plat_dev_init(struct pci_dev *dev);
++int ssb_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
++#endif /* CONFIG_SSB_EMBEDDED */
+
+ #endif /* LINUX_SSB_H_ */
+diff --git a/include/linux/ssb/ssb_driver_chipcommon.h b/include/linux/ssb/ssb_driver_chipcommon.h
+index 536851b..7d7e03d 100644
+--- a/include/linux/ssb/ssb_driver_chipcommon.h
++++ b/include/linux/ssb/ssb_driver_chipcommon.h
+@@ -367,8 +367,7 @@ static inline bool ssb_chipco_available(struct ssb_chipcommon *cc)
+
+ extern void ssb_chipcommon_init(struct ssb_chipcommon *cc);
+
+-#include <linux/pm.h>
+-extern void ssb_chipco_suspend(struct ssb_chipcommon *cc, pm_message_t state);
++extern void ssb_chipco_suspend(struct ssb_chipcommon *cc);
+ extern void ssb_chipco_resume(struct ssb_chipcommon *cc);
+
+ extern void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc,
+@@ -390,6 +389,10 @@ extern void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc,
+ extern void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc,
+ u32 ticks);
+
++void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value);
++
++u32 ssb_chipco_irq_status(struct ssb_chipcommon *cc, u32 mask);
++
+ /* Chipcommon GPIO pin access. */
+ u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask);
+ u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value);
+diff --git a/include/linux/ssb/ssb_driver_gige.h b/include/linux/ssb/ssb_driver_gige.h
+new file mode 100644
+index 0000000..01fbdf5
+--- /dev/null
++++ b/include/linux/ssb/ssb_driver_gige.h
+@@ -0,0 +1,174 @@
++#ifndef LINUX_SSB_DRIVER_GIGE_H_
++#define LINUX_SSB_DRIVER_GIGE_H_
++
++#include <linux/ssb/ssb.h>
++#include <linux/pci.h>
++#include <linux/spinlock.h>
++
++
++#ifdef CONFIG_SSB_DRIVER_GIGE
++
++
++#define SSB_GIGE_PCIIO 0x0000 /* PCI I/O Registers (1024 bytes) */
++#define SSB_GIGE_RESERVED 0x0400 /* Reserved (1024 bytes) */
++#define SSB_GIGE_PCICFG 0x0800 /* PCI config space (256 bytes) */
++#define SSB_GIGE_SHIM_FLUSHSTAT 0x0C00 /* PCI to OCP: Flush status control (32bit) */
++#define SSB_GIGE_SHIM_FLUSHRDA 0x0C04 /* PCI to OCP: Flush read address (32bit) */
++#define SSB_GIGE_SHIM_FLUSHTO 0x0C08 /* PCI to OCP: Flush timeout counter (32bit) */
++#define SSB_GIGE_SHIM_BARRIER 0x0C0C /* PCI to OCP: Barrier register (32bit) */
++#define SSB_GIGE_SHIM_MAOCPSI 0x0C10 /* PCI to OCP: MaocpSI Control (32bit) */
++#define SSB_GIGE_SHIM_SIOCPMA 0x0C14 /* PCI to OCP: SiocpMa Control (32bit) */
++
++/* TM Status High flags */
++#define SSB_GIGE_TMSHIGH_RGMII 0x00010000 /* Have an RGMII PHY-bus */
++/* TM Status Low flags */
++#define SSB_GIGE_TMSLOW_TXBYPASS 0x00080000 /* TX bypass (no delay) */
++#define SSB_GIGE_TMSLOW_RXBYPASS 0x00100000 /* RX bypass (no delay) */
++#define SSB_GIGE_TMSLOW_DLLEN 0x01000000 /* Enable DLL controls */
++
++/* Boardflags (low) */
++#define SSB_GIGE_BFL_ROBOSWITCH 0x0010
++
++
++#define SSB_GIGE_MEM_RES_NAME "SSB Broadcom 47xx GigE memory"
++#define SSB_GIGE_IO_RES_NAME "SSB Broadcom 47xx GigE I/O"
++
++struct ssb_gige {
++ struct ssb_device *dev;
++
++ spinlock_t lock;
++
++ /* True, if the device has an RGMII bus.
++ * False, if the device has a GMII bus. */
++ bool has_rgmii;
++
++ /* The PCI controller device. */
++ struct pci_controller pci_controller;
++ struct pci_ops pci_ops;
++ struct resource mem_resource;
++ struct resource io_resource;
++};
++
++/* Check whether a PCI device is a SSB Gigabit Ethernet core. */
++extern bool pdev_is_ssb_gige_core(struct pci_dev *pdev);
++
++/* Convert a pci_dev pointer to a ssb_gige pointer. */
++static inline struct ssb_gige * pdev_to_ssb_gige(struct pci_dev *pdev)
++{
++ if (!pdev_is_ssb_gige_core(pdev))
++ return NULL;
++ return container_of(pdev->bus->ops, struct ssb_gige, pci_ops);
++}
++
++/* Returns whether the PHY is connected by an RGMII bus. */
++static inline bool ssb_gige_is_rgmii(struct pci_dev *pdev)
++{
++ struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
++ return (dev ? dev->has_rgmii : 0);
++}
++
++/* Returns whether we have a Roboswitch. */
++static inline bool ssb_gige_have_roboswitch(struct pci_dev *pdev)
++{
++ struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
++ if (dev)
++ return !!(dev->dev->bus->sprom.boardflags_lo &
++ SSB_GIGE_BFL_ROBOSWITCH);
++ return 0;
++}
++
++/* Returns whether we can only do one DMA at once. */
++static inline bool ssb_gige_one_dma_at_once(struct pci_dev *pdev)
++{
++ struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
++ if (dev)
++ return ((dev->dev->bus->chip_id == 0x4785) &&
++ (dev->dev->bus->chip_rev < 2));
++ return 0;
++}
++
++/* Returns whether we must flush posted writes. */
++static inline bool ssb_gige_must_flush_posted_writes(struct pci_dev *pdev)
++{
++ struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
++ if (dev)
++ return (dev->dev->bus->chip_id == 0x4785);
++ return 0;
++}
++
++extern char * nvram_get(const char *name);
++/* Get the device MAC address */
++static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
++{
++#ifdef CONFIG_BCM947XX
++ char *res = nvram_get("et0macaddr");
++ if (res)
++ memcpy(macaddr, res, 6);
++#endif
++}
++
++extern int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,
++ struct pci_dev *pdev);
++extern int ssb_gige_map_irq(struct ssb_device *sdev,
++ const struct pci_dev *pdev);
++
++/* The GigE driver is not a standalone module, because we don't have support
++ * for unregistering the driver. So we could not unload the module anyway. */
++extern int ssb_gige_init(void);
++static inline void ssb_gige_exit(void)
++{
++ /* Currently we can not unregister the GigE driver,
++ * because we can not unregister the PCI bridge. */
++ BUG();
++}
++
++
++#else /* CONFIG_SSB_DRIVER_GIGE */
++/* Gigabit Ethernet driver disabled */
++
++
++static inline int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,
++ struct pci_dev *pdev)
++{
++ return -ENOSYS;
++}
++static inline int ssb_gige_map_irq(struct ssb_device *sdev,
++ const struct pci_dev *pdev)
++{
++ return -ENOSYS;
++}
++static inline int ssb_gige_init(void)
++{
++ return 0;
++}
++static inline void ssb_gige_exit(void)
++{
++}
++
++static inline bool pdev_is_ssb_gige_core(struct pci_dev *pdev)
++{
++ return 0;
++}
++static inline struct ssb_gige * pdev_to_ssb_gige(struct pci_dev *pdev)
++{
++ return NULL;
++}
++static inline bool ssb_gige_is_rgmii(struct pci_dev *pdev)
++{
++ return 0;
++}
++static inline bool ssb_gige_have_roboswitch(struct pci_dev *pdev)
++{
++ return 0;
++}
++static inline bool ssb_gige_one_dma_at_once(struct pci_dev *pdev)
++{
++ return 0;
++}
++static inline bool ssb_gige_must_flush_posted_writes(struct pci_dev *pdev)
++{
++ return 0;
++}
++
++#endif /* CONFIG_SSB_DRIVER_GIGE */
++#endif /* LINUX_SSB_DRIVER_GIGE_H_ */
+diff --git a/include/linux/ssb/ssb_driver_pci.h b/include/linux/ssb/ssb_driver_pci.h
+index 5e25bac..41e330e 100644
+--- a/include/linux/ssb/ssb_driver_pci.h
++++ b/include/linux/ssb/ssb_driver_pci.h
+@@ -1,6 +1,11 @@
+ #ifndef LINUX_SSB_PCICORE_H_
+ #define LINUX_SSB_PCICORE_H_
+
++#include <linux/types.h>
++
++struct pci_dev;
++
++
+ #ifdef CONFIG_SSB_DRIVER_PCICORE
+
+ /* PCI core registers. */
+@@ -88,6 +93,9 @@ extern void ssb_pcicore_init(struct ssb_pcicore *pc);
+ extern int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc,
+ struct ssb_device *dev);
+
++int ssb_pcicore_plat_dev_init(struct pci_dev *d);
++int ssb_pcicore_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
++
+
+ #else /* CONFIG_SSB_DRIVER_PCICORE */
+
+@@ -107,5 +115,16 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc,
+ return 0;
+ }
+
++static inline
++int ssb_pcicore_plat_dev_init(struct pci_dev *d)
++{
++ return -ENODEV;
++}
++static inline
++int ssb_pcicore_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
++{
++ return -ENODEV;
++}
++
+ #endif /* CONFIG_SSB_DRIVER_PCICORE */
+ #endif /* LINUX_SSB_PCICORE_H_ */
+diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
+index 7a69ca3..3f63218 100644
+--- a/include/linux/sunrpc/auth.h
++++ b/include/linux/sunrpc/auth.h
+@@ -26,6 +26,7 @@ struct auth_cred {
+ uid_t uid;
+ gid_t gid;
+ struct group_info *group_info;
++ unsigned char machine_cred : 1;
+ };
+
+ /*
+@@ -59,8 +60,8 @@ struct rpc_cred {
+ /*
+ * Client authentication handle
+ */
+-#define RPC_CREDCACHE_NR 8
+-#define RPC_CREDCACHE_MASK (RPC_CREDCACHE_NR - 1)
++#define RPC_CREDCACHE_HASHBITS 4
++#define RPC_CREDCACHE_NR (1 << RPC_CREDCACHE_HASHBITS)
+ struct rpc_cred_cache {
+ struct hlist_head hashtable[RPC_CREDCACHE_NR];
+ spinlock_t lock;
+@@ -89,7 +90,6 @@ struct rpc_auth {
+
+ /* Flags for rpcauth_lookupcred() */
+ #define RPCAUTH_LOOKUP_NEW 0x01 /* Accept an uninitialised cred */
+-#define RPCAUTH_LOOKUP_ROOTCREDS 0x02 /* This really ought to go! */
+
+ /*
+ * Client authentication ops
+@@ -97,9 +97,7 @@ struct rpc_auth {
+ struct rpc_authops {
+ struct module *owner;
+ rpc_authflavor_t au_flavor; /* flavor (RPC_AUTH_*) */
+-#ifdef RPC_DEBUG
+ char * au_name;
+-#endif
+ struct rpc_auth * (*create)(struct rpc_clnt *, rpc_authflavor_t);
+ void (*destroy)(struct rpc_auth *);
+
+@@ -113,6 +111,7 @@ struct rpc_credops {
+ void (*crdestroy)(struct rpc_cred *);
+
+ int (*crmatch)(struct auth_cred *, struct rpc_cred *, int);
++ void (*crbind)(struct rpc_task *, struct rpc_cred *);
+ __be32 * (*crmarshal)(struct rpc_task *, __be32 *);
+ int (*crrefresh)(struct rpc_task *);
+ __be32 * (*crvalidate)(struct rpc_task *, __be32 *);
+@@ -126,9 +125,13 @@ extern const struct rpc_authops authunix_ops;
+ extern const struct rpc_authops authnull_ops;
+
+ void __init rpc_init_authunix(void);
++void __init rpc_init_generic_auth(void);
+ void __init rpcauth_init_module(void);
+ void __exit rpcauth_remove_module(void);
++void __exit rpc_destroy_generic_auth(void);
+
++struct rpc_cred * rpc_lookup_cred(void);
++struct rpc_cred * rpc_lookup_machine_cred(void);
+ int rpcauth_register(const struct rpc_authops *);
+ int rpcauth_unregister(const struct rpc_authops *);
+ struct rpc_auth * rpcauth_create(rpc_authflavor_t, struct rpc_clnt *);
+@@ -136,8 +139,8 @@ void rpcauth_release(struct rpc_auth *);
+ struct rpc_cred * rpcauth_lookup_credcache(struct rpc_auth *, struct auth_cred *, int);
+ void rpcauth_init_cred(struct rpc_cred *, const struct auth_cred *, struct rpc_auth *, const struct rpc_credops *);
+ struct rpc_cred * rpcauth_lookupcred(struct rpc_auth *, int);
+-struct rpc_cred * rpcauth_bindcred(struct rpc_task *);
+-void rpcauth_holdcred(struct rpc_task *);
++void rpcauth_bindcred(struct rpc_task *, struct rpc_cred *, int);
++void rpcauth_generic_bind_cred(struct rpc_task *, struct rpc_cred *);
+ void put_rpccred(struct rpc_cred *);
+ void rpcauth_unbindcred(struct rpc_task *);
+ __be32 * rpcauth_marshcred(struct rpc_task *, __be32 *);
+diff --git a/include/linux/sunrpc/auth_gss.h b/include/linux/sunrpc/auth_gss.h
+index 67658e1..fec6899 100644
+--- a/include/linux/sunrpc/auth_gss.h
++++ b/include/linux/sunrpc/auth_gss.h
+@@ -84,6 +84,7 @@ struct gss_cred {
+ enum rpc_gss_svc gc_service;
+ struct gss_cl_ctx *gc_ctx;
+ struct gss_upcall_msg *gc_upcall;
++ unsigned char gc_machine_cred : 1;
+ };
+
+ #endif /* __KERNEL__ */
+diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
+index 03547d6..2d8b211 100644
+--- a/include/linux/sunrpc/cache.h
++++ b/include/linux/sunrpc/cache.h
+@@ -120,7 +120,6 @@ struct cache_deferred_req {
+ struct list_head hash; /* on hash chain */
+ struct list_head recent; /* on fifo */
+ struct cache_head *item; /* cache item we wait on */
+- time_t recv_time;
+ void *owner; /* we might need to discard all defered requests
+ * owned by someone */
+ void (*revisit)(struct cache_deferred_req *req,
+diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
+index 129a86e..6fff7f8 100644
+--- a/include/linux/sunrpc/clnt.h
++++ b/include/linux/sunrpc/clnt.h
+@@ -127,11 +127,12 @@ int rpcb_getport_sync(struct sockaddr_in *, u32, u32, int);
+ void rpcb_getport_async(struct rpc_task *);
+
+ void rpc_call_start(struct rpc_task *);
+-int rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg,
+- int flags, const struct rpc_call_ops *tk_ops,
++int rpc_call_async(struct rpc_clnt *clnt,
++ const struct rpc_message *msg, int flags,
++ const struct rpc_call_ops *tk_ops,
+ void *calldata);
+-int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg,
+- int flags);
++int rpc_call_sync(struct rpc_clnt *clnt,
++ const struct rpc_message *msg, int flags);
+ struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred,
+ int flags);
+ void rpc_restart_call(struct rpc_task *);
+diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
+index 5a4b1e0..a10f1fb 100644
+--- a/include/linux/sunrpc/gss_krb5.h
++++ b/include/linux/sunrpc/gss_krb5.h
+@@ -70,8 +70,6 @@ enum seal_alg {
+ SEAL_ALG_DES3KD = 0x0002
+ };
+
+-#define KRB5_CKSUM_LENGTH 8
+-
+ #define CKSUMTYPE_CRC32 0x0001
+ #define CKSUMTYPE_RSA_MD4 0x0002
+ #define CKSUMTYPE_RSA_MD4_DES 0x0003
+@@ -150,9 +148,9 @@ gss_decrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *inbuf,
+ s32
+ krb5_make_seq_num(struct crypto_blkcipher *key,
+ int direction,
+- s32 seqnum, unsigned char *cksum, unsigned char *buf);
++ u32 seqnum, unsigned char *cksum, unsigned char *buf);
+
+ s32
+ krb5_get_seq_num(struct crypto_blkcipher *key,
+ unsigned char *cksum,
+- unsigned char *buf, int *direction, s32 * seqnum);
++ unsigned char *buf, int *direction, u32 *seqnum);
+diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
+index f689f02..d1a5c8c 100644
+--- a/include/linux/sunrpc/sched.h
++++ b/include/linux/sunrpc/sched.h
+@@ -11,7 +11,6 @@
+
+ #include <linux/timer.h>
+ #include <linux/sunrpc/types.h>
+-#include <linux/rcupdate.h>
+ #include <linux/spinlock.h>
+ #include <linux/wait.h>
+ #include <linux/workqueue.h>
+@@ -33,7 +32,8 @@ struct rpc_wait_queue;
+ struct rpc_wait {
+ struct list_head list; /* wait queue links */
+ struct list_head links; /* Links to related tasks */
+- struct rpc_wait_queue * rpc_waitq; /* RPC wait queue we're on */
++ struct list_head timer_list; /* Timer list */
++ unsigned long expires;
+ };
+
+ /*
+@@ -57,33 +57,25 @@ struct rpc_task {
+ __u8 tk_cred_retry;
+
+ /*
+- * timeout_fn to be executed by timer bottom half
+ * callback to be executed after waking up
+ * action next procedure for async tasks
+ * tk_ops caller callbacks
+ */
+- void (*tk_timeout_fn)(struct rpc_task *);
+ void (*tk_callback)(struct rpc_task *);
+ void (*tk_action)(struct rpc_task *);
+ const struct rpc_call_ops *tk_ops;
+ void * tk_calldata;
+
+- /*
+- * tk_timer is used for async processing by the RPC scheduling
+- * primitives. You should not access this directly unless
+- * you have a pathological interest in kernel oopses.
+- */
+- struct timer_list tk_timer; /* kernel timer */
+ unsigned long tk_timeout; /* timeout for rpc_sleep() */
+ unsigned short tk_flags; /* misc flags */
+ unsigned long tk_runstate; /* Task run status */
+ struct workqueue_struct *tk_workqueue; /* Normally rpciod, but could
+ * be any workqueue
+ */
++ struct rpc_wait_queue *tk_waitqueue; /* RPC wait queue we're on */
+ union {
+ struct work_struct tk_work; /* Async task work queue */
+ struct rpc_wait tk_wait; /* RPC wait */
+- struct rcu_head tk_rcu; /* for task deletion */
+ } u;
+
+ unsigned short tk_timeouts; /* maj timeouts */
+@@ -123,6 +115,7 @@ struct rpc_task_setup {
+ const struct rpc_message *rpc_message;
+ const struct rpc_call_ops *callback_ops;
+ void *callback_data;
++ struct workqueue_struct *workqueue;
+ unsigned short flags;
+ signed char priority;
+ };
+@@ -147,9 +140,7 @@ struct rpc_task_setup {
+
+ #define RPC_TASK_RUNNING 0
+ #define RPC_TASK_QUEUED 1
+-#define RPC_TASK_WAKEUP 2
+-#define RPC_TASK_HAS_TIMER 3
+-#define RPC_TASK_ACTIVE 4
++#define RPC_TASK_ACTIVE 2
+
+ #define RPC_IS_RUNNING(t) test_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)
+ #define rpc_set_running(t) set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)
+@@ -171,15 +162,6 @@ struct rpc_task_setup {
+ smp_mb__after_clear_bit(); \
+ } while (0)
+
+-#define rpc_start_wakeup(t) \
+- (test_and_set_bit(RPC_TASK_WAKEUP, &(t)->tk_runstate) == 0)
+-#define rpc_finish_wakeup(t) \
+- do { \
+- smp_mb__before_clear_bit(); \
+- clear_bit(RPC_TASK_WAKEUP, &(t)->tk_runstate); \
+- smp_mb__after_clear_bit(); \
+- } while (0)
+-
+ #define RPC_IS_ACTIVATED(t) test_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate)
+
+ /*
+@@ -192,6 +174,12 @@ struct rpc_task_setup {
+ #define RPC_PRIORITY_HIGH (1)
+ #define RPC_NR_PRIORITY (1 + RPC_PRIORITY_HIGH - RPC_PRIORITY_LOW)
+
++struct rpc_timer {
++ struct timer_list timer;
++ struct list_head list;
++ unsigned long expires;
++};
++
+ /*
+ * RPC synchronization objects
+ */
+@@ -204,6 +192,7 @@ struct rpc_wait_queue {
+ unsigned char count; /* # task groups remaining serviced so far */
+ unsigned char nr; /* # tasks remaining for cookie */
+ unsigned short qlen; /* total # tasks waiting in queue */
++ struct rpc_timer timer_list;
+ #ifdef RPC_DEBUG
+ const char * name;
+ #endif
+@@ -229,9 +218,11 @@ void rpc_killall_tasks(struct rpc_clnt *);
+ void rpc_execute(struct rpc_task *);
+ void rpc_init_priority_wait_queue(struct rpc_wait_queue *, const char *);
+ void rpc_init_wait_queue(struct rpc_wait_queue *, const char *);
++void rpc_destroy_wait_queue(struct rpc_wait_queue *);
+ void rpc_sleep_on(struct rpc_wait_queue *, struct rpc_task *,
+- rpc_action action, rpc_action timer);
+-void rpc_wake_up_task(struct rpc_task *);
++ rpc_action action);
++void rpc_wake_up_queued_task(struct rpc_wait_queue *,
++ struct rpc_task *);
+ void rpc_wake_up(struct rpc_wait_queue *);
+ struct rpc_task *rpc_wake_up_next(struct rpc_wait_queue *);
+ void rpc_wake_up_status(struct rpc_wait_queue *, int);
+diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
+index 64c9755..4b54c5f 100644
+--- a/include/linux/sunrpc/svc.h
++++ b/include/linux/sunrpc/svc.h
+@@ -386,7 +386,6 @@ struct svc_serv * svc_create(struct svc_program *, unsigned int,
+ void (*shutdown)(struct svc_serv*));
+ struct svc_rqst *svc_prepare_thread(struct svc_serv *serv,
+ struct svc_pool *pool);
+-int svc_create_thread(svc_thread_fn, struct svc_serv *);
+ void svc_exit_thread(struct svc_rqst *);
+ struct svc_serv * svc_create_pooled(struct svc_program *, unsigned int,
+ void (*shutdown)(struct svc_serv*),
+diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h
+index 22e1ef8..d39dbdc 100644
+--- a/include/linux/sunrpc/svcauth.h
++++ b/include/linux/sunrpc/svcauth.h
+@@ -24,6 +24,7 @@ struct svc_cred {
+ };
+
+ struct svc_rqst; /* forward decl */
++struct in6_addr;
+
+ /* Authentication is done in the context of a domain.
+ *
+@@ -120,10 +121,10 @@ extern void svc_auth_unregister(rpc_authflavor_t flavor);
+
+ extern struct auth_domain *unix_domain_find(char *name);
+ extern void auth_domain_put(struct auth_domain *item);
+-extern int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom);
++extern int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom);
+ extern struct auth_domain *auth_domain_lookup(char *name, struct auth_domain *new);
+ extern struct auth_domain *auth_domain_find(char *name);
+-extern struct auth_domain *auth_unix_lookup(struct in_addr addr);
++extern struct auth_domain *auth_unix_lookup(struct in6_addr *addr);
+ extern int auth_unix_forget_old(struct auth_domain *dom);
+ extern void svcauth_unix_purge(void);
+ extern void svcauth_unix_info_release(void *);
+diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h
+index 206f092..8cff696 100644
+--- a/include/linux/sunrpc/svcsock.h
++++ b/include/linux/sunrpc/svcsock.h
+@@ -26,8 +26,8 @@ struct svc_sock {
+ void (*sk_owspace)(struct sock *);
+
+ /* private TCP part */
+- int sk_reclen; /* length of record */
+- int sk_tcplen; /* current read length */
++ u32 sk_reclen; /* length of record */
++ u32 sk_tcplen; /* current read length */
+ };
+
+ /*
+diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
+index b3ff9a8..4d80a11 100644
+--- a/include/linux/sunrpc/xprt.h
++++ b/include/linux/sunrpc/xprt.h
+@@ -86,6 +86,10 @@ struct rpc_rqst {
+ unsigned long rq_majortimeo; /* major timeout alarm */
+ unsigned long rq_timeout; /* Current timeout value */
+ unsigned int rq_retries; /* # of retries */
++ unsigned int rq_connect_cookie;
++ /* A cookie used to track the
++ state of the transport
++ connection */
+
+ /*
+ * Partial send handling
+@@ -152,6 +156,9 @@ struct rpc_xprt {
+ unsigned long connect_timeout,
+ bind_timeout,
+ reestablish_timeout;
++ unsigned int connect_cookie; /* A cookie that gets bumped
++ every time the transport
++ is reconnected */
+
+ /*
+ * Disconnection of idle transports
+@@ -232,7 +239,7 @@ int xprt_unregister_transport(struct xprt_class *type);
+ void xprt_set_retrans_timeout_def(struct rpc_task *task);
+ void xprt_set_retrans_timeout_rtt(struct rpc_task *task);
+ void xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status);
+-void xprt_wait_for_buffer_space(struct rpc_task *task);
++void xprt_wait_for_buffer_space(struct rpc_task *task, rpc_action action);
+ void xprt_write_space(struct rpc_xprt *xprt);
+ void xprt_update_rtt(struct rpc_task *task);
+ void xprt_adjust_cwnd(struct rpc_task *task, int result);
+@@ -241,6 +248,7 @@ void xprt_complete_rqst(struct rpc_task *task, int copied);
+ void xprt_release_rqst_cong(struct rpc_task *task);
+ void xprt_disconnect_done(struct rpc_xprt *xprt);
+ void xprt_force_disconnect(struct rpc_xprt *xprt);
++void xprt_conditional_disconnect(struct rpc_xprt *xprt, unsigned int cookie);
+
+ /*
+ * Reserved bit positions in xprt->state
+diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
+index 4c2577b..8df6d13 100644
+--- a/include/linux/syscalls.h
++++ b/include/linux/syscalls.h
+@@ -60,7 +60,6 @@ struct getcpu_cache;
+ #include <linux/capability.h>
+ #include <linux/list.h>
+ #include <linux/sem.h>
+-#include <asm/semaphore.h>
+ #include <asm/siginfo.h>
+ #include <asm/signal.h>
+ #include <linux/quota.h>
+diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h
+index f752e73..f2767bc 100644
+--- a/include/linux/sysdev.h
++++ b/include/linux/sysdev.h
+@@ -45,12 +45,16 @@ struct sysdev_class_attribute {
+ ssize_t (*store)(struct sysdev_class *, const char *, size_t);
+ };
+
+-#define SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) \
+-struct sysdev_class_attribute attr_##_name = { \
++#define _SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) \
++{ \
+ .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .show = _show, \
+ .store = _store, \
+-};
++}
++
++#define SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) \
++ struct sysdev_class_attribute attr_##_name = \
++ _SYSDEV_CLASS_ATTR(_name,_mode,_show,_store)
+
+
+ extern int sysdev_class_register(struct sysdev_class *);
+@@ -100,15 +104,16 @@ struct sysdev_attribute {
+ };
+
+
+-#define _SYSDEV_ATTR(_name,_mode,_show,_store) \
++#define _SYSDEV_ATTR(_name, _mode, _show, _store) \
+ { \
+ .attr = { .name = __stringify(_name), .mode = _mode }, \
+ .show = _show, \
+ .store = _store, \
+ }
+
+-#define SYSDEV_ATTR(_name,_mode,_show,_store) \
+-struct sysdev_attribute attr_##_name = _SYSDEV_ATTR(_name,_mode,_show,_store);
++#define SYSDEV_ATTR(_name, _mode, _show, _store) \
++ struct sysdev_attribute attr_##_name = \
++ _SYSDEV_ATTR(_name, _mode, _show, _store);
+
+ extern int sysdev_create_file(struct sys_device *, struct sysdev_attribute *);
+ extern void sysdev_remove_file(struct sys_device *, struct sysdev_attribute *);
+diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
+index 8027104..03378e3 100644
+--- a/include/linux/sysfs.h
++++ b/include/linux/sysfs.h
+@@ -131,7 +131,6 @@ static inline int sysfs_create_dir(struct kobject *kobj)
+
+ static inline void sysfs_remove_dir(struct kobject *kobj)
+ {
+- ;
+ }
+
+ static inline int sysfs_rename_dir(struct kobject *kobj, const char *new_name)
+@@ -160,7 +159,6 @@ static inline int sysfs_chmod_file(struct kobject *kobj,
+ static inline void sysfs_remove_file(struct kobject *kobj,
+ const struct attribute *attr)
+ {
+- ;
+ }
+
+ static inline int sysfs_create_bin_file(struct kobject *kobj,
+@@ -169,10 +167,9 @@ static inline int sysfs_create_bin_file(struct kobject *kobj,
+ return 0;
+ }
+
+-static inline int sysfs_remove_bin_file(struct kobject *kobj,
+- struct bin_attribute *attr)
++static inline void sysfs_remove_bin_file(struct kobject *kobj,
++ struct bin_attribute *attr)
+ {
+- return 0;
+ }
+
+ static inline int sysfs_create_link(struct kobject *kobj,
+@@ -183,7 +180,6 @@ static inline int sysfs_create_link(struct kobject *kobj,
+
+ static inline void sysfs_remove_link(struct kobject *kobj, const char *name)
+ {
+- ;
+ }
+
+ static inline int sysfs_create_group(struct kobject *kobj,
+@@ -195,7 +191,6 @@ static inline int sysfs_create_group(struct kobject *kobj,
+ static inline void sysfs_remove_group(struct kobject *kobj,
+ const struct attribute_group *grp)
+ {
+- ;
+ }
+
+ static inline int sysfs_add_file_to_group(struct kobject *kobj,
+diff --git a/include/linux/tcp.h b/include/linux/tcp.h
+index 08027f1..d96d9b1 100644
+--- a/include/linux/tcp.h
++++ b/include/linux/tcp.h
+@@ -239,6 +239,11 @@ static inline struct tcp_request_sock *tcp_rsk(const struct request_sock *req)
+ return (struct tcp_request_sock *)req;
+ }
+
++struct tcp_deferred_accept_info {
++ struct sock *listen_sk;
++ struct request_sock *request;
++};
++
+ struct tcp_sock {
+ /* inet_connection_sock has to be the first member of tcp_sock */
+ struct inet_connection_sock inet_conn;
+@@ -374,6 +379,8 @@ struct tcp_sock {
+ unsigned int keepalive_intvl; /* time interval between keep alive probes */
+ int linger2;
+
++ struct tcp_deferred_accept_info defer_tcp_accept;
++
+ unsigned long last_synq_overflow;
+
+ u32 tso_deferred;
+diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
+index 421323e..accd7ba 100644
+--- a/include/linux/thread_info.h
++++ b/include/linux/thread_info.h
+@@ -9,6 +9,9 @@
+
+ #include <linux/types.h>
+
++struct timespec;
++struct compat_timespec;
++
+ /*
+ * System call restart block.
+ */
+@@ -26,6 +29,15 @@ struct restart_block {
+ u32 bitset;
+ u64 time;
+ } futex;
++ /* For nanosleep */
++ struct {
++ clockid_t index;
++ struct timespec __user *rmtp;
++#ifdef CONFIG_COMPAT
++ struct compat_timespec __user *compat_rmtp;
++#endif
++ u64 expires;
++ } nanosleep;
+ };
+ };
+
+diff --git a/include/linux/topology.h b/include/linux/topology.h
+index bd14f8b..4bb7074 100644
+--- a/include/linux/topology.h
++++ b/include/linux/topology.h
+@@ -38,16 +38,15 @@
+ #endif
+
+ #ifndef nr_cpus_node
+-#define nr_cpus_node(node) \
+- ({ \
+- cpumask_t __tmp__; \
+- __tmp__ = node_to_cpumask(node); \
+- cpus_weight(__tmp__); \
++#define nr_cpus_node(node) \
++ ({ \
++ node_to_cpumask_ptr(__tmp__, node); \
++ cpus_weight(*__tmp__); \
+ })
+ #endif
+
+-#define for_each_node_with_cpus(node) \
+- for_each_online_node(node) \
++#define for_each_node_with_cpus(node) \
++ for_each_online_node(node) \
+ if (nr_cpus_node(node))
+
+ void arch_update_cpu_topology(void);
+@@ -80,7 +79,9 @@ void arch_update_cpu_topology(void);
+ * by defining their own arch-specific initializer in include/asm/topology.h.
+ * A definition there will automagically override these default initializers
+ * and allow arch-specific performance tuning of sched_domains.
++ * (Only non-zero and non-null fields need be specified.)
+ */
++
+ #ifdef CONFIG_SCHED_SMT
+ /* MCD - Do we really need this? It is always on if CONFIG_SCHED_SMT is,
+ * so can't we drop this in favor of CONFIG_SCHED_SMT?
+@@ -89,20 +90,10 @@ void arch_update_cpu_topology(void);
+ /* Common values for SMT siblings */
+ #ifndef SD_SIBLING_INIT
+ #define SD_SIBLING_INIT (struct sched_domain) { \
+- .span = CPU_MASK_NONE, \
+- .parent = NULL, \
+- .child = NULL, \
+- .groups = NULL, \
+ .min_interval = 1, \
+ .max_interval = 2, \
+ .busy_factor = 64, \
+ .imbalance_pct = 110, \
+- .cache_nice_tries = 0, \
+- .busy_idx = 0, \
+- .idle_idx = 0, \
+- .newidle_idx = 0, \
+- .wake_idx = 0, \
+- .forkexec_idx = 0, \
+ .flags = SD_LOAD_BALANCE \
+ | SD_BALANCE_NEWIDLE \
+ | SD_BALANCE_FORK \
+@@ -112,7 +103,6 @@ void arch_update_cpu_topology(void);
+ | SD_SHARE_CPUPOWER, \
+ .last_balance = jiffies, \
+ .balance_interval = 1, \
+- .nr_balance_failed = 0, \
+ }
+ #endif
+ #endif /* CONFIG_SCHED_SMT */
+@@ -121,18 +111,12 @@ void arch_update_cpu_topology(void);
+ /* Common values for MC siblings. for now mostly derived from SD_CPU_INIT */
+ #ifndef SD_MC_INIT
+ #define SD_MC_INIT (struct sched_domain) { \
+- .span = CPU_MASK_NONE, \
+- .parent = NULL, \
+- .child = NULL, \
+- .groups = NULL, \
+ .min_interval = 1, \
+ .max_interval = 4, \
+ .busy_factor = 64, \
+ .imbalance_pct = 125, \
+ .cache_nice_tries = 1, \
+ .busy_idx = 2, \
+- .idle_idx = 0, \
+- .newidle_idx = 0, \
+ .wake_idx = 1, \
+ .forkexec_idx = 1, \
+ .flags = SD_LOAD_BALANCE \
+@@ -144,7 +128,6 @@ void arch_update_cpu_topology(void);
+ | BALANCE_FOR_MC_POWER, \
+ .last_balance = jiffies, \
+ .balance_interval = 1, \
+- .nr_balance_failed = 0, \
+ }
+ #endif
+ #endif /* CONFIG_SCHED_MC */
+@@ -152,10 +135,6 @@ void arch_update_cpu_topology(void);
+ /* Common values for CPUs */
+ #ifndef SD_CPU_INIT
+ #define SD_CPU_INIT (struct sched_domain) { \
+- .span = CPU_MASK_NONE, \
+- .parent = NULL, \
+- .child = NULL, \
+- .groups = NULL, \
+ .min_interval = 1, \
+ .max_interval = 4, \
+ .busy_factor = 64, \
+@@ -174,16 +153,11 @@ void arch_update_cpu_topology(void);
+ | BALANCE_FOR_PKG_POWER,\
+ .last_balance = jiffies, \
+ .balance_interval = 1, \
+- .nr_balance_failed = 0, \
+ }
+ #endif
+
+ /* sched_domains SD_ALLNODES_INIT for NUMA machines */
+ #define SD_ALLNODES_INIT (struct sched_domain) { \
+- .span = CPU_MASK_NONE, \
+- .parent = NULL, \
+- .child = NULL, \
+- .groups = NULL, \
+ .min_interval = 64, \
+ .max_interval = 64*num_online_cpus(), \
+ .busy_factor = 128, \
+@@ -191,14 +165,10 @@ void arch_update_cpu_topology(void);
+ .cache_nice_tries = 1, \
+ .busy_idx = 3, \
+ .idle_idx = 3, \
+- .newidle_idx = 0, /* unused */ \
+- .wake_idx = 0, /* unused */ \
+- .forkexec_idx = 0, /* unused */ \
+ .flags = SD_LOAD_BALANCE \
+ | SD_SERIALIZE, \
+ .last_balance = jiffies, \
+ .balance_interval = 64, \
+- .nr_balance_failed = 0, \
+ }
+
+ #ifdef CONFIG_NUMA
+diff --git a/include/linux/transport_class.h b/include/linux/transport_class.h
+index 1d6cc22..eaec1ea 100644
+--- a/include/linux/transport_class.h
++++ b/include/linux/transport_class.h
+@@ -17,11 +17,11 @@ struct transport_container;
+ struct transport_class {
+ struct class class;
+ int (*setup)(struct transport_container *, struct device *,
+- struct class_device *);
++ struct device *);
+ int (*configure)(struct transport_container *, struct device *,
+- struct class_device *);
++ struct device *);
+ int (*remove)(struct transport_container *, struct device *,
+- struct class_device *);
++ struct device *);
+ };
+
+ #define DECLARE_TRANSPORT_CLASS(cls, nm, su, rm, cfg) \
+@@ -86,9 +86,10 @@ static inline int transport_container_register(struct transport_container *tc)
+ return attribute_container_register(&tc->ac);
+ }
+
+-static inline int transport_container_unregister(struct transport_container *tc)
++static inline void transport_container_unregister(struct transport_container *tc)
+ {
+- return attribute_container_unregister(&tc->ac);
++ if (unlikely(attribute_container_unregister(&tc->ac)))
++ BUG();
+ }
+
+ int transport_class_register(struct transport_class *);
+diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
+index 85c95cd..21f69ac 100644
+--- a/include/linux/tty_driver.h
++++ b/include/linux/tty_driver.h
+@@ -125,6 +125,7 @@
+ #include <linux/cdev.h>
+
+ struct tty_struct;
++struct tty_driver;
+
+ struct tty_operations {
+ int (*open)(struct tty_struct * tty, struct file * filp);
+@@ -157,6 +158,11 @@ struct tty_operations {
+ int (*tiocmget)(struct tty_struct *tty, struct file *file);
+ int (*tiocmset)(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
++#ifdef CONFIG_CONSOLE_POLL
++ int (*poll_init)(struct tty_driver *driver, int line, char *options);
++ int (*poll_get_char)(struct tty_driver *driver, int line);
++ void (*poll_put_char)(struct tty_driver *driver, int line, char ch);
++#endif
+ };
+
+ struct tty_driver {
+@@ -220,6 +226,11 @@ struct tty_driver {
+ int (*tiocmget)(struct tty_struct *tty, struct file *file);
+ int (*tiocmset)(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
++#ifdef CONFIG_CONSOLE_POLL
++ int (*poll_init)(struct tty_driver *driver, int line, char *options);
++ int (*poll_get_char)(struct tty_driver *driver, int line);
++ void (*poll_put_char)(struct tty_driver *driver, int line, char ch);
++#endif
+
+ struct list_head tty_drivers;
+ };
+@@ -230,6 +241,7 @@ struct tty_driver *alloc_tty_driver(int lines);
+ void put_tty_driver(struct tty_driver *driver);
+ void tty_set_operations(struct tty_driver *driver,
+ const struct tty_operations *op);
++extern struct tty_driver *tty_find_polling_driver(char *name, int *line);
+
+ /* tty driver magic number */
+ #define TTY_DRIVER_MAGIC 0x5402
+diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
+index 975c963..fec6dec 100644
+--- a/include/linux/uaccess.h
++++ b/include/linux/uaccess.h
+@@ -84,4 +84,26 @@ static inline unsigned long __copy_from_user_nocache(void *to,
+ ret; \
+ })
+
++/*
++ * probe_kernel_read(): safely attempt to read from a location
++ * @dst: pointer to the buffer that shall take the data
++ * @src: address to read from
++ * @size: size of the data chunk
++ *
++ * Safely read from address @src to the buffer at @dst. If a kernel fault
++ * happens, handle that and return -EFAULT.
++ */
++extern long probe_kernel_read(void *dst, void *src, size_t size);
++
++/*
++ * probe_kernel_write(): safely attempt to write to a location
++ * @dst: address to write to
++ * @src: pointer to the data that shall be written
++ * @size: size of the data chunk
++ *
++ * Safely write to address @dst from the buffer at @src. If a kernel fault
++ * happens, handle that and return -EFAULT.
++ */
++extern long probe_kernel_write(void *dst, void *src, size_t size);
++
+ #endif /* __LINUX_UACCESS_H__ */
+diff --git a/include/linux/udf_fs.h b/include/linux/udf_fs.h
+deleted file mode 100644
+index aa88654..0000000
+--- a/include/linux/udf_fs.h
++++ /dev/null
+@@ -1,51 +0,0 @@
+-/*
+- * udf_fs.h
+- *
+- * PURPOSE
+- * Included by fs/filesystems.c
+- *
+- * DESCRIPTION
+- * OSTA-UDF(tm) = Optical Storage Technology Association
+- * Universal Disk Format.
+- *
+- * This code is based on version 2.50 of the UDF specification,
+- * and revision 3 of the ECMA 167 standard [equivalent to ISO 13346].
+- * http://www.osta.org/ * http://www.ecma.ch/
+- * http://www.iso.org/
+- *
+- * COPYRIGHT
+- * This file is distributed under the terms of the GNU General Public
+- * License (GPL). Copies of the GPL can be obtained from:
+- * ftp://prep.ai.mit.edu/pub/gnu/GPL
+- * Each contributing author retains all rights to their own work.
+- *
+- * (C) 1999-2004 Ben Fennema
+- * (C) 1999-2000 Stelias Computing Inc
+- *
+- * HISTORY
+- *
+- */
+-
+-#ifndef _UDF_FS_H
+-#define _UDF_FS_H 1
+-
+-#define UDF_PREALLOCATE
+-#define UDF_DEFAULT_PREALLOC_BLOCKS 8
+-
+-#undef UDFFS_DEBUG
+-
+-#ifdef UDFFS_DEBUG
+-#define udf_debug(f, a...) \
+- do { \
+- printk (KERN_DEBUG "UDF-fs DEBUG %s:%d:%s: ", \
+- __FILE__, __LINE__, __FUNCTION__); \
+- printk (f, ##a); \
+- } while (0)
+-#else
+-#define udf_debug(f, a...) /**/
+-#endif
+-
+-#define udf_info(f, a...) \
+- printk (KERN_INFO "UDF-fs INFO " f, ##a);
+-
+-#endif /* _UDF_FS_H */
+diff --git a/include/linux/udf_fs_i.h b/include/linux/udf_fs_i.h
+index ffaf056..3536965 100644
+--- a/include/linux/udf_fs_i.h
++++ b/include/linux/udf_fs_i.h
+@@ -9,41 +9,10 @@
+ * ftp://prep.ai.mit.edu/pub/gnu/GPL
+ * Each contributing author retains all rights to their own work.
+ */
+-
+ #ifndef _UDF_FS_I_H
+ #define _UDF_FS_I_H 1
+
+-#ifdef __KERNEL__
+-
+-struct udf_inode_info
+-{
+- struct timespec i_crtime;
+- /* Physical address of inode */
+- kernel_lb_addr i_location;
+- __u64 i_unique;
+- __u32 i_lenEAttr;
+- __u32 i_lenAlloc;
+- __u64 i_lenExtents;
+- __u32 i_next_alloc_block;
+- __u32 i_next_alloc_goal;
+- unsigned i_alloc_type : 3;
+- unsigned i_efe : 1;
+- unsigned i_use : 1;
+- unsigned i_strat4096 : 1;
+- unsigned reserved : 26;
+- union
+- {
+- short_ad *i_sad;
+- long_ad *i_lad;
+- __u8 *i_data;
+- } i_ext;
+- struct inode vfs_inode;
+-};
+-
+-#endif
+-
+ /* exported IOCTLs, we have 'l', 0x40-0x7f */
+-
+ #define UDF_GETEASIZE _IOR('l', 0x40, int)
+ #define UDF_GETEABLOCK _IOR('l', 0x41, void *)
+ #define UDF_GETVOLIDENT _IOR('l', 0x42, void *)
+diff --git a/include/linux/udf_fs_sb.h b/include/linux/udf_fs_sb.h
+deleted file mode 100644
+index 9bc4735..0000000
+--- a/include/linux/udf_fs_sb.h
++++ /dev/null
+@@ -1,117 +0,0 @@
+-/*
+- * udf_fs_sb.h
+- *
+- * This include file is for the Linux kernel/module.
+- *
+- * COPYRIGHT
+- * This file is distributed under the terms of the GNU General Public
+- * License (GPL). Copies of the GPL can be obtained from:
+- * ftp://prep.ai.mit.edu/pub/gnu/GPL
+- * Each contributing author retains all rights to their own work.
+- */
+-
+-#ifndef _UDF_FS_SB_H
+-#define _UDF_FS_SB_H 1
+-
+-#include <linux/mutex.h>
+-
+-#pragma pack(1)
+-
+-#define UDF_MAX_BLOCK_LOADED 8
+-
+-#define UDF_TYPE1_MAP15 0x1511U
+-#define UDF_VIRTUAL_MAP15 0x1512U
+-#define UDF_VIRTUAL_MAP20 0x2012U
+-#define UDF_SPARABLE_MAP15 0x1522U
+-
+-struct udf_sparing_data
+-{
+- __u16 s_packet_len;
+- struct buffer_head *s_spar_map[4];
+-};
+-
+-struct udf_virtual_data
+-{
+- __u32 s_num_entries;
+- __u16 s_start_offset;
+-};
+-
+-struct udf_bitmap
+-{
+- __u32 s_extLength;
+- __u32 s_extPosition;
+- __u16 s_nr_groups;
+- struct buffer_head **s_block_bitmap;
+-};
+-
+-struct udf_part_map
+-{
+- union
+- {
+- struct udf_bitmap *s_bitmap;
+- struct inode *s_table;
+- } s_uspace;
+- union
+- {
+- struct udf_bitmap *s_bitmap;
+- struct inode *s_table;
+- } s_fspace;
+- __u32 s_partition_root;
+- __u32 s_partition_len;
+- __u16 s_partition_type;
+- __u16 s_partition_num;
+- union
+- {
+- struct udf_sparing_data s_sparing;
+- struct udf_virtual_data s_virtual;
+- } s_type_specific;
+- __u32 (*s_partition_func)(struct super_block *, __u32, __u16, __u32);
+- __u16 s_volumeseqnum;
+- __u16 s_partition_flags;
+-};
+-
+-#pragma pack()
+-
+-struct udf_sb_info
+-{
+- struct udf_part_map *s_partmaps;
+- __u8 s_volume_ident[32];
+-
+- /* Overall info */
+- __u16 s_partitions;
+- __u16 s_partition;
+-
+- /* Sector headers */
+- __s32 s_session;
+- __u32 s_anchor[4];
+- __u32 s_last_block;
+-
+- struct buffer_head *s_lvid_bh;
+-
+- /* Default permissions */
+- mode_t s_umask;
+- gid_t s_gid;
+- uid_t s_uid;
+-
+- /* Root Info */
+- struct timespec s_record_time;
+-
+- /* Fileset Info */
+- __u16 s_serial_number;
+-
+- /* highest UDF revision we have recorded to this media */
+- __u16 s_udfrev;
+-
+- /* Miscellaneous flags */
+- __u32 s_flags;
+-
+- /* Encoding info */
+- struct nls_table *s_nls_map;
+-
+- /* VAT inode */
+- struct inode *s_vat_inode;
+-
+- struct mutex s_alloc_mutex;
+-};
+-
+-#endif /* _UDF_FS_SB_H */
+diff --git a/include/linux/udp.h b/include/linux/udp.h
+index 8ec703f..581ca2c 100644
+--- a/include/linux/udp.h
++++ b/include/linux/udp.h
+@@ -26,15 +26,6 @@ struct udphdr {
+ __sum16 check;
+ };
+
+-#ifdef __KERNEL__
+-#include <linux/skbuff.h>
+-
+-static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
+-{
+- return (struct udphdr *)skb_transport_header(skb);
+-}
+-#endif
+-
+ /* UDP socket options */
+ #define UDP_CORK 1 /* Never send partially complete segments */
+ #define UDP_ENCAP 100 /* Set the socket to accept encapsulated packets */
+@@ -45,9 +36,14 @@ static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
+ #define UDP_ENCAP_L2TPINUDP 3 /* rfc2661 */
+
+ #ifdef __KERNEL__
+-#include <linux/types.h>
+-
+ #include <net/inet_sock.h>
++#include <linux/skbuff.h>
++
++static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
++{
++ return (struct udphdr *)skb_transport_header(skb);
++}
++
+ #define UDP_HTABLE_SIZE 128
+
+ struct udp_sock {
+@@ -82,6 +78,7 @@ static inline struct udp_sock *udp_sk(const struct sock *sk)
+ {
+ return (struct udp_sock *)sk;
+ }
++
+ #define IS_UDPLITE(__sk) (udp_sk(__sk)->pcflag)
+
+ #endif
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index 583e048..c08689e 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -23,6 +23,7 @@
+
+ struct usb_device;
+ struct usb_driver;
++struct wusb_dev;
+
+ /*-------------------------------------------------------------------------*/
+
+@@ -341,103 +342,146 @@ struct usb_bus {
+
+ struct usb_tt;
+
+-/*
++/**
+ * struct usb_device - kernel's representation of a USB device
+- *
+- * FIXME: Write the kerneldoc!
+- *
++ * @devnum: device number; address on a USB bus
++ * @devpath: device ID string for use in messages (e.g., /port/...)
++ * @state: device state: configured, not attached, etc.
++ * @speed: device speed: high/full/low (or error)
++ * @tt: Transaction Translator info; used with low/full speed dev, highspeed hub
++ * @ttport: device port on that tt hub
++ * @toggle: one bit for each endpoint, with ([0] = IN, [1] = OUT) endpoints
++ * @parent: our hub, unless we're the root
++ * @bus: bus we're part of
++ * @ep0: endpoint 0 data (default control pipe)
++ * @dev: generic device interface
++ * @descriptor: USB device descriptor
++ * @config: all of the device's configs
++ * @actconfig: the active configuration
++ * @ep_in: array of IN endpoints
++ * @ep_out: array of OUT endpoints
++ * @rawdescriptors: raw descriptors for each config
++ * @bus_mA: Current available from the bus
++ * @portnum: parent port number (origin 1)
++ * @level: number of USB hub ancestors
++ * @can_submit: URBs may be submitted
++ * @discon_suspended: disconnected while suspended
++ * @persist_enabled: USB_PERSIST enabled for this device
++ * @have_langid: whether string_langid is valid
++ * @authorized: policy has said we can use it;
++ * (user space) policy determines if we authorize this device to be
++ * used or not. By default, wired USB devices are authorized.
++ * WUSB devices are not, until we authorize them from user space.
++ * FIXME -- complete doc
++ * @authenticated: Crypto authentication passed
++ * @wusb: device is Wireless USB
++ * @string_langid: language ID for strings
++ * @product: iProduct string, if present (static)
++ * @manufacturer: iManufacturer string, if present (static)
++ * @serial: iSerialNumber string, if present (static)
++ * @filelist: usbfs files that are open to this device
++ * @usb_classdev: USB class device that was created for usbfs device
++ * access from userspace
++ * @usbfs_dentry: usbfs dentry entry for the device
++ * @maxchild: number of ports if hub
++ * @children: child devices - USB devices that are attached to this hub
++ * @pm_usage_cnt: usage counter for autosuspend
++ * @quirks: quirks of the whole device
++ * @urbnum: number of URBs submitted for the whole device
++ * @active_duration: total time device is not suspended
++ * @autosuspend: for delayed autosuspends
++ * @pm_mutex: protects PM operations
++ * @last_busy: time of last use
++ * @autosuspend_delay: in jiffies
++ * @connect_time: time device was first connected
++ * @auto_pm: autosuspend/resume in progress
++ * @do_remote_wakeup: remote wakeup should be enabled
++ * @reset_resume: needs reset instead of resume
++ * @autosuspend_disabled: autosuspend disabled by the user
++ * @autoresume_disabled: autoresume disabled by the user
++ * @skip_sys_resume: skip the next system resume
++ *
++ * Notes:
+ * Usbcore drivers should not set usbdev->state directly. Instead use
+ * usb_set_device_state().
+- *
+- * @authorized: (user space) policy determines if we authorize this
+- * device to be used or not. By default, wired USB
+- * devices are authorized. WUSB devices are not, until we
+- * authorize them from user space. FIXME -- complete doc
+ */
+ struct usb_device {
+- int devnum; /* Address on USB bus */
+- char devpath [16]; /* Use in messages: /port/port/... */
+- enum usb_device_state state; /* configured, not attached, etc */
+- enum usb_device_speed speed; /* high/full/low (or error) */
++ int devnum;
++ char devpath [16];
++ enum usb_device_state state;
++ enum usb_device_speed speed;
+
+- struct usb_tt *tt; /* low/full speed dev, highspeed hub */
+- int ttport; /* device port on that tt hub */
++ struct usb_tt *tt;
++ int ttport;
+
+- unsigned int toggle[2]; /* one bit for each endpoint
+- * ([0] = IN, [1] = OUT) */
++ unsigned int toggle[2];
+
+- struct usb_device *parent; /* our hub, unless we're the root */
+- struct usb_bus *bus; /* Bus we're part of */
++ struct usb_device *parent;
++ struct usb_bus *bus;
+ struct usb_host_endpoint ep0;
+
+- struct device dev; /* Generic device interface */
++ struct device dev;
+
+- struct usb_device_descriptor descriptor;/* Descriptor */
+- struct usb_host_config *config; /* All of the configs */
++ struct usb_device_descriptor descriptor;
++ struct usb_host_config *config;
+
+- struct usb_host_config *actconfig;/* the active configuration */
++ struct usb_host_config *actconfig;
+ struct usb_host_endpoint *ep_in[16];
+ struct usb_host_endpoint *ep_out[16];
+
+- char **rawdescriptors; /* Raw descriptors for each config */
++ char **rawdescriptors;
+
+- unsigned short bus_mA; /* Current available from the bus */
+- u8 portnum; /* Parent port number (origin 1) */
+- u8 level; /* Number of USB hub ancestors */
++ unsigned short bus_mA;
++ u8 portnum;
++ u8 level;
+
+- unsigned can_submit:1; /* URBs may be submitted */
+- unsigned discon_suspended:1; /* Disconnected while suspended */
+- unsigned have_langid:1; /* whether string_langid is valid */
+- unsigned authorized:1; /* Policy has said we can use it */
+- unsigned wusb:1; /* Device is Wireless USB */
+- int string_langid; /* language ID for strings */
++ unsigned can_submit:1;
++ unsigned discon_suspended:1;
++ unsigned persist_enabled:1;
++ unsigned have_langid:1;
++ unsigned authorized:1;
++ unsigned authenticated:1;
++ unsigned wusb:1;
++ int string_langid;
+
+ /* static strings from the device */
+- char *product; /* iProduct string, if present */
+- char *manufacturer; /* iManufacturer string, if present */
+- char *serial; /* iSerialNumber string, if present */
++ char *product;
++ char *manufacturer;
++ char *serial;
+
+ struct list_head filelist;
+ #ifdef CONFIG_USB_DEVICE_CLASS
+ struct device *usb_classdev;
+ #endif
+ #ifdef CONFIG_USB_DEVICEFS
+- struct dentry *usbfs_dentry; /* usbfs dentry entry for the device */
++ struct dentry *usbfs_dentry;
+ #endif
+- /*
+- * Child devices - these can be either new devices
+- * (if this is a hub device), or different instances
+- * of this same device.
+- *
+- * Each instance needs its own set of data structures.
+- */
+
+- int maxchild; /* Number of ports if hub */
++ int maxchild;
+ struct usb_device *children[USB_MAXCHILDREN];
+
+- int pm_usage_cnt; /* usage counter for autosuspend */
+- u32 quirks; /* quirks of the whole device */
+- atomic_t urbnum; /* number of URBs submitted for
+- the whole device */
++ int pm_usage_cnt;
++ u32 quirks;
++ atomic_t urbnum;
+
+- unsigned long active_duration; /* total time device is not suspended */
++ unsigned long active_duration;
+
+ #ifdef CONFIG_PM
+- struct delayed_work autosuspend; /* for delayed autosuspends */
+- struct mutex pm_mutex; /* protects PM operations */
+-
+- unsigned long last_busy; /* time of last use */
+- int autosuspend_delay; /* in jiffies */
+- unsigned long connect_time; /* time device was first connected */
+-
+- unsigned auto_pm:1; /* autosuspend/resume in progress */
+- unsigned do_remote_wakeup:1; /* remote wakeup should be enabled */
+- unsigned reset_resume:1; /* needs reset instead of resume */
+- unsigned persist_enabled:1; /* USB_PERSIST enabled for this dev */
+- unsigned autosuspend_disabled:1; /* autosuspend and autoresume */
+- unsigned autoresume_disabled:1; /* disabled by the user */
+- unsigned skip_sys_resume:1; /* skip the next system resume */
++ struct delayed_work autosuspend;
++ struct mutex pm_mutex;
++
++ unsigned long last_busy;
++ int autosuspend_delay;
++ unsigned long connect_time;
++
++ unsigned auto_pm:1;
++ unsigned do_remote_wakeup:1;
++ unsigned reset_resume:1;
++ unsigned autosuspend_disabled:1;
++ unsigned autoresume_disabled:1;
++ unsigned skip_sys_resume:1;
+ #endif
++ struct wusb_dev *wusb_dev;
+ };
+ #define to_usb_device(d) container_of(d, struct usb_device, dev)
+
+@@ -898,10 +942,11 @@ struct usbdrv_wrap {
+ * and should normally be the same as the module name.
+ * @probe: Called to see if the driver is willing to manage a particular
+ * interface on a device. If it is, probe returns zero and uses
+- * dev_set_drvdata() to associate driver-specific data with the
++ * usb_set_intfdata() to associate driver-specific data with the
+ * interface. It may also use usb_set_interface() to specify the
+ * appropriate altsetting. If unwilling to manage the interface,
+- * return a negative errno value.
++ * return -ENODEV, if genuine IO errors occured, an appropriate
++ * negative errno value.
+ * @disconnect: Called when the interface is no longer accessible, usually
+ * because its device has been (or is being) disconnected or the
+ * driver module is being unloaded.
+@@ -916,10 +961,7 @@ struct usbdrv_wrap {
+ * @pre_reset: Called by usb_reset_composite_device() when the device
+ * is about to be reset.
+ * @post_reset: Called by usb_reset_composite_device() after the device
+- * has been reset, or in lieu of @resume following a reset-resume
+- * (i.e., the device is reset instead of being resumed, as might
+- * happen if power was lost). The second argument tells which is
+- * the reason.
++ * has been reset
+ * @id_table: USB drivers use ID table to support hotplugging.
+ * Export this with MODULE_DEVICE_TABLE(usb,...). This must be set
+ * or your driver's probe function will never get called.
+@@ -1411,6 +1453,7 @@ extern int usb_submit_urb(struct urb *urb, gfp_t mem_flags);
+ extern int usb_unlink_urb(struct urb *urb);
+ extern void usb_kill_urb(struct urb *urb);
+ extern void usb_kill_anchored_urbs(struct usb_anchor *anchor);
++extern void usb_unlink_anchored_urbs(struct usb_anchor *anchor);
+ extern void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor);
+ extern void usb_unanchor_urb(struct urb *urb);
+ extern int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,
+@@ -1661,13 +1704,12 @@ extern void usb_unregister_notify(struct notifier_block *nb);
+ #define dbg(format, arg...) do {} while (0)
+ #endif
+
+-#define err(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
+- __FILE__ , ## arg)
+-#define info(format, arg...) printk(KERN_INFO "%s: " format "\n" , \
+- __FILE__ , ## arg)
+-#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n" , \
+- __FILE__ , ## arg)
+-
++#define err(format, arg...) printk(KERN_ERR KBUILD_MODNAME ": " \
++ format "\n" , ## arg)
++#define info(format, arg...) printk(KERN_INFO KBUILD_MODNAME ": " \
++ format "\n" , ## arg)
++#define warn(format, arg...) printk(KERN_WARNING KBUILD_MODNAME ": " \
++ format "\n" , ## arg)
+
+ #endif /* __KERNEL__ */
+
+diff --git a/include/linux/usb/atmel_usba_udc.h b/include/linux/usb/atmel_usba_udc.h
+new file mode 100644
+index 0000000..6311fa2
+--- /dev/null
++++ b/include/linux/usb/atmel_usba_udc.h
+@@ -0,0 +1,22 @@
++/*
++ * Platform data definitions for Atmel USBA gadget driver.
++ */
++#ifndef __LINUX_USB_USBA_H
++#define __LINUX_USB_USBA_H
++
++struct usba_ep_data {
++ char *name;
++ int index;
++ int fifo_size;
++ int nr_banks;
++ int can_dma;
++ int can_isoc;
++};
++
++struct usba_platform_data {
++ int vbus_pin;
++ int num_ep;
++ struct usba_ep_data ep[0];
++};
++
++#endif /* __LINUX_USB_USBA_H */
+diff --git a/include/linux/usb/audio.h b/include/linux/usb/audio.h
+index 2dfeef1..8cb025f 100644
+--- a/include/linux/usb/audio.h
++++ b/include/linux/usb/audio.h
+@@ -50,4 +50,4 @@ struct usb_ac_header_descriptor_##n { \
+ __u8 baInterfaceNr[n]; \
+ } __attribute__ ((packed))
+
+-#endif
++#endif /* __LINUX_USB_AUDIO_H */
+diff --git a/include/linux/usb/cdc.h b/include/linux/usb/cdc.h
+index 94ee4ec..71e52f2 100644
+--- a/include/linux/usb/cdc.h
++++ b/include/linux/usb/cdc.h
+@@ -6,6 +6,9 @@
+ * firmware based USB peripherals.
+ */
+
++#ifndef __LINUX_USB_CDC_H
++#define __LINUX_USB_CDC_H
++
+ #define USB_CDC_SUBCLASS_ACM 0x02
+ #define USB_CDC_SUBCLASS_ETHERNET 0x06
+ #define USB_CDC_SUBCLASS_WHCM 0x08
+@@ -221,3 +224,4 @@ struct usb_cdc_notification {
+ __le16 wLength;
+ } __attribute__ ((packed));
+
++#endif /* __LINUX_USB_CDC_H */
+diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
+index 6169438..7e0d308 100644
+--- a/include/linux/usb/ch9.h
++++ b/include/linux/usb/ch9.h
+@@ -66,8 +66,8 @@
+ #define USB_RECIP_ENDPOINT 0x02
+ #define USB_RECIP_OTHER 0x03
+ /* From Wireless USB 1.0 */
+-#define USB_RECIP_PORT 0x04
+-#define USB_RECIP_RPIPE 0x05
++#define USB_RECIP_PORT 0x04
++#define USB_RECIP_RPIPE 0x05
+
+ /*
+ * Standard requests, for the bRequest field of a SETUP packet.
+@@ -102,10 +102,16 @@
+ #define USB_REQ_LOOPBACK_DATA_READ 0x16
+ #define USB_REQ_SET_INTERFACE_DS 0x17
+
++/* The Link Power Mangement (LPM) ECN defines USB_REQ_TEST_AND_SET command,
++ * used by hubs to put ports into a new L1 suspend state, except that it
++ * forgot to define its number ...
++ */
++
+ /*
+ * USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and
+ * are read as a bit array returned by USB_REQ_GET_STATUS. (So there
+- * are at most sixteen features of each type.)
++ * are at most sixteen features of each type.) Hubs may also support a
++ * new USB_REQ_TEST_AND_SET_FEATURE to put ports into L1 suspend.
+ */
+ #define USB_DEVICE_SELF_POWERED 0 /* (read only) */
+ #define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */
+@@ -180,6 +186,7 @@ struct usb_ctrlrequest {
+ #define USB_DT_WIRELESS_ENDPOINT_COMP 0x11
+ #define USB_DT_WIRE_ADAPTER 0x21
+ #define USB_DT_RPIPE 0x22
++#define USB_DT_CS_RADIO_CONTROL 0x23
+
+ /* Conventional codes for class-specific descriptors. The convention is
+ * defined in the USB "Common Class" Spec (3.11). Individual class specs
+@@ -574,7 +581,9 @@ enum usb_device_state {
+ /* NOTE: there are actually four different SUSPENDED
+ * states, returning to POWERED, DEFAULT, ADDRESS, or
+ * CONFIGURED respectively when SOF tokens flow again.
++ * At this level there's no difference between L1 and L2
++ * suspend states. (L2 being original USB 1.1 suspend.)
+ */
+ };
+
+-#endif /* __LINUX_USB_CH9_H */
++#endif /* __LINUX_USB_CH9_H */
+diff --git a/include/linux/usb/g_printer.h b/include/linux/usb/g_printer.h
+index 0c5ea1e..6178fde 100644
+--- a/include/linux/usb/g_printer.h
++++ b/include/linux/usb/g_printer.h
+@@ -18,6 +18,8 @@
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
++#ifndef __LINUX_USB_G_PRINTER_H
++#define __LINUX_USB_G_PRINTER_H
+
+ #define PRINTER_NOT_ERROR 0x08
+ #define PRINTER_SELECTED 0x10
+@@ -29,3 +31,5 @@
+ */
+ #define GADGET_GET_PRINTER_STATUS _IOR('g', 0x21, unsigned char)
+ #define GADGET_SET_PRINTER_STATUS _IOWR('g', 0x22, unsigned char)
++
++#endif /* __LINUX_USB_G_PRINTER_H */
+diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
+index f329529..d8128f7 100644
+--- a/include/linux/usb/gadget.h
++++ b/include/linux/usb/gadget.h
+@@ -846,4 +846,4 @@ extern struct usb_ep *usb_ep_autoconfig(struct usb_gadget *,
+
+ extern void usb_ep_autoconfig_reset(struct usb_gadget *) __devinit;
+
+-#endif /* __LINUX_USB_GADGET_H */
++#endif /* __LINUX_USB_GADGET_H */
+diff --git a/include/linux/usb/gadgetfs.h b/include/linux/usb/gadgetfs.h
+index c291ab1..ea45f26 100644
+--- a/include/linux/usb/gadgetfs.h
++++ b/include/linux/usb/gadgetfs.h
+@@ -1,11 +1,3 @@
+-#ifndef __LINUX_USB_GADGETFS_H
+-#define __LINUX_USB_GADGETFS_H
+-
+-#include <asm/types.h>
+-#include <asm/ioctl.h>
+-
+-#include <linux/usb/ch9.h>
+-
+ /*
+ * Filesystem based user-mode API to USB Gadget controller hardware
+ *
+@@ -23,6 +15,14 @@
+ * then performing data transfers by reading or writing.
+ */
+
++#ifndef __LINUX_USB_GADGETFS_H
++#define __LINUX_USB_GADGETFS_H
++
++#include <asm/types.h>
++#include <asm/ioctl.h>
++
++#include <linux/usb/ch9.h>
++
+ /*
+ * Events are delivered on the ep0 file descriptor, when the user mode driver
+ * reads from this file descriptor after writing the descriptors. Don't
+diff --git a/include/linux/usb/input.h b/include/linux/usb/input.h
+index 716e0cc..0e010b2 100644
+--- a/include/linux/usb/input.h
++++ b/include/linux/usb/input.h
+@@ -1,6 +1,3 @@
+-#ifndef __USB_INPUT_H
+-#define __USB_INPUT_H
+-
+ /*
+ * Copyright (C) 2005 Dmitry Torokhov
+ *
+@@ -9,6 +6,9 @@
+ * the Free Software Foundation.
+ */
+
++#ifndef __LINUX_USB_INPUT_H
++#define __LINUX_USB_INPUT_H
++
+ #include <linux/usb.h>
+ #include <linux/input.h>
+ #include <asm/byteorder.h>
+@@ -22,4 +22,4 @@ usb_to_input_id(const struct usb_device *dev, struct input_id *id)
+ id->version = le16_to_cpu(dev->descriptor.bcdDevice);
+ }
+
+-#endif
++#endif /* __LINUX_USB_INPUT_H */
+diff --git a/include/linux/usb/iowarrior.h b/include/linux/usb/iowarrior.h
+index de6f380..4fd6513 100644
+--- a/include/linux/usb/iowarrior.h
++++ b/include/linux/usb/iowarrior.h
+@@ -1,5 +1,5 @@
+-#ifndef _IOWARRIOR_H_
+-#define _IOWARRIOR_H_
++#ifndef __LINUX_USB_IOWARRIOR_H
++#define __LINUX_USB_IOWARRIOR_H
+
+ #define CODEMERCS_MAGIC_NUMBER 0xC0 /* like COde Mercenaries */
+
+@@ -39,4 +39,4 @@ struct iowarrior_info {
+ */
+ #define IOW_GETINFO _IOR(CODEMERCS_MAGIC_NUMBER, 3, struct iowarrior_info)
+
+-#endif /* _IOWARRIOR_H_ */
++#endif /* __LINUX_USB_IOWARRIOR_H */
+diff --git a/include/linux/usb/isp116x.h b/include/linux/usb/isp116x.h
+index 67d2826..96ca114 100644
+--- a/include/linux/usb/isp116x.h
++++ b/include/linux/usb/isp116x.h
+@@ -1,9 +1,11 @@
+-
+ /*
+ * Board initialization code should put one of these into dev->platform_data
+ * and place the isp116x onto platform_bus.
+ */
+
++#ifndef __LINUX_USB_ISP116X_H
++#define __LINUX_USB_ISP116X_H
++
+ struct isp116x_platform_data {
+ /* Enable internal resistors on downstream ports */
+ unsigned sel15Kres:1;
+@@ -27,3 +29,5 @@ struct isp116x_platform_data {
+ */
+ void (*delay) (struct device *dev, int delay);
+ };
++
++#endif /* __LINUX_USB_ISP116X_H */
+diff --git a/include/linux/usb/midi.h b/include/linux/usb/midi.h
+index 80624c5..1d10408 100644
+--- a/include/linux/usb/midi.h
++++ b/include/linux/usb/midi.h
+@@ -109,4 +109,4 @@ struct usb_ms_endpoint_descriptor_##n { \
+ __u8 baAssocJackID[n]; \
+ } __attribute__ ((packed))
+
+-#endif
++#endif /* __LINUX_USB_MIDI_H */
+diff --git a/include/linux/usb/net2280.h b/include/linux/usb/net2280.h
+index ec897cb..96ca549 100644
+--- a/include/linux/usb/net2280.h
++++ b/include/linux/usb/net2280.h
+@@ -1,11 +1,7 @@
+ /*
+ * NetChip 2280 high/full speed USB device controller.
+ * Unlike many such controllers, this one talks PCI.
+- */
+-#ifndef __LINUX_USB_NET2280_H
+-#define __LINUX_USB_NET2280_H
+-
+-/*
++ *
+ * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
+ * Copyright (C) 2003 David Brownell
+ *
+@@ -24,6 +20,9 @@
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
++#ifndef __LINUX_USB_NET2280_H
++#define __LINUX_USB_NET2280_H
++
+ /*-------------------------------------------------------------------------*/
+
+ /* NET2280 MEMORY MAPPED REGISTERS
+diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
+index e007074..1db25d1 100644
+--- a/include/linux/usb/otg.h
++++ b/include/linux/usb/otg.h
+@@ -1,11 +1,13 @@
+ /* USB OTG (On The Go) defines */
+-
+ /*
++ *
+ * These APIs may be used between USB controllers. USB device drivers
+ * (for either host or peripheral roles) don't use these calls; they
+ * continue to use just usb_device and usb_gadget.
+ */
+
++#ifndef __LINUX_USB_OTG_H
++#define __LINUX_USB_OTG_H
+
+ /* OTG defines lots of enumeration states before device reset */
+ enum usb_otg_state {
+@@ -129,3 +131,5 @@ otg_start_srp(struct otg_transceiver *otg)
+
+ /* for OTG controller drivers (and maybe other stuff) */
+ extern int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num);
++
++#endif /* __LINUX_USB_OTG_H */
+diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h
+index 1f999ec..7f6c603 100644
+--- a/include/linux/usb/quirks.h
++++ b/include/linux/usb/quirks.h
+@@ -4,6 +4,9 @@
+ * belong here.
+ */
+
++#ifndef __LINUX_USB_QUIRKS_H
++#define __LINUX_USB_QUIRKS_H
++
+ /* string descriptors must not be fetched using a 255-byte read */
+ #define USB_QUIRK_STRING_FETCH_255 0x00000001
+
+@@ -12,3 +15,5 @@
+
+ /* device can't handle Set-Interface requests */
+ #define USB_QUIRK_NO_SET_INTF 0x00000004
++
++#endif /* __LINUX_USB_QUIRKS_H */
+diff --git a/include/linux/usb/rndis_host.h b/include/linux/usb/rndis_host.h
+index edc1d4a..29d6458 100644
+--- a/include/linux/usb/rndis_host.h
++++ b/include/linux/usb/rndis_host.h
+@@ -17,10 +17,8 @@
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+-
+-#ifndef __RNDIS_HOST_H
+-#define __RNDIS_HOST_H
+-
++#ifndef __LINUX_USB_RNDIS_HOST_H
++#define __LINUX_USB_RNDIS_HOST_H
+
+ /*
+ * CONTROL uses CDC "encapsulated commands" with funky notifications.
+@@ -270,5 +268,4 @@ extern int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb);
+ extern struct sk_buff *
+ rndis_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags);
+
+-#endif /* __RNDIS_HOST_H */
+-
++#endif /* __LINUX_USB_RNDIS_HOST_H */
+diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
+index 21b4a1c..8f891cb 100644
+--- a/include/linux/usb/serial.h
++++ b/include/linux/usb/serial.h
+@@ -10,7 +10,6 @@
+ *
+ */
+
+-
+ #ifndef __LINUX_USB_SERIAL_H
+ #define __LINUX_USB_SERIAL_H
+
+@@ -146,8 +145,6 @@ struct usb_serial {
+ };
+ #define to_usb_serial(d) container_of(d, struct usb_serial, kref)
+
+-#define NUM_DONT_CARE 99
+-
+ /* get and set the serial private data pointer helper functions */
+ static inline void *usb_get_serial_data(struct usb_serial *serial)
+ {
+@@ -165,18 +162,6 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data)
+ * used in the syslog messages when a device is inserted or removed.
+ * @id_table: pointer to a list of usb_device_id structures that define all
+ * of the devices this structure can support.
+- * @num_interrupt_in: If a device doesn't have this many interrupt-in
+- * endpoints, it won't be sent to the driver's attach() method.
+- * (But it might still be sent to the probe() method.)
+- * @num_interrupt_out: If a device doesn't have this many interrupt-out
+- * endpoints, it won't be sent to the driver's attach() method.
+- * (But it might still be sent to the probe() method.)
+- * @num_bulk_in: If a device doesn't have this many bulk-in
+- * endpoints, it won't be sent to the driver's attach() method.
+- * (But it might still be sent to the probe() method.)
+- * @num_bulk_out: If a device doesn't have this many bulk-out
+- * endpoints, it won't be sent to the driver's attach() method.
+- * (But it might still be sent to the probe() method.)
+ * @num_ports: the number of different ports this device will have.
+ * @calc_num_ports: pointer to a function to determine how many ports this
+ * device has dynamically. It will be called after the probe()
+@@ -212,10 +197,6 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data)
+ struct usb_serial_driver {
+ const char *description;
+ const struct usb_device_id *id_table;
+- char num_interrupt_in;
+- char num_interrupt_out;
+- char num_bulk_in;
+- char num_bulk_out;
+ char num_ports;
+
+ struct list_head driver_list;
+@@ -340,5 +321,5 @@ static inline void usb_serial_debug_data(int debug,
+
+
+
+-#endif /* ifdef __LINUX_USB_SERIAL_H */
++#endif /* __LINUX_USB_SERIAL_H */
+
+diff --git a/include/linux/usb/sl811.h b/include/linux/usb/sl811.h
+index 877373d..3afe4d1 100644
+--- a/include/linux/usb/sl811.h
++++ b/include/linux/usb/sl811.h
+@@ -1,9 +1,11 @@
+-
+ /*
+ * board initialization should put one of these into dev->platform_data
+ * and place the sl811hs onto platform_bus named "sl811-hcd".
+ */
+
++#ifndef __LINUX_USB_SL811_H
++#define __LINUX_USB_SL811_H
++
+ struct sl811_platform_data {
+ unsigned can_wakeup:1;
+
+@@ -24,3 +26,4 @@ struct sl811_platform_data {
+ /* void (*clock_enable)(struct device *dev, int is_on); */
+ };
+
++#endif /* __LINUX_USB_SL811_H */
+diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
+index e0501da..ba09fe8 100644
+--- a/include/linux/usb/usbnet.h
++++ b/include/linux/usb/usbnet.h
+@@ -19,10 +19,8 @@
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+-
+-#ifndef __USBNET_H
+-#define __USBNET_H
+-
++#ifndef __LINUX_USB_USBNET_H
++#define __LINUX_USB_USBNET_H
+
+ /* interface from usbnet core to each USB networking link we handle */
+ struct usbnet {
+@@ -211,4 +209,4 @@ extern int usbnet_nway_reset(struct net_device *net);
+ printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net->name , ## arg); \
+
+
+-#endif /* __USBNET_H */
++#endif /* __LINUX_USB_USBNET_H */
+diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
+index 0a40dfa..d9a3bbe 100644
+--- a/include/linux/usb_usual.h
++++ b/include/linux/usb_usual.h
+@@ -85,6 +85,7 @@ enum { US_DO_ALL_FLAGS };
+ #define US_SC_LOCKABLE 0x07 /* Password-protected */
+
+ #define US_SC_ISD200 0xf0 /* ISD200 ATA */
++#define US_SC_CYP_ATACB 0xf1 /* Cypress ATACB */
+ #define US_SC_DEVICE 0xff /* Use device's value */
+
+ /* Protocols */
+diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
+index 17cb108..3118ede 100644
+--- a/include/linux/usbdevice_fs.h
++++ b/include/linux/usbdevice_fs.h
+@@ -77,8 +77,11 @@ struct usbdevfs_connectinfo {
+ unsigned char slow;
+ };
+
+-#define USBDEVFS_URB_SHORT_NOT_OK 1
+-#define USBDEVFS_URB_ISO_ASAP 2
++#define USBDEVFS_URB_SHORT_NOT_OK 0x01
++#define USBDEVFS_URB_ISO_ASAP 0x02
++#define USBDEVFS_URB_NO_FSBR 0x20
++#define USBDEVFS_URB_ZERO_PACKET 0x40
++#define USBDEVFS_URB_NO_INTERRUPT 0x80
+
+ #define USBDEVFS_URB_TYPE_ISO 0
+ #define USBDEVFS_URB_TYPE_INTERRUPT 1
+diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
+index 17a8017..c141118 100644
+--- a/include/linux/videodev2.h
++++ b/include/linux/videodev2.h
+@@ -282,6 +282,7 @@ struct v4l2_pix_format
+ #define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B','G','R','4') /* 32 BGR-8-8-8-8 */
+ #define V4L2_PIX_FMT_RGB32 v4l2_fourcc('R','G','B','4') /* 32 RGB-8-8-8-8 */
+ #define V4L2_PIX_FMT_GREY v4l2_fourcc('G','R','E','Y') /* 8 Greyscale */
++#define V4L2_PIX_FMT_Y16 v4l2_fourcc('Y','1','6',' ') /* 16 Greyscale */
+ #define V4L2_PIX_FMT_PAL8 v4l2_fourcc('P','A','L','8') /* 8 8-bit palette */
+ #define V4L2_PIX_FMT_YVU410 v4l2_fourcc('Y','V','U','9') /* 9 YVU 4:1:0 */
+ #define V4L2_PIX_FMT_YVU420 v4l2_fourcc('Y','V','1','2') /* 12 YVU 4:2:0 */
+@@ -308,6 +309,7 @@ struct v4l2_pix_format
+
+ /* see http://www.siliconimaging.com/RGB%20Bayer.htm */
+ #define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B','A','8','1') /* 8 BGBG.. GRGR.. */
++#define V4L2_PIX_FMT_SBGGR16 v4l2_fourcc('B','Y','R','2') /* 16 BGBG.. GRGR.. */
+
+ /* compressed formats */
+ #define V4L2_PIX_FMT_MJPEG v4l2_fourcc('M','J','P','G') /* Motion-JPEG */
+@@ -793,6 +795,7 @@ struct v4l2_ext_controls
+ /* Values for ctrl_class field */
+ #define V4L2_CTRL_CLASS_USER 0x00980000 /* Old-style 'user' controls */
+ #define V4L2_CTRL_CLASS_MPEG 0x00990000 /* MPEG-compression controls */
++#define V4L2_CTRL_CLASS_CAMERA 0x009a0000 /* Camera class controls */
+
+ #define V4L2_CTRL_ID_MASK (0x0fffffff)
+ #define V4L2_CTRL_ID2CLASS(id) ((id) & 0x0fff0000UL)
+@@ -849,21 +852,37 @@ struct v4l2_querymenu
+ #define V4L2_CID_AUDIO_TREBLE (V4L2_CID_BASE+8)
+ #define V4L2_CID_AUDIO_MUTE (V4L2_CID_BASE+9)
+ #define V4L2_CID_AUDIO_LOUDNESS (V4L2_CID_BASE+10)
+-#define V4L2_CID_BLACK_LEVEL (V4L2_CID_BASE+11)
++#define V4L2_CID_BLACK_LEVEL (V4L2_CID_BASE+11) /* Deprecated */
+ #define V4L2_CID_AUTO_WHITE_BALANCE (V4L2_CID_BASE+12)
+ #define V4L2_CID_DO_WHITE_BALANCE (V4L2_CID_BASE+13)
+ #define V4L2_CID_RED_BALANCE (V4L2_CID_BASE+14)
+ #define V4L2_CID_BLUE_BALANCE (V4L2_CID_BASE+15)
+ #define V4L2_CID_GAMMA (V4L2_CID_BASE+16)
+-#define V4L2_CID_WHITENESS (V4L2_CID_GAMMA) /* ? Not sure */
++#define V4L2_CID_WHITENESS (V4L2_CID_GAMMA) /* Deprecated */
+ #define V4L2_CID_EXPOSURE (V4L2_CID_BASE+17)
+ #define V4L2_CID_AUTOGAIN (V4L2_CID_BASE+18)
+ #define V4L2_CID_GAIN (V4L2_CID_BASE+19)
+ #define V4L2_CID_HFLIP (V4L2_CID_BASE+20)
+ #define V4L2_CID_VFLIP (V4L2_CID_BASE+21)
+-#define V4L2_CID_HCENTER (V4L2_CID_BASE+22)
+-#define V4L2_CID_VCENTER (V4L2_CID_BASE+23)
+-#define V4L2_CID_LASTP1 (V4L2_CID_BASE+24) /* last CID + 1 */
++
++/* Deprecated, use V4L2_CID_PAN_RESET and V4L2_CID_TILT_RESET */
++#define V4L2_CID_HCENTER_DEPRECATED (V4L2_CID_BASE+22)
++#define V4L2_CID_VCENTER_DEPRECATED (V4L2_CID_BASE+23)
++
++#define V4L2_CID_POWER_LINE_FREQUENCY (V4L2_CID_BASE+24)
++enum v4l2_power_line_frequency {
++ V4L2_CID_POWER_LINE_FREQUENCY_DISABLED = 0,
++ V4L2_CID_POWER_LINE_FREQUENCY_50HZ = 1,
++ V4L2_CID_POWER_LINE_FREQUENCY_60HZ = 2,
++};
++#define V4L2_CID_HUE_AUTO (V4L2_CID_BASE+25)
++#define V4L2_CID_WHITE_BALANCE_TEMPERATURE (V4L2_CID_BASE+26)
++#define V4L2_CID_SHARPNESS (V4L2_CID_BASE+27)
++#define V4L2_CID_BACKLIGHT_COMPENSATION (V4L2_CID_BASE+28)
++#define V4L2_CID_CHROMA_AGC (V4L2_CID_BASE+29)
++#define V4L2_CID_COLOR_KILLER (V4L2_CID_BASE+30)
++/* last CID + 1 */
++#define V4L2_CID_LASTP1 (V4L2_CID_BASE+31)
+
+ /* MPEG-class control IDs defined by V4L2 */
+ #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900)
+@@ -1051,6 +1070,32 @@ enum v4l2_mpeg_cx2341x_video_median_filter_type {
+ #define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP (V4L2_CID_MPEG_CX2341X_BASE+10)
+ #define V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS (V4L2_CID_MPEG_CX2341X_BASE+11)
+
++/* Camera class control IDs */
++#define V4L2_CID_CAMERA_CLASS_BASE (V4L2_CTRL_CLASS_CAMERA | 0x900)
++#define V4L2_CID_CAMERA_CLASS (V4L2_CTRL_CLASS_CAMERA | 1)
++
++#define V4L2_CID_EXPOSURE_AUTO (V4L2_CID_CAMERA_CLASS_BASE+1)
++enum v4l2_exposure_auto_type {
++ V4L2_EXPOSURE_AUTO = 0,
++ V4L2_EXPOSURE_MANUAL = 1,
++ V4L2_EXPOSURE_SHUTTER_PRIORITY = 2,
++ V4L2_EXPOSURE_APERTURE_PRIORITY = 3
++};
++#define V4L2_CID_EXPOSURE_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+2)
++#define V4L2_CID_EXPOSURE_AUTO_PRIORITY (V4L2_CID_CAMERA_CLASS_BASE+3)
++
++#define V4L2_CID_PAN_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+4)
++#define V4L2_CID_TILT_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+5)
++#define V4L2_CID_PAN_RESET (V4L2_CID_CAMERA_CLASS_BASE+6)
++#define V4L2_CID_TILT_RESET (V4L2_CID_CAMERA_CLASS_BASE+7)
++
++#define V4L2_CID_PAN_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+8)
++#define V4L2_CID_TILT_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+9)
++
++#define V4L2_CID_FOCUS_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+10)
++#define V4L2_CID_FOCUS_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+11)
++#define V4L2_CID_FOCUS_AUTO (V4L2_CID_CAMERA_CLASS_BASE+12)
++
+ /*
+ * T U N I N G
+ */
+diff --git a/include/linux/wireless.h b/include/linux/wireless.h
+index 3160dfe..2864b16 100644
+--- a/include/linux/wireless.h
++++ b/include/linux/wireless.h
+@@ -455,6 +455,7 @@
+ #define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */
+ #define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */
+ #define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */
++#define IW_MODE_MESH 7 /* Mesh (IEEE 802.11s) network */
+
+ /* Statistics flags (bitmask in updated) */
+ #define IW_QUAL_QUAL_UPDATED 0x01 /* Value was updated since last read */
+diff --git a/include/linux/wm97xx.h b/include/linux/wm97xx.h
+new file mode 100644
+index 0000000..4d13732
+--- /dev/null
++++ b/include/linux/wm97xx.h
+@@ -0,0 +1,314 @@
++
++/*
++ * Register bits and API for Wolfson WM97xx series of codecs
++ */
++
++#ifndef _LINUX_WM97XX_H
++#define _LINUX_WM97XX_H
++
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/ac97_codec.h>
++#include <sound/initval.h>
++#include <linux/types.h>
++#include <linux/list.h>
++#include <linux/input.h> /* Input device layer */
++#include <linux/platform_device.h>
++
++/*
++ * WM97xx AC97 Touchscreen registers
++ */
++#define AC97_WM97XX_DIGITISER1 0x76
++#define AC97_WM97XX_DIGITISER2 0x78
++#define AC97_WM97XX_DIGITISER_RD 0x7a
++#define AC97_WM9713_DIG1 0x74
++#define AC97_WM9713_DIG2 AC97_WM97XX_DIGITISER1
++#define AC97_WM9713_DIG3 AC97_WM97XX_DIGITISER2
++
++/*
++ * WM97xx register bits
++ */
++#define WM97XX_POLL 0x8000 /* initiate a polling measurement */
++#define WM97XX_ADCSEL_X 0x1000 /* x coord measurement */
++#define WM97XX_ADCSEL_Y 0x2000 /* y coord measurement */
++#define WM97XX_ADCSEL_PRES 0x3000 /* pressure measurement */
++#define WM97XX_ADCSEL_MASK 0x7000
++#define WM97XX_COO 0x0800 /* enable coordinate mode */
++#define WM97XX_CTC 0x0400 /* enable continuous mode */
++#define WM97XX_CM_RATE_93 0x0000 /* 93.75Hz continuous rate */
++#define WM97XX_CM_RATE_187 0x0100 /* 187.5Hz continuous rate */
++#define WM97XX_CM_RATE_375 0x0200 /* 375Hz continuous rate */
++#define WM97XX_CM_RATE_750 0x0300 /* 750Hz continuous rate */
++#define WM97XX_CM_RATE_8K 0x00f0 /* 8kHz continuous rate */
++#define WM97XX_CM_RATE_12K 0x01f0 /* 12kHz continuous rate */
++#define WM97XX_CM_RATE_24K 0x02f0 /* 24kHz continuous rate */
++#define WM97XX_CM_RATE_48K 0x03f0 /* 48kHz continuous rate */
++#define WM97XX_CM_RATE_MASK 0x03f0
++#define WM97XX_RATE(i) (((i & 3) << 8) | ((i & 4) ? 0xf0 : 0))
++#define WM97XX_DELAY(i) ((i << 4) & 0x00f0) /* sample delay times */
++#define WM97XX_DELAY_MASK 0x00f0
++#define WM97XX_SLEN 0x0008 /* slot read back enable */
++#define WM97XX_SLT(i) ((i - 5) & 0x7) /* panel slot (5-11) */
++#define WM97XX_SLT_MASK 0x0007
++#define WM97XX_PRP_DETW 0x4000 /* detect on, digitise off, wake */
++#define WM97XX_PRP_DET 0x8000 /* detect on, digitise off, no wake */
++#define WM97XX_PRP_DET_DIG 0xc000 /* setect on, digitise on */
++#define WM97XX_RPR 0x2000 /* wake up on pen down */
++#define WM97XX_PEN_DOWN 0x8000 /* pen is down */
++#define WM97XX_ADCSRC_MASK 0x7000 /* ADC source mask */
++
++#define WM97XX_AUX_ID1 0x8001
++#define WM97XX_AUX_ID2 0x8002
++#define WM97XX_AUX_ID3 0x8003
++#define WM97XX_AUX_ID4 0x8004
++
++
++/* WM9712 Bits */
++#define WM9712_45W 0x1000 /* set for 5-wire touchscreen */
++#define WM9712_PDEN 0x0800 /* measure only when pen down */
++#define WM9712_WAIT 0x0200 /* wait until adc is read before next sample */
++#define WM9712_PIL 0x0100 /* current used for pressure measurement. set 400uA else 200uA */
++#define WM9712_MASK_HI 0x0040 /* hi on mask pin (47) stops conversions */
++#define WM9712_MASK_EDGE 0x0080 /* rising/falling edge on pin delays sample */
++#define WM9712_MASK_SYNC 0x00c0 /* rising/falling edge on mask initiates sample */
++#define WM9712_RPU(i) (i&0x3f) /* internal pull up on pen detect (64k / rpu) */
++#define WM9712_PD(i) (0x1 << i) /* power management */
++
++/* WM9712 Registers */
++#define AC97_WM9712_POWER 0x24
++#define AC97_WM9712_REV 0x58
++
++/* WM9705 Bits */
++#define WM9705_PDEN 0x1000 /* measure only when pen is down */
++#define WM9705_PINV 0x0800 /* inverts sense of pen down output */
++#define WM9705_BSEN 0x0400 /* BUSY flag enable, pin47 is 1 when busy */
++#define WM9705_BINV 0x0200 /* invert BUSY (pin47) output */
++#define WM9705_WAIT 0x0100 /* wait until adc is read before next sample */
++#define WM9705_PIL 0x0080 /* current used for pressure measurement. set 400uA else 200uA */
++#define WM9705_PHIZ 0x0040 /* set PHONE and PCBEEP inputs to high impedance */
++#define WM9705_MASK_HI 0x0010 /* hi on mask stops conversions */
++#define WM9705_MASK_EDGE 0x0020 /* rising/falling edge on pin delays sample */
++#define WM9705_MASK_SYNC 0x0030 /* rising/falling edge on mask initiates sample */
++#define WM9705_PDD(i) (i & 0x000f) /* pen detect comparator threshold */
++
++
++/* WM9713 Bits */
++#define WM9713_PDPOL 0x0400 /* Pen down polarity */
++#define WM9713_POLL 0x0200 /* initiate a polling measurement */
++#define WM9713_CTC 0x0100 /* enable continuous mode */
++#define WM9713_ADCSEL_X 0x0002 /* X measurement */
++#define WM9713_ADCSEL_Y 0x0004 /* Y measurement */
++#define WM9713_ADCSEL_PRES 0x0008 /* Pressure measurement */
++#define WM9713_COO 0x0001 /* enable coordinate mode */
++#define WM9713_PDEN 0x0800 /* measure only when pen down */
++#define WM9713_ADCSEL_MASK 0x00fe /* ADC selection mask */
++#define WM9713_WAIT 0x0200 /* coordinate wait */
++
++/* AUX ADC ID's */
++#define TS_COMP1 0x0
++#define TS_COMP2 0x1
++#define TS_BMON 0x2
++#define TS_WIPER 0x3
++
++/* ID numbers */
++#define WM97XX_ID1 0x574d
++#define WM9712_ID2 0x4c12
++#define WM9705_ID2 0x4c05
++#define WM9713_ID2 0x4c13
++
++/* Codec GPIO's */
++#define WM97XX_MAX_GPIO 16
++#define WM97XX_GPIO_1 (1 << 1)
++#define WM97XX_GPIO_2 (1 << 2)
++#define WM97XX_GPIO_3 (1 << 3)
++#define WM97XX_GPIO_4 (1 << 4)
++#define WM97XX_GPIO_5 (1 << 5)
++#define WM97XX_GPIO_6 (1 << 6)
++#define WM97XX_GPIO_7 (1 << 7)
++#define WM97XX_GPIO_8 (1 << 8)
++#define WM97XX_GPIO_9 (1 << 9)
++#define WM97XX_GPIO_10 (1 << 10)
++#define WM97XX_GPIO_11 (1 << 11)
++#define WM97XX_GPIO_12 (1 << 12)
++#define WM97XX_GPIO_13 (1 << 13)
++#define WM97XX_GPIO_14 (1 << 14)
++#define WM97XX_GPIO_15 (1 << 15)
++
++
++#define AC97_LINK_FRAME 21 /* time in uS for AC97 link frame */
++
++
++/*---------------- Return codes from sample reading functions ---------------*/
++
++/* More data is available; call the sample gathering function again */
++#define RC_AGAIN 0x00000001
++/* The returned sample is valid */
++#define RC_VALID 0x00000002
++/* The pen is up (the first RC_VALID without RC_PENUP means pen is down) */
++#define RC_PENUP 0x00000004
++/* The pen is down (RC_VALID implies RC_PENDOWN, but sometimes it is helpful
++ to tell the handler that the pen is down but we don't know yet his coords,
++ so the handler should not sleep or wait for pendown irq) */
++#define RC_PENDOWN 0x00000008
++
++/*
++ * The wm97xx driver provides a private API for writing platform-specific
++ * drivers.
++ */
++
++/* The structure used to return arch specific sampled data into */
++struct wm97xx_data {
++ int x;
++ int y;
++ int p;
++};
++
++/*
++ * Codec GPIO status
++ */
++enum wm97xx_gpio_status {
++ WM97XX_GPIO_HIGH,
++ WM97XX_GPIO_LOW
++};
++
++/*
++ * Codec GPIO direction
++ */
++enum wm97xx_gpio_dir {
++ WM97XX_GPIO_IN,
++ WM97XX_GPIO_OUT
++};
++
++/*
++ * Codec GPIO polarity
++ */
++enum wm97xx_gpio_pol {
++ WM97XX_GPIO_POL_HIGH,
++ WM97XX_GPIO_POL_LOW
++};
++
++/*
++ * Codec GPIO sticky
++ */
++enum wm97xx_gpio_sticky {
++ WM97XX_GPIO_STICKY,
++ WM97XX_GPIO_NOTSTICKY
++};
++
++/*
++ * Codec GPIO wake
++ */
++enum wm97xx_gpio_wake {
++ WM97XX_GPIO_WAKE,
++ WM97XX_GPIO_NOWAKE
++};
++
++/*
++ * Digitiser ioctl commands
++ */
++#define WM97XX_DIG_START 0x1
++#define WM97XX_DIG_STOP 0x2
++#define WM97XX_PHY_INIT 0x3
++#define WM97XX_AUX_PREPARE 0x4
++#define WM97XX_DIG_RESTORE 0x5
++
++struct wm97xx;
++
++extern struct wm97xx_codec_drv wm9705_codec;
++extern struct wm97xx_codec_drv wm9712_codec;
++extern struct wm97xx_codec_drv wm9713_codec;
++
++/*
++ * Codec driver interface - allows mapping to WM9705/12/13 and newer codecs
++ */
++struct wm97xx_codec_drv {
++ u16 id;
++ char *name;
++
++ /* read 1 sample */
++ int (*poll_sample) (struct wm97xx *, int adcsel, int *sample);
++
++ /* read X,Y,[P] in poll */
++ int (*poll_touch) (struct wm97xx *, struct wm97xx_data *);
++
++ int (*acc_enable) (struct wm97xx *, int enable);
++ void (*phy_init) (struct wm97xx *);
++ void (*dig_enable) (struct wm97xx *, int enable);
++ void (*dig_restore) (struct wm97xx *);
++ void (*aux_prepare) (struct wm97xx *);
++};
++
++
++/* Machine specific and accelerated touch operations */
++struct wm97xx_mach_ops {
++
++ /* accelerated touch readback - coords are transmited on AC97 link */
++ int acc_enabled;
++ void (*acc_pen_up) (struct wm97xx *);
++ int (*acc_pen_down) (struct wm97xx *);
++ int (*acc_startup) (struct wm97xx *);
++ void (*acc_shutdown) (struct wm97xx *);
++
++ /* interrupt mask control - required for accelerated operation */
++ void (*irq_enable) (struct wm97xx *, int enable);
++
++ /* GPIO pin used for accelerated operation */
++ int irq_gpio;
++
++ /* pre and post sample - can be used to minimise any analog noise */
++ void (*pre_sample) (int); /* function to run before sampling */
++ void (*post_sample) (int); /* function to run after sampling */
++};
++
++struct wm97xx {
++ u16 dig[3], id, gpio[6], misc; /* Cached codec registers */
++ u16 dig_save[3]; /* saved during aux reading */
++ struct wm97xx_codec_drv *codec; /* attached codec driver*/
++ struct input_dev *input_dev; /* touchscreen input device */
++ struct snd_ac97 *ac97; /* ALSA codec access */
++ struct device *dev; /* ALSA device */
++ struct platform_device *battery_dev;
++ struct platform_device *touch_dev;
++ struct wm97xx_mach_ops *mach_ops;
++ struct mutex codec_mutex;
++ struct delayed_work ts_reader; /* Used to poll touchscreen */
++ unsigned long ts_reader_interval; /* Current interval for timer */
++ unsigned long ts_reader_min_interval; /* Minimum interval */
++ unsigned int pen_irq; /* Pen IRQ number in use */
++ struct workqueue_struct *ts_workq;
++ struct work_struct pen_event_work;
++ u16 acc_slot; /* AC97 slot used for acc touch data */
++ u16 acc_rate; /* acc touch data rate */
++ unsigned pen_is_down:1; /* Pen is down */
++ unsigned aux_waiting:1; /* aux measurement waiting */
++ unsigned pen_probably_down:1; /* used in polling mode */
++ u16 suspend_mode; /* PRP in suspend mode */
++};
++
++/*
++ * Codec GPIO access (not supported on WM9705)
++ * This can be used to set/get codec GPIO and Virtual GPIO status.
++ */
++enum wm97xx_gpio_status wm97xx_get_gpio(struct wm97xx *wm, u32 gpio);
++void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio,
++ enum wm97xx_gpio_status status);
++void wm97xx_config_gpio(struct wm97xx *wm, u32 gpio,
++ enum wm97xx_gpio_dir dir,
++ enum wm97xx_gpio_pol pol,
++ enum wm97xx_gpio_sticky sticky,
++ enum wm97xx_gpio_wake wake);
++
++void wm97xx_set_suspend_mode(struct wm97xx *wm, u16 mode);
++
++/* codec AC97 IO access */
++int wm97xx_reg_read(struct wm97xx *wm, u16 reg);
++void wm97xx_reg_write(struct wm97xx *wm, u16 reg, u16 val);
++
++/* aux adc readback */
++int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel);
++
++/* machine ops */
++int wm97xx_register_mach_ops(struct wm97xx *, struct wm97xx_mach_ops *);
++void wm97xx_unregister_mach_ops(struct wm97xx *);
++
++#endif
+diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
+index e31b8c8..2ca6bae 100644
+--- a/include/linux/xfrm.h
++++ b/include/linux/xfrm.h
+@@ -97,10 +97,10 @@ struct xfrm_algo {
+ };
+
+ struct xfrm_algo_aead {
+- char alg_name[64];
+- int alg_key_len; /* in bits */
+- int alg_icv_len; /* in bits */
+- char alg_key[0];
++ char alg_name[64];
++ unsigned int alg_key_len; /* in bits */
++ unsigned int alg_icv_len; /* in bits */
++ char alg_key[0];
+ };
+
+ struct xfrm_stats {
+@@ -113,7 +113,8 @@ enum
+ {
+ XFRM_POLICY_TYPE_MAIN = 0,
+ XFRM_POLICY_TYPE_SUB = 1,
+- XFRM_POLICY_TYPE_MAX = 2
++ XFRM_POLICY_TYPE_MAX = 2,
++ XFRM_POLICY_TYPE_ANY = 255
+ };
+
+ enum
+diff --git a/include/media/ir-common.h b/include/media/ir-common.h
+index a427420..bfee8be 100644
+--- a/include/media/ir-common.h
++++ b/include/media/ir-common.h
+@@ -107,6 +107,7 @@ extern IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE];
+ extern IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE];
+ extern IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE];
+ extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE];
++extern IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE];
+ extern IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE];
+ extern IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE];
+ extern IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE];
+@@ -141,8 +142,10 @@ extern IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE];
+ extern IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE];
+ extern IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE];
+ extern IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE];
++extern IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE];
+ extern IR_KEYTAB_TYPE ir_codes_pinnacle_pctv_hd[IR_KEYTAB_SIZE];
+ extern IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE];
++extern IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE];
+
+ #endif
+
+diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
+new file mode 100644
+index 0000000..6a8c8be
+--- /dev/null
++++ b/include/media/soc_camera.h
+@@ -0,0 +1,179 @@
++/*
++ * camera image capture (abstract) bus driver header
++ *
++ * Copyright (C) 2006, Sascha Hauer, Pengutronix
++ * Copyright (C) 2008, Guennadi Liakhovetski <kernel at pengutronix.de>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef SOC_CAMERA_H
++#define SOC_CAMERA_H
++
++#include <linux/videodev2.h>
++#include <media/videobuf-dma-sg.h>
++
++struct soc_camera_device {
++ struct list_head list;
++ struct device dev;
++ struct device *control;
++ unsigned short width; /* Current window */
++ unsigned short height; /* sizes */
++ unsigned short x_min; /* Camera capabilities */
++ unsigned short y_min;
++ unsigned short x_current; /* Current window location */
++ unsigned short y_current;
++ unsigned short width_min;
++ unsigned short width_max;
++ unsigned short height_min;
++ unsigned short height_max;
++ unsigned short y_skip_top; /* Lines to skip at the top */
++ unsigned short gain;
++ unsigned short exposure;
++ unsigned char iface; /* Host number */
++ unsigned char devnum; /* Device number per host */
++ unsigned char buswidth; /* See comment in .c */
++ struct soc_camera_ops *ops;
++ struct video_device *vdev;
++ const struct soc_camera_data_format *current_fmt;
++ const struct soc_camera_data_format *formats;
++ int num_formats;
++ struct module *owner;
++ /* soc_camera.c private count. Only accessed with video_lock held */
++ int use_count;
++};
++
++struct soc_camera_file {
++ struct soc_camera_device *icd;
++ struct videobuf_queue vb_vidq;
++ spinlock_t *lock;
++};
++
++struct soc_camera_host {
++ struct list_head list;
++ struct device dev;
++ unsigned char nr; /* Host number */
++ size_t msize;
++ struct videobuf_queue_ops *vbq_ops;
++ void *priv;
++ char *drv_name;
++ struct soc_camera_host_ops *ops;
++};
++
++struct soc_camera_host_ops {
++ struct module *owner;
++ int (*add)(struct soc_camera_device *);
++ void (*remove)(struct soc_camera_device *);
++ int (*set_fmt_cap)(struct soc_camera_device *, __u32,
++ struct v4l2_rect *);
++ int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *);
++ int (*reqbufs)(struct soc_camera_file *, struct v4l2_requestbuffers *);
++ int (*querycap)(struct soc_camera_host *, struct v4l2_capability *);
++ int (*try_bus_param)(struct soc_camera_device *, __u32);
++ int (*set_bus_param)(struct soc_camera_device *, __u32);
++ unsigned int (*poll)(struct file *, poll_table *);
++ spinlock_t* (*spinlock_alloc)(struct soc_camera_file *);
++ void (*spinlock_free)(spinlock_t *);
++};
++
++struct soc_camera_link {
++ /* Camera bus id, used to match a camera and a bus */
++ int bus_id;
++ /* GPIO number to switch between 8 and 10 bit modes */
++ unsigned int gpio;
++};
++
++static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev)
++{
++ return container_of(dev, struct soc_camera_device, dev);
++}
++
++static inline struct soc_camera_host *to_soc_camera_host(struct device *dev)
++{
++ return container_of(dev, struct soc_camera_host, dev);
++}
++
++extern int soc_camera_host_register(struct soc_camera_host *ici);
++extern void soc_camera_host_unregister(struct soc_camera_host *ici);
++extern int soc_camera_device_register(struct soc_camera_device *icd);
++extern void soc_camera_device_unregister(struct soc_camera_device *icd);
++
++extern int soc_camera_video_start(struct soc_camera_device *icd);
++extern void soc_camera_video_stop(struct soc_camera_device *icd);
++
++struct soc_camera_data_format {
++ char *name;
++ unsigned int depth;
++ __u32 fourcc;
++ enum v4l2_colorspace colorspace;
++};
++
++struct soc_camera_ops {
++ struct module *owner;
++ int (*probe)(struct soc_camera_device *);
++ void (*remove)(struct soc_camera_device *);
++ int (*init)(struct soc_camera_device *);
++ int (*release)(struct soc_camera_device *);
++ int (*start_capture)(struct soc_camera_device *);
++ int (*stop_capture)(struct soc_camera_device *);
++ int (*set_fmt_cap)(struct soc_camera_device *, __u32,
++ struct v4l2_rect *);
++ int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *);
++ unsigned long (*query_bus_param)(struct soc_camera_device *);
++ int (*set_bus_param)(struct soc_camera_device *, unsigned long);
++ int (*get_chip_id)(struct soc_camera_device *,
++ struct v4l2_chip_ident *);
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++ int (*get_register)(struct soc_camera_device *, struct v4l2_register *);
++ int (*set_register)(struct soc_camera_device *, struct v4l2_register *);
++#endif
++ int (*get_control)(struct soc_camera_device *, struct v4l2_control *);
++ int (*set_control)(struct soc_camera_device *, struct v4l2_control *);
++ const struct v4l2_queryctrl *controls;
++ int num_controls;
++};
++
++static inline struct v4l2_queryctrl const *soc_camera_find_qctrl(
++ struct soc_camera_ops *ops, int id)
++{
++ int i;
++
++ for (i = 0; i < ops->num_controls; i++)
++ if (ops->controls[i].id == id)
++ return &ops->controls[i];
++
++ return NULL;
++}
++
++#define SOCAM_MASTER (1 << 0)
++#define SOCAM_SLAVE (1 << 1)
++#define SOCAM_HSYNC_ACTIVE_HIGH (1 << 2)
++#define SOCAM_HSYNC_ACTIVE_LOW (1 << 3)
++#define SOCAM_VSYNC_ACTIVE_HIGH (1 << 4)
++#define SOCAM_VSYNC_ACTIVE_LOW (1 << 5)
++#define SOCAM_DATAWIDTH_8 (1 << 6)
++#define SOCAM_DATAWIDTH_9 (1 << 7)
++#define SOCAM_DATAWIDTH_10 (1 << 8)
++#define SOCAM_PCLK_SAMPLE_RISING (1 << 9)
++#define SOCAM_PCLK_SAMPLE_FALLING (1 << 10)
++
++#define SOCAM_DATAWIDTH_MASK (SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_9 | \
++ SOCAM_DATAWIDTH_10)
++
++static inline unsigned long soc_camera_bus_param_compatible(
++ unsigned long camera_flags, unsigned long bus_flags)
++{
++ unsigned long common_flags, hsync, vsync, pclk;
++
++ common_flags = camera_flags & bus_flags;
++
++ hsync = common_flags & (SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW);
++ vsync = common_flags & (SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW);
++ pclk = common_flags & (SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING);
++
++ return (!hsync || !vsync || !pclk) ? 0 : common_flags;
++}
++
++#endif
+diff --git a/include/media/tuner-types.h b/include/media/tuner-types.h
+index b201371..ab03c53 100644
+--- a/include/media/tuner-types.h
++++ b/include/media/tuner-types.h
+@@ -6,10 +6,11 @@
+ #define __TUNER_TYPES_H__
+
+ enum param_type {
+- TUNER_PARAM_TYPE_RADIO, \
+- TUNER_PARAM_TYPE_PAL, \
+- TUNER_PARAM_TYPE_SECAM, \
+- TUNER_PARAM_TYPE_NTSC
++ TUNER_PARAM_TYPE_RADIO,
++ TUNER_PARAM_TYPE_PAL,
++ TUNER_PARAM_TYPE_SECAM,
++ TUNER_PARAM_TYPE_NTSC,
++ TUNER_PARAM_TYPE_DIGITAL,
+ };
+
+ struct tuner_range {
+@@ -105,6 +106,7 @@ struct tuner_params {
+ the SECAM-L/L' standards. Range: -16:+15 */
+ signed int default_top_secam_high:5;
+
++ u16 iffreq;
+
+ unsigned int count;
+ struct tuner_range *ranges;
+@@ -114,6 +116,13 @@ struct tunertype {
+ char *name;
+ unsigned int count;
+ struct tuner_params *params;
++
++ u16 min;
++ u16 max;
++ u32 stepsize;
++
++ u8 *initdata;
++ u8 *sleepdata;
+ };
+
+ extern struct tunertype tuners[];
+diff --git a/include/media/tuner.h b/include/media/tuner.h
+index 1bf24a6..77068fc 100644
+--- a/include/media/tuner.h
++++ b/include/media/tuner.h
+@@ -78,7 +78,7 @@
+
+ #define TUNER_HITACHI_NTSC 40
+ #define TUNER_PHILIPS_PAL_MK 41
+-#define TUNER_PHILIPS_ATSC 42
++#define TUNER_PHILIPS_FCV1236D 42
+ #define TUNER_PHILIPS_FM1236_MK3 43
+
+ #define TUNER_PHILIPS_4IN1 44 /* ATI TV Wonder Pro - Conexant */
+diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h
+index 032bb75..0ea0bd8 100644
+--- a/include/media/v4l2-chip-ident.h
++++ b/include/media/v4l2-chip-ident.h
+@@ -153,6 +153,12 @@ enum {
+ V4L2_IDENT_MSP4428G = 44287,
+ V4L2_IDENT_MSP4448G = 44487,
+ V4L2_IDENT_MSP4458G = 44587,
++
++ /* Micron CMOS sensor chips: 45000-45099 */
++ V4L2_IDENT_MT9M001C12ST = 45000,
++ V4L2_IDENT_MT9M001C12STM = 45005,
++ V4L2_IDENT_MT9V022IX7ATC = 45010, /* No way to detect "normal" I77ATx */
++ V4L2_IDENT_MT9V022IX7ATM = 45015, /* and "lead free" IA7ATx chips */
+ };
+
+ #endif
+diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
+index f211445..a807d2f 100644
+--- a/include/media/v4l2-dev.h
++++ b/include/media/v4l2-dev.h
+@@ -318,6 +318,10 @@ struct video_device
+ int (*vidioc_g_chip_ident) (struct file *file, void *fh,
+ struct v4l2_chip_ident *chip);
+
++ /* For other private ioctls */
++ int (*vidioc_default) (struct file *file, void *fh,
++ int cmd, void *arg);
++
+
+ #ifdef OBSOLETE_OWNER /* to be removed soon */
+ /* obsolete -- fops->owner is used instead */
+diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h
+index 9903394..5b39a22 100644
+--- a/include/media/videobuf-core.h
++++ b/include/media/videobuf-core.h
+@@ -13,6 +13,9 @@
+ * the Free Software Foundation; either version 2
+ */
+
++#ifndef _VIDEOBUF_CORE_H
++#define _VIDEOBUF_CORE_H
++
+ #include <linux/poll.h>
+ #ifdef CONFIG_VIDEO_V4L1_COMPAT
+ #include <linux/videodev.h>
+@@ -123,7 +126,8 @@ struct videobuf_queue_ops {
+ struct videobuf_qtype_ops {
+ u32 magic;
+
+- void* (*alloc) (size_t size);
++ void *(*alloc) (size_t size);
++ void *(*vmalloc) (struct videobuf_buffer *buf);
+ int (*iolock) (struct videobuf_queue* q,
+ struct videobuf_buffer *vb,
+ struct v4l2_framebuffer *fbuf);
+@@ -151,7 +155,9 @@ struct videobuf_qtype_ops {
+ struct videobuf_queue {
+ struct mutex vb_lock;
+ spinlock_t *irqlock;
+- void *dev; /* on pci, points to struct pci_dev */
++ struct device *dev;
++
++ wait_queue_head_t wait; /* wait if queue is empty */
+
+ enum v4l2_buf_type type;
+ unsigned int inputs; /* for V4L2_BUF_FLAG_INPUT */
+@@ -183,9 +189,13 @@ int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb,
+
+ void *videobuf_alloc(struct videobuf_queue* q);
+
++/* Used on videobuf-dvb */
++void *videobuf_queue_to_vmalloc (struct videobuf_queue* q,
++ struct videobuf_buffer *buf);
++
+ void videobuf_queue_core_init(struct videobuf_queue *q,
+ struct videobuf_queue_ops *ops,
+- void *dev,
++ struct device *dev,
+ spinlock_t *irqlock,
+ enum v4l2_buf_type type,
+ enum v4l2_field field,
+@@ -231,10 +241,4 @@ int videobuf_mmap_free(struct videobuf_queue *q);
+ int videobuf_mmap_mapper(struct videobuf_queue *q,
+ struct vm_area_struct *vma);
+
+-/* --------------------------------------------------------------------- */
+-
+-/*
+- * Local variables:
+- * c-basic-offset: 8
+- * End:
+- */
++#endif
+diff --git a/include/media/videobuf-dma-sg.h b/include/media/videobuf-dma-sg.h
+index 3810503..be8da26 100644
+--- a/include/media/videobuf-dma-sg.h
++++ b/include/media/videobuf-dma-sg.h
+@@ -1,5 +1,5 @@
+ /*
+- * helper functions for PCI DMA video4linux capture buffers
++ * helper functions for SG DMA video4linux capture buffers
+ *
+ * The functions expect the hardware being able to scatter gatter
+ * (i.e. the buffers are not linear in physical memory, but fragmented
+@@ -68,9 +68,6 @@ struct videobuf_dmabuf {
+ /* for kernel buffers */
+ void *vmalloc;
+
+- /* Stores the userspace pointer to vmalloc area */
+- void *varea;
+-
+ /* for overlay buffers (pci-pci dma) */
+ dma_addr_t bus_addr;
+
+@@ -81,7 +78,7 @@ struct videobuf_dmabuf {
+ int direction;
+ };
+
+-struct videbuf_pci_sg_memory
++struct videobuf_dma_sg_memory
+ {
+ u32 magic;
+
+@@ -103,11 +100,11 @@ int videobuf_dma_sync(struct videobuf_queue* q,struct videobuf_dmabuf *dma);
+ int videobuf_dma_unmap(struct videobuf_queue* q,struct videobuf_dmabuf *dma);
+ struct videobuf_dmabuf *videobuf_to_dma (struct videobuf_buffer *buf);
+
+-void *videobuf_pci_alloc (size_t size);
++void *videobuf_sg_alloc(size_t size);
+
+-void videobuf_queue_pci_init(struct videobuf_queue* q,
++void videobuf_queue_sg_init(struct videobuf_queue* q,
+ struct videobuf_queue_ops *ops,
+- void *dev,
++ struct device *dev,
+ spinlock_t *irqlock,
+ enum v4l2_buf_type type,
+ enum v4l2_field field,
+@@ -117,6 +114,6 @@ void videobuf_queue_pci_init(struct videobuf_queue* q,
+ /*FIXME: these variants are used only on *-alsa code, where videobuf is
+ * used without queue
+ */
+-int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma);
+-int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma);
++int videobuf_sg_dma_map(struct device *dev, struct videobuf_dmabuf *dma);
++int videobuf_sg_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma);
+
+diff --git a/include/media/videobuf-dvb.h b/include/media/videobuf-dvb.h
+index 8233caf..b777486 100644
+--- a/include/media/videobuf-dvb.h
++++ b/include/media/videobuf-dvb.h
+@@ -27,7 +27,8 @@ struct videobuf_dvb {
+ int videobuf_dvb_register(struct videobuf_dvb *dvb,
+ struct module *module,
+ void *adapter_priv,
+- struct device *device);
++ struct device *device,
++ short *adapter_nr);
+ void videobuf_dvb_unregister(struct videobuf_dvb *dvb);
+
+ /*
+diff --git a/include/media/videobuf-vmalloc.h b/include/media/videobuf-vmalloc.h
+index ec63ab0..aed3946 100644
+--- a/include/media/videobuf-vmalloc.h
++++ b/include/media/videobuf-vmalloc.h
+@@ -12,6 +12,8 @@
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2
+ */
++#ifndef _VIDEOBUF_VMALLOC_H
++#define _VIDEOBUF_VMALLOC_H
+
+ #include <media/videobuf-core.h>
+
+@@ -39,3 +41,5 @@ void videobuf_queue_vmalloc_init(struct videobuf_queue* q,
+ void *videobuf_to_vmalloc (struct videobuf_buffer *buf);
+
+ void videobuf_vmalloc_free (struct videobuf_buffer *buf);
++
++#endif
+diff --git a/include/mtd/Kbuild b/include/mtd/Kbuild
+index 4d46b3b..8eb018f 100644
+--- a/include/mtd/Kbuild
++++ b/include/mtd/Kbuild
+@@ -3,5 +3,4 @@ header-y += jffs2-user.h
+ header-y += mtd-abi.h
+ header-y += mtd-user.h
+ header-y += nftl-user.h
+-header-y += ubi-header.h
+ header-y += ubi-user.h
+diff --git a/include/mtd/ubi-header.h b/include/mtd/ubi-header.h
+deleted file mode 100644
+index 292f916..0000000
+--- a/include/mtd/ubi-header.h
++++ /dev/null
+@@ -1,372 +0,0 @@
+-/*
+- * Copyright (c) International Business Machines Corp., 2006
+- *
+- * 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
+- *
+- * Authors: Artem Bityutskiy (ÐиÑÑÑкий ÐÑÑÑм)
+- * Thomas Gleixner
+- * Frank Haverkamp
+- * Oliver Lohmann
+- * Andreas Arnez
+- */
+-
+-/*
+- * This file defines the layout of UBI headers and all the other UBI on-flash
+- * data structures. May be included by user-space.
+- */
+-
+-#ifndef __UBI_HEADER_H__
+-#define __UBI_HEADER_H__
+-
+-#include <asm/byteorder.h>
+-
+-/* The version of UBI images supported by this implementation */
+-#define UBI_VERSION 1
+-
+-/* The highest erase counter value supported by this implementation */
+-#define UBI_MAX_ERASECOUNTER 0x7FFFFFFF
+-
+-/* The initial CRC32 value used when calculating CRC checksums */
+-#define UBI_CRC32_INIT 0xFFFFFFFFU
+-
+-/* Erase counter header magic number (ASCII "UBI#") */
+-#define UBI_EC_HDR_MAGIC 0x55424923
+-/* Volume identifier header magic number (ASCII "UBI!") */
+-#define UBI_VID_HDR_MAGIC 0x55424921
+-
+-/*
+- * Volume type constants used in the volume identifier header.
+- *
+- * @UBI_VID_DYNAMIC: dynamic volume
+- * @UBI_VID_STATIC: static volume
+- */
+-enum {
+- UBI_VID_DYNAMIC = 1,
+- UBI_VID_STATIC = 2
+-};
+-
+-/*
+- * Volume flags used in the volume table record.
+- *
+- * @UBI_VTBL_AUTORESIZE_FLG: auto-resize this volume
+- *
+- * %UBI_VTBL_AUTORESIZE_FLG flag can be set only for one volume in the volume
+- * table. UBI automatically re-sizes the volume which has this flag and makes
+- * the volume to be of largest possible size. This means that if after the
+- * initialization UBI finds out that there are available physical eraseblocks
+- * present on the device, it automatically appends all of them to the volume
+- * (the physical eraseblocks reserved for bad eraseblocks handling and other
+- * reserved physical eraseblocks are not taken). So, if there is a volume with
+- * the %UBI_VTBL_AUTORESIZE_FLG flag set, the amount of available logical
+- * eraseblocks will be zero after UBI is loaded, because all of them will be
+- * reserved for this volume. Note, the %UBI_VTBL_AUTORESIZE_FLG bit is cleared
+- * after the volume had been initialized.
+- *
+- * The auto-resize feature is useful for device production purposes. For
+- * example, different NAND flash chips may have different amount of initial bad
+- * eraseblocks, depending of particular chip instance. Manufacturers of NAND
+- * chips usually guarantee that the amount of initial bad eraseblocks does not
+- * exceed certain percent, e.g. 2%. When one creates an UBI image which will be
+- * flashed to the end devices in production, he does not know the exact amount
+- * of good physical eraseblocks the NAND chip on the device will have, but this
+- * number is required to calculate the volume sized and put them to the volume
+- * table of the UBI image. In this case, one of the volumes (e.g., the one
+- * which will store the root file system) is marked as "auto-resizable", and
+- * UBI will adjust its size on the first boot if needed.
+- *
+- * Note, first UBI reserves some amount of physical eraseblocks for bad
+- * eraseblock handling, and then re-sizes the volume, not vice-versa. This
+- * means that the pool of reserved physical eraseblocks will always be present.
+- */
+-enum {
+- UBI_VTBL_AUTORESIZE_FLG = 0x01,
+-};
+-
+-/*
+- * Compatibility constants used by internal volumes.
+- *
+- * @UBI_COMPAT_DELETE: delete this internal volume before anything is written
+- * to the flash
+- * @UBI_COMPAT_RO: attach this device in read-only mode
+- * @UBI_COMPAT_PRESERVE: preserve this internal volume - do not touch its
+- * physical eraseblocks, don't allow the wear-leveling unit to move them
+- * @UBI_COMPAT_REJECT: reject this UBI image
+- */
+-enum {
+- UBI_COMPAT_DELETE = 1,
+- UBI_COMPAT_RO = 2,
+- UBI_COMPAT_PRESERVE = 4,
+- UBI_COMPAT_REJECT = 5
+-};
+-
+-/* Sizes of UBI headers */
+-#define UBI_EC_HDR_SIZE sizeof(struct ubi_ec_hdr)
+-#define UBI_VID_HDR_SIZE sizeof(struct ubi_vid_hdr)
+-
+-/* Sizes of UBI headers without the ending CRC */
+-#define UBI_EC_HDR_SIZE_CRC (UBI_EC_HDR_SIZE - sizeof(__be32))
+-#define UBI_VID_HDR_SIZE_CRC (UBI_VID_HDR_SIZE - sizeof(__be32))
+-
+-/**
+- * struct ubi_ec_hdr - UBI erase counter header.
+- * @magic: erase counter header magic number (%UBI_EC_HDR_MAGIC)
+- * @version: version of UBI implementation which is supposed to accept this
+- * UBI image
+- * @padding1: reserved for future, zeroes
+- * @ec: the erase counter
+- * @vid_hdr_offset: where the VID header starts
+- * @data_offset: where the user data start
+- * @padding2: reserved for future, zeroes
+- * @hdr_crc: erase counter header CRC checksum
+- *
+- * The erase counter header takes 64 bytes and has a plenty of unused space for
+- * future usage. The unused fields are zeroed. The @version field is used to
+- * indicate the version of UBI implementation which is supposed to be able to
+- * work with this UBI image. If @version is greater then the current UBI
+- * version, the image is rejected. This may be useful in future if something
+- * is changed radically. This field is duplicated in the volume identifier
+- * header.
+- *
+- * The @vid_hdr_offset and @data_offset fields contain the offset of the the
+- * volume identifier header and user data, relative to the beginning of the
+- * physical eraseblock. These values have to be the same for all physical
+- * eraseblocks.
+- */
+-struct ubi_ec_hdr {
+- __be32 magic;
+- __u8 version;
+- __u8 padding1[3];
+- __be64 ec; /* Warning: the current limit is 31-bit anyway! */
+- __be32 vid_hdr_offset;
+- __be32 data_offset;
+- __u8 padding2[36];
+- __be32 hdr_crc;
+-} __attribute__ ((packed));
+-
+-/**
+- * struct ubi_vid_hdr - on-flash UBI volume identifier header.
+- * @magic: volume identifier header magic number (%UBI_VID_HDR_MAGIC)
+- * @version: UBI implementation version which is supposed to accept this UBI
+- * image (%UBI_VERSION)
+- * @vol_type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC)
+- * @copy_flag: if this logical eraseblock was copied from another physical
+- * eraseblock (for wear-leveling reasons)
+- * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE,
+- * %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT)
+- * @vol_id: ID of this volume
+- * @lnum: logical eraseblock number
+- * @leb_ver: version of this logical eraseblock (IMPORTANT: obsolete, to be
+- * removed, kept only for not breaking older UBI users)
+- * @data_size: how many bytes of data this logical eraseblock contains
+- * @used_ebs: total number of used logical eraseblocks in this volume
+- * @data_pad: how many bytes at the end of this physical eraseblock are not
+- * used
+- * @data_crc: CRC checksum of the data stored in this logical eraseblock
+- * @padding1: reserved for future, zeroes
+- * @sqnum: sequence number
+- * @padding2: reserved for future, zeroes
+- * @hdr_crc: volume identifier header CRC checksum
+- *
+- * The @sqnum is the value of the global sequence counter at the time when this
+- * VID header was created. The global sequence counter is incremented each time
+- * UBI writes a new VID header to the flash, i.e. when it maps a logical
+- * eraseblock to a new physical eraseblock. The global sequence counter is an
+- * unsigned 64-bit integer and we assume it never overflows. The @sqnum
+- * (sequence number) is used to distinguish between older and newer versions of
+- * logical eraseblocks.
+- *
+- * There are 2 situations when there may be more then one physical eraseblock
+- * corresponding to the same logical eraseblock, i.e., having the same @vol_id
+- * and @lnum values in the volume identifier header. Suppose we have a logical
+- * eraseblock L and it is mapped to the physical eraseblock P.
+- *
+- * 1. Because UBI may erase physical eraseblocks asynchronously, the following
+- * situation is possible: L is asynchronously erased, so P is scheduled for
+- * erasure, then L is written to,i.e. mapped to another physical eraseblock P1,
+- * so P1 is written to, then an unclean reboot happens. Result - there are 2
+- * physical eraseblocks P and P1 corresponding to the same logical eraseblock
+- * L. But P1 has greater sequence number, so UBI picks P1 when it attaches the
+- * flash.
+- *
+- * 2. From time to time UBI moves logical eraseblocks to other physical
+- * eraseblocks for wear-leveling reasons. If, for example, UBI moves L from P
+- * to P1, and an unclean reboot happens before P is physically erased, there
+- * are two physical eraseblocks P and P1 corresponding to L and UBI has to
+- * select one of them when the flash is attached. The @sqnum field says which
+- * PEB is the original (obviously P will have lower @sqnum) and the copy. But
+- * it is not enough to select the physical eraseblock with the higher sequence
+- * number, because the unclean reboot could have happen in the middle of the
+- * copying process, so the data in P is corrupted. It is also not enough to
+- * just select the physical eraseblock with lower sequence number, because the
+- * data there may be old (consider a case if more data was added to P1 after
+- * the copying). Moreover, the unclean reboot may happen when the erasure of P
+- * was just started, so it result in unstable P, which is "mostly" OK, but
+- * still has unstable bits.
+- *
+- * UBI uses the @copy_flag field to indicate that this logical eraseblock is a
+- * copy. UBI also calculates data CRC when the data is moved and stores it at
+- * the @data_crc field of the copy (P1). So when UBI needs to pick one physical
+- * eraseblock of two (P or P1), the @copy_flag of the newer one (P1) is
+- * examined. If it is cleared, the situation* is simple and the newer one is
+- * picked. If it is set, the data CRC of the copy (P1) is examined. If the CRC
+- * checksum is correct, this physical eraseblock is selected (P1). Otherwise
+- * the older one (P) is selected.
+- *
+- * Note, there is an obsolete @leb_ver field which was used instead of @sqnum
+- * in the past. But it is not used anymore and we keep it in order to be able
+- * to deal with old UBI images. It will be removed at some point.
+- *
+- * There are 2 sorts of volumes in UBI: user volumes and internal volumes.
+- * Internal volumes are not seen from outside and are used for various internal
+- * UBI purposes. In this implementation there is only one internal volume - the
+- * layout volume. Internal volumes are the main mechanism of UBI extensions.
+- * For example, in future one may introduce a journal internal volume. Internal
+- * volumes have their own reserved range of IDs.
+- *
+- * The @compat field is only used for internal volumes and contains the "degree
+- * of their compatibility". It is always zero for user volumes. This field
+- * provides a mechanism to introduce UBI extensions and to be still compatible
+- * with older UBI binaries. For example, if someone introduced a journal in
+- * future, he would probably use %UBI_COMPAT_DELETE compatibility for the
+- * journal volume. And in this case, older UBI binaries, which know nothing
+- * about the journal volume, would just delete this volume and work perfectly
+- * fine. This is similar to what Ext2fs does when it is fed by an Ext3fs image
+- * - it just ignores the Ext3fs journal.
+- *
+- * The @data_crc field contains the CRC checksum of the contents of the logical
+- * eraseblock if this is a static volume. In case of dynamic volumes, it does
+- * not contain the CRC checksum as a rule. The only exception is when the
+- * data of the physical eraseblock was moved by the wear-leveling unit, then
+- * the wear-leveling unit calculates the data CRC and stores it in the
+- * @data_crc field. And of course, the @copy_flag is %in this case.
+- *
+- * The @data_size field is used only for static volumes because UBI has to know
+- * how many bytes of data are stored in this eraseblock. For dynamic volumes,
+- * this field usually contains zero. The only exception is when the data of the
+- * physical eraseblock was moved to another physical eraseblock for
+- * wear-leveling reasons. In this case, UBI calculates CRC checksum of the
+- * contents and uses both @data_crc and @data_size fields. In this case, the
+- * @data_size field contains data size.
+- *
+- * The @used_ebs field is used only for static volumes and indicates how many
+- * eraseblocks the data of the volume takes. For dynamic volumes this field is
+- * not used and always contains zero.
+- *
+- * The @data_pad is calculated when volumes are created using the alignment
+- * parameter. So, effectively, the @data_pad field reduces the size of logical
+- * eraseblocks of this volume. This is very handy when one uses block-oriented
+- * software (say, cramfs) on top of the UBI volume.
+- */
+-struct ubi_vid_hdr {
+- __be32 magic;
+- __u8 version;
+- __u8 vol_type;
+- __u8 copy_flag;
+- __u8 compat;
+- __be32 vol_id;
+- __be32 lnum;
+- __be32 leb_ver; /* obsolete, to be removed, don't use */
+- __be32 data_size;
+- __be32 used_ebs;
+- __be32 data_pad;
+- __be32 data_crc;
+- __u8 padding1[4];
+- __be64 sqnum;
+- __u8 padding2[12];
+- __be32 hdr_crc;
+-} __attribute__ ((packed));
+-
+-/* Internal UBI volumes count */
+-#define UBI_INT_VOL_COUNT 1
+-
+-/*
+- * Starting ID of internal volumes. There is reserved room for 4096 internal
+- * volumes.
+- */
+-#define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096)
+-
+-/* The layout volume contains the volume table */
+-
+-#define UBI_LAYOUT_VOLUME_ID UBI_INTERNAL_VOL_START
+-#define UBI_LAYOUT_VOLUME_TYPE UBI_VID_DYNAMIC
+-#define UBI_LAYOUT_VOLUME_ALIGN 1
+-#define UBI_LAYOUT_VOLUME_EBS 2
+-#define UBI_LAYOUT_VOLUME_NAME "layout volume"
+-#define UBI_LAYOUT_VOLUME_COMPAT UBI_COMPAT_REJECT
+-
+-/* The maximum number of volumes per one UBI device */
+-#define UBI_MAX_VOLUMES 128
+-
+-/* The maximum volume name length */
+-#define UBI_VOL_NAME_MAX 127
+-
+-/* Size of the volume table record */
+-#define UBI_VTBL_RECORD_SIZE sizeof(struct ubi_vtbl_record)
+-
+-/* Size of the volume table record without the ending CRC */
+-#define UBI_VTBL_RECORD_SIZE_CRC (UBI_VTBL_RECORD_SIZE - sizeof(__be32))
+-
+-/**
+- * struct ubi_vtbl_record - a record in the volume table.
+- * @reserved_pebs: how many physical eraseblocks are reserved for this volume
+- * @alignment: volume alignment
+- * @data_pad: how many bytes are unused at the end of the each physical
+- * eraseblock to satisfy the requested alignment
+- * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
+- * @upd_marker: if volume update was started but not finished
+- * @name_len: volume name length
+- * @name: the volume name
+- * @flags: volume flags (%UBI_VTBL_AUTORESIZE_FLG)
+- * @padding: reserved, zeroes
+- * @crc: a CRC32 checksum of the record
+- *
+- * The volume table records are stored in the volume table, which is stored in
+- * the layout volume. The layout volume consists of 2 logical eraseblock, each
+- * of which contains a copy of the volume table (i.e., the volume table is
+- * duplicated). The volume table is an array of &struct ubi_vtbl_record
+- * objects indexed by the volume ID.
+- *
+- * If the size of the logical eraseblock is large enough to fit
+- * %UBI_MAX_VOLUMES records, the volume table contains %UBI_MAX_VOLUMES
+- * records. Otherwise, it contains as many records as it can fit (i.e., size of
+- * logical eraseblock divided by sizeof(struct ubi_vtbl_record)).
+- *
+- * The @upd_marker flag is used to implement volume update. It is set to %1
+- * before update and set to %0 after the update. So if the update operation was
+- * interrupted, UBI knows that the volume is corrupted.
+- *
+- * The @alignment field is specified when the volume is created and cannot be
+- * later changed. It may be useful, for example, when a block-oriented file
+- * system works on top of UBI. The @data_pad field is calculated using the
+- * logical eraseblock size and @alignment. The alignment must be multiple to the
+- * minimal flash I/O unit. If @alignment is 1, all the available space of
+- * the physical eraseblocks is used.
+- *
+- * Empty records contain all zeroes and the CRC checksum of those zeroes.
+- */
+-struct ubi_vtbl_record {
+- __be32 reserved_pebs;
+- __be32 alignment;
+- __be32 data_pad;
+- __u8 vol_type;
+- __u8 upd_marker;
+- __be16 name_len;
+- __u8 name[UBI_VOL_NAME_MAX+1];
+- __u8 flags;
+- __u8 padding[23];
+- __be32 crc;
+-} __attribute__ ((packed));
+-
+-#endif /* !__UBI_HEADER_H__ */
+diff --git a/include/net/addrconf.h b/include/net/addrconf.h
+index 496503c..0a2f037 100644
+--- a/include/net/addrconf.h
++++ b/include/net/addrconf.h
+@@ -55,9 +55,12 @@ struct prefix_info {
+ extern int addrconf_init(void);
+ extern void addrconf_cleanup(void);
+
+-extern int addrconf_add_ifaddr(void __user *arg);
+-extern int addrconf_del_ifaddr(void __user *arg);
+-extern int addrconf_set_dstaddr(void __user *arg);
++extern int addrconf_add_ifaddr(struct net *net,
++ void __user *arg);
++extern int addrconf_del_ifaddr(struct net *net,
++ void __user *arg);
++extern int addrconf_set_dstaddr(struct net *net,
++ void __user *arg);
+
+ extern int ipv6_chk_addr(struct net *net,
+ struct in6_addr *addr,
+@@ -68,16 +71,18 @@ extern int ipv6_chk_addr(struct net *net,
+ extern int ipv6_chk_home_addr(struct net *net,
+ struct in6_addr *addr);
+ #endif
++
++extern int ipv6_chk_prefix(struct in6_addr *addr,
++ struct net_device *dev);
++
+ extern struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net,
+- struct in6_addr *addr,
++ const struct in6_addr *addr,
+ struct net_device *dev,
+ int strict);
+
+-extern int ipv6_get_saddr(struct dst_entry *dst,
+- struct in6_addr *daddr,
+- struct in6_addr *saddr);
+ extern int ipv6_dev_get_saddr(struct net_device *dev,
+- struct in6_addr *daddr,
++ const struct in6_addr *daddr,
++ unsigned int srcprefs,
+ struct in6_addr *saddr);
+ extern int ipv6_get_lladdr(struct net_device *dev,
+ struct in6_addr *addr,
+@@ -100,31 +105,31 @@ extern u32 ipv6_addr_label(const struct in6_addr *addr,
+ /*
+ * multicast prototypes (mcast.c)
+ */
+-extern int ipv6_sock_mc_join(struct sock *sk, int ifindex,
+- struct in6_addr *addr);
+-extern int ipv6_sock_mc_drop(struct sock *sk, int ifindex,
+- struct in6_addr *addr);
++extern int ipv6_sock_mc_join(struct sock *sk, int ifindex,
++ const struct in6_addr *addr);
++extern int ipv6_sock_mc_drop(struct sock *sk, int ifindex,
++ const struct in6_addr *addr);
+ extern void ipv6_sock_mc_close(struct sock *sk);
+-extern int inet6_mc_check(struct sock *sk, struct in6_addr *mc_addr,
+- struct in6_addr *src_addr);
++extern int inet6_mc_check(struct sock *sk,
++ const struct in6_addr *mc_addr,
++ const struct in6_addr *src_addr);
+
+-extern int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr);
+-extern int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr);
+-extern int ipv6_dev_mc_dec(struct net_device *dev, struct in6_addr *addr);
++extern int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr);
++extern int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr);
++extern int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr);
+ extern void ipv6_mc_up(struct inet6_dev *idev);
+ extern void ipv6_mc_down(struct inet6_dev *idev);
+ extern void ipv6_mc_init_dev(struct inet6_dev *idev);
+ extern void ipv6_mc_destroy_dev(struct inet6_dev *idev);
+ extern void addrconf_dad_failure(struct inet6_ifaddr *ifp);
+
+-extern int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *group,
+- struct in6_addr *src_addr);
++extern int ipv6_chk_mcast_addr(struct net_device *dev,
++ const struct in6_addr *group,
++ const struct in6_addr *src_addr);
+ extern int ipv6_is_mld(struct sk_buff *skb, int nexthdr);
+
+ extern void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len);
+
+-extern int ipv6_get_hoplimit(struct net_device *dev);
+-
+ /*
+ * anycast prototypes (anycast.c)
+ */
+@@ -135,7 +140,8 @@ extern int inet6_ac_check(struct sock *sk, struct in6_addr *addr, int ifindex);
+
+ extern int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr);
+ extern int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr);
+-extern int ipv6_chk_acast_addr(struct net_device *dev, struct in6_addr *addr);
++extern int ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
++ struct in6_addr *addr);
+
+
+ /* Device notifier */
+@@ -185,26 +191,6 @@ static inline void in6_ifa_put(struct inet6_ifaddr *ifp)
+ #define in6_ifa_hold(ifp) atomic_inc(&(ifp)->refcnt)
+
+
+-extern void addrconf_forwarding_on(void);
+-/*
+- * Hash function taken from net_alias.c
+- */
+-
+-static __inline__ u8 ipv6_addr_hash(const struct in6_addr *addr)
+-{
+- __u32 word;
+-
+- /*
+- * We perform the hash function over the last 64 bits of the address
+- * This will include the IEEE address token on links that support it.
+- */
+-
+- word = (__force u32)(addr->s6_addr32[2] ^ addr->s6_addr32[3]);
+- word ^= (word >> 16);
+- word ^= (word >> 8);
+-
+- return ((word ^ (word >> 4)) & 0x0f);
+-}
+
+ /*
+ * compute link-local solicited-node multicast address
+@@ -214,61 +200,31 @@ static inline void addrconf_addr_solict_mult(const struct in6_addr *addr,
+ struct in6_addr *solicited)
+ {
+ ipv6_addr_set(solicited,
+- __constant_htonl(0xFF020000), 0,
+- __constant_htonl(0x1),
+- __constant_htonl(0xFF000000) | addr->s6_addr32[3]);
+-}
+-
+-
+-static inline void ipv6_addr_all_nodes(struct in6_addr *addr)
+-{
+- ipv6_addr_set(addr,
+- __constant_htonl(0xFF020000), 0, 0,
+- __constant_htonl(0x1));
+-}
+-
+-static inline void ipv6_addr_all_routers(struct in6_addr *addr)
+-{
+- ipv6_addr_set(addr,
+- __constant_htonl(0xFF020000), 0, 0,
+- __constant_htonl(0x2));
++ htonl(0xFF020000), 0,
++ htonl(0x1),
++ htonl(0xFF000000) | addr->s6_addr32[3]);
+ }
+
+ static inline int ipv6_addr_is_multicast(const struct in6_addr *addr)
+ {
+- return (addr->s6_addr32[0] & __constant_htonl(0xFF000000)) == __constant_htonl(0xFF000000);
++ return (addr->s6_addr32[0] & htonl(0xFF000000)) == htonl(0xFF000000);
+ }
+
+ static inline int ipv6_addr_is_ll_all_nodes(const struct in6_addr *addr)
+ {
+- return (addr->s6_addr32[0] == htonl(0xff020000) &&
+- addr->s6_addr32[1] == 0 &&
+- addr->s6_addr32[2] == 0 &&
+- addr->s6_addr32[3] == htonl(0x00000001));
++ return (((addr->s6_addr32[0] ^ htonl(0xff020000)) |
++ addr->s6_addr32[1] | addr->s6_addr32[2] |
++ (addr->s6_addr32[3] ^ htonl(0x00000001))) == 0);
+ }
+
+ static inline int ipv6_addr_is_ll_all_routers(const struct in6_addr *addr)
+ {
+- return (addr->s6_addr32[0] == htonl(0xff020000) &&
+- addr->s6_addr32[1] == 0 &&
+- addr->s6_addr32[2] == 0 &&
+- addr->s6_addr32[3] == htonl(0x00000002));
++ return (((addr->s6_addr32[0] ^ htonl(0xff020000)) |
++ addr->s6_addr32[1] | addr->s6_addr32[2] |
++ (addr->s6_addr32[3] ^ htonl(0x00000002))) == 0);
+ }
+
+-static inline int ipv6_isatap_eui64(u8 *eui, __be32 addr)
+-{
+- eui[0] = (ipv4_is_zeronet(addr) || ipv4_is_private_10(addr) ||
+- ipv4_is_loopback(addr) || ipv4_is_linklocal_169(addr) ||
+- ipv4_is_private_172(addr) || ipv4_is_test_192(addr) ||
+- ipv4_is_anycast_6to4(addr) || ipv4_is_private_192(addr) ||
+- ipv4_is_test_198(addr) || ipv4_is_multicast(addr) ||
+- ipv4_is_lbcast(addr)) ? 0x00 : 0x02;
+- eui[1] = 0;
+- eui[2] = 0x5E;
+- eui[3] = 0xFE;
+- memcpy (eui+4, &addr, 4);
+- return 0;
+-}
++extern int __ipv6_isatap_ifid(u8 *eui, __be32 addr);
+
+ static inline int ipv6_addr_is_isatap(const struct in6_addr *addr)
+ {
+diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
+index bcc480b..e007508 100644
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -12,6 +12,16 @@
+ * Copyright 2006, 2007 Johannes Berg <johannes at sipsolutions.net>
+ */
+
++/**
++ * struct vif_params - describes virtual interface parameters
++ * @mesh_id: mesh ID to use
++ * @mesh_id_len: length of the mesh ID
++ */
++struct vif_params {
++ u8 *mesh_id;
++ int mesh_id_len;
++};
++
+ /* Radiotap header iteration
+ * implemented in net/wireless/radiotap.c
+ * docs in Documentation/networking/radiotap-headers.txt
+@@ -109,6 +119,19 @@ enum station_flags {
+ };
+
+ /**
++ * enum plink_action - actions to perform in mesh peers
++ *
++ * @PLINK_ACTION_INVALID: action 0 is reserved
++ * @PLINK_ACTION_OPEN: start mesh peer link establishment
++ * @PLINK_ACTION_BLOCL: block traffic from this mesh peer
++ */
++enum plink_actions {
++ PLINK_ACTION_INVALID,
++ PLINK_ACTION_OPEN,
++ PLINK_ACTION_BLOCK,
++};
++
++/**
+ * struct station_parameters - station parameters
+ *
+ * Used to change and create a new station.
+@@ -128,41 +151,124 @@ struct station_parameters {
+ int listen_interval;
+ u16 aid;
+ u8 supported_rates_len;
++ u8 plink_action;
+ };
+
+ /**
+- * enum station_stats_flags - station statistics flags
++ * enum station_info_flags - station information flags
+ *
+- * Used by the driver to indicate which info in &struct station_stats
+- * it has filled in during get_station().
++ * Used by the driver to indicate which info in &struct station_info
++ * it has filled in during get_station() or dump_station().
+ *
+- * @STATION_STAT_INACTIVE_TIME: @inactive_time filled
+- * @STATION_STAT_RX_BYTES: @rx_bytes filled
+- * @STATION_STAT_TX_BYTES: @tx_bytes filled
++ * @STATION_INFO_INACTIVE_TIME: @inactive_time filled
++ * @STATION_INFO_RX_BYTES: @rx_bytes filled
++ * @STATION_INFO_TX_BYTES: @tx_bytes filled
++ * @STATION_INFO_LLID: @llid filled
++ * @STATION_INFO_PLID: @plid filled
++ * @STATION_INFO_PLINK_STATE: @plink_state filled
+ */
+-enum station_stats_flags {
+- STATION_STAT_INACTIVE_TIME = 1<<0,
+- STATION_STAT_RX_BYTES = 1<<1,
+- STATION_STAT_TX_BYTES = 1<<2,
++enum station_info_flags {
++ STATION_INFO_INACTIVE_TIME = 1<<0,
++ STATION_INFO_RX_BYTES = 1<<1,
++ STATION_INFO_TX_BYTES = 1<<2,
++ STATION_INFO_LLID = 1<<3,
++ STATION_INFO_PLID = 1<<4,
++ STATION_INFO_PLINK_STATE = 1<<5,
+ };
+
+ /**
+- * struct station_stats - station statistics
++ * struct station_info - station information
+ *
+- * Station information filled by driver for get_station().
++ * Station information filled by driver for get_station() and dump_station.
+ *
+- * @filled: bitflag of flags from &enum station_stats_flags
++ * @filled: bitflag of flags from &enum station_info_flags
+ * @inactive_time: time since last station activity (tx/rx) in milliseconds
+ * @rx_bytes: bytes received from this station
+ * @tx_bytes: bytes transmitted to this station
++ * @llid: mesh local link id
++ * @plid: mesh peer link id
++ * @plink_state: mesh peer link state
+ */
+-struct station_stats {
++struct station_info {
+ u32 filled;
+ u32 inactive_time;
+ u32 rx_bytes;
+ u32 tx_bytes;
++ u16 llid;
++ u16 plid;
++ u8 plink_state;
++};
++
++/**
++ * enum monitor_flags - monitor flags
++ *
++ * Monitor interface configuration flags. Note that these must be the bits
++ * according to the nl80211 flags.
++ *
++ * @MONITOR_FLAG_FCSFAIL: pass frames with bad FCS
++ * @MONITOR_FLAG_PLCPFAIL: pass frames with bad PLCP
++ * @MONITOR_FLAG_CONTROL: pass control frames
++ * @MONITOR_FLAG_OTHER_BSS: disable BSSID filtering
++ * @MONITOR_FLAG_COOK_FRAMES: report frames after processing
++ */
++enum monitor_flags {
++ MONITOR_FLAG_FCSFAIL = 1<<NL80211_MNTR_FLAG_FCSFAIL,
++ MONITOR_FLAG_PLCPFAIL = 1<<NL80211_MNTR_FLAG_PLCPFAIL,
++ MONITOR_FLAG_CONTROL = 1<<NL80211_MNTR_FLAG_CONTROL,
++ MONITOR_FLAG_OTHER_BSS = 1<<NL80211_MNTR_FLAG_OTHER_BSS,
++ MONITOR_FLAG_COOK_FRAMES = 1<<NL80211_MNTR_FLAG_COOK_FRAMES,
+ };
+
++/**
++ * enum mpath_info_flags - mesh path information flags
++ *
++ * Used by the driver to indicate which info in &struct mpath_info it has filled
++ * in during get_station() or dump_station().
++ *
++ * MPATH_INFO_FRAME_QLEN: @frame_qlen filled
++ * MPATH_INFO_DSN: @dsn filled
++ * MPATH_INFO_METRIC: @metric filled
++ * MPATH_INFO_EXPTIME: @exptime filled
++ * MPATH_INFO_DISCOVERY_TIMEOUT: @discovery_timeout filled
++ * MPATH_INFO_DISCOVERY_RETRIES: @discovery_retries filled
++ * MPATH_INFO_FLAGS: @flags filled
++ */
++enum mpath_info_flags {
++ MPATH_INFO_FRAME_QLEN = BIT(0),
++ MPATH_INFO_DSN = BIT(1),
++ MPATH_INFO_METRIC = BIT(2),
++ MPATH_INFO_EXPTIME = BIT(3),
++ MPATH_INFO_DISCOVERY_TIMEOUT = BIT(4),
++ MPATH_INFO_DISCOVERY_RETRIES = BIT(5),
++ MPATH_INFO_FLAGS = BIT(6),
++};
++
++/**
++ * struct mpath_info - mesh path information
++ *
++ * Mesh path information filled by driver for get_mpath() and dump_mpath().
++ *
++ * @filled: bitfield of flags from &enum mpath_info_flags
++ * @frame_qlen: number of queued frames for this destination
++ * @dsn: destination sequence number
++ * @metric: metric (cost) of this mesh path
++ * @exptime: expiration time for the mesh path from now, in msecs
++ * @flags: mesh path flags
++ * @discovery_timeout: total mesh path discovery timeout, in msecs
++ * @discovery_retries: mesh path discovery retries
++ */
++struct mpath_info {
++ u32 filled;
++ u32 frame_qlen;
++ u32 dsn;
++ u32 metric;
++ u32 exptime;
++ u32 discovery_timeout;
++ u8 discovery_retries;
++ u8 flags;
++};
++
++
+ /* from net/wireless.h */
+ struct wiphy;
+
+@@ -210,13 +316,17 @@ struct wiphy;
+ * @del_station: Remove a station; @mac may be NULL to remove all stations.
+ *
+ * @change_station: Modify a given station.
++ *
++ * @set_mesh_cfg: set mesh parameters (by now, just mesh id)
+ */
+ struct cfg80211_ops {
+ int (*add_virtual_intf)(struct wiphy *wiphy, char *name,
+- enum nl80211_iftype type);
++ enum nl80211_iftype type, u32 *flags,
++ struct vif_params *params);
+ int (*del_virtual_intf)(struct wiphy *wiphy, int ifindex);
+ int (*change_virtual_intf)(struct wiphy *wiphy, int ifindex,
+- enum nl80211_iftype type);
++ enum nl80211_iftype type, u32 *flags,
++ struct vif_params *params);
+
+ int (*add_key)(struct wiphy *wiphy, struct net_device *netdev,
+ u8 key_index, u8 *mac_addr,
+@@ -244,7 +354,22 @@ struct cfg80211_ops {
+ int (*change_station)(struct wiphy *wiphy, struct net_device *dev,
+ u8 *mac, struct station_parameters *params);
+ int (*get_station)(struct wiphy *wiphy, struct net_device *dev,
+- u8 *mac, struct station_stats *stats);
++ u8 *mac, struct station_info *sinfo);
++ int (*dump_station)(struct wiphy *wiphy, struct net_device *dev,
++ int idx, u8 *mac, struct station_info *sinfo);
++
++ int (*add_mpath)(struct wiphy *wiphy, struct net_device *dev,
++ u8 *dst, u8 *next_hop);
++ int (*del_mpath)(struct wiphy *wiphy, struct net_device *dev,
++ u8 *dst);
++ int (*change_mpath)(struct wiphy *wiphy, struct net_device *dev,
++ u8 *dst, u8 *next_hop);
++ int (*get_mpath)(struct wiphy *wiphy, struct net_device *dev,
++ u8 *dst, u8 *next_hop,
++ struct mpath_info *pinfo);
++ int (*dump_mpath)(struct wiphy *wiphy, struct net_device *dev,
++ int idx, u8 *dst, u8 *next_hop,
++ struct mpath_info *pinfo);
+ };
+
+ #endif /* __NET_CFG80211_H */
+diff --git a/include/net/dst.h b/include/net/dst.h
+index ae13370..002500e 100644
+--- a/include/net/dst.h
++++ b/include/net/dst.h
+@@ -163,15 +163,7 @@ struct dst_entry * dst_clone(struct dst_entry * dst)
+ return dst;
+ }
+
+-static inline
+-void dst_release(struct dst_entry * dst)
+-{
+- if (dst) {
+- WARN_ON(atomic_read(&dst->__refcnt) < 1);
+- smp_mb__before_atomic_dec();
+- atomic_dec(&dst->__refcnt);
+- }
+-}
++extern void dst_release(struct dst_entry *dst);
+
+ /* Children define the path of the packet through the
+ * Linux networking. Thus, destinations are stackable.
+diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
+index 34349f9..a5c6ccc 100644
+--- a/include/net/fib_rules.h
++++ b/include/net/fib_rules.h
+@@ -87,6 +87,7 @@ static inline void fib_rule_get(struct fib_rule *rule)
+ static inline void fib_rule_put_rcu(struct rcu_head *head)
+ {
+ struct fib_rule *rule = container_of(head, struct fib_rule, rcu);
++ release_net(rule->fr_net);
+ kfree(rule);
+ }
+
+diff --git a/include/net/icmp.h b/include/net/icmp.h
+index 9f7ef3c..dddb839 100644
+--- a/include/net/icmp.h
++++ b/include/net/icmp.h
+@@ -48,7 +48,7 @@ struct sk_buff;
+ extern void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info);
+ extern int icmp_rcv(struct sk_buff *skb);
+ extern int icmp_ioctl(struct sock *sk, int cmd, unsigned long arg);
+-extern void icmp_init(struct net_proto_family *ops);
++extern int icmp_init(void);
+ extern void icmp_out_count(unsigned char type);
+
+ /* Move into dst.h ? */
+@@ -65,11 +65,4 @@ static inline struct raw_sock *raw_sk(const struct sock *sk)
+ return (struct raw_sock *)sk;
+ }
+
+-extern int sysctl_icmp_echo_ignore_all;
+-extern int sysctl_icmp_echo_ignore_broadcasts;
+-extern int sysctl_icmp_ignore_bogus_error_responses;
+-extern int sysctl_icmp_errors_use_inbound_ifaddr;
+-extern int sysctl_icmp_ratelimit;
+-extern int sysctl_icmp_ratemask;
+-
+ #endif /* _ICMP_H */
+diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
+index 285b2ad..529816b 100644
+--- a/include/net/ieee80211.h
++++ b/include/net/ieee80211.h
+@@ -183,7 +183,6 @@ const char *escape_essid(const char *essid, u8 essid_len);
+ #define IEEE80211_DEBUG_RX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a)
+ #define IEEE80211_DEBUG_QOS(f, a...) IEEE80211_DEBUG(IEEE80211_DL_QOS, f, ## a)
+ #include <linux/netdevice.h>
+-#include <linux/wireless.h>
+ #include <linux/if_arp.h> /* ARPHRD_ETHER */
+
+ #ifndef WIRELESS_SPY
+diff --git a/include/net/ieee80211softmac.h b/include/net/ieee80211softmac.h
+deleted file mode 100644
+index 1ef6282..0000000
+--- a/include/net/ieee80211softmac.h
++++ /dev/null
+@@ -1,373 +0,0 @@
+-/*
+- * ieee80211softmac.h - public interface to the softmac
+- *
+- * Copyright (c) 2005 Johannes Berg <johannes at sipsolutions.net>
+- * Joseph Jezak <josejx at gentoo.org>
+- * Larry Finger <Larry.Finger at lwfinger.net>
+- * Danny van Dyk <kugelfang at gentoo.org>
+- * Michael Buesch <mbuesch at freenet.de>
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of version 2 of the GNU General Public License as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+- *
+- * The full GNU General Public License is included in this distribution in the
+- * file called COPYING.
+- */
+-
+-#ifndef IEEE80211SOFTMAC_H_
+-#define IEEE80211SOFTMAC_H_
+-
+-#include <linux/kernel.h>
+-#include <linux/spinlock.h>
+-#include <linux/workqueue.h>
+-#include <linux/list.h>
+-#include <net/ieee80211.h>
+-
+-/* Once the API is considered more or less stable,
+- * this should be incremented on API incompatible changes.
+- */
+-#define IEEE80211SOFTMAC_API 0
+-
+-#define IEEE80211SOFTMAC_MAX_RATES_LEN 8
+-#define IEEE80211SOFTMAC_MAX_EX_RATES_LEN 255
+-
+-struct ieee80211softmac_ratesinfo {
+- u8 count;
+- u8 rates[IEEE80211SOFTMAC_MAX_RATES_LEN + IEEE80211SOFTMAC_MAX_EX_RATES_LEN];
+-};
+-
+-/* internal structures */
+-struct ieee80211softmac_network;
+-struct ieee80211softmac_scaninfo;
+-
+-struct ieee80211softmac_essid {
+- u8 len;
+- char data[IW_ESSID_MAX_SIZE+1];
+-};
+-
+-struct ieee80211softmac_wpa {
+- char *IE;
+- int IElen;
+- int IEbuflen;
+-};
+-
+-/*
+- * Information about association
+- */
+-struct ieee80211softmac_assoc_info {
+-
+- struct mutex mutex;
+-
+- /*
+- * This is the requested ESSID. It is written
+- * only by the WX handlers.
+- *
+- */
+- struct ieee80211softmac_essid req_essid;
+- /*
+- * the ESSID of the network we're currently
+- * associated (or trying) to. This is
+- * updated to the network's actual ESSID
+- * even if the requested ESSID was 'ANY'
+- */
+- struct ieee80211softmac_essid associate_essid;
+-
+- /* BSSID we're trying to associate to */
+- char bssid[ETH_ALEN];
+-
+- /* some flags.
+- * static_essid is valid if the essid is constant,
+- * this is for use by the wx handlers only.
+- *
+- * associating is true, if the network has been
+- * auth'ed on and we are in the process of associating.
+- *
+- * bssvalid is true if we found a matching network
+- * and saved it's BSSID into the bssid above.
+- *
+- * bssfixed is used for SIOCSIWAP.
+- */
+- u8 static_essid;
+- u8 short_preamble_available;
+- u8 associating;
+- u8 associated;
+- u8 assoc_wait;
+- u8 bssvalid;
+- u8 bssfixed;
+-
+- /* Scan retries remaining */
+- int scan_retry;
+-
+- struct delayed_work work;
+- struct delayed_work timeout;
+-};
+-
+-struct ieee80211softmac_bss_info {
+- /* Rates supported by the network */
+- struct ieee80211softmac_ratesinfo supported_rates;
+-
+- /* This indicates whether frames can currently be transmitted with
+- * short preamble (only use this variable during TX at CCK rates) */
+- u8 short_preamble:1;
+-
+- /* This indicates whether protection (e.g. self-CTS) should be used
+- * when transmitting with OFDM modulation */
+- u8 use_protection:1;
+-};
+-
+-enum {
+- IEEE80211SOFTMAC_AUTH_OPEN_REQUEST = 1,
+- IEEE80211SOFTMAC_AUTH_OPEN_RESPONSE = 2,
+-};
+-
+-enum {
+- IEEE80211SOFTMAC_AUTH_SHARED_REQUEST = 1,
+- IEEE80211SOFTMAC_AUTH_SHARED_CHALLENGE = 2,
+- IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE = 3,
+- IEEE80211SOFTMAC_AUTH_SHARED_PASS = 4,
+-};
+-
+-/* We should make these tunable
+- * AUTH_TIMEOUT seems really long, but that's what it is in BSD */
+-#define IEEE80211SOFTMAC_AUTH_TIMEOUT (12 * HZ)
+-#define IEEE80211SOFTMAC_AUTH_RETRY_LIMIT 5
+-#define IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT 3
+-
+-struct ieee80211softmac_txrates {
+- /* The Bit-Rate to be used for multicast frames. */
+- u8 mcast_rate;
+-
+- /* The Bit-Rate to be used for multicast management frames. */
+- u8 mgt_mcast_rate;
+-
+- /* The Bit-Rate to be used for any other (normal) data packet. */
+- u8 default_rate;
+- /* The Bit-Rate to be used for default fallback
+- * (If the device supports fallback and hardware-retry)
+- */
+- u8 default_fallback;
+-
+- /* This is the rate that the user asked for */
+- u8 user_rate;
+-};
+-
+-/* Bits for txrates_change callback. */
+-#define IEEE80211SOFTMAC_TXRATECHG_DEFAULT (1 << 0) /* default_rate */
+-#define IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK (1 << 1) /* default_fallback */
+-#define IEEE80211SOFTMAC_TXRATECHG_MCAST (1 << 2) /* mcast_rate */
+-#define IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST (1 << 3) /* mgt_mcast_rate */
+-
+-#define IEEE80211SOFTMAC_BSSINFOCHG_RATES (1 << 0) /* supported_rates */
+-#define IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE (1 << 1) /* short_preamble */
+-#define IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION (1 << 2) /* use_protection */
+-
+-struct ieee80211softmac_device {
+- /* 802.11 structure for data stuff */
+- struct ieee80211_device *ieee;
+- struct net_device *dev;
+-
+- /* only valid if associated, then holds the Association ID */
+- u16 association_id;
+-
+- /* the following methods are callbacks that the driver
+- * using this framework has to assign
+- */
+-
+- /* always assign these */
+- void (*set_bssid_filter)(struct net_device *dev, const u8 *bssid);
+- void (*set_channel)(struct net_device *dev, u8 channel);
+-
+- /* assign if you need it, informational only */
+- void (*link_change)(struct net_device *dev);
+-
+- /* If the hardware can do scanning, assign _all_ three of these callbacks.
+- * When the scan finishes, call ieee80211softmac_scan_finished().
+- */
+-
+- /* when called, start_scan is guaranteed to not be called again
+- * until you call ieee80211softmac_scan_finished.
+- * Return 0 if scanning could start, error otherwise.
+- * SOFTMAC AUTHORS: don't call this, use ieee80211softmac_start_scan */
+- int (*start_scan)(struct net_device *dev);
+- /* this should block until after ieee80211softmac_scan_finished was called
+- * SOFTMAC AUTHORS: don't call this, use ieee80211softmac_wait_for_scan */
+- void (*wait_for_scan)(struct net_device *dev);
+- /* stop_scan aborts a scan, but is asynchronous.
+- * if you want to wait for it too, use wait_for_scan
+- * SOFTMAC AUTHORS: don't call this, use ieee80211softmac_stop_scan */
+- void (*stop_scan)(struct net_device *dev);
+-
+- /* we'll need something about beacons here too, for AP or ad-hoc modes */
+-
+- /* Transmission rates to be used by the driver.
+- * The SoftMAC figures out the best possible rates.
+- * The driver just needs to read them.
+- */
+- struct ieee80211softmac_txrates txrates;
+-
+- /* If the driver needs to do stuff on TX rate changes, assign this
+- * callback. See IEEE80211SOFTMAC_TXRATECHG for change flags. */
+- void (*txrates_change)(struct net_device *dev,
+- u32 changes);
+-
+- /* If the driver needs to do stuff when BSS properties change, assign
+- * this callback. see IEEE80211SOFTMAC_BSSINFOCHG for change flags. */
+- void (*bssinfo_change)(struct net_device *dev,
+- u32 changes);
+-
+- /* private stuff follows */
+- /* this lock protects this structure */
+- spinlock_t lock;
+-
+- struct workqueue_struct *wq;
+-
+- u8 running; /* SoftMAC started? */
+- u8 scanning;
+-
+- struct ieee80211softmac_scaninfo *scaninfo;
+- struct ieee80211softmac_assoc_info associnfo;
+- struct ieee80211softmac_bss_info bssinfo;
+-
+- struct list_head auth_queue;
+- struct list_head events;
+-
+- struct ieee80211softmac_ratesinfo ratesinfo;
+- int txrate_badness;
+-
+- /* WPA stuff */
+- struct ieee80211softmac_wpa wpa;
+-
+- /* we need to keep a list of network structs we copied */
+- struct list_head network_list;
+-
+- /* This must be the last item so that it points to the data
+- * allocated beyond this structure by alloc_ieee80211 */
+- u8 priv[0];
+-};
+-
+-extern void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm);
+-
+-static inline void * ieee80211softmac_priv(struct net_device *dev)
+-{
+- return ((struct ieee80211softmac_device *)ieee80211_priv(dev))->priv;
+-}
+-
+-extern struct net_device * alloc_ieee80211softmac(int sizeof_priv);
+-extern void free_ieee80211softmac(struct net_device *dev);
+-
+-/* Call this function if you detect a lost TX fragment.
+- * (If the device indicates failure of ACK RX, for example.)
+- * It is wise to call this function if you are able to detect lost packets,
+- * because it contributes to the TX Rates auto adjustment.
+- */
+-extern void ieee80211softmac_fragment_lost(struct net_device *dev,
+- u16 wireless_sequence_number);
+-/* Call this function before _start to tell the softmac what rates
+- * the hw supports. The rates parameter is copied, so you can
+- * free it right after calling this function.
+- * Note that the rates need to be sorted. */
+-extern void ieee80211softmac_set_rates(struct net_device *dev, u8 count, u8 *rates);
+-
+-/* Finds the highest rate which is:
+- * 1. Present in ri (optionally a basic rate)
+- * 2. Supported by the device
+- * 3. Less than or equal to the user-defined rate
+- */
+-extern u8 ieee80211softmac_highest_supported_rate(struct ieee80211softmac_device *mac,
+- struct ieee80211softmac_ratesinfo *ri, int basic_only);
+-
+-/* Helper function which advises you the rate at which a frame should be
+- * transmitted at. */
+-static inline u8 ieee80211softmac_suggest_txrate(struct ieee80211softmac_device *mac,
+- int is_multicast,
+- int is_mgt)
+-{
+- struct ieee80211softmac_txrates *txrates = &mac->txrates;
+-
+- if (!mac->associnfo.associated)
+- return txrates->mgt_mcast_rate;
+-
+- /* We are associated, sending unicast frame */
+- if (!is_multicast)
+- return txrates->default_rate;
+-
+- /* We are associated, sending multicast frame */
+- if (is_mgt)
+- return txrates->mgt_mcast_rate;
+- else
+- return txrates->mcast_rate;
+-}
+-
+-/* Helper function which advises you when it is safe to transmit with short
+- * preamble.
+- * You should only call this function when transmitting at CCK rates. */
+-static inline int ieee80211softmac_short_preamble_ok(struct ieee80211softmac_device *mac,
+- int is_multicast,
+- int is_mgt)
+-{
+- return (is_multicast && is_mgt) ? 0 : mac->bssinfo.short_preamble;
+-}
+-
+-/* Helper function which advises you whether protection (e.g. self-CTS) is
+- * needed. 1 = protection needed, 0 = no protection needed
+- * Only use this function when transmitting with OFDM modulation. */
+-static inline int ieee80211softmac_protection_needed(struct ieee80211softmac_device *mac)
+-{
+- return mac->bssinfo.use_protection;
+-}
+-
+-/* Start the SoftMAC. Call this after you initialized the device
+- * and it is ready to run.
+- */
+-extern void ieee80211softmac_start(struct net_device *dev);
+-/* Stop the SoftMAC. Call this before you shutdown the device. */
+-extern void ieee80211softmac_stop(struct net_device *dev);
+-
+-/*
+- * Event system
+- */
+-
+-/* valid event types */
+-#define IEEE80211SOFTMAC_EVENT_ANY -1 /*private use only*/
+-#define IEEE80211SOFTMAC_EVENT_SCAN_FINISHED 0
+-#define IEEE80211SOFTMAC_EVENT_ASSOCIATED 1
+-#define IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED 2
+-#define IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT 3
+-#define IEEE80211SOFTMAC_EVENT_AUTHENTICATED 4
+-#define IEEE80211SOFTMAC_EVENT_AUTH_FAILED 5
+-#define IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT 6
+-#define IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND 7
+-#define IEEE80211SOFTMAC_EVENT_DISASSOCIATED 8
+-/* keep this updated! */
+-#define IEEE80211SOFTMAC_EVENT_LAST 8
+-/*
+- * If you want to be notified of certain events, you can call
+- * ieee80211softmac_notify[_atomic] with
+- * - event set to one of the constants below
+- * - fun set to a function pointer of the appropriate type
+- * - context set to the context data you want passed
+- * The return value is 0, or an error.
+- */
+-typedef void (*notify_function_ptr)(struct net_device *dev, int event_type, void *context);
+-
+-#define ieee80211softmac_notify(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_KERNEL);
+-#define ieee80211softmac_notify_atomic(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_ATOMIC);
+-
+-extern int ieee80211softmac_notify_gfp(struct net_device *dev,
+- int event, notify_function_ptr fun, void *context, gfp_t gfp_mask);
+-
+-/* To clear pending work (for ifconfig down, etc.) */
+-extern void
+-ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm);
+-
+-#endif /* IEEE80211SOFTMAC_H_ */
+diff --git a/include/net/ieee80211softmac_wx.h b/include/net/ieee80211softmac_wx.h
+deleted file mode 100644
+index 4ee3ad5..0000000
+--- a/include/net/ieee80211softmac_wx.h
++++ /dev/null
+@@ -1,99 +0,0 @@
+-/*
+- * This file contains the prototypes for the wireless extension
+- * handlers that the softmac API provides. Include this file to
+- * use the wx handlers, you can assign these directly.
+- *
+- * Copyright (c) 2005 Johannes Berg <johannes at sipsolutions.net>
+- * Joseph Jezak <josejx at gentoo.org>
+- * Larry Finger <Larry.Finger at lwfinger.net>
+- * Danny van Dyk <kugelfang at gentoo.org>
+- * Michael Buesch <mbuesch at freenet.de>
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of version 2 of the GNU General Public License as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+- *
+- * The full GNU General Public License is included in this distribution in the
+- * file called COPYING.
+- */
+-
+-#ifndef _IEEE80211SOFTMAC_WX_H
+-#define _IEEE80211SOFTMAC_WX_H
+-
+-#include <net/ieee80211softmac.h>
+-#include <net/iw_handler.h>
+-
+-extern int
+-ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra);
+-
+-extern int
+-ieee80211softmac_wx_get_scan_results(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra);
+-
+-extern int
+-ieee80211softmac_wx_set_essid(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra);
+-
+-extern int
+-ieee80211softmac_wx_get_essid(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra);
+-
+-extern int
+-ieee80211softmac_wx_set_rate(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra);
+-
+-extern int
+-ieee80211softmac_wx_get_rate(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra);
+-
+-extern int
+-ieee80211softmac_wx_get_wap(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra);
+-
+-extern int
+-ieee80211softmac_wx_set_wap(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra);
+-
+-extern int
+-ieee80211softmac_wx_set_genie(struct net_device *dev,
+- struct iw_request_info *info,
+- union iwreq_data *wrqu,
+- char *extra);
+-
+-extern int
+-ieee80211softmac_wx_get_genie(struct net_device *dev,
+- struct iw_request_info *info,
+- union iwreq_data *wrqu,
+- char *extra);
+-extern int
+-ieee80211softmac_wx_set_mlme(struct net_device *dev,
+- struct iw_request_info *info,
+- union iwreq_data *wrqu,
+- char *extra);
+-#endif /* _IEEE80211SOFTMAC_WX */
+diff --git a/include/net/inet_common.h b/include/net/inet_common.h
+index 38d5a1e..18c7732 100644
+--- a/include/net/inet_common.h
++++ b/include/net/inet_common.h
+@@ -39,6 +39,17 @@ extern int inet_getname(struct socket *sock,
+ extern int inet_ioctl(struct socket *sock,
+ unsigned int cmd, unsigned long arg);
+
++extern int inet_ctl_sock_create(struct sock **sk,
++ unsigned short family,
++ unsigned short type,
++ unsigned char protocol,
++ struct net *net);
++
++static inline void inet_ctl_sock_destroy(struct sock *sk)
++{
++ sk_release_kernel(sk);
++}
++
+ #endif
+
+
+diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
+index f00f057..2ff545a 100644
+--- a/include/net/inet_connection_sock.h
++++ b/include/net/inet_connection_sock.h
+@@ -327,11 +327,6 @@ extern void inet_csk_listen_stop(struct sock *sk);
+
+ extern void inet_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr);
+
+-extern int inet_csk_ctl_sock_create(struct socket **sock,
+- unsigned short family,
+- unsigned short type,
+- unsigned char protocol);
+-
+ extern int inet_csk_compat_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen);
+ extern int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname,
+diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h
+index 7374251..e081eef 100644
+--- a/include/net/inet_frag.h
++++ b/include/net/inet_frag.h
+@@ -25,9 +25,9 @@ struct inet_frag_queue {
+ int meat;
+ __u8 last_in; /* first/last segment arrived? */
+
+-#define COMPLETE 4
+-#define FIRST_IN 2
+-#define LAST_IN 1
++#define INET_FRAG_COMPLETE 4
++#define INET_FRAG_FIRST_IN 2
++#define INET_FRAG_LAST_IN 1
+ };
+
+ #define INETFRAGS_HASHSZ 64
+diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
+index 97dc35a..735b926 100644
+--- a/include/net/inet_hashtables.h
++++ b/include/net/inet_hashtables.h
+@@ -221,26 +221,7 @@ static inline int inet_sk_listen_hashfn(const struct sock *sk)
+ }
+
+ /* Caller must disable local BH processing. */
+-static inline void __inet_inherit_port(struct sock *sk, struct sock *child)
+-{
+- struct inet_hashinfo *table = sk->sk_prot->hashinfo;
+- const int bhash = inet_bhashfn(inet_sk(child)->num, table->bhash_size);
+- struct inet_bind_hashbucket *head = &table->bhash[bhash];
+- struct inet_bind_bucket *tb;
+-
+- spin_lock(&head->lock);
+- tb = inet_csk(sk)->icsk_bind_hash;
+- sk_add_bind_node(child, &tb->owners);
+- inet_csk(child)->icsk_bind_hash = tb;
+- spin_unlock(&head->lock);
+-}
+-
+-static inline void inet_inherit_port(struct sock *sk, struct sock *child)
+-{
+- local_bh_disable();
+- __inet_inherit_port(sk, child);
+- local_bh_enable();
+-}
++extern void __inet_inherit_port(struct sock *sk, struct sock *child);
+
+ extern void inet_put_port(struct sock *sk);
+
+@@ -314,25 +295,25 @@ typedef __u64 __bitwise __addrpair;
+ ((__force __u64)(__be32)(__saddr)));
+ #endif /* __BIG_ENDIAN */
+ #define INET_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
+- (((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net)) && \
++ (((__sk)->sk_hash == (__hash)) && sock_net((__sk)) == (__net) && \
+ ((*((__addrpair *)&(inet_sk(__sk)->daddr))) == (__cookie)) && \
+ ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports)) && \
+ (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+ #define INET_TW_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
+- (((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net)) && \
++ (((__sk)->sk_hash == (__hash)) && sock_net((__sk)) == (__net) && \
+ ((*((__addrpair *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) && \
+ ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \
+ (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+ #else /* 32-bit arch */
+ #define INET_ADDR_COOKIE(__name, __saddr, __daddr)
+ #define INET_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif) \
+- (((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net)) && \
++ (((__sk)->sk_hash == (__hash)) && sock_net((__sk)) == (__net) && \
+ (inet_sk(__sk)->daddr == (__saddr)) && \
+ (inet_sk(__sk)->rcv_saddr == (__daddr)) && \
+ ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports)) && \
+ (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+ #define INET_TW_MATCH(__sk, __net, __hash,__cookie, __saddr, __daddr, __ports, __dif) \
+- (((__sk)->sk_hash == (__hash)) && ((__sk)->sk_net == (__net)) && \
++ (((__sk)->sk_hash == (__hash)) && sock_net((__sk)) == (__net) && \
+ (inet_twsk(__sk)->tw_daddr == (__saddr)) && \
+ (inet_twsk(__sk)->tw_rcv_saddr == (__daddr)) && \
+ ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \
+diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
+index 89cd011..a42cd63 100644
+--- a/include/net/inet_sock.h
++++ b/include/net/inet_sock.h
+@@ -43,8 +43,7 @@ struct ip_options {
+ unsigned char srr;
+ unsigned char rr;
+ unsigned char ts;
+- unsigned char is_data:1,
+- is_strictroute:1,
++ unsigned char is_strictroute:1,
+ srr_is_hit:1,
+ is_changed:1,
+ rr_needaddr:1,
+@@ -137,7 +136,7 @@ struct inet_sock {
+ unsigned int flags;
+ unsigned int fragsize;
+ struct ip_options *opt;
+- struct rtable *rt;
++ struct dst_entry *dst;
+ int length; /* Total length of all frames */
+ __be32 addr;
+ struct flowi fl;
+@@ -195,7 +194,7 @@ static inline int inet_sk_ehashfn(const struct sock *sk)
+
+ static inline int inet_iif(const struct sk_buff *skb)
+ {
+- return ((struct rtable *)skb->dst)->rt_iif;
++ return skb->rtable->rt_iif;
+ }
+
+ #endif /* _INET_SOCK_H */
+diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
+index 296547b..95c660c 100644
+--- a/include/net/inet_timewait_sock.h
++++ b/include/net/inet_timewait_sock.h
+@@ -207,4 +207,22 @@ extern void inet_twsk_schedule(struct inet_timewait_sock *tw,
+ const int timeo, const int timewait_len);
+ extern void inet_twsk_deschedule(struct inet_timewait_sock *tw,
+ struct inet_timewait_death_row *twdr);
++
++static inline
++struct net *twsk_net(const struct inet_timewait_sock *twsk)
++{
++#ifdef CONFIG_NET_NS
++ return twsk->tw_net;
++#else
++ return &init_net;
++#endif
++}
++
++static inline
++void twsk_net_set(struct inet_timewait_sock *twsk, struct net *net)
++{
++#ifdef CONFIG_NET_NS
++ twsk->tw_net = net;
++#endif
++}
+ #endif /* _INET_TIMEWAIT_SOCK_ */
+diff --git a/include/net/ip.h b/include/net/ip.h
+index 9f50d4f..6d7bcd5 100644
+--- a/include/net/ip.h
++++ b/include/net/ip.h
+@@ -347,10 +347,11 @@ extern int ip_forward(struct sk_buff *skb);
+ extern void ip_options_build(struct sk_buff *skb, struct ip_options *opt, __be32 daddr, struct rtable *rt, int is_frag);
+ extern int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb);
+ extern void ip_options_fragment(struct sk_buff *skb);
+-extern int ip_options_compile(struct ip_options *opt, struct sk_buff *skb);
+-extern int ip_options_get(struct ip_options **optp,
++extern int ip_options_compile(struct net *net,
++ struct ip_options *opt, struct sk_buff *skb);
++extern int ip_options_get(struct net *net, struct ip_options **optp,
+ unsigned char *data, int optlen);
+-extern int ip_options_get_from_user(struct ip_options **optp,
++extern int ip_options_get_from_user(struct net *net, struct ip_options **optp,
+ unsigned char __user *data, int optlen);
+ extern void ip_options_undo(struct ip_options * opt);
+ extern void ip_forward_options(struct sk_buff *skb);
+@@ -361,7 +362,8 @@ extern int ip_options_rcv_srr(struct sk_buff *skb);
+ */
+
+ extern void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb);
+-extern int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc);
++extern int ip_cmsg_send(struct net *net,
++ struct msghdr *msg, struct ipcm_cookie *ipc);
+ extern int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen);
+ extern int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen);
+ extern int compat_ip_setsockopt(struct sock *sk, int level,
+diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
+index 953d604..7c5c0f7 100644
+--- a/include/net/ip6_fib.h
++++ b/include/net/ip6_fib.h
+@@ -174,17 +174,19 @@ struct fib6_table {
+ #define RT6_TABLE_LOCAL RT6_TABLE_MAIN
+ #endif
+
+-typedef struct rt6_info *(*pol_lookup_t)(struct fib6_table *,
++typedef struct rt6_info *(*pol_lookup_t)(struct net *,
++ struct fib6_table *,
+ struct flowi *, int);
+
+ /*
+ * exported functions
+ */
+
+-extern struct fib6_table * fib6_get_table(u32 id);
+-extern struct fib6_table * fib6_new_table(u32 id);
+-extern struct dst_entry * fib6_rule_lookup(struct flowi *fl, int flags,
+- pol_lookup_t lookup);
++extern struct fib6_table *fib6_get_table(struct net *net, u32 id);
++extern struct fib6_table *fib6_new_table(struct net *net, u32 id);
++extern struct dst_entry *fib6_rule_lookup(struct net *net,
++ struct flowi *fl, int flags,
++ pol_lookup_t lookup);
+
+ extern struct fib6_node *fib6_lookup(struct fib6_node *root,
+ struct in6_addr *daddr,
+@@ -194,7 +196,8 @@ struct fib6_node *fib6_locate(struct fib6_node *root,
+ struct in6_addr *daddr, int dst_len,
+ struct in6_addr *saddr, int src_len);
+
+-extern void fib6_clean_all(int (*func)(struct rt6_info *, void *arg),
++extern void fib6_clean_all(struct net *net,
++ int (*func)(struct rt6_info *, void *arg),
+ int prune, void *arg);
+
+ extern int fib6_add(struct fib6_node *root,
+@@ -207,7 +210,8 @@ extern int fib6_del(struct rt6_info *rt,
+ extern void inet6_rt_notify(int event, struct rt6_info *rt,
+ struct nl_info *info);
+
+-extern void fib6_run_gc(unsigned long dummy);
++extern void fib6_run_gc(unsigned long expires,
++ struct net *net);
+
+ extern void fib6_gc_cleanup(void);
+
+diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
+index f99e4f0..9313491 100644
+--- a/include/net/ip6_route.h
++++ b/include/net/ip6_route.h
+@@ -30,60 +30,54 @@ struct route_info {
+ #include <linux/ip.h>
+ #include <linux/ipv6.h>
+
+-#define RT6_LOOKUP_F_IFACE 0x1
+-#define RT6_LOOKUP_F_REACHABLE 0x2
+-#define RT6_LOOKUP_F_HAS_SADDR 0x4
++#define RT6_LOOKUP_F_IFACE 0x00000001
++#define RT6_LOOKUP_F_REACHABLE 0x00000002
++#define RT6_LOOKUP_F_HAS_SADDR 0x00000004
++#define RT6_LOOKUP_F_SRCPREF_TMP 0x00000008
++#define RT6_LOOKUP_F_SRCPREF_PUBLIC 0x00000010
++#define RT6_LOOKUP_F_SRCPREF_COA 0x00000020
+
+-extern struct rt6_info ip6_null_entry;
+
+ #ifdef CONFIG_IPV6_MULTIPLE_TABLES
+-extern struct rt6_info ip6_prohibit_entry;
+-extern struct rt6_info ip6_blk_hole_entry;
++extern struct rt6_info *ip6_prohibit_entry;
++extern struct rt6_info *ip6_blk_hole_entry;
+ #endif
+
+ extern void ip6_route_input(struct sk_buff *skb);
+
+-extern struct dst_entry * ip6_route_output(struct sock *sk,
++extern struct dst_entry * ip6_route_output(struct net *net,
++ struct sock *sk,
+ struct flowi *fl);
+
+ extern int ip6_route_init(void);
+ extern void ip6_route_cleanup(void);
+
+-extern int ipv6_route_ioctl(unsigned int cmd, void __user *arg);
++extern int ipv6_route_ioctl(struct net *net,
++ unsigned int cmd,
++ void __user *arg);
+
+ extern int ip6_route_add(struct fib6_config *cfg);
+ extern int ip6_ins_rt(struct rt6_info *);
+ extern int ip6_del_rt(struct rt6_info *);
+
+-extern int ip6_rt_addr_add(struct in6_addr *addr,
+- struct net_device *dev,
+- int anycast);
+-
+-extern int ip6_rt_addr_del(struct in6_addr *addr,
+- struct net_device *dev);
+-
+-extern void rt6_sndmsg(int type, struct in6_addr *dst,
+- struct in6_addr *src,
+- struct in6_addr *gw,
+- struct net_device *dev,
+- int dstlen, int srclen,
+- int metric, __u32 flags);
+-
+-extern struct rt6_info *rt6_lookup(struct in6_addr *daddr,
+- struct in6_addr *saddr,
++extern struct rt6_info *rt6_lookup(struct net *net,
++ const struct in6_addr *daddr,
++ const struct in6_addr *saddr,
+ int oif, int flags);
+
+-extern struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
++extern struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
+ struct neighbour *neigh,
+- struct in6_addr *addr,
+- int (*output)(struct sk_buff *));
+-extern int ndisc_dst_gc(int *more);
+-extern void fib6_force_start_gc(void);
++ const struct in6_addr *addr);
++extern int icmp6_dst_gc(int *more);
++
++extern void fib6_force_start_gc(struct net *net);
+
+ extern struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
+ const struct in6_addr *addr,
+ int anycast);
+
++extern int ip6_dst_hoplimit(struct dst_entry *dst);
++
+ /*
+ * support functions for ND
+ *
+@@ -94,7 +88,7 @@ extern struct rt6_info * rt6_add_dflt_router(struct in6_addr *gwaddr,
+ struct net_device *dev,
+ unsigned int pref);
+
+-extern void rt6_purge_dflt_routers(void);
++extern void rt6_purge_dflt_routers(struct net *net);
+
+ extern int rt6_route_rcv(struct net_device *dev,
+ u8 *opt, int len,
+@@ -121,7 +115,7 @@ struct rt6_rtnl_dump_arg
+ };
+
+ extern int rt6_dump_route(struct rt6_info *rt, void *p_arg);
+-extern void rt6_ifdown(struct net_device *dev);
++extern void rt6_ifdown(struct net *net, struct net_device *dev);
+ extern void rt6_mtu_change(struct net_device *dev, unsigned mtu);
+
+ extern rwlock_t rt6_lock;
+diff --git a/include/net/ipip.h b/include/net/ipip.h
+index 549e132..633ed4d 100644
+--- a/include/net/ipip.h
++++ b/include/net/ipip.h
+@@ -24,6 +24,16 @@ struct ip_tunnel
+ int mlink;
+
+ struct ip_tunnel_parm parms;
++
++ struct ip_tunnel_prl_entry *prl; /* potential router list */
++ unsigned int prl_count; /* # of entries in PRL */
++};
++
++struct ip_tunnel_prl_entry
++{
++ struct ip_tunnel_prl_entry *next;
++ __be32 addr;
++ u16 flags;
+ };
+
+ #define IPTUNNEL_XMIT() do { \
+diff --git a/include/net/ipv6.h b/include/net/ipv6.h
+index c0c019f..e0a612b 100644
+--- a/include/net/ipv6.h
++++ b/include/net/ipv6.h
+@@ -202,6 +202,7 @@ struct ip6_flowlabel
+ u32 owner;
+ unsigned long lastuse;
+ unsigned long expires;
++ struct net *fl_net;
+ };
+
+ #define IPV6_FLOWINFO_MASK __constant_htonl(0x0FFFFFFF)
+@@ -249,15 +250,6 @@ int ip6_frag_mem(struct net *net);
+
+ #define IPV6_FRAG_TIMEOUT (60*HZ) /* 60 seconds */
+
+-/*
+- * Function prototype for build_xmit
+- */
+-
+-typedef int (*inet_getfrag_t) (const void *data,
+- struct in6_addr *addr,
+- char *,
+- unsigned int, unsigned int);
+-
+ extern int __ipv6_addr_type(const struct in6_addr *addr);
+ static inline int ipv6_addr_type(const struct in6_addr *addr)
+ {
+@@ -288,12 +280,10 @@ static inline int
+ ipv6_masked_addr_cmp(const struct in6_addr *a1, const struct in6_addr *m,
+ const struct in6_addr *a2)
+ {
+- unsigned int i;
+-
+- for (i = 0; i < 4; i++)
+- if ((a1->s6_addr32[i] ^ a2->s6_addr32[i]) & m->s6_addr32[i])
+- return 1;
+- return 0;
++ return (!!(((a1->s6_addr32[0] ^ a2->s6_addr32[0]) & m->s6_addr32[0]) |
++ ((a1->s6_addr32[1] ^ a2->s6_addr32[1]) & m->s6_addr32[1]) |
++ ((a1->s6_addr32[2] ^ a2->s6_addr32[2]) & m->s6_addr32[2]) |
++ ((a1->s6_addr32[3] ^ a2->s6_addr32[3]) & m->s6_addr32[3])));
+ }
+
+ static inline void ipv6_addr_copy(struct in6_addr *a1, const struct in6_addr *a2)
+@@ -328,10 +318,10 @@ static inline void ipv6_addr_set(struct in6_addr *addr,
+ static inline int ipv6_addr_equal(const struct in6_addr *a1,
+ const struct in6_addr *a2)
+ {
+- return (a1->s6_addr32[0] == a2->s6_addr32[0] &&
+- a1->s6_addr32[1] == a2->s6_addr32[1] &&
+- a1->s6_addr32[2] == a2->s6_addr32[2] &&
+- a1->s6_addr32[3] == a2->s6_addr32[3]);
++ return (((a1->s6_addr32[0] ^ a2->s6_addr32[0]) |
++ (a1->s6_addr32[1] ^ a2->s6_addr32[1]) |
++ (a1->s6_addr32[2] ^ a2->s6_addr32[2]) |
++ (a1->s6_addr32[3] ^ a2->s6_addr32[3])) == 0);
+ }
+
+ static inline int __ipv6_prefix_equal(const __be32 *a1, const __be32 *a2,
+@@ -379,8 +369,27 @@ static inline int ipv6_addr_any(const struct in6_addr *a)
+
+ static inline int ipv6_addr_v4mapped(const struct in6_addr *a)
+ {
+- return ((a->s6_addr32[0] | a->s6_addr32[1]) == 0 &&
+- a->s6_addr32[2] == htonl(0x0000ffff));
++ return ((a->s6_addr32[0] | a->s6_addr32[1] |
++ (a->s6_addr32[2] ^ htonl(0x0000ffff))) == 0);
++}
++
++/*
++ * Check for a RFC 4843 ORCHID address
++ * (Overlay Routable Cryptographic Hash Identifiers)
++ */
++static inline int ipv6_addr_orchid(const struct in6_addr *a)
++{
++ return ((a->s6_addr32[0] & htonl(0xfffffff0))
++ == htonl(0x20010010));
++}
++
++static inline void ipv6_addr_set_v4mapped(const __be32 addr,
++ struct in6_addr *v4mapped)
++{
++ ipv6_addr_set(v4mapped,
++ 0, 0,
++ htonl(0x0000FFFF),
++ addr);
+ }
+
+ /*
+@@ -451,8 +460,8 @@ extern int ip6_xmit(struct sock *sk,
+ extern int ip6_nd_hdr(struct sock *sk,
+ struct sk_buff *skb,
+ struct net_device *dev,
+- struct in6_addr *saddr,
+- struct in6_addr *daddr,
++ const struct in6_addr *saddr,
++ const struct in6_addr *daddr,
+ int proto, int len);
+
+ extern int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr);
+@@ -499,14 +508,6 @@ extern int ip6_local_out(struct sk_buff *skb);
+ * Extension header (options) processing
+ */
+
+-extern u8 * ipv6_build_nfrag_opts(struct sk_buff *skb,
+- u8 *prev_hdr,
+- struct ipv6_txoptions *opt,
+- struct in6_addr *daddr,
+- u32 jumbolen);
+-extern u8 * ipv6_build_frag_opts(struct sk_buff *skb,
+- u8 *prev_hdr,
+- struct ipv6_txoptions *opt);
+ extern void ipv6_push_nfrag_opts(struct sk_buff *skb,
+ struct ipv6_txoptions *opt,
+ u8 *proto,
+@@ -545,10 +546,6 @@ extern int compat_ipv6_getsockopt(struct sock *sk,
+ char __user *optval,
+ int __user *optlen);
+
+-extern int ipv6_packet_init(void);
+-
+-extern void ipv6_packet_cleanup(void);
+-
+ extern int ip6_datagram_connect(struct sock *sk,
+ struct sockaddr *addr, int addr_len);
+
+@@ -585,14 +582,14 @@ extern int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
+ int __user *optlen);
+
+ #ifdef CONFIG_PROC_FS
+-extern int ac6_proc_init(void);
+-extern void ac6_proc_exit(void);
++extern int ac6_proc_init(struct net *net);
++extern void ac6_proc_exit(struct net *net);
+ extern int raw6_proc_init(void);
+ extern void raw6_proc_exit(void);
+-extern int tcp6_proc_init(void);
+-extern void tcp6_proc_exit(void);
+-extern int udp6_proc_init(void);
+-extern void udp6_proc_exit(void);
++extern int tcp6_proc_init(struct net *net);
++extern void tcp6_proc_exit(struct net *net);
++extern int udp6_proc_init(struct net *net);
++extern void udp6_proc_exit(struct net *net);
+ extern int udplite6_proc_init(void);
+ extern void udplite6_proc_exit(void);
+ extern int ipv6_misc_proc_init(void);
+@@ -600,17 +597,11 @@ extern void ipv6_misc_proc_exit(void);
+ extern int snmp6_register_dev(struct inet6_dev *idev);
+ extern int snmp6_unregister_dev(struct inet6_dev *idev);
+
+-extern struct rt6_statistics rt6_stats;
+ #else
+-static inline int snmp6_register_dev(struct inet6_dev *idev)
+-{
+- return 0;
+-}
+-
+-static inline int snmp6_unregister_dev(struct inet6_dev *idev)
+-{
+- return 0;
+-}
++static inline int ac6_proc_init(struct net *net) { return 0; }
++static inline void ac6_proc_exit(struct net *net) { }
++static inline int snmp6_register_dev(struct inet6_dev *idev) { return 0; }
++static inline int snmp6_unregister_dev(struct inet6_dev *idev) { return 0; }
+ #endif
+
+ #ifdef CONFIG_SYSCTL
+diff --git a/include/net/irda/irlan_eth.h b/include/net/irda/irlan_eth.h
+index 0062347..de5c816 100644
+--- a/include/net/irda/irlan_eth.h
++++ b/include/net/irda/irlan_eth.h
+@@ -29,5 +29,4 @@ struct net_device *alloc_irlandev(const char *name);
+ int irlan_eth_receive(void *instance, void *sap, struct sk_buff *skb);
+
+ void irlan_eth_flow_indication( void *instance, void *sap, LOCAL_FLOW flow);
+-void irlan_eth_send_gratuitous_arp(struct net_device *dev);
+ #endif
+diff --git a/include/net/llc_if.h b/include/net/llc_if.h
+index c608812..b595a00 100644
+--- a/include/net/llc_if.h
++++ b/include/net/llc_if.h
+@@ -74,11 +74,6 @@ static inline int llc_mac_null(const u8 *mac)
+ return is_zero_ether_addr(mac);
+ }
+
+-static inline int llc_addrany(const struct llc_addr *addr)
+-{
+- return llc_mac_null(addr->mac) && !addr->lsap;
+-}
+-
+ static inline int llc_mac_multicast(const u8 *mac)
+ {
+ return is_multicast_ether_addr(mac);
+diff --git a/include/net/mac80211.h b/include/net/mac80211.h
+index 9083baf..4a80d74 100644
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -38,7 +38,11 @@
+ * called in hardware interrupt context. The low-level driver must not call any
+ * other functions in hardware interrupt context. If there is a need for such
+ * call, the low-level driver should first ACK the interrupt and perform the
+- * IEEE 802.11 code call after this, e.g. from a scheduled workqueue function.
++ * IEEE 802.11 code call after this, e.g. from a scheduled workqueue or even
++ * tasklet function.
++ *
++ * NOTE: If the driver opts to use the _irqsafe() functions, it may not also
++ * use the non-irqsafe functions!
+ */
+
+ /**
+@@ -69,93 +73,12 @@
+ * not do so then mac80211 may add this under certain circumstances.
+ */
+
+-#define IEEE80211_CHAN_W_SCAN 0x00000001
+-#define IEEE80211_CHAN_W_ACTIVE_SCAN 0x00000002
+-#define IEEE80211_CHAN_W_IBSS 0x00000004
+-
+-/* Channel information structure. Low-level driver is expected to fill in chan,
+- * freq, and val fields. Other fields will be filled in by 80211.o based on
+- * hostapd information and low-level driver does not need to use them. The
+- * limits for each channel will be provided in 'struct ieee80211_conf' when
+- * configuring the low-level driver with hw->config callback. If a device has
+- * a default regulatory domain, IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED
+- * can be set to let the driver configure all fields */
+-struct ieee80211_channel {
+- short chan; /* channel number (IEEE 802.11) */
+- short freq; /* frequency in MHz */
+- int val; /* hw specific value for the channel */
+- int flag; /* flag for hostapd use (IEEE80211_CHAN_*) */
+- unsigned char power_level;
+- unsigned char antenna_max;
+-};
+-
+-#define IEEE80211_RATE_ERP 0x00000001
+-#define IEEE80211_RATE_BASIC 0x00000002
+-#define IEEE80211_RATE_PREAMBLE2 0x00000004
+-#define IEEE80211_RATE_SUPPORTED 0x00000010
+-#define IEEE80211_RATE_OFDM 0x00000020
+-#define IEEE80211_RATE_CCK 0x00000040
+-#define IEEE80211_RATE_MANDATORY 0x00000100
+-
+-#define IEEE80211_RATE_CCK_2 (IEEE80211_RATE_CCK | IEEE80211_RATE_PREAMBLE2)
+-#define IEEE80211_RATE_MODULATION(f) \
+- (f & (IEEE80211_RATE_CCK | IEEE80211_RATE_OFDM))
+-
+-/* Low-level driver should set PREAMBLE2, OFDM and CCK flags.
+- * BASIC, SUPPORTED, ERP, and MANDATORY flags are set in 80211.o based on the
+- * configuration. */
+-struct ieee80211_rate {
+- int rate; /* rate in 100 kbps */
+- int val; /* hw specific value for the rate */
+- int flags; /* IEEE80211_RATE_ flags */
+- int val2; /* hw specific value for the rate when using short preamble
+- * (only when IEEE80211_RATE_PREAMBLE2 flag is set, i.e., for
+- * 2, 5.5, and 11 Mbps) */
+- signed char min_rssi_ack;
+- unsigned char min_rssi_ack_delta;
+-
+- /* following fields are set by 80211.o and need not be filled by the
+- * low-level driver */
+- int rate_inv; /* inverse of the rate (LCM(all rates) / rate) for
+- * optimizing channel utilization estimates */
+-};
+-
+ /**
+- * enum ieee80211_phymode - PHY modes
+- *
+- * @MODE_IEEE80211A: 5GHz as defined by 802.11a/802.11h
+- * @MODE_IEEE80211B: 2.4 GHz as defined by 802.11b
+- * @MODE_IEEE80211G: 2.4 GHz as defined by 802.11g (with OFDM),
+- * backwards compatible with 11b mode
+- * @NUM_IEEE80211_MODES: internal
++ * enum ieee80211_notification_type - Low level driver notification
++ * @IEEE80211_NOTIFY_RE_ASSOC: start the re-association sequence
+ */
+-enum ieee80211_phymode {
+- MODE_IEEE80211A,
+- MODE_IEEE80211B,
+- MODE_IEEE80211G,
+-
+- /* keep last */
+- NUM_IEEE80211_MODES
+-};
+-
+-/**
+- * struct ieee80211_ht_info - describing STA's HT capabilities
+- *
+- * This structure describes most essential parameters needed
+- * to describe 802.11n HT capabilities for an STA.
+- *
+- * @ht_supported: is HT supported by STA, 0: no, 1: yes
+- * @cap: HT capabilities map as described in 802.11n spec
+- * @ampdu_factor: Maximum A-MPDU length factor
+- * @ampdu_density: Minimum A-MPDU spacing
+- * @supp_mcs_set: Supported MCS set as described in 802.11n spec
+- */
+-struct ieee80211_ht_info {
+- u8 ht_supported;
+- u16 cap; /* use IEEE80211_HT_CAP_ */
+- u8 ampdu_factor;
+- u8 ampdu_density;
+- u8 supp_mcs_set[16];
++enum ieee80211_notification_types {
++ IEEE80211_NOTIFY_RE_ASSOC,
+ };
+
+ /**
+@@ -175,46 +98,22 @@ struct ieee80211_ht_bss_info {
+ };
+
+ /**
+- * struct ieee80211_hw_mode - PHY mode definition
+- *
+- * This structure describes the capabilities supported by the device
+- * in a single PHY mode.
+- *
+- * @list: internal
+- * @channels: pointer to array of supported channels
+- * @rates: pointer to array of supported bitrates
+- * @mode: the PHY mode for this definition
+- * @num_channels: number of supported channels
+- * @num_rates: number of supported bitrates
+- * @ht_info: PHY's 802.11n HT abilities for this mode
+- */
+-struct ieee80211_hw_mode {
+- struct list_head list;
+- struct ieee80211_channel *channels;
+- struct ieee80211_rate *rates;
+- enum ieee80211_phymode mode;
+- int num_channels;
+- int num_rates;
+- struct ieee80211_ht_info ht_info;
+-};
+-
+-/**
+ * struct ieee80211_tx_queue_params - transmit queue configuration
+ *
+ * The information provided in this structure is required for QoS
+- * transmit queue configuration.
++ * transmit queue configuration. Cf. IEEE 802.11 7.3.2.29.
+ *
+ * @aifs: arbitration interface space [0..255, -1: use default]
+ * @cw_min: minimum contention window [will be a value of the form
+ * 2^n-1 in the range 1..1023; 0: use default]
+ * @cw_max: maximum contention window [like @cw_min]
+- * @burst_time: maximum burst time in units of 0.1ms, 0 meaning disabled
++ * @txop: maximum burst time in units of 32 usecs, 0 meaning disabled
+ */
+ struct ieee80211_tx_queue_params {
+- int aifs;
+- int cw_min;
+- int cw_max;
+- int burst_time;
++ s16 aifs;
++ u16 cw_min;
++ u16 cw_max;
++ u16 txop;
+ };
+
+ /**
+@@ -246,6 +145,7 @@ struct ieee80211_tx_queue_stats_data {
+ * @IEEE80211_TX_QUEUE_AFTER_BEACON: transmit queue for frames to be
+ * sent after a beacon
+ * @IEEE80211_TX_QUEUE_BEACON: transmit queue for beacon frames
++ * @NUM_TX_DATA_QUEUES_AMPDU: adding more queues for A-MPDU
+ */
+ enum ieee80211_tx_queue {
+ IEEE80211_TX_QUEUE_DATA0,
+@@ -261,11 +161,12 @@ enum ieee80211_tx_queue {
+ * this struct need to have fixed values. As soon as it is removed, we can
+ * fix these entries. */
+ IEEE80211_TX_QUEUE_AFTER_BEACON = 6,
+- IEEE80211_TX_QUEUE_BEACON = 7
++ IEEE80211_TX_QUEUE_BEACON = 7,
++ NUM_TX_DATA_QUEUES_AMPDU = 16
+ };
+
+ struct ieee80211_tx_queue_stats {
+- struct ieee80211_tx_queue_stats_data data[NUM_TX_DATA_QUEUES];
++ struct ieee80211_tx_queue_stats_data data[NUM_TX_DATA_QUEUES_AMPDU];
+ };
+
+ struct ieee80211_low_level_stats {
+@@ -285,11 +186,13 @@ struct ieee80211_low_level_stats {
+ * also implies a change in the AID.
+ * @BSS_CHANGED_ERP_CTS_PROT: CTS protection changed
+ * @BSS_CHANGED_ERP_PREAMBLE: preamble changed
++ * @BSS_CHANGED_HT: 802.11n parameters changed
+ */
+ enum ieee80211_bss_change {
+ BSS_CHANGED_ASSOC = 1<<0,
+ BSS_CHANGED_ERP_CTS_PROT = 1<<1,
+ BSS_CHANGED_ERP_PREAMBLE = 1<<2,
++ BSS_CHANGED_HT = 1<<4,
+ };
+
+ /**
+@@ -302,6 +205,12 @@ enum ieee80211_bss_change {
+ * @aid: association ID number, valid only when @assoc is true
+ * @use_cts_prot: use CTS protection
+ * @use_short_preamble: use 802.11b short preamble
++ * @timestamp: beacon timestamp
++ * @beacon_int: beacon interval
++ * @assoc_capability: capabbilities taken from assoc resp
++ * @assoc_ht: association in HT mode
++ * @ht_conf: ht capabilities
++ * @ht_bss_conf: ht extended capabilities
+ */
+ struct ieee80211_bss_conf {
+ /* association related data */
+@@ -310,6 +219,69 @@ struct ieee80211_bss_conf {
+ /* erp related data */
+ bool use_cts_prot;
+ bool use_short_preamble;
++ u16 beacon_int;
++ u16 assoc_capability;
++ u64 timestamp;
++ /* ht related data */
++ bool assoc_ht;
++ struct ieee80211_ht_info *ht_conf;
++ struct ieee80211_ht_bss_info *ht_bss_conf;
++};
++
++/**
++ * enum mac80211_tx_control_flags - flags to describe Tx configuration for
++ * the Tx frame
++ *
++ * These flags are used with the @flags member of &ieee80211_tx_control
++ *
++ * @IEEE80211_TXCTL_REQ_TX_STATUS: request TX status callback for this frame.
++ * @IEEE80211_TXCTL_DO_NOT_ENCRYPT: send this frame without encryption;
++ * e.g., for EAPOL frame
++ * @IEEE80211_TXCTL_USE_RTS_CTS: use RTS-CTS before sending frame
++ * @IEEE80211_TXCTL_USE_CTS_PROTECT: use CTS protection for the frame (e.g.,
++ * for combined 802.11g / 802.11b networks)
++ * @IEEE80211_TXCTL_NO_ACK: tell the low level not to wait for an ack
++ * @IEEE80211_TXCTL_RATE_CTRL_PROBE
++ * @EEE80211_TXCTL_CLEAR_PS_FILT: clear powersave filter
++ * for destination station
++ * @IEEE80211_TXCTL_REQUEUE:
++ * @IEEE80211_TXCTL_FIRST_FRAGMENT: this is a first fragment of the frame
++ * @IEEE80211_TXCTL_LONG_RETRY_LIMIT: this frame should be send using the
++ * through set_retry_limit configured long
++ * retry value
++ * @IEEE80211_TXCTL_EAPOL_FRAME: internal to mac80211
++ * @IEEE80211_TXCTL_SEND_AFTER_DTIM: send this frame after DTIM beacon
++ * @IEEE80211_TXCTL_AMPDU: this frame should be sent as part of an A-MPDU
++ * @IEEE80211_TXCTL_OFDM_HT: this frame can be sent in HT OFDM rates. number
++ * of streams when this flag is on can be extracted
++ * from antenna_sel_tx, so if 1 antenna is marked
++ * use SISO, 2 antennas marked use MIMO, n antennas
++ * marked use MIMO_n.
++ * @IEEE80211_TXCTL_GREEN_FIELD: use green field protection for this frame
++ * @IEEE80211_TXCTL_40_MHZ_WIDTH: send this frame using 40 Mhz channel width
++ * @IEEE80211_TXCTL_DUP_DATA: duplicate data frame on both 20 Mhz channels
++ * @IEEE80211_TXCTL_SHORT_GI: send this frame using short guard interval
++ */
++enum mac80211_tx_control_flags {
++ IEEE80211_TXCTL_REQ_TX_STATUS = (1<<0),
++ IEEE80211_TXCTL_DO_NOT_ENCRYPT = (1<<1),
++ IEEE80211_TXCTL_USE_RTS_CTS = (1<<2),
++ IEEE80211_TXCTL_USE_CTS_PROTECT = (1<<3),
++ IEEE80211_TXCTL_NO_ACK = (1<<4),
++ IEEE80211_TXCTL_RATE_CTRL_PROBE = (1<<5),
++ IEEE80211_TXCTL_CLEAR_PS_FILT = (1<<6),
++ IEEE80211_TXCTL_REQUEUE = (1<<7),
++ IEEE80211_TXCTL_FIRST_FRAGMENT = (1<<8),
++ IEEE80211_TXCTL_SHORT_PREAMBLE = (1<<9),
++ IEEE80211_TXCTL_LONG_RETRY_LIMIT = (1<<10),
++ IEEE80211_TXCTL_EAPOL_FRAME = (1<<11),
++ IEEE80211_TXCTL_SEND_AFTER_DTIM = (1<<12),
++ IEEE80211_TXCTL_AMPDU = (1<<13),
++ IEEE80211_TXCTL_OFDM_HT = (1<<14),
++ IEEE80211_TXCTL_GREEN_FIELD = (1<<15),
++ IEEE80211_TXCTL_40_MHZ_WIDTH = (1<<16),
++ IEEE80211_TXCTL_DUP_DATA = (1<<17),
++ IEEE80211_TXCTL_SHORT_GI = (1<<18),
+ };
+
+ /* Transmit control fields. This data structure is passed to low-level driver
+@@ -318,57 +290,27 @@ struct ieee80211_bss_conf {
+
+ struct ieee80211_tx_control {
+ struct ieee80211_vif *vif;
+- int tx_rate; /* Transmit rate, given as the hw specific value for the
+- * rate (from struct ieee80211_rate) */
+- int rts_cts_rate; /* Transmit rate for RTS/CTS frame, given as the hw
+- * specific value for the rate (from
+- * struct ieee80211_rate) */
+-
+-#define IEEE80211_TXCTL_REQ_TX_STATUS (1<<0)/* request TX status callback for
+- * this frame */
+-#define IEEE80211_TXCTL_DO_NOT_ENCRYPT (1<<1) /* send this frame without
+- * encryption; e.g., for EAPOL
+- * frames */
+-#define IEEE80211_TXCTL_USE_RTS_CTS (1<<2) /* use RTS-CTS before sending
+- * frame */
+-#define IEEE80211_TXCTL_USE_CTS_PROTECT (1<<3) /* use CTS protection for the
+- * frame (e.g., for combined
+- * 802.11g / 802.11b networks) */
+-#define IEEE80211_TXCTL_NO_ACK (1<<4) /* tell the low level not to
+- * wait for an ack */
+-#define IEEE80211_TXCTL_RATE_CTRL_PROBE (1<<5)
+-#define IEEE80211_TXCTL_CLEAR_DST_MASK (1<<6)
+-#define IEEE80211_TXCTL_REQUEUE (1<<7)
+-#define IEEE80211_TXCTL_FIRST_FRAGMENT (1<<8) /* this is a first fragment of
+- * the frame */
+-#define IEEE80211_TXCTL_LONG_RETRY_LIMIT (1<<10) /* this frame should be send
+- * using the through
+- * set_retry_limit configured
+- * long retry value */
+-#define IEEE80211_TXCTL_EAPOL_FRAME (1<<11) /* internal to mac80211 */
+-#define IEEE80211_TXCTL_SEND_AFTER_DTIM (1<<12) /* send this frame after DTIM
+- * beacon */
+- u32 flags; /* tx control flags defined
+- * above */
++ struct ieee80211_rate *tx_rate;
++
++ /* Transmit rate for RTS/CTS frame */
++ struct ieee80211_rate *rts_cts_rate;
++
++ /* retry rate for the last retries */
++ struct ieee80211_rate *alt_retry_rate;
++
++ u32 flags; /* tx control flags defined above */
+ u8 key_idx; /* keyidx from hw->set_key(), undefined if
+ * IEEE80211_TXCTL_DO_NOT_ENCRYPT is set */
+ u8 retry_limit; /* 1 = only first attempt, 2 = one retry, ..
+ * This could be used when set_retry_limit
+ * is not implemented by the driver */
+- u8 power_level; /* per-packet transmit power level, in dBm */
+- u8 antenna_sel_tx; /* 0 = default/diversity, 1 = Ant0, 2 = Ant1 */
++ u8 antenna_sel_tx; /* 0 = default/diversity, otherwise bit
++ * position represents antenna number used */
+ u8 icv_len; /* length of the ICV/MIC field in octets */
+ u8 iv_len; /* length of the IV field in octets */
+ u8 queue; /* hardware queue to use for this frame;
+ * 0 = highest, hw->queues-1 = lowest */
+- struct ieee80211_rate *rate; /* internal 80211.o rate */
+- struct ieee80211_rate *rts_rate; /* internal 80211.o rate
+- * for RTS/CTS */
+- int alt_retry_rate; /* retry rate for the last retries, given as the
+- * hw specific value for the rate (from
+- * struct ieee80211_rate). To be used to limit
+- * packet dropping when probing higher rates, if hw
+- * supports multiple retry rates. -1 = not used */
++ u16 aid; /* Station AID */
+ int type; /* internal */
+ };
+
+@@ -391,7 +333,8 @@ struct ieee80211_tx_control {
+ * @RX_FLAG_FAILED_PLCP_CRC: Set this flag if the PCLP check failed on
+ * the frame.
+ * @RX_FLAG_TSFT: The timestamp passed in the RX status (@mactime field)
+- * is valid.
++ * is valid. This is useful in monitor mode and necessary for beacon frames
++ * to enable IBSS merging.
+ */
+ enum mac80211_rx_flags {
+ RX_FLAG_MMIC_ERROR = 1<<0,
+@@ -410,27 +353,26 @@ enum mac80211_rx_flags {
+ * The low-level driver should provide this information (the subset
+ * supported by hardware) to the 802.11 code with each received
+ * frame.
+- * @mactime: MAC timestamp as defined by 802.11
++ * @mactime: value in microseconds of the 64-bit Time Synchronization Function
++ * (TSF) timer when the first data symbol (MPDU) arrived at the hardware.
++ * @band: the active band when this frame was received
+ * @freq: frequency the radio was tuned to when receiving this frame, in MHz
+- * @channel: channel the radio was tuned to
+- * @phymode: active PHY mode
+ * @ssi: signal strength when receiving this frame
+ * @signal: used as 'qual' in statistics reporting
+ * @noise: PHY noise when receiving this frame
+ * @antenna: antenna used
+- * @rate: data rate
++ * @rate_idx: index of data rate into band's supported rates
+ * @flag: %RX_FLAG_*
+ */
+ struct ieee80211_rx_status {
+ u64 mactime;
++ enum ieee80211_band band;
+ int freq;
+- int channel;
+- enum ieee80211_phymode phymode;
+ int ssi;
+ int signal;
+ int noise;
+ int antenna;
+- int rate;
++ int rate_idx;
+ int flag;
+ };
+
+@@ -441,12 +383,14 @@ struct ieee80211_rx_status {
+ *
+ * @IEEE80211_TX_STATUS_TX_FILTERED: The frame was not transmitted
+ * because the destination STA was in powersave mode.
+- *
+ * @IEEE80211_TX_STATUS_ACK: Frame was acknowledged
++ * @IEEE80211_TX_STATUS_AMPDU: The frame was aggregated, so status
++ * is for the whole aggregation.
+ */
+ enum ieee80211_tx_status_flags {
+ IEEE80211_TX_STATUS_TX_FILTERED = 1<<0,
+ IEEE80211_TX_STATUS_ACK = 1<<1,
++ IEEE80211_TX_STATUS_AMPDU = 1<<2,
+ };
+
+ /**
+@@ -457,24 +401,25 @@ enum ieee80211_tx_status_flags {
+ *
+ * @control: a copy of the &struct ieee80211_tx_control passed to the driver
+ * in the tx() callback.
+- *
+ * @flags: transmit status flags, defined above
+- *
+- * @ack_signal: signal strength of the ACK frame
+- *
++ * @retry_count: number of retries
+ * @excessive_retries: set to 1 if the frame was retried many times
+ * but not acknowledged
+- *
+- * @retry_count: number of retries
+- *
++ * @ampdu_ack_len: number of aggregated frames.
++ * relevant only if IEEE80211_TX_STATUS_AMPDU was set.
++ * @ampdu_ack_map: block ack bit map for the aggregation.
++ * relevant only if IEEE80211_TX_STATUS_AMPDU was set.
++ * @ack_signal: signal strength of the ACK frame
+ * @queue_length: ?? REMOVE
+ * @queue_number: ?? REMOVE
+ */
+ struct ieee80211_tx_status {
+ struct ieee80211_tx_control control;
+ u8 flags;
+- bool excessive_retries;
+ u8 retry_count;
++ bool excessive_retries;
++ u8 ampdu_ack_len;
++ u64 ampdu_ack_map;
+ int ack_signal;
+ int queue_length;
+ int queue_number;
+@@ -502,41 +447,29 @@ enum ieee80211_conf_flags {
+ *
+ * @radio_enabled: when zero, driver is required to switch off the radio.
+ * TODO make a flag
+- * @channel: IEEE 802.11 channel number
+- * @freq: frequency in MHz
+- * @channel_val: hardware specific channel value for the channel
+- * @phymode: PHY mode to activate (REMOVE)
+- * @chan: channel to switch to, pointer to the channel information
+- * @mode: pointer to mode definition
+- * @regulatory_domain: ??
+ * @beacon_int: beacon interval (TODO make interface config)
+ * @flags: configuration flags defined above
+- * @power_level: transmit power limit for current regulatory domain in dBm
+- * @antenna_max: maximum antenna gain
++ * @power_level: requested transmit power (in dBm)
++ * @max_antenna_gain: maximum antenna gain (in dBi)
+ * @antenna_sel_tx: transmit antenna selection, 0: default/diversity,
+ * 1/2: antenna 0/1
+ * @antenna_sel_rx: receive antenna selection, like @antenna_sel_tx
+ * @ht_conf: describes current self configuration of 802.11n HT capabilies
+ * @ht_bss_conf: describes current BSS configuration of 802.11n HT parameters
++ * @channel: the channel to tune to
+ */
+ struct ieee80211_conf {
+- int channel; /* IEEE 802.11 channel number */
+- int freq; /* MHz */
+- int channel_val; /* hw specific value for the channel */
+-
+- enum ieee80211_phymode phymode;
+- struct ieee80211_channel *chan;
+- struct ieee80211_hw_mode *mode;
+- unsigned int regulatory_domain;
+ int radio_enabled;
+
+ int beacon_int;
+ u32 flags;
+- u8 power_level;
+- u8 antenna_max;
++ int power_level;
++ int max_antenna_gain;
+ u8 antenna_sel_tx;
+ u8 antenna_sel_rx;
+
++ struct ieee80211_channel *channel;
++
+ struct ieee80211_ht_info ht_conf;
+ struct ieee80211_ht_bss_info ht_bss_conf;
+ };
+@@ -555,12 +488,14 @@ struct ieee80211_conf {
+ * @IEEE80211_IF_TYPE_WDS: interface in WDS mode.
+ * @IEEE80211_IF_TYPE_VLAN: VLAN interface bound to an AP, drivers
+ * will never see this type.
++ * @IEEE80211_IF_TYPE_MESH_POINT: 802.11s mesh point
+ */
+ enum ieee80211_if_types {
+ IEEE80211_IF_TYPE_INVALID,
+ IEEE80211_IF_TYPE_AP,
+ IEEE80211_IF_TYPE_STA,
+ IEEE80211_IF_TYPE_IBSS,
++ IEEE80211_IF_TYPE_MESH_POINT,
+ IEEE80211_IF_TYPE_MNTR,
+ IEEE80211_IF_TYPE_WDS,
+ IEEE80211_IF_TYPE_VLAN,
+@@ -582,6 +517,14 @@ struct ieee80211_vif {
+ u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
+ };
+
++static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif)
++{
++#ifdef CONFIG_MAC80211_MESH
++ return vif->type == IEEE80211_IF_TYPE_MESH_POINT;
++#endif
++ return false;
++}
++
+ /**
+ * struct ieee80211_if_init_conf - initial configuration of an interface
+ *
+@@ -725,6 +668,21 @@ enum sta_notify_cmd {
+ };
+
+ /**
++ * enum ieee80211_tkip_key_type - get tkip key
++ *
++ * Used by drivers which need to get a tkip key for skb. Some drivers need a
++ * phase 1 key, others need a phase 2 key. A single function allows the driver
++ * to get the key, this enum indicates what type of key is required.
++ *
++ * @IEEE80211_TKIP_P1_KEY: the driver needs a phase 1 key
++ * @IEEE80211_TKIP_P2_KEY: the driver needs a phase 2 key
++ */
++enum ieee80211_tkip_key_type {
++ IEEE80211_TKIP_P1_KEY,
++ IEEE80211_TKIP_P2_KEY,
++};
++
++/**
+ * enum ieee80211_hw_flags - hardware flags
+ *
+ * These flags are used to indicate hardware capabilities to
+@@ -757,15 +715,19 @@ enum sta_notify_cmd {
+ * %IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE is also not set because
+ * otherwise the stack will not know when the DTIM beacon was sent.
+ *
+- * @IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED:
+- * Channels are already configured to the default regulatory domain
+- * specified in the device's EEPROM
++ * @IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE:
++ * Hardware is not capable of short slot operation on the 2.4 GHz band.
++ *
++ * @IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE:
++ * Hardware is not capable of receiving frames with short preamble on
++ * the 2.4 GHz band.
+ */
+ enum ieee80211_hw_flags {
+ IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE = 1<<0,
+ IEEE80211_HW_RX_INCLUDES_FCS = 1<<1,
+ IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING = 1<<2,
+- IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED = 1<<3,
++ IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE = 1<<3,
++ IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE = 1<<4,
+ };
+
+ /**
+@@ -777,7 +739,8 @@ enum ieee80211_hw_flags {
+ * @wiphy: This points to the &struct wiphy allocated for this
+ * 802.11 PHY. You must fill in the @perm_addr and @dev
+ * members of this structure using SET_IEEE80211_DEV()
+- * and SET_IEEE80211_PERM_ADDR().
++ * and SET_IEEE80211_PERM_ADDR(). Additionally, all supported
++ * bands (with channels, bitrates) are registered here.
+ *
+ * @conf: &struct ieee80211_conf, device configuration, don't use.
+ *
+@@ -888,6 +851,16 @@ static inline void SET_IEEE80211_PERM_ADDR(struct ieee80211_hw *hw, u8 *addr)
+ * parameter is guaranteed to be valid until another call to set_key()
+ * removes it, but it can only be used as a cookie to differentiate
+ * keys.
++ *
++ * In TKIP some HW need to be provided a phase 1 key, for RX decryption
++ * acceleration (i.e. iwlwifi). Those drivers should provide update_tkip_key
++ * handler.
++ * The update_tkip_key() call updates the driver with the new phase 1 key.
++ * This happens everytime the iv16 wraps around (every 65536 packets). The
++ * set_key() call will happen only once for each key (unless the AP did
++ * rekeying), it will not include a valid phase 1 key. The valid phase 1 key is
++ * provided by udpate_tkip_key only. The trigger that makes mac80211 call this
++ * handler is software decryption with wrap around of iv16.
+ */
+
+ /**
+@@ -913,8 +886,18 @@ static inline void SET_IEEE80211_PERM_ADDR(struct ieee80211_hw *hw, u8 *addr)
+ * parameter to see whether multicast frames should be accepted
+ * or dropped.
+ *
+- * All unsupported flags in @total_flags must be cleared, i.e. you
+- * should clear all bits except those you honoured.
++ * All unsupported flags in @total_flags must be cleared.
++ * Hardware does not support a flag if it is incapable of _passing_
++ * the frame to the stack. Otherwise the driver must ignore
++ * the flag, but not clear it.
++ * You must _only_ clear the flag (announce no support for the
++ * flag to mac80211) if you are not able to pass the packet type
++ * to the stack (so the hardware always filters it).
++ * So for example, you should clear @FIF_CONTROL, if your hardware
++ * always filters control frames. If your hardware always passes
++ * control frames to the kernel and is incapable of filtering them,
++ * you do _not_ clear the @FIF_CONTROL flag.
++ * This rule applies to all other FIF flags as well.
+ */
+
+ /**
+@@ -967,10 +950,14 @@ enum ieee80211_filter_flags {
+ * &struct ieee80211_ops to indicate which action is needed.
+ * @IEEE80211_AMPDU_RX_START: start Rx aggregation
+ * @IEEE80211_AMPDU_RX_STOP: stop Rx aggregation
++ * @IEEE80211_AMPDU_TX_START: start Tx aggregation
++ * @IEEE80211_AMPDU_TX_STOP: stop Tx aggregation
+ */
+ enum ieee80211_ampdu_mlme_action {
+ IEEE80211_AMPDU_RX_START,
+ IEEE80211_AMPDU_RX_STOP,
++ IEEE80211_AMPDU_TX_START,
++ IEEE80211_AMPDU_TX_STOP,
+ };
+
+ /**
+@@ -1033,8 +1020,7 @@ enum ieee80211_ampdu_mlme_action {
+ * level driver (e.g. assoc/disassoc status, erp parameters).
+ * This function should not be used if no BSS has been set, unless
+ * for association indication. The @changed parameter indicates which
+- * of the bss parameters has changed when a call is made. This callback
+- * has to be atomic.
++ * of the bss parameters has changed when a call is made.
+ *
+ * @configure_filter: Configure the device's RX filter.
+ * See the section "Frame filtering" for more information.
+@@ -1050,8 +1036,14 @@ enum ieee80211_ampdu_mlme_action {
+ * and remove_interface calls, i.e. while the interface with the
+ * given local_address is enabled.
+ *
++ * @update_tkip_key: See the section "Hardware crypto acceleration"
++ * This callback will be called in the context of Rx. Called for drivers
++ * which set IEEE80211_KEY_FLAG_TKIP_REQ_RX_P1_KEY.
++ *
+ * @hw_scan: Ask the hardware to service the scan request, no need to start
+- * the scan state machine in stack.
++ * the scan state machine in stack. The scan must honour the channel
++ * configuration done by the regulatory agent in the wiphy's registered
++ * bands.
+ *
+ * @get_stats: return low-level statistics
+ *
+@@ -1111,7 +1103,8 @@ enum ieee80211_ampdu_mlme_action {
+ * The RA/TID combination determines the destination and TID we want
+ * the ampdu action to be performed for. The action is defined through
+ * ieee80211_ampdu_mlme_action. Starting sequence number (@ssn)
+- * is the first frame we expect to perform the action on.
++ * is the first frame we expect to perform the action on. notice
++ * that TX/RX_STOP can pass NULL for this parameter.
+ */
+ struct ieee80211_ops {
+ int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb,
+@@ -1138,6 +1131,9 @@ struct ieee80211_ops {
+ int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ const u8 *local_address, const u8 *address,
+ struct ieee80211_key_conf *key);
++ void (*update_tkip_key)(struct ieee80211_hw *hw,
++ struct ieee80211_key_conf *conf, const u8 *address,
++ u32 iv32, u16 *phase1key);
+ int (*hw_scan)(struct ieee80211_hw *hw, u8 *ssid, size_t len);
+ int (*get_stats)(struct ieee80211_hw *hw,
+ struct ieee80211_low_level_stats *stats);
+@@ -1159,10 +1155,9 @@ struct ieee80211_ops {
+ struct sk_buff *skb,
+ struct ieee80211_tx_control *control);
+ int (*tx_last_beacon)(struct ieee80211_hw *hw);
+- int (*conf_ht)(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
+ int (*ampdu_action)(struct ieee80211_hw *hw,
+ enum ieee80211_ampdu_mlme_action action,
+- const u8 *ra, u16 tid, u16 ssn);
++ const u8 *addr, u16 tid, u16 *ssn);
+ };
+
+ /**
+@@ -1183,8 +1178,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
+ /**
+ * ieee80211_register_hw - Register hardware device
+ *
+- * You must call this function before any other functions
+- * except ieee80211_register_hwmode.
++ * You must call this function before any other functions in
++ * mac80211. Note that before a hardware can be registered, you
++ * need to fill the contained wiphy's information.
+ *
+ * @hw: the device to register as returned by ieee80211_alloc_hw()
+ */
+@@ -1272,10 +1268,6 @@ static inline char *ieee80211_get_radio_led_name(struct ieee80211_hw *hw)
+ #endif
+ }
+
+-/* Register a new hardware PHYMODE capability to the stack. */
+-int ieee80211_register_hwmode(struct ieee80211_hw *hw,
+- struct ieee80211_hw_mode *mode);
+-
+ /**
+ * ieee80211_unregister_hw - Unregister a hardware device
+ *
+@@ -1308,7 +1300,10 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ * buffer in @skb must start with an IEEE 802.11 header or a radiotap
+ * header if %RX_FLAG_RADIOTAP is set in the @status flags.
+ *
+- * This function may not be called in IRQ context.
++ * This function may not be called in IRQ context. Calls to this function
++ * for a single hardware must be synchronized against each other. Calls
++ * to this function and ieee80211_rx_irqsafe() may not be mixed for a
++ * single hardware.
+ *
+ * @hw: the hardware this frame came in on
+ * @skb: the buffer to receive, owned by mac80211 after this call
+@@ -1325,7 +1320,10 @@ static inline void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ * ieee80211_rx_irqsafe - receive frame
+ *
+ * Like ieee80211_rx() but can be called in IRQ context
+- * (internally defers to a workqueue.)
++ * (internally defers to a tasklet.)
++ *
++ * Calls to this function and ieee80211_rx() may not be mixed for a
++ * single hardware.
+ *
+ * @hw: the hardware this frame came in on
+ * @skb: the buffer to receive, owned by mac80211 after this call
+@@ -1344,6 +1342,11 @@ void ieee80211_rx_irqsafe(struct ieee80211_hw *hw,
+ * transmitted. It is permissible to not call this function for
+ * multicast frames but this can affect statistics.
+ *
++ * This function may not be called in IRQ context. Calls to this function
++ * for a single hardware must be synchronized against each other. Calls
++ * to this function and ieee80211_tx_status_irqsafe() may not be mixed
++ * for a single hardware.
++ *
+ * @hw: the hardware the frame was transmitted by
+ * @skb: the frame that was transmitted, owned by mac80211 after this call
+ * @status: status information for this frame; the status pointer need not
+@@ -1353,6 +1356,22 @@ void ieee80211_rx_irqsafe(struct ieee80211_hw *hw,
+ void ieee80211_tx_status(struct ieee80211_hw *hw,
+ struct sk_buff *skb,
+ struct ieee80211_tx_status *status);
++
++/**
++ * ieee80211_tx_status_irqsafe - irq-safe transmit status callback
++ *
++ * Like ieee80211_tx_status() but can be called in IRQ context
++ * (internally defers to a tasklet.)
++ *
++ * Calls to this function and ieee80211_tx_status() may not be mixed for a
++ * single hardware.
++ *
++ * @hw: the hardware the frame was transmitted by
++ * @skb: the frame that was transmitted, owned by mac80211 after this call
++ * @status: status information for this frame; the status pointer need not
++ * be valid after this function returns and is not freed by mac80211,
++ * it is recommended that it points to a stack area
++ */
+ void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
+ struct sk_buff *skb,
+ struct ieee80211_tx_status *status);
+@@ -1449,7 +1468,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
+ * @frame_len: the length of the frame.
+- * @rate: the rate (in 100kbps) at which the frame is going to be transmitted.
++ * @rate: the rate at which the frame is going to be transmitted.
+ *
+ * Calculate the duration field of some generic frame, given its
+ * length and transmission rate (in 100kbps).
+@@ -1457,7 +1476,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
+ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ size_t frame_len,
+- int rate);
++ struct ieee80211_rate *rate);
+
+ /**
+ * ieee80211_get_buffered_bc - accessing buffered broadcast and multicast frames
+@@ -1507,6 +1526,21 @@ int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb);
+ int ieee80211_get_hdrlen(u16 fc);
+
+ /**
++ * ieee80211_get_tkip_key - get a TKIP rc4 for skb
++ *
++ * This function computes a TKIP rc4 key for an skb. It computes
++ * a phase 1 key if needed (iv16 wraps around). This function is to
++ * be used by drivers which can do HW encryption but need to compute
++ * to phase 1/2 key in SW.
++ *
++ * @keyconf: the parameter passed with the set key
++ * @skb: the skb for which the key is needed
++ * @rc4key: a buffer to which the key will be written
++ */
++void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf,
++ struct sk_buff *skb,
++ enum ieee80211_tkip_key_type type, u8 *key);
++/**
+ * ieee80211_wake_queue - wake specific queue
+ * @hw: pointer as obtained from ieee80211_alloc_hw().
+ * @queue: queue number (counted from zero).
+@@ -1574,4 +1608,92 @@ void ieee80211_iterate_active_interfaces(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif),
+ void *data);
+
++/**
++ * ieee80211_start_tx_ba_session - Start a tx Block Ack session.
++ * @hw: pointer as obtained from ieee80211_alloc_hw().
++ * @ra: receiver address of the BA session recipient
++ * @tid: the TID to BA on.
++ * @return: success if addBA request was sent, failure otherwise
++ *
++ * Although mac80211/low level driver/user space application can estimate
++ * the need to start aggregation on a certain RA/TID, the session level
++ * will be managed by the mac80211.
++ */
++int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid);
++
++/**
++ * ieee80211_start_tx_ba_cb - low level driver ready to aggregate.
++ * @hw: pointer as obtained from ieee80211_alloc_hw().
++ * @ra: receiver address of the BA session recipient.
++ * @tid: the TID to BA on.
++ *
++ * This function must be called by low level driver once it has
++ * finished with preparations for the BA session.
++ */
++void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid);
++
++/**
++ * ieee80211_start_tx_ba_cb_irqsafe - low level driver ready to aggregate.
++ * @hw: pointer as obtained from ieee80211_alloc_hw().
++ * @ra: receiver address of the BA session recipient.
++ * @tid: the TID to BA on.
++ *
++ * This function must be called by low level driver once it has
++ * finished with preparations for the BA session.
++ * This version of the function is irq safe.
++ */
++void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra,
++ u16 tid);
++
++/**
++ * ieee80211_stop_tx_ba_session - Stop a Block Ack session.
++ * @hw: pointer as obtained from ieee80211_alloc_hw().
++ * @ra: receiver address of the BA session recipient
++ * @tid: the TID to stop BA.
++ * @initiator: if indicates initiator DELBA frame will be sent.
++ * @return: error if no sta with matching da found, success otherwise
++ *
++ * Although mac80211/low level driver/user space application can estimate
++ * the need to stop aggregation on a certain RA/TID, the session level
++ * will be managed by the mac80211.
++ */
++int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
++ u8 *ra, u16 tid,
++ enum ieee80211_back_parties initiator);
++
++/**
++ * ieee80211_stop_tx_ba_cb - low level driver ready to stop aggregate.
++ * @hw: pointer as obtained from ieee80211_alloc_hw().
++ * @ra: receiver address of the BA session recipient.
++ * @tid: the desired TID to BA on.
++ *
++ * This function must be called by low level driver once it has
++ * finished with preparations for the BA session tear down.
++ */
++void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid);
++
++/**
++ * ieee80211_stop_tx_ba_cb_irqsafe - low level driver ready to stop aggregate.
++ * @hw: pointer as obtained from ieee80211_alloc_hw().
++ * @ra: receiver address of the BA session recipient.
++ * @tid: the desired TID to BA on.
++ *
++ * This function must be called by low level driver once it has
++ * finished with preparations for the BA session tear down.
++ * This version of the function is irq safe.
++ */
++void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra,
++ u16 tid);
++
++/**
++ * ieee80211_notify_mac - low level driver notification
++ * @hw: pointer as obtained from ieee80211_alloc_hw().
++ * @notification_types: enum ieee80211_notification_types
++ *
++ * This function must be called by low level driver to inform mac80211 of
++ * low level driver status change or force mac80211 to re-assoc for low
++ * level driver internal error that require re-assoc.
++ */
++void ieee80211_notify_mac(struct ieee80211_hw *hw,
++ enum ieee80211_notification_types notif_type);
+ #endif /* MAC80211_H */
+diff --git a/include/net/mip6.h b/include/net/mip6.h
+index 6327261..a83ad19 100644
+--- a/include/net/mip6.h
++++ b/include/net/mip6.h
+@@ -28,9 +28,6 @@
+ #include <linux/skbuff.h>
+ #include <net/sock.h>
+
+-#define MIP6_OPT_PAD_1 0
+-#define MIP6_OPT_PAD_N 1
+-
+ /*
+ * Mobility Header
+ */
+diff --git a/include/net/ndisc.h b/include/net/ndisc.h
+index 59b7062..9c451ff 100644
+--- a/include/net/ndisc.h
++++ b/include/net/ndisc.h
+@@ -12,6 +12,15 @@
+ #define NDISC_REDIRECT 137
+
+ /*
++ * Router type: cross-layer information from link-layer to
++ * IPv6 layer reported by certain link types (e.g., RFC4214).
++ */
++#define NDISC_NODETYPE_UNSPEC 0 /* unspecified (default) */
++#define NDISC_NODETYPE_HOST 1 /* host or unauthorized router */
++#define NDISC_NODETYPE_NODEFAULT 2 /* non-default router */
++#define NDISC_NODETYPE_DEFAULT 3 /* default router */
++
++/*
+ * ndisc options
+ */
+
+@@ -77,7 +86,7 @@ struct nd_opt_hdr {
+ } __attribute__((__packed__));
+
+
+-extern int ndisc_init(struct net_proto_family *ops);
++extern int ndisc_init(void);
+
+ extern void ndisc_cleanup(void);
+
+@@ -85,20 +94,17 @@ extern int ndisc_rcv(struct sk_buff *skb);
+
+ extern void ndisc_send_ns(struct net_device *dev,
+ struct neighbour *neigh,
+- struct in6_addr *solicit,
+- struct in6_addr *daddr,
+- struct in6_addr *saddr);
++ const struct in6_addr *solicit,
++ const struct in6_addr *daddr,
++ const struct in6_addr *saddr);
+
+ extern void ndisc_send_rs(struct net_device *dev,
+- struct in6_addr *saddr,
+- struct in6_addr *daddr);
+-
+-extern void ndisc_forwarding_on(void);
+-extern void ndisc_forwarding_off(void);
++ const struct in6_addr *saddr,
++ const struct in6_addr *daddr);
+
+ extern void ndisc_send_redirect(struct sk_buff *skb,
+ struct neighbour *neigh,
+- struct in6_addr *target);
++ const struct in6_addr *target);
+
+ extern int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir);
+
+@@ -107,7 +113,7 @@ extern int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *d
+ /*
+ * IGMP
+ */
+-extern int igmp6_init(struct net_proto_family *ops);
++extern int igmp6_init(void);
+
+ extern void igmp6_cleanup(void);
+
+@@ -115,7 +121,6 @@ extern int igmp6_event_query(struct sk_buff *skb);
+
+ extern int igmp6_event_report(struct sk_buff *skb);
+
+-extern void igmp6_cleanup(void);
+
+ #ifdef CONFIG_SYSCTL
+ extern int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl,
+@@ -129,7 +134,7 @@ extern int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl,
+ extern void inet6_ifinfo_notify(int event,
+ struct inet6_dev *idev);
+
+-static inline struct neighbour * ndisc_get_neigh(struct net_device *dev, struct in6_addr *addr)
++static inline struct neighbour * ndisc_get_neigh(struct net_device *dev, const struct in6_addr *addr)
+ {
+
+ if (dev)
+diff --git a/include/net/neighbour.h b/include/net/neighbour.h
+index 64a5f01..dc420fe 100644
+--- a/include/net/neighbour.h
++++ b/include/net/neighbour.h
+@@ -38,7 +38,9 @@ struct neighbour;
+
+ struct neigh_parms
+ {
++#ifdef CONFIG_NET_NS
+ struct net *net;
++#endif
+ struct net_device *dev;
+ struct neigh_parms *next;
+ int (*neigh_setup)(struct neighbour *);
+@@ -131,7 +133,9 @@ struct neigh_ops
+ struct pneigh_entry
+ {
+ struct pneigh_entry *next;
++#ifdef CONFIG_NET_NS
+ struct net *net;
++#endif
+ struct net_device *dev;
+ u8 flags;
+ u8 key[0];
+@@ -213,6 +217,17 @@ extern struct neighbour *neigh_event_ns(struct neigh_table *tbl,
+
+ extern struct neigh_parms *neigh_parms_alloc(struct net_device *dev, struct neigh_table *tbl);
+ extern void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms);
++
++static inline
++struct net *neigh_parms_net(const struct neigh_parms *parms)
++{
++#ifdef CONFIG_NET_NS
++ return parms->net;
++#else
++ return &init_net;
++#endif
++}
++
+ extern unsigned long neigh_rand_reach_time(unsigned long base);
+
+ extern void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
+@@ -224,6 +239,16 @@ extern struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
+ struct net_device *dev);
+ extern int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev);
+
++static inline
++struct net *pneigh_net(const struct pneigh_entry *pneigh)
++{
++#ifdef CONFIG_NET_NS
++ return pneigh->net;
++#else
++ return &init_net;
++#endif
++}
++
+ extern void neigh_app_ns(struct neighbour *n);
+ extern void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie);
+ extern void __neigh_for_each_release(struct neigh_table *tbl, int (*cb)(struct neighbour *));
+@@ -288,12 +313,6 @@ static inline void neigh_confirm(struct neighbour *neigh)
+ neigh->confirmed = jiffies;
+ }
+
+-static inline int neigh_is_connected(struct neighbour *neigh)
+-{
+- return neigh->nud_state&NUD_CONNECTED;
+-}
+-
+-
+ static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
+ {
+ neigh->used = jiffies;
+diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
+index 923f2b8..aa540e6 100644
+--- a/include/net/net_namespace.h
++++ b/include/net/net_namespace.h
+@@ -8,24 +8,29 @@
+ #include <linux/workqueue.h>
+ #include <linux/list.h>
+
++#include <net/netns/core.h>
+ #include <net/netns/unix.h>
+ #include <net/netns/packet.h>
+ #include <net/netns/ipv4.h>
+ #include <net/netns/ipv6.h>
++#include <net/netns/dccp.h>
+ #include <net/netns/x_tables.h>
+
+ struct proc_dir_entry;
+ struct net_device;
+ struct sock;
+ struct ctl_table_header;
++struct net_generic;
+
+ struct net {
+ atomic_t count; /* To decided when the network
+ * namespace should be freed.
+ */
++#ifdef NETNS_REFCNT_DEBUG
+ atomic_t use_count; /* To track references we
+ * destroy on demand
+ */
++#endif
+ struct list_head list; /* list of network namespaces */
+ struct work_struct work; /* work struct for freeing */
+
+@@ -46,40 +51,46 @@ struct net {
+
+ struct sock *rtnl; /* rtnetlink socket */
+
+- /* core sysctls */
+- struct ctl_table_header *sysctl_core_hdr;
+- int sysctl_somaxconn;
+-
++ struct netns_core core;
+ struct netns_packet packet;
+ struct netns_unix unx;
+ struct netns_ipv4 ipv4;
+ #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ struct netns_ipv6 ipv6;
+ #endif
++#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
++ struct netns_dccp dccp;
++#endif
+ #ifdef CONFIG_NETFILTER
+ struct netns_xt xt;
+ #endif
++ struct net_generic *gen;
+ };
+
+-#ifdef CONFIG_NET
++
++#include <linux/seq_file_net.h>
++
+ /* Init's network namespace */
+ extern struct net init_net;
+-#define INIT_NET_NS(net_ns) .net_ns = &init_net,
+-#else
+-#define INIT_NET_NS(net_ns)
+-#endif
+-
+-extern struct list_head net_namespace_list;
+
+ #ifdef CONFIG_NET
++#define INIT_NET_NS(net_ns) .net_ns = &init_net,
++
+ extern struct net *copy_net_ns(unsigned long flags, struct net *net_ns);
+-#else
++
++#else /* CONFIG_NET */
++
++#define INIT_NET_NS(net_ns)
++
+ static inline struct net *copy_net_ns(unsigned long flags, struct net *net_ns)
+ {
+ /* There is nothing to copy so this is a noop */
+ return net_ns;
+ }
+-#endif
++#endif /* CONFIG_NET */
++
++
++extern struct list_head net_namespace_list;
+
+ #ifdef CONFIG_NET_NS
+ extern void __put_net(struct net *net);
+@@ -108,41 +119,59 @@ static inline void put_net(struct net *net)
+ __put_net(net);
+ }
+
+-static inline struct net *hold_net(struct net *net)
++static inline
++int net_eq(const struct net *net1, const struct net *net2)
++{
++ return net1 == net2;
++}
++#else
++static inline struct net *get_net(struct net *net)
+ {
+- atomic_inc(&net->use_count);
+ return net;
+ }
+
+-static inline void release_net(struct net *net)
++static inline void put_net(struct net *net)
+ {
+- atomic_dec(&net->use_count);
+ }
+-#else
+-static inline struct net *get_net(struct net *net)
++
++static inline struct net *maybe_get_net(struct net *net)
+ {
+ return net;
+ }
+
+-static inline void put_net(struct net *net)
++static inline
++int net_eq(const struct net *net1, const struct net *net2)
+ {
++ return 1;
+ }
++#endif
++
+
++#ifdef NETNS_REFCNT_DEBUG
+ static inline struct net *hold_net(struct net *net)
+ {
++ if (net)
++ atomic_inc(&net->use_count);
+ return net;
+ }
+
+ static inline void release_net(struct net *net)
+ {
++ if (net)
++ atomic_dec(&net->use_count);
+ }
+-
+-static inline struct net *maybe_get_net(struct net *net)
++#else
++static inline struct net *hold_net(struct net *net)
+ {
+ return net;
+ }
++
++static inline void release_net(struct net *net)
++{
++}
+ #endif
+
++
+ #define for_each_net(VAR) \
+ list_for_each_entry(VAR, &net_namespace_list, list)
+
+@@ -166,6 +195,8 @@ extern int register_pernet_subsys(struct pernet_operations *);
+ extern void unregister_pernet_subsys(struct pernet_operations *);
+ extern int register_pernet_device(struct pernet_operations *);
+ extern void unregister_pernet_device(struct pernet_operations *);
++extern int register_pernet_gen_device(int *id, struct pernet_operations *);
++extern void unregister_pernet_gen_device(int id, struct pernet_operations *);
+
+ struct ctl_path;
+ struct ctl_table;
+diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
+index 90b3e7f..2dbd6c0 100644
+--- a/include/net/netfilter/nf_conntrack.h
++++ b/include/net/netfilter/nf_conntrack.h
+@@ -20,6 +20,7 @@
+ #include <asm/atomic.h>
+
+ #include <linux/netfilter/nf_conntrack_tcp.h>
++#include <linux/netfilter/nf_conntrack_dccp.h>
+ #include <linux/netfilter/nf_conntrack_sctp.h>
+ #include <linux/netfilter/nf_conntrack_proto_gre.h>
+ #include <net/netfilter/ipv4/nf_conntrack_icmp.h>
+@@ -30,6 +31,7 @@
+ /* per conntrack: protocol private data */
+ union nf_conntrack_proto {
+ /* insert conntrack proto private data here */
++ struct nf_ct_dccp dccp;
+ struct ip_ct_sctp sctp;
+ struct ip_ct_tcp tcp;
+ struct ip_ct_icmp icmp;
+@@ -46,6 +48,7 @@ union nf_conntrack_expect_proto {
+ #include <linux/netfilter/nf_conntrack_pptp.h>
+ #include <linux/netfilter/nf_conntrack_h323.h>
+ #include <linux/netfilter/nf_conntrack_sane.h>
++#include <linux/netfilter/nf_conntrack_sip.h>
+
+ /* per conntrack: application helper private data */
+ union nf_conntrack_help {
+@@ -54,6 +57,7 @@ union nf_conntrack_help {
+ struct nf_ct_pptp_master ct_pptp_info;
+ struct nf_ct_h323_master ct_h323_info;
+ struct nf_ct_sane_master ct_sane_info;
++ struct nf_ct_sip_master ct_sip_info;
+ };
+
+ #include <linux/types.h>
+@@ -61,20 +65,16 @@ union nf_conntrack_help {
+ #include <linux/timer.h>
+
+ #ifdef CONFIG_NETFILTER_DEBUG
+-#define NF_CT_ASSERT(x) \
+-do { \
+- if (!(x)) \
+- /* Wooah! I'm tripping my conntrack in a frenzy of \
+- netplay... */ \
+- printk("NF_CT_ASSERT: %s:%i(%s)\n", \
+- __FILE__, __LINE__, __FUNCTION__); \
+-} while(0)
++#define NF_CT_ASSERT(x) WARN_ON(!(x))
+ #else
+ #define NF_CT_ASSERT(x)
+ #endif
+
+ struct nf_conntrack_helper;
+
++/* Must be kept in sync with the classes defined by helpers */
++#define NF_CT_MAX_EXPECT_CLASSES 3
++
+ /* nf_conn feature for connections that have a helper */
+ struct nf_conn_help {
+ /* Helper. if any */
+@@ -85,7 +85,7 @@ struct nf_conn_help {
+ struct hlist_head expectations;
+
+ /* Current number of expected connections */
+- unsigned int expecting;
++ u8 expecting[NF_CT_MAX_EXPECT_CLASSES];
+ };
+
+
+@@ -140,6 +140,16 @@ nf_ct_tuplehash_to_ctrack(const struct nf_conntrack_tuple_hash *hash)
+ tuplehash[hash->tuple.dst.dir]);
+ }
+
++static inline u_int16_t nf_ct_l3num(const struct nf_conn *ct)
++{
++ return ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
++}
++
++static inline u_int8_t nf_ct_protonum(const struct nf_conn *ct)
++{
++ return ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
++}
++
+ /* get master conntrack via master expectation */
+ #define master_ct(conntr) (conntr->master)
+
+@@ -184,12 +194,11 @@ extern void nf_conntrack_hash_insert(struct nf_conn *ct);
+
+ extern void nf_conntrack_flush(void);
+
+-extern int nf_ct_get_tuplepr(const struct sk_buff *skb,
+- unsigned int nhoff,
+- u_int16_t l3num,
+- struct nf_conntrack_tuple *tuple);
+-extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
+- const struct nf_conntrack_tuple *orig);
++extern bool nf_ct_get_tuplepr(const struct sk_buff *skb,
++ unsigned int nhoff, u_int16_t l3num,
++ struct nf_conntrack_tuple *tuple);
++extern bool nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
++ const struct nf_conntrack_tuple *orig);
+
+ extern void __nf_ct_refresh_acct(struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h
+index 9ee2646..a817712 100644
+--- a/include/net/netfilter/nf_conntrack_core.h
++++ b/include/net/netfilter/nf_conntrack_core.h
+@@ -30,7 +30,7 @@ extern void nf_conntrack_cleanup(void);
+ extern int nf_conntrack_proto_init(void);
+ extern void nf_conntrack_proto_fini(void);
+
+-extern int
++extern bool
+ nf_ct_get_tuple(const struct sk_buff *skb,
+ unsigned int nhoff,
+ unsigned int dataoff,
+@@ -40,7 +40,7 @@ nf_ct_get_tuple(const struct sk_buff *skb,
+ const struct nf_conntrack_l3proto *l3proto,
+ const struct nf_conntrack_l4proto *l4proto);
+
+-extern int
++extern bool
+ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
+ const struct nf_conntrack_tuple *orig,
+ const struct nf_conntrack_l3proto *l3proto,
+diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
+index cb608a1..dfdf4b4 100644
+--- a/include/net/netfilter/nf_conntrack_expect.h
++++ b/include/net/netfilter/nf_conntrack_expect.h
+@@ -41,6 +41,9 @@ struct nf_conntrack_expect
+ /* Flags */
+ unsigned int flags;
+
++ /* Expectation class */
++ unsigned int class;
++
+ #ifdef CONFIG_NF_NAT_NEEDED
+ __be32 saved_ip;
+ /* This is the original per-proto part, used to map the
+@@ -53,7 +56,16 @@ struct nf_conntrack_expect
+ struct rcu_head rcu;
+ };
+
+-#define NF_CT_EXPECT_PERMANENT 0x1
++struct nf_conntrack_expect_policy
++{
++ unsigned int max_expected;
++ unsigned int timeout;
++};
++
++#define NF_CT_EXPECT_CLASS_DEFAULT 0
++
++#define NF_CT_EXPECT_PERMANENT 0x1
++#define NF_CT_EXPECT_INACTIVE 0x2
+
+ int nf_conntrack_expect_init(void);
+ void nf_conntrack_expect_fini(void);
+@@ -74,10 +86,10 @@ void nf_ct_unexpect_related(struct nf_conntrack_expect *exp);
+ /* Allocate space for an expectation: this is mandatory before calling
+ nf_ct_expect_related. You will have to call put afterwards. */
+ struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me);
+-void nf_ct_expect_init(struct nf_conntrack_expect *, int,
+- union nf_inet_addr *,
+- union nf_inet_addr *,
+- u_int8_t, __be16 *, __be16 *);
++void nf_ct_expect_init(struct nf_conntrack_expect *, unsigned int, int,
++ const union nf_inet_addr *,
++ const union nf_inet_addr *,
++ u_int8_t, const __be16 *, const __be16 *);
+ void nf_ct_expect_put(struct nf_conntrack_expect *exp);
+ int nf_ct_expect_related(struct nf_conntrack_expect *expect);
+
+diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
+index 4ca125e..f8060ab 100644
+--- a/include/net/netfilter/nf_conntrack_helper.h
++++ b/include/net/netfilter/nf_conntrack_helper.h
+@@ -20,9 +20,7 @@ struct nf_conntrack_helper
+
+ const char *name; /* name of the module */
+ struct module *me; /* pointer to self */
+- unsigned int max_expected; /* Maximum number of concurrent
+- * expected connections */
+- unsigned int timeout; /* timeout for expecteds */
++ const struct nf_conntrack_expect_policy *expect_policy;
+
+ /* Tuple of things we will help (compared against server response) */
+ struct nf_conntrack_tuple tuple;
+@@ -37,6 +35,7 @@ struct nf_conntrack_helper
+ void (*destroy)(struct nf_conn *ct);
+
+ int (*to_nlattr)(struct sk_buff *skb, const struct nf_conn *ct);
++ unsigned int expect_class_max;
+ };
+
+ extern struct nf_conntrack_helper *
+diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
+index b886e3a..0378676 100644
+--- a/include/net/netfilter/nf_conntrack_l3proto.h
++++ b/include/net/netfilter/nf_conntrack_l3proto.h
+@@ -28,31 +28,20 @@ struct nf_conntrack_l3proto
+ * Try to fill in the third arg: nhoff is offset of l3 proto
+ * hdr. Return true if possible.
+ */
+- int (*pkt_to_tuple)(const struct sk_buff *skb, unsigned int nhoff,
+- struct nf_conntrack_tuple *tuple);
++ bool (*pkt_to_tuple)(const struct sk_buff *skb, unsigned int nhoff,
++ struct nf_conntrack_tuple *tuple);
+
+ /*
+ * Invert the per-proto part of the tuple: ie. turn xmit into reply.
+ * Some packets can't be inverted: return 0 in that case.
+ */
+- int (*invert_tuple)(struct nf_conntrack_tuple *inverse,
+- const struct nf_conntrack_tuple *orig);
++ bool (*invert_tuple)(struct nf_conntrack_tuple *inverse,
++ const struct nf_conntrack_tuple *orig);
+
+ /* Print out the per-protocol part of the tuple. */
+ int (*print_tuple)(struct seq_file *s,
+ const struct nf_conntrack_tuple *);
+
+- /* Returns verdict for packet, or -1 for invalid. */
+- int (*packet)(struct nf_conn *ct,
+- const struct sk_buff *skb,
+- enum ip_conntrack_info ctinfo);
+-
+- /*
+- * Called when a new connection for this protocol found;
+- * returns TRUE if it's OK. If so, packet() called next.
+- */
+- int (*new)(struct nf_conn *ct, const struct sk_buff *skb);
+-
+ /*
+ * Called before tracking.
+ * *dataoff: offset of protocol header (TCP, UDP,...) in skb
+diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h
+index efc16ec..723df9d 100644
+--- a/include/net/netfilter/nf_conntrack_l4proto.h
++++ b/include/net/netfilter/nf_conntrack_l4proto.h
+@@ -25,15 +25,14 @@ struct nf_conntrack_l4proto
+
+ /* Try to fill in the third arg: dataoff is offset past network protocol
+ hdr. Return true if possible. */
+- int (*pkt_to_tuple)(const struct sk_buff *skb,
+- unsigned int dataoff,
+- struct nf_conntrack_tuple *tuple);
++ bool (*pkt_to_tuple)(const struct sk_buff *skb, unsigned int dataoff,
++ struct nf_conntrack_tuple *tuple);
+
+ /* Invert the per-proto part of the tuple: ie. turn xmit into reply.
+ * Some packets can't be inverted: return 0 in that case.
+ */
+- int (*invert_tuple)(struct nf_conntrack_tuple *inverse,
+- const struct nf_conntrack_tuple *orig);
++ bool (*invert_tuple)(struct nf_conntrack_tuple *inverse,
++ const struct nf_conntrack_tuple *orig);
+
+ /* Returns verdict for packet, or -1 for invalid. */
+ int (*packet)(struct nf_conn *ct,
+@@ -45,8 +44,8 @@ struct nf_conntrack_l4proto
+
+ /* Called when a new connection for this protocol found;
+ * returns TRUE if it's OK. If so, packet() called next. */
+- int (*new)(struct nf_conn *ct, const struct sk_buff *skb,
+- unsigned int dataoff);
++ bool (*new)(struct nf_conn *ct, const struct sk_buff *skb,
++ unsigned int dataoff);
+
+ /* Called when a conntrack entry is destroyed */
+ void (*destroy)(struct nf_conn *ct);
+diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h
+index e69ab2e..1bb7087 100644
+--- a/include/net/netfilter/nf_conntrack_tuple.h
++++ b/include/net/netfilter/nf_conntrack_tuple.h
+@@ -41,6 +41,9 @@ union nf_conntrack_man_proto
+ } icmp;
+ struct {
+ __be16 port;
++ } dccp;
++ struct {
++ __be16 port;
+ } sctp;
+ struct {
+ __be16 key; /* GRE key is 32bit, PPtP only uses 16bit */
+@@ -79,6 +82,9 @@ struct nf_conntrack_tuple
+ } icmp;
+ struct {
+ __be16 port;
++ } dccp;
++ struct {
++ __be16 port;
+ } sctp;
+ struct {
+ __be16 key;
+@@ -113,11 +119,37 @@ struct nf_conntrack_tuple_mask
+
+ #ifdef __KERNEL__
+
+-#define NF_CT_DUMP_TUPLE(tp) \
+-pr_debug("tuple %p: %u %u " NIP6_FMT " %hu -> " NIP6_FMT " %hu\n", \
+- (tp), (tp)->src.l3num, (tp)->dst.protonum, \
+- NIP6(*(struct in6_addr *)(tp)->src.u3.all), ntohs((tp)->src.u.all), \
+- NIP6(*(struct in6_addr *)(tp)->dst.u3.all), ntohs((tp)->dst.u.all))
++static inline void nf_ct_dump_tuple_ip(const struct nf_conntrack_tuple *t)
++{
++#ifdef DEBUG
++ printk("tuple %p: %u " NIPQUAD_FMT ":%hu -> " NIPQUAD_FMT ":%hu\n",
++ t, t->dst.protonum,
++ NIPQUAD(t->src.u3.ip), ntohs(t->src.u.all),
++ NIPQUAD(t->dst.u3.ip), ntohs(t->dst.u.all));
++#endif
++}
++
++static inline void nf_ct_dump_tuple_ipv6(const struct nf_conntrack_tuple *t)
++{
++#ifdef DEBUG
++ printk("tuple %p: %u " NIP6_FMT " %hu -> " NIP6_FMT " %hu\n",
++ t, t->dst.protonum,
++ NIP6(*(struct in6_addr *)t->src.u3.all), ntohs(t->src.u.all),
++ NIP6(*(struct in6_addr *)t->dst.u3.all), ntohs(t->dst.u.all));
++#endif
++}
++
++static inline void nf_ct_dump_tuple(const struct nf_conntrack_tuple *t)
++{
++ switch (t->src.l3num) {
++ case AF_INET:
++ nf_ct_dump_tuple_ip(t);
++ break;
++ case AF_INET6:
++ nf_ct_dump_tuple_ipv6(t);
++ break;
++ }
++}
+
+ /* If we're the first tuple, it's the original dir. */
+ #define NF_CT_DIRECTION(h) \
+@@ -132,70 +164,64 @@ struct nf_conntrack_tuple_hash
+
+ #endif /* __KERNEL__ */
+
+-static inline int __nf_ct_tuple_src_equal(const struct nf_conntrack_tuple *t1,
+- const struct nf_conntrack_tuple *t2)
++static inline bool __nf_ct_tuple_src_equal(const struct nf_conntrack_tuple *t1,
++ const struct nf_conntrack_tuple *t2)
+ {
+- return (t1->src.u3.all[0] == t2->src.u3.all[0] &&
+- t1->src.u3.all[1] == t2->src.u3.all[1] &&
+- t1->src.u3.all[2] == t2->src.u3.all[2] &&
+- t1->src.u3.all[3] == t2->src.u3.all[3] &&
++ return (nf_inet_addr_cmp(&t1->src.u3, &t2->src.u3) &&
+ t1->src.u.all == t2->src.u.all &&
+ t1->src.l3num == t2->src.l3num);
+ }
+
+-static inline int __nf_ct_tuple_dst_equal(const struct nf_conntrack_tuple *t1,
+- const struct nf_conntrack_tuple *t2)
++static inline bool __nf_ct_tuple_dst_equal(const struct nf_conntrack_tuple *t1,
++ const struct nf_conntrack_tuple *t2)
+ {
+- return (t1->dst.u3.all[0] == t2->dst.u3.all[0] &&
+- t1->dst.u3.all[1] == t2->dst.u3.all[1] &&
+- t1->dst.u3.all[2] == t2->dst.u3.all[2] &&
+- t1->dst.u3.all[3] == t2->dst.u3.all[3] &&
++ return (nf_inet_addr_cmp(&t1->dst.u3, &t2->dst.u3) &&
+ t1->dst.u.all == t2->dst.u.all &&
+ t1->dst.protonum == t2->dst.protonum);
+ }
+
+-static inline int nf_ct_tuple_equal(const struct nf_conntrack_tuple *t1,
+- const struct nf_conntrack_tuple *t2)
++static inline bool nf_ct_tuple_equal(const struct nf_conntrack_tuple *t1,
++ const struct nf_conntrack_tuple *t2)
+ {
+ return __nf_ct_tuple_src_equal(t1, t2) &&
+ __nf_ct_tuple_dst_equal(t1, t2);
+ }
+
+-static inline int nf_ct_tuple_mask_equal(const struct nf_conntrack_tuple_mask *m1,
+- const struct nf_conntrack_tuple_mask *m2)
++static inline bool
++nf_ct_tuple_mask_equal(const struct nf_conntrack_tuple_mask *m1,
++ const struct nf_conntrack_tuple_mask *m2)
+ {
+- return (m1->src.u3.all[0] == m2->src.u3.all[0] &&
+- m1->src.u3.all[1] == m2->src.u3.all[1] &&
+- m1->src.u3.all[2] == m2->src.u3.all[2] &&
+- m1->src.u3.all[3] == m2->src.u3.all[3] &&
++ return (nf_inet_addr_cmp(&m1->src.u3, &m2->src.u3) &&
+ m1->src.u.all == m2->src.u.all);
+ }
+
+-static inline int nf_ct_tuple_src_mask_cmp(const struct nf_conntrack_tuple *t1,
+- const struct nf_conntrack_tuple *t2,
+- const struct nf_conntrack_tuple_mask *mask)
++static inline bool
++nf_ct_tuple_src_mask_cmp(const struct nf_conntrack_tuple *t1,
++ const struct nf_conntrack_tuple *t2,
++ const struct nf_conntrack_tuple_mask *mask)
+ {
+ int count;
+
+ for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++) {
+ if ((t1->src.u3.all[count] ^ t2->src.u3.all[count]) &
+ mask->src.u3.all[count])
+- return 0;
++ return false;
+ }
+
+ if ((t1->src.u.all ^ t2->src.u.all) & mask->src.u.all)
+- return 0;
++ return false;
+
+ if (t1->src.l3num != t2->src.l3num ||
+ t1->dst.protonum != t2->dst.protonum)
+- return 0;
++ return false;
+
+- return 1;
++ return true;
+ }
+
+-static inline int nf_ct_tuple_mask_cmp(const struct nf_conntrack_tuple *t,
+- const struct nf_conntrack_tuple *tuple,
+- const struct nf_conntrack_tuple_mask *mask)
++static inline bool
++nf_ct_tuple_mask_cmp(const struct nf_conntrack_tuple *t,
++ const struct nf_conntrack_tuple *tuple,
++ const struct nf_conntrack_tuple_mask *mask)
+ {
+ return nf_ct_tuple_src_mask_cmp(t, tuple, mask) &&
+ __nf_ct_tuple_dst_equal(t, tuple);
+diff --git a/include/net/netfilter/nf_nat_helper.h b/include/net/netfilter/nf_nat_helper.h
+index 58dd226..237a961 100644
+--- a/include/net/netfilter/nf_nat_helper.h
++++ b/include/net/netfilter/nf_nat_helper.h
+@@ -24,6 +24,9 @@ extern int nf_nat_mangle_udp_packet(struct sk_buff *skb,
+ extern int nf_nat_seq_adjust(struct sk_buff *skb,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo);
++extern int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb,
++ struct nf_conn *ct,
++ enum ip_conntrack_info ctinfo);
+
+ /* Setup NAT on this expected conntrack so it follows master, but goes
+ * to port ct->master->saved_proto. */
+diff --git a/include/net/netfilter/nf_nat_protocol.h b/include/net/netfilter/nf_nat_protocol.h
+index 4aa0edb..f3662c4 100644
+--- a/include/net/netfilter/nf_nat_protocol.h
++++ b/include/net/netfilter/nf_nat_protocol.h
+@@ -8,9 +8,6 @@ struct nf_nat_range;
+
+ struct nf_nat_protocol
+ {
+- /* Protocol name */
+- const char *name;
+-
+ /* Protocol number. */
+ unsigned int protonum;
+
+@@ -18,25 +15,25 @@ struct nf_nat_protocol
+
+ /* Translate a packet to the target according to manip type.
+ Return true if succeeded. */
+- int (*manip_pkt)(struct sk_buff *skb,
+- unsigned int iphdroff,
+- const struct nf_conntrack_tuple *tuple,
+- enum nf_nat_manip_type maniptype);
++ bool (*manip_pkt)(struct sk_buff *skb,
++ unsigned int iphdroff,
++ const struct nf_conntrack_tuple *tuple,
++ enum nf_nat_manip_type maniptype);
+
+ /* Is the manipable part of the tuple between min and max incl? */
+- int (*in_range)(const struct nf_conntrack_tuple *tuple,
+- enum nf_nat_manip_type maniptype,
+- const union nf_conntrack_man_proto *min,
+- const union nf_conntrack_man_proto *max);
++ bool (*in_range)(const struct nf_conntrack_tuple *tuple,
++ enum nf_nat_manip_type maniptype,
++ const union nf_conntrack_man_proto *min,
++ const union nf_conntrack_man_proto *max);
+
+ /* Alter the per-proto part of the tuple (depending on
+ maniptype), to give a unique tuple in the given range if
+ possible; return false if not. Per-protocol part of tuple
+ is initialized to the incoming packet. */
+- int (*unique_tuple)(struct nf_conntrack_tuple *tuple,
+- const struct nf_nat_range *range,
+- enum nf_nat_manip_type maniptype,
+- const struct nf_conn *ct);
++ bool (*unique_tuple)(struct nf_conntrack_tuple *tuple,
++ const struct nf_nat_range *range,
++ enum nf_nat_manip_type maniptype,
++ const struct nf_conn *ct);
+
+ int (*range_to_nlattr)(struct sk_buff *skb,
+ const struct nf_nat_range *range);
+@@ -62,9 +59,20 @@ extern int init_protocols(void) __init;
+ extern void cleanup_protocols(void);
+ extern const struct nf_nat_protocol *find_nat_proto(u_int16_t protonum);
+
+-extern int nf_nat_port_range_to_nlattr(struct sk_buff *skb,
+- const struct nf_nat_range *range);
+-extern int nf_nat_port_nlattr_to_range(struct nlattr *tb[],
+- struct nf_nat_range *range);
++extern bool nf_nat_proto_in_range(const struct nf_conntrack_tuple *tuple,
++ enum nf_nat_manip_type maniptype,
++ const union nf_conntrack_man_proto *min,
++ const union nf_conntrack_man_proto *max);
++
++extern bool nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,
++ const struct nf_nat_range *range,
++ enum nf_nat_manip_type maniptype,
++ const struct nf_conn *ct,
++ u_int16_t *rover);
++
++extern int nf_nat_proto_range_to_nlattr(struct sk_buff *skb,
++ const struct nf_nat_range *range);
++extern int nf_nat_proto_nlattr_to_range(struct nlattr *tb[],
++ struct nf_nat_range *range);
+
+ #endif /*_NF_NAT_PROTO_H*/
+diff --git a/include/net/netfilter/nf_nat_rule.h b/include/net/netfilter/nf_nat_rule.h
+index 75d1825..e4a18ae 100644
+--- a/include/net/netfilter/nf_nat_rule.h
++++ b/include/net/netfilter/nf_nat_rule.h
+@@ -14,7 +14,4 @@ extern int nf_nat_rule_find(struct sk_buff *skb,
+
+ extern unsigned int
+ alloc_null_binding(struct nf_conn *ct, unsigned int hooknum);
+-
+-extern unsigned int
+-alloc_null_binding_confirmed(struct nf_conn *ct, unsigned int hooknum);
+ #endif /* _NF_NAT_RULE_H */
+diff --git a/include/net/netlabel.h b/include/net/netlabel.h
+index 0ca67d7..5e53a85 100644
+--- a/include/net/netlabel.h
++++ b/include/net/netlabel.h
+@@ -162,7 +162,7 @@ struct netlbl_lsm_secattr_catmap {
+
+ /**
+ * struct netlbl_lsm_secattr - NetLabel LSM security attributes
+- * @flags: indicate which attributes are contained in this structure
++ * @flags: indicate structure attributes, see NETLBL_SECATTR_*
+ * @type: indicate the NLTYPE of the attributes
+ * @domain: the NetLabel LSM domain
+ * @cache: NetLabel LSM specific cache
+@@ -180,17 +180,22 @@ struct netlbl_lsm_secattr_catmap {
+ * NetLabel itself when returning security attributes to the LSM.
+ *
+ */
++struct netlbl_lsm_secattr {
++ u32 flags;
++ /* bitmap values for 'flags' */
+ #define NETLBL_SECATTR_NONE 0x00000000
+ #define NETLBL_SECATTR_DOMAIN 0x00000001
++#define NETLBL_SECATTR_DOMAIN_CPY (NETLBL_SECATTR_DOMAIN | \
++ NETLBL_SECATTR_FREE_DOMAIN)
+ #define NETLBL_SECATTR_CACHE 0x00000002
+ #define NETLBL_SECATTR_MLS_LVL 0x00000004
+ #define NETLBL_SECATTR_MLS_CAT 0x00000008
+ #define NETLBL_SECATTR_SECID 0x00000010
++ /* bitmap meta-values for 'flags' */
++#define NETLBL_SECATTR_FREE_DOMAIN 0x01000000
+ #define NETLBL_SECATTR_CACHEABLE (NETLBL_SECATTR_MLS_LVL | \
+ NETLBL_SECATTR_MLS_CAT | \
+ NETLBL_SECATTR_SECID)
+-struct netlbl_lsm_secattr {
+- u32 flags;
+ u32 type;
+ char *domain;
+ struct netlbl_lsm_cache *cache;
+@@ -303,7 +308,8 @@ static inline void netlbl_secattr_init(struct netlbl_lsm_secattr *secattr)
+ */
+ static inline void netlbl_secattr_destroy(struct netlbl_lsm_secattr *secattr)
+ {
+- kfree(secattr->domain);
++ if (secattr->flags & NETLBL_SECATTR_FREE_DOMAIN)
++ kfree(secattr->domain);
+ if (secattr->flags & NETLBL_SECATTR_CACHE)
+ netlbl_secattr_cache_free(secattr->cache);
+ if (secattr->flags & NETLBL_SECATTR_MLS_CAT)
+diff --git a/include/net/netns/core.h b/include/net/netns/core.h
+new file mode 100644
+index 0000000..24d4be7
+--- /dev/null
++++ b/include/net/netns/core.h
+@@ -0,0 +1,16 @@
++#ifndef __NETNS_CORE_H__
++#define __NETNS_CORE_H__
++
++struct ctl_table_header;
++struct prot_inuse;
++
++struct netns_core {
++ /* core sysctls */
++ struct ctl_table_header *sysctl_hdr;
++
++ int sysctl_somaxconn;
++
++ struct prot_inuse *inuse;
++};
++
++#endif
+diff --git a/include/net/netns/dccp.h b/include/net/netns/dccp.h
+new file mode 100644
+index 0000000..98d2a7c
+--- /dev/null
++++ b/include/net/netns/dccp.h
+@@ -0,0 +1,11 @@
++#ifndef __NETNS_DCCP_H__
++#define __NETNS_DCCP_H__
++
++struct sock;
++
++struct netns_dccp {
++ struct sock *v4_ctl_sk;
++ struct sock *v6_ctl_sk;
++};
++
++#endif
+diff --git a/include/net/netns/generic.h b/include/net/netns/generic.h
+new file mode 100644
+index 0000000..0c04fd2
+--- /dev/null
++++ b/include/net/netns/generic.h
+@@ -0,0 +1,49 @@
++/*
++ * generic net pointers
++ */
++
++#ifndef __NET_GENERIC_H__
++#define __NET_GENERIC_H__
++
++#include <linux/rcupdate.h>
++
++/*
++ * Generic net pointers are to be used by modules to put some private
++ * stuff on the struct net without explicit struct net modification
++ *
++ * The rules are simple:
++ * 1. register the ops with register_pernet_gen_device to get the id
++ * of your private pointer;
++ * 2. call net_assign_generic() to put the private data on the struct
++ * net (most preferably this should be done in the ->init callback
++ * of the ops registered);
++ * 3. do not change this pointer while the net is alive;
++ * 4. do not try to have any private reference on the net_generic object.
++ *
++ * After accomplishing all of the above, the private pointer can be
++ * accessed with the net_generic() call.
++ */
++
++struct net_generic {
++ unsigned int len;
++ struct rcu_head rcu;
++
++ void *ptr[0];
++};
++
++static inline void *net_generic(struct net *net, int id)
++{
++ struct net_generic *ng;
++ void *ptr;
++
++ rcu_read_lock();
++ ng = rcu_dereference(net->gen);
++ BUG_ON(id == 0 || id > ng->len);
++ ptr = ng->ptr[id - 1];
++ rcu_read_unlock();
++
++ return ptr;
++}
++
++extern int net_assign_generic(struct net *net, int id, void *data);
++#endif
+diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
+index a9b4f60..34ee348 100644
+--- a/include/net/netns/ipv4.h
++++ b/include/net/netns/ipv4.h
+@@ -17,6 +17,7 @@ struct netns_ipv4 {
+ #ifdef CONFIG_SYSCTL
+ struct ctl_table_header *forw_hdr;
+ struct ctl_table_header *frags_hdr;
++ struct ctl_table_header *ipv4_hdr;
+ #endif
+ struct ipv4_devconf *devconf_all;
+ struct ipv4_devconf *devconf_dflt;
+@@ -26,6 +27,9 @@ struct netns_ipv4 {
+ struct hlist_head *fib_table_hash;
+ struct sock *fibnl;
+
++ struct sock **icmp_sk;
++ struct sock *tcp_sock;
++
+ struct netns_frags frags;
+ #ifdef CONFIG_NETFILTER
+ struct xt_table *iptable_filter;
+@@ -33,5 +37,12 @@ struct netns_ipv4 {
+ struct xt_table *iptable_raw;
+ struct xt_table *arptable_filter;
+ #endif
++
++ int sysctl_icmp_echo_ignore_all;
++ int sysctl_icmp_echo_ignore_broadcasts;
++ int sysctl_icmp_ignore_bogus_error_responses;
++ int sysctl_icmp_ratelimit;
++ int sysctl_icmp_ratemask;
++ int sysctl_icmp_errors_use_inbound_ifaddr;
+ };
+ #endif
+diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
+index 1dd7de4..ac053be 100644
+--- a/include/net/netns/ipv6.h
++++ b/include/net/netns/ipv6.h
+@@ -36,5 +36,23 @@ struct netns_ipv6 {
+ struct xt_table *ip6table_mangle;
+ struct xt_table *ip6table_raw;
+ #endif
++ struct rt6_info *ip6_null_entry;
++ struct rt6_statistics *rt6_stats;
++ struct timer_list *ip6_fib_timer;
++ struct hlist_head *fib_table_hash;
++ struct fib6_table *fib6_main_tbl;
++ struct dst_ops *ip6_dst_ops;
++ unsigned int ip6_rt_gc_expire;
++ unsigned long ip6_rt_last_gc;
++#ifdef CONFIG_IPV6_MULTIPLE_TABLES
++ struct rt6_info *ip6_prohibit_entry;
++ struct rt6_info *ip6_blk_hole_entry;
++ struct fib6_table *fib6_local_tbl;
++ struct fib_rules_ops *fib6_rules_ops;
++#endif
++ struct sock **icmp_sk;
++ struct sock *ndisc_sk;
++ struct sock *tcp_sk;
++ struct sock *igmp_sk;
+ };
+ #endif
+diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
+index d349c66..aa9e282 100644
+--- a/include/net/pkt_cls.h
++++ b/include/net/pkt_cls.h
+@@ -353,7 +353,7 @@ tcf_match_indev(struct sk_buff *skb, char *indev)
+ if (indev[0]) {
+ if (!skb->iif)
+ return 0;
+- dev = __dev_get_by_index(&init_net, skb->iif);
++ dev = __dev_get_by_index(dev_net(skb->dev), skb->iif);
+ if (!dev || strcmp(indev, dev->name))
+ return 0;
+ }
+diff --git a/include/net/protocol.h b/include/net/protocol.h
+index ad8c584..8d024d7 100644
+--- a/include/net/protocol.h
++++ b/include/net/protocol.h
+@@ -39,7 +39,8 @@ struct net_protocol {
+ int (*gso_send_check)(struct sk_buff *skb);
+ struct sk_buff *(*gso_segment)(struct sk_buff *skb,
+ int features);
+- int no_policy;
++ unsigned int no_policy:1,
++ netns_ok:1;
+ };
+
+ #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+diff --git a/include/net/raw.h b/include/net/raw.h
+index 1828f81..6c14a65 100644
+--- a/include/net/raw.h
++++ b/include/net/raw.h
+@@ -53,7 +53,7 @@ int raw_seq_open(struct inode *ino, struct file *file,
+
+ #endif
+
+-void raw_hash_sk(struct sock *sk, struct raw_hashinfo *h);
+-void raw_unhash_sk(struct sock *sk, struct raw_hashinfo *h);
++void raw_hash_sk(struct sock *sk);
++void raw_unhash_sk(struct sock *sk);
+
+ #endif /* _RAW_H */
+diff --git a/include/net/request_sock.h b/include/net/request_sock.h
+index cff4608..b220b5f 100644
+--- a/include/net/request_sock.h
++++ b/include/net/request_sock.h
+@@ -31,8 +31,7 @@ struct request_sock_ops {
+ int obj_size;
+ struct kmem_cache *slab;
+ int (*rtx_syn_ack)(struct sock *sk,
+- struct request_sock *req,
+- struct dst_entry *dst);
++ struct request_sock *req);
+ void (*send_ack)(struct sk_buff *skb,
+ struct request_sock *req);
+ void (*send_reset)(struct sock *sk,
+@@ -46,7 +45,7 @@ struct request_sock {
+ struct request_sock *dl_next; /* Must be first member! */
+ u16 mss;
+ u8 retrans;
+- u8 __pad;
++ u8 cookie_ts; /* syncookie: encode tcpopts in timestamp */
+ /* The following two fields can be easily recomputed I think -AK */
+ u32 window_clamp; /* window clamp at creation time */
+ u32 rcv_wnd; /* rcv_wnd offered first time */
+@@ -116,8 +115,8 @@ struct request_sock_queue {
+ struct request_sock *rskq_accept_head;
+ struct request_sock *rskq_accept_tail;
+ rwlock_t syn_wait_lock;
+- u8 rskq_defer_accept;
+- /* 3 bytes hole, try to pack */
++ u16 rskq_defer_accept;
++ /* 2 bytes hole, try to pack */
+ struct listen_sock *listen_opt;
+ };
+
+diff --git a/include/net/route.h b/include/net/route.h
+index eadad59..c633880 100644
+--- a/include/net/route.h
++++ b/include/net/route.h
+@@ -34,7 +34,6 @@
+ #include <linux/ip.h>
+ #include <linux/cache.h>
+ #include <linux/security.h>
+-#include <net/sock.h>
+
+ #ifndef __KERNEL__
+ #warning This file is not supposed to be used outside of kernel.
+@@ -161,7 +160,7 @@ static inline int ip_route_connect(struct rtable **rp, __be32 dst,
+ .dport = dport } } };
+
+ int err;
+- struct net *net = sk->sk_net;
++ struct net *net = sock_net(sk);
+ if (!dst || !src) {
+ err = __ip_route_output_key(net, rp, &fl);
+ if (err)
+@@ -189,7 +188,7 @@ static inline int ip_route_newports(struct rtable **rp, u8 protocol,
+ ip_rt_put(*rp);
+ *rp = NULL;
+ security_sk_classify_flow(sk, &fl);
+- return ip_route_output_flow(sk->sk_net, rp, &fl, sk, 0);
++ return ip_route_output_flow(sock_net(sk), rp, &fl, sk, 0);
+ }
+ return 0;
+ }
+diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
+index 793863e..3c1895e 100644
+--- a/include/net/rtnetlink.h
++++ b/include/net/rtnetlink.h
+@@ -74,6 +74,7 @@ struct rtnl_link_ops {
+
+ extern int __rtnl_link_register(struct rtnl_link_ops *ops);
+ extern void __rtnl_link_unregister(struct rtnl_link_ops *ops);
++extern void rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops);
+
+ extern int rtnl_link_register(struct rtnl_link_ops *ops);
+ extern void rtnl_link_unregister(struct rtnl_link_ops *ops);
+diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
+index 35b1e83..88988ab 100644
+--- a/include/net/sctp/command.h
++++ b/include/net/sctp/command.h
+@@ -206,12 +206,11 @@ typedef struct {
+ int sctp_init_cmd_seq(sctp_cmd_seq_t *seq);
+
+ /* Add a command to an sctp_cmd_seq_t.
+- * Return 0 if the command sequence is full.
+ *
+ * Use the SCTP_* constructors defined by SCTP_ARG_CONSTRUCTOR() above
+ * to wrap data which goes in the obj argument.
+ */
+-int sctp_add_cmd(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_arg_t obj);
++void sctp_add_cmd_sf(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_arg_t obj);
+
+ /* Return the next command structure in an sctp_cmd_seq.
+ * Return NULL at the end of the sequence.
+diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
+index ea80673..90b1e8d 100644
+--- a/include/net/sctp/sctp.h
++++ b/include/net/sctp/sctp.h
+@@ -368,11 +368,6 @@ void sctp_sysctl_unregister(void);
+ #else
+ static inline void sctp_sysctl_register(void) { return; }
+ static inline void sctp_sysctl_unregister(void) { return; }
+-static inline int sctp_sysctl_jiffies_ms(ctl_table *table, int __user *name, int nlen,
+- void __user *oldval, size_t __user *oldlenp,
+- void __user *newval, size_t newlen) {
+- return -ENOSYS;
+-}
+ #endif
+
+ /* Size of Supported Address Parameter for 'x' address types. */
+diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
+index ef9e7ed..2481173 100644
+--- a/include/net/sctp/sm.h
++++ b/include/net/sctp/sm.h
+@@ -385,14 +385,6 @@ static inline int ADDIP_SERIAL_gte(__u16 s, __u16 t)
+ return (((s) == (t)) || (((t) - (s)) & ADDIP_SERIAL_SIGN_BIT));
+ }
+
+-
+-/* Run sctp_add_cmd() generating a BUG() if there is a failure. */
+-static inline void sctp_add_cmd_sf(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_arg_t obj)
+-{
+- if (unlikely(!sctp_add_cmd(seq, verb, obj)))
+- BUG();
+-}
+-
+ /* Check VTAG of the packet matches the sender's own tag. */
+ static inline int
+ sctp_vtag_verify(const struct sctp_chunk *chunk,
+diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
+index 9c827a7..0ce0443 100644
+--- a/include/net/sctp/structs.h
++++ b/include/net/sctp/structs.h
+@@ -637,8 +637,6 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *,
+ struct sctp_sndrcvinfo *,
+ struct msghdr *, int len);
+ void sctp_datamsg_put(struct sctp_datamsg *);
+-void sctp_datamsg_free(struct sctp_datamsg *);
+-void sctp_datamsg_track(struct sctp_chunk *);
+ void sctp_chunk_fail(struct sctp_chunk *, int error);
+ int sctp_chunk_abandoned(struct sctp_chunk *);
+
+@@ -1661,6 +1659,9 @@ struct sctp_association {
+ /* Transport to which SHUTDOWN chunk was last sent. */
+ struct sctp_transport *shutdown_last_sent_to;
+
++ /* How many times have we resent a SHUTDOWN */
++ int shutdown_retries;
++
+ /* Transport to which INIT chunk was last sent. */
+ struct sctp_transport *init_last_sent_to;
+
+@@ -1695,6 +1696,11 @@ struct sctp_association {
+ */
+ __u16 unack_data;
+
++ /* The total number of data chunks that we've had to retransmit
++ * as the result of a T3 timer expiration
++ */
++ __u32 rtx_data_chunks;
++
+ /* This is the association's receive buffer space. This value is used
+ * to set a_rwnd field in an INIT or a SACK chunk.
+ */
+diff --git a/include/net/sock.h b/include/net/sock.h
+index fd98760..dc42b44 100644
+--- a/include/net/sock.h
++++ b/include/net/sock.h
+@@ -47,7 +47,6 @@
+ #include <linux/module.h>
+ #include <linux/lockdep.h>
+ #include <linux/netdevice.h>
+-#include <linux/pcounter.h>
+ #include <linux/skbuff.h> /* struct sk_buff */
+ #include <linux/mm.h>
+ #include <linux/security.h>
+@@ -70,7 +69,11 @@
+ #define SOCK_DEBUG(sk, msg...) do { if ((sk) && sock_flag((sk), SOCK_DBG)) \
+ printk(KERN_DEBUG msg); } while (0)
+ #else
+-#define SOCK_DEBUG(sk, msg...) do { } while (0)
++/* Validate arguments and do nothing */
++static void inline int __attribute__ ((format (printf, 2, 3)))
++SOCK_DEBUG(struct sock *sk, const char *msg, ...)
++{
++}
+ #endif
+
+ /* This is the per-socket lock. The spinlock provides a synchronization
+@@ -122,7 +125,9 @@ struct sock_common {
+ atomic_t skc_refcnt;
+ unsigned int skc_hash;
+ struct proto *skc_prot;
++#ifdef CONFIG_NET_NS
+ struct net *skc_net;
++#endif
+ };
+
+ /**
+@@ -151,6 +156,7 @@ struct sock_common {
+ * @sk_no_check: %SO_NO_CHECK setting, wether or not checkup packets
+ * @sk_route_caps: route capabilities (e.g. %NETIF_F_TSO)
+ * @sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4)
++ * @sk_gso_max_size: Maximum GSO segment size to build
+ * @sk_lingertime: %SO_LINGER l_linger setting
+ * @sk_backlog: always used with the per-socket spinlock held
+ * @sk_callback_lock: used with the callbacks in the end of this struct
+@@ -237,6 +243,7 @@ struct sock {
+ gfp_t sk_allocation;
+ int sk_route_caps;
+ int sk_gso_type;
++ unsigned int sk_gso_max_size;
+ int sk_rcvlowat;
+ unsigned long sk_flags;
+ unsigned long sk_lingertime;
+@@ -498,6 +505,7 @@ extern int sk_wait_data(struct sock *sk, long *timeo);
+ struct request_sock_ops;
+ struct timewait_sock_ops;
+ struct inet_hashinfo;
++struct raw_hashinfo;
+
+ /* Networking protocol blocks we attach to sockets.
+ * socket layer -> transport layer interface
+@@ -553,7 +561,7 @@ struct proto {
+
+ /* Keeping track of sockets in use */
+ #ifdef CONFIG_PROC_FS
+- struct pcounter inuse;
++ unsigned int inuse_idx;
+ #endif
+
+ /* Memory pressure */
+@@ -580,7 +588,11 @@ struct proto {
+ struct request_sock_ops *rsk_prot;
+ struct timewait_sock_ops *twsk_prot;
+
+- struct inet_hashinfo *hashinfo;
++ union {
++ struct inet_hashinfo *hashinfo;
++ struct hlist_head *udp_hash;
++ struct raw_hashinfo *raw_hash;
++ } h;
+
+ struct module *owner;
+
+@@ -622,36 +634,12 @@ static inline void sk_refcnt_debug_release(const struct sock *sk)
+
+
+ #ifdef CONFIG_PROC_FS
+-# define DEFINE_PROTO_INUSE(NAME) DEFINE_PCOUNTER(NAME)
+-# define REF_PROTO_INUSE(NAME) PCOUNTER_MEMBER_INITIALIZER(NAME, .inuse)
+ /* Called with local bh disabled */
+-static inline void sock_prot_inuse_add(struct proto *prot, int inc)
+-{
+- pcounter_add(&prot->inuse, inc);
+-}
+-static inline int sock_prot_inuse_init(struct proto *proto)
+-{
+- return pcounter_alloc(&proto->inuse);
+-}
+-static inline int sock_prot_inuse_get(struct proto *proto)
+-{
+- return pcounter_getval(&proto->inuse);
+-}
+-static inline void sock_prot_inuse_free(struct proto *proto)
+-{
+- pcounter_free(&proto->inuse);
+-}
++extern void sock_prot_inuse_add(struct net *net, struct proto *prot, int inc);
++extern int sock_prot_inuse_get(struct net *net, struct proto *proto);
+ #else
+-# define DEFINE_PROTO_INUSE(NAME)
+-# define REF_PROTO_INUSE(NAME)
+-static void inline sock_prot_inuse_add(struct proto *prot, int inc)
+-{
+-}
+-static int inline sock_prot_inuse_init(struct proto *proto)
+-{
+- return 0;
+-}
+-static void inline sock_prot_inuse_free(struct proto *proto)
++static void inline sock_prot_inuse_add(struct net *net, struct proto *prot,
++ int inc)
+ {
+ }
+ #endif
+@@ -850,6 +838,7 @@ extern struct sock *sk_alloc(struct net *net, int family,
+ gfp_t priority,
+ struct proto *prot);
+ extern void sk_free(struct sock *sk);
++extern void sk_release_kernel(struct sock *sk);
+ extern struct sock *sk_clone(const struct sock *sk,
+ const gfp_t priority);
+
+@@ -939,41 +928,6 @@ extern void sk_common_release(struct sock *sk);
+ extern void sock_init_data(struct socket *sock, struct sock *sk);
+
+ /**
+- * sk_filter - run a packet through a socket filter
+- * @sk: sock associated with &sk_buff
+- * @skb: buffer to filter
+- * @needlock: set to 1 if the sock is not locked by caller.
+- *
+- * Run the filter code and then cut skb->data to correct size returned by
+- * sk_run_filter. If pkt_len is 0 we toss packet. If skb->len is smaller
+- * than pkt_len we keep whole skb->data. This is the socket level
+- * wrapper to sk_run_filter. It returns 0 if the packet should
+- * be accepted or -EPERM if the packet should be tossed.
+- *
+- */
+-
+-static inline int sk_filter(struct sock *sk, struct sk_buff *skb)
+-{
+- int err;
+- struct sk_filter *filter;
+-
+- err = security_sock_rcv_skb(sk, skb);
+- if (err)
+- return err;
+-
+- rcu_read_lock_bh();
+- filter = rcu_dereference(sk->sk_filter);
+- if (filter) {
+- unsigned int pkt_len = sk_run_filter(skb, filter->insns,
+- filter->len);
+- err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM;
+- }
+- rcu_read_unlock_bh();
+-
+- return err;
+-}
+-
+-/**
+ * sk_filter_release: Release a socket filter
+ * @sk: socket
+ * @fp: filter to remove
+@@ -1333,6 +1287,36 @@ static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb, int copied_e
+ }
+ #endif
+
++static inline
++struct net *sock_net(const struct sock *sk)
++{
++#ifdef CONFIG_NET_NS
++ return sk->sk_net;
++#else
++ return &init_net;
++#endif
++}
++
++static inline
++void sock_net_set(struct sock *sk, struct net *net)
++{
++#ifdef CONFIG_NET_NS
++ sk->sk_net = net;
++#endif
++}
++
++/*
++ * Kernel sockets, f.e. rtnl or icmp_socket, are a part of a namespace.
++ * They should not hold a referrence to a namespace in order to allow
++ * to stop it.
++ * Sockets after sk_change_net should be released using sk_release_kernel
++ */
++static inline void sk_change_net(struct sock *sk, struct net *net)
++{
++ put_net(sock_net(sk));
++ sock_net_set(sk, hold_net(net));
++}
++
+ extern void sock_enable_timestamp(struct sock *sk);
+ extern int sock_get_timestamp(struct sock *, struct timeval __user *);
+ extern int sock_get_timestampns(struct sock *, struct timespec __user *);
+diff --git a/include/net/tcp.h b/include/net/tcp.h
+index 4fd3eb2..633147c 100644
+--- a/include/net/tcp.h
++++ b/include/net/tcp.h
+@@ -29,6 +29,7 @@
+ #include <linux/skbuff.h>
+ #include <linux/dmaengine.h>
+ #include <linux/crypto.h>
++#include <linux/cryptohash.h>
+
+ #include <net/inet_connection_sock.h>
+ #include <net/inet_timewait_sock.h>
+@@ -138,6 +139,7 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
+ #define MAX_TCP_KEEPINTVL 32767
+ #define MAX_TCP_KEEPCNT 127
+ #define MAX_TCP_SYNCNT 127
++#define MAX_TCP_ACCEPT_DEFERRED 65535
+
+ #define TCP_SYNQ_INTERVAL (HZ/5) /* Period of SYNACK timer */
+
+@@ -434,11 +436,20 @@ extern int tcp_disconnect(struct sock *sk, int flags);
+ extern void tcp_unhash(struct sock *sk);
+
+ /* From syncookies.c */
++extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS];
+ extern struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
+ struct ip_options *opt);
+ extern __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb,
+ __u16 *mss);
+
++extern __u32 cookie_init_timestamp(struct request_sock *req);
++extern void cookie_check_timestamp(struct tcp_options_received *tcp_opt);
++
++/* From net/ipv6/syncookies.c */
++extern struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb);
++extern __u32 cookie_v6_init_sequence(struct sock *sk, struct sk_buff *skb,
++ __u16 *mss);
++
+ /* tcp_output.c */
+
+ extern void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss,
+@@ -776,11 +787,14 @@ extern void tcp_enter_cwr(struct sock *sk, const int set_ssthresh);
+ extern __u32 tcp_init_cwnd(struct tcp_sock *tp, struct dst_entry *dst);
+
+ /* Slow start with delack produces 3 packets of burst, so that
+- * it is safe "de facto".
++ * it is safe "de facto". This will be the default - same as
++ * the default reordering threshold - but if reordering increases,
++ * we must be able to allow cwnd to burst at least this much in order
++ * to not pull it back when holes are filled.
+ */
+ static __inline__ __u32 tcp_max_burst(const struct tcp_sock *tp)
+ {
+- return 3;
++ return tp->reordering;
+ }
+
+ /* Returns end sequence number of the receiver's advertised window */
+@@ -950,6 +964,7 @@ static inline void tcp_openreq_init(struct request_sock *req,
+ struct inet_request_sock *ireq = inet_rsk(req);
+
+ req->rcv_wnd = 0; /* So that tcp_send_synack() knows! */
++ req->cookie_ts = 0;
+ tcp_rsk(req)->rcv_isn = TCP_SKB_CB(skb)->seq;
+ req->mss = rx_opt->mss_clamp;
+ req->ts_recent = rx_opt->saw_tstamp ? rx_opt->rcv_tsval : 0;
+@@ -1237,7 +1252,7 @@ static inline void tcp_insert_write_queue_after(struct sk_buff *skb,
+ struct sk_buff *buff,
+ struct sock *sk)
+ {
+- __skb_append(skb, buff, &sk->sk_write_queue);
++ __skb_queue_after(&sk->sk_write_queue, skb, buff);
+ }
+
+ /* Insert skb between prev and next on the write queue of sk. */
+@@ -1315,25 +1330,25 @@ enum tcp_seq_states {
+ };
+
+ struct tcp_seq_afinfo {
+- struct module *owner;
+ char *name;
+ sa_family_t family;
+- int (*seq_show) (struct seq_file *m, void *v);
+- struct file_operations *seq_fops;
++ struct file_operations seq_fops;
++ struct seq_operations seq_ops;
+ };
+
+ struct tcp_iter_state {
++ struct seq_net_private p;
+ sa_family_t family;
+ enum tcp_seq_states state;
+ struct sock *syn_wait_sk;
+ int bucket, sbucket, num, uid;
+- struct seq_operations seq_ops;
+ };
+
+-extern int tcp_proc_register(struct tcp_seq_afinfo *afinfo);
+-extern void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo);
++extern int tcp_proc_register(struct net *net, struct tcp_seq_afinfo *afinfo);
++extern void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo);
+
+ extern struct request_sock_ops tcp_request_sock_ops;
++extern struct request_sock_ops tcp6_request_sock_ops;
+
+ extern int tcp_v4_destroy_sock(struct sock *sk);
+
+@@ -1375,7 +1390,7 @@ struct tcp_request_sock_ops {
+ #endif
+ };
+
+-extern void tcp_v4_init(struct net_proto_family *ops);
++extern void tcp_v4_init(void);
+ extern void tcp_init(void);
+
+ #endif /* _TCP_H */
+diff --git a/include/net/tipc/tipc_bearer.h b/include/net/tipc/tipc_bearer.h
+index 2151a80..ee2f304 100644
+--- a/include/net/tipc/tipc_bearer.h
++++ b/include/net/tipc/tipc_bearer.h
+@@ -99,6 +99,9 @@ struct tipc_bearer {
+ char name[TIPC_MAX_BEARER_NAME];
+ };
+
++/*
++ * TIPC routines available to supported media types
++ */
+
+ int tipc_register_media(u32 media_type,
+ char *media_name,
+@@ -123,6 +126,12 @@ void tipc_continue(struct tipc_bearer *tb_ptr);
+ int tipc_enable_bearer(const char *bearer_name, u32 bcast_scope, u32 priority);
+ int tipc_disable_bearer(const char *name);
+
++/*
++ * Routines made available to TIPC by supported media types
++ */
++
++int tipc_eth_media_start(void);
++void tipc_eth_media_stop(void);
+
+ #endif
+
+diff --git a/include/net/tipc/tipc_port.h b/include/net/tipc/tipc_port.h
+index cfc4ba4..11105bc 100644
+--- a/include/net/tipc/tipc_port.h
++++ b/include/net/tipc/tipc_port.h
+@@ -86,13 +86,6 @@ u32 tipc_createport_raw(void *usr_handle,
+ void (*wakeup)(struct tipc_port *),
+ const u32 importance);
+
+-/*
+- * tipc_set_msg_option(): port must be locked.
+- */
+-int tipc_set_msg_option(struct tipc_port *tp_ptr,
+- const char *opt,
+- const u32 len);
+-
+ int tipc_reject_msg(struct sk_buff *buf, u32 err);
+
+ int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode);
+@@ -103,6 +96,12 @@ struct tipc_port *tipc_get_port(const u32 ref);
+
+ void *tipc_get_handle(const u32 ref);
+
++/*
++ * The following routines require that the port be locked on entry
++ */
++
++int tipc_disconnect_port(struct tipc_port *tp_ptr);
++
+
+ #endif
+
+diff --git a/include/net/udp.h b/include/net/udp.h
+index c6669c0..3e55a99 100644
+--- a/include/net/udp.h
++++ b/include/net/udp.h
+@@ -115,7 +115,7 @@ static inline void udp_lib_unhash(struct sock *sk)
+ write_lock_bh(&udp_hash_lock);
+ if (sk_del_node_init(sk)) {
+ inet_sk(sk)->num = 0;
+- sock_prot_inuse_add(sk->sk_prot, -1);
++ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
+ }
+ write_unlock_bh(&udp_hash_lock);
+ }
+@@ -125,6 +125,8 @@ static inline void udp_lib_close(struct sock *sk, long timeout)
+ sk_common_release(sk);
+ }
+
++extern int udp_lib_get_port(struct sock *sk, unsigned short snum,
++ int (*)(const struct sock*,const struct sock*));
+
+ /* net/ipv4/udp.c */
+ extern int udp_get_port(struct sock *sk, unsigned short snum,
+@@ -183,24 +185,23 @@ DECLARE_SNMP_STAT(struct udp_mib, udplite_stats_in6);
+
+ /* /proc */
+ struct udp_seq_afinfo {
+- struct module *owner;
+ char *name;
+ sa_family_t family;
+ struct hlist_head *hashtable;
+- int (*seq_show) (struct seq_file *m, void *v);
+- struct file_operations *seq_fops;
++ struct file_operations seq_fops;
++ struct seq_operations seq_ops;
+ };
+
+ struct udp_iter_state {
++ struct seq_net_private p;
+ sa_family_t family;
+ struct hlist_head *hashtable;
+ int bucket;
+- struct seq_operations seq_ops;
+ };
+
+ #ifdef CONFIG_PROC_FS
+-extern int udp_proc_register(struct udp_seq_afinfo *afinfo);
+-extern void udp_proc_unregister(struct udp_seq_afinfo *afinfo);
++extern int udp_proc_register(struct net *net, struct udp_seq_afinfo *afinfo);
++extern void udp_proc_unregister(struct net *net, struct udp_seq_afinfo *afinfo);
+
+ extern int udp4_proc_init(void);
+ extern void udp4_proc_exit(void);
+diff --git a/include/net/wireless.h b/include/net/wireless.h
+index d30c4ba..667b408 100644
+--- a/include/net/wireless.h
++++ b/include/net/wireless.h
+@@ -13,6 +13,162 @@
+ #include <net/cfg80211.h>
+
+ /**
++ * enum ieee80211_band - supported frequency bands
++ *
++ * The bands are assigned this way because the supported
++ * bitrates differ in these bands.
++ *
++ * @IEEE80211_BAND_2GHZ: 2.4GHz ISM band
++ * @IEEE80211_BAND_5GHZ: around 5GHz band (4.9-5.7)
++ */
++enum ieee80211_band {
++ IEEE80211_BAND_2GHZ,
++ IEEE80211_BAND_5GHZ,
++
++ /* keep last */
++ IEEE80211_NUM_BANDS
++};
++
++/**
++ * enum ieee80211_channel_flags - channel flags
++ *
++ * Channel flags set by the regulatory control code.
++ *
++ * @IEEE80211_CHAN_DISABLED: This channel is disabled.
++ * @IEEE80211_CHAN_PASSIVE_SCAN: Only passive scanning is permitted
++ * on this channel.
++ * @IEEE80211_CHAN_NO_IBSS: IBSS is not allowed on this channel.
++ * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel.
++ */
++enum ieee80211_channel_flags {
++ IEEE80211_CHAN_DISABLED = 1<<0,
++ IEEE80211_CHAN_PASSIVE_SCAN = 1<<1,
++ IEEE80211_CHAN_NO_IBSS = 1<<2,
++ IEEE80211_CHAN_RADAR = 1<<3,
++};
++
++/**
++ * struct ieee80211_channel - channel definition
++ *
++ * This structure describes a single channel for use
++ * with cfg80211.
++ *
++ * @center_freq: center frequency in MHz
++ * @hw_value: hardware-specific value for the channel
++ * @flags: channel flags from &enum ieee80211_channel_flags.
++ * @orig_flags: channel flags at registration time, used by regulatory
++ * code to support devices with additional restrictions
++ * @band: band this channel belongs to.
++ * @max_antenna_gain: maximum antenna gain in dBi
++ * @max_power: maximum transmission power (in dBm)
++ * @orig_mag: internal use
++ * @orig_mpwr: internal use
++ */
++struct ieee80211_channel {
++ enum ieee80211_band band;
++ u16 center_freq;
++ u16 hw_value;
++ u32 flags;
++ int max_antenna_gain;
++ int max_power;
++ u32 orig_flags;
++ int orig_mag, orig_mpwr;
++};
++
++/**
++ * enum ieee80211_rate_flags - rate flags
++ *
++ * Hardware/specification flags for rates. These are structured
++ * in a way that allows using the same bitrate structure for
++ * different bands/PHY modes.
++ *
++ * @IEEE80211_RATE_SHORT_PREAMBLE: Hardware can send with short
++ * preamble on this bitrate; only relevant in 2.4GHz band and
++ * with CCK rates.
++ * @IEEE80211_RATE_MANDATORY_A: This bitrate is a mandatory rate
++ * when used with 802.11a (on the 5 GHz band); filled by the
++ * core code when registering the wiphy.
++ * @IEEE80211_RATE_MANDATORY_B: This bitrate is a mandatory rate
++ * when used with 802.11b (on the 2.4 GHz band); filled by the
++ * core code when registering the wiphy.
++ * @IEEE80211_RATE_MANDATORY_G: This bitrate is a mandatory rate
++ * when used with 802.11g (on the 2.4 GHz band); filled by the
++ * core code when registering the wiphy.
++ * @IEEE80211_RATE_ERP_G: This is an ERP rate in 802.11g mode.
++ */
++enum ieee80211_rate_flags {
++ IEEE80211_RATE_SHORT_PREAMBLE = 1<<0,
++ IEEE80211_RATE_MANDATORY_A = 1<<1,
++ IEEE80211_RATE_MANDATORY_B = 1<<2,
++ IEEE80211_RATE_MANDATORY_G = 1<<3,
++ IEEE80211_RATE_ERP_G = 1<<4,
++};
++
++/**
++ * struct ieee80211_rate - bitrate definition
++ *
++ * This structure describes a bitrate that an 802.11 PHY can
++ * operate with. The two values @hw_value and @hw_value_short
++ * are only for driver use when pointers to this structure are
++ * passed around.
++ *
++ * @flags: rate-specific flags
++ * @bitrate: bitrate in units of 100 Kbps
++ * @hw_value: driver/hardware value for this rate
++ * @hw_value_short: driver/hardware value for this rate when
++ * short preamble is used
++ */
++struct ieee80211_rate {
++ u32 flags;
++ u16 bitrate;
++ u16 hw_value, hw_value_short;
++};
++
++/**
++ * struct ieee80211_ht_info - describing STA's HT capabilities
++ *
++ * This structure describes most essential parameters needed
++ * to describe 802.11n HT capabilities for an STA.
++ *
++ * @ht_supported: is HT supported by STA, 0: no, 1: yes
++ * @cap: HT capabilities map as described in 802.11n spec
++ * @ampdu_factor: Maximum A-MPDU length factor
++ * @ampdu_density: Minimum A-MPDU spacing
++ * @supp_mcs_set: Supported MCS set as described in 802.11n spec
++ */
++struct ieee80211_ht_info {
++ u16 cap; /* use IEEE80211_HT_CAP_ */
++ u8 ht_supported;
++ u8 ampdu_factor;
++ u8 ampdu_density;
++ u8 supp_mcs_set[16];
++};
++
++/**
++ * struct ieee80211_supported_band - frequency band definition
++ *
++ * This structure describes a frequency band a wiphy
++ * is able to operate in.
++ *
++ * @channels: Array of channels the hardware can operate in
++ * in this band.
++ * @band: the band this structure represents
++ * @n_channels: Number of channels in @channels
++ * @bitrates: Array of bitrates the hardware can operate with
++ * in this band. Must be sorted to give a valid "supported
++ * rates" IE, i.e. CCK rates first, then OFDM.
++ * @n_bitrates: Number of bitrates in @bitrates
++ */
++struct ieee80211_supported_band {
++ struct ieee80211_channel *channels;
++ struct ieee80211_rate *bitrates;
++ enum ieee80211_band band;
++ int n_channels;
++ int n_bitrates;
++ struct ieee80211_ht_info ht_info;
++};
++
++/**
+ * struct wiphy - wireless hardware description
+ * @idx: the wiphy index assigned to this item
+ * @class_dev: the class device representing /sys/class/ieee80211/<wiphy-name>
+@@ -30,6 +186,8 @@ struct wiphy {
+ * help determine whether you own this wiphy or not. */
+ void *privid;
+
++ struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS];
++
+ /* fields below are read-only, assigned by cfg80211 */
+
+ /* the item in /sys/class/ieee80211/ points to this,
+@@ -136,4 +294,32 @@ extern void wiphy_unregister(struct wiphy *wiphy);
+ */
+ extern void wiphy_free(struct wiphy *wiphy);
+
++/**
++ * ieee80211_channel_to_frequency - convert channel number to frequency
++ */
++extern int ieee80211_channel_to_frequency(int chan);
++
++/**
++ * ieee80211_frequency_to_channel - convert frequency to channel number
++ */
++extern int ieee80211_frequency_to_channel(int freq);
++
++/*
++ * Name indirection necessary because the ieee80211 code also has
++ * a function named "ieee80211_get_channel", so if you include
++ * cfg80211's header file you get cfg80211's version, if you try
++ * to include both header files you'll (rightfully!) get a symbol
++ * clash.
++ */
++extern struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy,
++ int freq);
++
++/**
++ * ieee80211_get_channel - get channel struct from wiphy for specified frequency
++ */
++static inline struct ieee80211_channel *
++ieee80211_get_channel(struct wiphy *wiphy, int freq)
++{
++ return __ieee80211_get_channel(wiphy, freq);
++}
+ #endif /* __NET_WIRELESS_H */
+diff --git a/include/net/xfrm.h b/include/net/xfrm.h
+index 0d255ae..baa9f37 100644
+--- a/include/net/xfrm.h
++++ b/include/net/xfrm.h
+@@ -121,6 +121,7 @@ extern struct mutex xfrm_cfg_mutex;
+ struct xfrm_state
+ {
+ /* Note: bydst is re-used during gc */
++ struct list_head all;
+ struct hlist_node bydst;
+ struct hlist_node bysrc;
+ struct hlist_node byspi;
+@@ -435,6 +436,9 @@ struct xfrm_tmpl
+ /* May skip this transfomration if no SA is found */
+ __u8 optional;
+
++/* Skip aalgos/ealgos/calgos checks. */
++ __u8 allalgs;
++
+ /* Bit mask of algos allowed for acquisition */
+ __u32 aalgos;
+ __u32 ealgos;
+@@ -446,6 +450,7 @@ struct xfrm_tmpl
+ struct xfrm_policy
+ {
+ struct xfrm_policy *next;
++ struct list_head bytype;
+ struct hlist_node bydst;
+ struct hlist_node byidx;
+
+@@ -1071,6 +1076,23 @@ xfrm_address_t *xfrm_flowi_saddr(struct flowi *fl, unsigned short family)
+ return NULL;
+ }
+
++static __inline__
++void xfrm_flowi_addr_get(struct flowi *fl,
++ xfrm_address_t *saddr, xfrm_address_t *daddr,
++ unsigned short family)
++{
++ switch(family) {
++ case AF_INET:
++ memcpy(&saddr->a4, &fl->fl4_src, sizeof(saddr->a4));
++ memcpy(&daddr->a4, &fl->fl4_dst, sizeof(daddr->a4));
++ break;
++ case AF_INET6:
++ ipv6_addr_copy((struct in6_addr *)&saddr->a6, &fl->fl6_src);
++ ipv6_addr_copy((struct in6_addr *)&daddr->a6, &fl->fl6_dst);
++ break;
++ }
++}
++
+ static __inline__ int
+ __xfrm4_state_addr_check(struct xfrm_state *x,
+ xfrm_address_t *daddr, xfrm_address_t *saddr)
+@@ -1188,6 +1210,18 @@ struct xfrm6_tunnel {
+ int priority;
+ };
+
++struct xfrm_state_walk {
++ struct xfrm_state *state;
++ int count;
++ u8 proto;
++};
++
++struct xfrm_policy_walk {
++ struct xfrm_policy *policy;
++ int count;
++ u8 type, cur_type;
++};
++
+ extern void xfrm_init(void);
+ extern void xfrm4_init(void);
+ extern void xfrm_state_init(void);
+@@ -1212,7 +1246,23 @@ static inline void xfrm6_fini(void)
+ extern int xfrm_proc_init(void);
+ #endif
+
+-extern int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*), void *);
++static inline void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto)
++{
++ walk->proto = proto;
++ walk->state = NULL;
++ walk->count = 0;
++}
++
++static inline void xfrm_state_walk_done(struct xfrm_state_walk *walk)
++{
++ if (walk->state != NULL) {
++ xfrm_state_put(walk->state);
++ walk->state = NULL;
++ }
++}
++
++extern int xfrm_state_walk(struct xfrm_state_walk *walk,
++ int (*func)(struct xfrm_state *, int, void*), void *);
+ extern struct xfrm_state *xfrm_state_alloc(void);
+ extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
+ struct flowi *fl, struct xfrm_tmpl *tmpl,
+@@ -1335,7 +1385,25 @@ static inline int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
+ #endif
+
+ struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp);
+-extern int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, void*), void *);
++
++static inline void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type)
++{
++ walk->cur_type = XFRM_POLICY_TYPE_MAIN;
++ walk->type = type;
++ walk->policy = NULL;
++ walk->count = 0;
++}
++
++static inline void xfrm_policy_walk_done(struct xfrm_policy_walk *walk)
++{
++ if (walk->policy != NULL) {
++ xfrm_pol_put(walk->policy);
++ walk->policy = NULL;
++ }
++}
++
++extern int xfrm_policy_walk(struct xfrm_policy_walk *walk,
++ int (*func)(struct xfrm_policy *, int, int, void*), void *);
+ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
+ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
+ struct xfrm_selector *sel,
+diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h
+index 64a721f..8d65bf0 100644
+--- a/include/rdma/ib_user_verbs.h
++++ b/include/rdma/ib_user_verbs.h
+@@ -533,7 +533,10 @@ struct ib_uverbs_send_wr {
+ __u32 num_sge;
+ __u32 opcode;
+ __u32 send_flags;
+- __u32 imm_data;
++ union {
++ __u32 imm_data;
++ __u32 invalidate_rkey;
++ } ex;
+ union {
+ struct {
+ __u64 remote_addr;
+diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
+index 701e7b4..2dcbecc 100644
+--- a/include/rdma/ib_verbs.h
++++ b/include/rdma/ib_verbs.h
+@@ -94,7 +94,7 @@ enum ib_device_cap_flags {
+ IB_DEVICE_SRQ_RESIZE = (1<<13),
+ IB_DEVICE_N_NOTIFY_CQ = (1<<14),
+ IB_DEVICE_ZERO_STAG = (1<<15),
+- IB_DEVICE_SEND_W_INV = (1<<16),
++ IB_DEVICE_RESERVED = (1<<16), /* old SEND_W_INV */
+ IB_DEVICE_MEM_WINDOW = (1<<17),
+ /*
+ * Devices should set IB_DEVICE_UD_IP_SUM if they support
+@@ -104,6 +104,8 @@ enum ib_device_cap_flags {
+ * IPoIB driver may set NETIF_F_IP_CSUM for datagram mode.
+ */
+ IB_DEVICE_UD_IP_CSUM = (1<<18),
++ IB_DEVICE_UD_TSO = (1<<19),
++ IB_DEVICE_SEND_W_INV = (1<<21),
+ };
+
+ enum ib_atomic_cap {
+@@ -411,6 +413,7 @@ enum ib_wc_opcode {
+ IB_WC_COMP_SWAP,
+ IB_WC_FETCH_ADD,
+ IB_WC_BIND_MW,
++ IB_WC_LSO,
+ /*
+ * Set value of IB_WC_RECV so consumers can test if a completion is a
+ * receive by testing (opcode & IB_WC_RECV).
+@@ -495,6 +498,10 @@ enum ib_qp_type {
+ IB_QPT_RAW_ETY
+ };
+
++enum ib_qp_create_flags {
++ IB_QP_CREATE_IPOIB_UD_LSO = 1 << 0,
++};
++
+ struct ib_qp_init_attr {
+ void (*event_handler)(struct ib_event *, void *);
+ void *qp_context;
+@@ -504,6 +511,7 @@ struct ib_qp_init_attr {
+ struct ib_qp_cap cap;
+ enum ib_sig_type sq_sig_type;
+ enum ib_qp_type qp_type;
++ enum ib_qp_create_flags create_flags;
+ u8 port_num; /* special QP types only */
+ };
+
+@@ -617,7 +625,9 @@ enum ib_wr_opcode {
+ IB_WR_SEND_WITH_IMM,
+ IB_WR_RDMA_READ,
+ IB_WR_ATOMIC_CMP_AND_SWP,
+- IB_WR_ATOMIC_FETCH_AND_ADD
++ IB_WR_ATOMIC_FETCH_AND_ADD,
++ IB_WR_LSO,
++ IB_WR_SEND_WITH_INV,
+ };
+
+ enum ib_send_flags {
+@@ -641,7 +651,10 @@ struct ib_send_wr {
+ int num_sge;
+ enum ib_wr_opcode opcode;
+ int send_flags;
+- __be32 imm_data;
++ union {
++ __be32 imm_data;
++ u32 invalidate_rkey;
++ } ex;
+ union {
+ struct {
+ u64 remote_addr;
+@@ -655,6 +668,9 @@ struct ib_send_wr {
+ } atomic;
+ struct {
+ struct ib_ah *ah;
++ void *header;
++ int hlen;
++ int mss;
+ u32 remote_qpn;
+ u32 remote_qkey;
+ u16 pkey_index; /* valid for GSI only */
+@@ -730,7 +746,7 @@ struct ib_uobject {
+ struct ib_ucontext *context; /* associated user context */
+ void *object; /* containing object */
+ struct list_head list; /* link to context's list */
+- u32 id; /* index into kernel idr */
++ int id; /* index into kernel idr */
+ struct kref ref;
+ struct rw_semaphore mutex; /* protects .live */
+ int live;
+@@ -971,6 +987,8 @@ struct ib_device {
+ int comp_vector,
+ struct ib_ucontext *context,
+ struct ib_udata *udata);
++ int (*modify_cq)(struct ib_cq *cq, u16 cq_count,
++ u16 cq_period);
+ int (*destroy_cq)(struct ib_cq *cq);
+ int (*resize_cq)(struct ib_cq *cq, int cqe,
+ struct ib_udata *udata);
+@@ -1033,7 +1051,7 @@ struct ib_device {
+ struct ib_dma_mapping_ops *dma_ops;
+
+ struct module *owner;
+- struct class_device class_dev;
++ struct device dev;
+ struct kobject *ports_parent;
+ struct list_head port_list;
+
+@@ -1376,6 +1394,15 @@ struct ib_cq *ib_create_cq(struct ib_device *device,
+ int ib_resize_cq(struct ib_cq *cq, int cqe);
+
+ /**
++ * ib_modify_cq - Modifies moderation params of the CQ
++ * @cq: The CQ to modify.
++ * @cq_count: number of CQEs that will trigger an event
++ * @cq_period: max period of time in usec before triggering an event
++ *
++ */
++int ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period);
++
++/**
+ * ib_destroy_cq - Destroys the specified CQ.
+ * @cq: The CQ to destroy.
+ */
+diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h
+index 5ffec8a..e0593bf 100644
+--- a/include/scsi/iscsi_proto.h
++++ b/include/scsi/iscsi_proto.h
+@@ -112,6 +112,7 @@ struct iscsi_ahs_hdr {
+
+ #define ISCSI_AHSTYPE_CDB 1
+ #define ISCSI_AHSTYPE_RLENGTH 2
++#define ISCSI_CDB_SIZE 16
+
+ /* iSCSI PDU Header */
+ struct iscsi_cmd {
+@@ -125,7 +126,7 @@ struct iscsi_cmd {
+ __be32 data_length;
+ __be32 cmdsn;
+ __be32 exp_statsn;
+- uint8_t cdb[16]; /* SCSI Command Block */
++ uint8_t cdb[ISCSI_CDB_SIZE]; /* SCSI Command Block */
+ /* Additional Data (Command Dependent) */
+ };
+
+@@ -154,7 +155,8 @@ struct iscsi_ecdb_ahdr {
+ __be16 ahslength; /* CDB length - 15, including reserved byte */
+ uint8_t ahstype;
+ uint8_t reserved;
+- uint8_t ecdb[260 - 16]; /* 4-byte aligned extended CDB spillover */
++ /* 4-byte aligned extended CDB spillover */
++ uint8_t ecdb[260 - ISCSI_CDB_SIZE];
+ };
+
+ /* SCSI Response Header */
+diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
+index 39e1cac..e78d3b6 100644
+--- a/include/scsi/libsas.h
++++ b/include/scsi/libsas.h
+@@ -32,7 +32,6 @@
+ #include <scsi/sas.h>
+ #include <linux/libata.h>
+ #include <linux/list.h>
+-#include <asm/semaphore.h>
+ #include <scsi/scsi_device.h>
+ #include <scsi/scsi_cmnd.h>
+ #include <scsi/scsi_transport_sas.h>
+@@ -677,4 +676,6 @@ extern void sas_ssp_task_response(struct device *dev, struct sas_task *task,
+ struct ssp_response_iu *iu);
+ struct sas_phy *sas_find_local_phy(struct domain_device *dev);
+
++int sas_request_addr(struct Scsi_Host *shost, u8 *addr);
++
+ #endif /* _SASLIB_H_ */
+diff --git a/include/scsi/sas_ata.h b/include/scsi/sas_ata.h
+index dd5edc9..c583193 100644
+--- a/include/scsi/sas_ata.h
++++ b/include/scsi/sas_ata.h
+@@ -47,12 +47,12 @@ static inline int dev_is_sata(struct domain_device *dev)
+ {
+ return 0;
+ }
+-int sas_ata_init_host_and_port(struct domain_device *found_dev,
++static inline int sas_ata_init_host_and_port(struct domain_device *found_dev,
+ struct scsi_target *starget)
+ {
+ return 0;
+ }
+-void sas_ata_task_abort(struct sas_task *task)
++static inline void sas_ata_task_abort(struct sas_task *task)
+ {
+ }
+ #endif
+diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
+index de28aab..8d20e60 100644
+--- a/include/scsi/scsi_cmnd.h
++++ b/include/scsi/scsi_cmnd.h
+@@ -130,6 +130,9 @@ extern void scsi_release_buffers(struct scsi_cmnd *cmd);
+ extern int scsi_dma_map(struct scsi_cmnd *cmd);
+ extern void scsi_dma_unmap(struct scsi_cmnd *cmd);
+
++struct scsi_cmnd *scsi_allocate_command(gfp_t gfp_mask);
++void scsi_free_command(gfp_t gfp_mask, struct scsi_cmnd *cmd);
++
+ static inline unsigned scsi_sg_count(struct scsi_cmnd *cmd)
+ {
+ return cmd->sdb.table.nents;
+@@ -175,4 +178,18 @@ static inline struct scsi_data_buffer *scsi_out(struct scsi_cmnd *cmd)
+ return &cmd->sdb;
+ }
+
++static inline int scsi_sg_copy_from_buffer(struct scsi_cmnd *cmd,
++ void *buf, int buflen)
++{
++ return sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd),
++ buf, buflen);
++}
++
++static inline int scsi_sg_copy_to_buffer(struct scsi_cmnd *cmd,
++ void *buf, int buflen)
++{
++ return sg_copy_to_buffer(scsi_sglist(cmd), scsi_sg_count(cmd),
++ buf, buflen);
++}
++
+ #endif /* _SCSI_SCSI_CMND_H */
+diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
+index ab7acbe..b8b19e2 100644
+--- a/include/scsi/scsi_device.h
++++ b/include/scsi/scsi_device.h
+@@ -156,8 +156,8 @@ struct scsi_device {
+
+ int timeout;
+
+- struct device sdev_gendev;
+- struct class_device sdev_classdev;
++ struct device sdev_gendev,
++ sdev_dev;
+
+ struct execute_work ew; /* used to get process context on put */
+
+@@ -167,9 +167,9 @@ struct scsi_device {
+ #define to_scsi_device(d) \
+ container_of(d, struct scsi_device, sdev_gendev)
+ #define class_to_sdev(d) \
+- container_of(d, struct scsi_device, sdev_classdev)
++ container_of(d, struct scsi_device, sdev_dev)
+ #define transport_class_to_sdev(class_dev) \
+- to_scsi_device(class_dev->dev)
++ to_scsi_device(class_dev->parent)
+
+ #define sdev_printk(prefix, sdev, fmt, a...) \
+ dev_printk(prefix, &(sdev)->sdev_gendev, fmt, ##a)
+@@ -220,7 +220,7 @@ static inline struct scsi_target *scsi_target(struct scsi_device *sdev)
+ return to_scsi_target(sdev->sdev_gendev.parent);
+ }
+ #define transport_class_to_starget(class_dev) \
+- to_scsi_target(class_dev->dev)
++ to_scsi_target(class_dev->parent)
+
+ #define starget_printk(prefix, starget, fmt, a...) \
+ dev_printk(prefix, &(starget)->dev, fmt, ##a)
+diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h
+index 25071d5..d3a133b 100644
+--- a/include/scsi/scsi_eh.h
++++ b/include/scsi/scsi_eh.h
+@@ -57,13 +57,16 @@ extern const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len,
+
+ extern int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len,
+ u64 * info_out);
+-
++
++extern void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq);
++
+ /*
+ * Reset request from external source
+ */
+ #define SCSI_TRY_RESET_DEVICE 1
+ #define SCSI_TRY_RESET_BUS 2
+ #define SCSI_TRY_RESET_HOST 3
++#define SCSI_TRY_RESET_TARGET 4
+
+ extern int scsi_reset_provider(struct scsi_device *, int);
+
+diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
+index 530ff4c..d967d6d 100644
+--- a/include/scsi/scsi_host.h
++++ b/include/scsi/scsi_host.h
+@@ -172,6 +172,7 @@ struct scsi_host_template {
+ */
+ int (* eh_abort_handler)(struct scsi_cmnd *);
+ int (* eh_device_reset_handler)(struct scsi_cmnd *);
++ int (* eh_target_reset_handler)(struct scsi_cmnd *);
+ int (* eh_bus_reset_handler)(struct scsi_cmnd *);
+ int (* eh_host_reset_handler)(struct scsi_cmnd *);
+
+@@ -469,7 +470,7 @@ struct scsi_host_template {
+ /*
+ * Pointer to the sysfs class properties for this host, NULL terminated.
+ */
+- struct class_device_attribute **shost_attrs;
++ struct device_attribute **shost_attrs;
+
+ /*
+ * Pointer to the SCSI device properties for this host, NULL terminated.
+@@ -654,8 +655,7 @@ struct Scsi_Host {
+ enum scsi_host_state shost_state;
+
+ /* ldm bits */
+- struct device shost_gendev;
+- struct class_device shost_classdev;
++ struct device shost_gendev, shost_dev;
+
+ /*
+ * List of hosts per template.
+@@ -682,7 +682,7 @@ struct Scsi_Host {
+ };
+
+ #define class_to_shost(d) \
+- container_of(d, struct Scsi_Host, shost_classdev)
++ container_of(d, struct Scsi_Host, shost_dev)
+
+ #define shost_printk(prefix, shost, fmt, a...) \
+ dev_printk(prefix, &(shost)->shost_gendev, fmt, ##a)
+diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h
+index 0dfef75..490bd13 100644
+--- a/include/scsi/scsi_transport.h
++++ b/include/scsi/scsi_transport.h
+@@ -80,7 +80,7 @@ struct scsi_transport_template {
+ };
+
+ #define transport_class_to_shost(tc) \
+- dev_to_shost((tc)->dev)
++ dev_to_shost((tc)->parent)
+
+
+ /* Private area maintenance. The driver requested allocations come
+diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
+index 4769efd..06f72ba 100644
+--- a/include/scsi/scsi_transport_fc.h
++++ b/include/scsi/scsi_transport_fc.h
+@@ -163,8 +163,8 @@ enum fc_tgtid_binding_type {
+
+
+ /* Macro for use in defining Virtual Port attributes */
+-#define FC_VPORT_ATTR(_name,_mode,_show,_store) \
+-struct class_device_attribute class_device_attr_vport_##_name = \
++#define FC_VPORT_ATTR(_name,_mode,_show,_store) \
++struct device_attribute dev_attr_vport_##_name = \
+ __ATTR(_name,_mode,_show,_store)
+
+
+@@ -234,8 +234,8 @@ struct fc_vport {
+
+ #define dev_to_vport(d) \
+ container_of(d, struct fc_vport, dev)
+-#define transport_class_to_vport(classdev) \
+- dev_to_vport(classdev->dev)
++#define transport_class_to_vport(dev) \
++ dev_to_vport(dev->parent)
+ #define vport_to_shost(v) \
+ (v->shost)
+ #define vport_to_shost_channel(v) \
+@@ -271,7 +271,7 @@ struct fc_rport_identifiers {
+
+ /* Macro for use in defining Remote Port attributes */
+ #define FC_RPORT_ATTR(_name,_mode,_show,_store) \
+-struct class_device_attribute class_device_attr_rport_##_name = \
++struct device_attribute dev_attr_rport_##_name = \
+ __ATTR(_name,_mode,_show,_store)
+
+
+@@ -341,8 +341,8 @@ struct fc_rport { /* aka fc_starget_attrs */
+
+ #define dev_to_rport(d) \
+ container_of(d, struct fc_rport, dev)
+-#define transport_class_to_rport(classdev) \
+- dev_to_rport(classdev->dev)
++#define transport_class_to_rport(dev) \
++ dev_to_rport(dev->parent)
+ #define rport_to_shost(r) \
+ dev_to_shost(r->dev.parent)
+
+diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h
+index 09125fa..61ad359 100644
+--- a/include/scsi/scsi_transport_sas.h
++++ b/include/scsi/scsi_transport_sas.h
+@@ -80,8 +80,8 @@ struct sas_phy {
+
+ #define dev_to_phy(d) \
+ container_of((d), struct sas_phy, dev)
+-#define transport_class_to_phy(cdev) \
+- dev_to_phy((cdev)->dev)
++#define transport_class_to_phy(dev) \
++ dev_to_phy((dev)->parent)
+ #define phy_to_shost(phy) \
+ dev_to_shost((phy)->dev.parent)
+
+@@ -96,8 +96,8 @@ struct sas_rphy {
+
+ #define dev_to_rphy(d) \
+ container_of((d), struct sas_rphy, dev)
+-#define transport_class_to_rphy(cdev) \
+- dev_to_rphy((cdev)->dev)
++#define transport_class_to_rphy(dev) \
++ dev_to_rphy((dev)->parent)
+ #define rphy_to_shost(rphy) \
+ dev_to_shost((rphy)->dev.parent)
+ #define target_to_rphy(targ) \
+@@ -152,8 +152,8 @@ struct sas_port {
+
+ #define dev_to_sas_port(d) \
+ container_of((d), struct sas_port, dev)
+-#define transport_class_to_sas_port(cdev) \
+- dev_to_sas_port((cdev)->dev)
++#define transport_class_to_sas_port(dev) \
++ dev_to_sas_port((dev)->parent)
+
+ struct sas_phy_linkrates {
+ enum sas_linkrate maximum_linkrate;
+diff --git a/include/scsi/sd.h b/include/scsi/sd.h
+index 8ea9f73..4f032d4 100644
+--- a/include/scsi/sd.h
++++ b/include/scsi/sd.h
+@@ -34,7 +34,7 @@
+ struct scsi_disk {
+ struct scsi_driver *driver; /* always &sd_template */
+ struct scsi_device *device;
+- struct class_device cdev;
++ struct device dev;
+ struct gendisk *disk;
+ unsigned int openers; /* protected by BKL for now, yuck */
+ sector_t capacity; /* size in 512-byte sectors */
+@@ -46,7 +46,7 @@ struct scsi_disk {
+ unsigned RCD : 1; /* state of disk RCD bit, unused */
+ unsigned DPOFUA : 1; /* state of disk DPOFUA bit */
+ };
+-#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,cdev)
++#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
+
+ #define sd_printk(prefix, sdsk, fmt, a...) \
+ (sdsk)->disk ? \
+diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
+index 0148058..049edc5 100644
+--- a/include/sound/ac97_codec.h
++++ b/include/sound/ac97_codec.h
+@@ -397,6 +397,7 @@
+ #define AC97_HAS_NO_TONE (1<<16) /* no Tone volume */
+ #define AC97_HAS_NO_STD_PCM (1<<17) /* no standard AC97 PCM volume and mute */
+ #define AC97_HAS_NO_AUX (1<<18) /* no standard AC97 AUX volume and mute */
++#define AC97_HAS_8CH (1<<19) /* supports 8-channel output */
+
+ /* rates indexes */
+ #define AC97_RATES_FRONT_DAC 0
+diff --git a/include/sound/ak4114.h b/include/sound/ak4114.h
+index 4e80d3f..d293d36 100644
+--- a/include/sound/ak4114.h
++++ b/include/sound/ak4114.h
+@@ -182,6 +182,7 @@ struct ak4114 {
+ unsigned char rcs0;
+ unsigned char rcs1;
+ struct delayed_work work;
++ unsigned int check_flags;
+ void *change_callback_private;
+ void (*change_callback)(struct ak4114 *ak4114, unsigned char c0, unsigned char c1);
+ };
+diff --git a/include/sound/ak4xxx-adda.h b/include/sound/ak4xxx-adda.h
+index 6153b91..891cf1a 100644
+--- a/include/sound/ak4xxx-adda.h
++++ b/include/sound/ak4xxx-adda.h
+@@ -68,7 +68,7 @@ struct snd_akm4xxx {
+ enum {
+ SND_AK4524, SND_AK4528, SND_AK4529,
+ SND_AK4355, SND_AK4358, SND_AK4381,
+- SND_AK5365, NON_AKM
++ SND_AK5365
+ } type;
+
+ /* (array) information of combined codecs */
+diff --git a/include/sound/asoundef.h b/include/sound/asoundef.h
+index 024ce62..a6e0fac 100644
+--- a/include/sound/asoundef.h
++++ b/include/sound/asoundef.h
+@@ -112,6 +112,14 @@
+ #define IEC958_AES3_CON_CLOCK_1000PPM (0<<4) /* 1000 ppm */
+ #define IEC958_AES3_CON_CLOCK_50PPM (1<<4) /* 50 ppm */
+ #define IEC958_AES3_CON_CLOCK_VARIABLE (2<<4) /* variable pitch */
++#define IEC958_AES4_CON_MAX_WORDLEN_24 (1<<0) /* 0 = 20-bit, 1 = 24-bit */
++#define IEC958_AES4_CON_WORDLEN (7<<1) /* mask - sample word length */
++#define IEC958_AES4_CON_WORDLEN_NOTID (0<<1) /* not indicated */
++#define IEC958_AES4_CON_WORDLEN_20_16 (1<<1) /* 20-bit or 16-bit */
++#define IEC958_AES4_CON_WORDLEN_22_18 (2<<1) /* 22-bit or 18-bit */
++#define IEC958_AES4_CON_WORDLEN_23_19 (4<<1) /* 23-bit or 19-bit */
++#define IEC958_AES4_CON_WORDLEN_24_20 (5<<1) /* 24-bit or 20-bit */
++#define IEC958_AES4_CON_WORDLEN_21_17 (6<<1) /* 21-bit or 17-bit */
+
+ /*****************************************************************************
+ * *
+diff --git a/include/sound/control.h b/include/sound/control.h
+index e79baa6..3dc1291 100644
+--- a/include/sound/control.h
++++ b/include/sound/control.h
+@@ -169,4 +169,11 @@ int snd_ctl_boolean_mono_info(struct snd_kcontrol *kcontrol,
+ int snd_ctl_boolean_stereo_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo);
+
++/*
++ * virtual master control
++ */
++struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
++ const unsigned int *tlv);
++int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave);
++
+ #endif /* __SOUND_CONTROL_H */
+diff --git a/include/sound/core.h b/include/sound/core.h
+index 4fc0235..695ee53 100644
+--- a/include/sound/core.h
++++ b/include/sound/core.h
+@@ -277,8 +277,8 @@ int snd_minor_info_done(void);
+ int snd_minor_info_oss_init(void);
+ int snd_minor_info_oss_done(void);
+ #else
+-#define snd_minor_info_oss_init() /*NOP*/
+-#define snd_minor_info_oss_done() /*NOP*/
++static inline int snd_minor_info_oss_init(void) { return 0; }
++static inline int snd_minor_info_oss_done(void) { return 0; }
+ #endif
+
+ /* memory.c */
+@@ -310,7 +310,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file);
+ int snd_card_file_remove(struct snd_card *card, struct file *file);
+
+ #ifndef snd_card_set_dev
+-#define snd_card_set_dev(card,devptr) ((card)->dev = (devptr))
++#define snd_card_set_dev(card, devptr) ((card)->dev = (devptr))
+ #endif
+
+ /* device.c */
+@@ -373,7 +373,7 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
+ * snd_printd - debug printk
+ * @fmt: format string
+ *
+- * Compiled only when Works like snd_printk() for debugging purpose.
++ * Works like snd_printk() for debugging purposes.
+ * Ignored when CONFIG_SND_DEBUG is not set.
+ */
+ #define snd_printd(fmt, args...) \
+@@ -417,7 +417,7 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
+ * snd_printdd - debug printk
+ * @format: format string
+ *
+- * Compiled only when Works like snd_printk() for debugging purpose.
++ * Works like snd_printk() for debugging purposes.
+ * Ignored when CONFIG_SND_DEBUG_DETECT is not set.
+ */
+ #define snd_printdd(format, args...) snd_printk(format, ##args)
+diff --git a/include/sound/mpu401.h b/include/sound/mpu401.h
+index d45218b..68b634b 100644
+--- a/include/sound/mpu401.h
++++ b/include/sound/mpu401.h
+@@ -103,6 +103,21 @@ struct snd_mpu401 {
+ #define MPU401D(mpu) (mpu)->port
+
+ /*
++ * control register bits
++ */
++/* read MPU401C() */
++#define MPU401_RX_EMPTY 0x80
++#define MPU401_TX_FULL 0x40
++
++/* write MPU401C() */
++#define MPU401_RESET 0xff
++#define MPU401_ENTER_UART 0x3f
++
++/* read MPU401D() */
++#define MPU401_ACK 0xfe
++
++
++/*
+
+ */
+
+diff --git a/include/sound/version.h b/include/sound/version.h
+index fac66c4..ed6fb2e 100644
+--- a/include/sound/version.h
++++ b/include/sound/version.h
+@@ -1,3 +1,3 @@
+ /* include/version.h. Generated by alsa/ksync script. */
+-#define CONFIG_SND_VERSION "1.0.16rc2"
+-#define CONFIG_SND_DATE " (Thu Jan 31 16:40:16 2008 UTC)"
++#define CONFIG_SND_VERSION "1.0.16"
++#define CONFIG_SND_DATE ""
+diff --git a/include/xen/balloon.h b/include/xen/balloon.h
+new file mode 100644
+index 0000000..fe43b0f
+--- /dev/null
++++ b/include/xen/balloon.h
+@@ -0,0 +1,61 @@
++/******************************************************************************
++ * balloon.h
++ *
++ * Xen balloon driver - enables returning/claiming memory to/from Xen.
++ *
++ * Copyright (c) 2003, B Dragovic
++ * Copyright (c) 2003-2004, M Williamson, K Fraser
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation; or, when distributed
++ * separately from the Linux kernel or incorporated into other
++ * software packages, subject to the following license:
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this source file (the "Software"), to deal in the Software without
++ * restriction, including without limitation the rights to use, copy, modify,
++ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
++ * IN THE SOFTWARE.
++ */
++
++#ifndef __XEN_BALLOON_H__
++#define __XEN_BALLOON_H__
++
++#include <linux/spinlock.h>
++
++#if 0
++/*
++ * Inform the balloon driver that it should allow some slop for device-driver
++ * memory activities.
++ */
++void balloon_update_driver_allowance(long delta);
++
++/* Allocate/free a set of empty pages in low memory (i.e., no RAM mapped). */
++struct page **alloc_empty_pages_and_pagevec(int nr_pages);
++void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages);
++
++void balloon_release_driver_page(struct page *page);
++
++/*
++ * Prevent the balloon driver from changing the memory reservation during
++ * a driver critical region.
++ */
++extern spinlock_t balloon_lock;
++#define balloon_lock(__flags) spin_lock_irqsave(&balloon_lock, __flags)
++#define balloon_unlock(__flags) spin_unlock_irqrestore(&balloon_lock, __flags)
++#endif
++
++#endif /* __XEN_BALLOON_H__ */
+diff --git a/include/xen/events.h b/include/xen/events.h
+index 2bde54d..acd8e06 100644
+--- a/include/xen/events.h
++++ b/include/xen/events.h
+@@ -5,13 +5,7 @@
+
+ #include <xen/interface/event_channel.h>
+ #include <asm/xen/hypercall.h>
+-
+-enum ipi_vector {
+- XEN_RESCHEDULE_VECTOR,
+- XEN_CALL_FUNCTION_VECTOR,
+-
+- XEN_NR_IPIS,
+-};
++#include <asm/xen/events.h>
+
+ int bind_evtchn_to_irq(unsigned int evtchn);
+ int bind_evtchn_to_irqhandler(unsigned int evtchn,
+@@ -37,6 +31,7 @@ int bind_ipi_to_irqhandler(enum ipi_vector ipi,
+ void unbind_from_irqhandler(unsigned int irq, void *dev_id);
+
+ void xen_send_IPI_one(unsigned int cpu, enum ipi_vector vector);
++int resend_irq_on_evtchn(unsigned int irq);
+
+ static inline void notify_remote_via_evtchn(int port)
+ {
+diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h
+index 761c834..4662048 100644
+--- a/include/xen/grant_table.h
++++ b/include/xen/grant_table.h
+@@ -39,6 +39,7 @@
+
+ #include <asm/xen/hypervisor.h>
+ #include <xen/interface/grant_table.h>
++#include <asm/xen/grant_table.h>
+
+ /* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */
+ #define NR_GRANT_FRAMES 4
+@@ -102,6 +103,12 @@ void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
+ void gnttab_grant_foreign_transfer_ref(grant_ref_t, domid_t domid,
+ unsigned long pfn);
+
++int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
++ unsigned long max_nr_gframes,
++ struct grant_entry **__shared);
++void arch_gnttab_unmap_shared(struct grant_entry *shared,
++ unsigned long nr_gframes);
++
+ #define gnttab_map_vaddr(map) ((void *)(map.host_virt_addr))
+
+ #endif /* __ASM_GNTTAB_H__ */
+diff --git a/include/xen/interface/callback.h b/include/xen/interface/callback.h
+new file mode 100644
+index 0000000..4aadcba
+--- /dev/null
++++ b/include/xen/interface/callback.h
+@@ -0,0 +1,102 @@
++/******************************************************************************
++ * callback.h
++ *
++ * Register guest OS callbacks with Xen.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to
++ * deal in the Software without restriction, including without limitation the
++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
++ * sell copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ *
++ * Copyright (c) 2006, Ian Campbell
++ */
++
++#ifndef __XEN_PUBLIC_CALLBACK_H__
++#define __XEN_PUBLIC_CALLBACK_H__
++
++#include "xen.h"
++
++/*
++ * Prototype for this hypercall is:
++ * long callback_op(int cmd, void *extra_args)
++ * @cmd == CALLBACKOP_??? (callback operation).
++ * @extra_args == Operation-specific extra arguments (NULL if none).
++ */
++
++/* ia64, x86: Callback for event delivery. */
++#define CALLBACKTYPE_event 0
++
++/* x86: Failsafe callback when guest state cannot be restored by Xen. */
++#define CALLBACKTYPE_failsafe 1
++
++/* x86/64 hypervisor: Syscall by 64-bit guest app ('64-on-64-on-64'). */
++#define CALLBACKTYPE_syscall 2
++
++/*
++ * x86/32 hypervisor: Only available on x86/32 when supervisor_mode_kernel
++ * feature is enabled. Do not use this callback type in new code.
++ */
++#define CALLBACKTYPE_sysenter_deprecated 3
++
++/* x86: Callback for NMI delivery. */
++#define CALLBACKTYPE_nmi 4
++
++/*
++ * x86: sysenter is only available as follows:
++ * - 32-bit hypervisor: with the supervisor_mode_kernel feature enabled
++ * - 64-bit hypervisor: 32-bit guest applications on Intel CPUs
++ * ('32-on-32-on-64', '32-on-64-on-64')
++ * [nb. also 64-bit guest applications on Intel CPUs
++ * ('64-on-64-on-64'), but syscall is preferred]
++ */
++#define CALLBACKTYPE_sysenter 5
++
++/*
++ * x86/64 hypervisor: Syscall by 32-bit guest app on AMD CPUs
++ * ('32-on-32-on-64', '32-on-64-on-64')
++ */
++#define CALLBACKTYPE_syscall32 7
++
++/*
++ * Disable event deliver during callback? This flag is ignored for event and
++ * NMI callbacks: event delivery is unconditionally disabled.
++ */
++#define _CALLBACKF_mask_events 0
++#define CALLBACKF_mask_events (1U << _CALLBACKF_mask_events)
++
++/*
++ * Register a callback.
++ */
++#define CALLBACKOP_register 0
++struct callback_register {
++ uint16_t type;
++ uint16_t flags;
++ struct xen_callback address;
++};
++
++/*
++ * Unregister a callback.
++ *
++ * Not all callbacks can be unregistered. -EINVAL will be returned if
++ * you attempt to unregister such a callback.
++ */
++#define CALLBACKOP_unregister 1
++struct callback_unregister {
++ uint16_t type;
++ uint16_t _unused;
++};
++
++#endif /* __XEN_PUBLIC_CALLBACK_H__ */
+diff --git a/include/xen/interface/grant_table.h b/include/xen/interface/grant_table.h
+index 2190498..39da93c 100644
+--- a/include/xen/interface/grant_table.h
++++ b/include/xen/interface/grant_table.h
+@@ -185,6 +185,7 @@ struct gnttab_map_grant_ref {
+ grant_handle_t handle;
+ uint64_t dev_bus_addr;
+ };
++DEFINE_GUEST_HANDLE_STRUCT(gnttab_map_grant_ref);
+
+ /*
+ * GNTTABOP_unmap_grant_ref: Destroy one or more grant-reference mappings
+@@ -206,6 +207,7 @@ struct gnttab_unmap_grant_ref {
+ /* OUT parameters. */
+ int16_t status; /* GNTST_* */
+ };
++DEFINE_GUEST_HANDLE_STRUCT(gnttab_unmap_grant_ref);
+
+ /*
+ * GNTTABOP_setup_table: Set up a grant table for <dom> comprising at least
+@@ -223,8 +225,9 @@ struct gnttab_setup_table {
+ uint32_t nr_frames;
+ /* OUT parameters. */
+ int16_t status; /* GNTST_* */
+- ulong *frame_list;
++ GUEST_HANDLE(ulong) frame_list;
+ };
++DEFINE_GUEST_HANDLE_STRUCT(gnttab_setup_table);
+
+ /*
+ * GNTTABOP_dump_table: Dump the contents of the grant table to the
+@@ -237,6 +240,7 @@ struct gnttab_dump_table {
+ /* OUT parameters. */
+ int16_t status; /* GNTST_* */
+ };
++DEFINE_GUEST_HANDLE_STRUCT(gnttab_dump_table);
+
+ /*
+ * GNTTABOP_transfer_grant_ref: Transfer <frame> to a foreign domain. The
+@@ -255,7 +259,7 @@ struct gnttab_transfer {
+ /* OUT parameters. */
+ int16_t status;
+ };
+-
++DEFINE_GUEST_HANDLE_STRUCT(gnttab_transfer);
+
+ /*
+ * GNTTABOP_copy: Hypervisor based copy
+@@ -296,6 +300,7 @@ struct gnttab_copy {
+ /* OUT parameters. */
+ int16_t status;
+ };
++DEFINE_GUEST_HANDLE_STRUCT(gnttab_copy);
+
+ /*
+ * GNTTABOP_query_size: Query the current and maximum sizes of the shared
+@@ -313,7 +318,7 @@ struct gnttab_query_size {
+ uint32_t max_nr_frames;
+ int16_t status; /* GNTST_* */
+ };
+-
++DEFINE_GUEST_HANDLE_STRUCT(gnttab_query_size);
+
+ /*
+ * Bitfield values for update_pin_status.flags.
+diff --git a/include/xen/interface/io/fbif.h b/include/xen/interface/io/fbif.h
+new file mode 100644
+index 0000000..5a934dd
+--- /dev/null
++++ b/include/xen/interface/io/fbif.h
+@@ -0,0 +1,124 @@
++/*
++ * fbif.h -- Xen virtual frame buffer device
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to
++ * deal in the Software without restriction, including without limitation the
++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
++ * sell copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ *
++ * Copyright (C) 2005 Anthony Liguori <aliguori at us.ibm.com>
++ * Copyright (C) 2006 Red Hat, Inc., Markus Armbruster <armbru at redhat.com>
++ */
++
++#ifndef __XEN_PUBLIC_IO_FBIF_H__
++#define __XEN_PUBLIC_IO_FBIF_H__
++
++/* Out events (frontend -> backend) */
++
++/*
++ * Out events may be sent only when requested by backend, and receipt
++ * of an unknown out event is an error.
++ */
++
++/* Event type 1 currently not used */
++/*
++ * Framebuffer update notification event
++ * Capable frontend sets feature-update in xenstore.
++ * Backend requests it by setting request-update in xenstore.
++ */
++#define XENFB_TYPE_UPDATE 2
++
++struct xenfb_update {
++ uint8_t type; /* XENFB_TYPE_UPDATE */
++ int32_t x; /* source x */
++ int32_t y; /* source y */
++ int32_t width; /* rect width */
++ int32_t height; /* rect height */
++};
++
++#define XENFB_OUT_EVENT_SIZE 40
++
++union xenfb_out_event {
++ uint8_t type;
++ struct xenfb_update update;
++ char pad[XENFB_OUT_EVENT_SIZE];
++};
++
++/* In events (backend -> frontend) */
++
++/*
++ * Frontends should ignore unknown in events.
++ * No in events currently defined.
++ */
++
++#define XENFB_IN_EVENT_SIZE 40
++
++union xenfb_in_event {
++ uint8_t type;
++ char pad[XENFB_IN_EVENT_SIZE];
++};
++
++/* shared page */
++
++#define XENFB_IN_RING_SIZE 1024
++#define XENFB_IN_RING_LEN (XENFB_IN_RING_SIZE / XENFB_IN_EVENT_SIZE)
++#define XENFB_IN_RING_OFFS 1024
++#define XENFB_IN_RING(page) \
++ ((union xenfb_in_event *)((char *)(page) + XENFB_IN_RING_OFFS))
++#define XENFB_IN_RING_REF(page, idx) \
++ (XENFB_IN_RING((page))[(idx) % XENFB_IN_RING_LEN])
++
++#define XENFB_OUT_RING_SIZE 2048
++#define XENFB_OUT_RING_LEN (XENFB_OUT_RING_SIZE / XENFB_OUT_EVENT_SIZE)
++#define XENFB_OUT_RING_OFFS (XENFB_IN_RING_OFFS + XENFB_IN_RING_SIZE)
++#define XENFB_OUT_RING(page) \
++ ((union xenfb_out_event *)((char *)(page) + XENFB_OUT_RING_OFFS))
++#define XENFB_OUT_RING_REF(page, idx) \
++ (XENFB_OUT_RING((page))[(idx) % XENFB_OUT_RING_LEN])
++
++struct xenfb_page {
++ uint32_t in_cons, in_prod;
++ uint32_t out_cons, out_prod;
++
++ int32_t width; /* width of the framebuffer (in pixels) */
++ int32_t height; /* height of the framebuffer (in pixels) */
++ uint32_t line_length; /* length of a row of pixels (in bytes) */
++ uint32_t mem_length; /* length of the framebuffer (in bytes) */
++ uint8_t depth; /* depth of a pixel (in bits) */
++
++ /*
++ * Framebuffer page directory
++ *
++ * Each directory page holds PAGE_SIZE / sizeof(*pd)
++ * framebuffer pages, and can thus map up to PAGE_SIZE *
++ * PAGE_SIZE / sizeof(*pd) bytes. With PAGE_SIZE == 4096 and
++ * sizeof(unsigned long) == 4, that's 4 Megs. Two directory
++ * pages should be enough for a while.
++ */
++ unsigned long pd[2];
++};
++
++/*
++ * Wart: xenkbd needs to know resolution. Put it here until a better
++ * solution is found, but don't leak it to the backend.
++ */
++#ifdef __KERNEL__
++#define XENFB_WIDTH 800
++#define XENFB_HEIGHT 600
++#define XENFB_DEPTH 32
++#endif
++
++#endif
+diff --git a/include/xen/interface/io/kbdif.h b/include/xen/interface/io/kbdif.h
+new file mode 100644
+index 0000000..fb97f42
+--- /dev/null
++++ b/include/xen/interface/io/kbdif.h
+@@ -0,0 +1,114 @@
++/*
++ * kbdif.h -- Xen virtual keyboard/mouse
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to
++ * deal in the Software without restriction, including without limitation the
++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
++ * sell copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ *
++ * Copyright (C) 2005 Anthony Liguori <aliguori at us.ibm.com>
++ * Copyright (C) 2006 Red Hat, Inc., Markus Armbruster <armbru at redhat.com>
++ */
++
++#ifndef __XEN_PUBLIC_IO_KBDIF_H__
++#define __XEN_PUBLIC_IO_KBDIF_H__
++
++/* In events (backend -> frontend) */
++
++/*
++ * Frontends should ignore unknown in events.
++ */
++
++/* Pointer movement event */
++#define XENKBD_TYPE_MOTION 1
++/* Event type 2 currently not used */
++/* Key event (includes pointer buttons) */
++#define XENKBD_TYPE_KEY 3
++/*
++ * Pointer position event
++ * Capable backend sets feature-abs-pointer in xenstore.
++ * Frontend requests ot instead of XENKBD_TYPE_MOTION by setting
++ * request-abs-update in xenstore.
++ */
++#define XENKBD_TYPE_POS 4
++
++struct xenkbd_motion {
++ uint8_t type; /* XENKBD_TYPE_MOTION */
++ int32_t rel_x; /* relative X motion */
++ int32_t rel_y; /* relative Y motion */
++};
++
++struct xenkbd_key {
++ uint8_t type; /* XENKBD_TYPE_KEY */
++ uint8_t pressed; /* 1 if pressed; 0 otherwise */
++ uint32_t keycode; /* KEY_* from linux/input.h */
++};
++
++struct xenkbd_position {
++ uint8_t type; /* XENKBD_TYPE_POS */
++ int32_t abs_x; /* absolute X position (in FB pixels) */
++ int32_t abs_y; /* absolute Y position (in FB pixels) */
++};
++
++#define XENKBD_IN_EVENT_SIZE 40
++
++union xenkbd_in_event {
++ uint8_t type;
++ struct xenkbd_motion motion;
++ struct xenkbd_key key;
++ struct xenkbd_position pos;
++ char pad[XENKBD_IN_EVENT_SIZE];
++};
++
++/* Out events (frontend -> backend) */
++
++/*
++ * Out events may be sent only when requested by backend, and receipt
++ * of an unknown out event is an error.
++ * No out events currently defined.
++ */
++
++#define XENKBD_OUT_EVENT_SIZE 40
++
++union xenkbd_out_event {
++ uint8_t type;
++ char pad[XENKBD_OUT_EVENT_SIZE];
++};
++
++/* shared page */
++
++#define XENKBD_IN_RING_SIZE 2048
++#define XENKBD_IN_RING_LEN (XENKBD_IN_RING_SIZE / XENKBD_IN_EVENT_SIZE)
++#define XENKBD_IN_RING_OFFS 1024
++#define XENKBD_IN_RING(page) \
++ ((union xenkbd_in_event *)((char *)(page) + XENKBD_IN_RING_OFFS))
++#define XENKBD_IN_RING_REF(page, idx) \
++ (XENKBD_IN_RING((page))[(idx) % XENKBD_IN_RING_LEN])
++
++#define XENKBD_OUT_RING_SIZE 1024
++#define XENKBD_OUT_RING_LEN (XENKBD_OUT_RING_SIZE / XENKBD_OUT_EVENT_SIZE)
++#define XENKBD_OUT_RING_OFFS (XENKBD_IN_RING_OFFS + XENKBD_IN_RING_SIZE)
++#define XENKBD_OUT_RING(page) \
++ ((union xenkbd_out_event *)((char *)(page) + XENKBD_OUT_RING_OFFS))
++#define XENKBD_OUT_RING_REF(page, idx) \
++ (XENKBD_OUT_RING((page))[(idx) % XENKBD_OUT_RING_LEN])
++
++struct xenkbd_page {
++ uint32_t in_cons, in_prod;
++ uint32_t out_cons, out_prod;
++};
++
++#endif
+diff --git a/include/xen/interface/io/protocols.h b/include/xen/interface/io/protocols.h
+new file mode 100644
+index 0000000..01fc8ae
+--- /dev/null
++++ b/include/xen/interface/io/protocols.h
+@@ -0,0 +1,21 @@
++#ifndef __XEN_PROTOCOLS_H__
++#define __XEN_PROTOCOLS_H__
++
++#define XEN_IO_PROTO_ABI_X86_32 "x86_32-abi"
++#define XEN_IO_PROTO_ABI_X86_64 "x86_64-abi"
++#define XEN_IO_PROTO_ABI_IA64 "ia64-abi"
++#define XEN_IO_PROTO_ABI_POWERPC64 "powerpc64-abi"
++
++#if defined(__i386__)
++# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_32
++#elif defined(__x86_64__)
++# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_64
++#elif defined(__ia64__)
++# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_IA64
++#elif defined(__powerpc64__)
++# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_POWERPC64
++#else
++# error arch fixup needed here
++#endif
++
++#endif
+diff --git a/include/xen/interface/memory.h b/include/xen/interface/memory.h
+index af36ead..da76846 100644
+--- a/include/xen/interface/memory.h
++++ b/include/xen/interface/memory.h
+@@ -29,7 +29,7 @@ struct xen_memory_reservation {
+ * OUT: GMFN bases of extents that were allocated
+ * (NB. This command also updates the mach_to_phys translation table)
+ */
+- GUEST_HANDLE(ulong) extent_start;
++ ulong extent_start;
+
+ /* Number of extents, and size/alignment of each (2^extent_order pages). */
+ unsigned long nr_extents;
+@@ -50,7 +50,6 @@ struct xen_memory_reservation {
+ domid_t domid;
+
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(xen_memory_reservation);
+
+ /*
+ * Returns the maximum machine frame number of mapped RAM in this system.
+@@ -86,7 +85,7 @@ struct xen_machphys_mfn_list {
+ * any large discontiguities in the machine address space, 2MB gaps in
+ * the machphys table will be represented by an MFN base of zero.
+ */
+- GUEST_HANDLE(ulong) extent_start;
++ ulong extent_start;
+
+ /*
+ * Number of extents written to the above array. This will be smaller
+@@ -94,7 +93,6 @@ struct xen_machphys_mfn_list {
+ */
+ unsigned int nr_extents;
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mfn_list);
+
+ /*
+ * Sets the GPFN at which a particular page appears in the specified guest's
+@@ -117,7 +115,6 @@ struct xen_add_to_physmap {
+ /* GPFN where the source mapping page should appear. */
+ unsigned long gpfn;
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap);
+
+ /*
+ * Translates a list of domain-specific GPFNs into MFNs. Returns a -ve error
+@@ -132,14 +129,13 @@ struct xen_translate_gpfn_list {
+ unsigned long nr_gpfns;
+
+ /* List of GPFNs to translate. */
+- GUEST_HANDLE(ulong) gpfn_list;
++ ulong gpfn_list;
+
+ /*
+ * Output list to contain MFN translations. May be the same as the input
+ * list (in which case each input GPFN is overwritten with the output MFN).
+ */
+- GUEST_HANDLE(ulong) mfn_list;
++ ulong mfn_list;
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(xen_translate_gpfn_list);
+
+ #endif /* __XEN_PUBLIC_MEMORY_H__ */
+diff --git a/include/xen/interface/vcpu.h b/include/xen/interface/vcpu.h
+index b05d8a6..87e6f8a 100644
+--- a/include/xen/interface/vcpu.h
++++ b/include/xen/interface/vcpu.h
+@@ -85,6 +85,7 @@ struct vcpu_runstate_info {
+ */
+ uint64_t time[4];
+ };
++DEFINE_GUEST_HANDLE_STRUCT(vcpu_runstate_info);
+
+ /* VCPU is currently running on a physical CPU. */
+ #define RUNSTATE_running 0
+@@ -119,6 +120,7 @@ struct vcpu_runstate_info {
+ #define VCPUOP_register_runstate_memory_area 5
+ struct vcpu_register_runstate_memory_area {
+ union {
++ GUEST_HANDLE(vcpu_runstate_info) h;
+ struct vcpu_runstate_info *v;
+ uint64_t p;
+ } addr;
+@@ -134,6 +136,7 @@ struct vcpu_register_runstate_memory_area {
+ struct vcpu_set_periodic_timer {
+ uint64_t period_ns;
+ };
++DEFINE_GUEST_HANDLE_STRUCT(vcpu_set_periodic_timer);
+
+ /*
+ * Set or stop a VCPU's single-shot timer. Every VCPU has one single-shot
+@@ -145,6 +148,7 @@ struct vcpu_set_singleshot_timer {
+ uint64_t timeout_abs_ns;
+ uint32_t flags; /* VCPU_SSHOTTMR_??? */
+ };
++DEFINE_GUEST_HANDLE_STRUCT(vcpu_set_singleshot_timer);
+
+ /* Flags to VCPUOP_set_singleshot_timer. */
+ /* Require the timeout to be in the future (return -ETIME if it's passed). */
+@@ -164,5 +168,6 @@ struct vcpu_register_vcpu_info {
+ uint32_t offset; /* offset within page */
+ uint32_t rsvd; /* unused */
+ };
++DEFINE_GUEST_HANDLE_STRUCT(vcpu_register_vcpu_info);
+
+ #endif /* __XEN_PUBLIC_VCPU_H__ */
+diff --git a/include/xen/interface/xen.h b/include/xen/interface/xen.h
+index 518a5bf..9b018da 100644
+--- a/include/xen/interface/xen.h
++++ b/include/xen/interface/xen.h
+@@ -58,6 +58,16 @@
+ #define __HYPERVISOR_physdev_op 33
+ #define __HYPERVISOR_hvm_op 34
+
++/* Architecture-specific hypercall definitions. */
++#define __HYPERVISOR_arch_0 48
++#define __HYPERVISOR_arch_1 49
++#define __HYPERVISOR_arch_2 50
++#define __HYPERVISOR_arch_3 51
++#define __HYPERVISOR_arch_4 52
++#define __HYPERVISOR_arch_5 53
++#define __HYPERVISOR_arch_6 54
++#define __HYPERVISOR_arch_7 55
++
+ /*
+ * VIRTUAL INTERRUPTS
+ *
+@@ -68,8 +78,18 @@
+ #define VIRQ_CONSOLE 2 /* (DOM0) Bytes received on emergency console. */
+ #define VIRQ_DOM_EXC 3 /* (DOM0) Exceptional event for some domain. */
+ #define VIRQ_DEBUGGER 6 /* (DOM0) A domain has paused for debugging. */
+-#define NR_VIRQS 8
+
++/* Architecture-specific VIRQ definitions. */
++#define VIRQ_ARCH_0 16
++#define VIRQ_ARCH_1 17
++#define VIRQ_ARCH_2 18
++#define VIRQ_ARCH_3 19
++#define VIRQ_ARCH_4 20
++#define VIRQ_ARCH_5 21
++#define VIRQ_ARCH_6 22
++#define VIRQ_ARCH_7 23
++
++#define NR_VIRQS 24
+ /*
+ * MMU-UPDATE REQUESTS
+ *
+diff --git a/include/xen/interface/xencomm.h b/include/xen/interface/xencomm.h
+new file mode 100644
+index 0000000..ac45e07
+--- /dev/null
++++ b/include/xen/interface/xencomm.h
+@@ -0,0 +1,41 @@
++/*
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to
++ * deal in the Software without restriction, including without limitation the
++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
++ * sell copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ *
++ * Copyright (C) IBM Corp. 2006
++ */
++
++#ifndef _XEN_XENCOMM_H_
++#define _XEN_XENCOMM_H_
++
++/* A xencomm descriptor is a scatter/gather list containing physical
++ * addresses corresponding to a virtually contiguous memory area. The
++ * hypervisor translates these physical addresses to machine addresses to copy
++ * to and from the virtually contiguous area.
++ */
++
++#define XENCOMM_MAGIC 0x58434F4D /* 'XCOM' */
++#define XENCOMM_INVALID (~0UL)
++
++struct xencomm_desc {
++ uint32_t magic;
++ uint32_t nr_addrs; /* the number of entries in address[] */
++ uint64_t address[0];
++};
++
++#endif /* _XEN_XENCOMM_H_ */
+diff --git a/include/xen/page.h b/include/xen/page.h
+index 031ef22..eaf85fa 100644
+--- a/include/xen/page.h
++++ b/include/xen/page.h
+@@ -1,180 +1 @@
+-#ifndef __XEN_PAGE_H
+-#define __XEN_PAGE_H
+-
+-#include <linux/pfn.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/pgtable.h>
+-
+-#include <xen/features.h>
+-
+-#ifdef CONFIG_X86_PAE
+-/* Xen machine address */
+-typedef struct xmaddr {
+- unsigned long long maddr;
+-} xmaddr_t;
+-
+-/* Xen pseudo-physical address */
+-typedef struct xpaddr {
+- unsigned long long paddr;
+-} xpaddr_t;
+-#else
+-/* Xen machine address */
+-typedef struct xmaddr {
+- unsigned long maddr;
+-} xmaddr_t;
+-
+-/* Xen pseudo-physical address */
+-typedef struct xpaddr {
+- unsigned long paddr;
+-} xpaddr_t;
+-#endif
+-
+-#define XMADDR(x) ((xmaddr_t) { .maddr = (x) })
+-#define XPADDR(x) ((xpaddr_t) { .paddr = (x) })
+-
+-/**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
+-#define INVALID_P2M_ENTRY (~0UL)
+-#define FOREIGN_FRAME_BIT (1UL<<31)
+-#define FOREIGN_FRAME(m) ((m) | FOREIGN_FRAME_BIT)
+-
+-extern unsigned long *phys_to_machine_mapping;
+-
+-static inline unsigned long pfn_to_mfn(unsigned long pfn)
+-{
+- if (xen_feature(XENFEAT_auto_translated_physmap))
+- return pfn;
+-
+- return phys_to_machine_mapping[(unsigned int)(pfn)] &
+- ~FOREIGN_FRAME_BIT;
+-}
+-
+-static inline int phys_to_machine_mapping_valid(unsigned long pfn)
+-{
+- if (xen_feature(XENFEAT_auto_translated_physmap))
+- return 1;
+-
+- return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
+-}
+-
+-static inline unsigned long mfn_to_pfn(unsigned long mfn)
+-{
+- unsigned long pfn;
+-
+- if (xen_feature(XENFEAT_auto_translated_physmap))
+- return mfn;
+-
+-#if 0
+- if (unlikely((mfn >> machine_to_phys_order) != 0))
+- return max_mapnr;
+-#endif
+-
+- pfn = 0;
+- /*
+- * The array access can fail (e.g., device space beyond end of RAM).
+- * In such cases it doesn't matter what we return (we return garbage),
+- * but we must handle the fault without crashing!
+- */
+- __get_user(pfn, &machine_to_phys_mapping[mfn]);
+-
+- return pfn;
+-}
+-
+-static inline xmaddr_t phys_to_machine(xpaddr_t phys)
+-{
+- unsigned offset = phys.paddr & ~PAGE_MASK;
+- return XMADDR(PFN_PHYS((u64)pfn_to_mfn(PFN_DOWN(phys.paddr))) | offset);
+-}
+-
+-static inline xpaddr_t machine_to_phys(xmaddr_t machine)
+-{
+- unsigned offset = machine.maddr & ~PAGE_MASK;
+- return XPADDR(PFN_PHYS((u64)mfn_to_pfn(PFN_DOWN(machine.maddr))) | offset);
+-}
+-
+-/*
+- * We detect special mappings in one of two ways:
+- * 1. If the MFN is an I/O page then Xen will set the m2p entry
+- * to be outside our maximum possible pseudophys range.
+- * 2. If the MFN belongs to a different domain then we will certainly
+- * not have MFN in our p2m table. Conversely, if the page is ours,
+- * then we'll have p2m(m2p(MFN))==MFN.
+- * If we detect a special mapping then it doesn't have a 'struct page'.
+- * We force !pfn_valid() by returning an out-of-range pointer.
+- *
+- * NB. These checks require that, for any MFN that is not in our reservation,
+- * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if
+- * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN.
+- * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety.
+- *
+- * NB2. When deliberately mapping foreign pages into the p2m table, you *must*
+- * use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we
+- * require. In all the cases we care about, the FOREIGN_FRAME bit is
+- * masked (e.g., pfn_to_mfn()) so behaviour there is correct.
+- */
+-static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
+-{
+- extern unsigned long max_mapnr;
+- unsigned long pfn = mfn_to_pfn(mfn);
+- if ((pfn < max_mapnr)
+- && !xen_feature(XENFEAT_auto_translated_physmap)
+- && (phys_to_machine_mapping[pfn] != mfn))
+- return max_mapnr; /* force !pfn_valid() */
+- return pfn;
+-}
+-
+-static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
+-{
+- if (xen_feature(XENFEAT_auto_translated_physmap)) {
+- BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
+- return;
+- }
+- phys_to_machine_mapping[pfn] = mfn;
+-}
+-
+-/* VIRT <-> MACHINE conversion */
+-#define virt_to_machine(v) (phys_to_machine(XPADDR(__pa(v))))
+-#define virt_to_mfn(v) (pfn_to_mfn(PFN_DOWN(__pa(v))))
+-#define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT))
+-
+-#ifdef CONFIG_X86_PAE
+-#define pte_mfn(_pte) (((_pte).pte_low >> PAGE_SHIFT) | \
+- (((_pte).pte_high & 0xfff) << (32-PAGE_SHIFT)))
+-
+-static inline pte_t mfn_pte(unsigned long page_nr, pgprot_t pgprot)
+-{
+- pte_t pte;
+-
+- pte.pte_high = (page_nr >> (32 - PAGE_SHIFT)) |
+- (pgprot_val(pgprot) >> 32);
+- pte.pte_high &= (__supported_pte_mask >> 32);
+- pte.pte_low = ((page_nr << PAGE_SHIFT) | pgprot_val(pgprot));
+- pte.pte_low &= __supported_pte_mask;
+-
+- return pte;
+-}
+-
+-static inline unsigned long long pte_val_ma(pte_t x)
+-{
+- return x.pte;
+-}
+-#define pmd_val_ma(v) ((v).pmd)
+-#define pud_val_ma(v) ((v).pgd.pgd)
+-#define __pte_ma(x) ((pte_t) { .pte = (x) })
+-#define __pmd_ma(x) ((pmd_t) { (x) } )
+-#else /* !X86_PAE */
+-#define pte_mfn(_pte) ((_pte).pte_low >> PAGE_SHIFT)
+-#define mfn_pte(pfn, prot) __pte_ma(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+-#define pte_val_ma(x) ((x).pte)
+-#define pmd_val_ma(v) ((v).pud.pgd.pgd)
+-#define __pte_ma(x) ((pte_t) { (x) } )
+-#endif /* CONFIG_X86_PAE */
+-
+-#define pgd_val_ma(x) ((x).pgd)
+-
+-
+-xmaddr_t arbitrary_virt_to_machine(unsigned long address);
+-void make_lowmem_page_readonly(void *vaddr);
+-void make_lowmem_page_readwrite(void *vaddr);
+-
+-#endif /* __XEN_PAGE_H */
++#include <asm/xen/page.h>
+diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
+new file mode 100644
+index 0000000..10ddfe0
+--- /dev/null
++++ b/include/xen/xen-ops.h
+@@ -0,0 +1,8 @@
++#ifndef INCLUDE_XEN_OPS_H
++#define INCLUDE_XEN_OPS_H
++
++#include <linux/percpu.h>
++
++DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu);
++
++#endif /* INCLUDE_XEN_OPS_H */
+diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h
+index 6f7c290..6369d89 100644
+--- a/include/xen/xenbus.h
++++ b/include/xen/xenbus.h
+@@ -97,6 +97,7 @@ struct xenbus_driver {
+ int (*uevent)(struct xenbus_device *, char **, int, char *, int);
+ struct device_driver driver;
+ int (*read_otherend_details)(struct xenbus_device *dev);
++ int (*is_ready)(struct xenbus_device *dev);
+ };
+
+ static inline struct xenbus_driver *to_xenbus_driver(struct device_driver *drv)
+diff --git a/include/xen/xencomm.h b/include/xen/xencomm.h
+new file mode 100644
+index 0000000..e43b039
+--- /dev/null
++++ b/include/xen/xencomm.h
+@@ -0,0 +1,77 @@
++/*
++ * 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
++ *
++ * Copyright (C) IBM Corp. 2006
++ *
++ * Authors: Hollis Blanchard <hollisb at us.ibm.com>
++ * Jerone Young <jyoung5 at us.ibm.com>
++ */
++
++#ifndef _LINUX_XENCOMM_H_
++#define _LINUX_XENCOMM_H_
++
++#include <xen/interface/xencomm.h>
++
++#define XENCOMM_MINI_ADDRS 3
++struct xencomm_mini {
++ struct xencomm_desc _desc;
++ uint64_t address[XENCOMM_MINI_ADDRS];
++};
++
++/* To avoid additionnal virt to phys conversion, an opaque structure is
++ presented. */
++struct xencomm_handle;
++
++extern void xencomm_free(struct xencomm_handle *desc);
++extern struct xencomm_handle *xencomm_map(void *ptr, unsigned long bytes);
++extern struct xencomm_handle *__xencomm_map_no_alloc(void *ptr,
++ unsigned long bytes, struct xencomm_mini *xc_area);
++
++#if 0
++#define XENCOMM_MINI_ALIGNED(xc_desc, n) \
++ struct xencomm_mini xc_desc ## _base[(n)] \
++ __attribute__((__aligned__(sizeof(struct xencomm_mini)))); \
++ struct xencomm_mini *xc_desc = &xc_desc ## _base[0];
++#else
++/*
++ * gcc bug workaround:
++ * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16660
++ * gcc doesn't handle properly stack variable with
++ * __attribute__((__align__(sizeof(struct xencomm_mini))))
++ */
++#define XENCOMM_MINI_ALIGNED(xc_desc, n) \
++ unsigned char xc_desc ## _base[((n) + 1 ) * \
++ sizeof(struct xencomm_mini)]; \
++ struct xencomm_mini *xc_desc = (struct xencomm_mini *) \
++ ((unsigned long)xc_desc ## _base + \
++ (sizeof(struct xencomm_mini) - \
++ ((unsigned long)xc_desc ## _base) % \
++ sizeof(struct xencomm_mini)));
++#endif
++#define xencomm_map_no_alloc(ptr, bytes) \
++ ({ XENCOMM_MINI_ALIGNED(xc_desc, 1); \
++ __xencomm_map_no_alloc(ptr, bytes, xc_desc); })
++
++/* provided by architecture code: */
++extern unsigned long xencomm_vtop(unsigned long vaddr);
++
++static inline void *xencomm_pa(void *ptr)
++{
++ return (void *)xencomm_vtop((unsigned long)ptr);
++}
++
++#define xen_guest_handle(hnd) ((hnd).p)
++
++#endif /* _LINUX_XENCOMM_H_ */
+diff --git a/init/Kconfig b/init/Kconfig
+index a97924b..ba3a389 100644
+--- a/init/Kconfig
++++ b/init/Kconfig
+@@ -328,6 +328,13 @@ config RT_GROUP_SCHED
+ depends on EXPERIMENTAL
+ depends on GROUP_SCHED
+ default n
++ help
++ This feature lets you explicitly allocate real CPU bandwidth
++ to users or control groups (depending on the "Basis for grouping tasks"
++ setting below. If enabled, it will also make it impossible to
++ schedule realtime tasks for non-root users until you allocate
++ realtime bandwidth for them.
++ See Documentation/sched-rt-group.txt for more information.
+
+ choice
+ depends on GROUP_SCHED
+@@ -763,7 +770,7 @@ endmenu # General setup
+ config SLABINFO
+ bool
+ depends on PROC_FS
+- depends on SLAB || SLUB
++ depends on SLAB || SLUB_DEBUG
+ default y
+
+ config RT_MUTEXES
+diff --git a/init/main.c b/init/main.c
+index 99ce949..1687b01 100644
+--- a/init/main.c
++++ b/init/main.c
+@@ -359,10 +359,31 @@ static void __init smp_init(void)
+ #endif
+
+ static inline void setup_per_cpu_areas(void) { }
++static inline void setup_nr_cpu_ids(void) { }
+ static inline void smp_prepare_cpus(unsigned int maxcpus) { }
+
+ #else
+
++#if NR_CPUS > BITS_PER_LONG
++cpumask_t cpu_mask_all __read_mostly = CPU_MASK_ALL;
++EXPORT_SYMBOL(cpu_mask_all);
++#endif
++
++/* Setup number of possible processor ids */
++int nr_cpu_ids __read_mostly = NR_CPUS;
++EXPORT_SYMBOL(nr_cpu_ids);
++
++/* An arch may set nr_cpu_ids earlier if needed, so this would be redundant */
++static void __init setup_nr_cpu_ids(void)
++{
++ int cpu, highest_cpu = 0;
++
++ for_each_possible_cpu(cpu)
++ highest_cpu = cpu;
++
++ nr_cpu_ids = highest_cpu + 1;
++}
++
+ #ifndef CONFIG_HAVE_SETUP_PER_CPU_AREA
+ unsigned long __per_cpu_offset[NR_CPUS] __read_mostly;
+
+@@ -500,7 +521,11 @@ static void __init boot_cpu_init(void)
+ cpu_set(cpu, cpu_possible_map);
+ }
+
+-void __init __attribute__((weak)) smp_setup_processor_id(void)
++void __init __weak smp_setup_processor_id(void)
++{
++}
++
++void __init __weak thread_info_cache_init(void)
+ {
+ }
+
+@@ -537,6 +562,7 @@ asmlinkage void __init start_kernel(void)
+ setup_command_line(command_line);
+ unwind_setup();
+ setup_per_cpu_areas();
++ setup_nr_cpu_ids();
+ smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
+
+ /*
+@@ -623,6 +649,7 @@ asmlinkage void __init start_kernel(void)
+ if (efi_enabled)
+ efi_enter_virtual_mode();
+ #endif
++ thread_info_cache_init();
+ fork_init(num_physpages);
+ proc_caches_init();
+ buffer_init();
+@@ -811,7 +838,7 @@ static int __init kernel_init(void * unused)
+ /*
+ * init can run on any cpu.
+ */
+- set_cpus_allowed(current, CPU_MASK_ALL);
++ set_cpus_allowed_ptr(current, CPU_MASK_ALL_PTR);
+ /*
+ * Tell the world that we're going to be the grim
+ * reaper of innocent orphaned children.
+diff --git a/ipc/mqueue.c b/ipc/mqueue.c
+index 60f7a27..94fd3b0 100644
+--- a/ipc/mqueue.c
++++ b/ipc/mqueue.c
+@@ -598,6 +598,7 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry,
+ int oflag, mode_t mode, struct mq_attr __user *u_attr)
+ {
+ struct mq_attr attr;
++ struct file *result;
+ int ret;
+
+ if (u_attr) {
+@@ -612,13 +613,24 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry,
+ }
+
+ mode &= ~current->fs->umask;
++ ret = mnt_want_write(mqueue_mnt);
++ if (ret)
++ goto out;
+ ret = vfs_create(dir->d_inode, dentry, mode, NULL);
+ dentry->d_fsdata = NULL;
+ if (ret)
+- goto out;
+-
+- return dentry_open(dentry, mqueue_mnt, oflag);
+-
++ goto out_drop_write;
++
++ result = dentry_open(dentry, mqueue_mnt, oflag);
++ /*
++ * dentry_open() took a persistent mnt_want_write(),
++ * so we can now drop this one.
++ */
++ mnt_drop_write(mqueue_mnt);
++ return result;
++
++out_drop_write:
++ mnt_drop_write(mqueue_mnt);
+ out:
+ dput(dentry);
+ mntput(mqueue_mnt);
+@@ -742,8 +754,11 @@ asmlinkage long sys_mq_unlink(const char __user *u_name)
+ inode = dentry->d_inode;
+ if (inode)
+ atomic_inc(&inode->i_count);
+-
++ err = mnt_want_write(mqueue_mnt);
++ if (err)
++ goto out_err;
+ err = vfs_unlink(dentry->d_parent->d_inode, dentry);
++ mnt_drop_write(mqueue_mnt);
+ out_err:
+ dput(dentry);
+
+diff --git a/kernel/Makefile b/kernel/Makefile
+index 6c584c5..6c5f081 100644
+--- a/kernel/Makefile
++++ b/kernel/Makefile
+@@ -8,7 +8,7 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
+ signal.o sys.o kmod.o workqueue.o pid.o \
+ rcupdate.o extable.o params.o posix-timers.o \
+ kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
+- hrtimer.o rwsem.o nsproxy.o srcu.o \
++ hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \
+ notifier.o ksysfs.o pm_qos_params.o
+
+ obj-$(CONFIG_SYSCTL) += sysctl_check.o
+@@ -53,6 +53,7 @@ obj-$(CONFIG_AUDIT) += audit.o auditfilter.o
+ obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
+ obj-$(CONFIG_AUDIT_TREE) += audit_tree.o
+ obj-$(CONFIG_KPROBES) += kprobes.o
++obj-$(CONFIG_KGDB) += kgdb.o
+ obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o
+ obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
+ obj-$(CONFIG_SECCOMP) += seccomp.o
+diff --git a/kernel/audit.c b/kernel/audit.c
+index b782b04..a7b1608 100644
+--- a/kernel/audit.c
++++ b/kernel/audit.c
+@@ -21,7 +21,7 @@
+ *
+ * Written by Rickard E. (Rik) Faith <faith at redhat.com>
+ *
+- * Goals: 1) Integrate fully with SELinux.
++ * Goals: 1) Integrate fully with Security Modules.
+ * 2) Minimal run-time overhead:
+ * a) Minimal when syscall auditing is disabled (audit_enable=0).
+ * b) Small when syscall auditing is enabled and no audit record
+@@ -55,7 +55,6 @@
+ #include <net/netlink.h>
+ #include <linux/skbuff.h>
+ #include <linux/netlink.h>
+-#include <linux/selinux.h>
+ #include <linux/inotify.h>
+ #include <linux/freezer.h>
+ #include <linux/tty.h>
+@@ -265,13 +264,13 @@ static int audit_log_config_change(char *function_name, int new, int old,
+ char *ctx = NULL;
+ u32 len;
+
+- rc = selinux_sid_to_string(sid, &ctx, &len);
++ rc = security_secid_to_secctx(sid, &ctx, &len);
+ if (rc) {
+ audit_log_format(ab, " sid=%u", sid);
+ allow_changes = 0; /* Something weird, deny request */
+ } else {
+ audit_log_format(ab, " subj=%s", ctx);
+- kfree(ctx);
++ security_release_secctx(ctx, len);
+ }
+ }
+ audit_log_format(ab, " res=%d", allow_changes);
+@@ -550,12 +549,13 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
+ audit_log_format(*ab, "user pid=%d uid=%u auid=%u",
+ pid, uid, auid);
+ if (sid) {
+- rc = selinux_sid_to_string(sid, &ctx, &len);
++ rc = security_secid_to_secctx(sid, &ctx, &len);
+ if (rc)
+ audit_log_format(*ab, " ssid=%u", sid);
+- else
++ else {
+ audit_log_format(*ab, " subj=%s", ctx);
+- kfree(ctx);
++ security_release_secctx(ctx, len);
++ }
+ }
+
+ return rc;
+@@ -758,18 +758,18 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ break;
+ }
+ case AUDIT_SIGNAL_INFO:
+- err = selinux_sid_to_string(audit_sig_sid, &ctx, &len);
++ err = security_secid_to_secctx(audit_sig_sid, &ctx, &len);
+ if (err)
+ return err;
+ sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL);
+ if (!sig_data) {
+- kfree(ctx);
++ security_release_secctx(ctx, len);
+ return -ENOMEM;
+ }
+ sig_data->uid = audit_sig_uid;
+ sig_data->pid = audit_sig_pid;
+ memcpy(sig_data->ctx, ctx, len);
+- kfree(ctx);
++ security_release_secctx(ctx, len);
+ audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO,
+ 0, 0, sig_data, sizeof(*sig_data) + len);
+ kfree(sig_data);
+@@ -881,10 +881,6 @@ static int __init audit_init(void)
+ audit_enabled = audit_default;
+ audit_ever_enabled |= !!audit_default;
+
+- /* Register the callback with selinux. This callback will be invoked
+- * when a new policy is loaded. */
+- selinux_audit_set_callback(&selinux_audit_rule_update);
+-
+ audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized");
+
+ #ifdef CONFIG_AUDITSYSCALL
+diff --git a/kernel/audit.h b/kernel/audit.h
+index 2554bd5..3cfc54e 100644
+--- a/kernel/audit.h
++++ b/kernel/audit.h
+@@ -65,34 +65,9 @@ struct audit_watch {
+ struct list_head rules; /* associated rules */
+ };
+
+-struct audit_field {
+- u32 type;
+- u32 val;
+- u32 op;
+- char *se_str;
+- struct selinux_audit_rule *se_rule;
+-};
+-
+ struct audit_tree;
+ struct audit_chunk;
+
+-struct audit_krule {
+- int vers_ops;
+- u32 flags;
+- u32 listnr;
+- u32 action;
+- u32 mask[AUDIT_BITMASK_SIZE];
+- u32 buflen; /* for data alloc on list rules */
+- u32 field_count;
+- char *filterkey; /* ties events to rules */
+- struct audit_field *fields;
+- struct audit_field *arch_f; /* quick access to arch field */
+- struct audit_field *inode_f; /* quick access to an inode field */
+- struct audit_watch *watch; /* associated watch */
+- struct audit_tree *tree; /* associated watched tree */
+- struct list_head rlist; /* entry in audit_{watch,tree}.rules list */
+-};
+-
+ struct audit_entry {
+ struct list_head list;
+ struct rcu_head rcu;
+diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
+index 2f2914b..28fef6b 100644
+--- a/kernel/auditfilter.c
++++ b/kernel/auditfilter.c
+@@ -28,7 +28,7 @@
+ #include <linux/netlink.h>
+ #include <linux/sched.h>
+ #include <linux/inotify.h>
+-#include <linux/selinux.h>
++#include <linux/security.h>
+ #include "audit.h"
+
+ /*
+@@ -38,7 +38,7 @@
+ * Synchronizes writes and blocking reads of audit's filterlist
+ * data. Rcu is used to traverse the filterlist and access
+ * contents of structs audit_entry, audit_watch and opaque
+- * selinux rules during filtering. If modified, these structures
++ * LSM rules during filtering. If modified, these structures
+ * must be copied and replace their counterparts in the filterlist.
+ * An audit_parent struct is not accessed during filtering, so may
+ * be written directly provided audit_filter_mutex is held.
+@@ -139,8 +139,8 @@ static inline void audit_free_rule(struct audit_entry *e)
+ if (e->rule.fields)
+ for (i = 0; i < e->rule.field_count; i++) {
+ struct audit_field *f = &e->rule.fields[i];
+- kfree(f->se_str);
+- selinux_audit_rule_free(f->se_rule);
++ kfree(f->lsm_str);
++ security_audit_rule_free(f->lsm_rule);
+ }
+ kfree(e->rule.fields);
+ kfree(e->rule.filterkey);
+@@ -554,8 +554,8 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
+ f->op = data->fieldflags[i] & AUDIT_OPERATORS;
+ f->type = data->fields[i];
+ f->val = data->values[i];
+- f->se_str = NULL;
+- f->se_rule = NULL;
++ f->lsm_str = NULL;
++ f->lsm_rule = NULL;
+ switch(f->type) {
+ case AUDIT_PID:
+ case AUDIT_UID:
+@@ -597,12 +597,12 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
+ goto exit_free;
+ entry->rule.buflen += f->val;
+
+- err = selinux_audit_rule_init(f->type, f->op, str,
+- &f->se_rule);
++ err = security_audit_rule_init(f->type, f->op, str,
++ (void **)&f->lsm_rule);
+ /* Keep currently invalid fields around in case they
+ * become valid after a policy reload. */
+ if (err == -EINVAL) {
+- printk(KERN_WARNING "audit rule for selinux "
++ printk(KERN_WARNING "audit rule for LSM "
+ "\'%s\' is invalid\n", str);
+ err = 0;
+ }
+@@ -610,7 +610,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
+ kfree(str);
+ goto exit_free;
+ } else
+- f->se_str = str;
++ f->lsm_str = str;
+ break;
+ case AUDIT_WATCH:
+ str = audit_unpack_string(&bufp, &remain, f->val);
+@@ -754,7 +754,7 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
+ case AUDIT_OBJ_LEV_LOW:
+ case AUDIT_OBJ_LEV_HIGH:
+ data->buflen += data->values[i] =
+- audit_pack_string(&bufp, f->se_str);
++ audit_pack_string(&bufp, f->lsm_str);
+ break;
+ case AUDIT_WATCH:
+ data->buflen += data->values[i] =
+@@ -806,7 +806,7 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
+ case AUDIT_OBJ_TYPE:
+ case AUDIT_OBJ_LEV_LOW:
+ case AUDIT_OBJ_LEV_HIGH:
+- if (strcmp(a->fields[i].se_str, b->fields[i].se_str))
++ if (strcmp(a->fields[i].lsm_str, b->fields[i].lsm_str))
+ return 1;
+ break;
+ case AUDIT_WATCH:
+@@ -862,28 +862,28 @@ out:
+ return new;
+ }
+
+-/* Duplicate selinux field information. The se_rule is opaque, so must be
++/* Duplicate LSM field information. The lsm_rule is opaque, so must be
+ * re-initialized. */
+-static inline int audit_dupe_selinux_field(struct audit_field *df,
++static inline int audit_dupe_lsm_field(struct audit_field *df,
+ struct audit_field *sf)
+ {
+ int ret = 0;
+- char *se_str;
++ char *lsm_str;
+
+- /* our own copy of se_str */
+- se_str = kstrdup(sf->se_str, GFP_KERNEL);
+- if (unlikely(!se_str))
++ /* our own copy of lsm_str */
++ lsm_str = kstrdup(sf->lsm_str, GFP_KERNEL);
++ if (unlikely(!lsm_str))
+ return -ENOMEM;
+- df->se_str = se_str;
++ df->lsm_str = lsm_str;
+
+- /* our own (refreshed) copy of se_rule */
+- ret = selinux_audit_rule_init(df->type, df->op, df->se_str,
+- &df->se_rule);
++ /* our own (refreshed) copy of lsm_rule */
++ ret = security_audit_rule_init(df->type, df->op, df->lsm_str,
++ (void **)&df->lsm_rule);
+ /* Keep currently invalid fields around in case they
+ * become valid after a policy reload. */
+ if (ret == -EINVAL) {
+- printk(KERN_WARNING "audit rule for selinux \'%s\' is "
+- "invalid\n", df->se_str);
++ printk(KERN_WARNING "audit rule for LSM \'%s\' is "
++ "invalid\n", df->lsm_str);
+ ret = 0;
+ }
+
+@@ -891,7 +891,7 @@ static inline int audit_dupe_selinux_field(struct audit_field *df,
+ }
+
+ /* Duplicate an audit rule. This will be a deep copy with the exception
+- * of the watch - that pointer is carried over. The selinux specific fields
++ * of the watch - that pointer is carried over. The LSM specific fields
+ * will be updated in the copy. The point is to be able to replace the old
+ * rule with the new rule in the filterlist, then free the old rule.
+ * The rlist element is undefined; list manipulations are handled apart from
+@@ -930,7 +930,7 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old,
+ new->tree = old->tree;
+ memcpy(new->fields, old->fields, sizeof(struct audit_field) * fcount);
+
+- /* deep copy this information, updating the se_rule fields, because
++ /* deep copy this information, updating the lsm_rule fields, because
+ * the originals will all be freed when the old rule is freed. */
+ for (i = 0; i < fcount; i++) {
+ switch (new->fields[i].type) {
+@@ -944,7 +944,7 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old,
+ case AUDIT_OBJ_TYPE:
+ case AUDIT_OBJ_LEV_LOW:
+ case AUDIT_OBJ_LEV_HIGH:
+- err = audit_dupe_selinux_field(&new->fields[i],
++ err = audit_dupe_lsm_field(&new->fields[i],
+ &old->fields[i]);
+ break;
+ case AUDIT_FILTERKEY:
+@@ -1515,11 +1515,12 @@ static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action,
+ if (sid) {
+ char *ctx = NULL;
+ u32 len;
+- if (selinux_sid_to_string(sid, &ctx, &len))
++ if (security_secid_to_secctx(sid, &ctx, &len))
+ audit_log_format(ab, " ssid=%u", sid);
+- else
++ else {
+ audit_log_format(ab, " subj=%s", ctx);
+- kfree(ctx);
++ security_release_secctx(ctx, len);
++ }
+ }
+ audit_log_format(ab, " op=%s rule key=", action);
+ if (rule->filterkey)
+@@ -1761,38 +1762,12 @@ unlock_and_return:
+ return result;
+ }
+
+-/* Check to see if the rule contains any selinux fields. Returns 1 if there
+- are selinux fields specified in the rule, 0 otherwise. */
+-static inline int audit_rule_has_selinux(struct audit_krule *rule)
+-{
+- int i;
+-
+- for (i = 0; i < rule->field_count; i++) {
+- struct audit_field *f = &rule->fields[i];
+- switch (f->type) {
+- case AUDIT_SUBJ_USER:
+- case AUDIT_SUBJ_ROLE:
+- case AUDIT_SUBJ_TYPE:
+- case AUDIT_SUBJ_SEN:
+- case AUDIT_SUBJ_CLR:
+- case AUDIT_OBJ_USER:
+- case AUDIT_OBJ_ROLE:
+- case AUDIT_OBJ_TYPE:
+- case AUDIT_OBJ_LEV_LOW:
+- case AUDIT_OBJ_LEV_HIGH:
+- return 1;
+- }
+- }
+-
+- return 0;
+-}
+-
+-/* This function will re-initialize the se_rule field of all applicable rules.
+- * It will traverse the filter lists serarching for rules that contain selinux
++/* This function will re-initialize the lsm_rule field of all applicable rules.
++ * It will traverse the filter lists serarching for rules that contain LSM
+ * specific filter fields. When such a rule is found, it is copied, the
+- * selinux field is re-initialized, and the old rule is replaced with the
++ * LSM field is re-initialized, and the old rule is replaced with the
+ * updated rule. */
+-int selinux_audit_rule_update(void)
++int audit_update_lsm_rules(void)
+ {
+ struct audit_entry *entry, *n, *nentry;
+ struct audit_watch *watch;
+@@ -1804,7 +1779,7 @@ int selinux_audit_rule_update(void)
+
+ for (i = 0; i < AUDIT_NR_FILTERS; i++) {
+ list_for_each_entry_safe(entry, n, &audit_filter_list[i], list) {
+- if (!audit_rule_has_selinux(&entry->rule))
++ if (!security_audit_rule_known(&entry->rule))
+ continue;
+
+ watch = entry->rule.watch;
+@@ -1815,7 +1790,7 @@ int selinux_audit_rule_update(void)
+ * return value */
+ if (!err)
+ err = PTR_ERR(nentry);
+- audit_panic("error updating selinux filters");
++ audit_panic("error updating LSM filters");
+ if (watch)
+ list_del(&entry->rule.rlist);
+ list_del_rcu(&entry->list);
+diff --git a/kernel/auditsc.c b/kernel/auditsc.c
+index 782262e..56e56ed 100644
+--- a/kernel/auditsc.c
++++ b/kernel/auditsc.c
+@@ -61,7 +61,6 @@
+ #include <linux/security.h>
+ #include <linux/list.h>
+ #include <linux/tty.h>
+-#include <linux/selinux.h>
+ #include <linux/binfmts.h>
+ #include <linux/highmem.h>
+ #include <linux/syscalls.h>
+@@ -528,14 +527,14 @@ static int audit_filter_rules(struct task_struct *tsk,
+ match for now to avoid losing information that
+ may be wanted. An error message will also be
+ logged upon error */
+- if (f->se_rule) {
++ if (f->lsm_rule) {
+ if (need_sid) {
+- selinux_get_task_sid(tsk, &sid);
++ security_task_getsecid(tsk, &sid);
+ need_sid = 0;
+ }
+- result = selinux_audit_rule_match(sid, f->type,
++ result = security_audit_rule_match(sid, f->type,
+ f->op,
+- f->se_rule,
++ f->lsm_rule,
+ ctx);
+ }
+ break;
+@@ -546,18 +545,18 @@ static int audit_filter_rules(struct task_struct *tsk,
+ case AUDIT_OBJ_LEV_HIGH:
+ /* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR
+ also applies here */
+- if (f->se_rule) {
++ if (f->lsm_rule) {
+ /* Find files that match */
+ if (name) {
+- result = selinux_audit_rule_match(
++ result = security_audit_rule_match(
+ name->osid, f->type, f->op,
+- f->se_rule, ctx);
++ f->lsm_rule, ctx);
+ } else if (ctx) {
+ for (j = 0; j < ctx->name_count; j++) {
+- if (selinux_audit_rule_match(
++ if (security_audit_rule_match(
+ ctx->names[j].osid,
+ f->type, f->op,
+- f->se_rule, ctx)) {
++ f->lsm_rule, ctx)) {
+ ++result;
+ break;
+ }
+@@ -570,7 +569,7 @@ static int audit_filter_rules(struct task_struct *tsk,
+ aux = aux->next) {
+ if (aux->type == AUDIT_IPC) {
+ struct audit_aux_data_ipcctl *axi = (void *)aux;
+- if (selinux_audit_rule_match(axi->osid, f->type, f->op, f->se_rule, ctx)) {
++ if (security_audit_rule_match(axi->osid, f->type, f->op, f->lsm_rule, ctx)) {
+ ++result;
+ break;
+ }
+@@ -885,11 +884,11 @@ void audit_log_task_context(struct audit_buffer *ab)
+ int error;
+ u32 sid;
+
+- selinux_get_task_sid(current, &sid);
++ security_task_getsecid(current, &sid);
+ if (!sid)
+ return;
+
+- error = selinux_sid_to_string(sid, &ctx, &len);
++ error = security_secid_to_secctx(sid, &ctx, &len);
+ if (error) {
+ if (error != -EINVAL)
+ goto error_path;
+@@ -897,7 +896,7 @@ void audit_log_task_context(struct audit_buffer *ab)
+ }
+
+ audit_log_format(ab, " subj=%s", ctx);
+- kfree(ctx);
++ security_release_secctx(ctx, len);
+ return;
+
+ error_path:
+@@ -941,7 +940,7 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
+ u32 sid, char *comm)
+ {
+ struct audit_buffer *ab;
+- char *s = NULL;
++ char *ctx = NULL;
+ u32 len;
+ int rc = 0;
+
+@@ -951,15 +950,16 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
+
+ audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid, auid,
+ uid, sessionid);
+- if (selinux_sid_to_string(sid, &s, &len)) {
++ if (security_secid_to_secctx(sid, &ctx, &len)) {
+ audit_log_format(ab, " obj=(none)");
+ rc = 1;
+- } else
+- audit_log_format(ab, " obj=%s", s);
++ } else {
++ audit_log_format(ab, " obj=%s", ctx);
++ security_release_secctx(ctx, len);
++ }
+ audit_log_format(ab, " ocomm=");
+ audit_log_untrustedstring(ab, comm);
+ audit_log_end(ab);
+- kfree(s);
+
+ return rc;
+ }
+@@ -1271,14 +1271,15 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
+ if (axi->osid != 0) {
+ char *ctx = NULL;
+ u32 len;
+- if (selinux_sid_to_string(
++ if (security_secid_to_secctx(
+ axi->osid, &ctx, &len)) {
+ audit_log_format(ab, " osid=%u",
+ axi->osid);
+ call_panic = 1;
+- } else
++ } else {
+ audit_log_format(ab, " obj=%s", ctx);
+- kfree(ctx);
++ security_release_secctx(ctx, len);
++ }
+ }
+ break; }
+
+@@ -1392,13 +1393,14 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
+ if (n->osid != 0) {
+ char *ctx = NULL;
+ u32 len;
+- if (selinux_sid_to_string(
++ if (security_secid_to_secctx(
+ n->osid, &ctx, &len)) {
+ audit_log_format(ab, " osid=%u", n->osid);
+ call_panic = 2;
+- } else
++ } else {
+ audit_log_format(ab, " obj=%s", ctx);
+- kfree(ctx);
++ security_release_secctx(ctx, len);
++ }
+ }
+
+ audit_log_end(ab);
+@@ -1775,7 +1777,7 @@ static void audit_copy_inode(struct audit_names *name, const struct inode *inode
+ name->uid = inode->i_uid;
+ name->gid = inode->i_gid;
+ name->rdev = inode->i_rdev;
+- selinux_get_inode_sid(inode, &name->osid);
++ security_inode_getsecid(inode, &name->osid);
+ }
+
+ /**
+@@ -2190,8 +2192,7 @@ int __audit_ipc_obj(struct kern_ipc_perm *ipcp)
+ ax->uid = ipcp->uid;
+ ax->gid = ipcp->gid;
+ ax->mode = ipcp->mode;
+- selinux_get_ipc_sid(ipcp, &ax->osid);
+-
++ security_ipc_getsecid(ipcp, &ax->osid);
+ ax->d.type = AUDIT_IPC;
+ ax->d.next = context->aux;
+ context->aux = (void *)ax;
+@@ -2343,7 +2344,7 @@ void __audit_ptrace(struct task_struct *t)
+ context->target_auid = audit_get_loginuid(t);
+ context->target_uid = t->uid;
+ context->target_sessionid = audit_get_sessionid(t);
+- selinux_get_task_sid(t, &context->target_sid);
++ security_task_getsecid(t, &context->target_sid);
+ memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
+ }
+
+@@ -2371,7 +2372,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
+ audit_sig_uid = tsk->loginuid;
+ else
+ audit_sig_uid = tsk->uid;
+- selinux_get_task_sid(tsk, &audit_sig_sid);
++ security_task_getsecid(tsk, &audit_sig_sid);
+ }
+ if (!audit_signals || audit_dummy_context())
+ return 0;
+@@ -2384,7 +2385,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
+ ctx->target_auid = audit_get_loginuid(t);
+ ctx->target_uid = t->uid;
+ ctx->target_sessionid = audit_get_sessionid(t);
+- selinux_get_task_sid(t, &ctx->target_sid);
++ security_task_getsecid(t, &ctx->target_sid);
+ memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
+ return 0;
+ }
+@@ -2405,7 +2406,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
+ axp->target_auid[axp->pid_count] = audit_get_loginuid(t);
+ axp->target_uid[axp->pid_count] = t->uid;
+ axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
+- selinux_get_task_sid(t, &axp->target_sid[axp->pid_count]);
++ security_task_getsecid(t, &axp->target_sid[axp->pid_count]);
+ memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
+ axp->pid_count++;
+
+@@ -2435,16 +2436,17 @@ void audit_core_dumps(long signr)
+ ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
+ audit_log_format(ab, "auid=%u uid=%u gid=%u ses=%u",
+ auid, current->uid, current->gid, sessionid);
+- selinux_get_task_sid(current, &sid);
++ security_task_getsecid(current, &sid);
+ if (sid) {
+ char *ctx = NULL;
+ u32 len;
+
+- if (selinux_sid_to_string(sid, &ctx, &len))
++ if (security_secid_to_secctx(sid, &ctx, &len))
+ audit_log_format(ab, " ssid=%u", sid);
+- else
++ else {
+ audit_log_format(ab, " subj=%s", ctx);
+- kfree(ctx);
++ security_release_secctx(ctx, len);
++ }
+ }
+ audit_log_format(ab, " pid=%d comm=", current->pid);
+ audit_log_untrustedstring(ab, current->comm);
+diff --git a/kernel/cgroup.c b/kernel/cgroup.c
+index 2727f92..6d8de05 100644
+--- a/kernel/cgroup.c
++++ b/kernel/cgroup.c
+@@ -1722,7 +1722,12 @@ void cgroup_enable_task_cg_lists(void)
+ use_task_css_set_links = 1;
+ do_each_thread(g, p) {
+ task_lock(p);
+- if (list_empty(&p->cg_list))
++ /*
++ * We should check if the process is exiting, otherwise
++ * it will race with cgroup_exit() in that the list
++ * entry won't be deleted though the process has exited.
++ */
++ if (!(p->flags & PF_EXITING) && list_empty(&p->cg_list))
+ list_add(&p->cg_list, &p->cgroups->tasks);
+ task_unlock(p);
+ } while_each_thread(g, p);
+diff --git a/kernel/compat.c b/kernel/compat.c
+index 5f0e201..e1ef048 100644
+--- a/kernel/compat.c
++++ b/kernel/compat.c
+@@ -47,15 +47,14 @@ static long compat_nanosleep_restart(struct restart_block *restart)
+ mm_segment_t oldfs;
+ long ret;
+
+- rmtp = (struct compat_timespec __user *)(restart->arg1);
+- restart->arg1 = (unsigned long)&rmt;
++ restart->nanosleep.rmtp = (struct timespec __user *) &rmt;
+ oldfs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = hrtimer_nanosleep_restart(restart);
+ set_fs(oldfs);
+
+ if (ret) {
+- restart->arg1 = (unsigned long)rmtp;
++ rmtp = restart->nanosleep.compat_rmtp;
+
+ if (rmtp && put_compat_timespec(&rmt, rmtp))
+ return -EFAULT;
+@@ -89,7 +88,7 @@ asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp,
+ = ¤t_thread_info()->restart_block;
+
+ restart->fn = compat_nanosleep_restart;
+- restart->arg1 = (unsigned long)rmtp;
++ restart->nanosleep.compat_rmtp = rmtp;
+
+ if (rmtp && put_compat_timespec(&rmt, rmtp))
+ return -EFAULT;
+@@ -446,7 +445,7 @@ asmlinkage long compat_sys_sched_setaffinity(compat_pid_t pid,
+ if (retval)
+ return retval;
+
+- return sched_setaffinity(pid, new_mask);
++ return sched_setaffinity(pid, &new_mask);
+ }
+
+ asmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid, unsigned int len,
+@@ -607,9 +606,9 @@ static long compat_clock_nanosleep_restart(struct restart_block *restart)
+ long err;
+ mm_segment_t oldfs;
+ struct timespec tu;
+- struct compat_timespec *rmtp = (struct compat_timespec *)(restart->arg1);
++ struct compat_timespec *rmtp = restart->nanosleep.compat_rmtp;
+
+- restart->arg1 = (unsigned long) &tu;
++ restart->nanosleep.rmtp = (struct timespec __user *) &tu;
+ oldfs = get_fs();
+ set_fs(KERNEL_DS);
+ err = clock_nanosleep_restart(restart);
+@@ -621,7 +620,7 @@ static long compat_clock_nanosleep_restart(struct restart_block *restart)
+
+ if (err == -ERESTART_RESTARTBLOCK) {
+ restart->fn = compat_clock_nanosleep_restart;
+- restart->arg1 = (unsigned long) rmtp;
++ restart->nanosleep.compat_rmtp = rmtp;
+ }
+ return err;
+ }
+@@ -652,7 +651,7 @@ long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,
+ if (err == -ERESTART_RESTARTBLOCK) {
+ restart = ¤t_thread_info()->restart_block;
+ restart->fn = compat_clock_nanosleep_restart;
+- restart->arg1 = (unsigned long) rmtp;
++ restart->nanosleep.compat_rmtp = rmtp;
+ }
+ return err;
+ }
+diff --git a/kernel/cpu.c b/kernel/cpu.c
+index 2eff3f6..2011ad8 100644
+--- a/kernel/cpu.c
++++ b/kernel/cpu.c
+@@ -232,9 +232,9 @@ static int _cpu_down(unsigned int cpu, int tasks_frozen)
+
+ /* Ensure that we are not runnable on dying cpu */
+ old_allowed = current->cpus_allowed;
+- tmp = CPU_MASK_ALL;
++ cpus_setall(tmp);
+ cpu_clear(cpu, tmp);
+- set_cpus_allowed(current, tmp);
++ set_cpus_allowed_ptr(current, &tmp);
+
+ p = __stop_machine_run(take_cpu_down, &tcd_param, cpu);
+
+@@ -268,7 +268,7 @@ static int _cpu_down(unsigned int cpu, int tasks_frozen)
+ out_thread:
+ err = kthread_stop(p);
+ out_allowed:
+- set_cpus_allowed(current, old_allowed);
++ set_cpus_allowed_ptr(current, &old_allowed);
+ out_release:
+ cpu_hotplug_done();
+ return err;
+diff --git a/kernel/cpuset.c b/kernel/cpuset.c
+index a1b61f4..8b35fbd 100644
+--- a/kernel/cpuset.c
++++ b/kernel/cpuset.c
+@@ -98,6 +98,9 @@ struct cpuset {
+ /* partition number for rebuild_sched_domains() */
+ int pn;
+
++ /* for custom sched domain */
++ int relax_domain_level;
++
+ /* used for walking a cpuset heirarchy */
+ struct list_head stack_list;
+ };
+@@ -478,6 +481,16 @@ static int cpusets_overlap(struct cpuset *a, struct cpuset *b)
+ return cpus_intersects(a->cpus_allowed, b->cpus_allowed);
+ }
+
++static void
++update_domain_attr(struct sched_domain_attr *dattr, struct cpuset *c)
++{
++ if (!dattr)
++ return;
++ if (dattr->relax_domain_level < c->relax_domain_level)
++ dattr->relax_domain_level = c->relax_domain_level;
++ return;
++}
++
+ /*
+ * rebuild_sched_domains()
+ *
+@@ -553,12 +566,14 @@ static void rebuild_sched_domains(void)
+ int csn; /* how many cpuset ptrs in csa so far */
+ int i, j, k; /* indices for partition finding loops */
+ cpumask_t *doms; /* resulting partition; i.e. sched domains */
++ struct sched_domain_attr *dattr; /* attributes for custom domains */
+ int ndoms; /* number of sched domains in result */
+ int nslot; /* next empty doms[] cpumask_t slot */
+
+ q = NULL;
+ csa = NULL;
+ doms = NULL;
++ dattr = NULL;
+
+ /* Special case for the 99% of systems with one, full, sched domain */
+ if (is_sched_load_balance(&top_cpuset)) {
+@@ -566,6 +581,11 @@ static void rebuild_sched_domains(void)
+ doms = kmalloc(sizeof(cpumask_t), GFP_KERNEL);
+ if (!doms)
+ goto rebuild;
++ dattr = kmalloc(sizeof(struct sched_domain_attr), GFP_KERNEL);
++ if (dattr) {
++ *dattr = SD_ATTR_INIT;
++ update_domain_attr(dattr, &top_cpuset);
++ }
+ *doms = top_cpuset.cpus_allowed;
+ goto rebuild;
+ }
+@@ -622,6 +642,7 @@ restart:
+ doms = kmalloc(ndoms * sizeof(cpumask_t), GFP_KERNEL);
+ if (!doms)
+ goto rebuild;
++ dattr = kmalloc(ndoms * sizeof(struct sched_domain_attr), GFP_KERNEL);
+
+ for (nslot = 0, i = 0; i < csn; i++) {
+ struct cpuset *a = csa[i];
+@@ -644,12 +665,15 @@ restart:
+ }
+
+ cpus_clear(*dp);
++ if (dattr)
++ *(dattr + nslot) = SD_ATTR_INIT;
+ for (j = i; j < csn; j++) {
+ struct cpuset *b = csa[j];
+
+ if (apn == b->pn) {
+ cpus_or(*dp, *dp, b->cpus_allowed);
+ b->pn = -1;
++ update_domain_attr(dattr, b);
+ }
+ }
+ nslot++;
+@@ -660,7 +684,7 @@ restart:
+ rebuild:
+ /* Have scheduler rebuild sched domains */
+ get_online_cpus();
+- partition_sched_domains(ndoms, doms);
++ partition_sched_domains(ndoms, doms, dattr);
+ put_online_cpus();
+
+ done:
+@@ -668,6 +692,7 @@ done:
+ kfifo_free(q);
+ kfree(csa);
+ /* Don't kfree(doms) -- partition_sched_domains() does that. */
++ /* Don't kfree(dattr) -- partition_sched_domains() does that. */
+ }
+
+ static inline int started_after_time(struct task_struct *t1,
+@@ -729,7 +754,7 @@ int cpuset_test_cpumask(struct task_struct *tsk, struct cgroup_scanner *scan)
+ */
+ void cpuset_change_cpumask(struct task_struct *tsk, struct cgroup_scanner *scan)
+ {
+- set_cpus_allowed(tsk, (cgroup_cs(scan->cg))->cpus_allowed);
++ set_cpus_allowed_ptr(tsk, &((cgroup_cs(scan->cg))->cpus_allowed));
+ }
+
+ /**
+@@ -1011,6 +1036,21 @@ static int update_memory_pressure_enabled(struct cpuset *cs, char *buf)
+ return 0;
+ }
+
++static int update_relax_domain_level(struct cpuset *cs, char *buf)
++{
++ int val = simple_strtol(buf, NULL, 10);
++
++ if (val < 0)
++ val = -1;
++
++ if (val != cs->relax_domain_level) {
++ cs->relax_domain_level = val;
++ rebuild_sched_domains();
++ }
++
++ return 0;
++}
++
+ /*
+ * update_flag - read a 0 or a 1 in a file and update associated flag
+ * bit: the bit to update (CS_CPU_EXCLUSIVE, CS_MEM_EXCLUSIVE,
+@@ -1178,7 +1218,7 @@ static void cpuset_attach(struct cgroup_subsys *ss,
+
+ mutex_lock(&callback_mutex);
+ guarantee_online_cpus(cs, &cpus);
+- set_cpus_allowed(tsk, cpus);
++ set_cpus_allowed_ptr(tsk, &cpus);
+ mutex_unlock(&callback_mutex);
+
+ from = oldcs->mems_allowed;
+@@ -1202,6 +1242,7 @@ typedef enum {
+ FILE_CPU_EXCLUSIVE,
+ FILE_MEM_EXCLUSIVE,
+ FILE_SCHED_LOAD_BALANCE,
++ FILE_SCHED_RELAX_DOMAIN_LEVEL,
+ FILE_MEMORY_PRESSURE_ENABLED,
+ FILE_MEMORY_PRESSURE,
+ FILE_SPREAD_PAGE,
+@@ -1256,6 +1297,9 @@ static ssize_t cpuset_common_file_write(struct cgroup *cont,
+ case FILE_SCHED_LOAD_BALANCE:
+ retval = update_flag(CS_SCHED_LOAD_BALANCE, cs, buffer);
+ break;
++ case FILE_SCHED_RELAX_DOMAIN_LEVEL:
++ retval = update_relax_domain_level(cs, buffer);
++ break;
+ case FILE_MEMORY_MIGRATE:
+ retval = update_flag(CS_MEMORY_MIGRATE, cs, buffer);
+ break;
+@@ -1354,6 +1398,9 @@ static ssize_t cpuset_common_file_read(struct cgroup *cont,
+ case FILE_SCHED_LOAD_BALANCE:
+ *s++ = is_sched_load_balance(cs) ? '1' : '0';
+ break;
++ case FILE_SCHED_RELAX_DOMAIN_LEVEL:
++ s += sprintf(s, "%d", cs->relax_domain_level);
++ break;
+ case FILE_MEMORY_MIGRATE:
+ *s++ = is_memory_migrate(cs) ? '1' : '0';
+ break;
+@@ -1424,6 +1471,13 @@ static struct cftype cft_sched_load_balance = {
+ .private = FILE_SCHED_LOAD_BALANCE,
+ };
+
++static struct cftype cft_sched_relax_domain_level = {
++ .name = "sched_relax_domain_level",
++ .read = cpuset_common_file_read,
++ .write = cpuset_common_file_write,
++ .private = FILE_SCHED_RELAX_DOMAIN_LEVEL,
++};
++
+ static struct cftype cft_memory_migrate = {
+ .name = "memory_migrate",
+ .read = cpuset_common_file_read,
+@@ -1475,6 +1529,9 @@ static int cpuset_populate(struct cgroup_subsys *ss, struct cgroup *cont)
+ return err;
+ if ((err = cgroup_add_file(cont, ss, &cft_sched_load_balance)) < 0)
+ return err;
++ if ((err = cgroup_add_file(cont, ss,
++ &cft_sched_relax_domain_level)) < 0)
++ return err;
+ if ((err = cgroup_add_file(cont, ss, &cft_memory_pressure)) < 0)
+ return err;
+ if ((err = cgroup_add_file(cont, ss, &cft_spread_page)) < 0)
+@@ -1555,10 +1612,11 @@ static struct cgroup_subsys_state *cpuset_create(
+ if (is_spread_slab(parent))
+ set_bit(CS_SPREAD_SLAB, &cs->flags);
+ set_bit(CS_SCHED_LOAD_BALANCE, &cs->flags);
+- cs->cpus_allowed = CPU_MASK_NONE;
+- cs->mems_allowed = NODE_MASK_NONE;
++ cpus_clear(cs->cpus_allowed);
++ nodes_clear(cs->mems_allowed);
+ cs->mems_generation = cpuset_mems_generation++;
+ fmeter_init(&cs->fmeter);
++ cs->relax_domain_level = -1;
+
+ cs->parent = parent;
+ number_of_cpusets++;
+@@ -1625,12 +1683,13 @@ int __init cpuset_init(void)
+ {
+ int err = 0;
+
+- top_cpuset.cpus_allowed = CPU_MASK_ALL;
+- top_cpuset.mems_allowed = NODE_MASK_ALL;
++ cpus_setall(top_cpuset.cpus_allowed);
++ nodes_setall(top_cpuset.mems_allowed);
+
+ fmeter_init(&top_cpuset.fmeter);
+ top_cpuset.mems_generation = cpuset_mems_generation++;
+ set_bit(CS_SCHED_LOAD_BALANCE, &top_cpuset.flags);
++ top_cpuset.relax_domain_level = -1;
+
+ err = register_filesystem(&cpuset_fs_type);
+ if (err < 0)
+@@ -1844,6 +1903,7 @@ void __init cpuset_init_smp(void)
+
+ * cpuset_cpus_allowed - return cpus_allowed mask from a tasks cpuset.
+ * @tsk: pointer to task_struct from which to obtain cpuset->cpus_allowed.
++ * @pmask: pointer to cpumask_t variable to receive cpus_allowed set.
+ *
+ * Description: Returns the cpumask_t cpus_allowed of the cpuset
+ * attached to the specified @tsk. Guaranteed to return some non-empty
+@@ -1851,35 +1911,27 @@ void __init cpuset_init_smp(void)
+ * tasks cpuset.
+ **/
+
+-cpumask_t cpuset_cpus_allowed(struct task_struct *tsk)
++void cpuset_cpus_allowed(struct task_struct *tsk, cpumask_t *pmask)
+ {
+- cpumask_t mask;
+-
+ mutex_lock(&callback_mutex);
+- mask = cpuset_cpus_allowed_locked(tsk);
++ cpuset_cpus_allowed_locked(tsk, pmask);
+ mutex_unlock(&callback_mutex);
+-
+- return mask;
+ }
+
+ /**
+ * cpuset_cpus_allowed_locked - return cpus_allowed mask from a tasks cpuset.
+ * Must be called with callback_mutex held.
+ **/
+-cpumask_t cpuset_cpus_allowed_locked(struct task_struct *tsk)
++void cpuset_cpus_allowed_locked(struct task_struct *tsk, cpumask_t *pmask)
+ {
+- cpumask_t mask;
+-
+ task_lock(tsk);
+- guarantee_online_cpus(task_cs(tsk), &mask);
++ guarantee_online_cpus(task_cs(tsk), pmask);
+ task_unlock(tsk);
+-
+- return mask;
+ }
+
+ void cpuset_init_current_mems_allowed(void)
+ {
+- current->mems_allowed = NODE_MASK_ALL;
++ nodes_setall(current->mems_allowed);
+ }
+
+ /**
+@@ -2261,8 +2313,16 @@ void cpuset_task_status_allowed(struct seq_file *m, struct task_struct *task)
+ m->count += cpumask_scnprintf(m->buf + m->count, m->size - m->count,
+ task->cpus_allowed);
+ seq_printf(m, "\n");
++ seq_printf(m, "Cpus_allowed_list:\t");
++ m->count += cpulist_scnprintf(m->buf + m->count, m->size - m->count,
++ task->cpus_allowed);
++ seq_printf(m, "\n");
+ seq_printf(m, "Mems_allowed:\t");
+ m->count += nodemask_scnprintf(m->buf + m->count, m->size - m->count,
+ task->mems_allowed);
+ seq_printf(m, "\n");
++ seq_printf(m, "Mems_allowed_list:\t");
++ m->count += nodelist_scnprintf(m->buf + m->count, m->size - m->count,
++ task->mems_allowed);
++ seq_printf(m, "\n");
+ }
+diff --git a/kernel/exit.c b/kernel/exit.c
+index 073005b..97f609f 100644
+--- a/kernel/exit.c
++++ b/kernel/exit.c
+@@ -507,10 +507,9 @@ void put_files_struct(struct files_struct *files)
+ }
+ }
+
+-EXPORT_SYMBOL(put_files_struct);
+-
+-void reset_files_struct(struct task_struct *tsk, struct files_struct *files)
++void reset_files_struct(struct files_struct *files)
+ {
++ struct task_struct *tsk = current;
+ struct files_struct *old;
+
+ old = tsk->files;
+@@ -519,9 +518,8 @@ void reset_files_struct(struct task_struct *tsk, struct files_struct *files)
+ task_unlock(tsk);
+ put_files_struct(old);
+ }
+-EXPORT_SYMBOL(reset_files_struct);
+
+-static void __exit_files(struct task_struct *tsk)
++void exit_files(struct task_struct *tsk)
+ {
+ struct files_struct * files = tsk->files;
+
+@@ -533,12 +531,7 @@ static void __exit_files(struct task_struct *tsk)
+ }
+ }
+
+-void exit_files(struct task_struct *tsk)
+-{
+- __exit_files(tsk);
+-}
+-
+-static void __put_fs_struct(struct fs_struct *fs)
++void put_fs_struct(struct fs_struct *fs)
+ {
+ /* No need to hold fs->lock if we are killing it */
+ if (atomic_dec_and_test(&fs->count)) {
+@@ -550,12 +543,7 @@ static void __put_fs_struct(struct fs_struct *fs)
+ }
+ }
+
+-void put_fs_struct(struct fs_struct *fs)
+-{
+- __put_fs_struct(fs);
+-}
+-
+-static void __exit_fs(struct task_struct *tsk)
++void exit_fs(struct task_struct *tsk)
+ {
+ struct fs_struct * fs = tsk->fs;
+
+@@ -563,15 +551,10 @@ static void __exit_fs(struct task_struct *tsk)
+ task_lock(tsk);
+ tsk->fs = NULL;
+ task_unlock(tsk);
+- __put_fs_struct(fs);
++ put_fs_struct(fs);
+ }
+ }
+
+-void exit_fs(struct task_struct *tsk)
+-{
+- __exit_fs(tsk);
+-}
+-
+ EXPORT_SYMBOL_GPL(exit_fs);
+
+ /*
+@@ -967,8 +950,8 @@ NORET_TYPE void do_exit(long code)
+ if (group_dead)
+ acct_process();
+ exit_sem(tsk);
+- __exit_files(tsk);
+- __exit_fs(tsk);
++ exit_files(tsk);
++ exit_fs(tsk);
+ check_stack_usage();
+ exit_thread();
+ cgroup_exit(tsk, 1);
+diff --git a/kernel/fork.c b/kernel/fork.c
+index 9c042f9..cb46bef 100644
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -132,6 +132,14 @@ void __put_task_struct(struct task_struct *tsk)
+ free_task(tsk);
+ }
+
++/*
++ * macro override instead of weak attribute alias, to workaround
++ * gcc 4.1.0 and 4.1.1 bugs with weak attribute and empty functions.
++ */
++#ifndef arch_task_cache_init
++#define arch_task_cache_init()
++#endif
++
+ void __init fork_init(unsigned long mempages)
+ {
+ #ifndef __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
+@@ -144,6 +152,9 @@ void __init fork_init(unsigned long mempages)
+ ARCH_MIN_TASKALIGN, SLAB_PANIC, NULL);
+ #endif
+
++ /* do the arch specific task caches init */
++ arch_task_cache_init();
++
+ /*
+ * The default maximum number of threads is set to a safe
+ * value: the thread structures can take up at most half
+@@ -163,6 +174,13 @@ void __init fork_init(unsigned long mempages)
+ init_task.signal->rlim[RLIMIT_NPROC];
+ }
+
++int __attribute__((weak)) arch_dup_task_struct(struct task_struct *dst,
++ struct task_struct *src)
++{
++ *dst = *src;
++ return 0;
++}
++
+ static struct task_struct *dup_task_struct(struct task_struct *orig)
+ {
+ struct task_struct *tsk;
+@@ -181,15 +199,15 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
+ return NULL;
+ }
+
+- *tsk = *orig;
++ err = arch_dup_task_struct(tsk, orig);
++ if (err)
++ goto out;
++
+ tsk->stack = ti;
+
+ err = prop_local_init_single(&tsk->dirties);
+- if (err) {
+- free_thread_info(ti);
+- free_task_struct(tsk);
+- return NULL;
+- }
++ if (err)
++ goto out;
+
+ setup_thread_stack(tsk, orig);
+
+@@ -205,6 +223,11 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
+ #endif
+ tsk->splice_pipe = NULL;
+ return tsk;
++
++out:
++ free_thread_info(ti);
++ free_task_struct(tsk);
++ return NULL;
+ }
+
+ #ifdef CONFIG_MMU
+@@ -782,12 +805,6 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
+ goto out;
+ }
+
+- /*
+- * Note: we may be using current for both targets (See exec.c)
+- * This works because we cache current->files (old) as oldf. Don't
+- * break this.
+- */
+- tsk->files = NULL;
+ newf = dup_fd(oldf, &error);
+ if (!newf)
+ goto out;
+@@ -823,34 +840,6 @@ static int copy_io(unsigned long clone_flags, struct task_struct *tsk)
+ return 0;
+ }
+
+-/*
+- * Helper to unshare the files of the current task.
+- * We don't want to expose copy_files internals to
+- * the exec layer of the kernel.
+- */
+-
+-int unshare_files(void)
+-{
+- struct files_struct *files = current->files;
+- int rc;
+-
+- BUG_ON(!files);
+-
+- /* This can race but the race causes us to copy when we don't
+- need to and drop the copy */
+- if(atomic_read(&files->count) == 1)
+- {
+- atomic_inc(&files->count);
+- return 0;
+- }
+- rc = copy_files(0, current);
+- if(rc)
+- current->files = files;
+- return rc;
+-}
+-
+-EXPORT_SYMBOL(unshare_files);
+-
+ static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk)
+ {
+ struct sighand_struct *sig;
+@@ -1788,3 +1777,27 @@ bad_unshare_cleanup_thread:
+ bad_unshare_out:
+ return err;
+ }
++
++/*
++ * Helper to unshare the files of the current task.
++ * We don't want to expose copy_files internals to
++ * the exec layer of the kernel.
++ */
++
++int unshare_files(struct files_struct **displaced)
++{
++ struct task_struct *task = current;
++ struct files_struct *copy = NULL;
++ int error;
++
++ error = unshare_fd(CLONE_FILES, ©);
++ if (error || !copy) {
++ *displaced = NULL;
++ return error;
++ }
++ *displaced = task->files;
++ task_lock(task);
++ task->files = copy;
++ task_unlock(task);
++ return 0;
++}
+diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
+index 98bee01..f78777a 100644
+--- a/kernel/hrtimer.c
++++ b/kernel/hrtimer.c
+@@ -1238,51 +1238,50 @@ void hrtimer_run_pending(void)
+ /*
+ * Called from hardirq context every jiffy
+ */
+-static inline void run_hrtimer_queue(struct hrtimer_cpu_base *cpu_base,
+- int index)
++void hrtimer_run_queues(void)
+ {
+ struct rb_node *node;
+- struct hrtimer_clock_base *base = &cpu_base->clock_base[index];
++ struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
++ struct hrtimer_clock_base *base;
++ int index, gettime = 1;
+
+- if (!base->first)
++ if (hrtimer_hres_active())
+ return;
+
+- if (base->get_softirq_time)
+- base->softirq_time = base->get_softirq_time();
+-
+- spin_lock(&cpu_base->lock);
++ for (index = 0; index < HRTIMER_MAX_CLOCK_BASES; index++) {
++ base = &cpu_base->clock_base[index];
+
+- while ((node = base->first)) {
+- struct hrtimer *timer;
+-
+- timer = rb_entry(node, struct hrtimer, node);
+- if (base->softirq_time.tv64 <= timer->expires.tv64)
+- break;
+-
+- if (timer->cb_mode == HRTIMER_CB_SOFTIRQ) {
+- __remove_hrtimer(timer, base, HRTIMER_STATE_PENDING, 0);
+- list_add_tail(&timer->cb_entry,
+- &base->cpu_base->cb_pending);
++ if (!base->first)
+ continue;
++
++ if (base->get_softirq_time)
++ base->softirq_time = base->get_softirq_time();
++ else if (gettime) {
++ hrtimer_get_softirq_time(cpu_base);
++ gettime = 0;
+ }
+
+- __run_hrtimer(timer);
+- }
+- spin_unlock(&cpu_base->lock);
+-}
++ spin_lock(&cpu_base->lock);
+
+-void hrtimer_run_queues(void)
+-{
+- struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
+- int i;
++ while ((node = base->first)) {
++ struct hrtimer *timer;
+
+- if (hrtimer_hres_active())
+- return;
++ timer = rb_entry(node, struct hrtimer, node);
++ if (base->softirq_time.tv64 <= timer->expires.tv64)
++ break;
+
+- hrtimer_get_softirq_time(cpu_base);
++ if (timer->cb_mode == HRTIMER_CB_SOFTIRQ) {
++ __remove_hrtimer(timer, base,
++ HRTIMER_STATE_PENDING, 0);
++ list_add_tail(&timer->cb_entry,
++ &base->cpu_base->cb_pending);
++ continue;
++ }
+
+- for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++)
+- run_hrtimer_queue(cpu_base, i);
++ __run_hrtimer(timer);
++ }
++ spin_unlock(&cpu_base->lock);
++ }
+ }
+
+ /*
+@@ -1354,13 +1353,13 @@ long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
+ struct hrtimer_sleeper t;
+ struct timespec __user *rmtp;
+
+- hrtimer_init(&t.timer, restart->arg0, HRTIMER_MODE_ABS);
+- t.timer.expires.tv64 = ((u64)restart->arg3 << 32) | (u64) restart->arg2;
++ hrtimer_init(&t.timer, restart->nanosleep.index, HRTIMER_MODE_ABS);
++ t.timer.expires.tv64 = restart->nanosleep.expires;
+
+ if (do_nanosleep(&t, HRTIMER_MODE_ABS))
+ return 0;
+
+- rmtp = (struct timespec __user *)restart->arg1;
++ rmtp = restart->nanosleep.rmtp;
+ if (rmtp) {
+ int ret = update_rmtp(&t.timer, rmtp);
+ if (ret <= 0)
+@@ -1394,10 +1393,9 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
+
+ restart = ¤t_thread_info()->restart_block;
+ restart->fn = hrtimer_nanosleep_restart;
+- restart->arg0 = (unsigned long) t.timer.base->index;
+- restart->arg1 = (unsigned long) rmtp;
+- restart->arg2 = t.timer.expires.tv64 & 0xFFFFFFFF;
+- restart->arg3 = t.timer.expires.tv64 >> 32;
++ restart->nanosleep.index = t.timer.base->index;
++ restart->nanosleep.rmtp = rmtp;
++ restart->nanosleep.expires = t.timer.expires.tv64;
+
+ return -ERESTART_RESTARTBLOCK;
+ }
+@@ -1425,7 +1423,6 @@ static void __cpuinit init_hrtimers_cpu(int cpu)
+ int i;
+
+ spin_lock_init(&cpu_base->lock);
+- lockdep_set_class(&cpu_base->lock, &cpu_base->lock_key);
+
+ for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++)
+ cpu_base->clock_base[i].cpu_base = cpu_base;
+@@ -1466,16 +1463,16 @@ static void migrate_hrtimers(int cpu)
+ tick_cancel_sched_timer(cpu);
+
+ local_irq_disable();
+- double_spin_lock(&new_base->lock, &old_base->lock,
+- smp_processor_id() < cpu);
++ spin_lock(&new_base->lock);
++ spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING);
+
+ for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
+ migrate_hrtimer_list(&old_base->clock_base[i],
+ &new_base->clock_base[i]);
+ }
+
+- double_spin_unlock(&new_base->lock, &old_base->lock,
+- smp_processor_id() < cpu);
++ spin_unlock(&old_base->lock);
++ spin_unlock(&new_base->lock);
+ local_irq_enable();
+ put_cpu_var(hrtimer_bases);
+ }
+diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
+index fdb3fbe..964964b 100644
+--- a/kernel/irq/chip.c
++++ b/kernel/irq/chip.c
+@@ -47,7 +47,7 @@ void dynamic_irq_init(unsigned int irq)
+ desc->irq_count = 0;
+ desc->irqs_unhandled = 0;
+ #ifdef CONFIG_SMP
+- desc->affinity = CPU_MASK_ALL;
++ cpus_setall(desc->affinity);
+ #endif
+ spin_unlock_irqrestore(&desc->lock, flags);
+ }
+diff --git a/kernel/kexec.c b/kernel/kexec.c
+index 06a0e27..6782dce 100644
+--- a/kernel/kexec.c
++++ b/kernel/kexec.c
+@@ -29,7 +29,6 @@
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
+ #include <asm/system.h>
+-#include <asm/semaphore.h>
+ #include <asm/sections.h>
+
+ /* Per cpu memory for storing cpu states in case of system crash. */
+diff --git a/kernel/kgdb.c b/kernel/kgdb.c
+new file mode 100644
+index 0000000..1bd0ec1
+--- /dev/null
++++ b/kernel/kgdb.c
+@@ -0,0 +1,1700 @@
++/*
++ * KGDB stub.
++ *
++ * Maintainer: Jason Wessel <jason.wessel at windriver.com>
++ *
++ * Copyright (C) 2000-2001 VERITAS Software Corporation.
++ * Copyright (C) 2002-2004 Timesys Corporation
++ * Copyright (C) 2003-2004 Amit S. Kale <amitkale at linsyssoft.com>
++ * Copyright (C) 2004 Pavel Machek <pavel at suse.cz>
++ * Copyright (C) 2004-2006 Tom Rini <trini at kernel.crashing.org>
++ * Copyright (C) 2004-2006 LinSysSoft Technologies Pvt. Ltd.
++ * Copyright (C) 2005-2008 Wind River Systems, Inc.
++ * Copyright (C) 2007 MontaVista Software, Inc.
++ * Copyright (C) 2008 Red Hat, Inc., Ingo Molnar <mingo at redhat.com>
++ *
++ * Contributors at various stages not listed above:
++ * Jason Wessel ( jason.wessel at windriver.com )
++ * George Anzinger <george at mvista.com>
++ * Anurekh Saxena (anurekh.saxena at timesys.com)
++ * Lake Stevens Instrument Division (Glenn Engel)
++ * Jim Kingdon, Cygnus Support.
++ *
++ * Original KGDB stub: David Grothe <dave at gcom.com>,
++ * Tigran Aivazian <tigran at sco.com>
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++#include <linux/pid_namespace.h>
++#include <linux/clocksource.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++#include <linux/console.h>
++#include <linux/threads.h>
++#include <linux/uaccess.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/ptrace.h>
++#include <linux/reboot.h>
++#include <linux/string.h>
++#include <linux/delay.h>
++#include <linux/sched.h>
++#include <linux/sysrq.h>
++#include <linux/init.h>
++#include <linux/kgdb.h>
++#include <linux/pid.h>
++#include <linux/smp.h>
++#include <linux/mm.h>
++
++#include <asm/cacheflush.h>
++#include <asm/byteorder.h>
++#include <asm/atomic.h>
++#include <asm/system.h>
++
++static int kgdb_break_asap;
++
++struct kgdb_state {
++ int ex_vector;
++ int signo;
++ int err_code;
++ int cpu;
++ int pass_exception;
++ long threadid;
++ long kgdb_usethreadid;
++ struct pt_regs *linux_regs;
++};
++
++static struct debuggerinfo_struct {
++ void *debuggerinfo;
++ struct task_struct *task;
++} kgdb_info[NR_CPUS];
++
++/**
++ * kgdb_connected - Is a host GDB connected to us?
++ */
++int kgdb_connected;
++EXPORT_SYMBOL_GPL(kgdb_connected);
++
++/* All the KGDB handlers are installed */
++static int kgdb_io_module_registered;
++
++/* Guard for recursive entry */
++static int exception_level;
++
++static struct kgdb_io *kgdb_io_ops;
++static DEFINE_SPINLOCK(kgdb_registration_lock);
++
++/* kgdb console driver is loaded */
++static int kgdb_con_registered;
++/* determine if kgdb console output should be used */
++static int kgdb_use_con;
++
++static int __init opt_kgdb_con(char *str)
++{
++ kgdb_use_con = 1;
++ return 0;
++}
++
++early_param("kgdbcon", opt_kgdb_con);
++
++module_param(kgdb_use_con, int, 0644);
++
++/*
++ * Holds information about breakpoints in a kernel. These breakpoints are
++ * added and removed by gdb.
++ */
++static struct kgdb_bkpt kgdb_break[KGDB_MAX_BREAKPOINTS] = {
++ [0 ... KGDB_MAX_BREAKPOINTS-1] = { .state = BP_UNDEFINED }
++};
++
++/*
++ * The CPU# of the active CPU, or -1 if none:
++ */
++atomic_t kgdb_active = ATOMIC_INIT(-1);
++
++/*
++ * We use NR_CPUs not PERCPU, in case kgdb is used to debug early
++ * bootup code (which might not have percpu set up yet):
++ */
++static atomic_t passive_cpu_wait[NR_CPUS];
++static atomic_t cpu_in_kgdb[NR_CPUS];
++atomic_t kgdb_setting_breakpoint;
++
++struct task_struct *kgdb_usethread;
++struct task_struct *kgdb_contthread;
++
++int kgdb_single_step;
++
++/* Our I/O buffers. */
++static char remcom_in_buffer[BUFMAX];
++static char remcom_out_buffer[BUFMAX];
++
++/* Storage for the registers, in GDB format. */
++static unsigned long gdb_regs[(NUMREGBYTES +
++ sizeof(unsigned long) - 1) /
++ sizeof(unsigned long)];
++
++/* to keep track of the CPU which is doing the single stepping*/
++atomic_t kgdb_cpu_doing_single_step = ATOMIC_INIT(-1);
++
++/*
++ * If you are debugging a problem where roundup (the collection of
++ * all other CPUs) is a problem [this should be extremely rare],
++ * then use the nokgdbroundup option to avoid roundup. In that case
++ * the other CPUs might interfere with your debugging context, so
++ * use this with care:
++ */
++int kgdb_do_roundup = 1;
++
++static int __init opt_nokgdbroundup(char *str)
++{
++ kgdb_do_roundup = 0;
++
++ return 0;
++}
++
++early_param("nokgdbroundup", opt_nokgdbroundup);
++
++/*
++ * Finally, some KGDB code :-)
++ */
++
++/*
++ * Weak aliases for breakpoint management,
++ * can be overriden by architectures when needed:
++ */
++int __weak kgdb_validate_break_address(unsigned long addr)
++{
++ char tmp_variable[BREAK_INSTR_SIZE];
++
++ return probe_kernel_read(tmp_variable, (char *)addr, BREAK_INSTR_SIZE);
++}
++
++int __weak kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr)
++{
++ int err;
++
++ err = probe_kernel_read(saved_instr, (char *)addr, BREAK_INSTR_SIZE);
++ if (err)
++ return err;
++
++ return probe_kernel_write((char *)addr, arch_kgdb_ops.gdb_bpt_instr,
++ BREAK_INSTR_SIZE);
++}
++
++int __weak kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle)
++{
++ return probe_kernel_write((char *)addr,
++ (char *)bundle, BREAK_INSTR_SIZE);
++}
++
++unsigned long __weak kgdb_arch_pc(int exception, struct pt_regs *regs)
++{
++ return instruction_pointer(regs);
++}
++
++int __weak kgdb_arch_init(void)
++{
++ return 0;
++}
++
++int __weak kgdb_skipexception(int exception, struct pt_regs *regs)
++{
++ return 0;
++}
++
++void __weak
++kgdb_post_primary_code(struct pt_regs *regs, int e_vector, int err_code)
++{
++ return;
++}
++
++/**
++ * kgdb_disable_hw_debug - Disable hardware debugging while we in kgdb.
++ * @regs: Current &struct pt_regs.
++ *
++ * This function will be called if the particular architecture must
++ * disable hardware debugging while it is processing gdb packets or
++ * handling exception.
++ */
++void __weak kgdb_disable_hw_debug(struct pt_regs *regs)
++{
++}
++
++/*
++ * GDB remote protocol parser:
++ */
++
++static const char hexchars[] = "0123456789abcdef";
++
++static int hex(char ch)
++{
++ if ((ch >= 'a') && (ch <= 'f'))
++ return ch - 'a' + 10;
++ if ((ch >= '0') && (ch <= '9'))
++ return ch - '0';
++ if ((ch >= 'A') && (ch <= 'F'))
++ return ch - 'A' + 10;
++ return -1;
++}
++
++/* scan for the sequence $<data>#<checksum> */
++static void get_packet(char *buffer)
++{
++ unsigned char checksum;
++ unsigned char xmitcsum;
++ int count;
++ char ch;
++
++ do {
++ /*
++ * Spin and wait around for the start character, ignore all
++ * other characters:
++ */
++ while ((ch = (kgdb_io_ops->read_char())) != '$')
++ /* nothing */;
++
++ kgdb_connected = 1;
++ checksum = 0;
++ xmitcsum = -1;
++
++ count = 0;
++
++ /*
++ * now, read until a # or end of buffer is found:
++ */
++ while (count < (BUFMAX - 1)) {
++ ch = kgdb_io_ops->read_char();
++ if (ch == '#')
++ break;
++ checksum = checksum + ch;
++ buffer[count] = ch;
++ count = count + 1;
++ }
++ buffer[count] = 0;
++
++ if (ch == '#') {
++ xmitcsum = hex(kgdb_io_ops->read_char()) << 4;
++ xmitcsum += hex(kgdb_io_ops->read_char());
++
++ if (checksum != xmitcsum)
++ /* failed checksum */
++ kgdb_io_ops->write_char('-');
++ else
++ /* successful transfer */
++ kgdb_io_ops->write_char('+');
++ if (kgdb_io_ops->flush)
++ kgdb_io_ops->flush();
++ }
++ } while (checksum != xmitcsum);
++}
++
++/*
++ * Send the packet in buffer.
++ * Check for gdb connection if asked for.
++ */
++static void put_packet(char *buffer)
++{
++ unsigned char checksum;
++ int count;
++ char ch;
++
++ /*
++ * $<packet info>#<checksum>.
++ */
++ while (1) {
++ kgdb_io_ops->write_char('$');
++ checksum = 0;
++ count = 0;
++
++ while ((ch = buffer[count])) {
++ kgdb_io_ops->write_char(ch);
++ checksum += ch;
++ count++;
++ }
++
++ kgdb_io_ops->write_char('#');
++ kgdb_io_ops->write_char(hexchars[checksum >> 4]);
++ kgdb_io_ops->write_char(hexchars[checksum & 0xf]);
++ if (kgdb_io_ops->flush)
++ kgdb_io_ops->flush();
++
++ /* Now see what we get in reply. */
++ ch = kgdb_io_ops->read_char();
++
++ if (ch == 3)
++ ch = kgdb_io_ops->read_char();
++
++ /* If we get an ACK, we are done. */
++ if (ch == '+')
++ return;
++
++ /*
++ * If we get the start of another packet, this means
++ * that GDB is attempting to reconnect. We will NAK
++ * the packet being sent, and stop trying to send this
++ * packet.
++ */
++ if (ch == '$') {
++ kgdb_io_ops->write_char('-');
++ if (kgdb_io_ops->flush)
++ kgdb_io_ops->flush();
++ return;
++ }
++ }
++}
++
++static char *pack_hex_byte(char *pkt, u8 byte)
++{
++ *pkt++ = hexchars[byte >> 4];
++ *pkt++ = hexchars[byte & 0xf];
++
++ return pkt;
++}
++
++/*
++ * Convert the memory pointed to by mem into hex, placing result in buf.
++ * Return a pointer to the last char put in buf (null). May return an error.
++ */
++int kgdb_mem2hex(char *mem, char *buf, int count)
++{
++ char *tmp;
++ int err;
++
++ /*
++ * We use the upper half of buf as an intermediate buffer for the
++ * raw memory copy. Hex conversion will work against this one.
++ */
++ tmp = buf + count;
++
++ err = probe_kernel_read(tmp, mem, count);
++ if (!err) {
++ while (count > 0) {
++ buf = pack_hex_byte(buf, *tmp);
++ tmp++;
++ count--;
++ }
++
++ *buf = 0;
++ }
++
++ return err;
++}
++
++/*
++ * Copy the binary array pointed to by buf into mem. Fix $, #, and
++ * 0x7d escaped with 0x7d. Return a pointer to the character after
++ * the last byte written.
++ */
++static int kgdb_ebin2mem(char *buf, char *mem, int count)
++{
++ int err = 0;
++ char c;
++
++ while (count-- > 0) {
++ c = *buf++;
++ if (c == 0x7d)
++ c = *buf++ ^ 0x20;
++
++ err = probe_kernel_write(mem, &c, 1);
++ if (err)
++ break;
++
++ mem++;
++ }
++
++ return err;
++}
++
++/*
++ * Convert the hex array pointed to by buf into binary to be placed in mem.
++ * Return a pointer to the character AFTER the last byte written.
++ * May return an error.
++ */
++int kgdb_hex2mem(char *buf, char *mem, int count)
++{
++ char *tmp_raw;
++ char *tmp_hex;
++
++ /*
++ * We use the upper half of buf as an intermediate buffer for the
++ * raw memory that is converted from hex.
++ */
++ tmp_raw = buf + count * 2;
++
++ tmp_hex = tmp_raw - 1;
++ while (tmp_hex >= buf) {
++ tmp_raw--;
++ *tmp_raw = hex(*tmp_hex--);
++ *tmp_raw |= hex(*tmp_hex--) << 4;
++ }
++
++ return probe_kernel_write(mem, tmp_raw, count);
++}
++
++/*
++ * While we find nice hex chars, build a long_val.
++ * Return number of chars processed.
++ */
++int kgdb_hex2long(char **ptr, long *long_val)
++{
++ int hex_val;
++ int num = 0;
++
++ *long_val = 0;
++
++ while (**ptr) {
++ hex_val = hex(**ptr);
++ if (hex_val < 0)
++ break;
++
++ *long_val = (*long_val << 4) | hex_val;
++ num++;
++ (*ptr)++;
++ }
++
++ return num;
++}
++
++/* Write memory due to an 'M' or 'X' packet. */
++static int write_mem_msg(int binary)
++{
++ char *ptr = &remcom_in_buffer[1];
++ unsigned long addr;
++ unsigned long length;
++ int err;
++
++ if (kgdb_hex2long(&ptr, &addr) > 0 && *(ptr++) == ',' &&
++ kgdb_hex2long(&ptr, &length) > 0 && *(ptr++) == ':') {
++ if (binary)
++ err = kgdb_ebin2mem(ptr, (char *)addr, length);
++ else
++ err = kgdb_hex2mem(ptr, (char *)addr, length);
++ if (err)
++ return err;
++ if (CACHE_FLUSH_IS_SAFE)
++ flush_icache_range(addr, addr + length + 1);
++ return 0;
++ }
++
++ return -EINVAL;
++}
++
++static void error_packet(char *pkt, int error)
++{
++ error = -error;
++ pkt[0] = 'E';
++ pkt[1] = hexchars[(error / 10)];
++ pkt[2] = hexchars[(error % 10)];
++ pkt[3] = '\0';
++}
++
++/*
++ * Thread ID accessors. We represent a flat TID space to GDB, where
++ * the per CPU idle threads (which under Linux all have PID 0) are
++ * remapped to negative TIDs.
++ */
++
++#define BUF_THREAD_ID_SIZE 16
++
++static char *pack_threadid(char *pkt, unsigned char *id)
++{
++ char *limit;
++
++ limit = pkt + BUF_THREAD_ID_SIZE;
++ while (pkt < limit)
++ pkt = pack_hex_byte(pkt, *id++);
++
++ return pkt;
++}
++
++static void int_to_threadref(unsigned char *id, int value)
++{
++ unsigned char *scan;
++ int i = 4;
++
++ scan = (unsigned char *)id;
++ while (i--)
++ *scan++ = 0;
++ *scan++ = (value >> 24) & 0xff;
++ *scan++ = (value >> 16) & 0xff;
++ *scan++ = (value >> 8) & 0xff;
++ *scan++ = (value & 0xff);
++}
++
++static struct task_struct *getthread(struct pt_regs *regs, int tid)
++{
++ /*
++ * Non-positive TIDs are remapped idle tasks:
++ */
++ if (tid <= 0)
++ return idle_task(-tid);
++
++ /*
++ * find_task_by_pid_ns() does not take the tasklist lock anymore
++ * but is nicely RCU locked - hence is a pretty resilient
++ * thing to use:
++ */
++ return find_task_by_pid_ns(tid, &init_pid_ns);
++}
++
++/*
++ * CPU debug state control:
++ */
++
++#ifdef CONFIG_SMP
++static void kgdb_wait(struct pt_regs *regs)
++{
++ unsigned long flags;
++ int cpu;
++
++ local_irq_save(flags);
++ cpu = raw_smp_processor_id();
++ kgdb_info[cpu].debuggerinfo = regs;
++ kgdb_info[cpu].task = current;
++ /*
++ * Make sure the above info reaches the primary CPU before
++ * our cpu_in_kgdb[] flag setting does:
++ */
++ smp_wmb();
++ atomic_set(&cpu_in_kgdb[cpu], 1);
++
++ /* Wait till primary CPU is done with debugging */
++ while (atomic_read(&passive_cpu_wait[cpu]))
++ cpu_relax();
++
++ kgdb_info[cpu].debuggerinfo = NULL;
++ kgdb_info[cpu].task = NULL;
++
++ /* fix up hardware debug registers on local cpu */
++ if (arch_kgdb_ops.correct_hw_break)
++ arch_kgdb_ops.correct_hw_break();
++
++ /* Signal the primary CPU that we are done: */
++ atomic_set(&cpu_in_kgdb[cpu], 0);
++ clocksource_touch_watchdog();
++ local_irq_restore(flags);
++}
++#endif
++
++/*
++ * Some architectures need cache flushes when we set/clear a
++ * breakpoint:
++ */
++static void kgdb_flush_swbreak_addr(unsigned long addr)
++{
++ if (!CACHE_FLUSH_IS_SAFE)
++ return;
++
++ if (current->mm && current->mm->mmap_cache) {
++ flush_cache_range(current->mm->mmap_cache,
++ addr, addr + BREAK_INSTR_SIZE);
++ }
++ /* Force flush instruction cache if it was outside the mm */
++ flush_icache_range(addr, addr + BREAK_INSTR_SIZE);
++}
++
++/*
++ * SW breakpoint management:
++ */
++static int kgdb_activate_sw_breakpoints(void)
++{
++ unsigned long addr;
++ int error = 0;
++ int i;
++
++ for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
++ if (kgdb_break[i].state != BP_SET)
++ continue;
++
++ addr = kgdb_break[i].bpt_addr;
++ error = kgdb_arch_set_breakpoint(addr,
++ kgdb_break[i].saved_instr);
++ if (error)
++ return error;
++
++ kgdb_flush_swbreak_addr(addr);
++ kgdb_break[i].state = BP_ACTIVE;
++ }
++ return 0;
++}
++
++static int kgdb_set_sw_break(unsigned long addr)
++{
++ int err = kgdb_validate_break_address(addr);
++ int breakno = -1;
++ int i;
++
++ if (err)
++ return err;
++
++ for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
++ if ((kgdb_break[i].state == BP_SET) &&
++ (kgdb_break[i].bpt_addr == addr))
++ return -EEXIST;
++ }
++ for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
++ if (kgdb_break[i].state == BP_REMOVED &&
++ kgdb_break[i].bpt_addr == addr) {
++ breakno = i;
++ break;
++ }
++ }
++
++ if (breakno == -1) {
++ for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
++ if (kgdb_break[i].state == BP_UNDEFINED) {
++ breakno = i;
++ break;
++ }
++ }
++ }
++
++ if (breakno == -1)
++ return -E2BIG;
++
++ kgdb_break[breakno].state = BP_SET;
++ kgdb_break[breakno].type = BP_BREAKPOINT;
++ kgdb_break[breakno].bpt_addr = addr;
++
++ return 0;
++}
++
++static int kgdb_deactivate_sw_breakpoints(void)
++{
++ unsigned long addr;
++ int error = 0;
++ int i;
++
++ for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
++ if (kgdb_break[i].state != BP_ACTIVE)
++ continue;
++ addr = kgdb_break[i].bpt_addr;
++ error = kgdb_arch_remove_breakpoint(addr,
++ kgdb_break[i].saved_instr);
++ if (error)
++ return error;
++
++ kgdb_flush_swbreak_addr(addr);
++ kgdb_break[i].state = BP_SET;
++ }
++ return 0;
++}
++
++static int kgdb_remove_sw_break(unsigned long addr)
++{
++ int i;
++
++ for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
++ if ((kgdb_break[i].state == BP_SET) &&
++ (kgdb_break[i].bpt_addr == addr)) {
++ kgdb_break[i].state = BP_REMOVED;
++ return 0;
++ }
++ }
++ return -ENOENT;
++}
++
++int kgdb_isremovedbreak(unsigned long addr)
++{
++ int i;
++
++ for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
++ if ((kgdb_break[i].state == BP_REMOVED) &&
++ (kgdb_break[i].bpt_addr == addr))
++ return 1;
++ }
++ return 0;
++}
++
++int remove_all_break(void)
++{
++ unsigned long addr;
++ int error;
++ int i;
++
++ /* Clear memory breakpoints. */
++ for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
++ if (kgdb_break[i].state != BP_ACTIVE)
++ goto setundefined;
++ addr = kgdb_break[i].bpt_addr;
++ error = kgdb_arch_remove_breakpoint(addr,
++ kgdb_break[i].saved_instr);
++ if (error)
++ printk(KERN_ERR "KGDB: breakpoint remove failed: %lx\n",
++ addr);
++setundefined:
++ kgdb_break[i].state = BP_UNDEFINED;
++ }
++
++ /* Clear hardware breakpoints. */
++ if (arch_kgdb_ops.remove_all_hw_break)
++ arch_kgdb_ops.remove_all_hw_break();
++
++ return 0;
++}
++
++/*
++ * Remap normal tasks to their real PID, idle tasks to -1 ... -NR_CPUs:
++ */
++static inline int shadow_pid(int realpid)
++{
++ if (realpid)
++ return realpid;
++
++ return -1-raw_smp_processor_id();
++}
++
++static char gdbmsgbuf[BUFMAX + 1];
++
++static void kgdb_msg_write(const char *s, int len)
++{
++ char *bufptr;
++ int wcount;
++ int i;
++
++ /* 'O'utput */
++ gdbmsgbuf[0] = 'O';
++
++ /* Fill and send buffers... */
++ while (len > 0) {
++ bufptr = gdbmsgbuf + 1;
++
++ /* Calculate how many this time */
++ if ((len << 1) > (BUFMAX - 2))
++ wcount = (BUFMAX - 2) >> 1;
++ else
++ wcount = len;
++
++ /* Pack in hex chars */
++ for (i = 0; i < wcount; i++)
++ bufptr = pack_hex_byte(bufptr, s[i]);
++ *bufptr = '\0';
++
++ /* Move up */
++ s += wcount;
++ len -= wcount;
++
++ /* Write packet */
++ put_packet(gdbmsgbuf);
++ }
++}
++
++/*
++ * Return true if there is a valid kgdb I/O module. Also if no
++ * debugger is attached a message can be printed to the console about
++ * waiting for the debugger to attach.
++ *
++ * The print_wait argument is only to be true when called from inside
++ * the core kgdb_handle_exception, because it will wait for the
++ * debugger to attach.
++ */
++static int kgdb_io_ready(int print_wait)
++{
++ if (!kgdb_io_ops)
++ return 0;
++ if (kgdb_connected)
++ return 1;
++ if (atomic_read(&kgdb_setting_breakpoint))
++ return 1;
++ if (print_wait)
++ printk(KERN_CRIT "KGDB: Waiting for remote debugger\n");
++ return 1;
++}
++
++/*
++ * All the functions that start with gdb_cmd are the various
++ * operations to implement the handlers for the gdbserial protocol
++ * where KGDB is communicating with an external debugger
++ */
++
++/* Handle the '?' status packets */
++static void gdb_cmd_status(struct kgdb_state *ks)
++{
++ /*
++ * We know that this packet is only sent
++ * during initial connect. So to be safe,
++ * we clear out our breakpoints now in case
++ * GDB is reconnecting.
++ */
++ remove_all_break();
++
++ remcom_out_buffer[0] = 'S';
++ pack_hex_byte(&remcom_out_buffer[1], ks->signo);
++}
++
++/* Handle the 'g' get registers request */
++static void gdb_cmd_getregs(struct kgdb_state *ks)
++{
++ struct task_struct *thread;
++ void *local_debuggerinfo;
++ int i;
++
++ thread = kgdb_usethread;
++ if (!thread) {
++ thread = kgdb_info[ks->cpu].task;
++ local_debuggerinfo = kgdb_info[ks->cpu].debuggerinfo;
++ } else {
++ local_debuggerinfo = NULL;
++ for (i = 0; i < NR_CPUS; i++) {
++ /*
++ * Try to find the task on some other
++ * or possibly this node if we do not
++ * find the matching task then we try
++ * to approximate the results.
++ */
++ if (thread == kgdb_info[i].task)
++ local_debuggerinfo = kgdb_info[i].debuggerinfo;
++ }
++ }
++
++ /*
++ * All threads that don't have debuggerinfo should be
++ * in __schedule() sleeping, since all other CPUs
++ * are in kgdb_wait, and thus have debuggerinfo.
++ */
++ if (local_debuggerinfo) {
++ pt_regs_to_gdb_regs(gdb_regs, local_debuggerinfo);
++ } else {
++ /*
++ * Pull stuff saved during switch_to; nothing
++ * else is accessible (or even particularly
++ * relevant).
++ *
++ * This should be enough for a stack trace.
++ */
++ sleeping_thread_to_gdb_regs(gdb_regs, thread);
++ }
++ kgdb_mem2hex((char *)gdb_regs, remcom_out_buffer, NUMREGBYTES);
++}
++
++/* Handle the 'G' set registers request */
++static void gdb_cmd_setregs(struct kgdb_state *ks)
++{
++ kgdb_hex2mem(&remcom_in_buffer[1], (char *)gdb_regs, NUMREGBYTES);
++
++ if (kgdb_usethread && kgdb_usethread != current) {
++ error_packet(remcom_out_buffer, -EINVAL);
++ } else {
++ gdb_regs_to_pt_regs(gdb_regs, ks->linux_regs);
++ strcpy(remcom_out_buffer, "OK");
++ }
++}
++
++/* Handle the 'm' memory read bytes */
++static void gdb_cmd_memread(struct kgdb_state *ks)
++{
++ char *ptr = &remcom_in_buffer[1];
++ unsigned long length;
++ unsigned long addr;
++ int err;
++
++ if (kgdb_hex2long(&ptr, &addr) > 0 && *ptr++ == ',' &&
++ kgdb_hex2long(&ptr, &length) > 0) {
++ err = kgdb_mem2hex((char *)addr, remcom_out_buffer, length);
++ if (err)
++ error_packet(remcom_out_buffer, err);
++ } else {
++ error_packet(remcom_out_buffer, -EINVAL);
++ }
++}
++
++/* Handle the 'M' memory write bytes */
++static void gdb_cmd_memwrite(struct kgdb_state *ks)
++{
++ int err = write_mem_msg(0);
++
++ if (err)
++ error_packet(remcom_out_buffer, err);
++ else
++ strcpy(remcom_out_buffer, "OK");
++}
++
++/* Handle the 'X' memory binary write bytes */
++static void gdb_cmd_binwrite(struct kgdb_state *ks)
++{
++ int err = write_mem_msg(1);
++
++ if (err)
++ error_packet(remcom_out_buffer, err);
++ else
++ strcpy(remcom_out_buffer, "OK");
++}
++
++/* Handle the 'D' or 'k', detach or kill packets */
++static void gdb_cmd_detachkill(struct kgdb_state *ks)
++{
++ int error;
++
++ /* The detach case */
++ if (remcom_in_buffer[0] == 'D') {
++ error = remove_all_break();
++ if (error < 0) {
++ error_packet(remcom_out_buffer, error);
++ } else {
++ strcpy(remcom_out_buffer, "OK");
++ kgdb_connected = 0;
++ }
++ put_packet(remcom_out_buffer);
++ } else {
++ /*
++ * Assume the kill case, with no exit code checking,
++ * trying to force detach the debugger:
++ */
++ remove_all_break();
++ kgdb_connected = 0;
++ }
++}
++
++/* Handle the 'R' reboot packets */
++static int gdb_cmd_reboot(struct kgdb_state *ks)
++{
++ /* For now, only honor R0 */
++ if (strcmp(remcom_in_buffer, "R0") == 0) {
++ printk(KERN_CRIT "Executing emergency reboot\n");
++ strcpy(remcom_out_buffer, "OK");
++ put_packet(remcom_out_buffer);
++
++ /*
++ * Execution should not return from
++ * machine_emergency_restart()
++ */
++ machine_emergency_restart();
++ kgdb_connected = 0;
++
++ return 1;
++ }
++ return 0;
++}
++
++/* Handle the 'q' query packets */
++static void gdb_cmd_query(struct kgdb_state *ks)
++{
++ struct task_struct *thread;
++ unsigned char thref[8];
++ char *ptr;
++ int i;
++
++ switch (remcom_in_buffer[1]) {
++ case 's':
++ case 'f':
++ if (memcmp(remcom_in_buffer + 2, "ThreadInfo", 10)) {
++ error_packet(remcom_out_buffer, -EINVAL);
++ break;
++ }
++
++ if (remcom_in_buffer[1] == 'f')
++ ks->threadid = 1;
++
++ remcom_out_buffer[0] = 'm';
++ ptr = remcom_out_buffer + 1;
++
++ for (i = 0; i < 17; ks->threadid++) {
++ thread = getthread(ks->linux_regs, ks->threadid);
++ if (thread) {
++ int_to_threadref(thref, ks->threadid);
++ pack_threadid(ptr, thref);
++ ptr += BUF_THREAD_ID_SIZE;
++ *(ptr++) = ',';
++ i++;
++ }
++ }
++ *(--ptr) = '\0';
++ break;
++
++ case 'C':
++ /* Current thread id */
++ strcpy(remcom_out_buffer, "QC");
++ ks->threadid = shadow_pid(current->pid);
++ int_to_threadref(thref, ks->threadid);
++ pack_threadid(remcom_out_buffer + 2, thref);
++ break;
++ case 'T':
++ if (memcmp(remcom_in_buffer + 1, "ThreadExtraInfo,", 16)) {
++ error_packet(remcom_out_buffer, -EINVAL);
++ break;
++ }
++ ks->threadid = 0;
++ ptr = remcom_in_buffer + 17;
++ kgdb_hex2long(&ptr, &ks->threadid);
++ if (!getthread(ks->linux_regs, ks->threadid)) {
++ error_packet(remcom_out_buffer, -EINVAL);
++ break;
++ }
++ if (ks->threadid > 0) {
++ kgdb_mem2hex(getthread(ks->linux_regs,
++ ks->threadid)->comm,
++ remcom_out_buffer, 16);
++ } else {
++ static char tmpstr[23 + BUF_THREAD_ID_SIZE];
++
++ sprintf(tmpstr, "Shadow task %d for pid 0",
++ (int)(-ks->threadid-1));
++ kgdb_mem2hex(tmpstr, remcom_out_buffer, strlen(tmpstr));
++ }
++ break;
++ }
++}
++
++/* Handle the 'H' task query packets */
++static void gdb_cmd_task(struct kgdb_state *ks)
++{
++ struct task_struct *thread;
++ char *ptr;
++
++ switch (remcom_in_buffer[1]) {
++ case 'g':
++ ptr = &remcom_in_buffer[2];
++ kgdb_hex2long(&ptr, &ks->threadid);
++ thread = getthread(ks->linux_regs, ks->threadid);
++ if (!thread && ks->threadid > 0) {
++ error_packet(remcom_out_buffer, -EINVAL);
++ break;
++ }
++ kgdb_usethread = thread;
++ ks->kgdb_usethreadid = ks->threadid;
++ strcpy(remcom_out_buffer, "OK");
++ break;
++ case 'c':
++ ptr = &remcom_in_buffer[2];
++ kgdb_hex2long(&ptr, &ks->threadid);
++ if (!ks->threadid) {
++ kgdb_contthread = NULL;
++ } else {
++ thread = getthread(ks->linux_regs, ks->threadid);
++ if (!thread && ks->threadid > 0) {
++ error_packet(remcom_out_buffer, -EINVAL);
++ break;
++ }
++ kgdb_contthread = thread;
++ }
++ strcpy(remcom_out_buffer, "OK");
++ break;
++ }
++}
++
++/* Handle the 'T' thread query packets */
++static void gdb_cmd_thread(struct kgdb_state *ks)
++{
++ char *ptr = &remcom_in_buffer[1];
++ struct task_struct *thread;
++
++ kgdb_hex2long(&ptr, &ks->threadid);
++ thread = getthread(ks->linux_regs, ks->threadid);
++ if (thread)
++ strcpy(remcom_out_buffer, "OK");
++ else
++ error_packet(remcom_out_buffer, -EINVAL);
++}
++
++/* Handle the 'z' or 'Z' breakpoint remove or set packets */
++static void gdb_cmd_break(struct kgdb_state *ks)
++{
++ /*
++ * Since GDB-5.3, it's been drafted that '0' is a software
++ * breakpoint, '1' is a hardware breakpoint, so let's do that.
++ */
++ char *bpt_type = &remcom_in_buffer[1];
++ char *ptr = &remcom_in_buffer[2];
++ unsigned long addr;
++ unsigned long length;
++ int error = 0;
++
++ if (arch_kgdb_ops.set_hw_breakpoint && *bpt_type >= '1') {
++ /* Unsupported */
++ if (*bpt_type > '4')
++ return;
++ } else {
++ if (*bpt_type != '0' && *bpt_type != '1')
++ /* Unsupported. */
++ return;
++ }
++
++ /*
++ * Test if this is a hardware breakpoint, and
++ * if we support it:
++ */
++ if (*bpt_type == '1' && !(arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT))
++ /* Unsupported. */
++ return;
++
++ if (*(ptr++) != ',') {
++ error_packet(remcom_out_buffer, -EINVAL);
++ return;
++ }
++ if (!kgdb_hex2long(&ptr, &addr)) {
++ error_packet(remcom_out_buffer, -EINVAL);
++ return;
++ }
++ if (*(ptr++) != ',' ||
++ !kgdb_hex2long(&ptr, &length)) {
++ error_packet(remcom_out_buffer, -EINVAL);
++ return;
++ }
++
++ if (remcom_in_buffer[0] == 'Z' && *bpt_type == '0')
++ error = kgdb_set_sw_break(addr);
++ else if (remcom_in_buffer[0] == 'z' && *bpt_type == '0')
++ error = kgdb_remove_sw_break(addr);
++ else if (remcom_in_buffer[0] == 'Z')
++ error = arch_kgdb_ops.set_hw_breakpoint(addr,
++ (int)length, *bpt_type - '0');
++ else if (remcom_in_buffer[0] == 'z')
++ error = arch_kgdb_ops.remove_hw_breakpoint(addr,
++ (int) length, *bpt_type - '0');
++
++ if (error == 0)
++ strcpy(remcom_out_buffer, "OK");
++ else
++ error_packet(remcom_out_buffer, error);
++}
++
++/* Handle the 'C' signal / exception passing packets */
++static int gdb_cmd_exception_pass(struct kgdb_state *ks)
++{
++ /* C09 == pass exception
++ * C15 == detach kgdb, pass exception
++ */
++ if (remcom_in_buffer[1] == '0' && remcom_in_buffer[2] == '9') {
++
++ ks->pass_exception = 1;
++ remcom_in_buffer[0] = 'c';
++
++ } else if (remcom_in_buffer[1] == '1' && remcom_in_buffer[2] == '5') {
++
++ ks->pass_exception = 1;
++ remcom_in_buffer[0] = 'D';
++ remove_all_break();
++ kgdb_connected = 0;
++ return 1;
++
++ } else {
++ error_packet(remcom_out_buffer, -EINVAL);
++ return 0;
++ }
++
++ /* Indicate fall through */
++ return -1;
++}
++
++/*
++ * This function performs all gdbserial command procesing
++ */
++static int gdb_serial_stub(struct kgdb_state *ks)
++{
++ int error = 0;
++ int tmp;
++
++ /* Clear the out buffer. */
++ memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer));
++
++ if (kgdb_connected) {
++ unsigned char thref[8];
++ char *ptr;
++
++ /* Reply to host that an exception has occurred */
++ ptr = remcom_out_buffer;
++ *ptr++ = 'T';
++ ptr = pack_hex_byte(ptr, ks->signo);
++ ptr += strlen(strcpy(ptr, "thread:"));
++ int_to_threadref(thref, shadow_pid(current->pid));
++ ptr = pack_threadid(ptr, thref);
++ *ptr++ = ';';
++ put_packet(remcom_out_buffer);
++ }
++
++ kgdb_usethread = kgdb_info[ks->cpu].task;
++ ks->kgdb_usethreadid = shadow_pid(kgdb_info[ks->cpu].task->pid);
++ ks->pass_exception = 0;
++
++ while (1) {
++ error = 0;
++
++ /* Clear the out buffer. */
++ memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer));
++
++ get_packet(remcom_in_buffer);
++
++ switch (remcom_in_buffer[0]) {
++ case '?': /* gdbserial status */
++ gdb_cmd_status(ks);
++ break;
++ case 'g': /* return the value of the CPU registers */
++ gdb_cmd_getregs(ks);
++ break;
++ case 'G': /* set the value of the CPU registers - return OK */
++ gdb_cmd_setregs(ks);
++ break;
++ case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
++ gdb_cmd_memread(ks);
++ break;
++ case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA..AA */
++ gdb_cmd_memwrite(ks);
++ break;
++ case 'X': /* XAA..AA,LLLL: Write LLLL bytes at address AA..AA */
++ gdb_cmd_binwrite(ks);
++ break;
++ /* kill or detach. KGDB should treat this like a
++ * continue.
++ */
++ case 'D': /* Debugger detach */
++ case 'k': /* Debugger detach via kill */
++ gdb_cmd_detachkill(ks);
++ goto default_handle;
++ case 'R': /* Reboot */
++ if (gdb_cmd_reboot(ks))
++ goto default_handle;
++ break;
++ case 'q': /* query command */
++ gdb_cmd_query(ks);
++ break;
++ case 'H': /* task related */
++ gdb_cmd_task(ks);
++ break;
++ case 'T': /* Query thread status */
++ gdb_cmd_thread(ks);
++ break;
++ case 'z': /* Break point remove */
++ case 'Z': /* Break point set */
++ gdb_cmd_break(ks);
++ break;
++ case 'C': /* Exception passing */
++ tmp = gdb_cmd_exception_pass(ks);
++ if (tmp > 0)
++ goto default_handle;
++ if (tmp == 0)
++ break;
++ /* Fall through on tmp < 0 */
++ case 'c': /* Continue packet */
++ case 's': /* Single step packet */
++ if (kgdb_contthread && kgdb_contthread != current) {
++ /* Can't switch threads in kgdb */
++ error_packet(remcom_out_buffer, -EINVAL);
++ break;
++ }
++ kgdb_activate_sw_breakpoints();
++ /* Fall through to default processing */
++ default:
++default_handle:
++ error = kgdb_arch_handle_exception(ks->ex_vector,
++ ks->signo,
++ ks->err_code,
++ remcom_in_buffer,
++ remcom_out_buffer,
++ ks->linux_regs);
++ /*
++ * Leave cmd processing on error, detach,
++ * kill, continue, or single step.
++ */
++ if (error >= 0 || remcom_in_buffer[0] == 'D' ||
++ remcom_in_buffer[0] == 'k') {
++ error = 0;
++ goto kgdb_exit;
++ }
++
++ }
++
++ /* reply to the request */
++ put_packet(remcom_out_buffer);
++ }
++
++kgdb_exit:
++ if (ks->pass_exception)
++ error = 1;
++ return error;
++}
++
++static int kgdb_reenter_check(struct kgdb_state *ks)
++{
++ unsigned long addr;
++
++ if (atomic_read(&kgdb_active) != raw_smp_processor_id())
++ return 0;
++
++ /* Panic on recursive debugger calls: */
++ exception_level++;
++ addr = kgdb_arch_pc(ks->ex_vector, ks->linux_regs);
++ kgdb_deactivate_sw_breakpoints();
++
++ /*
++ * If the break point removed ok at the place exception
++ * occurred, try to recover and print a warning to the end
++ * user because the user planted a breakpoint in a place that
++ * KGDB needs in order to function.
++ */
++ if (kgdb_remove_sw_break(addr) == 0) {
++ exception_level = 0;
++ kgdb_skipexception(ks->ex_vector, ks->linux_regs);
++ kgdb_activate_sw_breakpoints();
++ printk(KERN_CRIT "KGDB: re-enter error: breakpoint removed %lx\n",
++ addr);
++ WARN_ON_ONCE(1);
++
++ return 1;
++ }
++ remove_all_break();
++ kgdb_skipexception(ks->ex_vector, ks->linux_regs);
++
++ if (exception_level > 1) {
++ dump_stack();
++ panic("Recursive entry to debugger");
++ }
++
++ printk(KERN_CRIT "KGDB: re-enter exception: ALL breakpoints killed\n");
++ dump_stack();
++ panic("Recursive entry to debugger");
++
++ return 1;
++}
++
++/*
++ * kgdb_handle_exception() - main entry point from a kernel exception
++ *
++ * Locking hierarchy:
++ * interface locks, if any (begin_session)
++ * kgdb lock (kgdb_active)
++ */
++int
++kgdb_handle_exception(int evector, int signo, int ecode, struct pt_regs *regs)
++{
++ struct kgdb_state kgdb_var;
++ struct kgdb_state *ks = &kgdb_var;
++ unsigned long flags;
++ int error = 0;
++ int i, cpu;
++
++ ks->cpu = raw_smp_processor_id();
++ ks->ex_vector = evector;
++ ks->signo = signo;
++ ks->ex_vector = evector;
++ ks->err_code = ecode;
++ ks->kgdb_usethreadid = 0;
++ ks->linux_regs = regs;
++
++ if (kgdb_reenter_check(ks))
++ return 0; /* Ouch, double exception ! */
++
++acquirelock:
++ /*
++ * Interrupts will be restored by the 'trap return' code, except when
++ * single stepping.
++ */
++ local_irq_save(flags);
++
++ cpu = raw_smp_processor_id();
++
++ /*
++ * Acquire the kgdb_active lock:
++ */
++ while (atomic_cmpxchg(&kgdb_active, -1, cpu) != -1)
++ cpu_relax();
++
++ /*
++ * Do not start the debugger connection on this CPU if the last
++ * instance of the exception handler wanted to come into the
++ * debugger on a different CPU via a single step
++ */
++ if (atomic_read(&kgdb_cpu_doing_single_step) != -1 &&
++ atomic_read(&kgdb_cpu_doing_single_step) != cpu) {
++
++ atomic_set(&kgdb_active, -1);
++ clocksource_touch_watchdog();
++ local_irq_restore(flags);
++
++ goto acquirelock;
++ }
++
++ if (!kgdb_io_ready(1)) {
++ error = 1;
++ goto kgdb_restore; /* No I/O connection, so resume the system */
++ }
++
++ /*
++ * Don't enter if we have hit a removed breakpoint.
++ */
++ if (kgdb_skipexception(ks->ex_vector, ks->linux_regs))
++ goto kgdb_restore;
++
++ /* Call the I/O driver's pre_exception routine */
++ if (kgdb_io_ops->pre_exception)
++ kgdb_io_ops->pre_exception();
++
++ kgdb_info[ks->cpu].debuggerinfo = ks->linux_regs;
++ kgdb_info[ks->cpu].task = current;
++
++ kgdb_disable_hw_debug(ks->linux_regs);
++
++ /*
++ * Get the passive CPU lock which will hold all the non-primary
++ * CPU in a spin state while the debugger is active
++ */
++ if (!kgdb_single_step || !kgdb_contthread) {
++ for (i = 0; i < NR_CPUS; i++)
++ atomic_set(&passive_cpu_wait[i], 1);
++ }
++
++ /*
++ * spin_lock code is good enough as a barrier so we don't
++ * need one here:
++ */
++ atomic_set(&cpu_in_kgdb[ks->cpu], 1);
++
++#ifdef CONFIG_SMP
++ /* Signal the other CPUs to enter kgdb_wait() */
++ if ((!kgdb_single_step || !kgdb_contthread) && kgdb_do_roundup)
++ kgdb_roundup_cpus(flags);
++#endif
++
++ /*
++ * Wait for the other CPUs to be notified and be waiting for us:
++ */
++ for_each_online_cpu(i) {
++ while (!atomic_read(&cpu_in_kgdb[i]))
++ cpu_relax();
++ }
++
++ /*
++ * At this point the primary processor is completely
++ * in the debugger and all secondary CPUs are quiescent
++ */
++ kgdb_post_primary_code(ks->linux_regs, ks->ex_vector, ks->err_code);
++ kgdb_deactivate_sw_breakpoints();
++ kgdb_single_step = 0;
++ kgdb_contthread = NULL;
++ exception_level = 0;
++
++ /* Talk to debugger with gdbserial protocol */
++ error = gdb_serial_stub(ks);
++
++ /* Call the I/O driver's post_exception routine */
++ if (kgdb_io_ops->post_exception)
++ kgdb_io_ops->post_exception();
++
++ kgdb_info[ks->cpu].debuggerinfo = NULL;
++ kgdb_info[ks->cpu].task = NULL;
++ atomic_set(&cpu_in_kgdb[ks->cpu], 0);
++
++ if (!kgdb_single_step || !kgdb_contthread) {
++ for (i = NR_CPUS-1; i >= 0; i--)
++ atomic_set(&passive_cpu_wait[i], 0);
++ /*
++ * Wait till all the CPUs have quit
++ * from the debugger.
++ */
++ for_each_online_cpu(i) {
++ while (atomic_read(&cpu_in_kgdb[i]))
++ cpu_relax();
++ }
++ }
++
++kgdb_restore:
++ /* Free kgdb_active */
++ atomic_set(&kgdb_active, -1);
++ clocksource_touch_watchdog();
++ local_irq_restore(flags);
++
++ return error;
++}
++
++int kgdb_nmicallback(int cpu, void *regs)
++{
++#ifdef CONFIG_SMP
++ if (!atomic_read(&cpu_in_kgdb[cpu]) &&
++ atomic_read(&kgdb_active) != cpu &&
++ atomic_read(&cpu_in_kgdb[atomic_read(&kgdb_active)])) {
++ kgdb_wait((struct pt_regs *)regs);
++ return 0;
++ }
++#endif
++ return 1;
++}
++
++void kgdb_console_write(struct console *co, const char *s, unsigned count)
++{
++ unsigned long flags;
++
++ /* If we're debugging, or KGDB has not connected, don't try
++ * and print. */
++ if (!kgdb_connected || atomic_read(&kgdb_active) != -1)
++ return;
++
++ local_irq_save(flags);
++ kgdb_msg_write(s, count);
++ local_irq_restore(flags);
++}
++
++static struct console kgdbcons = {
++ .name = "kgdb",
++ .write = kgdb_console_write,
++ .flags = CON_PRINTBUFFER | CON_ENABLED,
++ .index = -1,
++};
++
++#ifdef CONFIG_MAGIC_SYSRQ
++static void sysrq_handle_gdb(int key, struct tty_struct *tty)
++{
++ if (!kgdb_io_ops) {
++ printk(KERN_CRIT "ERROR: No KGDB I/O module available\n");
++ return;
++ }
++ if (!kgdb_connected)
++ printk(KERN_CRIT "Entering KGDB\n");
++
++ kgdb_breakpoint();
++}
++
++static struct sysrq_key_op sysrq_gdb_op = {
++ .handler = sysrq_handle_gdb,
++ .help_msg = "Gdb",
++ .action_msg = "GDB",
++};
++#endif
++
++static void kgdb_register_callbacks(void)
++{
++ if (!kgdb_io_module_registered) {
++ kgdb_io_module_registered = 1;
++ kgdb_arch_init();
++#ifdef CONFIG_MAGIC_SYSRQ
++ register_sysrq_key('g', &sysrq_gdb_op);
++#endif
++ if (kgdb_use_con && !kgdb_con_registered) {
++ register_console(&kgdbcons);
++ kgdb_con_registered = 1;
++ }
++ }
++}
++
++static void kgdb_unregister_callbacks(void)
++{
++ /*
++ * When this routine is called KGDB should unregister from the
++ * panic handler and clean up, making sure it is not handling any
++ * break exceptions at the time.
++ */
++ if (kgdb_io_module_registered) {
++ kgdb_io_module_registered = 0;
++ kgdb_arch_exit();
++#ifdef CONFIG_MAGIC_SYSRQ
++ unregister_sysrq_key('g', &sysrq_gdb_op);
++#endif
++ if (kgdb_con_registered) {
++ unregister_console(&kgdbcons);
++ kgdb_con_registered = 0;
++ }
++ }
++}
++
++static void kgdb_initial_breakpoint(void)
++{
++ kgdb_break_asap = 0;
++
++ printk(KERN_CRIT "kgdb: Waiting for connection from remote gdb...\n");
++ kgdb_breakpoint();
++}
++
++/**
++ * kgdb_register_io_module - register KGDB IO module
++ * @new_kgdb_io_ops: the io ops vector
++ *
++ * Register it with the KGDB core.
++ */
++int kgdb_register_io_module(struct kgdb_io *new_kgdb_io_ops)
++{
++ int err;
++
++ spin_lock(&kgdb_registration_lock);
++
++ if (kgdb_io_ops) {
++ spin_unlock(&kgdb_registration_lock);
++
++ printk(KERN_ERR "kgdb: Another I/O driver is already "
++ "registered with KGDB.\n");
++ return -EBUSY;
++ }
++
++ if (new_kgdb_io_ops->init) {
++ err = new_kgdb_io_ops->init();
++ if (err) {
++ spin_unlock(&kgdb_registration_lock);
++ return err;
++ }
++ }
++
++ kgdb_io_ops = new_kgdb_io_ops;
++
++ spin_unlock(&kgdb_registration_lock);
++
++ printk(KERN_INFO "kgdb: Registered I/O driver %s.\n",
++ new_kgdb_io_ops->name);
++
++ /* Arm KGDB now. */
++ kgdb_register_callbacks();
++
++ if (kgdb_break_asap)
++ kgdb_initial_breakpoint();
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(kgdb_register_io_module);
++
++/**
++ * kkgdb_unregister_io_module - unregister KGDB IO module
++ * @old_kgdb_io_ops: the io ops vector
++ *
++ * Unregister it with the KGDB core.
++ */
++void kgdb_unregister_io_module(struct kgdb_io *old_kgdb_io_ops)
++{
++ BUG_ON(kgdb_connected);
++
++ /*
++ * KGDB is no longer able to communicate out, so
++ * unregister our callbacks and reset state.
++ */
++ kgdb_unregister_callbacks();
++
++ spin_lock(&kgdb_registration_lock);
++
++ WARN_ON_ONCE(kgdb_io_ops != old_kgdb_io_ops);
++ kgdb_io_ops = NULL;
++
++ spin_unlock(&kgdb_registration_lock);
++
++ printk(KERN_INFO
++ "kgdb: Unregistered I/O driver %s, debugger disabled.\n",
++ old_kgdb_io_ops->name);
++}
++EXPORT_SYMBOL_GPL(kgdb_unregister_io_module);
++
++/**
++ * kgdb_breakpoint - generate breakpoint exception
++ *
++ * This function will generate a breakpoint exception. It is used at the
++ * beginning of a program to sync up with a debugger and can be used
++ * otherwise as a quick means to stop program execution and "break" into
++ * the debugger.
++ */
++void kgdb_breakpoint(void)
++{
++ atomic_set(&kgdb_setting_breakpoint, 1);
++ wmb(); /* Sync point before breakpoint */
++ arch_kgdb_breakpoint();
++ wmb(); /* Sync point after breakpoint */
++ atomic_set(&kgdb_setting_breakpoint, 0);
++}
++EXPORT_SYMBOL_GPL(kgdb_breakpoint);
++
++static int __init opt_kgdb_wait(char *str)
++{
++ kgdb_break_asap = 1;
++
++ if (kgdb_io_module_registered)
++ kgdb_initial_breakpoint();
++
++ return 0;
++}
++
++early_param("kgdbwait", opt_kgdb_wait);
+diff --git a/kernel/kmod.c b/kernel/kmod.c
+index 22be3ff..e276404 100644
+--- a/kernel/kmod.c
++++ b/kernel/kmod.c
+@@ -165,7 +165,7 @@ static int ____call_usermodehelper(void *data)
+ }
+
+ /* We can run anywhere, unlike our parent keventd(). */
+- set_cpus_allowed(current, CPU_MASK_ALL);
++ set_cpus_allowed_ptr(current, CPU_MASK_ALL_PTR);
+
+ /*
+ * Our parent is keventd, which runs with elevated scheduling priority.
+diff --git a/kernel/kthread.c b/kernel/kthread.c
+index 0ac8878..92cf693 100644
+--- a/kernel/kthread.c
++++ b/kernel/kthread.c
+@@ -13,7 +13,6 @@
+ #include <linux/file.h>
+ #include <linux/module.h>
+ #include <linux/mutex.h>
+-#include <asm/semaphore.h>
+
+ #define KTHREAD_NICE_LEVEL (-5)
+
+@@ -180,6 +179,7 @@ void kthread_bind(struct task_struct *k, unsigned int cpu)
+ wait_task_inactive(k);
+ set_task_cpu(k, cpu);
+ k->cpus_allowed = cpumask_of_cpu(cpu);
++ k->rt.nr_cpus_allowed = 1;
+ }
+ EXPORT_SYMBOL(kthread_bind);
+
+diff --git a/kernel/latencytop.c b/kernel/latencytop.c
+index b4e3c85..7c74dab 100644
+--- a/kernel/latencytop.c
++++ b/kernel/latencytop.c
+@@ -64,8 +64,8 @@ account_global_scheduler_latency(struct task_struct *tsk, struct latency_record
+ return;
+
+ for (i = 0; i < MAXLR; i++) {
+- int q;
+- int same = 1;
++ int q, same = 1;
++
+ /* Nothing stored: */
+ if (!latency_record[i].backtrace[0]) {
+ if (firstnonnull > i)
+@@ -73,12 +73,15 @@ account_global_scheduler_latency(struct task_struct *tsk, struct latency_record
+ continue;
+ }
+ for (q = 0 ; q < LT_BACKTRACEDEPTH ; q++) {
+- if (latency_record[i].backtrace[q] !=
+- lat->backtrace[q])
++ unsigned long record = lat->backtrace[q];
++
++ if (latency_record[i].backtrace[q] != record) {
+ same = 0;
+- if (same && lat->backtrace[q] == 0)
+ break;
+- if (same && lat->backtrace[q] == ULONG_MAX)
++ }
++
++ /* 0 and ULONG_MAX entries mean end of backtrace: */
++ if (record == 0 || record == ULONG_MAX)
+ break;
+ }
+ if (same) {
+@@ -143,14 +146,18 @@ account_scheduler_latency(struct task_struct *tsk, int usecs, int inter)
+ for (i = 0; i < LT_SAVECOUNT ; i++) {
+ struct latency_record *mylat;
+ int same = 1;
++
+ mylat = &tsk->latency_record[i];
+ for (q = 0 ; q < LT_BACKTRACEDEPTH ; q++) {
+- if (mylat->backtrace[q] !=
+- lat.backtrace[q])
++ unsigned long record = lat.backtrace[q];
++
++ if (mylat->backtrace[q] != record) {
+ same = 0;
+- if (same && lat.backtrace[q] == 0)
+ break;
+- if (same && lat.backtrace[q] == ULONG_MAX)
++ }
++
++ /* 0 and ULONG_MAX entries mean end of backtrace: */
++ if (record == 0 || record == ULONG_MAX)
+ break;
+ }
+ if (same) {
+diff --git a/kernel/module.c b/kernel/module.c
+index 5d437bf..8d6cccc 100644
+--- a/kernel/module.c
++++ b/kernel/module.c
+@@ -43,7 +43,6 @@
+ #include <linux/mutex.h>
+ #include <linux/unwind.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #include <asm/cacheflush.h>
+ #include <linux/license.h>
+ #include <asm/sections.h>
+@@ -664,7 +663,7 @@ static void free_module(struct module *mod);
+
+ static void wait_for_zero_refcount(struct module *mod)
+ {
+- /* Since we might sleep for some time, drop the semaphore first */
++ /* Since we might sleep for some time, release the mutex first */
+ mutex_unlock(&module_mutex);
+ for (;;) {
+ DEBUGP("Looking at refcount...\n");
+diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
+index 2eae91f..ae5c6c1 100644
+--- a/kernel/posix-cpu-timers.c
++++ b/kernel/posix-cpu-timers.c
+@@ -1087,45 +1087,45 @@ static void check_process_timers(struct task_struct *tsk,
+ maxfire = 20;
+ prof_expires = cputime_zero;
+ while (!list_empty(timers)) {
+- struct cpu_timer_list *t = list_first_entry(timers,
++ struct cpu_timer_list *tl = list_first_entry(timers,
+ struct cpu_timer_list,
+ entry);
+- if (!--maxfire || cputime_lt(ptime, t->expires.cpu)) {
+- prof_expires = t->expires.cpu;
++ if (!--maxfire || cputime_lt(ptime, tl->expires.cpu)) {
++ prof_expires = tl->expires.cpu;
+ break;
+ }
+- t->firing = 1;
+- list_move_tail(&t->entry, firing);
++ tl->firing = 1;
++ list_move_tail(&tl->entry, firing);
+ }
+
+ ++timers;
+ maxfire = 20;
+ virt_expires = cputime_zero;
+ while (!list_empty(timers)) {
+- struct cpu_timer_list *t = list_first_entry(timers,
++ struct cpu_timer_list *tl = list_first_entry(timers,
+ struct cpu_timer_list,
+ entry);
+- if (!--maxfire || cputime_lt(utime, t->expires.cpu)) {
+- virt_expires = t->expires.cpu;
++ if (!--maxfire || cputime_lt(utime, tl->expires.cpu)) {
++ virt_expires = tl->expires.cpu;
+ break;
+ }
+- t->firing = 1;
+- list_move_tail(&t->entry, firing);
++ tl->firing = 1;
++ list_move_tail(&tl->entry, firing);
+ }
+
+ ++timers;
+ maxfire = 20;
+ sched_expires = 0;
+ while (!list_empty(timers)) {
+- struct cpu_timer_list *t = list_first_entry(timers,
++ struct cpu_timer_list *tl = list_first_entry(timers,
+ struct cpu_timer_list,
+ entry);
+- if (!--maxfire || sum_sched_runtime < t->expires.sched) {
+- sched_expires = t->expires.sched;
++ if (!--maxfire || sum_sched_runtime < tl->expires.sched) {
++ sched_expires = tl->expires.sched;
+ break;
+ }
+- t->firing = 1;
+- list_move_tail(&t->entry, firing);
++ tl->firing = 1;
++ list_move_tail(&tl->entry, firing);
+ }
+
+ /*
+diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
+index a9b0420..8476956 100644
+--- a/kernel/posix-timers.c
++++ b/kernel/posix-timers.c
+@@ -37,7 +37,6 @@
+ #include <linux/mutex.h>
+
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+ #include <linux/list.h>
+ #include <linux/init.h>
+ #include <linux/compiler.h>
+diff --git a/kernel/profile.c b/kernel/profile.c
+index 3b7a1b0..606d738 100644
+--- a/kernel/profile.c
++++ b/kernel/profile.c
+@@ -23,7 +23,6 @@
+ #include <linux/highmem.h>
+ #include <linux/mutex.h>
+ #include <asm/sections.h>
+-#include <asm/semaphore.h>
+ #include <asm/irq_regs.h>
+ #include <asm/ptrace.h>
+
+diff --git a/kernel/ptrace.c b/kernel/ptrace.c
+index fdb34e8..67e392e 100644
+--- a/kernel/ptrace.c
++++ b/kernel/ptrace.c
+@@ -323,9 +323,8 @@ static int ptrace_setoptions(struct task_struct *child, long data)
+ return (data & ~PTRACE_O_MASK) ? -EINVAL : 0;
+ }
+
+-static int ptrace_getsiginfo(struct task_struct *child, siginfo_t __user * data)
++static int ptrace_getsiginfo(struct task_struct *child, siginfo_t *info)
+ {
+- siginfo_t lastinfo;
+ int error = -ESRCH;
+
+ read_lock(&tasklist_lock);
+@@ -333,31 +332,25 @@ static int ptrace_getsiginfo(struct task_struct *child, siginfo_t __user * data)
+ error = -EINVAL;
+ spin_lock_irq(&child->sighand->siglock);
+ if (likely(child->last_siginfo != NULL)) {
+- lastinfo = *child->last_siginfo;
++ *info = *child->last_siginfo;
+ error = 0;
+ }
+ spin_unlock_irq(&child->sighand->siglock);
+ }
+ read_unlock(&tasklist_lock);
+- if (!error)
+- return copy_siginfo_to_user(data, &lastinfo);
+ return error;
+ }
+
+-static int ptrace_setsiginfo(struct task_struct *child, siginfo_t __user * data)
++static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info)
+ {
+- siginfo_t newinfo;
+ int error = -ESRCH;
+
+- if (copy_from_user(&newinfo, data, sizeof (siginfo_t)))
+- return -EFAULT;
+-
+ read_lock(&tasklist_lock);
+ if (likely(child->sighand != NULL)) {
+ error = -EINVAL;
+ spin_lock_irq(&child->sighand->siglock);
+ if (likely(child->last_siginfo != NULL)) {
+- *child->last_siginfo = newinfo;
++ *child->last_siginfo = *info;
+ error = 0;
+ }
+ spin_unlock_irq(&child->sighand->siglock);
+@@ -424,6 +417,7 @@ int ptrace_request(struct task_struct *child, long request,
+ long addr, long data)
+ {
+ int ret = -EIO;
++ siginfo_t siginfo;
+
+ switch (request) {
+ case PTRACE_PEEKTEXT:
+@@ -442,12 +436,22 @@ int ptrace_request(struct task_struct *child, long request,
+ case PTRACE_GETEVENTMSG:
+ ret = put_user(child->ptrace_message, (unsigned long __user *) data);
+ break;
++
+ case PTRACE_GETSIGINFO:
+- ret = ptrace_getsiginfo(child, (siginfo_t __user *) data);
++ ret = ptrace_getsiginfo(child, &siginfo);
++ if (!ret)
++ ret = copy_siginfo_to_user((siginfo_t __user *) data,
++ &siginfo);
+ break;
++
+ case PTRACE_SETSIGINFO:
+- ret = ptrace_setsiginfo(child, (siginfo_t __user *) data);
++ if (copy_from_user(&siginfo, (siginfo_t __user *) data,
++ sizeof siginfo))
++ ret = -EFAULT;
++ else
++ ret = ptrace_setsiginfo(child, &siginfo);
+ break;
++
+ case PTRACE_DETACH: /* detach a process that was attached. */
+ ret = ptrace_detach(child, data);
+ break;
+@@ -616,6 +620,7 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
+ {
+ compat_ulong_t __user *datap = compat_ptr(data);
+ compat_ulong_t word;
++ siginfo_t siginfo;
+ int ret;
+
+ switch (request) {
+@@ -638,6 +643,23 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
+ ret = put_user((compat_ulong_t) child->ptrace_message, datap);
+ break;
+
++ case PTRACE_GETSIGINFO:
++ ret = ptrace_getsiginfo(child, &siginfo);
++ if (!ret)
++ ret = copy_siginfo_to_user32(
++ (struct compat_siginfo __user *) datap,
++ &siginfo);
++ break;
++
++ case PTRACE_SETSIGINFO:
++ memset(&siginfo, 0, sizeof siginfo);
++ if (copy_siginfo_from_user32(
++ &siginfo, (struct compat_siginfo __user *) datap))
++ ret = -EFAULT;
++ else
++ ret = ptrace_setsiginfo(child, &siginfo);
++ break;
++
+ default:
+ ret = ptrace_request(child, request, addr, data);
+ }
+diff --git a/kernel/rcupreempt.c b/kernel/rcupreempt.c
+index e951701..e1cdf19 100644
+--- a/kernel/rcupreempt.c
++++ b/kernel/rcupreempt.c
+@@ -1007,10 +1007,10 @@ void __synchronize_sched(void)
+ if (sched_getaffinity(0, &oldmask) < 0)
+ oldmask = cpu_possible_map;
+ for_each_online_cpu(cpu) {
+- sched_setaffinity(0, cpumask_of_cpu(cpu));
++ sched_setaffinity(0, &cpumask_of_cpu(cpu));
+ schedule();
+ }
+- sched_setaffinity(0, oldmask);
++ sched_setaffinity(0, &oldmask);
+ }
+ EXPORT_SYMBOL_GPL(__synchronize_sched);
+
+diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
+index fd59982..47894f9 100644
+--- a/kernel/rcutorture.c
++++ b/kernel/rcutorture.c
+@@ -723,9 +723,10 @@ static int rcu_idle_cpu; /* Force all torture tasks off this CPU */
+ */
+ static void rcu_torture_shuffle_tasks(void)
+ {
+- cpumask_t tmp_mask = CPU_MASK_ALL;
++ cpumask_t tmp_mask;
+ int i;
+
++ cpus_setall(tmp_mask);
+ get_online_cpus();
+
+ /* No point in shuffling if there is only one online CPU (ex: UP) */
+@@ -737,25 +738,27 @@ static void rcu_torture_shuffle_tasks(void)
+ if (rcu_idle_cpu != -1)
+ cpu_clear(rcu_idle_cpu, tmp_mask);
+
+- set_cpus_allowed(current, tmp_mask);
++ set_cpus_allowed_ptr(current, &tmp_mask);
+
+ if (reader_tasks) {
+ for (i = 0; i < nrealreaders; i++)
+ if (reader_tasks[i])
+- set_cpus_allowed(reader_tasks[i], tmp_mask);
++ set_cpus_allowed_ptr(reader_tasks[i],
++ &tmp_mask);
+ }
+
+ if (fakewriter_tasks) {
+ for (i = 0; i < nfakewriters; i++)
+ if (fakewriter_tasks[i])
+- set_cpus_allowed(fakewriter_tasks[i], tmp_mask);
++ set_cpus_allowed_ptr(fakewriter_tasks[i],
++ &tmp_mask);
+ }
+
+ if (writer_task)
+- set_cpus_allowed(writer_task, tmp_mask);
++ set_cpus_allowed_ptr(writer_task, &tmp_mask);
+
+ if (stats_task)
+- set_cpus_allowed(stats_task, tmp_mask);
++ set_cpus_allowed_ptr(stats_task, &tmp_mask);
+
+ if (rcu_idle_cpu == -1)
+ rcu_idle_cpu = num_online_cpus() - 1;
+diff --git a/kernel/resource.c b/kernel/resource.c
+index 82aea81..cee12cc 100644
+--- a/kernel/resource.c
++++ b/kernel/resource.c
+@@ -486,6 +486,24 @@ int adjust_resource(struct resource *res, resource_size_t start, resource_size_t
+
+ EXPORT_SYMBOL(adjust_resource);
+
++/**
++ * resource_alignment - calculate resource's alignment
++ * @res: resource pointer
++ *
++ * Returns alignment on success, 0 (invalid alignment) on failure.
++ */
++resource_size_t resource_alignment(struct resource *res)
++{
++ switch (res->flags & (IORESOURCE_SIZEALIGN | IORESOURCE_STARTALIGN)) {
++ case IORESOURCE_SIZEALIGN:
++ return res->end - res->start + 1;
++ case IORESOURCE_STARTALIGN:
++ return res->start;
++ default:
++ return 0;
++ }
++}
++
+ /*
+ * This is compatibility stuff for IO resources.
+ *
+diff --git a/kernel/sched.c b/kernel/sched.c
+index 8dcdec6..740fb40 100644
+--- a/kernel/sched.c
++++ b/kernel/sched.c
+@@ -66,6 +66,10 @@
+ #include <linux/unistd.h>
+ #include <linux/pagemap.h>
+ #include <linux/hrtimer.h>
++#include <linux/tick.h>
++#include <linux/bootmem.h>
++#include <linux/debugfs.h>
++#include <linux/ctype.h>
+
+ #include <asm/tlb.h>
+ #include <asm/irq_regs.h>
+@@ -114,6 +118,11 @@ unsigned long long __attribute__((weak)) sched_clock(void)
+ */
+ #define DEF_TIMESLICE (100 * HZ / 1000)
+
++/*
++ * single value that denotes runtime == period, ie unlimited time.
++ */
++#define RUNTIME_INF ((u64)~0ULL)
++
+ #ifdef CONFIG_SMP
+ /*
+ * Divide a load by a sched group cpu_power : (load / sg->__cpu_power)
+@@ -155,6 +164,84 @@ struct rt_prio_array {
+ struct list_head queue[MAX_RT_PRIO];
+ };
+
++struct rt_bandwidth {
++ /* nests inside the rq lock: */
++ spinlock_t rt_runtime_lock;
++ ktime_t rt_period;
++ u64 rt_runtime;
++ struct hrtimer rt_period_timer;
++};
++
++static struct rt_bandwidth def_rt_bandwidth;
++
++static int do_sched_rt_period_timer(struct rt_bandwidth *rt_b, int overrun);
++
++static enum hrtimer_restart sched_rt_period_timer(struct hrtimer *timer)
++{
++ struct rt_bandwidth *rt_b =
++ container_of(timer, struct rt_bandwidth, rt_period_timer);
++ ktime_t now;
++ int overrun;
++ int idle = 0;
++
++ for (;;) {
++ now = hrtimer_cb_get_time(timer);
++ overrun = hrtimer_forward(timer, now, rt_b->rt_period);
++
++ if (!overrun)
++ break;
++
++ idle = do_sched_rt_period_timer(rt_b, overrun);
++ }
++
++ return idle ? HRTIMER_NORESTART : HRTIMER_RESTART;
++}
++
++static
++void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime)
++{
++ rt_b->rt_period = ns_to_ktime(period);
++ rt_b->rt_runtime = runtime;
++
++ spin_lock_init(&rt_b->rt_runtime_lock);
++
++ hrtimer_init(&rt_b->rt_period_timer,
++ CLOCK_MONOTONIC, HRTIMER_MODE_REL);
++ rt_b->rt_period_timer.function = sched_rt_period_timer;
++ rt_b->rt_period_timer.cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ;
++}
++
++static void start_rt_bandwidth(struct rt_bandwidth *rt_b)
++{
++ ktime_t now;
++
++ if (rt_b->rt_runtime == RUNTIME_INF)
++ return;
++
++ if (hrtimer_active(&rt_b->rt_period_timer))
++ return;
++
++ spin_lock(&rt_b->rt_runtime_lock);
++ for (;;) {
++ if (hrtimer_active(&rt_b->rt_period_timer))
++ break;
++
++ now = hrtimer_cb_get_time(&rt_b->rt_period_timer);
++ hrtimer_forward(&rt_b->rt_period_timer, now, rt_b->rt_period);
++ hrtimer_start(&rt_b->rt_period_timer,
++ rt_b->rt_period_timer.expires,
++ HRTIMER_MODE_ABS);
++ }
++ spin_unlock(&rt_b->rt_runtime_lock);
++}
++
++#ifdef CONFIG_RT_GROUP_SCHED
++static void destroy_rt_bandwidth(struct rt_bandwidth *rt_b)
++{
++ hrtimer_cancel(&rt_b->rt_period_timer);
++}
++#endif
++
+ #ifdef CONFIG_GROUP_SCHED
+
+ #include <linux/cgroup.h>
+@@ -181,29 +268,39 @@ struct task_group {
+ struct sched_rt_entity **rt_se;
+ struct rt_rq **rt_rq;
+
+- u64 rt_runtime;
++ struct rt_bandwidth rt_bandwidth;
+ #endif
+
+ struct rcu_head rcu;
+ struct list_head list;
++
++ struct task_group *parent;
++ struct list_head siblings;
++ struct list_head children;
+ };
+
++#ifdef CONFIG_USER_SCHED
++
++/*
++ * Root task group.
++ * Every UID task group (including init_task_group aka UID-0) will
++ * be a child to this group.
++ */
++struct task_group root_task_group;
++
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+ /* Default task group's sched entity on each cpu */
+ static DEFINE_PER_CPU(struct sched_entity, init_sched_entity);
+ /* Default task group's cfs_rq on each cpu */
+ static DEFINE_PER_CPU(struct cfs_rq, init_cfs_rq) ____cacheline_aligned_in_smp;
+-
+-static struct sched_entity *init_sched_entity_p[NR_CPUS];
+-static struct cfs_rq *init_cfs_rq_p[NR_CPUS];
+ #endif
+
+ #ifdef CONFIG_RT_GROUP_SCHED
+ static DEFINE_PER_CPU(struct sched_rt_entity, init_sched_rt_entity);
+ static DEFINE_PER_CPU(struct rt_rq, init_rt_rq) ____cacheline_aligned_in_smp;
+-
+-static struct sched_rt_entity *init_sched_rt_entity_p[NR_CPUS];
+-static struct rt_rq *init_rt_rq_p[NR_CPUS];
++#endif
++#else
++#define root_task_group init_task_group
+ #endif
+
+ /* task_group_lock serializes add/remove of task groups and also changes to
+@@ -221,23 +318,15 @@ static DEFINE_MUTEX(doms_cur_mutex);
+ # define INIT_TASK_GROUP_LOAD NICE_0_LOAD
+ #endif
+
++#define MIN_SHARES 2
++
+ static int init_task_group_load = INIT_TASK_GROUP_LOAD;
+ #endif
+
+ /* Default task group.
+ * Every task in system belong to this group at bootup.
+ */
+-struct task_group init_task_group = {
+-#ifdef CONFIG_FAIR_GROUP_SCHED
+- .se = init_sched_entity_p,
+- .cfs_rq = init_cfs_rq_p,
+-#endif
+-
+-#ifdef CONFIG_RT_GROUP_SCHED
+- .rt_se = init_sched_rt_entity_p,
+- .rt_rq = init_rt_rq_p,
+-#endif
+-};
++struct task_group init_task_group;
+
+ /* return group to which a task belongs */
+ static inline struct task_group *task_group(struct task_struct *p)
+@@ -297,8 +386,12 @@ struct cfs_rq {
+
+ struct rb_root tasks_timeline;
+ struct rb_node *rb_leftmost;
+- struct rb_node *rb_load_balance_curr;
+- /* 'curr' points to currently running entity on this cfs_rq.
++
++ struct list_head tasks;
++ struct list_head *balance_iterator;
++
++ /*
++ * 'curr' points to currently running entity on this cfs_rq.
+ * It is set to NULL otherwise (i.e when none are currently running).
+ */
+ struct sched_entity *curr, *next;
+@@ -318,6 +411,43 @@ struct cfs_rq {
+ */
+ struct list_head leaf_cfs_rq_list;
+ struct task_group *tg; /* group that "owns" this runqueue */
++
++#ifdef CONFIG_SMP
++ unsigned long task_weight;
++ unsigned long shares;
++ /*
++ * We need space to build a sched_domain wide view of the full task
++ * group tree, in order to avoid depending on dynamic memory allocation
++ * during the load balancing we place this in the per cpu task group
++ * hierarchy. This limits the load balancing to one instance per cpu,
++ * but more should not be needed anyway.
++ */
++ struct aggregate_struct {
++ /*
++ * load = weight(cpus) * f(tg)
++ *
++ * Where f(tg) is the recursive weight fraction assigned to
++ * this group.
++ */
++ unsigned long load;
++
++ /*
++ * part of the group weight distributed to this span.
++ */
++ unsigned long shares;
++
++ /*
++ * The sum of all runqueue weights within this span.
++ */
++ unsigned long rq_weight;
++
++ /*
++ * Weight contributed by tasks; this is the part we can
++ * influence by moving tasks around.
++ */
++ unsigned long task_weight;
++ } aggregate;
++#endif
+ #endif
+ };
+
+@@ -334,6 +464,9 @@ struct rt_rq {
+ #endif
+ int rt_throttled;
+ u64 rt_time;
++ u64 rt_runtime;
++ /* Nests inside the rq lock: */
++ spinlock_t rt_runtime_lock;
+
+ #ifdef CONFIG_RT_GROUP_SCHED
+ unsigned long rt_nr_boosted;
+@@ -396,6 +529,7 @@ struct rq {
+ unsigned long cpu_load[CPU_LOAD_IDX_MAX];
+ unsigned char idle_at_tick;
+ #ifdef CONFIG_NO_HZ
++ unsigned long last_tick_seen;
+ unsigned char in_nohz_recently;
+ #endif
+ /* capture load from *all* tasks on this cpu: */
+@@ -405,8 +539,6 @@ struct rq {
+
+ struct cfs_rq cfs;
+ struct rt_rq rt;
+- u64 rt_period_expire;
+- int rt_throttled;
+
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+ /* list of leaf cfs_rq on this cpu: */
+@@ -499,6 +631,32 @@ static inline int cpu_of(struct rq *rq)
+ #endif
+ }
+
++#ifdef CONFIG_NO_HZ
++static inline bool nohz_on(int cpu)
++{
++ return tick_get_tick_sched(cpu)->nohz_mode != NOHZ_MODE_INACTIVE;
++}
++
++static inline u64 max_skipped_ticks(struct rq *rq)
++{
++ return nohz_on(cpu_of(rq)) ? jiffies - rq->last_tick_seen + 2 : 1;
++}
++
++static inline void update_last_tick_seen(struct rq *rq)
++{
++ rq->last_tick_seen = jiffies;
++}
++#else
++static inline u64 max_skipped_ticks(struct rq *rq)
++{
++ return 1;
++}
++
++static inline void update_last_tick_seen(struct rq *rq)
++{
++}
++#endif
++
+ /*
+ * Update the per-runqueue clock, as finegrained as the platform can give
+ * us, but without assuming monotonicity, etc.:
+@@ -523,9 +681,12 @@ static void __update_rq_clock(struct rq *rq)
+ /*
+ * Catch too large forward jumps too:
+ */
+- if (unlikely(clock + delta > rq->tick_timestamp + TICK_NSEC)) {
+- if (clock < rq->tick_timestamp + TICK_NSEC)
+- clock = rq->tick_timestamp + TICK_NSEC;
++ u64 max_jump = max_skipped_ticks(rq) * TICK_NSEC;
++ u64 max_time = rq->tick_timestamp + max_jump;
++
++ if (unlikely(clock + delta > max_time)) {
++ if (clock < max_time)
++ clock = max_time;
+ else
+ clock++;
+ rq->clock_overflows++;
+@@ -561,23 +722,6 @@ static void update_rq_clock(struct rq *rq)
+ #define task_rq(p) cpu_rq(task_cpu(p))
+ #define cpu_curr(cpu) (cpu_rq(cpu)->curr)
+
+-unsigned long rt_needs_cpu(int cpu)
+-{
+- struct rq *rq = cpu_rq(cpu);
+- u64 delta;
+-
+- if (!rq->rt_throttled)
+- return 0;
+-
+- if (rq->clock > rq->rt_period_expire)
+- return 1;
+-
+- delta = rq->rt_period_expire - rq->clock;
+- do_div(delta, NSEC_PER_SEC / HZ);
+-
+- return (unsigned long)delta;
+-}
+-
+ /*
+ * Tunables that become constants when CONFIG_SCHED_DEBUG is off:
+ */
+@@ -590,22 +734,137 @@ unsigned long rt_needs_cpu(int cpu)
+ /*
+ * Debugging: various feature bits
+ */
++
++#define SCHED_FEAT(name, enabled) \
++ __SCHED_FEAT_##name ,
++
+ enum {
+- SCHED_FEAT_NEW_FAIR_SLEEPERS = 1,
+- SCHED_FEAT_WAKEUP_PREEMPT = 2,
+- SCHED_FEAT_START_DEBIT = 4,
+- SCHED_FEAT_HRTICK = 8,
+- SCHED_FEAT_DOUBLE_TICK = 16,
++#include "sched_features.h"
+ };
+
++#undef SCHED_FEAT
++
++#define SCHED_FEAT(name, enabled) \
++ (1UL << __SCHED_FEAT_##name) * enabled |
++
+ const_debug unsigned int sysctl_sched_features =
+- SCHED_FEAT_NEW_FAIR_SLEEPERS * 1 |
+- SCHED_FEAT_WAKEUP_PREEMPT * 1 |
+- SCHED_FEAT_START_DEBIT * 1 |
+- SCHED_FEAT_HRTICK * 1 |
+- SCHED_FEAT_DOUBLE_TICK * 0;
++#include "sched_features.h"
++ 0;
++
++#undef SCHED_FEAT
++
++#ifdef CONFIG_SCHED_DEBUG
++#define SCHED_FEAT(name, enabled) \
++ #name ,
++
++__read_mostly char *sched_feat_names[] = {
++#include "sched_features.h"
++ NULL
++};
++
++#undef SCHED_FEAT
+
+-#define sched_feat(x) (sysctl_sched_features & SCHED_FEAT_##x)
++int sched_feat_open(struct inode *inode, struct file *filp)
++{
++ filp->private_data = inode->i_private;
++ return 0;
++}
++
++static ssize_t
++sched_feat_read(struct file *filp, char __user *ubuf,
++ size_t cnt, loff_t *ppos)
++{
++ char *buf;
++ int r = 0;
++ int len = 0;
++ int i;
++
++ for (i = 0; sched_feat_names[i]; i++) {
++ len += strlen(sched_feat_names[i]);
++ len += 4;
++ }
++
++ buf = kmalloc(len + 2, GFP_KERNEL);
++ if (!buf)
++ return -ENOMEM;
++
++ for (i = 0; sched_feat_names[i]; i++) {
++ if (sysctl_sched_features & (1UL << i))
++ r += sprintf(buf + r, "%s ", sched_feat_names[i]);
++ else
++ r += sprintf(buf + r, "NO_%s ", sched_feat_names[i]);
++ }
++
++ r += sprintf(buf + r, "\n");
++ WARN_ON(r >= len + 2);
++
++ r = simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
++
++ kfree(buf);
++
++ return r;
++}
++
++static ssize_t
++sched_feat_write(struct file *filp, const char __user *ubuf,
++ size_t cnt, loff_t *ppos)
++{
++ char buf[64];
++ char *cmp = buf;
++ int neg = 0;
++ int i;
++
++ if (cnt > 63)
++ cnt = 63;
++
++ if (copy_from_user(&buf, ubuf, cnt))
++ return -EFAULT;
++
++ buf[cnt] = 0;
++
++ if (strncmp(buf, "NO_", 3) == 0) {
++ neg = 1;
++ cmp += 3;
++ }
++
++ for (i = 0; sched_feat_names[i]; i++) {
++ int len = strlen(sched_feat_names[i]);
++
++ if (strncmp(cmp, sched_feat_names[i], len) == 0) {
++ if (neg)
++ sysctl_sched_features &= ~(1UL << i);
++ else
++ sysctl_sched_features |= (1UL << i);
++ break;
++ }
++ }
++
++ if (!sched_feat_names[i])
++ return -EINVAL;
++
++ filp->f_pos += cnt;
++
++ return cnt;
++}
++
++static struct file_operations sched_feat_fops = {
++ .open = sched_feat_open,
++ .read = sched_feat_read,
++ .write = sched_feat_write,
++};
++
++static __init int sched_init_debug(void)
++{
++ debugfs_create_file("sched_features", 0644, NULL, NULL,
++ &sched_feat_fops);
++
++ return 0;
++}
++late_initcall(sched_init_debug);
++
++#endif
++
++#define sched_feat(x) (sysctl_sched_features & (1UL << __SCHED_FEAT_##x))
+
+ /*
+ * Number of tasks to iterate in a single balance run.
+@@ -627,16 +886,52 @@ static __read_mostly int scheduler_running;
+ */
+ int sysctl_sched_rt_runtime = 950000;
+
+-/*
+- * single value that denotes runtime == period, ie unlimited time.
+- */
+-#define RUNTIME_INF ((u64)~0ULL)
++static inline u64 global_rt_period(void)
++{
++ return (u64)sysctl_sched_rt_period * NSEC_PER_USEC;
++}
++
++static inline u64 global_rt_runtime(void)
++{
++ if (sysctl_sched_rt_period < 0)
++ return RUNTIME_INF;
++
++ return (u64)sysctl_sched_rt_runtime * NSEC_PER_USEC;
++}
++
++static const unsigned long long time_sync_thresh = 100000;
++
++static DEFINE_PER_CPU(unsigned long long, time_offset);
++static DEFINE_PER_CPU(unsigned long long, prev_cpu_time);
+
+ /*
+- * For kernel-internal use: high-speed (but slightly incorrect) per-cpu
+- * clock constructed from sched_clock():
++ * Global lock which we take every now and then to synchronize
++ * the CPUs time. This method is not warp-safe, but it's good
++ * enough to synchronize slowly diverging time sources and thus
++ * it's good enough for tracing:
+ */
+-unsigned long long cpu_clock(int cpu)
++static DEFINE_SPINLOCK(time_sync_lock);
++static unsigned long long prev_global_time;
++
++static unsigned long long __sync_cpu_clock(cycles_t time, int cpu)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&time_sync_lock, flags);
++
++ if (time < prev_global_time) {
++ per_cpu(time_offset, cpu) += prev_global_time - time;
++ time = prev_global_time;
++ } else {
++ prev_global_time = time;
++ }
++
++ spin_unlock_irqrestore(&time_sync_lock, flags);
++
++ return time;
++}
++
++static unsigned long long __cpu_clock(int cpu)
+ {
+ unsigned long long now;
+ unsigned long flags;
+@@ -657,6 +952,24 @@ unsigned long long cpu_clock(int cpu)
+
+ return now;
+ }
++
++/*
++ * For kernel-internal use: high-speed (but slightly incorrect) per-cpu
++ * clock constructed from sched_clock():
++ */
++unsigned long long cpu_clock(int cpu)
++{
++ unsigned long long prev_cpu_time, time, delta_time;
++
++ prev_cpu_time = per_cpu(prev_cpu_time, cpu);
++ time = __cpu_clock(cpu) + per_cpu(time_offset, cpu);
++ delta_time = time-prev_cpu_time;
++
++ if (unlikely(delta_time > time_sync_thresh))
++ time = __sync_cpu_clock(time, cpu);
++
++ return time;
++}
+ EXPORT_SYMBOL_GPL(cpu_clock);
+
+ #ifndef prepare_arch_switch
+@@ -1116,6 +1429,9 @@ static void __resched_task(struct task_struct *p, int tif_bit)
+ */
+ #define SRR(x, y) (((x) + (1UL << ((y) - 1))) >> (y))
+
++/*
++ * delta *= weight / lw
++ */
+ static unsigned long
+ calc_delta_mine(unsigned long delta_exec, unsigned long weight,
+ struct load_weight *lw)
+@@ -1138,12 +1454,6 @@ calc_delta_mine(unsigned long delta_exec, unsigned long weight,
+ return (unsigned long)min(tmp, (u64)(unsigned long)LONG_MAX);
+ }
+
+-static inline unsigned long
+-calc_delta_fair(unsigned long delta_exec, struct load_weight *lw)
+-{
+- return calc_delta_mine(delta_exec, NICE_0_LOAD, lw);
+-}
+-
+ static inline void update_load_add(struct load_weight *lw, unsigned long inc)
+ {
+ lw->weight += inc;
+@@ -1241,11 +1551,347 @@ static void cpuacct_charge(struct task_struct *tsk, u64 cputime);
+ static inline void cpuacct_charge(struct task_struct *tsk, u64 cputime) {}
+ #endif
+
++static inline void inc_cpu_load(struct rq *rq, unsigned long load)
++{
++ update_load_add(&rq->load, load);
++}
++
++static inline void dec_cpu_load(struct rq *rq, unsigned long load)
++{
++ update_load_sub(&rq->load, load);
++}
++
+ #ifdef CONFIG_SMP
+ static unsigned long source_load(int cpu, int type);
+ static unsigned long target_load(int cpu, int type);
+ static unsigned long cpu_avg_load_per_task(int cpu);
+ static int task_hot(struct task_struct *p, u64 now, struct sched_domain *sd);
++
++#ifdef CONFIG_FAIR_GROUP_SCHED
++
++/*
++ * Group load balancing.
++ *
++ * We calculate a few balance domain wide aggregate numbers; load and weight.
++ * Given the pictures below, and assuming each item has equal weight:
++ *
++ * root 1 - thread
++ * / | \ A - group
++ * A 1 B
++ * /|\ / \
++ * C 2 D 3 4
++ * | |
++ * 5 6
++ *
++ * load:
++ * A and B get 1/3-rd of the total load. C and D get 1/3-rd of A's 1/3-rd,
++ * which equals 1/9-th of the total load.
++ *
++ * shares:
++ * The weight of this group on the selected cpus.
++ *
++ * rq_weight:
++ * Direct sum of all the cpu's their rq weight, e.g. A would get 3 while
++ * B would get 2.
++ *
++ * task_weight:
++ * Part of the rq_weight contributed by tasks; all groups except B would
++ * get 1, B gets 2.
++ */
++
++static inline struct aggregate_struct *
++aggregate(struct task_group *tg, struct sched_domain *sd)
++{
++ return &tg->cfs_rq[sd->first_cpu]->aggregate;
++}
++
++typedef void (*aggregate_func)(struct task_group *, struct sched_domain *);
++
++/*
++ * Iterate the full tree, calling @down when first entering a node and @up when
++ * leaving it for the final time.
++ */
++static
++void aggregate_walk_tree(aggregate_func down, aggregate_func up,
++ struct sched_domain *sd)
++{
++ struct task_group *parent, *child;
++
++ rcu_read_lock();
++ parent = &root_task_group;
++down:
++ (*down)(parent, sd);
++ list_for_each_entry_rcu(child, &parent->children, siblings) {
++ parent = child;
++ goto down;
++
++up:
++ continue;
++ }
++ (*up)(parent, sd);
++
++ child = parent;
++ parent = parent->parent;
++ if (parent)
++ goto up;
++ rcu_read_unlock();
++}
++
++/*
++ * Calculate the aggregate runqueue weight.
++ */
++static
++void aggregate_group_weight(struct task_group *tg, struct sched_domain *sd)
++{
++ unsigned long rq_weight = 0;
++ unsigned long task_weight = 0;
++ int i;
++
++ for_each_cpu_mask(i, sd->span) {
++ rq_weight += tg->cfs_rq[i]->load.weight;
++ task_weight += tg->cfs_rq[i]->task_weight;
++ }
++
++ aggregate(tg, sd)->rq_weight = rq_weight;
++ aggregate(tg, sd)->task_weight = task_weight;
++}
++
++/*
++ * Compute the weight of this group on the given cpus.
++ */
++static
++void aggregate_group_shares(struct task_group *tg, struct sched_domain *sd)
++{
++ unsigned long shares = 0;
++ int i;
++
++ for_each_cpu_mask(i, sd->span)
++ shares += tg->cfs_rq[i]->shares;
++
++ if ((!shares && aggregate(tg, sd)->rq_weight) || shares > tg->shares)
++ shares = tg->shares;
++
++ aggregate(tg, sd)->shares = shares;
++}
++
++/*
++ * Compute the load fraction assigned to this group, relies on the aggregate
++ * weight and this group's parent's load, i.e. top-down.
++ */
++static
++void aggregate_group_load(struct task_group *tg, struct sched_domain *sd)
++{
++ unsigned long load;
++
++ if (!tg->parent) {
++ int i;
++
++ load = 0;
++ for_each_cpu_mask(i, sd->span)
++ load += cpu_rq(i)->load.weight;
++
++ } else {
++ load = aggregate(tg->parent, sd)->load;
++
++ /*
++ * shares is our weight in the parent's rq so
++ * shares/parent->rq_weight gives our fraction of the load
++ */
++ load *= aggregate(tg, sd)->shares;
++ load /= aggregate(tg->parent, sd)->rq_weight + 1;
++ }
++
++ aggregate(tg, sd)->load = load;
++}
++
++static void __set_se_shares(struct sched_entity *se, unsigned long shares);
++
++/*
++ * Calculate and set the cpu's group shares.
++ */
++static void
++__update_group_shares_cpu(struct task_group *tg, struct sched_domain *sd,
++ int tcpu)
++{
++ int boost = 0;
++ unsigned long shares;
++ unsigned long rq_weight;
++
++ if (!tg->se[tcpu])
++ return;
++
++ rq_weight = tg->cfs_rq[tcpu]->load.weight;
++
++ /*
++ * If there are currently no tasks on the cpu pretend there is one of
++ * average load so that when a new task gets to run here it will not
++ * get delayed by group starvation.
++ */
++ if (!rq_weight) {
++ boost = 1;
++ rq_weight = NICE_0_LOAD;
++ }
++
++ /*
++ * \Sum shares * rq_weight
++ * shares = -----------------------
++ * \Sum rq_weight
++ *
++ */
++ shares = aggregate(tg, sd)->shares * rq_weight;
++ shares /= aggregate(tg, sd)->rq_weight + 1;
++
++ /*
++ * record the actual number of shares, not the boosted amount.
++ */
++ tg->cfs_rq[tcpu]->shares = boost ? 0 : shares;
++
++ if (shares < MIN_SHARES)
++ shares = MIN_SHARES;
++
++ __set_se_shares(tg->se[tcpu], shares);
++}
++
++/*
++ * Re-adjust the weights on the cpu the task came from and on the cpu the
++ * task went to.
++ */
++static void
++__move_group_shares(struct task_group *tg, struct sched_domain *sd,
++ int scpu, int dcpu)
++{
++ unsigned long shares;
++
++ shares = tg->cfs_rq[scpu]->shares + tg->cfs_rq[dcpu]->shares;
++
++ __update_group_shares_cpu(tg, sd, scpu);
++ __update_group_shares_cpu(tg, sd, dcpu);
++
++ /*
++ * ensure we never loose shares due to rounding errors in the
++ * above redistribution.
++ */
++ shares -= tg->cfs_rq[scpu]->shares + tg->cfs_rq[dcpu]->shares;
++ if (shares)
++ tg->cfs_rq[dcpu]->shares += shares;
++}
++
++/*
++ * Because changing a group's shares changes the weight of the super-group
++ * we need to walk up the tree and change all shares until we hit the root.
++ */
++static void
++move_group_shares(struct task_group *tg, struct sched_domain *sd,
++ int scpu, int dcpu)
++{
++ while (tg) {
++ __move_group_shares(tg, sd, scpu, dcpu);
++ tg = tg->parent;
++ }
++}
++
++static
++void aggregate_group_set_shares(struct task_group *tg, struct sched_domain *sd)
++{
++ unsigned long shares = aggregate(tg, sd)->shares;
++ int i;
++
++ for_each_cpu_mask(i, sd->span) {
++ struct rq *rq = cpu_rq(i);
++ unsigned long flags;
++
++ spin_lock_irqsave(&rq->lock, flags);
++ __update_group_shares_cpu(tg, sd, i);
++ spin_unlock_irqrestore(&rq->lock, flags);
++ }
++
++ aggregate_group_shares(tg, sd);
++
++ /*
++ * ensure we never loose shares due to rounding errors in the
++ * above redistribution.
++ */
++ shares -= aggregate(tg, sd)->shares;
++ if (shares) {
++ tg->cfs_rq[sd->first_cpu]->shares += shares;
++ aggregate(tg, sd)->shares += shares;
++ }
++}
++
++/*
++ * Calculate the accumulative weight and recursive load of each task group
++ * while walking down the tree.
++ */
++static
++void aggregate_get_down(struct task_group *tg, struct sched_domain *sd)
++{
++ aggregate_group_weight(tg, sd);
++ aggregate_group_shares(tg, sd);
++ aggregate_group_load(tg, sd);
++}
++
++/*
++ * Rebalance the cpu shares while walking back up the tree.
++ */
++static
++void aggregate_get_up(struct task_group *tg, struct sched_domain *sd)
++{
++ aggregate_group_set_shares(tg, sd);
++}
++
++static DEFINE_PER_CPU(spinlock_t, aggregate_lock);
++
++static void __init init_aggregate(void)
++{
++ int i;
++
++ for_each_possible_cpu(i)
++ spin_lock_init(&per_cpu(aggregate_lock, i));
++}
++
++static int get_aggregate(struct sched_domain *sd)
++{
++ if (!spin_trylock(&per_cpu(aggregate_lock, sd->first_cpu)))
++ return 0;
++
++ aggregate_walk_tree(aggregate_get_down, aggregate_get_up, sd);
++ return 1;
++}
++
++static void put_aggregate(struct sched_domain *sd)
++{
++ spin_unlock(&per_cpu(aggregate_lock, sd->first_cpu));
++}
++
++static void cfs_rq_set_shares(struct cfs_rq *cfs_rq, unsigned long shares)
++{
++ cfs_rq->shares = shares;
++}
++
++#else
++
++static inline void init_aggregate(void)
++{
++}
++
++static inline int get_aggregate(struct sched_domain *sd)
++{
++ return 0;
++}
++
++static inline void put_aggregate(struct sched_domain *sd)
++{
++}
++#endif
++
++#else /* CONFIG_SMP */
++
++#ifdef CONFIG_FAIR_GROUP_SCHED
++static void cfs_rq_set_shares(struct cfs_rq *cfs_rq, unsigned long shares)
++{
++}
++#endif
++
+ #endif /* CONFIG_SMP */
+
+ #include "sched_stats.h"
+@@ -1258,26 +1904,14 @@ static int task_hot(struct task_struct *p, u64 now, struct sched_domain *sd);
+
+ #define sched_class_highest (&rt_sched_class)
+
+-static inline void inc_load(struct rq *rq, const struct task_struct *p)
+-{
+- update_load_add(&rq->load, p->se.load.weight);
+-}
+-
+-static inline void dec_load(struct rq *rq, const struct task_struct *p)
+-{
+- update_load_sub(&rq->load, p->se.load.weight);
+-}
+-
+-static void inc_nr_running(struct task_struct *p, struct rq *rq)
++static void inc_nr_running(struct rq *rq)
+ {
+ rq->nr_running++;
+- inc_load(rq, p);
+ }
+
+-static void dec_nr_running(struct task_struct *p, struct rq *rq)
++static void dec_nr_running(struct rq *rq)
+ {
+ rq->nr_running--;
+- dec_load(rq, p);
+ }
+
+ static void set_load_weight(struct task_struct *p)
+@@ -1369,7 +2003,7 @@ static void activate_task(struct rq *rq, struct task_struct *p, int wakeup)
+ rq->nr_uninterruptible--;
+
+ enqueue_task(rq, p, wakeup);
+- inc_nr_running(p, rq);
++ inc_nr_running(rq);
+ }
+
+ /*
+@@ -1381,7 +2015,7 @@ static void deactivate_task(struct rq *rq, struct task_struct *p, int sleep)
+ rq->nr_uninterruptible++;
+
+ dequeue_task(rq, p, sleep);
+- dec_nr_running(p, rq);
++ dec_nr_running(rq);
+ }
+
+ /**
+@@ -1438,7 +2072,7 @@ task_hot(struct task_struct *p, u64 now, struct sched_domain *sd)
+ /*
+ * Buddy candidates are cache hot:
+ */
+- if (&p->se == cfs_rq_of(&p->se)->next)
++ if (sched_feat(CACHE_HOT_BUDDY) && (&p->se == cfs_rq_of(&p->se)->next))
+ return 1;
+
+ if (p->sched_class != &fair_sched_class)
+@@ -1728,17 +2362,17 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p, int this_cpu)
+ * find_idlest_cpu - find the idlest cpu among the cpus in group.
+ */
+ static int
+-find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu)
++find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu,
++ cpumask_t *tmp)
+ {
+- cpumask_t tmp;
+ unsigned long load, min_load = ULONG_MAX;
+ int idlest = -1;
+ int i;
+
+ /* Traverse only the allowed CPUs */
+- cpus_and(tmp, group->cpumask, p->cpus_allowed);
++ cpus_and(*tmp, group->cpumask, p->cpus_allowed);
+
+- for_each_cpu_mask(i, tmp) {
++ for_each_cpu_mask(i, *tmp) {
+ load = weighted_cpuload(i);
+
+ if (load < min_load || (load == min_load && i == this_cpu)) {
+@@ -1777,7 +2411,7 @@ static int sched_balance_self(int cpu, int flag)
+ }
+
+ while (sd) {
+- cpumask_t span;
++ cpumask_t span, tmpmask;
+ struct sched_group *group;
+ int new_cpu, weight;
+
+@@ -1793,7 +2427,7 @@ static int sched_balance_self(int cpu, int flag)
+ continue;
+ }
+
+- new_cpu = find_idlest_cpu(group, t, cpu);
++ new_cpu = find_idlest_cpu(group, t, cpu, &tmpmask);
+ if (new_cpu == -1 || new_cpu == cpu) {
+ /* Now try balancing at a lower domain level of cpu */
+ sd = sd->child;
+@@ -1839,6 +2473,9 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync)
+ long old_state;
+ struct rq *rq;
+
++ if (!sched_feat(SYNC_WAKEUPS))
++ sync = 0;
++
+ smp_wmb();
+ rq = task_rq_lock(p, &flags);
+ old_state = p->state;
+@@ -1955,6 +2592,7 @@ static void __sched_fork(struct task_struct *p)
+
+ INIT_LIST_HEAD(&p->rt.run_list);
+ p->se.on_rq = 0;
++ INIT_LIST_HEAD(&p->se.group_node);
+
+ #ifdef CONFIG_PREEMPT_NOTIFIERS
+ INIT_HLIST_HEAD(&p->preempt_notifiers);
+@@ -2030,7 +2668,7 @@ void wake_up_new_task(struct task_struct *p, unsigned long clone_flags)
+ * management (if any):
+ */
+ p->sched_class->task_new(rq, p);
+- inc_nr_running(p, rq);
++ inc_nr_running(rq);
+ }
+ check_preempt_curr(rq, p);
+ #ifdef CONFIG_SMP
+@@ -2674,7 +3312,7 @@ static int move_one_task(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ static struct sched_group *
+ find_busiest_group(struct sched_domain *sd, int this_cpu,
+ unsigned long *imbalance, enum cpu_idle_type idle,
+- int *sd_idle, cpumask_t *cpus, int *balance)
++ int *sd_idle, const cpumask_t *cpus, int *balance)
+ {
+ struct sched_group *busiest = NULL, *this = NULL, *group = sd->groups;
+ unsigned long max_load, avg_load, total_load, this_load, total_pwr;
+@@ -2975,7 +3613,7 @@ ret:
+ */
+ static struct rq *
+ find_busiest_queue(struct sched_group *group, enum cpu_idle_type idle,
+- unsigned long imbalance, cpumask_t *cpus)
++ unsigned long imbalance, const cpumask_t *cpus)
+ {
+ struct rq *busiest = NULL, *rq;
+ unsigned long max_load = 0;
+@@ -3014,14 +3652,18 @@ find_busiest_queue(struct sched_group *group, enum cpu_idle_type idle,
+ */
+ static int load_balance(int this_cpu, struct rq *this_rq,
+ struct sched_domain *sd, enum cpu_idle_type idle,
+- int *balance)
++ int *balance, cpumask_t *cpus)
+ {
+ int ld_moved, all_pinned = 0, active_balance = 0, sd_idle = 0;
+ struct sched_group *group;
+ unsigned long imbalance;
+ struct rq *busiest;
+- cpumask_t cpus = CPU_MASK_ALL;
+ unsigned long flags;
++ int unlock_aggregate;
++
++ cpus_setall(*cpus);
++
++ unlock_aggregate = get_aggregate(sd);
+
+ /*
+ * When power savings policy is enabled for the parent domain, idle
+@@ -3037,7 +3679,7 @@ static int load_balance(int this_cpu, struct rq *this_rq,
+
+ redo:
+ group = find_busiest_group(sd, this_cpu, &imbalance, idle, &sd_idle,
+- &cpus, balance);
++ cpus, balance);
+
+ if (*balance == 0)
+ goto out_balanced;
+@@ -3047,7 +3689,7 @@ redo:
+ goto out_balanced;
+ }
+
+- busiest = find_busiest_queue(group, idle, imbalance, &cpus);
++ busiest = find_busiest_queue(group, idle, imbalance, cpus);
+ if (!busiest) {
+ schedstat_inc(sd, lb_nobusyq[idle]);
+ goto out_balanced;
+@@ -3080,8 +3722,8 @@ redo:
+
+ /* All tasks on this runqueue were pinned by CPU affinity */
+ if (unlikely(all_pinned)) {
+- cpu_clear(cpu_of(busiest), cpus);
+- if (!cpus_empty(cpus))
++ cpu_clear(cpu_of(busiest), *cpus);
++ if (!cpus_empty(*cpus))
+ goto redo;
+ goto out_balanced;
+ }
+@@ -3138,8 +3780,9 @@ redo:
+
+ if (!ld_moved && !sd_idle && sd->flags & SD_SHARE_CPUPOWER &&
+ !test_sd_parent(sd, SD_POWERSAVINGS_BALANCE))
+- return -1;
+- return ld_moved;
++ ld_moved = -1;
++
++ goto out;
+
+ out_balanced:
+ schedstat_inc(sd, lb_balanced[idle]);
+@@ -3154,8 +3797,13 @@ out_one_pinned:
+
+ if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER &&
+ !test_sd_parent(sd, SD_POWERSAVINGS_BALANCE))
+- return -1;
+- return 0;
++ ld_moved = -1;
++ else
++ ld_moved = 0;
++out:
++ if (unlock_aggregate)
++ put_aggregate(sd);
++ return ld_moved;
+ }
+
+ /*
+@@ -3166,7 +3814,8 @@ out_one_pinned:
+ * this_rq is locked.
+ */
+ static int
+-load_balance_newidle(int this_cpu, struct rq *this_rq, struct sched_domain *sd)
++load_balance_newidle(int this_cpu, struct rq *this_rq, struct sched_domain *sd,
++ cpumask_t *cpus)
+ {
+ struct sched_group *group;
+ struct rq *busiest = NULL;
+@@ -3174,7 +3823,8 @@ load_balance_newidle(int this_cpu, struct rq *this_rq, struct sched_domain *sd)
+ int ld_moved = 0;
+ int sd_idle = 0;
+ int all_pinned = 0;
+- cpumask_t cpus = CPU_MASK_ALL;
++
++ cpus_setall(*cpus);
+
+ /*
+ * When power savings policy is enabled for the parent domain, idle
+@@ -3189,14 +3839,13 @@ load_balance_newidle(int this_cpu, struct rq *this_rq, struct sched_domain *sd)
+ schedstat_inc(sd, lb_count[CPU_NEWLY_IDLE]);
+ redo:
+ group = find_busiest_group(sd, this_cpu, &imbalance, CPU_NEWLY_IDLE,
+- &sd_idle, &cpus, NULL);
++ &sd_idle, cpus, NULL);
+ if (!group) {
+ schedstat_inc(sd, lb_nobusyg[CPU_NEWLY_IDLE]);
+ goto out_balanced;
+ }
+
+- busiest = find_busiest_queue(group, CPU_NEWLY_IDLE, imbalance,
+- &cpus);
++ busiest = find_busiest_queue(group, CPU_NEWLY_IDLE, imbalance, cpus);
+ if (!busiest) {
+ schedstat_inc(sd, lb_nobusyq[CPU_NEWLY_IDLE]);
+ goto out_balanced;
+@@ -3218,8 +3867,8 @@ redo:
+ spin_unlock(&busiest->lock);
+
+ if (unlikely(all_pinned)) {
+- cpu_clear(cpu_of(busiest), cpus);
+- if (!cpus_empty(cpus))
++ cpu_clear(cpu_of(busiest), *cpus);
++ if (!cpus_empty(*cpus))
+ goto redo;
+ }
+ }
+@@ -3253,6 +3902,7 @@ static void idle_balance(int this_cpu, struct rq *this_rq)
+ struct sched_domain *sd;
+ int pulled_task = -1;
+ unsigned long next_balance = jiffies + HZ;
++ cpumask_t tmpmask;
+
+ for_each_domain(this_cpu, sd) {
+ unsigned long interval;
+@@ -3262,8 +3912,8 @@ static void idle_balance(int this_cpu, struct rq *this_rq)
+
+ if (sd->flags & SD_BALANCE_NEWIDLE)
+ /* If we've pulled tasks over stop searching: */
+- pulled_task = load_balance_newidle(this_cpu,
+- this_rq, sd);
++ pulled_task = load_balance_newidle(this_cpu, this_rq,
++ sd, &tmpmask);
+
+ interval = msecs_to_jiffies(sd->balance_interval);
+ if (time_after(next_balance, sd->last_balance + interval))
+@@ -3422,6 +4072,7 @@ static void rebalance_domains(int cpu, enum cpu_idle_type idle)
+ /* Earliest time when we have to do rebalance again */
+ unsigned long next_balance = jiffies + 60*HZ;
+ int update_next_balance = 0;
++ cpumask_t tmp;
+
+ for_each_domain(cpu, sd) {
+ if (!(sd->flags & SD_LOAD_BALANCE))
+@@ -3445,7 +4096,7 @@ static void rebalance_domains(int cpu, enum cpu_idle_type idle)
+ }
+
+ if (time_after_eq(jiffies, sd->last_balance + interval)) {
+- if (load_balance(cpu, rq, sd, idle, &balance)) {
++ if (load_balance(cpu, rq, sd, idle, &balance, &tmp)) {
+ /*
+ * We've pulled tasks over so either we're no
+ * longer idle, or one of our SMT siblings is
+@@ -3561,7 +4212,7 @@ static inline void trigger_load_balance(struct rq *rq, int cpu)
+ */
+ int ilb = first_cpu(nohz.cpu_mask);
+
+- if (ilb != NR_CPUS)
++ if (ilb < nr_cpu_ids)
+ resched_cpu(ilb);
+ }
+ }
+@@ -3765,9 +4416,9 @@ void scheduler_tick(void)
+ rq->clock_underflows++;
+ }
+ rq->tick_timestamp = rq->clock;
++ update_last_tick_seen(rq);
+ update_cpu_load(rq);
+ curr->sched_class->task_tick(rq, curr, 0);
+- update_sched_rt_period(rq);
+ spin_unlock(&rq->lock);
+
+ #ifdef CONFIG_SMP
+@@ -4367,10 +5018,8 @@ void set_user_nice(struct task_struct *p, long nice)
+ goto out_unlock;
+ }
+ on_rq = p->se.on_rq;
+- if (on_rq) {
++ if (on_rq)
+ dequeue_task(rq, p, 0);
+- dec_load(rq, p);
+- }
+
+ p->static_prio = NICE_TO_PRIO(nice);
+ set_load_weight(p);
+@@ -4380,7 +5029,6 @@ void set_user_nice(struct task_struct *p, long nice)
+
+ if (on_rq) {
+ enqueue_task(rq, p, 0);
+- inc_load(rq, p);
+ /*
+ * If the task increased its priority or is running and
+ * lowered its priority, then reschedule its CPU:
+@@ -4602,7 +5250,7 @@ recheck:
+ * Do not allow realtime tasks into groups that have no runtime
+ * assigned.
+ */
+- if (rt_policy(policy) && task_group(p)->rt_runtime == 0)
++ if (rt_policy(policy) && task_group(p)->rt_bandwidth.rt_runtime == 0)
+ return -EPERM;
+ #endif
+
+@@ -4764,9 +5412,10 @@ out_unlock:
+ return retval;
+ }
+
+-long sched_setaffinity(pid_t pid, cpumask_t new_mask)
++long sched_setaffinity(pid_t pid, const cpumask_t *in_mask)
+ {
+ cpumask_t cpus_allowed;
++ cpumask_t new_mask = *in_mask;
+ struct task_struct *p;
+ int retval;
+
+@@ -4797,13 +5446,13 @@ long sched_setaffinity(pid_t pid, cpumask_t new_mask)
+ if (retval)
+ goto out_unlock;
+
+- cpus_allowed = cpuset_cpus_allowed(p);
++ cpuset_cpus_allowed(p, &cpus_allowed);
+ cpus_and(new_mask, new_mask, cpus_allowed);
+ again:
+- retval = set_cpus_allowed(p, new_mask);
++ retval = set_cpus_allowed_ptr(p, &new_mask);
+
+ if (!retval) {
+- cpus_allowed = cpuset_cpus_allowed(p);
++ cpuset_cpus_allowed(p, &cpus_allowed);
+ if (!cpus_subset(new_mask, cpus_allowed)) {
+ /*
+ * We must have raced with a concurrent cpuset
+@@ -4847,7 +5496,7 @@ asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len,
+ if (retval)
+ return retval;
+
+- return sched_setaffinity(pid, new_mask);
++ return sched_setaffinity(pid, &new_mask);
+ }
+
+ /*
+@@ -5309,7 +5958,6 @@ static inline void sched_init_granularity(void)
+ sysctl_sched_latency = limit;
+
+ sysctl_sched_wakeup_granularity *= factor;
+- sysctl_sched_batch_wakeup_granularity *= factor;
+ }
+
+ #ifdef CONFIG_SMP
+@@ -5338,7 +5986,7 @@ static inline void sched_init_granularity(void)
+ * task must not exit() & deallocate itself prematurely. The
+ * call is not atomic; no spinlocks may be held.
+ */
+-int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask)
++int set_cpus_allowed_ptr(struct task_struct *p, const cpumask_t *new_mask)
+ {
+ struct migration_req req;
+ unsigned long flags;
+@@ -5346,23 +5994,23 @@ int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask)
+ int ret = 0;
+
+ rq = task_rq_lock(p, &flags);
+- if (!cpus_intersects(new_mask, cpu_online_map)) {
++ if (!cpus_intersects(*new_mask, cpu_online_map)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (p->sched_class->set_cpus_allowed)
+- p->sched_class->set_cpus_allowed(p, &new_mask);
++ p->sched_class->set_cpus_allowed(p, new_mask);
+ else {
+- p->cpus_allowed = new_mask;
+- p->rt.nr_cpus_allowed = cpus_weight(new_mask);
++ p->cpus_allowed = *new_mask;
++ p->rt.nr_cpus_allowed = cpus_weight(*new_mask);
+ }
+
+ /* Can the task run on the task's current CPU? If so, we're done */
+- if (cpu_isset(task_cpu(p), new_mask))
++ if (cpu_isset(task_cpu(p), *new_mask))
+ goto out;
+
+- if (migrate_task(p, any_online_cpu(new_mask), &req)) {
++ if (migrate_task(p, any_online_cpu(*new_mask), &req)) {
+ /* Need help from migration thread: drop lock and wait. */
+ task_rq_unlock(rq, &flags);
+ wake_up_process(rq->migration_thread);
+@@ -5375,7 +6023,7 @@ out:
+
+ return ret;
+ }
+-EXPORT_SYMBOL_GPL(set_cpus_allowed);
++EXPORT_SYMBOL_GPL(set_cpus_allowed_ptr);
+
+ /*
+ * Move (not current) task off this cpu, onto dest cpu. We're doing
+@@ -5513,12 +6161,14 @@ static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p)
+ dest_cpu = any_online_cpu(mask);
+
+ /* On any allowed CPU? */
+- if (dest_cpu == NR_CPUS)
++ if (dest_cpu >= nr_cpu_ids)
+ dest_cpu = any_online_cpu(p->cpus_allowed);
+
+ /* No more Mr. Nice Guy. */
+- if (dest_cpu == NR_CPUS) {
+- cpumask_t cpus_allowed = cpuset_cpus_allowed_locked(p);
++ if (dest_cpu >= nr_cpu_ids) {
++ cpumask_t cpus_allowed;
++
++ cpuset_cpus_allowed_locked(p, &cpus_allowed);
+ /*
+ * Try to stay on the same cpuset, where the
+ * current cpuset may be a subset of all cpus.
+@@ -5554,7 +6204,7 @@ static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p)
+ */
+ static void migrate_nr_uninterruptible(struct rq *rq_src)
+ {
+- struct rq *rq_dest = cpu_rq(any_online_cpu(CPU_MASK_ALL));
++ struct rq *rq_dest = cpu_rq(any_online_cpu(*CPU_MASK_ALL_PTR));
+ unsigned long flags;
+
+ local_irq_save(flags);
+@@ -5966,20 +6616,16 @@ void __init migration_init(void)
+
+ #ifdef CONFIG_SMP
+
+-/* Number of possible processor ids */
+-int nr_cpu_ids __read_mostly = NR_CPUS;
+-EXPORT_SYMBOL(nr_cpu_ids);
+-
+ #ifdef CONFIG_SCHED_DEBUG
+
+-static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level)
++static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level,
++ cpumask_t *groupmask)
+ {
+ struct sched_group *group = sd->groups;
+- cpumask_t groupmask;
+- char str[NR_CPUS];
++ char str[256];
+
+- cpumask_scnprintf(str, NR_CPUS, sd->span);
+- cpus_clear(groupmask);
++ cpulist_scnprintf(str, sizeof(str), sd->span);
++ cpus_clear(*groupmask);
+
+ printk(KERN_DEBUG "%*s domain %d: ", level, "", level);
+
+@@ -6023,25 +6669,25 @@ static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level)
+ break;
+ }
+
+- if (cpus_intersects(groupmask, group->cpumask)) {
++ if (cpus_intersects(*groupmask, group->cpumask)) {
+ printk(KERN_CONT "\n");
+ printk(KERN_ERR "ERROR: repeated CPUs\n");
+ break;
+ }
+
+- cpus_or(groupmask, groupmask, group->cpumask);
++ cpus_or(*groupmask, *groupmask, group->cpumask);
+
+- cpumask_scnprintf(str, NR_CPUS, group->cpumask);
++ cpulist_scnprintf(str, sizeof(str), group->cpumask);
+ printk(KERN_CONT " %s", str);
+
+ group = group->next;
+ } while (group != sd->groups);
+ printk(KERN_CONT "\n");
+
+- if (!cpus_equal(sd->span, groupmask))
++ if (!cpus_equal(sd->span, *groupmask))
+ printk(KERN_ERR "ERROR: groups don't span domain->span\n");
+
+- if (sd->parent && !cpus_subset(groupmask, sd->parent->span))
++ if (sd->parent && !cpus_subset(*groupmask, sd->parent->span))
+ printk(KERN_ERR "ERROR: parent span is not a superset "
+ "of domain->span\n");
+ return 0;
+@@ -6049,6 +6695,7 @@ static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level)
+
+ static void sched_domain_debug(struct sched_domain *sd, int cpu)
+ {
++ cpumask_t *groupmask;
+ int level = 0;
+
+ if (!sd) {
+@@ -6058,14 +6705,21 @@ static void sched_domain_debug(struct sched_domain *sd, int cpu)
+
+ printk(KERN_DEBUG "CPU%d attaching sched-domain:\n", cpu);
+
++ groupmask = kmalloc(sizeof(cpumask_t), GFP_KERNEL);
++ if (!groupmask) {
++ printk(KERN_DEBUG "Cannot load-balance (out of memory)\n");
++ return;
++ }
++
+ for (;;) {
+- if (sched_domain_debug_one(sd, cpu, level))
++ if (sched_domain_debug_one(sd, cpu, level, groupmask))
+ break;
+ level++;
+ sd = sd->parent;
+ if (!sd)
+ break;
+ }
++ kfree(groupmask);
+ }
+ #else
+ # define sched_domain_debug(sd, cpu) do { } while (0)
+@@ -6253,30 +6907,33 @@ __setup("isolcpus=", isolated_cpu_setup);
+ * and ->cpu_power to 0.
+ */
+ static void
+-init_sched_build_groups(cpumask_t span, const cpumask_t *cpu_map,
++init_sched_build_groups(const cpumask_t *span, const cpumask_t *cpu_map,
+ int (*group_fn)(int cpu, const cpumask_t *cpu_map,
+- struct sched_group **sg))
++ struct sched_group **sg,
++ cpumask_t *tmpmask),
++ cpumask_t *covered, cpumask_t *tmpmask)
+ {
+ struct sched_group *first = NULL, *last = NULL;
+- cpumask_t covered = CPU_MASK_NONE;
+ int i;
+
+- for_each_cpu_mask(i, span) {
++ cpus_clear(*covered);
++
++ for_each_cpu_mask(i, *span) {
+ struct sched_group *sg;
+- int group = group_fn(i, cpu_map, &sg);
++ int group = group_fn(i, cpu_map, &sg, tmpmask);
+ int j;
+
+- if (cpu_isset(i, covered))
++ if (cpu_isset(i, *covered))
+ continue;
+
+- sg->cpumask = CPU_MASK_NONE;
++ cpus_clear(sg->cpumask);
+ sg->__cpu_power = 0;
+
+- for_each_cpu_mask(j, span) {
+- if (group_fn(j, cpu_map, NULL) != group)
++ for_each_cpu_mask(j, *span) {
++ if (group_fn(j, cpu_map, NULL, tmpmask) != group)
+ continue;
+
+- cpu_set(j, covered);
++ cpu_set(j, *covered);
+ cpu_set(j, sg->cpumask);
+ }
+ if (!first)
+@@ -6302,7 +6959,7 @@ init_sched_build_groups(cpumask_t span, const cpumask_t *cpu_map,
+ *
+ * Should use nodemask_t.
+ */
+-static int find_next_best_node(int node, unsigned long *used_nodes)
++static int find_next_best_node(int node, nodemask_t *used_nodes)
+ {
+ int i, n, val, min_val, best_node = 0;
+
+@@ -6316,7 +6973,7 @@ static int find_next_best_node(int node, unsigned long *used_nodes)
+ continue;
+
+ /* Skip already used nodes */
+- if (test_bit(n, used_nodes))
++ if (node_isset(n, *used_nodes))
+ continue;
+
+ /* Simple min distance search */
+@@ -6328,40 +6985,37 @@ static int find_next_best_node(int node, unsigned long *used_nodes)
+ }
+ }
+
+- set_bit(best_node, used_nodes);
++ node_set(best_node, *used_nodes);
+ return best_node;
+ }
+
+ /**
+ * sched_domain_node_span - get a cpumask for a node's sched_domain
+ * @node: node whose cpumask we're constructing
+- * @size: number of nodes to include in this span
++ * @span: resulting cpumask
+ *
+ * Given a node, construct a good cpumask for its sched_domain to span. It
+ * should be one that prevents unnecessary balancing, but also spreads tasks
+ * out optimally.
+ */
+-static cpumask_t sched_domain_node_span(int node)
++static void sched_domain_node_span(int node, cpumask_t *span)
+ {
+- DECLARE_BITMAP(used_nodes, MAX_NUMNODES);
+- cpumask_t span, nodemask;
++ nodemask_t used_nodes;
++ node_to_cpumask_ptr(nodemask, node);
+ int i;
+
+- cpus_clear(span);
+- bitmap_zero(used_nodes, MAX_NUMNODES);
++ cpus_clear(*span);
++ nodes_clear(used_nodes);
+
+- nodemask = node_to_cpumask(node);
+- cpus_or(span, span, nodemask);
+- set_bit(node, used_nodes);
++ cpus_or(*span, *span, *nodemask);
++ node_set(node, used_nodes);
+
+ for (i = 1; i < SD_NODES_PER_DOMAIN; i++) {
+- int next_node = find_next_best_node(node, used_nodes);
++ int next_node = find_next_best_node(node, &used_nodes);
+
+- nodemask = node_to_cpumask(next_node);
+- cpus_or(span, span, nodemask);
++ node_to_cpumask_ptr_next(nodemask, next_node);
++ cpus_or(*span, *span, *nodemask);
+ }
+-
+- return span;
+ }
+ #endif
+
+@@ -6375,7 +7029,8 @@ static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
+ static DEFINE_PER_CPU(struct sched_group, sched_group_cpus);
+
+ static int
+-cpu_to_cpu_group(int cpu, const cpumask_t *cpu_map, struct sched_group **sg)
++cpu_to_cpu_group(int cpu, const cpumask_t *cpu_map, struct sched_group **sg,
++ cpumask_t *unused)
+ {
+ if (sg)
+ *sg = &per_cpu(sched_group_cpus, cpu);
+@@ -6393,19 +7048,22 @@ static DEFINE_PER_CPU(struct sched_group, sched_group_core);
+
+ #if defined(CONFIG_SCHED_MC) && defined(CONFIG_SCHED_SMT)
+ static int
+-cpu_to_core_group(int cpu, const cpumask_t *cpu_map, struct sched_group **sg)
++cpu_to_core_group(int cpu, const cpumask_t *cpu_map, struct sched_group **sg,
++ cpumask_t *mask)
+ {
+ int group;
+- cpumask_t mask = per_cpu(cpu_sibling_map, cpu);
+- cpus_and(mask, mask, *cpu_map);
+- group = first_cpu(mask);
++
++ *mask = per_cpu(cpu_sibling_map, cpu);
++ cpus_and(*mask, *mask, *cpu_map);
++ group = first_cpu(*mask);
+ if (sg)
+ *sg = &per_cpu(sched_group_core, group);
+ return group;
+ }
+ #elif defined(CONFIG_SCHED_MC)
+ static int
+-cpu_to_core_group(int cpu, const cpumask_t *cpu_map, struct sched_group **sg)
++cpu_to_core_group(int cpu, const cpumask_t *cpu_map, struct sched_group **sg,
++ cpumask_t *unused)
+ {
+ if (sg)
+ *sg = &per_cpu(sched_group_core, cpu);
+@@ -6417,17 +7075,18 @@ static DEFINE_PER_CPU(struct sched_domain, phys_domains);
+ static DEFINE_PER_CPU(struct sched_group, sched_group_phys);
+
+ static int
+-cpu_to_phys_group(int cpu, const cpumask_t *cpu_map, struct sched_group **sg)
++cpu_to_phys_group(int cpu, const cpumask_t *cpu_map, struct sched_group **sg,
++ cpumask_t *mask)
+ {
+ int group;
+ #ifdef CONFIG_SCHED_MC
+- cpumask_t mask = cpu_coregroup_map(cpu);
+- cpus_and(mask, mask, *cpu_map);
+- group = first_cpu(mask);
++ *mask = cpu_coregroup_map(cpu);
++ cpus_and(*mask, *mask, *cpu_map);
++ group = first_cpu(*mask);
+ #elif defined(CONFIG_SCHED_SMT)
+- cpumask_t mask = per_cpu(cpu_sibling_map, cpu);
+- cpus_and(mask, mask, *cpu_map);
+- group = first_cpu(mask);
++ *mask = per_cpu(cpu_sibling_map, cpu);
++ cpus_and(*mask, *mask, *cpu_map);
++ group = first_cpu(*mask);
+ #else
+ group = cpu;
+ #endif
+@@ -6443,19 +7102,19 @@ cpu_to_phys_group(int cpu, const cpumask_t *cpu_map, struct sched_group **sg)
+ * gets dynamically allocated.
+ */
+ static DEFINE_PER_CPU(struct sched_domain, node_domains);
+-static struct sched_group **sched_group_nodes_bycpu[NR_CPUS];
++static struct sched_group ***sched_group_nodes_bycpu;
+
+ static DEFINE_PER_CPU(struct sched_domain, allnodes_domains);
+ static DEFINE_PER_CPU(struct sched_group, sched_group_allnodes);
+
+ static int cpu_to_allnodes_group(int cpu, const cpumask_t *cpu_map,
+- struct sched_group **sg)
++ struct sched_group **sg, cpumask_t *nodemask)
+ {
+- cpumask_t nodemask = node_to_cpumask(cpu_to_node(cpu));
+ int group;
+
+- cpus_and(nodemask, nodemask, *cpu_map);
+- group = first_cpu(nodemask);
++ *nodemask = node_to_cpumask(cpu_to_node(cpu));
++ cpus_and(*nodemask, *nodemask, *cpu_map);
++ group = first_cpu(*nodemask);
+
+ if (sg)
+ *sg = &per_cpu(sched_group_allnodes, group);
+@@ -6491,7 +7150,7 @@ static void init_numa_sched_groups_power(struct sched_group *group_head)
+
+ #ifdef CONFIG_NUMA
+ /* Free memory allocated for various sched_group structures */
+-static void free_sched_groups(const cpumask_t *cpu_map)
++static void free_sched_groups(const cpumask_t *cpu_map, cpumask_t *nodemask)
+ {
+ int cpu, i;
+
+@@ -6503,11 +7162,11 @@ static void free_sched_groups(const cpumask_t *cpu_map)
+ continue;
+
+ for (i = 0; i < MAX_NUMNODES; i++) {
+- cpumask_t nodemask = node_to_cpumask(i);
+ struct sched_group *oldsg, *sg = sched_group_nodes[i];
+
+- cpus_and(nodemask, nodemask, *cpu_map);
+- if (cpus_empty(nodemask))
++ *nodemask = node_to_cpumask(i);
++ cpus_and(*nodemask, *nodemask, *cpu_map);
++ if (cpus_empty(*nodemask))
+ continue;
+
+ if (sg == NULL)
+@@ -6525,7 +7184,7 @@ next_sg:
+ }
+ }
+ #else
+-static void free_sched_groups(const cpumask_t *cpu_map)
++static void free_sched_groups(const cpumask_t *cpu_map, cpumask_t *nodemask)
+ {
+ }
+ #endif
+@@ -6583,13 +7242,106 @@ static void init_sched_groups_power(int cpu, struct sched_domain *sd)
+ }
+
+ /*
++ * Initializers for schedule domains
++ * Non-inlined to reduce accumulated stack pressure in build_sched_domains()
++ */
++
++#define SD_INIT(sd, type) sd_init_##type(sd)
++#define SD_INIT_FUNC(type) \
++static noinline void sd_init_##type(struct sched_domain *sd) \
++{ \
++ memset(sd, 0, sizeof(*sd)); \
++ *sd = SD_##type##_INIT; \
++ sd->level = SD_LV_##type; \
++}
++
++SD_INIT_FUNC(CPU)
++#ifdef CONFIG_NUMA
++ SD_INIT_FUNC(ALLNODES)
++ SD_INIT_FUNC(NODE)
++#endif
++#ifdef CONFIG_SCHED_SMT
++ SD_INIT_FUNC(SIBLING)
++#endif
++#ifdef CONFIG_SCHED_MC
++ SD_INIT_FUNC(MC)
++#endif
++
++/*
++ * To minimize stack usage kmalloc room for cpumasks and share the
++ * space as the usage in build_sched_domains() dictates. Used only
++ * if the amount of space is significant.
++ */
++struct allmasks {
++ cpumask_t tmpmask; /* make this one first */
++ union {
++ cpumask_t nodemask;
++ cpumask_t this_sibling_map;
++ cpumask_t this_core_map;
++ };
++ cpumask_t send_covered;
++
++#ifdef CONFIG_NUMA
++ cpumask_t domainspan;
++ cpumask_t covered;
++ cpumask_t notcovered;
++#endif
++};
++
++#if NR_CPUS > 128
++#define SCHED_CPUMASK_ALLOC 1
++#define SCHED_CPUMASK_FREE(v) kfree(v)
++#define SCHED_CPUMASK_DECLARE(v) struct allmasks *v
++#else
++#define SCHED_CPUMASK_ALLOC 0
++#define SCHED_CPUMASK_FREE(v)
++#define SCHED_CPUMASK_DECLARE(v) struct allmasks _v, *v = &_v
++#endif
++
++#define SCHED_CPUMASK_VAR(v, a) cpumask_t *v = (cpumask_t *) \
++ ((unsigned long)(a) + offsetof(struct allmasks, v))
++
++static int default_relax_domain_level = -1;
++
++static int __init setup_relax_domain_level(char *str)
++{
++ default_relax_domain_level = simple_strtoul(str, NULL, 0);
++ return 1;
++}
++__setup("relax_domain_level=", setup_relax_domain_level);
++
++static void set_domain_attribute(struct sched_domain *sd,
++ struct sched_domain_attr *attr)
++{
++ int request;
++
++ if (!attr || attr->relax_domain_level < 0) {
++ if (default_relax_domain_level < 0)
++ return;
++ else
++ request = default_relax_domain_level;
++ } else
++ request = attr->relax_domain_level;
++ if (request < sd->level) {
++ /* turn off idle balance on this domain */
++ sd->flags &= ~(SD_WAKE_IDLE|SD_BALANCE_NEWIDLE);
++ } else {
++ /* turn on idle balance on this domain */
++ sd->flags |= (SD_WAKE_IDLE_FAR|SD_BALANCE_NEWIDLE);
++ }
++}
++
++/*
+ * Build sched domains for a given set of cpus and attach the sched domains
+ * to the individual cpus
+ */
+-static int build_sched_domains(const cpumask_t *cpu_map)
++static int __build_sched_domains(const cpumask_t *cpu_map,
++ struct sched_domain_attr *attr)
+ {
+ int i;
+ struct root_domain *rd;
++ SCHED_CPUMASK_DECLARE(allmasks);
++ cpumask_t *tmpmask;
+ #ifdef CONFIG_NUMA
+ struct sched_group **sched_group_nodes = NULL;
+ int sd_allnodes = 0;
+@@ -6603,39 +7355,65 @@ static int build_sched_domains(const cpumask_t *cpu_map)
+ printk(KERN_WARNING "Can not alloc sched group node list\n");
+ return -ENOMEM;
+ }
+- sched_group_nodes_bycpu[first_cpu(*cpu_map)] = sched_group_nodes;
+ #endif
+
+ rd = alloc_rootdomain();
+ if (!rd) {
+ printk(KERN_WARNING "Cannot alloc root domain\n");
++#ifdef CONFIG_NUMA
++ kfree(sched_group_nodes);
++#endif
++ return -ENOMEM;
++ }
++
++#if SCHED_CPUMASK_ALLOC
++ /* get space for all scratch cpumask variables */
++ allmasks = kmalloc(sizeof(*allmasks), GFP_KERNEL);
++ if (!allmasks) {
++ printk(KERN_WARNING "Cannot alloc cpumask array\n");
++ kfree(rd);
++#ifdef CONFIG_NUMA
++ kfree(sched_group_nodes);
++#endif
+ return -ENOMEM;
+ }
++#endif
++ tmpmask = (cpumask_t *)allmasks;
++
++
++#ifdef CONFIG_NUMA
++ sched_group_nodes_bycpu[first_cpu(*cpu_map)] = sched_group_nodes;
++#endif
+
+ /*
+ * Set up domains for cpus specified by the cpu_map.
+ */
+ for_each_cpu_mask(i, *cpu_map) {
+ struct sched_domain *sd = NULL, *p;
+- cpumask_t nodemask = node_to_cpumask(cpu_to_node(i));
++ SCHED_CPUMASK_VAR(nodemask, allmasks);
+
+- cpus_and(nodemask, nodemask, *cpu_map);
++ *nodemask = node_to_cpumask(cpu_to_node(i));
++ cpus_and(*nodemask, *nodemask, *cpu_map);
+
+ #ifdef CONFIG_NUMA
+ if (cpus_weight(*cpu_map) >
+- SD_NODES_PER_DOMAIN*cpus_weight(nodemask)) {
++ SD_NODES_PER_DOMAIN*cpus_weight(*nodemask)) {
+ sd = &per_cpu(allnodes_domains, i);
+- *sd = SD_ALLNODES_INIT;
++ SD_INIT(sd, ALLNODES);
++ set_domain_attribute(sd, attr);
+ sd->span = *cpu_map;
+- cpu_to_allnodes_group(i, cpu_map, &sd->groups);
++ sd->first_cpu = first_cpu(sd->span);
++ cpu_to_allnodes_group(i, cpu_map, &sd->groups, tmpmask);
+ p = sd;
+ sd_allnodes = 1;
+ } else
+ p = NULL;
+
+ sd = &per_cpu(node_domains, i);
+- *sd = SD_NODE_INIT;
+- sd->span = sched_domain_node_span(cpu_to_node(i));
++ SD_INIT(sd, NODE);
++ set_domain_attribute(sd, attr);
++ sched_domain_node_span(cpu_to_node(i), &sd->span);
++ sd->first_cpu = first_cpu(sd->span);
+ sd->parent = p;
+ if (p)
+ p->child = sd;
+@@ -6644,94 +7422,120 @@ static int build_sched_domains(const cpumask_t *cpu_map)
+
+ p = sd;
+ sd = &per_cpu(phys_domains, i);
+- *sd = SD_CPU_INIT;
+- sd->span = nodemask;
++ SD_INIT(sd, CPU);
++ set_domain_attribute(sd, attr);
++ sd->span = *nodemask;
++ sd->first_cpu = first_cpu(sd->span);
+ sd->parent = p;
+ if (p)
+ p->child = sd;
+- cpu_to_phys_group(i, cpu_map, &sd->groups);
++ cpu_to_phys_group(i, cpu_map, &sd->groups, tmpmask);
+
+ #ifdef CONFIG_SCHED_MC
+ p = sd;
+ sd = &per_cpu(core_domains, i);
+- *sd = SD_MC_INIT;
++ SD_INIT(sd, MC);
++ set_domain_attribute(sd, attr);
+ sd->span = cpu_coregroup_map(i);
++ sd->first_cpu = first_cpu(sd->span);
+ cpus_and(sd->span, sd->span, *cpu_map);
+ sd->parent = p;
+ p->child = sd;
+- cpu_to_core_group(i, cpu_map, &sd->groups);
++ cpu_to_core_group(i, cpu_map, &sd->groups, tmpmask);
+ #endif
+
+ #ifdef CONFIG_SCHED_SMT
+ p = sd;
+ sd = &per_cpu(cpu_domains, i);
+- *sd = SD_SIBLING_INIT;
++ SD_INIT(sd, SIBLING);
++ set_domain_attribute(sd, attr);
+ sd->span = per_cpu(cpu_sibling_map, i);
++ sd->first_cpu = first_cpu(sd->span);
+ cpus_and(sd->span, sd->span, *cpu_map);
+ sd->parent = p;
+ p->child = sd;
+- cpu_to_cpu_group(i, cpu_map, &sd->groups);
++ cpu_to_cpu_group(i, cpu_map, &sd->groups, tmpmask);
+ #endif
+ }
+
+ #ifdef CONFIG_SCHED_SMT
+ /* Set up CPU (sibling) groups */
+ for_each_cpu_mask(i, *cpu_map) {
+- cpumask_t this_sibling_map = per_cpu(cpu_sibling_map, i);
+- cpus_and(this_sibling_map, this_sibling_map, *cpu_map);
+- if (i != first_cpu(this_sibling_map))
++ SCHED_CPUMASK_VAR(this_sibling_map, allmasks);
++ SCHED_CPUMASK_VAR(send_covered, allmasks);
++
++ *this_sibling_map = per_cpu(cpu_sibling_map, i);
++ cpus_and(*this_sibling_map, *this_sibling_map, *cpu_map);
++ if (i != first_cpu(*this_sibling_map))
+ continue;
+
+ init_sched_build_groups(this_sibling_map, cpu_map,
+- &cpu_to_cpu_group);
++ &cpu_to_cpu_group,
++ send_covered, tmpmask);
+ }
+ #endif
+
+ #ifdef CONFIG_SCHED_MC
+ /* Set up multi-core groups */
+ for_each_cpu_mask(i, *cpu_map) {
+- cpumask_t this_core_map = cpu_coregroup_map(i);
+- cpus_and(this_core_map, this_core_map, *cpu_map);
+- if (i != first_cpu(this_core_map))
++ SCHED_CPUMASK_VAR(this_core_map, allmasks);
++ SCHED_CPUMASK_VAR(send_covered, allmasks);
++
++ *this_core_map = cpu_coregroup_map(i);
++ cpus_and(*this_core_map, *this_core_map, *cpu_map);
++ if (i != first_cpu(*this_core_map))
+ continue;
++
+ init_sched_build_groups(this_core_map, cpu_map,
+- &cpu_to_core_group);
++ &cpu_to_core_group,
++ send_covered, tmpmask);
+ }
+ #endif
+
+ /* Set up physical groups */
+ for (i = 0; i < MAX_NUMNODES; i++) {
+- cpumask_t nodemask = node_to_cpumask(i);
++ SCHED_CPUMASK_VAR(nodemask, allmasks);
++ SCHED_CPUMASK_VAR(send_covered, allmasks);
+
+- cpus_and(nodemask, nodemask, *cpu_map);
+- if (cpus_empty(nodemask))
++ *nodemask = node_to_cpumask(i);
++ cpus_and(*nodemask, *nodemask, *cpu_map);
++ if (cpus_empty(*nodemask))
+ continue;
+
+- init_sched_build_groups(nodemask, cpu_map, &cpu_to_phys_group);
++ init_sched_build_groups(nodemask, cpu_map,
++ &cpu_to_phys_group,
++ send_covered, tmpmask);
+ }
+
+ #ifdef CONFIG_NUMA
+ /* Set up node groups */
+- if (sd_allnodes)
+- init_sched_build_groups(*cpu_map, cpu_map,
+- &cpu_to_allnodes_group);
++ if (sd_allnodes) {
++ SCHED_CPUMASK_VAR(send_covered, allmasks);
++
++ init_sched_build_groups(cpu_map, cpu_map,
++ &cpu_to_allnodes_group,
++ send_covered, tmpmask);
++ }
+
+ for (i = 0; i < MAX_NUMNODES; i++) {
+ /* Set up node groups */
+ struct sched_group *sg, *prev;
+- cpumask_t nodemask = node_to_cpumask(i);
+- cpumask_t domainspan;
+- cpumask_t covered = CPU_MASK_NONE;
++ SCHED_CPUMASK_VAR(nodemask, allmasks);
++ SCHED_CPUMASK_VAR(domainspan, allmasks);
++ SCHED_CPUMASK_VAR(covered, allmasks);
+ int j;
+
+- cpus_and(nodemask, nodemask, *cpu_map);
+- if (cpus_empty(nodemask)) {
++ *nodemask = node_to_cpumask(i);
++ cpus_clear(*covered);
++
++ cpus_and(*nodemask, *nodemask, *cpu_map);
++ if (cpus_empty(*nodemask)) {
+ sched_group_nodes[i] = NULL;
+ continue;
+ }
+
+- domainspan = sched_domain_node_span(i);
+- cpus_and(domainspan, domainspan, *cpu_map);
++ sched_domain_node_span(i, domainspan);
++ cpus_and(*domainspan, *domainspan, *cpu_map);
+
+ sg = kmalloc_node(sizeof(struct sched_group), GFP_KERNEL, i);
+ if (!sg) {
+@@ -6740,31 +7544,31 @@ static int build_sched_domains(const cpumask_t *cpu_map)
+ goto error;
+ }
+ sched_group_nodes[i] = sg;
+- for_each_cpu_mask(j, nodemask) {
++ for_each_cpu_mask(j, *nodemask) {
+ struct sched_domain *sd;
+
+ sd = &per_cpu(node_domains, j);
+ sd->groups = sg;
+ }
+ sg->__cpu_power = 0;
+- sg->cpumask = nodemask;
++ sg->cpumask = *nodemask;
+ sg->next = sg;
+- cpus_or(covered, covered, nodemask);
++ cpus_or(*covered, *covered, *nodemask);
+ prev = sg;
+
+ for (j = 0; j < MAX_NUMNODES; j++) {
+- cpumask_t tmp, notcovered;
++ SCHED_CPUMASK_VAR(notcovered, allmasks);
+ int n = (i + j) % MAX_NUMNODES;
++ node_to_cpumask_ptr(pnodemask, n);
+
+- cpus_complement(notcovered, covered);
+- cpus_and(tmp, notcovered, *cpu_map);
+- cpus_and(tmp, tmp, domainspan);
+- if (cpus_empty(tmp))
++ cpus_complement(*notcovered, *covered);
++ cpus_and(*tmpmask, *notcovered, *cpu_map);
++ cpus_and(*tmpmask, *tmpmask, *domainspan);
++ if (cpus_empty(*tmpmask))
+ break;
+
+- nodemask = node_to_cpumask(n);
+- cpus_and(tmp, tmp, nodemask);
+- if (cpus_empty(tmp))
++ cpus_and(*tmpmask, *tmpmask, *pnodemask);
++ if (cpus_empty(*tmpmask))
+ continue;
+
+ sg = kmalloc_node(sizeof(struct sched_group),
+@@ -6775,9 +7579,9 @@ static int build_sched_domains(const cpumask_t *cpu_map)
+ goto error;
+ }
+ sg->__cpu_power = 0;
+- sg->cpumask = tmp;
++ sg->cpumask = *tmpmask;
+ sg->next = prev->next;
+- cpus_or(covered, covered, tmp);
++ cpus_or(*covered, *covered, *tmpmask);
+ prev->next = sg;
+ prev = sg;
+ }
+@@ -6813,7 +7617,8 @@ static int build_sched_domains(const cpumask_t *cpu_map)
+ if (sd_allnodes) {
+ struct sched_group *sg;
+
+- cpu_to_allnodes_group(first_cpu(*cpu_map), cpu_map, &sg);
++ cpu_to_allnodes_group(first_cpu(*cpu_map), cpu_map, &sg,
++ tmpmask);
+ init_numa_sched_groups_power(sg);
+ }
+ #endif
+@@ -6831,17 +7636,26 @@ static int build_sched_domains(const cpumask_t *cpu_map)
+ cpu_attach_domain(sd, rd, i);
+ }
+
++ SCHED_CPUMASK_FREE((void *)allmasks);
+ return 0;
+
+ #ifdef CONFIG_NUMA
+ error:
+- free_sched_groups(cpu_map);
++ free_sched_groups(cpu_map, tmpmask);
++ SCHED_CPUMASK_FREE((void *)allmasks);
+ return -ENOMEM;
+ #endif
+ }
+
++static int build_sched_domains(const cpumask_t *cpu_map)
++{
++ return __build_sched_domains(cpu_map, NULL);
++}
++
+ static cpumask_t *doms_cur; /* current sched domains */
+ static int ndoms_cur; /* number of sched domains in 'doms_cur' */
++static struct sched_domain_attr *dattr_cur; /* attribues of custom domains
++ in 'doms_cur' */
+
+ /*
+ * Special case: If a kmalloc of a doms_cur partition (array of
+@@ -6869,15 +7683,17 @@ static int arch_init_sched_domains(const cpumask_t *cpu_map)
+ if (!doms_cur)
+ doms_cur = &fallback_doms;
+ cpus_andnot(*doms_cur, *cpu_map, cpu_isolated_map);
++ dattr_cur = NULL;
+ err = build_sched_domains(doms_cur);
+ register_sched_domain_sysctl();
+
+ return err;
+ }
+
+-static void arch_destroy_sched_domains(const cpumask_t *cpu_map)
++static void arch_destroy_sched_domains(const cpumask_t *cpu_map,
++ cpumask_t *tmpmask)
+ {
+- free_sched_groups(cpu_map);
++ free_sched_groups(cpu_map, tmpmask);
+ }
+
+ /*
+@@ -6886,6 +7702,7 @@ static void arch_destroy_sched_domains(const cpumask_t *cpu_map)
+ */
+ static void detach_destroy_domains(const cpumask_t *cpu_map)
+ {
++ cpumask_t tmpmask;
+ int i;
+
+ unregister_sched_domain_sysctl();
+@@ -6893,7 +7710,23 @@ static void detach_destroy_domains(const cpumask_t *cpu_map)
+ for_each_cpu_mask(i, *cpu_map)
+ cpu_attach_domain(NULL, &def_root_domain, i);
+ synchronize_sched();
+- arch_destroy_sched_domains(cpu_map);
++ arch_destroy_sched_domains(cpu_map, &tmpmask);
++}
++
++/* handle null as "default" */
++static int dattrs_equal(struct sched_domain_attr *cur, int idx_cur,
++ struct sched_domain_attr *new, int idx_new)
++{
++ struct sched_domain_attr tmp;
++
++ /* fast path */
++ if (!new && !cur)
++ return 1;
++
++ tmp = SD_ATTR_INIT;
++ return !memcmp(cur ? (cur + idx_cur) : &tmp,
++ new ? (new + idx_new) : &tmp,
++ sizeof(struct sched_domain_attr));
+ }
+
+ /*
+@@ -6917,7 +7750,8 @@ static void detach_destroy_domains(const cpumask_t *cpu_map)
+ *
+ * Call with hotplug lock held
+ */
+-void partition_sched_domains(int ndoms_new, cpumask_t *doms_new)
++void partition_sched_domains(int ndoms_new, cpumask_t *doms_new,
++ struct sched_domain_attr *dattr_new)
+ {
+ int i, j;
+
+@@ -6930,12 +7764,14 @@ void partition_sched_domains(int ndoms_new, cpumask_t *doms_new)
+ ndoms_new = 1;
+ doms_new = &fallback_doms;
+ cpus_andnot(doms_new[0], cpu_online_map, cpu_isolated_map);
++ dattr_new = NULL;
+ }
+
+ /* Destroy deleted domains */
+ for (i = 0; i < ndoms_cur; i++) {
+ for (j = 0; j < ndoms_new; j++) {
+- if (cpus_equal(doms_cur[i], doms_new[j]))
++ if (cpus_equal(doms_cur[i], doms_new[j])
++ && dattrs_equal(dattr_cur, i, dattr_new, j))
+ goto match1;
+ }
+ /* no match - a current sched domain not in new doms_new[] */
+@@ -6947,11 +7783,13 @@ match1:
+ /* Build new domains */
+ for (i = 0; i < ndoms_new; i++) {
+ for (j = 0; j < ndoms_cur; j++) {
+- if (cpus_equal(doms_new[i], doms_cur[j]))
++ if (cpus_equal(doms_new[i], doms_cur[j])
++ && dattrs_equal(dattr_new, i, dattr_cur, j))
+ goto match2;
+ }
+ /* no match - add a new doms_new */
+- build_sched_domains(doms_new + i);
++ __build_sched_domains(doms_new + i,
++ dattr_new ? dattr_new + i : NULL);
+ match2:
+ ;
+ }
+@@ -6959,7 +7797,9 @@ match2:
+ /* Remember the new sched domains */
+ if (doms_cur != &fallback_doms)
+ kfree(doms_cur);
++ kfree(dattr_cur); /* kfree(NULL) is safe */
+ doms_cur = doms_new;
++ dattr_cur = dattr_new;
+ ndoms_cur = ndoms_new;
+
+ register_sched_domain_sysctl();
+@@ -7086,6 +7926,11 @@ void __init sched_init_smp(void)
+ {
+ cpumask_t non_isolated_cpus;
+
++#if defined(CONFIG_NUMA)
++ sched_group_nodes_bycpu = kzalloc(nr_cpu_ids * sizeof(void **),
++ GFP_KERNEL);
++ BUG_ON(sched_group_nodes_bycpu == NULL);
++#endif
+ get_online_cpus();
+ arch_init_sched_domains(&cpu_online_map);
+ cpus_andnot(non_isolated_cpus, cpu_possible_map, cpu_isolated_map);
+@@ -7096,7 +7941,7 @@ void __init sched_init_smp(void)
+ hotcpu_notifier(update_sched_domains, 0);
+
+ /* Move init over to a non-isolated CPU */
+- if (set_cpus_allowed(current, non_isolated_cpus) < 0)
++ if (set_cpus_allowed_ptr(current, &non_isolated_cpus) < 0)
+ BUG();
+ sched_init_granularity();
+ }
+@@ -7117,6 +7962,7 @@ int in_sched_functions(unsigned long addr)
+ static void init_cfs_rq(struct cfs_rq *cfs_rq, struct rq *rq)
+ {
+ cfs_rq->tasks_timeline = RB_ROOT;
++ INIT_LIST_HEAD(&cfs_rq->tasks);
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+ cfs_rq->rq = rq;
+ #endif
+@@ -7146,6 +7992,8 @@ static void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq)
+
+ rt_rq->rt_time = 0;
+ rt_rq->rt_throttled = 0;
++ rt_rq->rt_runtime = 0;
++ spin_lock_init(&rt_rq->rt_runtime_lock);
+
+ #ifdef CONFIG_RT_GROUP_SCHED
+ rt_rq->rt_nr_boosted = 0;
+@@ -7154,10 +8002,11 @@ static void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq)
+ }
+
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+-static void init_tg_cfs_entry(struct rq *rq, struct task_group *tg,
+- struct cfs_rq *cfs_rq, struct sched_entity *se,
+- int cpu, int add)
++static void init_tg_cfs_entry(struct task_group *tg, struct cfs_rq *cfs_rq,
++ struct sched_entity *se, int cpu, int add,
++ struct sched_entity *parent)
+ {
++ struct rq *rq = cpu_rq(cpu);
+ tg->cfs_rq[cpu] = cfs_rq;
+ init_cfs_rq(cfs_rq, rq);
+ cfs_rq->tg = tg;
+@@ -7165,45 +8014,132 @@ static void init_tg_cfs_entry(struct rq *rq, struct task_group *tg,
+ list_add(&cfs_rq->leaf_cfs_rq_list, &rq->leaf_cfs_rq_list);
+
+ tg->se[cpu] = se;
+- se->cfs_rq = &rq->cfs;
++ /* se could be NULL for init_task_group */
++ if (!se)
++ return;
++
++ if (!parent)
++ se->cfs_rq = &rq->cfs;
++ else
++ se->cfs_rq = parent->my_q;
++
+ se->my_q = cfs_rq;
+ se->load.weight = tg->shares;
+ se->load.inv_weight = div64_64(1ULL<<32, se->load.weight);
+- se->parent = NULL;
++ se->parent = parent;
+ }
+ #endif
+
+ #ifdef CONFIG_RT_GROUP_SCHED
+-static void init_tg_rt_entry(struct rq *rq, struct task_group *tg,
+- struct rt_rq *rt_rq, struct sched_rt_entity *rt_se,
+- int cpu, int add)
++static void init_tg_rt_entry(struct task_group *tg, struct rt_rq *rt_rq,
++ struct sched_rt_entity *rt_se, int cpu, int add,
++ struct sched_rt_entity *parent)
+ {
++ struct rq *rq = cpu_rq(cpu);
++
+ tg->rt_rq[cpu] = rt_rq;
+ init_rt_rq(rt_rq, rq);
+ rt_rq->tg = tg;
+ rt_rq->rt_se = rt_se;
++ rt_rq->rt_runtime = tg->rt_bandwidth.rt_runtime;
+ if (add)
+ list_add(&rt_rq->leaf_rt_rq_list, &rq->leaf_rt_rq_list);
+
+ tg->rt_se[cpu] = rt_se;
++ if (!rt_se)
++ return;
++
++ if (!parent)
++ rt_se->rt_rq = &rq->rt;
++ else
++ rt_se->rt_rq = parent->my_q;
++
+ rt_se->rt_rq = &rq->rt;
+ rt_se->my_q = rt_rq;
+- rt_se->parent = NULL;
++ rt_se->parent = parent;
+ INIT_LIST_HEAD(&rt_se->run_list);
+ }
+ #endif
+
+ void __init sched_init(void)
+ {
+- int highest_cpu = 0;
+ int i, j;
++ unsigned long alloc_size = 0, ptr;
++
++#ifdef CONFIG_FAIR_GROUP_SCHED
++ alloc_size += 2 * nr_cpu_ids * sizeof(void **);
++#endif
++#ifdef CONFIG_RT_GROUP_SCHED
++ alloc_size += 2 * nr_cpu_ids * sizeof(void **);
++#endif
++#ifdef CONFIG_USER_SCHED
++ alloc_size *= 2;
++#endif
++ /*
++ * As sched_init() is called before page_alloc is setup,
++ * we use alloc_bootmem().
++ */
++ if (alloc_size) {
++ ptr = (unsigned long)alloc_bootmem(alloc_size);
++
++#ifdef CONFIG_FAIR_GROUP_SCHED
++ init_task_group.se = (struct sched_entity **)ptr;
++ ptr += nr_cpu_ids * sizeof(void **);
++
++ init_task_group.cfs_rq = (struct cfs_rq **)ptr;
++ ptr += nr_cpu_ids * sizeof(void **);
++
++#ifdef CONFIG_USER_SCHED
++ root_task_group.se = (struct sched_entity **)ptr;
++ ptr += nr_cpu_ids * sizeof(void **);
++
++ root_task_group.cfs_rq = (struct cfs_rq **)ptr;
++ ptr += nr_cpu_ids * sizeof(void **);
++#endif
++#endif
++#ifdef CONFIG_RT_GROUP_SCHED
++ init_task_group.rt_se = (struct sched_rt_entity **)ptr;
++ ptr += nr_cpu_ids * sizeof(void **);
++
++ init_task_group.rt_rq = (struct rt_rq **)ptr;
++ ptr += nr_cpu_ids * sizeof(void **);
++
++#ifdef CONFIG_USER_SCHED
++ root_task_group.rt_se = (struct sched_rt_entity **)ptr;
++ ptr += nr_cpu_ids * sizeof(void **);
++
++ root_task_group.rt_rq = (struct rt_rq **)ptr;
++ ptr += nr_cpu_ids * sizeof(void **);
++#endif
++#endif
++ }
+
+ #ifdef CONFIG_SMP
++ init_aggregate();
+ init_defrootdomain();
+ #endif
+
++ init_rt_bandwidth(&def_rt_bandwidth,
++ global_rt_period(), global_rt_runtime());
++
++#ifdef CONFIG_RT_GROUP_SCHED
++ init_rt_bandwidth(&init_task_group.rt_bandwidth,
++ global_rt_period(), global_rt_runtime());
++#ifdef CONFIG_USER_SCHED
++ init_rt_bandwidth(&root_task_group.rt_bandwidth,
++ global_rt_period(), RUNTIME_INF);
++#endif
++#endif
++
+ #ifdef CONFIG_GROUP_SCHED
+ list_add(&init_task_group.list, &task_groups);
++ INIT_LIST_HEAD(&init_task_group.children);
++
++#ifdef CONFIG_USER_SCHED
++ INIT_LIST_HEAD(&root_task_group.children);
++ init_task_group.parent = &root_task_group;
++ list_add(&init_task_group.siblings, &root_task_group.children);
++#endif
+ #endif
+
+ for_each_possible_cpu(i) {
+@@ -7214,26 +8150,68 @@ void __init sched_init(void)
+ lockdep_set_class(&rq->lock, &rq->rq_lock_key);
+ rq->nr_running = 0;
+ rq->clock = 1;
++ update_last_tick_seen(rq);
+ init_cfs_rq(&rq->cfs, rq);
+ init_rt_rq(&rq->rt, rq);
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+ init_task_group.shares = init_task_group_load;
+ INIT_LIST_HEAD(&rq->leaf_cfs_rq_list);
+- init_tg_cfs_entry(rq, &init_task_group,
++#ifdef CONFIG_CGROUP_SCHED
++ /*
++ * How much cpu bandwidth does init_task_group get?
++ *
++ * In case of task-groups formed thr' the cgroup filesystem, it
++ * gets 100% of the cpu resources in the system. This overall
++ * system cpu resource is divided among the tasks of
++ * init_task_group and its child task-groups in a fair manner,
++ * based on each entity's (task or task-group's) weight
++ * (se->load.weight).
++ *
++ * In other words, if init_task_group has 10 tasks of weight
++ * 1024) and two child groups A0 and A1 (of weight 1024 each),
++ * then A0's share of the cpu resource is:
++ *
++ * A0's bandwidth = 1024 / (10*1024 + 1024 + 1024) = 8.33%
++ *
++ * We achieve this by letting init_task_group's tasks sit
++ * directly in rq->cfs (i.e init_task_group->se[] = NULL).
++ */
++ init_tg_cfs_entry(&init_task_group, &rq->cfs, NULL, i, 1, NULL);
++#elif defined CONFIG_USER_SCHED
++ root_task_group.shares = NICE_0_LOAD;
++ init_tg_cfs_entry(&root_task_group, &rq->cfs, NULL, i, 0, NULL);
++ /*
++ * In case of task-groups formed thr' the user id of tasks,
++ * init_task_group represents tasks belonging to root user.
++ * Hence it forms a sibling of all subsequent groups formed.
++ * In this case, init_task_group gets only a fraction of overall
++ * system cpu resource, based on the weight assigned to root
++ * user's cpu share (INIT_TASK_GROUP_LOAD). This is accomplished
++ * by letting tasks of init_task_group sit in a separate cfs_rq
++ * (init_cfs_rq) and having one entity represent this group of
++ * tasks in rq->cfs (i.e init_task_group->se[] != NULL).
++ */
++ init_tg_cfs_entry(&init_task_group,
+ &per_cpu(init_cfs_rq, i),
+- &per_cpu(init_sched_entity, i), i, 1);
++ &per_cpu(init_sched_entity, i), i, 1,
++ root_task_group.se[i]);
+
+ #endif
++#endif /* CONFIG_FAIR_GROUP_SCHED */
++
++ rq->rt.rt_runtime = def_rt_bandwidth.rt_runtime;
+ #ifdef CONFIG_RT_GROUP_SCHED
+- init_task_group.rt_runtime =
+- sysctl_sched_rt_runtime * NSEC_PER_USEC;
+ INIT_LIST_HEAD(&rq->leaf_rt_rq_list);
+- init_tg_rt_entry(rq, &init_task_group,
++#ifdef CONFIG_CGROUP_SCHED
++ init_tg_rt_entry(&init_task_group, &rq->rt, NULL, i, 1, NULL);
++#elif defined CONFIG_USER_SCHED
++ init_tg_rt_entry(&root_task_group, &rq->rt, NULL, i, 0, NULL);
++ init_tg_rt_entry(&init_task_group,
+ &per_cpu(init_rt_rq, i),
+- &per_cpu(init_sched_rt_entity, i), i, 1);
++ &per_cpu(init_sched_rt_entity, i), i, 1,
++ root_task_group.rt_se[i]);
++#endif
+ #endif
+- rq->rt_period_expire = 0;
+- rq->rt_throttled = 0;
+
+ for (j = 0; j < CPU_LOAD_IDX_MAX; j++)
+ rq->cpu_load[j] = 0;
+@@ -7250,7 +8228,6 @@ void __init sched_init(void)
+ #endif
+ init_rq_hrtick(rq);
+ atomic_set(&rq->nr_iowait, 0);
+- highest_cpu = i;
+ }
+
+ set_load_weight(&init_task);
+@@ -7260,7 +8237,6 @@ void __init sched_init(void)
+ #endif
+
+ #ifdef CONFIG_SMP
+- nr_cpu_ids = highest_cpu + 1;
+ open_softirq(SCHED_SOFTIRQ, run_rebalance_domains, NULL);
+ #endif
+
+@@ -7419,8 +8395,6 @@ void set_curr_task(int cpu, struct task_struct *p)
+
+ #endif
+
+-#ifdef CONFIG_GROUP_SCHED
+-
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+ static void free_fair_sched_group(struct task_group *tg)
+ {
+@@ -7437,17 +8411,18 @@ static void free_fair_sched_group(struct task_group *tg)
+ kfree(tg->se);
+ }
+
+-static int alloc_fair_sched_group(struct task_group *tg)
++static
++int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
+ {
+ struct cfs_rq *cfs_rq;
+- struct sched_entity *se;
++ struct sched_entity *se, *parent_se;
+ struct rq *rq;
+ int i;
+
+- tg->cfs_rq = kzalloc(sizeof(cfs_rq) * NR_CPUS, GFP_KERNEL);
++ tg->cfs_rq = kzalloc(sizeof(cfs_rq) * nr_cpu_ids, GFP_KERNEL);
+ if (!tg->cfs_rq)
+ goto err;
+- tg->se = kzalloc(sizeof(se) * NR_CPUS, GFP_KERNEL);
++ tg->se = kzalloc(sizeof(se) * nr_cpu_ids, GFP_KERNEL);
+ if (!tg->se)
+ goto err;
+
+@@ -7466,7 +8441,8 @@ static int alloc_fair_sched_group(struct task_group *tg)
+ if (!se)
+ goto err;
+
+- init_tg_cfs_entry(rq, tg, cfs_rq, se, i, 0);
++ parent_se = parent ? parent->se[i] : NULL;
++ init_tg_cfs_entry(tg, cfs_rq, se, i, 0, parent_se);
+ }
+
+ return 1;
+@@ -7490,7 +8466,8 @@ static inline void free_fair_sched_group(struct task_group *tg)
+ {
+ }
+
+-static inline int alloc_fair_sched_group(struct task_group *tg)
++static inline
++int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
+ {
+ return 1;
+ }
+@@ -7509,6 +8486,8 @@ static void free_rt_sched_group(struct task_group *tg)
+ {
+ int i;
+
++ destroy_rt_bandwidth(&tg->rt_bandwidth);
++
+ for_each_possible_cpu(i) {
+ if (tg->rt_rq)
+ kfree(tg->rt_rq[i]);
+@@ -7520,21 +8499,23 @@ static void free_rt_sched_group(struct task_group *tg)
+ kfree(tg->rt_se);
+ }
+
+-static int alloc_rt_sched_group(struct task_group *tg)
++static
++int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent)
+ {
+ struct rt_rq *rt_rq;
+- struct sched_rt_entity *rt_se;
++ struct sched_rt_entity *rt_se, *parent_se;
+ struct rq *rq;
+ int i;
+
+- tg->rt_rq = kzalloc(sizeof(rt_rq) * NR_CPUS, GFP_KERNEL);
++ tg->rt_rq = kzalloc(sizeof(rt_rq) * nr_cpu_ids, GFP_KERNEL);
+ if (!tg->rt_rq)
+ goto err;
+- tg->rt_se = kzalloc(sizeof(rt_se) * NR_CPUS, GFP_KERNEL);
++ tg->rt_se = kzalloc(sizeof(rt_se) * nr_cpu_ids, GFP_KERNEL);
+ if (!tg->rt_se)
+ goto err;
+
+- tg->rt_runtime = 0;
++ init_rt_bandwidth(&tg->rt_bandwidth,
++ ktime_to_ns(def_rt_bandwidth.rt_period), 0);
+
+ for_each_possible_cpu(i) {
+ rq = cpu_rq(i);
+@@ -7549,7 +8530,8 @@ static int alloc_rt_sched_group(struct task_group *tg)
+ if (!rt_se)
+ goto err;
+
+- init_tg_rt_entry(rq, tg, rt_rq, rt_se, i, 0);
++ parent_se = parent ? parent->rt_se[i] : NULL;
++ init_tg_rt_entry(tg, rt_rq, rt_se, i, 0, parent_se);
+ }
+
+ return 1;
+@@ -7573,7 +8555,8 @@ static inline void free_rt_sched_group(struct task_group *tg)
+ {
+ }
+
+-static inline int alloc_rt_sched_group(struct task_group *tg)
++static inline
++int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent)
+ {
+ return 1;
+ }
+@@ -7587,6 +8570,7 @@ static inline void unregister_rt_sched_group(struct task_group *tg, int cpu)
+ }
+ #endif
+
++#ifdef CONFIG_GROUP_SCHED
+ static void free_sched_group(struct task_group *tg)
+ {
+ free_fair_sched_group(tg);
+@@ -7595,7 +8579,7 @@ static void free_sched_group(struct task_group *tg)
+ }
+
+ /* allocate runqueue etc for a new task group */
+-struct task_group *sched_create_group(void)
++struct task_group *sched_create_group(struct task_group *parent)
+ {
+ struct task_group *tg;
+ unsigned long flags;
+@@ -7605,10 +8589,10 @@ struct task_group *sched_create_group(void)
+ if (!tg)
+ return ERR_PTR(-ENOMEM);
+
+- if (!alloc_fair_sched_group(tg))
++ if (!alloc_fair_sched_group(tg, parent))
+ goto err;
+
+- if (!alloc_rt_sched_group(tg))
++ if (!alloc_rt_sched_group(tg, parent))
+ goto err;
+
+ spin_lock_irqsave(&task_group_lock, flags);
+@@ -7617,6 +8601,12 @@ struct task_group *sched_create_group(void)
+ register_rt_sched_group(tg, i);
+ }
+ list_add_rcu(&tg->list, &task_groups);
++
++ WARN_ON(!parent); /* root should already exist */
++
++ tg->parent = parent;
++ list_add_rcu(&tg->siblings, &parent->children);
++ INIT_LIST_HEAD(&tg->children);
+ spin_unlock_irqrestore(&task_group_lock, flags);
+
+ return tg;
+@@ -7645,6 +8635,7 @@ void sched_destroy_group(struct task_group *tg)
+ unregister_rt_sched_group(tg, i);
+ }
+ list_del_rcu(&tg->list);
++ list_del_rcu(&tg->siblings);
+ spin_unlock_irqrestore(&task_group_lock, flags);
+
+ /* wait for possible concurrent references to cfs_rqs complete */
+@@ -7688,16 +8679,14 @@ void sched_move_task(struct task_struct *tsk)
+
+ task_rq_unlock(rq, &flags);
+ }
++#endif
+
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+-static void set_se_shares(struct sched_entity *se, unsigned long shares)
++static void __set_se_shares(struct sched_entity *se, unsigned long shares)
+ {
+ struct cfs_rq *cfs_rq = se->cfs_rq;
+- struct rq *rq = cfs_rq->rq;
+ int on_rq;
+
+- spin_lock_irq(&rq->lock);
+-
+ on_rq = se->on_rq;
+ if (on_rq)
+ dequeue_entity(cfs_rq, se, 0);
+@@ -7707,8 +8696,17 @@ static void set_se_shares(struct sched_entity *se, unsigned long shares)
+
+ if (on_rq)
+ enqueue_entity(cfs_rq, se, 0);
++}
+
+- spin_unlock_irq(&rq->lock);
++static void set_se_shares(struct sched_entity *se, unsigned long shares)
++{
++ struct cfs_rq *cfs_rq = se->cfs_rq;
++ struct rq *rq = cfs_rq->rq;
++ unsigned long flags;
++
++ spin_lock_irqsave(&rq->lock, flags);
++ __set_se_shares(se, shares);
++ spin_unlock_irqrestore(&rq->lock, flags);
+ }
+
+ static DEFINE_MUTEX(shares_mutex);
+@@ -7719,12 +8717,18 @@ int sched_group_set_shares(struct task_group *tg, unsigned long shares)
+ unsigned long flags;
+
+ /*
++ * We can't change the weight of the root cgroup.
++ */
++ if (!tg->se[0])
++ return -EINVAL;
++
++ /*
+ * A weight of 0 or 1 can cause arithmetics problems.
+ * (The default weight is 1024 - so there's no practical
+ * limitation from this.)
+ */
+- if (shares < 2)
+- shares = 2;
++ if (shares < MIN_SHARES)
++ shares = MIN_SHARES;
+
+ mutex_lock(&shares_mutex);
+ if (tg->shares == shares)
+@@ -7733,6 +8737,7 @@ int sched_group_set_shares(struct task_group *tg, unsigned long shares)
+ spin_lock_irqsave(&task_group_lock, flags);
+ for_each_possible_cpu(i)
+ unregister_fair_sched_group(tg, i);
++ list_del_rcu(&tg->siblings);
+ spin_unlock_irqrestore(&task_group_lock, flags);
+
+ /* wait for any ongoing reference to this group to finish */
+@@ -7743,8 +8748,13 @@ int sched_group_set_shares(struct task_group *tg, unsigned long shares)
+ * w/o tripping rebalance_share or load_balance_fair.
+ */
+ tg->shares = shares;
+- for_each_possible_cpu(i)
+- set_se_shares(tg->se[i], shares);
++ for_each_possible_cpu(i) {
++ /*
++ * force a rebalance
++ */
++ cfs_rq_set_shares(tg->cfs_rq[i], 0);
++ set_se_shares(tg->se[i], shares/nr_cpu_ids);
++ }
+
+ /*
+ * Enable load balance activity on this group, by inserting it back on
+@@ -7753,6 +8763,7 @@ int sched_group_set_shares(struct task_group *tg, unsigned long shares)
+ spin_lock_irqsave(&task_group_lock, flags);
+ for_each_possible_cpu(i)
+ register_fair_sched_group(tg, i);
++ list_add_rcu(&tg->siblings, &tg->parent->children);
+ spin_unlock_irqrestore(&task_group_lock, flags);
+ done:
+ mutex_unlock(&shares_mutex);
+@@ -7779,26 +8790,58 @@ static unsigned long to_ratio(u64 period, u64 runtime)
+ return div64_64(runtime << 16, period);
+ }
+
++#ifdef CONFIG_CGROUP_SCHED
++static int __rt_schedulable(struct task_group *tg, u64 period, u64 runtime)
++{
++ struct task_group *tgi, *parent = tg->parent;
++ unsigned long total = 0;
++
++ if (!parent) {
++ if (global_rt_period() < period)
++ return 0;
++
++ return to_ratio(period, runtime) <
++ to_ratio(global_rt_period(), global_rt_runtime());
++ }
++
++ if (ktime_to_ns(parent->rt_bandwidth.rt_period) < period)
++ return 0;
++
++ rcu_read_lock();
++ list_for_each_entry_rcu(tgi, &parent->children, siblings) {
++ if (tgi == tg)
++ continue;
++
++ total += to_ratio(ktime_to_ns(tgi->rt_bandwidth.rt_period),
++ tgi->rt_bandwidth.rt_runtime);
++ }
++ rcu_read_unlock();
++
++ return total + to_ratio(period, runtime) <
++ to_ratio(ktime_to_ns(parent->rt_bandwidth.rt_period),
++ parent->rt_bandwidth.rt_runtime);
++}
++#elif defined CONFIG_USER_SCHED
+ static int __rt_schedulable(struct task_group *tg, u64 period, u64 runtime)
+ {
+ struct task_group *tgi;
+ unsigned long total = 0;
+ unsigned long global_ratio =
+- to_ratio(sysctl_sched_rt_period,
+- sysctl_sched_rt_runtime < 0 ?
+- RUNTIME_INF : sysctl_sched_rt_runtime);
++ to_ratio(global_rt_period(), global_rt_runtime());
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(tgi, &task_groups, list) {
+ if (tgi == tg)
+ continue;
+
+- total += to_ratio(period, tgi->rt_runtime);
++ total += to_ratio(ktime_to_ns(tgi->rt_bandwidth.rt_period),
++ tgi->rt_bandwidth.rt_runtime);
+ }
+ rcu_read_unlock();
+
+ return total + to_ratio(period, runtime) < global_ratio;
+ }
++#endif
+
+ /* Must be called with tasklist_lock held */
+ static inline int tg_has_rt_tasks(struct task_group *tg)
+@@ -7811,19 +8854,14 @@ static inline int tg_has_rt_tasks(struct task_group *tg)
+ return 0;
+ }
+
+-int sched_group_set_rt_runtime(struct task_group *tg, long rt_runtime_us)
++static int tg_set_bandwidth(struct task_group *tg,
++ u64 rt_period, u64 rt_runtime)
+ {
+- u64 rt_runtime, rt_period;
+- int err = 0;
+-
+- rt_period = (u64)sysctl_sched_rt_period * NSEC_PER_USEC;
+- rt_runtime = (u64)rt_runtime_us * NSEC_PER_USEC;
+- if (rt_runtime_us == -1)
+- rt_runtime = RUNTIME_INF;
++ int i, err = 0;
+
+ mutex_lock(&rt_constraints_mutex);
+ read_lock(&tasklist_lock);
+- if (rt_runtime_us == 0 && tg_has_rt_tasks(tg)) {
++ if (rt_runtime == 0 && tg_has_rt_tasks(tg)) {
+ err = -EBUSY;
+ goto unlock;
+ }
+@@ -7831,7 +8869,19 @@ int sched_group_set_rt_runtime(struct task_group *tg, long rt_runtime_us)
+ err = -EINVAL;
+ goto unlock;
+ }
+- tg->rt_runtime = rt_runtime;
++
++ spin_lock_irq(&tg->rt_bandwidth.rt_runtime_lock);
++ tg->rt_bandwidth.rt_period = ns_to_ktime(rt_period);
++ tg->rt_bandwidth.rt_runtime = rt_runtime;
++
++ for_each_possible_cpu(i) {
++ struct rt_rq *rt_rq = tg->rt_rq[i];
++
++ spin_lock(&rt_rq->rt_runtime_lock);
++ rt_rq->rt_runtime = rt_runtime;
++ spin_unlock(&rt_rq->rt_runtime_lock);
++ }
++ spin_unlock_irq(&tg->rt_bandwidth.rt_runtime_lock);
+ unlock:
+ read_unlock(&tasklist_lock);
+ mutex_unlock(&rt_constraints_mutex);
+@@ -7839,19 +8889,109 @@ int sched_group_set_rt_runtime(struct task_group *tg, long rt_runtime_us)
+ return err;
+ }
+
++int sched_group_set_rt_runtime(struct task_group *tg, long rt_runtime_us)
++{
++ u64 rt_runtime, rt_period;
++
++ rt_period = ktime_to_ns(tg->rt_bandwidth.rt_period);
++ rt_runtime = (u64)rt_runtime_us * NSEC_PER_USEC;
++ if (rt_runtime_us < 0)
++ rt_runtime = RUNTIME_INF;
++
++ return tg_set_bandwidth(tg, rt_period, rt_runtime);
++}
++
+ long sched_group_rt_runtime(struct task_group *tg)
+ {
+ u64 rt_runtime_us;
+
+- if (tg->rt_runtime == RUNTIME_INF)
++ if (tg->rt_bandwidth.rt_runtime == RUNTIME_INF)
+ return -1;
+
+- rt_runtime_us = tg->rt_runtime;
++ rt_runtime_us = tg->rt_bandwidth.rt_runtime;
+ do_div(rt_runtime_us, NSEC_PER_USEC);
+ return rt_runtime_us;
+ }
++
++int sched_group_set_rt_period(struct task_group *tg, long rt_period_us)
++{
++ u64 rt_runtime, rt_period;
++
++ rt_period = (u64)rt_period_us * NSEC_PER_USEC;
++ rt_runtime = tg->rt_bandwidth.rt_runtime;
++
++ return tg_set_bandwidth(tg, rt_period, rt_runtime);
++}
++
++long sched_group_rt_period(struct task_group *tg)
++{
++ u64 rt_period_us;
++
++ rt_period_us = ktime_to_ns(tg->rt_bandwidth.rt_period);
++ do_div(rt_period_us, NSEC_PER_USEC);
++ return rt_period_us;
++}
++
++static int sched_rt_global_constraints(void)
++{
++ int ret = 0;
++
++ mutex_lock(&rt_constraints_mutex);
++ if (!__rt_schedulable(NULL, 1, 0))
++ ret = -EINVAL;
++ mutex_unlock(&rt_constraints_mutex);
++
++ return ret;
++}
++#else
++static int sched_rt_global_constraints(void)
++{
++ unsigned long flags;
++ int i;
++
++ spin_lock_irqsave(&def_rt_bandwidth.rt_runtime_lock, flags);
++ for_each_possible_cpu(i) {
++ struct rt_rq *rt_rq = &cpu_rq(i)->rt;
++
++ spin_lock(&rt_rq->rt_runtime_lock);
++ rt_rq->rt_runtime = global_rt_runtime();
++ spin_unlock(&rt_rq->rt_runtime_lock);
++ }
++ spin_unlock_irqrestore(&def_rt_bandwidth.rt_runtime_lock, flags);
++
++ return 0;
++}
+ #endif
+-#endif /* CONFIG_GROUP_SCHED */
++
++int sched_rt_handler(struct ctl_table *table, int write,
++ struct file *filp, void __user *buffer, size_t *lenp,
++ loff_t *ppos)
++{
++ int ret;
++ int old_period, old_runtime;
++ static DEFINE_MUTEX(mutex);
++
++ mutex_lock(&mutex);
++ old_period = sysctl_sched_rt_period;
++ old_runtime = sysctl_sched_rt_runtime;
++
++ ret = proc_dointvec(table, write, filp, buffer, lenp, ppos);
++
++ if (!ret && write) {
++ ret = sched_rt_global_constraints();
++ if (ret) {
++ sysctl_sched_rt_period = old_period;
++ sysctl_sched_rt_runtime = old_runtime;
++ } else {
++ def_rt_bandwidth.rt_runtime = global_rt_runtime();
++ def_rt_bandwidth.rt_period =
++ ns_to_ktime(global_rt_period());
++ }
++ }
++ mutex_unlock(&mutex);
++
++ return ret;
++}
+
+ #ifdef CONFIG_CGROUP_SCHED
+
+@@ -7865,7 +9005,7 @@ static inline struct task_group *cgroup_tg(struct cgroup *cgrp)
+ static struct cgroup_subsys_state *
+ cpu_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cgrp)
+ {
+- struct task_group *tg;
++ struct task_group *tg, *parent;
+
+ if (!cgrp->parent) {
+ /* This is early initialization for the top cgroup */
+@@ -7873,11 +9013,8 @@ cpu_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cgrp)
+ return &init_task_group.css;
+ }
+
+- /* we support only 1-level deep hierarchical scheduler atm */
+- if (cgrp->parent->parent)
+- return ERR_PTR(-EINVAL);
+-
+- tg = sched_create_group();
++ parent = cgroup_tg(cgrp->parent);
++ tg = sched_create_group(parent);
+ if (IS_ERR(tg))
+ return ERR_PTR(-ENOMEM);
+
+@@ -7901,7 +9038,7 @@ cpu_cgroup_can_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
+ {
+ #ifdef CONFIG_RT_GROUP_SCHED
+ /* Don't accept realtime tasks when there is no way for them to run */
+- if (rt_task(tsk) && cgroup_tg(cgrp)->rt_runtime == 0)
++ if (rt_task(tsk) && cgroup_tg(cgrp)->rt_bandwidth.rt_runtime == 0)
+ return -EINVAL;
+ #else
+ /* We don't support RT-tasks being in separate groups */
+@@ -7935,7 +9072,7 @@ static u64 cpu_shares_read_uint(struct cgroup *cgrp, struct cftype *cft)
+ #endif
+
+ #ifdef CONFIG_RT_GROUP_SCHED
+-static int cpu_rt_runtime_write(struct cgroup *cgrp, struct cftype *cft,
++static ssize_t cpu_rt_runtime_write(struct cgroup *cgrp, struct cftype *cft,
+ struct file *file,
+ const char __user *userbuf,
+ size_t nbytes, loff_t *unused_ppos)
+@@ -7979,6 +9116,17 @@ static ssize_t cpu_rt_runtime_read(struct cgroup *cgrp, struct cftype *cft,
+
+ return simple_read_from_buffer(buf, nbytes, ppos, tmp, len);
+ }
++
++static int cpu_rt_period_write_uint(struct cgroup *cgrp, struct cftype *cftype,
++ u64 rt_period_us)
++{
++ return sched_group_set_rt_period(cgroup_tg(cgrp), rt_period_us);
++}
++
++static u64 cpu_rt_period_read_uint(struct cgroup *cgrp, struct cftype *cft)
++{
++ return sched_group_rt_period(cgroup_tg(cgrp));
++}
+ #endif
+
+ static struct cftype cpu_files[] = {
+@@ -7995,6 +9143,11 @@ static struct cftype cpu_files[] = {
+ .read = cpu_rt_runtime_read,
+ .write = cpu_rt_runtime_write,
+ },
++ {
++ .name = "rt_period_us",
++ .read_uint = cpu_rt_period_read_uint,
++ .write_uint = cpu_rt_period_write_uint,
++ },
+ #endif
+ };
+
+@@ -8035,9 +9188,9 @@ struct cpuacct {
+ struct cgroup_subsys cpuacct_subsys;
+
+ /* return cpu accounting group corresponding to this container */
+-static inline struct cpuacct *cgroup_ca(struct cgroup *cont)
++static inline struct cpuacct *cgroup_ca(struct cgroup *cgrp)
+ {
+- return container_of(cgroup_subsys_state(cont, cpuacct_subsys_id),
++ return container_of(cgroup_subsys_state(cgrp, cpuacct_subsys_id),
+ struct cpuacct, css);
+ }
+
+@@ -8050,7 +9203,7 @@ static inline struct cpuacct *task_ca(struct task_struct *tsk)
+
+ /* create a new cpu accounting group */
+ static struct cgroup_subsys_state *cpuacct_create(
+- struct cgroup_subsys *ss, struct cgroup *cont)
++ struct cgroup_subsys *ss, struct cgroup *cgrp)
+ {
+ struct cpuacct *ca = kzalloc(sizeof(*ca), GFP_KERNEL);
+
+@@ -8068,18 +9221,18 @@ static struct cgroup_subsys_state *cpuacct_create(
+
+ /* destroy an existing cpu accounting group */
+ static void
+-cpuacct_destroy(struct cgroup_subsys *ss, struct cgroup *cont)
++cpuacct_destroy(struct cgroup_subsys *ss, struct cgroup *cgrp)
+ {
+- struct cpuacct *ca = cgroup_ca(cont);
++ struct cpuacct *ca = cgroup_ca(cgrp);
+
+ free_percpu(ca->cpuusage);
+ kfree(ca);
+ }
+
+ /* return total cpu usage (in nanoseconds) of a group */
+-static u64 cpuusage_read(struct cgroup *cont, struct cftype *cft)
++static u64 cpuusage_read(struct cgroup *cgrp, struct cftype *cft)
+ {
+- struct cpuacct *ca = cgroup_ca(cont);
++ struct cpuacct *ca = cgroup_ca(cgrp);
+ u64 totalcpuusage = 0;
+ int i;
+
+@@ -8098,16 +9251,40 @@ static u64 cpuusage_read(struct cgroup *cont, struct cftype *cft)
+ return totalcpuusage;
+ }
+
++static int cpuusage_write(struct cgroup *cgrp, struct cftype *cftype,
++ u64 reset)
++{
++ struct cpuacct *ca = cgroup_ca(cgrp);
++ int err = 0;
++ int i;
++
++ if (reset) {
++ err = -EINVAL;
++ goto out;
++ }
++
++ for_each_possible_cpu(i) {
++ u64 *cpuusage = percpu_ptr(ca->cpuusage, i);
++
++ spin_lock_irq(&cpu_rq(i)->lock);
++ *cpuusage = 0;
++ spin_unlock_irq(&cpu_rq(i)->lock);
++ }
++out:
++ return err;
++}
++
+ static struct cftype files[] = {
+ {
+ .name = "usage",
+ .read_uint = cpuusage_read,
++ .write_uint = cpuusage_write,
+ },
+ };
+
+-static int cpuacct_populate(struct cgroup_subsys *ss, struct cgroup *cont)
++static int cpuacct_populate(struct cgroup_subsys *ss, struct cgroup *cgrp)
+ {
+- return cgroup_add_files(cont, ss, files, ARRAY_SIZE(files));
++ return cgroup_add_files(cgrp, ss, files, ARRAY_SIZE(files));
+ }
+
+ /*
+diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c
+index ef358ba..f3f4af4 100644
+--- a/kernel/sched_debug.c
++++ b/kernel/sched_debug.c
+@@ -67,14 +67,24 @@ print_task(struct seq_file *m, struct rq *rq, struct task_struct *p)
+ (long long)(p->nvcsw + p->nivcsw),
+ p->prio);
+ #ifdef CONFIG_SCHEDSTATS
+- SEQ_printf(m, "%9Ld.%06ld %9Ld.%06ld %9Ld.%06ld\n",
++ SEQ_printf(m, "%9Ld.%06ld %9Ld.%06ld %9Ld.%06ld",
+ SPLIT_NS(p->se.vruntime),
+ SPLIT_NS(p->se.sum_exec_runtime),
+ SPLIT_NS(p->se.sum_sleep_runtime));
+ #else
+- SEQ_printf(m, "%15Ld %15Ld %15Ld.%06ld %15Ld.%06ld %15Ld.%06ld\n",
++ SEQ_printf(m, "%15Ld %15Ld %15Ld.%06ld %15Ld.%06ld %15Ld.%06ld",
+ 0LL, 0LL, 0LL, 0L, 0LL, 0L, 0LL, 0L);
+ #endif
++
++#ifdef CONFIG_CGROUP_SCHED
++ {
++ char path[64];
++
++ cgroup_path(task_group(p)->css.cgroup, path, sizeof(path));
++ SEQ_printf(m, " %s", path);
++ }
++#endif
++ SEQ_printf(m, "\n");
+ }
+
+ static void print_rq(struct seq_file *m, struct rq *rq, int rq_cpu)
+@@ -109,7 +119,21 @@ void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
+ struct sched_entity *last;
+ unsigned long flags;
+
+- SEQ_printf(m, "\ncfs_rq\n");
++#if !defined(CONFIG_CGROUP_SCHED) || !defined(CONFIG_USER_SCHED)
++ SEQ_printf(m, "\ncfs_rq[%d]:\n", cpu);
++#else
++ char path[128] = "";
++ struct cgroup *cgroup = NULL;
++ struct task_group *tg = cfs_rq->tg;
++
++ if (tg)
++ cgroup = tg->css.cgroup;
++
++ if (cgroup)
++ cgroup_path(cgroup, path, sizeof(path));
++
++ SEQ_printf(m, "\ncfs_rq[%d]:%s\n", cpu, path);
++#endif
+
+ SEQ_printf(m, " .%-30s: %Ld.%06ld\n", "exec_clock",
+ SPLIT_NS(cfs_rq->exec_clock));
+@@ -143,6 +167,11 @@ void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
+ #endif
+ SEQ_printf(m, " .%-30s: %ld\n", "nr_spread_over",
+ cfs_rq->nr_spread_over);
++#ifdef CONFIG_FAIR_GROUP_SCHED
++#ifdef CONFIG_SMP
++ SEQ_printf(m, " .%-30s: %lu\n", "shares", cfs_rq->shares);
++#endif
++#endif
+ }
+
+ static void print_cpu(struct seq_file *m, int cpu)
+@@ -214,7 +243,6 @@ static int sched_debug_show(struct seq_file *m, void *v)
+ PN(sysctl_sched_latency);
+ PN(sysctl_sched_min_granularity);
+ PN(sysctl_sched_wakeup_granularity);
+- PN(sysctl_sched_batch_wakeup_granularity);
+ PN(sysctl_sched_child_runs_first);
+ P(sysctl_sched_features);
+ #undef PN
+diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
+index 0080968..89fa32b 100644
+--- a/kernel/sched_fair.c
++++ b/kernel/sched_fair.c
+@@ -62,24 +62,14 @@ const_debug unsigned int sysctl_sched_child_runs_first = 1;
+ unsigned int __read_mostly sysctl_sched_compat_yield;
+
+ /*
+- * SCHED_BATCH wake-up granularity.
+- * (default: 10 msec * (1 + ilog(ncpus)), units: nanoseconds)
+- *
+- * This option delays the preemption effects of decoupled workloads
+- * and reduces their over-scheduling. Synchronous workloads will still
+- * have immediate wakeup/sleep latencies.
+- */
+-unsigned int sysctl_sched_batch_wakeup_granularity = 10000000UL;
+-
+-/*
+ * SCHED_OTHER wake-up granularity.
+- * (default: 5 msec * (1 + ilog(ncpus)), units: nanoseconds)
++ * (default: 10 msec * (1 + ilog(ncpus)), units: nanoseconds)
+ *
+ * This option delays the preemption effects of decoupled workloads
+ * and reduces their over-scheduling. Synchronous workloads will still
+ * have immediate wakeup/sleep latencies.
+ */
+-unsigned int sysctl_sched_wakeup_granularity = 5000000UL;
++unsigned int sysctl_sched_wakeup_granularity = 10000000UL;
+
+ const_debug unsigned int sysctl_sched_migration_cost = 500000UL;
+
+@@ -87,6 +77,11 @@ const_debug unsigned int sysctl_sched_migration_cost = 500000UL;
+ * CFS operations on generic schedulable entities:
+ */
+
++static inline struct task_struct *task_of(struct sched_entity *se)
++{
++ return container_of(se, struct task_struct, se);
++}
++
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+
+ /* cpu runqueue to which this cfs_rq is attached */
+@@ -98,6 +93,54 @@ static inline struct rq *rq_of(struct cfs_rq *cfs_rq)
+ /* An entity is a task if it doesn't "own" a runqueue */
+ #define entity_is_task(se) (!se->my_q)
+
++/* Walk up scheduling entities hierarchy */
++#define for_each_sched_entity(se) \
++ for (; se; se = se->parent)
++
++static inline struct cfs_rq *task_cfs_rq(struct task_struct *p)
++{
++ return p->se.cfs_rq;
++}
++
++/* runqueue on which this entity is (to be) queued */
++static inline struct cfs_rq *cfs_rq_of(struct sched_entity *se)
++{
++ return se->cfs_rq;
++}
++
++/* runqueue "owned" by this group */
++static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp)
++{
++ return grp->my_q;
++}
++
++/* Given a group's cfs_rq on one cpu, return its corresponding cfs_rq on
++ * another cpu ('this_cpu')
++ */
++static inline struct cfs_rq *cpu_cfs_rq(struct cfs_rq *cfs_rq, int this_cpu)
++{
++ return cfs_rq->tg->cfs_rq[this_cpu];
++}
++
++/* Iterate thr' all leaf cfs_rq's on a runqueue */
++#define for_each_leaf_cfs_rq(rq, cfs_rq) \
++ list_for_each_entry_rcu(cfs_rq, &rq->leaf_cfs_rq_list, leaf_cfs_rq_list)
++
++/* Do the two (enqueued) entities belong to the same group ? */
++static inline int
++is_same_group(struct sched_entity *se, struct sched_entity *pse)
++{
++ if (se->cfs_rq == pse->cfs_rq)
++ return 1;
++
++ return 0;
++}
++
++static inline struct sched_entity *parent_entity(struct sched_entity *se)
++{
++ return se->parent;
++}
++
+ #else /* CONFIG_FAIR_GROUP_SCHED */
+
+ static inline struct rq *rq_of(struct cfs_rq *cfs_rq)
+@@ -107,13 +150,49 @@ static inline struct rq *rq_of(struct cfs_rq *cfs_rq)
+
+ #define entity_is_task(se) 1
+
+-#endif /* CONFIG_FAIR_GROUP_SCHED */
++#define for_each_sched_entity(se) \
++ for (; se; se = NULL)
+
+-static inline struct task_struct *task_of(struct sched_entity *se)
++static inline struct cfs_rq *task_cfs_rq(struct task_struct *p)
+ {
+- return container_of(se, struct task_struct, se);
++ return &task_rq(p)->cfs;
++}
++
++static inline struct cfs_rq *cfs_rq_of(struct sched_entity *se)
++{
++ struct task_struct *p = task_of(se);
++ struct rq *rq = task_rq(p);
++
++ return &rq->cfs;
++}
++
++/* runqueue "owned" by this group */
++static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp)
++{
++ return NULL;
++}
++
++static inline struct cfs_rq *cpu_cfs_rq(struct cfs_rq *cfs_rq, int this_cpu)
++{
++ return &cpu_rq(this_cpu)->cfs;
++}
++
++#define for_each_leaf_cfs_rq(rq, cfs_rq) \
++ for (cfs_rq = &rq->cfs; cfs_rq; cfs_rq = NULL)
++
++static inline int
++is_same_group(struct sched_entity *se, struct sched_entity *pse)
++{
++ return 1;
++}
++
++static inline struct sched_entity *parent_entity(struct sched_entity *se)
++{
++ return NULL;
+ }
+
++#endif /* CONFIG_FAIR_GROUP_SCHED */
++
+
+ /**************************************************************
+ * Scheduling class tree data structure manipulation methods:
+@@ -255,6 +334,34 @@ int sched_nr_latency_handler(struct ctl_table *table, int write,
+ #endif
+
+ /*
++ * delta *= w / rw
++ */
++static inline unsigned long
++calc_delta_weight(unsigned long delta, struct sched_entity *se)
++{
++ for_each_sched_entity(se) {
++ delta = calc_delta_mine(delta,
++ se->load.weight, &cfs_rq_of(se)->load);
++ }
++
++ return delta;
++}
++
++/*
++ * delta *= rw / w
++ */
++static inline unsigned long
++calc_delta_fair(unsigned long delta, struct sched_entity *se)
++{
++ for_each_sched_entity(se) {
++ delta = calc_delta_mine(delta,
++ cfs_rq_of(se)->load.weight, &se->load);
++ }
++
++ return delta;
++}
++
++/*
+ * The idea is to set a period in which each task runs once.
+ *
+ * When there are too many tasks (sysctl_sched_nr_latency) we have to stretch
+@@ -283,29 +390,54 @@ static u64 __sched_period(unsigned long nr_running)
+ */
+ static u64 sched_slice(struct cfs_rq *cfs_rq, struct sched_entity *se)
+ {
+- return calc_delta_mine(__sched_period(cfs_rq->nr_running),
+- se->load.weight, &cfs_rq->load);
++ return calc_delta_weight(__sched_period(cfs_rq->nr_running), se);
+ }
+
+ /*
+- * We calculate the vruntime slice.
++ * We calculate the vruntime slice of a to be inserted task
+ *
+- * vs = s/w = p/rw
++ * vs = s*rw/w = p
+ */
+-static u64 __sched_vslice(unsigned long rq_weight, unsigned long nr_running)
++static u64 sched_vslice_add(struct cfs_rq *cfs_rq, struct sched_entity *se)
+ {
+- u64 vslice = __sched_period(nr_running);
++ unsigned long nr_running = cfs_rq->nr_running;
+
+- vslice *= NICE_0_LOAD;
+- do_div(vslice, rq_weight);
++ if (!se->on_rq)
++ nr_running++;
+
+- return vslice;
++ return __sched_period(nr_running);
+ }
+
+-static u64 sched_vslice_add(struct cfs_rq *cfs_rq, struct sched_entity *se)
++/*
++ * The goal of calc_delta_asym() is to be asymmetrically around NICE_0_LOAD, in
++ * that it favours >=0 over <0.
++ *
++ * -20 |
++ * |
++ * 0 --------+-------
++ * .'
++ * 19 .'
++ *
++ */
++static unsigned long
++calc_delta_asym(unsigned long delta, struct sched_entity *se)
+ {
+- return __sched_vslice(cfs_rq->load.weight + se->load.weight,
+- cfs_rq->nr_running + 1);
++ struct load_weight lw = {
++ .weight = NICE_0_LOAD,
++ .inv_weight = 1UL << (WMULT_SHIFT-NICE_0_SHIFT)
++ };
++
++ for_each_sched_entity(se) {
++ struct load_weight *se_lw = &se->load;
++
++ if (se->load.weight < NICE_0_LOAD)
++ se_lw = &lw;
++
++ delta = calc_delta_mine(delta,
++ cfs_rq_of(se)->load.weight, se_lw);
++ }
++
++ return delta;
+ }
+
+ /*
+@@ -322,11 +454,7 @@ __update_curr(struct cfs_rq *cfs_rq, struct sched_entity *curr,
+
+ curr->sum_exec_runtime += delta_exec;
+ schedstat_add(cfs_rq, exec_clock, delta_exec);
+- delta_exec_weighted = delta_exec;
+- if (unlikely(curr->load.weight != NICE_0_LOAD)) {
+- delta_exec_weighted = calc_delta_fair(delta_exec_weighted,
+- &curr->load);
+- }
++ delta_exec_weighted = calc_delta_fair(delta_exec, curr);
+ curr->vruntime += delta_exec_weighted;
+ }
+
+@@ -413,20 +541,43 @@ update_stats_curr_start(struct cfs_rq *cfs_rq, struct sched_entity *se)
+ * Scheduling class queueing methods:
+ */
+
++#if defined CONFIG_SMP && defined CONFIG_FAIR_GROUP_SCHED
++static void
++add_cfs_task_weight(struct cfs_rq *cfs_rq, unsigned long weight)
++{
++ cfs_rq->task_weight += weight;
++}
++#else
++static inline void
++add_cfs_task_weight(struct cfs_rq *cfs_rq, unsigned long weight)
++{
++}
++#endif
++
+ static void
+ account_entity_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se)
+ {
+ update_load_add(&cfs_rq->load, se->load.weight);
++ if (!parent_entity(se))
++ inc_cpu_load(rq_of(cfs_rq), se->load.weight);
++ if (entity_is_task(se))
++ add_cfs_task_weight(cfs_rq, se->load.weight);
+ cfs_rq->nr_running++;
+ se->on_rq = 1;
++ list_add(&se->group_node, &cfs_rq->tasks);
+ }
+
+ static void
+ account_entity_dequeue(struct cfs_rq *cfs_rq, struct sched_entity *se)
+ {
+ update_load_sub(&cfs_rq->load, se->load.weight);
++ if (!parent_entity(se))
++ dec_cpu_load(rq_of(cfs_rq), se->load.weight);
++ if (entity_is_task(se))
++ add_cfs_task_weight(cfs_rq, -se->load.weight);
+ cfs_rq->nr_running--;
+ se->on_rq = 0;
++ list_del_init(&se->group_node);
+ }
+
+ static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se)
+@@ -510,8 +661,12 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial)
+
+ if (!initial) {
+ /* sleeps upto a single latency don't count. */
+- if (sched_feat(NEW_FAIR_SLEEPERS))
+- vruntime -= sysctl_sched_latency;
++ if (sched_feat(NEW_FAIR_SLEEPERS)) {
++ if (sched_feat(NORMALIZED_SLEEPER))
++ vruntime -= calc_delta_weight(sysctl_sched_latency, se);
++ else
++ vruntime -= sysctl_sched_latency;
++ }
+
+ /* ensure we never gain time by being placed backwards. */
+ vruntime = max_vruntime(se->vruntime, vruntime);
+@@ -627,20 +782,16 @@ set_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
+ se->prev_sum_exec_runtime = se->sum_exec_runtime;
+ }
+
++static int
++wakeup_preempt_entity(struct sched_entity *curr, struct sched_entity *se);
++
+ static struct sched_entity *
+ pick_next(struct cfs_rq *cfs_rq, struct sched_entity *se)
+ {
+- s64 diff, gran;
+-
+ if (!cfs_rq->next)
+ return se;
+
+- diff = cfs_rq->next->vruntime - se->vruntime;
+- if (diff < 0)
+- return se;
+-
+- gran = calc_delta_fair(sysctl_sched_wakeup_granularity, &cfs_rq->load);
+- if (diff > gran)
++ if (wakeup_preempt_entity(cfs_rq->next, se) != 0)
+ return se;
+
+ return cfs_rq->next;
+@@ -708,101 +859,6 @@ entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr, int queued)
+ * CFS operations on tasks:
+ */
+
+-#ifdef CONFIG_FAIR_GROUP_SCHED
+-
+-/* Walk up scheduling entities hierarchy */
+-#define for_each_sched_entity(se) \
+- for (; se; se = se->parent)
+-
+-static inline struct cfs_rq *task_cfs_rq(struct task_struct *p)
+-{
+- return p->se.cfs_rq;
+-}
+-
+-/* runqueue on which this entity is (to be) queued */
+-static inline struct cfs_rq *cfs_rq_of(struct sched_entity *se)
+-{
+- return se->cfs_rq;
+-}
+-
+-/* runqueue "owned" by this group */
+-static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp)
+-{
+- return grp->my_q;
+-}
+-
+-/* Given a group's cfs_rq on one cpu, return its corresponding cfs_rq on
+- * another cpu ('this_cpu')
+- */
+-static inline struct cfs_rq *cpu_cfs_rq(struct cfs_rq *cfs_rq, int this_cpu)
+-{
+- return cfs_rq->tg->cfs_rq[this_cpu];
+-}
+-
+-/* Iterate thr' all leaf cfs_rq's on a runqueue */
+-#define for_each_leaf_cfs_rq(rq, cfs_rq) \
+- list_for_each_entry_rcu(cfs_rq, &rq->leaf_cfs_rq_list, leaf_cfs_rq_list)
+-
+-/* Do the two (enqueued) entities belong to the same group ? */
+-static inline int
+-is_same_group(struct sched_entity *se, struct sched_entity *pse)
+-{
+- if (se->cfs_rq == pse->cfs_rq)
+- return 1;
+-
+- return 0;
+-}
+-
+-static inline struct sched_entity *parent_entity(struct sched_entity *se)
+-{
+- return se->parent;
+-}
+-
+-#else /* CONFIG_FAIR_GROUP_SCHED */
+-
+-#define for_each_sched_entity(se) \
+- for (; se; se = NULL)
+-
+-static inline struct cfs_rq *task_cfs_rq(struct task_struct *p)
+-{
+- return &task_rq(p)->cfs;
+-}
+-
+-static inline struct cfs_rq *cfs_rq_of(struct sched_entity *se)
+-{
+- struct task_struct *p = task_of(se);
+- struct rq *rq = task_rq(p);
+-
+- return &rq->cfs;
+-}
+-
+-/* runqueue "owned" by this group */
+-static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp)
+-{
+- return NULL;
+-}
+-
+-static inline struct cfs_rq *cpu_cfs_rq(struct cfs_rq *cfs_rq, int this_cpu)
+-{
+- return &cpu_rq(this_cpu)->cfs;
+-}
+-
+-#define for_each_leaf_cfs_rq(rq, cfs_rq) \
+- for (cfs_rq = &rq->cfs; cfs_rq; cfs_rq = NULL)
+-
+-static inline int
+-is_same_group(struct sched_entity *se, struct sched_entity *pse)
+-{
+- return 1;
+-}
+-
+-static inline struct sched_entity *parent_entity(struct sched_entity *se)
+-{
+- return NULL;
+-}
+-
+-#endif /* CONFIG_FAIR_GROUP_SCHED */
+-
+ #ifdef CONFIG_SCHED_HRTICK
+ static void hrtick_start_fair(struct rq *rq, struct task_struct *p)
+ {
+@@ -916,7 +972,7 @@ static void yield_task_fair(struct rq *rq)
+ /*
+ * Already in the rightmost position?
+ */
+- if (unlikely(rightmost->vruntime < se->vruntime))
++ if (unlikely(!rightmost || rightmost->vruntime < se->vruntime))
+ return;
+
+ /*
+@@ -955,7 +1011,9 @@ static int wake_idle(int cpu, struct task_struct *p)
+ return cpu;
+
+ for_each_domain(cpu, sd) {
+- if (sd->flags & SD_WAKE_IDLE) {
++ if ((sd->flags & SD_WAKE_IDLE)
++ || ((sd->flags & SD_WAKE_IDLE_FAR)
++ && !task_hot(p, task_rq(p)->clock, sd))) {
+ cpus_and(tmp, sd->span, p->cpus_allowed);
+ for_each_cpu_mask(i, tmp) {
+ if (idle_cpu(i)) {
+@@ -1099,6 +1157,58 @@ out:
+ }
+ #endif /* CONFIG_SMP */
+
++static unsigned long wakeup_gran(struct sched_entity *se)
++{
++ unsigned long gran = sysctl_sched_wakeup_granularity;
++
++ /*
++ * More easily preempt - nice tasks, while not making it harder for
++ * + nice tasks.
++ */
++ gran = calc_delta_asym(sysctl_sched_wakeup_granularity, se);
++
++ return gran;
++}
++
++/*
++ * Should 'se' preempt 'curr'.
++ *
++ * |s1
++ * |s2
++ * |s3
++ * g
++ * |<--->|c
++ *
++ * w(c, s1) = -1
++ * w(c, s2) = 0
++ * w(c, s3) = 1
++ *
++ */
++static int
++wakeup_preempt_entity(struct sched_entity *curr, struct sched_entity *se)
++{
++ s64 gran, vdiff = curr->vruntime - se->vruntime;
++
++ if (vdiff < 0)
++ return -1;
++
++ gran = wakeup_gran(curr);
++ if (vdiff > gran)
++ return 1;
++
++ return 0;
++}
++
++/* return depth at which a sched entity is present in the hierarchy */
++static inline int depth_se(struct sched_entity *se)
++{
++ int depth = 0;
++
++ for_each_sched_entity(se)
++ depth++;
++
++ return depth;
++}
+
+ /*
+ * Preempt the current task with a newly woken task if needed:
+@@ -1108,7 +1218,7 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p)
+ struct task_struct *curr = rq->curr;
+ struct cfs_rq *cfs_rq = task_cfs_rq(curr);
+ struct sched_entity *se = &curr->se, *pse = &p->se;
+- unsigned long gran;
++ int se_depth, pse_depth;
+
+ if (unlikely(rt_prio(p->prio))) {
+ update_rq_clock(rq);
+@@ -1133,20 +1243,33 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p)
+ if (!sched_feat(WAKEUP_PREEMPT))
+ return;
+
+- while (!is_same_group(se, pse)) {
++ /*
++ * preemption test can be made between sibling entities who are in the
++ * same cfs_rq i.e who have a common parent. Walk up the hierarchy of
++ * both tasks until we find their ancestors who are siblings of common
++ * parent.
++ */
++
++ /* First walk up until both entities are at same depth */
++ se_depth = depth_se(se);
++ pse_depth = depth_se(pse);
++
++ while (se_depth > pse_depth) {
++ se_depth--;
+ se = parent_entity(se);
++ }
++
++ while (pse_depth > se_depth) {
++ pse_depth--;
+ pse = parent_entity(pse);
+ }
+
+- gran = sysctl_sched_wakeup_granularity;
+- /*
+- * More easily preempt - nice tasks, while not making
+- * it harder for + nice tasks.
+- */
+- if (unlikely(se->load.weight > NICE_0_LOAD))
+- gran = calc_delta_fair(gran, &se->load);
++ while (!is_same_group(se, pse)) {
++ se = parent_entity(se);
++ pse = parent_entity(pse);
++ }
+
+- if (pse->vruntime + gran < se->vruntime)
++ if (wakeup_preempt_entity(se, pse) == 1)
+ resched_task(curr);
+ }
+
+@@ -1197,15 +1320,27 @@ static void put_prev_task_fair(struct rq *rq, struct task_struct *prev)
+ * the current task:
+ */
+ static struct task_struct *
+-__load_balance_iterator(struct cfs_rq *cfs_rq, struct rb_node *curr)
++__load_balance_iterator(struct cfs_rq *cfs_rq, struct list_head *next)
+ {
+- struct task_struct *p;
++ struct task_struct *p = NULL;
++ struct sched_entity *se;
++
++ if (next == &cfs_rq->tasks)
++ return NULL;
++
++ /* Skip over entities that are not tasks */
++ do {
++ se = list_entry(next, struct sched_entity, group_node);
++ next = next->next;
++ } while (next != &cfs_rq->tasks && !entity_is_task(se));
+
+- if (!curr)
++ if (next == &cfs_rq->tasks)
+ return NULL;
+
+- p = rb_entry(curr, struct task_struct, se.run_node);
+- cfs_rq->rb_load_balance_curr = rb_next(curr);
++ cfs_rq->balance_iterator = next;
++
++ if (entity_is_task(se))
++ p = task_of(se);
+
+ return p;
+ }
+@@ -1214,85 +1349,100 @@ static struct task_struct *load_balance_start_fair(void *arg)
+ {
+ struct cfs_rq *cfs_rq = arg;
+
+- return __load_balance_iterator(cfs_rq, first_fair(cfs_rq));
++ return __load_balance_iterator(cfs_rq, cfs_rq->tasks.next);
+ }
+
+ static struct task_struct *load_balance_next_fair(void *arg)
+ {
+ struct cfs_rq *cfs_rq = arg;
+
+- return __load_balance_iterator(cfs_rq, cfs_rq->rb_load_balance_curr);
++ return __load_balance_iterator(cfs_rq, cfs_rq->balance_iterator);
+ }
+
+-#ifdef CONFIG_FAIR_GROUP_SCHED
+-static int cfs_rq_best_prio(struct cfs_rq *cfs_rq)
++static unsigned long
++__load_balance_fair(struct rq *this_rq, int this_cpu, struct rq *busiest,
++ unsigned long max_load_move, struct sched_domain *sd,
++ enum cpu_idle_type idle, int *all_pinned, int *this_best_prio,
++ struct cfs_rq *cfs_rq)
+ {
+- struct sched_entity *curr;
+- struct task_struct *p;
+-
+- if (!cfs_rq->nr_running || !first_fair(cfs_rq))
+- return MAX_PRIO;
+-
+- curr = cfs_rq->curr;
+- if (!curr)
+- curr = __pick_next_entity(cfs_rq);
++ struct rq_iterator cfs_rq_iterator;
+
+- p = task_of(curr);
++ cfs_rq_iterator.start = load_balance_start_fair;
++ cfs_rq_iterator.next = load_balance_next_fair;
++ cfs_rq_iterator.arg = cfs_rq;
+
+- return p->prio;
++ return balance_tasks(this_rq, this_cpu, busiest,
++ max_load_move, sd, idle, all_pinned,
++ this_best_prio, &cfs_rq_iterator);
+ }
+-#endif
+
++#ifdef CONFIG_FAIR_GROUP_SCHED
+ static unsigned long
+ load_balance_fair(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ unsigned long max_load_move,
+ struct sched_domain *sd, enum cpu_idle_type idle,
+ int *all_pinned, int *this_best_prio)
+ {
+- struct cfs_rq *busy_cfs_rq;
+ long rem_load_move = max_load_move;
+- struct rq_iterator cfs_rq_iterator;
+-
+- cfs_rq_iterator.start = load_balance_start_fair;
+- cfs_rq_iterator.next = load_balance_next_fair;
++ int busiest_cpu = cpu_of(busiest);
++ struct task_group *tg;
+
+- for_each_leaf_cfs_rq(busiest, busy_cfs_rq) {
+-#ifdef CONFIG_FAIR_GROUP_SCHED
+- struct cfs_rq *this_cfs_rq;
++ rcu_read_lock();
++ list_for_each_entry(tg, &task_groups, list) {
+ long imbalance;
+- unsigned long maxload;
++ unsigned long this_weight, busiest_weight;
++ long rem_load, max_load, moved_load;
++
++ /*
++ * empty group
++ */
++ if (!aggregate(tg, sd)->task_weight)
++ continue;
++
++ rem_load = rem_load_move * aggregate(tg, sd)->rq_weight;
++ rem_load /= aggregate(tg, sd)->load + 1;
++
++ this_weight = tg->cfs_rq[this_cpu]->task_weight;
++ busiest_weight = tg->cfs_rq[busiest_cpu]->task_weight;
++
++ imbalance = (busiest_weight - this_weight) / 2;
+
+- this_cfs_rq = cpu_cfs_rq(busy_cfs_rq, this_cpu);
++ if (imbalance < 0)
++ imbalance = busiest_weight;
+
+- imbalance = busy_cfs_rq->load.weight - this_cfs_rq->load.weight;
+- /* Don't pull if this_cfs_rq has more load than busy_cfs_rq */
+- if (imbalance <= 0)
++ max_load = max(rem_load, imbalance);
++ moved_load = __load_balance_fair(this_rq, this_cpu, busiest,
++ max_load, sd, idle, all_pinned, this_best_prio,
++ tg->cfs_rq[busiest_cpu]);
++
++ if (!moved_load)
+ continue;
+
+- /* Don't pull more than imbalance/2 */
+- imbalance /= 2;
+- maxload = min(rem_load_move, imbalance);
++ move_group_shares(tg, sd, busiest_cpu, this_cpu);
+
+- *this_best_prio = cfs_rq_best_prio(this_cfs_rq);
+-#else
+-# define maxload rem_load_move
+-#endif
+- /*
+- * pass busy_cfs_rq argument into
+- * load_balance_[start|next]_fair iterators
+- */
+- cfs_rq_iterator.arg = busy_cfs_rq;
+- rem_load_move -= balance_tasks(this_rq, this_cpu, busiest,
+- maxload, sd, idle, all_pinned,
+- this_best_prio,
+- &cfs_rq_iterator);
++ moved_load *= aggregate(tg, sd)->load;
++ moved_load /= aggregate(tg, sd)->rq_weight + 1;
+
+- if (rem_load_move <= 0)
++ rem_load_move -= moved_load;
++ if (rem_load_move < 0)
+ break;
+ }
++ rcu_read_unlock();
+
+ return max_load_move - rem_load_move;
+ }
++#else
++static unsigned long
++load_balance_fair(struct rq *this_rq, int this_cpu, struct rq *busiest,
++ unsigned long max_load_move,
++ struct sched_domain *sd, enum cpu_idle_type idle,
++ int *all_pinned, int *this_best_prio)
++{
++ return __load_balance_fair(this_rq, this_cpu, busiest,
++ max_load_move, sd, idle, all_pinned,
++ this_best_prio, &busiest->cfs);
++}
++#endif
+
+ static int
+ move_one_task_fair(struct rq *this_rq, int this_cpu, struct rq *busiest,
+@@ -1461,16 +1611,40 @@ static const struct sched_class fair_sched_class = {
+ };
+
+ #ifdef CONFIG_SCHED_DEBUG
++static void
++print_cfs_rq_tasks(struct seq_file *m, struct cfs_rq *cfs_rq, int depth)
++{
++ struct sched_entity *se;
++
++ if (!cfs_rq)
++ return;
++
++ list_for_each_entry_rcu(se, &cfs_rq->tasks, group_node) {
++ int i;
++
++ for (i = depth; i; i--)
++ seq_puts(m, " ");
++
++ seq_printf(m, "%lu %s %lu\n",
++ se->load.weight,
++ entity_is_task(se) ? "T" : "G",
++ calc_delta_weight(SCHED_LOAD_SCALE, se)
++ );
++ if (!entity_is_task(se))
++ print_cfs_rq_tasks(m, group_cfs_rq(se), depth + 1);
++ }
++}
++
+ static void print_cfs_stats(struct seq_file *m, int cpu)
+ {
+ struct cfs_rq *cfs_rq;
+
+-#ifdef CONFIG_FAIR_GROUP_SCHED
+- print_cfs_rq(m, cpu, &cpu_rq(cpu)->cfs);
+-#endif
+ rcu_read_lock();
+ for_each_leaf_cfs_rq(cpu_rq(cpu), cfs_rq)
+ print_cfs_rq(m, cpu, cfs_rq);
++
++ seq_printf(m, "\nWeight tree:\n");
++ print_cfs_rq_tasks(m, &cpu_rq(cpu)->cfs, 1);
+ rcu_read_unlock();
+ }
+ #endif
+diff --git a/kernel/sched_features.h b/kernel/sched_features.h
+new file mode 100644
+index 0000000..1c7283c
+--- /dev/null
++++ b/kernel/sched_features.h
+@@ -0,0 +1,10 @@
++SCHED_FEAT(NEW_FAIR_SLEEPERS, 1)
++SCHED_FEAT(WAKEUP_PREEMPT, 1)
++SCHED_FEAT(START_DEBIT, 1)
++SCHED_FEAT(AFFINE_WAKEUPS, 1)
++SCHED_FEAT(CACHE_HOT_BUDDY, 1)
++SCHED_FEAT(SYNC_WAKEUPS, 1)
++SCHED_FEAT(HRTICK, 1)
++SCHED_FEAT(DOUBLE_TICK, 0)
++SCHED_FEAT(NORMALIZED_SLEEPER, 1)
++SCHED_FEAT(DEADLINE, 1)
+diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
+index 0a6d2e5..c2730a5 100644
+--- a/kernel/sched_rt.c
++++ b/kernel/sched_rt.c
+@@ -62,7 +62,12 @@ static inline u64 sched_rt_runtime(struct rt_rq *rt_rq)
+ if (!rt_rq->tg)
+ return RUNTIME_INF;
+
+- return rt_rq->tg->rt_runtime;
++ return rt_rq->rt_runtime;
++}
++
++static inline u64 sched_rt_period(struct rt_rq *rt_rq)
++{
++ return ktime_to_ns(rt_rq->tg->rt_bandwidth.rt_period);
+ }
+
+ #define for_each_leaf_rt_rq(rt_rq, rq) \
+@@ -127,14 +132,39 @@ static int rt_se_boosted(struct sched_rt_entity *rt_se)
+ return p->prio != p->normal_prio;
+ }
+
++#ifdef CONFIG_SMP
++static inline cpumask_t sched_rt_period_mask(void)
++{
++ return cpu_rq(smp_processor_id())->rd->span;
++}
++#else
++static inline cpumask_t sched_rt_period_mask(void)
++{
++ return cpu_online_map;
++}
++#endif
++
++static inline
++struct rt_rq *sched_rt_period_rt_rq(struct rt_bandwidth *rt_b, int cpu)
++{
++ return container_of(rt_b, struct task_group, rt_bandwidth)->rt_rq[cpu];
++}
++
++static inline struct rt_bandwidth *sched_rt_bandwidth(struct rt_rq *rt_rq)
++{
++ return &rt_rq->tg->rt_bandwidth;
++}
++
+ #else
+
+ static inline u64 sched_rt_runtime(struct rt_rq *rt_rq)
+ {
+- if (sysctl_sched_rt_runtime == -1)
+- return RUNTIME_INF;
++ return rt_rq->rt_runtime;
++}
+
+- return (u64)sysctl_sched_rt_runtime * NSEC_PER_USEC;
++static inline u64 sched_rt_period(struct rt_rq *rt_rq)
++{
++ return ktime_to_ns(def_rt_bandwidth.rt_period);
+ }
+
+ #define for_each_leaf_rt_rq(rt_rq, rq) \
+@@ -173,6 +203,102 @@ static inline int rt_rq_throttled(struct rt_rq *rt_rq)
+ {
+ return rt_rq->rt_throttled;
+ }
++
++static inline cpumask_t sched_rt_period_mask(void)
++{
++ return cpu_online_map;
++}
++
++static inline
++struct rt_rq *sched_rt_period_rt_rq(struct rt_bandwidth *rt_b, int cpu)
++{
++ return &cpu_rq(cpu)->rt;
++}
++
++static inline struct rt_bandwidth *sched_rt_bandwidth(struct rt_rq *rt_rq)
++{
++ return &def_rt_bandwidth;
++}
++
++#endif
++
++static int do_sched_rt_period_timer(struct rt_bandwidth *rt_b, int overrun)
++{
++ int i, idle = 1;
++ cpumask_t span;
++
++ if (rt_b->rt_runtime == RUNTIME_INF)
++ return 1;
++
++ span = sched_rt_period_mask();
++ for_each_cpu_mask(i, span) {
++ int enqueue = 0;
++ struct rt_rq *rt_rq = sched_rt_period_rt_rq(rt_b, i);
++ struct rq *rq = rq_of_rt_rq(rt_rq);
++
++ spin_lock(&rq->lock);
++ if (rt_rq->rt_time) {
++ u64 runtime;
++
++ spin_lock(&rt_rq->rt_runtime_lock);
++ runtime = rt_rq->rt_runtime;
++ rt_rq->rt_time -= min(rt_rq->rt_time, overrun*runtime);
++ if (rt_rq->rt_throttled && rt_rq->rt_time < runtime) {
++ rt_rq->rt_throttled = 0;
++ enqueue = 1;
++ }
++ if (rt_rq->rt_time || rt_rq->rt_nr_running)
++ idle = 0;
++ spin_unlock(&rt_rq->rt_runtime_lock);
++ }
++
++ if (enqueue)
++ sched_rt_rq_enqueue(rt_rq);
++ spin_unlock(&rq->lock);
++ }
++
++ return idle;
++}
++
++#ifdef CONFIG_SMP
++static int balance_runtime(struct rt_rq *rt_rq)
++{
++ struct rt_bandwidth *rt_b = sched_rt_bandwidth(rt_rq);
++ struct root_domain *rd = cpu_rq(smp_processor_id())->rd;
++ int i, weight, more = 0;
++ u64 rt_period;
++
++ weight = cpus_weight(rd->span);
++
++ spin_lock(&rt_b->rt_runtime_lock);
++ rt_period = ktime_to_ns(rt_b->rt_period);
++ for_each_cpu_mask(i, rd->span) {
++ struct rt_rq *iter = sched_rt_period_rt_rq(rt_b, i);
++ s64 diff;
++
++ if (iter == rt_rq)
++ continue;
++
++ spin_lock(&iter->rt_runtime_lock);
++ diff = iter->rt_runtime - iter->rt_time;
++ if (diff > 0) {
++ do_div(diff, weight);
++ if (rt_rq->rt_runtime + diff > rt_period)
++ diff = rt_period - rt_rq->rt_runtime;
++ iter->rt_runtime -= diff;
++ rt_rq->rt_runtime += diff;
++ more = 1;
++ if (rt_rq->rt_runtime == rt_period) {
++ spin_unlock(&iter->rt_runtime_lock);
++ break;
++ }
++ }
++ spin_unlock(&iter->rt_runtime_lock);
++ }
++ spin_unlock(&rt_b->rt_runtime_lock);
++
++ return more;
++}
+ #endif
+
+ static inline int rt_se_prio(struct sched_rt_entity *rt_se)
+@@ -197,12 +323,24 @@ static int sched_rt_runtime_exceeded(struct rt_rq *rt_rq)
+ if (rt_rq->rt_throttled)
+ return rt_rq_throttled(rt_rq);
+
++ if (sched_rt_runtime(rt_rq) >= sched_rt_period(rt_rq))
++ return 0;
++
++#ifdef CONFIG_SMP
+ if (rt_rq->rt_time > runtime) {
+- struct rq *rq = rq_of_rt_rq(rt_rq);
++ int more;
+
+- rq->rt_throttled = 1;
+- rt_rq->rt_throttled = 1;
++ spin_unlock(&rt_rq->rt_runtime_lock);
++ more = balance_runtime(rt_rq);
++ spin_lock(&rt_rq->rt_runtime_lock);
+
++ if (more)
++ runtime = sched_rt_runtime(rt_rq);
++ }
++#endif
++
++ if (rt_rq->rt_time > runtime) {
++ rt_rq->rt_throttled = 1;
+ if (rt_rq_throttled(rt_rq)) {
+ sched_rt_rq_dequeue(rt_rq);
+ return 1;
+@@ -212,29 +350,6 @@ static int sched_rt_runtime_exceeded(struct rt_rq *rt_rq)
+ return 0;
+ }
+
+-static void update_sched_rt_period(struct rq *rq)
+-{
+- struct rt_rq *rt_rq;
+- u64 period;
+-
+- while (rq->clock > rq->rt_period_expire) {
+- period = (u64)sysctl_sched_rt_period * NSEC_PER_USEC;
+- rq->rt_period_expire += period;
+-
+- for_each_leaf_rt_rq(rt_rq, rq) {
+- u64 runtime = sched_rt_runtime(rt_rq);
+-
+- rt_rq->rt_time -= min(rt_rq->rt_time, runtime);
+- if (rt_rq->rt_throttled && rt_rq->rt_time < runtime) {
+- rt_rq->rt_throttled = 0;
+- sched_rt_rq_enqueue(rt_rq);
+- }
+- }
+-
+- rq->rt_throttled = 0;
+- }
+-}
+-
+ /*
+ * Update the current task's runtime statistics. Skip current tasks that
+ * are not in our scheduling class.
+@@ -259,9 +374,15 @@ static void update_curr_rt(struct rq *rq)
+ curr->se.exec_start = rq->clock;
+ cpuacct_charge(curr, delta_exec);
+
+- rt_rq->rt_time += delta_exec;
+- if (sched_rt_runtime_exceeded(rt_rq))
+- resched_task(curr);
++ for_each_sched_rt_entity(rt_se) {
++ rt_rq = rt_rq_of_se(rt_se);
++
++ spin_lock(&rt_rq->rt_runtime_lock);
++ rt_rq->rt_time += delta_exec;
++ if (sched_rt_runtime_exceeded(rt_rq))
++ resched_task(curr);
++ spin_unlock(&rt_rq->rt_runtime_lock);
++ }
+ }
+
+ static inline
+@@ -284,6 +405,11 @@ void inc_rt_tasks(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq)
+ #ifdef CONFIG_RT_GROUP_SCHED
+ if (rt_se_boosted(rt_se))
+ rt_rq->rt_nr_boosted++;
++
++ if (rt_rq->tg)
++ start_rt_bandwidth(&rt_rq->tg->rt_bandwidth);
++#else
++ start_rt_bandwidth(&def_rt_bandwidth);
+ #endif
+ }
+
+@@ -353,27 +479,21 @@ static void dequeue_rt_entity(struct sched_rt_entity *rt_se)
+ /*
+ * Because the prio of an upper entry depends on the lower
+ * entries, we must remove entries top - down.
+- *
+- * XXX: O(1/2 h^2) because we can only walk up, not down the chain.
+- * doesn't matter much for now, as h=2 for GROUP_SCHED.
+ */
+ static void dequeue_rt_stack(struct task_struct *p)
+ {
+- struct sched_rt_entity *rt_se, *top_se;
++ struct sched_rt_entity *rt_se, *back = NULL;
+
+- /*
+- * dequeue all, top - down.
+- */
+- do {
+- rt_se = &p->rt;
+- top_se = NULL;
+- for_each_sched_rt_entity(rt_se) {
+- if (on_rt_rq(rt_se))
+- top_se = rt_se;
+- }
+- if (top_se)
+- dequeue_rt_entity(top_se);
+- } while (top_se);
++ rt_se = &p->rt;
++ for_each_sched_rt_entity(rt_se) {
++ rt_se->back = back;
++ back = rt_se;
++ }
++
++ for (rt_se = back; rt_se; rt_se = rt_se->back) {
++ if (on_rt_rq(rt_se))
++ dequeue_rt_entity(rt_se);
++ }
+ }
+
+ /*
+@@ -393,6 +513,8 @@ static void enqueue_task_rt(struct rq *rq, struct task_struct *p, int wakeup)
+ */
+ for_each_sched_rt_entity(rt_se)
+ enqueue_rt_entity(rt_se);
++
++ inc_cpu_load(rq, p->se.load.weight);
+ }
+
+ static void dequeue_task_rt(struct rq *rq, struct task_struct *p, int sleep)
+@@ -412,6 +534,8 @@ static void dequeue_task_rt(struct rq *rq, struct task_struct *p, int sleep)
+ if (rt_rq && rt_rq->rt_nr_running)
+ enqueue_rt_entity(rt_se);
+ }
++
++ dec_cpu_load(rq, p->se.load.weight);
+ }
+
+ /*
+@@ -1001,7 +1125,8 @@ move_one_task_rt(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ return 0;
+ }
+
+-static void set_cpus_allowed_rt(struct task_struct *p, cpumask_t *new_mask)
++static void set_cpus_allowed_rt(struct task_struct *p,
++ const cpumask_t *new_mask)
+ {
+ int weight = cpus_weight(*new_mask);
+
+diff --git a/kernel/sched_stats.h b/kernel/sched_stats.h
+index 5b32433..5bae2e0 100644
+--- a/kernel/sched_stats.h
++++ b/kernel/sched_stats.h
+@@ -9,6 +9,11 @@
+ static int show_schedstat(struct seq_file *seq, void *v)
+ {
+ int cpu;
++ int mask_len = NR_CPUS/32 * 9;
++ char *mask_str = kmalloc(mask_len, GFP_KERNEL);
++
++ if (mask_str == NULL)
++ return -ENOMEM;
+
+ seq_printf(seq, "version %d\n", SCHEDSTAT_VERSION);
+ seq_printf(seq, "timestamp %lu\n", jiffies);
+@@ -36,9 +41,8 @@ static int show_schedstat(struct seq_file *seq, void *v)
+ preempt_disable();
+ for_each_domain(cpu, sd) {
+ enum cpu_idle_type itype;
+- char mask_str[NR_CPUS];
+
+- cpumask_scnprintf(mask_str, NR_CPUS, sd->span);
++ cpumask_scnprintf(mask_str, mask_len, sd->span);
+ seq_printf(seq, "domain%d %s", dcount++, mask_str);
+ for (itype = CPU_IDLE; itype < CPU_MAX_IDLE_TYPES;
+ itype++) {
+diff --git a/kernel/semaphore.c b/kernel/semaphore.c
+new file mode 100644
+index 0000000..5c2942e
+--- /dev/null
++++ b/kernel/semaphore.c
+@@ -0,0 +1,264 @@
++/*
++ * Copyright (c) 2008 Intel Corporation
++ * Author: Matthew Wilcox <willy at linux.intel.com>
++ *
++ * Distributed under the terms of the GNU GPL, version 2
++ *
++ * This file implements counting semaphores.
++ * A counting semaphore may be acquired 'n' times before sleeping.
++ * See mutex.c for single-acquisition sleeping locks which enforce
++ * rules which allow code to be debugged more easily.
++ */
++
++/*
++ * Some notes on the implementation:
++ *
++ * The spinlock controls access to the other members of the semaphore.
++ * down_trylock() and up() can be called from interrupt context, so we
++ * have to disable interrupts when taking the lock. It turns out various
++ * parts of the kernel expect to be able to use down() on a semaphore in
++ * interrupt context when they know it will succeed, so we have to use
++ * irqsave variants for down(), down_interruptible() and down_killable()
++ * too.
++ *
++ * The ->count variable represents how many more tasks can acquire this
++ * semaphore. If it's zero, there may be tasks waiting on the wait_list.
++ */
++
++#include <linux/compiler.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/semaphore.h>
++#include <linux/spinlock.h>
++
++static noinline void __down(struct semaphore *sem);
++static noinline int __down_interruptible(struct semaphore *sem);
++static noinline int __down_killable(struct semaphore *sem);
++static noinline int __down_timeout(struct semaphore *sem, long jiffies);
++static noinline void __up(struct semaphore *sem);
++
++/**
++ * down - acquire the semaphore
++ * @sem: the semaphore to be acquired
++ *
++ * Acquires the semaphore. If no more tasks are allowed to acquire the
++ * semaphore, calling this function will put the task to sleep until the
++ * semaphore is released.
++ *
++ * Use of this function is deprecated, please use down_interruptible() or
++ * down_killable() instead.
++ */
++void down(struct semaphore *sem)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&sem->lock, flags);
++ if (likely(sem->count > 0))
++ sem->count--;
++ else
++ __down(sem);
++ spin_unlock_irqrestore(&sem->lock, flags);
++}
++EXPORT_SYMBOL(down);
++
++/**
++ * down_interruptible - acquire the semaphore unless interrupted
++ * @sem: the semaphore to be acquired
++ *
++ * Attempts to acquire the semaphore. If no more tasks are allowed to
++ * acquire the semaphore, calling this function will put the task to sleep.
++ * If the sleep is interrupted by a signal, this function will return -EINTR.
++ * If the semaphore is successfully acquired, this function returns 0.
++ */
++int down_interruptible(struct semaphore *sem)
++{
++ unsigned long flags;
++ int result = 0;
++
++ spin_lock_irqsave(&sem->lock, flags);
++ if (likely(sem->count > 0))
++ sem->count--;
++ else
++ result = __down_interruptible(sem);
++ spin_unlock_irqrestore(&sem->lock, flags);
++
++ return result;
++}
++EXPORT_SYMBOL(down_interruptible);
++
++/**
++ * down_killable - acquire the semaphore unless killed
++ * @sem: the semaphore to be acquired
++ *
++ * Attempts to acquire the semaphore. If no more tasks are allowed to
++ * acquire the semaphore, calling this function will put the task to sleep.
++ * If the sleep is interrupted by a fatal signal, this function will return
++ * -EINTR. If the semaphore is successfully acquired, this function returns
++ * 0.
++ */
++int down_killable(struct semaphore *sem)
++{
++ unsigned long flags;
++ int result = 0;
++
++ spin_lock_irqsave(&sem->lock, flags);
++ if (likely(sem->count > 0))
++ sem->count--;
++ else
++ result = __down_killable(sem);
++ spin_unlock_irqrestore(&sem->lock, flags);
++
++ return result;
++}
++EXPORT_SYMBOL(down_killable);
++
++/**
++ * down_trylock - try to acquire the semaphore, without waiting
++ * @sem: the semaphore to be acquired
++ *
++ * Try to acquire the semaphore atomically. Returns 0 if the mutex has
++ * been acquired successfully or 1 if it it cannot be acquired.
++ *
++ * NOTE: This return value is inverted from both spin_trylock and
++ * mutex_trylock! Be careful about this when converting code.
++ *
++ * Unlike mutex_trylock, this function can be used from interrupt context,
++ * and the semaphore can be released by any task or interrupt.
++ */
++int down_trylock(struct semaphore *sem)
++{
++ unsigned long flags;
++ int count;
++
++ spin_lock_irqsave(&sem->lock, flags);
++ count = sem->count - 1;
++ if (likely(count >= 0))
++ sem->count = count;
++ spin_unlock_irqrestore(&sem->lock, flags);
++
++ return (count < 0);
++}
++EXPORT_SYMBOL(down_trylock);
++
++/**
++ * down_timeout - acquire the semaphore within a specified time
++ * @sem: the semaphore to be acquired
++ * @jiffies: how long to wait before failing
++ *
++ * Attempts to acquire the semaphore. If no more tasks are allowed to
++ * acquire the semaphore, calling this function will put the task to sleep.
++ * If the semaphore is not released within the specified number of jiffies,
++ * this function returns -ETIME. It returns 0 if the semaphore was acquired.
++ */
++int down_timeout(struct semaphore *sem, long jiffies)
++{
++ unsigned long flags;
++ int result = 0;
++
++ spin_lock_irqsave(&sem->lock, flags);
++ if (likely(sem->count > 0))
++ sem->count--;
++ else
++ result = __down_timeout(sem, jiffies);
++ spin_unlock_irqrestore(&sem->lock, flags);
++
++ return result;
++}
++EXPORT_SYMBOL(down_timeout);
++
++/**
++ * up - release the semaphore
++ * @sem: the semaphore to release
++ *
++ * Release the semaphore. Unlike mutexes, up() may be called from any
++ * context and even by tasks which have never called down().
++ */
++void up(struct semaphore *sem)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&sem->lock, flags);
++ if (likely(list_empty(&sem->wait_list)))
++ sem->count++;
++ else
++ __up(sem);
++ spin_unlock_irqrestore(&sem->lock, flags);
++}
++EXPORT_SYMBOL(up);
++
++/* Functions for the contended case */
++
++struct semaphore_waiter {
++ struct list_head list;
++ struct task_struct *task;
++ int up;
++};
++
++/*
++ * Because this function is inlined, the 'state' parameter will be
++ * constant, and thus optimised away by the compiler. Likewise the
++ * 'timeout' parameter for the cases without timeouts.
++ */
++static inline int __sched __down_common(struct semaphore *sem, long state,
++ long timeout)
++{
++ struct task_struct *task = current;
++ struct semaphore_waiter waiter;
++
++ list_add_tail(&waiter.list, &sem->wait_list);
++ waiter.task = task;
++ waiter.up = 0;
++
++ for (;;) {
++ if (state == TASK_INTERRUPTIBLE && signal_pending(task))
++ goto interrupted;
++ if (state == TASK_KILLABLE && fatal_signal_pending(task))
++ goto interrupted;
++ if (timeout <= 0)
++ goto timed_out;
++ __set_task_state(task, state);
++ spin_unlock_irq(&sem->lock);
++ timeout = schedule_timeout(timeout);
++ spin_lock_irq(&sem->lock);
++ if (waiter.up)
++ return 0;
++ }
++
++ timed_out:
++ list_del(&waiter.list);
++ return -ETIME;
++
++ interrupted:
++ list_del(&waiter.list);
++ return -EINTR;
++}
++
++static noinline void __sched __down(struct semaphore *sem)
++{
++ __down_common(sem, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
++}
++
++static noinline int __sched __down_interruptible(struct semaphore *sem)
++{
++ return __down_common(sem, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
++}
++
++static noinline int __sched __down_killable(struct semaphore *sem)
++{
++ return __down_common(sem, TASK_KILLABLE, MAX_SCHEDULE_TIMEOUT);
++}
++
++static noinline int __sched __down_timeout(struct semaphore *sem, long jiffies)
++{
++ return __down_common(sem, TASK_UNINTERRUPTIBLE, jiffies);
++}
++
++static noinline void __sched __up(struct semaphore *sem)
++{
++ struct semaphore_waiter *waiter = list_first_entry(&sem->wait_list,
++ struct semaphore_waiter, list);
++ list_del(&waiter->list);
++ waiter->up = 1;
++ wake_up_process(waiter->task);
++}
+diff --git a/kernel/signal.c b/kernel/signal.c
+index 6af1210..64ad0ed 100644
+--- a/kernel/signal.c
++++ b/kernel/signal.c
+@@ -220,7 +220,7 @@ void flush_signals(struct task_struct *t)
+ unsigned long flags;
+
+ spin_lock_irqsave(&t->sighand->siglock, flags);
+- clear_tsk_thread_flag(t,TIF_SIGPENDING);
++ clear_tsk_thread_flag(t, TIF_SIGPENDING);
+ flush_sigqueue(&t->pending);
+ flush_sigqueue(&t->signal->shared_pending);
+ spin_unlock_irqrestore(&t->sighand->siglock, flags);
+@@ -424,7 +424,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
+ }
+ if (signr &&
+ ((info->si_code & __SI_MASK) == __SI_TIMER) &&
+- info->si_sys_private){
++ info->si_sys_private) {
+ /*
+ * Release the siglock to ensure proper locking order
+ * of timer locks outside of siglocks. Note, we leave
+@@ -1757,6 +1757,45 @@ static int do_signal_stop(int signr)
+ return 1;
+ }
+
++static int ptrace_signal(int signr, siginfo_t *info,
++ struct pt_regs *regs, void *cookie)
++{
++ if (!(current->ptrace & PT_PTRACED))
++ return signr;
++
++ ptrace_signal_deliver(regs, cookie);
++
++ /* Let the debugger run. */
++ ptrace_stop(signr, 0, info);
++
++ /* We're back. Did the debugger cancel the sig? */
++ signr = current->exit_code;
++ if (signr == 0)
++ return signr;
++
++ current->exit_code = 0;
++
++ /* Update the siginfo structure if the signal has
++ changed. If the debugger wanted something
++ specific in the siginfo structure then it should
++ have updated *info via PTRACE_SETSIGINFO. */
++ if (signr != info->si_signo) {
++ info->si_signo = signr;
++ info->si_errno = 0;
++ info->si_code = SI_USER;
++ info->si_pid = task_pid_vnr(current->parent);
++ info->si_uid = current->parent->uid;
++ }
++
++ /* If the (new) signal is now blocked, requeue it. */
++ if (sigismember(¤t->blocked, signr)) {
++ specific_send_sig_info(signr, info, current);
++ signr = 0;
++ }
++
++ return signr;
++}
++
+ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
+ struct pt_regs *regs, void *cookie)
+ {
+@@ -1785,36 +1824,10 @@ relock:
+ if (!signr)
+ break; /* will return 0 */
+
+- if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
+- ptrace_signal_deliver(regs, cookie);
+-
+- /* Let the debugger run. */
+- ptrace_stop(signr, 0, info);
+-
+- /* We're back. Did the debugger cancel the sig? */
+- signr = current->exit_code;
+- if (signr == 0)
+- continue;
+-
+- current->exit_code = 0;
+-
+- /* Update the siginfo structure if the signal has
+- changed. If the debugger wanted something
+- specific in the siginfo structure then it should
+- have updated *info via PTRACE_SETSIGINFO. */
+- if (signr != info->si_signo) {
+- info->si_signo = signr;
+- info->si_errno = 0;
+- info->si_code = SI_USER;
+- info->si_pid = task_pid_vnr(current->parent);
+- info->si_uid = current->parent->uid;
+- }
+-
+- /* If the (new) signal is now blocked, requeue it. */
+- if (sigismember(¤t->blocked, signr)) {
+- specific_send_sig_info(signr, info, current);
++ if (signr != SIGKILL) {
++ signr = ptrace_signal(signr, info, regs, cookie);
++ if (!signr)
+ continue;
+- }
+ }
+
+ ka = ¤t->sighand->action[signr-1];
+diff --git a/kernel/softirq.c b/kernel/softirq.c
+index 31e9f2a..3c44956 100644
+--- a/kernel/softirq.c
++++ b/kernel/softirq.c
+@@ -356,7 +356,8 @@ void open_softirq(int nr, void (*action)(struct softirq_action*), void *data)
+ /* Tasklets */
+ struct tasklet_head
+ {
+- struct tasklet_struct *list;
++ struct tasklet_struct *head;
++ struct tasklet_struct **tail;
+ };
+
+ /* Some compilers disobey section attribute on statics when not
+@@ -369,8 +370,9 @@ void __tasklet_schedule(struct tasklet_struct *t)
+ unsigned long flags;
+
+ local_irq_save(flags);
+- t->next = __get_cpu_var(tasklet_vec).list;
+- __get_cpu_var(tasklet_vec).list = t;
++ t->next = NULL;
++ *__get_cpu_var(tasklet_vec).tail = t;
++ __get_cpu_var(tasklet_vec).tail = &(t->next);
+ raise_softirq_irqoff(TASKLET_SOFTIRQ);
+ local_irq_restore(flags);
+ }
+@@ -382,8 +384,9 @@ void __tasklet_hi_schedule(struct tasklet_struct *t)
+ unsigned long flags;
+
+ local_irq_save(flags);
+- t->next = __get_cpu_var(tasklet_hi_vec).list;
+- __get_cpu_var(tasklet_hi_vec).list = t;
++ t->next = NULL;
++ *__get_cpu_var(tasklet_hi_vec).tail = t;
++ __get_cpu_var(tasklet_hi_vec).tail = &(t->next);
+ raise_softirq_irqoff(HI_SOFTIRQ);
+ local_irq_restore(flags);
+ }
+@@ -395,8 +398,9 @@ static void tasklet_action(struct softirq_action *a)
+ struct tasklet_struct *list;
+
+ local_irq_disable();
+- list = __get_cpu_var(tasklet_vec).list;
+- __get_cpu_var(tasklet_vec).list = NULL;
++ list = __get_cpu_var(tasklet_vec).head;
++ __get_cpu_var(tasklet_vec).head = NULL;
++ __get_cpu_var(tasklet_vec).tail = &__get_cpu_var(tasklet_vec).head;
+ local_irq_enable();
+
+ while (list) {
+@@ -416,8 +420,9 @@ static void tasklet_action(struct softirq_action *a)
+ }
+
+ local_irq_disable();
+- t->next = __get_cpu_var(tasklet_vec).list;
+- __get_cpu_var(tasklet_vec).list = t;
++ t->next = NULL;
++ *__get_cpu_var(tasklet_vec).tail = t;
++ __get_cpu_var(tasklet_vec).tail = &(t->next);
+ __raise_softirq_irqoff(TASKLET_SOFTIRQ);
+ local_irq_enable();
+ }
+@@ -428,8 +433,9 @@ static void tasklet_hi_action(struct softirq_action *a)
+ struct tasklet_struct *list;
+
+ local_irq_disable();
+- list = __get_cpu_var(tasklet_hi_vec).list;
+- __get_cpu_var(tasklet_hi_vec).list = NULL;
++ list = __get_cpu_var(tasklet_hi_vec).head;
++ __get_cpu_var(tasklet_hi_vec).head = NULL;
++ __get_cpu_var(tasklet_hi_vec).tail = &__get_cpu_var(tasklet_hi_vec).head;
+ local_irq_enable();
+
+ while (list) {
+@@ -449,8 +455,9 @@ static void tasklet_hi_action(struct softirq_action *a)
+ }
+
+ local_irq_disable();
+- t->next = __get_cpu_var(tasklet_hi_vec).list;
+- __get_cpu_var(tasklet_hi_vec).list = t;
++ t->next = NULL;
++ *__get_cpu_var(tasklet_hi_vec).tail = t;
++ __get_cpu_var(tasklet_hi_vec).tail = &(t->next);
+ __raise_softirq_irqoff(HI_SOFTIRQ);
+ local_irq_enable();
+ }
+@@ -487,6 +494,15 @@ EXPORT_SYMBOL(tasklet_kill);
+
+ void __init softirq_init(void)
+ {
++ int cpu;
++
++ for_each_possible_cpu(cpu) {
++ per_cpu(tasklet_vec, cpu).tail =
++ &per_cpu(tasklet_vec, cpu).head;
++ per_cpu(tasklet_hi_vec, cpu).tail =
++ &per_cpu(tasklet_hi_vec, cpu).head;
++ }
++
+ open_softirq(TASKLET_SOFTIRQ, tasklet_action, NULL);
+ open_softirq(HI_SOFTIRQ, tasklet_hi_action, NULL);
+ }
+@@ -555,9 +571,12 @@ void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu)
+ return;
+
+ /* CPU is dead, so no lock needed. */
+- for (i = &per_cpu(tasklet_vec, cpu).list; *i; i = &(*i)->next) {
++ for (i = &per_cpu(tasklet_vec, cpu).head; *i; i = &(*i)->next) {
+ if (*i == t) {
+ *i = t->next;
++ /* If this was the tail element, move the tail ptr */
++ if (*i == NULL)
++ per_cpu(tasklet_vec, cpu).tail = i;
+ return;
+ }
+ }
+@@ -566,20 +585,20 @@ void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu)
+
+ static void takeover_tasklets(unsigned int cpu)
+ {
+- struct tasklet_struct **i;
+-
+ /* CPU is dead, so no lock needed. */
+ local_irq_disable();
+
+ /* Find end, append list for that CPU. */
+- for (i = &__get_cpu_var(tasklet_vec).list; *i; i = &(*i)->next);
+- *i = per_cpu(tasklet_vec, cpu).list;
+- per_cpu(tasklet_vec, cpu).list = NULL;
++ *__get_cpu_var(tasklet_vec).tail = per_cpu(tasklet_vec, cpu).head;
++ __get_cpu_var(tasklet_vec).tail = per_cpu(tasklet_vec, cpu).tail;
++ per_cpu(tasklet_vec, cpu).head = NULL;
++ per_cpu(tasklet_vec, cpu).tail = &per_cpu(tasklet_vec, cpu).head;
+ raise_softirq_irqoff(TASKLET_SOFTIRQ);
+
+- for (i = &__get_cpu_var(tasklet_hi_vec).list; *i; i = &(*i)->next);
+- *i = per_cpu(tasklet_hi_vec, cpu).list;
+- per_cpu(tasklet_hi_vec, cpu).list = NULL;
++ *__get_cpu_var(tasklet_hi_vec).tail = per_cpu(tasklet_hi_vec, cpu).head;
++ __get_cpu_var(tasklet_hi_vec).tail = per_cpu(tasklet_hi_vec, cpu).tail;
++ per_cpu(tasklet_hi_vec, cpu).head = NULL;
++ per_cpu(tasklet_hi_vec, cpu).tail = &per_cpu(tasklet_hi_vec, cpu).head;
+ raise_softirq_irqoff(HI_SOFTIRQ);
+
+ local_irq_enable();
+diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
+index 6f4e0e1..0101aee 100644
+--- a/kernel/stop_machine.c
++++ b/kernel/stop_machine.c
+@@ -11,7 +11,6 @@
+ #include <linux/interrupt.h>
+
+ #include <asm/atomic.h>
+-#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+
+ /* Since we effect priority and affinity (both of which are visible
+@@ -35,7 +34,7 @@ static int stopmachine(void *cpu)
+ int irqs_disabled = 0;
+ int prepared = 0;
+
+- set_cpus_allowed(current, cpumask_of_cpu((int)(long)cpu));
++ set_cpus_allowed_ptr(current, &cpumask_of_cpu((int)(long)cpu));
+
+ /* Ack: we are alive */
+ smp_mb(); /* Theoretically the ack = 0 might not be on this CPU yet. */
+@@ -135,8 +134,7 @@ static void restart_machine(void)
+ preempt_enable_no_resched();
+ }
+
+-struct stop_machine_data
+-{
++struct stop_machine_data {
+ int (*fn)(void *);
+ void *data;
+ struct completion done;
+diff --git a/kernel/sys.c b/kernel/sys.c
+index a626116..6a0cc71 100644
+--- a/kernel/sys.c
++++ b/kernel/sys.c
+@@ -67,6 +67,12 @@
+ #ifndef SET_ENDIAN
+ # define SET_ENDIAN(a,b) (-EINVAL)
+ #endif
++#ifndef GET_TSC_CTL
++# define GET_TSC_CTL(a) (-EINVAL)
++#endif
++#ifndef SET_TSC_CTL
++# define SET_TSC_CTL(a) (-EINVAL)
++#endif
+
+ /*
+ * this is where the system-wide overflow UID and GID are defined, for
+@@ -1737,7 +1743,12 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
+ #else
+ return -EINVAL;
+ #endif
+-
++ case PR_GET_TSC:
++ error = GET_TSC_CTL(arg2);
++ break;
++ case PR_SET_TSC:
++ error = SET_TSC_CTL(arg2);
++ break;
+ default:
+ error = -EINVAL;
+ break;
+diff --git a/kernel/sysctl.c b/kernel/sysctl.c
+index b2a2d68..fd33648 100644
+--- a/kernel/sysctl.c
++++ b/kernel/sysctl.c
+@@ -270,17 +270,6 @@ static struct ctl_table kern_table[] = {
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+- .procname = "sched_batch_wakeup_granularity_ns",
+- .data = &sysctl_sched_batch_wakeup_granularity,
+- .maxlen = sizeof(unsigned int),
+- .mode = 0644,
+- .proc_handler = &proc_dointvec_minmax,
+- .strategy = &sysctl_intvec,
+- .extra1 = &min_wakeup_granularity_ns,
+- .extra2 = &max_wakeup_granularity_ns,
+- },
+- {
+- .ctl_name = CTL_UNNUMBERED,
+ .procname = "sched_child_runs_first",
+ .data = &sysctl_sched_child_runs_first,
+ .maxlen = sizeof(unsigned int),
+@@ -318,7 +307,7 @@ static struct ctl_table kern_table[] = {
+ .data = &sysctl_sched_rt_period,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+- .proc_handler = &proc_dointvec,
++ .proc_handler = &sched_rt_handler,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+@@ -326,7 +315,7 @@ static struct ctl_table kern_table[] = {
+ .data = &sysctl_sched_rt_runtime,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+- .proc_handler = &proc_dointvec,
++ .proc_handler = &sched_rt_handler,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+diff --git a/kernel/time.c b/kernel/time.c
+index a5ec013..35d373a 100644
+--- a/kernel/time.c
++++ b/kernel/time.c
+@@ -379,6 +379,7 @@ void set_normalized_timespec(struct timespec *ts, time_t sec, long nsec)
+ ts->tv_sec = sec;
+ ts->tv_nsec = nsec;
+ }
++EXPORT_SYMBOL(set_normalized_timespec);
+
+ /**
+ * ns_to_timespec - Convert nanoseconds to timespec
+diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
+index 7f60097..73961f3 100644
+--- a/kernel/time/clocksource.c
++++ b/kernel/time/clocksource.c
+@@ -141,8 +141,16 @@ static void clocksource_watchdog(unsigned long data)
+ }
+
+ if (!list_empty(&watchdog_list)) {
+- __mod_timer(&watchdog_timer,
+- watchdog_timer.expires + WATCHDOG_INTERVAL);
++ /*
++ * Cycle through CPUs to check if the CPUs stay
++ * synchronized to each other.
++ */
++ int next_cpu = next_cpu(raw_smp_processor_id(), cpu_online_map);
++
++ if (next_cpu >= NR_CPUS)
++ next_cpu = first_cpu(cpu_online_map);
++ watchdog_timer.expires += WATCHDOG_INTERVAL;
++ add_timer_on(&watchdog_timer, next_cpu);
+ }
+ spin_unlock(&watchdog_lock);
+ }
+@@ -164,7 +172,8 @@ static void clocksource_check_watchdog(struct clocksource *cs)
+ if (!started && watchdog) {
+ watchdog_last = watchdog->read();
+ watchdog_timer.expires = jiffies + WATCHDOG_INTERVAL;
+- add_timer(&watchdog_timer);
++ add_timer_on(&watchdog_timer,
++ first_cpu(cpu_online_map));
+ }
+ } else {
+ if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS)
+@@ -185,7 +194,8 @@ static void clocksource_check_watchdog(struct clocksource *cs)
+ watchdog_last = watchdog->read();
+ watchdog_timer.expires =
+ jiffies + WATCHDOG_INTERVAL;
+- add_timer(&watchdog_timer);
++ add_timer_on(&watchdog_timer,
++ first_cpu(cpu_online_map));
+ }
+ }
+ }
+@@ -222,6 +232,18 @@ void clocksource_resume(void)
+ }
+
+ /**
++ * clocksource_touch_watchdog - Update watchdog
++ *
++ * Update the watchdog after exception contexts such as kgdb so as not
++ * to incorrectly trip the watchdog.
++ *
++ */
++void clocksource_touch_watchdog(void)
++{
++ clocksource_resume_watchdog();
++}
++
++/**
+ * clocksource_get_next - Returns the selected clocksource
+ *
+ */
+diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
+index e1bd50c..57a1f02 100644
+--- a/kernel/time/tick-broadcast.c
++++ b/kernel/time/tick-broadcast.c
+@@ -14,7 +14,7 @@
+ #include <linux/cpu.h>
+ #include <linux/err.h>
+ #include <linux/hrtimer.h>
+-#include <linux/irq.h>
++#include <linux/interrupt.h>
+ #include <linux/percpu.h>
+ #include <linux/profile.h>
+ #include <linux/sched.h>
+@@ -262,7 +262,7 @@ out:
+ void tick_broadcast_on_off(unsigned long reason, int *oncpu)
+ {
+ if (!cpu_isset(*oncpu, cpu_online_map))
+- printk(KERN_ERR "tick-braodcast: ignoring broadcast for "
++ printk(KERN_ERR "tick-broadcast: ignoring broadcast for "
+ "offline CPU #%d\n", *oncpu);
+ else
+ smp_call_function_single(*oncpu, tick_do_broadcast_on_off,
+diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
+index 1bea399..4f38865 100644
+--- a/kernel/time/tick-common.c
++++ b/kernel/time/tick-common.c
+@@ -14,12 +14,14 @@
+ #include <linux/cpu.h>
+ #include <linux/err.h>
+ #include <linux/hrtimer.h>
+-#include <linux/irq.h>
++#include <linux/interrupt.h>
+ #include <linux/percpu.h>
+ #include <linux/profile.h>
+ #include <linux/sched.h>
+ #include <linux/tick.h>
+
++#include <asm/irq_regs.h>
++
+ #include "tick-internal.h"
+
+ /*
+diff --git a/kernel/time/tick-oneshot.c b/kernel/time/tick-oneshot.c
+index 0258d31..450c049 100644
+--- a/kernel/time/tick-oneshot.c
++++ b/kernel/time/tick-oneshot.c
+@@ -14,7 +14,7 @@
+ #include <linux/cpu.h>
+ #include <linux/err.h>
+ #include <linux/hrtimer.h>
+-#include <linux/irq.h>
++#include <linux/interrupt.h>
+ #include <linux/percpu.h>
+ #include <linux/profile.h>
+ #include <linux/sched.h>
+diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
+index 686da82..b854a89 100644
+--- a/kernel/time/tick-sched.c
++++ b/kernel/time/tick-sched.c
+@@ -158,9 +158,8 @@ void tick_nohz_stop_idle(int cpu)
+ }
+ }
+
+-static ktime_t tick_nohz_start_idle(int cpu)
++static ktime_t tick_nohz_start_idle(struct tick_sched *ts)
+ {
+- struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
+ ktime_t now, delta;
+
+ now = ktime_get();
+@@ -192,7 +191,6 @@ u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time)
+ void tick_nohz_stop_sched_tick(void)
+ {
+ unsigned long seq, last_jiffies, next_jiffies, delta_jiffies, flags;
+- unsigned long rt_jiffies;
+ struct tick_sched *ts;
+ ktime_t last_update, expires, now;
+ struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
+@@ -201,8 +199,8 @@ void tick_nohz_stop_sched_tick(void)
+ local_irq_save(flags);
+
+ cpu = smp_processor_id();
+- now = tick_nohz_start_idle(cpu);
+ ts = &per_cpu(tick_cpu_sched, cpu);
++ now = tick_nohz_start_idle(ts);
+
+ /*
+ * If this cpu is offline and it is the one which updates
+@@ -222,7 +220,6 @@ void tick_nohz_stop_sched_tick(void)
+ if (need_resched())
+ goto end;
+
+- cpu = smp_processor_id();
+ if (unlikely(local_softirq_pending())) {
+ static int ratelimit;
+
+@@ -245,10 +242,6 @@ void tick_nohz_stop_sched_tick(void)
+ next_jiffies = get_next_timer_interrupt(last_jiffies);
+ delta_jiffies = next_jiffies - last_jiffies;
+
+- rt_jiffies = rt_needs_cpu(cpu);
+- if (rt_jiffies && rt_jiffies < delta_jiffies)
+- delta_jiffies = rt_jiffies;
+-
+ if (rcu_needs_cpu(cpu))
+ delta_jiffies = 1;
+ /*
+@@ -400,6 +393,7 @@ void tick_nohz_restart_sched_tick(void)
+ sub_preempt_count(HARDIRQ_OFFSET);
+ }
+
++ touch_softlockup_watchdog();
+ /*
+ * Cancel the scheduled timer and restore the tick
+ */
+diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
+index a3fa587..2d6087c 100644
+--- a/kernel/time/timekeeping.c
++++ b/kernel/time/timekeeping.c
+@@ -178,6 +178,7 @@ static void change_clocksource(void)
+ if (clock == new)
+ return;
+
++ new->cycle_last = 0;
+ now = clocksource_read(new);
+ nsec = __get_nsec_offset();
+ timespec_add_ns(&xtime, nsec);
+@@ -295,6 +296,7 @@ static int timekeeping_resume(struct sys_device *dev)
+ timespec_add_ns(&xtime, timekeeping_suspend_nsecs);
+ update_xtime_cache(0);
+ /* re-base the last cycle value */
++ clock->cycle_last = 0;
+ clock->cycle_last = clocksource_read(clock);
+ clock->error = 0;
+ timekeeping_suspended = 0;
+diff --git a/kernel/timer.c b/kernel/timer.c
+index b024106..f3d35d4 100644
+--- a/kernel/timer.c
++++ b/kernel/timer.c
+@@ -1228,13 +1228,6 @@ asmlinkage long sys_sysinfo(struct sysinfo __user *info)
+ return 0;
+ }
+
+-/*
+- * lockdep: we want to track each per-CPU base as a separate lock-class,
+- * but timer-bases are kmalloc()-ed, so we need to attach separate
+- * keys to them:
+- */
+-static struct lock_class_key base_lock_keys[NR_CPUS];
+-
+ static int __cpuinit init_timers_cpu(int cpu)
+ {
+ int j;
+@@ -1277,7 +1270,6 @@ static int __cpuinit init_timers_cpu(int cpu)
+ }
+
+ spin_lock_init(&base->lock);
+- lockdep_set_class(&base->lock, base_lock_keys + cpu);
+
+ for (j = 0; j < TVN_SIZE; j++) {
+ INIT_LIST_HEAD(base->tv5.vec + j);
+@@ -1316,8 +1308,8 @@ static void __cpuinit migrate_timers(int cpu)
+ new_base = get_cpu_var(tvec_bases);
+
+ local_irq_disable();
+- double_spin_lock(&new_base->lock, &old_base->lock,
+- smp_processor_id() < cpu);
++ spin_lock(&new_base->lock);
++ spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING);
+
+ BUG_ON(old_base->running_timer);
+
+@@ -1330,8 +1322,8 @@ static void __cpuinit migrate_timers(int cpu)
+ migrate_timer_list(new_base, old_base->tv5.vec + i);
+ }
+
+- double_spin_unlock(&new_base->lock, &old_base->lock,
+- smp_processor_id() < cpu);
++ spin_unlock(&old_base->lock);
++ spin_unlock(&new_base->lock);
+ local_irq_enable();
+ put_cpu_var(tvec_bases);
+ }
+diff --git a/kernel/user.c b/kernel/user.c
+index 7132022..debce60 100644
+--- a/kernel/user.c
++++ b/kernel/user.c
+@@ -101,7 +101,7 @@ static int sched_create_user(struct user_struct *up)
+ {
+ int rc = 0;
+
+- up->tg = sched_create_group();
++ up->tg = sched_create_group(&root_task_group);
+ if (IS_ERR(up->tg))
+ rc = -ENOMEM;
+
+@@ -193,6 +193,33 @@ static ssize_t cpu_rt_runtime_store(struct kobject *kobj,
+
+ static struct kobj_attribute cpu_rt_runtime_attr =
+ __ATTR(cpu_rt_runtime, 0644, cpu_rt_runtime_show, cpu_rt_runtime_store);
++
++static ssize_t cpu_rt_period_show(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ char *buf)
++{
++ struct user_struct *up = container_of(kobj, struct user_struct, kobj);
++
++ return sprintf(buf, "%lu\n", sched_group_rt_period(up->tg));
++}
++
++static ssize_t cpu_rt_period_store(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ const char *buf, size_t size)
++{
++ struct user_struct *up = container_of(kobj, struct user_struct, kobj);
++ unsigned long rt_period;
++ int rc;
++
++ sscanf(buf, "%lu", &rt_period);
++
++ rc = sched_group_set_rt_period(up->tg, rt_period);
++
++ return (rc ? rc : size);
++}
++
++static struct kobj_attribute cpu_rt_period_attr =
++ __ATTR(cpu_rt_period, 0644, cpu_rt_period_show, cpu_rt_period_store);
+ #endif
+
+ /* default attributes per uid directory */
+@@ -202,6 +229,7 @@ static struct attribute *uids_attributes[] = {
+ #endif
+ #ifdef CONFIG_RT_GROUP_SCHED
+ &cpu_rt_runtime_attr.attr,
++ &cpu_rt_period_attr.attr,
+ #endif
+ NULL
+ };
+diff --git a/kernel/workqueue.c b/kernel/workqueue.c
+index ff06611..00ff4d0 100644
+--- a/kernel/workqueue.c
++++ b/kernel/workqueue.c
+@@ -219,6 +219,7 @@ int queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
+ struct timer_list *timer = &dwork->timer;
+ struct work_struct *work = &dwork->work;
+
++ timer_stats_timer_set_start_info(&dwork->timer);
+ if (!test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work))) {
+ BUG_ON(timer_pending(timer));
+ BUG_ON(!list_empty(&work->entry));
+@@ -580,6 +581,7 @@ EXPORT_SYMBOL(schedule_delayed_work);
+ int schedule_delayed_work_on(int cpu,
+ struct delayed_work *dwork, unsigned long delay)
+ {
++ timer_stats_timer_set_start_info(&dwork->timer);
+ return queue_delayed_work_on(cpu, keventd_wq, dwork, delay);
+ }
+ EXPORT_SYMBOL(schedule_delayed_work_on);
+diff --git a/lib/Kconfig b/lib/Kconfig
+index ba3d104..2d53dc0 100644
+--- a/lib/Kconfig
++++ b/lib/Kconfig
+@@ -141,4 +141,7 @@ config HAS_DMA
+ config CHECK_SIGNATURE
+ bool
+
++config HAVE_LMB
++ boolean
++
+ endmenu
+diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
+index 0796c1a..754cc00 100644
+--- a/lib/Kconfig.debug
++++ b/lib/Kconfig.debug
+@@ -25,6 +25,17 @@ config ENABLE_MUST_CHECK
+ suppress the "warning: ignoring return value of 'foo', declared with
+ attribute warn_unused_result" messages.
+
++config FRAME_WARN
++ int "Warn for stack frames larger than (needs gcc 4.4)"
++ range 0 8192
++ default 1024 if !64BIT
++ default 2048 if 64BIT
++ help
++ Tell gcc to warn at build time for stack frames larger than this.
++ Setting this too low will cause a lot of warnings.
++ Setting it to 0 disables the warning.
++ Requires gcc 4.4
++
+ config MAGIC_SYSRQ
+ bool "Magic SysRq key"
+ depends on !UML
+@@ -211,7 +222,7 @@ config SLUB_DEBUG_ON
+ config SLUB_STATS
+ default n
+ bool "Enable SLUB performance statistics"
+- depends on SLUB
++ depends on SLUB && SLUB_DEBUG && SYSFS
+ help
+ SLUB statistics are useful to debug SLUBs allocation behavior in
+ order find ways to optimize the allocator. This should never be
+@@ -265,16 +276,6 @@ config DEBUG_MUTEXES
+ This feature allows mutex semantics violations to be detected and
+ reported.
+
+-config DEBUG_SEMAPHORE
+- bool "Semaphore debugging"
+- depends on DEBUG_KERNEL
+- depends on ALPHA || FRV
+- default n
+- help
+- If you say Y here then semaphore processing will issue lots of
+- verbose debugging messages. If you suspect a semaphore problem or a
+- kernel hacker asks for this option then say Y. Otherwise say N.
+-
+ config DEBUG_LOCK_ALLOC
+ bool "Lock debugging: detect incorrect freeing of live locks"
+ depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
+@@ -437,6 +438,16 @@ config DEBUG_VM
+
+ If unsure, say N.
+
++config DEBUG_WRITECOUNT
++ bool "Debug filesystem writers count"
++ depends on DEBUG_KERNEL
++ help
++ Enable this to catch wrong use of the writers count in struct
++ vfsmount. This will increase the size of each file struct by
++ 32 bits.
++
++ If unsure, say N.
++
+ config DEBUG_LIST
+ bool "Debug linked list manipulation"
+ depends on DEBUG_KERNEL
+@@ -593,7 +604,7 @@ config LATENCYTOP
+ to find out which userspace is blocking on what kernel operations.
+
+ config PROVIDE_OHCI1394_DMA_INIT
+- bool "Provide code for enabling DMA over FireWire early on boot"
++ bool "Remote debugging over FireWire early on boot"
+ depends on PCI && X86
+ help
+ If you want to debug problems which hang or crash the kernel early
+@@ -621,4 +632,17 @@ config PROVIDE_OHCI1394_DMA_INIT
+
+ See Documentation/debugging-via-ohci1394.txt for more information.
+
++config FIREWIRE_OHCI_REMOTE_DMA
++ bool "Remote debugging over FireWire with firewire-ohci"
++ depends on FIREWIRE_OHCI
++ help
++ This option lets you use the FireWire bus for remote debugging
++ with help of the firewire-ohci driver. It enables unfiltered
++ remote DMA in firewire-ohci.
++ See Documentation/debugging-via-ohci1394.txt for more information.
++
++ If unsure, say N.
++
+ source "samples/Kconfig"
++
++source "lib/Kconfig.kgdb"
+diff --git a/lib/Kconfig.kgdb b/lib/Kconfig.kgdb
+new file mode 100644
+index 0000000..f2e01ac
+--- /dev/null
++++ b/lib/Kconfig.kgdb
+@@ -0,0 +1,58 @@
++
++menuconfig KGDB
++ bool "KGDB: kernel debugging with remote gdb"
++ select FRAME_POINTER
++ depends on HAVE_ARCH_KGDB
++ depends on DEBUG_KERNEL && EXPERIMENTAL
++ help
++ If you say Y here, it will be possible to remotely debug the
++ kernel using gdb. Documentation of kernel debugger is available
++ at http://kgdb.sourceforge.net as well as in DocBook form
++ in Documentation/DocBook/. If unsure, say N.
++
++config HAVE_ARCH_KGDB_SHADOW_INFO
++ bool
++
++config HAVE_ARCH_KGDB
++ bool
++
++config KGDB_SERIAL_CONSOLE
++ tristate "KGDB: use kgdb over the serial console"
++ depends on KGDB
++ select CONSOLE_POLL
++ select MAGIC_SYSRQ
++ default y
++ help
++ Share a serial console with kgdb. Sysrq-g must be used
++ to break in initially.
++
++config KGDB_TESTS
++ bool "KGDB: internal test suite"
++ depends on KGDB
++ default n
++ help
++ This is a kgdb I/O module specifically designed to test
++ kgdb's internal functions. This kgdb I/O module is
++ intended to for the development of new kgdb stubs
++ as well as regression testing the kgdb internals.
++ See the drivers/misc/kgdbts.c for the details about
++ the tests. The most basic of this I/O module is to boot
++ a kernel boot arguments "kgdbwait kgdbts=V1F100"
++
++config KGDB_TESTS_ON_BOOT
++ bool "KGDB: Run tests on boot"
++ depends on KGDB_TESTS
++ default n
++ help
++ Run the kgdb tests on boot up automatically without the need
++ to pass in a kernel parameter
++
++config KGDB_TESTS_BOOT_STRING
++ string "KGDB: which internal kgdb tests to run"
++ depends on KGDB_TESTS_ON_BOOT
++ default "V1F100"
++ help
++ This is the command string to send the kgdb test suite on
++ boot. See the drivers/misc/kgdbts.c for detailed
++ information about other strings you could use beyond the
++ default of V1F100.
+diff --git a/lib/Makefile b/lib/Makefile
+index 23de261..bf8000f 100644
+--- a/lib/Makefile
++++ b/lib/Makefile
+@@ -29,7 +29,6 @@ obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
+ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
+ lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
+ lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
+-lib-$(CONFIG_SEMAPHORE_SLEEPERS) += semaphore-sleepers.o
+ lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
+ obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
+ obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
+@@ -61,7 +60,6 @@ obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o
+ obj-$(CONFIG_TEXTSEARCH_BM) += ts_bm.o
+ obj-$(CONFIG_TEXTSEARCH_FSM) += ts_fsm.o
+ obj-$(CONFIG_SMP) += percpu_counter.o
+-obj-$(CONFIG_SMP) += pcounter.o
+ obj-$(CONFIG_AUDIT_GENERIC) += audit.o
+
+ obj-$(CONFIG_SWIOTLB) += swiotlb.o
+@@ -70,6 +68,8 @@ obj-$(CONFIG_FAULT_INJECTION) += fault-inject.o
+
+ lib-$(CONFIG_GENERIC_BUG) += bug.o
+
++obj-$(CONFIG_HAVE_LMB) += lmb.o
++
+ hostprogs-y := gen_crc32table
+ clean-files := crc32table.h
+
+diff --git a/lib/bitmap.c b/lib/bitmap.c
+index 2c9242e..a6939e1 100644
+--- a/lib/bitmap.c
++++ b/lib/bitmap.c
+@@ -316,6 +316,22 @@ int bitmap_scnprintf(char *buf, unsigned int buflen,
+ EXPORT_SYMBOL(bitmap_scnprintf);
+
+ /**
++ * bitmap_scnprintf_len - return buffer length needed to convert
++ * bitmap to an ASCII hex string.
++ * @len: number of bits to be converted
++ */
++int bitmap_scnprintf_len(unsigned int len)
++{
++ /* we need 9 chars per word for 32 bit words (8 hexdigits + sep/null) */
++ int bitslen = ALIGN(len, CHUNKSZ);
++ int wordlen = CHUNKSZ / 4;
++ int buflen = (bitslen / wordlen) * (wordlen + 1) * sizeof(char);
++
++ return buflen;
++}
++EXPORT_SYMBOL(bitmap_scnprintf_len);
++
++/**
+ * __bitmap_parse - convert an ASCII hex string into a bitmap.
+ * @buf: pointer to buffer containing string.
+ * @buflen: buffer size in bytes. If string is smaller than this
+diff --git a/lib/kernel_lock.c b/lib/kernel_lock.c
+index 812dbf0..cd3e825 100644
+--- a/lib/kernel_lock.c
++++ b/lib/kernel_lock.c
+@@ -8,6 +8,7 @@
+ #include <linux/smp_lock.h>
+ #include <linux/module.h>
+ #include <linux/kallsyms.h>
++#include <linux/semaphore.h>
+
+ /*
+ * The 'big kernel semaphore'
+diff --git a/lib/kobject.c b/lib/kobject.c
+index 0d03252..2c64903 100644
+--- a/lib/kobject.c
++++ b/lib/kobject.c
+@@ -58,11 +58,6 @@ static int create_dir(struct kobject *kobj)
+ return error;
+ }
+
+-static inline struct kobject *to_kobj(struct list_head *entry)
+-{
+- return container_of(entry, struct kobject, entry);
+-}
+-
+ static int get_kobj_path_length(struct kobject *kobj)
+ {
+ int length = 1;
+@@ -592,8 +587,15 @@ static void kobject_release(struct kref *kref)
+ */
+ void kobject_put(struct kobject *kobj)
+ {
+- if (kobj)
++ if (kobj) {
++ if (!kobj->state_initialized) {
++ printk(KERN_WARNING "kobject: '%s' (%p): is not "
++ "initialized, yet kobject_put() is being "
++ "called.\n", kobject_name(kobj), kobj);
++ WARN_ON(1);
++ }
+ kref_put(&kobj->kref, kobject_release);
++ }
+ }
+
+ static void dynamic_kobj_release(struct kobject *kobj)
+@@ -745,12 +747,11 @@ void kset_unregister(struct kset *k)
+ */
+ struct kobject *kset_find_obj(struct kset *kset, const char *name)
+ {
+- struct list_head *entry;
++ struct kobject *k;
+ struct kobject *ret = NULL;
+
+ spin_lock(&kset->list_lock);
+- list_for_each(entry, &kset->list) {
+- struct kobject *k = to_kobj(entry);
++ list_for_each_entry(k, &kset->list, entry) {
+ if (kobject_name(k) && !strcmp(kobject_name(k), name)) {
+ ret = kobject_get(k);
+ break;
+diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
+index 5b6d7f6..9fb6b86 100644
+--- a/lib/kobject_uevent.c
++++ b/lib/kobject_uevent.c
+@@ -15,11 +15,13 @@
+ */
+
+ #include <linux/spinlock.h>
++#include <linux/string.h>
++#include <linux/kobject.h>
++#include <linux/module.h>
++
+ #include <linux/socket.h>
+ #include <linux/skbuff.h>
+ #include <linux/netlink.h>
+-#include <linux/string.h>
+-#include <linux/kobject.h>
+ #include <net/sock.h>
+
+
+diff --git a/lib/lmb.c b/lib/lmb.c
+new file mode 100644
+index 0000000..207147a
+--- /dev/null
++++ b/lib/lmb.c
+@@ -0,0 +1,428 @@
++/*
++ * Procedures for maintaining information about logical memory blocks.
++ *
++ * Peter Bergner, IBM Corp. June 2001.
++ * Copyright (C) 2001 Peter Bergner.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/bitops.h>
++#include <linux/lmb.h>
++
++#define LMB_ALLOC_ANYWHERE 0
++
++struct lmb lmb;
++
++void lmb_dump_all(void)
++{
++#ifdef DEBUG
++ unsigned long i;
++
++ pr_debug("lmb_dump_all:\n");
++ pr_debug(" memory.cnt = 0x%lx\n", lmb.memory.cnt);
++ pr_debug(" memory.size = 0x%llx\n",
++ (unsigned long long)lmb.memory.size);
++ for (i=0; i < lmb.memory.cnt ;i++) {
++ pr_debug(" memory.region[0x%x].base = 0x%llx\n",
++ i, (unsigned long long)lmb.memory.region[i].base);
++ pr_debug(" .size = 0x%llx\n",
++ (unsigned long long)lmb.memory.region[i].size);
++ }
++
++ pr_debug(" reserved.cnt = 0x%lx\n", lmb.reserved.cnt);
++ pr_debug(" reserved.size = 0x%lx\n", lmb.reserved.size);
++ for (i=0; i < lmb.reserved.cnt ;i++) {
++ pr_debug(" reserved.region[0x%x].base = 0x%llx\n",
++ i, (unsigned long long)lmb.reserved.region[i].base);
++ pr_debug(" .size = 0x%llx\n",
++ (unsigned long long)lmb.reserved.region[i].size);
++ }
++#endif /* DEBUG */
++}
++
++static unsigned long __init lmb_addrs_overlap(u64 base1, u64 size1,
++ u64 base2, u64 size2)
++{
++ return ((base1 < (base2 + size2)) && (base2 < (base1 + size1)));
++}
++
++static long __init lmb_addrs_adjacent(u64 base1, u64 size1,
++ u64 base2, u64 size2)
++{
++ if (base2 == base1 + size1)
++ return 1;
++ else if (base1 == base2 + size2)
++ return -1;
++
++ return 0;
++}
++
++static long __init lmb_regions_adjacent(struct lmb_region *rgn,
++ unsigned long r1, unsigned long r2)
++{
++ u64 base1 = rgn->region[r1].base;
++ u64 size1 = rgn->region[r1].size;
++ u64 base2 = rgn->region[r2].base;
++ u64 size2 = rgn->region[r2].size;
++
++ return lmb_addrs_adjacent(base1, size1, base2, size2);
++}
++
++static void __init lmb_remove_region(struct lmb_region *rgn, unsigned long r)
++{
++ unsigned long i;
++
++ for (i = r; i < rgn->cnt - 1; i++) {
++ rgn->region[i].base = rgn->region[i + 1].base;
++ rgn->region[i].size = rgn->region[i + 1].size;
++ }
++ rgn->cnt--;
++}
++
++/* Assumption: base addr of region 1 < base addr of region 2 */
++static void __init lmb_coalesce_regions(struct lmb_region *rgn,
++ unsigned long r1, unsigned long r2)
++{
++ rgn->region[r1].size += rgn->region[r2].size;
++ lmb_remove_region(rgn, r2);
++}
++
++void __init lmb_init(void)
++{
++ /* Create a dummy zero size LMB which will get coalesced away later.
++ * This simplifies the lmb_add() code below...
++ */
++ lmb.memory.region[0].base = 0;
++ lmb.memory.region[0].size = 0;
++ lmb.memory.cnt = 1;
++
++ /* Ditto. */
++ lmb.reserved.region[0].base = 0;
++ lmb.reserved.region[0].size = 0;
++ lmb.reserved.cnt = 1;
++}
++
++void __init lmb_analyze(void)
++{
++ int i;
++
++ lmb.memory.size = 0;
++
++ for (i = 0; i < lmb.memory.cnt; i++)
++ lmb.memory.size += lmb.memory.region[i].size;
++}
++
++static long __init lmb_add_region(struct lmb_region *rgn, u64 base, u64 size)
++{
++ unsigned long coalesced = 0;
++ long adjacent, i;
++
++ if ((rgn->cnt == 1) && (rgn->region[0].size == 0)) {
++ rgn->region[0].base = base;
++ rgn->region[0].size = size;
++ return 0;
++ }
++
++ /* First try and coalesce this LMB with another. */
++ for (i = 0; i < rgn->cnt; i++) {
++ u64 rgnbase = rgn->region[i].base;
++ u64 rgnsize = rgn->region[i].size;
++
++ if ((rgnbase == base) && (rgnsize == size))
++ /* Already have this region, so we're done */
++ return 0;
++
++ adjacent = lmb_addrs_adjacent(base, size, rgnbase, rgnsize);
++ if (adjacent > 0) {
++ rgn->region[i].base -= size;
++ rgn->region[i].size += size;
++ coalesced++;
++ break;
++ } else if (adjacent < 0) {
++ rgn->region[i].size += size;
++ coalesced++;
++ break;
++ }
++ }
++
++ if ((i < rgn->cnt - 1) && lmb_regions_adjacent(rgn, i, i+1)) {
++ lmb_coalesce_regions(rgn, i, i+1);
++ coalesced++;
++ }
++
++ if (coalesced)
++ return coalesced;
++ if (rgn->cnt >= MAX_LMB_REGIONS)
++ return -1;
++
++ /* Couldn't coalesce the LMB, so add it to the sorted table. */
++ for (i = rgn->cnt - 1; i >= 0; i--) {
++ if (base < rgn->region[i].base) {
++ rgn->region[i+1].base = rgn->region[i].base;
++ rgn->region[i+1].size = rgn->region[i].size;
++ } else {
++ rgn->region[i+1].base = base;
++ rgn->region[i+1].size = size;
++ break;
++ }
++ }
++
++ if (base < rgn->region[0].base) {
++ rgn->region[0].base = base;
++ rgn->region[0].size = size;
++ }
++ rgn->cnt++;
++
++ return 0;
++}
++
++long __init lmb_add(u64 base, u64 size)
++{
++ struct lmb_region *_rgn = &lmb.memory;
++
++ /* On pSeries LPAR systems, the first LMB is our RMO region. */
++ if (base == 0)
++ lmb.rmo_size = size;
++
++ return lmb_add_region(_rgn, base, size);
++
++}
++
++long __init lmb_reserve(u64 base, u64 size)
++{
++ struct lmb_region *_rgn = &lmb.reserved;
++
++ BUG_ON(0 == size);
++
++ return lmb_add_region(_rgn, base, size);
++}
++
++long __init lmb_overlaps_region(struct lmb_region *rgn, u64 base, u64 size)
++{
++ unsigned long i;
++
++ for (i = 0; i < rgn->cnt; i++) {
++ u64 rgnbase = rgn->region[i].base;
++ u64 rgnsize = rgn->region[i].size;
++ if (lmb_addrs_overlap(base, size, rgnbase, rgnsize))
++ break;
++ }
++
++ return (i < rgn->cnt) ? i : -1;
++}
++
++static u64 lmb_align_down(u64 addr, u64 size)
++{
++ return addr & ~(size - 1);
++}
++
++static u64 lmb_align_up(u64 addr, u64 size)
++{
++ return (addr + (size - 1)) & ~(size - 1);
++}
++
++static u64 __init lmb_alloc_nid_unreserved(u64 start, u64 end,
++ u64 size, u64 align)
++{
++ u64 base, res_base;
++ long j;
++
++ base = lmb_align_down((end - size), align);
++ while (start <= base) {
++ j = lmb_overlaps_region(&lmb.reserved, base, size);
++ if (j < 0) {
++ /* this area isn't reserved, take it */
++ if (lmb_add_region(&lmb.reserved, base,
++ lmb_align_up(size, align)) < 0)
++ base = ~(u64)0;
++ return base;
++ }
++ res_base = lmb.reserved.region[j].base;
++ if (res_base < size)
++ break;
++ base = lmb_align_down(res_base - size, align);
++ }
++
++ return ~(u64)0;
++}
++
++static u64 __init lmb_alloc_nid_region(struct lmb_property *mp,
++ u64 (*nid_range)(u64, u64, int *),
++ u64 size, u64 align, int nid)
++{
++ u64 start, end;
++
++ start = mp->base;
++ end = start + mp->size;
++
++ start = lmb_align_up(start, align);
++ while (start < end) {
++ u64 this_end;
++ int this_nid;
++
++ this_end = nid_range(start, end, &this_nid);
++ if (this_nid == nid) {
++ u64 ret = lmb_alloc_nid_unreserved(start, this_end,
++ size, align);
++ if (ret != ~(u64)0)
++ return ret;
++ }
++ start = this_end;
++ }
++
++ return ~(u64)0;
++}
++
++u64 __init lmb_alloc_nid(u64 size, u64 align, int nid,
++ u64 (*nid_range)(u64 start, u64 end, int *nid))
++{
++ struct lmb_region *mem = &lmb.memory;
++ int i;
++
++ for (i = 0; i < mem->cnt; i++) {
++ u64 ret = lmb_alloc_nid_region(&mem->region[i],
++ nid_range,
++ size, align, nid);
++ if (ret != ~(u64)0)
++ return ret;
++ }
++
++ return lmb_alloc(size, align);
++}
++
++u64 __init lmb_alloc(u64 size, u64 align)
++{
++ return lmb_alloc_base(size, align, LMB_ALLOC_ANYWHERE);
++}
++
++u64 __init lmb_alloc_base(u64 size, u64 align, u64 max_addr)
++{
++ u64 alloc;
++
++ alloc = __lmb_alloc_base(size, align, max_addr);
++
++ if (alloc == 0)
++ panic("ERROR: Failed to allocate 0x%llx bytes below 0x%llx.\n",
++ (unsigned long long) size, (unsigned long long) max_addr);
++
++ return alloc;
++}
++
++u64 __init __lmb_alloc_base(u64 size, u64 align, u64 max_addr)
++{
++ long i, j;
++ u64 base = 0;
++ u64 res_base;
++
++ BUG_ON(0 == size);
++
++ /* On some platforms, make sure we allocate lowmem */
++ /* Note that LMB_REAL_LIMIT may be LMB_ALLOC_ANYWHERE */
++ if (max_addr == LMB_ALLOC_ANYWHERE)
++ max_addr = LMB_REAL_LIMIT;
++
++ for (i = lmb.memory.cnt - 1; i >= 0; i--) {
++ u64 lmbbase = lmb.memory.region[i].base;
++ u64 lmbsize = lmb.memory.region[i].size;
++
++ if (lmbsize < size)
++ continue;
++ if (max_addr == LMB_ALLOC_ANYWHERE)
++ base = lmb_align_down(lmbbase + lmbsize - size, align);
++ else if (lmbbase < max_addr) {
++ base = min(lmbbase + lmbsize, max_addr);
++ base = lmb_align_down(base - size, align);
++ } else
++ continue;
++
++ while (base && lmbbase <= base) {
++ j = lmb_overlaps_region(&lmb.reserved, base, size);
++ if (j < 0) {
++ /* this area isn't reserved, take it */
++ if (lmb_add_region(&lmb.reserved, base,
++ lmb_align_up(size, align)) < 0)
++ return 0;
++ return base;
++ }
++ res_base = lmb.reserved.region[j].base;
++ if (res_base < size)
++ break;
++ base = lmb_align_down(res_base - size, align);
++ }
++ }
++ return 0;
++}
++
++/* You must call lmb_analyze() before this. */
++u64 __init lmb_phys_mem_size(void)
++{
++ return lmb.memory.size;
++}
++
++u64 __init lmb_end_of_DRAM(void)
++{
++ int idx = lmb.memory.cnt - 1;
++
++ return (lmb.memory.region[idx].base + lmb.memory.region[idx].size);
++}
++
++/* You must call lmb_analyze() after this. */
++void __init lmb_enforce_memory_limit(u64 memory_limit)
++{
++ unsigned long i;
++ u64 limit;
++ struct lmb_property *p;
++
++ if (!memory_limit)
++ return;
++
++ /* Truncate the lmb regions to satisfy the memory limit. */
++ limit = memory_limit;
++ for (i = 0; i < lmb.memory.cnt; i++) {
++ if (limit > lmb.memory.region[i].size) {
++ limit -= lmb.memory.region[i].size;
++ continue;
++ }
++
++ lmb.memory.region[i].size = limit;
++ lmb.memory.cnt = i + 1;
++ break;
++ }
++
++ if (lmb.memory.region[0].size < lmb.rmo_size)
++ lmb.rmo_size = lmb.memory.region[0].size;
++
++ /* And truncate any reserves above the limit also. */
++ for (i = 0; i < lmb.reserved.cnt; i++) {
++ p = &lmb.reserved.region[i];
++
++ if (p->base > memory_limit)
++ p->size = 0;
++ else if ((p->base + p->size) > memory_limit)
++ p->size = memory_limit - p->base;
++
++ if (p->size == 0) {
++ lmb_remove_region(&lmb.reserved, i);
++ i--;
++ }
++ }
++}
++
++int __init lmb_is_reserved(u64 addr)
++{
++ int i;
++
++ for (i = 0; i < lmb.reserved.cnt; i++) {
++ u64 upper = lmb.reserved.region[i].base +
++ lmb.reserved.region[i].size - 1;
++ if ((addr >= lmb.reserved.region[i].base) && (addr <= upper))
++ return 1;
++ }
++ return 0;
++}
+diff --git a/lib/pcounter.c b/lib/pcounter.c
+deleted file mode 100644
+index 9b56807..0000000
+--- a/lib/pcounter.c
++++ /dev/null
+@@ -1,58 +0,0 @@
+-/*
+- * Define default pcounter functions
+- * Note that often used pcounters use dedicated functions to get a speed increase.
+- * (see DEFINE_PCOUNTER/REF_PCOUNTER_MEMBER)
+- */
+-
+-#include <linux/module.h>
+-#include <linux/pcounter.h>
+-#include <linux/smp.h>
+-#include <linux/cpumask.h>
+-
+-static void pcounter_dyn_add(struct pcounter *self, int inc)
+-{
+- per_cpu_ptr(self->per_cpu_values, smp_processor_id())[0] += inc;
+-}
+-
+-static int pcounter_dyn_getval(const struct pcounter *self, int cpu)
+-{
+- return per_cpu_ptr(self->per_cpu_values, cpu)[0];
+-}
+-
+-int pcounter_getval(const struct pcounter *self)
+-{
+- int res = 0, cpu;
+-
+- for_each_possible_cpu(cpu)
+- res += self->getval(self, cpu);
+-
+- return res;
+-}
+-EXPORT_SYMBOL_GPL(pcounter_getval);
+-
+-int pcounter_alloc(struct pcounter *self)
+-{
+- int rc = 0;
+- if (self->add == NULL) {
+- self->per_cpu_values = alloc_percpu(int);
+- if (self->per_cpu_values != NULL) {
+- self->add = pcounter_dyn_add;
+- self->getval = pcounter_dyn_getval;
+- } else
+- rc = 1;
+- }
+- return rc;
+-}
+-EXPORT_SYMBOL_GPL(pcounter_alloc);
+-
+-void pcounter_free(struct pcounter *self)
+-{
+- if (self->per_cpu_values != NULL) {
+- free_percpu(self->per_cpu_values);
+- self->per_cpu_values = NULL;
+- self->getval = NULL;
+- self->add = NULL;
+- }
+-}
+-EXPORT_SYMBOL_GPL(pcounter_free);
+-
+diff --git a/lib/reed_solomon/reed_solomon.c b/lib/reed_solomon/reed_solomon.c
+index 3ea2db9..06d04cf 100644
+--- a/lib/reed_solomon/reed_solomon.c
++++ b/lib/reed_solomon/reed_solomon.c
+@@ -45,7 +45,6 @@
+ #include <linux/rslib.h>
+ #include <linux/slab.h>
+ #include <linux/mutex.h>
+-#include <asm/semaphore.h>
+
+ /* This list holds all currently allocated rs control structures */
+ static LIST_HEAD (rslist);
+diff --git a/lib/scatterlist.c b/lib/scatterlist.c
+index acca490..b80c211 100644
+--- a/lib/scatterlist.c
++++ b/lib/scatterlist.c
+@@ -8,6 +8,7 @@
+ */
+ #include <linux/module.h>
+ #include <linux/scatterlist.h>
++#include <linux/highmem.h>
+
+ /**
+ * sg_next - return the next scatterlist entry in a list
+@@ -292,3 +293,104 @@ int sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask)
+ return ret;
+ }
+ EXPORT_SYMBOL(sg_alloc_table);
++
++/**
++ * sg_copy_buffer - Copy data between a linear buffer and an SG list
++ * @sgl: The SG list
++ * @nents: Number of SG entries
++ * @buf: Where to copy from
++ * @buflen: The number of bytes to copy
++ * @to_buffer: transfer direction (non zero == from an sg list to a
++ * buffer, 0 == from a buffer to an sg list
++ *
++ * Returns the number of copied bytes.
++ *
++ **/
++static size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents,
++ void *buf, size_t buflen, int to_buffer)
++{
++ struct scatterlist *sg;
++ size_t buf_off = 0;
++ int i;
++
++ WARN_ON(!irqs_disabled());
++
++ for_each_sg(sgl, sg, nents, i) {
++ struct page *page;
++ int n = 0;
++ unsigned int sg_off = sg->offset;
++ unsigned int sg_copy = sg->length;
++
++ if (sg_copy > buflen)
++ sg_copy = buflen;
++ buflen -= sg_copy;
++
++ while (sg_copy > 0) {
++ unsigned int page_copy;
++ void *p;
++
++ page_copy = PAGE_SIZE - sg_off;
++ if (page_copy > sg_copy)
++ page_copy = sg_copy;
++
++ page = nth_page(sg_page(sg), n);
++ p = kmap_atomic(page, KM_BIO_SRC_IRQ);
++
++ if (to_buffer)
++ memcpy(buf + buf_off, p + sg_off, page_copy);
++ else {
++ memcpy(p + sg_off, buf + buf_off, page_copy);
++ flush_kernel_dcache_page(page);
++ }
++
++ kunmap_atomic(p, KM_BIO_SRC_IRQ);
++
++ buf_off += page_copy;
++ sg_off += page_copy;
++ if (sg_off == PAGE_SIZE) {
++ sg_off = 0;
++ n++;
++ }
++ sg_copy -= page_copy;
++ }
++
++ if (!buflen)
++ break;
++ }
++
++ return buf_off;
++}
++
++/**
++ * sg_copy_from_buffer - Copy from a linear buffer to an SG list
++ * @sgl: The SG list
++ * @nents: Number of SG entries
++ * @buf: Where to copy from
++ * @buflen: The number of bytes to copy
++ *
++ * Returns the number of copied bytes.
++ *
++ **/
++size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents,
++ void *buf, size_t buflen)
++{
++ return sg_copy_buffer(sgl, nents, buf, buflen, 0);
++}
++EXPORT_SYMBOL(sg_copy_from_buffer);
++
++/**
++ * sg_copy_to_buffer - Copy from an SG list to a linear buffer
++ * @sgl: The SG list
++ * @nents: Number of SG entries
++ * @buf: Where to copy to
++ * @buflen: The number of bytes to copy
++ *
++ * Returns the number of copied bytes.
++ *
++ **/
++size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
++ void *buf, size_t buflen)
++{
++ return sg_copy_buffer(sgl, nents, buf, buflen, 1);
++}
++EXPORT_SYMBOL(sg_copy_to_buffer);
+diff --git a/lib/semaphore-sleepers.c b/lib/semaphore-sleepers.c
+deleted file mode 100644
+index 0198782..0000000
+--- a/lib/semaphore-sleepers.c
++++ /dev/null
+@@ -1,176 +0,0 @@
+-/*
+- * i386 and x86-64 semaphore implementation.
+- *
+- * (C) Copyright 1999 Linus Torvalds
+- *
+- * Portions Copyright 1999 Red Hat, Inc.
+- *
+- * 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.
+- *
+- * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl at kvack.org>
+- */
+-#include <linux/sched.h>
+-#include <linux/err.h>
+-#include <linux/init.h>
+-#include <asm/semaphore.h>
+-
+-/*
+- * Semaphores are implemented using a two-way counter:
+- * The "count" variable is decremented for each process
+- * that tries to acquire the semaphore, while the "sleeping"
+- * variable is a count of such acquires.
+- *
+- * Notably, the inline "up()" and "down()" functions can
+- * efficiently test if they need to do any extra work (up
+- * needs to do something only if count was negative before
+- * the increment operation.
+- *
+- * "sleeping" and the contention routine ordering is protected
+- * by the spinlock in the semaphore's waitqueue head.
+- *
+- * Note that these functions are only called when there is
+- * contention on the lock, and as such all this is the
+- * "non-critical" part of the whole semaphore business. The
+- * critical part is the inline stuff in <asm/semaphore.h>
+- * where we want to avoid any extra jumps and calls.
+- */
+-
+-/*
+- * Logic:
+- * - only on a boundary condition do we need to care. When we go
+- * from a negative count to a non-negative, we wake people up.
+- * - when we go from a non-negative count to a negative do we
+- * (a) synchronize with the "sleeper" count and (b) make sure
+- * that we're on the wakeup list before we synchronize so that
+- * we cannot lose wakeup events.
+- */
+-
+-void __up(struct semaphore *sem)
+-{
+- wake_up(&sem->wait);
+-}
+-
+-void __sched __down(struct semaphore *sem)
+-{
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+- unsigned long flags;
+-
+- tsk->state = TASK_UNINTERRUPTIBLE;
+- spin_lock_irqsave(&sem->wait.lock, flags);
+- add_wait_queue_exclusive_locked(&sem->wait, &wait);
+-
+- sem->sleepers++;
+- for (;;) {
+- int sleepers = sem->sleepers;
+-
+- /*
+- * Add "everybody else" into it. They aren't
+- * playing, because we own the spinlock in
+- * the wait_queue_head.
+- */
+- if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+- sem->sleepers = 0;
+- break;
+- }
+- sem->sleepers = 1; /* us - see -1 above */
+- spin_unlock_irqrestore(&sem->wait.lock, flags);
+-
+- schedule();
+-
+- spin_lock_irqsave(&sem->wait.lock, flags);
+- tsk->state = TASK_UNINTERRUPTIBLE;
+- }
+- remove_wait_queue_locked(&sem->wait, &wait);
+- wake_up_locked(&sem->wait);
+- spin_unlock_irqrestore(&sem->wait.lock, flags);
+- tsk->state = TASK_RUNNING;
+-}
+-
+-int __sched __down_interruptible(struct semaphore *sem)
+-{
+- int retval = 0;
+- struct task_struct *tsk = current;
+- DECLARE_WAITQUEUE(wait, tsk);
+- unsigned long flags;
+-
+- tsk->state = TASK_INTERRUPTIBLE;
+- spin_lock_irqsave(&sem->wait.lock, flags);
+- add_wait_queue_exclusive_locked(&sem->wait, &wait);
+-
+- sem->sleepers++;
+- for (;;) {
+- int sleepers = sem->sleepers;
+-
+- /*
+- * With signals pending, this turns into
+- * the trylock failure case - we won't be
+- * sleeping, and we* can't get the lock as
+- * it has contention. Just correct the count
+- * and exit.
+- */
+- if (signal_pending(current)) {
+- retval = -EINTR;
+- sem->sleepers = 0;
+- atomic_add(sleepers, &sem->count);
+- break;
+- }
+-
+- /*
+- * Add "everybody else" into it. They aren't
+- * playing, because we own the spinlock in
+- * wait_queue_head. The "-1" is because we're
+- * still hoping to get the semaphore.
+- */
+- if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+- sem->sleepers = 0;
+- break;
+- }
+- sem->sleepers = 1; /* us - see -1 above */
+- spin_unlock_irqrestore(&sem->wait.lock, flags);
+-
+- schedule();
+-
+- spin_lock_irqsave(&sem->wait.lock, flags);
+- tsk->state = TASK_INTERRUPTIBLE;
+- }
+- remove_wait_queue_locked(&sem->wait, &wait);
+- wake_up_locked(&sem->wait);
+- spin_unlock_irqrestore(&sem->wait.lock, flags);
+-
+- tsk->state = TASK_RUNNING;
+- return retval;
+-}
+-
+-/*
+- * Trylock failed - make sure we correct for
+- * having decremented the count.
+- *
+- * We could have done the trylock with a
+- * single "cmpxchg" without failure cases,
+- * but then it wouldn't work on a 386.
+- */
+-int __down_trylock(struct semaphore *sem)
+-{
+- int sleepers;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&sem->wait.lock, flags);
+- sleepers = sem->sleepers + 1;
+- sem->sleepers = 0;
+-
+- /*
+- * Add "everybody else" and us into it. They aren't
+- * playing, because we own the spinlock in the
+- * wait_queue_head.
+- */
+- if (!atomic_add_negative(sleepers, &sem->count)) {
+- wake_up_locked(&sem->wait);
+- }
+-
+- spin_unlock_irqrestore(&sem->wait.lock, flags);
+- return 1;
+-}
+diff --git a/mm/Makefile b/mm/Makefile
+index a5b0dd9..18c143b 100644
+--- a/mm/Makefile
++++ b/mm/Makefile
+@@ -8,7 +8,7 @@ mmu-$(CONFIG_MMU) := fremap.o highmem.o madvise.o memory.o mincore.o \
+ vmalloc.o
+
+ obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \
+- page_alloc.o page-writeback.o pdflush.o \
++ maccess.o page_alloc.o page-writeback.o pdflush.o \
+ readahead.o swap.o truncate.o vmscan.o \
+ prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \
+ page_isolation.o $(mmu-y)
+diff --git a/mm/allocpercpu.c b/mm/allocpercpu.c
+index b0012e2..f4026ba 100644
+--- a/mm/allocpercpu.c
++++ b/mm/allocpercpu.c
+@@ -82,9 +82,10 @@ EXPORT_SYMBOL_GPL(percpu_populate);
+ int __percpu_populate_mask(void *__pdata, size_t size, gfp_t gfp,
+ cpumask_t *mask)
+ {
+- cpumask_t populated = CPU_MASK_NONE;
++ cpumask_t populated;
+ int cpu;
+
++ cpus_clear(populated);
+ for_each_cpu_mask(cpu, *mask)
+ if (unlikely(!percpu_populate(__pdata, size, gfp, cpu))) {
+ __percpu_depopulate_mask(__pdata, &populated);
+diff --git a/mm/maccess.c b/mm/maccess.c
+new file mode 100644
+index 0000000..ac40796
+--- /dev/null
++++ b/mm/maccess.c
+@@ -0,0 +1,55 @@
++/*
++ * Access kernel memory without faulting.
++ */
++#include <linux/uaccess.h>
++#include <linux/module.h>
++#include <linux/mm.h>
++
++/**
++ * probe_kernel_read(): safely attempt to read from a location
++ * @dst: pointer to the buffer that shall take the data
++ * @src: address to read from
++ * @size: size of the data chunk
++ *
++ * Safely read from address @src to the buffer at @dst. If a kernel fault
++ * happens, handle that and return -EFAULT.
++ */
++long probe_kernel_read(void *dst, void *src, size_t size)
++{
++ long ret;
++ mm_segment_t old_fs = get_fs();
++
++ set_fs(KERNEL_DS);
++ pagefault_disable();
++ ret = __copy_from_user_inatomic(dst,
++ (__force const void __user *)src, size);
++ pagefault_enable();
++ set_fs(old_fs);
++
++ return ret ? -EFAULT : 0;
++}
++EXPORT_SYMBOL_GPL(probe_kernel_read);
++
++/**
++ * probe_kernel_write(): safely attempt to write to a location
++ * @dst: address to write to
++ * @src: pointer to the data that shall be written
++ * @size: size of the data chunk
++ *
++ * Safely write to address @dst from the buffer at @src. If a kernel fault
++ * happens, handle that and return -EFAULT.
++ */
++long probe_kernel_write(void *dst, void *src, size_t size)
++{
++ long ret;
++ mm_segment_t old_fs = get_fs();
++
++ set_fs(KERNEL_DS);
++ pagefault_disable();
++ ret = __copy_to_user_inatomic((__force void __user *)dst, src, size);
++ pagefault_enable();
++ set_fs(old_fs);
++
++ return ret ? -EFAULT : 0;
++}
++EXPORT_SYMBOL_GPL(probe_kernel_write);
+diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
+index 7469c50..0fb3302 100644
+--- a/mm/memory_hotplug.c
++++ b/mm/memory_hotplug.c
+@@ -208,7 +208,7 @@ int online_pages(unsigned long pfn, unsigned long nr_pages)
+ /*
+ * This doesn't need a lock to do pfn_to_page().
+ * The section can't be removed here because of the
+- * memory_block->state_sem.
++ * memory_block->state_mutex.
+ */
+ zone = page_zone(pfn_to_page(pfn));
+ pgdat_resize_lock(zone->zone_pgdat, &flags);
+diff --git a/mm/page_alloc.c b/mm/page_alloc.c
+index 402a504..32e796a 100644
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -2029,6 +2029,7 @@ static int find_next_best_node(int node, nodemask_t *used_node_mask)
+ int n, val;
+ int min_val = INT_MAX;
+ int best_node = -1;
++ node_to_cpumask_ptr(tmp, 0);
+
+ /* Use the local node if we haven't already */
+ if (!node_isset(node, *used_node_mask)) {
+@@ -2037,7 +2038,6 @@ static int find_next_best_node(int node, nodemask_t *used_node_mask)
+ }
+
+ for_each_node_state(n, N_HIGH_MEMORY) {
+- cpumask_t tmp;
+
+ /* Don't want a node to appear more than once */
+ if (node_isset(n, *used_node_mask))
+@@ -2050,8 +2050,8 @@ static int find_next_best_node(int node, nodemask_t *used_node_mask)
+ val += (n < node);
+
+ /* Give preference to headless and unused nodes */
+- tmp = node_to_cpumask(n);
+- if (!cpus_empty(tmp))
++ node_to_cpumask_ptr_next(tmp, n);
++ if (!cpus_empty(*tmp))
+ val += PENALTY_FOR_NODE_WITH_CPUS;
+
+ /* Slight preference for less loaded node */
+diff --git a/mm/pdflush.c b/mm/pdflush.c
+index 8f6ee07..1c96cfc 100644
+--- a/mm/pdflush.c
++++ b/mm/pdflush.c
+@@ -17,8 +17,8 @@
+ #include <linux/gfp.h>
+ #include <linux/init.h>
+ #include <linux/module.h>
+-#include <linux/fs.h> // Needed by writeback.h
+-#include <linux/writeback.h> // Prototypes pdflush_operation()
++#include <linux/fs.h> /* Needed by writeback.h */
++#include <linux/writeback.h> /* Prototypes pdflush_operation() */
+ #include <linux/kthread.h>
+ #include <linux/cpuset.h>
+ #include <linux/freezer.h>
+@@ -187,8 +187,8 @@ static int pdflush(void *dummy)
+ * This is needed as pdflush's are dynamically created and destroyed.
+ * The boottime pdflush's are easily placed w/o these 2 lines.
+ */
+- cpus_allowed = cpuset_cpus_allowed(current);
+- set_cpus_allowed(current, cpus_allowed);
++ cpuset_cpus_allowed(current, &cpus_allowed);
++ set_cpus_allowed_ptr(current, &cpus_allowed);
+
+ return __pdflush(&my_work);
+ }
+diff --git a/mm/slab.c b/mm/slab.c
+index 04b308c..03927cb 100644
+--- a/mm/slab.c
++++ b/mm/slab.c
+@@ -1160,14 +1160,13 @@ static void __cpuinit cpuup_canceled(long cpu)
+ struct kmem_cache *cachep;
+ struct kmem_list3 *l3 = NULL;
+ int node = cpu_to_node(cpu);
++ node_to_cpumask_ptr(mask, node);
+
+ list_for_each_entry(cachep, &cache_chain, next) {
+ struct array_cache *nc;
+ struct array_cache *shared;
+ struct array_cache **alien;
+- cpumask_t mask;
+
+- mask = node_to_cpumask(node);
+ /* cpu is dead; no one can alloc from it. */
+ nc = cachep->array[cpu];
+ cachep->array[cpu] = NULL;
+@@ -1183,7 +1182,7 @@ static void __cpuinit cpuup_canceled(long cpu)
+ if (nc)
+ free_block(cachep, nc->entry, nc->avail, node);
+
+- if (!cpus_empty(mask)) {
++ if (!cpus_empty(*mask)) {
+ spin_unlock_irq(&l3->list_lock);
+ goto free_array_cache;
+ }
+diff --git a/mm/slub.c b/mm/slub.c
+index acc975f..39592b5 100644
+--- a/mm/slub.c
++++ b/mm/slub.c
+@@ -521,7 +521,7 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)
+ static void object_err(struct kmem_cache *s, struct page *page,
+ u8 *object, char *reason)
+ {
+- slab_bug(s, reason);
++ slab_bug(s, "%s", reason);
+ print_trailer(s, page, object);
+ }
+
+@@ -533,7 +533,7 @@ static void slab_err(struct kmem_cache *s, struct page *page, char *fmt, ...)
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+- slab_bug(s, fmt);
++ slab_bug(s, "%s", buf);
+ print_page_info(page);
+ dump_stack();
+ }
+@@ -837,6 +837,35 @@ static void remove_full(struct kmem_cache *s, struct page *page)
+ spin_unlock(&n->list_lock);
+ }
+
++/* Tracking of the number of slabs for debugging purposes */
++static inline unsigned long slabs_node(struct kmem_cache *s, int node)
++{
++ struct kmem_cache_node *n = get_node(s, node);
++
++ return atomic_long_read(&n->nr_slabs);
++}
++
++static inline void inc_slabs_node(struct kmem_cache *s, int node)
++{
++ struct kmem_cache_node *n = get_node(s, node);
++
++ /*
++ * May be called early in order to allocate a slab for the
++ * kmem_cache_node structure. Solve the chicken-egg
++ * dilemma by deferring the increment of the count during
++ * bootstrap (see early_kmem_cache_node_alloc).
++ */
++ if (!NUMA_BUILD || n)
++ atomic_long_inc(&n->nr_slabs);
++}
++static inline void dec_slabs_node(struct kmem_cache *s, int node)
++{
++ struct kmem_cache_node *n = get_node(s, node);
++
++ atomic_long_dec(&n->nr_slabs);
++}
++
++/* Object debug checks for alloc/free paths */
+ static void setup_object_debug(struct kmem_cache *s, struct page *page,
+ void *object)
+ {
+@@ -1028,6 +1057,11 @@ static inline unsigned long kmem_cache_flags(unsigned long objsize,
+ return flags;
+ }
+ #define slub_debug 0
++
++static inline unsigned long slabs_node(struct kmem_cache *s, int node)
++ { return 0; }
++static inline void inc_slabs_node(struct kmem_cache *s, int node) {}
++static inline void dec_slabs_node(struct kmem_cache *s, int node) {}
+ #endif
+ /*
+ * Slab allocation and freeing
+@@ -1066,7 +1100,6 @@ static void setup_object(struct kmem_cache *s, struct page *page,
+ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
+ {
+ struct page *page;
+- struct kmem_cache_node *n;
+ void *start;
+ void *last;
+ void *p;
+@@ -1078,9 +1111,7 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
+ if (!page)
+ goto out;
+
+- n = get_node(s, page_to_nid(page));
+- if (n)
+- atomic_long_inc(&n->nr_slabs);
++ inc_slabs_node(s, page_to_nid(page));
+ page->slab = s;
+ page->flags |= 1 << PG_slab;
+ if (s->flags & (SLAB_DEBUG_FREE | SLAB_RED_ZONE | SLAB_POISON |
+@@ -1125,6 +1156,8 @@ static void __free_slab(struct kmem_cache *s, struct page *page)
+ NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE,
+ -pages);
+
++ __ClearPageSlab(page);
++ reset_page_mapcount(page);
+ __free_pages(page, s->order);
+ }
+
+@@ -1151,11 +1184,7 @@ static void free_slab(struct kmem_cache *s, struct page *page)
+
+ static void discard_slab(struct kmem_cache *s, struct page *page)
+ {
+- struct kmem_cache_node *n = get_node(s, page_to_nid(page));
+-
+- atomic_long_dec(&n->nr_slabs);
+- reset_page_mapcount(page);
+- __ClearPageSlab(page);
++ dec_slabs_node(s, page_to_nid(page));
+ free_slab(s, page);
+ }
+
+@@ -1886,15 +1915,18 @@ static void init_kmem_cache_cpu(struct kmem_cache *s,
+ c->node = 0;
+ c->offset = s->offset / sizeof(void *);
+ c->objsize = s->objsize;
++#ifdef CONFIG_SLUB_STATS
++ memset(c->stat, 0, NR_SLUB_STAT_ITEMS * sizeof(unsigned));
++#endif
+ }
+
+ static void init_kmem_cache_node(struct kmem_cache_node *n)
+ {
+ n->nr_partial = 0;
+- atomic_long_set(&n->nr_slabs, 0);
+ spin_lock_init(&n->list_lock);
+ INIT_LIST_HEAD(&n->partial);
+ #ifdef CONFIG_SLUB_DEBUG
++ atomic_long_set(&n->nr_slabs, 0);
+ INIT_LIST_HEAD(&n->full);
+ #endif
+ }
+@@ -2063,7 +2095,7 @@ static struct kmem_cache_node *early_kmem_cache_node_alloc(gfp_t gfpflags,
+ init_tracking(kmalloc_caches, n);
+ #endif
+ init_kmem_cache_node(n);
+- atomic_long_inc(&n->nr_slabs);
++ inc_slabs_node(kmalloc_caches, node);
+
+ /*
+ * lockdep requires consistent irq usage for each lock
+@@ -2376,7 +2408,7 @@ static inline int kmem_cache_close(struct kmem_cache *s)
+ struct kmem_cache_node *n = get_node(s, node);
+
+ n->nr_partial -= free_list(s, n, &n->partial);
+- if (atomic_long_read(&n->nr_slabs))
++ if (slabs_node(s, node))
+ return 1;
+ }
+ free_kmem_cache_nodes(s);
+@@ -2409,10 +2441,6 @@ EXPORT_SYMBOL(kmem_cache_destroy);
+ struct kmem_cache kmalloc_caches[PAGE_SHIFT + 1] __cacheline_aligned;
+ EXPORT_SYMBOL(kmalloc_caches);
+
+-#ifdef CONFIG_ZONE_DMA
+-static struct kmem_cache *kmalloc_caches_dma[PAGE_SHIFT + 1];
+-#endif
+-
+ static int __init setup_slub_min_order(char *str)
+ {
+ get_option(&str, &slub_min_order);
+@@ -2472,6 +2500,7 @@ panic:
+ }
+
+ #ifdef CONFIG_ZONE_DMA
++static struct kmem_cache *kmalloc_caches_dma[PAGE_SHIFT + 1];
+
+ static void sysfs_add_func(struct work_struct *w)
+ {
+@@ -2688,21 +2717,6 @@ void kfree(const void *x)
+ }
+ EXPORT_SYMBOL(kfree);
+
+-#if defined(CONFIG_SLUB_DEBUG) || defined(CONFIG_SLABINFO)
+-static unsigned long count_partial(struct kmem_cache_node *n)
+-{
+- unsigned long flags;
+- unsigned long x = 0;
+- struct page *page;
+-
+- spin_lock_irqsave(&n->list_lock, flags);
+- list_for_each_entry(page, &n->partial, lru)
+- x += page->inuse;
+- spin_unlock_irqrestore(&n->list_lock, flags);
+- return x;
+-}
+-#endif
+-
+ /*
+ * kmem_cache_shrink removes empty slabs from the partial lists and sorts
+ * the remaining slabs by the number of items in use. The slabs with the
+@@ -2816,7 +2830,7 @@ static void slab_mem_offline_callback(void *arg)
+ * and offline_pages() function shoudn't call this
+ * callback. So, we must fail.
+ */
+- BUG_ON(atomic_long_read(&n->nr_slabs));
++ BUG_ON(slabs_node(s, offline_node));
+
+ s->node[offline_node] = NULL;
+ kmem_cache_free(kmalloc_caches, n);
+@@ -3181,6 +3195,21 @@ void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags,
+ return slab_alloc(s, gfpflags, node, caller);
+ }
+
++#if (defined(CONFIG_SYSFS) && defined(CONFIG_SLUB_DEBUG)) || defined(CONFIG_SLABINFO)
++static unsigned long count_partial(struct kmem_cache_node *n)
++{
++ unsigned long flags;
++ unsigned long x = 0;
++ struct page *page;
++
++ spin_lock_irqsave(&n->list_lock, flags);
++ list_for_each_entry(page, &n->partial, lru)
++ x += page->inuse;
++ spin_unlock_irqrestore(&n->list_lock, flags);
++ return x;
++}
++#endif
++
+ #if defined(CONFIG_SYSFS) && defined(CONFIG_SLUB_DEBUG)
+ static int validate_slab(struct kmem_cache *s, struct page *page,
+ unsigned long *map)
+@@ -3979,10 +4008,12 @@ static int show_stat(struct kmem_cache *s, char *buf, enum stat_item si)
+
+ len = sprintf(buf, "%lu", sum);
+
++#ifdef CONFIG_SMP
+ for_each_online_cpu(cpu) {
+ if (data[cpu] && len < PAGE_SIZE - 20)
+- len += sprintf(buf + len, " c%d=%u", cpu, data[cpu]);
++ len += sprintf(buf + len, " C%d=%u", cpu, data[cpu]);
+ }
++#endif
+ kfree(data);
+ return len + sprintf(buf + len, "\n");
+ }
+diff --git a/mm/vmscan.c b/mm/vmscan.c
+index 4046434..f80a5b7 100644
+--- a/mm/vmscan.c
++++ b/mm/vmscan.c
+@@ -1647,11 +1647,10 @@ static int kswapd(void *p)
+ struct reclaim_state reclaim_state = {
+ .reclaimed_slab = 0,
+ };
+- cpumask_t cpumask;
++ node_to_cpumask_ptr(cpumask, pgdat->node_id);
+
+- cpumask = node_to_cpumask(pgdat->node_id);
+- if (!cpus_empty(cpumask))
+- set_cpus_allowed(tsk, cpumask);
++ if (!cpus_empty(*cpumask))
++ set_cpus_allowed_ptr(tsk, cpumask);
+ current->reclaim_state = &reclaim_state;
+
+ /*
+@@ -1880,17 +1879,16 @@ out:
+ static int __devinit cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+ {
+- pg_data_t *pgdat;
+- cpumask_t mask;
+ int nid;
+
+ if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN) {
+ for_each_node_state(nid, N_HIGH_MEMORY) {
+- pgdat = NODE_DATA(nid);
+- mask = node_to_cpumask(pgdat->node_id);
+- if (any_online_cpu(mask) != NR_CPUS)
++ pg_data_t *pgdat = NODE_DATA(nid);
++ node_to_cpumask_ptr(mask, pgdat->node_id);
++
++ if (any_online_cpu(*mask) < nr_cpu_ids)
+ /* One of our CPUs online: restore mask */
+- set_cpus_allowed(pgdat->kswapd, mask);
++ set_cpus_allowed_ptr(pgdat->kswapd, mask);
+ }
+ }
+ return NOTIFY_OK;
+diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
+index b33410a..2a739ad 100644
+--- a/net/8021q/vlan.c
++++ b/net/8021q/vlan.c
+@@ -32,6 +32,7 @@
+ #include <linux/rtnetlink.h>
+ #include <linux/notifier.h>
+ #include <net/net_namespace.h>
++#include <net/netns/generic.h>
+
+ #include <linux/if_vlan.h>
+ #include "vlan.h"
+@@ -41,6 +42,8 @@
+
+ /* Global VLAN variables */
+
++int vlan_net_id;
++
+ /* Our listing of VLAN group(s) */
+ static struct hlist_head vlan_group_hash[VLAN_GRP_HASH_SIZE];
+
+@@ -49,9 +52,6 @@ static char vlan_version[] = DRV_VERSION;
+ static char vlan_copyright[] = "Ben Greear <greearb at candelatech.com>";
+ static char vlan_buggyright[] = "David S. Miller <davem at redhat.com>";
+
+-/* Determines interface naming scheme. */
+-unsigned short vlan_name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD;
+-
+ static struct packet_type vlan_packet_type = {
+ .type = __constant_htons(ETH_P_8021Q),
+ .func = vlan_skb_recv, /* VLAN receive method */
+@@ -65,14 +65,14 @@ static inline unsigned int vlan_grp_hashfn(unsigned int idx)
+ }
+
+ /* Must be invoked with RCU read lock (no preempt) */
+-static struct vlan_group *__vlan_find_group(int real_dev_ifindex)
++static struct vlan_group *__vlan_find_group(struct net_device *real_dev)
+ {
+ struct vlan_group *grp;
+ struct hlist_node *n;
+- int hash = vlan_grp_hashfn(real_dev_ifindex);
++ int hash = vlan_grp_hashfn(real_dev->ifindex);
+
+ hlist_for_each_entry_rcu(grp, n, &vlan_group_hash[hash], hlist) {
+- if (grp->real_dev_ifindex == real_dev_ifindex)
++ if (grp->real_dev == real_dev)
+ return grp;
+ }
+
+@@ -86,7 +86,7 @@ static struct vlan_group *__vlan_find_group(int real_dev_ifindex)
+ struct net_device *__find_vlan_dev(struct net_device *real_dev,
+ unsigned short VID)
+ {
+- struct vlan_group *grp = __vlan_find_group(real_dev->ifindex);
++ struct vlan_group *grp = __vlan_find_group(real_dev);
+
+ if (grp)
+ return vlan_group_get_device(grp, VID);
+@@ -103,32 +103,38 @@ static void vlan_group_free(struct vlan_group *grp)
+ kfree(grp);
+ }
+
+-static struct vlan_group *vlan_group_alloc(int ifindex)
++static struct vlan_group *vlan_group_alloc(struct net_device *real_dev)
+ {
+ struct vlan_group *grp;
+- unsigned int size;
+- unsigned int i;
+
+ grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL);
+ if (!grp)
+ return NULL;
+
+- size = sizeof(struct net_device *) * VLAN_GROUP_ARRAY_PART_LEN;
+-
+- for (i = 0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) {
+- grp->vlan_devices_arrays[i] = kzalloc(size, GFP_KERNEL);
+- if (!grp->vlan_devices_arrays[i])
+- goto err;
+- }
+-
+- grp->real_dev_ifindex = ifindex;
++ grp->real_dev = real_dev;
+ hlist_add_head_rcu(&grp->hlist,
+- &vlan_group_hash[vlan_grp_hashfn(ifindex)]);
++ &vlan_group_hash[vlan_grp_hashfn(real_dev->ifindex)]);
+ return grp;
++}
+
+-err:
+- vlan_group_free(grp);
+- return NULL;
++static int vlan_group_prealloc_vid(struct vlan_group *vg, int vid)
++{
++ struct net_device **array;
++ unsigned int size;
++
++ ASSERT_RTNL();
++
++ array = vg->vlan_devices_arrays[vid / VLAN_GROUP_ARRAY_PART_LEN];
++ if (array != NULL)
++ return 0;
++
++ size = sizeof(struct net_device *) * VLAN_GROUP_ARRAY_PART_LEN;
++ array = kzalloc(size, GFP_KERNEL);
++ if (array == NULL)
++ return -ENOBUFS;
++
++ vg->vlan_devices_arrays[vid / VLAN_GROUP_ARRAY_PART_LEN] = array;
++ return 0;
+ }
+
+ static void vlan_rcu_free(struct rcu_head *rcu)
+@@ -145,11 +151,9 @@ void unregister_vlan_dev(struct net_device *dev)
+
+ ASSERT_RTNL();
+
+- grp = __vlan_find_group(real_dev->ifindex);
++ grp = __vlan_find_group(real_dev);
+ BUG_ON(!grp);
+
+- vlan_proc_rem_dev(dev);
+-
+ /* Take it out of our own structures, but be sure to interlock with
+ * HW accelerating devices or SW vlan input packet processing.
+ */
+@@ -240,13 +244,17 @@ int register_vlan_dev(struct net_device *dev)
+ struct vlan_group *grp, *ngrp = NULL;
+ int err;
+
+- grp = __vlan_find_group(real_dev->ifindex);
++ grp = __vlan_find_group(real_dev);
+ if (!grp) {
+- ngrp = grp = vlan_group_alloc(real_dev->ifindex);
++ ngrp = grp = vlan_group_alloc(real_dev);
+ if (!grp)
+ return -ENOBUFS;
+ }
+
++ err = vlan_group_prealloc_vid(grp, vlan_id);
++ if (err < 0)
++ goto out_free_group;
++
+ err = register_netdevice(dev);
+ if (err < 0)
+ goto out_free_group;
+@@ -268,9 +276,6 @@ int register_vlan_dev(struct net_device *dev)
+ if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
+ real_dev->vlan_rx_add_vid(real_dev, vlan_id);
+
+- if (vlan_proc_add_dev(dev) < 0)
+- pr_warning("8021q: failed to add proc entry for %s\n",
+- dev->name);
+ return 0;
+
+ out_free_group:
+@@ -286,6 +291,8 @@ static int register_vlan_device(struct net_device *real_dev,
+ unsigned short VLAN_ID)
+ {
+ struct net_device *new_dev;
++ struct net *net = dev_net(real_dev);
++ struct vlan_net *vn = net_generic(net, vlan_net_id);
+ char name[IFNAMSIZ];
+ int err;
+
+@@ -297,7 +304,7 @@ static int register_vlan_device(struct net_device *real_dev,
+ return err;
+
+ /* Gotta set up the fields for the device. */
+- switch (vlan_name_type) {
++ switch (vn->name_type) {
+ case VLAN_NAME_TYPE_RAW_PLUS_VID:
+ /* name will look like: eth1.0005 */
+ snprintf(name, IFNAMSIZ, "%s.%.4i", real_dev->name, VLAN_ID);
+@@ -328,6 +335,7 @@ static int register_vlan_device(struct net_device *real_dev,
+ if (new_dev == NULL)
+ return -ENOBUFS;
+
++ dev_net_set(new_dev, net);
+ /* need 4 bytes for extra VLAN header info,
+ * hope the underlying device can handle it.
+ */
+@@ -383,6 +391,14 @@ static void __vlan_device_event(struct net_device *dev, unsigned long event)
+ pr_warning("8021q: failed to change proc name for %s\n",
+ dev->name);
+ break;
++ case NETDEV_REGISTER:
++ if (vlan_proc_add_dev(dev) < 0)
++ pr_warning("8021q: failed to add proc entry for %s\n",
++ dev->name);
++ break;
++ case NETDEV_UNREGISTER:
++ vlan_proc_rem_dev(dev);
++ break;
+ }
+ }
+
+@@ -394,15 +410,12 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
+ int i, flgs;
+ struct net_device *vlandev;
+
+- if (dev->nd_net != &init_net)
+- return NOTIFY_DONE;
+-
+ if (is_vlan_dev(dev)) {
+ __vlan_device_event(dev, event);
+ goto out;
+ }
+
+- grp = __vlan_find_group(dev->ifindex);
++ grp = __vlan_find_group(dev);
+ if (!grp)
+ goto out;
+
+@@ -522,7 +535,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
+ case GET_VLAN_REALDEV_NAME_CMD:
+ case GET_VLAN_VID_CMD:
+ err = -ENODEV;
+- dev = __dev_get_by_name(&init_net, args.device1);
++ dev = __dev_get_by_name(net, args.device1);
+ if (!dev)
+ goto out;
+
+@@ -567,7 +580,10 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
+ break;
+ if ((args.u.name_type >= 0) &&
+ (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
+- vlan_name_type = args.u.name_type;
++ struct vlan_net *vn;
++
++ vn = net_generic(net, vlan_net_id);
++ vn->name_type = args.u.name_type;
+ err = 0;
+ } else {
+ err = -EINVAL;
+@@ -615,6 +631,51 @@ out:
+ return err;
+ }
+
++static int vlan_init_net(struct net *net)
++{
++ int err;
++ struct vlan_net *vn;
++
++ err = -ENOMEM;
++ vn = kzalloc(sizeof(struct vlan_net), GFP_KERNEL);
++ if (vn == NULL)
++ goto err_alloc;
++
++ err = net_assign_generic(net, vlan_net_id, vn);
++ if (err < 0)
++ goto err_assign;
++
++ vn->name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD;
++
++ err = vlan_proc_init(net);
++ if (err < 0)
++ goto err_proc;
++
++ return 0;
++
++err_proc:
++ /* nothing */
++err_assign:
++ kfree(vn);
++err_alloc:
++ return err;
++}
++
++static void vlan_exit_net(struct net *net)
++{
++ struct vlan_net *vn;
++
++ vn = net_generic(net, vlan_net_id);
++ rtnl_kill_links(net, &vlan_link_ops);
++ vlan_proc_cleanup(net);
++ kfree(vn);
++}
++
++static struct pernet_operations vlan_net_ops = {
++ .init = vlan_init_net,
++ .exit = vlan_exit_net,
++};
++
+ static int __init vlan_proto_init(void)
+ {
+ int err;
+@@ -622,9 +683,9 @@ static int __init vlan_proto_init(void)
+ pr_info("%s v%s %s\n", vlan_fullname, vlan_version, vlan_copyright);
+ pr_info("All bugs added by %s\n", vlan_buggyright);
+
+- err = vlan_proc_init();
++ err = register_pernet_gen_device(&vlan_net_id, &vlan_net_ops);
+ if (err < 0)
+- goto err1;
++ goto err0;
+
+ err = register_netdevice_notifier(&vlan_notifier_block);
+ if (err < 0)
+@@ -641,8 +702,8 @@ static int __init vlan_proto_init(void)
+ err3:
+ unregister_netdevice_notifier(&vlan_notifier_block);
+ err2:
+- vlan_proc_cleanup();
+-err1:
++ unregister_pernet_gen_device(vlan_net_id, &vlan_net_ops);
++err0:
+ return err;
+ }
+
+@@ -661,7 +722,7 @@ static void __exit vlan_cleanup_module(void)
+ for (i = 0; i < VLAN_GRP_HASH_SIZE; i++)
+ BUG_ON(!hlist_empty(&vlan_group_hash[i]));
+
+- vlan_proc_cleanup();
++ unregister_pernet_gen_device(vlan_net_id, &vlan_net_ops);
+
+ synchronize_net();
+ }
+diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
+index 51271ae..5229a72 100644
+--- a/net/8021q/vlan.h
++++ b/net/8021q/vlan.h
+@@ -3,8 +3,6 @@
+
+ #include <linux/if_vlan.h>
+
+-extern unsigned short vlan_name_type;
+-
+ #define VLAN_GRP_HASH_SHIFT 5
+ #define VLAN_GRP_HASH_SIZE (1 << VLAN_GRP_HASH_SHIFT)
+ #define VLAN_GRP_HASH_MASK (VLAN_GRP_HASH_SIZE - 1)
+@@ -50,4 +48,17 @@ static inline int is_vlan_dev(struct net_device *dev)
+ return dev->priv_flags & IFF_802_1Q_VLAN;
+ }
+
++extern int vlan_net_id;
++
++struct proc_dir_entry;
++
++struct vlan_net {
++ /* /proc/net/vlan */
++ struct proc_dir_entry *proc_vlan_dir;
++ /* /proc/net/vlan/config */
++ struct proc_dir_entry *proc_vlan_conf;
++ /* Determines interface naming scheme. */
++ unsigned short name_type;
++};
++
+ #endif /* !(__BEN_VLAN_802_1Q_INC__) */
+diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
+index 41a76a0..c961f08 100644
+--- a/net/8021q/vlan_dev.c
++++ b/net/8021q/vlan_dev.c
+@@ -153,9 +153,6 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
+ struct net_device_stats *stats;
+ unsigned short vlan_TCI;
+
+- if (dev->nd_net != &init_net)
+- goto err_free;
+-
+ skb = skb_share_check(skb, GFP_ATOMIC);
+ if (skb == NULL)
+ goto err_free;
+@@ -171,7 +168,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
+ skb->dev = __find_vlan_dev(dev, vid);
+ if (!skb->dev) {
+ pr_debug("%s: ERROR: No net_device for VID: %u on dev: %s\n",
+- __FUNCTION__, (unsigned int)vid, dev->name);
++ __func__, (unsigned int)vid, dev->name);
+ goto err_unlock;
+ }
+
+@@ -187,7 +184,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
+ ntohs(vhdr->h_vlan_TCI));
+
+ pr_debug("%s: priority: %u for TCI: %hu\n",
+- __FUNCTION__, skb->priority, ntohs(vhdr->h_vlan_TCI));
++ __func__, skb->priority, ntohs(vhdr->h_vlan_TCI));
+
+ switch (skb->pkt_type) {
+ case PACKET_BROADCAST: /* Yeah, stats collect these together.. */
+@@ -268,7 +265,7 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,
+ struct net_device *vdev = dev;
+
+ pr_debug("%s: skb: %p type: %hx len: %u vlan_id: %hx, daddr: %p\n",
+- __FUNCTION__, skb, type, len, vlan_dev_info(dev)->vlan_id,
++ __func__, skb, type, len, vlan_dev_info(dev)->vlan_id,
+ daddr);
+
+ /* build vlan header only if re_order_header flag is NOT set. This
+@@ -340,7 +337,7 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,
+ return -ENOMEM;
+ }
+ vlan_dev_info(vdev)->cnt_inc_headroom_on_tx++;
+- pr_debug("%s: %s: had to grow skb\n", __FUNCTION__, vdev->name);
++ pr_debug("%s: %s: had to grow skb\n", __func__, vdev->name);
+ }
+
+ if (build_vlan_header) {
+@@ -382,7 +379,7 @@ static int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ vlan_dev_info(dev)->cnt_encap_on_xmit++;
+
+ pr_debug("%s: proto to encap: 0x%hx\n",
+- __FUNCTION__, ntohs(veth->h_vlan_proto));
++ __func__, ntohs(veth->h_vlan_proto));
+ /* Construct the second two bytes. This field looks something
+ * like:
+ * usr_priority: 3 bits (high bits)
+@@ -403,7 +400,7 @@ static int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ }
+
+ pr_debug("%s: about to send skb: %p to dev: %s\n",
+- __FUNCTION__, skb, skb->dev->name);
++ __func__, skb, skb->dev->name);
+ pr_debug(" " MAC_FMT " " MAC_FMT " %4hx %4hx %4hx\n",
+ veth->h_dest[0], veth->h_dest[1], veth->h_dest[2],
+ veth->h_dest[3], veth->h_dest[4], veth->h_dest[5],
+diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c
+index e32eeb3..c93e69e 100644
+--- a/net/8021q/vlan_netlink.c
++++ b/net/8021q/vlan_netlink.c
+@@ -113,7 +113,7 @@ static int vlan_newlink(struct net_device *dev,
+
+ if (!tb[IFLA_LINK])
+ return -EINVAL;
+- real_dev = __dev_get_by_index(&init_net, nla_get_u32(tb[IFLA_LINK]));
++ real_dev = __dev_get_by_index(dev_net(dev), nla_get_u32(tb[IFLA_LINK]));
+ if (!real_dev)
+ return -ENODEV;
+
+diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
+index 9671aa5..daad006 100644
+--- a/net/8021q/vlanproc.c
++++ b/net/8021q/vlanproc.c
+@@ -34,6 +34,7 @@
+ #include <linux/netdevice.h>
+ #include <linux/if_vlan.h>
+ #include <net/net_namespace.h>
++#include <net/netns/generic.h>
+ #include "vlanproc.h"
+ #include "vlan.h"
+
+@@ -79,7 +80,8 @@ static const struct seq_operations vlan_seq_ops = {
+
+ static int vlan_seq_open(struct inode *inode, struct file *file)
+ {
+- return seq_open(file, &vlan_seq_ops);
++ return seq_open_net(inode, file, &vlan_seq_ops,
++ sizeof(struct seq_net_private));
+ }
+
+ static const struct file_operations vlan_fops = {
+@@ -87,7 +89,7 @@ static const struct file_operations vlan_fops = {
+ .open = vlan_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = seq_release,
++ .release = seq_release_net,
+ };
+
+ /*
+@@ -111,18 +113,6 @@ static const struct file_operations vlandev_fops = {
+ * Proc filesystem derectory entries.
+ */
+
+-/*
+- * /proc/net/vlan
+- */
+-
+-static struct proc_dir_entry *proc_vlan_dir;
+-
+-/*
+- * /proc/net/vlan/config
+- */
+-
+-static struct proc_dir_entry *proc_vlan_conf;
+-
+ /* Strings */
+ static const char *vlan_name_type_str[VLAN_NAME_TYPE_HIGHEST] = {
+ [VLAN_NAME_TYPE_RAW_PLUS_VID] = "VLAN_NAME_TYPE_RAW_PLUS_VID",
+@@ -138,13 +128,15 @@ static const char *vlan_name_type_str[VLAN_NAME_TYPE_HIGHEST] = {
+ * Clean up /proc/net/vlan entries
+ */
+
+-void vlan_proc_cleanup(void)
++void vlan_proc_cleanup(struct net *net)
+ {
+- if (proc_vlan_conf)
+- remove_proc_entry(name_conf, proc_vlan_dir);
++ struct vlan_net *vn = net_generic(net, vlan_net_id);
++
++ if (vn->proc_vlan_conf)
++ remove_proc_entry(name_conf, vn->proc_vlan_dir);
+
+- if (proc_vlan_dir)
+- proc_net_remove(&init_net, name_root);
++ if (vn->proc_vlan_dir)
++ proc_net_remove(net, name_root);
+
+ /* Dynamically added entries should be cleaned up as their vlan_device
+ * is removed, so we should not have to take care of it here...
+@@ -155,21 +147,23 @@ void vlan_proc_cleanup(void)
+ * Create /proc/net/vlan entries
+ */
+
+-int __init vlan_proc_init(void)
++int vlan_proc_init(struct net *net)
+ {
+- proc_vlan_dir = proc_mkdir(name_root, init_net.proc_net);
+- if (!proc_vlan_dir)
++ struct vlan_net *vn = net_generic(net, vlan_net_id);
++
++ vn->proc_vlan_dir = proc_net_mkdir(net, name_root, net->proc_net);
++ if (!vn->proc_vlan_dir)
+ goto err;
+
+- proc_vlan_conf = proc_create(name_conf, S_IFREG|S_IRUSR|S_IWUSR,
+- proc_vlan_dir, &vlan_fops);
+- if (!proc_vlan_conf)
++ vn->proc_vlan_conf = proc_create(name_conf, S_IFREG|S_IRUSR|S_IWUSR,
++ vn->proc_vlan_dir, &vlan_fops);
++ if (!vn->proc_vlan_conf)
+ goto err;
+ return 0;
+
+ err:
+- pr_err("%s: can't create entry in proc filesystem!\n", __FUNCTION__);
+- vlan_proc_cleanup();
++ pr_err("%s: can't create entry in proc filesystem!\n", __func__);
++ vlan_proc_cleanup(net);
+ return -ENOBUFS;
+ }
+
+@@ -180,9 +174,10 @@ err:
+ int vlan_proc_add_dev(struct net_device *vlandev)
+ {
+ struct vlan_dev_info *dev_info = vlan_dev_info(vlandev);
++ struct vlan_net *vn = net_generic(dev_net(vlandev), vlan_net_id);
+
+ dev_info->dent = proc_create(vlandev->name, S_IFREG|S_IRUSR|S_IWUSR,
+- proc_vlan_dir, &vlandev_fops);
++ vn->proc_vlan_dir, &vlandev_fops);
+ if (!dev_info->dent)
+ return -ENOBUFS;
+
+@@ -195,10 +190,12 @@ int vlan_proc_add_dev(struct net_device *vlandev)
+ */
+ int vlan_proc_rem_dev(struct net_device *vlandev)
+ {
++ struct vlan_net *vn = net_generic(dev_net(vlandev), vlan_net_id);
++
+ /** NOTE: This will consume the memory pointed to by dent, it seems. */
+ if (vlan_dev_info(vlandev)->dent) {
+ remove_proc_entry(vlan_dev_info(vlandev)->dent->name,
+- proc_vlan_dir);
++ vn->proc_vlan_dir);
+ vlan_dev_info(vlandev)->dent = NULL;
+ }
+ return 0;
+@@ -215,6 +212,7 @@ static void *vlan_seq_start(struct seq_file *seq, loff_t *pos)
+ __acquires(dev_base_lock)
+ {
+ struct net_device *dev;
++ struct net *net = seq_file_net(seq);
+ loff_t i = 1;
+
+ read_lock(&dev_base_lock);
+@@ -222,7 +220,7 @@ static void *vlan_seq_start(struct seq_file *seq, loff_t *pos)
+ if (*pos == 0)
+ return SEQ_START_TOKEN;
+
+- for_each_netdev(&init_net, dev) {
++ for_each_netdev(net, dev) {
+ if (!is_vlan_dev(dev))
+ continue;
+
+@@ -236,14 +234,15 @@ static void *vlan_seq_start(struct seq_file *seq, loff_t *pos)
+ static void *vlan_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+ {
+ struct net_device *dev;
++ struct net *net = seq_file_net(seq);
+
+ ++*pos;
+
+ dev = (struct net_device *)v;
+ if (v == SEQ_START_TOKEN)
+- dev = net_device_entry(&init_net.dev_base_head);
++ dev = net_device_entry(&net->dev_base_head);
+
+- for_each_netdev_continue(&init_net, dev) {
++ for_each_netdev_continue(net, dev) {
+ if (!is_vlan_dev(dev))
+ continue;
+
+@@ -261,13 +260,16 @@ static void vlan_seq_stop(struct seq_file *seq, void *v)
+
+ static int vlan_seq_show(struct seq_file *seq, void *v)
+ {
++ struct net *net = seq_file_net(seq);
++ struct vlan_net *vn = net_generic(net, vlan_net_id);
++
+ if (v == SEQ_START_TOKEN) {
+ const char *nmtype = NULL;
+
+ seq_puts(seq, "VLAN Dev name | VLAN ID\n");
+
+- if (vlan_name_type < ARRAY_SIZE(vlan_name_type_str))
+- nmtype = vlan_name_type_str[vlan_name_type];
++ if (vn->name_type < ARRAY_SIZE(vlan_name_type_str))
++ nmtype = vlan_name_type_str[vn->name_type];
+
+ seq_printf(seq, "Name-Type: %s\n",
+ nmtype ? nmtype : "UNKNOWN");
+diff --git a/net/8021q/vlanproc.h b/net/8021q/vlanproc.h
+index da542ca..063f60a 100644
+--- a/net/8021q/vlanproc.h
++++ b/net/8021q/vlanproc.h
+@@ -2,15 +2,17 @@
+ #define __BEN_VLAN_PROC_INC__
+
+ #ifdef CONFIG_PROC_FS
+-int vlan_proc_init(void);
++struct net;
++
++int vlan_proc_init(struct net *net);
+ int vlan_proc_rem_dev(struct net_device *vlandev);
+ int vlan_proc_add_dev(struct net_device *vlandev);
+-void vlan_proc_cleanup(void);
++void vlan_proc_cleanup(struct net *net);
+
+ #else /* No CONFIG_PROC_FS */
+
+-#define vlan_proc_init() (0)
+-#define vlan_proc_cleanup() do {} while (0)
++#define vlan_proc_init(net) (0)
++#define vlan_proc_cleanup(net) do {} while (0)
+ #define vlan_proc_add_dev(dev) ({(void)(dev), 0; })
+ #define vlan_proc_rem_dev(dev) ({(void)(dev), 0; })
+ #endif
+diff --git a/net/9p/error.c b/net/9p/error.c
+index ab2458b..64104b9 100644
+--- a/net/9p/error.c
++++ b/net/9p/error.c
+@@ -230,7 +230,7 @@ int p9_errstr2errno(char *errstr, int len)
+ if (errno == 0) {
+ /* TODO: if error isn't found, add it dynamically */
+ errstr[len] = 0;
+- printk(KERN_ERR "%s: errstr :%s: not found\n", __FUNCTION__,
++ printk(KERN_ERR "%s: errstr :%s: not found\n", __func__,
+ errstr);
+ errno = 1;
+ }
+diff --git a/net/Kconfig b/net/Kconfig
+index 6627c6a..acbf7c6 100644
+--- a/net/Kconfig
++++ b/net/Kconfig
+@@ -45,7 +45,7 @@ config INET
+ ---help---
+ These are the protocols used on the Internet and on most local
+ Ethernets. It is highly recommended to say Y here (this will enlarge
+- your kernel by about 144 KB), since some programs (e.g. the X window
++ your kernel by about 400 KB), since some programs (e.g. the X window
+ system) use TCP/IP even if your machine is not connected to any
+ other computer. You will get the so-called loopback device which
+ allows you to ping yourself (great fun, that!).
+diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c
+index 18058bb..25aa37c 100644
+--- a/net/appletalk/aarp.c
++++ b/net/appletalk/aarp.c
+@@ -333,7 +333,7 @@ static int aarp_device_event(struct notifier_block *this, unsigned long event,
+ struct net_device *dev = ptr;
+ int ct;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ if (event == NETDEV_DOWN) {
+@@ -716,7 +716,7 @@ static int aarp_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct atalk_addr sa, *ma, da;
+ struct atalk_iface *ifa;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ goto out0;
+
+ /* We only do Ethernet SNAP AARP. */
+@@ -1033,25 +1033,8 @@ static const struct seq_operations aarp_seq_ops = {
+
+ static int aarp_seq_open(struct inode *inode, struct file *file)
+ {
+- struct seq_file *seq;
+- int rc = -ENOMEM;
+- struct aarp_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+-
+- if (!s)
+- goto out;
+-
+- rc = seq_open(file, &aarp_seq_ops);
+- if (rc)
+- goto out_kfree;
+-
+- seq = file->private_data;
+- seq->private = s;
+- memset(s, 0, sizeof(*s));
+-out:
+- return rc;
+-out_kfree:
+- kfree(s);
+- goto out;
++ return seq_open_private(file, &aarp_seq_ops,
++ sizeof(struct aarp_iter_state));
+ }
+
+ const struct file_operations atalk_seq_arp_fops = {
+diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
+index 3be55c8..44cd42f 100644
+--- a/net/appletalk/ddp.c
++++ b/net/appletalk/ddp.c
+@@ -648,7 +648,7 @@ static int ddp_device_event(struct notifier_block *this, unsigned long event,
+ {
+ struct net_device *dev = ptr;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ if (event == NETDEV_DOWN)
+@@ -1405,7 +1405,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
+ int origlen;
+ __u16 len_hops;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ goto freeit;
+
+ /* Don't mangle buffer if shared */
+@@ -1493,7 +1493,7 @@ freeit:
+ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt, struct net_device *orig_dev)
+ {
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ goto freeit;
+
+ /* Expand any short form frames */
+diff --git a/net/atm/clip.c b/net/atm/clip.c
+index 2ab1e36..6f8223e 100644
+--- a/net/atm/clip.c
++++ b/net/atm/clip.c
+@@ -612,7 +612,7 @@ static int clip_device_event(struct notifier_block *this, unsigned long event,
+ {
+ struct net_device *dev = arg;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ if (event == NETDEV_UNREGISTER) {
+@@ -648,10 +648,6 @@ static int clip_inet_event(struct notifier_block *this, unsigned long event,
+ struct in_device *in_dev;
+
+ in_dev = ((struct in_ifaddr *)ifa)->ifa_dev;
+- if (!in_dev || !in_dev->dev) {
+- printk(KERN_WARNING "clip_inet_event: no device\n");
+- return NOTIFY_DONE;
+- }
+ /*
+ * Transitions are of the down-change-up type, so it's sufficient to
+ * handle the change on up.
+diff --git a/net/atm/lec.c b/net/atm/lec.c
+index 3235c57..653aca3 100644
+--- a/net/atm/lec.c
++++ b/net/atm/lec.c
+@@ -1023,7 +1023,7 @@ static void *lec_tbl_walk(struct lec_state *state, struct hlist_head *tbl,
+
+ if (!e)
+ e = tbl->first;
+- if (e == (void *)1) {
++ if (e == SEQ_START_TOKEN) {
+ e = tbl->first;
+ --*l;
+ }
+@@ -1125,9 +1125,9 @@ static void *lec_seq_start(struct seq_file *seq, loff_t *pos)
+ state->locked = NULL;
+ state->arp_table = 0;
+ state->misc_table = 0;
+- state->node = (void *)1;
++ state->node = SEQ_START_TOKEN;
+
+- return *pos ? lec_get_idx(state, *pos) : (void *)1;
++ return *pos ? lec_get_idx(state, *pos) : SEQ_START_TOKEN;
+ }
+
+ static void lec_seq_stop(struct seq_file *seq, void *v)
+@@ -1156,7 +1156,7 @@ static int lec_seq_show(struct seq_file *seq, void *v)
+ " Status Flags "
+ "VPI/VCI Recv VPI/VCI\n";
+
+- if (v == (void *)1)
++ if (v == SEQ_START_TOKEN)
+ seq_puts(seq, lec_banner);
+ else {
+ struct lec_state *state = seq->private;
+@@ -1178,32 +1178,7 @@ static const struct seq_operations lec_seq_ops = {
+
+ static int lec_seq_open(struct inode *inode, struct file *file)
+ {
+- struct lec_state *state;
+- struct seq_file *seq;
+- int rc = -EAGAIN;
+-
+- state = kmalloc(sizeof(*state), GFP_KERNEL);
+- if (!state) {
+- rc = -ENOMEM;
+- goto out;
+- }
+-
+- rc = seq_open(file, &lec_seq_ops);
+- if (rc)
+- goto out_kfree;
+- seq = file->private_data;
+- seq->private = state;
+-out:
+- return rc;
+-
+-out_kfree:
+- kfree(state);
+- goto out;
+-}
+-
+-static int lec_seq_release(struct inode *inode, struct file *file)
+-{
+- return seq_release_private(inode, file);
++ return seq_open_private(file, &lec_seq_ops, sizeof(struct lec_state));
+ }
+
+ static const struct file_operations lec_seq_fops = {
+@@ -1211,7 +1186,7 @@ static const struct file_operations lec_seq_fops = {
+ .open = lec_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = lec_seq_release,
++ .release = seq_release_private,
+ };
+ #endif
+
+diff --git a/net/atm/mpc.c b/net/atm/mpc.c
+index 9c7f712..9db332e 100644
+--- a/net/atm/mpc.c
++++ b/net/atm/mpc.c
+@@ -964,7 +964,7 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned lo
+
+ dev = (struct net_device *)dev_ptr;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ if (dev->name == NULL || strncmp(dev->name, "lec", 3))
+diff --git a/net/atm/proc.c b/net/atm/proc.c
+index e9693ae..5c9f3d1 100644
+--- a/net/atm/proc.c
++++ b/net/atm/proc.c
+@@ -78,7 +78,7 @@ static int __vcc_walk(struct sock **sock, int family, int *bucket, loff_t l)
+ {
+ struct sock *sk = *sock;
+
+- if (sk == (void *)1) {
++ if (sk == SEQ_START_TOKEN) {
+ for (*bucket = 0; *bucket < VCC_HTABLE_SIZE; ++*bucket) {
+ struct hlist_head *head = &vcc_hash[*bucket];
+
+@@ -98,7 +98,7 @@ try_again:
+ sk = sk_head(&vcc_hash[*bucket]);
+ goto try_again;
+ }
+- sk = (void *)1;
++ sk = SEQ_START_TOKEN;
+ out:
+ *sock = sk;
+ return (l < 0);
+@@ -114,31 +114,13 @@ static int __vcc_seq_open(struct inode *inode, struct file *file,
+ int family, const struct seq_operations *ops)
+ {
+ struct vcc_state *state;
+- struct seq_file *seq;
+- int rc = -ENOMEM;
+
+- state = kmalloc(sizeof(*state), GFP_KERNEL);
+- if (!state)
+- goto out;
+-
+- rc = seq_open(file, ops);
+- if (rc)
+- goto out_kfree;
++ state = __seq_open_private(file, ops, sizeof(*state));
++ if (state == NULL)
++ return -ENOMEM;
+
+ state->family = family;
+-
+- seq = file->private_data;
+- seq->private = state;
+-out:
+- return rc;
+-out_kfree:
+- kfree(state);
+- goto out;
+-}
+-
+-static int vcc_seq_release(struct inode *inode, struct file *file)
+-{
+- return seq_release_private(inode, file);
++ return 0;
+ }
+
+ static void *vcc_seq_start(struct seq_file *seq, loff_t *pos)
+@@ -148,8 +130,8 @@ static void *vcc_seq_start(struct seq_file *seq, loff_t *pos)
+ loff_t left = *pos;
+
+ read_lock(&vcc_sklist_lock);
+- state->sk = (void *)1;
+- return left ? vcc_walk(state, left) : (void *)1;
++ state->sk = SEQ_START_TOKEN;
++ return left ? vcc_walk(state, left) : SEQ_START_TOKEN;
+ }
+
+ static void vcc_seq_stop(struct seq_file *seq, void *v)
+@@ -253,7 +235,7 @@ static int atm_dev_seq_show(struct seq_file *seq, void *v)
+ "Itf Type ESI/\"MAC\"addr "
+ "AAL(TX,err,RX,err,drop) ... [refcnt]\n";
+
+- if (v == (void *)1)
++ if (v == SEQ_START_TOKEN)
+ seq_puts(seq, atm_dev_banner);
+ else {
+ struct atm_dev *dev = list_entry(v, struct atm_dev, dev_list);
+@@ -287,7 +269,7 @@ static int pvc_seq_show(struct seq_file *seq, void *v)
+ static char atm_pvc_banner[] =
+ "Itf VPI VCI AAL RX(PCR,Class) TX(PCR,Class)\n";
+
+- if (v == (void *)1)
++ if (v == SEQ_START_TOKEN)
+ seq_puts(seq, atm_pvc_banner);
+ else {
+ struct vcc_state *state = seq->private;
+@@ -314,12 +296,12 @@ static const struct file_operations pvc_seq_fops = {
+ .open = pvc_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = vcc_seq_release,
++ .release = seq_release_private,
+ };
+
+ static int vcc_seq_show(struct seq_file *seq, void *v)
+ {
+- if (v == (void *)1) {
++ if (v == SEQ_START_TOKEN) {
+ seq_printf(seq, sizeof(void *) == 4 ? "%-8s%s" : "%-16s%s",
+ "Address ", "Itf VPI VCI Fam Flags Reply "
+ "Send buffer Recv buffer [refcnt]\n");
+@@ -348,7 +330,7 @@ static const struct file_operations vcc_seq_fops = {
+ .open = vcc_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = vcc_seq_release,
++ .release = seq_release_private,
+ };
+
+ static int svc_seq_show(struct seq_file *seq, void *v)
+@@ -356,7 +338,7 @@ static int svc_seq_show(struct seq_file *seq, void *v)
+ static char atm_svc_banner[] =
+ "Itf VPI VCI State Remote\n";
+
+- if (v == (void *)1)
++ if (v == SEQ_START_TOKEN)
+ seq_puts(seq, atm_svc_banner);
+ else {
+ struct vcc_state *state = seq->private;
+@@ -383,7 +365,7 @@ static const struct file_operations svc_seq_fops = {
+ .open = svc_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = vcc_seq_release,
++ .release = seq_release_private,
+ };
+
+ static ssize_t proc_dev_atm_read(struct file *file, char __user *buf,
+diff --git a/net/atm/resources.c b/net/atm/resources.c
+index 1bcf6dc..a34ba94 100644
+--- a/net/atm/resources.c
++++ b/net/atm/resources.c
+@@ -415,7 +415,7 @@ static __inline__ void *dev_get_idx(loff_t left)
+ void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos)
+ {
+ mutex_lock(&atm_dev_mutex);
+- return *pos ? dev_get_idx(*pos) : (void *) 1;
++ return *pos ? dev_get_idx(*pos) : SEQ_START_TOKEN;
+ }
+
+ void atm_dev_seq_stop(struct seq_file *seq, void *v)
+@@ -426,7 +426,8 @@ void atm_dev_seq_stop(struct seq_file *seq, void *v)
+ void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+ {
+ ++*pos;
+- v = (v == (void *)1) ? atm_devs.next : ((struct list_head *)v)->next;
++ v = (v == SEQ_START_TOKEN)
++ ? atm_devs.next : ((struct list_head *)v)->next;
+ return (v == &atm_devs) ? NULL : v;
+ }
+
+diff --git a/net/atm/svc.c b/net/atm/svc.c
+index daf9a48..de1e4f2 100644
+--- a/net/atm/svc.c
++++ b/net/atm/svc.c
+@@ -326,7 +326,7 @@ static int svc_accept(struct socket *sock,struct socket *newsock,int flags)
+
+ lock_sock(sk);
+
+- error = svc_create(sk->sk_net, newsock,0);
++ error = svc_create(sock_net(sk), newsock,0);
+ if (error)
+ goto out;
+
+diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
+index 48bfcc7..2712544 100644
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -116,7 +116,7 @@ static int ax25_device_event(struct notifier_block *this, unsigned long event,
+ {
+ struct net_device *dev = (struct net_device *)ptr;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ /* Reject non AX.25 devices */
+@@ -869,7 +869,7 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)
+ struct sock *sk;
+ ax25_cb *ax25, *oax25;
+
+- sk = sk_alloc(osk->sk_net, PF_AX25, GFP_ATOMIC, osk->sk_prot);
++ sk = sk_alloc(sock_net(osk), PF_AX25, GFP_ATOMIC, osk->sk_prot);
+ if (sk == NULL)
+ return NULL;
+
+diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c
+index d1be080..33790a8 100644
+--- a/net/ax25/ax25_in.c
++++ b/net/ax25/ax25_in.c
+@@ -451,7 +451,7 @@ int ax25_kiss_rcv(struct sk_buff *skb, struct net_device *dev,
+ skb->sk = NULL; /* Initially we don't know who it's for */
+ skb->destructor = NULL; /* Who initializes this, dammit?! */
+
+- if (dev->nd_net != &init_net) {
++ if (dev_net(dev) != &init_net) {
+ kfree_skb(skb);
+ return 0;
+ }
+diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
+index 2957df4..a4849f2 100644
+--- a/net/bluetooth/l2cap.c
++++ b/net/bluetooth/l2cap.c
+@@ -1499,7 +1499,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
+ goto response;
+ }
+
+- sk = l2cap_sock_alloc(parent->sk_net, NULL, BTPROTO_L2CAP, GFP_ATOMIC);
++ sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
+ if (!sk)
+ goto response;
+
+diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
+index af4e393..5083adc 100644
+--- a/net/bluetooth/rfcomm/sock.c
++++ b/net/bluetooth/rfcomm/sock.c
+@@ -868,7 +868,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
+ goto done;
+ }
+
+- sk = rfcomm_sock_alloc(parent->sk_net, NULL, BTPROTO_RFCOMM, GFP_ATOMIC);
++ sk = rfcomm_sock_alloc(sock_net(parent), NULL, BTPROTO_RFCOMM, GFP_ATOMIC);
+ if (!sk)
+ goto done;
+
+diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
+index cd887cd..b0d487e 100644
+--- a/net/bluetooth/sco.c
++++ b/net/bluetooth/sco.c
+@@ -803,7 +803,7 @@ static void sco_conn_ready(struct sco_conn *conn)
+
+ bh_lock_sock(parent);
+
+- sk = sco_sock_alloc(parent->sk_net, NULL, BTPROTO_SCO, GFP_ATOMIC);
++ sk = sco_sock_alloc(sock_net(parent), NULL, BTPROTO_SCO, GFP_ATOMIC);
+ if (!sk) {
+ bh_unlock_sock(parent);
+ goto done;
+diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
+index af7e8be..bb90cd7 100644
+--- a/net/bridge/br_netfilter.c
++++ b/net/bridge/br_netfilter.c
+@@ -111,7 +111,9 @@ static inline __be16 pppoe_proto(const struct sk_buff *skb)
+ * require us to fill additional fields. */
+ static struct net_device __fake_net_device = {
+ .hard_header_len = ETH_HLEN,
++#ifdef CONFIG_NET_NS
+ .nd_net = &init_net,
++#endif
+ };
+
+ static struct rtable __fake_rtable = {
+@@ -224,8 +226,8 @@ static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb)
+ }
+ nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING;
+
+- skb->dst = (struct dst_entry *)&__fake_rtable;
+- dst_hold(skb->dst);
++ skb->rtable = &__fake_rtable;
++ dst_hold(&__fake_rtable.u.dst);
+
+ skb->dev = nf_bridge->physindev;
+ nf_bridge_push_encap_header(skb);
+@@ -389,8 +391,8 @@ bridged_dnat:
+ skb->pkt_type = PACKET_HOST;
+ }
+ } else {
+- skb->dst = (struct dst_entry *)&__fake_rtable;
+- dst_hold(skb->dst);
++ skb->rtable = &__fake_rtable;
++ dst_hold(&__fake_rtable.u.dst);
+ }
+
+ skb->dev = nf_bridge->physindev;
+@@ -609,9 +611,9 @@ static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff *skb,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+ {
+- if (skb->dst == (struct dst_entry *)&__fake_rtable) {
+- dst_release(skb->dst);
+- skb->dst = NULL;
++ if (skb->rtable == &__fake_rtable) {
++ dst_release(&__fake_rtable.u.dst);
++ skb->rtable = NULL;
+ }
+
+ return NF_ACCEPT;
+diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
+index f5d6933..f155e6c 100644
+--- a/net/bridge/br_netlink.c
++++ b/net/bridge/br_netlink.c
+@@ -108,7 +108,7 @@ errout:
+ */
+ static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct net_device *dev;
+ int idx;
+
+@@ -140,7 +140,7 @@ skip:
+ */
+ static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct ifinfomsg *ifm;
+ struct nlattr *protinfo;
+ struct net_device *dev;
+diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c
+index 07ac3ae..00644a5 100644
+--- a/net/bridge/br_notify.c
++++ b/net/bridge/br_notify.c
+@@ -37,7 +37,7 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
+ struct net_bridge_port *p = dev->br_port;
+ struct net_bridge *br;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ /* not a port of a bridge */
+diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c
+index 0edbd2a..8deab64 100644
+--- a/net/bridge/br_stp_bpdu.c
++++ b/net/bridge/br_stp_bpdu.c
+@@ -142,7 +142,7 @@ int br_stp_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct net_bridge *br;
+ const unsigned char *buf;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ goto err;
+
+ if (!p)
+diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
+index 9cf0538..27d6a51 100644
+--- a/net/bridge/br_sysfs_br.c
++++ b/net/bridge/br_sysfs_br.c
+@@ -415,21 +415,21 @@ int br_sysfs_addbr(struct net_device *dev)
+ err = sysfs_create_group(brobj, &bridge_group);
+ if (err) {
+ pr_info("%s: can't create group %s/%s\n",
+- __FUNCTION__, dev->name, bridge_group.name);
++ __func__, dev->name, bridge_group.name);
+ goto out1;
+ }
+
+ err = sysfs_create_bin_file(brobj, &bridge_forward);
+ if (err) {
+ pr_info("%s: can't create attribute file %s/%s\n",
+- __FUNCTION__, dev->name, bridge_forward.attr.name);
++ __func__, dev->name, bridge_forward.attr.name);
+ goto out2;
+ }
+
+ br->ifobj = kobject_create_and_add(SYSFS_BRIDGE_PORT_SUBDIR, brobj);
+ if (!br->ifobj) {
+ pr_info("%s: can't add kobject (directory) %s/%s\n",
+- __FUNCTION__, dev->name, SYSFS_BRIDGE_PORT_SUBDIR);
++ __func__, dev->name, SYSFS_BRIDGE_PORT_SUBDIR);
+ goto out3;
+ }
+ return 0;
+diff --git a/net/bridge/netfilter/Kconfig b/net/bridge/netfilter/Kconfig
+index 4a3e2bf..7beeefa 100644
+--- a/net/bridge/netfilter/Kconfig
++++ b/net/bridge/netfilter/Kconfig
+@@ -212,4 +212,18 @@ config BRIDGE_EBT_ULOG
+
+ To compile it as a module, choose M here. If unsure, say N.
+
++config BRIDGE_EBT_NFLOG
++ tristate "ebt: nflog support"
++ depends on BRIDGE_NF_EBTABLES
++ help
++ This option enables the nflog watcher, which allows to LOG
++ messages through the netfilter logging API, which can use
++ either the old LOG target, the old ULOG target or nfnetlink_log
++ as backend.
++
++ This option adds the ulog watcher, that you can use in any rule
++ in any ebtables table.
++
++ To compile it as a module, choose M here. If unsure, say N.
++
+ endmenu
+diff --git a/net/bridge/netfilter/Makefile b/net/bridge/netfilter/Makefile
+index 905087e..83715d7 100644
+--- a/net/bridge/netfilter/Makefile
++++ b/net/bridge/netfilter/Makefile
+@@ -30,3 +30,4 @@ obj-$(CONFIG_BRIDGE_EBT_SNAT) += ebt_snat.o
+ # watchers
+ obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_log.o
+ obj-$(CONFIG_BRIDGE_EBT_ULOG) += ebt_ulog.o
++obj-$(CONFIG_BRIDGE_EBT_NFLOG) += ebt_nflog.o
+diff --git a/net/bridge/netfilter/ebt_nflog.c b/net/bridge/netfilter/ebt_nflog.c
+new file mode 100644
+index 0000000..8e799aa
+--- /dev/null
++++ b/net/bridge/netfilter/ebt_nflog.c
+@@ -0,0 +1,74 @@
++/*
++ * ebt_nflog
++ *
++ * Author:
++ * Peter Warasin <peter at endian.com>
++ *
++ * February, 2008
++ *
++ * Based on:
++ * xt_NFLOG.c, (C) 2006 by Patrick McHardy <kaber at trash.net>
++ * ebt_ulog.c, (C) 2004 by Bart De Schuymer <bdschuym at pandora.be>
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/spinlock.h>
++#include <linux/netfilter_bridge/ebtables.h>
++#include <linux/netfilter_bridge/ebt_nflog.h>
++#include <net/netfilter/nf_log.h>
++
++static void ebt_nflog(const struct sk_buff *skb,
++ unsigned int hooknr,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *data, unsigned int datalen)
++{
++ struct ebt_nflog_info *info = (struct ebt_nflog_info *)data;
++ struct nf_loginfo li;
++
++ li.type = NF_LOG_TYPE_ULOG;
++ li.u.ulog.copy_len = info->len;
++ li.u.ulog.group = info->group;
++ li.u.ulog.qthreshold = info->threshold;
++
++ nf_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li, "%s", info->prefix);
++}
++
++static int ebt_nflog_check(const char *tablename,
++ unsigned int hookmask,
++ const struct ebt_entry *e,
++ void *data, unsigned int datalen)
++{
++ struct ebt_nflog_info *info = (struct ebt_nflog_info *)data;
++
++ if (datalen != EBT_ALIGN(sizeof(struct ebt_nflog_info)))
++ return -EINVAL;
++ if (info->flags & ~EBT_NFLOG_MASK)
++ return -EINVAL;
++ info->prefix[EBT_NFLOG_PREFIX_SIZE - 1] = '\0';
++ return 0;
++}
++
++static struct ebt_watcher nflog __read_mostly = {
++ .name = EBT_NFLOG_WATCHER,
++ .watcher = ebt_nflog,
++ .check = ebt_nflog_check,
++ .me = THIS_MODULE,
++};
++
++static int __init ebt_nflog_init(void)
++{
++ return ebt_register_watcher(&nflog);
++}
++
++static void __exit ebt_nflog_fini(void)
++{
++ ebt_unregister_watcher(&nflog);
++}
++
++module_init(ebt_nflog_init);
++module_exit(ebt_nflog_fini);
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Peter Warasin <peter at endian.com>");
++MODULE_DESCRIPTION("ebtables NFLOG netfilter logging module");
+diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c
+index be6f186..246626b 100644
+--- a/net/bridge/netfilter/ebtable_broute.c
++++ b/net/bridge/netfilter/ebtable_broute.c
+@@ -46,7 +46,7 @@ static struct ebt_table broute_table =
+ .name = "broute",
+ .table = &initial_table,
+ .valid_hooks = 1 << NF_BR_BROUTING,
+- .lock = RW_LOCK_UNLOCKED,
++ .lock = __RW_LOCK_UNLOCKED(broute_table.lock),
+ .check = check,
+ .me = THIS_MODULE,
+ };
+diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
+index fb81090..690bc3a 100644
+--- a/net/bridge/netfilter/ebtable_filter.c
++++ b/net/bridge/netfilter/ebtable_filter.c
+@@ -55,7 +55,7 @@ static struct ebt_table frame_filter =
+ .name = "filter",
+ .table = &initial_table,
+ .valid_hooks = FILTER_VALID_HOOKS,
+- .lock = RW_LOCK_UNLOCKED,
++ .lock = __RW_LOCK_UNLOCKED(frame_filter.lock),
+ .check = check,
+ .me = THIS_MODULE,
+ };
+diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c
+index bc71273..5b495fe 100644
+--- a/net/bridge/netfilter/ebtable_nat.c
++++ b/net/bridge/netfilter/ebtable_nat.c
+@@ -55,7 +55,7 @@ static struct ebt_table frame_nat =
+ .name = "nat",
+ .table = &initial_table,
+ .valid_hooks = NAT_VALID_HOOKS,
+- .lock = RW_LOCK_UNLOCKED,
++ .lock = __RW_LOCK_UNLOCKED(frame_nat.lock),
+ .check = check,
+ .me = THIS_MODULE,
+ };
+diff --git a/net/can/af_can.c b/net/can/af_can.c
+index 36b9f22..2759b76 100644
+--- a/net/can/af_can.c
++++ b/net/can/af_can.c
+@@ -599,7 +599,7 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct dev_rcv_lists *d;
+ int matches;
+
+- if (dev->type != ARPHRD_CAN || dev->nd_net != &init_net) {
++ if (dev->type != ARPHRD_CAN || dev_net(dev) != &init_net) {
+ kfree_skb(skb);
+ return 0;
+ }
+@@ -710,7 +710,7 @@ static int can_notifier(struct notifier_block *nb, unsigned long msg,
+ struct net_device *dev = (struct net_device *)data;
+ struct dev_rcv_lists *d;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ if (dev->type != ARPHRD_CAN)
+diff --git a/net/can/bcm.c b/net/can/bcm.c
+index bd4282d..74fd2d3 100644
+--- a/net/can/bcm.c
++++ b/net/can/bcm.c
+@@ -43,6 +43,7 @@
+
+ #include <linux/module.h>
+ #include <linux/init.h>
++#include <linux/hrtimer.h>
+ #include <linux/list.h>
+ #include <linux/proc_fs.h>
+ #include <linux/uio.h>
+@@ -66,7 +67,7 @@
+ #define REGMASK(id) ((id & CAN_RTR_FLAG) | ((id & CAN_EFF_FLAG) ? \
+ (CAN_EFF_MASK | CAN_EFF_FLAG) : CAN_SFF_MASK))
+
+-#define CAN_BCM_VERSION CAN_VERSION
++#define CAN_BCM_VERSION "20080415"
+ static __initdata const char banner[] = KERN_INFO
+ "can: broadcast manager protocol (rev " CAN_BCM_VERSION ")\n";
+
+@@ -85,11 +86,10 @@ struct bcm_op {
+ int ifindex;
+ canid_t can_id;
+ int flags;
+- unsigned long j_ival1, j_ival2, j_lastmsg;
+ unsigned long frames_abs, frames_filtered;
+- struct timer_list timer, thrtimer;
+ struct timeval ival1, ival2;
+- ktime_t rx_stamp;
++ struct hrtimer timer, thrtimer;
++ ktime_t rx_stamp, kt_ival1, kt_ival2, kt_lastmsg;
+ int rx_ifindex;
+ int count;
+ int nframes;
+@@ -126,39 +126,6 @@ static inline struct bcm_sock *bcm_sk(const struct sock *sk)
+ #define MHSIZ sizeof(struct bcm_msg_head)
+
+ /*
+- * rounded_tv2jif - calculate jiffies from timeval including optional up
+- * @tv: pointer to timeval
+- *
+- * Description:
+- * Unlike timeval_to_jiffies() provided in include/linux/jiffies.h, this
+- * function is intentionally more relaxed on precise timer ticks to get
+- * exact one jiffy for requested 1000us on a 1000HZ machine.
+- * This code is to be removed when upgrading to kernel hrtimer.
+- *
+- * Return:
+- * calculated jiffies (max: ULONG_MAX)
+- */
+-static unsigned long rounded_tv2jif(const struct timeval *tv)
+-{
+- unsigned long sec = tv->tv_sec;
+- unsigned long usec = tv->tv_usec;
+- unsigned long jif;
+-
+- if (sec > ULONG_MAX / HZ)
+- return ULONG_MAX;
+-
+- /* round up to get at least the requested time */
+- usec += 1000000 / HZ - 1;
+-
+- jif = usec / (1000000 / HZ);
+-
+- if (sec * HZ > ULONG_MAX - jif)
+- return ULONG_MAX;
+-
+- return jif + sec * HZ;
+-}
+-
+-/*
+ * procfs functions
+ */
+ static char *bcm_proc_getifname(int ifindex)
+@@ -208,13 +175,17 @@ static int bcm_read_proc(char *page, char **start, off_t off,
+ len += snprintf(page + len, PAGE_SIZE - len, "[%d]%c ",
+ op->nframes,
+ (op->flags & RX_CHECK_DLC)?'d':' ');
+- if (op->j_ival1)
++ if (op->kt_ival1.tv64)
+ len += snprintf(page + len, PAGE_SIZE - len,
+- "timeo=%ld ", op->j_ival1);
++ "timeo=%lld ",
++ (long long)
++ ktime_to_us(op->kt_ival1));
+
+- if (op->j_ival2)
++ if (op->kt_ival2.tv64)
+ len += snprintf(page + len, PAGE_SIZE - len,
+- "thr=%ld ", op->j_ival2);
++ "thr=%lld ",
++ (long long)
++ ktime_to_us(op->kt_ival2));
+
+ len += snprintf(page + len, PAGE_SIZE - len,
+ "# recv %ld (%ld) => reduction: ",
+@@ -238,13 +209,14 @@ static int bcm_read_proc(char *page, char **start, off_t off,
+ "tx_op: %03X %s [%d] ",
+ op->can_id, bcm_proc_getifname(op->ifindex),
+ op->nframes);
+- if (op->j_ival1)
+- len += snprintf(page + len, PAGE_SIZE - len, "t1=%ld ",
+- op->j_ival1);
+
+- if (op->j_ival2)
+- len += snprintf(page + len, PAGE_SIZE - len, "t2=%ld ",
+- op->j_ival2);
++ if (op->kt_ival1.tv64)
++ len += snprintf(page + len, PAGE_SIZE - len, "t1=%lld ",
++ (long long) ktime_to_us(op->kt_ival1));
++
++ if (op->kt_ival2.tv64)
++ len += snprintf(page + len, PAGE_SIZE - len, "t2=%lld ",
++ (long long) ktime_to_us(op->kt_ival2));
+
+ len += snprintf(page + len, PAGE_SIZE - len, "# sent %ld\n",
+ op->frames_abs);
+@@ -371,11 +343,12 @@ static void bcm_send_to_user(struct bcm_op *op, struct bcm_msg_head *head,
+ /*
+ * bcm_tx_timeout_handler - performes cyclic CAN frame transmissions
+ */
+-static void bcm_tx_timeout_handler(unsigned long data)
++static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer)
+ {
+- struct bcm_op *op = (struct bcm_op *)data;
++ struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
++ enum hrtimer_restart ret = HRTIMER_NORESTART;
+
+- if (op->j_ival1 && (op->count > 0)) {
++ if (op->kt_ival1.tv64 && (op->count > 0)) {
+
+ op->count--;
+ if (!op->count && (op->flags & TX_COUNTEVT)) {
+@@ -394,22 +367,24 @@ static void bcm_tx_timeout_handler(unsigned long data)
+ }
+ }
+
+- if (op->j_ival1 && (op->count > 0)) {
++ if (op->kt_ival1.tv64 && (op->count > 0)) {
+
+ /* send (next) frame */
+ bcm_can_tx(op);
+- mod_timer(&op->timer, jiffies + op->j_ival1);
++ hrtimer_forward(hrtimer, ktime_get(), op->kt_ival1);
++ ret = HRTIMER_RESTART;
+
+ } else {
+- if (op->j_ival2) {
++ if (op->kt_ival2.tv64) {
+
+ /* send (next) frame */
+ bcm_can_tx(op);
+- mod_timer(&op->timer, jiffies + op->j_ival2);
++ hrtimer_forward(hrtimer, ktime_get(), op->kt_ival2);
++ ret = HRTIMER_RESTART;
+ }
+ }
+
+- return;
++ return ret;
+ }
+
+ /*
+@@ -419,8 +394,6 @@ static void bcm_rx_changed(struct bcm_op *op, struct can_frame *data)
+ {
+ struct bcm_msg_head head;
+
+- op->j_lastmsg = jiffies;
+-
+ /* update statistics */
+ op->frames_filtered++;
+
+@@ -439,6 +412,12 @@ static void bcm_rx_changed(struct bcm_op *op, struct can_frame *data)
+ bcm_send_to_user(op, &head, data, 1);
+ }
+
++/* TODO: move to linux/hrtimer.h */
++static inline int hrtimer_callback_running(struct hrtimer *timer)
++{
++ return timer->state & HRTIMER_STATE_CALLBACK;
++}
++
+ /*
+ * bcm_rx_update_and_send - process a detected relevant receive content change
+ * 1. update the last received data
+@@ -448,30 +427,44 @@ static void bcm_rx_update_and_send(struct bcm_op *op,
+ struct can_frame *lastdata,
+ struct can_frame *rxdata)
+ {
+- unsigned long nexttx = op->j_lastmsg + op->j_ival2;
+-
+ memcpy(lastdata, rxdata, CFSIZ);
+
+ /* mark as used */
+ lastdata->can_dlc |= RX_RECV;
+
+- /* throttle bcm_rx_changed ? */
+- if ((op->thrtimer.expires) ||
+- ((op->j_ival2) && (nexttx > jiffies))) {
+- /* we are already waiting OR we have to start waiting */
++ /* throtteling mode inactive OR data update already on the run ? */
++ if (!op->kt_ival2.tv64 || hrtimer_callback_running(&op->thrtimer)) {
++ /* send RX_CHANGED to the user immediately */
++ bcm_rx_changed(op, rxdata);
++ return;
++ }
+
++ if (hrtimer_active(&op->thrtimer)) {
+ /* mark as 'throttled' */
+ lastdata->can_dlc |= RX_THR;
++ return;
++ }
+
+- if (!(op->thrtimer.expires)) {
+- /* start the timer only the first time */
+- mod_timer(&op->thrtimer, nexttx);
+- }
+-
+- } else {
+- /* send RX_CHANGED to the user immediately */
++ if (!op->kt_lastmsg.tv64) {
++ /* send first RX_CHANGED to the user immediately */
+ bcm_rx_changed(op, rxdata);
++ op->kt_lastmsg = ktime_get();
++ return;
++ }
++
++ if (ktime_us_delta(ktime_get(), op->kt_lastmsg) <
++ ktime_to_us(op->kt_ival2)) {
++ /* mark as 'throttled' and start timer */
++ lastdata->can_dlc |= RX_THR;
++ hrtimer_start(&op->thrtimer,
++ ktime_add(op->kt_lastmsg, op->kt_ival2),
++ HRTIMER_MODE_ABS);
++ return;
+ }
++
++ /* the gap was that big, that throttling was not needed here */
++ bcm_rx_changed(op, rxdata);
++ op->kt_lastmsg = ktime_get();
+ }
+
+ /*
+@@ -519,16 +512,16 @@ static void bcm_rx_starttimer(struct bcm_op *op)
+ if (op->flags & RX_NO_AUTOTIMER)
+ return;
+
+- if (op->j_ival1)
+- mod_timer(&op->timer, jiffies + op->j_ival1);
++ if (op->kt_ival1.tv64)
++ hrtimer_start(&op->timer, op->kt_ival1, HRTIMER_MODE_REL);
+ }
+
+ /*
+ * bcm_rx_timeout_handler - when the (cyclic) CAN frame receiption timed out
+ */
+-static void bcm_rx_timeout_handler(unsigned long data)
++static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
+ {
+- struct bcm_op *op = (struct bcm_op *)data;
++ struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
+ struct bcm_msg_head msg_head;
+
+ msg_head.opcode = RX_TIMEOUT;
+@@ -548,27 +541,27 @@ static void bcm_rx_timeout_handler(unsigned long data)
+ /* clear received can_frames to indicate 'nothing received' */
+ memset(op->last_frames, 0, op->nframes * CFSIZ);
+ }
++
++ return HRTIMER_NORESTART;
+ }
+
+ /*
+- * bcm_rx_thr_handler - the time for blocked content updates is over now:
+- * Check for throttled data and send it to the userspace
++ * bcm_rx_thr_flush - Check for throttled data and send it to the userspace
+ */
+-static void bcm_rx_thr_handler(unsigned long data)
++static int bcm_rx_thr_flush(struct bcm_op *op)
+ {
+- struct bcm_op *op = (struct bcm_op *)data;
+- int i = 0;
+-
+- /* mark disabled / consumed timer */
+- op->thrtimer.expires = 0;
++ int updated = 0;
+
+ if (op->nframes > 1) {
++ int i;
++
+ /* for MUX filter we start at index 1 */
+ for (i = 1; i < op->nframes; i++) {
+ if ((op->last_frames) &&
+ (op->last_frames[i].can_dlc & RX_THR)) {
+ op->last_frames[i].can_dlc &= ~RX_THR;
+ bcm_rx_changed(op, &op->last_frames[i]);
++ updated++;
+ }
+ }
+
+@@ -577,8 +570,29 @@ static void bcm_rx_thr_handler(unsigned long data)
+ if (op->last_frames && (op->last_frames[0].can_dlc & RX_THR)) {
+ op->last_frames[0].can_dlc &= ~RX_THR;
+ bcm_rx_changed(op, &op->last_frames[0]);
++ updated++;
+ }
+ }
++
++ return updated;
++}
++
++/*
++ * bcm_rx_thr_handler - the time for blocked content updates is over now:
++ * Check for throttled data and send it to the userspace
++ */
++static enum hrtimer_restart bcm_rx_thr_handler(struct hrtimer *hrtimer)
++{
++ struct bcm_op *op = container_of(hrtimer, struct bcm_op, thrtimer);
++
++ if (bcm_rx_thr_flush(op)) {
++ hrtimer_forward(hrtimer, ktime_get(), op->kt_ival2);
++ return HRTIMER_RESTART;
++ } else {
++ /* rearm throttle handling */
++ op->kt_lastmsg = ktime_set(0, 0);
++ return HRTIMER_NORESTART;
++ }
+ }
+
+ /*
+@@ -591,7 +605,7 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)
+ int i;
+
+ /* disable timeout */
+- del_timer(&op->timer);
++ hrtimer_cancel(&op->timer);
+
+ if (skb->len == sizeof(rxframe)) {
+ memcpy(&rxframe, skb->data, sizeof(rxframe));
+@@ -669,8 +683,8 @@ static struct bcm_op *bcm_find_op(struct list_head *ops, canid_t can_id,
+
+ static void bcm_remove_op(struct bcm_op *op)
+ {
+- del_timer(&op->timer);
+- del_timer(&op->thrtimer);
++ hrtimer_cancel(&op->timer);
++ hrtimer_cancel(&op->thrtimer);
+
+ if ((op->frames) && (op->frames != &op->sframe))
+ kfree(op->frames);
+@@ -871,11 +885,11 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
+ op->ifindex = ifindex;
+
+ /* initialize uninitialized (kzalloc) structure */
+- setup_timer(&op->timer, bcm_tx_timeout_handler,
+- (unsigned long)op);
++ hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
++ op->timer.function = bcm_tx_timeout_handler;
+
+ /* currently unused in tx_ops */
+- init_timer(&op->thrtimer);
++ hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+
+ /* add this bcm_op to the list of the tx_ops */
+ list_add(&op->list, &bo->tx_ops);
+@@ -902,25 +916,27 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
+ op->count = msg_head->count;
+ op->ival1 = msg_head->ival1;
+ op->ival2 = msg_head->ival2;
+- op->j_ival1 = rounded_tv2jif(&msg_head->ival1);
+- op->j_ival2 = rounded_tv2jif(&msg_head->ival2);
++ op->kt_ival1 = timeval_to_ktime(msg_head->ival1);
++ op->kt_ival2 = timeval_to_ktime(msg_head->ival2);
+
+ /* disable an active timer due to zero values? */
+- if (!op->j_ival1 && !op->j_ival2)
+- del_timer(&op->timer);
++ if (!op->kt_ival1.tv64 && !op->kt_ival2.tv64)
++ hrtimer_cancel(&op->timer);
+ }
+
+ if ((op->flags & STARTTIMER) &&
+- ((op->j_ival1 && op->count) || op->j_ival2)) {
++ ((op->kt_ival1.tv64 && op->count) || op->kt_ival2.tv64)) {
+
+ /* spec: send can_frame when starting timer */
+ op->flags |= TX_ANNOUNCE;
+
+- if (op->j_ival1 && (op->count > 0)) {
++ if (op->kt_ival1.tv64 && (op->count > 0)) {
+ /* op->count-- is done in bcm_tx_timeout_handler */
+- mod_timer(&op->timer, jiffies + op->j_ival1);
++ hrtimer_start(&op->timer, op->kt_ival1,
++ HRTIMER_MODE_REL);
+ } else
+- mod_timer(&op->timer, jiffies + op->j_ival2);
++ hrtimer_start(&op->timer, op->kt_ival2,
++ HRTIMER_MODE_REL);
+ }
+
+ if (op->flags & TX_ANNOUNCE)
+@@ -1032,15 +1048,11 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
+ op->ifindex = ifindex;
+
+ /* initialize uninitialized (kzalloc) structure */
+- setup_timer(&op->timer, bcm_rx_timeout_handler,
+- (unsigned long)op);
++ hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
++ op->timer.function = bcm_rx_timeout_handler;
+
+- /* init throttle timer for RX_CHANGED */
+- setup_timer(&op->thrtimer, bcm_rx_thr_handler,
+- (unsigned long)op);
+-
+- /* mark disabled timer */
+- op->thrtimer.expires = 0;
++ hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
++ op->thrtimer.function = bcm_rx_thr_handler;
+
+ /* add this bcm_op to the list of the rx_ops */
+ list_add(&op->list, &bo->rx_ops);
+@@ -1056,8 +1068,8 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
+ if (op->flags & RX_RTR_FRAME) {
+
+ /* no timers in RTR-mode */
+- del_timer(&op->thrtimer);
+- del_timer(&op->timer);
++ hrtimer_cancel(&op->thrtimer);
++ hrtimer_cancel(&op->timer);
+
+ /*
+ * funny feature in RX(!)_SETUP only for RTR-mode:
+@@ -1074,28 +1086,25 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
+ /* set timer value */
+ op->ival1 = msg_head->ival1;
+ op->ival2 = msg_head->ival2;
+- op->j_ival1 = rounded_tv2jif(&msg_head->ival1);
+- op->j_ival2 = rounded_tv2jif(&msg_head->ival2);
++ op->kt_ival1 = timeval_to_ktime(msg_head->ival1);
++ op->kt_ival2 = timeval_to_ktime(msg_head->ival2);
+
+ /* disable an active timer due to zero value? */
+- if (!op->j_ival1)
+- del_timer(&op->timer);
+-
+- /* free currently blocked msgs ? */
+- if (op->thrtimer.expires) {
+- /* send blocked msgs hereafter */
+- mod_timer(&op->thrtimer, jiffies + 2);
+- }
++ if (!op->kt_ival1.tv64)
++ hrtimer_cancel(&op->timer);
+
+ /*
+- * if (op->j_ival2) is zero, no (new) throttling
+- * will happen. For details see functions
+- * bcm_rx_update_and_send() and bcm_rx_thr_handler()
++ * In any case cancel the throttle timer, flush
++ * potentially blocked msgs and reset throttle handling
+ */
++ op->kt_lastmsg = ktime_set(0, 0);
++ hrtimer_cancel(&op->thrtimer);
++ bcm_rx_thr_flush(op);
+ }
+
+- if ((op->flags & STARTTIMER) && op->j_ival1)
+- mod_timer(&op->timer, jiffies + op->j_ival1);
++ if ((op->flags & STARTTIMER) && op->kt_ival1.tv64)
++ hrtimer_start(&op->timer, op->kt_ival1,
++ HRTIMER_MODE_REL);
+ }
+
+ /* now we can register for can_ids, if we added a new bcm_op */
+@@ -1285,7 +1294,7 @@ static int bcm_notifier(struct notifier_block *nb, unsigned long msg,
+ struct bcm_op *op;
+ int notify_enodev = 0;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ if (dev->type != ARPHRD_CAN)
+diff --git a/net/can/raw.c b/net/can/raw.c
+index 94cd7f2..201cbfc 100644
+--- a/net/can/raw.c
++++ b/net/can/raw.c
+@@ -210,7 +210,7 @@ static int raw_notifier(struct notifier_block *nb,
+ struct raw_sock *ro = container_of(nb, struct raw_sock, notifier);
+ struct sock *sk = &ro->sk;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ if (dev->type != ARPHRD_CAN)
+@@ -573,7 +573,8 @@ static int raw_getsockopt(struct socket *sock, int level, int optname,
+ int fsize = ro->count * sizeof(struct can_filter);
+ if (len > fsize)
+ len = fsize;
+- err = copy_to_user(optval, ro->filter, len);
++ if (copy_to_user(optval, ro->filter, len))
++ err = -EFAULT;
+ } else
+ len = 0;
+ release_sock(sk);
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 460e7f9..e1df1ab 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -216,7 +216,7 @@ static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex)
+ /* Device list insertion */
+ static int list_netdevice(struct net_device *dev)
+ {
+- struct net *net = dev->nd_net;
++ struct net *net = dev_net(dev);
+
+ ASSERT_RTNL();
+
+@@ -852,8 +852,8 @@ int dev_alloc_name(struct net_device *dev, const char *name)
+ struct net *net;
+ int ret;
+
+- BUG_ON(!dev->nd_net);
+- net = dev->nd_net;
++ BUG_ON(!dev_net(dev));
++ net = dev_net(dev);
+ ret = __dev_alloc_name(net, name, buf);
+ if (ret >= 0)
+ strlcpy(dev->name, buf, IFNAMSIZ);
+@@ -877,9 +877,9 @@ int dev_change_name(struct net_device *dev, char *newname)
+ struct net *net;
+
+ ASSERT_RTNL();
+- BUG_ON(!dev->nd_net);
++ BUG_ON(!dev_net(dev));
+
+- net = dev->nd_net;
++ net = dev_net(dev);
+ if (dev->flags & IFF_UP)
+ return -EBUSY;
+
+@@ -2615,7 +2615,7 @@ static int ptype_seq_show(struct seq_file *seq, void *v)
+
+ if (v == SEQ_START_TOKEN)
+ seq_puts(seq, "Type Device Function\n");
+- else {
++ else if (pt->dev == NULL || dev_net(pt->dev) == seq_file_net(seq)) {
+ if (pt->type == htons(ETH_P_ALL))
+ seq_puts(seq, "ALL ");
+ else
+@@ -2639,7 +2639,8 @@ static const struct seq_operations ptype_seq_ops = {
+
+ static int ptype_seq_open(struct inode *inode, struct file *file)
+ {
+- return seq_open(file, &ptype_seq_ops);
++ return seq_open_net(inode, file, &ptype_seq_ops,
++ sizeof(struct seq_net_private));
+ }
+
+ static const struct file_operations ptype_seq_fops = {
+@@ -2647,7 +2648,7 @@ static const struct file_operations ptype_seq_fops = {
+ .open = ptype_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = seq_release,
++ .release = seq_release_net,
+ };
+
+
+@@ -3688,8 +3689,8 @@ int register_netdevice(struct net_device *dev)
+
+ /* When net_device's are persistent, this will be fatal. */
+ BUG_ON(dev->reg_state != NETREG_UNINITIALIZED);
+- BUG_ON(!dev->nd_net);
+- net = dev->nd_net;
++ BUG_ON(!dev_net(dev));
++ net = dev_net(dev);
+
+ spin_lock_init(&dev->queue_lock);
+ spin_lock_init(&dev->_xmit_lock);
+@@ -3995,11 +3996,15 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
+
+ BUG_ON(strlen(name) >= sizeof(dev->name));
+
+- /* ensure 32-byte alignment of both the device and private area */
+- alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST +
+- (sizeof(struct net_device_subqueue) * (queue_count - 1))) &
+- ~NETDEV_ALIGN_CONST;
+- alloc_size += sizeof_priv + NETDEV_ALIGN_CONST;
++ alloc_size = sizeof(struct net_device) +
++ sizeof(struct net_device_subqueue) * (queue_count - 1);
++ if (sizeof_priv) {
++ /* ensure 32-byte alignment of private area */
++ alloc_size = (alloc_size + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST;
++ alloc_size += sizeof_priv;
++ }
++ /* ensure 32-byte alignment of whole construct */
++ alloc_size += NETDEV_ALIGN_CONST;
+
+ p = kzalloc(alloc_size, GFP_KERNEL);
+ if (!p) {
+@@ -4010,7 +4015,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
+ dev = (struct net_device *)
+ (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
+ dev->padded = (char *)dev - (char *)p;
+- dev->nd_net = &init_net;
++ dev_net_set(dev, &init_net);
+
+ if (sizeof_priv) {
+ dev->priv = ((char *)dev +
+@@ -4021,6 +4026,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
+ }
+
+ dev->egress_subqueue_count = queue_count;
++ dev->gso_max_size = GSO_MAX_SIZE;
+
+ dev->get_stats = internal_stats;
+ netpoll_netdev_init(dev);
+@@ -4040,6 +4046,8 @@ EXPORT_SYMBOL(alloc_netdev_mq);
+ */
+ void free_netdev(struct net_device *dev)
+ {
++ release_net(dev_net(dev));
++
+ /* Compatibility with error handling in drivers */
+ if (dev->reg_state == NETREG_UNINITIALIZED) {
+ kfree((char *)dev - dev->padded);
+@@ -4134,7 +4142,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
+
+ /* Get out if there is nothing todo */
+ err = 0;
+- if (dev->nd_net == net)
++ if (net_eq(dev_net(dev), net))
+ goto out;
+
+ /* Pick the destination device name, and ensure
+@@ -4185,7 +4193,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
+ dev_addr_discard(dev);
+
+ /* Actually switch the network namespace */
+- dev->nd_net = net;
++ dev_net_set(dev, net);
+
+ /* Assign the new device name */
+ if (destname != dev->name)
+diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c
+index cec5825..f8a3455 100644
+--- a/net/core/dev_mcast.c
++++ b/net/core/dev_mcast.c
+@@ -156,39 +156,14 @@ void dev_mc_unsync(struct net_device *to, struct net_device *from)
+ EXPORT_SYMBOL(dev_mc_unsync);
+
+ #ifdef CONFIG_PROC_FS
+-static void *dev_mc_seq_start(struct seq_file *seq, loff_t *pos)
+- __acquires(dev_base_lock)
+-{
+- struct net *net = seq_file_net(seq);
+- struct net_device *dev;
+- loff_t off = 0;
+-
+- read_lock(&dev_base_lock);
+- for_each_netdev(net, dev) {
+- if (off++ == *pos)
+- return dev;
+- }
+- return NULL;
+-}
+-
+-static void *dev_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+-{
+- ++*pos;
+- return next_net_device((struct net_device *)v);
+-}
+-
+-static void dev_mc_seq_stop(struct seq_file *seq, void *v)
+- __releases(dev_base_lock)
+-{
+- read_unlock(&dev_base_lock);
+-}
+-
+-
+ static int dev_mc_seq_show(struct seq_file *seq, void *v)
+ {
+ struct dev_addr_list *m;
+ struct net_device *dev = v;
+
++ if (v == SEQ_START_TOKEN)
++ return 0;
++
+ netif_tx_lock_bh(dev);
+ for (m = dev->mc_list; m; m = m->next) {
+ int i;
+@@ -206,9 +181,9 @@ static int dev_mc_seq_show(struct seq_file *seq, void *v)
+ }
+
+ static const struct seq_operations dev_mc_seq_ops = {
+- .start = dev_mc_seq_start,
+- .next = dev_mc_seq_next,
+- .stop = dev_mc_seq_stop,
++ .start = dev_seq_start,
++ .next = dev_seq_next,
++ .stop = dev_seq_stop,
+ .show = dev_mc_seq_show,
+ };
+
+diff --git a/net/core/dst.c b/net/core/dst.c
+index 7deef48..fe03266 100644
+--- a/net/core/dst.c
++++ b/net/core/dst.c
+@@ -259,6 +259,16 @@ again:
+ return NULL;
+ }
+
++void dst_release(struct dst_entry *dst)
++{
++ if (dst) {
++ WARN_ON(atomic_read(&dst->__refcnt) < 1);
++ smp_mb__before_atomic_dec();
++ atomic_dec(&dst->__refcnt);
++ }
++}
++EXPORT_SYMBOL(dst_release);
++
+ /* Dirty hack. We did it in 2.2 (in __dst_free),
+ * we have _very_ good reasons not to repeat
+ * this mistake in 2.3, but we have no choice
+@@ -279,7 +289,7 @@ static inline void dst_ifdown(struct dst_entry *dst, struct net_device *dev,
+ if (!unregister) {
+ dst->input = dst->output = dst_discard;
+ } else {
+- dst->dev = dst->dev->nd_net->loopback_dev;
++ dst->dev = dev_net(dst->dev)->loopback_dev;
+ dev_hold(dst->dev);
+ dev_put(dev);
+ if (dst->neighbour && dst->neighbour->dev == dev) {
+@@ -295,9 +305,6 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, void
+ struct net_device *dev = ptr;
+ struct dst_entry *dst, *last = NULL;
+
+- if (dev->nd_net != &init_net)
+- return NOTIFY_DONE;
+-
+ switch (event) {
+ case NETDEV_UNREGISTER:
+ case NETDEV_DOWN:
+diff --git a/net/core/ethtool.c b/net/core/ethtool.c
+index 1163eb2..0133b5e 100644
+--- a/net/core/ethtool.c
++++ b/net/core/ethtool.c
+@@ -284,8 +284,10 @@ static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr)
+ {
+ struct ethtool_eeprom eeprom;
+ const struct ethtool_ops *ops = dev->ethtool_ops;
++ void __user *userbuf = useraddr + sizeof(eeprom);
++ u32 bytes_remaining;
+ u8 *data;
+- int ret;
++ int ret = 0;
+
+ if (!ops->get_eeprom || !ops->get_eeprom_len)
+ return -EOPNOTSUPP;
+@@ -301,26 +303,31 @@ static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr)
+ if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev))
+ return -EINVAL;
+
+- data = kmalloc(eeprom.len, GFP_USER);
++ data = kmalloc(PAGE_SIZE, GFP_USER);
+ if (!data)
+ return -ENOMEM;
+
+- ret = -EFAULT;
+- if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len))
+- goto out;
++ bytes_remaining = eeprom.len;
++ while (bytes_remaining > 0) {
++ eeprom.len = min(bytes_remaining, (u32)PAGE_SIZE);
+
+- ret = ops->get_eeprom(dev, &eeprom, data);
+- if (ret)
+- goto out;
++ ret = ops->get_eeprom(dev, &eeprom, data);
++ if (ret)
++ break;
++ if (copy_to_user(userbuf, data, eeprom.len)) {
++ ret = -EFAULT;
++ break;
++ }
++ userbuf += eeprom.len;
++ eeprom.offset += eeprom.len;
++ bytes_remaining -= eeprom.len;
++ }
+
+- ret = -EFAULT;
++ eeprom.len = userbuf - (useraddr + sizeof(eeprom));
++ eeprom.offset -= eeprom.len;
+ if (copy_to_user(useraddr, &eeprom, sizeof(eeprom)))
+- goto out;
+- if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len))
+- goto out;
+- ret = 0;
++ ret = -EFAULT;
+
+- out:
+ kfree(data);
+ return ret;
+ }
+@@ -329,8 +336,10 @@ static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr)
+ {
+ struct ethtool_eeprom eeprom;
+ const struct ethtool_ops *ops = dev->ethtool_ops;
++ void __user *userbuf = useraddr + sizeof(eeprom);
++ u32 bytes_remaining;
+ u8 *data;
+- int ret;
++ int ret = 0;
+
+ if (!ops->set_eeprom || !ops->get_eeprom_len)
+ return -EOPNOTSUPP;
+@@ -346,22 +355,26 @@ static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr)
+ if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev))
+ return -EINVAL;
+
+- data = kmalloc(eeprom.len, GFP_USER);
++ data = kmalloc(PAGE_SIZE, GFP_USER);
+ if (!data)
+ return -ENOMEM;
+
+- ret = -EFAULT;
+- if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len))
+- goto out;
+-
+- ret = ops->set_eeprom(dev, &eeprom, data);
+- if (ret)
+- goto out;
++ bytes_remaining = eeprom.len;
++ while (bytes_remaining > 0) {
++ eeprom.len = min(bytes_remaining, (u32)PAGE_SIZE);
+
+- if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len))
+- ret = -EFAULT;
++ if (copy_from_user(data, userbuf, eeprom.len)) {
++ ret = -EFAULT;
++ break;
++ }
++ ret = ops->set_eeprom(dev, &eeprom, data);
++ if (ret)
++ break;
++ userbuf += eeprom.len;
++ eeprom.offset += eeprom.len;
++ bytes_remaining -= eeprom.len;
++ }
+
+- out:
+ kfree(data);
+ return ret;
+ }
+diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
+index 42ccaf5..e3e9ab0 100644
+--- a/net/core/fib_rules.c
++++ b/net/core/fib_rules.c
+@@ -29,7 +29,7 @@ int fib_default_rule_add(struct fib_rules_ops *ops,
+ r->pref = pref;
+ r->table = table;
+ r->flags = flags;
+- r->fr_net = ops->fro_net;
++ r->fr_net = hold_net(ops->fro_net);
+
+ /* The lock is not required here, the list in unreacheable
+ * at the moment this function is called */
+@@ -214,7 +214,7 @@ errout:
+
+ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct fib_rule_hdr *frh = nlmsg_data(nlh);
+ struct fib_rules_ops *ops = NULL;
+ struct fib_rule *rule, *r, *last = NULL;
+@@ -243,7 +243,7 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+ err = -ENOMEM;
+ goto errout;
+ }
+- rule->fr_net = net;
++ rule->fr_net = hold_net(net);
+
+ if (tb[FRA_PRIORITY])
+ rule->pref = nla_get_u32(tb[FRA_PRIORITY]);
+@@ -344,6 +344,7 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+ return 0;
+
+ errout_free:
++ release_net(rule->fr_net);
+ kfree(rule);
+ errout:
+ rules_ops_put(ops);
+@@ -352,7 +353,7 @@ errout:
+
+ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct fib_rule_hdr *frh = nlmsg_data(nlh);
+ struct fib_rules_ops *ops = NULL;
+ struct fib_rule *rule, *tmp;
+@@ -534,7 +535,7 @@ skip:
+
+ static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct fib_rules_ops *ops;
+ int idx = 0, family;
+
+@@ -618,7 +619,7 @@ static int fib_rules_event(struct notifier_block *this, unsigned long event,
+ void *ptr)
+ {
+ struct net_device *dev = ptr;
+- struct net *net = dev->nd_net;
++ struct net *net = dev_net(dev);
+ struct fib_rules_ops *ops;
+
+ ASSERT_RTNL();
+diff --git a/net/core/filter.c b/net/core/filter.c
+index e0a0694..f5f3cf6 100644
+--- a/net/core/filter.c
++++ b/net/core/filter.c
+@@ -27,6 +27,7 @@
+ #include <linux/if_packet.h>
+ #include <net/ip.h>
+ #include <net/protocol.h>
++#include <net/netlink.h>
+ #include <linux/skbuff.h>
+ #include <net/sock.h>
+ #include <linux/errno.h>
+@@ -64,6 +65,41 @@ static inline void *load_pointer(struct sk_buff *skb, int k,
+ }
+
+ /**
++ * sk_filter - run a packet through a socket filter
++ * @sk: sock associated with &sk_buff
++ * @skb: buffer to filter
++ * @needlock: set to 1 if the sock is not locked by caller.
++ *
++ * Run the filter code and then cut skb->data to correct size returned by
++ * sk_run_filter. If pkt_len is 0 we toss packet. If skb->len is smaller
++ * than pkt_len we keep whole skb->data. This is the socket level
++ * wrapper to sk_run_filter. It returns 0 if the packet should
++ * be accepted or -EPERM if the packet should be tossed.
++ *
++ */
++int sk_filter(struct sock *sk, struct sk_buff *skb)
++{
++ int err;
++ struct sk_filter *filter;
++
++ err = security_sock_rcv_skb(sk, skb);
++ if (err)
++ return err;
++
++ rcu_read_lock_bh();
++ filter = rcu_dereference(sk->sk_filter);
++ if (filter) {
++ unsigned int pkt_len = sk_run_filter(skb, filter->insns,
++ filter->len);
++ err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM;
++ }
++ rcu_read_unlock_bh();
++
++ return err;
++}
++EXPORT_SYMBOL(sk_filter);
++
++/**
+ * sk_run_filter - run a filter on a socket
+ * @skb: buffer to run the filter on
+ * @filter: filter to apply
+@@ -268,6 +304,22 @@ load_b:
+ case SKF_AD_IFINDEX:
+ A = skb->dev->ifindex;
+ continue;
++ case SKF_AD_NLATTR: {
++ struct nlattr *nla;
++
++ if (skb_is_nonlinear(skb))
++ return 0;
++ if (A > skb->len - sizeof(struct nlattr))
++ return 0;
++
++ nla = nla_find((struct nlattr *)&skb->data[A],
++ skb->len - A, X);
++ if (nla)
++ A = (void *)nla - (void *)skb->data;
++ else
++ A = 0;
++ continue;
++ }
+ default:
+ return 0;
+ }
+@@ -275,6 +327,7 @@ load_b:
+
+ return 0;
+ }
++EXPORT_SYMBOL(sk_run_filter);
+
+ /**
+ * sk_chk_filter - verify socket filter code
+@@ -385,6 +438,7 @@ int sk_chk_filter(struct sock_filter *filter, int flen)
+
+ return (BPF_CLASS(filter[flen - 1].code) == BPF_RET) ? 0 : -EINVAL;
+ }
++EXPORT_SYMBOL(sk_chk_filter);
+
+ /**
+ * sk_filter_rcu_release: Release a socket filter by rcu_head
+@@ -467,6 +521,3 @@ int sk_detach_filter(struct sock *sk)
+ rcu_read_unlock_bh();
+ return ret;
+ }
+-
+-EXPORT_SYMBOL(sk_chk_filter);
+-EXPORT_SYMBOL(sk_run_filter);
+diff --git a/net/core/flow.c b/net/core/flow.c
+index a77531c..1999117 100644
+--- a/net/core/flow.c
++++ b/net/core/flow.c
+@@ -23,7 +23,6 @@
+ #include <linux/mutex.h>
+ #include <net/flow.h>
+ #include <asm/atomic.h>
+-#include <asm/semaphore.h>
+ #include <linux/security.h>
+
+ struct flow_cache_entry {
+diff --git a/net/core/neighbour.c b/net/core/neighbour.c
+index 19b8e00..75075c3 100644
+--- a/net/core/neighbour.c
++++ b/net/core/neighbour.c
+@@ -123,6 +123,7 @@ unsigned long neigh_rand_reach_time(unsigned long base)
+ {
+ return (base ? (net_random() % base) + (base >> 1) : 0);
+ }
++EXPORT_SYMBOL(neigh_rand_reach_time);
+
+
+ static int neigh_forced_gc(struct neigh_table *tbl)
+@@ -241,6 +242,7 @@ void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev)
+ neigh_flush_dev(tbl, dev);
+ write_unlock_bh(&tbl->lock);
+ }
++EXPORT_SYMBOL(neigh_changeaddr);
+
+ int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
+ {
+@@ -253,6 +255,7 @@ int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
+ pneigh_queue_purge(&tbl->proxy_queue);
+ return 0;
+ }
++EXPORT_SYMBOL(neigh_ifdown);
+
+ static struct neighbour *neigh_alloc(struct neigh_table *tbl)
+ {
+@@ -374,6 +377,7 @@ struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
+ read_unlock_bh(&tbl->lock);
+ return n;
+ }
++EXPORT_SYMBOL(neigh_lookup);
+
+ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
+ const void *pkey)
+@@ -388,7 +392,7 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
+ hash_val = tbl->hash(pkey, NULL);
+ for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) {
+ if (!memcmp(n->primary_key, pkey, key_len) &&
+- (net == n->dev->nd_net)) {
++ net_eq(dev_net(n->dev), net)) {
+ neigh_hold(n);
+ NEIGH_CACHE_STAT_INC(tbl, hits);
+ break;
+@@ -397,6 +401,7 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
+ read_unlock_bh(&tbl->lock);
+ return n;
+ }
++EXPORT_SYMBOL(neigh_lookup_nodev);
+
+ struct neighbour *neigh_create(struct neigh_table *tbl, const void *pkey,
+ struct net_device *dev)
+@@ -465,28 +470,44 @@ out_neigh_release:
+ neigh_release(n);
+ goto out;
+ }
++EXPORT_SYMBOL(neigh_create);
+
+-struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
+- struct net *net, const void *pkey, struct net_device *dev)
++static u32 pneigh_hash(const void *pkey, int key_len)
+ {
+- struct pneigh_entry *n;
+- int key_len = tbl->key_len;
+ u32 hash_val = *(u32 *)(pkey + key_len - 4);
+-
+ hash_val ^= (hash_val >> 16);
+ hash_val ^= hash_val >> 8;
+ hash_val ^= hash_val >> 4;
+ hash_val &= PNEIGH_HASHMASK;
++ return hash_val;
++}
+
+- for (n = tbl->phash_buckets[hash_val]; n; n = n->next) {
++static struct pneigh_entry *__pneigh_lookup_1(struct pneigh_entry *n,
++ struct net *net,
++ const void *pkey,
++ int key_len,
++ struct net_device *dev)
++{
++ while (n) {
+ if (!memcmp(n->key, pkey, key_len) &&
+- (n->net == net) &&
++ net_eq(pneigh_net(n), net) &&
+ (n->dev == dev || !n->dev))
+- break;
++ return n;
++ n = n->next;
+ }
++ return NULL;
++}
+
+- return n;
++struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
++ struct net *net, const void *pkey, struct net_device *dev)
++{
++ int key_len = tbl->key_len;
++ u32 hash_val = pneigh_hash(pkey, key_len);
++
++ return __pneigh_lookup_1(tbl->phash_buckets[hash_val],
++ net, pkey, key_len, dev);
+ }
++EXPORT_SYMBOL_GPL(__pneigh_lookup);
+
+ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
+ struct net *net, const void *pkey,
+@@ -494,26 +515,14 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
+ {
+ struct pneigh_entry *n;
+ int key_len = tbl->key_len;
+- u32 hash_val = *(u32 *)(pkey + key_len - 4);
+-
+- hash_val ^= (hash_val >> 16);
+- hash_val ^= hash_val >> 8;
+- hash_val ^= hash_val >> 4;
+- hash_val &= PNEIGH_HASHMASK;
++ u32 hash_val = pneigh_hash(pkey, key_len);
+
+ read_lock_bh(&tbl->lock);
+-
+- for (n = tbl->phash_buckets[hash_val]; n; n = n->next) {
+- if (!memcmp(n->key, pkey, key_len) &&
+- (n->net == net) &&
+- (n->dev == dev || !n->dev)) {
+- read_unlock_bh(&tbl->lock);
+- goto out;
+- }
+- }
++ n = __pneigh_lookup_1(tbl->phash_buckets[hash_val],
++ net, pkey, key_len, dev);
+ read_unlock_bh(&tbl->lock);
+- n = NULL;
+- if (!creat)
++
++ if (n || !creat)
+ goto out;
+
+ ASSERT_RTNL();
+@@ -522,7 +531,9 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
+ if (!n)
+ goto out;
+
++#ifdef CONFIG_NET_NS
+ n->net = hold_net(net);
++#endif
+ memcpy(n->key, pkey, key_len);
+ n->dev = dev;
+ if (dev)
+@@ -544,6 +555,7 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
+ out:
+ return n;
+ }
++EXPORT_SYMBOL(pneigh_lookup);
+
+
+ int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
+@@ -551,25 +563,20 @@ int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
+ {
+ struct pneigh_entry *n, **np;
+ int key_len = tbl->key_len;
+- u32 hash_val = *(u32 *)(pkey + key_len - 4);
+-
+- hash_val ^= (hash_val >> 16);
+- hash_val ^= hash_val >> 8;
+- hash_val ^= hash_val >> 4;
+- hash_val &= PNEIGH_HASHMASK;
++ u32 hash_val = pneigh_hash(pkey, key_len);
+
+ write_lock_bh(&tbl->lock);
+ for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
+ np = &n->next) {
+ if (!memcmp(n->key, pkey, key_len) && n->dev == dev &&
+- (n->net == net)) {
++ net_eq(pneigh_net(n), net)) {
+ *np = n->next;
+ write_unlock_bh(&tbl->lock);
+ if (tbl->pdestructor)
+ tbl->pdestructor(n);
+ if (n->dev)
+ dev_put(n->dev);
+- release_net(n->net);
++ release_net(pneigh_net(n));
+ kfree(n);
+ return 0;
+ }
+@@ -592,7 +599,7 @@ static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
+ tbl->pdestructor(n);
+ if (n->dev)
+ dev_put(n->dev);
+- release_net(n->net);
++ release_net(pneigh_net(n));
+ kfree(n);
+ continue;
+ }
+@@ -651,6 +658,7 @@ void neigh_destroy(struct neighbour *neigh)
+ atomic_dec(&neigh->tbl->entries);
+ kmem_cache_free(neigh->tbl->kmem_cachep, neigh);
+ }
++EXPORT_SYMBOL(neigh_destroy);
+
+ /* Neighbour state is suspicious;
+ disable fast path.
+@@ -931,6 +939,7 @@ out_unlock_bh:
+ write_unlock_bh(&neigh->lock);
+ return rc;
+ }
++EXPORT_SYMBOL(__neigh_event_send);
+
+ static void neigh_update_hhs(struct neighbour *neigh)
+ {
+@@ -1103,6 +1112,7 @@ out:
+
+ return err;
+ }
++EXPORT_SYMBOL(neigh_update);
+
+ struct neighbour *neigh_event_ns(struct neigh_table *tbl,
+ u8 *lladdr, void *saddr,
+@@ -1115,6 +1125,7 @@ struct neighbour *neigh_event_ns(struct neigh_table *tbl,
+ NEIGH_UPDATE_F_OVERRIDE);
+ return neigh;
+ }
++EXPORT_SYMBOL(neigh_event_ns);
+
+ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
+ __be16 protocol)
+@@ -1169,6 +1180,7 @@ int neigh_compat_output(struct sk_buff *skb)
+
+ return dev_queue_xmit(skb);
+ }
++EXPORT_SYMBOL(neigh_compat_output);
+
+ /* Slow and careful. */
+
+@@ -1214,6 +1226,7 @@ out_kfree_skb:
+ kfree_skb(skb);
+ goto out;
+ }
++EXPORT_SYMBOL(neigh_resolve_output);
+
+ /* As fast as possible without hh cache */
+
+@@ -1238,6 +1251,7 @@ int neigh_connected_output(struct sk_buff *skb)
+ }
+ return err;
+ }
++EXPORT_SYMBOL(neigh_connected_output);
+
+ static void neigh_proxy_process(unsigned long arg)
+ {
+@@ -1299,6 +1313,7 @@ void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
+ mod_timer(&tbl->proxy_timer, sched_next);
+ spin_unlock(&tbl->proxy_queue.lock);
+ }
++EXPORT_SYMBOL(pneigh_enqueue);
+
+ static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
+ struct net *net, int ifindex)
+@@ -1306,9 +1321,7 @@ static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
+ struct neigh_parms *p;
+
+ for (p = &tbl->parms; p; p = p->next) {
+- if (p->net != net)
+- continue;
+- if ((p->dev && p->dev->ifindex == ifindex) ||
++ if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
+ (!p->dev && !ifindex))
+ return p;
+ }
+@@ -1322,7 +1335,7 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
+ struct neigh_parms *p, *ref;
+ struct net *net;
+
+- net = dev->nd_net;
++ net = dev_net(dev);
+ ref = lookup_neigh_params(tbl, net, 0);
+ if (!ref)
+ return NULL;
+@@ -1342,7 +1355,9 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
+
+ dev_hold(dev);
+ p->dev = dev;
++#ifdef CONFIG_NET_NS
+ p->net = hold_net(net);
++#endif
+ p->sysctl_table = NULL;
+ write_lock_bh(&tbl->lock);
+ p->next = tbl->parms.next;
+@@ -1351,6 +1366,7 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
+ }
+ return p;
+ }
++EXPORT_SYMBOL(neigh_parms_alloc);
+
+ static void neigh_rcu_free_parms(struct rcu_head *head)
+ {
+@@ -1381,10 +1397,11 @@ void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
+ write_unlock_bh(&tbl->lock);
+ NEIGH_PRINTK1("neigh_parms_release: not found\n");
+ }
++EXPORT_SYMBOL(neigh_parms_release);
+
+ static void neigh_parms_destroy(struct neigh_parms *parms)
+ {
+- release_net(parms->net);
++ release_net(neigh_parms_net(parms));
+ kfree(parms);
+ }
+
+@@ -1395,7 +1412,9 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl)
+ unsigned long now = jiffies;
+ unsigned long phsize;
+
++#ifdef CONFIG_NET_NS
+ tbl->parms.net = &init_net;
++#endif
+ atomic_set(&tbl->parms.refcnt, 1);
+ INIT_RCU_HEAD(&tbl->parms.rcu_head);
+ tbl->parms.reachable_time =
+@@ -1441,6 +1460,7 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl)
+ tbl->last_flush = now;
+ tbl->last_rand = now + tbl->parms.reachable_time * 20;
+ }
++EXPORT_SYMBOL(neigh_table_init_no_netlink);
+
+ void neigh_table_init(struct neigh_table *tbl)
+ {
+@@ -1462,6 +1482,7 @@ void neigh_table_init(struct neigh_table *tbl)
+ dump_stack();
+ }
+ }
++EXPORT_SYMBOL(neigh_table_init);
+
+ int neigh_table_clear(struct neigh_table *tbl)
+ {
+@@ -1499,10 +1520,11 @@ int neigh_table_clear(struct neigh_table *tbl)
+
+ return 0;
+ }
++EXPORT_SYMBOL(neigh_table_clear);
+
+ static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct ndmsg *ndm;
+ struct nlattr *dst_attr;
+ struct neigh_table *tbl;
+@@ -1568,7 +1590,7 @@ out:
+
+ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct ndmsg *ndm;
+ struct nlattr *tb[NDA_MAX+1];
+ struct neigh_table *tbl;
+@@ -1836,7 +1858,7 @@ static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
+
+ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct neigh_table *tbl;
+ struct ndtmsg *ndtmsg;
+ struct nlattr *tb[NDTA_MAX+1];
+@@ -1961,7 +1983,7 @@ errout:
+
+ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ int family, tidx, nidx = 0;
+ int tbl_skip = cb->args[0];
+ int neigh_skip = cb->args[1];
+@@ -1982,7 +2004,7 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
+ break;
+
+ for (nidx = 0, p = tbl->parms.next; p; p = p->next) {
+- if (net != p->net)
++ if (!net_eq(neigh_parms_net(p), net))
+ continue;
+
+ if (nidx++ < neigh_skip)
+@@ -2061,7 +2083,7 @@ static void neigh_update_notify(struct neighbour *neigh)
+ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
+ struct netlink_callback *cb)
+ {
+- struct net * net = skb->sk->sk_net;
++ struct net * net = sock_net(skb->sk);
+ struct neighbour *n;
+ int rc, h, s_h = cb->args[1];
+ int idx, s_idx = idx = cb->args[2];
+@@ -2074,7 +2096,7 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
+ s_idx = 0;
+ for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next) {
+ int lidx;
+- if (n->dev->nd_net != net)
++ if (dev_net(n->dev) != net)
+ continue;
+ lidx = idx++;
+ if (lidx < s_idx)
+@@ -2169,7 +2191,7 @@ EXPORT_SYMBOL(__neigh_for_each_release);
+ static struct neighbour *neigh_get_first(struct seq_file *seq)
+ {
+ struct neigh_seq_state *state = seq->private;
+- struct net *net = state->p.net;
++ struct net *net = seq_file_net(seq);
+ struct neigh_table *tbl = state->tbl;
+ struct neighbour *n = NULL;
+ int bucket = state->bucket;
+@@ -2179,7 +2201,7 @@ static struct neighbour *neigh_get_first(struct seq_file *seq)
+ n = tbl->hash_buckets[bucket];
+
+ while (n) {
+- if (n->dev->nd_net != net)
++ if (!net_eq(dev_net(n->dev), net))
+ goto next;
+ if (state->neigh_sub_iter) {
+ loff_t fakep = 0;
+@@ -2210,7 +2232,7 @@ static struct neighbour *neigh_get_next(struct seq_file *seq,
+ loff_t *pos)
+ {
+ struct neigh_seq_state *state = seq->private;
+- struct net *net = state->p.net;
++ struct net *net = seq_file_net(seq);
+ struct neigh_table *tbl = state->tbl;
+
+ if (state->neigh_sub_iter) {
+@@ -2222,7 +2244,7 @@ static struct neighbour *neigh_get_next(struct seq_file *seq,
+
+ while (1) {
+ while (n) {
+- if (n->dev->nd_net != net)
++ if (!net_eq(dev_net(n->dev), net))
+ goto next;
+ if (state->neigh_sub_iter) {
+ void *v = state->neigh_sub_iter(state, n, pos);
+@@ -2270,7 +2292,7 @@ static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
+ static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
+ {
+ struct neigh_seq_state *state = seq->private;
+- struct net * net = state->p.net;
++ struct net *net = seq_file_net(seq);
+ struct neigh_table *tbl = state->tbl;
+ struct pneigh_entry *pn = NULL;
+ int bucket = state->bucket;
+@@ -2278,7 +2300,7 @@ static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
+ state->flags |= NEIGH_SEQ_IS_PNEIGH;
+ for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
+ pn = tbl->phash_buckets[bucket];
+- while (pn && (pn->net != net))
++ while (pn && !net_eq(pneigh_net(pn), net))
+ pn = pn->next;
+ if (pn)
+ break;
+@@ -2293,7 +2315,7 @@ static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
+ loff_t *pos)
+ {
+ struct neigh_seq_state *state = seq->private;
+- struct net * net = state->p.net;
++ struct net *net = seq_file_net(seq);
+ struct neigh_table *tbl = state->tbl;
+
+ pn = pn->next;
+@@ -2301,7 +2323,7 @@ static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
+ if (++state->bucket > PNEIGH_HASHMASK)
+ break;
+ pn = tbl->phash_buckets[state->bucket];
+- while (pn && (pn->net != net))
++ while (pn && !net_eq(pneigh_net(pn), net))
+ pn = pn->next;
+ if (pn)
+ break;
+@@ -2506,7 +2528,7 @@ static inline size_t neigh_nlmsg_size(void)
+
+ static void __neigh_notify(struct neighbour *n, int type, int flags)
+ {
+- struct net *net = n->dev->nd_net;
++ struct net *net = dev_net(n->dev);
+ struct sk_buff *skb;
+ int err = -ENOBUFS;
+
+@@ -2532,6 +2554,7 @@ void neigh_app_ns(struct neighbour *n)
+ {
+ __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST);
+ }
++EXPORT_SYMBOL(neigh_app_ns);
+ #endif /* CONFIG_ARPD */
+
+ #ifdef CONFIG_SYSCTL
+@@ -2763,7 +2786,8 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
+ neigh_path[NEIGH_CTL_PATH_PROTO].procname = p_name;
+ neigh_path[NEIGH_CTL_PATH_PROTO].ctl_name = p_id;
+
+- t->sysctl_header = register_sysctl_paths(neigh_path, t->neigh_vars);
++ t->sysctl_header =
++ register_net_sysctl_table(neigh_parms_net(p), neigh_path, t->neigh_vars);
+ if (!t->sysctl_header)
+ goto free_procname;
+
+@@ -2777,6 +2801,7 @@ free:
+ err:
+ return -ENOBUFS;
+ }
++EXPORT_SYMBOL(neigh_sysctl_register);
+
+ void neigh_sysctl_unregister(struct neigh_parms *p)
+ {
+@@ -2788,6 +2813,7 @@ void neigh_sysctl_unregister(struct neigh_parms *p)
+ kfree(t);
+ }
+ }
++EXPORT_SYMBOL(neigh_sysctl_unregister);
+
+ #endif /* CONFIG_SYSCTL */
+
+@@ -2805,32 +2831,3 @@ static int __init neigh_init(void)
+
+ subsys_initcall(neigh_init);
+
+-EXPORT_SYMBOL(__neigh_event_send);
+-EXPORT_SYMBOL(neigh_changeaddr);
+-EXPORT_SYMBOL(neigh_compat_output);
+-EXPORT_SYMBOL(neigh_connected_output);
+-EXPORT_SYMBOL(neigh_create);
+-EXPORT_SYMBOL(neigh_destroy);
+-EXPORT_SYMBOL(neigh_event_ns);
+-EXPORT_SYMBOL(neigh_ifdown);
+-EXPORT_SYMBOL(neigh_lookup);
+-EXPORT_SYMBOL(neigh_lookup_nodev);
+-EXPORT_SYMBOL(neigh_parms_alloc);
+-EXPORT_SYMBOL(neigh_parms_release);
+-EXPORT_SYMBOL(neigh_rand_reach_time);
+-EXPORT_SYMBOL(neigh_resolve_output);
+-EXPORT_SYMBOL(neigh_table_clear);
+-EXPORT_SYMBOL(neigh_table_init);
+-EXPORT_SYMBOL(neigh_table_init_no_netlink);
+-EXPORT_SYMBOL(neigh_update);
+-EXPORT_SYMBOL(pneigh_enqueue);
+-EXPORT_SYMBOL(pneigh_lookup);
+-EXPORT_SYMBOL_GPL(__pneigh_lookup);
+-
+-#ifdef CONFIG_ARPD
+-EXPORT_SYMBOL(neigh_app_ns);
+-#endif
+-#ifdef CONFIG_SYSCTL
+-EXPORT_SYMBOL(neigh_sysctl_register);
+-EXPORT_SYMBOL(neigh_sysctl_unregister);
+-#endif
+diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
+index 7635d3f..4e7b847 100644
+--- a/net/core/net-sysfs.c
++++ b/net/core/net-sysfs.c
+@@ -87,6 +87,7 @@ static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,
+ return ret;
+ }
+
++NETDEVICE_SHOW(dev_id, fmt_hex);
+ NETDEVICE_SHOW(addr_len, fmt_dec);
+ NETDEVICE_SHOW(iflink, fmt_dec);
+ NETDEVICE_SHOW(ifindex, fmt_dec);
+@@ -210,6 +211,7 @@ static ssize_t store_tx_queue_len(struct device *dev,
+
+ static struct device_attribute net_class_attributes[] = {
+ __ATTR(addr_len, S_IRUGO, show_addr_len, NULL),
++ __ATTR(dev_id, S_IRUGO, show_dev_id, NULL),
+ __ATTR(iflink, S_IRUGO, show_iflink, NULL),
+ __ATTR(ifindex, S_IRUGO, show_ifindex, NULL),
+ __ATTR(features, S_IRUGO, show_features, NULL),
+diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
+index 7b66083..72b4c18 100644
+--- a/net/core/net_namespace.c
++++ b/net/core/net_namespace.c
+@@ -5,7 +5,9 @@
+ #include <linux/list.h>
+ #include <linux/delay.h>
+ #include <linux/sched.h>
++#include <linux/idr.h>
+ #include <net/net_namespace.h>
++#include <net/netns/generic.h>
+
+ /*
+ * Our network namespace constructor/destructor lists
+@@ -20,6 +22,8 @@ LIST_HEAD(net_namespace_list);
+ struct net init_net;
+ EXPORT_SYMBOL(init_net);
+
++#define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */
++
+ /*
+ * setup_net runs the initializers for the network namespace object.
+ */
+@@ -28,9 +32,22 @@ static __net_init int setup_net(struct net *net)
+ /* Must be called with net_mutex held */
+ struct pernet_operations *ops;
+ int error;
++ struct net_generic *ng;
+
+ 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;
++ INIT_RCU_HEAD(&ng->rcu);
++ rcu_assign_pointer(net->gen, ng);
+
+ error = 0;
+ list_for_each_entry(ops, &pernet_list, list) {
+@@ -53,6 +70,7 @@ out_undo:
+ }
+
+ rcu_barrier();
++ kfree(ng);
+ goto out;
+ }
+
+@@ -70,11 +88,13 @@ 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",
+ atomic_read(&net->use_count));
+ return;
+ }
++#endif
+
+ kmem_cache_free(net_cachep, net);
+ }
+@@ -253,6 +273,8 @@ static void unregister_pernet_operations(struct pernet_operations *ops)
+ }
+ #endif
+
++static DEFINE_IDA(net_generic_ids);
++
+ /**
+ * register_pernet_subsys - register a network namespace subsystem
+ * @ops: pernet operations structure for the subsystem
+@@ -330,6 +352,30 @@ int register_pernet_device(struct pernet_operations *ops)
+ }
+ EXPORT_SYMBOL_GPL(register_pernet_device);
+
++int register_pernet_gen_device(int *id, struct pernet_operations *ops)
++{
++ int error;
++ mutex_lock(&net_mutex);
++again:
++ error = ida_get_new_above(&net_generic_ids, 1, id);
++ if (error) {
++ if (error == -EAGAIN) {
++ ida_pre_get(&net_generic_ids, GFP_KERNEL);
++ goto again;
++ }
++ goto out;
++ }
++ error = register_pernet_operations(&pernet_list, ops);
++ if (error)
++ ida_remove(&net_generic_ids, *id);
++ else if (first_device == &pernet_list)
++ first_device = &ops->list;
++out:
++ mutex_unlock(&net_mutex);
++ return error;
++}
++EXPORT_SYMBOL_GPL(register_pernet_gen_device);
++
+ /**
+ * unregister_pernet_device - unregister a network namespace netdevice
+ * @ops: pernet operations structure to manipulate
+@@ -348,3 +394,61 @@ void unregister_pernet_device(struct pernet_operations *ops)
+ mutex_unlock(&net_mutex);
+ }
+ EXPORT_SYMBOL_GPL(unregister_pernet_device);
++
++void unregister_pernet_gen_device(int id, struct pernet_operations *ops)
++{
++ mutex_lock(&net_mutex);
++ if (&ops->list == first_device)
++ first_device = first_device->next;
++ unregister_pernet_operations(ops);
++ ida_remove(&net_generic_ids, id);
++ mutex_unlock(&net_mutex);
++}
++EXPORT_SYMBOL_GPL(unregister_pernet_gen_device);
++
++static void net_generic_release(struct rcu_head *rcu)
++{
++ struct net_generic *ng;
++
++ ng = container_of(rcu, struct net_generic, rcu);
++ kfree(ng);
++}
++
++int net_assign_generic(struct net *net, int id, void *data)
++{
++ struct net_generic *ng, *old_ng;
++
++ BUG_ON(!mutex_is_locked(&net_mutex));
++ BUG_ON(id == 0);
++
++ ng = old_ng = net->gen;
++ if (old_ng->len >= id)
++ goto assign;
++
++ ng = kzalloc(sizeof(struct net_generic) +
++ id * sizeof(void *), GFP_KERNEL);
++ if (ng == NULL)
++ return -ENOMEM;
++
++ /*
++ * Some synchronisation notes:
++ *
++ * The net_generic explores the net->gen array inside rcu
++ * read section. Besides once set the net->gen->ptr[x]
++ * pointer never changes (see rules in netns/generic.h).
++ *
++ * That said, we simply duplicate this array and schedule
++ * the old copy for kfree after a grace period.
++ */
++
++ ng->len = id;
++ INIT_RCU_HEAD(&ng->rcu);
++ memcpy(&ng->ptr, &old_ng->ptr, old_ng->len);
++
++ rcu_assign_pointer(net->gen, ng);
++ call_rcu(&old_ng->rcu, net_generic_release);
++assign:
++ ng->ptr[id - 1] = data;
++ return 0;
++}
++EXPORT_SYMBOL_GPL(net_assign_generic);
+diff --git a/net/core/netpoll.c b/net/core/netpoll.c
+index c635de5..b04d643 100644
+--- a/net/core/netpoll.c
++++ b/net/core/netpoll.c
+@@ -390,9 +390,7 @@ static void arp_reply(struct sk_buff *skb)
+ if (skb->dev->flags & IFF_NOARP)
+ return;
+
+- if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
+- (2 * skb->dev->addr_len) +
+- (2 * sizeof(u32)))))
++ if (!pskb_may_pull(skb, arp_hdr_len(skb->dev)))
+ return;
+
+ skb_reset_network_header(skb);
+@@ -420,7 +418,7 @@ static void arp_reply(struct sk_buff *skb)
+ ipv4_is_loopback(tip) || ipv4_is_multicast(tip))
+ return;
+
+- size = sizeof(struct arphdr) + 2 * (skb->dev->addr_len + 4);
++ size = arp_hdr_len(skb->dev);
+ send_skb = find_skb(np, size + LL_RESERVED_SPACE(np->dev),
+ LL_RESERVED_SPACE(np->dev));
+
+diff --git a/net/core/pktgen.c b/net/core/pktgen.c
+index 20e63b3..a803b44 100644
+--- a/net/core/pktgen.c
++++ b/net/core/pktgen.c
+@@ -1874,7 +1874,7 @@ static int pktgen_device_event(struct notifier_block *unused,
+ {
+ struct net_device *dev = ptr;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ /* It is OK that we do not hold the group lock right now,
+diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
+index 2bd9c5f..cf857c4 100644
+--- a/net/core/rtnetlink.c
++++ b/net/core/rtnetlink.c
+@@ -82,6 +82,11 @@ int rtnl_trylock(void)
+ return mutex_trylock(&rtnl_mutex);
+ }
+
++int rtnl_is_locked(void)
++{
++ return mutex_is_locked(&rtnl_mutex);
++}
++
+ static struct rtnl_link *rtnl_msg_handlers[NPROTO];
+
+ static inline int rtm_msgindex(int msgtype)
+@@ -269,6 +274,26 @@ int rtnl_link_register(struct rtnl_link_ops *ops)
+
+ EXPORT_SYMBOL_GPL(rtnl_link_register);
+
++static void __rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops)
++{
++ struct net_device *dev;
++restart:
++ for_each_netdev(net, dev) {
++ if (dev->rtnl_link_ops == ops) {
++ ops->dellink(dev);
++ goto restart;
++ }
++ }
++}
++
++void rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops)
++{
++ rtnl_lock();
++ __rtnl_kill_links(net, ops);
++ rtnl_unlock();
++}
++EXPORT_SYMBOL_GPL(rtnl_kill_links);
++
+ /**
+ * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink.
+ * @ops: struct rtnl_link_ops * to unregister
+@@ -277,17 +302,10 @@ EXPORT_SYMBOL_GPL(rtnl_link_register);
+ */
+ void __rtnl_link_unregister(struct rtnl_link_ops *ops)
+ {
+- struct net_device *dev, *n;
+ struct net *net;
+
+ for_each_net(net) {
+-restart:
+- for_each_netdev_safe(net, dev, n) {
+- if (dev->rtnl_link_ops == ops) {
+- ops->dellink(dev);
+- goto restart;
+- }
+- }
++ __rtnl_kill_links(net, ops);
+ }
+ list_del(&ops->list);
+ }
+@@ -662,7 +680,7 @@ nla_put_failure:
+
+ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ int idx;
+ int s_idx = cb->args[0];
+ struct net_device *dev;
+@@ -879,7 +897,7 @@ errout:
+
+ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct ifinfomsg *ifm;
+ struct net_device *dev;
+ int err;
+@@ -921,7 +939,7 @@ errout:
+
+ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ const struct rtnl_link_ops *ops;
+ struct net_device *dev;
+ struct ifinfomsg *ifm;
+@@ -972,7 +990,7 @@ struct net_device *rtnl_create_link(struct net *net, char *ifname,
+ goto err_free;
+ }
+
+- dev->nd_net = net;
++ dev_net_set(dev, net);
+ dev->rtnl_link_ops = ops;
+
+ if (tb[IFLA_MTU])
+@@ -1000,7 +1018,7 @@ err:
+
+ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ const struct rtnl_link_ops *ops;
+ struct net_device *dev;
+ struct ifinfomsg *ifm;
+@@ -1132,7 +1150,7 @@ replay:
+
+ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct ifinfomsg *ifm;
+ struct nlattr *tb[IFLA_MAX+1];
+ struct net_device *dev = NULL;
+@@ -1198,7 +1216,7 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
+
+ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
+ {
+- struct net *net = dev->nd_net;
++ struct net *net = dev_net(dev);
+ struct sk_buff *skb;
+ int err = -ENOBUFS;
+
+@@ -1227,7 +1245,7 @@ static int rtattr_max;
+
+ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ rtnl_doit_func doit;
+ int sz_idx, kind;
+ int min_len;
+@@ -1389,6 +1407,7 @@ EXPORT_SYMBOL(rtnetlink_put_metrics);
+ EXPORT_SYMBOL(rtnl_lock);
+ EXPORT_SYMBOL(rtnl_trylock);
+ EXPORT_SYMBOL(rtnl_unlock);
++EXPORT_SYMBOL(rtnl_is_locked);
+ EXPORT_SYMBOL(rtnl_unicast);
+ EXPORT_SYMBOL(rtnl_notify);
+ EXPORT_SYMBOL(rtnl_set_sk_err);
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index 6087013..4fe605f 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -263,6 +263,28 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
+ return skb;
+ }
+
++/**
++ * dev_alloc_skb - allocate an skbuff for receiving
++ * @length: length to allocate
++ *
++ * Allocate a new &sk_buff and assign it a usage count of one. The
++ * buffer has unspecified headroom built in. Users should allocate
++ * the headroom they think they need without accounting for the
++ * built in space. The built in space is used for optimisations.
++ *
++ * %NULL is returned if there is no free memory. Although this function
++ * allocates memory it can be called from an interrupt.
++ */
++struct sk_buff *dev_alloc_skb(unsigned int length)
++{
++ /*
++ * There is more code here than it seems:
++ * __dev_alloc_skb is an inline
++ */
++ return __dev_alloc_skb(length, GFP_ATOMIC);
++}
++EXPORT_SYMBOL(dev_alloc_skb);
++
+ static void skb_drop_list(struct sk_buff **listp)
+ {
+ struct sk_buff *list = *listp;
+@@ -857,6 +879,78 @@ free_skb:
+ return err;
+ }
+
++/**
++ * skb_put - add data to a buffer
++ * @skb: buffer to use
++ * @len: amount of data to add
++ *
++ * This function extends the used data area of the buffer. If this would
++ * exceed the total buffer size the kernel will panic. A pointer to the
++ * first byte of the extra data is returned.
++ */
++unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
++{
++ unsigned char *tmp = skb_tail_pointer(skb);
++ SKB_LINEAR_ASSERT(skb);
++ skb->tail += len;
++ skb->len += len;
++ if (unlikely(skb->tail > skb->end))
++ skb_over_panic(skb, len, __builtin_return_address(0));
++ return tmp;
++}
++EXPORT_SYMBOL(skb_put);
++
++/**
++ * skb_push - add data to the start of a buffer
++ * @skb: buffer to use
++ * @len: amount of data to add
++ *
++ * This function extends the used data area of the buffer at the buffer
++ * start. If this would exceed the total buffer headroom the kernel will
++ * panic. A pointer to the first byte of the extra data is returned.
++ */
++unsigned char *skb_push(struct sk_buff *skb, unsigned int len)
++{
++ skb->data -= len;
++ skb->len += len;
++ if (unlikely(skb->data<skb->head))
++ skb_under_panic(skb, len, __builtin_return_address(0));
++ return skb->data;
++}
++EXPORT_SYMBOL(skb_push);
++
++/**
++ * skb_pull - remove data from the start of a buffer
++ * @skb: buffer to use
++ * @len: amount of data to remove
++ *
++ * This function removes data from the start of a buffer, returning
++ * the memory to the headroom. A pointer to the next data in the buffer
++ * is returned. Once the data has been pulled future pushes will overwrite
++ * the old data.
++ */
++unsigned char *skb_pull(struct sk_buff *skb, unsigned int len)
++{
++ return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len);
++}
++EXPORT_SYMBOL(skb_pull);
++
++/**
++ * skb_trim - remove end from a buffer
++ * @skb: buffer to alter
++ * @len: new length
++ *
++ * Cut the length of a buffer down by removing data from the tail. If
++ * the buffer is already under the length specified it is not modified.
++ * The skb must be linear.
++ */
++void skb_trim(struct sk_buff *skb, unsigned int len)
++{
++ if (skb->len > len)
++ __skb_trim(skb, len);
++}
++EXPORT_SYMBOL(skb_trim);
++
+ /* Trims skb to length len. It can change skb pointers.
+ */
+
+@@ -1766,7 +1860,7 @@ void skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head
+ unsigned long flags;
+
+ spin_lock_irqsave(&list->lock, flags);
+- __skb_append(old, newsk, list);
++ __skb_queue_after(list, old, newsk);
+ spin_unlock_irqrestore(&list->lock, flags);
+ }
+
+diff --git a/net/core/sock.c b/net/core/sock.c
+index 7a0567b..5dbb81b 100644
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -372,7 +372,7 @@ static int sock_bindtodevice(struct sock *sk, char __user *optval, int optlen)
+ {
+ int ret = -ENOPROTOOPT;
+ #ifdef CONFIG_NETDEVICES
+- struct net *net = sk->sk_net;
++ struct net *net = sock_net(sk);
+ char devname[IFNAMSIZ];
+ int index;
+
+@@ -450,15 +450,6 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
+ * Options without arguments
+ */
+
+-#ifdef SO_DONTLINGER /* Compatibility item... */
+- if (optname == SO_DONTLINGER) {
+- lock_sock(sk);
+- sock_reset_flag(sk, SOCK_LINGER);
+- release_sock(sk);
+- return 0;
+- }
+-#endif
+-
+ if (optname == SO_BINDTODEVICE)
+ return sock_bindtodevice(sk, optval, optlen);
+
+@@ -942,7 +933,6 @@ static void sk_prot_free(struct proto *prot, struct sock *sk)
+ * @family: protocol family
+ * @priority: for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc)
+ * @prot: struct proto associated with this new sock instance
+- * @zero_it: if we should zero the newly allocated sock
+ */
+ struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
+ struct proto *prot)
+@@ -958,7 +948,7 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
+ */
+ sk->sk_prot = sk->sk_prot_creator = prot;
+ sock_lock_init(sk);
+- sk->sk_net = get_net(net);
++ sock_net_set(sk, get_net(net));
+ }
+
+ return sk;
+@@ -981,12 +971,32 @@ void sk_free(struct sock *sk)
+
+ if (atomic_read(&sk->sk_omem_alloc))
+ printk(KERN_DEBUG "%s: optmem leakage (%d bytes) detected.\n",
+- __FUNCTION__, atomic_read(&sk->sk_omem_alloc));
++ __func__, atomic_read(&sk->sk_omem_alloc));
+
+- put_net(sk->sk_net);
++ put_net(sock_net(sk));
+ sk_prot_free(sk->sk_prot_creator, sk);
+ }
+
++/*
++ * Last sock_put should drop referrence to sk->sk_net. It has already
++ * been dropped in sk_change_net. Taking referrence to stopping namespace
++ * is not an option.
++ * Take referrence to a socket to remove it from hash _alive_ and after that
++ * destroy it in the context of init_net.
++ */
++void sk_release_kernel(struct sock *sk)
++{
++ if (sk == NULL || sk->sk_socket == NULL)
++ return;
++
++ sock_hold(sk);
++ sock_release(sk->sk_socket);
++ release_net(sock_net(sk));
++ sock_net_set(sk, get_net(&init_net));
++ sock_put(sk);
++}
++EXPORT_SYMBOL(sk_release_kernel);
++
+ struct sock *sk_clone(const struct sock *sk, const gfp_t priority)
+ {
+ struct sock *newsk;
+@@ -998,7 +1008,7 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority)
+ sock_copy(newsk, sk);
+
+ /* SANITY */
+- get_net(newsk->sk_net);
++ get_net(sock_net(newsk));
+ sk_node_init(&newsk->sk_node);
+ sock_lock_init(newsk);
+ bh_lock_sock(newsk);
+@@ -1076,10 +1086,12 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
+ if (sk->sk_route_caps & NETIF_F_GSO)
+ sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE;
+ if (sk_can_gso(sk)) {
+- if (dst->header_len)
++ if (dst->header_len) {
+ sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
+- else
++ } else {
+ sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
++ sk->sk_gso_max_size = dst->dev->gso_max_size;
++ }
+ }
+ }
+ EXPORT_SYMBOL_GPL(sk_setup_caps);
+@@ -1919,16 +1931,113 @@ EXPORT_SYMBOL(sk_common_release);
+ static DEFINE_RWLOCK(proto_list_lock);
+ static LIST_HEAD(proto_list);
+
++#ifdef CONFIG_PROC_FS
++#define PROTO_INUSE_NR 64 /* should be enough for the first time */
++struct prot_inuse {
++ int val[PROTO_INUSE_NR];
++};
++
++static DECLARE_BITMAP(proto_inuse_idx, PROTO_INUSE_NR);
++
++#ifdef CONFIG_NET_NS
++void sock_prot_inuse_add(struct net *net, struct proto *prot, int val)
++{
++ int cpu = smp_processor_id();
++ per_cpu_ptr(net->core.inuse, cpu)->val[prot->inuse_idx] += val;
++}
++EXPORT_SYMBOL_GPL(sock_prot_inuse_add);
++
++int sock_prot_inuse_get(struct net *net, struct proto *prot)
++{
++ int cpu, idx = prot->inuse_idx;
++ int res = 0;
++
++ for_each_possible_cpu(cpu)
++ res += per_cpu_ptr(net->core.inuse, cpu)->val[idx];
++
++ return res >= 0 ? res : 0;
++}
++EXPORT_SYMBOL_GPL(sock_prot_inuse_get);
++
++static int sock_inuse_init_net(struct net *net)
++{
++ net->core.inuse = alloc_percpu(struct prot_inuse);
++ return net->core.inuse ? 0 : -ENOMEM;
++}
++
++static void sock_inuse_exit_net(struct net *net)
++{
++ free_percpu(net->core.inuse);
++}
++
++static struct pernet_operations net_inuse_ops = {
++ .init = sock_inuse_init_net,
++ .exit = sock_inuse_exit_net,
++};
++
++static __init int net_inuse_init(void)
++{
++ if (register_pernet_subsys(&net_inuse_ops))
++ panic("Cannot initialize net inuse counters");
++
++ return 0;
++}
++
++core_initcall(net_inuse_init);
++#else
++static DEFINE_PER_CPU(struct prot_inuse, prot_inuse);
++
++void sock_prot_inuse_add(struct net *net, struct proto *prot, int val)
++{
++ __get_cpu_var(prot_inuse).val[prot->inuse_idx] += val;
++}
++EXPORT_SYMBOL_GPL(sock_prot_inuse_add);
++
++int sock_prot_inuse_get(struct net *net, struct proto *prot)
++{
++ int cpu, idx = prot->inuse_idx;
++ int res = 0;
++
++ for_each_possible_cpu(cpu)
++ res += per_cpu(prot_inuse, cpu).val[idx];
++
++ return res >= 0 ? res : 0;
++}
++EXPORT_SYMBOL_GPL(sock_prot_inuse_get);
++#endif
++
++static void assign_proto_idx(struct proto *prot)
++{
++ prot->inuse_idx = find_first_zero_bit(proto_inuse_idx, PROTO_INUSE_NR);
++
++ if (unlikely(prot->inuse_idx == PROTO_INUSE_NR - 1)) {
++ printk(KERN_ERR "PROTO_INUSE_NR exhausted\n");
++ return;
++ }
++
++ set_bit(prot->inuse_idx, proto_inuse_idx);
++}
++
++static void release_proto_idx(struct proto *prot)
++{
++ if (prot->inuse_idx != PROTO_INUSE_NR - 1)
++ clear_bit(prot->inuse_idx, proto_inuse_idx);
++}
++#else
++static inline void assign_proto_idx(struct proto *prot)
++{
++}
++
++static inline void release_proto_idx(struct proto *prot)
++{
++}
++#endif
++
+ int proto_register(struct proto *prot, int alloc_slab)
+ {
+ char *request_sock_slab_name = NULL;
+ char *timewait_sock_slab_name;
+
+- if (sock_prot_inuse_init(prot) != 0) {
+- printk(KERN_CRIT "%s: Can't alloc inuse counters!\n", prot->name);
+- goto out;
+- }
+-
+ if (alloc_slab) {
+ prot->slab = kmem_cache_create(prot->name, prot->obj_size, 0,
+ SLAB_HWCACHE_ALIGN, NULL);
+@@ -1936,7 +2045,7 @@ int proto_register(struct proto *prot, int alloc_slab)
+ if (prot->slab == NULL) {
+ printk(KERN_CRIT "%s: Can't create sock SLAB cache!\n",
+ prot->name);
+- goto out_free_inuse;
++ goto out;
+ }
+
+ if (prot->rsk_prot != NULL) {
+@@ -1979,6 +2088,7 @@ int proto_register(struct proto *prot, int alloc_slab)
+
+ write_lock(&proto_list_lock);
+ list_add(&prot->node, &proto_list);
++ assign_proto_idx(prot);
+ write_unlock(&proto_list_lock);
+ return 0;
+
+@@ -1994,8 +2104,6 @@ out_free_request_sock_slab_name:
+ out_free_sock_slab:
+ kmem_cache_destroy(prot->slab);
+ prot->slab = NULL;
+-out_free_inuse:
+- sock_prot_inuse_free(prot);
+ out:
+ return -ENOBUFS;
+ }
+@@ -2005,11 +2113,10 @@ EXPORT_SYMBOL(proto_register);
+ void proto_unregister(struct proto *prot)
+ {
+ write_lock(&proto_list_lock);
++ release_proto_idx(prot);
+ list_del(&prot->node);
+ write_unlock(&proto_list_lock);
+
+- sock_prot_inuse_free(prot);
+-
+ if (prot->slab != NULL) {
+ kmem_cache_destroy(prot->slab);
+ prot->slab = NULL;
+diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
+index 130338f..5fc8010 100644
+--- a/net/core/sysctl_net_core.c
++++ b/net/core/sysctl_net_core.c
+@@ -127,7 +127,7 @@ static struct ctl_table net_core_table[] = {
+ {
+ .ctl_name = NET_CORE_SOMAXCONN,
+ .procname = "somaxconn",
+- .data = &init_net.sysctl_somaxconn,
++ .data = &init_net.core.sysctl_somaxconn,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec
+@@ -161,7 +161,7 @@ static __net_init int sysctl_core_net_init(struct net *net)
+ {
+ struct ctl_table *tbl, *tmp;
+
+- net->sysctl_somaxconn = SOMAXCONN;
++ net->core.sysctl_somaxconn = SOMAXCONN;
+
+ tbl = net_core_table;
+ if (net != &init_net) {
+@@ -178,9 +178,9 @@ static __net_init int sysctl_core_net_init(struct net *net)
+ }
+ }
+
+- net->sysctl_core_hdr = register_net_sysctl_table(net,
++ net->core.sysctl_hdr = register_net_sysctl_table(net,
+ net_core_path, tbl);
+- if (net->sysctl_core_hdr == NULL)
++ if (net->core.sysctl_hdr == NULL)
+ goto err_reg;
+
+ return 0;
+@@ -196,8 +196,8 @@ static __net_exit void sysctl_core_net_exit(struct net *net)
+ {
+ struct ctl_table *tbl;
+
+- tbl = net->sysctl_core_hdr->ctl_table_arg;
+- unregister_net_sysctl_table(net->sysctl_core_hdr);
++ tbl = net->core.sysctl_hdr->ctl_table_arg;
++ unregister_net_sysctl_table(net->core.sysctl_hdr);
+ BUG_ON(tbl == net_core_table);
+ kfree(tbl);
+ }
+diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
+index ba2ef94..f44d492 100644
+--- a/net/dccp/dccp.h
++++ b/net/dccp/dccp.h
+@@ -23,9 +23,9 @@
+ * DCCP - specific warning and debugging macros.
+ */
+ #define DCCP_WARN(fmt, a...) LIMIT_NETDEBUG(KERN_WARNING "%s: " fmt, \
+- __FUNCTION__, ##a)
++ __func__, ##a)
+ #define DCCP_CRIT(fmt, a...) printk(KERN_CRIT fmt " at %s:%d/%s()\n", ##a, \
+- __FILE__, __LINE__, __FUNCTION__)
++ __FILE__, __LINE__, __func__)
+ #define DCCP_BUG(a...) do { DCCP_CRIT("BUG: " a); dump_stack(); } while(0)
+ #define DCCP_BUG_ON(cond) do { if (unlikely((cond) != 0)) \
+ DCCP_BUG("\"%s\" holds (exception!)", \
+@@ -36,7 +36,7 @@
+ printk(fmt, ##args); \
+ } while(0)
+ #define DCCP_PR_DEBUG(enable, fmt, a...) DCCP_PRINTK(enable, KERN_DEBUG \
+- "%s: " fmt, __FUNCTION__, ##a)
++ "%s: " fmt, __func__, ##a)
+
+ #ifdef CONFIG_IP_DCCP_DEBUG
+ extern int dccp_debug;
+@@ -296,7 +296,7 @@ extern unsigned int dccp_poll(struct file *file, struct socket *sock,
+ extern int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr,
+ int addr_len);
+
+-extern struct sk_buff *dccp_ctl_make_reset(struct socket *ctl,
++extern struct sk_buff *dccp_ctl_make_reset(struct sock *sk,
+ struct sk_buff *skb);
+ extern int dccp_send_reset(struct sock *sk, enum dccp_reset_codes code);
+ extern void dccp_send_close(struct sock *sk, const int active);
+diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
+index b337044..b348dd7 100644
+--- a/net/dccp/ipv4.c
++++ b/net/dccp/ipv4.c
+@@ -32,11 +32,10 @@
+ #include "feat.h"
+
+ /*
+- * This is the global socket data structure used for responding to
++ * The per-net dccp.v4_ctl_sk socket is used for responding to
+ * the Out-of-the-blue (OOTB) packets. A control sock will be created
+ * for this socket at the initialization time.
+ */
+-static struct socket *dccp_v4_ctl_socket;
+
+ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+ {
+@@ -212,8 +211,9 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
+ return;
+ }
+
+- sk = inet_lookup(&init_net, &dccp_hashinfo, iph->daddr, dh->dccph_dport,
+- iph->saddr, dh->dccph_sport, inet_iif(skb));
++ sk = inet_lookup(dev_net(skb->dev), &dccp_hashinfo,
++ iph->daddr, dh->dccph_dport,
++ iph->saddr, dh->dccph_sport, inet_iif(skb));
+ if (sk == NULL) {
+ ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
+ return;
+@@ -430,7 +430,7 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
+ if (req != NULL)
+ return dccp_check_req(sk, skb, req, prev);
+
+- nsk = inet_lookup_established(&init_net, &dccp_hashinfo,
++ nsk = inet_lookup_established(sock_net(sk), &dccp_hashinfo,
+ iph->saddr, dh->dccph_sport,
+ iph->daddr, dh->dccph_dport,
+ inet_iif(skb));
+@@ -446,11 +446,11 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
+ return sk;
+ }
+
+-static struct dst_entry* dccp_v4_route_skb(struct sock *sk,
++static struct dst_entry* dccp_v4_route_skb(struct net *net, struct sock *sk,
+ struct sk_buff *skb)
+ {
+ struct rtable *rt;
+- struct flowi fl = { .oif = ((struct rtable *)skb->dst)->rt_iif,
++ struct flowi fl = { .oif = skb->rtable->rt_iif,
+ .nl_u = { .ip4_u =
+ { .daddr = ip_hdr(skb)->saddr,
+ .saddr = ip_hdr(skb)->daddr,
+@@ -463,7 +463,7 @@ static struct dst_entry* dccp_v4_route_skb(struct sock *sk,
+ };
+
+ security_skb_classify_flow(skb, &fl);
+- if (ip_route_output_flow(&init_net, &rt, &fl, sk, 0)) {
++ if (ip_route_output_flow(net, &rt, &fl, sk, 0)) {
+ IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
+ return NULL;
+ }
+@@ -471,15 +471,14 @@ static struct dst_entry* dccp_v4_route_skb(struct sock *sk,
+ return &rt->u.dst;
+ }
+
+-static int dccp_v4_send_response(struct sock *sk, struct request_sock *req,
+- struct dst_entry *dst)
++static int dccp_v4_send_response(struct sock *sk, struct request_sock *req)
+ {
+ int err = -1;
+ struct sk_buff *skb;
++ struct dst_entry *dst;
+
+- /* First, grab a route. */
+-
+- if (dst == NULL && (dst = inet_csk_route_req(sk, req)) == NULL)
++ dst = inet_csk_route_req(sk, req);
++ if (dst == NULL)
+ goto out;
+
+ skb = dccp_make_response(sk, dst, req);
+@@ -506,19 +505,21 @@ static void dccp_v4_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
+ const struct iphdr *rxiph;
+ struct sk_buff *skb;
+ struct dst_entry *dst;
++ struct net *net = dev_net(rxskb->dst->dev);
++ struct sock *ctl_sk = net->dccp.v4_ctl_sk;
+
+ /* Never send a reset in response to a reset. */
+ if (dccp_hdr(rxskb)->dccph_type == DCCP_PKT_RESET)
+ return;
+
+- if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL)
++ if (rxskb->rtable->rt_type != RTN_LOCAL)
+ return;
+
+- dst = dccp_v4_route_skb(dccp_v4_ctl_socket->sk, rxskb);
++ dst = dccp_v4_route_skb(net, ctl_sk, rxskb);
+ if (dst == NULL)
+ return;
+
+- skb = dccp_ctl_make_reset(dccp_v4_ctl_socket, rxskb);
++ skb = dccp_ctl_make_reset(ctl_sk, rxskb);
+ if (skb == NULL)
+ goto out;
+
+@@ -527,10 +528,10 @@ static void dccp_v4_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
+ rxiph->daddr);
+ skb->dst = dst_clone(dst);
+
+- bh_lock_sock(dccp_v4_ctl_socket->sk);
+- err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk,
++ bh_lock_sock(ctl_sk);
++ err = ip_build_and_send_pkt(skb, ctl_sk,
+ rxiph->daddr, rxiph->saddr, NULL);
+- bh_unlock_sock(dccp_v4_ctl_socket->sk);
++ bh_unlock_sock(ctl_sk);
+
+ if (net_xmit_eval(err) == 0) {
+ DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
+@@ -563,8 +564,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
+ struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
+
+ /* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */
+- if (((struct rtable *)skb->dst)->rt_flags &
+- (RTCF_BROADCAST | RTCF_MULTICAST))
++ if (skb->rtable->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
+ return 0; /* discard, don't send a reset here */
+
+ if (dccp_bad_service_code(sk, service)) {
+@@ -619,7 +619,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
+ dreq->dreq_iss = dccp_v4_init_sequence(skb);
+ dreq->dreq_service = service;
+
+- if (dccp_v4_send_response(sk, req, NULL))
++ if (dccp_v4_send_response(sk, req))
+ goto drop_and_free;
+
+ inet_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT);
+@@ -810,7 +810,7 @@ static int dccp_v4_rcv(struct sk_buff *skb)
+
+ /* Step 2:
+ * Look up flow ID in table and get corresponding socket */
+- sk = __inet_lookup(&init_net, &dccp_hashinfo,
++ sk = __inet_lookup(dev_net(skb->dst->dev), &dccp_hashinfo,
+ iph->saddr, dh->dccph_sport,
+ iph->daddr, dh->dccph_dport, inet_iif(skb));
+ /*
+@@ -916,8 +916,6 @@ static struct timewait_sock_ops dccp_timewait_sock_ops = {
+ .twsk_obj_size = sizeof(struct inet_timewait_sock),
+ };
+
+-DEFINE_PROTO_INUSE(dccp_v4)
+-
+ static struct proto dccp_v4_prot = {
+ .name = "DCCP",
+ .owner = THIS_MODULE,
+@@ -942,18 +940,18 @@ static struct proto dccp_v4_prot = {
+ .obj_size = sizeof(struct dccp_sock),
+ .rsk_prot = &dccp_request_sock_ops,
+ .twsk_prot = &dccp_timewait_sock_ops,
+- .hashinfo = &dccp_hashinfo,
++ .h.hashinfo = &dccp_hashinfo,
+ #ifdef CONFIG_COMPAT
+ .compat_setsockopt = compat_dccp_setsockopt,
+ .compat_getsockopt = compat_dccp_getsockopt,
+ #endif
+- REF_PROTO_INUSE(dccp_v4)
+ };
+
+ static struct net_protocol dccp_v4_protocol = {
+ .handler = dccp_v4_rcv,
+ .err_handler = dccp_v4_err,
+ .no_policy = 1,
++ .netns_ok = 1,
+ };
+
+ static const struct proto_ops inet_dccp_ops = {
+@@ -993,6 +991,25 @@ static struct inet_protosw dccp_v4_protosw = {
+ .flags = INET_PROTOSW_ICSK,
+ };
+
++static int dccp_v4_init_net(struct net *net)
++{
++ int err;
++
++ err = inet_ctl_sock_create(&net->dccp.v4_ctl_sk, PF_INET,
++ SOCK_DCCP, IPPROTO_DCCP, net);
++ return err;
++}
++
++static void dccp_v4_exit_net(struct net *net)
++{
++ inet_ctl_sock_destroy(net->dccp.v4_ctl_sk);
++}
++
++static struct pernet_operations dccp_v4_ops = {
++ .init = dccp_v4_init_net,
++ .exit = dccp_v4_exit_net,
++};
++
+ static int __init dccp_v4_init(void)
+ {
+ int err = proto_register(&dccp_v4_prot, 1);
+@@ -1006,13 +1023,12 @@ static int __init dccp_v4_init(void)
+
+ inet_register_protosw(&dccp_v4_protosw);
+
+- err = inet_csk_ctl_sock_create(&dccp_v4_ctl_socket, PF_INET,
+- SOCK_DCCP, IPPROTO_DCCP);
++ err = register_pernet_subsys(&dccp_v4_ops);
+ if (err)
+- goto out_unregister_protosw;
++ goto out_destroy_ctl_sock;
+ out:
+ return err;
+-out_unregister_protosw:
++out_destroy_ctl_sock:
+ inet_unregister_protosw(&dccp_v4_protosw);
+ inet_del_protocol(&dccp_v4_protocol, IPPROTO_DCCP);
+ out_proto_unregister:
+@@ -1022,6 +1038,7 @@ out_proto_unregister:
+
+ static void __exit dccp_v4_exit(void)
+ {
++ unregister_pernet_subsys(&dccp_v4_ops);
+ inet_unregister_protosw(&dccp_v4_protosw);
+ inet_del_protocol(&dccp_v4_protocol, IPPROTO_DCCP);
+ proto_unregister(&dccp_v4_prot);
+diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
+index 490333d..9b1129b 100644
+--- a/net/dccp/ipv6.c
++++ b/net/dccp/ipv6.c
+@@ -33,8 +33,7 @@
+ #include "ipv6.h"
+ #include "feat.h"
+
+-/* Socket used for sending RSTs and ACKs */
+-static struct socket *dccp_v6_ctl_socket;
++/* The per-net dccp.v6_ctl_sk is used for sending RSTs and ACKs */
+
+ static struct inet_connection_sock_af_ops dccp_ipv6_mapped;
+ static struct inet_connection_sock_af_ops dccp_ipv6_af_ops;
+@@ -95,7 +94,8 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ int err;
+ __u64 seq;
+
+- sk = inet6_lookup(&init_net, &dccp_hashinfo, &hdr->daddr, dh->dccph_dport,
++ sk = inet6_lookup(dev_net(skb->dev), &dccp_hashinfo,
++ &hdr->daddr, dh->dccph_dport,
+ &hdr->saddr, dh->dccph_sport, inet6_iif(skb));
+
+ if (sk == NULL) {
+@@ -224,8 +224,7 @@ out:
+ }
+
+
+-static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
+- struct dst_entry *dst)
++static int dccp_v6_send_response(struct sock *sk, struct request_sock *req)
+ {
+ struct inet6_request_sock *ireq6 = inet6_rsk(req);
+ struct ipv6_pinfo *np = inet6_sk(sk);
+@@ -234,6 +233,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
+ struct in6_addr *final_p = NULL, final;
+ struct flowi fl;
+ int err = -1;
++ struct dst_entry *dst;
+
+ memset(&fl, 0, sizeof(fl));
+ fl.proto = IPPROTO_DCCP;
+@@ -245,28 +245,26 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
+ fl.fl_ip_sport = inet_sk(sk)->sport;
+ security_req_classify_flow(req, &fl);
+
+- if (dst == NULL) {
+- opt = np->opt;
++ opt = np->opt;
+
+- if (opt != NULL && opt->srcrt != NULL) {
+- const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt;
++ if (opt != NULL && opt->srcrt != NULL) {
++ const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt;
+
+- ipv6_addr_copy(&final, &fl.fl6_dst);
+- ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+- final_p = &final;
+- }
++ ipv6_addr_copy(&final, &fl.fl6_dst);
++ ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
++ final_p = &final;
++ }
+
+- err = ip6_dst_lookup(sk, &dst, &fl);
+- if (err)
+- goto done;
++ err = ip6_dst_lookup(sk, &dst, &fl);
++ if (err)
++ goto done;
+
+- if (final_p)
+- ipv6_addr_copy(&fl.fl6_dst, final_p);
++ if (final_p)
++ ipv6_addr_copy(&fl.fl6_dst, final_p);
+
+- err = xfrm_lookup(&dst, &fl, sk, 0);
+- if (err < 0)
+- goto done;
+- }
++ err = xfrm_lookup(&dst, &fl, sk, 0);
++ if (err < 0)
++ goto done;
+
+ skb = dccp_make_response(sk, dst, req);
+ if (skb != NULL) {
+@@ -298,6 +296,8 @@ static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
+ struct ipv6hdr *rxip6h;
+ struct sk_buff *skb;
+ struct flowi fl;
++ struct net *net = dev_net(rxskb->dst->dev);
++ struct sock *ctl_sk = net->dccp.v6_ctl_sk;
+
+ if (dccp_hdr(rxskb)->dccph_type == DCCP_PKT_RESET)
+ return;
+@@ -305,7 +305,7 @@ static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
+ if (!ipv6_unicast_destination(rxskb))
+ return;
+
+- skb = dccp_ctl_make_reset(dccp_v6_ctl_socket, rxskb);
++ skb = dccp_ctl_make_reset(ctl_sk, rxskb);
+ if (skb == NULL)
+ return;
+
+@@ -324,9 +324,9 @@ static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
+ security_skb_classify_flow(rxskb, &fl);
+
+ /* sk = NULL, but it is safe for now. RST socket required. */
+- if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
++ if (!ip6_dst_lookup(ctl_sk, &skb->dst, &fl)) {
+ if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
+- ip6_xmit(dccp_v6_ctl_socket->sk, skb, &fl, NULL, 0);
++ ip6_xmit(ctl_sk, skb, &fl, NULL, 0);
+ DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
+ DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
+ return;
+@@ -360,7 +360,7 @@ static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
+ if (req != NULL)
+ return dccp_check_req(sk, skb, req, prev);
+
+- nsk = __inet6_lookup_established(&init_net, &dccp_hashinfo,
++ nsk = __inet6_lookup_established(sock_net(sk), &dccp_hashinfo,
+ &iph->saddr, dh->dccph_sport,
+ &iph->daddr, ntohs(dh->dccph_dport),
+ inet6_iif(skb));
+@@ -448,7 +448,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
+ dreq->dreq_iss = dccp_v6_init_sequence(skb);
+ dreq->dreq_service = service;
+
+- if (dccp_v6_send_response(sk, req, NULL))
++ if (dccp_v6_send_response(sk, req))
+ goto drop_and_free;
+
+ inet6_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT);
+@@ -625,7 +625,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
+ newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6;
+
+ __inet6_hash(newsk);
+- inet_inherit_port(sk, newsk);
++ __inet_inherit_port(sk, newsk);
+
+ return newsk;
+
+@@ -791,8 +791,8 @@ static int dccp_v6_rcv(struct sk_buff *skb)
+
+ /* Step 2:
+ * Look up flow ID in table and get corresponding socket */
+- sk = __inet6_lookup(&init_net, &dccp_hashinfo, &ipv6_hdr(skb)->saddr,
+- dh->dccph_sport,
++ sk = __inet6_lookup(dev_net(skb->dst->dev), &dccp_hashinfo,
++ &ipv6_hdr(skb)->saddr, dh->dccph_sport,
+ &ipv6_hdr(skb)->daddr, ntohs(dh->dccph_dport),
+ inet6_iif(skb));
+ /*
+@@ -1102,8 +1102,6 @@ static struct timewait_sock_ops dccp6_timewait_sock_ops = {
+ .twsk_obj_size = sizeof(struct dccp6_timewait_sock),
+ };
+
+-DEFINE_PROTO_INUSE(dccp_v6)
+-
+ static struct proto dccp_v6_prot = {
+ .name = "DCCPv6",
+ .owner = THIS_MODULE,
+@@ -1128,12 +1126,11 @@ static struct proto dccp_v6_prot = {
+ .obj_size = sizeof(struct dccp6_sock),
+ .rsk_prot = &dccp6_request_sock_ops,
+ .twsk_prot = &dccp6_timewait_sock_ops,
+- .hashinfo = &dccp_hashinfo,
++ .h.hashinfo = &dccp_hashinfo,
+ #ifdef CONFIG_COMPAT
+ .compat_setsockopt = compat_dccp_setsockopt,
+ .compat_getsockopt = compat_dccp_getsockopt,
+ #endif
+- REF_PROTO_INUSE(dccp_v6)
+ };
+
+ static struct inet6_protocol dccp_v6_protocol = {
+@@ -1176,6 +1173,25 @@ static struct inet_protosw dccp_v6_protosw = {
+ .flags = INET_PROTOSW_ICSK,
+ };
+
++static int dccp_v6_init_net(struct net *net)
++{
++ int err;
++
++ err = inet_ctl_sock_create(&net->dccp.v6_ctl_sk, PF_INET6,
++ SOCK_DCCP, IPPROTO_DCCP, net);
++ return err;
++}
++
++static void dccp_v6_exit_net(struct net *net)
++{
++ inet_ctl_sock_destroy(net->dccp.v6_ctl_sk);
++}
++
++static struct pernet_operations dccp_v6_ops = {
++ .init = dccp_v6_init_net,
++ .exit = dccp_v6_exit_net,
++};
++
+ static int __init dccp_v6_init(void)
+ {
+ int err = proto_register(&dccp_v6_prot, 1);
+@@ -1189,13 +1205,13 @@ static int __init dccp_v6_init(void)
+
+ inet6_register_protosw(&dccp_v6_protosw);
+
+- err = inet_csk_ctl_sock_create(&dccp_v6_ctl_socket, PF_INET6,
+- SOCK_DCCP, IPPROTO_DCCP);
++ err = register_pernet_subsys(&dccp_v6_ops);
+ if (err != 0)
+- goto out_unregister_protosw;
++ goto out_destroy_ctl_sock;
+ out:
+ return err;
+-out_unregister_protosw:
++
++out_destroy_ctl_sock:
+ inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
+ inet6_unregister_protosw(&dccp_v6_protosw);
+ out_unregister_proto:
+@@ -1205,6 +1221,7 @@ out_unregister_proto:
+
+ static void __exit dccp_v6_exit(void)
+ {
++ unregister_pernet_subsys(&dccp_v6_ops);
+ inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
+ inet6_unregister_protosw(&dccp_v6_protosw);
+ proto_unregister(&dccp_v6_prot);
+diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
+index 027d181..33ad483 100644
+--- a/net/dccp/minisocks.c
++++ b/net/dccp/minisocks.c
+@@ -216,7 +216,7 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
+ * counter (backoff, monitored by dccp_response_timer).
+ */
+ req->retrans++;
+- req->rsk_ops->rtx_syn_ack(sk, req, NULL);
++ req->rsk_ops->rtx_syn_ack(sk, req);
+ }
+ /* Network Duplicate, discard packet */
+ return NULL;
+diff --git a/net/dccp/output.c b/net/dccp/output.c
+index 3d7d628..1f8a9b6 100644
+--- a/net/dccp/output.c
++++ b/net/dccp/output.c
+@@ -347,7 +347,7 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
+ EXPORT_SYMBOL_GPL(dccp_make_response);
+
+ /* answer offending packet in @rcv_skb with Reset from control socket @ctl */
+-struct sk_buff *dccp_ctl_make_reset(struct socket *ctl, struct sk_buff *rcv_skb)
++struct sk_buff *dccp_ctl_make_reset(struct sock *sk, struct sk_buff *rcv_skb)
+ {
+ struct dccp_hdr *rxdh = dccp_hdr(rcv_skb), *dh;
+ struct dccp_skb_cb *dcb = DCCP_SKB_CB(rcv_skb);
+@@ -357,11 +357,11 @@ struct sk_buff *dccp_ctl_make_reset(struct socket *ctl, struct sk_buff *rcv_skb)
+ struct dccp_hdr_reset *dhr;
+ struct sk_buff *skb;
+
+- skb = alloc_skb(ctl->sk->sk_prot->max_header, GFP_ATOMIC);
++ skb = alloc_skb(sk->sk_prot->max_header, GFP_ATOMIC);
+ if (skb == NULL)
+ return NULL;
+
+- skb_reserve(skb, ctl->sk->sk_prot->max_header);
++ skb_reserve(skb, sk->sk_prot->max_header);
+
+ /* Swap the send and the receive. */
+ dh = dccp_zeroed_hdr(skb, dccp_hdr_reset_len);
+diff --git a/net/dccp/probe.c b/net/dccp/probe.c
+index 7053bb8..0bcdc92 100644
+--- a/net/dccp/probe.c
++++ b/net/dccp/probe.c
+@@ -46,29 +46,24 @@ struct {
+ struct kfifo *fifo;
+ spinlock_t lock;
+ wait_queue_head_t wait;
+- struct timeval tstart;
++ struct timespec tstart;
+ } dccpw;
+
+ static void printl(const char *fmt, ...)
+ {
+ va_list args;
+ int len;
+- struct timeval now;
++ struct timespec now;
+ char tbuf[256];
+
+ va_start(args, fmt);
+- do_gettimeofday(&now);
++ getnstimeofday(&now);
+
+- now.tv_sec -= dccpw.tstart.tv_sec;
+- now.tv_usec -= dccpw.tstart.tv_usec;
+- if (now.tv_usec < 0) {
+- --now.tv_sec;
+- now.tv_usec += 1000000;
+- }
++ now = timespec_sub(now, dccpw.tstart);
+
+ len = sprintf(tbuf, "%lu.%06lu ",
+ (unsigned long) now.tv_sec,
+- (unsigned long) now.tv_usec);
++ (unsigned long) now.tv_nsec / NSEC_PER_USEC);
+ len += vscnprintf(tbuf+len, sizeof(tbuf)-len, fmt, args);
+ va_end(args);
+
+@@ -119,7 +114,7 @@ static struct jprobe dccp_send_probe = {
+ static int dccpprobe_open(struct inode *inode, struct file *file)
+ {
+ kfifo_reset(dccpw.fifo);
+- do_gettimeofday(&dccpw.tstart);
++ getnstimeofday(&dccpw.tstart);
+ return 0;
+ }
+
+@@ -145,7 +140,7 @@ static ssize_t dccpprobe_read(struct file *file, char __user *buf,
+ goto out_free;
+
+ cnt = kfifo_get(dccpw.fifo, tbuf, len);
+- error = copy_to_user(buf, tbuf, cnt);
++ error = copy_to_user(buf, tbuf, cnt) ? -EFAULT : 0;
+
+ out_free:
+ vfree(tbuf);
+diff --git a/net/dccp/proto.c b/net/dccp/proto.c
+index c91d3c1..9dfe247 100644
+--- a/net/dccp/proto.c
++++ b/net/dccp/proto.c
+@@ -27,7 +27,6 @@
+ #include <net/xfrm.h>
+
+ #include <asm/ioctls.h>
+-#include <asm/semaphore.h>
+ #include <linux/spinlock.h>
+ #include <linux/timer.h>
+ #include <linux/delay.h>
+@@ -1010,33 +1009,14 @@ void dccp_shutdown(struct sock *sk, int how)
+
+ EXPORT_SYMBOL_GPL(dccp_shutdown);
+
+-static int __init dccp_mib_init(void)
++static inline int dccp_mib_init(void)
+ {
+- int rc = -ENOMEM;
+-
+- dccp_statistics[0] = alloc_percpu(struct dccp_mib);
+- if (dccp_statistics[0] == NULL)
+- goto out;
+-
+- dccp_statistics[1] = alloc_percpu(struct dccp_mib);
+- if (dccp_statistics[1] == NULL)
+- goto out_free_one;
+-
+- rc = 0;
+-out:
+- return rc;
+-out_free_one:
+- free_percpu(dccp_statistics[0]);
+- dccp_statistics[0] = NULL;
+- goto out;
+-
++ return snmp_mib_init((void**)dccp_statistics, sizeof(struct dccp_mib));
+ }
+
+-static void dccp_mib_exit(void)
++static inline void dccp_mib_exit(void)
+ {
+- free_percpu(dccp_statistics[0]);
+- free_percpu(dccp_statistics[1]);
+- dccp_statistics[0] = dccp_statistics[1] = NULL;
++ snmp_mib_free((void**)dccp_statistics);
+ }
+
+ static int thash_entries;
+diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
+index acd48ee..fc2efe8 100644
+--- a/net/decnet/af_decnet.c
++++ b/net/decnet/af_decnet.c
+@@ -1094,7 +1094,7 @@ static int dn_accept(struct socket *sock, struct socket *newsock, int flags)
+
+ cb = DN_SKB_CB(skb);
+ sk->sk_ack_backlog--;
+- newsk = dn_alloc_sock(sk->sk_net, newsock, sk->sk_allocation);
++ newsk = dn_alloc_sock(sock_net(sk), newsock, sk->sk_allocation);
+ if (newsk == NULL) {
+ release_sock(sk);
+ kfree_skb(skb);
+@@ -2089,7 +2089,7 @@ static int dn_device_event(struct notifier_block *this, unsigned long event,
+ {
+ struct net_device *dev = (struct net_device *)ptr;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ switch(event) {
+@@ -2320,25 +2320,8 @@ static const struct seq_operations dn_socket_seq_ops = {
+
+ static int dn_socket_seq_open(struct inode *inode, struct file *file)
+ {
+- struct seq_file *seq;
+- int rc = -ENOMEM;
+- struct dn_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+-
+- if (!s)
+- goto out;
+-
+- rc = seq_open(file, &dn_socket_seq_ops);
+- if (rc)
+- goto out_kfree;
+-
+- seq = file->private_data;
+- seq->private = s;
+- memset(s, 0, sizeof(*s));
+-out:
+- return rc;
+-out_kfree:
+- kfree(s);
+- goto out;
++ return seq_open_private(file, &dn_socket_seq_ops,
++ sizeof(struct dn_iter_state));
+ }
+
+ static const struct file_operations dn_socket_seq_fops = {
+diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
+index 1bbfce5..2f0ac3c 100644
+--- a/net/decnet/dn_dev.c
++++ b/net/decnet/dn_dev.c
+@@ -625,7 +625,7 @@ static const struct nla_policy dn_ifa_policy[IFA_MAX+1] = {
+
+ static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct nlattr *tb[IFA_MAX+1];
+ struct dn_dev *dn_db;
+ struct ifaddrmsg *ifm;
+@@ -663,7 +663,7 @@ errout:
+
+ static int dn_nl_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct nlattr *tb[IFA_MAX+1];
+ struct net_device *dev;
+ struct dn_dev *dn_db;
+@@ -779,7 +779,7 @@ errout:
+
+ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ int idx, dn_idx = 0, skip_ndevs, skip_naddr;
+ struct net_device *dev;
+ struct dn_dev *dn_db;
+diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
+index 4aa9a42..27ea2e9 100644
+--- a/net/decnet/dn_fib.c
++++ b/net/decnet/dn_fib.c
+@@ -504,7 +504,7 @@ static int dn_fib_check_attr(struct rtmsg *r, struct rtattr **rta)
+
+ static int dn_fib_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct dn_fib_table *tb;
+ struct rtattr **rta = arg;
+ struct rtmsg *r = NLMSG_DATA(nlh);
+@@ -524,7 +524,7 @@ static int dn_fib_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *
+
+ static int dn_fib_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct dn_fib_table *tb;
+ struct rtattr **rta = arg;
+ struct rtmsg *r = NLMSG_DATA(nlh);
+diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
+index 9dc0abb..2f665a5 100644
+--- a/net/decnet/dn_route.c
++++ b/net/decnet/dn_route.c
+@@ -580,7 +580,7 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type
+ struct dn_dev *dn = (struct dn_dev *)dev->dn_ptr;
+ unsigned char padlen = 0;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ goto dump_it;
+
+ if (dn == NULL)
+@@ -1512,7 +1512,7 @@ rtattr_failure:
+ */
+ static int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void *arg)
+ {
+- struct net *net = in_skb->sk->sk_net;
++ struct net *net = sock_net(in_skb->sk);
+ struct rtattr **rta = arg;
+ struct rtmsg *rtm = NLMSG_DATA(nlh);
+ struct dn_route *rt = NULL;
+@@ -1601,7 +1601,7 @@ out_free:
+ */
+ int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct dn_route *rt;
+ int h, s_h;
+ int idx, s_idx;
+diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c
+index e09d915..3a2830a 100644
+--- a/net/decnet/dn_table.c
++++ b/net/decnet/dn_table.c
+@@ -463,7 +463,7 @@ static int dn_fib_table_dump(struct dn_fib_table *tb, struct sk_buff *skb,
+
+ int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ unsigned int h, s_h;
+ unsigned int e = 0, s_e;
+ struct dn_fib_table *tb;
+diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
+index bc0f625..68d1544 100644
+--- a/net/econet/af_econet.c
++++ b/net/econet/af_econet.c
+@@ -1064,7 +1064,7 @@ static int econet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
+ struct sock *sk;
+ struct ec_device *edev = dev->ec_ptr;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ goto drop;
+
+ if (skb->pkt_type == PACKET_OTHERHOST)
+@@ -1121,7 +1121,7 @@ static int econet_notifier(struct notifier_block *this, unsigned long msg, void
+ struct net_device *dev = (struct net_device *)data;
+ struct ec_device *edev;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ switch (msg) {
+diff --git a/net/ieee80211/Kconfig b/net/ieee80211/Kconfig
+index bd50104..94ed7d3 100644
+--- a/net/ieee80211/Kconfig
++++ b/net/ieee80211/Kconfig
+@@ -71,4 +71,3 @@ config IEEE80211_CRYPT_TKIP
+ This can be compiled as a module and it will be called
+ "ieee80211_crypt_tkip".
+
+-source "net/ieee80211/softmac/Kconfig"
+diff --git a/net/ieee80211/Makefile b/net/ieee80211/Makefile
+index 796a7c7..f988417 100644
+--- a/net/ieee80211/Makefile
++++ b/net/ieee80211/Makefile
+@@ -10,4 +10,3 @@ ieee80211-objs := \
+ ieee80211_wx.o \
+ ieee80211_geo.o
+
+-obj-$(CONFIG_IEEE80211_SOFTMAC) += softmac/
+diff --git a/net/ieee80211/softmac/Kconfig b/net/ieee80211/softmac/Kconfig
+deleted file mode 100644
+index 2811651..0000000
+--- a/net/ieee80211/softmac/Kconfig
++++ /dev/null
+@@ -1,12 +0,0 @@
+-config IEEE80211_SOFTMAC
+- tristate "Software MAC add-on to the IEEE 802.11 networking stack"
+- depends on IEEE80211 && EXPERIMENTAL
+- select WIRELESS_EXT
+- select IEEE80211_CRYPT_WEP
+- ---help---
+- This option enables the hardware independent software MAC addon
+- for the IEEE 802.11 networking stack.
+-
+-config IEEE80211_SOFTMAC_DEBUG
+- bool "Enable full debugging output"
+- depends on IEEE80211_SOFTMAC
+diff --git a/net/ieee80211/softmac/Makefile b/net/ieee80211/softmac/Makefile
+deleted file mode 100644
+index bfcb391..0000000
+--- a/net/ieee80211/softmac/Makefile
++++ /dev/null
+@@ -1,9 +0,0 @@
+-obj-$(CONFIG_IEEE80211_SOFTMAC) += ieee80211softmac.o
+-ieee80211softmac-objs := \
+- ieee80211softmac_io.o \
+- ieee80211softmac_auth.o \
+- ieee80211softmac_module.o \
+- ieee80211softmac_scan.o \
+- ieee80211softmac_wx.o \
+- ieee80211softmac_assoc.o \
+- ieee80211softmac_event.o
+diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
+deleted file mode 100644
+index c4d122d..0000000
+--- a/net/ieee80211/softmac/ieee80211softmac_assoc.c
++++ /dev/null
+@@ -1,489 +0,0 @@
+-/*
+- * This file contains the softmac's association logic.
+- *
+- * Copyright (c) 2005, 2006 Johannes Berg <johannes at sipsolutions.net>
+- * Joseph Jezak <josejx at gentoo.org>
+- * Larry Finger <Larry.Finger at lwfinger.net>
+- * Danny van Dyk <kugelfang at gentoo.org>
+- * Michael Buesch <mbuesch at freenet.de>
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of version 2 of the GNU General Public License as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+- *
+- * The full GNU General Public License is included in this distribution in the
+- * file called COPYING.
+- */
+-
+-#include "ieee80211softmac_priv.h"
+-
+-/*
+- * Overview
+- *
+- * Before you can associate, you have to authenticate.
+- *
+- */
+-
+-/* Sends out an association request to the desired AP */
+-static void
+-ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net)
+-{
+- unsigned long flags;
+-
+- /* Switch to correct channel for this network */
+- mac->set_channel(mac->dev, net->channel);
+-
+- /* Send association request */
+- ieee80211softmac_send_mgt_frame(mac, net, IEEE80211_STYPE_ASSOC_REQ, 0);
+-
+- dprintk(KERN_INFO PFX "sent association request!\n");
+-
+- spin_lock_irqsave(&mac->lock, flags);
+- mac->associnfo.associated = 0; /* just to make sure */
+-
+- /* Set a timer for timeout */
+- /* FIXME: make timeout configurable */
+- if (likely(mac->running))
+- queue_delayed_work(mac->wq, &mac->associnfo.timeout, 5 * HZ);
+- spin_unlock_irqrestore(&mac->lock, flags);
+-}
+-
+-void
+-ieee80211softmac_assoc_timeout(struct work_struct *work)
+-{
+- struct ieee80211softmac_device *mac =
+- container_of(work, struct ieee80211softmac_device,
+- associnfo.timeout.work);
+- struct ieee80211softmac_network *n;
+-
+- mutex_lock(&mac->associnfo.mutex);
+- /* we might race against ieee80211softmac_handle_assoc_response,
+- * so make sure only one of us does something */
+- if (!mac->associnfo.associating)
+- goto out;
+- mac->associnfo.associating = 0;
+- mac->associnfo.bssvalid = 0;
+- mac->associnfo.associated = 0;
+-
+- n = ieee80211softmac_get_network_by_bssid_locked(mac, mac->associnfo.bssid);
+-
+- dprintk(KERN_INFO PFX "assoc request timed out!\n");
+- ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, n);
+-out:
+- mutex_unlock(&mac->associnfo.mutex);
+-}
+-
+-void
+-ieee80211softmac_disassoc(struct ieee80211softmac_device *mac)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&mac->lock, flags);
+- if (mac->associnfo.associating)
+- cancel_delayed_work(&mac->associnfo.timeout);
+-
+- netif_carrier_off(mac->dev);
+-
+- mac->associnfo.associated = 0;
+- mac->associnfo.bssvalid = 0;
+- mac->associnfo.associating = 0;
+- ieee80211softmac_init_bss(mac);
+- ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
+- spin_unlock_irqrestore(&mac->lock, flags);
+-}
+-
+-/* Sends out a disassociation request to the desired AP */
+-void
+-ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reason)
+-{
+- struct ieee80211softmac_network *found;
+-
+- if (mac->associnfo.bssvalid && mac->associnfo.associated) {
+- found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
+- if (found)
+- ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason);
+- }
+-
+- ieee80211softmac_disassoc(mac);
+-}
+-
+-static inline int
+-we_support_all_basic_rates(struct ieee80211softmac_device *mac, u8 *from, u8 from_len)
+-{
+- int idx;
+- u8 rate;
+-
+- for (idx = 0; idx < (from_len); idx++) {
+- rate = (from)[idx];
+- if (!(rate & IEEE80211_BASIC_RATE_MASK))
+- continue;
+- rate &= ~IEEE80211_BASIC_RATE_MASK;
+- if (!ieee80211softmac_ratesinfo_rate_supported(&mac->ratesinfo, rate))
+- return 0;
+- }
+- return 1;
+-}
+-
+-static int
+-network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_network *net)
+-{
+- /* we cannot associate to networks whose name we don't know */
+- if (ieee80211_is_empty_essid(net->ssid, net->ssid_len))
+- return 0;
+- /* do not associate to a network whose BSSBasicRateSet we cannot support */
+- if (!we_support_all_basic_rates(mac, net->rates, net->rates_len))
+- return 0;
+- /* do we really need to check the ex rates? */
+- if (!we_support_all_basic_rates(mac, net->rates_ex, net->rates_ex_len))
+- return 0;
+-
+- /* assume that users know what they're doing ...
+- * (note we don't let them select a net we're incompatible with) */
+- if (mac->associnfo.bssfixed) {
+- return !memcmp(mac->associnfo.bssid, net->bssid, ETH_ALEN);
+- }
+-
+- /* if 'ANY' network requested, take any that doesn't have privacy enabled */
+- if (mac->associnfo.req_essid.len == 0
+- && !(net->capability & WLAN_CAPABILITY_PRIVACY))
+- return 1;
+- if (net->ssid_len != mac->associnfo.req_essid.len)
+- return 0;
+- if (!memcmp(net->ssid, mac->associnfo.req_essid.data, mac->associnfo.req_essid.len))
+- return 1;
+- return 0;
+-}
+-
+-static void
+-ieee80211softmac_assoc_notify_scan(struct net_device *dev, int event_type, void *context)
+-{
+- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+- ieee80211softmac_assoc_work(&mac->associnfo.work.work);
+-}
+-
+-static void
+-ieee80211softmac_assoc_notify_auth(struct net_device *dev, int event_type, void *context)
+-{
+- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+-
+- switch (event_type) {
+- case IEEE80211SOFTMAC_EVENT_AUTHENTICATED:
+- ieee80211softmac_assoc_work(&mac->associnfo.work.work);
+- break;
+- case IEEE80211SOFTMAC_EVENT_AUTH_FAILED:
+- case IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT:
+- ieee80211softmac_disassoc(mac);
+- break;
+- }
+-}
+-
+-/* This function is called to handle userspace requests (asynchronously) */
+-void
+-ieee80211softmac_assoc_work(struct work_struct *work)
+-{
+- struct ieee80211softmac_device *mac =
+- container_of(work, struct ieee80211softmac_device,
+- associnfo.work.work);
+- struct ieee80211softmac_network *found = NULL;
+- struct ieee80211_network *net = NULL, *best = NULL;
+- int bssvalid;
+- unsigned long flags;
+-
+- mutex_lock(&mac->associnfo.mutex);
+-
+- if (!mac->associnfo.associating)
+- goto out;
+-
+- /* ieee80211_disassoc might clear this */
+- bssvalid = mac->associnfo.bssvalid;
+-
+- /* meh */
+- if (mac->associnfo.associated)
+- ieee80211softmac_send_disassoc_req(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
+-
+- /* try to find the requested network in our list, if we found one already */
+- if (bssvalid || mac->associnfo.bssfixed)
+- found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
+-
+- /* Search the ieee80211 networks for this network if we didn't find it by bssid,
+- * but only if we've scanned at least once (to get a better list of networks to
+- * select from). If we have not scanned before, the !found logic below will be
+- * invoked and will scan. */
+- if (!found && (mac->associnfo.scan_retry < IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT))
+- {
+- s8 rssi = -128; /* if I don't initialise, gcc emits an invalid warning
+- because it cannot follow the best pointer logic. */
+- spin_lock_irqsave(&mac->ieee->lock, flags);
+- list_for_each_entry(net, &mac->ieee->network_list, list) {
+- /* we're supposed to find the network with
+- * the best signal here, as we're asked to join
+- * any network with a specific ESSID, and many
+- * different ones could have that.
+- *
+- * I'll for now just go with the reported rssi.
+- *
+- * We also should take into account the rateset
+- * here to find the best BSSID to try.
+- */
+- if (network_matches_request(mac, net)) {
+- if (!best) {
+- best = net;
+- rssi = best->stats.rssi;
+- continue;
+- }
+- /* we already had a matching network, so
+- * compare their properties to get the
+- * better of the two ... (see above)
+- */
+- if (rssi < net->stats.rssi) {
+- best = net;
+- rssi = best->stats.rssi;
+- }
+- }
+- }
+- /* if we unlock here, we might get interrupted and the `best'
+- * pointer could go stale */
+- if (best) {
+- found = ieee80211softmac_create_network(mac, best);
+- /* if found is still NULL, then we got -ENOMEM somewhere */
+- if (found)
+- ieee80211softmac_add_network(mac, found);
+- }
+- spin_unlock_irqrestore(&mac->ieee->lock, flags);
+- }
+-
+- if (!found) {
+- if (mac->associnfo.scan_retry > 0) {
+- mac->associnfo.scan_retry--;
+-
+- /* We know of no such network. Let's scan.
+- * NB: this also happens if we had no memory to copy the network info...
+- * Maybe we can hope to have more memory after scanning finishes ;)
+- */
+- dprintk(KERN_INFO PFX "Associate: Scanning for networks first.\n");
+- ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL);
+- if (ieee80211softmac_start_scan(mac)) {
+- dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
+- }
+- goto out;
+- } else {
+- mac->associnfo.associating = 0;
+- mac->associnfo.associated = 0;
+-
+- dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n");
+- /* reset the retry counter for the next user request since we
+- * break out and don't reschedule ourselves after this point. */
+- mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
+- ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL);
+- goto out;
+- }
+- }
+-
+- /* reset the retry counter for the next user request since we
+- * now found a net and will try to associate to it, but not
+- * schedule this function again. */
+- mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
+- mac->associnfo.bssvalid = 1;
+- memcpy(mac->associnfo.bssid, found->bssid, ETH_ALEN);
+- /* copy the ESSID for displaying it */
+- mac->associnfo.associate_essid.len = found->essid.len;
+- memcpy(mac->associnfo.associate_essid.data, found->essid.data, IW_ESSID_MAX_SIZE + 1);
+-
+- /* we found a network! authenticate (if necessary) and associate to it. */
+- if (found->authenticating) {
+- dprintk(KERN_INFO PFX "Already requested authentication, waiting...\n");
+- if(!mac->associnfo.assoc_wait) {
+- mac->associnfo.assoc_wait = 1;
+- ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL);
+- }
+- goto out;
+- }
+- if (!found->authenticated && !found->authenticating) {
+- /* This relies on the fact that _auth_req only queues the work,
+- * otherwise adding the notification would be racy. */
+- if (!ieee80211softmac_auth_req(mac, found)) {
+- if(!mac->associnfo.assoc_wait) {
+- dprintk(KERN_INFO PFX "Cannot associate without being authenticated, requested authentication\n");
+- mac->associnfo.assoc_wait = 1;
+- ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL);
+- }
+- } else {
+- printkl(KERN_WARNING PFX "Not authenticated, but requesting authentication failed. Giving up to associate\n");
+- mac->associnfo.assoc_wait = 0;
+- ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found);
+- }
+- goto out;
+- }
+- /* finally! now we can start associating */
+- mac->associnfo.assoc_wait = 0;
+- ieee80211softmac_assoc(mac, found);
+-
+-out:
+- mutex_unlock(&mac->associnfo.mutex);
+-}
+-
+-/* call this to do whatever is necessary when we're associated */
+-static void
+-ieee80211softmac_associated(struct ieee80211softmac_device *mac,
+- struct ieee80211_assoc_response * resp,
+- struct ieee80211softmac_network *net)
+-{
+- u16 cap = le16_to_cpu(resp->capability);
+- u8 erp_value = net->erp_value;
+-
+- mac->associnfo.associating = 0;
+- mac->bssinfo.supported_rates = net->supported_rates;
+- ieee80211softmac_recalc_txrates(mac);
+-
+- mac->associnfo.associated = 1;
+-
+- mac->associnfo.short_preamble_available =
+- (cap & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0;
+- ieee80211softmac_process_erp(mac, erp_value);
+-
+- if (mac->set_bssid_filter)
+- mac->set_bssid_filter(mac->dev, net->bssid);
+- memcpy(mac->ieee->bssid, net->bssid, ETH_ALEN);
+- netif_carrier_on(mac->dev);
+-
+- mac->association_id = le16_to_cpup(&resp->aid);
+-}
+-
+-/* received frame handling functions */
+-int
+-ieee80211softmac_handle_assoc_response(struct net_device * dev,
+- struct ieee80211_assoc_response * resp,
+- struct ieee80211_network * _ieee80211_network)
+-{
+- /* NOTE: the network parameter has to be mostly ignored by
+- * this code because it is the ieee80211's pointer
+- * to the struct, not ours (we made a copy)
+- */
+- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+- u16 status = le16_to_cpup(&resp->status);
+- struct ieee80211softmac_network *network = NULL;
+- unsigned long flags;
+- DECLARE_MAC_BUF(mac2);
+-
+- if (unlikely(!mac->running))
+- return -ENODEV;
+-
+- spin_lock_irqsave(&mac->lock, flags);
+-
+- if (!mac->associnfo.associating) {
+- /* we race against the timeout function, so make sure
+- * only one of us can do work */
+- spin_unlock_irqrestore(&mac->lock, flags);
+- return 0;
+- }
+- network = ieee80211softmac_get_network_by_bssid_locked(mac, resp->header.addr3);
+-
+- /* someone sending us things without us knowing him? Ignore. */
+- if (!network) {
+- dprintk(KERN_INFO PFX "Received unrequested assocation response from %s\n",
+- print_mac(mac2, resp->header.addr3));
+- spin_unlock_irqrestore(&mac->lock, flags);
+- return 0;
+- }
+-
+- /* now that we know it was for us, we can cancel the timeout */
+- cancel_delayed_work(&mac->associnfo.timeout);
+-
+- /* if the association response included an ERP IE, update our saved
+- * copy */
+- if (_ieee80211_network->flags & NETWORK_HAS_ERP_VALUE)
+- network->erp_value = _ieee80211_network->erp_value;
+-
+- switch (status) {
+- case 0:
+- dprintk(KERN_INFO PFX "associated!\n");
+- ieee80211softmac_associated(mac, resp, network);
+- ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATED, network);
+- break;
+- case WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH:
+- if (!network->auth_desynced_once) {
+- /* there seem to be a few rare cases where our view of
+- * the world is obscured, or buggy APs that don't DEAUTH
+- * us properly. So we handle that, but allow it only once.
+- */
+- printkl(KERN_INFO PFX "We were not authenticated during association, retrying...\n");
+- network->authenticated = 0;
+- /* we don't want to do this more than once ... */
+- network->auth_desynced_once = 1;
+- queue_delayed_work(mac->wq, &mac->associnfo.work, 0);
+- break;
+- }
+- default:
+- dprintk(KERN_INFO PFX "associating failed (reason: 0x%x)!\n", status);
+- mac->associnfo.associating = 0;
+- mac->associnfo.bssvalid = 0;
+- mac->associnfo.associated = 0;
+- ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, network);
+- }
+-
+- spin_unlock_irqrestore(&mac->lock, flags);
+- return 0;
+-}
+-
+-void
+-ieee80211softmac_try_reassoc(struct ieee80211softmac_device *mac)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&mac->lock, flags);
+- mac->associnfo.associating = 1;
+- queue_delayed_work(mac->wq, &mac->associnfo.work, 0);
+- spin_unlock_irqrestore(&mac->lock, flags);
+-}
+-
+-int
+-ieee80211softmac_handle_disassoc(struct net_device * dev,
+- struct ieee80211_disassoc *disassoc)
+-{
+- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+-
+- if (unlikely(!mac->running))
+- return -ENODEV;
+-
+- if (memcmp(disassoc->header.addr2, mac->associnfo.bssid, ETH_ALEN))
+- return 0;
+-
+- if (memcmp(disassoc->header.addr1, mac->dev->dev_addr, ETH_ALEN))
+- return 0;
+-
+- dprintk(KERN_INFO PFX "got disassoc frame\n");
+- ieee80211softmac_disassoc(mac);
+-
+- ieee80211softmac_try_reassoc(mac);
+-
+- return 0;
+-}
+-
+-int
+-ieee80211softmac_handle_reassoc_req(struct net_device * dev,
+- struct ieee80211_reassoc_request * resp)
+-{
+- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+- struct ieee80211softmac_network *network;
+-
+- if (unlikely(!mac->running))
+- return -ENODEV;
+-
+- network = ieee80211softmac_get_network_by_bssid(mac, resp->header.addr3);
+- if (!network) {
+- dprintkl(KERN_INFO PFX "reassoc request from unknown network\n");
+- return 0;
+- }
+- queue_delayed_work(mac->wq, &mac->associnfo.work, 0);
+-
+- return 0;
+-}
+diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c
+deleted file mode 100644
+index 1a96c25..0000000
+--- a/net/ieee80211/softmac/ieee80211softmac_auth.c
++++ /dev/null
+@@ -1,413 +0,0 @@
+-/*
+- * This file contains the softmac's authentication logic.
+- *
+- * Copyright (c) 2005, 2006 Johannes Berg <johannes at sipsolutions.net>
+- * Joseph Jezak <josejx at gentoo.org>
+- * Larry Finger <Larry.Finger at lwfinger.net>
+- * Danny van Dyk <kugelfang at gentoo.org>
+- * Michael Buesch <mbuesch at freenet.de>
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of version 2 of the GNU General Public License as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+- *
+- * The full GNU General Public License is included in this distribution in the
+- * file called COPYING.
+- */
+-
+-#include "ieee80211softmac_priv.h"
+-
+-static void ieee80211softmac_auth_queue(struct work_struct *work);
+-
+-/* Queues an auth request to the desired AP */
+-int
+-ieee80211softmac_auth_req(struct ieee80211softmac_device *mac,
+- struct ieee80211softmac_network *net)
+-{
+- struct ieee80211softmac_auth_queue_item *auth;
+- unsigned long flags;
+- DECLARE_MAC_BUF(mac2);
+-
+- if (net->authenticating || net->authenticated)
+- return 0;
+- net->authenticating = 1;
+-
+- /* Add the network if it's not already added */
+- ieee80211softmac_add_network(mac, net);
+-
+- dprintk(KERN_NOTICE PFX "Queueing Authentication Request to %s\n", print_mac(mac2, net->bssid));
+- /* Queue the auth request */
+- auth = (struct ieee80211softmac_auth_queue_item *)
+- kmalloc(sizeof(struct ieee80211softmac_auth_queue_item), GFP_KERNEL);
+- if(auth == NULL)
+- return -ENOMEM;
+-
+- auth->net = net;
+- auth->mac = mac;
+- auth->retry = IEEE80211SOFTMAC_AUTH_RETRY_LIMIT;
+- auth->state = IEEE80211SOFTMAC_AUTH_OPEN_REQUEST;
+- INIT_DELAYED_WORK(&auth->work, ieee80211softmac_auth_queue);
+-
+- /* Lock (for list) */
+- spin_lock_irqsave(&mac->lock, flags);
+-
+- /* add to list */
+- list_add_tail(&auth->list, &mac->auth_queue);
+- queue_delayed_work(mac->wq, &auth->work, 0);
+- spin_unlock_irqrestore(&mac->lock, flags);
+-
+- return 0;
+-}
+-
+-
+-/* Sends an auth request to the desired AP and handles timeouts */
+-static void
+-ieee80211softmac_auth_queue(struct work_struct *work)
+-{
+- struct ieee80211softmac_device *mac;
+- struct ieee80211softmac_auth_queue_item *auth;
+- struct ieee80211softmac_network *net;
+- unsigned long flags;
+- DECLARE_MAC_BUF(mac2);
+-
+- auth = container_of(work, struct ieee80211softmac_auth_queue_item,
+- work.work);
+- net = auth->net;
+- mac = auth->mac;
+-
+- if(auth->retry > 0) {
+- /* Switch to correct channel for this network */
+- mac->set_channel(mac->dev, net->channel);
+-
+- /* Lock and set flags */
+- spin_lock_irqsave(&mac->lock, flags);
+- if (unlikely(!mac->running)) {
+- /* Prevent reschedule on workqueue flush */
+- spin_unlock_irqrestore(&mac->lock, flags);
+- return;
+- }
+- net->authenticated = 0;
+- /* add a timeout call so we eventually give up waiting for an auth reply */
+- queue_delayed_work(mac->wq, &auth->work, IEEE80211SOFTMAC_AUTH_TIMEOUT);
+- auth->retry--;
+- spin_unlock_irqrestore(&mac->lock, flags);
+- if (ieee80211softmac_send_mgt_frame(mac, auth->net, IEEE80211_STYPE_AUTH, auth->state))
+- dprintk(KERN_NOTICE PFX "Sending Authentication Request to %s failed (this shouldn't happen, wait for the timeout).\n",
+- print_mac(mac2, net->bssid));
+- else
+- dprintk(KERN_NOTICE PFX "Sent Authentication Request to %s.\n", print_mac(mac2, net->bssid));
+- return;
+- }
+-
+- printkl(KERN_WARNING PFX "Authentication timed out with %s\n", print_mac(mac2, net->bssid));
+- /* Remove this item from the queue */
+- spin_lock_irqsave(&mac->lock, flags);
+- net->authenticating = 0;
+- ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT, net);
+- cancel_delayed_work(&auth->work); /* just to make sure... */
+- list_del(&auth->list);
+- spin_unlock_irqrestore(&mac->lock, flags);
+- /* Free it */
+- kfree(auth);
+-}
+-
+-/* Sends a response to an auth challenge (for shared key auth). */
+-static void
+-ieee80211softmac_auth_challenge_response(struct work_struct *work)
+-{
+- struct ieee80211softmac_auth_queue_item *aq =
+- container_of(work, struct ieee80211softmac_auth_queue_item,
+- work.work);
+-
+- /* Send our response */
+- ieee80211softmac_send_mgt_frame(aq->mac, aq->net, IEEE80211_STYPE_AUTH, aq->state);
+-}
+-
+-/* Handle the auth response from the AP
+- * This should be registered with ieee80211 as handle_auth
+- */
+-int
+-ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
+-{
+-
+- struct list_head *list_ptr;
+- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+- struct ieee80211softmac_auth_queue_item *aq = NULL;
+- struct ieee80211softmac_network *net = NULL;
+- unsigned long flags;
+- u8 * data;
+- DECLARE_MAC_BUF(mac2);
+-
+- if (unlikely(!mac->running))
+- return -ENODEV;
+-
+- /* Find correct auth queue item */
+- spin_lock_irqsave(&mac->lock, flags);
+- list_for_each(list_ptr, &mac->auth_queue) {
+- aq = list_entry(list_ptr, struct ieee80211softmac_auth_queue_item, list);
+- net = aq->net;
+- if (!memcmp(net->bssid, auth->header.addr2, ETH_ALEN))
+- break;
+- else
+- aq = NULL;
+- }
+- spin_unlock_irqrestore(&mac->lock, flags);
+-
+- /* Make sure that we've got an auth queue item for this request */
+- if(aq == NULL)
+- {
+- dprintkl(KERN_DEBUG PFX "Authentication response received from %s but no queue item exists.\n", print_mac(mac2, auth->header.addr2));
+- /* Error #? */
+- return -1;
+- }
+-
+- /* Check for out of order authentication */
+- if(!net->authenticating)
+- {
+- dprintkl(KERN_DEBUG PFX "Authentication response received from %s but did not request authentication.\n",print_mac(mac2, auth->header.addr2));
+- return -1;
+- }
+-
+- /* Parse the auth packet */
+- switch(le16_to_cpu(auth->algorithm)) {
+- case WLAN_AUTH_OPEN:
+- /* Check the status code of the response */
+-
+- switch(le16_to_cpu(auth->status)) {
+- case WLAN_STATUS_SUCCESS:
+- /* Update the status to Authenticated */
+- spin_lock_irqsave(&mac->lock, flags);
+- net->authenticating = 0;
+- net->authenticated = 1;
+- spin_unlock_irqrestore(&mac->lock, flags);
+-
+- /* Send event */
+- printkl(KERN_NOTICE PFX "Open Authentication completed with %s\n", print_mac(mac2, net->bssid));
+- ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net);
+- break;
+- default:
+- /* Lock and reset flags */
+- spin_lock_irqsave(&mac->lock, flags);
+- net->authenticated = 0;
+- net->authenticating = 0;
+- spin_unlock_irqrestore(&mac->lock, flags);
+-
+- printkl(KERN_NOTICE PFX "Open Authentication with %s failed, error code: %i\n",
+- print_mac(mac2, net->bssid), le16_to_cpup(&auth->status));
+- /* Count the error? */
+- break;
+- }
+- goto free_aq;
+- break;
+- case WLAN_AUTH_SHARED_KEY:
+- /* Figure out where we are in the process */
+- switch(le16_to_cpu(auth->transaction)) {
+- case IEEE80211SOFTMAC_AUTH_SHARED_CHALLENGE:
+- /* Check to make sure we have a challenge IE */
+- data = (u8 *)auth->info_element;
+- if (*data++ != MFIE_TYPE_CHALLENGE) {
+- printkl(KERN_NOTICE PFX "Shared Key Authentication failed due to a missing challenge.\n");
+- break;
+- }
+- /* Save the challenge */
+- spin_lock_irqsave(&mac->lock, flags);
+- net->challenge_len = *data++;
+- if (net->challenge_len > WLAN_AUTH_CHALLENGE_LEN)
+- net->challenge_len = WLAN_AUTH_CHALLENGE_LEN;
+- kfree(net->challenge);
+- net->challenge = kmemdup(data, net->challenge_len,
+- GFP_ATOMIC);
+- if (net->challenge == NULL) {
+- printkl(KERN_NOTICE PFX "Shared Key "
+- "Authentication failed due to "
+- "memory shortage.\n");
+- spin_unlock_irqrestore(&mac->lock, flags);
+- break;
+- }
+- aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE;
+-
+- /* We reuse the work struct from the auth request here.
+- * It is safe to do so as each one is per-request, and
+- * at this point (dealing with authentication response)
+- * we have obviously already sent the initial auth
+- * request. */
+- cancel_delayed_work(&aq->work);
+- INIT_DELAYED_WORK(&aq->work, &ieee80211softmac_auth_challenge_response);
+- queue_delayed_work(mac->wq, &aq->work, 0);
+- spin_unlock_irqrestore(&mac->lock, flags);
+- return 0;
+- case IEEE80211SOFTMAC_AUTH_SHARED_PASS:
+- kfree(net->challenge);
+- net->challenge = NULL;
+- net->challenge_len = 0;
+- /* Check the status code of the response */
+- switch(auth->status) {
+- case WLAN_STATUS_SUCCESS:
+- /* Update the status to Authenticated */
+- spin_lock_irqsave(&mac->lock, flags);
+- net->authenticating = 0;
+- net->authenticated = 1;
+- spin_unlock_irqrestore(&mac->lock, flags);
+- printkl(KERN_NOTICE PFX "Shared Key Authentication completed with %s\n",
+- print_mac(mac2, net->bssid));
+- ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net);
+- break;
+- default:
+- printkl(KERN_NOTICE PFX "Shared Key Authentication with %s failed, error code: %i\n",
+- print_mac(mac2, net->bssid), le16_to_cpup(&auth->status));
+- /* Lock and reset flags */
+- spin_lock_irqsave(&mac->lock, flags);
+- net->authenticating = 0;
+- net->authenticated = 0;
+- spin_unlock_irqrestore(&mac->lock, flags);
+- /* Count the error? */
+- break;
+- }
+- goto free_aq;
+- break;
+- default:
+- printkl(KERN_WARNING PFX "Unhandled Authentication Step: %i\n", auth->transaction);
+- break;
+- }
+- goto free_aq;
+- break;
+- default:
+- /* ERROR */
+- goto free_aq;
+- break;
+- }
+- return 0;
+-free_aq:
+- /* Cancel the timeout */
+- spin_lock_irqsave(&mac->lock, flags);
+- cancel_delayed_work(&aq->work);
+- /* Remove this item from the queue */
+- list_del(&aq->list);
+- spin_unlock_irqrestore(&mac->lock, flags);
+-
+- /* Free it */
+- kfree(aq);
+- return 0;
+-}
+-
+-/*
+- * Handle deauthorization
+- */
+-static void
+-ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac,
+- struct ieee80211softmac_network *net)
+-{
+- struct ieee80211softmac_auth_queue_item *aq = NULL;
+- struct list_head *list_ptr;
+- unsigned long flags;
+-
+- /* deauthentication implies disassociation */
+- ieee80211softmac_disassoc(mac);
+-
+- /* Lock and reset status flags */
+- spin_lock_irqsave(&mac->lock, flags);
+- net->authenticating = 0;
+- net->authenticated = 0;
+-
+- /* Find correct auth queue item, if it exists */
+- list_for_each(list_ptr, &mac->auth_queue) {
+- aq = list_entry(list_ptr, struct ieee80211softmac_auth_queue_item, list);
+- if (!memcmp(net->bssid, aq->net->bssid, ETH_ALEN))
+- break;
+- else
+- aq = NULL;
+- }
+-
+- /* Cancel pending work */
+- if(aq != NULL)
+- /* Not entirely safe? What about running work? */
+- cancel_delayed_work(&aq->work);
+-
+- /* Free our network ref */
+- ieee80211softmac_del_network_locked(mac, net);
+- if(net->challenge != NULL)
+- kfree(net->challenge);
+- kfree(net);
+-
+- /* can't transmit data right now... */
+- netif_carrier_off(mac->dev);
+- spin_unlock_irqrestore(&mac->lock, flags);
+-
+- ieee80211softmac_try_reassoc(mac);
+-}
+-
+-/*
+- * Sends a deauth request to the desired AP
+- */
+-int
+-ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac,
+- struct ieee80211softmac_network *net, int reason)
+-{
+- int ret;
+-
+- /* Make sure the network is authenticated */
+- if (!net->authenticated)
+- {
+- dprintkl(KERN_DEBUG PFX "Can't send deauthentication packet, network is not authenticated.\n");
+- /* Error okay? */
+- return -EPERM;
+- }
+-
+- /* Send the de-auth packet */
+- if((ret = ieee80211softmac_send_mgt_frame(mac, net, IEEE80211_STYPE_DEAUTH, reason)))
+- return ret;
+-
+- ieee80211softmac_deauth_from_net(mac, net);
+- return 0;
+-}
+-
+-/*
+- * This should be registered with ieee80211 as handle_deauth
+- */
+-int
+-ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *deauth)
+-{
+-
+- struct ieee80211softmac_network *net = NULL;
+- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+- DECLARE_MAC_BUF(mac2);
+-
+- if (unlikely(!mac->running))
+- return -ENODEV;
+-
+- if (!deauth) {
+- dprintk("deauth without deauth packet. eek!\n");
+- return 0;
+- }
+-
+- net = ieee80211softmac_get_network_by_bssid(mac, deauth->header.addr2);
+-
+- if (net == NULL) {
+- dprintkl(KERN_DEBUG PFX "Received deauthentication packet from %s, but that network is unknown.\n",
+- print_mac(mac2, deauth->header.addr2));
+- return 0;
+- }
+-
+- /* Make sure the network is authenticated */
+- if(!net->authenticated)
+- {
+- dprintkl(KERN_DEBUG PFX "Can't perform deauthentication, network is not authenticated.\n");
+- /* Error okay? */
+- return -EPERM;
+- }
+-
+- ieee80211softmac_deauth_from_net(mac, net);
+-
+- /* let's try to re-associate */
+- queue_delayed_work(mac->wq, &mac->associnfo.work, 0);
+- return 0;
+-}
+diff --git a/net/ieee80211/softmac/ieee80211softmac_event.c b/net/ieee80211/softmac/ieee80211softmac_event.c
+deleted file mode 100644
+index 8cef05b..0000000
+--- a/net/ieee80211/softmac/ieee80211softmac_event.c
++++ /dev/null
+@@ -1,189 +0,0 @@
+-/*
+- * Event system
+- * Also see comments in public header file and longer explanation below.
+- *
+- * Copyright (c) 2005, 2006 Johannes Berg <johannes at sipsolutions.net>
+- * Joseph Jezak <josejx at gentoo.org>
+- * Larry Finger <Larry.Finger at lwfinger.net>
+- * Danny van Dyk <kugelfang at gentoo.org>
+- * Michael Buesch <mbuesch at freenet.de>
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of version 2 of the GNU General Public License as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+- *
+- * The full GNU General Public License is included in this distribution in the
+- * file called COPYING.
+- */
+-
+-#include "ieee80211softmac_priv.h"
+-
+-/*
+- * Each event has associated to it
+- * - an event type (see constants in public header)
+- * - an event context (see below)
+- * - the function to be called
+- * - a context (extra parameter to call the function with)
+- * - and the softmac struct
+- *
+- * The event context is private and can only be used from
+- * within this module. Its meaning varies with the event
+- * type:
+- * SCAN_FINISHED,
+- * DISASSOCIATED: NULL
+- * ASSOCIATED,
+- * ASSOCIATE_FAILED,
+- * ASSOCIATE_TIMEOUT,
+- * AUTHENTICATED,
+- * AUTH_FAILED,
+- * AUTH_TIMEOUT: a pointer to the network struct
+- * ...
+- * Code within this module can use the event context to be only
+- * called when the event is true for that specific context
+- * as per above table.
+- * If the event context is NULL, then the notification is always called,
+- * regardless of the event context. The event context is not passed to
+- * the callback, it is assumed that the context suffices.
+- *
+- * You can also use the event context only by setting the event type
+- * to -1 (private use only), in which case you'll be notified
+- * whenever the event context matches.
+- */
+-
+-static char *event_descriptions[IEEE80211SOFTMAC_EVENT_LAST+1] = {
+- NULL, /* scan finished */
+- NULL, /* associated */
+- "associating failed",
+- "associating timed out",
+- "authenticated",
+- "authenticating failed",
+- "authenticating timed out",
+- "associating failed because no suitable network was found",
+- NULL, /* disassociated */
+-};
+-
+-
+-static void
+-ieee80211softmac_notify_callback(struct work_struct *work)
+-{
+- struct ieee80211softmac_event *pevent =
+- container_of(work, struct ieee80211softmac_event, work.work);
+- struct ieee80211softmac_event event = *pevent;
+- kfree(pevent);
+-
+- event.fun(event.mac->dev, event.event_type, event.context);
+-}
+-
+-int
+-ieee80211softmac_notify_internal(struct ieee80211softmac_device *mac,
+- int event, void *event_context, notify_function_ptr fun, void *context, gfp_t gfp_mask)
+-{
+- struct ieee80211softmac_event *eventptr;
+- unsigned long flags;
+-
+- if (event < -1 || event > IEEE80211SOFTMAC_EVENT_LAST)
+- return -ENOSYS;
+-
+- if (!fun)
+- return -EINVAL;
+-
+- eventptr = kmalloc(sizeof(struct ieee80211softmac_event), gfp_mask);
+- if (!eventptr)
+- return -ENOMEM;
+-
+- eventptr->event_type = event;
+- INIT_DELAYED_WORK(&eventptr->work, ieee80211softmac_notify_callback);
+- eventptr->fun = fun;
+- eventptr->context = context;
+- eventptr->mac = mac;
+- eventptr->event_context = event_context;
+-
+- spin_lock_irqsave(&mac->lock, flags);
+- list_add(&eventptr->list, &mac->events);
+- spin_unlock_irqrestore(&mac->lock, flags);
+-
+- return 0;
+-}
+-
+-int
+-ieee80211softmac_notify_gfp(struct net_device *dev,
+- int event, notify_function_ptr fun, void *context, gfp_t gfp_mask)
+-{
+- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+-
+- if (event < 0 || event > IEEE80211SOFTMAC_EVENT_LAST)
+- return -ENOSYS;
+-
+- return ieee80211softmac_notify_internal(mac, event, NULL, fun, context, gfp_mask);
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_notify_gfp);
+-
+-/* private -- calling all callbacks that were specified */
+-void
+-ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_ctx)
+-{
+- struct ieee80211softmac_event *eventptr, *tmp;
+- struct ieee80211softmac_network *network;
+-
+- if (event >= 0) {
+- union iwreq_data wrqu;
+- int we_event;
+- char *msg = NULL;
+-
+- memset(&wrqu, '\0', sizeof (union iwreq_data));
+-
+- switch(event) {
+- case IEEE80211SOFTMAC_EVENT_ASSOCIATED:
+- network = (struct ieee80211softmac_network *)event_ctx;
+- memcpy(wrqu.ap_addr.sa_data, &network->bssid[0], ETH_ALEN);
+- /* fall through */
+- case IEEE80211SOFTMAC_EVENT_DISASSOCIATED:
+- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+- we_event = SIOCGIWAP;
+- break;
+- case IEEE80211SOFTMAC_EVENT_SCAN_FINISHED:
+- we_event = SIOCGIWSCAN;
+- break;
+- default:
+- msg = event_descriptions[event];
+- if (!msg)
+- msg = "SOFTMAC EVENT BUG";
+- wrqu.data.length = strlen(msg);
+- we_event = IWEVCUSTOM;
+- break;
+- }
+- wireless_send_event(mac->dev, we_event, &wrqu, msg);
+- }
+-
+- if (!list_empty(&mac->events))
+- list_for_each_entry_safe(eventptr, tmp, &mac->events, list) {
+- if ((eventptr->event_type == event || eventptr->event_type == -1)
+- && (eventptr->event_context == NULL || eventptr->event_context == event_ctx)) {
+- list_del(&eventptr->list);
+- /* User may have subscribed to ANY event, so
+- * we tell them which event triggered it. */
+- eventptr->event_type = event;
+- queue_delayed_work(mac->wq, &eventptr->work, 0);
+- }
+- }
+-}
+-
+-void
+-ieee80211softmac_call_events(struct ieee80211softmac_device *mac, int event, void *event_ctx)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&mac->lock, flags);
+- ieee80211softmac_call_events_locked(mac, event, event_ctx);
+-
+- spin_unlock_irqrestore(&mac->lock, flags);
+-}
+diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c
+deleted file mode 100644
+index 73b4b13..0000000
+--- a/net/ieee80211/softmac/ieee80211softmac_io.c
++++ /dev/null
+@@ -1,488 +0,0 @@
+-/*
+- * Some parts based on code from net80211
+- * Copyright (c) 2001 Atsushi Onoe
+- * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+- * All rights reserved.
+- *
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions
+- * are met:
+- * 1. Redistributions of source code must retain the above copyright
+- * notice, this list of conditions and the following disclaimer.
+- * 2. Redistributions in binary form must reproduce the above copyright
+- * notice, this list of conditions and the following disclaimer in the
+- * documentation and/or other materials provided with the distribution.
+- * 3. The name of the author may not be used to endorse or promote products
+- * derived from this software without specific prior written permission.
+- *
+- * Alternatively, this software may be distributed under the terms of the
+- * GNU General Public License ("GPL") version 2 as published by the Free
+- * Software Foundation.
+- *
+- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+- *
+- */
+-
+-#include "ieee80211softmac_priv.h"
+-
+-/* Helper functions for inserting data into the frames */
+-
+-/*
+- * Adds an ESSID element to the frame
+- *
+- */
+-static u8 *
+-ieee80211softmac_add_essid(u8 *dst, struct ieee80211softmac_essid *essid)
+-{
+- if (essid) {
+- *dst++ = MFIE_TYPE_SSID;
+- *dst++ = essid->len;
+- memcpy(dst, essid->data, essid->len);
+- return dst+essid->len;
+- } else {
+- *dst++ = MFIE_TYPE_SSID;
+- *dst++ = 0;
+- return dst;
+- }
+-}
+-
+-/* Adds Supported Rates and if required Extended Rates Information Element
+- * to the frame, ASSUMES WE HAVE A SORTED LIST OF RATES */
+-static u8 *
+-ieee80211softmac_frame_add_rates(u8 *dst, const struct ieee80211softmac_ratesinfo *r)
+-{
+- int cck_len, ofdm_len;
+- *dst++ = MFIE_TYPE_RATES;
+-
+- for(cck_len=0; ieee80211_is_cck_rate(r->rates[cck_len]) && (cck_len < r->count);cck_len++);
+-
+- if(cck_len > IEEE80211SOFTMAC_MAX_RATES_LEN)
+- cck_len = IEEE80211SOFTMAC_MAX_RATES_LEN;
+- *dst++ = cck_len;
+- memcpy(dst, r->rates, cck_len);
+- dst += cck_len;
+-
+- if(cck_len < r->count){
+- for (ofdm_len=0; ieee80211_is_ofdm_rate(r->rates[ofdm_len + cck_len]) && (ofdm_len + cck_len < r->count); ofdm_len++);
+- if (ofdm_len > 0) {
+- if (ofdm_len > IEEE80211SOFTMAC_MAX_EX_RATES_LEN)
+- ofdm_len = IEEE80211SOFTMAC_MAX_EX_RATES_LEN;
+- *dst++ = MFIE_TYPE_RATES_EX;
+- *dst++ = ofdm_len;
+- memcpy(dst, r->rates + cck_len, ofdm_len);
+- dst += ofdm_len;
+- }
+- }
+- return dst;
+-}
+-
+-/* Allocate a management frame */
+-static u8 *
+-ieee80211softmac_alloc_mgt(u32 size)
+-{
+- u8 * data;
+-
+- /* Add the header and FCS to the size */
+- size = size + IEEE80211_3ADDR_LEN;
+- if(size > IEEE80211_DATA_LEN)
+- return NULL;
+- /* Allocate the frame */
+- data = kzalloc(size, GFP_ATOMIC);
+- return data;
+-}
+-
+-/*
+- * Add a 2 Address Header
+- */
+-static void
+-ieee80211softmac_hdr_2addr(struct ieee80211softmac_device *mac,
+- struct ieee80211_hdr_2addr *header, u32 type, u8 *dest)
+-{
+- /* Fill in the frame control flags */
+- header->frame_ctl = cpu_to_le16(type);
+- /* Control packets always have WEP turned off */
+- if(type > IEEE80211_STYPE_CFENDACK && type < IEEE80211_STYPE_PSPOLL)
+- header->frame_ctl |= mac->ieee->sec.level ? cpu_to_le16(IEEE80211_FCTL_PROTECTED) : 0;
+-
+- /* Fill in the duration */
+- header->duration_id = 0;
+- /* FIXME: How do I find this?
+- * calculate. But most drivers just fill in 0 (except if it's a station id of course) */
+-
+- /* Fill in the Destination Address */
+- if(dest == NULL)
+- memset(header->addr1, 0xFF, ETH_ALEN);
+- else
+- memcpy(header->addr1, dest, ETH_ALEN);
+- /* Fill in the Source Address */
+- memcpy(header->addr2, mac->ieee->dev->dev_addr, ETH_ALEN);
+-
+-}
+-
+-
+-/* Add a 3 Address Header */
+-static void
+-ieee80211softmac_hdr_3addr(struct ieee80211softmac_device *mac,
+- struct ieee80211_hdr_3addr *header, u32 type, u8 *dest, u8 *bssid)
+-{
+- /* This is common with 2addr, so use that instead */
+- ieee80211softmac_hdr_2addr(mac, (struct ieee80211_hdr_2addr *)header, type, dest);
+-
+- /* Fill in the BSS ID */
+- if(bssid == NULL)
+- memset(header->addr3, 0xFF, ETH_ALEN);
+- else
+- memcpy(header->addr3, bssid, ETH_ALEN);
+-
+- /* Fill in the sequence # */
+- /* FIXME: I need to add this to the softmac struct
+- * shouldn't the sequence number be in ieee80211? */
+-}
+-
+-static __le16
+-ieee80211softmac_capabilities(struct ieee80211softmac_device *mac,
+- struct ieee80211softmac_network *net)
+-{
+- __le16 capability = 0;
+-
+- /* ESS and IBSS bits are set according to the current mode */
+- switch (mac->ieee->iw_mode) {
+- case IW_MODE_INFRA:
+- capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
+- break;
+- case IW_MODE_ADHOC:
+- capability = cpu_to_le16(WLAN_CAPABILITY_IBSS);
+- break;
+- case IW_MODE_AUTO:
+- capability = cpu_to_le16(net->capabilities &
+- (WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS));
+- break;
+- default:
+- /* bleh. we don't ever go to these modes */
+- printk(KERN_ERR PFX "invalid iw_mode!\n");
+- break;
+- }
+-
+- /* CF Pollable / CF Poll Request */
+- /* Needs to be implemented, for now, the 0's == not supported */
+-
+- /* Privacy Bit */
+- capability |= mac->ieee->sec.level ?
+- cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0;
+-
+- /* Short Preamble */
+- /* Always supported: we probably won't ever be powering devices which
+- * dont support this... */
+- capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE);
+-
+- /* PBCC */
+- /* Not widely used */
+-
+- /* Channel Agility */
+- /* Not widely used */
+-
+- /* Short Slot */
+- /* Will be implemented later */
+-
+- /* DSSS-OFDM */
+- /* Not widely used */
+-
+- return capability;
+-}
+-
+-/*****************************************************************************
+- * Create Management packets
+- *****************************************************************************/
+-
+-/* Creates an association request packet */
+-static u32
+-ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt,
+- struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net)
+-{
+- u8 *data;
+- (*pkt) = (struct ieee80211_assoc_request *)ieee80211softmac_alloc_mgt(
+- 2 + /* Capability Info */
+- 2 + /* Listen Interval */
+- /* SSID IE */
+- 1 + 1 + IW_ESSID_MAX_SIZE +
+- /* Rates IE */
+- 1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN +
+- /* Extended Rates IE */
+- 1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN +
+- /* WPA IE if present */
+- mac->wpa.IElen
+- /* Other IE's? Optional?
+- * Yeah, probably need an extra IE parameter -- lots of vendors like to
+- * fill in their own IEs */
+- );
+- if (unlikely((*pkt) == NULL))
+- return 0;
+- ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid);
+-
+- /* Fill in the capabilities */
+- (*pkt)->capability = ieee80211softmac_capabilities(mac, net);
+-
+- /* Fill in Listen Interval (?) */
+- (*pkt)->listen_interval = cpu_to_le16(10);
+-
+- data = (u8 *)(*pkt)->info_element;
+- /* Add SSID */
+- data = ieee80211softmac_add_essid(data, &net->essid);
+- /* Add Rates */
+- data = ieee80211softmac_frame_add_rates(data, &mac->ratesinfo);
+- /* Add WPA IE */
+- if (mac->wpa.IElen && mac->wpa.IE) {
+- memcpy(data, mac->wpa.IE, mac->wpa.IElen);
+- data += mac->wpa.IElen;
+- }
+- /* Return the number of used bytes */
+- return (data - (u8*)(*pkt));
+-}
+-
+-/* Create a reassociation request packet */
+-static u32
+-ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt,
+- struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net)
+-{
+- u8 *data;
+- (*pkt) = (struct ieee80211_reassoc_request *)ieee80211softmac_alloc_mgt(
+- 2 + /* Capability Info */
+- 2 + /* Listen Interval */
+- ETH_ALEN + /* AP MAC */
+- /* SSID IE */
+- 1 + 1 + IW_ESSID_MAX_SIZE +
+- /* Rates IE */
+- 1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN +
+- /* Extended Rates IE */
+- 1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN
+- /* Other IE's? */
+- );
+- if (unlikely((*pkt) == NULL))
+- return 0;
+- ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_REASSOC_REQ, net->bssid, net->bssid);
+-
+- /* Fill in the capabilities */
+- (*pkt)->capability = ieee80211softmac_capabilities(mac, net);
+-
+- /* Fill in Listen Interval (?) */
+- (*pkt)->listen_interval = cpu_to_le16(10);
+- /* Fill in the current AP MAC */
+- memcpy((*pkt)->current_ap, mac->ieee->bssid, ETH_ALEN);
+-
+- data = (u8 *)(*pkt)->info_element;
+- /* Add SSID */
+- data = ieee80211softmac_add_essid(data, &net->essid);
+- /* Add Rates */
+- data = ieee80211softmac_frame_add_rates(data, &mac->ratesinfo);
+- /* Return packet size */
+- return (data - (u8 *)(*pkt));
+-}
+-
+-/* Create an authentication packet */
+-static u32
+-ieee80211softmac_auth(struct ieee80211_auth **pkt,
+- struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net,
+- u16 transaction, u16 status, int *encrypt_mpdu)
+-{
+- u8 *data;
+- int auth_mode = mac->ieee->sec.auth_mode;
+- int is_shared_response = (auth_mode == WLAN_AUTH_SHARED_KEY
+- && transaction == IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE);
+-
+- /* Allocate Packet */
+- (*pkt) = (struct ieee80211_auth *)ieee80211softmac_alloc_mgt(
+- 2 + /* Auth Algorithm */
+- 2 + /* Auth Transaction Seq */
+- 2 + /* Status Code */
+- /* Challenge Text IE */
+- (is_shared_response ? 1 + 1 + net->challenge_len : 0)
+- );
+- if (unlikely((*pkt) == NULL))
+- return 0;
+- ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_AUTH, net->bssid, net->bssid);
+-
+- /* Algorithm */
+- (*pkt)->algorithm = cpu_to_le16(auth_mode);
+- /* Transaction */
+- (*pkt)->transaction = cpu_to_le16(transaction);
+- /* Status */
+- (*pkt)->status = cpu_to_le16(status);
+-
+- data = (u8 *)(*pkt)->info_element;
+- /* Challenge Text */
+- if (is_shared_response) {
+- *data = MFIE_TYPE_CHALLENGE;
+- data++;
+-
+- /* Copy the challenge in */
+- *data = net->challenge_len;
+- data++;
+- memcpy(data, net->challenge, net->challenge_len);
+- data += net->challenge_len;
+-
+- /* Make sure this frame gets encrypted with the shared key */
+- *encrypt_mpdu = 1;
+- } else
+- *encrypt_mpdu = 0;
+-
+- /* Return the packet size */
+- return (data - (u8 *)(*pkt));
+-}
+-
+-/* Create a disassocation or deauthentication packet */
+-static u32
+-ieee80211softmac_disassoc_deauth(struct ieee80211_disassoc **pkt,
+- struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net,
+- u16 type, u16 reason)
+-{
+- /* Allocate Packet */
+- (*pkt) = (struct ieee80211_disassoc *)ieee80211softmac_alloc_mgt(2);
+- if (unlikely((*pkt) == NULL))
+- return 0;
+- ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), type, net->bssid, net->bssid);
+- /* Reason */
+- (*pkt)->reason = cpu_to_le16(reason);
+- /* Return the packet size */
+- return (2 + IEEE80211_3ADDR_LEN);
+-}
+-
+-/* Create a probe request packet */
+-static u32
+-ieee80211softmac_probe_req(struct ieee80211_probe_request **pkt,
+- struct ieee80211softmac_device *mac, struct ieee80211softmac_essid *essid)
+-{
+- u8 *data;
+- /* Allocate Packet */
+- (*pkt) = (struct ieee80211_probe_request *)ieee80211softmac_alloc_mgt(
+- /* SSID of requested network */
+- 1 + 1 + IW_ESSID_MAX_SIZE +
+- /* Rates IE */
+- 1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN +
+- /* Extended Rates IE */
+- 1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN
+- );
+- if (unlikely((*pkt) == NULL))
+- return 0;
+- ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_PROBE_REQ, NULL, NULL);
+-
+- data = (u8 *)(*pkt)->info_element;
+- /* Add ESSID (can be NULL) */
+- data = ieee80211softmac_add_essid(data, essid);
+- /* Add Rates */
+- data = ieee80211softmac_frame_add_rates(data, &mac->ratesinfo);
+- /* Return packet size */
+- return (data - (u8 *)(*pkt));
+-}
+-
+-/* Create a probe response packet */
+-/* FIXME: Not complete */
+-static u32
+-ieee80211softmac_probe_resp(struct ieee80211_probe_response **pkt,
+- struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net)
+-{
+- u8 *data;
+- /* Allocate Packet */
+- (*pkt) = (struct ieee80211_probe_response *)ieee80211softmac_alloc_mgt(
+- 8 + /* Timestamp */
+- 2 + /* Beacon Interval */
+- 2 + /* Capability Info */
+- /* SSID IE */
+- 1 + 1 + IW_ESSID_MAX_SIZE +
+- 7 + /* FH Parameter Set */
+- 2 + /* DS Parameter Set */
+- 8 + /* CF Parameter Set */
+- 4 /* IBSS Parameter Set */
+- );
+- if (unlikely((*pkt) == NULL))
+- return 0;
+- ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_PROBE_RESP, net->bssid, net->bssid);
+- data = (u8 *)(*pkt)->info_element;
+-
+- /* Return the packet size */
+- return (data - (u8 *)(*pkt));
+-}
+-
+-
+-/* Sends a manangement packet
+- * FIXME: document the use of the arg parameter
+- * for _AUTH: (transaction #) | (status << 16)
+- */
+-int
+-ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
+- void *ptrarg, u32 type, u32 arg)
+-{
+- void *pkt = NULL;
+- u32 pkt_size = 0;
+- int encrypt_mpdu = 0;
+-
+- switch(type) {
+- case IEEE80211_STYPE_ASSOC_REQ:
+- pkt_size = ieee80211softmac_assoc_req((struct ieee80211_assoc_request **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg);
+- break;
+- case IEEE80211_STYPE_REASSOC_REQ:
+- pkt_size = ieee80211softmac_reassoc_req((struct ieee80211_reassoc_request **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg);
+- break;
+- case IEEE80211_STYPE_AUTH:
+- pkt_size = ieee80211softmac_auth((struct ieee80211_auth **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, (u16)(arg & 0xFFFF), (u16) (arg >> 16), &encrypt_mpdu);
+- break;
+- case IEEE80211_STYPE_DISASSOC:
+- case IEEE80211_STYPE_DEAUTH:
+- pkt_size = ieee80211softmac_disassoc_deauth((struct ieee80211_disassoc **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, type, (u16)(arg & 0xFFFF));
+- break;
+- case IEEE80211_STYPE_PROBE_REQ:
+- pkt_size = ieee80211softmac_probe_req((struct ieee80211_probe_request **)(&pkt), mac, (struct ieee80211softmac_essid *)ptrarg);
+- break;
+- case IEEE80211_STYPE_PROBE_RESP:
+- pkt_size = ieee80211softmac_probe_resp((struct ieee80211_probe_response **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg);
+- break;
+- default:
+- printkl(KERN_DEBUG PFX "Unsupported Management Frame type: %i\n", type);
+- return -EINVAL;
+- };
+-
+- if(pkt_size == 0 || pkt == NULL) {
+- printkl(KERN_DEBUG PFX "Error, packet is nonexistant or 0 length\n");
+- return -ENOMEM;
+- }
+-
+- /* Send the packet to the ieee80211 layer for tx */
+- /* we defined softmac->mgmt_xmit for this. Should we keep it
+- * as it is (that means we'd need to wrap this into a txb),
+- * modify the prototype (so it matches this function),
+- * or get rid of it alltogether?
+- * Does this work for you now?
+- */
+- ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *)pkt,
+- IEEE80211_3ADDR_LEN, pkt_size, encrypt_mpdu);
+-
+- kfree(pkt);
+- return 0;
+-}
+-
+-/* Beacon handling */
+-int ieee80211softmac_handle_beacon(struct net_device *dev,
+- struct ieee80211_beacon *beacon,
+- struct ieee80211_network *network)
+-{
+- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+-
+- /* This might race, but we don't really care and it's not worth
+- * adding heavyweight locking in this fastpath.
+- */
+- if (mac->associnfo.associated) {
+- if (memcmp(network->bssid, mac->associnfo.bssid, ETH_ALEN) == 0)
+- ieee80211softmac_process_erp(mac, network->erp_value);
+- }
+-
+- return 0;
+-}
+-
+diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c
+deleted file mode 100644
+index 07505ca..0000000
+--- a/net/ieee80211/softmac/ieee80211softmac_module.c
++++ /dev/null
+@@ -1,568 +0,0 @@
+-/*
+- * Contains some basic softmac functions along with module registration code etc.
+- *
+- * Copyright (c) 2005, 2006 Johannes Berg <johannes at sipsolutions.net>
+- * Joseph Jezak <josejx at gentoo.org>
+- * Larry Finger <Larry.Finger at lwfinger.net>
+- * Danny van Dyk <kugelfang at gentoo.org>
+- * Michael Buesch <mbuesch at freenet.de>
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of version 2 of the GNU General Public License as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+- *
+- * The full GNU General Public License is included in this distribution in the
+- * file called COPYING.
+- */
+-
+-#include "ieee80211softmac_priv.h"
+-#include <linux/sort.h>
+-#include <linux/etherdevice.h>
+-
+-struct net_device *alloc_ieee80211softmac(int sizeof_priv)
+-{
+- struct ieee80211softmac_device *softmac;
+- struct net_device *dev;
+-
+- dev = alloc_ieee80211(sizeof(*softmac) + sizeof_priv);
+- if (!dev)
+- return NULL;
+- softmac = ieee80211_priv(dev);
+- softmac->wq = create_freezeable_workqueue("softmac");
+- if (!softmac->wq) {
+- free_ieee80211(dev);
+- return NULL;
+- }
+-
+- softmac->dev = dev;
+- softmac->ieee = netdev_priv(dev);
+- spin_lock_init(&softmac->lock);
+-
+- softmac->ieee->handle_auth = ieee80211softmac_auth_resp;
+- softmac->ieee->handle_deauth = ieee80211softmac_deauth_resp;
+- softmac->ieee->handle_assoc_response = ieee80211softmac_handle_assoc_response;
+- softmac->ieee->handle_reassoc_request = ieee80211softmac_handle_reassoc_req;
+- softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc;
+- softmac->ieee->handle_beacon = ieee80211softmac_handle_beacon;
+- softmac->scaninfo = NULL;
+-
+- softmac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
+-
+- /* TODO: initialise all the other callbacks in the ieee struct
+- * (once they're written)
+- */
+-
+- INIT_LIST_HEAD(&softmac->auth_queue);
+- INIT_LIST_HEAD(&softmac->network_list);
+- INIT_LIST_HEAD(&softmac->events);
+-
+- mutex_init(&softmac->associnfo.mutex);
+- INIT_DELAYED_WORK(&softmac->associnfo.work, ieee80211softmac_assoc_work);
+- INIT_DELAYED_WORK(&softmac->associnfo.timeout, ieee80211softmac_assoc_timeout);
+- softmac->start_scan = ieee80211softmac_start_scan_implementation;
+- softmac->wait_for_scan = ieee80211softmac_wait_for_scan_implementation;
+- softmac->stop_scan = ieee80211softmac_stop_scan_implementation;
+-
+- /* to start with, we can't send anything ... */
+- netif_carrier_off(dev);
+-
+- return dev;
+-}
+-EXPORT_SYMBOL_GPL(alloc_ieee80211softmac);
+-
+-/* Clears the pending work queue items, stops all scans, etc. */
+-void
+-ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm)
+-{
+- unsigned long flags;
+- struct ieee80211softmac_event *eventptr, *eventtmp;
+- struct ieee80211softmac_auth_queue_item *authptr, *authtmp;
+- struct ieee80211softmac_network *netptr, *nettmp;
+-
+- ieee80211softmac_stop_scan(sm);
+- ieee80211softmac_wait_for_scan(sm);
+-
+- spin_lock_irqsave(&sm->lock, flags);
+- sm->running = 0;
+-
+- /* Free all pending assoc work items */
+- cancel_delayed_work(&sm->associnfo.work);
+-
+- /* Free all pending scan work items */
+- if(sm->scaninfo != NULL)
+- cancel_delayed_work(&sm->scaninfo->softmac_scan);
+-
+- /* Free all pending auth work items */
+- list_for_each_entry(authptr, &sm->auth_queue, list)
+- cancel_delayed_work(&authptr->work);
+-
+- /* delete all pending event calls and work items */
+- list_for_each_entry_safe(eventptr, eventtmp, &sm->events, list)
+- cancel_delayed_work(&eventptr->work);
+-
+- spin_unlock_irqrestore(&sm->lock, flags);
+- flush_workqueue(sm->wq);
+-
+- /* now we should be save and no longer need locking... */
+- spin_lock_irqsave(&sm->lock, flags);
+- /* Free all pending auth work items */
+- list_for_each_entry_safe(authptr, authtmp, &sm->auth_queue, list) {
+- list_del(&authptr->list);
+- kfree(authptr);
+- }
+-
+- /* delete all pending event calls and work items */
+- list_for_each_entry_safe(eventptr, eventtmp, &sm->events, list) {
+- list_del(&eventptr->list);
+- kfree(eventptr);
+- }
+-
+- /* Free all networks */
+- list_for_each_entry_safe(netptr, nettmp, &sm->network_list, list) {
+- ieee80211softmac_del_network_locked(sm, netptr);
+- if(netptr->challenge != NULL)
+- kfree(netptr->challenge);
+- kfree(netptr);
+- }
+-
+- spin_unlock_irqrestore(&sm->lock, flags);
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_clear_pending_work);
+-
+-void free_ieee80211softmac(struct net_device *dev)
+-{
+- struct ieee80211softmac_device *sm = ieee80211_priv(dev);
+- ieee80211softmac_clear_pending_work(sm);
+- kfree(sm->scaninfo);
+- kfree(sm->wpa.IE);
+- destroy_workqueue(sm->wq);
+- free_ieee80211(dev);
+-}
+-EXPORT_SYMBOL_GPL(free_ieee80211softmac);
+-
+-static void ieee80211softmac_start_check_rates(struct ieee80211softmac_device *mac)
+-{
+- struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo;
+- /* I took out the sorting check, we're seperating by modulation now. */
+- if (ri->count)
+- return;
+- /* otherwise assume we hav'em all! */
+- if (mac->ieee->modulation & IEEE80211_CCK_MODULATION) {
+- ri->rates[ri->count++] = IEEE80211_CCK_RATE_1MB;
+- ri->rates[ri->count++] = IEEE80211_CCK_RATE_2MB;
+- ri->rates[ri->count++] = IEEE80211_CCK_RATE_5MB;
+- ri->rates[ri->count++] = IEEE80211_CCK_RATE_11MB;
+- }
+- if (mac->ieee->modulation & IEEE80211_OFDM_MODULATION) {
+- ri->rates[ri->count++] = IEEE80211_OFDM_RATE_6MB;
+- ri->rates[ri->count++] = IEEE80211_OFDM_RATE_9MB;
+- ri->rates[ri->count++] = IEEE80211_OFDM_RATE_12MB;
+- ri->rates[ri->count++] = IEEE80211_OFDM_RATE_18MB;
+- ri->rates[ri->count++] = IEEE80211_OFDM_RATE_24MB;
+- ri->rates[ri->count++] = IEEE80211_OFDM_RATE_36MB;
+- ri->rates[ri->count++] = IEEE80211_OFDM_RATE_48MB;
+- ri->rates[ri->count++] = IEEE80211_OFDM_RATE_54MB;
+- }
+-}
+-
+-int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo *ri, u8 rate)
+-{
+- int search;
+- u8 search_rate;
+-
+- for (search = 0; search < ri->count; search++) {
+- search_rate = ri->rates[search];
+- search_rate &= ~IEEE80211_BASIC_RATE_MASK;
+- if (rate == search_rate)
+- return 1;
+- }
+-
+- return 0;
+-}
+-
+-u8 ieee80211softmac_highest_supported_rate(struct ieee80211softmac_device *mac,
+- struct ieee80211softmac_ratesinfo *ri, int basic_only)
+-{
+- u8 user_rate = mac->txrates.user_rate;
+- int i;
+-
+- if (ri->count == 0)
+- return IEEE80211_CCK_RATE_1MB;
+-
+- for (i = ri->count - 1; i >= 0; i--) {
+- u8 rate = ri->rates[i];
+- if (basic_only && !(rate & IEEE80211_BASIC_RATE_MASK))
+- continue;
+- rate &= ~IEEE80211_BASIC_RATE_MASK;
+- if (rate > user_rate)
+- continue;
+- if (ieee80211softmac_ratesinfo_rate_supported(&mac->ratesinfo, rate))
+- return rate;
+- }
+-
+- /* If we haven't found a suitable rate by now, just trust the user */
+- return user_rate;
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_highest_supported_rate);
+-
+-void ieee80211softmac_process_erp(struct ieee80211softmac_device *mac,
+- u8 erp_value)
+-{
+- int use_protection;
+- int short_preamble;
+- u32 changes = 0;
+-
+- /* Barker preamble mode */
+- short_preamble = ((erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0
+- && mac->associnfo.short_preamble_available) ? 1 : 0;
+-
+- /* Protection needed? */
+- use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
+-
+- if (mac->bssinfo.short_preamble != short_preamble) {
+- changes |= IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE;
+- mac->bssinfo.short_preamble = short_preamble;
+- }
+-
+- if (mac->bssinfo.use_protection != use_protection) {
+- changes |= IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION;
+- mac->bssinfo.use_protection = use_protection;
+- }
+-
+- if (mac->bssinfo_change && changes)
+- mac->bssinfo_change(mac->dev, changes);
+-}
+-
+-void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac)
+-{
+- struct ieee80211softmac_txrates *txrates = &mac->txrates;
+- u32 change = 0;
+-
+- change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
+- txrates->default_rate = ieee80211softmac_highest_supported_rate(mac, &mac->bssinfo.supported_rates, 0);
+-
+- change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
+- txrates->default_fallback = lower_rate(mac, txrates->default_rate);
+-
+- change |= IEEE80211SOFTMAC_TXRATECHG_MCAST;
+- txrates->mcast_rate = ieee80211softmac_highest_supported_rate(mac, &mac->bssinfo.supported_rates, 1);
+-
+- if (mac->txrates_change)
+- mac->txrates_change(mac->dev, change);
+-
+-}
+-
+-void ieee80211softmac_init_bss(struct ieee80211softmac_device *mac)
+-{
+- struct ieee80211_device *ieee = mac->ieee;
+- u32 change = 0;
+- struct ieee80211softmac_txrates *txrates = &mac->txrates;
+- struct ieee80211softmac_bss_info *bssinfo = &mac->bssinfo;
+-
+- /* TODO: We need some kind of state machine to lower the default rates
+- * if we loose too many packets.
+- */
+- /* Change the default txrate to the highest possible value.
+- * The txrate machine will lower it, if it is too high.
+- */
+- if (ieee->modulation & IEEE80211_OFDM_MODULATION)
+- txrates->user_rate = IEEE80211_OFDM_RATE_24MB;
+- else
+- txrates->user_rate = IEEE80211_CCK_RATE_11MB;
+-
+- txrates->default_rate = IEEE80211_CCK_RATE_1MB;
+- change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
+-
+- txrates->default_fallback = IEEE80211_CCK_RATE_1MB;
+- change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
+-
+- txrates->mcast_rate = IEEE80211_CCK_RATE_1MB;
+- change |= IEEE80211SOFTMAC_TXRATECHG_MCAST;
+-
+- txrates->mgt_mcast_rate = IEEE80211_CCK_RATE_1MB;
+- change |= IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST;
+-
+- if (mac->txrates_change)
+- mac->txrates_change(mac->dev, change);
+-
+- change = 0;
+-
+- bssinfo->supported_rates.count = 0;
+- memset(bssinfo->supported_rates.rates, 0,
+- sizeof(bssinfo->supported_rates.rates));
+- change |= IEEE80211SOFTMAC_BSSINFOCHG_RATES;
+-
+- bssinfo->short_preamble = 0;
+- change |= IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE;
+-
+- bssinfo->use_protection = 0;
+- change |= IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION;
+-
+- if (mac->bssinfo_change)
+- mac->bssinfo_change(mac->dev, change);
+-
+- mac->running = 1;
+-}
+-
+-void ieee80211softmac_start(struct net_device *dev)
+-{
+- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+-
+- ieee80211softmac_start_check_rates(mac);
+- ieee80211softmac_init_bss(mac);
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_start);
+-
+-void ieee80211softmac_stop(struct net_device *dev)
+-{
+- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+-
+- ieee80211softmac_clear_pending_work(mac);
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_stop);
+-
+-void ieee80211softmac_set_rates(struct net_device *dev, u8 count, u8 *rates)
+-{
+- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+- unsigned long flags;
+-
+- spin_lock_irqsave(&mac->lock, flags);
+- memcpy(mac->ratesinfo.rates, rates, count);
+- mac->ratesinfo.count = count;
+- spin_unlock_irqrestore(&mac->lock, flags);
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_set_rates);
+-
+-static u8 raise_rate(struct ieee80211softmac_device *mac, u8 rate)
+-{
+- int i;
+- struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo;
+-
+- for (i=0; i<ri->count-1; i++) {
+- if (ri->rates[i] == rate)
+- return ri->rates[i+1];
+- }
+- /* I guess we can't go any higher... */
+- return ri->rates[ri->count];
+-}
+-
+-u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta)
+-{
+- int i;
+- struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo;
+-
+- for (i=delta; i<ri->count; i++) {
+- if (ri->rates[i] == rate)
+- return ri->rates[i-delta];
+- }
+- /* I guess we can't go any lower... */
+- return ri->rates[0];
+-}
+-
+-static void ieee80211softmac_add_txrates_badness(struct ieee80211softmac_device *mac,
+- int amount)
+-{
+- u8 default_rate = mac->txrates.default_rate;
+- u8 default_fallback = mac->txrates.default_fallback;
+- u32 changes = 0;
+-
+- //TODO: This is highly experimental code.
+- // Maybe the dynamic rate selection does not work
+- // and it has to be removed again.
+-
+-printk("badness %d\n", mac->txrate_badness);
+- mac->txrate_badness += amount;
+- if (mac->txrate_badness <= -1000) {
+- /* Very small badness. Try a faster bitrate. */
+- default_rate = raise_rate(mac, default_rate);
+- changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
+- default_fallback = get_fallback_rate(mac, default_rate);
+- changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
+- mac->txrate_badness = 0;
+-printk("Bitrate raised to %u\n", default_rate);
+- } else if (mac->txrate_badness >= 10000) {
+- /* Very high badness. Try a slower bitrate. */
+- default_rate = lower_rate(mac, default_rate);
+- changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
+- default_fallback = get_fallback_rate(mac, default_rate);
+- changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
+- mac->txrate_badness = 0;
+-printk("Bitrate lowered to %u\n", default_rate);
+- }
+-
+- mac->txrates.default_rate = default_rate;
+- mac->txrates.default_fallback = default_fallback;
+-
+- if (changes && mac->txrates_change)
+- mac->txrates_change(mac->dev, changes);
+-}
+-
+-void ieee80211softmac_fragment_lost(struct net_device *dev,
+- u16 wl_seq)
+-{
+- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+- unsigned long flags;
+-
+- spin_lock_irqsave(&mac->lock, flags);
+- ieee80211softmac_add_txrates_badness(mac, 1000);
+- //TODO
+-
+- spin_unlock_irqrestore(&mac->lock, flags);
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_fragment_lost);
+-
+-static int rate_cmp(const void *a_, const void *b_) {
+- u8 *a, *b;
+- a = (u8*)a_;
+- b = (u8*)b_;
+- return ((*a & ~IEEE80211_BASIC_RATE_MASK) - (*b & ~IEEE80211_BASIC_RATE_MASK));
+-}
+-
+-/* Allocate a softmac network struct and fill it from a network */
+-struct ieee80211softmac_network *
+-ieee80211softmac_create_network(struct ieee80211softmac_device *mac,
+- struct ieee80211_network *net)
+-{
+- struct ieee80211softmac_network *softnet;
+- softnet = kzalloc(sizeof(struct ieee80211softmac_network), GFP_ATOMIC);
+- if(softnet == NULL)
+- return NULL;
+- memcpy(softnet->bssid, net->bssid, ETH_ALEN);
+- softnet->channel = net->channel;
+- softnet->essid.len = net->ssid_len;
+- memcpy(softnet->essid.data, net->ssid, softnet->essid.len);
+-
+- /* copy rates over */
+- softnet->supported_rates.count = net->rates_len;
+- memcpy(&softnet->supported_rates.rates[0], net->rates, net->rates_len);
+- memcpy(&softnet->supported_rates.rates[softnet->supported_rates.count], net->rates_ex, net->rates_ex_len);
+- softnet->supported_rates.count += net->rates_ex_len;
+- sort(softnet->supported_rates.rates, softnet->supported_rates.count, sizeof(softnet->supported_rates.rates[0]), rate_cmp, NULL);
+-
+- /* we save the ERP value because it is needed at association time, and
+- * many AP's do not include an ERP IE in the association response. */
+- softnet->erp_value = net->erp_value;
+-
+- softnet->capabilities = net->capability;
+- return softnet;
+-}
+-
+-
+-/* Add a network to the list, while locked */
+-void
+-ieee80211softmac_add_network_locked(struct ieee80211softmac_device *mac,
+- struct ieee80211softmac_network *add_net)
+-{
+- struct ieee80211softmac_network *softmac_net;
+-
+- list_for_each_entry(softmac_net, &mac->network_list, list) {
+- if(!memcmp(softmac_net->bssid, add_net->bssid, ETH_ALEN))
+- return;
+- }
+- list_add(&(add_net->list), &mac->network_list);
+-}
+-
+-/* Add a network to the list, with locking */
+-void
+-ieee80211softmac_add_network(struct ieee80211softmac_device *mac,
+- struct ieee80211softmac_network *add_net)
+-{
+- unsigned long flags;
+- spin_lock_irqsave(&mac->lock, flags);
+- ieee80211softmac_add_network_locked(mac, add_net);
+- spin_unlock_irqrestore(&mac->lock, flags);
+-}
+-
+-
+-/* Delete a network from the list, while locked*/
+-void
+-ieee80211softmac_del_network_locked(struct ieee80211softmac_device *mac,
+- struct ieee80211softmac_network *del_net)
+-{
+- list_del(&(del_net->list));
+-}
+-
+-/* Delete a network from the list with locking */
+-void
+-ieee80211softmac_del_network(struct ieee80211softmac_device *mac,
+- struct ieee80211softmac_network *del_net)
+-{
+- unsigned long flags;
+- spin_lock_irqsave(&mac->lock, flags);
+- ieee80211softmac_del_network_locked(mac, del_net);
+- spin_unlock_irqrestore(&mac->lock, flags);
+-}
+-
+-/* Get a network from the list by MAC while locked */
+-struct ieee80211softmac_network *
+-ieee80211softmac_get_network_by_bssid_locked(struct ieee80211softmac_device *mac,
+- u8 *bssid)
+-{
+- struct ieee80211softmac_network *softmac_net;
+-
+- list_for_each_entry(softmac_net, &mac->network_list, list) {
+- if(!memcmp(softmac_net->bssid, bssid, ETH_ALEN))
+- return softmac_net;
+- }
+- return NULL;
+-}
+-
+-/* Get a network from the list by BSSID with locking */
+-struct ieee80211softmac_network *
+-ieee80211softmac_get_network_by_bssid(struct ieee80211softmac_device *mac,
+- u8 *bssid)
+-{
+- unsigned long flags;
+- struct ieee80211softmac_network *softmac_net;
+-
+- spin_lock_irqsave(&mac->lock, flags);
+- softmac_net = ieee80211softmac_get_network_by_bssid_locked(mac, bssid);
+- spin_unlock_irqrestore(&mac->lock, flags);
+- return softmac_net;
+-}
+-
+-/* Get a network from the list by ESSID while locked */
+-struct ieee80211softmac_network *
+-ieee80211softmac_get_network_by_essid_locked(struct ieee80211softmac_device *mac,
+- struct ieee80211softmac_essid *essid)
+-{
+- struct ieee80211softmac_network *softmac_net;
+-
+- list_for_each_entry(softmac_net, &mac->network_list, list) {
+- if (softmac_net->essid.len == essid->len &&
+- !memcmp(softmac_net->essid.data, essid->data, essid->len))
+- return softmac_net;
+- }
+- return NULL;
+-}
+-
+-/* Get a network from the list by ESSID with locking */
+-struct ieee80211softmac_network *
+-ieee80211softmac_get_network_by_essid(struct ieee80211softmac_device *mac,
+- struct ieee80211softmac_essid *essid)
+-{
+- unsigned long flags;
+- struct ieee80211softmac_network *softmac_net = NULL;
+-
+- spin_lock_irqsave(&mac->lock, flags);
+- softmac_net = ieee80211softmac_get_network_by_essid_locked(mac, essid);
+- spin_unlock_irqrestore(&mac->lock, flags);
+- return softmac_net;
+-}
+-
+-MODULE_LICENSE("GPL");
+-MODULE_AUTHOR("Johannes Berg");
+-MODULE_AUTHOR("Joseph Jezak");
+-MODULE_AUTHOR("Larry Finger");
+-MODULE_AUTHOR("Danny van Dyk");
+-MODULE_AUTHOR("Michael Buesch");
+-MODULE_DESCRIPTION("802.11 software MAC");
+diff --git a/net/ieee80211/softmac/ieee80211softmac_priv.h b/net/ieee80211/softmac/ieee80211softmac_priv.h
+deleted file mode 100644
+index c43b189..0000000
+--- a/net/ieee80211/softmac/ieee80211softmac_priv.h
++++ /dev/null
+@@ -1,244 +0,0 @@
+-/*
+- * Internal softmac API definitions.
+- *
+- * Copyright (c) 2005, 2006 Johannes Berg <johannes at sipsolutions.net>
+- * Joseph Jezak <josejx at gentoo.org>
+- * Larry Finger <Larry.Finger at lwfinger.net>
+- * Danny van Dyk <kugelfang at gentoo.org>
+- * Michael Buesch <mbuesch at freenet.de>
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of version 2 of the GNU General Public License as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+- *
+- * The full GNU General Public License is included in this distribution in the
+- * file called COPYING.
+- */
+-
+-#ifndef IEEE80211SOFTMAC_PRIV_H_
+-#define IEEE80211SOFTMAC_PRIV_H_
+-
+-#include <net/ieee80211softmac.h>
+-#include <net/ieee80211softmac_wx.h>
+-#include <linux/kernel.h>
+-#include <linux/stringify.h>
+-
+-
+-#define PFX "SoftMAC: "
+-
+-#ifdef assert
+-# undef assert
+-#endif
+-#ifdef CONFIG_IEEE80211_SOFTMAC_DEBUG
+-#define assert(expr) \
+- do { \
+- if (unlikely(!(expr))) { \
+- printkl(KERN_ERR PFX "ASSERTION FAILED (%s) at: %s:%d:%s()\n", #expr, \
+- __FILE__, __LINE__, __FUNCTION__); \
+- } \
+- } while (0)
+-#else
+-#define assert(expr) do {} while (0)
+-#endif
+-
+-/* rate limited printk(). */
+-#ifdef printkl
+-# undef printkl
+-#endif
+-#define printkl(f, x...) do { if (printk_ratelimit()) printk(f ,##x); } while (0)
+-/* rate limited printk() for debugging */
+-#ifdef dprintkl
+-# undef dprintkl
+-#endif
+-#ifdef CONFIG_IEEE80211_SOFTMAC_DEBUG
+-# define dprintkl printkl
+-#else
+-# define dprintkl(f, x...) do { /* nothing */ } while (0)
+-#endif
+-
+-/* debugging printk() */
+-#ifdef dprintk
+-# undef dprintk
+-#endif
+-#ifdef CONFIG_IEEE80211_SOFTMAC_DEBUG
+-# define dprintk(f, x...) do { printk(f ,##x); } while (0)
+-#else
+-# define dprintk(f, x...) do { /* nothing */ } while (0)
+-#endif
+-
+-/* private definitions and prototypes */
+-
+-/*** prototypes from _scan.c */
+-void ieee80211softmac_scan(struct work_struct *work);
+-/* for internal use if scanning is needed */
+-int ieee80211softmac_start_scan(struct ieee80211softmac_device *mac);
+-void ieee80211softmac_stop_scan(struct ieee80211softmac_device *mac);
+-void ieee80211softmac_wait_for_scan(struct ieee80211softmac_device *mac);
+-
+-/* for use by _module.c to assign to the callbacks */
+-int ieee80211softmac_start_scan_implementation(struct net_device *dev);
+-void ieee80211softmac_stop_scan_implementation(struct net_device *dev);
+-void ieee80211softmac_wait_for_scan_implementation(struct net_device *dev);
+-
+-/*** Network prototypes from _module.c */
+-struct ieee80211softmac_network * ieee80211softmac_create_network(
+- struct ieee80211softmac_device *mac, struct ieee80211_network *net);
+-void ieee80211softmac_add_network_locked(struct ieee80211softmac_device *mac,
+- struct ieee80211softmac_network *net);
+-void ieee80211softmac_add_network(struct ieee80211softmac_device *mac,
+- struct ieee80211softmac_network *net);
+-void ieee80211softmac_del_network_locked(struct ieee80211softmac_device *mac,
+- struct ieee80211softmac_network *net);
+-void ieee80211softmac_del_network(struct ieee80211softmac_device *mac,
+- struct ieee80211softmac_network *net);
+-struct ieee80211softmac_network * ieee80211softmac_get_network_by_bssid_locked(
+- struct ieee80211softmac_device *mac, u8 *ea);
+-struct ieee80211softmac_network * ieee80211softmac_get_network_by_bssid(
+- struct ieee80211softmac_device *mac, u8 *ea);
+-struct ieee80211softmac_network * ieee80211softmac_get_network_by_ssid_locked(
+- struct ieee80211softmac_device *mac, u8 *ssid, u8 ssid_len);
+-struct ieee80211softmac_network * ieee80211softmac_get_network_by_ssid(
+- struct ieee80211softmac_device *mac, u8 *ssid, u8 ssid_len);
+-struct ieee80211softmac_network *
+-ieee80211softmac_get_network_by_essid_locked(struct ieee80211softmac_device *mac,
+- struct ieee80211softmac_essid *essid);
+-struct ieee80211softmac_network *
+-ieee80211softmac_get_network_by_essid(struct ieee80211softmac_device *mac,
+- struct ieee80211softmac_essid *essid);
+-
+-/* Rates related */
+-void ieee80211softmac_process_erp(struct ieee80211softmac_device *mac,
+- u8 erp_value);
+-int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo *ri, u8 rate);
+-u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta);
+-void ieee80211softmac_init_bss(struct ieee80211softmac_device *mac);
+-void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac);
+-static inline u8 lower_rate(struct ieee80211softmac_device *mac, u8 rate) {
+- return ieee80211softmac_lower_rate_delta(mac, rate, 1);
+-}
+-
+-static inline u8 get_fallback_rate(struct ieee80211softmac_device *mac, u8 rate)
+-{
+- return ieee80211softmac_lower_rate_delta(mac, rate, 2);
+-}
+-
+-
+-/*** prototypes from _io.c */
+-int ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
+- void* ptrarg, u32 type, u32 arg);
+-int ieee80211softmac_handle_beacon(struct net_device *dev,
+- struct ieee80211_beacon *beacon,
+- struct ieee80211_network *network);
+-
+-/*** prototypes from _auth.c */
+-/* do these have to go into the public header? */
+-int ieee80211softmac_auth_req(struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net);
+-int ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net, int reason);
+-
+-/* for use by _module.c to assign to the callbacks */
+-int ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth);
+-int ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *deauth);
+-
+-/*** prototypes from _assoc.c */
+-void ieee80211softmac_assoc_work(struct work_struct *work);
+-int ieee80211softmac_handle_assoc_response(struct net_device * dev,
+- struct ieee80211_assoc_response * resp,
+- struct ieee80211_network * network);
+-int ieee80211softmac_handle_disassoc(struct net_device * dev,
+- struct ieee80211_disassoc * disassoc);
+-int ieee80211softmac_handle_reassoc_req(struct net_device * dev,
+- struct ieee80211_reassoc_request * reassoc);
+-void ieee80211softmac_assoc_timeout(struct work_struct *work);
+-void ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reason);
+-void ieee80211softmac_disassoc(struct ieee80211softmac_device *mac);
+-
+-/* some helper functions */
+-static inline int ieee80211softmac_scan_handlers_check_self(struct ieee80211softmac_device *sm)
+-{
+- return (sm->start_scan == ieee80211softmac_start_scan_implementation) &&
+- (sm->stop_scan == ieee80211softmac_stop_scan_implementation) &&
+- (sm->wait_for_scan == ieee80211softmac_wait_for_scan_implementation);
+-}
+-
+-static inline int ieee80211softmac_scan_sanity_check(struct ieee80211softmac_device *sm)
+-{
+- return ((sm->start_scan != ieee80211softmac_start_scan_implementation) &&
+- (sm->stop_scan != ieee80211softmac_stop_scan_implementation) &&
+- (sm->wait_for_scan != ieee80211softmac_wait_for_scan_implementation)
+- ) || ieee80211softmac_scan_handlers_check_self(sm);
+-}
+-
+-#define IEEE80211SOFTMAC_PROBE_DELAY HZ/50
+-#define IEEE80211SOFTMAC_WORKQUEUE_NAME_LEN (17 + IFNAMSIZ)
+-
+-struct ieee80211softmac_network {
+- struct list_head list; /* List */
+- /* Network information copied from ieee80211_network */
+- u8 bssid[ETH_ALEN];
+- u8 channel;
+- struct ieee80211softmac_essid essid;
+-
+- struct ieee80211softmac_ratesinfo supported_rates;
+-
+- /* SoftMAC specific */
+- u16 authenticating:1, /* Status Flags */
+- authenticated:1,
+- auth_desynced_once:1;
+-
+- u8 erp_value; /* Saved ERP value */
+- u16 capabilities; /* Capabilities bitfield */
+- u8 challenge_len; /* Auth Challenge length */
+- char *challenge; /* Challenge Text */
+-};
+-
+-/* structure used to keep track of networks we're auth'ing to */
+-struct ieee80211softmac_auth_queue_item {
+- struct list_head list; /* List head */
+- struct ieee80211softmac_network *net; /* Network to auth */
+- struct ieee80211softmac_device *mac; /* SoftMAC device */
+- u8 retry; /* Retry limit */
+- u8 state; /* Auth State */
+- struct delayed_work work; /* Work queue */
+-};
+-
+-/* scanning information */
+-struct ieee80211softmac_scaninfo {
+- u8 current_channel_idx,
+- number_channels;
+- struct ieee80211_channel *channels;
+- u8 started:1,
+- stop:1;
+- u8 skip_flags;
+- struct completion finished;
+- struct delayed_work softmac_scan;
+- struct ieee80211softmac_device *mac;
+-};
+-
+-/* private event struct */
+-struct ieee80211softmac_event {
+- struct list_head list;
+- int event_type;
+- void *event_context;
+- struct delayed_work work;
+- notify_function_ptr fun;
+- void *context;
+- struct ieee80211softmac_device *mac;
+-};
+-
+-void ieee80211softmac_call_events(struct ieee80211softmac_device *mac, int event, void *event_context);
+-void ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_context);
+-int ieee80211softmac_notify_internal(struct ieee80211softmac_device *mac,
+- int event, void *event_context, notify_function_ptr fun, void *context, gfp_t gfp_mask);
+-
+-void ieee80211softmac_try_reassoc(struct ieee80211softmac_device *mac);
+-
+-#endif /* IEEE80211SOFTMAC_PRIV_H_ */
+diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c
+deleted file mode 100644
+index bfab8d7..0000000
+--- a/net/ieee80211/softmac/ieee80211softmac_scan.c
++++ /dev/null
+@@ -1,254 +0,0 @@
+-/*
+- * Scanning routines.
+- *
+- * These are not exported because they're assigned to the function pointers.
+- *
+- * Copyright (c) 2005, 2006 Johannes Berg <johannes at sipsolutions.net>
+- * Joseph Jezak <josejx at gentoo.org>
+- * Larry Finger <Larry.Finger at lwfinger.net>
+- * Danny van Dyk <kugelfang at gentoo.org>
+- * Michael Buesch <mbuesch at freenet.de>
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of version 2 of the GNU General Public License as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+- *
+- * The full GNU General Public License is included in this distribution in the
+- * file called COPYING.
+- */
+-
+-#include <linux/completion.h>
+-#include "ieee80211softmac_priv.h"
+-
+-/* internal, use to trigger scanning if needed.
+- * Returns -EBUSY if already scanning,
+- * result of start_scan otherwise */
+-int
+-ieee80211softmac_start_scan(struct ieee80211softmac_device *sm)
+-{
+- unsigned long flags;
+- int ret;
+-
+- spin_lock_irqsave(&sm->lock, flags);
+- if (sm->scanning)
+- {
+- spin_unlock_irqrestore(&sm->lock, flags);
+- return -EINPROGRESS;
+- }
+- sm->scanning = 1;
+- spin_unlock_irqrestore(&sm->lock, flags);
+-
+- ret = sm->start_scan(sm->dev);
+- if (ret) {
+- spin_lock_irqsave(&sm->lock, flags);
+- sm->scanning = 0;
+- spin_unlock_irqrestore(&sm->lock, flags);
+- }
+- return ret;
+-}
+-
+-void
+-ieee80211softmac_stop_scan(struct ieee80211softmac_device *sm)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&sm->lock, flags);
+-
+- if (!sm->scanning) {
+- spin_unlock_irqrestore(&sm->lock, flags);
+- return;
+- }
+-
+- spin_unlock_irqrestore(&sm->lock, flags);
+- sm->stop_scan(sm->dev);
+-}
+-
+-void
+-ieee80211softmac_wait_for_scan(struct ieee80211softmac_device *sm)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&sm->lock, flags);
+-
+- if (!sm->scanning) {
+- spin_unlock_irqrestore(&sm->lock, flags);
+- return;
+- }
+-
+- spin_unlock_irqrestore(&sm->lock, flags);
+- sm->wait_for_scan(sm->dev);
+-}
+-
+-
+-/* internal scanning implementation follows */
+-void ieee80211softmac_scan(struct work_struct *work)
+-{
+- int invalid_channel;
+- u8 current_channel_idx;
+- struct ieee80211softmac_scaninfo *si =
+- container_of(work, struct ieee80211softmac_scaninfo,
+- softmac_scan.work);
+- struct ieee80211softmac_device *sm = si->mac;
+- unsigned long flags;
+-
+- while (!(si->stop) && (si->current_channel_idx < si->number_channels)) {
+- current_channel_idx = si->current_channel_idx;
+- si->current_channel_idx++; /* go to the next channel */
+-
+- invalid_channel = (si->skip_flags & si->channels[current_channel_idx].flags);
+-
+- if (!invalid_channel) {
+- sm->set_channel(sm->dev, si->channels[current_channel_idx].channel);
+- // FIXME make this user configurable (active/passive)
+- if(ieee80211softmac_send_mgt_frame(sm, NULL, IEEE80211_STYPE_PROBE_REQ, 0))
+- printkl(KERN_DEBUG PFX "Sending Probe Request Failed\n");
+-
+- /* also send directed management frame for the network we're looking for */
+- // TODO: is this if correct, or should we do this only if scanning from assoc request?
+- if (sm->associnfo.req_essid.len)
+- ieee80211softmac_send_mgt_frame(sm, &sm->associnfo.req_essid, IEEE80211_STYPE_PROBE_REQ, 0);
+-
+- spin_lock_irqsave(&sm->lock, flags);
+- if (unlikely(!sm->running)) {
+- /* Prevent reschedule on workqueue flush */
+- spin_unlock_irqrestore(&sm->lock, flags);
+- break;
+- }
+- queue_delayed_work(sm->wq, &si->softmac_scan, IEEE80211SOFTMAC_PROBE_DELAY);
+- spin_unlock_irqrestore(&sm->lock, flags);
+- return;
+- } else {
+- dprintk(PFX "Not probing Channel %d (not allowed here)\n", si->channels[current_channel_idx].channel);
+- }
+- }
+-
+- spin_lock_irqsave(&sm->lock, flags);
+- cancel_delayed_work(&si->softmac_scan);
+- si->started = 0;
+- spin_unlock_irqrestore(&sm->lock, flags);
+-
+- dprintk(PFX "Scanning finished: scanned %d channels starting with channel %d\n",
+- sm->scaninfo->number_channels, sm->scaninfo->channels[0].channel);
+- ieee80211softmac_scan_finished(sm);
+- complete_all(&sm->scaninfo->finished);
+-}
+-
+-static inline struct ieee80211softmac_scaninfo *allocate_scaninfo(struct ieee80211softmac_device *mac)
+-{
+- /* ugh. can we call this without having the spinlock held? */
+- struct ieee80211softmac_scaninfo *info = kmalloc(sizeof(struct ieee80211softmac_scaninfo), GFP_ATOMIC);
+- if (unlikely(!info))
+- return NULL;
+- INIT_DELAYED_WORK(&info->softmac_scan, ieee80211softmac_scan);
+- info->mac = mac;
+- init_completion(&info->finished);
+- return info;
+-}
+-
+-int ieee80211softmac_start_scan_implementation(struct net_device *dev)
+-{
+- struct ieee80211softmac_device *sm = ieee80211_priv(dev);
+- unsigned long flags;
+-
+- if (!(dev->flags & IFF_UP))
+- return -ENODEV;
+-
+- assert(ieee80211softmac_scan_handlers_check_self(sm));
+- if (!ieee80211softmac_scan_handlers_check_self(sm))
+- return -EINVAL;
+-
+- spin_lock_irqsave(&sm->lock, flags);
+- /* it looks like we need to hold the lock here
+- * to make sure we don't allocate two of these... */
+- if (unlikely(!sm->scaninfo))
+- sm->scaninfo = allocate_scaninfo(sm);
+- if (unlikely(!sm->scaninfo)) {
+- spin_unlock_irqrestore(&sm->lock, flags);
+- return -ENOMEM;
+- }
+-
+- sm->scaninfo->skip_flags = IEEE80211_CH_INVALID;
+- if (0 /* not scanning in IEEE802.11b */)//TODO
+- sm->scaninfo->skip_flags |= IEEE80211_CH_B_ONLY;
+- if (0 /* IEEE802.11a */) {//TODO
+- sm->scaninfo->channels = sm->ieee->geo.a;
+- sm->scaninfo->number_channels = sm->ieee->geo.a_channels;
+- } else {
+- sm->scaninfo->channels = sm->ieee->geo.bg;
+- sm->scaninfo->number_channels = sm->ieee->geo.bg_channels;
+- }
+- sm->scaninfo->current_channel_idx = 0;
+- sm->scaninfo->started = 1;
+- sm->scaninfo->stop = 0;
+- INIT_COMPLETION(sm->scaninfo->finished);
+- queue_delayed_work(sm->wq, &sm->scaninfo->softmac_scan, 0);
+- spin_unlock_irqrestore(&sm->lock, flags);
+- return 0;
+-}
+-
+-void ieee80211softmac_stop_scan_implementation(struct net_device *dev)
+-{
+- struct ieee80211softmac_device *sm = ieee80211_priv(dev);
+- unsigned long flags;
+-
+- assert(ieee80211softmac_scan_handlers_check_self(sm));
+- if (!ieee80211softmac_scan_handlers_check_self(sm))
+- return;
+-
+- spin_lock_irqsave(&sm->lock, flags);
+- assert(sm->scaninfo != NULL);
+- if (sm->scaninfo) {
+- if (sm->scaninfo->started)
+- sm->scaninfo->stop = 1;
+- else
+- complete_all(&sm->scaninfo->finished);
+- }
+- spin_unlock_irqrestore(&sm->lock, flags);
+-}
+-
+-void ieee80211softmac_wait_for_scan_implementation(struct net_device *dev)
+-{
+- struct ieee80211softmac_device *sm = ieee80211_priv(dev);
+- unsigned long flags;
+-
+- assert(ieee80211softmac_scan_handlers_check_self(sm));
+- if (!ieee80211softmac_scan_handlers_check_self(sm))
+- return;
+-
+- spin_lock_irqsave(&sm->lock, flags);
+- if (!sm->scaninfo->started) {
+- spin_unlock_irqrestore(&sm->lock, flags);
+- return;
+- }
+- spin_unlock_irqrestore(&sm->lock, flags);
+- wait_for_completion(&sm->scaninfo->finished);
+-}
+-
+-/* this is what drivers (that do scanning) call when they're done */
+-void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm)
+-{
+- unsigned long flags;
+-
+- spin_lock_irqsave(&sm->lock, flags);
+- sm->scanning = 0;
+- spin_unlock_irqrestore(&sm->lock, flags);
+-
+- if (sm->associnfo.bssvalid) {
+- struct ieee80211softmac_network *net;
+-
+- net = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid);
+- if (net)
+- sm->set_channel(sm->dev, net->channel);
+- }
+- ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL);
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished);
+diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c
+deleted file mode 100644
+index e01b59a..0000000
+--- a/net/ieee80211/softmac/ieee80211softmac_wx.c
++++ /dev/null
+@@ -1,508 +0,0 @@
+-/*
+- * This file contains our _wx handlers. Make sure you EXPORT_SYMBOL_GPL them
+- *
+- * Copyright (c) 2005, 2006 Johannes Berg <johannes at sipsolutions.net>
+- * Joseph Jezak <josejx at gentoo.org>
+- * Larry Finger <Larry.Finger at lwfinger.net>
+- * Danny van Dyk <kugelfang at gentoo.org>
+- * Michael Buesch <mbuesch at freenet.de>
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of version 2 of the GNU General Public License as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+- *
+- * The full GNU General Public License is included in this distribution in the
+- * file called COPYING.
+- */
+-
+-#include "ieee80211softmac_priv.h"
+-
+-#include <net/iw_handler.h>
+-/* for is_broadcast_ether_addr and is_zero_ether_addr */
+-#include <linux/etherdevice.h>
+-
+-int
+-ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
+- return ieee80211softmac_start_scan(sm);
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan);
+-
+-
+-/* if we're still scanning, return -EAGAIN so that userspace tools
+- * can get the complete scan results, otherwise return 0. */
+-int
+-ieee80211softmac_wx_get_scan_results(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- unsigned long flags;
+- struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
+-
+- spin_lock_irqsave(&sm->lock, flags);
+- if (sm->scanning) {
+- spin_unlock_irqrestore(&sm->lock, flags);
+- return -EAGAIN;
+- }
+- spin_unlock_irqrestore(&sm->lock, flags);
+- return ieee80211_wx_get_scan(sm->ieee, info, data, extra);
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results);
+-
+-int
+-ieee80211softmac_wx_set_essid(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
+- struct ieee80211softmac_auth_queue_item *authptr;
+- int length = 0;
+- DECLARE_MAC_BUF(mac);
+-
+-check_assoc_again:
+- mutex_lock(&sm->associnfo.mutex);
+- if((sm->associnfo.associating || sm->associnfo.associated) &&
+- (data->essid.flags && data->essid.length)) {
+- dprintk(KERN_INFO PFX "Canceling existing associate request!\n");
+- /* Cancel assoc work */
+- cancel_delayed_work(&sm->associnfo.work);
+- /* We don't have to do this, but it's a little cleaner */
+- list_for_each_entry(authptr, &sm->auth_queue, list)
+- cancel_delayed_work(&authptr->work);
+- sm->associnfo.bssvalid = 0;
+- sm->associnfo.bssfixed = 0;
+- sm->associnfo.associating = 0;
+- sm->associnfo.associated = 0;
+- /* We must unlock to avoid deadlocks with the assoc workqueue
+- * on the associnfo.mutex */
+- mutex_unlock(&sm->associnfo.mutex);
+- flush_workqueue(sm->wq);
+- /* Avoid race! Check assoc status again. Maybe someone started an
+- * association while we flushed. */
+- goto check_assoc_again;
+- }
+-
+- sm->associnfo.static_essid = 0;
+- sm->associnfo.assoc_wait = 0;
+-
+- if (data->essid.flags && data->essid.length) {
+- length = min((int)data->essid.length, IW_ESSID_MAX_SIZE);
+- if (length) {
+- memcpy(sm->associnfo.req_essid.data, extra, length);
+- sm->associnfo.static_essid = 1;
+- }
+- }
+-
+- /* set our requested ESSID length.
+- * If applicable, we have already copied the data in */
+- sm->associnfo.req_essid.len = length;
+-
+- sm->associnfo.associating = 1;
+- /* queue lower level code to do work (if necessary) */
+- queue_delayed_work(sm->wq, &sm->associnfo.work, 0);
+-
+- mutex_unlock(&sm->associnfo.mutex);
+-
+- return 0;
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid);
+-
+-int
+-ieee80211softmac_wx_get_essid(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
+-
+- mutex_lock(&sm->associnfo.mutex);
+- /* If all fails, return ANY (empty) */
+- data->essid.length = 0;
+- data->essid.flags = 0; /* active */
+-
+- /* If we have a statically configured ESSID then return it */
+- if (sm->associnfo.static_essid) {
+- data->essid.length = sm->associnfo.req_essid.len;
+- data->essid.flags = 1; /* active */
+- memcpy(extra, sm->associnfo.req_essid.data, sm->associnfo.req_essid.len);
+- dprintk(KERN_INFO PFX "Getting essid from req_essid\n");
+- } else if (sm->associnfo.associated || sm->associnfo.associating) {
+- /* If we're associating/associated, return that */
+- data->essid.length = sm->associnfo.associate_essid.len;
+- data->essid.flags = 1; /* active */
+- memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len);
+- dprintk(KERN_INFO PFX "Getting essid from associate_essid\n");
+- }
+- mutex_unlock(&sm->associnfo.mutex);
+-
+- return 0;
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid);
+-
+-int
+-ieee80211softmac_wx_set_rate(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
+- struct ieee80211_device *ieee = mac->ieee;
+- unsigned long flags;
+- s32 in_rate = data->bitrate.value;
+- u8 rate;
+- int is_ofdm = 0;
+- int err = -EINVAL;
+-
+- if (in_rate == -1) {
+- if (ieee->modulation & IEEE80211_OFDM_MODULATION)
+- in_rate = 24000000;
+- else
+- in_rate = 11000000;
+- }
+-
+- switch (in_rate) {
+- case 1000000:
+- rate = IEEE80211_CCK_RATE_1MB;
+- break;
+- case 2000000:
+- rate = IEEE80211_CCK_RATE_2MB;
+- break;
+- case 5500000:
+- rate = IEEE80211_CCK_RATE_5MB;
+- break;
+- case 11000000:
+- rate = IEEE80211_CCK_RATE_11MB;
+- break;
+- case 6000000:
+- rate = IEEE80211_OFDM_RATE_6MB;
+- is_ofdm = 1;
+- break;
+- case 9000000:
+- rate = IEEE80211_OFDM_RATE_9MB;
+- is_ofdm = 1;
+- break;
+- case 12000000:
+- rate = IEEE80211_OFDM_RATE_12MB;
+- is_ofdm = 1;
+- break;
+- case 18000000:
+- rate = IEEE80211_OFDM_RATE_18MB;
+- is_ofdm = 1;
+- break;
+- case 24000000:
+- rate = IEEE80211_OFDM_RATE_24MB;
+- is_ofdm = 1;
+- break;
+- case 36000000:
+- rate = IEEE80211_OFDM_RATE_36MB;
+- is_ofdm = 1;
+- break;
+- case 48000000:
+- rate = IEEE80211_OFDM_RATE_48MB;
+- is_ofdm = 1;
+- break;
+- case 54000000:
+- rate = IEEE80211_OFDM_RATE_54MB;
+- is_ofdm = 1;
+- break;
+- default:
+- goto out;
+- }
+-
+- spin_lock_irqsave(&mac->lock, flags);
+-
+- /* Check if correct modulation for this PHY. */
+- if (is_ofdm && !(ieee->modulation & IEEE80211_OFDM_MODULATION))
+- goto out_unlock;
+-
+- mac->txrates.user_rate = rate;
+- ieee80211softmac_recalc_txrates(mac);
+- err = 0;
+-
+-out_unlock:
+- spin_unlock_irqrestore(&mac->lock, flags);
+-out:
+- return err;
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_rate);
+-
+-int
+-ieee80211softmac_wx_get_rate(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
+- unsigned long flags;
+- int err = -EINVAL;
+-
+- spin_lock_irqsave(&mac->lock, flags);
+-
+- if (unlikely(!mac->running)) {
+- err = -ENODEV;
+- goto out_unlock;
+- }
+-
+- switch (mac->txrates.default_rate) {
+- case IEEE80211_CCK_RATE_1MB:
+- data->bitrate.value = 1000000;
+- break;
+- case IEEE80211_CCK_RATE_2MB:
+- data->bitrate.value = 2000000;
+- break;
+- case IEEE80211_CCK_RATE_5MB:
+- data->bitrate.value = 5500000;
+- break;
+- case IEEE80211_CCK_RATE_11MB:
+- data->bitrate.value = 11000000;
+- break;
+- case IEEE80211_OFDM_RATE_6MB:
+- data->bitrate.value = 6000000;
+- break;
+- case IEEE80211_OFDM_RATE_9MB:
+- data->bitrate.value = 9000000;
+- break;
+- case IEEE80211_OFDM_RATE_12MB:
+- data->bitrate.value = 12000000;
+- break;
+- case IEEE80211_OFDM_RATE_18MB:
+- data->bitrate.value = 18000000;
+- break;
+- case IEEE80211_OFDM_RATE_24MB:
+- data->bitrate.value = 24000000;
+- break;
+- case IEEE80211_OFDM_RATE_36MB:
+- data->bitrate.value = 36000000;
+- break;
+- case IEEE80211_OFDM_RATE_48MB:
+- data->bitrate.value = 48000000;
+- break;
+- case IEEE80211_OFDM_RATE_54MB:
+- data->bitrate.value = 54000000;
+- break;
+- default:
+- assert(0);
+- goto out_unlock;
+- }
+- err = 0;
+-out_unlock:
+- spin_unlock_irqrestore(&mac->lock, flags);
+-
+- return err;
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_rate);
+-
+-int
+-ieee80211softmac_wx_get_wap(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
+- int err = 0;
+-
+- mutex_lock(&mac->associnfo.mutex);
+- if (mac->associnfo.bssvalid)
+- memcpy(data->ap_addr.sa_data, mac->associnfo.bssid, ETH_ALEN);
+- else
+- memset(data->ap_addr.sa_data, 0xff, ETH_ALEN);
+- data->ap_addr.sa_family = ARPHRD_ETHER;
+- mutex_unlock(&mac->associnfo.mutex);
+-
+- return err;
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap);
+-
+-int
+-ieee80211softmac_wx_set_wap(struct net_device *net_dev,
+- struct iw_request_info *info,
+- union iwreq_data *data,
+- char *extra)
+-{
+- struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
+-
+- /* sanity check */
+- if (data->ap_addr.sa_family != ARPHRD_ETHER) {
+- return -EINVAL;
+- }
+-
+- mutex_lock(&mac->associnfo.mutex);
+- if (is_broadcast_ether_addr(data->ap_addr.sa_data)) {
+- /* the bssid we have is not to be fixed any longer,
+- * and we should reassociate to the best AP. */
+- mac->associnfo.bssfixed = 0;
+- /* force reassociation */
+- mac->associnfo.bssvalid = 0;
+- if (mac->associnfo.associated)
+- queue_delayed_work(mac->wq, &mac->associnfo.work, 0);
+- } else if (is_zero_ether_addr(data->ap_addr.sa_data)) {
+- /* the bssid we have is no longer fixed */
+- mac->associnfo.bssfixed = 0;
+- } else {
+- if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) {
+- if (mac->associnfo.associating || mac->associnfo.associated) {
+- /* bssid unchanged and associated or associating - just return */
+- goto out;
+- }
+- } else {
+- /* copy new value in data->ap_addr.sa_data to bssid */
+- memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN);
+- }
+- /* tell the other code that this bssid should be used no matter what */
+- mac->associnfo.bssfixed = 1;
+- /* queue associate if new bssid or (old one again and not associated) */
+- queue_delayed_work(mac->wq, &mac->associnfo.work, 0);
+- }
+-
+- out:
+- mutex_unlock(&mac->associnfo.mutex);
+-
+- return 0;
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap);
+-
+-int
+-ieee80211softmac_wx_set_genie(struct net_device *dev,
+- struct iw_request_info *info,
+- union iwreq_data *wrqu,
+- char *extra)
+-{
+- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+- unsigned long flags;
+- int err = 0;
+- char *buf;
+- int i;
+-
+- mutex_lock(&mac->associnfo.mutex);
+- spin_lock_irqsave(&mac->lock, flags);
+- /* bleh. shouldn't be locked for that kmalloc... */
+-
+- if (wrqu->data.length) {
+- if ((wrqu->data.length < 2) || (extra[1]+2 != wrqu->data.length)) {
+- /* this is an IE, so the length must be
+- * correct. Is it possible though that
+- * more than one IE is passed in?
+- */
+- err = -EINVAL;
+- goto out;
+- }
+- if (mac->wpa.IEbuflen <= wrqu->data.length) {
+- buf = kmalloc(wrqu->data.length, GFP_ATOMIC);
+- if (!buf) {
+- err = -ENOMEM;
+- goto out;
+- }
+- kfree(mac->wpa.IE);
+- mac->wpa.IE = buf;
+- mac->wpa.IEbuflen = wrqu->data.length;
+- }
+- memcpy(mac->wpa.IE, extra, wrqu->data.length);
+- dprintk(KERN_INFO PFX "generic IE set to ");
+- for (i=0;i<wrqu->data.length;i++)
+- dprintk("%.2x", (u8)mac->wpa.IE[i]);
+- dprintk("\n");
+- mac->wpa.IElen = wrqu->data.length;
+- } else {
+- kfree(mac->wpa.IE);
+- mac->wpa.IE = NULL;
+- mac->wpa.IElen = 0;
+- mac->wpa.IEbuflen = 0;
+- }
+-
+- out:
+- spin_unlock_irqrestore(&mac->lock, flags);
+- mutex_unlock(&mac->associnfo.mutex);
+-
+- return err;
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie);
+-
+-int
+-ieee80211softmac_wx_get_genie(struct net_device *dev,
+- struct iw_request_info *info,
+- union iwreq_data *wrqu,
+- char *extra)
+-{
+- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+- unsigned long flags;
+- int err = 0;
+- int space = wrqu->data.length;
+-
+- mutex_lock(&mac->associnfo.mutex);
+- spin_lock_irqsave(&mac->lock, flags);
+-
+- wrqu->data.length = 0;
+-
+- if (mac->wpa.IE && mac->wpa.IElen) {
+- wrqu->data.length = mac->wpa.IElen;
+- if (mac->wpa.IElen <= space)
+- memcpy(extra, mac->wpa.IE, mac->wpa.IElen);
+- else
+- err = -E2BIG;
+- }
+- spin_unlock_irqrestore(&mac->lock, flags);
+- mutex_unlock(&mac->associnfo.mutex);
+-
+- return err;
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie);
+-
+-int
+-ieee80211softmac_wx_set_mlme(struct net_device *dev,
+- struct iw_request_info *info,
+- union iwreq_data *wrqu,
+- char *extra)
+-{
+- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+- struct iw_mlme *mlme = (struct iw_mlme *)extra;
+- u16 reason = mlme->reason_code;
+- struct ieee80211softmac_network *net;
+- int err = -EINVAL;
+-
+- mutex_lock(&mac->associnfo.mutex);
+-
+- if (memcmp(mac->associnfo.bssid, mlme->addr.sa_data, ETH_ALEN)) {
+- printk(KERN_DEBUG PFX "wx_set_mlme: requested operation on net we don't use\n");
+- goto out;
+- }
+-
+- switch (mlme->cmd) {
+- case IW_MLME_DEAUTH:
+- net = ieee80211softmac_get_network_by_bssid_locked(mac, mlme->addr.sa_data);
+- if (!net) {
+- printk(KERN_DEBUG PFX "wx_set_mlme: we should know the net here...\n");
+- goto out;
+- }
+- err = ieee80211softmac_deauth_req(mac, net, reason);
+- goto out;
+- case IW_MLME_DISASSOC:
+- ieee80211softmac_send_disassoc_req(mac, reason);
+- mac->associnfo.associated = 0;
+- mac->associnfo.associating = 0;
+- err = 0;
+- goto out;
+- default:
+- err = -EOPNOTSUPP;
+- }
+-
+-out:
+- mutex_unlock(&mac->associnfo.mutex);
+-
+- return err;
+-}
+-EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_mlme);
+diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
+index 0d10950..f2b5270 100644
+--- a/net/ipv4/af_inet.c
++++ b/net/ipv4/af_inet.c
+@@ -243,6 +243,23 @@ void build_ehash_secret(void)
+ }
+ EXPORT_SYMBOL(build_ehash_secret);
+
++static inline int inet_netns_ok(struct net *net, int protocol)
++{
++ int hash;
++ struct net_protocol *ipprot;
++
++ if (net == &init_net)
++ return 1;
++
++ hash = protocol & (MAX_INET_PROTOS - 1);
++ ipprot = rcu_dereference(inet_protos[hash]);
++
++ if (ipprot == NULL)
++ /* raw IP is OK */
++ return 1;
++ return ipprot->netns_ok;
++}
++
+ /*
+ * Create an inet socket.
+ */
+@@ -259,9 +276,6 @@ static int inet_create(struct net *net, struct socket *sock, int protocol)
+ int try_loading_module = 0;
+ int err;
+
+- if (net != &init_net)
+- return -EAFNOSUPPORT;
+-
+ if (sock->type != SOCK_RAW &&
+ sock->type != SOCK_DGRAM &&
+ !inet_ehash_secret)
+@@ -320,6 +334,10 @@ lookup_protocol:
+ if (answer->capability > 0 && !capable(answer->capability))
+ goto out_rcu_unlock;
+
++ err = -EAFNOSUPPORT;
++ if (!inet_netns_ok(net, protocol))
++ goto out_rcu_unlock;
++
+ sock->ops = answer->ops;
+ answer_prot = answer->prot;
+ answer_no_check = answer->no_check;
+@@ -446,7 +464,7 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ if (addr_len < sizeof(struct sockaddr_in))
+ goto out;
+
+- chk_addr_ret = inet_addr_type(&init_net, addr->sin_addr.s_addr);
++ chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr);
+
+ /* Not specified by any standard per-se, however it breaks too
+ * many applications when removed. It is unfortunate since
+@@ -784,6 +802,7 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+ {
+ struct sock *sk = sock->sk;
+ int err = 0;
++ struct net *net = sock_net(sk);
+
+ switch (cmd) {
+ case SIOCGSTAMP:
+@@ -795,12 +814,12 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+ case SIOCADDRT:
+ case SIOCDELRT:
+ case SIOCRTMSG:
+- err = ip_rt_ioctl(sk->sk_net, cmd, (void __user *)arg);
++ err = ip_rt_ioctl(net, cmd, (void __user *)arg);
+ break;
+ case SIOCDARP:
+ case SIOCGARP:
+ case SIOCSARP:
+- err = arp_ioctl(sk->sk_net, cmd, (void __user *)arg);
++ err = arp_ioctl(net, cmd, (void __user *)arg);
+ break;
+ case SIOCGIFADDR:
+ case SIOCSIFADDR:
+@@ -813,7 +832,7 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+ case SIOCSIFPFLAGS:
+ case SIOCGIFPFLAGS:
+ case SIOCSIFFLAGS:
+- err = devinet_ioctl(cmd, (void __user *)arg);
++ err = devinet_ioctl(net, cmd, (void __user *)arg);
+ break;
+ default:
+ if (sk->sk_prot->ioctl)
+@@ -1058,8 +1077,8 @@ static int inet_sk_reselect_saddr(struct sock *sk)
+
+ if (sysctl_ip_dynaddr > 1) {
+ printk(KERN_INFO "%s(): shifting inet->"
+- "saddr from %d.%d.%d.%d to %d.%d.%d.%d\n",
+- __FUNCTION__,
++ "saddr from " NIPQUAD_FMT " to " NIPQUAD_FMT "\n",
++ __func__,
+ NIPQUAD(old_saddr),
+ NIPQUAD(new_saddr));
+ }
+@@ -1113,7 +1132,7 @@ int inet_sk_rebuild_header(struct sock *sk)
+ };
+
+ security_sk_classify_flow(sk, &fl);
+- err = ip_route_output_flow(&init_net, &rt, &fl, sk, 0);
++ err = ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 0);
+ }
+ if (!err)
+ sk_setup_caps(sk, &rt->u.dst);
+@@ -1231,6 +1250,29 @@ out:
+ return segs;
+ }
+
++int inet_ctl_sock_create(struct sock **sk, unsigned short family,
++ unsigned short type, unsigned char protocol,
++ struct net *net)
++{
++ struct socket *sock;
++ int rc = sock_create_kern(family, type, protocol, &sock);
++
++ if (rc == 0) {
++ *sk = sock->sk;
++ (*sk)->sk_allocation = GFP_ATOMIC;
++ /*
++ * Unhash it so that IP input processing does not even see it,
++ * we do not wish this socket to see incoming packets.
++ */
++ (*sk)->sk_prot->unhash(*sk);
++
++ sk_change_net(*sk, net);
++ }
++ return rc;
++}
++
++EXPORT_SYMBOL_GPL(inet_ctl_sock_create);
++
+ unsigned long snmp_fold_field(void *mib[], int offt)
+ {
+ unsigned long res = 0;
+@@ -1283,17 +1325,20 @@ static struct net_protocol tcp_protocol = {
+ .gso_send_check = tcp_v4_gso_send_check,
+ .gso_segment = tcp_tso_segment,
+ .no_policy = 1,
++ .netns_ok = 1,
+ };
+
+ static struct net_protocol udp_protocol = {
+ .handler = udp_rcv,
+ .err_handler = udp_err,
+ .no_policy = 1,
++ .netns_ok = 1,
+ };
+
+ static struct net_protocol icmp_protocol = {
+ .handler = icmp_rcv,
+ .no_policy = 1,
++ .netns_ok = 1,
+ };
+
+ static int __init init_ipv4_mibs(void)
+@@ -1414,7 +1459,7 @@ static int __init inet_init(void)
+
+ ip_init();
+
+- tcp_v4_init(&inet_family_ops);
++ tcp_v4_init();
+
+ /* Setup TCP slab cache for open requests. */
+ tcp_init();
+@@ -1429,7 +1474,8 @@ static int __init inet_init(void)
+ * Set the ICMP layer up
+ */
+
+- icmp_init(&inet_family_ops);
++ if (icmp_init() < 0)
++ panic("Failed to create the ICMP control socket.\n");
+
+ /*
+ * Initialise the multicast router
+diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
+index 8e17f65..68b72a7 100644
+--- a/net/ipv4/arp.c
++++ b/net/ipv4/arp.c
+@@ -242,7 +242,7 @@ static int arp_constructor(struct neighbour *neigh)
+ return -EINVAL;
+ }
+
+- neigh->type = inet_addr_type(&init_net, addr);
++ neigh->type = inet_addr_type(dev_net(dev), addr);
+
+ parms = in_dev->arp_parms;
+ __neigh_parms_put(neigh->parms);
+@@ -341,14 +341,14 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
+ switch (IN_DEV_ARP_ANNOUNCE(in_dev)) {
+ default:
+ case 0: /* By default announce any local IP */
+- if (skb && inet_addr_type(&init_net, ip_hdr(skb)->saddr) == RTN_LOCAL)
++ if (skb && inet_addr_type(dev_net(dev), ip_hdr(skb)->saddr) == RTN_LOCAL)
+ saddr = ip_hdr(skb)->saddr;
+ break;
+ case 1: /* Restrict announcements of saddr in same subnet */
+ if (!skb)
+ break;
+ saddr = ip_hdr(skb)->saddr;
+- if (inet_addr_type(&init_net, saddr) == RTN_LOCAL) {
++ if (inet_addr_type(dev_net(dev), saddr) == RTN_LOCAL) {
+ /* saddr should be known to target */
+ if (inet_addr_onlink(in_dev, target, saddr))
+ break;
+@@ -424,7 +424,7 @@ static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev)
+ int flag = 0;
+ /*unsigned long now; */
+
+- if (ip_route_output_key(&init_net, &rt, &fl) < 0)
++ if (ip_route_output_key(dev_net(dev), &rt, &fl) < 0)
+ return 1;
+ if (rt->u.dst.dev != dev) {
+ NET_INC_STATS_BH(LINUX_MIB_ARPFILTER);
+@@ -475,9 +475,9 @@ int arp_find(unsigned char *haddr, struct sk_buff *skb)
+ return 1;
+ }
+
+- paddr = ((struct rtable*)skb->dst)->rt_gateway;
++ paddr = skb->rtable->rt_gateway;
+
+- if (arp_set_predefined(inet_addr_type(&init_net, paddr), haddr, paddr, dev))
++ if (arp_set_predefined(inet_addr_type(dev_net(dev), paddr), haddr, paddr, dev))
+ return 0;
+
+ n = __neigh_lookup(&arp_tbl, &paddr, dev, 1);
+@@ -570,14 +570,13 @@ struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
+ * Allocate a buffer
+ */
+
+- skb = alloc_skb(sizeof(struct arphdr)+ 2*(dev->addr_len+4)
+- + LL_RESERVED_SPACE(dev), GFP_ATOMIC);
++ skb = alloc_skb(arp_hdr_len(dev) + LL_RESERVED_SPACE(dev), GFP_ATOMIC);
+ if (skb == NULL)
+ return NULL;
+
+ skb_reserve(skb, LL_RESERVED_SPACE(dev));
+ skb_reset_network_header(skb);
+- arp = (struct arphdr *) skb_put(skb,sizeof(struct arphdr) + 2*(dev->addr_len+4));
++ arp = (struct arphdr *) skb_put(skb, arp_hdr_len(dev));
+ skb->dev = dev;
+ skb->protocol = htons(ETH_P_ARP);
+ if (src_hw == NULL)
+@@ -710,6 +709,7 @@ static int arp_process(struct sk_buff *skb)
+ u16 dev_type = dev->type;
+ int addr_type;
+ struct neighbour *n;
++ struct net *net = dev_net(dev);
+
+ /* arp_rcv below verifies the ARP header and verifies the device
+ * is ARP'able.
+@@ -805,7 +805,7 @@ static int arp_process(struct sk_buff *skb)
+ /* Special case: IPv4 duplicate address detection packet (RFC2131) */
+ if (sip == 0) {
+ if (arp->ar_op == htons(ARPOP_REQUEST) &&
+- inet_addr_type(&init_net, tip) == RTN_LOCAL &&
++ inet_addr_type(net, tip) == RTN_LOCAL &&
+ !arp_ignore(in_dev, sip, tip))
+ arp_send(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha,
+ dev->dev_addr, sha);
+@@ -815,7 +815,7 @@ static int arp_process(struct sk_buff *skb)
+ if (arp->ar_op == htons(ARPOP_REQUEST) &&
+ ip_route_input(skb, tip, sip, 0, dev) == 0) {
+
+- rt = (struct rtable*)skb->dst;
++ rt = skb->rtable;
+ addr_type = rt->rt_type;
+
+ if (addr_type == RTN_LOCAL) {
+@@ -835,7 +835,7 @@ static int arp_process(struct sk_buff *skb)
+ goto out;
+ } else if (IN_DEV_FORWARD(in_dev)) {
+ if (addr_type == RTN_UNICAST && rt->u.dst.dev != dev &&
+- (arp_fwd_proxy(in_dev, rt) || pneigh_lookup(&arp_tbl, &init_net, &tip, dev, 0))) {
++ (arp_fwd_proxy(in_dev, rt) || pneigh_lookup(&arp_tbl, net, &tip, dev, 0))) {
+ n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
+ if (n)
+ neigh_release(n);
+@@ -858,14 +858,14 @@ static int arp_process(struct sk_buff *skb)
+
+ n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
+
+- if (IPV4_DEVCONF_ALL(dev->nd_net, ARP_ACCEPT)) {
++ if (IPV4_DEVCONF_ALL(dev_net(dev), ARP_ACCEPT)) {
+ /* Unsolicited ARP is not accepted by default.
+ It is possible, that this option should be enabled for some
+ devices (strip is candidate)
+ */
+ if (n == NULL &&
+ arp->ar_op == htons(ARPOP_REPLY) &&
+- inet_addr_type(&init_net, sip) == RTN_UNICAST)
++ inet_addr_type(net, sip) == RTN_UNICAST)
+ n = __neigh_lookup(&arp_tbl, &sip, dev, 1);
+ }
+
+@@ -912,13 +912,8 @@ static int arp_rcv(struct sk_buff *skb, struct net_device *dev,
+ {
+ struct arphdr *arp;
+
+- if (dev->nd_net != &init_net)
+- goto freeskb;
+-
+ /* ARP header, plus 2 device addresses, plus 2 IP addresses. */
+- if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
+- (2 * dev->addr_len) +
+- (2 * sizeof(u32)))))
++ if (!pskb_may_pull(skb, arp_hdr_len(dev)))
+ goto freeskb;
+
+ arp = arp_hdr(skb);
+@@ -1201,9 +1196,6 @@ static int arp_netdev_event(struct notifier_block *this, unsigned long event, vo
+ {
+ struct net_device *dev = ptr;
+
+- if (dev->nd_net != &init_net)
+- return NOTIFY_DONE;
+-
+ switch (event) {
+ case NETDEV_CHANGEADDR:
+ neigh_changeaddr(&arp_tbl, dev);
+@@ -1318,7 +1310,7 @@ static void arp_format_neigh_entry(struct seq_file *seq,
+ #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
+ }
+ #endif
+- sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->primary_key));
++ sprintf(tbuf, NIPQUAD_FMT, NIPQUAD(*(u32*)n->primary_key));
+ seq_printf(seq, "%-16s 0x%-10x0x%-10x%s * %s\n",
+ tbuf, hatype, arp_state_to_flags(n), hbuffer, dev->name);
+ read_unlock(&n->lock);
+@@ -1331,7 +1323,7 @@ static void arp_format_pneigh_entry(struct seq_file *seq,
+ int hatype = dev ? dev->type : 0;
+ char tbuf[16];
+
+- sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->key));
++ sprintf(tbuf, NIPQUAD_FMT, NIPQUAD(*(u32*)n->key));
+ seq_printf(seq, "%-16s 0x%-10x0x%-10x%s * %s\n",
+ tbuf, hatype, ATF_PUBL | ATF_PERM, "00:00:00:00:00:00",
+ dev ? dev->name : "*");
+@@ -1385,13 +1377,29 @@ static const struct file_operations arp_seq_fops = {
+ .release = seq_release_net,
+ };
+
+-static int __init arp_proc_init(void)
++
++static int __net_init arp_net_init(struct net *net)
+ {
+- if (!proc_net_fops_create(&init_net, "arp", S_IRUGO, &arp_seq_fops))
++ if (!proc_net_fops_create(net, "arp", S_IRUGO, &arp_seq_fops))
+ return -ENOMEM;
+ return 0;
+ }
+
++static void __net_exit arp_net_exit(struct net *net)
++{
++ proc_net_remove(net, "arp");
++}
++
++static struct pernet_operations arp_net_ops = {
++ .init = arp_net_init,
++ .exit = arp_net_exit,
++};
++
++static int __init arp_proc_init(void)
++{
++ return register_pernet_subsys(&arp_net_ops);
++}
++
+ #else /* CONFIG_PROC_FS */
+
+ static int __init arp_proc_init(void)
+diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
+index 8cd357f..4637ded 100644
+--- a/net/ipv4/cipso_ipv4.c
++++ b/net/ipv4/cipso_ipv4.c
+@@ -1800,7 +1800,6 @@ int cipso_v4_sock_setattr(struct sock *sk,
+ }
+ memcpy(opt->__data, buf, buf_len);
+ opt->optlen = opt_len;
+- opt->is_data = 1;
+ opt->cipso = sizeof(struct iphdr);
+ kfree(buf);
+ buf = NULL;
+diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
+index 87490f7..6848e47 100644
+--- a/net/ipv4/devinet.c
++++ b/net/ipv4/devinet.c
+@@ -165,7 +165,7 @@ static struct in_device *inetdev_init(struct net_device *dev)
+ if (!in_dev)
+ goto out;
+ INIT_RCU_HEAD(&in_dev->rcu_head);
+- memcpy(&in_dev->cnf, dev->nd_net->ipv4.devconf_dflt,
++ memcpy(&in_dev->cnf, dev_net(dev)->ipv4.devconf_dflt,
+ sizeof(in_dev->cnf));
+ in_dev->cnf.sysctl = NULL;
+ in_dev->dev = dev;
+@@ -437,7 +437,7 @@ struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix,
+
+ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct nlattr *tb[IFA_MAX+1];
+ struct in_device *in_dev;
+ struct ifaddrmsg *ifm;
+@@ -446,9 +446,6 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg
+
+ ASSERT_RTNL();
+
+- if (net != &init_net)
+- return -EINVAL;
+-
+ err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy);
+ if (err < 0)
+ goto errout;
+@@ -555,14 +552,11 @@ errout:
+
+ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct in_ifaddr *ifa;
+
+ ASSERT_RTNL();
+
+- if (net != &init_net)
+- return -EINVAL;
+-
+ ifa = rtm_to_ifaddr(net, nlh);
+ if (IS_ERR(ifa))
+ return PTR_ERR(ifa);
+@@ -595,7 +589,7 @@ static __inline__ int inet_abc_len(__be32 addr)
+ }
+
+
+-int devinet_ioctl(unsigned int cmd, void __user *arg)
++int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
+ {
+ struct ifreq ifr;
+ struct sockaddr_in sin_orig;
+@@ -624,7 +618,7 @@ int devinet_ioctl(unsigned int cmd, void __user *arg)
+ *colon = 0;
+
+ #ifdef CONFIG_KMOD
+- dev_load(&init_net, ifr.ifr_name);
++ dev_load(net, ifr.ifr_name);
+ #endif
+
+ switch (cmd) {
+@@ -665,7 +659,7 @@ int devinet_ioctl(unsigned int cmd, void __user *arg)
+ rtnl_lock();
+
+ ret = -ENODEV;
+- if ((dev = __dev_get_by_name(&init_net, ifr.ifr_name)) == NULL)
++ if ((dev = __dev_get_by_name(net, ifr.ifr_name)) == NULL)
+ goto done;
+
+ if (colon)
+@@ -878,6 +872,7 @@ __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope)
+ {
+ __be32 addr = 0;
+ struct in_device *in_dev;
++ struct net *net = dev_net(dev);
+
+ rcu_read_lock();
+ in_dev = __in_dev_get_rcu(dev);
+@@ -906,7 +901,7 @@ no_in_dev:
+ */
+ read_lock(&dev_base_lock);
+ rcu_read_lock();
+- for_each_netdev(&init_net, dev) {
++ for_each_netdev(net, dev) {
+ if ((in_dev = __in_dev_get_rcu(dev)) == NULL)
+ continue;
+
+@@ -979,7 +974,7 @@ __be32 inet_confirm_addr(struct in_device *in_dev,
+ if (scope != RT_SCOPE_LINK)
+ return confirm_addr_indev(in_dev, dst, local, scope);
+
+- net = in_dev->dev->nd_net;
++ net = dev_net(in_dev->dev);
+ read_lock(&dev_base_lock);
+ rcu_read_lock();
+ for_each_netdev(net, dev) {
+@@ -1045,9 +1040,6 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
+ struct net_device *dev = ptr;
+ struct in_device *in_dev = __in_dev_get_rtnl(dev);
+
+- if (dev->nd_net != &init_net)
+- return NOTIFY_DONE;
+-
+ ASSERT_RTNL();
+
+ if (!in_dev) {
+@@ -1166,16 +1158,13 @@ nla_put_failure:
+
+ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ int idx, ip_idx;
+ struct net_device *dev;
+ struct in_device *in_dev;
+ struct in_ifaddr *ifa;
+ int s_ip_idx, s_idx = cb->args[0];
+
+- if (net != &init_net)
+- return 0;
+-
+ s_ip_idx = ip_idx = cb->args[1];
+ idx = 0;
+ for_each_netdev(net, dev) {
+@@ -1214,7 +1203,7 @@ static void rtmsg_ifa(int event, struct in_ifaddr* ifa, struct nlmsghdr *nlh,
+ int err = -ENOBUFS;
+ struct net *net;
+
+- net = ifa->ifa_dev->dev->nd_net;
++ net = dev_net(ifa->ifa_dev->dev);
+ skb = nlmsg_new(inet_nlmsg_size(), GFP_KERNEL);
+ if (skb == NULL)
+ goto errout;
+@@ -1528,7 +1517,7 @@ static void devinet_sysctl_register(struct in_device *idev)
+ {
+ neigh_sysctl_register(idev->dev, idev->arp_parms, NET_IPV4,
+ NET_IPV4_NEIGH, "ipv4", NULL, NULL);
+- __devinet_sysctl_register(idev->dev->nd_net, idev->dev->name,
++ __devinet_sysctl_register(dev_net(idev->dev), idev->dev->name,
+ idev->dev->ifindex, &idev->cnf);
+ }
+
+diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
+index 86ff271..0f1557a 100644
+--- a/net/ipv4/fib_frontend.c
++++ b/net/ipv4/fib_frontend.c
+@@ -257,7 +257,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
+ if (in_dev == NULL)
+ goto e_inval;
+
+- net = dev->nd_net;
++ net = dev_net(dev);
+ if (fib_lookup(net, &fl, &res))
+ goto last_resort;
+ if (res.type != RTN_UNICAST)
+@@ -583,7 +583,7 @@ errout:
+
+ static int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct fib_config cfg;
+ struct fib_table *tb;
+ int err;
+@@ -605,7 +605,7 @@ errout:
+
+ static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct fib_config cfg;
+ struct fib_table *tb;
+ int err;
+@@ -627,7 +627,7 @@ errout:
+
+ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ unsigned int h, s_h;
+ unsigned int e = 0, s_e;
+ struct fib_table *tb;
+@@ -674,7 +674,7 @@ out:
+
+ static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifaddr *ifa)
+ {
+- struct net *net = ifa->ifa_dev->dev->nd_net;
++ struct net *net = dev_net(ifa->ifa_dev->dev);
+ struct fib_table *tb;
+ struct fib_config cfg = {
+ .fc_protocol = RTPROT_KERNEL,
+@@ -801,15 +801,15 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa)
+ fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 32, prim);
+
+ /* Check, that this local address finally disappeared. */
+- if (inet_addr_type(dev->nd_net, ifa->ifa_local) != RTN_LOCAL) {
++ if (inet_addr_type(dev_net(dev), ifa->ifa_local) != RTN_LOCAL) {
+ /* And the last, but not the least thing.
+ We must flush stray FIB entries.
+
+ First of all, we scan fib_info list searching
+ for stray nexthop entries, then ignite fib_flush.
+ */
+- if (fib_sync_down_addr(dev->nd_net, ifa->ifa_local))
+- fib_flush(dev->nd_net);
++ if (fib_sync_down_addr(dev_net(dev), ifa->ifa_local))
++ fib_flush(dev_net(dev));
+ }
+ }
+ #undef LOCAL_OK
+@@ -857,7 +857,7 @@ static void nl_fib_input(struct sk_buff *skb)
+ struct fib_table *tb;
+ u32 pid;
+
+- net = skb->sk->sk_net;
++ net = sock_net(skb->sk);
+ nlh = nlmsg_hdr(skb);
+ if (skb->len < NLMSG_SPACE(0) || skb->len < nlh->nlmsg_len ||
+ nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*frn)))
+@@ -899,7 +899,7 @@ static void nl_fib_lookup_exit(struct net *net)
+ static void fib_disable_ip(struct net_device *dev, int force)
+ {
+ if (fib_sync_down_dev(dev, force))
+- fib_flush(dev->nd_net);
++ fib_flush(dev_net(dev));
+ rt_cache_flush(0);
+ arp_ifdown(dev);
+ }
+diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c
+index 8d58d85..2e2fc33 100644
+--- a/net/ipv4/fib_hash.c
++++ b/net/ipv4/fib_hash.c
+@@ -821,7 +821,7 @@ static struct fib_alias *fib_get_first(struct seq_file *seq)
+ struct fib_table *main_table;
+ struct fn_hash *table;
+
+- main_table = fib_get_table(iter->p.net, RT_TABLE_MAIN);
++ main_table = fib_get_table(seq_file_net(seq), RT_TABLE_MAIN);
+ table = (struct fn_hash *)main_table->tb_data;
+
+ iter->bucket = 0;
+@@ -959,11 +959,10 @@ static struct fib_alias *fib_get_idx(struct seq_file *seq, loff_t pos)
+ static void *fib_seq_start(struct seq_file *seq, loff_t *pos)
+ __acquires(fib_hash_lock)
+ {
+- struct fib_iter_state *iter = seq->private;
+ void *v = NULL;
+
+ read_lock(&fib_hash_lock);
+- if (fib_get_table(iter->p.net, RT_TABLE_MAIN))
++ if (fib_get_table(seq_file_net(seq), RT_TABLE_MAIN))
+ v = *pos ? fib_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
+ return v;
+ }
+@@ -1004,7 +1003,7 @@ static unsigned fib_flag_trans(int type, __be32 mask, struct fib_info *fi)
+ static int fib_seq_show(struct seq_file *seq, void *v)
+ {
+ struct fib_iter_state *iter;
+- char bf[128];
++ int len;
+ __be32 prefix, mask;
+ unsigned flags;
+ struct fib_node *f;
+@@ -1026,18 +1025,19 @@ static int fib_seq_show(struct seq_file *seq, void *v)
+ mask = FZ_MASK(iter->zone);
+ flags = fib_flag_trans(fa->fa_type, mask, fi);
+ if (fi)
+- snprintf(bf, sizeof(bf),
+- "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
++ seq_printf(seq,
++ "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u%n",
+ fi->fib_dev ? fi->fib_dev->name : "*", prefix,
+ fi->fib_nh->nh_gw, flags, 0, 0, fi->fib_priority,
+ mask, (fi->fib_advmss ? fi->fib_advmss + 40 : 0),
+ fi->fib_window,
+- fi->fib_rtt >> 3);
++ fi->fib_rtt >> 3, &len);
+ else
+- snprintf(bf, sizeof(bf),
+- "*\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
+- prefix, 0, flags, 0, 0, 0, mask, 0, 0, 0);
+- seq_printf(seq, "%-127s\n", bf);
++ seq_printf(seq,
++ "*\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u%n",
++ prefix, 0, flags, 0, 0, 0, mask, 0, 0, 0, &len);
++
++ seq_printf(seq, "%*s\n", 127 - len, "");
+ out:
+ return 0;
+ }
+diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
+index 19274d0..1fb5687 100644
+--- a/net/ipv4/fib_rules.c
++++ b/net/ipv4/fib_rules.c
+@@ -137,7 +137,7 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
+ struct nlmsghdr *nlh, struct fib_rule_hdr *frh,
+ struct nlattr **tb)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ int err = -EINVAL;
+ struct fib4_rule *rule4 = (struct fib4_rule *) rule;
+
+diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
+index a13c847..3b83c34 100644
+--- a/net/ipv4/fib_semantics.c
++++ b/net/ipv4/fib_semantics.c
+@@ -152,6 +152,7 @@ void free_fib_info(struct fib_info *fi)
+ nh->nh_dev = NULL;
+ } endfor_nexthops(fi);
+ fib_info_cnt--;
++ release_net(fi->fib_net);
+ kfree(fi);
+ }
+
+@@ -730,7 +731,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
+ goto failure;
+ fib_info_cnt++;
+
+- fi->fib_net = net;
++ fi->fib_net = hold_net(net);
+ fi->fib_protocol = cfg->fc_protocol;
+ fi->fib_flags = cfg->fc_flags;
+ fi->fib_priority = cfg->fc_priority;
+diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
+index f6cdc01..4b02d14 100644
+--- a/net/ipv4/fib_trie.c
++++ b/net/ipv4/fib_trie.c
+@@ -122,7 +122,10 @@ struct tnode {
+ unsigned char bits; /* 2log(KEYLENGTH) bits needed */
+ unsigned int full_children; /* KEYLENGTH bits needed */
+ unsigned int empty_children; /* KEYLENGTH bits needed */
+- struct rcu_head rcu;
++ union {
++ struct rcu_head rcu;
++ struct work_struct work;
++ };
+ struct node *child[0];
+ };
+
+@@ -160,7 +163,6 @@ static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n,
+ static struct node *resize(struct trie *t, struct tnode *tn);
+ static struct tnode *inflate(struct trie *t, struct tnode *tn);
+ static struct tnode *halve(struct trie *t, struct tnode *tn);
+-static void tnode_free(struct tnode *tn);
+
+ static struct kmem_cache *fn_alias_kmem __read_mostly;
+ static struct kmem_cache *trie_leaf_kmem __read_mostly;
+@@ -334,6 +336,11 @@ static void __leaf_free_rcu(struct rcu_head *head)
+ kmem_cache_free(trie_leaf_kmem, l);
+ }
+
++static inline void free_leaf(struct leaf *l)
++{
++ call_rcu_bh(&l->rcu, __leaf_free_rcu);
++}
++
+ static void __leaf_info_free_rcu(struct rcu_head *head)
+ {
+ kfree(container_of(head, struct leaf_info, rcu));
+@@ -346,16 +353,16 @@ static inline void free_leaf_info(struct leaf_info *leaf)
+
+ static struct tnode *tnode_alloc(size_t size)
+ {
+- struct page *pages;
+-
+ if (size <= PAGE_SIZE)
+ return kzalloc(size, GFP_KERNEL);
++ else
++ return __vmalloc(size, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
++}
+
+- pages = alloc_pages(GFP_KERNEL|__GFP_ZERO, get_order(size));
+- if (!pages)
+- return NULL;
+-
+- return page_address(pages);
++static void __tnode_vfree(struct work_struct *arg)
++{
++ struct tnode *tn = container_of(arg, struct tnode, work);
++ vfree(tn);
+ }
+
+ static void __tnode_free_rcu(struct rcu_head *head)
+@@ -366,16 +373,17 @@ static void __tnode_free_rcu(struct rcu_head *head)
+
+ if (size <= PAGE_SIZE)
+ kfree(tn);
+- else
+- free_pages((unsigned long)tn, get_order(size));
++ else {
++ INIT_WORK(&tn->work, __tnode_vfree);
++ schedule_work(&tn->work);
++ }
+ }
+
+ static inline void tnode_free(struct tnode *tn)
+ {
+- if (IS_LEAF(tn)) {
+- struct leaf *l = (struct leaf *) tn;
+- call_rcu_bh(&l->rcu, __leaf_free_rcu);
+- } else
++ if (IS_LEAF(tn))
++ free_leaf((struct leaf *) tn);
++ else
+ call_rcu(&tn->rcu, __tnode_free_rcu);
+ }
+
+@@ -1086,7 +1094,7 @@ static struct list_head *fib_insert_node(struct trie *t, u32 key, int plen)
+ li = leaf_info_new(plen);
+
+ if (!li) {
+- tnode_free((struct tnode *) l);
++ free_leaf(l);
+ return NULL;
+ }
+
+@@ -1122,7 +1130,7 @@ static struct list_head *fib_insert_node(struct trie *t, u32 key, int plen)
+
+ if (!tn) {
+ free_leaf_info(li);
+- tnode_free((struct tnode *) l);
++ free_leaf(l);
+ return NULL;
+ }
+
+@@ -1578,7 +1586,7 @@ static void trie_leaf_remove(struct trie *t, struct leaf *l)
+ } else
+ rcu_assign_pointer(t->trie, NULL);
+
+- tnode_free((struct tnode *) l);
++ free_leaf(l);
+ }
+
+ /*
+@@ -1665,7 +1673,7 @@ static int fn_trie_delete(struct fib_table *tb, struct fib_config *cfg)
+ return 0;
+ }
+
+-static int trie_flush_list(struct trie *t, struct list_head *head)
++static int trie_flush_list(struct list_head *head)
+ {
+ struct fib_alias *fa, *fa_node;
+ int found = 0;
+@@ -1683,7 +1691,7 @@ static int trie_flush_list(struct trie *t, struct list_head *head)
+ return found;
+ }
+
+-static int trie_flush_leaf(struct trie *t, struct leaf *l)
++static int trie_flush_leaf(struct leaf *l)
+ {
+ int found = 0;
+ struct hlist_head *lih = &l->list;
+@@ -1691,7 +1699,7 @@ static int trie_flush_leaf(struct trie *t, struct leaf *l)
+ struct leaf_info *li = NULL;
+
+ hlist_for_each_entry_safe(li, node, tmp, lih, hlist) {
+- found += trie_flush_list(t, &li->falh);
++ found += trie_flush_list(&li->falh);
+
+ if (list_empty(&li->falh)) {
+ hlist_del_rcu(&li->hlist);
+@@ -1782,7 +1790,7 @@ static int fn_trie_flush(struct fib_table *tb)
+ int found = 0;
+
+ for (l = trie_firstleaf(t); l; l = trie_nextleaf(l)) {
+- found += trie_flush_leaf(t, l);
++ found += trie_flush_leaf(l);
+
+ if (ll && hlist_empty(&ll->list))
+ trie_leaf_remove(t, ll);
+@@ -2029,9 +2037,8 @@ struct fib_table *fib_hash_table(u32 id)
+ /* Depth first Trie walk iterator */
+ struct fib_trie_iter {
+ struct seq_net_private p;
+- struct trie *trie_local, *trie_main;
++ struct fib_table *tb;
+ struct tnode *tnode;
+- struct trie *trie;
+ unsigned index;
+ unsigned depth;
+ };
+@@ -2084,31 +2091,26 @@ rescan:
+ static struct node *fib_trie_get_first(struct fib_trie_iter *iter,
+ struct trie *t)
+ {
+- struct node *n ;
++ struct node *n;
+
+ if (!t)
+ return NULL;
+
+ n = rcu_dereference(t->trie);
+-
+- if (!iter)
++ if (!n)
+ return NULL;
+
+- if (n) {
+- if (IS_TNODE(n)) {
+- iter->tnode = (struct tnode *) n;
+- iter->trie = t;
+- iter->index = 0;
+- iter->depth = 1;
+- } else {
+- iter->tnode = NULL;
+- iter->trie = t;
+- iter->index = 0;
+- iter->depth = 0;
+- }
+- return n;
++ if (IS_TNODE(n)) {
++ iter->tnode = (struct tnode *) n;
++ iter->index = 0;
++ iter->depth = 1;
++ } else {
++ iter->tnode = NULL;
++ iter->index = 0;
++ iter->depth = 0;
+ }
+- return NULL;
++
++ return n;
+ }
+
+ static void trie_collect_stats(struct trie *t, struct trie_stat *s)
+@@ -2119,8 +2121,7 @@ static void trie_collect_stats(struct trie *t, struct trie_stat *s)
+ memset(s, 0, sizeof(*s));
+
+ rcu_read_lock();
+- for (n = fib_trie_get_first(&iter, t); n;
+- n = fib_trie_get_next(&iter)) {
++ for (n = fib_trie_get_first(&iter, t); n; n = fib_trie_get_next(&iter)) {
+ if (IS_LEAF(n)) {
+ struct leaf *l = (struct leaf *)n;
+ struct leaf_info *li;
+@@ -2209,36 +2210,48 @@ static void trie_show_usage(struct seq_file *seq,
+ }
+ #endif /* CONFIG_IP_FIB_TRIE_STATS */
+
+-static void fib_trie_show(struct seq_file *seq, const char *name,
+- struct trie *trie)
++static void fib_table_print(struct seq_file *seq, struct fib_table *tb)
+ {
+- struct trie_stat stat;
+-
+- trie_collect_stats(trie, &stat);
+- seq_printf(seq, "%s:\n", name);
+- trie_show_stats(seq, &stat);
+-#ifdef CONFIG_IP_FIB_TRIE_STATS
+- trie_show_usage(seq, &trie->stats);
+-#endif
++ if (tb->tb_id == RT_TABLE_LOCAL)
++ seq_puts(seq, "Local:\n");
++ else if (tb->tb_id == RT_TABLE_MAIN)
++ seq_puts(seq, "Main:\n");
++ else
++ seq_printf(seq, "Id %d:\n", tb->tb_id);
+ }
+
++
+ static int fib_triestat_seq_show(struct seq_file *seq, void *v)
+ {
+ struct net *net = (struct net *)seq->private;
+- struct fib_table *tb;
++ unsigned int h;
+
+ seq_printf(seq,
+ "Basic info: size of leaf:"
+ " %Zd bytes, size of tnode: %Zd bytes.\n",
+ sizeof(struct leaf), sizeof(struct tnode));
+
+- tb = fib_get_table(net, RT_TABLE_LOCAL);
+- if (tb)
+- fib_trie_show(seq, "Local", (struct trie *) tb->tb_data);
++ for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
++ struct hlist_head *head = &net->ipv4.fib_table_hash[h];
++ struct hlist_node *node;
++ struct fib_table *tb;
++
++ hlist_for_each_entry_rcu(tb, node, head, tb_hlist) {
++ struct trie *t = (struct trie *) tb->tb_data;
++ struct trie_stat stat;
++
++ if (!t)
++ continue;
+
+- tb = fib_get_table(net, RT_TABLE_MAIN);
+- if (tb)
+- fib_trie_show(seq, "Main", (struct trie *) tb->tb_data);
++ fib_table_print(seq, tb);
++
++ trie_collect_stats(t, &stat);
++ trie_show_stats(seq, &stat);
++#ifdef CONFIG_IP_FIB_TRIE_STATS
++ trie_show_usage(seq, &t->stats);
++#endif
++ }
++ }
+
+ return 0;
+ }
+@@ -2274,67 +2287,79 @@ static const struct file_operations fib_triestat_fops = {
+ .release = fib_triestat_seq_release,
+ };
+
+-static struct node *fib_trie_get_idx(struct fib_trie_iter *iter,
+- loff_t pos)
++static struct node *fib_trie_get_idx(struct seq_file *seq, loff_t pos)
+ {
++ struct fib_trie_iter *iter = seq->private;
++ struct net *net = seq_file_net(seq);
+ loff_t idx = 0;
+- struct node *n;
++ unsigned int h;
+
+- for (n = fib_trie_get_first(iter, iter->trie_local);
+- n; ++idx, n = fib_trie_get_next(iter)) {
+- if (pos == idx)
+- return n;
+- }
++ for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
++ struct hlist_head *head = &net->ipv4.fib_table_hash[h];
++ struct hlist_node *node;
++ struct fib_table *tb;
+
+- for (n = fib_trie_get_first(iter, iter->trie_main);
+- n; ++idx, n = fib_trie_get_next(iter)) {
+- if (pos == idx)
+- return n;
++ hlist_for_each_entry_rcu(tb, node, head, tb_hlist) {
++ struct node *n;
++
++ for (n = fib_trie_get_first(iter,
++ (struct trie *) tb->tb_data);
++ n; n = fib_trie_get_next(iter))
++ if (pos == idx++) {
++ iter->tb = tb;
++ return n;
++ }
++ }
+ }
++
+ return NULL;
+ }
+
+ static void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos)
+ __acquires(RCU)
+ {
+- struct fib_trie_iter *iter = seq->private;
+- struct fib_table *tb;
+-
+- if (!iter->trie_local) {
+- tb = fib_get_table(iter->p.net, RT_TABLE_LOCAL);
+- if (tb)
+- iter->trie_local = (struct trie *) tb->tb_data;
+- }
+- if (!iter->trie_main) {
+- tb = fib_get_table(iter->p.net, RT_TABLE_MAIN);
+- if (tb)
+- iter->trie_main = (struct trie *) tb->tb_data;
+- }
+ rcu_read_lock();
+- if (*pos == 0)
+- return SEQ_START_TOKEN;
+- return fib_trie_get_idx(iter, *pos - 1);
++ return fib_trie_get_idx(seq, *pos);
+ }
+
+ static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+ {
+ struct fib_trie_iter *iter = seq->private;
+- void *l = v;
++ struct net *net = seq_file_net(seq);
++ struct fib_table *tb = iter->tb;
++ struct hlist_node *tb_node;
++ unsigned int h;
++ struct node *n;
+
+ ++*pos;
+- if (v == SEQ_START_TOKEN)
+- return fib_trie_get_idx(iter, 0);
+-
+- v = fib_trie_get_next(iter);
+- BUG_ON(v == l);
+- if (v)
+- return v;
++ /* next node in same table */
++ n = fib_trie_get_next(iter);
++ if (n)
++ return n;
+
+- /* continue scan in next trie */
+- if (iter->trie == iter->trie_local)
+- return fib_trie_get_first(iter, iter->trie_main);
++ /* walk rest of this hash chain */
++ h = tb->tb_id & (FIB_TABLE_HASHSZ - 1);
++ while ( (tb_node = rcu_dereference(tb->tb_hlist.next)) ) {
++ tb = hlist_entry(tb_node, struct fib_table, tb_hlist);
++ n = fib_trie_get_first(iter, (struct trie *) tb->tb_data);
++ if (n)
++ goto found;
++ }
+
++ /* new hash chain */
++ while (++h < FIB_TABLE_HASHSZ) {
++ struct hlist_head *head = &net->ipv4.fib_table_hash[h];
++ hlist_for_each_entry_rcu(tb, tb_node, head, tb_hlist) {
++ n = fib_trie_get_first(iter, (struct trie *) tb->tb_data);
++ if (n)
++ goto found;
++ }
++ }
+ return NULL;
++
++found:
++ iter->tb = tb;
++ return n;
+ }
+
+ static void fib_trie_seq_stop(struct seq_file *seq, void *v)
+@@ -2391,22 +2416,15 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v)
+ const struct fib_trie_iter *iter = seq->private;
+ struct node *n = v;
+
+- if (v == SEQ_START_TOKEN)
+- return 0;
+-
+- if (!node_parent_rcu(n)) {
+- if (iter->trie == iter->trie_local)
+- seq_puts(seq, "<local>:\n");
+- else
+- seq_puts(seq, "<main>:\n");
+- }
++ if (!node_parent_rcu(n))
++ fib_table_print(seq, iter->tb);
+
+ if (IS_TNODE(n)) {
+ struct tnode *tn = (struct tnode *) n;
+ __be32 prf = htonl(mask_pfx(tn->key, tn->pos));
+
+ seq_indent(seq, iter->depth-1);
+- seq_printf(seq, " +-- %d.%d.%d.%d/%d %d %d %d\n",
++ seq_printf(seq, " +-- " NIPQUAD_FMT "/%d %d %d %d\n",
+ NIPQUAD(prf), tn->pos, tn->bits, tn->full_children,
+ tn->empty_children);
+
+@@ -2417,7 +2435,7 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v)
+ __be32 val = htonl(l->key);
+
+ seq_indent(seq, iter->depth);
+- seq_printf(seq, " |-- %d.%d.%d.%d\n", NIPQUAD(val));
++ seq_printf(seq, " |-- " NIPQUAD_FMT "\n", NIPQUAD(val));
+
+ hlist_for_each_entry_rcu(li, node, &l->list, hlist) {
+ struct fib_alias *fa;
+@@ -2502,7 +2520,7 @@ static void *fib_route_seq_start(struct seq_file *seq, loff_t *pos)
+ struct fib_table *tb;
+
+ rcu_read_lock();
+- tb = fib_get_table(iter->p.net, RT_TABLE_MAIN);
++ tb = fib_get_table(seq_file_net(seq), RT_TABLE_MAIN);
+ if (!tb)
+ return NULL;
+
+@@ -2584,15 +2602,16 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
+ list_for_each_entry_rcu(fa, &li->falh, fa_list) {
+ const struct fib_info *fi = fa->fa_info;
+ unsigned flags = fib_flag_trans(fa->fa_type, mask, fi);
+- char bf[128];
++ int len;
+
+ if (fa->fa_type == RTN_BROADCAST
+ || fa->fa_type == RTN_MULTICAST)
+ continue;
+
+ if (fi)
+- snprintf(bf, sizeof(bf),
+- "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
++ seq_printf(seq,
++ "%s\t%08X\t%08X\t%04X\t%d\t%u\t"
++ "%d\t%08X\t%d\t%u\t%u%n",
+ fi->fib_dev ? fi->fib_dev->name : "*",
+ prefix,
+ fi->fib_nh->nh_gw, flags, 0, 0,
+@@ -2601,14 +2620,15 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
+ (fi->fib_advmss ?
+ fi->fib_advmss + 40 : 0),
+ fi->fib_window,
+- fi->fib_rtt >> 3);
++ fi->fib_rtt >> 3, &len);
+ else
+- snprintf(bf, sizeof(bf),
+- "*\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
++ seq_printf(seq,
++ "*\t%08X\t%08X\t%04X\t%d\t%u\t"
++ "%d\t%08X\t%d\t%u\t%u%n",
+ prefix, 0, flags, 0, 0, 0,
+- mask, 0, 0, 0);
++ mask, 0, 0, 0, &len);
+
+- seq_printf(seq, "%-127s\n", bf);
++ seq_printf(seq, "%*s\n", 127 - len, "");
+ }
+ }
+
+diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
+index 40508ba..c67d00e 100644
+--- a/net/ipv4/icmp.c
++++ b/net/ipv4/icmp.c
+@@ -93,6 +93,7 @@
+ #include <asm/uaccess.h>
+ #include <net/checksum.h>
+ #include <net/xfrm.h>
++#include <net/inet_common.h>
+
+ /*
+ * Build xmit assembly blocks
+@@ -188,29 +189,6 @@ struct icmp_err icmp_err_convert[] = {
+ },
+ };
+
+-/* Control parameters for ECHO replies. */
+-int sysctl_icmp_echo_ignore_all __read_mostly;
+-int sysctl_icmp_echo_ignore_broadcasts __read_mostly = 1;
+-
+-/* Control parameter - ignore bogus broadcast responses? */
+-int sysctl_icmp_ignore_bogus_error_responses __read_mostly = 1;
+-
+-/*
+- * Configurable global rate limit.
+- *
+- * ratelimit defines tokens/packet consumed for dst->rate_token bucket
+- * ratemask defines which icmp types are ratelimited by setting
+- * it's bit position.
+- *
+- * default:
+- * dest unreachable (3), source quench (4),
+- * time exceeded (11), parameter problem (12)
+- */
+-
+-int sysctl_icmp_ratelimit __read_mostly = 1 * HZ;
+-int sysctl_icmp_ratemask __read_mostly = 0x1818;
+-int sysctl_icmp_errors_use_inbound_ifaddr __read_mostly;
+-
+ /*
+ * ICMP control array. This specifies what to do with each ICMP.
+ */
+@@ -229,14 +207,16 @@ static const struct icmp_control icmp_pointers[NR_ICMP_TYPES+1];
+ *
+ * On SMP we have one ICMP socket per-cpu.
+ */
+-static DEFINE_PER_CPU(struct socket *, __icmp_socket) = NULL;
+-#define icmp_socket __get_cpu_var(__icmp_socket)
++static struct sock *icmp_sk(struct net *net)
++{
++ return net->ipv4.icmp_sk[smp_processor_id()];
++}
+
+-static inline int icmp_xmit_lock(void)
++static inline int icmp_xmit_lock(struct sock *sk)
+ {
+ local_bh_disable();
+
+- if (unlikely(!spin_trylock(&icmp_socket->sk->sk_lock.slock))) {
++ if (unlikely(!spin_trylock(&sk->sk_lock.slock))) {
+ /* This can happen if the output path signals a
+ * dst_link_failure() for an outgoing ICMP packet.
+ */
+@@ -246,9 +226,9 @@ static inline int icmp_xmit_lock(void)
+ return 0;
+ }
+
+-static inline void icmp_xmit_unlock(void)
++static inline void icmp_xmit_unlock(struct sock *sk)
+ {
+- spin_unlock_bh(&icmp_socket->sk->sk_lock.slock);
++ spin_unlock_bh(&sk->sk_lock.slock);
+ }
+
+ /*
+@@ -291,7 +271,8 @@ int xrlim_allow(struct dst_entry *dst, int timeout)
+ return rc;
+ }
+
+-static inline int icmpv4_xrlim_allow(struct rtable *rt, int type, int code)
++static inline int icmpv4_xrlim_allow(struct net *net, struct rtable *rt,
++ int type, int code)
+ {
+ struct dst_entry *dst = &rt->u.dst;
+ int rc = 1;
+@@ -308,8 +289,8 @@ static inline int icmpv4_xrlim_allow(struct rtable *rt, int type, int code)
+ goto out;
+
+ /* Limit if icmp type is enabled in ratemask. */
+- if ((1 << type) & sysctl_icmp_ratemask)
+- rc = xrlim_allow(dst, sysctl_icmp_ratelimit);
++ if ((1 << type) & net->ipv4.sysctl_icmp_ratemask)
++ rc = xrlim_allow(dst, net->ipv4.sysctl_icmp_ratelimit);
+ out:
+ return rc;
+ }
+@@ -346,19 +327,21 @@ static int icmp_glue_bits(void *from, char *to, int offset, int len, int odd,
+ static void icmp_push_reply(struct icmp_bxm *icmp_param,
+ struct ipcm_cookie *ipc, struct rtable *rt)
+ {
++ struct sock *sk;
+ struct sk_buff *skb;
+
+- if (ip_append_data(icmp_socket->sk, icmp_glue_bits, icmp_param,
++ sk = icmp_sk(dev_net(rt->u.dst.dev));
++ if (ip_append_data(sk, icmp_glue_bits, icmp_param,
+ icmp_param->data_len+icmp_param->head_len,
+ icmp_param->head_len,
+ ipc, rt, MSG_DONTWAIT) < 0)
+- ip_flush_pending_frames(icmp_socket->sk);
+- else if ((skb = skb_peek(&icmp_socket->sk->sk_write_queue)) != NULL) {
++ ip_flush_pending_frames(sk);
++ else if ((skb = skb_peek(&sk->sk_write_queue)) != NULL) {
+ struct icmphdr *icmph = icmp_hdr(skb);
+ __wsum csum = 0;
+ struct sk_buff *skb1;
+
+- skb_queue_walk(&icmp_socket->sk->sk_write_queue, skb1) {
++ skb_queue_walk(&sk->sk_write_queue, skb1) {
+ csum = csum_add(csum, skb1->csum);
+ }
+ csum = csum_partial_copy_nocheck((void *)&icmp_param->data,
+@@ -366,7 +349,7 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param,
+ icmp_param->head_len, csum);
+ icmph->checksum = csum_fold(csum);
+ skb->ip_summed = CHECKSUM_NONE;
+- ip_push_pending_frames(icmp_socket->sk);
++ ip_push_pending_frames(sk);
+ }
+ }
+
+@@ -376,16 +359,17 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param,
+
+ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
+ {
+- struct sock *sk = icmp_socket->sk;
+- struct inet_sock *inet = inet_sk(sk);
+ struct ipcm_cookie ipc;
+- struct rtable *rt = (struct rtable *)skb->dst;
++ struct rtable *rt = skb->rtable;
++ struct net *net = dev_net(rt->u.dst.dev);
++ struct sock *sk = icmp_sk(net);
++ struct inet_sock *inet = inet_sk(sk);
+ __be32 daddr;
+
+ if (ip_options_echo(&icmp_param->replyopts, skb))
+ return;
+
+- if (icmp_xmit_lock())
++ if (icmp_xmit_lock(sk))
+ return;
+
+ icmp_param->data.icmph.checksum = 0;
+@@ -405,15 +389,15 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
+ .tos = RT_TOS(ip_hdr(skb)->tos) } },
+ .proto = IPPROTO_ICMP };
+ security_skb_classify_flow(skb, &fl);
+- if (ip_route_output_key(rt->u.dst.dev->nd_net, &rt, &fl))
++ if (ip_route_output_key(net, &rt, &fl))
+ goto out_unlock;
+ }
+- if (icmpv4_xrlim_allow(rt, icmp_param->data.icmph.type,
++ if (icmpv4_xrlim_allow(net, rt, icmp_param->data.icmph.type,
+ icmp_param->data.icmph.code))
+ icmp_push_reply(icmp_param, &ipc, rt);
+ ip_rt_put(rt);
+ out_unlock:
+- icmp_xmit_unlock();
++ icmp_xmit_unlock(sk);
+ }
+
+
+@@ -433,15 +417,17 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
+ struct iphdr *iph;
+ int room;
+ struct icmp_bxm icmp_param;
+- struct rtable *rt = (struct rtable *)skb_in->dst;
++ struct rtable *rt = skb_in->rtable;
+ struct ipcm_cookie ipc;
+ __be32 saddr;
+ u8 tos;
+ struct net *net;
++ struct sock *sk;
+
+ if (!rt)
+ goto out;
+- net = rt->u.dst.dev->nd_net;
++ net = dev_net(rt->u.dst.dev);
++ sk = icmp_sk(net);
+
+ /*
+ * Find the original header. It is expected to be valid, of course.
+@@ -505,7 +491,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
+ }
+ }
+
+- if (icmp_xmit_lock())
++ if (icmp_xmit_lock(sk))
+ return;
+
+ /*
+@@ -516,7 +502,8 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
+ if (!(rt->rt_flags & RTCF_LOCAL)) {
+ struct net_device *dev = NULL;
+
+- if (rt->fl.iif && sysctl_icmp_errors_use_inbound_ifaddr)
++ if (rt->fl.iif &&
++ net->ipv4.sysctl_icmp_errors_use_inbound_ifaddr)
+ dev = dev_get_by_index(net, rt->fl.iif);
+
+ if (dev) {
+@@ -544,7 +531,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
+ icmp_param.data.icmph.checksum = 0;
+ icmp_param.skb = skb_in;
+ icmp_param.offset = skb_network_offset(skb_in);
+- inet_sk(icmp_socket->sk)->tos = tos;
++ inet_sk(sk)->tos = tos;
+ ipc.addr = iph->saddr;
+ ipc.opt = &icmp_param.replyopts;
+
+@@ -609,7 +596,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
+ RT_TOS(tos), rt2->u.dst.dev);
+
+ dst_release(&rt2->u.dst);
+- rt2 = (struct rtable *)skb_in->dst;
++ rt2 = skb_in->rtable;
+ skb_in->dst = odst;
+ }
+
+@@ -634,7 +621,7 @@ relookup_failed:
+ }
+
+ route_done:
+- if (!icmpv4_xrlim_allow(rt, type, code))
++ if (!icmpv4_xrlim_allow(net, rt, type, code))
+ goto ende;
+
+ /* RFC says return as much as we can without exceeding 576 bytes. */
+@@ -654,7 +641,7 @@ route_done:
+ ende:
+ ip_rt_put(rt);
+ out_unlock:
+- icmp_xmit_unlock();
++ icmp_xmit_unlock(sk);
+ out:;
+ }
+
+@@ -672,7 +659,7 @@ static void icmp_unreach(struct sk_buff *skb)
+ u32 info = 0;
+ struct net *net;
+
+- net = skb->dst->dev->nd_net;
++ net = dev_net(skb->dst->dev);
+
+ /*
+ * Incomplete header ?
+@@ -698,7 +685,7 @@ static void icmp_unreach(struct sk_buff *skb)
+ break;
+ case ICMP_FRAG_NEEDED:
+ if (ipv4_config.no_pmtu_disc) {
+- LIMIT_NETDEBUG(KERN_INFO "ICMP: %u.%u.%u.%u: "
++ LIMIT_NETDEBUG(KERN_INFO "ICMP: " NIPQUAD_FMT ": "
+ "fragmentation needed "
+ "and DF set.\n",
+ NIPQUAD(iph->daddr));
+@@ -710,7 +697,7 @@ static void icmp_unreach(struct sk_buff *skb)
+ }
+ break;
+ case ICMP_SR_FAILED:
+- LIMIT_NETDEBUG(KERN_INFO "ICMP: %u.%u.%u.%u: Source "
++ LIMIT_NETDEBUG(KERN_INFO "ICMP: " NIPQUAD_FMT ": Source "
+ "Route Failed.\n",
+ NIPQUAD(iph->daddr));
+ break;
+@@ -740,12 +727,12 @@ static void icmp_unreach(struct sk_buff *skb)
+ * get the other vendor to fix their kit.
+ */
+
+- if (!sysctl_icmp_ignore_bogus_error_responses &&
++ if (!net->ipv4.sysctl_icmp_ignore_bogus_error_responses &&
+ inet_addr_type(net, iph->daddr) == RTN_BROADCAST) {
+ if (net_ratelimit())
+- printk(KERN_WARNING "%u.%u.%u.%u sent an invalid ICMP "
++ printk(KERN_WARNING NIPQUAD_FMT " sent an invalid ICMP "
+ "type %u, code %u "
+- "error to a broadcast: %u.%u.%u.%u on %s\n",
++ "error to a broadcast: " NIPQUAD_FMT " on %s\n",
+ NIPQUAD(ip_hdr(skb)->saddr),
+ icmph->type, icmph->code,
+ NIPQUAD(iph->daddr),
+@@ -835,7 +822,10 @@ out_err:
+
+ static void icmp_echo(struct sk_buff *skb)
+ {
+- if (!sysctl_icmp_echo_ignore_all) {
++ struct net *net;
++
++ net = dev_net(skb->dst->dev);
++ if (!net->ipv4.sysctl_icmp_echo_ignore_all) {
+ struct icmp_bxm icmp_param;
+
+ icmp_param.data.icmph = *icmp_hdr(skb);
+@@ -857,7 +847,7 @@ static void icmp_echo(struct sk_buff *skb)
+ */
+ static void icmp_timestamp(struct sk_buff *skb)
+ {
+- struct timeval tv;
++ struct timespec tv;
+ struct icmp_bxm icmp_param;
+ /*
+ * Too short.
+@@ -868,9 +858,9 @@ static void icmp_timestamp(struct sk_buff *skb)
+ /*
+ * Fill in the current time as ms since midnight UT:
+ */
+- do_gettimeofday(&tv);
+- icmp_param.data.times[1] = htonl((tv.tv_sec % 86400) * 1000 +
+- tv.tv_usec / 1000);
++ getnstimeofday(&tv);
++ icmp_param.data.times[1] = htonl((tv.tv_sec % 86400) * MSEC_PER_SEC +
++ tv.tv_nsec / NSEC_PER_MSEC);
+ icmp_param.data.times[2] = icmp_param.data.times[1];
+ if (skb_copy_bits(skb, 0, &icmp_param.data.times[0], 4))
+ BUG();
+@@ -938,7 +928,7 @@ static void icmp_address(struct sk_buff *skb)
+
+ static void icmp_address_reply(struct sk_buff *skb)
+ {
+- struct rtable *rt = (struct rtable *)skb->dst;
++ struct rtable *rt = skb->rtable;
+ struct net_device *dev = skb->dev;
+ struct in_device *in_dev;
+ struct in_ifaddr *ifa;
+@@ -963,8 +953,8 @@ static void icmp_address_reply(struct sk_buff *skb)
+ break;
+ }
+ if (!ifa && net_ratelimit()) {
+- printk(KERN_INFO "Wrong address mask %u.%u.%u.%u from "
+- "%s/%u.%u.%u.%u\n",
++ printk(KERN_INFO "Wrong address mask " NIPQUAD_FMT " from "
++ "%s/" NIPQUAD_FMT "\n",
+ NIPQUAD(*mp), dev->name, NIPQUAD(rt->rt_src));
+ }
+ }
+@@ -983,7 +973,7 @@ static void icmp_discard(struct sk_buff *skb)
+ int icmp_rcv(struct sk_buff *skb)
+ {
+ struct icmphdr *icmph;
+- struct rtable *rt = (struct rtable *)skb->dst;
++ struct rtable *rt = skb->rtable;
+
+ if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
+ int nh;
+@@ -1038,6 +1028,9 @@ int icmp_rcv(struct sk_buff *skb)
+ */
+
+ if (rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) {
++ struct net *net;
++
++ net = dev_net(rt->u.dst.dev);
+ /*
+ * RFC 1122: 3.2.2.6 An ICMP_ECHO to broadcast MAY be
+ * silently ignored (we let user decide with a sysctl).
+@@ -1046,7 +1039,7 @@ int icmp_rcv(struct sk_buff *skb)
+ */
+ if ((icmph->type == ICMP_ECHO ||
+ icmph->type == ICMP_TIMESTAMP) &&
+- sysctl_icmp_echo_ignore_broadcasts) {
++ net->ipv4.sysctl_icmp_echo_ignore_broadcasts) {
+ goto error;
+ }
+ if (icmph->type != ICMP_ECHO &&
+@@ -1141,38 +1134,84 @@ static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = {
+ },
+ };
+
+-void __init icmp_init(struct net_proto_family *ops)
++static void __net_exit icmp_sk_exit(struct net *net)
+ {
+- struct inet_sock *inet;
+ int i;
+
+- for_each_possible_cpu(i) {
+- int err;
++ for_each_possible_cpu(i)
++ inet_ctl_sock_destroy(net->ipv4.icmp_sk[i]);
++ kfree(net->ipv4.icmp_sk);
++ net->ipv4.icmp_sk = NULL;
++}
++
++static int __net_init icmp_sk_init(struct net *net)
++{
++ int i, err;
+
+- err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP,
+- &per_cpu(__icmp_socket, i));
++ net->ipv4.icmp_sk =
++ kzalloc(nr_cpu_ids * sizeof(struct sock *), GFP_KERNEL);
++ if (net->ipv4.icmp_sk == NULL)
++ return -ENOMEM;
+
++ for_each_possible_cpu(i) {
++ struct sock *sk;
++
++ err = inet_ctl_sock_create(&sk, PF_INET,
++ SOCK_RAW, IPPROTO_ICMP, net);
+ if (err < 0)
+- panic("Failed to create the ICMP control socket.\n");
++ goto fail;
+
+- per_cpu(__icmp_socket, i)->sk->sk_allocation = GFP_ATOMIC;
++ net->ipv4.icmp_sk[i] = sk;
+
+ /* Enough space for 2 64K ICMP packets, including
+ * sk_buff struct overhead.
+ */
+- per_cpu(__icmp_socket, i)->sk->sk_sndbuf =
++ sk->sk_sndbuf =
+ (2 * ((64 * 1024) + sizeof(struct sk_buff)));
+
+- inet = inet_sk(per_cpu(__icmp_socket, i)->sk);
+- inet->uc_ttl = -1;
+- inet->pmtudisc = IP_PMTUDISC_DONT;
+-
+- /* Unhash it so that IP input processing does not even
+- * see it, we do not wish this socket to see incoming
+- * packets.
+- */
+- per_cpu(__icmp_socket, i)->sk->sk_prot->unhash(per_cpu(__icmp_socket, i)->sk);
++ inet_sk(sk)->pmtudisc = IP_PMTUDISC_DONT;
+ }
++
++ /* Control parameters for ECHO replies. */
++ net->ipv4.sysctl_icmp_echo_ignore_all = 0;
++ net->ipv4.sysctl_icmp_echo_ignore_broadcasts = 1;
++
++ /* Control parameter - ignore bogus broadcast responses? */
++ net->ipv4.sysctl_icmp_ignore_bogus_error_responses = 1;
++
++ /*
++ * Configurable global rate limit.
++ *
++ * ratelimit defines tokens/packet consumed for dst->rate_token
++ * bucket ratemask defines which icmp types are ratelimited by
++ * setting it's bit position.
++ *
++ * default:
++ * dest unreachable (3), source quench (4),
++ * time exceeded (11), parameter problem (12)
++ */
++
++ net->ipv4.sysctl_icmp_ratelimit = 1 * HZ;
++ net->ipv4.sysctl_icmp_ratemask = 0x1818;
++ net->ipv4.sysctl_icmp_errors_use_inbound_ifaddr = 0;
++
++ return 0;
++
++fail:
++ for_each_possible_cpu(i)
++ inet_ctl_sock_destroy(net->ipv4.icmp_sk[i]);
++ kfree(net->ipv4.icmp_sk);
++ return err;
++}
++
++static struct pernet_operations __net_initdata icmp_sk_ops = {
++ .init = icmp_sk_init,
++ .exit = icmp_sk_exit,
++};
++
++int __init icmp_init(void)
++{
++ return register_pernet_device(&icmp_sk_ops);
+ }
+
+ EXPORT_SYMBOL(icmp_err_convert);
+diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
+index 732cd07..6250f42 100644
+--- a/net/ipv4/igmp.c
++++ b/net/ipv4/igmp.c
+@@ -130,12 +130,12 @@
+ */
+
+ #define IGMP_V1_SEEN(in_dev) \
+- (IPV4_DEVCONF_ALL(in_dev->dev->nd_net, FORCE_IGMP_VERSION) == 1 || \
++ (IPV4_DEVCONF_ALL(dev_net(in_dev->dev), FORCE_IGMP_VERSION) == 1 || \
+ IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 1 || \
+ ((in_dev)->mr_v1_seen && \
+ time_before(jiffies, (in_dev)->mr_v1_seen)))
+ #define IGMP_V2_SEEN(in_dev) \
+- (IPV4_DEVCONF_ALL(in_dev->dev->nd_net, FORCE_IGMP_VERSION) == 2 || \
++ (IPV4_DEVCONF_ALL(dev_net(in_dev->dev), FORCE_IGMP_VERSION) == 2 || \
+ IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 2 || \
+ ((in_dev)->mr_v2_seen && \
+ time_before(jiffies, (in_dev)->mr_v2_seen)))
+@@ -948,7 +948,7 @@ int igmp_rcv(struct sk_buff *skb)
+ case IGMPV2_HOST_MEMBERSHIP_REPORT:
+ case IGMPV3_HOST_MEMBERSHIP_REPORT:
+ /* Is it our report looped back? */
+- if (((struct rtable*)skb->dst)->fl.iif == 0)
++ if (skb->rtable->fl.iif == 0)
+ break;
+ /* don't rely on MC router hearing unicast reports */
+ if (skb->pkt_type == PACKET_MULTICAST ||
+@@ -1198,6 +1198,9 @@ void ip_mc_inc_group(struct in_device *in_dev, __be32 addr)
+
+ ASSERT_RTNL();
+
++ if (dev_net(in_dev->dev) != &init_net)
++ return;
++
+ for (im=in_dev->mc_list; im; im=im->next) {
+ if (im->multiaddr == addr) {
+ im->users++;
+@@ -1277,6 +1280,9 @@ void ip_mc_dec_group(struct in_device *in_dev, __be32 addr)
+
+ ASSERT_RTNL();
+
++ if (dev_net(in_dev->dev) != &init_net)
++ return;
++
+ for (ip=&in_dev->mc_list; (i=*ip)!=NULL; ip=&i->next) {
+ if (i->multiaddr==addr) {
+ if (--i->users == 0) {
+@@ -1304,6 +1310,9 @@ void ip_mc_down(struct in_device *in_dev)
+
+ ASSERT_RTNL();
+
++ if (dev_net(in_dev->dev) != &init_net)
++ return;
++
+ for (i=in_dev->mc_list; i; i=i->next)
+ igmp_group_dropped(i);
+
+@@ -1324,6 +1333,9 @@ void ip_mc_init_dev(struct in_device *in_dev)
+ {
+ ASSERT_RTNL();
+
++ if (dev_net(in_dev->dev) != &init_net)
++ return;
++
+ in_dev->mc_tomb = NULL;
+ #ifdef CONFIG_IP_MULTICAST
+ in_dev->mr_gq_running = 0;
+@@ -1347,6 +1359,9 @@ void ip_mc_up(struct in_device *in_dev)
+
+ ASSERT_RTNL();
+
++ if (dev_net(in_dev->dev) != &init_net)
++ return;
++
+ ip_mc_inc_group(in_dev, IGMP_ALL_HOSTS);
+
+ for (i=in_dev->mc_list; i; i=i->next)
+@@ -1363,6 +1378,9 @@ void ip_mc_destroy_dev(struct in_device *in_dev)
+
+ ASSERT_RTNL();
+
++ if (dev_net(in_dev->dev) != &init_net)
++ return;
++
+ /* Deactivate timers */
+ ip_mc_down(in_dev);
+
+@@ -1744,6 +1762,9 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
+ if (!ipv4_is_multicast(addr))
+ return -EINVAL;
+
++ if (sock_net(sk) != &init_net)
++ return -EPROTONOSUPPORT;
++
+ rtnl_lock();
+
+ in_dev = ip_mc_find_dev(imr);
+@@ -1812,6 +1833,9 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
+ u32 ifindex;
+ int ret = -EADDRNOTAVAIL;
+
++ if (sock_net(sk) != &init_net)
++ return -EPROTONOSUPPORT;
++
+ rtnl_lock();
+ in_dev = ip_mc_find_dev(imr);
+ ifindex = imr->imr_ifindex;
+@@ -1857,6 +1881,9 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
+ if (!ipv4_is_multicast(addr))
+ return -EINVAL;
+
++ if (sock_net(sk) != &init_net)
++ return -EPROTONOSUPPORT;
++
+ rtnl_lock();
+
+ imr.imr_multiaddr.s_addr = mreqs->imr_multiaddr;
+@@ -1990,6 +2017,9 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
+ msf->imsf_fmode != MCAST_EXCLUDE)
+ return -EINVAL;
+
++ if (sock_net(sk) != &init_net)
++ return -EPROTONOSUPPORT;
++
+ rtnl_lock();
+
+ imr.imr_multiaddr.s_addr = msf->imsf_multiaddr;
+@@ -2070,6 +2100,9 @@ int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
+ if (!ipv4_is_multicast(addr))
+ return -EINVAL;
+
++ if (sock_net(sk) != &init_net)
++ return -EPROTONOSUPPORT;
++
+ rtnl_lock();
+
+ imr.imr_multiaddr.s_addr = msf->imsf_multiaddr;
+@@ -2132,6 +2165,9 @@ int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
+ if (!ipv4_is_multicast(addr))
+ return -EINVAL;
+
++ if (sock_net(sk) != &init_net)
++ return -EPROTONOSUPPORT;
++
+ rtnl_lock();
+
+ err = -EADDRNOTAVAIL;
+@@ -2216,6 +2252,9 @@ void ip_mc_drop_socket(struct sock *sk)
+ if (inet->mc_list == NULL)
+ return;
+
++ if (sock_net(sk) != &init_net)
++ return;
++
+ rtnl_lock();
+ while ((iml = inet->mc_list) != NULL) {
+ struct in_device *in_dev;
+diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
+index b189278..828ea21 100644
+--- a/net/ipv4/inet_connection_sock.c
++++ b/net/ipv4/inet_connection_sock.c
+@@ -55,6 +55,13 @@ int inet_csk_bind_conflict(const struct sock *sk,
+ struct hlist_node *node;
+ int reuse = sk->sk_reuse;
+
++ /*
++ * Unlike other sk lookup places we do not check
++ * for sk_net here, since _all_ the socks listed
++ * in tb->owners list belong to the same net - the
++ * one this bucket belongs to.
++ */
++
+ sk_for_each_bound(sk2, node, &tb->owners) {
+ if (sk != sk2 &&
+ !inet_v6_ipv6only(sk2) &&
+@@ -80,12 +87,12 @@ EXPORT_SYMBOL_GPL(inet_csk_bind_conflict);
+ */
+ int inet_csk_get_port(struct sock *sk, unsigned short snum)
+ {
+- struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
++ struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
+ struct inet_bind_hashbucket *head;
+ struct hlist_node *node;
+ struct inet_bind_bucket *tb;
+ int ret;
+- struct net *net = sk->sk_net;
++ struct net *net = sock_net(sk);
+
+ local_bh_disable();
+ if (!snum) {
+@@ -133,8 +140,6 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
+ goto tb_not_found;
+ tb_found:
+ if (!hlist_empty(&tb->owners)) {
+- if (sk->sk_reuse > 1)
+- goto success;
+ if (tb->fastreuse > 0 &&
+ sk->sk_reuse && sk->sk_state != TCP_LISTEN) {
+ goto success;
+@@ -333,7 +338,7 @@ struct dst_entry* inet_csk_route_req(struct sock *sk,
+ .dport = ireq->rmt_port } } };
+
+ security_req_classify_flow(req, &fl);
+- if (ip_route_output_flow(&init_net, &rt, &fl, sk, 0)) {
++ if (ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 0)) {
+ IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
+ return NULL;
+ }
+@@ -414,8 +419,7 @@ void inet_csk_reqsk_queue_prune(struct sock *parent,
+ struct inet_connection_sock *icsk = inet_csk(parent);
+ struct request_sock_queue *queue = &icsk->icsk_accept_queue;
+ struct listen_sock *lopt = queue->listen_opt;
+- int max_retries = icsk->icsk_syn_retries ? : sysctl_tcp_synack_retries;
+- int thresh = max_retries;
++ int thresh = icsk->icsk_syn_retries ? : sysctl_tcp_synack_retries;
+ unsigned long now = jiffies;
+ struct request_sock **reqp, *req;
+ int i, budget;
+@@ -451,9 +455,6 @@ void inet_csk_reqsk_queue_prune(struct sock *parent,
+ }
+ }
+
+- if (queue->rskq_defer_accept)
+- max_retries = queue->rskq_defer_accept;
+-
+ budget = 2 * (lopt->nr_table_entries / (timeout / interval));
+ i = lopt->clock_hand;
+
+@@ -461,9 +462,8 @@ void inet_csk_reqsk_queue_prune(struct sock *parent,
+ reqp=&lopt->syn_table[i];
+ while ((req = *reqp) != NULL) {
+ if (time_after_eq(now, req->expires)) {
+- if ((req->retrans < thresh ||
+- (inet_rsk(req)->acked && req->retrans < max_retries))
+- && !req->rsk_ops->rtx_syn_ack(parent, req, NULL)) {
++ if (req->retrans < thresh &&
++ !req->rsk_ops->rtx_syn_ack(parent, req)) {
+ unsigned long timeo;
+
+ if (req->retrans++ == 0)
+@@ -656,25 +656,6 @@ void inet_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr)
+
+ EXPORT_SYMBOL_GPL(inet_csk_addr2sockaddr);
+
+-int inet_csk_ctl_sock_create(struct socket **sock, unsigned short family,
+- unsigned short type, unsigned char protocol)
+-{
+- int rc = sock_create_kern(family, type, protocol, sock);
+-
+- if (rc == 0) {
+- (*sock)->sk->sk_allocation = GFP_ATOMIC;
+- inet_sk((*sock)->sk)->uc_ttl = -1;
+- /*
+- * Unhash it so that IP input processing does not even see it,
+- * we do not wish this socket to see incoming packets.
+- */
+- (*sock)->sk->sk_prot->unhash((*sock)->sk);
+- }
+- return rc;
+-}
+-
+-EXPORT_SYMBOL_GPL(inet_csk_ctl_sock_create);
+-
+ #ifdef CONFIG_COMPAT
+ int inet_csk_compat_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen)
+diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
+index a0a3c78..4ed429b 100644
+--- a/net/ipv4/inet_fragment.c
++++ b/net/ipv4/inet_fragment.c
+@@ -107,10 +107,10 @@ void inet_frag_kill(struct inet_frag_queue *fq, struct inet_frags *f)
+ if (del_timer(&fq->timer))
+ atomic_dec(&fq->refcnt);
+
+- if (!(fq->last_in & COMPLETE)) {
++ if (!(fq->last_in & INET_FRAG_COMPLETE)) {
+ fq_unlink(fq, f);
+ atomic_dec(&fq->refcnt);
+- fq->last_in |= COMPLETE;
++ fq->last_in |= INET_FRAG_COMPLETE;
+ }
+ }
+
+@@ -134,7 +134,7 @@ void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f,
+ struct sk_buff *fp;
+ struct netns_frags *nf;
+
+- BUG_TRAP(q->last_in & COMPLETE);
++ BUG_TRAP(q->last_in & INET_FRAG_COMPLETE);
+ BUG_TRAP(del_timer(&q->timer) == 0);
+
+ /* Release all fragment data. */
+@@ -177,7 +177,7 @@ int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f)
+ read_unlock(&f->lock);
+
+ spin_lock(&q->lock);
+- if (!(q->last_in & COMPLETE))
++ if (!(q->last_in & INET_FRAG_COMPLETE))
+ inet_frag_kill(q, f);
+ spin_unlock(&q->lock);
+
+@@ -209,7 +209,7 @@ static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf,
+ if (qp->net == nf && f->match(qp, arg)) {
+ atomic_inc(&qp->refcnt);
+ write_unlock(&f->lock);
+- qp_in->last_in |= COMPLETE;
++ qp_in->last_in |= INET_FRAG_COMPLETE;
+ inet_frag_put(qp_in, f);
+ return qp;
+ }
+diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
+index 1aba606..2023d37 100644
+--- a/net/ipv4/inet_hashtables.c
++++ b/net/ipv4/inet_hashtables.c
+@@ -35,7 +35,7 @@ struct inet_bind_bucket *inet_bind_bucket_create(struct kmem_cache *cachep,
+ struct inet_bind_bucket *tb = kmem_cache_alloc(cachep, GFP_ATOMIC);
+
+ if (tb != NULL) {
+- tb->ib_net = net;
++ tb->ib_net = hold_net(net);
+ tb->port = snum;
+ tb->fastreuse = 0;
+ INIT_HLIST_HEAD(&tb->owners);
+@@ -51,6 +51,7 @@ void inet_bind_bucket_destroy(struct kmem_cache *cachep, struct inet_bind_bucket
+ {
+ if (hlist_empty(&tb->owners)) {
+ __hlist_del(&tb->node);
++ release_net(tb->ib_net);
+ kmem_cache_free(cachep, tb);
+ }
+ }
+@@ -68,7 +69,7 @@ void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
+ */
+ static void __inet_put_port(struct sock *sk)
+ {
+- struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
++ struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
+ const int bhash = inet_bhashfn(inet_sk(sk)->num, hashinfo->bhash_size);
+ struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash];
+ struct inet_bind_bucket *tb;
+@@ -91,6 +92,22 @@ void inet_put_port(struct sock *sk)
+
+ EXPORT_SYMBOL(inet_put_port);
+
++void __inet_inherit_port(struct sock *sk, struct sock *child)
++{
++ struct inet_hashinfo *table = sk->sk_prot->h.hashinfo;
++ const int bhash = inet_bhashfn(inet_sk(child)->num, table->bhash_size);
++ struct inet_bind_hashbucket *head = &table->bhash[bhash];
++ struct inet_bind_bucket *tb;
++
++ spin_lock(&head->lock);
++ tb = inet_csk(sk)->icsk_bind_hash;
++ sk_add_bind_node(child, &tb->owners);
++ inet_csk(child)->icsk_bind_hash = tb;
++ spin_unlock(&head->lock);
++}
++
++EXPORT_SYMBOL_GPL(__inet_inherit_port);
++
+ /*
+ * This lock without WQ_FLAG_EXCLUSIVE is good on UP and it can be very bad on SMP.
+ * Look, when several writers sleep and reader wakes them up, all but one
+@@ -139,7 +156,7 @@ static struct sock *inet_lookup_listener_slow(struct net *net,
+ sk_for_each(sk, node, head) {
+ const struct inet_sock *inet = inet_sk(sk);
+
+- if (sk->sk_net == net && inet->num == hnum &&
++ if (net_eq(sock_net(sk), net) && inet->num == hnum &&
+ !ipv6_only_sock(sk)) {
+ const __be32 rcv_saddr = inet->rcv_saddr;
+ int score = sk->sk_family == PF_INET ? 1 : 0;
+@@ -182,7 +199,7 @@ struct sock *__inet_lookup_listener(struct net *net,
+ if (inet->num == hnum && !sk->sk_node.next &&
+ (!inet->rcv_saddr || inet->rcv_saddr == daddr) &&
+ (sk->sk_family == PF_INET || !ipv6_only_sock(sk)) &&
+- !sk->sk_bound_dev_if && sk->sk_net == net)
++ !sk->sk_bound_dev_if && net_eq(sock_net(sk), net))
+ goto sherry_cache;
+ sk = inet_lookup_listener_slow(net, head, daddr, hnum, dif);
+ }
+@@ -254,7 +271,7 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
+ struct sock *sk2;
+ const struct hlist_node *node;
+ struct inet_timewait_sock *tw;
+- struct net *net = sk->sk_net;
++ struct net *net = sock_net(sk);
+
+ prefetch(head->chain.first);
+ write_lock(lock);
+@@ -288,7 +305,7 @@ unique:
+ sk->sk_hash = hash;
+ BUG_TRAP(sk_unhashed(sk));
+ __sk_add_node(sk, &head->chain);
+- sock_prot_inuse_add(sk->sk_prot, 1);
++ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
+ write_unlock(lock);
+
+ if (twp) {
+@@ -318,7 +335,7 @@ static inline u32 inet_sk_port_offset(const struct sock *sk)
+
+ void __inet_hash_nolisten(struct sock *sk)
+ {
+- struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
++ struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
+ struct hlist_head *list;
+ rwlock_t *lock;
+ struct inet_ehash_bucket *head;
+@@ -332,14 +349,14 @@ void __inet_hash_nolisten(struct sock *sk)
+
+ write_lock(lock);
+ __sk_add_node(sk, list);
+- sock_prot_inuse_add(sk->sk_prot, 1);
++ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
+ write_unlock(lock);
+ }
+ EXPORT_SYMBOL_GPL(__inet_hash_nolisten);
+
+ static void __inet_hash(struct sock *sk)
+ {
+- struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
++ struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
+ struct hlist_head *list;
+ rwlock_t *lock;
+
+@@ -354,7 +371,7 @@ static void __inet_hash(struct sock *sk)
+
+ inet_listen_wlock(hashinfo);
+ __sk_add_node(sk, list);
+- sock_prot_inuse_add(sk->sk_prot, 1);
++ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
+ write_unlock(lock);
+ wake_up(&hashinfo->lhash_wait);
+ }
+@@ -372,7 +389,7 @@ EXPORT_SYMBOL_GPL(inet_hash);
+ void inet_unhash(struct sock *sk)
+ {
+ rwlock_t *lock;
+- struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
++ struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
+
+ if (sk_unhashed(sk))
+ goto out;
+@@ -387,7 +404,7 @@ void inet_unhash(struct sock *sk)
+ }
+
+ if (__sk_del_node_init(sk))
+- sock_prot_inuse_add(sk->sk_prot, -1);
++ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
+ write_unlock_bh(lock);
+ out:
+ if (sk->sk_state == TCP_LISTEN)
+@@ -406,7 +423,7 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
+ struct inet_bind_hashbucket *head;
+ struct inet_bind_bucket *tb;
+ int ret;
+- struct net *net = sk->sk_net;
++ struct net *net = sock_net(sk);
+
+ if (!snum) {
+ int i, remaining, low, high, port;
+diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c
+index 717c411..ce16e9a 100644
+--- a/net/ipv4/inet_timewait_sock.c
++++ b/net/ipv4/inet_timewait_sock.c
+@@ -57,6 +57,7 @@ void inet_twsk_put(struct inet_timewait_sock *tw)
+ printk(KERN_DEBUG "%s timewait_sock %p released\n",
+ tw->tw_prot->name, tw);
+ #endif
++ release_net(twsk_net(tw));
+ kmem_cache_free(tw->tw_prot->twsk_prot->twsk_slab, tw);
+ module_put(owner);
+ }
+@@ -91,7 +92,7 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
+
+ /* Step 2: Remove SK from established hash. */
+ if (__sk_del_node_init(sk))
+- sock_prot_inuse_add(sk->sk_prot, -1);
++ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
+
+ /* Step 3: Hash TW into TIMEWAIT chain. */
+ inet_twsk_add_node(tw, &ehead->twchain);
+@@ -124,7 +125,7 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int stat
+ tw->tw_hash = sk->sk_hash;
+ tw->tw_ipv6only = 0;
+ tw->tw_prot = sk->sk_prot_creator;
+- tw->tw_net = sk->sk_net;
++ twsk_net_set(tw, hold_net(sock_net(sk)));
+ atomic_set(&tw->tw_refcnt, 1);
+ inet_twsk_dead_node_init(tw);
+ __module_get(tw->tw_prot->owner);
+diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
+index a4506c8..4813c39 100644
+--- a/net/ipv4/ip_forward.c
++++ b/net/ipv4/ip_forward.c
+@@ -80,7 +80,7 @@ int ip_forward(struct sk_buff *skb)
+ if (!xfrm4_route_forward(skb))
+ goto drop;
+
+- rt = (struct rtable*)skb->dst;
++ rt = skb->rtable;
+
+ if (opt->is_strictroute && rt->rt_dst != rt->rt_gateway)
+ goto sr_failed;
+diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
+index 3b2e5ad..cd6ce6a 100644
+--- a/net/ipv4/ip_fragment.c
++++ b/net/ipv4/ip_fragment.c
+@@ -194,7 +194,7 @@ static void ip_expire(unsigned long arg)
+
+ spin_lock(&qp->q.lock);
+
+- if (qp->q.last_in & COMPLETE)
++ if (qp->q.last_in & INET_FRAG_COMPLETE)
+ goto out;
+
+ ipq_kill(qp);
+@@ -202,10 +202,13 @@ static void ip_expire(unsigned long arg)
+ IP_INC_STATS_BH(IPSTATS_MIB_REASMTIMEOUT);
+ IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
+
+- if ((qp->q.last_in&FIRST_IN) && qp->q.fragments != NULL) {
++ if ((qp->q.last_in & INET_FRAG_FIRST_IN) && qp->q.fragments != NULL) {
+ struct sk_buff *head = qp->q.fragments;
++ struct net *net;
++
++ net = container_of(qp->q.net, struct net, ipv4.frags);
+ /* Send an ICMP "Fragment Reassembly Timeout" message. */
+- if ((head->dev = dev_get_by_index(&init_net, qp->iif)) != NULL) {
++ if ((head->dev = dev_get_by_index(net, qp->iif)) != NULL) {
+ icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
+ dev_put(head->dev);
+ }
+@@ -298,7 +301,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
+ int ihl, end;
+ int err = -ENOENT;
+
+- if (qp->q.last_in & COMPLETE)
++ if (qp->q.last_in & INET_FRAG_COMPLETE)
+ goto err;
+
+ if (!(IPCB(skb)->flags & IPSKB_FRAG_COMPLETE) &&
+@@ -324,9 +327,9 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
+ * or have different end, the segment is corrrupted.
+ */
+ if (end < qp->q.len ||
+- ((qp->q.last_in & LAST_IN) && end != qp->q.len))
++ ((qp->q.last_in & INET_FRAG_LAST_IN) && end != qp->q.len))
+ goto err;
+- qp->q.last_in |= LAST_IN;
++ qp->q.last_in |= INET_FRAG_LAST_IN;
+ qp->q.len = end;
+ } else {
+ if (end&7) {
+@@ -336,7 +339,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
+ }
+ if (end > qp->q.len) {
+ /* Some bits beyond end -> corruption. */
+- if (qp->q.last_in & LAST_IN)
++ if (qp->q.last_in & INET_FRAG_LAST_IN)
+ goto err;
+ qp->q.len = end;
+ }
+@@ -435,9 +438,10 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
+ qp->q.meat += skb->len;
+ atomic_add(skb->truesize, &qp->q.net->mem);
+ if (offset == 0)
+- qp->q.last_in |= FIRST_IN;
++ qp->q.last_in |= INET_FRAG_FIRST_IN;
+
+- if (qp->q.last_in == (FIRST_IN | LAST_IN) && qp->q.meat == qp->q.len)
++ if (qp->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) &&
++ qp->q.meat == qp->q.len)
+ return ip_frag_reasm(qp, prev, dev);
+
+ write_lock(&ip4_frags.lock);
+@@ -553,7 +557,7 @@ out_nomem:
+ out_oversize:
+ if (net_ratelimit())
+ printk(KERN_INFO
+- "Oversized IP packet from %d.%d.%d.%d.\n",
++ "Oversized IP packet from " NIPQUAD_FMT ".\n",
+ NIPQUAD(qp->saddr));
+ out_fail:
+ IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
+@@ -568,7 +572,7 @@ int ip_defrag(struct sk_buff *skb, u32 user)
+
+ IP_INC_STATS_BH(IPSTATS_MIB_REASMREQDS);
+
+- net = skb->dev ? skb->dev->nd_net : skb->dst->dev->nd_net;
++ net = skb->dev ? dev_net(skb->dev) : dev_net(skb->dst->dev);
+ /* Start by cleaning up the memory. */
+ if (atomic_read(&net->ipv4.frags.mem) > net->ipv4.frags.high_thresh)
+ ip_evictor(net);
+diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
+index e7821ba..2ada033 100644
+--- a/net/ipv4/ip_gre.c
++++ b/net/ipv4/ip_gre.c
+@@ -39,6 +39,8 @@
+ #include <net/dsfield.h>
+ #include <net/inet_ecn.h>
+ #include <net/xfrm.h>
++#include <net/net_namespace.h>
++#include <net/netns/generic.h>
+
+ #ifdef CONFIG_IPV6
+ #include <net/ipv6.h>
+@@ -122,7 +124,14 @@ static void ipgre_tunnel_setup(struct net_device *dev);
+
+ static int ipgre_fb_tunnel_init(struct net_device *dev);
+
+-static struct net_device *ipgre_fb_tunnel_dev;
++#define HASH_SIZE 16
++
++static int ipgre_net_id;
++struct ipgre_net {
++ struct ip_tunnel *tunnels[4][HASH_SIZE];
++
++ struct net_device *fb_tunnel_dev;
++};
+
+ /* Tunnel hash table */
+
+@@ -142,39 +151,38 @@ static struct net_device *ipgre_fb_tunnel_dev;
+ will match fallback tunnel.
+ */
+
+-#define HASH_SIZE 16
+ #define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF)
+
+-static struct ip_tunnel *tunnels[4][HASH_SIZE];
+-
+-#define tunnels_r_l (tunnels[3])
+-#define tunnels_r (tunnels[2])
+-#define tunnels_l (tunnels[1])
+-#define tunnels_wc (tunnels[0])
++#define tunnels_r_l tunnels[3]
++#define tunnels_r tunnels[2]
++#define tunnels_l tunnels[1]
++#define tunnels_wc tunnels[0]
+
+ static DEFINE_RWLOCK(ipgre_lock);
+
+ /* Given src, dst and key, find appropriate for input tunnel. */
+
+-static struct ip_tunnel * ipgre_tunnel_lookup(__be32 remote, __be32 local, __be32 key)
++static struct ip_tunnel * ipgre_tunnel_lookup(struct net *net,
++ __be32 remote, __be32 local, __be32 key)
+ {
+ unsigned h0 = HASH(remote);
+ unsigned h1 = HASH(key);
+ struct ip_tunnel *t;
++ struct ipgre_net *ign = net_generic(net, ipgre_net_id);
+
+- for (t = tunnels_r_l[h0^h1]; t; t = t->next) {
++ for (t = ign->tunnels_r_l[h0^h1]; t; t = t->next) {
+ if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) {
+ if (t->parms.i_key == key && (t->dev->flags&IFF_UP))
+ return t;
+ }
+ }
+- for (t = tunnels_r[h0^h1]; t; t = t->next) {
++ for (t = ign->tunnels_r[h0^h1]; t; t = t->next) {
+ if (remote == t->parms.iph.daddr) {
+ if (t->parms.i_key == key && (t->dev->flags&IFF_UP))
+ return t;
+ }
+ }
+- for (t = tunnels_l[h1]; t; t = t->next) {
++ for (t = ign->tunnels_l[h1]; t; t = t->next) {
+ if (local == t->parms.iph.saddr ||
+ (local == t->parms.iph.daddr &&
+ ipv4_is_multicast(local))) {
+@@ -182,17 +190,18 @@ static struct ip_tunnel * ipgre_tunnel_lookup(__be32 remote, __be32 local, __be3
+ return t;
+ }
+ }
+- for (t = tunnels_wc[h1]; t; t = t->next) {
++ for (t = ign->tunnels_wc[h1]; t; t = t->next) {
+ if (t->parms.i_key == key && (t->dev->flags&IFF_UP))
+ return t;
+ }
+
+- if (ipgre_fb_tunnel_dev->flags&IFF_UP)
+- return netdev_priv(ipgre_fb_tunnel_dev);
++ if (ign->fb_tunnel_dev->flags&IFF_UP)
++ return netdev_priv(ign->fb_tunnel_dev);
+ return NULL;
+ }
+
+-static struct ip_tunnel **__ipgre_bucket(struct ip_tunnel_parm *parms)
++static struct ip_tunnel **__ipgre_bucket(struct ipgre_net *ign,
++ struct ip_tunnel_parm *parms)
+ {
+ __be32 remote = parms->iph.daddr;
+ __be32 local = parms->iph.saddr;
+@@ -207,17 +216,18 @@ static struct ip_tunnel **__ipgre_bucket(struct ip_tunnel_parm *parms)
+ h ^= HASH(remote);
+ }
+
+- return &tunnels[prio][h];
++ return &ign->tunnels[prio][h];
+ }
+
+-static inline struct ip_tunnel **ipgre_bucket(struct ip_tunnel *t)
++static inline struct ip_tunnel **ipgre_bucket(struct ipgre_net *ign,
++ struct ip_tunnel *t)
+ {
+- return __ipgre_bucket(&t->parms);
++ return __ipgre_bucket(ign, &t->parms);
+ }
+
+-static void ipgre_tunnel_link(struct ip_tunnel *t)
++static void ipgre_tunnel_link(struct ipgre_net *ign, struct ip_tunnel *t)
+ {
+- struct ip_tunnel **tp = ipgre_bucket(t);
++ struct ip_tunnel **tp = ipgre_bucket(ign, t);
+
+ t->next = *tp;
+ write_lock_bh(&ipgre_lock);
+@@ -225,11 +235,11 @@ static void ipgre_tunnel_link(struct ip_tunnel *t)
+ write_unlock_bh(&ipgre_lock);
+ }
+
+-static void ipgre_tunnel_unlink(struct ip_tunnel *t)
++static void ipgre_tunnel_unlink(struct ipgre_net *ign, struct ip_tunnel *t)
+ {
+ struct ip_tunnel **tp;
+
+- for (tp = ipgre_bucket(t); *tp; tp = &(*tp)->next) {
++ for (tp = ipgre_bucket(ign, t); *tp; tp = &(*tp)->next) {
+ if (t == *tp) {
+ write_lock_bh(&ipgre_lock);
+ *tp = t->next;
+@@ -239,7 +249,8 @@ static void ipgre_tunnel_unlink(struct ip_tunnel *t)
+ }
+ }
+
+-static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int create)
++static struct ip_tunnel * ipgre_tunnel_locate(struct net *net,
++ struct ip_tunnel_parm *parms, int create)
+ {
+ __be32 remote = parms->iph.daddr;
+ __be32 local = parms->iph.saddr;
+@@ -247,8 +258,9 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int
+ struct ip_tunnel *t, **tp, *nt;
+ struct net_device *dev;
+ char name[IFNAMSIZ];
++ struct ipgre_net *ign = net_generic(net, ipgre_net_id);
+
+- for (tp = __ipgre_bucket(parms); (t = *tp) != NULL; tp = &t->next) {
++ for (tp = __ipgre_bucket(ign, parms); (t = *tp) != NULL; tp = &t->next) {
+ if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) {
+ if (key == t->parms.i_key)
+ return t;
+@@ -266,6 +278,8 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int
+ if (!dev)
+ return NULL;
+
++ dev_net_set(dev, net);
++
+ if (strchr(name, '%')) {
+ if (dev_alloc_name(dev, name) < 0)
+ goto failed_free;
+@@ -279,7 +293,7 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int
+ goto failed_free;
+
+ dev_hold(dev);
+- ipgre_tunnel_link(nt);
++ ipgre_tunnel_link(ign, nt);
+ return nt;
+
+ failed_free:
+@@ -289,7 +303,10 @@ failed_free:
+
+ static void ipgre_tunnel_uninit(struct net_device *dev)
+ {
+- ipgre_tunnel_unlink(netdev_priv(dev));
++ struct net *net = dev_net(dev);
++ struct ipgre_net *ign = net_generic(net, ipgre_net_id);
++
++ ipgre_tunnel_unlink(ign, netdev_priv(dev));
+ dev_put(dev);
+ }
+
+@@ -363,7 +380,9 @@ static void ipgre_err(struct sk_buff *skb, u32 info)
+ }
+
+ read_lock(&ipgre_lock);
+- t = ipgre_tunnel_lookup(iph->daddr, iph->saddr, (flags&GRE_KEY) ? *(((__be32*)p) + (grehlen>>2) - 1) : 0);
++ t = ipgre_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr,
++ (flags&GRE_KEY) ?
++ *(((__be32*)p) + (grehlen>>2) - 1) : 0);
+ if (t == NULL || t->parms.iph.daddr == 0 ||
+ ipv4_is_multicast(t->parms.iph.daddr))
+ goto out;
+@@ -476,7 +495,7 @@ out:
+ fl.fl4_dst = eiph->saddr;
+ fl.fl4_tos = RT_TOS(eiph->tos);
+ fl.proto = IPPROTO_GRE;
+- if (ip_route_output_key(&init_net, &rt, &fl)) {
++ if (ip_route_output_key(dev_net(skb->dev), &rt, &fl)) {
+ kfree_skb(skb2);
+ return;
+ }
+@@ -489,7 +508,7 @@ out:
+ fl.fl4_dst = eiph->daddr;
+ fl.fl4_src = eiph->saddr;
+ fl.fl4_tos = eiph->tos;
+- if (ip_route_output_key(&init_net, &rt, &fl) ||
++ if (ip_route_output_key(dev_net(skb->dev), &rt, &fl) ||
+ rt->u.dst.dev->type != ARPHRD_IPGRE) {
+ ip_rt_put(rt);
+ kfree_skb(skb2);
+@@ -596,7 +615,8 @@ static int ipgre_rcv(struct sk_buff *skb)
+ }
+
+ read_lock(&ipgre_lock);
+- if ((tunnel = ipgre_tunnel_lookup(iph->saddr, iph->daddr, key)) != NULL) {
++ if ((tunnel = ipgre_tunnel_lookup(dev_net(skb->dev),
++ iph->saddr, iph->daddr, key)) != NULL) {
+ secpath_reset(skb);
+
+ skb->protocol = *(__be16*)(h + 2);
+@@ -619,7 +639,7 @@ static int ipgre_rcv(struct sk_buff *skb)
+ #ifdef CONFIG_NET_IPGRE_BROADCAST
+ if (ipv4_is_multicast(iph->daddr)) {
+ /* Looped back packet, drop it! */
+- if (((struct rtable*)skb->dst)->fl.iif == 0)
++ if (skb->rtable->fl.iif == 0)
+ goto drop;
+ tunnel->stat.multicast++;
+ skb->pkt_type = PACKET_BROADCAST;
+@@ -699,7 +719,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+ }
+
+ if (skb->protocol == htons(ETH_P_IP)) {
+- rt = (struct rtable*)skb->dst;
++ rt = skb->rtable;
+ if ((dst = rt->rt_gateway) == 0)
+ goto tx_error_icmp;
+ }
+@@ -744,7 +764,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+ .saddr = tiph->saddr,
+ .tos = RT_TOS(tos) } },
+ .proto = IPPROTO_GRE };
+- if (ip_route_output_key(&init_net, &rt, &fl)) {
++ if (ip_route_output_key(dev_net(dev), &rt, &fl)) {
+ tunnel->stat.tx_carrier_errors++;
+ goto tx_error;
+ }
+@@ -917,7 +937,7 @@ static void ipgre_tunnel_bind_dev(struct net_device *dev)
+ .tos = RT_TOS(iph->tos) } },
+ .proto = IPPROTO_GRE };
+ struct rtable *rt;
+- if (!ip_route_output_key(&init_net, &rt, &fl)) {
++ if (!ip_route_output_key(dev_net(dev), &rt, &fl)) {
+ tdev = rt->u.dst.dev;
+ ip_rt_put(rt);
+ }
+@@ -925,7 +945,7 @@ static void ipgre_tunnel_bind_dev(struct net_device *dev)
+ }
+
+ if (!tdev && tunnel->parms.link)
+- tdev = __dev_get_by_index(&init_net, tunnel->parms.link);
++ tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link);
+
+ if (tdev) {
+ hlen = tdev->hard_header_len;
+@@ -954,16 +974,18 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ int err = 0;
+ struct ip_tunnel_parm p;
+ struct ip_tunnel *t;
++ struct net *net = dev_net(dev);
++ struct ipgre_net *ign = net_generic(net, ipgre_net_id);
+
+ switch (cmd) {
+ case SIOCGETTUNNEL:
+ t = NULL;
+- if (dev == ipgre_fb_tunnel_dev) {
++ if (dev == ign->fb_tunnel_dev) {
+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) {
+ err = -EFAULT;
+ break;
+ }
+- t = ipgre_tunnel_locate(&p, 0);
++ t = ipgre_tunnel_locate(net, &p, 0);
+ }
+ if (t == NULL)
+ t = netdev_priv(dev);
+@@ -995,9 +1017,9 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ if (!(p.o_flags&GRE_KEY))
+ p.o_key = 0;
+
+- t = ipgre_tunnel_locate(&p, cmd == SIOCADDTUNNEL);
++ t = ipgre_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL);
+
+- if (dev != ipgre_fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
++ if (dev != ign->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
+ if (t != NULL) {
+ if (t->dev != dev) {
+ err = -EEXIST;
+@@ -1017,14 +1039,14 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ err = -EINVAL;
+ break;
+ }
+- ipgre_tunnel_unlink(t);
++ ipgre_tunnel_unlink(ign, t);
+ t->parms.iph.saddr = p.iph.saddr;
+ t->parms.iph.daddr = p.iph.daddr;
+ t->parms.i_key = p.i_key;
+ t->parms.o_key = p.o_key;
+ memcpy(dev->dev_addr, &p.iph.saddr, 4);
+ memcpy(dev->broadcast, &p.iph.daddr, 4);
+- ipgre_tunnel_link(t);
++ ipgre_tunnel_link(ign, t);
+ netdev_state_change(dev);
+ }
+ }
+@@ -1052,15 +1074,15 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ if (!capable(CAP_NET_ADMIN))
+ goto done;
+
+- if (dev == ipgre_fb_tunnel_dev) {
++ if (dev == ign->fb_tunnel_dev) {
+ err = -EFAULT;
+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
+ goto done;
+ err = -ENOENT;
+- if ((t = ipgre_tunnel_locate(&p, 0)) == NULL)
++ if ((t = ipgre_tunnel_locate(net, &p, 0)) == NULL)
+ goto done;
+ err = -EPERM;
+- if (t == netdev_priv(ipgre_fb_tunnel_dev))
++ if (t == netdev_priv(ign->fb_tunnel_dev))
+ goto done;
+ dev = t->dev;
+ }
+@@ -1173,7 +1195,7 @@ static int ipgre_open(struct net_device *dev)
+ .tos = RT_TOS(t->parms.iph.tos) } },
+ .proto = IPPROTO_GRE };
+ struct rtable *rt;
+- if (ip_route_output_key(&init_net, &rt, &fl))
++ if (ip_route_output_key(dev_net(dev), &rt, &fl))
+ return -EADDRNOTAVAIL;
+ dev = rt->u.dst.dev;
+ ip_rt_put(rt);
+@@ -1190,7 +1212,7 @@ static int ipgre_close(struct net_device *dev)
+ struct ip_tunnel *t = netdev_priv(dev);
+ if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) {
+ struct in_device *in_dev;
+- in_dev = inetdev_by_index(dev->nd_net, t->mlink);
++ in_dev = inetdev_by_index(dev_net(dev), t->mlink);
+ if (in_dev) {
+ ip_mc_dec_group(in_dev, t->parms.iph.daddr);
+ in_dev_put(in_dev);
+@@ -1216,6 +1238,7 @@ static void ipgre_tunnel_setup(struct net_device *dev)
+ dev->flags = IFF_NOARP;
+ dev->iflink = 0;
+ dev->addr_len = 4;
++ dev->features |= NETIF_F_NETNS_LOCAL;
+ }
+
+ static int ipgre_tunnel_init(struct net_device *dev)
+@@ -1251,10 +1274,11 @@ static int ipgre_tunnel_init(struct net_device *dev)
+ return 0;
+ }
+
+-static int __init ipgre_fb_tunnel_init(struct net_device *dev)
++static int ipgre_fb_tunnel_init(struct net_device *dev)
+ {
+ struct ip_tunnel *tunnel = netdev_priv(dev);
+ struct iphdr *iph = &tunnel->parms.iph;
++ struct ipgre_net *ign = net_generic(dev_net(dev), ipgre_net_id);
+
+ tunnel->dev = dev;
+ strcpy(tunnel->parms.name, dev->name);
+@@ -1265,7 +1289,7 @@ static int __init ipgre_fb_tunnel_init(struct net_device *dev)
+ tunnel->hlen = sizeof(struct iphdr) + 4;
+
+ dev_hold(dev);
+- tunnels_wc[0] = tunnel;
++ ign->tunnels_wc[0] = tunnel;
+ return 0;
+ }
+
+@@ -1273,56 +1297,98 @@ static int __init ipgre_fb_tunnel_init(struct net_device *dev)
+ static struct net_protocol ipgre_protocol = {
+ .handler = ipgre_rcv,
+ .err_handler = ipgre_err,
++ .netns_ok = 1,
+ };
+
++static void ipgre_destroy_tunnels(struct ipgre_net *ign)
++{
++ int prio;
+
+-/*
+- * And now the modules code and kernel interface.
+- */
++ for (prio = 0; prio < 4; prio++) {
++ int h;
++ for (h = 0; h < HASH_SIZE; h++) {
++ struct ip_tunnel *t;
++ while ((t = ign->tunnels[prio][h]) != NULL)
++ unregister_netdevice(t->dev);
++ }
++ }
++}
+
+-static int __init ipgre_init(void)
++static int ipgre_init_net(struct net *net)
+ {
+ int err;
++ struct ipgre_net *ign;
+
+- printk(KERN_INFO "GRE over IPv4 tunneling driver\n");
++ err = -ENOMEM;
++ ign = kzalloc(sizeof(struct ipgre_net), GFP_KERNEL);
++ if (ign == NULL)
++ goto err_alloc;
+
+- if (inet_add_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) {
+- printk(KERN_INFO "ipgre init: can't add protocol\n");
+- return -EAGAIN;
+- }
++ err = net_assign_generic(net, ipgre_net_id, ign);
++ if (err < 0)
++ goto err_assign;
+
+- ipgre_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "gre0",
++ ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "gre0",
+ ipgre_tunnel_setup);
+- if (!ipgre_fb_tunnel_dev) {
++ if (!ign->fb_tunnel_dev) {
+ err = -ENOMEM;
+- goto err1;
++ goto err_alloc_dev;
+ }
+
+- ipgre_fb_tunnel_dev->init = ipgre_fb_tunnel_init;
++ ign->fb_tunnel_dev->init = ipgre_fb_tunnel_init;
++ dev_net_set(ign->fb_tunnel_dev, net);
+
+- if ((err = register_netdev(ipgre_fb_tunnel_dev)))
+- goto err2;
+-out:
++ if ((err = register_netdev(ign->fb_tunnel_dev)))
++ goto err_reg_dev;
++
++ return 0;
++
++err_reg_dev:
++ free_netdev(ign->fb_tunnel_dev);
++err_alloc_dev:
++ /* nothing */
++err_assign:
++ kfree(ign);
++err_alloc:
+ return err;
+-err2:
+- free_netdev(ipgre_fb_tunnel_dev);
+-err1:
+- inet_del_protocol(&ipgre_protocol, IPPROTO_GRE);
+- goto out;
+ }
+
+-static void __exit ipgre_destroy_tunnels(void)
++static void ipgre_exit_net(struct net *net)
+ {
+- int prio;
++ struct ipgre_net *ign;
+
+- for (prio = 0; prio < 4; prio++) {
+- int h;
+- for (h = 0; h < HASH_SIZE; h++) {
+- struct ip_tunnel *t;
+- while ((t = tunnels[prio][h]) != NULL)
+- unregister_netdevice(t->dev);
+- }
++ ign = net_generic(net, ipgre_net_id);
++ rtnl_lock();
++ ipgre_destroy_tunnels(ign);
++ rtnl_unlock();
++ kfree(ign);
++}
++
++static struct pernet_operations ipgre_net_ops = {
++ .init = ipgre_init_net,
++ .exit = ipgre_exit_net,
++};
++
++/*
++ * And now the modules code and kernel interface.
++ */
++
++static int __init ipgre_init(void)
++{
++ int err;
++
++ printk(KERN_INFO "GRE over IPv4 tunneling driver\n");
++
++ if (inet_add_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) {
++ printk(KERN_INFO "ipgre init: can't add protocol\n");
++ return -EAGAIN;
+ }
++
++ err = register_pernet_gen_device(&ipgre_net_id, &ipgre_net_ops);
++ if (err < 0)
++ inet_del_protocol(&ipgre_protocol, IPPROTO_GRE);
++
++ return err;
+ }
+
+ static void __exit ipgre_fini(void)
+@@ -1330,9 +1396,7 @@ static void __exit ipgre_fini(void)
+ if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0)
+ printk(KERN_INFO "ipgre close: can't remove protocol\n");
+
+- rtnl_lock();
+- ipgre_destroy_tunnels();
+- rtnl_unlock();
++ unregister_pernet_gen_device(ipgre_net_id, &ipgre_net_ops);
+ }
+
+ module_init(ipgre_init);
+diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
+index 6563139..7b4bad6 100644
+--- a/net/ipv4/ip_input.c
++++ b/net/ipv4/ip_input.c
+@@ -160,6 +160,7 @@ int ip_call_ra_chain(struct sk_buff *skb)
+ struct ip_ra_chain *ra;
+ u8 protocol = ip_hdr(skb)->protocol;
+ struct sock *last = NULL;
++ struct net_device *dev = skb->dev;
+
+ read_lock(&ip_ra_lock);
+ for (ra = ip_ra_chain; ra; ra = ra->next) {
+@@ -170,7 +171,8 @@ int ip_call_ra_chain(struct sk_buff *skb)
+ */
+ if (sk && inet_sk(sk)->num == protocol &&
+ (!sk->sk_bound_dev_if ||
+- sk->sk_bound_dev_if == skb->dev->ifindex)) {
++ sk->sk_bound_dev_if == dev->ifindex) &&
++ sock_net(sk) == dev_net(dev)) {
+ if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
+ if (ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN)) {
+ read_unlock(&ip_ra_lock);
+@@ -197,6 +199,8 @@ int ip_call_ra_chain(struct sk_buff *skb)
+
+ static int ip_local_deliver_finish(struct sk_buff *skb)
+ {
++ struct net *net = dev_net(skb->dev);
++
+ __skb_pull(skb, ip_hdrlen(skb));
+
+ /* Point into the IP datagram, just past the header. */
+@@ -212,7 +216,8 @@ static int ip_local_deliver_finish(struct sk_buff *skb)
+ raw = raw_local_deliver(skb, protocol);
+
+ hash = protocol & (MAX_INET_PROTOS - 1);
+- if ((ipprot = rcu_dereference(inet_protos[hash])) != NULL) {
++ ipprot = rcu_dereference(inet_protos[hash]);
++ if (ipprot != NULL && (net == &init_net || ipprot->netns_ok)) {
+ int ret;
+
+ if (!ipprot->no_policy) {
+@@ -283,13 +288,14 @@ static inline int ip_rcv_options(struct sk_buff *skb)
+ }
+
+ iph = ip_hdr(skb);
++ opt = &(IPCB(skb)->opt);
++ opt->optlen = iph->ihl*4 - sizeof(struct iphdr);
+
+- if (ip_options_compile(NULL, skb)) {
++ if (ip_options_compile(dev_net(dev), opt, skb)) {
+ IP_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+ goto drop;
+ }
+
+- opt = &(IPCB(skb)->opt);
+ if (unlikely(opt->srr)) {
+ struct in_device *in_dev = in_dev_get(dev);
+ if (in_dev) {
+@@ -297,7 +303,7 @@ static inline int ip_rcv_options(struct sk_buff *skb)
+ if (IN_DEV_LOG_MARTIANS(in_dev) &&
+ net_ratelimit())
+ printk(KERN_INFO "source route option "
+- "%u.%u.%u.%u -> %u.%u.%u.%u\n",
++ NIPQUAD_FMT " -> " NIPQUAD_FMT "\n",
+ NIPQUAD(iph->saddr),
+ NIPQUAD(iph->daddr));
+ in_dev_put(in_dev);
+@@ -351,7 +357,7 @@ static int ip_rcv_finish(struct sk_buff *skb)
+ if (iph->ihl > 5 && ip_rcv_options(skb))
+ goto drop;
+
+- rt = (struct rtable*)skb->dst;
++ rt = skb->rtable;
+ if (rt->rt_type == RTN_MULTICAST)
+ IP_INC_STATS_BH(IPSTATS_MIB_INMCASTPKTS);
+ else if (rt->rt_type == RTN_BROADCAST)
+@@ -372,9 +378,6 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
+ struct iphdr *iph;
+ u32 len;
+
+- if (dev->nd_net != &init_net)
+- goto drop;
+-
+ /* When the interface is in promisc. mode, drop all the crap
+ * that it receives, do not try to analyse it.
+ */
+diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
+index 4d31515..33126ad 100644
+--- a/net/ipv4/ip_options.c
++++ b/net/ipv4/ip_options.c
+@@ -45,7 +45,6 @@ void ip_options_build(struct sk_buff * skb, struct ip_options * opt,
+ memcpy(&(IPCB(skb)->opt), opt, sizeof(struct ip_options));
+ memcpy(iph+sizeof(struct iphdr), opt->__data, opt->optlen);
+ opt = &(IPCB(skb)->opt);
+- opt->is_data = 0;
+
+ if (opt->srr)
+ memcpy(iph+opt->srr+iph[opt->srr+1]-4, &daddr, 4);
+@@ -56,10 +55,10 @@ void ip_options_build(struct sk_buff * skb, struct ip_options * opt,
+ if (opt->ts_needaddr)
+ ip_rt_get_source(iph+opt->ts+iph[opt->ts+2]-9, rt);
+ if (opt->ts_needtime) {
+- struct timeval tv;
++ struct timespec tv;
+ __be32 midtime;
+- do_gettimeofday(&tv);
+- midtime = htonl((tv.tv_sec % 86400) * 1000 + tv.tv_usec / 1000);
++ getnstimeofday(&tv);
++ midtime = htonl((tv.tv_sec % 86400) * MSEC_PER_SEC + tv.tv_nsec / NSEC_PER_MSEC);
+ memcpy(iph+opt->ts+iph[opt->ts+2]-5, &midtime, 4);
+ }
+ return;
+@@ -95,8 +94,6 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb)
+
+ memset(dopt, 0, sizeof(struct ip_options));
+
+- dopt->is_data = 1;
+-
+ sopt = &(IPCB(skb)->opt);
+
+ if (sopt->optlen == 0) {
+@@ -107,10 +104,7 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb)
+ sptr = skb_network_header(skb);
+ dptr = dopt->__data;
+
+- if (skb->dst)
+- daddr = ((struct rtable*)skb->dst)->rt_spec_dst;
+- else
+- daddr = ip_hdr(skb)->daddr;
++ daddr = skb->rtable->rt_spec_dst;
+
+ if (sopt->rr) {
+ optlen = sptr[sopt->rr+1];
+@@ -151,7 +145,7 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb)
+ __be32 addr;
+
+ memcpy(&addr, sptr+soffset-1, 4);
+- if (inet_addr_type(&init_net, addr) != RTN_LOCAL) {
++ if (inet_addr_type(dev_net(skb->dst->dev), addr) != RTN_LOCAL) {
+ dopt->ts_needtime = 1;
+ soffset += 8;
+ }
+@@ -254,26 +248,22 @@ void ip_options_fragment(struct sk_buff * skb)
+ * If opt == NULL, then skb->data should point to IP header.
+ */
+
+-int ip_options_compile(struct ip_options * opt, struct sk_buff * skb)
++int ip_options_compile(struct net *net,
++ struct ip_options * opt, struct sk_buff * skb)
+ {
+ int l;
+ unsigned char * iph;
+ unsigned char * optptr;
+ int optlen;
+ unsigned char * pp_ptr = NULL;
+- struct rtable *rt = skb ? (struct rtable*)skb->dst : NULL;
+-
+- if (!opt) {
+- opt = &(IPCB(skb)->opt);
+- iph = skb_network_header(skb);
+- opt->optlen = ((struct iphdr *)iph)->ihl*4 - sizeof(struct iphdr);
+- optptr = iph + sizeof(struct iphdr);
+- opt->is_data = 0;
+- } else {
+- optptr = opt->is_data ? opt->__data :
+- (unsigned char *)&(ip_hdr(skb)[1]);
+- iph = optptr - sizeof(struct iphdr);
+- }
++ struct rtable *rt = NULL;
++
++ if (skb != NULL) {
++ rt = skb->rtable;
++ optptr = (unsigned char *)&(ip_hdr(skb)[1]);
++ } else
++ optptr = opt->__data;
++ iph = optptr - sizeof(struct iphdr);
+
+ for (l = opt->optlen; l > 0; ) {
+ switch (*optptr) {
+@@ -400,7 +390,7 @@ int ip_options_compile(struct ip_options * opt, struct sk_buff * skb)
+ {
+ __be32 addr;
+ memcpy(&addr, &optptr[optptr[2]-1], 4);
+- if (inet_addr_type(&init_net, addr) == RTN_UNICAST)
++ if (inet_addr_type(net, addr) == RTN_UNICAST)
+ break;
+ if (skb)
+ timeptr = (__be32*)&optptr[optptr[2]+3];
+@@ -416,10 +406,10 @@ int ip_options_compile(struct ip_options * opt, struct sk_buff * skb)
+ break;
+ }
+ if (timeptr) {
+- struct timeval tv;
++ struct timespec tv;
+ __be32 midtime;
+- do_gettimeofday(&tv);
+- midtime = htonl((tv.tv_sec % 86400) * 1000 + tv.tv_usec / 1000);
++ getnstimeofday(&tv);
++ midtime = htonl((tv.tv_sec % 86400) * MSEC_PER_SEC + tv.tv_nsec / NSEC_PER_MSEC);
+ memcpy(timeptr, &midtime, sizeof(__be32));
+ opt->is_changed = 1;
+ }
+@@ -517,14 +507,13 @@ static struct ip_options *ip_options_get_alloc(const int optlen)
+ GFP_KERNEL);
+ }
+
+-static int ip_options_get_finish(struct ip_options **optp,
++static int ip_options_get_finish(struct net *net, struct ip_options **optp,
+ struct ip_options *opt, int optlen)
+ {
+ while (optlen & 3)
+ opt->__data[optlen++] = IPOPT_END;
+ opt->optlen = optlen;
+- opt->is_data = 1;
+- if (optlen && ip_options_compile(opt, NULL)) {
++ if (optlen && ip_options_compile(net, opt, NULL)) {
+ kfree(opt);
+ return -EINVAL;
+ }
+@@ -533,7 +522,8 @@ static int ip_options_get_finish(struct ip_options **optp,
+ return 0;
+ }
+
+-int ip_options_get_from_user(struct ip_options **optp, unsigned char __user *data, int optlen)
++int ip_options_get_from_user(struct net *net, struct ip_options **optp,
++ unsigned char __user *data, int optlen)
+ {
+ struct ip_options *opt = ip_options_get_alloc(optlen);
+
+@@ -543,10 +533,11 @@ int ip_options_get_from_user(struct ip_options **optp, unsigned char __user *dat
+ kfree(opt);
+ return -EFAULT;
+ }
+- return ip_options_get_finish(optp, opt, optlen);
++ return ip_options_get_finish(net, optp, opt, optlen);
+ }
+
+-int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen)
++int ip_options_get(struct net *net, struct ip_options **optp,
++ unsigned char *data, int optlen)
+ {
+ struct ip_options *opt = ip_options_get_alloc(optlen);
+
+@@ -554,14 +545,14 @@ int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen)
+ return -ENOMEM;
+ if (optlen)
+ memcpy(opt->__data, data, optlen);
+- return ip_options_get_finish(optp, opt, optlen);
++ return ip_options_get_finish(net, optp, opt, optlen);
+ }
+
+ void ip_forward_options(struct sk_buff *skb)
+ {
+ struct ip_options * opt = &(IPCB(skb)->opt);
+ unsigned char * optptr;
+- struct rtable *rt = (struct rtable*)skb->dst;
++ struct rtable *rt = skb->rtable;
+ unsigned char *raw = skb_network_header(skb);
+
+ if (opt->rr_needaddr) {
+@@ -609,7 +600,7 @@ int ip_options_rcv_srr(struct sk_buff *skb)
+ __be32 nexthop;
+ struct iphdr *iph = ip_hdr(skb);
+ unsigned char *optptr = skb_network_header(skb) + opt->srr;
+- struct rtable *rt = (struct rtable*)skb->dst;
++ struct rtable *rt = skb->rtable;
+ struct rtable *rt2;
+ int err;
+
+@@ -634,13 +625,13 @@ int ip_options_rcv_srr(struct sk_buff *skb)
+ }
+ memcpy(&nexthop, &optptr[srrptr-1], 4);
+
+- rt = (struct rtable*)skb->dst;
+- skb->dst = NULL;
++ rt = skb->rtable;
++ skb->rtable = NULL;
+ err = ip_route_input(skb, nexthop, iph->saddr, iph->tos, skb->dev);
+- rt2 = (struct rtable*)skb->dst;
++ rt2 = skb->rtable;
+ if (err || (rt2->rt_type != RTN_UNICAST && rt2->rt_type != RTN_LOCAL)) {
+ ip_rt_put(rt2);
+- skb->dst = &rt->u.dst;
++ skb->rtable = rt;
+ return -EINVAL;
+ }
+ ip_rt_put(rt);
+diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
+index 341779e..0834926 100644
+--- a/net/ipv4/ip_output.c
++++ b/net/ipv4/ip_output.c
+@@ -142,7 +142,7 @@ int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
+ __be32 saddr, __be32 daddr, struct ip_options *opt)
+ {
+ struct inet_sock *inet = inet_sk(sk);
+- struct rtable *rt = (struct rtable *)skb->dst;
++ struct rtable *rt = skb->rtable;
+ struct iphdr *iph;
+
+ /* Build the IP header. */
+@@ -240,7 +240,7 @@ static int ip_finish_output(struct sk_buff *skb)
+ int ip_mc_output(struct sk_buff *skb)
+ {
+ struct sock *sk = skb->sk;
+- struct rtable *rt = (struct rtable*)skb->dst;
++ struct rtable *rt = skb->rtable;
+ struct net_device *dev = rt->u.dst.dev;
+
+ /*
+@@ -321,7 +321,7 @@ int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
+ /* Skip all of this if the packet is already routed,
+ * f.e. by something like SCTP.
+ */
+- rt = (struct rtable *) skb->dst;
++ rt = skb->rtable;
+ if (rt != NULL)
+ goto packet_routed;
+
+@@ -351,7 +351,7 @@ int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
+ * itself out.
+ */
+ security_sk_classify_flow(sk, &fl);
+- if (ip_route_output_flow(&init_net, &rt, &fl, sk, 0))
++ if (ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 0))
+ goto no_route;
+ }
+ sk_setup_caps(sk, &rt->u.dst);
+@@ -441,7 +441,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
+ unsigned int mtu, hlen, left, len, ll_rs, pad;
+ int offset;
+ __be16 not_last_frag;
+- struct rtable *rt = (struct rtable*)skb->dst;
++ struct rtable *rt = skb->rtable;
+ int err = 0;
+
+ dev = rt->u.dst.dev;
+@@ -825,7 +825,7 @@ int ip_append_data(struct sock *sk,
+ inet->cork.fragsize = mtu = inet->pmtudisc == IP_PMTUDISC_PROBE ?
+ rt->u.dst.dev->mtu :
+ dst_mtu(rt->u.dst.path);
+- inet->cork.rt = rt;
++ inet->cork.dst = &rt->u.dst;
+ inet->cork.length = 0;
+ sk->sk_sndmsg_page = NULL;
+ sk->sk_sndmsg_off = 0;
+@@ -834,7 +834,7 @@ int ip_append_data(struct sock *sk,
+ transhdrlen += exthdrlen;
+ }
+ } else {
+- rt = inet->cork.rt;
++ rt = (struct rtable *)inet->cork.dst;
+ if (inet->cork.flags & IPCORK_OPT)
+ opt = inet->cork.opt;
+
+@@ -1083,7 +1083,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page,
+ if (skb_queue_empty(&sk->sk_write_queue))
+ return -EINVAL;
+
+- rt = inet->cork.rt;
++ rt = (struct rtable *)inet->cork.dst;
+ if (inet->cork.flags & IPCORK_OPT)
+ opt = inet->cork.opt;
+
+@@ -1208,10 +1208,8 @@ static void ip_cork_release(struct inet_sock *inet)
+ inet->cork.flags &= ~IPCORK_OPT;
+ kfree(inet->cork.opt);
+ inet->cork.opt = NULL;
+- if (inet->cork.rt) {
+- ip_rt_put(inet->cork.rt);
+- inet->cork.rt = NULL;
+- }
++ dst_release(inet->cork.dst);
++ inet->cork.dst = NULL;
+ }
+
+ /*
+@@ -1224,7 +1222,7 @@ int ip_push_pending_frames(struct sock *sk)
+ struct sk_buff **tail_skb;
+ struct inet_sock *inet = inet_sk(sk);
+ struct ip_options *opt = NULL;
+- struct rtable *rt = inet->cork.rt;
++ struct rtable *rt = (struct rtable *)inet->cork.dst;
+ struct iphdr *iph;
+ __be16 df = 0;
+ __u8 ttl;
+@@ -1357,7 +1355,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
+ } replyopts;
+ struct ipcm_cookie ipc;
+ __be32 daddr;
+- struct rtable *rt = (struct rtable*)skb->dst;
++ struct rtable *rt = skb->rtable;
+
+ if (ip_options_echo(&replyopts.opt, skb))
+ return;
+@@ -1384,7 +1382,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
+ .dport = tcp_hdr(skb)->source } },
+ .proto = sk->sk_protocol };
+ security_skb_classify_flow(skb, &fl);
+- if (ip_route_output_key(sk->sk_net, &rt, &fl))
++ if (ip_route_output_key(sock_net(sk), &rt, &fl))
+ return;
+ }
+
+diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
+index c2921d0..d8adfd4 100644
+--- a/net/ipv4/ip_sockglue.c
++++ b/net/ipv4/ip_sockglue.c
+@@ -57,7 +57,7 @@
+ static void ip_cmsg_recv_pktinfo(struct msghdr *msg, struct sk_buff *skb)
+ {
+ struct in_pktinfo info;
+- struct rtable *rt = (struct rtable *)skb->dst;
++ struct rtable *rt = skb->rtable;
+
+ info.ipi_addr.s_addr = ip_hdr(skb)->daddr;
+ if (rt) {
+@@ -163,7 +163,7 @@ void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb)
+ ip_cmsg_recv_security(msg, skb);
+ }
+
+-int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc)
++int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc)
+ {
+ int err;
+ struct cmsghdr *cmsg;
+@@ -176,7 +176,7 @@ int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc)
+ switch (cmsg->cmsg_type) {
+ case IP_RETOPTS:
+ err = cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr));
+- err = ip_options_get(&ipc->opt, CMSG_DATA(cmsg), err < 40 ? err : 40);
++ err = ip_options_get(net, &ipc->opt, CMSG_DATA(cmsg), err < 40 ? err : 40);
+ if (err)
+ return err;
+ break;
+@@ -449,7 +449,8 @@ static int do_ip_setsockopt(struct sock *sk, int level,
+ struct ip_options * opt = NULL;
+ if (optlen > 40 || optlen < 0)
+ goto e_inval;
+- err = ip_options_get_from_user(&opt, optval, optlen);
++ err = ip_options_get_from_user(sock_net(sk), &opt,
++ optval, optlen);
+ if (err)
+ break;
+ if (inet->is_icsk) {
+@@ -589,13 +590,13 @@ static int do_ip_setsockopt(struct sock *sk, int level,
+ err = 0;
+ break;
+ }
+- dev = ip_dev_find(&init_net, mreq.imr_address.s_addr);
++ dev = ip_dev_find(sock_net(sk), mreq.imr_address.s_addr);
+ if (dev) {
+ mreq.imr_ifindex = dev->ifindex;
+ dev_put(dev);
+ }
+ } else
+- dev = __dev_get_by_index(&init_net, mreq.imr_ifindex);
++ dev = __dev_get_by_index(sock_net(sk), mreq.imr_ifindex);
+
+
+ err = -EADDRNOTAVAIL;
+diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
+index 58b60b2..a75807b 100644
+--- a/net/ipv4/ipcomp.c
++++ b/net/ipv4/ipcomp.c
+@@ -14,7 +14,6 @@
+ * - Adaptive compression.
+ */
+ #include <linux/module.h>
+-#include <asm/semaphore.h>
+ #include <linux/crypto.h>
+ #include <linux/err.h>
+ #include <linux/pfkeyv2.h>
+@@ -179,7 +178,7 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info)
+ spi, IPPROTO_COMP, AF_INET);
+ if (!x)
+ return;
+- NETDEBUG(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/%u.%u.%u.%u\n",
++ NETDEBUG(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/" NIPQUAD_FMT "\n",
+ spi, NIPQUAD(iph->daddr));
+ xfrm_state_put(x);
+ }
+diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
+index 4824fe8..0f42d1c 100644
+--- a/net/ipv4/ipconfig.c
++++ b/net/ipv4/ipconfig.c
+@@ -292,7 +292,7 @@ static int __init ic_dev_ioctl(unsigned int cmd, struct ifreq *arg)
+
+ mm_segment_t oldfs = get_fs();
+ set_fs(get_ds());
+- res = devinet_ioctl(cmd, (struct ifreq __user *) arg);
++ res = devinet_ioctl(&init_net, cmd, (struct ifreq __user *) arg);
+ set_fs(oldfs);
+ return res;
+ }
+@@ -376,7 +376,7 @@ static int __init ic_defaults(void)
+ */
+
+ if (!ic_host_name_set)
+- sprintf(init_utsname()->nodename, "%u.%u.%u.%u", NIPQUAD(ic_myaddr));
++ sprintf(init_utsname()->nodename, NIPQUAD_FMT, NIPQUAD(ic_myaddr));
+
+ if (root_server_addr == NONE)
+ root_server_addr = ic_servaddr;
+@@ -389,11 +389,11 @@ static int __init ic_defaults(void)
+ else if (IN_CLASSC(ntohl(ic_myaddr)))
+ ic_netmask = htonl(IN_CLASSC_NET);
+ else {
+- printk(KERN_ERR "IP-Config: Unable to guess netmask for address %u.%u.%u.%u\n",
++ printk(KERN_ERR "IP-Config: Unable to guess netmask for address " NIPQUAD_FMT "\n",
+ NIPQUAD(ic_myaddr));
+ return -1;
+ }
+- printk("IP-Config: Guessing netmask %u.%u.%u.%u\n", NIPQUAD(ic_netmask));
++ printk("IP-Config: Guessing netmask " NIPQUAD_FMT "\n", NIPQUAD(ic_netmask));
+ }
+
+ return 0;
+@@ -434,7 +434,7 @@ ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
+ unsigned char *sha, *tha; /* s for "source", t for "target" */
+ struct ic_device *d;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ goto drop;
+
+ if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+@@ -460,10 +460,7 @@ ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
+ if (rarp->ar_pro != htons(ETH_P_IP))
+ goto drop;
+
+- if (!pskb_may_pull(skb,
+- sizeof(struct arphdr) +
+- (2 * dev->addr_len) +
+- (2 * 4)))
++ if (!pskb_may_pull(skb, arp_hdr_len(dev)))
+ goto drop;
+
+ /* OK, it is all there and looks valid, process... */
+@@ -857,7 +854,7 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
+ struct ic_device *d;
+ int len, ext_len;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ goto drop;
+
+ /* Perform verifications before taking the lock. */
+@@ -984,9 +981,9 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
+ ic_myaddr = b->your_ip;
+ ic_servaddr = server_id;
+ #ifdef IPCONFIG_DEBUG
+- printk("DHCP: Offered address %u.%u.%u.%u",
++ printk("DHCP: Offered address " NIPQUAD_FMT,
+ NIPQUAD(ic_myaddr));
+- printk(" by server %u.%u.%u.%u\n",
++ printk(" by server " NIPQUAD_FMT "\n",
+ NIPQUAD(ic_servaddr));
+ #endif
+ /* The DHCP indicated server address takes
+@@ -1182,11 +1179,11 @@ static int __init ic_dynamic(void)
+ return -1;
+ }
+
+- printk("IP-Config: Got %s answer from %u.%u.%u.%u, ",
++ printk("IP-Config: Got %s answer from " NIPQUAD_FMT ", ",
+ ((ic_got_reply & IC_RARP) ? "RARP"
+ : (ic_proto_enabled & IC_USE_DHCP) ? "DHCP" : "BOOTP"),
+ NIPQUAD(ic_servaddr));
+- printk("my address is %u.%u.%u.%u\n", NIPQUAD(ic_myaddr));
++ printk("my address is " NIPQUAD_FMT "\n", NIPQUAD(ic_myaddr));
+
+ return 0;
+ }
+@@ -1212,12 +1209,12 @@ static int pnp_seq_show(struct seq_file *seq, void *v)
+ for (i = 0; i < CONF_NAMESERVERS_MAX; i++) {
+ if (ic_nameservers[i] != NONE)
+ seq_printf(seq,
+- "nameserver %u.%u.%u.%u\n",
++ "nameserver " NIPQUAD_FMT "\n",
+ NIPQUAD(ic_nameservers[i]));
+ }
+ if (ic_servaddr != NONE)
+ seq_printf(seq,
+- "bootserver %u.%u.%u.%u\n",
++ "bootserver " NIPQUAD_FMT "\n",
+ NIPQUAD(ic_servaddr));
+ return 0;
+ }
+@@ -1392,13 +1389,13 @@ static int __init ip_auto_config(void)
+ */
+ printk("IP-Config: Complete:");
+ printk("\n device=%s", ic_dev->name);
+- printk(", addr=%u.%u.%u.%u", NIPQUAD(ic_myaddr));
+- printk(", mask=%u.%u.%u.%u", NIPQUAD(ic_netmask));
+- printk(", gw=%u.%u.%u.%u", NIPQUAD(ic_gateway));
++ printk(", addr=" NIPQUAD_FMT, NIPQUAD(ic_myaddr));
++ printk(", mask=" NIPQUAD_FMT, NIPQUAD(ic_netmask));
++ printk(", gw=" NIPQUAD_FMT, NIPQUAD(ic_gateway));
+ printk(",\n host=%s, domain=%s, nis-domain=%s",
+ utsname()->nodename, ic_domain, utsname()->domainname);
+- printk(",\n bootserver=%u.%u.%u.%u", NIPQUAD(ic_servaddr));
+- printk(", rootserver=%u.%u.%u.%u", NIPQUAD(root_server_addr));
++ printk(",\n bootserver=" NIPQUAD_FMT, NIPQUAD(ic_servaddr));
++ printk(", rootserver=" NIPQUAD_FMT, NIPQUAD(root_server_addr));
+ printk(", rootpath=%s", root_server_path);
+ printk("\n");
+ #endif /* !SILENT */
+diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
+index dbaed69..149111f 100644
+--- a/net/ipv4/ipip.c
++++ b/net/ipv4/ipip.c
+@@ -115,49 +115,57 @@
+ #include <net/ipip.h>
+ #include <net/inet_ecn.h>
+ #include <net/xfrm.h>
++#include <net/net_namespace.h>
++#include <net/netns/generic.h>
+
+ #define HASH_SIZE 16
+ #define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF)
+
++static int ipip_net_id;
++struct ipip_net {
++ struct ip_tunnel *tunnels_r_l[HASH_SIZE];
++ struct ip_tunnel *tunnels_r[HASH_SIZE];
++ struct ip_tunnel *tunnels_l[HASH_SIZE];
++ struct ip_tunnel *tunnels_wc[1];
++ struct ip_tunnel **tunnels[4];
++
++ struct net_device *fb_tunnel_dev;
++};
++
+ static int ipip_fb_tunnel_init(struct net_device *dev);
+ static int ipip_tunnel_init(struct net_device *dev);
+ static void ipip_tunnel_setup(struct net_device *dev);
+
+-static struct net_device *ipip_fb_tunnel_dev;
+-
+-static struct ip_tunnel *tunnels_r_l[HASH_SIZE];
+-static struct ip_tunnel *tunnels_r[HASH_SIZE];
+-static struct ip_tunnel *tunnels_l[HASH_SIZE];
+-static struct ip_tunnel *tunnels_wc[1];
+-static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunnels_r_l };
+-
+ static DEFINE_RWLOCK(ipip_lock);
+
+-static struct ip_tunnel * ipip_tunnel_lookup(__be32 remote, __be32 local)
++static struct ip_tunnel * ipip_tunnel_lookup(struct net *net,
++ __be32 remote, __be32 local)
+ {
+ unsigned h0 = HASH(remote);
+ unsigned h1 = HASH(local);
+ struct ip_tunnel *t;
++ struct ipip_net *ipn = net_generic(net, ipip_net_id);
+
+- for (t = tunnels_r_l[h0^h1]; t; t = t->next) {
++ for (t = ipn->tunnels_r_l[h0^h1]; t; t = t->next) {
+ if (local == t->parms.iph.saddr &&
+ remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
+ return t;
+ }
+- for (t = tunnels_r[h0]; t; t = t->next) {
++ for (t = ipn->tunnels_r[h0]; t; t = t->next) {
+ if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
+ return t;
+ }
+- for (t = tunnels_l[h1]; t; t = t->next) {
++ for (t = ipn->tunnels_l[h1]; t; t = t->next) {
+ if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP))
+ return t;
+ }
+- if ((t = tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP))
++ if ((t = ipn->tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP))
+ return t;
+ return NULL;
+ }
+
+-static struct ip_tunnel **__ipip_bucket(struct ip_tunnel_parm *parms)
++static struct ip_tunnel **__ipip_bucket(struct ipip_net *ipn,
++ struct ip_tunnel_parm *parms)
+ {
+ __be32 remote = parms->iph.daddr;
+ __be32 local = parms->iph.saddr;
+@@ -172,19 +180,20 @@ static struct ip_tunnel **__ipip_bucket(struct ip_tunnel_parm *parms)
+ prio |= 1;
+ h ^= HASH(local);
+ }
+- return &tunnels[prio][h];
++ return &ipn->tunnels[prio][h];
+ }
+
+-static inline struct ip_tunnel **ipip_bucket(struct ip_tunnel *t)
++static inline struct ip_tunnel **ipip_bucket(struct ipip_net *ipn,
++ struct ip_tunnel *t)
+ {
+- return __ipip_bucket(&t->parms);
++ return __ipip_bucket(ipn, &t->parms);
+ }
+
+-static void ipip_tunnel_unlink(struct ip_tunnel *t)
++static void ipip_tunnel_unlink(struct ipip_net *ipn, struct ip_tunnel *t)
+ {
+ struct ip_tunnel **tp;
+
+- for (tp = ipip_bucket(t); *tp; tp = &(*tp)->next) {
++ for (tp = ipip_bucket(ipn, t); *tp; tp = &(*tp)->next) {
+ if (t == *tp) {
+ write_lock_bh(&ipip_lock);
+ *tp = t->next;
+@@ -194,9 +203,9 @@ static void ipip_tunnel_unlink(struct ip_tunnel *t)
+ }
+ }
+
+-static void ipip_tunnel_link(struct ip_tunnel *t)
++static void ipip_tunnel_link(struct ipip_net *ipn, struct ip_tunnel *t)
+ {
+- struct ip_tunnel **tp = ipip_bucket(t);
++ struct ip_tunnel **tp = ipip_bucket(ipn, t);
+
+ t->next = *tp;
+ write_lock_bh(&ipip_lock);
+@@ -204,15 +213,17 @@ static void ipip_tunnel_link(struct ip_tunnel *t)
+ write_unlock_bh(&ipip_lock);
+ }
+
+-static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int create)
++static struct ip_tunnel * ipip_tunnel_locate(struct net *net,
++ struct ip_tunnel_parm *parms, int create)
+ {
+ __be32 remote = parms->iph.daddr;
+ __be32 local = parms->iph.saddr;
+ struct ip_tunnel *t, **tp, *nt;
+ struct net_device *dev;
+ char name[IFNAMSIZ];
++ struct ipip_net *ipn = net_generic(net, ipip_net_id);
+
+- for (tp = __ipip_bucket(parms); (t = *tp) != NULL; tp = &t->next) {
++ for (tp = __ipip_bucket(ipn, parms); (t = *tp) != NULL; tp = &t->next) {
+ if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr)
+ return t;
+ }
+@@ -228,6 +239,8 @@ static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int c
+ if (dev == NULL)
+ return NULL;
+
++ dev_net_set(dev, net);
++
+ if (strchr(name, '%')) {
+ if (dev_alloc_name(dev, name) < 0)
+ goto failed_free;
+@@ -241,7 +254,7 @@ static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int c
+ goto failed_free;
+
+ dev_hold(dev);
+- ipip_tunnel_link(nt);
++ ipip_tunnel_link(ipn, nt);
+ return nt;
+
+ failed_free:
+@@ -251,12 +264,15 @@ failed_free:
+
+ static void ipip_tunnel_uninit(struct net_device *dev)
+ {
+- if (dev == ipip_fb_tunnel_dev) {
++ struct net *net = dev_net(dev);
++ struct ipip_net *ipn = net_generic(net, ipip_net_id);
++
++ if (dev == ipn->fb_tunnel_dev) {
+ write_lock_bh(&ipip_lock);
+- tunnels_wc[0] = NULL;
++ ipn->tunnels_wc[0] = NULL;
+ write_unlock_bh(&ipip_lock);
+ } else
+- ipip_tunnel_unlink(netdev_priv(dev));
++ ipip_tunnel_unlink(ipn, netdev_priv(dev));
+ dev_put(dev);
+ }
+
+@@ -305,7 +321,7 @@ static int ipip_err(struct sk_buff *skb, u32 info)
+ err = -ENOENT;
+
+ read_lock(&ipip_lock);
+- t = ipip_tunnel_lookup(iph->daddr, iph->saddr);
++ t = ipip_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr);
+ if (t == NULL || t->parms.iph.daddr == 0)
+ goto out;
+
+@@ -401,7 +417,7 @@ out:
+ fl.fl4_daddr = eiph->saddr;
+ fl.fl4_tos = RT_TOS(eiph->tos);
+ fl.proto = IPPROTO_IPIP;
+- if (ip_route_output_key(&init_net, &rt, &key)) {
++ if (ip_route_output_key(dev_net(skb->dev), &rt, &key)) {
+ kfree_skb(skb2);
+ return 0;
+ }
+@@ -414,7 +430,7 @@ out:
+ fl.fl4_daddr = eiph->daddr;
+ fl.fl4_src = eiph->saddr;
+ fl.fl4_tos = eiph->tos;
+- if (ip_route_output_key(&init_net, &rt, &fl) ||
++ if (ip_route_output_key(dev_net(skb->dev), &rt, &fl) ||
+ rt->u.dst.dev->type != ARPHRD_TUNNEL) {
+ ip_rt_put(rt);
+ kfree_skb(skb2);
+@@ -465,7 +481,8 @@ static int ipip_rcv(struct sk_buff *skb)
+ const struct iphdr *iph = ip_hdr(skb);
+
+ read_lock(&ipip_lock);
+- if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
++ if ((tunnel = ipip_tunnel_lookup(dev_net(skb->dev),
++ iph->saddr, iph->daddr)) != NULL) {
+ if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
+ read_unlock(&ipip_lock);
+ kfree_skb(skb);
+@@ -528,7 +545,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+
+ if (!dst) {
+ /* NBMA tunnel */
+- if ((rt = (struct rtable*)skb->dst) == NULL) {
++ if ((rt = skb->rtable) == NULL) {
+ tunnel->stat.tx_fifo_errors++;
+ goto tx_error;
+ }
+@@ -543,7 +560,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+ .saddr = tiph->saddr,
+ .tos = RT_TOS(tos) } },
+ .proto = IPPROTO_IPIP };
+- if (ip_route_output_key(&init_net, &rt, &fl)) {
++ if (ip_route_output_key(dev_net(dev), &rt, &fl)) {
+ tunnel->stat.tx_carrier_errors++;
+ goto tx_error_icmp;
+ }
+@@ -664,7 +681,7 @@ static void ipip_tunnel_bind_dev(struct net_device *dev)
+ .tos = RT_TOS(iph->tos) } },
+ .proto = IPPROTO_IPIP };
+ struct rtable *rt;
+- if (!ip_route_output_key(&init_net, &rt, &fl)) {
++ if (!ip_route_output_key(dev_net(dev), &rt, &fl)) {
+ tdev = rt->u.dst.dev;
+ ip_rt_put(rt);
+ }
+@@ -672,7 +689,7 @@ static void ipip_tunnel_bind_dev(struct net_device *dev)
+ }
+
+ if (!tdev && tunnel->parms.link)
+- tdev = __dev_get_by_index(&init_net, tunnel->parms.link);
++ tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link);
+
+ if (tdev) {
+ dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
+@@ -687,16 +704,18 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ int err = 0;
+ struct ip_tunnel_parm p;
+ struct ip_tunnel *t;
++ struct net *net = dev_net(dev);
++ struct ipip_net *ipn = net_generic(net, ipip_net_id);
+
+ switch (cmd) {
+ case SIOCGETTUNNEL:
+ t = NULL;
+- if (dev == ipip_fb_tunnel_dev) {
++ if (dev == ipn->fb_tunnel_dev) {
+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) {
+ err = -EFAULT;
+ break;
+ }
+- t = ipip_tunnel_locate(&p, 0);
++ t = ipip_tunnel_locate(net, &p, 0);
+ }
+ if (t == NULL)
+ t = netdev_priv(dev);
+@@ -722,9 +741,9 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ if (p.iph.ttl)
+ p.iph.frag_off |= htons(IP_DF);
+
+- t = ipip_tunnel_locate(&p, cmd == SIOCADDTUNNEL);
++ t = ipip_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL);
+
+- if (dev != ipip_fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
++ if (dev != ipn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
+ if (t != NULL) {
+ if (t->dev != dev) {
+ err = -EEXIST;
+@@ -737,12 +756,12 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ break;
+ }
+ t = netdev_priv(dev);
+- ipip_tunnel_unlink(t);
++ ipip_tunnel_unlink(ipn, t);
+ t->parms.iph.saddr = p.iph.saddr;
+ t->parms.iph.daddr = p.iph.daddr;
+ memcpy(dev->dev_addr, &p.iph.saddr, 4);
+ memcpy(dev->broadcast, &p.iph.daddr, 4);
+- ipip_tunnel_link(t);
++ ipip_tunnel_link(ipn, t);
+ netdev_state_change(dev);
+ }
+ }
+@@ -770,15 +789,15 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ if (!capable(CAP_NET_ADMIN))
+ goto done;
+
+- if (dev == ipip_fb_tunnel_dev) {
++ if (dev == ipn->fb_tunnel_dev) {
+ err = -EFAULT;
+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
+ goto done;
+ err = -ENOENT;
+- if ((t = ipip_tunnel_locate(&p, 0)) == NULL)
++ if ((t = ipip_tunnel_locate(net, &p, 0)) == NULL)
+ goto done;
+ err = -EPERM;
+- if (t->dev == ipip_fb_tunnel_dev)
++ if (t->dev == ipn->fb_tunnel_dev)
+ goto done;
+ dev = t->dev;
+ }
+@@ -822,6 +841,7 @@ static void ipip_tunnel_setup(struct net_device *dev)
+ dev->flags = IFF_NOARP;
+ dev->iflink = 0;
+ dev->addr_len = 4;
++ dev->features |= NETIF_F_NETNS_LOCAL;
+ }
+
+ static int ipip_tunnel_init(struct net_device *dev)
+@@ -841,10 +861,11 @@ static int ipip_tunnel_init(struct net_device *dev)
+ return 0;
+ }
+
+-static int __init ipip_fb_tunnel_init(struct net_device *dev)
++static int ipip_fb_tunnel_init(struct net_device *dev)
+ {
+ struct ip_tunnel *tunnel = netdev_priv(dev);
+ struct iphdr *iph = &tunnel->parms.iph;
++ struct ipip_net *ipn = net_generic(dev_net(dev), ipip_net_id);
+
+ tunnel->dev = dev;
+ strcpy(tunnel->parms.name, dev->name);
+@@ -854,7 +875,7 @@ static int __init ipip_fb_tunnel_init(struct net_device *dev)
+ iph->ihl = 5;
+
+ dev_hold(dev);
+- tunnels_wc[0] = tunnel;
++ ipn->tunnels_wc[0] = tunnel;
+ return 0;
+ }
+
+@@ -867,50 +888,98 @@ static struct xfrm_tunnel ipip_handler = {
+ static char banner[] __initdata =
+ KERN_INFO "IPv4 over IPv4 tunneling driver\n";
+
+-static int __init ipip_init(void)
++static void ipip_destroy_tunnels(struct ipip_net *ipn)
++{
++ int prio;
++
++ for (prio = 1; prio < 4; prio++) {
++ int h;
++ for (h = 0; h < HASH_SIZE; h++) {
++ struct ip_tunnel *t;
++ while ((t = ipn->tunnels[prio][h]) != NULL)
++ unregister_netdevice(t->dev);
++ }
++ }
++}
++
++static int ipip_init_net(struct net *net)
+ {
+ int err;
++ struct ipip_net *ipn;
+
+- printk(banner);
++ err = -ENOMEM;
++ ipn = kzalloc(sizeof(struct ipip_net), GFP_KERNEL);
++ if (ipn == NULL)
++ goto err_alloc;
+
+- if (xfrm4_tunnel_register(&ipip_handler, AF_INET)) {
+- printk(KERN_INFO "ipip init: can't register tunnel\n");
+- return -EAGAIN;
+- }
++ err = net_assign_generic(net, ipip_net_id, ipn);
++ if (err < 0)
++ goto err_assign;
+
+- ipip_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel),
++ ipn->tunnels[0] = ipn->tunnels_wc;
++ ipn->tunnels[1] = ipn->tunnels_l;
++ ipn->tunnels[2] = ipn->tunnels_r;
++ ipn->tunnels[3] = ipn->tunnels_r_l;
++
++ ipn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel),
+ "tunl0",
+ ipip_tunnel_setup);
+- if (!ipip_fb_tunnel_dev) {
++ if (!ipn->fb_tunnel_dev) {
+ err = -ENOMEM;
+- goto err1;
++ goto err_alloc_dev;
+ }
+
+- ipip_fb_tunnel_dev->init = ipip_fb_tunnel_init;
++ ipn->fb_tunnel_dev->init = ipip_fb_tunnel_init;
++ dev_net_set(ipn->fb_tunnel_dev, net);
++
++ if ((err = register_netdev(ipn->fb_tunnel_dev)))
++ goto err_reg_dev;
++
++ return 0;
+
+- if ((err = register_netdev(ipip_fb_tunnel_dev)))
+- goto err2;
+- out:
++err_reg_dev:
++ free_netdev(ipn->fb_tunnel_dev);
++err_alloc_dev:
++ /* nothing */
++err_assign:
++ kfree(ipn);
++err_alloc:
+ return err;
+- err2:
+- free_netdev(ipip_fb_tunnel_dev);
+- err1:
+- xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
+- goto out;
+ }
+
+-static void __exit ipip_destroy_tunnels(void)
++static void ipip_exit_net(struct net *net)
+ {
+- int prio;
++ struct ipip_net *ipn;
+
+- for (prio = 1; prio < 4; prio++) {
+- int h;
+- for (h = 0; h < HASH_SIZE; h++) {
+- struct ip_tunnel *t;
+- while ((t = tunnels[prio][h]) != NULL)
+- unregister_netdevice(t->dev);
+- }
++ ipn = net_generic(net, ipip_net_id);
++ rtnl_lock();
++ ipip_destroy_tunnels(ipn);
++ unregister_netdevice(ipn->fb_tunnel_dev);
++ rtnl_unlock();
++ kfree(ipn);
++}
++
++static struct pernet_operations ipip_net_ops = {
++ .init = ipip_init_net,
++ .exit = ipip_exit_net,
++};
++
++static int __init ipip_init(void)
++{
++ int err;
++
++ printk(banner);
++
++ if (xfrm4_tunnel_register(&ipip_handler, AF_INET)) {
++ printk(KERN_INFO "ipip init: can't register tunnel\n");
++ return -EAGAIN;
+ }
++
++ err = register_pernet_gen_device(&ipip_net_id, &ipip_net_ops);
++ if (err)
++ xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
++
++ return err;
+ }
+
+ static void __exit ipip_fini(void)
+@@ -918,10 +987,7 @@ static void __exit ipip_fini(void)
+ if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET))
+ printk(KERN_INFO "ipip close: can't deregister tunnel\n");
+
+- rtnl_lock();
+- ipip_destroy_tunnels();
+- unregister_netdevice(ipip_fb_tunnel_dev);
+- rtnl_unlock();
++ unregister_pernet_gen_device(ipip_net_id, &ipip_net_ops);
+ }
+
+ module_init(ipip_init);
+diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
+index a94f52c..11700a4 100644
+--- a/net/ipv4/ipmr.c
++++ b/net/ipv4/ipmr.c
+@@ -849,7 +849,7 @@ static void mrtsock_destruct(struct sock *sk)
+ {
+ rtnl_lock();
+ if (sk == mroute_socket) {
+- IPV4_DEVCONF_ALL(sk->sk_net, MC_FORWARDING)--;
++ IPV4_DEVCONF_ALL(sock_net(sk), MC_FORWARDING)--;
+
+ write_lock_bh(&mrt_lock);
+ mroute_socket=NULL;
+@@ -898,7 +898,7 @@ int ip_mroute_setsockopt(struct sock *sk,int optname,char __user *optval,int opt
+ mroute_socket=sk;
+ write_unlock_bh(&mrt_lock);
+
+- IPV4_DEVCONF_ALL(sk->sk_net, MC_FORWARDING)++;
++ IPV4_DEVCONF_ALL(sock_net(sk), MC_FORWARDING)++;
+ }
+ rtnl_unlock();
+ return ret;
+@@ -1089,7 +1089,7 @@ static int ipmr_device_event(struct notifier_block *this, unsigned long event, v
+ struct vif_device *v;
+ int ct;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ if (event != NETDEV_UNREGISTER)
+@@ -1283,7 +1283,7 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local
+ if (vif_table[vif].dev != skb->dev) {
+ int true_vifi;
+
+- if (((struct rtable*)skb->dst)->fl.iif == 0) {
++ if (skb->rtable->fl.iif == 0) {
+ /* It is our own packet, looped back.
+ Very complicated situation...
+
+@@ -1357,7 +1357,7 @@ dont_forward:
+ int ip_mr_input(struct sk_buff *skb)
+ {
+ struct mfc_cache *cache;
+- int local = ((struct rtable*)skb->dst)->rt_flags&RTCF_LOCAL;
++ int local = skb->rtable->rt_flags&RTCF_LOCAL;
+
+ /* Packet is looped back after forward, it should not be
+ forwarded second time, but still can be delivered locally.
+@@ -1594,7 +1594,7 @@ int ipmr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait)
+ {
+ int err;
+ struct mfc_cache *cache;
+- struct rtable *rt = (struct rtable*)skb->dst;
++ struct rtable *rt = skb->rtable;
+
+ read_lock(&mrt_lock);
+ cache = ipmr_cache_find(rt->rt_src, rt->rt_dst);
+diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c
+index 12dc0d6..620e40f 100644
+--- a/net/ipv4/ipvs/ip_vs_proto_tcp.c
++++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c
+@@ -550,7 +550,7 @@ tcp_app_conn_bind(struct ip_vs_conn *cp)
+
+ IP_VS_DBG(9, "%s: Binding conn %u.%u.%u.%u:%u->"
+ "%u.%u.%u.%u:%u to app %s on port %u\n",
+- __FUNCTION__,
++ __func__,
+ NIPQUAD(cp->caddr), ntohs(cp->cport),
+ NIPQUAD(cp->vaddr), ntohs(cp->vport),
+ inc->name, ntohs(inc->port));
+diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c
+index 1fa7b33..1caa290 100644
+--- a/net/ipv4/ipvs/ip_vs_proto_udp.c
++++ b/net/ipv4/ipvs/ip_vs_proto_udp.c
+@@ -344,7 +344,7 @@ static int udp_app_conn_bind(struct ip_vs_conn *cp)
+
+ IP_VS_DBG(9, "%s: Binding conn %u.%u.%u.%u:%u->"
+ "%u.%u.%u.%u:%u to app %s on port %u\n",
+- __FUNCTION__,
++ __func__,
+ NIPQUAD(cp->caddr), ntohs(cp->cport),
+ NIPQUAD(cp->vaddr), ntohs(cp->vport),
+ inc->name, ntohs(inc->port));
+diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c
+index 948378d..69c5666 100644
+--- a/net/ipv4/ipvs/ip_vs_sync.c
++++ b/net/ipv4/ipvs/ip_vs_sync.c
+@@ -916,7 +916,7 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid)
+ if (!tinfo)
+ return -ENOMEM;
+
+- IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, task_pid_nr(current));
++ IP_VS_DBG(7, "%s: pid %d\n", __func__, task_pid_nr(current));
+ IP_VS_DBG(7, "Each ip_vs_sync_conn entry need %Zd bytes\n",
+ sizeof(struct ip_vs_sync_conn));
+
+@@ -956,7 +956,7 @@ int stop_sync_thread(int state)
+ (state == IP_VS_STATE_BACKUP && !sync_backup_pid))
+ return -ESRCH;
+
+- IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, task_pid_nr(current));
++ IP_VS_DBG(7, "%s: pid %d\n", __func__, task_pid_nr(current));
+ IP_VS_INFO("stopping sync thread %d ...\n",
+ (state == IP_VS_STATE_MASTER) ?
+ sync_master_pid : sync_backup_pid);
+diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
+index 9a904c6..f8edacd 100644
+--- a/net/ipv4/netfilter.c
++++ b/net/ipv4/netfilter.c
+@@ -182,21 +182,44 @@ __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
+ }
+ return csum;
+ }
+-
+ EXPORT_SYMBOL(nf_ip_checksum);
+
++static __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook,
++ unsigned int dataoff, unsigned int len,
++ u_int8_t protocol)
++{
++ const struct iphdr *iph = ip_hdr(skb);
++ __sum16 csum = 0;
++
++ switch (skb->ip_summed) {
++ case CHECKSUM_COMPLETE:
++ if (len == skb->len - dataoff)
++ return nf_ip_checksum(skb, hook, dataoff, protocol);
++ /* fall through */
++ case CHECKSUM_NONE:
++ skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr, protocol,
++ skb->len - dataoff, 0);
++ skb->ip_summed = CHECKSUM_NONE;
++ csum = __skb_checksum_complete_head(skb, dataoff + len);
++ if (!csum)
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++ }
++ return csum;
++}
++
+ static int nf_ip_route(struct dst_entry **dst, struct flowi *fl)
+ {
+ return ip_route_output_key(&init_net, (struct rtable **)dst, fl);
+ }
+
+ static const struct nf_afinfo nf_ip_afinfo = {
+- .family = AF_INET,
+- .checksum = nf_ip_checksum,
+- .route = nf_ip_route,
+- .saveroute = nf_ip_saveroute,
+- .reroute = nf_ip_reroute,
+- .route_key_size = sizeof(struct ip_rt_info),
++ .family = AF_INET,
++ .checksum = nf_ip_checksum,
++ .checksum_partial = nf_ip_checksum_partial,
++ .route = nf_ip_route,
++ .saveroute = nf_ip_saveroute,
++ .reroute = nf_ip_reroute,
++ .route_key_size = sizeof(struct ip_rt_info),
+ };
+
+ static int ipv4_netfilter_init(void)
+diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
+index 9a077cb..2767841 100644
+--- a/net/ipv4/netfilter/Kconfig
++++ b/net/ipv4/netfilter/Kconfig
+@@ -241,10 +241,26 @@ config NF_NAT_SNMP_BASIC
+ # <expr> '&&' <expr> (6)
+ #
+ # (6) Returns the result of min(/expr/, /expr/).
++config NF_NAT_PROTO_DCCP
++ tristate
++ depends on NF_NAT && NF_CT_PROTO_DCCP
++ default NF_NAT && NF_CT_PROTO_DCCP
++
+ config NF_NAT_PROTO_GRE
+ tristate
+ depends on NF_NAT && NF_CT_PROTO_GRE
+
++config NF_NAT_PROTO_UDPLITE
++ tristate
++ depends on NF_NAT && NF_CT_PROTO_UDPLITE
++ default NF_NAT && NF_CT_PROTO_UDPLITE
++
++config NF_NAT_PROTO_SCTP
++ tristate
++ default NF_NAT && NF_CT_PROTO_SCTP
++ depends on NF_NAT && NF_CT_PROTO_SCTP
++ select LIBCRC32C
++
+ config NF_NAT_FTP
+ tristate
+ depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
+diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
+index 0c7dc78..d9b92fb 100644
+--- a/net/ipv4/netfilter/Makefile
++++ b/net/ipv4/netfilter/Makefile
+@@ -10,7 +10,7 @@ nf_conntrack_ipv4-objs += nf_conntrack_l3proto_ipv4_compat.o
+ endif
+ endif
+
+-nf_nat-objs := nf_nat_core.o nf_nat_helper.o nf_nat_proto_unknown.o nf_nat_proto_tcp.o nf_nat_proto_udp.o nf_nat_proto_icmp.o
++nf_nat-objs := nf_nat_core.o nf_nat_helper.o nf_nat_proto_unknown.o nf_nat_proto_common.o nf_nat_proto_tcp.o nf_nat_proto_udp.o nf_nat_proto_icmp.o
+ iptable_nat-objs := nf_nat_rule.o nf_nat_standalone.o
+
+ # connection tracking
+@@ -29,7 +29,10 @@ obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o
+ obj-$(CONFIG_NF_NAT_TFTP) += nf_nat_tftp.o
+
+ # NAT protocols (nf_nat)
++obj-$(CONFIG_NF_NAT_PROTO_DCCP) += nf_nat_proto_dccp.o
+ obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o
++obj-$(CONFIG_NF_NAT_PROTO_UDPLITE) += nf_nat_proto_udplite.o
++obj-$(CONFIG_NF_NAT_PROTO_SCTP) += nf_nat_proto_sctp.o
+
+ # generic IP tables
+ obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
+diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
+index a7591ce..03e83a6 100644
+--- a/net/ipv4/netfilter/arp_tables.c
++++ b/net/ipv4/netfilter/arp_tables.c
+@@ -52,14 +52,14 @@ MODULE_DESCRIPTION("arptables core");
+ do { \
+ if (!(x)) \
+ printk("ARP_NF_ASSERT: %s:%s:%u\n", \
+- __FUNCTION__, __FILE__, __LINE__); \
++ __func__, __FILE__, __LINE__); \
+ } while(0)
+ #else
+ #define ARP_NF_ASSERT(x)
+ #endif
+
+ static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap,
+- char *hdr_addr, int len)
++ const char *hdr_addr, int len)
+ {
+ int i, ret;
+
+@@ -80,8 +80,8 @@ static inline int arp_packet_match(const struct arphdr *arphdr,
+ const char *outdev,
+ const struct arpt_arp *arpinfo)
+ {
+- char *arpptr = (char *)(arphdr + 1);
+- char *src_devaddr, *tgt_devaddr;
++ const char *arpptr = (char *)(arphdr + 1);
++ const char *src_devaddr, *tgt_devaddr;
+ __be32 src_ipaddr, tgt_ipaddr;
+ int i, ret;
+
+@@ -222,21 +222,18 @@ unsigned int arpt_do_table(struct sk_buff *skb,
+ unsigned int hook,
+ const struct net_device *in,
+ const struct net_device *out,
+- struct arpt_table *table)
++ struct xt_table *table)
+ {
+ static const char nulldevname[IFNAMSIZ];
+ unsigned int verdict = NF_DROP;
+- struct arphdr *arp;
++ const struct arphdr *arp;
+ bool hotdrop = false;
+ struct arpt_entry *e, *back;
+ const char *indev, *outdev;
+ void *table_base;
+- struct xt_table_info *private;
++ const struct xt_table_info *private;
+
+- /* ARP header, plus 2 device addresses, plus 2 IP addresses. */
+- if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
+- (2 * skb->dev->addr_len) +
+- (2 * sizeof(u32)))))
++ if (!pskb_may_pull(skb, arp_hdr_len(skb->dev)))
+ return NF_DROP;
+
+ indev = in ? in->name : nulldevname;
+@@ -355,7 +352,7 @@ static int mark_source_chains(struct xt_table_info *newinfo,
+ e->counters.pcnt = pos;
+
+ for (;;) {
+- struct arpt_standard_target *t
++ const struct arpt_standard_target *t
+ = (void *)arpt_get_target(e);
+ int visited = e->comefrom & (1 << hook);
+
+@@ -440,7 +437,7 @@ static int mark_source_chains(struct xt_table_info *newinfo,
+
+ static inline int check_entry(struct arpt_entry *e, const char *name)
+ {
+- struct arpt_entry_target *t;
++ const struct arpt_entry_target *t;
+
+ if (!arp_checkentry(&e->arp)) {
+ duprintf("arp_tables: arp check failed %p %s.\n", e, name);
+@@ -460,7 +457,7 @@ static inline int check_entry(struct arpt_entry *e, const char *name)
+ static inline int check_target(struct arpt_entry *e, const char *name)
+ {
+ struct arpt_entry_target *t;
+- struct arpt_target *target;
++ struct xt_target *target;
+ int ret;
+
+ t = arpt_get_target(e);
+@@ -483,7 +480,7 @@ find_check_entry(struct arpt_entry *e, const char *name, unsigned int size,
+ unsigned int *i)
+ {
+ struct arpt_entry_target *t;
+- struct arpt_target *target;
++ struct xt_target *target;
+ int ret;
+
+ ret = check_entry(e, name);
+@@ -709,11 +706,11 @@ static void get_counters(const struct xt_table_info *t,
+ }
+ }
+
+-static inline struct xt_counters *alloc_counters(struct arpt_table *table)
++static inline struct xt_counters *alloc_counters(struct xt_table *table)
+ {
+ unsigned int countersize;
+ struct xt_counters *counters;
+- struct xt_table_info *private = table->private;
++ const struct xt_table_info *private = table->private;
+
+ /* We need atomic snapshot of counters: rest doesn't change
+ * (other than comefrom, which userspace doesn't care
+@@ -734,7 +731,7 @@ static inline struct xt_counters *alloc_counters(struct arpt_table *table)
+ }
+
+ static int copy_entries_to_user(unsigned int total_size,
+- struct arpt_table *table,
++ struct xt_table *table,
+ void __user *userptr)
+ {
+ unsigned int off, num;
+@@ -854,7 +851,7 @@ static int compat_table_info(const struct xt_table_info *info,
+ static int get_info(struct net *net, void __user *user, int *len, int compat)
+ {
+ char name[ARPT_TABLE_MAXNAMELEN];
+- struct arpt_table *t;
++ struct xt_table *t;
+ int ret;
+
+ if (*len != sizeof(struct arpt_getinfo)) {
+@@ -875,7 +872,7 @@ static int get_info(struct net *net, void __user *user, int *len, int compat)
+ "arptable_%s", name);
+ if (t && !IS_ERR(t)) {
+ struct arpt_getinfo info;
+- struct xt_table_info *private = t->private;
++ const struct xt_table_info *private = t->private;
+
+ #ifdef CONFIG_COMPAT
+ if (compat) {
+@@ -914,7 +911,7 @@ static int get_entries(struct net *net, struct arpt_get_entries __user *uptr,
+ {
+ int ret;
+ struct arpt_get_entries get;
+- struct arpt_table *t;
++ struct xt_table *t;
+
+ if (*len < sizeof(get)) {
+ duprintf("get_entries: %u < %Zu\n", *len, sizeof(get));
+@@ -930,7 +927,8 @@ static int get_entries(struct net *net, struct arpt_get_entries __user *uptr,
+
+ t = xt_find_table_lock(net, NF_ARP, get.name);
+ if (t && !IS_ERR(t)) {
+- struct xt_table_info *private = t->private;
++ const struct xt_table_info *private = t->private;
++
+ duprintf("t->private->number = %u\n",
+ private->number);
+ if (get.size == private->size)
+@@ -939,7 +937,7 @@ static int get_entries(struct net *net, struct arpt_get_entries __user *uptr,
+ else {
+ duprintf("get_entries: I've got %u not %u!\n",
+ private->size, get.size);
+- ret = -EINVAL;
++ ret = -EAGAIN;
+ }
+ module_put(t->me);
+ xt_table_unlock(t);
+@@ -956,7 +954,7 @@ static int __do_replace(struct net *net, const char *name,
+ void __user *counters_ptr)
+ {
+ int ret;
+- struct arpt_table *t;
++ struct xt_table *t;
+ struct xt_table_info *oldinfo;
+ struct xt_counters *counters;
+ void *loc_cpu_old_entry;
+@@ -1090,11 +1088,11 @@ static int do_add_counters(struct net *net, void __user *user, unsigned int len,
+ struct xt_counters_info tmp;
+ struct xt_counters *paddc;
+ unsigned int num_counters;
+- char *name;
++ const char *name;
+ int size;
+ void *ptmp;
+- struct arpt_table *t;
+- struct xt_table_info *private;
++ struct xt_table *t;
++ const struct xt_table_info *private;
+ int ret = 0;
+ void *loc_cpu_entry;
+ #ifdef CONFIG_COMPAT
+@@ -1499,11 +1497,11 @@ static int compat_do_arpt_set_ctl(struct sock *sk, int cmd, void __user *user,
+
+ switch (cmd) {
+ case ARPT_SO_SET_REPLACE:
+- ret = compat_do_replace(sk->sk_net, user, len);
++ ret = compat_do_replace(sock_net(sk), user, len);
+ break;
+
+ case ARPT_SO_SET_ADD_COUNTERS:
+- ret = do_add_counters(sk->sk_net, user, len, 1);
++ ret = do_add_counters(sock_net(sk), user, len, 1);
+ break;
+
+ default:
+@@ -1557,11 +1555,11 @@ out:
+ }
+
+ static int compat_copy_entries_to_user(unsigned int total_size,
+- struct arpt_table *table,
++ struct xt_table *table,
+ void __user *userptr)
+ {
+ struct xt_counters *counters;
+- struct xt_table_info *private = table->private;
++ const struct xt_table_info *private = table->private;
+ void __user *pos;
+ unsigned int size;
+ int ret = 0;
+@@ -1595,7 +1593,7 @@ static int compat_get_entries(struct net *net,
+ {
+ int ret;
+ struct compat_arpt_get_entries get;
+- struct arpt_table *t;
++ struct xt_table *t;
+
+ if (*len < sizeof(get)) {
+ duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
+@@ -1612,7 +1610,7 @@ static int compat_get_entries(struct net *net,
+ xt_compat_lock(NF_ARP);
+ t = xt_find_table_lock(net, NF_ARP, get.name);
+ if (t && !IS_ERR(t)) {
+- struct xt_table_info *private = t->private;
++ const struct xt_table_info *private = t->private;
+ struct xt_table_info info;
+
+ duprintf("t->private->number = %u\n", private->number);
+@@ -1623,7 +1621,7 @@ static int compat_get_entries(struct net *net,
+ } else if (!ret) {
+ duprintf("compat_get_entries: I've got %u not %u!\n",
+ private->size, get.size);
+- ret = -EINVAL;
++ ret = -EAGAIN;
+ }
+ xt_compat_flush_offsets(NF_ARP);
+ module_put(t->me);
+@@ -1647,10 +1645,10 @@ static int compat_do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user,
+
+ switch (cmd) {
+ case ARPT_SO_GET_INFO:
+- ret = get_info(sk->sk_net, user, len, 1);
++ ret = get_info(sock_net(sk), user, len, 1);
+ break;
+ case ARPT_SO_GET_ENTRIES:
+- ret = compat_get_entries(sk->sk_net, user, len);
++ ret = compat_get_entries(sock_net(sk), user, len);
+ break;
+ default:
+ ret = do_arpt_get_ctl(sk, cmd, user, len);
+@@ -1668,11 +1666,11 @@ static int do_arpt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned
+
+ switch (cmd) {
+ case ARPT_SO_SET_REPLACE:
+- ret = do_replace(sk->sk_net, user, len);
++ ret = do_replace(sock_net(sk), user, len);
+ break;
+
+ case ARPT_SO_SET_ADD_COUNTERS:
+- ret = do_add_counters(sk->sk_net, user, len, 0);
++ ret = do_add_counters(sock_net(sk), user, len, 0);
+ break;
+
+ default:
+@@ -1692,11 +1690,11 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
+
+ switch (cmd) {
+ case ARPT_SO_GET_INFO:
+- ret = get_info(sk->sk_net, user, len, 0);
++ ret = get_info(sock_net(sk), user, len, 0);
+ break;
+
+ case ARPT_SO_GET_ENTRIES:
+- ret = get_entries(sk->sk_net, user, len);
++ ret = get_entries(sock_net(sk), user, len);
+ break;
+
+ case ARPT_SO_GET_REVISION_TARGET: {
+@@ -1725,9 +1723,8 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
+ return ret;
+ }
+
+-struct arpt_table *arpt_register_table(struct net *net,
+- struct arpt_table *table,
+- const struct arpt_replace *repl)
++struct xt_table *arpt_register_table(struct net *net, struct xt_table *table,
++ const struct arpt_replace *repl)
+ {
+ int ret;
+ struct xt_table_info *newinfo;
+@@ -1769,7 +1766,7 @@ out:
+ return ERR_PTR(ret);
+ }
+
+-void arpt_unregister_table(struct arpt_table *table)
++void arpt_unregister_table(struct xt_table *table)
+ {
+ struct xt_table_info *private;
+ void *loc_cpu_entry;
+@@ -1787,7 +1784,7 @@ void arpt_unregister_table(struct arpt_table *table)
+ }
+
+ /* The built-in targets: standard (NULL) and error. */
+-static struct arpt_target arpt_standard_target __read_mostly = {
++static struct xt_target arpt_standard_target __read_mostly = {
+ .name = ARPT_STANDARD_TARGET,
+ .targetsize = sizeof(int),
+ .family = NF_ARP,
+@@ -1798,7 +1795,7 @@ static struct arpt_target arpt_standard_target __read_mostly = {
+ #endif
+ };
+
+-static struct arpt_target arpt_error_target __read_mostly = {
++static struct xt_target arpt_error_target __read_mostly = {
+ .name = ARPT_ERROR_TARGET,
+ .target = arpt_error,
+ .targetsize = ARPT_FUNCTION_MAXNAMELEN,
+diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
+index 3f4222b..a385959 100644
+--- a/net/ipv4/netfilter/arpt_mangle.c
++++ b/net/ipv4/netfilter/arpt_mangle.c
+@@ -15,7 +15,7 @@ target(struct sk_buff *skb,
+ const void *targinfo)
+ {
+ const struct arpt_mangle *mangle = targinfo;
+- struct arphdr *arp;
++ const struct arphdr *arp;
+ unsigned char *arpptr;
+ int pln, hln;
+
+@@ -73,8 +73,9 @@ checkentry(const char *tablename, const void *e, const struct xt_target *target,
+ return true;
+ }
+
+-static struct arpt_target arpt_mangle_reg __read_mostly = {
++static struct xt_target arpt_mangle_reg __read_mostly = {
+ .name = "mangle",
++ .family = NF_ARP,
+ .target = target,
+ .targetsize = sizeof(struct arpt_mangle),
+ .checkentry = checkentry,
+@@ -83,15 +84,12 @@ static struct arpt_target arpt_mangle_reg __read_mostly = {
+
+ static int __init arpt_mangle_init(void)
+ {
+- if (arpt_register_target(&arpt_mangle_reg))
+- return -EINVAL;
+-
+- return 0;
++ return xt_register_target(&arpt_mangle_reg);
+ }
+
+ static void __exit arpt_mangle_fini(void)
+ {
+- arpt_unregister_target(&arpt_mangle_reg);
++ xt_unregister_target(&arpt_mangle_reg);
+ }
+
+ module_init(arpt_mangle_init);
+diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
+index 4e9c496..3be4d07 100644
+--- a/net/ipv4/netfilter/arptable_filter.c
++++ b/net/ipv4/netfilter/arptable_filter.c
+@@ -45,10 +45,10 @@ static struct
+ .term = ARPT_ERROR_INIT,
+ };
+
+-static struct arpt_table packet_filter = {
++static struct xt_table packet_filter = {
+ .name = "filter",
+ .valid_hooks = FILTER_VALID_HOOKS,
+- .lock = RW_LOCK_UNLOCKED,
++ .lock = __RW_LOCK_UNLOCKED(packet_filter.lock),
+ .private = NULL,
+ .me = THIS_MODULE,
+ .af = NF_ARP,
+@@ -70,18 +70,21 @@ static struct nf_hook_ops arpt_ops[] __read_mostly = {
+ .owner = THIS_MODULE,
+ .pf = NF_ARP,
+ .hooknum = NF_ARP_IN,
++ .priority = NF_IP_PRI_FILTER,
+ },
+ {
+ .hook = arpt_hook,
+ .owner = THIS_MODULE,
+ .pf = NF_ARP,
+ .hooknum = NF_ARP_OUT,
++ .priority = NF_IP_PRI_FILTER,
+ },
+ {
+ .hook = arpt_hook,
+ .owner = THIS_MODULE,
+ .pf = NF_ARP,
+ .hooknum = NF_ARP_FORWARD,
++ .priority = NF_IP_PRI_FILTER,
+ },
+ };
+
+diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
+index 4dc1628..719be29 100644
+--- a/net/ipv4/netfilter/ip_queue.c
++++ b/net/ipv4/netfilter/ip_queue.c
+@@ -481,7 +481,7 @@ ipq_rcv_dev_event(struct notifier_block *this,
+ {
+ struct net_device *dev = ptr;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ /* Drop any packets associated with the downed device */
+diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
+index 600737f..4e7c719 100644
+--- a/net/ipv4/netfilter/ip_tables.c
++++ b/net/ipv4/netfilter/ip_tables.c
+@@ -53,7 +53,7 @@ MODULE_DESCRIPTION("IPv4 packet filter");
+ do { \
+ if (!(x)) \
+ printk("IP_NF_ASSERT: %s:%s:%u\n", \
+- __FUNCTION__, __FILE__, __LINE__); \
++ __func__, __FILE__, __LINE__); \
+ } while(0)
+ #else
+ #define IP_NF_ASSERT(x)
+@@ -296,7 +296,7 @@ static void trace_packet(struct sk_buff *skb,
+ struct ipt_entry *e)
+ {
+ void *table_base;
+- struct ipt_entry *root;
++ const struct ipt_entry *root;
+ char *hookname, *chainname, *comment;
+ unsigned int rulenum = 0;
+
+@@ -327,7 +327,7 @@ ipt_do_table(struct sk_buff *skb,
+ {
+ static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
+ u_int16_t offset;
+- struct iphdr *ip;
++ const struct iphdr *ip;
+ u_int16_t datalen;
+ bool hotdrop = false;
+ /* Initializing verdict to NF_DROP keeps gcc happy. */
+@@ -926,7 +926,7 @@ static struct xt_counters * alloc_counters(struct xt_table *table)
+ {
+ unsigned int countersize;
+ struct xt_counters *counters;
+- struct xt_table_info *private = table->private;
++ const struct xt_table_info *private = table->private;
+
+ /* We need atomic snapshot of counters: rest doesn't change
+ (other than comefrom, which userspace doesn't care
+@@ -953,9 +953,9 @@ copy_entries_to_user(unsigned int total_size,
+ unsigned int off, num;
+ struct ipt_entry *e;
+ struct xt_counters *counters;
+- struct xt_table_info *private = table->private;
++ const struct xt_table_info *private = table->private;
+ int ret = 0;
+- void *loc_cpu_entry;
++ const void *loc_cpu_entry;
+
+ counters = alloc_counters(table);
+ if (IS_ERR(counters))
+@@ -975,8 +975,8 @@ copy_entries_to_user(unsigned int total_size,
+ /* ... then go back and fix counters and names */
+ for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
+ unsigned int i;
+- struct ipt_entry_match *m;
+- struct ipt_entry_target *t;
++ const struct ipt_entry_match *m;
++ const struct ipt_entry_target *t;
+
+ e = (struct ipt_entry *)(loc_cpu_entry + off);
+ if (copy_to_user(userptr + off
+@@ -1116,7 +1116,7 @@ static int get_info(struct net *net, void __user *user, int *len, int compat)
+ "iptable_%s", name);
+ if (t && !IS_ERR(t)) {
+ struct ipt_getinfo info;
+- struct xt_table_info *private = t->private;
++ const struct xt_table_info *private = t->private;
+
+ #ifdef CONFIG_COMPAT
+ if (compat) {
+@@ -1172,7 +1172,7 @@ get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len)
+
+ t = xt_find_table_lock(net, AF_INET, get.name);
+ if (t && !IS_ERR(t)) {
+- struct xt_table_info *private = t->private;
++ const struct xt_table_info *private = t->private;
+ duprintf("t->private->number = %u\n", private->number);
+ if (get.size == private->size)
+ ret = copy_entries_to_user(private->size,
+@@ -1180,7 +1180,7 @@ get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len)
+ else {
+ duprintf("get_entries: I've got %u not %u!\n",
+ private->size, get.size);
+- ret = -EINVAL;
++ ret = -EAGAIN;
+ }
+ module_put(t->me);
+ xt_table_unlock(t);
+@@ -1337,11 +1337,11 @@ do_add_counters(struct net *net, void __user *user, unsigned int len, int compat
+ struct xt_counters_info tmp;
+ struct xt_counters *paddc;
+ unsigned int num_counters;
+- char *name;
++ const char *name;
+ int size;
+ void *ptmp;
+ struct xt_table *t;
+- struct xt_table_info *private;
++ const struct xt_table_info *private;
+ int ret = 0;
+ void *loc_cpu_entry;
+ #ifdef CONFIG_COMPAT
+@@ -1852,11 +1852,11 @@ compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
+
+ switch (cmd) {
+ case IPT_SO_SET_REPLACE:
+- ret = compat_do_replace(sk->sk_net, user, len);
++ ret = compat_do_replace(sock_net(sk), user, len);
+ break;
+
+ case IPT_SO_SET_ADD_COUNTERS:
+- ret = do_add_counters(sk->sk_net, user, len, 1);
++ ret = do_add_counters(sock_net(sk), user, len, 1);
+ break;
+
+ default:
+@@ -1878,11 +1878,11 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
+ void __user *userptr)
+ {
+ struct xt_counters *counters;
+- struct xt_table_info *private = table->private;
++ const struct xt_table_info *private = table->private;
+ void __user *pos;
+ unsigned int size;
+ int ret = 0;
+- void *loc_cpu_entry;
++ const void *loc_cpu_entry;
+ unsigned int i = 0;
+
+ counters = alloc_counters(table);
+@@ -1929,7 +1929,7 @@ compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
+ xt_compat_lock(AF_INET);
+ t = xt_find_table_lock(net, AF_INET, get.name);
+ if (t && !IS_ERR(t)) {
+- struct xt_table_info *private = t->private;
++ const struct xt_table_info *private = t->private;
+ struct xt_table_info info;
+ duprintf("t->private->number = %u\n", private->number);
+ ret = compat_table_info(private, &info);
+@@ -1939,7 +1939,7 @@ compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
+ } else if (!ret) {
+ duprintf("compat_get_entries: I've got %u not %u!\n",
+ private->size, get.size);
+- ret = -EINVAL;
++ ret = -EAGAIN;
+ }
+ xt_compat_flush_offsets(AF_INET);
+ module_put(t->me);
+@@ -1963,10 +1963,10 @@ compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
+
+ switch (cmd) {
+ case IPT_SO_GET_INFO:
+- ret = get_info(sk->sk_net, user, len, 1);
++ ret = get_info(sock_net(sk), user, len, 1);
+ break;
+ case IPT_SO_GET_ENTRIES:
+- ret = compat_get_entries(sk->sk_net, user, len);
++ ret = compat_get_entries(sock_net(sk), user, len);
+ break;
+ default:
+ ret = do_ipt_get_ctl(sk, cmd, user, len);
+@@ -1985,11 +1985,11 @@ do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
+
+ switch (cmd) {
+ case IPT_SO_SET_REPLACE:
+- ret = do_replace(sk->sk_net, user, len);
++ ret = do_replace(sock_net(sk), user, len);
+ break;
+
+ case IPT_SO_SET_ADD_COUNTERS:
+- ret = do_add_counters(sk->sk_net, user, len, 0);
++ ret = do_add_counters(sock_net(sk), user, len, 0);
+ break;
+
+ default:
+@@ -2010,11 +2010,11 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
+
+ switch (cmd) {
+ case IPT_SO_GET_INFO:
+- ret = get_info(sk->sk_net, user, len, 0);
++ ret = get_info(sock_net(sk), user, len, 0);
+ break;
+
+ case IPT_SO_GET_ENTRIES:
+- ret = get_entries(sk->sk_net, user, len);
++ ret = get_entries(sock_net(sk), user, len);
+ break;
+
+ case IPT_SO_GET_REVISION_MATCH:
+@@ -2130,7 +2130,8 @@ icmp_match(const struct sk_buff *skb,
+ unsigned int protoff,
+ bool *hotdrop)
+ {
+- struct icmphdr _icmph, *ic;
++ const struct icmphdr *ic;
++ struct icmphdr _icmph;
+ const struct ipt_icmp *icmpinfo = matchinfo;
+
+ /* Must not be a fragment. */
+diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
+index a12dd32..22d8e7c 100644
+--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
++++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
+@@ -144,7 +144,7 @@ clusterip_config_init_nodelist(struct clusterip_config *c,
+ }
+
+ static struct clusterip_config *
+-clusterip_config_init(struct ipt_clusterip_tgt_info *i, __be32 ip,
++clusterip_config_init(const struct ipt_clusterip_tgt_info *i, __be32 ip,
+ struct net_device *dev)
+ {
+ struct clusterip_config *c;
+@@ -333,7 +333,7 @@ clusterip_tg(struct sk_buff *skb, const struct net_device *in,
+ }
+
+ #ifdef DEBUG
+- DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
++ nf_ct_dump_tuple_ip(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+ #endif
+ pr_debug("hash=%u ct_hash=%u ", hash, ct->mark);
+ if (!clusterip_responsible(cipinfo->config, hash)) {
+@@ -418,7 +418,7 @@ clusterip_tg_check(const char *tablename, const void *e_void,
+ /* drop reference count of cluster config when rule is deleted */
+ static void clusterip_tg_destroy(const struct xt_target *target, void *targinfo)
+ {
+- struct ipt_clusterip_tgt_info *cipinfo = targinfo;
++ const struct ipt_clusterip_tgt_info *cipinfo = targinfo;
+
+ /* if no more entries are referencing the config, remove it
+ * from the list and destroy the proc entry */
+@@ -567,7 +567,7 @@ struct clusterip_seq_position {
+
+ static void *clusterip_seq_start(struct seq_file *s, loff_t *pos)
+ {
+- struct proc_dir_entry *pde = s->private;
++ const struct proc_dir_entry *pde = s->private;
+ struct clusterip_config *c = pde->data;
+ unsigned int weight;
+ u_int32_t local_nodes;
+@@ -594,7 +594,7 @@ static void *clusterip_seq_start(struct seq_file *s, loff_t *pos)
+
+ static void *clusterip_seq_next(struct seq_file *s, void *v, loff_t *pos)
+ {
+- struct clusterip_seq_position *idx = (struct clusterip_seq_position *)v;
++ struct clusterip_seq_position *idx = v;
+
+ *pos = ++idx->pos;
+ if (*pos >= idx->weight) {
+@@ -613,7 +613,7 @@ static void clusterip_seq_stop(struct seq_file *s, void *v)
+
+ static int clusterip_seq_show(struct seq_file *s, void *v)
+ {
+- struct clusterip_seq_position *idx = (struct clusterip_seq_position *)v;
++ struct clusterip_seq_position *idx = v;
+
+ if (idx->pos != 0)
+ seq_putc(s, ',');
+@@ -669,7 +669,7 @@ static ssize_t clusterip_proc_write(struct file *file, const char __user *input,
+ {
+ #define PROC_WRITELEN 10
+ char buffer[PROC_WRITELEN+1];
+- struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
++ const struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+ struct clusterip_config *c = pde->data;
+ unsigned long nodenum;
+
+diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
+index 21395bc..d60139c 100644
+--- a/net/ipv4/netfilter/ipt_ECN.c
++++ b/net/ipv4/netfilter/ipt_ECN.c
+@@ -100,7 +100,7 @@ ecn_tg_check(const char *tablename, const void *e_void,
+ const struct xt_target *target, void *targinfo,
+ unsigned int hook_mask)
+ {
+- const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo;
++ const struct ipt_ECN_info *einfo = targinfo;
+ const struct ipt_entry *e = e_void;
+
+ if (einfo->operation & IPT_ECN_OP_MASK) {
+diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
+index b38d785..0af1413 100644
+--- a/net/ipv4/netfilter/ipt_LOG.c
++++ b/net/ipv4/netfilter/ipt_LOG.c
+@@ -76,7 +76,8 @@ static void dump_packet(const struct nf_loginfo *info,
+
+ if ((logflags & IPT_LOG_IPOPT)
+ && ih->ihl * 4 > sizeof(struct iphdr)) {
+- unsigned char _opt[4 * 15 - sizeof(struct iphdr)], *op;
++ const unsigned char *op;
++ unsigned char _opt[4 * 15 - sizeof(struct iphdr)];
+ unsigned int i, optsize;
+
+ optsize = ih->ihl * 4 - sizeof(struct iphdr);
+@@ -338,12 +339,16 @@ static void dump_packet(const struct nf_loginfo *info,
+ if ((logflags & IPT_LOG_UID) && !iphoff && skb->sk) {
+ read_lock_bh(&skb->sk->sk_callback_lock);
+ if (skb->sk->sk_socket && skb->sk->sk_socket->file)
+- printk("UID=%u GID=%u",
++ printk("UID=%u GID=%u ",
+ skb->sk->sk_socket->file->f_uid,
+ skb->sk->sk_socket->file->f_gid);
+ read_unlock_bh(&skb->sk->sk_callback_lock);
+ }
+
++ /* Max length: 16 "MARK=0xFFFFFFFF " */
++ if (!iphoff && skb->mark)
++ printk("MARK=0x%x ", skb->mark);
++
+ /* Proto Max log string length */
+ /* IP: 40+46+6+11+127 = 230 */
+ /* TCP: 10+max(25,20+30+13+9+32+11+127) = 252 */
+diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
+index d80fee8..84c26dd 100644
+--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
++++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
+@@ -77,7 +77,7 @@ masquerade_tg(struct sk_buff *skb, const struct net_device *in,
+ return NF_ACCEPT;
+
+ mr = targinfo;
+- rt = (struct rtable *)skb->dst;
++ rt = skb->rtable;
+ newsrc = inet_select_addr(out, rt->rt_gateway, RT_SCOPE_UNIVERSE);
+ if (!newsrc) {
+ printk("MASQUERADE: %s ate my IP address\n", out->name);
+@@ -120,7 +120,7 @@ static int masq_device_event(struct notifier_block *this,
+ {
+ const struct net_device *dev = ptr;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ if (event == NETDEV_DOWN) {
+@@ -139,18 +139,8 @@ static int masq_inet_event(struct notifier_block *this,
+ unsigned long event,
+ void *ptr)
+ {
+- const struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
+-
+- if (event == NETDEV_DOWN) {
+- /* IP address was deleted. Search entire table for
+- conntracks which were associated with that device,
+- and forget them. */
+- NF_CT_ASSERT(dev->ifindex != 0);
+-
+- nf_ct_iterate_cleanup(device_cmp, (void *)(long)dev->ifindex);
+- }
+-
+- return NOTIFY_DONE;
++ struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
++ return masq_device_event(this, event, dev);
+ }
+
+ static struct notifier_block masq_dev_notifier = {
+diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
+index 22606e2..2639872 100644
+--- a/net/ipv4/netfilter/ipt_REJECT.c
++++ b/net/ipv4/netfilter/ipt_REJECT.c
+@@ -35,8 +35,10 @@ MODULE_DESCRIPTION("Xtables: packet \"rejection\" target for IPv4");
+ static void send_reset(struct sk_buff *oldskb, int hook)
+ {
+ struct sk_buff *nskb;
+- struct iphdr *oiph, *niph;
+- struct tcphdr _otcph, *oth, *tcph;
++ const struct iphdr *oiph;
++ struct iphdr *niph;
++ const struct tcphdr *oth;
++ struct tcphdr _otcph, *tcph;
+ unsigned int addr_type;
+
+ /* IP header checks: fragment. */
+diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
+index 50e0669..21cb053 100644
+--- a/net/ipv4/netfilter/ipt_recent.c
++++ b/net/ipv4/netfilter/ipt_recent.c
+@@ -340,7 +340,7 @@ static void *recent_seq_start(struct seq_file *seq, loff_t *pos)
+ static void *recent_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+ {
+ struct recent_iter_state *st = seq->private;
+- struct recent_table *t = st->table;
++ const struct recent_table *t = st->table;
+ struct recent_entry *e = v;
+ struct list_head *head = e->list.next;
+
+@@ -361,7 +361,7 @@ static void recent_seq_stop(struct seq_file *s, void *v)
+
+ static int recent_seq_show(struct seq_file *seq, void *v)
+ {
+- struct recent_entry *e = v;
++ const struct recent_entry *e = v;
+ unsigned int i;
+
+ i = (e->index - 1) % ip_pkt_list_tot;
+@@ -396,7 +396,7 @@ static int recent_seq_open(struct inode *inode, struct file *file)
+ static ssize_t recent_proc_write(struct file *file, const char __user *input,
+ size_t size, loff_t *loff)
+ {
+- struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
++ const struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
+ struct recent_table *t = pde->data;
+ struct recent_entry *e;
+ char buf[sizeof("+255.255.255.255")], *c = buf;
+diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
+index 69f3d7e..1ea677d 100644
+--- a/net/ipv4/netfilter/iptable_filter.c
++++ b/net/ipv4/netfilter/iptable_filter.c
+@@ -56,20 +56,32 @@ static struct
+ static struct xt_table packet_filter = {
+ .name = "filter",
+ .valid_hooks = FILTER_VALID_HOOKS,
+- .lock = RW_LOCK_UNLOCKED,
++ .lock = __RW_LOCK_UNLOCKED(packet_filter.lock),
+ .me = THIS_MODULE,
+ .af = AF_INET,
+ };
+
+ /* The work comes in here from netfilter.c. */
+ static unsigned int
++ipt_local_in_hook(unsigned int hook,
++ struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ int (*okfn)(struct sk_buff *))
++{
++ return ipt_do_table(skb, hook, in, out,
++ nf_local_in_net(in, out)->ipv4.iptable_filter);
++}
++
++static unsigned int
+ ipt_hook(unsigned int hook,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+ {
+- return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_filter);
++ return ipt_do_table(skb, hook, in, out,
++ nf_forward_net(in, out)->ipv4.iptable_filter);
+ }
+
+ static unsigned int
+@@ -88,12 +100,13 @@ ipt_local_out_hook(unsigned int hook,
+ return NF_ACCEPT;
+ }
+
+- return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_filter);
++ return ipt_do_table(skb, hook, in, out,
++ nf_local_out_net(in, out)->ipv4.iptable_filter);
+ }
+
+ static struct nf_hook_ops ipt_ops[] __read_mostly = {
+ {
+- .hook = ipt_hook,
++ .hook = ipt_local_in_hook,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_INET_LOCAL_IN,
+diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
+index c55a210..da59182 100644
+--- a/net/ipv4/netfilter/iptable_mangle.c
++++ b/net/ipv4/netfilter/iptable_mangle.c
+@@ -67,20 +67,54 @@ static struct
+ static struct xt_table packet_mangler = {
+ .name = "mangle",
+ .valid_hooks = MANGLE_VALID_HOOKS,
+- .lock = RW_LOCK_UNLOCKED,
++ .lock = __RW_LOCK_UNLOCKED(packet_mangler.lock),
+ .me = THIS_MODULE,
+ .af = AF_INET,
+ };
+
+ /* The work comes in here from netfilter.c. */
+ static unsigned int
+-ipt_route_hook(unsigned int hook,
++ipt_pre_routing_hook(unsigned int hook,
++ struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ int (*okfn)(struct sk_buff *))
++{
++ return ipt_do_table(skb, hook, in, out,
++ nf_pre_routing_net(in, out)->ipv4.iptable_mangle);
++}
++
++static unsigned int
++ipt_post_routing_hook(unsigned int hook,
++ struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ int (*okfn)(struct sk_buff *))
++{
++ return ipt_do_table(skb, hook, in, out,
++ nf_post_routing_net(in, out)->ipv4.iptable_mangle);
++}
++
++static unsigned int
++ipt_local_in_hook(unsigned int hook,
++ struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ int (*okfn)(struct sk_buff *))
++{
++ return ipt_do_table(skb, hook, in, out,
++ nf_local_in_net(in, out)->ipv4.iptable_mangle);
++}
++
++static unsigned int
++ipt_forward_hook(unsigned int hook,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+ {
+- return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_mangle);
++ return ipt_do_table(skb, hook, in, out,
++ nf_forward_net(in, out)->ipv4.iptable_mangle);
+ }
+
+ static unsigned int
+@@ -112,7 +146,8 @@ ipt_local_hook(unsigned int hook,
+ daddr = iph->daddr;
+ tos = iph->tos;
+
+- ret = ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_mangle);
++ ret = ipt_do_table(skb, hook, in, out,
++ nf_local_out_net(in, out)->ipv4.iptable_mangle);
+ /* Reroute for ANY change. */
+ if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) {
+ iph = ip_hdr(skb);
+@@ -130,21 +165,21 @@ ipt_local_hook(unsigned int hook,
+
+ static struct nf_hook_ops ipt_ops[] __read_mostly = {
+ {
+- .hook = ipt_route_hook,
++ .hook = ipt_pre_routing_hook,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_INET_PRE_ROUTING,
+ .priority = NF_IP_PRI_MANGLE,
+ },
+ {
+- .hook = ipt_route_hook,
++ .hook = ipt_local_in_hook,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_INET_LOCAL_IN,
+ .priority = NF_IP_PRI_MANGLE,
+ },
+ {
+- .hook = ipt_route_hook,
++ .hook = ipt_forward_hook,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_INET_FORWARD,
+@@ -158,7 +193,7 @@ static struct nf_hook_ops ipt_ops[] __read_mostly = {
+ .priority = NF_IP_PRI_MANGLE,
+ },
+ {
+- .hook = ipt_route_hook,
++ .hook = ipt_post_routing_hook,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_INET_POST_ROUTING,
+diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
+index e41fe8c..fddce77 100644
+--- a/net/ipv4/netfilter/iptable_raw.c
++++ b/net/ipv4/netfilter/iptable_raw.c
+@@ -39,7 +39,7 @@ static struct
+ static struct xt_table packet_raw = {
+ .name = "raw",
+ .valid_hooks = RAW_VALID_HOOKS,
+- .lock = RW_LOCK_UNLOCKED,
++ .lock = __RW_LOCK_UNLOCKED(packet_raw.lock),
+ .me = THIS_MODULE,
+ .af = AF_INET,
+ };
+@@ -52,7 +52,8 @@ ipt_hook(unsigned int hook,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+ {
+- return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_raw);
++ return ipt_do_table(skb, hook, in, out,
++ nf_pre_routing_net(in, out)->ipv4.iptable_raw);
+ }
+
+ static unsigned int
+@@ -70,7 +71,8 @@ ipt_local_hook(unsigned int hook,
+ "packet.\n");
+ return NF_ACCEPT;
+ }
+- return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_raw);
++ return ipt_do_table(skb, hook, in, out,
++ nf_local_out_net(in, out)->ipv4.iptable_raw);
+ }
+
+ /* 'raw' is the very first table. */
+diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+index a65b845..cacb9cb 100644
+--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
++++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+@@ -23,30 +23,36 @@
+ #include <net/netfilter/nf_conntrack_l3proto.h>
+ #include <net/netfilter/nf_conntrack_core.h>
+ #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
++#include <net/netfilter/nf_nat_helper.h>
+
+-static int ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
+- struct nf_conntrack_tuple *tuple)
++int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb,
++ struct nf_conn *ct,
++ enum ip_conntrack_info ctinfo);
++EXPORT_SYMBOL_GPL(nf_nat_seq_adjust_hook);
++
++static bool ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
++ struct nf_conntrack_tuple *tuple)
+ {
+ const __be32 *ap;
+ __be32 _addrs[2];
+ ap = skb_header_pointer(skb, nhoff + offsetof(struct iphdr, saddr),
+ sizeof(u_int32_t) * 2, _addrs);
+ if (ap == NULL)
+- return 0;
++ return false;
+
+ tuple->src.u3.ip = ap[0];
+ tuple->dst.u3.ip = ap[1];
+
+- return 1;
++ return true;
+ }
+
+-static int ipv4_invert_tuple(struct nf_conntrack_tuple *tuple,
+- const struct nf_conntrack_tuple *orig)
++static bool ipv4_invert_tuple(struct nf_conntrack_tuple *tuple,
++ const struct nf_conntrack_tuple *orig)
+ {
+ tuple->src.u3.ip = orig->dst.u3.ip;
+ tuple->dst.u3.ip = orig->src.u3.ip;
+
+- return 1;
++ return true;
+ }
+
+ static int ipv4_print_tuple(struct seq_file *s,
+@@ -101,35 +107,41 @@ static unsigned int ipv4_confirm(unsigned int hooknum,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+ {
+- /* We've seen it coming out the other side: confirm it */
+- return nf_conntrack_confirm(skb);
+-}
+-
+-static unsigned int ipv4_conntrack_help(unsigned int hooknum,
+- struct sk_buff *skb,
+- const struct net_device *in,
+- const struct net_device *out,
+- int (*okfn)(struct sk_buff *))
+-{
+ struct nf_conn *ct;
+ enum ip_conntrack_info ctinfo;
+ const struct nf_conn_help *help;
+ const struct nf_conntrack_helper *helper;
++ unsigned int ret;
+
+ /* This is where we call the helper: as the packet goes out. */
+ ct = nf_ct_get(skb, &ctinfo);
+ if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)
+- return NF_ACCEPT;
++ goto out;
+
+ help = nfct_help(ct);
+ if (!help)
+- return NF_ACCEPT;
++ goto out;
++
+ /* rcu_read_lock()ed by nf_hook_slow */
+ helper = rcu_dereference(help->helper);
+ if (!helper)
+- return NF_ACCEPT;
+- return helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb),
+- ct, ctinfo);
++ goto out;
++
++ ret = helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb),
++ ct, ctinfo);
++ if (ret != NF_ACCEPT)
++ return ret;
++
++ if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
++ typeof(nf_nat_seq_adjust_hook) seq_adjust;
++
++ seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook);
++ if (!seq_adjust || !seq_adjust(skb, ct, ctinfo))
++ return NF_DROP;
++ }
++out:
++ /* We've seen it coming out the other side: confirm it */
++ return nf_conntrack_confirm(skb);
+ }
+
+ static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
+@@ -211,20 +223,6 @@ static struct nf_hook_ops ipv4_conntrack_ops[] __read_mostly = {
+ .priority = NF_IP_PRI_CONNTRACK,
+ },
+ {
+- .hook = ipv4_conntrack_help,
+- .owner = THIS_MODULE,
+- .pf = PF_INET,
+- .hooknum = NF_INET_POST_ROUTING,
+- .priority = NF_IP_PRI_CONNTRACK_HELPER,
+- },
+- {
+- .hook = ipv4_conntrack_help,
+- .owner = THIS_MODULE,
+- .pf = PF_INET,
+- .hooknum = NF_INET_LOCAL_IN,
+- .priority = NF_IP_PRI_CONNTRACK_HELPER,
+- },
+- {
+ .hook = ipv4_confirm,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
+index f500b0f..40a46d4 100644
+--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
++++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
+@@ -106,21 +106,16 @@ static int ct_seq_show(struct seq_file *s, void *v)
+ /* we only want to print DIR_ORIGINAL */
+ if (NF_CT_DIRECTION(hash))
+ return 0;
+- if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num != AF_INET)
++ if (nf_ct_l3num(ct) != AF_INET)
+ return 0;
+
+- l3proto = __nf_ct_l3proto_find(ct->tuplehash[IP_CT_DIR_ORIGINAL]
+- .tuple.src.l3num);
++ l3proto = __nf_ct_l3proto_find(nf_ct_l3num(ct));
+ NF_CT_ASSERT(l3proto);
+- l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_ORIGINAL]
+- .tuple.src.l3num,
+- ct->tuplehash[IP_CT_DIR_ORIGINAL]
+- .tuple.dst.protonum);
++ l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
+ NF_CT_ASSERT(l4proto);
+
+ if (seq_printf(s, "%-8s %u %ld ",
+- l4proto->name,
+- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,
++ l4proto->name, nf_ct_protonum(ct),
+ timer_pending(&ct->timeout)
+ ? (long)(ct->timeout.expires - jiffies)/HZ : 0) != 0)
+ return -ENOSPC;
+@@ -379,7 +374,7 @@ static const struct file_operations ct_cpu_seq_fops = {
+ .open = ct_cpu_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = seq_release_private,
++ .release = seq_release,
+ };
+
+ int __init nf_conntrack_ipv4_compat_init(void)
+diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+index 6873fdd..78ab19a 100644
+--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
++++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+@@ -22,22 +22,21 @@
+
+ static unsigned long nf_ct_icmp_timeout __read_mostly = 30*HZ;
+
+-static int icmp_pkt_to_tuple(const struct sk_buff *skb,
+- unsigned int dataoff,
+- struct nf_conntrack_tuple *tuple)
++static bool icmp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
++ struct nf_conntrack_tuple *tuple)
+ {
+ const struct icmphdr *hp;
+ struct icmphdr _hdr;
+
+ hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
+ if (hp == NULL)
+- return 0;
++ return false;
+
+ tuple->dst.u.icmp.type = hp->type;
+ tuple->src.u.icmp.id = hp->un.echo.id;
+ tuple->dst.u.icmp.code = hp->code;
+
+- return 1;
++ return true;
+ }
+
+ /* Add 1; spaces filled with 0. */
+@@ -52,17 +51,17 @@ static const u_int8_t invmap[] = {
+ [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1
+ };
+
+-static int icmp_invert_tuple(struct nf_conntrack_tuple *tuple,
+- const struct nf_conntrack_tuple *orig)
++static bool icmp_invert_tuple(struct nf_conntrack_tuple *tuple,
++ const struct nf_conntrack_tuple *orig)
+ {
+ if (orig->dst.u.icmp.type >= sizeof(invmap)
+ || !invmap[orig->dst.u.icmp.type])
+- return 0;
++ return false;
+
+ tuple->src.u.icmp.id = orig->src.u.icmp.id;
+ tuple->dst.u.icmp.type = invmap[orig->dst.u.icmp.type] - 1;
+ tuple->dst.u.icmp.code = orig->dst.u.icmp.code;
+- return 1;
++ return true;
+ }
+
+ /* Print out the per-protocol part of the tuple. */
+@@ -101,8 +100,8 @@ static int icmp_packet(struct nf_conn *ct,
+ }
+
+ /* Called when a new connection for this protocol found. */
+-static int icmp_new(struct nf_conn *ct,
+- const struct sk_buff *skb, unsigned int dataoff)
++static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb,
++ unsigned int dataoff)
+ {
+ static const u_int8_t valid_new[] = {
+ [ICMP_ECHO] = 1,
+@@ -116,11 +115,11 @@ static int icmp_new(struct nf_conn *ct,
+ /* Can't create a new ICMP `conn' with this. */
+ pr_debug("icmp: can't create new conn with type %u\n",
+ ct->tuplehash[0].tuple.dst.u.icmp.type);
+- NF_CT_DUMP_TUPLE(&ct->tuplehash[0].tuple);
+- return 0;
++ nf_ct_dump_tuple_ip(&ct->tuplehash[0].tuple);
++ return false;
+ }
+ atomic_set(&ct->proto.icmp.count, 0);
+- return 1;
++ return true;
+ }
+
+ /* Returns conntrack if it dealt with ICMP, and filled in skb fields */
+diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
+index 36b4e3b..0457859 100644
+--- a/net/ipv4/netfilter/nf_nat_core.c
++++ b/net/ipv4/netfilter/nf_nat_core.c
+@@ -150,9 +150,9 @@ find_appropriate_src(const struct nf_conntrack_tuple *tuple,
+ const struct nf_nat_range *range)
+ {
+ unsigned int h = hash_by_src(tuple);
+- struct nf_conn_nat *nat;
+- struct nf_conn *ct;
+- struct hlist_node *n;
++ const struct nf_conn_nat *nat;
++ const struct nf_conn *ct;
++ const struct hlist_node *n;
+
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(nat, n, &bysource[h], bysource) {
+@@ -349,7 +349,7 @@ nf_nat_setup_info(struct nf_conn *ct,
+ EXPORT_SYMBOL(nf_nat_setup_info);
+
+ /* Returns true if succeeded. */
+-static int
++static bool
+ manip_pkt(u_int16_t proto,
+ struct sk_buff *skb,
+ unsigned int iphdroff,
+@@ -360,7 +360,7 @@ manip_pkt(u_int16_t proto,
+ const struct nf_nat_protocol *p;
+
+ if (!skb_make_writable(skb, iphdroff + sizeof(*iph)))
+- return 0;
++ return false;
+
+ iph = (void *)skb->data + iphdroff;
+
+@@ -369,7 +369,7 @@ manip_pkt(u_int16_t proto,
+ /* rcu_read_lock()ed by nf_hook_slow */
+ p = __nf_nat_proto_find(proto);
+ if (!p->manip_pkt(skb, iphdroff, target, maniptype))
+- return 0;
++ return false;
+
+ iph = (void *)skb->data + iphdroff;
+
+@@ -380,7 +380,7 @@ manip_pkt(u_int16_t proto,
+ csum_replace4(&iph->check, iph->daddr, target->dst.u3.ip);
+ iph->daddr = target->dst.u3.ip;
+ }
+- return 1;
++ return true;
+ }
+
+ /* Do packet manipulations according to nf_nat_setup_info. */
+@@ -426,7 +426,7 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct,
+ struct icmphdr icmp;
+ struct iphdr ip;
+ } *inside;
+- struct nf_conntrack_l4proto *l4proto;
++ const struct nf_conntrack_l4proto *l4proto;
+ struct nf_conntrack_tuple inner, target;
+ int hdrlen = ip_hdrlen(skb);
+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+@@ -544,46 +544,6 @@ void nf_nat_protocol_unregister(const struct nf_nat_protocol *proto)
+ }
+ EXPORT_SYMBOL(nf_nat_protocol_unregister);
+
+-#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+-int
+-nf_nat_port_range_to_nlattr(struct sk_buff *skb,
+- const struct nf_nat_range *range)
+-{
+- NLA_PUT_BE16(skb, CTA_PROTONAT_PORT_MIN, range->min.tcp.port);
+- NLA_PUT_BE16(skb, CTA_PROTONAT_PORT_MAX, range->max.tcp.port);
+-
+- return 0;
+-
+-nla_put_failure:
+- return -1;
+-}
+-EXPORT_SYMBOL_GPL(nf_nat_port_nlattr_to_range);
+-
+-int
+-nf_nat_port_nlattr_to_range(struct nlattr *tb[], struct nf_nat_range *range)
+-{
+- int ret = 0;
+-
+- /* we have to return whether we actually parsed something or not */
+-
+- if (tb[CTA_PROTONAT_PORT_MIN]) {
+- ret = 1;
+- range->min.tcp.port = nla_get_be16(tb[CTA_PROTONAT_PORT_MIN]);
+- }
+-
+- if (!tb[CTA_PROTONAT_PORT_MAX]) {
+- if (ret)
+- range->max.tcp.port = range->min.tcp.port;
+- } else {
+- ret = 1;
+- range->max.tcp.port = nla_get_be16(tb[CTA_PROTONAT_PORT_MAX]);
+- }
+-
+- return ret;
+-}
+-EXPORT_SYMBOL_GPL(nf_nat_port_range_to_nlattr);
+-#endif
+-
+ /* Noone using conntrack by the time this called. */
+ static void nf_nat_cleanup_conntrack(struct nf_conn *ct)
+ {
+@@ -660,6 +620,9 @@ static int __init nf_nat_init(void)
+ nf_conntrack_untracked.status |= IPS_NAT_DONE_MASK;
+
+ l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET);
++
++ BUG_ON(nf_nat_seq_adjust_hook != NULL);
++ rcu_assign_pointer(nf_nat_seq_adjust_hook, nf_nat_seq_adjust);
+ return 0;
+
+ cleanup_extend:
+@@ -686,6 +649,8 @@ static void __exit nf_nat_cleanup(void)
+ nf_ct_free_hashtable(bysource, nf_nat_vmalloced, nf_nat_htable_size);
+ nf_ct_l3proto_put(l3proto);
+ nf_ct_extend_unregister(&nat_extend);
++ rcu_assign_pointer(nf_nat_seq_adjust_hook, NULL);
++ synchronize_net();
+ }
+
+ MODULE_LICENSE("GPL");
+diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c
+index ca57f47..11976ea 100644
+--- a/net/ipv4/netfilter/nf_nat_helper.c
++++ b/net/ipv4/netfilter/nf_nat_helper.c
+@@ -139,7 +139,7 @@ nf_nat_mangle_tcp_packet(struct sk_buff *skb,
+ const char *rep_buffer,
+ unsigned int rep_len)
+ {
+- struct rtable *rt = (struct rtable *)skb->dst;
++ struct rtable *rt = skb->rtable;
+ struct iphdr *iph;
+ struct tcphdr *tcph;
+ int oldlen, datalen;
+@@ -217,7 +217,7 @@ nf_nat_mangle_udp_packet(struct sk_buff *skb,
+ const char *rep_buffer,
+ unsigned int rep_len)
+ {
+- struct rtable *rt = (struct rtable *)skb->dst;
++ struct rtable *rt = skb->rtable;
+ struct iphdr *iph;
+ struct udphdr *udph;
+ int datalen, oldlen;
+@@ -416,7 +416,6 @@ nf_nat_seq_adjust(struct sk_buff *skb,
+
+ return 1;
+ }
+-EXPORT_SYMBOL(nf_nat_seq_adjust);
+
+ /* Setup NAT on this expected conntrack so it follows master. */
+ /* If we fail to get a free NAT slot, we'll get dropped on confirm */
+diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c
+index 3a1e6d6..da3d91a 100644
+--- a/net/ipv4/netfilter/nf_nat_pptp.c
++++ b/net/ipv4/netfilter/nf_nat_pptp.c
+@@ -72,7 +72,7 @@ static void pptp_nat_expected(struct nf_conn *ct,
+ }
+
+ pr_debug("trying to unexpect other dir: ");
+- NF_CT_DUMP_TUPLE(&t);
++ nf_ct_dump_tuple_ip(&t);
+ other_exp = nf_ct_expect_find_get(&t);
+ if (other_exp) {
+ nf_ct_unexpect_related(other_exp);
+diff --git a/net/ipv4/netfilter/nf_nat_proto_common.c b/net/ipv4/netfilter/nf_nat_proto_common.c
+new file mode 100644
+index 0000000..91537f1
+--- /dev/null
++++ b/net/ipv4/netfilter/nf_nat_proto_common.c
+@@ -0,0 +1,120 @@
++/* (C) 1999-2001 Paul `Rusty' Russell
++ * (C) 2002-2006 Netfilter Core Team <coreteam at netfilter.org>
++ * (C) 2008 Patrick McHardy <kaber at trash.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/types.h>
++#include <linux/random.h>
++#include <linux/ip.h>
++
++#include <linux/netfilter.h>
++#include <net/netfilter/nf_nat.h>
++#include <net/netfilter/nf_nat_core.h>
++#include <net/netfilter/nf_nat_rule.h>
++#include <net/netfilter/nf_nat_protocol.h>
++
++bool nf_nat_proto_in_range(const struct nf_conntrack_tuple *tuple,
++ enum nf_nat_manip_type maniptype,
++ const union nf_conntrack_man_proto *min,
++ const union nf_conntrack_man_proto *max)
++{
++ __be16 port;
++
++ if (maniptype == IP_NAT_MANIP_SRC)
++ port = tuple->src.u.all;
++ else
++ port = tuple->dst.u.all;
++
++ return ntohs(port) >= ntohs(min->all) &&
++ ntohs(port) <= ntohs(max->all);
++}
++EXPORT_SYMBOL_GPL(nf_nat_proto_in_range);
++
++bool nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,
++ const struct nf_nat_range *range,
++ enum nf_nat_manip_type maniptype,
++ const struct nf_conn *ct,
++ u_int16_t *rover)
++{
++ unsigned int range_size, min, i;
++ __be16 *portptr;
++ u_int16_t off;
++
++ if (maniptype == IP_NAT_MANIP_SRC)
++ portptr = &tuple->src.u.all;
++ else
++ portptr = &tuple->dst.u.all;
++
++ /* If no range specified... */
++ if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
++ /* If it's dst rewrite, can't change port */
++ if (maniptype == IP_NAT_MANIP_DST)
++ return false;
++
++ if (ntohs(*portptr) < 1024) {
++ /* Loose convention: >> 512 is credential passing */
++ if (ntohs(*portptr) < 512) {
++ min = 1;
++ range_size = 511 - min + 1;
++ } else {
++ min = 600;
++ range_size = 1023 - min + 1;
++ }
++ } else {
++ min = 1024;
++ range_size = 65535 - 1024 + 1;
++ }
++ } else {
++ min = ntohs(range->min.all);
++ range_size = ntohs(range->max.all) - min + 1;
++ }
++
++ off = *rover;
++ if (range->flags & IP_NAT_RANGE_PROTO_RANDOM)
++ off = net_random();
++
++ for (i = 0; i < range_size; i++, off++) {
++ *portptr = htons(min + off % range_size);
++ if (nf_nat_used_tuple(tuple, ct))
++ continue;
++ if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM))
++ *rover = off;
++ return true;
++ }
++ return false;
++}
++EXPORT_SYMBOL_GPL(nf_nat_proto_unique_tuple);
++
++#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
++int nf_nat_proto_range_to_nlattr(struct sk_buff *skb,
++ const struct nf_nat_range *range)
++{
++ NLA_PUT_BE16(skb, CTA_PROTONAT_PORT_MIN, range->min.all);
++ NLA_PUT_BE16(skb, CTA_PROTONAT_PORT_MAX, range->max.all);
++ return 0;
++
++nla_put_failure:
++ return -1;
++}
++EXPORT_SYMBOL_GPL(nf_nat_proto_nlattr_to_range);
++
++int nf_nat_proto_nlattr_to_range(struct nlattr *tb[],
++ struct nf_nat_range *range)
++{
++ if (tb[CTA_PROTONAT_PORT_MIN]) {
++ range->min.all = nla_get_be16(tb[CTA_PROTONAT_PORT_MIN]);
++ range->max.all = range->min.tcp.port;
++ range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
++ }
++ if (tb[CTA_PROTONAT_PORT_MAX]) {
++ range->max.all = nla_get_be16(tb[CTA_PROTONAT_PORT_MAX]);
++ range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
++ }
++ return 0;
++}
++EXPORT_SYMBOL_GPL(nf_nat_proto_range_to_nlattr);
++#endif
+diff --git a/net/ipv4/netfilter/nf_nat_proto_dccp.c b/net/ipv4/netfilter/nf_nat_proto_dccp.c
+new file mode 100644
+index 0000000..22485ce
+--- /dev/null
++++ b/net/ipv4/netfilter/nf_nat_proto_dccp.c
+@@ -0,0 +1,108 @@
++/*
++ * DCCP NAT protocol helper
++ *
++ * Copyright (c) 2005, 2006. 2008 Patrick McHardy <kaber at trash.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/skbuff.h>
++#include <linux/ip.h>
++#include <linux/dccp.h>
++
++#include <net/netfilter/nf_conntrack.h>
++#include <net/netfilter/nf_nat.h>
++#include <net/netfilter/nf_nat_protocol.h>
++
++static u_int16_t dccp_port_rover;
++
++static bool
++dccp_unique_tuple(struct nf_conntrack_tuple *tuple,
++ const struct nf_nat_range *range,
++ enum nf_nat_manip_type maniptype,
++ const struct nf_conn *ct)
++{
++ return nf_nat_proto_unique_tuple(tuple, range, maniptype, ct,
++ &dccp_port_rover);
++}
++
++static bool
++dccp_manip_pkt(struct sk_buff *skb,
++ unsigned int iphdroff,
++ const struct nf_conntrack_tuple *tuple,
++ enum nf_nat_manip_type maniptype)
++{
++ const struct iphdr *iph = (const void *)(skb->data + iphdroff);
++ struct dccp_hdr *hdr;
++ unsigned int hdroff = iphdroff + iph->ihl * 4;
++ __be32 oldip, newip;
++ __be16 *portptr, oldport, newport;
++ int hdrsize = 8; /* DCCP connection tracking guarantees this much */
++
++ if (skb->len >= hdroff + sizeof(struct dccp_hdr))
++ hdrsize = sizeof(struct dccp_hdr);
++
++ if (!skb_make_writable(skb, hdroff + hdrsize))
++ return false;
++
++ iph = (struct iphdr *)(skb->data + iphdroff);
++ hdr = (struct dccp_hdr *)(skb->data + hdroff);
++
++ if (maniptype == IP_NAT_MANIP_SRC) {
++ oldip = iph->saddr;
++ newip = tuple->src.u3.ip;
++ newport = tuple->src.u.dccp.port;
++ portptr = &hdr->dccph_sport;
++ } else {
++ oldip = iph->daddr;
++ newip = tuple->dst.u3.ip;
++ newport = tuple->dst.u.dccp.port;
++ portptr = &hdr->dccph_dport;
++ }
++
++ oldport = *portptr;
++ *portptr = newport;
++
++ if (hdrsize < sizeof(*hdr))
++ return true;
++
++ inet_proto_csum_replace4(&hdr->dccph_checksum, skb, oldip, newip, 1);
++ inet_proto_csum_replace2(&hdr->dccph_checksum, skb, oldport, newport,
++ 0);
++ return true;
++}
++
++static const struct nf_nat_protocol nf_nat_protocol_dccp = {
++ .protonum = IPPROTO_DCCP,
++ .me = THIS_MODULE,
++ .manip_pkt = dccp_manip_pkt,
++ .in_range = nf_nat_proto_in_range,
++ .unique_tuple = dccp_unique_tuple,
++#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
++ .range_to_nlattr = nf_nat_proto_range_to_nlattr,
++ .nlattr_to_range = nf_nat_proto_nlattr_to_range,
++#endif
++};
++
++static int __init nf_nat_proto_dccp_init(void)
++{
++ return nf_nat_protocol_register(&nf_nat_protocol_dccp);
++}
++
++static void __exit nf_nat_proto_dccp_fini(void)
++{
++ nf_nat_protocol_unregister(&nf_nat_protocol_dccp);
++}
++
++module_init(nf_nat_proto_dccp_init);
++module_exit(nf_nat_proto_dccp_fini);
++
++MODULE_AUTHOR("Patrick McHardy <kaber at trash.net>");
++MODULE_DESCRIPTION("DCCP NAT protocol helper");
++MODULE_LICENSE("GPL");
+diff --git a/net/ipv4/netfilter/nf_nat_proto_gre.c b/net/ipv4/netfilter/nf_nat_proto_gre.c
+index a1e4da1..d7e8920 100644
+--- a/net/ipv4/netfilter/nf_nat_proto_gre.c
++++ b/net/ipv4/netfilter/nf_nat_proto_gre.c
+@@ -36,26 +36,8 @@ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Harald Welte <laforge at gnumonks.org>");
+ MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
+
+-/* is key in given range between min and max */
+-static int
+-gre_in_range(const struct nf_conntrack_tuple *tuple,
+- enum nf_nat_manip_type maniptype,
+- const union nf_conntrack_man_proto *min,
+- const union nf_conntrack_man_proto *max)
+-{
+- __be16 key;
+-
+- if (maniptype == IP_NAT_MANIP_SRC)
+- key = tuple->src.u.gre.key;
+- else
+- key = tuple->dst.u.gre.key;
+-
+- return ntohs(key) >= ntohs(min->gre.key) &&
+- ntohs(key) <= ntohs(max->gre.key);
+-}
+-
+ /* generate unique tuple ... */
+-static int
++static bool
+ gre_unique_tuple(struct nf_conntrack_tuple *tuple,
+ const struct nf_nat_range *range,
+ enum nf_nat_manip_type maniptype,
+@@ -68,7 +50,7 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple,
+ /* If there is no master conntrack we are not PPTP,
+ do not change tuples */
+ if (!ct->master)
+- return 0;
++ return false;
+
+ if (maniptype == IP_NAT_MANIP_SRC)
+ keyptr = &tuple->src.u.gre.key;
+@@ -89,20 +71,20 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple,
+ for (i = 0; i < range_size; i++, key++) {
+ *keyptr = htons(min + key % range_size);
+ if (!nf_nat_used_tuple(tuple, ct))
+- return 1;
++ return true;
+ }
+
+ pr_debug("%p: no NAT mapping\n", ct);
+- return 0;
++ return false;
+ }
+
+ /* manipulate a GRE packet according to maniptype */
+-static int
++static bool
+ gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff,
+ const struct nf_conntrack_tuple *tuple,
+ enum nf_nat_manip_type maniptype)
+ {
+- struct gre_hdr *greh;
++ const struct gre_hdr *greh;
+ struct gre_hdr_pptp *pgreh;
+ const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
+ unsigned int hdroff = iphdroff + iph->ihl * 4;
+@@ -110,7 +92,7 @@ gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff,
+ /* pgreh includes two optional 32bit fields which are not required
+ * to be there. That's where the magic '8' comes from */
+ if (!skb_make_writable(skb, hdroff + sizeof(*pgreh) - 8))
+- return 0;
++ return false;
+
+ greh = (void *)skb->data + hdroff;
+ pgreh = (struct gre_hdr_pptp *)greh;
+@@ -118,7 +100,7 @@ gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff,
+ /* we only have destination manip of a packet, since 'source key'
+ * is not present in the packet itself */
+ if (maniptype != IP_NAT_MANIP_DST)
+- return 1;
++ return true;
+ switch (greh->version) {
+ case GRE_VERSION_1701:
+ /* We do not currently NAT any GREv0 packets.
+@@ -130,21 +112,20 @@ gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff,
+ break;
+ default:
+ pr_debug("can't nat unknown GRE version\n");
+- return 0;
++ return false;
+ }
+- return 1;
++ return true;
+ }
+
+ static const struct nf_nat_protocol gre = {
+- .name = "GRE",
+ .protonum = IPPROTO_GRE,
+ .me = THIS_MODULE,
+ .manip_pkt = gre_manip_pkt,
+- .in_range = gre_in_range,
++ .in_range = nf_nat_proto_in_range,
+ .unique_tuple = gre_unique_tuple,
+ #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+- .range_to_nlattr = nf_nat_port_range_to_nlattr,
+- .nlattr_to_range = nf_nat_port_nlattr_to_range,
++ .range_to_nlattr = nf_nat_proto_range_to_nlattr,
++ .nlattr_to_range = nf_nat_proto_nlattr_to_range,
+ #endif
+ };
+
+diff --git a/net/ipv4/netfilter/nf_nat_proto_icmp.c b/net/ipv4/netfilter/nf_nat_proto_icmp.c
+index 03a0296..19a8b0b 100644
+--- a/net/ipv4/netfilter/nf_nat_proto_icmp.c
++++ b/net/ipv4/netfilter/nf_nat_proto_icmp.c
+@@ -17,7 +17,7 @@
+ #include <net/netfilter/nf_nat_rule.h>
+ #include <net/netfilter/nf_nat_protocol.h>
+
+-static int
++static bool
+ icmp_in_range(const struct nf_conntrack_tuple *tuple,
+ enum nf_nat_manip_type maniptype,
+ const union nf_conntrack_man_proto *min,
+@@ -27,7 +27,7 @@ icmp_in_range(const struct nf_conntrack_tuple *tuple,
+ ntohs(tuple->src.u.icmp.id) <= ntohs(max->icmp.id);
+ }
+
+-static int
++static bool
+ icmp_unique_tuple(struct nf_conntrack_tuple *tuple,
+ const struct nf_nat_range *range,
+ enum nf_nat_manip_type maniptype,
+@@ -46,12 +46,12 @@ icmp_unique_tuple(struct nf_conntrack_tuple *tuple,
+ tuple->src.u.icmp.id = htons(ntohs(range->min.icmp.id) +
+ (id % range_size));
+ if (!nf_nat_used_tuple(tuple, ct))
+- return 1;
++ return true;
+ }
+- return 0;
++ return false;
+ }
+
+-static int
++static bool
+ icmp_manip_pkt(struct sk_buff *skb,
+ unsigned int iphdroff,
+ const struct nf_conntrack_tuple *tuple,
+@@ -62,24 +62,23 @@ icmp_manip_pkt(struct sk_buff *skb,
+ unsigned int hdroff = iphdroff + iph->ihl*4;
+
+ if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
+- return 0;
++ return false;
+
+ hdr = (struct icmphdr *)(skb->data + hdroff);
+ inet_proto_csum_replace2(&hdr->checksum, skb,
+ hdr->un.echo.id, tuple->src.u.icmp.id, 0);
+ hdr->un.echo.id = tuple->src.u.icmp.id;
+- return 1;
++ return true;
+ }
+
+ const struct nf_nat_protocol nf_nat_protocol_icmp = {
+- .name = "ICMP",
+ .protonum = IPPROTO_ICMP,
+ .me = THIS_MODULE,
+ .manip_pkt = icmp_manip_pkt,
+ .in_range = icmp_in_range,
+ .unique_tuple = icmp_unique_tuple,
+ #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+- .range_to_nlattr = nf_nat_port_range_to_nlattr,
+- .nlattr_to_range = nf_nat_port_nlattr_to_range,
++ .range_to_nlattr = nf_nat_proto_range_to_nlattr,
++ .nlattr_to_range = nf_nat_proto_nlattr_to_range,
+ #endif
+ };
+diff --git a/net/ipv4/netfilter/nf_nat_proto_sctp.c b/net/ipv4/netfilter/nf_nat_proto_sctp.c
+new file mode 100644
+index 0000000..82e4c0e
+--- /dev/null
++++ b/net/ipv4/netfilter/nf_nat_proto_sctp.c
+@@ -0,0 +1,96 @@
++/*
++ * Copyright (c) 2008 Patrick McHardy <kaber at trash.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/types.h>
++#include <linux/init.h>
++#include <linux/ip.h>
++#include <linux/sctp.h>
++#include <net/sctp/checksum.h>
++
++#include <net/netfilter/nf_nat_protocol.h>
++
++static u_int16_t nf_sctp_port_rover;
++
++static bool
++sctp_unique_tuple(struct nf_conntrack_tuple *tuple,
++ const struct nf_nat_range *range,
++ enum nf_nat_manip_type maniptype,
++ const struct nf_conn *ct)
++{
++ return nf_nat_proto_unique_tuple(tuple, range, maniptype, ct,
++ &nf_sctp_port_rover);
++}
++
++static bool
++sctp_manip_pkt(struct sk_buff *skb,
++ unsigned int iphdroff,
++ const struct nf_conntrack_tuple *tuple,
++ enum nf_nat_manip_type maniptype)
++{
++ const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
++ sctp_sctphdr_t *hdr;
++ unsigned int hdroff = iphdroff + iph->ihl*4;
++ __be32 oldip, newip;
++ u32 crc32;
++
++ if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
++ return false;
++
++ iph = (struct iphdr *)(skb->data + iphdroff);
++ hdr = (struct sctphdr *)(skb->data + hdroff);
++
++ if (maniptype == IP_NAT_MANIP_SRC) {
++ /* Get rid of src ip and src pt */
++ oldip = iph->saddr;
++ newip = tuple->src.u3.ip;
++ hdr->source = tuple->src.u.sctp.port;
++ } else {
++ /* Get rid of dst ip and dst pt */
++ oldip = iph->daddr;
++ newip = tuple->dst.u3.ip;
++ hdr->dest = tuple->dst.u.sctp.port;
++ }
++
++ crc32 = sctp_start_cksum((u8 *)hdr, skb_headlen(skb) - hdroff);
++ for (skb = skb_shinfo(skb)->frag_list; skb; skb = skb->next)
++ crc32 = sctp_update_cksum((u8 *)skb->data, skb_headlen(skb),
++ crc32);
++ crc32 = sctp_end_cksum(crc32);
++ hdr->checksum = htonl(crc32);
++
++ return true;
++}
++
++static const struct nf_nat_protocol nf_nat_protocol_sctp = {
++ .protonum = IPPROTO_SCTP,
++ .me = THIS_MODULE,
++ .manip_pkt = sctp_manip_pkt,
++ .in_range = nf_nat_proto_in_range,
++ .unique_tuple = sctp_unique_tuple,
++#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
++ .range_to_nlattr = nf_nat_proto_range_to_nlattr,
++ .nlattr_to_range = nf_nat_proto_nlattr_to_range,
++#endif
++};
++
++static int __init nf_nat_proto_sctp_init(void)
++{
++ return nf_nat_protocol_register(&nf_nat_protocol_sctp);
++}
++
++static void __exit nf_nat_proto_sctp_exit(void)
++{
++ nf_nat_protocol_unregister(&nf_nat_protocol_sctp);
++}
++
++module_init(nf_nat_proto_sctp_init);
++module_exit(nf_nat_proto_sctp_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("SCTP NAT protocol helper");
++MODULE_AUTHOR("Patrick McHardy <kaber at trash.net>");
+diff --git a/net/ipv4/netfilter/nf_nat_proto_tcp.c b/net/ipv4/netfilter/nf_nat_proto_tcp.c
+index ffd5d15..399e2cf 100644
+--- a/net/ipv4/netfilter/nf_nat_proto_tcp.c
++++ b/net/ipv4/netfilter/nf_nat_proto_tcp.c
+@@ -8,7 +8,6 @@
+
+ #include <linux/types.h>
+ #include <linux/init.h>
+-#include <linux/random.h>
+ #include <linux/ip.h>
+ #include <linux/tcp.h>
+
+@@ -19,75 +18,19 @@
+ #include <net/netfilter/nf_nat_protocol.h>
+ #include <net/netfilter/nf_nat_core.h>
+
+-static int
+-tcp_in_range(const struct nf_conntrack_tuple *tuple,
+- enum nf_nat_manip_type maniptype,
+- const union nf_conntrack_man_proto *min,
+- const union nf_conntrack_man_proto *max)
+-{
+- __be16 port;
+-
+- if (maniptype == IP_NAT_MANIP_SRC)
+- port = tuple->src.u.tcp.port;
+- else
+- port = tuple->dst.u.tcp.port;
+-
+- return ntohs(port) >= ntohs(min->tcp.port) &&
+- ntohs(port) <= ntohs(max->tcp.port);
+-}
++static u_int16_t tcp_port_rover;
+
+-static int
++static bool
+ tcp_unique_tuple(struct nf_conntrack_tuple *tuple,
+ const struct nf_nat_range *range,
+ enum nf_nat_manip_type maniptype,
+ const struct nf_conn *ct)
+ {
+- static u_int16_t port;
+- __be16 *portptr;
+- unsigned int range_size, min, i;
+-
+- if (maniptype == IP_NAT_MANIP_SRC)
+- portptr = &tuple->src.u.tcp.port;
+- else
+- portptr = &tuple->dst.u.tcp.port;
+-
+- /* If no range specified... */
+- if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
+- /* If it's dst rewrite, can't change port */
+- if (maniptype == IP_NAT_MANIP_DST)
+- return 0;
+-
+- /* Map privileged onto privileged. */
+- if (ntohs(*portptr) < 1024) {
+- /* Loose convention: >> 512 is credential passing */
+- if (ntohs(*portptr)<512) {
+- min = 1;
+- range_size = 511 - min + 1;
+- } else {
+- min = 600;
+- range_size = 1023 - min + 1;
+- }
+- } else {
+- min = 1024;
+- range_size = 65535 - 1024 + 1;
+- }
+- } else {
+- min = ntohs(range->min.tcp.port);
+- range_size = ntohs(range->max.tcp.port) - min + 1;
+- }
+-
+- if (range->flags & IP_NAT_RANGE_PROTO_RANDOM)
+- port = net_random();
+-
+- for (i = 0; i < range_size; i++, port++) {
+- *portptr = htons(min + port % range_size);
+- if (!nf_nat_used_tuple(tuple, ct))
+- return 1;
+- }
+- return 0;
++ return nf_nat_proto_unique_tuple(tuple, range, maniptype, ct,
++ &tcp_port_rover);
+ }
+
+-static int
++static bool
+ tcp_manip_pkt(struct sk_buff *skb,
+ unsigned int iphdroff,
+ const struct nf_conntrack_tuple *tuple,
+@@ -107,7 +50,7 @@ tcp_manip_pkt(struct sk_buff *skb,
+ hdrsize = sizeof(struct tcphdr);
+
+ if (!skb_make_writable(skb, hdroff + hdrsize))
+- return 0;
++ return false;
+
+ iph = (struct iphdr *)(skb->data + iphdroff);
+ hdr = (struct tcphdr *)(skb->data + hdroff);
+@@ -130,22 +73,21 @@ tcp_manip_pkt(struct sk_buff *skb,
+ *portptr = newport;
+
+ if (hdrsize < sizeof(*hdr))
+- return 1;
++ return true;
+
+ inet_proto_csum_replace4(&hdr->check, skb, oldip, newip, 1);
+ inet_proto_csum_replace2(&hdr->check, skb, oldport, newport, 0);
+- return 1;
++ return true;
+ }
+
+ const struct nf_nat_protocol nf_nat_protocol_tcp = {
+- .name = "TCP",
+ .protonum = IPPROTO_TCP,
+ .me = THIS_MODULE,
+ .manip_pkt = tcp_manip_pkt,
+- .in_range = tcp_in_range,
++ .in_range = nf_nat_proto_in_range,
+ .unique_tuple = tcp_unique_tuple,
+ #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+- .range_to_nlattr = nf_nat_port_range_to_nlattr,
+- .nlattr_to_range = nf_nat_port_nlattr_to_range,
++ .range_to_nlattr = nf_nat_proto_range_to_nlattr,
++ .nlattr_to_range = nf_nat_proto_nlattr_to_range,
+ #endif
+ };
+diff --git a/net/ipv4/netfilter/nf_nat_proto_udp.c b/net/ipv4/netfilter/nf_nat_proto_udp.c
+index 4b8f499..9e61c79 100644
+--- a/net/ipv4/netfilter/nf_nat_proto_udp.c
++++ b/net/ipv4/netfilter/nf_nat_proto_udp.c
+@@ -8,7 +8,6 @@
+
+ #include <linux/types.h>
+ #include <linux/init.h>
+-#include <linux/random.h>
+ #include <linux/ip.h>
+ #include <linux/udp.h>
+
+@@ -18,74 +17,19 @@
+ #include <net/netfilter/nf_nat_rule.h>
+ #include <net/netfilter/nf_nat_protocol.h>
+
+-static int
+-udp_in_range(const struct nf_conntrack_tuple *tuple,
+- enum nf_nat_manip_type maniptype,
+- const union nf_conntrack_man_proto *min,
+- const union nf_conntrack_man_proto *max)
+-{
+- __be16 port;
+-
+- if (maniptype == IP_NAT_MANIP_SRC)
+- port = tuple->src.u.udp.port;
+- else
+- port = tuple->dst.u.udp.port;
+-
+- return ntohs(port) >= ntohs(min->udp.port) &&
+- ntohs(port) <= ntohs(max->udp.port);
+-}
++static u_int16_t udp_port_rover;
+
+-static int
++static bool
+ udp_unique_tuple(struct nf_conntrack_tuple *tuple,
+ const struct nf_nat_range *range,
+ enum nf_nat_manip_type maniptype,
+ const struct nf_conn *ct)
+ {
+- static u_int16_t port;
+- __be16 *portptr;
+- unsigned int range_size, min, i;
+-
+- if (maniptype == IP_NAT_MANIP_SRC)
+- portptr = &tuple->src.u.udp.port;
+- else
+- portptr = &tuple->dst.u.udp.port;
+-
+- /* If no range specified... */
+- if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
+- /* If it's dst rewrite, can't change port */
+- if (maniptype == IP_NAT_MANIP_DST)
+- return 0;
+-
+- if (ntohs(*portptr) < 1024) {
+- /* Loose convention: >> 512 is credential passing */
+- if (ntohs(*portptr)<512) {
+- min = 1;
+- range_size = 511 - min + 1;
+- } else {
+- min = 600;
+- range_size = 1023 - min + 1;
+- }
+- } else {
+- min = 1024;
+- range_size = 65535 - 1024 + 1;
+- }
+- } else {
+- min = ntohs(range->min.udp.port);
+- range_size = ntohs(range->max.udp.port) - min + 1;
+- }
+-
+- if (range->flags & IP_NAT_RANGE_PROTO_RANDOM)
+- port = net_random();
+-
+- for (i = 0; i < range_size; i++, port++) {
+- *portptr = htons(min + port % range_size);
+- if (!nf_nat_used_tuple(tuple, ct))
+- return 1;
+- }
+- return 0;
++ return nf_nat_proto_unique_tuple(tuple, range, maniptype, ct,
++ &udp_port_rover);
+ }
+
+-static int
++static bool
+ udp_manip_pkt(struct sk_buff *skb,
+ unsigned int iphdroff,
+ const struct nf_conntrack_tuple *tuple,
+@@ -98,7 +42,7 @@ udp_manip_pkt(struct sk_buff *skb,
+ __be16 *portptr, newport;
+
+ if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
+- return 0;
++ return false;
+
+ iph = (struct iphdr *)(skb->data + iphdroff);
+ hdr = (struct udphdr *)(skb->data + hdroff);
+@@ -124,18 +68,17 @@ udp_manip_pkt(struct sk_buff *skb,
+ hdr->check = CSUM_MANGLED_0;
+ }
+ *portptr = newport;
+- return 1;
++ return true;
+ }
+
+ const struct nf_nat_protocol nf_nat_protocol_udp = {
+- .name = "UDP",
+ .protonum = IPPROTO_UDP,
+ .me = THIS_MODULE,
+ .manip_pkt = udp_manip_pkt,
+- .in_range = udp_in_range,
++ .in_range = nf_nat_proto_in_range,
+ .unique_tuple = udp_unique_tuple,
+ #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+- .range_to_nlattr = nf_nat_port_range_to_nlattr,
+- .nlattr_to_range = nf_nat_port_nlattr_to_range,
++ .range_to_nlattr = nf_nat_proto_range_to_nlattr,
++ .nlattr_to_range = nf_nat_proto_nlattr_to_range,
+ #endif
+ };
+diff --git a/net/ipv4/netfilter/nf_nat_proto_udplite.c b/net/ipv4/netfilter/nf_nat_proto_udplite.c
+new file mode 100644
+index 0000000..440a229
+--- /dev/null
++++ b/net/ipv4/netfilter/nf_nat_proto_udplite.c
+@@ -0,0 +1,99 @@
++/* (C) 1999-2001 Paul `Rusty' Russell
++ * (C) 2002-2006 Netfilter Core Team <coreteam at netfilter.org>
++ * (C) 2008 Patrick McHardy <kaber at trash.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/types.h>
++#include <linux/init.h>
++#include <linux/ip.h>
++#include <linux/udp.h>
++
++#include <linux/netfilter.h>
++#include <net/netfilter/nf_nat.h>
++#include <net/netfilter/nf_nat_protocol.h>
++
++static u_int16_t udplite_port_rover;
++
++static bool
++udplite_unique_tuple(struct nf_conntrack_tuple *tuple,
++ const struct nf_nat_range *range,
++ enum nf_nat_manip_type maniptype,
++ const struct nf_conn *ct)
++{
++ return nf_nat_proto_unique_tuple(tuple, range, maniptype, ct,
++ &udplite_port_rover);
++}
++
++static bool
++udplite_manip_pkt(struct sk_buff *skb,
++ unsigned int iphdroff,
++ const struct nf_conntrack_tuple *tuple,
++ enum nf_nat_manip_type maniptype)
++{
++ const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
++ struct udphdr *hdr;
++ unsigned int hdroff = iphdroff + iph->ihl*4;
++ __be32 oldip, newip;
++ __be16 *portptr, newport;
++
++ if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
++ return false;
++
++ iph = (struct iphdr *)(skb->data + iphdroff);
++ hdr = (struct udphdr *)(skb->data + hdroff);
++
++ if (maniptype == IP_NAT_MANIP_SRC) {
++ /* Get rid of src ip and src pt */
++ oldip = iph->saddr;
++ newip = tuple->src.u3.ip;
++ newport = tuple->src.u.udp.port;
++ portptr = &hdr->source;
++ } else {
++ /* Get rid of dst ip and dst pt */
++ oldip = iph->daddr;
++ newip = tuple->dst.u3.ip;
++ newport = tuple->dst.u.udp.port;
++ portptr = &hdr->dest;
++ }
++
++ inet_proto_csum_replace4(&hdr->check, skb, oldip, newip, 1);
++ inet_proto_csum_replace2(&hdr->check, skb, *portptr, newport, 0);
++ if (!hdr->check)
++ hdr->check = CSUM_MANGLED_0;
++
++ *portptr = newport;
++ return true;
++}
++
++static const struct nf_nat_protocol nf_nat_protocol_udplite = {
++ .protonum = IPPROTO_UDPLITE,
++ .me = THIS_MODULE,
++ .manip_pkt = udplite_manip_pkt,
++ .in_range = nf_nat_proto_in_range,
++ .unique_tuple = udplite_unique_tuple,
++#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
++ .range_to_nlattr = nf_nat_proto_range_to_nlattr,
++ .nlattr_to_range = nf_nat_proto_nlattr_to_range,
++#endif
++};
++
++static int __init nf_nat_proto_udplite_init(void)
++{
++ return nf_nat_protocol_register(&nf_nat_protocol_udplite);
++}
++
++static void __exit nf_nat_proto_udplite_fini(void)
++{
++ nf_nat_protocol_unregister(&nf_nat_protocol_udplite);
++}
++
++module_init(nf_nat_proto_udplite_init);
++module_exit(nf_nat_proto_udplite_fini);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("UDP-Lite NAT protocol helper");
++MODULE_AUTHOR("Patrick McHardy <kaber at trash.net>");
+diff --git a/net/ipv4/netfilter/nf_nat_proto_unknown.c b/net/ipv4/netfilter/nf_nat_proto_unknown.c
+index a26efeb..14381c6 100644
+--- a/net/ipv4/netfilter/nf_nat_proto_unknown.c
++++ b/net/ipv4/netfilter/nf_nat_proto_unknown.c
+@@ -18,35 +18,34 @@
+ #include <net/netfilter/nf_nat_rule.h>
+ #include <net/netfilter/nf_nat_protocol.h>
+
+-static int unknown_in_range(const struct nf_conntrack_tuple *tuple,
+- enum nf_nat_manip_type manip_type,
+- const union nf_conntrack_man_proto *min,
+- const union nf_conntrack_man_proto *max)
++static bool unknown_in_range(const struct nf_conntrack_tuple *tuple,
++ enum nf_nat_manip_type manip_type,
++ const union nf_conntrack_man_proto *min,
++ const union nf_conntrack_man_proto *max)
+ {
+- return 1;
++ return true;
+ }
+
+-static int unknown_unique_tuple(struct nf_conntrack_tuple *tuple,
+- const struct nf_nat_range *range,
+- enum nf_nat_manip_type maniptype,
+- const struct nf_conn *ct)
++static bool unknown_unique_tuple(struct nf_conntrack_tuple *tuple,
++ const struct nf_nat_range *range,
++ enum nf_nat_manip_type maniptype,
++ const struct nf_conn *ct)
+ {
+ /* Sorry: we can't help you; if it's not unique, we can't frob
+ anything. */
+- return 0;
++ return false;
+ }
+
+-static int
++static bool
+ unknown_manip_pkt(struct sk_buff *skb,
+ unsigned int iphdroff,
+ const struct nf_conntrack_tuple *tuple,
+ enum nf_nat_manip_type maniptype)
+ {
+- return 1;
++ return true;
+ }
+
+ const struct nf_nat_protocol nf_nat_unknown_protocol = {
+- .name = "unknown",
+ /* .me isn't set: getting a ref to this cannot fail. */
+ .manip_pkt = unknown_manip_pkt,
+ .in_range = unknown_in_range,
+diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
+index f8fda57..e8b4d0d 100644
+--- a/net/ipv4/netfilter/nf_nat_rule.c
++++ b/net/ipv4/netfilter/nf_nat_rule.c
+@@ -61,7 +61,7 @@ static struct
+ static struct xt_table __nat_table = {
+ .name = "nat",
+ .valid_hooks = NAT_VALID_HOOKS,
+- .lock = RW_LOCK_UNLOCKED,
++ .lock = __RW_LOCK_UNLOCKED(__nat_table.lock),
+ .me = THIS_MODULE,
+ .af = AF_INET,
+ };
+@@ -143,7 +143,7 @@ static bool ipt_snat_checkentry(const char *tablename,
+ void *targinfo,
+ unsigned int hook_mask)
+ {
+- struct nf_nat_multi_range_compat *mr = targinfo;
++ const struct nf_nat_multi_range_compat *mr = targinfo;
+
+ /* Must be a valid range */
+ if (mr->rangesize != 1) {
+@@ -159,7 +159,7 @@ static bool ipt_dnat_checkentry(const char *tablename,
+ void *targinfo,
+ unsigned int hook_mask)
+ {
+- struct nf_nat_multi_range_compat *mr = targinfo;
++ const struct nf_nat_multi_range_compat *mr = targinfo;
+
+ /* Must be a valid range */
+ if (mr->rangesize != 1) {
+@@ -188,25 +188,6 @@ alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
+ return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum));
+ }
+
+-unsigned int
+-alloc_null_binding_confirmed(struct nf_conn *ct, unsigned int hooknum)
+-{
+- __be32 ip
+- = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
+- ? ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip
+- : ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip);
+- __be16 all
+- = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
+- ? ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.all
+- : ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.all);
+- struct nf_nat_range range
+- = { IP_NAT_RANGE_MAP_IPS, ip, ip, { all }, { all } };
+-
+- pr_debug("Allocating NULL binding for confirmed %p (%u.%u.%u.%u)\n",
+- ct, NIPQUAD(ip));
+- return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum));
+-}
+-
+ int nf_nat_rule_find(struct sk_buff *skb,
+ unsigned int hooknum,
+ const struct net_device *in,
+diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
+index b4c8d49..4334d5c 100644
+--- a/net/ipv4/netfilter/nf_nat_sip.c
++++ b/net/ipv4/netfilter/nf_nat_sip.c
+@@ -2,6 +2,8 @@
+ *
+ * (C) 2005 by Christian Hentschel <chentschel at arnet.com.ar>
+ * based on RR's ip_nat_ftp.c and other modules.
++ * (C) 2007 United Security Providers
++ * (C) 2007, 2008 Patrick McHardy <kaber at trash.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+@@ -26,275 +28,461 @@ MODULE_AUTHOR("Christian Hentschel <chentschel at arnet.com.ar>");
+ MODULE_DESCRIPTION("SIP NAT helper");
+ MODULE_ALIAS("ip_nat_sip");
+
+-struct addr_map {
+- struct {
+- char src[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
+- char dst[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
+- unsigned int srclen, srciplen;
+- unsigned int dstlen, dstiplen;
+- } addr[IP_CT_DIR_MAX];
+-};
+
+-static void addr_map_init(const struct nf_conn *ct, struct addr_map *map)
++static unsigned int mangle_packet(struct sk_buff *skb,
++ const char **dptr, unsigned int *datalen,
++ unsigned int matchoff, unsigned int matchlen,
++ const char *buffer, unsigned int buflen)
+ {
+- const struct nf_conntrack_tuple *t;
+- enum ip_conntrack_dir dir;
+- unsigned int n;
+-
+- for (dir = 0; dir < IP_CT_DIR_MAX; dir++) {
+- t = &ct->tuplehash[dir].tuple;
+-
+- n = sprintf(map->addr[dir].src, "%u.%u.%u.%u",
+- NIPQUAD(t->src.u3.ip));
+- map->addr[dir].srciplen = n;
+- n += sprintf(map->addr[dir].src + n, ":%u",
+- ntohs(t->src.u.udp.port));
+- map->addr[dir].srclen = n;
+-
+- n = sprintf(map->addr[dir].dst, "%u.%u.%u.%u",
+- NIPQUAD(t->dst.u3.ip));
+- map->addr[dir].dstiplen = n;
+- n += sprintf(map->addr[dir].dst + n, ":%u",
+- ntohs(t->dst.u.udp.port));
+- map->addr[dir].dstlen = n;
+- }
++ enum ip_conntrack_info ctinfo;
++ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++
++ if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, matchoff, matchlen,
++ buffer, buflen))
++ return 0;
++
++ /* Reload data pointer and adjust datalen value */
++ *dptr = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr);
++ *datalen += buflen - matchlen;
++ return 1;
+ }
+
+-static int map_sip_addr(struct sk_buff *skb, enum ip_conntrack_info ctinfo,
+- struct nf_conn *ct, const char **dptr, size_t dlen,
+- enum sip_header_pos pos, struct addr_map *map)
++static int map_addr(struct sk_buff *skb,
++ const char **dptr, unsigned int *datalen,
++ unsigned int matchoff, unsigned int matchlen,
++ union nf_inet_addr *addr, __be16 port)
+ {
++ enum ip_conntrack_info ctinfo;
++ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+- unsigned int matchlen, matchoff, addrlen;
+- char *addr;
+-
+- if (ct_sip_get_info(ct, *dptr, dlen, &matchoff, &matchlen, pos) <= 0)
++ char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
++ unsigned int buflen;
++ __be32 newaddr;
++ __be16 newport;
++
++ if (ct->tuplehash[dir].tuple.src.u3.ip == addr->ip &&
++ ct->tuplehash[dir].tuple.src.u.udp.port == port) {
++ newaddr = ct->tuplehash[!dir].tuple.dst.u3.ip;
++ newport = ct->tuplehash[!dir].tuple.dst.u.udp.port;
++ } else if (ct->tuplehash[dir].tuple.dst.u3.ip == addr->ip &&
++ ct->tuplehash[dir].tuple.dst.u.udp.port == port) {
++ newaddr = ct->tuplehash[!dir].tuple.src.u3.ip;
++ newport = ct->tuplehash[!dir].tuple.src.u.udp.port;
++ } else
+ return 1;
+
+- if ((matchlen == map->addr[dir].srciplen ||
+- matchlen == map->addr[dir].srclen) &&
+- memcmp(*dptr + matchoff, map->addr[dir].src, matchlen) == 0) {
+- addr = map->addr[!dir].dst;
+- addrlen = map->addr[!dir].dstlen;
+- } else if ((matchlen == map->addr[dir].dstiplen ||
+- matchlen == map->addr[dir].dstlen) &&
+- memcmp(*dptr + matchoff, map->addr[dir].dst, matchlen) == 0) {
+- addr = map->addr[!dir].src;
+- addrlen = map->addr[!dir].srclen;
+- } else
++ if (newaddr == addr->ip && newport == port)
+ return 1;
+
+- if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo,
+- matchoff, matchlen, addr, addrlen))
+- return 0;
+- *dptr = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr);
+- return 1;
++ buflen = sprintf(buffer, "%u.%u.%u.%u:%u",
++ NIPQUAD(newaddr), ntohs(newport));
+
++ return mangle_packet(skb, dptr, datalen, matchoff, matchlen,
++ buffer, buflen);
+ }
+
+-static unsigned int ip_nat_sip(struct sk_buff *skb,
+- enum ip_conntrack_info ctinfo,
+- struct nf_conn *ct,
+- const char **dptr)
++static int map_sip_addr(struct sk_buff *skb,
++ const char **dptr, unsigned int *datalen,
++ enum sip_header_types type)
+ {
+- enum sip_header_pos pos;
+- struct addr_map map;
+- int dataoff, datalen;
++ enum ip_conntrack_info ctinfo;
++ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++ unsigned int matchlen, matchoff;
++ union nf_inet_addr addr;
++ __be16 port;
+
+- dataoff = ip_hdrlen(skb) + sizeof(struct udphdr);
+- datalen = skb->len - dataoff;
+- if (datalen < sizeof("SIP/2.0") - 1)
+- return NF_ACCEPT;
++ if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, type, NULL,
++ &matchoff, &matchlen, &addr, &port) <= 0)
++ return 1;
++ return map_addr(skb, dptr, datalen, matchoff, matchlen, &addr, port);
++}
+
+- addr_map_init(ct, &map);
++static unsigned int ip_nat_sip(struct sk_buff *skb,
++ const char **dptr, unsigned int *datalen)
++{
++ enum ip_conntrack_info ctinfo;
++ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
++ unsigned int dataoff, matchoff, matchlen;
++ union nf_inet_addr addr;
++ __be16 port;
++ int request, in_header;
+
+ /* Basic rules: requests and responses. */
+- if (strncmp(*dptr, "SIP/2.0", sizeof("SIP/2.0") - 1) != 0) {
+- /* 10.2: Constructing the REGISTER Request:
+- *
+- * The "userinfo" and "@" components of the SIP URI MUST NOT
+- * be present.
+- */
+- if (datalen >= sizeof("REGISTER") - 1 &&
+- strncmp(*dptr, "REGISTER", sizeof("REGISTER") - 1) == 0)
+- pos = POS_REG_REQ_URI;
+- else
+- pos = POS_REQ_URI;
+-
+- if (!map_sip_addr(skb, ctinfo, ct, dptr, datalen, pos, &map))
++ if (strnicmp(*dptr, "SIP/2.0", strlen("SIP/2.0")) != 0) {
++ if (ct_sip_parse_request(ct, *dptr, *datalen,
++ &matchoff, &matchlen,
++ &addr, &port) > 0 &&
++ !map_addr(skb, dptr, datalen, matchoff, matchlen,
++ &addr, port))
++ return NF_DROP;
++ request = 1;
++ } else
++ request = 0;
++
++ /* Translate topmost Via header and parameters */
++ if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen,
++ SIP_HDR_VIA, NULL, &matchoff, &matchlen,
++ &addr, &port) > 0) {
++ unsigned int matchend, poff, plen, buflen, n;
++ char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
++
++ /* We're only interested in headers related to this
++ * connection */
++ if (request) {
++ if (addr.ip != ct->tuplehash[dir].tuple.src.u3.ip ||
++ port != ct->tuplehash[dir].tuple.src.u.udp.port)
++ goto next;
++ } else {
++ if (addr.ip != ct->tuplehash[dir].tuple.dst.u3.ip ||
++ port != ct->tuplehash[dir].tuple.dst.u.udp.port)
++ goto next;
++ }
++
++ if (!map_addr(skb, dptr, datalen, matchoff, matchlen,
++ &addr, port))
+ return NF_DROP;
++
++ matchend = matchoff + matchlen;
++
++ /* The maddr= parameter (RFC 2361) specifies where to send
++ * the reply. */
++ if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen,
++ "maddr=", &poff, &plen,
++ &addr) > 0 &&
++ addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
++ addr.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) {
++ __be32 ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
++ buflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip));
++ if (!mangle_packet(skb, dptr, datalen, poff, plen,
++ buffer, buflen))
++ return NF_DROP;
++ }
++
++ /* The received= parameter (RFC 2361) contains the address
++ * from which the server received the request. */
++ if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen,
++ "received=", &poff, &plen,
++ &addr) > 0 &&
++ addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip &&
++ addr.ip != ct->tuplehash[!dir].tuple.src.u3.ip) {
++ __be32 ip = ct->tuplehash[!dir].tuple.src.u3.ip;
++ buflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip));
++ if (!mangle_packet(skb, dptr, datalen, poff, plen,
++ buffer, buflen))
++ return NF_DROP;
++ }
++
++ /* The rport= parameter (RFC 3581) contains the port number
++ * from which the server received the request. */
++ if (ct_sip_parse_numerical_param(ct, *dptr, matchend, *datalen,
++ "rport=", &poff, &plen,
++ &n) > 0 &&
++ htons(n) == ct->tuplehash[dir].tuple.dst.u.udp.port &&
++ htons(n) != ct->tuplehash[!dir].tuple.src.u.udp.port) {
++ __be16 p = ct->tuplehash[!dir].tuple.src.u.udp.port;
++ buflen = sprintf(buffer, "%u", ntohs(p));
++ if (!mangle_packet(skb, dptr, datalen, poff, plen,
++ buffer, buflen))
++ return NF_DROP;
++ }
+ }
+
+- if (!map_sip_addr(skb, ctinfo, ct, dptr, datalen, POS_FROM, &map) ||
+- !map_sip_addr(skb, ctinfo, ct, dptr, datalen, POS_TO, &map) ||
+- !map_sip_addr(skb, ctinfo, ct, dptr, datalen, POS_VIA, &map) ||
+- !map_sip_addr(skb, ctinfo, ct, dptr, datalen, POS_CONTACT, &map))
++next:
++ /* Translate Contact headers */
++ dataoff = 0;
++ in_header = 0;
++ while (ct_sip_parse_header_uri(ct, *dptr, &dataoff, *datalen,
++ SIP_HDR_CONTACT, &in_header,
++ &matchoff, &matchlen,
++ &addr, &port) > 0) {
++ if (!map_addr(skb, dptr, datalen, matchoff, matchlen,
++ &addr, port))
++ return NF_DROP;
++ }
++
++ if (!map_sip_addr(skb, dptr, datalen, SIP_HDR_FROM) ||
++ !map_sip_addr(skb, dptr, datalen, SIP_HDR_TO))
+ return NF_DROP;
+ return NF_ACCEPT;
+ }
+
+-static unsigned int mangle_sip_packet(struct sk_buff *skb,
+- enum ip_conntrack_info ctinfo,
+- struct nf_conn *ct,
+- const char **dptr, size_t dlen,
+- char *buffer, int bufflen,
+- enum sip_header_pos pos)
++/* Handles expected signalling connections and media streams */
++static void ip_nat_sip_expected(struct nf_conn *ct,
++ struct nf_conntrack_expect *exp)
+ {
+- unsigned int matchlen, matchoff;
++ struct nf_nat_range range;
+
+- if (ct_sip_get_info(ct, *dptr, dlen, &matchoff, &matchlen, pos) <= 0)
+- return 0;
++ /* This must be a fresh one. */
++ BUG_ON(ct->status & IPS_NAT_DONE_MASK);
+
+- if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo,
+- matchoff, matchlen, buffer, bufflen))
+- return 0;
++ /* For DST manip, map port here to where it's expected. */
++ range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
++ range.min = range.max = exp->saved_proto;
++ range.min_ip = range.max_ip = exp->saved_ip;
++ nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST);
+
+- /* We need to reload this. Thanks Patrick. */
+- *dptr = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr);
+- return 1;
++ /* Change src to where master sends to, but only if the connection
++ * actually came from the same source. */
++ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip ==
++ ct->master->tuplehash[exp->dir].tuple.src.u3.ip) {
++ range.flags = IP_NAT_RANGE_MAP_IPS;
++ range.min_ip = range.max_ip
++ = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip;
++ nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC);
++ }
+ }
+
+-static int mangle_content_len(struct sk_buff *skb,
+- enum ip_conntrack_info ctinfo,
+- struct nf_conn *ct,
+- const char *dptr)
++static unsigned int ip_nat_sip_expect(struct sk_buff *skb,
++ const char **dptr, unsigned int *datalen,
++ struct nf_conntrack_expect *exp,
++ unsigned int matchoff,
++ unsigned int matchlen)
+ {
+- unsigned int dataoff, matchoff, matchlen;
+- char buffer[sizeof("65536")];
+- int bufflen;
++ enum ip_conntrack_info ctinfo;
++ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
++ __be32 newip;
++ u_int16_t port;
++ char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
++ unsigned buflen;
+
+- dataoff = ip_hdrlen(skb) + sizeof(struct udphdr);
++ /* Connection will come from reply */
++ if (ct->tuplehash[dir].tuple.src.u3.ip == ct->tuplehash[!dir].tuple.dst.u3.ip)
++ newip = exp->tuple.dst.u3.ip;
++ else
++ newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
+
+- /* Get actual SDP length */
+- if (ct_sip_get_info(ct, dptr, skb->len - dataoff, &matchoff,
+- &matchlen, POS_SDP_HEADER) > 0) {
++ /* If the signalling port matches the connection's source port in the
++ * original direction, try to use the destination port in the opposite
++ * direction. */
++ if (exp->tuple.dst.u.udp.port ==
++ ct->tuplehash[dir].tuple.src.u.udp.port)
++ port = ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port);
++ else
++ port = ntohs(exp->tuple.dst.u.udp.port);
++
++ exp->saved_ip = exp->tuple.dst.u3.ip;
++ exp->tuple.dst.u3.ip = newip;
++ exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port;
++ exp->dir = !dir;
++ exp->expectfn = ip_nat_sip_expected;
+
+- /* since ct_sip_get_info() give us a pointer passing 'v='
+- we need to add 2 bytes in this count. */
+- int c_len = skb->len - dataoff - matchoff + 2;
++ for (; port != 0; port++) {
++ exp->tuple.dst.u.udp.port = htons(port);
++ if (nf_ct_expect_related(exp) == 0)
++ break;
++ }
+
+- /* Now, update SDP length */
+- if (ct_sip_get_info(ct, dptr, skb->len - dataoff, &matchoff,
+- &matchlen, POS_CONTENT) > 0) {
++ if (port == 0)
++ return NF_DROP;
+
+- bufflen = sprintf(buffer, "%u", c_len);
+- return nf_nat_mangle_udp_packet(skb, ct, ctinfo,
+- matchoff, matchlen,
+- buffer, bufflen);
+- }
++ if (exp->tuple.dst.u3.ip != exp->saved_ip ||
++ exp->tuple.dst.u.udp.port != exp->saved_proto.udp.port) {
++ buflen = sprintf(buffer, "%u.%u.%u.%u:%u",
++ NIPQUAD(newip), port);
++ if (!mangle_packet(skb, dptr, datalen, matchoff, matchlen,
++ buffer, buflen))
++ goto err;
+ }
+- return 0;
++ return NF_ACCEPT;
++
++err:
++ nf_ct_unexpect_related(exp);
++ return NF_DROP;
+ }
+
+-static unsigned int mangle_sdp(struct sk_buff *skb,
+- enum ip_conntrack_info ctinfo,
+- struct nf_conn *ct,
+- __be32 newip, u_int16_t port,
+- const char *dptr)
++static int mangle_content_len(struct sk_buff *skb,
++ const char **dptr, unsigned int *datalen)
+ {
+- char buffer[sizeof("nnn.nnn.nnn.nnn")];
+- unsigned int dataoff, bufflen;
++ enum ip_conntrack_info ctinfo;
++ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++ unsigned int matchoff, matchlen;
++ char buffer[sizeof("65536")];
++ int buflen, c_len;
+
+- dataoff = ip_hdrlen(skb) + sizeof(struct udphdr);
++ /* Get actual SDP length */
++ if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen,
++ SDP_HDR_VERSION, SDP_HDR_UNSPEC,
++ &matchoff, &matchlen) <= 0)
++ return 0;
++ c_len = *datalen - matchoff + strlen("v=");
+
+- /* Mangle owner and contact info. */
+- bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip));
+- if (!mangle_sip_packet(skb, ctinfo, ct, &dptr, skb->len - dataoff,
+- buffer, bufflen, POS_OWNER_IP4))
++ /* Now, update SDP length */
++ if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CONTENT_LENGTH,
++ &matchoff, &matchlen) <= 0)
+ return 0;
+
+- if (!mangle_sip_packet(skb, ctinfo, ct, &dptr, skb->len - dataoff,
+- buffer, bufflen, POS_CONNECTION_IP4))
++ buflen = sprintf(buffer, "%u", c_len);
++ return mangle_packet(skb, dptr, datalen, matchoff, matchlen,
++ buffer, buflen);
++}
++
++static unsigned mangle_sdp_packet(struct sk_buff *skb, const char **dptr,
++ unsigned int dataoff, unsigned int *datalen,
++ enum sdp_header_types type,
++ enum sdp_header_types term,
++ char *buffer, int buflen)
++{
++ enum ip_conntrack_info ctinfo;
++ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++ unsigned int matchlen, matchoff;
++
++ if (ct_sip_get_sdp_header(ct, *dptr, dataoff, *datalen, type, term,
++ &matchoff, &matchlen) <= 0)
+ return 0;
++ return mangle_packet(skb, dptr, datalen, matchoff, matchlen,
++ buffer, buflen);
++}
+
+- /* Mangle media port. */
+- bufflen = sprintf(buffer, "%u", port);
+- if (!mangle_sip_packet(skb, ctinfo, ct, &dptr, skb->len - dataoff,
+- buffer, bufflen, POS_MEDIA))
++static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, const char **dptr,
++ unsigned int dataoff,
++ unsigned int *datalen,
++ enum sdp_header_types type,
++ enum sdp_header_types term,
++ const union nf_inet_addr *addr)
++{
++ char buffer[sizeof("nnn.nnn.nnn.nnn")];
++ unsigned int buflen;
++
++ buflen = sprintf(buffer, NIPQUAD_FMT, NIPQUAD(addr->ip));
++ if (!mangle_sdp_packet(skb, dptr, dataoff, datalen, type, term,
++ buffer, buflen))
+ return 0;
+
+- return mangle_content_len(skb, ctinfo, ct, dptr);
++ return mangle_content_len(skb, dptr, datalen);
+ }
+
+-static void ip_nat_sdp_expect(struct nf_conn *ct,
+- struct nf_conntrack_expect *exp)
++static unsigned int ip_nat_sdp_port(struct sk_buff *skb,
++ const char **dptr,
++ unsigned int *datalen,
++ unsigned int matchoff,
++ unsigned int matchlen,
++ u_int16_t port)
+ {
+- struct nf_nat_range range;
++ char buffer[sizeof("nnnnn")];
++ unsigned int buflen;
+
+- /* This must be a fresh one. */
+- BUG_ON(ct->status & IPS_NAT_DONE_MASK);
++ buflen = sprintf(buffer, "%u", port);
++ if (!mangle_packet(skb, dptr, datalen, matchoff, matchlen,
++ buffer, buflen))
++ return 0;
+
+- /* Change src to where master sends to */
+- range.flags = IP_NAT_RANGE_MAP_IPS;
+- range.min_ip = range.max_ip
+- = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip;
+- nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC);
++ return mangle_content_len(skb, dptr, datalen);
++}
+
+- /* For DST manip, map port here to where it's expected. */
+- range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
+- range.min = range.max = exp->saved_proto;
+- range.min_ip = range.max_ip = exp->saved_ip;
+- nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST);
++static unsigned int ip_nat_sdp_session(struct sk_buff *skb, const char **dptr,
++ unsigned int dataoff,
++ unsigned int *datalen,
++ const union nf_inet_addr *addr)
++{
++ char buffer[sizeof("nnn.nnn.nnn.nnn")];
++ unsigned int buflen;
++
++ /* Mangle session description owner and contact addresses */
++ buflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(addr->ip));
++ if (!mangle_sdp_packet(skb, dptr, dataoff, datalen,
++ SDP_HDR_OWNER_IP4, SDP_HDR_MEDIA,
++ buffer, buflen))
++ return 0;
++
++ if (!mangle_sdp_packet(skb, dptr, dataoff, datalen,
++ SDP_HDR_CONNECTION_IP4, SDP_HDR_MEDIA,
++ buffer, buflen))
++ return 0;
++
++ return mangle_content_len(skb, dptr, datalen);
+ }
+
+ /* So, this packet has hit the connection tracking matching code.
+ Mangle it, and change the expectation to match the new version. */
+-static unsigned int ip_nat_sdp(struct sk_buff *skb,
+- enum ip_conntrack_info ctinfo,
+- struct nf_conntrack_expect *exp,
+- const char *dptr)
++static unsigned int ip_nat_sdp_media(struct sk_buff *skb,
++ const char **dptr,
++ unsigned int *datalen,
++ struct nf_conntrack_expect *rtp_exp,
++ struct nf_conntrack_expect *rtcp_exp,
++ unsigned int mediaoff,
++ unsigned int medialen,
++ union nf_inet_addr *rtp_addr)
+ {
+- struct nf_conn *ct = exp->master;
++ enum ip_conntrack_info ctinfo;
++ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+- __be32 newip;
+ u_int16_t port;
+
+ /* Connection will come from reply */
+ if (ct->tuplehash[dir].tuple.src.u3.ip ==
+ ct->tuplehash[!dir].tuple.dst.u3.ip)
+- newip = exp->tuple.dst.u3.ip;
++ rtp_addr->ip = rtp_exp->tuple.dst.u3.ip;
+ else
+- newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
+-
+- exp->saved_ip = exp->tuple.dst.u3.ip;
+- exp->tuple.dst.u3.ip = newip;
+- exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port;
+- exp->dir = !dir;
+-
+- /* When you see the packet, we need to NAT it the same as the
+- this one. */
+- exp->expectfn = ip_nat_sdp_expect;
+-
+- /* Try to get same port: if not, try to change it. */
+- for (port = ntohs(exp->saved_proto.udp.port); port != 0; port++) {
+- exp->tuple.dst.u.udp.port = htons(port);
+- if (nf_ct_expect_related(exp) == 0)
++ rtp_addr->ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
++
++ rtp_exp->saved_ip = rtp_exp->tuple.dst.u3.ip;
++ rtp_exp->tuple.dst.u3.ip = rtp_addr->ip;
++ rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
++ rtp_exp->dir = !dir;
++ rtp_exp->expectfn = ip_nat_sip_expected;
++
++ rtcp_exp->saved_ip = rtcp_exp->tuple.dst.u3.ip;
++ rtcp_exp->tuple.dst.u3.ip = rtp_addr->ip;
++ rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;
++ rtcp_exp->dir = !dir;
++ rtcp_exp->expectfn = ip_nat_sip_expected;
++
++ /* Try to get same pair of ports: if not, try to change them. */
++ for (port = ntohs(rtp_exp->tuple.dst.u.udp.port);
++ port != 0; port += 2) {
++ rtp_exp->tuple.dst.u.udp.port = htons(port);
++ if (nf_ct_expect_related(rtp_exp) != 0)
++ continue;
++ rtcp_exp->tuple.dst.u.udp.port = htons(port + 1);
++ if (nf_ct_expect_related(rtcp_exp) == 0)
+ break;
++ nf_ct_unexpect_related(rtp_exp);
+ }
+
+ if (port == 0)
+- return NF_DROP;
++ goto err1;
++
++ /* Update media port. */
++ if (rtp_exp->tuple.dst.u.udp.port != rtp_exp->saved_proto.udp.port &&
++ !ip_nat_sdp_port(skb, dptr, datalen, mediaoff, medialen, port))
++ goto err2;
+
+- if (!mangle_sdp(skb, ctinfo, ct, newip, port, dptr)) {
+- nf_ct_unexpect_related(exp);
+- return NF_DROP;
+- }
+ return NF_ACCEPT;
++
++err2:
++ nf_ct_unexpect_related(rtp_exp);
++ nf_ct_unexpect_related(rtcp_exp);
++err1:
++ return NF_DROP;
+ }
+
+ static void __exit nf_nat_sip_fini(void)
+ {
+ rcu_assign_pointer(nf_nat_sip_hook, NULL);
+- rcu_assign_pointer(nf_nat_sdp_hook, NULL);
++ rcu_assign_pointer(nf_nat_sip_expect_hook, NULL);
++ rcu_assign_pointer(nf_nat_sdp_addr_hook, NULL);
++ rcu_assign_pointer(nf_nat_sdp_port_hook, NULL);
++ rcu_assign_pointer(nf_nat_sdp_session_hook, NULL);
++ rcu_assign_pointer(nf_nat_sdp_media_hook, NULL);
+ synchronize_rcu();
+ }
+
+ static int __init nf_nat_sip_init(void)
+ {
+ BUG_ON(nf_nat_sip_hook != NULL);
+- BUG_ON(nf_nat_sdp_hook != NULL);
++ BUG_ON(nf_nat_sip_expect_hook != NULL);
++ BUG_ON(nf_nat_sdp_addr_hook != NULL);
++ BUG_ON(nf_nat_sdp_port_hook != NULL);
++ BUG_ON(nf_nat_sdp_session_hook != NULL);
++ BUG_ON(nf_nat_sdp_media_hook != NULL);
+ rcu_assign_pointer(nf_nat_sip_hook, ip_nat_sip);
+- rcu_assign_pointer(nf_nat_sdp_hook, ip_nat_sdp);
++ rcu_assign_pointer(nf_nat_sip_expect_hook, ip_nat_sip_expect);
++ rcu_assign_pointer(nf_nat_sdp_addr_hook, ip_nat_sdp_addr);
++ rcu_assign_pointer(nf_nat_sdp_port_hook, ip_nat_sdp_port);
++ rcu_assign_pointer(nf_nat_sdp_session_hook, ip_nat_sdp_session);
++ rcu_assign_pointer(nf_nat_sdp_media_hook, ip_nat_sdp_media);
+ return 0;
+ }
+
+diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c
+index 540ce6a..5daefad 100644
+--- a/net/ipv4/netfilter/nf_nat_snmp_basic.c
++++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c
+@@ -50,6 +50,7 @@
+ #include <net/udp.h>
+
+ #include <net/netfilter/nf_nat.h>
++#include <net/netfilter/nf_conntrack_expect.h>
+ #include <net/netfilter/nf_conntrack_helper.h>
+ #include <net/netfilter/nf_nat_helper.h>
+
+@@ -219,7 +220,7 @@ static unsigned char asn1_length_decode(struct asn1_ctx *ctx,
+ if (ch < 0x80)
+ *len = ch;
+ else {
+- cnt = (unsigned char) (ch & 0x7F);
++ cnt = ch & 0x7F;
+ *len = 0;
+
+ while (cnt > 0) {
+@@ -617,8 +618,7 @@ struct snmp_cnv
+ int syntax;
+ };
+
+-static struct snmp_cnv snmp_conv [] =
+-{
++static const struct snmp_cnv snmp_conv[] = {
+ {ASN1_UNI, ASN1_NUL, SNMP_NULL},
+ {ASN1_UNI, ASN1_INT, SNMP_INTEGER},
+ {ASN1_UNI, ASN1_OTS, SNMP_OCTETSTR},
+@@ -643,7 +643,7 @@ static unsigned char snmp_tag_cls2syntax(unsigned int tag,
+ unsigned int cls,
+ unsigned short *syntax)
+ {
+- struct snmp_cnv *cnv;
++ const struct snmp_cnv *cnv;
+
+ cnv = snmp_conv;
+
+@@ -903,7 +903,7 @@ static inline void mangle_address(unsigned char *begin,
+ u_int32_t old;
+
+ if (debug)
+- memcpy(&old, (unsigned char *)addr, sizeof(old));
++ memcpy(&old, addr, sizeof(old));
+
+ *addr = map->to;
+
+@@ -998,7 +998,7 @@ err_id_free:
+ *
+ *****************************************************************************/
+
+-static void hex_dump(unsigned char *buf, size_t len)
++static void hex_dump(const unsigned char *buf, size_t len)
+ {
+ size_t i;
+
+@@ -1079,7 +1079,7 @@ static int snmp_parse_mangle(unsigned char *msg,
+ if (cls != ASN1_CTX || con != ASN1_CON)
+ return 0;
+ if (debug > 1) {
+- unsigned char *pdus[] = {
++ static const unsigned char *const pdus[] = {
+ [SNMP_PDU_GET] = "get",
+ [SNMP_PDU_NEXT] = "get-next",
+ [SNMP_PDU_RESPONSE] = "response",
+@@ -1231,8 +1231,8 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+ {
+ int dir = CTINFO2DIR(ctinfo);
+ unsigned int ret;
+- struct iphdr *iph = ip_hdr(skb);
+- struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
++ const struct iphdr *iph = ip_hdr(skb);
++ const struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl);
+
+ /* SNMP replies and originating SNMP traps get mangled */
+ if (udph->source == htons(SNMP_PORT) && dir != IP_CT_DIR_REPLY)
+@@ -1267,11 +1267,15 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+ return ret;
+ }
+
++static const struct nf_conntrack_expect_policy snmp_exp_policy = {
++ .max_expected = 0,
++ .timeout = 180,
++};
++
+ static struct nf_conntrack_helper snmp_helper __read_mostly = {
+- .max_expected = 0,
+- .timeout = 180,
+ .me = THIS_MODULE,
+ .help = help,
++ .expect_policy = &snmp_exp_policy,
+ .name = "snmp",
+ .tuple.src.l3num = AF_INET,
+ .tuple.src.u.udp.port = __constant_htons(SNMP_PORT),
+@@ -1279,10 +1283,9 @@ static struct nf_conntrack_helper snmp_helper __read_mostly = {
+ };
+
+ static struct nf_conntrack_helper snmp_trap_helper __read_mostly = {
+- .max_expected = 0,
+- .timeout = 180,
+ .me = THIS_MODULE,
+ .help = help,
++ .expect_policy = &snmp_exp_policy,
+ .name = "snmp_trap",
+ .tuple.src.l3num = AF_INET,
+ .tuple.src.u.udp.port = __constant_htons(SNMP_TRAP_PORT),
+diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c
+index 99b2c78..b7dd695 100644
+--- a/net/ipv4/netfilter/nf_nat_standalone.c
++++ b/net/ipv4/netfilter/nf_nat_standalone.c
+@@ -30,8 +30,8 @@
+ #ifdef CONFIG_XFRM
+ static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
+ {
+- struct nf_conn *ct;
+- struct nf_conntrack_tuple *t;
++ const struct nf_conn *ct;
++ const struct nf_conntrack_tuple *t;
+ enum ip_conntrack_info ctinfo;
+ enum ip_conntrack_dir dir;
+ unsigned long statusbit;
+@@ -50,7 +50,10 @@ static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
+ if (ct->status & statusbit) {
+ fl->fl4_dst = t->dst.u3.ip;
+ if (t->dst.protonum == IPPROTO_TCP ||
+- t->dst.protonum == IPPROTO_UDP)
++ t->dst.protonum == IPPROTO_UDP ||
++ t->dst.protonum == IPPROTO_UDPLITE ||
++ t->dst.protonum == IPPROTO_DCCP ||
++ t->dst.protonum == IPPROTO_SCTP)
+ fl->fl_ip_dport = t->dst.u.tcp.port;
+ }
+
+@@ -59,7 +62,10 @@ static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
+ if (ct->status & statusbit) {
+ fl->fl4_src = t->src.u3.ip;
+ if (t->dst.protonum == IPPROTO_TCP ||
+- t->dst.protonum == IPPROTO_UDP)
++ t->dst.protonum == IPPROTO_UDP ||
++ t->dst.protonum == IPPROTO_UDPLITE ||
++ t->dst.protonum == IPPROTO_DCCP ||
++ t->dst.protonum == IPPROTO_SCTP)
+ fl->fl_ip_sport = t->src.u.tcp.port;
+ }
+ }
+@@ -87,21 +93,8 @@ nf_nat_fn(unsigned int hooknum,
+ have dropped it. Hence it's the user's responsibilty to
+ packet filter it out, or implement conntrack/NAT for that
+ protocol. 8) --RR */
+- if (!ct) {
+- /* Exception: ICMP redirect to new connection (not in
+- hash table yet). We must not let this through, in
+- case we're doing NAT to the same network. */
+- if (ip_hdr(skb)->protocol == IPPROTO_ICMP) {
+- struct icmphdr _hdr, *hp;
+-
+- hp = skb_header_pointer(skb, ip_hdrlen(skb),
+- sizeof(_hdr), &_hdr);
+- if (hp != NULL &&
+- hp->type == ICMP_REDIRECT)
+- return NF_DROP;
+- }
++ if (!ct)
+ return NF_ACCEPT;
+- }
+
+ /* Don't try to NAT if this packet is not conntracked */
+ if (ct == &nf_conntrack_untracked)
+@@ -109,6 +102,9 @@ nf_nat_fn(unsigned int hooknum,
+
+ nat = nfct_nat(ct);
+ if (!nat) {
++ /* NAT module was loaded late. */
++ if (nf_ct_is_confirmed(ct))
++ return NF_ACCEPT;
+ nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC);
+ if (nat == NULL) {
+ pr_debug("failed to add NAT extension\n");
+@@ -134,10 +130,7 @@ nf_nat_fn(unsigned int hooknum,
+ if (!nf_nat_initialized(ct, maniptype)) {
+ unsigned int ret;
+
+- if (unlikely(nf_ct_is_confirmed(ct)))
+- /* NAT module was loaded late */
+- ret = alloc_null_binding_confirmed(ct, hooknum);
+- else if (hooknum == NF_INET_LOCAL_IN)
++ if (hooknum == NF_INET_LOCAL_IN)
+ /* LOCAL_IN hook doesn't have a chain! */
+ ret = alloc_null_binding(ct, hooknum);
+ else
+@@ -189,7 +182,7 @@ nf_nat_out(unsigned int hooknum,
+ int (*okfn)(struct sk_buff *))
+ {
+ #ifdef CONFIG_XFRM
+- struct nf_conn *ct;
++ const struct nf_conn *ct;
+ enum ip_conntrack_info ctinfo;
+ #endif
+ unsigned int ret;
+@@ -223,7 +216,7 @@ nf_nat_local_fn(unsigned int hooknum,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+ {
+- struct nf_conn *ct;
++ const struct nf_conn *ct;
+ enum ip_conntrack_info ctinfo;
+ unsigned int ret;
+
+@@ -252,25 +245,6 @@ nf_nat_local_fn(unsigned int hooknum,
+ return ret;
+ }
+
+-static unsigned int
+-nf_nat_adjust(unsigned int hooknum,
+- struct sk_buff *skb,
+- const struct net_device *in,
+- const struct net_device *out,
+- int (*okfn)(struct sk_buff *))
+-{
+- struct nf_conn *ct;
+- enum ip_conntrack_info ctinfo;
+-
+- ct = nf_ct_get(skb, &ctinfo);
+- if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
+- pr_debug("nf_nat_standalone: adjusting sequence number\n");
+- if (!nf_nat_seq_adjust(skb, ct, ctinfo))
+- return NF_DROP;
+- }
+- return NF_ACCEPT;
+-}
+-
+ /* We must be after connection tracking and before packet filtering. */
+
+ static struct nf_hook_ops nf_nat_ops[] __read_mostly = {
+@@ -290,14 +264,6 @@ static struct nf_hook_ops nf_nat_ops[] __read_mostly = {
+ .hooknum = NF_INET_POST_ROUTING,
+ .priority = NF_IP_PRI_NAT_SRC,
+ },
+- /* After conntrack, adjust sequence number */
+- {
+- .hook = nf_nat_adjust,
+- .owner = THIS_MODULE,
+- .pf = PF_INET,
+- .hooknum = NF_INET_POST_ROUTING,
+- .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
+- },
+ /* Before packet filtering, change destination */
+ {
+ .hook = nf_nat_local_fn,
+@@ -314,14 +280,6 @@ static struct nf_hook_ops nf_nat_ops[] __read_mostly = {
+ .hooknum = NF_INET_LOCAL_IN,
+ .priority = NF_IP_PRI_NAT_SRC,
+ },
+- /* After conntrack, adjust sequence number */
+- {
+- .hook = nf_nat_adjust,
+- .owner = THIS_MODULE,
+- .pf = PF_INET,
+- .hooknum = NF_INET_LOCAL_IN,
+- .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
+- },
+ };
+
+ static int __init nf_nat_standalone_init(void)
+diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
+index d63474c..552169b 100644
+--- a/net/ipv4/proc.c
++++ b/net/ipv4/proc.c
+@@ -51,24 +51,54 @@
+ */
+ static int sockstat_seq_show(struct seq_file *seq, void *v)
+ {
++ struct net *net = seq->private;
++
+ socket_seq_show(seq);
+ seq_printf(seq, "TCP: inuse %d orphan %d tw %d alloc %d mem %d\n",
+- sock_prot_inuse_get(&tcp_prot),
++ sock_prot_inuse_get(net, &tcp_prot),
+ atomic_read(&tcp_orphan_count),
+ tcp_death_row.tw_count, atomic_read(&tcp_sockets_allocated),
+ atomic_read(&tcp_memory_allocated));
+- seq_printf(seq, "UDP: inuse %d mem %d\n", sock_prot_inuse_get(&udp_prot),
++ seq_printf(seq, "UDP: inuse %d mem %d\n",
++ sock_prot_inuse_get(net, &udp_prot),
+ atomic_read(&udp_memory_allocated));
+- seq_printf(seq, "UDPLITE: inuse %d\n", sock_prot_inuse_get(&udplite_prot));
+- seq_printf(seq, "RAW: inuse %d\n", sock_prot_inuse_get(&raw_prot));
++ seq_printf(seq, "UDPLITE: inuse %d\n",
++ sock_prot_inuse_get(net, &udplite_prot));
++ seq_printf(seq, "RAW: inuse %d\n",
++ sock_prot_inuse_get(net, &raw_prot));
+ seq_printf(seq, "FRAG: inuse %d memory %d\n",
+- ip_frag_nqueues(&init_net), ip_frag_mem(&init_net));
++ ip_frag_nqueues(net), ip_frag_mem(net));
+ return 0;
+ }
+
+ static int sockstat_seq_open(struct inode *inode, struct file *file)
+ {
+- return single_open(file, sockstat_seq_show, NULL);
++ int err;
++ struct net *net;
++
++ err = -ENXIO;
++ net = get_proc_net(inode);
++ if (net == NULL)
++ goto err_net;
++
++ err = single_open(file, sockstat_seq_show, net);
++ if (err < 0)
++ goto err_open;
++
++ return 0;
++
++err_open:
++ put_net(net);
++err_net:
++ return err;
++}
++
++static int sockstat_seq_release(struct inode *inode, struct file *file)
++{
++ struct net *net = ((struct seq_file *)file->private_data)->private;
++
++ put_net(net);
++ return single_release(inode, file);
+ }
+
+ static const struct file_operations sockstat_seq_fops = {
+@@ -76,7 +106,7 @@ static const struct file_operations sockstat_seq_fops = {
+ .open = sockstat_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = single_release,
++ .release = sockstat_seq_release,
+ };
+
+ /* snmp items */
+@@ -423,25 +453,42 @@ static const struct file_operations netstat_seq_fops = {
+ .release = single_release,
+ };
+
++static __net_init int ip_proc_init_net(struct net *net)
++{
++ if (!proc_net_fops_create(net, "sockstat", S_IRUGO, &sockstat_seq_fops))
++ return -ENOMEM;
++ return 0;
++}
++
++static __net_exit void ip_proc_exit_net(struct net *net)
++{
++ proc_net_remove(net, "sockstat");
++}
++
++static __net_initdata struct pernet_operations ip_proc_ops = {
++ .init = ip_proc_init_net,
++ .exit = ip_proc_exit_net,
++};
++
+ int __init ip_misc_proc_init(void)
+ {
+ int rc = 0;
+
++ if (register_pernet_subsys(&ip_proc_ops))
++ goto out_pernet;
++
+ if (!proc_net_fops_create(&init_net, "netstat", S_IRUGO, &netstat_seq_fops))
+ goto out_netstat;
+
+ if (!proc_net_fops_create(&init_net, "snmp", S_IRUGO, &snmp_seq_fops))
+ goto out_snmp;
+-
+- if (!proc_net_fops_create(&init_net, "sockstat", S_IRUGO, &sockstat_seq_fops))
+- goto out_sockstat;
+ out:
+ return rc;
+-out_sockstat:
+- proc_net_remove(&init_net, "snmp");
+ out_snmp:
+ proc_net_remove(&init_net, "netstat");
+ out_netstat:
++ unregister_pernet_subsys(&ip_proc_ops);
++out_pernet:
+ rc = -ENOMEM;
+ goto out;
+ }
+diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
+index a3002fe..11d7f75 100644
+--- a/net/ipv4/raw.c
++++ b/net/ipv4/raw.c
+@@ -81,41 +81,34 @@
+ #include <linux/netfilter_ipv4.h>
+
+ static struct raw_hashinfo raw_v4_hashinfo = {
+- .lock = __RW_LOCK_UNLOCKED(),
++ .lock = __RW_LOCK_UNLOCKED(raw_v4_hashinfo.lock),
+ };
+
+-void raw_hash_sk(struct sock *sk, struct raw_hashinfo *h)
++void raw_hash_sk(struct sock *sk)
+ {
++ struct raw_hashinfo *h = sk->sk_prot->h.raw_hash;
+ struct hlist_head *head;
+
+ head = &h->ht[inet_sk(sk)->num & (RAW_HTABLE_SIZE - 1)];
+
+ write_lock_bh(&h->lock);
+ sk_add_node(sk, head);
+- sock_prot_inuse_add(sk->sk_prot, 1);
++ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
+ write_unlock_bh(&h->lock);
+ }
+ EXPORT_SYMBOL_GPL(raw_hash_sk);
+
+-void raw_unhash_sk(struct sock *sk, struct raw_hashinfo *h)
++void raw_unhash_sk(struct sock *sk)
+ {
++ struct raw_hashinfo *h = sk->sk_prot->h.raw_hash;
++
+ write_lock_bh(&h->lock);
+ if (sk_del_node_init(sk))
+- sock_prot_inuse_add(sk->sk_prot, -1);
++ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
+ write_unlock_bh(&h->lock);
+ }
+ EXPORT_SYMBOL_GPL(raw_unhash_sk);
+
+-static void raw_v4_hash(struct sock *sk)
+-{
+- raw_hash_sk(sk, &raw_v4_hashinfo);
+-}
+-
+-static void raw_v4_unhash(struct sock *sk)
+-{
+- raw_unhash_sk(sk, &raw_v4_hashinfo);
+-}
+-
+ static struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
+ unsigned short num, __be32 raddr, __be32 laddr, int dif)
+ {
+@@ -124,7 +117,7 @@ static struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
+ sk_for_each_from(sk, node) {
+ struct inet_sock *inet = inet_sk(sk);
+
+- if (sk->sk_net == net && inet->num == num &&
++ if (net_eq(sock_net(sk), net) && inet->num == num &&
+ !(inet->daddr && inet->daddr != raddr) &&
+ !(inet->rcv_saddr && inet->rcv_saddr != laddr) &&
+ !(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif))
+@@ -175,7 +168,7 @@ static int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash)
+ if (hlist_empty(head))
+ goto out;
+
+- net = skb->dev->nd_net;
++ net = dev_net(skb->dev);
+ sk = __raw_v4_lookup(net, __sk_head(head), iph->protocol,
+ iph->saddr, iph->daddr,
+ skb->dev->ifindex);
+@@ -283,7 +276,7 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info)
+ raw_sk = sk_head(&raw_v4_hashinfo.ht[hash]);
+ if (raw_sk != NULL) {
+ iph = (struct iphdr *)skb->data;
+- net = skb->dev->nd_net;
++ net = dev_net(skb->dev);
+
+ while ((raw_sk = __raw_v4_lookup(net, raw_sk, protocol,
+ iph->daddr, iph->saddr,
+@@ -506,7 +499,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ ipc.oif = sk->sk_bound_dev_if;
+
+ if (msg->msg_controllen) {
+- err = ip_cmsg_send(msg, &ipc);
++ err = ip_cmsg_send(sock_net(sk), msg, &ipc);
+ if (err)
+ goto out;
+ if (ipc.opt)
+@@ -560,7 +553,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ }
+
+ security_sk_classify_flow(sk, &fl);
+- err = ip_route_output_flow(&init_net, &rt, &fl, sk, 1);
++ err = ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 1);
+ }
+ if (err)
+ goto done;
+@@ -627,7 +620,7 @@ static int raw_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+
+ if (sk->sk_state != TCP_CLOSE || addr_len < sizeof(struct sockaddr_in))
+ goto out;
+- chk_addr_ret = inet_addr_type(sk->sk_net, addr->sin_addr.s_addr);
++ chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr);
+ ret = -EADDRNOTAVAIL;
+ if (addr->sin_addr.s_addr && chk_addr_ret != RTN_LOCAL &&
+ chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST)
+@@ -825,8 +818,6 @@ static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
+ }
+ }
+
+-DEFINE_PROTO_INUSE(raw)
+-
+ struct proto raw_prot = {
+ .name = "RAW",
+ .owner = THIS_MODULE,
+@@ -841,14 +832,14 @@ struct proto raw_prot = {
+ .recvmsg = raw_recvmsg,
+ .bind = raw_bind,
+ .backlog_rcv = raw_rcv_skb,
+- .hash = raw_v4_hash,
+- .unhash = raw_v4_unhash,
++ .hash = raw_hash_sk,
++ .unhash = raw_unhash_sk,
+ .obj_size = sizeof(struct raw_sock),
++ .h.raw_hash = &raw_v4_hashinfo,
+ #ifdef CONFIG_COMPAT
+ .compat_setsockopt = compat_raw_setsockopt,
+ .compat_getsockopt = compat_raw_getsockopt,
+ #endif
+- REF_PROTO_INUSE(raw)
+ };
+
+ #ifdef CONFIG_PROC_FS
+@@ -862,7 +853,7 @@ static struct sock *raw_get_first(struct seq_file *seq)
+ struct hlist_node *node;
+
+ sk_for_each(sk, node, &state->h->ht[state->bucket])
+- if (sk->sk_net == state->p.net)
++ if (sock_net(sk) == seq_file_net(seq))
+ goto found;
+ }
+ sk = NULL;
+@@ -878,7 +869,7 @@ static struct sock *raw_get_next(struct seq_file *seq, struct sock *sk)
+ sk = sk_next(sk);
+ try_again:
+ ;
+- } while (sk && sk->sk_net != state->p.net);
++ } while (sk && sock_net(sk) != seq_file_net(seq));
+
+ if (!sk && ++state->bucket < RAW_HTABLE_SIZE) {
+ sk = sk_head(&state->h->ht[state->bucket]);
+diff --git a/net/ipv4/route.c b/net/ipv4/route.c
+index 7b5e8e1..ce25a13 100644
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -118,21 +118,19 @@
+ #define RT_GC_TIMEOUT (300*HZ)
+
+ static int ip_rt_max_size;
+-static int ip_rt_gc_timeout = RT_GC_TIMEOUT;
+-static int ip_rt_gc_interval = 60 * HZ;
+-static int ip_rt_gc_min_interval = HZ / 2;
+-static int ip_rt_redirect_number = 9;
+-static int ip_rt_redirect_load = HZ / 50;
+-static int ip_rt_redirect_silence = ((HZ / 50) << (9 + 1));
+-static int ip_rt_error_cost = HZ;
+-static int ip_rt_error_burst = 5 * HZ;
+-static int ip_rt_gc_elasticity = 8;
+-static int ip_rt_mtu_expires = 10 * 60 * HZ;
+-static int ip_rt_min_pmtu = 512 + 20 + 20;
+-static int ip_rt_min_advmss = 256;
+-static int ip_rt_secret_interval = 10 * 60 * HZ;
+-
+-#define RTprint(a...) printk(KERN_DEBUG a)
++static int ip_rt_gc_timeout __read_mostly = RT_GC_TIMEOUT;
++static int ip_rt_gc_interval __read_mostly = 60 * HZ;
++static int ip_rt_gc_min_interval __read_mostly = HZ / 2;
++static int ip_rt_redirect_number __read_mostly = 9;
++static int ip_rt_redirect_load __read_mostly = HZ / 50;
++static int ip_rt_redirect_silence __read_mostly = ((HZ / 50) << (9 + 1));
++static int ip_rt_error_cost __read_mostly = HZ;
++static int ip_rt_error_burst __read_mostly = 5 * HZ;
++static int ip_rt_gc_elasticity __read_mostly = 8;
++static int ip_rt_mtu_expires __read_mostly = 10 * 60 * HZ;
++static int ip_rt_min_pmtu __read_mostly = 512 + 20 + 20;
++static int ip_rt_min_advmss __read_mostly = 256;
++static int ip_rt_secret_interval __read_mostly = 10 * 60 * HZ;
+
+ static void rt_worker_func(struct work_struct *work);
+ static DECLARE_DELAYED_WORK(expires_work, rt_worker_func);
+@@ -252,40 +250,41 @@ static inline void rt_hash_lock_init(void)
+ }
+ #endif
+
+-static struct rt_hash_bucket *rt_hash_table;
+-static unsigned rt_hash_mask;
+-static unsigned int rt_hash_log;
+-static atomic_t rt_genid;
++static struct rt_hash_bucket *rt_hash_table __read_mostly;
++static unsigned rt_hash_mask __read_mostly;
++static unsigned int rt_hash_log __read_mostly;
++static atomic_t rt_genid __read_mostly;
+
+ static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat);
+ #define RT_CACHE_STAT_INC(field) \
+ (__raw_get_cpu_var(rt_cache_stat).field++)
+
+-static unsigned int rt_hash_code(u32 daddr, u32 saddr)
++static inline unsigned int rt_hash(__be32 daddr, __be32 saddr, int idx)
+ {
+- return jhash_2words(daddr, saddr, atomic_read(&rt_genid))
++ return jhash_3words((__force u32)(__be32)(daddr),
++ (__force u32)(__be32)(saddr),
++ idx, atomic_read(&rt_genid))
+ & rt_hash_mask;
+ }
+
+-#define rt_hash(daddr, saddr, idx) \
+- rt_hash_code((__force u32)(__be32)(daddr),\
+- (__force u32)(__be32)(saddr) ^ ((idx) << 5))
+-
+ #ifdef CONFIG_PROC_FS
+ struct rt_cache_iter_state {
++ struct seq_net_private p;
+ int bucket;
+ int genid;
+ };
+
+-static struct rtable *rt_cache_get_first(struct rt_cache_iter_state *st)
++static struct rtable *rt_cache_get_first(struct seq_file *seq)
+ {
++ struct rt_cache_iter_state *st = seq->private;
+ struct rtable *r = NULL;
+
+ for (st->bucket = rt_hash_mask; st->bucket >= 0; --st->bucket) {
+ rcu_read_lock_bh();
+ r = rcu_dereference(rt_hash_table[st->bucket].chain);
+ while (r) {
+- if (r->rt_genid == st->genid)
++ if (dev_net(r->u.dst.dev) == seq_file_net(seq) &&
++ r->rt_genid == st->genid)
+ return r;
+ r = rcu_dereference(r->u.dst.rt_next);
+ }
+@@ -294,8 +293,10 @@ static struct rtable *rt_cache_get_first(struct rt_cache_iter_state *st)
+ return r;
+ }
+
+-static struct rtable *rt_cache_get_next(struct rt_cache_iter_state *st, struct rtable *r)
++static struct rtable *__rt_cache_get_next(struct seq_file *seq,
++ struct rtable *r)
+ {
++ struct rt_cache_iter_state *st = seq->private;
+ r = r->u.dst.rt_next;
+ while (!r) {
+ rcu_read_unlock_bh();
+@@ -307,25 +308,34 @@ static struct rtable *rt_cache_get_next(struct rt_cache_iter_state *st, struct r
+ return rcu_dereference(r);
+ }
+
+-static struct rtable *rt_cache_get_idx(struct rt_cache_iter_state *st, loff_t pos)
++static struct rtable *rt_cache_get_next(struct seq_file *seq,
++ struct rtable *r)
++{
++ struct rt_cache_iter_state *st = seq->private;
++ while ((r = __rt_cache_get_next(seq, r)) != NULL) {
++ if (dev_net(r->u.dst.dev) != seq_file_net(seq))
++ continue;
++ if (r->rt_genid == st->genid)
++ break;
++ }
++ return r;
++}
++
++static struct rtable *rt_cache_get_idx(struct seq_file *seq, loff_t pos)
+ {
+- struct rtable *r = rt_cache_get_first(st);
++ struct rtable *r = rt_cache_get_first(seq);
+
+ if (r)
+- while (pos && (r = rt_cache_get_next(st, r))) {
+- if (r->rt_genid != st->genid)
+- continue;
++ while (pos && (r = rt_cache_get_next(seq, r)))
+ --pos;
+- }
+ return pos ? NULL : r;
+ }
+
+ static void *rt_cache_seq_start(struct seq_file *seq, loff_t *pos)
+ {
+ struct rt_cache_iter_state *st = seq->private;
+-
+ if (*pos)
+- return rt_cache_get_idx(st, *pos - 1);
++ return rt_cache_get_idx(seq, *pos - 1);
+ st->genid = atomic_read(&rt_genid);
+ return SEQ_START_TOKEN;
+ }
+@@ -333,12 +343,11 @@ static void *rt_cache_seq_start(struct seq_file *seq, loff_t *pos)
+ static void *rt_cache_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+ {
+ struct rtable *r;
+- struct rt_cache_iter_state *st = seq->private;
+
+ if (v == SEQ_START_TOKEN)
+- r = rt_cache_get_first(st);
++ r = rt_cache_get_first(seq);
+ else
+- r = rt_cache_get_next(st, v);
++ r = rt_cache_get_next(seq, v);
+ ++*pos;
+ return r;
+ }
+@@ -358,10 +367,10 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v)
+ "HHUptod\tSpecDst");
+ else {
+ struct rtable *r = v;
+- char temp[256];
++ int len;
+
+- sprintf(temp, "%s\t%08lX\t%08lX\t%8X\t%d\t%u\t%d\t"
+- "%08lX\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X",
++ seq_printf(seq, "%s\t%08lX\t%08lX\t%8X\t%d\t%u\t%d\t"
++ "%08lX\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X%n",
+ r->u.dst.dev ? r->u.dst.dev->name : "*",
+ (unsigned long)r->rt_dst, (unsigned long)r->rt_gateway,
+ r->rt_flags, atomic_read(&r->u.dst.__refcnt),
+@@ -375,8 +384,9 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v)
+ r->u.dst.hh ? atomic_read(&r->u.dst.hh->hh_refcnt) : -1,
+ r->u.dst.hh ? (r->u.dst.hh->hh_output ==
+ dev_queue_xmit) : 0,
+- r->rt_spec_dst);
+- seq_printf(seq, "%-127s\n", temp);
++ r->rt_spec_dst, &len);
++
++ seq_printf(seq, "%*s\n", 127 - len, "");
+ }
+ return 0;
+ }
+@@ -390,7 +400,7 @@ static const struct seq_operations rt_cache_seq_ops = {
+
+ static int rt_cache_seq_open(struct inode *inode, struct file *file)
+ {
+- return seq_open_private(file, &rt_cache_seq_ops,
++ return seq_open_net(inode, file, &rt_cache_seq_ops,
+ sizeof(struct rt_cache_iter_state));
+ }
+
+@@ -399,7 +409,7 @@ static const struct file_operations rt_cache_seq_fops = {
+ .open = rt_cache_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = seq_release_private,
++ .release = seq_release_net,
+ };
+
+
+@@ -533,7 +543,7 @@ static int ip_rt_acct_read(char *buffer, char **start, off_t offset,
+ }
+ #endif
+
+-static __init int ip_rt_proc_init(struct net *net)
++static int __net_init ip_rt_do_proc_init(struct net *net)
+ {
+ struct proc_dir_entry *pde;
+
+@@ -564,25 +574,43 @@ err2:
+ err1:
+ return -ENOMEM;
+ }
++
++static void __net_exit ip_rt_do_proc_exit(struct net *net)
++{
++ remove_proc_entry("rt_cache", net->proc_net_stat);
++ remove_proc_entry("rt_cache", net->proc_net);
++ remove_proc_entry("rt_acct", net->proc_net);
++}
++
++static struct pernet_operations ip_rt_proc_ops __net_initdata = {
++ .init = ip_rt_do_proc_init,
++ .exit = ip_rt_do_proc_exit,
++};
++
++static int __init ip_rt_proc_init(void)
++{
++ return register_pernet_subsys(&ip_rt_proc_ops);
++}
++
+ #else
+-static inline int ip_rt_proc_init(struct net *net)
++static inline int ip_rt_proc_init(void)
+ {
+ return 0;
+ }
+ #endif /* CONFIG_PROC_FS */
+
+-static __inline__ void rt_free(struct rtable *rt)
++static inline void rt_free(struct rtable *rt)
+ {
+ call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
+ }
+
+-static __inline__ void rt_drop(struct rtable *rt)
++static inline void rt_drop(struct rtable *rt)
+ {
+ ip_rt_put(rt);
+ call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
+ }
+
+-static __inline__ int rt_fast_clean(struct rtable *rth)
++static inline int rt_fast_clean(struct rtable *rth)
+ {
+ /* Kill broadcast/multicast entries very aggresively, if they
+ collide in hash table with more useful entries */
+@@ -590,7 +618,7 @@ static __inline__ int rt_fast_clean(struct rtable *rth)
+ rth->fl.iif && rth->u.dst.rt_next;
+ }
+
+-static __inline__ int rt_valuable(struct rtable *rth)
++static inline int rt_valuable(struct rtable *rth)
+ {
+ return (rth->rt_flags & (RTCF_REDIRECTED | RTCF_NOTIFY)) ||
+ rth->u.dst.expires;
+@@ -652,7 +680,7 @@ static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
+
+ static inline int compare_netns(struct rtable *rt1, struct rtable *rt2)
+ {
+- return rt1->u.dst.dev->nd_net == rt2->u.dst.dev->nd_net;
++ return dev_net(rt1->u.dst.dev) == dev_net(rt2->u.dst.dev);
+ }
+
+ /*
+@@ -1032,10 +1060,10 @@ restart:
+ #if RT_CACHE_DEBUG >= 2
+ if (rt->u.dst.rt_next) {
+ struct rtable *trt;
+- printk(KERN_DEBUG "rt_cache @%02x: %u.%u.%u.%u", hash,
++ printk(KERN_DEBUG "rt_cache @%02x: " NIPQUAD_FMT, hash,
+ NIPQUAD(rt->rt_dst));
+ for (trt = rt->u.dst.rt_next; trt; trt = trt->u.dst.rt_next)
+- printk(" . %u.%u.%u.%u", NIPQUAD(trt->rt_dst));
++ printk(" . " NIPQUAD_FMT, NIPQUAD(trt->rt_dst));
+ printk("\n");
+ }
+ #endif
+@@ -1131,10 +1159,12 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
+ __be32 skeys[2] = { saddr, 0 };
+ int ikeys[2] = { dev->ifindex, 0 };
+ struct netevent_redirect netevent;
++ struct net *net;
+
+ if (!in_dev)
+ return;
+
++ net = dev_net(dev);
+ if (new_gw == old_gw || !IN_DEV_RX_REDIRECTS(in_dev)
+ || ipv4_is_multicast(new_gw) || ipv4_is_lbcast(new_gw)
+ || ipv4_is_zeronet(new_gw))
+@@ -1146,7 +1176,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
+ if (IN_DEV_SEC_REDIRECTS(in_dev) && ip_fib_check_default(new_gw, dev))
+ goto reject_redirect;
+ } else {
+- if (inet_addr_type(&init_net, new_gw) != RTN_UNICAST)
++ if (inet_addr_type(net, new_gw) != RTN_UNICAST)
+ goto reject_redirect;
+ }
+
+@@ -1164,7 +1194,8 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
+ rth->fl.fl4_src != skeys[i] ||
+ rth->fl.oif != ikeys[k] ||
+ rth->fl.iif != 0 ||
+- rth->rt_genid != atomic_read(&rt_genid)) {
++ rth->rt_genid != atomic_read(&rt_genid) ||
++ !net_eq(dev_net(rth->u.dst.dev), net)) {
+ rthp = &rth->u.dst.rt_next;
+ continue;
+ }
+@@ -1245,9 +1276,9 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
+ reject_redirect:
+ #ifdef CONFIG_IP_ROUTE_VERBOSE
+ if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
+- printk(KERN_INFO "Redirect from %u.%u.%u.%u on %s about "
+- "%u.%u.%u.%u ignored.\n"
+- " Advised path = %u.%u.%u.%u -> %u.%u.%u.%u\n",
++ printk(KERN_INFO "Redirect from " NIPQUAD_FMT " on %s about "
++ NIPQUAD_FMT " ignored.\n"
++ " Advised path = " NIPQUAD_FMT " -> " NIPQUAD_FMT "\n",
+ NIPQUAD(old_gw), dev->name, NIPQUAD(new_gw),
+ NIPQUAD(saddr), NIPQUAD(daddr));
+ #endif
+@@ -1256,7 +1287,7 @@ reject_redirect:
+
+ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
+ {
+- struct rtable *rt = (struct rtable*)dst;
++ struct rtable *rt = (struct rtable *)dst;
+ struct dst_entry *ret = dst;
+
+ if (rt) {
+@@ -1269,7 +1300,7 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
+ rt->fl.oif);
+ #if RT_CACHE_DEBUG >= 1
+ printk(KERN_DEBUG "ipv4_negative_advice: redirect to "
+- "%u.%u.%u.%u/%02x dropped\n",
++ NIPQUAD_FMT "/%02x dropped\n",
+ NIPQUAD(rt->rt_dst), rt->fl.fl4_tos);
+ #endif
+ rt_del(hash, rt);
+@@ -1297,7 +1328,7 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
+
+ void ip_rt_send_redirect(struct sk_buff *skb)
+ {
+- struct rtable *rt = (struct rtable*)skb->dst;
++ struct rtable *rt = skb->rtable;
+ struct in_device *in_dev = in_dev_get(rt->u.dst.dev);
+
+ if (!in_dev)
+@@ -1334,8 +1365,8 @@ void ip_rt_send_redirect(struct sk_buff *skb)
+ if (IN_DEV_LOG_MARTIANS(in_dev) &&
+ rt->u.dst.rate_tokens == ip_rt_redirect_number &&
+ net_ratelimit())
+- printk(KERN_WARNING "host %u.%u.%u.%u/if%d ignores "
+- "redirects for %u.%u.%u.%u to %u.%u.%u.%u.\n",
++ printk(KERN_WARNING "host " NIPQUAD_FMT "/if%d ignores "
++ "redirects for " NIPQUAD_FMT " to " NIPQUAD_FMT ".\n",
+ NIPQUAD(rt->rt_src), rt->rt_iif,
+ NIPQUAD(rt->rt_dst), NIPQUAD(rt->rt_gateway));
+ #endif
+@@ -1346,7 +1377,7 @@ out:
+
+ static int ip_error(struct sk_buff *skb)
+ {
+- struct rtable *rt = (struct rtable*)skb->dst;
++ struct rtable *rt = skb->rtable;
+ unsigned long now;
+ int code;
+
+@@ -1388,7 +1419,7 @@ out: kfree_skb(skb);
+ static const unsigned short mtu_plateau[] =
+ {32000, 17914, 8166, 4352, 2002, 1492, 576, 296, 216, 128 };
+
+-static __inline__ unsigned short guess_mtu(unsigned short old_mtu)
++static inline unsigned short guess_mtu(unsigned short old_mtu)
+ {
+ int i;
+
+@@ -1423,7 +1454,7 @@ unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph,
+ rth->rt_src == iph->saddr &&
+ rth->fl.iif == 0 &&
+ !(dst_metric_locked(&rth->u.dst, RTAX_MTU)) &&
+- rth->u.dst.dev->nd_net == net &&
++ net_eq(dev_net(rth->u.dst.dev), net) &&
+ rth->rt_genid == atomic_read(&rt_genid)) {
+ unsigned short mtu = new_mtu;
+
+@@ -1499,9 +1530,9 @@ static void ipv4_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
+ {
+ struct rtable *rt = (struct rtable *) dst;
+ struct in_device *idev = rt->idev;
+- if (dev != dev->nd_net->loopback_dev && idev && idev->dev == dev) {
++ if (dev != dev_net(dev)->loopback_dev && idev && idev->dev == dev) {
+ struct in_device *loopback_idev =
+- in_dev_get(dev->nd_net->loopback_dev);
++ in_dev_get(dev_net(dev)->loopback_dev);
+ if (loopback_idev) {
+ rt->idev = loopback_idev;
+ in_dev_put(idev);
+@@ -1515,14 +1546,14 @@ static void ipv4_link_failure(struct sk_buff *skb)
+
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
+
+- rt = (struct rtable *) skb->dst;
++ rt = skb->rtable;
+ if (rt)
+ dst_set_expires(&rt->u.dst, 0);
+ }
+
+ static int ip_rt_bug(struct sk_buff *skb)
+ {
+- printk(KERN_DEBUG "ip_rt_bug: %u.%u.%u.%u -> %u.%u.%u.%u, %s\n",
++ printk(KERN_DEBUG "ip_rt_bug: " NIPQUAD_FMT " -> " NIPQUAD_FMT ", %s\n",
+ NIPQUAD(ip_hdr(skb)->saddr), NIPQUAD(ip_hdr(skb)->daddr),
+ skb->dev ? skb->dev->name : "?");
+ kfree_skb(skb);
+@@ -1545,7 +1576,7 @@ void ip_rt_get_source(u8 *addr, struct rtable *rt)
+
+ if (rt->fl.iif == 0)
+ src = rt->rt_src;
+- else if (fib_lookup(rt->u.dst.dev->nd_net, &rt->fl, &res) == 0) {
++ else if (fib_lookup(dev_net(rt->u.dst.dev), &rt->fl, &res) == 0) {
+ src = FIB_RES_PREFSRC(res);
+ fib_res_put(&res);
+ } else
+@@ -1675,7 +1706,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+
+ in_dev_put(in_dev);
+ hash = rt_hash(daddr, saddr, dev->ifindex);
+- return rt_intern_hash(hash, rth, (struct rtable**) &skb->dst);
++ return rt_intern_hash(hash, rth, &skb->rtable);
+
+ e_nobufs:
+ in_dev_put(in_dev);
+@@ -1700,8 +1731,8 @@ static void ip_handle_martian_source(struct net_device *dev,
+ * RFC1812 recommendation, if source is martian,
+ * the only hint is MAC header.
+ */
+- printk(KERN_WARNING "martian source %u.%u.%u.%u from "
+- "%u.%u.%u.%u, on dev %s\n",
++ printk(KERN_WARNING "martian source " NIPQUAD_FMT " from "
++ NIPQUAD_FMT", on dev %s\n",
+ NIPQUAD(daddr), NIPQUAD(saddr), dev->name);
+ if (dev->hard_header_len && skb_mac_header_was_set(skb)) {
+ int i;
+@@ -1718,11 +1749,11 @@ static void ip_handle_martian_source(struct net_device *dev,
+ #endif
+ }
+
+-static inline int __mkroute_input(struct sk_buff *skb,
+- struct fib_result* res,
+- struct in_device *in_dev,
+- __be32 daddr, __be32 saddr, u32 tos,
+- struct rtable **result)
++static int __mkroute_input(struct sk_buff *skb,
++ struct fib_result *res,
++ struct in_device *in_dev,
++ __be32 daddr, __be32 saddr, u32 tos,
++ struct rtable **result)
+ {
+
+ struct rtable *rth;
+@@ -1814,11 +1845,11 @@ static inline int __mkroute_input(struct sk_buff *skb,
+ return err;
+ }
+
+-static inline int ip_mkroute_input(struct sk_buff *skb,
+- struct fib_result* res,
+- const struct flowi *fl,
+- struct in_device *in_dev,
+- __be32 daddr, __be32 saddr, u32 tos)
++static int ip_mkroute_input(struct sk_buff *skb,
++ struct fib_result *res,
++ const struct flowi *fl,
++ struct in_device *in_dev,
++ __be32 daddr, __be32 saddr, u32 tos)
+ {
+ struct rtable* rth = NULL;
+ int err;
+@@ -1836,7 +1867,7 @@ static inline int ip_mkroute_input(struct sk_buff *skb,
+
+ /* put it into the cache */
+ hash = rt_hash(daddr, saddr, fl->iif);
+- return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
++ return rt_intern_hash(hash, rth, &skb->rtable);
+ }
+
+ /*
+@@ -1869,7 +1900,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+ __be32 spec_dst;
+ int err = -EINVAL;
+ int free_res = 0;
+- struct net * net = dev->nd_net;
++ struct net * net = dev_net(dev);
+
+ /* IP on this device is disabled. */
+
+@@ -1992,7 +2023,7 @@ local_input:
+ }
+ rth->rt_type = res.type;
+ hash = rt_hash(daddr, saddr, fl.iif);
+- err = rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
++ err = rt_intern_hash(hash, rth, &skb->rtable);
+ goto done;
+
+ no_route:
+@@ -2010,8 +2041,8 @@ martian_destination:
+ RT_CACHE_STAT_INC(in_martian_dst);
+ #ifdef CONFIG_IP_ROUTE_VERBOSE
+ if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
+- printk(KERN_WARNING "martian destination %u.%u.%u.%u from "
+- "%u.%u.%u.%u, dev %s\n",
++ printk(KERN_WARNING "martian destination " NIPQUAD_FMT " from "
++ NIPQUAD_FMT ", dev %s\n",
+ NIPQUAD(daddr), NIPQUAD(saddr), dev->name);
+ #endif
+
+@@ -2040,25 +2071,25 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+ int iif = dev->ifindex;
+ struct net *net;
+
+- net = dev->nd_net;
++ net = dev_net(dev);
+ tos &= IPTOS_RT_MASK;
+ hash = rt_hash(daddr, saddr, iif);
+
+ rcu_read_lock();
+ for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
+ rth = rcu_dereference(rth->u.dst.rt_next)) {
+- if (rth->fl.fl4_dst == daddr &&
+- rth->fl.fl4_src == saddr &&
+- rth->fl.iif == iif &&
+- rth->fl.oif == 0 &&
++ if (((rth->fl.fl4_dst ^ daddr) |
++ (rth->fl.fl4_src ^ saddr) |
++ (rth->fl.iif ^ iif) |
++ rth->fl.oif |
++ (rth->fl.fl4_tos ^ tos)) == 0 &&
+ rth->fl.mark == skb->mark &&
+- rth->fl.fl4_tos == tos &&
+- rth->u.dst.dev->nd_net == net &&
++ net_eq(dev_net(rth->u.dst.dev), net) &&
+ rth->rt_genid == atomic_read(&rt_genid)) {
+ dst_use(&rth->u.dst, jiffies);
+ RT_CACHE_STAT_INC(in_hit);
+ rcu_read_unlock();
+- skb->dst = (struct dst_entry*)rth;
++ skb->rtable = rth;
+ return 0;
+ }
+ RT_CACHE_STAT_INC(in_hlist_search);
+@@ -2100,12 +2131,12 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+ return ip_route_input_slow(skb, daddr, saddr, tos, dev);
+ }
+
+-static inline int __mkroute_output(struct rtable **result,
+- struct fib_result* res,
+- const struct flowi *fl,
+- const struct flowi *oldflp,
+- struct net_device *dev_out,
+- unsigned flags)
++static int __mkroute_output(struct rtable **result,
++ struct fib_result *res,
++ const struct flowi *fl,
++ const struct flowi *oldflp,
++ struct net_device *dev_out,
++ unsigned flags)
+ {
+ struct rtable *rth;
+ struct in_device *in_dev;
+@@ -2220,12 +2251,12 @@ static inline int __mkroute_output(struct rtable **result,
+ return err;
+ }
+
+-static inline int ip_mkroute_output(struct rtable **rp,
+- struct fib_result* res,
+- const struct flowi *fl,
+- const struct flowi *oldflp,
+- struct net_device *dev_out,
+- unsigned flags)
++static int ip_mkroute_output(struct rtable **rp,
++ struct fib_result *res,
++ const struct flowi *fl,
++ const struct flowi *oldflp,
++ struct net_device *dev_out,
++ unsigned flags)
+ {
+ struct rtable *rth = NULL;
+ int err = __mkroute_output(&rth, res, fl, oldflp, dev_out, flags);
+@@ -2455,7 +2486,7 @@ int __ip_route_output_key(struct net *net, struct rtable **rp,
+ rth->fl.mark == flp->mark &&
+ !((rth->fl.fl4_tos ^ flp->fl4_tos) &
+ (IPTOS_RT_MASK | RTO_ONLINK)) &&
+- rth->u.dst.dev->nd_net == net &&
++ net_eq(dev_net(rth->u.dst.dev), net) &&
+ rth->rt_genid == atomic_read(&rt_genid)) {
+ dst_use(&rth->u.dst, jiffies);
+ RT_CACHE_STAT_INC(out_hit);
+@@ -2487,7 +2518,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = {
+ };
+
+
+-static int ipv4_dst_blackhole(struct rtable **rp, struct flowi *flp, struct sock *sk)
++static int ipv4_dst_blackhole(struct rtable **rp, struct flowi *flp)
+ {
+ struct rtable *ort = *rp;
+ struct rtable *rt = (struct rtable *)
+@@ -2547,7 +2578,7 @@ int ip_route_output_flow(struct net *net, struct rtable **rp, struct flowi *flp,
+ err = __xfrm_lookup((struct dst_entry **)rp, flp, sk,
+ flags ? XFRM_LOOKUP_WAIT : 0);
+ if (err == -EREMOTE)
+- err = ipv4_dst_blackhole(rp, flp, sk);
++ err = ipv4_dst_blackhole(rp, flp);
+
+ return err;
+ }
+@@ -2565,7 +2596,7 @@ int ip_route_output_key(struct net *net, struct rtable **rp, struct flowi *flp)
+ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
+ int nowait, unsigned int flags)
+ {
+- struct rtable *rt = (struct rtable*)skb->dst;
++ struct rtable *rt = skb->rtable;
+ struct rtmsg *r;
+ struct nlmsghdr *nlh;
+ long expires;
+@@ -2658,7 +2689,7 @@ nla_put_failure:
+
+ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
+ {
+- struct net *net = in_skb->sk->sk_net;
++ struct net *net = sock_net(in_skb->sk);
+ struct rtmsg *rtm;
+ struct nlattr *tb[RTA_MAX+1];
+ struct rtable *rt = NULL;
+@@ -2668,9 +2699,6 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
+ int err;
+ struct sk_buff *skb;
+
+- if (net != &init_net)
+- return -EINVAL;
+-
+ err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv4_policy);
+ if (err < 0)
+ goto errout;
+@@ -2700,7 +2728,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
+ if (iif) {
+ struct net_device *dev;
+
+- dev = __dev_get_by_index(&init_net, iif);
++ dev = __dev_get_by_index(net, iif);
+ if (dev == NULL) {
+ err = -ENODEV;
+ goto errout_free;
+@@ -2712,7 +2740,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
+ err = ip_route_input(skb, dst, src, rtm->rtm_tos, dev);
+ local_bh_enable();
+
+- rt = (struct rtable*) skb->dst;
++ rt = skb->rtable;
+ if (err == 0 && rt->u.dst.error)
+ err = -rt->u.dst.error;
+ } else {
+@@ -2726,22 +2754,22 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
+ },
+ .oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0,
+ };
+- err = ip_route_output_key(&init_net, &rt, &fl);
++ err = ip_route_output_key(net, &rt, &fl);
+ }
+
+ if (err)
+ goto errout_free;
+
+- skb->dst = &rt->u.dst;
++ skb->rtable = rt;
+ if (rtm->rtm_flags & RTM_F_NOTIFY)
+ rt->rt_flags |= RTCF_NOTIFY;
+
+ err = rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
+- RTM_NEWROUTE, 0, 0);
++ RTM_NEWROUTE, 0, 0);
+ if (err <= 0)
+ goto errout_free;
+
+- err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid);
++ err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).pid);
+ errout:
+ return err;
+
+@@ -2755,6 +2783,9 @@ int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb)
+ struct rtable *rt;
+ int h, s_h;
+ int idx, s_idx;
++ struct net *net;
++
++ net = sock_net(skb->sk);
+
+ s_h = cb->args[0];
+ if (s_h < 0)
+@@ -2764,7 +2795,7 @@ int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb)
+ rcu_read_lock_bh();
+ for (rt = rcu_dereference(rt_hash_table[h].chain), idx = 0; rt;
+ rt = rcu_dereference(rt->u.dst.rt_next), idx++) {
+- if (idx < s_idx)
++ if (!net_eq(dev_net(rt->u.dst.dev), net) || idx < s_idx)
+ continue;
+ if (rt->rt_genid != atomic_read(&rt_genid))
+ continue;
+@@ -3028,7 +3059,9 @@ int __init ip_rt_init(void)
+ devinet_init();
+ ip_fib_init();
+
+- setup_timer(&rt_secret_timer, rt_secret_rebuild, 0);
++ rt_secret_timer.function = rt_secret_rebuild;
++ rt_secret_timer.data = 0;
++ init_timer_deferrable(&rt_secret_timer);
+
+ /* All the timers, started at system startup tend
+ to synchronize. Perturb it a bit.
+@@ -3040,7 +3073,7 @@ int __init ip_rt_init(void)
+ ip_rt_secret_interval;
+ add_timer(&rt_secret_timer);
+
+- if (ip_rt_proc_init(&init_net))
++ if (ip_rt_proc_init())
+ printk(KERN_ERR "Unable to create route proc files\n");
+ #ifdef CONFIG_XFRM
+ xfrm_init();
+diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
+index f470fe4..73ba989 100644
+--- a/net/ipv4/syncookies.c
++++ b/net/ipv4/syncookies.c
+@@ -10,8 +10,6 @@
+ * 2 of the License, or (at your option) any later version.
+ *
+ * $Id: syncookies.c,v 1.18 2002/02/01 22:01:04 davem Exp $
+- *
+- * Missing: IPv6 support.
+ */
+
+ #include <linux/tcp.h>
+@@ -21,26 +19,33 @@
+ #include <linux/kernel.h>
+ #include <net/tcp.h>
+
++/* Timestamps: lowest 9 bits store TCP options */
++#define TSBITS 9
++#define TSMASK (((__u32)1 << TSBITS) - 1)
++
+ extern int sysctl_tcp_syncookies;
+
+-static __u32 syncookie_secret[2][16-3+SHA_DIGEST_WORDS];
++__u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS];
++EXPORT_SYMBOL(syncookie_secret);
+
+ static __init int init_syncookies(void)
+ {
+ get_random_bytes(syncookie_secret, sizeof(syncookie_secret));
+ return 0;
+ }
+-module_init(init_syncookies);
++__initcall(init_syncookies);
+
+ #define COOKIEBITS 24 /* Upper bits store count */
+ #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)
+
++static DEFINE_PER_CPU(__u32, cookie_scratch)[16 + 5 + SHA_WORKSPACE_WORDS];
++
+ static u32 cookie_hash(__be32 saddr, __be32 daddr, __be16 sport, __be16 dport,
+ u32 count, int c)
+ {
+- __u32 tmp[16 + 5 + SHA_WORKSPACE_WORDS];
++ __u32 *tmp = __get_cpu_var(cookie_scratch);
+
+- memcpy(tmp + 3, syncookie_secret[c], sizeof(syncookie_secret[c]));
++ memcpy(tmp + 4, syncookie_secret[c], sizeof(syncookie_secret[c]));
+ tmp[0] = (__force u32)saddr;
+ tmp[1] = (__force u32)daddr;
+ tmp[2] = ((__force u32)sport << 16) + (__force u32)dport;
+@@ -50,6 +55,39 @@ static u32 cookie_hash(__be32 saddr, __be32 daddr, __be16 sport, __be16 dport,
+ return tmp[17];
+ }
+
++
++/*
++ * when syncookies are in effect and tcp timestamps are enabled we encode
++ * tcp options in the lowest 9 bits of the timestamp value that will be
++ * sent in the syn-ack.
++ * Since subsequent timestamps use the normal tcp_time_stamp value, we
++ * must make sure that the resulting initial timestamp is <= tcp_time_stamp.
++ */
++__u32 cookie_init_timestamp(struct request_sock *req)
++{
++ struct inet_request_sock *ireq;
++ u32 ts, ts_now = tcp_time_stamp;
++ u32 options = 0;
++
++ ireq = inet_rsk(req);
++ if (ireq->wscale_ok) {
++ options = ireq->snd_wscale;
++ options |= ireq->rcv_wscale << 4;
++ }
++ options |= ireq->sack_ok << 8;
++
++ ts = ts_now & ~TSMASK;
++ ts |= options;
++ if (ts > ts_now) {
++ ts >>= TSBITS;
++ ts--;
++ ts <<= TSBITS;
++ ts |= options;
++ }
++ return ts;
++}
++
++
+ static __u32 secure_tcp_syn_cookie(__be32 saddr, __be32 daddr, __be16 sport,
+ __be16 dport, __u32 sseq, __u32 count,
+ __u32 data)
+@@ -184,6 +222,35 @@ static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
+ return child;
+ }
+
++
++/*
++ * when syncookies are in effect and tcp timestamps are enabled we stored
++ * additional tcp options in the timestamp.
++ * This extracts these options from the timestamp echo.
++ *
++ * The lowest 4 bits are for snd_wscale
++ * The next 4 lsb are for rcv_wscale
++ * The next lsb is for sack_ok
++ */
++void cookie_check_timestamp(struct tcp_options_received *tcp_opt)
++{
++ /* echoed timestamp, 9 lowest bits contain options */
++ u32 options = tcp_opt->rcv_tsecr & TSMASK;
++
++ tcp_opt->snd_wscale = options & 0xf;
++ options >>= 4;
++ tcp_opt->rcv_wscale = options & 0xf;
++
++ tcp_opt->sack_ok = (options >> 4) & 0x1;
++
++ if (tcp_opt->sack_ok)
++ tcp_sack_reset(tcp_opt);
++
++ if (tcp_opt->snd_wscale || tcp_opt->rcv_wscale)
++ tcp_opt->wscale_ok = 1;
++}
++EXPORT_SYMBOL(cookie_check_timestamp);
++
+ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
+ struct ip_options *opt)
+ {
+@@ -197,6 +264,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
+ int mss;
+ struct rtable *rt;
+ __u8 rcv_wscale;
++ struct tcp_options_received tcp_opt;
+
+ if (!sysctl_tcp_syncookies || !th->ack)
+ goto out;
+@@ -209,6 +277,13 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
+
+ NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESRECV);
+
++ /* check for timestamp cookie support */
++ memset(&tcp_opt, 0, sizeof(tcp_opt));
++ tcp_parse_options(skb, &tcp_opt, 0);
++
++ if (tcp_opt.saw_tstamp)
++ cookie_check_timestamp(&tcp_opt);
++
+ ret = NULL;
+ req = reqsk_alloc(&tcp_request_sock_ops); /* for safety */
+ if (!req)
+@@ -227,6 +302,12 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
+ ireq->loc_addr = ip_hdr(skb)->daddr;
+ ireq->rmt_addr = ip_hdr(skb)->saddr;
+ ireq->opt = NULL;
++ ireq->snd_wscale = tcp_opt.snd_wscale;
++ ireq->rcv_wscale = tcp_opt.rcv_wscale;
++ ireq->sack_ok = tcp_opt.sack_ok;
++ ireq->wscale_ok = tcp_opt.wscale_ok;
++ ireq->tstamp_ok = tcp_opt.saw_tstamp;
++ req->ts_recent = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0;
+
+ /* We throwed the options of the initial SYN away, so we hope
+ * the ACK carries the same options again (see RFC1122 4.2.3.8)
+@@ -241,8 +322,6 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
+ }
+ }
+
+- ireq->snd_wscale = ireq->rcv_wscale = ireq->tstamp_ok = 0;
+- ireq->wscale_ok = ireq->sack_ok = 0;
+ req->expires = 0UL;
+ req->retrans = 0;
+
+@@ -271,11 +350,12 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
+ }
+
+ /* Try to redo what tcp_v4_send_synack did. */
+- req->window_clamp = dst_metric(&rt->u.dst, RTAX_WINDOW);
++ req->window_clamp = tp->window_clamp ? :dst_metric(&rt->u.dst, RTAX_WINDOW);
++
+ tcp_select_initial_window(tcp_full_space(sk), req->mss,
+ &req->rcv_wnd, &req->window_clamp,
+- 0, &rcv_wscale);
+- /* BTW win scale with syncookies is 0 by definition */
++ ireq->wscale_ok, &rcv_wscale);
++
+ ireq->rcv_wscale = rcv_wscale;
+
+ ret = get_cookie_sock(sk, skb, req, &rt->u.dst);
+diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
+index 88286f3..c437f80 100644
+--- a/net/ipv4/sysctl_net_ipv4.c
++++ b/net/ipv4/sysctl_net_ipv4.c
+@@ -404,38 +404,6 @@ static struct ctl_table ipv4_table[] = {
+ .strategy = &ipv4_sysctl_local_port_range,
+ },
+ {
+- .ctl_name = NET_IPV4_ICMP_ECHO_IGNORE_ALL,
+- .procname = "icmp_echo_ignore_all",
+- .data = &sysctl_icmp_echo_ignore_all,
+- .maxlen = sizeof(int),
+- .mode = 0644,
+- .proc_handler = &proc_dointvec
+- },
+- {
+- .ctl_name = NET_IPV4_ICMP_ECHO_IGNORE_BROADCASTS,
+- .procname = "icmp_echo_ignore_broadcasts",
+- .data = &sysctl_icmp_echo_ignore_broadcasts,
+- .maxlen = sizeof(int),
+- .mode = 0644,
+- .proc_handler = &proc_dointvec
+- },
+- {
+- .ctl_name = NET_IPV4_ICMP_IGNORE_BOGUS_ERROR_RESPONSES,
+- .procname = "icmp_ignore_bogus_error_responses",
+- .data = &sysctl_icmp_ignore_bogus_error_responses,
+- .maxlen = sizeof(int),
+- .mode = 0644,
+- .proc_handler = &proc_dointvec
+- },
+- {
+- .ctl_name = NET_IPV4_ICMP_ERRORS_USE_INBOUND_IFADDR,
+- .procname = "icmp_errors_use_inbound_ifaddr",
+- .data = &sysctl_icmp_errors_use_inbound_ifaddr,
+- .maxlen = sizeof(int),
+- .mode = 0644,
+- .proc_handler = &proc_dointvec
+- },
+- {
+ .ctl_name = NET_IPV4_ROUTE,
+ .procname = "route",
+ .maxlen = 0,
+@@ -586,22 +554,6 @@ static struct ctl_table ipv4_table[] = {
+ .proc_handler = &proc_dointvec
+ },
+ {
+- .ctl_name = NET_IPV4_ICMP_RATELIMIT,
+- .procname = "icmp_ratelimit",
+- .data = &sysctl_icmp_ratelimit,
+- .maxlen = sizeof(int),
+- .mode = 0644,
+- .proc_handler = &proc_dointvec
+- },
+- {
+- .ctl_name = NET_IPV4_ICMP_RATEMASK,
+- .procname = "icmp_ratemask",
+- .data = &sysctl_icmp_ratemask,
+- .maxlen = sizeof(int),
+- .mode = 0644,
+- .proc_handler = &proc_dointvec
+- },
+- {
+ .ctl_name = NET_TCP_TW_REUSE,
+ .procname = "tcp_tw_reuse",
+ .data = &sysctl_tcp_tw_reuse,
+@@ -804,6 +756,58 @@ static struct ctl_table ipv4_table[] = {
+ { .ctl_name = 0 }
+ };
+
++static struct ctl_table ipv4_net_table[] = {
++ {
++ .ctl_name = NET_IPV4_ICMP_ECHO_IGNORE_ALL,
++ .procname = "icmp_echo_ignore_all",
++ .data = &init_net.ipv4.sysctl_icmp_echo_ignore_all,
++ .maxlen = sizeof(int),
++ .mode = 0644,
++ .proc_handler = &proc_dointvec
++ },
++ {
++ .ctl_name = NET_IPV4_ICMP_ECHO_IGNORE_BROADCASTS,
++ .procname = "icmp_echo_ignore_broadcasts",
++ .data = &init_net.ipv4.sysctl_icmp_echo_ignore_broadcasts,
++ .maxlen = sizeof(int),
++ .mode = 0644,
++ .proc_handler = &proc_dointvec
++ },
++ {
++ .ctl_name = NET_IPV4_ICMP_IGNORE_BOGUS_ERROR_RESPONSES,
++ .procname = "icmp_ignore_bogus_error_responses",
++ .data = &init_net.ipv4.sysctl_icmp_ignore_bogus_error_responses,
++ .maxlen = sizeof(int),
++ .mode = 0644,
++ .proc_handler = &proc_dointvec
++ },
++ {
++ .ctl_name = NET_IPV4_ICMP_ERRORS_USE_INBOUND_IFADDR,
++ .procname = "icmp_errors_use_inbound_ifaddr",
++ .data = &init_net.ipv4.sysctl_icmp_errors_use_inbound_ifaddr,
++ .maxlen = sizeof(int),
++ .mode = 0644,
++ .proc_handler = &proc_dointvec
++ },
++ {
++ .ctl_name = NET_IPV4_ICMP_RATELIMIT,
++ .procname = "icmp_ratelimit",
++ .data = &init_net.ipv4.sysctl_icmp_ratelimit,
++ .maxlen = sizeof(int),
++ .mode = 0644,
++ .proc_handler = &proc_dointvec
++ },
++ {
++ .ctl_name = NET_IPV4_ICMP_RATEMASK,
++ .procname = "icmp_ratemask",
++ .data = &init_net.ipv4.sysctl_icmp_ratemask,
++ .maxlen = sizeof(int),
++ .mode = 0644,
++ .proc_handler = &proc_dointvec
++ },
++ { }
++};
++
+ struct ctl_path net_ipv4_ctl_path[] = {
+ { .procname = "net", .ctl_name = CTL_NET, },
+ { .procname = "ipv4", .ctl_name = NET_IPV4, },
+@@ -811,12 +815,72 @@ struct ctl_path net_ipv4_ctl_path[] = {
+ };
+ EXPORT_SYMBOL_GPL(net_ipv4_ctl_path);
+
++static __net_init int ipv4_sysctl_init_net(struct net *net)
++{
++ struct ctl_table *table;
++
++ table = ipv4_net_table;
++ if (net != &init_net) {
++ table = kmemdup(table, sizeof(ipv4_net_table), GFP_KERNEL);
++ if (table == NULL)
++ goto err_alloc;
++
++ table[0].data =
++ &net->ipv4.sysctl_icmp_echo_ignore_all;
++ table[1].data =
++ &net->ipv4.sysctl_icmp_echo_ignore_broadcasts;
++ table[2].data =
++ &net->ipv4.sysctl_icmp_ignore_bogus_error_responses;
++ table[3].data =
++ &net->ipv4.sysctl_icmp_errors_use_inbound_ifaddr;
++ table[4].data =
++ &net->ipv4.sysctl_icmp_ratelimit;
++ table[5].data =
++ &net->ipv4.sysctl_icmp_ratemask;
++ }
++
++ net->ipv4.ipv4_hdr = register_net_sysctl_table(net,
++ net_ipv4_ctl_path, table);
++ if (net->ipv4.ipv4_hdr == NULL)
++ goto err_reg;
++
++ return 0;
++
++err_reg:
++ if (net != &init_net)
++ kfree(table);
++err_alloc:
++ return -ENOMEM;
++}
++
++static __net_exit void ipv4_sysctl_exit_net(struct net *net)
++{
++ struct ctl_table *table;
++
++ table = net->ipv4.ipv4_hdr->ctl_table_arg;
++ unregister_net_sysctl_table(net->ipv4.ipv4_hdr);
++ kfree(table);
++}
++
++static __net_initdata struct pernet_operations ipv4_sysctl_ops = {
++ .init = ipv4_sysctl_init_net,
++ .exit = ipv4_sysctl_exit_net,
++};
++
+ static __init int sysctl_ipv4_init(void)
+ {
+ struct ctl_table_header *hdr;
+
+ hdr = register_sysctl_paths(net_ipv4_ctl_path, ipv4_table);
+- return hdr == NULL ? -ENOMEM : 0;
++ if (hdr == NULL)
++ return -ENOMEM;
++
++ if (register_pernet_subsys(&ipv4_sysctl_ops)) {
++ unregister_sysctl_table(hdr);
++ return -ENOMEM;
++ }
++
++ return 0;
+ }
+
+ __initcall(sysctl_ipv4_init);
+diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
+index 39b629a..f886531 100644
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -1722,7 +1722,7 @@ static int tcp_close_state(struct sock *sk)
+
+ /*
+ * Shutdown the sending side of a connection. Much like close except
+- * that we don't receive shut down or set_sock_flag(sk, SOCK_DEAD).
++ * that we don't receive shut down or sock_set_flag(sk, SOCK_DEAD).
+ */
+
+ void tcp_shutdown(struct sock *sk, int how)
+@@ -2105,15 +2105,12 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
+ break;
+
+ case TCP_DEFER_ACCEPT:
+- icsk->icsk_accept_queue.rskq_defer_accept = 0;
+- if (val > 0) {
+- /* Translate value in seconds to number of
+- * retransmits */
+- while (icsk->icsk_accept_queue.rskq_defer_accept < 32 &&
+- val > ((TCP_TIMEOUT_INIT / HZ) <<
+- icsk->icsk_accept_queue.rskq_defer_accept))
+- icsk->icsk_accept_queue.rskq_defer_accept++;
+- icsk->icsk_accept_queue.rskq_defer_accept++;
++ if (val < 0) {
++ err = -EINVAL;
++ } else {
++ if (val > MAX_TCP_ACCEPT_DEFERRED)
++ val = MAX_TCP_ACCEPT_DEFERRED;
++ icsk->icsk_accept_queue.rskq_defer_accept = val;
+ }
+ break;
+
+@@ -2295,8 +2292,7 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
+ val = (val ? : sysctl_tcp_fin_timeout) / HZ;
+ break;
+ case TCP_DEFER_ACCEPT:
+- val = !icsk->icsk_accept_queue.rskq_defer_accept ? 0 :
+- ((TCP_TIMEOUT_INIT / HZ) << (icsk->icsk_accept_queue.rskq_defer_accept - 1));
++ val = icsk->icsk_accept_queue.rskq_defer_accept;
+ break;
+ case TCP_WINDOW_CLAMP:
+ val = tp->window_clamp;
+diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c
+index 3aa0b23..eb5b985 100644
+--- a/net/ipv4/tcp_cubic.c
++++ b/net/ipv4/tcp_cubic.c
+@@ -1,12 +1,13 @@
+ /*
+- * TCP CUBIC: Binary Increase Congestion control for TCP v2.1
+- *
++ * TCP CUBIC: Binary Increase Congestion control for TCP v2.2
++ * Home page:
++ * http://netsrv.csc.ncsu.edu/twiki/bin/view/Main/BIC
+ * This is from the implementation of CUBIC TCP in
+ * Injong Rhee, Lisong Xu.
+ * "CUBIC: A New TCP-Friendly High-Speed TCP Variant
+ * in PFLDnet 2005
+ * Available from:
+- * http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/cubic-paper.pdf
++ * http://netsrv.csc.ncsu.edu/export/cubic-paper.pdf
+ *
+ * Unless CUBIC is enabled and congestion window is large
+ * this behaves the same as the original Reno.
+@@ -20,15 +21,10 @@
+ #define BICTCP_BETA_SCALE 1024 /* Scale factor beta calculation
+ * max_cwnd = snd_cwnd * beta
+ */
+-#define BICTCP_B 4 /*
+- * In binary search,
+- * go to point (max+min)/N
+- */
+ #define BICTCP_HZ 10 /* BIC HZ 2^10 = 1024 */
+
+ static int fast_convergence __read_mostly = 1;
+-static int max_increment __read_mostly = 16;
+-static int beta __read_mostly = 819; /* = 819/1024 (BICTCP_BETA_SCALE) */
++static int beta __read_mostly = 717; /* = 717/1024 (BICTCP_BETA_SCALE) */
+ static int initial_ssthresh __read_mostly;
+ static int bic_scale __read_mostly = 41;
+ static int tcp_friendliness __read_mostly = 1;
+@@ -40,9 +36,7 @@ static u64 cube_factor __read_mostly;
+ /* Note parameters that are used for precomputing scale factors are read-only */
+ module_param(fast_convergence, int, 0644);
+ MODULE_PARM_DESC(fast_convergence, "turn on/off fast convergence");
+-module_param(max_increment, int, 0644);
+-MODULE_PARM_DESC(max_increment, "Limit on increment allowed during binary search");
+-module_param(beta, int, 0444);
++module_param(beta, int, 0644);
+ MODULE_PARM_DESC(beta, "beta for multiplicative increase");
+ module_param(initial_ssthresh, int, 0644);
+ MODULE_PARM_DESC(initial_ssthresh, "initial value of slow start threshold");
+@@ -145,7 +139,7 @@ static u32 cubic_root(u64 a)
+ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
+ {
+ u64 offs;
+- u32 delta, t, bic_target, min_cnt, max_cnt;
++ u32 delta, t, bic_target, max_cnt;
+
+ ca->ack_cnt++; /* count the number of ACKs */
+
+@@ -211,19 +205,6 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
+ ca->cnt = 100 * cwnd; /* very small increment*/
+ }
+
+- if (ca->delay_min > 0) {
+- /* max increment = Smax * rtt / 0.1 */
+- min_cnt = (cwnd * HZ * 8)/(10 * max_increment * ca->delay_min);
+-
+- /* use concave growth when the target is above the origin */
+- if (ca->cnt < min_cnt && t >= ca->bic_K)
+- ca->cnt = min_cnt;
+- }
+-
+- /* slow start and low utilization */
+- if (ca->loss_cwnd == 0) /* could be aggressive in slow start */
+- ca->cnt = 50;
+-
+ /* TCP Friendly */
+ if (tcp_friendliness) {
+ u32 scale = beta_scale;
+@@ -391,4 +372,4 @@ module_exit(cubictcp_unregister);
+ MODULE_AUTHOR("Sangtae Ha, Stephen Hemminger");
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("CUBIC TCP");
+-MODULE_VERSION("2.1");
++MODULE_VERSION("2.2");
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
+index bbb7d88..ac9b848 100644
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -2298,7 +2298,7 @@ static inline int tcp_packet_delayed(struct tcp_sock *tp)
+ {
+ return !tp->retrans_stamp ||
+ (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr &&
+- (__s32)(tp->rx_opt.rcv_tsecr - tp->retrans_stamp) < 0);
++ before(tp->rx_opt.rcv_tsecr, tp->retrans_stamp));
+ }
+
+ /* Undo procedures. */
+@@ -2309,12 +2309,25 @@ static void DBGUNDO(struct sock *sk, const char *msg)
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct inet_sock *inet = inet_sk(sk);
+
+- printk(KERN_DEBUG "Undo %s %u.%u.%u.%u/%u c%u l%u ss%u/%u p%u\n",
+- msg,
+- NIPQUAD(inet->daddr), ntohs(inet->dport),
+- tp->snd_cwnd, tcp_left_out(tp),
+- tp->snd_ssthresh, tp->prior_ssthresh,
+- tp->packets_out);
++ if (sk->sk_family == AF_INET) {
++ printk(KERN_DEBUG "Undo %s " NIPQUAD_FMT "/%u c%u l%u ss%u/%u p%u\n",
++ msg,
++ NIPQUAD(inet->daddr), ntohs(inet->dport),
++ tp->snd_cwnd, tcp_left_out(tp),
++ tp->snd_ssthresh, tp->prior_ssthresh,
++ tp->packets_out);
++ }
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++ else if (sk->sk_family == AF_INET6) {
++ struct ipv6_pinfo *np = inet6_sk(sk);
++ printk(KERN_DEBUG "Undo %s " NIP6_FMT "/%u c%u l%u ss%u/%u p%u\n",
++ msg,
++ NIP6(np->daddr), ntohs(inet->dport),
++ tp->snd_cwnd, tcp_left_out(tp),
++ tp->snd_ssthresh, tp->prior_ssthresh,
++ tp->packets_out);
++ }
++#endif
+ }
+ #else
+ #define DBGUNDO(x...) do { } while (0)
+@@ -3592,7 +3605,7 @@ static void tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th)
+ * cases we should never reach this piece of code.
+ */
+ printk(KERN_ERR "%s: Impossible, sk->sk_state=%d\n",
+- __FUNCTION__, sk->sk_state);
++ __func__, sk->sk_state);
+ break;
+ }
+
+@@ -4012,7 +4025,7 @@ drop:
+ u32 end_seq = TCP_SKB_CB(skb)->end_seq;
+
+ if (seq == TCP_SKB_CB(skb1)->end_seq) {
+- __skb_append(skb1, skb, &tp->out_of_order_queue);
++ __skb_queue_after(&tp->out_of_order_queue, skb1, skb);
+
+ if (!tp->rx_opt.num_sacks ||
+ tp->selective_acks[0].end_seq != seq)
+@@ -4508,6 +4521,49 @@ static void tcp_urg(struct sock *sk, struct sk_buff *skb, struct tcphdr *th)
+ }
+ }
+
++static int tcp_defer_accept_check(struct sock *sk)
++{
++ struct tcp_sock *tp = tcp_sk(sk);
++
++ if (tp->defer_tcp_accept.request) {
++ int queued_data = tp->rcv_nxt - tp->copied_seq;
++ int hasfin = !skb_queue_empty(&sk->sk_receive_queue) ?
++ tcp_hdr((struct sk_buff *)
++ sk->sk_receive_queue.prev)->fin : 0;
++
++ if (queued_data && hasfin)
++ queued_data--;
++
++ if (queued_data &&
++ tp->defer_tcp_accept.listen_sk->sk_state == TCP_LISTEN) {
++ if (sock_flag(sk, SOCK_KEEPOPEN)) {
++ inet_csk_reset_keepalive_timer(sk,
++ keepalive_time_when(tp));
++ } else {
++ inet_csk_delete_keepalive_timer(sk);
++ }
++
++ inet_csk_reqsk_queue_add(
++ tp->defer_tcp_accept.listen_sk,
++ tp->defer_tcp_accept.request,
++ sk);
++
++ tp->defer_tcp_accept.listen_sk->sk_data_ready(
++ tp->defer_tcp_accept.listen_sk, 0);
++
++ sock_put(tp->defer_tcp_accept.listen_sk);
++ sock_put(sk);
++ tp->defer_tcp_accept.listen_sk = NULL;
++ tp->defer_tcp_accept.request = NULL;
++ } else if (hasfin ||
++ tp->defer_tcp_accept.listen_sk->sk_state != TCP_LISTEN) {
++ tcp_reset(sk);
++ return -1;
++ }
++ }
++ return 0;
++}
++
+ static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen)
+ {
+ struct tcp_sock *tp = tcp_sk(sk);
+@@ -4868,6 +4924,9 @@ step5:
+
+ tcp_data_snd_check(sk);
+ tcp_ack_snd_check(sk);
++
++ if (tcp_defer_accept_check(sk))
++ return -1;
+ return 0;
+
+ csum_error:
+@@ -5387,6 +5446,7 @@ discard:
+
+ EXPORT_SYMBOL(sysctl_tcp_ecn);
+ EXPORT_SYMBOL(sysctl_tcp_reordering);
++EXPORT_SYMBOL(sysctl_tcp_adv_win_scale);
+ EXPORT_SYMBOL(tcp_parse_options);
+ EXPORT_SYMBOL(tcp_rcv_established);
+ EXPORT_SYMBOL(tcp_rcv_state_process);
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index 00156bf..0e9bc12 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -88,9 +88,6 @@ int sysctl_tcp_low_latency __read_mostly;
+ /* Check TCP sequence numbers in ICMP packets. */
+ #define ICMP_MIN_LENGTH 8
+
+-/* Socket used for sending RSTs */
+-static struct socket *tcp_socket __read_mostly;
+-
+ void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb);
+
+ #ifdef CONFIG_TCP_MD5SIG
+@@ -353,7 +350,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
+ return;
+ }
+
+- sk = inet_lookup(skb->dev->nd_net, &tcp_hashinfo, iph->daddr, th->dest,
++ sk = inet_lookup(dev_net(skb->dev), &tcp_hashinfo, iph->daddr, th->dest,
+ iph->saddr, th->source, inet_iif(skb));
+ if (!sk) {
+ ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
+@@ -552,7 +549,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
+ if (th->rst)
+ return;
+
+- if (((struct rtable *)skb->dst)->rt_type != RTN_LOCAL)
++ if (skb->rtable->rt_type != RTN_LOCAL)
+ return;
+
+ /* Swap the send and the receive. */
+@@ -598,7 +595,8 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
+ sizeof(struct tcphdr), IPPROTO_TCP, 0);
+ arg.csumoffset = offsetof(struct tcphdr, check) / 2;
+
+- ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len);
++ ip_send_reply(dev_net(skb->dst->dev)->ipv4.tcp_sock, skb,
++ &arg, arg.iov[0].iov_len);
+
+ TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
+ TCP_INC_STATS_BH(TCP_MIB_OUTRSTS);
+@@ -693,7 +691,8 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
+ if (twsk)
+ arg.bound_dev_if = twsk->tw_sk.tw_bound_dev_if;
+
+- ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len);
++ ip_send_reply(dev_net(skb->dev)->ipv4.tcp_sock, skb,
++ &arg, arg.iov[0].iov_len);
+
+ TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
+ }
+@@ -723,8 +722,8 @@ static void tcp_v4_reqsk_send_ack(struct sk_buff *skb,
+ * This still operates on a request_sock only, not on a big
+ * socket.
+ */
+-static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req,
+- struct dst_entry *dst)
++static int __tcp_v4_send_synack(struct sock *sk, struct request_sock *req,
++ struct dst_entry *dst)
+ {
+ const struct inet_request_sock *ireq = inet_rsk(req);
+ int err = -1;
+@@ -732,7 +731,7 @@ static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req,
+
+ /* First, grab a route. */
+ if (!dst && (dst = inet_csk_route_req(sk, req)) == NULL)
+- goto out;
++ return -1;
+
+ skb = tcp_make_synack(sk, dst, req);
+
+@@ -751,11 +750,15 @@ static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req,
+ err = net_xmit_eval(err);
+ }
+
+-out:
+ dst_release(dst);
+ return err;
+ }
+
++static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req)
++{
++ return __tcp_v4_send_synack(sk, req, NULL);
++}
++
+ /*
+ * IPv4 request_sock destructor.
+ */
+@@ -1258,8 +1261,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
+ #endif
+
+ /* Never answer to SYNs send to broadcast or multicast */
+- if (((struct rtable *)skb->dst)->rt_flags &
+- (RTCF_BROADCAST | RTCF_MULTICAST))
++ if (skb->rtable->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
+ goto drop;
+
+ /* TW buckets are converted to open requests without
+@@ -1297,10 +1299,8 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
+
+ tcp_parse_options(skb, &tmp_opt, 0);
+
+- if (want_cookie) {
++ if (want_cookie && !tmp_opt.saw_tstamp)
+ tcp_clear_options(&tmp_opt);
+- tmp_opt.saw_tstamp = 0;
+- }
+
+ if (tmp_opt.saw_tstamp && !tmp_opt.rcv_tsval) {
+ /* Some OSes (unknown ones, but I see them on web server, which
+@@ -1328,6 +1328,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
+ if (want_cookie) {
+ #ifdef CONFIG_SYN_COOKIES
+ syn_flood_warning(skb);
++ req->cookie_ts = tmp_opt.tstamp_ok;
+ #endif
+ isn = cookie_v4_init_sequence(sk, skb, &req->mss);
+ } else if (!isn) {
+@@ -1351,8 +1352,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
+ (s32)(peer->tcp_ts - req->ts_recent) >
+ TCP_PAWS_WINDOW) {
+ NET_INC_STATS_BH(LINUX_MIB_PAWSPASSIVEREJECTED);
+- dst_release(dst);
+- goto drop_and_free;
++ goto drop_and_release;
+ }
+ }
+ /* Kill the following clause, if you dislike this way. */
+@@ -1369,27 +1369,24 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
+ * to the moment of synflood.
+ */
+ LIMIT_NETDEBUG(KERN_DEBUG "TCP: drop open "
+- "request from %u.%u.%u.%u/%u\n",
++ "request from " NIPQUAD_FMT "/%u\n",
+ NIPQUAD(saddr),
+ ntohs(tcp_hdr(skb)->source));
+- dst_release(dst);
+- goto drop_and_free;
++ goto drop_and_release;
+ }
+
+ isn = tcp_v4_init_sequence(skb);
+ }
+ tcp_rsk(req)->snt_isn = isn;
+
+- if (tcp_v4_send_synack(sk, req, dst))
++ if (__tcp_v4_send_synack(sk, req, dst) || want_cookie)
+ goto drop_and_free;
+
+- if (want_cookie) {
+- reqsk_free(req);
+- } else {
+- inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
+- }
++ inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
+ return 0;
+
++drop_and_release:
++ dst_release(dst);
+ drop_and_free:
+ reqsk_free(req);
+ drop:
+@@ -1487,7 +1484,7 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
+ if (req)
+ return tcp_check_req(sk, skb, req, prev);
+
+- nsk = inet_lookup_established(sk->sk_net, &tcp_hashinfo, iph->saddr,
++ nsk = inet_lookup_established(sock_net(sk), &tcp_hashinfo, iph->saddr,
+ th->source, iph->daddr, th->dest, inet_iif(skb));
+
+ if (nsk) {
+@@ -1645,7 +1642,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
+ TCP_SKB_CB(skb)->flags = iph->tos;
+ TCP_SKB_CB(skb)->sacked = 0;
+
+- sk = __inet_lookup(skb->dev->nd_net, &tcp_hashinfo, iph->saddr,
++ sk = __inet_lookup(dev_net(skb->dev), &tcp_hashinfo, iph->saddr,
+ th->source, iph->daddr, th->dest, inet_iif(skb));
+ if (!sk)
+ goto no_tcp_socket;
+@@ -1719,7 +1716,7 @@ do_time_wait:
+ }
+ switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
+ case TCP_TW_SYN: {
+- struct sock *sk2 = inet_lookup_listener(skb->dev->nd_net,
++ struct sock *sk2 = inet_lookup_listener(dev_net(skb->dev),
+ &tcp_hashinfo,
+ iph->daddr, th->dest,
+ inet_iif(skb));
+@@ -1921,6 +1918,14 @@ int tcp_v4_destroy_sock(struct sock *sk)
+ sk->sk_sndmsg_page = NULL;
+ }
+
++ if (tp->defer_tcp_accept.request) {
++ reqsk_free(tp->defer_tcp_accept.request);
++ sock_put(tp->defer_tcp_accept.listen_sk);
++ sock_put(sk);
++ tp->defer_tcp_accept.listen_sk = NULL;
++ tp->defer_tcp_accept.request = NULL;
++ }
++
+ atomic_dec(&tcp_sockets_allocated);
+
+ return 0;
+@@ -1949,6 +1954,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
+ struct hlist_node *node;
+ struct sock *sk = cur;
+ struct tcp_iter_state* st = seq->private;
++ struct net *net = seq_file_net(seq);
+
+ if (!sk) {
+ st->bucket = 0;
+@@ -1965,7 +1971,8 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
+ req = req->dl_next;
+ while (1) {
+ while (req) {
+- if (req->rsk_ops->family == st->family) {
++ if (req->rsk_ops->family == st->family &&
++ net_eq(sock_net(req->sk), net)) {
+ cur = req;
+ goto out;
+ }
+@@ -1989,7 +1996,7 @@ get_req:
+ }
+ get_sk:
+ sk_for_each_from(sk, node) {
+- if (sk->sk_family == st->family) {
++ if (sk->sk_family == st->family && net_eq(sock_net(sk), net)) {
+ cur = sk;
+ goto out;
+ }
+@@ -2028,6 +2035,7 @@ static void *listening_get_idx(struct seq_file *seq, loff_t *pos)
+ static void *established_get_first(struct seq_file *seq)
+ {
+ struct tcp_iter_state* st = seq->private;
++ struct net *net = seq_file_net(seq);
+ void *rc = NULL;
+
+ for (st->bucket = 0; st->bucket < tcp_hashinfo.ehash_size; ++st->bucket) {
+@@ -2038,7 +2046,8 @@ static void *established_get_first(struct seq_file *seq)
+
+ read_lock_bh(lock);
+ sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) {
+- if (sk->sk_family != st->family) {
++ if (sk->sk_family != st->family ||
++ !net_eq(sock_net(sk), net)) {
+ continue;
+ }
+ rc = sk;
+@@ -2047,7 +2056,8 @@ static void *established_get_first(struct seq_file *seq)
+ st->state = TCP_SEQ_STATE_TIME_WAIT;
+ inet_twsk_for_each(tw, node,
+ &tcp_hashinfo.ehash[st->bucket].twchain) {
+- if (tw->tw_family != st->family) {
++ if (tw->tw_family != st->family ||
++ !net_eq(twsk_net(tw), net)) {
+ continue;
+ }
+ rc = tw;
+@@ -2066,6 +2076,7 @@ static void *established_get_next(struct seq_file *seq, void *cur)
+ struct inet_timewait_sock *tw;
+ struct hlist_node *node;
+ struct tcp_iter_state* st = seq->private;
++ struct net *net = seq_file_net(seq);
+
+ ++st->num;
+
+@@ -2073,7 +2084,7 @@ static void *established_get_next(struct seq_file *seq, void *cur)
+ tw = cur;
+ tw = tw_next(tw);
+ get_tw:
+- while (tw && tw->tw_family != st->family) {
++ while (tw && (tw->tw_family != st->family || !net_eq(twsk_net(tw), net))) {
+ tw = tw_next(tw);
+ }
+ if (tw) {
+@@ -2094,7 +2105,7 @@ get_tw:
+ sk = sk_next(sk);
+
+ sk_for_each_from(sk, node) {
+- if (sk->sk_family == st->family)
++ if (sk->sk_family == st->family && net_eq(sock_net(sk), net))
+ goto found;
+ }
+
+@@ -2200,48 +2211,37 @@ static void tcp_seq_stop(struct seq_file *seq, void *v)
+ static int tcp_seq_open(struct inode *inode, struct file *file)
+ {
+ struct tcp_seq_afinfo *afinfo = PDE(inode)->data;
+- struct seq_file *seq;
+ struct tcp_iter_state *s;
+- int rc;
++ int err;
+
+ if (unlikely(afinfo == NULL))
+ return -EINVAL;
+
+- s = kzalloc(sizeof(*s), GFP_KERNEL);
+- if (!s)
+- return -ENOMEM;
++ err = seq_open_net(inode, file, &afinfo->seq_ops,
++ sizeof(struct tcp_iter_state));
++ if (err < 0)
++ return err;
++
++ s = ((struct seq_file *)file->private_data)->private;
+ s->family = afinfo->family;
+- s->seq_ops.start = tcp_seq_start;
+- s->seq_ops.next = tcp_seq_next;
+- s->seq_ops.show = afinfo->seq_show;
+- s->seq_ops.stop = tcp_seq_stop;
+-
+- rc = seq_open(file, &s->seq_ops);
+- if (rc)
+- goto out_kfree;
+- seq = file->private_data;
+- seq->private = s;
+-out:
+- return rc;
+-out_kfree:
+- kfree(s);
+- goto out;
++ return 0;
+ }
+
+-int tcp_proc_register(struct tcp_seq_afinfo *afinfo)
++int tcp_proc_register(struct net *net, struct tcp_seq_afinfo *afinfo)
+ {
+ int rc = 0;
+ struct proc_dir_entry *p;
+
+- if (!afinfo)
+- return -EINVAL;
+- afinfo->seq_fops->owner = afinfo->owner;
+- afinfo->seq_fops->open = tcp_seq_open;
+- afinfo->seq_fops->read = seq_read;
+- afinfo->seq_fops->llseek = seq_lseek;
+- afinfo->seq_fops->release = seq_release_private;
++ afinfo->seq_fops.open = tcp_seq_open;
++ afinfo->seq_fops.read = seq_read;
++ afinfo->seq_fops.llseek = seq_lseek;
++ afinfo->seq_fops.release = seq_release_net;
++
++ afinfo->seq_ops.start = tcp_seq_start;
++ afinfo->seq_ops.next = tcp_seq_next;
++ afinfo->seq_ops.stop = tcp_seq_stop;
+
+- p = proc_net_fops_create(&init_net, afinfo->name, S_IRUGO, afinfo->seq_fops);
++ p = proc_net_fops_create(net, afinfo->name, S_IRUGO, &afinfo->seq_fops);
+ if (p)
+ p->data = afinfo;
+ else
+@@ -2249,22 +2249,19 @@ int tcp_proc_register(struct tcp_seq_afinfo *afinfo)
+ return rc;
+ }
+
+-void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo)
++void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo)
+ {
+- if (!afinfo)
+- return;
+- proc_net_remove(&init_net, afinfo->name);
+- memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));
++ proc_net_remove(net, afinfo->name);
+ }
+
+ static void get_openreq4(struct sock *sk, struct request_sock *req,
+- char *tmpbuf, int i, int uid)
++ struct seq_file *f, int i, int uid, int *len)
+ {
+ const struct inet_request_sock *ireq = inet_rsk(req);
+ int ttd = req->expires - jiffies;
+
+- sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
+- " %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %p",
++ seq_printf(f, "%4d: %08X:%04X %08X:%04X"
++ " %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %p%n",
+ i,
+ ireq->loc_addr,
+ ntohs(inet_sk(sk)->sport),
+@@ -2279,10 +2276,11 @@ static void get_openreq4(struct sock *sk, struct request_sock *req,
+ 0, /* non standard timer */
+ 0, /* open_requests have no inode */
+ atomic_read(&sk->sk_refcnt),
+- req);
++ req,
++ len);
+ }
+
+-static void get_tcp4_sock(struct sock *sk, char *tmpbuf, int i)
++static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len)
+ {
+ int timer_active;
+ unsigned long timer_expires;
+@@ -2308,8 +2306,8 @@ static void get_tcp4_sock(struct sock *sk, char *tmpbuf, int i)
+ timer_expires = jiffies;
+ }
+
+- sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX "
+- "%08X %5d %8d %lu %d %p %u %u %u %u %d",
++ seq_printf(f, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX "
++ "%08X %5d %8d %lu %d %p %u %u %u %u %d%n",
+ i, src, srcp, dest, destp, sk->sk_state,
+ tp->write_seq - tp->snd_una,
+ sk->sk_state == TCP_LISTEN ? sk->sk_ack_backlog :
+@@ -2325,11 +2323,12 @@ static void get_tcp4_sock(struct sock *sk, char *tmpbuf, int i)
+ icsk->icsk_ack.ato,
+ (icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong,
+ tp->snd_cwnd,
+- tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh);
++ tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh,
++ len);
+ }
+
+ static void get_timewait4_sock(struct inet_timewait_sock *tw,
+- char *tmpbuf, int i)
++ struct seq_file *f, int i, int *len)
+ {
+ __be32 dest, src;
+ __u16 destp, srcp;
+@@ -2343,11 +2342,11 @@ static void get_timewait4_sock(struct inet_timewait_sock *tw,
+ destp = ntohs(tw->tw_dport);
+ srcp = ntohs(tw->tw_sport);
+
+- sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
+- " %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p",
++ seq_printf(f, "%4d: %08X:%04X %08X:%04X"
++ " %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p%n",
+ i, src, srcp, dest, destp, tw->tw_substate, 0, 0,
+ 3, jiffies_to_clock_t(ttd), 0, 0, 0, 0,
+- atomic_read(&tw->tw_refcnt), tw);
++ atomic_read(&tw->tw_refcnt), tw, len);
+ }
+
+ #define TMPSZ 150
+@@ -2355,7 +2354,7 @@ static void get_timewait4_sock(struct inet_timewait_sock *tw,
+ static int tcp4_seq_show(struct seq_file *seq, void *v)
+ {
+ struct tcp_iter_state* st;
+- char tmpbuf[TMPSZ + 1];
++ int len;
+
+ if (v == SEQ_START_TOKEN) {
+ seq_printf(seq, "%-*s\n", TMPSZ - 1,
+@@ -2369,42 +2368,57 @@ static int tcp4_seq_show(struct seq_file *seq, void *v)
+ switch (st->state) {
+ case TCP_SEQ_STATE_LISTENING:
+ case TCP_SEQ_STATE_ESTABLISHED:
+- get_tcp4_sock(v, tmpbuf, st->num);
++ get_tcp4_sock(v, seq, st->num, &len);
+ break;
+ case TCP_SEQ_STATE_OPENREQ:
+- get_openreq4(st->syn_wait_sk, v, tmpbuf, st->num, st->uid);
++ get_openreq4(st->syn_wait_sk, v, seq, st->num, st->uid, &len);
+ break;
+ case TCP_SEQ_STATE_TIME_WAIT:
+- get_timewait4_sock(v, tmpbuf, st->num);
++ get_timewait4_sock(v, seq, st->num, &len);
+ break;
+ }
+- seq_printf(seq, "%-*s\n", TMPSZ - 1, tmpbuf);
++ seq_printf(seq, "%*s\n", TMPSZ - 1 - len, "");
+ out:
+ return 0;
+ }
+
+-static struct file_operations tcp4_seq_fops;
+ static struct tcp_seq_afinfo tcp4_seq_afinfo = {
+- .owner = THIS_MODULE,
+ .name = "tcp",
+ .family = AF_INET,
+- .seq_show = tcp4_seq_show,
+- .seq_fops = &tcp4_seq_fops,
++ .seq_fops = {
++ .owner = THIS_MODULE,
++ },
++ .seq_ops = {
++ .show = tcp4_seq_show,
++ },
++};
++
++static int tcp4_proc_init_net(struct net *net)
++{
++ return tcp_proc_register(net, &tcp4_seq_afinfo);
++}
++
++static void tcp4_proc_exit_net(struct net *net)
++{
++ tcp_proc_unregister(net, &tcp4_seq_afinfo);
++}
++
++static struct pernet_operations tcp4_net_ops = {
++ .init = tcp4_proc_init_net,
++ .exit = tcp4_proc_exit_net,
+ };
+
+ int __init tcp4_proc_init(void)
+ {
+- return tcp_proc_register(&tcp4_seq_afinfo);
++ return register_pernet_subsys(&tcp4_net_ops);
+ }
+
+ void tcp4_proc_exit(void)
+ {
+- tcp_proc_unregister(&tcp4_seq_afinfo);
++ unregister_pernet_subsys(&tcp4_net_ops);
+ }
+ #endif /* CONFIG_PROC_FS */
+
+-DEFINE_PROTO_INUSE(tcp)
+-
+ struct proto tcp_prot = {
+ .name = "TCP",
+ .owner = THIS_MODULE,
+@@ -2435,18 +2449,33 @@ struct proto tcp_prot = {
+ .obj_size = sizeof(struct tcp_sock),
+ .twsk_prot = &tcp_timewait_sock_ops,
+ .rsk_prot = &tcp_request_sock_ops,
+- .hashinfo = &tcp_hashinfo,
++ .h.hashinfo = &tcp_hashinfo,
+ #ifdef CONFIG_COMPAT
+ .compat_setsockopt = compat_tcp_setsockopt,
+ .compat_getsockopt = compat_tcp_getsockopt,
+ #endif
+- REF_PROTO_INUSE(tcp)
+ };
+
+-void __init tcp_v4_init(struct net_proto_family *ops)
++
++static int __net_init tcp_sk_init(struct net *net)
++{
++ return inet_ctl_sock_create(&net->ipv4.tcp_sock,
++ PF_INET, SOCK_RAW, IPPROTO_TCP, net);
++}
++
++static void __net_exit tcp_sk_exit(struct net *net)
++{
++ inet_ctl_sock_destroy(net->ipv4.tcp_sock);
++}
++
++static struct pernet_operations __net_initdata tcp_sk_ops = {
++ .init = tcp_sk_init,
++ .exit = tcp_sk_exit,
++};
++
++void __init tcp_v4_init(void)
+ {
+- if (inet_csk_ctl_sock_create(&tcp_socket, PF_INET, SOCK_RAW,
+- IPPROTO_TCP) < 0)
++ if (register_pernet_device(&tcp_sk_ops))
+ panic("Failed to create the TCP control socket.\n");
+ }
+
+diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
+index b61b768..019c8c1 100644
+--- a/net/ipv4/tcp_minisocks.c
++++ b/net/ipv4/tcp_minisocks.c
+@@ -35,6 +35,8 @@
+ #endif
+
+ int sysctl_tcp_syncookies __read_mostly = SYNC_INIT;
++EXPORT_SYMBOL(sysctl_tcp_syncookies);
++
+ int sysctl_tcp_abort_on_overflow __read_mostly;
+
+ struct inet_timewait_death_row tcp_death_row = {
+@@ -536,7 +538,7 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
+ * Enforce "SYN-ACK" according to figure 8, figure 6
+ * of RFC793, fixed by RFC1122.
+ */
+- req->rsk_ops->rtx_syn_ack(sk, req, NULL);
++ req->rsk_ops->rtx_syn_ack(sk, req);
+ return NULL;
+ }
+
+@@ -569,10 +571,8 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
+ does sequence test, SYN is truncated, and thus we consider
+ it a bare ACK.
+
+- If icsk->icsk_accept_queue.rskq_defer_accept, we silently drop this
+- bare ACK. Otherwise, we create an established connection. Both
+- ends (listening sockets) accept the new incoming connection and try
+- to talk to each other. 8-)
++ Both ends (listening sockets) accept the new incoming
++ connection and try to talk to each other. 8-)
+
+ Note: This case is both harmless, and rare. Possibility is about the
+ same as us discovering intelligent life on another plant tomorrow.
+@@ -640,13 +640,6 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
+ if (!(flg & TCP_FLAG_ACK))
+ return NULL;
+
+- /* If TCP_DEFER_ACCEPT is set, drop bare ACK. */
+- if (inet_csk(sk)->icsk_accept_queue.rskq_defer_accept &&
+- TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) {
+- inet_rsk(req)->acked = 1;
+- return NULL;
+- }
+-
+ /* OK, ACK is valid, create big socket and
+ * feed this segment to it. It will repeat all
+ * the tests. THIS SEGMENT MUST MOVE SOCKET TO
+@@ -685,7 +678,24 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
+ inet_csk_reqsk_queue_unlink(sk, req, prev);
+ inet_csk_reqsk_queue_removed(sk, req);
+
+- inet_csk_reqsk_queue_add(sk, req, child);
++ if (inet_csk(sk)->icsk_accept_queue.rskq_defer_accept &&
++ TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) {
++
++ /* the accept queue handling is done is est recv slow
++ * path so lets make sure to start there
++ */
++ tcp_sk(child)->pred_flags = 0;
++ sock_hold(sk);
++ sock_hold(child);
++ tcp_sk(child)->defer_tcp_accept.listen_sk = sk;
++ tcp_sk(child)->defer_tcp_accept.request = req;
++
++ inet_csk_reset_keepalive_timer(child,
++ inet_csk(sk)->icsk_accept_queue.rskq_defer_accept * HZ);
++ } else {
++ inet_csk_reqsk_queue_add(sk, req, child);
++ }
++
+ return child;
+
+ listen_overflow:
+diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
+index d29ef79..debf235 100644
+--- a/net/ipv4/tcp_output.c
++++ b/net/ipv4/tcp_output.c
+@@ -998,7 +998,7 @@ unsigned int tcp_current_mss(struct sock *sk, int large_allowed)
+ xmit_size_goal = mss_now;
+
+ if (doing_tso) {
+- xmit_size_goal = (65535 -
++ xmit_size_goal = ((sk->sk_gso_max_size - 1) -
+ inet_csk(sk)->icsk_af_ops->net_header_len -
+ inet_csk(sk)->icsk_ext_hdr_len -
+ tp->tcp_header_len);
+@@ -1057,7 +1057,7 @@ static unsigned int tcp_mss_split_point(struct sock *sk, struct sk_buff *skb,
+
+ needed = min(skb->len, window);
+
+- if (skb == tcp_write_queue_tail(sk) && cwnd_len <= needed)
++ if (cwnd_len <= needed)
+ return cwnd_len;
+
+ return needed - needed % mss_now;
+@@ -1282,7 +1282,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb)
+ limit = min(send_win, cong_win);
+
+ /* If a full-sized TSO skb can be sent, do it. */
+- if (limit >= 65536)
++ if (limit >= sk->sk_gso_max_size)
+ goto send_now;
+
+ if (sysctl_tcp_tso_win_divisor) {
+@@ -2236,7 +2236,11 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
+
+ /* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */
+ th->window = htons(min(req->rcv_wnd, 65535U));
+-
++#ifdef CONFIG_SYN_COOKIES
++ if (unlikely(req->cookie_ts))
++ TCP_SKB_CB(skb)->when = cookie_init_timestamp(req);
++ else
++#endif
+ TCP_SKB_CB(skb)->when = tcp_time_stamp;
+ tcp_syn_build_options((__be32 *)(th + 1), dst_metric(dst, RTAX_ADVMSS), ireq->tstamp_ok,
+ ireq->sack_ok, ireq->wscale_ok, ireq->rcv_wscale,
+@@ -2571,6 +2575,7 @@ void tcp_send_probe0(struct sock *sk)
+ }
+ }
+
++EXPORT_SYMBOL(tcp_select_initial_window);
+ EXPORT_SYMBOL(tcp_connect);
+ EXPORT_SYMBOL(tcp_make_synack);
+ EXPORT_SYMBOL(tcp_simple_retransmit);
+diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c
+index 87dd5bf..5ff0ce6 100644
+--- a/net/ipv4/tcp_probe.c
++++ b/net/ipv4/tcp_probe.c
+@@ -153,7 +153,7 @@ static int tcpprobe_sprint(char *tbuf, int n)
+ = ktime_to_timespec(ktime_sub(p->tstamp, tcp_probe.start));
+
+ return snprintf(tbuf, n,
+- "%lu.%09lu %d.%d.%d.%d:%u %d.%d.%d.%d:%u"
++ "%lu.%09lu " NIPQUAD_FMT ":%u " NIPQUAD_FMT ":%u"
+ " %d %#x %#x %u %u %u %u\n",
+ (unsigned long) tv.tv_sec,
+ (unsigned long) tv.tv_nsec,
+@@ -190,19 +190,18 @@ static ssize_t tcpprobe_read(struct file *file, char __user *buf,
+
+ width = tcpprobe_sprint(tbuf, sizeof(tbuf));
+
+- if (width < len)
++ if (cnt + width < len)
+ tcp_probe.tail = (tcp_probe.tail + 1) % bufsize;
+
+ spin_unlock_bh(&tcp_probe.lock);
+
+ /* if record greater than space available
+ return partial buffer (so far) */
+- if (width >= len)
++ if (cnt + width >= len)
+ break;
+
+- error = copy_to_user(buf + cnt, tbuf, width);
+- if (error)
+- break;
++ if (copy_to_user(buf + cnt, tbuf, width))
++ return -EFAULT;
+ cnt += width;
+ }
+
+diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
+index 803d758..4de68cf 100644
+--- a/net/ipv4/tcp_timer.c
++++ b/net/ipv4/tcp_timer.c
+@@ -299,12 +299,20 @@ static void tcp_retransmit_timer(struct sock *sk)
+ * we cannot allow such beasts to hang infinitely.
+ */
+ #ifdef TCP_DEBUG
+- if (1) {
+- struct inet_sock *inet = inet_sk(sk);
+- LIMIT_NETDEBUG(KERN_DEBUG "TCP: Treason uncloaked! Peer %u.%u.%u.%u:%u/%u shrinks window %u:%u. Repaired.\n",
++ struct inet_sock *inet = inet_sk(sk);
++ if (sk->sk_family == AF_INET) {
++ LIMIT_NETDEBUG(KERN_DEBUG "TCP: Treason uncloaked! Peer " NIPQUAD_FMT ":%u/%u shrinks window %u:%u. Repaired.\n",
+ NIPQUAD(inet->daddr), ntohs(inet->dport),
+ inet->num, tp->snd_una, tp->snd_nxt);
+ }
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++ else if (sk->sk_family == AF_INET6) {
++ struct ipv6_pinfo *np = inet6_sk(sk);
++ LIMIT_NETDEBUG(KERN_DEBUG "TCP: Treason uncloaked! Peer " NIP6_FMT ":%u/%u shrinks window %u:%u. Repaired.\n",
++ NIP6(np->daddr), ntohs(inet->dport),
++ inet->num, tp->snd_una, tp->snd_nxt);
++ }
++#endif
+ #endif
+ if (tcp_time_stamp - tp->rcv_tstamp > TCP_RTO_MAX) {
+ tcp_write_err(sk);
+@@ -481,6 +489,11 @@ static void tcp_keepalive_timer (unsigned long data)
+ goto death;
+ }
+
++ if (tp->defer_tcp_accept.request && sk->sk_state == TCP_ESTABLISHED) {
++ tcp_send_active_reset(sk, GFP_ATOMIC);
++ goto death;
++ }
++
+ if (!sock_flag(sk, SOCK_KEEPOPEN) || sk->sk_state == TCP_CLOSE)
+ goto out;
+
+diff --git a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c
+index 978b3fd..d3b709a 100644
+--- a/net/ipv4/tunnel4.c
++++ b/net/ipv4/tunnel4.c
+@@ -136,6 +136,7 @@ static struct net_protocol tunnel4_protocol = {
+ .handler = tunnel4_rcv,
+ .err_handler = tunnel4_err,
+ .no_policy = 1,
++ .netns_ok = 1,
+ };
+
+ #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+@@ -143,6 +144,7 @@ static struct net_protocol tunnel64_protocol = {
+ .handler = tunnel64_rcv,
+ .err_handler = tunnel64_err,
+ .no_policy = 1,
++ .netns_ok = 1,
+ };
+ #endif
+
+diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
+index 1704c14..1f535e3 100644
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -137,29 +137,28 @@ static inline int __udp_lib_lport_inuse(struct net *net, __u16 num,
+ struct hlist_node *node;
+
+ sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)])
+- if (sk->sk_net == net && sk->sk_hash == num)
++ if (net_eq(sock_net(sk), net) && sk->sk_hash == num)
+ return 1;
+ return 0;
+ }
+
+ /**
+- * __udp_lib_get_port - UDP/-Lite port lookup for IPv4 and IPv6
++ * udp_lib_get_port - UDP/-Lite port lookup for IPv4 and IPv6
+ *
+ * @sk: socket struct in question
+ * @snum: port number to look up
+- * @udptable: hash list table, must be of UDP_HTABLE_SIZE
+ * @saddr_comp: AF-dependent comparison of bound local IP addresses
+ */
+-int __udp_lib_get_port(struct sock *sk, unsigned short snum,
+- struct hlist_head udptable[],
++int udp_lib_get_port(struct sock *sk, unsigned short snum,
+ int (*saddr_comp)(const struct sock *sk1,
+ const struct sock *sk2 ) )
+ {
++ struct hlist_head *udptable = sk->sk_prot->h.udp_hash;
+ struct hlist_node *node;
+ struct hlist_head *head;
+ struct sock *sk2;
+ int error = 1;
+- struct net *net = sk->sk_net;
++ struct net *net = sock_net(sk);
+
+ write_lock_bh(&udp_hash_lock);
+
+@@ -219,7 +218,7 @@ gotit:
+ sk_for_each(sk2, node, head)
+ if (sk2->sk_hash == snum &&
+ sk2 != sk &&
+- sk2->sk_net == net &&
++ net_eq(sock_net(sk2), net) &&
+ (!sk2->sk_reuse || !sk->sk_reuse) &&
+ (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if
+ || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
+@@ -232,7 +231,7 @@ gotit:
+ if (sk_unhashed(sk)) {
+ head = &udptable[snum & (UDP_HTABLE_SIZE - 1)];
+ sk_add_node(sk, head);
+- sock_prot_inuse_add(sk->sk_prot, 1);
++ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
+ }
+ error = 0;
+ fail:
+@@ -240,13 +239,7 @@ fail:
+ return error;
+ }
+
+-int udp_get_port(struct sock *sk, unsigned short snum,
+- int (*scmp)(const struct sock *, const struct sock *))
+-{
+- return __udp_lib_get_port(sk, snum, udp_hash, scmp);
+-}
+-
+-int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
++static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
+ {
+ struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2);
+
+@@ -255,9 +248,9 @@ int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
+ inet1->rcv_saddr == inet2->rcv_saddr ));
+ }
+
+-static inline int udp_v4_get_port(struct sock *sk, unsigned short snum)
++int udp_v4_get_port(struct sock *sk, unsigned short snum)
+ {
+- return udp_get_port(sk, snum, ipv4_rcv_saddr_equal);
++ return udp_lib_get_port(sk, snum, ipv4_rcv_saddr_equal);
+ }
+
+ /* UDP is nearly always wildcards out the wazoo, it makes no sense to try
+@@ -276,7 +269,7 @@ static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,
+ sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) {
+ struct inet_sock *inet = inet_sk(sk);
+
+- if (sk->sk_net == net && sk->sk_hash == hnum &&
++ if (net_eq(sock_net(sk), net) && sk->sk_hash == hnum &&
+ !ipv6_only_sock(sk)) {
+ int score = (sk->sk_family == PF_INET ? 1 : 0);
+ if (inet->rcv_saddr) {
+@@ -364,7 +357,7 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct hlist_head udptable[])
+ int harderr;
+ int err;
+
+- sk = __udp4_lib_lookup(skb->dev->nd_net, iph->daddr, uh->dest,
++ sk = __udp4_lib_lookup(dev_net(skb->dev), iph->daddr, uh->dest,
+ iph->saddr, uh->source, skb->dev->ifindex, udptable);
+ if (sk == NULL) {
+ ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
+@@ -614,7 +607,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+
+ ipc.oif = sk->sk_bound_dev_if;
+ if (msg->msg_controllen) {
+- err = ip_cmsg_send(msg, &ipc);
++ err = ip_cmsg_send(sock_net(sk), msg, &ipc);
+ if (err)
+ return err;
+ if (ipc.opt)
+@@ -663,7 +656,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ { .sport = inet->sport,
+ .dport = dport } } };
+ security_sk_classify_flow(sk, &fl);
+- err = ip_route_output_flow(&init_net, &rt, &fl, sk, 1);
++ err = ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 1);
+ if (err) {
+ if (err == -ENETUNREACH)
+ IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
+@@ -1188,7 +1181,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
+ if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
+ return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable);
+
+- sk = __udp4_lib_lookup(skb->dev->nd_net, saddr, uh->source, daddr,
++ sk = __udp4_lib_lookup(dev_net(skb->dev), saddr, uh->source, daddr,
+ uh->dest, inet_iif(skb), udptable);
+
+ if (sk != NULL) {
+@@ -1228,7 +1221,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
+ return 0;
+
+ short_packet:
+- LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: short packet: From %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n",
++ LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: short packet: From " NIPQUAD_FMT ":%u %d/%d to " NIPQUAD_FMT ":%u\n",
+ proto == IPPROTO_UDPLITE ? "-Lite" : "",
+ NIPQUAD(saddr),
+ ntohs(uh->source),
+@@ -1243,7 +1236,7 @@ csum_error:
+ * RFC1122: OK. Discards the bad packet silently (as far as
+ * the network is concerned, anyway) as per 4.1.3.4 (MUST).
+ */
+- LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n",
++ LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: bad checksum. From " NIPQUAD_FMT ":%u to " NIPQUAD_FMT ":%u ulen %d\n",
+ proto == IPPROTO_UDPLITE ? "-Lite" : "",
+ NIPQUAD(saddr),
+ ntohs(uh->source),
+@@ -1474,8 +1467,6 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
+
+ }
+
+-DEFINE_PROTO_INUSE(udp)
+-
+ struct proto udp_prot = {
+ .name = "UDP",
+ .owner = THIS_MODULE,
+@@ -1498,11 +1489,11 @@ struct proto udp_prot = {
+ .sysctl_wmem = &sysctl_udp_wmem_min,
+ .sysctl_rmem = &sysctl_udp_rmem_min,
+ .obj_size = sizeof(struct udp_sock),
++ .h.udp_hash = udp_hash,
+ #ifdef CONFIG_COMPAT
+ .compat_setsockopt = compat_udp_setsockopt,
+ .compat_getsockopt = compat_udp_getsockopt,
+ #endif
+- REF_PROTO_INUSE(udp)
+ };
+
+ /* ------------------------------------------------------------------------ */
+@@ -1512,10 +1503,13 @@ static struct sock *udp_get_first(struct seq_file *seq)
+ {
+ struct sock *sk;
+ struct udp_iter_state *state = seq->private;
++ struct net *net = seq_file_net(seq);
+
+ for (state->bucket = 0; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) {
+ struct hlist_node *node;
+ sk_for_each(sk, node, state->hashtable + state->bucket) {
++ if (!net_eq(sock_net(sk), net))
++ continue;
+ if (sk->sk_family == state->family)
+ goto found;
+ }
+@@ -1528,12 +1522,13 @@ found:
+ static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk)
+ {
+ struct udp_iter_state *state = seq->private;
++ struct net *net = seq_file_net(seq);
+
+ do {
+ sk = sk_next(sk);
+ try_again:
+ ;
+- } while (sk && sk->sk_family != state->family);
++ } while (sk && (!net_eq(sock_net(sk), net) || sk->sk_family != state->family));
+
+ if (!sk && ++state->bucket < UDP_HTABLE_SIZE) {
+ sk = sk_head(state->hashtable + state->bucket);
+@@ -1581,47 +1576,36 @@ static void udp_seq_stop(struct seq_file *seq, void *v)
+ static int udp_seq_open(struct inode *inode, struct file *file)
+ {
+ struct udp_seq_afinfo *afinfo = PDE(inode)->data;
+- struct seq_file *seq;
+- int rc = -ENOMEM;
+- struct udp_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
++ struct udp_iter_state *s;
++ int err;
+
+- if (!s)
+- goto out;
++ err = seq_open_net(inode, file, &afinfo->seq_ops,
++ sizeof(struct udp_iter_state));
++ if (err < 0)
++ return err;
++
++ s = ((struct seq_file *)file->private_data)->private;
+ s->family = afinfo->family;
+ s->hashtable = afinfo->hashtable;
+- s->seq_ops.start = udp_seq_start;
+- s->seq_ops.next = udp_seq_next;
+- s->seq_ops.show = afinfo->seq_show;
+- s->seq_ops.stop = udp_seq_stop;
+-
+- rc = seq_open(file, &s->seq_ops);
+- if (rc)
+- goto out_kfree;
+-
+- seq = file->private_data;
+- seq->private = s;
+-out:
+- return rc;
+-out_kfree:
+- kfree(s);
+- goto out;
++ return err;
+ }
+
+ /* ------------------------------------------------------------------------ */
+-int udp_proc_register(struct udp_seq_afinfo *afinfo)
++int udp_proc_register(struct net *net, struct udp_seq_afinfo *afinfo)
+ {
+ struct proc_dir_entry *p;
+ int rc = 0;
+
+- if (!afinfo)
+- return -EINVAL;
+- afinfo->seq_fops->owner = afinfo->owner;
+- afinfo->seq_fops->open = udp_seq_open;
+- afinfo->seq_fops->read = seq_read;
+- afinfo->seq_fops->llseek = seq_lseek;
+- afinfo->seq_fops->release = seq_release_private;
++ afinfo->seq_fops.open = udp_seq_open;
++ afinfo->seq_fops.read = seq_read;
++ afinfo->seq_fops.llseek = seq_lseek;
++ afinfo->seq_fops.release = seq_release_net;
++
++ afinfo->seq_ops.start = udp_seq_start;
++ afinfo->seq_ops.next = udp_seq_next;
++ afinfo->seq_ops.stop = udp_seq_stop;
+
+- p = proc_net_fops_create(&init_net, afinfo->name, S_IRUGO, afinfo->seq_fops);
++ p = proc_net_fops_create(net, afinfo->name, S_IRUGO, &afinfo->seq_fops);
+ if (p)
+ p->data = afinfo;
+ else
+@@ -1629,16 +1613,14 @@ int udp_proc_register(struct udp_seq_afinfo *afinfo)
+ return rc;
+ }
+
+-void udp_proc_unregister(struct udp_seq_afinfo *afinfo)
++void udp_proc_unregister(struct net *net, struct udp_seq_afinfo *afinfo)
+ {
+- if (!afinfo)
+- return;
+- proc_net_remove(&init_net, afinfo->name);
+- memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));
++ proc_net_remove(net, afinfo->name);
+ }
+
+ /* ------------------------------------------------------------------------ */
+-static void udp4_format_sock(struct sock *sp, char *tmpbuf, int bucket)
++static void udp4_format_sock(struct sock *sp, struct seq_file *f,
++ int bucket, int *len)
+ {
+ struct inet_sock *inet = inet_sk(sp);
+ __be32 dest = inet->daddr;
+@@ -1646,13 +1628,13 @@ static void udp4_format_sock(struct sock *sp, char *tmpbuf, int bucket)
+ __u16 destp = ntohs(inet->dport);
+ __u16 srcp = ntohs(inet->sport);
+
+- sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
+- " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p",
++ seq_printf(f, "%4d: %08X:%04X %08X:%04X"
++ " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p%n",
+ bucket, src, srcp, dest, destp, sp->sk_state,
+ atomic_read(&sp->sk_wmem_alloc),
+ atomic_read(&sp->sk_rmem_alloc),
+ 0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp),
+- atomic_read(&sp->sk_refcnt), sp);
++ atomic_read(&sp->sk_refcnt), sp, len);
+ }
+
+ int udp4_seq_show(struct seq_file *seq, void *v)
+@@ -1663,34 +1645,51 @@ int udp4_seq_show(struct seq_file *seq, void *v)
+ "rx_queue tr tm->when retrnsmt uid timeout "
+ "inode");
+ else {
+- char tmpbuf[129];
+ struct udp_iter_state *state = seq->private;
++ int len;
+
+- udp4_format_sock(v, tmpbuf, state->bucket);
+- seq_printf(seq, "%-127s\n", tmpbuf);
++ udp4_format_sock(v, seq, state->bucket, &len);
++ seq_printf(seq, "%*s\n", 127 - len ,"");
+ }
+ return 0;
+ }
+
+ /* ------------------------------------------------------------------------ */
+-static struct file_operations udp4_seq_fops;
+ static struct udp_seq_afinfo udp4_seq_afinfo = {
+- .owner = THIS_MODULE,
+ .name = "udp",
+ .family = AF_INET,
+ .hashtable = udp_hash,
+- .seq_show = udp4_seq_show,
+- .seq_fops = &udp4_seq_fops,
++ .seq_fops = {
++ .owner = THIS_MODULE,
++ },
++ .seq_ops = {
++ .show = udp4_seq_show,
++ },
++};
++
++static int udp4_proc_init_net(struct net *net)
++{
++ return udp_proc_register(net, &udp4_seq_afinfo);
++}
++
++static void udp4_proc_exit_net(struct net *net)
++{
++ udp_proc_unregister(net, &udp4_seq_afinfo);
++}
++
++static struct pernet_operations udp4_net_ops = {
++ .init = udp4_proc_init_net,
++ .exit = udp4_proc_exit_net,
+ };
+
+ int __init udp4_proc_init(void)
+ {
+- return udp_proc_register(&udp4_seq_afinfo);
++ return register_pernet_subsys(&udp4_net_ops);
+ }
+
+ void udp4_proc_exit(void)
+ {
+- udp_proc_unregister(&udp4_seq_afinfo);
++ unregister_pernet_subsys(&udp4_net_ops);
+ }
+ #endif /* CONFIG_PROC_FS */
+
+@@ -1717,12 +1716,12 @@ EXPORT_SYMBOL(udp_disconnect);
+ EXPORT_SYMBOL(udp_hash);
+ EXPORT_SYMBOL(udp_hash_lock);
+ EXPORT_SYMBOL(udp_ioctl);
+-EXPORT_SYMBOL(udp_get_port);
+ EXPORT_SYMBOL(udp_prot);
+ EXPORT_SYMBOL(udp_sendmsg);
+ EXPORT_SYMBOL(udp_lib_getsockopt);
+ EXPORT_SYMBOL(udp_lib_setsockopt);
+ EXPORT_SYMBOL(udp_poll);
++EXPORT_SYMBOL(udp_lib_get_port);
+
+ #ifdef CONFIG_PROC_FS
+ EXPORT_SYMBOL(udp_proc_register);
+diff --git a/net/ipv4/udp_impl.h b/net/ipv4/udp_impl.h
+index 6c55828..7288bf7 100644
+--- a/net/ipv4/udp_impl.h
++++ b/net/ipv4/udp_impl.h
+@@ -8,11 +8,7 @@
+ extern int __udp4_lib_rcv(struct sk_buff *, struct hlist_head [], int );
+ extern void __udp4_lib_err(struct sk_buff *, u32, struct hlist_head []);
+
+-extern int __udp_lib_get_port(struct sock *sk, unsigned short snum,
+- struct hlist_head udptable[],
+- int (*)(const struct sock*,const struct sock*));
+-extern int ipv4_rcv_saddr_equal(const struct sock *, const struct sock *);
+-
++extern int udp_v4_get_port(struct sock *sk, unsigned short snum);
+
+ extern int udp_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int optlen);
+diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c
+index 001b881..72ce26b 100644
+--- a/net/ipv4/udplite.c
++++ b/net/ipv4/udplite.c
+@@ -17,17 +17,6 @@ DEFINE_SNMP_STAT(struct udp_mib, udplite_statistics) __read_mostly;
+
+ struct hlist_head udplite_hash[UDP_HTABLE_SIZE];
+
+-int udplite_get_port(struct sock *sk, unsigned short p,
+- int (*c)(const struct sock *, const struct sock *))
+-{
+- return __udp_lib_get_port(sk, p, udplite_hash, c);
+-}
+-
+-static int udplite_v4_get_port(struct sock *sk, unsigned short snum)
+-{
+- return udplite_get_port(sk, snum, ipv4_rcv_saddr_equal);
+-}
+-
+ static int udplite_rcv(struct sk_buff *skb)
+ {
+ return __udp4_lib_rcv(skb, udplite_hash, IPPROTO_UDPLITE);
+@@ -42,10 +31,9 @@ static struct net_protocol udplite_protocol = {
+ .handler = udplite_rcv,
+ .err_handler = udplite_err,
+ .no_policy = 1,
++ .netns_ok = 1,
+ };
+
+-DEFINE_PROTO_INUSE(udplite)
+-
+ struct proto udplite_prot = {
+ .name = "UDP-Lite",
+ .owner = THIS_MODULE,
+@@ -63,13 +51,13 @@ struct proto udplite_prot = {
+ .backlog_rcv = udp_queue_rcv_skb,
+ .hash = udp_lib_hash,
+ .unhash = udp_lib_unhash,
+- .get_port = udplite_v4_get_port,
++ .get_port = udp_v4_get_port,
+ .obj_size = sizeof(struct udp_sock),
++ .h.udp_hash = udplite_hash,
+ #ifdef CONFIG_COMPAT
+ .compat_setsockopt = compat_udp_setsockopt,
+ .compat_getsockopt = compat_udp_getsockopt,
+ #endif
+- REF_PROTO_INUSE(udplite)
+ };
+
+ static struct inet_protosw udplite4_protosw = {
+@@ -83,15 +71,42 @@ static struct inet_protosw udplite4_protosw = {
+ };
+
+ #ifdef CONFIG_PROC_FS
+-static struct file_operations udplite4_seq_fops;
+ static struct udp_seq_afinfo udplite4_seq_afinfo = {
+- .owner = THIS_MODULE,
+ .name = "udplite",
+ .family = AF_INET,
+ .hashtable = udplite_hash,
+- .seq_show = udp4_seq_show,
+- .seq_fops = &udplite4_seq_fops,
++ .seq_fops = {
++ .owner = THIS_MODULE,
++ },
++ .seq_ops = {
++ .show = udp4_seq_show,
++ },
++};
++
++static int udplite4_proc_init_net(struct net *net)
++{
++ return udp_proc_register(net, &udplite4_seq_afinfo);
++}
++
++static void udplite4_proc_exit_net(struct net *net)
++{
++ udp_proc_unregister(net, &udplite4_seq_afinfo);
++}
++
++static struct pernet_operations udplite4_net_ops = {
++ .init = udplite4_proc_init_net,
++ .exit = udplite4_proc_exit_net,
+ };
++
++static __init int udplite4_proc_init(void)
++{
++ return register_pernet_subsys(&udplite4_net_ops);
++}
++#else
++static inline int udplite4_proc_init(void)
++{
++ return 0;
++}
+ #endif
+
+ void __init udplite4_register(void)
+@@ -104,18 +119,15 @@ void __init udplite4_register(void)
+
+ inet_register_protosw(&udplite4_protosw);
+
+-#ifdef CONFIG_PROC_FS
+- if (udp_proc_register(&udplite4_seq_afinfo)) /* udplite4_proc_init() */
+- printk(KERN_ERR "%s: Cannot register /proc!\n", __FUNCTION__);
+-#endif
++ if (udplite4_proc_init())
++ printk(KERN_ERR "%s: Cannot register /proc!\n", __func__);
+ return;
+
+ out_unregister_proto:
+ proto_unregister(&udplite_prot);
+ out_register_err:
+- printk(KERN_CRIT "%s: Cannot add UDP-Lite protocol.\n", __FUNCTION__);
++ printk(KERN_CRIT "%s: Cannot add UDP-Lite protocol.\n", __func__);
+ }
+
+ EXPORT_SYMBOL(udplite_hash);
+ EXPORT_SYMBOL(udplite_prot);
+-EXPORT_SYMBOL(udplite_get_port);
+diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
+index 10ed704..c63de0a 100644
+--- a/net/ipv4/xfrm4_policy.c
++++ b/net/ipv4/xfrm4_policy.c
+@@ -221,7 +221,7 @@ static void xfrm4_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
+ xdst = (struct xfrm_dst *)dst;
+ if (xdst->u.rt.idev->dev == dev) {
+ struct in_device *loopback_idev =
+- in_dev_get(dev->nd_net->loopback_dev);
++ in_dev_get(dev_net(dev)->loopback_dev);
+ BUG_ON(!loopback_idev);
+
+ do {
+diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
+index 47263e4..b2c9bec 100644
+--- a/net/ipv6/Kconfig
++++ b/net/ipv6/Kconfig
+@@ -3,7 +3,7 @@
+ #
+
+ # IPv6 as module will cause a CRASH if you try to unload it
+-config IPV6
++menuconfig IPV6
+ tristate "The IPv6 protocol"
+ default m
+ ---help---
+@@ -19,9 +19,10 @@ config IPV6
+ To compile this protocol support as a module, choose M here: the
+ module will be called ipv6.
+
++if IPV6
++
+ config IPV6_PRIVACY
+ bool "IPv6: Privacy Extensions support"
+- depends on IPV6
+ ---help---
+ Privacy Extensions for Stateless Address Autoconfiguration in IPv6
+ support. With this option, additional periodically-alter
+@@ -40,7 +41,6 @@ config IPV6_PRIVACY
+
+ config IPV6_ROUTER_PREF
+ bool "IPv6: Router Preference (RFC 4191) support"
+- depends on IPV6
+ ---help---
+ Router Preference is an optional extension to the Router
+ Advertisement message to improve the ability of hosts
+@@ -59,7 +59,7 @@ config IPV6_ROUTE_INFO
+
+ config IPV6_OPTIMISTIC_DAD
+ bool "IPv6: Enable RFC 4429 Optimistic DAD (EXPERIMENTAL)"
+- depends on IPV6 && EXPERIMENTAL
++ depends on EXPERIMENTAL
+ ---help---
+ This is experimental support for optimistic Duplicate
+ Address Detection. It allows for autoconfigured addresses
+@@ -69,7 +69,6 @@ config IPV6_OPTIMISTIC_DAD
+
+ config INET6_AH
+ tristate "IPv6: AH transformation"
+- depends on IPV6
+ select XFRM
+ select CRYPTO
+ select CRYPTO_HMAC
+@@ -82,7 +81,6 @@ config INET6_AH
+
+ config INET6_ESP
+ tristate "IPv6: ESP transformation"
+- depends on IPV6
+ select XFRM
+ select CRYPTO
+ select CRYPTO_AUTHENC
+@@ -98,7 +96,6 @@ config INET6_ESP
+
+ config INET6_IPCOMP
+ tristate "IPv6: IPComp transformation"
+- depends on IPV6
+ select XFRM
+ select INET6_XFRM_TUNNEL
+ select CRYPTO
+@@ -111,7 +108,7 @@ config INET6_IPCOMP
+
+ config IPV6_MIP6
+ tristate "IPv6: Mobility (EXPERIMENTAL)"
+- depends on IPV6 && EXPERIMENTAL
++ depends on EXPERIMENTAL
+ select XFRM
+ ---help---
+ Support for IPv6 Mobility described in RFC 3775.
+@@ -129,7 +126,6 @@ config INET6_TUNNEL
+
+ config INET6_XFRM_MODE_TRANSPORT
+ tristate "IPv6: IPsec transport mode"
+- depends on IPV6
+ default IPV6
+ select XFRM
+ ---help---
+@@ -139,7 +135,6 @@ config INET6_XFRM_MODE_TRANSPORT
+
+ config INET6_XFRM_MODE_TUNNEL
+ tristate "IPv6: IPsec tunnel mode"
+- depends on IPV6
+ default IPV6
+ select XFRM
+ ---help---
+@@ -149,7 +144,6 @@ config INET6_XFRM_MODE_TUNNEL
+
+ config INET6_XFRM_MODE_BEET
+ tristate "IPv6: IPsec BEET mode"
+- depends on IPV6
+ default IPV6
+ select XFRM
+ ---help---
+@@ -159,29 +153,31 @@ config INET6_XFRM_MODE_BEET
+
+ config INET6_XFRM_MODE_ROUTEOPTIMIZATION
+ tristate "IPv6: MIPv6 route optimization mode (EXPERIMENTAL)"
+- depends on IPV6 && EXPERIMENTAL
++ depends on EXPERIMENTAL
+ select XFRM
+ ---help---
+ Support for MIPv6 route optimization mode.
+
+ config IPV6_SIT
+ tristate "IPv6: IPv6-in-IPv4 tunnel (SIT driver)"
+- depends on IPV6
+ select INET_TUNNEL
++ select IPV6_NDISC_NODETYPE
+ default y
+ ---help---
+ Tunneling means encapsulating data of one protocol type within
+ another protocol and sending it over a channel that understands the
+ encapsulating protocol. This driver implements encapsulation of IPv6
+- into IPv4 packets. This is useful if you want to connect two IPv6
++ into IPv4 packets. This is useful if you want to connect to IPv6
+ networks over an IPv4-only path.
+
+ Saying M here will produce a module called sit.ko. If unsure, say Y.
+
++config IPV6_NDISC_NODETYPE
++ bool
++
+ config IPV6_TUNNEL
+ tristate "IPv6: IP-in-IPv6 tunnel (RFC2473)"
+ select INET6_TUNNEL
+- depends on IPV6
+ ---help---
+ Support for IPv6-in-IPv6 and IPv4-in-IPv6 tunnels described in
+ RFC 2473.
+@@ -190,7 +186,7 @@ config IPV6_TUNNEL
+
+ config IPV6_MULTIPLE_TABLES
+ bool "IPv6: Multiple Routing Tables"
+- depends on IPV6 && EXPERIMENTAL
++ depends on EXPERIMENTAL
+ select FIB_RULES
+ ---help---
+ Support multiple routing tables.
+@@ -209,3 +205,18 @@ config IPV6_SUBTREES
+
+ If unsure, say N.
+
++config IPV6_MROUTE
++ bool "IPv6: multicast routing (EXPERIMENTAL)"
++ depends on IPV6 && EXPERIMENTAL
++ ---help---
++ Experimental support for IPv6 multicast forwarding.
++ If unsure, say N.
++
++config IPV6_PIMSM_V2
++ bool "IPv6: PIM-SM version 2 support (EXPERIMENTAL)"
++ depends on IPV6_MROUTE
++ ---help---
++ Support for IPv6 PIM multicast routing protocol PIM-SMv2.
++ If unsure, say N.
++
++endif # IPV6
+diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
+index 24f3aa0..686934a 100644
+--- a/net/ipv6/Makefile
++++ b/net/ipv6/Makefile
+@@ -11,11 +11,14 @@ ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \
+ exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o
+
+ ipv6-$(CONFIG_SYSCTL) = sysctl_net_ipv6.o
++ipv6-$(CONFIG_IPV6_MROUTE) += ip6mr.o
++
+ ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \
+ xfrm6_output.o
+ ipv6-$(CONFIG_NETFILTER) += netfilter.o
+ ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o
+ ipv6-$(CONFIG_PROC_FS) += proc.o
++ipv6-$(CONFIG_SYN_COOKIES) += syncookies.o
+
+ ipv6-objs += $(ipv6-y)
+
+diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
+index e08955b..e591e09 100644
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -222,6 +222,8 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
+ /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
+ const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
+ const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
++const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
++const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
+
+ /* Check if a valid qdisc is available */
+ static inline int addrconf_qdisc_ok(struct net_device *dev)
+@@ -321,7 +323,6 @@ EXPORT_SYMBOL(in6_dev_finish_destroy);
+ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
+ {
+ struct inet6_dev *ndev;
+- struct in6_addr maddr;
+
+ ASSERT_RTNL();
+
+@@ -335,7 +336,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
+
+ rwlock_init(&ndev->lock);
+ ndev->dev = dev;
+- memcpy(&ndev->cnf, dev->nd_net->ipv6.devconf_dflt, sizeof(ndev->cnf));
++ memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf));
+ ndev->cnf.mtu6 = dev->mtu;
+ ndev->cnf.sysctl = NULL;
+ ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl);
+@@ -349,7 +350,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
+ if (snmp6_alloc_dev(ndev) < 0) {
+ ADBG((KERN_WARNING
+ "%s(): cannot allocate memory for statistics; dev=%s.\n",
+- __FUNCTION__, dev->name));
++ __func__, dev->name));
+ neigh_parms_release(&nd_tbl, ndev->nd_parms);
+ ndev->dead = 1;
+ in6_dev_finish_destroy(ndev);
+@@ -359,7 +360,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
+ if (snmp6_register_dev(ndev) < 0) {
+ ADBG((KERN_WARNING
+ "%s(): cannot create /proc/net/dev_snmp6/%s\n",
+- __FUNCTION__, dev->name));
++ __func__, dev->name));
+ neigh_parms_release(&nd_tbl, ndev->nd_parms);
+ ndev->dead = 1;
+ in6_dev_finish_destroy(ndev);
+@@ -407,8 +408,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
+ rcu_assign_pointer(dev->ip6_ptr, ndev);
+
+ /* Join all-node multicast group */
+- ipv6_addr_all_nodes(&maddr);
+- ipv6_dev_mc_inc(dev, &maddr);
++ ipv6_dev_mc_inc(dev, &in6addr_linklocal_allnodes);
+
+ return ndev;
+ }
+@@ -434,18 +434,15 @@ static void dev_forward_change(struct inet6_dev *idev)
+ {
+ struct net_device *dev;
+ struct inet6_ifaddr *ifa;
+- struct in6_addr addr;
+
+ if (!idev)
+ return;
+ dev = idev->dev;
+ if (dev && (dev->flags & IFF_MULTICAST)) {
+- ipv6_addr_all_routers(&addr);
+-
+ if (idev->cnf.forwarding)
+- ipv6_dev_mc_inc(dev, &addr);
++ ipv6_dev_mc_inc(dev, &in6addr_linklocal_allrouters);
+ else
+- ipv6_dev_mc_dec(dev, &addr);
++ ipv6_dev_mc_dec(dev, &in6addr_linklocal_allrouters);
+ }
+ for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) {
+ if (ifa->flags&IFA_F_TENTATIVE)
+@@ -494,7 +491,7 @@ static void addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old)
+ dev_forward_change((struct inet6_dev *)table->extra1);
+
+ if (*p)
+- rt6_purge_dflt_routers();
++ rt6_purge_dflt_routers(net);
+ }
+ #endif
+
+@@ -542,6 +539,25 @@ ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp)
+ *ifap = ifp;
+ }
+
++/*
++ * Hash function taken from net_alias.c
++ */
++static u8 ipv6_addr_hash(const struct in6_addr *addr)
++{
++ __u32 word;
++
++ /*
++ * We perform the hash function over the last 64 bits of the address
++ * This will include the IEEE address token on links that support it.
++ */
++
++ word = (__force u32)(addr->s6_addr32[2] ^ addr->s6_addr32[3]);
++ word ^= (word >> 16);
++ word ^= (word >> 8);
++
++ return ((word ^ (word >> 4)) & 0x0f);
++}
++
+ /* On success it returns ifp with increased reference count */
+
+ static struct inet6_ifaddr *
+@@ -562,7 +578,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
+ write_lock(&addrconf_hash_lock);
+
+ /* Ignore adding duplicate addresses on an interface */
+- if (ipv6_chk_same_addr(&init_net, addr, idev->dev)) {
++ if (ipv6_chk_same_addr(dev_net(idev->dev), addr, idev->dev)) {
+ ADBG(("ipv6_add_addr: already assigned\n"));
+ err = -EEXIST;
+ goto out;
+@@ -752,9 +768,9 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
+ if ((ifp->flags & IFA_F_PERMANENT) && onlink < 1) {
+ struct in6_addr prefix;
+ struct rt6_info *rt;
+-
++ struct net *net = dev_net(ifp->idev->dev);
+ ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len);
+- rt = rt6_lookup(&prefix, NULL, ifp->idev->dev->ifindex, 1);
++ rt = rt6_lookup(net, &prefix, NULL, ifp->idev->dev->ifindex, 1);
+
+ if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
+ if (onlink == 0) {
+@@ -894,20 +910,40 @@ out:
+ /*
+ * Choose an appropriate source address (RFC3484)
+ */
++enum {
++ IPV6_SADDR_RULE_INIT = 0,
++ IPV6_SADDR_RULE_LOCAL,
++ IPV6_SADDR_RULE_SCOPE,
++ IPV6_SADDR_RULE_PREFERRED,
++#ifdef CONFIG_IPV6_MIP6
++ IPV6_SADDR_RULE_HOA,
++#endif
++ IPV6_SADDR_RULE_OIF,
++ IPV6_SADDR_RULE_LABEL,
++#ifdef CONFIG_IPV6_PRIVACY
++ IPV6_SADDR_RULE_PRIVACY,
++#endif
++ IPV6_SADDR_RULE_ORCHID,
++ IPV6_SADDR_RULE_PREFIX,
++ IPV6_SADDR_RULE_MAX
++};
++
+ struct ipv6_saddr_score {
+- int addr_type;
+- unsigned int attrs;
+- int matchlen;
+- int scope;
+- unsigned int rule;
++ int rule;
++ int addr_type;
++ struct inet6_ifaddr *ifa;
++ DECLARE_BITMAP(scorebits, IPV6_SADDR_RULE_MAX);
++ int scopedist;
++ int matchlen;
+ };
+
+-#define IPV6_SADDR_SCORE_LOCAL 0x0001
+-#define IPV6_SADDR_SCORE_PREFERRED 0x0004
+-#define IPV6_SADDR_SCORE_HOA 0x0008
+-#define IPV6_SADDR_SCORE_OIF 0x0010
+-#define IPV6_SADDR_SCORE_LABEL 0x0020
+-#define IPV6_SADDR_SCORE_PRIVACY 0x0040
++struct ipv6_saddr_dst {
++ const struct in6_addr *addr;
++ int ifindex;
++ int scope;
++ int label;
++ unsigned int prefs;
++};
+
+ static inline int ipv6_saddr_preferred(int type)
+ {
+@@ -917,27 +953,152 @@ static inline int ipv6_saddr_preferred(int type)
+ return 0;
+ }
+
+-int ipv6_dev_get_saddr(struct net_device *daddr_dev,
+- struct in6_addr *daddr, struct in6_addr *saddr)
++static int ipv6_get_saddr_eval(struct ipv6_saddr_score *score,
++ struct ipv6_saddr_dst *dst,
++ int i)
+ {
+- struct ipv6_saddr_score hiscore;
+- struct inet6_ifaddr *ifa_result = NULL;
+- int daddr_type = __ipv6_addr_type(daddr);
+- int daddr_scope = __ipv6_addr_src_scope(daddr_type);
+- int daddr_ifindex = daddr_dev ? daddr_dev->ifindex : 0;
+- u32 daddr_label = ipv6_addr_label(daddr, daddr_type, daddr_ifindex);
++ int ret;
++
++ if (i <= score->rule) {
++ switch (i) {
++ case IPV6_SADDR_RULE_SCOPE:
++ ret = score->scopedist;
++ break;
++ case IPV6_SADDR_RULE_PREFIX:
++ ret = score->matchlen;
++ break;
++ default:
++ ret = !!test_bit(i, score->scorebits);
++ }
++ goto out;
++ }
++
++ switch (i) {
++ case IPV6_SADDR_RULE_INIT:
++ /* Rule 0: remember if hiscore is not ready yet */
++ ret = !!score->ifa;
++ break;
++ case IPV6_SADDR_RULE_LOCAL:
++ /* Rule 1: Prefer same address */
++ ret = ipv6_addr_equal(&score->ifa->addr, dst->addr);
++ break;
++ case IPV6_SADDR_RULE_SCOPE:
++ /* Rule 2: Prefer appropriate scope
++ *
++ * ret
++ * ^
++ * -1 | d 15
++ * ---+--+-+---> scope
++ * |
++ * | d is scope of the destination.
++ * B-d | \
++ * | \ <- smaller scope is better if
++ * B-15 | \ if scope is enough for destinaion.
++ * | ret = B - scope (-1 <= scope >= d <= 15).
++ * d-C-1 | /
++ * |/ <- greater is better
++ * -C / if scope is not enough for destination.
++ * /| ret = scope - C (-1 <= d < scope <= 15).
++ *
++ * d - C - 1 < B -15 (for all -1 <= d <= 15).
++ * C > d + 14 - B >= 15 + 14 - B = 29 - B.
++ * Assume B = 0 and we get C > 29.
++ */
++ ret = __ipv6_addr_src_scope(score->addr_type);
++ if (ret >= dst->scope)
++ ret = -ret;
++ else
++ ret -= 128; /* 30 is enough */
++ score->scopedist = ret;
++ break;
++ case IPV6_SADDR_RULE_PREFERRED:
++ /* Rule 3: Avoid deprecated and optimistic addresses */
++ ret = ipv6_saddr_preferred(score->addr_type) ||
++ !(score->ifa->flags & (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC));
++ break;
++#ifdef CONFIG_IPV6_MIP6
++ case IPV6_SADDR_RULE_HOA:
++ {
++ /* Rule 4: Prefer home address */
++ int prefhome = !(dst->prefs & IPV6_PREFER_SRC_COA);
++ ret = !(score->ifa->flags & IFA_F_HOMEADDRESS) ^ prefhome;
++ break;
++ }
++#endif
++ case IPV6_SADDR_RULE_OIF:
++ /* Rule 5: Prefer outgoing interface */
++ ret = (!dst->ifindex ||
++ dst->ifindex == score->ifa->idev->dev->ifindex);
++ break;
++ case IPV6_SADDR_RULE_LABEL:
++ /* Rule 6: Prefer matching label */
++ ret = ipv6_addr_label(&score->ifa->addr, score->addr_type,
++ score->ifa->idev->dev->ifindex) == dst->label;
++ break;
++#ifdef CONFIG_IPV6_PRIVACY
++ case IPV6_SADDR_RULE_PRIVACY:
++ {
++ /* Rule 7: Prefer public address
++ * Note: prefer temprary address if use_tempaddr >= 2
++ */
++ int preftmp = dst->prefs & (IPV6_PREFER_SRC_PUBLIC|IPV6_PREFER_SRC_TMP) ?
++ !!(dst->prefs & IPV6_PREFER_SRC_TMP) :
++ score->ifa->idev->cnf.use_tempaddr >= 2;
++ ret = (!(score->ifa->flags & IFA_F_TEMPORARY)) ^ preftmp;
++ break;
++ }
++#endif
++ case IPV6_SADDR_RULE_ORCHID:
++ /* Rule 8-: Prefer ORCHID vs ORCHID or
++ * non-ORCHID vs non-ORCHID
++ */
++ ret = !(ipv6_addr_orchid(&score->ifa->addr) ^
++ ipv6_addr_orchid(dst->addr));
++ break;
++ case IPV6_SADDR_RULE_PREFIX:
++ /* Rule 8: Use longest matching prefix */
++ score->matchlen = ret = ipv6_addr_diff(&score->ifa->addr,
++ dst->addr);
++ break;
++ default:
++ ret = 0;
++ }
++
++ if (ret)
++ __set_bit(i, score->scorebits);
++ score->rule = i;
++out:
++ return ret;
++}
++
++int ipv6_dev_get_saddr(struct net_device *dst_dev,
++ const struct in6_addr *daddr, unsigned int prefs,
++ struct in6_addr *saddr)
++{
++ struct ipv6_saddr_score scores[2],
++ *score = &scores[0], *hiscore = &scores[1];
++ struct net *net = dev_net(dst_dev);
++ struct ipv6_saddr_dst dst;
+ struct net_device *dev;
++ int dst_type;
+
+- memset(&hiscore, 0, sizeof(hiscore));
++ dst_type = __ipv6_addr_type(daddr);
++ dst.addr = daddr;
++ dst.ifindex = dst_dev ? dst_dev->ifindex : 0;
++ dst.scope = __ipv6_addr_src_scope(dst_type);
++ dst.label = ipv6_addr_label(daddr, dst_type, dst.ifindex);
++ dst.prefs = prefs;
++
++ hiscore->rule = -1;
++ hiscore->ifa = NULL;
+
+ read_lock(&dev_base_lock);
+ rcu_read_lock();
+
+- for_each_netdev(&init_net, dev) {
++ for_each_netdev(net, dev) {
+ struct inet6_dev *idev;
+- struct inet6_ifaddr *ifa;
+
+- /* Rule 0: Candidate Source Address (section 4)
++ /* Candidate Source Address (section 4)
+ * - multicast and link-local destination address,
+ * the set of candidate source address MUST only
+ * include addresses assigned to interfaces
+@@ -949,9 +1110,9 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
+ * belonging to the same site as the outgoing
+ * interface.)
+ */
+- if ((daddr_type & IPV6_ADDR_MULTICAST ||
+- daddr_scope <= IPV6_ADDR_SCOPE_LINKLOCAL) &&
+- daddr_dev && dev != daddr_dev)
++ if (((dst_type & IPV6_ADDR_MULTICAST) ||
++ dst.scope <= IPV6_ADDR_SCOPE_LINKLOCAL) &&
++ dst.ifindex && dev->ifindex != dst.ifindex)
+ continue;
+
+ idev = __in6_dev_get(dev);
+@@ -959,12 +1120,10 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
+ continue;
+
+ read_lock_bh(&idev->lock);
+- for (ifa = idev->addr_list; ifa; ifa = ifa->if_next) {
+- struct ipv6_saddr_score score;
++ for (score->ifa = idev->addr_list; score->ifa; score->ifa = score->ifa->if_next) {
++ int i;
+
+- score.addr_type = __ipv6_addr_type(&ifa->addr);
+-
+- /* Rule 0:
++ /*
+ * - Tentative Address (RFC2462 section 5.4)
+ * - A tentative address is not considered
+ * "assigned to an interface" in the traditional
+@@ -974,11 +1133,14 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
+ * addresses, and the unspecified address MUST
+ * NOT be included in a candidate set.
+ */
+- if ((ifa->flags & IFA_F_TENTATIVE) &&
+- (!(ifa->flags & IFA_F_OPTIMISTIC)))
++ if ((score->ifa->flags & IFA_F_TENTATIVE) &&
++ (!(score->ifa->flags & IFA_F_OPTIMISTIC)))
+ continue;
+- if (unlikely(score.addr_type == IPV6_ADDR_ANY ||
+- score.addr_type & IPV6_ADDR_MULTICAST)) {
++
++ score->addr_type = __ipv6_addr_type(&score->ifa->addr);
++
++ if (unlikely(score->addr_type == IPV6_ADDR_ANY ||
++ score->addr_type & IPV6_ADDR_MULTICAST)) {
+ LIMIT_NETDEBUG(KERN_DEBUG
+ "ADDRCONF: unspecified / multicast address "
+ "assigned as unicast address on %s",
+@@ -986,207 +1148,63 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
+ continue;
+ }
+
+- score.attrs = 0;
+- score.matchlen = 0;
+- score.scope = 0;
+- score.rule = 0;
+-
+- if (ifa_result == NULL) {
+- /* record it if the first available entry */
+- goto record_it;
+- }
+-
+- /* Rule 1: Prefer same address */
+- if (hiscore.rule < 1) {
+- if (ipv6_addr_equal(&ifa_result->addr, daddr))
+- hiscore.attrs |= IPV6_SADDR_SCORE_LOCAL;
+- hiscore.rule++;
+- }
+- if (ipv6_addr_equal(&ifa->addr, daddr)) {
+- score.attrs |= IPV6_SADDR_SCORE_LOCAL;
+- if (!(hiscore.attrs & IPV6_SADDR_SCORE_LOCAL)) {
+- score.rule = 1;
+- goto record_it;
+- }
+- } else {
+- if (hiscore.attrs & IPV6_SADDR_SCORE_LOCAL)
+- continue;
+- }
+-
+- /* Rule 2: Prefer appropriate scope */
+- if (hiscore.rule < 2) {
+- hiscore.scope = __ipv6_addr_src_scope(hiscore.addr_type);
+- hiscore.rule++;
+- }
+- score.scope = __ipv6_addr_src_scope(score.addr_type);
+- if (hiscore.scope < score.scope) {
+- if (hiscore.scope < daddr_scope) {
+- score.rule = 2;
+- goto record_it;
+- } else
+- continue;
+- } else if (score.scope < hiscore.scope) {
+- if (score.scope < daddr_scope)
+- break; /* addresses sorted by scope */
+- else {
+- score.rule = 2;
+- goto record_it;
+- }
+- }
++ score->rule = -1;
++ bitmap_zero(score->scorebits, IPV6_SADDR_RULE_MAX);
++
++ for (i = 0; i < IPV6_SADDR_RULE_MAX; i++) {
++ int minihiscore, miniscore;
++
++ minihiscore = ipv6_get_saddr_eval(hiscore, &dst, i);
++ miniscore = ipv6_get_saddr_eval(score, &dst, i);
++
++ if (minihiscore > miniscore) {
++ if (i == IPV6_SADDR_RULE_SCOPE &&
++ score->scopedist > 0) {
++ /*
++ * special case:
++ * each remaining entry
++ * has too small (not enough)
++ * scope, because ifa entries
++ * are sorted by their scope
++ * values.
++ */
++ goto try_nextdev;
++ }
++ break;
++ } else if (minihiscore < miniscore) {
++ struct ipv6_saddr_score *tmp;
+
+- /* Rule 3: Avoid deprecated and optimistic addresses */
+- if (hiscore.rule < 3) {
+- if (ipv6_saddr_preferred(hiscore.addr_type) ||
+- (((ifa_result->flags &
+- (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0)))
+- hiscore.attrs |= IPV6_SADDR_SCORE_PREFERRED;
+- hiscore.rule++;
+- }
+- if (ipv6_saddr_preferred(score.addr_type) ||
+- (((ifa->flags &
+- (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0))) {
+- score.attrs |= IPV6_SADDR_SCORE_PREFERRED;
+- if (!(hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED)) {
+- score.rule = 3;
+- goto record_it;
+- }
+- } else {
+- if (hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED)
+- continue;
+- }
++ if (hiscore->ifa)
++ in6_ifa_put(hiscore->ifa);
+
+- /* Rule 4: Prefer home address */
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+- if (hiscore.rule < 4) {
+- if (ifa_result->flags & IFA_F_HOMEADDRESS)
+- hiscore.attrs |= IPV6_SADDR_SCORE_HOA;
+- hiscore.rule++;
+- }
+- if (ifa->flags & IFA_F_HOMEADDRESS) {
+- score.attrs |= IPV6_SADDR_SCORE_HOA;
+- if (!(ifa_result->flags & IFA_F_HOMEADDRESS)) {
+- score.rule = 4;
+- goto record_it;
+- }
+- } else {
+- if (hiscore.attrs & IPV6_SADDR_SCORE_HOA)
+- continue;
+- }
+-#else
+- if (hiscore.rule < 4)
+- hiscore.rule++;
+-#endif
++ in6_ifa_hold(score->ifa);
+
+- /* Rule 5: Prefer outgoing interface */
+- if (hiscore.rule < 5) {
+- if (daddr_dev == NULL ||
+- daddr_dev == ifa_result->idev->dev)
+- hiscore.attrs |= IPV6_SADDR_SCORE_OIF;
+- hiscore.rule++;
+- }
+- if (daddr_dev == NULL ||
+- daddr_dev == ifa->idev->dev) {
+- score.attrs |= IPV6_SADDR_SCORE_OIF;
+- if (!(hiscore.attrs & IPV6_SADDR_SCORE_OIF)) {
+- score.rule = 5;
+- goto record_it;
+- }
+- } else {
+- if (hiscore.attrs & IPV6_SADDR_SCORE_OIF)
+- continue;
+- }
++ tmp = hiscore;
++ hiscore = score;
++ score = tmp;
+
+- /* Rule 6: Prefer matching label */
+- if (hiscore.rule < 6) {
+- if (ipv6_addr_label(&ifa_result->addr,
+- hiscore.addr_type,
+- ifa_result->idev->dev->ifindex) == daddr_label)
+- hiscore.attrs |= IPV6_SADDR_SCORE_LABEL;
+- hiscore.rule++;
+- }
+- if (ipv6_addr_label(&ifa->addr,
+- score.addr_type,
+- ifa->idev->dev->ifindex) == daddr_label) {
+- score.attrs |= IPV6_SADDR_SCORE_LABEL;
+- if (!(hiscore.attrs & IPV6_SADDR_SCORE_LABEL)) {
+- score.rule = 6;
+- goto record_it;
+- }
+- } else {
+- if (hiscore.attrs & IPV6_SADDR_SCORE_LABEL)
+- continue;
+- }
++ /* restore our iterator */
++ score->ifa = hiscore->ifa;
+
+-#ifdef CONFIG_IPV6_PRIVACY
+- /* Rule 7: Prefer public address
+- * Note: prefer temprary address if use_tempaddr >= 2
+- */
+- if (hiscore.rule < 7) {
+- if ((!(ifa_result->flags & IFA_F_TEMPORARY)) ^
+- (ifa_result->idev->cnf.use_tempaddr >= 2))
+- hiscore.attrs |= IPV6_SADDR_SCORE_PRIVACY;
+- hiscore.rule++;
+- }
+- if ((!(ifa->flags & IFA_F_TEMPORARY)) ^
+- (ifa->idev->cnf.use_tempaddr >= 2)) {
+- score.attrs |= IPV6_SADDR_SCORE_PRIVACY;
+- if (!(hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY)) {
+- score.rule = 7;
+- goto record_it;
++ break;
+ }
+- } else {
+- if (hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY)
+- continue;
+- }
+-#else
+- if (hiscore.rule < 7)
+- hiscore.rule++;
+-#endif
+- /* Rule 8: Use longest matching prefix */
+- if (hiscore.rule < 8) {
+- hiscore.matchlen = ipv6_addr_diff(&ifa_result->addr, daddr);
+- hiscore.rule++;
+ }
+- score.matchlen = ipv6_addr_diff(&ifa->addr, daddr);
+- if (score.matchlen > hiscore.matchlen) {
+- score.rule = 8;
+- goto record_it;
+- }
+-#if 0
+- else if (score.matchlen < hiscore.matchlen)
+- continue;
+-#endif
+-
+- /* Final Rule: choose first available one */
+- continue;
+-record_it:
+- if (ifa_result)
+- in6_ifa_put(ifa_result);
+- in6_ifa_hold(ifa);
+- ifa_result = ifa;
+- hiscore = score;
+ }
++try_nextdev:
+ read_unlock_bh(&idev->lock);
+ }
+ rcu_read_unlock();
+ read_unlock(&dev_base_lock);
+
+- if (!ifa_result)
++ if (!hiscore->ifa)
+ return -EADDRNOTAVAIL;
+
+- ipv6_addr_copy(saddr, &ifa_result->addr);
+- in6_ifa_put(ifa_result);
++ ipv6_addr_copy(saddr, &hiscore->ifa->addr);
++ in6_ifa_put(hiscore->ifa);
+ return 0;
+ }
+
+-
+-int ipv6_get_saddr(struct dst_entry *dst,
+- struct in6_addr *daddr, struct in6_addr *saddr)
+-{
+- return ipv6_dev_get_saddr(dst ? ip6_dst_idev(dst)->dev : NULL, daddr, saddr);
+-}
+-
+-EXPORT_SYMBOL(ipv6_get_saddr);
++EXPORT_SYMBOL(ipv6_dev_get_saddr);
+
+ int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
+ unsigned char banned_flags)
+@@ -1232,7 +1250,7 @@ int ipv6_chk_addr(struct net *net, struct in6_addr *addr,
+
+ read_lock_bh(&addrconf_hash_lock);
+ for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) {
+- if (ifp->idev->dev->nd_net != net)
++ if (!net_eq(dev_net(ifp->idev->dev), net))
+ continue;
+ if (ipv6_addr_equal(&ifp->addr, addr) &&
+ !(ifp->flags&IFA_F_TENTATIVE)) {
+@@ -1254,7 +1272,7 @@ int ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr,
+ u8 hash = ipv6_addr_hash(addr);
+
+ for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) {
+- if (ifp->idev->dev->nd_net != net)
++ if (!net_eq(dev_net(ifp->idev->dev), net))
+ continue;
+ if (ipv6_addr_equal(&ifp->addr, addr)) {
+ if (dev == NULL || ifp->idev->dev == dev)
+@@ -1264,7 +1282,32 @@ int ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr,
+ return ifp != NULL;
+ }
+
+-struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, struct in6_addr *addr,
++int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev)
++{
++ struct inet6_dev *idev;
++ struct inet6_ifaddr *ifa;
++ int onlink;
++
++ onlink = 0;
++ rcu_read_lock();
++ idev = __in6_dev_get(dev);
++ if (idev) {
++ read_lock_bh(&idev->lock);
++ for (ifa = idev->addr_list; ifa; ifa = ifa->if_next) {
++ onlink = ipv6_prefix_equal(addr, &ifa->addr,
++ ifa->prefix_len);
++ if (onlink)
++ break;
++ }
++ read_unlock_bh(&idev->lock);
++ }
++ rcu_read_unlock();
++ return onlink;
++}
++
++EXPORT_SYMBOL(ipv6_chk_prefix);
++
++struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *addr,
+ struct net_device *dev, int strict)
+ {
+ struct inet6_ifaddr * ifp;
+@@ -1272,7 +1315,7 @@ struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, struct in6_addr *addr,
+
+ read_lock_bh(&addrconf_hash_lock);
+ for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) {
+- if (ifp->idev->dev->nd_net != net)
++ if (!net_eq(dev_net(ifp->idev->dev), net))
+ continue;
+ if (ipv6_addr_equal(&ifp->addr, addr)) {
+ if (dev == NULL || ifp->idev->dev == dev ||
+@@ -1449,6 +1492,29 @@ static int addrconf_ifid_infiniband(u8 *eui, struct net_device *dev)
+ return 0;
+ }
+
++int __ipv6_isatap_ifid(u8 *eui, __be32 addr)
++{
++ eui[0] = (ipv4_is_zeronet(addr) || ipv4_is_private_10(addr) ||
++ ipv4_is_loopback(addr) || ipv4_is_linklocal_169(addr) ||
++ ipv4_is_private_172(addr) || ipv4_is_test_192(addr) ||
++ ipv4_is_anycast_6to4(addr) || ipv4_is_private_192(addr) ||
++ ipv4_is_test_198(addr) || ipv4_is_multicast(addr) ||
++ ipv4_is_lbcast(addr)) ? 0x00 : 0x02;
++ eui[1] = 0;
++ eui[2] = 0x5E;
++ eui[3] = 0xFE;
++ memcpy(eui + 4, &addr, 4);
++ return 0;
++}
++EXPORT_SYMBOL(__ipv6_isatap_ifid);
++
++static int addrconf_ifid_sit(u8 *eui, struct net_device *dev)
++{
++ if (dev->priv_flags & IFF_ISATAP)
++ return __ipv6_isatap_ifid(eui, *(__be32 *)dev->dev_addr);
++ return -1;
++}
++
+ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
+ {
+ switch (dev->type) {
+@@ -1461,8 +1527,7 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
+ case ARPHRD_INFINIBAND:
+ return addrconf_ifid_infiniband(eui, dev);
+ case ARPHRD_SIT:
+- if (dev->priv_flags & IFF_ISATAP)
+- return ipv6_isatap_eui64(eui, *(__be32 *)dev->dev_addr);
++ return addrconf_ifid_sit(eui, dev);
+ }
+ return -1;
+ }
+@@ -1574,7 +1639,7 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,
+ .fc_expires = expires,
+ .fc_dst_len = plen,
+ .fc_flags = RTF_UP | flags,
+- .fc_nlinfo.nl_net = &init_net,
++ .fc_nlinfo.nl_net = dev_net(dev),
+ };
+
+ ipv6_addr_copy(&cfg.fc_dst, pfx);
+@@ -1601,7 +1666,7 @@ static void addrconf_add_mroute(struct net_device *dev)
+ .fc_ifindex = dev->ifindex,
+ .fc_dst_len = 8,
+ .fc_flags = RTF_UP,
+- .fc_nlinfo.nl_net = &init_net,
++ .fc_nlinfo.nl_net = dev_net(dev),
+ };
+
+ ipv6_addr_set(&cfg.fc_dst, htonl(0xFF000000), 0, 0, 0);
+@@ -1618,7 +1683,7 @@ static void sit_route_add(struct net_device *dev)
+ .fc_ifindex = dev->ifindex,
+ .fc_dst_len = 96,
+ .fc_flags = RTF_UP | RTF_NONEXTHOP,
+- .fc_nlinfo.nl_net = &init_net,
++ .fc_nlinfo.nl_net = dev_net(dev),
+ };
+
+ /* prefix length - 96 bits "::d.d.d.d" */
+@@ -1719,7 +1784,8 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
+
+ if (pinfo->onlink) {
+ struct rt6_info *rt;
+- rt = rt6_lookup(&pinfo->prefix, NULL, dev->ifindex, 1);
++ rt = rt6_lookup(dev_net(dev), &pinfo->prefix, NULL,
++ dev->ifindex, 1);
+
+ if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
+ if (rt->rt6i_flags&RTF_EXPIRES) {
+@@ -1762,7 +1828,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
+
+ ok:
+
+- ifp = ipv6_get_ifaddr(&init_net, &addr, dev, 1);
++ ifp = ipv6_get_ifaddr(dev_net(dev), &addr, dev, 1);
+
+ if (ifp == NULL && valid_lft) {
+ int max_addresses = in6_dev->cnf.max_addresses;
+@@ -1888,7 +1954,7 @@ ok:
+ * Special case for SIT interfaces where we create a new "virtual"
+ * device.
+ */
+-int addrconf_set_dstaddr(void __user *arg)
++int addrconf_set_dstaddr(struct net *net, void __user *arg)
+ {
+ struct in6_ifreq ireq;
+ struct net_device *dev;
+@@ -1900,7 +1966,7 @@ int addrconf_set_dstaddr(void __user *arg)
+ if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
+ goto err_exit;
+
+- dev = __dev_get_by_index(&init_net, ireq.ifr6_ifindex);
++ dev = __dev_get_by_index(net, ireq.ifr6_ifindex);
+
+ err = -ENODEV;
+ if (dev == NULL)
+@@ -1931,7 +1997,8 @@ int addrconf_set_dstaddr(void __user *arg)
+
+ if (err == 0) {
+ err = -ENOBUFS;
+- if ((dev = __dev_get_by_name(&init_net, p.name)) == NULL)
++ dev = __dev_get_by_name(net, p.name);
++ if (!dev)
+ goto err_exit;
+ err = dev_open(dev);
+ }
+@@ -1946,8 +2013,9 @@ err_exit:
+ /*
+ * Manual configuration of address on an interface
+ */
+-static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen,
+- __u8 ifa_flags, __u32 prefered_lft, __u32 valid_lft)
++static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx,
++ int plen, __u8 ifa_flags, __u32 prefered_lft,
++ __u32 valid_lft)
+ {
+ struct inet6_ifaddr *ifp;
+ struct inet6_dev *idev;
+@@ -1961,7 +2029,8 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen,
+ if (!valid_lft || prefered_lft > valid_lft)
+ return -EINVAL;
+
+- if ((dev = __dev_get_by_index(&init_net, ifindex)) == NULL)
++ dev = __dev_get_by_index(net, ifindex);
++ if (!dev)
+ return -ENODEV;
+
+ if ((idev = addrconf_add_dev(dev)) == NULL)
+@@ -2006,13 +2075,15 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen,
+ return PTR_ERR(ifp);
+ }
+
+-static int inet6_addr_del(int ifindex, struct in6_addr *pfx, int plen)
++static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx,
++ int plen)
+ {
+ struct inet6_ifaddr *ifp;
+ struct inet6_dev *idev;
+ struct net_device *dev;
+
+- if ((dev = __dev_get_by_index(&init_net, ifindex)) == NULL)
++ dev = __dev_get_by_index(net, ifindex);
++ if (!dev)
+ return -ENODEV;
+
+ if ((idev = __in6_dev_get(dev)) == NULL)
+@@ -2040,7 +2111,7 @@ static int inet6_addr_del(int ifindex, struct in6_addr *pfx, int plen)
+ }
+
+
+-int addrconf_add_ifaddr(void __user *arg)
++int addrconf_add_ifaddr(struct net *net, void __user *arg)
+ {
+ struct in6_ifreq ireq;
+ int err;
+@@ -2052,13 +2123,14 @@ int addrconf_add_ifaddr(void __user *arg)
+ return -EFAULT;
+
+ rtnl_lock();
+- err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen,
+- IFA_F_PERMANENT, INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
++ err = inet6_addr_add(net, ireq.ifr6_ifindex, &ireq.ifr6_addr,
++ ireq.ifr6_prefixlen, IFA_F_PERMANENT,
++ INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
+ rtnl_unlock();
+ return err;
+ }
+
+-int addrconf_del_ifaddr(void __user *arg)
++int addrconf_del_ifaddr(struct net *net, void __user *arg)
+ {
+ struct in6_ifreq ireq;
+ int err;
+@@ -2070,7 +2142,8 @@ int addrconf_del_ifaddr(void __user *arg)
+ return -EFAULT;
+
+ rtnl_lock();
+- err = inet6_addr_del(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen);
++ err = inet6_addr_del(net, ireq.ifr6_ifindex, &ireq.ifr6_addr,
++ ireq.ifr6_prefixlen);
+ rtnl_unlock();
+ return err;
+ }
+@@ -2081,6 +2154,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev)
+ struct inet6_ifaddr * ifp;
+ struct in6_addr addr;
+ struct net_device *dev;
++ struct net *net = dev_net(idev->dev);
+ int scope;
+
+ ASSERT_RTNL();
+@@ -2107,7 +2181,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev)
+ return;
+ }
+
+- for_each_netdev(&init_net, dev) {
++ for_each_netdev(net, dev) {
+ struct in_device * in_dev = __in_dev_get_rtnl(dev);
+ if (in_dev && (dev->flags & IFF_UP)) {
+ struct in_ifaddr * ifa;
+@@ -2270,15 +2344,16 @@ ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev)
+ static void ip6_tnl_add_linklocal(struct inet6_dev *idev)
+ {
+ struct net_device *link_dev;
++ struct net *net = dev_net(idev->dev);
+
+ /* first try to inherit the link-local address from the link device */
+ if (idev->dev->iflink &&
+- (link_dev = __dev_get_by_index(&init_net, idev->dev->iflink))) {
++ (link_dev = __dev_get_by_index(net, idev->dev->iflink))) {
+ if (!ipv6_inherit_linklocal(idev, link_dev))
+ return;
+ }
+ /* then try to inherit it from any device */
+- for_each_netdev(&init_net, link_dev) {
++ for_each_netdev(net, link_dev) {
+ if (!ipv6_inherit_linklocal(idev, link_dev))
+ return;
+ }
+@@ -2311,9 +2386,6 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
+ int run_pending = 0;
+ int err;
+
+- if (dev->nd_net != &init_net)
+- return NOTIFY_DONE;
+-
+ switch(event) {
+ case NETDEV_REGISTER:
+ if (!idev && dev->mtu >= IPV6_MIN_MTU) {
+@@ -2453,6 +2525,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
+ {
+ struct inet6_dev *idev;
+ struct inet6_ifaddr *ifa, **bifa;
++ struct net *net = dev_net(dev);
+ int i;
+
+ ASSERT_RTNL();
+@@ -2460,7 +2533,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
+ if ((dev->flags & IFF_LOOPBACK) && how == 1)
+ how = 0;
+
+- rt6_ifdown(dev);
++ rt6_ifdown(net, dev);
+ neigh_ifdown(&nd_tbl, dev);
+
+ idev = __in6_dev_get(dev);
+@@ -2579,8 +2652,6 @@ static void addrconf_rs_timer(unsigned long data)
+
+ spin_lock(&ifp->lock);
+ if (ifp->probes++ < ifp->idev->cnf.rtr_solicits) {
+- struct in6_addr all_routers;
+-
+ /* The wait after the last probe can be shorter */
+ addrconf_mod_timer(ifp, AC_RS,
+ (ifp->probes == ifp->idev->cnf.rtr_solicits) ?
+@@ -2588,9 +2659,7 @@ static void addrconf_rs_timer(unsigned long data)
+ ifp->idev->cnf.rtr_solicit_interval);
+ spin_unlock(&ifp->lock);
+
+- ipv6_addr_all_routers(&all_routers);
+-
+- ndisc_send_rs(ifp->idev->dev, &ifp->addr, &all_routers);
++ ndisc_send_rs(ifp->idev->dev, &ifp->addr, &in6addr_linklocal_allrouters);
+ } else {
+ spin_unlock(&ifp->lock);
+ /*
+@@ -2677,7 +2746,6 @@ static void addrconf_dad_timer(unsigned long data)
+ {
+ struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data;
+ struct inet6_dev *idev = ifp->idev;
+- struct in6_addr unspec;
+ struct in6_addr mcaddr;
+
+ read_lock_bh(&idev->lock);
+@@ -2706,9 +2774,8 @@ static void addrconf_dad_timer(unsigned long data)
+ read_unlock_bh(&idev->lock);
+
+ /* send a neighbour solicitation for our addr */
+- memset(&unspec, 0, sizeof(unspec));
+ addrconf_addr_solict_mult(&ifp->addr, &mcaddr);
+- ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &unspec);
++ ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &in6addr_any);
+ out:
+ in6_ifa_put(ifp);
+ }
+@@ -2731,16 +2798,12 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
+ ifp->idev->cnf.rtr_solicits > 0 &&
+ (dev->flags&IFF_LOOPBACK) == 0 &&
+ (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) {
+- struct in6_addr all_routers;
+-
+- ipv6_addr_all_routers(&all_routers);
+-
+ /*
+ * If a host as already performed a random delay
+ * [...] as part of DAD [...] there is no need
+ * to delay again before sending the first RS
+ */
+- ndisc_send_rs(ifp->idev->dev, &ifp->addr, &all_routers);
++ ndisc_send_rs(ifp->idev->dev, &ifp->addr, &in6addr_linklocal_allrouters);
+
+ spin_lock_bh(&ifp->lock);
+ ifp->probes = 1;
+@@ -2776,12 +2839,12 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq)
+ {
+ struct inet6_ifaddr *ifa = NULL;
+ struct if6_iter_state *state = seq->private;
+- struct net *net = state->p.net;
++ struct net *net = seq_file_net(seq);
+
+ for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) {
+ ifa = inet6_addr_lst[state->bucket];
+
+- while (ifa && ifa->idev->dev->nd_net != net)
++ while (ifa && !net_eq(dev_net(ifa->idev->dev), net))
+ ifa = ifa->lst_next;
+ if (ifa)
+ break;
+@@ -2792,12 +2855,12 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq)
+ static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct inet6_ifaddr *ifa)
+ {
+ struct if6_iter_state *state = seq->private;
+- struct net *net = state->p.net;
++ struct net *net = seq_file_net(seq);
+
+ ifa = ifa->lst_next;
+ try_again:
+ if (ifa) {
+- if (ifa->idev->dev->nd_net != net) {
++ if (!net_eq(dev_net(ifa->idev->dev), net)) {
+ ifa = ifa->lst_next;
+ goto try_again;
+ }
+@@ -2915,9 +2978,9 @@ int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr)
+ u8 hash = ipv6_addr_hash(addr);
+ read_lock_bh(&addrconf_hash_lock);
+ for (ifp = inet6_addr_lst[hash]; ifp; ifp = ifp->lst_next) {
+- if (ifp->idev->dev->nd_net != net)
++ if (!net_eq(dev_net(ifp->idev->dev), net))
+ continue;
+- if (ipv6_addr_cmp(&ifp->addr, addr) == 0 &&
++ if (ipv6_addr_equal(&ifp->addr, addr) &&
+ (ifp->flags & IFA_F_HOMEADDRESS)) {
+ ret = 1;
+ break;
+@@ -3064,15 +3127,12 @@ static const struct nla_policy ifa_ipv6_policy[IFA_MAX+1] = {
+ static int
+ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct ifaddrmsg *ifm;
+ struct nlattr *tb[IFA_MAX+1];
+ struct in6_addr *pfx;
+ int err;
+
+- if (net != &init_net)
+- return -EINVAL;
+-
+ err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
+ if (err < 0)
+ return err;
+@@ -3082,7 +3142,7 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ if (pfx == NULL)
+ return -EINVAL;
+
+- return inet6_addr_del(ifm->ifa_index, pfx, ifm->ifa_prefixlen);
++ return inet6_addr_del(net, ifm->ifa_index, pfx, ifm->ifa_prefixlen);
+ }
+
+ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
+@@ -3125,7 +3185,7 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
+ static int
+ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct ifaddrmsg *ifm;
+ struct nlattr *tb[IFA_MAX+1];
+ struct in6_addr *pfx;
+@@ -3135,9 +3195,6 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ u8 ifa_flags;
+ int err;
+
+- if (net != &init_net)
+- return -EINVAL;
+-
+ err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
+ if (err < 0)
+ return err;
+@@ -3158,7 +3215,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ valid_lft = INFINITY_LIFE_TIME;
+ }
+
+- dev = __dev_get_by_index(&init_net, ifm->ifa_index);
++ dev = __dev_get_by_index(net, ifm->ifa_index);
+ if (dev == NULL)
+ return -ENODEV;
+
+@@ -3171,8 +3228,9 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+ * It would be best to check for !NLM_F_CREATE here but
+ * userspace alreay relies on not having to provide this.
+ */
+- return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen,
+- ifa_flags, preferred_lft, valid_lft);
++ return inet6_addr_add(net, ifm->ifa_index, pfx,
++ ifm->ifa_prefixlen, ifa_flags,
++ preferred_lft, valid_lft);
+ }
+
+ if (nlh->nlmsg_flags & NLM_F_EXCL ||
+@@ -3337,12 +3395,13 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
+ struct inet6_ifaddr *ifa;
+ struct ifmcaddr6 *ifmca;
+ struct ifacaddr6 *ifaca;
++ struct net *net = sock_net(skb->sk);
+
+ s_idx = cb->args[0];
+ s_ip_idx = ip_idx = cb->args[1];
+
+ idx = 0;
+- for_each_netdev(&init_net, dev) {
++ for_each_netdev(net, dev) {
+ if (idx < s_idx)
+ goto cont;
+ if (idx > s_idx)
+@@ -3409,42 +3468,30 @@ cont:
+
+ static int inet6_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+- struct net *net = skb->sk->sk_net;
+ enum addr_type_t type = UNICAST_ADDR;
+
+- if (net != &init_net)
+- return 0;
+-
+ return inet6_dump_addr(skb, cb, type);
+ }
+
+ static int inet6_dump_ifmcaddr(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+- struct net *net = skb->sk->sk_net;
+ enum addr_type_t type = MULTICAST_ADDR;
+
+- if (net != &init_net)
+- return 0;
+-
+ return inet6_dump_addr(skb, cb, type);
+ }
+
+
+ static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+- struct net *net = skb->sk->sk_net;
+ enum addr_type_t type = ANYCAST_ADDR;
+
+- if (net != &init_net)
+- return 0;
+-
+ return inet6_dump_addr(skb, cb, type);
+ }
+
+ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh,
+ void *arg)
+ {
+- struct net *net = in_skb->sk->sk_net;
++ struct net *net = sock_net(in_skb->sk);
+ struct ifaddrmsg *ifm;
+ struct nlattr *tb[IFA_MAX+1];
+ struct in6_addr *addr = NULL;
+@@ -3453,9 +3500,6 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh,
+ struct sk_buff *skb;
+ int err;
+
+- if (net != &init_net)
+- return -EINVAL;
+-
+ err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
+ if (err < 0)
+ goto errout;
+@@ -3468,7 +3512,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh,
+
+ ifm = nlmsg_data(nlh);
+ if (ifm->ifa_index)
+- dev = __dev_get_by_index(&init_net, ifm->ifa_index);
++ dev = __dev_get_by_index(net, ifm->ifa_index);
+
+ if ((ifa = ipv6_get_ifaddr(net, addr, dev, 1)) == NULL) {
+ err = -EADDRNOTAVAIL;
+@@ -3488,7 +3532,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh,
+ kfree_skb(skb);
+ goto errout_ifa;
+ }
+- err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid);
++ err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).pid);
+ errout_ifa:
+ in6_ifa_put(ifa);
+ errout:
+@@ -3498,6 +3542,7 @@ errout:
+ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
+ {
+ struct sk_buff *skb;
++ struct net *net = dev_net(ifa->idev->dev);
+ int err = -ENOBUFS;
+
+ skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_ATOMIC);
+@@ -3511,10 +3556,10 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
+ kfree_skb(skb);
+ goto errout;
+ }
+- err = rtnl_notify(skb, &init_net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
++ err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
+ errout:
+ if (err < 0)
+- rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_IFADDR, err);
++ rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err);
+ }
+
+ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
+@@ -3556,6 +3601,9 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
+ #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
+ array[DEVCONF_OPTIMISTIC_DAD] = cnf->optimistic_dad;
+ #endif
++#ifdef CONFIG_IPV6_MROUTE
++ array[DEVCONF_MC_FORWARDING] = cnf->mc_forwarding;
++#endif
+ }
+
+ static inline size_t inet6_if_nlmsg_size(void)
+@@ -3673,18 +3721,15 @@ nla_put_failure:
+
+ static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ int idx, err;
+ int s_idx = cb->args[0];
+ struct net_device *dev;
+ struct inet6_dev *idev;
+
+- if (net != &init_net)
+- return 0;
+-
+ read_lock(&dev_base_lock);
+ idx = 0;
+- for_each_netdev(&init_net, dev) {
++ for_each_netdev(net, dev) {
+ if (idx < s_idx)
+ goto cont;
+ if ((idev = in6_dev_get(dev)) == NULL)
+@@ -3706,6 +3751,7 @@ cont:
+ void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
+ {
+ struct sk_buff *skb;
++ struct net *net = dev_net(idev->dev);
+ int err = -ENOBUFS;
+
+ skb = nlmsg_new(inet6_if_nlmsg_size(), GFP_ATOMIC);
+@@ -3719,10 +3765,10 @@ void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
+ kfree_skb(skb);
+ goto errout;
+ }
+- err = rtnl_notify(skb, &init_net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
++ err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
+ errout:
+ if (err < 0)
+- rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_IFADDR, err);
++ rtnl_set_sk_err(net, RTNLGRP_IPV6_IFADDR, err);
+ }
+
+ static inline size_t inet6_prefix_nlmsg_size(void)
+@@ -3775,6 +3821,7 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev,
+ struct prefix_info *pinfo)
+ {
+ struct sk_buff *skb;
++ struct net *net = dev_net(idev->dev);
+ int err = -ENOBUFS;
+
+ skb = nlmsg_new(inet6_prefix_nlmsg_size(), GFP_ATOMIC);
+@@ -3788,10 +3835,10 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev,
+ kfree_skb(skb);
+ goto errout;
+ }
+- err = rtnl_notify(skb, &init_net, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
++ err = rtnl_notify(skb, net, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
+ errout:
+ if (err < 0)
+- rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_PREFIX, err);
++ rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err);
+ }
+
+ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
+@@ -3887,7 +3934,7 @@ static int addrconf_sysctl_forward_strategy(ctl_table *table,
+ static struct addrconf_sysctl_table
+ {
+ struct ctl_table_header *sysctl_header;
+- ctl_table addrconf_vars[__NET_IPV6_MAX];
++ ctl_table addrconf_vars[DEVCONF_MAX+1];
+ char *dev_name;
+ } addrconf_sysctl __read_mostly = {
+ .sysctl_header = NULL,
+@@ -4105,6 +4152,16 @@ static struct addrconf_sysctl_table
+
+ },
+ #endif
++#ifdef CONFIG_IPV6_MROUTE
++ {
++ .ctl_name = CTL_UNNUMBERED,
++ .procname = "mc_forwarding",
++ .data = &ipv6_devconf.mc_forwarding,
++ .maxlen = sizeof(int),
++ .mode = 0644,
++ .proc_handler = &proc_dointvec,
++ },
++#endif
+ {
+ .ctl_name = 0, /* sentinel */
+ }
+@@ -4186,7 +4243,7 @@ static void addrconf_sysctl_register(struct inet6_dev *idev)
+ NET_IPV6_NEIGH, "ipv6",
+ &ndisc_ifinfo_sysctl_change,
+ NULL);
+- __addrconf_sysctl_register(idev->dev->nd_net, idev->dev->name,
++ __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name,
+ idev->dev->ifindex, idev, &idev->cnf);
+ }
+
+@@ -4281,6 +4338,25 @@ int unregister_inet6addr_notifier(struct notifier_block *nb)
+
+ EXPORT_SYMBOL(unregister_inet6addr_notifier);
+
++static void addrconf_net_exit(struct net *net)
++{
++ struct net_device *dev;
++
++ rtnl_lock();
++ /* clean dev list */
++ for_each_netdev(net, dev) {
++ if (__in6_dev_get(dev) == NULL)
++ continue;
++ addrconf_ifdown(dev, 1);
++ }
++ addrconf_ifdown(net->loopback_dev, 2);
++ rtnl_unlock();
++}
++
++static struct pernet_operations addrconf_net_ops = {
++ .exit = addrconf_net_exit,
++};
++
+ /*
+ * Init / cleanup code
+ */
+@@ -4322,14 +4398,9 @@ int __init addrconf_init(void)
+ if (err)
+ goto errlo;
+
+- ip6_null_entry.u.dst.dev = init_net.loopback_dev;
+- ip6_null_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev);
+-#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+- ip6_prohibit_entry.u.dst.dev = init_net.loopback_dev;
+- ip6_prohibit_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev);
+- ip6_blk_hole_entry.u.dst.dev = init_net.loopback_dev;
+- ip6_blk_hole_entry.rt6i_idev = in6_dev_get(init_net.loopback_dev);
+-#endif
++ err = register_pernet_device(&addrconf_net_ops);
++ if (err)
++ return err;
+
+ register_netdevice_notifier(&ipv6_dev_notf);
+
+@@ -4359,31 +4430,19 @@ errlo:
+
+ void addrconf_cleanup(void)
+ {
+- struct net_device *dev;
+ struct inet6_ifaddr *ifa;
+ int i;
+
+ unregister_netdevice_notifier(&ipv6_dev_notf);
++ unregister_pernet_device(&addrconf_net_ops);
+
+ unregister_pernet_subsys(&addrconf_ops);
+
+ rtnl_lock();
+
+ /*
+- * clean dev list.
+- */
+-
+- for_each_netdev(&init_net, dev) {
+- if (__in6_dev_get(dev) == NULL)
+- continue;
+- addrconf_ifdown(dev, 1);
+- }
+- addrconf_ifdown(init_net.loopback_dev, 2);
+-
+- /*
+ * Check hash table.
+ */
+-
+ write_lock_bh(&addrconf_hash_lock);
+ for (i=0; i < IN6_ADDR_HSIZE; i++) {
+ for (ifa=inet6_addr_lst[i]; ifa; ) {
+@@ -4400,6 +4459,7 @@ void addrconf_cleanup(void)
+ write_unlock_bh(&addrconf_hash_lock);
+
+ del_timer(&addr_chk_timer);
+-
+ rtnl_unlock();
++
++ unregister_pernet_subsys(&addrconf_net_ops);
+ }
+diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c
+index a3c5a72..9bfa884 100644
+--- a/net/ipv6/addrlabel.c
++++ b/net/ipv6/addrlabel.c
+@@ -58,6 +58,7 @@ static struct ip6addrlbl_table
+ * ::ffff:0:0/96 V4MAPPED 4
+ * fc00::/7 N/A 5 ULA (RFC 4193)
+ * 2001::/32 N/A 6 Teredo (RFC 4380)
++ * 2001:10::/28 N/A 7 ORCHID (RFC 4843)
+ *
+ * Note: 0xffffffff is used if we do not have any policies.
+ */
+@@ -85,6 +86,10 @@ static const __initdata struct ip6addrlbl_init_table
+ .prefix = &(struct in6_addr){{{ 0x20, 0x01 }}},
+ .prefixlen = 32,
+ .label = 6,
++ },{ /* 2001:10::/28 */
++ .prefix = &(struct in6_addr){{{ 0x20, 0x01, 0x00, 0x10 }}},
++ .prefixlen = 28,
++ .label = 7,
+ },{ /* ::ffff:0:0 */
+ .prefix = &(struct in6_addr){{{ [10] = 0xff, [11] = 0xff }}},
+ .prefixlen = 96,
+@@ -161,7 +166,7 @@ u32 ipv6_addr_label(const struct in6_addr *addr, int type, int ifindex)
+ rcu_read_unlock();
+
+ ADDRLABEL(KERN_DEBUG "%s(addr=" NIP6_FMT ", type=%d, ifindex=%d) => %08x\n",
+- __FUNCTION__,
++ __func__,
+ NIP6(*addr), type, ifindex,
+ label);
+
+@@ -177,7 +182,7 @@ static struct ip6addrlbl_entry *ip6addrlbl_alloc(const struct in6_addr *prefix,
+ int addrtype;
+
+ ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d, label=%u)\n",
+- __FUNCTION__,
++ __func__,
+ NIP6(*prefix), prefixlen,
+ ifindex,
+ (unsigned int)label);
+@@ -221,7 +226,7 @@ static int __ip6addrlbl_add(struct ip6addrlbl_entry *newp, int replace)
+ int ret = 0;
+
+ ADDRLABEL(KERN_DEBUG "%s(newp=%p, replace=%d)\n",
+- __FUNCTION__,
++ __func__,
+ newp, replace);
+
+ if (hlist_empty(&ip6addrlbl_table.head)) {
+@@ -263,7 +268,7 @@ static int ip6addrlbl_add(const struct in6_addr *prefix, int prefixlen,
+ int ret = 0;
+
+ ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d, label=%u, replace=%d)\n",
+- __FUNCTION__,
++ __func__,
+ NIP6(*prefix), prefixlen,
+ ifindex,
+ (unsigned int)label,
+@@ -289,7 +294,7 @@ static int __ip6addrlbl_del(const struct in6_addr *prefix, int prefixlen,
+ int ret = -ESRCH;
+
+ ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d)\n",
+- __FUNCTION__,
++ __func__,
+ NIP6(*prefix), prefixlen,
+ ifindex);
+
+@@ -313,7 +318,7 @@ static int ip6addrlbl_del(const struct in6_addr *prefix, int prefixlen,
+ int ret;
+
+ ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d)\n",
+- __FUNCTION__,
++ __func__,
+ NIP6(*prefix), prefixlen,
+ ifindex);
+
+@@ -330,7 +335,7 @@ static __init int ip6addrlbl_init(void)
+ int err = 0;
+ int i;
+
+- ADDRLABEL(KERN_DEBUG "%s()\n", __FUNCTION__);
++ ADDRLABEL(KERN_DEBUG "%s()\n", __func__);
+
+ for (i = 0; i < ARRAY_SIZE(ip6addrlbl_init_table); i++) {
+ int ret = ip6addrlbl_add(ip6addrlbl_init_table[i].prefix,
+@@ -359,7 +364,7 @@ static const struct nla_policy ifal_policy[IFAL_MAX+1] = {
+ static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh,
+ void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct ifaddrlblmsg *ifal;
+ struct nlattr *tb[IFAL_MAX+1];
+ struct in6_addr *pfx;
+@@ -447,7 +452,7 @@ static int ip6addrlbl_fill(struct sk_buff *skb,
+
+ static int ip6addrlbl_dump(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct ip6addrlbl_entry *p;
+ struct hlist_node *pos;
+ int idx = 0, s_idx = cb->args[0];
+@@ -485,7 +490,7 @@ static inline int ip6addrlbl_msgsize(void)
+ static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh,
+ void *arg)
+ {
+- struct net *net = in_skb->sk->sk_net;
++ struct net *net = sock_net(in_skb->sk);
+ struct ifaddrlblmsg *ifal;
+ struct nlattr *tb[IFAL_MAX+1];
+ struct in6_addr *addr;
+diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
+index f0aa977..3c6aafb 100644
+--- a/net/ipv6/af_inet6.c
++++ b/net/ipv6/af_inet6.c
+@@ -61,6 +61,9 @@
+
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
++#ifdef CONFIG_IPV6_MROUTE
++#include <linux/mroute6.h>
++#endif
+
+ MODULE_AUTHOR("Cast of dozens");
+ MODULE_DESCRIPTION("IPv6 protocol stack for Linux");
+@@ -92,9 +95,6 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol)
+ int try_loading_module = 0;
+ int err;
+
+- if (net != &init_net)
+- return -EAFNOSUPPORT;
+-
+ if (sock->type != SOCK_RAW &&
+ sock->type != SOCK_DGRAM &&
+ !inet_ehash_secret)
+@@ -248,6 +248,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ struct sock *sk = sock->sk;
+ struct inet_sock *inet = inet_sk(sk);
+ struct ipv6_pinfo *np = inet6_sk(sk);
++ struct net *net = sock_net(sk);
+ __be32 v4addr = 0;
+ unsigned short snum;
+ int addr_type = 0;
+@@ -278,7 +279,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ /* Check if the address belongs to the host. */
+ if (addr_type == IPV6_ADDR_MAPPED) {
+ v4addr = addr->sin6_addr.s6_addr32[3];
+- if (inet_addr_type(&init_net, v4addr) != RTN_LOCAL) {
++ if (inet_addr_type(net, v4addr) != RTN_LOCAL) {
+ err = -EADDRNOTAVAIL;
+ goto out;
+ }
+@@ -300,7 +301,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ err = -EINVAL;
+ goto out;
+ }
+- dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if);
++ dev = dev_get_by_index(net, sk->sk_bound_dev_if);
+ if (!dev) {
+ err = -ENODEV;
+ goto out;
+@@ -312,7 +313,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ */
+ v4addr = LOOPBACK4_IPV6;
+ if (!(addr_type & IPV6_ADDR_MULTICAST)) {
+- if (!ipv6_chk_addr(&init_net, &addr->sin6_addr,
++ if (!ipv6_chk_addr(net, &addr->sin6_addr,
+ dev, 0)) {
+ if (dev)
+ dev_put(dev);
+@@ -440,6 +441,7 @@ EXPORT_SYMBOL(inet6_getname);
+ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+ {
+ struct sock *sk = sock->sk;
++ struct net *net = sock_net(sk);
+
+ switch(cmd)
+ {
+@@ -452,14 +454,14 @@ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+ case SIOCADDRT:
+ case SIOCDELRT:
+
+- return(ipv6_route_ioctl(cmd,(void __user *)arg));
++ return(ipv6_route_ioctl(net, cmd, (void __user *)arg));
+
+ case SIOCSIFADDR:
+- return addrconf_add_ifaddr((void __user *) arg);
++ return addrconf_add_ifaddr(net, (void __user *) arg);
+ case SIOCDIFADDR:
+- return addrconf_del_ifaddr((void __user *) arg);
++ return addrconf_del_ifaddr(net, (void __user *) arg);
+ case SIOCSIFDSTADDR:
+- return addrconf_set_dstaddr((void __user *) arg);
++ return addrconf_set_dstaddr(net, (void __user *) arg);
+ default:
+ if (!sk->sk_prot->ioctl)
+ return -ENOIOCTLCMD;
+@@ -678,6 +680,129 @@ int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb)
+
+ EXPORT_SYMBOL_GPL(ipv6_opt_accepted);
+
++static struct inet6_protocol *ipv6_gso_pull_exthdrs(struct sk_buff *skb,
++ int proto)
++{
++ struct inet6_protocol *ops = NULL;
++
++ for (;;) {
++ struct ipv6_opt_hdr *opth;
++ int len;
++
++ if (proto != NEXTHDR_HOP) {
++ ops = rcu_dereference(inet6_protos[proto]);
++
++ if (unlikely(!ops))
++ break;
++
++ if (!(ops->flags & INET6_PROTO_GSO_EXTHDR))
++ break;
++ }
++
++ if (unlikely(!pskb_may_pull(skb, 8)))
++ break;
++
++ opth = (void *)skb->data;
++ len = ipv6_optlen(opth);
++
++ if (unlikely(!pskb_may_pull(skb, len)))
++ break;
++
++ proto = opth->nexthdr;
++ __skb_pull(skb, len);
++ }
++
++ return ops;
++}
++
++static int ipv6_gso_send_check(struct sk_buff *skb)
++{
++ struct ipv6hdr *ipv6h;
++ struct inet6_protocol *ops;
++ int err = -EINVAL;
++
++ if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
++ goto out;
++
++ ipv6h = ipv6_hdr(skb);
++ __skb_pull(skb, sizeof(*ipv6h));
++ err = -EPROTONOSUPPORT;
++
++ rcu_read_lock();
++ ops = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
++ if (likely(ops && ops->gso_send_check)) {
++ skb_reset_transport_header(skb);
++ err = ops->gso_send_check(skb);
++ }
++ rcu_read_unlock();
++
++out:
++ return err;
++}
++
++static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features)
++{
++ struct sk_buff *segs = ERR_PTR(-EINVAL);
++ struct ipv6hdr *ipv6h;
++ struct inet6_protocol *ops;
++
++ if (!(features & NETIF_F_V6_CSUM))
++ features &= ~NETIF_F_SG;
++
++ if (unlikely(skb_shinfo(skb)->gso_type &
++ ~(SKB_GSO_UDP |
++ SKB_GSO_DODGY |
++ SKB_GSO_TCP_ECN |
++ SKB_GSO_TCPV6 |
++ 0)))
++ goto out;
++
++ if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
++ goto out;
++
++ ipv6h = ipv6_hdr(skb);
++ __skb_pull(skb, sizeof(*ipv6h));
++ segs = ERR_PTR(-EPROTONOSUPPORT);
++
++ rcu_read_lock();
++ ops = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
++ if (likely(ops && ops->gso_segment)) {
++ skb_reset_transport_header(skb);
++ segs = ops->gso_segment(skb, features);
++ }
++ rcu_read_unlock();
++
++ if (unlikely(IS_ERR(segs)))
++ goto out;
++
++ for (skb = segs; skb; skb = skb->next) {
++ ipv6h = ipv6_hdr(skb);
++ ipv6h->payload_len = htons(skb->len - skb->mac_len -
++ sizeof(*ipv6h));
++ }
++
++out:
++ return segs;
++}
++
++static struct packet_type ipv6_packet_type = {
++ .type = __constant_htons(ETH_P_IPV6),
++ .func = ipv6_rcv,
++ .gso_send_check = ipv6_gso_send_check,
++ .gso_segment = ipv6_gso_segment,
++};
++
++static int __init ipv6_packet_init(void)
++{
++ dev_add_pack(&ipv6_packet_type);
++ return 0;
++}
++
++static void ipv6_packet_cleanup(void)
++{
++ dev_remove_pack(&ipv6_packet_type);
++}
++
+ static int __init init_ipv6_mibs(void)
+ {
+ if (snmp_mib_init((void **)ipv6_statistics,
+@@ -720,6 +845,8 @@ static void cleanup_ipv6_mibs(void)
+
+ static int inet6_net_init(struct net *net)
+ {
++ int err = 0;
++
+ net->ipv6.sysctl.bindv6only = 0;
+ net->ipv6.sysctl.flush_delay = 0;
+ net->ipv6.sysctl.ip6_rt_max_size = 4096;
+@@ -731,12 +858,36 @@ static int inet6_net_init(struct net *net)
+ net->ipv6.sysctl.ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40;
+ net->ipv6.sysctl.icmpv6_time = 1*HZ;
+
+- return 0;
++#ifdef CONFIG_PROC_FS
++ err = udp6_proc_init(net);
++ if (err)
++ goto out;
++ err = tcp6_proc_init(net);
++ if (err)
++ goto proc_tcp6_fail;
++ err = ac6_proc_init(net);
++ if (err)
++ goto proc_ac6_fail;
++out:
++#endif
++ return err;
++
++#ifdef CONFIG_PROC_FS
++proc_ac6_fail:
++ tcp6_proc_exit(net);
++proc_tcp6_fail:
++ udp6_proc_exit(net);
++ goto out;
++#endif
+ }
+
+ static void inet6_net_exit(struct net *net)
+ {
+- return;
++#ifdef CONFIG_PROC_FS
++ udp6_proc_exit(net);
++ tcp6_proc_exit(net);
++ ac6_proc_exit(net);
++#endif
+ }
+
+ static struct pernet_operations inet6_net_ops = {
+@@ -802,19 +953,16 @@ static int __init inet6_init(void)
+ err = register_pernet_subsys(&inet6_net_ops);
+ if (err)
+ goto register_pernet_fail;
+-
+-#ifdef CONFIG_SYSCTL
+- err = ipv6_sysctl_register();
+- if (err)
+- goto sysctl_fail;
+-#endif
+- err = icmpv6_init(&inet6_family_ops);
++ err = icmpv6_init();
+ if (err)
+ goto icmp_fail;
+- err = ndisc_init(&inet6_family_ops);
++#ifdef CONFIG_IPV6_MROUTE
++ ip6_mr_init();
++#endif
++ err = ndisc_init();
+ if (err)
+ goto ndisc_fail;
+- err = igmp6_init(&inet6_family_ops);
++ err = igmp6_init();
+ if (err)
+ goto igmp_fail;
+ err = ipv6_netfilter_init();
+@@ -825,17 +973,10 @@ static int __init inet6_init(void)
+ err = -ENOMEM;
+ if (raw6_proc_init())
+ goto proc_raw6_fail;
+- if (tcp6_proc_init())
+- goto proc_tcp6_fail;
+- if (udp6_proc_init())
+- goto proc_udp6_fail;
+ if (udplite6_proc_init())
+ goto proc_udplite6_fail;
+ if (ipv6_misc_proc_init())
+ goto proc_misc6_fail;
+-
+- if (ac6_proc_init())
+- goto proc_anycast6_fail;
+ if (if6_proc_init())
+ goto proc_if6_fail;
+ #endif
+@@ -874,9 +1015,19 @@ static int __init inet6_init(void)
+ err = ipv6_packet_init();
+ if (err)
+ goto ipv6_packet_fail;
++
++#ifdef CONFIG_SYSCTL
++ err = ipv6_sysctl_register();
++ if (err)
++ goto sysctl_fail;
++#endif
+ out:
+ return err;
+
++#ifdef CONFIG_SYSCTL
++sysctl_fail:
++ ipv6_packet_cleanup();
++#endif
+ ipv6_packet_fail:
+ tcpv6_exit();
+ tcpv6_fail:
+@@ -897,16 +1048,10 @@ ip6_route_fail:
+ #ifdef CONFIG_PROC_FS
+ if6_proc_exit();
+ proc_if6_fail:
+- ac6_proc_exit();
+-proc_anycast6_fail:
+ ipv6_misc_proc_exit();
+ proc_misc6_fail:
+ udplite6_proc_exit();
+ proc_udplite6_fail:
+- udp6_proc_exit();
+-proc_udp6_fail:
+- tcp6_proc_exit();
+-proc_tcp6_fail:
+ raw6_proc_exit();
+ proc_raw6_fail:
+ #endif
+@@ -918,10 +1063,6 @@ igmp_fail:
+ ndisc_fail:
+ icmpv6_cleanup();
+ icmp_fail:
+-#ifdef CONFIG_SYSCTL
+- ipv6_sysctl_unregister();
+-sysctl_fail:
+-#endif
+ unregister_pernet_subsys(&inet6_net_ops);
+ register_pernet_fail:
+ cleanup_ipv6_mibs();
+@@ -949,6 +1090,9 @@ static void __exit inet6_exit(void)
+ /* Disallow any further netlink messages */
+ rtnl_unregister_all(PF_INET6);
+
++#ifdef CONFIG_SYSCTL
++ ipv6_sysctl_unregister();
++#endif
+ udpv6_exit();
+ udplitev6_exit();
+ tcpv6_exit();
+@@ -964,11 +1108,8 @@ static void __exit inet6_exit(void)
+
+ /* Cleanup code parts. */
+ if6_proc_exit();
+- ac6_proc_exit();
+ ipv6_misc_proc_exit();
+ udplite6_proc_exit();
+- udp6_proc_exit();
+- tcp6_proc_exit();
+ raw6_proc_exit();
+ #endif
+ ipv6_netfilter_fini();
+@@ -976,9 +1117,7 @@ static void __exit inet6_exit(void)
+ ndisc_cleanup();
+ icmpv6_cleanup();
+ rawv6_exit();
+-#ifdef CONFIG_SYSCTL
+- ipv6_sysctl_unregister();
+-#endif
++
+ unregister_pernet_subsys(&inet6_net_ops);
+ cleanup_ipv6_mibs();
+ proto_unregister(&rawv6_prot);
+diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
+index e5f56c9..4e1b29f 100644
+--- a/net/ipv6/anycast.c
++++ b/net/ipv6/anycast.c
+@@ -48,29 +48,6 @@ static int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr);
+ /* Big ac list lock for all the sockets */
+ static DEFINE_RWLOCK(ipv6_sk_ac_lock);
+
+-static int
+-ip6_onlink(struct in6_addr *addr, struct net_device *dev)
+-{
+- struct inet6_dev *idev;
+- struct inet6_ifaddr *ifa;
+- int onlink;
+-
+- onlink = 0;
+- rcu_read_lock();
+- idev = __in6_dev_get(dev);
+- if (idev) {
+- read_lock_bh(&idev->lock);
+- for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) {
+- onlink = ipv6_prefix_equal(addr, &ifa->addr,
+- ifa->prefix_len);
+- if (onlink)
+- break;
+- }
+- read_unlock_bh(&idev->lock);
+- }
+- rcu_read_unlock();
+- return onlink;
+-}
+
+ /*
+ * socket join an anycast group
+@@ -82,6 +59,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr)
+ struct net_device *dev = NULL;
+ struct inet6_dev *idev;
+ struct ipv6_ac_socklist *pac;
++ struct net *net = sock_net(sk);
+ int ishost = !ipv6_devconf.forwarding;
+ int err = 0;
+
+@@ -89,7 +67,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr)
+ return -EPERM;
+ if (ipv6_addr_is_multicast(addr))
+ return -EINVAL;
+- if (ipv6_chk_addr(&init_net, addr, NULL, 0))
++ if (ipv6_chk_addr(net, addr, NULL, 0))
+ return -EINVAL;
+
+ pac = sock_kmalloc(sk, sizeof(struct ipv6_ac_socklist), GFP_KERNEL);
+@@ -101,7 +79,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr)
+ if (ifindex == 0) {
+ struct rt6_info *rt;
+
+- rt = rt6_lookup(addr, NULL, 0, 0);
++ rt = rt6_lookup(net, addr, NULL, 0, 0);
+ if (rt) {
+ dev = rt->rt6i_dev;
+ dev_hold(dev);
+@@ -112,10 +90,10 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr)
+ } else {
+ /* router, no matching interface: just pick one */
+
+- dev = dev_get_by_flags(&init_net, IFF_UP, IFF_UP|IFF_LOOPBACK);
++ dev = dev_get_by_flags(net, IFF_UP, IFF_UP|IFF_LOOPBACK);
+ }
+ } else
+- dev = dev_get_by_index(&init_net, ifindex);
++ dev = dev_get_by_index(net, ifindex);
+
+ if (dev == NULL) {
+ err = -ENODEV;
+@@ -141,7 +119,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr)
+ * This obviates the need for propagating anycast routes while
+ * still allowing some non-router anycast participation.
+ */
+- if (!ip6_onlink(addr, dev)) {
++ if (!ipv6_chk_prefix(addr, dev)) {
+ if (ishost)
+ err = -EADDRNOTAVAIL;
+ if (err)
+@@ -176,6 +154,7 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct net_device *dev;
+ struct ipv6_ac_socklist *pac, *prev_pac;
++ struct net *net = sock_net(sk);
+
+ write_lock_bh(&ipv6_sk_ac_lock);
+ prev_pac = NULL;
+@@ -196,7 +175,7 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
+
+ write_unlock_bh(&ipv6_sk_ac_lock);
+
+- dev = dev_get_by_index(&init_net, pac->acl_ifindex);
++ dev = dev_get_by_index(net, pac->acl_ifindex);
+ if (dev) {
+ ipv6_dev_ac_dec(dev, &pac->acl_addr);
+ dev_put(dev);
+@@ -210,6 +189,7 @@ void ipv6_sock_ac_close(struct sock *sk)
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct net_device *dev = NULL;
+ struct ipv6_ac_socklist *pac;
++ struct net *net = sock_net(sk);
+ int prev_index;
+
+ write_lock_bh(&ipv6_sk_ac_lock);
+@@ -224,7 +204,7 @@ void ipv6_sock_ac_close(struct sock *sk)
+ if (pac->acl_ifindex != prev_index) {
+ if (dev)
+ dev_put(dev);
+- dev = dev_get_by_index(&init_net, pac->acl_ifindex);
++ dev = dev_get_by_index(net, pac->acl_ifindex);
+ prev_index = pac->acl_ifindex;
+ }
+ if (dev)
+@@ -417,14 +397,15 @@ static int ipv6_chk_acast_dev(struct net_device *dev, struct in6_addr *addr)
+ /*
+ * check if given interface (or any, if dev==0) has this anycast address
+ */
+-int ipv6_chk_acast_addr(struct net_device *dev, struct in6_addr *addr)
++int ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
++ struct in6_addr *addr)
+ {
+ int found = 0;
+
+ if (dev)
+ return ipv6_chk_acast_dev(dev, addr);
+ read_lock(&dev_base_lock);
+- for_each_netdev(&init_net, dev)
++ for_each_netdev(net, dev)
+ if (ipv6_chk_acast_dev(dev, addr)) {
+ found = 1;
+ break;
+@@ -436,6 +417,7 @@ int ipv6_chk_acast_addr(struct net_device *dev, struct in6_addr *addr)
+
+ #ifdef CONFIG_PROC_FS
+ struct ac6_iter_state {
++ struct seq_net_private p;
+ struct net_device *dev;
+ struct inet6_dev *idev;
+ };
+@@ -446,9 +428,10 @@ static inline struct ifacaddr6 *ac6_get_first(struct seq_file *seq)
+ {
+ struct ifacaddr6 *im = NULL;
+ struct ac6_iter_state *state = ac6_seq_private(seq);
++ struct net *net = seq_file_net(seq);
+
+ state->idev = NULL;
+- for_each_netdev(&init_net, state->dev) {
++ for_each_netdev(net, state->dev) {
+ struct inet6_dev *idev;
+ idev = in6_dev_get(state->dev);
+ if (!idev)
+@@ -546,8 +529,8 @@ static const struct seq_operations ac6_seq_ops = {
+
+ static int ac6_seq_open(struct inode *inode, struct file *file)
+ {
+- return seq_open_private(file, &ac6_seq_ops,
+- sizeof(struct ac6_iter_state));
++ return seq_open_net(inode, file, &ac6_seq_ops,
++ sizeof(struct ac6_iter_state));
+ }
+
+ static const struct file_operations ac6_seq_fops = {
+@@ -555,20 +538,20 @@ static const struct file_operations ac6_seq_fops = {
+ .open = ac6_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = seq_release_private,
++ .release = seq_release_net,
+ };
+
+-int __init ac6_proc_init(void)
++int ac6_proc_init(struct net *net)
+ {
+- if (!proc_net_fops_create(&init_net, "anycast6", S_IRUGO, &ac6_seq_fops))
++ if (!proc_net_fops_create(net, "anycast6", S_IRUGO, &ac6_seq_fops))
+ return -ENOMEM;
+
+ return 0;
+ }
+
+-void ac6_proc_exit(void)
++void ac6_proc_exit(struct net *net)
+ {
+- proc_net_remove(&init_net, "anycast6");
++ proc_net_remove(net, "anycast6");
+ }
+ #endif
+
+diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
+index 695c0ca..8d05527 100644
+--- a/net/ipv6/fib6_rules.c
++++ b/net/ipv6/fib6_rules.c
+@@ -29,24 +29,22 @@ struct fib6_rule
+ u8 tclass;
+ };
+
+-static struct fib_rules_ops fib6_rules_ops;
+-
+-struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags,
+- pol_lookup_t lookup)
++struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl,
++ int flags, pol_lookup_t lookup)
+ {
+ struct fib_lookup_arg arg = {
+ .lookup_ptr = lookup,
+ };
+
+- fib_rules_lookup(&fib6_rules_ops, fl, flags, &arg);
++ fib_rules_lookup(net->ipv6.fib6_rules_ops, fl, flags, &arg);
+ if (arg.rule)
+ fib_rule_put(arg.rule);
+
+ if (arg.result)
+ return arg.result;
+
+- dst_hold(&ip6_null_entry.u.dst);
+- return &ip6_null_entry.u.dst;
++ dst_hold(&net->ipv6.ip6_null_entry->u.dst);
++ return &net->ipv6.ip6_null_entry->u.dst;
+ }
+
+ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
+@@ -54,28 +52,29 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
+ {
+ struct rt6_info *rt = NULL;
+ struct fib6_table *table;
++ struct net *net = rule->fr_net;
+ pol_lookup_t lookup = arg->lookup_ptr;
+
+ switch (rule->action) {
+ case FR_ACT_TO_TBL:
+ break;
+ case FR_ACT_UNREACHABLE:
+- rt = &ip6_null_entry;
++ rt = net->ipv6.ip6_null_entry;
+ goto discard_pkt;
+ default:
+ case FR_ACT_BLACKHOLE:
+- rt = &ip6_blk_hole_entry;
++ rt = net->ipv6.ip6_blk_hole_entry;
+ goto discard_pkt;
+ case FR_ACT_PROHIBIT:
+- rt = &ip6_prohibit_entry;
++ rt = net->ipv6.ip6_prohibit_entry;
+ goto discard_pkt;
+ }
+
+- table = fib6_get_table(rule->table);
++ table = fib6_get_table(net, rule->table);
+ if (table)
+- rt = lookup(table, flp, flags);
++ rt = lookup(net, table, flp, flags);
+
+- if (rt != &ip6_null_entry) {
++ if (rt != net->ipv6.ip6_null_entry) {
+ struct fib6_rule *r = (struct fib6_rule *)rule;
+
+ /*
+@@ -85,8 +84,18 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
+ if ((rule->flags & FIB_RULE_FIND_SADDR) &&
+ r->src.plen && !(flags & RT6_LOOKUP_F_HAS_SADDR)) {
+ struct in6_addr saddr;
+- if (ipv6_get_saddr(&rt->u.dst, &flp->fl6_dst,
+- &saddr))
++ unsigned int srcprefs = 0;
++
++ if (flags & RT6_LOOKUP_F_SRCPREF_TMP)
++ srcprefs |= IPV6_PREFER_SRC_TMP;
++ if (flags & RT6_LOOKUP_F_SRCPREF_PUBLIC)
++ srcprefs |= IPV6_PREFER_SRC_PUBLIC;
++ if (flags & RT6_LOOKUP_F_SRCPREF_COA)
++ srcprefs |= IPV6_PREFER_SRC_COA;
++
++ if (ipv6_dev_get_saddr(ip6_dst_idev(&rt->u.dst)->dev,
++ &flp->fl6_dst, srcprefs,
++ &saddr))
+ goto again;
+ if (!ipv6_prefix_equal(&saddr, &r->src.addr,
+ r->src.plen))
+@@ -145,13 +154,14 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
+ struct nlattr **tb)
+ {
+ int err = -EINVAL;
++ struct net *net = sock_net(skb->sk);
+ struct fib6_rule *rule6 = (struct fib6_rule *) rule;
+
+ if (rule->action == FR_ACT_TO_TBL) {
+ if (rule->table == RT6_TABLE_UNSPEC)
+ goto errout;
+
+- if (fib6_new_table(rule->table) == NULL) {
++ if (fib6_new_table(net, rule->table) == NULL) {
+ err = -ENOBUFS;
+ goto errout;
+ }
+@@ -234,7 +244,7 @@ static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule)
+ + nla_total_size(16); /* src */
+ }
+
+-static struct fib_rules_ops fib6_rules_ops = {
++static struct fib_rules_ops fib6_rules_ops_template = {
+ .family = AF_INET6,
+ .rule_size = sizeof(struct fib6_rule),
+ .addr_size = sizeof(struct in6_addr),
+@@ -247,45 +257,64 @@ static struct fib_rules_ops fib6_rules_ops = {
+ .nlmsg_payload = fib6_rule_nlmsg_payload,
+ .nlgroup = RTNLGRP_IPV6_RULE,
+ .policy = fib6_rule_policy,
+- .rules_list = LIST_HEAD_INIT(fib6_rules_ops.rules_list),
+ .owner = THIS_MODULE,
+ .fro_net = &init_net,
+ };
+
+-static int __init fib6_default_rules_init(void)
++static int fib6_rules_net_init(struct net *net)
+ {
+- int err;
++ int err = -ENOMEM;
+
+- err = fib_default_rule_add(&fib6_rules_ops, 0,
+- RT6_TABLE_LOCAL, FIB_RULE_PERMANENT);
+- if (err < 0)
+- return err;
+- err = fib_default_rule_add(&fib6_rules_ops, 0x7FFE, RT6_TABLE_MAIN, 0);
+- if (err < 0)
+- return err;
+- return 0;
+-}
++ net->ipv6.fib6_rules_ops = kmemdup(&fib6_rules_ops_template,
++ sizeof(*net->ipv6.fib6_rules_ops),
++ GFP_KERNEL);
++ if (!net->ipv6.fib6_rules_ops)
++ goto out;
+
+-int __init fib6_rules_init(void)
+-{
+- int ret;
++ net->ipv6.fib6_rules_ops->fro_net = net;
++ INIT_LIST_HEAD(&net->ipv6.fib6_rules_ops->rules_list);
+
+- ret = fib6_default_rules_init();
+- if (ret)
+- goto out;
++ err = fib_default_rule_add(net->ipv6.fib6_rules_ops, 0,
++ RT6_TABLE_LOCAL, FIB_RULE_PERMANENT);
++ if (err)
++ goto out_fib6_rules_ops;
+
+- ret = fib_rules_register(&fib6_rules_ops);
+- if (ret)
+- goto out_default_rules_init;
++ err = fib_default_rule_add(net->ipv6.fib6_rules_ops,
++ 0x7FFE, RT6_TABLE_MAIN, 0);
++ if (err)
++ goto out_fib6_default_rule_add;
++
++ err = fib_rules_register(net->ipv6.fib6_rules_ops);
++ if (err)
++ goto out_fib6_default_rule_add;
+ out:
+- return ret;
++ return err;
+
+-out_default_rules_init:
+- fib_rules_cleanup_ops(&fib6_rules_ops);
++out_fib6_default_rule_add:
++ fib_rules_cleanup_ops(net->ipv6.fib6_rules_ops);
++out_fib6_rules_ops:
++ kfree(net->ipv6.fib6_rules_ops);
+ goto out;
+ }
+
++static void fib6_rules_net_exit(struct net *net)
++{
++ fib_rules_unregister(net->ipv6.fib6_rules_ops);
++ kfree(net->ipv6.fib6_rules_ops);
++}
++
++static struct pernet_operations fib6_rules_net_ops = {
++ .init = fib6_rules_net_init,
++ .exit = fib6_rules_net_exit,
++};
++
++int __init fib6_rules_init(void)
++{
++ return register_pernet_subsys(&fib6_rules_net_ops);
++}
++
++
+ void fib6_rules_cleanup(void)
+ {
+- fib_rules_unregister(&fib6_rules_ops);
++ unregister_pernet_subsys(&fib6_rules_net_ops);
+ }
+diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
+index 893287e..d42dd16 100644
+--- a/net/ipv6/icmp.c
++++ b/net/ipv6/icmp.c
+@@ -64,6 +64,7 @@
+ #include <net/addrconf.h>
+ #include <net/icmp.h>
+ #include <net/xfrm.h>
++#include <net/inet_common.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+@@ -80,8 +81,10 @@ EXPORT_SYMBOL(icmpv6msg_statistics);
+ *
+ * On SMP we have one ICMP socket per-cpu.
+ */
+-static DEFINE_PER_CPU(struct socket *, __icmpv6_socket) = NULL;
+-#define icmpv6_socket __get_cpu_var(__icmpv6_socket)
++static inline struct sock *icmpv6_sk(struct net *net)
++{
++ return net->ipv6.icmp_sk[smp_processor_id()];
++}
+
+ static int icmpv6_rcv(struct sk_buff *skb);
+
+@@ -90,11 +93,11 @@ static struct inet6_protocol icmpv6_protocol = {
+ .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
+ };
+
+-static __inline__ int icmpv6_xmit_lock(void)
++static __inline__ int icmpv6_xmit_lock(struct sock *sk)
+ {
+ local_bh_disable();
+
+- if (unlikely(!spin_trylock(&icmpv6_socket->sk->sk_lock.slock))) {
++ if (unlikely(!spin_trylock(&sk->sk_lock.slock))) {
+ /* This can happen if the output path (f.e. SIT or
+ * ip6ip6 tunnel) signals dst_link_failure() for an
+ * outgoing ICMP6 packet.
+@@ -105,9 +108,9 @@ static __inline__ int icmpv6_xmit_lock(void)
+ return 0;
+ }
+
+-static __inline__ void icmpv6_xmit_unlock(void)
++static __inline__ void icmpv6_xmit_unlock(struct sock *sk)
+ {
+- spin_unlock_bh(&icmpv6_socket->sk->sk_lock.slock);
++ spin_unlock_bh(&sk->sk_lock.slock);
+ }
+
+ /*
+@@ -161,6 +164,7 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type,
+ struct flowi *fl)
+ {
+ struct dst_entry *dst;
++ struct net *net = sock_net(sk);
+ int res = 0;
+
+ /* Informational messages are not limited. */
+@@ -176,7 +180,7 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type,
+ * XXX: perhaps the expire for routing entries cloned by
+ * this lookup should be more aggressive (not longer than timeout).
+ */
+- dst = ip6_route_output(sk, fl);
++ dst = ip6_route_output(net, sk, fl);
+ if (dst->error) {
+ IP6_INC_STATS(ip6_dst_idev(dst),
+ IPSTATS_MIB_OUTNOROUTES);
+@@ -184,7 +188,7 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type,
+ res = 1;
+ } else {
+ struct rt6_info *rt = (struct rt6_info *)dst;
+- int tmo = init_net.ipv6.sysctl.icmpv6_time;
++ int tmo = net->ipv6.sysctl.icmpv6_time;
+
+ /* Give more bandwidth to wider prefixes. */
+ if (rt->rt6i_dst.plen < 128)
+@@ -303,6 +307,7 @@ static inline void mip6_addr_swap(struct sk_buff *skb) {}
+ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
+ struct net_device *dev)
+ {
++ struct net *net = dev_net(skb->dev);
+ struct inet6_dev *idev = NULL;
+ struct ipv6hdr *hdr = ipv6_hdr(skb);
+ struct sock *sk;
+@@ -332,7 +337,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
+ */
+ addr_type = ipv6_addr_type(&hdr->daddr);
+
+- if (ipv6_chk_addr(&init_net, &hdr->daddr, skb->dev, 0))
++ if (ipv6_chk_addr(net, &hdr->daddr, skb->dev, 0))
+ saddr = &hdr->daddr;
+
+ /*
+@@ -389,12 +394,12 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
+ fl.fl_icmp_code = code;
+ security_skb_classify_flow(skb, &fl);
+
+- if (icmpv6_xmit_lock())
+- return;
+-
+- sk = icmpv6_socket->sk;
++ sk = icmpv6_sk(net);
+ np = inet6_sk(sk);
+
++ if (icmpv6_xmit_lock(sk))
++ return;
++
+ if (!icmpv6_xrlim_allow(sk, type, &fl))
+ goto out;
+
+@@ -462,9 +467,7 @@ route_done:
+ else
+ hlimit = np->hop_limit;
+ if (hlimit < 0)
+- hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+- if (hlimit < 0)
+- hlimit = ipv6_get_hoplimit(dst->dev);
++ hlimit = ip6_dst_hoplimit(dst);
+
+ tclass = np->tclass;
+ if (tclass < 0)
+@@ -500,13 +503,14 @@ out_put:
+ out_dst_release:
+ dst_release(dst);
+ out:
+- icmpv6_xmit_unlock();
++ icmpv6_xmit_unlock(sk);
+ }
+
+ EXPORT_SYMBOL(icmpv6_send);
+
+ static void icmpv6_echo_reply(struct sk_buff *skb)
+ {
++ struct net *net = dev_net(skb->dev);
+ struct sock *sk;
+ struct inet6_dev *idev;
+ struct ipv6_pinfo *np;
+@@ -537,12 +541,12 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
+ fl.fl_icmp_type = ICMPV6_ECHO_REPLY;
+ security_skb_classify_flow(skb, &fl);
+
+- if (icmpv6_xmit_lock())
+- return;
+-
+- sk = icmpv6_socket->sk;
++ sk = icmpv6_sk(net);
+ np = inet6_sk(sk);
+
++ if (icmpv6_xmit_lock(sk))
++ return;
++
+ if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
+ fl.oif = np->mcast_oif;
+
+@@ -557,9 +561,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
+ else
+ hlimit = np->hop_limit;
+ if (hlimit < 0)
+- hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+- if (hlimit < 0)
+- hlimit = ipv6_get_hoplimit(dst->dev);
++ hlimit = ip6_dst_hoplimit(dst);
+
+ tclass = np->tclass;
+ if (tclass < 0)
+@@ -586,7 +588,7 @@ out_put:
+ in6_dev_put(idev);
+ dst_release(dst);
+ out:
+- icmpv6_xmit_unlock();
++ icmpv6_xmit_unlock(sk);
+ }
+
+ static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info)
+@@ -777,19 +779,40 @@ drop_no_count:
+ return 0;
+ }
+
++void icmpv6_flow_init(struct sock *sk, struct flowi *fl,
++ u8 type,
++ const struct in6_addr *saddr,
++ const struct in6_addr *daddr,
++ int oif)
++{
++ memset(fl, 0, sizeof(*fl));
++ ipv6_addr_copy(&fl->fl6_src, saddr);
++ ipv6_addr_copy(&fl->fl6_dst, daddr);
++ fl->proto = IPPROTO_ICMPV6;
++ fl->fl_icmp_type = type;
++ fl->fl_icmp_code = 0;
++ fl->oif = oif;
++ security_sk_classify_flow(sk, fl);
++}
++
+ /*
+- * Special lock-class for __icmpv6_socket:
++ * Special lock-class for __icmpv6_sk:
+ */
+ static struct lock_class_key icmpv6_socket_sk_dst_lock_key;
+
+-int __init icmpv6_init(struct net_proto_family *ops)
++static int __net_init icmpv6_sk_init(struct net *net)
+ {
+ struct sock *sk;
+ int err, i, j;
+
++ net->ipv6.icmp_sk =
++ kzalloc(nr_cpu_ids * sizeof(struct sock *), GFP_KERNEL);
++ if (net->ipv6.icmp_sk == NULL)
++ return -ENOMEM;
++
+ for_each_possible_cpu(i) {
+- err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6,
+- &per_cpu(__icmpv6_socket, i));
++ err = inet_ctl_sock_create(&sk, PF_INET6,
++ SOCK_RAW, IPPROTO_ICMPV6, net);
+ if (err < 0) {
+ printk(KERN_ERR
+ "Failed to initialize the ICMP6 control socket "
+@@ -798,12 +821,12 @@ int __init icmpv6_init(struct net_proto_family *ops)
+ goto fail;
+ }
+
+- sk = per_cpu(__icmpv6_socket, i)->sk;
+- sk->sk_allocation = GFP_ATOMIC;
++ net->ipv6.icmp_sk[i] = sk;
++
+ /*
+ * Split off their lock-class, because sk->sk_dst_lock
+ * gets used from softirqs, which is safe for
+- * __icmpv6_socket (because those never get directly used
++ * __icmpv6_sk (because those never get directly used
+ * via userspace syscalls), but unsafe for normal sockets.
+ */
+ lockdep_set_class(&sk->sk_dst_lock,
+@@ -814,39 +837,57 @@ int __init icmpv6_init(struct net_proto_family *ops)
+ */
+ sk->sk_sndbuf =
+ (2 * ((64 * 1024) + sizeof(struct sk_buff)));
+-
+- sk->sk_prot->unhash(sk);
+ }
+-
+-
+- if (inet6_add_protocol(&icmpv6_protocol, IPPROTO_ICMPV6) < 0) {
+- printk(KERN_ERR "Failed to register ICMP6 protocol\n");
+- err = -EAGAIN;
+- goto fail;
+- }
+-
+ return 0;
+
+ fail:
+- for (j = 0; j < i; j++) {
+- if (!cpu_possible(j))
+- continue;
+- sock_release(per_cpu(__icmpv6_socket, j));
+- }
+-
++ for (j = 0; j < i; j++)
++ inet_ctl_sock_destroy(net->ipv6.icmp_sk[j]);
++ kfree(net->ipv6.icmp_sk);
+ return err;
+ }
+
+-void icmpv6_cleanup(void)
++static void __net_exit icmpv6_sk_exit(struct net *net)
+ {
+ int i;
+
+ for_each_possible_cpu(i) {
+- sock_release(per_cpu(__icmpv6_socket, i));
++ inet_ctl_sock_destroy(net->ipv6.icmp_sk[i]);
+ }
++ kfree(net->ipv6.icmp_sk);
++}
++
++static struct pernet_operations icmpv6_sk_ops = {
++ .init = icmpv6_sk_init,
++ .exit = icmpv6_sk_exit,
++};
++
++int __init icmpv6_init(void)
++{
++ int err;
++
++ err = register_pernet_subsys(&icmpv6_sk_ops);
++ if (err < 0)
++ return err;
++
++ err = -EAGAIN;
++ if (inet6_add_protocol(&icmpv6_protocol, IPPROTO_ICMPV6) < 0)
++ goto fail;
++ return 0;
++
++fail:
++ printk(KERN_ERR "Failed to register ICMP6 protocol\n");
++ unregister_pernet_subsys(&icmpv6_sk_ops);
++ return err;
++}
++
++void icmpv6_cleanup(void)
++{
++ unregister_pernet_subsys(&icmpv6_sk_ops);
+ inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6);
+ }
+
++
+ static const struct icmp6_err {
+ int err;
+ int fatal;
+@@ -927,6 +968,10 @@ struct ctl_table *ipv6_icmp_sysctl_init(struct net *net)
+ table = kmemdup(ipv6_icmp_table_template,
+ sizeof(ipv6_icmp_table_template),
+ GFP_KERNEL);
++
++ if (table)
++ table[0].data = &net->ipv6.sysctl.icmpv6_time;
++
+ return table;
+ }
+ #endif
+diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
+index 78de42a..87801cc 100644
+--- a/net/ipv6/inet6_connection_sock.c
++++ b/net/ipv6/inet6_connection_sock.c
+@@ -33,6 +33,10 @@ int inet6_csk_bind_conflict(const struct sock *sk,
+ const struct hlist_node *node;
+
+ /* We must walk the whole port owner list in this case. -DaveM */
++ /*
++ * See comment in inet_csk_bind_conflict about sock lookup
++ * vs net namespaces issues.
++ */
+ sk_for_each_bound(sk2, node, &tb->owners) {
+ if (sk != sk2 &&
+ (!sk->sk_bound_dev_if ||
+diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
+index 99fd25f..580014a 100644
+--- a/net/ipv6/inet6_hashtables.c
++++ b/net/ipv6/inet6_hashtables.c
+@@ -24,7 +24,7 @@
+
+ void __inet6_hash(struct sock *sk)
+ {
+- struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
++ struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
+ struct hlist_head *list;
+ rwlock_t *lock;
+
+@@ -43,7 +43,7 @@ void __inet6_hash(struct sock *sk)
+ }
+
+ __sk_add_node(sk, list);
+- sock_prot_inuse_add(sk->sk_prot, 1);
++ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
+ write_unlock(lock);
+ }
+ EXPORT_SYMBOL(__inet6_hash);
+@@ -105,7 +105,7 @@ struct sock *inet6_lookup_listener(struct net *net,
+
+ read_lock(&hashinfo->lhash_lock);
+ sk_for_each(sk, node, &hashinfo->listening_hash[inet_lhashfn(hnum)]) {
+- if (sk->sk_net == net && inet_sk(sk)->num == hnum &&
++ if (net_eq(sock_net(sk), net) && inet_sk(sk)->num == hnum &&
+ sk->sk_family == PF_INET6) {
+ const struct ipv6_pinfo *np = inet6_sk(sk);
+
+@@ -172,7 +172,7 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row,
+ struct sock *sk2;
+ const struct hlist_node *node;
+ struct inet_timewait_sock *tw;
+- struct net *net = sk->sk_net;
++ struct net *net = sock_net(sk);
+
+ prefetch(head->chain.first);
+ write_lock(lock);
+@@ -204,7 +204,7 @@ unique:
+ BUG_TRAP(sk_unhashed(sk));
+ __sk_add_node(sk, &head->chain);
+ sk->sk_hash = hash;
+- sock_prot_inuse_add(sk->sk_prot, 1);
++ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
+ write_unlock(lock);
+
+ if (twp != NULL) {
+diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
+index bab72b6..1ee4fa1 100644
+--- a/net/ipv6/ip6_fib.c
++++ b/net/ipv6/ip6_fib.c
+@@ -48,8 +48,6 @@
+ #define RT6_TRACE(x...) do { ; } while (0)
+ #endif
+
+-struct rt6_statistics rt6_stats;
+-
+ static struct kmem_cache * fib6_node_kmem __read_mostly;
+
+ enum fib_walk_state_t
+@@ -66,6 +64,7 @@ enum fib_walk_state_t
+ struct fib6_cleaner_t
+ {
+ struct fib6_walker_t w;
++ struct net *net;
+ int (*func)(struct rt6_info *, void *arg);
+ void *arg;
+ };
+@@ -78,9 +77,10 @@ static DEFINE_RWLOCK(fib6_walker_lock);
+ #define FWS_INIT FWS_L
+ #endif
+
+-static void fib6_prune_clones(struct fib6_node *fn, struct rt6_info *rt);
+-static struct rt6_info * fib6_find_prefix(struct fib6_node *fn);
+-static struct fib6_node * fib6_repair_tree(struct fib6_node *fn);
++static void fib6_prune_clones(struct net *net, struct fib6_node *fn,
++ struct rt6_info *rt);
++static struct rt6_info *fib6_find_prefix(struct net *net, struct fib6_node *fn);
++static struct fib6_node *fib6_repair_tree(struct net *net, struct fib6_node *fn);
+ static int fib6_walk(struct fib6_walker_t *w);
+ static int fib6_walk_continue(struct fib6_walker_t *w);
+
+@@ -93,7 +93,7 @@ static int fib6_walk_continue(struct fib6_walker_t *w);
+
+ static __u32 rt_sernum;
+
+-static DEFINE_TIMER(ip6_fib_timer, fib6_run_gc, 0, 0);
++static void fib6_gc_timer_cb(unsigned long arg);
+
+ static struct fib6_walker_t fib6_walker_list = {
+ .prev = &fib6_walker_list,
+@@ -166,22 +166,13 @@ static __inline__ void rt6_release(struct rt6_info *rt)
+ dst_free(&rt->u.dst);
+ }
+
+-static struct fib6_table fib6_main_tbl = {
+- .tb6_id = RT6_TABLE_MAIN,
+- .tb6_root = {
+- .leaf = &ip6_null_entry,
+- .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
+- },
+-};
+-
+ #ifdef CONFIG_IPV6_MULTIPLE_TABLES
+ #define FIB_TABLE_HASHSZ 256
+ #else
+ #define FIB_TABLE_HASHSZ 1
+ #endif
+-static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ];
+
+-static void fib6_link_table(struct fib6_table *tb)
++static void fib6_link_table(struct net *net, struct fib6_table *tb)
+ {
+ unsigned int h;
+
+@@ -197,52 +188,46 @@ static void fib6_link_table(struct fib6_table *tb)
+ * No protection necessary, this is the only list mutatation
+ * operation, tables never disappear once they exist.
+ */
+- hlist_add_head_rcu(&tb->tb6_hlist, &fib_table_hash[h]);
++ hlist_add_head_rcu(&tb->tb6_hlist, &net->ipv6.fib_table_hash[h]);
+ }
+
+ #ifdef CONFIG_IPV6_MULTIPLE_TABLES
+-static struct fib6_table fib6_local_tbl = {
+- .tb6_id = RT6_TABLE_LOCAL,
+- .tb6_root = {
+- .leaf = &ip6_null_entry,
+- .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
+- },
+-};
+
+-static struct fib6_table *fib6_alloc_table(u32 id)
++static struct fib6_table *fib6_alloc_table(struct net *net, u32 id)
+ {
+ struct fib6_table *table;
+
+ table = kzalloc(sizeof(*table), GFP_ATOMIC);
+ if (table != NULL) {
+ table->tb6_id = id;
+- table->tb6_root.leaf = &ip6_null_entry;
++ table->tb6_root.leaf = net->ipv6.ip6_null_entry;
+ table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
+ }
+
+ return table;
+ }
+
+-struct fib6_table *fib6_new_table(u32 id)
++struct fib6_table *fib6_new_table(struct net *net, u32 id)
+ {
+ struct fib6_table *tb;
+
+ if (id == 0)
+ id = RT6_TABLE_MAIN;
+- tb = fib6_get_table(id);
++ tb = fib6_get_table(net, id);
+ if (tb)
+ return tb;
+
+- tb = fib6_alloc_table(id);
++ tb = fib6_alloc_table(net, id);
+ if (tb != NULL)
+- fib6_link_table(tb);
++ fib6_link_table(net, tb);
+
+ return tb;
+ }
+
+-struct fib6_table *fib6_get_table(u32 id)
++struct fib6_table *fib6_get_table(struct net *net, u32 id)
+ {
+ struct fib6_table *tb;
++ struct hlist_head *head;
+ struct hlist_node *node;
+ unsigned int h;
+
+@@ -250,7 +235,8 @@ struct fib6_table *fib6_get_table(u32 id)
+ id = RT6_TABLE_MAIN;
+ h = id & (FIB_TABLE_HASHSZ - 1);
+ rcu_read_lock();
+- hlist_for_each_entry_rcu(tb, node, &fib_table_hash[h], tb6_hlist) {
++ head = &net->ipv6.fib_table_hash[h];
++ hlist_for_each_entry_rcu(tb, node, head, tb6_hlist) {
+ if (tb->tb6_id == id) {
+ rcu_read_unlock();
+ return tb;
+@@ -261,33 +247,32 @@ struct fib6_table *fib6_get_table(u32 id)
+ return NULL;
+ }
+
+-static void __init fib6_tables_init(void)
++static void fib6_tables_init(struct net *net)
+ {
+- fib6_link_table(&fib6_main_tbl);
+- fib6_link_table(&fib6_local_tbl);
++ fib6_link_table(net, net->ipv6.fib6_main_tbl);
++ fib6_link_table(net, net->ipv6.fib6_local_tbl);
+ }
+-
+ #else
+
+-struct fib6_table *fib6_new_table(u32 id)
++struct fib6_table *fib6_new_table(struct net *net, u32 id)
+ {
+- return fib6_get_table(id);
++ return fib6_get_table(net, id);
+ }
+
+-struct fib6_table *fib6_get_table(u32 id)
++struct fib6_table *fib6_get_table(struct net *net, u32 id)
+ {
+- return &fib6_main_tbl;
++ return net->ipv6.fib6_main_tbl;
+ }
+
+-struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags,
+- pol_lookup_t lookup)
++struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl,
++ int flags, pol_lookup_t lookup)
+ {
+- return (struct dst_entry *) lookup(&fib6_main_tbl, fl, flags);
++ return (struct dst_entry *) lookup(net, net->ipv6.fib6_main_tbl, fl, flags);
+ }
+
+-static void __init fib6_tables_init(void)
++static void fib6_tables_init(struct net *net)
+ {
+- fib6_link_table(&fib6_main_tbl);
++ fib6_link_table(net, net->ipv6.fib6_main_tbl);
+ }
+
+ #endif
+@@ -361,18 +346,16 @@ end:
+
+ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ unsigned int h, s_h;
+ unsigned int e = 0, s_e;
+ struct rt6_rtnl_dump_arg arg;
+ struct fib6_walker_t *w;
+ struct fib6_table *tb;
+ struct hlist_node *node;
++ struct hlist_head *head;
+ int res = 0;
+
+- if (net != &init_net)
+- return 0;
+-
+ s_h = cb->args[0];
+ s_e = cb->args[1];
+
+@@ -401,7 +384,8 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
+
+ for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) {
+ e = 0;
+- hlist_for_each_entry(tb, node, &fib_table_hash[h], tb6_hlist) {
++ head = &net->ipv6.fib_table_hash[h];
++ hlist_for_each_entry(tb, node, head, tb6_hlist) {
+ if (e < s_e)
+ goto next;
+ res = fib6_dump_table(tb, skb, cb);
+@@ -667,29 +651,29 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
+ rt->rt6i_node = fn;
+ atomic_inc(&rt->rt6i_ref);
+ inet6_rt_notify(RTM_NEWROUTE, rt, info);
+- rt6_stats.fib_rt_entries++;
++ info->nl_net->ipv6.rt6_stats->fib_rt_entries++;
+
+ if ((fn->fn_flags & RTN_RTINFO) == 0) {
+- rt6_stats.fib_route_nodes++;
++ info->nl_net->ipv6.rt6_stats->fib_route_nodes++;
+ fn->fn_flags |= RTN_RTINFO;
+ }
+
+ return 0;
+ }
+
+-static __inline__ void fib6_start_gc(struct rt6_info *rt)
++static __inline__ void fib6_start_gc(struct net *net, struct rt6_info *rt)
+ {
+- if (ip6_fib_timer.expires == 0 &&
++ if (net->ipv6.ip6_fib_timer->expires == 0 &&
+ (rt->rt6i_flags & (RTF_EXPIRES|RTF_CACHE)))
+- mod_timer(&ip6_fib_timer, jiffies +
+- init_net.ipv6.sysctl.ip6_rt_gc_interval);
++ mod_timer(net->ipv6.ip6_fib_timer, jiffies +
++ net->ipv6.sysctl.ip6_rt_gc_interval);
+ }
+
+-void fib6_force_start_gc(void)
++void fib6_force_start_gc(struct net *net)
+ {
+- if (ip6_fib_timer.expires == 0)
+- mod_timer(&ip6_fib_timer, jiffies +
+- init_net.ipv6.sysctl.ip6_rt_gc_interval);
++ if (net->ipv6.ip6_fib_timer->expires == 0)
++ mod_timer(net->ipv6.ip6_fib_timer, jiffies +
++ net->ipv6.sysctl.ip6_rt_gc_interval);
+ }
+
+ /*
+@@ -733,8 +717,8 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
+ if (sfn == NULL)
+ goto st_failure;
+
+- sfn->leaf = &ip6_null_entry;
+- atomic_inc(&ip6_null_entry.rt6i_ref);
++ sfn->leaf = info->nl_net->ipv6.ip6_null_entry;
++ atomic_inc(&info->nl_net->ipv6.ip6_null_entry->rt6i_ref);
+ sfn->fn_flags = RTN_ROOT;
+ sfn->fn_sernum = fib6_new_sernum();
+
+@@ -776,9 +760,9 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
+ err = fib6_add_rt2node(fn, rt, info);
+
+ if (err == 0) {
+- fib6_start_gc(rt);
++ fib6_start_gc(info->nl_net, rt);
+ if (!(rt->rt6i_flags&RTF_CACHE))
+- fib6_prune_clones(pn, rt);
++ fib6_prune_clones(info->nl_net, pn, rt);
+ }
+
+ out:
+@@ -788,12 +772,16 @@ out:
+ * If fib6_add_1 has cleared the old leaf pointer in the
+ * super-tree leaf node we have to find a new one for it.
+ */
++ if (pn != fn && pn->leaf == rt) {
++ pn->leaf = NULL;
++ atomic_dec(&rt->rt6i_ref);
++ }
+ if (pn != fn && !pn->leaf && !(pn->fn_flags & RTN_RTINFO)) {
+- pn->leaf = fib6_find_prefix(pn);
++ pn->leaf = fib6_find_prefix(info->nl_net, pn);
+ #if RT6_DEBUG >= 2
+ if (!pn->leaf) {
+ BUG_TRAP(pn->leaf != NULL);
+- pn->leaf = &ip6_null_entry;
++ pn->leaf = info->nl_net->ipv6.ip6_null_entry;
+ }
+ #endif
+ atomic_inc(&pn->leaf->rt6i_ref);
+@@ -809,7 +797,7 @@ out:
+ */
+ st_failure:
+ if (fn && !(fn->fn_flags & (RTN_RTINFO|RTN_ROOT)))
+- fib6_repair_tree(fn);
++ fib6_repair_tree(info->nl_net, fn);
+ dst_free(&rt->u.dst);
+ return err;
+ #endif
+@@ -975,10 +963,10 @@ struct fib6_node * fib6_locate(struct fib6_node *root,
+ *
+ */
+
+-static struct rt6_info * fib6_find_prefix(struct fib6_node *fn)
++static struct rt6_info *fib6_find_prefix(struct net *net, struct fib6_node *fn)
+ {
+ if (fn->fn_flags&RTN_ROOT)
+- return &ip6_null_entry;
++ return net->ipv6.ip6_null_entry;
+
+ while(fn) {
+ if(fn->left)
+@@ -997,7 +985,8 @@ static struct rt6_info * fib6_find_prefix(struct fib6_node *fn)
+ * is the node we want to try and remove.
+ */
+
+-static struct fib6_node * fib6_repair_tree(struct fib6_node *fn)
++static struct fib6_node *fib6_repair_tree(struct net *net,
++ struct fib6_node *fn)
+ {
+ int children;
+ int nstate;
+@@ -1024,11 +1013,11 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn)
+ || (children && fn->fn_flags&RTN_ROOT)
+ #endif
+ ) {
+- fn->leaf = fib6_find_prefix(fn);
++ fn->leaf = fib6_find_prefix(net, fn);
+ #if RT6_DEBUG >= 2
+ if (fn->leaf==NULL) {
+ BUG_TRAP(fn->leaf);
+- fn->leaf = &ip6_null_entry;
++ fn->leaf = net->ipv6.ip6_null_entry;
+ }
+ #endif
+ atomic_inc(&fn->leaf->rt6i_ref);
+@@ -1101,14 +1090,15 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
+ {
+ struct fib6_walker_t *w;
+ struct rt6_info *rt = *rtp;
++ struct net *net = info->nl_net;
+
+ RT6_TRACE("fib6_del_route\n");
+
+ /* Unlink it */
+ *rtp = rt->u.dst.rt6_next;
+ rt->rt6i_node = NULL;
+- rt6_stats.fib_rt_entries--;
+- rt6_stats.fib_discarded_routes++;
++ net->ipv6.rt6_stats->fib_rt_entries--;
++ net->ipv6.rt6_stats->fib_discarded_routes++;
+
+ /* Reset round-robin state, if necessary */
+ if (fn->rr_ptr == rt)
+@@ -1131,8 +1121,8 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
+ /* If it was last route, expunge its radix tree node */
+ if (fn->leaf == NULL) {
+ fn->fn_flags &= ~RTN_RTINFO;
+- rt6_stats.fib_route_nodes--;
+- fn = fib6_repair_tree(fn);
++ net->ipv6.rt6_stats->fib_route_nodes--;
++ fn = fib6_repair_tree(net, fn);
+ }
+
+ if (atomic_read(&rt->rt6i_ref) != 1) {
+@@ -1144,7 +1134,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
+ */
+ while (fn) {
+ if (!(fn->fn_flags&RTN_RTINFO) && fn->leaf == rt) {
+- fn->leaf = fib6_find_prefix(fn);
++ fn->leaf = fib6_find_prefix(net, fn);
+ atomic_inc(&fn->leaf->rt6i_ref);
+ rt6_release(rt);
+ }
+@@ -1160,6 +1150,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
+
+ int fib6_del(struct rt6_info *rt, struct nl_info *info)
+ {
++ struct net *net = info->nl_net;
+ struct fib6_node *fn = rt->rt6i_node;
+ struct rt6_info **rtp;
+
+@@ -1169,7 +1160,7 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info)
+ return -ENOENT;
+ }
+ #endif
+- if (fn == NULL || rt == &ip6_null_entry)
++ if (fn == NULL || rt == net->ipv6.ip6_null_entry)
+ return -ENOENT;
+
+ BUG_TRAP(fn->fn_flags&RTN_RTINFO);
+@@ -1184,7 +1175,7 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info)
+ pn = pn->parent;
+ }
+ #endif
+- fib6_prune_clones(pn, rt);
++ fib6_prune_clones(info->nl_net, pn, rt);
+ }
+
+ /*
+@@ -1314,12 +1305,12 @@ static int fib6_walk(struct fib6_walker_t *w)
+
+ static int fib6_clean_node(struct fib6_walker_t *w)
+ {
+- struct nl_info info = {
+- .nl_net = &init_net,
+- };
+ int res;
+ struct rt6_info *rt;
+ struct fib6_cleaner_t *c = container_of(w, struct fib6_cleaner_t, w);
++ struct nl_info info = {
++ .nl_net = c->net,
++ };
+
+ for (rt = w->leaf; rt; rt = rt->u.dst.rt6_next) {
+ res = c->func(rt, c->arg);
+@@ -1351,7 +1342,7 @@ static int fib6_clean_node(struct fib6_walker_t *w)
+ * ignoring pure split nodes) will be scanned.
+ */
+
+-static void fib6_clean_tree(struct fib6_node *root,
++static void fib6_clean_tree(struct net *net, struct fib6_node *root,
+ int (*func)(struct rt6_info *, void *arg),
+ int prune, void *arg)
+ {
+@@ -1362,23 +1353,26 @@ static void fib6_clean_tree(struct fib6_node *root,
+ c.w.prune = prune;
+ c.func = func;
+ c.arg = arg;
++ c.net = net;
+
+ fib6_walk(&c.w);
+ }
+
+-void fib6_clean_all(int (*func)(struct rt6_info *, void *arg),
++void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg),
+ int prune, void *arg)
+ {
+ struct fib6_table *table;
+ struct hlist_node *node;
++ struct hlist_head *head;
+ unsigned int h;
+
+ rcu_read_lock();
+ for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
+- hlist_for_each_entry_rcu(table, node, &fib_table_hash[h],
+- tb6_hlist) {
++ head = &net->ipv6.fib_table_hash[h];
++ hlist_for_each_entry_rcu(table, node, head, tb6_hlist) {
+ write_lock_bh(&table->tb6_lock);
+- fib6_clean_tree(&table->tb6_root, func, prune, arg);
++ fib6_clean_tree(net, &table->tb6_root,
++ func, prune, arg);
+ write_unlock_bh(&table->tb6_lock);
+ }
+ }
+@@ -1395,9 +1389,10 @@ static int fib6_prune_clone(struct rt6_info *rt, void *arg)
+ return 0;
+ }
+
+-static void fib6_prune_clones(struct fib6_node *fn, struct rt6_info *rt)
++static void fib6_prune_clones(struct net *net, struct fib6_node *fn,
++ struct rt6_info *rt)
+ {
+- fib6_clean_tree(fn, fib6_prune_clone, 1, rt);
++ fib6_clean_tree(net, fn, fib6_prune_clone, 1, rt);
+ }
+
+ /*
+@@ -1447,54 +1442,145 @@ static int fib6_age(struct rt6_info *rt, void *arg)
+
+ static DEFINE_SPINLOCK(fib6_gc_lock);
+
+-void fib6_run_gc(unsigned long dummy)
++void fib6_run_gc(unsigned long expires, struct net *net)
+ {
+- if (dummy != ~0UL) {
++ if (expires != ~0UL) {
+ spin_lock_bh(&fib6_gc_lock);
+- gc_args.timeout = dummy ? (int)dummy :
+- init_net.ipv6.sysctl.ip6_rt_gc_interval;
++ gc_args.timeout = expires ? (int)expires :
++ net->ipv6.sysctl.ip6_rt_gc_interval;
+ } else {
+ local_bh_disable();
+ if (!spin_trylock(&fib6_gc_lock)) {
+- mod_timer(&ip6_fib_timer, jiffies + HZ);
++ mod_timer(net->ipv6.ip6_fib_timer, jiffies + HZ);
+ local_bh_enable();
+ return;
+ }
+- gc_args.timeout = init_net.ipv6.sysctl.ip6_rt_gc_interval;
++ gc_args.timeout = net->ipv6.sysctl.ip6_rt_gc_interval;
+ }
+ gc_args.more = 0;
+
+- ndisc_dst_gc(&gc_args.more);
+- fib6_clean_all(fib6_age, 0, NULL);
++ icmp6_dst_gc(&gc_args.more);
++
++ fib6_clean_all(net, fib6_age, 0, NULL);
+
+ if (gc_args.more)
+- mod_timer(&ip6_fib_timer, jiffies +
+- init_net.ipv6.sysctl.ip6_rt_gc_interval);
++ mod_timer(net->ipv6.ip6_fib_timer, jiffies +
++ net->ipv6.sysctl.ip6_rt_gc_interval);
+ else {
+- del_timer(&ip6_fib_timer);
+- ip6_fib_timer.expires = 0;
++ del_timer(net->ipv6.ip6_fib_timer);
++ net->ipv6.ip6_fib_timer->expires = 0;
+ }
+ spin_unlock_bh(&fib6_gc_lock);
+ }
+
+-int __init fib6_init(void)
++static void fib6_gc_timer_cb(unsigned long arg)
++{
++ fib6_run_gc(0, (struct net *)arg);
++}
++
++static int fib6_net_init(struct net *net)
+ {
+ int ret;
++ struct timer_list *timer;
++
++ ret = -ENOMEM;
++ timer = kzalloc(sizeof(*timer), GFP_KERNEL);
++ if (!timer)
++ goto out;
++
++ setup_timer(timer, fib6_gc_timer_cb, (unsigned long)net);
++ net->ipv6.ip6_fib_timer = timer;
++
++ net->ipv6.rt6_stats = kzalloc(sizeof(*net->ipv6.rt6_stats), GFP_KERNEL);
++ if (!net->ipv6.rt6_stats)
++ goto out_timer;
++
++ net->ipv6.fib_table_hash =
++ kzalloc(sizeof(*net->ipv6.fib_table_hash)*FIB_TABLE_HASHSZ,
++ GFP_KERNEL);
++ if (!net->ipv6.fib_table_hash)
++ goto out_rt6_stats;
++
++ net->ipv6.fib6_main_tbl = kzalloc(sizeof(*net->ipv6.fib6_main_tbl),
++ GFP_KERNEL);
++ if (!net->ipv6.fib6_main_tbl)
++ goto out_fib_table_hash;
++
++ net->ipv6.fib6_main_tbl->tb6_id = RT6_TABLE_MAIN;
++ net->ipv6.fib6_main_tbl->tb6_root.leaf = net->ipv6.ip6_null_entry;
++ net->ipv6.fib6_main_tbl->tb6_root.fn_flags =
++ RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
++
++#ifdef CONFIG_IPV6_MULTIPLE_TABLES
++ net->ipv6.fib6_local_tbl = kzalloc(sizeof(*net->ipv6.fib6_local_tbl),
++ GFP_KERNEL);
++ if (!net->ipv6.fib6_local_tbl)
++ goto out_fib6_main_tbl;
++ net->ipv6.fib6_local_tbl->tb6_id = RT6_TABLE_LOCAL;
++ net->ipv6.fib6_local_tbl->tb6_root.leaf = net->ipv6.ip6_null_entry;
++ net->ipv6.fib6_local_tbl->tb6_root.fn_flags =
++ RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
++#endif
++ fib6_tables_init(net);
++
++ ret = 0;
++out:
++ return ret;
++
++#ifdef CONFIG_IPV6_MULTIPLE_TABLES
++out_fib6_main_tbl:
++ kfree(net->ipv6.fib6_main_tbl);
++#endif
++out_fib_table_hash:
++ kfree(net->ipv6.fib_table_hash);
++out_rt6_stats:
++ kfree(net->ipv6.rt6_stats);
++out_timer:
++ kfree(timer);
++ goto out;
++ }
++
++static void fib6_net_exit(struct net *net)
++{
++ rt6_ifdown(net, NULL);
++ del_timer_sync(net->ipv6.ip6_fib_timer);
++ kfree(net->ipv6.ip6_fib_timer);
++#ifdef CONFIG_IPV6_MULTIPLE_TABLES
++ kfree(net->ipv6.fib6_local_tbl);
++#endif
++ kfree(net->ipv6.fib6_main_tbl);
++ kfree(net->ipv6.fib_table_hash);
++ kfree(net->ipv6.rt6_stats);
++}
++
++static struct pernet_operations fib6_net_ops = {
++ .init = fib6_net_init,
++ .exit = fib6_net_exit,
++};
++
++int __init fib6_init(void)
++{
++ int ret = -ENOMEM;
++
+ fib6_node_kmem = kmem_cache_create("fib6_nodes",
+ sizeof(struct fib6_node),
+ 0, SLAB_HWCACHE_ALIGN,
+ NULL);
+ if (!fib6_node_kmem)
+- return -ENOMEM;
++ goto out;
+
+- fib6_tables_init();
++ ret = register_pernet_subsys(&fib6_net_ops);
++ if (ret)
++ goto out_kmem_cache_create;
+
+ ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib);
+ if (ret)
+- goto out_kmem_cache_create;
++ goto out_unregister_subsys;
+ out:
+ return ret;
+
++out_unregister_subsys:
++ unregister_pernet_subsys(&fib6_net_ops);
+ out_kmem_cache_create:
+ kmem_cache_destroy(fib6_node_kmem);
+ goto out;
+@@ -1502,6 +1588,6 @@ out_kmem_cache_create:
+
+ void fib6_gc_cleanup(void)
+ {
+- del_timer(&ip6_fib_timer);
++ unregister_pernet_subsys(&fib6_net_ops);
+ kmem_cache_destroy(fib6_node_kmem);
+ }
+diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
+index 2b7d9ee..eb7a940 100644
+--- a/net/ipv6/ip6_flowlabel.c
++++ b/net/ipv6/ip6_flowlabel.c
+@@ -62,23 +62,23 @@ static DEFINE_RWLOCK(ip6_fl_lock);
+ static DEFINE_RWLOCK(ip6_sk_fl_lock);
+
+
+-static __inline__ struct ip6_flowlabel * __fl_lookup(__be32 label)
++static inline struct ip6_flowlabel *__fl_lookup(struct net *net, __be32 label)
+ {
+ struct ip6_flowlabel *fl;
+
+ for (fl=fl_ht[FL_HASH(label)]; fl; fl = fl->next) {
+- if (fl->label == label)
++ if (fl->label == label && fl->fl_net == net)
+ return fl;
+ }
+ return NULL;
+ }
+
+-static struct ip6_flowlabel * fl_lookup(__be32 label)
++static struct ip6_flowlabel *fl_lookup(struct net *net, __be32 label)
+ {
+ struct ip6_flowlabel *fl;
+
+ read_lock_bh(&ip6_fl_lock);
+- fl = __fl_lookup(label);
++ fl = __fl_lookup(net, label);
+ if (fl)
+ atomic_inc(&fl->users);
+ read_unlock_bh(&ip6_fl_lock);
+@@ -88,8 +88,10 @@ static struct ip6_flowlabel * fl_lookup(__be32 label)
+
+ static void fl_free(struct ip6_flowlabel *fl)
+ {
+- if (fl)
++ if (fl) {
++ release_net(fl->fl_net);
+ kfree(fl->opt);
++ }
+ kfree(fl);
+ }
+
+@@ -112,7 +114,6 @@ static void fl_release(struct ip6_flowlabel *fl)
+ time_after(ip6_fl_gc_timer.expires, ttd))
+ mod_timer(&ip6_fl_gc_timer, ttd);
+ }
+-
+ write_unlock_bh(&ip6_fl_lock);
+ }
+
+@@ -148,13 +149,34 @@ static void ip6_fl_gc(unsigned long dummy)
+ if (!sched && atomic_read(&fl_size))
+ sched = now + FL_MAX_LINGER;
+ if (sched) {
+- ip6_fl_gc_timer.expires = sched;
+- add_timer(&ip6_fl_gc_timer);
++ mod_timer(&ip6_fl_gc_timer, sched);
++ }
++ write_unlock(&ip6_fl_lock);
++}
++
++static void ip6_fl_purge(struct net *net)
++{
++ int i;
++
++ write_lock(&ip6_fl_lock);
++ for (i = 0; i <= FL_HASH_MASK; i++) {
++ struct ip6_flowlabel *fl, **flp;
++ flp = &fl_ht[i];
++ while ((fl = *flp) != NULL) {
++ if (fl->fl_net == net && atomic_read(&fl->users) == 0) {
++ *flp = fl->next;
++ fl_free(fl);
++ atomic_dec(&fl_size);
++ continue;
++ }
++ flp = &fl->next;
++ }
+ }
+ write_unlock(&ip6_fl_lock);
+ }
+
+-static struct ip6_flowlabel *fl_intern(struct ip6_flowlabel *fl, __be32 label)
++static struct ip6_flowlabel *fl_intern(struct net *net,
++ struct ip6_flowlabel *fl, __be32 label)
+ {
+ struct ip6_flowlabel *lfl;
+
+@@ -165,7 +187,7 @@ static struct ip6_flowlabel *fl_intern(struct ip6_flowlabel *fl, __be32 label)
+ for (;;) {
+ fl->label = htonl(net_random())&IPV6_FLOWLABEL_MASK;
+ if (fl->label) {
+- lfl = __fl_lookup(fl->label);
++ lfl = __fl_lookup(net, fl->label);
+ if (lfl == NULL)
+ break;
+ }
+@@ -179,7 +201,7 @@ static struct ip6_flowlabel *fl_intern(struct ip6_flowlabel *fl, __be32 label)
+ * done in ipv6_flowlabel_opt - sock is locked, so new entry
+ * with the same label can only appear on another sock
+ */
+- lfl = __fl_lookup(fl->label);
++ lfl = __fl_lookup(net, fl->label);
+ if (lfl != NULL) {
+ atomic_inc(&lfl->users);
+ write_unlock_bh(&ip6_fl_lock);
+@@ -298,7 +320,8 @@ static int fl6_renew(struct ip6_flowlabel *fl, unsigned long linger, unsigned lo
+ }
+
+ static struct ip6_flowlabel *
+-fl_create(struct in6_flowlabel_req *freq, char __user *optval, int optlen, int *err_p)
++fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval,
++ int optlen, int *err_p)
+ {
+ struct ip6_flowlabel *fl;
+ int olen;
+@@ -343,6 +366,7 @@ fl_create(struct in6_flowlabel_req *freq, char __user *optval, int optlen, int *
+ }
+ }
+
++ fl->fl_net = hold_net(net);
+ fl->expires = jiffies;
+ err = fl6_renew(fl, freq->flr_linger, freq->flr_expires);
+ if (err)
+@@ -441,6 +465,7 @@ static inline void fl_link(struct ipv6_pinfo *np, struct ipv6_fl_socklist *sfl,
+ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
+ {
+ int err;
++ struct net *net = sock_net(sk);
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct in6_flowlabel_req freq;
+ struct ipv6_fl_socklist *sfl1=NULL;
+@@ -483,7 +508,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
+ read_unlock_bh(&ip6_sk_fl_lock);
+
+ if (freq.flr_share == IPV6_FL_S_NONE && capable(CAP_NET_ADMIN)) {
+- fl = fl_lookup(freq.flr_label);
++ fl = fl_lookup(net, freq.flr_label);
+ if (fl) {
+ err = fl6_renew(fl, freq.flr_linger, freq.flr_expires);
+ fl_release(fl);
+@@ -496,7 +521,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
+ if (freq.flr_label & ~IPV6_FLOWLABEL_MASK)
+ return -EINVAL;
+
+- fl = fl_create(&freq, optval, optlen, &err);
++ fl = fl_create(net, &freq, optval, optlen, &err);
+ if (fl == NULL)
+ return err;
+ sfl1 = kmalloc(sizeof(*sfl1), GFP_KERNEL);
+@@ -518,7 +543,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
+ read_unlock_bh(&ip6_sk_fl_lock);
+
+ if (fl1 == NULL)
+- fl1 = fl_lookup(freq.flr_label);
++ fl1 = fl_lookup(net, freq.flr_label);
+ if (fl1) {
+ recheck:
+ err = -EEXIST;
+@@ -559,7 +584,7 @@ release:
+ if (sfl1 == NULL || (err = mem_check(sk)) != 0)
+ goto done;
+
+- fl1 = fl_intern(fl, freq.flr_label);
++ fl1 = fl_intern(net, fl, freq.flr_label);
+ if (fl1 != NULL)
+ goto recheck;
+
+@@ -586,6 +611,7 @@ done:
+ #ifdef CONFIG_PROC_FS
+
+ struct ip6fl_iter_state {
++ struct seq_net_private p;
+ int bucket;
+ };
+
+@@ -595,12 +621,15 @@ static struct ip6_flowlabel *ip6fl_get_first(struct seq_file *seq)
+ {
+ struct ip6_flowlabel *fl = NULL;
+ struct ip6fl_iter_state *state = ip6fl_seq_private(seq);
++ struct net *net = seq_file_net(seq);
+
+ for (state->bucket = 0; state->bucket <= FL_HASH_MASK; ++state->bucket) {
+- if (fl_ht[state->bucket]) {
+- fl = fl_ht[state->bucket];
++ fl = fl_ht[state->bucket];
++
++ while (fl && fl->fl_net != net)
++ fl = fl->next;
++ if (fl)
+ break;
+- }
+ }
+ return fl;
+ }
+@@ -608,12 +637,18 @@ static struct ip6_flowlabel *ip6fl_get_first(struct seq_file *seq)
+ static struct ip6_flowlabel *ip6fl_get_next(struct seq_file *seq, struct ip6_flowlabel *fl)
+ {
+ struct ip6fl_iter_state *state = ip6fl_seq_private(seq);
++ struct net *net = seq_file_net(seq);
+
+ fl = fl->next;
++try_again:
++ while (fl && fl->fl_net != net)
++ fl = fl->next;
++
+ while (!fl) {
+- if (++state->bucket <= FL_HASH_MASK)
++ if (++state->bucket <= FL_HASH_MASK) {
+ fl = fl_ht[state->bucket];
+- else
++ goto try_again;
++ } else
+ break;
+ }
+ return fl;
+@@ -683,8 +718,8 @@ static const struct seq_operations ip6fl_seq_ops = {
+
+ static int ip6fl_seq_open(struct inode *inode, struct file *file)
+ {
+- return seq_open_private(file, &ip6fl_seq_ops,
+- sizeof(struct ip6fl_iter_state));
++ return seq_open_net(inode, file, &ip6fl_seq_ops,
++ sizeof(struct ip6fl_iter_state));
+ }
+
+ static const struct file_operations ip6fl_seq_fops = {
+@@ -692,12 +727,13 @@ static const struct file_operations ip6fl_seq_fops = {
+ .open = ip6fl_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = seq_release_private,
++ .release = seq_release_net,
+ };
+
+ static int ip6_flowlabel_proc_init(struct net *net)
+ {
+- if (!proc_net_fops_create(net, "ip6_flowlabel", S_IRUGO, &ip6fl_seq_fops))
++ if (!proc_net_fops_create(net, "ip6_flowlabel",
++ S_IRUGO, &ip6fl_seq_fops))
+ return -ENOMEM;
+ return 0;
+ }
+@@ -717,13 +753,24 @@ static inline void ip6_flowlabel_proc_fini(struct net *net)
+ }
+ #endif
+
++static inline void ip6_flowlabel_net_exit(struct net *net)
++{
++ ip6_fl_purge(net);
++ ip6_flowlabel_proc_fini(net);
++}
++
++static struct pernet_operations ip6_flowlabel_net_ops = {
++ .init = ip6_flowlabel_proc_init,
++ .exit = ip6_flowlabel_net_exit,
++};
++
+ int ip6_flowlabel_init(void)
+ {
+- return ip6_flowlabel_proc_init(&init_net);
++ return register_pernet_subsys(&ip6_flowlabel_net_ops);
+ }
+
+ void ip6_flowlabel_cleanup(void)
+ {
+ del_timer(&ip6_fl_gc_timer);
+- ip6_flowlabel_proc_fini(&init_net);
++ unregister_pernet_subsys(&ip6_flowlabel_net_ops);
+ }
+diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
+index 98ab4f4..4e5c861 100644
+--- a/net/ipv6/ip6_input.c
++++ b/net/ipv6/ip6_input.c
+@@ -29,6 +29,7 @@
+ #include <linux/netdevice.h>
+ #include <linux/in6.h>
+ #include <linux/icmpv6.h>
++#include <linux/mroute6.h>
+
+ #include <linux/netfilter.h>
+ #include <linux/netfilter_ipv6.h>
+@@ -61,11 +62,6 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
+ u32 pkt_len;
+ struct inet6_dev *idev;
+
+- if (dev->nd_net != &init_net) {
+- kfree_skb(skb);
+- return 0;
+- }
+-
+ if (skb->pkt_type == PACKET_OTHERHOST) {
+ kfree_skb(skb);
+ return 0;
+@@ -241,38 +237,84 @@ int ip6_mc_input(struct sk_buff *skb)
+ hdr = ipv6_hdr(skb);
+ deliver = ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL);
+
++#ifdef CONFIG_IPV6_MROUTE
+ /*
+- * IPv6 multicast router mode isnt currently supported.
++ * IPv6 multicast router mode is now supported ;)
+ */
+-#if 0
+- if (ipv6_config.multicast_route) {
+- int addr_type;
+-
+- addr_type = ipv6_addr_type(&hdr->daddr);
+-
+- if (!(addr_type & (IPV6_ADDR_LOOPBACK | IPV6_ADDR_LINKLOCAL))) {
+- struct sk_buff *skb2;
+- struct dst_entry *dst;
++ if (ipv6_devconf.mc_forwarding &&
++ likely(!(IP6CB(skb)->flags & IP6SKB_FORWARDED))) {
++ /*
++ * Okay, we try to forward - split and duplicate
++ * packets.
++ */
++ struct sk_buff *skb2;
++ struct inet6_skb_parm *opt = IP6CB(skb);
++
++ /* Check for MLD */
++ if (unlikely(opt->ra)) {
++ /* Check if this is a mld message */
++ u8 *ptr = skb_network_header(skb) + opt->ra;
++ struct icmp6hdr *icmp6;
++ u8 nexthdr = hdr->nexthdr;
++ int offset;
++
++ /* Check if the value of Router Alert
++ * is for MLD (0x0000).
++ */
++ if ((ptr[2] | ptr[3]) == 0) {
++ deliver = 0;
++
++ if (!ipv6_ext_hdr(nexthdr)) {
++ /* BUG */
++ goto out;
++ }
++ offset = ipv6_skip_exthdr(skb, sizeof(*hdr),
++ &nexthdr);
++ if (offset < 0)
++ goto out;
++
++ if (nexthdr != IPPROTO_ICMPV6)
++ goto out;
++
++ if (!pskb_may_pull(skb, (skb_network_header(skb) +
++ offset + 1 - skb->data)))
++ goto out;
++
++ icmp6 = (struct icmp6hdr *)(skb_network_header(skb) + offset);
++
++ switch (icmp6->icmp6_type) {
++ case ICMPV6_MGM_QUERY:
++ case ICMPV6_MGM_REPORT:
++ case ICMPV6_MGM_REDUCTION:
++ case ICMPV6_MLD2_REPORT:
++ deliver = 1;
++ break;
++ }
++ goto out;
++ }
++ /* unknown RA - process it normally */
++ }
+
+- dst = skb->dst;
++ if (deliver)
++ skb2 = skb_clone(skb, GFP_ATOMIC);
++ else {
++ skb2 = skb;
++ skb = NULL;
++ }
+
+- if (deliver) {
+- skb2 = skb_clone(skb, GFP_ATOMIC);
+- dst_output(skb2);
+- } else {
+- dst_output(skb);
+- return 0;
+- }
++ if (skb2) {
++ skb2->dev = skb2->dst->dev;
++ ip6_mr_input(skb2);
+ }
+ }
++out:
+ #endif
+-
+- if (likely(deliver)) {
++ if (likely(deliver))
+ ip6_input(skb);
+- return 0;
++ else {
++ /* discard */
++ kfree_skb(skb);
+ }
+- /* discard */
+- kfree_skb(skb);
+
+ return 0;
+ }
+diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
+index 8b67ca0..0af2e05 100644
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -55,6 +55,7 @@
+ #include <net/icmp.h>
+ #include <net/xfrm.h>
+ #include <net/checksum.h>
++#include <linux/mroute6.h>
+
+ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
+
+@@ -137,8 +138,9 @@ static int ip6_output2(struct sk_buff *skb)
+ struct inet6_dev *idev = ip6_dst_idev(skb->dst);
+
+ if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) &&
+- ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr,
+- &ipv6_hdr(skb)->saddr)) {
++ ((mroute6_socket && !(IP6CB(skb)->flags & IP6SKB_FORWARDED)) ||
++ ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr,
++ &ipv6_hdr(skb)->saddr))) {
+ struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC);
+
+ /* Do not check for IFF_ALLMULTI; multicast routing
+@@ -237,9 +239,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
+ if (np)
+ hlimit = np->hop_limit;
+ if (hlimit < 0)
+- hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+- if (hlimit < 0)
+- hlimit = ipv6_get_hoplimit(dst->dev);
++ hlimit = ip6_dst_hoplimit(dst);
+
+ tclass = -1;
+ if (np)
+@@ -286,7 +286,7 @@ EXPORT_SYMBOL(ip6_xmit);
+ */
+
+ int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev,
+- struct in6_addr *saddr, struct in6_addr *daddr,
++ const struct in6_addr *saddr, const struct in6_addr *daddr,
+ int proto, int len)
+ {
+ struct ipv6_pinfo *np = inet6_sk(sk);
+@@ -404,6 +404,7 @@ int ip6_forward(struct sk_buff *skb)
+ struct dst_entry *dst = skb->dst;
+ struct ipv6hdr *hdr = ipv6_hdr(skb);
+ struct inet6_skb_parm *opt = IP6CB(skb);
++ struct net *net = dev_net(dst->dev);
+
+ if (ipv6_devconf.forwarding == 0)
+ goto error;
+@@ -450,7 +451,7 @@ int ip6_forward(struct sk_buff *skb)
+
+ /* XXX: idev->cnf.proxy_ndp? */
+ if (ipv6_devconf.proxy_ndp &&
+- pneigh_lookup(&nd_tbl, &init_net, &hdr->daddr, skb->dev, 0)) {
++ pneigh_lookup(&nd_tbl, net, &hdr->daddr, skb->dev, 0)) {
+ int proxied = ip6_forward_proxy_check(skb);
+ if (proxied > 0)
+ return ip6_input(skb);
+@@ -596,7 +597,6 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
+
+ return offset;
+ }
+-EXPORT_SYMBOL_GPL(ip6_find_1stfragopt);
+
+ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
+ {
+@@ -912,15 +912,19 @@ static int ip6_dst_lookup_tail(struct sock *sk,
+ struct dst_entry **dst, struct flowi *fl)
+ {
+ int err;
++ struct net *net = sock_net(sk);
+
+ if (*dst == NULL)
+- *dst = ip6_route_output(sk, fl);
++ *dst = ip6_route_output(net, sk, fl);
+
+ if ((err = (*dst)->error))
+ goto out_err_release;
+
+ if (ipv6_addr_any(&fl->fl6_src)) {
+- err = ipv6_get_saddr(*dst, &fl->fl6_dst, &fl->fl6_src);
++ err = ipv6_dev_get_saddr(ip6_dst_idev(*dst)->dev,
++ &fl->fl6_dst,
++ sk ? inet6_sk(sk)->srcprefs : 0,
++ &fl->fl6_src);
+ if (err)
+ goto out_err_release;
+ }
+@@ -939,7 +943,7 @@ static int ip6_dst_lookup_tail(struct sock *sk,
+ struct flowi fl_gw;
+ int redirect;
+
+- ifp = ipv6_get_ifaddr(&init_net, &fl->fl6_src,
++ ifp = ipv6_get_ifaddr(net, &fl->fl6_src,
+ (*dst)->dev, 1);
+
+ redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC);
+@@ -954,7 +958,7 @@ static int ip6_dst_lookup_tail(struct sock *sk,
+ dst_release(*dst);
+ memcpy(&fl_gw, fl, sizeof(struct flowi));
+ memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr));
+- *dst = ip6_route_output(sk, &fl_gw);
++ *dst = ip6_route_output(net, sk, &fl_gw);
+ if ((err = (*dst)->error))
+ goto out_err_release;
+ }
+@@ -1113,7 +1117,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
+ /* need source address above miyazawa*/
+ }
+ dst_hold(&rt->u.dst);
+- np->cork.rt = rt;
++ inet->cork.dst = &rt->u.dst;
+ inet->cork.fl = *fl;
+ np->cork.hop_limit = hlimit;
+ np->cork.tclass = tclass;
+@@ -1134,7 +1138,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
+ length += exthdrlen;
+ transhdrlen += exthdrlen;
+ } else {
+- rt = np->cork.rt;
++ rt = (struct rt6_info *)inet->cork.dst;
+ fl = &inet->cork.fl;
+ if (inet->cork.flags & IPCORK_OPT)
+ opt = np->cork.opt;
+@@ -1379,9 +1383,9 @@ static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np)
+ inet->cork.flags &= ~IPCORK_OPT;
+ kfree(np->cork.opt);
+ np->cork.opt = NULL;
+- if (np->cork.rt) {
+- dst_release(&np->cork.rt->u.dst);
+- np->cork.rt = NULL;
++ if (inet->cork.dst) {
++ dst_release(inet->cork.dst);
++ inet->cork.dst = NULL;
+ inet->cork.flags &= ~IPCORK_ALLFRAG;
+ }
+ memset(&inet->cork.fl, 0, sizeof(inet->cork.fl));
+@@ -1396,7 +1400,7 @@ int ip6_push_pending_frames(struct sock *sk)
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct ipv6hdr *hdr;
+ struct ipv6_txoptions *opt = np->cork.opt;
+- struct rt6_info *rt = np->cork.rt;
++ struct rt6_info *rt = (struct rt6_info *)inet->cork.dst;
+ struct flowi *fl = &inet->cork.fl;
+ unsigned char proto = fl->proto;
+ int err = 0;
+diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
+index 78f4388..2bda3ba 100644
+--- a/net/ipv6/ip6_tunnel.c
++++ b/net/ipv6/ip6_tunnel.c
+@@ -52,6 +52,8 @@
+ #include <net/xfrm.h>
+ #include <net/dsfield.h>
+ #include <net/inet_ecn.h>
++#include <net/net_namespace.h>
++#include <net/netns/generic.h>
+
+ MODULE_AUTHOR("Ville Nuorvala");
+ MODULE_DESCRIPTION("IPv6 tunneling device");
+@@ -60,7 +62,7 @@ MODULE_LICENSE("GPL");
+ #define IPV6_TLV_TEL_DST_SIZE 8
+
+ #ifdef IP6_TNL_DEBUG
+-#define IP6_TNL_TRACE(x...) printk(KERN_DEBUG "%s:" x "\n", __FUNCTION__)
++#define IP6_TNL_TRACE(x...) printk(KERN_DEBUG "%s:" x "\n", __func__)
+ #else
+ #define IP6_TNL_TRACE(x...) do {;} while(0)
+ #endif
+@@ -78,14 +80,15 @@ static int ip6_fb_tnl_dev_init(struct net_device *dev);
+ static int ip6_tnl_dev_init(struct net_device *dev);
+ static void ip6_tnl_dev_setup(struct net_device *dev);
+
+-/* the IPv6 tunnel fallback device */
+-static struct net_device *ip6_fb_tnl_dev;
+-
+-
+-/* lists for storing tunnels in use */
+-static struct ip6_tnl *tnls_r_l[HASH_SIZE];
+-static struct ip6_tnl *tnls_wc[1];
+-static struct ip6_tnl **tnls[2] = { tnls_wc, tnls_r_l };
++static int ip6_tnl_net_id;
++struct ip6_tnl_net {
++ /* the IPv6 tunnel fallback device */
++ struct net_device *fb_tnl_dev;
++ /* lists for storing tunnels in use */
++ struct ip6_tnl *tnls_r_l[HASH_SIZE];
++ struct ip6_tnl *tnls_wc[1];
++ struct ip6_tnl **tnls[2];
++};
+
+ /* lock for the tunnel lists */
+ static DEFINE_RWLOCK(ip6_tnl_lock);
+@@ -130,19 +133,20 @@ static inline void ip6_tnl_dst_store(struct ip6_tnl *t, struct dst_entry *dst)
+ **/
+
+ static struct ip6_tnl *
+-ip6_tnl_lookup(struct in6_addr *remote, struct in6_addr *local)
++ip6_tnl_lookup(struct net *net, struct in6_addr *remote, struct in6_addr *local)
+ {
+ unsigned h0 = HASH(remote);
+ unsigned h1 = HASH(local);
+ struct ip6_tnl *t;
++ struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+
+- for (t = tnls_r_l[h0 ^ h1]; t; t = t->next) {
++ for (t = ip6n->tnls_r_l[h0 ^ h1]; t; t = t->next) {
+ if (ipv6_addr_equal(local, &t->parms.laddr) &&
+ ipv6_addr_equal(remote, &t->parms.raddr) &&
+ (t->dev->flags & IFF_UP))
+ return t;
+ }
+- if ((t = tnls_wc[0]) != NULL && (t->dev->flags & IFF_UP))
++ if ((t = ip6n->tnls_wc[0]) != NULL && (t->dev->flags & IFF_UP))
+ return t;
+
+ return NULL;
+@@ -160,7 +164,7 @@ ip6_tnl_lookup(struct in6_addr *remote, struct in6_addr *local)
+ **/
+
+ static struct ip6_tnl **
+-ip6_tnl_bucket(struct ip6_tnl_parm *p)
++ip6_tnl_bucket(struct ip6_tnl_net *ip6n, struct ip6_tnl_parm *p)
+ {
+ struct in6_addr *remote = &p->raddr;
+ struct in6_addr *local = &p->laddr;
+@@ -171,7 +175,7 @@ ip6_tnl_bucket(struct ip6_tnl_parm *p)
+ prio = 1;
+ h = HASH(remote) ^ HASH(local);
+ }
+- return &tnls[prio][h];
++ return &ip6n->tnls[prio][h];
+ }
+
+ /**
+@@ -180,9 +184,9 @@ ip6_tnl_bucket(struct ip6_tnl_parm *p)
+ **/
+
+ static void
+-ip6_tnl_link(struct ip6_tnl *t)
++ip6_tnl_link(struct ip6_tnl_net *ip6n, struct ip6_tnl *t)
+ {
+- struct ip6_tnl **tp = ip6_tnl_bucket(&t->parms);
++ struct ip6_tnl **tp = ip6_tnl_bucket(ip6n, &t->parms);
+
+ t->next = *tp;
+ write_lock_bh(&ip6_tnl_lock);
+@@ -196,11 +200,11 @@ ip6_tnl_link(struct ip6_tnl *t)
+ **/
+
+ static void
+-ip6_tnl_unlink(struct ip6_tnl *t)
++ip6_tnl_unlink(struct ip6_tnl_net *ip6n, struct ip6_tnl *t)
+ {
+ struct ip6_tnl **tp;
+
+- for (tp = ip6_tnl_bucket(&t->parms); *tp; tp = &(*tp)->next) {
++ for (tp = ip6_tnl_bucket(ip6n, &t->parms); *tp; tp = &(*tp)->next) {
+ if (t == *tp) {
+ write_lock_bh(&ip6_tnl_lock);
+ *tp = t->next;
+@@ -222,12 +226,13 @@ ip6_tnl_unlink(struct ip6_tnl *t)
+ * created tunnel or NULL
+ **/
+
+-static struct ip6_tnl *ip6_tnl_create(struct ip6_tnl_parm *p)
++static struct ip6_tnl *ip6_tnl_create(struct net *net, struct ip6_tnl_parm *p)
+ {
+ struct net_device *dev;
+ struct ip6_tnl *t;
+ char name[IFNAMSIZ];
+ int err;
++ struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+
+ if (p->name[0])
+ strlcpy(name, p->name, IFNAMSIZ);
+@@ -238,6 +243,8 @@ static struct ip6_tnl *ip6_tnl_create(struct ip6_tnl_parm *p)
+ if (dev == NULL)
+ goto failed;
+
++ dev_net_set(dev, net);
++
+ if (strchr(name, '%')) {
+ if (dev_alloc_name(dev, name) < 0)
+ goto failed_free;
+@@ -251,7 +258,7 @@ static struct ip6_tnl *ip6_tnl_create(struct ip6_tnl_parm *p)
+ goto failed_free;
+
+ dev_hold(dev);
+- ip6_tnl_link(t);
++ ip6_tnl_link(ip6n, t);
+ return t;
+
+ failed_free:
+@@ -274,20 +281,22 @@ failed:
+ * matching tunnel or NULL
+ **/
+
+-static struct ip6_tnl *ip6_tnl_locate(struct ip6_tnl_parm *p, int create)
++static struct ip6_tnl *ip6_tnl_locate(struct net *net,
++ struct ip6_tnl_parm *p, int create)
+ {
+ struct in6_addr *remote = &p->raddr;
+ struct in6_addr *local = &p->laddr;
+ struct ip6_tnl *t;
++ struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+
+- for (t = *ip6_tnl_bucket(p); t; t = t->next) {
++ for (t = *ip6_tnl_bucket(ip6n, p); t; t = t->next) {
+ if (ipv6_addr_equal(local, &t->parms.laddr) &&
+ ipv6_addr_equal(remote, &t->parms.raddr))
+ return t;
+ }
+ if (!create)
+ return NULL;
+- return ip6_tnl_create(p);
++ return ip6_tnl_create(net, p);
+ }
+
+ /**
+@@ -302,13 +311,15 @@ static void
+ ip6_tnl_dev_uninit(struct net_device *dev)
+ {
+ struct ip6_tnl *t = netdev_priv(dev);
++ struct net *net = dev_net(dev);
++ struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+
+- if (dev == ip6_fb_tnl_dev) {
++ if (dev == ip6n->fb_tnl_dev) {
+ write_lock_bh(&ip6_tnl_lock);
+- tnls_wc[0] = NULL;
++ ip6n->tnls_wc[0] = NULL;
+ write_unlock_bh(&ip6_tnl_lock);
+ } else {
+- ip6_tnl_unlink(t);
++ ip6_tnl_unlink(ip6n, t);
+ }
+ ip6_tnl_dst_reset(t);
+ dev_put(dev);
+@@ -401,7 +412,8 @@ ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt,
+ processing of the error. */
+
+ read_lock(&ip6_tnl_lock);
+- if ((t = ip6_tnl_lookup(&ipv6h->daddr, &ipv6h->saddr)) == NULL)
++ if ((t = ip6_tnl_lookup(dev_net(skb->dev), &ipv6h->daddr,
++ &ipv6h->saddr)) == NULL)
+ goto out;
+
+ if (t->parms.proto != ipproto && t->parms.proto != 0)
+@@ -533,7 +545,7 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ fl.fl4_dst = eiph->saddr;
+ fl.fl4_tos = RT_TOS(eiph->tos);
+ fl.proto = IPPROTO_IPIP;
+- if (ip_route_output_key(&init_net, &rt, &fl))
++ if (ip_route_output_key(dev_net(skb->dev), &rt, &fl))
+ goto out;
+
+ skb2->dev = rt->u.dst.dev;
+@@ -545,7 +557,7 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ fl.fl4_dst = eiph->daddr;
+ fl.fl4_src = eiph->saddr;
+ fl.fl4_tos = eiph->tos;
+- if (ip_route_output_key(&init_net, &rt, &fl) ||
++ if (ip_route_output_key(dev_net(skb->dev), &rt, &fl) ||
+ rt->u.dst.dev->type != ARPHRD_TUNNEL) {
+ ip_rt_put(rt);
+ goto out;
+@@ -602,7 +614,8 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ skb_reset_network_header(skb2);
+
+ /* Try to guess incoming interface */
+- rt = rt6_lookup(&ipv6_hdr(skb2)->saddr, NULL, 0, 0);
++ rt = rt6_lookup(dev_net(skb->dev), &ipv6_hdr(skb2)->saddr,
++ NULL, 0, 0);
+
+ if (rt && rt->rt6i_dev)
+ skb2->dev = rt->rt6i_dev;
+@@ -646,16 +659,17 @@ static inline int ip6_tnl_rcv_ctl(struct ip6_tnl *t)
+ {
+ struct ip6_tnl_parm *p = &t->parms;
+ int ret = 0;
++ struct net *net = dev_net(t->dev);
+
+ if (p->flags & IP6_TNL_F_CAP_RCV) {
+ struct net_device *ldev = NULL;
+
+ if (p->link)
+- ldev = dev_get_by_index(&init_net, p->link);
++ ldev = dev_get_by_index(net, p->link);
+
+ if ((ipv6_addr_is_multicast(&p->laddr) ||
+- likely(ipv6_chk_addr(&init_net, &p->laddr, ldev, 0))) &&
+- likely(!ipv6_chk_addr(&init_net, &p->raddr, NULL, 0)))
++ likely(ipv6_chk_addr(net, &p->laddr, ldev, 0))) &&
++ likely(!ipv6_chk_addr(net, &p->raddr, NULL, 0)))
+ ret = 1;
+
+ if (ldev)
+@@ -684,7 +698,8 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol,
+
+ read_lock(&ip6_tnl_lock);
+
+- if ((t = ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) {
++ if ((t = ip6_tnl_lookup(dev_net(skb->dev), &ipv6h->saddr,
++ &ipv6h->daddr)) != NULL) {
+ if (t->parms.proto != ipproto && t->parms.proto != 0) {
+ read_unlock(&ip6_tnl_lock);
+ goto discard;
+@@ -782,19 +797,20 @@ static inline int ip6_tnl_xmit_ctl(struct ip6_tnl *t)
+ {
+ struct ip6_tnl_parm *p = &t->parms;
+ int ret = 0;
++ struct net *net = dev_net(t->dev);
+
+ if (p->flags & IP6_TNL_F_CAP_XMIT) {
+ struct net_device *ldev = NULL;
+
+ if (p->link)
+- ldev = dev_get_by_index(&init_net, p->link);
++ ldev = dev_get_by_index(net, p->link);
+
+- if (unlikely(!ipv6_chk_addr(&init_net, &p->laddr, ldev, 0)))
++ if (unlikely(!ipv6_chk_addr(net, &p->laddr, ldev, 0)))
+ printk(KERN_WARNING
+ "%s xmit: Local address not yet configured!\n",
+ p->name);
+ else if (!ipv6_addr_is_multicast(&p->raddr) &&
+- unlikely(ipv6_chk_addr(&init_net, &p->raddr, NULL, 0)))
++ unlikely(ipv6_chk_addr(net, &p->raddr, NULL, 0)))
+ printk(KERN_WARNING
+ "%s xmit: Routing loop! "
+ "Remote address found on this node!\n",
+@@ -847,7 +863,7 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
+ if ((dst = ip6_tnl_dst_check(t)) != NULL)
+ dst_hold(dst);
+ else {
+- dst = ip6_route_output(NULL, fl);
++ dst = ip6_route_output(dev_net(dev), NULL, fl);
+
+ if (dst->error || xfrm_lookup(&dst, fl, NULL, 0) < 0)
+ goto tx_err_link_failure;
+@@ -1112,7 +1128,8 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
+ int strict = (ipv6_addr_type(&p->raddr) &
+ (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL));
+
+- struct rt6_info *rt = rt6_lookup(&p->raddr, &p->laddr,
++ struct rt6_info *rt = rt6_lookup(dev_net(dev),
++ &p->raddr, &p->laddr,
+ p->link, strict);
+
+ if (rt == NULL)
+@@ -1191,15 +1208,17 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ int err = 0;
+ struct ip6_tnl_parm p;
+ struct ip6_tnl *t = NULL;
++ struct net *net = dev_net(dev);
++ struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+
+ switch (cmd) {
+ case SIOCGETTUNNEL:
+- if (dev == ip6_fb_tnl_dev) {
++ if (dev == ip6n->fb_tnl_dev) {
+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) {
+ err = -EFAULT;
+ break;
+ }
+- t = ip6_tnl_locate(&p, 0);
++ t = ip6_tnl_locate(net, &p, 0);
+ }
+ if (t == NULL)
+ t = netdev_priv(dev);
+@@ -1220,8 +1239,8 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ if (p.proto != IPPROTO_IPV6 && p.proto != IPPROTO_IPIP &&
+ p.proto != 0)
+ break;
+- t = ip6_tnl_locate(&p, cmd == SIOCADDTUNNEL);
+- if (dev != ip6_fb_tnl_dev && cmd == SIOCCHGTUNNEL) {
++ t = ip6_tnl_locate(net, &p, cmd == SIOCADDTUNNEL);
++ if (dev != ip6n->fb_tnl_dev && cmd == SIOCCHGTUNNEL) {
+ if (t != NULL) {
+ if (t->dev != dev) {
+ err = -EEXIST;
+@@ -1230,9 +1249,9 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ } else
+ t = netdev_priv(dev);
+
+- ip6_tnl_unlink(t);
++ ip6_tnl_unlink(ip6n, t);
+ err = ip6_tnl_change(t, &p);
+- ip6_tnl_link(t);
++ ip6_tnl_link(ip6n, t);
+ netdev_state_change(dev);
+ }
+ if (t) {
+@@ -1248,15 +1267,15 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ if (!capable(CAP_NET_ADMIN))
+ break;
+
+- if (dev == ip6_fb_tnl_dev) {
++ if (dev == ip6n->fb_tnl_dev) {
+ err = -EFAULT;
+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p)))
+ break;
+ err = -ENOENT;
+- if ((t = ip6_tnl_locate(&p, 0)) == NULL)
++ if ((t = ip6_tnl_locate(net, &p, 0)) == NULL)
+ break;
+ err = -EPERM;
+- if (t->dev == ip6_fb_tnl_dev)
++ if (t->dev == ip6n->fb_tnl_dev)
+ break;
+ dev = t->dev;
+ }
+@@ -1324,6 +1343,7 @@ static void ip6_tnl_dev_setup(struct net_device *dev)
+ dev->mtu = ETH_DATA_LEN - sizeof (struct ipv6hdr);
+ dev->flags |= IFF_NOARP;
+ dev->addr_len = sizeof(struct in6_addr);
++ dev->features |= NETIF_F_NETNS_LOCAL;
+ }
+
+
+@@ -1365,10 +1385,13 @@ static int
+ ip6_fb_tnl_dev_init(struct net_device *dev)
+ {
+ struct ip6_tnl *t = netdev_priv(dev);
++ struct net *net = dev_net(dev);
++ struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
++
+ ip6_tnl_dev_init_gen(dev);
+ t->parms.proto = IPPROTO_IPV6;
+ dev_hold(dev);
+- tnls_wc[0] = t;
++ ip6n->tnls_wc[0] = t;
+ return 0;
+ }
+
+@@ -1384,6 +1407,78 @@ static struct xfrm6_tunnel ip6ip6_handler = {
+ .priority = 1,
+ };
+
++static void ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n)
++{
++ int h;
++ struct ip6_tnl *t;
++
++ for (h = 0; h < HASH_SIZE; h++) {
++ while ((t = ip6n->tnls_r_l[h]) != NULL)
++ unregister_netdevice(t->dev);
++ }
++
++ t = ip6n->tnls_wc[0];
++ unregister_netdevice(t->dev);
++}
++
++static int ip6_tnl_init_net(struct net *net)
++{
++ int err;
++ struct ip6_tnl_net *ip6n;
++
++ err = -ENOMEM;
++ ip6n = kzalloc(sizeof(struct ip6_tnl_net), GFP_KERNEL);
++ if (ip6n == NULL)
++ goto err_alloc;
++
++ err = net_assign_generic(net, ip6_tnl_net_id, ip6n);
++ if (err < 0)
++ goto err_assign;
++
++ ip6n->tnls[0] = ip6n->tnls_wc;
++ ip6n->tnls[1] = ip6n->tnls_r_l;
++
++ err = -ENOMEM;
++ ip6n->fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0",
++ ip6_tnl_dev_setup);
++
++ if (!ip6n->fb_tnl_dev)
++ goto err_alloc_dev;
++
++ ip6n->fb_tnl_dev->init = ip6_fb_tnl_dev_init;
++ dev_net_set(ip6n->fb_tnl_dev, net);
++
++ err = register_netdev(ip6n->fb_tnl_dev);
++ if (err < 0)
++ goto err_register;
++ return 0;
++
++err_register:
++ free_netdev(ip6n->fb_tnl_dev);
++err_alloc_dev:
++ /* nothing */
++err_assign:
++ kfree(ip6n);
++err_alloc:
++ return err;
++}
++
++static void ip6_tnl_exit_net(struct net *net)
++{
++ struct ip6_tnl_net *ip6n;
++
++ ip6n = net_generic(net, ip6_tnl_net_id);
++ rtnl_lock();
++ ip6_tnl_destroy_tunnels(ip6n);
++ rtnl_unlock();
++ kfree(ip6n);
++}
++
++static struct pernet_operations ip6_tnl_net_ops = {
++ .init = ip6_tnl_init_net,
++ .exit = ip6_tnl_exit_net,
++};
++
+ /**
+ * ip6_tunnel_init - register protocol and reserve needed resources
+ *
+@@ -1405,21 +1500,12 @@ static int __init ip6_tunnel_init(void)
+ err = -EAGAIN;
+ goto unreg_ip4ip6;
+ }
+- ip6_fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0",
+- ip6_tnl_dev_setup);
+
+- if (!ip6_fb_tnl_dev) {
+- err = -ENOMEM;
+- goto fail;
+- }
+- ip6_fb_tnl_dev->init = ip6_fb_tnl_dev_init;
+-
+- if ((err = register_netdev(ip6_fb_tnl_dev))) {
+- free_netdev(ip6_fb_tnl_dev);
+- goto fail;
+- }
++ err = register_pernet_gen_device(&ip6_tnl_net_id, &ip6_tnl_net_ops);
++ if (err < 0)
++ goto err_pernet;
+ return 0;
+-fail:
++err_pernet:
+ xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6);
+ unreg_ip4ip6:
+ xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET);
+@@ -1427,20 +1513,6 @@ out:
+ return err;
+ }
+
+-static void __exit ip6_tnl_destroy_tunnels(void)
+-{
+- int h;
+- struct ip6_tnl *t;
+-
+- for (h = 0; h < HASH_SIZE; h++) {
+- while ((t = tnls_r_l[h]) != NULL)
+- unregister_netdevice(t->dev);
+- }
+-
+- t = tnls_wc[0];
+- unregister_netdevice(t->dev);
+-}
+-
+ /**
+ * ip6_tunnel_cleanup - free resources and unregister protocol
+ **/
+@@ -1453,9 +1525,7 @@ static void __exit ip6_tunnel_cleanup(void)
+ if (xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6))
+ printk(KERN_INFO "ip6_tunnel close: can't deregister ip6ip6\n");
+
+- rtnl_lock();
+- ip6_tnl_destroy_tunnels();
+- rtnl_unlock();
++ unregister_pernet_gen_device(ip6_tnl_net_id, &ip6_tnl_net_ops);
+ }
+
+ module_init(ip6_tunnel_init);
+diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
+new file mode 100644
+index 0000000..c8c6e33
+--- /dev/null
++++ b/net/ipv6/ip6mr.c
+@@ -0,0 +1,1643 @@
++/*
++ * Linux IPv6 multicast routing support for BSD pim6sd
++ * Based on net/ipv4/ipmr.c.
++ *
++ * (c) 2004 Mickael Hoerdt, <hoerdt at clarinet.u-strasbg.fr>
++ * LSIIT Laboratory, Strasbourg, France
++ * (c) 2004 Jean-Philippe Andriot, <jean-philippe.andriot at 6WIND.com>
++ * 6WIND, Paris, France
++ * Copyright (C)2007,2008 USAGI/WIDE Project
++ * YOSHIFUJI Hideaki <yoshfuji at linux-ipv6.org>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ */
++
++#include <asm/system.h>
++#include <asm/uaccess.h>
++#include <linux/types.h>
++#include <linux/sched.h>
++#include <linux/errno.h>
++#include <linux/timer.h>
++#include <linux/mm.h>
++#include <linux/kernel.h>
++#include <linux/fcntl.h>
++#include <linux/stat.h>
++#include <linux/socket.h>
++#include <linux/inet.h>
++#include <linux/netdevice.h>
++#include <linux/inetdevice.h>
++#include <linux/proc_fs.h>
++#include <linux/seq_file.h>
++#include <linux/init.h>
++#include <net/protocol.h>
++#include <linux/skbuff.h>
++#include <net/sock.h>
++#include <net/raw.h>
++#include <linux/notifier.h>
++#include <linux/if_arp.h>
++#include <net/checksum.h>
++#include <net/netlink.h>
++
++#include <net/ipv6.h>
++#include <net/ip6_route.h>
++#include <linux/mroute6.h>
++#include <linux/pim.h>
++#include <net/addrconf.h>
++#include <linux/netfilter_ipv6.h>
++
++struct sock *mroute6_socket;
++
++
++/* Big lock, protecting vif table, mrt cache and mroute socket state.
++ Note that the changes are semaphored via rtnl_lock.
++ */
++
++static DEFINE_RWLOCK(mrt_lock);
++
++/*
++ * Multicast router control variables
++ */
++
++static struct mif_device vif6_table[MAXMIFS]; /* Devices */
++static int maxvif;
++
++#define MIF_EXISTS(idx) (vif6_table[idx].dev != NULL)
++
++static int mroute_do_assert; /* Set in PIM assert */
++#ifdef CONFIG_IPV6_PIMSM_V2
++static int mroute_do_pim;
++#else
++#define mroute_do_pim 0
++#endif
++
++static struct mfc6_cache *mfc6_cache_array[MFC6_LINES]; /* Forwarding cache */
++
++static struct mfc6_cache *mfc_unres_queue; /* Queue of unresolved entries */
++static atomic_t cache_resolve_queue_len; /* Size of unresolved */
++
++/* Special spinlock for queue of unresolved entries */
++static DEFINE_SPINLOCK(mfc_unres_lock);
++
++/* We return to original Alan's scheme. Hash table of resolved
++ entries is changed only in process context and protected
++ with weak lock mrt_lock. Queue of unresolved entries is protected
++ with strong spinlock mfc_unres_lock.
++
++ In this case data path is free of exclusive locks at all.
++ */
++
++static struct kmem_cache *mrt_cachep __read_mostly;
++
++static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache);
++static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert);
++static int ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm);
++
++#ifdef CONFIG_IPV6_PIMSM_V2
++static struct inet6_protocol pim6_protocol;
++#endif
++
++static struct timer_list ipmr_expire_timer;
++
++
++#ifdef CONFIG_PROC_FS
++
++struct ipmr_mfc_iter {
++ struct mfc6_cache **cache;
++ int ct;
++};
++
++
++static struct mfc6_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos)
++{
++ struct mfc6_cache *mfc;
++
++ it->cache = mfc6_cache_array;
++ read_lock(&mrt_lock);
++ for (it->ct = 0; it->ct < ARRAY_SIZE(mfc6_cache_array); it->ct++)
++ for (mfc = mfc6_cache_array[it->ct]; mfc; mfc = mfc->next)
++ if (pos-- == 0)
++ return mfc;
++ read_unlock(&mrt_lock);
++
++ it->cache = &mfc_unres_queue;
++ spin_lock_bh(&mfc_unres_lock);
++ for (mfc = mfc_unres_queue; mfc; mfc = mfc->next)
++ if (pos-- == 0)
++ return mfc;
++ spin_unlock_bh(&mfc_unres_lock);
++
++ it->cache = NULL;
++ return NULL;
++}
++
++
++
++
++/*
++ * The /proc interfaces to multicast routing /proc/ip6_mr_cache /proc/ip6_mr_vif
++ */
++
++struct ipmr_vif_iter {
++ int ct;
++};
++
++static struct mif_device *ip6mr_vif_seq_idx(struct ipmr_vif_iter *iter,
++ loff_t pos)
++{
++ for (iter->ct = 0; iter->ct < maxvif; ++iter->ct) {
++ if (!MIF_EXISTS(iter->ct))
++ continue;
++ if (pos-- == 0)
++ return &vif6_table[iter->ct];
++ }
++ return NULL;
++}
++
++static void *ip6mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
++ __acquires(mrt_lock)
++{
++ read_lock(&mrt_lock);
++ return (*pos ? ip6mr_vif_seq_idx(seq->private, *pos - 1)
++ : SEQ_START_TOKEN);
++}
++
++static void *ip6mr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++ struct ipmr_vif_iter *iter = seq->private;
++
++ ++*pos;
++ if (v == SEQ_START_TOKEN)
++ return ip6mr_vif_seq_idx(iter, 0);
++
++ while (++iter->ct < maxvif) {
++ if (!MIF_EXISTS(iter->ct))
++ continue;
++ return &vif6_table[iter->ct];
++ }
++ return NULL;
++}
++
++static void ip6mr_vif_seq_stop(struct seq_file *seq, void *v)
++ __releases(mrt_lock)
++{
++ read_unlock(&mrt_lock);
++}
++
++static int ip6mr_vif_seq_show(struct seq_file *seq, void *v)
++{
++ if (v == SEQ_START_TOKEN) {
++ seq_puts(seq,
++ "Interface BytesIn PktsIn BytesOut PktsOut Flags\n");
++ } else {
++ const struct mif_device *vif = v;
++ const char *name = vif->dev ? vif->dev->name : "none";
++
++ seq_printf(seq,
++ "%2Zd %-10s %8ld %7ld %8ld %7ld %05X\n",
++ vif - vif6_table,
++ name, vif->bytes_in, vif->pkt_in,
++ vif->bytes_out, vif->pkt_out,
++ vif->flags);
++ }
++ return 0;
++}
++
++static struct seq_operations ip6mr_vif_seq_ops = {
++ .start = ip6mr_vif_seq_start,
++ .next = ip6mr_vif_seq_next,
++ .stop = ip6mr_vif_seq_stop,
++ .show = ip6mr_vif_seq_show,
++};
++
++static int ip6mr_vif_open(struct inode *inode, struct file *file)
++{
++ return seq_open_private(file, &ip6mr_vif_seq_ops,
++ sizeof(struct ipmr_vif_iter));
++}
++
++static struct file_operations ip6mr_vif_fops = {
++ .owner = THIS_MODULE,
++ .open = ip6mr_vif_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = seq_release,
++};
++
++static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos)
++{
++ return (*pos ? ipmr_mfc_seq_idx(seq->private, *pos - 1)
++ : SEQ_START_TOKEN);
++}
++
++static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++ struct mfc6_cache *mfc = v;
++ struct ipmr_mfc_iter *it = seq->private;
++
++ ++*pos;
++
++ if (v == SEQ_START_TOKEN)
++ return ipmr_mfc_seq_idx(seq->private, 0);
++
++ if (mfc->next)
++ return mfc->next;
++
++ if (it->cache == &mfc_unres_queue)
++ goto end_of_list;
++
++ BUG_ON(it->cache != mfc6_cache_array);
++
++ while (++it->ct < ARRAY_SIZE(mfc6_cache_array)) {
++ mfc = mfc6_cache_array[it->ct];
++ if (mfc)
++ return mfc;
++ }
++
++ /* exhausted cache_array, show unresolved */
++ read_unlock(&mrt_lock);
++ it->cache = &mfc_unres_queue;
++ it->ct = 0;
++
++ spin_lock_bh(&mfc_unres_lock);
++ mfc = mfc_unres_queue;
++ if (mfc)
++ return mfc;
++
++ end_of_list:
++ spin_unlock_bh(&mfc_unres_lock);
++ it->cache = NULL;
++
++ return NULL;
++}
++
++static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v)
++{
++ struct ipmr_mfc_iter *it = seq->private;
++
++ if (it->cache == &mfc_unres_queue)
++ spin_unlock_bh(&mfc_unres_lock);
++ else if (it->cache == mfc6_cache_array)
++ read_unlock(&mrt_lock);
++}
++
++static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
++{
++ int n;
++
++ if (v == SEQ_START_TOKEN) {
++ seq_puts(seq,
++ "Group "
++ "Origin "
++ "Iif Pkts Bytes Wrong Oifs\n");
++ } else {
++ const struct mfc6_cache *mfc = v;
++ const struct ipmr_mfc_iter *it = seq->private;
++
++ seq_printf(seq,
++ NIP6_FMT " " NIP6_FMT " %-3d %8ld %8ld %8ld",
++ NIP6(mfc->mf6c_mcastgrp), NIP6(mfc->mf6c_origin),
++ mfc->mf6c_parent,
++ mfc->mfc_un.res.pkt,
++ mfc->mfc_un.res.bytes,
++ mfc->mfc_un.res.wrong_if);
++
++ if (it->cache != &mfc_unres_queue) {
++ for (n = mfc->mfc_un.res.minvif;
++ n < mfc->mfc_un.res.maxvif; n++) {
++ if (MIF_EXISTS(n) &&
++ mfc->mfc_un.res.ttls[n] < 255)
++ seq_printf(seq,
++ " %2d:%-3d",
++ n, mfc->mfc_un.res.ttls[n]);
++ }
++ }
++ seq_putc(seq, '\n');
++ }
++ return 0;
++}
++
++static struct seq_operations ipmr_mfc_seq_ops = {
++ .start = ipmr_mfc_seq_start,
++ .next = ipmr_mfc_seq_next,
++ .stop = ipmr_mfc_seq_stop,
++ .show = ipmr_mfc_seq_show,
++};
++
++static int ipmr_mfc_open(struct inode *inode, struct file *file)
++{
++ return seq_open_private(file, &ipmr_mfc_seq_ops,
++ sizeof(struct ipmr_mfc_iter));
++}
++
++static struct file_operations ip6mr_mfc_fops = {
++ .owner = THIS_MODULE,
++ .open = ipmr_mfc_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = seq_release,
++};
++#endif
++
++#ifdef CONFIG_IPV6_PIMSM_V2
++static int reg_vif_num = -1;
++
++static int pim6_rcv(struct sk_buff *skb)
++{
++ struct pimreghdr *pim;
++ struct ipv6hdr *encap;
++ struct net_device *reg_dev = NULL;
++
++ if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap)))
++ goto drop;
++
++ pim = (struct pimreghdr *)skb_transport_header(skb);
++ if (pim->type != ((PIM_VERSION << 4) | PIM_REGISTER) ||
++ (pim->flags & PIM_NULL_REGISTER) ||
++ (ip_compute_csum((void *)pim, sizeof(*pim)) != 0 &&
++ (u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))))
++ goto drop;
++
++ /* check if the inner packet is destined to mcast group */
++ encap = (struct ipv6hdr *)(skb_transport_header(skb) +
++ sizeof(*pim));
++
++ if (!ipv6_addr_is_multicast(&encap->daddr) ||
++ encap->payload_len == 0 ||
++ ntohs(encap->payload_len) + sizeof(*pim) > skb->len)
++ goto drop;
++
++ read_lock(&mrt_lock);
++ if (reg_vif_num >= 0)
++ reg_dev = vif6_table[reg_vif_num].dev;
++ if (reg_dev)
++ dev_hold(reg_dev);
++ read_unlock(&mrt_lock);
++
++ if (reg_dev == NULL)
++ goto drop;
++
++ skb->mac_header = skb->network_header;
++ skb_pull(skb, (u8 *)encap - skb->data);
++ skb_reset_network_header(skb);
++ skb->dev = reg_dev;
++ skb->protocol = htons(ETH_P_IP);
++ skb->ip_summed = 0;
++ skb->pkt_type = PACKET_HOST;
++ dst_release(skb->dst);
++ ((struct net_device_stats *)netdev_priv(reg_dev))->rx_bytes += skb->len;
++ ((struct net_device_stats *)netdev_priv(reg_dev))->rx_packets++;
++ skb->dst = NULL;
++ nf_reset(skb);
++ netif_rx(skb);
++ dev_put(reg_dev);
++ return 0;
++ drop:
++ kfree_skb(skb);
++ return 0;
++}
++
++static struct inet6_protocol pim6_protocol = {
++ .handler = pim6_rcv,
++};
++
++/* Service routines creating virtual interfaces: PIMREG */
++
++static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++ read_lock(&mrt_lock);
++ ((struct net_device_stats *)netdev_priv(dev))->tx_bytes += skb->len;
++ ((struct net_device_stats *)netdev_priv(dev))->tx_packets++;
++ ip6mr_cache_report(skb, reg_vif_num, MRT6MSG_WHOLEPKT);
++ read_unlock(&mrt_lock);
++ kfree_skb(skb);
++ return 0;
++}
++
++static struct net_device_stats *reg_vif_get_stats(struct net_device *dev)
++{
++ return (struct net_device_stats *)netdev_priv(dev);
++}
++
++static void reg_vif_setup(struct net_device *dev)
++{
++ dev->type = ARPHRD_PIMREG;
++ dev->mtu = 1500 - sizeof(struct ipv6hdr) - 8;
++ dev->flags = IFF_NOARP;
++ dev->hard_start_xmit = reg_vif_xmit;
++ dev->get_stats = reg_vif_get_stats;
++ dev->destructor = free_netdev;
++}
++
++static struct net_device *ip6mr_reg_vif(void)
++{
++ struct net_device *dev;
++
++ dev = alloc_netdev(sizeof(struct net_device_stats), "pim6reg",
++ reg_vif_setup);
++
++ if (dev == NULL)
++ return NULL;
++
++ if (register_netdevice(dev)) {
++ free_netdev(dev);
++ return NULL;
++ }
++ dev->iflink = 0;
++
++ if (dev_open(dev))
++ goto failure;
++
++ return dev;
++
++failure:
++ /* allow the register to be completed before unregistering. */
++ rtnl_unlock();
++ rtnl_lock();
++
++ unregister_netdevice(dev);
++ return NULL;
++}
++#endif
++
++/*
++ * Delete a VIF entry
++ */
++
++static int mif6_delete(int vifi)
++{
++ struct mif_device *v;
++ struct net_device *dev;
++ if (vifi < 0 || vifi >= maxvif)
++ return -EADDRNOTAVAIL;
++
++ v = &vif6_table[vifi];
++
++ write_lock_bh(&mrt_lock);
++ dev = v->dev;
++ v->dev = NULL;
++
++ if (!dev) {
++ write_unlock_bh(&mrt_lock);
++ return -EADDRNOTAVAIL;
++ }
++
++#ifdef CONFIG_IPV6_PIMSM_V2
++ if (vifi == reg_vif_num)
++ reg_vif_num = -1;
++#endif
++
++ if (vifi + 1 == maxvif) {
++ int tmp;
++ for (tmp = vifi - 1; tmp >= 0; tmp--) {
++ if (MIF_EXISTS(tmp))
++ break;
++ }
++ maxvif = tmp + 1;
++ }
++
++ write_unlock_bh(&mrt_lock);
++
++ dev_set_allmulti(dev, -1);
++
++ if (v->flags & MIFF_REGISTER)
++ unregister_netdevice(dev);
++
++ dev_put(dev);
++ return 0;
++}
++
++/* Destroy an unresolved cache entry, killing queued skbs
++ and reporting error to netlink readers.
++ */
++
++static void ip6mr_destroy_unres(struct mfc6_cache *c)
++{
++ struct sk_buff *skb;
++
++ atomic_dec(&cache_resolve_queue_len);
++
++ while((skb = skb_dequeue(&c->mfc_un.unres.unresolved)) != NULL) {
++ if (ipv6_hdr(skb)->version == 0) {
++ struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr));
++ nlh->nlmsg_type = NLMSG_ERROR;
++ nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr));
++ skb_trim(skb, nlh->nlmsg_len);
++ ((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -ETIMEDOUT;
++ rtnl_unicast(skb, &init_net, NETLINK_CB(skb).pid);
++ } else
++ kfree_skb(skb);
++ }
++
++ kmem_cache_free(mrt_cachep, c);
++}
++
++
++/* Single timer process for all the unresolved queue. */
++
++static void ipmr_do_expire_process(unsigned long dummy)
++{
++ unsigned long now = jiffies;
++ unsigned long expires = 10 * HZ;
++ struct mfc6_cache *c, **cp;
++
++ cp = &mfc_unres_queue;
++
++ while ((c = *cp) != NULL) {
++ if (time_after(c->mfc_un.unres.expires, now)) {
++ /* not yet... */
++ unsigned long interval = c->mfc_un.unres.expires - now;
++ if (interval < expires)
++ expires = interval;
++ cp = &c->next;
++ continue;
++ }
++
++ *cp = c->next;
++ ip6mr_destroy_unres(c);
++ }
++
++ if (atomic_read(&cache_resolve_queue_len))
++ mod_timer(&ipmr_expire_timer, jiffies + expires);
++}
++
++static void ipmr_expire_process(unsigned long dummy)
++{
++ if (!spin_trylock(&mfc_unres_lock)) {
++ mod_timer(&ipmr_expire_timer, jiffies + 1);
++ return;
++ }
++
++ if (atomic_read(&cache_resolve_queue_len))
++ ipmr_do_expire_process(dummy);
++
++ spin_unlock(&mfc_unres_lock);
++}
++
++/* Fill oifs list. It is called under write locked mrt_lock. */
++
++static void ip6mr_update_thresholds(struct mfc6_cache *cache, unsigned char *ttls)
++{
++ int vifi;
++
++ cache->mfc_un.res.minvif = MAXMIFS;
++ cache->mfc_un.res.maxvif = 0;
++ memset(cache->mfc_un.res.ttls, 255, MAXMIFS);
++
++ for (vifi = 0; vifi < maxvif; vifi++) {
++ if (MIF_EXISTS(vifi) && ttls[vifi] && ttls[vifi] < 255) {
++ cache->mfc_un.res.ttls[vifi] = ttls[vifi];
++ if (cache->mfc_un.res.minvif > vifi)
++ cache->mfc_un.res.minvif = vifi;
++ if (cache->mfc_un.res.maxvif <= vifi)
++ cache->mfc_un.res.maxvif = vifi + 1;
++ }
++ }
++}
++
++static int mif6_add(struct mif6ctl *vifc, int mrtsock)
++{
++ int vifi = vifc->mif6c_mifi;
++ struct mif_device *v = &vif6_table[vifi];
++ struct net_device *dev;
++
++ /* Is vif busy ? */
++ if (MIF_EXISTS(vifi))
++ return -EADDRINUSE;
++
++ switch (vifc->mif6c_flags) {
++#ifdef CONFIG_IPV6_PIMSM_V2
++ case MIFF_REGISTER:
++ /*
++ * Special Purpose VIF in PIM
++ * All the packets will be sent to the daemon
++ */
++ if (reg_vif_num >= 0)
++ return -EADDRINUSE;
++ dev = ip6mr_reg_vif();
++ if (!dev)
++ return -ENOBUFS;
++ break;
++#endif
++ case 0:
++ dev = dev_get_by_index(&init_net, vifc->mif6c_pifi);
++ if (!dev)
++ return -EADDRNOTAVAIL;
++ dev_put(dev);
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ dev_set_allmulti(dev, 1);
++
++ /*
++ * Fill in the VIF structures
++ */
++ v->rate_limit = vifc->vifc_rate_limit;
++ v->flags = vifc->mif6c_flags;
++ if (!mrtsock)
++ v->flags |= VIFF_STATIC;
++ v->threshold = vifc->vifc_threshold;
++ v->bytes_in = 0;
++ v->bytes_out = 0;
++ v->pkt_in = 0;
++ v->pkt_out = 0;
++ v->link = dev->ifindex;
++ if (v->flags & MIFF_REGISTER)
++ v->link = dev->iflink;
++
++ /* And finish update writing critical data */
++ write_lock_bh(&mrt_lock);
++ dev_hold(dev);
++ v->dev = dev;
++#ifdef CONFIG_IPV6_PIMSM_V2
++ if (v->flags & MIFF_REGISTER)
++ reg_vif_num = vifi;
++#endif
++ if (vifi + 1 > maxvif)
++ maxvif = vifi + 1;
++ write_unlock_bh(&mrt_lock);
++ return 0;
++}
++
++static struct mfc6_cache *ip6mr_cache_find(struct in6_addr *origin, struct in6_addr *mcastgrp)
++{
++ int line = MFC6_HASH(mcastgrp, origin);
++ struct mfc6_cache *c;
++
++ for (c = mfc6_cache_array[line]; c; c = c->next) {
++ if (ipv6_addr_equal(&c->mf6c_origin, origin) &&
++ ipv6_addr_equal(&c->mf6c_mcastgrp, mcastgrp))
++ break;
++ }
++ return c;
++}
++
++/*
++ * Allocate a multicast cache entry
++ */
++static struct mfc6_cache *ip6mr_cache_alloc(void)
++{
++ struct mfc6_cache *c = kmem_cache_alloc(mrt_cachep, GFP_KERNEL);
++ if (c == NULL)
++ return NULL;
++ memset(c, 0, sizeof(*c));
++ c->mfc_un.res.minvif = MAXMIFS;
++ return c;
++}
++
++static struct mfc6_cache *ip6mr_cache_alloc_unres(void)
++{
++ struct mfc6_cache *c = kmem_cache_alloc(mrt_cachep, GFP_ATOMIC);
++ if (c == NULL)
++ return NULL;
++ memset(c, 0, sizeof(*c));
++ skb_queue_head_init(&c->mfc_un.unres.unresolved);
++ c->mfc_un.unres.expires = jiffies + 10 * HZ;
++ return c;
++}
++
++/*
++ * A cache entry has gone into a resolved state from queued
++ */
++
++static void ip6mr_cache_resolve(struct mfc6_cache *uc, struct mfc6_cache *c)
++{
++ struct sk_buff *skb;
++
++ /*
++ * Play the pending entries through our router
++ */
++
++ while((skb = __skb_dequeue(&uc->mfc_un.unres.unresolved))) {
++ if (ipv6_hdr(skb)->version == 0) {
++ int err;
++ struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr));
++
++ if (ip6mr_fill_mroute(skb, c, NLMSG_DATA(nlh)) > 0) {
++ nlh->nlmsg_len = skb_tail_pointer(skb) - (u8 *)nlh;
++ } else {
++ nlh->nlmsg_type = NLMSG_ERROR;
++ nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr));
++ skb_trim(skb, nlh->nlmsg_len);
++ ((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -EMSGSIZE;
++ }
++ err = rtnl_unicast(skb, &init_net, NETLINK_CB(skb).pid);
++ } else
++ ip6_mr_forward(skb, c);
++ }
++}
++
++/*
++ * Bounce a cache query up to pim6sd. We could use netlink for this but pim6sd
++ * expects the following bizarre scheme.
++ *
++ * Called under mrt_lock.
++ */
++
++static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert)
++{
++ struct sk_buff *skb;
++ struct mrt6msg *msg;
++ int ret;
++
++#ifdef CONFIG_IPV6_PIMSM_V2
++ if (assert == MRT6MSG_WHOLEPKT)
++ skb = skb_realloc_headroom(pkt, -skb_network_offset(pkt)
++ +sizeof(*msg));
++ else
++#endif
++ skb = alloc_skb(sizeof(struct ipv6hdr) + sizeof(*msg), GFP_ATOMIC);
++
++ if (!skb)
++ return -ENOBUFS;
++
++ /* I suppose that internal messages
++ * do not require checksums */
++
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++
++#ifdef CONFIG_IPV6_PIMSM_V2
++ if (assert == MRT6MSG_WHOLEPKT) {
++ /* Ugly, but we have no choice with this interface.
++ Duplicate old header, fix length etc.
++ And all this only to mangle msg->im6_msgtype and
++ to set msg->im6_mbz to "mbz" :-)
++ */
++ skb_push(skb, -skb_network_offset(pkt));
++
++ skb_push(skb, sizeof(*msg));
++ skb_reset_transport_header(skb);
++ msg = (struct mrt6msg *)skb_transport_header(skb);
++ msg->im6_mbz = 0;
++ msg->im6_msgtype = MRT6MSG_WHOLEPKT;
++ msg->im6_mif = reg_vif_num;
++ msg->im6_pad = 0;
++ ipv6_addr_copy(&msg->im6_src, &ipv6_hdr(pkt)->saddr);
++ ipv6_addr_copy(&msg->im6_dst, &ipv6_hdr(pkt)->daddr);
++
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++ } else
++#endif
++ {
++ /*
++ * Copy the IP header
++ */
++
++ skb_put(skb, sizeof(struct ipv6hdr));
++ skb_reset_network_header(skb);
++ skb_copy_to_linear_data(skb, ipv6_hdr(pkt), sizeof(struct ipv6hdr));
++
++ /*
++ * Add our header
++ */
++ skb_put(skb, sizeof(*msg));
++ skb_reset_transport_header(skb);
++ msg = (struct mrt6msg *)skb_transport_header(skb);
++
++ msg->im6_mbz = 0;
++ msg->im6_msgtype = assert;
++ msg->im6_mif = mifi;
++ msg->im6_pad = 0;
++ ipv6_addr_copy(&msg->im6_src, &ipv6_hdr(pkt)->saddr);
++ ipv6_addr_copy(&msg->im6_dst, &ipv6_hdr(pkt)->daddr);
++
++ skb->dst = dst_clone(pkt->dst);
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++
++ skb_pull(skb, sizeof(struct ipv6hdr));
++ }
++
++ if (mroute6_socket == NULL) {
++ kfree_skb(skb);
++ return -EINVAL;
++ }
++
++ /*
++ * Deliver to user space multicast routing algorithms
++ */
++ if ((ret = sock_queue_rcv_skb(mroute6_socket, skb)) < 0) {
++ if (net_ratelimit())
++ printk(KERN_WARNING "mroute6: pending queue full, dropping entries.\n");
++ kfree_skb(skb);
++ }
++
++ return ret;
++}
++
++/*
++ * Queue a packet for resolution. It gets locked cache entry!
++ */
++
++static int
++ip6mr_cache_unresolved(mifi_t mifi, struct sk_buff *skb)
++{
++ int err;
++ struct mfc6_cache *c;
++
++ spin_lock_bh(&mfc_unres_lock);
++ for (c = mfc_unres_queue; c; c = c->next) {
++ if (ipv6_addr_equal(&c->mf6c_mcastgrp, &ipv6_hdr(skb)->daddr) &&
++ ipv6_addr_equal(&c->mf6c_origin, &ipv6_hdr(skb)->saddr))
++ break;
++ }
++
++ if (c == NULL) {
++ /*
++ * Create a new entry if allowable
++ */
++
++ if (atomic_read(&cache_resolve_queue_len) >= 10 ||
++ (c = ip6mr_cache_alloc_unres()) == NULL) {
++ spin_unlock_bh(&mfc_unres_lock);
++
++ kfree_skb(skb);
++ return -ENOBUFS;
++ }
++
++ /*
++ * Fill in the new cache entry
++ */
++ c->mf6c_parent = -1;
++ c->mf6c_origin = ipv6_hdr(skb)->saddr;
++ c->mf6c_mcastgrp = ipv6_hdr(skb)->daddr;
++
++ /*
++ * Reflect first query at pim6sd
++ */
++ if ((err = ip6mr_cache_report(skb, mifi, MRT6MSG_NOCACHE)) < 0) {
++ /* If the report failed throw the cache entry
++ out - Brad Parker
++ */
++ spin_unlock_bh(&mfc_unres_lock);
++
++ kmem_cache_free(mrt_cachep, c);
++ kfree_skb(skb);
++ return err;
++ }
++
++ atomic_inc(&cache_resolve_queue_len);
++ c->next = mfc_unres_queue;
++ mfc_unres_queue = c;
++
++ ipmr_do_expire_process(1);
++ }
++
++ /*
++ * See if we can append the packet
++ */
++ if (c->mfc_un.unres.unresolved.qlen > 3) {
++ kfree_skb(skb);
++ err = -ENOBUFS;
++ } else {
++ skb_queue_tail(&c->mfc_un.unres.unresolved, skb);
++ err = 0;
++ }
++
++ spin_unlock_bh(&mfc_unres_lock);
++ return err;
++}
++
++/*
++ * MFC6 cache manipulation by user space
++ */
++
++static int ip6mr_mfc_delete(struct mf6cctl *mfc)
++{
++ int line;
++ struct mfc6_cache *c, **cp;
++
++ line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr);
++
++ for (cp = &mfc6_cache_array[line]; (c = *cp) != NULL; cp = &c->next) {
++ if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) &&
++ ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) {
++ write_lock_bh(&mrt_lock);
++ *cp = c->next;
++ write_unlock_bh(&mrt_lock);
++
++ kmem_cache_free(mrt_cachep, c);
++ return 0;
++ }
++ }
++ return -ENOENT;
++}
++
++static int ip6mr_device_event(struct notifier_block *this,
++ unsigned long event, void *ptr)
++{
++ struct net_device *dev = ptr;
++ struct mif_device *v;
++ int ct;
++
++ if (dev_net(dev) != &init_net)
++ return NOTIFY_DONE;
++
++ if (event != NETDEV_UNREGISTER)
++ return NOTIFY_DONE;
++
++ v = &vif6_table[0];
++ for (ct = 0; ct < maxvif; ct++, v++) {
++ if (v->dev == dev)
++ mif6_delete(ct);
++ }
++ return NOTIFY_DONE;
++}
++
++static struct notifier_block ip6_mr_notifier = {
++ .notifier_call = ip6mr_device_event
++};
++
++/*
++ * Setup for IP multicast routing
++ */
++
++void __init ip6_mr_init(void)
++{
++ mrt_cachep = kmem_cache_create("ip6_mrt_cache",
++ sizeof(struct mfc6_cache),
++ 0, SLAB_HWCACHE_ALIGN,
++ NULL);
++ if (!mrt_cachep)
++ panic("cannot allocate ip6_mrt_cache");
++
++ setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0);
++ register_netdevice_notifier(&ip6_mr_notifier);
++#ifdef CONFIG_PROC_FS
++ proc_net_fops_create(&init_net, "ip6_mr_vif", 0, &ip6mr_vif_fops);
++ proc_net_fops_create(&init_net, "ip6_mr_cache", 0, &ip6mr_mfc_fops);
++#endif
++}
++
++
++static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock)
++{
++ int line;
++ struct mfc6_cache *uc, *c, **cp;
++ unsigned char ttls[MAXMIFS];
++ int i;
++
++ memset(ttls, 255, MAXMIFS);
++ for (i = 0; i < MAXMIFS; i++) {
++ if (IF_ISSET(i, &mfc->mf6cc_ifset))
++ ttls[i] = 1;
++
++ }
++
++ line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr);
++
++ for (cp = &mfc6_cache_array[line]; (c = *cp) != NULL; cp = &c->next) {
++ if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) &&
++ ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr))
++ break;
++ }
++
++ if (c != NULL) {
++ write_lock_bh(&mrt_lock);
++ c->mf6c_parent = mfc->mf6cc_parent;
++ ip6mr_update_thresholds(c, ttls);
++ if (!mrtsock)
++ c->mfc_flags |= MFC_STATIC;
++ write_unlock_bh(&mrt_lock);
++ return 0;
++ }
++
++ if (!ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr))
++ return -EINVAL;
++
++ c = ip6mr_cache_alloc();
++ if (c == NULL)
++ return -ENOMEM;
++
++ c->mf6c_origin = mfc->mf6cc_origin.sin6_addr;
++ c->mf6c_mcastgrp = mfc->mf6cc_mcastgrp.sin6_addr;
++ c->mf6c_parent = mfc->mf6cc_parent;
++ ip6mr_update_thresholds(c, ttls);
++ if (!mrtsock)
++ c->mfc_flags |= MFC_STATIC;
++
++ write_lock_bh(&mrt_lock);
++ c->next = mfc6_cache_array[line];
++ mfc6_cache_array[line] = c;
++ write_unlock_bh(&mrt_lock);
++
++ /*
++ * Check to see if we resolved a queued list. If so we
++ * need to send on the frames and tidy up.
++ */
++ spin_lock_bh(&mfc_unres_lock);
++ for (cp = &mfc_unres_queue; (uc = *cp) != NULL;
++ cp = &uc->next) {
++ if (ipv6_addr_equal(&uc->mf6c_origin, &c->mf6c_origin) &&
++ ipv6_addr_equal(&uc->mf6c_mcastgrp, &c->mf6c_mcastgrp)) {
++ *cp = uc->next;
++ if (atomic_dec_and_test(&cache_resolve_queue_len))
++ del_timer(&ipmr_expire_timer);
++ break;
++ }
++ }
++ spin_unlock_bh(&mfc_unres_lock);
++
++ if (uc) {
++ ip6mr_cache_resolve(uc, c);
++ kmem_cache_free(mrt_cachep, uc);
++ }
++ return 0;
++}
++
++/*
++ * Close the multicast socket, and clear the vif tables etc
++ */
++
++static void mroute_clean_tables(struct sock *sk)
++{
++ int i;
++
++ /*
++ * Shut down all active vif entries
++ */
++ for (i = 0; i < maxvif; i++) {
++ if (!(vif6_table[i].flags & VIFF_STATIC))
++ mif6_delete(i);
++ }
++
++ /*
++ * Wipe the cache
++ */
++ for (i = 0; i < ARRAY_SIZE(mfc6_cache_array); i++) {
++ struct mfc6_cache *c, **cp;
++
++ cp = &mfc6_cache_array[i];
++ while ((c = *cp) != NULL) {
++ if (c->mfc_flags & MFC_STATIC) {
++ cp = &c->next;
++ continue;
++ }
++ write_lock_bh(&mrt_lock);
++ *cp = c->next;
++ write_unlock_bh(&mrt_lock);
++
++ kmem_cache_free(mrt_cachep, c);
++ }
++ }
++
++ if (atomic_read(&cache_resolve_queue_len) != 0) {
++ struct mfc6_cache *c;
++
++ spin_lock_bh(&mfc_unres_lock);
++ while (mfc_unres_queue != NULL) {
++ c = mfc_unres_queue;
++ mfc_unres_queue = c->next;
++ spin_unlock_bh(&mfc_unres_lock);
++
++ ip6mr_destroy_unres(c);
++
++ spin_lock_bh(&mfc_unres_lock);
++ }
++ spin_unlock_bh(&mfc_unres_lock);
++ }
++}
++
++static int ip6mr_sk_init(struct sock *sk)
++{
++ int err = 0;
++
++ rtnl_lock();
++ write_lock_bh(&mrt_lock);
++ if (likely(mroute6_socket == NULL))
++ mroute6_socket = sk;
++ else
++ err = -EADDRINUSE;
++ write_unlock_bh(&mrt_lock);
++
++ rtnl_unlock();
++
++ return err;
++}
++
++int ip6mr_sk_done(struct sock *sk)
++{
++ int err = 0;
++
++ rtnl_lock();
++ if (sk == mroute6_socket) {
++ write_lock_bh(&mrt_lock);
++ mroute6_socket = NULL;
++ write_unlock_bh(&mrt_lock);
++
++ mroute_clean_tables(sk);
++ } else
++ err = -EACCES;
++ rtnl_unlock();
++
++ return err;
++}
++
++/*
++ * Socket options and virtual interface manipulation. The whole
++ * virtual interface system is a complete heap, but unfortunately
++ * that's how BSD mrouted happens to think. Maybe one day with a proper
++ * MOSPF/PIM router set up we can clean this up.
++ */
++
++int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int optlen)
++{
++ int ret;
++ struct mif6ctl vif;
++ struct mf6cctl mfc;
++ mifi_t mifi;
++
++ if (optname != MRT6_INIT) {
++ if (sk != mroute6_socket && !capable(CAP_NET_ADMIN))
++ return -EACCES;
++ }
++
++ switch (optname) {
++ case MRT6_INIT:
++ if (sk->sk_type != SOCK_RAW ||
++ inet_sk(sk)->num != IPPROTO_ICMPV6)
++ return -EOPNOTSUPP;
++ if (optlen < sizeof(int))
++ return -EINVAL;
++
++ return ip6mr_sk_init(sk);
++
++ case MRT6_DONE:
++ return ip6mr_sk_done(sk);
++
++ case MRT6_ADD_MIF:
++ if (optlen < sizeof(vif))
++ return -EINVAL;
++ if (copy_from_user(&vif, optval, sizeof(vif)))
++ return -EFAULT;
++ if (vif.mif6c_mifi >= MAXMIFS)
++ return -ENFILE;
++ rtnl_lock();
++ ret = mif6_add(&vif, sk == mroute6_socket);
++ rtnl_unlock();
++ return ret;
++
++ case MRT6_DEL_MIF:
++ if (optlen < sizeof(mifi_t))
++ return -EINVAL;
++ if (copy_from_user(&mifi, optval, sizeof(mifi_t)))
++ return -EFAULT;
++ rtnl_lock();
++ ret = mif6_delete(mifi);
++ rtnl_unlock();
++ return ret;
++
++ /*
++ * Manipulate the forwarding caches. These live
++ * in a sort of kernel/user symbiosis.
++ */
++ case MRT6_ADD_MFC:
++ case MRT6_DEL_MFC:
++ if (optlen < sizeof(mfc))
++ return -EINVAL;
++ if (copy_from_user(&mfc, optval, sizeof(mfc)))
++ return -EFAULT;
++ rtnl_lock();
++ if (optname == MRT6_DEL_MFC)
++ ret = ip6mr_mfc_delete(&mfc);
++ else
++ ret = ip6mr_mfc_add(&mfc, sk == mroute6_socket);
++ rtnl_unlock();
++ return ret;
++
++ /*
++ * Control PIM assert (to activate pim will activate assert)
++ */
++ case MRT6_ASSERT:
++ {
++ int v;
++ if (get_user(v, (int __user *)optval))
++ return -EFAULT;
++ mroute_do_assert = !!v;
++ return 0;
++ }
++
++#ifdef CONFIG_IPV6_PIMSM_V2
++ case MRT6_PIM:
++ {
++ int v;
++ if (get_user(v, (int __user *)optval))
++ return -EFAULT;
++ v = !!v;
++ rtnl_lock();
++ ret = 0;
++ if (v != mroute_do_pim) {
++ mroute_do_pim = v;
++ mroute_do_assert = v;
++ if (mroute_do_pim)
++ ret = inet6_add_protocol(&pim6_protocol,
++ IPPROTO_PIM);
++ else
++ ret = inet6_del_protocol(&pim6_protocol,
++ IPPROTO_PIM);
++ if (ret < 0)
++ ret = -EAGAIN;
++ }
++ rtnl_unlock();
++ return ret;
++ }
++
++#endif
++ /*
++ * Spurious command, or MRT_VERSION which you cannot
++ * set.
++ */
++ default:
++ return -ENOPROTOOPT;
++ }
++}
++
++/*
++ * Getsock opt support for the multicast routing system.
++ */
++
++int ip6_mroute_getsockopt(struct sock *sk, int optname, char __user *optval,
++ int __user *optlen)
++{
++ int olr;
++ int val;
++
++ switch (optname) {
++ case MRT6_VERSION:
++ val = 0x0305;
++ break;
++#ifdef CONFIG_IPV6_PIMSM_V2
++ case MRT6_PIM:
++ val = mroute_do_pim;
++ break;
++#endif
++ case MRT6_ASSERT:
++ val = mroute_do_assert;
++ break;
++ default:
++ return -ENOPROTOOPT;
++ }
++
++ if (get_user(olr, optlen))
++ return -EFAULT;
++
++ olr = min_t(int, olr, sizeof(int));
++ if (olr < 0)
++ return -EINVAL;
++
++ if (put_user(olr, optlen))
++ return -EFAULT;
++ if (copy_to_user(optval, &val, olr))
++ return -EFAULT;
++ return 0;
++}
++
++/*
++ * The IP multicast ioctl support routines.
++ */
++
++int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
++{
++ struct sioc_sg_req6 sr;
++ struct sioc_mif_req6 vr;
++ struct mif_device *vif;
++ struct mfc6_cache *c;
++
++ switch (cmd) {
++ case SIOCGETMIFCNT_IN6:
++ if (copy_from_user(&vr, arg, sizeof(vr)))
++ return -EFAULT;
++ if (vr.mifi >= maxvif)
++ return -EINVAL;
++ read_lock(&mrt_lock);
++ vif = &vif6_table[vr.mifi];
++ if (MIF_EXISTS(vr.mifi)) {
++ vr.icount = vif->pkt_in;
++ vr.ocount = vif->pkt_out;
++ vr.ibytes = vif->bytes_in;
++ vr.obytes = vif->bytes_out;
++ read_unlock(&mrt_lock);
++
++ if (copy_to_user(arg, &vr, sizeof(vr)))
++ return -EFAULT;
++ return 0;
++ }
++ read_unlock(&mrt_lock);
++ return -EADDRNOTAVAIL;
++ case SIOCGETSGCNT_IN6:
++ if (copy_from_user(&sr, arg, sizeof(sr)))
++ return -EFAULT;
++
++ read_lock(&mrt_lock);
++ c = ip6mr_cache_find(&sr.src.sin6_addr, &sr.grp.sin6_addr);
++ if (c) {
++ sr.pktcnt = c->mfc_un.res.pkt;
++ sr.bytecnt = c->mfc_un.res.bytes;
++ sr.wrong_if = c->mfc_un.res.wrong_if;
++ read_unlock(&mrt_lock);
++
++ if (copy_to_user(arg, &sr, sizeof(sr)))
++ return -EFAULT;
++ return 0;
++ }
++ read_unlock(&mrt_lock);
++ return -EADDRNOTAVAIL;
++ default:
++ return -ENOIOCTLCMD;
++ }
++}
++
++
++static inline int ip6mr_forward2_finish(struct sk_buff *skb)
++{
++ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_OUTFORWDATAGRAMS);
++ return dst_output(skb);
++}
++
++/*
++ * Processing handlers for ip6mr_forward
++ */
++
++static int ip6mr_forward2(struct sk_buff *skb, struct mfc6_cache *c, int vifi)
++{
++ struct ipv6hdr *ipv6h;
++ struct mif_device *vif = &vif6_table[vifi];
++ struct net_device *dev;
++ struct dst_entry *dst;
++ struct flowi fl;
++
++ if (vif->dev == NULL)
++ goto out_free;
++
++#ifdef CONFIG_IPV6_PIMSM_V2
++ if (vif->flags & MIFF_REGISTER) {
++ vif->pkt_out++;
++ vif->bytes_out += skb->len;
++ ((struct net_device_stats *)netdev_priv(vif->dev))->tx_bytes += skb->len;
++ ((struct net_device_stats *)netdev_priv(vif->dev))->tx_packets++;
++ ip6mr_cache_report(skb, vifi, MRT6MSG_WHOLEPKT);
++ kfree_skb(skb);
++ return 0;
++ }
++#endif
++
++ ipv6h = ipv6_hdr(skb);
++
++ fl = (struct flowi) {
++ .oif = vif->link,
++ .nl_u = { .ip6_u =
++ { .daddr = ipv6h->daddr, }
++ }
++ };
++
++ dst = ip6_route_output(&init_net, NULL, &fl);
++ if (!dst)
++ goto out_free;
++
++ dst_release(skb->dst);
++ skb->dst = dst;
++
++ /*
++ * RFC1584 teaches, that DVMRP/PIM router must deliver packets locally
++ * not only before forwarding, but after forwarding on all output
++ * interfaces. It is clear, if mrouter runs a multicasting
++ * program, it should receive packets not depending to what interface
++ * program is joined.
++ * If we will not make it, the program will have to join on all
++ * interfaces. On the other hand, multihoming host (or router, but
++ * not mrouter) cannot join to more than one interface - it will
++ * result in receiving multiple packets.
++ */
++ dev = vif->dev;
++ skb->dev = dev;
++ vif->pkt_out++;
++ vif->bytes_out += skb->len;
++
++ /* We are about to write */
++ /* XXX: extension headers? */
++ if (skb_cow(skb, sizeof(*ipv6h) + LL_RESERVED_SPACE(dev)))
++ goto out_free;
++
++ ipv6h = ipv6_hdr(skb);
++ ipv6h->hop_limit--;
++
++ IP6CB(skb)->flags |= IP6SKB_FORWARDED;
++
++ return NF_HOOK(PF_INET6, NF_INET_FORWARD, skb, skb->dev, dev,
++ ip6mr_forward2_finish);
++
++out_free:
++ kfree_skb(skb);
++ return 0;
++}
++
++static int ip6mr_find_vif(struct net_device *dev)
++{
++ int ct;
++ for (ct = maxvif - 1; ct >= 0; ct--) {
++ if (vif6_table[ct].dev == dev)
++ break;
++ }
++ return ct;
++}
++
++static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache)
++{
++ int psend = -1;
++ int vif, ct;
++
++ vif = cache->mf6c_parent;
++ cache->mfc_un.res.pkt++;
++ cache->mfc_un.res.bytes += skb->len;
++
++ /*
++ * Wrong interface: drop packet and (maybe) send PIM assert.
++ */
++ if (vif6_table[vif].dev != skb->dev) {
++ int true_vifi;
++
++ cache->mfc_un.res.wrong_if++;
++ true_vifi = ip6mr_find_vif(skb->dev);
++
++ if (true_vifi >= 0 && mroute_do_assert &&
++ /* pimsm uses asserts, when switching from RPT to SPT,
++ so that we cannot check that packet arrived on an oif.
++ It is bad, but otherwise we would need to move pretty
++ large chunk of pimd to kernel. Ough... --ANK
++ */
++ (mroute_do_pim || cache->mfc_un.res.ttls[true_vifi] < 255) &&
++ time_after(jiffies,
++ cache->mfc_un.res.last_assert + MFC_ASSERT_THRESH)) {
++ cache->mfc_un.res.last_assert = jiffies;
++ ip6mr_cache_report(skb, true_vifi, MRT6MSG_WRONGMIF);
++ }
++ goto dont_forward;
++ }
++
++ vif6_table[vif].pkt_in++;
++ vif6_table[vif].bytes_in += skb->len;
++
++ /*
++ * Forward the frame
++ */
++ for (ct = cache->mfc_un.res.maxvif - 1; ct >= cache->mfc_un.res.minvif; ct--) {
++ if (ipv6_hdr(skb)->hop_limit > cache->mfc_un.res.ttls[ct]) {
++ if (psend != -1) {
++ struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
++ if (skb2)
++ ip6mr_forward2(skb2, cache, psend);
++ }
++ psend = ct;
++ }
++ }
++ if (psend != -1) {
++ ip6mr_forward2(skb, cache, psend);
++ return 0;
++ }
++
++dont_forward:
++ kfree_skb(skb);
++ return 0;
++}
++
++
++/*
++ * Multicast packets for forwarding arrive here
++ */
++
++int ip6_mr_input(struct sk_buff *skb)
++{
++ struct mfc6_cache *cache;
++
++ read_lock(&mrt_lock);
++ cache = ip6mr_cache_find(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr);
++
++ /*
++ * No usable cache entry
++ */
++ if (cache == NULL) {
++ int vif;
++
++ vif = ip6mr_find_vif(skb->dev);
++ if (vif >= 0) {
++ int err = ip6mr_cache_unresolved(vif, skb);
++ read_unlock(&mrt_lock);
++
++ return err;
++ }
++ read_unlock(&mrt_lock);
++ kfree_skb(skb);
++ return -ENODEV;
++ }
++
++ ip6_mr_forward(skb, cache);
++
++ read_unlock(&mrt_lock);
++
++ return 0;
++}
++
++
++static int
++ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm)
++{
++ int ct;
++ struct rtnexthop *nhp;
++ struct net_device *dev = vif6_table[c->mf6c_parent].dev;
++ u8 *b = skb_tail_pointer(skb);
++ struct rtattr *mp_head;
++
++ if (dev)
++ RTA_PUT(skb, RTA_IIF, 4, &dev->ifindex);
++
++ mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0));
++
++ for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) {
++ if (c->mfc_un.res.ttls[ct] < 255) {
++ if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4))
++ goto rtattr_failure;
++ nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));
++ nhp->rtnh_flags = 0;
++ nhp->rtnh_hops = c->mfc_un.res.ttls[ct];
++ nhp->rtnh_ifindex = vif6_table[ct].dev->ifindex;
++ nhp->rtnh_len = sizeof(*nhp);
++ }
++ }
++ mp_head->rta_type = RTA_MULTIPATH;
++ mp_head->rta_len = skb_tail_pointer(skb) - (u8 *)mp_head;
++ rtm->rtm_type = RTN_MULTICAST;
++ return 1;
++
++rtattr_failure:
++ nlmsg_trim(skb, b);
++ return -EMSGSIZE;
++}
++
++int ip6mr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait)
++{
++ int err;
++ struct mfc6_cache *cache;
++ struct rt6_info *rt = (struct rt6_info *)skb->dst;
++
++ read_lock(&mrt_lock);
++ cache = ip6mr_cache_find(&rt->rt6i_src.addr, &rt->rt6i_dst.addr);
++
++ if (!cache) {
++ struct sk_buff *skb2;
++ struct ipv6hdr *iph;
++ struct net_device *dev;
++ int vif;
++
++ if (nowait) {
++ read_unlock(&mrt_lock);
++ return -EAGAIN;
++ }
++
++ dev = skb->dev;
++ if (dev == NULL || (vif = ip6mr_find_vif(dev)) < 0) {
++ read_unlock(&mrt_lock);
++ return -ENODEV;
++ }
++
++ /* really correct? */
++ skb2 = alloc_skb(sizeof(struct ipv6hdr), GFP_ATOMIC);
++ if (!skb2) {
++ read_unlock(&mrt_lock);
++ return -ENOMEM;
++ }
++
++ skb_reset_transport_header(skb2);
++
++ skb_put(skb2, sizeof(struct ipv6hdr));
++ skb_reset_network_header(skb2);
++
++ iph = ipv6_hdr(skb2);
++ iph->version = 0;
++ iph->priority = 0;
++ iph->flow_lbl[0] = 0;
++ iph->flow_lbl[1] = 0;
++ iph->flow_lbl[2] = 0;
++ iph->payload_len = 0;
++ iph->nexthdr = IPPROTO_NONE;
++ iph->hop_limit = 0;
++ ipv6_addr_copy(&iph->saddr, &rt->rt6i_src.addr);
++ ipv6_addr_copy(&iph->daddr, &rt->rt6i_dst.addr);
++
++ err = ip6mr_cache_unresolved(vif, skb2);
++ read_unlock(&mrt_lock);
++
++ return err;
++ }
++
++ if (!nowait && (rtm->rtm_flags&RTM_F_NOTIFY))
++ cache->mfc_flags |= MFC_NOTIFY;
++
++ err = ip6mr_fill_mroute(skb, cache, rtm);
++ read_unlock(&mrt_lock);
++ return err;
++}
++
+diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
+index e3dcfa2..ee6de42 100644
+--- a/net/ipv6/ipcomp6.c
++++ b/net/ipv6/ipcomp6.c
+@@ -34,7 +34,6 @@
+ #include <net/ip.h>
+ #include <net/xfrm.h>
+ #include <net/ipcomp.h>
+-#include <asm/semaphore.h>
+ #include <linux/crypto.h>
+ #include <linux/err.h>
+ #include <linux/pfkeyv2.h>
+diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
+index bf2a686..06de9d0 100644
+--- a/net/ipv6/ipv6_sockglue.c
++++ b/net/ipv6/ipv6_sockglue.c
+@@ -16,7 +16,6 @@
+ *
+ * FIXME: Make the setsockopt code POSIX compliant: That is
+ *
+- * o Return -EINVAL for setsockopt of short lengths
+ * o Truncate getsockopt returns
+ * o Return an optlen of the truncated length if need be
+ *
+@@ -33,6 +32,7 @@
+ #include <linux/sockios.h>
+ #include <linux/net.h>
+ #include <linux/in6.h>
++#include <linux/mroute6.h>
+ #include <linux/netdevice.h>
+ #include <linux/if_arp.h>
+ #include <linux/init.h>
+@@ -57,118 +57,6 @@
+
+ DEFINE_SNMP_STAT(struct ipstats_mib, ipv6_statistics) __read_mostly;
+
+-static struct inet6_protocol *ipv6_gso_pull_exthdrs(struct sk_buff *skb,
+- int proto)
+-{
+- struct inet6_protocol *ops = NULL;
+-
+- for (;;) {
+- struct ipv6_opt_hdr *opth;
+- int len;
+-
+- if (proto != NEXTHDR_HOP) {
+- ops = rcu_dereference(inet6_protos[proto]);
+-
+- if (unlikely(!ops))
+- break;
+-
+- if (!(ops->flags & INET6_PROTO_GSO_EXTHDR))
+- break;
+- }
+-
+- if (unlikely(!pskb_may_pull(skb, 8)))
+- break;
+-
+- opth = (void *)skb->data;
+- len = opth->hdrlen * 8 + 8;
+-
+- if (unlikely(!pskb_may_pull(skb, len)))
+- break;
+-
+- proto = opth->nexthdr;
+- __skb_pull(skb, len);
+- }
+-
+- return ops;
+-}
+-
+-static int ipv6_gso_send_check(struct sk_buff *skb)
+-{
+- struct ipv6hdr *ipv6h;
+- struct inet6_protocol *ops;
+- int err = -EINVAL;
+-
+- if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
+- goto out;
+-
+- ipv6h = ipv6_hdr(skb);
+- __skb_pull(skb, sizeof(*ipv6h));
+- err = -EPROTONOSUPPORT;
+-
+- rcu_read_lock();
+- ops = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
+- if (likely(ops && ops->gso_send_check)) {
+- skb_reset_transport_header(skb);
+- err = ops->gso_send_check(skb);
+- }
+- rcu_read_unlock();
+-
+-out:
+- return err;
+-}
+-
+-static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features)
+-{
+- struct sk_buff *segs = ERR_PTR(-EINVAL);
+- struct ipv6hdr *ipv6h;
+- struct inet6_protocol *ops;
+-
+- if (!(features & NETIF_F_V6_CSUM))
+- features &= ~NETIF_F_SG;
+-
+- if (unlikely(skb_shinfo(skb)->gso_type &
+- ~(SKB_GSO_UDP |
+- SKB_GSO_DODGY |
+- SKB_GSO_TCP_ECN |
+- SKB_GSO_TCPV6 |
+- 0)))
+- goto out;
+-
+- if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
+- goto out;
+-
+- ipv6h = ipv6_hdr(skb);
+- __skb_pull(skb, sizeof(*ipv6h));
+- segs = ERR_PTR(-EPROTONOSUPPORT);
+-
+- rcu_read_lock();
+- ops = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
+- if (likely(ops && ops->gso_segment)) {
+- skb_reset_transport_header(skb);
+- segs = ops->gso_segment(skb, features);
+- }
+- rcu_read_unlock();
+-
+- if (unlikely(IS_ERR(segs)))
+- goto out;
+-
+- for (skb = segs; skb; skb = skb->next) {
+- ipv6h = ipv6_hdr(skb);
+- ipv6h->payload_len = htons(skb->len - skb->mac_len -
+- sizeof(*ipv6h));
+- }
+-
+-out:
+- return segs;
+-}
+-
+-static struct packet_type ipv6_packet_type = {
+- .type = __constant_htons(ETH_P_IPV6),
+- .func = ipv6_rcv,
+- .gso_send_check = ipv6_gso_send_check,
+- .gso_segment = ipv6_gso_segment,
+-};
+-
+ struct ip6_ra_chain *ip6_ra_chain;
+ DEFINE_RWLOCK(ip6_ra_lock);
+
+@@ -215,25 +103,59 @@ int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *))
+ return 0;
+ }
+
++static
++struct ipv6_txoptions *ipv6_update_options(struct sock *sk,
++ struct ipv6_txoptions *opt)
++{
++ if (inet_sk(sk)->is_icsk) {
++ if (opt &&
++ !((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) &&
++ inet_sk(sk)->daddr != LOOPBACK4_IPV6) {
++ struct inet_connection_sock *icsk = inet_csk(sk);
++ icsk->icsk_ext_hdr_len = opt->opt_flen + opt->opt_nflen;
++ icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie);
++ }
++ opt = xchg(&inet6_sk(sk)->opt, opt);
++ } else {
++ write_lock(&sk->sk_dst_lock);
++ opt = xchg(&inet6_sk(sk)->opt, opt);
++ write_unlock(&sk->sk_dst_lock);
++ }
++ sk_dst_reset(sk);
++
++ return opt;
++}
++
+ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int optlen)
+ {
+ struct ipv6_pinfo *np = inet6_sk(sk);
++ struct net *net = sock_net(sk);
+ int val, valbool;
+ int retv = -ENOPROTOOPT;
+
+ if (optval == NULL)
+ val=0;
+- else if (get_user(val, (int __user *) optval))
+- return -EFAULT;
++ else {
++ if (optlen >= sizeof(int)) {
++ if (get_user(val, (int __user *) optval))
++ return -EFAULT;
++ } else
++ val = 0;
++ }
+
+ valbool = (val!=0);
+
++ if (ip6_mroute_opt(optname))
++ return ip6_mroute_setsockopt(sk, optname, optval, optlen);
++
+ lock_sock(sk);
+
+ switch (optname) {
+
+ case IPV6_ADDRFORM:
++ if (optlen < sizeof(int))
++ goto e_inval;
+ if (val == PF_INET) {
+ struct ipv6_txoptions *opt;
+ struct sk_buff *pktopt;
+@@ -266,10 +188,9 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
+
+ if (sk->sk_protocol == IPPROTO_TCP) {
+ struct inet_connection_sock *icsk = inet_csk(sk);
+-
+ local_bh_disable();
+- sock_prot_inuse_add(sk->sk_prot, -1);
+- sock_prot_inuse_add(&tcp_prot, 1);
++ sock_prot_inuse_add(net, sk->sk_prot, -1);
++ sock_prot_inuse_add(net, &tcp_prot, 1);
+ local_bh_enable();
+ sk->sk_prot = &tcp_prot;
+ icsk->icsk_af_ops = &ipv4_specific;
+@@ -282,8 +203,8 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
+ if (sk->sk_protocol == IPPROTO_UDPLITE)
+ prot = &udplite_prot;
+ local_bh_disable();
+- sock_prot_inuse_add(sk->sk_prot, -1);
+- sock_prot_inuse_add(prot, 1);
++ sock_prot_inuse_add(net, sk->sk_prot, -1);
++ sock_prot_inuse_add(net, prot, 1);
+ local_bh_enable();
+ sk->sk_prot = prot;
+ sk->sk_socket->ops = &inet_dgram_ops;
+@@ -309,63 +230,86 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
+ goto e_inval;
+
+ case IPV6_V6ONLY:
+- if (inet_sk(sk)->num)
++ if (optlen < sizeof(int) ||
++ inet_sk(sk)->num)
+ goto e_inval;
+ np->ipv6only = valbool;
+ retv = 0;
+ break;
+
+ case IPV6_RECVPKTINFO:
++ if (optlen < sizeof(int))
++ goto e_inval;
+ np->rxopt.bits.rxinfo = valbool;
+ retv = 0;
+ break;
+
+ case IPV6_2292PKTINFO:
++ if (optlen < sizeof(int))
++ goto e_inval;
+ np->rxopt.bits.rxoinfo = valbool;
+ retv = 0;
+ break;
+
+ case IPV6_RECVHOPLIMIT:
++ if (optlen < sizeof(int))
++ goto e_inval;
+ np->rxopt.bits.rxhlim = valbool;
+ retv = 0;
+ break;
+
+ case IPV6_2292HOPLIMIT:
++ if (optlen < sizeof(int))
++ goto e_inval;
+ np->rxopt.bits.rxohlim = valbool;
+ retv = 0;
+ break;
+
+ case IPV6_RECVRTHDR:
++ if (optlen < sizeof(int))
++ goto e_inval;
+ np->rxopt.bits.srcrt = valbool;
+ retv = 0;
+ break;
+
+ case IPV6_2292RTHDR:
++ if (optlen < sizeof(int))
++ goto e_inval;
+ np->rxopt.bits.osrcrt = valbool;
+ retv = 0;
+ break;
+
+ case IPV6_RECVHOPOPTS:
++ if (optlen < sizeof(int))
++ goto e_inval;
+ np->rxopt.bits.hopopts = valbool;
+ retv = 0;
+ break;
+
+ case IPV6_2292HOPOPTS:
++ if (optlen < sizeof(int))
++ goto e_inval;
+ np->rxopt.bits.ohopopts = valbool;
+ retv = 0;
+ break;
+
+ case IPV6_RECVDSTOPTS:
++ if (optlen < sizeof(int))
++ goto e_inval;
+ np->rxopt.bits.dstopts = valbool;
+ retv = 0;
+ break;
+
+ case IPV6_2292DSTOPTS:
++ if (optlen < sizeof(int))
++ goto e_inval;
+ np->rxopt.bits.odstopts = valbool;
+ retv = 0;
+ break;
+
+ case IPV6_TCLASS:
++ if (optlen < sizeof(int))
++ goto e_inval;
+ if (val < -1 || val > 0xff)
+ goto e_inval;
+ np->tclass = val;
+@@ -373,11 +317,15 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
+ break;
+
+ case IPV6_RECVTCLASS:
++ if (optlen < sizeof(int))
++ goto e_inval;
+ np->rxopt.bits.rxtclass = valbool;
+ retv = 0;
+ break;
+
+ case IPV6_FLOWINFO:
++ if (optlen < sizeof(int))
++ goto e_inval;
+ np->rxopt.bits.rxflow = valbool;
+ retv = 0;
+ break;
+@@ -396,9 +344,9 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
+ if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW))
+ break;
+
+- retv = -EINVAL;
+- if (optlen & 0x7 || optlen > 8 * 255)
+- break;
++ if (optlen < sizeof(struct ipv6_opt_hdr) ||
++ optlen & 0x7 || optlen > 8 * 255)
++ goto e_inval;
+
+ opt = ipv6_renew_options(sk, np->opt, optname,
+ (struct ipv6_opt_hdr __user *)optval,
+@@ -426,25 +374,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
+ }
+
+ retv = 0;
+- if (inet_sk(sk)->is_icsk) {
+- if (opt) {
+- struct inet_connection_sock *icsk = inet_csk(sk);
+- if (!((1 << sk->sk_state) &
+- (TCPF_LISTEN | TCPF_CLOSE))
+- && inet_sk(sk)->daddr != LOOPBACK4_IPV6) {
+- icsk->icsk_ext_hdr_len =
+- opt->opt_flen + opt->opt_nflen;
+- icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie);
+- }
+- }
+- opt = xchg(&np->opt, opt);
+- sk_dst_reset(sk);
+- } else {
+- write_lock(&sk->sk_dst_lock);
+- opt = xchg(&np->opt, opt);
+- write_unlock(&sk->sk_dst_lock);
+- sk_dst_reset(sk);
+- }
++ opt = ipv6_update_options(sk, opt);
+ sticky_done:
+ if (opt)
+ sock_kfree_s(sk, opt, opt->tot_len);
+@@ -490,32 +420,15 @@ sticky_done:
+ goto done;
+ update:
+ retv = 0;
+- if (inet_sk(sk)->is_icsk) {
+- if (opt) {
+- struct inet_connection_sock *icsk = inet_csk(sk);
+- if (!((1 << sk->sk_state) &
+- (TCPF_LISTEN | TCPF_CLOSE))
+- && inet_sk(sk)->daddr != LOOPBACK4_IPV6) {
+- icsk->icsk_ext_hdr_len =
+- opt->opt_flen + opt->opt_nflen;
+- icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie);
+- }
+- }
+- opt = xchg(&np->opt, opt);
+- sk_dst_reset(sk);
+- } else {
+- write_lock(&sk->sk_dst_lock);
+- opt = xchg(&np->opt, opt);
+- write_unlock(&sk->sk_dst_lock);
+- sk_dst_reset(sk);
+- }
+-
++ opt = ipv6_update_options(sk, opt);
+ done:
+ if (opt)
+ sock_kfree_s(sk, opt, opt->tot_len);
+ break;
+ }
+ case IPV6_UNICAST_HOPS:
++ if (optlen < sizeof(int))
++ goto e_inval;
+ if (val > 255 || val < -1)
+ goto e_inval;
+ np->hop_limit = val;
+@@ -525,6 +438,8 @@ done:
+ case IPV6_MULTICAST_HOPS:
+ if (sk->sk_type == SOCK_STREAM)
+ goto e_inval;
++ if (optlen < sizeof(int))
++ goto e_inval;
+ if (val > 255 || val < -1)
+ goto e_inval;
+ np->mcast_hops = val;
+@@ -532,6 +447,8 @@ done:
+ break;
+
+ case IPV6_MULTICAST_LOOP:
++ if (optlen < sizeof(int))
++ goto e_inval;
+ np->mc_loop = valbool;
+ retv = 0;
+ break;
+@@ -539,12 +456,14 @@ done:
+ case IPV6_MULTICAST_IF:
+ if (sk->sk_type == SOCK_STREAM)
+ goto e_inval;
++ if (optlen < sizeof(int))
++ goto e_inval;
+
+ if (val) {
+ if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != val)
+ goto e_inval;
+
+- if (__dev_get_by_index(&init_net, val) == NULL) {
++ if (__dev_get_by_index(net, val) == NULL) {
+ retv = -ENODEV;
+ break;
+ }
+@@ -557,6 +476,9 @@ done:
+ {
+ struct ipv6_mreq mreq;
+
++ if (optlen < sizeof(struct ipv6_mreq))
++ goto e_inval;
++
+ retv = -EPROTO;
+ if (inet_sk(sk)->is_icsk)
+ break;
+@@ -576,7 +498,7 @@ done:
+ {
+ struct ipv6_mreq mreq;
+
+- if (optlen != sizeof(struct ipv6_mreq))
++ if (optlen < sizeof(struct ipv6_mreq))
+ goto e_inval;
+
+ retv = -EFAULT;
+@@ -595,6 +517,9 @@ done:
+ struct group_req greq;
+ struct sockaddr_in6 *psin6;
+
++ if (optlen < sizeof(struct group_req))
++ goto e_inval;
++
+ retv = -EFAULT;
+ if (copy_from_user(&greq, optval, sizeof(struct group_req)))
+ break;
+@@ -619,7 +544,7 @@ done:
+ struct group_source_req greqs;
+ int omode, add;
+
+- if (optlen != sizeof(struct group_source_req))
++ if (optlen < sizeof(struct group_source_req))
+ goto e_inval;
+ if (copy_from_user(&greqs, optval, sizeof(greqs))) {
+ retv = -EFAULT;
+@@ -693,27 +618,37 @@ done:
+ break;
+ }
+ case IPV6_ROUTER_ALERT:
++ if (optlen < sizeof(int))
++ goto e_inval;
+ retv = ip6_ra_control(sk, val, NULL);
+ break;
+ case IPV6_MTU_DISCOVER:
++ if (optlen < sizeof(int))
++ goto e_inval;
+ if (val<0 || val>3)
+ goto e_inval;
+ np->pmtudisc = val;
+ retv = 0;
+ break;
+ case IPV6_MTU:
++ if (optlen < sizeof(int))
++ goto e_inval;
+ if (val && val < IPV6_MIN_MTU)
+ goto e_inval;
+ np->frag_size = val;
+ retv = 0;
+ break;
+ case IPV6_RECVERR:
++ if (optlen < sizeof(int))
++ goto e_inval;
+ np->recverr = valbool;
+ if (!val)
+ skb_queue_purge(&sk->sk_error_queue);
+ retv = 0;
+ break;
+ case IPV6_FLOWINFO_SEND:
++ if (optlen < sizeof(int))
++ goto e_inval;
+ np->sndflow = valbool;
+ retv = 0;
+ break;
+@@ -728,7 +663,70 @@ done:
+ retv = xfrm_user_policy(sk, optname, optval, optlen);
+ break;
+
++ case IPV6_ADDR_PREFERENCES:
++ {
++ unsigned int pref = 0;
++ unsigned int prefmask = ~0;
++
++ if (optlen < sizeof(int))
++ goto e_inval;
++
++ retv = -EINVAL;
++
++ /* check PUBLIC/TMP/PUBTMP_DEFAULT conflicts */
++ switch (val & (IPV6_PREFER_SRC_PUBLIC|
++ IPV6_PREFER_SRC_TMP|
++ IPV6_PREFER_SRC_PUBTMP_DEFAULT)) {
++ case IPV6_PREFER_SRC_PUBLIC:
++ pref |= IPV6_PREFER_SRC_PUBLIC;
++ break;
++ case IPV6_PREFER_SRC_TMP:
++ pref |= IPV6_PREFER_SRC_TMP;
++ break;
++ case IPV6_PREFER_SRC_PUBTMP_DEFAULT:
++ break;
++ case 0:
++ goto pref_skip_pubtmp;
++ default:
++ goto e_inval;
++ }
++
++ prefmask &= ~(IPV6_PREFER_SRC_PUBLIC|
++ IPV6_PREFER_SRC_TMP);
++pref_skip_pubtmp:
++
++ /* check HOME/COA conflicts */
++ switch (val & (IPV6_PREFER_SRC_HOME|IPV6_PREFER_SRC_COA)) {
++ case IPV6_PREFER_SRC_HOME:
++ break;
++ case IPV6_PREFER_SRC_COA:
++ pref |= IPV6_PREFER_SRC_COA;
++ case 0:
++ goto pref_skip_coa;
++ default:
++ goto e_inval;
++ }
++
++ prefmask &= ~IPV6_PREFER_SRC_COA;
++pref_skip_coa:
++
++ /* check CGA/NONCGA conflicts */
++ switch (val & (IPV6_PREFER_SRC_CGA|IPV6_PREFER_SRC_NONCGA)) {
++ case IPV6_PREFER_SRC_CGA:
++ case IPV6_PREFER_SRC_NONCGA:
++ case 0:
++ break;
++ default:
++ goto e_inval;
++ }
++
++ np->srcprefs = (np->srcprefs & prefmask) | pref;
++ retv = 0;
++
++ break;
++ }
+ }
++
+ release_sock(sk);
+
+ return retv;
+@@ -839,6 +837,9 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
+ int len;
+ int val;
+
++ if (ip6_mroute_opt(optname))
++ return ip6_mroute_getsockopt(sk, optname, optval, optlen);
++
+ if (get_user(len, optlen))
+ return -EFAULT;
+ switch (optname) {
+@@ -1015,9 +1016,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
+ dst = sk_dst_get(sk);
+ if (dst) {
+ if (val < 0)
+- val = dst_metric(dst, RTAX_HOPLIMIT);
+- if (val < 0)
+- val = ipv6_get_hoplimit(dst->dev);
++ val = ip6_dst_hoplimit(dst);
+ dst_release(dst);
+ }
+ if (val < 0)
+@@ -1045,6 +1044,24 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
+ val = np->sndflow;
+ break;
+
++ case IPV6_ADDR_PREFERENCES:
++ val = 0;
++
++ if (np->srcprefs & IPV6_PREFER_SRC_TMP)
++ val |= IPV6_PREFER_SRC_TMP;
++ else if (np->srcprefs & IPV6_PREFER_SRC_PUBLIC)
++ val |= IPV6_PREFER_SRC_PUBLIC;
++ else {
++ /* XXX: should we return system default? */
++ val |= IPV6_PREFER_SRC_PUBTMP_DEFAULT;
++ }
++
++ if (np->srcprefs & IPV6_PREFER_SRC_COA)
++ val |= IPV6_PREFER_SRC_COA;
++ else
++ val |= IPV6_PREFER_SRC_HOME;
++ break;
++
+ default:
+ return -ENOPROTOOPT;
+ }
+@@ -1128,13 +1145,3 @@ int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
+ EXPORT_SYMBOL(compat_ipv6_getsockopt);
+ #endif
+
+-int __init ipv6_packet_init(void)
+-{
+- dev_add_pack(&ipv6_packet_type);
+- return 0;
+-}
+-
+-void ipv6_packet_cleanup(void)
+-{
+- dev_remove_pack(&ipv6_packet_type);
+-}
+diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
+index ab228d1..54f91ef 100644
+--- a/net/ipv6/mcast.c
++++ b/net/ipv6/mcast.c
+@@ -59,6 +59,7 @@
+ #include <net/ndisc.h>
+ #include <net/addrconf.h>
+ #include <net/ip6_route.h>
++#include <net/inet_common.h>
+
+ #include <net/ip6_checksum.h>
+
+@@ -126,10 +127,6 @@ static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT;
+ /* Big mc list lock for all the sockets */
+ static DEFINE_RWLOCK(ipv6_sk_mc_lock);
+
+-static struct socket *igmp6_socket;
+-
+-int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr);
+-
+ static void igmp6_join_group(struct ifmcaddr6 *ma);
+ static void igmp6_leave_group(struct ifmcaddr6 *ma);
+ static void igmp6_timer_handler(unsigned long data);
+@@ -178,11 +175,12 @@ int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF;
+ * socket join on multicast group
+ */
+
+-int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr)
++int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
+ {
+ struct net_device *dev = NULL;
+ struct ipv6_mc_socklist *mc_lst;
+ struct ipv6_pinfo *np = inet6_sk(sk);
++ struct net *net = sock_net(sk);
+ int err;
+
+ if (!ipv6_addr_is_multicast(addr))
+@@ -208,14 +206,14 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr)
+
+ if (ifindex == 0) {
+ struct rt6_info *rt;
+- rt = rt6_lookup(addr, NULL, 0, 0);
++ rt = rt6_lookup(net, addr, NULL, 0, 0);
+ if (rt) {
+ dev = rt->rt6i_dev;
+ dev_hold(dev);
+ dst_release(&rt->u.dst);
+ }
+ } else
+- dev = dev_get_by_index(&init_net, ifindex);
++ dev = dev_get_by_index(net, ifindex);
+
+ if (dev == NULL) {
+ sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
+@@ -252,10 +250,11 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr)
+ /*
+ * socket leave on multicast group
+ */
+-int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
++int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
+ {
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct ipv6_mc_socklist *mc_lst, **lnk;
++ struct net *net = sock_net(sk);
+
+ write_lock_bh(&ipv6_sk_mc_lock);
+ for (lnk = &np->ipv6_mc_list; (mc_lst = *lnk) !=NULL ; lnk = &mc_lst->next) {
+@@ -266,7 +265,8 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
+ *lnk = mc_lst->next;
+ write_unlock_bh(&ipv6_sk_mc_lock);
+
+- if ((dev = dev_get_by_index(&init_net, mc_lst->ifindex)) != NULL) {
++ dev = dev_get_by_index(net, mc_lst->ifindex);
++ if (dev != NULL) {
+ struct inet6_dev *idev = in6_dev_get(dev);
+
+ (void) ip6_mc_leave_src(sk, mc_lst, idev);
+@@ -286,7 +286,9 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
+ return -EADDRNOTAVAIL;
+ }
+
+-static struct inet6_dev *ip6_mc_find_dev(struct in6_addr *group, int ifindex)
++static struct inet6_dev *ip6_mc_find_dev(struct net *net,
++ struct in6_addr *group,
++ int ifindex)
+ {
+ struct net_device *dev = NULL;
+ struct inet6_dev *idev = NULL;
+@@ -294,14 +296,14 @@ static struct inet6_dev *ip6_mc_find_dev(struct in6_addr *group, int ifindex)
+ if (ifindex == 0) {
+ struct rt6_info *rt;
+
+- rt = rt6_lookup(group, NULL, 0, 0);
++ rt = rt6_lookup(net, group, NULL, 0, 0);
+ if (rt) {
+ dev = rt->rt6i_dev;
+ dev_hold(dev);
+ dst_release(&rt->u.dst);
+ }
+ } else
+- dev = dev_get_by_index(&init_net, ifindex);
++ dev = dev_get_by_index(net, ifindex);
+
+ if (!dev)
+ return NULL;
+@@ -324,6 +326,7 @@ void ipv6_sock_mc_close(struct sock *sk)
+ {
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct ipv6_mc_socklist *mc_lst;
++ struct net *net = sock_net(sk);
+
+ write_lock_bh(&ipv6_sk_mc_lock);
+ while ((mc_lst = np->ipv6_mc_list) != NULL) {
+@@ -332,7 +335,7 @@ void ipv6_sock_mc_close(struct sock *sk)
+ np->ipv6_mc_list = mc_lst->next;
+ write_unlock_bh(&ipv6_sk_mc_lock);
+
+- dev = dev_get_by_index(&init_net, mc_lst->ifindex);
++ dev = dev_get_by_index(net, mc_lst->ifindex);
+ if (dev) {
+ struct inet6_dev *idev = in6_dev_get(dev);
+
+@@ -361,6 +364,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
+ struct inet6_dev *idev;
+ struct ipv6_pinfo *inet6 = inet6_sk(sk);
+ struct ip6_sf_socklist *psl;
++ struct net *net = sock_net(sk);
+ int i, j, rv;
+ int leavegroup = 0;
+ int pmclocked = 0;
+@@ -376,7 +380,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
+ if (!ipv6_addr_is_multicast(group))
+ return -EINVAL;
+
+- idev = ip6_mc_find_dev(group, pgsr->gsr_interface);
++ idev = ip6_mc_find_dev(net, group, pgsr->gsr_interface);
+ if (!idev)
+ return -ENODEV;
+ dev = idev->dev;
+@@ -500,6 +504,7 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
+ struct inet6_dev *idev;
+ struct ipv6_pinfo *inet6 = inet6_sk(sk);
+ struct ip6_sf_socklist *newpsl, *psl;
++ struct net *net = sock_net(sk);
+ int leavegroup = 0;
+ int i, err;
+
+@@ -511,7 +516,7 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
+ gsf->gf_fmode != MCAST_EXCLUDE)
+ return -EINVAL;
+
+- idev = ip6_mc_find_dev(group, gsf->gf_interface);
++ idev = ip6_mc_find_dev(net, group, gsf->gf_interface);
+
+ if (!idev)
+ return -ENODEV;
+@@ -592,13 +597,14 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
+ struct net_device *dev;
+ struct ipv6_pinfo *inet6 = inet6_sk(sk);
+ struct ip6_sf_socklist *psl;
++ struct net *net = sock_net(sk);
+
+ group = &((struct sockaddr_in6 *)&gsf->gf_group)->sin6_addr;
+
+ if (!ipv6_addr_is_multicast(group))
+ return -EINVAL;
+
+- idev = ip6_mc_find_dev(group, gsf->gf_interface);
++ idev = ip6_mc_find_dev(net, group, gsf->gf_interface);
+
+ if (!idev)
+ return -ENODEV;
+@@ -656,8 +662,8 @@ done:
+ return err;
+ }
+
+-int inet6_mc_check(struct sock *sk, struct in6_addr *mc_addr,
+- struct in6_addr *src_addr)
++int inet6_mc_check(struct sock *sk, const struct in6_addr *mc_addr,
++ const struct in6_addr *src_addr)
+ {
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct ipv6_mc_socklist *mc;
+@@ -863,7 +869,7 @@ static void mld_clear_delrec(struct inet6_dev *idev)
+ /*
+ * device multicast group inc (add if not found)
+ */
+-int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr)
++int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr)
+ {
+ struct ifmcaddr6 *mc;
+ struct inet6_dev *idev;
+@@ -934,7 +940,7 @@ int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr)
+ /*
+ * device multicast group del
+ */
+-int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr)
++int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr)
+ {
+ struct ifmcaddr6 *ma, **map;
+
+@@ -959,7 +965,7 @@ int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr)
+ return -ENOENT;
+ }
+
+-int ipv6_dev_mc_dec(struct net_device *dev, struct in6_addr *addr)
++int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr)
+ {
+ struct inet6_dev *idev = in6_dev_get(dev);
+ int err;
+@@ -1004,8 +1010,8 @@ int ipv6_is_mld(struct sk_buff *skb, int nexthdr)
+ /*
+ * check if the interface/address pair is valid
+ */
+-int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *group,
+- struct in6_addr *src_addr)
++int ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group,
++ const struct in6_addr *src_addr)
+ {
+ struct inet6_dev *idev;
+ struct ifmcaddr6 *mc;
+@@ -1393,10 +1399,12 @@ mld_scount(struct ifmcaddr6 *pmc, int type, int gdeleted, int sdeleted)
+
+ static struct sk_buff *mld_newpack(struct net_device *dev, int size)
+ {
+- struct sock *sk = igmp6_socket->sk;
++ struct net *net = dev_net(dev);
++ struct sock *sk = net->ipv6.igmp_sk;
+ struct sk_buff *skb;
+ struct mld2_report *pmr;
+ struct in6_addr addr_buf;
++ const struct in6_addr *saddr;
+ int err;
+ u8 ra[8] = { IPPROTO_ICMPV6, 0,
+ IPV6_TLV_ROUTERALERT, 2, 0, 0,
+@@ -1415,10 +1423,11 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size)
+ * use unspecified address as the source address
+ * when a valid link-local address is not available.
+ */
+- memset(&addr_buf, 0, sizeof(addr_buf));
+- }
++ saddr = &in6addr_any;
++ } else
++ saddr = &addr_buf;
+
+- ip6_nd_hdr(sk, skb, dev, &addr_buf, &mld2_all_mcr, NEXTHDR_HOP, 0);
++ ip6_nd_hdr(sk, skb, dev, saddr, &mld2_all_mcr, NEXTHDR_HOP, 0);
+
+ memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra));
+
+@@ -1433,25 +1442,6 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size)
+ return skb;
+ }
+
+-static inline int mld_dev_queue_xmit2(struct sk_buff *skb)
+-{
+- struct net_device *dev = skb->dev;
+- unsigned char ha[MAX_ADDR_LEN];
+-
+- ndisc_mc_map(&ipv6_hdr(skb)->daddr, ha, dev, 1);
+- if (dev_hard_header(skb, dev, ETH_P_IPV6, ha, NULL, skb->len) < 0) {
+- kfree_skb(skb);
+- return -EINVAL;
+- }
+- return dev_queue_xmit(skb);
+-}
+-
+-static inline int mld_dev_queue_xmit(struct sk_buff *skb)
+-{
+- return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb->dev,
+- mld_dev_queue_xmit2);
+-}
+-
+ static void mld_sendpack(struct sk_buff *skb)
+ {
+ struct ipv6hdr *pip6 = ipv6_hdr(skb);
+@@ -1459,7 +1449,9 @@ static void mld_sendpack(struct sk_buff *skb)
+ (struct mld2_report *)skb_transport_header(skb);
+ int payload_len, mldlen;
+ struct inet6_dev *idev = in6_dev_get(skb->dev);
++ struct net *net = dev_net(skb->dev);
+ int err;
++ struct flowi fl;
+
+ IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
+ payload_len = (skb->tail - skb->network_header) - sizeof(*pip6);
+@@ -1469,8 +1461,25 @@ static void mld_sendpack(struct sk_buff *skb)
+ pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen,
+ IPPROTO_ICMPV6, csum_partial(skb_transport_header(skb),
+ mldlen, 0));
++
++ skb->dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr);
++
++ if (!skb->dst) {
++ err = -ENOMEM;
++ goto err_out;
++ }
++
++ icmpv6_flow_init(net->ipv6.igmp_sk, &fl, ICMPV6_MLD2_REPORT,
++ &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
++ skb->dev->ifindex);
++
++ err = xfrm_lookup(&skb->dst, &fl, NULL, 0);
++ if (err)
++ goto err_out;
++
+ err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev,
+- mld_dev_queue_xmit);
++ dst_output);
++out:
+ if (!err) {
+ ICMP6MSGOUT_INC_STATS_BH(idev, ICMPV6_MLD2_REPORT);
+ ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS);
+@@ -1480,6 +1489,11 @@ static void mld_sendpack(struct sk_buff *skb)
+
+ if (likely(idev != NULL))
+ in6_dev_put(idev);
++ return;
++
++err_out:
++ kfree_skb(skb);
++ goto out;
+ }
+
+ static int grec_size(struct ifmcaddr6 *pmc, int type, int gdel, int sdel)
+@@ -1749,28 +1763,28 @@ static void mld_send_cr(struct inet6_dev *idev)
+
+ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
+ {
+- struct sock *sk = igmp6_socket->sk;
++ struct net *net = dev_net(dev);
++ struct sock *sk = net->ipv6.igmp_sk;
+ struct inet6_dev *idev;
+ struct sk_buff *skb;
+ struct icmp6hdr *hdr;
+- struct in6_addr *snd_addr;
++ const struct in6_addr *snd_addr, *saddr;
+ struct in6_addr *addrp;
+ struct in6_addr addr_buf;
+- struct in6_addr all_routers;
+ int err, len, payload_len, full_len;
+ u8 ra[8] = { IPPROTO_ICMPV6, 0,
+ IPV6_TLV_ROUTERALERT, 2, 0, 0,
+ IPV6_TLV_PADN, 0 };
++ struct flowi fl;
+
+ rcu_read_lock();
+ IP6_INC_STATS(__in6_dev_get(dev),
+ IPSTATS_MIB_OUTREQUESTS);
+ rcu_read_unlock();
+- snd_addr = addr;
+- if (type == ICMPV6_MGM_REDUCTION) {
+- snd_addr = &all_routers;
+- ipv6_addr_all_routers(&all_routers);
+- }
++ if (type == ICMPV6_MGM_REDUCTION)
++ snd_addr = &in6addr_linklocal_allrouters;
++ else
++ snd_addr = addr;
+
+ len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
+ payload_len = len + sizeof(ra);
+@@ -1793,10 +1807,11 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
+ * use unspecified address as the source address
+ * when a valid link-local address is not available.
+ */
+- memset(&addr_buf, 0, sizeof(addr_buf));
+- }
++ saddr = &in6addr_any;
++ } else
++ saddr = &addr_buf;
+
+- ip6_nd_hdr(sk, skb, dev, &addr_buf, snd_addr, NEXTHDR_HOP, payload_len);
++ ip6_nd_hdr(sk, skb, dev, saddr, snd_addr, NEXTHDR_HOP, payload_len);
+
+ memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra));
+
+@@ -1807,14 +1822,29 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
+ addrp = (struct in6_addr *) skb_put(skb, sizeof(struct in6_addr));
+ ipv6_addr_copy(addrp, addr);
+
+- hdr->icmp6_cksum = csum_ipv6_magic(&addr_buf, snd_addr, len,
++ hdr->icmp6_cksum = csum_ipv6_magic(saddr, snd_addr, len,
+ IPPROTO_ICMPV6,
+ csum_partial((__u8 *) hdr, len, 0));
+
+ idev = in6_dev_get(skb->dev);
+
++ skb->dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr);
++ if (!skb->dst) {
++ err = -ENOMEM;
++ goto err_out;
++ }
++
++ icmpv6_flow_init(sk, &fl, type,
++ &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
++ skb->dev->ifindex);
++
++ err = xfrm_lookup(&skb->dst, &fl, NULL, 0);
++ if (err)
++ goto err_out;
++
+ err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev,
+- mld_dev_queue_xmit);
++ dst_output);
++out:
+ if (!err) {
+ ICMP6MSGOUT_INC_STATS(idev, type);
+ ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
+@@ -1825,6 +1855,10 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
+ if (likely(idev != NULL))
+ in6_dev_put(idev);
+ return;
++
++err_out:
++ kfree_skb(skb);
++ goto out;
+ }
+
+ static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode,
+@@ -2276,24 +2310,19 @@ void ipv6_mc_init_dev(struct inet6_dev *idev)
+ void ipv6_mc_destroy_dev(struct inet6_dev *idev)
+ {
+ struct ifmcaddr6 *i;
+- struct in6_addr maddr;
+
+ /* Deactivate timers */
+ ipv6_mc_down(idev);
+
+ /* Delete all-nodes address. */
+- ipv6_addr_all_nodes(&maddr);
+-
+ /* We cannot call ipv6_dev_mc_dec() directly, our caller in
+ * addrconf.c has NULL'd out dev->ip6_ptr so in6_dev_get() will
+ * fail.
+ */
+- __ipv6_dev_mc_dec(idev, &maddr);
++ __ipv6_dev_mc_dec(idev, &in6addr_linklocal_allnodes);
+
+- if (idev->cnf.forwarding) {
+- ipv6_addr_all_routers(&maddr);
+- __ipv6_dev_mc_dec(idev, &maddr);
+- }
++ if (idev->cnf.forwarding)
++ __ipv6_dev_mc_dec(idev, &in6addr_linklocal_allrouters);
+
+ write_lock_bh(&idev->lock);
+ while ((i = idev->mc_list) != NULL) {
+@@ -2310,6 +2339,7 @@ void ipv6_mc_destroy_dev(struct inet6_dev *idev)
+
+ #ifdef CONFIG_PROC_FS
+ struct igmp6_mc_iter_state {
++ struct seq_net_private p;
+ struct net_device *dev;
+ struct inet6_dev *idev;
+ };
+@@ -2320,9 +2350,10 @@ static inline struct ifmcaddr6 *igmp6_mc_get_first(struct seq_file *seq)
+ {
+ struct ifmcaddr6 *im = NULL;
+ struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
++ struct net *net = seq_file_net(seq);
+
+ state->idev = NULL;
+- for_each_netdev(&init_net, state->dev) {
++ for_each_netdev(net, state->dev) {
+ struct inet6_dev *idev;
+ idev = in6_dev_get(state->dev);
+ if (!idev)
+@@ -2424,8 +2455,8 @@ static const struct seq_operations igmp6_mc_seq_ops = {
+
+ static int igmp6_mc_seq_open(struct inode *inode, struct file *file)
+ {
+- return seq_open_private(file, &igmp6_mc_seq_ops,
+- sizeof(struct igmp6_mc_iter_state));
++ return seq_open_net(inode, file, &igmp6_mc_seq_ops,
++ sizeof(struct igmp6_mc_iter_state));
+ }
+
+ static const struct file_operations igmp6_mc_seq_fops = {
+@@ -2433,10 +2464,11 @@ static const struct file_operations igmp6_mc_seq_fops = {
+ .open = igmp6_mc_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = seq_release_private,
++ .release = seq_release_net,
+ };
+
+ struct igmp6_mcf_iter_state {
++ struct seq_net_private p;
+ struct net_device *dev;
+ struct inet6_dev *idev;
+ struct ifmcaddr6 *im;
+@@ -2449,10 +2481,11 @@ static inline struct ip6_sf_list *igmp6_mcf_get_first(struct seq_file *seq)
+ struct ip6_sf_list *psf = NULL;
+ struct ifmcaddr6 *im = NULL;
+ struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
++ struct net *net = seq_file_net(seq);
+
+ state->idev = NULL;
+ state->im = NULL;
+- for_each_netdev(&init_net, state->dev) {
++ for_each_netdev(net, state->dev) {
+ struct inet6_dev *idev;
+ idev = in6_dev_get(state->dev);
+ if (unlikely(idev == NULL))
+@@ -2584,8 +2617,8 @@ static const struct seq_operations igmp6_mcf_seq_ops = {
+
+ static int igmp6_mcf_seq_open(struct inode *inode, struct file *file)
+ {
+- return seq_open_private(file, &igmp6_mcf_seq_ops,
+- sizeof(struct igmp6_mcf_iter_state));
++ return seq_open_net(inode, file, &igmp6_mcf_seq_ops,
++ sizeof(struct igmp6_mcf_iter_state));
+ }
+
+ static const struct file_operations igmp6_mcf_seq_fops = {
+@@ -2593,47 +2626,88 @@ static const struct file_operations igmp6_mcf_seq_fops = {
+ .open = igmp6_mcf_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = seq_release_private,
++ .release = seq_release_net,
+ };
++
++static int igmp6_proc_init(struct net *net)
++{
++ int err;
++
++ err = -ENOMEM;
++ if (!proc_net_fops_create(net, "igmp6", S_IRUGO, &igmp6_mc_seq_fops))
++ goto out;
++ if (!proc_net_fops_create(net, "mcfilter6", S_IRUGO,
++ &igmp6_mcf_seq_fops))
++ goto out_proc_net_igmp6;
++
++ err = 0;
++out:
++ return err;
++
++out_proc_net_igmp6:
++ proc_net_remove(net, "igmp6");
++ goto out;
++}
++
++static void igmp6_proc_exit(struct net *net)
++{
++ proc_net_remove(net, "mcfilter6");
++ proc_net_remove(net, "igmp6");
++}
++#else
++static int igmp6_proc_init(struct net *net)
++{
++ return 0;
++}
++static void igmp6_proc_exit(struct net *net)
++{
++ ;
++}
+ #endif
+
+-int __init igmp6_init(struct net_proto_family *ops)
++static int igmp6_net_init(struct net *net)
+ {
+- struct ipv6_pinfo *np;
+- struct sock *sk;
+ int err;
+
+- err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &igmp6_socket);
++ err = inet_ctl_sock_create(&net->ipv6.igmp_sk, PF_INET6,
++ SOCK_RAW, IPPROTO_ICMPV6, net);
+ if (err < 0) {
+ printk(KERN_ERR
+ "Failed to initialize the IGMP6 control socket (err %d).\n",
+ err);
+- igmp6_socket = NULL; /* For safety. */
+- return err;
++ goto out;
+ }
+
+- sk = igmp6_socket->sk;
+- sk->sk_allocation = GFP_ATOMIC;
+- sk->sk_prot->unhash(sk);
++ inet6_sk(net->ipv6.igmp_sk)->hop_limit = 1;
+
+- np = inet6_sk(sk);
+- np->hop_limit = 1;
++ err = igmp6_proc_init(net);
++ if (err)
++ goto out_sock_create;
++out:
++ return err;
+
+-#ifdef CONFIG_PROC_FS
+- proc_net_fops_create(&init_net, "igmp6", S_IRUGO, &igmp6_mc_seq_fops);
+- proc_net_fops_create(&init_net, "mcfilter6", S_IRUGO, &igmp6_mcf_seq_fops);
+-#endif
++out_sock_create:
++ inet_ctl_sock_destroy(net->ipv6.igmp_sk);
++ goto out;
++}
+
+- return 0;
++static void igmp6_net_exit(struct net *net)
++{
++ inet_ctl_sock_destroy(net->ipv6.igmp_sk);
++ igmp6_proc_exit(net);
+ }
+
+-void igmp6_cleanup(void)
++static struct pernet_operations igmp6_net_ops = {
++ .init = igmp6_net_init,
++ .exit = igmp6_net_exit,
++};
++
++int __init igmp6_init(void)
+ {
+- sock_release(igmp6_socket);
+- igmp6_socket = NULL; /* for safety */
++ return register_pernet_subsys(&igmp6_net_ops);
++}
+
+-#ifdef CONFIG_PROC_FS
+- proc_net_remove(&init_net, "mcfilter6");
+- proc_net_remove(&init_net, "igmp6");
+-#endif
++void igmp6_cleanup(void)
++{
++ unregister_pernet_subsys(&igmp6_net_ops);
+ }
+diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c
+index cd8a5bd..ad1cc5b 100644
+--- a/net/ipv6/mip6.c
++++ b/net/ipv6/mip6.c
+@@ -44,9 +44,9 @@ static inline void *mip6_padn(__u8 *data, __u8 padlen)
+ if (!data)
+ return NULL;
+ if (padlen == 1) {
+- data[0] = MIP6_OPT_PAD_1;
++ data[0] = IPV6_TLV_PAD0;
+ } else if (padlen > 1) {
+- data[0] = MIP6_OPT_PAD_N;
++ data[0] = IPV6_TLV_PADN;
+ data[1] = padlen - 2;
+ if (padlen > 2)
+ memset(data+2, 0, data[1]);
+@@ -304,13 +304,13 @@ static int mip6_destopt_offset(struct xfrm_state *x, struct sk_buff *skb,
+ static int mip6_destopt_init_state(struct xfrm_state *x)
+ {
+ if (x->id.spi) {
+- printk(KERN_INFO "%s: spi is not 0: %u\n", __FUNCTION__,
++ printk(KERN_INFO "%s: spi is not 0: %u\n", __func__,
+ x->id.spi);
+ return -EINVAL;
+ }
+ if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) {
+ printk(KERN_INFO "%s: state's mode is not %u: %u\n",
+- __FUNCTION__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode);
++ __func__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode);
+ return -EINVAL;
+ }
+
+@@ -439,13 +439,13 @@ static int mip6_rthdr_offset(struct xfrm_state *x, struct sk_buff *skb,
+ static int mip6_rthdr_init_state(struct xfrm_state *x)
+ {
+ if (x->id.spi) {
+- printk(KERN_INFO "%s: spi is not 0: %u\n", __FUNCTION__,
++ printk(KERN_INFO "%s: spi is not 0: %u\n", __func__,
+ x->id.spi);
+ return -EINVAL;
+ }
+ if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) {
+ printk(KERN_INFO "%s: state's mode is not %u: %u\n",
+- __FUNCTION__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode);
++ __func__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode);
+ return -EINVAL;
+ }
+
+@@ -480,15 +480,15 @@ static int __init mip6_init(void)
+ printk(KERN_INFO "Mobile IPv6\n");
+
+ if (xfrm_register_type(&mip6_destopt_type, AF_INET6) < 0) {
+- printk(KERN_INFO "%s: can't add xfrm type(destopt)\n", __FUNCTION__);
++ printk(KERN_INFO "%s: can't add xfrm type(destopt)\n", __func__);
+ goto mip6_destopt_xfrm_fail;
+ }
+ if (xfrm_register_type(&mip6_rthdr_type, AF_INET6) < 0) {
+- printk(KERN_INFO "%s: can't add xfrm type(rthdr)\n", __FUNCTION__);
++ printk(KERN_INFO "%s: can't add xfrm type(rthdr)\n", __func__);
+ goto mip6_rthdr_xfrm_fail;
+ }
+ if (rawv6_mh_filter_register(mip6_mh_filter) < 0) {
+- printk(KERN_INFO "%s: can't add rawv6 mh filter\n", __FUNCTION__);
++ printk(KERN_INFO "%s: can't add rawv6 mh filter\n", __func__);
+ goto mip6_rawv6_mh_fail;
+ }
+
+@@ -506,11 +506,11 @@ static int __init mip6_init(void)
+ static void __exit mip6_fini(void)
+ {
+ if (rawv6_mh_filter_unregister(mip6_mh_filter) < 0)
+- printk(KERN_INFO "%s: can't remove rawv6 mh filter\n", __FUNCTION__);
++ printk(KERN_INFO "%s: can't remove rawv6 mh filter\n", __func__);
+ if (xfrm_unregister_type(&mip6_rthdr_type, AF_INET6) < 0)
+- printk(KERN_INFO "%s: can't remove xfrm type(rthdr)\n", __FUNCTION__);
++ printk(KERN_INFO "%s: can't remove xfrm type(rthdr)\n", __func__);
+ if (xfrm_unregister_type(&mip6_destopt_type, AF_INET6) < 0)
+- printk(KERN_INFO "%s: can't remove xfrm type(destopt)\n", __FUNCTION__);
++ printk(KERN_INFO "%s: can't remove xfrm type(destopt)\n", __func__);
+ }
+
+ module_init(mip6_init);
+diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
+index 452a2ac..2c74885 100644
+--- a/net/ipv6/ndisc.c
++++ b/net/ipv6/ndisc.c
+@@ -84,13 +84,12 @@
+
+ #include <net/flow.h>
+ #include <net/ip6_checksum.h>
++#include <net/inet_common.h>
+ #include <linux/proc_fs.h>
+
+ #include <linux/netfilter.h>
+ #include <linux/netfilter_ipv6.h>
+
+-static struct socket *ndisc_socket;
+-
+ static u32 ndisc_hash(const void *pkey, const struct net_device *dev);
+ static int ndisc_constructor(struct neighbour *neigh);
+ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb);
+@@ -270,7 +269,7 @@ static struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
+ if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {
+ ND_PRINTK2(KERN_WARNING
+ "%s(): duplicated ND6 option found: type=%d\n",
+- __FUNCTION__,
++ __func__,
+ nd_opt->nd_opt_type);
+ } else {
+ ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt;
+@@ -301,7 +300,7 @@ static struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
+ */
+ ND_PRINTK2(KERN_NOTICE
+ "%s(): ignored unsupported option; type=%d, len=%d\n",
+- __FUNCTION__,
++ __func__,
+ nd_opt->nd_opt_type, nd_opt->nd_opt_len);
+ }
+ }
+@@ -441,30 +440,17 @@ static void pndisc_destructor(struct pneigh_entry *n)
+ /*
+ * Send a Neighbour Advertisement
+ */
+-
+-static inline void ndisc_flow_init(struct flowi *fl, u8 type,
+- struct in6_addr *saddr, struct in6_addr *daddr,
+- int oif)
+-{
+- memset(fl, 0, sizeof(*fl));
+- ipv6_addr_copy(&fl->fl6_src, saddr);
+- ipv6_addr_copy(&fl->fl6_dst, daddr);
+- fl->proto = IPPROTO_ICMPV6;
+- fl->fl_icmp_type = type;
+- fl->fl_icmp_code = 0;
+- fl->oif = oif;
+- security_sk_classify_flow(ndisc_socket->sk, fl);
+-}
+-
+ static void __ndisc_send(struct net_device *dev,
+ struct neighbour *neigh,
+- struct in6_addr *daddr, struct in6_addr *saddr,
+- struct icmp6hdr *icmp6h, struct in6_addr *target,
++ const struct in6_addr *daddr,
++ const struct in6_addr *saddr,
++ struct icmp6hdr *icmp6h, const struct in6_addr *target,
+ int llinfo)
+ {
+ struct flowi fl;
+ struct dst_entry *dst;
+- struct sock *sk = ndisc_socket->sk;
++ struct net *net = dev_net(dev);
++ struct sock *sk = net->ipv6.ndisc_sk;
+ struct sk_buff *skb;
+ struct icmp6hdr *hdr;
+ struct inet6_dev *idev;
+@@ -474,10 +460,9 @@ static void __ndisc_send(struct net_device *dev,
+
+ type = icmp6h->icmp6_type;
+
+- ndisc_flow_init(&fl, type, saddr, daddr,
+- dev->ifindex);
++ icmpv6_flow_init(sk, &fl, type, saddr, daddr, dev->ifindex);
+
+- dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output);
++ dst = icmp6_dst_alloc(dev, neigh, daddr);
+ if (!dst)
+ return;
+
+@@ -499,7 +484,7 @@ static void __ndisc_send(struct net_device *dev,
+ if (!skb) {
+ ND_PRINTK0(KERN_ERR
+ "ICMPv6 ND: %s() failed to allocate an skb.\n",
+- __FUNCTION__);
++ __func__);
+ dst_release(dst);
+ return;
+ }
+@@ -545,25 +530,28 @@ static void __ndisc_send(struct net_device *dev,
+ }
+
+ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
+- struct in6_addr *daddr, struct in6_addr *solicited_addr,
+- int router, int solicited, int override, int inc_opt)
++ const struct in6_addr *daddr,
++ const struct in6_addr *solicited_addr,
++ int router, int solicited, int override, int inc_opt)
+ {
+ struct in6_addr tmpaddr;
+ struct inet6_ifaddr *ifp;
+- struct in6_addr *src_addr;
++ const struct in6_addr *src_addr;
+ struct icmp6hdr icmp6h = {
+ .icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT,
+ };
+
+ /* for anycast or proxy, solicited_addr != src_addr */
+- ifp = ipv6_get_ifaddr(&init_net, solicited_addr, dev, 1);
++ ifp = ipv6_get_ifaddr(dev_net(dev), solicited_addr, dev, 1);
+ if (ifp) {
+ src_addr = solicited_addr;
+ if (ifp->flags & IFA_F_OPTIMISTIC)
+ override = 0;
+ in6_ifa_put(ifp);
+ } else {
+- if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr))
++ if (ipv6_dev_get_saddr(dev, daddr,
++ inet6_sk(dev_net(dev)->ipv6.ndisc_sk)->srcprefs,
++ &tmpaddr))
+ return;
+ src_addr = &tmpaddr;
+ }
+@@ -578,8 +566,8 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
+ }
+
+ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
+- struct in6_addr *solicit,
+- struct in6_addr *daddr, struct in6_addr *saddr)
++ const struct in6_addr *solicit,
++ const struct in6_addr *daddr, const struct in6_addr *saddr)
+ {
+ struct in6_addr addr_buf;
+ struct icmp6hdr icmp6h = {
+@@ -598,8 +586,8 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
+ !ipv6_addr_any(saddr) ? ND_OPT_SOURCE_LL_ADDR : 0);
+ }
+
+-void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
+- struct in6_addr *daddr)
++void ndisc_send_rs(struct net_device *dev, const struct in6_addr *saddr,
++ const struct in6_addr *daddr)
+ {
+ struct icmp6hdr icmp6h = {
+ .icmp6_type = NDISC_ROUTER_SOLICITATION,
+@@ -616,7 +604,7 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
+ * suppress the inclusion of the sllao.
+ */
+ if (send_sllao) {
+- struct inet6_ifaddr *ifp = ipv6_get_ifaddr(&init_net, saddr,
++ struct inet6_ifaddr *ifp = ipv6_get_ifaddr(dev_net(dev), saddr,
+ dev, 1);
+ if (ifp) {
+ if (ifp->flags & IFA_F_OPTIMISTIC) {
+@@ -654,7 +642,7 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
+ struct in6_addr *target = (struct in6_addr *)&neigh->primary_key;
+ int probes = atomic_read(&neigh->probes);
+
+- if (skb && ipv6_chk_addr(&init_net, &ipv6_hdr(skb)->saddr, dev, 1))
++ if (skb && ipv6_chk_addr(dev_net(dev), &ipv6_hdr(skb)->saddr, dev, 1))
+ saddr = &ipv6_hdr(skb)->saddr;
+
+ if ((probes -= neigh->parms->ucast_probes) < 0) {
+@@ -662,7 +650,7 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
+ ND_PRINTK1(KERN_DEBUG
+ "%s(): trying to ucast probe in NUD_INVALID: "
+ NIP6_FMT "\n",
+- __FUNCTION__,
++ __func__,
+ NIP6(*target));
+ }
+ ndisc_send_ns(dev, neigh, target, target, saddr);
+@@ -676,18 +664,19 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
+ }
+ }
+
+-static struct pneigh_entry *pndisc_check_router(struct net_device *dev,
+- struct in6_addr *addr, int *is_router)
++static int pndisc_is_router(const void *pkey,
++ struct net_device *dev)
+ {
+ struct pneigh_entry *n;
++ int ret = -1;
+
+ read_lock_bh(&nd_tbl.lock);
+- n = __pneigh_lookup(&nd_tbl, &init_net, addr, dev);
+- if (n != NULL)
+- *is_router = (n->flags & NTF_ROUTER);
++ n = __pneigh_lookup(&nd_tbl, dev_net(dev), pkey, dev);
++ if (n)
++ ret = !!(n->flags & NTF_ROUTER);
+ read_unlock_bh(&nd_tbl.lock);
+
+- return n;
++ return ret;
+ }
+
+ static void ndisc_recv_ns(struct sk_buff *skb)
+@@ -703,10 +692,9 @@ static void ndisc_recv_ns(struct sk_buff *skb)
+ struct inet6_ifaddr *ifp;
+ struct inet6_dev *idev = NULL;
+ struct neighbour *neigh;
+- struct pneigh_entry *pneigh = NULL;
+ int dad = ipv6_addr_any(saddr);
+ int inc;
+- int is_router = 0;
++ int is_router = -1;
+
+ if (ipv6_addr_is_multicast(&msg->target)) {
+ ND_PRINTK2(KERN_WARNING
+@@ -756,7 +744,8 @@ static void ndisc_recv_ns(struct sk_buff *skb)
+
+ inc = ipv6_addr_is_multicast(daddr);
+
+- if ((ifp = ipv6_get_ifaddr(&init_net, &msg->target, dev, 1)) != NULL) {
++ ifp = ipv6_get_ifaddr(dev_net(dev), &msg->target, dev, 1);
++ if (ifp) {
+
+ if (ifp->flags & (IFA_F_TENTATIVE|IFA_F_OPTIMISTIC)) {
+ if (dad) {
+@@ -801,11 +790,10 @@ static void ndisc_recv_ns(struct sk_buff *skb)
+ return;
+ }
+
+- if (ipv6_chk_acast_addr(dev, &msg->target) ||
++ if (ipv6_chk_acast_addr(dev_net(dev), dev, &msg->target) ||
+ (idev->cnf.forwarding &&
+ (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) &&
+- (pneigh = pndisc_check_router(dev, &msg->target,
+- &is_router)) != NULL)) {
++ (is_router = pndisc_is_router(&msg->target, dev)) >= 0)) {
+ if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) &&
+ skb->pkt_type != PACKET_HOST &&
+ inc != 0 &&
+@@ -826,13 +814,11 @@ static void ndisc_recv_ns(struct sk_buff *skb)
+ goto out;
+ }
+
+- is_router = !!(pneigh ? is_router : idev->cnf.forwarding);
++ if (is_router < 0)
++ is_router = !!idev->cnf.forwarding;
+
+ if (dad) {
+- struct in6_addr maddr;
+-
+- ipv6_addr_all_nodes(&maddr);
+- ndisc_send_na(dev, NULL, &maddr, &msg->target,
++ ndisc_send_na(dev, NULL, &in6addr_linklocal_allnodes, &msg->target,
+ is_router, 0, (ifp != NULL), 1);
+ goto out;
+ }
+@@ -914,7 +900,8 @@ static void ndisc_recv_na(struct sk_buff *skb)
+ return;
+ }
+ }
+- if ((ifp = ipv6_get_ifaddr(&init_net, &msg->target, dev, 1))) {
++ ifp = ipv6_get_ifaddr(dev_net(dev), &msg->target, dev, 1);
++ if (ifp) {
+ if (ifp->flags & IFA_F_TENTATIVE) {
+ addrconf_dad_failure(ifp);
+ return;
+@@ -945,7 +932,7 @@ static void ndisc_recv_na(struct sk_buff *skb)
+ */
+ if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) &&
+ ipv6_devconf.forwarding && ipv6_devconf.proxy_ndp &&
+- pneigh_lookup(&nd_tbl, &init_net, &msg->target, dev, 0)) {
++ pneigh_lookup(&nd_tbl, dev_net(dev), &msg->target, dev, 0)) {
+ /* XXX: idev->cnf.prixy_ndp */
+ goto out;
+ }
+@@ -1035,6 +1022,7 @@ static void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt)
+ struct sk_buff *skb;
+ struct nlmsghdr *nlh;
+ struct nduseroptmsg *ndmsg;
++ struct net *net = dev_net(ra->dev);
+ int err;
+ int base_size = NLMSG_ALIGN(sizeof(struct nduseroptmsg)
+ + (opt->nd_opt_len << 3));
+@@ -1064,7 +1052,7 @@ static void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt)
+ &ipv6_hdr(ra)->saddr);
+ nlmsg_end(skb, nlh);
+
+- err = rtnl_notify(skb, &init_net, 0, RTNLGRP_ND_USEROPT, NULL,
++ err = rtnl_notify(skb, net, 0, RTNLGRP_ND_USEROPT, NULL,
+ GFP_ATOMIC);
+ if (err < 0)
+ goto errout;
+@@ -1075,7 +1063,7 @@ nla_put_failure:
+ nlmsg_free(skb);
+ err = -EMSGSIZE;
+ errout:
+- rtnl_set_sk_err(&init_net, RTNLGRP_ND_USEROPT, err);
++ rtnl_set_sk_err(net, RTNLGRP_ND_USEROPT, err);
+ }
+
+ static void ndisc_router_discovery(struct sk_buff *skb)
+@@ -1104,6 +1092,14 @@ static void ndisc_router_discovery(struct sk_buff *skb)
+ return;
+ }
+
++#ifdef CONFIG_IPV6_NDISC_NODETYPE
++ if (skb->ndisc_nodetype == NDISC_NODETYPE_HOST) {
++ ND_PRINTK2(KERN_WARNING
++ "ICMPv6 RA: from host or unauthorized router\n");
++ return;
++ }
++#endif
++
+ /*
+ * set the RA_RECV flag in the interface
+ */
+@@ -1127,6 +1123,12 @@ static void ndisc_router_discovery(struct sk_buff *skb)
+ return;
+ }
+
++#ifdef CONFIG_IPV6_NDISC_NODETYPE
++ /* skip link-specific parameters from interior routers */
++ if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT)
++ goto skip_linkparms;
++#endif
++
+ if (in6_dev->if_flags & IF_RS_SENT) {
+ /*
+ * flag that an RA was received after an RS was sent
+@@ -1178,7 +1180,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
+ if (rt == NULL) {
+ ND_PRINTK0(KERN_ERR
+ "ICMPv6 RA: %s() failed to add default route.\n",
+- __FUNCTION__);
++ __func__);
+ in6_dev_put(in6_dev);
+ return;
+ }
+@@ -1187,7 +1189,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
+ if (neigh == NULL) {
+ ND_PRINTK0(KERN_ERR
+ "ICMPv6 RA: %s() got default router without neighbour.\n",
+- __FUNCTION__);
++ __func__);
+ dst_release(&rt->u.dst);
+ in6_dev_put(in6_dev);
+ return;
+@@ -1241,6 +1243,10 @@ skip_defrtr:
+ }
+ }
+
++#ifdef CONFIG_IPV6_NDISC_NODETYPE
++skip_linkparms:
++#endif
++
+ /*
+ * Process options.
+ */
+@@ -1272,7 +1278,13 @@ skip_defrtr:
+ for (p = ndopts.nd_opts_ri;
+ p;
+ p = ndisc_next_option(p, ndopts.nd_opts_ri_end)) {
+- if (((struct route_info *)p)->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen)
++ struct route_info *ri = (struct route_info *)p;
++#ifdef CONFIG_IPV6_NDISC_NODETYPE
++ if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT &&
++ ri->prefix_len == 0)
++ continue;
++#endif
++ if (ri->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen)
+ continue;
+ rt6_route_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3,
+ &ipv6_hdr(skb)->saddr);
+@@ -1280,6 +1292,12 @@ skip_defrtr:
+ }
+ #endif
+
++#ifdef CONFIG_IPV6_NDISC_NODETYPE
++ /* skip link-specific ndopts from interior routers */
++ if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT)
++ goto out;
++#endif
++
+ if (in6_dev->cnf.accept_ra_pinfo && ndopts.nd_opts_pi) {
+ struct nd_opt_hdr *p;
+ for (p = ndopts.nd_opts_pi;
+@@ -1343,6 +1361,16 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
+ int optlen;
+ u8 *lladdr = NULL;
+
++#ifdef CONFIG_IPV6_NDISC_NODETYPE
++ switch (skb->ndisc_nodetype) {
++ case NDISC_NODETYPE_HOST:
++ case NDISC_NODETYPE_NODEFAULT:
++ ND_PRINTK2(KERN_WARNING
++ "ICMPv6 Redirect: from host or unauthorized router\n");
++ return;
++ }
++#endif
++
+ if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) {
+ ND_PRINTK2(KERN_WARNING
+ "ICMPv6 Redirect: source address is not link-local.\n");
+@@ -1418,15 +1446,16 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
+ }
+
+ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
+- struct in6_addr *target)
++ const struct in6_addr *target)
+ {
+- struct sock *sk = ndisc_socket->sk;
++ struct net_device *dev = skb->dev;
++ struct net *net = dev_net(dev);
++ struct sock *sk = net->ipv6.ndisc_sk;
+ int len = sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr);
+ struct sk_buff *buff;
+ struct icmp6hdr *icmph;
+ struct in6_addr saddr_buf;
+ struct in6_addr *addrp;
+- struct net_device *dev;
+ struct rt6_info *rt;
+ struct dst_entry *dst;
+ struct inet6_dev *idev;
+@@ -1436,8 +1465,6 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
+ int err;
+ u8 ha_buf[MAX_ADDR_LEN], *ha = NULL;
+
+- dev = skb->dev;
+-
+ if (ipv6_get_lladdr(dev, &saddr_buf, IFA_F_TENTATIVE)) {
+ ND_PRINTK2(KERN_WARNING
+ "ICMPv6 Redirect: no link-local address on %s\n",
+@@ -1452,10 +1479,10 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
+ return;
+ }
+
+- ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &ipv6_hdr(skb)->saddr,
+- dev->ifindex);
++ icmpv6_flow_init(sk, &fl, NDISC_REDIRECT,
++ &saddr_buf, &ipv6_hdr(skb)->saddr, dev->ifindex);
+
+- dst = ip6_route_output(NULL, &fl);
++ dst = ip6_route_output(net, NULL, &fl);
+ if (dst == NULL)
+ return;
+
+@@ -1499,12 +1526,11 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
+ if (buff == NULL) {
+ ND_PRINTK0(KERN_ERR
+ "ICMPv6 Redirect: %s() failed to allocate an skb.\n",
+- __FUNCTION__);
++ __func__);
+ dst_release(dst);
+ return;
+ }
+
+-
+ skb_reserve(buff, LL_RESERVED_SPACE(dev));
+ ip6_nd_hdr(sk, buff, dev, &saddr_buf, &ipv6_hdr(skb)->saddr,
+ IPPROTO_ICMPV6, len);
+@@ -1625,18 +1651,16 @@ int ndisc_rcv(struct sk_buff *skb)
+ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
+ {
+ struct net_device *dev = ptr;
+-
+- if (dev->nd_net != &init_net)
+- return NOTIFY_DONE;
++ struct net *net = dev_net(dev);
+
+ switch (event) {
+ case NETDEV_CHANGEADDR:
+ neigh_changeaddr(&nd_tbl, dev);
+- fib6_run_gc(~0UL);
++ fib6_run_gc(~0UL, net);
+ break;
+ case NETDEV_DOWN:
+ neigh_ifdown(&nd_tbl, dev);
+- fib6_run_gc(~0UL);
++ fib6_run_gc(~0UL, net);
+ break;
+ default:
+ break;
+@@ -1745,44 +1769,74 @@ static int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, int __user *name,
+
+ #endif
+
+-int __init ndisc_init(struct net_proto_family *ops)
++static int ndisc_net_init(struct net *net)
+ {
+ struct ipv6_pinfo *np;
+ struct sock *sk;
+ int err;
+
+- err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &ndisc_socket);
++ err = inet_ctl_sock_create(&sk, PF_INET6,
++ SOCK_RAW, IPPROTO_ICMPV6, net);
+ if (err < 0) {
+ ND_PRINTK0(KERN_ERR
+ "ICMPv6 NDISC: Failed to initialize the control socket (err %d).\n",
+ err);
+- ndisc_socket = NULL; /* For safety. */
+ return err;
+ }
+
+- sk = ndisc_socket->sk;
++ net->ipv6.ndisc_sk = sk;
++
+ np = inet6_sk(sk);
+- sk->sk_allocation = GFP_ATOMIC;
+ np->hop_limit = 255;
+ /* Do not loopback ndisc messages */
+ np->mc_loop = 0;
+- sk->sk_prot->unhash(sk);
+
++ return 0;
++}
++
++static void ndisc_net_exit(struct net *net)
++{
++ inet_ctl_sock_destroy(net->ipv6.ndisc_sk);
++}
++
++static struct pernet_operations ndisc_net_ops = {
++ .init = ndisc_net_init,
++ .exit = ndisc_net_exit,
++};
++
++int __init ndisc_init(void)
++{
++ int err;
++
++ err = register_pernet_subsys(&ndisc_net_ops);
++ if (err)
++ return err;
+ /*
+ * Initialize the neighbour table
+ */
+-
+ neigh_table_init(&nd_tbl);
+
+ #ifdef CONFIG_SYSCTL
+- neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6, NET_IPV6_NEIGH,
+- "ipv6",
+- &ndisc_ifinfo_sysctl_change,
+- &ndisc_ifinfo_sysctl_strategy);
++ err = neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6,
++ NET_IPV6_NEIGH, "ipv6",
++ &ndisc_ifinfo_sysctl_change,
++ &ndisc_ifinfo_sysctl_strategy);
++ if (err)
++ goto out_unregister_pernet;
+ #endif
++ err = register_netdevice_notifier(&ndisc_netdev_notifier);
++ if (err)
++ goto out_unregister_sysctl;
++out:
++ return err;
+
+- register_netdevice_notifier(&ndisc_netdev_notifier);
+- return 0;
++out_unregister_sysctl:
++#ifdef CONFIG_SYSCTL
++ neigh_sysctl_unregister(&nd_tbl.parms);
++out_unregister_pernet:
++#endif
++ unregister_pernet_subsys(&ndisc_net_ops);
++ goto out;
+ }
+
+ void ndisc_cleanup(void)
+@@ -1792,6 +1846,5 @@ void ndisc_cleanup(void)
+ neigh_sysctl_unregister(&nd_tbl.parms);
+ #endif
+ neigh_table_clear(&nd_tbl);
+- sock_release(ndisc_socket);
+- ndisc_socket = NULL; /* For safety. */
++ unregister_pernet_subsys(&ndisc_net_ops);
+ }
+diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
+index 2e06724..8c6c5e7 100644
+--- a/net/ipv6/netfilter.c
++++ b/net/ipv6/netfilter.c
+@@ -23,7 +23,7 @@ int ip6_route_me_harder(struct sk_buff *skb)
+ .saddr = iph->saddr, } },
+ };
+
+- dst = ip6_route_output(skb->sk, &fl);
++ dst = ip6_route_output(&init_net, skb->sk, &fl);
+
+ #ifdef CONFIG_XFRM
+ if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
+@@ -86,7 +86,7 @@ static int nf_ip6_reroute(struct sk_buff *skb,
+
+ static int nf_ip6_route(struct dst_entry **dst, struct flowi *fl)
+ {
+- *dst = ip6_route_output(NULL, fl);
++ *dst = ip6_route_output(&init_net, NULL, fl);
+ return (*dst)->error;
+ }
+
+@@ -121,16 +121,44 @@ __sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
+ }
+ return csum;
+ }
+-
+ EXPORT_SYMBOL(nf_ip6_checksum);
+
++static __sum16 nf_ip6_checksum_partial(struct sk_buff *skb, unsigned int hook,
++ unsigned int dataoff, unsigned int len,
++ u_int8_t protocol)
++{
++ struct ipv6hdr *ip6h = ipv6_hdr(skb);
++ __wsum hsum;
++ __sum16 csum = 0;
++
++ switch (skb->ip_summed) {
++ case CHECKSUM_COMPLETE:
++ if (len == skb->len - dataoff)
++ return nf_ip6_checksum(skb, hook, dataoff, protocol);
++ /* fall through */
++ case CHECKSUM_NONE:
++ hsum = skb_checksum(skb, 0, dataoff, 0);
++ skb->csum = ~csum_unfold(csum_ipv6_magic(&ip6h->saddr,
++ &ip6h->daddr,
++ skb->len - dataoff,
++ protocol,
++ csum_sub(0, hsum)));
++ skb->ip_summed = CHECKSUM_NONE;
++ csum = __skb_checksum_complete_head(skb, dataoff + len);
++ if (!csum)
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++ }
++ return csum;
++};
++
+ static const struct nf_afinfo nf_ip6_afinfo = {
+- .family = AF_INET6,
+- .checksum = nf_ip6_checksum,
+- .route = nf_ip6_route,
+- .saveroute = nf_ip6_saveroute,
+- .reroute = nf_ip6_reroute,
+- .route_key_size = sizeof(struct ip6_rt_info),
++ .family = AF_INET6,
++ .checksum = nf_ip6_checksum,
++ .checksum_partial = nf_ip6_checksum_partial,
++ .route = nf_ip6_route,
++ .saveroute = nf_ip6_saveroute,
++ .reroute = nf_ip6_reroute,
++ .route_key_size = sizeof(struct ip6_rt_info),
+ };
+
+ int __init ipv6_netfilter_init(void)
+diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
+index 8d366f7..92a36c9 100644
+--- a/net/ipv6/netfilter/ip6_queue.c
++++ b/net/ipv6/netfilter/ip6_queue.c
+@@ -484,7 +484,7 @@ ipq_rcv_dev_event(struct notifier_block *this,
+ {
+ struct net_device *dev = ptr;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ /* Drop any packets associated with the downed device */
+diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
+index bf9bb6e..0b4557e 100644
+--- a/net/ipv6/netfilter/ip6_tables.c
++++ b/net/ipv6/netfilter/ip6_tables.c
+@@ -55,7 +55,7 @@ MODULE_DESCRIPTION("IPv6 packet filter");
+ do { \
+ if (!(x)) \
+ printk("IP_NF_ASSERT: %s:%s:%u\n", \
+- __FUNCTION__, __FILE__, __LINE__); \
++ __func__, __FILE__, __LINE__); \
+ } while(0)
+ #else
+ #define IP_NF_ASSERT(x)
+@@ -325,7 +325,7 @@ static void trace_packet(struct sk_buff *skb,
+ struct ip6t_entry *e)
+ {
+ void *table_base;
+- struct ip6t_entry *root;
++ const struct ip6t_entry *root;
+ char *hookname, *chainname, *comment;
+ unsigned int rulenum = 0;
+
+@@ -952,7 +952,7 @@ static struct xt_counters *alloc_counters(struct xt_table *table)
+ {
+ unsigned int countersize;
+ struct xt_counters *counters;
+- struct xt_table_info *private = table->private;
++ const struct xt_table_info *private = table->private;
+
+ /* We need atomic snapshot of counters: rest doesn't change
+ (other than comefrom, which userspace doesn't care
+@@ -979,9 +979,9 @@ copy_entries_to_user(unsigned int total_size,
+ unsigned int off, num;
+ struct ip6t_entry *e;
+ struct xt_counters *counters;
+- struct xt_table_info *private = table->private;
++ const struct xt_table_info *private = table->private;
+ int ret = 0;
+- void *loc_cpu_entry;
++ const void *loc_cpu_entry;
+
+ counters = alloc_counters(table);
+ if (IS_ERR(counters))
+@@ -1001,8 +1001,8 @@ copy_entries_to_user(unsigned int total_size,
+ /* ... then go back and fix counters and names */
+ for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
+ unsigned int i;
+- struct ip6t_entry_match *m;
+- struct ip6t_entry_target *t;
++ const struct ip6t_entry_match *m;
++ const struct ip6t_entry_target *t;
+
+ e = (struct ip6t_entry *)(loc_cpu_entry + off);
+ if (copy_to_user(userptr + off
+@@ -1142,7 +1142,7 @@ static int get_info(struct net *net, void __user *user, int *len, int compat)
+ "ip6table_%s", name);
+ if (t && !IS_ERR(t)) {
+ struct ip6t_getinfo info;
+- struct xt_table_info *private = t->private;
++ const struct xt_table_info *private = t->private;
+
+ #ifdef CONFIG_COMPAT
+ if (compat) {
+@@ -1206,7 +1206,7 @@ get_entries(struct net *net, struct ip6t_get_entries __user *uptr, int *len)
+ else {
+ duprintf("get_entries: I've got %u not %u!\n",
+ private->size, get.size);
+- ret = -EINVAL;
++ ret = -EAGAIN;
+ }
+ module_put(t->me);
+ xt_table_unlock(t);
+@@ -1225,7 +1225,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
+ struct xt_table *t;
+ struct xt_table_info *oldinfo;
+ struct xt_counters *counters;
+- void *loc_cpu_old_entry;
++ const void *loc_cpu_old_entry;
+
+ ret = 0;
+ counters = vmalloc_node(num_counters * sizeof(struct xt_counters),
+@@ -1369,9 +1369,9 @@ do_add_counters(struct net *net, void __user *user, unsigned int len,
+ int size;
+ void *ptmp;
+ struct xt_table *t;
+- struct xt_table_info *private;
++ const struct xt_table_info *private;
+ int ret = 0;
+- void *loc_cpu_entry;
++ const void *loc_cpu_entry;
+ #ifdef CONFIG_COMPAT
+ struct compat_xt_counters_info compat_tmp;
+
+@@ -1879,11 +1879,11 @@ compat_do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user,
+
+ switch (cmd) {
+ case IP6T_SO_SET_REPLACE:
+- ret = compat_do_replace(sk->sk_net, user, len);
++ ret = compat_do_replace(sock_net(sk), user, len);
+ break;
+
+ case IP6T_SO_SET_ADD_COUNTERS:
+- ret = do_add_counters(sk->sk_net, user, len, 1);
++ ret = do_add_counters(sock_net(sk), user, len, 1);
+ break;
+
+ default:
+@@ -1905,11 +1905,11 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
+ void __user *userptr)
+ {
+ struct xt_counters *counters;
+- struct xt_table_info *private = table->private;
++ const struct xt_table_info *private = table->private;
+ void __user *pos;
+ unsigned int size;
+ int ret = 0;
+- void *loc_cpu_entry;
++ const void *loc_cpu_entry;
+ unsigned int i = 0;
+
+ counters = alloc_counters(table);
+@@ -1956,7 +1956,7 @@ compat_get_entries(struct net *net, struct compat_ip6t_get_entries __user *uptr,
+ xt_compat_lock(AF_INET6);
+ t = xt_find_table_lock(net, AF_INET6, get.name);
+ if (t && !IS_ERR(t)) {
+- struct xt_table_info *private = t->private;
++ const struct xt_table_info *private = t->private;
+ struct xt_table_info info;
+ duprintf("t->private->number = %u\n", private->number);
+ ret = compat_table_info(private, &info);
+@@ -1966,7 +1966,7 @@ compat_get_entries(struct net *net, struct compat_ip6t_get_entries __user *uptr,
+ } else if (!ret) {
+ duprintf("compat_get_entries: I've got %u not %u!\n",
+ private->size, get.size);
+- ret = -EINVAL;
++ ret = -EAGAIN;
+ }
+ xt_compat_flush_offsets(AF_INET6);
+ module_put(t->me);
+@@ -1990,10 +1990,10 @@ compat_do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
+
+ switch (cmd) {
+ case IP6T_SO_GET_INFO:
+- ret = get_info(sk->sk_net, user, len, 1);
++ ret = get_info(sock_net(sk), user, len, 1);
+ break;
+ case IP6T_SO_GET_ENTRIES:
+- ret = compat_get_entries(sk->sk_net, user, len);
++ ret = compat_get_entries(sock_net(sk), user, len);
+ break;
+ default:
+ ret = do_ip6t_get_ctl(sk, cmd, user, len);
+@@ -2012,11 +2012,11 @@ do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
+
+ switch (cmd) {
+ case IP6T_SO_SET_REPLACE:
+- ret = do_replace(sk->sk_net, user, len);
++ ret = do_replace(sock_net(sk), user, len);
+ break;
+
+ case IP6T_SO_SET_ADD_COUNTERS:
+- ret = do_add_counters(sk->sk_net, user, len, 0);
++ ret = do_add_counters(sock_net(sk), user, len, 0);
+ break;
+
+ default:
+@@ -2037,11 +2037,11 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
+
+ switch (cmd) {
+ case IP6T_SO_GET_INFO:
+- ret = get_info(sk->sk_net, user, len, 0);
++ ret = get_info(sock_net(sk), user, len, 0);
+ break;
+
+ case IP6T_SO_GET_ENTRIES:
+- ret = get_entries(sk->sk_net, user, len);
++ ret = get_entries(sock_net(sk), user, len);
+ break;
+
+ case IP6T_SO_GET_REVISION_MATCH:
+@@ -2155,7 +2155,8 @@ icmp6_match(const struct sk_buff *skb,
+ unsigned int protoff,
+ bool *hotdrop)
+ {
+- struct icmp6hdr _icmph, *ic;
++ const struct icmp6hdr *ic;
++ struct icmp6hdr _icmph;
+ const struct ip6t_icmp *icmpinfo = matchinfo;
+
+ /* Must not be a fragment. */
+diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
+index 86a6138..3a23169 100644
+--- a/net/ipv6/netfilter/ip6t_LOG.c
++++ b/net/ipv6/netfilter/ip6t_LOG.c
+@@ -363,11 +363,15 @@ static void dump_packet(const struct nf_loginfo *info,
+ if ((logflags & IP6T_LOG_UID) && recurse && skb->sk) {
+ read_lock_bh(&skb->sk->sk_callback_lock);
+ if (skb->sk->sk_socket && skb->sk->sk_socket->file)
+- printk("UID=%u GID=%u",
++ printk("UID=%u GID=%u ",
+ skb->sk->sk_socket->file->f_uid,
+ skb->sk->sk_socket->file->f_gid);
+ read_unlock_bh(&skb->sk->sk_callback_lock);
+ }
++
++ /* Max length: 16 "MARK=0xFFFFFFFF " */
++ if (!recurse && skb->mark)
++ printk("MARK=0x%x ", skb->mark);
+ }
+
+ static struct nf_loginfo default_loginfo = {
+diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
+index b23baa6..44c8d65 100644
+--- a/net/ipv6/netfilter/ip6t_REJECT.c
++++ b/net/ipv6/netfilter/ip6t_REJECT.c
+@@ -41,7 +41,8 @@ static void send_reset(struct sk_buff *oldskb)
+ struct tcphdr otcph, *tcph;
+ unsigned int otcplen, hh_len;
+ int tcphoff, needs_ack;
+- struct ipv6hdr *oip6h = ipv6_hdr(oldskb), *ip6h;
++ const struct ipv6hdr *oip6h = ipv6_hdr(oldskb);
++ struct ipv6hdr *ip6h;
+ struct dst_entry *dst = NULL;
+ u8 proto;
+ struct flowi fl;
+@@ -93,7 +94,7 @@ static void send_reset(struct sk_buff *oldskb)
+ fl.fl_ip_sport = otcph.dest;
+ fl.fl_ip_dport = otcph.source;
+ security_skb_classify_flow(oldskb, &fl);
+- dst = ip6_route_output(NULL, &fl);
++ dst = ip6_route_output(&init_net, NULL, &fl);
+ if (dst == NULL)
+ return;
+ if (dst->error || xfrm_lookup(&dst, &fl, NULL, 0))
+@@ -177,7 +178,7 @@ reject_tg6(struct sk_buff *skb, const struct net_device *in,
+ {
+ const struct ip6t_reject_info *reject = targinfo;
+
+- pr_debug("%s: medium point\n", __FUNCTION__);
++ pr_debug("%s: medium point\n", __func__);
+ /* WARNING: This code causes reentry within ip6tables.
+ This means that the ip6tables jump stack is now crap. We
+ must return an absolute verdict. --RR */
+diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c
+index 3a94017..317a896 100644
+--- a/net/ipv6/netfilter/ip6t_ipv6header.c
++++ b/net/ipv6/netfilter/ip6t_ipv6header.c
+@@ -49,7 +49,8 @@ ipv6header_mt6(const struct sk_buff *skb, const struct net_device *in,
+ temp = 0;
+
+ while (ip6t_ext_hdr(nexthdr)) {
+- struct ipv6_opt_hdr _hdr, *hp;
++ const struct ipv6_opt_hdr *hp;
++ struct ipv6_opt_hdr _hdr;
+ int hdrlen;
+
+ /* Is there enough space for the next ext header? */
+diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
+index 12a9efe..81aaf7a 100644
+--- a/net/ipv6/netfilter/ip6t_rt.c
++++ b/net/ipv6/netfilter/ip6t_rt.c
+@@ -110,7 +110,8 @@ rt_mt6(const struct sk_buff *skb, const struct net_device *in,
+ !!(rtinfo->invflags & IP6T_RT_INV_TYP)));
+
+ if (ret && (rtinfo->flags & IP6T_RT_RES)) {
+- u_int32_t *rp, _reserved;
++ const u_int32_t *rp;
++ u_int32_t _reserved;
+ rp = skb_header_pointer(skb,
+ ptr + offsetof(struct rt0_hdr,
+ reserved),
+diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
+index 2d9cd09..f979e48 100644
+--- a/net/ipv6/netfilter/ip6table_filter.c
++++ b/net/ipv6/netfilter/ip6table_filter.c
+@@ -54,7 +54,7 @@ static struct
+ static struct xt_table packet_filter = {
+ .name = "filter",
+ .valid_hooks = FILTER_VALID_HOOKS,
+- .lock = RW_LOCK_UNLOCKED,
++ .lock = __RW_LOCK_UNLOCKED(packet_filter.lock),
+ .me = THIS_MODULE,
+ .af = AF_INET6,
+ };
+diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
+index 035343a..27a5e8b 100644
+--- a/net/ipv6/netfilter/ip6table_mangle.c
++++ b/net/ipv6/netfilter/ip6table_mangle.c
+@@ -60,7 +60,7 @@ static struct
+ static struct xt_table packet_mangler = {
+ .name = "mangle",
+ .valid_hooks = MANGLE_VALID_HOOKS,
+- .lock = RW_LOCK_UNLOCKED,
++ .lock = __RW_LOCK_UNLOCKED(packet_mangler.lock),
+ .me = THIS_MODULE,
+ .af = AF_INET6,
+ };
+diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
+index 5cd8420..92b9107 100644
+--- a/net/ipv6/netfilter/ip6table_raw.c
++++ b/net/ipv6/netfilter/ip6table_raw.c
+@@ -38,7 +38,7 @@ static struct
+ static struct xt_table packet_raw = {
+ .name = "raw",
+ .valid_hooks = RAW_VALID_HOOKS,
+- .lock = RW_LOCK_UNLOCKED,
++ .lock = __RW_LOCK_UNLOCKED(packet_raw.lock),
+ .me = THIS_MODULE,
+ .af = AF_INET6,
+ };
+diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+index 3717bdf..85050c0 100644
+--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
++++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+@@ -27,8 +27,8 @@
+ #include <net/netfilter/nf_conntrack_l3proto.h>
+ #include <net/netfilter/nf_conntrack_core.h>
+
+-static int ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
+- struct nf_conntrack_tuple *tuple)
++static bool ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
++ struct nf_conntrack_tuple *tuple)
+ {
+ const u_int32_t *ap;
+ u_int32_t _addrs[8];
+@@ -36,21 +36,21 @@ static int ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
+ ap = skb_header_pointer(skb, nhoff + offsetof(struct ipv6hdr, saddr),
+ sizeof(_addrs), _addrs);
+ if (ap == NULL)
+- return 0;
++ return false;
+
+ memcpy(tuple->src.u3.ip6, ap, sizeof(tuple->src.u3.ip6));
+ memcpy(tuple->dst.u3.ip6, ap + 4, sizeof(tuple->dst.u3.ip6));
+
+- return 1;
++ return true;
+ }
+
+-static int ipv6_invert_tuple(struct nf_conntrack_tuple *tuple,
+- const struct nf_conntrack_tuple *orig)
++static bool ipv6_invert_tuple(struct nf_conntrack_tuple *tuple,
++ const struct nf_conntrack_tuple *orig)
+ {
+ memcpy(tuple->src.u3.ip6, orig->dst.u3.ip6, sizeof(tuple->src.u3.ip6));
+ memcpy(tuple->dst.u3.ip6, orig->src.u3.ip6, sizeof(tuple->dst.u3.ip6));
+
+- return 1;
++ return true;
+ }
+
+ static int ipv6_print_tuple(struct seq_file *s,
+diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+index 0897d0f..ee713b0 100644
+--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
++++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+@@ -28,21 +28,21 @@
+
+ static unsigned long nf_ct_icmpv6_timeout __read_mostly = 30*HZ;
+
+-static int icmpv6_pkt_to_tuple(const struct sk_buff *skb,
+- unsigned int dataoff,
+- struct nf_conntrack_tuple *tuple)
++static bool icmpv6_pkt_to_tuple(const struct sk_buff *skb,
++ unsigned int dataoff,
++ struct nf_conntrack_tuple *tuple)
+ {
+ const struct icmp6hdr *hp;
+ struct icmp6hdr _hdr;
+
+ hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
+ if (hp == NULL)
+- return 0;
++ return false;
+ tuple->dst.u.icmp.type = hp->icmp6_type;
+ tuple->src.u.icmp.id = hp->icmp6_identifier;
+ tuple->dst.u.icmp.code = hp->icmp6_code;
+
+- return 1;
++ return true;
+ }
+
+ /* Add 1; spaces filled with 0. */
+@@ -53,17 +53,17 @@ static const u_int8_t invmap[] = {
+ [ICMPV6_NI_REPLY - 128] = ICMPV6_NI_REPLY +1
+ };
+
+-static int icmpv6_invert_tuple(struct nf_conntrack_tuple *tuple,
+- const struct nf_conntrack_tuple *orig)
++static bool icmpv6_invert_tuple(struct nf_conntrack_tuple *tuple,
++ const struct nf_conntrack_tuple *orig)
+ {
+ int type = orig->dst.u.icmp.type - 128;
+ if (type < 0 || type >= sizeof(invmap) || !invmap[type])
+- return 0;
++ return false;
+
+ tuple->src.u.icmp.id = orig->src.u.icmp.id;
+ tuple->dst.u.icmp.type = invmap[type] - 1;
+ tuple->dst.u.icmp.code = orig->dst.u.icmp.code;
+- return 1;
++ return true;
+ }
+
+ /* Print out the per-protocol part of the tuple. */
+@@ -102,9 +102,8 @@ static int icmpv6_packet(struct nf_conn *ct,
+ }
+
+ /* Called when a new connection for this protocol found. */
+-static int icmpv6_new(struct nf_conn *ct,
+- const struct sk_buff *skb,
+- unsigned int dataoff)
++static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb,
++ unsigned int dataoff)
+ {
+ static const u_int8_t valid_new[] = {
+ [ICMPV6_ECHO_REQUEST - 128] = 1,
+@@ -116,11 +115,11 @@ static int icmpv6_new(struct nf_conn *ct,
+ /* Can't create a new ICMPv6 `conn' with this. */
+ pr_debug("icmpv6: can't create new conn with type %u\n",
+ type + 128);
+- NF_CT_DUMP_TUPLE(&ct->tuplehash[0].tuple);
+- return 0;
++ nf_ct_dump_tuple_ipv6(&ct->tuplehash[0].tuple);
++ return false;
+ }
+ atomic_set(&ct->proto.icmp.count, 0);
+- return 1;
++ return true;
+ }
+
+ static int
+diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
+index 24c0d03..2dccad4 100644
+--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
++++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
+@@ -103,8 +103,8 @@ struct ctl_table nf_ct_ipv6_sysctl_table[] = {
+ };
+ #endif
+
+-static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr,
+- struct in6_addr *daddr)
++static unsigned int ip6qhashfn(__be32 id, const struct in6_addr *saddr,
++ const struct in6_addr *daddr)
+ {
+ u32 a, b, c;
+
+@@ -132,7 +132,7 @@ static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr,
+
+ static unsigned int nf_hashfn(struct inet_frag_queue *q)
+ {
+- struct nf_ct_frag6_queue *nq;
++ const struct nf_ct_frag6_queue *nq;
+
+ nq = container_of(q, struct nf_ct_frag6_queue, q);
+ return ip6qhashfn(nq->id, &nq->saddr, &nq->daddr);
+@@ -185,7 +185,7 @@ static void nf_ct_frag6_expire(unsigned long data)
+
+ spin_lock(&fq->q.lock);
+
+- if (fq->q.last_in & COMPLETE)
++ if (fq->q.last_in & INET_FRAG_COMPLETE)
+ goto out;
+
+ fq_kill(fq);
+@@ -222,12 +222,12 @@ oom:
+
+
+ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
+- struct frag_hdr *fhdr, int nhoff)
++ const struct frag_hdr *fhdr, int nhoff)
+ {
+ struct sk_buff *prev, *next;
+ int offset, end;
+
+- if (fq->q.last_in & COMPLETE) {
++ if (fq->q.last_in & INET_FRAG_COMPLETE) {
+ pr_debug("Allready completed\n");
+ goto err;
+ }
+@@ -254,11 +254,11 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
+ * or have different end, the segment is corrupted.
+ */
+ if (end < fq->q.len ||
+- ((fq->q.last_in & LAST_IN) && end != fq->q.len)) {
++ ((fq->q.last_in & INET_FRAG_LAST_IN) && end != fq->q.len)) {
+ pr_debug("already received last fragment\n");
+ goto err;
+ }
+- fq->q.last_in |= LAST_IN;
++ fq->q.last_in |= INET_FRAG_LAST_IN;
+ fq->q.len = end;
+ } else {
+ /* Check if the fragment is rounded to 8 bytes.
+@@ -273,7 +273,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
+ }
+ if (end > fq->q.len) {
+ /* Some bits beyond end -> corruption. */
+- if (fq->q.last_in & LAST_IN) {
++ if (fq->q.last_in & INET_FRAG_LAST_IN) {
+ pr_debug("last packet already reached.\n");
+ goto err;
+ }
+@@ -385,7 +385,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
+ */
+ if (offset == 0) {
+ fq->nhoffset = nhoff;
+- fq->q.last_in |= FIRST_IN;
++ fq->q.last_in |= INET_FRAG_FIRST_IN;
+ }
+ write_lock(&nf_frags.lock);
+ list_move_tail(&fq->q.lru_list, &nf_init_frags.lru_list);
+@@ -647,7 +647,8 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb)
+ goto ret_orig;
+ }
+
+- if (fq->q.last_in == (FIRST_IN|LAST_IN) && fq->q.meat == fq->q.len) {
++ if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) &&
++ fq->q.meat == fq->q.len) {
+ ret_skb = nf_ct_frag6_reasm(fq, dev);
+ if (ret_skb == NULL)
+ pr_debug("Can't reassemble fragmented packets\n");
+diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
+index 199ef37..ca8b82f 100644
+--- a/net/ipv6/proc.c
++++ b/net/ipv6/proc.c
+@@ -35,16 +35,18 @@ static struct proc_dir_entry *proc_net_devsnmp6;
+
+ static int sockstat6_seq_show(struct seq_file *seq, void *v)
+ {
++ struct net *net = seq->private;
++
+ seq_printf(seq, "TCP6: inuse %d\n",
+- sock_prot_inuse_get(&tcpv6_prot));
++ sock_prot_inuse_get(net, &tcpv6_prot));
+ seq_printf(seq, "UDP6: inuse %d\n",
+- sock_prot_inuse_get(&udpv6_prot));
++ sock_prot_inuse_get(net, &udpv6_prot));
+ seq_printf(seq, "UDPLITE6: inuse %d\n",
+- sock_prot_inuse_get(&udplitev6_prot));
++ sock_prot_inuse_get(net, &udplitev6_prot));
+ seq_printf(seq, "RAW6: inuse %d\n",
+- sock_prot_inuse_get(&rawv6_prot));
++ sock_prot_inuse_get(net, &rawv6_prot));
+ seq_printf(seq, "FRAG6: inuse %d memory %d\n",
+- ip6_frag_nqueues(&init_net), ip6_frag_mem(&init_net));
++ ip6_frag_nqueues(net), ip6_frag_mem(net));
+ return 0;
+ }
+
+@@ -183,7 +185,32 @@ static int snmp6_seq_show(struct seq_file *seq, void *v)
+
+ static int sockstat6_seq_open(struct inode *inode, struct file *file)
+ {
+- return single_open(file, sockstat6_seq_show, NULL);
++ int err;
++ struct net *net;
++
++ err = -ENXIO;
++ net = get_proc_net(inode);
++ if (net == NULL)
++ goto err_net;
++
++ err = single_open(file, sockstat6_seq_show, net);
++ if (err < 0)
++ goto err_open;
++
++ return 0;
++
++err_open:
++ put_net(net);
++err_net:
++ return err;
++}
++
++static int sockstat6_seq_release(struct inode *inode, struct file *file)
++{
++ struct net *net = ((struct seq_file *)file->private_data)->private;
++
++ put_net(net);
++ return single_release(inode, file);
+ }
+
+ static const struct file_operations sockstat6_seq_fops = {
+@@ -191,7 +218,7 @@ static const struct file_operations sockstat6_seq_fops = {
+ .open = sockstat6_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = single_release,
++ .release = sockstat6_seq_release,
+ };
+
+ static int snmp6_seq_open(struct inode *inode, struct file *file)
+@@ -214,6 +241,9 @@ int snmp6_register_dev(struct inet6_dev *idev)
+ if (!idev || !idev->dev)
+ return -EINVAL;
+
++ if (dev_net(idev->dev) != &init_net)
++ return 0;
++
+ if (!proc_net_devsnmp6)
+ return -ENOENT;
+
+@@ -240,27 +270,45 @@ int snmp6_unregister_dev(struct inet6_dev *idev)
+ return 0;
+ }
+
++static int ipv6_proc_init_net(struct net *net)
++{
++ if (!proc_net_fops_create(net, "sockstat6", S_IRUGO,
++ &sockstat6_seq_fops))
++ return -ENOMEM;
++ return 0;
++}
++
++static void ipv6_proc_exit_net(struct net *net)
++{
++ proc_net_remove(net, "sockstat6");
++}
++
++static struct pernet_operations ipv6_proc_ops = {
++ .init = ipv6_proc_init_net,
++ .exit = ipv6_proc_exit_net,
++};
++
+ int __init ipv6_misc_proc_init(void)
+ {
+ int rc = 0;
+
++ if (register_pernet_subsys(&ipv6_proc_ops))
++ goto proc_net_fail;
++
+ if (!proc_net_fops_create(&init_net, "snmp6", S_IRUGO, &snmp6_seq_fops))
+ goto proc_snmp6_fail;
+
+ proc_net_devsnmp6 = proc_mkdir("dev_snmp6", init_net.proc_net);
+ if (!proc_net_devsnmp6)
+ goto proc_dev_snmp6_fail;
+-
+- if (!proc_net_fops_create(&init_net, "sockstat6", S_IRUGO, &sockstat6_seq_fops))
+- goto proc_sockstat6_fail;
+ out:
+ return rc;
+
+-proc_sockstat6_fail:
+- proc_net_remove(&init_net, "dev_snmp6");
+ proc_dev_snmp6_fail:
+ proc_net_remove(&init_net, "snmp6");
+ proc_snmp6_fail:
++ unregister_pernet_subsys(&ipv6_proc_ops);
++proc_net_fail:
+ rc = -ENOMEM;
+ goto out;
+ }
+@@ -270,5 +318,6 @@ void ipv6_misc_proc_exit(void)
+ proc_net_remove(&init_net, "sockstat6");
+ proc_net_remove(&init_net, "dev_snmp6");
+ proc_net_remove(&init_net, "snmp6");
++ unregister_pernet_subsys(&ipv6_proc_ops);
+ }
+
+diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
+index 0a6fbc1..396f0ea 100644
+--- a/net/ipv6/raw.c
++++ b/net/ipv6/raw.c
+@@ -53,6 +53,7 @@
+ #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+ #include <net/mip6.h>
+ #endif
++#include <linux/mroute6.h>
+
+ #include <net/raw.h>
+ #include <net/rawv6.h>
+@@ -62,20 +63,9 @@
+ #include <linux/seq_file.h>
+
+ static struct raw_hashinfo raw_v6_hashinfo = {
+- .lock = __RW_LOCK_UNLOCKED(),
++ .lock = __RW_LOCK_UNLOCKED(raw_v6_hashinfo.lock),
+ };
+
+-static void raw_v6_hash(struct sock *sk)
+-{
+- raw_hash_sk(sk, &raw_v6_hashinfo);
+-}
+-
+-static void raw_v6_unhash(struct sock *sk)
+-{
+- raw_unhash_sk(sk, &raw_v6_hashinfo);
+-}
+-
+-
+ static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
+ unsigned short num, struct in6_addr *loc_addr,
+ struct in6_addr *rmt_addr, int dif)
+@@ -87,7 +77,7 @@ static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
+ if (inet_sk(sk)->num == num) {
+ struct ipv6_pinfo *np = inet6_sk(sk);
+
+- if (sk->sk_net != net)
++ if (!net_eq(sock_net(sk), net))
+ continue;
+
+ if (!ipv6_addr_any(&np->daddr) &&
+@@ -179,15 +169,10 @@ static int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
+ read_lock(&raw_v6_hashinfo.lock);
+ sk = sk_head(&raw_v6_hashinfo.ht[hash]);
+
+- /*
+- * The first socket found will be delivered after
+- * delivery to transport protocols.
+- */
+-
+ if (sk == NULL)
+ goto out;
+
+- net = skb->dev->nd_net;
++ net = dev_net(skb->dev);
+ sk = __raw_v6_lookup(net, sk, nexthdr, daddr, saddr, IP6CB(skb)->iif);
+
+ while (sk) {
+@@ -291,7 +276,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+ if (!sk->sk_bound_dev_if)
+ goto out;
+
+- dev = dev_get_by_index(sk->sk_net, sk->sk_bound_dev_if);
++ dev = dev_get_by_index(sock_net(sk), sk->sk_bound_dev_if);
+ if (!dev) {
+ err = -ENODEV;
+ goto out;
+@@ -304,7 +289,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+ v4addr = LOOPBACK4_IPV6;
+ if (!(addr_type & IPV6_ADDR_MULTICAST)) {
+ err = -EADDRNOTAVAIL;
+- if (!ipv6_chk_addr(sk->sk_net, &addr->sin6_addr,
++ if (!ipv6_chk_addr(sock_net(sk), &addr->sin6_addr,
+ dev, 0)) {
+ if (dev)
+ dev_put(dev);
+@@ -372,11 +357,11 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr,
+ read_lock(&raw_v6_hashinfo.lock);
+ sk = sk_head(&raw_v6_hashinfo.ht[hash]);
+ if (sk != NULL) {
+- struct ipv6hdr *hdr = (struct ipv6hdr *) skb->data;
+-
+- saddr = &hdr->saddr;
+- daddr = &hdr->daddr;
+- net = skb->dev->nd_net;
++ /* Note: ipv6_hdr(skb) != skb->data */
++ struct ipv6hdr *ip6h = (struct ipv6hdr *)skb->data;
++ saddr = &ip6h->saddr;
++ daddr = &ip6h->daddr;
++ net = dev_net(skb->dev);
+
+ while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr,
+ IP6CB(skb)->iif))) {
+@@ -822,15 +807,6 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
+ fl.fl6_flowlabel = np->flow_label;
+ }
+
+- if (ipv6_addr_any(daddr)) {
+- /*
+- * unspecified destination address
+- * treated as error... is this correct ?
+- */
+- fl6_sock_release(flowlabel);
+- return(-EINVAL);
+- }
+-
+ if (fl.oif == 0)
+ fl.oif = sk->sk_bound_dev_if;
+
+@@ -863,7 +839,10 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
+ if (err)
+ goto out;
+
+- ipv6_addr_copy(&fl.fl6_dst, daddr);
++ if (!ipv6_addr_any(daddr))
++ ipv6_addr_copy(&fl.fl6_dst, daddr);
++ else
++ fl.fl6_dst.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */
+ if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
+ ipv6_addr_copy(&fl.fl6_src, &np->saddr);
+
+@@ -898,9 +877,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
+ else
+ hlimit = np->hop_limit;
+ if (hlimit < 0)
+- hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+- if (hlimit < 0)
+- hlimit = ipv6_get_hoplimit(dst->dev);
++ hlimit = ip6_dst_hoplimit(dst);
+ }
+
+ if (tclass < 0) {
+@@ -994,6 +971,19 @@ static int do_rawv6_setsockopt(struct sock *sk, int level, int optname,
+
+ switch (optname) {
+ case IPV6_CHECKSUM:
++ if (inet_sk(sk)->num == IPPROTO_ICMPV6 &&
++ level == IPPROTO_IPV6) {
++ /*
++ * RFC3542 tells that IPV6_CHECKSUM socket
++ * option in the IPPROTO_IPV6 level is not
++ * allowed on ICMPv6 sockets.
++ * If you want to set it, use IPPROTO_RAW
++ * level IPV6_CHECKSUM socket option
++ * (Linux extension).
++ */
++ return -EINVAL;
++ }
++
+ /* You may get strange result with a positive odd offset;
+ RFC2292bis agrees with me. */
+ if (val > 0 && (val&1))
+@@ -1069,6 +1059,11 @@ static int do_rawv6_getsockopt(struct sock *sk, int level, int optname,
+
+ switch (optname) {
+ case IPV6_CHECKSUM:
++ /*
++ * We allow getsockopt() for IPPROTO_IPV6-level
++ * IPV6_CHECKSUM socket option on ICMPv6 sockets
++ * since RFC3542 is silent about it.
++ */
+ if (rp->checksum == 0)
+ val = -1;
+ else
+@@ -1155,7 +1150,11 @@ static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg)
+ }
+
+ default:
++#ifdef CONFIG_IPV6_MROUTE
++ return ip6mr_ioctl(sk, cmd, (void __user *)arg);
++#else
+ return -ENOIOCTLCMD;
++#endif
+ }
+ }
+
+@@ -1163,7 +1162,7 @@ static void rawv6_close(struct sock *sk, long timeout)
+ {
+ if (inet_sk(sk)->num == IPPROTO_RAW)
+ ip6_ra_control(sk, -1, NULL);
+-
++ ip6mr_sk_done(sk);
+ sk_common_release(sk);
+ }
+
+@@ -1186,8 +1185,6 @@ static int rawv6_init_sk(struct sock *sk)
+ return(0);
+ }
+
+-DEFINE_PROTO_INUSE(rawv6)
+-
+ struct proto rawv6_prot = {
+ .name = "RAWv6",
+ .owner = THIS_MODULE,
+@@ -1203,14 +1200,14 @@ struct proto rawv6_prot = {
+ .recvmsg = rawv6_recvmsg,
+ .bind = rawv6_bind,
+ .backlog_rcv = rawv6_rcv_skb,
+- .hash = raw_v6_hash,
+- .unhash = raw_v6_unhash,
++ .hash = raw_hash_sk,
++ .unhash = raw_unhash_sk,
+ .obj_size = sizeof(struct raw6_sock),
++ .h.raw_hash = &raw_v6_hashinfo,
+ #ifdef CONFIG_COMPAT
+ .compat_setsockopt = compat_rawv6_setsockopt,
+ .compat_getsockopt = compat_rawv6_getsockopt,
+ #endif
+- REF_PROTO_INUSE(rawv6)
+ };
+
+ #ifdef CONFIG_PROC_FS
+diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
+index f936d04..7b247e3 100644
+--- a/net/ipv6/reassembly.c
++++ b/net/ipv6/reassembly.c
+@@ -202,7 +202,7 @@ static void ip6_frag_expire(unsigned long data)
+
+ spin_lock(&fq->q.lock);
+
+- if (fq->q.last_in & COMPLETE)
++ if (fq->q.last_in & INET_FRAG_COMPLETE)
+ goto out;
+
+ fq_kill(fq);
+@@ -217,7 +217,7 @@ static void ip6_frag_expire(unsigned long data)
+ rcu_read_unlock();
+
+ /* Don't send error if the first segment did not arrive. */
+- if (!(fq->q.last_in&FIRST_IN) || !fq->q.fragments)
++ if (!(fq->q.last_in & INET_FRAG_FIRST_IN) || !fq->q.fragments)
+ goto out;
+
+ /*
+@@ -265,7 +265,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
+ struct net_device *dev;
+ int offset, end;
+
+- if (fq->q.last_in & COMPLETE)
++ if (fq->q.last_in & INET_FRAG_COMPLETE)
+ goto err;
+
+ offset = ntohs(fhdr->frag_off) & ~0x7;
+@@ -294,9 +294,9 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
+ * or have different end, the segment is corrupted.
+ */
+ if (end < fq->q.len ||
+- ((fq->q.last_in & LAST_IN) && end != fq->q.len))
++ ((fq->q.last_in & INET_FRAG_LAST_IN) && end != fq->q.len))
+ goto err;
+- fq->q.last_in |= LAST_IN;
++ fq->q.last_in |= INET_FRAG_LAST_IN;
+ fq->q.len = end;
+ } else {
+ /* Check if the fragment is rounded to 8 bytes.
+@@ -314,7 +314,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
+ }
+ if (end > fq->q.len) {
+ /* Some bits beyond end -> corruption. */
+- if (fq->q.last_in & LAST_IN)
++ if (fq->q.last_in & INET_FRAG_LAST_IN)
+ goto err;
+ fq->q.len = end;
+ }
+@@ -417,10 +417,11 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
+ */
+ if (offset == 0) {
+ fq->nhoffset = nhoff;
+- fq->q.last_in |= FIRST_IN;
++ fq->q.last_in |= INET_FRAG_FIRST_IN;
+ }
+
+- if (fq->q.last_in == (FIRST_IN | LAST_IN) && fq->q.meat == fq->q.len)
++ if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) &&
++ fq->q.meat == fq->q.len)
+ return ip6_frag_reasm(fq, prev, dev);
+
+ write_lock(&ip6_frags.lock);
+@@ -600,7 +601,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
+ return 1;
+ }
+
+- net = skb->dev->nd_net;
++ net = dev_net(skb->dev);
+ if (atomic_read(&net->ipv6.frags.mem) > net->ipv6.frags.high_thresh)
+ ip6_evictor(net, ip6_dst_idev(skb->dst));
+
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c
+index e8b241c..a493ad9 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -36,10 +36,12 @@
+ #include <linux/route.h>
+ #include <linux/netdevice.h>
+ #include <linux/in6.h>
++#include <linux/mroute6.h>
+ #include <linux/init.h>
+ #include <linux/if_arp.h>
+ #include <linux/proc_fs.h>
+ #include <linux/seq_file.h>
++#include <linux/nsproxy.h>
+ #include <net/net_namespace.h>
+ #include <net/snmp.h>
+ #include <net/ipv6.h>
+@@ -87,14 +89,16 @@ static void ip6_link_failure(struct sk_buff *skb);
+ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu);
+
+ #ifdef CONFIG_IPV6_ROUTE_INFO
+-static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixlen,
++static struct rt6_info *rt6_add_route_info(struct net *net,
++ struct in6_addr *prefix, int prefixlen,
+ struct in6_addr *gwaddr, int ifindex,
+ unsigned pref);
+-static struct rt6_info *rt6_get_route_info(struct in6_addr *prefix, int prefixlen,
++static struct rt6_info *rt6_get_route_info(struct net *net,
++ struct in6_addr *prefix, int prefixlen,
+ struct in6_addr *gwaddr, int ifindex);
+ #endif
+
+-static struct dst_ops ip6_dst_ops = {
++static struct dst_ops ip6_dst_ops_template = {
+ .family = AF_INET6,
+ .protocol = __constant_htons(ETH_P_IPV6),
+ .gc = ip6_dst_gc,
+@@ -124,7 +128,7 @@ static struct dst_ops ip6_dst_blackhole_ops = {
+ .entries = ATOMIC_INIT(0),
+ };
+
+-struct rt6_info ip6_null_entry = {
++static struct rt6_info ip6_null_entry_template = {
+ .u = {
+ .dst = {
+ .__refcnt = ATOMIC_INIT(1),
+@@ -134,8 +138,6 @@ struct rt6_info ip6_null_entry = {
+ .metrics = { [RTAX_HOPLIMIT - 1] = 255, },
+ .input = ip6_pkt_discard,
+ .output = ip6_pkt_discard_out,
+- .ops = &ip6_dst_ops,
+- .path = (struct dst_entry*)&ip6_null_entry,
+ }
+ },
+ .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
+@@ -148,7 +150,7 @@ struct rt6_info ip6_null_entry = {
+ static int ip6_pkt_prohibit(struct sk_buff *skb);
+ static int ip6_pkt_prohibit_out(struct sk_buff *skb);
+
+-struct rt6_info ip6_prohibit_entry = {
++static struct rt6_info ip6_prohibit_entry_template = {
+ .u = {
+ .dst = {
+ .__refcnt = ATOMIC_INIT(1),
+@@ -158,8 +160,6 @@ struct rt6_info ip6_prohibit_entry = {
+ .metrics = { [RTAX_HOPLIMIT - 1] = 255, },
+ .input = ip6_pkt_prohibit,
+ .output = ip6_pkt_prohibit_out,
+- .ops = &ip6_dst_ops,
+- .path = (struct dst_entry*)&ip6_prohibit_entry,
+ }
+ },
+ .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
+@@ -167,7 +167,7 @@ struct rt6_info ip6_prohibit_entry = {
+ .rt6i_ref = ATOMIC_INIT(1),
+ };
+
+-struct rt6_info ip6_blk_hole_entry = {
++static struct rt6_info ip6_blk_hole_entry_template = {
+ .u = {
+ .dst = {
+ .__refcnt = ATOMIC_INIT(1),
+@@ -177,8 +177,6 @@ struct rt6_info ip6_blk_hole_entry = {
+ .metrics = { [RTAX_HOPLIMIT - 1] = 255, },
+ .input = dst_discard,
+ .output = dst_discard,
+- .ops = &ip6_dst_ops,
+- .path = (struct dst_entry*)&ip6_blk_hole_entry,
+ }
+ },
+ .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
+@@ -189,9 +187,9 @@ struct rt6_info ip6_blk_hole_entry = {
+ #endif
+
+ /* allocate dst with ip6_dst_ops */
+-static __inline__ struct rt6_info *ip6_dst_alloc(void)
++static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops)
+ {
+- return (struct rt6_info *)dst_alloc(&ip6_dst_ops);
++ return (struct rt6_info *)dst_alloc(ops);
+ }
+
+ static void ip6_dst_destroy(struct dst_entry *dst)
+@@ -211,7 +209,7 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
+ struct rt6_info *rt = (struct rt6_info *)dst;
+ struct inet6_dev *idev = rt->rt6i_idev;
+ struct net_device *loopback_dev =
+- dev->nd_net->loopback_dev;
++ dev_net(dev)->loopback_dev;
+
+ if (dev != loopback_dev && idev != NULL && idev->dev == dev) {
+ struct inet6_dev *loopback_idev =
+@@ -239,7 +237,8 @@ static inline int rt6_need_strict(struct in6_addr *daddr)
+ * Route lookup. Any table->tb6_lock is implied.
+ */
+
+-static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt,
++static inline struct rt6_info *rt6_device_match(struct net *net,
++ struct rt6_info *rt,
+ int oif,
+ int strict)
+ {
+@@ -268,7 +267,7 @@ static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt,
+ return local;
+
+ if (strict)
+- return &ip6_null_entry;
++ return net->ipv6.ip6_null_entry;
+ }
+ return rt;
+ }
+@@ -409,9 +408,10 @@ static struct rt6_info *find_rr_leaf(struct fib6_node *fn,
+ static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict)
+ {
+ struct rt6_info *match, *rt0;
++ struct net *net;
+
+ RT6_TRACE("%s(fn->leaf=%p, oif=%d)\n",
+- __FUNCTION__, fn->leaf, oif);
++ __func__, fn->leaf, oif);
+
+ rt0 = fn->rr_ptr;
+ if (!rt0)
+@@ -432,15 +432,17 @@ static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict)
+ }
+
+ RT6_TRACE("%s() => %p\n",
+- __FUNCTION__, match);
++ __func__, match);
+
+- return (match ? match : &ip6_null_entry);
++ net = dev_net(rt0->rt6i_dev);
++ return (match ? match : net->ipv6.ip6_null_entry);
+ }
+
+ #ifdef CONFIG_IPV6_ROUTE_INFO
+ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
+ struct in6_addr *gwaddr)
+ {
++ struct net *net = dev_net(dev);
+ struct route_info *rinfo = (struct route_info *) opt;
+ struct in6_addr prefix_buf, *prefix;
+ unsigned int pref;
+@@ -488,7 +490,8 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
+ prefix = &prefix_buf;
+ }
+
+- rt = rt6_get_route_info(prefix, rinfo->prefix_len, gwaddr, dev->ifindex);
++ rt = rt6_get_route_info(net, prefix, rinfo->prefix_len, gwaddr,
++ dev->ifindex);
+
+ if (rt && !lifetime) {
+ ip6_del_rt(rt);
+@@ -496,7 +499,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
+ }
+
+ if (!rt && lifetime)
+- rt = rt6_add_route_info(prefix, rinfo->prefix_len, gwaddr, dev->ifindex,
++ rt = rt6_add_route_info(net, prefix, rinfo->prefix_len, gwaddr, dev->ifindex,
+ pref);
+ else if (rt)
+ rt->rt6i_flags = RTF_ROUTEINFO |
+@@ -515,9 +518,9 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
+ }
+ #endif
+
+-#define BACKTRACK(saddr) \
++#define BACKTRACK(__net, saddr) \
+ do { \
+- if (rt == &ip6_null_entry) { \
++ if (rt == __net->ipv6.ip6_null_entry) { \
+ struct fib6_node *pn; \
+ while (1) { \
+ if (fn->fn_flags & RTN_TL_ROOT) \
+@@ -533,7 +536,8 @@ do { \
+ } \
+ } while(0)
+
+-static struct rt6_info *ip6_pol_route_lookup(struct fib6_table *table,
++static struct rt6_info *ip6_pol_route_lookup(struct net *net,
++ struct fib6_table *table,
+ struct flowi *fl, int flags)
+ {
+ struct fib6_node *fn;
+@@ -543,8 +547,8 @@ static struct rt6_info *ip6_pol_route_lookup(struct fib6_table *table,
+ fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
+ restart:
+ rt = fn->leaf;
+- rt = rt6_device_match(rt, fl->oif, flags);
+- BACKTRACK(&fl->fl6_src);
++ rt = rt6_device_match(net, rt, fl->oif, flags);
++ BACKTRACK(net, &fl->fl6_src);
+ out:
+ dst_use(&rt->u.dst, jiffies);
+ read_unlock_bh(&table->tb6_lock);
+@@ -552,8 +556,8 @@ out:
+
+ }
+
+-struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr,
+- int oif, int strict)
++struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr,
++ const struct in6_addr *saddr, int oif, int strict)
+ {
+ struct flowi fl = {
+ .oif = oif,
+@@ -571,7 +575,7 @@ struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr,
+ flags |= RT6_LOOKUP_F_HAS_SADDR;
+ }
+
+- dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_lookup);
++ dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_lookup);
+ if (dst->error == 0)
+ return (struct rt6_info *) dst;
+
+@@ -604,7 +608,7 @@ static int __ip6_ins_rt(struct rt6_info *rt, struct nl_info *info)
+ int ip6_ins_rt(struct rt6_info *rt)
+ {
+ struct nl_info info = {
+- .nl_net = &init_net,
++ .nl_net = dev_net(rt->rt6i_dev),
+ };
+ return __ip6_ins_rt(rt, &info);
+ }
+@@ -660,8 +664,8 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *d
+ return rt;
+ }
+
+-static struct rt6_info *ip6_pol_route(struct fib6_table *table, int oif,
+- struct flowi *fl, int flags)
++static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, int oif,
++ struct flowi *fl, int flags)
+ {
+ struct fib6_node *fn;
+ struct rt6_info *rt, *nrt;
+@@ -680,8 +684,9 @@ restart_2:
+
+ restart:
+ rt = rt6_select(fn, oif, strict | reachable);
+- BACKTRACK(&fl->fl6_src);
+- if (rt == &ip6_null_entry ||
++
++ BACKTRACK(net, &fl->fl6_src);
++ if (rt == net->ipv6.ip6_null_entry ||
+ rt->rt6i_flags & RTF_CACHE)
+ goto out;
+
+@@ -699,7 +704,7 @@ restart:
+ }
+
+ dst_release(&rt->u.dst);
+- rt = nrt ? : &ip6_null_entry;
++ rt = nrt ? : net->ipv6.ip6_null_entry;
+
+ dst_hold(&rt->u.dst);
+ if (nrt) {
+@@ -732,15 +737,16 @@ out2:
+ return rt;
+ }
+
+-static struct rt6_info *ip6_pol_route_input(struct fib6_table *table,
++static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *table,
+ struct flowi *fl, int flags)
+ {
+- return ip6_pol_route(table, fl->iif, fl, flags);
++ return ip6_pol_route(net, table, fl->iif, fl, flags);
+ }
+
+ void ip6_route_input(struct sk_buff *skb)
+ {
+ struct ipv6hdr *iph = ipv6_hdr(skb);
++ struct net *net = dev_net(skb->dev);
+ int flags = RT6_LOOKUP_F_HAS_SADDR;
+ struct flowi fl = {
+ .iif = skb->dev->ifindex,
+@@ -758,16 +764,17 @@ void ip6_route_input(struct sk_buff *skb)
+ if (rt6_need_strict(&iph->daddr))
+ flags |= RT6_LOOKUP_F_IFACE;
+
+- skb->dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_input);
++ skb->dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_input);
+ }
+
+-static struct rt6_info *ip6_pol_route_output(struct fib6_table *table,
++static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table,
+ struct flowi *fl, int flags)
+ {
+- return ip6_pol_route(table, fl->oif, fl, flags);
++ return ip6_pol_route(net, table, fl->oif, fl, flags);
+ }
+
+-struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl)
++struct dst_entry * ip6_route_output(struct net *net, struct sock *sk,
++ struct flowi *fl)
+ {
+ int flags = 0;
+
+@@ -776,8 +783,17 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl)
+
+ if (!ipv6_addr_any(&fl->fl6_src))
+ flags |= RT6_LOOKUP_F_HAS_SADDR;
++ else if (sk) {
++ unsigned int prefs = inet6_sk(sk)->srcprefs;
++ if (prefs & IPV6_PREFER_SRC_TMP)
++ flags |= RT6_LOOKUP_F_SRCPREF_TMP;
++ if (prefs & IPV6_PREFER_SRC_PUBLIC)
++ flags |= RT6_LOOKUP_F_SRCPREF_PUBLIC;
++ if (prefs & IPV6_PREFER_SRC_COA)
++ flags |= RT6_LOOKUP_F_SRCPREF_COA;
++ }
+
+- return fib6_rule_lookup(fl, flags, ip6_pol_route_output);
++ return fib6_rule_lookup(net, fl, flags, ip6_pol_route_output);
+ }
+
+ EXPORT_SYMBOL(ip6_route_output);
+@@ -886,12 +902,12 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
+
+ static int ipv6_get_mtu(struct net_device *dev);
+
+-static inline unsigned int ipv6_advmss(unsigned int mtu)
++static inline unsigned int ipv6_advmss(struct net *net, unsigned int mtu)
+ {
+ mtu -= sizeof(struct ipv6hdr) + sizeof(struct tcphdr);
+
+- if (mtu < init_net.ipv6.sysctl.ip6_rt_min_advmss)
+- mtu = init_net.ipv6.sysctl.ip6_rt_min_advmss;
++ if (mtu < net->ipv6.sysctl.ip6_rt_min_advmss)
++ mtu = net->ipv6.sysctl.ip6_rt_min_advmss;
+
+ /*
+ * Maximal non-jumbo IPv6 payload is IPV6_MAXPLEN and
+@@ -904,21 +920,21 @@ static inline unsigned int ipv6_advmss(unsigned int mtu)
+ return mtu;
+ }
+
+-static struct dst_entry *ndisc_dst_gc_list;
+-static DEFINE_SPINLOCK(ndisc_lock);
++static struct dst_entry *icmp6_dst_gc_list;
++static DEFINE_SPINLOCK(icmp6_dst_lock);
+
+-struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
++struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
+ struct neighbour *neigh,
+- struct in6_addr *addr,
+- int (*output)(struct sk_buff *))
++ const struct in6_addr *addr)
+ {
+ struct rt6_info *rt;
+ struct inet6_dev *idev = in6_dev_get(dev);
++ struct net *net = dev_net(dev);
+
+ if (unlikely(idev == NULL))
+ return NULL;
+
+- rt = ip6_dst_alloc();
++ rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops);
+ if (unlikely(rt == NULL)) {
+ in6_dev_put(idev);
+ goto out;
+@@ -936,8 +952,8 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
+ atomic_set(&rt->u.dst.__refcnt, 1);
+ rt->u.dst.metrics[RTAX_HOPLIMIT-1] = 255;
+ rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev);
+- rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
+- rt->u.dst.output = output;
++ rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst));
++ rt->u.dst.output = ip6_output;
+
+ #if 0 /* there's no chance to use these for ndisc */
+ rt->u.dst.flags = ipv6_addr_type(addr) & IPV6_ADDR_UNICAST
+@@ -947,18 +963,18 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
+ rt->rt6i_dst.plen = 128;
+ #endif
+
+- spin_lock_bh(&ndisc_lock);
+- rt->u.dst.next = ndisc_dst_gc_list;
+- ndisc_dst_gc_list = &rt->u.dst;
+- spin_unlock_bh(&ndisc_lock);
++ spin_lock_bh(&icmp6_dst_lock);
++ rt->u.dst.next = icmp6_dst_gc_list;
++ icmp6_dst_gc_list = &rt->u.dst;
++ spin_unlock_bh(&icmp6_dst_lock);
+
+- fib6_force_start_gc();
++ fib6_force_start_gc(net);
+
+ out:
+ return &rt->u.dst;
+ }
+
+-int ndisc_dst_gc(int *more)
++int icmp6_dst_gc(int *more)
+ {
+ struct dst_entry *dst, *next, **pprev;
+ int freed;
+@@ -966,8 +982,8 @@ int ndisc_dst_gc(int *more)
+ next = NULL;
+ freed = 0;
+
+- spin_lock_bh(&ndisc_lock);
+- pprev = &ndisc_dst_gc_list;
++ spin_lock_bh(&icmp6_dst_lock);
++ pprev = &icmp6_dst_gc_list;
+
+ while ((dst = *pprev) != NULL) {
+ if (!atomic_read(&dst->__refcnt)) {
+@@ -980,30 +996,33 @@ int ndisc_dst_gc(int *more)
+ }
+ }
+
+- spin_unlock_bh(&ndisc_lock);
++ spin_unlock_bh(&icmp6_dst_lock);
+
+ return freed;
+ }
+
+ static int ip6_dst_gc(struct dst_ops *ops)
+ {
+- static unsigned expire = 30*HZ;
+- static unsigned long last_gc;
+ unsigned long now = jiffies;
+-
+- if (time_after(last_gc + init_net.ipv6.sysctl.ip6_rt_gc_min_interval, now) &&
+- atomic_read(&ip6_dst_ops.entries) <= init_net.ipv6.sysctl.ip6_rt_max_size)
++ struct net *net = ops->dst_net;
++ int rt_min_interval = net->ipv6.sysctl.ip6_rt_gc_min_interval;
++ int rt_max_size = net->ipv6.sysctl.ip6_rt_max_size;
++ int rt_elasticity = net->ipv6.sysctl.ip6_rt_gc_elasticity;
++ int rt_gc_timeout = net->ipv6.sysctl.ip6_rt_gc_timeout;
++ unsigned long rt_last_gc = net->ipv6.ip6_rt_last_gc;
++
++ if (time_after(rt_last_gc + rt_min_interval, now) &&
++ atomic_read(&ops->entries) <= rt_max_size)
+ goto out;
+
+- expire++;
+- fib6_run_gc(expire);
+- last_gc = now;
+- if (atomic_read(&ip6_dst_ops.entries) < ip6_dst_ops.gc_thresh)
+- expire = init_net.ipv6.sysctl.ip6_rt_gc_timeout>>1;
+-
++ net->ipv6.ip6_rt_gc_expire++;
++ fib6_run_gc(net->ipv6.ip6_rt_gc_expire, net);
++ net->ipv6.ip6_rt_last_gc = now;
++ if (atomic_read(&ops->entries) < ops->gc_thresh)
++ net->ipv6.ip6_rt_gc_expire = rt_gc_timeout>>1;
+ out:
+- expire -= expire>>init_net.ipv6.sysctl.ip6_rt_gc_elasticity;
+- return (atomic_read(&ip6_dst_ops.entries) > init_net.ipv6.sysctl.ip6_rt_max_size);
++ net->ipv6.ip6_rt_gc_expire -= net->ipv6.ip6_rt_gc_expire>>rt_elasticity;
++ return (atomic_read(&ops->entries) > rt_max_size);
+ }
+
+ /* Clean host part of a prefix. Not necessary in radix tree,
+@@ -1025,15 +1044,17 @@ static int ipv6_get_mtu(struct net_device *dev)
+ return mtu;
+ }
+
+-int ipv6_get_hoplimit(struct net_device *dev)
++int ip6_dst_hoplimit(struct dst_entry *dst)
+ {
+- int hoplimit = ipv6_devconf.hop_limit;
+- struct inet6_dev *idev;
+-
+- idev = in6_dev_get(dev);
+- if (idev) {
+- hoplimit = idev->cnf.hop_limit;
+- in6_dev_put(idev);
++ int hoplimit = dst_metric(dst, RTAX_HOPLIMIT);
++ if (hoplimit < 0) {
++ struct net_device *dev = dst->dev;
++ struct inet6_dev *idev = in6_dev_get(dev);
++ if (idev) {
++ hoplimit = idev->cnf.hop_limit;
++ in6_dev_put(idev);
++ } else
++ hoplimit = ipv6_devconf.hop_limit;
+ }
+ return hoplimit;
+ }
+@@ -1045,6 +1066,7 @@ int ipv6_get_hoplimit(struct net_device *dev)
+ int ip6_route_add(struct fib6_config *cfg)
+ {
+ int err;
++ struct net *net = cfg->fc_nlinfo.nl_net;
+ struct rt6_info *rt = NULL;
+ struct net_device *dev = NULL;
+ struct inet6_dev *idev = NULL;
+@@ -1059,7 +1081,7 @@ int ip6_route_add(struct fib6_config *cfg)
+ #endif
+ if (cfg->fc_ifindex) {
+ err = -ENODEV;
+- dev = dev_get_by_index(&init_net, cfg->fc_ifindex);
++ dev = dev_get_by_index(net, cfg->fc_ifindex);
+ if (!dev)
+ goto out;
+ idev = in6_dev_get(dev);
+@@ -1070,13 +1092,13 @@ int ip6_route_add(struct fib6_config *cfg)
+ if (cfg->fc_metric == 0)
+ cfg->fc_metric = IP6_RT_PRIO_USER;
+
+- table = fib6_new_table(cfg->fc_table);
++ table = fib6_new_table(net, cfg->fc_table);
+ if (table == NULL) {
+ err = -ENOBUFS;
+ goto out;
+ }
+
+- rt = ip6_dst_alloc();
++ rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops);
+
+ if (rt == NULL) {
+ err = -ENOMEM;
+@@ -1117,12 +1139,12 @@ int ip6_route_add(struct fib6_config *cfg)
+ if ((cfg->fc_flags & RTF_REJECT) ||
+ (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) {
+ /* hold loopback dev/idev if we haven't done so. */
+- if (dev != init_net.loopback_dev) {
++ if (dev != net->loopback_dev) {
+ if (dev) {
+ dev_put(dev);
+ in6_dev_put(idev);
+ }
+- dev = init_net.loopback_dev;
++ dev = net->loopback_dev;
+ dev_hold(dev);
+ idev = in6_dev_get(dev);
+ if (!idev) {
+@@ -1159,7 +1181,7 @@ int ip6_route_add(struct fib6_config *cfg)
+ if (!(gwa_type&IPV6_ADDR_UNICAST))
+ goto out;
+
+- grt = rt6_lookup(gw_addr, NULL, cfg->fc_ifindex, 1);
++ grt = rt6_lookup(net, gw_addr, NULL, cfg->fc_ifindex, 1);
+
+ err = -EHOSTUNREACH;
+ if (grt == NULL)
+@@ -1226,10 +1248,13 @@ install_route:
+ if (!rt->u.dst.metrics[RTAX_MTU-1])
+ rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev);
+ if (!rt->u.dst.metrics[RTAX_ADVMSS-1])
+- rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
++ rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst));
+ rt->u.dst.dev = dev;
+ rt->rt6i_idev = idev;
+ rt->rt6i_table = table;
++
++ cfg->fc_nlinfo.nl_net = dev_net(dev);
++
+ return __ip6_ins_rt(rt, &cfg->fc_nlinfo);
+
+ out:
+@@ -1246,8 +1271,9 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info)
+ {
+ int err;
+ struct fib6_table *table;
++ struct net *net = dev_net(rt->rt6i_dev);
+
+- if (rt == &ip6_null_entry)
++ if (rt == net->ipv6.ip6_null_entry)
+ return -ENOENT;
+
+ table = rt->rt6i_table;
+@@ -1264,7 +1290,7 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info)
+ int ip6_del_rt(struct rt6_info *rt)
+ {
+ struct nl_info info = {
+- .nl_net = &init_net,
++ .nl_net = dev_net(rt->rt6i_dev),
+ };
+ return __ip6_del_rt(rt, &info);
+ }
+@@ -1276,7 +1302,7 @@ static int ip6_route_del(struct fib6_config *cfg)
+ struct rt6_info *rt;
+ int err = -ESRCH;
+
+- table = fib6_get_table(cfg->fc_table);
++ table = fib6_get_table(cfg->fc_nlinfo.nl_net, cfg->fc_table);
+ if (table == NULL)
+ return err;
+
+@@ -1316,7 +1342,8 @@ struct ip6rd_flowi {
+ struct in6_addr gateway;
+ };
+
+-static struct rt6_info *__ip6_route_redirect(struct fib6_table *table,
++static struct rt6_info *__ip6_route_redirect(struct net *net,
++ struct fib6_table *table,
+ struct flowi *fl,
+ int flags)
+ {
+@@ -1359,8 +1386,8 @@ restart:
+ }
+
+ if (!rt)
+- rt = &ip6_null_entry;
+- BACKTRACK(&fl->fl6_src);
++ rt = net->ipv6.ip6_null_entry;
++ BACKTRACK(net, &fl->fl6_src);
+ out:
+ dst_hold(&rt->u.dst);
+
+@@ -1375,6 +1402,7 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest,
+ struct net_device *dev)
+ {
+ int flags = RT6_LOOKUP_F_HAS_SADDR;
++ struct net *net = dev_net(dev);
+ struct ip6rd_flowi rdfl = {
+ .fl = {
+ .oif = dev->ifindex,
+@@ -1391,7 +1419,8 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest,
+ if (rt6_need_strict(dest))
+ flags |= RT6_LOOKUP_F_IFACE;
+
+- return (struct rt6_info *)fib6_rule_lookup((struct flowi *)&rdfl, flags, __ip6_route_redirect);
++ return (struct rt6_info *)fib6_rule_lookup(net, (struct flowi *)&rdfl,
++ flags, __ip6_route_redirect);
+ }
+
+ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src,
+@@ -1400,10 +1429,11 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src,
+ {
+ struct rt6_info *rt, *nrt = NULL;
+ struct netevent_redirect netevent;
++ struct net *net = dev_net(neigh->dev);
+
+ rt = ip6_route_redirect(dest, src, saddr, neigh->dev);
+
+- if (rt == &ip6_null_entry) {
++ if (rt == net->ipv6.ip6_null_entry) {
+ if (net_ratelimit())
+ printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop "
+ "for redirect target\n");
+@@ -1448,7 +1478,8 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src,
+ nrt->rt6i_nexthop = neigh_clone(neigh);
+ /* Reset pmtu, it may be better */
+ nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev);
+- nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&nrt->u.dst));
++ nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dev_net(neigh->dev),
++ dst_mtu(&nrt->u.dst));
+
+ if (ip6_ins_rt(nrt))
+ goto out;
+@@ -1476,9 +1507,10 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
+ struct net_device *dev, u32 pmtu)
+ {
+ struct rt6_info *rt, *nrt;
++ struct net *net = dev_net(dev);
+ int allfrag = 0;
+
+- rt = rt6_lookup(daddr, saddr, dev->ifindex, 0);
++ rt = rt6_lookup(net, daddr, saddr, dev->ifindex, 0);
+ if (rt == NULL)
+ return;
+
+@@ -1511,7 +1543,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
+ rt->u.dst.metrics[RTAX_MTU-1] = pmtu;
+ if (allfrag)
+ rt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
+- dst_set_expires(&rt->u.dst, init_net.ipv6.sysctl.ip6_rt_mtu_expires);
++ dst_set_expires(&rt->u.dst, net->ipv6.sysctl.ip6_rt_mtu_expires);
+ rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES;
+ goto out;
+ }
+@@ -1537,7 +1569,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
+ * which is 10 mins. After 10 mins the decreased pmtu is expired
+ * and detecting PMTU increase will be automatically happened.
+ */
+- dst_set_expires(&nrt->u.dst, init_net.ipv6.sysctl.ip6_rt_mtu_expires);
++ dst_set_expires(&nrt->u.dst, net->ipv6.sysctl.ip6_rt_mtu_expires);
+ nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES;
+
+ ip6_ins_rt(nrt);
+@@ -1552,7 +1584,8 @@ out:
+
+ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
+ {
+- struct rt6_info *rt = ip6_dst_alloc();
++ struct net *net = dev_net(ort->rt6i_dev);
++ struct rt6_info *rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops);
+
+ if (rt) {
+ rt->u.dst.input = ort->u.dst.input;
+@@ -1583,14 +1616,15 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
+ }
+
+ #ifdef CONFIG_IPV6_ROUTE_INFO
+-static struct rt6_info *rt6_get_route_info(struct in6_addr *prefix, int prefixlen,
++static struct rt6_info *rt6_get_route_info(struct net *net,
++ struct in6_addr *prefix, int prefixlen,
+ struct in6_addr *gwaddr, int ifindex)
+ {
+ struct fib6_node *fn;
+ struct rt6_info *rt = NULL;
+ struct fib6_table *table;
+
+- table = fib6_get_table(RT6_TABLE_INFO);
++ table = fib6_get_table(net, RT6_TABLE_INFO);
+ if (table == NULL)
+ return NULL;
+
+@@ -1614,7 +1648,8 @@ out:
+ return rt;
+ }
+
+-static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixlen,
++static struct rt6_info *rt6_add_route_info(struct net *net,
++ struct in6_addr *prefix, int prefixlen,
+ struct in6_addr *gwaddr, int ifindex,
+ unsigned pref)
+ {
+@@ -1625,6 +1660,9 @@ static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixle
+ .fc_dst_len = prefixlen,
+ .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO |
+ RTF_UP | RTF_PREF(pref),
++ .fc_nlinfo.pid = 0,
++ .fc_nlinfo.nlh = NULL,
++ .fc_nlinfo.nl_net = net,
+ };
+
+ ipv6_addr_copy(&cfg.fc_dst, prefix);
+@@ -1636,7 +1674,7 @@ static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixle
+
+ ip6_route_add(&cfg);
+
+- return rt6_get_route_info(prefix, prefixlen, gwaddr, ifindex);
++ return rt6_get_route_info(net, prefix, prefixlen, gwaddr, ifindex);
+ }
+ #endif
+
+@@ -1645,7 +1683,7 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d
+ struct rt6_info *rt;
+ struct fib6_table *table;
+
+- table = fib6_get_table(RT6_TABLE_DFLT);
++ table = fib6_get_table(dev_net(dev), RT6_TABLE_DFLT);
+ if (table == NULL)
+ return NULL;
+
+@@ -1662,8 +1700,6 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d
+ return rt;
+ }
+
+-EXPORT_SYMBOL(rt6_get_dflt_router);
+-
+ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr,
+ struct net_device *dev,
+ unsigned int pref)
+@@ -1674,6 +1710,9 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr,
+ .fc_ifindex = dev->ifindex,
+ .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT |
+ RTF_UP | RTF_EXPIRES | RTF_PREF(pref),
++ .fc_nlinfo.pid = 0,
++ .fc_nlinfo.nlh = NULL,
++ .fc_nlinfo.nl_net = dev_net(dev),
+ };
+
+ ipv6_addr_copy(&cfg.fc_gateway, gwaddr);
+@@ -1683,13 +1722,13 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr,
+ return rt6_get_dflt_router(gwaddr, dev);
+ }
+
+-void rt6_purge_dflt_routers(void)
++void rt6_purge_dflt_routers(struct net *net)
+ {
+ struct rt6_info *rt;
+ struct fib6_table *table;
+
+ /* NOTE: Keep consistent with rt6_get_dflt_router */
+- table = fib6_get_table(RT6_TABLE_DFLT);
++ table = fib6_get_table(net, RT6_TABLE_DFLT);
+ if (table == NULL)
+ return;
+
+@@ -1706,7 +1745,8 @@ restart:
+ read_unlock_bh(&table->tb6_lock);
+ }
+
+-static void rtmsg_to_fib6_config(struct in6_rtmsg *rtmsg,
++static void rtmsg_to_fib6_config(struct net *net,
++ struct in6_rtmsg *rtmsg,
+ struct fib6_config *cfg)
+ {
+ memset(cfg, 0, sizeof(*cfg));
+@@ -1719,14 +1759,14 @@ static void rtmsg_to_fib6_config(struct in6_rtmsg *rtmsg,
+ cfg->fc_src_len = rtmsg->rtmsg_src_len;
+ cfg->fc_flags = rtmsg->rtmsg_flags;
+
+- cfg->fc_nlinfo.nl_net = &init_net;
++ cfg->fc_nlinfo.nl_net = net;
+
+ ipv6_addr_copy(&cfg->fc_dst, &rtmsg->rtmsg_dst);
+ ipv6_addr_copy(&cfg->fc_src, &rtmsg->rtmsg_src);
+ ipv6_addr_copy(&cfg->fc_gateway, &rtmsg->rtmsg_gateway);
+ }
+
+-int ipv6_route_ioctl(unsigned int cmd, void __user *arg)
++int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg)
+ {
+ struct fib6_config cfg;
+ struct in6_rtmsg rtmsg;
+@@ -1742,7 +1782,7 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg)
+ if (err)
+ return -EFAULT;
+
+- rtmsg_to_fib6_config(&rtmsg, &cfg);
++ rtmsg_to_fib6_config(net, &rtmsg, &cfg);
+
+ rtnl_lock();
+ switch (cmd) {
+@@ -1821,21 +1861,22 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
+ const struct in6_addr *addr,
+ int anycast)
+ {
+- struct rt6_info *rt = ip6_dst_alloc();
++ struct net *net = dev_net(idev->dev);
++ struct rt6_info *rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops);
+
+ if (rt == NULL)
+ return ERR_PTR(-ENOMEM);
+
+- dev_hold(init_net.loopback_dev);
++ dev_hold(net->loopback_dev);
+ in6_dev_hold(idev);
+
+ rt->u.dst.flags = DST_HOST;
+ rt->u.dst.input = ip6_input;
+ rt->u.dst.output = ip6_output;
+- rt->rt6i_dev = init_net.loopback_dev;
++ rt->rt6i_dev = net->loopback_dev;
+ rt->rt6i_idev = idev;
+ rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev);
+- rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
++ rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst));
+ rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1;
+ rt->u.dst.obsolete = -1;
+
+@@ -1852,26 +1893,39 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
+
+ ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
+ rt->rt6i_dst.plen = 128;
+- rt->rt6i_table = fib6_get_table(RT6_TABLE_LOCAL);
++ rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL);
+
+ atomic_set(&rt->u.dst.__refcnt, 1);
+
+ return rt;
+ }
+
++struct arg_dev_net {
++ struct net_device *dev;
++ struct net *net;
++};
++
+ static int fib6_ifdown(struct rt6_info *rt, void *arg)
+ {
+- if (((void*)rt->rt6i_dev == arg || arg == NULL) &&
+- rt != &ip6_null_entry) {
++ struct net_device *dev = ((struct arg_dev_net *)arg)->dev;
++ struct net *net = ((struct arg_dev_net *)arg)->net;
++
++ if (((void *)rt->rt6i_dev == dev || dev == NULL) &&
++ rt != net->ipv6.ip6_null_entry) {
+ RT6_TRACE("deleted by ifdown %p\n", rt);
+ return -1;
+ }
+ return 0;
+ }
+
+-void rt6_ifdown(struct net_device *dev)
++void rt6_ifdown(struct net *net, struct net_device *dev)
+ {
+- fib6_clean_all(fib6_ifdown, 0, dev);
++ struct arg_dev_net adn = {
++ .dev = dev,
++ .net = net,
++ };
++
++ fib6_clean_all(net, fib6_ifdown, 0, &adn);
+ }
+
+ struct rt6_mtu_change_arg
+@@ -1884,6 +1938,7 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg)
+ {
+ struct rt6_mtu_change_arg *arg = (struct rt6_mtu_change_arg *) p_arg;
+ struct inet6_dev *idev;
++ struct net *net = dev_net(arg->dev);
+
+ /* In IPv6 pmtu discovery is not optional,
+ so that RTAX_MTU lock cannot disable it.
+@@ -1915,7 +1970,7 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg)
+ (dst_mtu(&rt->u.dst) < arg->mtu &&
+ dst_mtu(&rt->u.dst) == idev->cnf.mtu6))) {
+ rt->u.dst.metrics[RTAX_MTU-1] = arg->mtu;
+- rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(arg->mtu);
++ rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, arg->mtu);
+ }
+ return 0;
+ }
+@@ -1927,7 +1982,7 @@ void rt6_mtu_change(struct net_device *dev, unsigned mtu)
+ .mtu = mtu,
+ };
+
+- fib6_clean_all(rt6_mtu_change_route, 0, &arg);
++ fib6_clean_all(dev_net(dev), rt6_mtu_change_route, 0, &arg);
+ }
+
+ static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
+@@ -1964,7 +2019,7 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
+
+ cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid;
+ cfg->fc_nlinfo.nlh = nlh;
+- cfg->fc_nlinfo.nl_net = skb->sk->sk_net;
++ cfg->fc_nlinfo.nl_net = sock_net(skb->sk);
+
+ if (tb[RTA_GATEWAY]) {
+ nla_memcpy(&cfg->fc_gateway, tb[RTA_GATEWAY], 16);
+@@ -2010,13 +2065,9 @@ errout:
+
+ static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
+ struct fib6_config cfg;
+ int err;
+
+- if (net != &init_net)
+- return -EINVAL;
+-
+ err = rtm_to_fib6_config(skb, nlh, &cfg);
+ if (err < 0)
+ return err;
+@@ -2026,13 +2077,9 @@ static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *a
+
+ static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
+ struct fib6_config cfg;
+ int err;
+
+- if (net != &init_net)
+- return -EINVAL;
+-
+ err = rtm_to_fib6_config(skb, nlh, &cfg);
+ if (err < 0)
+ return err;
+@@ -2058,7 +2105,7 @@ static inline size_t rt6_nlmsg_size(void)
+ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
+ struct in6_addr *dst, struct in6_addr *src,
+ int iif, int type, u32 pid, u32 seq,
+- int prefix, unsigned int flags)
++ int prefix, int nowait, unsigned int flags)
+ {
+ struct rtmsg *rtm;
+ struct nlmsghdr *nlh;
+@@ -2118,11 +2165,27 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
+ } else if (rtm->rtm_src_len)
+ NLA_PUT(skb, RTA_SRC, 16, &rt->rt6i_src.addr);
+ #endif
+- if (iif)
+- NLA_PUT_U32(skb, RTA_IIF, iif);
+- else if (dst) {
++ if (iif) {
++#ifdef CONFIG_IPV6_MROUTE
++ if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr)) {
++ int err = ip6mr_get_route(skb, rtm, nowait);
++ if (err <= 0) {
++ if (!nowait) {
++ if (err == 0)
++ return 0;
++ goto nla_put_failure;
++ } else {
++ if (err == -EMSGSIZE)
++ goto nla_put_failure;
++ }
++ }
++ } else
++#endif
++ NLA_PUT_U32(skb, RTA_IIF, iif);
++ } else if (dst) {
+ struct in6_addr saddr_buf;
+- if (ipv6_get_saddr(&rt->u.dst, dst, &saddr_buf) == 0)
++ if (ipv6_dev_get_saddr(ip6_dst_idev(&rt->u.dst)->dev,
++ dst, 0, &saddr_buf) == 0)
+ NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
+ }
+
+@@ -2162,12 +2225,12 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg)
+
+ return rt6_fill_node(arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE,
+ NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq,
+- prefix, NLM_F_MULTI);
++ prefix, 0, NLM_F_MULTI);
+ }
+
+ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
+ {
+- struct net *net = in_skb->sk->sk_net;
++ struct net *net = sock_net(in_skb->sk);
+ struct nlattr *tb[RTA_MAX+1];
+ struct rt6_info *rt;
+ struct sk_buff *skb;
+@@ -2175,9 +2238,6 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
+ struct flowi fl;
+ int err, iif = 0;
+
+- if (net != &init_net)
+- return -EINVAL;
+-
+ err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy);
+ if (err < 0)
+ goto errout;
+@@ -2207,7 +2267,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
+
+ if (iif) {
+ struct net_device *dev;
+- dev = __dev_get_by_index(&init_net, iif);
++ dev = __dev_get_by_index(net, iif);
+ if (!dev) {
+ err = -ENODEV;
+ goto errout;
+@@ -2226,18 +2286,18 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
+ skb_reset_mac_header(skb);
+ skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr));
+
+- rt = (struct rt6_info*) ip6_route_output(NULL, &fl);
++ rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl);
+ skb->dst = &rt->u.dst;
+
+ err = rt6_fill_node(skb, rt, &fl.fl6_dst, &fl.fl6_src, iif,
+ RTM_NEWROUTE, NETLINK_CB(in_skb).pid,
+- nlh->nlmsg_seq, 0, 0);
++ nlh->nlmsg_seq, 0, 0, 0);
+ if (err < 0) {
+ kfree_skb(skb);
+ goto errout;
+ }
+
+- err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid);
++ err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).pid);
+ errout:
+ return err;
+ }
+@@ -2245,6 +2305,7 @@ errout:
+ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
+ {
+ struct sk_buff *skb;
++ struct net *net = info->nl_net;
+ u32 seq;
+ int err;
+
+@@ -2256,18 +2317,38 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
+ goto errout;
+
+ err = rt6_fill_node(skb, rt, NULL, NULL, 0,
+- event, info->pid, seq, 0, 0);
++ event, info->pid, seq, 0, 0, 0);
+ if (err < 0) {
+ /* -EMSGSIZE implies BUG in rt6_nlmsg_size() */
+ WARN_ON(err == -EMSGSIZE);
+ kfree_skb(skb);
+ goto errout;
+ }
+- err = rtnl_notify(skb, &init_net, info->pid,
+- RTNLGRP_IPV6_ROUTE, info->nlh, gfp_any());
++ err = rtnl_notify(skb, net, info->pid, RTNLGRP_IPV6_ROUTE,
++ info->nlh, gfp_any());
+ errout:
+ if (err < 0)
+- rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_ROUTE, err);
++ rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err);
++}
++
++static int ip6_route_dev_notify(struct notifier_block *this,
++ unsigned long event, void *data)
++{
++ struct net_device *dev = (struct net_device *)data;
++ struct net *net = dev_net(dev);
++
++ if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) {
++ net->ipv6.ip6_null_entry->u.dst.dev = dev;
++ net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev);
++#ifdef CONFIG_IPV6_MULTIPLE_TABLES
++ net->ipv6.ip6_prohibit_entry->u.dst.dev = dev;
++ net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev);
++ net->ipv6.ip6_blk_hole_entry->u.dst.dev = dev;
++ net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev);
++#endif
++ }
++
++ return NOTIFY_OK;
+ }
+
+ /*
+@@ -2316,13 +2397,33 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg)
+
+ static int ipv6_route_show(struct seq_file *m, void *v)
+ {
+- fib6_clean_all(rt6_info_route, 0, m);
++ struct net *net = (struct net *)m->private;
++ fib6_clean_all(net, rt6_info_route, 0, m);
+ return 0;
+ }
+
+ static int ipv6_route_open(struct inode *inode, struct file *file)
+ {
+- return single_open(file, ipv6_route_show, NULL);
++ int err;
++ struct net *net = get_proc_net(inode);
++ if (!net)
++ return -ENXIO;
++
++ err = single_open(file, ipv6_route_show, net);
++ if (err < 0) {
++ put_net(net);
++ return err;
++ }
++
++ return 0;
++}
++
++static int ipv6_route_release(struct inode *inode, struct file *file)
++{
++ struct seq_file *seq = file->private_data;
++ struct net *net = seq->private;
++ put_net(net);
++ return single_release(inode, file);
+ }
+
+ static const struct file_operations ipv6_route_proc_fops = {
+@@ -2330,24 +2431,46 @@ static const struct file_operations ipv6_route_proc_fops = {
+ .open = ipv6_route_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = single_release,
++ .release = ipv6_route_release,
+ };
+
+ static int rt6_stats_seq_show(struct seq_file *seq, void *v)
+ {
++ struct net *net = (struct net *)seq->private;
+ seq_printf(seq, "%04x %04x %04x %04x %04x %04x %04x\n",
+- rt6_stats.fib_nodes, rt6_stats.fib_route_nodes,
+- rt6_stats.fib_rt_alloc, rt6_stats.fib_rt_entries,
+- rt6_stats.fib_rt_cache,
+- atomic_read(&ip6_dst_ops.entries),
+- rt6_stats.fib_discarded_routes);
++ net->ipv6.rt6_stats->fib_nodes,
++ net->ipv6.rt6_stats->fib_route_nodes,
++ net->ipv6.rt6_stats->fib_rt_alloc,
++ net->ipv6.rt6_stats->fib_rt_entries,
++ net->ipv6.rt6_stats->fib_rt_cache,
++ atomic_read(&net->ipv6.ip6_dst_ops->entries),
++ net->ipv6.rt6_stats->fib_discarded_routes);
+
+ return 0;
+ }
+
+ static int rt6_stats_seq_open(struct inode *inode, struct file *file)
+ {
+- return single_open(file, rt6_stats_seq_show, NULL);
++ int err;
++ struct net *net = get_proc_net(inode);
++ if (!net)
++ return -ENXIO;
++
++ err = single_open(file, rt6_stats_seq_show, net);
++ if (err < 0) {
++ put_net(net);
++ return err;
++ }
++
++ return 0;
++}
++
++static int rt6_stats_seq_release(struct inode *inode, struct file *file)
++{
++ struct seq_file *seq = file->private_data;
++ struct net *net = (struct net *)seq->private;
++ put_net(net);
++ return single_release(inode, file);
+ }
+
+ static const struct file_operations rt6_stats_seq_fops = {
+@@ -2355,42 +2478,8 @@ static const struct file_operations rt6_stats_seq_fops = {
+ .open = rt6_stats_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = single_release,
++ .release = rt6_stats_seq_release,
+ };
+-
+-static int ipv6_route_proc_init(struct net *net)
+-{
+- int ret = -ENOMEM;
+- if (!proc_net_fops_create(net, "ipv6_route",
+- 0, &ipv6_route_proc_fops))
+- goto out;
+-
+- if (!proc_net_fops_create(net, "rt6_stats",
+- S_IRUGO, &rt6_stats_seq_fops))
+- goto out_ipv6_route;
+-
+- ret = 0;
+-out:
+- return ret;
+-out_ipv6_route:
+- proc_net_remove(net, "ipv6_route");
+- goto out;
+-}
+-
+-static void ipv6_route_proc_fini(struct net *net)
+-{
+- proc_net_remove(net, "ipv6_route");
+- proc_net_remove(net, "rt6_stats");
+-}
+-#else
+-static inline int ipv6_route_proc_init(struct net *net)
+-{
+- return 0;
+-}
+-static inline void ipv6_route_proc_fini(struct net *net)
+-{
+- return ;
+-}
+ #endif /* CONFIG_PROC_FS */
+
+ #ifdef CONFIG_SYSCTL
+@@ -2399,10 +2488,11 @@ static
+ int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, struct file * filp,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+ {
+- int delay = init_net.ipv6.sysctl.flush_delay;
++ struct net *net = current->nsproxy->net_ns;
++ int delay = net->ipv6.sysctl.flush_delay;
+ if (write) {
+ proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
+- fib6_run_gc(delay <= 0 ? ~0UL : (unsigned long)delay);
++ fib6_run_gc(delay <= 0 ? ~0UL : (unsigned long)delay, net);
+ return 0;
+ } else
+ return -EINVAL;
+@@ -2419,7 +2509,7 @@ ctl_table ipv6_route_table_template[] = {
+ {
+ .ctl_name = NET_IPV6_ROUTE_GC_THRESH,
+ .procname = "gc_thresh",
+- .data = &ip6_dst_ops.gc_thresh,
++ .data = &ip6_dst_ops_template.gc_thresh,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+@@ -2505,33 +2595,142 @@ struct ctl_table *ipv6_route_sysctl_init(struct net *net)
+ table = kmemdup(ipv6_route_table_template,
+ sizeof(ipv6_route_table_template),
+ GFP_KERNEL);
++
++ if (table) {
++ table[0].data = &net->ipv6.sysctl.flush_delay;
++ table[1].data = &net->ipv6.ip6_dst_ops->gc_thresh;
++ table[2].data = &net->ipv6.sysctl.ip6_rt_max_size;
++ table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval;
++ table[4].data = &net->ipv6.sysctl.ip6_rt_gc_timeout;
++ table[5].data = &net->ipv6.sysctl.ip6_rt_gc_interval;
++ table[6].data = &net->ipv6.sysctl.ip6_rt_gc_elasticity;
++ table[7].data = &net->ipv6.sysctl.ip6_rt_mtu_expires;
++ table[8].data = &net->ipv6.sysctl.ip6_rt_min_advmss;
++ }
++
+ return table;
+ }
+ #endif
+
++static int ip6_route_net_init(struct net *net)
++{
++ int ret = -ENOMEM;
++
++ net->ipv6.ip6_dst_ops = kmemdup(&ip6_dst_ops_template,
++ sizeof(*net->ipv6.ip6_dst_ops),
++ GFP_KERNEL);
++ if (!net->ipv6.ip6_dst_ops)
++ goto out;
++ net->ipv6.ip6_dst_ops->dst_net = hold_net(net);
++
++ net->ipv6.ip6_null_entry = kmemdup(&ip6_null_entry_template,
++ sizeof(*net->ipv6.ip6_null_entry),
++ GFP_KERNEL);
++ if (!net->ipv6.ip6_null_entry)
++ goto out_ip6_dst_ops;
++ net->ipv6.ip6_null_entry->u.dst.path =
++ (struct dst_entry *)net->ipv6.ip6_null_entry;
++ net->ipv6.ip6_null_entry->u.dst.ops = net->ipv6.ip6_dst_ops;
++
++#ifdef CONFIG_IPV6_MULTIPLE_TABLES
++ net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template,
++ sizeof(*net->ipv6.ip6_prohibit_entry),
++ GFP_KERNEL);
++ if (!net->ipv6.ip6_prohibit_entry) {
++ kfree(net->ipv6.ip6_null_entry);
++ goto out;
++ }
++ net->ipv6.ip6_prohibit_entry->u.dst.path =
++ (struct dst_entry *)net->ipv6.ip6_prohibit_entry;
++ net->ipv6.ip6_prohibit_entry->u.dst.ops = net->ipv6.ip6_dst_ops;
++
++ net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template,
++ sizeof(*net->ipv6.ip6_blk_hole_entry),
++ GFP_KERNEL);
++ if (!net->ipv6.ip6_blk_hole_entry) {
++ kfree(net->ipv6.ip6_null_entry);
++ kfree(net->ipv6.ip6_prohibit_entry);
++ goto out;
++ }
++ net->ipv6.ip6_blk_hole_entry->u.dst.path =
++ (struct dst_entry *)net->ipv6.ip6_blk_hole_entry;
++ net->ipv6.ip6_blk_hole_entry->u.dst.ops = net->ipv6.ip6_dst_ops;
++#endif
++
++#ifdef CONFIG_PROC_FS
++ proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops);
++ proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops);
++#endif
++ net->ipv6.ip6_rt_gc_expire = 30*HZ;
++
++ ret = 0;
++out:
++ return ret;
++
++out_ip6_dst_ops:
++ release_net(net->ipv6.ip6_dst_ops->dst_net);
++ kfree(net->ipv6.ip6_dst_ops);
++ goto out;
++}
++
++static void ip6_route_net_exit(struct net *net)
++{
++#ifdef CONFIG_PROC_FS
++ proc_net_remove(net, "ipv6_route");
++ proc_net_remove(net, "rt6_stats");
++#endif
++ kfree(net->ipv6.ip6_null_entry);
++#ifdef CONFIG_IPV6_MULTIPLE_TABLES
++ kfree(net->ipv6.ip6_prohibit_entry);
++ kfree(net->ipv6.ip6_blk_hole_entry);
++#endif
++ release_net(net->ipv6.ip6_dst_ops->dst_net);
++ kfree(net->ipv6.ip6_dst_ops);
++}
++
++static struct pernet_operations ip6_route_net_ops = {
++ .init = ip6_route_net_init,
++ .exit = ip6_route_net_exit,
++};
++
++static struct notifier_block ip6_route_dev_notifier = {
++ .notifier_call = ip6_route_dev_notify,
++ .priority = 0,
++};
++
+ int __init ip6_route_init(void)
+ {
+ int ret;
+
+- ip6_dst_ops.kmem_cachep =
++ ret = -ENOMEM;
++ ip6_dst_ops_template.kmem_cachep =
+ kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0,
+ SLAB_HWCACHE_ALIGN, NULL);
+- if (!ip6_dst_ops.kmem_cachep)
+- return -ENOMEM;
+-
+- ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep;
++ if (!ip6_dst_ops_template.kmem_cachep)
++ goto out;;
+
+- ret = fib6_init();
++ ret = register_pernet_subsys(&ip6_route_net_ops);
+ if (ret)
+ goto out_kmem_cache;
+
+- ret = ipv6_route_proc_init(&init_net);
++ /* Registering of the loopback is done before this portion of code,
++ * the loopback reference in rt6_info will not be taken, do it
++ * manually for init_net */
++ init_net.ipv6.ip6_null_entry->u.dst.dev = init_net.loopback_dev;
++ init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
++ #ifdef CONFIG_IPV6_MULTIPLE_TABLES
++ init_net.ipv6.ip6_prohibit_entry->u.dst.dev = init_net.loopback_dev;
++ init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
++ init_net.ipv6.ip6_blk_hole_entry->u.dst.dev = init_net.loopback_dev;
++ init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
++ #endif
++ ret = fib6_init();
+ if (ret)
+- goto out_fib6_init;
++ goto out_register_subsys;
+
+ ret = xfrm6_init();
+ if (ret)
+- goto out_proc_init;
++ goto out_fib6_init;
+
+ ret = fib6_rules_init();
+ if (ret)
+@@ -2543,7 +2742,10 @@ int __init ip6_route_init(void)
+ __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL))
+ goto fib6_rules_init;
+
+- ret = 0;
++ ret = register_netdevice_notifier(&ip6_route_dev_notifier);
++ if (ret)
++ goto fib6_rules_init;
++
+ out:
+ return ret;
+
+@@ -2551,22 +2753,21 @@ fib6_rules_init:
+ fib6_rules_cleanup();
+ xfrm6_init:
+ xfrm6_fini();
+-out_proc_init:
+- ipv6_route_proc_fini(&init_net);
+ out_fib6_init:
+- rt6_ifdown(NULL);
+ fib6_gc_cleanup();
++out_register_subsys:
++ unregister_pernet_subsys(&ip6_route_net_ops);
+ out_kmem_cache:
+- kmem_cache_destroy(ip6_dst_ops.kmem_cachep);
++ kmem_cache_destroy(ip6_dst_ops_template.kmem_cachep);
+ goto out;
+ }
+
+ void ip6_route_cleanup(void)
+ {
++ unregister_netdevice_notifier(&ip6_route_dev_notifier);
+ fib6_rules_cleanup();
+- ipv6_route_proc_fini(&init_net);
+ xfrm6_fini();
+- rt6_ifdown(NULL);
+ fib6_gc_cleanup();
+- kmem_cache_destroy(ip6_dst_ops.kmem_cachep);
++ unregister_pernet_subsys(&ip6_route_net_ops);
++ kmem_cache_destroy(ip6_dst_ops_template.kmem_cachep);
+ }
+diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
+index 1656c00..4b2f103 100644
+--- a/net/ipv6/sit.c
++++ b/net/ipv6/sit.c
+@@ -16,7 +16,7 @@
+ * Changes:
+ * Roger Venning <r.venning at telstra.com>: 6to4 support
+ * Nate Thompson <nate at thebog.net>: 6to4 support
+- * Fred L. Templin <fltemplin at acm.org>: isatap support
++ * Fred Templin <fred.l.templin at boeing.com>: isatap support
+ */
+
+ #include <linux/module.h>
+@@ -52,6 +52,8 @@
+ #include <net/inet_ecn.h>
+ #include <net/xfrm.h>
+ #include <net/dsfield.h>
++#include <net/net_namespace.h>
++#include <net/netns/generic.h>
+
+ /*
+ This version of net/ipv6/sit.c is cloned of net/ipv4/ip_gre.c
+@@ -66,41 +68,47 @@ static int ipip6_fb_tunnel_init(struct net_device *dev);
+ static int ipip6_tunnel_init(struct net_device *dev);
+ static void ipip6_tunnel_setup(struct net_device *dev);
+
+-static struct net_device *ipip6_fb_tunnel_dev;
++static int sit_net_id;
++struct sit_net {
++ struct ip_tunnel *tunnels_r_l[HASH_SIZE];
++ struct ip_tunnel *tunnels_r[HASH_SIZE];
++ struct ip_tunnel *tunnels_l[HASH_SIZE];
++ struct ip_tunnel *tunnels_wc[1];
++ struct ip_tunnel **tunnels[4];
+
+-static struct ip_tunnel *tunnels_r_l[HASH_SIZE];
+-static struct ip_tunnel *tunnels_r[HASH_SIZE];
+-static struct ip_tunnel *tunnels_l[HASH_SIZE];
+-static struct ip_tunnel *tunnels_wc[1];
+-static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunnels_r_l };
++ struct net_device *fb_tunnel_dev;
++};
+
+ static DEFINE_RWLOCK(ipip6_lock);
+
+-static struct ip_tunnel * ipip6_tunnel_lookup(__be32 remote, __be32 local)
++static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net,
++ __be32 remote, __be32 local)
+ {
+ unsigned h0 = HASH(remote);
+ unsigned h1 = HASH(local);
+ struct ip_tunnel *t;
++ struct sit_net *sitn = net_generic(net, sit_net_id);
+
+- for (t = tunnels_r_l[h0^h1]; t; t = t->next) {
++ for (t = sitn->tunnels_r_l[h0^h1]; t; t = t->next) {
+ if (local == t->parms.iph.saddr &&
+ remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
+ return t;
+ }
+- for (t = tunnels_r[h0]; t; t = t->next) {
++ for (t = sitn->tunnels_r[h0]; t; t = t->next) {
+ if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
+ return t;
+ }
+- for (t = tunnels_l[h1]; t; t = t->next) {
++ for (t = sitn->tunnels_l[h1]; t; t = t->next) {
+ if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP))
+ return t;
+ }
+- if ((t = tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP))
++ if ((t = sitn->tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP))
+ return t;
+ return NULL;
+ }
+
+-static struct ip_tunnel **__ipip6_bucket(struct ip_tunnel_parm *parms)
++static struct ip_tunnel **__ipip6_bucket(struct sit_net *sitn,
++ struct ip_tunnel_parm *parms)
+ {
+ __be32 remote = parms->iph.daddr;
+ __be32 local = parms->iph.saddr;
+@@ -115,19 +123,20 @@ static struct ip_tunnel **__ipip6_bucket(struct ip_tunnel_parm *parms)
+ prio |= 1;
+ h ^= HASH(local);
+ }
+- return &tunnels[prio][h];
++ return &sitn->tunnels[prio][h];
+ }
+
+-static inline struct ip_tunnel **ipip6_bucket(struct ip_tunnel *t)
++static inline struct ip_tunnel **ipip6_bucket(struct sit_net *sitn,
++ struct ip_tunnel *t)
+ {
+- return __ipip6_bucket(&t->parms);
++ return __ipip6_bucket(sitn, &t->parms);
+ }
+
+-static void ipip6_tunnel_unlink(struct ip_tunnel *t)
++static void ipip6_tunnel_unlink(struct sit_net *sitn, struct ip_tunnel *t)
+ {
+ struct ip_tunnel **tp;
+
+- for (tp = ipip6_bucket(t); *tp; tp = &(*tp)->next) {
++ for (tp = ipip6_bucket(sitn, t); *tp; tp = &(*tp)->next) {
+ if (t == *tp) {
+ write_lock_bh(&ipip6_lock);
+ *tp = t->next;
+@@ -137,9 +146,9 @@ static void ipip6_tunnel_unlink(struct ip_tunnel *t)
+ }
+ }
+
+-static void ipip6_tunnel_link(struct ip_tunnel *t)
++static void ipip6_tunnel_link(struct sit_net *sitn, struct ip_tunnel *t)
+ {
+- struct ip_tunnel **tp = ipip6_bucket(t);
++ struct ip_tunnel **tp = ipip6_bucket(sitn, t);
+
+ t->next = *tp;
+ write_lock_bh(&ipip6_lock);
+@@ -147,15 +156,17 @@ static void ipip6_tunnel_link(struct ip_tunnel *t)
+ write_unlock_bh(&ipip6_lock);
+ }
+
+-static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int create)
++static struct ip_tunnel * ipip6_tunnel_locate(struct net *net,
++ struct ip_tunnel_parm *parms, int create)
+ {
+ __be32 remote = parms->iph.daddr;
+ __be32 local = parms->iph.saddr;
+ struct ip_tunnel *t, **tp, *nt;
+ struct net_device *dev;
+ char name[IFNAMSIZ];
++ struct sit_net *sitn = net_generic(net, sit_net_id);
+
+- for (tp = __ipip6_bucket(parms); (t = *tp) != NULL; tp = &t->next) {
++ for (tp = __ipip6_bucket(sitn, parms); (t = *tp) != NULL; tp = &t->next) {
+ if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr)
+ return t;
+ }
+@@ -171,6 +182,8 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int
+ if (dev == NULL)
+ return NULL;
+
++ dev_net_set(dev, net);
++
+ if (strchr(name, '%')) {
+ if (dev_alloc_name(dev, name) < 0)
+ goto failed_free;
+@@ -188,7 +201,7 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int
+
+ dev_hold(dev);
+
+- ipip6_tunnel_link(nt);
++ ipip6_tunnel_link(sitn, nt);
+ return nt;
+
+ failed_free:
+@@ -197,15 +210,192 @@ failed:
+ return NULL;
+ }
+
++static struct ip_tunnel_prl_entry *
++__ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr)
++{
++ struct ip_tunnel_prl_entry *p = (struct ip_tunnel_prl_entry *)NULL;
++
++ for (p = t->prl; p; p = p->next)
++ if (p->addr == addr)
++ break;
++ return p;
++
++}
++
++static int ipip6_tunnel_get_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a)
++{
++ struct ip_tunnel_prl *kp;
++ struct ip_tunnel_prl_entry *prl;
++ unsigned int cmax, c = 0, ca, len;
++ int ret = 0;
++
++ cmax = a->datalen / sizeof(*a);
++ if (cmax > 1 && a->addr != htonl(INADDR_ANY))
++ cmax = 1;
++
++ /* For simple GET or for root users,
++ * we try harder to allocate.
++ */
++ kp = (cmax <= 1 || capable(CAP_NET_ADMIN)) ?
++ kcalloc(cmax, sizeof(*kp), GFP_KERNEL) :
++ NULL;
++
++ read_lock(&ipip6_lock);
++
++ ca = t->prl_count < cmax ? t->prl_count : cmax;
++
++ if (!kp) {
++ /* We don't try hard to allocate much memory for
++ * non-root users.
++ * For root users, retry allocating enough memory for
++ * the answer.
++ */
++ kp = kcalloc(ca, sizeof(*kp), GFP_ATOMIC);
++ if (!kp) {
++ ret = -ENOMEM;
++ goto out;
++ }
++ }
++
++ c = 0;
++ for (prl = t->prl; prl; prl = prl->next) {
++ if (c > cmax)
++ break;
++ if (a->addr != htonl(INADDR_ANY) && prl->addr != a->addr)
++ continue;
++ kp[c].addr = prl->addr;
++ kp[c].flags = prl->flags;
++ c++;
++ if (a->addr != htonl(INADDR_ANY))
++ break;
++ }
++out:
++ read_unlock(&ipip6_lock);
++
++ len = sizeof(*kp) * c;
++ ret = len ? copy_to_user(a->data, kp, len) : 0;
++
++ kfree(kp);
++ if (ret)
++ return -EFAULT;
++
++ a->datalen = len;
++ return 0;
++}
++
++static int
++ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg)
++{
++ struct ip_tunnel_prl_entry *p;
++ int err = 0;
++
++ if (a->addr == htonl(INADDR_ANY))
++ return -EINVAL;
++
++ write_lock(&ipip6_lock);
++
++ for (p = t->prl; p; p = p->next) {
++ if (p->addr == a->addr) {
++ if (chg)
++ goto update;
++ err = -EEXIST;
++ goto out;
++ }
++ }
++
++ if (chg) {
++ err = -ENXIO;
++ goto out;
++ }
++
++ p = kzalloc(sizeof(struct ip_tunnel_prl_entry), GFP_KERNEL);
++ if (!p) {
++ err = -ENOBUFS;
++ goto out;
++ }
++
++ p->next = t->prl;
++ t->prl = p;
++ t->prl_count++;
++update:
++ p->addr = a->addr;
++ p->flags = a->flags;
++out:
++ write_unlock(&ipip6_lock);
++ return err;
++}
++
++static int
++ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a)
++{
++ struct ip_tunnel_prl_entry *x, **p;
++ int err = 0;
++
++ write_lock(&ipip6_lock);
++
++ if (a && a->addr != htonl(INADDR_ANY)) {
++ for (p = &t->prl; *p; p = &(*p)->next) {
++ if ((*p)->addr == a->addr) {
++ x = *p;
++ *p = x->next;
++ kfree(x);
++ t->prl_count--;
++ goto out;
++ }
++ }
++ err = -ENXIO;
++ } else {
++ while (t->prl) {
++ x = t->prl;
++ t->prl = t->prl->next;
++ kfree(x);
++ t->prl_count--;
++ }
++ }
++out:
++ write_unlock(&ipip6_lock);
++ return 0;
++}
++
++static int
++isatap_chksrc(struct sk_buff *skb, struct iphdr *iph, struct ip_tunnel *t)
++{
++ struct ip_tunnel_prl_entry *p;
++ int ok = 1;
++
++ read_lock(&ipip6_lock);
++ p = __ipip6_tunnel_locate_prl(t, iph->saddr);
++ if (p) {
++ if (p->flags & PRL_DEFAULT)
++ skb->ndisc_nodetype = NDISC_NODETYPE_DEFAULT;
++ else
++ skb->ndisc_nodetype = NDISC_NODETYPE_NODEFAULT;
++ } else {
++ struct in6_addr *addr6 = &ipv6_hdr(skb)->saddr;
++ if (ipv6_addr_is_isatap(addr6) &&
++ (addr6->s6_addr32[3] == iph->saddr) &&
++ ipv6_chk_prefix(addr6, t->dev))
++ skb->ndisc_nodetype = NDISC_NODETYPE_HOST;
++ else
++ ok = 0;
++ }
++ read_unlock(&ipip6_lock);
++ return ok;
++}
++
+ static void ipip6_tunnel_uninit(struct net_device *dev)
+ {
+- if (dev == ipip6_fb_tunnel_dev) {
++ struct net *net = dev_net(dev);
++ struct sit_net *sitn = net_generic(net, sit_net_id);
++
++ if (dev == sitn->fb_tunnel_dev) {
+ write_lock_bh(&ipip6_lock);
+- tunnels_wc[0] = NULL;
++ sitn->tunnels_wc[0] = NULL;
+ write_unlock_bh(&ipip6_lock);
+ dev_put(dev);
+ } else {
+- ipip6_tunnel_unlink(netdev_priv(dev));
++ ipip6_tunnel_unlink(sitn, netdev_priv(dev));
++ ipip6_tunnel_del_prl(netdev_priv(dev), NULL);
+ dev_put(dev);
+ }
+ }
+@@ -256,7 +446,7 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
+ err = -ENOENT;
+
+ read_lock(&ipip6_lock);
+- t = ipip6_tunnel_lookup(iph->daddr, iph->saddr);
++ t = ipip6_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr);
+ if (t == NULL || t->parms.iph.daddr == 0)
+ goto out;
+
+@@ -339,11 +529,12 @@ out:
+ skb_reset_network_header(skb2);
+
+ /* Try to guess incoming interface */
+- rt6i = rt6_lookup(&iph6->saddr, NULL, NULL, 0);
++ rt6i = rt6_lookup(dev_net(skb->dev), &iph6->saddr, NULL, NULL, 0);
+ if (rt6i && rt6i->rt6i_dev) {
+ skb2->dev = rt6i->rt6i_dev;
+
+- rt6i = rt6_lookup(&iph6->daddr, &iph6->saddr, NULL, 0);
++ rt6i = rt6_lookup(dev_net(skb->dev),
++ &iph6->daddr, &iph6->saddr, NULL, 0);
+
+ if (rt6i && rt6i->rt6i_dev && rt6i->rt6i_dev->type == ARPHRD_SIT) {
+ struct ip_tunnel *t = netdev_priv(rt6i->rt6i_dev);
+@@ -365,48 +556,6 @@ static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
+ IP6_ECN_set_ce(ipv6_hdr(skb));
+ }
+
+-/* ISATAP (RFC4214) - check source address */
+-static int
+-isatap_srcok(struct sk_buff *skb, struct iphdr *iph, struct net_device *dev)
+-{
+- struct neighbour *neigh;
+- struct dst_entry *dst;
+- struct rt6_info *rt;
+- struct flowi fl;
+- struct in6_addr *addr6;
+- struct in6_addr rtr;
+- struct ipv6hdr *iph6;
+- int ok = 0;
+-
+- /* from onlink default router */
+- ipv6_addr_set(&rtr, htonl(0xFE800000), 0, 0, 0);
+- ipv6_isatap_eui64(rtr.s6_addr + 8, iph->saddr);
+- if ((rt = rt6_get_dflt_router(&rtr, dev))) {
+- dst_release(&rt->u.dst);
+- return 1;
+- }
+-
+- iph6 = ipv6_hdr(skb);
+- memset(&fl, 0, sizeof(fl));
+- fl.proto = iph6->nexthdr;
+- ipv6_addr_copy(&fl.fl6_dst, &iph6->saddr);
+- fl.oif = dev->ifindex;
+- security_skb_classify_flow(skb, &fl);
+-
+- dst = ip6_route_output(NULL, &fl);
+- if (!dst->error && (dst->dev == dev) && (neigh = dst->neighbour)) {
+-
+- addr6 = (struct in6_addr*)&neigh->primary_key;
+-
+- /* from correct previous hop */
+- if (ipv6_addr_is_isatap(addr6) &&
+- (addr6->s6_addr32[3] == iph->saddr))
+- ok = 1;
+- }
+- dst_release(dst);
+- return ok;
+-}
+-
+ static int ipip6_rcv(struct sk_buff *skb)
+ {
+ struct iphdr *iph;
+@@ -418,7 +567,8 @@ static int ipip6_rcv(struct sk_buff *skb)
+ iph = ip_hdr(skb);
+
+ read_lock(&ipip6_lock);
+- if ((tunnel = ipip6_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
++ if ((tunnel = ipip6_tunnel_lookup(dev_net(skb->dev),
++ iph->saddr, iph->daddr)) != NULL) {
+ secpath_reset(skb);
+ skb->mac_header = skb->network_header;
+ skb_reset_network_header(skb);
+@@ -427,7 +577,7 @@ static int ipip6_rcv(struct sk_buff *skb)
+ skb->pkt_type = PACKET_HOST;
+
+ if ((tunnel->dev->priv_flags & IFF_ISATAP) &&
+- !isatap_srcok(skb, iph, tunnel->dev)) {
++ !isatap_chksrc(skb, iph, tunnel)) {
+ tunnel->stat.rx_errors++;
+ read_unlock(&ipip6_lock);
+ kfree_skb(skb);
+@@ -554,7 +704,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+ .tos = RT_TOS(tos) } },
+ .oif = tunnel->parms.link,
+ .proto = IPPROTO_IPV6 };
+- if (ip_route_output_key(&init_net, &rt, &fl)) {
++ if (ip_route_output_key(dev_net(dev), &rt, &fl)) {
+ tunnel->stat.tx_carrier_errors++;
+ goto tx_error_icmp;
+ }
+@@ -683,7 +833,7 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
+ .oif = tunnel->parms.link,
+ .proto = IPPROTO_IPV6 };
+ struct rtable *rt;
+- if (!ip_route_output_key(&init_net, &rt, &fl)) {
++ if (!ip_route_output_key(dev_net(dev), &rt, &fl)) {
+ tdev = rt->u.dst.dev;
+ ip_rt_put(rt);
+ }
+@@ -691,7 +841,7 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
+ }
+
+ if (!tdev && tunnel->parms.link)
+- tdev = __dev_get_by_index(&init_net, tunnel->parms.link);
++ tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link);
+
+ if (tdev) {
+ dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
+@@ -707,17 +857,20 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ {
+ int err = 0;
+ struct ip_tunnel_parm p;
++ struct ip_tunnel_prl prl;
+ struct ip_tunnel *t;
++ struct net *net = dev_net(dev);
++ struct sit_net *sitn = net_generic(net, sit_net_id);
+
+ switch (cmd) {
+ case SIOCGETTUNNEL:
+ t = NULL;
+- if (dev == ipip6_fb_tunnel_dev) {
++ if (dev == sitn->fb_tunnel_dev) {
+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) {
+ err = -EFAULT;
+ break;
+ }
+- t = ipip6_tunnel_locate(&p, 0);
++ t = ipip6_tunnel_locate(net, &p, 0);
+ }
+ if (t == NULL)
+ t = netdev_priv(dev);
+@@ -743,9 +896,9 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ if (p.iph.ttl)
+ p.iph.frag_off |= htons(IP_DF);
+
+- t = ipip6_tunnel_locate(&p, cmd == SIOCADDTUNNEL);
++ t = ipip6_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL);
+
+- if (dev != ipip6_fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
++ if (dev != sitn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) {
+ if (t != NULL) {
+ if (t->dev != dev) {
+ err = -EEXIST;
+@@ -758,12 +911,12 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ break;
+ }
+ t = netdev_priv(dev);
+- ipip6_tunnel_unlink(t);
++ ipip6_tunnel_unlink(sitn, t);
+ t->parms.iph.saddr = p.iph.saddr;
+ t->parms.iph.daddr = p.iph.daddr;
+ memcpy(dev->dev_addr, &p.iph.saddr, 4);
+ memcpy(dev->broadcast, &p.iph.daddr, 4);
+- ipip6_tunnel_link(t);
++ ipip6_tunnel_link(sitn, t);
+ netdev_state_change(dev);
+ }
+ }
+@@ -790,15 +943,15 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ if (!capable(CAP_NET_ADMIN))
+ goto done;
+
+- if (dev == ipip6_fb_tunnel_dev) {
++ if (dev == sitn->fb_tunnel_dev) {
+ err = -EFAULT;
+ if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
+ goto done;
+ err = -ENOENT;
+- if ((t = ipip6_tunnel_locate(&p, 0)) == NULL)
++ if ((t = ipip6_tunnel_locate(net, &p, 0)) == NULL)
+ goto done;
+ err = -EPERM;
+- if (t == netdev_priv(ipip6_fb_tunnel_dev))
++ if (t == netdev_priv(sitn->fb_tunnel_dev))
+ goto done;
+ dev = t->dev;
+ }
+@@ -806,6 +959,42 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+ err = 0;
+ break;
+
++ case SIOCGETPRL:
++ case SIOCADDPRL:
++ case SIOCDELPRL:
++ case SIOCCHGPRL:
++ err = -EPERM;
++ if (cmd != SIOCGETPRL && !capable(CAP_NET_ADMIN))
++ goto done;
++ err = -EINVAL;
++ if (dev == sitn->fb_tunnel_dev)
++ goto done;
++ err = -EFAULT;
++ if (copy_from_user(&prl, ifr->ifr_ifru.ifru_data, sizeof(prl)))
++ goto done;
++ err = -ENOENT;
++ if (!(t = netdev_priv(dev)))
++ goto done;
++
++ switch (cmd) {
++ case SIOCGETPRL:
++ err = ipip6_tunnel_get_prl(t, &prl);
++ if (!err && copy_to_user(ifr->ifr_ifru.ifru_data,
++ &prl, sizeof(prl)))
++ err = -EFAULT;
++ break;
++ case SIOCDELPRL:
++ err = ipip6_tunnel_del_prl(t, &prl);
++ break;
++ case SIOCADDPRL:
++ case SIOCCHGPRL:
++ err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL);
++ break;
++ }
++ if (cmd != SIOCGETPRL)
++ netdev_state_change(dev);
++ break;
++
+ default:
+ err = -EINVAL;
+ }
+@@ -842,6 +1031,7 @@ static void ipip6_tunnel_setup(struct net_device *dev)
+ dev->flags = IFF_NOARP;
+ dev->iflink = 0;
+ dev->addr_len = 4;
++ dev->features |= NETIF_F_NETNS_LOCAL;
+ }
+
+ static int ipip6_tunnel_init(struct net_device *dev)
+@@ -861,10 +1051,12 @@ static int ipip6_tunnel_init(struct net_device *dev)
+ return 0;
+ }
+
+-static int __init ipip6_fb_tunnel_init(struct net_device *dev)
++static int ipip6_fb_tunnel_init(struct net_device *dev)
+ {
+ struct ip_tunnel *tunnel = netdev_priv(dev);
+ struct iphdr *iph = &tunnel->parms.iph;
++ struct net *net = dev_net(dev);
++ struct sit_net *sitn = net_generic(net, sit_net_id);
+
+ tunnel->dev = dev;
+ strcpy(tunnel->parms.name, dev->name);
+@@ -875,7 +1067,7 @@ static int __init ipip6_fb_tunnel_init(struct net_device *dev)
+ iph->ttl = 64;
+
+ dev_hold(dev);
+- tunnels_wc[0] = tunnel;
++ sitn->tunnels_wc[0] = tunnel;
+ return 0;
+ }
+
+@@ -885,7 +1077,7 @@ static struct xfrm_tunnel sit_handler = {
+ .priority = 1,
+ };
+
+-static void __exit sit_destroy_tunnels(void)
++static void sit_destroy_tunnels(struct sit_net *sitn)
+ {
+ int prio;
+
+@@ -893,20 +1085,78 @@ static void __exit sit_destroy_tunnels(void)
+ int h;
+ for (h = 0; h < HASH_SIZE; h++) {
+ struct ip_tunnel *t;
+- while ((t = tunnels[prio][h]) != NULL)
++ while ((t = sitn->tunnels[prio][h]) != NULL)
+ unregister_netdevice(t->dev);
+ }
+ }
+ }
+
+-static void __exit sit_cleanup(void)
++static int sit_init_net(struct net *net)
+ {
+- xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
++ int err;
++ struct sit_net *sitn;
++
++ err = -ENOMEM;
++ sitn = kzalloc(sizeof(struct sit_net), GFP_KERNEL);
++ if (sitn == NULL)
++ goto err_alloc;
++
++ err = net_assign_generic(net, sit_net_id, sitn);
++ if (err < 0)
++ goto err_assign;
++
++ sitn->tunnels[0] = sitn->tunnels_wc;
++ sitn->tunnels[1] = sitn->tunnels_l;
++ sitn->tunnels[2] = sitn->tunnels_r;
++ sitn->tunnels[3] = sitn->tunnels_r_l;
++
++ sitn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0",
++ ipip6_tunnel_setup);
++ if (!sitn->fb_tunnel_dev) {
++ err = -ENOMEM;
++ goto err_alloc_dev;
++ }
++
++ sitn->fb_tunnel_dev->init = ipip6_fb_tunnel_init;
++ dev_net_set(sitn->fb_tunnel_dev, net);
++
++ if ((err = register_netdev(sitn->fb_tunnel_dev)))
++ goto err_reg_dev;
+
++ return 0;
++
++err_reg_dev:
++ free_netdev(sitn->fb_tunnel_dev);
++err_alloc_dev:
++ /* nothing */
++err_assign:
++ kfree(sitn);
++err_alloc:
++ return err;
++}
++
++static void sit_exit_net(struct net *net)
++{
++ struct sit_net *sitn;
++
++ sitn = net_generic(net, sit_net_id);
+ rtnl_lock();
+- sit_destroy_tunnels();
+- unregister_netdevice(ipip6_fb_tunnel_dev);
++ sit_destroy_tunnels(sitn);
++ unregister_netdevice(sitn->fb_tunnel_dev);
+ rtnl_unlock();
++ kfree(sitn);
++}
++
++static struct pernet_operations sit_net_ops = {
++ .init = sit_init_net,
++ .exit = sit_exit_net,
++};
++
++static void __exit sit_cleanup(void)
++{
++ xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
++
++ unregister_pernet_gen_device(sit_net_id, &sit_net_ops);
+ }
+
+ static int __init sit_init(void)
+@@ -920,25 +1170,11 @@ static int __init sit_init(void)
+ return -EAGAIN;
+ }
+
+- ipip6_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0",
+- ipip6_tunnel_setup);
+- if (!ipip6_fb_tunnel_dev) {
+- err = -ENOMEM;
+- goto err1;
+- }
+-
+- ipip6_fb_tunnel_dev->init = ipip6_fb_tunnel_init;
++ err = register_pernet_gen_device(&sit_net_id, &sit_net_ops);
++ if (err < 0)
++ xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
+
+- if ((err = register_netdev(ipip6_fb_tunnel_dev)))
+- goto err2;
+-
+- out:
+ return err;
+- err2:
+- free_netdev(ipip6_fb_tunnel_dev);
+- err1:
+- xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
+- goto out;
+ }
+
+ module_init(sit_init);
+diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
+new file mode 100644
+index 0000000..938ce4e
+--- /dev/null
++++ b/net/ipv6/syncookies.c
+@@ -0,0 +1,279 @@
++/*
++ * IPv6 Syncookies implementation for the Linux kernel
++ *
++ * Authors:
++ * Glenn Griffin <ggriffin.kernel at gmail.com>
++ *
++ * Based on IPv4 implementation by Andi Kleen
++ * linux/net/ipv4/syncookies.c
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ */
++
++#include <linux/tcp.h>
++#include <linux/random.h>
++#include <linux/cryptohash.h>
++#include <linux/kernel.h>
++#include <net/ipv6.h>
++#include <net/tcp.h>
++
++extern int sysctl_tcp_syncookies;
++extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS];
++
++#define COOKIEBITS 24 /* Upper bits store count */
++#define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)
++
++/*
++ * This table has to be sorted and terminated with (__u16)-1.
++ * XXX generate a better table.
++ * Unresolved Issues: HIPPI with a 64k MSS is not well supported.
++ *
++ * Taken directly from ipv4 implementation.
++ * Should this list be modified for ipv6 use or is it close enough?
++ * rfc 2460 8.3 suggests mss values 20 bytes less than ipv4 counterpart
++ */
++static __u16 const msstab[] = {
++ 64 - 1,
++ 256 - 1,
++ 512 - 1,
++ 536 - 1,
++ 1024 - 1,
++ 1440 - 1,
++ 1460 - 1,
++ 4312 - 1,
++ (__u16)-1
++};
++/* The number doesn't include the -1 terminator */
++#define NUM_MSS (ARRAY_SIZE(msstab) - 1)
++
++/*
++ * This (misnamed) value is the age of syncookie which is permitted.
++ * Its ideal value should be dependent on TCP_TIMEOUT_INIT and
++ * sysctl_tcp_retries1. It's a rather complicated formula (exponential
++ * backoff) to compute at runtime so it's currently hardcoded here.
++ */
++#define COUNTER_TRIES 4
++
++static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
++ struct request_sock *req,
++ struct dst_entry *dst)
++{
++ struct inet_connection_sock *icsk = inet_csk(sk);
++ struct sock *child;
++
++ child = icsk->icsk_af_ops->syn_recv_sock(sk, skb, req, dst);
++ if (child)
++ inet_csk_reqsk_queue_add(sk, req, child);
++ else
++ reqsk_free(req);
++
++ return child;
++}
++
++static DEFINE_PER_CPU(__u32, cookie_scratch)[16 + 5 + SHA_WORKSPACE_WORDS];
++
++static u32 cookie_hash(struct in6_addr *saddr, struct in6_addr *daddr,
++ __be16 sport, __be16 dport, u32 count, int c)
++{
++ __u32 *tmp = __get_cpu_var(cookie_scratch);
++
++ /*
++ * we have 320 bits of information to hash, copy in the remaining
++ * 192 bits required for sha_transform, from the syncookie_secret
++ * and overwrite the digest with the secret
++ */
++ memcpy(tmp + 10, syncookie_secret[c], 44);
++ memcpy(tmp, saddr, 16);
++ memcpy(tmp + 4, daddr, 16);
++ tmp[8] = ((__force u32)sport << 16) + (__force u32)dport;
++ tmp[9] = count;
++ sha_transform(tmp + 16, (__u8 *)tmp, tmp + 16 + 5);
++
++ return tmp[17];
++}
++
++static __u32 secure_tcp_syn_cookie(struct in6_addr *saddr, struct in6_addr *daddr,
++ __be16 sport, __be16 dport, __u32 sseq,
++ __u32 count, __u32 data)
++{
++ return (cookie_hash(saddr, daddr, sport, dport, 0, 0) +
++ sseq + (count << COOKIEBITS) +
++ ((cookie_hash(saddr, daddr, sport, dport, count, 1) + data)
++ & COOKIEMASK));
++}
++
++static __u32 check_tcp_syn_cookie(__u32 cookie, struct in6_addr *saddr,
++ struct in6_addr *daddr, __be16 sport,
++ __be16 dport, __u32 sseq, __u32 count,
++ __u32 maxdiff)
++{
++ __u32 diff;
++
++ cookie -= cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq;
++
++ diff = (count - (cookie >> COOKIEBITS)) & ((__u32) -1 >> COOKIEBITS);
++ if (diff >= maxdiff)
++ return (__u32)-1;
++
++ return (cookie -
++ cookie_hash(saddr, daddr, sport, dport, count - diff, 1))
++ & COOKIEMASK;
++}
++
++__u32 cookie_v6_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp)
++{
++ struct ipv6hdr *iph = ipv6_hdr(skb);
++ const struct tcphdr *th = tcp_hdr(skb);
++ int mssind;
++ const __u16 mss = *mssp;
++
++ tcp_sk(sk)->last_synq_overflow = jiffies;
++
++ for (mssind = 0; mss > msstab[mssind + 1]; mssind++)
++ ;
++ *mssp = msstab[mssind] + 1;
++
++ NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESSENT);
++
++ return secure_tcp_syn_cookie(&iph->saddr, &iph->daddr, th->source,
++ th->dest, ntohl(th->seq),
++ jiffies / (HZ * 60), mssind);
++}
++
++static inline int cookie_check(struct sk_buff *skb, __u32 cookie)
++{
++ struct ipv6hdr *iph = ipv6_hdr(skb);
++ const struct tcphdr *th = tcp_hdr(skb);
++ __u32 seq = ntohl(th->seq) - 1;
++ __u32 mssind = check_tcp_syn_cookie(cookie, &iph->saddr, &iph->daddr,
++ th->source, th->dest, seq,
++ jiffies / (HZ * 60), COUNTER_TRIES);
++
++ return mssind < NUM_MSS ? msstab[mssind] + 1 : 0;
++}
++
++struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
++{
++ struct inet_request_sock *ireq;
++ struct inet6_request_sock *ireq6;
++ struct tcp_request_sock *treq;
++ struct ipv6_pinfo *np = inet6_sk(sk);
++ struct tcp_sock *tp = tcp_sk(sk);
++ const struct tcphdr *th = tcp_hdr(skb);
++ __u32 cookie = ntohl(th->ack_seq) - 1;
++ struct sock *ret = sk;
++ struct request_sock *req;
++ int mss;
++ struct dst_entry *dst;
++ __u8 rcv_wscale;
++ struct tcp_options_received tcp_opt;
++
++ if (!sysctl_tcp_syncookies || !th->ack)
++ goto out;
++
++ if (time_after(jiffies, tp->last_synq_overflow + TCP_TIMEOUT_INIT) ||
++ (mss = cookie_check(skb, cookie)) == 0) {
++ NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESFAILED);
++ goto out;
++ }
++
++ NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESRECV);
++
++ /* check for timestamp cookie support */
++ memset(&tcp_opt, 0, sizeof(tcp_opt));
++ tcp_parse_options(skb, &tcp_opt, 0);
++
++ if (tcp_opt.saw_tstamp)
++ cookie_check_timestamp(&tcp_opt);
++
++ ret = NULL;
++ req = inet6_reqsk_alloc(&tcp6_request_sock_ops);
++ if (!req)
++ goto out;
++
++ ireq = inet_rsk(req);
++ ireq6 = inet6_rsk(req);
++ treq = tcp_rsk(req);
++ ireq6->pktopts = NULL;
++
++ if (security_inet_conn_request(sk, skb, req)) {
++ reqsk_free(req);
++ goto out;
++ }
++
++ req->mss = mss;
++ ireq->rmt_port = th->source;
++ ipv6_addr_copy(&ireq6->rmt_addr, &ipv6_hdr(skb)->saddr);
++ ipv6_addr_copy(&ireq6->loc_addr, &ipv6_hdr(skb)->daddr);
++ if (ipv6_opt_accepted(sk, skb) ||
++ np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
++ np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
++ atomic_inc(&skb->users);
++ ireq6->pktopts = skb;
++ }
++
++ ireq6->iif = sk->sk_bound_dev_if;
++ /* So that link locals have meaning */
++ if (!sk->sk_bound_dev_if &&
++ ipv6_addr_type(&ireq6->rmt_addr) & IPV6_ADDR_LINKLOCAL)
++ ireq6->iif = inet6_iif(skb);
++
++ req->expires = 0UL;
++ req->retrans = 0;
++ ireq->snd_wscale = tcp_opt.snd_wscale;
++ ireq->rcv_wscale = tcp_opt.rcv_wscale;
++ ireq->sack_ok = tcp_opt.sack_ok;
++ ireq->wscale_ok = tcp_opt.wscale_ok;
++ ireq->tstamp_ok = tcp_opt.saw_tstamp;
++ req->ts_recent = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0;
++ treq->rcv_isn = ntohl(th->seq) - 1;
++ treq->snt_isn = cookie;
++
++ /*
++ * We need to lookup the dst_entry to get the correct window size.
++ * This is taken from tcp_v6_syn_recv_sock. Somebody please enlighten
++ * me if there is a preferred way.
++ */
++ {
++ struct in6_addr *final_p = NULL, final;
++ struct flowi fl;
++ memset(&fl, 0, sizeof(fl));
++ fl.proto = IPPROTO_TCP;
++ ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
++ if (np->opt && np->opt->srcrt) {
++ struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
++ ipv6_addr_copy(&final, &fl.fl6_dst);
++ ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
++ final_p = &final;
++ }
++ ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr);
++ fl.oif = sk->sk_bound_dev_if;
++ fl.fl_ip_dport = inet_rsk(req)->rmt_port;
++ fl.fl_ip_sport = inet_sk(sk)->sport;
++ security_req_classify_flow(req, &fl);
++ if (ip6_dst_lookup(sk, &dst, &fl)) {
++ reqsk_free(req);
++ goto out;
++ }
++ if (final_p)
++ ipv6_addr_copy(&fl.fl6_dst, final_p);
++ if ((xfrm_lookup(&dst, &fl, sk, 0)) < 0)
++ goto out;
++ }
++
++ req->window_clamp = tp->window_clamp ? :dst_metric(dst, RTAX_WINDOW);
++ tcp_select_initial_window(tcp_full_space(sk), req->mss,
++ &req->rcv_wnd, &req->window_clamp,
++ ireq->wscale_ok, &rcv_wscale);
++
++ ireq->rcv_wscale = rcv_wscale;
++
++ ret = get_cookie_sock(sk, skb, req, dst);
++
++out: return ret;
++}
++
+diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
+index d6d3e68..3804dcb 100644
+--- a/net/ipv6/sysctl_net_ipv6.c
++++ b/net/ipv6/sysctl_net_ipv6.c
+@@ -71,24 +71,11 @@ static int ipv6_sysctl_net_init(struct net *net)
+ ipv6_route_table = ipv6_route_sysctl_init(net);
+ if (!ipv6_route_table)
+ goto out_ipv6_table;
++ ipv6_table[0].child = ipv6_route_table;
+
+ ipv6_icmp_table = ipv6_icmp_sysctl_init(net);
+ if (!ipv6_icmp_table)
+ goto out_ipv6_route_table;
+-
+- ipv6_route_table[0].data = &net->ipv6.sysctl.flush_delay;
+- /* ipv6_route_table[1].data will be handled when we have
+- routes per namespace */
+- ipv6_route_table[2].data = &net->ipv6.sysctl.ip6_rt_max_size;
+- ipv6_route_table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval;
+- ipv6_route_table[4].data = &net->ipv6.sysctl.ip6_rt_gc_timeout;
+- ipv6_route_table[5].data = &net->ipv6.sysctl.ip6_rt_gc_interval;
+- ipv6_route_table[6].data = &net->ipv6.sysctl.ip6_rt_gc_elasticity;
+- ipv6_route_table[7].data = &net->ipv6.sysctl.ip6_rt_mtu_expires;
+- ipv6_route_table[8].data = &net->ipv6.sysctl.ip6_rt_min_advmss;
+- ipv6_table[0].child = ipv6_route_table;
+-
+- ipv6_icmp_table[0].data = &net->ipv6.sysctl.icmpv6_time;
+ ipv6_table[1].child = ipv6_icmp_table;
+
+ ipv6_table[2].data = &net->ipv6.sysctl.bindv6only;
+diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
+index 12750f2..715965f 100644
+--- a/net/ipv6/tcp_ipv6.c
++++ b/net/ipv6/tcp_ipv6.c
+@@ -60,6 +60,7 @@
+ #include <net/dsfield.h>
+ #include <net/timewait_sock.h>
+ #include <net/netdma.h>
++#include <net/inet_common.h>
+
+ #include <asm/uaccess.h>
+
+@@ -69,9 +70,6 @@
+ #include <linux/crypto.h>
+ #include <linux/scatterlist.h>
+
+-/* Socket used for sending RSTs and ACKs */
+-static struct socket *tcp6_socket;
+-
+ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb);
+ static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req);
+ static void tcp_v6_send_check(struct sock *sk, int len,
+@@ -324,7 +322,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ struct tcp_sock *tp;
+ __u32 seq;
+
+- sk = inet6_lookup(skb->dev->nd_net, &tcp_hashinfo, &hdr->daddr,
++ sk = inet6_lookup(dev_net(skb->dev), &tcp_hashinfo, &hdr->daddr,
+ th->dest, &hdr->saddr, th->source, skb->dev->ifindex);
+
+ if (sk == NULL) {
+@@ -455,8 +453,7 @@ out:
+ }
+
+
+-static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
+- struct dst_entry *dst)
++static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req)
+ {
+ struct inet6_request_sock *treq = inet6_rsk(req);
+ struct ipv6_pinfo *np = inet6_sk(sk);
+@@ -464,6 +461,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
+ struct ipv6_txoptions *opt = NULL;
+ struct in6_addr * final_p = NULL, final;
+ struct flowi fl;
++ struct dst_entry *dst;
+ int err = -1;
+
+ memset(&fl, 0, sizeof(fl));
+@@ -476,24 +474,22 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
+ fl.fl_ip_sport = inet_sk(sk)->sport;
+ security_req_classify_flow(req, &fl);
+
+- if (dst == NULL) {
+- opt = np->opt;
+- if (opt && opt->srcrt) {
+- struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
+- ipv6_addr_copy(&final, &fl.fl6_dst);
+- ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+- final_p = &final;
+- }
+-
+- err = ip6_dst_lookup(sk, &dst, &fl);
+- if (err)
+- goto done;
+- if (final_p)
+- ipv6_addr_copy(&fl.fl6_dst, final_p);
+- if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
+- goto done;
++ opt = np->opt;
++ if (opt && opt->srcrt) {
++ struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
++ ipv6_addr_copy(&final, &fl.fl6_dst);
++ ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
++ final_p = &final;
+ }
+
++ err = ip6_dst_lookup(sk, &dst, &fl);
++ if (err)
++ goto done;
++ if (final_p)
++ ipv6_addr_copy(&fl.fl6_dst, final_p);
++ if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
++ goto done;
++
+ skb = tcp_make_synack(sk, dst, req);
+ if (skb) {
+ struct tcphdr *th = tcp_hdr(skb);
+@@ -514,6 +510,20 @@ done:
+ return err;
+ }
+
++static inline void syn_flood_warning(struct sk_buff *skb)
++{
++#ifdef CONFIG_SYN_COOKIES
++ if (sysctl_tcp_syncookies)
++ printk(KERN_INFO
++ "TCPv6: Possible SYN flooding on port %d. "
++ "Sending cookies.\n", ntohs(tcp_hdr(skb)->dest));
++ else
++#endif
++ printk(KERN_INFO
++ "TCPv6: Possible SYN flooding on port %d. "
++ "Dropping request.\n", ntohs(tcp_hdr(skb)->dest));
++}
++
+ static void tcp_v6_reqsk_destructor(struct request_sock *req)
+ {
+ if (inet6_rsk(req)->pktopts)
+@@ -533,7 +543,7 @@ static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk,
+ return NULL;
+
+ for (i = 0; i < tp->md5sig_info->entries6; i++) {
+- if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, addr) == 0)
++ if (ipv6_addr_equal(&tp->md5sig_info->keys6[i].addr, addr))
+ return &tp->md5sig_info->keys6[i].base;
+ }
+ return NULL;
+@@ -622,7 +632,7 @@ static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer)
+ int i;
+
+ for (i = 0; i < tp->md5sig_info->entries6; i++) {
+- if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, peer) == 0) {
++ if (ipv6_addr_equal(&tp->md5sig_info->keys6[i].addr, peer)) {
+ /* Free the key */
+ kfree(tp->md5sig_info->keys6[i].base.key);
+ tp->md5sig_info->entries6--;
+@@ -741,7 +751,7 @@ static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
+
+ hp = tcp_get_md5sig_pool();
+ if (!hp) {
+- printk(KERN_WARNING "%s(): hash pool not found...\n", __FUNCTION__);
++ printk(KERN_WARNING "%s(): hash pool not found...\n", __func__);
+ goto clear_hash_noput;
+ }
+ bp = &hp->md5_blk.ip6;
+@@ -781,17 +791,17 @@ static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
+ /* Now store the hash into the packet */
+ err = crypto_hash_init(desc);
+ if (err) {
+- printk(KERN_WARNING "%s(): hash_init failed\n", __FUNCTION__);
++ printk(KERN_WARNING "%s(): hash_init failed\n", __func__);
+ goto clear_hash;
+ }
+ err = crypto_hash_update(desc, sg, nbytes);
+ if (err) {
+- printk(KERN_WARNING "%s(): hash_update failed\n", __FUNCTION__);
++ printk(KERN_WARNING "%s(): hash_update failed\n", __func__);
+ goto clear_hash;
+ }
+ err = crypto_hash_final(desc, md5_hash);
+ if (err) {
+- printk(KERN_WARNING "%s(): hash_final failed\n", __FUNCTION__);
++ printk(KERN_WARNING "%s(): hash_final failed\n", __func__);
+ goto clear_hash;
+ }
+
+@@ -917,7 +927,7 @@ done_opts:
+ }
+ #endif
+
+-static struct request_sock_ops tcp6_request_sock_ops __read_mostly = {
++struct request_sock_ops tcp6_request_sock_ops __read_mostly = {
+ .family = AF_INET6,
+ .obj_size = sizeof(struct tcp6_request_sock),
+ .rtx_syn_ack = tcp_v6_send_synack,
+@@ -979,6 +989,8 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
+ struct tcphdr *th = tcp_hdr(skb), *t1;
+ struct sk_buff *buff;
+ struct flowi fl;
++ struct net *net = dev_net(skb->dst->dev);
++ struct sock *ctl_sk = net->ipv6.tcp_sk;
+ unsigned int tot_len = sizeof(*th);
+ #ifdef CONFIG_TCP_MD5SIG
+ struct tcp_md5sig_key *key;
+@@ -1059,11 +1071,14 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
+ fl.fl_ip_sport = t1->source;
+ security_skb_classify_flow(skb, &fl);
+
+- /* sk = NULL, but it is safe for now. RST socket required. */
+- if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
++ /* Pass a socket to ip6_dst_lookup either it is for RST
++ * Underlying function will use this to retrieve the network
++ * namespace
++ */
++ if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) {
+
+ if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) {
+- ip6_xmit(tcp6_socket->sk, buff, &fl, NULL, 0);
++ ip6_xmit(ctl_sk, buff, &fl, NULL, 0);
+ TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
+ TCP_INC_STATS_BH(TCP_MIB_OUTRSTS);
+ return;
+@@ -1079,6 +1094,8 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw,
+ struct tcphdr *th = tcp_hdr(skb), *t1;
+ struct sk_buff *buff;
+ struct flowi fl;
++ struct net *net = dev_net(skb->dev);
++ struct sock *ctl_sk = net->ipv6.tcp_sk;
+ unsigned int tot_len = sizeof(struct tcphdr);
+ __be32 *topt;
+ #ifdef CONFIG_TCP_MD5SIG
+@@ -1160,9 +1177,9 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw,
+ fl.fl_ip_sport = t1->source;
+ security_skb_classify_flow(skb, &fl);
+
+- if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
++ if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) {
+ if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) {
+- ip6_xmit(tcp6_socket->sk, buff, &fl, NULL, 0);
++ ip6_xmit(ctl_sk, buff, &fl, NULL, 0);
+ TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
+ return;
+ }
+@@ -1202,7 +1219,7 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
+ if (req)
+ return tcp_check_req(sk, skb, req, prev);
+
+- nsk = __inet6_lookup_established(sk->sk_net, &tcp_hashinfo,
++ nsk = __inet6_lookup_established(sock_net(sk), &tcp_hashinfo,
+ &ipv6_hdr(skb)->saddr, th->source,
+ &ipv6_hdr(skb)->daddr, ntohs(th->dest), inet6_iif(skb));
+
+@@ -1215,9 +1232,9 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
+ return NULL;
+ }
+
+-#if 0 /*def CONFIG_SYN_COOKIES*/
++#ifdef CONFIG_SYN_COOKIES
+ if (!th->rst && !th->syn && th->ack)
+- sk = cookie_v6_check(sk, skb, &(IPCB(skb)->opt));
++ sk = cookie_v6_check(sk, skb);
+ #endif
+ return sk;
+ }
+@@ -1233,6 +1250,11 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct request_sock *req = NULL;
+ __u32 isn = TCP_SKB_CB(skb)->when;
++#ifdef CONFIG_SYN_COOKIES
++ int want_cookie = 0;
++#else
++#define want_cookie 0
++#endif
+
+ if (skb->protocol == htons(ETH_P_IP))
+ return tcp_v4_conn_request(sk, skb);
+@@ -1240,12 +1262,14 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
+ if (!ipv6_unicast_destination(skb))
+ goto drop;
+
+- /*
+- * There are no SYN attacks on IPv6, yet...
+- */
+ if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
+ if (net_ratelimit())
+- printk(KERN_INFO "TCPv6: dropping request, synflood is possible\n");
++ syn_flood_warning(skb);
++#ifdef CONFIG_SYN_COOKIES
++ if (sysctl_tcp_syncookies)
++ want_cookie = 1;
++ else
++#endif
+ goto drop;
+ }
+
+@@ -1266,39 +1290,50 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
+
+ tcp_parse_options(skb, &tmp_opt, 0);
+
++ if (want_cookie && !tmp_opt.saw_tstamp)
++ tcp_clear_options(&tmp_opt);
++
+ tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
+ tcp_openreq_init(req, &tmp_opt, skb);
+
+ treq = inet6_rsk(req);
+ ipv6_addr_copy(&treq->rmt_addr, &ipv6_hdr(skb)->saddr);
+ ipv6_addr_copy(&treq->loc_addr, &ipv6_hdr(skb)->daddr);
+- TCP_ECN_create_request(req, tcp_hdr(skb));
+ treq->pktopts = NULL;
+- if (ipv6_opt_accepted(sk, skb) ||
+- np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
+- np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
+- atomic_inc(&skb->users);
+- treq->pktopts = skb;
+- }
+- treq->iif = sk->sk_bound_dev_if;
++ if (!want_cookie)
++ TCP_ECN_create_request(req, tcp_hdr(skb));
++
++ if (want_cookie) {
++ isn = cookie_v6_init_sequence(sk, skb, &req->mss);
++ req->cookie_ts = tmp_opt.tstamp_ok;
++ } else if (!isn) {
++ if (ipv6_opt_accepted(sk, skb) ||
++ np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
++ np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
++ atomic_inc(&skb->users);
++ treq->pktopts = skb;
++ }
++ treq->iif = sk->sk_bound_dev_if;
+
+- /* So that link locals have meaning */
+- if (!sk->sk_bound_dev_if &&
+- ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL)
+- treq->iif = inet6_iif(skb);
++ /* So that link locals have meaning */
++ if (!sk->sk_bound_dev_if &&
++ ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL)
++ treq->iif = inet6_iif(skb);
+
+- if (isn == 0)
+ isn = tcp_v6_init_sequence(skb);
++ }
+
+ tcp_rsk(req)->snt_isn = isn;
+
+ security_inet_conn_request(sk, skb, req);
+
+- if (tcp_v6_send_synack(sk, req, NULL))
++ if (tcp_v6_send_synack(sk, req))
+ goto drop;
+
+- inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
+- return 0;
++ if (!want_cookie) {
++ inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
++ return 0;
++ }
+
+ drop:
+ if (req)
+@@ -1499,7 +1534,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
+ #endif
+
+ __inet6_hash(newsk);
+- inet_inherit_port(sk, newsk);
++ __inet_inherit_port(sk, newsk);
+
+ return newsk;
+
+@@ -1704,7 +1739,7 @@ static int tcp_v6_rcv(struct sk_buff *skb)
+ TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb));
+ TCP_SKB_CB(skb)->sacked = 0;
+
+- sk = __inet6_lookup(skb->dev->nd_net, &tcp_hashinfo,
++ sk = __inet6_lookup(dev_net(skb->dev), &tcp_hashinfo,
+ &ipv6_hdr(skb)->saddr, th->source,
+ &ipv6_hdr(skb)->daddr, ntohs(th->dest),
+ inet6_iif(skb));
+@@ -1787,7 +1822,7 @@ do_time_wait:
+ {
+ struct sock *sk2;
+
+- sk2 = inet6_lookup_listener(skb->dev->nd_net, &tcp_hashinfo,
++ sk2 = inet6_lookup_listener(dev_net(skb->dev), &tcp_hashinfo,
+ &ipv6_hdr(skb)->daddr,
+ ntohs(th->dest), inet6_iif(skb));
+ if (sk2 != NULL) {
+@@ -2085,28 +2120,28 @@ out:
+ return 0;
+ }
+
+-static struct file_operations tcp6_seq_fops;
+ static struct tcp_seq_afinfo tcp6_seq_afinfo = {
+- .owner = THIS_MODULE,
+ .name = "tcp6",
+ .family = AF_INET6,
+- .seq_show = tcp6_seq_show,
+- .seq_fops = &tcp6_seq_fops,
++ .seq_fops = {
++ .owner = THIS_MODULE,
++ },
++ .seq_ops = {
++ .show = tcp6_seq_show,
++ },
+ };
+
+-int __init tcp6_proc_init(void)
++int tcp6_proc_init(struct net *net)
+ {
+- return tcp_proc_register(&tcp6_seq_afinfo);
++ return tcp_proc_register(net, &tcp6_seq_afinfo);
+ }
+
+-void tcp6_proc_exit(void)
++void tcp6_proc_exit(struct net *net)
+ {
+- tcp_proc_unregister(&tcp6_seq_afinfo);
++ tcp_proc_unregister(net, &tcp6_seq_afinfo);
+ }
+ #endif
+
+-DEFINE_PROTO_INUSE(tcpv6)
+-
+ struct proto tcpv6_prot = {
+ .name = "TCPv6",
+ .owner = THIS_MODULE,
+@@ -2137,12 +2172,11 @@ struct proto tcpv6_prot = {
+ .obj_size = sizeof(struct tcp6_sock),
+ .twsk_prot = &tcp6_timewait_sock_ops,
+ .rsk_prot = &tcp6_request_sock_ops,
+- .hashinfo = &tcp_hashinfo,
++ .h.hashinfo = &tcp_hashinfo,
+ #ifdef CONFIG_COMPAT
+ .compat_setsockopt = compat_tcp_setsockopt,
+ .compat_getsockopt = compat_tcp_getsockopt,
+ #endif
+- REF_PROTO_INUSE(tcpv6)
+ };
+
+ static struct inet6_protocol tcpv6_protocol = {
+@@ -2164,6 +2198,22 @@ static struct inet_protosw tcpv6_protosw = {
+ INET_PROTOSW_ICSK,
+ };
+
++static int tcpv6_net_init(struct net *net)
++{
++ return inet_ctl_sock_create(&net->ipv6.tcp_sk, PF_INET6,
++ SOCK_RAW, IPPROTO_TCP, net);
++}
++
++static void tcpv6_net_exit(struct net *net)
++{
++ inet_ctl_sock_destroy(net->ipv6.tcp_sk);
++}
++
++static struct pernet_operations tcpv6_net_ops = {
++ .init = tcpv6_net_init,
++ .exit = tcpv6_net_exit,
++};
++
+ int __init tcpv6_init(void)
+ {
+ int ret;
+@@ -2177,8 +2227,7 @@ int __init tcpv6_init(void)
+ if (ret)
+ goto out_tcpv6_protocol;
+
+- ret = inet_csk_ctl_sock_create(&tcp6_socket, PF_INET6,
+- SOCK_RAW, IPPROTO_TCP);
++ ret = register_pernet_subsys(&tcpv6_net_ops);
+ if (ret)
+ goto out_tcpv6_protosw;
+ out:
+@@ -2193,7 +2242,7 @@ out_tcpv6_protosw:
+
+ void tcpv6_exit(void)
+ {
+- sock_release(tcp6_socket);
++ unregister_pernet_subsys(&tcpv6_net_ops);
+ inet6_unregister_protosw(&tcpv6_protosw);
+ inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
+ }
+diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
+index 53739de..1fd784f 100644
+--- a/net/ipv6/udp.c
++++ b/net/ipv6/udp.c
+@@ -51,9 +51,9 @@
+ #include <linux/seq_file.h>
+ #include "udp_impl.h"
+
+-static inline int udp_v6_get_port(struct sock *sk, unsigned short snum)
++int udp_v6_get_port(struct sock *sk, unsigned short snum)
+ {
+- return udp_get_port(sk, snum, ipv6_rcv_saddr_equal);
++ return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal);
+ }
+
+ static struct sock *__udp6_lib_lookup(struct net *net,
+@@ -70,7 +70,7 @@ static struct sock *__udp6_lib_lookup(struct net *net,
+ sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) {
+ struct inet_sock *inet = inet_sk(sk);
+
+- if (sk->sk_net == net && sk->sk_hash == hnum &&
++ if (net_eq(sock_net(sk), net) && sk->sk_hash == hnum &&
+ sk->sk_family == PF_INET6) {
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ int score = 0;
+@@ -235,7 +235,7 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ struct sock *sk;
+ int err;
+
+- sk = __udp6_lib_lookup(skb->dev->nd_net, daddr, uh->dest,
++ sk = __udp6_lib_lookup(dev_net(skb->dev), daddr, uh->dest,
+ saddr, uh->source, inet6_iif(skb), udptable);
+ if (sk == NULL)
+ return;
+@@ -323,6 +323,9 @@ static struct sock *udp_v6_mcast_next(struct sock *sk,
+ sk_for_each_from(s, node) {
+ struct inet_sock *inet = inet_sk(s);
+
++ if (sock_net(s) != sock_net(sk))
++ continue;
++
+ if (s->sk_hash == num && s->sk_family == PF_INET6) {
+ struct ipv6_pinfo *np = inet6_sk(s);
+ if (inet->dport) {
+@@ -480,7 +483,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
+ * check socket cache ... must talk to Alan about his plans
+ * for sock caches... i'll skip this for now.
+ */
+- sk = __udp6_lib_lookup(skb->dev->nd_net, saddr, uh->source,
++ sk = __udp6_lib_lookup(dev_net(skb->dev), saddr, uh->source,
+ daddr, uh->dest, inet6_iif(skb), udptable);
+
+ if (sk == NULL) {
+@@ -749,7 +752,10 @@ do_udp_sendmsg:
+ opt = ipv6_fixup_options(&opt_space, opt);
+
+ fl.proto = sk->sk_protocol;
+- ipv6_addr_copy(&fl.fl6_dst, daddr);
++ if (!ipv6_addr_any(daddr))
++ ipv6_addr_copy(&fl.fl6_dst, daddr);
++ else
++ fl.fl6_dst.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */
+ if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
+ ipv6_addr_copy(&fl.fl6_src, &np->saddr);
+ fl.fl_ip_sport = inet->sport;
+@@ -789,9 +795,7 @@ do_udp_sendmsg:
+ else
+ hlimit = np->hop_limit;
+ if (hlimit < 0)
+- hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+- if (hlimit < 0)
+- hlimit = ipv6_get_hoplimit(dst->dev);
++ hlimit = ip6_dst_hoplimit(dst);
+ }
+
+ if (tclass < 0) {
+@@ -976,30 +980,30 @@ int udp6_seq_show(struct seq_file *seq, void *v)
+ return 0;
+ }
+
+-static struct file_operations udp6_seq_fops;
+ static struct udp_seq_afinfo udp6_seq_afinfo = {
+- .owner = THIS_MODULE,
+ .name = "udp6",
+ .family = AF_INET6,
+ .hashtable = udp_hash,
+- .seq_show = udp6_seq_show,
+- .seq_fops = &udp6_seq_fops,
++ .seq_fops = {
++ .owner = THIS_MODULE,
++ },
++ .seq_ops = {
++ .show = udp6_seq_show,
++ },
+ };
+
+-int __init udp6_proc_init(void)
++int udp6_proc_init(struct net *net)
+ {
+- return udp_proc_register(&udp6_seq_afinfo);
++ return udp_proc_register(net, &udp6_seq_afinfo);
+ }
+
+-void udp6_proc_exit(void) {
+- udp_proc_unregister(&udp6_seq_afinfo);
++void udp6_proc_exit(struct net *net) {
++ udp_proc_unregister(net, &udp6_seq_afinfo);
+ }
+ #endif /* CONFIG_PROC_FS */
+
+ /* ------------------------------------------------------------------------ */
+
+-DEFINE_PROTO_INUSE(udpv6)
+-
+ struct proto udpv6_prot = {
+ .name = "UDPv6",
+ .owner = THIS_MODULE,
+@@ -1021,11 +1025,11 @@ struct proto udpv6_prot = {
+ .sysctl_wmem = &sysctl_udp_wmem_min,
+ .sysctl_rmem = &sysctl_udp_rmem_min,
+ .obj_size = sizeof(struct udp6_sock),
++ .h.udp_hash = udp_hash,
+ #ifdef CONFIG_COMPAT
+ .compat_setsockopt = compat_udpv6_setsockopt,
+ .compat_getsockopt = compat_udpv6_getsockopt,
+ #endif
+- REF_PROTO_INUSE(udpv6)
+ };
+
+ static struct inet_protosw udpv6_protosw = {
+diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h
+index 21be3a8..321b81a 100644
+--- a/net/ipv6/udp_impl.h
++++ b/net/ipv6/udp_impl.h
+@@ -11,6 +11,8 @@ extern int __udp6_lib_rcv(struct sk_buff *, struct hlist_head [], int );
+ extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *,
+ int , int , int , __be32 , struct hlist_head []);
+
++extern int udp_v6_get_port(struct sock *sk, unsigned short snum);
++
+ extern int udpv6_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen);
+ extern int udpv6_setsockopt(struct sock *sk, int level, int optname,
+diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c
+index 87d4202..491efd0 100644
+--- a/net/ipv6/udplite.c
++++ b/net/ipv6/udplite.c
+@@ -35,13 +35,6 @@ static struct inet6_protocol udplitev6_protocol = {
+ .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
+ };
+
+-static int udplite_v6_get_port(struct sock *sk, unsigned short snum)
+-{
+- return udplite_get_port(sk, snum, ipv6_rcv_saddr_equal);
+-}
+-
+-DEFINE_PROTO_INUSE(udplitev6)
+-
+ struct proto udplitev6_prot = {
+ .name = "UDPLITEv6",
+ .owner = THIS_MODULE,
+@@ -58,13 +51,13 @@ struct proto udplitev6_prot = {
+ .backlog_rcv = udpv6_queue_rcv_skb,
+ .hash = udp_lib_hash,
+ .unhash = udp_lib_unhash,
+- .get_port = udplite_v6_get_port,
++ .get_port = udp_v6_get_port,
+ .obj_size = sizeof(struct udp6_sock),
++ .h.udp_hash = udplite_hash,
+ #ifdef CONFIG_COMPAT
+ .compat_setsockopt = compat_udpv6_setsockopt,
+ .compat_getsockopt = compat_udpv6_getsockopt,
+ #endif
+- REF_PROTO_INUSE(udplitev6)
+ };
+
+ static struct inet_protosw udplite6_protosw = {
+@@ -103,23 +96,40 @@ void udplitev6_exit(void)
+ }
+
+ #ifdef CONFIG_PROC_FS
+-static struct file_operations udplite6_seq_fops;
+ static struct udp_seq_afinfo udplite6_seq_afinfo = {
+- .owner = THIS_MODULE,
+ .name = "udplite6",
+ .family = AF_INET6,
+ .hashtable = udplite_hash,
+- .seq_show = udp6_seq_show,
+- .seq_fops = &udplite6_seq_fops,
++ .seq_fops = {
++ .owner = THIS_MODULE,
++ },
++ .seq_ops = {
++ .show = udp6_seq_show,
++ },
++};
++
++static int udplite6_proc_init_net(struct net *net)
++{
++ return udp_proc_register(net, &udplite6_seq_afinfo);
++}
++
++static void udplite6_proc_exit_net(struct net *net)
++{
++ udp_proc_unregister(net, &udplite6_seq_afinfo);
++}
++
++static struct pernet_operations udplite6_net_ops = {
++ .init = udplite6_proc_init_net,
++ .exit = udplite6_proc_exit_net,
+ };
+
+ int __init udplite6_proc_init(void)
+ {
+- return udp_proc_register(&udplite6_seq_afinfo);
++ return register_pernet_subsys(&udplite6_net_ops);
+ }
+
+ void udplite6_proc_exit(void)
+ {
+- udp_proc_unregister(&udplite6_seq_afinfo);
++ unregister_pernet_subsys(&udplite6_net_ops);
+ }
+ #endif
+diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
+index a4714d7..a71c7dd 100644
+--- a/net/ipv6/xfrm6_input.c
++++ b/net/ipv6/xfrm6_input.c
+@@ -59,9 +59,6 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
+ xfrm_address_t *saddr, u8 proto)
+ {
+ struct xfrm_state *x = NULL;
+- int wildcard = 0;
+- xfrm_address_t *xany;
+- int nh = 0;
+ int i = 0;
+
+ /* Allocate new secpath or COW existing one. */
+@@ -83,10 +80,9 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
+ goto drop;
+ }
+
+- xany = (xfrm_address_t *)&in6addr_any;
+-
+ for (i = 0; i < 3; i++) {
+ xfrm_address_t *dst, *src;
++
+ switch (i) {
+ case 0:
+ dst = daddr;
+@@ -94,16 +90,13 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
+ break;
+ case 1:
+ /* lookup state with wild-card source address */
+- wildcard = 1;
+ dst = daddr;
+- src = xany;
++ src = (xfrm_address_t *)&in6addr_any;
+ break;
+- case 2:
+ default:
+ /* lookup state with wild-card addresses */
+- wildcard = 1; /* XXX */
+- dst = xany;
+- src = xany;
++ dst = (xfrm_address_t *)&in6addr_any;
++ src = (xfrm_address_t *)&in6addr_any;
+ break;
+ }
+
+@@ -113,39 +106,19 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
+
+ spin_lock(&x->lock);
+
+- if (wildcard) {
+- if ((x->props.flags & XFRM_STATE_WILDRECV) == 0) {
+- spin_unlock(&x->lock);
+- xfrm_state_put(x);
+- x = NULL;
+- continue;
+- }
+- }
+-
+- if (unlikely(x->km.state != XFRM_STATE_VALID)) {
++ if ((!i || (x->props.flags & XFRM_STATE_WILDRECV)) &&
++ likely(x->km.state == XFRM_STATE_VALID) &&
++ !xfrm_state_check_expire(x)) {
+ spin_unlock(&x->lock);
+- xfrm_state_put(x);
+- x = NULL;
+- continue;
+- }
+- if (xfrm_state_check_expire(x)) {
++ if (x->type->input(x, skb) > 0) {
++ /* found a valid state */
++ break;
++ }
++ } else
+ spin_unlock(&x->lock);
+- xfrm_state_put(x);
+- x = NULL;
+- continue;
+- }
+-
+- spin_unlock(&x->lock);
+-
+- nh = x->type->input(x, skb);
+- if (nh <= 0) {
+- xfrm_state_put(x);
+- x = NULL;
+- continue;
+- }
+
+- /* Found a state */
+- break;
++ xfrm_state_put(x);
++ x = NULL;
+ }
+
+ if (!x) {
+diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
+index 7d20199..8f1e054 100644
+--- a/net/ipv6/xfrm6_policy.c
++++ b/net/ipv6/xfrm6_policy.c
+@@ -38,7 +38,7 @@ static struct dst_entry *xfrm6_dst_lookup(int tos, xfrm_address_t *saddr,
+ if (saddr)
+ memcpy(&fl.fl6_src, saddr, sizeof(fl.fl6_src));
+
+- dst = ip6_route_output(NULL, &fl);
++ dst = ip6_route_output(&init_net, NULL, &fl);
+
+ err = dst->error;
+ if (dst->error) {
+@@ -57,8 +57,9 @@ static int xfrm6_get_saddr(xfrm_address_t *saddr, xfrm_address_t *daddr)
+ if (IS_ERR(dst))
+ return -EHOSTUNREACH;
+
+- ipv6_get_saddr(dst, (struct in6_addr *)&daddr->a6,
+- (struct in6_addr *)&saddr->a6);
++ ipv6_dev_get_saddr(ip6_dst_idev(dst)->dev,
++ (struct in6_addr *)&daddr->a6, 0,
++ (struct in6_addr *)&saddr->a6);
+ dst_release(dst);
+ return 0;
+ }
+@@ -246,7 +247,7 @@ static void xfrm6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
+ xdst = (struct xfrm_dst *)dst;
+ if (xdst->u.rt6.rt6i_idev->dev == dev) {
+ struct inet6_dev *loopback_idev =
+- in6_dev_get(dev->nd_net->loopback_dev);
++ in6_dev_get(dev_net(dev)->loopback_dev);
+ BUG_ON(!loopback_idev);
+
+ do {
+diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
+index ff1e1db..89884a4 100644
+--- a/net/ipv6/xfrm6_state.c
++++ b/net/ipv6/xfrm6_state.c
+@@ -49,125 +49,102 @@ __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl,
+ x->props.family = AF_INET6;
+ }
+
++/* distribution counting sort function for xfrm_state and xfrm_tmpl */
+ static int
+-__xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n)
++__xfrm6_sort(void **dst, void **src, int n, int (*cmp)(void *p), int maxclass)
+ {
+ int i;
+- int j = 0;
++ int class[XFRM_MAX_DEPTH];
++ int count[maxclass];
+
+- /* Rule 1: select IPsec transport except AH */
+- for (i = 0; i < n; i++) {
+- if (src[i]->props.mode == XFRM_MODE_TRANSPORT &&
+- src[i]->id.proto != IPPROTO_AH) {
+- dst[j++] = src[i];
+- src[i] = NULL;
+- }
+- }
+- if (j == n)
+- goto end;
++ memset(count, 0, sizeof(count));
+
+- /* Rule 2: select MIPv6 RO or inbound trigger */
+-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+ for (i = 0; i < n; i++) {
+- if (src[i] &&
+- (src[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION ||
+- src[i]->props.mode == XFRM_MODE_IN_TRIGGER)) {
+- dst[j++] = src[i];
+- src[i] = NULL;
+- }
++ int c;
++ class[i] = c = cmp(src[i]);
++ count[c]++;
+ }
+- if (j == n)
+- goto end;
+-#endif
+
+- /* Rule 3: select IPsec transport AH */
+- for (i = 0; i < n; i++) {
+- if (src[i] &&
+- src[i]->props.mode == XFRM_MODE_TRANSPORT &&
+- src[i]->id.proto == IPPROTO_AH) {
+- dst[j++] = src[i];
+- src[i] = NULL;
+- }
+- }
+- if (j == n)
+- goto end;
++ for (i = 2; i < maxclass; i++)
++ count[i] += count[i - 1];
+
+- /* Rule 4: select IPsec tunnel */
+ for (i = 0; i < n; i++) {
+- if (src[i] &&
+- (src[i]->props.mode == XFRM_MODE_TUNNEL ||
+- src[i]->props.mode == XFRM_MODE_BEET)) {
+- dst[j++] = src[i];
+- src[i] = NULL;
+- }
++ dst[count[class[i] - 1]++] = src[i];
++ src[i] = 0;
+ }
+- if (likely(j == n))
+- goto end;
+
+- /* Final rule */
+- for (i = 0; i < n; i++) {
+- if (src[i]) {
+- dst[j++] = src[i];
+- src[i] = NULL;
+- }
+- }
+-
+- end:
+ return 0;
+ }
+
+-static int
+-__xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n)
++/*
++ * Rule for xfrm_state:
++ *
++ * rule 1: select IPsec transport except AH
++ * rule 2: select MIPv6 RO or inbound trigger
++ * rule 3: select IPsec transport AH
++ * rule 4: select IPsec tunnel
++ * rule 5: others
++ */
++static int __xfrm6_state_sort_cmp(void *p)
+ {
+- int i;
+- int j = 0;
+-
+- /* Rule 1: select IPsec transport */
+- for (i = 0; i < n; i++) {
+- if (src[i]->mode == XFRM_MODE_TRANSPORT) {
+- dst[j++] = src[i];
+- src[i] = NULL;
+- }
+- }
+- if (j == n)
+- goto end;
+-
+- /* Rule 2: select MIPv6 RO or inbound trigger */
++ struct xfrm_state *v = p;
++
++ switch (v->props.mode) {
++ case XFRM_MODE_TRANSPORT:
++ if (v->id.proto != IPPROTO_AH)
++ return 1;
++ else
++ return 3;
+ #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+- for (i = 0; i < n; i++) {
+- if (src[i] &&
+- (src[i]->mode == XFRM_MODE_ROUTEOPTIMIZATION ||
+- src[i]->mode == XFRM_MODE_IN_TRIGGER)) {
+- dst[j++] = src[i];
+- src[i] = NULL;
+- }
+- }
+- if (j == n)
+- goto end;
++ case XFRM_MODE_ROUTEOPTIMIZATION:
++ case XFRM_MODE_IN_TRIGGER:
++ return 2;
+ #endif
+-
+- /* Rule 3: select IPsec tunnel */
+- for (i = 0; i < n; i++) {
+- if (src[i] &&
+- (src[i]->mode == XFRM_MODE_TUNNEL ||
+- src[i]->mode == XFRM_MODE_BEET)) {
+- dst[j++] = src[i];
+- src[i] = NULL;
+- }
++ case XFRM_MODE_TUNNEL:
++ case XFRM_MODE_BEET:
++ return 4;
+ }
+- if (likely(j == n))
+- goto end;
++ return 5;
++}
+
+- /* Final rule */
+- for (i = 0; i < n; i++) {
+- if (src[i]) {
+- dst[j++] = src[i];
+- src[i] = NULL;
+- }
++static int
++__xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n)
++{
++ return __xfrm6_sort((void **)dst, (void **)src, n,
++ __xfrm6_state_sort_cmp, 6);
++}
++
++/*
++ * Rule for xfrm_tmpl:
++ *
++ * rule 1: select IPsec transport
++ * rule 2: select MIPv6 RO or inbound trigger
++ * rule 3: select IPsec tunnel
++ * rule 4: others
++ */
++static int __xfrm6_tmpl_sort_cmp(void *p)
++{
++ struct xfrm_tmpl *v = p;
++ switch (v->mode) {
++ case XFRM_MODE_TRANSPORT:
++ return 1;
++#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
++ case XFRM_MODE_ROUTEOPTIMIZATION:
++ case XFRM_MODE_IN_TRIGGER:
++ return 2;
++#endif
++ case XFRM_MODE_TUNNEL:
++ case XFRM_MODE_BEET:
++ return 3;
+ }
++ return 4;
++}
+
+- end:
+- return 0;
++static int
++__xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n)
++{
++ return __xfrm6_sort((void **)dst, (void **)src, n,
++ __xfrm6_tmpl_sort_cmp, 5);
+ }
+
+ int xfrm6_extract_header(struct sk_buff *skb)
+diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
+index 639fe8a..c2b2781 100644
+--- a/net/ipv6/xfrm6_tunnel.c
++++ b/net/ipv6/xfrm6_tunnel.c
+@@ -140,12 +140,26 @@ __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr)
+
+ EXPORT_SYMBOL(xfrm6_tunnel_spi_lookup);
+
++static int __xfrm6_tunnel_spi_check(u32 spi)
++{
++ struct xfrm6_tunnel_spi *x6spi;
++ int index = xfrm6_tunnel_spi_hash_byspi(spi);
++ struct hlist_node *pos;
++
++ hlist_for_each_entry(x6spi, pos,
++ &xfrm6_tunnel_spi_byspi[index],
++ list_byspi) {
++ if (x6spi->spi == spi)
++ return -1;
++ }
++ return index;
++}
++
+ static u32 __xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr)
+ {
+ u32 spi;
+ struct xfrm6_tunnel_spi *x6spi;
+- struct hlist_node *pos;
+- unsigned index;
++ int index;
+
+ if (xfrm6_tunnel_spi < XFRM6_TUNNEL_SPI_MIN ||
+ xfrm6_tunnel_spi >= XFRM6_TUNNEL_SPI_MAX)
+@@ -154,32 +168,19 @@ static u32 __xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr)
+ xfrm6_tunnel_spi++;
+
+ for (spi = xfrm6_tunnel_spi; spi <= XFRM6_TUNNEL_SPI_MAX; spi++) {
+- index = xfrm6_tunnel_spi_hash_byspi(spi);
+- hlist_for_each_entry(x6spi, pos,
+- &xfrm6_tunnel_spi_byspi[index],
+- list_byspi) {
+- if (x6spi->spi == spi)
+- goto try_next_1;
+- }
+- xfrm6_tunnel_spi = spi;
+- goto alloc_spi;
+-try_next_1:;
++ index = __xfrm6_tunnel_spi_check(spi);
++ if (index >= 0)
++ goto alloc_spi;
+ }
+ for (spi = XFRM6_TUNNEL_SPI_MIN; spi < xfrm6_tunnel_spi; spi++) {
+- index = xfrm6_tunnel_spi_hash_byspi(spi);
+- hlist_for_each_entry(x6spi, pos,
+- &xfrm6_tunnel_spi_byspi[index],
+- list_byspi) {
+- if (x6spi->spi == spi)
+- goto try_next_2;
+- }
+- xfrm6_tunnel_spi = spi;
+- goto alloc_spi;
+-try_next_2:;
++ index = __xfrm6_tunnel_spi_check(spi);
++ if (index >= 0)
++ goto alloc_spi;
+ }
+ spi = 0;
+ goto out;
+ alloc_spi:
++ xfrm6_tunnel_spi = spi;
+ x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, GFP_ATOMIC);
+ if (!x6spi)
+ goto out;
+diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
+index c76a952..81ae873 100644
+--- a/net/ipx/af_ipx.c
++++ b/net/ipx/af_ipx.c
+@@ -335,7 +335,7 @@ static int ipxitf_device_event(struct notifier_block *notifier,
+ struct net_device *dev = ptr;
+ struct ipx_interface *i, *tmp;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ if (event != NETDEV_DOWN && event != NETDEV_UP)
+@@ -1636,7 +1636,7 @@ static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty
+ u16 ipx_pktsize;
+ int rc = 0;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ goto drop;
+
+ /* Not ours */
+diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
+index 240b0cb..ae54b20 100644
+--- a/net/irda/af_irda.c
++++ b/net/irda/af_irda.c
+@@ -85,14 +85,14 @@ static int irda_data_indication(void *instance, void *sap, struct sk_buff *skb)
+ struct sock *sk;
+ int err;
+
+- IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(3, "%s()\n", __func__);
+
+ self = instance;
+ sk = instance;
+
+ err = sock_queue_rcv_skb(sk, skb);
+ if (err) {
+- IRDA_DEBUG(1, "%s(), error: no more mem!\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), error: no more mem!\n", __func__);
+ self->rx_flow = FLOW_STOP;
+
+ /* When we return error, TTP will need to requeue the skb */
+@@ -116,7 +116,7 @@ static void irda_disconnect_indication(void *instance, void *sap,
+
+ self = instance;
+
+- IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
++ IRDA_DEBUG(2, "%s(%p)\n", __func__, self);
+
+ /* Don't care about it, but let's not leak it */
+ if(skb)
+@@ -125,7 +125,7 @@ static void irda_disconnect_indication(void *instance, void *sap,
+ sk = instance;
+ if (sk == NULL) {
+ IRDA_DEBUG(0, "%s(%p) : BUG : sk is NULL\n",
+- __FUNCTION__, self);
++ __func__, self);
+ return;
+ }
+
+@@ -181,7 +181,7 @@ static void irda_connect_confirm(void *instance, void *sap,
+
+ self = instance;
+
+- IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
++ IRDA_DEBUG(2, "%s(%p)\n", __func__, self);
+
+ sk = instance;
+ if (sk == NULL) {
+@@ -203,7 +203,7 @@ static void irda_connect_confirm(void *instance, void *sap,
+ case SOCK_STREAM:
+ if (max_sdu_size != 0) {
+ IRDA_ERROR("%s: max_sdu_size must be 0\n",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+ self->max_data_size = irttp_get_max_seg_size(self->tsap);
+@@ -211,7 +211,7 @@ static void irda_connect_confirm(void *instance, void *sap,
+ case SOCK_SEQPACKET:
+ if (max_sdu_size == 0) {
+ IRDA_ERROR("%s: max_sdu_size cannot be 0\n",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+ self->max_data_size = max_sdu_size;
+@@ -220,7 +220,7 @@ static void irda_connect_confirm(void *instance, void *sap,
+ self->max_data_size = irttp_get_max_seg_size(self->tsap);
+ }
+
+- IRDA_DEBUG(2, "%s(), max_data_size=%d\n", __FUNCTION__,
++ IRDA_DEBUG(2, "%s(), max_data_size=%d\n", __func__,
+ self->max_data_size);
+
+ memcpy(&self->qos_tx, qos, sizeof(struct qos_info));
+@@ -245,7 +245,7 @@ static void irda_connect_indication(void *instance, void *sap,
+
+ self = instance;
+
+- IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
++ IRDA_DEBUG(2, "%s(%p)\n", __func__, self);
+
+ sk = instance;
+ if (sk == NULL) {
+@@ -264,7 +264,7 @@ static void irda_connect_indication(void *instance, void *sap,
+ case SOCK_STREAM:
+ if (max_sdu_size != 0) {
+ IRDA_ERROR("%s: max_sdu_size must be 0\n",
+- __FUNCTION__);
++ __func__);
+ kfree_skb(skb);
+ return;
+ }
+@@ -273,7 +273,7 @@ static void irda_connect_indication(void *instance, void *sap,
+ case SOCK_SEQPACKET:
+ if (max_sdu_size == 0) {
+ IRDA_ERROR("%s: max_sdu_size cannot be 0\n",
+- __FUNCTION__);
++ __func__);
+ kfree_skb(skb);
+ return;
+ }
+@@ -283,7 +283,7 @@ static void irda_connect_indication(void *instance, void *sap,
+ self->max_data_size = irttp_get_max_seg_size(self->tsap);
+ }
+
+- IRDA_DEBUG(2, "%s(), max_data_size=%d\n", __FUNCTION__,
++ IRDA_DEBUG(2, "%s(), max_data_size=%d\n", __func__,
+ self->max_data_size);
+
+ memcpy(&self->qos_tx, qos, sizeof(struct qos_info));
+@@ -302,13 +302,13 @@ static void irda_connect_response(struct irda_sock *self)
+ {
+ struct sk_buff *skb;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s()\n", __func__);
+
+ skb = alloc_skb(TTP_MAX_HEADER + TTP_SAR_HEADER,
+ GFP_ATOMIC);
+ if (skb == NULL) {
+ IRDA_DEBUG(0, "%s() Unable to allocate sk_buff!\n",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+
+@@ -329,7 +329,7 @@ static void irda_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
+ struct irda_sock *self;
+ struct sock *sk;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s()\n", __func__);
+
+ self = instance;
+ sk = instance;
+@@ -338,17 +338,17 @@ static void irda_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
+ switch (flow) {
+ case FLOW_STOP:
+ IRDA_DEBUG(1, "%s(), IrTTP wants us to slow down\n",
+- __FUNCTION__);
++ __func__);
+ self->tx_flow = flow;
+ break;
+ case FLOW_START:
+ self->tx_flow = flow;
+ IRDA_DEBUG(1, "%s(), IrTTP wants us to start again\n",
+- __FUNCTION__);
++ __func__);
+ wake_up_interruptible(sk->sk_sleep);
+ break;
+ default:
+- IRDA_DEBUG(0, "%s(), Unknown flow command!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), Unknown flow command!\n", __func__);
+ /* Unknown flow command, better stop */
+ self->tx_flow = flow;
+ break;
+@@ -370,11 +370,11 @@ static void irda_getvalue_confirm(int result, __u16 obj_id,
+
+ self = (struct irda_sock *) priv;
+ if (!self) {
+- IRDA_WARNING("%s: lost myself!\n", __FUNCTION__);
++ IRDA_WARNING("%s: lost myself!\n", __func__);
+ return;
+ }
+
+- IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
++ IRDA_DEBUG(2, "%s(%p)\n", __func__, self);
+
+ /* We probably don't need to make any more queries */
+ iriap_close(self->iriap);
+@@ -382,7 +382,7 @@ static void irda_getvalue_confirm(int result, __u16 obj_id,
+
+ /* Check if request succeeded */
+ if (result != IAS_SUCCESS) {
+- IRDA_DEBUG(1, "%s(), IAS query failed! (%d)\n", __FUNCTION__,
++ IRDA_DEBUG(1, "%s(), IAS query failed! (%d)\n", __func__,
+ result);
+
+ self->errno = result; /* We really need it later */
+@@ -415,11 +415,11 @@ static void irda_selective_discovery_indication(discinfo_t *discovery,
+ {
+ struct irda_sock *self;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s()\n", __func__);
+
+ self = (struct irda_sock *) priv;
+ if (!self) {
+- IRDA_WARNING("%s: lost myself!\n", __FUNCTION__);
++ IRDA_WARNING("%s: lost myself!\n", __func__);
+ return;
+ }
+
+@@ -442,7 +442,7 @@ static void irda_discovery_timeout(u_long priv)
+ {
+ struct irda_sock *self;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s()\n", __func__);
+
+ self = (struct irda_sock *) priv;
+ BUG_ON(self == NULL);
+@@ -467,7 +467,7 @@ static int irda_open_tsap(struct irda_sock *self, __u8 tsap_sel, char *name)
+ notify_t notify;
+
+ if (self->tsap) {
+- IRDA_WARNING("%s: busy!\n", __FUNCTION__);
++ IRDA_WARNING("%s: busy!\n", __func__);
+ return -EBUSY;
+ }
+
+@@ -486,7 +486,7 @@ static int irda_open_tsap(struct irda_sock *self, __u8 tsap_sel, char *name)
+ ¬ify);
+ if (self->tsap == NULL) {
+ IRDA_DEBUG(0, "%s(), Unable to allocate TSAP!\n",
+- __FUNCTION__);
++ __func__);
+ return -ENOMEM;
+ }
+ /* Remember which TSAP selector we actually got */
+@@ -507,7 +507,7 @@ static int irda_open_lsap(struct irda_sock *self, int pid)
+ notify_t notify;
+
+ if (self->lsap) {
+- IRDA_WARNING("%s(), busy!\n", __FUNCTION__);
++ IRDA_WARNING("%s(), busy!\n", __func__);
+ return -EBUSY;
+ }
+
+@@ -519,7 +519,7 @@ static int irda_open_lsap(struct irda_sock *self, int pid)
+
+ self->lsap = irlmp_open_lsap(LSAP_CONNLESS, ¬ify, pid);
+ if (self->lsap == NULL) {
+- IRDA_DEBUG( 0, "%s(), Unable to allocate LSAP!\n", __FUNCTION__);
++ IRDA_DEBUG( 0, "%s(), Unable to allocate LSAP!\n", __func__);
+ return -ENOMEM;
+ }
+
+@@ -540,11 +540,11 @@ static int irda_open_lsap(struct irda_sock *self, int pid)
+ */
+ static int irda_find_lsap_sel(struct irda_sock *self, char *name)
+ {
+- IRDA_DEBUG(2, "%s(%p, %s)\n", __FUNCTION__, self, name);
++ IRDA_DEBUG(2, "%s(%p, %s)\n", __func__, self, name);
+
+ if (self->iriap) {
+ IRDA_WARNING("%s(): busy with a previous query\n",
+- __FUNCTION__);
++ __func__);
+ return -EBUSY;
+ }
+
+@@ -580,7 +580,7 @@ static int irda_find_lsap_sel(struct irda_sock *self, char *name)
+ switch (self->ias_result->type) {
+ case IAS_INTEGER:
+ IRDA_DEBUG(4, "%s() int=%d\n",
+- __FUNCTION__, self->ias_result->t.integer);
++ __func__, self->ias_result->t.integer);
+
+ if (self->ias_result->t.integer != -1)
+ self->dtsap_sel = self->ias_result->t.integer;
+@@ -589,7 +589,7 @@ static int irda_find_lsap_sel(struct irda_sock *self, char *name)
+ break;
+ default:
+ self->dtsap_sel = 0;
+- IRDA_DEBUG(0, "%s(), bad type!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), bad type!\n", __func__);
+ break;
+ }
+ if (self->ias_result)
+@@ -627,7 +627,7 @@ static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name)
+ __u32 daddr = DEV_ADDR_ANY; /* Address we found the service on */
+ __u8 dtsap_sel = 0x0; /* TSAP associated with it */
+
+- IRDA_DEBUG(2, "%s(), name=%s\n", __FUNCTION__, name);
++ IRDA_DEBUG(2, "%s(), name=%s\n", __func__, name);
+
+ /* Ask lmp for the current discovery log
+ * Note : we have to use irlmp_get_discoveries(), as opposed
+@@ -649,7 +649,7 @@ static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name)
+ self->daddr = discoveries[i].daddr;
+ self->saddr = 0x0;
+ IRDA_DEBUG(1, "%s(), trying daddr = %08x\n",
+- __FUNCTION__, self->daddr);
++ __func__, self->daddr);
+
+ /* Query remote LM-IAS for this service */
+ err = irda_find_lsap_sel(self, name);
+@@ -658,7 +658,7 @@ static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name)
+ /* We found the requested service */
+ if(daddr != DEV_ADDR_ANY) {
+ IRDA_DEBUG(1, "%s(), discovered service ''%s'' in two different devices !!!\n",
+- __FUNCTION__, name);
++ __func__, name);
+ self->daddr = DEV_ADDR_ANY;
+ kfree(discoveries);
+ return(-ENOTUNIQ);
+@@ -672,7 +672,7 @@ static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name)
+ break;
+ default:
+ /* Something bad did happen :-( */
+- IRDA_DEBUG(0, "%s(), unexpected IAS query failure\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), unexpected IAS query failure\n", __func__);
+ self->daddr = DEV_ADDR_ANY;
+ kfree(discoveries);
+ return(-EHOSTUNREACH);
+@@ -685,7 +685,7 @@ static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name)
+ /* Check out what we found */
+ if(daddr == DEV_ADDR_ANY) {
+ IRDA_DEBUG(1, "%s(), cannot discover service ''%s'' in any device !!!\n",
+- __FUNCTION__, name);
++ __func__, name);
+ self->daddr = DEV_ADDR_ANY;
+ return(-EADDRNOTAVAIL);
+ }
+@@ -696,7 +696,7 @@ static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name)
+ self->dtsap_sel = dtsap_sel;
+
+ IRDA_DEBUG(1, "%s(), discovered requested service ''%s'' at address %08x\n",
+- __FUNCTION__, name, self->daddr);
++ __func__, name, self->daddr);
+
+ return 0;
+ }
+@@ -727,8 +727,8 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr,
+ saddr.sir_addr = self->saddr;
+ }
+
+- IRDA_DEBUG(1, "%s(), tsap_sel = %#x\n", __FUNCTION__, saddr.sir_lsap_sel);
+- IRDA_DEBUG(1, "%s(), addr = %08x\n", __FUNCTION__, saddr.sir_addr);
++ IRDA_DEBUG(1, "%s(), tsap_sel = %#x\n", __func__, saddr.sir_lsap_sel);
++ IRDA_DEBUG(1, "%s(), addr = %08x\n", __func__, saddr.sir_addr);
+
+ /* uaddr_len come to us uninitialised */
+ *uaddr_len = sizeof (struct sockaddr_irda);
+@@ -747,7 +747,7 @@ static int irda_listen(struct socket *sock, int backlog)
+ {
+ struct sock *sk = sock->sk;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s()\n", __func__);
+
+ if ((sk->sk_type != SOCK_STREAM) && (sk->sk_type != SOCK_SEQPACKET) &&
+ (sk->sk_type != SOCK_DGRAM))
+@@ -776,7 +776,7 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ struct irda_sock *self = irda_sk(sk);
+ int err;
+
+- IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
++ IRDA_DEBUG(2, "%s(%p)\n", __func__, self);
+
+ if (addr_len != sizeof(struct sockaddr_irda))
+ return -EINVAL;
+@@ -787,7 +787,7 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ (sk->sk_protocol == IRDAPROTO_ULTRA)) {
+ self->pid = addr->sir_lsap_sel;
+ if (self->pid & 0x80) {
+- IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __func__);
+ return -EOPNOTSUPP;
+ }
+ err = irda_open_lsap(self, self->pid);
+@@ -835,9 +835,9 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
+ struct sk_buff *skb;
+ int err;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s()\n", __func__);
+
+- err = irda_create(sk->sk_net, newsock, sk->sk_protocol);
++ err = irda_create(sock_net(sk), newsock, sk->sk_protocol);
+ if (err)
+ return err;
+
+@@ -893,7 +893,7 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
+ /* Now attach up the new socket */
+ new->tsap = irttp_dup(self->tsap, new);
+ if (!new->tsap) {
+- IRDA_DEBUG(0, "%s(), dup failed!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), dup failed!\n", __func__);
+ kfree_skb(skb);
+ return -1;
+ }
+@@ -954,7 +954,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
+ struct irda_sock *self = irda_sk(sk);
+ int err;
+
+- IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
++ IRDA_DEBUG(2, "%s(%p)\n", __func__, self);
+
+ /* Don't allow connect for Ultra sockets */
+ if ((sk->sk_type == SOCK_DGRAM) && (sk->sk_protocol == IRDAPROTO_ULTRA))
+@@ -984,13 +984,13 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
+ /* Try to find one suitable */
+ err = irda_discover_daddr_and_lsap_sel(self, addr->sir_name);
+ if (err) {
+- IRDA_DEBUG(0, "%s(), auto-connect failed!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), auto-connect failed!\n", __func__);
+ return err;
+ }
+ } else {
+ /* Use the one provided by the user */
+ self->daddr = addr->sir_addr;
+- IRDA_DEBUG(1, "%s(), daddr = %08x\n", __FUNCTION__, self->daddr);
++ IRDA_DEBUG(1, "%s(), daddr = %08x\n", __func__, self->daddr);
+
+ /* If we don't have a valid service name, we assume the
+ * user want to connect on a specific LSAP. Prevent
+@@ -1000,7 +1000,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
+ /* Query remote LM-IAS using service name */
+ err = irda_find_lsap_sel(self, addr->sir_name);
+ if (err) {
+- IRDA_DEBUG(0, "%s(), connect failed!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), connect failed!\n", __func__);
+ return err;
+ }
+ } else {
+@@ -1025,7 +1025,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
+ self->saddr, self->daddr, NULL,
+ self->max_sdu_size_rx, NULL);
+ if (err) {
+- IRDA_DEBUG(0, "%s(), connect failed!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), connect failed!\n", __func__);
+ return err;
+ }
+
+@@ -1068,7 +1068,7 @@ static int irda_create(struct net *net, struct socket *sock, int protocol)
+ struct sock *sk;
+ struct irda_sock *self;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s()\n", __func__);
+
+ if (net != &init_net)
+ return -EAFNOSUPPORT;
+@@ -1089,7 +1089,7 @@ static int irda_create(struct net *net, struct socket *sock, int protocol)
+ return -ENOMEM;
+
+ self = irda_sk(sk);
+- IRDA_DEBUG(2, "%s() : self is %p\n", __FUNCTION__, self);
++ IRDA_DEBUG(2, "%s() : self is %p\n", __func__, self);
+
+ init_waitqueue_head(&self->query_wait);
+
+@@ -1149,7 +1149,7 @@ static int irda_create(struct net *net, struct socket *sock, int protocol)
+ */
+ static void irda_destroy_socket(struct irda_sock *self)
+ {
+- IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
++ IRDA_DEBUG(2, "%s(%p)\n", __func__, self);
+
+ /* Unregister with IrLMP */
+ irlmp_unregister_client(self->ckey);
+@@ -1186,7 +1186,7 @@ static int irda_release(struct socket *sock)
+ {
+ struct sock *sk = sock->sk;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s()\n", __func__);
+
+ if (sk == NULL)
+ return 0;
+@@ -1254,7 +1254,7 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock,
+ struct sk_buff *skb;
+ int err = -EPIPE;
+
+- IRDA_DEBUG(4, "%s(), len=%zd\n", __FUNCTION__, len);
++ IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len);
+
+ /* Note : socket.c set MSG_EOR on SEQPACKET sockets */
+ if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_EOR | MSG_CMSG_COMPAT |
+@@ -1282,7 +1282,7 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock,
+ /* Check that we don't send out too big frames */
+ if (len > self->max_data_size) {
+ IRDA_DEBUG(2, "%s(), Chopping frame from %zd to %d bytes!\n",
+- __FUNCTION__, len, self->max_data_size);
++ __func__, len, self->max_data_size);
+ len = self->max_data_size;
+ }
+
+@@ -1306,7 +1306,7 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock,
+ */
+ err = irttp_data_request(self->tsap, skb);
+ if (err) {
+- IRDA_DEBUG(0, "%s(), err=%d\n", __FUNCTION__, err);
++ IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err);
+ goto out_err;
+ }
+ /* Tell client how much data we actually sent */
+@@ -1332,7 +1332,7 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,
+ size_t copied;
+ int err;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ if ((err = sock_error(sk)) < 0)
+ return err;
+@@ -1347,7 +1347,7 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,
+
+ if (copied > size) {
+ IRDA_DEBUG(2, "%s(), Received truncated frame (%zd < %zd)!\n",
+- __FUNCTION__, copied, size);
++ __func__, copied, size);
+ copied = size;
+ msg->msg_flags |= MSG_TRUNC;
+ }
+@@ -1363,7 +1363,7 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,
+ */
+ if (self->rx_flow == FLOW_STOP) {
+ if ((atomic_read(&sk->sk_rmem_alloc) << 2) <= sk->sk_rcvbuf) {
+- IRDA_DEBUG(2, "%s(), Starting IrTTP\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s(), Starting IrTTP\n", __func__);
+ self->rx_flow = FLOW_START;
+ irttp_flow_request(self->tsap, FLOW_START);
+ }
+@@ -1385,7 +1385,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
+ int target, err;
+ long timeo;
+
+- IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(3, "%s()\n", __func__);
+
+ if ((err = sock_error(sk)) < 0)
+ return err;
+@@ -1459,14 +1459,14 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
+ /* put the skb back if we didn't use it up.. */
+ if (skb->len) {
+ IRDA_DEBUG(1, "%s(), back on q!\n",
+- __FUNCTION__);
++ __func__);
+ skb_queue_head(&sk->sk_receive_queue, skb);
+ break;
+ }
+
+ kfree_skb(skb);
+ } else {
+- IRDA_DEBUG(0, "%s() questionable!?\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s() questionable!?\n", __func__);
+
+ /* put message back and return */
+ skb_queue_head(&sk->sk_receive_queue, skb);
+@@ -1482,7 +1482,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
+ */
+ if (self->rx_flow == FLOW_STOP) {
+ if ((atomic_read(&sk->sk_rmem_alloc) << 2) <= sk->sk_rcvbuf) {
+- IRDA_DEBUG(2, "%s(), Starting IrTTP\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s(), Starting IrTTP\n", __func__);
+ self->rx_flow = FLOW_START;
+ irttp_flow_request(self->tsap, FLOW_START);
+ }
+@@ -1506,7 +1506,7 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
+ struct sk_buff *skb;
+ int err;
+
+- IRDA_DEBUG(4, "%s(), len=%zd\n", __FUNCTION__, len);
++ IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len);
+
+ if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT))
+ return -EINVAL;
+@@ -1528,7 +1528,7 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
+ if (len > self->max_data_size) {
+ IRDA_DEBUG(0, "%s(), Warning to much data! "
+ "Chopping frame from %zd to %d bytes!\n",
+- __FUNCTION__, len, self->max_data_size);
++ __func__, len, self->max_data_size);
+ len = self->max_data_size;
+ }
+
+@@ -1540,7 +1540,7 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
+ skb_reserve(skb, self->max_header_size);
+ skb_reset_transport_header(skb);
+
+- IRDA_DEBUG(4, "%s(), appending user data\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s(), appending user data\n", __func__);
+ skb_put(skb, len);
+ err = memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len);
+ if (err) {
+@@ -1554,7 +1554,7 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
+ */
+ err = irttp_udata_request(self->tsap, skb);
+ if (err) {
+- IRDA_DEBUG(0, "%s(), err=%d\n", __FUNCTION__, err);
++ IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err);
+ return err;
+ }
+ return len;
+@@ -1577,7 +1577,7 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
+ struct sk_buff *skb;
+ int err;
+
+- IRDA_DEBUG(4, "%s(), len=%zd\n", __FUNCTION__, len);
++ IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len);
+
+ if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT))
+ return -EINVAL;
+@@ -1600,7 +1600,7 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
+
+ pid = addr->sir_lsap_sel;
+ if (pid & 0x80) {
+- IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __func__);
+ return -EOPNOTSUPP;
+ }
+ } else {
+@@ -1609,7 +1609,7 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
+ if ((self->lsap == NULL) ||
+ (sk->sk_state != TCP_ESTABLISHED)) {
+ IRDA_DEBUG(0, "%s(), socket not bound to Ultra PID.\n",
+- __FUNCTION__);
++ __func__);
+ return -ENOTCONN;
+ }
+ /* Use PID from socket */
+@@ -1623,7 +1623,7 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
+ if (len > self->max_data_size) {
+ IRDA_DEBUG(0, "%s(), Warning to much data! "
+ "Chopping frame from %zd to %d bytes!\n",
+- __FUNCTION__, len, self->max_data_size);
++ __func__, len, self->max_data_size);
+ len = self->max_data_size;
+ }
+
+@@ -1635,7 +1635,7 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
+ skb_reserve(skb, self->max_header_size);
+ skb_reset_transport_header(skb);
+
+- IRDA_DEBUG(4, "%s(), appending user data\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s(), appending user data\n", __func__);
+ skb_put(skb, len);
+ err = memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len);
+ if (err) {
+@@ -1646,7 +1646,7 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
+ err = irlmp_connless_data_request((bound ? self->lsap : NULL),
+ skb, pid);
+ if (err) {
+- IRDA_DEBUG(0, "%s(), err=%d\n", __FUNCTION__, err);
++ IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err);
+ return err;
+ }
+ return len;
+@@ -1661,7 +1661,7 @@ static int irda_shutdown(struct socket *sock, int how)
+ struct sock *sk = sock->sk;
+ struct irda_sock *self = irda_sk(sk);
+
+- IRDA_DEBUG(1, "%s(%p)\n", __FUNCTION__, self);
++ IRDA_DEBUG(1, "%s(%p)\n", __func__, self);
+
+ sk->sk_state = TCP_CLOSE;
+ sk->sk_shutdown |= SEND_SHUTDOWN;
+@@ -1696,7 +1696,7 @@ static unsigned int irda_poll(struct file * file, struct socket *sock,
+ struct irda_sock *self = irda_sk(sk);
+ unsigned int mask;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ poll_wait(file, sk->sk_sleep, wait);
+ mask = 0;
+@@ -1705,7 +1705,7 @@ static unsigned int irda_poll(struct file * file, struct socket *sock,
+ if (sk->sk_err)
+ mask |= POLLERR;
+ if (sk->sk_shutdown & RCV_SHUTDOWN) {
+- IRDA_DEBUG(0, "%s(), POLLHUP\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), POLLHUP\n", __func__);
+ mask |= POLLHUP;
+ }
+
+@@ -1719,7 +1719,7 @@ static unsigned int irda_poll(struct file * file, struct socket *sock,
+ switch (sk->sk_type) {
+ case SOCK_STREAM:
+ if (sk->sk_state == TCP_CLOSE) {
+- IRDA_DEBUG(0, "%s(), POLLHUP\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), POLLHUP\n", __func__);
+ mask |= POLLHUP;
+ }
+
+@@ -1755,7 +1755,7 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+ {
+ struct sock *sk = sock->sk;
+
+- IRDA_DEBUG(4, "%s(), cmd=%#x\n", __FUNCTION__, cmd);
++ IRDA_DEBUG(4, "%s(), cmd=%#x\n", __func__, cmd);
+
+ switch (cmd) {
+ case TIOCOUTQ: {
+@@ -1796,7 +1796,7 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+ case SIOCSIFMETRIC:
+ return -EINVAL;
+ default:
+- IRDA_DEBUG(1, "%s(), doing device ioctl!\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), doing device ioctl!\n", __func__);
+ return -ENOIOCTLCMD;
+ }
+
+@@ -1833,7 +1833,7 @@ static int irda_setsockopt(struct socket *sock, int level, int optname,
+ struct ias_attrib * ias_attr; /* Attribute in IAS object */
+ int opt, free_ias = 0;
+
+- IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
++ IRDA_DEBUG(2, "%s(%p)\n", __func__, self);
+
+ if (level != SOL_IRLMP)
+ return -ENOPROTOOPT;
+@@ -2012,7 +2012,7 @@ static int irda_setsockopt(struct socket *sock, int level, int optname,
+
+ /* Check is the user space own the object */
+ if(ias_attr->value->owner != IAS_USER_ATTR) {
+- IRDA_DEBUG(1, "%s(), attempting to delete a kernel attribute\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), attempting to delete a kernel attribute\n", __func__);
+ kfree(ias_opt);
+ return -EPERM;
+ }
+@@ -2031,11 +2031,11 @@ static int irda_setsockopt(struct socket *sock, int level, int optname,
+ /* Only possible for a seqpacket service (TTP with SAR) */
+ if (sk->sk_type != SOCK_SEQPACKET) {
+ IRDA_DEBUG(2, "%s(), setting max_sdu_size = %d\n",
+- __FUNCTION__, opt);
++ __func__, opt);
+ self->max_sdu_size_rx = opt;
+ } else {
+ IRDA_WARNING("%s: not allowed to set MAXSDUSIZE for this socket type!\n",
+- __FUNCTION__);
++ __func__);
+ return -ENOPROTOOPT;
+ }
+ break;
+@@ -2149,7 +2149,7 @@ static int irda_getsockopt(struct socket *sock, int level, int optname,
+ int err;
+ int offset, total;
+
+- IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
++ IRDA_DEBUG(2, "%s(%p)\n", __func__, self);
+
+ if (level != SOL_IRLMP)
+ return -ENOPROTOOPT;
+@@ -2310,7 +2310,7 @@ bed:
+ /* Check that we can proceed with IAP */
+ if (self->iriap) {
+ IRDA_WARNING("%s: busy with a previous query\n",
+- __FUNCTION__);
++ __func__);
+ kfree(ias_opt);
+ return -EBUSY;
+ }
+@@ -2406,7 +2406,7 @@ bed:
+ if (!self->cachedaddr) {
+ int ret = 0;
+
+- IRDA_DEBUG(1, "%s(), nothing discovered yet, going to sleep...\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), nothing discovered yet, going to sleep...\n", __func__);
+
+ /* Set watchdog timer to expire in <val> ms. */
+ self->errno = 0;
+@@ -2424,14 +2424,14 @@ bed:
+ if(timer_pending(&(self->watchdog)))
+ del_timer(&(self->watchdog));
+
+- IRDA_DEBUG(1, "%s(), ...waking up !\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), ...waking up !\n", __func__);
+
+ if (ret != 0)
+ return ret;
+ }
+ else
+ IRDA_DEBUG(1, "%s(), found immediately !\n",
+- __FUNCTION__);
++ __func__);
+
+ /* Tell IrLMP that we have been notified */
+ irlmp_update_client(self->ckey, self->mask.word,
+diff --git a/net/irda/discovery.c b/net/irda/discovery.c
+index 80c33f4..bfacef8 100644
+--- a/net/irda/discovery.c
++++ b/net/irda/discovery.c
+@@ -110,7 +110,7 @@ void irlmp_add_discovery_log(hashbin_t *cachelog, hashbin_t *log)
+ {
+ discovery_t *discovery;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ /*
+ * If log is missing this means that IrLAP was unable to perform the
+@@ -157,7 +157,7 @@ void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force)
+ int i = 0; /* How many we expired */
+
+ IRDA_ASSERT(log != NULL, return;);
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ spin_lock_irqsave(&log->hb_spinlock, flags);
+
+diff --git a/net/irda/ircomm/ircomm_core.c b/net/irda/ircomm/ircomm_core.c
+index 6eef1f2..018c929 100644
+--- a/net/irda/ircomm/ircomm_core.c
++++ b/net/irda/ircomm/ircomm_core.c
+@@ -70,7 +70,7 @@ static int __init ircomm_init(void)
+ {
+ ircomm = hashbin_new(HB_LOCK);
+ if (ircomm == NULL) {
+- IRDA_ERROR("%s(), can't allocate hashbin!\n", __FUNCTION__);
++ IRDA_ERROR("%s(), can't allocate hashbin!\n", __func__);
+ return -ENOMEM;
+ }
+
+@@ -91,7 +91,7 @@ static int __init ircomm_init(void)
+
+ static void __exit ircomm_cleanup(void)
+ {
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ hashbin_delete(ircomm, (FREE_FUNC) __ircomm_close);
+
+@@ -111,7 +111,7 @@ struct ircomm_cb *ircomm_open(notify_t *notify, __u8 service_type, int line)
+ struct ircomm_cb *self = NULL;
+ int ret;
+
+- IRDA_DEBUG(2, "%s(), service_type=0x%02x\n", __FUNCTION__ ,
++ IRDA_DEBUG(2, "%s(), service_type=0x%02x\n", __func__ ,
+ service_type);
+
+ IRDA_ASSERT(ircomm != NULL, return NULL;);
+@@ -155,7 +155,7 @@ EXPORT_SYMBOL(ircomm_open);
+ */
+ static int __ircomm_close(struct ircomm_cb *self)
+ {
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ /* Disconnect link if any */
+ ircomm_do_event(self, IRCOMM_DISCONNECT_REQUEST, NULL, NULL);
+@@ -191,7 +191,7 @@ int ircomm_close(struct ircomm_cb *self)
+ IRDA_ASSERT(self != NULL, return -EIO;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -EIO;);
+
+- IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s()\n", __func__ );
+
+ entry = hashbin_remove(ircomm, self->line, NULL);
+
+@@ -216,7 +216,7 @@ int ircomm_connect_request(struct ircomm_cb *self, __u8 dlsap_sel,
+ struct ircomm_info info;
+ int ret;
+
+- IRDA_DEBUG(2 , "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2 , "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+@@ -245,7 +245,7 @@ void ircomm_connect_indication(struct ircomm_cb *self, struct sk_buff *skb,
+ {
+ int clen = 0;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ /* Check if the packet contains data on the control channel */
+ if (skb->len > 0)
+@@ -261,7 +261,7 @@ void ircomm_connect_indication(struct ircomm_cb *self, struct sk_buff *skb,
+ info->qos, info->max_data_size,
+ info->max_header_size, skb);
+ else {
+- IRDA_DEBUG(0, "%s(), missing handler\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s(), missing handler\n", __func__ );
+ }
+ }
+
+@@ -278,7 +278,7 @@ int ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata)
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ ret = ircomm_do_event(self, IRCOMM_CONNECT_RESPONSE, userdata, NULL);
+
+@@ -296,7 +296,7 @@ EXPORT_SYMBOL(ircomm_connect_response);
+ void ircomm_connect_confirm(struct ircomm_cb *self, struct sk_buff *skb,
+ struct ircomm_info *info)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ if (self->notify.connect_confirm )
+ self->notify.connect_confirm(self->notify.instance,
+@@ -304,7 +304,7 @@ void ircomm_connect_confirm(struct ircomm_cb *self, struct sk_buff *skb,
+ info->max_data_size,
+ info->max_header_size, skb);
+ else {
+- IRDA_DEBUG(0, "%s(), missing handler\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s(), missing handler\n", __func__ );
+ }
+ }
+
+@@ -318,7 +318,7 @@ int ircomm_data_request(struct ircomm_cb *self, struct sk_buff *skb)
+ {
+ int ret;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -EFAULT;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -EFAULT;);
+@@ -339,14 +339,14 @@ EXPORT_SYMBOL(ircomm_data_request);
+ */
+ void ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(skb->len > 0, return;);
+
+ if (self->notify.data_indication)
+ self->notify.data_indication(self->notify.instance, self, skb);
+ else {
+- IRDA_DEBUG(0, "%s(), missing handler\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s(), missing handler\n", __func__ );
+ }
+ }
+
+@@ -372,7 +372,7 @@ void ircomm_process_data(struct ircomm_cb *self, struct sk_buff *skb)
+ */
+ if (unlikely(skb->len < (clen + 1))) {
+ IRDA_DEBUG(2, "%s() throwing away illegal frame\n",
+- __FUNCTION__ );
++ __func__ );
+ return;
+ }
+
+@@ -391,7 +391,7 @@ void ircomm_process_data(struct ircomm_cb *self, struct sk_buff *skb)
+ ircomm_data_indication(self, skb);
+ else {
+ IRDA_DEBUG(4, "%s(), data was control info only!\n",
+- __FUNCTION__ );
++ __func__ );
+ }
+ }
+
+@@ -405,7 +405,7 @@ int ircomm_control_request(struct ircomm_cb *self, struct sk_buff *skb)
+ {
+ int ret;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -EFAULT;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -EFAULT;);
+@@ -427,7 +427,7 @@ EXPORT_SYMBOL(ircomm_control_request);
+ static void ircomm_control_indication(struct ircomm_cb *self,
+ struct sk_buff *skb, int clen)
+ {
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ /* Use udata for delivering data on the control channel */
+ if (self->notify.udata_indication) {
+@@ -448,7 +448,7 @@ static void ircomm_control_indication(struct ircomm_cb *self,
+ * see ircomm_tty_control_indication(). */
+ dev_kfree_skb(ctrl_skb);
+ } else {
+- IRDA_DEBUG(0, "%s(), missing handler\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s(), missing handler\n", __func__ );
+ }
+ }
+
+@@ -463,7 +463,7 @@ int ircomm_disconnect_request(struct ircomm_cb *self, struct sk_buff *userdata)
+ struct ircomm_info info;
+ int ret;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+@@ -484,7 +484,7 @@ EXPORT_SYMBOL(ircomm_disconnect_request);
+ void ircomm_disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb,
+ struct ircomm_info *info)
+ {
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ IRDA_ASSERT(info != NULL, return;);
+
+@@ -492,7 +492,7 @@ void ircomm_disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb,
+ self->notify.disconnect_indication(self->notify.instance, self,
+ info->reason, skb);
+ } else {
+- IRDA_DEBUG(0, "%s(), missing handler\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s(), missing handler\n", __func__ );
+ }
+ }
+
+@@ -504,7 +504,7 @@ void ircomm_disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb,
+ */
+ void ircomm_flow_request(struct ircomm_cb *self, LOCAL_FLOW flow)
+ {
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
+diff --git a/net/irda/ircomm/ircomm_event.c b/net/irda/ircomm/ircomm_event.c
+index 8ba4e59..c35b3ef 100644
+--- a/net/irda/ircomm/ircomm_event.c
++++ b/net/irda/ircomm/ircomm_event.c
+@@ -108,7 +108,7 @@ static int ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event,
+ ircomm_connect_indication(self, skb, info);
+ break;
+ default:
+- IRDA_DEBUG(4, "%s(), unknown event: %s\n", __FUNCTION__ ,
++ IRDA_DEBUG(4, "%s(), unknown event: %s\n", __func__ ,
+ ircomm_event[event]);
+ ret = -EINVAL;
+ }
+@@ -138,7 +138,7 @@ static int ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event,
+ ircomm_disconnect_indication(self, skb, info);
+ break;
+ default:
+- IRDA_DEBUG(0, "%s(), unknown event: %s\n", __FUNCTION__ ,
++ IRDA_DEBUG(0, "%s(), unknown event: %s\n", __func__ ,
+ ircomm_event[event]);
+ ret = -EINVAL;
+ }
+@@ -171,7 +171,7 @@ static int ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event,
+ ircomm_disconnect_indication(self, skb, info);
+ break;
+ default:
+- IRDA_DEBUG(0, "%s(), unknown event = %s\n", __FUNCTION__ ,
++ IRDA_DEBUG(0, "%s(), unknown event = %s\n", __func__ ,
+ ircomm_event[event]);
+ ret = -EINVAL;
+ }
+@@ -213,7 +213,7 @@ static int ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event,
+ ret = self->issue.disconnect_request(self, skb, info);
+ break;
+ default:
+- IRDA_DEBUG(0, "%s(), unknown event = %s\n", __FUNCTION__ ,
++ IRDA_DEBUG(0, "%s(), unknown event = %s\n", __func__ ,
+ ircomm_event[event]);
+ ret = -EINVAL;
+ }
+@@ -229,7 +229,7 @@ static int ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event,
+ int ircomm_do_event(struct ircomm_cb *self, IRCOMM_EVENT event,
+ struct sk_buff *skb, struct ircomm_info *info)
+ {
+- IRDA_DEBUG(4, "%s: state=%s, event=%s\n", __FUNCTION__ ,
++ IRDA_DEBUG(4, "%s: state=%s, event=%s\n", __func__ ,
+ ircomm_state[self->state], ircomm_event[event]);
+
+ return (*state[self->state])(self, event, skb, info);
+@@ -245,6 +245,6 @@ void ircomm_next_state(struct ircomm_cb *self, IRCOMM_STATE state)
+ {
+ self->state = state;
+
+- IRDA_DEBUG(4, "%s: next state=%s, service type=%d\n", __FUNCTION__ ,
++ IRDA_DEBUG(4, "%s: next state=%s, service type=%d\n", __func__ ,
+ ircomm_state[self->state], self->service_type);
+ }
+diff --git a/net/irda/ircomm/ircomm_lmp.c b/net/irda/ircomm/ircomm_lmp.c
+index 55860ee..67c99d2 100644
+--- a/net/irda/ircomm/ircomm_lmp.c
++++ b/net/irda/ircomm/ircomm_lmp.c
+@@ -53,7 +53,7 @@ static int ircomm_lmp_connect_request(struct ircomm_cb *self,
+ {
+ int ret = 0;
+
+- IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s()\n", __func__ );
+
+ /* Don't forget to refcount it - should be NULL anyway */
+ if(userdata)
+@@ -76,7 +76,7 @@ static int ircomm_lmp_connect_response(struct ircomm_cb *self,
+ struct sk_buff *tx_skb;
+ int ret;
+
+- IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s()\n", __func__ );
+
+ /* Any userdata supplied? */
+ if (userdata == NULL) {
+@@ -111,7 +111,7 @@ static int ircomm_lmp_disconnect_request(struct ircomm_cb *self,
+ struct sk_buff *tx_skb;
+ int ret;
+
+- IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s()\n", __func__ );
+
+ if (!userdata) {
+ tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC);
+@@ -148,13 +148,13 @@ static void ircomm_lmp_flow_control(struct sk_buff *skb)
+
+ cb = (struct irda_skb_cb *) skb->cb;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ line = cb->line;
+
+ self = (struct ircomm_cb *) hashbin_lock_find(ircomm, line, NULL);
+ if (!self) {
+- IRDA_DEBUG(2, "%s(), didn't find myself\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), didn't find myself\n", __func__ );
+ return;
+ }
+
+@@ -164,7 +164,7 @@ static void ircomm_lmp_flow_control(struct sk_buff *skb)
+ self->pkt_count--;
+
+ if ((self->pkt_count < 2) && (self->flow_status == FLOW_STOP)) {
+- IRDA_DEBUG(2, "%s(), asking TTY to start again!\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), asking TTY to start again!\n", __func__ );
+ self->flow_status = FLOW_START;
+ if (self->notify.flow_indication)
+ self->notify.flow_indication(self->notify.instance,
+@@ -191,7 +191,7 @@ static int ircomm_lmp_data_request(struct ircomm_cb *self,
+
+ cb->line = self->line;
+
+- IRDA_DEBUG(4, "%s(), sending frame\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s(), sending frame\n", __func__ );
+
+ /* Don't forget to refcount it - see ircomm_tty_do_softint() */
+ skb_get(skb);
+@@ -199,7 +199,7 @@ static int ircomm_lmp_data_request(struct ircomm_cb *self,
+ skb->destructor = ircomm_lmp_flow_control;
+
+ if ((self->pkt_count++ > 7) && (self->flow_status == FLOW_START)) {
+- IRDA_DEBUG(2, "%s(), asking TTY to slow down!\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), asking TTY to slow down!\n", __func__ );
+ self->flow_status = FLOW_STOP;
+ if (self->notify.flow_indication)
+ self->notify.flow_indication(self->notify.instance,
+@@ -207,7 +207,7 @@ static int ircomm_lmp_data_request(struct ircomm_cb *self,
+ }
+ ret = irlmp_data_request(self->lsap, skb);
+ if (ret) {
+- IRDA_ERROR("%s(), failed\n", __FUNCTION__);
++ IRDA_ERROR("%s(), failed\n", __func__);
+ /* irlmp_data_request already free the packet */
+ }
+
+@@ -225,7 +225,7 @@ static int ircomm_lmp_data_indication(void *instance, void *sap,
+ {
+ struct ircomm_cb *self = (struct ircomm_cb *) instance;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+@@ -255,7 +255,7 @@ static void ircomm_lmp_connect_confirm(void *instance, void *sap,
+ struct ircomm_cb *self = (struct ircomm_cb *) instance;
+ struct ircomm_info info;
+
+- IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
+@@ -288,7 +288,7 @@ static void ircomm_lmp_connect_indication(void *instance, void *sap,
+ struct ircomm_cb *self = (struct ircomm_cb *)instance;
+ struct ircomm_info info;
+
+- IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
+@@ -318,7 +318,7 @@ static void ircomm_lmp_disconnect_indication(void *instance, void *sap,
+ struct ircomm_cb *self = (struct ircomm_cb *) instance;
+ struct ircomm_info info;
+
+- IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
+@@ -341,7 +341,7 @@ int ircomm_open_lsap(struct ircomm_cb *self)
+ {
+ notify_t notify;
+
+- IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s()\n", __func__ );
+
+ /* Register callbacks */
+ irda_notify_init(¬ify);
+@@ -354,7 +354,7 @@ int ircomm_open_lsap(struct ircomm_cb *self)
+
+ self->lsap = irlmp_open_lsap(LSAP_ANY, ¬ify, 0);
+ if (!self->lsap) {
+- IRDA_DEBUG(0,"%sfailed to allocate tsap\n", __FUNCTION__ );
++ IRDA_DEBUG(0,"%sfailed to allocate tsap\n", __func__ );
+ return -1;
+ }
+ self->slsap_sel = self->lsap->slsap_sel;
+diff --git a/net/irda/ircomm/ircomm_param.c b/net/irda/ircomm/ircomm_param.c
+index 598dcbe..d57aefd 100644
+--- a/net/irda/ircomm/ircomm_param.c
++++ b/net/irda/ircomm/ircomm_param.c
+@@ -103,7 +103,7 @@ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)
+ struct sk_buff *skb;
+ int count;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+@@ -136,7 +136,7 @@ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)
+ count = irda_param_insert(self, pi, skb_tail_pointer(skb),
+ skb_tailroom(skb), &ircomm_param_info);
+ if (count < 0) {
+- IRDA_WARNING("%s(), no room for parameter!\n", __FUNCTION__);
++ IRDA_WARNING("%s(), no room for parameter!\n", __func__);
+ spin_unlock_irqrestore(&self->spinlock, flags);
+ return -1;
+ }
+@@ -144,7 +144,7 @@ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)
+
+ spin_unlock_irqrestore(&self->spinlock, flags);
+
+- IRDA_DEBUG(2, "%s(), skb->len=%d\n", __FUNCTION__ , skb->len);
++ IRDA_DEBUG(2, "%s(), skb->len=%d\n", __func__ , skb->len);
+
+ if (flush) {
+ /* ircomm_tty_do_softint will take care of the rest */
+@@ -179,10 +179,10 @@ static int ircomm_param_service_type(void *instance, irda_param_t *param,
+ service_type &= self->service_type;
+ if (!service_type) {
+ IRDA_DEBUG(2,
+- "%s(), No common service type to use!\n", __FUNCTION__ );
++ "%s(), No common service type to use!\n", __func__ );
+ return -1;
+ }
+- IRDA_DEBUG(0, "%s(), services in common=%02x\n", __FUNCTION__ ,
++ IRDA_DEBUG(0, "%s(), services in common=%02x\n", __func__ ,
+ service_type);
+
+ /*
+@@ -197,7 +197,7 @@ static int ircomm_param_service_type(void *instance, irda_param_t *param,
+ else if (service_type & IRCOMM_3_WIRE_RAW)
+ self->settings.service_type = IRCOMM_3_WIRE_RAW;
+
+- IRDA_DEBUG(0, "%s(), resulting service type=0x%02x\n", __FUNCTION__ ,
++ IRDA_DEBUG(0, "%s(), resulting service type=0x%02x\n", __func__ ,
+ self->settings.service_type);
+
+ /*
+@@ -240,7 +240,7 @@ static int ircomm_param_port_type(void *instance, irda_param_t *param, int get)
+ else {
+ self->settings.port_type = (__u8) param->pv.i;
+
+- IRDA_DEBUG(0, "%s(), port type=%d\n", __FUNCTION__ ,
++ IRDA_DEBUG(0, "%s(), port type=%d\n", __func__ ,
+ self->settings.port_type);
+ }
+ return 0;
+@@ -260,9 +260,9 @@ static int ircomm_param_port_name(void *instance, irda_param_t *param, int get)
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+ if (get) {
+- IRDA_DEBUG(0, "%s(), not imp!\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s(), not imp!\n", __func__ );
+ } else {
+- IRDA_DEBUG(0, "%s(), port-name=%s\n", __FUNCTION__ , param->pv.c);
++ IRDA_DEBUG(0, "%s(), port-name=%s\n", __func__ , param->pv.c);
+ strncpy(self->settings.port_name, param->pv.c, 32);
+ }
+
+@@ -287,7 +287,7 @@ static int ircomm_param_data_rate(void *instance, irda_param_t *param, int get)
+ else
+ self->settings.data_rate = param->pv.i;
+
+- IRDA_DEBUG(2, "%s(), data rate = %d\n", __FUNCTION__ , param->pv.i);
++ IRDA_DEBUG(2, "%s(), data rate = %d\n", __func__ , param->pv.i);
+
+ return 0;
+ }
+@@ -333,7 +333,7 @@ static int ircomm_param_flow_control(void *instance, irda_param_t *param,
+ else
+ self->settings.flow_control = (__u8) param->pv.i;
+
+- IRDA_DEBUG(1, "%s(), flow control = 0x%02x\n", __FUNCTION__ , (__u8) param->pv.i);
++ IRDA_DEBUG(1, "%s(), flow control = 0x%02x\n", __func__ , (__u8) param->pv.i);
+
+ return 0;
+ }
+@@ -359,7 +359,7 @@ static int ircomm_param_xon_xoff(void *instance, irda_param_t *param, int get)
+ self->settings.xonxoff[1] = (__u16) param->pv.i >> 8;
+ }
+
+- IRDA_DEBUG(0, "%s(), XON/XOFF = 0x%02x,0x%02x\n", __FUNCTION__ ,
++ IRDA_DEBUG(0, "%s(), XON/XOFF = 0x%02x,0x%02x\n", __func__ ,
+ param->pv.i & 0xff, param->pv.i >> 8);
+
+ return 0;
+@@ -386,7 +386,7 @@ static int ircomm_param_enq_ack(void *instance, irda_param_t *param, int get)
+ self->settings.enqack[1] = (__u16) param->pv.i >> 8;
+ }
+
+- IRDA_DEBUG(0, "%s(), ENQ/ACK = 0x%02x,0x%02x\n", __FUNCTION__ ,
++ IRDA_DEBUG(0, "%s(), ENQ/ACK = 0x%02x,0x%02x\n", __func__ ,
+ param->pv.i & 0xff, param->pv.i >> 8);
+
+ return 0;
+@@ -401,7 +401,7 @@ static int ircomm_param_enq_ack(void *instance, irda_param_t *param, int get)
+ static int ircomm_param_line_status(void *instance, irda_param_t *param,
+ int get)
+ {
+- IRDA_DEBUG(2, "%s(), not impl.\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), not impl.\n", __func__ );
+
+ return 0;
+ }
+@@ -462,7 +462,7 @@ static int ircomm_param_dce(void *instance, irda_param_t *param, int get)
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+ __u8 dce;
+
+- IRDA_DEBUG(1, "%s(), dce = 0x%02x\n", __FUNCTION__ , (__u8) param->pv.i);
++ IRDA_DEBUG(1, "%s(), dce = 0x%02x\n", __func__ , (__u8) param->pv.i);
+
+ dce = (__u8) param->pv.i;
+
+@@ -474,7 +474,7 @@ static int ircomm_param_dce(void *instance, irda_param_t *param, int get)
+ /* Check if any of the settings have changed */
+ if (dce & 0x0f) {
+ if (dce & IRCOMM_DELTA_CTS) {
+- IRDA_DEBUG(2, "%s(), CTS \n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), CTS \n", __func__ );
+ }
+ }
+
+diff --git a/net/irda/ircomm/ircomm_ttp.c b/net/irda/ircomm/ircomm_ttp.c
+index 712eafd..6e6509f 100644
+--- a/net/irda/ircomm/ircomm_ttp.c
++++ b/net/irda/ircomm/ircomm_ttp.c
+@@ -78,7 +78,7 @@ int ircomm_open_tsap(struct ircomm_cb *self)
+ {
+ notify_t notify;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ /* Register callbacks */
+ irda_notify_init(¬ify);
+@@ -93,7 +93,7 @@ int ircomm_open_tsap(struct ircomm_cb *self)
+ self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT,
+ ¬ify);
+ if (!self->tsap) {
+- IRDA_DEBUG(0, "%sfailed to allocate tsap\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%sfailed to allocate tsap\n", __func__ );
+ return -1;
+ }
+ self->slsap_sel = self->tsap->stsap_sel;
+@@ -121,7 +121,7 @@ static int ircomm_ttp_connect_request(struct ircomm_cb *self,
+ {
+ int ret = 0;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ /* Don't forget to refcount it - should be NULL anyway */
+ if(userdata)
+@@ -145,7 +145,7 @@ static int ircomm_ttp_connect_response(struct ircomm_cb *self,
+ {
+ int ret;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ /* Don't forget to refcount it - should be NULL anyway */
+ if(userdata)
+@@ -173,7 +173,7 @@ static int ircomm_ttp_data_request(struct ircomm_cb *self,
+
+ IRDA_ASSERT(skb != NULL, return -1;);
+
+- IRDA_DEBUG(2, "%s(), clen=%d\n", __FUNCTION__ , clen);
++ IRDA_DEBUG(2, "%s(), clen=%d\n", __func__ , clen);
+
+ /*
+ * Insert clen field, currently we either send data only, or control
+@@ -190,7 +190,7 @@ static int ircomm_ttp_data_request(struct ircomm_cb *self,
+
+ ret = irttp_data_request(self->tsap, skb);
+ if (ret) {
+- IRDA_ERROR("%s(), failed\n", __FUNCTION__);
++ IRDA_ERROR("%s(), failed\n", __func__);
+ /* irttp_data_request already free the packet */
+ }
+
+@@ -208,7 +208,7 @@ static int ircomm_ttp_data_indication(void *instance, void *sap,
+ {
+ struct ircomm_cb *self = (struct ircomm_cb *) instance;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+@@ -231,7 +231,7 @@ static void ircomm_ttp_connect_confirm(void *instance, void *sap,
+ struct ircomm_cb *self = (struct ircomm_cb *) instance;
+ struct ircomm_info info;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
+@@ -240,7 +240,7 @@ static void ircomm_ttp_connect_confirm(void *instance, void *sap,
+
+ if (max_sdu_size != TTP_SAR_DISABLE) {
+ IRDA_ERROR("%s(), SAR not allowed for IrCOMM!\n",
+- __FUNCTION__);
++ __func__);
+ goto out;
+ }
+
+@@ -272,7 +272,7 @@ static void ircomm_ttp_connect_indication(void *instance, void *sap,
+ struct ircomm_cb *self = (struct ircomm_cb *)instance;
+ struct ircomm_info info;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
+@@ -281,7 +281,7 @@ static void ircomm_ttp_connect_indication(void *instance, void *sap,
+
+ if (max_sdu_size != TTP_SAR_DISABLE) {
+ IRDA_ERROR("%s(), SAR not allowed for IrCOMM!\n",
+- __FUNCTION__);
++ __func__);
+ goto out;
+ }
+
+@@ -331,7 +331,7 @@ static void ircomm_ttp_disconnect_indication(void *instance, void *sap,
+ struct ircomm_cb *self = (struct ircomm_cb *) instance;
+ struct ircomm_info info;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
+@@ -356,7 +356,7 @@ static void ircomm_ttp_flow_indication(void *instance, void *sap,
+ {
+ struct ircomm_cb *self = (struct ircomm_cb *) instance;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
+diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
+index be627e1..d262041 100644
+--- a/net/irda/ircomm/ircomm_tty.c
++++ b/net/irda/ircomm/ircomm_tty.c
+@@ -115,7 +115,7 @@ static int __init ircomm_tty_init(void)
+ return -ENOMEM;
+ ircomm_tty = hashbin_new(HB_LOCK);
+ if (ircomm_tty == NULL) {
+- IRDA_ERROR("%s(), can't allocate hashbin!\n", __FUNCTION__);
++ IRDA_ERROR("%s(), can't allocate hashbin!\n", __func__);
+ put_tty_driver(driver);
+ return -ENOMEM;
+ }
+@@ -133,7 +133,7 @@ static int __init ircomm_tty_init(void)
+ tty_set_operations(driver, &ops);
+ if (tty_register_driver(driver)) {
+ IRDA_ERROR("%s(): Couldn't register serial driver\n",
+- __FUNCTION__);
++ __func__);
+ put_tty_driver(driver);
+ return -1;
+ }
+@@ -142,7 +142,7 @@ static int __init ircomm_tty_init(void)
+
+ static void __exit __ircomm_tty_cleanup(struct ircomm_tty_cb *self)
+ {
+- IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -163,12 +163,12 @@ static void __exit ircomm_tty_cleanup(void)
+ {
+ int ret;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ ret = tty_unregister_driver(driver);
+ if (ret) {
+ IRDA_ERROR("%s(), failed to unregister driver\n",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+
+@@ -187,14 +187,14 @@ static int ircomm_tty_startup(struct ircomm_tty_cb *self)
+ notify_t notify;
+ int ret = -ENODEV;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+ /* Check if already open */
+ if (test_and_set_bit(ASYNC_B_INITIALIZED, &self->flags)) {
+- IRDA_DEBUG(2, "%s(), already open so break out!\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), already open so break out!\n", __func__ );
+ return 0;
+ }
+
+@@ -224,7 +224,7 @@ static int ircomm_tty_startup(struct ircomm_tty_cb *self)
+ /* Connect IrCOMM link with remote device */
+ ret = ircomm_tty_attach_cable(self);
+ if (ret < 0) {
+- IRDA_ERROR("%s(), error attaching cable!\n", __FUNCTION__);
++ IRDA_ERROR("%s(), error attaching cable!\n", __func__);
+ goto err;
+ }
+
+@@ -249,7 +249,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
+ unsigned long flags;
+ struct tty_struct *tty;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ tty = self->tty;
+
+@@ -260,12 +260,12 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
+ if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
+ /* nonblock mode is set or port is not enabled */
+ self->flags |= ASYNC_NORMAL_ACTIVE;
+- IRDA_DEBUG(1, "%s(), O_NONBLOCK requested!\n", __FUNCTION__ );
++ IRDA_DEBUG(1, "%s(), O_NONBLOCK requested!\n", __func__ );
+ return 0;
+ }
+
+ if (tty->termios->c_cflag & CLOCAL) {
+- IRDA_DEBUG(1, "%s(), doing CLOCAL!\n", __FUNCTION__ );
++ IRDA_DEBUG(1, "%s(), doing CLOCAL!\n", __func__ );
+ do_clocal = 1;
+ }
+
+@@ -368,7 +368,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
+ unsigned long flags;
+ int ret;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ line = tty->index;
+ if ((line < 0) || (line >= IRCOMM_TTY_PORTS)) {
+@@ -381,7 +381,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
+ /* No, so make new instance */
+ self = kzalloc(sizeof(struct ircomm_tty_cb), GFP_KERNEL);
+ if (self == NULL) {
+- IRDA_ERROR("%s(), kmalloc failed!\n", __FUNCTION__);
++ IRDA_ERROR("%s(), kmalloc failed!\n", __func__);
+ return -ENOMEM;
+ }
+
+@@ -420,7 +420,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
+ self->tty = tty;
+ spin_unlock_irqrestore(&self->spinlock, flags);
+
+- IRDA_DEBUG(1, "%s(), %s%d, count = %d\n", __FUNCTION__ , tty->driver->name,
++ IRDA_DEBUG(1, "%s(), %s%d, count = %d\n", __func__ , tty->driver->name,
+ self->line, self->open_count);
+
+ /* Not really used by us, but lets do it anyway */
+@@ -442,7 +442,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
+
+ if (wait_event_interruptible(self->close_wait, !test_bit(ASYNC_B_CLOSING, &self->flags))) {
+ IRDA_WARNING("%s - got signal while blocking on ASYNC_CLOSING!\n",
+- __FUNCTION__);
++ __func__);
+ return -ERESTARTSYS;
+ }
+
+@@ -460,9 +460,9 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
+ self->settings.service_type = IRCOMM_9_WIRE; /* 9 wire as default */
+ /* Jan Kiszka -> add DSR/RI -> Conform to IrCOMM spec */
+ self->settings.dce = IRCOMM_CTS | IRCOMM_CD | IRCOMM_DSR | IRCOMM_RI; /* Default line settings */
+- IRDA_DEBUG(2, "%s(), IrCOMM device\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), IrCOMM device\n", __func__ );
+ } else {
+- IRDA_DEBUG(2, "%s(), IrLPT device\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), IrLPT device\n", __func__ );
+ self->service_type = IRCOMM_3_WIRE_RAW;
+ self->settings.service_type = IRCOMM_3_WIRE_RAW; /* Default */
+ }
+@@ -474,7 +474,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
+ ret = ircomm_tty_block_til_ready(self, filp);
+ if (ret) {
+ IRDA_DEBUG(2,
+- "%s(), returning after block_til_ready with %d\n", __FUNCTION__ ,
++ "%s(), returning after block_til_ready with %d\n", __func__ ,
+ ret);
+
+ return ret;
+@@ -493,7 +493,7 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+ unsigned long flags;
+
+- IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s()\n", __func__ );
+
+ if (!tty)
+ return;
+@@ -506,7 +506,7 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
+ if (tty_hung_up_p(filp)) {
+ spin_unlock_irqrestore(&self->spinlock, flags);
+
+- IRDA_DEBUG(0, "%s(), returning 1\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s(), returning 1\n", __func__ );
+ return;
+ }
+
+@@ -519,20 +519,20 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
+ * serial port won't be shutdown.
+ */
+ IRDA_DEBUG(0, "%s(), bad serial port count; "
+- "tty->count is 1, state->count is %d\n", __FUNCTION__ ,
++ "tty->count is 1, state->count is %d\n", __func__ ,
+ self->open_count);
+ self->open_count = 1;
+ }
+
+ if (--self->open_count < 0) {
+ IRDA_ERROR("%s(), bad serial port count for ttys%d: %d\n",
+- __FUNCTION__, self->line, self->open_count);
++ __func__, self->line, self->open_count);
+ self->open_count = 0;
+ }
+ if (self->open_count) {
+ spin_unlock_irqrestore(&self->spinlock, flags);
+
+- IRDA_DEBUG(0, "%s(), open count > 0\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s(), open count > 0\n", __func__ );
+ return;
+ }
+
+@@ -608,7 +608,7 @@ static void ircomm_tty_do_softint(struct work_struct *work)
+ unsigned long flags;
+ struct sk_buff *skb, *ctrl_skb;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ if (!self || self->magic != IRCOMM_TTY_MAGIC)
+ return;
+@@ -678,7 +678,7 @@ static int ircomm_tty_write(struct tty_struct *tty,
+ int len = 0;
+ int size;
+
+- IRDA_DEBUG(2, "%s(), count=%d, hw_stopped=%d\n", __FUNCTION__ , count,
++ IRDA_DEBUG(2, "%s(), count=%d, hw_stopped=%d\n", __func__ , count,
+ tty->hw_stopped);
+
+ IRDA_ASSERT(self != NULL, return -1;);
+@@ -701,7 +701,7 @@ static int ircomm_tty_write(struct tty_struct *tty,
+ * we don't mess up the original "safe skb" (see tx_data_size).
+ * Jean II */
+ if (self->max_header_size == IRCOMM_TTY_HDR_UNINITIALISED) {
+- IRDA_DEBUG(1, "%s() : not initialised\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s() : not initialised\n", __func__);
+ #ifdef IRCOMM_NO_TX_BEFORE_INIT
+ /* We didn't consume anything, TTY will retry */
+ return 0;
+@@ -830,7 +830,7 @@ static int ircomm_tty_write_room(struct tty_struct *tty)
+ ret = self->max_data_size;
+ spin_unlock_irqrestore(&self->spinlock, flags);
+ }
+- IRDA_DEBUG(2, "%s(), ret=%d\n", __FUNCTION__ , ret);
++ IRDA_DEBUG(2, "%s(), ret=%d\n", __func__ , ret);
+
+ return ret;
+ }
+@@ -847,7 +847,7 @@ static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout)
+ unsigned long orig_jiffies, poll_time;
+ unsigned long flags;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -882,7 +882,7 @@ static void ircomm_tty_throttle(struct tty_struct *tty)
+ {
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -913,7 +913,7 @@ static void ircomm_tty_unthrottle(struct tty_struct *tty)
+ {
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -928,7 +928,7 @@ static void ircomm_tty_unthrottle(struct tty_struct *tty)
+ self->settings.dte |= (IRCOMM_RTS|IRCOMM_DELTA_RTS);
+
+ ircomm_param_request(self, IRCOMM_DTE, TRUE);
+- IRDA_DEBUG(1, "%s(), FLOW_START\n", __FUNCTION__ );
++ IRDA_DEBUG(1, "%s(), FLOW_START\n", __func__ );
+ }
+ ircomm_flow_request(self->ircomm, FLOW_START);
+ }
+@@ -965,7 +965,7 @@ static void ircomm_tty_shutdown(struct ircomm_tty_cb *self)
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+- IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s()\n", __func__ );
+
+ if (!test_and_clear_bit(ASYNC_B_INITIALIZED, &self->flags))
+ return;
+@@ -1008,7 +1008,7 @@ static void ircomm_tty_hangup(struct tty_struct *tty)
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+ unsigned long flags;
+
+- IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -1037,7 +1037,7 @@ static void ircomm_tty_hangup(struct tty_struct *tty)
+ */
+ static void ircomm_tty_send_xchar(struct tty_struct *tty, char ch)
+ {
+- IRDA_DEBUG(0, "%s(), not impl\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s(), not impl\n", __func__ );
+ }
+
+ /*
+@@ -1081,7 +1081,7 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
+ struct tty_struct *tty;
+ int status;
+
+- IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -1095,14 +1095,14 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
+ }
+ if ((self->flags & ASYNC_CHECK_CD) && (status & IRCOMM_DELTA_CD)) {
+ IRDA_DEBUG(2,
+- "%s(), ircomm%d CD now %s...\n", __FUNCTION__ , self->line,
++ "%s(), ircomm%d CD now %s...\n", __func__ , self->line,
+ (status & IRCOMM_CD) ? "on" : "off");
+
+ if (status & IRCOMM_CD) {
+ wake_up_interruptible(&self->open_wait);
+ } else {
+ IRDA_DEBUG(2,
+- "%s(), Doing serial hangup..\n", __FUNCTION__ );
++ "%s(), Doing serial hangup..\n", __func__ );
+ if (tty)
+ tty_hangup(tty);
+
+@@ -1114,7 +1114,7 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
+ if (tty->hw_stopped) {
+ if (status & IRCOMM_CTS) {
+ IRDA_DEBUG(2,
+- "%s(), CTS tx start...\n", __FUNCTION__ );
++ "%s(), CTS tx start...\n", __func__ );
+ tty->hw_stopped = 0;
+
+ /* Wake up processes blocked on open */
+@@ -1126,7 +1126,7 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
+ } else {
+ if (!(status & IRCOMM_CTS)) {
+ IRDA_DEBUG(2,
+- "%s(), CTS tx stop...\n", __FUNCTION__ );
++ "%s(), CTS tx stop...\n", __func__ );
+ tty->hw_stopped = 1;
+ }
+ }
+@@ -1144,14 +1144,14 @@ static int ircomm_tty_data_indication(void *instance, void *sap,
+ {
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ IRDA_ASSERT(skb != NULL, return -1;);
+
+ if (!self->tty) {
+- IRDA_DEBUG(0, "%s(), no tty!\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s(), no tty!\n", __func__ );
+ return 0;
+ }
+
+@@ -1162,7 +1162,7 @@ static int ircomm_tty_data_indication(void *instance, void *sap,
+ * params, we can just as well declare the hardware for running.
+ */
+ if (self->tty->hw_stopped && (self->flow == FLOW_START)) {
+- IRDA_DEBUG(0, "%s(), polling for line settings!\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s(), polling for line settings!\n", __func__ );
+ ircomm_param_request(self, IRCOMM_POLL, TRUE);
+
+ /* We can just as well declare the hardware for running */
+@@ -1194,7 +1194,7 @@ static int ircomm_tty_control_indication(void *instance, void *sap,
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+ int clen;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+@@ -1230,7 +1230,7 @@ static void ircomm_tty_flow_indication(void *instance, void *sap,
+
+ switch (cmd) {
+ case FLOW_START:
+- IRDA_DEBUG(2, "%s(), hw start!\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), hw start!\n", __func__ );
+ tty->hw_stopped = 0;
+
+ /* ircomm_tty_do_softint will take care of the rest */
+@@ -1238,7 +1238,7 @@ static void ircomm_tty_flow_indication(void *instance, void *sap,
+ break;
+ default: /* If we get here, something is very wrong, better stop */
+ case FLOW_STOP:
+- IRDA_DEBUG(2, "%s(), hw stopped!\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), hw stopped!\n", __func__ );
+ tty->hw_stopped = 1;
+ break;
+ }
+diff --git a/net/irda/ircomm/ircomm_tty_attach.c b/net/irda/ircomm/ircomm_tty_attach.c
+index b5a1388..9032a1d 100644
+--- a/net/irda/ircomm/ircomm_tty_attach.c
++++ b/net/irda/ircomm/ircomm_tty_attach.c
+@@ -129,14 +129,14 @@ static int (*state[])(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
+ */
+ int ircomm_tty_attach_cable(struct ircomm_tty_cb *self)
+ {
+- IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+ /* Check if somebody has already connected to us */
+ if (ircomm_is_connected(self->ircomm)) {
+- IRDA_DEBUG(0, "%s(), already connected!\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s(), already connected!\n", __func__ );
+ return 0;
+ }
+
+@@ -158,7 +158,7 @@ int ircomm_tty_attach_cable(struct ircomm_tty_cb *self)
+ */
+ void ircomm_tty_detach_cable(struct ircomm_tty_cb *self)
+ {
+- IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -207,7 +207,7 @@ static void ircomm_tty_ias_register(struct ircomm_tty_cb *self)
+ __u8 oct_seq[6];
+ __u16 hints;
+
+- IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -308,16 +308,16 @@ int ircomm_tty_send_initial_parameters(struct ircomm_tty_cb *self)
+ * Set default values, but only if the application for some reason
+ * haven't set them already
+ */
+- IRDA_DEBUG(2, "%s(), data-rate = %d\n", __FUNCTION__ ,
++ IRDA_DEBUG(2, "%s(), data-rate = %d\n", __func__ ,
+ self->settings.data_rate);
+ if (!self->settings.data_rate)
+ self->settings.data_rate = 9600;
+- IRDA_DEBUG(2, "%s(), data-format = %d\n", __FUNCTION__ ,
++ IRDA_DEBUG(2, "%s(), data-format = %d\n", __func__ ,
+ self->settings.data_format);
+ if (!self->settings.data_format)
+ self->settings.data_format = IRCOMM_WSIZE_8; /* 8N1 */
+
+- IRDA_DEBUG(2, "%s(), flow-control = %d\n", __FUNCTION__ ,
++ IRDA_DEBUG(2, "%s(), flow-control = %d\n", __func__ ,
+ self->settings.flow_control);
+ /*self->settings.flow_control = IRCOMM_RTS_CTS_IN|IRCOMM_RTS_CTS_OUT;*/
+
+@@ -362,7 +362,7 @@ static void ircomm_tty_discovery_indication(discinfo_t *discovery,
+ struct ircomm_tty_cb *self;
+ struct ircomm_tty_info info;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ /* Important note :
+ * We need to drop all passive discoveries.
+@@ -398,7 +398,7 @@ void ircomm_tty_disconnect_indication(void *instance, void *sap,
+ {
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -428,7 +428,7 @@ static void ircomm_tty_getvalue_confirm(int result, __u16 obj_id,
+ {
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) priv;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -439,13 +439,13 @@ static void ircomm_tty_getvalue_confirm(int result, __u16 obj_id,
+
+ /* Check if request succeeded */
+ if (result != IAS_SUCCESS) {
+- IRDA_DEBUG(4, "%s(), got NULL value!\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s(), got NULL value!\n", __func__ );
+ return;
+ }
+
+ switch (value->type) {
+ case IAS_OCT_SEQ:
+- IRDA_DEBUG(2, "%s(), got octet sequence\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), got octet sequence\n", __func__ );
+
+ irda_param_extract_all(self, value->t.oct_seq, value->len,
+ &ircomm_param_info);
+@@ -455,21 +455,21 @@ static void ircomm_tty_getvalue_confirm(int result, __u16 obj_id,
+ break;
+ case IAS_INTEGER:
+ /* Got LSAP selector */
+- IRDA_DEBUG(2, "%s(), got lsapsel = %d\n", __FUNCTION__ ,
++ IRDA_DEBUG(2, "%s(), got lsapsel = %d\n", __func__ ,
+ value->t.integer);
+
+ if (value->t.integer == -1) {
+- IRDA_DEBUG(0, "%s(), invalid value!\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s(), invalid value!\n", __func__ );
+ } else
+ self->dlsap_sel = value->t.integer;
+
+ ircomm_tty_do_event(self, IRCOMM_TTY_GOT_LSAPSEL, NULL, NULL);
+ break;
+ case IAS_MISSING:
+- IRDA_DEBUG(0, "%s(), got IAS_MISSING\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s(), got IAS_MISSING\n", __func__ );
+ break;
+ default:
+- IRDA_DEBUG(0, "%s(), got unknown type!\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s(), got unknown type!\n", __func__ );
+ break;
+ }
+ irias_delete_value(value);
+@@ -489,7 +489,7 @@ void ircomm_tty_connect_confirm(void *instance, void *sap,
+ {
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -520,7 +520,7 @@ void ircomm_tty_connect_indication(void *instance, void *sap,
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+ int clen;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -549,7 +549,7 @@ void ircomm_tty_connect_indication(void *instance, void *sap,
+ */
+ void ircomm_tty_link_established(struct ircomm_tty_cb *self)
+ {
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -566,10 +566,10 @@ void ircomm_tty_link_established(struct ircomm_tty_cb *self)
+ * line.
+ */
+ if ((self->flags & ASYNC_CTS_FLOW) && ((self->settings.dce & IRCOMM_CTS) == 0)) {
+- IRDA_DEBUG(0, "%s(), waiting for CTS ...\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s(), waiting for CTS ...\n", __func__ );
+ return;
+ } else {
+- IRDA_DEBUG(1, "%s(), starting hardware!\n", __FUNCTION__ );
++ IRDA_DEBUG(1, "%s(), starting hardware!\n", __func__ );
+
+ self->tty->hw_stopped = 0;
+
+@@ -607,7 +607,7 @@ static void ircomm_tty_watchdog_timer_expired(void *data)
+ {
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) data;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+@@ -628,7 +628,7 @@ int ircomm_tty_do_event(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+- IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __FUNCTION__ ,
++ IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ ,
+ ircomm_tty_state[self->state], ircomm_tty_event[event]);
+
+ return (*state[self->state])(self, event, skb, info);
+@@ -646,7 +646,7 @@ static inline void ircomm_tty_next_state(struct ircomm_tty_cb *self, IRCOMM_TTY_
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+- IRDA_DEBUG(2, "%s: next state=%s, service type=%d\n", __FUNCTION__ ,
++ IRDA_DEBUG(2, "%s: next state=%s, service type=%d\n", __func__ ,
+ ircomm_tty_state[self->state], self->service_type);
+ */
+ self->state = state;
+@@ -665,7 +665,7 @@ static int ircomm_tty_state_idle(struct ircomm_tty_cb *self,
+ {
+ int ret = 0;
+
+- IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __FUNCTION__ ,
++ IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ ,
+ ircomm_tty_state[self->state], ircomm_tty_event[event]);
+ switch (event) {
+ case IRCOMM_TTY_ATTACH_CABLE:
+@@ -681,7 +681,7 @@ static int ircomm_tty_state_idle(struct ircomm_tty_cb *self,
+
+ if (self->iriap) {
+ IRDA_WARNING("%s(), busy with a previous query\n",
+- __FUNCTION__);
++ __func__);
+ return -EBUSY;
+ }
+
+@@ -709,7 +709,7 @@ static int ircomm_tty_state_idle(struct ircomm_tty_cb *self,
+ ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), unknown event: %s\n", __FUNCTION__ ,
++ IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ ,
+ ircomm_tty_event[event]);
+ ret = -EINVAL;
+ }
+@@ -729,7 +729,7 @@ static int ircomm_tty_state_search(struct ircomm_tty_cb *self,
+ {
+ int ret = 0;
+
+- IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __FUNCTION__ ,
++ IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ ,
+ ircomm_tty_state[self->state], ircomm_tty_event[event]);
+
+ switch (event) {
+@@ -739,7 +739,7 @@ static int ircomm_tty_state_search(struct ircomm_tty_cb *self,
+
+ if (self->iriap) {
+ IRDA_WARNING("%s(), busy with a previous query\n",
+- __FUNCTION__);
++ __func__);
+ return -EBUSY;
+ }
+
+@@ -782,7 +782,7 @@ static int ircomm_tty_state_search(struct ircomm_tty_cb *self,
+ ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), unknown event: %s\n", __FUNCTION__ ,
++ IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ ,
+ ircomm_tty_event[event]);
+ ret = -EINVAL;
+ }
+@@ -802,14 +802,14 @@ static int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self,
+ {
+ int ret = 0;
+
+- IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __FUNCTION__ ,
++ IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ ,
+ ircomm_tty_state[self->state], ircomm_tty_event[event]);
+
+ switch (event) {
+ case IRCOMM_TTY_GOT_PARAMETERS:
+ if (self->iriap) {
+ IRDA_WARNING("%s(), busy with a previous query\n",
+- __FUNCTION__);
++ __func__);
+ return -EBUSY;
+ }
+
+@@ -840,7 +840,7 @@ static int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self,
+ ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), unknown event: %s\n", __FUNCTION__ ,
++ IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ ,
+ ircomm_tty_event[event]);
+ ret = -EINVAL;
+ }
+@@ -860,7 +860,7 @@ static int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb *self,
+ {
+ int ret = 0;
+
+- IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __FUNCTION__ ,
++ IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ ,
+ ircomm_tty_state[self->state], ircomm_tty_event[event]);
+
+ switch (event) {
+@@ -889,7 +889,7 @@ static int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb *self,
+ ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), unknown event: %s\n", __FUNCTION__ ,
++ IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ ,
+ ircomm_tty_event[event]);
+ ret = -EINVAL;
+ }
+@@ -909,7 +909,7 @@ static int ircomm_tty_state_setup(struct ircomm_tty_cb *self,
+ {
+ int ret = 0;
+
+- IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __FUNCTION__ ,
++ IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ ,
+ ircomm_tty_state[self->state], ircomm_tty_event[event]);
+
+ switch (event) {
+@@ -943,7 +943,7 @@ static int ircomm_tty_state_setup(struct ircomm_tty_cb *self,
+ ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), unknown event: %s\n", __FUNCTION__ ,
++ IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ ,
+ ircomm_tty_event[event]);
+ ret = -EINVAL;
+ }
+@@ -981,13 +981,13 @@ static int ircomm_tty_state_ready(struct ircomm_tty_cb *self,
+ self->settings.dce = IRCOMM_DELTA_CD;
+ ircomm_tty_check_modem_status(self);
+ } else {
+- IRDA_DEBUG(0, "%s(), hanging up!\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s(), hanging up!\n", __func__ );
+ if (self->tty)
+ tty_hangup(self->tty);
+ }
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), unknown event: %s\n", __FUNCTION__ ,
++ IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ ,
+ ircomm_tty_event[event]);
+ ret = -EINVAL;
+ }
+diff --git a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c
+index 6030947..24cb3aa 100644
+--- a/net/irda/ircomm/ircomm_tty_ioctl.c
++++ b/net/irda/ircomm/ircomm_tty_ioctl.c
+@@ -57,7 +57,7 @@ static void ircomm_tty_change_speed(struct ircomm_tty_cb *self)
+ unsigned cflag, cval;
+ int baud;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ if (!self->tty || !self->tty->termios || !self->ircomm)
+ return;
+@@ -94,7 +94,7 @@ static void ircomm_tty_change_speed(struct ircomm_tty_cb *self)
+ self->settings.flow_control |= IRCOMM_RTS_CTS_IN;
+ /* This got me. Bummer. Jean II */
+ if (self->service_type == IRCOMM_3_WIRE_RAW)
+- IRDA_WARNING("%s(), enabling RTS/CTS on link that doesn't support it (3-wire-raw)\n", __FUNCTION__);
++ IRDA_WARNING("%s(), enabling RTS/CTS on link that doesn't support it (3-wire-raw)\n", __func__);
+ } else {
+ self->flags &= ~ASYNC_CTS_FLOW;
+ self->settings.flow_control &= ~IRCOMM_RTS_CTS_IN;
+@@ -150,7 +150,7 @@ void ircomm_tty_set_termios(struct tty_struct *tty,
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+ unsigned int cflag = tty->termios->c_cflag;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ if ((cflag == old_termios->c_cflag) &&
+ (RELEVANT_IFLAG(tty->termios->c_iflag) ==
+@@ -199,7 +199,7 @@ int ircomm_tty_tiocmget(struct tty_struct *tty, struct file *file)
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+ unsigned int result;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+@@ -224,7 +224,7 @@ int ircomm_tty_tiocmset(struct tty_struct *tty, struct file *file,
+ {
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+@@ -266,7 +266,7 @@ static int ircomm_tty_get_serial_info(struct ircomm_tty_cb *self,
+ if (!retinfo)
+ return -EFAULT;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ memset(&info, 0, sizeof(info));
+ info.line = self->line;
+@@ -302,7 +302,7 @@ static int ircomm_tty_set_serial_info(struct ircomm_tty_cb *self,
+ struct serial_struct new_serial;
+ struct ircomm_tty_cb old_state, *state;
+
+- IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s()\n", __func__ );
+
+ if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
+ return -EFAULT;
+@@ -376,7 +376,7 @@ int ircomm_tty_ioctl(struct tty_struct *tty, struct file *file,
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+ int ret = 0;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+ (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
+@@ -397,7 +397,7 @@ int ircomm_tty_ioctl(struct tty_struct *tty, struct file *file,
+ break;
+
+ case TIOCGICOUNT:
+- IRDA_DEBUG(0, "%s(), TIOCGICOUNT not impl!\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s(), TIOCGICOUNT not impl!\n", __func__ );
+ #if 0
+ save_flags(flags); cli();
+ cnow = driver->icount;
+diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c
+index 8718591..ea319e3 100644
+--- a/net/irda/irda_device.c
++++ b/net/irda/irda_device.c
+@@ -90,7 +90,7 @@ static void leftover_dongle(void *arg)
+
+ void irda_device_cleanup(void)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ hashbin_delete(tasks, (FREE_FUNC) __irda_task_delete);
+
+@@ -107,7 +107,7 @@ void irda_device_set_media_busy(struct net_device *dev, int status)
+ {
+ struct irlap_cb *self;
+
+- IRDA_DEBUG(4, "%s(%s)\n", __FUNCTION__, status ? "TRUE" : "FALSE");
++ IRDA_DEBUG(4, "%s(%s)\n", __func__, status ? "TRUE" : "FALSE");
+
+ self = (struct irlap_cb *) dev->atalk_ptr;
+
+@@ -147,11 +147,11 @@ int irda_device_is_receiving(struct net_device *dev)
+ struct if_irda_req req;
+ int ret;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s()\n", __func__);
+
+ if (!dev->do_ioctl) {
+ IRDA_ERROR("%s: do_ioctl not impl. by device driver\n",
+- __FUNCTION__);
++ __func__);
+ return -1;
+ }
+
+@@ -191,7 +191,7 @@ static int irda_task_kick(struct irda_task *task)
+ int count = 0;
+ int timeout;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s()\n", __func__);
+
+ IRDA_ASSERT(task != NULL, return -1;);
+ IRDA_ASSERT(task->magic == IRDA_TASK_MAGIC, return -1;);
+@@ -201,14 +201,14 @@ static int irda_task_kick(struct irda_task *task)
+ timeout = task->function(task);
+ if (count++ > 100) {
+ IRDA_ERROR("%s: error in task handler!\n",
+- __FUNCTION__);
++ __func__);
+ irda_task_delete(task);
+ return TRUE;
+ }
+ } while ((timeout == 0) && (task->state != IRDA_TASK_DONE));
+
+ if (timeout < 0) {
+- IRDA_ERROR("%s: Error executing task!\n", __FUNCTION__);
++ IRDA_ERROR("%s: Error executing task!\n", __func__);
+ irda_task_delete(task);
+ return TRUE;
+ }
+@@ -241,7 +241,7 @@ static int irda_task_kick(struct irda_task *task)
+ finished = FALSE;
+ } else {
+ IRDA_DEBUG(0, "%s(), not finished, and no timeout!\n",
+- __FUNCTION__);
++ __func__);
+ finished = FALSE;
+ }
+
+@@ -258,7 +258,7 @@ static void irda_task_timer_expired(void *data)
+ {
+ struct irda_task *task;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s()\n", __func__);
+
+ task = (struct irda_task *) data;
+
+diff --git a/net/irda/iriap.c b/net/irda/iriap.c
+index 390a790..9e15c82 100644
+--- a/net/irda/iriap.c
++++ b/net/irda/iriap.c
+@@ -108,7 +108,7 @@ int __init iriap_init(void)
+ irias_objects = hashbin_new(HB_LOCK);
+ if (!irias_objects) {
+ IRDA_WARNING("%s: Can't allocate irias_objects hashbin!\n",
+- __FUNCTION__);
++ __func__);
+ hashbin_delete(iriap, NULL);
+ return -ENOMEM;
+ }
+@@ -139,7 +139,7 @@ int __init iriap_init(void)
+ */
+ server = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL);
+ if (!server) {
+- IRDA_DEBUG(0, "%s(), unable to open server\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), unable to open server\n", __func__);
+ return -1;
+ }
+ iriap_register_lsap(server, LSAP_IAS, IAS_SERVER);
+@@ -171,11 +171,11 @@ struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv,
+ {
+ struct iriap_cb *self;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s()\n", __func__);
+
+ self = kzalloc(sizeof(*self), GFP_ATOMIC);
+ if (!self) {
+- IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
++ IRDA_WARNING("%s: Unable to kmalloc!\n", __func__);
+ return NULL;
+ }
+
+@@ -217,7 +217,7 @@ EXPORT_SYMBOL(iriap_open);
+ */
+ static void __iriap_close(struct iriap_cb *self)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
+@@ -241,7 +241,7 @@ void iriap_close(struct iriap_cb *self)
+ {
+ struct iriap_cb *entry;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
+@@ -262,7 +262,7 @@ static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode)
+ {
+ notify_t notify;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s()\n", __func__);
+
+ irda_notify_init(¬ify);
+ notify.connect_confirm = iriap_connect_confirm;
+@@ -277,7 +277,7 @@ static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode)
+
+ self->lsap = irlmp_open_lsap(slsap_sel, ¬ify, 0);
+ if (self->lsap == NULL) {
+- IRDA_ERROR("%s: Unable to allocated LSAP!\n", __FUNCTION__);
++ IRDA_ERROR("%s: Unable to allocated LSAP!\n", __func__);
+ return -1;
+ }
+ self->slsap_sel = self->lsap->slsap_sel;
+@@ -297,7 +297,7 @@ static void iriap_disconnect_indication(void *instance, void *sap,
+ {
+ struct iriap_cb *self;
+
+- IRDA_DEBUG(4, "%s(), reason=%s\n", __FUNCTION__, irlmp_reasons[reason]);
++ IRDA_DEBUG(4, "%s(), reason=%s\n", __func__, irlmp_reasons[reason]);
+
+ self = (struct iriap_cb *) instance;
+
+@@ -313,7 +313,7 @@ static void iriap_disconnect_indication(void *instance, void *sap,
+ dev_kfree_skb(skb);
+
+ if (self->mode == IAS_CLIENT) {
+- IRDA_DEBUG(4, "%s(), disconnect as client\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s(), disconnect as client\n", __func__);
+
+
+ iriap_do_client_event(self, IAP_LM_DISCONNECT_INDICATION,
+@@ -326,7 +326,7 @@ static void iriap_disconnect_indication(void *instance, void *sap,
+ if (self->confirm)
+ self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
+ } else {
+- IRDA_DEBUG(4, "%s(), disconnect as server\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s(), disconnect as server\n", __func__);
+ iriap_do_server_event(self, IAP_LM_DISCONNECT_INDICATION,
+ NULL);
+ iriap_close(self);
+@@ -340,7 +340,7 @@ static void iriap_disconnect_request(struct iriap_cb *self)
+ {
+ struct sk_buff *tx_skb;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
+@@ -349,7 +349,7 @@ static void iriap_disconnect_request(struct iriap_cb *self)
+ if (tx_skb == NULL) {
+ IRDA_DEBUG(0,
+ "%s(), Could not allocate an sk_buff of length %d\n",
+- __FUNCTION__, LMP_MAX_HEADER);
++ __func__, LMP_MAX_HEADER);
+ return;
+ }
+
+@@ -453,13 +453,13 @@ static void iriap_getvaluebyclass_confirm(struct iriap_cb *self,
+ /* Get length, MSB first */
+ len = be16_to_cpu(get_unaligned((__be16 *)(fp+n))); n += 2;
+
+- IRDA_DEBUG(4, "%s(), len=%d\n", __FUNCTION__, len);
++ IRDA_DEBUG(4, "%s(), len=%d\n", __func__, len);
+
+ /* Get object ID, MSB first */
+ obj_id = be16_to_cpu(get_unaligned((__be16 *)(fp+n))); n += 2;
+
+ type = fp[n++];
+- IRDA_DEBUG(4, "%s(), Value type = %d\n", __FUNCTION__, type);
++ IRDA_DEBUG(4, "%s(), Value type = %d\n", __func__, type);
+
+ switch (type) {
+ case IAS_INTEGER:
+@@ -468,7 +468,7 @@ static void iriap_getvaluebyclass_confirm(struct iriap_cb *self,
+ value = irias_new_integer_value(tmp_cpu32);
+
+ /* Legal values restricted to 0x01-0x6f, page 15 irttp */
+- IRDA_DEBUG(4, "%s(), lsap=%d\n", __FUNCTION__, value->t.integer);
++ IRDA_DEBUG(4, "%s(), lsap=%d\n", __func__, value->t.integer);
+ break;
+ case IAS_STRING:
+ charset = fp[n++];
+@@ -488,7 +488,7 @@ static void iriap_getvaluebyclass_confirm(struct iriap_cb *self,
+ /* case CS_UNICODE: */
+ default:
+ IRDA_DEBUG(0, "%s(), charset %s, not supported\n",
+- __FUNCTION__, ias_charset_types[charset]);
++ __func__, ias_charset_types[charset]);
+
+ /* Aborting, close connection! */
+ iriap_disconnect_request(self);
+@@ -496,7 +496,7 @@ static void iriap_getvaluebyclass_confirm(struct iriap_cb *self,
+ /* break; */
+ }
+ value_len = fp[n++];
+- IRDA_DEBUG(4, "%s(), strlen=%d\n", __FUNCTION__, value_len);
++ IRDA_DEBUG(4, "%s(), strlen=%d\n", __func__, value_len);
+
+ /* Make sure the string is null-terminated */
+ fp[n+value_len] = 0x00;
+@@ -526,7 +526,7 @@ static void iriap_getvaluebyclass_confirm(struct iriap_cb *self,
+ if (self->confirm)
+ self->confirm(IAS_SUCCESS, obj_id, value, self->priv);
+ else {
+- IRDA_DEBUG(0, "%s(), missing handler!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), missing handler!\n", __func__);
+ irias_delete_value(value);
+ }
+ }
+@@ -548,7 +548,7 @@ static void iriap_getvaluebyclass_response(struct iriap_cb *self,
+ __be16 tmp_be16;
+ __u8 *fp;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
+@@ -610,12 +610,12 @@ static void iriap_getvaluebyclass_response(struct iriap_cb *self,
+ memcpy(fp+n, value->t.oct_seq, value->len); n+=value->len;
+ break;
+ case IAS_MISSING:
+- IRDA_DEBUG( 3, "%s: sending IAS_MISSING\n", __FUNCTION__);
++ IRDA_DEBUG( 3, "%s: sending IAS_MISSING\n", __func__);
+ skb_put(tx_skb, 1);
+ fp[n++] = value->type;
+ break;
+ default:
+- IRDA_DEBUG(0, "%s(), type not implemented!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), type not implemented!\n", __func__);
+ break;
+ }
+ iriap_do_r_connect_event(self, IAP_CALL_RESPONSE, tx_skb);
+@@ -642,7 +642,7 @@ static void iriap_getvaluebyclass_indication(struct iriap_cb *self,
+ __u8 *fp;
+ int n;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
+@@ -697,7 +697,7 @@ void iriap_send_ack(struct iriap_cb *self)
+ struct sk_buff *tx_skb;
+ __u8 *frame;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
+@@ -728,7 +728,7 @@ void iriap_connect_request(struct iriap_cb *self)
+ self->saddr, self->daddr,
+ NULL, NULL);
+ if (ret < 0) {
+- IRDA_DEBUG(0, "%s(), connect failed!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), connect failed!\n", __func__);
+ self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
+ }
+ }
+@@ -776,7 +776,7 @@ static void iriap_connect_indication(void *instance, void *sap,
+ {
+ struct iriap_cb *self, *new;
+
+- IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s()\n", __func__);
+
+ self = (struct iriap_cb *) instance;
+
+@@ -787,14 +787,14 @@ static void iriap_connect_indication(void *instance, void *sap,
+ /* Start new server */
+ new = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL);
+ if (!new) {
+- IRDA_DEBUG(0, "%s(), open failed\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), open failed\n", __func__);
+ goto out;
+ }
+
+ /* Now attach up the new "socket" */
+ new->lsap = irlmp_dup(self->lsap, new);
+ if (!new->lsap) {
+- IRDA_DEBUG(0, "%s(), dup failed!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), dup failed!\n", __func__);
+ goto out;
+ }
+
+@@ -824,7 +824,7 @@ static int iriap_data_indication(void *instance, void *sap,
+ __u8 *frame;
+ __u8 opcode;
+
+- IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(3, "%s()\n", __func__);
+
+ self = (struct iriap_cb *) instance;
+
+@@ -836,7 +836,7 @@ static int iriap_data_indication(void *instance, void *sap,
+
+ if (self->mode == IAS_SERVER) {
+ /* Call server */
+- IRDA_DEBUG(4, "%s(), Calling server!\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s(), Calling server!\n", __func__);
+ iriap_do_r_connect_event(self, IAP_RECV_F_LST, skb);
+ goto out;
+ }
+@@ -844,13 +844,13 @@ static int iriap_data_indication(void *instance, void *sap,
+ if (~opcode & IAP_LST) {
+ IRDA_WARNING("%s:, IrIAS multiframe commands or "
+ "results is not implemented yet!\n",
+- __FUNCTION__);
++ __func__);
+ goto out;
+ }
+
+ /* Check for ack frames since they don't contain any data */
+ if (opcode & IAP_ACK) {
+- IRDA_DEBUG(0, "%s() Got ack frame!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s() Got ack frame!\n", __func__);
+ goto out;
+ }
+
+@@ -868,7 +868,7 @@ static int iriap_data_indication(void *instance, void *sap,
+ iriap_getvaluebyclass_confirm(self, skb);
+ break;
+ case IAS_CLASS_UNKNOWN:
+- IRDA_DEBUG(1, "%s(), No such class!\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), No such class!\n", __func__);
+ /* Finished, close connection! */
+ iriap_disconnect_request(self);
+
+@@ -881,7 +881,7 @@ static int iriap_data_indication(void *instance, void *sap,
+ self->priv);
+ break;
+ case IAS_ATTRIB_UNKNOWN:
+- IRDA_DEBUG(1, "%s(), No such attribute!\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), No such attribute!\n", __func__);
+ /* Finished, close connection! */
+ iriap_disconnect_request(self);
+
+@@ -896,7 +896,7 @@ static int iriap_data_indication(void *instance, void *sap,
+ }
+ break;
+ default:
+- IRDA_DEBUG(0, "%s(), Unknown op-code: %02x\n", __FUNCTION__,
++ IRDA_DEBUG(0, "%s(), Unknown op-code: %02x\n", __func__,
+ opcode);
+ break;
+ }
+@@ -918,7 +918,7 @@ void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb)
+ __u8 *fp;
+ __u8 opcode;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
+@@ -929,7 +929,7 @@ void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb)
+ opcode = fp[0];
+ if (~opcode & 0x80) {
+ IRDA_WARNING("%s: IrIAS multiframe commands or results "
+- "is not implemented yet!\n", __FUNCTION__);
++ "is not implemented yet!\n", __func__);
+ return;
+ }
+ opcode &= 0x7f; /* Mask away LST bit */
+@@ -937,7 +937,7 @@ void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb)
+ switch (opcode) {
+ case GET_INFO_BASE:
+ IRDA_WARNING("%s: GetInfoBaseDetails not implemented yet!\n",
+- __FUNCTION__);
++ __func__);
+ break;
+ case GET_VALUE_BY_CLASS:
+ iriap_getvaluebyclass_indication(self, skb);
+diff --git a/net/irda/iriap_event.c b/net/irda/iriap_event.c
+index 8fb9d72..a301cbd 100644
+--- a/net/irda/iriap_event.c
++++ b/net/irda/iriap_event.c
+@@ -185,7 +185,7 @@ static void state_s_disconnect(struct iriap_cb *self, IRIAP_EVENT event,
+ case IAP_LM_DISCONNECT_INDICATION:
+ break;
+ default:
+- IRDA_DEBUG(0, "%s(), Unknown event %d\n", __FUNCTION__, event);
++ IRDA_DEBUG(0, "%s(), Unknown event %d\n", __func__, event);
+ break;
+ }
+ }
+@@ -217,7 +217,7 @@ static void state_s_connecting(struct iriap_cb *self, IRIAP_EVENT event,
+ iriap_next_client_state(self, S_DISCONNECT);
+ break;
+ default:
+- IRDA_DEBUG(0, "%s(), Unknown event %d\n", __FUNCTION__, event);
++ IRDA_DEBUG(0, "%s(), Unknown event %d\n", __func__, event);
+ break;
+ }
+ }
+@@ -269,7 +269,7 @@ static void state_s_make_call(struct iriap_cb *self, IRIAP_EVENT event,
+ iriap_next_call_state(self, S_OUTSTANDING);
+ break;
+ default:
+- IRDA_DEBUG(0, "%s(), Unknown event %d\n", __FUNCTION__, event);
++ IRDA_DEBUG(0, "%s(), Unknown event %d\n", __func__, event);
+ break;
+ }
+ }
+@@ -283,7 +283,7 @@ static void state_s_make_call(struct iriap_cb *self, IRIAP_EVENT event,
+ static void state_s_calling(struct iriap_cb *self, IRIAP_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(0, "%s(), Not implemented\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), Not implemented\n", __func__);
+ }
+
+ /*
+@@ -305,7 +305,7 @@ static void state_s_outstanding(struct iriap_cb *self, IRIAP_EVENT event,
+ iriap_next_call_state(self, S_WAIT_FOR_CALL);
+ break;
+ default:
+- IRDA_DEBUG(0, "%s(), Unknown event %d\n", __FUNCTION__, event);
++ IRDA_DEBUG(0, "%s(), Unknown event %d\n", __func__, event);
+ break;
+ }
+ }
+@@ -318,7 +318,7 @@ static void state_s_outstanding(struct iriap_cb *self, IRIAP_EVENT event,
+ static void state_s_replying(struct iriap_cb *self, IRIAP_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(0, "%s(), Not implemented\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), Not implemented\n", __func__);
+ }
+
+ /*
+@@ -330,7 +330,7 @@ static void state_s_replying(struct iriap_cb *self, IRIAP_EVENT event,
+ static void state_s_wait_for_call(struct iriap_cb *self, IRIAP_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(0, "%s(), Not implemented\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), Not implemented\n", __func__);
+ }
+
+
+@@ -343,7 +343,7 @@ static void state_s_wait_for_call(struct iriap_cb *self, IRIAP_EVENT event,
+ static void state_s_wait_active(struct iriap_cb *self, IRIAP_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(0, "%s(), Not implemented\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), Not implemented\n", __func__);
+ }
+
+ /**************************************************************************
+@@ -367,7 +367,7 @@ static void state_r_disconnect(struct iriap_cb *self, IRIAP_EVENT event,
+ case IAP_LM_CONNECT_INDICATION:
+ tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC);
+ if (tx_skb == NULL) {
+- IRDA_WARNING("%s: unable to malloc!\n", __FUNCTION__);
++ IRDA_WARNING("%s: unable to malloc!\n", __func__);
+ return;
+ }
+
+@@ -386,7 +386,7 @@ static void state_r_disconnect(struct iriap_cb *self, IRIAP_EVENT event,
+ iriap_next_r_connect_state(self, R_RECEIVING);
+ break;
+ default:
+- IRDA_DEBUG(0, "%s(), unknown event %d\n", __FUNCTION__, event);
++ IRDA_DEBUG(0, "%s(), unknown event %d\n", __func__, event);
+ break;
+ }
+ }
+@@ -397,7 +397,7 @@ static void state_r_disconnect(struct iriap_cb *self, IRIAP_EVENT event,
+ static void state_r_call(struct iriap_cb *self, IRIAP_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ switch (event) {
+ case IAP_LM_DISCONNECT_INDICATION:
+@@ -406,7 +406,7 @@ static void state_r_call(struct iriap_cb *self, IRIAP_EVENT event,
+ iriap_next_r_connect_state(self, R_WAITING);
+ break;
+ default:
+- IRDA_DEBUG(0, "%s(), unknown event!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), unknown event!\n", __func__);
+ break;
+ }
+ }
+@@ -421,13 +421,13 @@ static void state_r_call(struct iriap_cb *self, IRIAP_EVENT event,
+ static void state_r_waiting(struct iriap_cb *self, IRIAP_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(0, "%s(), Not implemented\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), Not implemented\n", __func__);
+ }
+
+ static void state_r_wait_active(struct iriap_cb *self, IRIAP_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(0, "%s(), Not implemented\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), Not implemented\n", __func__);
+ }
+
+ /*
+@@ -439,7 +439,7 @@ static void state_r_wait_active(struct iriap_cb *self, IRIAP_EVENT event,
+ static void state_r_receiving(struct iriap_cb *self, IRIAP_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ switch (event) {
+ case IAP_RECV_F_LST:
+@@ -448,7 +448,7 @@ static void state_r_receiving(struct iriap_cb *self, IRIAP_EVENT event,
+ iriap_call_indication(self, skb);
+ break;
+ default:
+- IRDA_DEBUG(0, "%s(), unknown event!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), unknown event!\n", __func__);
+ break;
+ }
+ }
+@@ -462,7 +462,7 @@ static void state_r_receiving(struct iriap_cb *self, IRIAP_EVENT event,
+ static void state_r_execute(struct iriap_cb *self, IRIAP_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+@@ -483,7 +483,7 @@ static void state_r_execute(struct iriap_cb *self, IRIAP_EVENT event,
+ irlmp_data_request(self->lsap, skb);
+ break;
+ default:
+- IRDA_DEBUG(0, "%s(), unknown event!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), unknown event!\n", __func__);
+ break;
+ }
+ }
+@@ -491,7 +491,7 @@ static void state_r_execute(struct iriap_cb *self, IRIAP_EVENT event,
+ static void state_r_returning(struct iriap_cb *self, IRIAP_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(0, "%s(), event=%d\n", __FUNCTION__, event);
++ IRDA_DEBUG(0, "%s(), event=%d\n", __func__, event);
+
+ switch (event) {
+ case IAP_RECV_F_LST:
+diff --git a/net/irda/irias_object.c b/net/irda/irias_object.c
+index cbcf043..99ebb96 100644
+--- a/net/irda/irias_object.c
++++ b/net/irda/irias_object.c
+@@ -47,12 +47,12 @@ struct ias_object *irias_new_object( char *name, int id)
+ {
+ struct ias_object *obj;
+
+- IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG( 4, "%s()\n", __func__);
+
+ obj = kzalloc(sizeof(struct ias_object), GFP_ATOMIC);
+ if (obj == NULL) {
+ IRDA_WARNING("%s(), Unable to allocate object!\n",
+- __FUNCTION__);
++ __func__);
+ return NULL;
+ }
+
+@@ -60,7 +60,7 @@ struct ias_object *irias_new_object( char *name, int id)
+ obj->name = kstrndup(name, IAS_MAX_CLASSNAME, GFP_ATOMIC);
+ if (!obj->name) {
+ IRDA_WARNING("%s(), Unable to allocate name!\n",
+- __FUNCTION__);
++ __func__);
+ kfree(obj);
+ return NULL;
+ }
+@@ -73,7 +73,7 @@ struct ias_object *irias_new_object( char *name, int id)
+
+ if (obj->attribs == NULL) {
+ IRDA_WARNING("%s(), Unable to allocate attribs!\n",
+- __FUNCTION__);
++ __func__);
+ kfree(obj->name);
+ kfree(obj);
+ return NULL;
+@@ -134,7 +134,7 @@ int irias_delete_object(struct ias_object *obj)
+ node = hashbin_remove_this(irias_objects, (irda_queue_t *) obj);
+ if (!node)
+ IRDA_DEBUG( 0, "%s(), object already removed!\n",
+- __FUNCTION__);
++ __func__);
+
+ /* Destroy */
+ __irias_delete_object(obj);
+@@ -268,7 +268,7 @@ int irias_object_change_attribute(char *obj_name, char *attrib_name,
+ /* Find object */
+ obj = hashbin_lock_find(irias_objects, 0, obj_name);
+ if (obj == NULL) {
+- IRDA_WARNING("%s: Unable to find object: %s\n", __FUNCTION__,
++ IRDA_WARNING("%s: Unable to find object: %s\n", __func__,
+ obj_name);
+ return -1;
+ }
+@@ -280,14 +280,14 @@ int irias_object_change_attribute(char *obj_name, char *attrib_name,
+ attrib = hashbin_find(obj->attribs, 0, attrib_name);
+ if (attrib == NULL) {
+ IRDA_WARNING("%s: Unable to find attribute: %s\n",
+- __FUNCTION__, attrib_name);
++ __func__, attrib_name);
+ spin_unlock_irqrestore(&obj->attribs->hb_spinlock, flags);
+ return -1;
+ }
+
+ if ( attrib->value->type != new_value->type) {
+ IRDA_DEBUG( 0, "%s(), changing value type not allowed!\n",
+- __FUNCTION__);
++ __func__);
+ spin_unlock_irqrestore(&obj->attribs->hb_spinlock, flags);
+ return -1;
+ }
+@@ -322,7 +322,7 @@ void irias_add_integer_attrib(struct ias_object *obj, char *name, int value,
+ attrib = kzalloc(sizeof(struct ias_attrib), GFP_ATOMIC);
+ if (attrib == NULL) {
+ IRDA_WARNING("%s: Unable to allocate attribute!\n",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+
+@@ -333,7 +333,7 @@ void irias_add_integer_attrib(struct ias_object *obj, char *name, int value,
+ attrib->value = irias_new_integer_value(value);
+ if (!attrib->name || !attrib->value) {
+ IRDA_WARNING("%s: Unable to allocate attribute!\n",
+- __FUNCTION__);
++ __func__);
+ if (attrib->value)
+ irias_delete_value(attrib->value);
+ kfree(attrib->name);
+@@ -366,7 +366,7 @@ void irias_add_octseq_attrib(struct ias_object *obj, char *name, __u8 *octets,
+ attrib = kzalloc(sizeof(struct ias_attrib), GFP_ATOMIC);
+ if (attrib == NULL) {
+ IRDA_WARNING("%s: Unable to allocate attribute!\n",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+
+@@ -376,7 +376,7 @@ void irias_add_octseq_attrib(struct ias_object *obj, char *name, __u8 *octets,
+ attrib->value = irias_new_octseq_value( octets, len);
+ if (!attrib->name || !attrib->value) {
+ IRDA_WARNING("%s: Unable to allocate attribute!\n",
+- __FUNCTION__);
++ __func__);
+ if (attrib->value)
+ irias_delete_value(attrib->value);
+ kfree(attrib->name);
+@@ -408,7 +408,7 @@ void irias_add_string_attrib(struct ias_object *obj, char *name, char *value,
+ attrib = kzalloc(sizeof( struct ias_attrib), GFP_ATOMIC);
+ if (attrib == NULL) {
+ IRDA_WARNING("%s: Unable to allocate attribute!\n",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+
+@@ -418,7 +418,7 @@ void irias_add_string_attrib(struct ias_object *obj, char *name, char *value,
+ attrib->value = irias_new_string_value(value);
+ if (!attrib->name || !attrib->value) {
+ IRDA_WARNING("%s: Unable to allocate attribute!\n",
+- __FUNCTION__);
++ __func__);
+ if (attrib->value)
+ irias_delete_value(attrib->value);
+ kfree(attrib->name);
+@@ -442,7 +442,7 @@ struct ias_value *irias_new_integer_value(int integer)
+
+ value = kzalloc(sizeof(struct ias_value), GFP_ATOMIC);
+ if (value == NULL) {
+- IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
++ IRDA_WARNING("%s: Unable to kmalloc!\n", __func__);
+ return NULL;
+ }
+
+@@ -467,7 +467,7 @@ struct ias_value *irias_new_string_value(char *string)
+
+ value = kzalloc(sizeof(struct ias_value), GFP_ATOMIC);
+ if (value == NULL) {
+- IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
++ IRDA_WARNING("%s: Unable to kmalloc!\n", __func__);
+ return NULL;
+ }
+
+@@ -475,7 +475,7 @@ struct ias_value *irias_new_string_value(char *string)
+ value->charset = CS_ASCII;
+ value->t.string = kstrndup(string, IAS_MAX_STRING, GFP_ATOMIC);
+ if (!value->t.string) {
+- IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
++ IRDA_WARNING("%s: Unable to kmalloc!\n", __func__);
+ kfree(value);
+ return NULL;
+ }
+@@ -498,7 +498,7 @@ struct ias_value *irias_new_octseq_value(__u8 *octseq , int len)
+
+ value = kzalloc(sizeof(struct ias_value), GFP_ATOMIC);
+ if (value == NULL) {
+- IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
++ IRDA_WARNING("%s: Unable to kmalloc!\n", __func__);
+ return NULL;
+ }
+
+@@ -510,7 +510,7 @@ struct ias_value *irias_new_octseq_value(__u8 *octseq , int len)
+
+ value->t.oct_seq = kmemdup(octseq, len, GFP_ATOMIC);
+ if (value->t.oct_seq == NULL){
+- IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
++ IRDA_WARNING("%s: Unable to kmalloc!\n", __func__);
+ kfree(value);
+ return NULL;
+ }
+@@ -523,7 +523,7 @@ struct ias_value *irias_new_missing_value(void)
+
+ value = kzalloc(sizeof(struct ias_value), GFP_ATOMIC);
+ if (value == NULL) {
+- IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
++ IRDA_WARNING("%s: Unable to kmalloc!\n", __func__);
+ return NULL;
+ }
+
+@@ -540,7 +540,7 @@ struct ias_value *irias_new_missing_value(void)
+ */
+ void irias_delete_value(struct ias_value *value)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(value != NULL, return;);
+
+@@ -558,7 +558,7 @@ void irias_delete_value(struct ias_value *value)
+ kfree(value->t.oct_seq);
+ break;
+ default:
+- IRDA_DEBUG(0, "%s(), Unknown value type!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), Unknown value type!\n", __func__);
+ break;
+ }
+ kfree(value);
+diff --git a/net/irda/irlan/irlan_client.c b/net/irda/irlan/irlan_client.c
+index fff52d5..6be1ec2 100644
+--- a/net/irda/irlan/irlan_client.c
++++ b/net/irda/irlan/irlan_client.c
+@@ -72,7 +72,7 @@ static void irlan_client_kick_timer_expired(void *data)
+ {
+ struct irlan_cb *self = (struct irlan_cb *) data;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -91,7 +91,7 @@ static void irlan_client_kick_timer_expired(void *data)
+
+ static void irlan_client_start_kick_timer(struct irlan_cb *self, int timeout)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ irda_start_timer(&self->client.kick_timer, timeout, (void *) self,
+ irlan_client_kick_timer_expired);
+@@ -105,7 +105,7 @@ static void irlan_client_start_kick_timer(struct irlan_cb *self, int timeout)
+ */
+ void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr)
+ {
+- IRDA_DEBUG(1, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(1, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -117,7 +117,7 @@ void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr)
+ if ((self->client.state != IRLAN_IDLE) ||
+ (self->provider.access_type == ACCESS_DIRECT))
+ {
+- IRDA_DEBUG(0, "%s(), already awake!\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s(), already awake!\n", __func__ );
+ return;
+ }
+
+@@ -126,7 +126,7 @@ void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr)
+ self->daddr = daddr;
+
+ if (self->disconnect_reason == LM_USER_REQUEST) {
+- IRDA_DEBUG(0, "%s(), still stopped by user\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s(), still stopped by user\n", __func__ );
+ return;
+ }
+
+@@ -153,7 +153,7 @@ void irlan_client_discovery_indication(discinfo_t *discovery,
+ struct irlan_cb *self;
+ __u32 saddr, daddr;
+
+- IRDA_DEBUG(1, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(1, "%s()\n", __func__ );
+
+ IRDA_ASSERT(discovery != NULL, return;);
+
+@@ -175,7 +175,7 @@ void irlan_client_discovery_indication(discinfo_t *discovery,
+ if (self) {
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, goto out;);
+
+- IRDA_DEBUG(1, "%s(), Found instance (%08x)!\n", __FUNCTION__ ,
++ IRDA_DEBUG(1, "%s(), Found instance (%08x)!\n", __func__ ,
+ daddr);
+
+ irlan_client_wakeup(self, saddr, daddr);
+@@ -195,7 +195,7 @@ static int irlan_client_ctrl_data_indication(void *instance, void *sap,
+ {
+ struct irlan_cb *self;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ self = (struct irlan_cb *) instance;
+
+@@ -206,7 +206,7 @@ static int irlan_client_ctrl_data_indication(void *instance, void *sap,
+ irlan_do_client_event(self, IRLAN_DATA_INDICATION, skb);
+
+ /* Ready for a new command */
+- IRDA_DEBUG(2, "%s(), clearing tx_busy\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), clearing tx_busy\n", __func__ );
+ self->client.tx_busy = FALSE;
+
+ /* Check if we have some queued commands waiting to be sent */
+@@ -223,7 +223,7 @@ static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap,
+ struct tsap_cb *tsap;
+ struct sk_buff *skb;
+
+- IRDA_DEBUG(4, "%s(), reason=%d\n", __FUNCTION__ , reason);
++ IRDA_DEBUG(4, "%s(), reason=%d\n", __func__ , reason);
+
+ self = (struct irlan_cb *) instance;
+ tsap = (struct tsap_cb *) sap;
+@@ -255,7 +255,7 @@ static void irlan_client_open_ctrl_tsap(struct irlan_cb *self)
+ struct tsap_cb *tsap;
+ notify_t notify;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -275,7 +275,7 @@ static void irlan_client_open_ctrl_tsap(struct irlan_cb *self)
+
+ tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, ¬ify);
+ if (!tsap) {
+- IRDA_DEBUG(2, "%s(), Got no tsap!\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), Got no tsap!\n", __func__ );
+ return;
+ }
+ self->client.tsap_ctrl = tsap;
+@@ -295,7 +295,7 @@ static void irlan_client_ctrl_connect_confirm(void *instance, void *sap,
+ {
+ struct irlan_cb *self;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ self = (struct irlan_cb *) instance;
+
+@@ -374,13 +374,13 @@ void irlan_client_parse_response(struct irlan_cb *self, struct sk_buff *skb)
+
+ IRDA_ASSERT(skb != NULL, return;);
+
+- IRDA_DEBUG(4, "%s() skb->len=%d\n", __FUNCTION__ , (int) skb->len);
++ IRDA_DEBUG(4, "%s() skb->len=%d\n", __func__ , (int) skb->len);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+ if (!skb) {
+- IRDA_ERROR("%s(), Got NULL skb!\n", __FUNCTION__);
++ IRDA_ERROR("%s(), Got NULL skb!\n", __func__);
+ return;
+ }
+ frame = skb->data;
+@@ -405,7 +405,7 @@ void irlan_client_parse_response(struct irlan_cb *self, struct sk_buff *skb)
+ /* How many parameters? */
+ count = frame[1];
+
+- IRDA_DEBUG(4, "%s(), got %d parameters\n", __FUNCTION__ , count);
++ IRDA_DEBUG(4, "%s(), got %d parameters\n", __func__ , count);
+
+ ptr = frame+2;
+
+@@ -413,7 +413,7 @@ void irlan_client_parse_response(struct irlan_cb *self, struct sk_buff *skb)
+ for (i=0; i<count;i++) {
+ ret = irlan_extract_param(ptr, name, value, &val_len);
+ if (ret < 0) {
+- IRDA_DEBUG(2, "%s(), IrLAN, Error!\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), IrLAN, Error!\n", __func__ );
+ break;
+ }
+ ptr += ret;
+@@ -438,7 +438,7 @@ static void irlan_check_response_param(struct irlan_cb *self, char *param,
+ int i;
+ DECLARE_MAC_BUF(mac);
+
+- IRDA_DEBUG(4, "%s(), parm=%s\n", __FUNCTION__ , param);
++ IRDA_DEBUG(4, "%s(), parm=%s\n", __func__ , param);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -476,7 +476,7 @@ static void irlan_check_response_param(struct irlan_cb *self, char *param,
+ else if (strcmp(value, "HOSTED") == 0)
+ self->client.access_type = ACCESS_HOSTED;
+ else {
+- IRDA_DEBUG(2, "%s(), unknown access type!\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), unknown access type!\n", __func__ );
+ }
+ }
+ /* IRLAN version */
+@@ -498,14 +498,14 @@ static void irlan_check_response_param(struct irlan_cb *self, char *param,
+ memcpy(&tmp_cpu, value, 2); /* Align value */
+ le16_to_cpus(&tmp_cpu); /* Convert to host order */
+ self->client.recv_arb_val = tmp_cpu;
+- IRDA_DEBUG(2, "%s(), receive arb val=%d\n", __FUNCTION__ ,
++ IRDA_DEBUG(2, "%s(), receive arb val=%d\n", __func__ ,
+ self->client.recv_arb_val);
+ }
+ if (strcmp(param, "MAX_FRAME") == 0) {
+ memcpy(&tmp_cpu, value, 2); /* Align value */
+ le16_to_cpus(&tmp_cpu); /* Convert to host order */
+ self->client.max_frame = tmp_cpu;
+- IRDA_DEBUG(4, "%s(), max frame=%d\n", __FUNCTION__ ,
++ IRDA_DEBUG(4, "%s(), max frame=%d\n", __func__ ,
+ self->client.max_frame);
+ }
+
+@@ -539,7 +539,7 @@ void irlan_client_get_value_confirm(int result, __u16 obj_id,
+ {
+ struct irlan_cb *self;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(priv != NULL, return;);
+
+@@ -552,7 +552,7 @@ void irlan_client_get_value_confirm(int result, __u16 obj_id,
+
+ /* Check if request succeeded */
+ if (result != IAS_SUCCESS) {
+- IRDA_DEBUG(2, "%s(), got NULL value!\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), got NULL value!\n", __func__ );
+ irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL,
+ NULL);
+ return;
+@@ -570,7 +570,7 @@ void irlan_client_get_value_confirm(int result, __u16 obj_id,
+ irias_delete_value(value);
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), unknown type!\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), unknown type!\n", __func__ );
+ break;
+ }
+ irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL, NULL);
+diff --git a/net/irda/irlan/irlan_client_event.c b/net/irda/irlan/irlan_client_event.c
+index 6afcee5..8d5a8eb 100644
+--- a/net/irda/irlan/irlan_client_event.c
++++ b/net/irda/irlan/irlan_client_event.c
+@@ -92,7 +92,7 @@ void irlan_do_client_event(struct irlan_cb *self, IRLAN_EVENT event,
+ static int irlan_client_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+@@ -101,7 +101,7 @@ static int irlan_client_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
+ case IRLAN_DISCOVERY_INDICATION:
+ if (self->client.iriap) {
+ IRDA_WARNING("%s(), busy with a previous query\n",
+- __FUNCTION__);
++ __func__);
+ return -EBUSY;
+ }
+
+@@ -114,10 +114,10 @@ static int irlan_client_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
+ "IrLAN", "IrDA:TinyTP:LsapSel");
+ break;
+ case IRLAN_WATCHDOG_TIMEOUT:
+- IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
+ break;
+ default:
+- IRDA_DEBUG(4, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++ IRDA_DEBUG(4, "%s(), Unknown event %d\n", __func__ , event);
+ break;
+ }
+ if (skb)
+@@ -136,7 +136,7 @@ static int irlan_client_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
+ static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+@@ -154,7 +154,7 @@ static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event,
+ irlan_next_client_state(self, IRLAN_CONN);
+ break;
+ case IRLAN_IAS_PROVIDER_NOT_AVAIL:
+- IRDA_DEBUG(2, "%s(), IAS_PROVIDER_NOT_AVAIL\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), IAS_PROVIDER_NOT_AVAIL\n", __func__ );
+ irlan_next_client_state(self, IRLAN_IDLE);
+
+ /* Give the client a kick! */
+@@ -167,10 +167,10 @@ static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event,
+ irlan_next_client_state(self, IRLAN_IDLE);
+ break;
+ case IRLAN_WATCHDOG_TIMEOUT:
+- IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++ IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
+ break;
+ }
+ if (skb)
+@@ -189,7 +189,7 @@ static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event,
+ static int irlan_client_state_conn(struct irlan_cb *self, IRLAN_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -1;);
+
+@@ -204,10 +204,10 @@ static int irlan_client_state_conn(struct irlan_cb *self, IRLAN_EVENT event,
+ irlan_next_client_state(self, IRLAN_IDLE);
+ break;
+ case IRLAN_WATCHDOG_TIMEOUT:
+- IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++ IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
+ break;
+ }
+ if (skb)
+@@ -224,7 +224,7 @@ static int irlan_client_state_conn(struct irlan_cb *self, IRLAN_EVENT event,
+ static int irlan_client_state_info(struct irlan_cb *self, IRLAN_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -1;);
+
+@@ -244,10 +244,10 @@ static int irlan_client_state_info(struct irlan_cb *self, IRLAN_EVENT event,
+ irlan_next_client_state(self, IRLAN_IDLE);
+ break;
+ case IRLAN_WATCHDOG_TIMEOUT:
+- IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++ IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
+ break;
+ }
+ if (skb)
+@@ -266,7 +266,7 @@ static int irlan_client_state_info(struct irlan_cb *self, IRLAN_EVENT event,
+ static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -1;);
+
+@@ -281,10 +281,10 @@ static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event,
+ irlan_next_client_state(self, IRLAN_IDLE);
+ break;
+ case IRLAN_WATCHDOG_TIMEOUT:
+- IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++ IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
+ break;
+ }
+ if (skb)
+@@ -305,7 +305,7 @@ static int irlan_client_state_open(struct irlan_cb *self, IRLAN_EVENT event,
+ {
+ struct qos_info qos;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -1;);
+
+@@ -344,7 +344,7 @@ static int irlan_client_state_open(struct irlan_cb *self, IRLAN_EVENT event,
+ irlan_next_client_state(self, IRLAN_DATA);
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), unknown access type!\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), unknown access type!\n", __func__ );
+ break;
+ }
+ break;
+@@ -353,10 +353,10 @@ static int irlan_client_state_open(struct irlan_cb *self, IRLAN_EVENT event,
+ irlan_next_client_state(self, IRLAN_IDLE);
+ break;
+ case IRLAN_WATCHDOG_TIMEOUT:
+- IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++ IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
+ break;
+ }
+
+@@ -376,7 +376,7 @@ static int irlan_client_state_open(struct irlan_cb *self, IRLAN_EVENT event,
+ static int irlan_client_state_wait(struct irlan_cb *self, IRLAN_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -1;);
+
+@@ -390,10 +390,10 @@ static int irlan_client_state_wait(struct irlan_cb *self, IRLAN_EVENT event,
+ irlan_next_client_state(self, IRLAN_IDLE);
+ break;
+ case IRLAN_WATCHDOG_TIMEOUT:
+- IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++ IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
+ break;
+ }
+ if (skb)
+@@ -407,7 +407,7 @@ static int irlan_client_state_arb(struct irlan_cb *self, IRLAN_EVENT event,
+ {
+ struct qos_info qos;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -1;);
+
+@@ -429,7 +429,7 @@ static int irlan_client_state_arb(struct irlan_cb *self, IRLAN_EVENT event,
+ } else if (self->client.recv_arb_val >
+ self->provider.send_arb_val)
+ {
+- IRDA_DEBUG(2, "%s(), lost the battle :-(\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), lost the battle :-(\n", __func__ );
+ }
+ break;
+ case IRLAN_DATA_CONNECT_INDICATION:
+@@ -440,10 +440,10 @@ static int irlan_client_state_arb(struct irlan_cb *self, IRLAN_EVENT event,
+ irlan_next_client_state(self, IRLAN_IDLE);
+ break;
+ case IRLAN_WATCHDOG_TIMEOUT:
+- IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++ IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
+ break;
+ }
+ if (skb)
+@@ -462,7 +462,7 @@ static int irlan_client_state_arb(struct irlan_cb *self, IRLAN_EVENT event,
+ static int irlan_client_state_data(struct irlan_cb *self, IRLAN_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+@@ -476,7 +476,7 @@ static int irlan_client_state_data(struct irlan_cb *self, IRLAN_EVENT event,
+ irlan_next_client_state(self, IRLAN_IDLE);
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++ IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
+ break;
+ }
+ if (skb)
+@@ -494,7 +494,7 @@ static int irlan_client_state_data(struct irlan_cb *self, IRLAN_EVENT event,
+ static int irlan_client_state_close(struct irlan_cb *self, IRLAN_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ if (skb)
+ dev_kfree_skb(skb);
+@@ -511,7 +511,7 @@ static int irlan_client_state_close(struct irlan_cb *self, IRLAN_EVENT event,
+ static int irlan_client_state_sync(struct irlan_cb *self, IRLAN_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ if (skb)
+ dev_kfree_skb(skb);
+diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c
+index 1eb4bbc..9a1cd87 100644
+--- a/net/irda/irlan/irlan_common.c
++++ b/net/irda/irlan/irlan_common.c
+@@ -54,13 +54,6 @@
+ #include <net/irda/irlan_filter.h>
+
+
+-/*
+- * Send gratuitous ARP when connected to a new AP or not. May be a clever
+- * thing to do, but for some reason the machine crashes if you use DHCP. So
+- * lets not use it by default.
+- */
+-#undef CONFIG_IRLAN_SEND_GRATUITOUS_ARP
+-
+ /* extern char sysctl_devname[]; */
+
+ /*
+@@ -124,7 +117,7 @@ static int __init irlan_init(void)
+ struct irlan_cb *new;
+ __u16 hints;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ #ifdef CONFIG_PROC_FS
+ { struct proc_dir_entry *proc;
+@@ -136,7 +129,7 @@ static int __init irlan_init(void)
+ }
+ #endif /* CONFIG_PROC_FS */
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+ hints = irlmp_service_to_hint(S_LAN);
+
+ /* Register with IrLMP as a client */
+@@ -179,7 +172,7 @@ static void __exit irlan_cleanup(void)
+ {
+ struct irlan_cb *self, *next;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ irlmp_unregister_client(ckey);
+ irlmp_unregister_service(skey);
+@@ -207,7 +200,7 @@ static struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr)
+ struct net_device *dev;
+ struct irlan_cb *self;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ /* Create network device with irlan */
+ dev = alloc_irlandev(eth ? "eth%d" : "irlan%d");
+@@ -252,7 +245,7 @@ static struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr)
+
+ if (register_netdev(dev)) {
+ IRDA_DEBUG(2, "%s(), register_netdev() failed!\n",
+- __FUNCTION__ );
++ __func__ );
+ self = NULL;
+ free_netdev(dev);
+ } else {
+@@ -272,7 +265,7 @@ static struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr)
+ */
+ static void __irlan_close(struct irlan_cb *self)
+ {
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ ASSERT_RTNL();
+ IRDA_ASSERT(self != NULL, return;);
+@@ -320,7 +313,7 @@ static void irlan_connect_indication(void *instance, void *sap,
+ struct irlan_cb *self;
+ struct tsap_cb *tsap;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ self = (struct irlan_cb *) instance;
+ tsap = (struct tsap_cb *) sap;
+@@ -332,7 +325,7 @@ static void irlan_connect_indication(void *instance, void *sap,
+ self->max_sdu_size = max_sdu_size;
+ self->max_header_size = max_header_size;
+
+- IRDA_DEBUG(0, "%s: We are now connected!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s: We are now connected!\n", __func__);
+
+ del_timer(&self->watchdog_timer);
+
+@@ -376,7 +369,7 @@ static void irlan_connect_confirm(void *instance, void *sap,
+
+ /* TODO: we could set the MTU depending on the max_sdu_size */
+
+- IRDA_DEBUG(0, "%s: We are now connected!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s: We are now connected!\n", __func__);
+ del_timer(&self->watchdog_timer);
+
+ /*
+@@ -393,9 +386,6 @@ static void irlan_connect_confirm(void *instance, void *sap,
+ /* Ready to transfer Ethernet frames */
+ netif_start_queue(self->dev);
+ self->disconnect_reason = 0; /* Clear reason */
+-#ifdef CONFIG_IRLAN_SEND_GRATUITOUS_ARP
+- irlan_eth_send_gratuitous_arp(&self->dev);
+-#endif
+ wake_up_interruptible(&self->open_wait);
+ }
+
+@@ -412,7 +402,7 @@ static void irlan_disconnect_indication(void *instance,
+ struct irlan_cb *self;
+ struct tsap_cb *tsap;
+
+- IRDA_DEBUG(0, "%s(), reason=%d\n", __FUNCTION__ , reason);
++ IRDA_DEBUG(0, "%s(), reason=%d\n", __func__ , reason);
+
+ self = (struct irlan_cb *) instance;
+ tsap = (struct tsap_cb *) sap;
+@@ -431,22 +421,22 @@ static void irlan_disconnect_indication(void *instance,
+
+ switch (reason) {
+ case LM_USER_REQUEST: /* User request */
+- IRDA_DEBUG(2, "%s(), User requested\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), User requested\n", __func__ );
+ break;
+ case LM_LAP_DISCONNECT: /* Unexpected IrLAP disconnect */
+- IRDA_DEBUG(2, "%s(), Unexpected IrLAP disconnect\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), Unexpected IrLAP disconnect\n", __func__ );
+ break;
+ case LM_CONNECT_FAILURE: /* Failed to establish IrLAP connection */
+- IRDA_DEBUG(2, "%s(), IrLAP connect failed\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), IrLAP connect failed\n", __func__ );
+ break;
+ case LM_LAP_RESET: /* IrLAP reset */
+- IRDA_DEBUG(2, "%s(), IrLAP reset\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), IrLAP reset\n", __func__ );
+ break;
+ case LM_INIT_DISCONNECT:
+- IRDA_DEBUG(2, "%s(), IrLMP connect failed\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), IrLMP connect failed\n", __func__ );
+ break;
+ default:
+- IRDA_ERROR("%s(), Unknown disconnect reason\n", __FUNCTION__);
++ IRDA_ERROR("%s(), Unknown disconnect reason\n", __func__);
+ break;
+ }
+
+@@ -468,7 +458,7 @@ void irlan_open_data_tsap(struct irlan_cb *self)
+ struct tsap_cb *tsap;
+ notify_t notify;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -490,7 +480,7 @@ void irlan_open_data_tsap(struct irlan_cb *self)
+
+ tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, ¬ify);
+ if (!tsap) {
+- IRDA_DEBUG(2, "%s(), Got no tsap!\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), Got no tsap!\n", __func__ );
+ return;
+ }
+ self->tsap_data = tsap;
+@@ -504,7 +494,7 @@ void irlan_open_data_tsap(struct irlan_cb *self)
+
+ void irlan_close_tsaps(struct irlan_cb *self)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -594,7 +584,7 @@ int irlan_run_ctrl_tx_queue(struct irlan_cb *self)
+ {
+ struct sk_buff *skb;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ if (irda_lock(&self->client.tx_busy) == FALSE)
+ return -EBUSY;
+@@ -613,7 +603,7 @@ int irlan_run_ctrl_tx_queue(struct irlan_cb *self)
+ dev_kfree_skb(skb);
+ return -1;
+ }
+- IRDA_DEBUG(2, "%s(), sending ...\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), sending ...\n", __func__ );
+
+ return irttp_data_request(self->client.tsap_ctrl, skb);
+ }
+@@ -626,7 +616,7 @@ int irlan_run_ctrl_tx_queue(struct irlan_cb *self)
+ */
+ static void irlan_ctrl_data_request(struct irlan_cb *self, struct sk_buff *skb)
+ {
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ /* Queue command */
+ skb_queue_tail(&self->client.txq, skb);
+@@ -646,7 +636,7 @@ void irlan_get_provider_info(struct irlan_cb *self)
+ struct sk_buff *skb;
+ __u8 *frame;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -679,7 +669,7 @@ void irlan_open_data_channel(struct irlan_cb *self)
+ struct sk_buff *skb;
+ __u8 *frame;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -714,7 +704,7 @@ void irlan_close_data_channel(struct irlan_cb *self)
+ struct sk_buff *skb;
+ __u8 *frame;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -755,7 +745,7 @@ static void irlan_open_unicast_addr(struct irlan_cb *self)
+ struct sk_buff *skb;
+ __u8 *frame;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -797,7 +787,7 @@ void irlan_set_broadcast_filter(struct irlan_cb *self, int status)
+ struct sk_buff *skb;
+ __u8 *frame;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -841,7 +831,7 @@ void irlan_set_multicast_filter(struct irlan_cb *self, int status)
+ struct sk_buff *skb;
+ __u8 *frame;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -886,7 +876,7 @@ static void irlan_get_unicast_addr(struct irlan_cb *self)
+ struct sk_buff *skb;
+ __u8 *frame;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -926,7 +916,7 @@ void irlan_get_media_char(struct irlan_cb *self)
+ struct sk_buff *skb;
+ __u8 *frame;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -1014,7 +1004,7 @@ static int __irlan_insert_param(struct sk_buff *skb, char *param, int type,
+ int n=0;
+
+ if (skb == NULL) {
+- IRDA_DEBUG(2, "%s(), Got NULL skb\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), Got NULL skb\n", __func__ );
+ return 0;
+ }
+
+@@ -1031,7 +1021,7 @@ static int __irlan_insert_param(struct sk_buff *skb, char *param, int type,
+ IRDA_ASSERT(value_len > 0, return 0;);
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), Unknown parameter type!\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), Unknown parameter type!\n", __func__ );
+ return 0;
+ break;
+ }
+@@ -1041,7 +1031,7 @@ static int __irlan_insert_param(struct sk_buff *skb, char *param, int type,
+
+ /* Make space for data */
+ if (skb_tailroom(skb) < (param_len+value_len+3)) {
+- IRDA_DEBUG(2, "%s(), No more space at end of skb\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), No more space at end of skb\n", __func__ );
+ return 0;
+ }
+ skb_put(skb, param_len+value_len+3);
+@@ -1088,13 +1078,13 @@ int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len)
+ __u16 val_len;
+ int n=0;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ /* get length of parameter name (1 byte) */
+ name_len = buf[n++];
+
+ if (name_len > 254) {
+- IRDA_DEBUG(2, "%s(), name_len > 254\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), name_len > 254\n", __func__ );
+ return -RSP_INVALID_COMMAND_FORMAT;
+ }
+
+@@ -1111,7 +1101,7 @@ int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len)
+ le16_to_cpus(&val_len); n+=2;
+
+ if (val_len > 1016) {
+- IRDA_DEBUG(2, "%s(), parameter length to long\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), parameter length to long\n", __func__ );
+ return -RSP_INVALID_COMMAND_FORMAT;
+ }
+ *len = val_len;
+diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c
+index 1ab91f7..05112be 100644
+--- a/net/irda/irlan/irlan_eth.c
++++ b/net/irda/irlan/irlan_eth.c
+@@ -103,7 +103,7 @@ static int irlan_eth_open(struct net_device *dev)
+ {
+ struct irlan_cb *self = netdev_priv(dev);
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ /* Ready to play! */
+ netif_stop_queue(dev); /* Wait until data link is ready */
+@@ -130,7 +130,7 @@ static int irlan_eth_close(struct net_device *dev)
+ {
+ struct irlan_cb *self = netdev_priv(dev);
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ /* Stop device */
+ netif_stop_queue(dev);
+@@ -221,7 +221,7 @@ int irlan_eth_receive(void *instance, void *sap, struct sk_buff *skb)
+ }
+ if (skb->len < ETH_HLEN) {
+ IRDA_DEBUG(0, "%s() : IrLAN frame too short (%d)\n",
+- __FUNCTION__, skb->len);
++ __func__, skb->len);
+ ++self->stats.rx_dropped;
+ dev_kfree_skb(skb);
+ return 0;
+@@ -270,7 +270,7 @@ void irlan_eth_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
+
+ IRDA_ASSERT(dev != NULL, return;);
+
+- IRDA_DEBUG(0, "%s() : flow %s ; running %d\n", __FUNCTION__,
++ IRDA_DEBUG(0, "%s() : flow %s ; running %d\n", __func__,
+ flow == FLOW_STOP ? "FLOW_STOP" : "FLOW_START",
+ netif_running(dev));
+
+@@ -289,39 +289,6 @@ void irlan_eth_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
+ }
+
+ /*
+- * Function irlan_etc_send_gratuitous_arp (dev)
+- *
+- * Send gratuitous ARP to announce that we have changed
+- * hardware address, so that all peers updates their ARP tables
+- */
+-void irlan_eth_send_gratuitous_arp(struct net_device *dev)
+-{
+-#ifdef CONFIG_INET
+- struct in_device *in_dev;
+-
+- /*
+- * When we get a new MAC address do a gratuitous ARP. This
+- * is useful if we have changed access points on the same
+- * subnet.
+- */
+- IRDA_DEBUG(4, "IrLAN: Sending gratuitous ARP\n");
+- rcu_read_lock();
+- in_dev = __in_dev_get_rcu(dev);
+- if (in_dev == NULL)
+- goto out;
+- if (in_dev->ifa_list)
+-
+- arp_send(ARPOP_REQUEST, ETH_P_ARP,
+- in_dev->ifa_list->ifa_address,
+- dev,
+- in_dev->ifa_list->ifa_address,
+- NULL, dev->dev_addr, NULL);
+-out:
+- rcu_read_unlock();
+-#endif /* CONFIG_INET */
+-}
+-
+-/*
+ * Function set_multicast_list (dev)
+ *
+ * Configure the filtering of the device
+@@ -332,11 +299,11 @@ static void irlan_eth_set_multicast_list(struct net_device *dev)
+ {
+ struct irlan_cb *self = netdev_priv(dev);
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s()\n", __func__ );
+
+ /* Check if data channel has been connected yet */
+ if (self->client.state != IRLAN_DATA) {
+- IRDA_DEBUG(1, "%s(), delaying!\n", __FUNCTION__ );
++ IRDA_DEBUG(1, "%s(), delaying!\n", __func__ );
+ return;
+ }
+
+@@ -346,20 +313,20 @@ static void irlan_eth_set_multicast_list(struct net_device *dev)
+ }
+ else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > HW_MAX_ADDRS) {
+ /* Disable promiscuous mode, use normal mode. */
+- IRDA_DEBUG(4, "%s(), Setting multicast filter\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s(), Setting multicast filter\n", __func__ );
+ /* hardware_set_filter(NULL); */
+
+ irlan_set_multicast_filter(self, TRUE);
+ }
+ else if (dev->mc_count) {
+- IRDA_DEBUG(4, "%s(), Setting multicast filter\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s(), Setting multicast filter\n", __func__ );
+ /* Walk the address list, and load the filter */
+ /* hardware_set_filter(dev->mc_list); */
+
+ irlan_set_multicast_filter(self, TRUE);
+ }
+ else {
+- IRDA_DEBUG(4, "%s(), Clearing multicast filter\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s(), Clearing multicast filter\n", __func__ );
+ irlan_set_multicast_filter(self, FALSE);
+ }
+
+diff --git a/net/irda/irlan/irlan_event.c b/net/irda/irlan/irlan_event.c
+index a9750a8..cbcb4eb 100644
+--- a/net/irda/irlan/irlan_event.c
++++ b/net/irda/irlan/irlan_event.c
+@@ -40,7 +40,7 @@ char *irlan_state[] = {
+
+ void irlan_next_client_state(struct irlan_cb *self, IRLAN_STATE state)
+ {
+- IRDA_DEBUG(2, "%s(), %s\n", __FUNCTION__ , irlan_state[state]);
++ IRDA_DEBUG(2, "%s(), %s\n", __func__ , irlan_state[state]);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -50,7 +50,7 @@ void irlan_next_client_state(struct irlan_cb *self, IRLAN_STATE state)
+
+ void irlan_next_provider_state(struct irlan_cb *self, IRLAN_STATE state)
+ {
+- IRDA_DEBUG(2, "%s(), %s\n", __FUNCTION__ , irlan_state[state]);
++ IRDA_DEBUG(2, "%s(), %s\n", __func__ , irlan_state[state]);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+diff --git a/net/irda/irlan/irlan_filter.c b/net/irda/irlan/irlan_filter.c
+index 4384be9..9ff7823 100644
+--- a/net/irda/irlan/irlan_filter.c
++++ b/net/irda/irlan/irlan_filter.c
+@@ -145,7 +145,7 @@ void irlan_check_command_param(struct irlan_cb *self, char *param, char *value)
+ {
+ __u8 *bytes;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ bytes = value;
+
+@@ -158,7 +158,7 @@ void irlan_check_command_param(struct irlan_cb *self, char *param, char *value)
+ * This is experimental!! DB.
+ */
+ if (strcmp(param, "MODE") == 0) {
+- IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s()\n", __func__ );
+ self->use_udata = TRUE;
+ return;
+ }
+diff --git a/net/irda/irlan/irlan_provider.c b/net/irda/irlan/irlan_provider.c
+index 13db942..3f81f81 100644
+--- a/net/irda/irlan/irlan_provider.c
++++ b/net/irda/irlan/irlan_provider.c
+@@ -70,7 +70,7 @@ static int irlan_provider_data_indication(void *instance, void *sap,
+ struct irlan_cb *self;
+ __u8 code;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ self = (struct irlan_cb *) instance;
+
+@@ -99,15 +99,15 @@ static int irlan_provider_data_indication(void *instance, void *sap,
+ irlan_do_provider_event(self, IRLAN_FILTER_CONFIG_CMD, skb);
+ break;
+ case CMD_RECONNECT_DATA_CHAN:
+- IRDA_DEBUG(2, "%s(), Got RECONNECT_DATA_CHAN command\n", __FUNCTION__ );
+- IRDA_DEBUG(2, "%s(), NOT IMPLEMENTED\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), Got RECONNECT_DATA_CHAN command\n", __func__ );
++ IRDA_DEBUG(2, "%s(), NOT IMPLEMENTED\n", __func__ );
+ break;
+ case CMD_CLOSE_DATA_CHAN:
+ IRDA_DEBUG(2, "Got CLOSE_DATA_CHAN command!\n");
+- IRDA_DEBUG(2, "%s(), NOT IMPLEMENTED\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), NOT IMPLEMENTED\n", __func__ );
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), Unknown command!\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), Unknown command!\n", __func__ );
+ break;
+ }
+ return 0;
+@@ -129,7 +129,7 @@ static void irlan_provider_connect_indication(void *instance, void *sap,
+ struct tsap_cb *tsap;
+ __u32 saddr, daddr;
+
+- IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(0, "%s()\n", __func__ );
+
+ self = (struct irlan_cb *) instance;
+ tsap = (struct tsap_cb *) sap;
+@@ -182,7 +182,7 @@ static void irlan_provider_disconnect_indication(void *instance, void *sap,
+ struct irlan_cb *self;
+ struct tsap_cb *tsap;
+
+- IRDA_DEBUG(4, "%s(), reason=%d\n", __FUNCTION__ , reason);
++ IRDA_DEBUG(4, "%s(), reason=%d\n", __func__ , reason);
+
+ self = (struct irlan_cb *) instance;
+ tsap = (struct tsap_cb *) sap;
+@@ -236,7 +236,7 @@ int irlan_provider_parse_command(struct irlan_cb *self, int cmd,
+
+ IRDA_ASSERT(skb != NULL, return -RSP_PROTOCOL_ERROR;);
+
+- IRDA_DEBUG(4, "%s(), skb->len=%d\n", __FUNCTION__ , (int)skb->len);
++ IRDA_DEBUG(4, "%s(), skb->len=%d\n", __func__ , (int)skb->len);
+
+ IRDA_ASSERT(self != NULL, return -RSP_PROTOCOL_ERROR;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -RSP_PROTOCOL_ERROR;);
+@@ -266,7 +266,7 @@ int irlan_provider_parse_command(struct irlan_cb *self, int cmd,
+ for (i=0; i<count;i++) {
+ ret = irlan_extract_param(ptr, name, value, &val_len);
+ if (ret < 0) {
+- IRDA_DEBUG(2, "%s(), IrLAN, Error!\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), IrLAN, Error!\n", __func__ );
+ break;
+ }
+ ptr+=ret;
+@@ -291,7 +291,7 @@ void irlan_provider_send_reply(struct irlan_cb *self, int command,
+ {
+ struct sk_buff *skb;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+@@ -323,7 +323,7 @@ void irlan_provider_send_reply(struct irlan_cb *self, int command,
+ irlan_insert_string_param(skb, "MEDIA", "802.5");
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), unknown media type!\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), unknown media type!\n", __func__ );
+ break;
+ }
+ irlan_insert_short_param(skb, "IRLAN_VER", 0x0101);
+@@ -347,7 +347,7 @@ void irlan_provider_send_reply(struct irlan_cb *self, int command,
+ irlan_insert_string_param(skb, "ACCESS_TYPE", "HOSTED");
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), Unknown access type\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), Unknown access type\n", __func__ );
+ break;
+ }
+ irlan_insert_short_param(skb, "MAX_FRAME", 0x05ee);
+@@ -367,7 +367,7 @@ void irlan_provider_send_reply(struct irlan_cb *self, int command,
+ irlan_filter_request(self, skb);
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), Unknown command!\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), Unknown command!\n", __func__ );
+ break;
+ }
+
+@@ -385,7 +385,7 @@ int irlan_provider_open_ctrl_tsap(struct irlan_cb *self)
+ struct tsap_cb *tsap;
+ notify_t notify;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+@@ -406,7 +406,7 @@ int irlan_provider_open_ctrl_tsap(struct irlan_cb *self)
+
+ tsap = irttp_open_tsap(LSAP_ANY, 1, ¬ify);
+ if (!tsap) {
+- IRDA_DEBUG(2, "%s(), Got no tsap!\n", __FUNCTION__ );
++ IRDA_DEBUG(2, "%s(), Got no tsap!\n", __func__ );
+ return -1;
+ }
+ self->provider.tsap_ctrl = tsap;
+diff --git a/net/irda/irlan/irlan_provider_event.c b/net/irda/irlan/irlan_provider_event.c
+index 10ece5a..01a9d7c 100644
+--- a/net/irda/irlan/irlan_provider_event.c
++++ b/net/irda/irlan/irlan_provider_event.c
+@@ -72,7 +72,7 @@ void irlan_do_provider_event(struct irlan_cb *self, IRLAN_EVENT event,
+ static int irlan_provider_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -1;);
+
+@@ -82,7 +82,7 @@ static int irlan_provider_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
+ irlan_next_provider_state( self, IRLAN_INFO);
+ break;
+ default:
+- IRDA_DEBUG(4, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++ IRDA_DEBUG(4, "%s(), Unknown event %d\n", __func__ , event);
+ break;
+ }
+ if (skb)
+@@ -101,7 +101,7 @@ static int irlan_provider_state_info(struct irlan_cb *self, IRLAN_EVENT event,
+ {
+ int ret;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -1;);
+
+@@ -147,7 +147,7 @@ static int irlan_provider_state_info(struct irlan_cb *self, IRLAN_EVENT event,
+ irlan_next_provider_state(self, IRLAN_IDLE);
+ break;
+ default:
+- IRDA_DEBUG( 0, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++ IRDA_DEBUG( 0, "%s(), Unknown event %d\n", __func__ , event);
+ break;
+ }
+ if (skb)
+@@ -166,7 +166,7 @@ static int irlan_provider_state_info(struct irlan_cb *self, IRLAN_EVENT event,
+ static int irlan_provider_state_open(struct irlan_cb *self, IRLAN_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -1;);
+
+@@ -186,7 +186,7 @@ static int irlan_provider_state_open(struct irlan_cb *self, IRLAN_EVENT event,
+ irlan_next_provider_state(self, IRLAN_IDLE);
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++ IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
+ break;
+ }
+ if (skb)
+@@ -205,7 +205,7 @@ static int irlan_provider_state_open(struct irlan_cb *self, IRLAN_EVENT event,
+ static int irlan_provider_state_data(struct irlan_cb *self, IRLAN_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
++ IRDA_DEBUG(4, "%s()\n", __func__ );
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+@@ -221,7 +221,7 @@ static int irlan_provider_state_data(struct irlan_cb *self, IRLAN_EVENT event,
+ irlan_next_provider_state(self, IRLAN_IDLE);
+ break;
+ default:
+- IRDA_DEBUG( 0, "%s(), Unknown event %d\n", __FUNCTION__ , event);
++ IRDA_DEBUG( 0, "%s(), Unknown event %d\n", __func__ , event);
+ break;
+ }
+ if (skb)
+diff --git a/net/irda/irlap.c b/net/irda/irlap.c
+index f3236ac..e4965b7 100644
+--- a/net/irda/irlap.c
++++ b/net/irda/irlap.c
+@@ -88,7 +88,7 @@ int __init irlap_init(void)
+ irlap = hashbin_new(HB_LOCK);
+ if (irlap == NULL) {
+ IRDA_ERROR("%s: can't allocate irlap hashbin!\n",
+- __FUNCTION__);
++ __func__);
+ return -ENOMEM;
+ }
+
+@@ -113,7 +113,7 @@ struct irlap_cb *irlap_open(struct net_device *dev, struct qos_info *qos,
+ {
+ struct irlap_cb *self;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ /* Initialize the irlap structure. */
+ self = kzalloc(sizeof(struct irlap_cb), GFP_KERNEL);
+@@ -215,7 +215,7 @@ void irlap_close(struct irlap_cb *self)
+ {
+ struct irlap_cb *lap;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -231,7 +231,7 @@ void irlap_close(struct irlap_cb *self)
+ /* Be sure that we manage to remove ourself from the hash */
+ lap = hashbin_remove(irlap, self->saddr, NULL);
+ if (!lap) {
+- IRDA_DEBUG(1, "%s(), Didn't find myself!\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), Didn't find myself!\n", __func__);
+ return;
+ }
+ __irlap_close(lap);
+@@ -246,7 +246,7 @@ EXPORT_SYMBOL(irlap_close);
+ */
+ void irlap_connect_indication(struct irlap_cb *self, struct sk_buff *skb)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -265,7 +265,7 @@ void irlap_connect_indication(struct irlap_cb *self, struct sk_buff *skb)
+ */
+ void irlap_connect_response(struct irlap_cb *self, struct sk_buff *userdata)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ irlap_do_event(self, CONNECT_RESPONSE, userdata, NULL);
+ }
+@@ -280,7 +280,7 @@ void irlap_connect_response(struct irlap_cb *self, struct sk_buff *userdata)
+ void irlap_connect_request(struct irlap_cb *self, __u32 daddr,
+ struct qos_info *qos_user, int sniff)
+ {
+- IRDA_DEBUG(3, "%s(), daddr=0x%08x\n", __FUNCTION__, daddr);
++ IRDA_DEBUG(3, "%s(), daddr=0x%08x\n", __func__, daddr);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -307,7 +307,7 @@ void irlap_connect_request(struct irlap_cb *self, __u32 daddr,
+ */
+ void irlap_connect_confirm(struct irlap_cb *self, struct sk_buff *skb)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -344,7 +344,7 @@ void irlap_data_request(struct irlap_cb *self, struct sk_buff *skb,
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+
+- IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(3, "%s()\n", __func__);
+
+ IRDA_ASSERT(skb_headroom(skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER),
+ return;);
+@@ -391,7 +391,7 @@ void irlap_unitdata_request(struct irlap_cb *self, struct sk_buff *skb)
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+
+- IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(3, "%s()\n", __func__);
+
+ IRDA_ASSERT(skb_headroom(skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER),
+ return;);
+@@ -417,7 +417,7 @@ void irlap_unitdata_request(struct irlap_cb *self, struct sk_buff *skb)
+ #ifdef CONFIG_IRDA_ULTRA
+ void irlap_unitdata_indication(struct irlap_cb *self, struct sk_buff *skb)
+ {
+- IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -437,7 +437,7 @@ void irlap_unitdata_indication(struct irlap_cb *self, struct sk_buff *skb)
+ */
+ void irlap_disconnect_request(struct irlap_cb *self)
+ {
+- IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(3, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -458,7 +458,7 @@ void irlap_disconnect_request(struct irlap_cb *self)
+ irlap_do_event(self, DISCONNECT_REQUEST, NULL, NULL);
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), disconnect pending!\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s(), disconnect pending!\n", __func__);
+ self->disconnect_pending = TRUE;
+ break;
+ }
+@@ -472,7 +472,7 @@ void irlap_disconnect_request(struct irlap_cb *self)
+ */
+ void irlap_disconnect_indication(struct irlap_cb *self, LAP_REASON reason)
+ {
+- IRDA_DEBUG(1, "%s(), reason=%s\n", __FUNCTION__, lap_reasons[reason]);
++ IRDA_DEBUG(1, "%s(), reason=%s\n", __func__, lap_reasons[reason]);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -482,7 +482,7 @@ void irlap_disconnect_indication(struct irlap_cb *self, LAP_REASON reason)
+
+ switch (reason) {
+ case LAP_RESET_INDICATION:
+- IRDA_DEBUG(1, "%s(), Sending reset request!\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), Sending reset request!\n", __func__);
+ irlap_do_event(self, RESET_REQUEST, NULL, NULL);
+ break;
+ case LAP_NO_RESPONSE: /* FALLTROUGH */
+@@ -493,7 +493,7 @@ void irlap_disconnect_indication(struct irlap_cb *self, LAP_REASON reason)
+ reason, NULL);
+ break;
+ default:
+- IRDA_ERROR("%s: Unknown reason %d\n", __FUNCTION__, reason);
++ IRDA_ERROR("%s: Unknown reason %d\n", __func__, reason);
+ }
+ }
+
+@@ -511,7 +511,7 @@ void irlap_discovery_request(struct irlap_cb *self, discovery_t *discovery)
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(discovery != NULL, return;);
+
+- IRDA_DEBUG(4, "%s(), nslots = %d\n", __FUNCTION__, discovery->nslots);
++ IRDA_DEBUG(4, "%s(), nslots = %d\n", __func__, discovery->nslots);
+
+ IRDA_ASSERT((discovery->nslots == 1) || (discovery->nslots == 6) ||
+ (discovery->nslots == 8) || (discovery->nslots == 16),
+@@ -520,7 +520,7 @@ void irlap_discovery_request(struct irlap_cb *self, discovery_t *discovery)
+ /* Discovery is only possible in NDM mode */
+ if (self->state != LAP_NDM) {
+ IRDA_DEBUG(4, "%s(), discovery only possible in NDM mode\n",
+- __FUNCTION__);
++ __func__);
+ irlap_discovery_confirm(self, NULL);
+ /* Note : in theory, if we are not in NDM, we could postpone
+ * the discovery like we do for connection request.
+@@ -543,7 +543,7 @@ void irlap_discovery_request(struct irlap_cb *self, discovery_t *discovery)
+
+ if (self->discovery_log == NULL) {
+ IRDA_WARNING("%s(), Unable to allocate discovery log!\n",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+
+@@ -598,7 +598,7 @@ void irlap_discovery_confirm(struct irlap_cb *self, hashbin_t *discovery_log)
+ */
+ void irlap_discovery_indication(struct irlap_cb *self, discovery_t *discovery)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -644,7 +644,7 @@ void irlap_status_indication(struct irlap_cb *self, int quality_of_link)
+ */
+ void irlap_reset_indication(struct irlap_cb *self)
+ {
+- IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -660,7 +660,7 @@ void irlap_reset_indication(struct irlap_cb *self)
+ */
+ void irlap_reset_confirm(void)
+ {
+- IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s()\n", __func__);
+ }
+
+ /*
+@@ -760,7 +760,7 @@ int irlap_validate_nr_received(struct irlap_cb *self, int nr)
+ {
+ /* nr as expected? */
+ if (nr == self->vs) {
+- IRDA_DEBUG(4, "%s(), expected!\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s(), expected!\n", __func__);
+ return NR_EXPECTED;
+ }
+
+@@ -788,7 +788,7 @@ int irlap_validate_nr_received(struct irlap_cb *self, int nr)
+ */
+ void irlap_initiate_connection_state(struct irlap_cb *self)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -871,7 +871,7 @@ static void irlap_change_speed(struct irlap_cb *self, __u32 speed, int now)
+ {
+ struct sk_buff *skb;
+
+- IRDA_DEBUG(0, "%s(), setting speed to %d\n", __FUNCTION__, speed);
++ IRDA_DEBUG(0, "%s(), setting speed to %d\n", __func__, speed);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -914,7 +914,7 @@ static void irlap_init_qos_capabilities(struct irlap_cb *self,
+ * user may not have set all of them.
+ */
+ if (qos_user) {
+- IRDA_DEBUG(1, "%s(), Found user specified QoS!\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), Found user specified QoS!\n", __func__);
+
+ if (qos_user->baud_rate.bits)
+ self->qos_rx.baud_rate.bits &= qos_user->baud_rate.bits;
+@@ -944,7 +944,7 @@ static void irlap_init_qos_capabilities(struct irlap_cb *self,
+ */
+ void irlap_apply_default_connection_parameters(struct irlap_cb *self)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -1007,7 +1007,7 @@ void irlap_apply_default_connection_parameters(struct irlap_cb *self)
+ */
+ void irlap_apply_connection_parameters(struct irlap_cb *self, int now)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+diff --git a/net/irda/irlap_event.c b/net/irda/irlap_event.c
+index 6af86eb..16c4ef0 100644
+--- a/net/irda/irlap_event.c
++++ b/net/irda/irlap_event.c
+@@ -217,7 +217,7 @@ static void irlap_start_poll_timer(struct irlap_cb *self, int timeout)
+ } else
+ self->fast_RR = FALSE;
+
+- IRDA_DEBUG(3, "%s(), timeout=%d (%ld)\n", __FUNCTION__, timeout, jiffies);
++ IRDA_DEBUG(3, "%s(), timeout=%d (%ld)\n", __func__, timeout, jiffies);
+ #endif /* CONFIG_IRDA_FAST_RR */
+
+ if (timeout == 0)
+@@ -241,7 +241,7 @@ void irlap_do_event(struct irlap_cb *self, IRLAP_EVENT event,
+ if (!self || self->magic != LAP_MAGIC)
+ return;
+
+- IRDA_DEBUG(3, "%s(), event = %s, state = %s\n", __FUNCTION__,
++ IRDA_DEBUG(3, "%s(), event = %s, state = %s\n", __func__,
+ irlap_event[event], irlap_state[self->state]);
+
+ ret = (*state[self->state])(self, event, skb, info);
+@@ -259,7 +259,7 @@ void irlap_do_event(struct irlap_cb *self, IRLAP_EVENT event,
+ * try to disconnect link if we send any data frames, since
+ * that will change the state away form XMIT
+ */
+- IRDA_DEBUG(2, "%s() : queue len = %d\n", __FUNCTION__,
++ IRDA_DEBUG(2, "%s() : queue len = %d\n", __func__,
+ skb_queue_len(&self->txq));
+
+ if (!skb_queue_empty(&self->txq)) {
+@@ -340,7 +340,7 @@ static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event,
+ * media busy in irlap_connect_request() and
+ * postpone the event... - Jean II */
+ IRDA_DEBUG(0, "%s(), CONNECT_REQUEST: media busy!\n",
+- __FUNCTION__);
++ __func__);
+
+ /* Always switch state before calling upper layers */
+ irlap_next_state(self, LAP_NDM);
+@@ -367,7 +367,7 @@ static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event,
+ irlap_connect_indication(self, skb);
+ } else {
+ IRDA_DEBUG(0, "%s(), SNRM frame does not "
+- "contain an I field!\n", __FUNCTION__);
++ "contain an I field!\n", __func__);
+ }
+ break;
+ case DISCOVERY_REQUEST:
+@@ -375,7 +375,7 @@ static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event,
+
+ if (self->media_busy) {
+ IRDA_DEBUG(1, "%s(), DISCOVERY_REQUEST: media busy!\n",
+- __FUNCTION__);
++ __func__);
+ /* irlap->log.condition = MEDIA_BUSY; */
+
+ /* This will make IrLMP try again */
+@@ -441,7 +441,7 @@ static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event,
+ * those cases...
+ * Jean II
+ */
+- IRDA_DEBUG(1, "%s(), Receiving final discovery request, missed the discovery slots :-(\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), Receiving final discovery request, missed the discovery slots :-(\n", __func__);
+
+ /* Last discovery request -> in the log */
+ irlap_discovery_indication(self, info->discovery);
+@@ -520,7 +520,7 @@ static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event,
+ /* Only accept broadcast frames in NDM mode */
+ if (info->caddr != CBROADCAST) {
+ IRDA_DEBUG(0, "%s(), not a broadcast frame!\n",
+- __FUNCTION__);
++ __func__);
+ } else
+ irlap_unitdata_indication(self, skb);
+ break;
+@@ -536,10 +536,10 @@ static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event,
+ irlap_send_test_frame(self, CBROADCAST, info->daddr, skb);
+ break;
+ case RECV_TEST_RSP:
+- IRDA_DEBUG(0, "%s() not implemented!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s() not implemented!\n", __func__);
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), Unknown event %s\n", __FUNCTION__,
++ IRDA_DEBUG(2, "%s(), Unknown event %s\n", __func__,
+ irlap_event[event]);
+
+ ret = -1;
+@@ -567,13 +567,13 @@ static int irlap_state_query(struct irlap_cb *self, IRLAP_EVENT event,
+ IRDA_ASSERT(info != NULL, return -1;);
+ IRDA_ASSERT(info->discovery != NULL, return -1;);
+
+- IRDA_DEBUG(4, "%s(), daddr=%08x\n", __FUNCTION__,
++ IRDA_DEBUG(4, "%s(), daddr=%08x\n", __func__,
+ info->discovery->data.daddr);
+
+ if (!self->discovery_log) {
+ IRDA_WARNING("%s: discovery log is gone! "
+ "maybe the discovery timeout has been set"
+- " too short?\n", __FUNCTION__);
++ " too short?\n", __func__);
+ break;
+ }
+ hashbin_insert(self->discovery_log,
+@@ -598,7 +598,7 @@ static int irlap_state_query(struct irlap_cb *self, IRLAP_EVENT event,
+
+ IRDA_ASSERT(info != NULL, return -1;);
+
+- IRDA_DEBUG(1, "%s(), Receiving discovery request (s = %d) while performing discovery :-(\n", __FUNCTION__, info->s);
++ IRDA_DEBUG(1, "%s(), Receiving discovery request (s = %d) while performing discovery :-(\n", __func__, info->s);
+
+ /* Last discovery request ? */
+ if (info->s == 0xff)
+@@ -613,7 +613,7 @@ static int irlap_state_query(struct irlap_cb *self, IRLAP_EVENT event,
+ */
+ if (irda_device_is_receiving(self->netdev) && !self->add_wait) {
+ IRDA_DEBUG(2, "%s(), device is slow to answer, "
+- "waiting some more!\n", __FUNCTION__);
++ "waiting some more!\n", __func__);
+ irlap_start_slot_timer(self, msecs_to_jiffies(10));
+ self->add_wait = TRUE;
+ return ret;
+@@ -649,7 +649,7 @@ static int irlap_state_query(struct irlap_cb *self, IRLAP_EVENT event,
+ }
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), Unknown event %s\n", __FUNCTION__,
++ IRDA_DEBUG(2, "%s(), Unknown event %s\n", __func__,
+ irlap_event[event]);
+
+ ret = -1;
+@@ -671,7 +671,7 @@ static int irlap_state_reply(struct irlap_cb *self, IRLAP_EVENT event,
+ discovery_t *discovery_rsp;
+ int ret=0;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
+@@ -679,7 +679,7 @@ static int irlap_state_reply(struct irlap_cb *self, IRLAP_EVENT event,
+ switch (event) {
+ case QUERY_TIMER_EXPIRED:
+ IRDA_DEBUG(0, "%s(), QUERY_TIMER_EXPIRED <%ld>\n",
+- __FUNCTION__, jiffies);
++ __func__, jiffies);
+ irlap_next_state(self, LAP_NDM);
+ break;
+ case RECV_DISCOVERY_XID_CMD:
+@@ -717,7 +717,7 @@ static int irlap_state_reply(struct irlap_cb *self, IRLAP_EVENT event,
+ }
+ break;
+ default:
+- IRDA_DEBUG(1, "%s(), Unknown event %d, %s\n", __FUNCTION__,
++ IRDA_DEBUG(1, "%s(), Unknown event %d, %s\n", __func__,
+ event, irlap_event[event]);
+
+ ret = -1;
+@@ -738,7 +738,7 @@ static int irlap_state_conn(struct irlap_cb *self, IRLAP_EVENT event,
+ {
+ int ret = 0;
+
+- IRDA_DEBUG(4, "%s(), event=%s\n", __FUNCTION__, irlap_event[ event]);
++ IRDA_DEBUG(4, "%s(), event=%s\n", __func__, irlap_event[ event]);
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
+@@ -799,18 +799,18 @@ static int irlap_state_conn(struct irlap_cb *self, IRLAP_EVENT event,
+ break;
+ case RECV_DISCOVERY_XID_CMD:
+ IRDA_DEBUG(3, "%s(), event RECV_DISCOVER_XID_CMD!\n",
+- __FUNCTION__);
++ __func__);
+ irlap_next_state(self, LAP_NDM);
+
+ break;
+ case DISCONNECT_REQUEST:
+- IRDA_DEBUG(0, "%s(), Disconnect request!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), Disconnect request!\n", __func__);
+ irlap_send_dm_frame(self);
+ irlap_next_state( self, LAP_NDM);
+ irlap_disconnect_indication(self, LAP_DISC_INDICATION);
+ break;
+ default:
+- IRDA_DEBUG(1, "%s(), Unknown event %d, %s\n", __FUNCTION__,
++ IRDA_DEBUG(1, "%s(), Unknown event %d, %s\n", __func__,
+ event, irlap_event[event]);
+
+ ret = -1;
+@@ -832,7 +832,7 @@ static int irlap_state_setup(struct irlap_cb *self, IRLAP_EVENT event,
+ {
+ int ret = 0;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
+@@ -861,7 +861,7 @@ static int irlap_state_setup(struct irlap_cb *self, IRLAP_EVENT event,
+ self->retry_count++;
+ break;
+ case RECV_SNRM_CMD:
+- IRDA_DEBUG(4, "%s(), SNRM battle!\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s(), SNRM battle!\n", __func__);
+
+ IRDA_ASSERT(skb != NULL, return 0;);
+ IRDA_ASSERT(info != NULL, return 0;);
+@@ -948,7 +948,7 @@ static int irlap_state_setup(struct irlap_cb *self, IRLAP_EVENT event,
+ irlap_disconnect_indication(self, LAP_DISC_INDICATION);
+ break;
+ default:
+- IRDA_DEBUG(1, "%s(), Unknown event %d, %s\n", __FUNCTION__,
++ IRDA_DEBUG(1, "%s(), Unknown event %d, %s\n", __func__,
+ event, irlap_event[event]);
+
+ ret = -1;
+@@ -966,7 +966,7 @@ static int irlap_state_setup(struct irlap_cb *self, IRLAP_EVENT event,
+ static int irlap_state_offline(struct irlap_cb *self, IRLAP_EVENT event,
+ struct sk_buff *skb, struct irlap_info *info)
+ {
+- IRDA_DEBUG( 0, "%s(), Unknown event\n", __FUNCTION__);
++ IRDA_DEBUG( 0, "%s(), Unknown event\n", __func__);
+
+ return -1;
+ }
+@@ -1030,7 +1030,7 @@ static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event,
+ */
+ if((!nextfit) && (skb->len > self->bytes_left)) {
+ IRDA_DEBUG(0, "%s(), Not allowed to transmit"
+- " more bytes!\n", __FUNCTION__);
++ " more bytes!\n", __func__);
+ /* Requeue the skb */
+ skb_queue_head(&self->txq, skb_get(skb));
+ /*
+@@ -1082,7 +1082,7 @@ static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event,
+ #endif /* CONFIG_IRDA_FAST_RR */
+ } else {
+ IRDA_DEBUG(4, "%s(), Unable to send! remote busy?\n",
+- __FUNCTION__);
++ __func__);
+ skb_queue_head(&self->txq, skb_get(skb));
+
+ /*
+@@ -1094,7 +1094,7 @@ static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event,
+ break;
+ case POLL_TIMER_EXPIRED:
+ IRDA_DEBUG(3, "%s(), POLL_TIMER_EXPIRED <%ld>\n",
+- __FUNCTION__, jiffies);
++ __func__, jiffies);
+ irlap_send_rr_frame(self, CMD_FRAME);
+ /* Return to NRM properly - Jean II */
+ self->window = self->window_size;
+@@ -1120,7 +1120,7 @@ static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event,
+ break;
+ default:
+ IRDA_DEBUG(0, "%s(), Unknown event %s\n",
+- __FUNCTION__, irlap_event[event]);
++ __func__, irlap_event[event]);
+
+ ret = -EINVAL;
+ break;
+@@ -1138,7 +1138,7 @@ static int irlap_state_pclose(struct irlap_cb *self, IRLAP_EVENT event,
+ {
+ int ret = 0;
+
+- IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
+@@ -1173,7 +1173,7 @@ static int irlap_state_pclose(struct irlap_cb *self, IRLAP_EVENT event,
+ }
+ break;
+ default:
+- IRDA_DEBUG(1, "%s(), Unknown event %d\n", __FUNCTION__, event);
++ IRDA_DEBUG(1, "%s(), Unknown event %d\n", __func__, event);
+
+ ret = -1;
+ break;
+@@ -1297,7 +1297,7 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
+ } else {
+ IRDA_DEBUG(4,
+ "%s(), missing or duplicate frame!\n",
+- __FUNCTION__);
++ __func__);
+
+ /* Update Nr received */
+ irlap_update_nr_received(self, info->nr);
+@@ -1367,7 +1367,7 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
+ (nr_status == NR_UNEXPECTED))
+ {
+ IRDA_DEBUG(4, "%s(), unexpected nr and ns!\n",
+- __FUNCTION__);
++ __func__);
+ if (info->pf) {
+ /* Resend rejected frames */
+ irlap_resend_rejected_frames(self, CMD_FRAME);
+@@ -1407,9 +1407,9 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
+ }
+ break;
+ }
+- IRDA_DEBUG(1, "%s(), Not implemented!\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), Not implemented!\n", __func__);
+ IRDA_DEBUG(1, "%s(), event=%s, ns_status=%d, nr_status=%d\n",
+- __FUNCTION__, irlap_event[event], ns_status, nr_status);
++ __func__, irlap_event[event], ns_status, nr_status);
+ break;
+ case RECV_UI_FRAME:
+ /* Poll bit cleared? */
+@@ -1420,7 +1420,7 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
+ del_timer(&self->final_timer);
+ irlap_data_indication(self, skb, TRUE);
+ irlap_next_state(self, LAP_XMIT_P);
+- IRDA_DEBUG(1, "%s: RECV_UI_FRAME: next state %s\n", __FUNCTION__, irlap_state[self->state]);
++ IRDA_DEBUG(1, "%s: RECV_UI_FRAME: next state %s\n", __func__, irlap_state[self->state]);
+ irlap_start_poll_timer(self, self->poll_timeout);
+ }
+ break;
+@@ -1475,7 +1475,7 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
+ irlap_next_state(self, LAP_NRM_P);
+ } else if (ret == NR_INVALID) {
+ IRDA_DEBUG(1, "%s(), Received RR with "
+- "invalid nr !\n", __FUNCTION__);
++ "invalid nr !\n", __func__);
+
+ irlap_next_state(self, LAP_RESET_WAIT);
+
+@@ -1580,7 +1580,7 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
+ irlap_start_final_timer(self, 2 * self->final_timeout);
+ break;
+ case RECV_RD_RSP:
+- IRDA_DEBUG(1, "%s(), RECV_RD_RSP\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), RECV_RD_RSP\n", __func__);
+
+ irlap_flush_all_queues(self);
+ irlap_next_state(self, LAP_XMIT_P);
+@@ -1589,7 +1589,7 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
+ break;
+ default:
+ IRDA_DEBUG(1, "%s(), Unknown event %s\n",
+- __FUNCTION__, irlap_event[event]);
++ __func__, irlap_event[event]);
+
+ ret = -1;
+ break;
+@@ -1609,7 +1609,7 @@ static int irlap_state_reset_wait(struct irlap_cb *self, IRLAP_EVENT event,
+ {
+ int ret = 0;
+
+- IRDA_DEBUG(3, "%s(), event = %s\n", __FUNCTION__, irlap_event[event]);
++ IRDA_DEBUG(3, "%s(), event = %s\n", __func__, irlap_event[event]);
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
+@@ -1635,7 +1635,7 @@ static int irlap_state_reset_wait(struct irlap_cb *self, IRLAP_EVENT event,
+ irlap_next_state( self, LAP_PCLOSE);
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), Unknown event %s\n", __FUNCTION__,
++ IRDA_DEBUG(2, "%s(), Unknown event %s\n", __func__,
+ irlap_event[event]);
+
+ ret = -1;
+@@ -1656,7 +1656,7 @@ static int irlap_state_reset(struct irlap_cb *self, IRLAP_EVENT event,
+ {
+ int ret = 0;
+
+- IRDA_DEBUG(3, "%s(), event = %s\n", __FUNCTION__, irlap_event[event]);
++ IRDA_DEBUG(3, "%s(), event = %s\n", __func__, irlap_event[event]);
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
+@@ -1714,7 +1714,7 @@ static int irlap_state_reset(struct irlap_cb *self, IRLAP_EVENT event,
+ * state
+ */
+ if (!info) {
+- IRDA_DEBUG(3, "%s(), RECV_SNRM_CMD\n", __FUNCTION__);
++ IRDA_DEBUG(3, "%s(), RECV_SNRM_CMD\n", __func__);
+ irlap_initiate_connection_state(self);
+ irlap_wait_min_turn_around(self, &self->qos_tx);
+ irlap_send_ua_response_frame(self, &self->qos_rx);
+@@ -1724,12 +1724,12 @@ static int irlap_state_reset(struct irlap_cb *self, IRLAP_EVENT event,
+ } else {
+ IRDA_DEBUG(0,
+ "%s(), SNRM frame contained an I field!\n",
+- __FUNCTION__);
++ __func__);
+ }
+ break;
+ default:
+ IRDA_DEBUG(1, "%s(), Unknown event %s\n",
+- __FUNCTION__, irlap_event[event]);
++ __func__, irlap_event[event]);
+
+ ret = -1;
+ break;
+@@ -1749,7 +1749,7 @@ static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event,
+ {
+ int ret = 0;
+
+- IRDA_DEBUG(4, "%s(), event=%s\n", __FUNCTION__, irlap_event[event]);
++ IRDA_DEBUG(4, "%s(), event=%s\n", __func__, irlap_event[event]);
+
+ IRDA_ASSERT(self != NULL, return -ENODEV;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
+@@ -1786,7 +1786,7 @@ static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event,
+ */
+ if((!nextfit) && (skb->len > self->bytes_left)) {
+ IRDA_DEBUG(0, "%s(), Not allowed to transmit"
+- " more bytes!\n", __FUNCTION__);
++ " more bytes!\n", __func__);
+ /* Requeue the skb */
+ skb_queue_head(&self->txq, skb_get(skb));
+
+@@ -1832,7 +1832,7 @@ static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event,
+ ret = -EPROTO;
+ }
+ } else {
+- IRDA_DEBUG(2, "%s(), Unable to send!\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s(), Unable to send!\n", __func__);
+ skb_queue_head(&self->txq, skb_get(skb));
+ ret = -EPROTO;
+ }
+@@ -1848,7 +1848,7 @@ static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event,
+ * when we return... - Jean II */
+ break;
+ default:
+- IRDA_DEBUG(2, "%s(), Unknown event %s\n", __FUNCTION__,
++ IRDA_DEBUG(2, "%s(), Unknown event %s\n", __func__,
+ irlap_event[event]);
+
+ ret = -EINVAL;
+@@ -1871,7 +1871,7 @@ static int irlap_state_nrm_s(struct irlap_cb *self, IRLAP_EVENT event,
+ int nr_status;
+ int ret = 0;
+
+- IRDA_DEBUG(4, "%s(), event=%s\n", __FUNCTION__, irlap_event[ event]);
++ IRDA_DEBUG(4, "%s(), event=%s\n", __func__, irlap_event[ event]);
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
+@@ -1880,7 +1880,7 @@ static int irlap_state_nrm_s(struct irlap_cb *self, IRLAP_EVENT event,
+ case RECV_I_CMD: /* Optimize for the common case */
+ /* FIXME: must check for remote_busy below */
+ IRDA_DEBUG(4, "%s(), event=%s nr=%d, vs=%d, ns=%d, "
+- "vr=%d, pf=%d\n", __FUNCTION__,
++ "vr=%d, pf=%d\n", __func__,
+ irlap_event[event], info->nr,
+ self->vs, info->ns, self->vr, info->pf);
+
+@@ -2112,21 +2112,21 @@ static int irlap_state_nrm_s(struct irlap_cb *self, IRLAP_EVENT event,
+ irlap_next_state(self, LAP_NRM_S);
+ } else {
+ IRDA_DEBUG(1, "%s(), invalid nr not implemented!\n",
+- __FUNCTION__);
++ __func__);
+ }
+ break;
+ case RECV_SNRM_CMD:
+ /* SNRM frame is not allowed to contain an I-field */
+ if (!info) {
+ del_timer(&self->wd_timer);
+- IRDA_DEBUG(1, "%s(), received SNRM cmd\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), received SNRM cmd\n", __func__);
+ irlap_next_state(self, LAP_RESET_CHECK);
+
+ irlap_reset_indication(self);
+ } else {
+ IRDA_DEBUG(0,
+ "%s(), SNRM frame contained an I-field!\n",
+- __FUNCTION__);
++ __func__);
+
+ }
+ break;
+@@ -2158,7 +2158,7 @@ static int irlap_state_nrm_s(struct irlap_cb *self, IRLAP_EVENT event,
+ * which explain why we use (self->N2 / 2) here !!!
+ * Jean II
+ */
+- IRDA_DEBUG(1, "%s(), retry_count = %d\n", __FUNCTION__,
++ IRDA_DEBUG(1, "%s(), retry_count = %d\n", __func__,
+ self->retry_count);
+
+ if (self->retry_count < (self->N2 / 2)) {
+@@ -2211,7 +2211,7 @@ static int irlap_state_nrm_s(struct irlap_cb *self, IRLAP_EVENT event,
+ irlap_send_test_frame(self, self->caddr, info->daddr, skb);
+ break;
+ default:
+- IRDA_DEBUG(1, "%s(), Unknown event %d, (%s)\n", __FUNCTION__,
++ IRDA_DEBUG(1, "%s(), Unknown event %d, (%s)\n", __func__,
+ event, irlap_event[event]);
+
+ ret = -EINVAL;
+@@ -2228,7 +2228,7 @@ static int irlap_state_sclose(struct irlap_cb *self, IRLAP_EVENT event,
+ {
+ int ret = 0;
+
+- IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return -ENODEV;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
+@@ -2285,7 +2285,7 @@ static int irlap_state_sclose(struct irlap_cb *self, IRLAP_EVENT event,
+ break; /* stay in SCLOSE */
+ }
+
+- IRDA_DEBUG(1, "%s(), Unknown event %d, (%s)\n", __FUNCTION__,
++ IRDA_DEBUG(1, "%s(), Unknown event %d, (%s)\n", __func__,
+ event, irlap_event[event]);
+
+ ret = -EINVAL;
+@@ -2301,7 +2301,7 @@ static int irlap_state_reset_check( struct irlap_cb *self, IRLAP_EVENT event,
+ {
+ int ret = 0;
+
+- IRDA_DEBUG(1, "%s(), event=%s\n", __FUNCTION__, irlap_event[event]);
++ IRDA_DEBUG(1, "%s(), event=%s\n", __func__, irlap_event[event]);
+
+ IRDA_ASSERT(self != NULL, return -ENODEV;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
+@@ -2322,7 +2322,7 @@ static int irlap_state_reset_check( struct irlap_cb *self, IRLAP_EVENT event,
+ irlap_next_state(self, LAP_SCLOSE);
+ break;
+ default:
+- IRDA_DEBUG(1, "%s(), Unknown event %d, (%s)\n", __FUNCTION__,
++ IRDA_DEBUG(1, "%s(), Unknown event %d, (%s)\n", __func__,
+ event, irlap_event[event]);
+
+ ret = -EINVAL;
+diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c
+index 7c132d6..9089453 100644
+--- a/net/irda/irlap_frame.c
++++ b/net/irda/irlap_frame.c
+@@ -102,7 +102,7 @@ void irlap_queue_xmit(struct irlap_cb *self, struct sk_buff *skb)
+ irlap_insert_info(self, skb);
+
+ if (unlikely(self->mode & IRDA_MODE_MONITOR)) {
+- IRDA_DEBUG(3, "%s(): %s is in monitor mode\n", __FUNCTION__,
++ IRDA_DEBUG(3, "%s(): %s is in monitor mode\n", __func__,
+ self->netdev->name);
+ dev_kfree_skb(skb);
+ return;
+@@ -182,7 +182,7 @@ static void irlap_recv_snrm_cmd(struct irlap_cb *self, struct sk_buff *skb,
+ /* Check if the new connection address is valid */
+ if ((info->caddr == 0x00) || (info->caddr == 0xfe)) {
+ IRDA_DEBUG(3, "%s(), invalid connection address!\n",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+
+@@ -193,7 +193,7 @@ static void irlap_recv_snrm_cmd(struct irlap_cb *self, struct sk_buff *skb,
+ /* Only accept if addressed directly to us */
+ if (info->saddr != self->saddr) {
+ IRDA_DEBUG(2, "%s(), not addressed to us!\n",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+ irlap_do_event(self, RECV_SNRM_CMD, skb, info);
+@@ -215,7 +215,7 @@ void irlap_send_ua_response_frame(struct irlap_cb *self, struct qos_info *qos)
+ struct ua_frame *frame;
+ int ret;
+
+- IRDA_DEBUG(2, "%s() <%ld>\n", __FUNCTION__, jiffies);
++ IRDA_DEBUG(2, "%s() <%ld>\n", __func__, jiffies);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -290,7 +290,7 @@ void irlap_send_disc_frame(struct irlap_cb *self)
+ struct sk_buff *tx_skb = NULL;
+ struct disc_frame *frame;
+
+- IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(3, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -321,7 +321,7 @@ void irlap_send_discovery_xid_frame(struct irlap_cb *self, int S, __u8 s,
+ __u32 bcast = BROADCAST;
+ __u8 *info;
+
+- IRDA_DEBUG(4, "%s(), s=%d, S=%d, command=%d\n", __FUNCTION__,
++ IRDA_DEBUG(4, "%s(), s=%d, S=%d, command=%d\n", __func__,
+ s, S, command);
+
+ IRDA_ASSERT(self != NULL, return;);
+@@ -414,13 +414,13 @@ static void irlap_recv_discovery_xid_rsp(struct irlap_cb *self,
+ __u8 *discovery_info;
+ char *text;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+
+ if (!pskb_may_pull(skb, sizeof(struct xid_frame))) {
+- IRDA_ERROR("%s: frame too short!\n", __FUNCTION__);
++ IRDA_ERROR("%s: frame too short!\n", __func__);
+ return;
+ }
+
+@@ -432,12 +432,12 @@ static void irlap_recv_discovery_xid_rsp(struct irlap_cb *self,
+ /* Make sure frame is addressed to us */
+ if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) {
+ IRDA_DEBUG(0, "%s(), frame is not addressed to us!\n",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+
+ if ((discovery = kzalloc(sizeof(discovery_t), GFP_ATOMIC)) == NULL) {
+- IRDA_WARNING("%s: kmalloc failed!\n", __FUNCTION__);
++ IRDA_WARNING("%s: kmalloc failed!\n", __func__);
+ return;
+ }
+
+@@ -445,7 +445,7 @@ static void irlap_recv_discovery_xid_rsp(struct irlap_cb *self,
+ discovery->data.saddr = self->saddr;
+ discovery->timestamp = jiffies;
+
+- IRDA_DEBUG(4, "%s(), daddr=%08x\n", __FUNCTION__,
++ IRDA_DEBUG(4, "%s(), daddr=%08x\n", __func__,
+ discovery->data.daddr);
+
+ discovery_info = skb_pull(skb, sizeof(struct xid_frame));
+@@ -491,7 +491,7 @@ static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
+ char *text;
+
+ if (!pskb_may_pull(skb, sizeof(struct xid_frame))) {
+- IRDA_ERROR("%s: frame too short!\n", __FUNCTION__);
++ IRDA_ERROR("%s: frame too short!\n", __func__);
+ return;
+ }
+
+@@ -503,7 +503,7 @@ static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
+ /* Make sure frame is addressed to us */
+ if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) {
+ IRDA_DEBUG(0, "%s(), frame is not addressed to us!\n",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+
+@@ -536,7 +536,7 @@ static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
+ if((discovery_info == NULL) ||
+ !pskb_may_pull(skb, 3)) {
+ IRDA_ERROR("%s: discovery frame too short!\n",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+
+@@ -545,7 +545,7 @@ static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
+ */
+ discovery = kmalloc(sizeof(discovery_t), GFP_ATOMIC);
+ if (!discovery) {
+- IRDA_WARNING("%s: unable to malloc!\n", __FUNCTION__);
++ IRDA_WARNING("%s: unable to malloc!\n", __func__);
+ return;
+ }
+
+@@ -657,7 +657,7 @@ static void irlap_recv_rnr_frame(struct irlap_cb *self, struct sk_buff *skb,
+ {
+ info->nr = skb->data[1] >> 5;
+
+- IRDA_DEBUG(4, "%s(), nr=%d, %ld\n", __FUNCTION__, info->nr, jiffies);
++ IRDA_DEBUG(4, "%s(), nr=%d, %ld\n", __func__, info->nr, jiffies);
+
+ if (command)
+ irlap_do_event(self, RECV_RNR_CMD, skb, info);
+@@ -668,7 +668,7 @@ static void irlap_recv_rnr_frame(struct irlap_cb *self, struct sk_buff *skb,
+ static void irlap_recv_rej_frame(struct irlap_cb *self, struct sk_buff *skb,
+ struct irlap_info *info, int command)
+ {
+- IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s()\n", __func__);
+
+ info->nr = skb->data[1] >> 5;
+
+@@ -682,7 +682,7 @@ static void irlap_recv_rej_frame(struct irlap_cb *self, struct sk_buff *skb,
+ static void irlap_recv_srej_frame(struct irlap_cb *self, struct sk_buff *skb,
+ struct irlap_info *info, int command)
+ {
+- IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s()\n", __func__);
+
+ info->nr = skb->data[1] >> 5;
+
+@@ -696,7 +696,7 @@ static void irlap_recv_srej_frame(struct irlap_cb *self, struct sk_buff *skb,
+ static void irlap_recv_disc_frame(struct irlap_cb *self, struct sk_buff *skb,
+ struct irlap_info *info, int command)
+ {
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s()\n", __func__);
+
+ /* Check if this is a command or a response frame */
+ if (command)
+@@ -755,7 +755,7 @@ void irlap_send_data_primary(struct irlap_cb *self, struct sk_buff *skb)
+
+ irlap_send_i_frame( self, tx_skb, CMD_FRAME);
+ } else {
+- IRDA_DEBUG(4, "%s(), sending unreliable frame\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s(), sending unreliable frame\n", __func__);
+ irlap_send_ui_frame(self, skb_get(skb), self->caddr, CMD_FRAME);
+ self->window -= 1;
+ }
+@@ -808,7 +808,7 @@ void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb)
+ irlap_next_state(self, LAP_NRM_P);
+ irlap_send_i_frame(self, tx_skb, CMD_FRAME);
+ } else {
+- IRDA_DEBUG(4, "%s(), sending unreliable frame\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s(), sending unreliable frame\n", __func__);
+
+ if (self->ack_required) {
+ irlap_send_ui_frame(self, skb_get(skb), self->caddr, CMD_FRAME);
+@@ -835,7 +835,7 @@ void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb)
+ * See max_line_capacities[][] in qos.c for details. Jean II */
+ transmission_time -= (self->final_timeout * self->bytes_left
+ / self->line_capacity);
+- IRDA_DEBUG(4, "%s() adjusting transmission_time : ft=%d, bl=%d, lc=%d -> tt=%d\n", __FUNCTION__, self->final_timeout, self->bytes_left, self->line_capacity, transmission_time);
++ IRDA_DEBUG(4, "%s() adjusting transmission_time : ft=%d, bl=%d, lc=%d -> tt=%d\n", __func__, self->final_timeout, self->bytes_left, self->line_capacity, transmission_time);
+
+ /* We are allowed to transmit a maximum number of bytes again. */
+ self->bytes_left = self->line_capacity;
+@@ -1001,7 +1001,7 @@ void irlap_resend_rejected_frames(struct irlap_cb *self, int command)
+ /* tx_skb = skb_clone( skb, GFP_ATOMIC); */
+ tx_skb = skb_copy(skb, GFP_ATOMIC);
+ if (!tx_skb) {
+- IRDA_DEBUG(0, "%s(), unable to copy\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), unable to copy\n", __func__);
+ return;
+ }
+
+@@ -1033,7 +1033,7 @@ void irlap_resend_rejected_frames(struct irlap_cb *self, int command)
+ */
+ while (!skb_queue_empty(&self->txq)) {
+
+- IRDA_DEBUG(0, "%s(), sending additional frames!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), sending additional frames!\n", __func__);
+ if (self->window > 0) {
+ skb = skb_dequeue( &self->txq);
+ IRDA_ASSERT(skb != NULL, return;);
+@@ -1073,7 +1073,7 @@ void irlap_resend_rejected_frame(struct irlap_cb *self, int command)
+ /* tx_skb = skb_clone( skb, GFP_ATOMIC); */
+ tx_skb = skb_copy(skb, GFP_ATOMIC);
+ if (!tx_skb) {
+- IRDA_DEBUG(0, "%s(), unable to copy\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), unable to copy\n", __func__);
+ return;
+ }
+
+@@ -1096,7 +1096,7 @@ void irlap_resend_rejected_frame(struct irlap_cb *self, int command)
+ void irlap_send_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
+ __u8 caddr, int command)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -1156,7 +1156,7 @@ static inline void irlap_recv_i_frame(struct irlap_cb *self,
+ static void irlap_recv_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
+ struct irlap_info *info)
+ {
+- IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG( 4, "%s()\n", __func__);
+
+ info->pf = skb->data[1] & PF_BIT; /* Final bit */
+
+@@ -1175,7 +1175,7 @@ static void irlap_recv_frmr_frame(struct irlap_cb *self, struct sk_buff *skb,
+ __u8 *frame;
+ int w, x, y, z;
+
+- IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+@@ -1183,7 +1183,7 @@ static void irlap_recv_frmr_frame(struct irlap_cb *self, struct sk_buff *skb,
+ IRDA_ASSERT(info != NULL, return;);
+
+ if (!pskb_may_pull(skb, 4)) {
+- IRDA_ERROR("%s: frame too short!\n", __FUNCTION__);
++ IRDA_ERROR("%s: frame too short!\n", __func__);
+ return;
+ }
+
+@@ -1269,10 +1269,10 @@ static void irlap_recv_test_frame(struct irlap_cb *self, struct sk_buff *skb,
+ {
+ struct test_frame *frame;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s()\n", __func__);
+
+ if (!pskb_may_pull(skb, sizeof(*frame))) {
+- IRDA_ERROR("%s: frame too short!\n", __FUNCTION__);
++ IRDA_ERROR("%s: frame too short!\n", __func__);
+ return;
+ }
+ frame = (struct test_frame *) skb->data;
+@@ -1281,7 +1281,7 @@ static void irlap_recv_test_frame(struct irlap_cb *self, struct sk_buff *skb,
+ if (info->caddr == CBROADCAST) {
+ if (skb->len < sizeof(struct test_frame)) {
+ IRDA_DEBUG(0, "%s() test frame too short!\n",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+
+@@ -1326,7 +1326,7 @@ int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
+ int command;
+ __u8 control;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ goto out;
+
+ /* FIXME: should we get our own field? */
+@@ -1342,14 +1342,14 @@ int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
+ * share and non linear skbs. This should never happen, so
+ * we don't need to be clever about it. Jean II */
+ if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
+- IRDA_ERROR("%s: can't clone shared skb!\n", __FUNCTION__);
++ IRDA_ERROR("%s: can't clone shared skb!\n", __func__);
+ dev_kfree_skb(skb);
+ return -1;
+ }
+
+ /* Check if frame is large enough for parsing */
+ if (!pskb_may_pull(skb, 2)) {
+- IRDA_ERROR("%s: frame too short!\n", __FUNCTION__);
++ IRDA_ERROR("%s: frame too short!\n", __func__);
+ dev_kfree_skb(skb);
+ return -1;
+ }
+@@ -1365,7 +1365,7 @@ int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
+ /* First we check if this frame has a valid connection address */
+ if ((info.caddr != self->caddr) && (info.caddr != CBROADCAST)) {
+ IRDA_DEBUG(0, "%s(), wrong connection address!\n",
+- __FUNCTION__);
++ __func__);
+ goto out;
+ }
+ /*
+@@ -1400,7 +1400,7 @@ int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
+ break;
+ default:
+ IRDA_WARNING("%s: Unknown S-frame %02x received!\n",
+- __FUNCTION__, info.control);
++ __func__, info.control);
+ break;
+ }
+ goto out;
+@@ -1438,7 +1438,7 @@ int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
+ break;
+ default:
+ IRDA_WARNING("%s: Unknown frame %02x received!\n",
+- __FUNCTION__, info.control);
++ __func__, info.control);
+ break;
+ }
+ out:
+diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c
+index 135ac69..1f81f8e 100644
+--- a/net/irda/irlmp.c
++++ b/net/irda/irlmp.c
+@@ -76,7 +76,7 @@ const char *irlmp_reasons[] = {
+ */
+ int __init irlmp_init(void)
+ {
+- IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s()\n", __func__);
+ /* Initialize the irlmp structure. */
+ irlmp = kzalloc( sizeof(struct irlmp_cb), GFP_KERNEL);
+ if (irlmp == NULL)
+@@ -164,7 +164,7 @@ struct lsap_cb *irlmp_open_lsap(__u8 slsap_sel, notify_t *notify, __u8 pid)
+ /* Allocate new instance of a LSAP connection */
+ self = kzalloc(sizeof(struct lsap_cb), GFP_ATOMIC);
+ if (self == NULL) {
+- IRDA_ERROR("%s: can't allocate memory\n", __FUNCTION__);
++ IRDA_ERROR("%s: can't allocate memory\n", __func__);
+ return NULL;
+ }
+
+@@ -202,7 +202,7 @@ EXPORT_SYMBOL(irlmp_open_lsap);
+ */
+ static void __irlmp_close_lsap(struct lsap_cb *self)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+@@ -264,7 +264,7 @@ void irlmp_close_lsap(struct lsap_cb *self)
+ if (!lsap) {
+ IRDA_DEBUG(0,
+ "%s(), Looks like somebody has removed me already!\n",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+ __irlmp_close_lsap(self);
+@@ -291,7 +291,7 @@ void irlmp_register_link(struct irlap_cb *irlap, __u32 saddr, notify_t *notify)
+ */
+ lap = kzalloc(sizeof(struct lap_cb), GFP_KERNEL);
+ if (lap == NULL) {
+- IRDA_ERROR("%s: unable to kmalloc\n", __FUNCTION__);
++ IRDA_ERROR("%s: unable to kmalloc\n", __func__);
+ return;
+ }
+
+@@ -304,7 +304,7 @@ void irlmp_register_link(struct irlap_cb *irlap, __u32 saddr, notify_t *notify)
+ #endif
+ lap->lsaps = hashbin_new(HB_LOCK);
+ if (lap->lsaps == NULL) {
+- IRDA_WARNING("%s(), unable to kmalloc lsaps\n", __FUNCTION__);
++ IRDA_WARNING("%s(), unable to kmalloc lsaps\n", __func__);
+ kfree(lap);
+ return;
+ }
+@@ -336,7 +336,7 @@ void irlmp_unregister_link(__u32 saddr)
+ {
+ struct lap_cb *link;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ /* We must remove ourselves from the hashbin *first*. This ensure
+ * that no more LSAPs will be open on this link and no discovery
+@@ -381,7 +381,7 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
+
+ IRDA_DEBUG(2,
+ "%s(), slsap_sel=%02x, dlsap_sel=%02x, saddr=%08x, daddr=%08x\n",
+- __FUNCTION__, self->slsap_sel, dlsap_sel, saddr, daddr);
++ __func__, self->slsap_sel, dlsap_sel, saddr, daddr);
+
+ if (test_bit(0, &self->connected)) {
+ ret = -EISCONN;
+@@ -425,7 +425,7 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
+ if (daddr != DEV_ADDR_ANY)
+ discovery = hashbin_find(irlmp->cachelog, daddr, NULL);
+ else {
+- IRDA_DEBUG(2, "%s(), no daddr\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s(), no daddr\n", __func__);
+ discovery = (discovery_t *)
+ hashbin_get_first(irlmp->cachelog);
+ }
+@@ -438,7 +438,7 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
+ }
+ lap = hashbin_lock_find(irlmp->links, saddr, NULL);
+ if (lap == NULL) {
+- IRDA_DEBUG(1, "%s(), Unable to find a usable link!\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), Unable to find a usable link!\n", __func__);
+ ret = -EHOSTUNREACH;
+ goto err;
+ }
+@@ -453,14 +453,14 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
+ * disconnected yet (waiting for timeout in LAP).
+ * Maybe we could give LAP a bit of help in this case.
+ */
+- IRDA_DEBUG(0, "%s(), sorry, but I'm waiting for LAP to timeout!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), sorry, but I'm waiting for LAP to timeout!\n", __func__);
+ ret = -EAGAIN;
+ goto err;
+ }
+
+ /* LAP is already connected to a different node, and LAP
+ * can only talk to one node at a time */
+- IRDA_DEBUG(0, "%s(), sorry, but link is busy!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), sorry, but link is busy!\n", __func__);
+ ret = -EBUSY;
+ goto err;
+ }
+@@ -522,7 +522,7 @@ void irlmp_connect_indication(struct lsap_cb *self, struct sk_buff *skb)
+ IRDA_ASSERT(self->lap != NULL, return;);
+
+ IRDA_DEBUG(2, "%s(), slsap_sel=%02x, dlsap_sel=%02x\n",
+- __FUNCTION__, self->slsap_sel, self->dlsap_sel);
++ __func__, self->slsap_sel, self->dlsap_sel);
+
+ /* Note : self->lap is set in irlmp_link_data_indication(),
+ * (case CONNECT_CMD:) because we have no way to set it here.
+@@ -563,7 +563,7 @@ int irlmp_connect_response(struct lsap_cb *self, struct sk_buff *userdata)
+ * in the state machine itself. Jean II */
+
+ IRDA_DEBUG(2, "%s(), slsap_sel=%02x, dlsap_sel=%02x\n",
+- __FUNCTION__, self->slsap_sel, self->dlsap_sel);
++ __func__, self->slsap_sel, self->dlsap_sel);
+
+ /* Make room for MUX control header (3 bytes) */
+ IRDA_ASSERT(skb_headroom(userdata) >= LMP_CONTROL_HEADER, return -1;);
+@@ -589,7 +589,7 @@ void irlmp_connect_confirm(struct lsap_cb *self, struct sk_buff *skb)
+ int lap_header_size;
+ int max_seg_size;
+
+- IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(3, "%s()\n", __func__);
+
+ IRDA_ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+@@ -603,7 +603,7 @@ void irlmp_connect_confirm(struct lsap_cb *self, struct sk_buff *skb)
+ max_header_size = LMP_HEADER + lap_header_size;
+
+ IRDA_DEBUG(2, "%s(), max_header_size=%d\n",
+- __FUNCTION__, max_header_size);
++ __func__, max_header_size);
+
+ /* Hide LMP_CONTROL_HEADER header from layer above */
+ skb_pull(skb, LMP_CONTROL_HEADER);
+@@ -629,7 +629,7 @@ struct lsap_cb *irlmp_dup(struct lsap_cb *orig, void *instance)
+ struct lsap_cb *new;
+ unsigned long flags;
+
+- IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s()\n", __func__);
+
+ spin_lock_irqsave(&irlmp->unconnected_lsaps->hb_spinlock, flags);
+
+@@ -638,7 +638,7 @@ struct lsap_cb *irlmp_dup(struct lsap_cb *orig, void *instance)
+ if ((!hashbin_find(irlmp->unconnected_lsaps, (long) orig, NULL)) ||
+ (orig->lap == NULL)) {
+ IRDA_DEBUG(0, "%s(), invalid LSAP (wrong state)\n",
+- __FUNCTION__);
++ __func__);
+ spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock,
+ flags);
+ return NULL;
+@@ -647,7 +647,7 @@ struct lsap_cb *irlmp_dup(struct lsap_cb *orig, void *instance)
+ /* Allocate a new instance */
+ new = kmemdup(orig, sizeof(*new), GFP_ATOMIC);
+ if (!new) {
+- IRDA_DEBUG(0, "%s(), unable to kmalloc\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), unable to kmalloc\n", __func__);
+ spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock,
+ flags);
+ return NULL;
+@@ -693,7 +693,7 @@ int irlmp_disconnect_request(struct lsap_cb *self, struct sk_buff *userdata)
+ * and us that might mess up the hashbins below. This fixes it.
+ * Jean II */
+ if (! test_and_clear_bit(0, &self->connected)) {
+- IRDA_DEBUG(0, "%s(), already disconnected!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), already disconnected!\n", __func__);
+ dev_kfree_skb(userdata);
+ return -1;
+ }
+@@ -747,19 +747,19 @@ void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason,
+ {
+ struct lsap_cb *lsap;
+
+- IRDA_DEBUG(1, "%s(), reason=%s\n", __FUNCTION__, irlmp_reasons[reason]);
++ IRDA_DEBUG(1, "%s(), reason=%s\n", __func__, irlmp_reasons[reason]);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+
+ IRDA_DEBUG(3, "%s(), slsap_sel=%02x, dlsap_sel=%02x\n",
+- __FUNCTION__, self->slsap_sel, self->dlsap_sel);
++ __func__, self->slsap_sel, self->dlsap_sel);
+
+ /* Already disconnected ?
+ * There is a race condition between irlmp_disconnect_request()
+ * and us that might mess up the hashbins below. This fixes it.
+ * Jean II */
+ if (! test_and_clear_bit(0, &self->connected)) {
+- IRDA_DEBUG(0, "%s(), already disconnected!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), already disconnected!\n", __func__);
+ return;
+ }
+
+@@ -792,7 +792,7 @@ void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason,
+ self->notify.disconnect_indication(self->notify.instance,
+ self, reason, skb);
+ } else {
+- IRDA_DEBUG(0, "%s(), no handler\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), no handler\n", __func__);
+ }
+ }
+
+@@ -845,7 +845,7 @@ void irlmp_do_discovery(int nslots)
+ /* Make sure the value is sane */
+ if ((nslots != 1) && (nslots != 6) && (nslots != 8) && (nslots != 16)){
+ IRDA_WARNING("%s: invalid value for number of slots!\n",
+- __FUNCTION__);
++ __func__);
+ nslots = sysctl_discovery_slots = 8;
+ }
+
+@@ -963,7 +963,7 @@ irlmp_notify_client(irlmp_client_t *client,
+ int number; /* Number of nodes in the log */
+ int i;
+
+- IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(3, "%s()\n", __func__);
+
+ /* Check if client wants or not partial/selective log (optimisation) */
+ if (!client->disco_callback)
+@@ -1014,7 +1014,7 @@ void irlmp_discovery_confirm(hashbin_t *log, DISCOVERY_MODE mode)
+ irlmp_client_t *client;
+ irlmp_client_t *client_next;
+
+- IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(3, "%s()\n", __func__);
+
+ IRDA_ASSERT(log != NULL, return;);
+
+@@ -1049,7 +1049,7 @@ void irlmp_discovery_expiry(discinfo_t *expiries, int number)
+ irlmp_client_t *client_next;
+ int i;
+
+- IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(3, "%s()\n", __func__);
+
+ IRDA_ASSERT(expiries != NULL, return;);
+
+@@ -1082,7 +1082,7 @@ void irlmp_discovery_expiry(discinfo_t *expiries, int number)
+ */
+ discovery_t *irlmp_get_discovery_response(void)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(irlmp != NULL, return NULL;);
+
+@@ -1160,7 +1160,7 @@ int irlmp_udata_request(struct lsap_cb *self, struct sk_buff *userdata)
+ {
+ int ret;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(userdata != NULL, return -1;);
+
+@@ -1184,7 +1184,7 @@ int irlmp_udata_request(struct lsap_cb *self, struct sk_buff *userdata)
+ */
+ void irlmp_udata_indication(struct lsap_cb *self, struct sk_buff *skb)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+@@ -1211,7 +1211,7 @@ int irlmp_connless_data_request(struct lsap_cb *self, struct sk_buff *userdata,
+ struct sk_buff *clone_skb;
+ struct lap_cb *lap;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(userdata != NULL, return -1;);
+
+@@ -1262,7 +1262,7 @@ int irlmp_connless_data_request(struct lsap_cb *self, struct sk_buff *userdata,
+ #ifdef CONFIG_IRDA_ULTRA
+ void irlmp_connless_data_indication(struct lsap_cb *self, struct sk_buff *skb)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+@@ -1305,7 +1305,7 @@ void irlmp_status_indication(struct lap_cb *self,
+ curr->notify.status_indication(curr->notify.instance,
+ link, lock);
+ else
+- IRDA_DEBUG(2, "%s(), no handler\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s(), no handler\n", __func__);
+
+ curr = next;
+ }
+@@ -1333,7 +1333,7 @@ void irlmp_flow_indication(struct lap_cb *self, LOCAL_FLOW flow)
+ /* Get the number of lsap. That's the only safe way to know
+ * that we have looped around... - Jean II */
+ lsap_todo = HASHBIN_GET_SIZE(self->lsaps);
+- IRDA_DEBUG(4, "%s() : %d lsaps to scan\n", __FUNCTION__, lsap_todo);
++ IRDA_DEBUG(4, "%s() : %d lsaps to scan\n", __func__, lsap_todo);
+
+ /* Poll lsap in order until the queue is full or until we
+ * tried them all.
+@@ -1352,14 +1352,14 @@ void irlmp_flow_indication(struct lap_cb *self, LOCAL_FLOW flow)
+ /* Uh-oh... Paranoia */
+ if(curr == NULL)
+ break;
+- IRDA_DEBUG(4, "%s() : curr is %p, next was %p and is now %p, still %d to go - queue len = %d\n", __FUNCTION__, curr, next, self->flow_next, lsap_todo, IRLAP_GET_TX_QUEUE_LEN(self->irlap));
++ IRDA_DEBUG(4, "%s() : curr is %p, next was %p and is now %p, still %d to go - queue len = %d\n", __func__, curr, next, self->flow_next, lsap_todo, IRLAP_GET_TX_QUEUE_LEN(self->irlap));
+
+ /* Inform lsap user that it can send one more packet. */
+ if (curr->notify.flow_indication != NULL)
+ curr->notify.flow_indication(curr->notify.instance,
+ curr, flow);
+ else
+- IRDA_DEBUG(1, "%s(), no handler\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), no handler\n", __func__);
+ }
+ }
+
+@@ -1381,7 +1381,7 @@ __u8 *irlmp_hint_to_service(__u8 *hint)
+ */
+ service = kmalloc(16, GFP_ATOMIC);
+ if (!service) {
+- IRDA_DEBUG(1, "%s(), Unable to kmalloc!\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), Unable to kmalloc!\n", __func__);
+ return NULL;
+ }
+
+@@ -1482,12 +1482,12 @@ void *irlmp_register_service(__u16 hints)
+ {
+ irlmp_service_t *service;
+
+- IRDA_DEBUG(4, "%s(), hints = %04x\n", __FUNCTION__, hints);
++ IRDA_DEBUG(4, "%s(), hints = %04x\n", __func__, hints);
+
+ /* Make a new registration */
+ service = kmalloc(sizeof(irlmp_service_t), GFP_ATOMIC);
+ if (!service) {
+- IRDA_DEBUG(1, "%s(), Unable to kmalloc!\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), Unable to kmalloc!\n", __func__);
+ return NULL;
+ }
+ service->hints.word = hints;
+@@ -1512,7 +1512,7 @@ int irlmp_unregister_service(void *handle)
+ irlmp_service_t *service;
+ unsigned long flags;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ if (!handle)
+ return -1;
+@@ -1520,7 +1520,7 @@ int irlmp_unregister_service(void *handle)
+ /* Caller may call with invalid handle (it's legal) - Jean II */
+ service = hashbin_lock_find(irlmp->services, (long) handle, NULL);
+ if (!service) {
+- IRDA_DEBUG(1, "%s(), Unknown service!\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), Unknown service!\n", __func__);
+ return -1;
+ }
+
+@@ -1557,13 +1557,13 @@ void *irlmp_register_client(__u16 hint_mask, DISCOVERY_CALLBACK1 disco_clb,
+ {
+ irlmp_client_t *client;
+
+- IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s()\n", __func__);
+ IRDA_ASSERT(irlmp != NULL, return NULL;);
+
+ /* Make a new registration */
+ client = kmalloc(sizeof(irlmp_client_t), GFP_ATOMIC);
+ if (!client) {
+- IRDA_DEBUG( 1, "%s(), Unable to kmalloc!\n", __FUNCTION__);
++ IRDA_DEBUG( 1, "%s(), Unable to kmalloc!\n", __func__);
+ return NULL;
+ }
+
+@@ -1599,7 +1599,7 @@ int irlmp_update_client(void *handle, __u16 hint_mask,
+
+ client = hashbin_lock_find(irlmp->clients, (long) handle, NULL);
+ if (!client) {
+- IRDA_DEBUG(1, "%s(), Unknown client!\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), Unknown client!\n", __func__);
+ return -1;
+ }
+
+@@ -1622,7 +1622,7 @@ int irlmp_unregister_client(void *handle)
+ {
+ struct irlmp_client *client;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ if (!handle)
+ return -1;
+@@ -1630,11 +1630,11 @@ int irlmp_unregister_client(void *handle)
+ /* Caller may call with invalid handle (it's legal) - Jean II */
+ client = hashbin_lock_find(irlmp->clients, (long) handle, NULL);
+ if (!client) {
+- IRDA_DEBUG(1, "%s(), Unknown client!\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), Unknown client!\n", __func__);
+ return -1;
+ }
+
+- IRDA_DEBUG(4, "%s(), removing client!\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s(), removing client!\n", __func__);
+ hashbin_remove_this(irlmp->clients, (irda_queue_t *) client);
+ kfree(client);
+
+@@ -1663,7 +1663,7 @@ static int irlmp_slsap_inuse(__u8 slsap_sel)
+ IRDA_ASSERT(irlmp->magic == LMP_MAGIC, return TRUE;);
+ IRDA_ASSERT(slsap_sel != LSAP_ANY, return TRUE;);
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ #ifdef CONFIG_IRDA_ULTRA
+ /* Accept all bindings to the connectionless LSAP */
+@@ -1790,7 +1790,7 @@ static __u8 irlmp_find_free_slsap(void)
+ /* Make sure we terminate the loop */
+ if (wrapped++) {
+ IRDA_ERROR("%s: no more free LSAPs !\n",
+- __FUNCTION__);
++ __func__);
+ return 0;
+ }
+ }
+@@ -1805,7 +1805,7 @@ static __u8 irlmp_find_free_slsap(void)
+ /* Got it ! */
+ lsap_sel = irlmp->last_lsap_sel;
+ IRDA_DEBUG(4, "%s(), found free lsap_sel=%02x\n",
+- __FUNCTION__, lsap_sel);
++ __func__, lsap_sel);
+
+ return lsap_sel;
+ }
+@@ -1823,26 +1823,26 @@ LM_REASON irlmp_convert_lap_reason( LAP_REASON lap_reason)
+
+ switch (lap_reason) {
+ case LAP_DISC_INDICATION: /* Received a disconnect request from peer */
+- IRDA_DEBUG( 1, "%s(), LAP_DISC_INDICATION\n", __FUNCTION__);
++ IRDA_DEBUG( 1, "%s(), LAP_DISC_INDICATION\n", __func__);
+ reason = LM_USER_REQUEST;
+ break;
+ case LAP_NO_RESPONSE: /* To many retransmits without response */
+- IRDA_DEBUG( 1, "%s(), LAP_NO_RESPONSE\n", __FUNCTION__);
++ IRDA_DEBUG( 1, "%s(), LAP_NO_RESPONSE\n", __func__);
+ reason = LM_LAP_DISCONNECT;
+ break;
+ case LAP_RESET_INDICATION:
+- IRDA_DEBUG( 1, "%s(), LAP_RESET_INDICATION\n", __FUNCTION__);
++ IRDA_DEBUG( 1, "%s(), LAP_RESET_INDICATION\n", __func__);
+ reason = LM_LAP_RESET;
+ break;
+ case LAP_FOUND_NONE:
+ case LAP_MEDIA_BUSY:
+ case LAP_PRIMARY_CONFLICT:
+- IRDA_DEBUG(1, "%s(), LAP_FOUND_NONE, LAP_MEDIA_BUSY or LAP_PRIMARY_CONFLICT\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), LAP_FOUND_NONE, LAP_MEDIA_BUSY or LAP_PRIMARY_CONFLICT\n", __func__);
+ reason = LM_CONNECT_FAILURE;
+ break;
+ default:
+ IRDA_DEBUG(1, "%s(), Unknow IrLAP disconnect reason %d!\n",
+- __FUNCTION__, lap_reason);
++ __func__, lap_reason);
+ reason = LM_LAP_DISCONNECT;
+ break;
+ }
+diff --git a/net/irda/irlmp_event.c b/net/irda/irlmp_event.c
+index 150cd3f..78cce0c 100644
+--- a/net/irda/irlmp_event.c
++++ b/net/irda/irlmp_event.c
+@@ -120,7 +120,7 @@ static inline void irlmp_next_lap_state(struct lap_cb *self,
+ IRLMP_STATE state)
+ {
+ /*
+- IRDA_DEBUG(4, "%s(), LMP LAP = %s\n", __FUNCTION__, irlmp_state[state]);
++ IRDA_DEBUG(4, "%s(), LMP LAP = %s\n", __func__, irlmp_state[state]);
+ */
+ self->lap_state = state;
+ }
+@@ -130,7 +130,7 @@ static inline void irlmp_next_lsap_state(struct lsap_cb *self,
+ {
+ /*
+ IRDA_ASSERT(self != NULL, return;);
+- IRDA_DEBUG(4, "%s(), LMP LSAP = %s\n", __FUNCTION__, irlsap_state[state]);
++ IRDA_DEBUG(4, "%s(), LMP LSAP = %s\n", __func__, irlsap_state[state]);
+ */
+ self->lsap_state = state;
+ }
+@@ -143,7 +143,7 @@ int irlmp_do_lsap_event(struct lsap_cb *self, IRLMP_EVENT event,
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+
+ IRDA_DEBUG(4, "%s(), EVENT = %s, STATE = %s\n",
+- __FUNCTION__, irlmp_event[event], irlsap_state[ self->lsap_state]);
++ __func__, irlmp_event[event], irlsap_state[ self->lsap_state]);
+
+ return (*lsap_state[self->lsap_state]) (self, event, skb);
+ }
+@@ -160,7 +160,7 @@ void irlmp_do_lap_event(struct lap_cb *self, IRLMP_EVENT event,
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+
+- IRDA_DEBUG(4, "%s(), EVENT = %s, STATE = %s\n", __FUNCTION__,
++ IRDA_DEBUG(4, "%s(), EVENT = %s, STATE = %s\n", __func__,
+ irlmp_event[event],
+ irlmp_state[self->lap_state]);
+
+@@ -169,7 +169,7 @@ void irlmp_do_lap_event(struct lap_cb *self, IRLMP_EVENT event,
+
+ void irlmp_discovery_timer_expired(void *data)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ /* We always cleanup the log (active & passive discovery) */
+ irlmp_do_expiry();
+@@ -184,7 +184,7 @@ void irlmp_watchdog_timer_expired(void *data)
+ {
+ struct lsap_cb *self = (struct lsap_cb *) data;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+@@ -196,7 +196,7 @@ void irlmp_idle_timer_expired(void *data)
+ {
+ struct lap_cb *self = (struct lap_cb *) data;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+@@ -256,7 +256,7 @@ irlmp_do_all_lsap_event(hashbin_t * lsap_hashbin,
+ static void irlmp_state_standby(struct lap_cb *self, IRLMP_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+ IRDA_ASSERT(self->irlap != NULL, return;);
+
+ switch (event) {
+@@ -276,7 +276,7 @@ static void irlmp_state_standby(struct lap_cb *self, IRLMP_EVENT event,
+ irlap_connect_response(self->irlap, skb);
+ break;
+ case LM_LAP_CONNECT_REQUEST:
+- IRDA_DEBUG(4, "%s() LS_CONNECT_REQUEST\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s() LS_CONNECT_REQUEST\n", __func__);
+
+ irlmp_next_lap_state(self, LAP_U_CONNECT);
+
+@@ -285,13 +285,13 @@ static void irlmp_state_standby(struct lap_cb *self, IRLMP_EVENT event,
+ break;
+ case LM_LAP_DISCONNECT_INDICATION:
+ IRDA_DEBUG(4, "%s(), Error LM_LAP_DISCONNECT_INDICATION\n",
+- __FUNCTION__);
++ __func__);
+
+ irlmp_next_lap_state(self, LAP_STANDBY);
+ break;
+ default:
+ IRDA_DEBUG(0, "%s(), Unknown event %s\n",
+- __FUNCTION__, irlmp_event[event]);
++ __func__, irlmp_event[event]);
+ break;
+ }
+ }
+@@ -306,7 +306,7 @@ static void irlmp_state_standby(struct lap_cb *self, IRLMP_EVENT event,
+ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(2, "%s(), event=%s\n", __FUNCTION__, irlmp_event[event]);
++ IRDA_DEBUG(2, "%s(), event=%s\n", __func__, irlmp_event[event]);
+
+ switch (event) {
+ case LM_LAP_CONNECT_INDICATION:
+@@ -326,7 +326,7 @@ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
+ * the lsaps may already have gone. This avoid getting stuck
+ * forever in LAP_ACTIVE state - Jean II */
+ if (HASHBIN_GET_SIZE(self->lsaps) == 0) {
+- IRDA_DEBUG(0, "%s() NO LSAPs !\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s() NO LSAPs !\n", __func__);
+ irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
+ }
+ break;
+@@ -344,12 +344,12 @@ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
+ * the lsaps may already have gone. This avoid getting stuck
+ * forever in LAP_ACTIVE state - Jean II */
+ if (HASHBIN_GET_SIZE(self->lsaps) == 0) {
+- IRDA_DEBUG(0, "%s() NO LSAPs !\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s() NO LSAPs !\n", __func__);
+ irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
+ }
+ break;
+ case LM_LAP_DISCONNECT_INDICATION:
+- IRDA_DEBUG(4, "%s(), LM_LAP_DISCONNECT_INDICATION\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s(), LM_LAP_DISCONNECT_INDICATION\n", __func__);
+ irlmp_next_lap_state(self, LAP_STANDBY);
+
+ /* Send disconnect event to all LSAPs using this link */
+@@ -357,7 +357,7 @@ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
+ LM_LAP_DISCONNECT_INDICATION);
+ break;
+ case LM_LAP_DISCONNECT_REQUEST:
+- IRDA_DEBUG(4, "%s(), LM_LAP_DISCONNECT_REQUEST\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s(), LM_LAP_DISCONNECT_REQUEST\n", __func__);
+
+ /* One of the LSAP did timeout or was closed, if it was
+ * the last one, try to get out of here - Jean II */
+@@ -367,7 +367,7 @@ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
+ break;
+ default:
+ IRDA_DEBUG(0, "%s(), Unknown event %s\n",
+- __FUNCTION__, irlmp_event[event]);
++ __func__, irlmp_event[event]);
+ break;
+ }
+ }
+@@ -381,11 +381,11 @@ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
+ static void irlmp_state_active(struct lap_cb *self, IRLMP_EVENT event,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ switch (event) {
+ case LM_LAP_CONNECT_REQUEST:
+- IRDA_DEBUG(4, "%s(), LS_CONNECT_REQUEST\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s(), LS_CONNECT_REQUEST\n", __func__);
+
+ /*
+ * IrLAP may have a pending disconnect. We tried to close
+@@ -468,7 +468,7 @@ static void irlmp_state_active(struct lap_cb *self, IRLMP_EVENT event,
+ break;
+ default:
+ IRDA_DEBUG(0, "%s(), Unknown event %s\n",
+- __FUNCTION__, irlmp_event[event]);
++ __func__, irlmp_event[event]);
+ break;
+ }
+ }
+@@ -490,7 +490,7 @@ static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
+ {
+ int ret = 0;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+@@ -505,11 +505,11 @@ static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
+ break;
+ #endif /* CONFIG_IRDA_ULTRA */
+ case LM_CONNECT_REQUEST:
+- IRDA_DEBUG(4, "%s(), LM_CONNECT_REQUEST\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s(), LM_CONNECT_REQUEST\n", __func__);
+
+ if (self->conn_skb) {
+ IRDA_WARNING("%s: busy with another request!\n",
+- __FUNCTION__);
++ __func__);
+ return -EBUSY;
+ }
+ /* Don't forget to refcount it (see irlmp_connect_request()) */
+@@ -526,7 +526,7 @@ static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
+ case LM_CONNECT_INDICATION:
+ if (self->conn_skb) {
+ IRDA_WARNING("%s: busy with another request!\n",
+- __FUNCTION__);
++ __func__);
+ return -EBUSY;
+ }
+ /* Don't forget to refcount it (see irlap_driver_rcv()) */
+@@ -552,7 +552,7 @@ static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
+ break;
+ default:
+ IRDA_DEBUG(1, "%s(), Unknown event %s on LSAP %#02x\n",
+- __FUNCTION__, irlmp_event[event], self->slsap_sel);
++ __func__, irlmp_event[event], self->slsap_sel);
+ break;
+ }
+ return ret;
+@@ -570,7 +570,7 @@ static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event,
+ struct lsap_cb *lsap;
+ int ret = 0;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+@@ -603,7 +603,7 @@ static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event,
+ case LM_WATCHDOG_TIMEOUT:
+ /* May happen, who knows...
+ * Jean II */
+- IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __func__);
+
+ /* Disconnect, get out... - Jean II */
+ self->lap = NULL;
+@@ -614,7 +614,7 @@ static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event,
+ /* LM_LAP_DISCONNECT_INDICATION : Should never happen, we
+ * are *not* yet bound to the IrLAP link. Jean II */
+ IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
+- __FUNCTION__, irlmp_event[event], self->slsap_sel);
++ __func__, irlmp_event[event], self->slsap_sel);
+ break;
+ }
+ return ret;
+@@ -632,7 +632,7 @@ static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
+ struct sk_buff *tx_skb;
+ int ret = 0;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+@@ -643,16 +643,16 @@ static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
+ break;
+ case LM_CONNECT_RESPONSE:
+ IRDA_DEBUG(0, "%s(), LM_CONNECT_RESPONSE, "
+- "no indication issued yet\n", __FUNCTION__);
++ "no indication issued yet\n", __func__);
+ /* Keep state */
+ break;
+ case LM_DISCONNECT_REQUEST:
+ IRDA_DEBUG(0, "%s(), LM_DISCONNECT_REQUEST, "
+- "not yet bound to IrLAP connection\n", __FUNCTION__);
++ "not yet bound to IrLAP connection\n", __func__);
+ /* Keep state */
+ break;
+ case LM_LAP_CONNECT_CONFIRM:
+- IRDA_DEBUG(4, "%s(), LS_CONNECT_CONFIRM\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s(), LS_CONNECT_CONFIRM\n", __func__);
+ irlmp_next_lsap_state(self, LSAP_CONNECT);
+
+ tx_skb = self->conn_skb;
+@@ -666,7 +666,7 @@ static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
+ /* Will happen in some rare cases because of a race condition.
+ * Just make sure we don't stay there forever...
+ * Jean II */
+- IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __func__);
+
+ /* Go back to disconnected mode, keep the socket waiting */
+ self->lap = NULL;
+@@ -680,7 +680,7 @@ static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
+ /* LM_LAP_DISCONNECT_INDICATION : Should never happen, we
+ * are *not* yet bound to the IrLAP link. Jean II */
+ IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
+- __FUNCTION__, irlmp_event[event], self->slsap_sel);
++ __func__, irlmp_event[event], self->slsap_sel);
+ break;
+ }
+ return ret;
+@@ -698,7 +698,7 @@ static int irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event,
+ LM_REASON reason;
+ int ret = 0;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+@@ -722,12 +722,12 @@ static int irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event,
+ break;
+ case LM_CONNECT_REQUEST:
+ IRDA_DEBUG(0, "%s(), LM_CONNECT_REQUEST, "
+- "error, LSAP already connected\n", __FUNCTION__);
++ "error, LSAP already connected\n", __func__);
+ /* Keep state */
+ break;
+ case LM_CONNECT_RESPONSE:
+ IRDA_DEBUG(0, "%s(), LM_CONNECT_RESPONSE, "
+- "error, LSAP already connected\n", __FUNCTION__);
++ "error, LSAP already connected\n", __func__);
+ /* Keep state */
+ break;
+ case LM_DISCONNECT_REQUEST:
+@@ -740,7 +740,7 @@ static int irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event,
+ /* Try to close the LAP connection if its still there */
+ if (self->lap) {
+ IRDA_DEBUG(4, "%s(), trying to close IrLAP\n",
+- __FUNCTION__);
++ __func__);
+ irlmp_do_lap_event(self->lap,
+ LM_LAP_DISCONNECT_REQUEST,
+ NULL);
+@@ -764,14 +764,14 @@ static int irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event,
+ reason = skb->data[3];
+
+ /* Try to close the LAP connection */
+- IRDA_DEBUG(4, "%s(), trying to close IrLAP\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s(), trying to close IrLAP\n", __func__);
+ irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
+
+ irlmp_disconnect_indication(self, reason, skb);
+ break;
+ default:
+ IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
+- __FUNCTION__, irlmp_event[event], self->slsap_sel);
++ __func__, irlmp_event[event], self->slsap_sel);
+ break;
+ }
+ return ret;
+@@ -793,7 +793,7 @@ static int irlmp_state_setup(struct lsap_cb *self, IRLMP_EVENT event,
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ switch (event) {
+ case LM_CONNECT_CONFIRM:
+@@ -814,7 +814,7 @@ static int irlmp_state_setup(struct lsap_cb *self, IRLMP_EVENT event,
+ reason = skb->data[3];
+
+ /* Try to close the LAP connection */
+- IRDA_DEBUG(4, "%s(), trying to close IrLAP\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s(), trying to close IrLAP\n", __func__);
+ irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
+
+ irlmp_disconnect_indication(self, reason, skb);
+@@ -832,7 +832,7 @@ static int irlmp_state_setup(struct lsap_cb *self, IRLMP_EVENT event,
+ irlmp_disconnect_indication(self, reason, skb);
+ break;
+ case LM_WATCHDOG_TIMEOUT:
+- IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __func__);
+
+ IRDA_ASSERT(self->lap != NULL, return -1;);
+ irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
+@@ -842,7 +842,7 @@ static int irlmp_state_setup(struct lsap_cb *self, IRLMP_EVENT event,
+ break;
+ default:
+ IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
+- __FUNCTION__, irlmp_event[event], self->slsap_sel);
++ __func__, irlmp_event[event], self->slsap_sel);
+ break;
+ }
+ return ret;
+@@ -863,7 +863,7 @@ static int irlmp_state_setup_pend(struct lsap_cb *self, IRLMP_EVENT event,
+ LM_REASON reason;
+ int ret = 0;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(irlmp != NULL, return -1;);
+@@ -883,7 +883,7 @@ static int irlmp_state_setup_pend(struct lsap_cb *self, IRLMP_EVENT event,
+ irlmp_next_lsap_state(self, LSAP_SETUP);
+ break;
+ case LM_WATCHDOG_TIMEOUT:
+- IRDA_DEBUG(0, "%s() : WATCHDOG_TIMEOUT !\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s() : WATCHDOG_TIMEOUT !\n", __func__);
+
+ IRDA_ASSERT(self->lap != NULL, return -1;);
+ irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
+@@ -902,7 +902,7 @@ static int irlmp_state_setup_pend(struct lsap_cb *self, IRLMP_EVENT event,
+ break;
+ default:
+ IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
+- __FUNCTION__, irlmp_event[event], self->slsap_sel);
++ __func__, irlmp_event[event], self->slsap_sel);
+ break;
+ }
+ return ret;
+diff --git a/net/irda/irlmp_frame.c b/net/irda/irlmp_frame.c
+index 0a79d9a..3750884 100644
+--- a/net/irda/irlmp_frame.c
++++ b/net/irda/irlmp_frame.c
+@@ -44,7 +44,7 @@ inline void irlmp_send_data_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap,
+ skb->data[1] = slsap;
+
+ if (expedited) {
+- IRDA_DEBUG(4, "%s(), sending expedited data\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s(), sending expedited data\n", __func__);
+ irlap_data_request(self->irlap, skb, TRUE);
+ } else
+ irlap_data_request(self->irlap, skb, FALSE);
+@@ -60,7 +60,7 @@ void irlmp_send_lcf_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap,
+ {
+ __u8 *frame;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+@@ -95,7 +95,7 @@ void irlmp_link_data_indication(struct lap_cb *self, struct sk_buff *skb,
+ __u8 dlsap_sel; /* Destination LSAP address */
+ __u8 *fp;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+@@ -117,7 +117,7 @@ void irlmp_link_data_indication(struct lap_cb *self, struct sk_buff *skb,
+ if ((fp[0] & CONTROL_BIT) && (fp[2] == CONNECT_CMD)) {
+ IRDA_DEBUG(3, "%s(), incoming connection, "
+ "source LSAP=%d, dest LSAP=%d\n",
+- __FUNCTION__, slsap_sel, dlsap_sel);
++ __func__, slsap_sel, dlsap_sel);
+
+ /* Try to find LSAP among the unconnected LSAPs */
+ lsap = irlmp_find_lsap(self, dlsap_sel, slsap_sel, CONNECT_CMD,
+@@ -125,7 +125,7 @@ void irlmp_link_data_indication(struct lap_cb *self, struct sk_buff *skb,
+
+ /* Maybe LSAP was already connected, so try one more time */
+ if (!lsap) {
+- IRDA_DEBUG(1, "%s(), incoming connection for LSAP already connected\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), incoming connection for LSAP already connected\n", __func__);
+ lsap = irlmp_find_lsap(self, dlsap_sel, slsap_sel, 0,
+ self->lsaps);
+ }
+@@ -136,12 +136,12 @@ void irlmp_link_data_indication(struct lap_cb *self, struct sk_buff *skb,
+ if (lsap == NULL) {
+ IRDA_DEBUG(2, "IrLMP, Sorry, no LSAP for received frame!\n");
+ IRDA_DEBUG(2, "%s(), slsap_sel = %02x, dlsap_sel = %02x\n",
+- __FUNCTION__, slsap_sel, dlsap_sel);
++ __func__, slsap_sel, dlsap_sel);
+ if (fp[0] & CONTROL_BIT) {
+ IRDA_DEBUG(2, "%s(), received control frame %02x\n",
+- __FUNCTION__, fp[2]);
++ __func__, fp[2]);
+ } else {
+- IRDA_DEBUG(2, "%s(), received data frame\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s(), received data frame\n", __func__);
+ }
+ return;
+ }
+@@ -160,7 +160,7 @@ void irlmp_link_data_indication(struct lap_cb *self, struct sk_buff *skb,
+ break;
+ case DISCONNECT:
+ IRDA_DEBUG(4, "%s(), Disconnect indication!\n",
+- __FUNCTION__);
++ __func__);
+ irlmp_do_lsap_event(lsap, LM_DISCONNECT_INDICATION,
+ skb);
+ break;
+@@ -172,7 +172,7 @@ void irlmp_link_data_indication(struct lap_cb *self, struct sk_buff *skb,
+ break;
+ default:
+ IRDA_DEBUG(0, "%s(), Unknown control frame %02x\n",
+- __FUNCTION__, fp[2]);
++ __func__, fp[2]);
+ break;
+ }
+ } else if (unreliable) {
+@@ -206,7 +206,7 @@ void irlmp_link_unitdata_indication(struct lap_cb *self, struct sk_buff *skb)
+ __u8 *fp;
+ unsigned long flags;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+@@ -224,13 +224,13 @@ void irlmp_link_unitdata_indication(struct lap_cb *self, struct sk_buff *skb)
+
+ if (pid & 0x80) {
+ IRDA_DEBUG(0, "%s(), extension in PID not supp!\n",
+- __FUNCTION__);
++ __func__);
+ return;
+ }
+
+ /* Check if frame is addressed to the connectionless LSAP */
+ if ((slsap_sel != LSAP_CONNLESS) || (dlsap_sel != LSAP_CONNLESS)) {
+- IRDA_DEBUG(0, "%s(), dropping frame!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), dropping frame!\n", __func__);
+ return;
+ }
+
+@@ -254,7 +254,7 @@ void irlmp_link_unitdata_indication(struct lap_cb *self, struct sk_buff *skb)
+ if (lsap)
+ irlmp_connless_data_indication(lsap, skb);
+ else {
+- IRDA_DEBUG(0, "%s(), found no matching LSAP!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), found no matching LSAP!\n", __func__);
+ }
+ }
+ #endif /* CONFIG_IRDA_ULTRA */
+@@ -270,7 +270,7 @@ void irlmp_link_disconnect_indication(struct lap_cb *lap,
+ LAP_REASON reason,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s()\n", __func__);
+
+ IRDA_ASSERT(lap != NULL, return;);
+ IRDA_ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
+@@ -296,7 +296,7 @@ void irlmp_link_connect_indication(struct lap_cb *self, __u32 saddr,
+ __u32 daddr, struct qos_info *qos,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ /* Copy QoS settings for this session */
+ self->qos = qos;
+@@ -317,7 +317,7 @@ void irlmp_link_connect_indication(struct lap_cb *self, __u32 saddr,
+ void irlmp_link_connect_confirm(struct lap_cb *self, struct qos_info *qos,
+ struct sk_buff *skb)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+@@ -383,7 +383,7 @@ void irlmp_link_discovery_indication(struct lap_cb *self,
+ */
+ void irlmp_link_discovery_confirm(struct lap_cb *self, hashbin_t *log)
+ {
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+diff --git a/net/irda/irmod.c b/net/irda/irmod.c
+index 01554b9..4c487a8 100644
+--- a/net/irda/irmod.c
++++ b/net/irda/irmod.c
+@@ -90,7 +90,7 @@ static int __init irda_init(void)
+ {
+ int ret = 0;
+
+- IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s()\n", __func__);
+
+ /* Lower layer of the stack */
+ irlmp_init();
+diff --git a/net/irda/irnet/irnet.h b/net/irda/irnet/irnet.h
+index 7873c39..b001c36 100644
+--- a/net/irda/irnet/irnet.h
++++ b/net/irda/irnet/irnet.h
+@@ -337,27 +337,27 @@
+ /* All error messages (will show up in the normal logs) */
+ #define DERROR(dbg, format, args...) \
+ {if(DEBUG_##dbg) \
+- printk(KERN_INFO "irnet: %s(): " format, __FUNCTION__ , ##args);}
++ printk(KERN_INFO "irnet: %s(): " format, __func__ , ##args);}
+
+ /* Normal debug message (will show up in /var/log/debug) */
+ #define DEBUG(dbg, format, args...) \
+ {if(DEBUG_##dbg) \
+- printk(KERN_DEBUG "irnet: %s(): " format, __FUNCTION__ , ##args);}
++ printk(KERN_DEBUG "irnet: %s(): " format, __func__ , ##args);}
+
+ /* Entering a function (trace) */
+ #define DENTER(dbg, format, args...) \
+ {if(DEBUG_##dbg) \
+- printk(KERN_DEBUG "irnet: -> %s" format, __FUNCTION__ , ##args);}
++ printk(KERN_DEBUG "irnet: -> %s" format, __func__ , ##args);}
+
+ /* Entering and exiting a function in one go (trace) */
+ #define DPASS(dbg, format, args...) \
+ {if(DEBUG_##dbg) \
+- printk(KERN_DEBUG "irnet: <>%s" format, __FUNCTION__ , ##args);}
++ printk(KERN_DEBUG "irnet: <>%s" format, __func__ , ##args);}
+
+ /* Exiting a function (trace) */
+ #define DEXIT(dbg, format, args...) \
+ {if(DEBUG_##dbg) \
+- printk(KERN_DEBUG "irnet: <-%s()" format, __FUNCTION__ , ##args);}
++ printk(KERN_DEBUG "irnet: <-%s()" format, __func__ , ##args);}
+
+ /* Exit a function with debug */
+ #define DRETURN(ret, dbg, args...) \
+diff --git a/net/irda/irnetlink.c b/net/irda/irnetlink.c
+index cd9ff17..9e1fb82 100644
+--- a/net/irda/irnetlink.c
++++ b/net/irda/irnetlink.c
+@@ -40,7 +40,7 @@ static struct net_device * ifname_to_netdev(struct net *net, struct genl_info *i
+
+ ifname = nla_data(info->attrs[IRDA_NL_ATTR_IFNAME]);
+
+- IRDA_DEBUG(5, "%s(): Looking for %s\n", __FUNCTION__, ifname);
++ IRDA_DEBUG(5, "%s(): Looking for %s\n", __func__, ifname);
+
+ return dev_get_by_name(net, ifname);
+ }
+@@ -56,7 +56,7 @@ static int irda_nl_set_mode(struct sk_buff *skb, struct genl_info *info)
+
+ mode = nla_get_u32(info->attrs[IRDA_NL_ATTR_MODE]);
+
+- IRDA_DEBUG(5, "%s(): Switching to mode: %d\n", __FUNCTION__, mode);
++ IRDA_DEBUG(5, "%s(): Switching to mode: %d\n", __func__, mode);
+
+ dev = ifname_to_netdev(&init_net, info);
+ if (!dev)
+diff --git a/net/irda/irqueue.c b/net/irda/irqueue.c
+index 40c28ef..ba01938 100644
+--- a/net/irda/irqueue.c
++++ b/net/irda/irqueue.c
+@@ -232,7 +232,7 @@ static __u32 hash( const char* name)
+ static void enqueue_first(irda_queue_t **queue, irda_queue_t* element)
+ {
+
+- IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG( 4, "%s()\n", __func__);
+
+ /*
+ * Check if queue is empty.
+@@ -451,7 +451,7 @@ void hashbin_insert(hashbin_t* hashbin, irda_queue_t* entry, long hashv,
+ unsigned long flags = 0;
+ int bin;
+
+- IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG( 4, "%s()\n", __func__);
+
+ IRDA_ASSERT( hashbin != NULL, return;);
+ IRDA_ASSERT( hashbin->magic == HB_MAGIC, return;);
+@@ -564,7 +564,7 @@ void* hashbin_remove( hashbin_t* hashbin, long hashv, const char* name)
+ unsigned long flags = 0;
+ irda_queue_t* entry;
+
+- IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG( 4, "%s()\n", __func__);
+
+ IRDA_ASSERT( hashbin != NULL, return NULL;);
+ IRDA_ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
+@@ -657,7 +657,7 @@ void* hashbin_remove_this( hashbin_t* hashbin, irda_queue_t* entry)
+ int bin;
+ long hashv;
+
+- IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG( 4, "%s()\n", __func__);
+
+ IRDA_ASSERT( hashbin != NULL, return NULL;);
+ IRDA_ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
+diff --git a/net/irda/irttp.c b/net/irda/irttp.c
+index 97db158..74e439e 100644
+--- a/net/irda/irttp.c
++++ b/net/irda/irttp.c
+@@ -95,7 +95,7 @@ int __init irttp_init(void)
+ irttp->tsaps = hashbin_new(HB_LOCK);
+ if (!irttp->tsaps) {
+ IRDA_ERROR("%s: can't allocate IrTTP hashbin!\n",
+- __FUNCTION__);
++ __func__);
+ kfree(irttp);
+ return -ENOMEM;
+ }
+@@ -164,7 +164,7 @@ static void irttp_todo_expired(unsigned long data)
+ if (!self || self->magic != TTP_TSAP_MAGIC)
+ return;
+
+- IRDA_DEBUG(4, "%s(instance=%p)\n", __FUNCTION__, self);
++ IRDA_DEBUG(4, "%s(instance=%p)\n", __func__, self);
+
+ /* Try to make some progress, especially on Tx side - Jean II */
+ irttp_run_rx_queue(self);
+@@ -205,7 +205,7 @@ void irttp_flush_queues(struct tsap_cb *self)
+ {
+ struct sk_buff* skb;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+@@ -238,7 +238,7 @@ static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self)
+ IRDA_ASSERT(self != NULL, return NULL;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return NULL;);
+
+- IRDA_DEBUG(2, "%s(), self->rx_sdu_size=%d\n", __FUNCTION__,
++ IRDA_DEBUG(2, "%s(), self->rx_sdu_size=%d\n", __func__,
+ self->rx_sdu_size);
+
+ skb = dev_alloc_skb(TTP_HEADER + self->rx_sdu_size);
+@@ -264,7 +264,7 @@ static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self)
+
+ IRDA_DEBUG(2,
+ "%s(), frame len=%d, rx_sdu_size=%d, rx_max_sdu_size=%d\n",
+- __FUNCTION__, n, self->rx_sdu_size, self->rx_max_sdu_size);
++ __func__, n, self->rx_sdu_size, self->rx_max_sdu_size);
+ /* Note : irttp_run_rx_queue() calculate self->rx_sdu_size
+ * by summing the size of all fragments, so we should always
+ * have n == self->rx_sdu_size, except in cases where we
+@@ -293,7 +293,7 @@ static inline void irttp_fragment_skb(struct tsap_cb *self,
+ struct sk_buff *frag;
+ __u8 *frame;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+@@ -303,7 +303,7 @@ static inline void irttp_fragment_skb(struct tsap_cb *self,
+ * Split frame into a number of segments
+ */
+ while (skb->len > self->max_seg_size) {
+- IRDA_DEBUG(2, "%s(), fragmenting ...\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s(), fragmenting ...\n", __func__);
+
+ /* Make new segment */
+ frag = alloc_skb(self->max_seg_size+self->max_header_size,
+@@ -328,7 +328,7 @@ static inline void irttp_fragment_skb(struct tsap_cb *self,
+ skb_queue_tail(&self->tx_queue, frag);
+ }
+ /* Queue what is left of the original skb */
+- IRDA_DEBUG(2, "%s(), queuing last segment\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s(), queuing last segment\n", __func__);
+
+ frame = skb_push(skb, TTP_HEADER);
+ frame[0] = 0x00; /* Clear more bit */
+@@ -359,7 +359,7 @@ static int irttp_param_max_sdu_size(void *instance, irda_param_t *param,
+ else
+ self->tx_max_sdu_size = param->pv.i;
+
+- IRDA_DEBUG(1, "%s(), MaxSduSize=%d\n", __FUNCTION__, param->pv.i);
++ IRDA_DEBUG(1, "%s(), MaxSduSize=%d\n", __func__, param->pv.i);
+
+ return 0;
+ }
+@@ -400,13 +400,13 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify)
+ * JeanII */
+ if((stsap_sel != LSAP_ANY) &&
+ ((stsap_sel < 0x01) || (stsap_sel >= 0x70))) {
+- IRDA_DEBUG(0, "%s(), invalid tsap!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), invalid tsap!\n", __func__);
+ return NULL;
+ }
+
+ self = kzalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
+ if (self == NULL) {
+- IRDA_DEBUG(0, "%s(), unable to kmalloc!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), unable to kmalloc!\n", __func__);
+ return NULL;
+ }
+
+@@ -438,7 +438,7 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify)
+ */
+ lsap = irlmp_open_lsap(stsap_sel, &ttp_notify, 0);
+ if (lsap == NULL) {
+- IRDA_WARNING("%s: unable to allocate LSAP!!\n", __FUNCTION__);
++ IRDA_WARNING("%s: unable to allocate LSAP!!\n", __func__);
+ return NULL;
+ }
+
+@@ -448,7 +448,7 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify)
+ * the stsap_sel we have might not be valid anymore
+ */
+ self->stsap_sel = lsap->slsap_sel;
+- IRDA_DEBUG(4, "%s(), stsap_sel=%02x\n", __FUNCTION__, self->stsap_sel);
++ IRDA_DEBUG(4, "%s(), stsap_sel=%02x\n", __func__, self->stsap_sel);
+
+ self->notify = *notify;
+ self->lsap = lsap;
+@@ -506,7 +506,7 @@ int irttp_close_tsap(struct tsap_cb *self)
+ {
+ struct tsap_cb *tsap;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+@@ -516,7 +516,7 @@ int irttp_close_tsap(struct tsap_cb *self)
+ /* Check if disconnect is not pending */
+ if (!test_bit(0, &self->disconnect_pend)) {
+ IRDA_WARNING("%s: TSAP still connected!\n",
+- __FUNCTION__);
++ __func__);
+ irttp_disconnect_request(self, NULL, P_NORMAL);
+ }
+ self->close_pend = TRUE;
+@@ -553,18 +553,18 @@ int irttp_udata_request(struct tsap_cb *self, struct sk_buff *skb)
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+ IRDA_ASSERT(skb != NULL, return -1;);
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ /* Check that nothing bad happens */
+ if ((skb->len == 0) || (!self->connected)) {
+ IRDA_DEBUG(1, "%s(), No data, or not connected\n",
+- __FUNCTION__);
++ __func__);
+ goto err;
+ }
+
+ if (skb->len > self->max_seg_size) {
+ IRDA_DEBUG(1, "%s(), UData is too large for IrLAP!\n",
+- __FUNCTION__);
++ __func__);
+ goto err;
+ }
+
+@@ -595,12 +595,12 @@ int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb)
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+ IRDA_ASSERT(skb != NULL, return -1;);
+
+- IRDA_DEBUG(2, "%s() : queue len = %d\n", __FUNCTION__,
++ IRDA_DEBUG(2, "%s() : queue len = %d\n", __func__,
+ skb_queue_len(&self->tx_queue));
+
+ /* Check that nothing bad happens */
+ if ((skb->len == 0) || (!self->connected)) {
+- IRDA_WARNING("%s: No data, or not connected\n", __FUNCTION__);
++ IRDA_WARNING("%s: No data, or not connected\n", __func__);
+ ret = -ENOTCONN;
+ goto err;
+ }
+@@ -611,7 +611,7 @@ int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb)
+ */
+ if ((self->tx_max_sdu_size == 0) && (skb->len > self->max_seg_size)) {
+ IRDA_ERROR("%s: SAR disabled, and data is too large for IrLAP!\n",
+- __FUNCTION__);
++ __func__);
+ ret = -EMSGSIZE;
+ goto err;
+ }
+@@ -625,7 +625,7 @@ int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb)
+ (skb->len > self->tx_max_sdu_size))
+ {
+ IRDA_ERROR("%s: SAR enabled, but data is larger than TxMaxSduSize!\n",
+- __FUNCTION__);
++ __func__);
+ ret = -EMSGSIZE;
+ goto err;
+ }
+@@ -704,7 +704,7 @@ static void irttp_run_tx_queue(struct tsap_cb *self)
+ int n;
+
+ IRDA_DEBUG(2, "%s() : send_credit = %d, queue_len = %d\n",
+- __FUNCTION__,
++ __func__,
+ self->send_credit, skb_queue_len(&self->tx_queue));
+
+ /* Get exclusive access to the tx queue, otherwise don't touch it */
+@@ -813,7 +813,7 @@ static inline void irttp_give_credit(struct tsap_cb *self)
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+
+ IRDA_DEBUG(4, "%s() send=%d,avail=%d,remote=%d\n",
+- __FUNCTION__,
++ __func__,
+ self->send_credit, self->avail_credit, self->remote_credit);
+
+ /* Give credit to peer */
+@@ -862,7 +862,7 @@ static int irttp_udata_indication(void *instance, void *sap,
+ struct tsap_cb *self;
+ int err;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ self = (struct tsap_cb *) instance;
+
+@@ -979,7 +979,7 @@ static void irttp_status_indication(void *instance,
+ {
+ struct tsap_cb *self;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ self = (struct tsap_cb *) instance;
+
+@@ -997,7 +997,7 @@ static void irttp_status_indication(void *instance,
+ self->notify.status_indication(self->notify.instance,
+ link, lock);
+ else
+- IRDA_DEBUG(2, "%s(), no handler\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s(), no handler\n", __func__);
+ }
+
+ /*
+@@ -1015,7 +1015,7 @@ static void irttp_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+
+- IRDA_DEBUG(4, "%s(instance=%p)\n", __FUNCTION__, self);
++ IRDA_DEBUG(4, "%s(instance=%p)\n", __func__, self);
+
+ /* We are "polled" directly from LAP, and the LAP want to fill
+ * its Tx window. We want to do our best to send it data, so that
+@@ -1053,18 +1053,18 @@ static void irttp_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
+ */
+ void irttp_flow_request(struct tsap_cb *self, LOCAL_FLOW flow)
+ {
+- IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s()\n", __func__);
+
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+
+ switch (flow) {
+ case FLOW_STOP:
+- IRDA_DEBUG(1, "%s(), flow stop\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), flow stop\n", __func__);
+ self->rx_sdu_busy = TRUE;
+ break;
+ case FLOW_START:
+- IRDA_DEBUG(1, "%s(), flow start\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), flow start\n", __func__);
+ self->rx_sdu_busy = FALSE;
+
+ /* Client say he can accept more data, try to free our
+@@ -1073,7 +1073,7 @@ void irttp_flow_request(struct tsap_cb *self, LOCAL_FLOW flow)
+
+ break;
+ default:
+- IRDA_DEBUG(1, "%s(), Unknown flow command!\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), Unknown flow command!\n", __func__);
+ }
+ }
+ EXPORT_SYMBOL(irttp_flow_request);
+@@ -1093,7 +1093,7 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,
+ __u8 *frame;
+ __u8 n;
+
+- IRDA_DEBUG(4, "%s(), max_sdu_size=%d\n", __FUNCTION__, max_sdu_size);
++ IRDA_DEBUG(4, "%s(), max_sdu_size=%d\n", __func__, max_sdu_size);
+
+ IRDA_ASSERT(self != NULL, return -EBADR;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -EBADR;);
+@@ -1191,7 +1191,7 @@ static void irttp_connect_confirm(void *instance, void *sap,
+ __u8 plen;
+ __u8 n;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ self = (struct tsap_cb *) instance;
+
+@@ -1215,7 +1215,7 @@ static void irttp_connect_confirm(void *instance, void *sap,
+
+ n = skb->data[0] & 0x7f;
+
+- IRDA_DEBUG(4, "%s(), Initial send_credit=%d\n", __FUNCTION__, n);
++ IRDA_DEBUG(4, "%s(), Initial send_credit=%d\n", __func__, n);
+
+ self->send_credit = n;
+ self->tx_max_sdu_size = 0;
+@@ -1236,7 +1236,7 @@ static void irttp_connect_confirm(void *instance, void *sap,
+ /* Any errors in the parameter list? */
+ if (ret < 0) {
+ IRDA_WARNING("%s: error extracting parameters\n",
+- __FUNCTION__);
++ __func__);
+ dev_kfree_skb(skb);
+
+ /* Do not accept this connection attempt */
+@@ -1246,10 +1246,10 @@ static void irttp_connect_confirm(void *instance, void *sap,
+ skb_pull(skb, IRDA_MIN(skb->len, plen+1));
+ }
+
+- IRDA_DEBUG(4, "%s() send=%d,avail=%d,remote=%d\n", __FUNCTION__,
++ IRDA_DEBUG(4, "%s() send=%d,avail=%d,remote=%d\n", __func__,
+ self->send_credit, self->avail_credit, self->remote_credit);
+
+- IRDA_DEBUG(2, "%s(), MaxSduSize=%d\n", __FUNCTION__,
++ IRDA_DEBUG(2, "%s(), MaxSduSize=%d\n", __func__,
+ self->tx_max_sdu_size);
+
+ if (self->notify.connect_confirm) {
+@@ -1288,7 +1288,7 @@ void irttp_connect_indication(void *instance, void *sap, struct qos_info *qos,
+ self->max_seg_size = max_seg_size - TTP_HEADER;
+ self->max_header_size = max_header_size+TTP_HEADER;
+
+- IRDA_DEBUG(4, "%s(), TSAP sel=%02x\n", __FUNCTION__, self->stsap_sel);
++ IRDA_DEBUG(4, "%s(), TSAP sel=%02x\n", __func__, self->stsap_sel);
+
+ /* Need to update dtsap_sel if its equal to LSAP_ANY */
+ self->dtsap_sel = lsap->dlsap_sel;
+@@ -1313,7 +1313,7 @@ void irttp_connect_indication(void *instance, void *sap, struct qos_info *qos,
+ /* Any errors in the parameter list? */
+ if (ret < 0) {
+ IRDA_WARNING("%s: error extracting parameters\n",
+- __FUNCTION__);
++ __func__);
+ dev_kfree_skb(skb);
+
+ /* Do not accept this connection attempt */
+@@ -1350,7 +1350,7 @@ int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+
+- IRDA_DEBUG(4, "%s(), Source TSAP selector=%02x\n", __FUNCTION__,
++ IRDA_DEBUG(4, "%s(), Source TSAP selector=%02x\n", __func__,
+ self->stsap_sel);
+
+ /* Any userdata supplied? */
+@@ -1432,14 +1432,14 @@ struct tsap_cb *irttp_dup(struct tsap_cb *orig, void *instance)
+ struct tsap_cb *new;
+ unsigned long flags;
+
+- IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s()\n", __func__);
+
+ /* Protect our access to the old tsap instance */
+ spin_lock_irqsave(&irttp->tsaps->hb_spinlock, flags);
+
+ /* Find the old instance */
+ if (!hashbin_find(irttp->tsaps, (long) orig, NULL)) {
+- IRDA_DEBUG(0, "%s(), unable to find TSAP\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), unable to find TSAP\n", __func__);
+ spin_unlock_irqrestore(&irttp->tsaps->hb_spinlock, flags);
+ return NULL;
+ }
+@@ -1447,7 +1447,7 @@ struct tsap_cb *irttp_dup(struct tsap_cb *orig, void *instance)
+ /* Allocate a new instance */
+ new = kmalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
+ if (!new) {
+- IRDA_DEBUG(0, "%s(), unable to kmalloc\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), unable to kmalloc\n", __func__);
+ spin_unlock_irqrestore(&irttp->tsaps->hb_spinlock, flags);
+ return NULL;
+ }
+@@ -1460,7 +1460,7 @@ struct tsap_cb *irttp_dup(struct tsap_cb *orig, void *instance)
+ /* Try to dup the LSAP (may fail if we were too slow) */
+ new->lsap = irlmp_dup(orig->lsap, new);
+ if (!new->lsap) {
+- IRDA_DEBUG(0, "%s(), dup failed!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), dup failed!\n", __func__);
+ kfree(new);
+ return NULL;
+ }
+@@ -1495,7 +1495,7 @@ int irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata,
+
+ /* Already disconnected? */
+ if (!self->connected) {
+- IRDA_DEBUG(4, "%s(), already disconnected!\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s(), already disconnected!\n", __func__);
+ if (userdata)
+ dev_kfree_skb(userdata);
+ return -1;
+@@ -1508,7 +1508,7 @@ int irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata,
+ * Jean II */
+ if(test_and_set_bit(0, &self->disconnect_pend)) {
+ IRDA_DEBUG(0, "%s(), disconnect already pending\n",
+- __FUNCTION__);
++ __func__);
+ if (userdata)
+ dev_kfree_skb(userdata);
+
+@@ -1527,7 +1527,7 @@ int irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata,
+ * disconnecting right now since the data will
+ * not have any usable connection to be sent on
+ */
+- IRDA_DEBUG(1, "%s(): High priority!!()\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(): High priority!!()\n", __func__);
+ irttp_flush_queues(self);
+ } else if (priority == P_NORMAL) {
+ /*
+@@ -1548,7 +1548,7 @@ int irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata,
+ * be sent at the LMP level (so even if the peer has its Tx queue
+ * full of data). - Jean II */
+
+- IRDA_DEBUG(1, "%s(), Disconnecting ...\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), Disconnecting ...\n", __func__);
+ self->connected = FALSE;
+
+ if (!userdata) {
+@@ -1584,7 +1584,7 @@ void irttp_disconnect_indication(void *instance, void *sap, LM_REASON reason,
+ {
+ struct tsap_cb *self;
+
+- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(4, "%s()\n", __func__);
+
+ self = (struct tsap_cb *) instance;
+
+@@ -1644,7 +1644,7 @@ static void irttp_do_data_indication(struct tsap_cb *self, struct sk_buff *skb)
+ * give an error back
+ */
+ if (err) {
+- IRDA_DEBUG(0, "%s() requeueing skb!\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s() requeueing skb!\n", __func__);
+
+ /* Make sure we take a break */
+ self->rx_sdu_busy = TRUE;
+@@ -1669,7 +1669,7 @@ void irttp_run_rx_queue(struct tsap_cb *self)
+ struct sk_buff *skb;
+ int more = 0;
+
+- IRDA_DEBUG(2, "%s() send=%d,avail=%d,remote=%d\n", __FUNCTION__,
++ IRDA_DEBUG(2, "%s() send=%d,avail=%d,remote=%d\n", __func__,
+ self->send_credit, self->avail_credit, self->remote_credit);
+
+ /* Get exclusive access to the rx queue, otherwise don't touch it */
+@@ -1710,7 +1710,7 @@ void irttp_run_rx_queue(struct tsap_cb *self)
+ */
+ if (self->rx_sdu_size <= self->rx_max_sdu_size) {
+ IRDA_DEBUG(4, "%s(), queueing frag\n",
+- __FUNCTION__);
++ __func__);
+ skb_queue_tail(&self->rx_fragments, skb);
+ } else {
+ /* Free the part of the SDU that is too big */
+@@ -1740,7 +1740,7 @@ void irttp_run_rx_queue(struct tsap_cb *self)
+ /* Now we can deliver the reassembled skb */
+ irttp_do_data_indication(self, skb);
+ } else {
+- IRDA_DEBUG(1, "%s(), Truncated frame\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), Truncated frame\n", __func__);
+
+ /* Free the part of the SDU that is too big */
+ dev_kfree_skb(skb);
+diff --git a/net/irda/parameters.c b/net/irda/parameters.c
+index 722bbe0..fc1a205 100644
+--- a/net/irda/parameters.c
++++ b/net/irda/parameters.c
+@@ -148,23 +148,23 @@ static int irda_insert_integer(void *self, __u8 *buf, int len, __u8 pi,
+ */
+ if (p.pl == 0) {
+ if (p.pv.i < 0xff) {
+- IRDA_DEBUG(2, "%s(), using 1 byte\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s(), using 1 byte\n", __func__);
+ p.pl = 1;
+ } else if (p.pv.i < 0xffff) {
+- IRDA_DEBUG(2, "%s(), using 2 bytes\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s(), using 2 bytes\n", __func__);
+ p.pl = 2;
+ } else {
+- IRDA_DEBUG(2, "%s(), using 4 bytes\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s(), using 4 bytes\n", __func__);
+ p.pl = 4; /* Default length */
+ }
+ }
+ /* Check if buffer is long enough for insertion */
+ if (len < (2+p.pl)) {
+ IRDA_WARNING("%s: buffer too short for insertion!\n",
+- __FUNCTION__);
++ __func__);
+ return -1;
+ }
+- IRDA_DEBUG(2, "%s(), pi=%#x, pl=%d, pi=%d\n", __FUNCTION__,
++ IRDA_DEBUG(2, "%s(), pi=%#x, pl=%d, pi=%d\n", __func__,
+ p.pi, p.pl, p.pv.i);
+ switch (p.pl) {
+ case 1:
+@@ -187,7 +187,7 @@ static int irda_insert_integer(void *self, __u8 *buf, int len, __u8 pi,
+ break;
+ default:
+ IRDA_WARNING("%s: length %d not supported\n",
+- __FUNCTION__, p.pl);
++ __func__, p.pl);
+ /* Skip parameter */
+ return -1;
+ }
+@@ -218,7 +218,7 @@ static int irda_extract_integer(void *self, __u8 *buf, int len, __u8 pi,
+ if (len < (2+p.pl)) {
+ IRDA_WARNING("%s: buffer too short for parsing! "
+ "Need %d bytes, but len is only %d\n",
+- __FUNCTION__, p.pl, len);
++ __func__, p.pl, len);
+ return -1;
+ }
+
+@@ -230,7 +230,7 @@ static int irda_extract_integer(void *self, __u8 *buf, int len, __u8 pi,
+ if (((type & PV_MASK) != PV_INTEGER) && ((type & PV_MASK) != p.pl)) {
+ IRDA_ERROR("%s: invalid parameter length! "
+ "Expected %d bytes, but value had %d bytes!\n",
+- __FUNCTION__, type & PV_MASK, p.pl);
++ __func__, type & PV_MASK, p.pl);
+
+ /* Most parameters are bit/byte fields or little endian,
+ * so it's ok to only extract a subset of it (the subset
+@@ -268,13 +268,13 @@ static int irda_extract_integer(void *self, __u8 *buf, int len, __u8 pi,
+ break;
+ default:
+ IRDA_WARNING("%s: length %d not supported\n",
+- __FUNCTION__, p.pl);
++ __func__, p.pl);
+
+ /* Skip parameter */
+ return p.pl+2;
+ }
+
+- IRDA_DEBUG(2, "%s(), pi=%#x, pl=%d, pi=%d\n", __FUNCTION__,
++ IRDA_DEBUG(2, "%s(), pi=%#x, pl=%d, pi=%d\n", __func__,
+ p.pi, p.pl, p.pv.i);
+ /* Call handler for this parameter */
+ err = (*func)(self, &p, PV_PUT);
+@@ -294,19 +294,19 @@ static int irda_extract_string(void *self, __u8 *buf, int len, __u8 pi,
+ irda_param_t p;
+ int err;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s()\n", __func__);
+
+ p.pi = pi; /* In case handler needs to know */
+ p.pl = buf[1]; /* Extract length of value */
+
+- IRDA_DEBUG(2, "%s(), pi=%#x, pl=%d\n", __FUNCTION__,
++ IRDA_DEBUG(2, "%s(), pi=%#x, pl=%d\n", __func__,
+ p.pi, p.pl);
+
+ /* Check if buffer is long enough for parsing */
+ if (len < (2+p.pl)) {
+ IRDA_WARNING("%s: buffer too short for parsing! "
+ "Need %d bytes, but len is only %d\n",
+- __FUNCTION__, p.pl, len);
++ __func__, p.pl, len);
+ return -1;
+ }
+
+@@ -314,7 +314,7 @@ static int irda_extract_string(void *self, __u8 *buf, int len, __u8 pi,
+ * checked that the buffer is long enough */
+ strncpy(str, buf+2, p.pl);
+
+- IRDA_DEBUG(2, "%s(), str=0x%02x 0x%02x\n", __FUNCTION__,
++ IRDA_DEBUG(2, "%s(), str=0x%02x 0x%02x\n", __func__,
+ (__u8) str[0], (__u8) str[1]);
+
+ /* Null terminate string */
+@@ -345,11 +345,11 @@ static int irda_extract_octseq(void *self, __u8 *buf, int len, __u8 pi,
+ if (len < (2+p.pl)) {
+ IRDA_WARNING("%s: buffer too short for parsing! "
+ "Need %d bytes, but len is only %d\n",
+- __FUNCTION__, p.pl, len);
++ __func__, p.pl, len);
+ return -1;
+ }
+
+- IRDA_DEBUG(0, "%s(), not impl\n", __FUNCTION__);
++ IRDA_DEBUG(0, "%s(), not impl\n", __func__);
+
+ return p.pl+2; /* Extracted pl+2 bytes */
+ }
+@@ -473,7 +473,7 @@ int irda_param_insert(void *self, __u8 pi, __u8 *buf, int len,
+ (pi_minor > info->tables[pi_major].len-1))
+ {
+ IRDA_DEBUG(0, "%s(), no handler for parameter=0x%02x\n",
+- __FUNCTION__, pi);
++ __func__, pi);
+
+ /* Skip this parameter */
+ return -1;
+@@ -487,7 +487,7 @@ int irda_param_insert(void *self, __u8 pi, __u8 *buf, int len,
+
+ /* Check if handler has been implemented */
+ if (!pi_minor_info->func) {
+- IRDA_MESSAGE("%s: no handler for pi=%#x\n", __FUNCTION__, pi);
++ IRDA_MESSAGE("%s: no handler for pi=%#x\n", __func__, pi);
+ /* Skip this parameter */
+ return -1;
+ }
+@@ -527,7 +527,7 @@ static int irda_param_extract(void *self, __u8 *buf, int len,
+ (pi_minor > info->tables[pi_major].len-1))
+ {
+ IRDA_DEBUG(0, "%s(), no handler for parameter=0x%02x\n",
+- __FUNCTION__, buf[0]);
++ __func__, buf[0]);
+
+ /* Skip this parameter */
+ return 2 + buf[n + 1]; /* Continue */
+@@ -539,13 +539,13 @@ static int irda_param_extract(void *self, __u8 *buf, int len,
+ /* Find expected data type for this parameter identifier (pi)*/
+ type = pi_minor_info->type;
+
+- IRDA_DEBUG(3, "%s(), pi=[%d,%d], type=%d\n", __FUNCTION__,
++ IRDA_DEBUG(3, "%s(), pi=[%d,%d], type=%d\n", __func__,
+ pi_major, pi_minor, type);
+
+ /* Check if handler has been implemented */
+ if (!pi_minor_info->func) {
+ IRDA_MESSAGE("%s: no handler for pi=%#x\n",
+- __FUNCTION__, buf[n]);
++ __func__, buf[n]);
+ /* Skip this parameter */
+ return 2 + buf[n + 1]; /* Continue */
+ }
+diff --git a/net/irda/qos.c b/net/irda/qos.c
+index aeb18cf..2b00974 100644
+--- a/net/irda/qos.c
++++ b/net/irda/qos.c
+@@ -201,7 +201,7 @@ static int msb_index (__u16 word)
+ * it's very likely the peer. - Jean II */
+ if (word == 0) {
+ IRDA_WARNING("%s(), Detected buggy peer, adjust null PV to 0x1!\n",
+- __FUNCTION__);
++ __func__);
+ /* The only safe choice (we don't know the array size) */
+ word = 0x1;
+ }
+@@ -342,7 +342,7 @@ static void irlap_adjust_qos_settings(struct qos_info *qos)
+ __u32 line_capacity;
+ int index;
+
+- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
++ IRDA_DEBUG(2, "%s()\n", __func__);
+
+ /*
+ * Make sure the mintt is sensible.
+@@ -352,7 +352,7 @@ static void irlap_adjust_qos_settings(struct qos_info *qos)
+ int i;
+
+ IRDA_WARNING("%s(), Detected buggy peer, adjust mtt to %dus!\n",
+- __FUNCTION__, sysctl_min_tx_turn_time);
++ __func__, sysctl_min_tx_turn_time);
+
+ /* We don't really need bits, but easier this way */
+ i = value_highest_bit(sysctl_min_tx_turn_time, min_turn_times,
+@@ -370,7 +370,7 @@ static void irlap_adjust_qos_settings(struct qos_info *qos)
+ {
+ IRDA_DEBUG(0,
+ "%s(), adjusting max turn time from %d to 500 ms\n",
+- __FUNCTION__, qos->max_turn_time.value);
++ __func__, qos->max_turn_time.value);
+ qos->max_turn_time.value = 500;
+ }
+
+@@ -386,7 +386,7 @@ static void irlap_adjust_qos_settings(struct qos_info *qos)
+ while ((qos->data_size.value > line_capacity) && (index > 0)) {
+ qos->data_size.value = data_sizes[index--];
+ IRDA_DEBUG(2, "%s(), reducing data size to %d\n",
+- __FUNCTION__, qos->data_size.value);
++ __func__, qos->data_size.value);
+ }
+ #else /* Use method described in section 6.6.11 of IrLAP */
+ while (irlap_requested_line_capacity(qos) > line_capacity) {
+@@ -396,14 +396,14 @@ static void irlap_adjust_qos_settings(struct qos_info *qos)
+ if (qos->window_size.value > 1) {
+ qos->window_size.value--;
+ IRDA_DEBUG(2, "%s(), reducing window size to %d\n",
+- __FUNCTION__, qos->window_size.value);
++ __func__, qos->window_size.value);
+ } else if (index > 1) {
+ qos->data_size.value = data_sizes[index--];
+ IRDA_DEBUG(2, "%s(), reducing data size to %d\n",
+- __FUNCTION__, qos->data_size.value);
++ __func__, qos->data_size.value);
+ } else {
+ IRDA_WARNING("%s(), nothing more we can do!\n",
+- __FUNCTION__);
++ __func__);
+ }
+ }
+ #endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
+@@ -538,7 +538,7 @@ static int irlap_param_baud_rate(void *instance, irda_param_t *param, int get)
+ if (get) {
+ param->pv.i = self->qos_rx.baud_rate.bits;
+ IRDA_DEBUG(2, "%s(), baud rate = 0x%02x\n",
+- __FUNCTION__, param->pv.i);
++ __func__, param->pv.i);
+ } else {
+ /*
+ * Stations must agree on baud rate, so calculate
+@@ -711,7 +711,7 @@ __u32 irlap_max_line_capacity(__u32 speed, __u32 max_turn_time)
+ int i,j;
+
+ IRDA_DEBUG(2, "%s(), speed=%d, max_turn_time=%d\n",
+- __FUNCTION__, speed, max_turn_time);
++ __func__, speed, max_turn_time);
+
+ i = value_index(speed, baud_rates, 10);
+ j = value_index(max_turn_time, max_turn_times, 4);
+@@ -722,7 +722,7 @@ __u32 irlap_max_line_capacity(__u32 speed, __u32 max_turn_time)
+ line_capacity = max_line_capacities[i][j];
+
+ IRDA_DEBUG(2, "%s(), line capacity=%d bytes\n",
+- __FUNCTION__, line_capacity);
++ __func__, line_capacity);
+
+ return line_capacity;
+ }
+@@ -738,7 +738,7 @@ static __u32 irlap_requested_line_capacity(struct qos_info *qos)
+ qos->min_turn_time.value);
+
+ IRDA_DEBUG(2, "%s(), requested line capacity=%d\n",
+- __FUNCTION__, line_capacity);
++ __func__, line_capacity);
+
+ return line_capacity;
+ }
+diff --git a/net/irda/wrapper.c b/net/irda/wrapper.c
+index c246983..fd0995b 100644
+--- a/net/irda/wrapper.c
++++ b/net/irda/wrapper.c
+@@ -106,16 +106,16 @@ int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize)
+ * Nothing to worry about, but we set the default number of
+ * BOF's
+ */
+- IRDA_DEBUG(1, "%s(), wrong magic in skb!\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), wrong magic in skb!\n", __func__);
+ xbofs = 10;
+ } else
+ xbofs = cb->xbofs + cb->xbofs_delay;
+
+- IRDA_DEBUG(4, "%s(), xbofs=%d\n", __FUNCTION__, xbofs);
++ IRDA_DEBUG(4, "%s(), xbofs=%d\n", __func__, xbofs);
+
+ /* Check that we never use more than 115 + 48 xbofs */
+ if (xbofs > 163) {
+- IRDA_DEBUG(0, "%s(), too many xbofs (%d)\n", __FUNCTION__,
++ IRDA_DEBUG(0, "%s(), too many xbofs (%d)\n", __func__,
+ xbofs);
+ xbofs = 163;
+ }
+@@ -135,7 +135,7 @@ int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize)
+ */
+ if(n >= (buffsize-5)) {
+ IRDA_ERROR("%s(), tx buffer overflow (n=%d)\n",
+- __FUNCTION__, n);
++ __func__, n);
+ return n;
+ }
+
+@@ -287,7 +287,7 @@ async_unwrap_bof(struct net_device *dev,
+ /* Not supposed to happen, the previous frame is not
+ * finished - Jean II */
+ IRDA_DEBUG(1, "%s(), Discarding incomplete frame\n",
+- __FUNCTION__);
++ __func__);
+ stats->rx_errors++;
+ stats->rx_missed_errors++;
+ irda_device_set_media_busy(dev, TRUE);
+@@ -360,7 +360,7 @@ async_unwrap_eof(struct net_device *dev,
+ /* Wrong CRC, discard frame! */
+ irda_device_set_media_busy(dev, TRUE);
+
+- IRDA_DEBUG(1, "%s(), crc error\n", __FUNCTION__);
++ IRDA_DEBUG(1, "%s(), crc error\n", __func__);
+ stats->rx_errors++;
+ stats->rx_crc_errors++;
+ }
+@@ -386,7 +386,7 @@ async_unwrap_ce(struct net_device *dev,
+ break;
+
+ case LINK_ESCAPE:
+- IRDA_WARNING("%s: state not defined\n", __FUNCTION__);
++ IRDA_WARNING("%s: state not defined\n", __func__);
+ break;
+
+ case BEGIN_FRAME:
+@@ -421,7 +421,7 @@ async_unwrap_other(struct net_device *dev,
+ #endif
+ } else {
+ IRDA_DEBUG(1, "%s(), Rx buffer overflow, aborting\n",
+- __FUNCTION__);
++ __func__);
+ rx_buff->state = OUTSIDE_FRAME;
+ }
+ break;
+@@ -440,7 +440,7 @@ async_unwrap_other(struct net_device *dev,
+ rx_buff->state = INSIDE_FRAME;
+ } else {
+ IRDA_DEBUG(1, "%s(), Rx buffer overflow, aborting\n",
+- __FUNCTION__);
++ __func__);
+ rx_buff->state = OUTSIDE_FRAME;
+ }
+ break;
+diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
+index fee22ca..7b0038f 100644
+--- a/net/iucv/af_iucv.c
++++ b/net/iucv/af_iucv.c
+@@ -53,7 +53,7 @@ static int iucv_callback_connreq(struct iucv_path *, u8 ipvmid[8],
+ static void iucv_callback_connrej(struct iucv_path *, u8 ipuser[16]);
+
+ static struct iucv_sock_list iucv_sk_list = {
+- .lock = RW_LOCK_UNLOCKED,
++ .lock = __RW_LOCK_UNLOCKED(iucv_sk_list.lock),
+ .autobind_name = ATOMIC_INIT(0)
+ };
+
+diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c
+index d764f4c..9189707 100644
+--- a/net/iucv/iucv.c
++++ b/net/iucv/iucv.c
+@@ -795,7 +795,6 @@ int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler,
+ union iucv_param *parm;
+ int rc;
+
+- BUG_ON(in_atomic());
+ spin_lock_bh(&iucv_table_lock);
+ iucv_cleanup_queue();
+ parm = iucv_param[smp_processor_id()];
+@@ -1609,13 +1608,10 @@ static int __init iucv_init(void)
+ rc = register_external_interrupt(0x4000, iucv_external_interrupt);
+ if (rc)
+ goto out;
+- rc = bus_register(&iucv_bus);
+- if (rc)
+- goto out_int;
+ iucv_root = s390_root_dev_register("iucv");
+ if (IS_ERR(iucv_root)) {
+ rc = PTR_ERR(iucv_root);
+- goto out_bus;
++ goto out_int;
+ }
+
+ for_each_online_cpu(cpu) {
+@@ -1635,13 +1631,20 @@ static int __init iucv_init(void)
+ goto out_free;
+ }
+ }
+- register_hotcpu_notifier(&iucv_cpu_notifier);
++ rc = register_hotcpu_notifier(&iucv_cpu_notifier);
++ if (rc)
++ goto out_free;
+ ASCEBC(iucv_error_no_listener, 16);
+ ASCEBC(iucv_error_no_memory, 16);
+ ASCEBC(iucv_error_pathid, 16);
+ iucv_available = 1;
++ rc = bus_register(&iucv_bus);
++ if (rc)
++ goto out_cpu;
+ return 0;
+
++out_cpu:
++ unregister_hotcpu_notifier(&iucv_cpu_notifier);
+ out_free:
+ for_each_possible_cpu(cpu) {
+ kfree(iucv_param[cpu]);
+@@ -1650,8 +1653,6 @@ out_free:
+ iucv_irq_data[cpu] = NULL;
+ }
+ s390_root_dev_unregister(iucv_root);
+-out_bus:
+- bus_unregister(&iucv_bus);
+ out_int:
+ unregister_external_interrupt(0x4000, iucv_external_interrupt);
+ out:
+diff --git a/net/key/af_key.c b/net/key/af_key.c
+index e9ef9af..2403a31 100644
+--- a/net/key/af_key.c
++++ b/net/key/af_key.c
+@@ -48,6 +48,17 @@ struct pfkey_sock {
+ struct sock sk;
+ int registered;
+ int promisc;
++
++ struct {
++ uint8_t msg_version;
++ uint32_t msg_pid;
++ int (*dump)(struct pfkey_sock *sk);
++ void (*done)(struct pfkey_sock *sk);
++ union {
++ struct xfrm_policy_walk policy;
++ struct xfrm_state_walk state;
++ } u;
++ } dump;
+ };
+
+ static inline struct pfkey_sock *pfkey_sk(struct sock *sk)
+@@ -55,6 +66,27 @@ static inline struct pfkey_sock *pfkey_sk(struct sock *sk)
+ return (struct pfkey_sock *)sk;
+ }
+
++static int pfkey_can_dump(struct sock *sk)
++{
++ if (3 * atomic_read(&sk->sk_rmem_alloc) <= 2 * sk->sk_rcvbuf)
++ return 1;
++ return 0;
++}
++
++static int pfkey_do_dump(struct pfkey_sock *pfk)
++{
++ int rc;
++
++ rc = pfk->dump.dump(pfk);
++ if (rc == -ENOBUFS)
++ return 0;
++
++ pfk->dump.done(pfk);
++ pfk->dump.dump = NULL;
++ pfk->dump.done = NULL;
++ return rc;
++}
++
+ static void pfkey_sock_destruct(struct sock *sk)
+ {
+ skb_queue_purge(&sk->sk_receive_queue);
+@@ -1709,45 +1741,60 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd
+ return 0;
+ }
+
+-struct pfkey_dump_data
+-{
+- struct sk_buff *skb;
+- struct sadb_msg *hdr;
+- struct sock *sk;
+-};
+-
+ static int dump_sa(struct xfrm_state *x, int count, void *ptr)
+ {
+- struct pfkey_dump_data *data = ptr;
++ struct pfkey_sock *pfk = ptr;
+ struct sk_buff *out_skb;
+ struct sadb_msg *out_hdr;
+
++ if (!pfkey_can_dump(&pfk->sk))
++ return -ENOBUFS;
++
+ out_skb = pfkey_xfrm_state2msg(x);
+ if (IS_ERR(out_skb))
+ return PTR_ERR(out_skb);
+
+ out_hdr = (struct sadb_msg *) out_skb->data;
+- out_hdr->sadb_msg_version = data->hdr->sadb_msg_version;
++ out_hdr->sadb_msg_version = pfk->dump.msg_version;
+ out_hdr->sadb_msg_type = SADB_DUMP;
+ out_hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto);
+ out_hdr->sadb_msg_errno = 0;
+ out_hdr->sadb_msg_reserved = 0;
+ out_hdr->sadb_msg_seq = count;
+- out_hdr->sadb_msg_pid = data->hdr->sadb_msg_pid;
+- pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, data->sk);
++ out_hdr->sadb_msg_pid = pfk->dump.msg_pid;
++ pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, &pfk->sk);
+ return 0;
+ }
+
++static int pfkey_dump_sa(struct pfkey_sock *pfk)
++{
++ return xfrm_state_walk(&pfk->dump.u.state, dump_sa, (void *) pfk);
++}
++
++static void pfkey_dump_sa_done(struct pfkey_sock *pfk)
++{
++ xfrm_state_walk_done(&pfk->dump.u.state);
++}
++
+ static int pfkey_dump(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+ {
+ u8 proto;
+- struct pfkey_dump_data data = { .skb = skb, .hdr = hdr, .sk = sk };
++ struct pfkey_sock *pfk = pfkey_sk(sk);
++
++ if (pfk->dump.dump != NULL)
++ return -EBUSY;
+
+ proto = pfkey_satype2proto(hdr->sadb_msg_satype);
+ if (proto == 0)
+ return -EINVAL;
+
+- return xfrm_state_walk(proto, dump_sa, &data);
++ pfk->dump.msg_version = hdr->sadb_msg_version;
++ pfk->dump.msg_pid = hdr->sadb_msg_pid;
++ pfk->dump.dump = pfkey_dump_sa;
++ pfk->dump.done = pfkey_dump_sa_done;
++ xfrm_state_walk_init(&pfk->dump.u.state, proto);
++
++ return pfkey_do_dump(pfk);
+ }
+
+ static int pfkey_promisc(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+@@ -1780,7 +1827,9 @@ static int check_reqid(struct xfrm_policy *xp, int dir, int count, void *ptr)
+
+ static u32 gen_reqid(void)
+ {
++ struct xfrm_policy_walk walk;
+ u32 start;
++ int rc;
+ static u32 reqid = IPSEC_MANUAL_REQID_MAX;
+
+ start = reqid;
+@@ -1788,8 +1837,10 @@ static u32 gen_reqid(void)
+ ++reqid;
+ if (reqid == 0)
+ reqid = IPSEC_MANUAL_REQID_MAX+1;
+- if (xfrm_policy_walk(XFRM_POLICY_TYPE_MAIN, check_reqid,
+- (void*)&reqid) != -EEXIST)
++ xfrm_policy_walk_init(&walk, XFRM_POLICY_TYPE_MAIN);
++ rc = xfrm_policy_walk(&walk, check_reqid, (void*)&reqid);
++ xfrm_policy_walk_done(&walk);
++ if (rc != -EEXIST)
+ return reqid;
+ } while (reqid != start);
+ return 0;
+@@ -1856,7 +1907,7 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
+ t->encap_family = xp->family;
+
+ /* No way to set this via kame pfkey */
+- t->aalgos = t->ealgos = t->calgos = ~0;
++ t->allalgs = 1;
+ xp->xfrm_nr++;
+ return 0;
+ }
+@@ -2241,7 +2292,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
+ goto out;
+ }
+
+- err = security_xfrm_policy_alloc(xp, uctx);
++ err = security_xfrm_policy_alloc(&xp->security, uctx);
+ kfree(uctx);
+
+ if (err)
+@@ -2301,10 +2352,11 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
+ int err;
+ struct sadb_address *sa;
+ struct sadb_x_policy *pol;
+- struct xfrm_policy *xp, tmp;
++ struct xfrm_policy *xp;
+ struct xfrm_selector sel;
+ struct km_event c;
+ struct sadb_x_sec_ctx *sec_ctx;
++ struct xfrm_sec_ctx *pol_ctx = NULL;
+
+ if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
+ ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||
+@@ -2334,25 +2386,22 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
+ sel.dport_mask = htons(0xffff);
+
+ sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
+- memset(&tmp, 0, sizeof(struct xfrm_policy));
+-
+ if (sec_ctx != NULL) {
+ struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
+
+ if (!uctx)
+ return -ENOMEM;
+
+- err = security_xfrm_policy_alloc(&tmp, uctx);
++ err = security_xfrm_policy_alloc(&pol_ctx, uctx);
+ kfree(uctx);
+-
+ if (err)
+ return err;
+ }
+
+- xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN, pol->sadb_x_policy_dir-1,
+- &sel, tmp.security, 1, &err);
+- security_xfrm_policy_free(&tmp);
+-
++ xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN,
++ pol->sadb_x_policy_dir - 1, &sel, pol_ctx,
++ 1, &err);
++ security_xfrm_policy_free(pol_ctx);
+ if (xp == NULL)
+ return -ENOENT;
+
+@@ -2638,11 +2687,14 @@ out:
+
+ static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr)
+ {
+- struct pfkey_dump_data *data = ptr;
++ struct pfkey_sock *pfk = ptr;
+ struct sk_buff *out_skb;
+ struct sadb_msg *out_hdr;
+ int err;
+
++ if (!pfkey_can_dump(&pfk->sk))
++ return -ENOBUFS;
++
+ out_skb = pfkey_xfrm_policy2msg_prep(xp);
+ if (IS_ERR(out_skb))
+ return PTR_ERR(out_skb);
+@@ -2652,21 +2704,40 @@ static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr)
+ return err;
+
+ out_hdr = (struct sadb_msg *) out_skb->data;
+- out_hdr->sadb_msg_version = data->hdr->sadb_msg_version;
++ out_hdr->sadb_msg_version = pfk->dump.msg_version;
+ out_hdr->sadb_msg_type = SADB_X_SPDDUMP;
+ out_hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC;
+ out_hdr->sadb_msg_errno = 0;
+ out_hdr->sadb_msg_seq = count;
+- out_hdr->sadb_msg_pid = data->hdr->sadb_msg_pid;
+- pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, data->sk);
++ out_hdr->sadb_msg_pid = pfk->dump.msg_pid;
++ pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, &pfk->sk);
+ return 0;
+ }
+
++static int pfkey_dump_sp(struct pfkey_sock *pfk)
++{
++ return xfrm_policy_walk(&pfk->dump.u.policy, dump_sp, (void *) pfk);
++}
++
++static void pfkey_dump_sp_done(struct pfkey_sock *pfk)
++{
++ xfrm_policy_walk_done(&pfk->dump.u.policy);
++}
++
+ static int pfkey_spddump(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+ {
+- struct pfkey_dump_data data = { .skb = skb, .hdr = hdr, .sk = sk };
++ struct pfkey_sock *pfk = pfkey_sk(sk);
++
++ if (pfk->dump.dump != NULL)
++ return -EBUSY;
++
++ pfk->dump.msg_version = hdr->sadb_msg_version;
++ pfk->dump.msg_pid = hdr->sadb_msg_pid;
++ pfk->dump.dump = pfkey_dump_sp;
++ pfk->dump.done = pfkey_dump_sp_done;
++ xfrm_policy_walk_init(&pfk->dump.u.policy, XFRM_POLICY_TYPE_MAIN);
+
+- return xfrm_policy_walk(XFRM_POLICY_TYPE_MAIN, dump_sp, &data);
++ return pfkey_do_dump(pfk);
+ }
+
+ static int key_notify_policy_flush(struct km_event *c)
+@@ -3225,7 +3296,7 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt,
+ if ((*dir = verify_sec_ctx_len(p)))
+ goto out;
+ uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
+- *dir = security_xfrm_policy_alloc(xp, uctx);
++ *dir = security_xfrm_policy_alloc(&xp->security, uctx);
+ kfree(uctx);
+
+ if (*dir)
+@@ -3671,6 +3742,7 @@ static int pfkey_recvmsg(struct kiocb *kiocb,
+ int flags)
+ {
+ struct sock *sk = sock->sk;
++ struct pfkey_sock *pfk = pfkey_sk(sk);
+ struct sk_buff *skb;
+ int copied, err;
+
+@@ -3698,6 +3770,10 @@ static int pfkey_recvmsg(struct kiocb *kiocb,
+
+ err = (flags & MSG_TRUNC) ? skb->len : copied;
+
++ if (pfk->dump.dump != NULL &&
++ 3 * atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf)
++ pfkey_do_dump(pfk);
++
+ out_free:
+ skb_free_datagram(sk, skb);
+ out:
+diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
+index 8c50eb4..97101dc 100644
+--- a/net/llc/af_llc.c
++++ b/net/llc/af_llc.c
+@@ -188,7 +188,7 @@ static int llc_ui_release(struct socket *sock)
+ sock_hold(sk);
+ lock_sock(sk);
+ llc = llc_sk(sk);
+- dprintk("%s: closing local(%02X) remote(%02X)\n", __FUNCTION__,
++ dprintk("%s: closing local(%02X) remote(%02X)\n", __func__,
+ llc->laddr.lsap, llc->daddr.lsap);
+ if (!llc_send_disc(sk))
+ llc_ui_wait_for_disc(sk, sk->sk_rcvtimeo);
+@@ -298,7 +298,7 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
+ struct llc_sap *sap;
+ int rc = -EINVAL;
+
+- dprintk("%s: binding %02X\n", __FUNCTION__, addr->sllc_sap);
++ dprintk("%s: binding %02X\n", __func__, addr->sllc_sap);
+ if (unlikely(!sock_flag(sk, SOCK_ZAPPED) || addrlen != sizeof(*addr)))
+ goto out;
+ rc = -EAFNOSUPPORT;
+@@ -435,7 +435,7 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr,
+ rc = llc_establish_connection(sk, llc->dev->dev_addr,
+ addr->sllc_mac, addr->sllc_sap);
+ if (rc) {
+- dprintk("%s: llc_ui_send_conn failed :-(\n", __FUNCTION__);
++ dprintk("%s: llc_ui_send_conn failed :-(\n", __func__);
+ sock->state = SS_UNCONNECTED;
+ sk->sk_state = TCP_CLOSE;
+ goto out;
+@@ -607,7 +607,7 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags)
+ struct sk_buff *skb;
+ int rc = -EOPNOTSUPP;
+
+- dprintk("%s: accepting on %02X\n", __FUNCTION__,
++ dprintk("%s: accepting on %02X\n", __func__,
+ llc_sk(sk)->laddr.lsap);
+ lock_sock(sk);
+ if (unlikely(sk->sk_type != SOCK_STREAM))
+@@ -622,7 +622,7 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags)
+ if (rc)
+ goto out;
+ }
+- dprintk("%s: got a new connection on %02X\n", __FUNCTION__,
++ dprintk("%s: got a new connection on %02X\n", __func__,
+ llc_sk(sk)->laddr.lsap);
+ skb = skb_dequeue(&sk->sk_receive_queue);
+ rc = -EINVAL;
+@@ -643,7 +643,7 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags)
+ /* put original socket back into a clean listen state. */
+ sk->sk_state = TCP_LISTEN;
+ sk->sk_ack_backlog--;
+- dprintk("%s: ok success on %02X, client on %02X\n", __FUNCTION__,
++ dprintk("%s: ok success on %02X, client on %02X\n", __func__,
+ llc_sk(sk)->addr.sllc_sap, newllc->daddr.lsap);
+ frees:
+ kfree_skb(skb);
+@@ -836,7 +836,7 @@ static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock,
+ size_t size = 0;
+ int rc = -EINVAL, copied = 0, hdrlen;
+
+- dprintk("%s: sending from %02X to %02X\n", __FUNCTION__,
++ dprintk("%s: sending from %02X to %02X\n", __func__,
+ llc->laddr.lsap, llc->daddr.lsap);
+ lock_sock(sk);
+ if (addr) {
+@@ -894,7 +894,7 @@ out:
+ kfree_skb(skb);
+ release:
+ dprintk("%s: failed sending from %02X to %02X: %d\n",
+- __FUNCTION__, llc->laddr.lsap, llc->daddr.lsap, rc);
++ __func__, llc->laddr.lsap, llc->daddr.lsap, rc);
+ }
+ release_sock(sk);
+ return rc ? : copied;
+diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c
+index 71a0022..019c780 100644
+--- a/net/llc/llc_c_ac.c
++++ b/net/llc/llc_c_ac.c
+@@ -1430,7 +1430,7 @@ static void llc_process_tmr_ev(struct sock *sk, struct sk_buff *skb)
+ {
+ if (llc_sk(sk)->state == LLC_CONN_OUT_OF_SVC) {
+ printk(KERN_WARNING "%s: timer called on closed connection\n",
+- __FUNCTION__);
++ __func__);
+ kfree_skb(skb);
+ } else {
+ if (!sock_owned_by_user(sk))
+diff --git a/net/llc/llc_c_ev.c b/net/llc/llc_c_ev.c
+index c5deda2..523fdd1 100644
+--- a/net/llc/llc_c_ev.c
++++ b/net/llc/llc_c_ev.c
+@@ -228,7 +228,7 @@ int llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns(struct sock *sk,
+ llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
+ if (!rc)
+ dprintk("%s: matched, state=%d, ns=%d, vr=%d\n",
+- __FUNCTION__, llc_sk(sk)->state, ns, vr);
++ __func__, llc_sk(sk)->state, ns, vr);
+ return rc;
+ }
+
+@@ -306,7 +306,7 @@ int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk,
+ llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
+ if (!rc)
+ dprintk("%s: matched, state=%d, ns=%d, vr=%d\n",
+- __FUNCTION__, llc_sk(sk)->state, ns, vr);
++ __func__, llc_sk(sk)->state, ns, vr);
+ return rc;
+ }
+
+@@ -511,7 +511,7 @@ int llc_conn_ev_rx_zzz_cmd_pbit_set_x_inval_nr(struct sock *sk,
+ (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) &&
+ nr != vs && llc_util_nr_inside_tx_window(sk, nr)) {
+ dprintk("%s: matched, state=%d, vs=%d, nr=%d\n",
+- __FUNCTION__, llc_sk(sk)->state, vs, nr);
++ __func__, llc_sk(sk)->state, vs, nr);
+ rc = 0;
+ }
+ return rc;
+@@ -530,7 +530,7 @@ int llc_conn_ev_rx_zzz_rsp_fbit_set_x_inval_nr(struct sock *sk,
+ nr != vs && llc_util_nr_inside_tx_window(sk, nr)) {
+ rc = 0;
+ dprintk("%s: matched, state=%d, vs=%d, nr=%d\n",
+- __FUNCTION__, llc_sk(sk)->state, vs, nr);
++ __func__, llc_sk(sk)->state, vs, nr);
+ }
+ return rc;
+ }
+diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c
+index 441bc18..5c6d89c 100644
+--- a/net/llc/llc_conn.c
++++ b/net/llc/llc_conn.c
+@@ -73,7 +73,7 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
+ */
+ rc = llc_conn_service(skb->sk, skb);
+ if (unlikely(rc != 0)) {
+- printk(KERN_ERR "%s: llc_conn_service failed\n", __FUNCTION__);
++ printk(KERN_ERR "%s: llc_conn_service failed\n", __func__);
+ goto out_kfree_skb;
+ }
+
+@@ -99,7 +99,7 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
+ * shouldn't happen
+ */
+ printk(KERN_ERR "%s: sock_queue_rcv_skb failed!\n",
+- __FUNCTION__);
++ __func__);
+ kfree_skb(skb);
+ }
+ break;
+@@ -132,13 +132,13 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
+ * FIXME:
+ * RESET is not being notified to upper layers for now
+ */
+- printk(KERN_INFO "%s: received a reset ind!\n", __FUNCTION__);
++ printk(KERN_INFO "%s: received a reset ind!\n", __func__);
+ kfree_skb(skb);
+ break;
+ default:
+ if (ev->ind_prim) {
+ printk(KERN_INFO "%s: received unknown %d prim!\n",
+- __FUNCTION__, ev->ind_prim);
++ __func__, ev->ind_prim);
+ kfree_skb(skb);
+ }
+ /* No indication */
+@@ -179,12 +179,12 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
+ * FIXME:
+ * RESET is not being notified to upper layers for now
+ */
+- printk(KERN_INFO "%s: received a reset conf!\n", __FUNCTION__);
++ printk(KERN_INFO "%s: received a reset conf!\n", __func__);
+ break;
+ default:
+ if (ev->cfm_prim) {
+ printk(KERN_INFO "%s: received unknown %d prim!\n",
+- __FUNCTION__, ev->cfm_prim);
++ __func__, ev->cfm_prim);
+ break;
+ }
+ goto out_skb_put; /* No confirmation */
+@@ -700,7 +700,7 @@ static struct sock *llc_create_incoming_sock(struct sock *sk,
+ struct llc_addr *saddr,
+ struct llc_addr *daddr)
+ {
+- struct sock *newsk = llc_sk_alloc(sk->sk_net, sk->sk_family, GFP_ATOMIC,
++ struct sock *newsk = llc_sk_alloc(sock_net(sk), sk->sk_family, GFP_ATOMIC,
+ sk->sk_prot);
+ struct llc_sock *newllc, *llc = llc_sk(sk);
+
+@@ -759,7 +759,7 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)
+ if (!sock_owned_by_user(sk))
+ llc_conn_rcv(sk, skb);
+ else {
+- dprintk("%s: adding to backlog...\n", __FUNCTION__);
++ dprintk("%s: adding to backlog...\n", __func__);
+ llc_set_backlog_type(skb, LLC_PACKET);
+ sk_add_backlog(sk, skb);
+ }
+@@ -807,7 +807,7 @@ static int llc_backlog_rcv(struct sock *sk, struct sk_buff *skb)
+ else
+ goto out_kfree_skb;
+ } else {
+- printk(KERN_ERR "%s: invalid skb in backlog\n", __FUNCTION__);
++ printk(KERN_ERR "%s: invalid skb in backlog\n", __func__);
+ goto out_kfree_skb;
+ }
+ out:
+@@ -874,7 +874,7 @@ struct sock *llc_sk_alloc(struct net *net, int family, gfp_t priority, struct pr
+ #ifdef LLC_REFCNT_DEBUG
+ atomic_inc(&llc_sock_nr);
+ printk(KERN_DEBUG "LLC socket %p created in %s, now we have %d alive\n", sk,
+- __FUNCTION__, atomic_read(&llc_sock_nr));
++ __func__, atomic_read(&llc_sock_nr));
+ #endif
+ out:
+ return sk;
+@@ -894,7 +894,7 @@ void llc_sk_free(struct sock *sk)
+ /* Stop all (possibly) running timers */
+ llc_conn_ac_stop_all_timers(sk, NULL);
+ #ifdef DEBUG_LLC_CONN_ALLOC
+- printk(KERN_INFO "%s: unackq=%d, txq=%d\n", __FUNCTION__,
++ printk(KERN_INFO "%s: unackq=%d, txq=%d\n", __func__,
+ skb_queue_len(&llc->pdu_unack_q),
+ skb_queue_len(&sk->sk_write_queue));
+ #endif
+@@ -904,13 +904,13 @@ void llc_sk_free(struct sock *sk)
+ #ifdef LLC_REFCNT_DEBUG
+ if (atomic_read(&sk->sk_refcnt) != 1) {
+ printk(KERN_DEBUG "Destruction of LLC sock %p delayed in %s, cnt=%d\n",
+- sk, __FUNCTION__, atomic_read(&sk->sk_refcnt));
++ sk, __func__, atomic_read(&sk->sk_refcnt));
+ printk(KERN_DEBUG "%d LLC sockets are still alive\n",
+ atomic_read(&llc_sock_nr));
+ } else {
+ atomic_dec(&llc_sock_nr);
+ printk(KERN_DEBUG "LLC socket %p released in %s, %d are still alive\n", sk,
+- __FUNCTION__, atomic_read(&llc_sock_nr));
++ __func__, atomic_read(&llc_sock_nr));
+ }
+ #endif
+ sock_put(sk);
+diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c
+index bfd2567..1c45f17 100644
+--- a/net/llc/llc_input.c
++++ b/net/llc/llc_input.c
+@@ -150,7 +150,7 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
+ int (*rcv)(struct sk_buff *, struct net_device *,
+ struct packet_type *, struct net_device *);
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ goto drop;
+
+ /*
+@@ -158,7 +158,7 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
+ * receives, do not try to analyse it.
+ */
+ if (unlikely(skb->pkt_type == PACKET_OTHERHOST)) {
+- dprintk("%s: PACKET_OTHERHOST\n", __FUNCTION__);
++ dprintk("%s: PACKET_OTHERHOST\n", __func__);
+ goto drop;
+ }
+ skb = skb_share_check(skb, GFP_ATOMIC);
+@@ -171,7 +171,7 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
+ goto handle_station;
+ sap = llc_sap_find(pdu->dsap);
+ if (unlikely(!sap)) {/* unknown SAP */
+- dprintk("%s: llc_sap_find(%02X) failed!\n", __FUNCTION__,
++ dprintk("%s: llc_sap_find(%02X) failed!\n", __func__,
+ pdu->dsap);
+ goto drop;
+ }
+diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
+index 45c7c0c..520a518 100644
+--- a/net/mac80211/Kconfig
++++ b/net/mac80211/Kconfig
+@@ -32,15 +32,6 @@ config MAC80211_RC_DEFAULT_PID
+ default rate control algorithm. You should choose
+ this unless you know what you are doing.
+
+-config MAC80211_RC_DEFAULT_SIMPLE
+- bool "Simple rate control algorithm"
+- select MAC80211_RC_SIMPLE
+- ---help---
+- Select the simple rate control as the default rate
+- control algorithm. Note that this is a non-responsive,
+- dumb algorithm. You should choose the PID rate control
+- instead.
+-
+ config MAC80211_RC_DEFAULT_NONE
+ bool "No default algorithm"
+ depends on EMBEDDED
+@@ -57,7 +48,6 @@ comment "build the algorithm into mac80211."
+ config MAC80211_RC_DEFAULT
+ string
+ default "pid" if MAC80211_RC_DEFAULT_PID
+- default "simple" if MAC80211_RC_DEFAULT_SIMPLE
+ default ""
+
+ config MAC80211_RC_PID
+@@ -70,16 +60,16 @@ config MAC80211_RC_PID
+ Say Y or M unless you're sure you want to use a
+ different rate control algorithm.
+
+-config MAC80211_RC_SIMPLE
+- tristate "Simple rate control algorithm (DEPRECATED)"
++endmenu
++
++config MAC80211_MESH
++ bool "Enable mac80211 mesh networking (pre-802.11s) support"
++ depends on MAC80211 && EXPERIMENTAL
+ ---help---
+- This option enables a very simple, non-responsive TX
+- rate control algorithm. This algorithm is deprecated
+- and will be removed from the kernel in the near future.
+- It has been replaced by the PID algorithm.
++ This options enables support of Draft 802.11s mesh networking.
++ The implementation is based on Draft 1.08 of the Mesh Networking
++ amendment. For more information visit http://o11s.org/.
+
+- Say N unless you know what you are doing.
+-endmenu
+
+ config MAC80211_LEDS
+ bool "Enable LED triggers"
+@@ -166,3 +156,10 @@ config MAC80211_VERBOSE_PS_DEBUG
+ ---help---
+ Say Y here to print out verbose powersave
+ mode debug messages.
++
++config MAC80211_VERBOSE_MPL_DEBUG
++ bool "Verbose mesh peer link debugging"
++ depends on MAC80211_DEBUG && MAC80211_MESH
++ ---help---
++ Say Y here to print out verbose mesh peer link
++ debug messages.
+diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
+index 54f46bc..4e5847f 100644
+--- a/net/mac80211/Makefile
++++ b/net/mac80211/Makefile
+@@ -10,16 +10,15 @@ rc-pid-m := rc80211_pid.o
+
+ # mac80211 objects
+ mac80211-y := \
+- ieee80211.o \
+- ieee80211_ioctl.o \
++ main.o \
++ wext.o \
+ sta_info.o \
+ wep.o \
+ wpa.o \
+- ieee80211_sta.o \
+- ieee80211_iface.o \
+- ieee80211_rate.o \
++ mlme.o \
++ iface.o \
++ rate.o \
+ michael.o \
+- regdomain.o \
+ tkip.o \
+ aes_ccm.o \
+ cfg.o \
+@@ -29,7 +28,7 @@ mac80211-y := \
+ util.o \
+ event.o
+
+-mac80211-$(CONFIG_MAC80211_LEDS) += ieee80211_led.o
++mac80211-$(CONFIG_MAC80211_LEDS) += led.o
+ mac80211-$(CONFIG_NET_SCHED) += wme.o
+ mac80211-$(CONFIG_MAC80211_DEBUGFS) += \
+ debugfs.o \
+@@ -37,11 +36,15 @@ mac80211-$(CONFIG_MAC80211_DEBUGFS) += \
+ debugfs_netdev.o \
+ debugfs_key.o
+
++mac80211-$(CONFIG_MAC80211_MESH) += \
++ mesh.o \
++ mesh_pathtbl.o \
++ mesh_plink.o \
++ mesh_hwmp.o
++
+
+ # Build rate control algorithm(s)
+-CFLAGS_rc80211_simple.o += -DRC80211_SIMPLE_COMPILE
+ CFLAGS_rc80211_pid_algo.o += -DRC80211_PID_COMPILE
+-mac80211-$(CONFIG_MAC80211_RC_SIMPLE) += rc80211_simple.o
+ mac80211-$(CONFIG_MAC80211_RC_PID) += $(rc-pid-$(CONFIG_MAC80211_RC_PID))
+
+ # Modular rate algorithms are assigned to mac80211-m - make separate modules
+diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
+index e62fe55..59f1691 100644
+--- a/net/mac80211/aes_ccm.c
++++ b/net/mac80211/aes_ccm.c
+@@ -13,7 +13,7 @@
+ #include <linux/err.h>
+
+ #include <net/mac80211.h>
+-#include "ieee80211_key.h"
++#include "key.h"
+ #include "aes_ccm.h"
+
+
+diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
+index 22c9619..699d97b 100644
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -14,7 +14,8 @@
+ #include <net/cfg80211.h>
+ #include "ieee80211_i.h"
+ #include "cfg.h"
+-#include "ieee80211_rate.h"
++#include "rate.h"
++#include "mesh.h"
+
+ static enum ieee80211_if_types
+ nl80211_type_to_mac80211_type(enum nl80211_iftype type)
+@@ -28,16 +29,26 @@ nl80211_type_to_mac80211_type(enum nl80211_iftype type)
+ return IEEE80211_IF_TYPE_STA;
+ case NL80211_IFTYPE_MONITOR:
+ return IEEE80211_IF_TYPE_MNTR;
++#ifdef CONFIG_MAC80211_MESH
++ case NL80211_IFTYPE_MESH_POINT:
++ return IEEE80211_IF_TYPE_MESH_POINT;
++#endif
++ case NL80211_IFTYPE_WDS:
++ return IEEE80211_IF_TYPE_WDS;
+ default:
+ return IEEE80211_IF_TYPE_INVALID;
+ }
+ }
+
+ static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
+- enum nl80211_iftype type)
++ enum nl80211_iftype type, u32 *flags,
++ struct vif_params *params)
+ {
+ struct ieee80211_local *local = wiphy_priv(wiphy);
+ enum ieee80211_if_types itype;
++ struct net_device *dev;
++ struct ieee80211_sub_if_data *sdata;
++ int err;
+
+ if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
+ return -ENODEV;
+@@ -46,7 +57,13 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
+ if (itype == IEEE80211_IF_TYPE_INVALID)
+ return -EINVAL;
+
+- return ieee80211_if_add(local->mdev, name, NULL, itype);
++ err = ieee80211_if_add(local->mdev, name, &dev, itype, params);
++ if (err || itype != IEEE80211_IF_TYPE_MNTR || !flags)
++ return err;
++
++ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ sdata->u.mntr_flags = *flags;
++ return 0;
+ }
+
+ static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
+@@ -69,7 +86,8 @@ static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
+ }
+
+ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
+- enum nl80211_iftype type)
++ enum nl80211_iftype type, u32 *flags,
++ struct vif_params *params)
+ {
+ struct ieee80211_local *local = wiphy_priv(wiphy);
+ struct net_device *dev;
+@@ -99,6 +117,15 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
+ ieee80211_if_reinit(dev);
+ ieee80211_if_set_type(dev, itype);
+
++ if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len)
++ ieee80211_if_sta_set_mesh_id(&sdata->u.sta,
++ params->mesh_id_len,
++ params->mesh_id);
++
++ if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR || !flags)
++ return 0;
++
++ sdata->u.mntr_flags = *flags;
+ return 0;
+ }
+
+@@ -109,7 +136,8 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+ struct ieee80211_sub_if_data *sdata;
+ struct sta_info *sta = NULL;
+ enum ieee80211_key_alg alg;
+- int ret;
++ struct ieee80211_key *key;
++ int err;
+
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+@@ -128,21 +156,28 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+ return -EINVAL;
+ }
+
++ key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key);
++ if (!key)
++ return -ENOMEM;
++
++ rcu_read_lock();
++
+ if (mac_addr) {
+ sta = sta_info_get(sdata->local, mac_addr);
+- if (!sta)
+- return -ENOENT;
++ if (!sta) {
++ ieee80211_key_free(key);
++ err = -ENOENT;
++ goto out_unlock;
++ }
+ }
+
+- ret = 0;
+- if (!ieee80211_key_alloc(sdata, sta, alg, key_idx,
+- params->key_len, params->key))
+- ret = -ENOMEM;
++ ieee80211_key_link(key, sdata, sta);
+
+- if (sta)
+- sta_info_put(sta);
++ err = 0;
++ out_unlock:
++ rcu_read_unlock();
+
+- return ret;
++ return err;
+ }
+
+ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+@@ -154,27 +189,37 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
++ rcu_read_lock();
++
+ if (mac_addr) {
++ ret = -ENOENT;
++
+ sta = sta_info_get(sdata->local, mac_addr);
+ if (!sta)
+- return -ENOENT;
++ goto out_unlock;
+
+- ret = 0;
+- if (sta->key)
++ if (sta->key) {
+ ieee80211_key_free(sta->key);
+- else
+- ret = -ENOENT;
++ WARN_ON(sta->key);
++ ret = 0;
++ }
+
+- sta_info_put(sta);
+- return ret;
++ goto out_unlock;
+ }
+
+- if (!sdata->keys[key_idx])
+- return -ENOENT;
++ if (!sdata->keys[key_idx]) {
++ ret = -ENOENT;
++ goto out_unlock;
++ }
+
+ ieee80211_key_free(sdata->keys[key_idx]);
++ WARN_ON(sdata->keys[key_idx]);
+
+- return 0;
++ ret = 0;
++ out_unlock:
++ rcu_read_unlock();
++
++ return ret;
+ }
+
+ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+@@ -191,6 +236,8 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+ u16 iv16;
+ int err = -ENOENT;
+
++ rcu_read_lock();
++
+ if (mac_addr) {
+ sta = sta_info_get(sdata->local, mac_addr);
+ if (!sta)
+@@ -254,8 +301,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+ err = 0;
+
+ out:
+- if (sta)
+- sta_info_put(sta);
++ rcu_read_unlock();
+ return err;
+ }
+
+@@ -265,35 +311,83 @@ static int ieee80211_config_default_key(struct wiphy *wiphy,
+ {
+ struct ieee80211_sub_if_data *sdata;
+
++ rcu_read_lock();
++
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ ieee80211_set_default_key(sdata, key_idx);
+
++ rcu_read_unlock();
++
+ return 0;
+ }
+
++static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
++{
++ struct ieee80211_sub_if_data *sdata = sta->sdata;
++
++ sinfo->filled = STATION_INFO_INACTIVE_TIME |
++ STATION_INFO_RX_BYTES |
++ STATION_INFO_TX_BYTES;
++
++ sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
++ sinfo->rx_bytes = sta->rx_bytes;
++ sinfo->tx_bytes = sta->tx_bytes;
++
++ if (ieee80211_vif_is_mesh(&sdata->vif)) {
++#ifdef CONFIG_MAC80211_MESH
++ sinfo->filled |= STATION_INFO_LLID |
++ STATION_INFO_PLID |
++ STATION_INFO_PLINK_STATE;
++
++ sinfo->llid = le16_to_cpu(sta->llid);
++ sinfo->plid = le16_to_cpu(sta->plid);
++ sinfo->plink_state = sta->plink_state;
++#endif
++ }
++}
++
++
++static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
++ int idx, u8 *mac, struct station_info *sinfo)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct sta_info *sta;
++ int ret = -ENOENT;
++
++ rcu_read_lock();
++
++ sta = sta_info_get_by_idx(local, idx, dev);
++ if (sta) {
++ ret = 0;
++ memcpy(mac, sta->addr, ETH_ALEN);
++ sta_set_sinfo(sta, sinfo);
++ }
++
++ rcu_read_unlock();
++
++ return ret;
++}
++
+ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
+- u8 *mac, struct station_stats *stats)
++ u8 *mac, struct station_info *sinfo)
+ {
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct sta_info *sta;
++ int ret = -ENOENT;
+
+- sta = sta_info_get(local, mac);
+- if (!sta)
+- return -ENOENT;
++ rcu_read_lock();
+
+ /* XXX: verify sta->dev == dev */
+
+- stats->filled = STATION_STAT_INACTIVE_TIME |
+- STATION_STAT_RX_BYTES |
+- STATION_STAT_TX_BYTES;
+-
+- stats->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
+- stats->rx_bytes = sta->rx_bytes;
+- stats->tx_bytes = sta->tx_bytes;
++ sta = sta_info_get(local, mac);
++ if (sta) {
++ ret = 0;
++ sta_set_sinfo(sta, sinfo);
++ }
+
+- sta_info_put(sta);
++ rcu_read_unlock();
+
+- return 0;
++ return ret;
+ }
+
+ /*
+@@ -486,8 +580,8 @@ static void ieee80211_send_layer2_update(struct sta_info *sta)
+ msg->xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */
+ msg->xid_info[2] = 0; /* XID sender's receive window size (RW) */
+
+- skb->dev = sta->dev;
+- skb->protocol = eth_type_trans(skb, sta->dev);
++ skb->dev = sta->sdata->dev;
++ skb->protocol = eth_type_trans(skb, sta->sdata->dev);
+ memset(skb->cb, 0, sizeof(skb->cb));
+ netif_rx(skb);
+ }
+@@ -498,7 +592,14 @@ static void sta_apply_parameters(struct ieee80211_local *local,
+ {
+ u32 rates;
+ int i, j;
+- struct ieee80211_hw_mode *mode;
++ struct ieee80211_supported_band *sband;
++ struct ieee80211_sub_if_data *sdata = sta->sdata;
++
++ /*
++ * FIXME: updating the flags is racy when this function is
++ * called from ieee80211_change_station(), this will
++ * be resolved in a future patch.
++ */
+
+ if (params->station_flags & STATION_FLAG_CHANGED) {
+ sta->flags &= ~WLAN_STA_AUTHORIZED;
+@@ -514,6 +615,13 @@ static void sta_apply_parameters(struct ieee80211_local *local,
+ sta->flags |= WLAN_STA_WME;
+ }
+
++ /*
++ * FIXME: updating the following information is racy when this
++ * function is called from ieee80211_change_station().
++ * However, all this information should be static so
++ * maybe we should just reject attemps to change it.
++ */
++
+ if (params->aid) {
+ sta->aid = params->aid;
+ if (sta->aid > IEEE80211_MAX_AID)
+@@ -525,15 +633,27 @@ static void sta_apply_parameters(struct ieee80211_local *local,
+
+ if (params->supported_rates) {
+ rates = 0;
+- mode = local->oper_hw_mode;
++ sband = local->hw.wiphy->bands[local->oper_channel->band];
++
+ for (i = 0; i < params->supported_rates_len; i++) {
+ int rate = (params->supported_rates[i] & 0x7f) * 5;
+- for (j = 0; j < mode->num_rates; j++) {
+- if (mode->rates[j].rate == rate)
++ for (j = 0; j < sband->n_bitrates; j++) {
++ if (sband->bitrates[j].bitrate == rate)
+ rates |= BIT(j);
+ }
+ }
+- sta->supp_rates = rates;
++ sta->supp_rates[local->oper_channel->band] = rates;
++ }
++
++ if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) {
++ switch (params->plink_action) {
++ case PLINK_ACTION_OPEN:
++ mesh_plink_open(sta);
++ break;
++ case PLINK_ACTION_BLOCK:
++ mesh_plink_block(sta);
++ break;
++ }
+ }
+ }
+
+@@ -543,18 +663,12 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct sta_info *sta;
+ struct ieee80211_sub_if_data *sdata;
++ int err;
+
+ /* Prevent a race with changing the rate control algorithm */
+ if (!netif_running(dev))
+ return -ENETDOWN;
+
+- /* XXX: get sta belonging to dev */
+- sta = sta_info_get(local, mac);
+- if (sta) {
+- sta_info_put(sta);
+- return -EEXIST;
+- }
+-
+ if (params->vlan) {
+ sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
+
+@@ -564,22 +678,36 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
+ } else
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+- sta = sta_info_add(local, dev, mac, GFP_KERNEL);
++ if (compare_ether_addr(mac, dev->dev_addr) == 0)
++ return -EINVAL;
++
++ if (is_multicast_ether_addr(mac))
++ return -EINVAL;
++
++ sta = sta_info_alloc(sdata, mac, GFP_KERNEL);
+ if (!sta)
+ return -ENOMEM;
+
+- sta->dev = sdata->dev;
+- if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN ||
+- sdata->vif.type == IEEE80211_IF_TYPE_AP)
+- ieee80211_send_layer2_update(sta);
+-
+ sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC;
+
+ sta_apply_parameters(local, sta, params);
+
+ rate_control_rate_init(sta, local);
+
+- sta_info_put(sta);
++ rcu_read_lock();
++
++ err = sta_info_insert(sta);
++ if (err) {
++ /* STA has been freed */
++ rcu_read_unlock();
++ return err;
++ }
++
++ if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN ||
++ sdata->vif.type == IEEE80211_IF_TYPE_AP)
++ ieee80211_send_layer2_update(sta);
++
++ rcu_read_unlock();
+
+ return 0;
+ }
+@@ -587,19 +715,26 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
+ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
+ u8 *mac)
+ {
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_local *local = sdata->local;
+ struct sta_info *sta;
+
+ if (mac) {
++ rcu_read_lock();
++
+ /* XXX: get sta belonging to dev */
+ sta = sta_info_get(local, mac);
+- if (!sta)
++ if (!sta) {
++ rcu_read_unlock();
+ return -ENOENT;
++ }
++
++ sta_info_unlink(&sta);
++ rcu_read_unlock();
+
+- sta_info_free(sta);
+- sta_info_put(sta);
++ sta_info_destroy(sta);
+ } else
+- sta_info_flush(local, dev);
++ sta_info_flush(local, sdata);
+
+ return 0;
+ }
+@@ -613,28 +748,203 @@ static int ieee80211_change_station(struct wiphy *wiphy,
+ struct sta_info *sta;
+ struct ieee80211_sub_if_data *vlansdata;
+
++ rcu_read_lock();
++
+ /* XXX: get sta belonging to dev */
+ sta = sta_info_get(local, mac);
+- if (!sta)
++ if (!sta) {
++ rcu_read_unlock();
+ return -ENOENT;
++ }
+
+- if (params->vlan && params->vlan != sta->dev) {
++ if (params->vlan && params->vlan != sta->sdata->dev) {
+ vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
+
+ if (vlansdata->vif.type != IEEE80211_IF_TYPE_VLAN ||
+- vlansdata->vif.type != IEEE80211_IF_TYPE_AP)
++ vlansdata->vif.type != IEEE80211_IF_TYPE_AP) {
++ rcu_read_unlock();
+ return -EINVAL;
++ }
+
+- sta->dev = params->vlan;
++ sta->sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
+ ieee80211_send_layer2_update(sta);
+ }
+
+ sta_apply_parameters(local, sta, params);
+
+- sta_info_put(sta);
++ rcu_read_unlock();
++
++ return 0;
++}
++
++#ifdef CONFIG_MAC80211_MESH
++static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
++ u8 *dst, u8 *next_hop)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct mesh_path *mpath;
++ struct sta_info *sta;
++ int err;
++
++ if (!netif_running(dev))
++ return -ENETDOWN;
++
++ if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
++ return -ENOTSUPP;
++
++ rcu_read_lock();
++ sta = sta_info_get(local, next_hop);
++ if (!sta) {
++ rcu_read_unlock();
++ return -ENOENT;
++ }
+
++ err = mesh_path_add(dst, dev);
++ if (err) {
++ rcu_read_unlock();
++ return err;
++ }
++
++ mpath = mesh_path_lookup(dst, dev);
++ if (!mpath) {
++ rcu_read_unlock();
++ return -ENXIO;
++ }
++ mesh_path_fix_nexthop(mpath, sta);
++
++ rcu_read_unlock();
++ return 0;
++}
++
++static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev,
++ u8 *dst)
++{
++ if (dst)
++ return mesh_path_del(dst, dev);
++
++ mesh_path_flush(dev);
++ return 0;
++}
++
++static int ieee80211_change_mpath(struct wiphy *wiphy,
++ struct net_device *dev,
++ u8 *dst, u8 *next_hop)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct mesh_path *mpath;
++ struct sta_info *sta;
++
++ if (!netif_running(dev))
++ return -ENETDOWN;
++
++ if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
++ return -ENOTSUPP;
++
++ rcu_read_lock();
++
++ sta = sta_info_get(local, next_hop);
++ if (!sta) {
++ rcu_read_unlock();
++ return -ENOENT;
++ }
++
++ mpath = mesh_path_lookup(dst, dev);
++ if (!mpath) {
++ rcu_read_unlock();
++ return -ENOENT;
++ }
++
++ mesh_path_fix_nexthop(mpath, sta);
++
++ rcu_read_unlock();
++ return 0;
++}
++
++static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
++ struct mpath_info *pinfo)
++{
++ if (mpath->next_hop)
++ memcpy(next_hop, mpath->next_hop->addr, ETH_ALEN);
++ else
++ memset(next_hop, 0, ETH_ALEN);
++
++ pinfo->filled = MPATH_INFO_FRAME_QLEN |
++ MPATH_INFO_DSN |
++ MPATH_INFO_METRIC |
++ MPATH_INFO_EXPTIME |
++ MPATH_INFO_DISCOVERY_TIMEOUT |
++ MPATH_INFO_DISCOVERY_RETRIES |
++ MPATH_INFO_FLAGS;
++
++ pinfo->frame_qlen = mpath->frame_queue.qlen;
++ pinfo->dsn = mpath->dsn;
++ pinfo->metric = mpath->metric;
++ if (time_before(jiffies, mpath->exp_time))
++ pinfo->exptime = jiffies_to_msecs(mpath->exp_time - jiffies);
++ pinfo->discovery_timeout =
++ jiffies_to_msecs(mpath->discovery_timeout);
++ pinfo->discovery_retries = mpath->discovery_retries;
++ pinfo->flags = 0;
++ if (mpath->flags & MESH_PATH_ACTIVE)
++ pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE;
++ if (mpath->flags & MESH_PATH_RESOLVING)
++ pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;
++ if (mpath->flags & MESH_PATH_DSN_VALID)
++ pinfo->flags |= NL80211_MPATH_FLAG_DSN_VALID;
++ if (mpath->flags & MESH_PATH_FIXED)
++ pinfo->flags |= NL80211_MPATH_FLAG_FIXED;
++ if (mpath->flags & MESH_PATH_RESOLVING)
++ pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;
++
++ pinfo->flags = mpath->flags;
++}
++
++static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev,
++ u8 *dst, u8 *next_hop, struct mpath_info *pinfo)
++
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct mesh_path *mpath;
++
++ if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
++ return -ENOTSUPP;
++
++ rcu_read_lock();
++ mpath = mesh_path_lookup(dst, dev);
++ if (!mpath) {
++ rcu_read_unlock();
++ return -ENOENT;
++ }
++ memcpy(dst, mpath->dst, ETH_ALEN);
++ mpath_set_pinfo(mpath, next_hop, pinfo);
++ rcu_read_unlock();
++ return 0;
++}
++
++static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev,
++ int idx, u8 *dst, u8 *next_hop,
++ struct mpath_info *pinfo)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct mesh_path *mpath;
++
++ if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
++ return -ENOTSUPP;
++
++ rcu_read_lock();
++ mpath = mesh_path_lookup_by_idx(idx, dev);
++ if (!mpath) {
++ rcu_read_unlock();
++ return -ENOENT;
++ }
++ memcpy(dst, mpath->dst, ETH_ALEN);
++ mpath_set_pinfo(mpath, next_hop, pinfo);
++ rcu_read_unlock();
+ return 0;
+ }
++#endif
+
+ struct cfg80211_ops mac80211_config_ops = {
+ .add_virtual_intf = ieee80211_add_iface,
+@@ -651,4 +961,12 @@ struct cfg80211_ops mac80211_config_ops = {
+ .del_station = ieee80211_del_station,
+ .change_station = ieee80211_change_station,
+ .get_station = ieee80211_get_station,
++ .dump_station = ieee80211_dump_station,
++#ifdef CONFIG_MAC80211_MESH
++ .add_mpath = ieee80211_add_mpath,
++ .del_mpath = ieee80211_del_mpath,
++ .change_mpath = ieee80211_change_mpath,
++ .get_mpath = ieee80211_get_mpath,
++ .dump_mpath = ieee80211_dump_mpath,
++#endif
+ };
+diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
+index 60514b2..1cccbfd 100644
+--- a/net/mac80211/debugfs.c
++++ b/net/mac80211/debugfs.c
+@@ -10,7 +10,7 @@
+ #include <linux/debugfs.h>
+ #include <linux/rtnetlink.h>
+ #include "ieee80211_i.h"
+-#include "ieee80211_rate.h"
++#include "rate.h"
+ #include "debugfs.h"
+
+ int mac80211_open_file_generic(struct inode *inode, struct file *file)
+@@ -19,41 +19,6 @@ int mac80211_open_file_generic(struct inode *inode, struct file *file)
+ return 0;
+ }
+
+-static const char *ieee80211_mode_str(int mode)
+-{
+- switch (mode) {
+- case MODE_IEEE80211A:
+- return "IEEE 802.11a";
+- case MODE_IEEE80211B:
+- return "IEEE 802.11b";
+- case MODE_IEEE80211G:
+- return "IEEE 802.11g";
+- default:
+- return "UNKNOWN";
+- }
+-}
+-
+-static ssize_t modes_read(struct file *file, char __user *userbuf,
+- size_t count, loff_t *ppos)
+-{
+- struct ieee80211_local *local = file->private_data;
+- struct ieee80211_hw_mode *mode;
+- char buf[150], *p = buf;
+-
+- /* FIXME: locking! */
+- list_for_each_entry(mode, &local->modes_list, list) {
+- p += scnprintf(p, sizeof(buf)+buf-p,
+- "%s\n", ieee80211_mode_str(mode->mode));
+- }
+-
+- return simple_read_from_buffer(userbuf, count, ppos, buf, p-buf);
+-}
+-
+-static const struct file_operations modes_ops = {
+- .read = modes_read,
+- .open = mac80211_open_file_generic,
+-};
+-
+ #define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \
+ static ssize_t name## _read(struct file *file, char __user *userbuf, \
+ size_t count, loff_t *ppos) \
+@@ -72,7 +37,7 @@ static const struct file_operations name## _ops = { \
+ };
+
+ #define DEBUGFS_ADD(name) \
+- local->debugfs.name = debugfs_create_file(#name, 0444, phyd, \
++ local->debugfs.name = debugfs_create_file(#name, 0400, phyd, \
+ local, &name## _ops);
+
+ #define DEBUGFS_DEL(name) \
+@@ -80,10 +45,8 @@ static const struct file_operations name## _ops = { \
+ local->debugfs.name = NULL;
+
+
+-DEBUGFS_READONLY_FILE(channel, 20, "%d",
+- local->hw.conf.channel);
+ DEBUGFS_READONLY_FILE(frequency, 20, "%d",
+- local->hw.conf.freq);
++ local->hw.conf.channel->center_freq);
+ DEBUGFS_READONLY_FILE(antenna_sel_tx, 20, "%d",
+ local->hw.conf.antenna_sel_tx);
+ DEBUGFS_READONLY_FILE(antenna_sel_rx, 20, "%d",
+@@ -100,8 +63,6 @@ DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d",
+ local->long_retry_limit);
+ DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d",
+ local->total_ps_buffered);
+-DEBUGFS_READONLY_FILE(mode, 20, "%s",
+- ieee80211_mode_str(local->hw.conf.phymode));
+ DEBUGFS_READONLY_FILE(wep_iv, 20, "%#06x",
+ local->wep_iv & 0xffffff);
+ DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s",
+@@ -169,7 +130,7 @@ static const struct file_operations stats_ ##name## _ops = { \
+ };
+
+ #define DEBUGFS_STATS_ADD(name) \
+- local->debugfs.stats.name = debugfs_create_file(#name, 0444, statsd,\
++ local->debugfs.stats.name = debugfs_create_file(#name, 0400, statsd,\
+ local, &stats_ ##name## _ops);
+
+ #define DEBUGFS_STATS_DEL(name) \
+@@ -294,7 +255,6 @@ void debugfs_hw_add(struct ieee80211_local *local)
+ local->debugfs.stations = debugfs_create_dir("stations", phyd);
+ local->debugfs.keys = debugfs_create_dir("keys", phyd);
+
+- DEBUGFS_ADD(channel);
+ DEBUGFS_ADD(frequency);
+ DEBUGFS_ADD(antenna_sel_tx);
+ DEBUGFS_ADD(antenna_sel_rx);
+@@ -304,9 +264,7 @@ void debugfs_hw_add(struct ieee80211_local *local)
+ DEBUGFS_ADD(short_retry_limit);
+ DEBUGFS_ADD(long_retry_limit);
+ DEBUGFS_ADD(total_ps_buffered);
+- DEBUGFS_ADD(mode);
+ DEBUGFS_ADD(wep_iv);
+- DEBUGFS_ADD(modes);
+
+ statsd = debugfs_create_dir("statistics", phyd);
+ local->debugfs.statistics = statsd;
+@@ -356,7 +314,6 @@ void debugfs_hw_add(struct ieee80211_local *local)
+
+ void debugfs_hw_del(struct ieee80211_local *local)
+ {
+- DEBUGFS_DEL(channel);
+ DEBUGFS_DEL(frequency);
+ DEBUGFS_DEL(antenna_sel_tx);
+ DEBUGFS_DEL(antenna_sel_rx);
+@@ -366,9 +323,7 @@ void debugfs_hw_del(struct ieee80211_local *local)
+ DEBUGFS_DEL(short_retry_limit);
+ DEBUGFS_DEL(long_retry_limit);
+ DEBUGFS_DEL(total_ps_buffered);
+- DEBUGFS_DEL(mode);
+ DEBUGFS_DEL(wep_iv);
+- DEBUGFS_DEL(modes);
+
+ DEBUGFS_STATS_DEL(transmitted_fragment_count);
+ DEBUGFS_STATS_DEL(multicast_transmitted_frame_count);
+diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
+index c881524..879e721 100644
+--- a/net/mac80211/debugfs_key.c
++++ b/net/mac80211/debugfs_key.c
+@@ -10,7 +10,7 @@
+
+ #include <linux/kobject.h>
+ #include "ieee80211_i.h"
+-#include "ieee80211_key.h"
++#include "key.h"
+ #include "debugfs.h"
+ #include "debugfs_key.h"
+
+@@ -184,23 +184,36 @@ KEY_OPS(key);
+ key->debugfs.name = debugfs_create_file(#name, 0400,\
+ key->debugfs.dir, key, &key_##name##_ops);
+
+-void ieee80211_debugfs_key_add(struct ieee80211_local *local,
+- struct ieee80211_key *key)
+-{
++void ieee80211_debugfs_key_add(struct ieee80211_key *key)
++ {
+ static int keycount;
+- char buf[20];
++ char buf[50];
++ DECLARE_MAC_BUF(mac);
++ struct sta_info *sta;
+
+- if (!local->debugfs.keys)
++ if (!key->local->debugfs.keys)
+ return;
+
+ sprintf(buf, "%d", keycount);
++ key->debugfs.cnt = keycount;
+ keycount++;
+ key->debugfs.dir = debugfs_create_dir(buf,
+- local->debugfs.keys);
++ key->local->debugfs.keys);
+
+ if (!key->debugfs.dir)
+ return;
+
++ rcu_read_lock();
++ sta = rcu_dereference(key->sta);
++ if (sta)
++ sprintf(buf, "../../stations/%s", print_mac(mac, sta->addr));
++ rcu_read_unlock();
++
++ /* using sta as a boolean is fine outside RCU lock */
++ if (sta)
++ key->debugfs.stalink =
++ debugfs_create_symlink("station", key->debugfs.dir, buf);
++
+ DEBUGFS_ADD(keylen);
+ DEBUGFS_ADD(flags);
+ DEBUGFS_ADD(keyidx);
+@@ -246,7 +259,7 @@ void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata)
+ if (!sdata->debugfsdir)
+ return;
+
+- sprintf(buf, "../keys/%d", sdata->default_key->conf.keyidx);
++ sprintf(buf, "../keys/%d", sdata->default_key->debugfs.cnt);
+ sdata->debugfs.default_key =
+ debugfs_create_symlink("default_key", sdata->debugfsdir, buf);
+ }
+@@ -258,19 +271,6 @@ void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata)
+ debugfs_remove(sdata->debugfs.default_key);
+ sdata->debugfs.default_key = NULL;
+ }
+-void ieee80211_debugfs_key_sta_link(struct ieee80211_key *key,
+- struct sta_info *sta)
+-{
+- char buf[50];
+- DECLARE_MAC_BUF(mac);
+-
+- if (!key->debugfs.dir)
+- return;
+-
+- sprintf(buf, "../../stations/%s", print_mac(mac, sta->addr));
+- key->debugfs.stalink =
+- debugfs_create_symlink("station", key->debugfs.dir, buf);
+-}
+
+ void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
+ struct sta_info *sta)
+diff --git a/net/mac80211/debugfs_key.h b/net/mac80211/debugfs_key.h
+index aecfce3..b1a3754 100644
+--- a/net/mac80211/debugfs_key.h
++++ b/net/mac80211/debugfs_key.h
+@@ -2,18 +2,14 @@
+ #define __MAC80211_DEBUGFS_KEY_H
+
+ #ifdef CONFIG_MAC80211_DEBUGFS
+-void ieee80211_debugfs_key_add(struct ieee80211_local *local,
+- struct ieee80211_key *key);
++void ieee80211_debugfs_key_add(struct ieee80211_key *key);
+ void ieee80211_debugfs_key_remove(struct ieee80211_key *key);
+ void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata);
+ void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata);
+-void ieee80211_debugfs_key_sta_link(struct ieee80211_key *key,
+- struct sta_info *sta);
+ void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
+ struct sta_info *sta);
+ #else
+-static inline void ieee80211_debugfs_key_add(struct ieee80211_local *local,
+- struct ieee80211_key *key)
++static inline void ieee80211_debugfs_key_add(struct ieee80211_key *key)
+ {}
+ static inline void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
+ {}
+@@ -23,9 +19,6 @@ static inline void ieee80211_debugfs_key_add_default(
+ static inline void ieee80211_debugfs_key_remove_default(
+ struct ieee80211_sub_if_data *sdata)
+ {}
+-static inline void ieee80211_debugfs_key_sta_link(
+- struct ieee80211_key *key, struct sta_info *sta)
+-{}
+ static inline void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
+ struct sta_info *sta)
+ {}
+diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
+index 829872a..e3326d0 100644
+--- a/net/mac80211/debugfs_netdev.c
++++ b/net/mac80211/debugfs_netdev.c
+@@ -17,7 +17,7 @@
+ #include <net/mac80211.h>
+ #include <net/cfg80211.h>
+ #include "ieee80211_i.h"
+-#include "ieee80211_rate.h"
++#include "rate.h"
+ #include "debugfs.h"
+ #include "debugfs_netdev.h"
+
+@@ -31,14 +31,39 @@ static ssize_t ieee80211_if_read(
+ ssize_t ret = -EINVAL;
+
+ read_lock(&dev_base_lock);
+- if (sdata->dev->reg_state == NETREG_REGISTERED) {
++ if (sdata->dev->reg_state == NETREG_REGISTERED)
+ ret = (*format)(sdata, buf, sizeof(buf));
+- ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret);
+- }
+ read_unlock(&dev_base_lock);
++
++ if (ret != -EINVAL)
++ ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret);
++
+ return ret;
+ }
+
++#ifdef CONFIG_MAC80211_MESH
++static ssize_t ieee80211_if_write(
++ struct ieee80211_sub_if_data *sdata,
++ char const __user *userbuf,
++ size_t count, loff_t *ppos,
++ int (*format)(struct ieee80211_sub_if_data *, char *))
++{
++ char buf[10];
++ int buf_size;
++
++ memset(buf, 0x00, sizeof(buf));
++ buf_size = min(count, (sizeof(buf)-1));
++ if (copy_from_user(buf, userbuf, buf_size))
++ return count;
++ read_lock(&dev_base_lock);
++ if (sdata->dev->reg_state == NETREG_REGISTERED)
++ (*format)(sdata, buf);
++ read_unlock(&dev_base_lock);
++
++ return count;
++}
++#endif
++
+ #define IEEE80211_IF_FMT(name, field, format_string) \
+ static ssize_t ieee80211_if_fmt_##name( \
+ const struct ieee80211_sub_if_data *sdata, char *buf, \
+@@ -46,6 +71,19 @@ static ssize_t ieee80211_if_fmt_##name( \
+ { \
+ return scnprintf(buf, buflen, format_string, sdata->field); \
+ }
++#define IEEE80211_IF_WFMT(name, field, type) \
++static int ieee80211_if_wfmt_##name( \
++ struct ieee80211_sub_if_data *sdata, char *buf) \
++{ \
++ unsigned long tmp; \
++ char *endp; \
++ \
++ tmp = simple_strtoul(buf, &endp, 0); \
++ if ((endp == buf) || ((type)tmp != tmp)) \
++ return -EINVAL; \
++ sdata->field = tmp; \
++ return 0; \
++}
+ #define IEEE80211_IF_FMT_DEC(name, field) \
+ IEEE80211_IF_FMT(name, field, "%d\n")
+ #define IEEE80211_IF_FMT_HEX(name, field) \
+@@ -88,10 +126,37 @@ static const struct file_operations name##_ops = { \
+ IEEE80211_IF_FMT_##format(name, field) \
+ __IEEE80211_IF_FILE(name)
+
++#define __IEEE80211_IF_WFILE(name) \
++static ssize_t ieee80211_if_read_##name(struct file *file, \
++ char __user *userbuf, \
++ size_t count, loff_t *ppos) \
++{ \
++ return ieee80211_if_read(file->private_data, \
++ userbuf, count, ppos, \
++ ieee80211_if_fmt_##name); \
++} \
++static ssize_t ieee80211_if_write_##name(struct file *file, \
++ const char __user *userbuf, \
++ size_t count, loff_t *ppos) \
++{ \
++ return ieee80211_if_write(file->private_data, \
++ userbuf, count, ppos, \
++ ieee80211_if_wfmt_##name); \
++} \
++static const struct file_operations name##_ops = { \
++ .read = ieee80211_if_read_##name, \
++ .write = ieee80211_if_write_##name, \
++ .open = mac80211_open_file_generic, \
++}
++
++#define IEEE80211_IF_WFILE(name, field, format, type) \
++ IEEE80211_IF_FMT_##format(name, field) \
++ IEEE80211_IF_WFMT(name, field, type) \
++ __IEEE80211_IF_WFILE(name)
++
+ /* common attributes */
+ IEEE80211_IF_FILE(channel_use, channel_use, DEC);
+ IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
+-IEEE80211_IF_FILE(ieee802_1x_pac, ieee802_1x_pac, DEC);
+
+ /* STA/IBSS attributes */
+ IEEE80211_IF_FILE(state, u.sta.state, DEC);
+@@ -107,6 +172,7 @@ IEEE80211_IF_FILE(assoc_tries, u.sta.assoc_tries, DEC);
+ IEEE80211_IF_FILE(auth_algs, u.sta.auth_algs, HEX);
+ IEEE80211_IF_FILE(auth_alg, u.sta.auth_alg, DEC);
+ IEEE80211_IF_FILE(auth_transaction, u.sta.auth_transaction, DEC);
++IEEE80211_IF_FILE(num_beacons_sta, u.sta.num_beacons, DEC);
+
+ static ssize_t ieee80211_if_fmt_flags(
+ const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
+@@ -140,15 +206,50 @@ __IEEE80211_IF_FILE(num_buffered_multicast);
+ /* WDS attributes */
+ IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC);
+
++#ifdef CONFIG_MAC80211_MESH
++/* Mesh stats attributes */
++IEEE80211_IF_FILE(fwded_frames, u.sta.mshstats.fwded_frames, DEC);
++IEEE80211_IF_FILE(dropped_frames_ttl, u.sta.mshstats.dropped_frames_ttl, DEC);
++IEEE80211_IF_FILE(dropped_frames_no_route,
++ u.sta.mshstats.dropped_frames_no_route, DEC);
++IEEE80211_IF_FILE(estab_plinks, u.sta.mshstats.estab_plinks, ATOMIC);
++
++/* Mesh parameters */
++IEEE80211_IF_WFILE(dot11MeshMaxRetries,
++ u.sta.mshcfg.dot11MeshMaxRetries, DEC, u8);
++IEEE80211_IF_WFILE(dot11MeshRetryTimeout,
++ u.sta.mshcfg.dot11MeshRetryTimeout, DEC, u16);
++IEEE80211_IF_WFILE(dot11MeshConfirmTimeout,
++ u.sta.mshcfg.dot11MeshConfirmTimeout, DEC, u16);
++IEEE80211_IF_WFILE(dot11MeshHoldingTimeout,
++ u.sta.mshcfg.dot11MeshHoldingTimeout, DEC, u16);
++IEEE80211_IF_WFILE(dot11MeshTTL, u.sta.mshcfg.dot11MeshTTL, DEC, u8);
++IEEE80211_IF_WFILE(auto_open_plinks, u.sta.mshcfg.auto_open_plinks, DEC, u8);
++IEEE80211_IF_WFILE(dot11MeshMaxPeerLinks,
++ u.sta.mshcfg.dot11MeshMaxPeerLinks, DEC, u16);
++IEEE80211_IF_WFILE(dot11MeshHWMPactivePathTimeout,
++ u.sta.mshcfg.dot11MeshHWMPactivePathTimeout, DEC, u32);
++IEEE80211_IF_WFILE(dot11MeshHWMPpreqMinInterval,
++ u.sta.mshcfg.dot11MeshHWMPpreqMinInterval, DEC, u16);
++IEEE80211_IF_WFILE(dot11MeshHWMPnetDiameterTraversalTime,
++ u.sta.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC, u16);
++IEEE80211_IF_WFILE(dot11MeshHWMPmaxPREQretries,
++ u.sta.mshcfg.dot11MeshHWMPmaxPREQretries, DEC, u8);
++IEEE80211_IF_WFILE(path_refresh_time,
++ u.sta.mshcfg.path_refresh_time, DEC, u32);
++IEEE80211_IF_WFILE(min_discovery_timeout,
++ u.sta.mshcfg.min_discovery_timeout, DEC, u16);
++#endif
++
++
+ #define DEBUGFS_ADD(name, type)\
+- sdata->debugfs.type.name = debugfs_create_file(#name, 0444,\
++ sdata->debugfs.type.name = debugfs_create_file(#name, 0400,\
+ sdata->debugfsdir, sdata, &name##_ops);
+
+ static void add_sta_files(struct ieee80211_sub_if_data *sdata)
+ {
+ DEBUGFS_ADD(channel_use, sta);
+ DEBUGFS_ADD(drop_unencrypted, sta);
+- DEBUGFS_ADD(ieee802_1x_pac, sta);
+ DEBUGFS_ADD(state, sta);
+ DEBUGFS_ADD(bssid, sta);
+ DEBUGFS_ADD(prev_bssid, sta);
+@@ -163,13 +264,13 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata)
+ DEBUGFS_ADD(auth_alg, sta);
+ DEBUGFS_ADD(auth_transaction, sta);
+ DEBUGFS_ADD(flags, sta);
++ DEBUGFS_ADD(num_beacons_sta, sta);
+ }
+
+ static void add_ap_files(struct ieee80211_sub_if_data *sdata)
+ {
+ DEBUGFS_ADD(channel_use, ap);
+ DEBUGFS_ADD(drop_unencrypted, ap);
+- DEBUGFS_ADD(ieee802_1x_pac, ap);
+ DEBUGFS_ADD(num_sta_ps, ap);
+ DEBUGFS_ADD(dtim_count, ap);
+ DEBUGFS_ADD(num_beacons, ap);
+@@ -182,7 +283,6 @@ static void add_wds_files(struct ieee80211_sub_if_data *sdata)
+ {
+ DEBUGFS_ADD(channel_use, wds);
+ DEBUGFS_ADD(drop_unencrypted, wds);
+- DEBUGFS_ADD(ieee802_1x_pac, wds);
+ DEBUGFS_ADD(peer, wds);
+ }
+
+@@ -190,19 +290,63 @@ static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
+ {
+ DEBUGFS_ADD(channel_use, vlan);
+ DEBUGFS_ADD(drop_unencrypted, vlan);
+- DEBUGFS_ADD(ieee802_1x_pac, vlan);
+ }
+
+ static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
+ {
+ }
+
++#ifdef CONFIG_MAC80211_MESH
++#define MESHSTATS_ADD(name)\
++ sdata->mesh_stats.name = debugfs_create_file(#name, 0400,\
++ sdata->mesh_stats_dir, sdata, &name##_ops);
++
++static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
++{
++ sdata->mesh_stats_dir = debugfs_create_dir("mesh_stats",
++ sdata->debugfsdir);
++ MESHSTATS_ADD(fwded_frames);
++ MESHSTATS_ADD(dropped_frames_ttl);
++ MESHSTATS_ADD(dropped_frames_no_route);
++ MESHSTATS_ADD(estab_plinks);
++}
++
++#define MESHPARAMS_ADD(name)\
++ sdata->mesh_config.name = debugfs_create_file(#name, 0600,\
++ sdata->mesh_config_dir, sdata, &name##_ops);
++
++static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
++{
++ sdata->mesh_config_dir = debugfs_create_dir("mesh_config",
++ sdata->debugfsdir);
++ MESHPARAMS_ADD(dot11MeshMaxRetries);
++ MESHPARAMS_ADD(dot11MeshRetryTimeout);
++ MESHPARAMS_ADD(dot11MeshConfirmTimeout);
++ MESHPARAMS_ADD(dot11MeshHoldingTimeout);
++ MESHPARAMS_ADD(dot11MeshTTL);
++ MESHPARAMS_ADD(auto_open_plinks);
++ MESHPARAMS_ADD(dot11MeshMaxPeerLinks);
++ MESHPARAMS_ADD(dot11MeshHWMPactivePathTimeout);
++ MESHPARAMS_ADD(dot11MeshHWMPpreqMinInterval);
++ MESHPARAMS_ADD(dot11MeshHWMPnetDiameterTraversalTime);
++ MESHPARAMS_ADD(dot11MeshHWMPmaxPREQretries);
++ MESHPARAMS_ADD(path_refresh_time);
++ MESHPARAMS_ADD(min_discovery_timeout);
++}
++#endif
++
+ static void add_files(struct ieee80211_sub_if_data *sdata)
+ {
+ if (!sdata->debugfsdir)
+ return;
+
+ switch (sdata->vif.type) {
++ case IEEE80211_IF_TYPE_MESH_POINT:
++#ifdef CONFIG_MAC80211_MESH
++ add_mesh_stats(sdata);
++ add_mesh_config(sdata);
++#endif
++ /* fall through */
+ case IEEE80211_IF_TYPE_STA:
+ case IEEE80211_IF_TYPE_IBSS:
+ add_sta_files(sdata);
+@@ -234,7 +378,6 @@ static void del_sta_files(struct ieee80211_sub_if_data *sdata)
+ {
+ DEBUGFS_DEL(channel_use, sta);
+ DEBUGFS_DEL(drop_unencrypted, sta);
+- DEBUGFS_DEL(ieee802_1x_pac, sta);
+ DEBUGFS_DEL(state, sta);
+ DEBUGFS_DEL(bssid, sta);
+ DEBUGFS_DEL(prev_bssid, sta);
+@@ -249,13 +392,13 @@ static void del_sta_files(struct ieee80211_sub_if_data *sdata)
+ DEBUGFS_DEL(auth_alg, sta);
+ DEBUGFS_DEL(auth_transaction, sta);
+ DEBUGFS_DEL(flags, sta);
++ DEBUGFS_DEL(num_beacons_sta, sta);
+ }
+
+ static void del_ap_files(struct ieee80211_sub_if_data *sdata)
+ {
+ DEBUGFS_DEL(channel_use, ap);
+ DEBUGFS_DEL(drop_unencrypted, ap);
+- DEBUGFS_DEL(ieee802_1x_pac, ap);
+ DEBUGFS_DEL(num_sta_ps, ap);
+ DEBUGFS_DEL(dtim_count, ap);
+ DEBUGFS_DEL(num_beacons, ap);
+@@ -268,7 +411,6 @@ static void del_wds_files(struct ieee80211_sub_if_data *sdata)
+ {
+ DEBUGFS_DEL(channel_use, wds);
+ DEBUGFS_DEL(drop_unencrypted, wds);
+- DEBUGFS_DEL(ieee802_1x_pac, wds);
+ DEBUGFS_DEL(peer, wds);
+ }
+
+@@ -276,19 +418,67 @@ static void del_vlan_files(struct ieee80211_sub_if_data *sdata)
+ {
+ DEBUGFS_DEL(channel_use, vlan);
+ DEBUGFS_DEL(drop_unencrypted, vlan);
+- DEBUGFS_DEL(ieee802_1x_pac, vlan);
+ }
+
+ static void del_monitor_files(struct ieee80211_sub_if_data *sdata)
+ {
+ }
+
++#ifdef CONFIG_MAC80211_MESH
++#define MESHSTATS_DEL(name) \
++ do { \
++ debugfs_remove(sdata->mesh_stats.name); \
++ sdata->mesh_stats.name = NULL; \
++ } while (0)
++
++static void del_mesh_stats(struct ieee80211_sub_if_data *sdata)
++{
++ MESHSTATS_DEL(fwded_frames);
++ MESHSTATS_DEL(dropped_frames_ttl);
++ MESHSTATS_DEL(dropped_frames_no_route);
++ MESHSTATS_DEL(estab_plinks);
++ debugfs_remove(sdata->mesh_stats_dir);
++ sdata->mesh_stats_dir = NULL;
++}
++
++#define MESHPARAMS_DEL(name) \
++ do { \
++ debugfs_remove(sdata->mesh_config.name); \
++ sdata->mesh_config.name = NULL; \
++ } while (0)
++
++static void del_mesh_config(struct ieee80211_sub_if_data *sdata)
++{
++ MESHPARAMS_DEL(dot11MeshMaxRetries);
++ MESHPARAMS_DEL(dot11MeshRetryTimeout);
++ MESHPARAMS_DEL(dot11MeshConfirmTimeout);
++ MESHPARAMS_DEL(dot11MeshHoldingTimeout);
++ MESHPARAMS_DEL(dot11MeshTTL);
++ MESHPARAMS_DEL(auto_open_plinks);
++ MESHPARAMS_DEL(dot11MeshMaxPeerLinks);
++ MESHPARAMS_DEL(dot11MeshHWMPactivePathTimeout);
++ MESHPARAMS_DEL(dot11MeshHWMPpreqMinInterval);
++ MESHPARAMS_DEL(dot11MeshHWMPnetDiameterTraversalTime);
++ MESHPARAMS_DEL(dot11MeshHWMPmaxPREQretries);
++ MESHPARAMS_DEL(path_refresh_time);
++ MESHPARAMS_DEL(min_discovery_timeout);
++ debugfs_remove(sdata->mesh_config_dir);
++ sdata->mesh_config_dir = NULL;
++}
++#endif
++
+ static void del_files(struct ieee80211_sub_if_data *sdata, int type)
+ {
+ if (!sdata->debugfsdir)
+ return;
+
+ switch (type) {
++ case IEEE80211_IF_TYPE_MESH_POINT:
++#ifdef CONFIG_MAC80211_MESH
++ del_mesh_stats(sdata);
++ del_mesh_config(sdata);
++#endif
++ /* fall through */
+ case IEEE80211_IF_TYPE_STA:
+ case IEEE80211_IF_TYPE_IBSS:
+ del_sta_files(sdata);
+diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
+index 8f5944c..6d47a1d 100644
+--- a/net/mac80211/debugfs_sta.c
++++ b/net/mac80211/debugfs_sta.c
+@@ -33,25 +33,16 @@ static ssize_t sta_ ##name## _read(struct file *file, \
+ #define STA_READ_LU(name, field) STA_READ(name, 20, field, "%lu\n")
+ #define STA_READ_S(name, field) STA_READ(name, 20, field, "%s\n")
+
+-#define STA_READ_RATE(name, field) \
+-static ssize_t sta_##name##_read(struct file *file, \
+- char __user *userbuf, \
+- size_t count, loff_t *ppos) \
+-{ \
+- struct sta_info *sta = file->private_data; \
+- struct ieee80211_local *local = wdev_priv(sta->dev->ieee80211_ptr);\
+- struct ieee80211_hw_mode *mode = local->oper_hw_mode; \
+- char buf[20]; \
+- int res = scnprintf(buf, sizeof(buf), "%d\n", \
+- (sta->field >= 0 && \
+- sta->field < mode->num_rates) ? \
+- mode->rates[sta->field].rate : -1); \
+- return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
++#define STA_OPS(name) \
++static const struct file_operations sta_ ##name## _ops = { \
++ .read = sta_##name##_read, \
++ .open = mac80211_open_file_generic, \
+ }
+
+-#define STA_OPS(name) \
++#define STA_OPS_WR(name) \
+ static const struct file_operations sta_ ##name## _ops = { \
+ .read = sta_##name##_read, \
++ .write = sta_##name##_write, \
+ .open = mac80211_open_file_generic, \
+ }
+
+@@ -60,7 +51,7 @@ static const struct file_operations sta_ ##name## _ops = { \
+ STA_OPS(name)
+
+ STA_FILE(aid, aid, D);
+-STA_FILE(dev, dev->name, S);
++STA_FILE(dev, sdata->dev->name, S);
+ STA_FILE(rx_packets, rx_packets, LU);
+ STA_FILE(tx_packets, tx_packets, LU);
+ STA_FILE(rx_bytes, rx_bytes, LU);
+@@ -70,27 +61,23 @@ STA_FILE(rx_fragments, rx_fragments, LU);
+ STA_FILE(rx_dropped, rx_dropped, LU);
+ STA_FILE(tx_fragments, tx_fragments, LU);
+ STA_FILE(tx_filtered, tx_filtered_count, LU);
+-STA_FILE(txrate, txrate, RATE);
+-STA_FILE(last_txrate, last_txrate, RATE);
+ STA_FILE(tx_retry_failed, tx_retry_failed, LU);
+ STA_FILE(tx_retry_count, tx_retry_count, LU);
+ STA_FILE(last_rssi, last_rssi, D);
+ STA_FILE(last_signal, last_signal, D);
+ STA_FILE(last_noise, last_noise, D);
+ STA_FILE(channel_use, channel_use, D);
+-STA_FILE(wep_weak_iv_count, wep_weak_iv_count, D);
++STA_FILE(wep_weak_iv_count, wep_weak_iv_count, LU);
+
+ static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+ {
+ char buf[100];
+ struct sta_info *sta = file->private_data;
+- int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s",
++ int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s",
+ sta->flags & WLAN_STA_AUTH ? "AUTH\n" : "",
+ sta->flags & WLAN_STA_ASSOC ? "ASSOC\n" : "",
+ sta->flags & WLAN_STA_PS ? "PS\n" : "",
+- sta->flags & WLAN_STA_TIM ? "TIM\n" : "",
+- sta->flags & WLAN_STA_PERM ? "PERM\n" : "",
+ sta->flags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "",
+ sta->flags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "",
+ sta->flags & WLAN_STA_WME ? "WME\n" : "",
+@@ -111,31 +98,6 @@ static ssize_t sta_num_ps_buf_frames_read(struct file *file,
+ }
+ STA_OPS(num_ps_buf_frames);
+
+-static ssize_t sta_last_ack_rssi_read(struct file *file, char __user *userbuf,
+- size_t count, loff_t *ppos)
+-{
+- char buf[100];
+- struct sta_info *sta = file->private_data;
+- int res = scnprintf(buf, sizeof(buf), "%d %d %d\n",
+- sta->last_ack_rssi[0],
+- sta->last_ack_rssi[1],
+- sta->last_ack_rssi[2]);
+- return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+-}
+-STA_OPS(last_ack_rssi);
+-
+-static ssize_t sta_last_ack_ms_read(struct file *file, char __user *userbuf,
+- size_t count, loff_t *ppos)
+-{
+- char buf[20];
+- struct sta_info *sta = file->private_data;
+- int res = scnprintf(buf, sizeof(buf), "%d\n",
+- sta->last_ack ?
+- jiffies_to_msecs(jiffies - sta->last_ack) : -1);
+- return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+-}
+-STA_OPS(last_ack_ms);
+-
+ static ssize_t sta_inactive_ms_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+ {
+@@ -191,8 +153,120 @@ static ssize_t sta_wme_tx_queue_read(struct file *file, char __user *userbuf,
+ STA_OPS(wme_tx_queue);
+ #endif
+
++static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
++ size_t count, loff_t *ppos)
++{
++ char buf[768], *p = buf;
++ int i;
++ struct sta_info *sta = file->private_data;
++ p += scnprintf(p, sizeof(buf)+buf-p, "Agg state for STA is:\n");
++ p += scnprintf(p, sizeof(buf)+buf-p, " STA next dialog_token is %d \n "
++ "TIDs info is: \n TID :",
++ (sta->ampdu_mlme.dialog_token_allocator + 1));
++ for (i = 0; i < STA_TID_NUM; i++)
++ p += scnprintf(p, sizeof(buf)+buf-p, "%5d", i);
++
++ p += scnprintf(p, sizeof(buf)+buf-p, "\n RX :");
++ for (i = 0; i < STA_TID_NUM; i++)
++ p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
++ sta->ampdu_mlme.tid_state_rx[i]);
++
++ p += scnprintf(p, sizeof(buf)+buf-p, "\n DTKN:");
++ for (i = 0; i < STA_TID_NUM; i++)
++ p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
++ sta->ampdu_mlme.tid_state_rx[i]?
++ sta->ampdu_mlme.tid_rx[i]->dialog_token : 0);
++
++ p += scnprintf(p, sizeof(buf)+buf-p, "\n TX :");
++ for (i = 0; i < STA_TID_NUM; i++)
++ p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
++ sta->ampdu_mlme.tid_state_tx[i]);
++
++ p += scnprintf(p, sizeof(buf)+buf-p, "\n DTKN:");
++ for (i = 0; i < STA_TID_NUM; i++)
++ p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
++ sta->ampdu_mlme.tid_state_tx[i]?
++ sta->ampdu_mlme.tid_tx[i]->dialog_token : 0);
++
++ p += scnprintf(p, sizeof(buf)+buf-p, "\n SSN :");
++ for (i = 0; i < STA_TID_NUM; i++)
++ p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
++ sta->ampdu_mlme.tid_state_tx[i]?
++ sta->ampdu_mlme.tid_tx[i]->ssn : 0);
++
++ p += scnprintf(p, sizeof(buf)+buf-p, "\n");
++
++ return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
++}
++
++static ssize_t sta_agg_status_write(struct file *file,
++ const char __user *user_buf, size_t count, loff_t *ppos)
++{
++ struct sta_info *sta = file->private_data;
++ struct net_device *dev = sta->sdata->dev;
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_hw *hw = &local->hw;
++ u8 *da = sta->addr;
++ static int tid_static_tx[16] = {0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0};
++ static int tid_static_rx[16] = {1, 1, 1, 1, 1, 1, 1, 1,
++ 1, 1, 1, 1, 1, 1, 1, 1};
++ char *endp;
++ char buf[32];
++ int buf_size, rs;
++ unsigned int tid_num;
++ char state[4];
++
++ memset(buf, 0x00, sizeof(buf));
++ buf_size = min(count, (sizeof(buf)-1));
++ if (copy_from_user(buf, user_buf, buf_size))
++ return -EFAULT;
++
++ tid_num = simple_strtoul(buf, &endp, 0);
++ if (endp == buf)
++ return -EINVAL;
++
++ if ((tid_num >= 100) && (tid_num <= 115)) {
++ /* toggle Rx aggregation command */
++ tid_num = tid_num - 100;
++ if (tid_static_rx[tid_num] == 1) {
++ strcpy(state, "off ");
++ ieee80211_sta_stop_rx_ba_session(dev, da, tid_num, 0,
++ WLAN_REASON_QSTA_REQUIRE_SETUP);
++ sta->ampdu_mlme.tid_state_rx[tid_num] |=
++ HT_AGG_STATE_DEBUGFS_CTL;
++ tid_static_rx[tid_num] = 0;
++ } else {
++ strcpy(state, "on ");
++ sta->ampdu_mlme.tid_state_rx[tid_num] &=
++ ~HT_AGG_STATE_DEBUGFS_CTL;
++ tid_static_rx[tid_num] = 1;
++ }
++ printk(KERN_DEBUG "debugfs - try switching tid %u %s\n",
++ tid_num, state);
++ } else if ((tid_num >= 0) && (tid_num <= 15)) {
++ /* toggle Tx aggregation command */
++ if (tid_static_tx[tid_num] == 0) {
++ strcpy(state, "on ");
++ rs = ieee80211_start_tx_ba_session(hw, da, tid_num);
++ if (rs == 0)
++ tid_static_tx[tid_num] = 1;
++ } else {
++ strcpy(state, "off");
++ rs = ieee80211_stop_tx_ba_session(hw, da, tid_num, 1);
++ if (rs == 0)
++ tid_static_tx[tid_num] = 0;
++ }
++ printk(KERN_DEBUG "debugfs - switching tid %u %s, return=%d\n",
++ tid_num, state, rs);
++ }
++
++ return count;
++}
++STA_OPS_WR(agg_status);
++
+ #define DEBUGFS_ADD(name) \
+- sta->debugfs.name = debugfs_create_file(#name, 0444, \
++ sta->debugfs.name = debugfs_create_file(#name, 0400, \
+ sta->debugfs.dir, sta, &sta_ ##name## _ops);
+
+ #define DEBUGFS_DEL(name) \
+@@ -203,12 +277,13 @@ STA_OPS(wme_tx_queue);
+ void ieee80211_sta_debugfs_add(struct sta_info *sta)
+ {
+ struct dentry *stations_dir = sta->local->debugfs.stations;
+- DECLARE_MAC_BUF(mac);
++ DECLARE_MAC_BUF(mbuf);
++ u8 *mac;
+
+ if (!stations_dir)
+ return;
+
+- print_mac(mac, sta->addr);
++ mac = print_mac(mbuf, sta->addr);
+
+ sta->debugfs.dir = debugfs_create_dir(mac, stations_dir);
+ if (!sta->debugfs.dir)
+@@ -216,28 +291,26 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
+
+ DEBUGFS_ADD(flags);
+ DEBUGFS_ADD(num_ps_buf_frames);
+- DEBUGFS_ADD(last_ack_rssi);
+- DEBUGFS_ADD(last_ack_ms);
+ DEBUGFS_ADD(inactive_ms);
+ DEBUGFS_ADD(last_seq_ctrl);
+ #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+ DEBUGFS_ADD(wme_rx_queue);
+ DEBUGFS_ADD(wme_tx_queue);
+ #endif
++ DEBUGFS_ADD(agg_status);
+ }
+
+ void ieee80211_sta_debugfs_remove(struct sta_info *sta)
+ {
+ DEBUGFS_DEL(flags);
+ DEBUGFS_DEL(num_ps_buf_frames);
+- DEBUGFS_DEL(last_ack_rssi);
+- DEBUGFS_DEL(last_ack_ms);
+ DEBUGFS_DEL(inactive_ms);
+ DEBUGFS_DEL(last_seq_ctrl);
+ #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+ DEBUGFS_DEL(wme_rx_queue);
+ DEBUGFS_DEL(wme_tx_queue);
+ #endif
++ DEBUGFS_DEL(agg_status);
+
+ debugfs_remove(sta->debugfs.dir);
+ sta->debugfs.dir = NULL;
+diff --git a/net/mac80211/debugfs_sta.h b/net/mac80211/debugfs_sta.h
+index 574a1cd..8b60890 100644
+--- a/net/mac80211/debugfs_sta.h
++++ b/net/mac80211/debugfs_sta.h
+@@ -1,6 +1,8 @@
+ #ifndef __MAC80211_DEBUGFS_STA_H
+ #define __MAC80211_DEBUGFS_STA_H
+
++#include "sta_info.h"
++
+ #ifdef CONFIG_MAC80211_DEBUGFS
+ void ieee80211_sta_debugfs_add(struct sta_info *sta);
+ void ieee80211_sta_debugfs_remove(struct sta_info *sta);
+diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
+deleted file mode 100644
+index 8e58639..0000000
+--- a/net/mac80211/ieee80211.c
++++ /dev/null
+@@ -1,1402 +0,0 @@
+-/*
+- * Copyright 2002-2005, Instant802 Networks, Inc.
+- * Copyright 2005-2006, Devicescape Software, Inc.
+- * Copyright 2006-2007 Jiri Benc <jbenc at suse.cz>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#include <net/mac80211.h>
+-#include <net/ieee80211_radiotap.h>
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/netdevice.h>
+-#include <linux/types.h>
+-#include <linux/slab.h>
+-#include <linux/skbuff.h>
+-#include <linux/etherdevice.h>
+-#include <linux/if_arp.h>
+-#include <linux/wireless.h>
+-#include <linux/rtnetlink.h>
+-#include <linux/bitmap.h>
+-#include <net/net_namespace.h>
+-#include <net/cfg80211.h>
+-
+-#include "ieee80211_i.h"
+-#include "ieee80211_rate.h"
+-#include "wep.h"
+-#include "wme.h"
+-#include "aes_ccm.h"
+-#include "ieee80211_led.h"
+-#include "cfg.h"
+-#include "debugfs.h"
+-#include "debugfs_netdev.h"
+-
+-#define SUPP_MCS_SET_LEN 16
+-
+-/*
+- * For seeing transmitted packets on monitor interfaces
+- * we have a radiotap header too.
+- */
+-struct ieee80211_tx_status_rtap_hdr {
+- struct ieee80211_radiotap_header hdr;
+- __le16 tx_flags;
+- u8 data_retries;
+-} __attribute__ ((packed));
+-
+-/* common interface routines */
+-
+-static int header_parse_80211(const struct sk_buff *skb, unsigned char *haddr)
+-{
+- memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */
+- return ETH_ALEN;
+-}
+-
+-/* must be called under mdev tx lock */
+-static void ieee80211_configure_filter(struct ieee80211_local *local)
+-{
+- unsigned int changed_flags;
+- unsigned int new_flags = 0;
+-
+- if (atomic_read(&local->iff_promiscs))
+- new_flags |= FIF_PROMISC_IN_BSS;
+-
+- if (atomic_read(&local->iff_allmultis))
+- new_flags |= FIF_ALLMULTI;
+-
+- if (local->monitors)
+- new_flags |= FIF_CONTROL |
+- FIF_OTHER_BSS |
+- FIF_BCN_PRBRESP_PROMISC;
+-
+- changed_flags = local->filter_flags ^ new_flags;
+-
+- /* be a bit nasty */
+- new_flags |= (1<<31);
+-
+- local->ops->configure_filter(local_to_hw(local),
+- changed_flags, &new_flags,
+- local->mdev->mc_count,
+- local->mdev->mc_list);
+-
+- WARN_ON(new_flags & (1<<31));
+-
+- local->filter_flags = new_flags & ~(1<<31);
+-}
+-
+-/* master interface */
+-
+-static int ieee80211_master_open(struct net_device *dev)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_sub_if_data *sdata;
+- int res = -EOPNOTSUPP;
+-
+- /* we hold the RTNL here so can safely walk the list */
+- list_for_each_entry(sdata, &local->interfaces, list) {
+- if (sdata->dev != dev && netif_running(sdata->dev)) {
+- res = 0;
+- break;
+- }
+- }
+- return res;
+-}
+-
+-static int ieee80211_master_stop(struct net_device *dev)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_sub_if_data *sdata;
+-
+- /* we hold the RTNL here so can safely walk the list */
+- list_for_each_entry(sdata, &local->interfaces, list)
+- if (sdata->dev != dev && netif_running(sdata->dev))
+- dev_close(sdata->dev);
+-
+- return 0;
+-}
+-
+-static void ieee80211_master_set_multicast_list(struct net_device *dev)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+- ieee80211_configure_filter(local);
+-}
+-
+-/* regular interfaces */
+-
+-static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
+-{
+- /* FIX: what would be proper limits for MTU?
+- * This interface uses 802.3 frames. */
+- if (new_mtu < 256 || new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6) {
+- printk(KERN_WARNING "%s: invalid MTU %d\n",
+- dev->name, new_mtu);
+- return -EINVAL;
+- }
+-
+-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+- printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu);
+-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+- dev->mtu = new_mtu;
+- return 0;
+-}
+-
+-static inline int identical_mac_addr_allowed(int type1, int type2)
+-{
+- return (type1 == IEEE80211_IF_TYPE_MNTR ||
+- type2 == IEEE80211_IF_TYPE_MNTR ||
+- (type1 == IEEE80211_IF_TYPE_AP &&
+- type2 == IEEE80211_IF_TYPE_WDS) ||
+- (type1 == IEEE80211_IF_TYPE_WDS &&
+- (type2 == IEEE80211_IF_TYPE_WDS ||
+- type2 == IEEE80211_IF_TYPE_AP)) ||
+- (type1 == IEEE80211_IF_TYPE_AP &&
+- type2 == IEEE80211_IF_TYPE_VLAN) ||
+- (type1 == IEEE80211_IF_TYPE_VLAN &&
+- (type2 == IEEE80211_IF_TYPE_AP ||
+- type2 == IEEE80211_IF_TYPE_VLAN)));
+-}
+-
+-static int ieee80211_open(struct net_device *dev)
+-{
+- struct ieee80211_sub_if_data *sdata, *nsdata;
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_if_init_conf conf;
+- int res;
+- bool need_hw_reconfig = 0;
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-
+- /* we hold the RTNL here so can safely walk the list */
+- list_for_each_entry(nsdata, &local->interfaces, list) {
+- struct net_device *ndev = nsdata->dev;
+-
+- if (ndev != dev && ndev != local->mdev && netif_running(ndev) &&
+- compare_ether_addr(dev->dev_addr, ndev->dev_addr) == 0) {
+- /*
+- * check whether it may have the same address
+- */
+- if (!identical_mac_addr_allowed(sdata->vif.type,
+- nsdata->vif.type))
+- return -ENOTUNIQ;
+-
+- /*
+- * can only add VLANs to enabled APs
+- */
+- if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN &&
+- nsdata->vif.type == IEEE80211_IF_TYPE_AP &&
+- netif_running(nsdata->dev))
+- sdata->u.vlan.ap = nsdata;
+- }
+- }
+-
+- switch (sdata->vif.type) {
+- case IEEE80211_IF_TYPE_WDS:
+- if (is_zero_ether_addr(sdata->u.wds.remote_addr))
+- return -ENOLINK;
+- break;
+- case IEEE80211_IF_TYPE_VLAN:
+- if (!sdata->u.vlan.ap)
+- return -ENOLINK;
+- break;
+- case IEEE80211_IF_TYPE_AP:
+- case IEEE80211_IF_TYPE_STA:
+- case IEEE80211_IF_TYPE_MNTR:
+- case IEEE80211_IF_TYPE_IBSS:
+- /* no special treatment */
+- break;
+- case IEEE80211_IF_TYPE_INVALID:
+- /* cannot happen */
+- WARN_ON(1);
+- break;
+- }
+-
+- if (local->open_count == 0) {
+- res = 0;
+- if (local->ops->start)
+- res = local->ops->start(local_to_hw(local));
+- if (res)
+- return res;
+- need_hw_reconfig = 1;
+- ieee80211_led_radio(local, local->hw.conf.radio_enabled);
+- }
+-
+- switch (sdata->vif.type) {
+- case IEEE80211_IF_TYPE_VLAN:
+- list_add(&sdata->u.vlan.list, &sdata->u.vlan.ap->u.ap.vlans);
+- /* no need to tell driver */
+- break;
+- case IEEE80211_IF_TYPE_MNTR:
+- /* must be before the call to ieee80211_configure_filter */
+- local->monitors++;
+- if (local->monitors == 1) {
+- netif_tx_lock_bh(local->mdev);
+- ieee80211_configure_filter(local);
+- netif_tx_unlock_bh(local->mdev);
+-
+- local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
+- }
+- break;
+- case IEEE80211_IF_TYPE_STA:
+- case IEEE80211_IF_TYPE_IBSS:
+- sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET;
+- /* fall through */
+- default:
+- conf.vif = &sdata->vif;
+- conf.type = sdata->vif.type;
+- conf.mac_addr = dev->dev_addr;
+- res = local->ops->add_interface(local_to_hw(local), &conf);
+- if (res && !local->open_count && local->ops->stop)
+- local->ops->stop(local_to_hw(local));
+- if (res)
+- return res;
+-
+- ieee80211_if_config(dev);
+- ieee80211_reset_erp_info(dev);
+- ieee80211_enable_keys(sdata);
+-
+- if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
+- !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME))
+- netif_carrier_off(dev);
+- else
+- netif_carrier_on(dev);
+- }
+-
+- if (local->open_count == 0) {
+- res = dev_open(local->mdev);
+- WARN_ON(res);
+- tasklet_enable(&local->tx_pending_tasklet);
+- tasklet_enable(&local->tasklet);
+- }
+-
+- /*
+- * set_multicast_list will be invoked by the networking core
+- * which will check whether any increments here were done in
+- * error and sync them down to the hardware as filter flags.
+- */
+- if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
+- atomic_inc(&local->iff_allmultis);
+-
+- if (sdata->flags & IEEE80211_SDATA_PROMISC)
+- atomic_inc(&local->iff_promiscs);
+-
+- local->open_count++;
+- if (need_hw_reconfig)
+- ieee80211_hw_config(local);
+-
+- /*
+- * ieee80211_sta_work is disabled while network interface
+- * is down. Therefore, some configuration changes may not
+- * yet be effective. Trigger execution of ieee80211_sta_work
+- * to fix this.
+- */
+- if(sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+- sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
+- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+- queue_work(local->hw.workqueue, &ifsta->work);
+- }
+-
+- netif_start_queue(dev);
+-
+- return 0;
+-}
+-
+-static int ieee80211_stop(struct net_device *dev)
+-{
+- struct ieee80211_sub_if_data *sdata;
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_if_init_conf conf;
+- struct sta_info *sta;
+- int i;
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-
+- list_for_each_entry(sta, &local->sta_list, list) {
+- if (sta->dev == dev)
+- for (i = 0; i < STA_TID_NUM; i++)
+- ieee80211_sta_stop_rx_ba_session(sta->dev,
+- sta->addr, i,
+- WLAN_BACK_RECIPIENT,
+- WLAN_REASON_QSTA_LEAVE_QBSS);
+- }
+-
+- netif_stop_queue(dev);
+-
+- /*
+- * Don't count this interface for promisc/allmulti while it
+- * is down. dev_mc_unsync() will invoke set_multicast_list
+- * on the master interface which will sync these down to the
+- * hardware as filter flags.
+- */
+- if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
+- atomic_dec(&local->iff_allmultis);
+-
+- if (sdata->flags & IEEE80211_SDATA_PROMISC)
+- atomic_dec(&local->iff_promiscs);
+-
+- dev_mc_unsync(local->mdev, dev);
+-
+- /* APs need special treatment */
+- if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
+- struct ieee80211_sub_if_data *vlan, *tmp;
+- struct beacon_data *old_beacon = sdata->u.ap.beacon;
+-
+- /* remove beacon */
+- rcu_assign_pointer(sdata->u.ap.beacon, NULL);
+- synchronize_rcu();
+- kfree(old_beacon);
+-
+- /* down all dependent devices, that is VLANs */
+- list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans,
+- u.vlan.list)
+- dev_close(vlan->dev);
+- WARN_ON(!list_empty(&sdata->u.ap.vlans));
+- }
+-
+- local->open_count--;
+-
+- switch (sdata->vif.type) {
+- case IEEE80211_IF_TYPE_VLAN:
+- list_del(&sdata->u.vlan.list);
+- sdata->u.vlan.ap = NULL;
+- /* no need to tell driver */
+- break;
+- case IEEE80211_IF_TYPE_MNTR:
+- local->monitors--;
+- if (local->monitors == 0) {
+- netif_tx_lock_bh(local->mdev);
+- ieee80211_configure_filter(local);
+- netif_tx_unlock_bh(local->mdev);
+-
+- local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
+- }
+- break;
+- case IEEE80211_IF_TYPE_STA:
+- case IEEE80211_IF_TYPE_IBSS:
+- sdata->u.sta.state = IEEE80211_DISABLED;
+- del_timer_sync(&sdata->u.sta.timer);
+- /*
+- * When we get here, the interface is marked down.
+- * Call synchronize_rcu() to wait for the RX path
+- * should it be using the interface and enqueuing
+- * frames at this very time on another CPU.
+- */
+- synchronize_rcu();
+- skb_queue_purge(&sdata->u.sta.skb_queue);
+-
+- if (local->scan_dev == sdata->dev) {
+- if (!local->ops->hw_scan) {
+- local->sta_sw_scanning = 0;
+- cancel_delayed_work(&local->scan_work);
+- } else
+- local->sta_hw_scanning = 0;
+- }
+-
+- flush_workqueue(local->hw.workqueue);
+-
+- sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
+- kfree(sdata->u.sta.extra_ie);
+- sdata->u.sta.extra_ie = NULL;
+- sdata->u.sta.extra_ie_len = 0;
+- /* fall through */
+- default:
+- conf.vif = &sdata->vif;
+- conf.type = sdata->vif.type;
+- conf.mac_addr = dev->dev_addr;
+- /* disable all keys for as long as this netdev is down */
+- ieee80211_disable_keys(sdata);
+- local->ops->remove_interface(local_to_hw(local), &conf);
+- }
+-
+- if (local->open_count == 0) {
+- if (netif_running(local->mdev))
+- dev_close(local->mdev);
+-
+- if (local->ops->stop)
+- local->ops->stop(local_to_hw(local));
+-
+- ieee80211_led_radio(local, 0);
+-
+- tasklet_disable(&local->tx_pending_tasklet);
+- tasklet_disable(&local->tasklet);
+- }
+-
+- return 0;
+-}
+-
+-static void ieee80211_set_multicast_list(struct net_device *dev)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- int allmulti, promisc, sdata_allmulti, sdata_promisc;
+-
+- allmulti = !!(dev->flags & IFF_ALLMULTI);
+- promisc = !!(dev->flags & IFF_PROMISC);
+- sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI);
+- sdata_promisc = !!(sdata->flags & IEEE80211_SDATA_PROMISC);
+-
+- if (allmulti != sdata_allmulti) {
+- if (dev->flags & IFF_ALLMULTI)
+- atomic_inc(&local->iff_allmultis);
+- else
+- atomic_dec(&local->iff_allmultis);
+- sdata->flags ^= IEEE80211_SDATA_ALLMULTI;
+- }
+-
+- if (promisc != sdata_promisc) {
+- if (dev->flags & IFF_PROMISC)
+- atomic_inc(&local->iff_promiscs);
+- else
+- atomic_dec(&local->iff_promiscs);
+- sdata->flags ^= IEEE80211_SDATA_PROMISC;
+- }
+-
+- dev_mc_sync(local->mdev, dev);
+-}
+-
+-static const struct header_ops ieee80211_header_ops = {
+- .create = eth_header,
+- .parse = header_parse_80211,
+- .rebuild = eth_rebuild_header,
+- .cache = eth_header_cache,
+- .cache_update = eth_header_cache_update,
+-};
+-
+-/* Must not be called for mdev */
+-void ieee80211_if_setup(struct net_device *dev)
+-{
+- ether_setup(dev);
+- dev->hard_start_xmit = ieee80211_subif_start_xmit;
+- dev->wireless_handlers = &ieee80211_iw_handler_def;
+- dev->set_multicast_list = ieee80211_set_multicast_list;
+- dev->change_mtu = ieee80211_change_mtu;
+- dev->open = ieee80211_open;
+- dev->stop = ieee80211_stop;
+- dev->destructor = ieee80211_if_free;
+-}
+-
+-/* WDS specialties */
+-
+-int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- struct sta_info *sta;
+- DECLARE_MAC_BUF(mac);
+-
+- if (compare_ether_addr(remote_addr, sdata->u.wds.remote_addr) == 0)
+- return 0;
+-
+- /* Create STA entry for the new peer */
+- sta = sta_info_add(local, dev, remote_addr, GFP_KERNEL);
+- if (!sta)
+- return -ENOMEM;
+- sta_info_put(sta);
+-
+- /* Remove STA entry for the old peer */
+- sta = sta_info_get(local, sdata->u.wds.remote_addr);
+- if (sta) {
+- sta_info_free(sta);
+- sta_info_put(sta);
+- } else {
+- printk(KERN_DEBUG "%s: could not find STA entry for WDS link "
+- "peer %s\n",
+- dev->name, print_mac(mac, sdata->u.wds.remote_addr));
+- }
+-
+- /* Update WDS link data */
+- memcpy(&sdata->u.wds.remote_addr, remote_addr, ETH_ALEN);
+-
+- return 0;
+-}
+-
+-/* everything else */
+-
+-static int __ieee80211_if_config(struct net_device *dev,
+- struct sk_buff *beacon,
+- struct ieee80211_tx_control *control)
+-{
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_if_conf conf;
+-
+- if (!local->ops->config_interface || !netif_running(dev))
+- return 0;
+-
+- memset(&conf, 0, sizeof(conf));
+- conf.type = sdata->vif.type;
+- if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+- sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
+- conf.bssid = sdata->u.sta.bssid;
+- conf.ssid = sdata->u.sta.ssid;
+- conf.ssid_len = sdata->u.sta.ssid_len;
+- } else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
+- conf.ssid = sdata->u.ap.ssid;
+- conf.ssid_len = sdata->u.ap.ssid_len;
+- conf.beacon = beacon;
+- conf.beacon_control = control;
+- }
+- return local->ops->config_interface(local_to_hw(local),
+- &sdata->vif, &conf);
+-}
+-
+-int ieee80211_if_config(struct net_device *dev)
+-{
+- return __ieee80211_if_config(dev, NULL, NULL);
+-}
+-
+-int ieee80211_if_config_beacon(struct net_device *dev)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_tx_control control;
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- struct sk_buff *skb;
+-
+- if (!(local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE))
+- return 0;
+- skb = ieee80211_beacon_get(local_to_hw(local), &sdata->vif,
+- &control);
+- if (!skb)
+- return -ENOMEM;
+- return __ieee80211_if_config(dev, skb, &control);
+-}
+-
+-int ieee80211_hw_config(struct ieee80211_local *local)
+-{
+- struct ieee80211_hw_mode *mode;
+- struct ieee80211_channel *chan;
+- int ret = 0;
+-
+- if (local->sta_sw_scanning) {
+- chan = local->scan_channel;
+- mode = local->scan_hw_mode;
+- } else {
+- chan = local->oper_channel;
+- mode = local->oper_hw_mode;
+- }
+-
+- local->hw.conf.channel = chan->chan;
+- local->hw.conf.channel_val = chan->val;
+- if (!local->hw.conf.power_level) {
+- local->hw.conf.power_level = chan->power_level;
+- } else {
+- local->hw.conf.power_level = min(chan->power_level,
+- local->hw.conf.power_level);
+- }
+- local->hw.conf.freq = chan->freq;
+- local->hw.conf.phymode = mode->mode;
+- local->hw.conf.antenna_max = chan->antenna_max;
+- local->hw.conf.chan = chan;
+- local->hw.conf.mode = mode;
+-
+-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+- printk(KERN_DEBUG "HW CONFIG: channel=%d freq=%d "
+- "phymode=%d\n", local->hw.conf.channel, local->hw.conf.freq,
+- local->hw.conf.phymode);
+-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+-
+- if (local->open_count)
+- ret = local->ops->config(local_to_hw(local), &local->hw.conf);
+-
+- return ret;
+-}
+-
+-/**
+- * ieee80211_hw_config_ht should be used only after legacy configuration
+- * has been determined, as ht configuration depends upon the hardware's
+- * HT abilities for a _specific_ band.
+- */
+-int ieee80211_hw_config_ht(struct ieee80211_local *local, int enable_ht,
+- struct ieee80211_ht_info *req_ht_cap,
+- struct ieee80211_ht_bss_info *req_bss_cap)
+-{
+- struct ieee80211_conf *conf = &local->hw.conf;
+- struct ieee80211_hw_mode *mode = conf->mode;
+- int i;
+-
+- /* HT is not supported */
+- if (!mode->ht_info.ht_supported) {
+- conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
+- return -EOPNOTSUPP;
+- }
+-
+- /* disable HT */
+- if (!enable_ht) {
+- conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
+- } else {
+- conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE;
+- conf->ht_conf.cap = req_ht_cap->cap & mode->ht_info.cap;
+- conf->ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS);
+- conf->ht_conf.cap |=
+- mode->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS;
+- conf->ht_bss_conf.primary_channel =
+- req_bss_cap->primary_channel;
+- conf->ht_bss_conf.bss_cap = req_bss_cap->bss_cap;
+- conf->ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode;
+- for (i = 0; i < SUPP_MCS_SET_LEN; i++)
+- conf->ht_conf.supp_mcs_set[i] =
+- mode->ht_info.supp_mcs_set[i] &
+- req_ht_cap->supp_mcs_set[i];
+-
+- /* In STA mode, this gives us indication
+- * to the AP's mode of operation */
+- conf->ht_conf.ht_supported = 1;
+- conf->ht_conf.ampdu_factor = req_ht_cap->ampdu_factor;
+- conf->ht_conf.ampdu_density = req_ht_cap->ampdu_density;
+- }
+-
+- local->ops->conf_ht(local_to_hw(local), &local->hw.conf);
+-
+- return 0;
+-}
+-
+-void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
+- u32 changed)
+-{
+- struct ieee80211_local *local = sdata->local;
+-
+- if (!changed)
+- return;
+-
+- if (local->ops->bss_info_changed)
+- local->ops->bss_info_changed(local_to_hw(local),
+- &sdata->vif,
+- &sdata->bss_conf,
+- changed);
+-}
+-
+-void ieee80211_reset_erp_info(struct net_device *dev)
+-{
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-
+- sdata->bss_conf.use_cts_prot = 0;
+- sdata->bss_conf.use_short_preamble = 0;
+- ieee80211_bss_info_change_notify(sdata,
+- BSS_CHANGED_ERP_CTS_PROT |
+- BSS_CHANGED_ERP_PREAMBLE);
+-}
+-
+-void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
+- struct sk_buff *skb,
+- struct ieee80211_tx_status *status)
+-{
+- struct ieee80211_local *local = hw_to_local(hw);
+- struct ieee80211_tx_status *saved;
+- int tmp;
+-
+- skb->dev = local->mdev;
+- saved = kmalloc(sizeof(struct ieee80211_tx_status), GFP_ATOMIC);
+- if (unlikely(!saved)) {
+- if (net_ratelimit())
+- printk(KERN_WARNING "%s: Not enough memory, "
+- "dropping tx status", skb->dev->name);
+- /* should be dev_kfree_skb_irq, but due to this function being
+- * named _irqsafe instead of just _irq we can't be sure that
+- * people won't call it from non-irq contexts */
+- dev_kfree_skb_any(skb);
+- return;
+- }
+- memcpy(saved, status, sizeof(struct ieee80211_tx_status));
+- /* copy pointer to saved status into skb->cb for use by tasklet */
+- memcpy(skb->cb, &saved, sizeof(saved));
+-
+- skb->pkt_type = IEEE80211_TX_STATUS_MSG;
+- skb_queue_tail(status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS ?
+- &local->skb_queue : &local->skb_queue_unreliable, skb);
+- tmp = skb_queue_len(&local->skb_queue) +
+- skb_queue_len(&local->skb_queue_unreliable);
+- while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT &&
+- (skb = skb_dequeue(&local->skb_queue_unreliable))) {
+- memcpy(&saved, skb->cb, sizeof(saved));
+- kfree(saved);
+- dev_kfree_skb_irq(skb);
+- tmp--;
+- I802_DEBUG_INC(local->tx_status_drop);
+- }
+- tasklet_schedule(&local->tasklet);
+-}
+-EXPORT_SYMBOL(ieee80211_tx_status_irqsafe);
+-
+-static void ieee80211_tasklet_handler(unsigned long data)
+-{
+- struct ieee80211_local *local = (struct ieee80211_local *) data;
+- struct sk_buff *skb;
+- struct ieee80211_rx_status rx_status;
+- struct ieee80211_tx_status *tx_status;
+-
+- while ((skb = skb_dequeue(&local->skb_queue)) ||
+- (skb = skb_dequeue(&local->skb_queue_unreliable))) {
+- switch (skb->pkt_type) {
+- case IEEE80211_RX_MSG:
+- /* status is in skb->cb */
+- memcpy(&rx_status, skb->cb, sizeof(rx_status));
+- /* Clear skb->pkt_type in order to not confuse kernel
+- * netstack. */
+- skb->pkt_type = 0;
+- __ieee80211_rx(local_to_hw(local), skb, &rx_status);
+- break;
+- case IEEE80211_TX_STATUS_MSG:
+- /* get pointer to saved status out of skb->cb */
+- memcpy(&tx_status, skb->cb, sizeof(tx_status));
+- skb->pkt_type = 0;
+- ieee80211_tx_status(local_to_hw(local),
+- skb, tx_status);
+- kfree(tx_status);
+- break;
+- default: /* should never get here! */
+- printk(KERN_ERR "%s: Unknown message type (%d)\n",
+- wiphy_name(local->hw.wiphy), skb->pkt_type);
+- dev_kfree_skb(skb);
+- break;
+- }
+- }
+-}
+-
+-/* Remove added headers (e.g., QoS control), encryption header/MIC, etc. to
+- * make a prepared TX frame (one that has been given to hw) to look like brand
+- * new IEEE 802.11 frame that is ready to go through TX processing again.
+- * Also, tx_packet_data in cb is restored from tx_control. */
+-static void ieee80211_remove_tx_extra(struct ieee80211_local *local,
+- struct ieee80211_key *key,
+- struct sk_buff *skb,
+- struct ieee80211_tx_control *control)
+-{
+- int hdrlen, iv_len, mic_len;
+- struct ieee80211_tx_packet_data *pkt_data;
+-
+- pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
+- pkt_data->ifindex = vif_to_sdata(control->vif)->dev->ifindex;
+- pkt_data->flags = 0;
+- if (control->flags & IEEE80211_TXCTL_REQ_TX_STATUS)
+- pkt_data->flags |= IEEE80211_TXPD_REQ_TX_STATUS;
+- if (control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)
+- pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT;
+- if (control->flags & IEEE80211_TXCTL_REQUEUE)
+- pkt_data->flags |= IEEE80211_TXPD_REQUEUE;
+- if (control->flags & IEEE80211_TXCTL_EAPOL_FRAME)
+- pkt_data->flags |= IEEE80211_TXPD_EAPOL_FRAME;
+- pkt_data->queue = control->queue;
+-
+- hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+-
+- if (!key)
+- goto no_key;
+-
+- switch (key->conf.alg) {
+- case ALG_WEP:
+- iv_len = WEP_IV_LEN;
+- mic_len = WEP_ICV_LEN;
+- break;
+- case ALG_TKIP:
+- iv_len = TKIP_IV_LEN;
+- mic_len = TKIP_ICV_LEN;
+- break;
+- case ALG_CCMP:
+- iv_len = CCMP_HDR_LEN;
+- mic_len = CCMP_MIC_LEN;
+- break;
+- default:
+- goto no_key;
+- }
+-
+- if (skb->len >= mic_len &&
+- !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
+- skb_trim(skb, skb->len - mic_len);
+- if (skb->len >= iv_len && skb->len > hdrlen) {
+- memmove(skb->data + iv_len, skb->data, hdrlen);
+- skb_pull(skb, iv_len);
+- }
+-
+-no_key:
+- {
+- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+- u16 fc = le16_to_cpu(hdr->frame_control);
+- if ((fc & 0x8C) == 0x88) /* QoS Control Field */ {
+- fc &= ~IEEE80211_STYPE_QOS_DATA;
+- hdr->frame_control = cpu_to_le16(fc);
+- memmove(skb->data + 2, skb->data, hdrlen - 2);
+- skb_pull(skb, 2);
+- }
+- }
+-}
+-
+-void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
+- struct ieee80211_tx_status *status)
+-{
+- struct sk_buff *skb2;
+- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+- struct ieee80211_local *local = hw_to_local(hw);
+- u16 frag, type;
+- struct ieee80211_tx_status_rtap_hdr *rthdr;
+- struct ieee80211_sub_if_data *sdata;
+- int monitors;
+-
+- if (!status) {
+- printk(KERN_ERR
+- "%s: ieee80211_tx_status called with NULL status\n",
+- wiphy_name(local->hw.wiphy));
+- dev_kfree_skb(skb);
+- return;
+- }
+-
+- if (status->excessive_retries) {
+- struct sta_info *sta;
+- sta = sta_info_get(local, hdr->addr1);
+- if (sta) {
+- if (sta->flags & WLAN_STA_PS) {
+- /* The STA is in power save mode, so assume
+- * that this TX packet failed because of that.
+- */
+- status->excessive_retries = 0;
+- status->flags |= IEEE80211_TX_STATUS_TX_FILTERED;
+- }
+- sta_info_put(sta);
+- }
+- }
+-
+- if (status->flags & IEEE80211_TX_STATUS_TX_FILTERED) {
+- struct sta_info *sta;
+- sta = sta_info_get(local, hdr->addr1);
+- if (sta) {
+- sta->tx_filtered_count++;
+-
+- /* Clear the TX filter mask for this STA when sending
+- * the next packet. If the STA went to power save mode,
+- * this will happen when it is waking up for the next
+- * time. */
+- sta->clear_dst_mask = 1;
+-
+- /* TODO: Is the WLAN_STA_PS flag always set here or is
+- * the race between RX and TX status causing some
+- * packets to be filtered out before 80211.o gets an
+- * update for PS status? This seems to be the case, so
+- * no changes are likely to be needed. */
+- if (sta->flags & WLAN_STA_PS &&
+- skb_queue_len(&sta->tx_filtered) <
+- STA_MAX_TX_BUFFER) {
+- ieee80211_remove_tx_extra(local, sta->key,
+- skb,
+- &status->control);
+- skb_queue_tail(&sta->tx_filtered, skb);
+- } else if (!(sta->flags & WLAN_STA_PS) &&
+- !(status->control.flags & IEEE80211_TXCTL_REQUEUE)) {
+- /* Software retry the packet once */
+- status->control.flags |= IEEE80211_TXCTL_REQUEUE;
+- ieee80211_remove_tx_extra(local, sta->key,
+- skb,
+- &status->control);
+- dev_queue_xmit(skb);
+- } else {
+- if (net_ratelimit()) {
+- printk(KERN_DEBUG "%s: dropped TX "
+- "filtered frame queue_len=%d "
+- "PS=%d @%lu\n",
+- wiphy_name(local->hw.wiphy),
+- skb_queue_len(
+- &sta->tx_filtered),
+- !!(sta->flags & WLAN_STA_PS),
+- jiffies);
+- }
+- dev_kfree_skb(skb);
+- }
+- sta_info_put(sta);
+- return;
+- }
+- } else
+- rate_control_tx_status(local->mdev, skb, status);
+-
+- ieee80211_led_tx(local, 0);
+-
+- /* SNMP counters
+- * Fragments are passed to low-level drivers as separate skbs, so these
+- * are actually fragments, not frames. Update frame counters only for
+- * the first fragment of the frame. */
+-
+- frag = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
+- type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE;
+-
+- if (status->flags & IEEE80211_TX_STATUS_ACK) {
+- if (frag == 0) {
+- local->dot11TransmittedFrameCount++;
+- if (is_multicast_ether_addr(hdr->addr1))
+- local->dot11MulticastTransmittedFrameCount++;
+- if (status->retry_count > 0)
+- local->dot11RetryCount++;
+- if (status->retry_count > 1)
+- local->dot11MultipleRetryCount++;
+- }
+-
+- /* This counter shall be incremented for an acknowledged MPDU
+- * with an individual address in the address 1 field or an MPDU
+- * with a multicast address in the address 1 field of type Data
+- * or Management. */
+- if (!is_multicast_ether_addr(hdr->addr1) ||
+- type == IEEE80211_FTYPE_DATA ||
+- type == IEEE80211_FTYPE_MGMT)
+- local->dot11TransmittedFragmentCount++;
+- } else {
+- if (frag == 0)
+- local->dot11FailedCount++;
+- }
+-
+- /* this was a transmitted frame, but now we want to reuse it */
+- skb_orphan(skb);
+-
+- if (!local->monitors) {
+- dev_kfree_skb(skb);
+- return;
+- }
+-
+- /* send frame to monitor interfaces now */
+-
+- if (skb_headroom(skb) < sizeof(*rthdr)) {
+- printk(KERN_ERR "ieee80211_tx_status: headroom too small\n");
+- dev_kfree_skb(skb);
+- return;
+- }
+-
+- rthdr = (struct ieee80211_tx_status_rtap_hdr*)
+- skb_push(skb, sizeof(*rthdr));
+-
+- memset(rthdr, 0, sizeof(*rthdr));
+- rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr));
+- rthdr->hdr.it_present =
+- cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
+- (1 << IEEE80211_RADIOTAP_DATA_RETRIES));
+-
+- if (!(status->flags & IEEE80211_TX_STATUS_ACK) &&
+- !is_multicast_ether_addr(hdr->addr1))
+- rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL);
+-
+- if ((status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) &&
+- (status->control.flags & IEEE80211_TXCTL_USE_CTS_PROTECT))
+- rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS);
+- else if (status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS)
+- rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS);
+-
+- rthdr->data_retries = status->retry_count;
+-
+- rcu_read_lock();
+- monitors = local->monitors;
+- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+- /*
+- * Using the monitors counter is possibly racy, but
+- * if the value is wrong we simply either clone the skb
+- * once too much or forget sending it to one monitor iface
+- * The latter case isn't nice but fixing the race is much
+- * more complicated.
+- */
+- if (!monitors || !skb)
+- goto out;
+-
+- if (sdata->vif.type == IEEE80211_IF_TYPE_MNTR) {
+- if (!netif_running(sdata->dev))
+- continue;
+- monitors--;
+- if (monitors)
+- skb2 = skb_clone(skb, GFP_ATOMIC);
+- else
+- skb2 = NULL;
+- skb->dev = sdata->dev;
+- /* XXX: is this sufficient for BPF? */
+- skb_set_mac_header(skb, 0);
+- skb->ip_summed = CHECKSUM_UNNECESSARY;
+- skb->pkt_type = PACKET_OTHERHOST;
+- skb->protocol = htons(ETH_P_802_2);
+- memset(skb->cb, 0, sizeof(skb->cb));
+- netif_rx(skb);
+- skb = skb2;
+- }
+- }
+- out:
+- rcu_read_unlock();
+- if (skb)
+- dev_kfree_skb(skb);
+-}
+-EXPORT_SYMBOL(ieee80211_tx_status);
+-
+-struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
+- const struct ieee80211_ops *ops)
+-{
+- struct net_device *mdev;
+- struct ieee80211_local *local;
+- struct ieee80211_sub_if_data *sdata;
+- int priv_size;
+- struct wiphy *wiphy;
+-
+- /* Ensure 32-byte alignment of our private data and hw private data.
+- * We use the wiphy priv data for both our ieee80211_local and for
+- * the driver's private data
+- *
+- * In memory it'll be like this:
+- *
+- * +-------------------------+
+- * | struct wiphy |
+- * +-------------------------+
+- * | struct ieee80211_local |
+- * +-------------------------+
+- * | driver's private data |
+- * +-------------------------+
+- *
+- */
+- priv_size = ((sizeof(struct ieee80211_local) +
+- NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST) +
+- priv_data_len;
+-
+- wiphy = wiphy_new(&mac80211_config_ops, priv_size);
+-
+- if (!wiphy)
+- return NULL;
+-
+- wiphy->privid = mac80211_wiphy_privid;
+-
+- local = wiphy_priv(wiphy);
+- local->hw.wiphy = wiphy;
+-
+- local->hw.priv = (char *)local +
+- ((sizeof(struct ieee80211_local) +
+- NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
+-
+- BUG_ON(!ops->tx);
+- BUG_ON(!ops->start);
+- BUG_ON(!ops->stop);
+- BUG_ON(!ops->config);
+- BUG_ON(!ops->add_interface);
+- BUG_ON(!ops->remove_interface);
+- BUG_ON(!ops->configure_filter);
+- local->ops = ops;
+-
+- /* for now, mdev needs sub_if_data :/ */
+- mdev = alloc_netdev(sizeof(struct ieee80211_sub_if_data),
+- "wmaster%d", ether_setup);
+- if (!mdev) {
+- wiphy_free(wiphy);
+- return NULL;
+- }
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(mdev);
+- mdev->ieee80211_ptr = &sdata->wdev;
+- sdata->wdev.wiphy = wiphy;
+-
+- local->hw.queues = 1; /* default */
+-
+- local->mdev = mdev;
+- local->rx_pre_handlers = ieee80211_rx_pre_handlers;
+- local->rx_handlers = ieee80211_rx_handlers;
+- local->tx_handlers = ieee80211_tx_handlers;
+-
+- local->bridge_packets = 1;
+-
+- local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
+- local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
+- local->short_retry_limit = 7;
+- local->long_retry_limit = 4;
+- local->hw.conf.radio_enabled = 1;
+-
+- local->enabled_modes = ~0;
+-
+- INIT_LIST_HEAD(&local->modes_list);
+-
+- INIT_LIST_HEAD(&local->interfaces);
+-
+- INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work);
+- ieee80211_rx_bss_list_init(mdev);
+-
+- sta_info_init(local);
+-
+- mdev->hard_start_xmit = ieee80211_master_start_xmit;
+- mdev->open = ieee80211_master_open;
+- mdev->stop = ieee80211_master_stop;
+- mdev->type = ARPHRD_IEEE80211;
+- mdev->header_ops = &ieee80211_header_ops;
+- mdev->set_multicast_list = ieee80211_master_set_multicast_list;
+-
+- sdata->vif.type = IEEE80211_IF_TYPE_AP;
+- sdata->dev = mdev;
+- sdata->local = local;
+- sdata->u.ap.force_unicast_rateidx = -1;
+- sdata->u.ap.max_ratectrl_rateidx = -1;
+- ieee80211_if_sdata_init(sdata);
+- /* no RCU needed since we're still during init phase */
+- list_add_tail(&sdata->list, &local->interfaces);
+-
+- tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending,
+- (unsigned long)local);
+- tasklet_disable(&local->tx_pending_tasklet);
+-
+- tasklet_init(&local->tasklet,
+- ieee80211_tasklet_handler,
+- (unsigned long) local);
+- tasklet_disable(&local->tasklet);
+-
+- skb_queue_head_init(&local->skb_queue);
+- skb_queue_head_init(&local->skb_queue_unreliable);
+-
+- return local_to_hw(local);
+-}
+-EXPORT_SYMBOL(ieee80211_alloc_hw);
+-
+-int ieee80211_register_hw(struct ieee80211_hw *hw)
+-{
+- struct ieee80211_local *local = hw_to_local(hw);
+- const char *name;
+- int result;
+-
+- result = wiphy_register(local->hw.wiphy);
+- if (result < 0)
+- return result;
+-
+- name = wiphy_dev(local->hw.wiphy)->driver->name;
+- local->hw.workqueue = create_singlethread_workqueue(name);
+- if (!local->hw.workqueue) {
+- result = -ENOMEM;
+- goto fail_workqueue;
+- }
+-
+- /*
+- * The hardware needs headroom for sending the frame,
+- * and we need some headroom for passing the frame to monitor
+- * interfaces, but never both at the same time.
+- */
+- local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
+- sizeof(struct ieee80211_tx_status_rtap_hdr));
+-
+- debugfs_hw_add(local);
+-
+- local->hw.conf.beacon_int = 1000;
+-
+- local->wstats_flags |= local->hw.max_rssi ?
+- IW_QUAL_LEVEL_UPDATED : IW_QUAL_LEVEL_INVALID;
+- local->wstats_flags |= local->hw.max_signal ?
+- IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID;
+- local->wstats_flags |= local->hw.max_noise ?
+- IW_QUAL_NOISE_UPDATED : IW_QUAL_NOISE_INVALID;
+- if (local->hw.max_rssi < 0 || local->hw.max_noise < 0)
+- local->wstats_flags |= IW_QUAL_DBM;
+-
+- result = sta_info_start(local);
+- if (result < 0)
+- goto fail_sta_info;
+-
+- rtnl_lock();
+- result = dev_alloc_name(local->mdev, local->mdev->name);
+- if (result < 0)
+- goto fail_dev;
+-
+- memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
+- SET_NETDEV_DEV(local->mdev, wiphy_dev(local->hw.wiphy));
+-
+- result = register_netdevice(local->mdev);
+- if (result < 0)
+- goto fail_dev;
+-
+- ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
+- ieee80211_if_set_type(local->mdev, IEEE80211_IF_TYPE_AP);
+-
+- result = ieee80211_init_rate_ctrl_alg(local,
+- hw->rate_control_algorithm);
+- if (result < 0) {
+- printk(KERN_DEBUG "%s: Failed to initialize rate control "
+- "algorithm\n", wiphy_name(local->hw.wiphy));
+- goto fail_rate;
+- }
+-
+- result = ieee80211_wep_init(local);
+-
+- if (result < 0) {
+- printk(KERN_DEBUG "%s: Failed to initialize wep\n",
+- wiphy_name(local->hw.wiphy));
+- goto fail_wep;
+- }
+-
+- ieee80211_install_qdisc(local->mdev);
+-
+- /* add one default STA interface */
+- result = ieee80211_if_add(local->mdev, "wlan%d", NULL,
+- IEEE80211_IF_TYPE_STA);
+- if (result)
+- printk(KERN_WARNING "%s: Failed to add default virtual iface\n",
+- wiphy_name(local->hw.wiphy));
+-
+- local->reg_state = IEEE80211_DEV_REGISTERED;
+- rtnl_unlock();
+-
+- ieee80211_led_init(local);
+-
+- return 0;
+-
+-fail_wep:
+- rate_control_deinitialize(local);
+-fail_rate:
+- ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
+- unregister_netdevice(local->mdev);
+-fail_dev:
+- rtnl_unlock();
+- sta_info_stop(local);
+-fail_sta_info:
+- debugfs_hw_del(local);
+- destroy_workqueue(local->hw.workqueue);
+-fail_workqueue:
+- wiphy_unregister(local->hw.wiphy);
+- return result;
+-}
+-EXPORT_SYMBOL(ieee80211_register_hw);
+-
+-int ieee80211_register_hwmode(struct ieee80211_hw *hw,
+- struct ieee80211_hw_mode *mode)
+-{
+- struct ieee80211_local *local = hw_to_local(hw);
+- struct ieee80211_rate *rate;
+- int i;
+-
+- INIT_LIST_HEAD(&mode->list);
+- list_add_tail(&mode->list, &local->modes_list);
+-
+- local->hw_modes |= (1 << mode->mode);
+- for (i = 0; i < mode->num_rates; i++) {
+- rate = &(mode->rates[i]);
+- rate->rate_inv = CHAN_UTIL_RATE_LCM / rate->rate;
+- }
+- ieee80211_prepare_rates(local, mode);
+-
+- if (!local->oper_hw_mode) {
+- /* Default to this mode */
+- local->hw.conf.phymode = mode->mode;
+- local->oper_hw_mode = local->scan_hw_mode = mode;
+- local->oper_channel = local->scan_channel = &mode->channels[0];
+- local->hw.conf.mode = local->oper_hw_mode;
+- local->hw.conf.chan = local->oper_channel;
+- }
+-
+- if (!(hw->flags & IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED))
+- ieee80211_set_default_regdomain(mode);
+-
+- return 0;
+-}
+-EXPORT_SYMBOL(ieee80211_register_hwmode);
+-
+-void ieee80211_unregister_hw(struct ieee80211_hw *hw)
+-{
+- struct ieee80211_local *local = hw_to_local(hw);
+- struct ieee80211_sub_if_data *sdata, *tmp;
+- int i;
+-
+- tasklet_kill(&local->tx_pending_tasklet);
+- tasklet_kill(&local->tasklet);
+-
+- rtnl_lock();
+-
+- BUG_ON(local->reg_state != IEEE80211_DEV_REGISTERED);
+-
+- local->reg_state = IEEE80211_DEV_UNREGISTERED;
+-
+- /*
+- * At this point, interface list manipulations are fine
+- * because the driver cannot be handing us frames any
+- * more and the tasklet is killed.
+- */
+-
+- /*
+- * First, we remove all non-master interfaces. Do this because they
+- * may have bss pointer dependency on the master, and when we free
+- * the master these would be freed as well, breaking our list
+- * iteration completely.
+- */
+- list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
+- if (sdata->dev == local->mdev)
+- continue;
+- list_del(&sdata->list);
+- __ieee80211_if_del(local, sdata);
+- }
+-
+- /* then, finally, remove the master interface */
+- __ieee80211_if_del(local, IEEE80211_DEV_TO_SUB_IF(local->mdev));
+-
+- rtnl_unlock();
+-
+- ieee80211_rx_bss_list_deinit(local->mdev);
+- ieee80211_clear_tx_pending(local);
+- sta_info_stop(local);
+- rate_control_deinitialize(local);
+- debugfs_hw_del(local);
+-
+- for (i = 0; i < NUM_IEEE80211_MODES; i++) {
+- kfree(local->supp_rates[i]);
+- kfree(local->basic_rates[i]);
+- }
+-
+- if (skb_queue_len(&local->skb_queue)
+- || skb_queue_len(&local->skb_queue_unreliable))
+- printk(KERN_WARNING "%s: skb_queue not empty\n",
+- wiphy_name(local->hw.wiphy));
+- skb_queue_purge(&local->skb_queue);
+- skb_queue_purge(&local->skb_queue_unreliable);
+-
+- destroy_workqueue(local->hw.workqueue);
+- wiphy_unregister(local->hw.wiphy);
+- ieee80211_wep_free(local);
+- ieee80211_led_exit(local);
+-}
+-EXPORT_SYMBOL(ieee80211_unregister_hw);
+-
+-void ieee80211_free_hw(struct ieee80211_hw *hw)
+-{
+- struct ieee80211_local *local = hw_to_local(hw);
+-
+- ieee80211_if_free(local->mdev);
+- wiphy_free(local->hw.wiphy);
+-}
+-EXPORT_SYMBOL(ieee80211_free_hw);
+-
+-static int __init ieee80211_init(void)
+-{
+- struct sk_buff *skb;
+- int ret;
+-
+- BUILD_BUG_ON(sizeof(struct ieee80211_tx_packet_data) > sizeof(skb->cb));
+-
+- ret = rc80211_simple_init();
+- if (ret)
+- goto out;
+-
+- ret = rc80211_pid_init();
+- if (ret)
+- goto out_cleanup_simple;
+-
+- ret = ieee80211_wme_register();
+- if (ret) {
+- printk(KERN_DEBUG "ieee80211_init: failed to "
+- "initialize WME (err=%d)\n", ret);
+- goto out_cleanup_pid;
+- }
+-
+- ieee80211_debugfs_netdev_init();
+- ieee80211_regdomain_init();
+-
+- return 0;
+-
+- out_cleanup_pid:
+- rc80211_pid_exit();
+- out_cleanup_simple:
+- rc80211_simple_exit();
+- out:
+- return ret;
+-}
+-
+-static void __exit ieee80211_exit(void)
+-{
+- rc80211_simple_exit();
+- rc80211_pid_exit();
+-
+- ieee80211_wme_unregister();
+- ieee80211_debugfs_netdev_exit();
+-}
+-
+-
+-subsys_initcall(ieee80211_init);
+-module_exit(ieee80211_exit);
+-
+-MODULE_DESCRIPTION("IEEE 802.11 subsystem");
+-MODULE_LICENSE("GPL");
+diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
+index 72ecbf7..8e53ce7 100644
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -23,7 +23,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/etherdevice.h>
+ #include <net/wireless.h>
+-#include "ieee80211_key.h"
++#include "key.h"
+ #include "sta_info.h"
+
+ /* ieee80211.o internal definitions, etc. These are not included into
+@@ -35,9 +35,9 @@
+
+ #define WLAN_FC_DATA_PRESENT(fc) (((fc) & 0x4c) == 0x08)
+
+-struct ieee80211_local;
++#define IEEE80211_FC(type, subtype) cpu_to_le16(type | subtype)
+
+-#define IEEE80211_ALIGN32_PAD(a) ((4 - ((a) & 3)) & 3)
++struct ieee80211_local;
+
+ /* Maximum number of broadcast/multicast frames to buffer when some of the
+ * associated stations are using power saving. */
+@@ -73,14 +73,14 @@ struct ieee80211_fragment_entry {
+ struct ieee80211_sta_bss {
+ struct list_head list;
+ struct ieee80211_sta_bss *hnext;
++ size_t ssid_len;
++
+ atomic_t users;
+
+ u8 bssid[ETH_ALEN];
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
+- size_t ssid_len;
+ u16 capability; /* host byte order */
+- int hw_mode;
+- int channel;
++ enum ieee80211_band band;
+ int freq;
+ int rssi, signal, noise;
+ u8 *wpa_ie;
+@@ -91,13 +91,18 @@ struct ieee80211_sta_bss {
+ size_t wmm_ie_len;
+ u8 *ht_ie;
+ size_t ht_ie_len;
++#ifdef CONFIG_MAC80211_MESH
++ u8 *mesh_id;
++ size_t mesh_id_len;
++ u8 *mesh_cfg;
++#endif
+ #define IEEE80211_MAX_SUPP_RATES 32
+ u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
+ size_t supp_rates_len;
+- int beacon_int;
+ u64 timestamp;
++ int beacon_int;
+
+- int probe_resp;
++ bool probe_resp;
+ unsigned long last_update;
+
+ /* during assocation, we save an ERP value from a probe response so
+@@ -108,56 +113,98 @@ struct ieee80211_sta_bss {
+ u8 erp_value;
+ };
+
++static inline u8 *bss_mesh_cfg(struct ieee80211_sta_bss *bss)
++{
++#ifdef CONFIG_MAC80211_MESH
++ return bss->mesh_cfg;
++#endif
++ return NULL;
++}
+
+-typedef enum {
+- TXRX_CONTINUE, TXRX_DROP, TXRX_QUEUED
+-} ieee80211_txrx_result;
++static inline u8 *bss_mesh_id(struct ieee80211_sta_bss *bss)
++{
++#ifdef CONFIG_MAC80211_MESH
++ return bss->mesh_id;
++#endif
++ return NULL;
++}
+
+-/* flags used in struct ieee80211_txrx_data.flags */
+-/* whether the MSDU was fragmented */
+-#define IEEE80211_TXRXD_FRAGMENTED BIT(0)
+-#define IEEE80211_TXRXD_TXUNICAST BIT(1)
+-#define IEEE80211_TXRXD_TXPS_BUFFERED BIT(2)
+-#define IEEE80211_TXRXD_TXPROBE_LAST_FRAG BIT(3)
+-#define IEEE80211_TXRXD_RXIN_SCAN BIT(4)
+-/* frame is destined to interface currently processed (incl. multicast frames) */
+-#define IEEE80211_TXRXD_RXRA_MATCH BIT(5)
+-#define IEEE80211_TXRXD_TX_INJECTED BIT(6)
+-#define IEEE80211_TXRXD_RX_AMSDU BIT(7)
+-struct ieee80211_txrx_data {
++static inline u8 bss_mesh_id_len(struct ieee80211_sta_bss *bss)
++{
++#ifdef CONFIG_MAC80211_MESH
++ return bss->mesh_id_len;
++#endif
++ return 0;
++}
++
++
++typedef unsigned __bitwise__ ieee80211_tx_result;
++#define TX_CONTINUE ((__force ieee80211_tx_result) 0u)
++#define TX_DROP ((__force ieee80211_tx_result) 1u)
++#define TX_QUEUED ((__force ieee80211_tx_result) 2u)
++
++#define IEEE80211_TX_FRAGMENTED BIT(0)
++#define IEEE80211_TX_UNICAST BIT(1)
++#define IEEE80211_TX_PS_BUFFERED BIT(2)
++#define IEEE80211_TX_PROBE_LAST_FRAG BIT(3)
++#define IEEE80211_TX_INJECTED BIT(4)
++
++struct ieee80211_tx_data {
+ struct sk_buff *skb;
+ struct net_device *dev;
+ struct ieee80211_local *local;
+ struct ieee80211_sub_if_data *sdata;
+ struct sta_info *sta;
++ struct ieee80211_key *key;
++
++ struct ieee80211_tx_control *control;
++ struct ieee80211_channel *channel;
++ struct ieee80211_rate *rate;
++ /* use this rate (if set) for last fragment; rate can
++ * be set to lower rate for the first fragments, e.g.,
++ * when using CTS protection with IEEE 802.11g. */
++ struct ieee80211_rate *last_frag_rate;
++
++ /* Extra fragments (in addition to the first fragment
++ * in skb) */
++ struct sk_buff **extra_frag;
++ int num_extra_frag;
++
+ u16 fc, ethertype;
++ unsigned int flags;
++};
++
++
++typedef unsigned __bitwise__ ieee80211_rx_result;
++#define RX_CONTINUE ((__force ieee80211_rx_result) 0u)
++#define RX_DROP_UNUSABLE ((__force ieee80211_rx_result) 1u)
++#define RX_DROP_MONITOR ((__force ieee80211_rx_result) 2u)
++#define RX_QUEUED ((__force ieee80211_rx_result) 3u)
++
++#define IEEE80211_RX_IN_SCAN BIT(0)
++/* frame is destined to interface currently processed (incl. multicast frames) */
++#define IEEE80211_RX_RA_MATCH BIT(1)
++#define IEEE80211_RX_AMSDU BIT(2)
++#define IEEE80211_RX_CMNTR_REPORTED BIT(3)
++#define IEEE80211_RX_FRAGMENTED BIT(4)
++
++struct ieee80211_rx_data {
++ struct sk_buff *skb;
++ struct net_device *dev;
++ struct ieee80211_local *local;
++ struct ieee80211_sub_if_data *sdata;
++ struct sta_info *sta;
+ struct ieee80211_key *key;
++ struct ieee80211_rx_status *status;
++ struct ieee80211_rate *rate;
++
++ u16 fc, ethertype;
+ unsigned int flags;
+- union {
+- struct {
+- struct ieee80211_tx_control *control;
+- struct ieee80211_hw_mode *mode;
+- struct ieee80211_rate *rate;
+- /* use this rate (if set) for last fragment; rate can
+- * be set to lower rate for the first fragments, e.g.,
+- * when using CTS protection with IEEE 802.11g. */
+- struct ieee80211_rate *last_frag_rate;
+- int last_frag_hwrate;
+-
+- /* Extra fragments (in addition to the first fragment
+- * in skb) */
+- int num_extra_frag;
+- struct sk_buff **extra_frag;
+- } tx;
+- struct {
+- struct ieee80211_rx_status *status;
+- int sent_ps_buffered;
+- int queue;
+- int load;
+- u32 tkip_iv32;
+- u16 tkip_iv16;
+- } rx;
+- } u;
++ int sent_ps_buffered;
++ int queue;
++ int load;
++ u32 tkip_iv32;
++ u16 tkip_iv16;
+ };
+
+ /* flags used in struct ieee80211_tx_packet_data.flags */
+@@ -165,6 +212,7 @@ struct ieee80211_txrx_data {
+ #define IEEE80211_TXPD_DO_NOT_ENCRYPT BIT(1)
+ #define IEEE80211_TXPD_REQUEUE BIT(2)
+ #define IEEE80211_TXPD_EAPOL_FRAME BIT(3)
++#define IEEE80211_TXPD_AMPDU BIT(4)
+ /* Stored in sk_buff->cb */
+ struct ieee80211_tx_packet_data {
+ int ifindex;
+@@ -176,20 +224,12 @@ struct ieee80211_tx_packet_data {
+ struct ieee80211_tx_stored_packet {
+ struct ieee80211_tx_control control;
+ struct sk_buff *skb;
+- int num_extra_frag;
+ struct sk_buff **extra_frag;
+- int last_frag_rateidx;
+- int last_frag_hwrate;
+ struct ieee80211_rate *last_frag_rate;
++ int num_extra_frag;
+ unsigned int last_frag_rate_ctrl_probe;
+ };
+
+-typedef ieee80211_txrx_result (*ieee80211_tx_handler)
+-(struct ieee80211_txrx_data *tx);
+-
+-typedef ieee80211_txrx_result (*ieee80211_rx_handler)
+-(struct ieee80211_txrx_data *rx);
+-
+ struct beacon_data {
+ u8 *head, *tail;
+ int head_len, tail_len;
+@@ -206,10 +246,10 @@ struct ieee80211_if_ap {
+
+ /* yes, this looks ugly, but guarantees that we can later use
+ * bitmap_empty :)
+- * NB: don't ever use set_bit, use bss_tim_set/bss_tim_clear! */
++ * NB: don't touch this bitmap, use sta_info_{set,clear}_tim_bit */
+ u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)];
+- atomic_t num_sta_ps; /* number of stations in PS mode */
+ struct sk_buff_head ps_bc_buf;
++ atomic_t num_sta_ps; /* number of stations in PS mode */
+ int dtim_count;
+ int force_unicast_rateidx; /* forced TX rateidx for unicast frames */
+ int max_ratectrl_rateidx; /* max TX rateidx for rate control */
+@@ -217,8 +257,8 @@ struct ieee80211_if_ap {
+ };
+
+ struct ieee80211_if_wds {
+- u8 remote_addr[ETH_ALEN];
+ struct sta_info *sta;
++ u8 remote_addr[ETH_ALEN];
+ };
+
+ struct ieee80211_if_vlan {
+@@ -226,6 +266,41 @@ struct ieee80211_if_vlan {
+ struct list_head list;
+ };
+
++struct mesh_stats {
++ __u32 fwded_frames; /* Mesh forwarded frames */
++ __u32 dropped_frames_ttl; /* Not transmitted since mesh_ttl == 0*/
++ __u32 dropped_frames_no_route; /* Not transmitted, no route found */
++ atomic_t estab_plinks;
++};
++
++#define PREQ_Q_F_START 0x1
++#define PREQ_Q_F_REFRESH 0x2
++struct mesh_preq_queue {
++ struct list_head list;
++ u8 dst[ETH_ALEN];
++ u8 flags;
++};
++
++struct mesh_config {
++ /* Timeouts in ms */
++ /* Mesh plink management parameters */
++ u16 dot11MeshRetryTimeout;
++ u16 dot11MeshConfirmTimeout;
++ u16 dot11MeshHoldingTimeout;
++ u16 dot11MeshMaxPeerLinks;
++ u8 dot11MeshMaxRetries;
++ u8 dot11MeshTTL;
++ bool auto_open_plinks;
++ /* HWMP parameters */
++ u8 dot11MeshHWMPmaxPREQretries;
++ u32 path_refresh_time;
++ u16 min_discovery_timeout;
++ u32 dot11MeshHWMPactivePathTimeout;
++ u16 dot11MeshHWMPpreqMinInterval;
++ u16 dot11MeshHWMPnetDiameterTraversalTime;
++};
++
++
+ /* flags used in struct ieee80211_if_sta.flags */
+ #define IEEE80211_STA_SSID_SET BIT(0)
+ #define IEEE80211_STA_BSSID_SET BIT(1)
+@@ -241,18 +316,47 @@ struct ieee80211_if_vlan {
+ #define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12)
+ #define IEEE80211_STA_PRIVACY_INVOKED BIT(13)
+ struct ieee80211_if_sta {
+- enum {
+- IEEE80211_DISABLED, IEEE80211_AUTHENTICATE,
+- IEEE80211_ASSOCIATE, IEEE80211_ASSOCIATED,
+- IEEE80211_IBSS_SEARCH, IEEE80211_IBSS_JOINED
+- } state;
+ struct timer_list timer;
+ struct work_struct work;
+ u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
++ enum {
++ IEEE80211_DISABLED, IEEE80211_AUTHENTICATE,
++ IEEE80211_ASSOCIATE, IEEE80211_ASSOCIATED,
++ IEEE80211_IBSS_SEARCH, IEEE80211_IBSS_JOINED,
++ IEEE80211_MESH_UP
++ } state;
+ size_t ssid_len;
+ u8 scan_ssid[IEEE80211_MAX_SSID_LEN];
+ size_t scan_ssid_len;
++#ifdef CONFIG_MAC80211_MESH
++ struct timer_list mesh_path_timer;
++ u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN];
++ size_t mesh_id_len;
++ /* Active Path Selection Protocol Identifier */
++ u8 mesh_pp_id[4];
++ /* Active Path Selection Metric Identifier */
++ u8 mesh_pm_id[4];
++ /* Congestion Control Mode Identifier */
++ u8 mesh_cc_id[4];
++ /* Local mesh Destination Sequence Number */
++ u32 dsn;
++ /* Last used PREQ ID */
++ u32 preq_id;
++ atomic_t mpaths;
++ /* Timestamp of last DSN update */
++ unsigned long last_dsn_update;
++ /* Timestamp of last DSN sent */
++ unsigned long last_preq;
++ struct mesh_rmc *rmc;
++ spinlock_t mesh_preq_queue_lock;
++ struct mesh_preq_queue preq_queue;
++ int preq_queue_len;
++ struct mesh_stats mshstats;
++ struct mesh_config mshcfg;
++ u8 mesh_seqnum[3];
++ bool accepting_plinks;
++#endif
+ u16 aid;
+ u16 ap_capab, capab;
+ u8 *extra_ie; /* to be added to the end of AssocReq */
+@@ -262,16 +366,18 @@ struct ieee80211_if_sta {
+ u8 *assocreq_ies, *assocresp_ies;
+ size_t assocreq_ies_len, assocresp_ies_len;
+
++ struct sk_buff_head skb_queue;
++
+ int auth_tries, assoc_tries;
+
++ unsigned long request;
++
++ unsigned long last_probe;
++
+ unsigned int flags;
+ #define IEEE80211_STA_REQ_SCAN 0
+ #define IEEE80211_STA_REQ_AUTH 1
+ #define IEEE80211_STA_REQ_RUN 2
+- unsigned long request;
+- struct sk_buff_head skb_queue;
+-
+- unsigned long last_probe;
+
+ #define IEEE80211_AUTH_ALG_OPEN BIT(0)
+ #define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1)
+@@ -282,16 +388,34 @@ struct ieee80211_if_sta {
+
+ unsigned long ibss_join_req;
+ struct sk_buff *probe_resp; /* ProbeResp template for IBSS */
+- u32 supp_rates_bits;
++ u32 supp_rates_bits[IEEE80211_NUM_BANDS];
+
+ int wmm_last_param_set;
++ int num_beacons; /* number of TXed beacon frames by this STA */
+ };
+
++static inline void ieee80211_if_sta_set_mesh_id(struct ieee80211_if_sta *ifsta,
++ u8 mesh_id_len, u8 *mesh_id)
++{
++#ifdef CONFIG_MAC80211_MESH
++ ifsta->mesh_id_len = mesh_id_len;
++ memcpy(ifsta->mesh_id, mesh_id, mesh_id_len);
++#endif
++}
++
++#ifdef CONFIG_MAC80211_MESH
++#define IEEE80211_IFSTA_MESH_CTR_INC(sta, name) \
++ do { (sta)->mshstats.name++; } while (0)
++#else
++#define IEEE80211_IFSTA_MESH_CTR_INC(sta, name) \
++ do { } while (0)
++#endif
+
+ /* flags used in struct ieee80211_sub_if_data.flags */
+ #define IEEE80211_SDATA_ALLMULTI BIT(0)
+ #define IEEE80211_SDATA_PROMISC BIT(1)
+ #define IEEE80211_SDATA_USERSPACE_MLME BIT(2)
++#define IEEE80211_SDATA_OPERATING_GMODE BIT(3)
+ struct ieee80211_sub_if_data {
+ struct list_head list;
+
+@@ -306,11 +430,11 @@ struct ieee80211_sub_if_data {
+ unsigned int flags;
+
+ int drop_unencrypted;
++
+ /*
+- * IEEE 802.1X Port access control in effect,
+- * drop packets to/from unauthorized port
++ * basic rates of this AP or the AP we're associated to
+ */
+- int ieee802_1x_pac;
++ u64 basic_rates;
+
+ u16 sequence;
+
+@@ -338,6 +462,7 @@ struct ieee80211_sub_if_data {
+ struct ieee80211_if_wds wds;
+ struct ieee80211_if_vlan vlan;
+ struct ieee80211_if_sta sta;
++ u32 mntr_flags;
+ } u;
+ int channel_use;
+ int channel_use_raw;
+@@ -348,7 +473,6 @@ struct ieee80211_sub_if_data {
+ struct {
+ struct dentry *channel_use;
+ struct dentry *drop_unencrypted;
+- struct dentry *ieee802_1x_pac;
+ struct dentry *state;
+ struct dentry *bssid;
+ struct dentry *prev_bssid;
+@@ -363,11 +487,11 @@ struct ieee80211_sub_if_data {
+ struct dentry *auth_alg;
+ struct dentry *auth_transaction;
+ struct dentry *flags;
++ struct dentry *num_beacons_sta;
+ } sta;
+ struct {
+ struct dentry *channel_use;
+ struct dentry *drop_unencrypted;
+- struct dentry *ieee802_1x_pac;
+ struct dentry *num_sta_ps;
+ struct dentry *dtim_count;
+ struct dentry *num_beacons;
+@@ -378,19 +502,46 @@ struct ieee80211_sub_if_data {
+ struct {
+ struct dentry *channel_use;
+ struct dentry *drop_unencrypted;
+- struct dentry *ieee802_1x_pac;
+ struct dentry *peer;
+ } wds;
+ struct {
+ struct dentry *channel_use;
+ struct dentry *drop_unencrypted;
+- struct dentry *ieee802_1x_pac;
+ } vlan;
+ struct {
+ struct dentry *mode;
+ } monitor;
+ struct dentry *default_key;
+ } debugfs;
++
++#ifdef CONFIG_MAC80211_MESH
++ struct dentry *mesh_stats_dir;
++ struct {
++ struct dentry *fwded_frames;
++ struct dentry *dropped_frames_ttl;
++ struct dentry *dropped_frames_no_route;
++ struct dentry *estab_plinks;
++ struct timer_list mesh_path_timer;
++ } mesh_stats;
++
++ struct dentry *mesh_config_dir;
++ struct {
++ struct dentry *dot11MeshRetryTimeout;
++ struct dentry *dot11MeshConfirmTimeout;
++ struct dentry *dot11MeshHoldingTimeout;
++ struct dentry *dot11MeshMaxRetries;
++ struct dentry *dot11MeshTTL;
++ struct dentry *auto_open_plinks;
++ struct dentry *dot11MeshMaxPeerLinks;
++ struct dentry *dot11MeshHWMPactivePathTimeout;
++ struct dentry *dot11MeshHWMPpreqMinInterval;
++ struct dentry *dot11MeshHWMPnetDiameterTraversalTime;
++ struct dentry *dot11MeshHWMPmaxPREQretries;
++ struct dentry *path_refresh_time;
++ struct dentry *min_discovery_timeout;
++ } mesh_config;
++#endif
++
+ #endif
+ /* must be last, dynamically sized area in this! */
+ struct ieee80211_vif vif;
+@@ -407,6 +558,8 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p)
+ enum {
+ IEEE80211_RX_MSG = 1,
+ IEEE80211_TX_STATUS_MSG = 2,
++ IEEE80211_DELBA_MSG = 3,
++ IEEE80211_ADDBA_MSG = 4,
+ };
+
+ struct ieee80211_local {
+@@ -417,15 +570,15 @@ struct ieee80211_local {
+
+ const struct ieee80211_ops *ops;
+
+- /* List of registered struct ieee80211_hw_mode */
+- struct list_head modes_list;
+-
+ struct net_device *mdev; /* wmaster# - "master" 802.11 device */
+ int open_count;
+- int monitors;
++ int monitors, cooked_mntrs;
++ /* number of interfaces with corresponding FIF_ flags */
++ int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss;
+ unsigned int filter_flags; /* FIF_* */
+ struct iw_statistics wstats;
+ u8 wstats_flags;
++ bool tim_in_locked_section; /* see ieee80211_beacon_get() */
+ int tx_headroom; /* required headroom for hardware/radiotap */
+
+ enum {
+@@ -443,15 +596,22 @@ struct ieee80211_local {
+ struct sk_buff_head skb_queue;
+ struct sk_buff_head skb_queue_unreliable;
+
+- /* Station data structures */
+- rwlock_t sta_lock; /* protects STA data structures */
+- int num_sta; /* number of stations in sta_list */
++ /* Station data */
++ /*
++ * The lock only protects the list, hash, timer and counter
++ * against manipulation, reads are done in RCU. Additionally,
++ * the lock protects each BSS's TIM bitmap.
++ */
++ spinlock_t sta_lock;
++ unsigned long num_sta;
+ struct list_head sta_list;
++ struct list_head sta_flush_list;
++ struct work_struct sta_flush_work;
+ struct sta_info *sta_hash[STA_HASH_SIZE];
+ struct timer_list sta_cleanup;
+
+- unsigned long state[NUM_TX_DATA_QUEUES];
+- struct ieee80211_tx_stored_packet pending_packet[NUM_TX_DATA_QUEUES];
++ unsigned long state[NUM_TX_DATA_QUEUES_AMPDU];
++ struct ieee80211_tx_stored_packet pending_packet[NUM_TX_DATA_QUEUES_AMPDU];
+ struct tasklet_struct tx_pending_tasklet;
+
+ /* number of interfaces with corresponding IFF_ flags */
+@@ -459,11 +619,6 @@ struct ieee80211_local {
+
+ struct rate_control_ref *rate_ctrl;
+
+- /* Supported and basic rate filters for different modes. These are
+- * pointers to -1 terminated lists and rates in 100 kbps units. */
+- int *supp_rates[NUM_IEEE80211_MODES];
+- int *basic_rates[NUM_IEEE80211_MODES];
+-
+ int rts_threshold;
+ int fragmentation_threshold;
+ int short_retry_limit; /* dot11ShortRetryLimit */
+@@ -477,21 +632,25 @@ struct ieee80211_local {
+ * deliver multicast frames both back to wireless
+ * media and to the local net stack */
+
+- ieee80211_rx_handler *rx_pre_handlers;
+- ieee80211_rx_handler *rx_handlers;
+- ieee80211_tx_handler *tx_handlers;
+-
+ struct list_head interfaces;
+
++ /*
++ * Key lock, protects sdata's key_list and sta_info's
++ * key pointers (write access, they're RCU.)
++ */
++ spinlock_t key_lock;
++
++
+ bool sta_sw_scanning;
+ bool sta_hw_scanning;
+ int scan_channel_idx;
++ enum ieee80211_band scan_band;
++
+ enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state;
+ unsigned long last_scan_completed;
+ struct delayed_work scan_work;
+ struct net_device *scan_dev;
+ struct ieee80211_channel *oper_channel, *scan_channel;
+- struct ieee80211_hw_mode *oper_hw_mode, *scan_hw_mode;
+ u8 scan_ssid[IEEE80211_MAX_SSID_LEN];
+ size_t scan_ssid_len;
+ struct list_head sta_bss_list;
+@@ -560,14 +719,8 @@ struct ieee80211_local {
+ int wifi_wme_noack_test;
+ unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */
+
+- unsigned int enabled_modes; /* bitfield of allowed modes;
+- * (1 << MODE_*) */
+- unsigned int hw_modes; /* bitfield of supported hardware modes;
+- * (1 << MODE_*) */
+-
+ #ifdef CONFIG_MAC80211_DEBUGFS
+ struct local_debugfsdentries {
+- struct dentry *channel;
+ struct dentry *frequency;
+ struct dentry *antenna_sel_tx;
+ struct dentry *antenna_sel_rx;
+@@ -577,9 +730,7 @@ struct ieee80211_local {
+ struct dentry *short_retry_limit;
+ struct dentry *long_retry_limit;
+ struct dentry *total_ps_buffered;
+- struct dentry *mode;
+ struct dentry *wep_iv;
+- struct dentry *modes;
+ struct dentry *statistics;
+ struct local_debugfsdentries_statsdentries {
+ struct dentry *transmitted_fragment_count;
+@@ -627,6 +778,63 @@ struct ieee80211_local {
+ #endif
+ };
+
++/* this struct represents 802.11n's RA/TID combination */
++struct ieee80211_ra_tid {
++ u8 ra[ETH_ALEN];
++ u16 tid;
++};
++
++/* Parsed Information Elements */
++struct ieee802_11_elems {
++ /* pointers to IEs */
++ u8 *ssid;
++ u8 *supp_rates;
++ u8 *fh_params;
++ u8 *ds_params;
++ u8 *cf_params;
++ u8 *tim;
++ u8 *ibss_params;
++ u8 *challenge;
++ u8 *wpa;
++ u8 *rsn;
++ u8 *erp_info;
++ u8 *ext_supp_rates;
++ u8 *wmm_info;
++ u8 *wmm_param;
++ u8 *ht_cap_elem;
++ u8 *ht_info_elem;
++ u8 *mesh_config;
++ u8 *mesh_id;
++ u8 *peer_link;
++ u8 *preq;
++ u8 *prep;
++ u8 *perr;
++
++ /* length of them, respectively */
++ u8 ssid_len;
++ u8 supp_rates_len;
++ u8 fh_params_len;
++ u8 ds_params_len;
++ u8 cf_params_len;
++ u8 tim_len;
++ u8 ibss_params_len;
++ u8 challenge_len;
++ u8 wpa_len;
++ u8 rsn_len;
++ u8 erp_info_len;
++ u8 ext_supp_rates_len;
++ u8 wmm_info_len;
++ u8 wmm_param_len;
++ u8 ht_cap_elem_len;
++ u8 ht_info_elem_len;
++ u8 mesh_config_len;
++ u8 mesh_id_len;
++ u8 peer_link_len;
++ u8 preq_len;
++ u8 prep_len;
++ u8 perr_len;
++};
++
+ static inline struct ieee80211_local *hw_to_local(
+ struct ieee80211_hw *hw)
+ {
+@@ -650,57 +858,6 @@ struct sta_attribute {
+ ssize_t (*store)(struct sta_info *, const char *buf, size_t count);
+ };
+
+-static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid)
+-{
+- /*
+- * This format has been mandated by the IEEE specifications,
+- * so this line may not be changed to use the __set_bit() format.
+- */
+- bss->tim[aid / 8] |= (1 << (aid % 8));
+-}
+-
+-static inline void bss_tim_set(struct ieee80211_local *local,
+- struct ieee80211_if_ap *bss, u16 aid)
+-{
+- read_lock_bh(&local->sta_lock);
+- __bss_tim_set(bss, aid);
+- read_unlock_bh(&local->sta_lock);
+-}
+-
+-static inline void __bss_tim_clear(struct ieee80211_if_ap *bss, u16 aid)
+-{
+- /*
+- * This format has been mandated by the IEEE specifications,
+- * so this line may not be changed to use the __clear_bit() format.
+- */
+- bss->tim[aid / 8] &= ~(1 << (aid % 8));
+-}
+-
+-static inline void bss_tim_clear(struct ieee80211_local *local,
+- struct ieee80211_if_ap *bss, u16 aid)
+-{
+- read_lock_bh(&local->sta_lock);
+- __bss_tim_clear(bss, aid);
+- read_unlock_bh(&local->sta_lock);
+-}
+-
+-/**
+- * ieee80211_is_erp_rate - Check if a rate is an ERP rate
+- * @phymode: The PHY-mode for this rate (MODE_IEEE80211...)
+- * @rate: Transmission rate to check, in 100 kbps
+- *
+- * Check if a given rate is an Extended Rate PHY (ERP) rate.
+- */
+-static inline int ieee80211_is_erp_rate(int phymode, int rate)
+-{
+- if (phymode == MODE_IEEE80211G) {
+- if (rate != 10 && rate != 20 &&
+- rate != 55 && rate != 110)
+- return 1;
+- }
+- return 0;
+-}
+-
+ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr)
+ {
+ return compare_ether_addr(raddr, addr) == 0 ||
+@@ -712,16 +869,11 @@ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr)
+ int ieee80211_hw_config(struct ieee80211_local *local);
+ int ieee80211_if_config(struct net_device *dev);
+ int ieee80211_if_config_beacon(struct net_device *dev);
+-void ieee80211_prepare_rates(struct ieee80211_local *local,
+- struct ieee80211_hw_mode *mode);
+-void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx);
+-int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr);
++void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx);
+ void ieee80211_if_setup(struct net_device *dev);
+-struct ieee80211_rate *ieee80211_get_rate(struct ieee80211_local *local,
+- int phymode, int hwrate);
+-int ieee80211_hw_config_ht(struct ieee80211_local *local, int enable_ht,
+- struct ieee80211_ht_info *req_ht_cap,
+- struct ieee80211_ht_bss_info *req_bss_cap);
++u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht,
++ struct ieee80211_ht_info *req_ht_cap,
++ struct ieee80211_ht_bss_info *req_bss_cap);
+
+ /* ieee80211_ioctl.c */
+ extern const struct iw_handler_def ieee80211_iw_handler_def;
+@@ -747,9 +899,7 @@ extern const struct iw_handler_def ieee80211_iw_handler_def;
+
+
+ /* ieee80211_ioctl.c */
+-int ieee80211_set_compression(struct ieee80211_local *local,
+- struct net_device *dev, struct sta_info *sta);
+-int ieee80211_set_channel(struct ieee80211_local *local, int channel, int freq);
++int ieee80211_set_freq(struct ieee80211_local *local, int freq);
+ /* ieee80211_sta.c */
+ void ieee80211_sta_timer(unsigned long data);
+ void ieee80211_sta_work(struct work_struct *work);
+@@ -763,9 +913,9 @@ int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len);
+ void ieee80211_sta_req_auth(struct net_device *dev,
+ struct ieee80211_if_sta *ifsta);
+ int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len);
+-ieee80211_txrx_result ieee80211_sta_rx_scan(struct net_device *dev,
+- struct sk_buff *skb,
+- struct ieee80211_rx_status *rx_status);
++ieee80211_rx_result ieee80211_sta_rx_scan(
++ struct net_device *dev, struct sk_buff *skb,
++ struct ieee80211_rx_status *rx_status);
+ void ieee80211_rx_bss_list_init(struct net_device *dev);
+ void ieee80211_rx_bss_list_deinit(struct net_device *dev);
+ int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len);
+@@ -782,12 +932,36 @@ int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie,
+ int ieee80211_ht_addt_info_ie_to_ht_bss_info(
+ struct ieee80211_ht_addt_info *ht_add_info_ie,
+ struct ieee80211_ht_bss_info *bss_info);
++void ieee80211_send_addba_request(struct net_device *dev, const u8 *da,
++ u16 tid, u8 dialog_token, u16 start_seq_num,
++ u16 agg_size, u16 timeout);
++void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid,
++ u16 initiator, u16 reason_code);
++
+ void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *da,
+ u16 tid, u16 initiator, u16 reason);
+ void sta_rx_agg_session_timer_expired(unsigned long data);
++void sta_addba_resp_timer_expired(unsigned long data);
++void ieee80211_sta_tear_down_BA_sessions(struct net_device *dev, u8 *addr);
++u64 ieee80211_sta_get_rates(struct ieee80211_local *local,
++ struct ieee802_11_elems *elems,
++ enum ieee80211_band band);
++void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb,
++ int encrypt);
++void ieee802_11_parse_elems(u8 *start, size_t len,
++ struct ieee802_11_elems *elems);
++
++#ifdef CONFIG_MAC80211_MESH
++void ieee80211_start_mesh(struct net_device *dev);
++#else
++static inline void ieee80211_start_mesh(struct net_device *dev)
++{}
++#endif
++
+ /* ieee80211_iface.c */
+ int ieee80211_if_add(struct net_device *dev, const char *name,
+- struct net_device **new_dev, int type);
++ struct net_device **new_dev, int type,
++ struct vif_params *params);
+ void ieee80211_if_set_type(struct net_device *dev, int type);
+ void ieee80211_if_reinit(struct net_device *dev);
+ void __ieee80211_if_del(struct ieee80211_local *local,
+@@ -796,16 +970,7 @@ int ieee80211_if_remove(struct net_device *dev, const char *name, int id);
+ void ieee80211_if_free(struct net_device *dev);
+ void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata);
+
+-/* regdomain.c */
+-void ieee80211_regdomain_init(void);
+-void ieee80211_set_default_regdomain(struct ieee80211_hw_mode *mode);
+-
+-/* rx handling */
+-extern ieee80211_rx_handler ieee80211_rx_pre_handlers[];
+-extern ieee80211_rx_handler ieee80211_rx_handlers[];
+-
+ /* tx handling */
+-extern ieee80211_tx_handler ieee80211_tx_handlers[];
+ void ieee80211_clear_tx_pending(struct ieee80211_local *local);
+ void ieee80211_tx_pending(unsigned long data);
+ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev);
+diff --git a/net/mac80211/ieee80211_iface.c b/net/mac80211/ieee80211_iface.c
+deleted file mode 100644
+index 92f1eb2..0000000
+--- a/net/mac80211/ieee80211_iface.c
++++ /dev/null
+@@ -1,298 +0,0 @@
+-/*
+- * Copyright 2002-2005, Instant802 Networks, Inc.
+- * Copyright 2005-2006, Devicescape Software, Inc.
+- * Copyright (c) 2006 Jiri Benc <jbenc at suse.cz>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-#include <linux/kernel.h>
+-#include <linux/if_arp.h>
+-#include <linux/netdevice.h>
+-#include <linux/rtnetlink.h>
+-#include <net/mac80211.h>
+-#include "ieee80211_i.h"
+-#include "sta_info.h"
+-#include "debugfs_netdev.h"
+-
+-void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata)
+-{
+- int i;
+-
+- /* Default values for sub-interface parameters */
+- sdata->drop_unencrypted = 0;
+- for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
+- skb_queue_head_init(&sdata->fragments[i].skb_list);
+-
+- INIT_LIST_HEAD(&sdata->key_list);
+-}
+-
+-static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata)
+-{
+- int i;
+-
+- for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) {
+- __skb_queue_purge(&sdata->fragments[i].skb_list);
+- }
+-}
+-
+-/* Must be called with rtnl lock held. */
+-int ieee80211_if_add(struct net_device *dev, const char *name,
+- struct net_device **new_dev, int type)
+-{
+- struct net_device *ndev;
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_sub_if_data *sdata = NULL;
+- int ret;
+-
+- ASSERT_RTNL();
+- ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size,
+- name, ieee80211_if_setup);
+- if (!ndev)
+- return -ENOMEM;
+-
+- ret = dev_alloc_name(ndev, ndev->name);
+- if (ret < 0)
+- goto fail;
+-
+- memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
+- ndev->base_addr = dev->base_addr;
+- ndev->irq = dev->irq;
+- ndev->mem_start = dev->mem_start;
+- ndev->mem_end = dev->mem_end;
+- SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
+- ndev->ieee80211_ptr = &sdata->wdev;
+- sdata->wdev.wiphy = local->hw.wiphy;
+- sdata->vif.type = IEEE80211_IF_TYPE_AP;
+- sdata->dev = ndev;
+- sdata->local = local;
+- ieee80211_if_sdata_init(sdata);
+-
+- ret = register_netdevice(ndev);
+- if (ret)
+- goto fail;
+-
+- ieee80211_debugfs_add_netdev(sdata);
+- ieee80211_if_set_type(ndev, type);
+-
+- /* we're under RTNL so all this is fine */
+- if (unlikely(local->reg_state == IEEE80211_DEV_UNREGISTERED)) {
+- __ieee80211_if_del(local, sdata);
+- return -ENODEV;
+- }
+- list_add_tail_rcu(&sdata->list, &local->interfaces);
+-
+- if (new_dev)
+- *new_dev = ndev;
+-
+- return 0;
+-
+-fail:
+- free_netdev(ndev);
+- return ret;
+-}
+-
+-void ieee80211_if_set_type(struct net_device *dev, int type)
+-{
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- int oldtype = sdata->vif.type;
+-
+- /*
+- * We need to call this function on the master interface
+- * which already has a hard_start_xmit routine assigned
+- * which must not be changed.
+- */
+- if (dev != sdata->local->mdev)
+- dev->hard_start_xmit = ieee80211_subif_start_xmit;
+-
+- /*
+- * Called even when register_netdevice fails, it would
+- * oops if assigned before initialising the rest.
+- */
+- dev->uninit = ieee80211_if_reinit;
+-
+- /* most have no BSS pointer */
+- sdata->bss = NULL;
+- sdata->vif.type = type;
+-
+- switch (type) {
+- case IEEE80211_IF_TYPE_WDS:
+- /* nothing special */
+- break;
+- case IEEE80211_IF_TYPE_VLAN:
+- sdata->u.vlan.ap = NULL;
+- break;
+- case IEEE80211_IF_TYPE_AP:
+- sdata->u.ap.force_unicast_rateidx = -1;
+- sdata->u.ap.max_ratectrl_rateidx = -1;
+- skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
+- sdata->bss = &sdata->u.ap;
+- INIT_LIST_HEAD(&sdata->u.ap.vlans);
+- break;
+- case IEEE80211_IF_TYPE_STA:
+- case IEEE80211_IF_TYPE_IBSS: {
+- struct ieee80211_sub_if_data *msdata;
+- struct ieee80211_if_sta *ifsta;
+-
+- ifsta = &sdata->u.sta;
+- INIT_WORK(&ifsta->work, ieee80211_sta_work);
+- setup_timer(&ifsta->timer, ieee80211_sta_timer,
+- (unsigned long) sdata);
+- skb_queue_head_init(&ifsta->skb_queue);
+-
+- ifsta->capab = WLAN_CAPABILITY_ESS;
+- ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN |
+- IEEE80211_AUTH_ALG_SHARED_KEY;
+- ifsta->flags |= IEEE80211_STA_CREATE_IBSS |
+- IEEE80211_STA_WMM_ENABLED |
+- IEEE80211_STA_AUTO_BSSID_SEL |
+- IEEE80211_STA_AUTO_CHANNEL_SEL;
+-
+- msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev);
+- sdata->bss = &msdata->u.ap;
+- break;
+- }
+- case IEEE80211_IF_TYPE_MNTR:
+- dev->type = ARPHRD_IEEE80211_RADIOTAP;
+- dev->hard_start_xmit = ieee80211_monitor_start_xmit;
+- break;
+- default:
+- printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x",
+- dev->name, __FUNCTION__, type);
+- }
+- ieee80211_debugfs_change_if_type(sdata, oldtype);
+-}
+-
+-/* Must be called with rtnl lock held. */
+-void ieee80211_if_reinit(struct net_device *dev)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- struct sta_info *sta;
+- struct sk_buff *skb;
+-
+- ASSERT_RTNL();
+-
+- ieee80211_free_keys(sdata);
+-
+- ieee80211_if_sdata_deinit(sdata);
+-
+- switch (sdata->vif.type) {
+- case IEEE80211_IF_TYPE_INVALID:
+- /* cannot happen */
+- WARN_ON(1);
+- break;
+- case IEEE80211_IF_TYPE_AP: {
+- /* Remove all virtual interfaces that use this BSS
+- * as their sdata->bss */
+- struct ieee80211_sub_if_data *tsdata, *n;
+-
+- list_for_each_entry_safe(tsdata, n, &local->interfaces, list) {
+- if (tsdata != sdata && tsdata->bss == &sdata->u.ap) {
+- printk(KERN_DEBUG "%s: removing virtual "
+- "interface %s because its BSS interface"
+- " is being removed\n",
+- sdata->dev->name, tsdata->dev->name);
+- list_del_rcu(&tsdata->list);
+- /*
+- * We have lots of time and can afford
+- * to sync for each interface
+- */
+- synchronize_rcu();
+- __ieee80211_if_del(local, tsdata);
+- }
+- }
+-
+- kfree(sdata->u.ap.beacon);
+-
+- while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
+- local->total_ps_buffered--;
+- dev_kfree_skb(skb);
+- }
+-
+- break;
+- }
+- case IEEE80211_IF_TYPE_WDS:
+- sta = sta_info_get(local, sdata->u.wds.remote_addr);
+- if (sta) {
+- sta_info_free(sta);
+- sta_info_put(sta);
+- } else {
+-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+- printk(KERN_DEBUG "%s: Someone had deleted my STA "
+- "entry for the WDS link\n", dev->name);
+-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+- }
+- break;
+- case IEEE80211_IF_TYPE_STA:
+- case IEEE80211_IF_TYPE_IBSS:
+- kfree(sdata->u.sta.extra_ie);
+- sdata->u.sta.extra_ie = NULL;
+- kfree(sdata->u.sta.assocreq_ies);
+- sdata->u.sta.assocreq_ies = NULL;
+- kfree(sdata->u.sta.assocresp_ies);
+- sdata->u.sta.assocresp_ies = NULL;
+- if (sdata->u.sta.probe_resp) {
+- dev_kfree_skb(sdata->u.sta.probe_resp);
+- sdata->u.sta.probe_resp = NULL;
+- }
+-
+- break;
+- case IEEE80211_IF_TYPE_MNTR:
+- dev->type = ARPHRD_ETHER;
+- break;
+- case IEEE80211_IF_TYPE_VLAN:
+- sdata->u.vlan.ap = NULL;
+- break;
+- }
+-
+- /* remove all STAs that are bound to this virtual interface */
+- sta_info_flush(local, dev);
+-
+- memset(&sdata->u, 0, sizeof(sdata->u));
+- ieee80211_if_sdata_init(sdata);
+-}
+-
+-/* Must be called with rtnl lock held. */
+-void __ieee80211_if_del(struct ieee80211_local *local,
+- struct ieee80211_sub_if_data *sdata)
+-{
+- struct net_device *dev = sdata->dev;
+-
+- ieee80211_debugfs_remove_netdev(sdata);
+- unregister_netdevice(dev);
+- /* Except master interface, the net_device will be freed by
+- * net_device->destructor (i. e. ieee80211_if_free). */
+-}
+-
+-/* Must be called with rtnl lock held. */
+-int ieee80211_if_remove(struct net_device *dev, const char *name, int id)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_sub_if_data *sdata, *n;
+-
+- ASSERT_RTNL();
+-
+- list_for_each_entry_safe(sdata, n, &local->interfaces, list) {
+- if ((sdata->vif.type == id || id == -1) &&
+- strcmp(name, sdata->dev->name) == 0 &&
+- sdata->dev != local->mdev) {
+- list_del_rcu(&sdata->list);
+- synchronize_rcu();
+- __ieee80211_if_del(local, sdata);
+- return 0;
+- }
+- }
+- return -ENODEV;
+-}
+-
+-void ieee80211_if_free(struct net_device *dev)
+-{
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-
+- ieee80211_if_sdata_deinit(sdata);
+- free_netdev(dev);
+-}
+diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c
+deleted file mode 100644
+index 5024d37..0000000
+--- a/net/mac80211/ieee80211_ioctl.c
++++ /dev/null
+@@ -1,1138 +0,0 @@
+-/*
+- * Copyright 2002-2005, Instant802 Networks, Inc.
+- * Copyright 2005-2006, Devicescape Software, Inc.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/netdevice.h>
+-#include <linux/types.h>
+-#include <linux/slab.h>
+-#include <linux/skbuff.h>
+-#include <linux/etherdevice.h>
+-#include <linux/if_arp.h>
+-#include <linux/wireless.h>
+-#include <net/iw_handler.h>
+-#include <asm/uaccess.h>
+-
+-#include <net/mac80211.h>
+-#include "ieee80211_i.h"
+-#include "ieee80211_led.h"
+-#include "ieee80211_rate.h"
+-#include "wpa.h"
+-#include "aes_ccm.h"
+-
+-
+-static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
+- int idx, int alg, int remove,
+- int set_tx_key, const u8 *_key,
+- size_t key_len)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- int ret = 0;
+- struct sta_info *sta;
+- struct ieee80211_key *key;
+- struct ieee80211_sub_if_data *sdata;
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-
+- if (idx < 0 || idx >= NUM_DEFAULT_KEYS) {
+- printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n",
+- dev->name, idx);
+- return -EINVAL;
+- }
+-
+- if (is_broadcast_ether_addr(sta_addr)) {
+- sta = NULL;
+- key = sdata->keys[idx];
+- } else {
+- set_tx_key = 0;
+- /*
+- * According to the standard, the key index of a pairwise
+- * key must be zero. However, some AP are broken when it
+- * comes to WEP key indices, so we work around this.
+- */
+- if (idx != 0 && alg != ALG_WEP) {
+- printk(KERN_DEBUG "%s: set_encrypt - non-zero idx for "
+- "individual key\n", dev->name);
+- return -EINVAL;
+- }
+-
+- sta = sta_info_get(local, sta_addr);
+- if (!sta) {
+-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+- DECLARE_MAC_BUF(mac);
+- printk(KERN_DEBUG "%s: set_encrypt - unknown addr "
+- "%s\n",
+- dev->name, print_mac(mac, sta_addr));
+-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+-
+- return -ENOENT;
+- }
+-
+- key = sta->key;
+- }
+-
+- if (remove) {
+- ieee80211_key_free(key);
+- key = NULL;
+- } else {
+- /*
+- * Automatically frees any old key if present.
+- */
+- key = ieee80211_key_alloc(sdata, sta, alg, idx, key_len, _key);
+- if (!key) {
+- ret = -ENOMEM;
+- goto err_out;
+- }
+- }
+-
+- if (set_tx_key || (!sta && !sdata->default_key && key))
+- ieee80211_set_default_key(sdata, idx);
+-
+- ret = 0;
+- err_out:
+- if (sta)
+- sta_info_put(sta);
+- return ret;
+-}
+-
+-static int ieee80211_ioctl_siwgenie(struct net_device *dev,
+- struct iw_request_info *info,
+- struct iw_point *data, char *extra)
+-{
+- struct ieee80211_sub_if_data *sdata;
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-
+- if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)
+- return -EOPNOTSUPP;
+-
+- if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+- sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
+- int ret = ieee80211_sta_set_extra_ie(dev, extra, data->length);
+- if (ret)
+- return ret;
+- sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
+- ieee80211_sta_req_auth(dev, &sdata->u.sta);
+- return 0;
+- }
+-
+- return -EOPNOTSUPP;
+-}
+-
+-static int ieee80211_ioctl_giwname(struct net_device *dev,
+- struct iw_request_info *info,
+- char *name, char *extra)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+- switch (local->hw.conf.phymode) {
+- case MODE_IEEE80211A:
+- strcpy(name, "IEEE 802.11a");
+- break;
+- case MODE_IEEE80211B:
+- strcpy(name, "IEEE 802.11b");
+- break;
+- case MODE_IEEE80211G:
+- strcpy(name, "IEEE 802.11g");
+- break;
+- default:
+- strcpy(name, "IEEE 802.11");
+- break;
+- }
+-
+- return 0;
+-}
+-
+-
+-static int ieee80211_ioctl_giwrange(struct net_device *dev,
+- struct iw_request_info *info,
+- struct iw_point *data, char *extra)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct iw_range *range = (struct iw_range *) extra;
+- struct ieee80211_hw_mode *mode = NULL;
+- int c = 0;
+-
+- data->length = sizeof(struct iw_range);
+- memset(range, 0, sizeof(struct iw_range));
+-
+- range->we_version_compiled = WIRELESS_EXT;
+- range->we_version_source = 21;
+- range->retry_capa = IW_RETRY_LIMIT;
+- range->retry_flags = IW_RETRY_LIMIT;
+- range->min_retry = 0;
+- range->max_retry = 255;
+- range->min_rts = 0;
+- range->max_rts = 2347;
+- range->min_frag = 256;
+- range->max_frag = 2346;
+-
+- range->encoding_size[0] = 5;
+- range->encoding_size[1] = 13;
+- range->num_encoding_sizes = 2;
+- range->max_encoding_tokens = NUM_DEFAULT_KEYS;
+-
+- range->max_qual.qual = local->hw.max_signal;
+- range->max_qual.level = local->hw.max_rssi;
+- range->max_qual.noise = local->hw.max_noise;
+- range->max_qual.updated = local->wstats_flags;
+-
+- range->avg_qual.qual = local->hw.max_signal/2;
+- range->avg_qual.level = 0;
+- range->avg_qual.noise = 0;
+- range->avg_qual.updated = local->wstats_flags;
+-
+- range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
+- IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+-
+- list_for_each_entry(mode, &local->modes_list, list) {
+- int i = 0;
+-
+- if (!(local->enabled_modes & (1 << mode->mode)) ||
+- (local->hw_modes & local->enabled_modes &
+- (1 << MODE_IEEE80211G) && mode->mode == MODE_IEEE80211B))
+- continue;
+-
+- while (i < mode->num_channels && c < IW_MAX_FREQUENCIES) {
+- struct ieee80211_channel *chan = &mode->channels[i];
+-
+- if (chan->flag & IEEE80211_CHAN_W_SCAN) {
+- range->freq[c].i = chan->chan;
+- range->freq[c].m = chan->freq * 100000;
+- range->freq[c].e = 1;
+- c++;
+- }
+- i++;
+- }
+- }
+- range->num_channels = c;
+- range->num_frequency = c;
+-
+- IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
+- IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
+- IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
+- IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
+-
+- range->scan_capa |= IW_SCAN_CAPA_ESSID;
+-
+- return 0;
+-}
+-
+-
+-static int ieee80211_ioctl_siwmode(struct net_device *dev,
+- struct iw_request_info *info,
+- __u32 *mode, char *extra)
+-{
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- int type;
+-
+- if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
+- return -EOPNOTSUPP;
+-
+- switch (*mode) {
+- case IW_MODE_INFRA:
+- type = IEEE80211_IF_TYPE_STA;
+- break;
+- case IW_MODE_ADHOC:
+- type = IEEE80211_IF_TYPE_IBSS;
+- break;
+- case IW_MODE_MONITOR:
+- type = IEEE80211_IF_TYPE_MNTR;
+- break;
+- default:
+- return -EINVAL;
+- }
+-
+- if (type == sdata->vif.type)
+- return 0;
+- if (netif_running(dev))
+- return -EBUSY;
+-
+- ieee80211_if_reinit(dev);
+- ieee80211_if_set_type(dev, type);
+-
+- return 0;
+-}
+-
+-
+-static int ieee80211_ioctl_giwmode(struct net_device *dev,
+- struct iw_request_info *info,
+- __u32 *mode, char *extra)
+-{
+- struct ieee80211_sub_if_data *sdata;
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- switch (sdata->vif.type) {
+- case IEEE80211_IF_TYPE_AP:
+- *mode = IW_MODE_MASTER;
+- break;
+- case IEEE80211_IF_TYPE_STA:
+- *mode = IW_MODE_INFRA;
+- break;
+- case IEEE80211_IF_TYPE_IBSS:
+- *mode = IW_MODE_ADHOC;
+- break;
+- case IEEE80211_IF_TYPE_MNTR:
+- *mode = IW_MODE_MONITOR;
+- break;
+- case IEEE80211_IF_TYPE_WDS:
+- *mode = IW_MODE_REPEAT;
+- break;
+- case IEEE80211_IF_TYPE_VLAN:
+- *mode = IW_MODE_SECOND; /* FIXME */
+- break;
+- default:
+- *mode = IW_MODE_AUTO;
+- break;
+- }
+- return 0;
+-}
+-
+-int ieee80211_set_channel(struct ieee80211_local *local, int channel, int freq)
+-{
+- struct ieee80211_hw_mode *mode;
+- int c, set = 0;
+- int ret = -EINVAL;
+-
+- list_for_each_entry(mode, &local->modes_list, list) {
+- if (!(local->enabled_modes & (1 << mode->mode)))
+- continue;
+- for (c = 0; c < mode->num_channels; c++) {
+- struct ieee80211_channel *chan = &mode->channels[c];
+- if (chan->flag & IEEE80211_CHAN_W_SCAN &&
+- ((chan->chan == channel) || (chan->freq == freq))) {
+- local->oper_channel = chan;
+- local->oper_hw_mode = mode;
+- set = 1;
+- break;
+- }
+- }
+- if (set)
+- break;
+- }
+-
+- if (set) {
+- if (local->sta_sw_scanning)
+- ret = 0;
+- else
+- ret = ieee80211_hw_config(local);
+-
+- rate_control_clear(local);
+- }
+-
+- return ret;
+-}
+-
+-static int ieee80211_ioctl_siwfreq(struct net_device *dev,
+- struct iw_request_info *info,
+- struct iw_freq *freq, char *extra)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-
+- if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
+- sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL;
+-
+- /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
+- if (freq->e == 0) {
+- if (freq->m < 0) {
+- if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
+- sdata->u.sta.flags |=
+- IEEE80211_STA_AUTO_CHANNEL_SEL;
+- return 0;
+- } else
+- return ieee80211_set_channel(local, freq->m, -1);
+- } else {
+- int i, div = 1000000;
+- for (i = 0; i < freq->e; i++)
+- div /= 10;
+- if (div > 0)
+- return ieee80211_set_channel(local, -1, freq->m / div);
+- else
+- return -EINVAL;
+- }
+-}
+-
+-
+-static int ieee80211_ioctl_giwfreq(struct net_device *dev,
+- struct iw_request_info *info,
+- struct iw_freq *freq, char *extra)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+- /* TODO: in station mode (Managed/Ad-hoc) might need to poll low-level
+- * driver for the current channel with firmware-based management */
+-
+- freq->m = local->hw.conf.freq;
+- freq->e = 6;
+-
+- return 0;
+-}
+-
+-
+-static int ieee80211_ioctl_siwessid(struct net_device *dev,
+- struct iw_request_info *info,
+- struct iw_point *data, char *ssid)
+-{
+- struct ieee80211_sub_if_data *sdata;
+- size_t len = data->length;
+-
+- /* iwconfig uses nul termination in SSID.. */
+- if (len > 0 && ssid[len - 1] == '\0')
+- len--;
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+- sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
+- int ret;
+- if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) {
+- if (len > IEEE80211_MAX_SSID_LEN)
+- return -EINVAL;
+- memcpy(sdata->u.sta.ssid, ssid, len);
+- sdata->u.sta.ssid_len = len;
+- return 0;
+- }
+- if (data->flags)
+- sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
+- else
+- sdata->u.sta.flags |= IEEE80211_STA_AUTO_SSID_SEL;
+- ret = ieee80211_sta_set_ssid(dev, ssid, len);
+- if (ret)
+- return ret;
+- ieee80211_sta_req_auth(dev, &sdata->u.sta);
+- return 0;
+- }
+-
+- if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
+- memcpy(sdata->u.ap.ssid, ssid, len);
+- memset(sdata->u.ap.ssid + len, 0,
+- IEEE80211_MAX_SSID_LEN - len);
+- sdata->u.ap.ssid_len = len;
+- return ieee80211_if_config(dev);
+- }
+- return -EOPNOTSUPP;
+-}
+-
+-
+-static int ieee80211_ioctl_giwessid(struct net_device *dev,
+- struct iw_request_info *info,
+- struct iw_point *data, char *ssid)
+-{
+- size_t len;
+-
+- struct ieee80211_sub_if_data *sdata;
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+- sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
+- int res = ieee80211_sta_get_ssid(dev, ssid, &len);
+- if (res == 0) {
+- data->length = len;
+- data->flags = 1;
+- } else
+- data->flags = 0;
+- return res;
+- }
+-
+- if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
+- len = sdata->u.ap.ssid_len;
+- if (len > IW_ESSID_MAX_SIZE)
+- len = IW_ESSID_MAX_SIZE;
+- memcpy(ssid, sdata->u.ap.ssid, len);
+- data->length = len;
+- data->flags = 1;
+- return 0;
+- }
+- return -EOPNOTSUPP;
+-}
+-
+-
+-static int ieee80211_ioctl_siwap(struct net_device *dev,
+- struct iw_request_info *info,
+- struct sockaddr *ap_addr, char *extra)
+-{
+- struct ieee80211_sub_if_data *sdata;
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+- sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
+- int ret;
+- if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) {
+- memcpy(sdata->u.sta.bssid, (u8 *) &ap_addr->sa_data,
+- ETH_ALEN);
+- return 0;
+- }
+- if (is_zero_ether_addr((u8 *) &ap_addr->sa_data))
+- sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL |
+- IEEE80211_STA_AUTO_CHANNEL_SEL;
+- else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data))
+- sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL;
+- else
+- sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
+- ret = ieee80211_sta_set_bssid(dev, (u8 *) &ap_addr->sa_data);
+- if (ret)
+- return ret;
+- ieee80211_sta_req_auth(dev, &sdata->u.sta);
+- return 0;
+- } else if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) {
+- if (memcmp(sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data,
+- ETH_ALEN) == 0)
+- return 0;
+- return ieee80211_if_update_wds(dev, (u8 *) &ap_addr->sa_data);
+- }
+-
+- return -EOPNOTSUPP;
+-}
+-
+-
+-static int ieee80211_ioctl_giwap(struct net_device *dev,
+- struct iw_request_info *info,
+- struct sockaddr *ap_addr, char *extra)
+-{
+- struct ieee80211_sub_if_data *sdata;
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+- sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
+- ap_addr->sa_family = ARPHRD_ETHER;
+- memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN);
+- return 0;
+- } else if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) {
+- ap_addr->sa_family = ARPHRD_ETHER;
+- memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN);
+- return 0;
+- }
+-
+- return -EOPNOTSUPP;
+-}
+-
+-
+-static int ieee80211_ioctl_siwscan(struct net_device *dev,
+- struct iw_request_info *info,
+- union iwreq_data *wrqu, char *extra)
+-{
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- struct iw_scan_req *req = NULL;
+- u8 *ssid = NULL;
+- size_t ssid_len = 0;
+-
+- if (!netif_running(dev))
+- return -ENETDOWN;
+-
+- if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
+- sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
+- sdata->vif.type != IEEE80211_IF_TYPE_AP)
+- return -EOPNOTSUPP;
+-
+- /* if SSID was specified explicitly then use that */
+- if (wrqu->data.length == sizeof(struct iw_scan_req) &&
+- wrqu->data.flags & IW_SCAN_THIS_ESSID) {
+- req = (struct iw_scan_req *)extra;
+- ssid = req->essid;
+- ssid_len = req->essid_len;
+- }
+-
+- return ieee80211_sta_req_scan(dev, ssid, ssid_len);
+-}
+-
+-
+-static int ieee80211_ioctl_giwscan(struct net_device *dev,
+- struct iw_request_info *info,
+- struct iw_point *data, char *extra)
+-{
+- int res;
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+- if (local->sta_sw_scanning || local->sta_hw_scanning)
+- return -EAGAIN;
+-
+- res = ieee80211_sta_scan_results(dev, extra, data->length);
+- if (res >= 0) {
+- data->length = res;
+- return 0;
+- }
+- data->length = 0;
+- return res;
+-}
+-
+-
+-static int ieee80211_ioctl_siwrate(struct net_device *dev,
+- struct iw_request_info *info,
+- struct iw_param *rate, char *extra)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_hw_mode *mode;
+- int i;
+- u32 target_rate = rate->value / 100000;
+- struct ieee80211_sub_if_data *sdata;
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- if (!sdata->bss)
+- return -ENODEV;
+- mode = local->oper_hw_mode;
+- /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
+- * target_rate = X, rate->fixed = 1 means only rate X
+- * target_rate = X, rate->fixed = 0 means all rates <= X */
+- sdata->bss->max_ratectrl_rateidx = -1;
+- sdata->bss->force_unicast_rateidx = -1;
+- if (rate->value < 0)
+- return 0;
+- for (i=0; i < mode->num_rates; i++) {
+- struct ieee80211_rate *rates = &mode->rates[i];
+- int this_rate = rates->rate;
+-
+- if (target_rate == this_rate) {
+- sdata->bss->max_ratectrl_rateidx = i;
+- if (rate->fixed)
+- sdata->bss->force_unicast_rateidx = i;
+- return 0;
+- }
+- }
+- return -EINVAL;
+-}
+-
+-static int ieee80211_ioctl_giwrate(struct net_device *dev,
+- struct iw_request_info *info,
+- struct iw_param *rate, char *extra)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct sta_info *sta;
+- struct ieee80211_sub_if_data *sdata;
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
+- sta = sta_info_get(local, sdata->u.sta.bssid);
+- else
+- return -EOPNOTSUPP;
+- if (!sta)
+- return -ENODEV;
+- if (sta->txrate < local->oper_hw_mode->num_rates)
+- rate->value = local->oper_hw_mode->rates[sta->txrate].rate * 100000;
+- else
+- rate->value = 0;
+- sta_info_put(sta);
+- return 0;
+-}
+-
+-static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
+- struct iw_request_info *info,
+- union iwreq_data *data, char *extra)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- bool need_reconfig = 0;
+- u8 new_power_level;
+-
+- if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
+- return -EINVAL;
+- if (data->txpower.flags & IW_TXPOW_RANGE)
+- return -EINVAL;
+-
+- if (data->txpower.fixed) {
+- new_power_level = data->txpower.value;
+- } else {
+- /* Automatic power level. Get the px power from the current
+- * channel. */
+- struct ieee80211_channel* chan = local->oper_channel;
+- if (!chan)
+- return -EINVAL;
+-
+- new_power_level = chan->power_level;
+- }
+-
+- if (local->hw.conf.power_level != new_power_level) {
+- local->hw.conf.power_level = new_power_level;
+- need_reconfig = 1;
+- }
+-
+- if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {
+- local->hw.conf.radio_enabled = !(data->txpower.disabled);
+- need_reconfig = 1;
+- ieee80211_led_radio(local, local->hw.conf.radio_enabled);
+- }
+-
+- if (need_reconfig) {
+- ieee80211_hw_config(local);
+- /* The return value of hw_config is not of big interest here,
+- * as it doesn't say that it failed because of _this_ config
+- * change or something else. Ignore it. */
+- }
+-
+- return 0;
+-}
+-
+-static int ieee80211_ioctl_giwtxpower(struct net_device *dev,
+- struct iw_request_info *info,
+- union iwreq_data *data, char *extra)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+- data->txpower.fixed = 1;
+- data->txpower.disabled = !(local->hw.conf.radio_enabled);
+- data->txpower.value = local->hw.conf.power_level;
+- data->txpower.flags = IW_TXPOW_DBM;
+-
+- return 0;
+-}
+-
+-static int ieee80211_ioctl_siwrts(struct net_device *dev,
+- struct iw_request_info *info,
+- struct iw_param *rts, char *extra)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+- if (rts->disabled)
+- local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
+- else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD)
+- return -EINVAL;
+- else
+- local->rts_threshold = rts->value;
+-
+- /* If the wlan card performs RTS/CTS in hardware/firmware,
+- * configure it here */
+-
+- if (local->ops->set_rts_threshold)
+- local->ops->set_rts_threshold(local_to_hw(local),
+- local->rts_threshold);
+-
+- return 0;
+-}
+-
+-static int ieee80211_ioctl_giwrts(struct net_device *dev,
+- struct iw_request_info *info,
+- struct iw_param *rts, char *extra)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+- rts->value = local->rts_threshold;
+- rts->disabled = (rts->value >= IEEE80211_MAX_RTS_THRESHOLD);
+- rts->fixed = 1;
+-
+- return 0;
+-}
+-
+-
+-static int ieee80211_ioctl_siwfrag(struct net_device *dev,
+- struct iw_request_info *info,
+- struct iw_param *frag, char *extra)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+- if (frag->disabled)
+- local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
+- else if (frag->value < 256 ||
+- frag->value > IEEE80211_MAX_FRAG_THRESHOLD)
+- return -EINVAL;
+- else {
+- /* Fragment length must be even, so strip LSB. */
+- local->fragmentation_threshold = frag->value & ~0x1;
+- }
+-
+- /* If the wlan card performs fragmentation in hardware/firmware,
+- * configure it here */
+-
+- if (local->ops->set_frag_threshold)
+- local->ops->set_frag_threshold(
+- local_to_hw(local),
+- local->fragmentation_threshold);
+-
+- return 0;
+-}
+-
+-static int ieee80211_ioctl_giwfrag(struct net_device *dev,
+- struct iw_request_info *info,
+- struct iw_param *frag, char *extra)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+- frag->value = local->fragmentation_threshold;
+- frag->disabled = (frag->value >= IEEE80211_MAX_RTS_THRESHOLD);
+- frag->fixed = 1;
+-
+- return 0;
+-}
+-
+-
+-static int ieee80211_ioctl_siwretry(struct net_device *dev,
+- struct iw_request_info *info,
+- struct iw_param *retry, char *extra)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+- if (retry->disabled ||
+- (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
+- return -EINVAL;
+-
+- if (retry->flags & IW_RETRY_MAX)
+- local->long_retry_limit = retry->value;
+- else if (retry->flags & IW_RETRY_MIN)
+- local->short_retry_limit = retry->value;
+- else {
+- local->long_retry_limit = retry->value;
+- local->short_retry_limit = retry->value;
+- }
+-
+- if (local->ops->set_retry_limit) {
+- return local->ops->set_retry_limit(
+- local_to_hw(local),
+- local->short_retry_limit,
+- local->long_retry_limit);
+- }
+-
+- return 0;
+-}
+-
+-
+-static int ieee80211_ioctl_giwretry(struct net_device *dev,
+- struct iw_request_info *info,
+- struct iw_param *retry, char *extra)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+- retry->disabled = 0;
+- if (retry->flags == 0 || retry->flags & IW_RETRY_MIN) {
+- /* first return min value, iwconfig will ask max value
+- * later if needed */
+- retry->flags |= IW_RETRY_LIMIT;
+- retry->value = local->short_retry_limit;
+- if (local->long_retry_limit != local->short_retry_limit)
+- retry->flags |= IW_RETRY_MIN;
+- return 0;
+- }
+- if (retry->flags & IW_RETRY_MAX) {
+- retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+- retry->value = local->long_retry_limit;
+- }
+-
+- return 0;
+-}
+-
+-static int ieee80211_ioctl_siwmlme(struct net_device *dev,
+- struct iw_request_info *info,
+- struct iw_point *data, char *extra)
+-{
+- struct ieee80211_sub_if_data *sdata;
+- struct iw_mlme *mlme = (struct iw_mlme *) extra;
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
+- sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
+- return -EINVAL;
+-
+- switch (mlme->cmd) {
+- case IW_MLME_DEAUTH:
+- /* TODO: mlme->addr.sa_data */
+- return ieee80211_sta_deauthenticate(dev, mlme->reason_code);
+- case IW_MLME_DISASSOC:
+- /* TODO: mlme->addr.sa_data */
+- return ieee80211_sta_disassociate(dev, mlme->reason_code);
+- default:
+- return -EOPNOTSUPP;
+- }
+-}
+-
+-
+-static int ieee80211_ioctl_siwencode(struct net_device *dev,
+- struct iw_request_info *info,
+- struct iw_point *erq, char *keybuf)
+-{
+- struct ieee80211_sub_if_data *sdata;
+- int idx, i, alg = ALG_WEP;
+- u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+- int remove = 0;
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-
+- idx = erq->flags & IW_ENCODE_INDEX;
+- if (idx == 0) {
+- if (sdata->default_key)
+- for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+- if (sdata->default_key == sdata->keys[i]) {
+- idx = i;
+- break;
+- }
+- }
+- } else if (idx < 1 || idx > 4)
+- return -EINVAL;
+- else
+- idx--;
+-
+- if (erq->flags & IW_ENCODE_DISABLED)
+- remove = 1;
+- else if (erq->length == 0) {
+- /* No key data - just set the default TX key index */
+- ieee80211_set_default_key(sdata, idx);
+- return 0;
+- }
+-
+- return ieee80211_set_encryption(
+- dev, bcaddr,
+- idx, alg, remove,
+- !sdata->default_key,
+- keybuf, erq->length);
+-}
+-
+-
+-static int ieee80211_ioctl_giwencode(struct net_device *dev,
+- struct iw_request_info *info,
+- struct iw_point *erq, char *key)
+-{
+- struct ieee80211_sub_if_data *sdata;
+- int idx, i;
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-
+- idx = erq->flags & IW_ENCODE_INDEX;
+- if (idx < 1 || idx > 4) {
+- idx = -1;
+- if (!sdata->default_key)
+- idx = 0;
+- else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+- if (sdata->default_key == sdata->keys[i]) {
+- idx = i;
+- break;
+- }
+- }
+- if (idx < 0)
+- return -EINVAL;
+- } else
+- idx--;
+-
+- erq->flags = idx + 1;
+-
+- if (!sdata->keys[idx]) {
+- erq->length = 0;
+- erq->flags |= IW_ENCODE_DISABLED;
+- return 0;
+- }
+-
+- memcpy(key, sdata->keys[idx]->conf.key,
+- min_t(int, erq->length, sdata->keys[idx]->conf.keylen));
+- erq->length = sdata->keys[idx]->conf.keylen;
+- erq->flags |= IW_ENCODE_ENABLED;
+-
+- return 0;
+-}
+-
+-static int ieee80211_ioctl_siwauth(struct net_device *dev,
+- struct iw_request_info *info,
+- struct iw_param *data, char *extra)
+-{
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- int ret = 0;
+-
+- switch (data->flags & IW_AUTH_INDEX) {
+- case IW_AUTH_WPA_VERSION:
+- case IW_AUTH_CIPHER_PAIRWISE:
+- case IW_AUTH_CIPHER_GROUP:
+- case IW_AUTH_WPA_ENABLED:
+- case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+- case IW_AUTH_KEY_MGMT:
+- break;
+- case IW_AUTH_DROP_UNENCRYPTED:
+- sdata->drop_unencrypted = !!data->value;
+- break;
+- case IW_AUTH_PRIVACY_INVOKED:
+- if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
+- ret = -EINVAL;
+- else {
+- sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
+- /*
+- * Privacy invoked by wpa_supplicant, store the
+- * value and allow associating to a protected
+- * network without having a key up front.
+- */
+- if (data->value)
+- sdata->u.sta.flags |=
+- IEEE80211_STA_PRIVACY_INVOKED;
+- }
+- break;
+- case IW_AUTH_80211_AUTH_ALG:
+- if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+- sdata->vif.type == IEEE80211_IF_TYPE_IBSS)
+- sdata->u.sta.auth_algs = data->value;
+- else
+- ret = -EOPNOTSUPP;
+- break;
+- default:
+- ret = -EOPNOTSUPP;
+- break;
+- }
+- return ret;
+-}
+-
+-/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
+-static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct iw_statistics *wstats = &local->wstats;
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- struct sta_info *sta = NULL;
+-
+- if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+- sdata->vif.type == IEEE80211_IF_TYPE_IBSS)
+- sta = sta_info_get(local, sdata->u.sta.bssid);
+- if (!sta) {
+- wstats->discard.fragment = 0;
+- wstats->discard.misc = 0;
+- wstats->qual.qual = 0;
+- wstats->qual.level = 0;
+- wstats->qual.noise = 0;
+- wstats->qual.updated = IW_QUAL_ALL_INVALID;
+- } else {
+- wstats->qual.level = sta->last_rssi;
+- wstats->qual.qual = sta->last_signal;
+- wstats->qual.noise = sta->last_noise;
+- wstats->qual.updated = local->wstats_flags;
+- sta_info_put(sta);
+- }
+- return wstats;
+-}
+-
+-static int ieee80211_ioctl_giwauth(struct net_device *dev,
+- struct iw_request_info *info,
+- struct iw_param *data, char *extra)
+-{
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- int ret = 0;
+-
+- switch (data->flags & IW_AUTH_INDEX) {
+- case IW_AUTH_80211_AUTH_ALG:
+- if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+- sdata->vif.type == IEEE80211_IF_TYPE_IBSS)
+- data->value = sdata->u.sta.auth_algs;
+- else
+- ret = -EOPNOTSUPP;
+- break;
+- default:
+- ret = -EOPNOTSUPP;
+- break;
+- }
+- return ret;
+-}
+-
+-
+-static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
+- struct iw_request_info *info,
+- struct iw_point *erq, char *extra)
+-{
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
+- int uninitialized_var(alg), idx, i, remove = 0;
+-
+- switch (ext->alg) {
+- case IW_ENCODE_ALG_NONE:
+- remove = 1;
+- break;
+- case IW_ENCODE_ALG_WEP:
+- alg = ALG_WEP;
+- break;
+- case IW_ENCODE_ALG_TKIP:
+- alg = ALG_TKIP;
+- break;
+- case IW_ENCODE_ALG_CCMP:
+- alg = ALG_CCMP;
+- break;
+- default:
+- return -EOPNOTSUPP;
+- }
+-
+- if (erq->flags & IW_ENCODE_DISABLED)
+- remove = 1;
+-
+- idx = erq->flags & IW_ENCODE_INDEX;
+- if (idx < 1 || idx > 4) {
+- idx = -1;
+- if (!sdata->default_key)
+- idx = 0;
+- else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+- if (sdata->default_key == sdata->keys[i]) {
+- idx = i;
+- break;
+- }
+- }
+- if (idx < 0)
+- return -EINVAL;
+- } else
+- idx--;
+-
+- return ieee80211_set_encryption(dev, ext->addr.sa_data, idx, alg,
+- remove,
+- ext->ext_flags &
+- IW_ENCODE_EXT_SET_TX_KEY,
+- ext->key, ext->key_len);
+-}
+-
+-
+-/* Structures to export the Wireless Handlers */
+-
+-static const iw_handler ieee80211_handler[] =
+-{
+- (iw_handler) NULL, /* SIOCSIWCOMMIT */
+- (iw_handler) ieee80211_ioctl_giwname, /* SIOCGIWNAME */
+- (iw_handler) NULL, /* SIOCSIWNWID */
+- (iw_handler) NULL, /* SIOCGIWNWID */
+- (iw_handler) ieee80211_ioctl_siwfreq, /* SIOCSIWFREQ */
+- (iw_handler) ieee80211_ioctl_giwfreq, /* SIOCGIWFREQ */
+- (iw_handler) ieee80211_ioctl_siwmode, /* SIOCSIWMODE */
+- (iw_handler) ieee80211_ioctl_giwmode, /* SIOCGIWMODE */
+- (iw_handler) NULL, /* SIOCSIWSENS */
+- (iw_handler) NULL, /* SIOCGIWSENS */
+- (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */
+- (iw_handler) ieee80211_ioctl_giwrange, /* SIOCGIWRANGE */
+- (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */
+- (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */
+- (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */
+- (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */
+- (iw_handler) NULL, /* SIOCSIWSPY */
+- (iw_handler) NULL, /* SIOCGIWSPY */
+- (iw_handler) NULL, /* SIOCSIWTHRSPY */
+- (iw_handler) NULL, /* SIOCGIWTHRSPY */
+- (iw_handler) ieee80211_ioctl_siwap, /* SIOCSIWAP */
+- (iw_handler) ieee80211_ioctl_giwap, /* SIOCGIWAP */
+- (iw_handler) ieee80211_ioctl_siwmlme, /* SIOCSIWMLME */
+- (iw_handler) NULL, /* SIOCGIWAPLIST */
+- (iw_handler) ieee80211_ioctl_siwscan, /* SIOCSIWSCAN */
+- (iw_handler) ieee80211_ioctl_giwscan, /* SIOCGIWSCAN */
+- (iw_handler) ieee80211_ioctl_siwessid, /* SIOCSIWESSID */
+- (iw_handler) ieee80211_ioctl_giwessid, /* SIOCGIWESSID */
+- (iw_handler) NULL, /* SIOCSIWNICKN */
+- (iw_handler) NULL, /* SIOCGIWNICKN */
+- (iw_handler) NULL, /* -- hole -- */
+- (iw_handler) NULL, /* -- hole -- */
+- (iw_handler) ieee80211_ioctl_siwrate, /* SIOCSIWRATE */
+- (iw_handler) ieee80211_ioctl_giwrate, /* SIOCGIWRATE */
+- (iw_handler) ieee80211_ioctl_siwrts, /* SIOCSIWRTS */
+- (iw_handler) ieee80211_ioctl_giwrts, /* SIOCGIWRTS */
+- (iw_handler) ieee80211_ioctl_siwfrag, /* SIOCSIWFRAG */
+- (iw_handler) ieee80211_ioctl_giwfrag, /* SIOCGIWFRAG */
+- (iw_handler) ieee80211_ioctl_siwtxpower, /* SIOCSIWTXPOW */
+- (iw_handler) ieee80211_ioctl_giwtxpower, /* SIOCGIWTXPOW */
+- (iw_handler) ieee80211_ioctl_siwretry, /* SIOCSIWRETRY */
+- (iw_handler) ieee80211_ioctl_giwretry, /* SIOCGIWRETRY */
+- (iw_handler) ieee80211_ioctl_siwencode, /* SIOCSIWENCODE */
+- (iw_handler) ieee80211_ioctl_giwencode, /* SIOCGIWENCODE */
+- (iw_handler) NULL, /* SIOCSIWPOWER */
+- (iw_handler) NULL, /* SIOCGIWPOWER */
+- (iw_handler) NULL, /* -- hole -- */
+- (iw_handler) NULL, /* -- hole -- */
+- (iw_handler) ieee80211_ioctl_siwgenie, /* SIOCSIWGENIE */
+- (iw_handler) NULL, /* SIOCGIWGENIE */
+- (iw_handler) ieee80211_ioctl_siwauth, /* SIOCSIWAUTH */
+- (iw_handler) ieee80211_ioctl_giwauth, /* SIOCGIWAUTH */
+- (iw_handler) ieee80211_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */
+- (iw_handler) NULL, /* SIOCGIWENCODEEXT */
+- (iw_handler) NULL, /* SIOCSIWPMKSA */
+- (iw_handler) NULL, /* -- hole -- */
+-};
+-
+-const struct iw_handler_def ieee80211_iw_handler_def =
+-{
+- .num_standard = ARRAY_SIZE(ieee80211_handler),
+- .standard = (iw_handler *) ieee80211_handler,
+- .get_wireless_stats = ieee80211_get_wireless_stats,
+-};
+diff --git a/net/mac80211/ieee80211_key.h b/net/mac80211/ieee80211_key.h
+deleted file mode 100644
+index fc770e9..0000000
+--- a/net/mac80211/ieee80211_key.h
++++ /dev/null
+@@ -1,127 +0,0 @@
+-/*
+- * Copyright 2002-2004, Instant802 Networks, Inc.
+- * Copyright 2005, Devicescape Software, Inc.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#ifndef IEEE80211_KEY_H
+-#define IEEE80211_KEY_H
+-
+-#include <linux/types.h>
+-#include <linux/list.h>
+-#include <linux/crypto.h>
+-#include <net/mac80211.h>
+-
+-/* ALG_TKIP
+- * struct ieee80211_key::key is encoded as a 256-bit (32 byte) data block:
+- * Temporal Encryption Key (128 bits)
+- * Temporal Authenticator Tx MIC Key (64 bits)
+- * Temporal Authenticator Rx MIC Key (64 bits)
+- */
+-
+-#define WEP_IV_LEN 4
+-#define WEP_ICV_LEN 4
+-
+-#define ALG_TKIP_KEY_LEN 32
+-/* Starting offsets for each key */
+-#define ALG_TKIP_TEMP_ENCR_KEY 0
+-#define ALG_TKIP_TEMP_AUTH_TX_MIC_KEY 16
+-#define ALG_TKIP_TEMP_AUTH_RX_MIC_KEY 24
+-#define TKIP_IV_LEN 8
+-#define TKIP_ICV_LEN 4
+-
+-#define ALG_CCMP_KEY_LEN 16
+-#define CCMP_HDR_LEN 8
+-#define CCMP_MIC_LEN 8
+-#define CCMP_TK_LEN 16
+-#define CCMP_PN_LEN 6
+-
+-#define NUM_RX_DATA_QUEUES 17
+-
+-struct ieee80211_local;
+-struct ieee80211_sub_if_data;
+-struct sta_info;
+-
+-#define KEY_FLAG_UPLOADED_TO_HARDWARE (1<<0)
+-
+-struct ieee80211_key {
+- struct ieee80211_local *local;
+- struct ieee80211_sub_if_data *sdata;
+- struct sta_info *sta;
+-
+- struct list_head list;
+-
+- unsigned int flags;
+-
+- union {
+- struct {
+- /* last used TSC */
+- u32 iv32;
+- u16 iv16;
+- u16 p1k[5];
+- int tx_initialized;
+-
+- /* last received RSC */
+- u32 iv32_rx[NUM_RX_DATA_QUEUES];
+- u16 iv16_rx[NUM_RX_DATA_QUEUES];
+- u16 p1k_rx[NUM_RX_DATA_QUEUES][5];
+- int rx_initialized[NUM_RX_DATA_QUEUES];
+- } tkip;
+- struct {
+- u8 tx_pn[6];
+- u8 rx_pn[NUM_RX_DATA_QUEUES][6];
+- struct crypto_cipher *tfm;
+- u32 replays; /* dot11RSNAStatsCCMPReplays */
+- /* scratch buffers for virt_to_page() (crypto API) */
+-#ifndef AES_BLOCK_LEN
+-#define AES_BLOCK_LEN 16
+-#endif
+- u8 tx_crypto_buf[6 * AES_BLOCK_LEN];
+- u8 rx_crypto_buf[6 * AES_BLOCK_LEN];
+- } ccmp;
+- } u;
+-
+- /* number of times this key has been used */
+- int tx_rx_count;
+-
+-#ifdef CONFIG_MAC80211_DEBUGFS
+- struct {
+- struct dentry *stalink;
+- struct dentry *dir;
+- struct dentry *keylen;
+- struct dentry *flags;
+- struct dentry *keyidx;
+- struct dentry *hw_key_idx;
+- struct dentry *tx_rx_count;
+- struct dentry *algorithm;
+- struct dentry *tx_spec;
+- struct dentry *rx_spec;
+- struct dentry *replays;
+- struct dentry *key;
+- struct dentry *ifindex;
+- } debugfs;
+-#endif
+-
+- /*
+- * key config, must be last because it contains key
+- * material as variable length member
+- */
+- struct ieee80211_key_conf conf;
+-};
+-
+-struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
+- struct sta_info *sta,
+- enum ieee80211_key_alg alg,
+- int idx,
+- size_t key_len,
+- const u8 *key_data);
+-void ieee80211_key_free(struct ieee80211_key *key);
+-void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx);
+-void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata);
+-void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata);
+-void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata);
+-
+-#endif /* IEEE80211_KEY_H */
+diff --git a/net/mac80211/ieee80211_led.c b/net/mac80211/ieee80211_led.c
+deleted file mode 100644
+index f401484..0000000
+--- a/net/mac80211/ieee80211_led.c
++++ /dev/null
+@@ -1,161 +0,0 @@
+-/*
+- * Copyright 2006, Johannes Berg <johannes at sipsolutions.net>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-/* just for IFNAMSIZ */
+-#include <linux/if.h>
+-#include "ieee80211_led.h"
+-
+-void ieee80211_led_rx(struct ieee80211_local *local)
+-{
+- if (unlikely(!local->rx_led))
+- return;
+- if (local->rx_led_counter++ % 2 == 0)
+- led_trigger_event(local->rx_led, LED_OFF);
+- else
+- led_trigger_event(local->rx_led, LED_FULL);
+-}
+-
+-/* q is 1 if a packet was enqueued, 0 if it has been transmitted */
+-void ieee80211_led_tx(struct ieee80211_local *local, int q)
+-{
+- if (unlikely(!local->tx_led))
+- return;
+- /* not sure how this is supposed to work ... */
+- local->tx_led_counter += 2*q-1;
+- if (local->tx_led_counter % 2 == 0)
+- led_trigger_event(local->tx_led, LED_OFF);
+- else
+- led_trigger_event(local->tx_led, LED_FULL);
+-}
+-
+-void ieee80211_led_assoc(struct ieee80211_local *local, bool associated)
+-{
+- if (unlikely(!local->assoc_led))
+- return;
+- if (associated)
+- led_trigger_event(local->assoc_led, LED_FULL);
+- else
+- led_trigger_event(local->assoc_led, LED_OFF);
+-}
+-
+-void ieee80211_led_radio(struct ieee80211_local *local, bool enabled)
+-{
+- if (unlikely(!local->radio_led))
+- return;
+- if (enabled)
+- led_trigger_event(local->radio_led, LED_FULL);
+- else
+- led_trigger_event(local->radio_led, LED_OFF);
+-}
+-
+-void ieee80211_led_init(struct ieee80211_local *local)
+-{
+- local->rx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
+- if (local->rx_led) {
+- snprintf(local->rx_led_name, sizeof(local->rx_led_name),
+- "%srx", wiphy_name(local->hw.wiphy));
+- local->rx_led->name = local->rx_led_name;
+- if (led_trigger_register(local->rx_led)) {
+- kfree(local->rx_led);
+- local->rx_led = NULL;
+- }
+- }
+-
+- local->tx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
+- if (local->tx_led) {
+- snprintf(local->tx_led_name, sizeof(local->tx_led_name),
+- "%stx", wiphy_name(local->hw.wiphy));
+- local->tx_led->name = local->tx_led_name;
+- if (led_trigger_register(local->tx_led)) {
+- kfree(local->tx_led);
+- local->tx_led = NULL;
+- }
+- }
+-
+- local->assoc_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
+- if (local->assoc_led) {
+- snprintf(local->assoc_led_name, sizeof(local->assoc_led_name),
+- "%sassoc", wiphy_name(local->hw.wiphy));
+- local->assoc_led->name = local->assoc_led_name;
+- if (led_trigger_register(local->assoc_led)) {
+- kfree(local->assoc_led);
+- local->assoc_led = NULL;
+- }
+- }
+-
+- local->radio_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
+- if (local->radio_led) {
+- snprintf(local->radio_led_name, sizeof(local->radio_led_name),
+- "%sradio", wiphy_name(local->hw.wiphy));
+- local->radio_led->name = local->radio_led_name;
+- if (led_trigger_register(local->radio_led)) {
+- kfree(local->radio_led);
+- local->radio_led = NULL;
+- }
+- }
+-}
+-
+-void ieee80211_led_exit(struct ieee80211_local *local)
+-{
+- if (local->radio_led) {
+- led_trigger_unregister(local->radio_led);
+- kfree(local->radio_led);
+- }
+- if (local->assoc_led) {
+- led_trigger_unregister(local->assoc_led);
+- kfree(local->assoc_led);
+- }
+- if (local->tx_led) {
+- led_trigger_unregister(local->tx_led);
+- kfree(local->tx_led);
+- }
+- if (local->rx_led) {
+- led_trigger_unregister(local->rx_led);
+- kfree(local->rx_led);
+- }
+-}
+-
+-char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw)
+-{
+- struct ieee80211_local *local = hw_to_local(hw);
+-
+- if (local->radio_led)
+- return local->radio_led_name;
+- return NULL;
+-}
+-EXPORT_SYMBOL(__ieee80211_get_radio_led_name);
+-
+-char *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw)
+-{
+- struct ieee80211_local *local = hw_to_local(hw);
+-
+- if (local->assoc_led)
+- return local->assoc_led_name;
+- return NULL;
+-}
+-EXPORT_SYMBOL(__ieee80211_get_assoc_led_name);
+-
+-char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw)
+-{
+- struct ieee80211_local *local = hw_to_local(hw);
+-
+- if (local->tx_led)
+- return local->tx_led_name;
+- return NULL;
+-}
+-EXPORT_SYMBOL(__ieee80211_get_tx_led_name);
+-
+-char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw)
+-{
+- struct ieee80211_local *local = hw_to_local(hw);
+-
+- if (local->rx_led)
+- return local->rx_led_name;
+- return NULL;
+-}
+-EXPORT_SYMBOL(__ieee80211_get_rx_led_name);
+diff --git a/net/mac80211/ieee80211_led.h b/net/mac80211/ieee80211_led.h
+deleted file mode 100644
+index 77b1e1b..0000000
+--- a/net/mac80211/ieee80211_led.h
++++ /dev/null
+@@ -1,44 +0,0 @@
+-/*
+- * Copyright 2006, Johannes Berg <johannes at sipsolutions.net>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#include <linux/list.h>
+-#include <linux/spinlock.h>
+-#include <linux/leds.h>
+-#include "ieee80211_i.h"
+-
+-#ifdef CONFIG_MAC80211_LEDS
+-extern void ieee80211_led_rx(struct ieee80211_local *local);
+-extern void ieee80211_led_tx(struct ieee80211_local *local, int q);
+-extern void ieee80211_led_assoc(struct ieee80211_local *local,
+- bool associated);
+-extern void ieee80211_led_radio(struct ieee80211_local *local,
+- bool enabled);
+-extern void ieee80211_led_init(struct ieee80211_local *local);
+-extern void ieee80211_led_exit(struct ieee80211_local *local);
+-#else
+-static inline void ieee80211_led_rx(struct ieee80211_local *local)
+-{
+-}
+-static inline void ieee80211_led_tx(struct ieee80211_local *local, int q)
+-{
+-}
+-static inline void ieee80211_led_assoc(struct ieee80211_local *local,
+- bool associated)
+-{
+-}
+-static inline void ieee80211_led_radio(struct ieee80211_local *local,
+- bool enabled)
+-{
+-}
+-static inline void ieee80211_led_init(struct ieee80211_local *local)
+-{
+-}
+-static inline void ieee80211_led_exit(struct ieee80211_local *local)
+-{
+-}
+-#endif
+diff --git a/net/mac80211/ieee80211_rate.c b/net/mac80211/ieee80211_rate.c
+deleted file mode 100644
+index b957e67..0000000
+--- a/net/mac80211/ieee80211_rate.c
++++ /dev/null
+@@ -1,246 +0,0 @@
+-/*
+- * Copyright 2002-2005, Instant802 Networks, Inc.
+- * Copyright 2005-2006, Devicescape Software, Inc.
+- * Copyright (c) 2006 Jiri Benc <jbenc at suse.cz>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/rtnetlink.h>
+-#include "ieee80211_rate.h"
+-#include "ieee80211_i.h"
+-
+-struct rate_control_alg {
+- struct list_head list;
+- struct rate_control_ops *ops;
+-};
+-
+-static LIST_HEAD(rate_ctrl_algs);
+-static DEFINE_MUTEX(rate_ctrl_mutex);
+-
+-static char *ieee80211_default_rc_algo = CONFIG_MAC80211_RC_DEFAULT;
+-module_param(ieee80211_default_rc_algo, charp, 0644);
+-MODULE_PARM_DESC(ieee80211_default_rc_algo,
+- "Default rate control algorithm for mac80211 to use");
+-
+-int ieee80211_rate_control_register(struct rate_control_ops *ops)
+-{
+- struct rate_control_alg *alg;
+-
+- if (!ops->name)
+- return -EINVAL;
+-
+- mutex_lock(&rate_ctrl_mutex);
+- list_for_each_entry(alg, &rate_ctrl_algs, list) {
+- if (!strcmp(alg->ops->name, ops->name)) {
+- /* don't register an algorithm twice */
+- WARN_ON(1);
+- mutex_unlock(&rate_ctrl_mutex);
+- return -EALREADY;
+- }
+- }
+-
+- alg = kzalloc(sizeof(*alg), GFP_KERNEL);
+- if (alg == NULL) {
+- mutex_unlock(&rate_ctrl_mutex);
+- return -ENOMEM;
+- }
+- alg->ops = ops;
+-
+- list_add_tail(&alg->list, &rate_ctrl_algs);
+- mutex_unlock(&rate_ctrl_mutex);
+-
+- return 0;
+-}
+-EXPORT_SYMBOL(ieee80211_rate_control_register);
+-
+-void ieee80211_rate_control_unregister(struct rate_control_ops *ops)
+-{
+- struct rate_control_alg *alg;
+-
+- mutex_lock(&rate_ctrl_mutex);
+- list_for_each_entry(alg, &rate_ctrl_algs, list) {
+- if (alg->ops == ops) {
+- list_del(&alg->list);
+- kfree(alg);
+- break;
+- }
+- }
+- mutex_unlock(&rate_ctrl_mutex);
+-}
+-EXPORT_SYMBOL(ieee80211_rate_control_unregister);
+-
+-static struct rate_control_ops *
+-ieee80211_try_rate_control_ops_get(const char *name)
+-{
+- struct rate_control_alg *alg;
+- struct rate_control_ops *ops = NULL;
+-
+- if (!name)
+- return NULL;
+-
+- mutex_lock(&rate_ctrl_mutex);
+- list_for_each_entry(alg, &rate_ctrl_algs, list) {
+- if (!strcmp(alg->ops->name, name))
+- if (try_module_get(alg->ops->module)) {
+- ops = alg->ops;
+- break;
+- }
+- }
+- mutex_unlock(&rate_ctrl_mutex);
+- return ops;
+-}
+-
+-/* Get the rate control algorithm. */
+-static struct rate_control_ops *
+-ieee80211_rate_control_ops_get(const char *name)
+-{
+- struct rate_control_ops *ops;
+- const char *alg_name;
+-
+- if (!name)
+- alg_name = ieee80211_default_rc_algo;
+- else
+- alg_name = name;
+-
+- ops = ieee80211_try_rate_control_ops_get(alg_name);
+- if (!ops) {
+- request_module("rc80211_%s", alg_name);
+- ops = ieee80211_try_rate_control_ops_get(alg_name);
+- }
+- if (!ops && name)
+- /* try default if specific alg requested but not found */
+- ops = ieee80211_try_rate_control_ops_get(ieee80211_default_rc_algo);
+-
+- /* try built-in one if specific alg requested but not found */
+- if (!ops && strlen(CONFIG_MAC80211_RC_DEFAULT))
+- ops = ieee80211_try_rate_control_ops_get(CONFIG_MAC80211_RC_DEFAULT);
+-
+- return ops;
+-}
+-
+-static void ieee80211_rate_control_ops_put(struct rate_control_ops *ops)
+-{
+- module_put(ops->module);
+-}
+-
+-struct rate_control_ref *rate_control_alloc(const char *name,
+- struct ieee80211_local *local)
+-{
+- struct rate_control_ref *ref;
+-
+- ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL);
+- if (!ref)
+- goto fail_ref;
+- kref_init(&ref->kref);
+- ref->ops = ieee80211_rate_control_ops_get(name);
+- if (!ref->ops)
+- goto fail_ops;
+- ref->priv = ref->ops->alloc(local);
+- if (!ref->priv)
+- goto fail_priv;
+- return ref;
+-
+-fail_priv:
+- ieee80211_rate_control_ops_put(ref->ops);
+-fail_ops:
+- kfree(ref);
+-fail_ref:
+- return NULL;
+-}
+-
+-static void rate_control_release(struct kref *kref)
+-{
+- struct rate_control_ref *ctrl_ref;
+-
+- ctrl_ref = container_of(kref, struct rate_control_ref, kref);
+- ctrl_ref->ops->free(ctrl_ref->priv);
+- ieee80211_rate_control_ops_put(ctrl_ref->ops);
+- kfree(ctrl_ref);
+-}
+-
+-void rate_control_get_rate(struct net_device *dev,
+- struct ieee80211_hw_mode *mode, struct sk_buff *skb,
+- struct rate_selection *sel)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct rate_control_ref *ref = local->rate_ctrl;
+- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+- struct sta_info *sta = sta_info_get(local, hdr->addr1);
+- int i;
+-
+- memset(sel, 0, sizeof(struct rate_selection));
+-
+- ref->ops->get_rate(ref->priv, dev, mode, skb, sel);
+-
+- /* Select a non-ERP backup rate. */
+- if (!sel->nonerp) {
+- for (i = 0; i < mode->num_rates - 1; i++) {
+- struct ieee80211_rate *rate = &mode->rates[i];
+- if (sel->rate->rate < rate->rate)
+- break;
+-
+- if (rate_supported(sta, mode, i) &&
+- !(rate->flags & IEEE80211_RATE_ERP))
+- sel->nonerp = rate;
+- }
+- }
+-
+- if (sta)
+- sta_info_put(sta);
+-}
+-
+-struct rate_control_ref *rate_control_get(struct rate_control_ref *ref)
+-{
+- kref_get(&ref->kref);
+- return ref;
+-}
+-
+-void rate_control_put(struct rate_control_ref *ref)
+-{
+- kref_put(&ref->kref, rate_control_release);
+-}
+-
+-int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
+- const char *name)
+-{
+- struct rate_control_ref *ref, *old;
+-
+- ASSERT_RTNL();
+- if (local->open_count || netif_running(local->mdev))
+- return -EBUSY;
+-
+- ref = rate_control_alloc(name, local);
+- if (!ref) {
+- printk(KERN_WARNING "%s: Failed to select rate control "
+- "algorithm\n", wiphy_name(local->hw.wiphy));
+- return -ENOENT;
+- }
+-
+- old = local->rate_ctrl;
+- local->rate_ctrl = ref;
+- if (old) {
+- rate_control_put(old);
+- sta_info_flush(local, NULL);
+- }
+-
+- printk(KERN_DEBUG "%s: Selected rate control "
+- "algorithm '%s'\n", wiphy_name(local->hw.wiphy),
+- ref->ops->name);
+-
+-
+- return 0;
+-}
+-
+-void rate_control_deinitialize(struct ieee80211_local *local)
+-{
+- struct rate_control_ref *ref;
+-
+- ref = local->rate_ctrl;
+- local->rate_ctrl = NULL;
+- rate_control_put(ref);
+-}
+-
+diff --git a/net/mac80211/ieee80211_rate.h b/net/mac80211/ieee80211_rate.h
+deleted file mode 100644
+index 73f19e8..0000000
+--- a/net/mac80211/ieee80211_rate.h
++++ /dev/null
+@@ -1,199 +0,0 @@
+-/*
+- * Copyright 2002-2005, Instant802 Networks, Inc.
+- * Copyright 2005, Devicescape Software, Inc.
+- * Copyright (c) 2006 Jiri Benc <jbenc at suse.cz>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#ifndef IEEE80211_RATE_H
+-#define IEEE80211_RATE_H
+-
+-#include <linux/netdevice.h>
+-#include <linux/skbuff.h>
+-#include <linux/types.h>
+-#include <net/mac80211.h>
+-#include "ieee80211_i.h"
+-#include "sta_info.h"
+-
+-struct rate_selection {
+- /* Selected transmission rate */
+- struct ieee80211_rate *rate;
+- /* Non-ERP rate to use if mac80211 decides it cannot use an ERP rate */
+- struct ieee80211_rate *nonerp;
+- /* probe with this rate, or NULL for no probing */
+- struct ieee80211_rate *probe;
+-};
+-
+-struct rate_control_ops {
+- struct module *module;
+- const char *name;
+- void (*tx_status)(void *priv, struct net_device *dev,
+- struct sk_buff *skb,
+- struct ieee80211_tx_status *status);
+- void (*get_rate)(void *priv, struct net_device *dev,
+- struct ieee80211_hw_mode *mode, struct sk_buff *skb,
+- struct rate_selection *sel);
+- void (*rate_init)(void *priv, void *priv_sta,
+- struct ieee80211_local *local, struct sta_info *sta);
+- void (*clear)(void *priv);
+-
+- void *(*alloc)(struct ieee80211_local *local);
+- void (*free)(void *priv);
+- void *(*alloc_sta)(void *priv, gfp_t gfp);
+- void (*free_sta)(void *priv, void *priv_sta);
+-
+- int (*add_attrs)(void *priv, struct kobject *kobj);
+- void (*remove_attrs)(void *priv, struct kobject *kobj);
+- void (*add_sta_debugfs)(void *priv, void *priv_sta,
+- struct dentry *dir);
+- void (*remove_sta_debugfs)(void *priv, void *priv_sta);
+-};
+-
+-struct rate_control_ref {
+- struct rate_control_ops *ops;
+- void *priv;
+- struct kref kref;
+-};
+-
+-int ieee80211_rate_control_register(struct rate_control_ops *ops);
+-void ieee80211_rate_control_unregister(struct rate_control_ops *ops);
+-
+-/* Get a reference to the rate control algorithm. If `name' is NULL, get the
+- * first available algorithm. */
+-struct rate_control_ref *rate_control_alloc(const char *name,
+- struct ieee80211_local *local);
+-void rate_control_get_rate(struct net_device *dev,
+- struct ieee80211_hw_mode *mode, struct sk_buff *skb,
+- struct rate_selection *sel);
+-struct rate_control_ref *rate_control_get(struct rate_control_ref *ref);
+-void rate_control_put(struct rate_control_ref *ref);
+-
+-static inline void rate_control_tx_status(struct net_device *dev,
+- struct sk_buff *skb,
+- struct ieee80211_tx_status *status)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct rate_control_ref *ref = local->rate_ctrl;
+-
+- ref->ops->tx_status(ref->priv, dev, skb, status);
+-}
+-
+-
+-static inline void rate_control_rate_init(struct sta_info *sta,
+- struct ieee80211_local *local)
+-{
+- struct rate_control_ref *ref = sta->rate_ctrl;
+- ref->ops->rate_init(ref->priv, sta->rate_ctrl_priv, local, sta);
+-}
+-
+-
+-static inline void rate_control_clear(struct ieee80211_local *local)
+-{
+- struct rate_control_ref *ref = local->rate_ctrl;
+- ref->ops->clear(ref->priv);
+-}
+-
+-static inline void *rate_control_alloc_sta(struct rate_control_ref *ref,
+- gfp_t gfp)
+-{
+- return ref->ops->alloc_sta(ref->priv, gfp);
+-}
+-
+-static inline void rate_control_free_sta(struct rate_control_ref *ref,
+- void *priv)
+-{
+- ref->ops->free_sta(ref->priv, priv);
+-}
+-
+-static inline void rate_control_add_sta_debugfs(struct sta_info *sta)
+-{
+-#ifdef CONFIG_MAC80211_DEBUGFS
+- struct rate_control_ref *ref = sta->rate_ctrl;
+- if (sta->debugfs.dir && ref->ops->add_sta_debugfs)
+- ref->ops->add_sta_debugfs(ref->priv, sta->rate_ctrl_priv,
+- sta->debugfs.dir);
+-#endif
+-}
+-
+-static inline void rate_control_remove_sta_debugfs(struct sta_info *sta)
+-{
+-#ifdef CONFIG_MAC80211_DEBUGFS
+- struct rate_control_ref *ref = sta->rate_ctrl;
+- if (ref->ops->remove_sta_debugfs)
+- ref->ops->remove_sta_debugfs(ref->priv, sta->rate_ctrl_priv);
+-#endif
+-}
+-
+-static inline int
+-rate_supported(struct sta_info *sta, struct ieee80211_hw_mode *mode, int index)
+-{
+- return (sta == NULL || sta->supp_rates & BIT(index)) &&
+- (mode->rates[index].flags & IEEE80211_RATE_SUPPORTED);
+-}
+-
+-static inline int
+-rate_lowest_index(struct ieee80211_local *local, struct ieee80211_hw_mode *mode,
+- struct sta_info *sta)
+-{
+- int i;
+-
+- for (i = 0; i < mode->num_rates; i++) {
+- if (rate_supported(sta, mode, i))
+- return i;
+- }
+-
+- /* warn when we cannot find a rate. */
+- WARN_ON(1);
+-
+- return 0;
+-}
+-
+-static inline struct ieee80211_rate *
+-rate_lowest(struct ieee80211_local *local, struct ieee80211_hw_mode *mode,
+- struct sta_info *sta)
+-{
+- return &mode->rates[rate_lowest_index(local, mode, sta)];
+-}
+-
+-
+-/* functions for rate control related to a device */
+-int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
+- const char *name);
+-void rate_control_deinitialize(struct ieee80211_local *local);
+-
+-
+-/* Rate control algorithms */
+-#if defined(RC80211_SIMPLE_COMPILE) || \
+- (defined(CONFIG_MAC80211_RC_SIMPLE) && \
+- !defined(CONFIG_MAC80211_RC_SIMPLE_MODULE))
+-extern int rc80211_simple_init(void);
+-extern void rc80211_simple_exit(void);
+-#else
+-static inline int rc80211_simple_init(void)
+-{
+- return 0;
+-}
+-static inline void rc80211_simple_exit(void)
+-{
+-}
+-#endif
+-
+-#if defined(RC80211_PID_COMPILE) || \
+- (defined(CONFIG_MAC80211_RC_PID) && \
+- !defined(CONFIG_MAC80211_RC_PID_MODULE))
+-extern int rc80211_pid_init(void);
+-extern void rc80211_pid_exit(void);
+-#else
+-static inline int rc80211_pid_init(void)
+-{
+- return 0;
+-}
+-static inline void rc80211_pid_exit(void)
+-{
+-}
+-#endif
+-
+-#endif /* IEEE80211_RATE_H */
+diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
+deleted file mode 100644
+index c170685..0000000
+--- a/net/mac80211/ieee80211_sta.c
++++ /dev/null
+@@ -1,3632 +0,0 @@
+-/*
+- * BSS client mode implementation
+- * Copyright 2003, Jouni Malinen <jkmaline at cc.hut.fi>
+- * Copyright 2004, Instant802 Networks, Inc.
+- * Copyright 2005, Devicescape Software, Inc.
+- * Copyright 2006-2007 Jiri Benc <jbenc at suse.cz>
+- * Copyright 2007, Michael Wu <flamingice at sourmilk.net>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-/* TODO:
+- * order BSS list by RSSI(?) ("quality of AP")
+- * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE,
+- * SSID)
+- */
+-#include <linux/delay.h>
+-#include <linux/if_ether.h>
+-#include <linux/skbuff.h>
+-#include <linux/netdevice.h>
+-#include <linux/if_arp.h>
+-#include <linux/wireless.h>
+-#include <linux/random.h>
+-#include <linux/etherdevice.h>
+-#include <net/iw_handler.h>
+-#include <asm/types.h>
+-
+-#include <net/mac80211.h>
+-#include "ieee80211_i.h"
+-#include "ieee80211_rate.h"
+-#include "ieee80211_led.h"
+-
+-#define IEEE80211_AUTH_TIMEOUT (HZ / 5)
+-#define IEEE80211_AUTH_MAX_TRIES 3
+-#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
+-#define IEEE80211_ASSOC_MAX_TRIES 3
+-#define IEEE80211_MONITORING_INTERVAL (2 * HZ)
+-#define IEEE80211_PROBE_INTERVAL (60 * HZ)
+-#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ)
+-#define IEEE80211_SCAN_INTERVAL (2 * HZ)
+-#define IEEE80211_SCAN_INTERVAL_SLOW (15 * HZ)
+-#define IEEE80211_IBSS_JOIN_TIMEOUT (20 * HZ)
+-
+-#define IEEE80211_PROBE_DELAY (HZ / 33)
+-#define IEEE80211_CHANNEL_TIME (HZ / 33)
+-#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5)
+-#define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ)
+-#define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ)
+-#define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ)
+-
+-#define IEEE80211_IBSS_MAX_STA_ENTRIES 128
+-
+-
+-#define IEEE80211_FC(type, stype) cpu_to_le16(type | stype)
+-
+-#define ERP_INFO_USE_PROTECTION BIT(1)
+-
+-/* mgmt header + 1 byte action code */
+-#define IEEE80211_MIN_ACTION_SIZE (24 + 1)
+-
+-#define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002
+-#define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C
+-#define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFA0
+-#define IEEE80211_DELBA_PARAM_TID_MASK 0xF000
+-#define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800
+-
+-/* next values represent the buffer size for A-MPDU frame.
+- * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) */
+-#define IEEE80211_MIN_AMPDU_BUF 0x8
+-#define IEEE80211_MAX_AMPDU_BUF 0x40
+-
+-static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
+- u8 *ssid, size_t ssid_len);
+-static struct ieee80211_sta_bss *
+-ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel,
+- u8 *ssid, u8 ssid_len);
+-static void ieee80211_rx_bss_put(struct net_device *dev,
+- struct ieee80211_sta_bss *bss);
+-static int ieee80211_sta_find_ibss(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta);
+-static int ieee80211_sta_wep_configured(struct net_device *dev);
+-static int ieee80211_sta_start_scan(struct net_device *dev,
+- u8 *ssid, size_t ssid_len);
+-static int ieee80211_sta_config_auth(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta);
+-
+-
+-/* Parsed Information Elements */
+-struct ieee802_11_elems {
+- /* pointers to IEs */
+- u8 *ssid;
+- u8 *supp_rates;
+- u8 *fh_params;
+- u8 *ds_params;
+- u8 *cf_params;
+- u8 *tim;
+- u8 *ibss_params;
+- u8 *challenge;
+- u8 *wpa;
+- u8 *rsn;
+- u8 *erp_info;
+- u8 *ext_supp_rates;
+- u8 *wmm_info;
+- u8 *wmm_param;
+- u8 *ht_cap_elem;
+- u8 *ht_info_elem;
+- /* length of them, respectively */
+- u8 ssid_len;
+- u8 supp_rates_len;
+- u8 fh_params_len;
+- u8 ds_params_len;
+- u8 cf_params_len;
+- u8 tim_len;
+- u8 ibss_params_len;
+- u8 challenge_len;
+- u8 wpa_len;
+- u8 rsn_len;
+- u8 erp_info_len;
+- u8 ext_supp_rates_len;
+- u8 wmm_info_len;
+- u8 wmm_param_len;
+- u8 ht_cap_elem_len;
+- u8 ht_info_elem_len;
+-};
+-
+-static void ieee802_11_parse_elems(u8 *start, size_t len,
+- struct ieee802_11_elems *elems)
+-{
+- size_t left = len;
+- u8 *pos = start;
+-
+- memset(elems, 0, sizeof(*elems));
+-
+- while (left >= 2) {
+- u8 id, elen;
+-
+- id = *pos++;
+- elen = *pos++;
+- left -= 2;
+-
+- if (elen > left)
+- return;
+-
+- switch (id) {
+- case WLAN_EID_SSID:
+- elems->ssid = pos;
+- elems->ssid_len = elen;
+- break;
+- case WLAN_EID_SUPP_RATES:
+- elems->supp_rates = pos;
+- elems->supp_rates_len = elen;
+- break;
+- case WLAN_EID_FH_PARAMS:
+- elems->fh_params = pos;
+- elems->fh_params_len = elen;
+- break;
+- case WLAN_EID_DS_PARAMS:
+- elems->ds_params = pos;
+- elems->ds_params_len = elen;
+- break;
+- case WLAN_EID_CF_PARAMS:
+- elems->cf_params = pos;
+- elems->cf_params_len = elen;
+- break;
+- case WLAN_EID_TIM:
+- elems->tim = pos;
+- elems->tim_len = elen;
+- break;
+- case WLAN_EID_IBSS_PARAMS:
+- elems->ibss_params = pos;
+- elems->ibss_params_len = elen;
+- break;
+- case WLAN_EID_CHALLENGE:
+- elems->challenge = pos;
+- elems->challenge_len = elen;
+- break;
+- case WLAN_EID_WPA:
+- if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
+- pos[2] == 0xf2) {
+- /* Microsoft OUI (00:50:F2) */
+- if (pos[3] == 1) {
+- /* OUI Type 1 - WPA IE */
+- elems->wpa = pos;
+- elems->wpa_len = elen;
+- } else if (elen >= 5 && pos[3] == 2) {
+- if (pos[4] == 0) {
+- elems->wmm_info = pos;
+- elems->wmm_info_len = elen;
+- } else if (pos[4] == 1) {
+- elems->wmm_param = pos;
+- elems->wmm_param_len = elen;
+- }
+- }
+- }
+- break;
+- case WLAN_EID_RSN:
+- elems->rsn = pos;
+- elems->rsn_len = elen;
+- break;
+- case WLAN_EID_ERP_INFO:
+- elems->erp_info = pos;
+- elems->erp_info_len = elen;
+- break;
+- case WLAN_EID_EXT_SUPP_RATES:
+- elems->ext_supp_rates = pos;
+- elems->ext_supp_rates_len = elen;
+- break;
+- case WLAN_EID_HT_CAPABILITY:
+- elems->ht_cap_elem = pos;
+- elems->ht_cap_elem_len = elen;
+- break;
+- case WLAN_EID_HT_EXTRA_INFO:
+- elems->ht_info_elem = pos;
+- elems->ht_info_elem_len = elen;
+- break;
+- default:
+- break;
+- }
+-
+- left -= elen;
+- pos += elen;
+- }
+-}
+-
+-
+-static int ecw2cw(int ecw)
+-{
+- int cw = 1;
+- while (ecw > 0) {
+- cw <<= 1;
+- ecw--;
+- }
+- return cw - 1;
+-}
+-
+-static void ieee80211_sta_wmm_params(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta,
+- u8 *wmm_param, size_t wmm_param_len)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_tx_queue_params params;
+- size_t left;
+- int count;
+- u8 *pos;
+-
+- if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
+- return;
+- count = wmm_param[6] & 0x0f;
+- if (count == ifsta->wmm_last_param_set)
+- return;
+- ifsta->wmm_last_param_set = count;
+-
+- pos = wmm_param + 8;
+- left = wmm_param_len - 8;
+-
+- memset(¶ms, 0, sizeof(params));
+-
+- if (!local->ops->conf_tx)
+- return;
+-
+- local->wmm_acm = 0;
+- for (; left >= 4; left -= 4, pos += 4) {
+- int aci = (pos[0] >> 5) & 0x03;
+- int acm = (pos[0] >> 4) & 0x01;
+- int queue;
+-
+- switch (aci) {
+- case 1:
+- queue = IEEE80211_TX_QUEUE_DATA3;
+- if (acm) {
+- local->wmm_acm |= BIT(0) | BIT(3);
+- }
+- break;
+- case 2:
+- queue = IEEE80211_TX_QUEUE_DATA1;
+- if (acm) {
+- local->wmm_acm |= BIT(4) | BIT(5);
+- }
+- break;
+- case 3:
+- queue = IEEE80211_TX_QUEUE_DATA0;
+- if (acm) {
+- local->wmm_acm |= BIT(6) | BIT(7);
+- }
+- break;
+- case 0:
+- default:
+- queue = IEEE80211_TX_QUEUE_DATA2;
+- if (acm) {
+- local->wmm_acm |= BIT(1) | BIT(2);
+- }
+- break;
+- }
+-
+- params.aifs = pos[0] & 0x0f;
+- params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
+- params.cw_min = ecw2cw(pos[1] & 0x0f);
+- /* TXOP is in units of 32 usec; burst_time in 0.1 ms */
+- params.burst_time = (pos[2] | (pos[3] << 8)) * 32 / 100;
+- printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d "
+- "cWmin=%d cWmax=%d burst=%d\n",
+- dev->name, queue, aci, acm, params.aifs, params.cw_min,
+- params.cw_max, params.burst_time);
+- /* TODO: handle ACM (block TX, fallback to next lowest allowed
+- * AC for now) */
+- if (local->ops->conf_tx(local_to_hw(local), queue, ¶ms)) {
+- printk(KERN_DEBUG "%s: failed to set TX queue "
+- "parameters for queue %d\n", dev->name, queue);
+- }
+- }
+-}
+-
+-static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata,
+- bool use_protection,
+- bool use_short_preamble)
+-{
+- struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf;
+- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+- DECLARE_MAC_BUF(mac);
+- u32 changed = 0;
+-
+- if (use_protection != bss_conf->use_cts_prot) {
+- if (net_ratelimit()) {
+- printk(KERN_DEBUG "%s: CTS protection %s (BSSID="
+- "%s)\n",
+- sdata->dev->name,
+- use_protection ? "enabled" : "disabled",
+- print_mac(mac, ifsta->bssid));
+- }
+- bss_conf->use_cts_prot = use_protection;
+- changed |= BSS_CHANGED_ERP_CTS_PROT;
+- }
+-
+- if (use_short_preamble != bss_conf->use_short_preamble) {
+- if (net_ratelimit()) {
+- printk(KERN_DEBUG "%s: switched to %s barker preamble"
+- " (BSSID=%s)\n",
+- sdata->dev->name,
+- use_short_preamble ? "short" : "long",
+- print_mac(mac, ifsta->bssid));
+- }
+- bss_conf->use_short_preamble = use_short_preamble;
+- changed |= BSS_CHANGED_ERP_PREAMBLE;
+- }
+-
+- return changed;
+-}
+-
+-static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata,
+- u8 erp_value)
+-{
+- bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
+- bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0;
+-
+- return ieee80211_handle_protect_preamb(sdata,
+- use_protection, use_short_preamble);
+-}
+-
+-static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
+- struct ieee80211_sta_bss *bss)
+-{
+- u32 changed = 0;
+-
+- if (bss->has_erp_value)
+- changed |= ieee80211_handle_erp_ie(sdata, bss->erp_value);
+- else {
+- u16 capab = bss->capability;
+- changed |= ieee80211_handle_protect_preamb(sdata, false,
+- (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0);
+- }
+-
+- return changed;
+-}
+-
+-int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie,
+- struct ieee80211_ht_info *ht_info)
+-{
+-
+- if (ht_info == NULL)
+- return -EINVAL;
+-
+- memset(ht_info, 0, sizeof(*ht_info));
+-
+- if (ht_cap_ie) {
+- u8 ampdu_info = ht_cap_ie->ampdu_params_info;
+-
+- ht_info->ht_supported = 1;
+- ht_info->cap = le16_to_cpu(ht_cap_ie->cap_info);
+- ht_info->ampdu_factor =
+- ampdu_info & IEEE80211_HT_CAP_AMPDU_FACTOR;
+- ht_info->ampdu_density =
+- (ampdu_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2;
+- memcpy(ht_info->supp_mcs_set, ht_cap_ie->supp_mcs_set, 16);
+- } else
+- ht_info->ht_supported = 0;
+-
+- return 0;
+-}
+-
+-int ieee80211_ht_addt_info_ie_to_ht_bss_info(
+- struct ieee80211_ht_addt_info *ht_add_info_ie,
+- struct ieee80211_ht_bss_info *bss_info)
+-{
+- if (bss_info == NULL)
+- return -EINVAL;
+-
+- memset(bss_info, 0, sizeof(*bss_info));
+-
+- if (ht_add_info_ie) {
+- u16 op_mode;
+- op_mode = le16_to_cpu(ht_add_info_ie->operation_mode);
+-
+- bss_info->primary_channel = ht_add_info_ie->control_chan;
+- bss_info->bss_cap = ht_add_info_ie->ht_param;
+- bss_info->bss_op_mode = (u8)(op_mode & 0xff);
+- }
+-
+- return 0;
+-}
+-
+-static void ieee80211_sta_send_associnfo(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta)
+-{
+- char *buf;
+- size_t len;
+- int i;
+- union iwreq_data wrqu;
+-
+- if (!ifsta->assocreq_ies && !ifsta->assocresp_ies)
+- return;
+-
+- buf = kmalloc(50 + 2 * (ifsta->assocreq_ies_len +
+- ifsta->assocresp_ies_len), GFP_KERNEL);
+- if (!buf)
+- return;
+-
+- len = sprintf(buf, "ASSOCINFO(");
+- if (ifsta->assocreq_ies) {
+- len += sprintf(buf + len, "ReqIEs=");
+- for (i = 0; i < ifsta->assocreq_ies_len; i++) {
+- len += sprintf(buf + len, "%02x",
+- ifsta->assocreq_ies[i]);
+- }
+- }
+- if (ifsta->assocresp_ies) {
+- if (ifsta->assocreq_ies)
+- len += sprintf(buf + len, " ");
+- len += sprintf(buf + len, "RespIEs=");
+- for (i = 0; i < ifsta->assocresp_ies_len; i++) {
+- len += sprintf(buf + len, "%02x",
+- ifsta->assocresp_ies[i]);
+- }
+- }
+- len += sprintf(buf + len, ")");
+-
+- if (len > IW_CUSTOM_MAX) {
+- len = sprintf(buf, "ASSOCRESPIE=");
+- for (i = 0; i < ifsta->assocresp_ies_len; i++) {
+- len += sprintf(buf + len, "%02x",
+- ifsta->assocresp_ies[i]);
+- }
+- }
+-
+- memset(&wrqu, 0, sizeof(wrqu));
+- wrqu.data.length = len;
+- wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
+-
+- kfree(buf);
+-}
+-
+-
+-static void ieee80211_set_associated(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta,
+- bool assoc)
+-{
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- struct ieee80211_local *local = sdata->local;
+- union iwreq_data wrqu;
+- u32 changed = BSS_CHANGED_ASSOC;
+-
+- if (assoc) {
+- struct ieee80211_sta_bss *bss;
+-
+- ifsta->flags |= IEEE80211_STA_ASSOCIATED;
+-
+- if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
+- return;
+-
+- bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
+- local->hw.conf.channel,
+- ifsta->ssid, ifsta->ssid_len);
+- if (bss) {
+- changed |= ieee80211_handle_bss_capability(sdata, bss);
+- ieee80211_rx_bss_put(dev, bss);
+- }
+-
+- netif_carrier_on(dev);
+- ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET;
+- memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN);
+- memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN);
+- ieee80211_sta_send_associnfo(dev, ifsta);
+- } else {
+- ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
+-
+- netif_carrier_off(dev);
+- ieee80211_reset_erp_info(dev);
+- memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+- }
+- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+- wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
+- ifsta->last_probe = jiffies;
+- ieee80211_led_assoc(local, assoc);
+-
+- ieee80211_bss_info_change_notify(sdata, changed);
+-}
+-
+-static void ieee80211_set_disassoc(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta, int deauth)
+-{
+- if (deauth)
+- ifsta->auth_tries = 0;
+- ifsta->assoc_tries = 0;
+- ieee80211_set_associated(dev, ifsta, 0);
+-}
+-
+-static void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb,
+- int encrypt)
+-{
+- struct ieee80211_sub_if_data *sdata;
+- struct ieee80211_tx_packet_data *pkt_data;
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- skb->dev = sdata->local->mdev;
+- skb_set_mac_header(skb, 0);
+- skb_set_network_header(skb, 0);
+- skb_set_transport_header(skb, 0);
+-
+- pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
+- memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
+- pkt_data->ifindex = sdata->dev->ifindex;
+- if (!encrypt)
+- pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT;
+-
+- dev_queue_xmit(skb);
+-}
+-
+-
+-static void ieee80211_send_auth(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta,
+- int transaction, u8 *extra, size_t extra_len,
+- int encrypt)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct sk_buff *skb;
+- struct ieee80211_mgmt *mgmt;
+-
+- skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+- sizeof(*mgmt) + 6 + extra_len);
+- if (!skb) {
+- printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
+- "frame\n", dev->name);
+- return;
+- }
+- skb_reserve(skb, local->hw.extra_tx_headroom);
+-
+- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6);
+- memset(mgmt, 0, 24 + 6);
+- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+- IEEE80211_STYPE_AUTH);
+- if (encrypt)
+- mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+- memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
+- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+- memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+- mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg);
+- mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);
+- ifsta->auth_transaction = transaction + 1;
+- mgmt->u.auth.status_code = cpu_to_le16(0);
+- if (extra)
+- memcpy(skb_put(skb, extra_len), extra, extra_len);
+-
+- ieee80211_sta_tx(dev, skb, encrypt);
+-}
+-
+-
+-static void ieee80211_authenticate(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta)
+-{
+- DECLARE_MAC_BUF(mac);
+-
+- ifsta->auth_tries++;
+- if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) {
+- printk(KERN_DEBUG "%s: authentication with AP %s"
+- " timed out\n",
+- dev->name, print_mac(mac, ifsta->bssid));
+- ifsta->state = IEEE80211_DISABLED;
+- return;
+- }
+-
+- ifsta->state = IEEE80211_AUTHENTICATE;
+- printk(KERN_DEBUG "%s: authenticate with AP %s\n",
+- dev->name, print_mac(mac, ifsta->bssid));
+-
+- ieee80211_send_auth(dev, ifsta, 1, NULL, 0, 0);
+-
+- mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
+-}
+-
+-
+-static void ieee80211_send_assoc(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_hw_mode *mode;
+- struct sk_buff *skb;
+- struct ieee80211_mgmt *mgmt;
+- u8 *pos, *ies;
+- int i, len;
+- u16 capab;
+- struct ieee80211_sta_bss *bss;
+- int wmm = 0;
+-
+- skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+- sizeof(*mgmt) + 200 + ifsta->extra_ie_len +
+- ifsta->ssid_len);
+- if (!skb) {
+- printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
+- "frame\n", dev->name);
+- return;
+- }
+- skb_reserve(skb, local->hw.extra_tx_headroom);
+-
+- mode = local->oper_hw_mode;
+- capab = ifsta->capab;
+- if (mode->mode == MODE_IEEE80211G) {
+- capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME |
+- WLAN_CAPABILITY_SHORT_PREAMBLE;
+- }
+- bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel,
+- ifsta->ssid, ifsta->ssid_len);
+- if (bss) {
+- if (bss->capability & WLAN_CAPABILITY_PRIVACY)
+- capab |= WLAN_CAPABILITY_PRIVACY;
+- if (bss->wmm_ie) {
+- wmm = 1;
+- }
+- ieee80211_rx_bss_put(dev, bss);
+- }
+-
+- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
+- memset(mgmt, 0, 24);
+- memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
+- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+- memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+-
+- if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) {
+- skb_put(skb, 10);
+- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+- IEEE80211_STYPE_REASSOC_REQ);
+- mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);
+- mgmt->u.reassoc_req.listen_interval = cpu_to_le16(1);
+- memcpy(mgmt->u.reassoc_req.current_ap, ifsta->prev_bssid,
+- ETH_ALEN);
+- } else {
+- skb_put(skb, 4);
+- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+- IEEE80211_STYPE_ASSOC_REQ);
+- mgmt->u.assoc_req.capab_info = cpu_to_le16(capab);
+- mgmt->u.assoc_req.listen_interval = cpu_to_le16(1);
+- }
+-
+- /* SSID */
+- ies = pos = skb_put(skb, 2 + ifsta->ssid_len);
+- *pos++ = WLAN_EID_SSID;
+- *pos++ = ifsta->ssid_len;
+- memcpy(pos, ifsta->ssid, ifsta->ssid_len);
+-
+- len = mode->num_rates;
+- if (len > 8)
+- len = 8;
+- pos = skb_put(skb, len + 2);
+- *pos++ = WLAN_EID_SUPP_RATES;
+- *pos++ = len;
+- for (i = 0; i < len; i++) {
+- int rate = mode->rates[i].rate;
+- *pos++ = (u8) (rate / 5);
+- }
+-
+- if (mode->num_rates > len) {
+- pos = skb_put(skb, mode->num_rates - len + 2);
+- *pos++ = WLAN_EID_EXT_SUPP_RATES;
+- *pos++ = mode->num_rates - len;
+- for (i = len; i < mode->num_rates; i++) {
+- int rate = mode->rates[i].rate;
+- *pos++ = (u8) (rate / 5);
+- }
+- }
+-
+- if (ifsta->extra_ie) {
+- pos = skb_put(skb, ifsta->extra_ie_len);
+- memcpy(pos, ifsta->extra_ie, ifsta->extra_ie_len);
+- }
+-
+- if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
+- pos = skb_put(skb, 9);
+- *pos++ = WLAN_EID_VENDOR_SPECIFIC;
+- *pos++ = 7; /* len */
+- *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
+- *pos++ = 0x50;
+- *pos++ = 0xf2;
+- *pos++ = 2; /* WME */
+- *pos++ = 0; /* WME info */
+- *pos++ = 1; /* WME ver */
+- *pos++ = 0;
+- }
+- /* wmm support is a must to HT */
+- if (wmm && mode->ht_info.ht_supported) {
+- __le16 tmp = cpu_to_le16(mode->ht_info.cap);
+- pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2);
+- *pos++ = WLAN_EID_HT_CAPABILITY;
+- *pos++ = sizeof(struct ieee80211_ht_cap);
+- memset(pos, 0, sizeof(struct ieee80211_ht_cap));
+- memcpy(pos, &tmp, sizeof(u16));
+- pos += sizeof(u16);
+- *pos++ = (mode->ht_info.ampdu_factor |
+- (mode->ht_info.ampdu_density << 2));
+- memcpy(pos, mode->ht_info.supp_mcs_set, 16);
+- }
+-
+- kfree(ifsta->assocreq_ies);
+- ifsta->assocreq_ies_len = (skb->data + skb->len) - ies;
+- ifsta->assocreq_ies = kmalloc(ifsta->assocreq_ies_len, GFP_KERNEL);
+- if (ifsta->assocreq_ies)
+- memcpy(ifsta->assocreq_ies, ies, ifsta->assocreq_ies_len);
+-
+- ieee80211_sta_tx(dev, skb, 0);
+-}
+-
+-
+-static void ieee80211_send_deauth(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta, u16 reason)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct sk_buff *skb;
+- struct ieee80211_mgmt *mgmt;
+-
+- skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
+- if (!skb) {
+- printk(KERN_DEBUG "%s: failed to allocate buffer for deauth "
+- "frame\n", dev->name);
+- return;
+- }
+- skb_reserve(skb, local->hw.extra_tx_headroom);
+-
+- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
+- memset(mgmt, 0, 24);
+- memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
+- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+- memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+- IEEE80211_STYPE_DEAUTH);
+- skb_put(skb, 2);
+- mgmt->u.deauth.reason_code = cpu_to_le16(reason);
+-
+- ieee80211_sta_tx(dev, skb, 0);
+-}
+-
+-
+-static void ieee80211_send_disassoc(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta, u16 reason)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct sk_buff *skb;
+- struct ieee80211_mgmt *mgmt;
+-
+- skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
+- if (!skb) {
+- printk(KERN_DEBUG "%s: failed to allocate buffer for disassoc "
+- "frame\n", dev->name);
+- return;
+- }
+- skb_reserve(skb, local->hw.extra_tx_headroom);
+-
+- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
+- memset(mgmt, 0, 24);
+- memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
+- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+- memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+- IEEE80211_STYPE_DISASSOC);
+- skb_put(skb, 2);
+- mgmt->u.disassoc.reason_code = cpu_to_le16(reason);
+-
+- ieee80211_sta_tx(dev, skb, 0);
+-}
+-
+-
+-static int ieee80211_privacy_mismatch(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_sta_bss *bss;
+- int bss_privacy;
+- int wep_privacy;
+- int privacy_invoked;
+-
+- if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL))
+- return 0;
+-
+- bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel,
+- ifsta->ssid, ifsta->ssid_len);
+- if (!bss)
+- return 0;
+-
+- bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY);
+- wep_privacy = !!ieee80211_sta_wep_configured(dev);
+- privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED);
+-
+- ieee80211_rx_bss_put(dev, bss);
+-
+- if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked))
+- return 0;
+-
+- return 1;
+-}
+-
+-
+-static void ieee80211_associate(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta)
+-{
+- DECLARE_MAC_BUF(mac);
+-
+- ifsta->assoc_tries++;
+- if (ifsta->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) {
+- printk(KERN_DEBUG "%s: association with AP %s"
+- " timed out\n",
+- dev->name, print_mac(mac, ifsta->bssid));
+- ifsta->state = IEEE80211_DISABLED;
+- return;
+- }
+-
+- ifsta->state = IEEE80211_ASSOCIATE;
+- printk(KERN_DEBUG "%s: associate with AP %s\n",
+- dev->name, print_mac(mac, ifsta->bssid));
+- if (ieee80211_privacy_mismatch(dev, ifsta)) {
+- printk(KERN_DEBUG "%s: mismatch in privacy configuration and "
+- "mixed-cell disabled - abort association\n", dev->name);
+- ifsta->state = IEEE80211_DISABLED;
+- return;
+- }
+-
+- ieee80211_send_assoc(dev, ifsta);
+-
+- mod_timer(&ifsta->timer, jiffies + IEEE80211_ASSOC_TIMEOUT);
+-}
+-
+-
+-static void ieee80211_associated(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct sta_info *sta;
+- int disassoc;
+- DECLARE_MAC_BUF(mac);
+-
+- /* TODO: start monitoring current AP signal quality and number of
+- * missed beacons. Scan other channels every now and then and search
+- * for better APs. */
+- /* TODO: remove expired BSSes */
+-
+- ifsta->state = IEEE80211_ASSOCIATED;
+-
+- sta = sta_info_get(local, ifsta->bssid);
+- if (!sta) {
+- printk(KERN_DEBUG "%s: No STA entry for own AP %s\n",
+- dev->name, print_mac(mac, ifsta->bssid));
+- disassoc = 1;
+- } else {
+- disassoc = 0;
+- if (time_after(jiffies,
+- sta->last_rx + IEEE80211_MONITORING_INTERVAL)) {
+- if (ifsta->flags & IEEE80211_STA_PROBEREQ_POLL) {
+- printk(KERN_DEBUG "%s: No ProbeResp from "
+- "current AP %s - assume out of "
+- "range\n",
+- dev->name, print_mac(mac, ifsta->bssid));
+- disassoc = 1;
+- sta_info_free(sta);
+- } else
+- ieee80211_send_probe_req(dev, ifsta->bssid,
+- local->scan_ssid,
+- local->scan_ssid_len);
+- ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL;
+- } else {
+- ifsta->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
+- if (time_after(jiffies, ifsta->last_probe +
+- IEEE80211_PROBE_INTERVAL)) {
+- ifsta->last_probe = jiffies;
+- ieee80211_send_probe_req(dev, ifsta->bssid,
+- ifsta->ssid,
+- ifsta->ssid_len);
+- }
+- }
+- sta_info_put(sta);
+- }
+- if (disassoc) {
+- ifsta->state = IEEE80211_DISABLED;
+- ieee80211_set_associated(dev, ifsta, 0);
+- } else {
+- mod_timer(&ifsta->timer, jiffies +
+- IEEE80211_MONITORING_INTERVAL);
+- }
+-}
+-
+-
+-static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
+- u8 *ssid, size_t ssid_len)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_hw_mode *mode;
+- struct sk_buff *skb;
+- struct ieee80211_mgmt *mgmt;
+- u8 *pos, *supp_rates, *esupp_rates = NULL;
+- int i;
+-
+- skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200);
+- if (!skb) {
+- printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
+- "request\n", dev->name);
+- return;
+- }
+- skb_reserve(skb, local->hw.extra_tx_headroom);
+-
+- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
+- memset(mgmt, 0, 24);
+- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+- IEEE80211_STYPE_PROBE_REQ);
+- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+- if (dst) {
+- memcpy(mgmt->da, dst, ETH_ALEN);
+- memcpy(mgmt->bssid, dst, ETH_ALEN);
+- } else {
+- memset(mgmt->da, 0xff, ETH_ALEN);
+- memset(mgmt->bssid, 0xff, ETH_ALEN);
+- }
+- pos = skb_put(skb, 2 + ssid_len);
+- *pos++ = WLAN_EID_SSID;
+- *pos++ = ssid_len;
+- memcpy(pos, ssid, ssid_len);
+-
+- supp_rates = skb_put(skb, 2);
+- supp_rates[0] = WLAN_EID_SUPP_RATES;
+- supp_rates[1] = 0;
+- mode = local->oper_hw_mode;
+- for (i = 0; i < mode->num_rates; i++) {
+- struct ieee80211_rate *rate = &mode->rates[i];
+- if (!(rate->flags & IEEE80211_RATE_SUPPORTED))
+- continue;
+- if (esupp_rates) {
+- pos = skb_put(skb, 1);
+- esupp_rates[1]++;
+- } else if (supp_rates[1] == 8) {
+- esupp_rates = skb_put(skb, 3);
+- esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES;
+- esupp_rates[1] = 1;
+- pos = &esupp_rates[2];
+- } else {
+- pos = skb_put(skb, 1);
+- supp_rates[1]++;
+- }
+- *pos = rate->rate / 5;
+- }
+-
+- ieee80211_sta_tx(dev, skb, 0);
+-}
+-
+-
+-static int ieee80211_sta_wep_configured(struct net_device *dev)
+-{
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- if (!sdata || !sdata->default_key ||
+- sdata->default_key->conf.alg != ALG_WEP)
+- return 0;
+- return 1;
+-}
+-
+-
+-static void ieee80211_auth_completed(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta)
+-{
+- printk(KERN_DEBUG "%s: authenticated\n", dev->name);
+- ifsta->flags |= IEEE80211_STA_AUTHENTICATED;
+- ieee80211_associate(dev, ifsta);
+-}
+-
+-
+-static void ieee80211_auth_challenge(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta,
+- struct ieee80211_mgmt *mgmt,
+- size_t len)
+-{
+- u8 *pos;
+- struct ieee802_11_elems elems;
+-
+- printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name);
+- pos = mgmt->u.auth.variable;
+- ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
+- if (!elems.challenge) {
+- printk(KERN_DEBUG "%s: no challenge IE in shared key auth "
+- "frame\n", dev->name);
+- return;
+- }
+- ieee80211_send_auth(dev, ifsta, 3, elems.challenge - 2,
+- elems.challenge_len + 2, 1);
+-}
+-
+-static void ieee80211_send_addba_resp(struct net_device *dev, u8 *da, u16 tid,
+- u8 dialog_token, u16 status, u16 policy,
+- u16 buf_size, u16 timeout)
+-{
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct sk_buff *skb;
+- struct ieee80211_mgmt *mgmt;
+- u16 capab;
+-
+- skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom + 1 +
+- sizeof(mgmt->u.action.u.addba_resp));
+- if (!skb) {
+- printk(KERN_DEBUG "%s: failed to allocate buffer "
+- "for addba resp frame\n", dev->name);
+- return;
+- }
+-
+- skb_reserve(skb, local->hw.extra_tx_headroom);
+- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
+- memset(mgmt, 0, 24);
+- memcpy(mgmt->da, da, ETH_ALEN);
+- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+- if (sdata->vif.type == IEEE80211_IF_TYPE_AP)
+- memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN);
+- else
+- memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+- IEEE80211_STYPE_ACTION);
+-
+- skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp));
+- mgmt->u.action.category = WLAN_CATEGORY_BACK;
+- mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP;
+- mgmt->u.action.u.addba_resp.dialog_token = dialog_token;
+-
+- capab = (u16)(policy << 1); /* bit 1 aggregation policy */
+- capab |= (u16)(tid << 2); /* bit 5:2 TID number */
+- capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */
+-
+- mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab);
+- mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout);
+- mgmt->u.action.u.addba_resp.status = cpu_to_le16(status);
+-
+- ieee80211_sta_tx(dev, skb, 0);
+-
+- return;
+-}
+-
+-static void ieee80211_sta_process_addba_request(struct net_device *dev,
+- struct ieee80211_mgmt *mgmt,
+- size_t len)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_hw *hw = &local->hw;
+- struct ieee80211_conf *conf = &hw->conf;
+- struct sta_info *sta;
+- struct tid_ampdu_rx *tid_agg_rx;
+- u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status;
+- u8 dialog_token;
+- int ret = -EOPNOTSUPP;
+- DECLARE_MAC_BUF(mac);
+-
+- sta = sta_info_get(local, mgmt->sa);
+- if (!sta)
+- return;
+-
+- /* extract session parameters from addba request frame */
+- dialog_token = mgmt->u.action.u.addba_req.dialog_token;
+- timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout);
+- start_seq_num =
+- le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4;
+-
+- capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
+- ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1;
+- tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
+- buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
+-
+- status = WLAN_STATUS_REQUEST_DECLINED;
+-
+- /* sanity check for incoming parameters:
+- * check if configuration can support the BA policy
+- * and if buffer size does not exceeds max value */
+- if (((ba_policy != 1)
+- && (!(conf->ht_conf.cap & IEEE80211_HT_CAP_DELAY_BA)))
+- || (buf_size > IEEE80211_MAX_AMPDU_BUF)) {
+- status = WLAN_STATUS_INVALID_QOS_PARAM;
+-#ifdef CONFIG_MAC80211_HT_DEBUG
+- if (net_ratelimit())
+- printk(KERN_DEBUG "Block Ack Req with bad params from "
+- "%s on tid %u. policy %d, buffer size %d\n",
+- print_mac(mac, mgmt->sa), tid, ba_policy,
+- buf_size);
+-#endif /* CONFIG_MAC80211_HT_DEBUG */
+- goto end_no_lock;
+- }
+- /* determine default buffer size */
+- if (buf_size == 0) {
+- struct ieee80211_hw_mode *mode = conf->mode;
+- buf_size = IEEE80211_MIN_AMPDU_BUF;
+- buf_size = buf_size << mode->ht_info.ampdu_factor;
+- }
+-
+- tid_agg_rx = &sta->ampdu_mlme.tid_rx[tid];
+-
+- /* examine state machine */
+- spin_lock_bh(&sta->ampdu_mlme.ampdu_rx);
+-
+- if (tid_agg_rx->state != HT_AGG_STATE_IDLE) {
+-#ifdef CONFIG_MAC80211_HT_DEBUG
+- if (net_ratelimit())
+- printk(KERN_DEBUG "unexpected Block Ack Req from "
+- "%s on tid %u\n",
+- print_mac(mac, mgmt->sa), tid);
+-#endif /* CONFIG_MAC80211_HT_DEBUG */
+- goto end;
+- }
+-
+- /* prepare reordering buffer */
+- tid_agg_rx->reorder_buf =
+- kmalloc(buf_size * sizeof(struct sk_buf *), GFP_ATOMIC);
+- if (!tid_agg_rx->reorder_buf) {
+- if (net_ratelimit())
+- printk(KERN_ERR "can not allocate reordering buffer "
+- "to tid %d\n", tid);
+- goto end;
+- }
+- memset(tid_agg_rx->reorder_buf, 0,
+- buf_size * sizeof(struct sk_buf *));
+-
+- if (local->ops->ampdu_action)
+- ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_START,
+- sta->addr, tid, start_seq_num);
+-#ifdef CONFIG_MAC80211_HT_DEBUG
+- printk(KERN_DEBUG "Rx A-MPDU on tid %d result %d", tid, ret);
+-#endif /* CONFIG_MAC80211_HT_DEBUG */
+-
+- if (ret) {
+- kfree(tid_agg_rx->reorder_buf);
+- goto end;
+- }
+-
+- /* change state and send addba resp */
+- tid_agg_rx->state = HT_AGG_STATE_OPERATIONAL;
+- tid_agg_rx->dialog_token = dialog_token;
+- tid_agg_rx->ssn = start_seq_num;
+- tid_agg_rx->head_seq_num = start_seq_num;
+- tid_agg_rx->buf_size = buf_size;
+- tid_agg_rx->timeout = timeout;
+- tid_agg_rx->stored_mpdu_num = 0;
+- status = WLAN_STATUS_SUCCESS;
+-end:
+- spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
+-
+-end_no_lock:
+- ieee80211_send_addba_resp(sta->dev, sta->addr, tid, dialog_token,
+- status, 1, buf_size, timeout);
+- sta_info_put(sta);
+-}
+-
+-static void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid,
+- u16 initiator, u16 reason_code)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+- struct sk_buff *skb;
+- struct ieee80211_mgmt *mgmt;
+- u16 params;
+-
+- skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom + 1 +
+- sizeof(mgmt->u.action.u.delba));
+-
+- if (!skb) {
+- printk(KERN_ERR "%s: failed to allocate buffer "
+- "for delba frame\n", dev->name);
+- return;
+- }
+-
+- skb_reserve(skb, local->hw.extra_tx_headroom);
+- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
+- memset(mgmt, 0, 24);
+- memcpy(mgmt->da, da, ETH_ALEN);
+- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+- if (sdata->vif.type == IEEE80211_IF_TYPE_AP)
+- memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN);
+- else
+- memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+- IEEE80211_STYPE_ACTION);
+-
+- skb_put(skb, 1 + sizeof(mgmt->u.action.u.delba));
+-
+- mgmt->u.action.category = WLAN_CATEGORY_BACK;
+- mgmt->u.action.u.delba.action_code = WLAN_ACTION_DELBA;
+- params = (u16)(initiator << 11); /* bit 11 initiator */
+- params |= (u16)(tid << 12); /* bit 15:12 TID number */
+-
+- mgmt->u.action.u.delba.params = cpu_to_le16(params);
+- mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code);
+-
+- ieee80211_sta_tx(dev, skb, 0);
+-}
+-
+-void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid,
+- u16 initiator, u16 reason)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_hw *hw = &local->hw;
+- struct sta_info *sta;
+- int ret, i;
+-
+- sta = sta_info_get(local, ra);
+- if (!sta)
+- return;
+-
+- /* check if TID is in operational state */
+- spin_lock_bh(&sta->ampdu_mlme.ampdu_rx);
+- if (sta->ampdu_mlme.tid_rx[tid].state
+- != HT_AGG_STATE_OPERATIONAL) {
+- spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
+- sta_info_put(sta);
+- return;
+- }
+- sta->ampdu_mlme.tid_rx[tid].state =
+- HT_AGG_STATE_REQ_STOP_BA_MSK |
+- (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
+- spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
+-
+- /* stop HW Rx aggregation. ampdu_action existence
+- * already verified in session init so we add the BUG_ON */
+- BUG_ON(!local->ops->ampdu_action);
+-
+- ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP,
+- ra, tid, EINVAL);
+- if (ret)
+- printk(KERN_DEBUG "HW problem - can not stop rx "
+- "aggergation for tid %d\n", tid);
+-
+- /* shutdown timer has not expired */
+- if (initiator != WLAN_BACK_TIMER)
+- del_timer_sync(&sta->ampdu_mlme.tid_rx[tid].
+- session_timer);
+-
+- /* check if this is a self generated aggregation halt */
+- if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER)
+- ieee80211_send_delba(dev, ra, tid, 0, reason);
+-
+- /* free the reordering buffer */
+- for (i = 0; i < sta->ampdu_mlme.tid_rx[tid].buf_size; i++) {
+- if (sta->ampdu_mlme.tid_rx[tid].reorder_buf[i]) {
+- /* release the reordered frames */
+- dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid].reorder_buf[i]);
+- sta->ampdu_mlme.tid_rx[tid].stored_mpdu_num--;
+- sta->ampdu_mlme.tid_rx[tid].reorder_buf[i] = NULL;
+- }
+- }
+- kfree(sta->ampdu_mlme.tid_rx[tid].reorder_buf);
+-
+- sta->ampdu_mlme.tid_rx[tid].state = HT_AGG_STATE_IDLE;
+- sta_info_put(sta);
+-}
+-
+-static void ieee80211_sta_process_delba(struct net_device *dev,
+- struct ieee80211_mgmt *mgmt, size_t len)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct sta_info *sta;
+- u16 tid, params;
+- u16 initiator;
+- DECLARE_MAC_BUF(mac);
+-
+- sta = sta_info_get(local, mgmt->sa);
+- if (!sta)
+- return;
+-
+- params = le16_to_cpu(mgmt->u.action.u.delba.params);
+- tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12;
+- initiator = (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) >> 11;
+-
+-#ifdef CONFIG_MAC80211_HT_DEBUG
+- if (net_ratelimit())
+- printk(KERN_DEBUG "delba from %s on tid %d reason code %d\n",
+- print_mac(mac, mgmt->sa), tid,
+- mgmt->u.action.u.delba.reason_code);
+-#endif /* CONFIG_MAC80211_HT_DEBUG */
+-
+- if (initiator == WLAN_BACK_INITIATOR)
+- ieee80211_sta_stop_rx_ba_session(dev, sta->addr, tid,
+- WLAN_BACK_INITIATOR, 0);
+- sta_info_put(sta);
+-}
+-
+-/*
+- * After receiving Block Ack Request (BAR) we activated a
+- * timer after each frame arrives from the originator.
+- * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed.
+- */
+-void sta_rx_agg_session_timer_expired(unsigned long data)
+-{
+- /* not an elegant detour, but there is no choice as the timer passes
+- * only one argument, and verious sta_info are needed here, so init
+- * flow in sta_info_add gives the TID as data, while the timer_to_id
+- * array gives the sta through container_of */
+- u8 *ptid = (u8 *)data;
+- u8 *timer_to_id = ptid - *ptid;
+- struct sta_info *sta = container_of(timer_to_id, struct sta_info,
+- timer_to_tid[0]);
+-
+- printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid);
+- ieee80211_sta_stop_rx_ba_session(sta->dev, sta->addr, (u16)*ptid,
+- WLAN_BACK_TIMER,
+- WLAN_REASON_QSTA_TIMEOUT);
+-}
+-
+-
+-static void ieee80211_rx_mgmt_auth(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta,
+- struct ieee80211_mgmt *mgmt,
+- size_t len)
+-{
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- u16 auth_alg, auth_transaction, status_code;
+- DECLARE_MAC_BUF(mac);
+-
+- if (ifsta->state != IEEE80211_AUTHENTICATE &&
+- sdata->vif.type != IEEE80211_IF_TYPE_IBSS) {
+- printk(KERN_DEBUG "%s: authentication frame received from "
+- "%s, but not in authenticate state - ignored\n",
+- dev->name, print_mac(mac, mgmt->sa));
+- return;
+- }
+-
+- if (len < 24 + 6) {
+- printk(KERN_DEBUG "%s: too short (%zd) authentication frame "
+- "received from %s - ignored\n",
+- dev->name, len, print_mac(mac, mgmt->sa));
+- return;
+- }
+-
+- if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
+- memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
+- printk(KERN_DEBUG "%s: authentication frame received from "
+- "unknown AP (SA=%s BSSID=%s) - "
+- "ignored\n", dev->name, print_mac(mac, mgmt->sa),
+- print_mac(mac, mgmt->bssid));
+- return;
+- }
+-
+- if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
+- memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) {
+- printk(KERN_DEBUG "%s: authentication frame received from "
+- "unknown BSSID (SA=%s BSSID=%s) - "
+- "ignored\n", dev->name, print_mac(mac, mgmt->sa),
+- print_mac(mac, mgmt->bssid));
+- return;
+- }
+-
+- auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
+- auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
+- status_code = le16_to_cpu(mgmt->u.auth.status_code);
+-
+- printk(KERN_DEBUG "%s: RX authentication from %s (alg=%d "
+- "transaction=%d status=%d)\n",
+- dev->name, print_mac(mac, mgmt->sa), auth_alg,
+- auth_transaction, status_code);
+-
+- if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
+- /* IEEE 802.11 standard does not require authentication in IBSS
+- * networks and most implementations do not seem to use it.
+- * However, try to reply to authentication attempts if someone
+- * has actually implemented this.
+- * TODO: Could implement shared key authentication. */
+- if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) {
+- printk(KERN_DEBUG "%s: unexpected IBSS authentication "
+- "frame (alg=%d transaction=%d)\n",
+- dev->name, auth_alg, auth_transaction);
+- return;
+- }
+- ieee80211_send_auth(dev, ifsta, 2, NULL, 0, 0);
+- }
+-
+- if (auth_alg != ifsta->auth_alg ||
+- auth_transaction != ifsta->auth_transaction) {
+- printk(KERN_DEBUG "%s: unexpected authentication frame "
+- "(alg=%d transaction=%d)\n",
+- dev->name, auth_alg, auth_transaction);
+- return;
+- }
+-
+- if (status_code != WLAN_STATUS_SUCCESS) {
+- printk(KERN_DEBUG "%s: AP denied authentication (auth_alg=%d "
+- "code=%d)\n", dev->name, ifsta->auth_alg, status_code);
+- if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
+- u8 algs[3];
+- const int num_algs = ARRAY_SIZE(algs);
+- int i, pos;
+- algs[0] = algs[1] = algs[2] = 0xff;
+- if (ifsta->auth_algs & IEEE80211_AUTH_ALG_OPEN)
+- algs[0] = WLAN_AUTH_OPEN;
+- if (ifsta->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
+- algs[1] = WLAN_AUTH_SHARED_KEY;
+- if (ifsta->auth_algs & IEEE80211_AUTH_ALG_LEAP)
+- algs[2] = WLAN_AUTH_LEAP;
+- if (ifsta->auth_alg == WLAN_AUTH_OPEN)
+- pos = 0;
+- else if (ifsta->auth_alg == WLAN_AUTH_SHARED_KEY)
+- pos = 1;
+- else
+- pos = 2;
+- for (i = 0; i < num_algs; i++) {
+- pos++;
+- if (pos >= num_algs)
+- pos = 0;
+- if (algs[pos] == ifsta->auth_alg ||
+- algs[pos] == 0xff)
+- continue;
+- if (algs[pos] == WLAN_AUTH_SHARED_KEY &&
+- !ieee80211_sta_wep_configured(dev))
+- continue;
+- ifsta->auth_alg = algs[pos];
+- printk(KERN_DEBUG "%s: set auth_alg=%d for "
+- "next try\n",
+- dev->name, ifsta->auth_alg);
+- break;
+- }
+- }
+- return;
+- }
+-
+- switch (ifsta->auth_alg) {
+- case WLAN_AUTH_OPEN:
+- case WLAN_AUTH_LEAP:
+- ieee80211_auth_completed(dev, ifsta);
+- break;
+- case WLAN_AUTH_SHARED_KEY:
+- if (ifsta->auth_transaction == 4)
+- ieee80211_auth_completed(dev, ifsta);
+- else
+- ieee80211_auth_challenge(dev, ifsta, mgmt, len);
+- break;
+- }
+-}
+-
+-
+-static void ieee80211_rx_mgmt_deauth(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta,
+- struct ieee80211_mgmt *mgmt,
+- size_t len)
+-{
+- u16 reason_code;
+- DECLARE_MAC_BUF(mac);
+-
+- if (len < 24 + 2) {
+- printk(KERN_DEBUG "%s: too short (%zd) deauthentication frame "
+- "received from %s - ignored\n",
+- dev->name, len, print_mac(mac, mgmt->sa));
+- return;
+- }
+-
+- if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
+- printk(KERN_DEBUG "%s: deauthentication frame received from "
+- "unknown AP (SA=%s BSSID=%s) - "
+- "ignored\n", dev->name, print_mac(mac, mgmt->sa),
+- print_mac(mac, mgmt->bssid));
+- return;
+- }
+-
+- reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
+-
+- printk(KERN_DEBUG "%s: RX deauthentication from %s"
+- " (reason=%d)\n",
+- dev->name, print_mac(mac, mgmt->sa), reason_code);
+-
+- if (ifsta->flags & IEEE80211_STA_AUTHENTICATED) {
+- printk(KERN_DEBUG "%s: deauthenticated\n", dev->name);
+- }
+-
+- if (ifsta->state == IEEE80211_AUTHENTICATE ||
+- ifsta->state == IEEE80211_ASSOCIATE ||
+- ifsta->state == IEEE80211_ASSOCIATED) {
+- ifsta->state = IEEE80211_AUTHENTICATE;
+- mod_timer(&ifsta->timer, jiffies +
+- IEEE80211_RETRY_AUTH_INTERVAL);
+- }
+-
+- ieee80211_set_disassoc(dev, ifsta, 1);
+- ifsta->flags &= ~IEEE80211_STA_AUTHENTICATED;
+-}
+-
+-
+-static void ieee80211_rx_mgmt_disassoc(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta,
+- struct ieee80211_mgmt *mgmt,
+- size_t len)
+-{
+- u16 reason_code;
+- DECLARE_MAC_BUF(mac);
+-
+- if (len < 24 + 2) {
+- printk(KERN_DEBUG "%s: too short (%zd) disassociation frame "
+- "received from %s - ignored\n",
+- dev->name, len, print_mac(mac, mgmt->sa));
+- return;
+- }
+-
+- if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
+- printk(KERN_DEBUG "%s: disassociation frame received from "
+- "unknown AP (SA=%s BSSID=%s) - "
+- "ignored\n", dev->name, print_mac(mac, mgmt->sa),
+- print_mac(mac, mgmt->bssid));
+- return;
+- }
+-
+- reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
+-
+- printk(KERN_DEBUG "%s: RX disassociation from %s"
+- " (reason=%d)\n",
+- dev->name, print_mac(mac, mgmt->sa), reason_code);
+-
+- if (ifsta->flags & IEEE80211_STA_ASSOCIATED)
+- printk(KERN_DEBUG "%s: disassociated\n", dev->name);
+-
+- if (ifsta->state == IEEE80211_ASSOCIATED) {
+- ifsta->state = IEEE80211_ASSOCIATE;
+- mod_timer(&ifsta->timer, jiffies +
+- IEEE80211_RETRY_AUTH_INTERVAL);
+- }
+-
+- ieee80211_set_disassoc(dev, ifsta, 0);
+-}
+-
+-
+-static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
+- struct ieee80211_if_sta *ifsta,
+- struct ieee80211_mgmt *mgmt,
+- size_t len,
+- int reassoc)
+-{
+- struct ieee80211_local *local = sdata->local;
+- struct net_device *dev = sdata->dev;
+- struct ieee80211_hw_mode *mode;
+- struct sta_info *sta;
+- u32 rates;
+- u16 capab_info, status_code, aid;
+- struct ieee802_11_elems elems;
+- struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf;
+- u8 *pos;
+- int i, j;
+- DECLARE_MAC_BUF(mac);
+-
+- /* AssocResp and ReassocResp have identical structure, so process both
+- * of them in this function. */
+-
+- if (ifsta->state != IEEE80211_ASSOCIATE) {
+- printk(KERN_DEBUG "%s: association frame received from "
+- "%s, but not in associate state - ignored\n",
+- dev->name, print_mac(mac, mgmt->sa));
+- return;
+- }
+-
+- if (len < 24 + 6) {
+- printk(KERN_DEBUG "%s: too short (%zd) association frame "
+- "received from %s - ignored\n",
+- dev->name, len, print_mac(mac, mgmt->sa));
+- return;
+- }
+-
+- if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
+- printk(KERN_DEBUG "%s: association frame received from "
+- "unknown AP (SA=%s BSSID=%s) - "
+- "ignored\n", dev->name, print_mac(mac, mgmt->sa),
+- print_mac(mac, mgmt->bssid));
+- return;
+- }
+-
+- capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
+- status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
+- aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
+-
+- printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x "
+- "status=%d aid=%d)\n",
+- dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa),
+- capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
+-
+- if (status_code != WLAN_STATUS_SUCCESS) {
+- printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
+- dev->name, status_code);
+- /* if this was a reassociation, ensure we try a "full"
+- * association next time. This works around some broken APs
+- * which do not correctly reject reassociation requests. */
+- ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
+- return;
+- }
+-
+- if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
+- printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not "
+- "set\n", dev->name, aid);
+- aid &= ~(BIT(15) | BIT(14));
+-
+- pos = mgmt->u.assoc_resp.variable;
+- ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
+-
+- if (!elems.supp_rates) {
+- printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
+- dev->name);
+- return;
+- }
+-
+- printk(KERN_DEBUG "%s: associated\n", dev->name);
+- ifsta->aid = aid;
+- ifsta->ap_capab = capab_info;
+-
+- kfree(ifsta->assocresp_ies);
+- ifsta->assocresp_ies_len = len - (pos - (u8 *) mgmt);
+- ifsta->assocresp_ies = kmalloc(ifsta->assocresp_ies_len, GFP_KERNEL);
+- if (ifsta->assocresp_ies)
+- memcpy(ifsta->assocresp_ies, pos, ifsta->assocresp_ies_len);
+-
+- /* set AID, ieee80211_set_associated() will tell the driver */
+- bss_conf->aid = aid;
+- ieee80211_set_associated(dev, ifsta, 1);
+-
+- /* Add STA entry for the AP */
+- sta = sta_info_get(local, ifsta->bssid);
+- if (!sta) {
+- struct ieee80211_sta_bss *bss;
+- sta = sta_info_add(local, dev, ifsta->bssid, GFP_KERNEL);
+- if (!sta) {
+- printk(KERN_DEBUG "%s: failed to add STA entry for the"
+- " AP\n", dev->name);
+- return;
+- }
+- bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
+- local->hw.conf.channel,
+- ifsta->ssid, ifsta->ssid_len);
+- if (bss) {
+- sta->last_rssi = bss->rssi;
+- sta->last_signal = bss->signal;
+- sta->last_noise = bss->noise;
+- ieee80211_rx_bss_put(dev, bss);
+- }
+- }
+-
+- sta->dev = dev;
+- sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP;
+-
+- rates = 0;
+- mode = local->oper_hw_mode;
+- for (i = 0; i < elems.supp_rates_len; i++) {
+- int rate = (elems.supp_rates[i] & 0x7f) * 5;
+- for (j = 0; j < mode->num_rates; j++)
+- if (mode->rates[j].rate == rate)
+- rates |= BIT(j);
+- }
+- for (i = 0; i < elems.ext_supp_rates_len; i++) {
+- int rate = (elems.ext_supp_rates[i] & 0x7f) * 5;
+- for (j = 0; j < mode->num_rates; j++)
+- if (mode->rates[j].rate == rate)
+- rates |= BIT(j);
+- }
+- sta->supp_rates = rates;
+-
+- if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param &&
+- local->ops->conf_ht) {
+- struct ieee80211_ht_bss_info bss_info;
+-
+- ieee80211_ht_cap_ie_to_ht_info(
+- (struct ieee80211_ht_cap *)
+- elems.ht_cap_elem, &sta->ht_info);
+- ieee80211_ht_addt_info_ie_to_ht_bss_info(
+- (struct ieee80211_ht_addt_info *)
+- elems.ht_info_elem, &bss_info);
+- ieee80211_hw_config_ht(local, 1, &sta->ht_info, &bss_info);
+- }
+-
+- rate_control_rate_init(sta, local);
+-
+- if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
+- sta->flags |= WLAN_STA_WME;
+- ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
+- elems.wmm_param_len);
+- }
+-
+-
+- sta_info_put(sta);
+-
+- ieee80211_associated(dev, ifsta);
+-}
+-
+-
+-/* Caller must hold local->sta_bss_lock */
+-static void __ieee80211_rx_bss_hash_add(struct net_device *dev,
+- struct ieee80211_sta_bss *bss)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- bss->hnext = local->sta_bss_hash[STA_HASH(bss->bssid)];
+- local->sta_bss_hash[STA_HASH(bss->bssid)] = bss;
+-}
+-
+-
+-/* Caller must hold local->sta_bss_lock */
+-static void __ieee80211_rx_bss_hash_del(struct net_device *dev,
+- struct ieee80211_sta_bss *bss)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_sta_bss *b, *prev = NULL;
+- b = local->sta_bss_hash[STA_HASH(bss->bssid)];
+- while (b) {
+- if (b == bss) {
+- if (!prev)
+- local->sta_bss_hash[STA_HASH(bss->bssid)] =
+- bss->hnext;
+- else
+- prev->hnext = bss->hnext;
+- break;
+- }
+- prev = b;
+- b = b->hnext;
+- }
+-}
+-
+-
+-static struct ieee80211_sta_bss *
+-ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel,
+- u8 *ssid, u8 ssid_len)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_sta_bss *bss;
+-
+- bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
+- if (!bss)
+- return NULL;
+- atomic_inc(&bss->users);
+- atomic_inc(&bss->users);
+- memcpy(bss->bssid, bssid, ETH_ALEN);
+- bss->channel = channel;
+- if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) {
+- memcpy(bss->ssid, ssid, ssid_len);
+- bss->ssid_len = ssid_len;
+- }
+-
+- spin_lock_bh(&local->sta_bss_lock);
+- /* TODO: order by RSSI? */
+- list_add_tail(&bss->list, &local->sta_bss_list);
+- __ieee80211_rx_bss_hash_add(dev, bss);
+- spin_unlock_bh(&local->sta_bss_lock);
+- return bss;
+-}
+-
+-
+-static struct ieee80211_sta_bss *
+-ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel,
+- u8 *ssid, u8 ssid_len)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_sta_bss *bss;
+-
+- spin_lock_bh(&local->sta_bss_lock);
+- bss = local->sta_bss_hash[STA_HASH(bssid)];
+- while (bss) {
+- if (!memcmp(bss->bssid, bssid, ETH_ALEN) &&
+- bss->channel == channel &&
+- bss->ssid_len == ssid_len &&
+- (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) {
+- atomic_inc(&bss->users);
+- break;
+- }
+- bss = bss->hnext;
+- }
+- spin_unlock_bh(&local->sta_bss_lock);
+- return bss;
+-}
+-
+-
+-static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss)
+-{
+- kfree(bss->wpa_ie);
+- kfree(bss->rsn_ie);
+- kfree(bss->wmm_ie);
+- kfree(bss->ht_ie);
+- kfree(bss);
+-}
+-
+-
+-static void ieee80211_rx_bss_put(struct net_device *dev,
+- struct ieee80211_sta_bss *bss)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- if (!atomic_dec_and_test(&bss->users))
+- return;
+-
+- spin_lock_bh(&local->sta_bss_lock);
+- __ieee80211_rx_bss_hash_del(dev, bss);
+- list_del(&bss->list);
+- spin_unlock_bh(&local->sta_bss_lock);
+- ieee80211_rx_bss_free(bss);
+-}
+-
+-
+-void ieee80211_rx_bss_list_init(struct net_device *dev)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- spin_lock_init(&local->sta_bss_lock);
+- INIT_LIST_HEAD(&local->sta_bss_list);
+-}
+-
+-
+-void ieee80211_rx_bss_list_deinit(struct net_device *dev)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_sta_bss *bss, *tmp;
+-
+- list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list)
+- ieee80211_rx_bss_put(dev, bss);
+-}
+-
+-
+-static void ieee80211_rx_bss_info(struct net_device *dev,
+- struct ieee80211_mgmt *mgmt,
+- size_t len,
+- struct ieee80211_rx_status *rx_status,
+- int beacon)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee802_11_elems elems;
+- size_t baselen;
+- int channel, clen;
+- struct ieee80211_sta_bss *bss;
+- struct sta_info *sta;
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- u64 timestamp;
+- DECLARE_MAC_BUF(mac);
+- DECLARE_MAC_BUF(mac2);
+-
+- if (!beacon && memcmp(mgmt->da, dev->dev_addr, ETH_ALEN))
+- return; /* ignore ProbeResp to foreign address */
+-
+-#if 0
+- printk(KERN_DEBUG "%s: RX %s from %s to %s\n",
+- dev->name, beacon ? "Beacon" : "Probe Response",
+- print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da));
+-#endif
+-
+- baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
+- if (baselen > len)
+- return;
+-
+- timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);
+-
+- if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon &&
+- memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) {
+-#ifdef CONFIG_MAC80211_IBSS_DEBUG
+- static unsigned long last_tsf_debug = 0;
+- u64 tsf;
+- if (local->ops->get_tsf)
+- tsf = local->ops->get_tsf(local_to_hw(local));
+- else
+- tsf = -1LLU;
+- if (time_after(jiffies, last_tsf_debug + 5 * HZ)) {
+- printk(KERN_DEBUG "RX beacon SA=%s BSSID="
+- "%s TSF=0x%llx BCN=0x%llx diff=%lld "
+- "@%lu\n",
+- print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->bssid),
+- (unsigned long long)tsf,
+- (unsigned long long)timestamp,
+- (unsigned long long)(tsf - timestamp),
+- jiffies);
+- last_tsf_debug = jiffies;
+- }
+-#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+- }
+-
+- ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
+-
+- if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates &&
+- memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 &&
+- (sta = sta_info_get(local, mgmt->sa))) {
+- struct ieee80211_hw_mode *mode;
+- struct ieee80211_rate *rates;
+- size_t num_rates;
+- u32 supp_rates, prev_rates;
+- int i, j;
+-
+- mode = local->sta_sw_scanning ?
+- local->scan_hw_mode : local->oper_hw_mode;
+-
+- if (local->sta_hw_scanning) {
+- /* search for the correct mode matches the beacon */
+- list_for_each_entry(mode, &local->modes_list, list)
+- if (mode->mode == rx_status->phymode)
+- break;
+-
+- if (mode == NULL)
+- mode = local->oper_hw_mode;
+- }
+- rates = mode->rates;
+- num_rates = mode->num_rates;
+-
+- supp_rates = 0;
+- for (i = 0; i < elems.supp_rates_len +
+- elems.ext_supp_rates_len; i++) {
+- u8 rate = 0;
+- int own_rate;
+- if (i < elems.supp_rates_len)
+- rate = elems.supp_rates[i];
+- else if (elems.ext_supp_rates)
+- rate = elems.ext_supp_rates
+- [i - elems.supp_rates_len];
+- own_rate = 5 * (rate & 0x7f);
+- for (j = 0; j < num_rates; j++)
+- if (rates[j].rate == own_rate)
+- supp_rates |= BIT(j);
+- }
+-
+- prev_rates = sta->supp_rates;
+- sta->supp_rates &= supp_rates;
+- if (sta->supp_rates == 0) {
+- /* No matching rates - this should not really happen.
+- * Make sure that at least one rate is marked
+- * supported to avoid issues with TX rate ctrl. */
+- sta->supp_rates = sdata->u.sta.supp_rates_bits;
+- }
+- if (sta->supp_rates != prev_rates) {
+- printk(KERN_DEBUG "%s: updated supp_rates set for "
+- "%s based on beacon info (0x%x & 0x%x -> "
+- "0x%x)\n",
+- dev->name, print_mac(mac, sta->addr), prev_rates,
+- supp_rates, sta->supp_rates);
+- }
+- sta_info_put(sta);
+- }
+-
+- if (!elems.ssid)
+- return;
+-
+- if (elems.ds_params && elems.ds_params_len == 1)
+- channel = elems.ds_params[0];
+- else
+- channel = rx_status->channel;
+-
+- bss = ieee80211_rx_bss_get(dev, mgmt->bssid, channel,
+- elems.ssid, elems.ssid_len);
+- if (!bss) {
+- bss = ieee80211_rx_bss_add(dev, mgmt->bssid, channel,
+- elems.ssid, elems.ssid_len);
+- if (!bss)
+- return;
+- } else {
+-#if 0
+- /* TODO: order by RSSI? */
+- spin_lock_bh(&local->sta_bss_lock);
+- list_move_tail(&bss->list, &local->sta_bss_list);
+- spin_unlock_bh(&local->sta_bss_lock);
+-#endif
+- }
+-
+- if (bss->probe_resp && beacon) {
+- /* Do not allow beacon to override data from Probe Response. */
+- ieee80211_rx_bss_put(dev, bss);
+- return;
+- }
+-
+- /* save the ERP value so that it is available at association time */
+- if (elems.erp_info && elems.erp_info_len >= 1) {
+- bss->erp_value = elems.erp_info[0];
+- bss->has_erp_value = 1;
+- }
+-
+- bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
+- bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
+-
+- bss->supp_rates_len = 0;
+- if (elems.supp_rates) {
+- clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
+- if (clen > elems.supp_rates_len)
+- clen = elems.supp_rates_len;
+- memcpy(&bss->supp_rates[bss->supp_rates_len], elems.supp_rates,
+- clen);
+- bss->supp_rates_len += clen;
+- }
+- if (elems.ext_supp_rates) {
+- clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
+- if (clen > elems.ext_supp_rates_len)
+- clen = elems.ext_supp_rates_len;
+- memcpy(&bss->supp_rates[bss->supp_rates_len],
+- elems.ext_supp_rates, clen);
+- bss->supp_rates_len += clen;
+- }
+-
+- if (elems.wpa &&
+- (!bss->wpa_ie || bss->wpa_ie_len != elems.wpa_len ||
+- memcmp(bss->wpa_ie, elems.wpa, elems.wpa_len))) {
+- kfree(bss->wpa_ie);
+- bss->wpa_ie = kmalloc(elems.wpa_len + 2, GFP_ATOMIC);
+- if (bss->wpa_ie) {
+- memcpy(bss->wpa_ie, elems.wpa - 2, elems.wpa_len + 2);
+- bss->wpa_ie_len = elems.wpa_len + 2;
+- } else
+- bss->wpa_ie_len = 0;
+- } else if (!elems.wpa && bss->wpa_ie) {
+- kfree(bss->wpa_ie);
+- bss->wpa_ie = NULL;
+- bss->wpa_ie_len = 0;
+- }
+-
+- if (elems.rsn &&
+- (!bss->rsn_ie || bss->rsn_ie_len != elems.rsn_len ||
+- memcmp(bss->rsn_ie, elems.rsn, elems.rsn_len))) {
+- kfree(bss->rsn_ie);
+- bss->rsn_ie = kmalloc(elems.rsn_len + 2, GFP_ATOMIC);
+- if (bss->rsn_ie) {
+- memcpy(bss->rsn_ie, elems.rsn - 2, elems.rsn_len + 2);
+- bss->rsn_ie_len = elems.rsn_len + 2;
+- } else
+- bss->rsn_ie_len = 0;
+- } else if (!elems.rsn && bss->rsn_ie) {
+- kfree(bss->rsn_ie);
+- bss->rsn_ie = NULL;
+- bss->rsn_ie_len = 0;
+- }
+-
+- if (elems.wmm_param &&
+- (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_param_len ||
+- memcmp(bss->wmm_ie, elems.wmm_param, elems.wmm_param_len))) {
+- kfree(bss->wmm_ie);
+- bss->wmm_ie = kmalloc(elems.wmm_param_len + 2, GFP_ATOMIC);
+- if (bss->wmm_ie) {
+- memcpy(bss->wmm_ie, elems.wmm_param - 2,
+- elems.wmm_param_len + 2);
+- bss->wmm_ie_len = elems.wmm_param_len + 2;
+- } else
+- bss->wmm_ie_len = 0;
+- } else if (!elems.wmm_param && bss->wmm_ie) {
+- kfree(bss->wmm_ie);
+- bss->wmm_ie = NULL;
+- bss->wmm_ie_len = 0;
+- }
+- if (elems.ht_cap_elem &&
+- (!bss->ht_ie || bss->ht_ie_len != elems.ht_cap_elem_len ||
+- memcmp(bss->ht_ie, elems.ht_cap_elem, elems.ht_cap_elem_len))) {
+- kfree(bss->ht_ie);
+- bss->ht_ie = kmalloc(elems.ht_cap_elem_len + 2, GFP_ATOMIC);
+- if (bss->ht_ie) {
+- memcpy(bss->ht_ie, elems.ht_cap_elem - 2,
+- elems.ht_cap_elem_len + 2);
+- bss->ht_ie_len = elems.ht_cap_elem_len + 2;
+- } else
+- bss->ht_ie_len = 0;
+- } else if (!elems.ht_cap_elem && bss->ht_ie) {
+- kfree(bss->ht_ie);
+- bss->ht_ie = NULL;
+- bss->ht_ie_len = 0;
+- }
+-
+- bss->hw_mode = rx_status->phymode;
+- bss->freq = rx_status->freq;
+- if (channel != rx_status->channel &&
+- (bss->hw_mode == MODE_IEEE80211G ||
+- bss->hw_mode == MODE_IEEE80211B) &&
+- channel >= 1 && channel <= 14) {
+- static const int freq_list[] = {
+- 2412, 2417, 2422, 2427, 2432, 2437, 2442,
+- 2447, 2452, 2457, 2462, 2467, 2472, 2484
+- };
+- /* IEEE 802.11g/b mode can receive packets from neighboring
+- * channels, so map the channel into frequency. */
+- bss->freq = freq_list[channel - 1];
+- }
+- bss->timestamp = timestamp;
+- bss->last_update = jiffies;
+- bss->rssi = rx_status->ssi;
+- bss->signal = rx_status->signal;
+- bss->noise = rx_status->noise;
+- if (!beacon)
+- bss->probe_resp++;
+- ieee80211_rx_bss_put(dev, bss);
+-}
+-
+-
+-static void ieee80211_rx_mgmt_probe_resp(struct net_device *dev,
+- struct ieee80211_mgmt *mgmt,
+- size_t len,
+- struct ieee80211_rx_status *rx_status)
+-{
+- ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 0);
+-}
+-
+-
+-static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
+- struct ieee80211_mgmt *mgmt,
+- size_t len,
+- struct ieee80211_rx_status *rx_status)
+-{
+- struct ieee80211_sub_if_data *sdata;
+- struct ieee80211_if_sta *ifsta;
+- size_t baselen;
+- struct ieee802_11_elems elems;
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_conf *conf = &local->hw.conf;
+- u32 changed = 0;
+-
+- ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 1);
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
+- return;
+- ifsta = &sdata->u.sta;
+-
+- if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED) ||
+- memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0)
+- return;
+-
+- /* Process beacon from the current BSS */
+- baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
+- if (baselen > len)
+- return;
+-
+- ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
+-
+- if (elems.erp_info && elems.erp_info_len >= 1)
+- changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]);
+- else {
+- u16 capab = le16_to_cpu(mgmt->u.beacon.capab_info);
+- changed |= ieee80211_handle_protect_preamb(sdata, false,
+- (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0);
+- }
+-
+- if (elems.ht_cap_elem && elems.ht_info_elem &&
+- elems.wmm_param && local->ops->conf_ht &&
+- conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
+- struct ieee80211_ht_bss_info bss_info;
+-
+- ieee80211_ht_addt_info_ie_to_ht_bss_info(
+- (struct ieee80211_ht_addt_info *)
+- elems.ht_info_elem, &bss_info);
+- /* check if AP changed bss inforamation */
+- if ((conf->ht_bss_conf.primary_channel !=
+- bss_info.primary_channel) ||
+- (conf->ht_bss_conf.bss_cap != bss_info.bss_cap) ||
+- (conf->ht_bss_conf.bss_op_mode != bss_info.bss_op_mode))
+- ieee80211_hw_config_ht(local, 1, &conf->ht_conf,
+- &bss_info);
+- }
+-
+- if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
+- ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
+- elems.wmm_param_len);
+- }
+-
+- ieee80211_bss_info_change_notify(sdata, changed);
+-}
+-
+-
+-static void ieee80211_rx_mgmt_probe_req(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta,
+- struct ieee80211_mgmt *mgmt,
+- size_t len,
+- struct ieee80211_rx_status *rx_status)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- int tx_last_beacon;
+- struct sk_buff *skb;
+- struct ieee80211_mgmt *resp;
+- u8 *pos, *end;
+- DECLARE_MAC_BUF(mac);
+-#ifdef CONFIG_MAC80211_IBSS_DEBUG
+- DECLARE_MAC_BUF(mac2);
+- DECLARE_MAC_BUF(mac3);
+-#endif
+-
+- if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS ||
+- ifsta->state != IEEE80211_IBSS_JOINED ||
+- len < 24 + 2 || !ifsta->probe_resp)
+- return;
+-
+- if (local->ops->tx_last_beacon)
+- tx_last_beacon = local->ops->tx_last_beacon(local_to_hw(local));
+- else
+- tx_last_beacon = 1;
+-
+-#ifdef CONFIG_MAC80211_IBSS_DEBUG
+- printk(KERN_DEBUG "%s: RX ProbeReq SA=%s DA=%s BSSID="
+- "%s (tx_last_beacon=%d)\n",
+- dev->name, print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da),
+- print_mac(mac3, mgmt->bssid), tx_last_beacon);
+-#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+-
+- if (!tx_last_beacon)
+- return;
+-
+- if (memcmp(mgmt->bssid, ifsta->bssid, ETH_ALEN) != 0 &&
+- memcmp(mgmt->bssid, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0)
+- return;
+-
+- end = ((u8 *) mgmt) + len;
+- pos = mgmt->u.probe_req.variable;
+- if (pos[0] != WLAN_EID_SSID ||
+- pos + 2 + pos[1] > end) {
+- if (net_ratelimit()) {
+- printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq "
+- "from %s\n",
+- dev->name, print_mac(mac, mgmt->sa));
+- }
+- return;
+- }
+- if (pos[1] != 0 &&
+- (pos[1] != ifsta->ssid_len ||
+- memcmp(pos + 2, ifsta->ssid, ifsta->ssid_len) != 0)) {
+- /* Ignore ProbeReq for foreign SSID */
+- return;
+- }
+-
+- /* Reply with ProbeResp */
+- skb = skb_copy(ifsta->probe_resp, GFP_KERNEL);
+- if (!skb)
+- return;
+-
+- resp = (struct ieee80211_mgmt *) skb->data;
+- memcpy(resp->da, mgmt->sa, ETH_ALEN);
+-#ifdef CONFIG_MAC80211_IBSS_DEBUG
+- printk(KERN_DEBUG "%s: Sending ProbeResp to %s\n",
+- dev->name, print_mac(mac, resp->da));
+-#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+- ieee80211_sta_tx(dev, skb, 0);
+-}
+-
+-static void ieee80211_rx_mgmt_action(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta,
+- struct ieee80211_mgmt *mgmt,
+- size_t len)
+-{
+- if (len < IEEE80211_MIN_ACTION_SIZE)
+- return;
+-
+- switch (mgmt->u.action.category) {
+- case WLAN_CATEGORY_BACK:
+- switch (mgmt->u.action.u.addba_req.action_code) {
+- case WLAN_ACTION_ADDBA_REQ:
+- if (len < (IEEE80211_MIN_ACTION_SIZE +
+- sizeof(mgmt->u.action.u.addba_req)))
+- break;
+- ieee80211_sta_process_addba_request(dev, mgmt, len);
+- break;
+- case WLAN_ACTION_DELBA:
+- if (len < (IEEE80211_MIN_ACTION_SIZE +
+- sizeof(mgmt->u.action.u.delba)))
+- break;
+- ieee80211_sta_process_delba(dev, mgmt, len);
+- break;
+- default:
+- if (net_ratelimit())
+- printk(KERN_DEBUG "%s: Rx unknown A-MPDU action\n",
+- dev->name);
+- break;
+- }
+- break;
+- default:
+- break;
+- }
+-}
+-
+-void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb,
+- struct ieee80211_rx_status *rx_status)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_sub_if_data *sdata;
+- struct ieee80211_if_sta *ifsta;
+- struct ieee80211_mgmt *mgmt;
+- u16 fc;
+-
+- if (skb->len < 24)
+- goto fail;
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- ifsta = &sdata->u.sta;
+-
+- mgmt = (struct ieee80211_mgmt *) skb->data;
+- fc = le16_to_cpu(mgmt->frame_control);
+-
+- switch (fc & IEEE80211_FCTL_STYPE) {
+- case IEEE80211_STYPE_PROBE_REQ:
+- case IEEE80211_STYPE_PROBE_RESP:
+- case IEEE80211_STYPE_BEACON:
+- memcpy(skb->cb, rx_status, sizeof(*rx_status));
+- case IEEE80211_STYPE_AUTH:
+- case IEEE80211_STYPE_ASSOC_RESP:
+- case IEEE80211_STYPE_REASSOC_RESP:
+- case IEEE80211_STYPE_DEAUTH:
+- case IEEE80211_STYPE_DISASSOC:
+- case IEEE80211_STYPE_ACTION:
+- skb_queue_tail(&ifsta->skb_queue, skb);
+- queue_work(local->hw.workqueue, &ifsta->work);
+- return;
+- default:
+- printk(KERN_DEBUG "%s: received unknown management frame - "
+- "stype=%d\n", dev->name,
+- (fc & IEEE80211_FCTL_STYPE) >> 4);
+- break;
+- }
+-
+- fail:
+- kfree_skb(skb);
+-}
+-
+-
+-static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev,
+- struct sk_buff *skb)
+-{
+- struct ieee80211_rx_status *rx_status;
+- struct ieee80211_sub_if_data *sdata;
+- struct ieee80211_if_sta *ifsta;
+- struct ieee80211_mgmt *mgmt;
+- u16 fc;
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- ifsta = &sdata->u.sta;
+-
+- rx_status = (struct ieee80211_rx_status *) skb->cb;
+- mgmt = (struct ieee80211_mgmt *) skb->data;
+- fc = le16_to_cpu(mgmt->frame_control);
+-
+- switch (fc & IEEE80211_FCTL_STYPE) {
+- case IEEE80211_STYPE_PROBE_REQ:
+- ieee80211_rx_mgmt_probe_req(dev, ifsta, mgmt, skb->len,
+- rx_status);
+- break;
+- case IEEE80211_STYPE_PROBE_RESP:
+- ieee80211_rx_mgmt_probe_resp(dev, mgmt, skb->len, rx_status);
+- break;
+- case IEEE80211_STYPE_BEACON:
+- ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, rx_status);
+- break;
+- case IEEE80211_STYPE_AUTH:
+- ieee80211_rx_mgmt_auth(dev, ifsta, mgmt, skb->len);
+- break;
+- case IEEE80211_STYPE_ASSOC_RESP:
+- ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 0);
+- break;
+- case IEEE80211_STYPE_REASSOC_RESP:
+- ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 1);
+- break;
+- case IEEE80211_STYPE_DEAUTH:
+- ieee80211_rx_mgmt_deauth(dev, ifsta, mgmt, skb->len);
+- break;
+- case IEEE80211_STYPE_DISASSOC:
+- ieee80211_rx_mgmt_disassoc(dev, ifsta, mgmt, skb->len);
+- break;
+- case IEEE80211_STYPE_ACTION:
+- ieee80211_rx_mgmt_action(dev, ifsta, mgmt, skb->len);
+- break;
+- }
+-
+- kfree_skb(skb);
+-}
+-
+-
+-ieee80211_txrx_result
+-ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb,
+- struct ieee80211_rx_status *rx_status)
+-{
+- struct ieee80211_mgmt *mgmt;
+- u16 fc;
+-
+- if (skb->len < 2)
+- return TXRX_DROP;
+-
+- mgmt = (struct ieee80211_mgmt *) skb->data;
+- fc = le16_to_cpu(mgmt->frame_control);
+-
+- if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL)
+- return TXRX_CONTINUE;
+-
+- if (skb->len < 24)
+- return TXRX_DROP;
+-
+- if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
+- if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP) {
+- ieee80211_rx_mgmt_probe_resp(dev, mgmt,
+- skb->len, rx_status);
+- dev_kfree_skb(skb);
+- return TXRX_QUEUED;
+- } else if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) {
+- ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len,
+- rx_status);
+- dev_kfree_skb(skb);
+- return TXRX_QUEUED;
+- }
+- }
+- return TXRX_CONTINUE;
+-}
+-
+-
+-static int ieee80211_sta_active_ibss(struct net_device *dev)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- int active = 0;
+- struct sta_info *sta;
+-
+- read_lock_bh(&local->sta_lock);
+- list_for_each_entry(sta, &local->sta_list, list) {
+- if (sta->dev == dev &&
+- time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL,
+- jiffies)) {
+- active++;
+- break;
+- }
+- }
+- read_unlock_bh(&local->sta_lock);
+-
+- return active;
+-}
+-
+-
+-static void ieee80211_sta_expire(struct net_device *dev)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct sta_info *sta, *tmp;
+- LIST_HEAD(tmp_list);
+- DECLARE_MAC_BUF(mac);
+-
+- write_lock_bh(&local->sta_lock);
+- list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
+- if (time_after(jiffies, sta->last_rx +
+- IEEE80211_IBSS_INACTIVITY_LIMIT)) {
+- printk(KERN_DEBUG "%s: expiring inactive STA %s\n",
+- dev->name, print_mac(mac, sta->addr));
+- __sta_info_get(sta);
+- sta_info_remove(sta);
+- list_add(&sta->list, &tmp_list);
+- }
+- write_unlock_bh(&local->sta_lock);
+-
+- list_for_each_entry_safe(sta, tmp, &tmp_list, list) {
+- sta_info_free(sta);
+- sta_info_put(sta);
+- }
+-}
+-
+-
+-static void ieee80211_sta_merge_ibss(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta)
+-{
+- mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
+-
+- ieee80211_sta_expire(dev);
+- if (ieee80211_sta_active_ibss(dev))
+- return;
+-
+- printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other "
+- "IBSS networks with same SSID (merge)\n", dev->name);
+- ieee80211_sta_req_scan(dev, ifsta->ssid, ifsta->ssid_len);
+-}
+-
+-
+-void ieee80211_sta_timer(unsigned long data)
+-{
+- struct ieee80211_sub_if_data *sdata =
+- (struct ieee80211_sub_if_data *) data;
+- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+- struct ieee80211_local *local = wdev_priv(&sdata->wdev);
+-
+- set_bit(IEEE80211_STA_REQ_RUN, &ifsta->request);
+- queue_work(local->hw.workqueue, &ifsta->work);
+-}
+-
+-
+-void ieee80211_sta_work(struct work_struct *work)
+-{
+- struct ieee80211_sub_if_data *sdata =
+- container_of(work, struct ieee80211_sub_if_data, u.sta.work);
+- struct net_device *dev = sdata->dev;
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_if_sta *ifsta;
+- struct sk_buff *skb;
+-
+- if (!netif_running(dev))
+- return;
+-
+- if (local->sta_sw_scanning || local->sta_hw_scanning)
+- return;
+-
+- if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
+- sdata->vif.type != IEEE80211_IF_TYPE_IBSS) {
+- printk(KERN_DEBUG "%s: ieee80211_sta_work: non-STA interface "
+- "(type=%d)\n", dev->name, sdata->vif.type);
+- return;
+- }
+- ifsta = &sdata->u.sta;
+-
+- while ((skb = skb_dequeue(&ifsta->skb_queue)))
+- ieee80211_sta_rx_queued_mgmt(dev, skb);
+-
+- if (ifsta->state != IEEE80211_AUTHENTICATE &&
+- ifsta->state != IEEE80211_ASSOCIATE &&
+- test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) {
+- if (ifsta->scan_ssid_len)
+- ieee80211_sta_start_scan(dev, ifsta->scan_ssid, ifsta->scan_ssid_len);
+- else
+- ieee80211_sta_start_scan(dev, NULL, 0);
+- return;
+- }
+-
+- if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request)) {
+- if (ieee80211_sta_config_auth(dev, ifsta))
+- return;
+- clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request);
+- } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request))
+- return;
+-
+- switch (ifsta->state) {
+- case IEEE80211_DISABLED:
+- break;
+- case IEEE80211_AUTHENTICATE:
+- ieee80211_authenticate(dev, ifsta);
+- break;
+- case IEEE80211_ASSOCIATE:
+- ieee80211_associate(dev, ifsta);
+- break;
+- case IEEE80211_ASSOCIATED:
+- ieee80211_associated(dev, ifsta);
+- break;
+- case IEEE80211_IBSS_SEARCH:
+- ieee80211_sta_find_ibss(dev, ifsta);
+- break;
+- case IEEE80211_IBSS_JOINED:
+- ieee80211_sta_merge_ibss(dev, ifsta);
+- break;
+- default:
+- printk(KERN_DEBUG "ieee80211_sta_work: Unknown state %d\n",
+- ifsta->state);
+- break;
+- }
+-
+- if (ieee80211_privacy_mismatch(dev, ifsta)) {
+- printk(KERN_DEBUG "%s: privacy configuration mismatch and "
+- "mixed-cell disabled - disassociate\n", dev->name);
+-
+- ieee80211_send_disassoc(dev, ifsta, WLAN_REASON_UNSPECIFIED);
+- ieee80211_set_disassoc(dev, ifsta, 0);
+- }
+-}
+-
+-
+-static void ieee80211_sta_reset_auth(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+- if (local->ops->reset_tsf) {
+- /* Reset own TSF to allow time synchronization work. */
+- local->ops->reset_tsf(local_to_hw(local));
+- }
+-
+- ifsta->wmm_last_param_set = -1; /* allow any WMM update */
+-
+-
+- if (ifsta->auth_algs & IEEE80211_AUTH_ALG_OPEN)
+- ifsta->auth_alg = WLAN_AUTH_OPEN;
+- else if (ifsta->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
+- ifsta->auth_alg = WLAN_AUTH_SHARED_KEY;
+- else if (ifsta->auth_algs & IEEE80211_AUTH_ALG_LEAP)
+- ifsta->auth_alg = WLAN_AUTH_LEAP;
+- else
+- ifsta->auth_alg = WLAN_AUTH_OPEN;
+- printk(KERN_DEBUG "%s: Initial auth_alg=%d\n", dev->name,
+- ifsta->auth_alg);
+- ifsta->auth_transaction = -1;
+- ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
+- ifsta->auth_tries = ifsta->assoc_tries = 0;
+- netif_carrier_off(dev);
+-}
+-
+-
+-void ieee80211_sta_req_auth(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+-
+- if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
+- return;
+-
+- if ((ifsta->flags & (IEEE80211_STA_BSSID_SET |
+- IEEE80211_STA_AUTO_BSSID_SEL)) &&
+- (ifsta->flags & (IEEE80211_STA_SSID_SET |
+- IEEE80211_STA_AUTO_SSID_SEL))) {
+- set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
+- queue_work(local->hw.workqueue, &ifsta->work);
+- }
+-}
+-
+-static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta,
+- const char *ssid, int ssid_len)
+-{
+- int tmp, hidden_ssid;
+-
+- if (ssid_len == ifsta->ssid_len &&
+- !memcmp(ifsta->ssid, ssid, ssid_len))
+- return 1;
+-
+- if (ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL)
+- return 0;
+-
+- hidden_ssid = 1;
+- tmp = ssid_len;
+- while (tmp--) {
+- if (ssid[tmp] != '\0') {
+- hidden_ssid = 0;
+- break;
+- }
+- }
+-
+- if (hidden_ssid && ifsta->ssid_len == ssid_len)
+- return 1;
+-
+- if (ssid_len == 1 && ssid[0] == ' ')
+- return 1;
+-
+- return 0;
+-}
+-
+-static int ieee80211_sta_config_auth(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- struct ieee80211_sta_bss *bss, *selected = NULL;
+- int top_rssi = 0, freq;
+-
+- if (!(ifsta->flags & (IEEE80211_STA_AUTO_SSID_SEL |
+- IEEE80211_STA_AUTO_BSSID_SEL | IEEE80211_STA_AUTO_CHANNEL_SEL))) {
+- ifsta->state = IEEE80211_AUTHENTICATE;
+- ieee80211_sta_reset_auth(dev, ifsta);
+- return 0;
+- }
+-
+- spin_lock_bh(&local->sta_bss_lock);
+- freq = local->oper_channel->freq;
+- list_for_each_entry(bss, &local->sta_bss_list, list) {
+- if (!(bss->capability & WLAN_CAPABILITY_ESS))
+- continue;
+-
+- if (!!(bss->capability & WLAN_CAPABILITY_PRIVACY) ^
+- !!sdata->default_key)
+- continue;
+-
+- if (!(ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) &&
+- bss->freq != freq)
+- continue;
+-
+- if (!(ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) &&
+- memcmp(bss->bssid, ifsta->bssid, ETH_ALEN))
+- continue;
+-
+- if (!(ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) &&
+- !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len))
+- continue;
+-
+- if (!selected || top_rssi < bss->rssi) {
+- selected = bss;
+- top_rssi = bss->rssi;
+- }
+- }
+- if (selected)
+- atomic_inc(&selected->users);
+- spin_unlock_bh(&local->sta_bss_lock);
+-
+- if (selected) {
+- ieee80211_set_channel(local, -1, selected->freq);
+- if (!(ifsta->flags & IEEE80211_STA_SSID_SET))
+- ieee80211_sta_set_ssid(dev, selected->ssid,
+- selected->ssid_len);
+- ieee80211_sta_set_bssid(dev, selected->bssid);
+- ieee80211_rx_bss_put(dev, selected);
+- ifsta->state = IEEE80211_AUTHENTICATE;
+- ieee80211_sta_reset_auth(dev, ifsta);
+- return 0;
+- } else {
+- if (ifsta->state != IEEE80211_AUTHENTICATE) {
+- if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL)
+- ieee80211_sta_start_scan(dev, NULL, 0);
+- else
+- ieee80211_sta_start_scan(dev, ifsta->ssid,
+- ifsta->ssid_len);
+- ifsta->state = IEEE80211_AUTHENTICATE;
+- set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
+- } else
+- ifsta->state = IEEE80211_DISABLED;
+- }
+- return -1;
+-}
+-
+-static int ieee80211_sta_join_ibss(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta,
+- struct ieee80211_sta_bss *bss)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- int res, rates, i, j;
+- struct sk_buff *skb;
+- struct ieee80211_mgmt *mgmt;
+- struct ieee80211_tx_control control;
+- struct ieee80211_hw_mode *mode;
+- struct rate_selection ratesel;
+- u8 *pos;
+- struct ieee80211_sub_if_data *sdata;
+-
+- /* Remove possible STA entries from other IBSS networks. */
+- sta_info_flush(local, NULL);
+-
+- if (local->ops->reset_tsf) {
+- /* Reset own TSF to allow time synchronization work. */
+- local->ops->reset_tsf(local_to_hw(local));
+- }
+- memcpy(ifsta->bssid, bss->bssid, ETH_ALEN);
+- res = ieee80211_if_config(dev);
+- if (res)
+- return res;
+-
+- local->hw.conf.beacon_int = bss->beacon_int >= 10 ? bss->beacon_int : 10;
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- sdata->drop_unencrypted = bss->capability &
+- WLAN_CAPABILITY_PRIVACY ? 1 : 0;
+-
+- res = ieee80211_set_channel(local, -1, bss->freq);
+-
+- if (!(local->oper_channel->flag & IEEE80211_CHAN_W_IBSS)) {
+- printk(KERN_DEBUG "%s: IBSS not allowed on channel %d "
+- "(%d MHz)\n", dev->name, local->hw.conf.channel,
+- local->hw.conf.freq);
+- return -1;
+- }
+-
+- /* Set beacon template based on scan results */
+- skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
+- do {
+- if (!skb)
+- break;
+-
+- skb_reserve(skb, local->hw.extra_tx_headroom);
+-
+- mgmt = (struct ieee80211_mgmt *)
+- skb_put(skb, 24 + sizeof(mgmt->u.beacon));
+- memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
+- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+- IEEE80211_STYPE_BEACON);
+- memset(mgmt->da, 0xff, ETH_ALEN);
+- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+- memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+- mgmt->u.beacon.beacon_int =
+- cpu_to_le16(local->hw.conf.beacon_int);
+- mgmt->u.beacon.capab_info = cpu_to_le16(bss->capability);
+-
+- pos = skb_put(skb, 2 + ifsta->ssid_len);
+- *pos++ = WLAN_EID_SSID;
+- *pos++ = ifsta->ssid_len;
+- memcpy(pos, ifsta->ssid, ifsta->ssid_len);
+-
+- rates = bss->supp_rates_len;
+- if (rates > 8)
+- rates = 8;
+- pos = skb_put(skb, 2 + rates);
+- *pos++ = WLAN_EID_SUPP_RATES;
+- *pos++ = rates;
+- memcpy(pos, bss->supp_rates, rates);
+-
+- pos = skb_put(skb, 2 + 1);
+- *pos++ = WLAN_EID_DS_PARAMS;
+- *pos++ = 1;
+- *pos++ = bss->channel;
+-
+- pos = skb_put(skb, 2 + 2);
+- *pos++ = WLAN_EID_IBSS_PARAMS;
+- *pos++ = 2;
+- /* FIX: set ATIM window based on scan results */
+- *pos++ = 0;
+- *pos++ = 0;
+-
+- if (bss->supp_rates_len > 8) {
+- rates = bss->supp_rates_len - 8;
+- pos = skb_put(skb, 2 + rates);
+- *pos++ = WLAN_EID_EXT_SUPP_RATES;
+- *pos++ = rates;
+- memcpy(pos, &bss->supp_rates[8], rates);
+- }
+-
+- memset(&control, 0, sizeof(control));
+- rate_control_get_rate(dev, local->oper_hw_mode, skb, &ratesel);
+- if (!ratesel.rate) {
+- printk(KERN_DEBUG "%s: Failed to determine TX rate "
+- "for IBSS beacon\n", dev->name);
+- break;
+- }
+- control.vif = &sdata->vif;
+- control.tx_rate =
+- (sdata->bss_conf.use_short_preamble &&
+- (ratesel.rate->flags & IEEE80211_RATE_PREAMBLE2)) ?
+- ratesel.rate->val2 : ratesel.rate->val;
+- control.antenna_sel_tx = local->hw.conf.antenna_sel_tx;
+- control.power_level = local->hw.conf.power_level;
+- control.flags |= IEEE80211_TXCTL_NO_ACK;
+- control.retry_limit = 1;
+-
+- ifsta->probe_resp = skb_copy(skb, GFP_ATOMIC);
+- if (ifsta->probe_resp) {
+- mgmt = (struct ieee80211_mgmt *)
+- ifsta->probe_resp->data;
+- mgmt->frame_control =
+- IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+- IEEE80211_STYPE_PROBE_RESP);
+- } else {
+- printk(KERN_DEBUG "%s: Could not allocate ProbeResp "
+- "template for IBSS\n", dev->name);
+- }
+-
+- if (local->ops->beacon_update &&
+- local->ops->beacon_update(local_to_hw(local),
+- skb, &control) == 0) {
+- printk(KERN_DEBUG "%s: Configured IBSS beacon "
+- "template based on scan results\n", dev->name);
+- skb = NULL;
+- }
+-
+- rates = 0;
+- mode = local->oper_hw_mode;
+- for (i = 0; i < bss->supp_rates_len; i++) {
+- int bitrate = (bss->supp_rates[i] & 0x7f) * 5;
+- for (j = 0; j < mode->num_rates; j++)
+- if (mode->rates[j].rate == bitrate)
+- rates |= BIT(j);
+- }
+- ifsta->supp_rates_bits = rates;
+- } while (0);
+-
+- if (skb) {
+- printk(KERN_DEBUG "%s: Failed to configure IBSS beacon "
+- "template\n", dev->name);
+- dev_kfree_skb(skb);
+- }
+-
+- ifsta->state = IEEE80211_IBSS_JOINED;
+- mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
+-
+- ieee80211_rx_bss_put(dev, bss);
+-
+- return res;
+-}
+-
+-
+-static int ieee80211_sta_create_ibss(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_sta_bss *bss;
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- struct ieee80211_hw_mode *mode;
+- u8 bssid[ETH_ALEN], *pos;
+- int i;
+- DECLARE_MAC_BUF(mac);
+-
+-#if 0
+- /* Easier testing, use fixed BSSID. */
+- memset(bssid, 0xfe, ETH_ALEN);
+-#else
+- /* Generate random, not broadcast, locally administered BSSID. Mix in
+- * own MAC address to make sure that devices that do not have proper
+- * random number generator get different BSSID. */
+- get_random_bytes(bssid, ETH_ALEN);
+- for (i = 0; i < ETH_ALEN; i++)
+- bssid[i] ^= dev->dev_addr[i];
+- bssid[0] &= ~0x01;
+- bssid[0] |= 0x02;
+-#endif
+-
+- printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n",
+- dev->name, print_mac(mac, bssid));
+-
+- bss = ieee80211_rx_bss_add(dev, bssid, local->hw.conf.channel,
+- sdata->u.sta.ssid, sdata->u.sta.ssid_len);
+- if (!bss)
+- return -ENOMEM;
+-
+- mode = local->oper_hw_mode;
+-
+- if (local->hw.conf.beacon_int == 0)
+- local->hw.conf.beacon_int = 100;
+- bss->beacon_int = local->hw.conf.beacon_int;
+- bss->hw_mode = local->hw.conf.phymode;
+- bss->freq = local->hw.conf.freq;
+- bss->last_update = jiffies;
+- bss->capability = WLAN_CAPABILITY_IBSS;
+- if (sdata->default_key) {
+- bss->capability |= WLAN_CAPABILITY_PRIVACY;
+- } else
+- sdata->drop_unencrypted = 0;
+- bss->supp_rates_len = mode->num_rates;
+- pos = bss->supp_rates;
+- for (i = 0; i < mode->num_rates; i++) {
+- int rate = mode->rates[i].rate;
+- *pos++ = (u8) (rate / 5);
+- }
+-
+- return ieee80211_sta_join_ibss(dev, ifsta, bss);
+-}
+-
+-
+-static int ieee80211_sta_find_ibss(struct net_device *dev,
+- struct ieee80211_if_sta *ifsta)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_sta_bss *bss;
+- int found = 0;
+- u8 bssid[ETH_ALEN];
+- int active_ibss;
+- DECLARE_MAC_BUF(mac);
+- DECLARE_MAC_BUF(mac2);
+-
+- if (ifsta->ssid_len == 0)
+- return -EINVAL;
+-
+- active_ibss = ieee80211_sta_active_ibss(dev);
+-#ifdef CONFIG_MAC80211_IBSS_DEBUG
+- printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n",
+- dev->name, active_ibss);
+-#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+- spin_lock_bh(&local->sta_bss_lock);
+- list_for_each_entry(bss, &local->sta_bss_list, list) {
+- if (ifsta->ssid_len != bss->ssid_len ||
+- memcmp(ifsta->ssid, bss->ssid, bss->ssid_len) != 0
+- || !(bss->capability & WLAN_CAPABILITY_IBSS))
+- continue;
+-#ifdef CONFIG_MAC80211_IBSS_DEBUG
+- printk(KERN_DEBUG " bssid=%s found\n",
+- print_mac(mac, bss->bssid));
+-#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+- memcpy(bssid, bss->bssid, ETH_ALEN);
+- found = 1;
+- if (active_ibss || memcmp(bssid, ifsta->bssid, ETH_ALEN) != 0)
+- break;
+- }
+- spin_unlock_bh(&local->sta_bss_lock);
+-
+-#ifdef CONFIG_MAC80211_IBSS_DEBUG
+- printk(KERN_DEBUG " sta_find_ibss: selected %s current "
+- "%s\n", print_mac(mac, bssid), print_mac(mac2, ifsta->bssid));
+-#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+- if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 &&
+- (bss = ieee80211_rx_bss_get(dev, bssid, local->hw.conf.channel,
+- ifsta->ssid, ifsta->ssid_len))) {
+- printk(KERN_DEBUG "%s: Selected IBSS BSSID %s"
+- " based on configured SSID\n",
+- dev->name, print_mac(mac, bssid));
+- return ieee80211_sta_join_ibss(dev, ifsta, bss);
+- }
+-#ifdef CONFIG_MAC80211_IBSS_DEBUG
+- printk(KERN_DEBUG " did not try to join ibss\n");
+-#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+-
+- /* Selected IBSS not found in current scan results - try to scan */
+- if (ifsta->state == IEEE80211_IBSS_JOINED &&
+- !ieee80211_sta_active_ibss(dev)) {
+- mod_timer(&ifsta->timer, jiffies +
+- IEEE80211_IBSS_MERGE_INTERVAL);
+- } else if (time_after(jiffies, local->last_scan_completed +
+- IEEE80211_SCAN_INTERVAL)) {
+- printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to "
+- "join\n", dev->name);
+- return ieee80211_sta_req_scan(dev, ifsta->ssid,
+- ifsta->ssid_len);
+- } else if (ifsta->state != IEEE80211_IBSS_JOINED) {
+- int interval = IEEE80211_SCAN_INTERVAL;
+-
+- if (time_after(jiffies, ifsta->ibss_join_req +
+- IEEE80211_IBSS_JOIN_TIMEOUT)) {
+- if ((ifsta->flags & IEEE80211_STA_CREATE_IBSS) &&
+- local->oper_channel->flag & IEEE80211_CHAN_W_IBSS)
+- return ieee80211_sta_create_ibss(dev, ifsta);
+- if (ifsta->flags & IEEE80211_STA_CREATE_IBSS) {
+- printk(KERN_DEBUG "%s: IBSS not allowed on the"
+- " configured channel %d (%d MHz)\n",
+- dev->name, local->hw.conf.channel,
+- local->hw.conf.freq);
+- }
+-
+- /* No IBSS found - decrease scan interval and continue
+- * scanning. */
+- interval = IEEE80211_SCAN_INTERVAL_SLOW;
+- }
+-
+- ifsta->state = IEEE80211_IBSS_SEARCH;
+- mod_timer(&ifsta->timer, jiffies + interval);
+- return 0;
+- }
+-
+- return 0;
+-}
+-
+-
+-int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len)
+-{
+- struct ieee80211_sub_if_data *sdata;
+- struct ieee80211_if_sta *ifsta;
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+- if (len > IEEE80211_MAX_SSID_LEN)
+- return -EINVAL;
+-
+- /* TODO: This should always be done for IBSS, even if IEEE80211_QOS is
+- * not defined. */
+- if (local->ops->conf_tx) {
+- struct ieee80211_tx_queue_params qparam;
+- int i;
+-
+- memset(&qparam, 0, sizeof(qparam));
+- /* TODO: are these ok defaults for all hw_modes? */
+- qparam.aifs = 2;
+- qparam.cw_min =
+- local->hw.conf.phymode == MODE_IEEE80211B ? 31 : 15;
+- qparam.cw_max = 1023;
+- qparam.burst_time = 0;
+- for (i = IEEE80211_TX_QUEUE_DATA0; i < NUM_TX_DATA_QUEUES; i++)
+- {
+- local->ops->conf_tx(local_to_hw(local),
+- i + IEEE80211_TX_QUEUE_DATA0,
+- &qparam);
+- }
+- /* IBSS uses different parameters for Beacon sending */
+- qparam.cw_min++;
+- qparam.cw_min *= 2;
+- qparam.cw_min--;
+- local->ops->conf_tx(local_to_hw(local),
+- IEEE80211_TX_QUEUE_BEACON, &qparam);
+- }
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- ifsta = &sdata->u.sta;
+-
+- if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0)
+- ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
+- memcpy(ifsta->ssid, ssid, len);
+- memset(ifsta->ssid + len, 0, IEEE80211_MAX_SSID_LEN - len);
+- ifsta->ssid_len = len;
+-
+- if (len)
+- ifsta->flags |= IEEE80211_STA_SSID_SET;
+- else
+- ifsta->flags &= ~IEEE80211_STA_SSID_SET;
+- if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
+- !(ifsta->flags & IEEE80211_STA_BSSID_SET)) {
+- ifsta->ibss_join_req = jiffies;
+- ifsta->state = IEEE80211_IBSS_SEARCH;
+- return ieee80211_sta_find_ibss(dev, ifsta);
+- }
+- return 0;
+-}
+-
+-
+-int ieee80211_sta_get_ssid(struct net_device *dev, char *ssid, size_t *len)
+-{
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+- memcpy(ssid, ifsta->ssid, ifsta->ssid_len);
+- *len = ifsta->ssid_len;
+- return 0;
+-}
+-
+-
+-int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid)
+-{
+- struct ieee80211_sub_if_data *sdata;
+- struct ieee80211_if_sta *ifsta;
+- int res;
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- ifsta = &sdata->u.sta;
+-
+- if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) {
+- memcpy(ifsta->bssid, bssid, ETH_ALEN);
+- res = ieee80211_if_config(dev);
+- if (res) {
+- printk(KERN_DEBUG "%s: Failed to config new BSSID to "
+- "the low-level driver\n", dev->name);
+- return res;
+- }
+- }
+-
+- if (is_valid_ether_addr(bssid))
+- ifsta->flags |= IEEE80211_STA_BSSID_SET;
+- else
+- ifsta->flags &= ~IEEE80211_STA_BSSID_SET;
+-
+- return 0;
+-}
+-
+-
+-static void ieee80211_send_nullfunc(struct ieee80211_local *local,
+- struct ieee80211_sub_if_data *sdata,
+- int powersave)
+-{
+- struct sk_buff *skb;
+- struct ieee80211_hdr *nullfunc;
+- u16 fc;
+-
+- skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24);
+- if (!skb) {
+- printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc "
+- "frame\n", sdata->dev->name);
+- return;
+- }
+- skb_reserve(skb, local->hw.extra_tx_headroom);
+-
+- nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24);
+- memset(nullfunc, 0, 24);
+- fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC |
+- IEEE80211_FCTL_TODS;
+- if (powersave)
+- fc |= IEEE80211_FCTL_PM;
+- nullfunc->frame_control = cpu_to_le16(fc);
+- memcpy(nullfunc->addr1, sdata->u.sta.bssid, ETH_ALEN);
+- memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN);
+- memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN);
+-
+- ieee80211_sta_tx(sdata->dev, skb, 0);
+-}
+-
+-
+-void ieee80211_scan_completed(struct ieee80211_hw *hw)
+-{
+- struct ieee80211_local *local = hw_to_local(hw);
+- struct net_device *dev = local->scan_dev;
+- struct ieee80211_sub_if_data *sdata;
+- union iwreq_data wrqu;
+-
+- local->last_scan_completed = jiffies;
+- memset(&wrqu, 0, sizeof(wrqu));
+- wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
+-
+- if (local->sta_hw_scanning) {
+- local->sta_hw_scanning = 0;
+- goto done;
+- }
+-
+- local->sta_sw_scanning = 0;
+- if (ieee80211_hw_config(local))
+- printk(KERN_DEBUG "%s: failed to restore operational "
+- "channel after scan\n", dev->name);
+-
+-
+- netif_tx_lock_bh(local->mdev);
+- local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC;
+- local->ops->configure_filter(local_to_hw(local),
+- FIF_BCN_PRBRESP_PROMISC,
+- &local->filter_flags,
+- local->mdev->mc_count,
+- local->mdev->mc_list);
+-
+- netif_tx_unlock_bh(local->mdev);
+-
+- rcu_read_lock();
+- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+-
+- /* No need to wake the master device. */
+- if (sdata->dev == local->mdev)
+- continue;
+-
+- if (sdata->vif.type == IEEE80211_IF_TYPE_STA) {
+- if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED)
+- ieee80211_send_nullfunc(local, sdata, 0);
+- ieee80211_sta_timer((unsigned long)sdata);
+- }
+-
+- netif_wake_queue(sdata->dev);
+- }
+- rcu_read_unlock();
+-
+-done:
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
+- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+- if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) ||
+- (!ifsta->state == IEEE80211_IBSS_JOINED &&
+- !ieee80211_sta_active_ibss(dev)))
+- ieee80211_sta_find_ibss(dev, ifsta);
+- }
+-}
+-EXPORT_SYMBOL(ieee80211_scan_completed);
+-
+-void ieee80211_sta_scan_work(struct work_struct *work)
+-{
+- struct ieee80211_local *local =
+- container_of(work, struct ieee80211_local, scan_work.work);
+- struct net_device *dev = local->scan_dev;
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- struct ieee80211_hw_mode *mode;
+- struct ieee80211_channel *chan;
+- int skip;
+- unsigned long next_delay = 0;
+-
+- if (!local->sta_sw_scanning)
+- return;
+-
+- switch (local->scan_state) {
+- case SCAN_SET_CHANNEL:
+- mode = local->scan_hw_mode;
+- if (local->scan_hw_mode->list.next == &local->modes_list &&
+- local->scan_channel_idx >= mode->num_channels) {
+- ieee80211_scan_completed(local_to_hw(local));
+- return;
+- }
+- skip = !(local->enabled_modes & (1 << mode->mode));
+- chan = &mode->channels[local->scan_channel_idx];
+- if (!(chan->flag & IEEE80211_CHAN_W_SCAN) ||
+- (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
+- !(chan->flag & IEEE80211_CHAN_W_IBSS)) ||
+- (local->hw_modes & local->enabled_modes &
+- (1 << MODE_IEEE80211G) && mode->mode == MODE_IEEE80211B))
+- skip = 1;
+-
+- if (!skip) {
+-#if 0
+- printk(KERN_DEBUG "%s: scan channel %d (%d MHz)\n",
+- dev->name, chan->chan, chan->freq);
+-#endif
+-
+- local->scan_channel = chan;
+- if (ieee80211_hw_config(local)) {
+- printk(KERN_DEBUG "%s: failed to set channel "
+- "%d (%d MHz) for scan\n", dev->name,
+- chan->chan, chan->freq);
+- skip = 1;
+- }
+- }
+-
+- local->scan_channel_idx++;
+- if (local->scan_channel_idx >= local->scan_hw_mode->num_channels) {
+- if (local->scan_hw_mode->list.next != &local->modes_list) {
+- local->scan_hw_mode = list_entry(local->scan_hw_mode->list.next,
+- struct ieee80211_hw_mode,
+- list);
+- local->scan_channel_idx = 0;
+- }
+- }
+-
+- if (skip)
+- break;
+-
+- next_delay = IEEE80211_PROBE_DELAY +
+- usecs_to_jiffies(local->hw.channel_change_time);
+- local->scan_state = SCAN_SEND_PROBE;
+- break;
+- case SCAN_SEND_PROBE:
+- if (local->scan_channel->flag & IEEE80211_CHAN_W_ACTIVE_SCAN) {
+- ieee80211_send_probe_req(dev, NULL, local->scan_ssid,
+- local->scan_ssid_len);
+- next_delay = IEEE80211_CHANNEL_TIME;
+- } else
+- next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
+- local->scan_state = SCAN_SET_CHANNEL;
+- break;
+- }
+-
+- if (local->sta_sw_scanning)
+- queue_delayed_work(local->hw.workqueue, &local->scan_work,
+- next_delay);
+-}
+-
+-
+-static int ieee80211_sta_start_scan(struct net_device *dev,
+- u8 *ssid, size_t ssid_len)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_sub_if_data *sdata;
+-
+- if (ssid_len > IEEE80211_MAX_SSID_LEN)
+- return -EINVAL;
+-
+- /* MLME-SCAN.request (page 118) page 144 (11.1.3.1)
+- * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS
+- * BSSID: MACAddress
+- * SSID
+- * ScanType: ACTIVE, PASSIVE
+- * ProbeDelay: delay (in microseconds) to be used prior to transmitting
+- * a Probe frame during active scanning
+- * ChannelList
+- * MinChannelTime (>= ProbeDelay), in TU
+- * MaxChannelTime: (>= MinChannelTime), in TU
+- */
+-
+- /* MLME-SCAN.confirm
+- * BSSDescriptionSet
+- * ResultCode: SUCCESS, INVALID_PARAMETERS
+- */
+-
+- if (local->sta_sw_scanning || local->sta_hw_scanning) {
+- if (local->scan_dev == dev)
+- return 0;
+- return -EBUSY;
+- }
+-
+- if (local->ops->hw_scan) {
+- int rc = local->ops->hw_scan(local_to_hw(local),
+- ssid, ssid_len);
+- if (!rc) {
+- local->sta_hw_scanning = 1;
+- local->scan_dev = dev;
+- }
+- return rc;
+- }
+-
+- local->sta_sw_scanning = 1;
+-
+- rcu_read_lock();
+- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+-
+- /* Don't stop the master interface, otherwise we can't transmit
+- * probes! */
+- if (sdata->dev == local->mdev)
+- continue;
+-
+- netif_stop_queue(sdata->dev);
+- if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
+- (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED))
+- ieee80211_send_nullfunc(local, sdata, 1);
+- }
+- rcu_read_unlock();
+-
+- if (ssid) {
+- local->scan_ssid_len = ssid_len;
+- memcpy(local->scan_ssid, ssid, ssid_len);
+- } else
+- local->scan_ssid_len = 0;
+- local->scan_state = SCAN_SET_CHANNEL;
+- local->scan_hw_mode = list_entry(local->modes_list.next,
+- struct ieee80211_hw_mode,
+- list);
+- local->scan_channel_idx = 0;
+- local->scan_dev = dev;
+-
+- netif_tx_lock_bh(local->mdev);
+- local->filter_flags |= FIF_BCN_PRBRESP_PROMISC;
+- local->ops->configure_filter(local_to_hw(local),
+- FIF_BCN_PRBRESP_PROMISC,
+- &local->filter_flags,
+- local->mdev->mc_count,
+- local->mdev->mc_list);
+- netif_tx_unlock_bh(local->mdev);
+-
+- /* TODO: start scan as soon as all nullfunc frames are ACKed */
+- queue_delayed_work(local->hw.workqueue, &local->scan_work,
+- IEEE80211_CHANNEL_TIME);
+-
+- return 0;
+-}
+-
+-
+-int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len)
+-{
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+-
+- if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
+- return ieee80211_sta_start_scan(dev, ssid, ssid_len);
+-
+- if (local->sta_sw_scanning || local->sta_hw_scanning) {
+- if (local->scan_dev == dev)
+- return 0;
+- return -EBUSY;
+- }
+-
+- ifsta->scan_ssid_len = ssid_len;
+- if (ssid_len)
+- memcpy(ifsta->scan_ssid, ssid, ssid_len);
+- set_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request);
+- queue_work(local->hw.workqueue, &ifsta->work);
+- return 0;
+-}
+-
+-static char *
+-ieee80211_sta_scan_result(struct net_device *dev,
+- struct ieee80211_sta_bss *bss,
+- char *current_ev, char *end_buf)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct iw_event iwe;
+-
+- if (time_after(jiffies,
+- bss->last_update + IEEE80211_SCAN_RESULT_EXPIRE))
+- return current_ev;
+-
+- if (!(local->enabled_modes & (1 << bss->hw_mode)))
+- return current_ev;
+-
+- memset(&iwe, 0, sizeof(iwe));
+- iwe.cmd = SIOCGIWAP;
+- iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+- memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN);
+- current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+- IW_EV_ADDR_LEN);
+-
+- memset(&iwe, 0, sizeof(iwe));
+- iwe.cmd = SIOCGIWESSID;
+- iwe.u.data.length = bss->ssid_len;
+- iwe.u.data.flags = 1;
+- current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+- bss->ssid);
+-
+- if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
+- memset(&iwe, 0, sizeof(iwe));
+- iwe.cmd = SIOCGIWMODE;
+- if (bss->capability & WLAN_CAPABILITY_ESS)
+- iwe.u.mode = IW_MODE_MASTER;
+- else
+- iwe.u.mode = IW_MODE_ADHOC;
+- current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+- IW_EV_UINT_LEN);
+- }
+-
+- memset(&iwe, 0, sizeof(iwe));
+- iwe.cmd = SIOCGIWFREQ;
+- iwe.u.freq.m = bss->channel;
+- iwe.u.freq.e = 0;
+- current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+- IW_EV_FREQ_LEN);
+- iwe.u.freq.m = bss->freq * 100000;
+- iwe.u.freq.e = 1;
+- current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+- IW_EV_FREQ_LEN);
+-
+- memset(&iwe, 0, sizeof(iwe));
+- iwe.cmd = IWEVQUAL;
+- iwe.u.qual.qual = bss->signal;
+- iwe.u.qual.level = bss->rssi;
+- iwe.u.qual.noise = bss->noise;
+- iwe.u.qual.updated = local->wstats_flags;
+- current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+- IW_EV_QUAL_LEN);
+-
+- memset(&iwe, 0, sizeof(iwe));
+- iwe.cmd = SIOCGIWENCODE;
+- if (bss->capability & WLAN_CAPABILITY_PRIVACY)
+- iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+- else
+- iwe.u.data.flags = IW_ENCODE_DISABLED;
+- iwe.u.data.length = 0;
+- current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, "");
+-
+- if (bss && bss->wpa_ie) {
+- memset(&iwe, 0, sizeof(iwe));
+- iwe.cmd = IWEVGENIE;
+- iwe.u.data.length = bss->wpa_ie_len;
+- current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+- bss->wpa_ie);
+- }
+-
+- if (bss && bss->rsn_ie) {
+- memset(&iwe, 0, sizeof(iwe));
+- iwe.cmd = IWEVGENIE;
+- iwe.u.data.length = bss->rsn_ie_len;
+- current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+- bss->rsn_ie);
+- }
+-
+- if (bss && bss->supp_rates_len > 0) {
+- /* display all supported rates in readable format */
+- char *p = current_ev + IW_EV_LCP_LEN;
+- int i;
+-
+- memset(&iwe, 0, sizeof(iwe));
+- iwe.cmd = SIOCGIWRATE;
+- /* Those two flags are ignored... */
+- iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+-
+- for (i = 0; i < bss->supp_rates_len; i++) {
+- iwe.u.bitrate.value = ((bss->supp_rates[i] &
+- 0x7f) * 500000);
+- p = iwe_stream_add_value(current_ev, p,
+- end_buf, &iwe, IW_EV_PARAM_LEN);
+- }
+- current_ev = p;
+- }
+-
+- if (bss) {
+- char *buf;
+- buf = kmalloc(30, GFP_ATOMIC);
+- if (buf) {
+- memset(&iwe, 0, sizeof(iwe));
+- iwe.cmd = IWEVCUSTOM;
+- sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->timestamp));
+- iwe.u.data.length = strlen(buf);
+- current_ev = iwe_stream_add_point(current_ev, end_buf,
+- &iwe, buf);
+- kfree(buf);
+- }
+- }
+-
+- return current_ev;
+-}
+-
+-
+-int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- char *current_ev = buf;
+- char *end_buf = buf + len;
+- struct ieee80211_sta_bss *bss;
+-
+- spin_lock_bh(&local->sta_bss_lock);
+- list_for_each_entry(bss, &local->sta_bss_list, list) {
+- if (buf + len - current_ev <= IW_EV_ADDR_LEN) {
+- spin_unlock_bh(&local->sta_bss_lock);
+- return -E2BIG;
+- }
+- current_ev = ieee80211_sta_scan_result(dev, bss, current_ev,
+- end_buf);
+- }
+- spin_unlock_bh(&local->sta_bss_lock);
+- return current_ev - buf;
+-}
+-
+-
+-int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len)
+-{
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+- kfree(ifsta->extra_ie);
+- if (len == 0) {
+- ifsta->extra_ie = NULL;
+- ifsta->extra_ie_len = 0;
+- return 0;
+- }
+- ifsta->extra_ie = kmalloc(len, GFP_KERNEL);
+- if (!ifsta->extra_ie) {
+- ifsta->extra_ie_len = 0;
+- return -ENOMEM;
+- }
+- memcpy(ifsta->extra_ie, ie, len);
+- ifsta->extra_ie_len = len;
+- return 0;
+-}
+-
+-
+-struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev,
+- struct sk_buff *skb, u8 *bssid,
+- u8 *addr)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct sta_info *sta;
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- DECLARE_MAC_BUF(mac);
+-
+- /* TODO: Could consider removing the least recently used entry and
+- * allow new one to be added. */
+- if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
+- if (net_ratelimit()) {
+- printk(KERN_DEBUG "%s: No room for a new IBSS STA "
+- "entry %s\n", dev->name, print_mac(mac, addr));
+- }
+- return NULL;
+- }
+-
+- printk(KERN_DEBUG "%s: Adding new IBSS station %s (dev=%s)\n",
+- wiphy_name(local->hw.wiphy), print_mac(mac, addr), dev->name);
+-
+- sta = sta_info_add(local, dev, addr, GFP_ATOMIC);
+- if (!sta)
+- return NULL;
+-
+- sta->supp_rates = sdata->u.sta.supp_rates_bits;
+-
+- rate_control_rate_init(sta, local);
+-
+- return sta; /* caller will call sta_info_put() */
+-}
+-
+-
+-int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason)
+-{
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+-
+- printk(KERN_DEBUG "%s: deauthenticate(reason=%d)\n",
+- dev->name, reason);
+-
+- if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
+- sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
+- return -EINVAL;
+-
+- ieee80211_send_deauth(dev, ifsta, reason);
+- ieee80211_set_disassoc(dev, ifsta, 1);
+- return 0;
+-}
+-
+-
+-int ieee80211_sta_disassociate(struct net_device *dev, u16 reason)
+-{
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+-
+- printk(KERN_DEBUG "%s: disassociate(reason=%d)\n",
+- dev->name, reason);
+-
+- if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
+- return -EINVAL;
+-
+- if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED))
+- return -1;
+-
+- ieee80211_send_disassoc(dev, ifsta, reason);
+- ieee80211_set_disassoc(dev, ifsta, 0);
+- return 0;
+-}
+diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
+new file mode 100644
+index 0000000..80954a5
+--- /dev/null
++++ b/net/mac80211/iface.c
+@@ -0,0 +1,314 @@
++/*
++ * Copyright 2002-2005, Instant802 Networks, Inc.
++ * Copyright 2005-2006, Devicescape Software, Inc.
++ * Copyright (c) 2006 Jiri Benc <jbenc at suse.cz>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/kernel.h>
++#include <linux/if_arp.h>
++#include <linux/netdevice.h>
++#include <linux/rtnetlink.h>
++#include <net/mac80211.h>
++#include "ieee80211_i.h"
++#include "sta_info.h"
++#include "debugfs_netdev.h"
++#include "mesh.h"
++
++void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata)
++{
++ int i;
++
++ /* Default values for sub-interface parameters */
++ sdata->drop_unencrypted = 0;
++ for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
++ skb_queue_head_init(&sdata->fragments[i].skb_list);
++
++ INIT_LIST_HEAD(&sdata->key_list);
++}
++
++static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata)
++{
++ int i;
++
++ for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) {
++ __skb_queue_purge(&sdata->fragments[i].skb_list);
++ }
++}
++
++/* Must be called with rtnl lock held. */
++int ieee80211_if_add(struct net_device *dev, const char *name,
++ struct net_device **new_dev, int type,
++ struct vif_params *params)
++{
++ struct net_device *ndev;
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sub_if_data *sdata = NULL;
++ int ret;
++
++ ASSERT_RTNL();
++ ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size,
++ name, ieee80211_if_setup);
++ if (!ndev)
++ return -ENOMEM;
++
++ ret = dev_alloc_name(ndev, ndev->name);
++ if (ret < 0)
++ goto fail;
++
++ memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
++ ndev->base_addr = dev->base_addr;
++ ndev->irq = dev->irq;
++ ndev->mem_start = dev->mem_start;
++ ndev->mem_end = dev->mem_end;
++ SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
++
++ sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
++ ndev->ieee80211_ptr = &sdata->wdev;
++ sdata->wdev.wiphy = local->hw.wiphy;
++ sdata->vif.type = IEEE80211_IF_TYPE_AP;
++ sdata->dev = ndev;
++ sdata->local = local;
++ ieee80211_if_sdata_init(sdata);
++
++ ret = register_netdevice(ndev);
++ if (ret)
++ goto fail;
++
++ ieee80211_debugfs_add_netdev(sdata);
++ ieee80211_if_set_type(ndev, type);
++
++ if (ieee80211_vif_is_mesh(&sdata->vif) &&
++ params && params->mesh_id_len)
++ ieee80211_if_sta_set_mesh_id(&sdata->u.sta,
++ params->mesh_id_len,
++ params->mesh_id);
++
++ /* we're under RTNL so all this is fine */
++ if (unlikely(local->reg_state == IEEE80211_DEV_UNREGISTERED)) {
++ __ieee80211_if_del(local, sdata);
++ return -ENODEV;
++ }
++ list_add_tail_rcu(&sdata->list, &local->interfaces);
++
++ if (new_dev)
++ *new_dev = ndev;
++
++ return 0;
++
++fail:
++ free_netdev(ndev);
++ return ret;
++}
++
++void ieee80211_if_set_type(struct net_device *dev, int type)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ int oldtype = sdata->vif.type;
++
++ /*
++ * We need to call this function on the master interface
++ * which already has a hard_start_xmit routine assigned
++ * which must not be changed.
++ */
++ if (dev != sdata->local->mdev)
++ dev->hard_start_xmit = ieee80211_subif_start_xmit;
++
++ /*
++ * Called even when register_netdevice fails, it would
++ * oops if assigned before initialising the rest.
++ */
++ dev->uninit = ieee80211_if_reinit;
++
++ /* most have no BSS pointer */
++ sdata->bss = NULL;
++ sdata->vif.type = type;
++
++ sdata->basic_rates = 0;
++
++ switch (type) {
++ case IEEE80211_IF_TYPE_WDS:
++ /* nothing special */
++ break;
++ case IEEE80211_IF_TYPE_VLAN:
++ sdata->u.vlan.ap = NULL;
++ break;
++ case IEEE80211_IF_TYPE_AP:
++ sdata->u.ap.force_unicast_rateidx = -1;
++ sdata->u.ap.max_ratectrl_rateidx = -1;
++ skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
++ sdata->bss = &sdata->u.ap;
++ INIT_LIST_HEAD(&sdata->u.ap.vlans);
++ break;
++ case IEEE80211_IF_TYPE_MESH_POINT:
++ case IEEE80211_IF_TYPE_STA:
++ case IEEE80211_IF_TYPE_IBSS: {
++ struct ieee80211_sub_if_data *msdata;
++ struct ieee80211_if_sta *ifsta;
++
++ ifsta = &sdata->u.sta;
++ INIT_WORK(&ifsta->work, ieee80211_sta_work);
++ setup_timer(&ifsta->timer, ieee80211_sta_timer,
++ (unsigned long) sdata);
++ skb_queue_head_init(&ifsta->skb_queue);
++
++ ifsta->capab = WLAN_CAPABILITY_ESS;
++ ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN |
++ IEEE80211_AUTH_ALG_SHARED_KEY;
++ ifsta->flags |= IEEE80211_STA_CREATE_IBSS |
++ IEEE80211_STA_WMM_ENABLED |
++ IEEE80211_STA_AUTO_BSSID_SEL |
++ IEEE80211_STA_AUTO_CHANNEL_SEL;
++
++ msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev);
++ sdata->bss = &msdata->u.ap;
++
++ if (ieee80211_vif_is_mesh(&sdata->vif))
++ ieee80211_mesh_init_sdata(sdata);
++ break;
++ }
++ case IEEE80211_IF_TYPE_MNTR:
++ dev->type = ARPHRD_IEEE80211_RADIOTAP;
++ dev->hard_start_xmit = ieee80211_monitor_start_xmit;
++ sdata->u.mntr_flags = MONITOR_FLAG_CONTROL |
++ MONITOR_FLAG_OTHER_BSS;
++ break;
++ default:
++ printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x",
++ dev->name, __func__, type);
++ }
++ ieee80211_debugfs_change_if_type(sdata, oldtype);
++}
++
++/* Must be called with rtnl lock held. */
++void ieee80211_if_reinit(struct net_device *dev)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct sk_buff *skb;
++ int flushed;
++
++ ASSERT_RTNL();
++
++ ieee80211_free_keys(sdata);
++
++ ieee80211_if_sdata_deinit(sdata);
++
++ /* Need to handle mesh specially to allow eliding the function call */
++ if (ieee80211_vif_is_mesh(&sdata->vif))
++ mesh_rmc_free(dev);
++
++ switch (sdata->vif.type) {
++ case IEEE80211_IF_TYPE_INVALID:
++ /* cannot happen */
++ WARN_ON(1);
++ break;
++ case IEEE80211_IF_TYPE_AP: {
++ /* Remove all virtual interfaces that use this BSS
++ * as their sdata->bss */
++ struct ieee80211_sub_if_data *tsdata, *n;
++ struct beacon_data *beacon;
++
++ list_for_each_entry_safe(tsdata, n, &local->interfaces, list) {
++ if (tsdata != sdata && tsdata->bss == &sdata->u.ap) {
++ printk(KERN_DEBUG "%s: removing virtual "
++ "interface %s because its BSS interface"
++ " is being removed\n",
++ sdata->dev->name, tsdata->dev->name);
++ list_del_rcu(&tsdata->list);
++ /*
++ * We have lots of time and can afford
++ * to sync for each interface
++ */
++ synchronize_rcu();
++ __ieee80211_if_del(local, tsdata);
++ }
++ }
++
++ beacon = sdata->u.ap.beacon;
++ rcu_assign_pointer(sdata->u.ap.beacon, NULL);
++ synchronize_rcu();
++ kfree(beacon);
++
++ while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
++ local->total_ps_buffered--;
++ dev_kfree_skb(skb);
++ }
++
++ break;
++ }
++ case IEEE80211_IF_TYPE_WDS:
++ /* nothing to do */
++ break;
++ case IEEE80211_IF_TYPE_MESH_POINT:
++ case IEEE80211_IF_TYPE_STA:
++ case IEEE80211_IF_TYPE_IBSS:
++ kfree(sdata->u.sta.extra_ie);
++ sdata->u.sta.extra_ie = NULL;
++ kfree(sdata->u.sta.assocreq_ies);
++ sdata->u.sta.assocreq_ies = NULL;
++ kfree(sdata->u.sta.assocresp_ies);
++ sdata->u.sta.assocresp_ies = NULL;
++ if (sdata->u.sta.probe_resp) {
++ dev_kfree_skb(sdata->u.sta.probe_resp);
++ sdata->u.sta.probe_resp = NULL;
++ }
++
++ break;
++ case IEEE80211_IF_TYPE_MNTR:
++ dev->type = ARPHRD_ETHER;
++ break;
++ case IEEE80211_IF_TYPE_VLAN:
++ sdata->u.vlan.ap = NULL;
++ break;
++ }
++
++ flushed = sta_info_flush(local, sdata);
++ WARN_ON(flushed);
++
++ memset(&sdata->u, 0, sizeof(sdata->u));
++ ieee80211_if_sdata_init(sdata);
++}
++
++/* Must be called with rtnl lock held. */
++void __ieee80211_if_del(struct ieee80211_local *local,
++ struct ieee80211_sub_if_data *sdata)
++{
++ struct net_device *dev = sdata->dev;
++
++ ieee80211_debugfs_remove_netdev(sdata);
++ unregister_netdevice(dev);
++ /* Except master interface, the net_device will be freed by
++ * net_device->destructor (i. e. ieee80211_if_free). */
++}
++
++/* Must be called with rtnl lock held. */
++int ieee80211_if_remove(struct net_device *dev, const char *name, int id)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sub_if_data *sdata, *n;
++
++ ASSERT_RTNL();
++
++ list_for_each_entry_safe(sdata, n, &local->interfaces, list) {
++ if ((sdata->vif.type == id || id == -1) &&
++ strcmp(name, sdata->dev->name) == 0 &&
++ sdata->dev != local->mdev) {
++ list_del_rcu(&sdata->list);
++ synchronize_rcu();
++ __ieee80211_if_del(local, sdata);
++ return 0;
++ }
++ }
++ return -ENODEV;
++}
++
++void ieee80211_if_free(struct net_device *dev)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++ ieee80211_if_sdata_deinit(sdata);
++ free_netdev(dev);
++}
+diff --git a/net/mac80211/key.c b/net/mac80211/key.c
+index ed57fb8..150d66d 100644
+--- a/net/mac80211/key.c
++++ b/net/mac80211/key.c
+@@ -2,7 +2,7 @@
+ * Copyright 2002-2005, Instant802 Networks, Inc.
+ * Copyright 2005-2006, Devicescape Software, Inc.
+ * Copyright 2006-2007 Jiri Benc <jbenc at suse.cz>
+- * Copyright 2007 Johannes Berg <johannes at sipsolutions.net>
++ * Copyright 2007-2008 Johannes Berg <johannes at sipsolutions.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+@@ -13,14 +13,15 @@
+ #include <linux/etherdevice.h>
+ #include <linux/list.h>
+ #include <linux/rcupdate.h>
++#include <linux/rtnetlink.h>
+ #include <net/mac80211.h>
+ #include "ieee80211_i.h"
+ #include "debugfs_key.h"
+ #include "aes_ccm.h"
+
+
+-/*
+- * Key handling basics
++/**
++ * DOC: Key handling basics
+ *
+ * Key handling in mac80211 is done based on per-interface (sub_if_data)
+ * keys and per-station keys. Since each station belongs to an interface,
+@@ -32,13 +33,81 @@
+ * There is currently no way of knowing this except by looking into
+ * debugfs.
+ *
+- * All operations here are called under RTNL so no extra locking is
+- * required.
++ * All key operations are protected internally so you can call them at
++ * any time.
++ *
++ * Within mac80211, key references are, just as STA structure references,
++ * protected by RCU. Note, however, that some things are unprotected,
++ * namely the key->sta dereferences within the hardware acceleration
++ * functions. This means that sta_info_destroy() must flush the key todo
++ * list.
++ *
++ * All the direct key list manipulation functions must not sleep because
++ * they can operate on STA info structs that are protected by RCU.
+ */
+
+ static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+ static const u8 zero_addr[ETH_ALEN];
+
++/* key mutex: used to synchronise todo runners */
++static DEFINE_MUTEX(key_mutex);
++static DEFINE_SPINLOCK(todo_lock);
++static LIST_HEAD(todo_list);
++
++static void key_todo(struct work_struct *work)
++{
++ ieee80211_key_todo();
++}
++
++static DECLARE_WORK(todo_work, key_todo);
++
++/**
++ * add_todo - add todo item for a key
++ *
++ * @key: key to add to do item for
++ * @flag: todo flag(s)
++ */
++static void add_todo(struct ieee80211_key *key, u32 flag)
++{
++ if (!key)
++ return;
++
++ spin_lock(&todo_lock);
++ key->flags |= flag;
++ /*
++ * Remove again if already on the list so that we move it to the end.
++ */
++ if (!list_empty(&key->todo))
++ list_del(&key->todo);
++ list_add_tail(&key->todo, &todo_list);
++ schedule_work(&todo_work);
++ spin_unlock(&todo_lock);
++}
++
++/**
++ * ieee80211_key_lock - lock the mac80211 key operation lock
++ *
++ * This locks the (global) mac80211 key operation lock, all
++ * key operations must be done under this lock.
++ */
++static void ieee80211_key_lock(void)
++{
++ mutex_lock(&key_mutex);
++}
++
++/**
++ * ieee80211_key_unlock - unlock the mac80211 key operation lock
++ */
++static void ieee80211_key_unlock(void)
++{
++ mutex_unlock(&key_mutex);
++}
++
++static void assert_key_lock(void)
++{
++ WARN_ON(!mutex_is_locked(&key_mutex));
++}
++
+ static const u8 *get_mac_for_key(struct ieee80211_key *key)
+ {
+ const u8 *addr = bcast_addr;
+@@ -65,6 +134,9 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
+ int ret;
+ DECLARE_MAC_BUF(mac);
+
++ assert_key_lock();
++ might_sleep();
++
+ if (!key->local->ops->set_key)
+ return;
+
+@@ -74,8 +146,11 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
+ key->sdata->dev->dev_addr, addr,
+ &key->conf);
+
+- if (!ret)
++ if (!ret) {
++ spin_lock(&todo_lock);
+ key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
++ spin_unlock(&todo_lock);
++ }
+
+ if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP)
+ printk(KERN_ERR "mac80211-%s: failed to set key "
+@@ -90,11 +165,18 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
+ int ret;
+ DECLARE_MAC_BUF(mac);
+
+- if (!key->local->ops->set_key)
++ assert_key_lock();
++ might_sleep();
++
++ if (!key || !key->local->ops->set_key)
+ return;
+
+- if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
++ spin_lock(&todo_lock);
++ if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
++ spin_unlock(&todo_lock);
+ return;
++ }
++ spin_unlock(&todo_lock);
+
+ addr = get_mac_for_key(key);
+
+@@ -108,12 +190,75 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
+ wiphy_name(key->local->hw.wiphy),
+ key->conf.keyidx, print_mac(mac, addr), ret);
+
++ spin_lock(&todo_lock);
+ key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
++ spin_unlock(&todo_lock);
+ }
+
+-struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
+- struct sta_info *sta,
+- enum ieee80211_key_alg alg,
++static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
++ int idx)
++{
++ struct ieee80211_key *key = NULL;
++
++ if (idx >= 0 && idx < NUM_DEFAULT_KEYS)
++ key = sdata->keys[idx];
++
++ rcu_assign_pointer(sdata->default_key, key);
++
++ if (key)
++ add_todo(key, KEY_FLAG_TODO_DEFKEY);
++}
++
++void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&sdata->local->key_lock, flags);
++ __ieee80211_set_default_key(sdata, idx);
++ spin_unlock_irqrestore(&sdata->local->key_lock, flags);
++}
++
++
++static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
++ struct sta_info *sta,
++ struct ieee80211_key *old,
++ struct ieee80211_key *new)
++{
++ int idx, defkey;
++
++ if (new)
++ list_add(&new->list, &sdata->key_list);
++
++ if (sta) {
++ rcu_assign_pointer(sta->key, new);
++ } else {
++ WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx);
++
++ if (old)
++ idx = old->conf.keyidx;
++ else
++ idx = new->conf.keyidx;
++
++ defkey = old && sdata->default_key == old;
++
++ if (defkey && !new)
++ __ieee80211_set_default_key(sdata, -1);
++
++ rcu_assign_pointer(sdata->keys[idx], new);
++ if (defkey && new)
++ __ieee80211_set_default_key(sdata, new->conf.keyidx);
++ }
++
++ if (old) {
++ /*
++ * We'll use an empty list to indicate that the key
++ * has already been removed.
++ */
++ list_del_init(&old->list);
++ }
++}
++
++struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
+ int idx,
+ size_t key_len,
+ const u8 *key_data)
+@@ -137,10 +282,8 @@ struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
+ key->conf.keyidx = idx;
+ key->conf.keylen = key_len;
+ memcpy(key->conf.key, key_data, key_len);
+-
+- key->local = sdata->local;
+- key->sdata = sdata;
+- key->sta = sta;
++ INIT_LIST_HEAD(&key->list);
++ INIT_LIST_HEAD(&key->todo);
+
+ if (alg == ALG_CCMP) {
+ /*
+@@ -149,22 +292,31 @@ struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
+ */
+ key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data);
+ if (!key->u.ccmp.tfm) {
+- ieee80211_key_free(key);
++ kfree(key);
+ return NULL;
+ }
+ }
+
+- ieee80211_debugfs_key_add(key->local, key);
++ return key;
++}
+
+- /* remove key first */
+- if (sta)
+- ieee80211_key_free(sta->key);
+- else
+- ieee80211_key_free(sdata->keys[idx]);
++void ieee80211_key_link(struct ieee80211_key *key,
++ struct ieee80211_sub_if_data *sdata,
++ struct sta_info *sta)
++{
++ struct ieee80211_key *old_key;
++ unsigned long flags;
++ int idx;
+
+- if (sta) {
+- ieee80211_debugfs_key_sta_link(key, sta);
++ BUG_ON(!sdata);
++ BUG_ON(!key);
+
++ idx = key->conf.keyidx;
++ key->local = sdata->local;
++ key->sdata = sdata;
++ key->sta = sta;
++
++ if (sta) {
+ /*
+ * some hardware cannot handle TKIP with QoS, so
+ * we indicate whether QoS could be in use.
+@@ -175,105 +327,194 @@ struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
+ if (sdata->vif.type == IEEE80211_IF_TYPE_STA) {
+ struct sta_info *ap;
+
++ /*
++ * We're getting a sta pointer in,
++ * so must be under RCU read lock.
++ */
++
+ /* same here, the AP could be using QoS */
+ ap = sta_info_get(key->local, key->sdata->u.sta.bssid);
+ if (ap) {
+ if (ap->flags & WLAN_STA_WME)
+ key->conf.flags |=
+ IEEE80211_KEY_FLAG_WMM_STA;
+- sta_info_put(ap);
+ }
+ }
+ }
+
+- /* enable hwaccel if appropriate */
+- if (netif_running(key->sdata->dev))
+- ieee80211_key_enable_hw_accel(key);
++ spin_lock_irqsave(&sdata->local->key_lock, flags);
+
+ if (sta)
+- rcu_assign_pointer(sta->key, key);
++ old_key = sta->key;
+ else
+- rcu_assign_pointer(sdata->keys[idx], key);
++ old_key = sdata->keys[idx];
+
+- list_add(&key->list, &sdata->key_list);
++ __ieee80211_key_replace(sdata, sta, old_key, key);
+
+- return key;
++ spin_unlock_irqrestore(&sdata->local->key_lock, flags);
++
++ /* free old key later */
++ add_todo(old_key, KEY_FLAG_TODO_DELETE);
++
++ add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS);
++ if (netif_running(sdata->dev))
++ add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD);
++}
++
++static void __ieee80211_key_free(struct ieee80211_key *key)
++{
++ /*
++ * Replace key with nothingness if it was ever used.
++ */
++ if (key->sdata)
++ __ieee80211_key_replace(key->sdata, key->sta,
++ key, NULL);
++
++ add_todo(key, KEY_FLAG_TODO_DELETE);
+ }
+
+ void ieee80211_key_free(struct ieee80211_key *key)
+ {
++ unsigned long flags;
++
+ if (!key)
+ return;
+
+- if (key->sta) {
+- rcu_assign_pointer(key->sta->key, NULL);
+- } else {
+- if (key->sdata->default_key == key)
+- ieee80211_set_default_key(key->sdata, -1);
+- if (key->conf.keyidx >= 0 &&
+- key->conf.keyidx < NUM_DEFAULT_KEYS)
+- rcu_assign_pointer(key->sdata->keys[key->conf.keyidx],
+- NULL);
+- else
+- WARN_ON(1);
+- }
++ spin_lock_irqsave(&key->sdata->local->key_lock, flags);
++ __ieee80211_key_free(key);
++ spin_unlock_irqrestore(&key->sdata->local->key_lock, flags);
++}
+
+- /* wait for all key users to complete */
+- synchronize_rcu();
++/*
++ * To be safe against concurrent manipulations of the list (which shouldn't
++ * actually happen) we need to hold the spinlock. But under the spinlock we
++ * can't actually do much, so we defer processing to the todo list. Then run
++ * the todo list to be sure the operation and possibly previously pending
++ * operations are completed.
++ */
++static void ieee80211_todo_for_each_key(struct ieee80211_sub_if_data *sdata,
++ u32 todo_flags)
++{
++ struct ieee80211_key *key;
++ unsigned long flags;
++
++ might_sleep();
++
++ spin_lock_irqsave(&sdata->local->key_lock, flags);
++ list_for_each_entry(key, &sdata->key_list, list)
++ add_todo(key, todo_flags);
++ spin_unlock_irqrestore(&sdata->local->key_lock, flags);
++
++ ieee80211_key_todo();
++}
++
++void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
++{
++ ASSERT_RTNL();
++
++ if (WARN_ON(!netif_running(sdata->dev)))
++ return;
++
++ ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_ADD);
++}
++
++void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
++{
++ ASSERT_RTNL();
++
++ ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_REMOVE);
++}
++
++static void __ieee80211_key_destroy(struct ieee80211_key *key)
++{
++ if (!key)
++ return;
+
+- /* remove from hwaccel if appropriate */
+ ieee80211_key_disable_hw_accel(key);
+
+ if (key->conf.alg == ALG_CCMP)
+ ieee80211_aes_key_free(key->u.ccmp.tfm);
+ ieee80211_debugfs_key_remove(key);
+
+- list_del(&key->list);
+-
+ kfree(key);
+ }
+
+-void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx)
++static void __ieee80211_key_todo(void)
+ {
+- struct ieee80211_key *key = NULL;
++ struct ieee80211_key *key;
++ bool work_done;
++ u32 todoflags;
+
+- if (idx >= 0 && idx < NUM_DEFAULT_KEYS)
+- key = sdata->keys[idx];
++ /*
++ * NB: sta_info_destroy relies on this!
++ */
++ synchronize_rcu();
+
+- if (sdata->default_key != key) {
+- ieee80211_debugfs_key_remove_default(sdata);
++ spin_lock(&todo_lock);
++ while (!list_empty(&todo_list)) {
++ key = list_first_entry(&todo_list, struct ieee80211_key, todo);
++ list_del_init(&key->todo);
++ todoflags = key->flags & (KEY_FLAG_TODO_ADD_DEBUGFS |
++ KEY_FLAG_TODO_DEFKEY |
++ KEY_FLAG_TODO_HWACCEL_ADD |
++ KEY_FLAG_TODO_HWACCEL_REMOVE |
++ KEY_FLAG_TODO_DELETE);
++ key->flags &= ~todoflags;
++ spin_unlock(&todo_lock);
++
++ work_done = false;
++
++ if (todoflags & KEY_FLAG_TODO_ADD_DEBUGFS) {
++ ieee80211_debugfs_key_add(key);
++ work_done = true;
++ }
++ if (todoflags & KEY_FLAG_TODO_DEFKEY) {
++ ieee80211_debugfs_key_remove_default(key->sdata);
++ ieee80211_debugfs_key_add_default(key->sdata);
++ work_done = true;
++ }
++ if (todoflags & KEY_FLAG_TODO_HWACCEL_ADD) {
++ ieee80211_key_enable_hw_accel(key);
++ work_done = true;
++ }
++ if (todoflags & KEY_FLAG_TODO_HWACCEL_REMOVE) {
++ ieee80211_key_disable_hw_accel(key);
++ work_done = true;
++ }
++ if (todoflags & KEY_FLAG_TODO_DELETE) {
++ __ieee80211_key_destroy(key);
++ work_done = true;
++ }
+
+- rcu_assign_pointer(sdata->default_key, key);
++ WARN_ON(!work_done);
+
+- if (sdata->default_key)
+- ieee80211_debugfs_key_add_default(sdata);
++ spin_lock(&todo_lock);
+ }
++ spin_unlock(&todo_lock);
+ }
+
+-void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
++void ieee80211_key_todo(void)
+ {
+- struct ieee80211_key *key, *tmp;
+-
+- list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
+- ieee80211_key_free(key);
++ ieee80211_key_lock();
++ __ieee80211_key_todo();
++ ieee80211_key_unlock();
+ }
+
+-void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
++void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
+ {
+- struct ieee80211_key *key;
++ struct ieee80211_key *key, *tmp;
++ unsigned long flags;
+
+- WARN_ON(!netif_running(sdata->dev));
+- if (!netif_running(sdata->dev))
+- return;
++ ieee80211_key_lock();
+
+- list_for_each_entry(key, &sdata->key_list, list)
+- ieee80211_key_enable_hw_accel(key);
+-}
++ ieee80211_debugfs_key_remove_default(sdata);
+
+-void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
+-{
+- struct ieee80211_key *key;
++ spin_lock_irqsave(&sdata->local->key_lock, flags);
++ list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
++ __ieee80211_key_free(key);
++ spin_unlock_irqrestore(&sdata->local->key_lock, flags);
+
+- list_for_each_entry(key, &sdata->key_list, list)
+- ieee80211_key_disable_hw_accel(key);
++ __ieee80211_key_todo();
++
++ ieee80211_key_unlock();
+ }
+diff --git a/net/mac80211/key.h b/net/mac80211/key.h
+new file mode 100644
+index 0000000..f52c3df
+--- /dev/null
++++ b/net/mac80211/key.h
+@@ -0,0 +1,161 @@
++/*
++ * Copyright 2002-2004, Instant802 Networks, Inc.
++ * Copyright 2005, Devicescape Software, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef IEEE80211_KEY_H
++#define IEEE80211_KEY_H
++
++#include <linux/types.h>
++#include <linux/list.h>
++#include <linux/crypto.h>
++#include <linux/rcupdate.h>
++#include <net/mac80211.h>
++
++/* ALG_TKIP
++ * struct ieee80211_key::key is encoded as a 256-bit (32 byte) data block:
++ * Temporal Encryption Key (128 bits)
++ * Temporal Authenticator Tx MIC Key (64 bits)
++ * Temporal Authenticator Rx MIC Key (64 bits)
++ */
++
++#define WEP_IV_LEN 4
++#define WEP_ICV_LEN 4
++
++#define ALG_TKIP_KEY_LEN 32
++/* Starting offsets for each key */
++#define ALG_TKIP_TEMP_ENCR_KEY 0
++#define ALG_TKIP_TEMP_AUTH_TX_MIC_KEY 16
++#define ALG_TKIP_TEMP_AUTH_RX_MIC_KEY 24
++#define TKIP_IV_LEN 8
++#define TKIP_ICV_LEN 4
++
++#define ALG_CCMP_KEY_LEN 16
++#define CCMP_HDR_LEN 8
++#define CCMP_MIC_LEN 8
++#define CCMP_TK_LEN 16
++#define CCMP_PN_LEN 6
++
++#define NUM_RX_DATA_QUEUES 17
++
++struct ieee80211_local;
++struct ieee80211_sub_if_data;
++struct sta_info;
++
++/**
++ * enum ieee80211_internal_key_flags - internal key flags
++ *
++ * @KEY_FLAG_UPLOADED_TO_HARDWARE: Indicates that this key is present
++ * in the hardware for TX crypto hardware acceleration.
++ * @KEY_FLAG_TODO_DELETE: Key is marked for deletion and will, after an
++ * RCU grace period, no longer be reachable other than from the
++ * todo list.
++ * @KEY_FLAG_TODO_HWACCEL_ADD: Key needs to be added to hardware acceleration.
++ * @KEY_FLAG_TODO_HWACCEL_REMOVE: Key needs to be removed from hardware
++ * acceleration.
++ * @KEY_FLAG_TODO_DEFKEY: Key is default key and debugfs needs to be updated.
++ * @KEY_FLAG_TODO_ADD_DEBUGFS: Key needs to be added to debugfs.
++ */
++enum ieee80211_internal_key_flags {
++ KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0),
++ KEY_FLAG_TODO_DELETE = BIT(1),
++ KEY_FLAG_TODO_HWACCEL_ADD = BIT(2),
++ KEY_FLAG_TODO_HWACCEL_REMOVE = BIT(3),
++ KEY_FLAG_TODO_DEFKEY = BIT(4),
++ KEY_FLAG_TODO_ADD_DEBUGFS = BIT(5),
++};
++
++struct ieee80211_key {
++ struct ieee80211_local *local;
++ struct ieee80211_sub_if_data *sdata;
++ struct sta_info *sta;
++
++ /* for sdata list */
++ struct list_head list;
++ /* for todo list */
++ struct list_head todo;
++
++ /* protected by todo lock! */
++ unsigned int flags;
++
++ union {
++ struct {
++ /* last used TSC */
++ u32 iv32;
++ u16 iv16;
++ u16 p1k[5];
++ int tx_initialized;
++
++ /* last received RSC */
++ u32 iv32_rx[NUM_RX_DATA_QUEUES];
++ u16 iv16_rx[NUM_RX_DATA_QUEUES];
++ u16 p1k_rx[NUM_RX_DATA_QUEUES][5];
++ int rx_initialized[NUM_RX_DATA_QUEUES];
++ } tkip;
++ struct {
++ u8 tx_pn[6];
++ u8 rx_pn[NUM_RX_DATA_QUEUES][6];
++ struct crypto_cipher *tfm;
++ u32 replays; /* dot11RSNAStatsCCMPReplays */
++ /* scratch buffers for virt_to_page() (crypto API) */
++#ifndef AES_BLOCK_LEN
++#define AES_BLOCK_LEN 16
++#endif
++ u8 tx_crypto_buf[6 * AES_BLOCK_LEN];
++ u8 rx_crypto_buf[6 * AES_BLOCK_LEN];
++ } ccmp;
++ } u;
++
++ /* number of times this key has been used */
++ int tx_rx_count;
++
++#ifdef CONFIG_MAC80211_DEBUGFS
++ struct {
++ struct dentry *stalink;
++ struct dentry *dir;
++ struct dentry *keylen;
++ struct dentry *flags;
++ struct dentry *keyidx;
++ struct dentry *hw_key_idx;
++ struct dentry *tx_rx_count;
++ struct dentry *algorithm;
++ struct dentry *tx_spec;
++ struct dentry *rx_spec;
++ struct dentry *replays;
++ struct dentry *key;
++ struct dentry *ifindex;
++ int cnt;
++ } debugfs;
++#endif
++
++ /*
++ * key config, must be last because it contains key
++ * material as variable length member
++ */
++ struct ieee80211_key_conf conf;
++};
++
++struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
++ int idx,
++ size_t key_len,
++ const u8 *key_data);
++/*
++ * Insert a key into data structures (sdata, sta if necessary)
++ * to make it used, free old key.
++ */
++void ieee80211_key_link(struct ieee80211_key *key,
++ struct ieee80211_sub_if_data *sdata,
++ struct sta_info *sta);
++void ieee80211_key_free(struct ieee80211_key *key);
++void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx);
++void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata);
++void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata);
++void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata);
++
++void ieee80211_key_todo(void);
++
++#endif /* IEEE80211_KEY_H */
+diff --git a/net/mac80211/led.c b/net/mac80211/led.c
+new file mode 100644
+index 0000000..162a643
+--- /dev/null
++++ b/net/mac80211/led.c
+@@ -0,0 +1,161 @@
++/*
++ * Copyright 2006, Johannes Berg <johannes at sipsolutions.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++/* just for IFNAMSIZ */
++#include <linux/if.h>
++#include "led.h"
++
++void ieee80211_led_rx(struct ieee80211_local *local)
++{
++ if (unlikely(!local->rx_led))
++ return;
++ if (local->rx_led_counter++ % 2 == 0)
++ led_trigger_event(local->rx_led, LED_OFF);
++ else
++ led_trigger_event(local->rx_led, LED_FULL);
++}
++
++/* q is 1 if a packet was enqueued, 0 if it has been transmitted */
++void ieee80211_led_tx(struct ieee80211_local *local, int q)
++{
++ if (unlikely(!local->tx_led))
++ return;
++ /* not sure how this is supposed to work ... */
++ local->tx_led_counter += 2*q-1;
++ if (local->tx_led_counter % 2 == 0)
++ led_trigger_event(local->tx_led, LED_OFF);
++ else
++ led_trigger_event(local->tx_led, LED_FULL);
++}
++
++void ieee80211_led_assoc(struct ieee80211_local *local, bool associated)
++{
++ if (unlikely(!local->assoc_led))
++ return;
++ if (associated)
++ led_trigger_event(local->assoc_led, LED_FULL);
++ else
++ led_trigger_event(local->assoc_led, LED_OFF);
++}
++
++void ieee80211_led_radio(struct ieee80211_local *local, bool enabled)
++{
++ if (unlikely(!local->radio_led))
++ return;
++ if (enabled)
++ led_trigger_event(local->radio_led, LED_FULL);
++ else
++ led_trigger_event(local->radio_led, LED_OFF);
++}
++
++void ieee80211_led_init(struct ieee80211_local *local)
++{
++ local->rx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
++ if (local->rx_led) {
++ snprintf(local->rx_led_name, sizeof(local->rx_led_name),
++ "%srx", wiphy_name(local->hw.wiphy));
++ local->rx_led->name = local->rx_led_name;
++ if (led_trigger_register(local->rx_led)) {
++ kfree(local->rx_led);
++ local->rx_led = NULL;
++ }
++ }
++
++ local->tx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
++ if (local->tx_led) {
++ snprintf(local->tx_led_name, sizeof(local->tx_led_name),
++ "%stx", wiphy_name(local->hw.wiphy));
++ local->tx_led->name = local->tx_led_name;
++ if (led_trigger_register(local->tx_led)) {
++ kfree(local->tx_led);
++ local->tx_led = NULL;
++ }
++ }
++
++ local->assoc_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
++ if (local->assoc_led) {
++ snprintf(local->assoc_led_name, sizeof(local->assoc_led_name),
++ "%sassoc", wiphy_name(local->hw.wiphy));
++ local->assoc_led->name = local->assoc_led_name;
++ if (led_trigger_register(local->assoc_led)) {
++ kfree(local->assoc_led);
++ local->assoc_led = NULL;
++ }
++ }
++
++ local->radio_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
++ if (local->radio_led) {
++ snprintf(local->radio_led_name, sizeof(local->radio_led_name),
++ "%sradio", wiphy_name(local->hw.wiphy));
++ local->radio_led->name = local->radio_led_name;
++ if (led_trigger_register(local->radio_led)) {
++ kfree(local->radio_led);
++ local->radio_led = NULL;
++ }
++ }
++}
++
++void ieee80211_led_exit(struct ieee80211_local *local)
++{
++ if (local->radio_led) {
++ led_trigger_unregister(local->radio_led);
++ kfree(local->radio_led);
++ }
++ if (local->assoc_led) {
++ led_trigger_unregister(local->assoc_led);
++ kfree(local->assoc_led);
++ }
++ if (local->tx_led) {
++ led_trigger_unregister(local->tx_led);
++ kfree(local->tx_led);
++ }
++ if (local->rx_led) {
++ led_trigger_unregister(local->rx_led);
++ kfree(local->rx_led);
++ }
++}
++
++char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw)
++{
++ struct ieee80211_local *local = hw_to_local(hw);
++
++ if (local->radio_led)
++ return local->radio_led_name;
++ return NULL;
++}
++EXPORT_SYMBOL(__ieee80211_get_radio_led_name);
++
++char *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw)
++{
++ struct ieee80211_local *local = hw_to_local(hw);
++
++ if (local->assoc_led)
++ return local->assoc_led_name;
++ return NULL;
++}
++EXPORT_SYMBOL(__ieee80211_get_assoc_led_name);
++
++char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw)
++{
++ struct ieee80211_local *local = hw_to_local(hw);
++
++ if (local->tx_led)
++ return local->tx_led_name;
++ return NULL;
++}
++EXPORT_SYMBOL(__ieee80211_get_tx_led_name);
++
++char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw)
++{
++ struct ieee80211_local *local = hw_to_local(hw);
++
++ if (local->rx_led)
++ return local->rx_led_name;
++ return NULL;
++}
++EXPORT_SYMBOL(__ieee80211_get_rx_led_name);
+diff --git a/net/mac80211/led.h b/net/mac80211/led.h
+new file mode 100644
+index 0000000..77b1e1b
+--- /dev/null
++++ b/net/mac80211/led.h
+@@ -0,0 +1,44 @@
++/*
++ * Copyright 2006, Johannes Berg <johannes at sipsolutions.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/list.h>
++#include <linux/spinlock.h>
++#include <linux/leds.h>
++#include "ieee80211_i.h"
++
++#ifdef CONFIG_MAC80211_LEDS
++extern void ieee80211_led_rx(struct ieee80211_local *local);
++extern void ieee80211_led_tx(struct ieee80211_local *local, int q);
++extern void ieee80211_led_assoc(struct ieee80211_local *local,
++ bool associated);
++extern void ieee80211_led_radio(struct ieee80211_local *local,
++ bool enabled);
++extern void ieee80211_led_init(struct ieee80211_local *local);
++extern void ieee80211_led_exit(struct ieee80211_local *local);
++#else
++static inline void ieee80211_led_rx(struct ieee80211_local *local)
++{
++}
++static inline void ieee80211_led_tx(struct ieee80211_local *local, int q)
++{
++}
++static inline void ieee80211_led_assoc(struct ieee80211_local *local,
++ bool associated)
++{
++}
++static inline void ieee80211_led_radio(struct ieee80211_local *local,
++ bool enabled)
++{
++}
++static inline void ieee80211_led_init(struct ieee80211_local *local)
++{
++}
++static inline void ieee80211_led_exit(struct ieee80211_local *local)
++{
++}
++#endif
+diff --git a/net/mac80211/main.c b/net/mac80211/main.c
+new file mode 100644
+index 0000000..e9a9789
+--- /dev/null
++++ b/net/mac80211/main.c
+@@ -0,0 +1,1891 @@
++/*
++ * Copyright 2002-2005, Instant802 Networks, Inc.
++ * Copyright 2005-2006, Devicescape Software, Inc.
++ * Copyright 2006-2007 Jiri Benc <jbenc at suse.cz>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <net/mac80211.h>
++#include <net/ieee80211_radiotap.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/netdevice.h>
++#include <linux/types.h>
++#include <linux/slab.h>
++#include <linux/skbuff.h>
++#include <linux/etherdevice.h>
++#include <linux/if_arp.h>
++#include <linux/wireless.h>
++#include <linux/rtnetlink.h>
++#include <linux/bitmap.h>
++#include <net/net_namespace.h>
++#include <net/cfg80211.h>
++
++#include "ieee80211_i.h"
++#include "rate.h"
++#include "mesh.h"
++#include "wep.h"
++#include "wme.h"
++#include "aes_ccm.h"
++#include "led.h"
++#include "cfg.h"
++#include "debugfs.h"
++#include "debugfs_netdev.h"
++
++#define SUPP_MCS_SET_LEN 16
++
++/*
++ * For seeing transmitted packets on monitor interfaces
++ * we have a radiotap header too.
++ */
++struct ieee80211_tx_status_rtap_hdr {
++ struct ieee80211_radiotap_header hdr;
++ __le16 tx_flags;
++ u8 data_retries;
++} __attribute__ ((packed));
++
++/* common interface routines */
++
++static int header_parse_80211(const struct sk_buff *skb, unsigned char *haddr)
++{
++ memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */
++ return ETH_ALEN;
++}
++
++/* must be called under mdev tx lock */
++static void ieee80211_configure_filter(struct ieee80211_local *local)
++{
++ unsigned int changed_flags;
++ unsigned int new_flags = 0;
++
++ if (atomic_read(&local->iff_promiscs))
++ new_flags |= FIF_PROMISC_IN_BSS;
++
++ if (atomic_read(&local->iff_allmultis))
++ new_flags |= FIF_ALLMULTI;
++
++ if (local->monitors)
++ new_flags |= FIF_BCN_PRBRESP_PROMISC;
++
++ if (local->fif_fcsfail)
++ new_flags |= FIF_FCSFAIL;
++
++ if (local->fif_plcpfail)
++ new_flags |= FIF_PLCPFAIL;
++
++ if (local->fif_control)
++ new_flags |= FIF_CONTROL;
++
++ if (local->fif_other_bss)
++ new_flags |= FIF_OTHER_BSS;
++
++ changed_flags = local->filter_flags ^ new_flags;
++
++ /* be a bit nasty */
++ new_flags |= (1<<31);
++
++ local->ops->configure_filter(local_to_hw(local),
++ changed_flags, &new_flags,
++ local->mdev->mc_count,
++ local->mdev->mc_list);
++
++ WARN_ON(new_flags & (1<<31));
++
++ local->filter_flags = new_flags & ~(1<<31);
++}
++
++/* master interface */
++
++static int ieee80211_master_open(struct net_device *dev)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sub_if_data *sdata;
++ int res = -EOPNOTSUPP;
++
++ /* we hold the RTNL here so can safely walk the list */
++ list_for_each_entry(sdata, &local->interfaces, list) {
++ if (sdata->dev != dev && netif_running(sdata->dev)) {
++ res = 0;
++ break;
++ }
++ }
++ return res;
++}
++
++static int ieee80211_master_stop(struct net_device *dev)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sub_if_data *sdata;
++
++ /* we hold the RTNL here so can safely walk the list */
++ list_for_each_entry(sdata, &local->interfaces, list)
++ if (sdata->dev != dev && netif_running(sdata->dev))
++ dev_close(sdata->dev);
++
++ return 0;
++}
++
++static void ieee80211_master_set_multicast_list(struct net_device *dev)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++ ieee80211_configure_filter(local);
++}
++
++/* regular interfaces */
++
++static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
++{
++ int meshhdrlen;
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++ meshhdrlen = (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) ? 5 : 0;
++
++ /* FIX: what would be proper limits for MTU?
++ * This interface uses 802.3 frames. */
++ if (new_mtu < 256 ||
++ new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) {
++ printk(KERN_WARNING "%s: invalid MTU %d\n",
++ dev->name, new_mtu);
++ return -EINVAL;
++ }
++
++#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
++ printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu);
++#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
++ dev->mtu = new_mtu;
++ return 0;
++}
++
++static inline int identical_mac_addr_allowed(int type1, int type2)
++{
++ return (type1 == IEEE80211_IF_TYPE_MNTR ||
++ type2 == IEEE80211_IF_TYPE_MNTR ||
++ (type1 == IEEE80211_IF_TYPE_AP &&
++ type2 == IEEE80211_IF_TYPE_WDS) ||
++ (type1 == IEEE80211_IF_TYPE_WDS &&
++ (type2 == IEEE80211_IF_TYPE_WDS ||
++ type2 == IEEE80211_IF_TYPE_AP)) ||
++ (type1 == IEEE80211_IF_TYPE_AP &&
++ type2 == IEEE80211_IF_TYPE_VLAN) ||
++ (type1 == IEEE80211_IF_TYPE_VLAN &&
++ (type2 == IEEE80211_IF_TYPE_AP ||
++ type2 == IEEE80211_IF_TYPE_VLAN)));
++}
++
++static int ieee80211_open(struct net_device *dev)
++{
++ struct ieee80211_sub_if_data *sdata, *nsdata;
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_if_init_conf conf;
++ int res;
++ bool need_hw_reconfig = 0;
++ struct sta_info *sta;
++
++ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++ /* we hold the RTNL here so can safely walk the list */
++ list_for_each_entry(nsdata, &local->interfaces, list) {
++ struct net_device *ndev = nsdata->dev;
++
++ if (ndev != dev && ndev != local->mdev && netif_running(ndev)) {
++ /*
++ * Allow only a single IBSS interface to be up at any
++ * time. This is restricted because beacon distribution
++ * cannot work properly if both are in the same IBSS.
++ *
++ * To remove this restriction we'd have to disallow them
++ * from setting the same SSID on different IBSS interfaces
++ * belonging to the same hardware. Then, however, we're
++ * faced with having to adopt two different TSF timers...
++ */
++ if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
++ nsdata->vif.type == IEEE80211_IF_TYPE_IBSS)
++ return -EBUSY;
++
++ /*
++ * Disallow multiple IBSS/STA mode interfaces.
++ *
++ * This is a technical restriction, it is possible although
++ * most likely not IEEE 802.11 compliant to have multiple
++ * STAs with just a single hardware (the TSF timer will not
++ * be adjusted properly.)
++ *
++ * However, because mac80211 uses the master device's BSS
++ * information for each STA/IBSS interface, doing this will
++ * currently corrupt that BSS information completely, unless,
++ * a not very useful case, both STAs are associated to the
++ * same BSS.
++ *
++ * To remove this restriction, the BSS information needs to
++ * be embedded in the STA/IBSS mode sdata instead of using
++ * the master device's BSS structure.
++ */
++ if ((sdata->vif.type == IEEE80211_IF_TYPE_STA ||
++ sdata->vif.type == IEEE80211_IF_TYPE_IBSS) &&
++ (nsdata->vif.type == IEEE80211_IF_TYPE_STA ||
++ nsdata->vif.type == IEEE80211_IF_TYPE_IBSS))
++ return -EBUSY;
++
++ /*
++ * The remaining checks are only performed for interfaces
++ * with the same MAC address.
++ */
++ if (compare_ether_addr(dev->dev_addr, ndev->dev_addr))
++ continue;
++
++ /*
++ * check whether it may have the same address
++ */
++ if (!identical_mac_addr_allowed(sdata->vif.type,
++ nsdata->vif.type))
++ return -ENOTUNIQ;
++
++ /*
++ * can only add VLANs to enabled APs
++ */
++ if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN &&
++ nsdata->vif.type == IEEE80211_IF_TYPE_AP)
++ sdata->u.vlan.ap = nsdata;
++ }
++ }
++
++ switch (sdata->vif.type) {
++ case IEEE80211_IF_TYPE_WDS:
++ if (is_zero_ether_addr(sdata->u.wds.remote_addr))
++ return -ENOLINK;
++
++ /* Create STA entry for the WDS peer */
++ sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
++ GFP_KERNEL);
++ if (!sta)
++ return -ENOMEM;
++
++ sta->flags |= WLAN_STA_AUTHORIZED;
++
++ res = sta_info_insert(sta);
++ if (res) {
++ /* STA has been freed */
++ return res;
++ }
++ break;
++ case IEEE80211_IF_TYPE_VLAN:
++ if (!sdata->u.vlan.ap)
++ return -ENOLINK;
++ break;
++ case IEEE80211_IF_TYPE_AP:
++ case IEEE80211_IF_TYPE_STA:
++ case IEEE80211_IF_TYPE_MNTR:
++ case IEEE80211_IF_TYPE_IBSS:
++ case IEEE80211_IF_TYPE_MESH_POINT:
++ /* no special treatment */
++ break;
++ case IEEE80211_IF_TYPE_INVALID:
++ /* cannot happen */
++ WARN_ON(1);
++ break;
++ }
++
++ if (local->open_count == 0) {
++ res = 0;
++ if (local->ops->start)
++ res = local->ops->start(local_to_hw(local));
++ if (res)
++ return res;
++ need_hw_reconfig = 1;
++ ieee80211_led_radio(local, local->hw.conf.radio_enabled);
++ }
++
++ switch (sdata->vif.type) {
++ case IEEE80211_IF_TYPE_VLAN:
++ list_add(&sdata->u.vlan.list, &sdata->u.vlan.ap->u.ap.vlans);
++ /* no need to tell driver */
++ break;
++ case IEEE80211_IF_TYPE_MNTR:
++ if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) {
++ local->cooked_mntrs++;
++ break;
++ }
++
++ /* must be before the call to ieee80211_configure_filter */
++ local->monitors++;
++ if (local->monitors == 1)
++ local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
++
++ if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
++ local->fif_fcsfail++;
++ if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL)
++ local->fif_plcpfail++;
++ if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL)
++ local->fif_control++;
++ if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
++ local->fif_other_bss++;
++
++ netif_tx_lock_bh(local->mdev);
++ ieee80211_configure_filter(local);
++ netif_tx_unlock_bh(local->mdev);
++ break;
++ case IEEE80211_IF_TYPE_STA:
++ case IEEE80211_IF_TYPE_IBSS:
++ sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET;
++ /* fall through */
++ default:
++ conf.vif = &sdata->vif;
++ conf.type = sdata->vif.type;
++ conf.mac_addr = dev->dev_addr;
++ res = local->ops->add_interface(local_to_hw(local), &conf);
++ if (res && !local->open_count && local->ops->stop)
++ local->ops->stop(local_to_hw(local));
++ if (res)
++ return res;
++
++ ieee80211_if_config(dev);
++ ieee80211_reset_erp_info(dev);
++ ieee80211_enable_keys(sdata);
++
++ if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
++ !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME))
++ netif_carrier_off(dev);
++ else
++ netif_carrier_on(dev);
++ }
++
++ if (local->open_count == 0) {
++ res = dev_open(local->mdev);
++ WARN_ON(res);
++ tasklet_enable(&local->tx_pending_tasklet);
++ tasklet_enable(&local->tasklet);
++ }
++
++ /*
++ * set_multicast_list will be invoked by the networking core
++ * which will check whether any increments here were done in
++ * error and sync them down to the hardware as filter flags.
++ */
++ if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
++ atomic_inc(&local->iff_allmultis);
++
++ if (sdata->flags & IEEE80211_SDATA_PROMISC)
++ atomic_inc(&local->iff_promiscs);
++
++ local->open_count++;
++ if (need_hw_reconfig)
++ ieee80211_hw_config(local);
++
++ /*
++ * ieee80211_sta_work is disabled while network interface
++ * is down. Therefore, some configuration changes may not
++ * yet be effective. Trigger execution of ieee80211_sta_work
++ * to fix this.
++ */
++ if(sdata->vif.type == IEEE80211_IF_TYPE_STA ||
++ sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
++ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++ queue_work(local->hw.workqueue, &ifsta->work);
++ }
++
++ netif_start_queue(dev);
++
++ return 0;
++}
++
++static int ieee80211_stop(struct net_device *dev)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_local *local = sdata->local;
++ struct ieee80211_if_init_conf conf;
++ struct sta_info *sta;
++
++ /*
++ * Stop TX on this interface first.
++ */
++ netif_stop_queue(dev);
++
++ /*
++ * Now delete all active aggregation sessions.
++ */
++ rcu_read_lock();
++
++ list_for_each_entry_rcu(sta, &local->sta_list, list) {
++ if (sta->sdata == sdata)
++ ieee80211_sta_tear_down_BA_sessions(dev, sta->addr);
++ }
++
++ rcu_read_unlock();
++
++ /*
++ * Remove all stations associated with this interface.
++ *
++ * This must be done before calling ops->remove_interface()
++ * because otherwise we can later invoke ops->sta_notify()
++ * whenever the STAs are removed, and that invalidates driver
++ * assumptions about always getting a vif pointer that is valid
++ * (because if we remove a STA after ops->remove_interface()
++ * the driver will have removed the vif info already!)
++ *
++ * We could relax this and only unlink the stations from the
++ * hash table and list but keep them on a per-sdata list that
++ * will be inserted back again when the interface is brought
++ * up again, but I don't currently see a use case for that,
++ * except with WDS which gets a STA entry created when it is
++ * brought up.
++ */
++ sta_info_flush(local, sdata);
++
++ /*
++ * Don't count this interface for promisc/allmulti while it
++ * is down. dev_mc_unsync() will invoke set_multicast_list
++ * on the master interface which will sync these down to the
++ * hardware as filter flags.
++ */
++ if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
++ atomic_dec(&local->iff_allmultis);
++
++ if (sdata->flags & IEEE80211_SDATA_PROMISC)
++ atomic_dec(&local->iff_promiscs);
++
++ dev_mc_unsync(local->mdev, dev);
++
++ /* APs need special treatment */
++ if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
++ struct ieee80211_sub_if_data *vlan, *tmp;
++ struct beacon_data *old_beacon = sdata->u.ap.beacon;
++
++ /* remove beacon */
++ rcu_assign_pointer(sdata->u.ap.beacon, NULL);
++ synchronize_rcu();
++ kfree(old_beacon);
++
++ /* down all dependent devices, that is VLANs */
++ list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans,
++ u.vlan.list)
++ dev_close(vlan->dev);
++ WARN_ON(!list_empty(&sdata->u.ap.vlans));
++ }
++
++ local->open_count--;
++
++ switch (sdata->vif.type) {
++ case IEEE80211_IF_TYPE_VLAN:
++ list_del(&sdata->u.vlan.list);
++ sdata->u.vlan.ap = NULL;
++ /* no need to tell driver */
++ break;
++ case IEEE80211_IF_TYPE_MNTR:
++ if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) {
++ local->cooked_mntrs--;
++ break;
++ }
++
++ local->monitors--;
++ if (local->monitors == 0)
++ local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
++
++ if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
++ local->fif_fcsfail--;
++ if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL)
++ local->fif_plcpfail--;
++ if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL)
++ local->fif_control--;
++ if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
++ local->fif_other_bss--;
++
++ netif_tx_lock_bh(local->mdev);
++ ieee80211_configure_filter(local);
++ netif_tx_unlock_bh(local->mdev);
++ break;
++ case IEEE80211_IF_TYPE_MESH_POINT:
++ case IEEE80211_IF_TYPE_STA:
++ case IEEE80211_IF_TYPE_IBSS:
++ sdata->u.sta.state = IEEE80211_DISABLED;
++ del_timer_sync(&sdata->u.sta.timer);
++ /*
++ * When we get here, the interface is marked down.
++ * Call synchronize_rcu() to wait for the RX path
++ * should it be using the interface and enqueuing
++ * frames at this very time on another CPU.
++ */
++ synchronize_rcu();
++ skb_queue_purge(&sdata->u.sta.skb_queue);
++
++ if (local->scan_dev == sdata->dev) {
++ if (!local->ops->hw_scan) {
++ local->sta_sw_scanning = 0;
++ cancel_delayed_work(&local->scan_work);
++ } else
++ local->sta_hw_scanning = 0;
++ }
++
++ flush_workqueue(local->hw.workqueue);
++
++ sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
++ kfree(sdata->u.sta.extra_ie);
++ sdata->u.sta.extra_ie = NULL;
++ sdata->u.sta.extra_ie_len = 0;
++ /* fall through */
++ default:
++ conf.vif = &sdata->vif;
++ conf.type = sdata->vif.type;
++ conf.mac_addr = dev->dev_addr;
++ /* disable all keys for as long as this netdev is down */
++ ieee80211_disable_keys(sdata);
++ local->ops->remove_interface(local_to_hw(local), &conf);
++ }
++
++ if (local->open_count == 0) {
++ if (netif_running(local->mdev))
++ dev_close(local->mdev);
++
++ if (local->ops->stop)
++ local->ops->stop(local_to_hw(local));
++
++ ieee80211_led_radio(local, 0);
++
++ tasklet_disable(&local->tx_pending_tasklet);
++ tasklet_disable(&local->tasklet);
++ }
++
++ return 0;
++}
++
++int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
++{
++ struct ieee80211_local *local = hw_to_local(hw);
++ struct sta_info *sta;
++ struct ieee80211_sub_if_data *sdata;
++ u16 start_seq_num = 0;
++ u8 *state;
++ int ret;
++ DECLARE_MAC_BUF(mac);
++
++ if (tid >= STA_TID_NUM)
++ return -EINVAL;
++
++#ifdef CONFIG_MAC80211_HT_DEBUG
++ printk(KERN_DEBUG "Open BA session requested for %s tid %u\n",
++ print_mac(mac, ra), tid);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++
++ rcu_read_lock();
++
++ sta = sta_info_get(local, ra);
++ if (!sta) {
++ printk(KERN_DEBUG "Could not find the station\n");
++ rcu_read_unlock();
++ return -ENOENT;
++ }
++
++ spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
++
++ /* we have tried too many times, receiver does not want A-MPDU */
++ if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) {
++ ret = -EBUSY;
++ goto start_ba_exit;
++ }
++
++ state = &sta->ampdu_mlme.tid_state_tx[tid];
++ /* check if the TID is not in aggregation flow already */
++ if (*state != HT_AGG_STATE_IDLE) {
++#ifdef CONFIG_MAC80211_HT_DEBUG
++ printk(KERN_DEBUG "BA request denied - session is not "
++ "idle on tid %u\n", tid);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++ ret = -EAGAIN;
++ goto start_ba_exit;
++ }
++
++ /* prepare A-MPDU MLME for Tx aggregation */
++ sta->ampdu_mlme.tid_tx[tid] =
++ kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC);
++ if (!sta->ampdu_mlme.tid_tx[tid]) {
++ if (net_ratelimit())
++ printk(KERN_ERR "allocate tx mlme to tid %d failed\n",
++ tid);
++ ret = -ENOMEM;
++ goto start_ba_exit;
++ }
++ /* Tx timer */
++ sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function =
++ sta_addba_resp_timer_expired;
++ sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data =
++ (unsigned long)&sta->timer_to_tid[tid];
++ init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
++
++ /* ensure that TX flow won't interrupt us
++ * until the end of the call to requeue function */
++ spin_lock_bh(&local->mdev->queue_lock);
++
++ /* create a new queue for this aggregation */
++ ret = ieee80211_ht_agg_queue_add(local, sta, tid);
++
++ /* case no queue is available to aggregation
++ * don't switch to aggregation */
++ if (ret) {
++#ifdef CONFIG_MAC80211_HT_DEBUG
++ printk(KERN_DEBUG "BA request denied - queue unavailable for"
++ " tid %d\n", tid);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++ goto start_ba_err;
++ }
++ sdata = sta->sdata;
++
++ /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the
++ * call back right away, it must see that the flow has begun */
++ *state |= HT_ADDBA_REQUESTED_MSK;
++
++ if (local->ops->ampdu_action)
++ ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START,
++ ra, tid, &start_seq_num);
++
++ if (ret) {
++ /* No need to requeue the packets in the agg queue, since we
++ * held the tx lock: no packet could be enqueued to the newly
++ * allocated queue */
++ ieee80211_ht_agg_queue_remove(local, sta, tid, 0);
++#ifdef CONFIG_MAC80211_HT_DEBUG
++ printk(KERN_DEBUG "BA request denied - HW unavailable for"
++ " tid %d\n", tid);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++ *state = HT_AGG_STATE_IDLE;
++ goto start_ba_err;
++ }
++
++ /* Will put all the packets in the new SW queue */
++ ieee80211_requeue(local, ieee802_1d_to_ac[tid]);
++ spin_unlock_bh(&local->mdev->queue_lock);
++
++ /* send an addBA request */
++ sta->ampdu_mlme.dialog_token_allocator++;
++ sta->ampdu_mlme.tid_tx[tid]->dialog_token =
++ sta->ampdu_mlme.dialog_token_allocator;
++ sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num;
++
++ ieee80211_send_addba_request(sta->sdata->dev, ra, tid,
++ sta->ampdu_mlme.tid_tx[tid]->dialog_token,
++ sta->ampdu_mlme.tid_tx[tid]->ssn,
++ 0x40, 5000);
++
++ /* activate the timer for the recipient's addBA response */
++ sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires =
++ jiffies + ADDBA_RESP_INTERVAL;
++ add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
++ printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid);
++ goto start_ba_exit;
++
++start_ba_err:
++ kfree(sta->ampdu_mlme.tid_tx[tid]);
++ sta->ampdu_mlme.tid_tx[tid] = NULL;
++ spin_unlock_bh(&local->mdev->queue_lock);
++ ret = -EBUSY;
++start_ba_exit:
++ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++ rcu_read_unlock();
++ return ret;
++}
++EXPORT_SYMBOL(ieee80211_start_tx_ba_session);
++
++int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
++ u8 *ra, u16 tid,
++ enum ieee80211_back_parties initiator)
++{
++ struct ieee80211_local *local = hw_to_local(hw);
++ struct sta_info *sta;
++ u8 *state;
++ int ret = 0;
++ DECLARE_MAC_BUF(mac);
++
++ if (tid >= STA_TID_NUM)
++ return -EINVAL;
++
++ rcu_read_lock();
++ sta = sta_info_get(local, ra);
++ if (!sta) {
++ rcu_read_unlock();
++ return -ENOENT;
++ }
++
++ /* check if the TID is in aggregation */
++ state = &sta->ampdu_mlme.tid_state_tx[tid];
++ spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
++
++ if (*state != HT_AGG_STATE_OPERATIONAL) {
++ ret = -ENOENT;
++ goto stop_BA_exit;
++ }
++
++#ifdef CONFIG_MAC80211_HT_DEBUG
++ printk(KERN_DEBUG "Tx BA session stop requested for %s tid %u\n",
++ print_mac(mac, ra), tid);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++
++ ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]);
++
++ *state = HT_AGG_STATE_REQ_STOP_BA_MSK |
++ (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
++
++ if (local->ops->ampdu_action)
++ ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_STOP,
++ ra, tid, NULL);
++
++ /* case HW denied going back to legacy */
++ if (ret) {
++ WARN_ON(ret != -EBUSY);
++ *state = HT_AGG_STATE_OPERATIONAL;
++ ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
++ goto stop_BA_exit;
++ }
++
++stop_BA_exit:
++ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++ rcu_read_unlock();
++ return ret;
++}
++EXPORT_SYMBOL(ieee80211_stop_tx_ba_session);
++
++void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
++{
++ struct ieee80211_local *local = hw_to_local(hw);
++ struct sta_info *sta;
++ u8 *state;
++ DECLARE_MAC_BUF(mac);
++
++ if (tid >= STA_TID_NUM) {
++ printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
++ tid, STA_TID_NUM);
++ return;
++ }
++
++ rcu_read_lock();
++ sta = sta_info_get(local, ra);
++ if (!sta) {
++ rcu_read_unlock();
++ printk(KERN_DEBUG "Could not find station: %s\n",
++ print_mac(mac, ra));
++ return;
++ }
++
++ state = &sta->ampdu_mlme.tid_state_tx[tid];
++ spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
++
++ if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
++ printk(KERN_DEBUG "addBA was not requested yet, state is %d\n",
++ *state);
++ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++ rcu_read_unlock();
++ return;
++ }
++
++ WARN_ON_ONCE(*state & HT_ADDBA_DRV_READY_MSK);
++
++ *state |= HT_ADDBA_DRV_READY_MSK;
++
++ if (*state == HT_AGG_STATE_OPERATIONAL) {
++ printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid);
++ ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
++ }
++ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++ rcu_read_unlock();
++}
++EXPORT_SYMBOL(ieee80211_start_tx_ba_cb);
++
++void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
++{
++ struct ieee80211_local *local = hw_to_local(hw);
++ struct sta_info *sta;
++ u8 *state;
++ int agg_queue;
++ DECLARE_MAC_BUF(mac);
++
++ if (tid >= STA_TID_NUM) {
++ printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
++ tid, STA_TID_NUM);
++ return;
++ }
++
++#ifdef CONFIG_MAC80211_HT_DEBUG
++ printk(KERN_DEBUG "Stopping Tx BA session for %s tid %d\n",
++ print_mac(mac, ra), tid);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++
++ rcu_read_lock();
++ sta = sta_info_get(local, ra);
++ if (!sta) {
++ printk(KERN_DEBUG "Could not find station: %s\n",
++ print_mac(mac, ra));
++ rcu_read_unlock();
++ return;
++ }
++ state = &sta->ampdu_mlme.tid_state_tx[tid];
++
++ spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
++ if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) {
++ printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n");
++ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++ rcu_read_unlock();
++ return;
++ }
++
++ if (*state & HT_AGG_STATE_INITIATOR_MSK)
++ ieee80211_send_delba(sta->sdata->dev, ra, tid,
++ WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
++
++ agg_queue = sta->tid_to_tx_q[tid];
++
++ /* avoid ordering issues: we are the only one that can modify
++ * the content of the qdiscs */
++ spin_lock_bh(&local->mdev->queue_lock);
++ /* remove the queue for this aggregation */
++ ieee80211_ht_agg_queue_remove(local, sta, tid, 1);
++ spin_unlock_bh(&local->mdev->queue_lock);
++
++ /* we just requeued the all the frames that were in the removed
++ * queue, and since we might miss a softirq we do netif_schedule.
++ * ieee80211_wake_queue is not used here as this queue is not
++ * necessarily stopped */
++ netif_schedule(local->mdev);
++ *state = HT_AGG_STATE_IDLE;
++ sta->ampdu_mlme.addba_req_num[tid] = 0;
++ kfree(sta->ampdu_mlme.tid_tx[tid]);
++ sta->ampdu_mlme.tid_tx[tid] = NULL;
++ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++
++ rcu_read_unlock();
++}
++EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb);
++
++void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw,
++ const u8 *ra, u16 tid)
++{
++ struct ieee80211_local *local = hw_to_local(hw);
++ struct ieee80211_ra_tid *ra_tid;
++ struct sk_buff *skb = dev_alloc_skb(0);
++
++ if (unlikely(!skb)) {
++ if (net_ratelimit())
++ printk(KERN_WARNING "%s: Not enough memory, "
++ "dropping start BA session", skb->dev->name);
++ return;
++ }
++ ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
++ memcpy(&ra_tid->ra, ra, ETH_ALEN);
++ ra_tid->tid = tid;
++
++ skb->pkt_type = IEEE80211_ADDBA_MSG;
++ skb_queue_tail(&local->skb_queue, skb);
++ tasklet_schedule(&local->tasklet);
++}
++EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe);
++
++void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw,
++ const u8 *ra, u16 tid)
++{
++ struct ieee80211_local *local = hw_to_local(hw);
++ struct ieee80211_ra_tid *ra_tid;
++ struct sk_buff *skb = dev_alloc_skb(0);
++
++ if (unlikely(!skb)) {
++ if (net_ratelimit())
++ printk(KERN_WARNING "%s: Not enough memory, "
++ "dropping stop BA session", skb->dev->name);
++ return;
++ }
++ ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
++ memcpy(&ra_tid->ra, ra, ETH_ALEN);
++ ra_tid->tid = tid;
++
++ skb->pkt_type = IEEE80211_DELBA_MSG;
++ skb_queue_tail(&local->skb_queue, skb);
++ tasklet_schedule(&local->tasklet);
++}
++EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe);
++
++static void ieee80211_set_multicast_list(struct net_device *dev)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ int allmulti, promisc, sdata_allmulti, sdata_promisc;
++
++ allmulti = !!(dev->flags & IFF_ALLMULTI);
++ promisc = !!(dev->flags & IFF_PROMISC);
++ sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI);
++ sdata_promisc = !!(sdata->flags & IEEE80211_SDATA_PROMISC);
++
++ if (allmulti != sdata_allmulti) {
++ if (dev->flags & IFF_ALLMULTI)
++ atomic_inc(&local->iff_allmultis);
++ else
++ atomic_dec(&local->iff_allmultis);
++ sdata->flags ^= IEEE80211_SDATA_ALLMULTI;
++ }
++
++ if (promisc != sdata_promisc) {
++ if (dev->flags & IFF_PROMISC)
++ atomic_inc(&local->iff_promiscs);
++ else
++ atomic_dec(&local->iff_promiscs);
++ sdata->flags ^= IEEE80211_SDATA_PROMISC;
++ }
++
++ dev_mc_sync(local->mdev, dev);
++}
++
++static const struct header_ops ieee80211_header_ops = {
++ .create = eth_header,
++ .parse = header_parse_80211,
++ .rebuild = eth_rebuild_header,
++ .cache = eth_header_cache,
++ .cache_update = eth_header_cache_update,
++};
++
++/* Must not be called for mdev */
++void ieee80211_if_setup(struct net_device *dev)
++{
++ ether_setup(dev);
++ dev->hard_start_xmit = ieee80211_subif_start_xmit;
++ dev->wireless_handlers = &ieee80211_iw_handler_def;
++ dev->set_multicast_list = ieee80211_set_multicast_list;
++ dev->change_mtu = ieee80211_change_mtu;
++ dev->open = ieee80211_open;
++ dev->stop = ieee80211_stop;
++ dev->destructor = ieee80211_if_free;
++}
++
++/* everything else */
++
++static int __ieee80211_if_config(struct net_device *dev,
++ struct sk_buff *beacon,
++ struct ieee80211_tx_control *control)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_if_conf conf;
++
++ if (!local->ops->config_interface || !netif_running(dev))
++ return 0;
++
++ memset(&conf, 0, sizeof(conf));
++ conf.type = sdata->vif.type;
++ if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
++ sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
++ conf.bssid = sdata->u.sta.bssid;
++ conf.ssid = sdata->u.sta.ssid;
++ conf.ssid_len = sdata->u.sta.ssid_len;
++ } else if (ieee80211_vif_is_mesh(&sdata->vif)) {
++ conf.beacon = beacon;
++ ieee80211_start_mesh(dev);
++ } else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
++ conf.ssid = sdata->u.ap.ssid;
++ conf.ssid_len = sdata->u.ap.ssid_len;
++ conf.beacon = beacon;
++ conf.beacon_control = control;
++ }
++ return local->ops->config_interface(local_to_hw(local),
++ &sdata->vif, &conf);
++}
++
++int ieee80211_if_config(struct net_device *dev)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT &&
++ (local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE))
++ return ieee80211_if_config_beacon(dev);
++ return __ieee80211_if_config(dev, NULL, NULL);
++}
++
++int ieee80211_if_config_beacon(struct net_device *dev)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_tx_control control;
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct sk_buff *skb;
++
++ if (!(local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE))
++ return 0;
++ skb = ieee80211_beacon_get(local_to_hw(local), &sdata->vif,
++ &control);
++ if (!skb)
++ return -ENOMEM;
++ return __ieee80211_if_config(dev, skb, &control);
++}
++
++int ieee80211_hw_config(struct ieee80211_local *local)
++{
++ struct ieee80211_channel *chan;
++ int ret = 0;
++
++ if (local->sta_sw_scanning)
++ chan = local->scan_channel;
++ else
++ chan = local->oper_channel;
++
++ local->hw.conf.channel = chan;
++
++ if (!local->hw.conf.power_level)
++ local->hw.conf.power_level = chan->max_power;
++ else
++ local->hw.conf.power_level = min(chan->max_power,
++ local->hw.conf.power_level);
++
++ local->hw.conf.max_antenna_gain = chan->max_antenna_gain;
++
++#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
++ printk(KERN_DEBUG "%s: HW CONFIG: freq=%d\n",
++ wiphy_name(local->hw.wiphy), chan->center_freq);
++#endif
++
++ if (local->open_count)
++ ret = local->ops->config(local_to_hw(local), &local->hw.conf);
++
++ return ret;
++}
++
++/**
++ * ieee80211_handle_ht should be used only after legacy configuration
++ * has been determined namely band, as ht configuration depends upon
++ * the hardware's HT abilities for a _specific_ band.
++ */
++u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht,
++ struct ieee80211_ht_info *req_ht_cap,
++ struct ieee80211_ht_bss_info *req_bss_cap)
++{
++ struct ieee80211_conf *conf = &local->hw.conf;
++ struct ieee80211_supported_band *sband;
++ struct ieee80211_ht_info ht_conf;
++ struct ieee80211_ht_bss_info ht_bss_conf;
++ int i;
++ u32 changed = 0;
++
++ sband = local->hw.wiphy->bands[conf->channel->band];
++
++ /* HT is not supported */
++ if (!sband->ht_info.ht_supported) {
++ conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
++ return 0;
++ }
++
++ memset(&ht_conf, 0, sizeof(struct ieee80211_ht_info));
++ memset(&ht_bss_conf, 0, sizeof(struct ieee80211_ht_bss_info));
++
++ if (enable_ht) {
++ if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE))
++ changed |= BSS_CHANGED_HT;
++
++ conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE;
++ ht_conf.ht_supported = 1;
++
++ ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap;
++ ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS);
++ ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS;
++
++ for (i = 0; i < SUPP_MCS_SET_LEN; i++)
++ ht_conf.supp_mcs_set[i] =
++ sband->ht_info.supp_mcs_set[i] &
++ req_ht_cap->supp_mcs_set[i];
++
++ ht_bss_conf.primary_channel = req_bss_cap->primary_channel;
++ ht_bss_conf.bss_cap = req_bss_cap->bss_cap;
++ ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode;
++
++ ht_conf.ampdu_factor = req_ht_cap->ampdu_factor;
++ ht_conf.ampdu_density = req_ht_cap->ampdu_density;
++
++ /* if bss configuration changed store the new one */
++ if (memcmp(&conf->ht_conf, &ht_conf, sizeof(ht_conf)) ||
++ memcmp(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf))) {
++ changed |= BSS_CHANGED_HT;
++ memcpy(&conf->ht_conf, &ht_conf, sizeof(ht_conf));
++ memcpy(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf));
++ }
++ } else {
++ if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)
++ changed |= BSS_CHANGED_HT;
++ conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
++ }
++
++ return changed;
++}
++
++void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
++ u32 changed)
++{
++ struct ieee80211_local *local = sdata->local;
++
++ if (!changed)
++ return;
++
++ if (local->ops->bss_info_changed)
++ local->ops->bss_info_changed(local_to_hw(local),
++ &sdata->vif,
++ &sdata->bss_conf,
++ changed);
++}
++
++void ieee80211_reset_erp_info(struct net_device *dev)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++ sdata->bss_conf.use_cts_prot = 0;
++ sdata->bss_conf.use_short_preamble = 0;
++ ieee80211_bss_info_change_notify(sdata,
++ BSS_CHANGED_ERP_CTS_PROT |
++ BSS_CHANGED_ERP_PREAMBLE);
++}
++
++void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
++ struct sk_buff *skb,
++ struct ieee80211_tx_status *status)
++{
++ struct ieee80211_local *local = hw_to_local(hw);
++ struct ieee80211_tx_status *saved;
++ int tmp;
++
++ skb->dev = local->mdev;
++ saved = kmalloc(sizeof(struct ieee80211_tx_status), GFP_ATOMIC);
++ if (unlikely(!saved)) {
++ if (net_ratelimit())
++ printk(KERN_WARNING "%s: Not enough memory, "
++ "dropping tx status", skb->dev->name);
++ /* should be dev_kfree_skb_irq, but due to this function being
++ * named _irqsafe instead of just _irq we can't be sure that
++ * people won't call it from non-irq contexts */
++ dev_kfree_skb_any(skb);
++ return;
++ }
++ memcpy(saved, status, sizeof(struct ieee80211_tx_status));
++ /* copy pointer to saved status into skb->cb for use by tasklet */
++ memcpy(skb->cb, &saved, sizeof(saved));
++
++ skb->pkt_type = IEEE80211_TX_STATUS_MSG;
++ skb_queue_tail(status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS ?
++ &local->skb_queue : &local->skb_queue_unreliable, skb);
++ tmp = skb_queue_len(&local->skb_queue) +
++ skb_queue_len(&local->skb_queue_unreliable);
++ while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT &&
++ (skb = skb_dequeue(&local->skb_queue_unreliable))) {
++ memcpy(&saved, skb->cb, sizeof(saved));
++ kfree(saved);
++ dev_kfree_skb_irq(skb);
++ tmp--;
++ I802_DEBUG_INC(local->tx_status_drop);
++ }
++ tasklet_schedule(&local->tasklet);
++}
++EXPORT_SYMBOL(ieee80211_tx_status_irqsafe);
++
++static void ieee80211_tasklet_handler(unsigned long data)
++{
++ struct ieee80211_local *local = (struct ieee80211_local *) data;
++ struct sk_buff *skb;
++ struct ieee80211_rx_status rx_status;
++ struct ieee80211_tx_status *tx_status;
++ struct ieee80211_ra_tid *ra_tid;
++
++ while ((skb = skb_dequeue(&local->skb_queue)) ||
++ (skb = skb_dequeue(&local->skb_queue_unreliable))) {
++ switch (skb->pkt_type) {
++ case IEEE80211_RX_MSG:
++ /* status is in skb->cb */
++ memcpy(&rx_status, skb->cb, sizeof(rx_status));
++ /* Clear skb->pkt_type in order to not confuse kernel
++ * netstack. */
++ skb->pkt_type = 0;
++ __ieee80211_rx(local_to_hw(local), skb, &rx_status);
++ break;
++ case IEEE80211_TX_STATUS_MSG:
++ /* get pointer to saved status out of skb->cb */
++ memcpy(&tx_status, skb->cb, sizeof(tx_status));
++ skb->pkt_type = 0;
++ ieee80211_tx_status(local_to_hw(local),
++ skb, tx_status);
++ kfree(tx_status);
++ break;
++ case IEEE80211_DELBA_MSG:
++ ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
++ ieee80211_stop_tx_ba_cb(local_to_hw(local),
++ ra_tid->ra, ra_tid->tid);
++ dev_kfree_skb(skb);
++ break;
++ case IEEE80211_ADDBA_MSG:
++ ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
++ ieee80211_start_tx_ba_cb(local_to_hw(local),
++ ra_tid->ra, ra_tid->tid);
++ dev_kfree_skb(skb);
++ break ;
++ default: /* should never get here! */
++ printk(KERN_ERR "%s: Unknown message type (%d)\n",
++ wiphy_name(local->hw.wiphy), skb->pkt_type);
++ dev_kfree_skb(skb);
++ break;
++ }
++ }
++}
++
++/* Remove added headers (e.g., QoS control), encryption header/MIC, etc. to
++ * make a prepared TX frame (one that has been given to hw) to look like brand
++ * new IEEE 802.11 frame that is ready to go through TX processing again.
++ * Also, tx_packet_data in cb is restored from tx_control. */
++static void ieee80211_remove_tx_extra(struct ieee80211_local *local,
++ struct ieee80211_key *key,
++ struct sk_buff *skb,
++ struct ieee80211_tx_control *control)
++{
++ int hdrlen, iv_len, mic_len;
++ struct ieee80211_tx_packet_data *pkt_data;
++
++ pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
++ pkt_data->ifindex = vif_to_sdata(control->vif)->dev->ifindex;
++ pkt_data->flags = 0;
++ if (control->flags & IEEE80211_TXCTL_REQ_TX_STATUS)
++ pkt_data->flags |= IEEE80211_TXPD_REQ_TX_STATUS;
++ if (control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)
++ pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT;
++ if (control->flags & IEEE80211_TXCTL_REQUEUE)
++ pkt_data->flags |= IEEE80211_TXPD_REQUEUE;
++ if (control->flags & IEEE80211_TXCTL_EAPOL_FRAME)
++ pkt_data->flags |= IEEE80211_TXPD_EAPOL_FRAME;
++ pkt_data->queue = control->queue;
++
++ hdrlen = ieee80211_get_hdrlen_from_skb(skb);
++
++ if (!key)
++ goto no_key;
++
++ switch (key->conf.alg) {
++ case ALG_WEP:
++ iv_len = WEP_IV_LEN;
++ mic_len = WEP_ICV_LEN;
++ break;
++ case ALG_TKIP:
++ iv_len = TKIP_IV_LEN;
++ mic_len = TKIP_ICV_LEN;
++ break;
++ case ALG_CCMP:
++ iv_len = CCMP_HDR_LEN;
++ mic_len = CCMP_MIC_LEN;
++ break;
++ default:
++ goto no_key;
++ }
++
++ if (skb->len >= mic_len &&
++ !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
++ skb_trim(skb, skb->len - mic_len);
++ if (skb->len >= iv_len && skb->len > hdrlen) {
++ memmove(skb->data + iv_len, skb->data, hdrlen);
++ skb_pull(skb, iv_len);
++ }
++
++no_key:
++ {
++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
++ u16 fc = le16_to_cpu(hdr->frame_control);
++ if ((fc & 0x8C) == 0x88) /* QoS Control Field */ {
++ fc &= ~IEEE80211_STYPE_QOS_DATA;
++ hdr->frame_control = cpu_to_le16(fc);
++ memmove(skb->data + 2, skb->data, hdrlen - 2);
++ skb_pull(skb, 2);
++ }
++ }
++}
++
++static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
++ struct sta_info *sta,
++ struct sk_buff *skb,
++ struct ieee80211_tx_status *status)
++{
++ sta->tx_filtered_count++;
++
++ /*
++ * Clear the TX filter mask for this STA when sending the next
++ * packet. If the STA went to power save mode, this will happen
++ * happen when it wakes up for the next time.
++ */
++ sta->flags |= WLAN_STA_CLEAR_PS_FILT;
++
++ /*
++ * This code races in the following way:
++ *
++ * (1) STA sends frame indicating it will go to sleep and does so
++ * (2) hardware/firmware adds STA to filter list, passes frame up
++ * (3) hardware/firmware processes TX fifo and suppresses a frame
++ * (4) we get TX status before having processed the frame and
++ * knowing that the STA has gone to sleep.
++ *
++ * This is actually quite unlikely even when both those events are
++ * processed from interrupts coming in quickly after one another or
++ * even at the same time because we queue both TX status events and
++ * RX frames to be processed by a tasklet and process them in the
++ * same order that they were received or TX status last. Hence, there
++ * is no race as long as the frame RX is processed before the next TX
++ * status, which drivers can ensure, see below.
++ *
++ * Note that this can only happen if the hardware or firmware can
++ * actually add STAs to the filter list, if this is done by the
++ * driver in response to set_tim() (which will only reduce the race
++ * this whole filtering tries to solve, not completely solve it)
++ * this situation cannot happen.
++ *
++ * To completely solve this race drivers need to make sure that they
++ * (a) don't mix the irq-safe/not irq-safe TX status/RX processing
++ * functions and
++ * (b) always process RX events before TX status events if ordering
++ * can be unknown, for example with different interrupt status
++ * bits.
++ */
++ if (sta->flags & WLAN_STA_PS &&
++ skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) {
++ ieee80211_remove_tx_extra(local, sta->key, skb,
++ &status->control);
++ skb_queue_tail(&sta->tx_filtered, skb);
++ return;
++ }
++
++ if (!(sta->flags & WLAN_STA_PS) &&
++ !(status->control.flags & IEEE80211_TXCTL_REQUEUE)) {
++ /* Software retry the packet once */
++ status->control.flags |= IEEE80211_TXCTL_REQUEUE;
++ ieee80211_remove_tx_extra(local, sta->key, skb,
++ &status->control);
++ dev_queue_xmit(skb);
++ return;
++ }
++
++ if (net_ratelimit())
++ printk(KERN_DEBUG "%s: dropped TX filtered frame, "
++ "queue_len=%d PS=%d @%lu\n",
++ wiphy_name(local->hw.wiphy),
++ skb_queue_len(&sta->tx_filtered),
++ !!(sta->flags & WLAN_STA_PS), jiffies);
++ dev_kfree_skb(skb);
++}
++
++void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
++ struct ieee80211_tx_status *status)
++{
++ struct sk_buff *skb2;
++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
++ struct ieee80211_local *local = hw_to_local(hw);
++ u16 frag, type;
++ struct ieee80211_tx_status_rtap_hdr *rthdr;
++ struct ieee80211_sub_if_data *sdata;
++ struct net_device *prev_dev = NULL;
++
++ if (!status) {
++ printk(KERN_ERR
++ "%s: ieee80211_tx_status called with NULL status\n",
++ wiphy_name(local->hw.wiphy));
++ dev_kfree_skb(skb);
++ return;
++ }
++
++ rcu_read_lock();
++
++ if (status->excessive_retries) {
++ struct sta_info *sta;
++ sta = sta_info_get(local, hdr->addr1);
++ if (sta) {
++ if (sta->flags & WLAN_STA_PS) {
++ /*
++ * The STA is in power save mode, so assume
++ * that this TX packet failed because of that.
++ */
++ status->excessive_retries = 0;
++ status->flags |= IEEE80211_TX_STATUS_TX_FILTERED;
++ ieee80211_handle_filtered_frame(local, sta,
++ skb, status);
++ rcu_read_unlock();
++ return;
++ }
++ }
++ }
++
++ if (status->flags & IEEE80211_TX_STATUS_TX_FILTERED) {
++ struct sta_info *sta;
++ sta = sta_info_get(local, hdr->addr1);
++ if (sta) {
++ ieee80211_handle_filtered_frame(local, sta, skb,
++ status);
++ rcu_read_unlock();
++ return;
++ }
++ } else
++ rate_control_tx_status(local->mdev, skb, status);
++
++ rcu_read_unlock();
++
++ ieee80211_led_tx(local, 0);
++
++ /* SNMP counters
++ * Fragments are passed to low-level drivers as separate skbs, so these
++ * are actually fragments, not frames. Update frame counters only for
++ * the first fragment of the frame. */
++
++ frag = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
++ type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE;
++
++ if (status->flags & IEEE80211_TX_STATUS_ACK) {
++ if (frag == 0) {
++ local->dot11TransmittedFrameCount++;
++ if (is_multicast_ether_addr(hdr->addr1))
++ local->dot11MulticastTransmittedFrameCount++;
++ if (status->retry_count > 0)
++ local->dot11RetryCount++;
++ if (status->retry_count > 1)
++ local->dot11MultipleRetryCount++;
++ }
++
++ /* This counter shall be incremented for an acknowledged MPDU
++ * with an individual address in the address 1 field or an MPDU
++ * with a multicast address in the address 1 field of type Data
++ * or Management. */
++ if (!is_multicast_ether_addr(hdr->addr1) ||
++ type == IEEE80211_FTYPE_DATA ||
++ type == IEEE80211_FTYPE_MGMT)
++ local->dot11TransmittedFragmentCount++;
++ } else {
++ if (frag == 0)
++ local->dot11FailedCount++;
++ }
++
++ /* this was a transmitted frame, but now we want to reuse it */
++ skb_orphan(skb);
++
++ /*
++ * This is a bit racy but we can avoid a lot of work
++ * with this test...
++ */
++ if (!local->monitors && !local->cooked_mntrs) {
++ dev_kfree_skb(skb);
++ return;
++ }
++
++ /* send frame to monitor interfaces now */
++
++ if (skb_headroom(skb) < sizeof(*rthdr)) {
++ printk(KERN_ERR "ieee80211_tx_status: headroom too small\n");
++ dev_kfree_skb(skb);
++ return;
++ }
++
++ rthdr = (struct ieee80211_tx_status_rtap_hdr*)
++ skb_push(skb, sizeof(*rthdr));
++
++ memset(rthdr, 0, sizeof(*rthdr));
++ rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr));
++ rthdr->hdr.it_present =
++ cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
++ (1 << IEEE80211_RADIOTAP_DATA_RETRIES));
++
++ if (!(status->flags & IEEE80211_TX_STATUS_ACK) &&
++ !is_multicast_ether_addr(hdr->addr1))
++ rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL);
++
++ if ((status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) &&
++ (status->control.flags & IEEE80211_TXCTL_USE_CTS_PROTECT))
++ rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS);
++ else if (status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS)
++ rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS);
++
++ rthdr->data_retries = status->retry_count;
++
++ /* XXX: is this sufficient for BPF? */
++ skb_set_mac_header(skb, 0);
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++ skb->pkt_type = PACKET_OTHERHOST;
++ skb->protocol = htons(ETH_P_802_2);
++ memset(skb->cb, 0, sizeof(skb->cb));
++
++ rcu_read_lock();
++ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
++ if (sdata->vif.type == IEEE80211_IF_TYPE_MNTR) {
++ if (!netif_running(sdata->dev))
++ continue;
++
++ if (prev_dev) {
++ skb2 = skb_clone(skb, GFP_ATOMIC);
++ if (skb2) {
++ skb2->dev = prev_dev;
++ netif_rx(skb2);
++ }
++ }
++
++ prev_dev = sdata->dev;
++ }
++ }
++ if (prev_dev) {
++ skb->dev = prev_dev;
++ netif_rx(skb);
++ skb = NULL;
++ }
++ rcu_read_unlock();
++ dev_kfree_skb(skb);
++}
++EXPORT_SYMBOL(ieee80211_tx_status);
++
++struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
++ const struct ieee80211_ops *ops)
++{
++ struct ieee80211_local *local;
++ int priv_size;
++ struct wiphy *wiphy;
++
++ /* Ensure 32-byte alignment of our private data and hw private data.
++ * We use the wiphy priv data for both our ieee80211_local and for
++ * the driver's private data
++ *
++ * In memory it'll be like this:
++ *
++ * +-------------------------+
++ * | struct wiphy |
++ * +-------------------------+
++ * | struct ieee80211_local |
++ * +-------------------------+
++ * | driver's private data |
++ * +-------------------------+
++ *
++ */
++ priv_size = ((sizeof(struct ieee80211_local) +
++ NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST) +
++ priv_data_len;
++
++ wiphy = wiphy_new(&mac80211_config_ops, priv_size);
++
++ if (!wiphy)
++ return NULL;
++
++ wiphy->privid = mac80211_wiphy_privid;
++
++ local = wiphy_priv(wiphy);
++ local->hw.wiphy = wiphy;
++
++ local->hw.priv = (char *)local +
++ ((sizeof(struct ieee80211_local) +
++ NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
++
++ BUG_ON(!ops->tx);
++ BUG_ON(!ops->start);
++ BUG_ON(!ops->stop);
++ BUG_ON(!ops->config);
++ BUG_ON(!ops->add_interface);
++ BUG_ON(!ops->remove_interface);
++ BUG_ON(!ops->configure_filter);
++ local->ops = ops;
++
++ local->hw.queues = 1; /* default */
++
++ local->bridge_packets = 1;
++
++ local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
++ local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
++ local->short_retry_limit = 7;
++ local->long_retry_limit = 4;
++ local->hw.conf.radio_enabled = 1;
++
++ INIT_LIST_HEAD(&local->interfaces);
++
++ spin_lock_init(&local->key_lock);
++
++ INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work);
++
++ sta_info_init(local);
++
++ tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending,
++ (unsigned long)local);
++ tasklet_disable(&local->tx_pending_tasklet);
++
++ tasklet_init(&local->tasklet,
++ ieee80211_tasklet_handler,
++ (unsigned long) local);
++ tasklet_disable(&local->tasklet);
++
++ skb_queue_head_init(&local->skb_queue);
++ skb_queue_head_init(&local->skb_queue_unreliable);
++
++ return local_to_hw(local);
++}
++EXPORT_SYMBOL(ieee80211_alloc_hw);
++
++int ieee80211_register_hw(struct ieee80211_hw *hw)
++{
++ struct ieee80211_local *local = hw_to_local(hw);
++ const char *name;
++ int result;
++ enum ieee80211_band band;
++ struct net_device *mdev;
++ struct ieee80211_sub_if_data *sdata;
++
++ /*
++ * generic code guarantees at least one band,
++ * set this very early because much code assumes
++ * that hw.conf.channel is assigned
++ */
++ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
++ struct ieee80211_supported_band *sband;
++
++ sband = local->hw.wiphy->bands[band];
++ if (sband) {
++ /* init channel we're on */
++ local->hw.conf.channel =
++ local->oper_channel =
++ local->scan_channel = &sband->channels[0];
++ break;
++ }
++ }
++
++ result = wiphy_register(local->hw.wiphy);
++ if (result < 0)
++ return result;
++
++ /* for now, mdev needs sub_if_data :/ */
++ mdev = alloc_netdev(sizeof(struct ieee80211_sub_if_data),
++ "wmaster%d", ether_setup);
++ if (!mdev)
++ goto fail_mdev_alloc;
++
++ sdata = IEEE80211_DEV_TO_SUB_IF(mdev);
++ mdev->ieee80211_ptr = &sdata->wdev;
++ sdata->wdev.wiphy = local->hw.wiphy;
++
++ local->mdev = mdev;
++
++ ieee80211_rx_bss_list_init(mdev);
++
++ mdev->hard_start_xmit = ieee80211_master_start_xmit;
++ mdev->open = ieee80211_master_open;
++ mdev->stop = ieee80211_master_stop;
++ mdev->type = ARPHRD_IEEE80211;
++ mdev->header_ops = &ieee80211_header_ops;
++ mdev->set_multicast_list = ieee80211_master_set_multicast_list;
++
++ sdata->vif.type = IEEE80211_IF_TYPE_AP;
++ sdata->dev = mdev;
++ sdata->local = local;
++ sdata->u.ap.force_unicast_rateidx = -1;
++ sdata->u.ap.max_ratectrl_rateidx = -1;
++ ieee80211_if_sdata_init(sdata);
++
++ /* no RCU needed since we're still during init phase */
++ list_add_tail(&sdata->list, &local->interfaces);
++
++ name = wiphy_dev(local->hw.wiphy)->driver->name;
++ local->hw.workqueue = create_singlethread_workqueue(name);
++ if (!local->hw.workqueue) {
++ result = -ENOMEM;
++ goto fail_workqueue;
++ }
++
++ /*
++ * The hardware needs headroom for sending the frame,
++ * and we need some headroom for passing the frame to monitor
++ * interfaces, but never both at the same time.
++ */
++ local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
++ sizeof(struct ieee80211_tx_status_rtap_hdr));
++
++ debugfs_hw_add(local);
++
++ local->hw.conf.beacon_int = 1000;
++
++ local->wstats_flags |= local->hw.max_rssi ?
++ IW_QUAL_LEVEL_UPDATED : IW_QUAL_LEVEL_INVALID;
++ local->wstats_flags |= local->hw.max_signal ?
++ IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID;
++ local->wstats_flags |= local->hw.max_noise ?
++ IW_QUAL_NOISE_UPDATED : IW_QUAL_NOISE_INVALID;
++ if (local->hw.max_rssi < 0 || local->hw.max_noise < 0)
++ local->wstats_flags |= IW_QUAL_DBM;
++
++ result = sta_info_start(local);
++ if (result < 0)
++ goto fail_sta_info;
++
++ rtnl_lock();
++ result = dev_alloc_name(local->mdev, local->mdev->name);
++ if (result < 0)
++ goto fail_dev;
++
++ memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
++ SET_NETDEV_DEV(local->mdev, wiphy_dev(local->hw.wiphy));
++
++ result = register_netdevice(local->mdev);
++ if (result < 0)
++ goto fail_dev;
++
++ ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
++ ieee80211_if_set_type(local->mdev, IEEE80211_IF_TYPE_AP);
++
++ result = ieee80211_init_rate_ctrl_alg(local,
++ hw->rate_control_algorithm);
++ if (result < 0) {
++ printk(KERN_DEBUG "%s: Failed to initialize rate control "
++ "algorithm\n", wiphy_name(local->hw.wiphy));
++ goto fail_rate;
++ }
++
++ result = ieee80211_wep_init(local);
++
++ if (result < 0) {
++ printk(KERN_DEBUG "%s: Failed to initialize wep\n",
++ wiphy_name(local->hw.wiphy));
++ goto fail_wep;
++ }
++
++ ieee80211_install_qdisc(local->mdev);
++
++ /* add one default STA interface */
++ result = ieee80211_if_add(local->mdev, "wlan%d", NULL,
++ IEEE80211_IF_TYPE_STA, NULL);
++ if (result)
++ printk(KERN_WARNING "%s: Failed to add default virtual iface\n",
++ wiphy_name(local->hw.wiphy));
++
++ local->reg_state = IEEE80211_DEV_REGISTERED;
++ rtnl_unlock();
++
++ ieee80211_led_init(local);
++
++ return 0;
++
++fail_wep:
++ rate_control_deinitialize(local);
++fail_rate:
++ ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
++ unregister_netdevice(local->mdev);
++fail_dev:
++ rtnl_unlock();
++ sta_info_stop(local);
++fail_sta_info:
++ debugfs_hw_del(local);
++ destroy_workqueue(local->hw.workqueue);
++fail_workqueue:
++ ieee80211_if_free(local->mdev);
++ local->mdev = NULL;
++fail_mdev_alloc:
++ wiphy_unregister(local->hw.wiphy);
++ return result;
++}
++EXPORT_SYMBOL(ieee80211_register_hw);
++
++void ieee80211_unregister_hw(struct ieee80211_hw *hw)
++{
++ struct ieee80211_local *local = hw_to_local(hw);
++ struct ieee80211_sub_if_data *sdata, *tmp;
++
++ tasklet_kill(&local->tx_pending_tasklet);
++ tasklet_kill(&local->tasklet);
++
++ rtnl_lock();
++
++ BUG_ON(local->reg_state != IEEE80211_DEV_REGISTERED);
++
++ local->reg_state = IEEE80211_DEV_UNREGISTERED;
++
++ /*
++ * At this point, interface list manipulations are fine
++ * because the driver cannot be handing us frames any
++ * more and the tasklet is killed.
++ */
++
++ /*
++ * First, we remove all non-master interfaces. Do this because they
++ * may have bss pointer dependency on the master, and when we free
++ * the master these would be freed as well, breaking our list
++ * iteration completely.
++ */
++ list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
++ if (sdata->dev == local->mdev)
++ continue;
++ list_del(&sdata->list);
++ __ieee80211_if_del(local, sdata);
++ }
++
++ /* then, finally, remove the master interface */
++ __ieee80211_if_del(local, IEEE80211_DEV_TO_SUB_IF(local->mdev));
++
++ rtnl_unlock();
++
++ ieee80211_rx_bss_list_deinit(local->mdev);
++ ieee80211_clear_tx_pending(local);
++ sta_info_stop(local);
++ rate_control_deinitialize(local);
++ debugfs_hw_del(local);
++
++ if (skb_queue_len(&local->skb_queue)
++ || skb_queue_len(&local->skb_queue_unreliable))
++ printk(KERN_WARNING "%s: skb_queue not empty\n",
++ wiphy_name(local->hw.wiphy));
++ skb_queue_purge(&local->skb_queue);
++ skb_queue_purge(&local->skb_queue_unreliable);
++
++ destroy_workqueue(local->hw.workqueue);
++ wiphy_unregister(local->hw.wiphy);
++ ieee80211_wep_free(local);
++ ieee80211_led_exit(local);
++ ieee80211_if_free(local->mdev);
++ local->mdev = NULL;
++}
++EXPORT_SYMBOL(ieee80211_unregister_hw);
++
++void ieee80211_free_hw(struct ieee80211_hw *hw)
++{
++ struct ieee80211_local *local = hw_to_local(hw);
++
++ wiphy_free(local->hw.wiphy);
++}
++EXPORT_SYMBOL(ieee80211_free_hw);
++
++static int __init ieee80211_init(void)
++{
++ struct sk_buff *skb;
++ int ret;
++
++ BUILD_BUG_ON(sizeof(struct ieee80211_tx_packet_data) > sizeof(skb->cb));
++
++ ret = rc80211_pid_init();
++ if (ret)
++ goto out;
++
++ ret = ieee80211_wme_register();
++ if (ret) {
++ printk(KERN_DEBUG "ieee80211_init: failed to "
++ "initialize WME (err=%d)\n", ret);
++ goto out_cleanup_pid;
++ }
++
++ ieee80211_debugfs_netdev_init();
++
++ return 0;
++
++ out_cleanup_pid:
++ rc80211_pid_exit();
++ out:
++ return ret;
++}
++
++static void __exit ieee80211_exit(void)
++{
++ rc80211_pid_exit();
++
++ /*
++ * For key todo, it'll be empty by now but the work
++ * might still be scheduled.
++ */
++ flush_scheduled_work();
++
++ if (mesh_allocated)
++ ieee80211s_stop();
++
++ ieee80211_wme_unregister();
++ ieee80211_debugfs_netdev_exit();
++}
++
++
++subsys_initcall(ieee80211_init);
++module_exit(ieee80211_exit);
++
++MODULE_DESCRIPTION("IEEE 802.11 subsystem");
++MODULE_LICENSE("GPL");
+diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
+new file mode 100644
+index 0000000..594a335
+--- /dev/null
++++ b/net/mac80211/mesh.c
+@@ -0,0 +1,449 @@
++/*
++ * Copyright (c) 2008 open80211s Ltd.
++ * Authors: Luis Carlos Cobo <luisca at cozybit.com>
++ * Javier Cardona <javier at cozybit.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include "ieee80211_i.h"
++#include "mesh.h"
++
++#define PP_OFFSET 1 /* Path Selection Protocol */
++#define PM_OFFSET 5 /* Path Selection Metric */
++#define CC_OFFSET 9 /* Congestion Control Mode */
++#define CAPAB_OFFSET 17
++#define ACCEPT_PLINKS 0x80
++
++int mesh_allocated;
++static struct kmem_cache *rm_cache;
++
++void ieee80211s_init(void)
++{
++ mesh_pathtbl_init();
++ mesh_allocated = 1;
++ rm_cache = kmem_cache_create("mesh_rmc", sizeof(struct rmc_entry),
++ 0, 0, NULL);
++}
++
++void ieee80211s_stop(void)
++{
++ mesh_pathtbl_unregister();
++ kmem_cache_destroy(rm_cache);
++}
++
++/**
++ * mesh_matches_local - check if the config of a mesh point matches ours
++ *
++ * @ie: information elements of a management frame from the mesh peer
++ * @dev: local mesh interface
++ *
++ * This function checks if the mesh configuration of a mesh point matches the
++ * local mesh configuration, i.e. if both nodes belong to the same mesh network.
++ */
++bool mesh_matches_local(struct ieee802_11_elems *ie, struct net_device *dev)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_if_sta *sta = &sdata->u.sta;
++
++ /*
++ * As support for each feature is added, check for matching
++ * - On mesh config capabilities
++ * - Power Save Support En
++ * - Sync support enabled
++ * - Sync support active
++ * - Sync support required from peer
++ * - MDA enabled
++ * - Power management control on fc
++ */
++ if (sta->mesh_id_len == ie->mesh_id_len &&
++ memcmp(sta->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 &&
++ memcmp(sta->mesh_pp_id, ie->mesh_config + PP_OFFSET, 4) == 0 &&
++ memcmp(sta->mesh_pm_id, ie->mesh_config + PM_OFFSET, 4) == 0 &&
++ memcmp(sta->mesh_cc_id, ie->mesh_config + CC_OFFSET, 4) == 0)
++ return true;
++
++ return false;
++}
++
++/**
++ * mesh_peer_accepts_plinks - check if an mp is willing to establish peer links
++ *
++ * @ie: information elements of a management frame from the mesh peer
++ * @dev: local mesh interface
++ */
++bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie,
++ struct net_device *dev)
++{
++ return (*(ie->mesh_config + CAPAB_OFFSET) & ACCEPT_PLINKS) != 0;
++}
++
++/**
++ * mesh_accept_plinks_update: update accepting_plink in local mesh beacons
++ *
++ * @sdata: mesh interface in which mesh beacons are going to be updated
++ */
++void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata)
++{
++ bool free_plinks;
++
++ /* In case mesh_plink_free_count > 0 and mesh_plinktbl_capacity == 0,
++ * the mesh interface might be able to establish plinks with peers that
++ * are already on the table but are not on PLINK_ESTAB state. However,
++ * in general the mesh interface is not accepting peer link requests
++ * from new peers, and that must be reflected in the beacon
++ */
++ free_plinks = mesh_plink_availables(sdata);
++
++ if (free_plinks != sdata->u.sta.accepting_plinks)
++ ieee80211_sta_timer((unsigned long) sdata);
++}
++
++void mesh_ids_set_default(struct ieee80211_if_sta *sta)
++{
++ u8 def_id[4] = {0x00, 0x0F, 0xAC, 0xff};
++
++ memcpy(sta->mesh_pp_id, def_id, 4);
++ memcpy(sta->mesh_pm_id, def_id, 4);
++ memcpy(sta->mesh_cc_id, def_id, 4);
++}
++
++int mesh_rmc_init(struct net_device *dev)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ int i;
++
++ sdata->u.sta.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL);
++ if (!sdata->u.sta.rmc)
++ return -ENOMEM;
++ sdata->u.sta.rmc->idx_mask = RMC_BUCKETS - 1;
++ for (i = 0; i < RMC_BUCKETS; i++)
++ INIT_LIST_HEAD(&sdata->u.sta.rmc->bucket[i].list);
++ return 0;
++}
++
++void mesh_rmc_free(struct net_device *dev)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct mesh_rmc *rmc = sdata->u.sta.rmc;
++ struct rmc_entry *p, *n;
++ int i;
++
++ if (!sdata->u.sta.rmc)
++ return;
++
++ for (i = 0; i < RMC_BUCKETS; i++)
++ list_for_each_entry_safe(p, n, &rmc->bucket[i].list, list) {
++ list_del(&p->list);
++ kmem_cache_free(rm_cache, p);
++ }
++
++ kfree(rmc);
++ sdata->u.sta.rmc = NULL;
++}
++
++/**
++ * mesh_rmc_check - Check frame in recent multicast cache and add if absent.
++ *
++ * @sa: source address
++ * @mesh_hdr: mesh_header
++ *
++ * Returns: 0 if the frame is not in the cache, nonzero otherwise.
++ *
++ * Checks using the source address and the mesh sequence number if we have
++ * received this frame lately. If the frame is not in the cache, it is added to
++ * it.
++ */
++int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr,
++ struct net_device *dev)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct mesh_rmc *rmc = sdata->u.sta.rmc;
++ u32 seqnum = 0;
++ int entries = 0;
++ u8 idx;
++ struct rmc_entry *p, *n;
++
++ /* Don't care about endianness since only match matters */
++ memcpy(&seqnum, mesh_hdr->seqnum, sizeof(mesh_hdr->seqnum));
++ idx = mesh_hdr->seqnum[0] & rmc->idx_mask;
++ list_for_each_entry_safe(p, n, &rmc->bucket[idx].list, list) {
++ ++entries;
++ if (time_after(jiffies, p->exp_time) ||
++ (entries == RMC_QUEUE_MAX_LEN)) {
++ list_del(&p->list);
++ kmem_cache_free(rm_cache, p);
++ --entries;
++ } else if ((seqnum == p->seqnum)
++ && (memcmp(sa, p->sa, ETH_ALEN) == 0))
++ return -1;
++ }
++
++ p = kmem_cache_alloc(rm_cache, GFP_ATOMIC);
++ if (!p) {
++ printk(KERN_DEBUG "o11s: could not allocate RMC entry\n");
++ return 0;
++ }
++ p->seqnum = seqnum;
++ p->exp_time = jiffies + RMC_TIMEOUT;
++ memcpy(p->sa, sa, ETH_ALEN);
++ list_add(&p->list, &rmc->bucket[idx].list);
++ return 0;
++}
++
++void mesh_mgmt_ies_add(struct sk_buff *skb, struct net_device *dev)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_supported_band *sband;
++ u8 *pos;
++ int len, i, rate;
++
++ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++ len = sband->n_bitrates;
++ if (len > 8)
++ len = 8;
++ pos = skb_put(skb, len + 2);
++ *pos++ = WLAN_EID_SUPP_RATES;
++ *pos++ = len;
++ for (i = 0; i < len; i++) {
++ rate = sband->bitrates[i].bitrate;
++ *pos++ = (u8) (rate / 5);
++ }
++
++ if (sband->n_bitrates > len) {
++ pos = skb_put(skb, sband->n_bitrates - len + 2);
++ *pos++ = WLAN_EID_EXT_SUPP_RATES;
++ *pos++ = sband->n_bitrates - len;
++ for (i = len; i < sband->n_bitrates; i++) {
++ rate = sband->bitrates[i].bitrate;
++ *pos++ = (u8) (rate / 5);
++ }
++ }
++
++ pos = skb_put(skb, 2 + sdata->u.sta.mesh_id_len);
++ *pos++ = WLAN_EID_MESH_ID;
++ *pos++ = sdata->u.sta.mesh_id_len;
++ if (sdata->u.sta.mesh_id_len)
++ memcpy(pos, sdata->u.sta.mesh_id, sdata->u.sta.mesh_id_len);
++
++ pos = skb_put(skb, 21);
++ *pos++ = WLAN_EID_MESH_CONFIG;
++ *pos++ = MESH_CFG_LEN;
++ /* Version */
++ *pos++ = 1;
++
++ /* Active path selection protocol ID */
++ memcpy(pos, sdata->u.sta.mesh_pp_id, 4);
++ pos += 4;
++
++ /* Active path selection metric ID */
++ memcpy(pos, sdata->u.sta.mesh_pm_id, 4);
++ pos += 4;
++
++ /* Congestion control mode identifier */
++ memcpy(pos, sdata->u.sta.mesh_cc_id, 4);
++ pos += 4;
++
++ /* Channel precedence:
++ * Not running simple channel unification protocol
++ */
++ memset(pos, 0x00, 4);
++ pos += 4;
++
++ /* Mesh capability */
++ sdata->u.sta.accepting_plinks = mesh_plink_availables(sdata);
++ *pos++ = sdata->u.sta.accepting_plinks ? ACCEPT_PLINKS : 0x00;
++ *pos++ = 0x00;
++
++ return;
++}
++
++u32 mesh_table_hash(u8 *addr, struct net_device *dev, struct mesh_table *tbl)
++{
++ /* Use last four bytes of hw addr and interface index as hash index */
++ return jhash_2words(*(u32 *)(addr+2), dev->ifindex, tbl->hash_rnd)
++ & tbl->hash_mask;
++}
++
++u8 mesh_id_hash(u8 *mesh_id, int mesh_id_len)
++{
++ if (!mesh_id_len)
++ return 1;
++ else if (mesh_id_len == 1)
++ return (u8) mesh_id[0];
++ else
++ return (u8) (mesh_id[0] + 2 * mesh_id[1]);
++}
++
++struct mesh_table *mesh_table_alloc(int size_order)
++{
++ int i;
++ struct mesh_table *newtbl;
++
++ newtbl = kmalloc(sizeof(struct mesh_table), GFP_KERNEL);
++ if (!newtbl)
++ return NULL;
++
++ newtbl->hash_buckets = kzalloc(sizeof(struct hlist_head) *
++ (1 << size_order), GFP_KERNEL);
++
++ if (!newtbl->hash_buckets) {
++ kfree(newtbl);
++ return NULL;
++ }
++
++ newtbl->hashwlock = kmalloc(sizeof(spinlock_t) *
++ (1 << size_order), GFP_KERNEL);
++ if (!newtbl->hashwlock) {
++ kfree(newtbl->hash_buckets);
++ kfree(newtbl);
++ return NULL;
++ }
++
++ newtbl->size_order = size_order;
++ newtbl->hash_mask = (1 << size_order) - 1;
++ atomic_set(&newtbl->entries, 0);
++ get_random_bytes(&newtbl->hash_rnd,
++ sizeof(newtbl->hash_rnd));
++ for (i = 0; i <= newtbl->hash_mask; i++)
++ spin_lock_init(&newtbl->hashwlock[i]);
++
++ return newtbl;
++}
++
++void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
++{
++ struct hlist_head *mesh_hash;
++ struct hlist_node *p, *q;
++ int i;
++
++ mesh_hash = tbl->hash_buckets;
++ for (i = 0; i <= tbl->hash_mask; i++) {
++ spin_lock(&tbl->hashwlock[i]);
++ hlist_for_each_safe(p, q, &mesh_hash[i]) {
++ tbl->free_node(p, free_leafs);
++ atomic_dec(&tbl->entries);
++ }
++ spin_unlock(&tbl->hashwlock[i]);
++ }
++ kfree(tbl->hash_buckets);
++ kfree(tbl->hashwlock);
++ kfree(tbl);
++}
++
++static void ieee80211_mesh_path_timer(unsigned long data)
++{
++ struct ieee80211_sub_if_data *sdata =
++ (struct ieee80211_sub_if_data *) data;
++ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++ struct ieee80211_local *local = wdev_priv(&sdata->wdev);
++
++ queue_work(local->hw.workqueue, &ifsta->work);
++}
++
++struct mesh_table *mesh_table_grow(struct mesh_table *tbl)
++{
++ struct mesh_table *newtbl;
++ struct hlist_head *oldhash;
++ struct hlist_node *p;
++ int err = 0;
++ int i;
++
++ if (atomic_read(&tbl->entries)
++ < tbl->mean_chain_len * (tbl->hash_mask + 1)) {
++ err = -EPERM;
++ goto endgrow;
++ }
++
++ newtbl = mesh_table_alloc(tbl->size_order + 1);
++ if (!newtbl) {
++ err = -ENOMEM;
++ goto endgrow;
++ }
++
++ newtbl->free_node = tbl->free_node;
++ newtbl->mean_chain_len = tbl->mean_chain_len;
++ newtbl->copy_node = tbl->copy_node;
++ atomic_set(&newtbl->entries, atomic_read(&tbl->entries));
++
++ oldhash = tbl->hash_buckets;
++ for (i = 0; i <= tbl->hash_mask; i++)
++ hlist_for_each(p, &oldhash[i])
++ tbl->copy_node(p, newtbl);
++
++endgrow:
++ if (err)
++ return NULL;
++ else
++ return newtbl;
++}
++
++/**
++ * ieee80211_new_mesh_header - create a new mesh header
++ * @meshhdr: uninitialized mesh header
++ * @sdata: mesh interface to be used
++ *
++ * Return the header length.
++ */
++int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
++ struct ieee80211_sub_if_data *sdata)
++{
++ meshhdr->flags = 0;
++ meshhdr->ttl = sdata->u.sta.mshcfg.dot11MeshTTL;
++
++ meshhdr->seqnum[0] = sdata->u.sta.mesh_seqnum[0]++;
++ meshhdr->seqnum[1] = sdata->u.sta.mesh_seqnum[1];
++ meshhdr->seqnum[2] = sdata->u.sta.mesh_seqnum[2];
++
++ if (sdata->u.sta.mesh_seqnum[0] == 0) {
++ sdata->u.sta.mesh_seqnum[1]++;
++ if (sdata->u.sta.mesh_seqnum[1] == 0)
++ sdata->u.sta.mesh_seqnum[2]++;
++ }
++
++ return 5;
++}
++
++void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
++{
++ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++
++ ifsta->mshcfg.dot11MeshRetryTimeout = MESH_RET_T;
++ ifsta->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T;
++ ifsta->mshcfg.dot11MeshHoldingTimeout = MESH_HOLD_T;
++ ifsta->mshcfg.dot11MeshMaxRetries = MESH_MAX_RETR;
++ ifsta->mshcfg.dot11MeshTTL = MESH_TTL;
++ ifsta->mshcfg.auto_open_plinks = true;
++ ifsta->mshcfg.dot11MeshMaxPeerLinks =
++ MESH_MAX_ESTAB_PLINKS;
++ ifsta->mshcfg.dot11MeshHWMPactivePathTimeout =
++ MESH_PATH_TIMEOUT;
++ ifsta->mshcfg.dot11MeshHWMPpreqMinInterval =
++ MESH_PREQ_MIN_INT;
++ ifsta->mshcfg.dot11MeshHWMPnetDiameterTraversalTime =
++ MESH_DIAM_TRAVERSAL_TIME;
++ ifsta->mshcfg.dot11MeshHWMPmaxPREQretries =
++ MESH_MAX_PREQ_RETRIES;
++ ifsta->mshcfg.path_refresh_time =
++ MESH_PATH_REFRESH_TIME;
++ ifsta->mshcfg.min_discovery_timeout =
++ MESH_MIN_DISCOVERY_TIMEOUT;
++ ifsta->accepting_plinks = true;
++ ifsta->preq_id = 0;
++ ifsta->dsn = 0;
++ atomic_set(&ifsta->mpaths, 0);
++ mesh_rmc_init(sdata->dev);
++ ifsta->last_preq = jiffies;
++ /* Allocate all mesh structures when creating the first mesh interface. */
++ if (!mesh_allocated)
++ ieee80211s_init();
++ mesh_ids_set_default(ifsta);
++ setup_timer(&ifsta->mesh_path_timer,
++ ieee80211_mesh_path_timer,
++ (unsigned long) sdata);
++ INIT_LIST_HEAD(&ifsta->preq_queue.list);
++ spin_lock_init(&ifsta->mesh_preq_queue_lock);
++}
+diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
+new file mode 100644
+index 0000000..742003d
+--- /dev/null
++++ b/net/mac80211/mesh.h
+@@ -0,0 +1,290 @@
++/*
++ * Copyright (c) 2008 open80211s Ltd.
++ * Authors: Luis Carlos Cobo <luisca at cozybit.com>
++ * Javier Cardona <javier at cozybit.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef IEEE80211S_H
++#define IEEE80211S_H
++
++#include <linux/types.h>
++#include <linux/jhash.h>
++#include "ieee80211_i.h"
++
++
++/* Data structures */
++
++/**
++ * enum mesh_path_flags - mac80211 mesh path flags
++ *
++ *
++ *
++ * @MESH_PATH_ACTIVE: the mesh path is can be used for forwarding
++ * @MESH_PATH_RESOLVED: the discovery process is running for this mesh path
++ * @MESH_PATH_DSN_VALID: the mesh path contains a valid destination sequence
++ * number
++ * @MESH_PATH_FIXED: the mesh path has been manually set and should not be
++ * modified
++ * @MESH_PATH_RESOLVED: the mesh path can has been resolved
++ *
++ * MESH_PATH_RESOLVED and MESH_PATH_DELETE are used by the mesh path timer to
++ * decide when to stop or cancel the mesh path discovery.
++ */
++enum mesh_path_flags {
++ MESH_PATH_ACTIVE = BIT(0),
++ MESH_PATH_RESOLVING = BIT(1),
++ MESH_PATH_DSN_VALID = BIT(2),
++ MESH_PATH_FIXED = BIT(3),
++ MESH_PATH_RESOLVED = BIT(4),
++};
++
++/**
++ * struct mesh_path - mac80211 mesh path structure
++ *
++ * @dst: mesh path destination mac address
++ * @dev: mesh path device
++ * @next_hop: mesh neighbor to which frames for this destination will be
++ * forwarded
++ * @timer: mesh path discovery timer
++ * @frame_queue: pending queue for frames sent to this destination while the
++ * path is unresolved
++ * @dsn: destination sequence number of the destination
++ * @metric: current metric to this destination
++ * @hop_count: hops to destination
++ * @exp_time: in jiffies, when the path will expire or when it expired
++ * @discovery_timeout: timeout (lapse in jiffies) used for the last discovery
++ * retry
++ * @discovery_retries: number of discovery retries
++ * @flags: mesh path flags, as specified on &enum mesh_path_flags
++ * @state_lock: mesh pat state lock
++ *
++ *
++ * The combination of dst and dev is unique in the mesh path table. Since the
++ * next_hop STA is only protected by RCU as well, deleting the STA must also
++ * remove/substitute the mesh_path structure and wait until that is no longer
++ * reachable before destroying the STA completely.
++ */
++struct mesh_path {
++ u8 dst[ETH_ALEN];
++ struct net_device *dev;
++ struct sta_info *next_hop;
++ struct timer_list timer;
++ struct sk_buff_head frame_queue;
++ struct rcu_head rcu;
++ u32 dsn;
++ u32 metric;
++ u8 hop_count;
++ unsigned long exp_time;
++ u32 discovery_timeout;
++ u8 discovery_retries;
++ enum mesh_path_flags flags;
++ spinlock_t state_lock;
++};
++
++/**
++ * struct mesh_table
++ *
++ * @hash_buckets: array of hash buckets of the table
++ * @hashwlock: array of locks to protect write operations, one per bucket
++ * @hash_mask: 2^size_order - 1, used to compute hash idx
++ * @hash_rnd: random value used for hash computations
++ * @entries: number of entries in the table
++ * @free_node: function to free nodes of the table
++ * @copy_node: fuction to copy nodes of the table
++ * @size_order: determines size of the table, there will be 2^size_order hash
++ * buckets
++ * @mean_chain_len: maximum average length for the hash buckets' list, if it is
++ * reached, the table will grow
++ */
++struct mesh_table {
++ /* Number of buckets will be 2^N */
++ struct hlist_head *hash_buckets;
++ spinlock_t *hashwlock; /* One per bucket, for add/del */
++ unsigned int hash_mask; /* (2^size_order) - 1 */
++ __u32 hash_rnd; /* Used for hash generation */
++ atomic_t entries; /* Up to MAX_MESH_NEIGHBOURS */
++ void (*free_node) (struct hlist_node *p, bool free_leafs);
++ void (*copy_node) (struct hlist_node *p, struct mesh_table *newtbl);
++ int size_order;
++ int mean_chain_len;
++};
++
++/* Recent multicast cache */
++/* RMC_BUCKETS must be a power of 2, maximum 256 */
++#define RMC_BUCKETS 256
++#define RMC_QUEUE_MAX_LEN 4
++#define RMC_TIMEOUT (3 * HZ)
++
++/**
++ * struct rmc_entry - entry in the Recent Multicast Cache
++ *
++ * @seqnum: mesh sequence number of the frame
++ * @exp_time: expiration time of the entry, in jiffies
++ * @sa: source address of the frame
++ *
++ * The Recent Multicast Cache keeps track of the latest multicast frames that
++ * have been received by a mesh interface and discards received multicast frames
++ * that are found in the cache.
++ */
++struct rmc_entry {
++ struct list_head list;
++ u32 seqnum;
++ unsigned long exp_time;
++ u8 sa[ETH_ALEN];
++};
++
++struct mesh_rmc {
++ struct rmc_entry bucket[RMC_BUCKETS];
++ u8 idx_mask;
++};
++
++
++/* Mesh IEs constants */
++#define MESH_CFG_LEN 19
++
++/*
++ * MESH_CFG_COMP_LEN Includes:
++ * - Active path selection protocol ID.
++ * - Active path selection metric ID.
++ * - Congestion control mode identifier.
++ * - Channel precedence.
++ * Does not include mesh capabilities, which may vary across nodes in the same
++ * mesh
++ */
++#define MESH_CFG_CMP_LEN 17
++
++/* Default values, timeouts in ms */
++#define MESH_TTL 5
++#define MESH_MAX_RETR 3
++#define MESH_RET_T 100
++#define MESH_CONF_T 100
++#define MESH_HOLD_T 100
++
++#define MESH_PATH_TIMEOUT 5000
++/* Minimum interval between two consecutive PREQs originated by the same
++ * interface
++ */
++#define MESH_PREQ_MIN_INT 10
++#define MESH_DIAM_TRAVERSAL_TIME 50
++/* Paths will be refreshed if they are closer than PATH_REFRESH_TIME to their
++ * expiration
++ */
++#define MESH_PATH_REFRESH_TIME 1000
++#define MESH_MIN_DISCOVERY_TIMEOUT (2 * MESH_DIAM_TRAVERSAL_TIME)
++
++#define MESH_MAX_PREQ_RETRIES 4
++#define MESH_PATH_EXPIRE (600 * HZ)
++
++/* Default maximum number of established plinks per interface */
++#define MESH_MAX_ESTAB_PLINKS 32
++
++/* Default maximum number of plinks per interface */
++#define MESH_MAX_PLINKS 256
++
++/* Maximum number of paths per interface */
++#define MESH_MAX_MPATHS 1024
++
++/* Pending ANA approval */
++#define PLINK_CATEGORY 30
++#define MESH_PATH_SEL_CATEGORY 32
++
++/* Mesh Header Flags */
++#define IEEE80211S_FLAGS_AE 0x3
++
++/* Public interfaces */
++/* Various */
++u8 mesh_id_hash(u8 *mesh_id, int mesh_id_len);
++int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
++int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
++ struct ieee80211_sub_if_data *sdata);
++int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr,
++ struct net_device *dev);
++bool mesh_matches_local(struct ieee802_11_elems *ie, struct net_device *dev);
++void mesh_ids_set_default(struct ieee80211_if_sta *sta);
++void mesh_mgmt_ies_add(struct sk_buff *skb, struct net_device *dev);
++void mesh_rmc_free(struct net_device *dev);
++int mesh_rmc_init(struct net_device *dev);
++void ieee80211s_init(void);
++void ieee80211s_stop(void);
++void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata);
++
++/* Mesh paths */
++int mesh_nexthop_lookup(u8 *next_hop, struct sk_buff *skb,
++ struct net_device *dev);
++void mesh_path_start_discovery(struct net_device *dev);
++struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev);
++struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev);
++void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop);
++void mesh_path_expire(struct net_device *dev);
++void mesh_path_flush(struct net_device *dev);
++void mesh_rx_path_sel_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
++ size_t len);
++int mesh_path_add(u8 *dst, struct net_device *dev);
++/* Mesh plinks */
++void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct net_device *dev,
++ bool add);
++bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie,
++ struct net_device *dev);
++void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata);
++void mesh_plink_broken(struct sta_info *sta);
++void mesh_plink_deactivate(struct sta_info *sta);
++int mesh_plink_open(struct sta_info *sta);
++int mesh_plink_close(struct sta_info *sta);
++void mesh_plink_block(struct sta_info *sta);
++void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
++ size_t len, struct ieee80211_rx_status *rx_status);
++
++/* Private interfaces */
++/* Mesh tables */
++struct mesh_table *mesh_table_alloc(int size_order);
++void mesh_table_free(struct mesh_table *tbl, bool free_leafs);
++struct mesh_table *mesh_table_grow(struct mesh_table *tbl);
++u32 mesh_table_hash(u8 *addr, struct net_device *dev, struct mesh_table *tbl);
++/* Mesh paths */
++int mesh_path_error_tx(u8 *dest, __le32 dest_dsn, u8 *ra,
++ struct net_device *dev);
++void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta);
++void mesh_path_flush_pending(struct mesh_path *mpath);
++void mesh_path_tx_pending(struct mesh_path *mpath);
++int mesh_pathtbl_init(void);
++void mesh_pathtbl_unregister(void);
++int mesh_path_del(u8 *addr, struct net_device *dev);
++void mesh_path_timer(unsigned long data);
++void mesh_path_flush_by_nexthop(struct sta_info *sta);
++void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev);
++
++#ifdef CONFIG_MAC80211_MESH
++extern int mesh_allocated;
++
++static inline int mesh_plink_free_count(struct ieee80211_sub_if_data *sdata)
++{
++ return sdata->u.sta.mshcfg.dot11MeshMaxPeerLinks -
++ atomic_read(&sdata->u.sta.mshstats.estab_plinks);
++}
++
++static inline bool mesh_plink_availables(struct ieee80211_sub_if_data *sdata)
++{
++ return (min_t(long, mesh_plink_free_count(sdata),
++ MESH_MAX_PLINKS - sdata->local->num_sta)) > 0;
++}
++
++static inline void mesh_path_activate(struct mesh_path *mpath)
++{
++ mpath->flags |= MESH_PATH_ACTIVE | MESH_PATH_RESOLVED;
++}
++
++#define for_each_mesh_entry(x, p, node, i) \
++ for (i = 0; i <= x->hash_mask; i++) \
++ hlist_for_each_entry_rcu(node, p, &x->hash_buckets[i], list)
++
++#else
++#define mesh_allocated 0
++#endif
++
++#define MESH_PREQ(skb) (skb->cb + 30)
++
++#endif /* IEEE80211S_H */
+diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
+new file mode 100644
+index 0000000..02de8f1
+--- /dev/null
++++ b/net/mac80211/mesh_hwmp.c
+@@ -0,0 +1,855 @@
++/*
++ * Copyright (c) 2008 open80211s Ltd.
++ * Author: Luis Carlos Cobo <luisca at cozybit.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <asm/unaligned.h>
++#include "mesh.h"
++
++#define TEST_FRAME_LEN 8192
++#define MAX_METRIC 0xffffffff
++#define ARITH_SHIFT 8
++
++/* Number of frames buffered per destination for unresolved destinations */
++#define MESH_FRAME_QUEUE_LEN 10
++#define MAX_PREQ_QUEUE_LEN 64
++
++/* Destination only */
++#define MP_F_DO 0x1
++/* Reply and forward */
++#define MP_F_RF 0x2
++
++static inline u32 u32_field_get(u8 *preq_elem, int offset, bool ae)
++{
++ if (ae)
++ offset += 6;
++ return le32_to_cpu(get_unaligned((__le32 *) (preq_elem + offset)));
++}
++
++/* HWMP IE processing macros */
++#define AE_F (1<<6)
++#define AE_F_SET(x) (*x & AE_F)
++#define PREQ_IE_FLAGS(x) (*(x))
++#define PREQ_IE_HOPCOUNT(x) (*(x + 1))
++#define PREQ_IE_TTL(x) (*(x + 2))
++#define PREQ_IE_PREQ_ID(x) u32_field_get(x, 3, 0)
++#define PREQ_IE_ORIG_ADDR(x) (x + 7)
++#define PREQ_IE_ORIG_DSN(x) u32_field_get(x, 13, 0);
++#define PREQ_IE_LIFETIME(x) u32_field_get(x, 17, AE_F_SET(x));
++#define PREQ_IE_METRIC(x) u32_field_get(x, 21, AE_F_SET(x));
++#define PREQ_IE_DST_F(x) (*(AE_F_SET(x) ? x + 32 : x + 26))
++#define PREQ_IE_DST_ADDR(x) (AE_F_SET(x) ? x + 33 : x + 27)
++#define PREQ_IE_DST_DSN(x) u32_field_get(x, 33, AE_F_SET(x));
++
++
++#define PREP_IE_FLAGS(x) PREQ_IE_FLAGS(x)
++#define PREP_IE_HOPCOUNT(x) PREQ_IE_HOPCOUNT(x)
++#define PREP_IE_TTL(x) PREQ_IE_TTL(x)
++#define PREP_IE_ORIG_ADDR(x) (x + 3)
++#define PREP_IE_ORIG_DSN(x) u32_field_get(x, 9, 0);
++#define PREP_IE_LIFETIME(x) u32_field_get(x, 13, AE_F_SET(x));
++#define PREP_IE_METRIC(x) u32_field_get(x, 17, AE_F_SET(x));
++#define PREP_IE_DST_ADDR(x) (AE_F_SET(x) ? x + 27 : x + 21)
++#define PREP_IE_DST_DSN(x) u32_field_get(x, 27, AE_F_SET(x));
++
++#define PERR_IE_DST_ADDR(x) (x + 2)
++#define PERR_IE_DST_DSN(x) u32_field_get(x, 8, 0);
++
++#define TU_TO_EXP_TIME(x) (jiffies + msecs_to_jiffies(x * 1024 / 1000))
++#define MSEC_TO_TU(x) (x*1000/1024)
++#define DSN_GT(x, y) ((long) (y) - (long) (x) < 0)
++#define DSN_LT(x, y) ((long) (x) - (long) (y) < 0)
++
++#define net_traversal_jiffies(s) \
++ msecs_to_jiffies(s->u.sta.mshcfg.dot11MeshHWMPnetDiameterTraversalTime)
++#define default_lifetime(s) \
++ MSEC_TO_TU(s->u.sta.mshcfg.dot11MeshHWMPactivePathTimeout)
++#define min_preq_int_jiff(s) \
++ (msecs_to_jiffies(s->u.sta.mshcfg.dot11MeshHWMPpreqMinInterval))
++#define max_preq_retries(s) (s->u.sta.mshcfg.dot11MeshHWMPmaxPREQretries)
++#define disc_timeout_jiff(s) \
++ msecs_to_jiffies(sdata->u.sta.mshcfg.min_discovery_timeout)
++
++enum mpath_frame_type {
++ MPATH_PREQ = 0,
++ MPATH_PREP,
++ MPATH_PERR
++};
++
++static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
++ u8 *orig_addr, __le32 orig_dsn, u8 dst_flags, u8 *dst,
++ __le32 dst_dsn, u8 *da, u8 hop_count, u8 ttl, __le32 lifetime,
++ __le32 metric, __le32 preq_id, struct net_device *dev)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
++ struct ieee80211_mgmt *mgmt;
++ u8 *pos;
++ int ie_len;
++
++ if (!skb)
++ return -1;
++ skb_reserve(skb, local->hw.extra_tx_headroom);
++ /* 25 is the size of the common mgmt part (24) plus the size of the
++ * common action part (1)
++ */
++ mgmt = (struct ieee80211_mgmt *)
++ skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action));
++ memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action));
++ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++ IEEE80211_STYPE_ACTION);
++
++ memcpy(mgmt->da, da, ETH_ALEN);
++ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
++ /* BSSID is left zeroed, wildcard value */
++ mgmt->u.action.category = MESH_PATH_SEL_CATEGORY;
++ mgmt->u.action.u.mesh_action.action_code = action;
++
++ switch (action) {
++ case MPATH_PREQ:
++ ie_len = 37;
++ pos = skb_put(skb, 2 + ie_len);
++ *pos++ = WLAN_EID_PREQ;
++ break;
++ case MPATH_PREP:
++ ie_len = 31;
++ pos = skb_put(skb, 2 + ie_len);
++ *pos++ = WLAN_EID_PREP;
++ break;
++ default:
++ kfree(skb);
++ return -ENOTSUPP;
++ break;
++ }
++ *pos++ = ie_len;
++ *pos++ = flags;
++ *pos++ = hop_count;
++ *pos++ = ttl;
++ if (action == MPATH_PREQ) {
++ memcpy(pos, &preq_id, 4);
++ pos += 4;
++ }
++ memcpy(pos, orig_addr, ETH_ALEN);
++ pos += ETH_ALEN;
++ memcpy(pos, &orig_dsn, 4);
++ pos += 4;
++ memcpy(pos, &lifetime, 4);
++ pos += 4;
++ memcpy(pos, &metric, 4);
++ pos += 4;
++ if (action == MPATH_PREQ) {
++ /* destination count */
++ *pos++ = 1;
++ *pos++ = dst_flags;
++ }
++ memcpy(pos, dst, ETH_ALEN);
++ pos += ETH_ALEN;
++ memcpy(pos, &dst_dsn, 4);
++
++ ieee80211_sta_tx(dev, skb, 0);
++ return 0;
++}
++
++/**
++ * mesh_send_path error - Sends a PERR mesh management frame
++ *
++ * @dst: broken destination
++ * @dst_dsn: dsn of the broken destination
++ * @ra: node this frame is addressed to
++ */
++int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra,
++ struct net_device *dev)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
++ struct ieee80211_mgmt *mgmt;
++ u8 *pos;
++ int ie_len;
++
++ if (!skb)
++ return -1;
++ skb_reserve(skb, local->hw.extra_tx_headroom);
++ /* 25 is the size of the common mgmt part (24) plus the size of the
++ * common action part (1)
++ */
++ mgmt = (struct ieee80211_mgmt *)
++ skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action));
++ memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action));
++ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++ IEEE80211_STYPE_ACTION);
++
++ memcpy(mgmt->da, ra, ETH_ALEN);
++ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
++ /* BSSID is left zeroed, wildcard value */
++ mgmt->u.action.category = MESH_PATH_SEL_CATEGORY;
++ mgmt->u.action.u.mesh_action.action_code = MPATH_PERR;
++ ie_len = 12;
++ pos = skb_put(skb, 2 + ie_len);
++ *pos++ = WLAN_EID_PERR;
++ *pos++ = ie_len;
++ /* mode flags, reserved */
++ *pos++ = 0;
++ /* number of destinations */
++ *pos++ = 1;
++ memcpy(pos, dst, ETH_ALEN);
++ pos += ETH_ALEN;
++ memcpy(pos, &dst_dsn, 4);
++
++ ieee80211_sta_tx(dev, skb, 0);
++ return 0;
++}
++
++static u32 airtime_link_metric_get(struct ieee80211_local *local,
++ struct sta_info *sta)
++{
++ struct ieee80211_supported_band *sband;
++ /* This should be adjusted for each device */
++ int device_constant = 1 << ARITH_SHIFT;
++ int test_frame_len = TEST_FRAME_LEN << ARITH_SHIFT;
++ int s_unit = 1 << ARITH_SHIFT;
++ int rate, err;
++ u32 tx_time, estimated_retx;
++ u64 result;
++
++ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++
++ if (sta->fail_avg >= 100)
++ return MAX_METRIC;
++ err = (sta->fail_avg << ARITH_SHIFT) / 100;
++
++ /* bitrate is in units of 100 Kbps, while we need rate in units of
++ * 1Mbps. This will be corrected on tx_time computation.
++ */
++ rate = sband->bitrates[sta->txrate_idx].bitrate;
++ tx_time = (device_constant + 10 * test_frame_len / rate);
++ estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err));
++ result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ;
++ return (u32)result;
++}
++
++/**
++ * hwmp_route_info_get - Update routing info to originator and transmitter
++ *
++ * @dev: local mesh interface
++ * @mgmt: mesh management frame
++ * @hwmp_ie: hwmp information element (PREP or PREQ)
++ *
++ * This function updates the path routing information to the originator and the
++ * transmitter of a HWMP PREQ or PREP fram.
++ *
++ * Returns: metric to frame originator or 0 if the frame should not be further
++ * processed
++ *
++ * Notes: this function is the only place (besides user-provided info) where
++ * path routing information is updated.
++ */
++static u32 hwmp_route_info_get(struct net_device *dev,
++ struct ieee80211_mgmt *mgmt,
++ u8 *hwmp_ie)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct mesh_path *mpath;
++ struct sta_info *sta;
++ bool fresh_info;
++ u8 *orig_addr, *ta;
++ u32 orig_dsn, orig_metric;
++ unsigned long orig_lifetime, exp_time;
++ u32 last_hop_metric, new_metric;
++ bool process = true;
++ u8 action = mgmt->u.action.u.mesh_action.action_code;
++
++ rcu_read_lock();
++ sta = sta_info_get(local, mgmt->sa);
++ if (!sta) {
++ rcu_read_unlock();
++ return 0;
++ }
++
++ last_hop_metric = airtime_link_metric_get(local, sta);
++ /* Update and check originator routing info */
++ fresh_info = true;
++
++ switch (action) {
++ case MPATH_PREQ:
++ orig_addr = PREQ_IE_ORIG_ADDR(hwmp_ie);
++ orig_dsn = PREQ_IE_ORIG_DSN(hwmp_ie);
++ orig_lifetime = PREQ_IE_LIFETIME(hwmp_ie);
++ orig_metric = PREQ_IE_METRIC(hwmp_ie);
++ break;
++ case MPATH_PREP:
++ /* Originator here refers to the MP that was the destination in
++ * the Path Request. The draft refers to that MP as the
++ * destination address, even though usually it is the origin of
++ * the PREP frame. We divert from the nomenclature in the draft
++ * so that we can easily use a single function to gather path
++ * information from both PREQ and PREP frames.
++ */
++ orig_addr = PREP_IE_ORIG_ADDR(hwmp_ie);
++ orig_dsn = PREP_IE_ORIG_DSN(hwmp_ie);
++ orig_lifetime = PREP_IE_LIFETIME(hwmp_ie);
++ orig_metric = PREP_IE_METRIC(hwmp_ie);
++ break;
++ default:
++ rcu_read_unlock();
++ return 0;
++ }
++ new_metric = orig_metric + last_hop_metric;
++ if (new_metric < orig_metric)
++ new_metric = MAX_METRIC;
++ exp_time = TU_TO_EXP_TIME(orig_lifetime);
++
++ if (memcmp(orig_addr, dev->dev_addr, ETH_ALEN) == 0) {
++ /* This MP is the originator, we are not interested in this
++ * frame, except for updating transmitter's path info.
++ */
++ process = false;
++ fresh_info = false;
++ } else {
++ mpath = mesh_path_lookup(orig_addr, dev);
++ if (mpath) {
++ spin_lock_bh(&mpath->state_lock);
++ if (mpath->flags & MESH_PATH_FIXED)
++ fresh_info = false;
++ else if ((mpath->flags & MESH_PATH_ACTIVE) &&
++ (mpath->flags & MESH_PATH_DSN_VALID)) {
++ if (DSN_GT(mpath->dsn, orig_dsn) ||
++ (mpath->dsn == orig_dsn &&
++ action == MPATH_PREQ &&
++ new_metric > mpath->metric)) {
++ process = false;
++ fresh_info = false;
++ }
++ }
++ } else {
++ mesh_path_add(orig_addr, dev);
++ mpath = mesh_path_lookup(orig_addr, dev);
++ if (!mpath) {
++ rcu_read_unlock();
++ return 0;
++ }
++ spin_lock_bh(&mpath->state_lock);
++ }
++
++ if (fresh_info) {
++ mesh_path_assign_nexthop(mpath, sta);
++ mpath->flags |= MESH_PATH_DSN_VALID;
++ mpath->metric = new_metric;
++ mpath->dsn = orig_dsn;
++ mpath->exp_time = time_after(mpath->exp_time, exp_time)
++ ? mpath->exp_time : exp_time;
++ mesh_path_activate(mpath);
++ spin_unlock_bh(&mpath->state_lock);
++ mesh_path_tx_pending(mpath);
++ /* draft says preq_id should be saved to, but there does
++ * not seem to be any use for it, skipping by now
++ */
++ } else
++ spin_unlock_bh(&mpath->state_lock);
++ }
++
++ /* Update and check transmitter routing info */
++ ta = mgmt->sa;
++ if (memcmp(orig_addr, ta, ETH_ALEN) == 0)
++ fresh_info = false;
++ else {
++ fresh_info = true;
++
++ mpath = mesh_path_lookup(ta, dev);
++ if (mpath) {
++ spin_lock_bh(&mpath->state_lock);
++ if ((mpath->flags & MESH_PATH_FIXED) ||
++ ((mpath->flags & MESH_PATH_ACTIVE) &&
++ (last_hop_metric > mpath->metric)))
++ fresh_info = false;
++ } else {
++ mesh_path_add(ta, dev);
++ mpath = mesh_path_lookup(ta, dev);
++ if (!mpath) {
++ rcu_read_unlock();
++ return 0;
++ }
++ spin_lock_bh(&mpath->state_lock);
++ }
++
++ if (fresh_info) {
++ mesh_path_assign_nexthop(mpath, sta);
++ mpath->flags &= ~MESH_PATH_DSN_VALID;
++ mpath->metric = last_hop_metric;
++ mpath->exp_time = time_after(mpath->exp_time, exp_time)
++ ? mpath->exp_time : exp_time;
++ mesh_path_activate(mpath);
++ spin_unlock_bh(&mpath->state_lock);
++ mesh_path_tx_pending(mpath);
++ } else
++ spin_unlock_bh(&mpath->state_lock);
++ }
++
++ rcu_read_unlock();
++
++ return process ? new_metric : 0;
++}
++
++static void hwmp_preq_frame_process(struct net_device *dev,
++ struct ieee80211_mgmt *mgmt,
++ u8 *preq_elem, u32 metric) {
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++ struct mesh_path *mpath;
++ u8 *dst_addr, *orig_addr;
++ u8 dst_flags, ttl;
++ u32 orig_dsn, dst_dsn, lifetime;
++ bool reply = false;
++ bool forward = true;
++
++ /* Update destination DSN, if present */
++ dst_addr = PREQ_IE_DST_ADDR(preq_elem);
++ orig_addr = PREQ_IE_ORIG_ADDR(preq_elem);
++ dst_dsn = PREQ_IE_DST_DSN(preq_elem);
++ orig_dsn = PREQ_IE_ORIG_DSN(preq_elem);
++ dst_flags = PREQ_IE_DST_F(preq_elem);
++
++ if (memcmp(dst_addr, dev->dev_addr, ETH_ALEN) == 0) {
++ forward = false;
++ reply = true;
++ metric = 0;
++ if (time_after(jiffies, ifsta->last_dsn_update +
++ net_traversal_jiffies(sdata)) ||
++ time_before(jiffies, ifsta->last_dsn_update)) {
++ dst_dsn = ++ifsta->dsn;
++ ifsta->last_dsn_update = jiffies;
++ }
++ } else {
++ rcu_read_lock();
++ mpath = mesh_path_lookup(dst_addr, dev);
++ if (mpath) {
++ if ((!(mpath->flags & MESH_PATH_DSN_VALID)) ||
++ DSN_LT(mpath->dsn, dst_dsn)) {
++ mpath->dsn = dst_dsn;
++ mpath->flags &= MESH_PATH_DSN_VALID;
++ } else if ((!(dst_flags & MP_F_DO)) &&
++ (mpath->flags & MESH_PATH_ACTIVE)) {
++ reply = true;
++ metric = mpath->metric;
++ dst_dsn = mpath->dsn;
++ if (dst_flags & MP_F_RF)
++ dst_flags |= MP_F_DO;
++ else
++ forward = false;
++ }
++ }
++ rcu_read_unlock();
++ }
++
++ if (reply) {
++ lifetime = PREQ_IE_LIFETIME(preq_elem);
++ ttl = ifsta->mshcfg.dot11MeshTTL;
++ if (ttl != 0)
++ mesh_path_sel_frame_tx(MPATH_PREP, 0, dst_addr,
++ cpu_to_le32(dst_dsn), 0, orig_addr,
++ cpu_to_le32(orig_dsn), mgmt->sa, 0, ttl,
++ cpu_to_le32(lifetime), cpu_to_le32(metric),
++ 0, dev);
++ else
++ ifsta->mshstats.dropped_frames_ttl++;
++ }
++
++ if (forward) {
++ u32 preq_id;
++ u8 hopcount, flags;
++
++ ttl = PREQ_IE_TTL(preq_elem);
++ lifetime = PREQ_IE_LIFETIME(preq_elem);
++ if (ttl <= 1) {
++ ifsta->mshstats.dropped_frames_ttl++;
++ return;
++ }
++ --ttl;
++ flags = PREQ_IE_FLAGS(preq_elem);
++ preq_id = PREQ_IE_PREQ_ID(preq_elem);
++ hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1;
++ mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr,
++ cpu_to_le32(orig_dsn), dst_flags, dst_addr,
++ cpu_to_le32(dst_dsn), dev->broadcast,
++ hopcount, ttl, cpu_to_le32(lifetime),
++ cpu_to_le32(metric), cpu_to_le32(preq_id),
++ dev);
++ ifsta->mshstats.fwded_frames++;
++ }
++}
++
++
++static void hwmp_prep_frame_process(struct net_device *dev,
++ struct ieee80211_mgmt *mgmt,
++ u8 *prep_elem, u32 metric)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct mesh_path *mpath;
++ u8 *dst_addr, *orig_addr;
++ u8 ttl, hopcount, flags;
++ u8 next_hop[ETH_ALEN];
++ u32 dst_dsn, orig_dsn, lifetime;
++
++ /* Note that we divert from the draft nomenclature and denominate
++ * destination to what the draft refers to as origininator. So in this
++ * function destnation refers to the final destination of the PREP,
++ * which corresponds with the originator of the PREQ which this PREP
++ * replies
++ */
++ dst_addr = PREP_IE_DST_ADDR(prep_elem);
++ if (memcmp(dst_addr, dev->dev_addr, ETH_ALEN) == 0)
++ /* destination, no forwarding required */
++ return;
++
++ ttl = PREP_IE_TTL(prep_elem);
++ if (ttl <= 1) {
++ sdata->u.sta.mshstats.dropped_frames_ttl++;
++ return;
++ }
++
++ rcu_read_lock();
++ mpath = mesh_path_lookup(dst_addr, dev);
++ if (mpath)
++ spin_lock_bh(&mpath->state_lock);
++ else
++ goto fail;
++ if (!(mpath->flags & MESH_PATH_ACTIVE)) {
++ spin_unlock_bh(&mpath->state_lock);
++ goto fail;
++ }
++ memcpy(next_hop, mpath->next_hop->addr, ETH_ALEN);
++ spin_unlock_bh(&mpath->state_lock);
++ --ttl;
++ flags = PREP_IE_FLAGS(prep_elem);
++ lifetime = PREP_IE_LIFETIME(prep_elem);
++ hopcount = PREP_IE_HOPCOUNT(prep_elem) + 1;
++ orig_addr = PREP_IE_ORIG_ADDR(prep_elem);
++ dst_dsn = PREP_IE_DST_DSN(prep_elem);
++ orig_dsn = PREP_IE_ORIG_DSN(prep_elem);
++
++ mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr,
++ cpu_to_le32(orig_dsn), 0, dst_addr,
++ cpu_to_le32(dst_dsn), mpath->next_hop->addr, hopcount, ttl,
++ cpu_to_le32(lifetime), cpu_to_le32(metric),
++ 0, dev);
++ rcu_read_unlock();
++ sdata->u.sta.mshstats.fwded_frames++;
++ return;
++
++fail:
++ rcu_read_unlock();
++ sdata->u.sta.mshstats.dropped_frames_no_route++;
++ return;
++}
++
++static void hwmp_perr_frame_process(struct net_device *dev,
++ struct ieee80211_mgmt *mgmt, u8 *perr_elem)
++{
++ struct mesh_path *mpath;
++ u8 *ta, *dst_addr;
++ u32 dst_dsn;
++
++ ta = mgmt->sa;
++ dst_addr = PERR_IE_DST_ADDR(perr_elem);
++ dst_dsn = PERR_IE_DST_DSN(perr_elem);
++ rcu_read_lock();
++ mpath = mesh_path_lookup(dst_addr, dev);
++ if (mpath) {
++ spin_lock_bh(&mpath->state_lock);
++ if (mpath->flags & MESH_PATH_ACTIVE &&
++ memcmp(ta, mpath->next_hop->addr, ETH_ALEN) == 0 &&
++ (!(mpath->flags & MESH_PATH_DSN_VALID) ||
++ DSN_GT(dst_dsn, mpath->dsn))) {
++ mpath->flags &= ~MESH_PATH_ACTIVE;
++ mpath->dsn = dst_dsn;
++ spin_unlock_bh(&mpath->state_lock);
++ mesh_path_error_tx(dst_addr, cpu_to_le32(dst_dsn),
++ dev->broadcast, dev);
++ } else
++ spin_unlock_bh(&mpath->state_lock);
++ }
++ rcu_read_unlock();
++}
++
++
++
++void mesh_rx_path_sel_frame(struct net_device *dev,
++ struct ieee80211_mgmt *mgmt,
++ size_t len)
++{
++ struct ieee802_11_elems elems;
++ size_t baselen;
++ u32 last_hop_metric;
++
++ baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt;
++ ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
++ len - baselen, &elems);
++
++ switch (mgmt->u.action.u.mesh_action.action_code) {
++ case MPATH_PREQ:
++ if (!elems.preq || elems.preq_len != 37)
++ /* Right now we support just 1 destination and no AE */
++ return;
++ last_hop_metric = hwmp_route_info_get(dev, mgmt, elems.preq);
++ if (!last_hop_metric)
++ return;
++ hwmp_preq_frame_process(dev, mgmt, elems.preq, last_hop_metric);
++ break;
++ case MPATH_PREP:
++ if (!elems.prep || elems.prep_len != 31)
++ /* Right now we support no AE */
++ return;
++ last_hop_metric = hwmp_route_info_get(dev, mgmt, elems.prep);
++ if (!last_hop_metric)
++ return;
++ hwmp_prep_frame_process(dev, mgmt, elems.prep, last_hop_metric);
++ break;
++ case MPATH_PERR:
++ if (!elems.perr || elems.perr_len != 12)
++ /* Right now we support only one destination per PERR */
++ return;
++ hwmp_perr_frame_process(dev, mgmt, elems.perr);
++ default:
++ return;
++ }
++
++}
++
++/**
++ * mesh_queue_preq - queue a PREQ to a given destination
++ *
++ * @mpath: mesh path to discover
++ * @flags: special attributes of the PREQ to be sent
++ *
++ * Locking: the function must be called from within a rcu read lock block.
++ *
++ */
++static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
++{
++ struct ieee80211_sub_if_data *sdata =
++ IEEE80211_DEV_TO_SUB_IF(mpath->dev);
++ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++ struct mesh_preq_queue *preq_node;
++
++ preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_KERNEL);
++ if (!preq_node) {
++ printk(KERN_DEBUG "Mesh HWMP: could not allocate PREQ node\n");
++ return;
++ }
++
++ spin_lock(&ifsta->mesh_preq_queue_lock);
++ if (ifsta->preq_queue_len == MAX_PREQ_QUEUE_LEN) {
++ spin_unlock(&ifsta->mesh_preq_queue_lock);
++ kfree(preq_node);
++ if (printk_ratelimit())
++ printk(KERN_DEBUG "Mesh HWMP: PREQ node queue full\n");
++ return;
++ }
++
++ memcpy(preq_node->dst, mpath->dst, ETH_ALEN);
++ preq_node->flags = flags;
++
++ list_add_tail(&preq_node->list, &ifsta->preq_queue.list);
++ ++ifsta->preq_queue_len;
++ spin_unlock(&ifsta->mesh_preq_queue_lock);
++
++ if (time_after(jiffies, ifsta->last_preq + min_preq_int_jiff(sdata)))
++ queue_work(sdata->local->hw.workqueue, &ifsta->work);
++
++ else if (time_before(jiffies, ifsta->last_preq)) {
++ /* avoid long wait if did not send preqs for a long time
++ * and jiffies wrapped around
++ */
++ ifsta->last_preq = jiffies - min_preq_int_jiff(sdata) - 1;
++ queue_work(sdata->local->hw.workqueue, &ifsta->work);
++ } else
++ mod_timer(&ifsta->mesh_path_timer, ifsta->last_preq +
++ min_preq_int_jiff(sdata));
++}
++
++/**
++ * mesh_path_start_discovery - launch a path discovery from the PREQ queue
++ *
++ * @dev: local mesh interface
++ */
++void mesh_path_start_discovery(struct net_device *dev)
++{
++ struct ieee80211_sub_if_data *sdata =
++ IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++ struct mesh_preq_queue *preq_node;
++ struct mesh_path *mpath;
++ u8 ttl, dst_flags;
++ u32 lifetime;
++
++ spin_lock(&ifsta->mesh_preq_queue_lock);
++ if (!ifsta->preq_queue_len ||
++ time_before(jiffies, ifsta->last_preq +
++ min_preq_int_jiff(sdata))) {
++ spin_unlock(&ifsta->mesh_preq_queue_lock);
++ return;
++ }
++
++ preq_node = list_first_entry(&ifsta->preq_queue.list,
++ struct mesh_preq_queue, list);
++ list_del(&preq_node->list);
++ --ifsta->preq_queue_len;
++ spin_unlock(&ifsta->mesh_preq_queue_lock);
++
++ rcu_read_lock();
++ mpath = mesh_path_lookup(preq_node->dst, dev);
++ if (!mpath)
++ goto enddiscovery;
++
++ spin_lock_bh(&mpath->state_lock);
++ if (preq_node->flags & PREQ_Q_F_START) {
++ if (mpath->flags & MESH_PATH_RESOLVING) {
++ spin_unlock_bh(&mpath->state_lock);
++ goto enddiscovery;
++ } else {
++ mpath->flags &= ~MESH_PATH_RESOLVED;
++ mpath->flags |= MESH_PATH_RESOLVING;
++ mpath->discovery_retries = 0;
++ mpath->discovery_timeout = disc_timeout_jiff(sdata);
++ }
++ } else if (!(mpath->flags & MESH_PATH_RESOLVING) ||
++ mpath->flags & MESH_PATH_RESOLVED) {
++ mpath->flags &= ~MESH_PATH_RESOLVING;
++ spin_unlock_bh(&mpath->state_lock);
++ goto enddiscovery;
++ }
++
++ ifsta->last_preq = jiffies;
++
++ if (time_after(jiffies, ifsta->last_dsn_update +
++ net_traversal_jiffies(sdata)) ||
++ time_before(jiffies, ifsta->last_dsn_update)) {
++ ++ifsta->dsn;
++ sdata->u.sta.last_dsn_update = jiffies;
++ }
++ lifetime = default_lifetime(sdata);
++ ttl = sdata->u.sta.mshcfg.dot11MeshTTL;
++ if (ttl == 0) {
++ sdata->u.sta.mshstats.dropped_frames_ttl++;
++ spin_unlock_bh(&mpath->state_lock);
++ goto enddiscovery;
++ }
++
++ if (preq_node->flags & PREQ_Q_F_REFRESH)
++ dst_flags = MP_F_DO;
++ else
++ dst_flags = MP_F_RF;
++
++ spin_unlock_bh(&mpath->state_lock);
++ mesh_path_sel_frame_tx(MPATH_PREQ, 0, dev->dev_addr,
++ cpu_to_le32(ifsta->dsn), dst_flags, mpath->dst,
++ cpu_to_le32(mpath->dsn), dev->broadcast, 0,
++ ttl, cpu_to_le32(lifetime), 0,
++ cpu_to_le32(ifsta->preq_id++), dev);
++ mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout);
++
++enddiscovery:
++ rcu_read_unlock();
++ kfree(preq_node);
++}
++
++/**
++ * ieee80211s_lookup_nexthop - put the appropriate next hop on a mesh frame
++ *
++ * @next_hop: output argument for next hop address
++ * @skb: frame to be sent
++ * @dev: network device the frame will be sent through
++ *
++ * Returns: 0 if the next hop was found. Nonzero otherwise. If no next hop is
++ * found, the function will start a path discovery and queue the frame so it is
++ * sent when the path is resolved. This means the caller must not free the skb
++ * in this case.
++ */
++int mesh_nexthop_lookup(u8 *next_hop, struct sk_buff *skb,
++ struct net_device *dev)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct sk_buff *skb_to_free = NULL;
++ struct mesh_path *mpath;
++ int err = 0;
++
++ rcu_read_lock();
++ mpath = mesh_path_lookup(skb->data, dev);
++
++ if (!mpath) {
++ mesh_path_add(skb->data, dev);
++ mpath = mesh_path_lookup(skb->data, dev);
++ if (!mpath) {
++ dev_kfree_skb(skb);
++ sdata->u.sta.mshstats.dropped_frames_no_route++;
++ err = -ENOSPC;
++ goto endlookup;
++ }
++ }
++
++ if (mpath->flags & MESH_PATH_ACTIVE) {
++ if (time_after(jiffies, mpath->exp_time -
++ msecs_to_jiffies(sdata->u.sta.mshcfg.path_refresh_time))
++ && skb->pkt_type != PACKET_OTHERHOST
++ && !(mpath->flags & MESH_PATH_RESOLVING)
++ && !(mpath->flags & MESH_PATH_FIXED)) {
++ mesh_queue_preq(mpath,
++ PREQ_Q_F_START | PREQ_Q_F_REFRESH);
++ }
++ memcpy(next_hop, mpath->next_hop->addr,
++ ETH_ALEN);
++ } else {
++ if (!(mpath->flags & MESH_PATH_RESOLVING)) {
++ /* Start discovery only if it is not running yet */
++ mesh_queue_preq(mpath, PREQ_Q_F_START);
++ }
++
++ if (skb_queue_len(&mpath->frame_queue) >=
++ MESH_FRAME_QUEUE_LEN) {
++ skb_to_free = mpath->frame_queue.next;
++ skb_unlink(skb_to_free, &mpath->frame_queue);
++ }
++
++ skb_queue_tail(&mpath->frame_queue, skb);
++ if (skb_to_free)
++ mesh_path_discard_frame(skb_to_free, dev);
++ err = -ENOENT;
++ }
++
++endlookup:
++ rcu_read_unlock();
++ return err;
++}
++
++void mesh_path_timer(unsigned long data)
++{
++ struct ieee80211_sub_if_data *sdata;
++ struct mesh_path *mpath;
++
++ rcu_read_lock();
++ mpath = (struct mesh_path *) data;
++ mpath = rcu_dereference(mpath);
++ if (!mpath)
++ goto endmpathtimer;
++ spin_lock_bh(&mpath->state_lock);
++ sdata = IEEE80211_DEV_TO_SUB_IF(mpath->dev);
++ if (mpath->flags & MESH_PATH_RESOLVED ||
++ (!(mpath->flags & MESH_PATH_RESOLVING)))
++ mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED);
++ else if (mpath->discovery_retries < max_preq_retries(sdata)) {
++ ++mpath->discovery_retries;
++ mpath->discovery_timeout *= 2;
++ mesh_queue_preq(mpath, 0);
++ } else {
++ mpath->flags = 0;
++ mpath->exp_time = jiffies;
++ mesh_path_flush_pending(mpath);
++ }
++
++ spin_unlock_bh(&mpath->state_lock);
++endmpathtimer:
++ rcu_read_unlock();
++}
+diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
+new file mode 100644
+index 0000000..5845dc2
+--- /dev/null
++++ b/net/mac80211/mesh_pathtbl.c
+@@ -0,0 +1,516 @@
++/*
++ * Copyright (c) 2008 open80211s Ltd.
++ * Author: Luis Carlos Cobo <luisca at cozybit.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/etherdevice.h>
++#include <linux/list.h>
++#include <linux/netdevice.h>
++#include <linux/random.h>
++#include <linux/spinlock.h>
++#include <linux/string.h>
++#include <net/mac80211.h>
++#include "ieee80211_i.h"
++#include "mesh.h"
++
++/* There will be initially 2^INIT_PATHS_SIZE_ORDER buckets */
++#define INIT_PATHS_SIZE_ORDER 2
++
++/* Keep the mean chain length below this constant */
++#define MEAN_CHAIN_LEN 2
++
++#define MPATH_EXPIRED(mpath) ((mpath->flags & MESH_PATH_ACTIVE) && \
++ time_after(jiffies, mpath->exp_time) && \
++ !(mpath->flags & MESH_PATH_FIXED))
++
++struct mpath_node {
++ struct hlist_node list;
++ struct rcu_head rcu;
++ /* This indirection allows two different tables to point to the same
++ * mesh_path structure, useful when resizing
++ */
++ struct mesh_path *mpath;
++};
++
++static struct mesh_table *mesh_paths;
++
++/* This lock will have the grow table function as writer and add / delete nodes
++ * as readers. When reading the table (i.e. doing lookups) we are well protected
++ * by RCU
++ */
++static DEFINE_RWLOCK(pathtbl_resize_lock);
++
++/**
++ *
++ * mesh_path_assign_nexthop - update mesh path next hop
++ *
++ * @mpath: mesh path to update
++ * @sta: next hop to assign
++ *
++ * Locking: mpath->state_lock must be held when calling this function
++ */
++void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta)
++{
++ rcu_assign_pointer(mpath->next_hop, sta);
++}
++
++
++/**
++ * mesh_path_lookup - look up a path in the mesh path table
++ * @dst: hardware address (ETH_ALEN length) of destination
++ * @dev: local interface
++ *
++ * Returns: pointer to the mesh path structure, or NULL if not found
++ *
++ * Locking: must be called within a read rcu section.
++ */
++struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev)
++{
++ struct mesh_path *mpath;
++ struct hlist_node *n;
++ struct hlist_head *bucket;
++ struct mesh_table *tbl;
++ struct mpath_node *node;
++
++ tbl = rcu_dereference(mesh_paths);
++
++ bucket = &tbl->hash_buckets[mesh_table_hash(dst, dev, tbl)];
++ hlist_for_each_entry_rcu(node, n, bucket, list) {
++ mpath = node->mpath;
++ if (mpath->dev == dev &&
++ memcmp(dst, mpath->dst, ETH_ALEN) == 0) {
++ if (MPATH_EXPIRED(mpath)) {
++ spin_lock_bh(&mpath->state_lock);
++ if (MPATH_EXPIRED(mpath))
++ mpath->flags &= ~MESH_PATH_ACTIVE;
++ spin_unlock_bh(&mpath->state_lock);
++ }
++ return mpath;
++ }
++ }
++ return NULL;
++}
++
++/**
++ * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index
++ * @idx: index
++ * @dev: local interface, or NULL for all entries
++ *
++ * Returns: pointer to the mesh path structure, or NULL if not found.
++ *
++ * Locking: must be called within a read rcu section.
++ */
++struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev)
++{
++ struct mpath_node *node;
++ struct hlist_node *p;
++ int i;
++ int j = 0;
++
++ for_each_mesh_entry(mesh_paths, p, node, i) {
++ if (dev && node->mpath->dev != dev)
++ continue;
++ if (j++ == idx) {
++ if (MPATH_EXPIRED(node->mpath)) {
++ spin_lock_bh(&node->mpath->state_lock);
++ if (MPATH_EXPIRED(node->mpath))
++ node->mpath->flags &= ~MESH_PATH_ACTIVE;
++ spin_unlock_bh(&node->mpath->state_lock);
++ }
++ return node->mpath;
++ }
++ }
++
++ return NULL;
++}
++
++/**
++ * mesh_path_add - allocate and add a new path to the mesh path table
++ * @addr: destination address of the path (ETH_ALEN length)
++ * @dev: local interface
++ *
++ * Returns: 0 on sucess
++ *
++ * State: the initial state of the new path is set to 0
++ */
++int mesh_path_add(u8 *dst, struct net_device *dev)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct mesh_path *mpath, *new_mpath;
++ struct mpath_node *node, *new_node;
++ struct hlist_head *bucket;
++ struct hlist_node *n;
++ int grow = 0;
++ int err = 0;
++ u32 hash_idx;
++
++ if (memcmp(dst, dev->dev_addr, ETH_ALEN) == 0)
++ /* never add ourselves as neighbours */
++ return -ENOTSUPP;
++
++ if (is_multicast_ether_addr(dst))
++ return -ENOTSUPP;
++
++ if (atomic_add_unless(&sdata->u.sta.mpaths, 1, MESH_MAX_MPATHS) == 0)
++ return -ENOSPC;
++
++ read_lock(&pathtbl_resize_lock);
++
++ new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL);
++ if (!new_mpath) {
++ atomic_dec(&sdata->u.sta.mpaths);
++ err = -ENOMEM;
++ goto endadd2;
++ }
++ memcpy(new_mpath->dst, dst, ETH_ALEN);
++ new_mpath->dev = dev;
++ new_mpath->flags = 0;
++ skb_queue_head_init(&new_mpath->frame_queue);
++ new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL);
++ new_node->mpath = new_mpath;
++ new_mpath->timer.data = (unsigned long) new_mpath;
++ new_mpath->timer.function = mesh_path_timer;
++ new_mpath->exp_time = jiffies;
++ spin_lock_init(&new_mpath->state_lock);
++ init_timer(&new_mpath->timer);
++
++ hash_idx = mesh_table_hash(dst, dev, mesh_paths);
++ bucket = &mesh_paths->hash_buckets[hash_idx];
++
++ spin_lock(&mesh_paths->hashwlock[hash_idx]);
++
++ hlist_for_each_entry(node, n, bucket, list) {
++ mpath = node->mpath;
++ if (mpath->dev == dev && memcmp(dst, mpath->dst, ETH_ALEN)
++ == 0) {
++ err = -EEXIST;
++ atomic_dec(&sdata->u.sta.mpaths);
++ kfree(new_node);
++ kfree(new_mpath);
++ goto endadd;
++ }
++ }
++
++ hlist_add_head_rcu(&new_node->list, bucket);
++ if (atomic_inc_return(&mesh_paths->entries) >=
++ mesh_paths->mean_chain_len * (mesh_paths->hash_mask + 1))
++ grow = 1;
++
++endadd:
++ spin_unlock(&mesh_paths->hashwlock[hash_idx]);
++endadd2:
++ read_unlock(&pathtbl_resize_lock);
++ if (!err && grow) {
++ struct mesh_table *oldtbl, *newtbl;
++
++ write_lock(&pathtbl_resize_lock);
++ oldtbl = mesh_paths;
++ newtbl = mesh_table_grow(mesh_paths);
++ if (!newtbl) {
++ write_unlock(&pathtbl_resize_lock);
++ return -ENOMEM;
++ }
++ rcu_assign_pointer(mesh_paths, newtbl);
++ synchronize_rcu();
++ mesh_table_free(oldtbl, false);
++ write_unlock(&pathtbl_resize_lock);
++ }
++ return err;
++}
++
++
++/**
++ * mesh_plink_broken - deactivates paths and sends perr when a link breaks
++ *
++ * @sta: broken peer link
++ *
++ * This function must be called from the rate control algorithm if enough
++ * delivery errors suggest that a peer link is no longer usable.
++ */
++void mesh_plink_broken(struct sta_info *sta)
++{
++ struct mesh_path *mpath;
++ struct mpath_node *node;
++ struct hlist_node *p;
++ struct net_device *dev = sta->sdata->dev;
++ int i;
++
++ rcu_read_lock();
++ for_each_mesh_entry(mesh_paths, p, node, i) {
++ mpath = node->mpath;
++ spin_lock_bh(&mpath->state_lock);
++ if (mpath->next_hop == sta &&
++ mpath->flags & MESH_PATH_ACTIVE &&
++ !(mpath->flags & MESH_PATH_FIXED)) {
++ mpath->flags &= ~MESH_PATH_ACTIVE;
++ ++mpath->dsn;
++ spin_unlock_bh(&mpath->state_lock);
++ mesh_path_error_tx(mpath->dst,
++ cpu_to_le32(mpath->dsn),
++ dev->broadcast, dev);
++ } else
++ spin_unlock_bh(&mpath->state_lock);
++ }
++ rcu_read_unlock();
++}
++EXPORT_SYMBOL(mesh_plink_broken);
++
++/**
++ * mesh_path_flush_by_nexthop - Deletes mesh paths if their next hop matches
++ *
++ * @sta - mesh peer to match
++ *
++ * RCU notes: this function is called when a mesh plink transitions from
++ * PLINK_ESTAB to any other state, since PLINK_ESTAB state is the only one that
++ * allows path creation. This will happen before the sta can be freed (because
++ * sta_info_destroy() calls this) so any reader in a rcu read block will be
++ * protected against the plink disappearing.
++ */
++void mesh_path_flush_by_nexthop(struct sta_info *sta)
++{
++ struct mesh_path *mpath;
++ struct mpath_node *node;
++ struct hlist_node *p;
++ int i;
++
++ for_each_mesh_entry(mesh_paths, p, node, i) {
++ mpath = node->mpath;
++ if (mpath->next_hop == sta)
++ mesh_path_del(mpath->dst, mpath->dev);
++ }
++}
++
++void mesh_path_flush(struct net_device *dev)
++{
++ struct mesh_path *mpath;
++ struct mpath_node *node;
++ struct hlist_node *p;
++ int i;
++
++ for_each_mesh_entry(mesh_paths, p, node, i) {
++ mpath = node->mpath;
++ if (mpath->dev == dev)
++ mesh_path_del(mpath->dst, mpath->dev);
++ }
++}
++
++static void mesh_path_node_reclaim(struct rcu_head *rp)
++{
++ struct mpath_node *node = container_of(rp, struct mpath_node, rcu);
++ struct ieee80211_sub_if_data *sdata =
++ IEEE80211_DEV_TO_SUB_IF(node->mpath->dev);
++
++ del_timer_sync(&node->mpath->timer);
++ atomic_dec(&sdata->u.sta.mpaths);
++ kfree(node->mpath);
++ kfree(node);
++}
++
++/**
++ * mesh_path_del - delete a mesh path from the table
++ *
++ * @addr: dst address (ETH_ALEN length)
++ * @dev: local interface
++ *
++ * Returns: 0 if succesful
++ */
++int mesh_path_del(u8 *addr, struct net_device *dev)
++{
++ struct mesh_path *mpath;
++ struct mpath_node *node;
++ struct hlist_head *bucket;
++ struct hlist_node *n;
++ int hash_idx;
++ int err = 0;
++
++ read_lock(&pathtbl_resize_lock);
++ hash_idx = mesh_table_hash(addr, dev, mesh_paths);
++ bucket = &mesh_paths->hash_buckets[hash_idx];
++
++ spin_lock(&mesh_paths->hashwlock[hash_idx]);
++ hlist_for_each_entry(node, n, bucket, list) {
++ mpath = node->mpath;
++ if (mpath->dev == dev &&
++ memcmp(addr, mpath->dst, ETH_ALEN) == 0) {
++ spin_lock_bh(&mpath->state_lock);
++ mpath->flags |= MESH_PATH_RESOLVING;
++ hlist_del_rcu(&node->list);
++ call_rcu(&node->rcu, mesh_path_node_reclaim);
++ atomic_dec(&mesh_paths->entries);
++ spin_unlock_bh(&mpath->state_lock);
++ goto enddel;
++ }
++ }
++
++ err = -ENXIO;
++enddel:
++ spin_unlock(&mesh_paths->hashwlock[hash_idx]);
++ read_unlock(&pathtbl_resize_lock);
++ return err;
++}
++
++/**
++ * mesh_path_tx_pending - sends pending frames in a mesh path queue
++ *
++ * @mpath: mesh path to activate
++ *
++ * Locking: the state_lock of the mpath structure must NOT be held when calling
++ * this function.
++ */
++void mesh_path_tx_pending(struct mesh_path *mpath)
++{
++ struct sk_buff *skb;
++
++ while ((skb = skb_dequeue(&mpath->frame_queue)) &&
++ (mpath->flags & MESH_PATH_ACTIVE))
++ dev_queue_xmit(skb);
++}
++
++/**
++ * mesh_path_discard_frame - discard a frame whose path could not be resolved
++ *
++ * @skb: frame to discard
++ * @dev: network device the frame was to be sent through
++ *
++ * If the frame was beign forwarded from another MP, a PERR frame will be sent
++ * to the precursor.
++ *
++ * Locking: the function must me called within a rcu_read_lock region
++ */
++void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct mesh_path *mpath;
++ u32 dsn = 0;
++
++ if (skb->pkt_type == PACKET_OTHERHOST) {
++ struct ieee80211s_hdr *prev_meshhdr;
++ int mshhdrlen;
++ u8 *ra, *da;
++
++ prev_meshhdr = ((struct ieee80211s_hdr *)skb->cb);
++ mshhdrlen = ieee80211_get_mesh_hdrlen(prev_meshhdr);
++ da = skb->data;
++ ra = MESH_PREQ(skb);
++ mpath = mesh_path_lookup(da, dev);
++ if (mpath)
++ dsn = ++mpath->dsn;
++ mesh_path_error_tx(skb->data, cpu_to_le32(dsn), ra, dev);
++ }
++
++ kfree_skb(skb);
++ sdata->u.sta.mshstats.dropped_frames_no_route++;
++}
++
++/**
++ * mesh_path_flush_pending - free the pending queue of a mesh path
++ *
++ * @mpath: mesh path whose queue has to be freed
++ *
++ * Locking: the function must me called withing a rcu_read_lock region
++ */
++void mesh_path_flush_pending(struct mesh_path *mpath)
++{
++ struct ieee80211_sub_if_data *sdata;
++ struct sk_buff *skb;
++
++ sdata = IEEE80211_DEV_TO_SUB_IF(mpath->dev);
++
++ while ((skb = skb_dequeue(&mpath->frame_queue)) &&
++ (mpath->flags & MESH_PATH_ACTIVE))
++ mesh_path_discard_frame(skb, mpath->dev);
++}
++
++/**
++ * mesh_path_fix_nexthop - force a specific next hop for a mesh path
++ *
++ * @mpath: the mesh path to modify
++ * @next_hop: the next hop to force
++ *
++ * Locking: this function must be called holding mpath->state_lock
++ */
++void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop)
++{
++ spin_lock_bh(&mpath->state_lock);
++ mesh_path_assign_nexthop(mpath, next_hop);
++ mpath->dsn = 0xffff;
++ mpath->metric = 0;
++ mpath->hop_count = 0;
++ mpath->exp_time = 0;
++ mpath->flags |= MESH_PATH_FIXED;
++ mesh_path_activate(mpath);
++ spin_unlock_bh(&mpath->state_lock);
++ mesh_path_tx_pending(mpath);
++}
++
++static void mesh_path_node_free(struct hlist_node *p, bool free_leafs)
++{
++ struct mesh_path *mpath;
++ struct mpath_node *node = hlist_entry(p, struct mpath_node, list);
++ mpath = node->mpath;
++ hlist_del_rcu(p);
++ synchronize_rcu();
++ if (free_leafs)
++ kfree(mpath);
++ kfree(node);
++}
++
++static void mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl)
++{
++ struct mesh_path *mpath;
++ struct mpath_node *node, *new_node;
++ u32 hash_idx;
++
++ node = hlist_entry(p, struct mpath_node, list);
++ mpath = node->mpath;
++ new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL);
++ new_node->mpath = mpath;
++ hash_idx = mesh_table_hash(mpath->dst, mpath->dev, newtbl);
++ hlist_add_head(&new_node->list,
++ &newtbl->hash_buckets[hash_idx]);
++}
++
++int mesh_pathtbl_init(void)
++{
++ mesh_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER);
++ mesh_paths->free_node = &mesh_path_node_free;
++ mesh_paths->copy_node = &mesh_path_node_copy;
++ mesh_paths->mean_chain_len = MEAN_CHAIN_LEN;
++ if (!mesh_paths)
++ return -ENOMEM;
++ return 0;
++}
++
++void mesh_path_expire(struct net_device *dev)
++{
++ struct mesh_path *mpath;
++ struct mpath_node *node;
++ struct hlist_node *p;
++ int i;
++
++ read_lock(&pathtbl_resize_lock);
++ for_each_mesh_entry(mesh_paths, p, node, i) {
++ if (node->mpath->dev != dev)
++ continue;
++ mpath = node->mpath;
++ spin_lock_bh(&mpath->state_lock);
++ if ((!(mpath->flags & MESH_PATH_RESOLVING)) &&
++ (!(mpath->flags & MESH_PATH_FIXED)) &&
++ time_after(jiffies,
++ mpath->exp_time + MESH_PATH_EXPIRE)) {
++ spin_unlock_bh(&mpath->state_lock);
++ mesh_path_del(mpath->dst, mpath->dev);
++ } else
++ spin_unlock_bh(&mpath->state_lock);
++ }
++ read_unlock(&pathtbl_resize_lock);
++}
++
++void mesh_pathtbl_unregister(void)
++{
++ mesh_table_free(mesh_paths, true);
++}
+diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
+new file mode 100644
+index 0000000..37f0c2b
+--- /dev/null
++++ b/net/mac80211/mesh_plink.c
+@@ -0,0 +1,762 @@
++/*
++ * Copyright (c) 2008 open80211s Ltd.
++ * Author: Luis Carlos Cobo <luisca at cozybit.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/kernel.h>
++#include <linux/random.h>
++#include "ieee80211_i.h"
++#include "rate.h"
++#include "mesh.h"
++
++#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
++#define mpl_dbg(fmt, args...) printk(KERN_DEBUG fmt, ##args)
++#else
++#define mpl_dbg(fmt, args...) do { (void)(0); } while (0)
++#endif
++
++#define PLINK_GET_FRAME_SUBTYPE(p) (p)
++#define PLINK_GET_LLID(p) (p + 1)
++#define PLINK_GET_PLID(p) (p + 3)
++
++#define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \
++ jiffies + HZ * t / 1000))
++
++/* Peer link cancel reasons, all subject to ANA approval */
++#define MESH_LINK_CANCELLED 2
++#define MESH_MAX_NEIGHBORS 3
++#define MESH_CAPABILITY_POLICY_VIOLATION 4
++#define MESH_CLOSE_RCVD 5
++#define MESH_MAX_RETRIES 6
++#define MESH_CONFIRM_TIMEOUT 7
++#define MESH_SECURITY_ROLE_NEGOTIATION_DIFFERS 8
++#define MESH_SECURITY_AUTHENTICATION_IMPOSSIBLE 9
++#define MESH_SECURITY_FAILED_VERIFICATION 10
++
++#define dot11MeshMaxRetries(s) (s->u.sta.mshcfg.dot11MeshMaxRetries)
++#define dot11MeshRetryTimeout(s) (s->u.sta.mshcfg.dot11MeshRetryTimeout)
++#define dot11MeshConfirmTimeout(s) (s->u.sta.mshcfg.dot11MeshConfirmTimeout)
++#define dot11MeshHoldingTimeout(s) (s->u.sta.mshcfg.dot11MeshHoldingTimeout)
++#define dot11MeshMaxPeerLinks(s) (s->u.sta.mshcfg.dot11MeshMaxPeerLinks)
++
++enum plink_frame_type {
++ PLINK_OPEN = 0,
++ PLINK_CONFIRM,
++ PLINK_CLOSE
++};
++
++enum plink_event {
++ PLINK_UNDEFINED,
++ OPN_ACPT,
++ OPN_RJCT,
++ OPN_IGNR,
++ CNF_ACPT,
++ CNF_RJCT,
++ CNF_IGNR,
++ CLS_ACPT,
++ CLS_IGNR
++};
++
++static inline
++void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
++{
++ atomic_inc(&sdata->u.sta.mshstats.estab_plinks);
++ mesh_accept_plinks_update(sdata);
++}
++
++static inline
++void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
++{
++ atomic_dec(&sdata->u.sta.mshstats.estab_plinks);
++ mesh_accept_plinks_update(sdata);
++}
++
++/**
++ * mesh_plink_fsm_restart - restart a mesh peer link finite state machine
++ *
++ * @sta: mes peer link to restart
++ *
++ * Locking: this function must be called holding sta->plink_lock
++ */
++static inline void mesh_plink_fsm_restart(struct sta_info *sta)
++{
++ sta->plink_state = PLINK_LISTEN;
++ sta->llid = sta->plid = sta->reason = 0;
++ sta->plink_retries = 0;
++}
++
++/*
++ * NOTE: This is just an alias for sta_info_alloc(), see notes
++ * on it in the lifecycle management section!
++ */
++static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
++ u8 *hw_addr, u64 rates)
++{
++ struct ieee80211_local *local = sdata->local;
++ struct sta_info *sta;
++
++ if (local->num_sta >= MESH_MAX_PLINKS)
++ return NULL;
++
++ sta = sta_info_alloc(sdata, hw_addr, GFP_ATOMIC);
++ if (!sta)
++ return NULL;
++
++ sta->flags |= WLAN_STA_AUTHORIZED;
++ sta->supp_rates[local->hw.conf.channel->band] = rates;
++
++ return sta;
++}
++
++/**
++ * mesh_plink_deactivate - deactivate mesh peer link
++ *
++ * @sta: mesh peer link to deactivate
++ *
++ * All mesh paths with this peer as next hop will be flushed
++ *
++ * Locking: the caller must hold sta->plink_lock
++ */
++static void __mesh_plink_deactivate(struct sta_info *sta)
++{
++ struct ieee80211_sub_if_data *sdata = sta->sdata;
++
++ if (sta->plink_state == PLINK_ESTAB)
++ mesh_plink_dec_estab_count(sdata);
++ sta->plink_state = PLINK_BLOCKED;
++ mesh_path_flush_by_nexthop(sta);
++}
++
++/**
++ * __mesh_plink_deactivate - deactivate mesh peer link
++ *
++ * @sta: mesh peer link to deactivate
++ *
++ * All mesh paths with this peer as next hop will be flushed
++ */
++void mesh_plink_deactivate(struct sta_info *sta)
++{
++ spin_lock_bh(&sta->plink_lock);
++ __mesh_plink_deactivate(sta);
++ spin_unlock_bh(&sta->plink_lock);
++}
++
++static int mesh_plink_frame_tx(struct net_device *dev,
++ enum plink_frame_type action, u8 *da, __le16 llid, __le16 plid,
++ __le16 reason) {
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
++ struct ieee80211_mgmt *mgmt;
++ bool include_plid = false;
++ u8 *pos;
++ int ie_len;
++
++ if (!skb)
++ return -1;
++ skb_reserve(skb, local->hw.extra_tx_headroom);
++ /* 25 is the size of the common mgmt part (24) plus the size of the
++ * common action part (1)
++ */
++ mgmt = (struct ieee80211_mgmt *)
++ skb_put(skb, 25 + sizeof(mgmt->u.action.u.plink_action));
++ memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.plink_action));
++ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++ IEEE80211_STYPE_ACTION);
++ memcpy(mgmt->da, da, ETH_ALEN);
++ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
++ /* BSSID is left zeroed, wildcard value */
++ mgmt->u.action.category = PLINK_CATEGORY;
++ mgmt->u.action.u.plink_action.action_code = action;
++
++ if (action == PLINK_CLOSE)
++ mgmt->u.action.u.plink_action.aux = reason;
++ else {
++ mgmt->u.action.u.plink_action.aux = cpu_to_le16(0x0);
++ if (action == PLINK_CONFIRM) {
++ pos = skb_put(skb, 4);
++ /* two-byte status code followed by two-byte AID */
++ memset(pos, 0, 4);
++ }
++ mesh_mgmt_ies_add(skb, dev);
++ }
++
++ /* Add Peer Link Management element */
++ switch (action) {
++ case PLINK_OPEN:
++ ie_len = 3;
++ break;
++ case PLINK_CONFIRM:
++ ie_len = 5;
++ include_plid = true;
++ break;
++ case PLINK_CLOSE:
++ default:
++ if (!plid)
++ ie_len = 5;
++ else {
++ ie_len = 7;
++ include_plid = true;
++ }
++ break;
++ }
++
++ pos = skb_put(skb, 2 + ie_len);
++ *pos++ = WLAN_EID_PEER_LINK;
++ *pos++ = ie_len;
++ *pos++ = action;
++ memcpy(pos, &llid, 2);
++ if (include_plid) {
++ pos += 2;
++ memcpy(pos, &plid, 2);
++ }
++ if (action == PLINK_CLOSE) {
++ pos += 2;
++ memcpy(pos, &reason, 2);
++ }
++
++ ieee80211_sta_tx(dev, skb, 0);
++ return 0;
++}
++
++void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct net_device *dev,
++ bool peer_accepting_plinks)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct sta_info *sta;
++
++ rcu_read_lock();
++
++ sta = sta_info_get(local, hw_addr);
++ if (!sta) {
++ sta = mesh_plink_alloc(sdata, hw_addr, rates);
++ if (!sta) {
++ rcu_read_unlock();
++ return;
++ }
++ if (sta_info_insert(sta)) {
++ rcu_read_unlock();
++ return;
++ }
++ }
++
++ sta->last_rx = jiffies;
++ sta->supp_rates[local->hw.conf.channel->band] = rates;
++ if (peer_accepting_plinks && sta->plink_state == PLINK_LISTEN &&
++ sdata->u.sta.accepting_plinks &&
++ sdata->u.sta.mshcfg.auto_open_plinks)
++ mesh_plink_open(sta);
++
++ rcu_read_unlock();
++}
++
++static void mesh_plink_timer(unsigned long data)
++{
++ struct sta_info *sta;
++ __le16 llid, plid, reason;
++ struct net_device *dev = NULL;
++ struct ieee80211_sub_if_data *sdata;
++#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
++ DECLARE_MAC_BUF(mac);
++#endif
++
++ /*
++ * This STA is valid because sta_info_destroy() will
++ * del_timer_sync() this timer after having made sure
++ * it cannot be readded (by deleting the plink.)
++ */
++ sta = (struct sta_info *) data;
++
++ spin_lock_bh(&sta->plink_lock);
++ if (sta->ignore_plink_timer) {
++ sta->ignore_plink_timer = false;
++ spin_unlock_bh(&sta->plink_lock);
++ return;
++ }
++ mpl_dbg("Mesh plink timer for %s fired on state %d\n",
++ print_mac(mac, sta->addr), sta->plink_state);
++ reason = 0;
++ llid = sta->llid;
++ plid = sta->plid;
++ sdata = sta->sdata;
++ dev = sdata->dev;
++
++ switch (sta->plink_state) {
++ case PLINK_OPN_RCVD:
++ case PLINK_OPN_SNT:
++ /* retry timer */
++ if (sta->plink_retries < dot11MeshMaxRetries(sdata)) {
++ u32 rand;
++ mpl_dbg("Mesh plink for %s (retry, timeout): %d %d\n",
++ print_mac(mac, sta->addr),
++ sta->plink_retries, sta->plink_timeout);
++ get_random_bytes(&rand, sizeof(u32));
++ sta->plink_timeout = sta->plink_timeout +
++ rand % sta->plink_timeout;
++ ++sta->plink_retries;
++ mod_plink_timer(sta, sta->plink_timeout);
++ spin_unlock_bh(&sta->plink_lock);
++ mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid,
++ 0, 0);
++ break;
++ }
++ reason = cpu_to_le16(MESH_MAX_RETRIES);
++ /* fall through on else */
++ case PLINK_CNF_RCVD:
++ /* confirm timer */
++ if (!reason)
++ reason = cpu_to_le16(MESH_CONFIRM_TIMEOUT);
++ sta->plink_state = PLINK_HOLDING;
++ mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
++ spin_unlock_bh(&sta->plink_lock);
++ mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, plid,
++ reason);
++ break;
++ case PLINK_HOLDING:
++ /* holding timer */
++ del_timer(&sta->plink_timer);
++ mesh_plink_fsm_restart(sta);
++ spin_unlock_bh(&sta->plink_lock);
++ break;
++ default:
++ spin_unlock_bh(&sta->plink_lock);
++ break;
++ }
++}
++
++static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout)
++{
++ sta->plink_timer.expires = jiffies + (HZ * timeout / 1000);
++ sta->plink_timer.data = (unsigned long) sta;
++ sta->plink_timer.function = mesh_plink_timer;
++ sta->plink_timeout = timeout;
++ add_timer(&sta->plink_timer);
++}
++
++int mesh_plink_open(struct sta_info *sta)
++{
++ __le16 llid;
++ struct ieee80211_sub_if_data *sdata = sta->sdata;
++#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
++ DECLARE_MAC_BUF(mac);
++#endif
++
++ spin_lock_bh(&sta->plink_lock);
++ get_random_bytes(&llid, 2);
++ sta->llid = llid;
++ if (sta->plink_state != PLINK_LISTEN) {
++ spin_unlock_bh(&sta->plink_lock);
++ return -EBUSY;
++ }
++ sta->plink_state = PLINK_OPN_SNT;
++ mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
++ spin_unlock_bh(&sta->plink_lock);
++ mpl_dbg("Mesh plink: starting establishment with %s\n",
++ print_mac(mac, sta->addr));
++
++ return mesh_plink_frame_tx(sdata->dev, PLINK_OPEN,
++ sta->addr, llid, 0, 0);
++}
++
++void mesh_plink_block(struct sta_info *sta)
++{
++#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
++ DECLARE_MAC_BUF(mac);
++#endif
++
++ spin_lock_bh(&sta->plink_lock);
++ __mesh_plink_deactivate(sta);
++ sta->plink_state = PLINK_BLOCKED;
++ spin_unlock_bh(&sta->plink_lock);
++}
++
++int mesh_plink_close(struct sta_info *sta)
++{
++ struct ieee80211_sub_if_data *sdata = sta->sdata;
++ __le16 llid, plid, reason;
++#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
++ DECLARE_MAC_BUF(mac);
++#endif
++
++ mpl_dbg("Mesh plink: closing link with %s\n",
++ print_mac(mac, sta->addr));
++ spin_lock_bh(&sta->plink_lock);
++ sta->reason = cpu_to_le16(MESH_LINK_CANCELLED);
++ reason = sta->reason;
++
++ if (sta->plink_state == PLINK_LISTEN ||
++ sta->plink_state == PLINK_BLOCKED) {
++ mesh_plink_fsm_restart(sta);
++ spin_unlock_bh(&sta->plink_lock);
++ return 0;
++ } else if (sta->plink_state == PLINK_ESTAB) {
++ __mesh_plink_deactivate(sta);
++ /* The timer should not be running */
++ mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
++ } else if (!mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)))
++ sta->ignore_plink_timer = true;
++
++ sta->plink_state = PLINK_HOLDING;
++ llid = sta->llid;
++ plid = sta->plid;
++ spin_unlock_bh(&sta->plink_lock);
++ mesh_plink_frame_tx(sta->sdata->dev, PLINK_CLOSE, sta->addr, llid,
++ plid, reason);
++ return 0;
++}
++
++void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
++ size_t len, struct ieee80211_rx_status *rx_status)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_local *local = sdata->local;
++ struct ieee802_11_elems elems;
++ struct sta_info *sta;
++ enum plink_event event;
++ enum plink_frame_type ftype;
++ size_t baselen;
++ u8 ie_len;
++ u8 *baseaddr;
++ __le16 plid, llid, reason;
++#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
++ DECLARE_MAC_BUF(mac);
++#endif
++
++ if (is_multicast_ether_addr(mgmt->da)) {
++ mpl_dbg("Mesh plink: ignore frame from multicast address");
++ return;
++ }
++
++ baseaddr = mgmt->u.action.u.plink_action.variable;
++ baselen = (u8 *) mgmt->u.action.u.plink_action.variable - (u8 *) mgmt;
++ if (mgmt->u.action.u.plink_action.action_code == PLINK_CONFIRM) {
++ baseaddr += 4;
++ baselen -= 4;
++ }
++ ieee802_11_parse_elems(baseaddr, len - baselen, &elems);
++ if (!elems.peer_link) {
++ mpl_dbg("Mesh plink: missing necessary peer link ie\n");
++ return;
++ }
++
++ ftype = *((u8 *)PLINK_GET_FRAME_SUBTYPE(elems.peer_link));
++ ie_len = elems.peer_link_len;
++ if ((ftype == PLINK_OPEN && ie_len != 3) ||
++ (ftype == PLINK_CONFIRM && ie_len != 5) ||
++ (ftype == PLINK_CLOSE && ie_len != 5 && ie_len != 7)) {
++ mpl_dbg("Mesh plink: incorrect plink ie length\n");
++ return;
++ }
++
++ if (ftype != PLINK_CLOSE && (!elems.mesh_id || !elems.mesh_config)) {
++ mpl_dbg("Mesh plink: missing necessary ie\n");
++ return;
++ }
++ /* Note the lines below are correct, the llid in the frame is the plid
++ * from the point of view of this host.
++ */
++ memcpy(&plid, PLINK_GET_LLID(elems.peer_link), 2);
++ if (ftype == PLINK_CONFIRM || (ftype == PLINK_CLOSE && ie_len == 7))
++ memcpy(&llid, PLINK_GET_PLID(elems.peer_link), 2);
++
++ rcu_read_lock();
++
++ sta = sta_info_get(local, mgmt->sa);
++ if (!sta && ftype != PLINK_OPEN) {
++ mpl_dbg("Mesh plink: cls or cnf from unknown peer\n");
++ rcu_read_unlock();
++ return;
++ }
++
++ if (sta && sta->plink_state == PLINK_BLOCKED) {
++ rcu_read_unlock();
++ return;
++ }
++
++ /* Now we will figure out the appropriate event... */
++ event = PLINK_UNDEFINED;
++ if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, dev))) {
++ switch (ftype) {
++ case PLINK_OPEN:
++ event = OPN_RJCT;
++ break;
++ case PLINK_CONFIRM:
++ event = CNF_RJCT;
++ break;
++ case PLINK_CLOSE:
++ /* avoid warning */
++ break;
++ }
++ spin_lock_bh(&sta->plink_lock);
++ } else if (!sta) {
++ /* ftype == PLINK_OPEN */
++ u64 rates;
++ if (!mesh_plink_free_count(sdata)) {
++ mpl_dbg("Mesh plink error: no more free plinks\n");
++ rcu_read_unlock();
++ return;
++ }
++
++ rates = ieee80211_sta_get_rates(local, &elems, rx_status->band);
++ sta = mesh_plink_alloc(sdata, mgmt->sa, rates);
++ if (!sta) {
++ mpl_dbg("Mesh plink error: plink table full\n");
++ rcu_read_unlock();
++ return;
++ }
++ if (sta_info_insert(sta)) {
++ rcu_read_unlock();
++ return;
++ }
++ event = OPN_ACPT;
++ spin_lock_bh(&sta->plink_lock);
++ } else {
++ spin_lock_bh(&sta->plink_lock);
++ switch (ftype) {
++ case PLINK_OPEN:
++ if (!mesh_plink_free_count(sdata) ||
++ (sta->plid && sta->plid != plid))
++ event = OPN_IGNR;
++ else
++ event = OPN_ACPT;
++ break;
++ case PLINK_CONFIRM:
++ if (!mesh_plink_free_count(sdata) ||
++ (sta->llid != llid || sta->plid != plid))
++ event = CNF_IGNR;
++ else
++ event = CNF_ACPT;
++ break;
++ case PLINK_CLOSE:
++ if (sta->plink_state == PLINK_ESTAB)
++ /* Do not check for llid or plid. This does not
++ * follow the standard but since multiple plinks
++ * per sta are not supported, it is necessary in
++ * order to avoid a livelock when MP A sees an
++ * establish peer link to MP B but MP B does not
++ * see it. This can be caused by a timeout in
++ * B's peer link establishment or B beign
++ * restarted.
++ */
++ event = CLS_ACPT;
++ else if (sta->plid != plid)
++ event = CLS_IGNR;
++ else if (ie_len == 7 && sta->llid != llid)
++ event = CLS_IGNR;
++ else
++ event = CLS_ACPT;
++ break;
++ default:
++ mpl_dbg("Mesh plink: unknown frame subtype\n");
++ spin_unlock_bh(&sta->plink_lock);
++ rcu_read_unlock();
++ return;
++ }
++ }
++
++ mpl_dbg("Mesh plink (peer, state, llid, plid, event): %s %d %d %d %d\n",
++ print_mac(mac, mgmt->sa), sta->plink_state,
++ le16_to_cpu(sta->llid), le16_to_cpu(sta->plid),
++ event);
++ reason = 0;
++ switch (sta->plink_state) {
++ /* spin_unlock as soon as state is updated at each case */
++ case PLINK_LISTEN:
++ switch (event) {
++ case CLS_ACPT:
++ mesh_plink_fsm_restart(sta);
++ spin_unlock_bh(&sta->plink_lock);
++ break;
++ case OPN_ACPT:
++ sta->plink_state = PLINK_OPN_RCVD;
++ sta->plid = plid;
++ get_random_bytes(&llid, 2);
++ sta->llid = llid;
++ mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
++ spin_unlock_bh(&sta->plink_lock);
++ mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid,
++ 0, 0);
++ mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr,
++ llid, plid, 0);
++ break;
++ default:
++ spin_unlock_bh(&sta->plink_lock);
++ break;
++ }
++ break;
++
++ case PLINK_OPN_SNT:
++ switch (event) {
++ case OPN_RJCT:
++ case CNF_RJCT:
++ reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION);
++ case CLS_ACPT:
++ if (!reason)
++ reason = cpu_to_le16(MESH_CLOSE_RCVD);
++ sta->reason = reason;
++ sta->plink_state = PLINK_HOLDING;
++ if (!mod_plink_timer(sta,
++ dot11MeshHoldingTimeout(sdata)))
++ sta->ignore_plink_timer = true;
++
++ llid = sta->llid;
++ spin_unlock_bh(&sta->plink_lock);
++ mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
++ plid, reason);
++ break;
++ case OPN_ACPT:
++ /* retry timer is left untouched */
++ sta->plink_state = PLINK_OPN_RCVD;
++ sta->plid = plid;
++ llid = sta->llid;
++ spin_unlock_bh(&sta->plink_lock);
++ mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid,
++ plid, 0);
++ break;
++ case CNF_ACPT:
++ sta->plink_state = PLINK_CNF_RCVD;
++ if (!mod_plink_timer(sta,
++ dot11MeshConfirmTimeout(sdata)))
++ sta->ignore_plink_timer = true;
++
++ spin_unlock_bh(&sta->plink_lock);
++ break;
++ default:
++ spin_unlock_bh(&sta->plink_lock);
++ break;
++ }
++ break;
++
++ case PLINK_OPN_RCVD:
++ switch (event) {
++ case OPN_RJCT:
++ case CNF_RJCT:
++ reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION);
++ case CLS_ACPT:
++ if (!reason)
++ reason = cpu_to_le16(MESH_CLOSE_RCVD);
++ sta->reason = reason;
++ sta->plink_state = PLINK_HOLDING;
++ if (!mod_plink_timer(sta,
++ dot11MeshHoldingTimeout(sdata)))
++ sta->ignore_plink_timer = true;
++
++ llid = sta->llid;
++ spin_unlock_bh(&sta->plink_lock);
++ mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
++ plid, reason);
++ break;
++ case OPN_ACPT:
++ llid = sta->llid;
++ spin_unlock_bh(&sta->plink_lock);
++ mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid,
++ plid, 0);
++ break;
++ case CNF_ACPT:
++ del_timer(&sta->plink_timer);
++ sta->plink_state = PLINK_ESTAB;
++ mesh_plink_inc_estab_count(sdata);
++ spin_unlock_bh(&sta->plink_lock);
++ mpl_dbg("Mesh plink with %s ESTABLISHED\n",
++ print_mac(mac, sta->addr));
++ break;
++ default:
++ spin_unlock_bh(&sta->plink_lock);
++ break;
++ }
++ break;
++
++ case PLINK_CNF_RCVD:
++ switch (event) {
++ case OPN_RJCT:
++ case CNF_RJCT:
++ reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION);
++ case CLS_ACPT:
++ if (!reason)
++ reason = cpu_to_le16(MESH_CLOSE_RCVD);
++ sta->reason = reason;
++ sta->plink_state = PLINK_HOLDING;
++ if (!mod_plink_timer(sta,
++ dot11MeshHoldingTimeout(sdata)))
++ sta->ignore_plink_timer = true;
++
++ llid = sta->llid;
++ spin_unlock_bh(&sta->plink_lock);
++ mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
++ plid, reason);
++ break;
++ case OPN_ACPT:
++ del_timer(&sta->plink_timer);
++ sta->plink_state = PLINK_ESTAB;
++ mesh_plink_inc_estab_count(sdata);
++ spin_unlock_bh(&sta->plink_lock);
++ mpl_dbg("Mesh plink with %s ESTABLISHED\n",
++ print_mac(mac, sta->addr));
++ mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid,
++ plid, 0);
++ break;
++ default:
++ spin_unlock_bh(&sta->plink_lock);
++ break;
++ }
++ break;
++
++ case PLINK_ESTAB:
++ switch (event) {
++ case CLS_ACPT:
++ reason = cpu_to_le16(MESH_CLOSE_RCVD);
++ sta->reason = reason;
++ __mesh_plink_deactivate(sta);
++ sta->plink_state = PLINK_HOLDING;
++ llid = sta->llid;
++ mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
++ spin_unlock_bh(&sta->plink_lock);
++ mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
++ plid, reason);
++ break;
++ case OPN_ACPT:
++ llid = sta->llid;
++ spin_unlock_bh(&sta->plink_lock);
++ mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid,
++ plid, 0);
++ break;
++ default:
++ spin_unlock_bh(&sta->plink_lock);
++ break;
++ }
++ break;
++ case PLINK_HOLDING:
++ switch (event) {
++ case CLS_ACPT:
++ if (del_timer(&sta->plink_timer))
++ sta->ignore_plink_timer = 1;
++ mesh_plink_fsm_restart(sta);
++ spin_unlock_bh(&sta->plink_lock);
++ break;
++ case OPN_ACPT:
++ case CNF_ACPT:
++ case OPN_RJCT:
++ case CNF_RJCT:
++ llid = sta->llid;
++ reason = sta->reason;
++ spin_unlock_bh(&sta->plink_lock);
++ mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
++ plid, reason);
++ break;
++ default:
++ spin_unlock_bh(&sta->plink_lock);
++ }
++ break;
++ default:
++ /* should not get here, PLINK_BLOCKED is dealt with at the
++ * beggining of the function
++ */
++ spin_unlock_bh(&sta->plink_lock);
++ break;
++ }
++
++ rcu_read_unlock();
++}
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+new file mode 100644
+index 0000000..a5e5c31
+--- /dev/null
++++ b/net/mac80211/mlme.c
+@@ -0,0 +1,4321 @@
++/*
++ * BSS client mode implementation
++ * Copyright 2003, Jouni Malinen <jkmaline at cc.hut.fi>
++ * Copyright 2004, Instant802 Networks, Inc.
++ * Copyright 2005, Devicescape Software, Inc.
++ * Copyright 2006-2007 Jiri Benc <jbenc at suse.cz>
++ * Copyright 2007, Michael Wu <flamingice at sourmilk.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++/* TODO:
++ * order BSS list by RSSI(?) ("quality of AP")
++ * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE,
++ * SSID)
++ */
++#include <linux/delay.h>
++#include <linux/if_ether.h>
++#include <linux/skbuff.h>
++#include <linux/netdevice.h>
++#include <linux/if_arp.h>
++#include <linux/wireless.h>
++#include <linux/random.h>
++#include <linux/etherdevice.h>
++#include <linux/rtnetlink.h>
++#include <net/iw_handler.h>
++#include <asm/types.h>
++
++#include <net/mac80211.h>
++#include "ieee80211_i.h"
++#include "rate.h"
++#include "led.h"
++#include "mesh.h"
++
++#define IEEE80211_AUTH_TIMEOUT (HZ / 5)
++#define IEEE80211_AUTH_MAX_TRIES 3
++#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
++#define IEEE80211_ASSOC_MAX_TRIES 3
++#define IEEE80211_MONITORING_INTERVAL (2 * HZ)
++#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ)
++#define IEEE80211_PROBE_INTERVAL (60 * HZ)
++#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ)
++#define IEEE80211_SCAN_INTERVAL (2 * HZ)
++#define IEEE80211_SCAN_INTERVAL_SLOW (15 * HZ)
++#define IEEE80211_IBSS_JOIN_TIMEOUT (20 * HZ)
++
++#define IEEE80211_PROBE_DELAY (HZ / 33)
++#define IEEE80211_CHANNEL_TIME (HZ / 33)
++#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5)
++#define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ)
++#define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ)
++#define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ)
++#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ)
++
++#define IEEE80211_IBSS_MAX_STA_ENTRIES 128
++
++
++#define ERP_INFO_USE_PROTECTION BIT(1)
++
++/* mgmt header + 1 byte action code */
++#define IEEE80211_MIN_ACTION_SIZE (24 + 1)
++
++#define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002
++#define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C
++#define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFA0
++#define IEEE80211_DELBA_PARAM_TID_MASK 0xF000
++#define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800
++
++/* next values represent the buffer size for A-MPDU frame.
++ * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) */
++#define IEEE80211_MIN_AMPDU_BUF 0x8
++#define IEEE80211_MAX_AMPDU_BUF 0x40
++
++static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
++ u8 *ssid, size_t ssid_len);
++static struct ieee80211_sta_bss *
++ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq,
++ u8 *ssid, u8 ssid_len);
++static void ieee80211_rx_bss_put(struct net_device *dev,
++ struct ieee80211_sta_bss *bss);
++static int ieee80211_sta_find_ibss(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta);
++static int ieee80211_sta_wep_configured(struct net_device *dev);
++static int ieee80211_sta_start_scan(struct net_device *dev,
++ u8 *ssid, size_t ssid_len);
++static int ieee80211_sta_config_auth(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta);
++
++
++void ieee802_11_parse_elems(u8 *start, size_t len,
++ struct ieee802_11_elems *elems)
++{
++ size_t left = len;
++ u8 *pos = start;
++
++ memset(elems, 0, sizeof(*elems));
++
++ while (left >= 2) {
++ u8 id, elen;
++
++ id = *pos++;
++ elen = *pos++;
++ left -= 2;
++
++ if (elen > left)
++ return;
++
++ switch (id) {
++ case WLAN_EID_SSID:
++ elems->ssid = pos;
++ elems->ssid_len = elen;
++ break;
++ case WLAN_EID_SUPP_RATES:
++ elems->supp_rates = pos;
++ elems->supp_rates_len = elen;
++ break;
++ case WLAN_EID_FH_PARAMS:
++ elems->fh_params = pos;
++ elems->fh_params_len = elen;
++ break;
++ case WLAN_EID_DS_PARAMS:
++ elems->ds_params = pos;
++ elems->ds_params_len = elen;
++ break;
++ case WLAN_EID_CF_PARAMS:
++ elems->cf_params = pos;
++ elems->cf_params_len = elen;
++ break;
++ case WLAN_EID_TIM:
++ elems->tim = pos;
++ elems->tim_len = elen;
++ break;
++ case WLAN_EID_IBSS_PARAMS:
++ elems->ibss_params = pos;
++ elems->ibss_params_len = elen;
++ break;
++ case WLAN_EID_CHALLENGE:
++ elems->challenge = pos;
++ elems->challenge_len = elen;
++ break;
++ case WLAN_EID_WPA:
++ if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
++ pos[2] == 0xf2) {
++ /* Microsoft OUI (00:50:F2) */
++ if (pos[3] == 1) {
++ /* OUI Type 1 - WPA IE */
++ elems->wpa = pos;
++ elems->wpa_len = elen;
++ } else if (elen >= 5 && pos[3] == 2) {
++ if (pos[4] == 0) {
++ elems->wmm_info = pos;
++ elems->wmm_info_len = elen;
++ } else if (pos[4] == 1) {
++ elems->wmm_param = pos;
++ elems->wmm_param_len = elen;
++ }
++ }
++ }
++ break;
++ case WLAN_EID_RSN:
++ elems->rsn = pos;
++ elems->rsn_len = elen;
++ break;
++ case WLAN_EID_ERP_INFO:
++ elems->erp_info = pos;
++ elems->erp_info_len = elen;
++ break;
++ case WLAN_EID_EXT_SUPP_RATES:
++ elems->ext_supp_rates = pos;
++ elems->ext_supp_rates_len = elen;
++ break;
++ case WLAN_EID_HT_CAPABILITY:
++ elems->ht_cap_elem = pos;
++ elems->ht_cap_elem_len = elen;
++ break;
++ case WLAN_EID_HT_EXTRA_INFO:
++ elems->ht_info_elem = pos;
++ elems->ht_info_elem_len = elen;
++ break;
++ case WLAN_EID_MESH_ID:
++ elems->mesh_id = pos;
++ elems->mesh_id_len = elen;
++ break;
++ case WLAN_EID_MESH_CONFIG:
++ elems->mesh_config = pos;
++ elems->mesh_config_len = elen;
++ break;
++ case WLAN_EID_PEER_LINK:
++ elems->peer_link = pos;
++ elems->peer_link_len = elen;
++ break;
++ case WLAN_EID_PREQ:
++ elems->preq = pos;
++ elems->preq_len = elen;
++ break;
++ case WLAN_EID_PREP:
++ elems->prep = pos;
++ elems->prep_len = elen;
++ break;
++ case WLAN_EID_PERR:
++ elems->perr = pos;
++ elems->perr_len = elen;
++ break;
++ default:
++ break;
++ }
++
++ left -= elen;
++ pos += elen;
++ }
++}
++
++
++static int ecw2cw(int ecw)
++{
++ return (1 << ecw) - 1;
++}
++
++
++static void ieee80211_sta_def_wmm_params(struct net_device *dev,
++ struct ieee80211_sta_bss *bss,
++ int ibss)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_local *local = sdata->local;
++ int i, have_higher_than_11mbit = 0;
++
++
++ /* cf. IEEE 802.11 9.2.12 */
++ for (i = 0; i < bss->supp_rates_len; i++)
++ if ((bss->supp_rates[i] & 0x7f) * 5 > 110)
++ have_higher_than_11mbit = 1;
++
++ if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ &&
++ have_higher_than_11mbit)
++ sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
++ else
++ sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
++
++
++ if (local->ops->conf_tx) {
++ struct ieee80211_tx_queue_params qparam;
++
++ memset(&qparam, 0, sizeof(qparam));
++
++ qparam.aifs = 2;
++
++ if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ &&
++ !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE))
++ qparam.cw_min = 31;
++ else
++ qparam.cw_min = 15;
++
++ qparam.cw_max = 1023;
++ qparam.txop = 0;
++
++ for (i = IEEE80211_TX_QUEUE_DATA0; i < NUM_TX_DATA_QUEUES; i++)
++ local->ops->conf_tx(local_to_hw(local),
++ i + IEEE80211_TX_QUEUE_DATA0,
++ &qparam);
++
++ if (ibss) {
++ /* IBSS uses different parameters for Beacon sending */
++ qparam.cw_min++;
++ qparam.cw_min *= 2;
++ qparam.cw_min--;
++ local->ops->conf_tx(local_to_hw(local),
++ IEEE80211_TX_QUEUE_BEACON, &qparam);
++ }
++ }
++}
++
++static void ieee80211_sta_wmm_params(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta,
++ u8 *wmm_param, size_t wmm_param_len)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_tx_queue_params params;
++ size_t left;
++ int count;
++ u8 *pos;
++
++ if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
++ return;
++ count = wmm_param[6] & 0x0f;
++ if (count == ifsta->wmm_last_param_set)
++ return;
++ ifsta->wmm_last_param_set = count;
++
++ pos = wmm_param + 8;
++ left = wmm_param_len - 8;
++
++ memset(¶ms, 0, sizeof(params));
++
++ if (!local->ops->conf_tx)
++ return;
++
++ local->wmm_acm = 0;
++ for (; left >= 4; left -= 4, pos += 4) {
++ int aci = (pos[0] >> 5) & 0x03;
++ int acm = (pos[0] >> 4) & 0x01;
++ int queue;
++
++ switch (aci) {
++ case 1:
++ queue = IEEE80211_TX_QUEUE_DATA3;
++ if (acm) {
++ local->wmm_acm |= BIT(0) | BIT(3);
++ }
++ break;
++ case 2:
++ queue = IEEE80211_TX_QUEUE_DATA1;
++ if (acm) {
++ local->wmm_acm |= BIT(4) | BIT(5);
++ }
++ break;
++ case 3:
++ queue = IEEE80211_TX_QUEUE_DATA0;
++ if (acm) {
++ local->wmm_acm |= BIT(6) | BIT(7);
++ }
++ break;
++ case 0:
++ default:
++ queue = IEEE80211_TX_QUEUE_DATA2;
++ if (acm) {
++ local->wmm_acm |= BIT(1) | BIT(2);
++ }
++ break;
++ }
++
++ params.aifs = pos[0] & 0x0f;
++ params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
++ params.cw_min = ecw2cw(pos[1] & 0x0f);
++ params.txop = pos[2] | (pos[3] << 8);
++#ifdef CONFIG_MAC80211_DEBUG
++ printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d "
++ "cWmin=%d cWmax=%d txop=%d\n",
++ dev->name, queue, aci, acm, params.aifs, params.cw_min,
++ params.cw_max, params.txop);
++#endif
++ /* TODO: handle ACM (block TX, fallback to next lowest allowed
++ * AC for now) */
++ if (local->ops->conf_tx(local_to_hw(local), queue, ¶ms)) {
++ printk(KERN_DEBUG "%s: failed to set TX queue "
++ "parameters for queue %d\n", dev->name, queue);
++ }
++ }
++}
++
++static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata,
++ bool use_protection,
++ bool use_short_preamble)
++{
++ struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf;
++ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++ DECLARE_MAC_BUF(mac);
++ u32 changed = 0;
++
++ if (use_protection != bss_conf->use_cts_prot) {
++ if (net_ratelimit()) {
++ printk(KERN_DEBUG "%s: CTS protection %s (BSSID="
++ "%s)\n",
++ sdata->dev->name,
++ use_protection ? "enabled" : "disabled",
++ print_mac(mac, ifsta->bssid));
++ }
++ bss_conf->use_cts_prot = use_protection;
++ changed |= BSS_CHANGED_ERP_CTS_PROT;
++ }
++
++ if (use_short_preamble != bss_conf->use_short_preamble) {
++ if (net_ratelimit()) {
++ printk(KERN_DEBUG "%s: switched to %s barker preamble"
++ " (BSSID=%s)\n",
++ sdata->dev->name,
++ use_short_preamble ? "short" : "long",
++ print_mac(mac, ifsta->bssid));
++ }
++ bss_conf->use_short_preamble = use_short_preamble;
++ changed |= BSS_CHANGED_ERP_PREAMBLE;
++ }
++
++ return changed;
++}
++
++static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata,
++ u8 erp_value)
++{
++ bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
++ bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0;
++
++ return ieee80211_handle_protect_preamb(sdata,
++ use_protection, use_short_preamble);
++}
++
++static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
++ struct ieee80211_sta_bss *bss)
++{
++ u32 changed = 0;
++
++ if (bss->has_erp_value)
++ changed |= ieee80211_handle_erp_ie(sdata, bss->erp_value);
++ else {
++ u16 capab = bss->capability;
++ changed |= ieee80211_handle_protect_preamb(sdata, false,
++ (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0);
++ }
++
++ return changed;
++}
++
++int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie,
++ struct ieee80211_ht_info *ht_info)
++{
++
++ if (ht_info == NULL)
++ return -EINVAL;
++
++ memset(ht_info, 0, sizeof(*ht_info));
++
++ if (ht_cap_ie) {
++ u8 ampdu_info = ht_cap_ie->ampdu_params_info;
++
++ ht_info->ht_supported = 1;
++ ht_info->cap = le16_to_cpu(ht_cap_ie->cap_info);
++ ht_info->ampdu_factor =
++ ampdu_info & IEEE80211_HT_CAP_AMPDU_FACTOR;
++ ht_info->ampdu_density =
++ (ampdu_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2;
++ memcpy(ht_info->supp_mcs_set, ht_cap_ie->supp_mcs_set, 16);
++ } else
++ ht_info->ht_supported = 0;
++
++ return 0;
++}
++
++int ieee80211_ht_addt_info_ie_to_ht_bss_info(
++ struct ieee80211_ht_addt_info *ht_add_info_ie,
++ struct ieee80211_ht_bss_info *bss_info)
++{
++ if (bss_info == NULL)
++ return -EINVAL;
++
++ memset(bss_info, 0, sizeof(*bss_info));
++
++ if (ht_add_info_ie) {
++ u16 op_mode;
++ op_mode = le16_to_cpu(ht_add_info_ie->operation_mode);
++
++ bss_info->primary_channel = ht_add_info_ie->control_chan;
++ bss_info->bss_cap = ht_add_info_ie->ht_param;
++ bss_info->bss_op_mode = (u8)(op_mode & 0xff);
++ }
++
++ return 0;
++}
++
++static void ieee80211_sta_send_associnfo(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta)
++{
++ char *buf;
++ size_t len;
++ int i;
++ union iwreq_data wrqu;
++
++ if (!ifsta->assocreq_ies && !ifsta->assocresp_ies)
++ return;
++
++ buf = kmalloc(50 + 2 * (ifsta->assocreq_ies_len +
++ ifsta->assocresp_ies_len), GFP_KERNEL);
++ if (!buf)
++ return;
++
++ len = sprintf(buf, "ASSOCINFO(");
++ if (ifsta->assocreq_ies) {
++ len += sprintf(buf + len, "ReqIEs=");
++ for (i = 0; i < ifsta->assocreq_ies_len; i++) {
++ len += sprintf(buf + len, "%02x",
++ ifsta->assocreq_ies[i]);
++ }
++ }
++ if (ifsta->assocresp_ies) {
++ if (ifsta->assocreq_ies)
++ len += sprintf(buf + len, " ");
++ len += sprintf(buf + len, "RespIEs=");
++ for (i = 0; i < ifsta->assocresp_ies_len; i++) {
++ len += sprintf(buf + len, "%02x",
++ ifsta->assocresp_ies[i]);
++ }
++ }
++ len += sprintf(buf + len, ")");
++
++ if (len > IW_CUSTOM_MAX) {
++ len = sprintf(buf, "ASSOCRESPIE=");
++ for (i = 0; i < ifsta->assocresp_ies_len; i++) {
++ len += sprintf(buf + len, "%02x",
++ ifsta->assocresp_ies[i]);
++ }
++ }
++
++ memset(&wrqu, 0, sizeof(wrqu));
++ wrqu.data.length = len;
++ wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
++
++ kfree(buf);
++}
++
++
++static void ieee80211_set_associated(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta,
++ bool assoc)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_local *local = sdata->local;
++ struct ieee80211_conf *conf = &local_to_hw(local)->conf;
++ union iwreq_data wrqu;
++ u32 changed = BSS_CHANGED_ASSOC;
++
++ if (assoc) {
++ struct ieee80211_sta_bss *bss;
++
++ ifsta->flags |= IEEE80211_STA_ASSOCIATED;
++
++ if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
++ return;
++
++ bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
++ conf->channel->center_freq,
++ ifsta->ssid, ifsta->ssid_len);
++ if (bss) {
++ /* set timing information */
++ sdata->bss_conf.beacon_int = bss->beacon_int;
++ sdata->bss_conf.timestamp = bss->timestamp;
++
++ changed |= ieee80211_handle_bss_capability(sdata, bss);
++
++ ieee80211_rx_bss_put(dev, bss);
++ }
++
++ if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
++ changed |= BSS_CHANGED_HT;
++ sdata->bss_conf.assoc_ht = 1;
++ sdata->bss_conf.ht_conf = &conf->ht_conf;
++ sdata->bss_conf.ht_bss_conf = &conf->ht_bss_conf;
++ }
++
++ netif_carrier_on(dev);
++ ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET;
++ memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN);
++ memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN);
++ ieee80211_sta_send_associnfo(dev, ifsta);
++ } else {
++ ieee80211_sta_tear_down_BA_sessions(dev, ifsta->bssid);
++ ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
++ netif_carrier_off(dev);
++ ieee80211_reset_erp_info(dev);
++
++ sdata->bss_conf.assoc_ht = 0;
++ sdata->bss_conf.ht_conf = NULL;
++ sdata->bss_conf.ht_bss_conf = NULL;
++
++ memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
++ }
++ ifsta->last_probe = jiffies;
++ ieee80211_led_assoc(local, assoc);
++
++ sdata->bss_conf.assoc = assoc;
++ ieee80211_bss_info_change_notify(sdata, changed);
++ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
++ wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
++}
++
++static void ieee80211_set_disassoc(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta, int deauth)
++{
++ if (deauth)
++ ifsta->auth_tries = 0;
++ ifsta->assoc_tries = 0;
++ ieee80211_set_associated(dev, ifsta, 0);
++}
++
++void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb,
++ int encrypt)
++{
++ struct ieee80211_sub_if_data *sdata;
++ struct ieee80211_tx_packet_data *pkt_data;
++
++ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ skb->dev = sdata->local->mdev;
++ skb_set_mac_header(skb, 0);
++ skb_set_network_header(skb, 0);
++ skb_set_transport_header(skb, 0);
++
++ pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
++ memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
++ pkt_data->ifindex = sdata->dev->ifindex;
++ if (!encrypt)
++ pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT;
++
++ dev_queue_xmit(skb);
++}
++
++
++static void ieee80211_send_auth(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta,
++ int transaction, u8 *extra, size_t extra_len,
++ int encrypt)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct sk_buff *skb;
++ struct ieee80211_mgmt *mgmt;
++
++ skb = dev_alloc_skb(local->hw.extra_tx_headroom +
++ sizeof(*mgmt) + 6 + extra_len);
++ if (!skb) {
++ printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
++ "frame\n", dev->name);
++ return;
++ }
++ skb_reserve(skb, local->hw.extra_tx_headroom);
++
++ mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6);
++ memset(mgmt, 0, 24 + 6);
++ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++ IEEE80211_STYPE_AUTH);
++ if (encrypt)
++ mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
++ memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
++ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
++ memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
++ mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg);
++ mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);
++ ifsta->auth_transaction = transaction + 1;
++ mgmt->u.auth.status_code = cpu_to_le16(0);
++ if (extra)
++ memcpy(skb_put(skb, extra_len), extra, extra_len);
++
++ ieee80211_sta_tx(dev, skb, encrypt);
++}
++
++
++static void ieee80211_authenticate(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta)
++{
++ DECLARE_MAC_BUF(mac);
++
++ ifsta->auth_tries++;
++ if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) {
++ printk(KERN_DEBUG "%s: authentication with AP %s"
++ " timed out\n",
++ dev->name, print_mac(mac, ifsta->bssid));
++ ifsta->state = IEEE80211_DISABLED;
++ return;
++ }
++
++ ifsta->state = IEEE80211_AUTHENTICATE;
++ printk(KERN_DEBUG "%s: authenticate with AP %s\n",
++ dev->name, print_mac(mac, ifsta->bssid));
++
++ ieee80211_send_auth(dev, ifsta, 1, NULL, 0, 0);
++
++ mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
++}
++
++
++static void ieee80211_send_assoc(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct sk_buff *skb;
++ struct ieee80211_mgmt *mgmt;
++ u8 *pos, *ies;
++ int i, len;
++ u16 capab;
++ struct ieee80211_sta_bss *bss;
++ int wmm = 0;
++ struct ieee80211_supported_band *sband;
++
++ skb = dev_alloc_skb(local->hw.extra_tx_headroom +
++ sizeof(*mgmt) + 200 + ifsta->extra_ie_len +
++ ifsta->ssid_len);
++ if (!skb) {
++ printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
++ "frame\n", dev->name);
++ return;
++ }
++ skb_reserve(skb, local->hw.extra_tx_headroom);
++
++ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++
++ capab = ifsta->capab;
++
++ if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) {
++ if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
++ capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
++ if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
++ capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
++ }
++
++ bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
++ local->hw.conf.channel->center_freq,
++ ifsta->ssid, ifsta->ssid_len);
++ if (bss) {
++ if (bss->capability & WLAN_CAPABILITY_PRIVACY)
++ capab |= WLAN_CAPABILITY_PRIVACY;
++ if (bss->wmm_ie) {
++ wmm = 1;
++ }
++ ieee80211_rx_bss_put(dev, bss);
++ }
++
++ mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
++ memset(mgmt, 0, 24);
++ memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
++ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
++ memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
++
++ if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) {
++ skb_put(skb, 10);
++ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++ IEEE80211_STYPE_REASSOC_REQ);
++ mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);
++ mgmt->u.reassoc_req.listen_interval = cpu_to_le16(1);
++ memcpy(mgmt->u.reassoc_req.current_ap, ifsta->prev_bssid,
++ ETH_ALEN);
++ } else {
++ skb_put(skb, 4);
++ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++ IEEE80211_STYPE_ASSOC_REQ);
++ mgmt->u.assoc_req.capab_info = cpu_to_le16(capab);
++ mgmt->u.assoc_req.listen_interval = cpu_to_le16(1);
++ }
++
++ /* SSID */
++ ies = pos = skb_put(skb, 2 + ifsta->ssid_len);
++ *pos++ = WLAN_EID_SSID;
++ *pos++ = ifsta->ssid_len;
++ memcpy(pos, ifsta->ssid, ifsta->ssid_len);
++
++ len = sband->n_bitrates;
++ if (len > 8)
++ len = 8;
++ pos = skb_put(skb, len + 2);
++ *pos++ = WLAN_EID_SUPP_RATES;
++ *pos++ = len;
++ for (i = 0; i < len; i++) {
++ int rate = sband->bitrates[i].bitrate;
++ *pos++ = (u8) (rate / 5);
++ }
++
++ if (sband->n_bitrates > len) {
++ pos = skb_put(skb, sband->n_bitrates - len + 2);
++ *pos++ = WLAN_EID_EXT_SUPP_RATES;
++ *pos++ = sband->n_bitrates - len;
++ for (i = len; i < sband->n_bitrates; i++) {
++ int rate = sband->bitrates[i].bitrate;
++ *pos++ = (u8) (rate / 5);
++ }
++ }
++
++ if (ifsta->extra_ie) {
++ pos = skb_put(skb, ifsta->extra_ie_len);
++ memcpy(pos, ifsta->extra_ie, ifsta->extra_ie_len);
++ }
++
++ if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
++ pos = skb_put(skb, 9);
++ *pos++ = WLAN_EID_VENDOR_SPECIFIC;
++ *pos++ = 7; /* len */
++ *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
++ *pos++ = 0x50;
++ *pos++ = 0xf2;
++ *pos++ = 2; /* WME */
++ *pos++ = 0; /* WME info */
++ *pos++ = 1; /* WME ver */
++ *pos++ = 0;
++ }
++ /* wmm support is a must to HT */
++ if (wmm && sband->ht_info.ht_supported) {
++ __le16 tmp = cpu_to_le16(sband->ht_info.cap);
++ pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2);
++ *pos++ = WLAN_EID_HT_CAPABILITY;
++ *pos++ = sizeof(struct ieee80211_ht_cap);
++ memset(pos, 0, sizeof(struct ieee80211_ht_cap));
++ memcpy(pos, &tmp, sizeof(u16));
++ pos += sizeof(u16);
++ /* TODO: needs a define here for << 2 */
++ *pos++ = sband->ht_info.ampdu_factor |
++ (sband->ht_info.ampdu_density << 2);
++ memcpy(pos, sband->ht_info.supp_mcs_set, 16);
++ }
++
++ kfree(ifsta->assocreq_ies);
++ ifsta->assocreq_ies_len = (skb->data + skb->len) - ies;
++ ifsta->assocreq_ies = kmalloc(ifsta->assocreq_ies_len, GFP_KERNEL);
++ if (ifsta->assocreq_ies)
++ memcpy(ifsta->assocreq_ies, ies, ifsta->assocreq_ies_len);
++
++ ieee80211_sta_tx(dev, skb, 0);
++}
++
++
++static void ieee80211_send_deauth(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta, u16 reason)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct sk_buff *skb;
++ struct ieee80211_mgmt *mgmt;
++
++ skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
++ if (!skb) {
++ printk(KERN_DEBUG "%s: failed to allocate buffer for deauth "
++ "frame\n", dev->name);
++ return;
++ }
++ skb_reserve(skb, local->hw.extra_tx_headroom);
++
++ mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
++ memset(mgmt, 0, 24);
++ memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
++ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
++ memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
++ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++ IEEE80211_STYPE_DEAUTH);
++ skb_put(skb, 2);
++ mgmt->u.deauth.reason_code = cpu_to_le16(reason);
++
++ ieee80211_sta_tx(dev, skb, 0);
++}
++
++
++static void ieee80211_send_disassoc(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta, u16 reason)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct sk_buff *skb;
++ struct ieee80211_mgmt *mgmt;
++
++ skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
++ if (!skb) {
++ printk(KERN_DEBUG "%s: failed to allocate buffer for disassoc "
++ "frame\n", dev->name);
++ return;
++ }
++ skb_reserve(skb, local->hw.extra_tx_headroom);
++
++ mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
++ memset(mgmt, 0, 24);
++ memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
++ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
++ memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
++ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++ IEEE80211_STYPE_DISASSOC);
++ skb_put(skb, 2);
++ mgmt->u.disassoc.reason_code = cpu_to_le16(reason);
++
++ ieee80211_sta_tx(dev, skb, 0);
++}
++
++
++static int ieee80211_privacy_mismatch(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sta_bss *bss;
++ int bss_privacy;
++ int wep_privacy;
++ int privacy_invoked;
++
++ if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL))
++ return 0;
++
++ bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
++ local->hw.conf.channel->center_freq,
++ ifsta->ssid, ifsta->ssid_len);
++ if (!bss)
++ return 0;
++
++ bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY);
++ wep_privacy = !!ieee80211_sta_wep_configured(dev);
++ privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED);
++
++ ieee80211_rx_bss_put(dev, bss);
++
++ if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked))
++ return 0;
++
++ return 1;
++}
++
++
++static void ieee80211_associate(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta)
++{
++ DECLARE_MAC_BUF(mac);
++
++ ifsta->assoc_tries++;
++ if (ifsta->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) {
++ printk(KERN_DEBUG "%s: association with AP %s"
++ " timed out\n",
++ dev->name, print_mac(mac, ifsta->bssid));
++ ifsta->state = IEEE80211_DISABLED;
++ return;
++ }
++
++ ifsta->state = IEEE80211_ASSOCIATE;
++ printk(KERN_DEBUG "%s: associate with AP %s\n",
++ dev->name, print_mac(mac, ifsta->bssid));
++ if (ieee80211_privacy_mismatch(dev, ifsta)) {
++ printk(KERN_DEBUG "%s: mismatch in privacy configuration and "
++ "mixed-cell disabled - abort association\n", dev->name);
++ ifsta->state = IEEE80211_DISABLED;
++ return;
++ }
++
++ ieee80211_send_assoc(dev, ifsta);
++
++ mod_timer(&ifsta->timer, jiffies + IEEE80211_ASSOC_TIMEOUT);
++}
++
++
++static void ieee80211_associated(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct sta_info *sta;
++ int disassoc;
++ DECLARE_MAC_BUF(mac);
++
++ /* TODO: start monitoring current AP signal quality and number of
++ * missed beacons. Scan other channels every now and then and search
++ * for better APs. */
++ /* TODO: remove expired BSSes */
++
++ ifsta->state = IEEE80211_ASSOCIATED;
++
++ rcu_read_lock();
++
++ sta = sta_info_get(local, ifsta->bssid);
++ if (!sta) {
++ printk(KERN_DEBUG "%s: No STA entry for own AP %s\n",
++ dev->name, print_mac(mac, ifsta->bssid));
++ disassoc = 1;
++ } else {
++ disassoc = 0;
++ if (time_after(jiffies,
++ sta->last_rx + IEEE80211_MONITORING_INTERVAL)) {
++ if (ifsta->flags & IEEE80211_STA_PROBEREQ_POLL) {
++ printk(KERN_DEBUG "%s: No ProbeResp from "
++ "current AP %s - assume out of "
++ "range\n",
++ dev->name, print_mac(mac, ifsta->bssid));
++ disassoc = 1;
++ sta_info_unlink(&sta);
++ } else
++ ieee80211_send_probe_req(dev, ifsta->bssid,
++ local->scan_ssid,
++ local->scan_ssid_len);
++ ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL;
++ } else {
++ ifsta->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
++ if (time_after(jiffies, ifsta->last_probe +
++ IEEE80211_PROBE_INTERVAL)) {
++ ifsta->last_probe = jiffies;
++ ieee80211_send_probe_req(dev, ifsta->bssid,
++ ifsta->ssid,
++ ifsta->ssid_len);
++ }
++ }
++ }
++
++ rcu_read_unlock();
++
++ if (disassoc && sta)
++ sta_info_destroy(sta);
++
++ if (disassoc) {
++ ifsta->state = IEEE80211_DISABLED;
++ ieee80211_set_associated(dev, ifsta, 0);
++ } else {
++ mod_timer(&ifsta->timer, jiffies +
++ IEEE80211_MONITORING_INTERVAL);
++ }
++}
++
++
++static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
++ u8 *ssid, size_t ssid_len)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_supported_band *sband;
++ struct sk_buff *skb;
++ struct ieee80211_mgmt *mgmt;
++ u8 *pos, *supp_rates, *esupp_rates = NULL;
++ int i;
++
++ skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200);
++ if (!skb) {
++ printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
++ "request\n", dev->name);
++ return;
++ }
++ skb_reserve(skb, local->hw.extra_tx_headroom);
++
++ mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
++ memset(mgmt, 0, 24);
++ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++ IEEE80211_STYPE_PROBE_REQ);
++ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
++ if (dst) {
++ memcpy(mgmt->da, dst, ETH_ALEN);
++ memcpy(mgmt->bssid, dst, ETH_ALEN);
++ } else {
++ memset(mgmt->da, 0xff, ETH_ALEN);
++ memset(mgmt->bssid, 0xff, ETH_ALEN);
++ }
++ pos = skb_put(skb, 2 + ssid_len);
++ *pos++ = WLAN_EID_SSID;
++ *pos++ = ssid_len;
++ memcpy(pos, ssid, ssid_len);
++
++ supp_rates = skb_put(skb, 2);
++ supp_rates[0] = WLAN_EID_SUPP_RATES;
++ supp_rates[1] = 0;
++ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++
++ for (i = 0; i < sband->n_bitrates; i++) {
++ struct ieee80211_rate *rate = &sband->bitrates[i];
++ if (esupp_rates) {
++ pos = skb_put(skb, 1);
++ esupp_rates[1]++;
++ } else if (supp_rates[1] == 8) {
++ esupp_rates = skb_put(skb, 3);
++ esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES;
++ esupp_rates[1] = 1;
++ pos = &esupp_rates[2];
++ } else {
++ pos = skb_put(skb, 1);
++ supp_rates[1]++;
++ }
++ *pos = rate->bitrate / 5;
++ }
++
++ ieee80211_sta_tx(dev, skb, 0);
++}
++
++
++static int ieee80211_sta_wep_configured(struct net_device *dev)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ if (!sdata || !sdata->default_key ||
++ sdata->default_key->conf.alg != ALG_WEP)
++ return 0;
++ return 1;
++}
++
++
++static void ieee80211_auth_completed(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta)
++{
++ printk(KERN_DEBUG "%s: authenticated\n", dev->name);
++ ifsta->flags |= IEEE80211_STA_AUTHENTICATED;
++ ieee80211_associate(dev, ifsta);
++}
++
++
++static void ieee80211_auth_challenge(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta,
++ struct ieee80211_mgmt *mgmt,
++ size_t len)
++{
++ u8 *pos;
++ struct ieee802_11_elems elems;
++
++ printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name);
++ pos = mgmt->u.auth.variable;
++ ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
++ if (!elems.challenge) {
++ printk(KERN_DEBUG "%s: no challenge IE in shared key auth "
++ "frame\n", dev->name);
++ return;
++ }
++ ieee80211_send_auth(dev, ifsta, 3, elems.challenge - 2,
++ elems.challenge_len + 2, 1);
++}
++
++static void ieee80211_send_addba_resp(struct net_device *dev, u8 *da, u16 tid,
++ u8 dialog_token, u16 status, u16 policy,
++ u16 buf_size, u16 timeout)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct sk_buff *skb;
++ struct ieee80211_mgmt *mgmt;
++ u16 capab;
++
++ skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom + 1 +
++ sizeof(mgmt->u.action.u.addba_resp));
++ if (!skb) {
++ printk(KERN_DEBUG "%s: failed to allocate buffer "
++ "for addba resp frame\n", dev->name);
++ return;
++ }
++
++ skb_reserve(skb, local->hw.extra_tx_headroom);
++ mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
++ memset(mgmt, 0, 24);
++ memcpy(mgmt->da, da, ETH_ALEN);
++ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
++ if (sdata->vif.type == IEEE80211_IF_TYPE_AP)
++ memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN);
++ else
++ memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
++ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++ IEEE80211_STYPE_ACTION);
++
++ skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp));
++ mgmt->u.action.category = WLAN_CATEGORY_BACK;
++ mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP;
++ mgmt->u.action.u.addba_resp.dialog_token = dialog_token;
++
++ capab = (u16)(policy << 1); /* bit 1 aggregation policy */
++ capab |= (u16)(tid << 2); /* bit 5:2 TID number */
++ capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */
++
++ mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab);
++ mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout);
++ mgmt->u.action.u.addba_resp.status = cpu_to_le16(status);
++
++ ieee80211_sta_tx(dev, skb, 0);
++
++ return;
++}
++
++void ieee80211_send_addba_request(struct net_device *dev, const u8 *da,
++ u16 tid, u8 dialog_token, u16 start_seq_num,
++ u16 agg_size, u16 timeout)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++ struct sk_buff *skb;
++ struct ieee80211_mgmt *mgmt;
++ u16 capab;
++
++ skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom + 1 +
++ sizeof(mgmt->u.action.u.addba_req));
++
++
++ if (!skb) {
++ printk(KERN_ERR "%s: failed to allocate buffer "
++ "for addba request frame\n", dev->name);
++ return;
++ }
++ skb_reserve(skb, local->hw.extra_tx_headroom);
++ mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
++ memset(mgmt, 0, 24);
++ memcpy(mgmt->da, da, ETH_ALEN);
++ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
++ if (sdata->vif.type == IEEE80211_IF_TYPE_AP)
++ memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN);
++ else
++ memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
++
++ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++ IEEE80211_STYPE_ACTION);
++
++ skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req));
++
++ mgmt->u.action.category = WLAN_CATEGORY_BACK;
++ mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ;
++
++ mgmt->u.action.u.addba_req.dialog_token = dialog_token;
++ capab = (u16)(1 << 1); /* bit 1 aggregation policy */
++ capab |= (u16)(tid << 2); /* bit 5:2 TID number */
++ capab |= (u16)(agg_size << 6); /* bit 15:6 max size of aggergation */
++
++ mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab);
++
++ mgmt->u.action.u.addba_req.timeout = cpu_to_le16(timeout);
++ mgmt->u.action.u.addba_req.start_seq_num =
++ cpu_to_le16(start_seq_num << 4);
++
++ ieee80211_sta_tx(dev, skb, 0);
++}
++
++static void ieee80211_sta_process_addba_request(struct net_device *dev,
++ struct ieee80211_mgmt *mgmt,
++ size_t len)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_hw *hw = &local->hw;
++ struct ieee80211_conf *conf = &hw->conf;
++ struct sta_info *sta;
++ struct tid_ampdu_rx *tid_agg_rx;
++ u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status;
++ u8 dialog_token;
++ int ret = -EOPNOTSUPP;
++ DECLARE_MAC_BUF(mac);
++
++ rcu_read_lock();
++
++ sta = sta_info_get(local, mgmt->sa);
++ if (!sta) {
++ rcu_read_unlock();
++ return;
++ }
++
++ /* extract session parameters from addba request frame */
++ dialog_token = mgmt->u.action.u.addba_req.dialog_token;
++ timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout);
++ start_seq_num =
++ le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4;
++
++ capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
++ ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1;
++ tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
++ buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
++
++ status = WLAN_STATUS_REQUEST_DECLINED;
++
++ /* sanity check for incoming parameters:
++ * check if configuration can support the BA policy
++ * and if buffer size does not exceeds max value */
++ if (((ba_policy != 1)
++ && (!(conf->ht_conf.cap & IEEE80211_HT_CAP_DELAY_BA)))
++ || (buf_size > IEEE80211_MAX_AMPDU_BUF)) {
++ status = WLAN_STATUS_INVALID_QOS_PARAM;
++#ifdef CONFIG_MAC80211_HT_DEBUG
++ if (net_ratelimit())
++ printk(KERN_DEBUG "AddBA Req with bad params from "
++ "%s on tid %u. policy %d, buffer size %d\n",
++ print_mac(mac, mgmt->sa), tid, ba_policy,
++ buf_size);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++ goto end_no_lock;
++ }
++ /* determine default buffer size */
++ if (buf_size == 0) {
++ struct ieee80211_supported_band *sband;
++
++ sband = local->hw.wiphy->bands[conf->channel->band];
++ buf_size = IEEE80211_MIN_AMPDU_BUF;
++ buf_size = buf_size << sband->ht_info.ampdu_factor;
++ }
++
++
++ /* examine state machine */
++ spin_lock_bh(&sta->ampdu_mlme.ampdu_rx);
++
++ if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) {
++#ifdef CONFIG_MAC80211_HT_DEBUG
++ if (net_ratelimit())
++ printk(KERN_DEBUG "unexpected AddBA Req from "
++ "%s on tid %u\n",
++ print_mac(mac, mgmt->sa), tid);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++ goto end;
++ }
++
++ /* prepare A-MPDU MLME for Rx aggregation */
++ sta->ampdu_mlme.tid_rx[tid] =
++ kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC);
++ if (!sta->ampdu_mlme.tid_rx[tid]) {
++ if (net_ratelimit())
++ printk(KERN_ERR "allocate rx mlme to tid %d failed\n",
++ tid);
++ goto end;
++ }
++ /* rx timer */
++ sta->ampdu_mlme.tid_rx[tid]->session_timer.function =
++ sta_rx_agg_session_timer_expired;
++ sta->ampdu_mlme.tid_rx[tid]->session_timer.data =
++ (unsigned long)&sta->timer_to_tid[tid];
++ init_timer(&sta->ampdu_mlme.tid_rx[tid]->session_timer);
++
++ tid_agg_rx = sta->ampdu_mlme.tid_rx[tid];
++
++ /* prepare reordering buffer */
++ tid_agg_rx->reorder_buf =
++ kmalloc(buf_size * sizeof(struct sk_buf *), GFP_ATOMIC);
++ if (!tid_agg_rx->reorder_buf) {
++ if (net_ratelimit())
++ printk(KERN_ERR "can not allocate reordering buffer "
++ "to tid %d\n", tid);
++ kfree(sta->ampdu_mlme.tid_rx[tid]);
++ goto end;
++ }
++ memset(tid_agg_rx->reorder_buf, 0,
++ buf_size * sizeof(struct sk_buf *));
++
++ if (local->ops->ampdu_action)
++ ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_START,
++ sta->addr, tid, &start_seq_num);
++#ifdef CONFIG_MAC80211_HT_DEBUG
++ printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++
++ if (ret) {
++ kfree(tid_agg_rx->reorder_buf);
++ kfree(tid_agg_rx);
++ sta->ampdu_mlme.tid_rx[tid] = NULL;
++ goto end;
++ }
++
++ /* change state and send addba resp */
++ sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL;
++ tid_agg_rx->dialog_token = dialog_token;
++ tid_agg_rx->ssn = start_seq_num;
++ tid_agg_rx->head_seq_num = start_seq_num;
++ tid_agg_rx->buf_size = buf_size;
++ tid_agg_rx->timeout = timeout;
++ tid_agg_rx->stored_mpdu_num = 0;
++ status = WLAN_STATUS_SUCCESS;
++end:
++ spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
++
++end_no_lock:
++ ieee80211_send_addba_resp(sta->sdata->dev, sta->addr, tid,
++ dialog_token, status, 1, buf_size, timeout);
++ rcu_read_unlock();
++}
++
++static void ieee80211_sta_process_addba_resp(struct net_device *dev,
++ struct ieee80211_mgmt *mgmt,
++ size_t len)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_hw *hw = &local->hw;
++ struct sta_info *sta;
++ u16 capab;
++ u16 tid;
++ u8 *state;
++
++ rcu_read_lock();
++
++ sta = sta_info_get(local, mgmt->sa);
++ if (!sta) {
++ rcu_read_unlock();
++ return;
++ }
++
++ capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
++ tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
++
++ state = &sta->ampdu_mlme.tid_state_tx[tid];
++
++ spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
++
++ if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
++ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++ printk(KERN_DEBUG "state not HT_ADDBA_REQUESTED_MSK:"
++ "%d\n", *state);
++ goto addba_resp_exit;
++ }
++
++ if (mgmt->u.action.u.addba_resp.dialog_token !=
++ sta->ampdu_mlme.tid_tx[tid]->dialog_token) {
++ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++#ifdef CONFIG_MAC80211_HT_DEBUG
++ printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++ goto addba_resp_exit;
++ }
++
++ del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
++#ifdef CONFIG_MAC80211_HT_DEBUG
++ printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++ if (le16_to_cpu(mgmt->u.action.u.addba_resp.status)
++ == WLAN_STATUS_SUCCESS) {
++ if (*state & HT_ADDBA_RECEIVED_MSK)
++ printk(KERN_DEBUG "double addBA response\n");
++
++ *state |= HT_ADDBA_RECEIVED_MSK;
++ sta->ampdu_mlme.addba_req_num[tid] = 0;
++
++ if (*state == HT_AGG_STATE_OPERATIONAL) {
++ printk(KERN_DEBUG "Aggregation on for tid %d \n", tid);
++ ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
++ }
++
++ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++ printk(KERN_DEBUG "recipient accepted agg: tid %d \n", tid);
++ } else {
++ printk(KERN_DEBUG "recipient rejected agg: tid %d \n", tid);
++
++ sta->ampdu_mlme.addba_req_num[tid]++;
++ /* this will allow the state check in stop_BA_session */
++ *state = HT_AGG_STATE_OPERATIONAL;
++ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++ ieee80211_stop_tx_ba_session(hw, sta->addr, tid,
++ WLAN_BACK_INITIATOR);
++ }
++
++addba_resp_exit:
++ rcu_read_unlock();
++}
++
++void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid,
++ u16 initiator, u16 reason_code)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++ struct sk_buff *skb;
++ struct ieee80211_mgmt *mgmt;
++ u16 params;
++
++ skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom + 1 +
++ sizeof(mgmt->u.action.u.delba));
++
++ if (!skb) {
++ printk(KERN_ERR "%s: failed to allocate buffer "
++ "for delba frame\n", dev->name);
++ return;
++ }
++
++ skb_reserve(skb, local->hw.extra_tx_headroom);
++ mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
++ memset(mgmt, 0, 24);
++ memcpy(mgmt->da, da, ETH_ALEN);
++ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
++ if (sdata->vif.type == IEEE80211_IF_TYPE_AP)
++ memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN);
++ else
++ memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
++ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++ IEEE80211_STYPE_ACTION);
++
++ skb_put(skb, 1 + sizeof(mgmt->u.action.u.delba));
++
++ mgmt->u.action.category = WLAN_CATEGORY_BACK;
++ mgmt->u.action.u.delba.action_code = WLAN_ACTION_DELBA;
++ params = (u16)(initiator << 11); /* bit 11 initiator */
++ params |= (u16)(tid << 12); /* bit 15:12 TID number */
++
++ mgmt->u.action.u.delba.params = cpu_to_le16(params);
++ mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code);
++
++ ieee80211_sta_tx(dev, skb, 0);
++}
++
++void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid,
++ u16 initiator, u16 reason)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_hw *hw = &local->hw;
++ struct sta_info *sta;
++ int ret, i;
++ DECLARE_MAC_BUF(mac);
++
++ rcu_read_lock();
++
++ sta = sta_info_get(local, ra);
++ if (!sta) {
++ rcu_read_unlock();
++ return;
++ }
++
++ /* check if TID is in operational state */
++ spin_lock_bh(&sta->ampdu_mlme.ampdu_rx);
++ if (sta->ampdu_mlme.tid_state_rx[tid]
++ != HT_AGG_STATE_OPERATIONAL) {
++ spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
++ rcu_read_unlock();
++ return;
++ }
++ sta->ampdu_mlme.tid_state_rx[tid] =
++ HT_AGG_STATE_REQ_STOP_BA_MSK |
++ (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
++ spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
++
++ /* stop HW Rx aggregation. ampdu_action existence
++ * already verified in session init so we add the BUG_ON */
++ BUG_ON(!local->ops->ampdu_action);
++
++#ifdef CONFIG_MAC80211_HT_DEBUG
++ printk(KERN_DEBUG "Rx BA session stop requested for %s tid %u\n",
++ print_mac(mac, ra), tid);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++
++ ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP,
++ ra, tid, NULL);
++ if (ret)
++ printk(KERN_DEBUG "HW problem - can not stop rx "
++ "aggergation for tid %d\n", tid);
++
++ /* shutdown timer has not expired */
++ if (initiator != WLAN_BACK_TIMER)
++ del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer);
++
++ /* check if this is a self generated aggregation halt */
++ if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER)
++ ieee80211_send_delba(dev, ra, tid, 0, reason);
++
++ /* free the reordering buffer */
++ for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) {
++ if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) {
++ /* release the reordered frames */
++ dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]);
++ sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--;
++ sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL;
++ }
++ }
++ /* free resources */
++ kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf);
++ kfree(sta->ampdu_mlme.tid_rx[tid]);
++ sta->ampdu_mlme.tid_rx[tid] = NULL;
++ sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE;
++
++ rcu_read_unlock();
++}
++
++
++static void ieee80211_sta_process_delba(struct net_device *dev,
++ struct ieee80211_mgmt *mgmt, size_t len)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct sta_info *sta;
++ u16 tid, params;
++ u16 initiator;
++ DECLARE_MAC_BUF(mac);
++
++ rcu_read_lock();
++
++ sta = sta_info_get(local, mgmt->sa);
++ if (!sta) {
++ rcu_read_unlock();
++ return;
++ }
++
++ params = le16_to_cpu(mgmt->u.action.u.delba.params);
++ tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12;
++ initiator = (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) >> 11;
++
++#ifdef CONFIG_MAC80211_HT_DEBUG
++ if (net_ratelimit())
++ printk(KERN_DEBUG "delba from %s (%s) tid %d reason code %d\n",
++ print_mac(mac, mgmt->sa),
++ initiator ? "initiator" : "recipient", tid,
++ mgmt->u.action.u.delba.reason_code);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++
++ if (initiator == WLAN_BACK_INITIATOR)
++ ieee80211_sta_stop_rx_ba_session(dev, sta->addr, tid,
++ WLAN_BACK_INITIATOR, 0);
++ else { /* WLAN_BACK_RECIPIENT */
++ spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
++ sta->ampdu_mlme.tid_state_tx[tid] =
++ HT_AGG_STATE_OPERATIONAL;
++ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++ ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid,
++ WLAN_BACK_RECIPIENT);
++ }
++ rcu_read_unlock();
++}
++
++/*
++ * After sending add Block Ack request we activated a timer until
++ * add Block Ack response will arrive from the recipient.
++ * If this timer expires sta_addba_resp_timer_expired will be executed.
++ */
++void sta_addba_resp_timer_expired(unsigned long data)
++{
++ /* not an elegant detour, but there is no choice as the timer passes
++ * only one argument, and both sta_info and TID are needed, so init
++ * flow in sta_info_create gives the TID as data, while the timer_to_id
++ * array gives the sta through container_of */
++ u16 tid = *(int *)data;
++ struct sta_info *temp_sta = container_of((void *)data,
++ struct sta_info, timer_to_tid[tid]);
++
++ struct ieee80211_local *local = temp_sta->local;
++ struct ieee80211_hw *hw = &local->hw;
++ struct sta_info *sta;
++ u8 *state;
++
++ rcu_read_lock();
++
++ sta = sta_info_get(local, temp_sta->addr);
++ if (!sta) {
++ rcu_read_unlock();
++ return;
++ }
++
++ state = &sta->ampdu_mlme.tid_state_tx[tid];
++ /* check if the TID waits for addBA response */
++ spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
++ if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
++ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++ *state = HT_AGG_STATE_IDLE;
++ printk(KERN_DEBUG "timer expired on tid %d but we are not "
++ "expecting addBA response there", tid);
++ goto timer_expired_exit;
++ }
++
++ printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid);
++
++ /* go through the state check in stop_BA_session */
++ *state = HT_AGG_STATE_OPERATIONAL;
++ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
++ ieee80211_stop_tx_ba_session(hw, temp_sta->addr, tid,
++ WLAN_BACK_INITIATOR);
++
++timer_expired_exit:
++ rcu_read_unlock();
++}
++
++/*
++ * After accepting the AddBA Request we activated a timer,
++ * resetting it after each frame that arrives from the originator.
++ * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed.
++ */
++void sta_rx_agg_session_timer_expired(unsigned long data)
++{
++ /* not an elegant detour, but there is no choice as the timer passes
++ * only one argument, and verious sta_info are needed here, so init
++ * flow in sta_info_create gives the TID as data, while the timer_to_id
++ * array gives the sta through container_of */
++ u8 *ptid = (u8 *)data;
++ u8 *timer_to_id = ptid - *ptid;
++ struct sta_info *sta = container_of(timer_to_id, struct sta_info,
++ timer_to_tid[0]);
++
++ printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid);
++ ieee80211_sta_stop_rx_ba_session(sta->sdata->dev, sta->addr,
++ (u16)*ptid, WLAN_BACK_TIMER,
++ WLAN_REASON_QSTA_TIMEOUT);
++}
++
++void ieee80211_sta_tear_down_BA_sessions(struct net_device *dev, u8 *addr)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ int i;
++
++ for (i = 0; i < STA_TID_NUM; i++) {
++ ieee80211_stop_tx_ba_session(&local->hw, addr, i,
++ WLAN_BACK_INITIATOR);
++ ieee80211_sta_stop_rx_ba_session(dev, addr, i,
++ WLAN_BACK_RECIPIENT,
++ WLAN_REASON_QSTA_LEAVE_QBSS);
++ }
++}
++
++static void ieee80211_rx_mgmt_auth(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta,
++ struct ieee80211_mgmt *mgmt,
++ size_t len)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ u16 auth_alg, auth_transaction, status_code;
++ DECLARE_MAC_BUF(mac);
++
++ if (ifsta->state != IEEE80211_AUTHENTICATE &&
++ sdata->vif.type != IEEE80211_IF_TYPE_IBSS) {
++ printk(KERN_DEBUG "%s: authentication frame received from "
++ "%s, but not in authenticate state - ignored\n",
++ dev->name, print_mac(mac, mgmt->sa));
++ return;
++ }
++
++ if (len < 24 + 6) {
++ printk(KERN_DEBUG "%s: too short (%zd) authentication frame "
++ "received from %s - ignored\n",
++ dev->name, len, print_mac(mac, mgmt->sa));
++ return;
++ }
++
++ if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
++ memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
++ printk(KERN_DEBUG "%s: authentication frame received from "
++ "unknown AP (SA=%s BSSID=%s) - "
++ "ignored\n", dev->name, print_mac(mac, mgmt->sa),
++ print_mac(mac, mgmt->bssid));
++ return;
++ }
++
++ if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
++ memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) {
++ printk(KERN_DEBUG "%s: authentication frame received from "
++ "unknown BSSID (SA=%s BSSID=%s) - "
++ "ignored\n", dev->name, print_mac(mac, mgmt->sa),
++ print_mac(mac, mgmt->bssid));
++ return;
++ }
++
++ auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
++ auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
++ status_code = le16_to_cpu(mgmt->u.auth.status_code);
++
++ printk(KERN_DEBUG "%s: RX authentication from %s (alg=%d "
++ "transaction=%d status=%d)\n",
++ dev->name, print_mac(mac, mgmt->sa), auth_alg,
++ auth_transaction, status_code);
++
++ if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
++ /* IEEE 802.11 standard does not require authentication in IBSS
++ * networks and most implementations do not seem to use it.
++ * However, try to reply to authentication attempts if someone
++ * has actually implemented this.
++ * TODO: Could implement shared key authentication. */
++ if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) {
++ printk(KERN_DEBUG "%s: unexpected IBSS authentication "
++ "frame (alg=%d transaction=%d)\n",
++ dev->name, auth_alg, auth_transaction);
++ return;
++ }
++ ieee80211_send_auth(dev, ifsta, 2, NULL, 0, 0);
++ }
++
++ if (auth_alg != ifsta->auth_alg ||
++ auth_transaction != ifsta->auth_transaction) {
++ printk(KERN_DEBUG "%s: unexpected authentication frame "
++ "(alg=%d transaction=%d)\n",
++ dev->name, auth_alg, auth_transaction);
++ return;
++ }
++
++ if (status_code != WLAN_STATUS_SUCCESS) {
++ printk(KERN_DEBUG "%s: AP denied authentication (auth_alg=%d "
++ "code=%d)\n", dev->name, ifsta->auth_alg, status_code);
++ if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
++ u8 algs[3];
++ const int num_algs = ARRAY_SIZE(algs);
++ int i, pos;
++ algs[0] = algs[1] = algs[2] = 0xff;
++ if (ifsta->auth_algs & IEEE80211_AUTH_ALG_OPEN)
++ algs[0] = WLAN_AUTH_OPEN;
++ if (ifsta->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
++ algs[1] = WLAN_AUTH_SHARED_KEY;
++ if (ifsta->auth_algs & IEEE80211_AUTH_ALG_LEAP)
++ algs[2] = WLAN_AUTH_LEAP;
++ if (ifsta->auth_alg == WLAN_AUTH_OPEN)
++ pos = 0;
++ else if (ifsta->auth_alg == WLAN_AUTH_SHARED_KEY)
++ pos = 1;
++ else
++ pos = 2;
++ for (i = 0; i < num_algs; i++) {
++ pos++;
++ if (pos >= num_algs)
++ pos = 0;
++ if (algs[pos] == ifsta->auth_alg ||
++ algs[pos] == 0xff)
++ continue;
++ if (algs[pos] == WLAN_AUTH_SHARED_KEY &&
++ !ieee80211_sta_wep_configured(dev))
++ continue;
++ ifsta->auth_alg = algs[pos];
++ printk(KERN_DEBUG "%s: set auth_alg=%d for "
++ "next try\n",
++ dev->name, ifsta->auth_alg);
++ break;
++ }
++ }
++ return;
++ }
++
++ switch (ifsta->auth_alg) {
++ case WLAN_AUTH_OPEN:
++ case WLAN_AUTH_LEAP:
++ ieee80211_auth_completed(dev, ifsta);
++ break;
++ case WLAN_AUTH_SHARED_KEY:
++ if (ifsta->auth_transaction == 4)
++ ieee80211_auth_completed(dev, ifsta);
++ else
++ ieee80211_auth_challenge(dev, ifsta, mgmt, len);
++ break;
++ }
++}
++
++
++static void ieee80211_rx_mgmt_deauth(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta,
++ struct ieee80211_mgmt *mgmt,
++ size_t len)
++{
++ u16 reason_code;
++ DECLARE_MAC_BUF(mac);
++
++ if (len < 24 + 2) {
++ printk(KERN_DEBUG "%s: too short (%zd) deauthentication frame "
++ "received from %s - ignored\n",
++ dev->name, len, print_mac(mac, mgmt->sa));
++ return;
++ }
++
++ if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
++ printk(KERN_DEBUG "%s: deauthentication frame received from "
++ "unknown AP (SA=%s BSSID=%s) - "
++ "ignored\n", dev->name, print_mac(mac, mgmt->sa),
++ print_mac(mac, mgmt->bssid));
++ return;
++ }
++
++ reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
++
++ printk(KERN_DEBUG "%s: RX deauthentication from %s"
++ " (reason=%d)\n",
++ dev->name, print_mac(mac, mgmt->sa), reason_code);
++
++ if (ifsta->flags & IEEE80211_STA_AUTHENTICATED) {
++ printk(KERN_DEBUG "%s: deauthenticated\n", dev->name);
++ }
++
++ if (ifsta->state == IEEE80211_AUTHENTICATE ||
++ ifsta->state == IEEE80211_ASSOCIATE ||
++ ifsta->state == IEEE80211_ASSOCIATED) {
++ ifsta->state = IEEE80211_AUTHENTICATE;
++ mod_timer(&ifsta->timer, jiffies +
++ IEEE80211_RETRY_AUTH_INTERVAL);
++ }
++
++ ieee80211_set_disassoc(dev, ifsta, 1);
++ ifsta->flags &= ~IEEE80211_STA_AUTHENTICATED;
++}
++
++
++static void ieee80211_rx_mgmt_disassoc(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta,
++ struct ieee80211_mgmt *mgmt,
++ size_t len)
++{
++ u16 reason_code;
++ DECLARE_MAC_BUF(mac);
++
++ if (len < 24 + 2) {
++ printk(KERN_DEBUG "%s: too short (%zd) disassociation frame "
++ "received from %s - ignored\n",
++ dev->name, len, print_mac(mac, mgmt->sa));
++ return;
++ }
++
++ if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
++ printk(KERN_DEBUG "%s: disassociation frame received from "
++ "unknown AP (SA=%s BSSID=%s) - "
++ "ignored\n", dev->name, print_mac(mac, mgmt->sa),
++ print_mac(mac, mgmt->bssid));
++ return;
++ }
++
++ reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
++
++ printk(KERN_DEBUG "%s: RX disassociation from %s"
++ " (reason=%d)\n",
++ dev->name, print_mac(mac, mgmt->sa), reason_code);
++
++ if (ifsta->flags & IEEE80211_STA_ASSOCIATED)
++ printk(KERN_DEBUG "%s: disassociated\n", dev->name);
++
++ if (ifsta->state == IEEE80211_ASSOCIATED) {
++ ifsta->state = IEEE80211_ASSOCIATE;
++ mod_timer(&ifsta->timer, jiffies +
++ IEEE80211_RETRY_AUTH_INTERVAL);
++ }
++
++ ieee80211_set_disassoc(dev, ifsta, 0);
++}
++
++
++static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
++ struct ieee80211_if_sta *ifsta,
++ struct ieee80211_mgmt *mgmt,
++ size_t len,
++ int reassoc)
++{
++ struct ieee80211_local *local = sdata->local;
++ struct net_device *dev = sdata->dev;
++ struct ieee80211_supported_band *sband;
++ struct sta_info *sta;
++ u64 rates, basic_rates;
++ u16 capab_info, status_code, aid;
++ struct ieee802_11_elems elems;
++ struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf;
++ u8 *pos;
++ int i, j;
++ DECLARE_MAC_BUF(mac);
++ bool have_higher_than_11mbit = false;
++
++ /* AssocResp and ReassocResp have identical structure, so process both
++ * of them in this function. */
++
++ if (ifsta->state != IEEE80211_ASSOCIATE) {
++ printk(KERN_DEBUG "%s: association frame received from "
++ "%s, but not in associate state - ignored\n",
++ dev->name, print_mac(mac, mgmt->sa));
++ return;
++ }
++
++ if (len < 24 + 6) {
++ printk(KERN_DEBUG "%s: too short (%zd) association frame "
++ "received from %s - ignored\n",
++ dev->name, len, print_mac(mac, mgmt->sa));
++ return;
++ }
++
++ if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
++ printk(KERN_DEBUG "%s: association frame received from "
++ "unknown AP (SA=%s BSSID=%s) - "
++ "ignored\n", dev->name, print_mac(mac, mgmt->sa),
++ print_mac(mac, mgmt->bssid));
++ return;
++ }
++
++ capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
++ status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
++ aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
++
++ printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x "
++ "status=%d aid=%d)\n",
++ dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa),
++ capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
++
++ if (status_code != WLAN_STATUS_SUCCESS) {
++ printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
++ dev->name, status_code);
++ /* if this was a reassociation, ensure we try a "full"
++ * association next time. This works around some broken APs
++ * which do not correctly reject reassociation requests. */
++ ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
++ return;
++ }
++
++ if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
++ printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not "
++ "set\n", dev->name, aid);
++ aid &= ~(BIT(15) | BIT(14));
++
++ pos = mgmt->u.assoc_resp.variable;
++ ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
++
++ if (!elems.supp_rates) {
++ printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
++ dev->name);
++ return;
++ }
++
++ printk(KERN_DEBUG "%s: associated\n", dev->name);
++ ifsta->aid = aid;
++ ifsta->ap_capab = capab_info;
++
++ kfree(ifsta->assocresp_ies);
++ ifsta->assocresp_ies_len = len - (pos - (u8 *) mgmt);
++ ifsta->assocresp_ies = kmalloc(ifsta->assocresp_ies_len, GFP_KERNEL);
++ if (ifsta->assocresp_ies)
++ memcpy(ifsta->assocresp_ies, pos, ifsta->assocresp_ies_len);
++
++ rcu_read_lock();
++
++ /* Add STA entry for the AP */
++ sta = sta_info_get(local, ifsta->bssid);
++ if (!sta) {
++ struct ieee80211_sta_bss *bss;
++ int err;
++
++ sta = sta_info_alloc(sdata, ifsta->bssid, GFP_ATOMIC);
++ if (!sta) {
++ printk(KERN_DEBUG "%s: failed to alloc STA entry for"
++ " the AP\n", dev->name);
++ rcu_read_unlock();
++ return;
++ }
++ bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
++ local->hw.conf.channel->center_freq,
++ ifsta->ssid, ifsta->ssid_len);
++ if (bss) {
++ sta->last_rssi = bss->rssi;
++ sta->last_signal = bss->signal;
++ sta->last_noise = bss->noise;
++ ieee80211_rx_bss_put(dev, bss);
++ }
++
++ err = sta_info_insert(sta);
++ if (err) {
++ printk(KERN_DEBUG "%s: failed to insert STA entry for"
++ " the AP (error %d)\n", dev->name, err);
++ rcu_read_unlock();
++ return;
++ }
++ }
++
++ /*
++ * FIXME: Do we really need to update the sta_info's information here?
++ * We already know about the AP (we found it in our list) so it
++ * should already be filled with the right info, no?
++ * As is stands, all this is racy because typically we assume
++ * the information that is filled in here (except flags) doesn't
++ * change while a STA structure is alive. As such, it should move
++ * to between the sta_info_alloc() and sta_info_insert() above.
++ */
++
++ sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP |
++ WLAN_STA_AUTHORIZED;
++
++ rates = 0;
++ basic_rates = 0;
++ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++
++ for (i = 0; i < elems.supp_rates_len; i++) {
++ int rate = (elems.supp_rates[i] & 0x7f) * 5;
++
++ if (rate > 110)
++ have_higher_than_11mbit = true;
++
++ for (j = 0; j < sband->n_bitrates; j++) {
++ if (sband->bitrates[j].bitrate == rate)
++ rates |= BIT(j);
++ if (elems.supp_rates[i] & 0x80)
++ basic_rates |= BIT(j);
++ }
++ }
++
++ for (i = 0; i < elems.ext_supp_rates_len; i++) {
++ int rate = (elems.ext_supp_rates[i] & 0x7f) * 5;
++
++ if (rate > 110)
++ have_higher_than_11mbit = true;
++
++ for (j = 0; j < sband->n_bitrates; j++) {
++ if (sband->bitrates[j].bitrate == rate)
++ rates |= BIT(j);
++ if (elems.ext_supp_rates[i] & 0x80)
++ basic_rates |= BIT(j);
++ }
++ }
++
++ sta->supp_rates[local->hw.conf.channel->band] = rates;
++ sdata->basic_rates = basic_rates;
++
++ /* cf. IEEE 802.11 9.2.12 */
++ if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ &&
++ have_higher_than_11mbit)
++ sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
++ else
++ sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
++
++ if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param) {
++ struct ieee80211_ht_bss_info bss_info;
++ ieee80211_ht_cap_ie_to_ht_info(
++ (struct ieee80211_ht_cap *)
++ elems.ht_cap_elem, &sta->ht_info);
++ ieee80211_ht_addt_info_ie_to_ht_bss_info(
++ (struct ieee80211_ht_addt_info *)
++ elems.ht_info_elem, &bss_info);
++ ieee80211_handle_ht(local, 1, &sta->ht_info, &bss_info);
++ }
++
++ rate_control_rate_init(sta, local);
++
++ if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
++ sta->flags |= WLAN_STA_WME;
++ rcu_read_unlock();
++ ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
++ elems.wmm_param_len);
++ } else
++ rcu_read_unlock();
++
++ /* set AID and assoc capability,
++ * ieee80211_set_associated() will tell the driver */
++ bss_conf->aid = aid;
++ bss_conf->assoc_capability = capab_info;
++ ieee80211_set_associated(dev, ifsta, 1);
++
++ ieee80211_associated(dev, ifsta);
++}
++
++
++/* Caller must hold local->sta_bss_lock */
++static void __ieee80211_rx_bss_hash_add(struct net_device *dev,
++ struct ieee80211_sta_bss *bss)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ u8 hash_idx;
++
++ if (bss_mesh_cfg(bss))
++ hash_idx = mesh_id_hash(bss_mesh_id(bss),
++ bss_mesh_id_len(bss));
++ else
++ hash_idx = STA_HASH(bss->bssid);
++
++ bss->hnext = local->sta_bss_hash[hash_idx];
++ local->sta_bss_hash[hash_idx] = bss;
++}
++
++
++/* Caller must hold local->sta_bss_lock */
++static void __ieee80211_rx_bss_hash_del(struct net_device *dev,
++ struct ieee80211_sta_bss *bss)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sta_bss *b, *prev = NULL;
++ b = local->sta_bss_hash[STA_HASH(bss->bssid)];
++ while (b) {
++ if (b == bss) {
++ if (!prev)
++ local->sta_bss_hash[STA_HASH(bss->bssid)] =
++ bss->hnext;
++ else
++ prev->hnext = bss->hnext;
++ break;
++ }
++ prev = b;
++ b = b->hnext;
++ }
++}
++
++
++static struct ieee80211_sta_bss *
++ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int freq,
++ u8 *ssid, u8 ssid_len)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sta_bss *bss;
++
++ bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
++ if (!bss)
++ return NULL;
++ atomic_inc(&bss->users);
++ atomic_inc(&bss->users);
++ memcpy(bss->bssid, bssid, ETH_ALEN);
++ bss->freq = freq;
++ if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) {
++ memcpy(bss->ssid, ssid, ssid_len);
++ bss->ssid_len = ssid_len;
++ }
++
++ spin_lock_bh(&local->sta_bss_lock);
++ /* TODO: order by RSSI? */
++ list_add_tail(&bss->list, &local->sta_bss_list);
++ __ieee80211_rx_bss_hash_add(dev, bss);
++ spin_unlock_bh(&local->sta_bss_lock);
++ return bss;
++}
++
++static struct ieee80211_sta_bss *
++ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq,
++ u8 *ssid, u8 ssid_len)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sta_bss *bss;
++
++ spin_lock_bh(&local->sta_bss_lock);
++ bss = local->sta_bss_hash[STA_HASH(bssid)];
++ while (bss) {
++ if (!bss_mesh_cfg(bss) &&
++ !memcmp(bss->bssid, bssid, ETH_ALEN) &&
++ bss->freq == freq &&
++ bss->ssid_len == ssid_len &&
++ (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) {
++ atomic_inc(&bss->users);
++ break;
++ }
++ bss = bss->hnext;
++ }
++ spin_unlock_bh(&local->sta_bss_lock);
++ return bss;
++}
++
++#ifdef CONFIG_MAC80211_MESH
++static struct ieee80211_sta_bss *
++ieee80211_rx_mesh_bss_get(struct net_device *dev, u8 *mesh_id, int mesh_id_len,
++ u8 *mesh_cfg, int freq)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sta_bss *bss;
++
++ spin_lock_bh(&local->sta_bss_lock);
++ bss = local->sta_bss_hash[mesh_id_hash(mesh_id, mesh_id_len)];
++ while (bss) {
++ if (bss_mesh_cfg(bss) &&
++ !memcmp(bss_mesh_cfg(bss), mesh_cfg, MESH_CFG_CMP_LEN) &&
++ bss->freq == freq &&
++ mesh_id_len == bss->mesh_id_len &&
++ (mesh_id_len == 0 || !memcmp(bss->mesh_id, mesh_id,
++ mesh_id_len))) {
++ atomic_inc(&bss->users);
++ break;
++ }
++ bss = bss->hnext;
++ }
++ spin_unlock_bh(&local->sta_bss_lock);
++ return bss;
++}
++
++static struct ieee80211_sta_bss *
++ieee80211_rx_mesh_bss_add(struct net_device *dev, u8 *mesh_id, int mesh_id_len,
++ u8 *mesh_cfg, int mesh_config_len, int freq)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sta_bss *bss;
++
++ if (mesh_config_len != MESH_CFG_LEN)
++ return NULL;
++
++ bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
++ if (!bss)
++ return NULL;
++
++ bss->mesh_cfg = kmalloc(MESH_CFG_CMP_LEN, GFP_ATOMIC);
++ if (!bss->mesh_cfg) {
++ kfree(bss);
++ return NULL;
++ }
++
++ if (mesh_id_len && mesh_id_len <= IEEE80211_MAX_MESH_ID_LEN) {
++ bss->mesh_id = kmalloc(mesh_id_len, GFP_ATOMIC);
++ if (!bss->mesh_id) {
++ kfree(bss->mesh_cfg);
++ kfree(bss);
++ return NULL;
++ }
++ memcpy(bss->mesh_id, mesh_id, mesh_id_len);
++ }
++
++ atomic_inc(&bss->users);
++ atomic_inc(&bss->users);
++ memcpy(bss->mesh_cfg, mesh_cfg, MESH_CFG_CMP_LEN);
++ bss->mesh_id_len = mesh_id_len;
++ bss->freq = freq;
++ spin_lock_bh(&local->sta_bss_lock);
++ /* TODO: order by RSSI? */
++ list_add_tail(&bss->list, &local->sta_bss_list);
++ __ieee80211_rx_bss_hash_add(dev, bss);
++ spin_unlock_bh(&local->sta_bss_lock);
++ return bss;
++}
++#endif
++
++static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss)
++{
++ kfree(bss->wpa_ie);
++ kfree(bss->rsn_ie);
++ kfree(bss->wmm_ie);
++ kfree(bss->ht_ie);
++ kfree(bss_mesh_id(bss));
++ kfree(bss_mesh_cfg(bss));
++ kfree(bss);
++}
++
++
++static void ieee80211_rx_bss_put(struct net_device *dev,
++ struct ieee80211_sta_bss *bss)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++ local_bh_disable();
++ if (!atomic_dec_and_lock(&bss->users, &local->sta_bss_lock)) {
++ local_bh_enable();
++ return;
++ }
++
++ __ieee80211_rx_bss_hash_del(dev, bss);
++ list_del(&bss->list);
++ spin_unlock_bh(&local->sta_bss_lock);
++ ieee80211_rx_bss_free(bss);
++}
++
++
++void ieee80211_rx_bss_list_init(struct net_device *dev)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ spin_lock_init(&local->sta_bss_lock);
++ INIT_LIST_HEAD(&local->sta_bss_list);
++}
++
++
++void ieee80211_rx_bss_list_deinit(struct net_device *dev)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sta_bss *bss, *tmp;
++
++ list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list)
++ ieee80211_rx_bss_put(dev, bss);
++}
++
++
++static int ieee80211_sta_join_ibss(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta,
++ struct ieee80211_sta_bss *bss)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ int res, rates, i, j;
++ struct sk_buff *skb;
++ struct ieee80211_mgmt *mgmt;
++ struct ieee80211_tx_control control;
++ struct rate_selection ratesel;
++ u8 *pos;
++ struct ieee80211_sub_if_data *sdata;
++ struct ieee80211_supported_band *sband;
++
++ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++
++ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++ /* Remove possible STA entries from other IBSS networks. */
++ sta_info_flush_delayed(sdata);
++
++ if (local->ops->reset_tsf) {
++ /* Reset own TSF to allow time synchronization work. */
++ local->ops->reset_tsf(local_to_hw(local));
++ }
++ memcpy(ifsta->bssid, bss->bssid, ETH_ALEN);
++ res = ieee80211_if_config(dev);
++ if (res)
++ return res;
++
++ local->hw.conf.beacon_int = bss->beacon_int >= 10 ? bss->beacon_int : 10;
++
++ sdata->drop_unencrypted = bss->capability &
++ WLAN_CAPABILITY_PRIVACY ? 1 : 0;
++
++ res = ieee80211_set_freq(local, bss->freq);
++
++ if (local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS) {
++ printk(KERN_DEBUG "%s: IBSS not allowed on frequency "
++ "%d MHz\n", dev->name, local->oper_channel->center_freq);
++ return -1;
++ }
++
++ /* Set beacon template */
++ skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
++ do {
++ if (!skb)
++ break;
++
++ skb_reserve(skb, local->hw.extra_tx_headroom);
++
++ mgmt = (struct ieee80211_mgmt *)
++ skb_put(skb, 24 + sizeof(mgmt->u.beacon));
++ memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
++ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++ IEEE80211_STYPE_BEACON);
++ memset(mgmt->da, 0xff, ETH_ALEN);
++ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
++ memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
++ mgmt->u.beacon.beacon_int =
++ cpu_to_le16(local->hw.conf.beacon_int);
++ mgmt->u.beacon.capab_info = cpu_to_le16(bss->capability);
++
++ pos = skb_put(skb, 2 + ifsta->ssid_len);
++ *pos++ = WLAN_EID_SSID;
++ *pos++ = ifsta->ssid_len;
++ memcpy(pos, ifsta->ssid, ifsta->ssid_len);
++
++ rates = bss->supp_rates_len;
++ if (rates > 8)
++ rates = 8;
++ pos = skb_put(skb, 2 + rates);
++ *pos++ = WLAN_EID_SUPP_RATES;
++ *pos++ = rates;
++ memcpy(pos, bss->supp_rates, rates);
++
++ if (bss->band == IEEE80211_BAND_2GHZ) {
++ pos = skb_put(skb, 2 + 1);
++ *pos++ = WLAN_EID_DS_PARAMS;
++ *pos++ = 1;
++ *pos++ = ieee80211_frequency_to_channel(bss->freq);
++ }
++
++ pos = skb_put(skb, 2 + 2);
++ *pos++ = WLAN_EID_IBSS_PARAMS;
++ *pos++ = 2;
++ /* FIX: set ATIM window based on scan results */
++ *pos++ = 0;
++ *pos++ = 0;
++
++ if (bss->supp_rates_len > 8) {
++ rates = bss->supp_rates_len - 8;
++ pos = skb_put(skb, 2 + rates);
++ *pos++ = WLAN_EID_EXT_SUPP_RATES;
++ *pos++ = rates;
++ memcpy(pos, &bss->supp_rates[8], rates);
++ }
++
++ memset(&control, 0, sizeof(control));
++ rate_control_get_rate(dev, sband, skb, &ratesel);
++ if (!ratesel.rate) {
++ printk(KERN_DEBUG "%s: Failed to determine TX rate "
++ "for IBSS beacon\n", dev->name);
++ break;
++ }
++ control.vif = &sdata->vif;
++ control.tx_rate = ratesel.rate;
++ if (sdata->bss_conf.use_short_preamble &&
++ ratesel.rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
++ control.flags |= IEEE80211_TXCTL_SHORT_PREAMBLE;
++ control.antenna_sel_tx = local->hw.conf.antenna_sel_tx;
++ control.flags |= IEEE80211_TXCTL_NO_ACK;
++ control.retry_limit = 1;
++
++ ifsta->probe_resp = skb_copy(skb, GFP_ATOMIC);
++ if (ifsta->probe_resp) {
++ mgmt = (struct ieee80211_mgmt *)
++ ifsta->probe_resp->data;
++ mgmt->frame_control =
++ IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++ IEEE80211_STYPE_PROBE_RESP);
++ } else {
++ printk(KERN_DEBUG "%s: Could not allocate ProbeResp "
++ "template for IBSS\n", dev->name);
++ }
++
++ if (local->ops->beacon_update &&
++ local->ops->beacon_update(local_to_hw(local),
++ skb, &control) == 0) {
++ printk(KERN_DEBUG "%s: Configured IBSS beacon "
++ "template\n", dev->name);
++ skb = NULL;
++ }
++
++ rates = 0;
++ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++ for (i = 0; i < bss->supp_rates_len; i++) {
++ int bitrate = (bss->supp_rates[i] & 0x7f) * 5;
++ for (j = 0; j < sband->n_bitrates; j++)
++ if (sband->bitrates[j].bitrate == bitrate)
++ rates |= BIT(j);
++ }
++ ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates;
++
++ ieee80211_sta_def_wmm_params(dev, bss, 1);
++ } while (0);
++
++ if (skb) {
++ printk(KERN_DEBUG "%s: Failed to configure IBSS beacon "
++ "template\n", dev->name);
++ dev_kfree_skb(skb);
++ }
++
++ ifsta->state = IEEE80211_IBSS_JOINED;
++ mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
++
++ ieee80211_rx_bss_put(dev, bss);
++
++ return res;
++}
++
++u64 ieee80211_sta_get_rates(struct ieee80211_local *local,
++ struct ieee802_11_elems *elems,
++ enum ieee80211_band band)
++{
++ struct ieee80211_supported_band *sband;
++ struct ieee80211_rate *bitrates;
++ size_t num_rates;
++ u64 supp_rates;
++ int i, j;
++ sband = local->hw.wiphy->bands[band];
++
++ if (!sband) {
++ WARN_ON(1);
++ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++ }
++
++ bitrates = sband->bitrates;
++ num_rates = sband->n_bitrates;
++ supp_rates = 0;
++ for (i = 0; i < elems->supp_rates_len +
++ elems->ext_supp_rates_len; i++) {
++ u8 rate = 0;
++ int own_rate;
++ if (i < elems->supp_rates_len)
++ rate = elems->supp_rates[i];
++ else if (elems->ext_supp_rates)
++ rate = elems->ext_supp_rates
++ [i - elems->supp_rates_len];
++ own_rate = 5 * (rate & 0x7f);
++ for (j = 0; j < num_rates; j++)
++ if (bitrates[j].bitrate == own_rate)
++ supp_rates |= BIT(j);
++ }
++ return supp_rates;
++}
++
++
++static void ieee80211_rx_bss_info(struct net_device *dev,
++ struct ieee80211_mgmt *mgmt,
++ size_t len,
++ struct ieee80211_rx_status *rx_status,
++ int beacon)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee802_11_elems elems;
++ size_t baselen;
++ int freq, clen;
++ struct ieee80211_sta_bss *bss;
++ struct sta_info *sta;
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ u64 beacon_timestamp, rx_timestamp;
++ struct ieee80211_channel *channel;
++ DECLARE_MAC_BUF(mac);
++ DECLARE_MAC_BUF(mac2);
++
++ if (!beacon && memcmp(mgmt->da, dev->dev_addr, ETH_ALEN))
++ return; /* ignore ProbeResp to foreign address */
++
++#if 0
++ printk(KERN_DEBUG "%s: RX %s from %s to %s\n",
++ dev->name, beacon ? "Beacon" : "Probe Response",
++ print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da));
++#endif
++
++ baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
++ if (baselen > len)
++ return;
++
++ beacon_timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);
++ ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
++
++ if (ieee80211_vif_is_mesh(&sdata->vif) && elems.mesh_id &&
++ elems.mesh_config && mesh_matches_local(&elems, dev)) {
++ u64 rates = ieee80211_sta_get_rates(local, &elems,
++ rx_status->band);
++
++ mesh_neighbour_update(mgmt->sa, rates, dev,
++ mesh_peer_accepts_plinks(&elems, dev));
++ }
++
++ rcu_read_lock();
++
++ if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates &&
++ memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 &&
++ (sta = sta_info_get(local, mgmt->sa))) {
++ u64 prev_rates;
++ u64 supp_rates = ieee80211_sta_get_rates(local, &elems,
++ rx_status->band);
++
++ prev_rates = sta->supp_rates[rx_status->band];
++ sta->supp_rates[rx_status->band] &= supp_rates;
++ if (sta->supp_rates[rx_status->band] == 0) {
++ /* No matching rates - this should not really happen.
++ * Make sure that at least one rate is marked
++ * supported to avoid issues with TX rate ctrl. */
++ sta->supp_rates[rx_status->band] =
++ sdata->u.sta.supp_rates_bits[rx_status->band];
++ }
++ if (sta->supp_rates[rx_status->band] != prev_rates) {
++ printk(KERN_DEBUG "%s: updated supp_rates set for "
++ "%s based on beacon info (0x%llx & 0x%llx -> "
++ "0x%llx)\n",
++ dev->name, print_mac(mac, sta->addr),
++ (unsigned long long) prev_rates,
++ (unsigned long long) supp_rates,
++ (unsigned long long) sta->supp_rates[rx_status->band]);
++ }
++ }
++
++ rcu_read_unlock();
++
++ if (elems.ds_params && elems.ds_params_len == 1)
++ freq = ieee80211_channel_to_frequency(elems.ds_params[0]);
++ else
++ freq = rx_status->freq;
++
++ channel = ieee80211_get_channel(local->hw.wiphy, freq);
++
++ if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
++ return;
++
++#ifdef CONFIG_MAC80211_MESH
++ if (elems.mesh_config)
++ bss = ieee80211_rx_mesh_bss_get(dev, elems.mesh_id,
++ elems.mesh_id_len, elems.mesh_config, freq);
++ else
++#endif
++ bss = ieee80211_rx_bss_get(dev, mgmt->bssid, freq,
++ elems.ssid, elems.ssid_len);
++ if (!bss) {
++#ifdef CONFIG_MAC80211_MESH
++ if (elems.mesh_config)
++ bss = ieee80211_rx_mesh_bss_add(dev, elems.mesh_id,
++ elems.mesh_id_len, elems.mesh_config,
++ elems.mesh_config_len, freq);
++ else
++#endif
++ bss = ieee80211_rx_bss_add(dev, mgmt->bssid, freq,
++ elems.ssid, elems.ssid_len);
++ if (!bss)
++ return;
++ } else {
++#if 0
++ /* TODO: order by RSSI? */
++ spin_lock_bh(&local->sta_bss_lock);
++ list_move_tail(&bss->list, &local->sta_bss_list);
++ spin_unlock_bh(&local->sta_bss_lock);
++#endif
++ }
++
++ /* save the ERP value so that it is available at association time */
++ if (elems.erp_info && elems.erp_info_len >= 1) {
++ bss->erp_value = elems.erp_info[0];
++ bss->has_erp_value = 1;
++ }
++
++ if (elems.ht_cap_elem &&
++ (!bss->ht_ie || bss->ht_ie_len != elems.ht_cap_elem_len ||
++ memcmp(bss->ht_ie, elems.ht_cap_elem, elems.ht_cap_elem_len))) {
++ kfree(bss->ht_ie);
++ bss->ht_ie = kmalloc(elems.ht_cap_elem_len + 2, GFP_ATOMIC);
++ if (bss->ht_ie) {
++ memcpy(bss->ht_ie, elems.ht_cap_elem - 2,
++ elems.ht_cap_elem_len + 2);
++ bss->ht_ie_len = elems.ht_cap_elem_len + 2;
++ } else
++ bss->ht_ie_len = 0;
++ } else if (!elems.ht_cap_elem && bss->ht_ie) {
++ kfree(bss->ht_ie);
++ bss->ht_ie = NULL;
++ bss->ht_ie_len = 0;
++ }
++
++ bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
++ bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
++
++ bss->supp_rates_len = 0;
++ if (elems.supp_rates) {
++ clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
++ if (clen > elems.supp_rates_len)
++ clen = elems.supp_rates_len;
++ memcpy(&bss->supp_rates[bss->supp_rates_len], elems.supp_rates,
++ clen);
++ bss->supp_rates_len += clen;
++ }
++ if (elems.ext_supp_rates) {
++ clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
++ if (clen > elems.ext_supp_rates_len)
++ clen = elems.ext_supp_rates_len;
++ memcpy(&bss->supp_rates[bss->supp_rates_len],
++ elems.ext_supp_rates, clen);
++ bss->supp_rates_len += clen;
++ }
++
++ bss->band = rx_status->band;
++
++ bss->timestamp = beacon_timestamp;
++ bss->last_update = jiffies;
++ bss->rssi = rx_status->ssi;
++ bss->signal = rx_status->signal;
++ bss->noise = rx_status->noise;
++ if (!beacon && !bss->probe_resp)
++ bss->probe_resp = true;
++
++ /*
++ * In STA mode, the remaining parameters should not be overridden
++ * by beacons because they're not necessarily accurate there.
++ */
++ if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
++ bss->probe_resp && beacon) {
++ ieee80211_rx_bss_put(dev, bss);
++ return;
++ }
++
++ if (elems.wpa &&
++ (!bss->wpa_ie || bss->wpa_ie_len != elems.wpa_len ||
++ memcmp(bss->wpa_ie, elems.wpa, elems.wpa_len))) {
++ kfree(bss->wpa_ie);
++ bss->wpa_ie = kmalloc(elems.wpa_len + 2, GFP_ATOMIC);
++ if (bss->wpa_ie) {
++ memcpy(bss->wpa_ie, elems.wpa - 2, elems.wpa_len + 2);
++ bss->wpa_ie_len = elems.wpa_len + 2;
++ } else
++ bss->wpa_ie_len = 0;
++ } else if (!elems.wpa && bss->wpa_ie) {
++ kfree(bss->wpa_ie);
++ bss->wpa_ie = NULL;
++ bss->wpa_ie_len = 0;
++ }
++
++ if (elems.rsn &&
++ (!bss->rsn_ie || bss->rsn_ie_len != elems.rsn_len ||
++ memcmp(bss->rsn_ie, elems.rsn, elems.rsn_len))) {
++ kfree(bss->rsn_ie);
++ bss->rsn_ie = kmalloc(elems.rsn_len + 2, GFP_ATOMIC);
++ if (bss->rsn_ie) {
++ memcpy(bss->rsn_ie, elems.rsn - 2, elems.rsn_len + 2);
++ bss->rsn_ie_len = elems.rsn_len + 2;
++ } else
++ bss->rsn_ie_len = 0;
++ } else if (!elems.rsn && bss->rsn_ie) {
++ kfree(bss->rsn_ie);
++ bss->rsn_ie = NULL;
++ bss->rsn_ie_len = 0;
++ }
++
++ /*
++ * Cf.
++ * http://www.wipo.int/pctdb/en/wo.jsp?wo=2007047181&IA=WO2007047181&DISPLAY=DESC
++ *
++ * quoting:
++ *
++ * In particular, "Wi-Fi CERTIFIED for WMM - Support for Multimedia
++ * Applications with Quality of Service in Wi-Fi Networks," Wi- Fi
++ * Alliance (September 1, 2004) is incorporated by reference herein.
++ * The inclusion of the WMM Parameters in probe responses and
++ * association responses is mandatory for WMM enabled networks. The
++ * inclusion of the WMM Parameters in beacons, however, is optional.
++ */
++
++ if (elems.wmm_param &&
++ (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_param_len ||
++ memcmp(bss->wmm_ie, elems.wmm_param, elems.wmm_param_len))) {
++ kfree(bss->wmm_ie);
++ bss->wmm_ie = kmalloc(elems.wmm_param_len + 2, GFP_ATOMIC);
++ if (bss->wmm_ie) {
++ memcpy(bss->wmm_ie, elems.wmm_param - 2,
++ elems.wmm_param_len + 2);
++ bss->wmm_ie_len = elems.wmm_param_len + 2;
++ } else
++ bss->wmm_ie_len = 0;
++ } else if (elems.wmm_info &&
++ (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_info_len ||
++ memcmp(bss->wmm_ie, elems.wmm_info, elems.wmm_info_len))) {
++ /* As for certain AP's Fifth bit is not set in WMM IE in
++ * beacon frames.So while parsing the beacon frame the
++ * wmm_info structure is used instead of wmm_param.
++ * wmm_info structure was never used to set bss->wmm_ie.
++ * This code fixes this problem by copying the WME
++ * information from wmm_info to bss->wmm_ie and enabling
++ * n-band association.
++ */
++ kfree(bss->wmm_ie);
++ bss->wmm_ie = kmalloc(elems.wmm_info_len + 2, GFP_ATOMIC);
++ if (bss->wmm_ie) {
++ memcpy(bss->wmm_ie, elems.wmm_info - 2,
++ elems.wmm_info_len + 2);
++ bss->wmm_ie_len = elems.wmm_info_len + 2;
++ } else
++ bss->wmm_ie_len = 0;
++ } else if (!elems.wmm_param && !elems.wmm_info && bss->wmm_ie) {
++ kfree(bss->wmm_ie);
++ bss->wmm_ie = NULL;
++ bss->wmm_ie_len = 0;
++ }
++
++ /* check if we need to merge IBSS */
++ if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon &&
++ !local->sta_sw_scanning && !local->sta_hw_scanning &&
++ bss->capability & WLAN_CAPABILITY_IBSS &&
++ bss->freq == local->oper_channel->center_freq &&
++ elems.ssid_len == sdata->u.sta.ssid_len &&
++ memcmp(elems.ssid, sdata->u.sta.ssid, sdata->u.sta.ssid_len) == 0) {
++ if (rx_status->flag & RX_FLAG_TSFT) {
++ /* in order for correct IBSS merging we need mactime
++ *
++ * since mactime is defined as the time the first data
++ * symbol of the frame hits the PHY, and the timestamp
++ * of the beacon is defined as "the time that the data
++ * symbol containing the first bit of the timestamp is
++ * transmitted to the PHY plus the transmitting STAâs
++ * delays through its local PHY from the MAC-PHY
++ * interface to its interface with the WM"
++ * (802.11 11.1.2) - equals the time this bit arrives at
++ * the receiver - we have to take into account the
++ * offset between the two.
++ * e.g: at 1 MBit that means mactime is 192 usec earlier
++ * (=24 bytes * 8 usecs/byte) than the beacon timestamp.
++ */
++ int rate = local->hw.wiphy->bands[rx_status->band]->
++ bitrates[rx_status->rate_idx].bitrate;
++ rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate);
++ } else if (local && local->ops && local->ops->get_tsf)
++ /* second best option: get current TSF */
++ rx_timestamp = local->ops->get_tsf(local_to_hw(local));
++ else
++ /* can't merge without knowing the TSF */
++ rx_timestamp = -1LLU;
++#ifdef CONFIG_MAC80211_IBSS_DEBUG
++ printk(KERN_DEBUG "RX beacon SA=%s BSSID="
++ "%s TSF=0x%llx BCN=0x%llx diff=%lld @%lu\n",
++ print_mac(mac, mgmt->sa),
++ print_mac(mac2, mgmt->bssid),
++ (unsigned long long)rx_timestamp,
++ (unsigned long long)beacon_timestamp,
++ (unsigned long long)(rx_timestamp - beacon_timestamp),
++ jiffies);
++#endif /* CONFIG_MAC80211_IBSS_DEBUG */
++ if (beacon_timestamp > rx_timestamp) {
++#ifndef CONFIG_MAC80211_IBSS_DEBUG
++ if (net_ratelimit())
++#endif
++ printk(KERN_DEBUG "%s: beacon TSF higher than "
++ "local TSF - IBSS merge with BSSID %s\n",
++ dev->name, print_mac(mac, mgmt->bssid));
++ ieee80211_sta_join_ibss(dev, &sdata->u.sta, bss);
++ ieee80211_ibss_add_sta(dev, NULL,
++ mgmt->bssid, mgmt->sa);
++ }
++ }
++
++ ieee80211_rx_bss_put(dev, bss);
++}
++
++
++static void ieee80211_rx_mgmt_probe_resp(struct net_device *dev,
++ struct ieee80211_mgmt *mgmt,
++ size_t len,
++ struct ieee80211_rx_status *rx_status)
++{
++ ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 0);
++}
++
++
++static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
++ struct ieee80211_mgmt *mgmt,
++ size_t len,
++ struct ieee80211_rx_status *rx_status)
++{
++ struct ieee80211_sub_if_data *sdata;
++ struct ieee80211_if_sta *ifsta;
++ size_t baselen;
++ struct ieee802_11_elems elems;
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_conf *conf = &local->hw.conf;
++ u32 changed = 0;
++
++ ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 1);
++
++ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
++ return;
++ ifsta = &sdata->u.sta;
++
++ if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED) ||
++ memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0)
++ return;
++
++ /* Process beacon from the current BSS */
++ baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
++ if (baselen > len)
++ return;
++
++ ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
++
++ if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
++ ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
++ elems.wmm_param_len);
++ }
++
++ /* Do not send changes to driver if we are scanning. This removes
++ * requirement that driver's bss_info_changed function needs to be
++ * atomic. */
++ if (local->sta_sw_scanning || local->sta_hw_scanning)
++ return;
++
++ if (elems.erp_info && elems.erp_info_len >= 1)
++ changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]);
++ else {
++ u16 capab = le16_to_cpu(mgmt->u.beacon.capab_info);
++ changed |= ieee80211_handle_protect_preamb(sdata, false,
++ (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0);
++ }
++
++ if (elems.ht_cap_elem && elems.ht_info_elem &&
++ elems.wmm_param && conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
++ struct ieee80211_ht_bss_info bss_info;
++
++ ieee80211_ht_addt_info_ie_to_ht_bss_info(
++ (struct ieee80211_ht_addt_info *)
++ elems.ht_info_elem, &bss_info);
++ changed |= ieee80211_handle_ht(local, 1, &conf->ht_conf,
++ &bss_info);
++ }
++
++ ieee80211_bss_info_change_notify(sdata, changed);
++}
++
++
++static void ieee80211_rx_mgmt_probe_req(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta,
++ struct ieee80211_mgmt *mgmt,
++ size_t len,
++ struct ieee80211_rx_status *rx_status)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ int tx_last_beacon;
++ struct sk_buff *skb;
++ struct ieee80211_mgmt *resp;
++ u8 *pos, *end;
++ DECLARE_MAC_BUF(mac);
++#ifdef CONFIG_MAC80211_IBSS_DEBUG
++ DECLARE_MAC_BUF(mac2);
++ DECLARE_MAC_BUF(mac3);
++#endif
++
++ if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS ||
++ ifsta->state != IEEE80211_IBSS_JOINED ||
++ len < 24 + 2 || !ifsta->probe_resp)
++ return;
++
++ if (local->ops->tx_last_beacon)
++ tx_last_beacon = local->ops->tx_last_beacon(local_to_hw(local));
++ else
++ tx_last_beacon = 1;
++
++#ifdef CONFIG_MAC80211_IBSS_DEBUG
++ printk(KERN_DEBUG "%s: RX ProbeReq SA=%s DA=%s BSSID="
++ "%s (tx_last_beacon=%d)\n",
++ dev->name, print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da),
++ print_mac(mac3, mgmt->bssid), tx_last_beacon);
++#endif /* CONFIG_MAC80211_IBSS_DEBUG */
++
++ if (!tx_last_beacon)
++ return;
++
++ if (memcmp(mgmt->bssid, ifsta->bssid, ETH_ALEN) != 0 &&
++ memcmp(mgmt->bssid, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0)
++ return;
++
++ end = ((u8 *) mgmt) + len;
++ pos = mgmt->u.probe_req.variable;
++ if (pos[0] != WLAN_EID_SSID ||
++ pos + 2 + pos[1] > end) {
++ if (net_ratelimit()) {
++ printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq "
++ "from %s\n",
++ dev->name, print_mac(mac, mgmt->sa));
++ }
++ return;
++ }
++ if (pos[1] != 0 &&
++ (pos[1] != ifsta->ssid_len ||
++ memcmp(pos + 2, ifsta->ssid, ifsta->ssid_len) != 0)) {
++ /* Ignore ProbeReq for foreign SSID */
++ return;
++ }
++
++ /* Reply with ProbeResp */
++ skb = skb_copy(ifsta->probe_resp, GFP_KERNEL);
++ if (!skb)
++ return;
++
++ resp = (struct ieee80211_mgmt *) skb->data;
++ memcpy(resp->da, mgmt->sa, ETH_ALEN);
++#ifdef CONFIG_MAC80211_IBSS_DEBUG
++ printk(KERN_DEBUG "%s: Sending ProbeResp to %s\n",
++ dev->name, print_mac(mac, resp->da));
++#endif /* CONFIG_MAC80211_IBSS_DEBUG */
++ ieee80211_sta_tx(dev, skb, 0);
++}
++
++static void ieee80211_rx_mgmt_action(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta,
++ struct ieee80211_mgmt *mgmt,
++ size_t len,
++ struct ieee80211_rx_status *rx_status)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++ if (len < IEEE80211_MIN_ACTION_SIZE)
++ return;
++
++ switch (mgmt->u.action.category) {
++ case WLAN_CATEGORY_BACK:
++ switch (mgmt->u.action.u.addba_req.action_code) {
++ case WLAN_ACTION_ADDBA_REQ:
++ if (len < (IEEE80211_MIN_ACTION_SIZE +
++ sizeof(mgmt->u.action.u.addba_req)))
++ break;
++ ieee80211_sta_process_addba_request(dev, mgmt, len);
++ break;
++ case WLAN_ACTION_ADDBA_RESP:
++ if (len < (IEEE80211_MIN_ACTION_SIZE +
++ sizeof(mgmt->u.action.u.addba_resp)))
++ break;
++ ieee80211_sta_process_addba_resp(dev, mgmt, len);
++ break;
++ case WLAN_ACTION_DELBA:
++ if (len < (IEEE80211_MIN_ACTION_SIZE +
++ sizeof(mgmt->u.action.u.delba)))
++ break;
++ ieee80211_sta_process_delba(dev, mgmt, len);
++ break;
++ default:
++ if (net_ratelimit())
++ printk(KERN_DEBUG "%s: Rx unknown A-MPDU action\n",
++ dev->name);
++ break;
++ }
++ break;
++ case PLINK_CATEGORY:
++ if (ieee80211_vif_is_mesh(&sdata->vif))
++ mesh_rx_plink_frame(dev, mgmt, len, rx_status);
++ break;
++ case MESH_PATH_SEL_CATEGORY:
++ if (ieee80211_vif_is_mesh(&sdata->vif))
++ mesh_rx_path_sel_frame(dev, mgmt, len);
++ break;
++ default:
++ if (net_ratelimit())
++ printk(KERN_DEBUG "%s: Rx unknown action frame - "
++ "category=%d\n", dev->name, mgmt->u.action.category);
++ break;
++ }
++}
++
++void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb,
++ struct ieee80211_rx_status *rx_status)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sub_if_data *sdata;
++ struct ieee80211_if_sta *ifsta;
++ struct ieee80211_mgmt *mgmt;
++ u16 fc;
++
++ if (skb->len < 24)
++ goto fail;
++
++ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ ifsta = &sdata->u.sta;
++
++ mgmt = (struct ieee80211_mgmt *) skb->data;
++ fc = le16_to_cpu(mgmt->frame_control);
++
++ switch (fc & IEEE80211_FCTL_STYPE) {
++ case IEEE80211_STYPE_PROBE_REQ:
++ case IEEE80211_STYPE_PROBE_RESP:
++ case IEEE80211_STYPE_BEACON:
++ case IEEE80211_STYPE_ACTION:
++ memcpy(skb->cb, rx_status, sizeof(*rx_status));
++ case IEEE80211_STYPE_AUTH:
++ case IEEE80211_STYPE_ASSOC_RESP:
++ case IEEE80211_STYPE_REASSOC_RESP:
++ case IEEE80211_STYPE_DEAUTH:
++ case IEEE80211_STYPE_DISASSOC:
++ skb_queue_tail(&ifsta->skb_queue, skb);
++ queue_work(local->hw.workqueue, &ifsta->work);
++ return;
++ default:
++ printk(KERN_DEBUG "%s: received unknown management frame - "
++ "stype=%d\n", dev->name,
++ (fc & IEEE80211_FCTL_STYPE) >> 4);
++ break;
++ }
++
++ fail:
++ kfree_skb(skb);
++}
++
++
++static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev,
++ struct sk_buff *skb)
++{
++ struct ieee80211_rx_status *rx_status;
++ struct ieee80211_sub_if_data *sdata;
++ struct ieee80211_if_sta *ifsta;
++ struct ieee80211_mgmt *mgmt;
++ u16 fc;
++
++ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ ifsta = &sdata->u.sta;
++
++ rx_status = (struct ieee80211_rx_status *) skb->cb;
++ mgmt = (struct ieee80211_mgmt *) skb->data;
++ fc = le16_to_cpu(mgmt->frame_control);
++
++ switch (fc & IEEE80211_FCTL_STYPE) {
++ case IEEE80211_STYPE_PROBE_REQ:
++ ieee80211_rx_mgmt_probe_req(dev, ifsta, mgmt, skb->len,
++ rx_status);
++ break;
++ case IEEE80211_STYPE_PROBE_RESP:
++ ieee80211_rx_mgmt_probe_resp(dev, mgmt, skb->len, rx_status);
++ break;
++ case IEEE80211_STYPE_BEACON:
++ ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, rx_status);
++ break;
++ case IEEE80211_STYPE_AUTH:
++ ieee80211_rx_mgmt_auth(dev, ifsta, mgmt, skb->len);
++ break;
++ case IEEE80211_STYPE_ASSOC_RESP:
++ ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 0);
++ break;
++ case IEEE80211_STYPE_REASSOC_RESP:
++ ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 1);
++ break;
++ case IEEE80211_STYPE_DEAUTH:
++ ieee80211_rx_mgmt_deauth(dev, ifsta, mgmt, skb->len);
++ break;
++ case IEEE80211_STYPE_DISASSOC:
++ ieee80211_rx_mgmt_disassoc(dev, ifsta, mgmt, skb->len);
++ break;
++ case IEEE80211_STYPE_ACTION:
++ ieee80211_rx_mgmt_action(dev, ifsta, mgmt, skb->len, rx_status);
++ break;
++ }
++
++ kfree_skb(skb);
++}
++
++
++ieee80211_rx_result
++ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb,
++ struct ieee80211_rx_status *rx_status)
++{
++ struct ieee80211_mgmt *mgmt;
++ u16 fc;
++
++ if (skb->len < 2)
++ return RX_DROP_UNUSABLE;
++
++ mgmt = (struct ieee80211_mgmt *) skb->data;
++ fc = le16_to_cpu(mgmt->frame_control);
++
++ if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL)
++ return RX_CONTINUE;
++
++ if (skb->len < 24)
++ return RX_DROP_MONITOR;
++
++ if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
++ if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP) {
++ ieee80211_rx_mgmt_probe_resp(dev, mgmt,
++ skb->len, rx_status);
++ dev_kfree_skb(skb);
++ return RX_QUEUED;
++ } else if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) {
++ ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len,
++ rx_status);
++ dev_kfree_skb(skb);
++ return RX_QUEUED;
++ }
++ }
++ return RX_CONTINUE;
++}
++
++
++static int ieee80211_sta_active_ibss(struct net_device *dev)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ int active = 0;
++ struct sta_info *sta;
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++ rcu_read_lock();
++
++ list_for_each_entry_rcu(sta, &local->sta_list, list) {
++ if (sta->sdata == sdata &&
++ time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL,
++ jiffies)) {
++ active++;
++ break;
++ }
++ }
++
++ rcu_read_unlock();
++
++ return active;
++}
++
++
++static void ieee80211_sta_expire(struct net_device *dev, unsigned long exp_time)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct sta_info *sta, *tmp;
++ LIST_HEAD(tmp_list);
++ DECLARE_MAC_BUF(mac);
++ unsigned long flags;
++
++ spin_lock_irqsave(&local->sta_lock, flags);
++ list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
++ if (time_after(jiffies, sta->last_rx + exp_time)) {
++ printk(KERN_DEBUG "%s: expiring inactive STA %s\n",
++ dev->name, print_mac(mac, sta->addr));
++ __sta_info_unlink(&sta);
++ if (sta)
++ list_add(&sta->list, &tmp_list);
++ }
++ spin_unlock_irqrestore(&local->sta_lock, flags);
++
++ list_for_each_entry_safe(sta, tmp, &tmp_list, list)
++ sta_info_destroy(sta);
++}
++
++
++static void ieee80211_sta_merge_ibss(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta)
++{
++ mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
++
++ ieee80211_sta_expire(dev, IEEE80211_IBSS_INACTIVITY_LIMIT);
++ if (ieee80211_sta_active_ibss(dev))
++ return;
++
++ printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other "
++ "IBSS networks with same SSID (merge)\n", dev->name);
++ ieee80211_sta_req_scan(dev, ifsta->ssid, ifsta->ssid_len);
++}
++
++
++#ifdef CONFIG_MAC80211_MESH
++static void ieee80211_mesh_housekeeping(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ bool free_plinks;
++
++ ieee80211_sta_expire(dev, IEEE80211_MESH_PEER_INACTIVITY_LIMIT);
++ mesh_path_expire(dev);
++
++ free_plinks = mesh_plink_availables(sdata);
++ if (free_plinks != sdata->u.sta.accepting_plinks)
++ ieee80211_if_config_beacon(dev);
++
++ mod_timer(&ifsta->timer, jiffies +
++ IEEE80211_MESH_HOUSEKEEPING_INTERVAL);
++}
++
++
++void ieee80211_start_mesh(struct net_device *dev)
++{
++ struct ieee80211_if_sta *ifsta;
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ ifsta = &sdata->u.sta;
++ ifsta->state = IEEE80211_MESH_UP;
++ ieee80211_sta_timer((unsigned long)sdata);
++}
++#endif
++
++
++void ieee80211_sta_timer(unsigned long data)
++{
++ struct ieee80211_sub_if_data *sdata =
++ (struct ieee80211_sub_if_data *) data;
++ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++ struct ieee80211_local *local = wdev_priv(&sdata->wdev);
++
++ set_bit(IEEE80211_STA_REQ_RUN, &ifsta->request);
++ queue_work(local->hw.workqueue, &ifsta->work);
++}
++
++void ieee80211_sta_work(struct work_struct *work)
++{
++ struct ieee80211_sub_if_data *sdata =
++ container_of(work, struct ieee80211_sub_if_data, u.sta.work);
++ struct net_device *dev = sdata->dev;
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_if_sta *ifsta;
++ struct sk_buff *skb;
++
++ if (!netif_running(dev))
++ return;
++
++ if (local->sta_sw_scanning || local->sta_hw_scanning)
++ return;
++
++ if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
++ sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
++ sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) {
++ printk(KERN_DEBUG "%s: ieee80211_sta_work: non-STA interface "
++ "(type=%d)\n", dev->name, sdata->vif.type);
++ return;
++ }
++ ifsta = &sdata->u.sta;
++
++ while ((skb = skb_dequeue(&ifsta->skb_queue)))
++ ieee80211_sta_rx_queued_mgmt(dev, skb);
++
++#ifdef CONFIG_MAC80211_MESH
++ if (ifsta->preq_queue_len &&
++ time_after(jiffies,
++ ifsta->last_preq + msecs_to_jiffies(ifsta->mshcfg.dot11MeshHWMPpreqMinInterval)))
++ mesh_path_start_discovery(dev);
++#endif
++
++ if (ifsta->state != IEEE80211_AUTHENTICATE &&
++ ifsta->state != IEEE80211_ASSOCIATE &&
++ test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) {
++ if (ifsta->scan_ssid_len)
++ ieee80211_sta_start_scan(dev, ifsta->scan_ssid, ifsta->scan_ssid_len);
++ else
++ ieee80211_sta_start_scan(dev, NULL, 0);
++ return;
++ }
++
++ if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request)) {
++ if (ieee80211_sta_config_auth(dev, ifsta))
++ return;
++ clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request);
++ } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request))
++ return;
++
++ switch (ifsta->state) {
++ case IEEE80211_DISABLED:
++ break;
++ case IEEE80211_AUTHENTICATE:
++ ieee80211_authenticate(dev, ifsta);
++ break;
++ case IEEE80211_ASSOCIATE:
++ ieee80211_associate(dev, ifsta);
++ break;
++ case IEEE80211_ASSOCIATED:
++ ieee80211_associated(dev, ifsta);
++ break;
++ case IEEE80211_IBSS_SEARCH:
++ ieee80211_sta_find_ibss(dev, ifsta);
++ break;
++ case IEEE80211_IBSS_JOINED:
++ ieee80211_sta_merge_ibss(dev, ifsta);
++ break;
++#ifdef CONFIG_MAC80211_MESH
++ case IEEE80211_MESH_UP:
++ ieee80211_mesh_housekeeping(dev, ifsta);
++ break;
++#endif
++ default:
++ printk(KERN_DEBUG "ieee80211_sta_work: Unknown state %d\n",
++ ifsta->state);
++ break;
++ }
++
++ if (ieee80211_privacy_mismatch(dev, ifsta)) {
++ printk(KERN_DEBUG "%s: privacy configuration mismatch and "
++ "mixed-cell disabled - disassociate\n", dev->name);
++
++ ieee80211_send_disassoc(dev, ifsta, WLAN_REASON_UNSPECIFIED);
++ ieee80211_set_disassoc(dev, ifsta, 0);
++ }
++}
++
++
++static void ieee80211_sta_reset_auth(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++ if (local->ops->reset_tsf) {
++ /* Reset own TSF to allow time synchronization work. */
++ local->ops->reset_tsf(local_to_hw(local));
++ }
++
++ ifsta->wmm_last_param_set = -1; /* allow any WMM update */
++
++
++ if (ifsta->auth_algs & IEEE80211_AUTH_ALG_OPEN)
++ ifsta->auth_alg = WLAN_AUTH_OPEN;
++ else if (ifsta->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
++ ifsta->auth_alg = WLAN_AUTH_SHARED_KEY;
++ else if (ifsta->auth_algs & IEEE80211_AUTH_ALG_LEAP)
++ ifsta->auth_alg = WLAN_AUTH_LEAP;
++ else
++ ifsta->auth_alg = WLAN_AUTH_OPEN;
++ printk(KERN_DEBUG "%s: Initial auth_alg=%d\n", dev->name,
++ ifsta->auth_alg);
++ ifsta->auth_transaction = -1;
++ ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
++ ifsta->auth_tries = ifsta->assoc_tries = 0;
++ netif_carrier_off(dev);
++}
++
++
++void ieee80211_sta_req_auth(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++ if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
++ return;
++
++ if ((ifsta->flags & (IEEE80211_STA_BSSID_SET |
++ IEEE80211_STA_AUTO_BSSID_SEL)) &&
++ (ifsta->flags & (IEEE80211_STA_SSID_SET |
++ IEEE80211_STA_AUTO_SSID_SEL))) {
++ set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
++ queue_work(local->hw.workqueue, &ifsta->work);
++ }
++}
++
++static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta,
++ const char *ssid, int ssid_len)
++{
++ int tmp, hidden_ssid;
++
++ if (ssid_len == ifsta->ssid_len &&
++ !memcmp(ifsta->ssid, ssid, ssid_len))
++ return 1;
++
++ if (ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL)
++ return 0;
++
++ hidden_ssid = 1;
++ tmp = ssid_len;
++ while (tmp--) {
++ if (ssid[tmp] != '\0') {
++ hidden_ssid = 0;
++ break;
++ }
++ }
++
++ if (hidden_ssid && ifsta->ssid_len == ssid_len)
++ return 1;
++
++ if (ssid_len == 1 && ssid[0] == ' ')
++ return 1;
++
++ return 0;
++}
++
++static int ieee80211_sta_config_auth(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_sta_bss *bss, *selected = NULL;
++ int top_rssi = 0, freq;
++
++ if (!(ifsta->flags & (IEEE80211_STA_AUTO_SSID_SEL |
++ IEEE80211_STA_AUTO_BSSID_SEL | IEEE80211_STA_AUTO_CHANNEL_SEL))) {
++ ifsta->state = IEEE80211_AUTHENTICATE;
++ ieee80211_sta_reset_auth(dev, ifsta);
++ return 0;
++ }
++
++ spin_lock_bh(&local->sta_bss_lock);
++ freq = local->oper_channel->center_freq;
++ list_for_each_entry(bss, &local->sta_bss_list, list) {
++ if (!(bss->capability & WLAN_CAPABILITY_ESS))
++ continue;
++
++ if (!!(bss->capability & WLAN_CAPABILITY_PRIVACY) ^
++ !!sdata->default_key)
++ continue;
++
++ if (!(ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) &&
++ bss->freq != freq)
++ continue;
++
++ if (!(ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) &&
++ memcmp(bss->bssid, ifsta->bssid, ETH_ALEN))
++ continue;
++
++ if (!(ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) &&
++ !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len))
++ continue;
++
++ if (!selected || top_rssi < bss->rssi) {
++ selected = bss;
++ top_rssi = bss->rssi;
++ }
++ }
++ if (selected)
++ atomic_inc(&selected->users);
++ spin_unlock_bh(&local->sta_bss_lock);
++
++ if (selected) {
++ ieee80211_set_freq(local, selected->freq);
++ if (!(ifsta->flags & IEEE80211_STA_SSID_SET))
++ ieee80211_sta_set_ssid(dev, selected->ssid,
++ selected->ssid_len);
++ ieee80211_sta_set_bssid(dev, selected->bssid);
++ ieee80211_sta_def_wmm_params(dev, selected, 0);
++ ieee80211_rx_bss_put(dev, selected);
++ ifsta->state = IEEE80211_AUTHENTICATE;
++ ieee80211_sta_reset_auth(dev, ifsta);
++ return 0;
++ } else {
++ if (ifsta->state != IEEE80211_AUTHENTICATE) {
++ if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL)
++ ieee80211_sta_start_scan(dev, NULL, 0);
++ else
++ ieee80211_sta_start_scan(dev, ifsta->ssid,
++ ifsta->ssid_len);
++ ifsta->state = IEEE80211_AUTHENTICATE;
++ set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
++ } else
++ ifsta->state = IEEE80211_DISABLED;
++ }
++ return -1;
++}
++
++
++static int ieee80211_sta_create_ibss(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sta_bss *bss;
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_supported_band *sband;
++ u8 bssid[ETH_ALEN], *pos;
++ int i;
++ DECLARE_MAC_BUF(mac);
++
++#if 0
++ /* Easier testing, use fixed BSSID. */
++ memset(bssid, 0xfe, ETH_ALEN);
++#else
++ /* Generate random, not broadcast, locally administered BSSID. Mix in
++ * own MAC address to make sure that devices that do not have proper
++ * random number generator get different BSSID. */
++ get_random_bytes(bssid, ETH_ALEN);
++ for (i = 0; i < ETH_ALEN; i++)
++ bssid[i] ^= dev->dev_addr[i];
++ bssid[0] &= ~0x01;
++ bssid[0] |= 0x02;
++#endif
++
++ printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n",
++ dev->name, print_mac(mac, bssid));
++
++ bss = ieee80211_rx_bss_add(dev, bssid,
++ local->hw.conf.channel->center_freq,
++ sdata->u.sta.ssid, sdata->u.sta.ssid_len);
++ if (!bss)
++ return -ENOMEM;
++
++ bss->band = local->hw.conf.channel->band;
++ sband = local->hw.wiphy->bands[bss->band];
++
++ if (local->hw.conf.beacon_int == 0)
++ local->hw.conf.beacon_int = 10000;
++ bss->beacon_int = local->hw.conf.beacon_int;
++ bss->last_update = jiffies;
++ bss->capability = WLAN_CAPABILITY_IBSS;
++ if (sdata->default_key) {
++ bss->capability |= WLAN_CAPABILITY_PRIVACY;
++ } else
++ sdata->drop_unencrypted = 0;
++ bss->supp_rates_len = sband->n_bitrates;
++ pos = bss->supp_rates;
++ for (i = 0; i < sband->n_bitrates; i++) {
++ int rate = sband->bitrates[i].bitrate;
++ *pos++ = (u8) (rate / 5);
++ }
++
++ return ieee80211_sta_join_ibss(dev, ifsta, bss);
++}
++
++
++static int ieee80211_sta_find_ibss(struct net_device *dev,
++ struct ieee80211_if_sta *ifsta)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sta_bss *bss;
++ int found = 0;
++ u8 bssid[ETH_ALEN];
++ int active_ibss;
++ DECLARE_MAC_BUF(mac);
++ DECLARE_MAC_BUF(mac2);
++
++ if (ifsta->ssid_len == 0)
++ return -EINVAL;
++
++ active_ibss = ieee80211_sta_active_ibss(dev);
++#ifdef CONFIG_MAC80211_IBSS_DEBUG
++ printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n",
++ dev->name, active_ibss);
++#endif /* CONFIG_MAC80211_IBSS_DEBUG */
++ spin_lock_bh(&local->sta_bss_lock);
++ list_for_each_entry(bss, &local->sta_bss_list, list) {
++ if (ifsta->ssid_len != bss->ssid_len ||
++ memcmp(ifsta->ssid, bss->ssid, bss->ssid_len) != 0
++ || !(bss->capability & WLAN_CAPABILITY_IBSS))
++ continue;
++#ifdef CONFIG_MAC80211_IBSS_DEBUG
++ printk(KERN_DEBUG " bssid=%s found\n",
++ print_mac(mac, bss->bssid));
++#endif /* CONFIG_MAC80211_IBSS_DEBUG */
++ memcpy(bssid, bss->bssid, ETH_ALEN);
++ found = 1;
++ if (active_ibss || memcmp(bssid, ifsta->bssid, ETH_ALEN) != 0)
++ break;
++ }
++ spin_unlock_bh(&local->sta_bss_lock);
++
++#ifdef CONFIG_MAC80211_IBSS_DEBUG
++ printk(KERN_DEBUG " sta_find_ibss: selected %s current "
++ "%s\n", print_mac(mac, bssid), print_mac(mac2, ifsta->bssid));
++#endif /* CONFIG_MAC80211_IBSS_DEBUG */
++ if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 &&
++ (bss = ieee80211_rx_bss_get(dev, bssid,
++ local->hw.conf.channel->center_freq,
++ ifsta->ssid, ifsta->ssid_len))) {
++ printk(KERN_DEBUG "%s: Selected IBSS BSSID %s"
++ " based on configured SSID\n",
++ dev->name, print_mac(mac, bssid));
++ return ieee80211_sta_join_ibss(dev, ifsta, bss);
++ }
++#ifdef CONFIG_MAC80211_IBSS_DEBUG
++ printk(KERN_DEBUG " did not try to join ibss\n");
++#endif /* CONFIG_MAC80211_IBSS_DEBUG */
++
++ /* Selected IBSS not found in current scan results - try to scan */
++ if (ifsta->state == IEEE80211_IBSS_JOINED &&
++ !ieee80211_sta_active_ibss(dev)) {
++ mod_timer(&ifsta->timer, jiffies +
++ IEEE80211_IBSS_MERGE_INTERVAL);
++ } else if (time_after(jiffies, local->last_scan_completed +
++ IEEE80211_SCAN_INTERVAL)) {
++ printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to "
++ "join\n", dev->name);
++ return ieee80211_sta_req_scan(dev, ifsta->ssid,
++ ifsta->ssid_len);
++ } else if (ifsta->state != IEEE80211_IBSS_JOINED) {
++ int interval = IEEE80211_SCAN_INTERVAL;
++
++ if (time_after(jiffies, ifsta->ibss_join_req +
++ IEEE80211_IBSS_JOIN_TIMEOUT)) {
++ if ((ifsta->flags & IEEE80211_STA_CREATE_IBSS) &&
++ (!(local->oper_channel->flags &
++ IEEE80211_CHAN_NO_IBSS)))
++ return ieee80211_sta_create_ibss(dev, ifsta);
++ if (ifsta->flags & IEEE80211_STA_CREATE_IBSS) {
++ printk(KERN_DEBUG "%s: IBSS not allowed on"
++ " %d MHz\n", dev->name,
++ local->hw.conf.channel->center_freq);
++ }
++
++ /* No IBSS found - decrease scan interval and continue
++ * scanning. */
++ interval = IEEE80211_SCAN_INTERVAL_SLOW;
++ }
++
++ ifsta->state = IEEE80211_IBSS_SEARCH;
++ mod_timer(&ifsta->timer, jiffies + interval);
++ return 0;
++ }
++
++ return 0;
++}
++
++
++int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_if_sta *ifsta;
++
++ if (len > IEEE80211_MAX_SSID_LEN)
++ return -EINVAL;
++
++ ifsta = &sdata->u.sta;
++
++ if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0)
++ ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
++ memcpy(ifsta->ssid, ssid, len);
++ memset(ifsta->ssid + len, 0, IEEE80211_MAX_SSID_LEN - len);
++ ifsta->ssid_len = len;
++
++ if (len)
++ ifsta->flags |= IEEE80211_STA_SSID_SET;
++ else
++ ifsta->flags &= ~IEEE80211_STA_SSID_SET;
++ if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
++ !(ifsta->flags & IEEE80211_STA_BSSID_SET)) {
++ ifsta->ibss_join_req = jiffies;
++ ifsta->state = IEEE80211_IBSS_SEARCH;
++ return ieee80211_sta_find_ibss(dev, ifsta);
++ }
++ return 0;
++}
++
++
++int ieee80211_sta_get_ssid(struct net_device *dev, char *ssid, size_t *len)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++ memcpy(ssid, ifsta->ssid, ifsta->ssid_len);
++ *len = ifsta->ssid_len;
++ return 0;
++}
++
++
++int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid)
++{
++ struct ieee80211_sub_if_data *sdata;
++ struct ieee80211_if_sta *ifsta;
++ int res;
++
++ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ ifsta = &sdata->u.sta;
++
++ if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) {
++ memcpy(ifsta->bssid, bssid, ETH_ALEN);
++ res = ieee80211_if_config(dev);
++ if (res) {
++ printk(KERN_DEBUG "%s: Failed to config new BSSID to "
++ "the low-level driver\n", dev->name);
++ return res;
++ }
++ }
++
++ if (is_valid_ether_addr(bssid))
++ ifsta->flags |= IEEE80211_STA_BSSID_SET;
++ else
++ ifsta->flags &= ~IEEE80211_STA_BSSID_SET;
++
++ return 0;
++}
++
++
++static void ieee80211_send_nullfunc(struct ieee80211_local *local,
++ struct ieee80211_sub_if_data *sdata,
++ int powersave)
++{
++ struct sk_buff *skb;
++ struct ieee80211_hdr *nullfunc;
++ u16 fc;
++
++ skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24);
++ if (!skb) {
++ printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc "
++ "frame\n", sdata->dev->name);
++ return;
++ }
++ skb_reserve(skb, local->hw.extra_tx_headroom);
++
++ nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24);
++ memset(nullfunc, 0, 24);
++ fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC |
++ IEEE80211_FCTL_TODS;
++ if (powersave)
++ fc |= IEEE80211_FCTL_PM;
++ nullfunc->frame_control = cpu_to_le16(fc);
++ memcpy(nullfunc->addr1, sdata->u.sta.bssid, ETH_ALEN);
++ memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN);
++ memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN);
++
++ ieee80211_sta_tx(sdata->dev, skb, 0);
++}
++
++
++static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
++{
++ if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
++ ieee80211_vif_is_mesh(&sdata->vif))
++ ieee80211_sta_timer((unsigned long)sdata);
++}
++
++void ieee80211_scan_completed(struct ieee80211_hw *hw)
++{
++ struct ieee80211_local *local = hw_to_local(hw);
++ struct net_device *dev = local->scan_dev;
++ struct ieee80211_sub_if_data *sdata;
++ union iwreq_data wrqu;
++
++ local->last_scan_completed = jiffies;
++ memset(&wrqu, 0, sizeof(wrqu));
++ wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
++
++ if (local->sta_hw_scanning) {
++ local->sta_hw_scanning = 0;
++ if (ieee80211_hw_config(local))
++ printk(KERN_DEBUG "%s: failed to restore operational "
++ "channel after scan\n", dev->name);
++ /* Restart STA timer for HW scan case */
++ rcu_read_lock();
++ list_for_each_entry_rcu(sdata, &local->interfaces, list)
++ ieee80211_restart_sta_timer(sdata);
++ rcu_read_unlock();
++
++ goto done;
++ }
++
++ local->sta_sw_scanning = 0;
++ if (ieee80211_hw_config(local))
++ printk(KERN_DEBUG "%s: failed to restore operational "
++ "channel after scan\n", dev->name);
++
++
++ netif_tx_lock_bh(local->mdev);
++ local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC;
++ local->ops->configure_filter(local_to_hw(local),
++ FIF_BCN_PRBRESP_PROMISC,
++ &local->filter_flags,
++ local->mdev->mc_count,
++ local->mdev->mc_list);
++
++ netif_tx_unlock_bh(local->mdev);
++
++ rcu_read_lock();
++ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
++
++ /* No need to wake the master device. */
++ if (sdata->dev == local->mdev)
++ continue;
++
++ /* Tell AP we're back */
++ if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
++ sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED)
++ ieee80211_send_nullfunc(local, sdata, 0);
++
++ ieee80211_restart_sta_timer(sdata);
++
++ netif_wake_queue(sdata->dev);
++ }
++ rcu_read_unlock();
++
++done:
++ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
++ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++ if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) ||
++ (!ifsta->state == IEEE80211_IBSS_JOINED &&
++ !ieee80211_sta_active_ibss(dev)))
++ ieee80211_sta_find_ibss(dev, ifsta);
++ }
++}
++EXPORT_SYMBOL(ieee80211_scan_completed);
++
++void ieee80211_sta_scan_work(struct work_struct *work)
++{
++ struct ieee80211_local *local =
++ container_of(work, struct ieee80211_local, scan_work.work);
++ struct net_device *dev = local->scan_dev;
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_supported_band *sband;
++ struct ieee80211_channel *chan;
++ int skip;
++ unsigned long next_delay = 0;
++
++ if (!local->sta_sw_scanning)
++ return;
++
++ switch (local->scan_state) {
++ case SCAN_SET_CHANNEL:
++ /*
++ * Get current scan band. scan_band may be IEEE80211_NUM_BANDS
++ * after we successfully scanned the last channel of the last
++ * band (and the last band is supported by the hw)
++ */
++ if (local->scan_band < IEEE80211_NUM_BANDS)
++ sband = local->hw.wiphy->bands[local->scan_band];
++ else
++ sband = NULL;
++
++ /*
++ * If we are at an unsupported band and have more bands
++ * left to scan, advance to the next supported one.
++ */
++ while (!sband && local->scan_band < IEEE80211_NUM_BANDS - 1) {
++ local->scan_band++;
++ sband = local->hw.wiphy->bands[local->scan_band];
++ local->scan_channel_idx = 0;
++ }
++
++ /* if no more bands/channels left, complete scan */
++ if (!sband || local->scan_channel_idx >= sband->n_channels) {
++ ieee80211_scan_completed(local_to_hw(local));
++ return;
++ }
++ skip = 0;
++ chan = &sband->channels[local->scan_channel_idx];
++
++ if (chan->flags & IEEE80211_CHAN_DISABLED ||
++ (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
++ chan->flags & IEEE80211_CHAN_NO_IBSS))
++ skip = 1;
++
++ if (!skip) {
++ local->scan_channel = chan;
++ if (ieee80211_hw_config(local)) {
++ printk(KERN_DEBUG "%s: failed to set freq to "
++ "%d MHz for scan\n", dev->name,
++ chan->center_freq);
++ skip = 1;
++ }
++ }
++
++ /* advance state machine to next channel/band */
++ local->scan_channel_idx++;
++ if (local->scan_channel_idx >= sband->n_channels) {
++ /*
++ * scan_band may end up == IEEE80211_NUM_BANDS, but
++ * we'll catch that case above and complete the scan
++ * if that is the case.
++ */
++ local->scan_band++;
++ local->scan_channel_idx = 0;
++ }
++
++ if (skip)
++ break;
++
++ next_delay = IEEE80211_PROBE_DELAY +
++ usecs_to_jiffies(local->hw.channel_change_time);
++ local->scan_state = SCAN_SEND_PROBE;
++ break;
++ case SCAN_SEND_PROBE:
++ next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
++ local->scan_state = SCAN_SET_CHANNEL;
++
++ if (local->scan_channel->flags & IEEE80211_CHAN_PASSIVE_SCAN)
++ break;
++ ieee80211_send_probe_req(dev, NULL, local->scan_ssid,
++ local->scan_ssid_len);
++ next_delay = IEEE80211_CHANNEL_TIME;
++ break;
++ }
++
++ if (local->sta_sw_scanning)
++ queue_delayed_work(local->hw.workqueue, &local->scan_work,
++ next_delay);
++}
++
++
++static int ieee80211_sta_start_scan(struct net_device *dev,
++ u8 *ssid, size_t ssid_len)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sub_if_data *sdata;
++
++ if (ssid_len > IEEE80211_MAX_SSID_LEN)
++ return -EINVAL;
++
++ /* MLME-SCAN.request (page 118) page 144 (11.1.3.1)
++ * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS
++ * BSSID: MACAddress
++ * SSID
++ * ScanType: ACTIVE, PASSIVE
++ * ProbeDelay: delay (in microseconds) to be used prior to transmitting
++ * a Probe frame during active scanning
++ * ChannelList
++ * MinChannelTime (>= ProbeDelay), in TU
++ * MaxChannelTime: (>= MinChannelTime), in TU
++ */
++
++ /* MLME-SCAN.confirm
++ * BSSDescriptionSet
++ * ResultCode: SUCCESS, INVALID_PARAMETERS
++ */
++
++ if (local->sta_sw_scanning || local->sta_hw_scanning) {
++ if (local->scan_dev == dev)
++ return 0;
++ return -EBUSY;
++ }
++
++ if (local->ops->hw_scan) {
++ int rc = local->ops->hw_scan(local_to_hw(local),
++ ssid, ssid_len);
++ if (!rc) {
++ local->sta_hw_scanning = 1;
++ local->scan_dev = dev;
++ }
++ return rc;
++ }
++
++ local->sta_sw_scanning = 1;
++
++ rcu_read_lock();
++ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
++
++ /* Don't stop the master interface, otherwise we can't transmit
++ * probes! */
++ if (sdata->dev == local->mdev)
++ continue;
++
++ netif_stop_queue(sdata->dev);
++ if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
++ (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED))
++ ieee80211_send_nullfunc(local, sdata, 1);
++ }
++ rcu_read_unlock();
++
++ if (ssid) {
++ local->scan_ssid_len = ssid_len;
++ memcpy(local->scan_ssid, ssid, ssid_len);
++ } else
++ local->scan_ssid_len = 0;
++ local->scan_state = SCAN_SET_CHANNEL;
++ local->scan_channel_idx = 0;
++ local->scan_band = IEEE80211_BAND_2GHZ;
++ local->scan_dev = dev;
++
++ netif_tx_lock_bh(local->mdev);
++ local->filter_flags |= FIF_BCN_PRBRESP_PROMISC;
++ local->ops->configure_filter(local_to_hw(local),
++ FIF_BCN_PRBRESP_PROMISC,
++ &local->filter_flags,
++ local->mdev->mc_count,
++ local->mdev->mc_list);
++ netif_tx_unlock_bh(local->mdev);
++
++ /* TODO: start scan as soon as all nullfunc frames are ACKed */
++ queue_delayed_work(local->hw.workqueue, &local->scan_work,
++ IEEE80211_CHANNEL_TIME);
++
++ return 0;
++}
++
++
++int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++ if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
++ return ieee80211_sta_start_scan(dev, ssid, ssid_len);
++
++ if (local->sta_sw_scanning || local->sta_hw_scanning) {
++ if (local->scan_dev == dev)
++ return 0;
++ return -EBUSY;
++ }
++
++ ifsta->scan_ssid_len = ssid_len;
++ if (ssid_len)
++ memcpy(ifsta->scan_ssid, ssid, ssid_len);
++ set_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request);
++ queue_work(local->hw.workqueue, &ifsta->work);
++ return 0;
++}
++
++static char *
++ieee80211_sta_scan_result(struct net_device *dev,
++ struct ieee80211_sta_bss *bss,
++ char *current_ev, char *end_buf)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct iw_event iwe;
++
++ if (time_after(jiffies,
++ bss->last_update + IEEE80211_SCAN_RESULT_EXPIRE))
++ return current_ev;
++
++ memset(&iwe, 0, sizeof(iwe));
++ iwe.cmd = SIOCGIWAP;
++ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
++ memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN);
++ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
++ IW_EV_ADDR_LEN);
++
++ memset(&iwe, 0, sizeof(iwe));
++ iwe.cmd = SIOCGIWESSID;
++ if (bss_mesh_cfg(bss)) {
++ iwe.u.data.length = bss_mesh_id_len(bss);
++ iwe.u.data.flags = 1;
++ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
++ bss_mesh_id(bss));
++ } else {
++ iwe.u.data.length = bss->ssid_len;
++ iwe.u.data.flags = 1;
++ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
++ bss->ssid);
++ }
++
++ if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)
++ || bss_mesh_cfg(bss)) {
++ memset(&iwe, 0, sizeof(iwe));
++ iwe.cmd = SIOCGIWMODE;
++ if (bss_mesh_cfg(bss))
++ iwe.u.mode = IW_MODE_MESH;
++ else if (bss->capability & WLAN_CAPABILITY_ESS)
++ iwe.u.mode = IW_MODE_MASTER;
++ else
++ iwe.u.mode = IW_MODE_ADHOC;
++ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
++ IW_EV_UINT_LEN);
++ }
++
++ memset(&iwe, 0, sizeof(iwe));
++ iwe.cmd = SIOCGIWFREQ;
++ iwe.u.freq.m = bss->freq;
++ iwe.u.freq.e = 6;
++ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
++ IW_EV_FREQ_LEN);
++
++ memset(&iwe, 0, sizeof(iwe));
++ iwe.cmd = SIOCGIWFREQ;
++ iwe.u.freq.m = ieee80211_frequency_to_channel(bss->freq);
++ iwe.u.freq.e = 0;
++ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
++ IW_EV_FREQ_LEN);
++
++ memset(&iwe, 0, sizeof(iwe));
++ iwe.cmd = IWEVQUAL;
++ iwe.u.qual.qual = bss->signal;
++ iwe.u.qual.level = bss->rssi;
++ iwe.u.qual.noise = bss->noise;
++ iwe.u.qual.updated = local->wstats_flags;
++ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
++ IW_EV_QUAL_LEN);
++
++ memset(&iwe, 0, sizeof(iwe));
++ iwe.cmd = SIOCGIWENCODE;
++ if (bss->capability & WLAN_CAPABILITY_PRIVACY)
++ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
++ else
++ iwe.u.data.flags = IW_ENCODE_DISABLED;
++ iwe.u.data.length = 0;
++ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, "");
++
++ if (bss && bss->wpa_ie) {
++ memset(&iwe, 0, sizeof(iwe));
++ iwe.cmd = IWEVGENIE;
++ iwe.u.data.length = bss->wpa_ie_len;
++ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
++ bss->wpa_ie);
++ }
++
++ if (bss && bss->rsn_ie) {
++ memset(&iwe, 0, sizeof(iwe));
++ iwe.cmd = IWEVGENIE;
++ iwe.u.data.length = bss->rsn_ie_len;
++ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
++ bss->rsn_ie);
++ }
++
++ if (bss && bss->supp_rates_len > 0) {
++ /* display all supported rates in readable format */
++ char *p = current_ev + IW_EV_LCP_LEN;
++ int i;
++
++ memset(&iwe, 0, sizeof(iwe));
++ iwe.cmd = SIOCGIWRATE;
++ /* Those two flags are ignored... */
++ iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
++
++ for (i = 0; i < bss->supp_rates_len; i++) {
++ iwe.u.bitrate.value = ((bss->supp_rates[i] &
++ 0x7f) * 500000);
++ p = iwe_stream_add_value(current_ev, p,
++ end_buf, &iwe, IW_EV_PARAM_LEN);
++ }
++ current_ev = p;
++ }
++
++ if (bss) {
++ char *buf;
++ buf = kmalloc(30, GFP_ATOMIC);
++ if (buf) {
++ memset(&iwe, 0, sizeof(iwe));
++ iwe.cmd = IWEVCUSTOM;
++ sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->timestamp));
++ iwe.u.data.length = strlen(buf);
++ current_ev = iwe_stream_add_point(current_ev, end_buf,
++ &iwe, buf);
++ kfree(buf);
++ }
++ }
++
++ if (bss_mesh_cfg(bss)) {
++ char *buf;
++ u8 *cfg = bss_mesh_cfg(bss);
++ buf = kmalloc(50, GFP_ATOMIC);
++ if (buf) {
++ memset(&iwe, 0, sizeof(iwe));
++ iwe.cmd = IWEVCUSTOM;
++ sprintf(buf, "Mesh network (version %d)", cfg[0]);
++ iwe.u.data.length = strlen(buf);
++ current_ev = iwe_stream_add_point(current_ev, end_buf,
++ &iwe, buf);
++ sprintf(buf, "Path Selection Protocol ID: "
++ "0x%02X%02X%02X%02X", cfg[1], cfg[2], cfg[3],
++ cfg[4]);
++ iwe.u.data.length = strlen(buf);
++ current_ev = iwe_stream_add_point(current_ev, end_buf,
++ &iwe, buf);
++ sprintf(buf, "Path Selection Metric ID: "
++ "0x%02X%02X%02X%02X", cfg[5], cfg[6], cfg[7],
++ cfg[8]);
++ iwe.u.data.length = strlen(buf);
++ current_ev = iwe_stream_add_point(current_ev, end_buf,
++ &iwe, buf);
++ sprintf(buf, "Congestion Control Mode ID: "
++ "0x%02X%02X%02X%02X", cfg[9], cfg[10],
++ cfg[11], cfg[12]);
++ iwe.u.data.length = strlen(buf);
++ current_ev = iwe_stream_add_point(current_ev, end_buf,
++ &iwe, buf);
++ sprintf(buf, "Channel Precedence: "
++ "0x%02X%02X%02X%02X", cfg[13], cfg[14],
++ cfg[15], cfg[16]);
++ iwe.u.data.length = strlen(buf);
++ current_ev = iwe_stream_add_point(current_ev, end_buf,
++ &iwe, buf);
++ kfree(buf);
++ }
++ }
++
++ return current_ev;
++}
++
++
++int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ char *current_ev = buf;
++ char *end_buf = buf + len;
++ struct ieee80211_sta_bss *bss;
++
++ spin_lock_bh(&local->sta_bss_lock);
++ list_for_each_entry(bss, &local->sta_bss_list, list) {
++ if (buf + len - current_ev <= IW_EV_ADDR_LEN) {
++ spin_unlock_bh(&local->sta_bss_lock);
++ return -E2BIG;
++ }
++ current_ev = ieee80211_sta_scan_result(dev, bss, current_ev,
++ end_buf);
++ }
++ spin_unlock_bh(&local->sta_bss_lock);
++ return current_ev - buf;
++}
++
++
++int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++ kfree(ifsta->extra_ie);
++ if (len == 0) {
++ ifsta->extra_ie = NULL;
++ ifsta->extra_ie_len = 0;
++ return 0;
++ }
++ ifsta->extra_ie = kmalloc(len, GFP_KERNEL);
++ if (!ifsta->extra_ie) {
++ ifsta->extra_ie_len = 0;
++ return -ENOMEM;
++ }
++ memcpy(ifsta->extra_ie, ie, len);
++ ifsta->extra_ie_len = len;
++ return 0;
++}
++
++
++struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev,
++ struct sk_buff *skb, u8 *bssid,
++ u8 *addr)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct sta_info *sta;
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ DECLARE_MAC_BUF(mac);
++
++ /* TODO: Could consider removing the least recently used entry and
++ * allow new one to be added. */
++ if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
++ if (net_ratelimit()) {
++ printk(KERN_DEBUG "%s: No room for a new IBSS STA "
++ "entry %s\n", dev->name, print_mac(mac, addr));
++ }
++ return NULL;
++ }
++
++ printk(KERN_DEBUG "%s: Adding new IBSS station %s (dev=%s)\n",
++ wiphy_name(local->hw.wiphy), print_mac(mac, addr), dev->name);
++
++ sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
++ if (!sta)
++ return NULL;
++
++ sta->flags |= WLAN_STA_AUTHORIZED;
++
++ sta->supp_rates[local->hw.conf.channel->band] =
++ sdata->u.sta.supp_rates_bits[local->hw.conf.channel->band];
++
++ rate_control_rate_init(sta, local);
++
++ if (sta_info_insert(sta))
++ return NULL;
++
++ return sta;
++}
++
++
++int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++
++ printk(KERN_DEBUG "%s: deauthenticate(reason=%d)\n",
++ dev->name, reason);
++
++ if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
++ sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
++ return -EINVAL;
++
++ ieee80211_send_deauth(dev, ifsta, reason);
++ ieee80211_set_disassoc(dev, ifsta, 1);
++ return 0;
++}
++
++
++int ieee80211_sta_disassociate(struct net_device *dev, u16 reason)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
++
++ printk(KERN_DEBUG "%s: disassociate(reason=%d)\n",
++ dev->name, reason);
++
++ if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
++ return -EINVAL;
++
++ if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED))
++ return -1;
++
++ ieee80211_send_disassoc(dev, ifsta, reason);
++ ieee80211_set_disassoc(dev, ifsta, 0);
++ return 0;
++}
++
++void ieee80211_notify_mac(struct ieee80211_hw *hw,
++ enum ieee80211_notification_types notif_type)
++{
++ struct ieee80211_local *local = hw_to_local(hw);
++ struct ieee80211_sub_if_data *sdata;
++
++ switch (notif_type) {
++ case IEEE80211_NOTIFY_RE_ASSOC:
++ rcu_read_lock();
++ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
++
++ if (sdata->vif.type == IEEE80211_IF_TYPE_STA) {
++ ieee80211_sta_req_auth(sdata->dev,
++ &sdata->u.sta);
++ }
++
++ }
++ rcu_read_unlock();
++ break;
++ }
++}
++EXPORT_SYMBOL(ieee80211_notify_mac);
+diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
+new file mode 100644
+index 0000000..841df93
+--- /dev/null
++++ b/net/mac80211/rate.c
+@@ -0,0 +1,249 @@
++/*
++ * Copyright 2002-2005, Instant802 Networks, Inc.
++ * Copyright 2005-2006, Devicescape Software, Inc.
++ * Copyright (c) 2006 Jiri Benc <jbenc at suse.cz>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/kernel.h>
++#include <linux/rtnetlink.h>
++#include "rate.h"
++#include "ieee80211_i.h"
++
++struct rate_control_alg {
++ struct list_head list;
++ struct rate_control_ops *ops;
++};
++
++static LIST_HEAD(rate_ctrl_algs);
++static DEFINE_MUTEX(rate_ctrl_mutex);
++
++static char *ieee80211_default_rc_algo = CONFIG_MAC80211_RC_DEFAULT;
++module_param(ieee80211_default_rc_algo, charp, 0644);
++MODULE_PARM_DESC(ieee80211_default_rc_algo,
++ "Default rate control algorithm for mac80211 to use");
++
++int ieee80211_rate_control_register(struct rate_control_ops *ops)
++{
++ struct rate_control_alg *alg;
++
++ if (!ops->name)
++ return -EINVAL;
++
++ mutex_lock(&rate_ctrl_mutex);
++ list_for_each_entry(alg, &rate_ctrl_algs, list) {
++ if (!strcmp(alg->ops->name, ops->name)) {
++ /* don't register an algorithm twice */
++ WARN_ON(1);
++ mutex_unlock(&rate_ctrl_mutex);
++ return -EALREADY;
++ }
++ }
++
++ alg = kzalloc(sizeof(*alg), GFP_KERNEL);
++ if (alg == NULL) {
++ mutex_unlock(&rate_ctrl_mutex);
++ return -ENOMEM;
++ }
++ alg->ops = ops;
++
++ list_add_tail(&alg->list, &rate_ctrl_algs);
++ mutex_unlock(&rate_ctrl_mutex);
++
++ return 0;
++}
++EXPORT_SYMBOL(ieee80211_rate_control_register);
++
++void ieee80211_rate_control_unregister(struct rate_control_ops *ops)
++{
++ struct rate_control_alg *alg;
++
++ mutex_lock(&rate_ctrl_mutex);
++ list_for_each_entry(alg, &rate_ctrl_algs, list) {
++ if (alg->ops == ops) {
++ list_del(&alg->list);
++ kfree(alg);
++ break;
++ }
++ }
++ mutex_unlock(&rate_ctrl_mutex);
++}
++EXPORT_SYMBOL(ieee80211_rate_control_unregister);
++
++static struct rate_control_ops *
++ieee80211_try_rate_control_ops_get(const char *name)
++{
++ struct rate_control_alg *alg;
++ struct rate_control_ops *ops = NULL;
++
++ if (!name)
++ return NULL;
++
++ mutex_lock(&rate_ctrl_mutex);
++ list_for_each_entry(alg, &rate_ctrl_algs, list) {
++ if (!strcmp(alg->ops->name, name))
++ if (try_module_get(alg->ops->module)) {
++ ops = alg->ops;
++ break;
++ }
++ }
++ mutex_unlock(&rate_ctrl_mutex);
++ return ops;
++}
++
++/* Get the rate control algorithm. */
++static struct rate_control_ops *
++ieee80211_rate_control_ops_get(const char *name)
++{
++ struct rate_control_ops *ops;
++ const char *alg_name;
++
++ if (!name)
++ alg_name = ieee80211_default_rc_algo;
++ else
++ alg_name = name;
++
++ ops = ieee80211_try_rate_control_ops_get(alg_name);
++ if (!ops) {
++ request_module("rc80211_%s", alg_name);
++ ops = ieee80211_try_rate_control_ops_get(alg_name);
++ }
++ if (!ops && name)
++ /* try default if specific alg requested but not found */
++ ops = ieee80211_try_rate_control_ops_get(ieee80211_default_rc_algo);
++
++ /* try built-in one if specific alg requested but not found */
++ if (!ops && strlen(CONFIG_MAC80211_RC_DEFAULT))
++ ops = ieee80211_try_rate_control_ops_get(CONFIG_MAC80211_RC_DEFAULT);
++
++ return ops;
++}
++
++static void ieee80211_rate_control_ops_put(struct rate_control_ops *ops)
++{
++ module_put(ops->module);
++}
++
++struct rate_control_ref *rate_control_alloc(const char *name,
++ struct ieee80211_local *local)
++{
++ struct rate_control_ref *ref;
++
++ ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL);
++ if (!ref)
++ goto fail_ref;
++ kref_init(&ref->kref);
++ ref->ops = ieee80211_rate_control_ops_get(name);
++ if (!ref->ops)
++ goto fail_ops;
++ ref->priv = ref->ops->alloc(local);
++ if (!ref->priv)
++ goto fail_priv;
++ return ref;
++
++fail_priv:
++ ieee80211_rate_control_ops_put(ref->ops);
++fail_ops:
++ kfree(ref);
++fail_ref:
++ return NULL;
++}
++
++static void rate_control_release(struct kref *kref)
++{
++ struct rate_control_ref *ctrl_ref;
++
++ ctrl_ref = container_of(kref, struct rate_control_ref, kref);
++ ctrl_ref->ops->free(ctrl_ref->priv);
++ ieee80211_rate_control_ops_put(ctrl_ref->ops);
++ kfree(ctrl_ref);
++}
++
++void rate_control_get_rate(struct net_device *dev,
++ struct ieee80211_supported_band *sband,
++ struct sk_buff *skb,
++ struct rate_selection *sel)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct rate_control_ref *ref = local->rate_ctrl;
++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
++ struct sta_info *sta;
++ int i;
++
++ rcu_read_lock();
++ sta = sta_info_get(local, hdr->addr1);
++
++ memset(sel, 0, sizeof(struct rate_selection));
++
++ ref->ops->get_rate(ref->priv, dev, sband, skb, sel);
++
++ /* Select a non-ERP backup rate. */
++ if (!sel->nonerp) {
++ for (i = 0; i < sband->n_bitrates; i++) {
++ struct ieee80211_rate *rate = &sband->bitrates[i];
++ if (sel->rate->bitrate < rate->bitrate)
++ break;
++
++ if (rate_supported(sta, sband->band, i) &&
++ !(rate->flags & IEEE80211_RATE_ERP_G))
++ sel->nonerp = rate;
++ }
++ }
++
++ rcu_read_unlock();
++}
++
++struct rate_control_ref *rate_control_get(struct rate_control_ref *ref)
++{
++ kref_get(&ref->kref);
++ return ref;
++}
++
++void rate_control_put(struct rate_control_ref *ref)
++{
++ kref_put(&ref->kref, rate_control_release);
++}
++
++int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
++ const char *name)
++{
++ struct rate_control_ref *ref, *old;
++
++ ASSERT_RTNL();
++ if (local->open_count || netif_running(local->mdev))
++ return -EBUSY;
++
++ ref = rate_control_alloc(name, local);
++ if (!ref) {
++ printk(KERN_WARNING "%s: Failed to select rate control "
++ "algorithm\n", wiphy_name(local->hw.wiphy));
++ return -ENOENT;
++ }
++
++ old = local->rate_ctrl;
++ local->rate_ctrl = ref;
++ if (old) {
++ rate_control_put(old);
++ sta_info_flush(local, NULL);
++ }
++
++ printk(KERN_DEBUG "%s: Selected rate control "
++ "algorithm '%s'\n", wiphy_name(local->hw.wiphy),
++ ref->ops->name);
++
++
++ return 0;
++}
++
++void rate_control_deinitialize(struct ieee80211_local *local)
++{
++ struct rate_control_ref *ref;
++
++ ref = local->rate_ctrl;
++ local->rate_ctrl = NULL;
++ rate_control_put(ref);
++}
++
+diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h
+new file mode 100644
+index 0000000..5b45f33
+--- /dev/null
++++ b/net/mac80211/rate.h
+@@ -0,0 +1,189 @@
++/*
++ * Copyright 2002-2005, Instant802 Networks, Inc.
++ * Copyright 2005, Devicescape Software, Inc.
++ * Copyright (c) 2006 Jiri Benc <jbenc at suse.cz>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef IEEE80211_RATE_H
++#define IEEE80211_RATE_H
++
++#include <linux/netdevice.h>
++#include <linux/skbuff.h>
++#include <linux/types.h>
++#include <linux/kref.h>
++#include <net/mac80211.h>
++#include "ieee80211_i.h"
++#include "sta_info.h"
++
++/* TODO: kdoc */
++struct rate_selection {
++ /* Selected transmission rate */
++ struct ieee80211_rate *rate;
++ /* Non-ERP rate to use if mac80211 decides it cannot use an ERP rate */
++ struct ieee80211_rate *nonerp;
++ /* probe with this rate, or NULL for no probing */
++ struct ieee80211_rate *probe;
++};
++
++struct rate_control_ops {
++ struct module *module;
++ const char *name;
++ void (*tx_status)(void *priv, struct net_device *dev,
++ struct sk_buff *skb,
++ struct ieee80211_tx_status *status);
++ void (*get_rate)(void *priv, struct net_device *dev,
++ struct ieee80211_supported_band *band,
++ struct sk_buff *skb,
++ struct rate_selection *sel);
++ void (*rate_init)(void *priv, void *priv_sta,
++ struct ieee80211_local *local, struct sta_info *sta);
++ void (*clear)(void *priv);
++
++ void *(*alloc)(struct ieee80211_local *local);
++ void (*free)(void *priv);
++ void *(*alloc_sta)(void *priv, gfp_t gfp);
++ void (*free_sta)(void *priv, void *priv_sta);
++
++ int (*add_attrs)(void *priv, struct kobject *kobj);
++ void (*remove_attrs)(void *priv, struct kobject *kobj);
++ void (*add_sta_debugfs)(void *priv, void *priv_sta,
++ struct dentry *dir);
++ void (*remove_sta_debugfs)(void *priv, void *priv_sta);
++};
++
++struct rate_control_ref {
++ struct rate_control_ops *ops;
++ void *priv;
++ struct kref kref;
++};
++
++int ieee80211_rate_control_register(struct rate_control_ops *ops);
++void ieee80211_rate_control_unregister(struct rate_control_ops *ops);
++
++/* Get a reference to the rate control algorithm. If `name' is NULL, get the
++ * first available algorithm. */
++struct rate_control_ref *rate_control_alloc(const char *name,
++ struct ieee80211_local *local);
++void rate_control_get_rate(struct net_device *dev,
++ struct ieee80211_supported_band *sband,
++ struct sk_buff *skb,
++ struct rate_selection *sel);
++struct rate_control_ref *rate_control_get(struct rate_control_ref *ref);
++void rate_control_put(struct rate_control_ref *ref);
++
++static inline void rate_control_tx_status(struct net_device *dev,
++ struct sk_buff *skb,
++ struct ieee80211_tx_status *status)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct rate_control_ref *ref = local->rate_ctrl;
++
++ ref->ops->tx_status(ref->priv, dev, skb, status);
++}
++
++
++static inline void rate_control_rate_init(struct sta_info *sta,
++ struct ieee80211_local *local)
++{
++ struct rate_control_ref *ref = sta->rate_ctrl;
++ ref->ops->rate_init(ref->priv, sta->rate_ctrl_priv, local, sta);
++}
++
++
++static inline void rate_control_clear(struct ieee80211_local *local)
++{
++ struct rate_control_ref *ref = local->rate_ctrl;
++ ref->ops->clear(ref->priv);
++}
++
++static inline void *rate_control_alloc_sta(struct rate_control_ref *ref,
++ gfp_t gfp)
++{
++ return ref->ops->alloc_sta(ref->priv, gfp);
++}
++
++static inline void rate_control_free_sta(struct rate_control_ref *ref,
++ void *priv)
++{
++ ref->ops->free_sta(ref->priv, priv);
++}
++
++static inline void rate_control_add_sta_debugfs(struct sta_info *sta)
++{
++#ifdef CONFIG_MAC80211_DEBUGFS
++ struct rate_control_ref *ref = sta->rate_ctrl;
++ if (sta->debugfs.dir && ref->ops->add_sta_debugfs)
++ ref->ops->add_sta_debugfs(ref->priv, sta->rate_ctrl_priv,
++ sta->debugfs.dir);
++#endif
++}
++
++static inline void rate_control_remove_sta_debugfs(struct sta_info *sta)
++{
++#ifdef CONFIG_MAC80211_DEBUGFS
++ struct rate_control_ref *ref = sta->rate_ctrl;
++ if (ref->ops->remove_sta_debugfs)
++ ref->ops->remove_sta_debugfs(ref->priv, sta->rate_ctrl_priv);
++#endif
++}
++
++static inline int rate_supported(struct sta_info *sta,
++ enum ieee80211_band band,
++ int index)
++{
++ return (sta == NULL || sta->supp_rates[band] & BIT(index));
++}
++
++static inline int
++rate_lowest_index(struct ieee80211_local *local,
++ struct ieee80211_supported_band *sband,
++ struct sta_info *sta)
++{
++ int i;
++
++ for (i = 0; i < sband->n_bitrates; i++)
++ if (rate_supported(sta, sband->band, i))
++ return i;
++
++ /* warn when we cannot find a rate. */
++ WARN_ON(1);
++
++ return 0;
++}
++
++static inline struct ieee80211_rate *
++rate_lowest(struct ieee80211_local *local,
++ struct ieee80211_supported_band *sband,
++ struct sta_info *sta)
++{
++ return &sband->bitrates[rate_lowest_index(local, sband, sta)];
++}
++
++
++/* functions for rate control related to a device */
++int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
++ const char *name);
++void rate_control_deinitialize(struct ieee80211_local *local);
++
++
++/* Rate control algorithms */
++#if defined(RC80211_PID_COMPILE) || \
++ (defined(CONFIG_MAC80211_RC_PID) && \
++ !defined(CONFIG_MAC80211_RC_PID_MODULE))
++extern int rc80211_pid_init(void);
++extern void rc80211_pid_exit(void);
++#else
++static inline int rc80211_pid_init(void)
++{
++ return 0;
++}
++static inline void rc80211_pid_exit(void)
++{
++}
++#endif
++
++#endif /* IEEE80211_RATE_H */
+diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c
+index 3b77410..a849b74 100644
+--- a/net/mac80211/rc80211_pid_algo.c
++++ b/net/mac80211/rc80211_pid_algo.c
+@@ -14,8 +14,8 @@
+ #include <linux/skbuff.h>
+ #include <linux/debugfs.h>
+ #include <net/mac80211.h>
+-#include "ieee80211_rate.h"
+-
++#include "rate.h"
++#include "mesh.h"
+ #include "rc80211_pid.h"
+
+
+@@ -63,6 +63,7 @@
+ * RC_PID_ARITH_SHIFT.
+ */
+
++
+ /* Adjust the rate while ensuring that we won't switch to a lower rate if it
+ * exhibited a worse failed frames behaviour and we'll choose the highest rate
+ * whose failed frames behaviour is not worse than the one of the original rate
+@@ -72,14 +73,14 @@ static void rate_control_pid_adjust_rate(struct ieee80211_local *local,
+ struct rc_pid_rateinfo *rinfo)
+ {
+ struct ieee80211_sub_if_data *sdata;
+- struct ieee80211_hw_mode *mode;
+- int cur_sorted, new_sorted, probe, tmp, n_bitrates;
+- int cur = sta->txrate;
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
++ struct ieee80211_supported_band *sband;
++ int cur_sorted, new_sorted, probe, tmp, n_bitrates, band;
++ int cur = sta->txrate_idx;
+
+- mode = local->oper_hw_mode;
+- n_bitrates = mode->num_rates;
++ sdata = sta->sdata;
++ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++ band = sband->band;
++ n_bitrates = sband->n_bitrates;
+
+ /* Map passed arguments to sorted values. */
+ cur_sorted = rinfo[cur].rev_index;
+@@ -97,20 +98,20 @@ static void rate_control_pid_adjust_rate(struct ieee80211_local *local,
+ /* Ensure that the rate decrease isn't disadvantageous. */
+ for (probe = cur_sorted; probe >= new_sorted; probe--)
+ if (rinfo[probe].diff <= rinfo[cur_sorted].diff &&
+- rate_supported(sta, mode, rinfo[probe].index))
++ rate_supported(sta, band, rinfo[probe].index))
+ tmp = probe;
+ } else {
+ /* Look for rate increase with zero (or below) cost. */
+ for (probe = new_sorted + 1; probe < n_bitrates; probe++)
+ if (rinfo[probe].diff <= rinfo[new_sorted].diff &&
+- rate_supported(sta, mode, rinfo[probe].index))
++ rate_supported(sta, band, rinfo[probe].index))
+ tmp = probe;
+ }
+
+ /* Fit the rate found to the nearest supported rate. */
+ do {
+- if (rate_supported(sta, mode, rinfo[tmp].index)) {
+- sta->txrate = rinfo[tmp].index;
++ if (rate_supported(sta, band, rinfo[tmp].index)) {
++ sta->txrate_idx = rinfo[tmp].index;
+ break;
+ }
+ if (adj < 0)
+@@ -122,7 +123,7 @@ static void rate_control_pid_adjust_rate(struct ieee80211_local *local,
+ #ifdef CONFIG_MAC80211_DEBUGFS
+ rate_control_pid_event_rate_change(
+ &((struct rc_pid_sta_info *)sta->rate_ctrl_priv)->events,
+- cur, mode->rates[cur].rate);
++ sta->txrate_idx, sband->bitrates[sta->txrate_idx].bitrate);
+ #endif
+ }
+
+@@ -147,9 +148,12 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
+ struct ieee80211_local *local,
+ struct sta_info *sta)
+ {
++#ifdef CONFIG_MAC80211_MESH
++ struct ieee80211_sub_if_data *sdata = sta->sdata;
++#endif
+ struct rc_pid_sta_info *spinfo = sta->rate_ctrl_priv;
+ struct rc_pid_rateinfo *rinfo = pinfo->rinfo;
+- struct ieee80211_hw_mode *mode;
++ struct ieee80211_supported_band *sband;
+ u32 pf;
+ s32 err_avg;
+ u32 err_prop;
+@@ -158,7 +162,7 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
+ int adj, i, j, tmp;
+ unsigned long period;
+
+- mode = local->oper_hw_mode;
++ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+ spinfo = sta->rate_ctrl_priv;
+
+ /* In case nothing happened during the previous control interval, turn
+@@ -177,25 +181,32 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
+ pf = spinfo->last_pf;
+ else {
+ pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit;
++#ifdef CONFIG_MAC80211_MESH
++ if (pf == 100 &&
++ sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT)
++ mesh_plink_broken(sta);
++#endif
+ pf <<= RC_PID_ARITH_SHIFT;
++ sta->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9)
++ >> RC_PID_ARITH_SHIFT;
+ }
+
+ spinfo->tx_num_xmit = 0;
+ spinfo->tx_num_failed = 0;
+
+ /* If we just switched rate, update the rate behaviour info. */
+- if (pinfo->oldrate != sta->txrate) {
++ if (pinfo->oldrate != sta->txrate_idx) {
+
+ i = rinfo[pinfo->oldrate].rev_index;
+- j = rinfo[sta->txrate].rev_index;
++ j = rinfo[sta->txrate_idx].rev_index;
+
+ tmp = (pf - spinfo->last_pf);
+ tmp = RC_PID_DO_ARITH_RIGHT_SHIFT(tmp, RC_PID_ARITH_SHIFT);
+
+ rinfo[j].diff = rinfo[i].diff + tmp;
+- pinfo->oldrate = sta->txrate;
++ pinfo->oldrate = sta->txrate_idx;
+ }
+- rate_control_pid_normalize(pinfo, mode->num_rates);
++ rate_control_pid_normalize(pinfo, sband->n_bitrates);
+
+ /* Compute the proportional, integral and derivative errors. */
+ err_prop = (pinfo->target << RC_PID_ARITH_SHIFT) - pf;
+@@ -236,23 +247,27 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev,
+ struct sta_info *sta;
+ struct rc_pid_sta_info *spinfo;
+ unsigned long period;
++ struct ieee80211_supported_band *sband;
++
++ rcu_read_lock();
+
+ sta = sta_info_get(local, hdr->addr1);
++ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+
+ if (!sta)
+- return;
++ goto unlock;
+
+ /* Don't update the state if we're not controlling the rate. */
+- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
++ sdata = sta->sdata;
+ if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
+- sta->txrate = sdata->bss->max_ratectrl_rateidx;
+- return;
++ sta->txrate_idx = sdata->bss->max_ratectrl_rateidx;
++ goto unlock;
+ }
+
+ /* Ignore all frames that were sent with a different rate than the rate
+ * we currently advise mac80211 to use. */
+- if (status->control.rate != &local->oper_hw_mode->rates[sta->txrate])
+- goto ignore;
++ if (status->control.tx_rate != &sband->bitrates[sta->txrate_idx])
++ goto unlock;
+
+ spinfo = sta->rate_ctrl_priv;
+ spinfo->tx_num_xmit++;
+@@ -277,9 +292,6 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev,
+ sta->tx_num_consecutive_failures++;
+ sta->tx_num_mpdu_fail++;
+ } else {
+- sta->last_ack_rssi[0] = sta->last_ack_rssi[1];
+- sta->last_ack_rssi[1] = sta->last_ack_rssi[2];
+- sta->last_ack_rssi[2] = status->ack_signal;
+ sta->tx_num_consecutive_failures = 0;
+ sta->tx_num_mpdu_ok++;
+ }
+@@ -293,12 +305,12 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev,
+ if (time_after(jiffies, spinfo->last_sample + period))
+ rate_control_pid_sample(pinfo, local, sta);
+
+-ignore:
+- sta_info_put(sta);
++ unlock:
++ rcu_read_unlock();
+ }
+
+ static void rate_control_pid_get_rate(void *priv, struct net_device *dev,
+- struct ieee80211_hw_mode *mode,
++ struct ieee80211_supported_band *sband,
+ struct sk_buff *skb,
+ struct rate_selection *sel)
+ {
+@@ -309,6 +321,8 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev,
+ int rateidx;
+ u16 fc;
+
++ rcu_read_lock();
++
+ sta = sta_info_get(local, hdr->addr1);
+
+ /* Send management frames and broadcast/multicast data using lowest
+@@ -316,32 +330,31 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev,
+ fc = le16_to_cpu(hdr->frame_control);
+ if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
+ is_multicast_ether_addr(hdr->addr1) || !sta) {
+- sel->rate = rate_lowest(local, mode, sta);
+- if (sta)
+- sta_info_put(sta);
++ sel->rate = rate_lowest(local, sband, sta);
++ rcu_read_unlock();
+ return;
+ }
+
+ /* If a forced rate is in effect, select it. */
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ if (sdata->bss && sdata->bss->force_unicast_rateidx > -1)
+- sta->txrate = sdata->bss->force_unicast_rateidx;
++ sta->txrate_idx = sdata->bss->force_unicast_rateidx;
+
+- rateidx = sta->txrate;
++ rateidx = sta->txrate_idx;
+
+- if (rateidx >= mode->num_rates)
+- rateidx = mode->num_rates - 1;
++ if (rateidx >= sband->n_bitrates)
++ rateidx = sband->n_bitrates - 1;
+
+- sta->last_txrate = rateidx;
++ sta->last_txrate_idx = rateidx;
+
+- sta_info_put(sta);
++ rcu_read_unlock();
+
+- sel->rate = &mode->rates[rateidx];
++ sel->rate = &sband->bitrates[rateidx];
+
+ #ifdef CONFIG_MAC80211_DEBUGFS
+ rate_control_pid_event_tx_rate(
+ &((struct rc_pid_sta_info *) sta->rate_ctrl_priv)->events,
+- rateidx, mode->rates[rateidx].rate);
++ rateidx, sband->bitrates[rateidx].bitrate);
+ #endif
+ }
+
+@@ -353,28 +366,33 @@ static void rate_control_pid_rate_init(void *priv, void *priv_sta,
+ * as we need to have IEEE 802.1X auth succeed immediately after assoc..
+ * Until that method is implemented, we will use the lowest supported
+ * rate as a workaround. */
+- sta->txrate = rate_lowest_index(local, local->oper_hw_mode, sta);
++ struct ieee80211_supported_band *sband;
++
++ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++ sta->txrate_idx = rate_lowest_index(local, sband, sta);
++ sta->fail_avg = 0;
+ }
+
+ static void *rate_control_pid_alloc(struct ieee80211_local *local)
+ {
+ struct rc_pid_info *pinfo;
+ struct rc_pid_rateinfo *rinfo;
+- struct ieee80211_hw_mode *mode;
++ struct ieee80211_supported_band *sband;
+ int i, j, tmp;
+ bool s;
+ #ifdef CONFIG_MAC80211_DEBUGFS
+ struct rc_pid_debugfs_entries *de;
+ #endif
+
++ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++
+ pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC);
+ if (!pinfo)
+ return NULL;
+
+- /* We can safely assume that oper_hw_mode won't change unless we get
++ /* We can safely assume that sband won't change unless we get
+ * reinitialized. */
+- mode = local->oper_hw_mode;
+- rinfo = kmalloc(sizeof(*rinfo) * mode->num_rates, GFP_ATOMIC);
++ rinfo = kmalloc(sizeof(*rinfo) * sband->n_bitrates, GFP_ATOMIC);
+ if (!rinfo) {
+ kfree(pinfo);
+ return NULL;
+@@ -383,7 +401,7 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local)
+ /* Sort the rates. This is optimized for the most common case (i.e.
+ * almost-sorted CCK+OFDM rates). Kind of bubble-sort with reversed
+ * mapping too. */
+- for (i = 0; i < mode->num_rates; i++) {
++ for (i = 0; i < sband->n_bitrates; i++) {
+ rinfo[i].index = i;
+ rinfo[i].rev_index = i;
+ if (pinfo->fast_start)
+@@ -391,11 +409,11 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local)
+ else
+ rinfo[i].diff = i * pinfo->norm_offset;
+ }
+- for (i = 1; i < mode->num_rates; i++) {
++ for (i = 1; i < sband->n_bitrates; i++) {
+ s = 0;
+- for (j = 0; j < mode->num_rates - i; j++)
+- if (unlikely(mode->rates[rinfo[j].index].rate >
+- mode->rates[rinfo[j + 1].index].rate)) {
++ for (j = 0; j < sband->n_bitrates - i; j++)
++ if (unlikely(sband->bitrates[rinfo[j].index].bitrate >
++ sband->bitrates[rinfo[j + 1].index].bitrate)) {
+ tmp = rinfo[j].index;
+ rinfo[j].index = rinfo[j + 1].index;
+ rinfo[j + 1].index = tmp;
+diff --git a/net/mac80211/rc80211_pid_debugfs.c b/net/mac80211/rc80211_pid_debugfs.c
+index 88b8dc9..ae75d41 100644
+--- a/net/mac80211/rc80211_pid_debugfs.c
++++ b/net/mac80211/rc80211_pid_debugfs.c
+@@ -13,7 +13,7 @@
+ #include <linux/skbuff.h>
+
+ #include <net/mac80211.h>
+-#include "ieee80211_rate.h"
++#include "rate.h"
+
+ #include "rc80211_pid.h"
+
+diff --git a/net/mac80211/rc80211_simple.c b/net/mac80211/rc80211_simple.c
+deleted file mode 100644
+index 9a78b11..0000000
+--- a/net/mac80211/rc80211_simple.c
++++ /dev/null
+@@ -1,400 +0,0 @@
+-/*
+- * Copyright 2002-2005, Instant802 Networks, Inc.
+- * Copyright 2005, Devicescape Software, Inc.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#include <linux/init.h>
+-#include <linux/netdevice.h>
+-#include <linux/types.h>
+-#include <linux/slab.h>
+-#include <linux/skbuff.h>
+-#include <linux/compiler.h>
+-#include <linux/module.h>
+-
+-#include <net/mac80211.h>
+-#include "ieee80211_i.h"
+-#include "ieee80211_rate.h"
+-#include "debugfs.h"
+-
+-
+-/* This is a minimal implementation of TX rate controlling that can be used
+- * as the default when no improved mechanisms are available. */
+-
+-#define RATE_CONTROL_NUM_DOWN 20
+-#define RATE_CONTROL_NUM_UP 15
+-
+-#define RATE_CONTROL_EMERG_DEC 2
+-#define RATE_CONTROL_INTERVAL (HZ / 20)
+-#define RATE_CONTROL_MIN_TX 10
+-
+-static void rate_control_rate_inc(struct ieee80211_local *local,
+- struct sta_info *sta)
+-{
+- struct ieee80211_sub_if_data *sdata;
+- struct ieee80211_hw_mode *mode;
+- int i = sta->txrate;
+- int maxrate;
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+- if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
+- /* forced unicast rate - do not change STA rate */
+- return;
+- }
+-
+- mode = local->oper_hw_mode;
+- maxrate = sdata->bss ? sdata->bss->max_ratectrl_rateidx : -1;
+-
+- if (i > mode->num_rates)
+- i = mode->num_rates - 2;
+-
+- while (i + 1 < mode->num_rates) {
+- i++;
+- if (sta->supp_rates & BIT(i) &&
+- mode->rates[i].flags & IEEE80211_RATE_SUPPORTED &&
+- (maxrate < 0 || i <= maxrate)) {
+- sta->txrate = i;
+- break;
+- }
+- }
+-}
+-
+-
+-static void rate_control_rate_dec(struct ieee80211_local *local,
+- struct sta_info *sta)
+-{
+- struct ieee80211_sub_if_data *sdata;
+- struct ieee80211_hw_mode *mode;
+- int i = sta->txrate;
+-
+- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+- if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
+- /* forced unicast rate - do not change STA rate */
+- return;
+- }
+-
+- mode = local->oper_hw_mode;
+- if (i > mode->num_rates)
+- i = mode->num_rates;
+-
+- while (i > 0) {
+- i--;
+- if (sta->supp_rates & BIT(i) &&
+- mode->rates[i].flags & IEEE80211_RATE_SUPPORTED) {
+- sta->txrate = i;
+- break;
+- }
+- }
+-}
+-
+-struct global_rate_control {
+- int dummy;
+-};
+-
+-struct sta_rate_control {
+- unsigned long last_rate_change;
+- u32 tx_num_failures;
+- u32 tx_num_xmit;
+-
+- unsigned long avg_rate_update;
+- u32 tx_avg_rate_sum;
+- u32 tx_avg_rate_num;
+-
+-#ifdef CONFIG_MAC80211_DEBUGFS
+- struct dentry *tx_avg_rate_sum_dentry;
+- struct dentry *tx_avg_rate_num_dentry;
+-#endif
+-};
+-
+-
+-static void rate_control_simple_tx_status(void *priv, struct net_device *dev,
+- struct sk_buff *skb,
+- struct ieee80211_tx_status *status)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+- struct sta_info *sta;
+- struct sta_rate_control *srctrl;
+-
+- sta = sta_info_get(local, hdr->addr1);
+-
+- if (!sta)
+- return;
+-
+- srctrl = sta->rate_ctrl_priv;
+- srctrl->tx_num_xmit++;
+- if (status->excessive_retries) {
+- srctrl->tx_num_failures++;
+- sta->tx_retry_failed++;
+- sta->tx_num_consecutive_failures++;
+- sta->tx_num_mpdu_fail++;
+- } else {
+- sta->last_ack_rssi[0] = sta->last_ack_rssi[1];
+- sta->last_ack_rssi[1] = sta->last_ack_rssi[2];
+- sta->last_ack_rssi[2] = status->ack_signal;
+- sta->tx_num_consecutive_failures = 0;
+- sta->tx_num_mpdu_ok++;
+- }
+- sta->tx_retry_count += status->retry_count;
+- sta->tx_num_mpdu_fail += status->retry_count;
+-
+- if (time_after(jiffies,
+- srctrl->last_rate_change + RATE_CONTROL_INTERVAL) &&
+- srctrl->tx_num_xmit > RATE_CONTROL_MIN_TX) {
+- u32 per_failed;
+- srctrl->last_rate_change = jiffies;
+-
+- per_failed = (100 * sta->tx_num_mpdu_fail) /
+- (sta->tx_num_mpdu_fail + sta->tx_num_mpdu_ok);
+- /* TODO: calculate average per_failed to make adjusting
+- * parameters easier */
+-#if 0
+- if (net_ratelimit()) {
+- printk(KERN_DEBUG "MPDU fail=%d ok=%d per_failed=%d\n",
+- sta->tx_num_mpdu_fail, sta->tx_num_mpdu_ok,
+- per_failed);
+- }
+-#endif
+-
+- /*
+- * XXX: Make these configurable once we have an
+- * interface to the rate control algorithms
+- */
+- if (per_failed > RATE_CONTROL_NUM_DOWN) {
+- rate_control_rate_dec(local, sta);
+- } else if (per_failed < RATE_CONTROL_NUM_UP) {
+- rate_control_rate_inc(local, sta);
+- }
+- srctrl->tx_avg_rate_sum += status->control.rate->rate;
+- srctrl->tx_avg_rate_num++;
+- srctrl->tx_num_failures = 0;
+- srctrl->tx_num_xmit = 0;
+- } else if (sta->tx_num_consecutive_failures >=
+- RATE_CONTROL_EMERG_DEC) {
+- rate_control_rate_dec(local, sta);
+- }
+-
+- if (srctrl->avg_rate_update + 60 * HZ < jiffies) {
+- srctrl->avg_rate_update = jiffies;
+- if (srctrl->tx_avg_rate_num > 0) {
+-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+- DECLARE_MAC_BUF(mac);
+- printk(KERN_DEBUG "%s: STA %s Average rate: "
+- "%d (%d/%d)\n",
+- dev->name, print_mac(mac, sta->addr),
+- srctrl->tx_avg_rate_sum /
+- srctrl->tx_avg_rate_num,
+- srctrl->tx_avg_rate_sum,
+- srctrl->tx_avg_rate_num);
+-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+- srctrl->tx_avg_rate_sum = 0;
+- srctrl->tx_avg_rate_num = 0;
+- }
+- }
+-
+- sta_info_put(sta);
+-}
+-
+-
+-static void
+-rate_control_simple_get_rate(void *priv, struct net_device *dev,
+- struct ieee80211_hw_mode *mode,
+- struct sk_buff *skb,
+- struct rate_selection *sel)
+-{
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+- struct ieee80211_sub_if_data *sdata;
+- struct sta_info *sta;
+- int rateidx;
+- u16 fc;
+-
+- sta = sta_info_get(local, hdr->addr1);
+-
+- /* Send management frames and broadcast/multicast data using lowest
+- * rate. */
+- fc = le16_to_cpu(hdr->frame_control);
+- if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
+- is_multicast_ether_addr(hdr->addr1) || !sta) {
+- sel->rate = rate_lowest(local, mode, sta);
+- if (sta)
+- sta_info_put(sta);
+- return;
+- }
+-
+- /* If a forced rate is in effect, select it. */
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- if (sdata->bss && sdata->bss->force_unicast_rateidx > -1)
+- sta->txrate = sdata->bss->force_unicast_rateidx;
+-
+- rateidx = sta->txrate;
+-
+- if (rateidx >= mode->num_rates)
+- rateidx = mode->num_rates - 1;
+-
+- sta->last_txrate = rateidx;
+-
+- sta_info_put(sta);
+-
+- sel->rate = &mode->rates[rateidx];
+-}
+-
+-
+-static void rate_control_simple_rate_init(void *priv, void *priv_sta,
+- struct ieee80211_local *local,
+- struct sta_info *sta)
+-{
+- struct ieee80211_hw_mode *mode;
+- int i;
+- sta->txrate = 0;
+- mode = local->oper_hw_mode;
+- /* TODO: This routine should consider using RSSI from previous packets
+- * as we need to have IEEE 802.1X auth succeed immediately after assoc..
+- * Until that method is implemented, we will use the lowest supported rate
+- * as a workaround, */
+- for (i = 0; i < mode->num_rates; i++) {
+- if ((sta->supp_rates & BIT(i)) &&
+- (mode->rates[i].flags & IEEE80211_RATE_SUPPORTED)) {
+- sta->txrate = i;
+- break;
+- }
+- }
+-}
+-
+-
+-static void * rate_control_simple_alloc(struct ieee80211_local *local)
+-{
+- struct global_rate_control *rctrl;
+-
+- rctrl = kzalloc(sizeof(*rctrl), GFP_ATOMIC);
+-
+- return rctrl;
+-}
+-
+-
+-static void rate_control_simple_free(void *priv)
+-{
+- struct global_rate_control *rctrl = priv;
+- kfree(rctrl);
+-}
+-
+-
+-static void rate_control_simple_clear(void *priv)
+-{
+-}
+-
+-
+-static void * rate_control_simple_alloc_sta(void *priv, gfp_t gfp)
+-{
+- struct sta_rate_control *rctrl;
+-
+- rctrl = kzalloc(sizeof(*rctrl), gfp);
+-
+- return rctrl;
+-}
+-
+-
+-static void rate_control_simple_free_sta(void *priv, void *priv_sta)
+-{
+- struct sta_rate_control *rctrl = priv_sta;
+- kfree(rctrl);
+-}
+-
+-#ifdef CONFIG_MAC80211_DEBUGFS
+-
+-static int open_file_generic(struct inode *inode, struct file *file)
+-{
+- file->private_data = inode->i_private;
+- return 0;
+-}
+-
+-static ssize_t sta_tx_avg_rate_sum_read(struct file *file,
+- char __user *userbuf,
+- size_t count, loff_t *ppos)
+-{
+- struct sta_rate_control *srctrl = file->private_data;
+- char buf[20];
+-
+- sprintf(buf, "%d\n", srctrl->tx_avg_rate_sum);
+- return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
+-}
+-
+-static const struct file_operations sta_tx_avg_rate_sum_ops = {
+- .read = sta_tx_avg_rate_sum_read,
+- .open = open_file_generic,
+-};
+-
+-static ssize_t sta_tx_avg_rate_num_read(struct file *file,
+- char __user *userbuf,
+- size_t count, loff_t *ppos)
+-{
+- struct sta_rate_control *srctrl = file->private_data;
+- char buf[20];
+-
+- sprintf(buf, "%d\n", srctrl->tx_avg_rate_num);
+- return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
+-}
+-
+-static const struct file_operations sta_tx_avg_rate_num_ops = {
+- .read = sta_tx_avg_rate_num_read,
+- .open = open_file_generic,
+-};
+-
+-static void rate_control_simple_add_sta_debugfs(void *priv, void *priv_sta,
+- struct dentry *dir)
+-{
+- struct sta_rate_control *srctrl = priv_sta;
+-
+- srctrl->tx_avg_rate_num_dentry =
+- debugfs_create_file("rc_simple_sta_tx_avg_rate_num", 0400,
+- dir, srctrl, &sta_tx_avg_rate_num_ops);
+- srctrl->tx_avg_rate_sum_dentry =
+- debugfs_create_file("rc_simple_sta_tx_avg_rate_sum", 0400,
+- dir, srctrl, &sta_tx_avg_rate_sum_ops);
+-}
+-
+-static void rate_control_simple_remove_sta_debugfs(void *priv, void *priv_sta)
+-{
+- struct sta_rate_control *srctrl = priv_sta;
+-
+- debugfs_remove(srctrl->tx_avg_rate_sum_dentry);
+- debugfs_remove(srctrl->tx_avg_rate_num_dentry);
+-}
+-#endif
+-
+-static struct rate_control_ops mac80211_rcsimple = {
+- .name = "simple",
+- .tx_status = rate_control_simple_tx_status,
+- .get_rate = rate_control_simple_get_rate,
+- .rate_init = rate_control_simple_rate_init,
+- .clear = rate_control_simple_clear,
+- .alloc = rate_control_simple_alloc,
+- .free = rate_control_simple_free,
+- .alloc_sta = rate_control_simple_alloc_sta,
+- .free_sta = rate_control_simple_free_sta,
+-#ifdef CONFIG_MAC80211_DEBUGFS
+- .add_sta_debugfs = rate_control_simple_add_sta_debugfs,
+- .remove_sta_debugfs = rate_control_simple_remove_sta_debugfs,
+-#endif
+-};
+-
+-MODULE_LICENSE("GPL");
+-MODULE_DESCRIPTION("Simple rate control algorithm");
+-
+-int __init rc80211_simple_init(void)
+-{
+- return ieee80211_rate_control_register(&mac80211_rcsimple);
+-}
+-
+-void rc80211_simple_exit(void)
+-{
+- ieee80211_rate_control_unregister(&mac80211_rcsimple);
+-}
+-
+-#ifdef CONFIG_MAC80211_RC_SIMPLE_MODULE
+-module_init(rc80211_simple_init);
+-module_exit(rc80211_simple_exit);
+-#endif
+diff --git a/net/mac80211/regdomain.c b/net/mac80211/regdomain.c
+deleted file mode 100644
+index f42678f..0000000
+--- a/net/mac80211/regdomain.c
++++ /dev/null
+@@ -1,152 +0,0 @@
+-/*
+- * Copyright 2002-2005, Instant802 Networks, Inc.
+- * Copyright 2005-2006, Devicescape Software, Inc.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-/*
+- * This regulatory domain control implementation is known to be incomplete
+- * and confusing. mac80211 regulatory domain control will be significantly
+- * reworked in the not-too-distant future.
+- *
+- * For now, drivers wishing to control which channels are and aren't available
+- * are advised as follows:
+- * - set the IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED flag
+- * - continue to include *ALL* possible channels in the modes registered
+- * through ieee80211_register_hwmode()
+- * - for each allowable ieee80211_channel structure registered in the above
+- * call, set the flag member to some meaningful value such as
+- * IEEE80211_CHAN_W_SCAN | IEEE80211_CHAN_W_ACTIVE_SCAN |
+- * IEEE80211_CHAN_W_IBSS.
+- * - leave flag as 0 for non-allowable channels
+- *
+- * The usual implementation is for a driver to read a device EEPROM to
+- * determine which regulatory domain it should be operating under, then
+- * looking up the allowable channels in a driver-local table, then performing
+- * the above.
+- */
+-
+-#include <linux/module.h>
+-#include <linux/netdevice.h>
+-#include <net/mac80211.h>
+-#include "ieee80211_i.h"
+-
+-static int ieee80211_regdom = 0x10; /* FCC */
+-module_param(ieee80211_regdom, int, 0444);
+-MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain; 64=MKK");
+-
+-/*
+- * If firmware is upgraded by the vendor, additional channels can be used based
+- * on the new Japanese regulatory rules. This is indicated by setting
+- * ieee80211_japan_5ghz module parameter to one when loading the 80211 kernel
+- * module.
+- */
+-static int ieee80211_japan_5ghz /* = 0 */;
+-module_param(ieee80211_japan_5ghz, int, 0444);
+-MODULE_PARM_DESC(ieee80211_japan_5ghz, "Vendor-updated firmware for 5 GHz");
+-
+-
+-struct ieee80211_channel_range {
+- short start_freq;
+- short end_freq;
+- unsigned char power_level;
+- unsigned char antenna_max;
+-};
+-
+-static const struct ieee80211_channel_range ieee80211_fcc_channels[] = {
+- { 2412, 2462, 27, 6 } /* IEEE 802.11b/g, channels 1..11 */,
+- { 5180, 5240, 17, 6 } /* IEEE 802.11a, channels 36..48 */,
+- { 5260, 5320, 23, 6 } /* IEEE 802.11a, channels 52..64 */,
+- { 5745, 5825, 30, 6 } /* IEEE 802.11a, channels 149..165, outdoor */,
+- { 0 }
+-};
+-
+-static const struct ieee80211_channel_range ieee80211_mkk_channels[] = {
+- { 2412, 2472, 20, 6 } /* IEEE 802.11b/g, channels 1..13 */,
+- { 5170, 5240, 20, 6 } /* IEEE 802.11a, channels 34..48 */,
+- { 5260, 5320, 20, 6 } /* IEEE 802.11a, channels 52..64 */,
+- { 0 }
+-};
+-
+-
+-static const struct ieee80211_channel_range *channel_range =
+- ieee80211_fcc_channels;
+-
+-
+-static void ieee80211_unmask_channel(int mode, struct ieee80211_channel *chan)
+-{
+- int i;
+-
+- chan->flag = 0;
+-
+- for (i = 0; channel_range[i].start_freq; i++) {
+- const struct ieee80211_channel_range *r = &channel_range[i];
+- if (r->start_freq <= chan->freq && r->end_freq >= chan->freq) {
+- if (ieee80211_regdom == 64 && !ieee80211_japan_5ghz &&
+- chan->freq >= 5260 && chan->freq <= 5320) {
+- /*
+- * Skip new channels in Japan since the
+- * firmware was not marked having been upgraded
+- * by the vendor.
+- */
+- continue;
+- }
+-
+- if (ieee80211_regdom == 0x10 &&
+- (chan->freq == 5190 || chan->freq == 5210 ||
+- chan->freq == 5230)) {
+- /* Skip MKK channels when in FCC domain. */
+- continue;
+- }
+-
+- chan->flag |= IEEE80211_CHAN_W_SCAN |
+- IEEE80211_CHAN_W_ACTIVE_SCAN |
+- IEEE80211_CHAN_W_IBSS;
+- chan->power_level = r->power_level;
+- chan->antenna_max = r->antenna_max;
+-
+- if (ieee80211_regdom == 64 &&
+- (chan->freq == 5170 || chan->freq == 5190 ||
+- chan->freq == 5210 || chan->freq == 5230)) {
+- /*
+- * New regulatory rules in Japan have backwards
+- * compatibility with old channels in 5.15-5.25
+- * GHz band, but the station is not allowed to
+- * use active scan on these old channels.
+- */
+- chan->flag &= ~IEEE80211_CHAN_W_ACTIVE_SCAN;
+- }
+-
+- if (ieee80211_regdom == 64 &&
+- (chan->freq == 5260 || chan->freq == 5280 ||
+- chan->freq == 5300 || chan->freq == 5320)) {
+- /*
+- * IBSS is not allowed on 5.25-5.35 GHz band
+- * due to radar detection requirements.
+- */
+- chan->flag &= ~IEEE80211_CHAN_W_IBSS;
+- }
+-
+- break;
+- }
+- }
+-}
+-
+-
+-void ieee80211_set_default_regdomain(struct ieee80211_hw_mode *mode)
+-{
+- int c;
+- for (c = 0; c < mode->num_channels; c++)
+- ieee80211_unmask_channel(mode->mode, &mode->channels[c]);
+-}
+-
+-
+-void ieee80211_regdomain_init(void)
+-{
+- if (ieee80211_regdom == 0x40)
+- channel_range = ieee80211_mkk_channels;
+-}
+-
+diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
+index a8a40ab..02f436a 100644
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -9,6 +9,7 @@
+ * published by the Free Software Foundation.
+ */
+
++#include <linux/jiffies.h>
+ #include <linux/kernel.h>
+ #include <linux/skbuff.h>
+ #include <linux/netdevice.h>
+@@ -18,7 +19,8 @@
+ #include <net/ieee80211_radiotap.h>
+
+ #include "ieee80211_i.h"
+-#include "ieee80211_led.h"
++#include "led.h"
++#include "mesh.h"
+ #include "wep.h"
+ #include "wpa.h"
+ #include "tkip.h"
+@@ -82,10 +84,10 @@ static inline int should_drop_frame(struct ieee80211_rx_status *status,
+ */
+ static struct sk_buff *
+ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
+- struct ieee80211_rx_status *status)
++ struct ieee80211_rx_status *status,
++ struct ieee80211_rate *rate)
+ {
+ struct ieee80211_sub_if_data *sdata;
+- struct ieee80211_rate *rate;
+ int needed_headroom = 0;
+ struct ieee80211_radiotap_header *rthdr;
+ __le64 *rttsft = NULL;
+@@ -194,14 +196,11 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
+ rtfixed->rx_flags |=
+ cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADFCS);
+
+- rate = ieee80211_get_rate(local, status->phymode,
+- status->rate);
+- if (rate)
+- rtfixed->rate = rate->rate / 5;
++ rtfixed->rate = rate->bitrate / 5;
+
+ rtfixed->chan_freq = cpu_to_le16(status->freq);
+
+- if (status->phymode == MODE_IEEE80211A)
++ if (status->band == IEEE80211_BAND_5GHZ)
+ rtfixed->chan_flags =
+ cpu_to_le16(IEEE80211_CHAN_OFDM |
+ IEEE80211_CHAN_5GHZ);
+@@ -226,6 +225,9 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
+ if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR)
+ continue;
+
++ if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)
++ continue;
++
+ if (prev_dev) {
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ if (skb2) {
+@@ -249,15 +251,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
+ }
+
+
+-/* pre-rx handlers
+- *
+- * these don't have dev/sdata fields in the rx data
+- * The sta value should also not be used because it may
+- * be NULL even though a STA (in IBSS mode) will be added.
+- */
+-
+-static ieee80211_txrx_result
+-ieee80211_rx_h_parse_qos(struct ieee80211_txrx_data *rx)
++static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
+ {
+ u8 *data = rx->skb->data;
+ int tid;
+@@ -268,9 +262,9 @@ ieee80211_rx_h_parse_qos(struct ieee80211_txrx_data *rx)
+ /* frame has qos control */
+ tid = qc[0] & QOS_CONTROL_TID_MASK;
+ if (qc[0] & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
+- rx->flags |= IEEE80211_TXRXD_RX_AMSDU;
++ rx->flags |= IEEE80211_RX_AMSDU;
+ else
+- rx->flags &= ~IEEE80211_TXRXD_RX_AMSDU;
++ rx->flags &= ~IEEE80211_RX_AMSDU;
+ } else {
+ if (unlikely((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)) {
+ /* Separate TID for management frames */
+@@ -286,68 +280,19 @@ ieee80211_rx_h_parse_qos(struct ieee80211_txrx_data *rx)
+ if (rx->sta)
+ I802_DEBUG_INC(rx->sta->wme_rx_queue[tid]);
+
+- rx->u.rx.queue = tid;
++ rx->queue = tid;
+ /* Set skb->priority to 1d tag if highest order bit of TID is not set.
+ * For now, set skb->priority to 0 for other cases. */
+ rx->skb->priority = (tid > 7) ? 0 : tid;
+-
+- return TXRX_CONTINUE;
+ }
+
+-
+-static u32 ieee80211_rx_load_stats(struct ieee80211_local *local,
+- struct sk_buff *skb,
+- struct ieee80211_rx_status *status)
++static void ieee80211_verify_ip_alignment(struct ieee80211_rx_data *rx)
+ {
+- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+- u32 load = 0, hdrtime;
+- struct ieee80211_rate *rate;
+- struct ieee80211_hw_mode *mode = local->hw.conf.mode;
+- int i;
+-
+- /* Estimate total channel use caused by this frame */
+-
+- if (unlikely(mode->num_rates < 0))
+- return TXRX_CONTINUE;
+-
+- rate = &mode->rates[0];
+- for (i = 0; i < mode->num_rates; i++) {
+- if (mode->rates[i].val == status->rate) {
+- rate = &mode->rates[i];
+- break;
+- }
+- }
+-
+- /* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values,
+- * 1 usec = 1/8 * (1080 / 10) = 13.5 */
+-
+- if (mode->mode == MODE_IEEE80211A ||
+- (mode->mode == MODE_IEEE80211G &&
+- rate->flags & IEEE80211_RATE_ERP))
+- hdrtime = CHAN_UTIL_HDR_SHORT;
+- else
+- hdrtime = CHAN_UTIL_HDR_LONG;
+-
+- load = hdrtime;
+- if (!is_multicast_ether_addr(hdr->addr1))
+- load += hdrtime;
+-
+- load += skb->len * rate->rate_inv;
+-
+- /* Divide channel_use by 8 to avoid wrapping around the counter */
+- load >>= CHAN_UTIL_SHIFT;
+-
+- return load;
+-}
+-
+ #ifdef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT
+-static ieee80211_txrx_result
+-ieee80211_rx_h_verify_ip_alignment(struct ieee80211_txrx_data *rx)
+-{
+ int hdrlen;
+
+ if (!WLAN_FC_DATA_PRESENT(rx->fc))
+- return TXRX_CONTINUE;
++ return;
+
+ /*
+ * Drivers are required to align the payload data in a way that
+@@ -369,83 +314,158 @@ ieee80211_rx_h_verify_ip_alignment(struct ieee80211_txrx_data *rx)
+ * to move the 802.11 header further back in that case.
+ */
+ hdrlen = ieee80211_get_hdrlen(rx->fc);
+- if (rx->flags & IEEE80211_TXRXD_RX_AMSDU)
++ if (rx->flags & IEEE80211_RX_AMSDU)
+ hdrlen += ETH_HLEN;
+ WARN_ON_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3);
+-
+- return TXRX_CONTINUE;
+-}
+ #endif
++}
+
+-ieee80211_rx_handler ieee80211_rx_pre_handlers[] =
++
++static u32 ieee80211_rx_load_stats(struct ieee80211_local *local,
++ struct sk_buff *skb,
++ struct ieee80211_rx_status *status,
++ struct ieee80211_rate *rate)
+ {
+- ieee80211_rx_h_parse_qos,
+-#ifdef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT
+- ieee80211_rx_h_verify_ip_alignment,
+-#endif
+- NULL
+-};
++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
++ u32 load = 0, hdrtime;
++
++ /* Estimate total channel use caused by this frame */
++
++ /* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values,
++ * 1 usec = 1/8 * (1080 / 10) = 13.5 */
++
++ if (status->band == IEEE80211_BAND_5GHZ ||
++ (status->band == IEEE80211_BAND_5GHZ &&
++ rate->flags & IEEE80211_RATE_ERP_G))
++ hdrtime = CHAN_UTIL_HDR_SHORT;
++ else
++ hdrtime = CHAN_UTIL_HDR_LONG;
++
++ load = hdrtime;
++ if (!is_multicast_ether_addr(hdr->addr1))
++ load += hdrtime;
++
++ /* TODO: optimise again */
++ load += skb->len * CHAN_UTIL_RATE_LCM / rate->bitrate;
++
++ /* Divide channel_use by 8 to avoid wrapping around the counter */
++ load >>= CHAN_UTIL_SHIFT;
++
++ return load;
++}
+
+ /* rx handlers */
+
+-static ieee80211_txrx_result
+-ieee80211_rx_h_if_stats(struct ieee80211_txrx_data *rx)
++static ieee80211_rx_result
++ieee80211_rx_h_if_stats(struct ieee80211_rx_data *rx)
+ {
+ if (rx->sta)
+- rx->sta->channel_use_raw += rx->u.rx.load;
+- rx->sdata->channel_use_raw += rx->u.rx.load;
+- return TXRX_CONTINUE;
++ rx->sta->channel_use_raw += rx->load;
++ rx->sdata->channel_use_raw += rx->load;
++ return RX_CONTINUE;
+ }
+
+-static ieee80211_txrx_result
+-ieee80211_rx_h_passive_scan(struct ieee80211_txrx_data *rx)
++static ieee80211_rx_result
++ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
+ {
+ struct ieee80211_local *local = rx->local;
+ struct sk_buff *skb = rx->skb;
+
+ if (unlikely(local->sta_hw_scanning))
+- return ieee80211_sta_rx_scan(rx->dev, skb, rx->u.rx.status);
++ return ieee80211_sta_rx_scan(rx->dev, skb, rx->status);
+
+ if (unlikely(local->sta_sw_scanning)) {
+ /* drop all the other packets during a software scan anyway */
+- if (ieee80211_sta_rx_scan(rx->dev, skb, rx->u.rx.status)
+- != TXRX_QUEUED)
++ if (ieee80211_sta_rx_scan(rx->dev, skb, rx->status)
++ != RX_QUEUED)
+ dev_kfree_skb(skb);
+- return TXRX_QUEUED;
++ return RX_QUEUED;
+ }
+
+- if (unlikely(rx->flags & IEEE80211_TXRXD_RXIN_SCAN)) {
++ if (unlikely(rx->flags & IEEE80211_RX_IN_SCAN)) {
+ /* scanning finished during invoking of handlers */
+ I802_DEBUG_INC(local->rx_handlers_drop_passive_scan);
+- return TXRX_DROP;
++ return RX_DROP_UNUSABLE;
+ }
+
+- return TXRX_CONTINUE;
++ return RX_CONTINUE;
++}
++
++static ieee80211_rx_result
++ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
++{
++ int hdrlen = ieee80211_get_hdrlen(rx->fc);
++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
++
++#define msh_h_get(h, l) ((struct ieee80211s_hdr *) ((u8 *)h + l))
++
++ if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) {
++ if (!((rx->fc & IEEE80211_FCTL_FROMDS) &&
++ (rx->fc & IEEE80211_FCTL_TODS)))
++ return RX_DROP_MONITOR;
++ if (memcmp(hdr->addr4, rx->dev->dev_addr, ETH_ALEN) == 0)
++ return RX_DROP_MONITOR;
++ }
++
++ /* If there is not an established peer link and this is not a peer link
++ * establisment frame, beacon or probe, drop the frame.
++ */
++
++ if (!rx->sta || sta_plink_state(rx->sta) != PLINK_ESTAB) {
++ struct ieee80211_mgmt *mgmt;
++
++ if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT)
++ return RX_DROP_MONITOR;
++
++ switch (rx->fc & IEEE80211_FCTL_STYPE) {
++ case IEEE80211_STYPE_ACTION:
++ mgmt = (struct ieee80211_mgmt *)hdr;
++ if (mgmt->u.action.category != PLINK_CATEGORY)
++ return RX_DROP_MONITOR;
++ /* fall through on else */
++ case IEEE80211_STYPE_PROBE_REQ:
++ case IEEE80211_STYPE_PROBE_RESP:
++ case IEEE80211_STYPE_BEACON:
++ return RX_CONTINUE;
++ break;
++ default:
++ return RX_DROP_MONITOR;
++ }
++
++ } else if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
++ is_multicast_ether_addr(hdr->addr1) &&
++ mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->dev))
++ return RX_DROP_MONITOR;
++#undef msh_h_get
++
++ return RX_CONTINUE;
+ }
+
+-static ieee80211_txrx_result
+-ieee80211_rx_h_check(struct ieee80211_txrx_data *rx)
++
++static ieee80211_rx_result
++ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
+ {
+ struct ieee80211_hdr *hdr;
++
+ hdr = (struct ieee80211_hdr *) rx->skb->data;
+
+ /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */
+ if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) {
+ if (unlikely(rx->fc & IEEE80211_FCTL_RETRY &&
+- rx->sta->last_seq_ctrl[rx->u.rx.queue] ==
++ rx->sta->last_seq_ctrl[rx->queue] ==
+ hdr->seq_ctrl)) {
+- if (rx->flags & IEEE80211_TXRXD_RXRA_MATCH) {
++ if (rx->flags & IEEE80211_RX_RA_MATCH) {
+ rx->local->dot11FrameDuplicateCount++;
+ rx->sta->num_duplicates++;
+ }
+- return TXRX_DROP;
++ return RX_DROP_MONITOR;
+ } else
+- rx->sta->last_seq_ctrl[rx->u.rx.queue] = hdr->seq_ctrl;
++ rx->sta->last_seq_ctrl[rx->queue] = hdr->seq_ctrl;
+ }
+
+ if (unlikely(rx->skb->len < 16)) {
+ I802_DEBUG_INC(rx->local->rx_handlers_drop_short);
+- return TXRX_DROP;
++ return RX_DROP_MONITOR;
+ }
+
+ /* Drop disallowed frame classes based on STA auth/assoc state;
+@@ -456,6 +476,10 @@ ieee80211_rx_h_check(struct ieee80211_txrx_data *rx)
+ * deauth/disassoc frames when needed. In addition, hostapd is
+ * responsible for filtering on both auth and assoc states.
+ */
++
++ if (ieee80211_vif_is_mesh(&rx->sdata->vif))
++ return ieee80211_rx_mesh_check(rx);
++
+ if (unlikely(((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA ||
+ ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL &&
+ (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)) &&
+@@ -464,26 +488,26 @@ ieee80211_rx_h_check(struct ieee80211_txrx_data *rx)
+ if ((!(rx->fc & IEEE80211_FCTL_FROMDS) &&
+ !(rx->fc & IEEE80211_FCTL_TODS) &&
+ (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)
+- || !(rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) {
++ || !(rx->flags & IEEE80211_RX_RA_MATCH)) {
+ /* Drop IBSS frames and frames for other hosts
+ * silently. */
+- return TXRX_DROP;
++ return RX_DROP_MONITOR;
+ }
+
+- return TXRX_DROP;
++ return RX_DROP_MONITOR;
+ }
+
+- return TXRX_CONTINUE;
++ return RX_CONTINUE;
+ }
+
+
+-static ieee80211_txrx_result
+-ieee80211_rx_h_decrypt(struct ieee80211_txrx_data *rx)
++static ieee80211_rx_result
++ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
+ {
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
+ int keyidx;
+ int hdrlen;
+- ieee80211_txrx_result result = TXRX_DROP;
++ ieee80211_rx_result result = RX_DROP_UNUSABLE;
+ struct ieee80211_key *stakey = NULL;
+
+ /*
+@@ -513,14 +537,14 @@ ieee80211_rx_h_decrypt(struct ieee80211_txrx_data *rx)
+ */
+
+ if (!(rx->fc & IEEE80211_FCTL_PROTECTED))
+- return TXRX_CONTINUE;
++ return RX_CONTINUE;
+
+ /*
+ * No point in finding a key and decrypting if the frame is neither
+ * addressed to us nor a multicast frame.
+ */
+- if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
+- return TXRX_CONTINUE;
++ if (!(rx->flags & IEEE80211_RX_RA_MATCH))
++ return RX_CONTINUE;
+
+ if (rx->sta)
+ stakey = rcu_dereference(rx->sta->key);
+@@ -537,14 +561,14 @@ ieee80211_rx_h_decrypt(struct ieee80211_txrx_data *rx)
+ * we somehow allow the driver to tell us which key
+ * the hardware used if this flag is set?
+ */
+- if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
+- (rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED))
+- return TXRX_CONTINUE;
++ if ((rx->status->flag & RX_FLAG_DECRYPTED) &&
++ (rx->status->flag & RX_FLAG_IV_STRIPPED))
++ return RX_CONTINUE;
+
+ hdrlen = ieee80211_get_hdrlen(rx->fc);
+
+ if (rx->skb->len < 8 + hdrlen)
+- return TXRX_DROP; /* TODO: count this? */
++ return RX_DROP_UNUSABLE; /* TODO: count this? */
+
+ /*
+ * no need to call ieee80211_wep_get_keyidx,
+@@ -573,14 +597,14 @@ ieee80211_rx_h_decrypt(struct ieee80211_txrx_data *rx)
+ printk(KERN_DEBUG "%s: RX protected frame,"
+ " but have no key\n", rx->dev->name);
+ #endif /* CONFIG_MAC80211_DEBUG */
+- return TXRX_DROP;
++ return RX_DROP_MONITOR;
+ }
+
+ /* Check for weak IVs if possible */
+ if (rx->sta && rx->key->conf.alg == ALG_WEP &&
+ ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
+- (!(rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED) ||
+- !(rx->u.rx.status->flag & RX_FLAG_DECRYPTED)) &&
++ (!(rx->status->flag & RX_FLAG_IV_STRIPPED) ||
++ !(rx->status->flag & RX_FLAG_DECRYPTED)) &&
+ ieee80211_wep_is_weak_iv(rx->skb, rx->key))
+ rx->sta->wep_weak_iv_count++;
+
+@@ -597,7 +621,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_txrx_data *rx)
+ }
+
+ /* either the frame has been decrypted or will be dropped */
+- rx->u.rx.status->flag |= RX_FLAG_DECRYPTED;
++ rx->status->flag |= RX_FLAG_DECRYPTED;
+
+ return result;
+ }
+@@ -607,12 +631,12 @@ static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta)
+ struct ieee80211_sub_if_data *sdata;
+ DECLARE_MAC_BUF(mac);
+
+- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
++ sdata = sta->sdata;
+
+ if (sdata->bss)
+ atomic_inc(&sdata->bss->num_sta_ps);
+ sta->flags |= WLAN_STA_PS;
+- sta->pspoll = 0;
++ sta->flags &= ~WLAN_STA_PSPOLL;
+ #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+ printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n",
+ dev->name, print_mac(mac, sta->addr), sta->aid);
+@@ -628,21 +652,21 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
+ struct ieee80211_tx_packet_data *pkt_data;
+ DECLARE_MAC_BUF(mac);
+
+- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
++ sdata = sta->sdata;
++
+ if (sdata->bss)
+ atomic_dec(&sdata->bss->num_sta_ps);
+- sta->flags &= ~(WLAN_STA_PS | WLAN_STA_TIM);
+- sta->pspoll = 0;
+- if (!skb_queue_empty(&sta->ps_tx_buf)) {
+- if (local->ops->set_tim)
+- local->ops->set_tim(local_to_hw(local), sta->aid, 0);
+- if (sdata->bss)
+- bss_tim_clear(local, sdata->bss, sta->aid);
+- }
++
++ sta->flags &= ~(WLAN_STA_PS | WLAN_STA_PSPOLL);
++
++ if (!skb_queue_empty(&sta->ps_tx_buf))
++ sta_info_clear_tim_bit(sta);
++
+ #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+ printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n",
+ dev->name, print_mac(mac, sta->addr), sta->aid);
+ #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
++
+ /* Send all buffered frames to the station */
+ while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
+ pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
+@@ -666,15 +690,15 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
+ return sent;
+ }
+
+-static ieee80211_txrx_result
+-ieee80211_rx_h_sta_process(struct ieee80211_txrx_data *rx)
++static ieee80211_rx_result
++ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
+ {
+ struct sta_info *sta = rx->sta;
+ struct net_device *dev = rx->dev;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
+
+ if (!sta)
+- return TXRX_CONTINUE;
++ return RX_CONTINUE;
+
+ /* Update last_rx only for IBSS packets which are for the current
+ * BSSID to avoid keeping the current IBSS network alive in cases where
+@@ -690,24 +714,26 @@ ieee80211_rx_h_sta_process(struct ieee80211_txrx_data *rx)
+ /* Update last_rx only for unicast frames in order to prevent
+ * the Probe Request frames (the only broadcast frames from a
+ * STA in infrastructure mode) from keeping a connection alive.
++ * Mesh beacons will update last_rx when if they are found to
++ * match the current local configuration when processed.
+ */
+ sta->last_rx = jiffies;
+ }
+
+- if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
+- return TXRX_CONTINUE;
++ if (!(rx->flags & IEEE80211_RX_RA_MATCH))
++ return RX_CONTINUE;
+
+ sta->rx_fragments++;
+ sta->rx_bytes += rx->skb->len;
+- sta->last_rssi = rx->u.rx.status->ssi;
+- sta->last_signal = rx->u.rx.status->signal;
+- sta->last_noise = rx->u.rx.status->noise;
++ sta->last_rssi = rx->status->ssi;
++ sta->last_signal = rx->status->signal;
++ sta->last_noise = rx->status->noise;
+
+ if (!(rx->fc & IEEE80211_FCTL_MOREFRAGS)) {
+ /* Change STA power saving mode only in the end of a frame
+ * exchange sequence */
+ if ((sta->flags & WLAN_STA_PS) && !(rx->fc & IEEE80211_FCTL_PM))
+- rx->u.rx.sent_ps_buffered += ap_sta_ps_end(dev, sta);
++ rx->sent_ps_buffered += ap_sta_ps_end(dev, sta);
+ else if (!(sta->flags & WLAN_STA_PS) &&
+ (rx->fc & IEEE80211_FCTL_PM))
+ ap_sta_ps_start(dev, sta);
+@@ -722,10 +748,10 @@ ieee80211_rx_h_sta_process(struct ieee80211_txrx_data *rx)
+ * as a dropped packed. */
+ sta->rx_packets++;
+ dev_kfree_skb(rx->skb);
+- return TXRX_QUEUED;
++ return RX_QUEUED;
+ }
+
+- return TXRX_CONTINUE;
++ return RX_CONTINUE;
+ } /* ieee80211_rx_h_sta_process */
+
+ static inline struct ieee80211_fragment_entry *
+@@ -801,7 +827,7 @@ ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata,
+ compare_ether_addr(hdr->addr2, f_hdr->addr2) != 0)
+ continue;
+
+- if (entry->first_frag_time + 2 * HZ < jiffies) {
++ if (time_after(jiffies, entry->first_frag_time + 2 * HZ)) {
+ __skb_queue_purge(&entry->skb_list);
+ continue;
+ }
+@@ -811,8 +837,8 @@ ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata,
+ return NULL;
+ }
+
+-static ieee80211_txrx_result
+-ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx)
++static ieee80211_rx_result
++ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
+ {
+ struct ieee80211_hdr *hdr;
+ u16 sc;
+@@ -838,27 +864,27 @@ ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx)
+ if (frag == 0) {
+ /* This is the first fragment of a new frame. */
+ entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
+- rx->u.rx.queue, &(rx->skb));
++ rx->queue, &(rx->skb));
+ if (rx->key && rx->key->conf.alg == ALG_CCMP &&
+ (rx->fc & IEEE80211_FCTL_PROTECTED)) {
+ /* Store CCMP PN so that we can verify that the next
+ * fragment has a sequential PN value. */
+ entry->ccmp = 1;
+ memcpy(entry->last_pn,
+- rx->key->u.ccmp.rx_pn[rx->u.rx.queue],
++ rx->key->u.ccmp.rx_pn[rx->queue],
+ CCMP_PN_LEN);
+ }
+- return TXRX_QUEUED;
++ return RX_QUEUED;
+ }
+
+ /* This is a fragment for a frame that should already be pending in
+ * fragment cache. Add this fragment to the end of the pending entry.
+ */
+ entry = ieee80211_reassemble_find(rx->sdata, rx->fc, frag, seq,
+- rx->u.rx.queue, hdr);
++ rx->queue, hdr);
+ if (!entry) {
+ I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
+- return TXRX_DROP;
++ return RX_DROP_MONITOR;
+ }
+
+ /* Verify that MPDUs within one MSDU have sequential PN values.
+@@ -867,14 +893,14 @@ ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx)
+ int i;
+ u8 pn[CCMP_PN_LEN], *rpn;
+ if (!rx->key || rx->key->conf.alg != ALG_CCMP)
+- return TXRX_DROP;
++ return RX_DROP_UNUSABLE;
+ memcpy(pn, entry->last_pn, CCMP_PN_LEN);
+ for (i = CCMP_PN_LEN - 1; i >= 0; i--) {
+ pn[i]++;
+ if (pn[i])
+ break;
+ }
+- rpn = rx->key->u.ccmp.rx_pn[rx->u.rx.queue];
++ rpn = rx->key->u.ccmp.rx_pn[rx->queue];
+ if (memcmp(pn, rpn, CCMP_PN_LEN) != 0) {
+ if (net_ratelimit())
+ printk(KERN_DEBUG "%s: defrag: CCMP PN not "
+@@ -885,7 +911,7 @@ ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx)
+ rpn[0], rpn[1], rpn[2], rpn[3], rpn[4],
+ rpn[5], pn[0], pn[1], pn[2], pn[3],
+ pn[4], pn[5]);
+- return TXRX_DROP;
++ return RX_DROP_UNUSABLE;
+ }
+ memcpy(entry->last_pn, pn, CCMP_PN_LEN);
+ }
+@@ -896,7 +922,7 @@ ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx)
+ entry->extra_len += rx->skb->len;
+ if (rx->fc & IEEE80211_FCTL_MOREFRAGS) {
+ rx->skb = NULL;
+- return TXRX_QUEUED;
++ return RX_QUEUED;
+ }
+
+ rx->skb = __skb_dequeue(&entry->skb_list);
+@@ -906,7 +932,7 @@ ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx)
+ GFP_ATOMIC))) {
+ I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
+ __skb_queue_purge(&entry->skb_list);
+- return TXRX_DROP;
++ return RX_DROP_UNUSABLE;
+ }
+ }
+ while ((skb = __skb_dequeue(&entry->skb_list))) {
+@@ -915,7 +941,7 @@ ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx)
+ }
+
+ /* Complete frame has been reassembled - process it now */
+- rx->flags |= IEEE80211_TXRXD_FRAGMENTED;
++ rx->flags |= IEEE80211_RX_FRAGMENTED;
+
+ out:
+ if (rx->sta)
+@@ -924,11 +950,11 @@ ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx)
+ rx->local->dot11MulticastReceivedFrameCount++;
+ else
+ ieee80211_led_rx(rx->local);
+- return TXRX_CONTINUE;
++ return RX_CONTINUE;
+ }
+
+-static ieee80211_txrx_result
+-ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx)
++static ieee80211_rx_result
++ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
+ {
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
+ struct sk_buff *skb;
+@@ -938,12 +964,12 @@ ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx)
+ if (likely(!rx->sta ||
+ (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_CTL ||
+ (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PSPOLL ||
+- !(rx->flags & IEEE80211_TXRXD_RXRA_MATCH)))
+- return TXRX_CONTINUE;
++ !(rx->flags & IEEE80211_RX_RA_MATCH)))
++ return RX_CONTINUE;
+
+ if ((sdata->vif.type != IEEE80211_IF_TYPE_AP) &&
+ (sdata->vif.type != IEEE80211_IF_TYPE_VLAN))
+- return TXRX_DROP;
++ return RX_DROP_UNUSABLE;
+
+ skb = skb_dequeue(&rx->sta->tx_filtered);
+ if (!skb) {
+@@ -958,9 +984,11 @@ ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx)
+ struct ieee80211_hdr *hdr =
+ (struct ieee80211_hdr *) skb->data;
+
+- /* tell TX path to send one frame even though the STA may
+- * still remain is PS mode after this frame exchange */
+- rx->sta->pspoll = 1;
++ /*
++ * Tell TX path to send one frame even though the STA may
++ * still remain is PS mode after this frame exchange.
++ */
++ rx->sta->flags |= WLAN_STA_PSPOLL;
+
+ #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+ printk(KERN_DEBUG "STA %s aid %d: PS Poll (entries after %d)\n",
+@@ -970,46 +998,45 @@ ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx)
+
+ /* Use MoreData flag to indicate whether there are more
+ * buffered frames for this STA */
+- if (no_pending_pkts) {
++ if (no_pending_pkts)
+ hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREDATA);
+- rx->sta->flags &= ~WLAN_STA_TIM;
+- } else
++ else
+ hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+
+ dev_queue_xmit(skb);
+
+- if (no_pending_pkts) {
+- if (rx->local->ops->set_tim)
+- rx->local->ops->set_tim(local_to_hw(rx->local),
+- rx->sta->aid, 0);
+- if (rx->sdata->bss)
+- bss_tim_clear(rx->local, rx->sdata->bss, rx->sta->aid);
+- }
++ if (no_pending_pkts)
++ sta_info_clear_tim_bit(rx->sta);
+ #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+- } else if (!rx->u.rx.sent_ps_buffered) {
++ } else if (!rx->sent_ps_buffered) {
++ /*
++ * FIXME: This can be the result of a race condition between
++ * us expiring a frame and the station polling for it.
++ * Should we send it a null-func frame indicating we
++ * have nothing buffered for it?
++ */
+ printk(KERN_DEBUG "%s: STA %s sent PS Poll even "
+ "though there is no buffered frames for it\n",
+ rx->dev->name, print_mac(mac, rx->sta->addr));
+ #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+-
+ }
+
+- /* Free PS Poll skb here instead of returning TXRX_DROP that would
++ /* Free PS Poll skb here instead of returning RX_DROP that would
+ * count as an dropped frame. */
+ dev_kfree_skb(rx->skb);
+
+- return TXRX_QUEUED;
++ return RX_QUEUED;
+ }
+
+-static ieee80211_txrx_result
+-ieee80211_rx_h_remove_qos_control(struct ieee80211_txrx_data *rx)
++static ieee80211_rx_result
++ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx)
+ {
+ u16 fc = rx->fc;
+ u8 *data = rx->skb->data;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) data;
+
+ if (!WLAN_FC_IS_QOS_DATA(fc))
+- return TXRX_CONTINUE;
++ return RX_CONTINUE;
+
+ /* remove the qos control field, update frame type and meta-data */
+ memmove(data + 2, data, ieee80211_get_hdrlen(fc) - 2);
+@@ -1018,17 +1045,17 @@ ieee80211_rx_h_remove_qos_control(struct ieee80211_txrx_data *rx)
+ rx->fc = fc &= ~IEEE80211_STYPE_QOS_DATA;
+ hdr->frame_control = cpu_to_le16(fc);
+
+- return TXRX_CONTINUE;
++ return RX_CONTINUE;
+ }
+
+ static int
+-ieee80211_802_1x_port_control(struct ieee80211_txrx_data *rx)
++ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx)
+ {
+- if (unlikely(rx->sdata->ieee802_1x_pac &&
+- (!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED)))) {
++ if (unlikely(!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED))) {
+ #ifdef CONFIG_MAC80211_DEBUG
+- printk(KERN_DEBUG "%s: dropped frame "
+- "(unauthorized port)\n", rx->dev->name);
++ if (net_ratelimit())
++ printk(KERN_DEBUG "%s: dropped frame "
++ "(unauthorized port)\n", rx->dev->name);
+ #endif /* CONFIG_MAC80211_DEBUG */
+ return -EACCES;
+ }
+@@ -1037,13 +1064,13 @@ ieee80211_802_1x_port_control(struct ieee80211_txrx_data *rx)
+ }
+
+ static int
+-ieee80211_drop_unencrypted(struct ieee80211_txrx_data *rx)
++ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx)
+ {
+ /*
+ * Pass through unencrypted frames if the hardware has
+ * decrypted them already.
+ */
+- if (rx->u.rx.status->flag & RX_FLAG_DECRYPTED)
++ if (rx->status->flag & RX_FLAG_DECRYPTED)
+ return 0;
+
+ /* Drop unencrypted frames if key is set. */
+@@ -1057,7 +1084,7 @@ ieee80211_drop_unencrypted(struct ieee80211_txrx_data *rx)
+ }
+
+ static int
+-ieee80211_data_to_8023(struct ieee80211_txrx_data *rx)
++ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
+ {
+ struct net_device *dev = rx->dev;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
+@@ -1079,6 +1106,21 @@ ieee80211_data_to_8023(struct ieee80211_txrx_data *rx)
+
+ hdrlen = ieee80211_get_hdrlen(fc);
+
++ if (ieee80211_vif_is_mesh(&sdata->vif)) {
++ int meshhdrlen = ieee80211_get_mesh_hdrlen(
++ (struct ieee80211s_hdr *) (skb->data + hdrlen));
++ /* Copy on cb:
++ * - mesh header: to be used for mesh forwarding
++ * decision. It will also be used as mesh header template at
++ * tx.c:ieee80211_subif_start_xmit() if interface
++ * type is mesh and skb->pkt_type == PACKET_OTHERHOST
++ * - ta: to be used if a RERR needs to be sent.
++ */
++ memcpy(skb->cb, skb->data + hdrlen, meshhdrlen);
++ memcpy(MESH_PREQ(skb), hdr->addr2, ETH_ALEN);
++ hdrlen += meshhdrlen;
++ }
++
+ /* convert IEEE 802.11 header + possible LLC headers into Ethernet
+ * header
+ * IEEE 802.11 address fields:
+@@ -1112,9 +1154,10 @@ ieee80211_data_to_8023(struct ieee80211_txrx_data *rx)
+ memcpy(dst, hdr->addr3, ETH_ALEN);
+ memcpy(src, hdr->addr4, ETH_ALEN);
+
+- if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_WDS)) {
+- if (net_ratelimit())
+- printk(KERN_DEBUG "%s: dropped FromDS&ToDS "
++ if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_WDS &&
++ sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)) {
++ if (net_ratelimit())
++ printk(KERN_DEBUG "%s: dropped FromDS&ToDS "
+ "frame (RA=%s TA=%s DA=%s SA=%s)\n",
+ rx->dev->name,
+ print_mac(mac, hdr->addr1),
+@@ -1189,7 +1232,7 @@ ieee80211_data_to_8023(struct ieee80211_txrx_data *rx)
+ /*
+ * requires that rx->skb is a frame with ethernet header
+ */
+-static bool ieee80211_frame_allowed(struct ieee80211_txrx_data *rx)
++static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx)
+ {
+ static const u8 pae_group_addr[ETH_ALEN]
+ = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x03 };
+@@ -1215,7 +1258,7 @@ static bool ieee80211_frame_allowed(struct ieee80211_txrx_data *rx)
+ * requires that rx->skb is a frame with ethernet header
+ */
+ static void
+-ieee80211_deliver_skb(struct ieee80211_txrx_data *rx)
++ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
+ {
+ struct net_device *dev = rx->dev;
+ struct ieee80211_local *local = rx->local;
+@@ -1229,7 +1272,7 @@ ieee80211_deliver_skb(struct ieee80211_txrx_data *rx)
+
+ if (local->bridge_packets && (sdata->vif.type == IEEE80211_IF_TYPE_AP ||
+ sdata->vif.type == IEEE80211_IF_TYPE_VLAN) &&
+- (rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) {
++ (rx->flags & IEEE80211_RX_RA_MATCH)) {
+ if (is_multicast_ether_addr(ehdr->h_dest)) {
+ /*
+ * send multicast frames both to higher layers in
+@@ -1241,7 +1284,7 @@ ieee80211_deliver_skb(struct ieee80211_txrx_data *rx)
+ "multicast frame\n", dev->name);
+ } else {
+ dsta = sta_info_get(local, skb->data);
+- if (dsta && dsta->dev == dev) {
++ if (dsta && dsta->sdata->dev == dev) {
+ /*
+ * The destination station is associated to
+ * this AP (in this VLAN), so send the frame
+@@ -1251,8 +1294,38 @@ ieee80211_deliver_skb(struct ieee80211_txrx_data *rx)
+ xmit_skb = skb;
+ skb = NULL;
+ }
+- if (dsta)
+- sta_info_put(dsta);
++ }
++ }
++
++ /* Mesh forwarding */
++ if (ieee80211_vif_is_mesh(&sdata->vif)) {
++ u8 *mesh_ttl = &((struct ieee80211s_hdr *)skb->cb)->ttl;
++ (*mesh_ttl)--;
++
++ if (is_multicast_ether_addr(skb->data)) {
++ if (*mesh_ttl > 0) {
++ xmit_skb = skb_copy(skb, GFP_ATOMIC);
++ if (!xmit_skb && net_ratelimit())
++ printk(KERN_DEBUG "%s: failed to clone "
++ "multicast frame\n", dev->name);
++ else
++ xmit_skb->pkt_type = PACKET_OTHERHOST;
++ } else
++ IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.sta,
++ dropped_frames_ttl);
++ } else if (skb->pkt_type != PACKET_OTHERHOST &&
++ compare_ether_addr(dev->dev_addr, skb->data) != 0) {
++ if (*mesh_ttl == 0) {
++ IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.sta,
++ dropped_frames_ttl);
++ dev_kfree_skb(skb);
++ skb = NULL;
++ } else {
++ xmit_skb = skb;
++ xmit_skb->pkt_type = PACKET_OTHERHOST;
++ if (!(dev->flags & IFF_PROMISC))
++ skb = NULL;
++ }
+ }
+ }
+
+@@ -1272,8 +1345,8 @@ ieee80211_deliver_skb(struct ieee80211_txrx_data *rx)
+ }
+ }
+
+-static ieee80211_txrx_result
+-ieee80211_rx_h_amsdu(struct ieee80211_txrx_data *rx)
++static ieee80211_rx_result
++ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
+ {
+ struct net_device *dev = rx->dev;
+ struct ieee80211_local *local = rx->local;
+@@ -1288,17 +1361,17 @@ ieee80211_rx_h_amsdu(struct ieee80211_txrx_data *rx)
+
+ fc = rx->fc;
+ if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA))
+- return TXRX_CONTINUE;
++ return RX_CONTINUE;
+
+ if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
+- return TXRX_DROP;
++ return RX_DROP_MONITOR;
+
+- if (!(rx->flags & IEEE80211_TXRXD_RX_AMSDU))
+- return TXRX_CONTINUE;
++ if (!(rx->flags & IEEE80211_RX_AMSDU))
++ return RX_CONTINUE;
+
+ err = ieee80211_data_to_8023(rx);
+ if (unlikely(err))
+- return TXRX_DROP;
++ return RX_DROP_UNUSABLE;
+
+ skb->dev = dev;
+
+@@ -1308,7 +1381,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_txrx_data *rx)
+ /* skip the wrapping header */
+ eth = (struct ethhdr *) skb_pull(skb, sizeof(struct ethhdr));
+ if (!eth)
+- return TXRX_DROP;
++ return RX_DROP_UNUSABLE;
+
+ while (skb != frame) {
+ u8 padding;
+@@ -1323,7 +1396,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_txrx_data *rx)
+ /* the last MSDU has no padding */
+ if (subframe_len > remaining) {
+ printk(KERN_DEBUG "%s: wrong buffer size", dev->name);
+- return TXRX_DROP;
++ return RX_DROP_UNUSABLE;
+ }
+
+ skb_pull(skb, sizeof(struct ethhdr));
+@@ -1335,7 +1408,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_txrx_data *rx)
+ subframe_len);
+
+ if (frame == NULL)
+- return TXRX_DROP;
++ return RX_DROP_UNUSABLE;
+
+ skb_reserve(frame, local->hw.extra_tx_headroom +
+ sizeof(struct ethhdr));
+@@ -1348,7 +1421,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_txrx_data *rx)
+ printk(KERN_DEBUG "%s: wrong buffer size ",
+ dev->name);
+ dev_kfree_skb(frame);
+- return TXRX_DROP;
++ return RX_DROP_UNUSABLE;
+ }
+ }
+
+@@ -1378,7 +1451,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_txrx_data *rx)
+
+ if (!ieee80211_frame_allowed(rx)) {
+ if (skb == frame) /* last frame */
+- return TXRX_DROP;
++ return RX_DROP_UNUSABLE;
+ dev_kfree_skb(frame);
+ continue;
+ }
+@@ -1386,11 +1459,11 @@ ieee80211_rx_h_amsdu(struct ieee80211_txrx_data *rx)
+ ieee80211_deliver_skb(rx);
+ }
+
+- return TXRX_QUEUED;
++ return RX_QUEUED;
+ }
+
+-static ieee80211_txrx_result
+-ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
++static ieee80211_rx_result
++ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
+ {
+ struct net_device *dev = rx->dev;
+ u16 fc;
+@@ -1398,17 +1471,17 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
+
+ fc = rx->fc;
+ if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA))
+- return TXRX_CONTINUE;
++ return RX_CONTINUE;
+
+ if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
+- return TXRX_DROP;
++ return RX_DROP_MONITOR;
+
+ err = ieee80211_data_to_8023(rx);
+ if (unlikely(err))
+- return TXRX_DROP;
++ return RX_DROP_UNUSABLE;
+
+ if (!ieee80211_frame_allowed(rx))
+- return TXRX_DROP;
++ return RX_DROP_MONITOR;
+
+ rx->skb->dev = dev;
+
+@@ -1417,11 +1490,11 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
+
+ ieee80211_deliver_skb(rx);
+
+- return TXRX_QUEUED;
++ return RX_QUEUED;
+ }
+
+-static ieee80211_txrx_result
+-ieee80211_rx_h_ctrl(struct ieee80211_txrx_data *rx)
++static ieee80211_rx_result
++ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
+ {
+ struct ieee80211_local *local = rx->local;
+ struct ieee80211_hw *hw = &local->hw;
+@@ -1432,15 +1505,16 @@ ieee80211_rx_h_ctrl(struct ieee80211_txrx_data *rx)
+ u16 tid;
+
+ if (likely((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_CTL))
+- return TXRX_CONTINUE;
++ return RX_CONTINUE;
+
+ if ((rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BACK_REQ) {
+ if (!rx->sta)
+- return TXRX_CONTINUE;
++ return RX_CONTINUE;
+ tid = le16_to_cpu(bar->control) >> 12;
+- tid_agg_rx = &(rx->sta->ampdu_mlme.tid_rx[tid]);
+- if (tid_agg_rx->state != HT_AGG_STATE_OPERATIONAL)
+- return TXRX_CONTINUE;
++ if (rx->sta->ampdu_mlme.tid_state_rx[tid]
++ != HT_AGG_STATE_OPERATIONAL)
++ return RX_CONTINUE;
++ tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid];
+
+ start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4;
+
+@@ -1457,77 +1531,35 @@ ieee80211_rx_h_ctrl(struct ieee80211_txrx_data *rx)
+ ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, NULL,
+ start_seq_num, 1);
+ rcu_read_unlock();
+- return TXRX_DROP;
++ return RX_DROP_UNUSABLE;
+ }
+
+- return TXRX_CONTINUE;
++ return RX_CONTINUE;
+ }
+
+-static ieee80211_txrx_result
+-ieee80211_rx_h_mgmt(struct ieee80211_txrx_data *rx)
++static ieee80211_rx_result
++ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
+ {
+ struct ieee80211_sub_if_data *sdata;
+
+- if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
+- return TXRX_DROP;
++ if (!(rx->flags & IEEE80211_RX_RA_MATCH))
++ return RX_DROP_MONITOR;
+
+ sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
+ if ((sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+- sdata->vif.type == IEEE80211_IF_TYPE_IBSS) &&
++ sdata->vif.type == IEEE80211_IF_TYPE_IBSS ||
++ sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) &&
+ !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME))
+- ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status);
++ ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->status);
+ else
+- return TXRX_DROP;
++ return RX_DROP_MONITOR;
+
+- return TXRX_QUEUED;
+-}
+-
+-static inline ieee80211_txrx_result __ieee80211_invoke_rx_handlers(
+- struct ieee80211_local *local,
+- ieee80211_rx_handler *handlers,
+- struct ieee80211_txrx_data *rx,
+- struct sta_info *sta)
+-{
+- ieee80211_rx_handler *handler;
+- ieee80211_txrx_result res = TXRX_DROP;
+-
+- for (handler = handlers; *handler != NULL; handler++) {
+- res = (*handler)(rx);
+-
+- switch (res) {
+- case TXRX_CONTINUE:
+- continue;
+- case TXRX_DROP:
+- I802_DEBUG_INC(local->rx_handlers_drop);
+- if (sta)
+- sta->rx_dropped++;
+- break;
+- case TXRX_QUEUED:
+- I802_DEBUG_INC(local->rx_handlers_queued);
+- break;
+- }
+- break;
+- }
+-
+- if (res == TXRX_DROP)
+- dev_kfree_skb(rx->skb);
+- return res;
+-}
+-
+-static inline void ieee80211_invoke_rx_handlers(struct ieee80211_local *local,
+- ieee80211_rx_handler *handlers,
+- struct ieee80211_txrx_data *rx,
+- struct sta_info *sta)
+-{
+- if (__ieee80211_invoke_rx_handlers(local, handlers, rx, sta) ==
+- TXRX_CONTINUE)
+- dev_kfree_skb(rx->skb);
++ return RX_QUEUED;
+ }
+
+ static void ieee80211_rx_michael_mic_report(struct net_device *dev,
+ struct ieee80211_hdr *hdr,
+- struct sta_info *sta,
+- struct ieee80211_txrx_data *rx)
++ struct ieee80211_rx_data *rx)
+ {
+ int keyidx, hdrlen;
+ DECLARE_MAC_BUF(mac);
+@@ -1545,7 +1577,7 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev,
+ dev->name, print_mac(mac, hdr->addr2),
+ print_mac(mac2, hdr->addr1), keyidx);
+
+- if (!sta) {
++ if (!rx->sta) {
+ /*
+ * Some hardware seem to generate incorrect Michael MIC
+ * reports; ignore them to avoid triggering countermeasures.
+@@ -1597,7 +1629,89 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev,
+ rx->skb = NULL;
+ }
+
+-ieee80211_rx_handler ieee80211_rx_handlers[] =
++/* TODO: use IEEE80211_RX_FRAGMENTED */
++static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx)
++{
++ struct ieee80211_sub_if_data *sdata;
++ struct ieee80211_local *local = rx->local;
++ struct ieee80211_rtap_hdr {
++ struct ieee80211_radiotap_header hdr;
++ u8 flags;
++ u8 rate;
++ __le16 chan_freq;
++ __le16 chan_flags;
++ } __attribute__ ((packed)) *rthdr;
++ struct sk_buff *skb = rx->skb, *skb2;
++ struct net_device *prev_dev = NULL;
++ struct ieee80211_rx_status *status = rx->status;
++
++ if (rx->flags & IEEE80211_RX_CMNTR_REPORTED)
++ goto out_free_skb;
++
++ if (skb_headroom(skb) < sizeof(*rthdr) &&
++ pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC))
++ goto out_free_skb;
++
++ rthdr = (void *)skb_push(skb, sizeof(*rthdr));
++ memset(rthdr, 0, sizeof(*rthdr));
++ rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr));
++ rthdr->hdr.it_present =
++ cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
++ (1 << IEEE80211_RADIOTAP_RATE) |
++ (1 << IEEE80211_RADIOTAP_CHANNEL));
++
++ rthdr->rate = rx->rate->bitrate / 5;
++ rthdr->chan_freq = cpu_to_le16(status->freq);
++
++ if (status->band == IEEE80211_BAND_5GHZ)
++ rthdr->chan_flags = cpu_to_le16(IEEE80211_CHAN_OFDM |
++ IEEE80211_CHAN_5GHZ);
++ else
++ rthdr->chan_flags = cpu_to_le16(IEEE80211_CHAN_DYN |
++ IEEE80211_CHAN_2GHZ);
++
++ skb_set_mac_header(skb, 0);
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++ skb->pkt_type = PACKET_OTHERHOST;
++ skb->protocol = htons(ETH_P_802_2);
++
++ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
++ if (!netif_running(sdata->dev))
++ continue;
++
++ if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR ||
++ !(sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES))
++ continue;
++
++ if (prev_dev) {
++ skb2 = skb_clone(skb, GFP_ATOMIC);
++ if (skb2) {
++ skb2->dev = prev_dev;
++ netif_rx(skb2);
++ }
++ }
++
++ prev_dev = sdata->dev;
++ sdata->dev->stats.rx_packets++;
++ sdata->dev->stats.rx_bytes += skb->len;
++ }
++
++ if (prev_dev) {
++ skb->dev = prev_dev;
++ netif_rx(skb);
++ skb = NULL;
++ } else
++ goto out_free_skb;
++
++ rx->flags |= IEEE80211_RX_CMNTR_REPORTED;
++ return;
++
++ out_free_skb:
++ dev_kfree_skb(skb);
++}
++
++typedef ieee80211_rx_result (*ieee80211_rx_handler)(struct ieee80211_rx_data *);
++static ieee80211_rx_handler ieee80211_rx_handlers[] =
+ {
+ ieee80211_rx_h_if_stats,
+ ieee80211_rx_h_passive_scan,
+@@ -1619,10 +1733,51 @@ ieee80211_rx_handler ieee80211_rx_handlers[] =
+ NULL
+ };
+
++static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata,
++ struct ieee80211_rx_data *rx,
++ struct sk_buff *skb)
++{
++ ieee80211_rx_handler *handler;
++ ieee80211_rx_result res = RX_DROP_MONITOR;
++
++ rx->skb = skb;
++ rx->sdata = sdata;
++ rx->dev = sdata->dev;
++
++ for (handler = ieee80211_rx_handlers; *handler != NULL; handler++) {
++ res = (*handler)(rx);
++
++ switch (res) {
++ case RX_CONTINUE:
++ continue;
++ case RX_DROP_UNUSABLE:
++ case RX_DROP_MONITOR:
++ I802_DEBUG_INC(sdata->local->rx_handlers_drop);
++ if (rx->sta)
++ rx->sta->rx_dropped++;
++ break;
++ case RX_QUEUED:
++ I802_DEBUG_INC(sdata->local->rx_handlers_queued);
++ break;
++ }
++ break;
++ }
++
++ switch (res) {
++ case RX_CONTINUE:
++ case RX_DROP_MONITOR:
++ ieee80211_rx_cooked_monitor(rx);
++ break;
++ case RX_DROP_UNUSABLE:
++ dev_kfree_skb(rx->skb);
++ break;
++ }
++}
++
+ /* main receive path */
+
+ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
+- u8 *bssid, struct ieee80211_txrx_data *rx,
++ u8 *bssid, struct ieee80211_rx_data *rx,
+ struct ieee80211_hdr *hdr)
+ {
+ int multicast = is_multicast_ether_addr(hdr->addr1);
+@@ -1632,34 +1787,47 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
+ if (!bssid)
+ return 0;
+ if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) {
+- if (!(rx->flags & IEEE80211_TXRXD_RXIN_SCAN))
++ if (!(rx->flags & IEEE80211_RX_IN_SCAN))
+ return 0;
+- rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;
++ rx->flags &= ~IEEE80211_RX_RA_MATCH;
+ } else if (!multicast &&
+ compare_ether_addr(sdata->dev->dev_addr,
+ hdr->addr1) != 0) {
+ if (!(sdata->dev->flags & IFF_PROMISC))
+ return 0;
+- rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;
++ rx->flags &= ~IEEE80211_RX_RA_MATCH;
+ }
+ break;
+ case IEEE80211_IF_TYPE_IBSS:
+ if (!bssid)
+ return 0;
+- if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) {
+- if (!(rx->flags & IEEE80211_TXRXD_RXIN_SCAN))
++ if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT &&
++ (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON)
++ return 1;
++ else if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) {
++ if (!(rx->flags & IEEE80211_RX_IN_SCAN))
+ return 0;
+- rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;
++ rx->flags &= ~IEEE80211_RX_RA_MATCH;
+ } else if (!multicast &&
+ compare_ether_addr(sdata->dev->dev_addr,
+ hdr->addr1) != 0) {
+ if (!(sdata->dev->flags & IFF_PROMISC))
+ return 0;
+- rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;
++ rx->flags &= ~IEEE80211_RX_RA_MATCH;
+ } else if (!rx->sta)
+ rx->sta = ieee80211_ibss_add_sta(sdata->dev, rx->skb,
+ bssid, hdr->addr2);
+ break;
++ case IEEE80211_IF_TYPE_MESH_POINT:
++ if (!multicast &&
++ compare_ether_addr(sdata->dev->dev_addr,
++ hdr->addr1) != 0) {
++ if (!(sdata->dev->flags & IFF_PROMISC))
++ return 0;
++
++ rx->flags &= ~IEEE80211_RX_RA_MATCH;
++ }
++ break;
+ case IEEE80211_IF_TYPE_VLAN:
+ case IEEE80211_IF_TYPE_AP:
+ if (!bssid) {
+@@ -1668,12 +1836,12 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
+ return 0;
+ } else if (!ieee80211_bssid_match(bssid,
+ sdata->dev->dev_addr)) {
+- if (!(rx->flags & IEEE80211_TXRXD_RXIN_SCAN))
++ if (!(rx->flags & IEEE80211_RX_IN_SCAN))
+ return 0;
+- rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;
++ rx->flags &= ~IEEE80211_RX_RA_MATCH;
+ }
+ if (sdata->dev == sdata->local->mdev &&
+- !(rx->flags & IEEE80211_TXRXD_RXIN_SCAN))
++ !(rx->flags & IEEE80211_RX_IN_SCAN))
+ /* do not receive anything via
+ * master device when not scanning */
+ return 0;
+@@ -1704,13 +1872,13 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
+ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
+ struct sk_buff *skb,
+ struct ieee80211_rx_status *status,
+- u32 load)
++ u32 load,
++ struct ieee80211_rate *rate)
+ {
+ struct ieee80211_local *local = hw_to_local(hw);
+ struct ieee80211_sub_if_data *sdata;
+- struct sta_info *sta;
+ struct ieee80211_hdr *hdr;
+- struct ieee80211_txrx_data rx;
++ struct ieee80211_rx_data rx;
+ u16 type;
+ int prepares;
+ struct ieee80211_sub_if_data *prev = NULL;
+@@ -1722,42 +1890,33 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
+ rx.skb = skb;
+ rx.local = local;
+
+- rx.u.rx.status = status;
+- rx.u.rx.load = load;
++ rx.status = status;
++ rx.load = load;
++ rx.rate = rate;
+ rx.fc = le16_to_cpu(hdr->frame_control);
+ type = rx.fc & IEEE80211_FCTL_FTYPE;
+
+ if (type == IEEE80211_FTYPE_DATA || type == IEEE80211_FTYPE_MGMT)
+ local->dot11ReceivedFragmentCount++;
+
+- sta = rx.sta = sta_info_get(local, hdr->addr2);
+- if (sta) {
+- rx.dev = rx.sta->dev;
+- rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev);
++ rx.sta = sta_info_get(local, hdr->addr2);
++ if (rx.sta) {
++ rx.sdata = rx.sta->sdata;
++ rx.dev = rx.sta->sdata->dev;
+ }
+
+ if ((status->flag & RX_FLAG_MMIC_ERROR)) {
+- ieee80211_rx_michael_mic_report(local->mdev, hdr, sta, &rx);
+- goto end;
++ ieee80211_rx_michael_mic_report(local->mdev, hdr, &rx);
++ return;
+ }
+
+ if (unlikely(local->sta_sw_scanning || local->sta_hw_scanning))
+- rx.flags |= IEEE80211_TXRXD_RXIN_SCAN;
++ rx.flags |= IEEE80211_RX_IN_SCAN;
+
+- if (__ieee80211_invoke_rx_handlers(local, local->rx_pre_handlers, &rx,
+- sta) != TXRX_CONTINUE)
+- goto end;
+- skb = rx.skb;
++ ieee80211_parse_qos(&rx);
++ ieee80211_verify_ip_alignment(&rx);
+
+- if (sta && !(sta->flags & (WLAN_STA_WDS | WLAN_STA_ASSOC_AP)) &&
+- !atomic_read(&local->iff_promiscs) &&
+- !is_multicast_ether_addr(hdr->addr1)) {
+- rx.flags |= IEEE80211_TXRXD_RXRA_MATCH;
+- ieee80211_invoke_rx_handlers(local, local->rx_handlers, &rx,
+- rx.sta);
+- sta_info_put(sta);
+- return;
+- }
++ skb = rx.skb;
+
+ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+ if (!netif_running(sdata->dev))
+@@ -1767,10 +1926,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
+ continue;
+
+ bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type);
+- rx.flags |= IEEE80211_TXRXD_RXRA_MATCH;
++ rx.flags |= IEEE80211_RX_RA_MATCH;
+ prepares = prepare_for_handlers(sdata, bssid, &rx, hdr);
+- /* prepare_for_handlers can change sta */
+- sta = rx.sta;
+
+ if (!prepares)
+ continue;
+@@ -1801,26 +1958,14 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
+ continue;
+ }
+ rx.fc = le16_to_cpu(hdr->frame_control);
+- rx.skb = skb_new;
+- rx.dev = prev->dev;
+- rx.sdata = prev;
+- ieee80211_invoke_rx_handlers(local, local->rx_handlers,
+- &rx, sta);
++ ieee80211_invoke_rx_handlers(prev, &rx, skb_new);
+ prev = sdata;
+ }
+ if (prev) {
+ rx.fc = le16_to_cpu(hdr->frame_control);
+- rx.skb = skb;
+- rx.dev = prev->dev;
+- rx.sdata = prev;
+- ieee80211_invoke_rx_handlers(local, local->rx_handlers,
+- &rx, sta);
++ ieee80211_invoke_rx_handlers(prev, &rx, skb);
+ } else
+ dev_kfree_skb(skb);
+-
+- end:
+- if (sta)
+- sta_info_put(sta);
+ }
+
+ #define SEQ_MODULO 0x1000
+@@ -1856,6 +2001,8 @@ u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
+ u16 head_seq_num, buf_size;
+ int index;
+ u32 pkt_load;
++ struct ieee80211_supported_band *sband;
++ struct ieee80211_rate *rate;
+
+ buf_size = tid_agg_rx->buf_size;
+ head_seq_num = tid_agg_rx->head_seq_num;
+@@ -1886,12 +2033,14 @@ u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
+ memcpy(&status,
+ tid_agg_rx->reorder_buf[index]->cb,
+ sizeof(status));
++ sband = local->hw.wiphy->bands[status.band];
++ rate = &sband->bitrates[status.rate_idx];
+ pkt_load = ieee80211_rx_load_stats(local,
+ tid_agg_rx->reorder_buf[index],
+- &status);
++ &status, rate);
+ __ieee80211_rx_handle_packet(hw,
+ tid_agg_rx->reorder_buf[index],
+- &status, pkt_load);
++ &status, pkt_load, rate);
+ tid_agg_rx->stored_mpdu_num--;
+ tid_agg_rx->reorder_buf[index] = NULL;
+ }
+@@ -1931,11 +2080,13 @@ u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
+ /* release the reordered frame back to stack */
+ memcpy(&status, tid_agg_rx->reorder_buf[index]->cb,
+ sizeof(status));
++ sband = local->hw.wiphy->bands[status.band];
++ rate = &sband->bitrates[status.rate_idx];
+ pkt_load = ieee80211_rx_load_stats(local,
+ tid_agg_rx->reorder_buf[index],
+- &status);
++ &status, rate);
+ __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index],
+- &status, pkt_load);
++ &status, pkt_load, rate);
+ tid_agg_rx->stored_mpdu_num--;
+ tid_agg_rx->reorder_buf[index] = NULL;
+ tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);
+@@ -1970,11 +2121,12 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
+
+ qc = skb->data + ieee80211_get_hdrlen(fc) - QOS_CONTROL_LEN;
+ tid = qc[0] & QOS_CONTROL_TID_MASK;
+- tid_agg_rx = &(sta->ampdu_mlme.tid_rx[tid]);
+
+- if (tid_agg_rx->state != HT_AGG_STATE_OPERATIONAL)
++ if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL)
+ goto end_reorder;
+
++ tid_agg_rx = sta->ampdu_mlme.tid_rx[tid];
++
+ /* null data frames are excluded */
+ if (unlikely(fc & IEEE80211_STYPE_NULLFUNC))
+ goto end_reorder;
+@@ -1991,7 +2143,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
+ /* if this mpdu is fragmented - terminate rx aggregation session */
+ sc = le16_to_cpu(hdr->seq_ctrl);
+ if (sc & IEEE80211_SCTL_FRAG) {
+- ieee80211_sta_stop_rx_ba_session(sta->dev, sta->addr,
++ ieee80211_sta_stop_rx_ba_session(sta->sdata->dev, sta->addr,
+ tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP);
+ ret = 1;
+ goto end_reorder;
+@@ -2001,9 +2153,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
+ mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4;
+ ret = ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb,
+ mpdu_seq_num, 0);
+-end_reorder:
+- if (sta)
+- sta_info_put(sta);
++ end_reorder:
+ return ret;
+ }
+
+@@ -2016,6 +2166,25 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ {
+ struct ieee80211_local *local = hw_to_local(hw);
+ u32 pkt_load;
++ struct ieee80211_rate *rate = NULL;
++ struct ieee80211_supported_band *sband;
++
++ if (status->band < 0 ||
++ status->band >= IEEE80211_NUM_BANDS) {
++ WARN_ON(1);
++ return;
++ }
++
++ sband = local->hw.wiphy->bands[status->band];
++
++ if (!sband ||
++ status->rate_idx < 0 ||
++ status->rate_idx >= sband->n_bitrates) {
++ WARN_ON(1);
++ return;
++ }
++
++ rate = &sband->bitrates[status->rate_idx];
+
+ /*
+ * key references and virtual interfaces are protected using RCU
+@@ -2030,17 +2199,17 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ * if it was previously present.
+ * Also, frames with less than 16 bytes are dropped.
+ */
+- skb = ieee80211_rx_monitor(local, skb, status);
++ skb = ieee80211_rx_monitor(local, skb, status, rate);
+ if (!skb) {
+ rcu_read_unlock();
+ return;
+ }
+
+- pkt_load = ieee80211_rx_load_stats(local, skb, status);
++ pkt_load = ieee80211_rx_load_stats(local, skb, status, rate);
+ local->channel_use_raw += pkt_load;
+
+ if (!ieee80211_rx_reorder_ampdu(local, skb))
+- __ieee80211_rx_handle_packet(hw, skb, status, pkt_load);
++ __ieee80211_rx_handle_packet(hw, skb, status, pkt_load, rate);
+
+ rcu_read_unlock();
+ }
+diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
+index 1f74bd2..7d4fe4a 100644
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -15,21 +15,57 @@
+ #include <linux/skbuff.h>
+ #include <linux/if_arp.h>
+ #include <linux/timer.h>
++#include <linux/rtnetlink.h>
+
+ #include <net/mac80211.h>
+ #include "ieee80211_i.h"
+-#include "ieee80211_rate.h"
++#include "rate.h"
+ #include "sta_info.h"
+ #include "debugfs_sta.h"
++#include "mesh.h"
+
+-/* Caller must hold local->sta_lock */
+-static void sta_info_hash_add(struct ieee80211_local *local,
+- struct sta_info *sta)
+-{
+- sta->hnext = local->sta_hash[STA_HASH(sta->addr)];
+- local->sta_hash[STA_HASH(sta->addr)] = sta;
+-}
+-
++/**
++ * DOC: STA information lifetime rules
++ *
++ * STA info structures (&struct sta_info) are managed in a hash table
++ * for faster lookup and a list for iteration. They are managed using
++ * RCU, i.e. access to the list and hash table is protected by RCU.
++ *
++ * Upon allocating a STA info structure with sta_info_alloc(), the caller owns
++ * that structure. It must then either destroy it using sta_info_destroy()
++ * (which is pretty useless) or insert it into the hash table using
++ * sta_info_insert() which demotes the reference from ownership to a regular
++ * RCU-protected reference; if the function is called without protection by an
++ * RCU critical section the reference is instantly invalidated. Note that the
++ * caller may not do much with the STA info before inserting it, in particular,
++ * it may not start any mesh peer link management or add encryption keys.
++ *
++ * When the insertion fails (sta_info_insert()) returns non-zero), the
++ * structure will have been freed by sta_info_insert()!
++ *
++ * Because there are debugfs entries for each station, and adding those
++ * must be able to sleep, it is also possible to "pin" a station entry,
++ * that means it can be removed from the hash table but not be freed.
++ * See the comment in __sta_info_unlink() for more information, this is
++ * an internal capability only.
++ *
++ * In order to remove a STA info structure, the caller needs to first
++ * unlink it (sta_info_unlink()) from the list and hash tables and
++ * then destroy it; sta_info_destroy() will wait for an RCU grace period
++ * to elapse before actually freeing it. Due to the pinning and the
++ * possibility of multiple callers trying to remove the same STA info at
++ * the same time, sta_info_unlink() can clear the STA info pointer it is
++ * passed to indicate that the STA info is owned by somebody else now.
++ *
++ * If sta_info_unlink() did not clear the pointer then the caller owns
++ * the STA info structure now and is responsible of destroying it with
++ * a call to sta_info_destroy().
++ *
++ * In all other cases, there is no concept of ownership on a STA entry,
++ * each structure is owned by the global hash table/list until it is
++ * removed. All users of the structure need to be RCU protected so that
++ * the structure won't be freed before they are done using it.
++ */
+
+ /* Caller must hold local->sta_lock */
+ static int sta_info_hash_del(struct ieee80211_local *local,
+@@ -41,237 +77,439 @@ static int sta_info_hash_del(struct ieee80211_local *local,
+ if (!s)
+ return -ENOENT;
+ if (s == sta) {
+- local->sta_hash[STA_HASH(sta->addr)] = s->hnext;
++ rcu_assign_pointer(local->sta_hash[STA_HASH(sta->addr)],
++ s->hnext);
+ return 0;
+ }
+
+ while (s->hnext && s->hnext != sta)
+ s = s->hnext;
+ if (s->hnext) {
+- s->hnext = sta->hnext;
++ rcu_assign_pointer(s->hnext, sta->hnext);
+ return 0;
+ }
+
+ return -ENOENT;
+ }
+
+-struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr)
++/* protected by RCU */
++static struct sta_info *__sta_info_find(struct ieee80211_local *local,
++ u8 *addr)
+ {
+ struct sta_info *sta;
+
+- read_lock_bh(&local->sta_lock);
+- sta = local->sta_hash[STA_HASH(addr)];
++ sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]);
+ while (sta) {
+- if (memcmp(sta->addr, addr, ETH_ALEN) == 0) {
+- __sta_info_get(sta);
++ if (compare_ether_addr(sta->addr, addr) == 0)
+ break;
+- }
+- sta = sta->hnext;
++ sta = rcu_dereference(sta->hnext);
+ }
+- read_unlock_bh(&local->sta_lock);
+-
+ return sta;
+ }
++
++struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr)
++{
++ return __sta_info_find(local, addr);
++}
+ EXPORT_SYMBOL(sta_info_get);
+
+-int sta_info_min_txrate_get(struct ieee80211_local *local)
++struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx,
++ struct net_device *dev)
+ {
+ struct sta_info *sta;
+- struct ieee80211_hw_mode *mode;
+- int min_txrate = 9999999;
+- int i;
+-
+- read_lock_bh(&local->sta_lock);
+- mode = local->oper_hw_mode;
+- for (i = 0; i < STA_HASH_SIZE; i++) {
+- sta = local->sta_hash[i];
+- while (sta) {
+- if (sta->txrate < min_txrate)
+- min_txrate = sta->txrate;
+- sta = sta->hnext;
++ int i = 0;
++
++ list_for_each_entry_rcu(sta, &local->sta_list, list) {
++ if (dev && dev != sta->sdata->dev)
++ continue;
++ if (i < idx) {
++ ++i;
++ continue;
+ }
++ return sta;
+ }
+- read_unlock_bh(&local->sta_lock);
+- if (min_txrate == 9999999)
+- min_txrate = 0;
+
+- return mode->rates[min_txrate].rate;
++ return NULL;
+ }
+
++/**
++ * __sta_info_free - internal STA free helper
++ *
++ * @sta: STA info to free
++ *
++ * This function must undo everything done by sta_info_alloc()
++ * that may happen before sta_info_insert().
++ */
++static void __sta_info_free(struct ieee80211_local *local,
++ struct sta_info *sta)
++{
++ DECLARE_MAC_BUF(mbuf);
++
++ rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv);
++ rate_control_put(sta->rate_ctrl);
++
++#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
++ printk(KERN_DEBUG "%s: Destroyed STA %s\n",
++ wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->addr));
++#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+
+-static void sta_info_release(struct kref *kref)
++ kfree(sta);
++}
++
++void sta_info_destroy(struct sta_info *sta)
+ {
+- struct sta_info *sta = container_of(kref, struct sta_info, kref);
+- struct ieee80211_local *local = sta->local;
++ struct ieee80211_local *local;
+ struct sk_buff *skb;
+ int i;
+
+- /* free sta structure; it has already been removed from
+- * hash table etc. external structures. Make sure that all
+- * buffered frames are release (one might have been added
+- * after sta_info_free() was called). */
++ might_sleep();
++
++ if (!sta)
++ return;
++
++ local = sta->local;
++
++ rate_control_remove_sta_debugfs(sta);
++ ieee80211_sta_debugfs_remove(sta);
++
++#ifdef CONFIG_MAC80211_MESH
++ if (ieee80211_vif_is_mesh(&sta->sdata->vif))
++ mesh_plink_deactivate(sta);
++#endif
++
++ /*
++ * We have only unlinked the key, and actually destroying it
++ * may mean it is removed from hardware which requires that
++ * the key->sta pointer is still valid, so flush the key todo
++ * list here.
++ *
++ * ieee80211_key_todo() will synchronize_rcu() so after this
++ * nothing can reference this sta struct any more.
++ */
++ ieee80211_key_todo();
++
++#ifdef CONFIG_MAC80211_MESH
++ if (ieee80211_vif_is_mesh(&sta->sdata->vif))
++ del_timer_sync(&sta->plink_timer);
++#endif
++
+ while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
+ local->total_ps_buffered--;
+ dev_kfree_skb_any(skb);
+ }
+- while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
++
++ while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL)
+ dev_kfree_skb_any(skb);
++
++ for (i = 0; i < STA_TID_NUM; i++) {
++ spin_lock_bh(&sta->ampdu_mlme.ampdu_rx);
++ if (sta->ampdu_mlme.tid_rx[i])
++ del_timer_sync(&sta->ampdu_mlme.tid_rx[i]->session_timer);
++ spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
++ spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
++ if (sta->ampdu_mlme.tid_tx[i])
++ del_timer_sync(&sta->ampdu_mlme.tid_tx[i]->addba_resp_timer);
++ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
+ }
+- for (i = 0; i < STA_TID_NUM; i++)
+- del_timer_sync(&sta->ampdu_mlme.tid_rx[i].session_timer);
+- rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv);
+- rate_control_put(sta->rate_ctrl);
+- kfree(sta);
++
++ __sta_info_free(local, sta);
+ }
+
+
+-void sta_info_put(struct sta_info *sta)
++/* Caller must hold local->sta_lock */
++static void sta_info_hash_add(struct ieee80211_local *local,
++ struct sta_info *sta)
+ {
+- kref_put(&sta->kref, sta_info_release);
++ sta->hnext = local->sta_hash[STA_HASH(sta->addr)];
++ rcu_assign_pointer(local->sta_hash[STA_HASH(sta->addr)], sta);
+ }
+-EXPORT_SYMBOL(sta_info_put);
+
+-
+-struct sta_info * sta_info_add(struct ieee80211_local *local,
+- struct net_device *dev, u8 *addr, gfp_t gfp)
++struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
++ u8 *addr, gfp_t gfp)
+ {
++ struct ieee80211_local *local = sdata->local;
+ struct sta_info *sta;
+ int i;
+- DECLARE_MAC_BUF(mac);
++ DECLARE_MAC_BUF(mbuf);
+
+ sta = kzalloc(sizeof(*sta), gfp);
+ if (!sta)
+ return NULL;
+
+- kref_init(&sta->kref);
++ memcpy(sta->addr, addr, ETH_ALEN);
++ sta->local = local;
++ sta->sdata = sdata;
+
+ sta->rate_ctrl = rate_control_get(local->rate_ctrl);
+- sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, gfp);
++ sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl,
++ gfp);
+ if (!sta->rate_ctrl_priv) {
+ rate_control_put(sta->rate_ctrl);
+ kfree(sta);
+ return NULL;
+ }
+
+- memcpy(sta->addr, addr, ETH_ALEN);
+- sta->local = local;
+- sta->dev = dev;
+ spin_lock_init(&sta->ampdu_mlme.ampdu_rx);
++ spin_lock_init(&sta->ampdu_mlme.ampdu_tx);
+ for (i = 0; i < STA_TID_NUM; i++) {
+ /* timer_to_tid must be initialized with identity mapping to
+ * enable session_timer's data differentiation. refer to
+ * sta_rx_agg_session_timer_expired for useage */
+ sta->timer_to_tid[i] = i;
+- /* rx timers */
+- sta->ampdu_mlme.tid_rx[i].session_timer.function =
+- sta_rx_agg_session_timer_expired;
+- sta->ampdu_mlme.tid_rx[i].session_timer.data =
+- (unsigned long)&sta->timer_to_tid[i];
+- init_timer(&sta->ampdu_mlme.tid_rx[i].session_timer);
++ /* tid to tx queue: initialize according to HW (0 is valid) */
++ sta->tid_to_tx_q[i] = local->hw.queues;
++ /* rx */
++ sta->ampdu_mlme.tid_state_rx[i] = HT_AGG_STATE_IDLE;
++ sta->ampdu_mlme.tid_rx[i] = NULL;
++ /* tx */
++ sta->ampdu_mlme.tid_state_tx[i] = HT_AGG_STATE_IDLE;
++ sta->ampdu_mlme.tid_tx[i] = NULL;
++ sta->ampdu_mlme.addba_req_num[i] = 0;
+ }
+ skb_queue_head_init(&sta->ps_tx_buf);
+ skb_queue_head_init(&sta->tx_filtered);
+- __sta_info_get(sta); /* sta used by caller, decremented by
+- * sta_info_put() */
+- write_lock_bh(&local->sta_lock);
++
++#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
++ printk(KERN_DEBUG "%s: Allocated STA %s\n",
++ wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->addr));
++#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
++
++#ifdef CONFIG_MAC80211_MESH
++ sta->plink_state = PLINK_LISTEN;
++ spin_lock_init(&sta->plink_lock);
++ init_timer(&sta->plink_timer);
++#endif
++
++ return sta;
++}
++
++int sta_info_insert(struct sta_info *sta)
++{
++ struct ieee80211_local *local = sta->local;
++ struct ieee80211_sub_if_data *sdata = sta->sdata;
++ unsigned long flags;
++ int err = 0;
++ DECLARE_MAC_BUF(mac);
++
++ /*
++ * Can't be a WARN_ON because it can be triggered through a race:
++ * something inserts a STA (on one CPU) without holding the RTNL
++ * and another CPU turns off the net device.
++ */
++ if (unlikely(!netif_running(sdata->dev))) {
++ err = -ENETDOWN;
++ goto out_free;
++ }
++
++ if (WARN_ON(compare_ether_addr(sta->addr, sdata->dev->dev_addr) == 0 ||
++ is_multicast_ether_addr(sta->addr))) {
++ err = -EINVAL;
++ goto out_free;
++ }
++
++ spin_lock_irqsave(&local->sta_lock, flags);
++ /* check if STA exists already */
++ if (__sta_info_find(local, sta->addr)) {
++ spin_unlock_irqrestore(&local->sta_lock, flags);
++ err = -EEXIST;
++ goto out_free;
++ }
+ list_add(&sta->list, &local->sta_list);
+ local->num_sta++;
+ sta_info_hash_add(local, sta);
+- if (local->ops->sta_notify) {
+- struct ieee80211_sub_if_data *sdata;
+
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ /* notify driver */
++ if (local->ops->sta_notify) {
+ if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
+ sdata = sdata->u.vlan.ap;
+
+ local->ops->sta_notify(local_to_hw(local), &sdata->vif,
+- STA_NOTIFY_ADD, addr);
++ STA_NOTIFY_ADD, sta->addr);
+ }
+- write_unlock_bh(&local->sta_lock);
+
+ #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+- printk(KERN_DEBUG "%s: Added STA %s\n",
+- wiphy_name(local->hw.wiphy), print_mac(mac, addr));
++ printk(KERN_DEBUG "%s: Inserted STA %s\n",
++ wiphy_name(local->hw.wiphy), print_mac(mac, sta->addr));
+ #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+
++ spin_unlock_irqrestore(&local->sta_lock, flags);
++
+ #ifdef CONFIG_MAC80211_DEBUGFS
+- /* debugfs entry adding might sleep, so schedule process
++ /*
++ * Debugfs entry adding might sleep, so schedule process
+ * context task for adding entry for STAs that do not yet
+- * have one. */
+- queue_work(local->hw.workqueue, &local->sta_debugfs_add);
++ * have one.
++ * NOTE: due to auto-freeing semantics this may only be done
++ * if the insertion is successful!
++ */
++ schedule_work(&local->sta_debugfs_add);
+ #endif
+
+- return sta;
++ if (ieee80211_vif_is_mesh(&sdata->vif))
++ mesh_accept_plinks_update(sdata);
++
++ return 0;
++ out_free:
++ BUG_ON(!err);
++ __sta_info_free(local, sta);
++ return err;
+ }
+
+-/* Caller must hold local->sta_lock */
+-void sta_info_remove(struct sta_info *sta)
++static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid)
+ {
+- struct ieee80211_local *local = sta->local;
+- struct ieee80211_sub_if_data *sdata;
++ /*
++ * This format has been mandated by the IEEE specifications,
++ * so this line may not be changed to use the __set_bit() format.
++ */
++ bss->tim[aid / 8] |= (1 << (aid % 8));
++}
+
+- /* don't do anything if we've been removed already */
+- if (sta_info_hash_del(local, sta))
+- return;
++static inline void __bss_tim_clear(struct ieee80211_if_ap *bss, u16 aid)
++{
++ /*
++ * This format has been mandated by the IEEE specifications,
++ * so this line may not be changed to use the __clear_bit() format.
++ */
++ bss->tim[aid / 8] &= ~(1 << (aid % 8));
++}
+
+- list_del(&sta->list);
+- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+- if (sta->flags & WLAN_STA_PS) {
+- sta->flags &= ~WLAN_STA_PS;
+- if (sdata->bss)
+- atomic_dec(&sdata->bss->num_sta_ps);
++static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss,
++ struct sta_info *sta)
++{
++ if (bss)
++ __bss_tim_set(bss, sta->aid);
++ if (sta->local->ops->set_tim) {
++ sta->local->tim_in_locked_section = true;
++ sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 1);
++ sta->local->tim_in_locked_section = false;
+ }
+- local->num_sta--;
+- sta_info_remove_aid_ptr(sta);
++}
++
++void sta_info_set_tim_bit(struct sta_info *sta)
++{
++ unsigned long flags;
+
++ spin_lock_irqsave(&sta->local->sta_lock, flags);
++ __sta_info_set_tim_bit(sta->sdata->bss, sta);
++ spin_unlock_irqrestore(&sta->local->sta_lock, flags);
+ }
+
+-void sta_info_free(struct sta_info *sta)
++static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss,
++ struct sta_info *sta)
+ {
+- struct sk_buff *skb;
+- struct ieee80211_local *local = sta->local;
+- DECLARE_MAC_BUF(mac);
++ if (bss)
++ __bss_tim_clear(bss, sta->aid);
++ if (sta->local->ops->set_tim) {
++ sta->local->tim_in_locked_section = true;
++ sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 0);
++ sta->local->tim_in_locked_section = false;
++ }
++}
+
+- might_sleep();
++void sta_info_clear_tim_bit(struct sta_info *sta)
++{
++ unsigned long flags;
+
+- write_lock_bh(&local->sta_lock);
+- sta_info_remove(sta);
+- write_unlock_bh(&local->sta_lock);
++ spin_lock_irqsave(&sta->local->sta_lock, flags);
++ __sta_info_clear_tim_bit(sta->sdata->bss, sta);
++ spin_unlock_irqrestore(&sta->local->sta_lock, flags);
++}
+
+- while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
+- local->total_ps_buffered--;
+- dev_kfree_skb(skb);
+- }
+- while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
+- dev_kfree_skb(skb);
++void __sta_info_unlink(struct sta_info **sta)
++{
++ struct ieee80211_local *local = (*sta)->local;
++ struct ieee80211_sub_if_data *sdata = (*sta)->sdata;
++#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
++ DECLARE_MAC_BUF(mbuf);
++#endif
++ /*
++ * pull caller's reference if we're already gone.
++ */
++ if (sta_info_hash_del(local, *sta)) {
++ *sta = NULL;
++ return;
+ }
+
+-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+- printk(KERN_DEBUG "%s: Removed STA %s\n",
+- wiphy_name(local->hw.wiphy), print_mac(mac, sta->addr));
+-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
++ if ((*sta)->key) {
++ ieee80211_key_free((*sta)->key);
++ WARN_ON((*sta)->key);
++ }
+
+- ieee80211_key_free(sta->key);
+- sta->key = NULL;
++ list_del(&(*sta)->list);
+
+- if (local->ops->sta_notify) {
+- struct ieee80211_sub_if_data *sdata;
++ if ((*sta)->flags & WLAN_STA_PS) {
++ (*sta)->flags &= ~WLAN_STA_PS;
++ if (sdata->bss)
++ atomic_dec(&sdata->bss->num_sta_ps);
++ __sta_info_clear_tim_bit(sdata->bss, *sta);
++ }
+
+- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
++ local->num_sta--;
+
++ if (local->ops->sta_notify) {
+ if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
+ sdata = sdata->u.vlan.ap;
+
+ local->ops->sta_notify(local_to_hw(local), &sdata->vif,
+- STA_NOTIFY_REMOVE, sta->addr);
++ STA_NOTIFY_REMOVE, (*sta)->addr);
+ }
+
+- rate_control_remove_sta_debugfs(sta);
+- ieee80211_sta_debugfs_remove(sta);
++ if (ieee80211_vif_is_mesh(&sdata->vif)) {
++ mesh_accept_plinks_update(sdata);
++#ifdef CONFIG_MAC80211_MESH
++ del_timer(&(*sta)->plink_timer);
++#endif
++ }
+
+- sta_info_put(sta);
++#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
++ printk(KERN_DEBUG "%s: Removed STA %s\n",
++ wiphy_name(local->hw.wiphy), print_mac(mbuf, (*sta)->addr));
++#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
++
++ /*
++ * Finally, pull caller's reference if the STA is pinned by the
++ * task that is adding the debugfs entries. In that case, we
++ * leave the STA "to be freed".
++ *
++ * The rules are not trivial, but not too complex either:
++ * (1) pin_status is only modified under the sta_lock
++ * (2) STAs may only be pinned under the RTNL so that
++ * sta_info_flush() is guaranteed to actually destroy
++ * all STAs that are active for a given interface, this
++ * is required for correctness because otherwise we
++ * could notify a driver that an interface is going
++ * away and only after that (!) notify it about a STA
++ * on that interface going away.
++ * (3) sta_info_debugfs_add_work() will set the status
++ * to PINNED when it found an item that needs a new
++ * debugfs directory created. In that case, that item
++ * must not be freed although all *RCU* users are done
++ * with it. Hence, we tell the caller of _unlink()
++ * that the item is already gone (as can happen when
++ * two tasks try to unlink/destroy at the same time)
++ * (4) We set the pin_status to DESTROY here when we
++ * find such an item.
++ * (5) sta_info_debugfs_add_work() will reset the pin_status
++ * from PINNED to NORMAL when it is done with the item,
++ * but will check for DESTROY before resetting it in
++ * which case it will free the item.
++ */
++ if ((*sta)->pin_status == STA_INFO_PIN_STAT_PINNED) {
++ (*sta)->pin_status = STA_INFO_PIN_STAT_DESTROY;
++ *sta = NULL;
++ return;
++ }
+ }
+
++void sta_info_unlink(struct sta_info **sta)
++{
++ struct ieee80211_local *local = (*sta)->local;
++ unsigned long flags;
++
++ spin_lock_irqsave(&local->sta_lock, flags);
++ __sta_info_unlink(sta);
++ spin_unlock_irqrestore(&local->sta_lock, flags);
++}
+
+ static inline int sta_info_buffer_expired(struct ieee80211_local *local,
+ struct sta_info *sta,
+@@ -299,6 +537,7 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
+ {
+ unsigned long flags;
+ struct sk_buff *skb;
++ struct ieee80211_sub_if_data *sdata;
+ DECLARE_MAC_BUF(mac);
+
+ if (skb_queue_empty(&sta->ps_tx_buf))
+@@ -307,21 +546,23 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
+ for (;;) {
+ spin_lock_irqsave(&sta->ps_tx_buf.lock, flags);
+ skb = skb_peek(&sta->ps_tx_buf);
+- if (sta_info_buffer_expired(local, sta, skb)) {
++ if (sta_info_buffer_expired(local, sta, skb))
+ skb = __skb_dequeue(&sta->ps_tx_buf);
+- if (skb_queue_empty(&sta->ps_tx_buf))
+- sta->flags &= ~WLAN_STA_TIM;
+- } else
++ else
+ skb = NULL;
+ spin_unlock_irqrestore(&sta->ps_tx_buf.lock, flags);
+
+- if (skb) {
+- local->total_ps_buffered--;
+- printk(KERN_DEBUG "Buffered frame expired (STA "
+- "%s)\n", print_mac(mac, sta->addr));
+- dev_kfree_skb(skb);
+- } else
++ if (!skb)
+ break;
++
++ sdata = sta->sdata;
++ local->total_ps_buffered--;
++ printk(KERN_DEBUG "Buffered frame expired (STA "
++ "%s)\n", print_mac(mac, sta->addr));
++ dev_kfree_skb(skb);
++
++ if (skb_queue_empty(&sta->ps_tx_buf))
++ sta_info_clear_tim_bit(sta);
+ }
+ }
+
+@@ -331,13 +572,10 @@ static void sta_info_cleanup(unsigned long data)
+ struct ieee80211_local *local = (struct ieee80211_local *) data;
+ struct sta_info *sta;
+
+- read_lock_bh(&local->sta_lock);
+- list_for_each_entry(sta, &local->sta_list, list) {
+- __sta_info_get(sta);
++ rcu_read_lock();
++ list_for_each_entry_rcu(sta, &local->sta_list, list)
+ sta_info_cleanup_expire_buffered(local, sta);
+- sta_info_put(sta);
+- }
+- read_unlock_bh(&local->sta_lock);
++ rcu_read_unlock();
+
+ local->sta_cleanup.expires =
+ round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL);
+@@ -345,38 +583,106 @@ static void sta_info_cleanup(unsigned long data)
+ }
+
+ #ifdef CONFIG_MAC80211_DEBUGFS
+-static void sta_info_debugfs_add_task(struct work_struct *work)
++/*
++ * See comment in __sta_info_unlink,
++ * caller must hold local->sta_lock.
++ */
++static void __sta_info_pin(struct sta_info *sta)
++{
++ WARN_ON(sta->pin_status != STA_INFO_PIN_STAT_NORMAL);
++ sta->pin_status = STA_INFO_PIN_STAT_PINNED;
++}
++
++/*
++ * See comment in __sta_info_unlink, returns sta if it
++ * needs to be destroyed.
++ */
++static struct sta_info *__sta_info_unpin(struct sta_info *sta)
++{
++ struct sta_info *ret = NULL;
++ unsigned long flags;
++
++ spin_lock_irqsave(&sta->local->sta_lock, flags);
++ WARN_ON(sta->pin_status != STA_INFO_PIN_STAT_DESTROY &&
++ sta->pin_status != STA_INFO_PIN_STAT_PINNED);
++ if (sta->pin_status == STA_INFO_PIN_STAT_DESTROY)
++ ret = sta;
++ sta->pin_status = STA_INFO_PIN_STAT_NORMAL;
++ spin_unlock_irqrestore(&sta->local->sta_lock, flags);
++
++ return ret;
++}
++
++static void sta_info_debugfs_add_work(struct work_struct *work)
+ {
+ struct ieee80211_local *local =
+ container_of(work, struct ieee80211_local, sta_debugfs_add);
+ struct sta_info *sta, *tmp;
++ unsigned long flags;
+
++ /* We need to keep the RTNL across the whole pinned status. */
++ rtnl_lock();
+ while (1) {
+ sta = NULL;
+- read_lock_bh(&local->sta_lock);
++
++ spin_lock_irqsave(&local->sta_lock, flags);
+ list_for_each_entry(tmp, &local->sta_list, list) {
+ if (!tmp->debugfs.dir) {
+ sta = tmp;
+- __sta_info_get(sta);
++ __sta_info_pin(sta);
+ break;
+ }
+ }
+- read_unlock_bh(&local->sta_lock);
++ spin_unlock_irqrestore(&local->sta_lock, flags);
+
+ if (!sta)
+ break;
+
+ ieee80211_sta_debugfs_add(sta);
+ rate_control_add_sta_debugfs(sta);
+- sta_info_put(sta);
++
++ sta = __sta_info_unpin(sta);
++ sta_info_destroy(sta);
+ }
++ rtnl_unlock();
+ }
+ #endif
+
++static void __ieee80211_run_pending_flush(struct ieee80211_local *local)
++{
++ struct sta_info *sta;
++ unsigned long flags;
++
++ ASSERT_RTNL();
++
++ spin_lock_irqsave(&local->sta_lock, flags);
++ while (!list_empty(&local->sta_flush_list)) {
++ sta = list_first_entry(&local->sta_flush_list,
++ struct sta_info, list);
++ list_del(&sta->list);
++ spin_unlock_irqrestore(&local->sta_lock, flags);
++ sta_info_destroy(sta);
++ spin_lock_irqsave(&local->sta_lock, flags);
++ }
++ spin_unlock_irqrestore(&local->sta_lock, flags);
++}
++
++static void ieee80211_sta_flush_work(struct work_struct *work)
++{
++ struct ieee80211_local *local =
++ container_of(work, struct ieee80211_local, sta_flush_work);
++
++ rtnl_lock();
++ __ieee80211_run_pending_flush(local);
++ rtnl_unlock();
++}
++
+ void sta_info_init(struct ieee80211_local *local)
+ {
+- rwlock_init(&local->sta_lock);
++ spin_lock_init(&local->sta_lock);
+ INIT_LIST_HEAD(&local->sta_list);
++ INIT_LIST_HEAD(&local->sta_flush_list);
++ INIT_WORK(&local->sta_flush_work, ieee80211_sta_flush_work);
+
+ setup_timer(&local->sta_cleanup, sta_info_cleanup,
+ (unsigned long)local);
+@@ -384,7 +690,7 @@ void sta_info_init(struct ieee80211_local *local)
+ round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL);
+
+ #ifdef CONFIG_MAC80211_DEBUGFS
+- INIT_WORK(&local->sta_debugfs_add, sta_info_debugfs_add_task);
++ INIT_WORK(&local->sta_debugfs_add, sta_info_debugfs_add_work);
+ #endif
+ }
+
+@@ -397,47 +703,89 @@ int sta_info_start(struct ieee80211_local *local)
+ void sta_info_stop(struct ieee80211_local *local)
+ {
+ del_timer(&local->sta_cleanup);
++ cancel_work_sync(&local->sta_flush_work);
++#ifdef CONFIG_MAC80211_DEBUGFS
++ /*
++ * Make sure the debugfs adding work isn't pending after this
++ * because we're about to be destroyed. It doesn't matter
++ * whether it ran or not since we're going to flush all STAs
++ * anyway.
++ */
++ cancel_work_sync(&local->sta_debugfs_add);
++#endif
++
++ rtnl_lock();
+ sta_info_flush(local, NULL);
++ __ieee80211_run_pending_flush(local);
++ rtnl_unlock();
+ }
+
+-void sta_info_remove_aid_ptr(struct sta_info *sta)
++/**
++ * sta_info_flush - flush matching STA entries from the STA table
++ *
++ * Returns the number of removed STA entries.
++ *
++ * @local: local interface data
++ * @sdata: matching rule for the net device (sta->dev) or %NULL to match all STAs
++ */
++int sta_info_flush(struct ieee80211_local *local,
++ struct ieee80211_sub_if_data *sdata)
+ {
+- struct ieee80211_sub_if_data *sdata;
++ struct sta_info *sta, *tmp;
++ LIST_HEAD(tmp_list);
++ int ret = 0;
++ unsigned long flags;
+
+- if (sta->aid <= 0)
+- return;
++ might_sleep();
++ ASSERT_RTNL();
++
++ spin_lock_irqsave(&local->sta_lock, flags);
++ list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
++ if (!sdata || sdata == sta->sdata) {
++ __sta_info_unlink(&sta);
++ if (sta) {
++ list_add_tail(&sta->list, &tmp_list);
++ ret++;
++ }
++ }
++ }
++ spin_unlock_irqrestore(&local->sta_lock, flags);
+
+- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
++ list_for_each_entry_safe(sta, tmp, &tmp_list, list)
++ sta_info_destroy(sta);
+
+- if (sdata->local->ops->set_tim)
+- sdata->local->ops->set_tim(local_to_hw(sdata->local),
+- sta->aid, 0);
+- if (sdata->bss)
+- __bss_tim_clear(sdata->bss, sta->aid);
++ return ret;
+ }
+
+-
+ /**
+- * sta_info_flush - flush matching STA entries from the STA table
+- * @local: local interface data
+- * @dev: matching rule for the net device (sta->dev) or %NULL to match all STAs
++ * sta_info_flush_delayed - flush matching STA entries from the STA table
++ *
++ * This function unlinks all stations for a given interface and queues
++ * them for freeing. Note that the workqueue function scheduled here has
++ * to run before any new keys can be added to the system to avoid set_key()
++ * callback ordering issues.
++ *
++ * @sdata: the interface
+ */
+-void sta_info_flush(struct ieee80211_local *local, struct net_device *dev)
++void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata)
+ {
++ struct ieee80211_local *local = sdata->local;
+ struct sta_info *sta, *tmp;
+- LIST_HEAD(tmp_list);
+-
+- write_lock_bh(&local->sta_lock);
+- list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
+- if (!dev || dev == sta->dev) {
+- __sta_info_get(sta);
+- sta_info_remove(sta);
+- list_add_tail(&sta->list, &tmp_list);
++ unsigned long flags;
++ bool work = false;
++
++ spin_lock_irqsave(&local->sta_lock, flags);
++ list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
++ if (sdata == sta->sdata) {
++ __sta_info_unlink(&sta);
++ if (sta) {
++ list_add_tail(&sta->list,
++ &local->sta_flush_list);
++ work = true;
++ }
+ }
+- write_unlock_bh(&local->sta_lock);
+-
+- list_for_each_entry_safe(sta, tmp, &tmp_list, list) {
+- sta_info_free(sta);
+- sta_info_put(sta);
+ }
++ if (work)
++ schedule_work(&local->sta_flush_work);
++ spin_unlock_irqrestore(&local->sta_lock, flags);
+ }
+diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
+index 96fe3ed..f8c95bc 100644
+--- a/net/mac80211/sta_info.h
++++ b/net/mac80211/sta_info.h
+@@ -12,160 +12,293 @@
+ #include <linux/list.h>
+ #include <linux/types.h>
+ #include <linux/if_ether.h>
+-#include <linux/kref.h>
+-#include "ieee80211_key.h"
+-
+-/* Stations flags (struct sta_info::flags) */
+-#define WLAN_STA_AUTH BIT(0)
+-#define WLAN_STA_ASSOC BIT(1)
+-#define WLAN_STA_PS BIT(2)
+-#define WLAN_STA_TIM BIT(3) /* TIM bit is on for PS stations */
+-#define WLAN_STA_PERM BIT(4) /* permanent; do not remove entry on expiration */
+-#define WLAN_STA_AUTHORIZED BIT(5) /* If 802.1X is used, this flag is
+- * controlling whether STA is authorized to
+- * send and receive non-IEEE 802.1X frames
+- */
+-#define WLAN_STA_SHORT_PREAMBLE BIT(7)
+-/* whether this is an AP that we are associated with as a client */
+-#define WLAN_STA_ASSOC_AP BIT(8)
+-#define WLAN_STA_WME BIT(9)
+-#define WLAN_STA_WDS BIT(27)
++#include "key.h"
++
++/**
++ * enum ieee80211_sta_info_flags - Stations flags
++ *
++ * These flags are used with &struct sta_info's @flags member.
++ *
++ * @WLAN_STA_AUTH: Station is authenticated.
++ * @WLAN_STA_ASSOC: Station is associated.
++ * @WLAN_STA_PS: Station is in power-save mode
++ * @WLAN_STA_AUTHORIZED: Station is authorized to send/receive traffic.
++ * This bit is always checked so needs to be enabled for all stations
++ * when virtual port control is not in use.
++ * @WLAN_STA_SHORT_PREAMBLE: Station is capable of receiving short-preamble
++ * frames.
++ * @WLAN_STA_ASSOC_AP: We're associated to that station, it is an AP.
++ * @WLAN_STA_WME: Station is a QoS-STA.
++ * @WLAN_STA_WDS: Station is one of our WDS peers.
++ * @WLAN_STA_PSPOLL: Station has just PS-polled us.
++ * @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the
++ * IEEE80211_TXCTL_CLEAR_PS_FILT control flag) when the next
++ * frame to this station is transmitted.
++ */
++enum ieee80211_sta_info_flags {
++ WLAN_STA_AUTH = 1<<0,
++ WLAN_STA_ASSOC = 1<<1,
++ WLAN_STA_PS = 1<<2,
++ WLAN_STA_AUTHORIZED = 1<<3,
++ WLAN_STA_SHORT_PREAMBLE = 1<<4,
++ WLAN_STA_ASSOC_AP = 1<<5,
++ WLAN_STA_WME = 1<<6,
++ WLAN_STA_WDS = 1<<7,
++ WLAN_STA_PSPOLL = 1<<8,
++ WLAN_STA_CLEAR_PS_FILT = 1<<9,
++};
+
+ #define STA_TID_NUM 16
+ #define ADDBA_RESP_INTERVAL HZ
++#define HT_AGG_MAX_RETRIES (0x3)
+
+ #define HT_AGG_STATE_INITIATOR_SHIFT (4)
+
++#define HT_ADDBA_REQUESTED_MSK BIT(0)
++#define HT_ADDBA_DRV_READY_MSK BIT(1)
++#define HT_ADDBA_RECEIVED_MSK BIT(2)
+ #define HT_AGG_STATE_REQ_STOP_BA_MSK BIT(3)
+-
++#define HT_AGG_STATE_INITIATOR_MSK BIT(HT_AGG_STATE_INITIATOR_SHIFT)
+ #define HT_AGG_STATE_IDLE (0x0)
+-#define HT_AGG_STATE_OPERATIONAL (0x7)
++#define HT_AGG_STATE_OPERATIONAL (HT_ADDBA_REQUESTED_MSK | \
++ HT_ADDBA_DRV_READY_MSK | \
++ HT_ADDBA_RECEIVED_MSK)
++#define HT_AGG_STATE_DEBUGFS_CTL BIT(7)
+
+ /**
+- * struct tid_ampdu_rx - TID aggregation information (Rx).
++ * struct tid_ampdu_tx - TID aggregation information (Tx).
+ *
+- * @state: TID's state in session state machine.
++ * @addba_resp_timer: timer for peer's response to addba request
++ * @ssn: Starting Sequence Number expected to be aggregated.
+ * @dialog_token: dialog token for aggregation session
++ */
++struct tid_ampdu_tx {
++ struct timer_list addba_resp_timer;
++ u16 ssn;
++ u8 dialog_token;
++};
++
++/**
++ * struct tid_ampdu_rx - TID aggregation information (Rx).
++ *
++ * @reorder_buf: buffer to reorder incoming aggregated MPDUs
++ * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value)
++ * @head_seq_num: head sequence number in reordering buffer.
++ * @stored_mpdu_num: number of MPDUs in reordering buffer
+ * @ssn: Starting Sequence Number expected to be aggregated.
+ * @buf_size: buffer size for incoming A-MPDUs
+ * @timeout: reset timer value.
+- * @head_seq_num: head sequence number in reordering buffer.
+- * @stored_mpdu_num: number of MPDUs in reordering buffer
+- * @reorder_buf: buffer to reorder incoming aggregated MPDUs
+- * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value)
++ * @dialog_token: dialog token for aggregation session
+ */
+ struct tid_ampdu_rx {
+- u8 state;
+- u8 dialog_token;
++ struct sk_buff **reorder_buf;
++ struct timer_list session_timer;
++ u16 head_seq_num;
++ u16 stored_mpdu_num;
+ u16 ssn;
+ u16 buf_size;
+ u16 timeout;
+- u16 head_seq_num;
+- u16 stored_mpdu_num;
+- struct sk_buff **reorder_buf;
+- struct timer_list session_timer;
++ u8 dialog_token;
++};
++
++/**
++ * enum plink_state - state of a mesh peer link finite state machine
++ *
++ * @PLINK_LISTEN: initial state, considered the implicit state of non existant
++ * mesh peer links
++ * @PLINK_OPN_SNT: mesh plink open frame has been sent to this mesh peer
++ * @PLINK_OPN_RCVD: mesh plink open frame has been received from this mesh peer
++ * @PLINK_CNF_RCVD: mesh plink confirm frame has been received from this mesh
++ * peer
++ * @PLINK_ESTAB: mesh peer link is established
++ * @PLINK_HOLDING: mesh peer link is being closed or cancelled
++ * @PLINK_BLOCKED: all frames transmitted from this mesh plink are discarded
++ */
++enum plink_state {
++ PLINK_LISTEN,
++ PLINK_OPN_SNT,
++ PLINK_OPN_RCVD,
++ PLINK_CNF_RCVD,
++ PLINK_ESTAB,
++ PLINK_HOLDING,
++ PLINK_BLOCKED
+ };
+
+ /**
+ * struct sta_ampdu_mlme - STA aggregation information.
+ *
+- * @tid_agg_info_rx: aggregation info for Rx per TID
++ * @tid_state_rx: TID's state in Rx session state machine.
++ * @tid_rx: aggregation info for Rx per TID
+ * @ampdu_rx: for locking sections in aggregation Rx flow
++ * @tid_state_tx: TID's state in Tx session state machine.
++ * @tid_tx: aggregation info for Tx per TID
++ * @addba_req_num: number of times addBA request has been sent.
++ * @ampdu_tx: for locking sectionsi in aggregation Tx flow
++ * @dialog_token_allocator: dialog token enumerator for each new session;
+ */
+ struct sta_ampdu_mlme {
+- struct tid_ampdu_rx tid_rx[STA_TID_NUM];
++ /* rx */
++ u8 tid_state_rx[STA_TID_NUM];
++ struct tid_ampdu_rx *tid_rx[STA_TID_NUM];
+ spinlock_t ampdu_rx;
++ /* tx */
++ u8 tid_state_tx[STA_TID_NUM];
++ struct tid_ampdu_tx *tid_tx[STA_TID_NUM];
++ u8 addba_req_num[STA_TID_NUM];
++ spinlock_t ampdu_tx;
++ u8 dialog_token_allocator;
+ };
+
++
++/* see __sta_info_unlink */
++#define STA_INFO_PIN_STAT_NORMAL 0
++#define STA_INFO_PIN_STAT_PINNED 1
++#define STA_INFO_PIN_STAT_DESTROY 2
++
++/**
++ * struct sta_info - STA information
++ *
++ * This structure collects information about a station that
++ * mac80211 is communicating with.
++ *
++ * @list: global linked list entry
++ * @hnext: hash table linked list pointer
++ * @local: pointer to the global information
++ * @addr: MAC address of this STA
++ * @aid: STA's unique AID (1..2007, 0 = not assigned yet),
++ * only used in AP (and IBSS?) mode
++ * @flags: STA flags, see &enum ieee80211_sta_info_flags
++ * @ps_tx_buf: buffer of frames to transmit to this station
++ * when it leaves power saving state
++ * @tx_filtered: buffer of frames we already tried to transmit
++ * but were filtered by hardware due to STA having entered
++ * power saving state
++ * @rx_packets: Number of MSDUs received from this STA
++ * @rx_bytes: Number of bytes received from this STA
++ * @supp_rates: Bitmap of supported rates (per band)
++ * @ht_info: HT capabilities of this STA
++ */
+ struct sta_info {
+- struct kref kref;
++ /* General information, mostly static */
+ struct list_head list;
+- struct sta_info *hnext; /* next entry in hash table list */
+-
++ struct sta_info *hnext;
+ struct ieee80211_local *local;
+-
+- u8 addr[ETH_ALEN];
+- u16 aid; /* STA's unique AID (1..2007), 0 = not yet assigned */
+- u32 flags; /* WLAN_STA_ */
+-
+- struct sk_buff_head ps_tx_buf; /* buffer of TX frames for station in
+- * power saving state */
+- int pspoll; /* whether STA has send a PS Poll frame */
+- struct sk_buff_head tx_filtered; /* buffer of TX frames that were
+- * already given to low-level driver,
+- * but were filtered */
+- int clear_dst_mask;
+-
+- unsigned long rx_packets, tx_packets; /* number of RX/TX MSDUs */
+- unsigned long rx_bytes, tx_bytes;
+- unsigned long tx_retry_failed, tx_retry_count;
+- unsigned long tx_filtered_count;
+-
+- unsigned int wep_weak_iv_count; /* number of RX frames with weak IV */
+-
+- unsigned long last_rx;
+- u32 supp_rates; /* bitmap of supported rates in local->curr_rates */
+- int txrate; /* index in local->curr_rates */
+- int last_txrate; /* last rate used to send a frame to this STA */
+- int last_nonerp_idx;
+-
+- struct net_device *dev; /* which net device is this station associated
+- * to */
+-
++ struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_key *key;
+-
+- u32 tx_num_consecutive_failures;
+- u32 tx_num_mpdu_ok;
+- u32 tx_num_mpdu_fail;
+-
+ struct rate_control_ref *rate_ctrl;
+ void *rate_ctrl_priv;
++ struct ieee80211_ht_info ht_info;
++ u64 supp_rates[IEEE80211_NUM_BANDS];
++ u8 addr[ETH_ALEN];
++ u16 aid;
++ u16 listen_interval;
+
+- /* last received seq/frag number from this STA (per RX queue) */
+- __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES];
++ /*
++ * for use by the internal lifetime management,
++ * see __sta_info_unlink
++ */
++ u8 pin_status;
++
++ /* frequently updated information, needs locking? */
++ u32 flags;
++
++ /*
++ * STA powersave frame queues, no more than the internal
++ * locking required.
++ */
++ struct sk_buff_head ps_tx_buf;
++ struct sk_buff_head tx_filtered;
++
++ /* Updated from RX path only, no locking requirements */
++ unsigned long rx_packets, rx_bytes;
++ unsigned long wep_weak_iv_count;
++ unsigned long last_rx;
+ unsigned long num_duplicates; /* number of duplicate frames received
+ * from this STA */
+- unsigned long tx_fragments; /* number of transmitted MPDUs */
+ unsigned long rx_fragments; /* number of received MPDUs */
+ unsigned long rx_dropped; /* number of dropped MPDUs from this STA */
+-
+ int last_rssi; /* RSSI of last received frame from this STA */
+ int last_signal; /* signal of last received frame from this STA */
+ int last_noise; /* noise of last received frame from this STA */
+- int last_ack_rssi[3]; /* RSSI of last received ACKs from this STA */
+- unsigned long last_ack;
+- int channel_use;
+- int channel_use_raw;
+-
++ /* last received seq/frag number from this STA (per RX queue) */
++ __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES];
+ #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+ unsigned int wme_rx_queue[NUM_RX_DATA_QUEUES];
++#endif
++
++ /* Updated from TX status path only, no locking requirements */
++ unsigned long tx_filtered_count;
++ unsigned long tx_retry_failed, tx_retry_count;
++ /* TODO: update in generic code not rate control? */
++ u32 tx_num_consecutive_failures;
++ u32 tx_num_mpdu_ok;
++ u32 tx_num_mpdu_fail;
++ /* moving percentage of failed MSDUs */
++ unsigned int fail_avg;
++
++ /* Updated from TX path only, no locking requirements */
++ unsigned long tx_packets; /* number of RX/TX MSDUs */
++ unsigned long tx_bytes;
++ unsigned long tx_fragments; /* number of transmitted MPDUs */
++ int txrate_idx;
++ int last_txrate_idx;
++#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+ unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES];
+-#endif /* CONFIG_MAC80211_DEBUG_COUNTERS */
++#endif
+
+- u16 listen_interval;
++ /* Debug counters, no locking doesn't matter */
++ int channel_use;
++ int channel_use_raw;
+
+- struct ieee80211_ht_info ht_info; /* 802.11n HT capabilities
+- of this STA */
++ /*
++ * Aggregation information, comes with own locking.
++ */
+ struct sta_ampdu_mlme ampdu_mlme;
+- u8 timer_to_tid[STA_TID_NUM]; /* convert timer id to tid */
++ u8 timer_to_tid[STA_TID_NUM]; /* identity mapping to ID timers */
++ u8 tid_to_tx_q[STA_TID_NUM]; /* map tid to tx queue */
++
++#ifdef CONFIG_MAC80211_MESH
++ /*
++ * Mesh peer link attributes
++ * TODO: move to a sub-structure that is referenced with pointer?
++ */
++ __le16 llid; /* Local link ID */
++ __le16 plid; /* Peer link ID */
++ __le16 reason; /* Cancel reason on PLINK_HOLDING state */
++ u8 plink_retries; /* Retries in establishment */
++ bool ignore_plink_timer;
++ enum plink_state plink_state;
++ u32 plink_timeout;
++ struct timer_list plink_timer;
++ spinlock_t plink_lock; /* For peer_state reads / updates and other
++ updates in the structure. Ensures robust
++ transitions for the peerlink FSM */
++#endif
+
+ #ifdef CONFIG_MAC80211_DEBUGFS
+ struct sta_info_debugfsdentries {
+ struct dentry *dir;
+ struct dentry *flags;
+ struct dentry *num_ps_buf_frames;
+- struct dentry *last_ack_rssi;
+- struct dentry *last_ack_ms;
+ struct dentry *inactive_ms;
+ struct dentry *last_seq_ctrl;
+ #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+ struct dentry *wme_rx_queue;
+ struct dentry *wme_tx_queue;
+ #endif
++ struct dentry *agg_status;
+ } debugfs;
+ #endif
+ };
+
++static inline enum plink_state sta_plink_state(struct sta_info *sta)
++{
++#ifdef CONFIG_MAC80211_MESH
++ return sta->plink_state;
++#endif
++ return PLINK_LISTEN;
++}
++
+
+ /* Maximum number of concurrently registered stations */
+ #define MAX_STA_COUNT 2007
+@@ -185,22 +318,46 @@ struct sta_info {
+ */
+ #define STA_INFO_CLEANUP_INTERVAL (10 * HZ)
+
+-static inline void __sta_info_get(struct sta_info *sta)
+-{
+- kref_get(&sta->kref);
+-}
++/*
++ * Get a STA info, must have be under RCU read lock.
++ */
++struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr);
++/*
++ * Get STA info by index, BROKEN!
++ */
++struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx,
++ struct net_device *dev);
++/*
++ * Create a new STA info, caller owns returned structure
++ * until sta_info_insert().
++ */
++struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
++ u8 *addr, gfp_t gfp);
++/*
++ * Insert STA info into hash table/list, returns zero or a
++ * -EEXIST if (if the same MAC address is already present).
++ *
++ * Calling this without RCU protection makes the caller
++ * relinquish its reference to @sta.
++ */
++int sta_info_insert(struct sta_info *sta);
++/*
++ * Unlink a STA info from the hash table/list.
++ * This can NULL the STA pointer if somebody else
++ * has already unlinked it.
++ */
++void sta_info_unlink(struct sta_info **sta);
++void __sta_info_unlink(struct sta_info **sta);
++
++void sta_info_destroy(struct sta_info *sta);
++void sta_info_set_tim_bit(struct sta_info *sta);
++void sta_info_clear_tim_bit(struct sta_info *sta);
+
+-struct sta_info * sta_info_get(struct ieee80211_local *local, u8 *addr);
+-int sta_info_min_txrate_get(struct ieee80211_local *local);
+-void sta_info_put(struct sta_info *sta);
+-struct sta_info * sta_info_add(struct ieee80211_local *local,
+- struct net_device *dev, u8 *addr, gfp_t gfp);
+-void sta_info_remove(struct sta_info *sta);
+-void sta_info_free(struct sta_info *sta);
+ void sta_info_init(struct ieee80211_local *local);
+ int sta_info_start(struct ieee80211_local *local);
+ void sta_info_stop(struct ieee80211_local *local);
+-void sta_info_remove_aid_ptr(struct sta_info *sta);
+-void sta_info_flush(struct ieee80211_local *local, struct net_device *dev);
++int sta_info_flush(struct ieee80211_local *local,
++ struct ieee80211_sub_if_data *sdata);
++void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata);
+
+ #endif /* STA_INFO_H */
+diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c
+index 3abe194..dddbfd6 100644
+--- a/net/mac80211/tkip.c
++++ b/net/mac80211/tkip.c
+@@ -12,7 +12,7 @@
+ #include <linux/netdevice.h>
+
+ #include <net/mac80211.h>
+-#include "ieee80211_key.h"
++#include "key.h"
+ #include "tkip.h"
+ #include "wep.h"
+
+@@ -214,6 +214,59 @@ void ieee80211_tkip_gen_rc4key(struct ieee80211_key *key, u8 *ta,
+ key->u.tkip.iv16, rc4key);
+ }
+
++void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf,
++ struct sk_buff *skb, enum ieee80211_tkip_key_type type,
++ u8 *outkey)
++{
++ struct ieee80211_key *key = (struct ieee80211_key *)
++ container_of(keyconf, struct ieee80211_key, conf);
++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
++ u8 *data = (u8 *) hdr;
++ u16 fc = le16_to_cpu(hdr->frame_control);
++ int hdr_len = ieee80211_get_hdrlen(fc);
++ u8 *ta = hdr->addr2;
++ u16 iv16;
++ u32 iv32;
++
++ iv16 = data[hdr_len] << 8;
++ iv16 += data[hdr_len + 2];
++ iv32 = data[hdr_len + 4] +
++ (data[hdr_len + 5] >> 8) +
++ (data[hdr_len + 6] >> 16) +
++ (data[hdr_len + 7] >> 24);
++
++#ifdef CONFIG_TKIP_DEBUG
++ printk(KERN_DEBUG "TKIP encrypt: iv16 = 0x%04x, iv32 = 0x%08x\n",
++ iv16, iv32);
++
++ if (iv32 != key->u.tkip.iv32) {
++ printk(KERN_DEBUG "skb: iv32 = 0x%08x key: iv32 = 0x%08x\n",
++ iv32, key->u.tkip.iv32);
++ printk(KERN_DEBUG "Wrap around of iv16 in the middle of a "
++ "fragmented packet\n");
++ }
++#endif /* CONFIG_TKIP_DEBUG */
++
++ /* Update the p1k only when the iv16 in the packet wraps around, this
++ * might occur after the wrap around of iv16 in the key in case of
++ * fragmented packets. */
++ if (iv16 == 0 || !key->u.tkip.tx_initialized) {
++ /* IV16 wrapped around - perform TKIP phase 1 */
++ tkip_mixing_phase1(ta, &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY],
++ iv32, key->u.tkip.p1k);
++ key->u.tkip.tx_initialized = 1;
++ }
++
++ if (type == IEEE80211_TKIP_P1_KEY) {
++ memcpy(outkey, key->u.tkip.p1k, sizeof(u16) * 5);
++ return;
++ }
++
++ tkip_mixing_phase2(key->u.tkip.p1k,
++ &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY], iv16, outkey);
++}
++EXPORT_SYMBOL(ieee80211_get_tkip_key);
++
+ /* Encrypt packet payload with TKIP using @key. @pos is a pointer to the
+ * beginning of the buffer containing payload. This payload must include
+ * headroom of eight octets for IV and Ext. IV and taildroom of four octets
+@@ -238,7 +291,7 @@ void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
+ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
+ struct ieee80211_key *key,
+ u8 *payload, size_t payload_len, u8 *ta,
+- int only_iv, int queue,
++ u8 *ra, int only_iv, int queue,
+ u32 *out_iv32, u16 *out_iv16)
+ {
+ u32 iv32;
+@@ -315,6 +368,19 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
+ printk("\n");
+ }
+ #endif /* CONFIG_TKIP_DEBUG */
++ if (key->local->ops->update_tkip_key &&
++ key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
++ u8 bcast[ETH_ALEN] =
++ {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
++ u8 *sta_addr = key->sta->addr;
++
++ if (is_multicast_ether_addr(ra))
++ sta_addr = bcast;
++
++ key->local->ops->update_tkip_key(
++ local_to_hw(key->local), &key->conf,
++ sta_addr, iv32, key->u.tkip.p1k_rx[queue]);
++ }
+ }
+
+ tkip_mixing_phase2(key->u.tkip.p1k_rx[queue],
+diff --git a/net/mac80211/tkip.h b/net/mac80211/tkip.h
+index 73d8ef2..b7c2ee7 100644
+--- a/net/mac80211/tkip.h
++++ b/net/mac80211/tkip.h
+@@ -11,7 +11,7 @@
+
+ #include <linux/types.h>
+ #include <linux/crypto.h>
+-#include "ieee80211_key.h"
++#include "key.h"
+
+ u8 * ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key,
+ u8 iv0, u8 iv1, u8 iv2);
+@@ -31,7 +31,7 @@ enum {
+ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
+ struct ieee80211_key *key,
+ u8 *payload, size_t payload_len, u8 *ta,
+- int only_iv, int queue,
++ u8 *ra, int only_iv, int queue,
+ u32 *out_iv32, u16 *out_iv16);
+
+ #endif /* TKIP_H */
+diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
+index 67b509e..f35eaea 100644
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -25,11 +25,12 @@
+ #include <asm/unaligned.h>
+
+ #include "ieee80211_i.h"
+-#include "ieee80211_led.h"
++#include "led.h"
++#include "mesh.h"
+ #include "wep.h"
+ #include "wpa.h"
+ #include "wme.h"
+-#include "ieee80211_rate.h"
++#include "rate.h"
+
+ #define IEEE80211_TX_OK 0
+ #define IEEE80211_TX_AGAIN 1
+@@ -86,15 +87,19 @@ static inline void ieee80211_dump_frame(const char *ifname, const char *title,
+ }
+ #endif /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */
+
+-static u16 ieee80211_duration(struct ieee80211_txrx_data *tx, int group_addr,
++static u16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr,
+ int next_frag_len)
+ {
+ int rate, mrate, erp, dur, i;
+- struct ieee80211_rate *txrate = tx->u.tx.rate;
++ struct ieee80211_rate *txrate = tx->rate;
+ struct ieee80211_local *local = tx->local;
+- struct ieee80211_hw_mode *mode = tx->u.tx.mode;
++ struct ieee80211_supported_band *sband;
+
+- erp = txrate->flags & IEEE80211_RATE_ERP;
++ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++
++ erp = 0;
++ if (tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
++ erp = txrate->flags & IEEE80211_RATE_ERP_G;
+
+ /*
+ * data and mgmt (except PS Poll):
+@@ -150,20 +155,36 @@ static u16 ieee80211_duration(struct ieee80211_txrx_data *tx, int group_addr,
+ * Mandatory rates for IEEE 802.11g PHY: 1, 2, 5.5, 11, 6, 12, 24 Mbps
+ */
+ rate = -1;
+- mrate = 10; /* use 1 Mbps if everything fails */
+- for (i = 0; i < mode->num_rates; i++) {
+- struct ieee80211_rate *r = &mode->rates[i];
+- if (r->rate > txrate->rate)
+- break;
++ /* use lowest available if everything fails */
++ mrate = sband->bitrates[0].bitrate;
++ for (i = 0; i < sband->n_bitrates; i++) {
++ struct ieee80211_rate *r = &sband->bitrates[i];
+
+- if (IEEE80211_RATE_MODULATION(txrate->flags) !=
+- IEEE80211_RATE_MODULATION(r->flags))
+- continue;
++ if (r->bitrate > txrate->bitrate)
++ break;
+
+- if (r->flags & IEEE80211_RATE_BASIC)
+- rate = r->rate;
+- else if (r->flags & IEEE80211_RATE_MANDATORY)
+- mrate = r->rate;
++ if (tx->sdata->basic_rates & BIT(i))
++ rate = r->bitrate;
++
++ switch (sband->band) {
++ case IEEE80211_BAND_2GHZ: {
++ u32 flag;
++ if (tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
++ flag = IEEE80211_RATE_MANDATORY_G;
++ else
++ flag = IEEE80211_RATE_MANDATORY_B;
++ if (r->flags & flag)
++ mrate = r->bitrate;
++ break;
++ }
++ case IEEE80211_BAND_5GHZ:
++ if (r->flags & IEEE80211_RATE_MANDATORY_A)
++ mrate = r->bitrate;
++ break;
++ case IEEE80211_NUM_BANDS:
++ WARN_ON(1);
++ break;
++ }
+ }
+ if (rate == -1) {
+ /* No matching basic rate found; use highest suitable mandatory
+@@ -184,7 +205,7 @@ static u16 ieee80211_duration(struct ieee80211_txrx_data *tx, int group_addr,
+ dur *= 2; /* ACK + SIFS */
+ /* next fragment */
+ dur += ieee80211_frame_duration(local, next_frag_len,
+- txrate->rate, erp,
++ txrate->bitrate, erp,
+ tx->sdata->bss_conf.use_short_preamble);
+ }
+
+@@ -212,8 +233,8 @@ static int inline is_ieee80211_device(struct net_device *dev,
+
+ /* tx handlers */
+
+-static ieee80211_txrx_result
+-ieee80211_tx_h_check_assoc(struct ieee80211_txrx_data *tx)
++static ieee80211_tx_result
++ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
+ {
+ #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+ struct sk_buff *skb = tx->skb;
+@@ -221,20 +242,23 @@ ieee80211_tx_h_check_assoc(struct ieee80211_txrx_data *tx)
+ #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+ u32 sta_flags;
+
+- if (unlikely(tx->flags & IEEE80211_TXRXD_TX_INJECTED))
+- return TXRX_CONTINUE;
++ if (unlikely(tx->flags & IEEE80211_TX_INJECTED))
++ return TX_CONTINUE;
+
+ if (unlikely(tx->local->sta_sw_scanning) &&
+ ((tx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT ||
+ (tx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PROBE_REQ))
+- return TXRX_DROP;
++ return TX_DROP;
+
+- if (tx->flags & IEEE80211_TXRXD_TXPS_BUFFERED)
+- return TXRX_CONTINUE;
++ if (tx->sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT)
++ return TX_CONTINUE;
++
++ if (tx->flags & IEEE80211_TX_PS_BUFFERED)
++ return TX_CONTINUE;
+
+ sta_flags = tx->sta ? tx->sta->flags : 0;
+
+- if (likely(tx->flags & IEEE80211_TXRXD_TXUNICAST)) {
++ if (likely(tx->flags & IEEE80211_TX_UNICAST)) {
+ if (unlikely(!(sta_flags & WLAN_STA_ASSOC) &&
+ tx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
+ (tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) {
+@@ -245,7 +269,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_txrx_data *tx)
+ tx->dev->name, print_mac(mac, hdr->addr1));
+ #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+ I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc);
+- return TXRX_DROP;
++ return TX_DROP;
+ }
+ } else {
+ if (unlikely((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
+@@ -255,23 +279,23 @@ ieee80211_tx_h_check_assoc(struct ieee80211_txrx_data *tx)
+ * No associated STAs - no need to send multicast
+ * frames.
+ */
+- return TXRX_DROP;
++ return TX_DROP;
+ }
+- return TXRX_CONTINUE;
++ return TX_CONTINUE;
+ }
+
+- return TXRX_CONTINUE;
++ return TX_CONTINUE;
+ }
+
+-static ieee80211_txrx_result
+-ieee80211_tx_h_sequence(struct ieee80211_txrx_data *tx)
++static ieee80211_tx_result
++ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
+ {
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
+
+ if (ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)) >= 24)
+ ieee80211_include_sequence(tx->sdata, hdr);
+
+- return TXRX_CONTINUE;
++ return TX_CONTINUE;
+ }
+
+ /* This function is called whenever the AP is about to exceed the maximum limit
+@@ -303,10 +327,8 @@ static void purge_old_ps_buffers(struct ieee80211_local *local)
+ }
+ total += skb_queue_len(&ap->ps_bc_buf);
+ }
+- rcu_read_unlock();
+
+- read_lock_bh(&local->sta_lock);
+- list_for_each_entry(sta, &local->sta_list, list) {
++ list_for_each_entry_rcu(sta, &local->sta_list, list) {
+ skb = skb_dequeue(&sta->ps_tx_buf);
+ if (skb) {
+ purged++;
+@@ -314,15 +336,16 @@ static void purge_old_ps_buffers(struct ieee80211_local *local)
+ }
+ total += skb_queue_len(&sta->ps_tx_buf);
+ }
+- read_unlock_bh(&local->sta_lock);
++
++ rcu_read_unlock();
+
+ local->total_ps_buffered = total;
+ printk(KERN_DEBUG "%s: PS buffers full - purged %d frames\n",
+ wiphy_name(local->hw.wiphy), purged);
+ }
+
+-static ieee80211_txrx_result
+-ieee80211_tx_h_multicast_ps_buf(struct ieee80211_txrx_data *tx)
++static ieee80211_tx_result
++ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
+ {
+ /*
+ * broadcast/multicast frame
+@@ -334,11 +357,11 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_txrx_data *tx)
+
+ /* not AP/IBSS or ordered frame */
+ if (!tx->sdata->bss || (tx->fc & IEEE80211_FCTL_ORDER))
+- return TXRX_CONTINUE;
++ return TX_CONTINUE;
+
+ /* no stations in PS mode */
+ if (!atomic_read(&tx->sdata->bss->num_sta_ps))
+- return TXRX_CONTINUE;
++ return TX_CONTINUE;
+
+ /* buffered in mac80211 */
+ if (tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING) {
+@@ -355,17 +378,17 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_txrx_data *tx)
+ } else
+ tx->local->total_ps_buffered++;
+ skb_queue_tail(&tx->sdata->bss->ps_bc_buf, tx->skb);
+- return TXRX_QUEUED;
++ return TX_QUEUED;
+ }
+
+ /* buffered in hardware */
+- tx->u.tx.control->flags |= IEEE80211_TXCTL_SEND_AFTER_DTIM;
++ tx->control->flags |= IEEE80211_TXCTL_SEND_AFTER_DTIM;
+
+- return TXRX_CONTINUE;
++ return TX_CONTINUE;
+ }
+
+-static ieee80211_txrx_result
+-ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx)
++static ieee80211_tx_result
++ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
+ {
+ struct sta_info *sta = tx->sta;
+ DECLARE_MAC_BUF(mac);
+@@ -373,9 +396,10 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx)
+ if (unlikely(!sta ||
+ ((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT &&
+ (tx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP)))
+- return TXRX_CONTINUE;
++ return TX_CONTINUE;
+
+- if (unlikely((sta->flags & WLAN_STA_PS) && !sta->pspoll)) {
++ if (unlikely((sta->flags & WLAN_STA_PS) &&
++ !(sta->flags & WLAN_STA_PSPOLL))) {
+ struct ieee80211_tx_packet_data *pkt_data;
+ #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+ printk(KERN_DEBUG "STA %s aid %d: PS buffer (entries "
+@@ -383,7 +407,6 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx)
+ print_mac(mac, sta->addr), sta->aid,
+ skb_queue_len(&sta->ps_tx_buf));
+ #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+- sta->flags |= WLAN_STA_TIM;
+ if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
+ purge_old_ps_buffers(tx->local);
+ if (skb_queue_len(&sta->ps_tx_buf) >= STA_MAX_TX_BUFFER) {
+@@ -396,18 +419,15 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx)
+ dev_kfree_skb(old);
+ } else
+ tx->local->total_ps_buffered++;
++
+ /* Queue frame to be sent after STA sends an PS Poll frame */
+- if (skb_queue_empty(&sta->ps_tx_buf)) {
+- if (tx->local->ops->set_tim)
+- tx->local->ops->set_tim(local_to_hw(tx->local),
+- sta->aid, 1);
+- if (tx->sdata->bss)
+- bss_tim_set(tx->local, tx->sdata->bss, sta->aid);
+- }
++ if (skb_queue_empty(&sta->ps_tx_buf))
++ sta_info_set_tim_bit(sta);
++
+ pkt_data = (struct ieee80211_tx_packet_data *)tx->skb->cb;
+ pkt_data->jiffies = jiffies;
+ skb_queue_tail(&sta->ps_tx_buf, tx->skb);
+- return TXRX_QUEUED;
++ return TX_QUEUED;
+ }
+ #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+ else if (unlikely(sta->flags & WLAN_STA_PS)) {
+@@ -416,40 +436,40 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx)
+ print_mac(mac, sta->addr));
+ }
+ #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+- sta->pspoll = 0;
++ sta->flags &= ~WLAN_STA_PSPOLL;
+
+- return TXRX_CONTINUE;
++ return TX_CONTINUE;
+ }
+
+-static ieee80211_txrx_result
+-ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx)
++static ieee80211_tx_result
++ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx)
+ {
+- if (unlikely(tx->flags & IEEE80211_TXRXD_TXPS_BUFFERED))
+- return TXRX_CONTINUE;
++ if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED))
++ return TX_CONTINUE;
+
+- if (tx->flags & IEEE80211_TXRXD_TXUNICAST)
++ if (tx->flags & IEEE80211_TX_UNICAST)
+ return ieee80211_tx_h_unicast_ps_buf(tx);
+ else
+ return ieee80211_tx_h_multicast_ps_buf(tx);
+ }
+
+-static ieee80211_txrx_result
+-ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx)
++static ieee80211_tx_result
++ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
+ {
+ struct ieee80211_key *key;
+ u16 fc = tx->fc;
+
+- if (unlikely(tx->u.tx.control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
++ if (unlikely(tx->control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
+ tx->key = NULL;
+ else if (tx->sta && (key = rcu_dereference(tx->sta->key)))
+ tx->key = key;
+ else if ((key = rcu_dereference(tx->sdata->default_key)))
+ tx->key = key;
+ else if (tx->sdata->drop_unencrypted &&
+- !(tx->u.tx.control->flags & IEEE80211_TXCTL_EAPOL_FRAME) &&
+- !(tx->flags & IEEE80211_TXRXD_TX_INJECTED)) {
++ !(tx->control->flags & IEEE80211_TXCTL_EAPOL_FRAME) &&
++ !(tx->flags & IEEE80211_TX_INJECTED)) {
+ I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
+- return TXRX_DROP;
++ return TX_DROP;
+ } else
+ tx->key = NULL;
+
+@@ -476,13 +496,13 @@ ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx)
+ }
+
+ if (!tx->key || !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
+- tx->u.tx.control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
++ tx->control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
+
+- return TXRX_CONTINUE;
++ return TX_CONTINUE;
+ }
+
+-static ieee80211_txrx_result
+-ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx)
++static ieee80211_tx_result
++ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
+ {
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
+ size_t hdrlen, per_fragm, num_fragm, payload_len, left;
+@@ -492,8 +512,8 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx)
+ u8 *pos;
+ int frag_threshold = tx->local->fragmentation_threshold;
+
+- if (!(tx->flags & IEEE80211_TXRXD_FRAGMENTED))
+- return TXRX_CONTINUE;
++ if (!(tx->flags & IEEE80211_TX_FRAGMENTED))
++ return TX_CONTINUE;
+
+ first = tx->skb;
+
+@@ -544,10 +564,10 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx)
+ }
+ skb_trim(first, hdrlen + per_fragm);
+
+- tx->u.tx.num_extra_frag = num_fragm - 1;
+- tx->u.tx.extra_frag = frags;
++ tx->num_extra_frag = num_fragm - 1;
++ tx->extra_frag = frags;
+
+- return TXRX_CONTINUE;
++ return TX_CONTINUE;
+
+ fail:
+ printk(KERN_DEBUG "%s: failed to fragment frame\n", tx->dev->name);
+@@ -558,14 +578,14 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx)
+ kfree(frags);
+ }
+ I802_DEBUG_INC(tx->local->tx_handlers_drop_fragment);
+- return TXRX_DROP;
++ return TX_DROP;
+ }
+
+-static ieee80211_txrx_result
+-ieee80211_tx_h_encrypt(struct ieee80211_txrx_data *tx)
++static ieee80211_tx_result
++ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
+ {
+ if (!tx->key)
+- return TXRX_CONTINUE;
++ return TX_CONTINUE;
+
+ switch (tx->key->conf.alg) {
+ case ALG_WEP:
+@@ -578,59 +598,60 @@ ieee80211_tx_h_encrypt(struct ieee80211_txrx_data *tx)
+
+ /* not reached */
+ WARN_ON(1);
+- return TXRX_DROP;
++ return TX_DROP;
+ }
+
+-static ieee80211_txrx_result
+-ieee80211_tx_h_rate_ctrl(struct ieee80211_txrx_data *tx)
++static ieee80211_tx_result
++ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
+ {
+ struct rate_selection rsel;
++ struct ieee80211_supported_band *sband;
++
++ sband = tx->local->hw.wiphy->bands[tx->local->hw.conf.channel->band];
+
+- if (likely(!tx->u.tx.rate)) {
+- rate_control_get_rate(tx->dev, tx->u.tx.mode, tx->skb, &rsel);
+- tx->u.tx.rate = rsel.rate;
+- if (unlikely(rsel.probe != NULL)) {
+- tx->u.tx.control->flags |=
++ if (likely(!tx->rate)) {
++ rate_control_get_rate(tx->dev, sband, tx->skb, &rsel);
++ tx->rate = rsel.rate;
++ if (unlikely(rsel.probe)) {
++ tx->control->flags |=
+ IEEE80211_TXCTL_RATE_CTRL_PROBE;
+- tx->flags |= IEEE80211_TXRXD_TXPROBE_LAST_FRAG;
+- tx->u.tx.control->alt_retry_rate = tx->u.tx.rate->val;
+- tx->u.tx.rate = rsel.probe;
++ tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG;
++ tx->control->alt_retry_rate = tx->rate;
++ tx->rate = rsel.probe;
+ } else
+- tx->u.tx.control->alt_retry_rate = -1;
++ tx->control->alt_retry_rate = NULL;
+
+- if (!tx->u.tx.rate)
+- return TXRX_DROP;
++ if (!tx->rate)
++ return TX_DROP;
+ } else
+- tx->u.tx.control->alt_retry_rate = -1;
++ tx->control->alt_retry_rate = NULL;
+
+- if (tx->u.tx.mode->mode == MODE_IEEE80211G &&
+- tx->sdata->bss_conf.use_cts_prot &&
+- (tx->flags & IEEE80211_TXRXD_FRAGMENTED) && rsel.nonerp) {
+- tx->u.tx.last_frag_rate = tx->u.tx.rate;
++ if (tx->sdata->bss_conf.use_cts_prot &&
++ (tx->flags & IEEE80211_TX_FRAGMENTED) && rsel.nonerp) {
++ tx->last_frag_rate = tx->rate;
+ if (rsel.probe)
+- tx->flags &= ~IEEE80211_TXRXD_TXPROBE_LAST_FRAG;
++ tx->flags &= ~IEEE80211_TX_PROBE_LAST_FRAG;
+ else
+- tx->flags |= IEEE80211_TXRXD_TXPROBE_LAST_FRAG;
+- tx->u.tx.rate = rsel.nonerp;
+- tx->u.tx.control->rate = rsel.nonerp;
+- tx->u.tx.control->flags &= ~IEEE80211_TXCTL_RATE_CTRL_PROBE;
++ tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG;
++ tx->rate = rsel.nonerp;
++ tx->control->tx_rate = rsel.nonerp;
++ tx->control->flags &= ~IEEE80211_TXCTL_RATE_CTRL_PROBE;
+ } else {
+- tx->u.tx.last_frag_rate = tx->u.tx.rate;
+- tx->u.tx.control->rate = tx->u.tx.rate;
++ tx->last_frag_rate = tx->rate;
++ tx->control->tx_rate = tx->rate;
+ }
+- tx->u.tx.control->tx_rate = tx->u.tx.rate->val;
++ tx->control->tx_rate = tx->rate;
+
+- return TXRX_CONTINUE;
++ return TX_CONTINUE;
+ }
+
+-static ieee80211_txrx_result
+-ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx)
++static ieee80211_tx_result
++ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
+ {
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
+ u16 fc = le16_to_cpu(hdr->frame_control);
+ u16 dur;
+- struct ieee80211_tx_control *control = tx->u.tx.control;
+- struct ieee80211_hw_mode *mode = tx->u.tx.mode;
++ struct ieee80211_tx_control *control = tx->control;
+
+ if (!control->retry_limit) {
+ if (!is_multicast_ether_addr(hdr->addr1)) {
+@@ -652,20 +673,20 @@ ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx)
+ }
+ }
+
+- if (tx->flags & IEEE80211_TXRXD_FRAGMENTED) {
++ if (tx->flags & IEEE80211_TX_FRAGMENTED) {
+ /* Do not use multiple retry rates when sending fragmented
+ * frames.
+ * TODO: The last fragment could still use multiple retry
+ * rates. */
+- control->alt_retry_rate = -1;
++ control->alt_retry_rate = NULL;
+ }
+
+ /* Use CTS protection for unicast frames sent using extended rates if
+ * there are associated non-ERP stations and RTS/CTS is not configured
+ * for the frame. */
+- if (mode->mode == MODE_IEEE80211G &&
+- (tx->u.tx.rate->flags & IEEE80211_RATE_ERP) &&
+- (tx->flags & IEEE80211_TXRXD_TXUNICAST) &&
++ if ((tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) &&
++ (tx->rate->flags & IEEE80211_RATE_ERP_G) &&
++ (tx->flags & IEEE80211_TX_UNICAST) &&
+ tx->sdata->bss_conf.use_cts_prot &&
+ !(control->flags & IEEE80211_TXCTL_USE_RTS_CTS))
+ control->flags |= IEEE80211_TXCTL_USE_CTS_PROTECT;
+@@ -674,62 +695,77 @@ ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx)
+ * short preambles at the selected rate and short preambles are
+ * available on the network at the current point in time. */
+ if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
+- (tx->u.tx.rate->flags & IEEE80211_RATE_PREAMBLE2) &&
++ (tx->rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) &&
+ tx->sdata->bss_conf.use_short_preamble &&
+ (!tx->sta || (tx->sta->flags & WLAN_STA_SHORT_PREAMBLE))) {
+- tx->u.tx.control->tx_rate = tx->u.tx.rate->val2;
++ tx->control->flags |= IEEE80211_TXCTL_SHORT_PREAMBLE;
+ }
+
+ /* Setup duration field for the first fragment of the frame. Duration
+ * for remaining fragments will be updated when they are being sent
+ * to low-level driver in ieee80211_tx(). */
+ dur = ieee80211_duration(tx, is_multicast_ether_addr(hdr->addr1),
+- (tx->flags & IEEE80211_TXRXD_FRAGMENTED) ?
+- tx->u.tx.extra_frag[0]->len : 0);
++ (tx->flags & IEEE80211_TX_FRAGMENTED) ?
++ tx->extra_frag[0]->len : 0);
+ hdr->duration_id = cpu_to_le16(dur);
+
+ if ((control->flags & IEEE80211_TXCTL_USE_RTS_CTS) ||
+ (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) {
+- struct ieee80211_rate *rate;
++ struct ieee80211_supported_band *sband;
++ struct ieee80211_rate *rate, *baserate;
++ int idx;
++
++ sband = tx->local->hw.wiphy->bands[
++ tx->local->hw.conf.channel->band];
+
+ /* Do not use multiple retry rates when using RTS/CTS */
+- control->alt_retry_rate = -1;
++ control->alt_retry_rate = NULL;
+
+ /* Use min(data rate, max base rate) as CTS/RTS rate */
+- rate = tx->u.tx.rate;
+- while (rate > mode->rates &&
+- !(rate->flags & IEEE80211_RATE_BASIC))
+- rate--;
++ rate = tx->rate;
++ baserate = NULL;
++
++ for (idx = 0; idx < sband->n_bitrates; idx++) {
++ if (sband->bitrates[idx].bitrate > rate->bitrate)
++ continue;
++ if (tx->sdata->basic_rates & BIT(idx) &&
++ (!baserate ||
++ (baserate->bitrate < sband->bitrates[idx].bitrate)))
++ baserate = &sband->bitrates[idx];
++ }
+
+- control->rts_cts_rate = rate->val;
+- control->rts_rate = rate;
++ if (baserate)
++ control->rts_cts_rate = baserate;
++ else
++ control->rts_cts_rate = &sband->bitrates[0];
+ }
+
+ if (tx->sta) {
++ control->aid = tx->sta->aid;
+ tx->sta->tx_packets++;
+ tx->sta->tx_fragments++;
+ tx->sta->tx_bytes += tx->skb->len;
+- if (tx->u.tx.extra_frag) {
++ if (tx->extra_frag) {
+ int i;
+- tx->sta->tx_fragments += tx->u.tx.num_extra_frag;
+- for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
++ tx->sta->tx_fragments += tx->num_extra_frag;
++ for (i = 0; i < tx->num_extra_frag; i++) {
+ tx->sta->tx_bytes +=
+- tx->u.tx.extra_frag[i]->len;
++ tx->extra_frag[i]->len;
+ }
+ }
+ }
+
+- return TXRX_CONTINUE;
++ return TX_CONTINUE;
+ }
+
+-static ieee80211_txrx_result
+-ieee80211_tx_h_load_stats(struct ieee80211_txrx_data *tx)
++static ieee80211_tx_result
++ieee80211_tx_h_load_stats(struct ieee80211_tx_data *tx)
+ {
+ struct ieee80211_local *local = tx->local;
+- struct ieee80211_hw_mode *mode = tx->u.tx.mode;
+ struct sk_buff *skb = tx->skb;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ u32 load = 0, hdrtime;
++ struct ieee80211_rate *rate = tx->rate;
+
+ /* TODO: this could be part of tx_status handling, so that the number
+ * of retries would be known; TX rate should in that case be stored
+@@ -740,9 +776,9 @@ ieee80211_tx_h_load_stats(struct ieee80211_txrx_data *tx)
+ /* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values,
+ * 1 usec = 1/8 * (1080 / 10) = 13.5 */
+
+- if (mode->mode == MODE_IEEE80211A ||
+- (mode->mode == MODE_IEEE80211G &&
+- tx->u.tx.rate->flags & IEEE80211_RATE_ERP))
++ if (tx->channel->band == IEEE80211_BAND_5GHZ ||
++ (tx->channel->band == IEEE80211_BAND_2GHZ &&
++ rate->flags & IEEE80211_RATE_ERP_G))
+ hdrtime = CHAN_UTIL_HDR_SHORT;
+ else
+ hdrtime = CHAN_UTIL_HDR_LONG;
+@@ -751,19 +787,20 @@ ieee80211_tx_h_load_stats(struct ieee80211_txrx_data *tx)
+ if (!is_multicast_ether_addr(hdr->addr1))
+ load += hdrtime;
+
+- if (tx->u.tx.control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
++ if (tx->control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
+ load += 2 * hdrtime;
+- else if (tx->u.tx.control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
++ else if (tx->control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
+ load += hdrtime;
+
+- load += skb->len * tx->u.tx.rate->rate_inv;
++ /* TODO: optimise again */
++ load += skb->len * CHAN_UTIL_RATE_LCM / rate->bitrate;
+
+- if (tx->u.tx.extra_frag) {
++ if (tx->extra_frag) {
+ int i;
+- for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
++ for (i = 0; i < tx->num_extra_frag; i++) {
+ load += 2 * hdrtime;
+- load += tx->u.tx.extra_frag[i]->len *
+- tx->u.tx.rate->rate;
++ load += tx->extra_frag[i]->len *
++ tx->rate->bitrate;
+ }
+ }
+
+@@ -774,13 +811,12 @@ ieee80211_tx_h_load_stats(struct ieee80211_txrx_data *tx)
+ tx->sta->channel_use_raw += load;
+ tx->sdata->channel_use_raw += load;
+
+- return TXRX_CONTINUE;
++ return TX_CONTINUE;
+ }
+
+-/* TODO: implement register/unregister functions for adding TX/RX handlers
+- * into ordered list */
+
+-ieee80211_tx_handler ieee80211_tx_handlers[] =
++typedef ieee80211_tx_result (*ieee80211_tx_handler)(struct ieee80211_tx_data *);
++static ieee80211_tx_handler ieee80211_tx_handlers[] =
+ {
+ ieee80211_tx_h_check_assoc,
+ ieee80211_tx_h_sequence,
+@@ -801,8 +837,8 @@ ieee80211_tx_handler ieee80211_tx_handlers[] =
+ * deal with packet injection down monitor interface
+ * with Radiotap Header -- only called for monitor mode interface
+ */
+-static ieee80211_txrx_result
+-__ieee80211_parse_tx_radiotap(struct ieee80211_txrx_data *tx,
++static ieee80211_tx_result
++__ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
+ struct sk_buff *skb)
+ {
+ /*
+@@ -816,13 +852,15 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_txrx_data *tx,
+ struct ieee80211_radiotap_iterator iterator;
+ struct ieee80211_radiotap_header *rthdr =
+ (struct ieee80211_radiotap_header *) skb->data;
+- struct ieee80211_hw_mode *mode = tx->local->hw.conf.mode;
++ struct ieee80211_supported_band *sband;
+ int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len);
+- struct ieee80211_tx_control *control = tx->u.tx.control;
++ struct ieee80211_tx_control *control = tx->control;
++
++ sband = tx->local->hw.wiphy->bands[tx->local->hw.conf.channel->band];
+
+ control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
+- tx->flags |= IEEE80211_TXRXD_TX_INJECTED;
+- tx->flags &= ~IEEE80211_TXRXD_FRAGMENTED;
++ tx->flags |= IEEE80211_TX_INJECTED;
++ tx->flags &= ~IEEE80211_TX_FRAGMENTED;
+
+ /*
+ * for every radiotap entry that is present
+@@ -852,11 +890,13 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_txrx_data *tx,
+ * ieee80211 rate int is in 100kbps units eg, 0x0a=1Mbps
+ */
+ target_rate = (*iterator.this_arg) * 5;
+- for (i = 0; i < mode->num_rates; i++) {
+- struct ieee80211_rate *r = &mode->rates[i];
++ for (i = 0; i < sband->n_bitrates; i++) {
++ struct ieee80211_rate *r;
++
++ r = &sband->bitrates[i];
+
+- if (r->rate == target_rate) {
+- tx->u.tx.rate = r;
++ if (r->bitrate == target_rate) {
++ tx->rate = r;
+ break;
+ }
+ }
+@@ -870,9 +910,11 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_txrx_data *tx,
+ control->antenna_sel_tx = (*iterator.this_arg) + 1;
+ break;
+
++#if 0
+ case IEEE80211_RADIOTAP_DBM_TX_POWER:
+ control->power_level = *iterator.this_arg;
+ break;
++#endif
+
+ case IEEE80211_RADIOTAP_FLAGS:
+ if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) {
+@@ -884,7 +926,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_txrx_data *tx,
+ * on transmission
+ */
+ if (skb->len < (iterator.max_length + FCS_LEN))
+- return TXRX_DROP;
++ return TX_DROP;
+
+ skb_trim(skb, skb->len - FCS_LEN);
+ }
+@@ -892,7 +934,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_txrx_data *tx,
+ control->flags &=
+ ~IEEE80211_TXCTL_DO_NOT_ENCRYPT;
+ if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG)
+- tx->flags |= IEEE80211_TXRXD_FRAGMENTED;
++ tx->flags |= IEEE80211_TX_FRAGMENTED;
+ break;
+
+ /*
+@@ -907,7 +949,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_txrx_data *tx,
+ }
+
+ if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */
+- return TXRX_DROP;
++ return TX_DROP;
+
+ /*
+ * remove the radiotap header
+@@ -916,14 +958,14 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_txrx_data *tx,
+ */
+ skb_pull(skb, iterator.max_length);
+
+- return TXRX_CONTINUE;
++ return TX_CONTINUE;
+ }
+
+ /*
+ * initialises @tx
+ */
+-static ieee80211_txrx_result
+-__ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
++static ieee80211_tx_result
++__ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
+ struct sk_buff *skb,
+ struct net_device *dev,
+ struct ieee80211_tx_control *control)
+@@ -939,18 +981,18 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
+ tx->dev = dev; /* use original interface */
+ tx->local = local;
+ tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- tx->u.tx.control = control;
++ tx->control = control;
+ /*
+ * Set this flag (used below to indicate "automatic fragmentation"),
+ * it will be cleared/left by radiotap as desired.
+ */
+- tx->flags |= IEEE80211_TXRXD_FRAGMENTED;
++ tx->flags |= IEEE80211_TX_FRAGMENTED;
+
+ /* process and remove the injection radiotap header */
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ if (unlikely(sdata->vif.type == IEEE80211_IF_TYPE_MNTR)) {
+- if (__ieee80211_parse_tx_radiotap(tx, skb) == TXRX_DROP)
+- return TXRX_DROP;
++ if (__ieee80211_parse_tx_radiotap(tx, skb) == TX_DROP)
++ return TX_DROP;
+
+ /*
+ * __ieee80211_parse_tx_radiotap has now removed
+@@ -965,27 +1007,27 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
+ tx->fc = le16_to_cpu(hdr->frame_control);
+
+ if (is_multicast_ether_addr(hdr->addr1)) {
+- tx->flags &= ~IEEE80211_TXRXD_TXUNICAST;
++ tx->flags &= ~IEEE80211_TX_UNICAST;
+ control->flags |= IEEE80211_TXCTL_NO_ACK;
+ } else {
+- tx->flags |= IEEE80211_TXRXD_TXUNICAST;
++ tx->flags |= IEEE80211_TX_UNICAST;
+ control->flags &= ~IEEE80211_TXCTL_NO_ACK;
+ }
+
+- if (tx->flags & IEEE80211_TXRXD_FRAGMENTED) {
+- if ((tx->flags & IEEE80211_TXRXD_TXUNICAST) &&
++ if (tx->flags & IEEE80211_TX_FRAGMENTED) {
++ if ((tx->flags & IEEE80211_TX_UNICAST) &&
+ skb->len + FCS_LEN > local->fragmentation_threshold &&
+ !local->ops->set_frag_threshold)
+- tx->flags |= IEEE80211_TXRXD_FRAGMENTED;
++ tx->flags |= IEEE80211_TX_FRAGMENTED;
+ else
+- tx->flags &= ~IEEE80211_TXRXD_FRAGMENTED;
++ tx->flags &= ~IEEE80211_TX_FRAGMENTED;
+ }
+
+ if (!tx->sta)
+- control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;
+- else if (tx->sta->clear_dst_mask) {
+- control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;
+- tx->sta->clear_dst_mask = 0;
++ control->flags |= IEEE80211_TXCTL_CLEAR_PS_FILT;
++ else if (tx->sta->flags & WLAN_STA_CLEAR_PS_FILT) {
++ control->flags |= IEEE80211_TXCTL_CLEAR_PS_FILT;
++ tx->sta->flags &= ~WLAN_STA_CLEAR_PS_FILT;
+ }
+
+ hdrlen = ieee80211_get_hdrlen(tx->fc);
+@@ -995,13 +1037,13 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
+ }
+ control->flags |= IEEE80211_TXCTL_FIRST_FRAGMENT;
+
+- return TXRX_CONTINUE;
++ return TX_CONTINUE;
+ }
+
+ /*
+ * NB: @tx is uninitialised when passed in here
+ */
+-static int ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
++static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
+ struct sk_buff *skb,
+ struct net_device *mdev,
+ struct ieee80211_tx_control *control)
+@@ -1024,9 +1066,9 @@ static int ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
+ }
+
+ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
+- struct ieee80211_txrx_data *tx)
++ struct ieee80211_tx_data *tx)
+ {
+- struct ieee80211_tx_control *control = tx->u.tx.control;
++ struct ieee80211_tx_control *control = tx->control;
+ int ret, i;
+
+ if (!ieee80211_qdisc_installed(local->mdev) &&
+@@ -1043,20 +1085,20 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
+ local->mdev->trans_start = jiffies;
+ ieee80211_led_tx(local, 1);
+ }
+- if (tx->u.tx.extra_frag) {
++ if (tx->extra_frag) {
+ control->flags &= ~(IEEE80211_TXCTL_USE_RTS_CTS |
+ IEEE80211_TXCTL_USE_CTS_PROTECT |
+- IEEE80211_TXCTL_CLEAR_DST_MASK |
++ IEEE80211_TXCTL_CLEAR_PS_FILT |
+ IEEE80211_TXCTL_FIRST_FRAGMENT);
+- for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+- if (!tx->u.tx.extra_frag[i])
++ for (i = 0; i < tx->num_extra_frag; i++) {
++ if (!tx->extra_frag[i])
+ continue;
+ if (__ieee80211_queue_stopped(local, control->queue))
+ return IEEE80211_TX_FRAG_AGAIN;
+- if (i == tx->u.tx.num_extra_frag) {
+- control->tx_rate = tx->u.tx.last_frag_hwrate;
+- control->rate = tx->u.tx.last_frag_rate;
+- if (tx->flags & IEEE80211_TXRXD_TXPROBE_LAST_FRAG)
++ if (i == tx->num_extra_frag) {
++ control->tx_rate = tx->last_frag_rate;
++
++ if (tx->flags & IEEE80211_TX_PROBE_LAST_FRAG)
+ control->flags |=
+ IEEE80211_TXCTL_RATE_CTRL_PROBE;
+ else
+@@ -1066,18 +1108,18 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
+
+ ieee80211_dump_frame(wiphy_name(local->hw.wiphy),
+ "TX to low-level driver",
+- tx->u.tx.extra_frag[i]);
++ tx->extra_frag[i]);
+ ret = local->ops->tx(local_to_hw(local),
+- tx->u.tx.extra_frag[i],
++ tx->extra_frag[i],
+ control);
+ if (ret)
+ return IEEE80211_TX_FRAG_AGAIN;
+ local->mdev->trans_start = jiffies;
+ ieee80211_led_tx(local, 1);
+- tx->u.tx.extra_frag[i] = NULL;
++ tx->extra_frag[i] = NULL;
+ }
+- kfree(tx->u.tx.extra_frag);
+- tx->u.tx.extra_frag = NULL;
++ kfree(tx->extra_frag);
++ tx->extra_frag = NULL;
+ }
+ return IEEE80211_TX_OK;
+ }
+@@ -1088,8 +1130,8 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct sta_info *sta;
+ ieee80211_tx_handler *handler;
+- struct ieee80211_txrx_data tx;
+- ieee80211_txrx_result res = TXRX_DROP, res_prepare;
++ struct ieee80211_tx_data tx;
++ ieee80211_tx_result res = TX_DROP, res_prepare;
+ int ret, i;
+
+ WARN_ON(__ieee80211_queue_pending(local, control->queue));
+@@ -1099,59 +1141,52 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
+ return 0;
+ }
+
++ rcu_read_lock();
++
+ /* initialises tx */
+ res_prepare = __ieee80211_tx_prepare(&tx, skb, dev, control);
+
+- if (res_prepare == TXRX_DROP) {
++ if (res_prepare == TX_DROP) {
+ dev_kfree_skb(skb);
++ rcu_read_unlock();
+ return 0;
+ }
+
+- /*
+- * key references are protected using RCU and this requires that
+- * we are in a read-site RCU section during receive processing
+- */
+- rcu_read_lock();
+-
+ sta = tx.sta;
+- tx.u.tx.mode = local->hw.conf.mode;
++ tx.channel = local->hw.conf.channel;
+
+- for (handler = local->tx_handlers; *handler != NULL;
++ for (handler = ieee80211_tx_handlers; *handler != NULL;
+ handler++) {
+ res = (*handler)(&tx);
+- if (res != TXRX_CONTINUE)
++ if (res != TX_CONTINUE)
+ break;
+ }
+
+ skb = tx.skb; /* handlers are allowed to change skb */
+
+- if (sta)
+- sta_info_put(sta);
+-
+- if (unlikely(res == TXRX_DROP)) {
++ if (unlikely(res == TX_DROP)) {
+ I802_DEBUG_INC(local->tx_handlers_drop);
+ goto drop;
+ }
+
+- if (unlikely(res == TXRX_QUEUED)) {
++ if (unlikely(res == TX_QUEUED)) {
+ I802_DEBUG_INC(local->tx_handlers_queued);
+ rcu_read_unlock();
+ return 0;
+ }
+
+- if (tx.u.tx.extra_frag) {
+- for (i = 0; i < tx.u.tx.num_extra_frag; i++) {
++ if (tx.extra_frag) {
++ for (i = 0; i < tx.num_extra_frag; i++) {
+ int next_len, dur;
+ struct ieee80211_hdr *hdr =
+ (struct ieee80211_hdr *)
+- tx.u.tx.extra_frag[i]->data;
++ tx.extra_frag[i]->data;
+
+- if (i + 1 < tx.u.tx.num_extra_frag) {
+- next_len = tx.u.tx.extra_frag[i + 1]->len;
++ if (i + 1 < tx.num_extra_frag) {
++ next_len = tx.extra_frag[i + 1]->len;
+ } else {
+ next_len = 0;
+- tx.u.tx.rate = tx.u.tx.last_frag_rate;
+- tx.u.tx.last_frag_hwrate = tx.u.tx.rate->val;
++ tx.rate = tx.last_frag_rate;
+ }
+ dur = ieee80211_duration(&tx, 0, next_len);
+ hdr->duration_id = cpu_to_le16(dur);
+@@ -1186,12 +1221,11 @@ retry:
+ memcpy(&store->control, control,
+ sizeof(struct ieee80211_tx_control));
+ store->skb = skb;
+- store->extra_frag = tx.u.tx.extra_frag;
+- store->num_extra_frag = tx.u.tx.num_extra_frag;
+- store->last_frag_hwrate = tx.u.tx.last_frag_hwrate;
+- store->last_frag_rate = tx.u.tx.last_frag_rate;
++ store->extra_frag = tx.extra_frag;
++ store->num_extra_frag = tx.num_extra_frag;
++ store->last_frag_rate = tx.last_frag_rate;
+ store->last_frag_rate_ctrl_probe =
+- !!(tx.flags & IEEE80211_TXRXD_TXPROBE_LAST_FRAG);
++ !!(tx.flags & IEEE80211_TX_PROBE_LAST_FRAG);
+ }
+ rcu_read_unlock();
+ return 0;
+@@ -1199,10 +1233,10 @@ retry:
+ drop:
+ if (skb)
+ dev_kfree_skb(skb);
+- for (i = 0; i < tx.u.tx.num_extra_frag; i++)
+- if (tx.u.tx.extra_frag[i])
+- dev_kfree_skb(tx.u.tx.extra_frag[i]);
+- kfree(tx.u.tx.extra_frag);
++ for (i = 0; i < tx.num_extra_frag; i++)
++ if (tx.extra_frag[i])
++ dev_kfree_skb(tx.extra_frag[i]);
++ kfree(tx.extra_frag);
+ rcu_read_unlock();
+ return 0;
+ }
+@@ -1260,6 +1294,8 @@ int ieee80211_master_start_xmit(struct sk_buff *skb,
+ control.flags |= IEEE80211_TXCTL_REQUEUE;
+ if (pkt_data->flags & IEEE80211_TXPD_EAPOL_FRAME)
+ control.flags |= IEEE80211_TXCTL_EAPOL_FRAME;
++ if (pkt_data->flags & IEEE80211_TXPD_AMPDU)
++ control.flags |= IEEE80211_TXCTL_AMPDU;
+ control.queue = pkt_data->queue;
+
+ ret = ieee80211_tx(odev, skb, &control);
+@@ -1346,8 +1382,9 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
+ struct ieee80211_tx_packet_data *pkt_data;
+ struct ieee80211_sub_if_data *sdata;
+ int ret = 1, head_need;
+- u16 ethertype, hdrlen, fc;
++ u16 ethertype, hdrlen, meshhdrlen = 0, fc;
+ struct ieee80211_hdr hdr;
++ struct ieee80211s_hdr mesh_hdr;
+ const u8 *encaps_data;
+ int encaps_len, skip_header_bytes;
+ int nh_pos, h_pos;
+@@ -1389,6 +1426,37 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
+ memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
+ hdrlen = 30;
+ break;
++#ifdef CONFIG_MAC80211_MESH
++ case IEEE80211_IF_TYPE_MESH_POINT:
++ fc |= IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS;
++ /* RA TA DA SA */
++ if (is_multicast_ether_addr(skb->data))
++ memcpy(hdr.addr1, skb->data, ETH_ALEN);
++ else if (mesh_nexthop_lookup(hdr.addr1, skb, dev))
++ return 0;
++ memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
++ memcpy(hdr.addr3, skb->data, ETH_ALEN);
++ memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
++ if (skb->pkt_type == PACKET_OTHERHOST) {
++ /* Forwarded frame, keep mesh ttl and seqnum */
++ struct ieee80211s_hdr *prev_meshhdr;
++ prev_meshhdr = ((struct ieee80211s_hdr *)skb->cb);
++ meshhdrlen = ieee80211_get_mesh_hdrlen(prev_meshhdr);
++ memcpy(&mesh_hdr, prev_meshhdr, meshhdrlen);
++ sdata->u.sta.mshstats.fwded_frames++;
++ } else {
++ if (!sdata->u.sta.mshcfg.dot11MeshTTL) {
++ /* Do not send frames with mesh_ttl == 0 */
++ sdata->u.sta.mshstats.dropped_frames_ttl++;
++ ret = 0;
++ goto fail;
++ }
++ meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr,
++ sdata);
++ }
++ hdrlen = 30;
++ break;
++#endif
+ case IEEE80211_IF_TYPE_STA:
+ fc |= IEEE80211_FCTL_TODS;
+ /* BSSID SA DA */
+@@ -1409,10 +1477,17 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
+ goto fail;
+ }
+
+- sta = sta_info_get(local, hdr.addr1);
+- if (sta) {
+- sta_flags = sta->flags;
+- sta_info_put(sta);
++ /*
++ * There's no need to try to look up the destination
++ * if it is a multicast address (which can only happen
++ * in AP mode)
++ */
++ if (!is_multicast_ether_addr(hdr.addr1)) {
++ rcu_read_lock();
++ sta = sta_info_get(local, hdr.addr1);
++ if (sta)
++ sta_flags = sta->flags;
++ rcu_read_unlock();
+ }
+
+ /* receiver is QoS enabled, use a QoS type frame */
+@@ -1422,12 +1497,12 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
+ }
+
+ /*
+- * If port access control is enabled, drop frames to unauthorised
+- * stations unless they are EAPOL frames from the local station.
++ * Drop unicast frames to unauthorised stations unless they are
++ * EAPOL frames from the local station.
+ */
+- if (unlikely(sdata->ieee802_1x_pac &&
+- !(sta_flags & WLAN_STA_AUTHORIZED) &&
+- !(ethertype == ETH_P_PAE &&
++ if (unlikely(!is_multicast_ether_addr(hdr.addr1) &&
++ !(sta_flags & WLAN_STA_AUTHORIZED) &&
++ !(ethertype == ETH_P_PAE &&
+ compare_ether_addr(dev->dev_addr,
+ skb->data + ETH_ALEN) == 0))) {
+ #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+@@ -1480,7 +1555,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
+ * build in headroom in __dev_alloc_skb() (linux/skbuff.h) and
+ * alloc_skb() (net/core/skbuff.c)
+ */
+- head_need = hdrlen + encaps_len + local->tx_headroom;
++ head_need = hdrlen + encaps_len + meshhdrlen + local->tx_headroom;
+ head_need -= skb_headroom(skb);
+
+ /* We are going to modify skb data, so make a copy of it if happens to
+@@ -1514,6 +1589,12 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
+ h_pos += encaps_len;
+ }
+
++ if (meshhdrlen > 0) {
++ memcpy(skb_push(skb, meshhdrlen), &mesh_hdr, meshhdrlen);
++ nh_pos += meshhdrlen;
++ h_pos += meshhdrlen;
++ }
++
+ if (fc & IEEE80211_STYPE_QOS_DATA) {
+ __le16 *qos_control;
+
+@@ -1583,7 +1664,7 @@ void ieee80211_tx_pending(unsigned long data)
+ struct ieee80211_local *local = (struct ieee80211_local *)data;
+ struct net_device *dev = local->mdev;
+ struct ieee80211_tx_stored_packet *store;
+- struct ieee80211_txrx_data tx;
++ struct ieee80211_tx_data tx;
+ int i, ret, reschedule = 0;
+
+ netif_tx_lock_bh(dev);
+@@ -1595,14 +1676,13 @@ void ieee80211_tx_pending(unsigned long data)
+ continue;
+ }
+ store = &local->pending_packet[i];
+- tx.u.tx.control = &store->control;
+- tx.u.tx.extra_frag = store->extra_frag;
+- tx.u.tx.num_extra_frag = store->num_extra_frag;
+- tx.u.tx.last_frag_hwrate = store->last_frag_hwrate;
+- tx.u.tx.last_frag_rate = store->last_frag_rate;
++ tx.control = &store->control;
++ tx.extra_frag = store->extra_frag;
++ tx.num_extra_frag = store->num_extra_frag;
++ tx.last_frag_rate = store->last_frag_rate;
+ tx.flags = 0;
+ if (store->last_frag_rate_ctrl_probe)
+- tx.flags |= IEEE80211_TXRXD_TXPROBE_LAST_FRAG;
++ tx.flags |= IEEE80211_TX_PROBE_LAST_FRAG;
+ ret = __ieee80211_tx(local, store->skb, &tx);
+ if (ret) {
+ if (ret == IEEE80211_TX_FRAG_AGAIN)
+@@ -1636,7 +1716,6 @@ static void ieee80211_beacon_add_tim(struct ieee80211_local *local,
+
+ /* Generate bitmap for TIM only if there are any STAs in power save
+ * mode. */
+- read_lock_bh(&local->sta_lock);
+ if (atomic_read(&bss->num_sta_ps) > 0)
+ /* in the hope that this is faster than
+ * checking byte-for-byte */
+@@ -1687,7 +1766,6 @@ static void ieee80211_beacon_add_tim(struct ieee80211_local *local,
+ *pos++ = aid0; /* Bitmap control */
+ *pos++ = 0; /* Part Virt Bitmap */
+ }
+- read_unlock_bh(&local->sta_lock);
+ }
+
+ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
+@@ -1701,16 +1779,96 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
+ struct ieee80211_if_ap *ap = NULL;
+ struct rate_selection rsel;
+ struct beacon_data *beacon;
++ struct ieee80211_supported_band *sband;
++ struct ieee80211_mgmt *mgmt;
++ int *num_beacons;
++ bool err = true;
++ u8 *pos;
++
++ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+
+ rcu_read_lock();
+
+ sdata = vif_to_sdata(vif);
+ bdev = sdata->dev;
+- ap = &sdata->u.ap;
+
+- beacon = rcu_dereference(ap->beacon);
++ if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
++ ap = &sdata->u.ap;
++ beacon = rcu_dereference(ap->beacon);
++ if (ap && beacon) {
++ /*
++ * headroom, head length,
++ * tail length and maximum TIM length
++ */
++ skb = dev_alloc_skb(local->tx_headroom +
++ beacon->head_len +
++ beacon->tail_len + 256);
++ if (!skb)
++ goto out;
++
++ skb_reserve(skb, local->tx_headroom);
++ memcpy(skb_put(skb, beacon->head_len), beacon->head,
++ beacon->head_len);
++
++ ieee80211_include_sequence(sdata,
++ (struct ieee80211_hdr *)skb->data);
++
++ /*
++ * Not very nice, but we want to allow the driver to call
++ * ieee80211_beacon_get() as a response to the set_tim()
++ * callback. That, however, is already invoked under the
++ * sta_lock to guarantee consistent and race-free update
++ * of the tim bitmap in mac80211 and the driver.
++ */
++ if (local->tim_in_locked_section) {
++ ieee80211_beacon_add_tim(local, ap, skb, beacon);
++ } else {
++ unsigned long flags;
++
++ spin_lock_irqsave(&local->sta_lock, flags);
++ ieee80211_beacon_add_tim(local, ap, skb, beacon);
++ spin_unlock_irqrestore(&local->sta_lock, flags);
++ }
++
++ if (beacon->tail)
++ memcpy(skb_put(skb, beacon->tail_len),
++ beacon->tail, beacon->tail_len);
+
+- if (!ap || sdata->vif.type != IEEE80211_IF_TYPE_AP || !beacon) {
++ num_beacons = &ap->num_beacons;
++
++ err = false;
++ }
++ } else if (ieee80211_vif_is_mesh(&sdata->vif)) {
++ /* headroom, head length, tail length and maximum TIM length */
++ skb = dev_alloc_skb(local->tx_headroom + 400);
++ if (!skb)
++ goto out;
++
++ skb_reserve(skb, local->hw.extra_tx_headroom);
++ mgmt = (struct ieee80211_mgmt *)
++ skb_put(skb, 24 + sizeof(mgmt->u.beacon));
++ memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
++ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
++ IEEE80211_STYPE_BEACON);
++ memset(mgmt->da, 0xff, ETH_ALEN);
++ memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
++ /* BSSID is left zeroed, wildcard value */
++ mgmt->u.beacon.beacon_int =
++ cpu_to_le16(local->hw.conf.beacon_int);
++ mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */
++
++ pos = skb_put(skb, 2);
++ *pos++ = WLAN_EID_SSID;
++ *pos++ = 0x0;
++
++ mesh_mgmt_ies_add(skb, sdata->dev);
++
++ num_beacons = &sdata->u.sta.num_beacons;
++
++ err = false;
++ }
++
++ if (err) {
+ #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+ if (net_ratelimit())
+ printk(KERN_DEBUG "no beacon data avail for %s\n",
+@@ -1720,27 +1878,8 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
+ goto out;
+ }
+
+- /* headroom, head length, tail length and maximum TIM length */
+- skb = dev_alloc_skb(local->tx_headroom + beacon->head_len +
+- beacon->tail_len + 256);
+- if (!skb)
+- goto out;
+-
+- skb_reserve(skb, local->tx_headroom);
+- memcpy(skb_put(skb, beacon->head_len), beacon->head,
+- beacon->head_len);
+-
+- ieee80211_include_sequence(sdata, (struct ieee80211_hdr *)skb->data);
+-
+- ieee80211_beacon_add_tim(local, ap, skb, beacon);
+-
+- if (beacon->tail)
+- memcpy(skb_put(skb, beacon->tail_len), beacon->tail,
+- beacon->tail_len);
+-
+ if (control) {
+- rate_control_get_rate(local->mdev, local->oper_hw_mode, skb,
+- &rsel);
++ rate_control_get_rate(local->mdev, sband, skb, &rsel);
+ if (!rsel.rate) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "%s: ieee80211_beacon_get: "
+@@ -1753,20 +1892,17 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
+ }
+
+ control->vif = vif;
+- control->tx_rate =
+- (sdata->bss_conf.use_short_preamble &&
+- (rsel.rate->flags & IEEE80211_RATE_PREAMBLE2)) ?
+- rsel.rate->val2 : rsel.rate->val;
++ control->tx_rate = rsel.rate;
++ if (sdata->bss_conf.use_short_preamble &&
++ rsel.rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
++ control->flags |= IEEE80211_TXCTL_SHORT_PREAMBLE;
+ control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
+- control->power_level = local->hw.conf.power_level;
+ control->flags |= IEEE80211_TXCTL_NO_ACK;
+ control->retry_limit = 1;
+- control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;
++ control->flags |= IEEE80211_TXCTL_CLEAR_PS_FILT;
+ }
+-
+- ap->num_beacons++;
+-
+- out:
++ (*num_beacons)++;
++out:
+ rcu_read_unlock();
+ return skb;
+ }
+@@ -1814,8 +1950,8 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
+ struct sk_buff *skb;
+ struct sta_info *sta;
+ ieee80211_tx_handler *handler;
+- struct ieee80211_txrx_data tx;
+- ieee80211_txrx_result res = TXRX_DROP;
++ struct ieee80211_tx_data tx;
++ ieee80211_tx_result res = TX_DROP;
+ struct net_device *bdev;
+ struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_if_ap *bss = NULL;
+@@ -1836,7 +1972,6 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
+ rcu_read_unlock();
+ return NULL;
+ }
+- rcu_read_unlock();
+
+ if (bss->dtim_count != 0)
+ return NULL; /* send buffered bc/mc only after DTIM beacon */
+@@ -1862,27 +1997,26 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
+ dev_kfree_skb_any(skb);
+ }
+ sta = tx.sta;
+- tx.flags |= IEEE80211_TXRXD_TXPS_BUFFERED;
+- tx.u.tx.mode = local->hw.conf.mode;
++ tx.flags |= IEEE80211_TX_PS_BUFFERED;
++ tx.channel = local->hw.conf.channel;
+
+- for (handler = local->tx_handlers; *handler != NULL; handler++) {
++ for (handler = ieee80211_tx_handlers; *handler != NULL; handler++) {
+ res = (*handler)(&tx);
+- if (res == TXRX_DROP || res == TXRX_QUEUED)
++ if (res == TX_DROP || res == TX_QUEUED)
+ break;
+ }
+ skb = tx.skb; /* handlers are allowed to change skb */
+
+- if (res == TXRX_DROP) {
++ if (res == TX_DROP) {
+ I802_DEBUG_INC(local->tx_handlers_drop);
+ dev_kfree_skb(skb);
+ skb = NULL;
+- } else if (res == TXRX_QUEUED) {
++ } else if (res == TX_QUEUED) {
+ I802_DEBUG_INC(local->tx_handlers_queued);
+ skb = NULL;
+ }
+
+- if (sta)
+- sta_info_put(sta);
++ rcu_read_unlock();
+
+ return skb;
+ }
+diff --git a/net/mac80211/util.c b/net/mac80211/util.c
+index 5e631ce..cc9f715 100644
+--- a/net/mac80211/util.c
++++ b/net/mac80211/util.c
+@@ -25,7 +25,8 @@
+ #include <net/rtnetlink.h>
+
+ #include "ieee80211_i.h"
+-#include "ieee80211_rate.h"
++#include "rate.h"
++#include "mesh.h"
+ #include "wme.h"
+
+ /* privid for wiphys to determine whether they belong to us or not */
+@@ -41,92 +42,6 @@ const unsigned char bridge_tunnel_header[] =
+ { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
+
+
+-static int rate_list_match(const int *rate_list, int rate)
+-{
+- int i;
+-
+- if (!rate_list)
+- return 0;
+-
+- for (i = 0; rate_list[i] >= 0; i++)
+- if (rate_list[i] == rate)
+- return 1;
+-
+- return 0;
+-}
+-
+-void ieee80211_prepare_rates(struct ieee80211_local *local,
+- struct ieee80211_hw_mode *mode)
+-{
+- int i;
+-
+- for (i = 0; i < mode->num_rates; i++) {
+- struct ieee80211_rate *rate = &mode->rates[i];
+-
+- rate->flags &= ~(IEEE80211_RATE_SUPPORTED |
+- IEEE80211_RATE_BASIC);
+-
+- if (local->supp_rates[mode->mode]) {
+- if (!rate_list_match(local->supp_rates[mode->mode],
+- rate->rate))
+- continue;
+- }
+-
+- rate->flags |= IEEE80211_RATE_SUPPORTED;
+-
+- /* Use configured basic rate set if it is available. If not,
+- * use defaults that are sane for most cases. */
+- if (local->basic_rates[mode->mode]) {
+- if (rate_list_match(local->basic_rates[mode->mode],
+- rate->rate))
+- rate->flags |= IEEE80211_RATE_BASIC;
+- } else switch (mode->mode) {
+- case MODE_IEEE80211A:
+- if (rate->rate == 60 || rate->rate == 120 ||
+- rate->rate == 240)
+- rate->flags |= IEEE80211_RATE_BASIC;
+- break;
+- case MODE_IEEE80211B:
+- if (rate->rate == 10 || rate->rate == 20)
+- rate->flags |= IEEE80211_RATE_BASIC;
+- break;
+- case MODE_IEEE80211G:
+- if (rate->rate == 10 || rate->rate == 20 ||
+- rate->rate == 55 || rate->rate == 110)
+- rate->flags |= IEEE80211_RATE_BASIC;
+- break;
+- case NUM_IEEE80211_MODES:
+- /* not useful */
+- break;
+- }
+-
+- /* Set ERP and MANDATORY flags based on phymode */
+- switch (mode->mode) {
+- case MODE_IEEE80211A:
+- if (rate->rate == 60 || rate->rate == 120 ||
+- rate->rate == 240)
+- rate->flags |= IEEE80211_RATE_MANDATORY;
+- break;
+- case MODE_IEEE80211B:
+- if (rate->rate == 10)
+- rate->flags |= IEEE80211_RATE_MANDATORY;
+- break;
+- case MODE_IEEE80211G:
+- if (rate->rate == 10 || rate->rate == 20 ||
+- rate->rate == 55 || rate->rate == 110 ||
+- rate->rate == 60 || rate->rate == 120 ||
+- rate->rate == 240)
+- rate->flags |= IEEE80211_RATE_MANDATORY;
+- break;
+- case NUM_IEEE80211_MODES:
+- /* not useful */
+- break;
+- }
+- if (ieee80211_is_erp_rate(mode->mode, rate->rate))
+- rate->flags |= IEEE80211_RATE_ERP;
+- }
+-}
+-
+ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
+ enum ieee80211_if_types type)
+ {
+@@ -232,17 +147,35 @@ int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)
+ }
+ EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
+
+-void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx)
++int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
++{
++ int ae = meshhdr->flags & IEEE80211S_FLAGS_AE;
++ /* 7.1.3.5a.2 */
++ switch (ae) {
++ case 0:
++ return 5;
++ case 1:
++ return 11;
++ case 2:
++ return 17;
++ case 3:
++ return 23;
++ default:
++ return 5;
++ }
++}
++
++void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx)
+ {
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
+
+ hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+- if (tx->u.tx.extra_frag) {
++ if (tx->extra_frag) {
+ struct ieee80211_hdr *fhdr;
+ int i;
+- for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
++ for (i = 0; i < tx->num_extra_frag; i++) {
+ fhdr = (struct ieee80211_hdr *)
+- tx->u.tx.extra_frag[i]->data;
++ tx->extra_frag[i]->data;
+ fhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+ }
+ }
+@@ -262,7 +195,7 @@ int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
+ * DIV_ROUND_UP() operations.
+ */
+
+- if (local->hw.conf.phymode == MODE_IEEE80211A || erp) {
++ if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ || erp) {
+ /*
+ * OFDM:
+ *
+@@ -304,15 +237,19 @@ int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
+ /* Exported duration function for driver use */
+ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+- size_t frame_len, int rate)
++ size_t frame_len,
++ struct ieee80211_rate *rate)
+ {
+ struct ieee80211_local *local = hw_to_local(hw);
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+ u16 dur;
+ int erp;
+
+- erp = ieee80211_is_erp_rate(hw->conf.phymode, rate);
+- dur = ieee80211_frame_duration(local, frame_len, rate, erp,
++ erp = 0;
++ if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
++ erp = rate->flags & IEEE80211_RATE_ERP_G;
++
++ dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, erp,
+ sdata->bss_conf.use_short_preamble);
+
+ return cpu_to_le16(dur);
+@@ -332,17 +269,20 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
+
+ short_preamble = sdata->bss_conf.use_short_preamble;
+
+- rate = frame_txctl->rts_rate;
+- erp = !!(rate->flags & IEEE80211_RATE_ERP);
++ rate = frame_txctl->rts_cts_rate;
++
++ erp = 0;
++ if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
++ erp = rate->flags & IEEE80211_RATE_ERP_G;
+
+ /* CTS duration */
+- dur = ieee80211_frame_duration(local, 10, rate->rate,
++ dur = ieee80211_frame_duration(local, 10, rate->bitrate,
+ erp, short_preamble);
+ /* Data frame duration */
+- dur += ieee80211_frame_duration(local, frame_len, rate->rate,
++ dur += ieee80211_frame_duration(local, frame_len, rate->bitrate,
+ erp, short_preamble);
+ /* ACK duration */
+- dur += ieee80211_frame_duration(local, 10, rate->rate,
++ dur += ieee80211_frame_duration(local, 10, rate->bitrate,
+ erp, short_preamble);
+
+ return cpu_to_le16(dur);
+@@ -363,15 +303,17 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
+
+ short_preamble = sdata->bss_conf.use_short_preamble;
+
+- rate = frame_txctl->rts_rate;
+- erp = !!(rate->flags & IEEE80211_RATE_ERP);
++ rate = frame_txctl->rts_cts_rate;
++ erp = 0;
++ if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
++ erp = rate->flags & IEEE80211_RATE_ERP_G;
+
+ /* Data frame duration */
+- dur = ieee80211_frame_duration(local, frame_len, rate->rate,
++ dur = ieee80211_frame_duration(local, frame_len, rate->bitrate,
+ erp, short_preamble);
+ if (!(frame_txctl->flags & IEEE80211_TXCTL_NO_ACK)) {
+ /* ACK duration */
+- dur += ieee80211_frame_duration(local, 10, rate->rate,
++ dur += ieee80211_frame_duration(local, 10, rate->bitrate,
+ erp, short_preamble);
+ }
+
+@@ -379,27 +321,6 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
+ }
+ EXPORT_SYMBOL(ieee80211_ctstoself_duration);
+
+-struct ieee80211_rate *
+-ieee80211_get_rate(struct ieee80211_local *local, int phymode, int hw_rate)
+-{
+- struct ieee80211_hw_mode *mode;
+- int r;
+-
+- list_for_each_entry(mode, &local->modes_list, list) {
+- if (mode->mode != phymode)
+- continue;
+- for (r = 0; r < mode->num_rates; r++) {
+- struct ieee80211_rate *rate = &mode->rates[r];
+- if (rate->val == hw_rate ||
+- (rate->flags & IEEE80211_RATE_PREAMBLE2 &&
+- rate->val2 == hw_rate))
+- return rate;
+- }
+- }
+-
+- return NULL;
+-}
+-
+ void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue)
+ {
+ struct ieee80211_local *local = hw_to_local(hw);
+@@ -480,6 +401,7 @@ void ieee80211_iterate_active_interfaces(
+ case IEEE80211_IF_TYPE_STA:
+ case IEEE80211_IF_TYPE_IBSS:
+ case IEEE80211_IF_TYPE_WDS:
++ case IEEE80211_IF_TYPE_MESH_POINT:
+ break;
+ }
+ if (sdata->dev == local->mdev)
+diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c
+index a0cff72..affcecd 100644
+--- a/net/mac80211/wep.c
++++ b/net/mac80211/wep.c
+@@ -305,39 +305,39 @@ u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key)
+ return NULL;
+ }
+
+-ieee80211_txrx_result
+-ieee80211_crypto_wep_decrypt(struct ieee80211_txrx_data *rx)
++ieee80211_rx_result
++ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx)
+ {
+ if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA &&
+ ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT ||
+ (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH))
+- return TXRX_CONTINUE;
++ return RX_CONTINUE;
+
+- if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED)) {
++ if (!(rx->status->flag & RX_FLAG_DECRYPTED)) {
+ if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) {
+ #ifdef CONFIG_MAC80211_DEBUG
+ if (net_ratelimit())
+ printk(KERN_DEBUG "%s: RX WEP frame, decrypt "
+ "failed\n", rx->dev->name);
+ #endif /* CONFIG_MAC80211_DEBUG */
+- return TXRX_DROP;
++ return RX_DROP_UNUSABLE;
+ }
+- } else if (!(rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED)) {
++ } else if (!(rx->status->flag & RX_FLAG_IV_STRIPPED)) {
+ ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key);
+ /* remove ICV */
+ skb_trim(rx->skb, rx->skb->len - 4);
+ }
+
+- return TXRX_CONTINUE;
++ return RX_CONTINUE;
+ }
+
+-static int wep_encrypt_skb(struct ieee80211_txrx_data *tx, struct sk_buff *skb)
++static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
+ {
+ if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
+ if (ieee80211_wep_encrypt(tx->local, skb, tx->key))
+ return -1;
+ } else {
+- tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx;
++ tx->control->key_idx = tx->key->conf.hw_key_idx;
+ if (tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) {
+ if (!ieee80211_wep_add_iv(tx->local, skb, tx->key))
+ return -1;
+@@ -346,28 +346,28 @@ static int wep_encrypt_skb(struct ieee80211_txrx_data *tx, struct sk_buff *skb)
+ return 0;
+ }
+
+-ieee80211_txrx_result
+-ieee80211_crypto_wep_encrypt(struct ieee80211_txrx_data *tx)
++ieee80211_tx_result
++ieee80211_crypto_wep_encrypt(struct ieee80211_tx_data *tx)
+ {
+- tx->u.tx.control->iv_len = WEP_IV_LEN;
+- tx->u.tx.control->icv_len = WEP_ICV_LEN;
+- ieee80211_tx_set_iswep(tx);
++ tx->control->iv_len = WEP_IV_LEN;
++ tx->control->icv_len = WEP_ICV_LEN;
++ ieee80211_tx_set_protected(tx);
+
+ if (wep_encrypt_skb(tx, tx->skb) < 0) {
+ I802_DEBUG_INC(tx->local->tx_handlers_drop_wep);
+- return TXRX_DROP;
++ return TX_DROP;
+ }
+
+- if (tx->u.tx.extra_frag) {
++ if (tx->extra_frag) {
+ int i;
+- for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+- if (wep_encrypt_skb(tx, tx->u.tx.extra_frag[i]) < 0) {
++ for (i = 0; i < tx->num_extra_frag; i++) {
++ if (wep_encrypt_skb(tx, tx->extra_frag[i]) < 0) {
+ I802_DEBUG_INC(tx->local->
+ tx_handlers_drop_wep);
+- return TXRX_DROP;
++ return TX_DROP;
+ }
+ }
+ }
+
+- return TXRX_CONTINUE;
++ return TX_CONTINUE;
+ }
+diff --git a/net/mac80211/wep.h b/net/mac80211/wep.h
+index 785fbb4..363779c 100644
+--- a/net/mac80211/wep.h
++++ b/net/mac80211/wep.h
+@@ -14,7 +14,7 @@
+ #include <linux/skbuff.h>
+ #include <linux/types.h>
+ #include "ieee80211_i.h"
+-#include "ieee80211_key.h"
++#include "key.h"
+
+ int ieee80211_wep_init(struct ieee80211_local *local);
+ void ieee80211_wep_free(struct ieee80211_local *local);
+@@ -28,9 +28,9 @@ int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb,
+ struct ieee80211_key *key);
+ u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key);
+
+-ieee80211_txrx_result
+-ieee80211_crypto_wep_decrypt(struct ieee80211_txrx_data *rx);
+-ieee80211_txrx_result
+-ieee80211_crypto_wep_encrypt(struct ieee80211_txrx_data *tx);
++ieee80211_rx_result
++ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx);
++ieee80211_tx_result
++ieee80211_crypto_wep_encrypt(struct ieee80211_tx_data *tx);
+
+ #endif /* WEP_H */
+diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
+new file mode 100644
+index 0000000..76e1de1
+--- /dev/null
++++ b/net/mac80211/wext.c
+@@ -0,0 +1,1152 @@
++/*
++ * Copyright 2002-2005, Instant802 Networks, Inc.
++ * Copyright 2005-2006, Devicescape Software, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/netdevice.h>
++#include <linux/types.h>
++#include <linux/slab.h>
++#include <linux/skbuff.h>
++#include <linux/etherdevice.h>
++#include <linux/if_arp.h>
++#include <linux/wireless.h>
++#include <net/iw_handler.h>
++#include <asm/uaccess.h>
++
++#include <net/mac80211.h>
++#include "ieee80211_i.h"
++#include "led.h"
++#include "rate.h"
++#include "wpa.h"
++#include "aes_ccm.h"
++
++
++static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
++ int idx, int alg, int remove,
++ int set_tx_key, const u8 *_key,
++ size_t key_len)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct sta_info *sta;
++ struct ieee80211_key *key;
++ struct ieee80211_sub_if_data *sdata;
++ int err;
++
++ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++ if (idx < 0 || idx >= NUM_DEFAULT_KEYS) {
++ printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n",
++ dev->name, idx);
++ return -EINVAL;
++ }
++
++ if (remove) {
++ rcu_read_lock();
++
++ err = 0;
++
++ if (is_broadcast_ether_addr(sta_addr)) {
++ key = sdata->keys[idx];
++ } else {
++ sta = sta_info_get(local, sta_addr);
++ if (!sta) {
++ err = -ENOENT;
++ goto out_unlock;
++ }
++ key = sta->key;
++ }
++
++ ieee80211_key_free(key);
++ } else {
++ key = ieee80211_key_alloc(alg, idx, key_len, _key);
++ if (!key)
++ return -ENOMEM;
++
++ sta = NULL;
++ err = 0;
++
++ rcu_read_lock();
++
++ if (!is_broadcast_ether_addr(sta_addr)) {
++ set_tx_key = 0;
++ /*
++ * According to the standard, the key index of a
++ * pairwise key must be zero. However, some AP are
++ * broken when it comes to WEP key indices, so we
++ * work around this.
++ */
++ if (idx != 0 && alg != ALG_WEP) {
++ ieee80211_key_free(key);
++ err = -EINVAL;
++ goto out_unlock;
++ }
++
++ sta = sta_info_get(local, sta_addr);
++ if (!sta) {
++ ieee80211_key_free(key);
++ err = -ENOENT;
++ goto out_unlock;
++ }
++ }
++
++ ieee80211_key_link(key, sdata, sta);
++
++ if (set_tx_key || (!sta && !sdata->default_key && key))
++ ieee80211_set_default_key(sdata, idx);
++ }
++
++ out_unlock:
++ rcu_read_unlock();
++
++ return err;
++}
++
++static int ieee80211_ioctl_siwgenie(struct net_device *dev,
++ struct iw_request_info *info,
++ struct iw_point *data, char *extra)
++{
++ struct ieee80211_sub_if_data *sdata;
++
++ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++ if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)
++ return -EOPNOTSUPP;
++
++ if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
++ sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
++ int ret = ieee80211_sta_set_extra_ie(dev, extra, data->length);
++ if (ret)
++ return ret;
++ sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
++ ieee80211_sta_req_auth(dev, &sdata->u.sta);
++ return 0;
++ }
++
++ return -EOPNOTSUPP;
++}
++
++static int ieee80211_ioctl_giwname(struct net_device *dev,
++ struct iw_request_info *info,
++ char *name, char *extra)
++{
++ strcpy(name, "IEEE 802.11");
++
++ return 0;
++}
++
++
++static int ieee80211_ioctl_giwrange(struct net_device *dev,
++ struct iw_request_info *info,
++ struct iw_point *data, char *extra)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct iw_range *range = (struct iw_range *) extra;
++ enum ieee80211_band band;
++ int c = 0;
++
++ data->length = sizeof(struct iw_range);
++ memset(range, 0, sizeof(struct iw_range));
++
++ range->we_version_compiled = WIRELESS_EXT;
++ range->we_version_source = 21;
++ range->retry_capa = IW_RETRY_LIMIT;
++ range->retry_flags = IW_RETRY_LIMIT;
++ range->min_retry = 0;
++ range->max_retry = 255;
++ range->min_rts = 0;
++ range->max_rts = 2347;
++ range->min_frag = 256;
++ range->max_frag = 2346;
++
++ range->encoding_size[0] = 5;
++ range->encoding_size[1] = 13;
++ range->num_encoding_sizes = 2;
++ range->max_encoding_tokens = NUM_DEFAULT_KEYS;
++
++ range->max_qual.qual = local->hw.max_signal;
++ range->max_qual.level = local->hw.max_rssi;
++ range->max_qual.noise = local->hw.max_noise;
++ range->max_qual.updated = local->wstats_flags;
++
++ range->avg_qual.qual = local->hw.max_signal/2;
++ range->avg_qual.level = 0;
++ range->avg_qual.noise = 0;
++ range->avg_qual.updated = local->wstats_flags;
++
++ range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
++ IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
++
++
++ for (band = 0; band < IEEE80211_NUM_BANDS; band ++) {
++ int i;
++ struct ieee80211_supported_band *sband;
++
++ sband = local->hw.wiphy->bands[band];
++
++ if (!sband)
++ continue;
++
++ for (i = 0; i < sband->n_channels && c < IW_MAX_FREQUENCIES; i++) {
++ struct ieee80211_channel *chan = &sband->channels[i];
++
++ if (!(chan->flags & IEEE80211_CHAN_DISABLED)) {
++ range->freq[c].i =
++ ieee80211_frequency_to_channel(
++ chan->center_freq);
++ range->freq[c].m = chan->center_freq;
++ range->freq[c].e = 6;
++ c++;
++ }
++ }
++ }
++ range->num_channels = c;
++ range->num_frequency = c;
++
++ IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
++ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
++ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
++ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
++
++ range->scan_capa |= IW_SCAN_CAPA_ESSID;
++
++ return 0;
++}
++
++
++static int ieee80211_ioctl_siwmode(struct net_device *dev,
++ struct iw_request_info *info,
++ __u32 *mode, char *extra)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ int type;
++
++ if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
++ return -EOPNOTSUPP;
++
++ switch (*mode) {
++ case IW_MODE_INFRA:
++ type = IEEE80211_IF_TYPE_STA;
++ break;
++ case IW_MODE_ADHOC:
++ type = IEEE80211_IF_TYPE_IBSS;
++ break;
++ case IW_MODE_REPEAT:
++ type = IEEE80211_IF_TYPE_WDS;
++ break;
++ case IW_MODE_MONITOR:
++ type = IEEE80211_IF_TYPE_MNTR;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ if (type == sdata->vif.type)
++ return 0;
++ if (netif_running(dev))
++ return -EBUSY;
++
++ ieee80211_if_reinit(dev);
++ ieee80211_if_set_type(dev, type);
++
++ return 0;
++}
++
++
++static int ieee80211_ioctl_giwmode(struct net_device *dev,
++ struct iw_request_info *info,
++ __u32 *mode, char *extra)
++{
++ struct ieee80211_sub_if_data *sdata;
++
++ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ switch (sdata->vif.type) {
++ case IEEE80211_IF_TYPE_AP:
++ *mode = IW_MODE_MASTER;
++ break;
++ case IEEE80211_IF_TYPE_STA:
++ *mode = IW_MODE_INFRA;
++ break;
++ case IEEE80211_IF_TYPE_IBSS:
++ *mode = IW_MODE_ADHOC;
++ break;
++ case IEEE80211_IF_TYPE_MNTR:
++ *mode = IW_MODE_MONITOR;
++ break;
++ case IEEE80211_IF_TYPE_WDS:
++ *mode = IW_MODE_REPEAT;
++ break;
++ case IEEE80211_IF_TYPE_VLAN:
++ *mode = IW_MODE_SECOND; /* FIXME */
++ break;
++ default:
++ *mode = IW_MODE_AUTO;
++ break;
++ }
++ return 0;
++}
++
++int ieee80211_set_freq(struct ieee80211_local *local, int freqMHz)
++{
++ int ret = -EINVAL;
++ struct ieee80211_channel *chan;
++
++ chan = ieee80211_get_channel(local->hw.wiphy, freqMHz);
++
++ if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
++ local->oper_channel = chan;
++
++ if (local->sta_sw_scanning || local->sta_hw_scanning)
++ ret = 0;
++ else
++ ret = ieee80211_hw_config(local);
++
++ rate_control_clear(local);
++ }
++
++ return ret;
++}
++
++static int ieee80211_ioctl_siwfreq(struct net_device *dev,
++ struct iw_request_info *info,
++ struct iw_freq *freq, char *extra)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++ if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
++ sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL;
++
++ /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
++ if (freq->e == 0) {
++ if (freq->m < 0) {
++ if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
++ sdata->u.sta.flags |=
++ IEEE80211_STA_AUTO_CHANNEL_SEL;
++ return 0;
++ } else
++ return ieee80211_set_freq(local,
++ ieee80211_channel_to_frequency(freq->m));
++ } else {
++ int i, div = 1000000;
++ for (i = 0; i < freq->e; i++)
++ div /= 10;
++ if (div > 0)
++ return ieee80211_set_freq(local, freq->m / div);
++ else
++ return -EINVAL;
++ }
++}
++
++
++static int ieee80211_ioctl_giwfreq(struct net_device *dev,
++ struct iw_request_info *info,
++ struct iw_freq *freq, char *extra)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++ freq->m = local->hw.conf.channel->center_freq;
++ freq->e = 6;
++
++ return 0;
++}
++
++
++static int ieee80211_ioctl_siwessid(struct net_device *dev,
++ struct iw_request_info *info,
++ struct iw_point *data, char *ssid)
++{
++ struct ieee80211_sub_if_data *sdata;
++ size_t len = data->length;
++
++ /* iwconfig uses nul termination in SSID.. */
++ if (len > 0 && ssid[len - 1] == '\0')
++ len--;
++
++ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
++ sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
++ int ret;
++ if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) {
++ if (len > IEEE80211_MAX_SSID_LEN)
++ return -EINVAL;
++ memcpy(sdata->u.sta.ssid, ssid, len);
++ sdata->u.sta.ssid_len = len;
++ return 0;
++ }
++ if (data->flags)
++ sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
++ else
++ sdata->u.sta.flags |= IEEE80211_STA_AUTO_SSID_SEL;
++ ret = ieee80211_sta_set_ssid(dev, ssid, len);
++ if (ret)
++ return ret;
++ ieee80211_sta_req_auth(dev, &sdata->u.sta);
++ return 0;
++ }
++
++ if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
++ memcpy(sdata->u.ap.ssid, ssid, len);
++ memset(sdata->u.ap.ssid + len, 0,
++ IEEE80211_MAX_SSID_LEN - len);
++ sdata->u.ap.ssid_len = len;
++ return ieee80211_if_config(dev);
++ }
++ return -EOPNOTSUPP;
++}
++
++
++static int ieee80211_ioctl_giwessid(struct net_device *dev,
++ struct iw_request_info *info,
++ struct iw_point *data, char *ssid)
++{
++ size_t len;
++
++ struct ieee80211_sub_if_data *sdata;
++ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
++ sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
++ int res = ieee80211_sta_get_ssid(dev, ssid, &len);
++ if (res == 0) {
++ data->length = len;
++ data->flags = 1;
++ } else
++ data->flags = 0;
++ return res;
++ }
++
++ if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
++ len = sdata->u.ap.ssid_len;
++ if (len > IW_ESSID_MAX_SIZE)
++ len = IW_ESSID_MAX_SIZE;
++ memcpy(ssid, sdata->u.ap.ssid, len);
++ data->length = len;
++ data->flags = 1;
++ return 0;
++ }
++ return -EOPNOTSUPP;
++}
++
++
++static int ieee80211_ioctl_siwap(struct net_device *dev,
++ struct iw_request_info *info,
++ struct sockaddr *ap_addr, char *extra)
++{
++ struct ieee80211_sub_if_data *sdata;
++
++ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
++ sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
++ int ret;
++ if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) {
++ memcpy(sdata->u.sta.bssid, (u8 *) &ap_addr->sa_data,
++ ETH_ALEN);
++ return 0;
++ }
++ if (is_zero_ether_addr((u8 *) &ap_addr->sa_data))
++ sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL |
++ IEEE80211_STA_AUTO_CHANNEL_SEL;
++ else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data))
++ sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL;
++ else
++ sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
++ ret = ieee80211_sta_set_bssid(dev, (u8 *) &ap_addr->sa_data);
++ if (ret)
++ return ret;
++ ieee80211_sta_req_auth(dev, &sdata->u.sta);
++ return 0;
++ } else if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) {
++ /*
++ * If it is necessary to update the WDS peer address
++ * while the interface is running, then we need to do
++ * more work here, namely if it is running we need to
++ * add a new and remove the old STA entry, this is
++ * normally handled by _open() and _stop().
++ */
++ if (netif_running(dev))
++ return -EBUSY;
++
++ memcpy(&sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data,
++ ETH_ALEN);
++
++ return 0;
++ }
++
++ return -EOPNOTSUPP;
++}
++
++
++static int ieee80211_ioctl_giwap(struct net_device *dev,
++ struct iw_request_info *info,
++ struct sockaddr *ap_addr, char *extra)
++{
++ struct ieee80211_sub_if_data *sdata;
++
++ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
++ sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
++ ap_addr->sa_family = ARPHRD_ETHER;
++ memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN);
++ return 0;
++ } else if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) {
++ ap_addr->sa_family = ARPHRD_ETHER;
++ memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN);
++ return 0;
++ }
++
++ return -EOPNOTSUPP;
++}
++
++
++static int ieee80211_ioctl_siwscan(struct net_device *dev,
++ struct iw_request_info *info,
++ union iwreq_data *wrqu, char *extra)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct iw_scan_req *req = NULL;
++ u8 *ssid = NULL;
++ size_t ssid_len = 0;
++
++ if (!netif_running(dev))
++ return -ENETDOWN;
++
++ if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
++ sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
++ sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT &&
++ sdata->vif.type != IEEE80211_IF_TYPE_AP)
++ return -EOPNOTSUPP;
++
++ /* if SSID was specified explicitly then use that */
++ if (wrqu->data.length == sizeof(struct iw_scan_req) &&
++ wrqu->data.flags & IW_SCAN_THIS_ESSID) {
++ req = (struct iw_scan_req *)extra;
++ ssid = req->essid;
++ ssid_len = req->essid_len;
++ }
++
++ return ieee80211_sta_req_scan(dev, ssid, ssid_len);
++}
++
++
++static int ieee80211_ioctl_giwscan(struct net_device *dev,
++ struct iw_request_info *info,
++ struct iw_point *data, char *extra)
++{
++ int res;
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++ if (local->sta_sw_scanning || local->sta_hw_scanning)
++ return -EAGAIN;
++
++ res = ieee80211_sta_scan_results(dev, extra, data->length);
++ if (res >= 0) {
++ data->length = res;
++ return 0;
++ }
++ data->length = 0;
++ return res;
++}
++
++
++static int ieee80211_ioctl_siwrate(struct net_device *dev,
++ struct iw_request_info *info,
++ struct iw_param *rate, char *extra)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ int i, err = -EINVAL;
++ u32 target_rate = rate->value / 100000;
++ struct ieee80211_sub_if_data *sdata;
++ struct ieee80211_supported_band *sband;
++
++ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ if (!sdata->bss)
++ return -ENODEV;
++
++ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++
++ /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
++ * target_rate = X, rate->fixed = 1 means only rate X
++ * target_rate = X, rate->fixed = 0 means all rates <= X */
++ sdata->bss->max_ratectrl_rateidx = -1;
++ sdata->bss->force_unicast_rateidx = -1;
++ if (rate->value < 0)
++ return 0;
++
++ for (i=0; i< sband->n_bitrates; i++) {
++ struct ieee80211_rate *brate = &sband->bitrates[i];
++ int this_rate = brate->bitrate;
++
++ if (target_rate == this_rate) {
++ sdata->bss->max_ratectrl_rateidx = i;
++ if (rate->fixed)
++ sdata->bss->force_unicast_rateidx = i;
++ err = 0;
++ break;
++ }
++ }
++ return err;
++}
++
++static int ieee80211_ioctl_giwrate(struct net_device *dev,
++ struct iw_request_info *info,
++ struct iw_param *rate, char *extra)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct sta_info *sta;
++ struct ieee80211_sub_if_data *sdata;
++ struct ieee80211_supported_band *sband;
++
++ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++ if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
++ return -EOPNOTSUPP;
++
++ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++
++ rcu_read_lock();
++
++ sta = sta_info_get(local, sdata->u.sta.bssid);
++
++ if (sta && sta->txrate_idx < sband->n_bitrates)
++ rate->value = sband->bitrates[sta->txrate_idx].bitrate;
++ else
++ rate->value = 0;
++
++ rcu_read_unlock();
++
++ if (!sta)
++ return -ENODEV;
++
++ rate->value *= 100000;
++
++ return 0;
++}
++
++static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
++ struct iw_request_info *info,
++ union iwreq_data *data, char *extra)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ bool need_reconfig = 0;
++ int new_power_level;
++
++ if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
++ return -EINVAL;
++ if (data->txpower.flags & IW_TXPOW_RANGE)
++ return -EINVAL;
++
++ if (data->txpower.fixed) {
++ new_power_level = data->txpower.value;
++ } else {
++ /*
++ * Automatic power level. Use maximum power for the current
++ * channel. Should be part of rate control.
++ */
++ struct ieee80211_channel* chan = local->hw.conf.channel;
++ if (!chan)
++ return -EINVAL;
++
++ new_power_level = chan->max_power;
++ }
++
++ if (local->hw.conf.power_level != new_power_level) {
++ local->hw.conf.power_level = new_power_level;
++ need_reconfig = 1;
++ }
++
++ if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {
++ local->hw.conf.radio_enabled = !(data->txpower.disabled);
++ need_reconfig = 1;
++ ieee80211_led_radio(local, local->hw.conf.radio_enabled);
++ }
++
++ if (need_reconfig) {
++ ieee80211_hw_config(local);
++ /* The return value of hw_config is not of big interest here,
++ * as it doesn't say that it failed because of _this_ config
++ * change or something else. Ignore it. */
++ }
++
++ return 0;
++}
++
++static int ieee80211_ioctl_giwtxpower(struct net_device *dev,
++ struct iw_request_info *info,
++ union iwreq_data *data, char *extra)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++ data->txpower.fixed = 1;
++ data->txpower.disabled = !(local->hw.conf.radio_enabled);
++ data->txpower.value = local->hw.conf.power_level;
++ data->txpower.flags = IW_TXPOW_DBM;
++
++ return 0;
++}
++
++static int ieee80211_ioctl_siwrts(struct net_device *dev,
++ struct iw_request_info *info,
++ struct iw_param *rts, char *extra)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++ if (rts->disabled)
++ local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
++ else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD)
++ return -EINVAL;
++ else
++ local->rts_threshold = rts->value;
++
++ /* If the wlan card performs RTS/CTS in hardware/firmware,
++ * configure it here */
++
++ if (local->ops->set_rts_threshold)
++ local->ops->set_rts_threshold(local_to_hw(local),
++ local->rts_threshold);
++
++ return 0;
++}
++
++static int ieee80211_ioctl_giwrts(struct net_device *dev,
++ struct iw_request_info *info,
++ struct iw_param *rts, char *extra)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++ rts->value = local->rts_threshold;
++ rts->disabled = (rts->value >= IEEE80211_MAX_RTS_THRESHOLD);
++ rts->fixed = 1;
++
++ return 0;
++}
++
++
++static int ieee80211_ioctl_siwfrag(struct net_device *dev,
++ struct iw_request_info *info,
++ struct iw_param *frag, char *extra)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++ if (frag->disabled)
++ local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
++ else if (frag->value < 256 ||
++ frag->value > IEEE80211_MAX_FRAG_THRESHOLD)
++ return -EINVAL;
++ else {
++ /* Fragment length must be even, so strip LSB. */
++ local->fragmentation_threshold = frag->value & ~0x1;
++ }
++
++ /* If the wlan card performs fragmentation in hardware/firmware,
++ * configure it here */
++
++ if (local->ops->set_frag_threshold)
++ local->ops->set_frag_threshold(
++ local_to_hw(local),
++ local->fragmentation_threshold);
++
++ return 0;
++}
++
++static int ieee80211_ioctl_giwfrag(struct net_device *dev,
++ struct iw_request_info *info,
++ struct iw_param *frag, char *extra)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++ frag->value = local->fragmentation_threshold;
++ frag->disabled = (frag->value >= IEEE80211_MAX_RTS_THRESHOLD);
++ frag->fixed = 1;
++
++ return 0;
++}
++
++
++static int ieee80211_ioctl_siwretry(struct net_device *dev,
++ struct iw_request_info *info,
++ struct iw_param *retry, char *extra)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++ if (retry->disabled ||
++ (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
++ return -EINVAL;
++
++ if (retry->flags & IW_RETRY_MAX)
++ local->long_retry_limit = retry->value;
++ else if (retry->flags & IW_RETRY_MIN)
++ local->short_retry_limit = retry->value;
++ else {
++ local->long_retry_limit = retry->value;
++ local->short_retry_limit = retry->value;
++ }
++
++ if (local->ops->set_retry_limit) {
++ return local->ops->set_retry_limit(
++ local_to_hw(local),
++ local->short_retry_limit,
++ local->long_retry_limit);
++ }
++
++ return 0;
++}
++
++
++static int ieee80211_ioctl_giwretry(struct net_device *dev,
++ struct iw_request_info *info,
++ struct iw_param *retry, char *extra)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++
++ retry->disabled = 0;
++ if (retry->flags == 0 || retry->flags & IW_RETRY_MIN) {
++ /* first return min value, iwconfig will ask max value
++ * later if needed */
++ retry->flags |= IW_RETRY_LIMIT;
++ retry->value = local->short_retry_limit;
++ if (local->long_retry_limit != local->short_retry_limit)
++ retry->flags |= IW_RETRY_MIN;
++ return 0;
++ }
++ if (retry->flags & IW_RETRY_MAX) {
++ retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
++ retry->value = local->long_retry_limit;
++ }
++
++ return 0;
++}
++
++static int ieee80211_ioctl_siwmlme(struct net_device *dev,
++ struct iw_request_info *info,
++ struct iw_point *data, char *extra)
++{
++ struct ieee80211_sub_if_data *sdata;
++ struct iw_mlme *mlme = (struct iw_mlme *) extra;
++
++ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
++ sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
++ return -EINVAL;
++
++ switch (mlme->cmd) {
++ case IW_MLME_DEAUTH:
++ /* TODO: mlme->addr.sa_data */
++ return ieee80211_sta_deauthenticate(dev, mlme->reason_code);
++ case IW_MLME_DISASSOC:
++ /* TODO: mlme->addr.sa_data */
++ return ieee80211_sta_disassociate(dev, mlme->reason_code);
++ default:
++ return -EOPNOTSUPP;
++ }
++}
++
++
++static int ieee80211_ioctl_siwencode(struct net_device *dev,
++ struct iw_request_info *info,
++ struct iw_point *erq, char *keybuf)
++{
++ struct ieee80211_sub_if_data *sdata;
++ int idx, i, alg = ALG_WEP;
++ u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
++ int remove = 0;
++
++ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++ idx = erq->flags & IW_ENCODE_INDEX;
++ if (idx == 0) {
++ if (sdata->default_key)
++ for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
++ if (sdata->default_key == sdata->keys[i]) {
++ idx = i;
++ break;
++ }
++ }
++ } else if (idx < 1 || idx > 4)
++ return -EINVAL;
++ else
++ idx--;
++
++ if (erq->flags & IW_ENCODE_DISABLED)
++ remove = 1;
++ else if (erq->length == 0) {
++ /* No key data - just set the default TX key index */
++ ieee80211_set_default_key(sdata, idx);
++ return 0;
++ }
++
++ return ieee80211_set_encryption(
++ dev, bcaddr,
++ idx, alg, remove,
++ !sdata->default_key,
++ keybuf, erq->length);
++}
++
++
++static int ieee80211_ioctl_giwencode(struct net_device *dev,
++ struct iw_request_info *info,
++ struct iw_point *erq, char *key)
++{
++ struct ieee80211_sub_if_data *sdata;
++ int idx, i;
++
++ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++
++ idx = erq->flags & IW_ENCODE_INDEX;
++ if (idx < 1 || idx > 4) {
++ idx = -1;
++ if (!sdata->default_key)
++ idx = 0;
++ else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
++ if (sdata->default_key == sdata->keys[i]) {
++ idx = i;
++ break;
++ }
++ }
++ if (idx < 0)
++ return -EINVAL;
++ } else
++ idx--;
++
++ erq->flags = idx + 1;
++
++ if (!sdata->keys[idx]) {
++ erq->length = 0;
++ erq->flags |= IW_ENCODE_DISABLED;
++ return 0;
++ }
++
++ memcpy(key, sdata->keys[idx]->conf.key,
++ min_t(int, erq->length, sdata->keys[idx]->conf.keylen));
++ erq->length = sdata->keys[idx]->conf.keylen;
++ erq->flags |= IW_ENCODE_ENABLED;
++
++ return 0;
++}
++
++static int ieee80211_ioctl_siwauth(struct net_device *dev,
++ struct iw_request_info *info,
++ struct iw_param *data, char *extra)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ int ret = 0;
++
++ switch (data->flags & IW_AUTH_INDEX) {
++ case IW_AUTH_WPA_VERSION:
++ case IW_AUTH_CIPHER_PAIRWISE:
++ case IW_AUTH_CIPHER_GROUP:
++ case IW_AUTH_WPA_ENABLED:
++ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
++ case IW_AUTH_KEY_MGMT:
++ break;
++ case IW_AUTH_DROP_UNENCRYPTED:
++ sdata->drop_unencrypted = !!data->value;
++ break;
++ case IW_AUTH_PRIVACY_INVOKED:
++ if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
++ ret = -EINVAL;
++ else {
++ sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
++ /*
++ * Privacy invoked by wpa_supplicant, store the
++ * value and allow associating to a protected
++ * network without having a key up front.
++ */
++ if (data->value)
++ sdata->u.sta.flags |=
++ IEEE80211_STA_PRIVACY_INVOKED;
++ }
++ break;
++ case IW_AUTH_80211_AUTH_ALG:
++ if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
++ sdata->vif.type == IEEE80211_IF_TYPE_IBSS)
++ sdata->u.sta.auth_algs = data->value;
++ else
++ ret = -EOPNOTSUPP;
++ break;
++ default:
++ ret = -EOPNOTSUPP;
++ break;
++ }
++ return ret;
++}
++
++/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
++static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev)
++{
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ struct iw_statistics *wstats = &local->wstats;
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct sta_info *sta = NULL;
++
++ rcu_read_lock();
++
++ if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
++ sdata->vif.type == IEEE80211_IF_TYPE_IBSS)
++ sta = sta_info_get(local, sdata->u.sta.bssid);
++ if (!sta) {
++ wstats->discard.fragment = 0;
++ wstats->discard.misc = 0;
++ wstats->qual.qual = 0;
++ wstats->qual.level = 0;
++ wstats->qual.noise = 0;
++ wstats->qual.updated = IW_QUAL_ALL_INVALID;
++ } else {
++ wstats->qual.level = sta->last_rssi;
++ wstats->qual.qual = sta->last_signal;
++ wstats->qual.noise = sta->last_noise;
++ wstats->qual.updated = local->wstats_flags;
++ }
++
++ rcu_read_unlock();
++
++ return wstats;
++}
++
++static int ieee80211_ioctl_giwauth(struct net_device *dev,
++ struct iw_request_info *info,
++ struct iw_param *data, char *extra)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ int ret = 0;
++
++ switch (data->flags & IW_AUTH_INDEX) {
++ case IW_AUTH_80211_AUTH_ALG:
++ if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
++ sdata->vif.type == IEEE80211_IF_TYPE_IBSS)
++ data->value = sdata->u.sta.auth_algs;
++ else
++ ret = -EOPNOTSUPP;
++ break;
++ default:
++ ret = -EOPNOTSUPP;
++ break;
++ }
++ return ret;
++}
++
++
++static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
++ struct iw_request_info *info,
++ struct iw_point *erq, char *extra)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
++ int uninitialized_var(alg), idx, i, remove = 0;
++
++ switch (ext->alg) {
++ case IW_ENCODE_ALG_NONE:
++ remove = 1;
++ break;
++ case IW_ENCODE_ALG_WEP:
++ alg = ALG_WEP;
++ break;
++ case IW_ENCODE_ALG_TKIP:
++ alg = ALG_TKIP;
++ break;
++ case IW_ENCODE_ALG_CCMP:
++ alg = ALG_CCMP;
++ break;
++ default:
++ return -EOPNOTSUPP;
++ }
++
++ if (erq->flags & IW_ENCODE_DISABLED)
++ remove = 1;
++
++ idx = erq->flags & IW_ENCODE_INDEX;
++ if (idx < 1 || idx > 4) {
++ idx = -1;
++ if (!sdata->default_key)
++ idx = 0;
++ else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
++ if (sdata->default_key == sdata->keys[i]) {
++ idx = i;
++ break;
++ }
++ }
++ if (idx < 0)
++ return -EINVAL;
++ } else
++ idx--;
++
++ return ieee80211_set_encryption(dev, ext->addr.sa_data, idx, alg,
++ remove,
++ ext->ext_flags &
++ IW_ENCODE_EXT_SET_TX_KEY,
++ ext->key, ext->key_len);
++}
++
++
++/* Structures to export the Wireless Handlers */
++
++static const iw_handler ieee80211_handler[] =
++{
++ (iw_handler) NULL, /* SIOCSIWCOMMIT */
++ (iw_handler) ieee80211_ioctl_giwname, /* SIOCGIWNAME */
++ (iw_handler) NULL, /* SIOCSIWNWID */
++ (iw_handler) NULL, /* SIOCGIWNWID */
++ (iw_handler) ieee80211_ioctl_siwfreq, /* SIOCSIWFREQ */
++ (iw_handler) ieee80211_ioctl_giwfreq, /* SIOCGIWFREQ */
++ (iw_handler) ieee80211_ioctl_siwmode, /* SIOCSIWMODE */
++ (iw_handler) ieee80211_ioctl_giwmode, /* SIOCGIWMODE */
++ (iw_handler) NULL, /* SIOCSIWSENS */
++ (iw_handler) NULL, /* SIOCGIWSENS */
++ (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */
++ (iw_handler) ieee80211_ioctl_giwrange, /* SIOCGIWRANGE */
++ (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */
++ (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */
++ (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */
++ (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */
++ (iw_handler) NULL, /* SIOCSIWSPY */
++ (iw_handler) NULL, /* SIOCGIWSPY */
++ (iw_handler) NULL, /* SIOCSIWTHRSPY */
++ (iw_handler) NULL, /* SIOCGIWTHRSPY */
++ (iw_handler) ieee80211_ioctl_siwap, /* SIOCSIWAP */
++ (iw_handler) ieee80211_ioctl_giwap, /* SIOCGIWAP */
++ (iw_handler) ieee80211_ioctl_siwmlme, /* SIOCSIWMLME */
++ (iw_handler) NULL, /* SIOCGIWAPLIST */
++ (iw_handler) ieee80211_ioctl_siwscan, /* SIOCSIWSCAN */
++ (iw_handler) ieee80211_ioctl_giwscan, /* SIOCGIWSCAN */
++ (iw_handler) ieee80211_ioctl_siwessid, /* SIOCSIWESSID */
++ (iw_handler) ieee80211_ioctl_giwessid, /* SIOCGIWESSID */
++ (iw_handler) NULL, /* SIOCSIWNICKN */
++ (iw_handler) NULL, /* SIOCGIWNICKN */
++ (iw_handler) NULL, /* -- hole -- */
++ (iw_handler) NULL, /* -- hole -- */
++ (iw_handler) ieee80211_ioctl_siwrate, /* SIOCSIWRATE */
++ (iw_handler) ieee80211_ioctl_giwrate, /* SIOCGIWRATE */
++ (iw_handler) ieee80211_ioctl_siwrts, /* SIOCSIWRTS */
++ (iw_handler) ieee80211_ioctl_giwrts, /* SIOCGIWRTS */
++ (iw_handler) ieee80211_ioctl_siwfrag, /* SIOCSIWFRAG */
++ (iw_handler) ieee80211_ioctl_giwfrag, /* SIOCGIWFRAG */
++ (iw_handler) ieee80211_ioctl_siwtxpower, /* SIOCSIWTXPOW */
++ (iw_handler) ieee80211_ioctl_giwtxpower, /* SIOCGIWTXPOW */
++ (iw_handler) ieee80211_ioctl_siwretry, /* SIOCSIWRETRY */
++ (iw_handler) ieee80211_ioctl_giwretry, /* SIOCGIWRETRY */
++ (iw_handler) ieee80211_ioctl_siwencode, /* SIOCSIWENCODE */
++ (iw_handler) ieee80211_ioctl_giwencode, /* SIOCGIWENCODE */
++ (iw_handler) NULL, /* SIOCSIWPOWER */
++ (iw_handler) NULL, /* SIOCGIWPOWER */
++ (iw_handler) NULL, /* -- hole -- */
++ (iw_handler) NULL, /* -- hole -- */
++ (iw_handler) ieee80211_ioctl_siwgenie, /* SIOCSIWGENIE */
++ (iw_handler) NULL, /* SIOCGIWGENIE */
++ (iw_handler) ieee80211_ioctl_siwauth, /* SIOCSIWAUTH */
++ (iw_handler) ieee80211_ioctl_giwauth, /* SIOCGIWAUTH */
++ (iw_handler) ieee80211_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */
++ (iw_handler) NULL, /* SIOCGIWENCODEEXT */
++ (iw_handler) NULL, /* SIOCSIWPMKSA */
++ (iw_handler) NULL, /* -- hole -- */
++};
++
++const struct iw_handler_def ieee80211_iw_handler_def =
++{
++ .num_standard = ARRAY_SIZE(ieee80211_handler),
++ .standard = (iw_handler *) ieee80211_handler,
++ .get_wireless_stats = ieee80211_get_wireless_stats,
++};
+diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
+index 4e23659..64faa3d 100644
+--- a/net/mac80211/wme.c
++++ b/net/mac80211/wme.c
+@@ -19,10 +19,13 @@
+ #include "wme.h"
+
+ /* maximum number of hardware queues we support. */
+-#define TC_80211_MAX_QUEUES 8
++#define TC_80211_MAX_QUEUES 16
++
++const int ieee802_1d_to_ac[8] = { 2, 3, 3, 2, 1, 1, 0, 0 };
+
+ struct ieee80211_sched_data
+ {
++ unsigned long qdisc_pool[BITS_TO_LONGS(TC_80211_MAX_QUEUES)];
+ struct tcf_proto *filter_list;
+ struct Qdisc *queues[TC_80211_MAX_QUEUES];
+ struct sk_buff_head requeued[TC_80211_MAX_QUEUES];
+@@ -98,7 +101,6 @@ static inline int classify80211(struct sk_buff *skb, struct Qdisc *qd)
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ unsigned short fc = le16_to_cpu(hdr->frame_control);
+ int qos;
+- const int ieee802_1d_to_ac[8] = { 2, 3, 3, 2, 1, 1, 0, 0 };
+
+ /* see if frame is data or non data frame */
+ if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)) {
+@@ -146,9 +148,26 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
+ unsigned short fc = le16_to_cpu(hdr->frame_control);
+ struct Qdisc *qdisc;
+ int err, queue;
++ struct sta_info *sta;
++ u8 tid;
+
+ if (pkt_data->flags & IEEE80211_TXPD_REQUEUE) {
+- skb_queue_tail(&q->requeued[pkt_data->queue], skb);
++ queue = pkt_data->queue;
++ rcu_read_lock();
++ sta = sta_info_get(local, hdr->addr1);
++ tid = skb->priority & QOS_CONTROL_TAG1D_MASK;
++ if (sta) {
++ int ampdu_queue = sta->tid_to_tx_q[tid];
++ if ((ampdu_queue < local->hw.queues) &&
++ test_bit(ampdu_queue, q->qdisc_pool)) {
++ queue = ampdu_queue;
++ pkt_data->flags |= IEEE80211_TXPD_AMPDU;
++ } else {
++ pkt_data->flags &= ~IEEE80211_TXPD_AMPDU;
++ }
++ }
++ rcu_read_unlock();
++ skb_queue_tail(&q->requeued[queue], skb);
+ qd->q.qlen++;
+ return 0;
+ }
+@@ -159,14 +178,31 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
+ */
+ if (WLAN_FC_IS_QOS_DATA(fc)) {
+ u8 *p = skb->data + ieee80211_get_hdrlen(fc) - 2;
+- u8 qos_hdr = skb->priority & QOS_CONTROL_TAG1D_MASK;
++ u8 ack_policy = 0;
++ tid = skb->priority & QOS_CONTROL_TAG1D_MASK;
+ if (local->wifi_wme_noack_test)
+- qos_hdr |= QOS_CONTROL_ACK_POLICY_NOACK <<
++ ack_policy |= QOS_CONTROL_ACK_POLICY_NOACK <<
+ QOS_CONTROL_ACK_POLICY_SHIFT;
+ /* qos header is 2 bytes, second reserved */
+- *p = qos_hdr;
++ *p = ack_policy | tid;
+ p++;
+ *p = 0;
++
++ rcu_read_lock();
++
++ sta = sta_info_get(local, hdr->addr1);
++ if (sta) {
++ int ampdu_queue = sta->tid_to_tx_q[tid];
++ if ((ampdu_queue < local->hw.queues) &&
++ test_bit(ampdu_queue, q->qdisc_pool)) {
++ queue = ampdu_queue;
++ pkt_data->flags |= IEEE80211_TXPD_AMPDU;
++ } else {
++ pkt_data->flags &= ~IEEE80211_TXPD_AMPDU;
++ }
++ }
++
++ rcu_read_unlock();
+ }
+
+ if (unlikely(queue >= local->hw.queues)) {
+@@ -184,6 +220,7 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
+ kfree_skb(skb);
+ err = NET_XMIT_DROP;
+ } else {
++ tid = skb->priority & QOS_CONTROL_TAG1D_MASK;
+ pkt_data->queue = (unsigned int) queue;
+ qdisc = q->queues[queue];
+ err = qdisc->enqueue(skb, qdisc);
+@@ -235,10 +272,11 @@ static struct sk_buff *wme_qdiscop_dequeue(struct Qdisc* qd)
+ /* check all the h/w queues in numeric/priority order */
+ for (queue = 0; queue < hw->queues; queue++) {
+ /* see if there is room in this hardware queue */
+- if (test_bit(IEEE80211_LINK_STATE_XOFF,
+- &local->state[queue]) ||
+- test_bit(IEEE80211_LINK_STATE_PENDING,
+- &local->state[queue]))
++ if ((test_bit(IEEE80211_LINK_STATE_XOFF,
++ &local->state[queue])) ||
++ (test_bit(IEEE80211_LINK_STATE_PENDING,
++ &local->state[queue])) ||
++ (!test_bit(queue, q->qdisc_pool)))
+ continue;
+
+ /* there is space - try and get a frame */
+@@ -360,6 +398,10 @@ static int wme_qdiscop_init(struct Qdisc *qd, struct nlattr *opt)
+ }
+ }
+
++ /* reserve all legacy QoS queues */
++ for (i = 0; i < min(IEEE80211_TX_QUEUE_DATA4, queues); i++)
++ set_bit(i, q->qdisc_pool);
++
+ return err;
+ }
+
+@@ -605,3 +647,80 @@ void ieee80211_wme_unregister(void)
+ {
+ unregister_qdisc(&wme_qdisc_ops);
+ }
++
++int ieee80211_ht_agg_queue_add(struct ieee80211_local *local,
++ struct sta_info *sta, u16 tid)
++{
++ int i;
++ struct ieee80211_sched_data *q =
++ qdisc_priv(local->mdev->qdisc_sleeping);
++ DECLARE_MAC_BUF(mac);
++
++ /* prepare the filter and save it for the SW queue
++ * matching the recieved HW queue */
++
++ /* try to get a Qdisc from the pool */
++ for (i = IEEE80211_TX_QUEUE_BEACON; i < local->hw.queues; i++)
++ if (!test_and_set_bit(i, q->qdisc_pool)) {
++ ieee80211_stop_queue(local_to_hw(local), i);
++ sta->tid_to_tx_q[tid] = i;
++
++ /* IF there are already pending packets
++ * on this tid first we need to drain them
++ * on the previous queue
++ * since HT is strict in order */
++#ifdef CONFIG_MAC80211_HT_DEBUG
++ if (net_ratelimit())
++ printk(KERN_DEBUG "allocated aggregation queue"
++ " %d tid %d addr %s pool=0x%lX",
++ i, tid, print_mac(mac, sta->addr),
++ q->qdisc_pool[0]);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++ return 0;
++ }
++
++ return -EAGAIN;
++}
++
++/**
++ * the caller needs to hold local->mdev->queue_lock
++ */
++void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local,
++ struct sta_info *sta, u16 tid,
++ u8 requeue)
++{
++ struct ieee80211_sched_data *q =
++ qdisc_priv(local->mdev->qdisc_sleeping);
++ int agg_queue = sta->tid_to_tx_q[tid];
++
++ /* return the qdisc to the pool */
++ clear_bit(agg_queue, q->qdisc_pool);
++ sta->tid_to_tx_q[tid] = local->hw.queues;
++
++ if (requeue)
++ ieee80211_requeue(local, agg_queue);
++ else
++ q->queues[agg_queue]->ops->reset(q->queues[agg_queue]);
++}
++
++void ieee80211_requeue(struct ieee80211_local *local, int queue)
++{
++ struct Qdisc *root_qd = local->mdev->qdisc_sleeping;
++ struct ieee80211_sched_data *q = qdisc_priv(root_qd);
++ struct Qdisc *qdisc = q->queues[queue];
++ struct sk_buff *skb = NULL;
++ u32 len;
++
++ if (!qdisc || !qdisc->dequeue)
++ return;
++
++ printk(KERN_DEBUG "requeue: qlen = %d\n", qdisc->q.qlen);
++ for (len = qdisc->q.qlen; len > 0; len--) {
++ skb = qdisc->dequeue(qdisc);
++ root_qd->q.qlen--;
++ /* packet will be classified again and */
++ /* skb->packet_data->queue will be overridden if needed */
++ if (skb)
++ wme_qdiscop_enqueue(skb, root_qd);
++ }
++}
+diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h
+index 76c713a..fcc6b05 100644
+--- a/net/mac80211/wme.h
++++ b/net/mac80211/wme.h
+@@ -24,6 +24,8 @@
+
+ #define QOS_CONTROL_TAG1D_MASK 0x07
+
++extern const int ieee802_1d_to_ac[8];
++
+ static inline int WLAN_FC_IS_QOS_DATA(u16 fc)
+ {
+ return (fc & 0x8C) == 0x88;
+@@ -32,7 +34,12 @@ static inline int WLAN_FC_IS_QOS_DATA(u16 fc)
+ #ifdef CONFIG_NET_SCHED
+ void ieee80211_install_qdisc(struct net_device *dev);
+ int ieee80211_qdisc_installed(struct net_device *dev);
+-
++int ieee80211_ht_agg_queue_add(struct ieee80211_local *local,
++ struct sta_info *sta, u16 tid);
++void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local,
++ struct sta_info *sta, u16 tid,
++ u8 requeue);
++void ieee80211_requeue(struct ieee80211_local *local, int queue);
+ int ieee80211_wme_register(void);
+ void ieee80211_wme_unregister(void);
+ #else
+@@ -43,7 +50,19 @@ static inline int ieee80211_qdisc_installed(struct net_device *dev)
+ {
+ return 0;
+ }
+-
++static inline int ieee80211_ht_agg_queue_add(struct ieee80211_local *local,
++ struct sta_info *sta, u16 tid)
++{
++ return -EAGAIN;
++}
++static inline void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local,
++ struct sta_info *sta, u16 tid,
++ u8 requeue)
++{
++}
++static inline void ieee80211_requeue(struct ieee80211_local *local, int queue)
++{
++}
+ static inline int ieee80211_wme_register(void)
+ {
+ return 0;
+diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
+index 6f04311..45709ad 100644
+--- a/net/mac80211/wpa.c
++++ b/net/mac80211/wpa.c
+@@ -70,8 +70,8 @@ static int ieee80211_get_hdr_info(const struct sk_buff *skb, u8 **sa, u8 **da,
+ }
+
+
+-ieee80211_txrx_result
+-ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx)
++ieee80211_tx_result
++ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
+ {
+ u8 *data, *sa, *da, *key, *mic, qos_tid;
+ size_t data_len;
+@@ -84,18 +84,18 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx)
+
+ if (!tx->key || tx->key->conf.alg != ALG_TKIP || skb->len < 24 ||
+ !WLAN_FC_DATA_PRESENT(fc))
+- return TXRX_CONTINUE;
++ return TX_CONTINUE;
+
+ if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len))
+- return TXRX_DROP;
++ return TX_DROP;
+
+ if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
+- !(tx->flags & IEEE80211_TXRXD_FRAGMENTED) &&
++ !(tx->flags & IEEE80211_TX_FRAGMENTED) &&
+ !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) &&
+ !wpa_test) {
+ /* hwaccel - with no need for preallocated room for Michael MIC
+ */
+- return TXRX_CONTINUE;
++ return TX_CONTINUE;
+ }
+
+ if (skb_tailroom(skb) < MICHAEL_MIC_LEN) {
+@@ -105,7 +105,7 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx)
+ GFP_ATOMIC))) {
+ printk(KERN_DEBUG "%s: failed to allocate more memory "
+ "for Michael MIC\n", tx->dev->name);
+- return TXRX_DROP;
++ return TX_DROP;
+ }
+ }
+
+@@ -119,12 +119,12 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx)
+ mic = skb_put(skb, MICHAEL_MIC_LEN);
+ michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic);
+
+- return TXRX_CONTINUE;
++ return TX_CONTINUE;
+ }
+
+
+-ieee80211_txrx_result
+-ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx)
++ieee80211_rx_result
++ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
+ {
+ u8 *data, *sa, *da, *key = NULL, qos_tid;
+ size_t data_len;
+@@ -139,16 +139,16 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx)
+ /*
+ * No way to verify the MIC if the hardware stripped it
+ */
+- if (rx->u.rx.status->flag & RX_FLAG_MMIC_STRIPPED)
+- return TXRX_CONTINUE;
++ if (rx->status->flag & RX_FLAG_MMIC_STRIPPED)
++ return RX_CONTINUE;
+
+ if (!rx->key || rx->key->conf.alg != ALG_TKIP ||
+ !(rx->fc & IEEE80211_FCTL_PROTECTED) || !WLAN_FC_DATA_PRESENT(fc))
+- return TXRX_CONTINUE;
++ return RX_CONTINUE;
+
+ if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len)
+ || data_len < MICHAEL_MIC_LEN)
+- return TXRX_DROP;
++ return RX_DROP_UNUSABLE;
+
+ data_len -= MICHAEL_MIC_LEN;
+
+@@ -161,29 +161,29 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx)
+ ALG_TKIP_TEMP_AUTH_TX_MIC_KEY];
+ michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic);
+ if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) {
+- if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
+- return TXRX_DROP;
++ if (!(rx->flags & IEEE80211_RX_RA_MATCH))
++ return RX_DROP_UNUSABLE;
+
+ printk(KERN_DEBUG "%s: invalid Michael MIC in data frame from "
+ "%s\n", rx->dev->name, print_mac(mac, sa));
+
+ mac80211_ev_michael_mic_failure(rx->dev, rx->key->conf.keyidx,
+ (void *) skb->data);
+- return TXRX_DROP;
++ return RX_DROP_UNUSABLE;
+ }
+
+ /* remove Michael MIC from payload */
+ skb_trim(skb, skb->len - MICHAEL_MIC_LEN);
+
+ /* update IV in key information to be able to detect replays */
+- rx->key->u.tkip.iv32_rx[rx->u.rx.queue] = rx->u.rx.tkip_iv32;
+- rx->key->u.tkip.iv16_rx[rx->u.rx.queue] = rx->u.rx.tkip_iv16;
++ rx->key->u.tkip.iv32_rx[rx->queue] = rx->tkip_iv32;
++ rx->key->u.tkip.iv16_rx[rx->queue] = rx->tkip_iv16;
+
+- return TXRX_CONTINUE;
++ return RX_CONTINUE;
+ }
+
+
+-static int tkip_encrypt_skb(struct ieee80211_txrx_data *tx,
++static int tkip_encrypt_skb(struct ieee80211_tx_data *tx,
+ struct sk_buff *skb, int test)
+ {
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+@@ -228,7 +228,7 @@ static int tkip_encrypt_skb(struct ieee80211_txrx_data *tx,
+ 0x7f),
+ (u8) key->u.tkip.iv16);
+
+- tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx;
++ tx->control->key_idx = tx->key->conf.hw_key_idx;
+ return 0;
+ }
+
+@@ -242,42 +242,42 @@ static int tkip_encrypt_skb(struct ieee80211_txrx_data *tx,
+ }
+
+
+-ieee80211_txrx_result
+-ieee80211_crypto_tkip_encrypt(struct ieee80211_txrx_data *tx)
++ieee80211_tx_result
++ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx)
+ {
+ struct sk_buff *skb = tx->skb;
+ int wpa_test = 0, test = 0;
+
+- tx->u.tx.control->icv_len = TKIP_ICV_LEN;
+- tx->u.tx.control->iv_len = TKIP_IV_LEN;
+- ieee80211_tx_set_iswep(tx);
++ tx->control->icv_len = TKIP_ICV_LEN;
++ tx->control->iv_len = TKIP_IV_LEN;
++ ieee80211_tx_set_protected(tx);
+
+ if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
+ !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
+ !wpa_test) {
+ /* hwaccel - with no need for preallocated room for IV/ICV */
+- tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx;
+- return TXRX_CONTINUE;
++ tx->control->key_idx = tx->key->conf.hw_key_idx;
++ return TX_CONTINUE;
+ }
+
+ if (tkip_encrypt_skb(tx, skb, test) < 0)
+- return TXRX_DROP;
++ return TX_DROP;
+
+- if (tx->u.tx.extra_frag) {
++ if (tx->extra_frag) {
+ int i;
+- for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+- if (tkip_encrypt_skb(tx, tx->u.tx.extra_frag[i], test)
++ for (i = 0; i < tx->num_extra_frag; i++) {
++ if (tkip_encrypt_skb(tx, tx->extra_frag[i], test)
+ < 0)
+- return TXRX_DROP;
++ return TX_DROP;
+ }
+ }
+
+- return TXRX_CONTINUE;
++ return TX_CONTINUE;
+ }
+
+
+-ieee80211_txrx_result
+-ieee80211_crypto_tkip_decrypt(struct ieee80211_txrx_data *rx)
++ieee80211_rx_result
++ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
+ {
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
+ u16 fc;
+@@ -290,19 +290,19 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_txrx_data *rx)
+ hdrlen = ieee80211_get_hdrlen(fc);
+
+ if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)
+- return TXRX_CONTINUE;
++ return RX_CONTINUE;
+
+ if (!rx->sta || skb->len - hdrlen < 12)
+- return TXRX_DROP;
++ return RX_DROP_UNUSABLE;
+
+- if (rx->u.rx.status->flag & RX_FLAG_DECRYPTED) {
+- if (rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED) {
++ if (rx->status->flag & RX_FLAG_DECRYPTED) {
++ if (rx->status->flag & RX_FLAG_IV_STRIPPED) {
+ /*
+ * Hardware took care of all processing, including
+ * replay protection, and stripped the ICV/IV so
+ * we cannot do any checks here.
+ */
+- return TXRX_CONTINUE;
++ return RX_CONTINUE;
+ }
+
+ /* let TKIP code verify IV, but skip decryption */
+@@ -312,9 +312,9 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_txrx_data *rx)
+ res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm,
+ key, skb->data + hdrlen,
+ skb->len - hdrlen, rx->sta->addr,
+- hwaccel, rx->u.rx.queue,
+- &rx->u.rx.tkip_iv32,
+- &rx->u.rx.tkip_iv16);
++ hdr->addr1, hwaccel, rx->queue,
++ &rx->tkip_iv32,
++ &rx->tkip_iv16);
+ if (res != TKIP_DECRYPT_OK || wpa_test) {
+ #ifdef CONFIG_MAC80211_DEBUG
+ if (net_ratelimit())
+@@ -322,7 +322,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_txrx_data *rx)
+ "frame from %s (res=%d)\n", rx->dev->name,
+ print_mac(mac, rx->sta->addr), res);
+ #endif /* CONFIG_MAC80211_DEBUG */
+- return TXRX_DROP;
++ return RX_DROP_UNUSABLE;
+ }
+
+ /* Trim ICV */
+@@ -332,7 +332,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_txrx_data *rx)
+ memmove(skb->data + TKIP_IV_LEN, skb->data, hdrlen);
+ skb_pull(skb, TKIP_IV_LEN);
+
+- return TXRX_CONTINUE;
++ return RX_CONTINUE;
+ }
+
+
+@@ -429,7 +429,7 @@ static inline int ccmp_hdr2pn(u8 *pn, u8 *hdr)
+ }
+
+
+-static int ccmp_encrypt_skb(struct ieee80211_txrx_data *tx,
++static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx,
+ struct sk_buff *skb, int test)
+ {
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+@@ -478,7 +478,7 @@ static int ccmp_encrypt_skb(struct ieee80211_txrx_data *tx,
+
+ if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
+ /* hwaccel - with preallocated room for CCMP header */
+- tx->u.tx.control->key_idx = key->conf.hw_key_idx;
++ tx->control->key_idx = key->conf.hw_key_idx;
+ return 0;
+ }
+
+@@ -491,42 +491,42 @@ static int ccmp_encrypt_skb(struct ieee80211_txrx_data *tx,
+ }
+
+
+-ieee80211_txrx_result
+-ieee80211_crypto_ccmp_encrypt(struct ieee80211_txrx_data *tx)
++ieee80211_tx_result
++ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx)
+ {
+ struct sk_buff *skb = tx->skb;
+ int test = 0;
+
+- tx->u.tx.control->icv_len = CCMP_MIC_LEN;
+- tx->u.tx.control->iv_len = CCMP_HDR_LEN;
+- ieee80211_tx_set_iswep(tx);
++ tx->control->icv_len = CCMP_MIC_LEN;
++ tx->control->iv_len = CCMP_HDR_LEN;
++ ieee80211_tx_set_protected(tx);
+
+ if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
+ !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
+ /* hwaccel - with no need for preallocated room for CCMP "
+ * header or MIC fields */
+- tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx;
+- return TXRX_CONTINUE;
++ tx->control->key_idx = tx->key->conf.hw_key_idx;
++ return TX_CONTINUE;
+ }
+
+ if (ccmp_encrypt_skb(tx, skb, test) < 0)
+- return TXRX_DROP;
++ return TX_DROP;
+
+- if (tx->u.tx.extra_frag) {
++ if (tx->extra_frag) {
+ int i;
+- for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+- if (ccmp_encrypt_skb(tx, tx->u.tx.extra_frag[i], test)
++ for (i = 0; i < tx->num_extra_frag; i++) {
++ if (ccmp_encrypt_skb(tx, tx->extra_frag[i], test)
+ < 0)
+- return TXRX_DROP;
++ return TX_DROP;
+ }
+ }
+
+- return TXRX_CONTINUE;
++ return TX_CONTINUE;
+ }
+
+
+-ieee80211_txrx_result
+-ieee80211_crypto_ccmp_decrypt(struct ieee80211_txrx_data *rx)
++ieee80211_rx_result
++ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
+ {
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
+ u16 fc;
+@@ -541,21 +541,21 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_txrx_data *rx)
+ hdrlen = ieee80211_get_hdrlen(fc);
+
+ if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)
+- return TXRX_CONTINUE;
++ return RX_CONTINUE;
+
+ data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN;
+ if (!rx->sta || data_len < 0)
+- return TXRX_DROP;
++ return RX_DROP_UNUSABLE;
+
+- if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
+- (rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED))
+- return TXRX_CONTINUE;
++ if ((rx->status->flag & RX_FLAG_DECRYPTED) &&
++ (rx->status->flag & RX_FLAG_IV_STRIPPED))
++ return RX_CONTINUE;
+
+ (void) ccmp_hdr2pn(pn, skb->data + hdrlen);
+
+- if (memcmp(pn, key->u.ccmp.rx_pn[rx->u.rx.queue], CCMP_PN_LEN) <= 0) {
++ if (memcmp(pn, key->u.ccmp.rx_pn[rx->queue], CCMP_PN_LEN) <= 0) {
+ #ifdef CONFIG_MAC80211_DEBUG
+- u8 *ppn = key->u.ccmp.rx_pn[rx->u.rx.queue];
++ u8 *ppn = key->u.ccmp.rx_pn[rx->queue];
+
+ printk(KERN_DEBUG "%s: CCMP replay detected for RX frame from "
+ "%s (RX PN %02x%02x%02x%02x%02x%02x <= prev. PN "
+@@ -565,10 +565,10 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_txrx_data *rx)
+ ppn[0], ppn[1], ppn[2], ppn[3], ppn[4], ppn[5]);
+ #endif /* CONFIG_MAC80211_DEBUG */
+ key->u.ccmp.replays++;
+- return TXRX_DROP;
++ return RX_DROP_UNUSABLE;
+ }
+
+- if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED)) {
++ if (!(rx->status->flag & RX_FLAG_DECRYPTED)) {
+ /* hardware didn't decrypt/verify MIC */
+ u8 *scratch, *b_0, *aad;
+
+@@ -589,16 +589,16 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_txrx_data *rx)
+ "for RX frame from %s\n", rx->dev->name,
+ print_mac(mac, rx->sta->addr));
+ #endif /* CONFIG_MAC80211_DEBUG */
+- return TXRX_DROP;
++ return RX_DROP_UNUSABLE;
+ }
+ }
+
+- memcpy(key->u.ccmp.rx_pn[rx->u.rx.queue], pn, CCMP_PN_LEN);
++ memcpy(key->u.ccmp.rx_pn[rx->queue], pn, CCMP_PN_LEN);
+
+ /* Remove CCMP header and MIC */
+ skb_trim(skb, skb->len - CCMP_MIC_LEN);
+ memmove(skb->data + CCMP_HDR_LEN, skb->data, hdrlen);
+ skb_pull(skb, CCMP_HDR_LEN);
+
+- return TXRX_CONTINUE;
++ return RX_CONTINUE;
+ }
+diff --git a/net/mac80211/wpa.h b/net/mac80211/wpa.h
+index 49d80cf..d42d221 100644
+--- a/net/mac80211/wpa.h
++++ b/net/mac80211/wpa.h
+@@ -13,19 +13,19 @@
+ #include <linux/types.h>
+ #include "ieee80211_i.h"
+
+-ieee80211_txrx_result
+-ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx);
+-ieee80211_txrx_result
+-ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx);
++ieee80211_tx_result
++ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx);
++ieee80211_rx_result
++ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx);
+
+-ieee80211_txrx_result
+-ieee80211_crypto_tkip_encrypt(struct ieee80211_txrx_data *tx);
+-ieee80211_txrx_result
+-ieee80211_crypto_tkip_decrypt(struct ieee80211_txrx_data *rx);
++ieee80211_tx_result
++ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx);
++ieee80211_rx_result
++ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx);
+
+-ieee80211_txrx_result
+-ieee80211_crypto_ccmp_encrypt(struct ieee80211_txrx_data *tx);
+-ieee80211_txrx_result
+-ieee80211_crypto_ccmp_decrypt(struct ieee80211_txrx_data *rx);
++ieee80211_tx_result
++ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx);
++ieee80211_rx_result
++ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx);
+
+ #endif /* WPA_H */
+diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
+index daf5b88..c1fc0f1 100644
+--- a/net/netfilter/Kconfig
++++ b/net/netfilter/Kconfig
+@@ -86,6 +86,16 @@ config NF_CONNTRACK_EVENTS
+
+ If unsure, say `N'.
+
++config NF_CT_PROTO_DCCP
++ tristate 'DCCP protocol connection tracking support (EXPERIMENTAL)'
++ depends on EXPERIMENTAL && NF_CONNTRACK
++ depends on NETFILTER_ADVANCED
++ help
++ With this option enabled, the layer 3 independent connection
++ tracking code will be able to do state tracking on DCCP connections.
++
++ If unsure, say 'N'.
++
+ config NF_CT_PROTO_GRE
+ tristate
+ depends on NF_CONNTRACK
+diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
+index ea75083..5c4b183 100644
+--- a/net/netfilter/Makefile
++++ b/net/netfilter/Makefile
+@@ -13,6 +13,7 @@ obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o
+ obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o
+
+ # SCTP protocol connection tracking
++obj-$(CONFIG_NF_CT_PROTO_DCCP) += nf_conntrack_proto_dccp.o
+ obj-$(CONFIG_NF_CT_PROTO_GRE) += nf_conntrack_proto_gre.o
+ obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o
+ obj-$(CONFIG_NF_CT_PROTO_UDPLITE) += nf_conntrack_proto_udplite.o
+diff --git a/net/netfilter/core.c b/net/netfilter/core.c
+index c4065b8..292fa28 100644
+--- a/net/netfilter/core.c
++++ b/net/netfilter/core.c
+@@ -165,6 +165,14 @@ int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
+ unsigned int verdict;
+ int ret = 0;
+
++#ifdef CONFIG_NET_NS
++ struct net *net;
++
++ net = indev == NULL ? dev_net(outdev) : dev_net(indev);
++ if (net != &init_net)
++ return 1;
++#endif
++
+ /* We may already have this, but read-locks nest anyway */
+ rcu_read_lock();
+
+diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c
+index 7b8239c..38aedee 100644
+--- a/net/netfilter/nf_conntrack_amanda.c
++++ b/net/netfilter/nf_conntrack_amanda.c
+@@ -53,7 +53,7 @@ enum amanda_strings {
+ };
+
+ static struct {
+- char *string;
++ const char *string;
+ size_t len;
+ struct ts_config *ts;
+ } search[] __read_mostly = {
+@@ -91,7 +91,6 @@ static int amanda_help(struct sk_buff *skb,
+ char pbuf[sizeof("65535")], *tmp;
+ u_int16_t len;
+ __be16 port;
+- int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ int ret = NF_ACCEPT;
+ typeof(nf_nat_amanda_hook) nf_nat_amanda;
+
+@@ -148,7 +147,9 @@ static int amanda_help(struct sk_buff *skb,
+ goto out;
+ }
+ tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
+- nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3,
++ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,
++ nf_ct_l3num(ct),
++ &tuple->src.u3, &tuple->dst.u3,
+ IPPROTO_TCP, NULL, &port);
+
+ nf_nat_amanda = rcu_dereference(nf_nat_amanda_hook);
+@@ -164,26 +165,29 @@ out:
+ return ret;
+ }
+
++static const struct nf_conntrack_expect_policy amanda_exp_policy = {
++ .max_expected = 3,
++ .timeout = 180,
++};
++
+ static struct nf_conntrack_helper amanda_helper[2] __read_mostly = {
+ {
+ .name = "amanda",
+- .max_expected = 3,
+- .timeout = 180,
+ .me = THIS_MODULE,
+ .help = amanda_help,
+ .tuple.src.l3num = AF_INET,
+ .tuple.src.u.udp.port = __constant_htons(10080),
+ .tuple.dst.protonum = IPPROTO_UDP,
++ .expect_policy = &amanda_exp_policy,
+ },
+ {
+ .name = "amanda",
+- .max_expected = 3,
+- .timeout = 180,
+ .me = THIS_MODULE,
+ .help = amanda_help,
+ .tuple.src.l3num = AF_INET6,
+ .tuple.src.u.udp.port = __constant_htons(10080),
+ .tuple.dst.protonum = IPPROTO_UDP,
++ .expect_policy = &amanda_exp_policy,
+ },
+ };
+
+diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
+index b77eb56..4eac65c 100644
+--- a/net/netfilter/nf_conntrack_core.c
++++ b/net/netfilter/nf_conntrack_core.c
+@@ -94,7 +94,7 @@ static inline u_int32_t hash_conntrack(const struct nf_conntrack_tuple *tuple)
+ nf_conntrack_hash_rnd);
+ }
+
+-int
++bool
+ nf_ct_get_tuple(const struct sk_buff *skb,
+ unsigned int nhoff,
+ unsigned int dataoff,
+@@ -108,7 +108,7 @@ nf_ct_get_tuple(const struct sk_buff *skb,
+
+ tuple->src.l3num = l3num;
+ if (l3proto->pkt_to_tuple(skb, nhoff, tuple) == 0)
+- return 0;
++ return false;
+
+ tuple->dst.protonum = protonum;
+ tuple->dst.dir = IP_CT_DIR_ORIGINAL;
+@@ -117,10 +117,8 @@ nf_ct_get_tuple(const struct sk_buff *skb,
+ }
+ EXPORT_SYMBOL_GPL(nf_ct_get_tuple);
+
+-int nf_ct_get_tuplepr(const struct sk_buff *skb,
+- unsigned int nhoff,
+- u_int16_t l3num,
+- struct nf_conntrack_tuple *tuple)
++bool nf_ct_get_tuplepr(const struct sk_buff *skb, unsigned int nhoff,
++ u_int16_t l3num, struct nf_conntrack_tuple *tuple)
+ {
+ struct nf_conntrack_l3proto *l3proto;
+ struct nf_conntrack_l4proto *l4proto;
+@@ -134,7 +132,7 @@ int nf_ct_get_tuplepr(const struct sk_buff *skb,
+ ret = l3proto->get_l4proto(skb, nhoff, &protoff, &protonum);
+ if (ret != NF_ACCEPT) {
+ rcu_read_unlock();
+- return 0;
++ return false;
+ }
+
+ l4proto = __nf_ct_l4proto_find(l3num, protonum);
+@@ -147,7 +145,7 @@ int nf_ct_get_tuplepr(const struct sk_buff *skb,
+ }
+ EXPORT_SYMBOL_GPL(nf_ct_get_tuplepr);
+
+-int
++bool
+ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
+ const struct nf_conntrack_tuple *orig,
+ const struct nf_conntrack_l3proto *l3proto,
+@@ -157,7 +155,7 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
+
+ inverse->src.l3num = orig->src.l3num;
+ if (l3proto->invert_tuple(inverse, orig) == 0)
+- return 0;
++ return false;
+
+ inverse->dst.dir = !orig->dst.dir;
+
+@@ -194,8 +192,7 @@ destroy_conntrack(struct nf_conntrack *nfct)
+ * destroy_conntrack() MUST NOT be called with a write lock
+ * to nf_conntrack_lock!!! -HW */
+ rcu_read_lock();
+- l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num,
+- ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
++ l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
+ if (l4proto && l4proto->destroy)
+ l4proto->destroy(ct);
+
+@@ -739,10 +736,10 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff *skb)
+ }
+ EXPORT_SYMBOL_GPL(nf_conntrack_in);
+
+-int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
+- const struct nf_conntrack_tuple *orig)
++bool nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
++ const struct nf_conntrack_tuple *orig)
+ {
+- int ret;
++ bool ret;
+
+ rcu_read_lock();
+ ret = nf_ct_invert_tuple(inverse, orig,
+@@ -766,10 +763,10 @@ void nf_conntrack_alter_reply(struct nf_conn *ct,
+ NF_CT_ASSERT(!nf_ct_is_confirmed(ct));
+
+ pr_debug("Altering reply tuple of %p to ", ct);
+- NF_CT_DUMP_TUPLE(newreply);
++ nf_ct_dump_tuple(newreply);
+
+ ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
+- if (ct->master || (help && help->expecting != 0))
++ if (ct->master || (help && !hlist_empty(&help->expectations)))
+ return;
+
+ rcu_read_lock();
+diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
+index 684ec9c..e31beeb 100644
+--- a/net/netfilter/nf_conntrack_expect.c
++++ b/net/netfilter/nf_conntrack_expect.c
+@@ -54,7 +54,7 @@ void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
+ nf_ct_expect_count--;
+
+ hlist_del(&exp->lnode);
+- master_help->expecting--;
++ master_help->expecting[exp->class]--;
+ nf_ct_expect_put(exp);
+
+ NF_CT_STAT_INC(expect_delete);
+@@ -126,9 +126,21 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_find_get);
+ struct nf_conntrack_expect *
+ nf_ct_find_expectation(const struct nf_conntrack_tuple *tuple)
+ {
+- struct nf_conntrack_expect *exp;
++ struct nf_conntrack_expect *i, *exp = NULL;
++ struct hlist_node *n;
++ unsigned int h;
++
++ if (!nf_ct_expect_count)
++ return NULL;
+
+- exp = __nf_ct_expect_find(tuple);
++ h = nf_ct_expect_dst_hash(tuple);
++ hlist_for_each_entry(i, n, &nf_ct_expect_hash[h], hnode) {
++ if (!(i->flags & NF_CT_EXPECT_INACTIVE) &&
++ nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) {
++ exp = i;
++ break;
++ }
++ }
+ if (!exp)
+ return NULL;
+
+@@ -159,7 +171,7 @@ void nf_ct_remove_expectations(struct nf_conn *ct)
+ struct hlist_node *n, *next;
+
+ /* Optimization: most connection never expect any others. */
+- if (!help || help->expecting == 0)
++ if (!help)
+ return;
+
+ hlist_for_each_entry_safe(exp, n, next, &help->expectations, lnode) {
+@@ -193,7 +205,7 @@ static inline int expect_clash(const struct nf_conntrack_expect *a,
+ static inline int expect_matches(const struct nf_conntrack_expect *a,
+ const struct nf_conntrack_expect *b)
+ {
+- return a->master == b->master
++ return a->master == b->master && a->class == b->class
+ && nf_ct_tuple_equal(&a->tuple, &b->tuple)
+ && nf_ct_tuple_mask_equal(&a->mask, &b->mask);
+ }
+@@ -228,10 +240,11 @@ struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me)
+ }
+ EXPORT_SYMBOL_GPL(nf_ct_expect_alloc);
+
+-void nf_ct_expect_init(struct nf_conntrack_expect *exp, int family,
+- union nf_inet_addr *saddr,
+- union nf_inet_addr *daddr,
+- u_int8_t proto, __be16 *src, __be16 *dst)
++void nf_ct_expect_init(struct nf_conntrack_expect *exp, unsigned int class,
++ int family,
++ const union nf_inet_addr *saddr,
++ const union nf_inet_addr *daddr,
++ u_int8_t proto, const __be16 *src, const __be16 *dst)
+ {
+ int len;
+
+@@ -241,6 +254,7 @@ void nf_ct_expect_init(struct nf_conntrack_expect *exp, int family,
+ len = 16;
+
+ exp->flags = 0;
++ exp->class = class;
+ exp->expectfn = NULL;
+ exp->helper = NULL;
+ exp->tuple.src.l3num = family;
+@@ -297,19 +311,21 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_put);
+ static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
+ {
+ struct nf_conn_help *master_help = nfct_help(exp->master);
++ const struct nf_conntrack_expect_policy *p;
+ unsigned int h = nf_ct_expect_dst_hash(&exp->tuple);
+
+ atomic_inc(&exp->use);
+
+ hlist_add_head(&exp->lnode, &master_help->expectations);
+- master_help->expecting++;
++ master_help->expecting[exp->class]++;
+
+ hlist_add_head_rcu(&exp->hnode, &nf_ct_expect_hash[h]);
+ nf_ct_expect_count++;
+
+ setup_timer(&exp->timeout, nf_ct_expectation_timed_out,
+ (unsigned long)exp);
+- exp->timeout.expires = jiffies + master_help->helper->timeout * HZ;
++ p = &master_help->helper->expect_policy[exp->class];
++ exp->timeout.expires = jiffies + p->timeout * HZ;
+ add_timer(&exp->timeout);
+
+ atomic_inc(&exp->use);
+@@ -317,35 +333,41 @@ static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
+ }
+
+ /* Race with expectations being used means we could have none to find; OK. */
+-static void evict_oldest_expect(struct nf_conn *master)
++static void evict_oldest_expect(struct nf_conn *master,
++ struct nf_conntrack_expect *new)
+ {
+ struct nf_conn_help *master_help = nfct_help(master);
+- struct nf_conntrack_expect *exp = NULL;
++ struct nf_conntrack_expect *exp, *last = NULL;
+ struct hlist_node *n;
+
+- hlist_for_each_entry(exp, n, &master_help->expectations, lnode)
+- ; /* nothing */
++ hlist_for_each_entry(exp, n, &master_help->expectations, lnode) {
++ if (exp->class == new->class)
++ last = exp;
++ }
+
+- if (exp && del_timer(&exp->timeout)) {
+- nf_ct_unlink_expect(exp);
+- nf_ct_expect_put(exp);
++ if (last && del_timer(&last->timeout)) {
++ nf_ct_unlink_expect(last);
++ nf_ct_expect_put(last);
+ }
+ }
+
+ static inline int refresh_timer(struct nf_conntrack_expect *i)
+ {
+ struct nf_conn_help *master_help = nfct_help(i->master);
++ const struct nf_conntrack_expect_policy *p;
+
+ if (!del_timer(&i->timeout))
+ return 0;
+
+- i->timeout.expires = jiffies + master_help->helper->timeout*HZ;
++ p = &master_help->helper->expect_policy[i->class];
++ i->timeout.expires = jiffies + p->timeout * HZ;
+ add_timer(&i->timeout);
+ return 1;
+ }
+
+ int nf_ct_expect_related(struct nf_conntrack_expect *expect)
+ {
++ const struct nf_conntrack_expect_policy *p;
+ struct nf_conntrack_expect *i;
+ struct nf_conn *master = expect->master;
+ struct nf_conn_help *master_help = nfct_help(master);
+@@ -374,9 +396,15 @@ int nf_ct_expect_related(struct nf_conntrack_expect *expect)
+ }
+ }
+ /* Will be over limit? */
+- if (master_help->helper->max_expected &&
+- master_help->expecting >= master_help->helper->max_expected)
+- evict_oldest_expect(master);
++ p = &master_help->helper->expect_policy[expect->class];
++ if (p->max_expected &&
++ master_help->expecting[expect->class] >= p->max_expected) {
++ evict_oldest_expect(master, expect);
++ if (master_help->expecting[expect->class] >= p->max_expected) {
++ ret = -EMFILE;
++ goto out;
++ }
++ }
+
+ if (nf_ct_expect_count >= nf_ct_expect_max) {
+ if (net_ratelimit())
+@@ -460,6 +488,7 @@ static int exp_seq_show(struct seq_file *s, void *v)
+ {
+ struct nf_conntrack_expect *expect;
+ struct hlist_node *n = v;
++ char *delim = "";
+
+ expect = hlist_entry(n, struct nf_conntrack_expect, hnode);
+
+@@ -475,6 +504,14 @@ static int exp_seq_show(struct seq_file *s, void *v)
+ __nf_ct_l3proto_find(expect->tuple.src.l3num),
+ __nf_ct_l4proto_find(expect->tuple.src.l3num,
+ expect->tuple.dst.protonum));
++
++ if (expect->flags & NF_CT_EXPECT_PERMANENT) {
++ seq_printf(s, "PERMANENT");
++ delim = ",";
++ }
++ if (expect->flags & NF_CT_EXPECT_INACTIVE)
++ seq_printf(s, "%sINACTIVE", delim);
++
+ return seq_putc(s, '\n');
+ }
+
+diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c
+index 2bd9963..bcc19fa 100644
+--- a/net/netfilter/nf_conntrack_extend.c
++++ b/net/netfilter/nf_conntrack_extend.c
+@@ -71,6 +71,9 @@ void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
+ int i, newlen, newoff;
+ struct nf_ct_ext_type *t;
+
++ /* Conntrack must not be confirmed to avoid races on reallocation. */
++ NF_CT_ASSERT(!nf_ct_is_confirmed(ct));
++
+ if (!ct->ext)
+ return nf_ct_ext_create(&ct->ext, id, gfp);
+
+diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
+index 6770baf..bb20672 100644
+--- a/net/netfilter/nf_conntrack_ftp.c
++++ b/net/netfilter/nf_conntrack_ftp.c
+@@ -350,8 +350,9 @@ static int help(struct sk_buff *skb,
+ enum ip_conntrack_info ctinfo)
+ {
+ unsigned int dataoff, datalen;
+- struct tcphdr _tcph, *th;
+- char *fb_ptr;
++ const struct tcphdr *th;
++ struct tcphdr _tcph;
++ const char *fb_ptr;
+ int ret;
+ u32 seq;
+ int dir = CTINFO2DIR(ctinfo);
+@@ -405,7 +406,7 @@ static int help(struct sk_buff *skb,
+
+ /* Initialize IP/IPv6 addr to expected address (it's not mentioned
+ in EPSV responses) */
+- cmd.l3num = ct->tuplehash[dir].tuple.src.l3num;
++ cmd.l3num = nf_ct_l3num(ct);
+ memcpy(cmd.u3.all, &ct->tuplehash[dir].tuple.src.u3.all,
+ sizeof(cmd.u3.all));
+
+@@ -452,7 +453,7 @@ static int help(struct sk_buff *skb,
+ daddr = &ct->tuplehash[!dir].tuple.dst.u3;
+
+ /* Update the ftp info */
+- if ((cmd.l3num == ct->tuplehash[dir].tuple.src.l3num) &&
++ if ((cmd.l3num == nf_ct_l3num(ct)) &&
+ memcmp(&cmd.u3.all, &ct->tuplehash[dir].tuple.src.u3.all,
+ sizeof(cmd.u3.all))) {
+ /* Enrico Scholz's passive FTP to partially RNAT'd ftp
+@@ -483,7 +484,7 @@ static int help(struct sk_buff *skb,
+ daddr = &cmd.u3;
+ }
+
+- nf_ct_expect_init(exp, cmd.l3num,
++ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, cmd.l3num,
+ &ct->tuplehash[!dir].tuple.src.u3, daddr,
+ IPPROTO_TCP, NULL, &cmd.u.tcp.port);
+
+@@ -517,6 +518,11 @@ out_update_nl:
+ static struct nf_conntrack_helper ftp[MAX_PORTS][2] __read_mostly;
+ static char ftp_names[MAX_PORTS][2][sizeof("ftp-65535")] __read_mostly;
+
++static const struct nf_conntrack_expect_policy ftp_exp_policy = {
++ .max_expected = 1,
++ .timeout = 5 * 60,
++};
++
+ /* don't make this __exit, since it's called from __init ! */
+ static void nf_conntrack_ftp_fini(void)
+ {
+@@ -556,8 +562,7 @@ static int __init nf_conntrack_ftp_init(void)
+ for (j = 0; j < 2; j++) {
+ ftp[i][j].tuple.src.u.tcp.port = htons(ports[i]);
+ ftp[i][j].tuple.dst.protonum = IPPROTO_TCP;
+- ftp[i][j].max_expected = 1;
+- ftp[i][j].timeout = 5 * 60; /* 5 Minutes */
++ ftp[i][j].expect_policy = &ftp_exp_policy;
+ ftp[i][j].me = THIS_MODULE;
+ ftp[i][j].help = help;
+ tmpname = &ftp_names[i][j][0];
+diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
+index 898f192..95da1a2 100644
+--- a/net/netfilter/nf_conntrack_h323_main.c
++++ b/net/netfilter/nf_conntrack_h323_main.c
+@@ -218,7 +218,6 @@ static int get_h245_addr(struct nf_conn *ct, const unsigned char *data,
+ union nf_inet_addr *addr, __be16 *port)
+ {
+ const unsigned char *p;
+- int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ int len;
+
+ if (taddr->choice != eH245_TransportAddress_unicastAddress)
+@@ -226,13 +225,13 @@ static int get_h245_addr(struct nf_conn *ct, const unsigned char *data,
+
+ switch (taddr->unicastAddress.choice) {
+ case eUnicastAddress_iPAddress:
+- if (family != AF_INET)
++ if (nf_ct_l3num(ct) != AF_INET)
+ return 0;
+ p = data + taddr->unicastAddress.iPAddress.network;
+ len = 4;
+ break;
+ case eUnicastAddress_iP6Address:
+- if (family != AF_INET6)
++ if (nf_ct_l3num(ct) != AF_INET6)
+ return 0;
+ p = data + taddr->unicastAddress.iP6Address.network;
+ len = 16;
+@@ -277,7 +276,7 @@ static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
+ /* Create expect for RTP */
+ if ((rtp_exp = nf_ct_expect_alloc(ct)) == NULL)
+ return -1;
+- nf_ct_expect_init(rtp_exp, ct->tuplehash[!dir].tuple.src.l3num,
++ nf_ct_expect_init(rtp_exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
+ &ct->tuplehash[!dir].tuple.src.u3,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ IPPROTO_UDP, NULL, &rtp_port);
+@@ -287,7 +286,7 @@ static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
+ nf_ct_expect_put(rtp_exp);
+ return -1;
+ }
+- nf_ct_expect_init(rtcp_exp, ct->tuplehash[!dir].tuple.src.l3num,
++ nf_ct_expect_init(rtcp_exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
+ &ct->tuplehash[!dir].tuple.src.u3,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ IPPROTO_UDP, NULL, &rtcp_port);
+@@ -304,9 +303,9 @@ static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
+ if (nf_ct_expect_related(rtp_exp) == 0) {
+ if (nf_ct_expect_related(rtcp_exp) == 0) {
+ pr_debug("nf_ct_h323: expect RTP ");
+- NF_CT_DUMP_TUPLE(&rtp_exp->tuple);
++ nf_ct_dump_tuple(&rtp_exp->tuple);
+ pr_debug("nf_ct_h323: expect RTCP ");
+- NF_CT_DUMP_TUPLE(&rtcp_exp->tuple);
++ nf_ct_dump_tuple(&rtcp_exp->tuple);
+ } else {
+ nf_ct_unexpect_related(rtp_exp);
+ ret = -1;
+@@ -344,7 +343,7 @@ static int expect_t120(struct sk_buff *skb,
+ /* Create expect for T.120 connections */
+ if ((exp = nf_ct_expect_alloc(ct)) == NULL)
+ return -1;
+- nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
++ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
+ &ct->tuplehash[!dir].tuple.src.u3,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ IPPROTO_TCP, NULL, &port);
+@@ -361,7 +360,7 @@ static int expect_t120(struct sk_buff *skb,
+ } else { /* Conntrack only */
+ if (nf_ct_expect_related(exp) == 0) {
+ pr_debug("nf_ct_h323: expect T.120 ");
+- NF_CT_DUMP_TUPLE(&exp->tuple);
++ nf_ct_dump_tuple(&exp->tuple);
+ } else
+ ret = -1;
+ }
+@@ -583,7 +582,7 @@ static int h245_help(struct sk_buff *skb, unsigned int protoff,
+ while (get_tpkt_data(skb, protoff, ct, ctinfo,
+ &data, &datalen, &dataoff)) {
+ pr_debug("nf_ct_h245: TPKT len=%d ", datalen);
+- NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
++ nf_ct_dump_tuple(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
+
+ /* Decode H.245 signal */
+ ret = DecodeMultimediaSystemControlMessage(data, datalen,
+@@ -612,13 +611,17 @@ static int h245_help(struct sk_buff *skb, unsigned int protoff,
+ }
+
+ /****************************************************************************/
++static const struct nf_conntrack_expect_policy h245_exp_policy = {
++ .max_expected = H323_RTP_CHANNEL_MAX * 4 + 2 /* T.120 */,
++ .timeout = 240,
++};
++
+ static struct nf_conntrack_helper nf_conntrack_helper_h245 __read_mostly = {
+ .name = "H.245",
+ .me = THIS_MODULE,
+- .max_expected = H323_RTP_CHANNEL_MAX * 4 + 2 /* T.120 */,
+- .timeout = 240,
+ .tuple.dst.protonum = IPPROTO_UDP,
+- .help = h245_help
++ .help = h245_help,
++ .expect_policy = &h245_exp_policy,
+ };
+
+ /****************************************************************************/
+@@ -627,18 +630,17 @@ int get_h225_addr(struct nf_conn *ct, unsigned char *data,
+ union nf_inet_addr *addr, __be16 *port)
+ {
+ const unsigned char *p;
+- int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ int len;
+
+ switch (taddr->choice) {
+ case eTransportAddress_ipAddress:
+- if (family != AF_INET)
++ if (nf_ct_l3num(ct) != AF_INET)
+ return 0;
+ p = data + taddr->ipAddress.ip;
+ len = 4;
+ break;
+ case eTransportAddress_ip6Address:
+- if (family != AF_INET6)
++ if (nf_ct_l3num(ct) != AF_INET6)
+ return 0;
+ p = data + taddr->ip6Address.ip;
+ len = 16;
+@@ -676,7 +678,7 @@ static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,
+ /* Create expect for h245 connection */
+ if ((exp = nf_ct_expect_alloc(ct)) == NULL)
+ return -1;
+- nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
++ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
+ &ct->tuplehash[!dir].tuple.src.u3,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ IPPROTO_TCP, NULL, &port);
+@@ -693,7 +695,7 @@ static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,
+ } else { /* Conntrack only */
+ if (nf_ct_expect_related(exp) == 0) {
+ pr_debug("nf_ct_q931: expect H.245 ");
+- NF_CT_DUMP_TUPLE(&exp->tuple);
++ nf_ct_dump_tuple(&exp->tuple);
+ } else
+ ret = -1;
+ }
+@@ -784,7 +786,7 @@ static int expect_callforwarding(struct sk_buff *skb,
+ * we don't need to track the second call */
+ if (callforward_filter &&
+ callforward_do_filter(&addr, &ct->tuplehash[!dir].tuple.src.u3,
+- ct->tuplehash[!dir].tuple.src.l3num)) {
++ nf_ct_l3num(ct))) {
+ pr_debug("nf_ct_q931: Call Forwarding not tracked\n");
+ return 0;
+ }
+@@ -792,7 +794,7 @@ static int expect_callforwarding(struct sk_buff *skb,
+ /* Create expect for the second call leg */
+ if ((exp = nf_ct_expect_alloc(ct)) == NULL)
+ return -1;
+- nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
++ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
+ &ct->tuplehash[!dir].tuple.src.u3, &addr,
+ IPPROTO_TCP, NULL, &port);
+ exp->helper = nf_conntrack_helper_q931;
+@@ -808,7 +810,7 @@ static int expect_callforwarding(struct sk_buff *skb,
+ } else { /* Conntrack only */
+ if (nf_ct_expect_related(exp) == 0) {
+ pr_debug("nf_ct_q931: expect Call Forwarding ");
+- NF_CT_DUMP_TUPLE(&exp->tuple);
++ nf_ct_dump_tuple(&exp->tuple);
+ } else
+ ret = -1;
+ }
+@@ -1128,7 +1130,7 @@ static int q931_help(struct sk_buff *skb, unsigned int protoff,
+ while (get_tpkt_data(skb, protoff, ct, ctinfo,
+ &data, &datalen, &dataoff)) {
+ pr_debug("nf_ct_q931: TPKT len=%d ", datalen);
+- NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
++ nf_ct_dump_tuple(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
+
+ /* Decode Q.931 signal */
+ ret = DecodeQ931(data, datalen, &q931);
+@@ -1156,28 +1158,30 @@ static int q931_help(struct sk_buff *skb, unsigned int protoff,
+ }
+
+ /****************************************************************************/
++static const struct nf_conntrack_expect_policy q931_exp_policy = {
++ /* T.120 and H.245 */
++ .max_expected = H323_RTP_CHANNEL_MAX * 4 + 4,
++ .timeout = 240,
++};
++
+ static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = {
+ {
+ .name = "Q.931",
+ .me = THIS_MODULE,
+- /* T.120 and H.245 */
+- .max_expected = H323_RTP_CHANNEL_MAX * 4 + 4,
+- .timeout = 240,
+ .tuple.src.l3num = AF_INET,
+ .tuple.src.u.tcp.port = __constant_htons(Q931_PORT),
+ .tuple.dst.protonum = IPPROTO_TCP,
+- .help = q931_help
++ .help = q931_help,
++ .expect_policy = &q931_exp_policy,
+ },
+ {
+ .name = "Q.931",
+ .me = THIS_MODULE,
+- /* T.120 and H.245 */
+- .max_expected = H323_RTP_CHANNEL_MAX * 4 + 4,
+- .timeout = 240,
+ .tuple.src.l3num = AF_INET6,
+ .tuple.src.u.tcp.port = __constant_htons(Q931_PORT),
+ .tuple.dst.protonum = IPPROTO_TCP,
+- .help = q931_help
++ .help = q931_help,
++ .expect_policy = &q931_exp_policy,
+ },
+ };
+
+@@ -1261,7 +1265,7 @@ static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,
+ /* Create expect for Q.931 */
+ if ((exp = nf_ct_expect_alloc(ct)) == NULL)
+ return -1;
+- nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
++ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
+ gkrouted_only ? /* only accept calls from GK? */
+ &ct->tuplehash[!dir].tuple.src.u3 : NULL,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+@@ -1275,7 +1279,7 @@ static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,
+ } else { /* Conntrack only */
+ if (nf_ct_expect_related(exp) == 0) {
+ pr_debug("nf_ct_ras: expect Q.931 ");
+- NF_CT_DUMP_TUPLE(&exp->tuple);
++ nf_ct_dump_tuple(&exp->tuple);
+
+ /* Save port for looking up expect in processing RCF */
+ info->sig_port[dir] = port;
+@@ -1332,14 +1336,14 @@ static int process_gcf(struct sk_buff *skb, struct nf_conn *ct,
+ /* Need new expect */
+ if ((exp = nf_ct_expect_alloc(ct)) == NULL)
+ return -1;
+- nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
++ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
+ &ct->tuplehash[!dir].tuple.src.u3, &addr,
+ IPPROTO_UDP, NULL, &port);
+ exp->helper = nf_conntrack_helper_ras;
+
+ if (nf_ct_expect_related(exp) == 0) {
+ pr_debug("nf_ct_ras: expect RAS ");
+- NF_CT_DUMP_TUPLE(&exp->tuple);
++ nf_ct_dump_tuple(&exp->tuple);
+ } else
+ ret = -1;
+
+@@ -1423,7 +1427,7 @@ static int process_rcf(struct sk_buff *skb, struct nf_conn *ct,
+ pr_debug("nf_ct_ras: set Q.931 expect "
+ "timeout to %u seconds for",
+ info->timeout);
+- NF_CT_DUMP_TUPLE(&exp->tuple);
++ nf_ct_dump_tuple(&exp->tuple);
+ set_expect_timeout(exp, info->timeout);
+ }
+ spin_unlock_bh(&nf_conntrack_lock);
+@@ -1536,7 +1540,7 @@ static int process_acf(struct sk_buff *skb, struct nf_conn *ct,
+ /* Need new expect */
+ if ((exp = nf_ct_expect_alloc(ct)) == NULL)
+ return -1;
+- nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
++ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
+ &ct->tuplehash[!dir].tuple.src.u3, &addr,
+ IPPROTO_TCP, NULL, &port);
+ exp->flags = NF_CT_EXPECT_PERMANENT;
+@@ -1544,7 +1548,7 @@ static int process_acf(struct sk_buff *skb, struct nf_conn *ct,
+
+ if (nf_ct_expect_related(exp) == 0) {
+ pr_debug("nf_ct_ras: expect Q.931 ");
+- NF_CT_DUMP_TUPLE(&exp->tuple);
++ nf_ct_dump_tuple(&exp->tuple);
+ } else
+ ret = -1;
+
+@@ -1589,7 +1593,7 @@ static int process_lcf(struct sk_buff *skb, struct nf_conn *ct,
+ /* Need new expect for call signal */
+ if ((exp = nf_ct_expect_alloc(ct)) == NULL)
+ return -1;
+- nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
++ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
+ &ct->tuplehash[!dir].tuple.src.u3, &addr,
+ IPPROTO_TCP, NULL, &port);
+ exp->flags = NF_CT_EXPECT_PERMANENT;
+@@ -1597,7 +1601,7 @@ static int process_lcf(struct sk_buff *skb, struct nf_conn *ct,
+
+ if (nf_ct_expect_related(exp) == 0) {
+ pr_debug("nf_ct_ras: expect Q.931 ");
+- NF_CT_DUMP_TUPLE(&exp->tuple);
++ nf_ct_dump_tuple(&exp->tuple);
+ } else
+ ret = -1;
+
+@@ -1701,7 +1705,7 @@ static int ras_help(struct sk_buff *skb, unsigned int protoff,
+ if (data == NULL)
+ goto accept;
+ pr_debug("nf_ct_ras: RAS message len=%d ", datalen);
+- NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
++ nf_ct_dump_tuple(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
+
+ /* Decode RAS message */
+ ret = DecodeRasMessage(data, datalen, &ras);
+@@ -1728,26 +1732,29 @@ static int ras_help(struct sk_buff *skb, unsigned int protoff,
+ }
+
+ /****************************************************************************/
++static const struct nf_conntrack_expect_policy ras_exp_policy = {
++ .max_expected = 32,
++ .timeout = 240,
++};
++
+ static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = {
+ {
+ .name = "RAS",
+ .me = THIS_MODULE,
+- .max_expected = 32,
+- .timeout = 240,
+ .tuple.src.l3num = AF_INET,
+ .tuple.src.u.udp.port = __constant_htons(RAS_PORT),
+ .tuple.dst.protonum = IPPROTO_UDP,
+ .help = ras_help,
++ .expect_policy = &ras_exp_policy,
+ },
+ {
+ .name = "RAS",
+ .me = THIS_MODULE,
+- .max_expected = 32,
+- .timeout = 240,
+ .tuple.src.l3num = AF_INET6,
+ .tuple.src.u.udp.port = __constant_htons(RAS_PORT),
+ .tuple.dst.protonum = IPPROTO_UDP,
+ .help = ras_help,
++ .expect_policy = &ras_exp_policy,
+ },
+ };
+
+diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
+index b1fd21c..7d1b117 100644
+--- a/net/netfilter/nf_conntrack_helper.c
++++ b/net/netfilter/nf_conntrack_helper.c
+@@ -110,7 +110,8 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
+ {
+ unsigned int h = helper_hash(&me->tuple);
+
+- BUG_ON(me->timeout == 0);
++ BUG_ON(me->expect_policy == NULL);
++ BUG_ON(me->expect_class_max >= NF_CT_MAX_EXPECT_CLASSES);
+
+ mutex_lock(&nf_ct_helper_mutex);
+ hlist_add_head_rcu(&me->hnode, &nf_ct_helper_hash[h]);
+@@ -125,7 +126,7 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
+ {
+ struct nf_conntrack_tuple_hash *h;
+ struct nf_conntrack_expect *exp;
+- struct hlist_node *n, *next;
++ const struct hlist_node *n, *next;
+ unsigned int i;
+
+ mutex_lock(&nf_ct_helper_mutex);
+diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
+index c336b07..1b1226d 100644
+--- a/net/netfilter/nf_conntrack_irc.c
++++ b/net/netfilter/nf_conntrack_irc.c
+@@ -50,7 +50,7 @@ MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per "
+ module_param(dcc_timeout, uint, 0400);
+ MODULE_PARM_DESC(dcc_timeout, "timeout on for unestablished DCC channels");
+
+-static const char *dccprotos[] = {
++static const char *const dccprotos[] = {
+ "SEND ", "CHAT ", "MOVE ", "TSEND ", "SCHAT "
+ };
+
+@@ -65,7 +65,7 @@ static const char *dccprotos[] = {
+ * ad_beg_p returns pointer to first byte of addr data
+ * ad_end_p returns pointer to last byte of addr data
+ */
+-static int parse_dcc(char *data, char *data_end, u_int32_t *ip,
++static int parse_dcc(char *data, const char *data_end, u_int32_t *ip,
+ u_int16_t *port, char **ad_beg_p, char **ad_end_p)
+ {
+ /* at least 12: "AAAAAAAA P\1\n" */
+@@ -93,9 +93,11 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+ struct nf_conn *ct, enum ip_conntrack_info ctinfo)
+ {
+ unsigned int dataoff;
+- struct iphdr *iph;
+- struct tcphdr _tcph, *th;
+- char *data, *data_limit, *ib_ptr;
++ const struct iphdr *iph;
++ const struct tcphdr *th;
++ struct tcphdr _tcph;
++ const char *data_limit;
++ char *data, *ib_ptr;
+ int dir = CTINFO2DIR(ctinfo);
+ struct nf_conntrack_expect *exp;
+ struct nf_conntrack_tuple *tuple;
+@@ -159,7 +161,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+ /* we have at least
+ * (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid
+ * data left (== 14/13 bytes) */
+- if (parse_dcc((char *)data, data_limit, &dcc_ip,
++ if (parse_dcc(data, data_limit, &dcc_ip,
+ &dcc_port, &addr_beg_p, &addr_end_p)) {
+ pr_debug("unable to parse dcc command\n");
+ continue;
+@@ -187,7 +189,8 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+ }
+ tuple = &ct->tuplehash[!dir].tuple;
+ port = htons(dcc_port);
+- nf_ct_expect_init(exp, tuple->src.l3num,
++ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,
++ tuple->src.l3num,
+ NULL, &tuple->dst.u3,
+ IPPROTO_TCP, NULL, &port);
+
+@@ -210,6 +213,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+
+ static struct nf_conntrack_helper irc[MAX_PORTS] __read_mostly;
+ static char irc_names[MAX_PORTS][sizeof("irc-65535")] __read_mostly;
++static struct nf_conntrack_expect_policy irc_exp_policy;
+
+ static void nf_conntrack_irc_fini(void);
+
+@@ -223,6 +227,9 @@ static int __init nf_conntrack_irc_init(void)
+ return -EINVAL;
+ }
+
++ irc_exp_policy.max_expected = max_dcc_channels;
++ irc_exp_policy.timeout = dcc_timeout;
++
+ irc_buffer = kmalloc(65536, GFP_KERNEL);
+ if (!irc_buffer)
+ return -ENOMEM;
+@@ -235,8 +242,7 @@ static int __init nf_conntrack_irc_init(void)
+ irc[i].tuple.src.l3num = AF_INET;
+ irc[i].tuple.src.u.tcp.port = htons(ports[i]);
+ irc[i].tuple.dst.protonum = IPPROTO_TCP;
+- irc[i].max_expected = max_dcc_channels;
+- irc[i].timeout = dcc_timeout;
++ irc[i].expect_policy = &irc_exp_policy;
+ irc[i].me = THIS_MODULE;
+ irc[i].help = help;
+
+diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c
+index 8e914e5..e7eb807 100644
+--- a/net/netfilter/nf_conntrack_l3proto_generic.c
++++ b/net/netfilter/nf_conntrack_l3proto_generic.c
+@@ -31,22 +31,22 @@
+ #include <net/netfilter/nf_conntrack_core.h>
+ #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
+
+-static int generic_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
+- struct nf_conntrack_tuple *tuple)
++static bool generic_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
++ struct nf_conntrack_tuple *tuple)
+ {
+ memset(&tuple->src.u3, 0, sizeof(tuple->src.u3));
+ memset(&tuple->dst.u3, 0, sizeof(tuple->dst.u3));
+
+- return 1;
++ return true;
+ }
+
+-static int generic_invert_tuple(struct nf_conntrack_tuple *tuple,
+- const struct nf_conntrack_tuple *orig)
++static bool generic_invert_tuple(struct nf_conntrack_tuple *tuple,
++ const struct nf_conntrack_tuple *orig)
+ {
+ memset(&tuple->src.u3, 0, sizeof(tuple->src.u3));
+ memset(&tuple->dst.u3, 0, sizeof(tuple->dst.u3));
+
+- return 1;
++ return true;
+ }
+
+ static int generic_print_tuple(struct seq_file *s,
+diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c
+index 9810d81..08404e6 100644
+--- a/net/netfilter/nf_conntrack_netbios_ns.c
++++ b/net/netfilter/nf_conntrack_netbios_ns.c
+@@ -47,7 +47,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+ {
+ struct nf_conntrack_expect *exp;
+ struct iphdr *iph = ip_hdr(skb);
+- struct rtable *rt = (struct rtable *)skb->dst;
++ struct rtable *rt = skb->rtable;
+ struct in_device *in_dev;
+ __be32 mask = 0;
+
+@@ -86,6 +86,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
+
+ exp->expectfn = NULL;
+ exp->flags = NF_CT_EXPECT_PERMANENT;
++ exp->class = NF_CT_EXPECT_CLASS_DEFAULT;
+ exp->helper = NULL;
+
+ nf_ct_expect_related(exp);
+@@ -96,19 +97,23 @@ out:
+ return NF_ACCEPT;
+ }
+
++static struct nf_conntrack_expect_policy exp_policy = {
++ .max_expected = 1,
++};
++
+ static struct nf_conntrack_helper helper __read_mostly = {
+ .name = "netbios-ns",
+ .tuple.src.l3num = AF_INET,
+ .tuple.src.u.udp.port = __constant_htons(NMBD_PORT),
+ .tuple.dst.protonum = IPPROTO_UDP,
+- .max_expected = 1,
+ .me = THIS_MODULE,
+ .help = help,
++ .expect_policy = &exp_policy,
+ };
+
+ static int __init nf_conntrack_netbios_ns_init(void)
+ {
+- helper.timeout = timeout;
++ exp_policy.timeout = timeout;
+ return nf_conntrack_helper_register(&helper);
+ }
+
+diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
+index 4a1b42b..16774ec 100644
+--- a/net/netfilter/nf_conntrack_netlink.c
++++ b/net/netfilter/nf_conntrack_netlink.c
+@@ -145,10 +145,11 @@ nla_put_failure:
+ static inline int
+ ctnetlink_dump_protoinfo(struct sk_buff *skb, const struct nf_conn *ct)
+ {
+- struct nf_conntrack_l4proto *l4proto = nf_ct_l4proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num, ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
++ struct nf_conntrack_l4proto *l4proto;
+ struct nlattr *nest_proto;
+ int ret;
+
++ l4proto = nf_ct_l4proto_find_get(nf_ct_l3num(ct), nf_ct_protonum(ct));
+ if (!l4proto->to_nlattr) {
+ nf_ct_l4proto_put(l4proto);
+ return 0;
+@@ -368,8 +369,7 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
+ nfmsg = NLMSG_DATA(nlh);
+
+ nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0;
+- nfmsg->nfgen_family =
+- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
++ nfmsg->nfgen_family = nf_ct_l3num(ct);
+ nfmsg->version = NFNETLINK_V0;
+ nfmsg->res_id = 0;
+
+@@ -454,7 +454,7 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
+ nfmsg = NLMSG_DATA(nlh);
+
+ nlh->nlmsg_flags = flags;
+- nfmsg->nfgen_family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
++ nfmsg->nfgen_family = nf_ct_l3num(ct);
+ nfmsg->version = NFNETLINK_V0;
+ nfmsg->res_id = 0;
+
+@@ -535,8 +535,6 @@ static int ctnetlink_done(struct netlink_callback *cb)
+ return 0;
+ }
+
+-#define L3PROTO(ct) (ct)->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num
+-
+ static int
+ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+@@ -558,7 +556,7 @@ restart:
+ /* Dump entries of a given L3 protocol number.
+ * If it is not specified, ie. l3proto == 0,
+ * then dump everything. */
+- if (l3proto && L3PROTO(ct) != l3proto)
++ if (l3proto && nf_ct_l3num(ct) != l3proto)
+ continue;
+ if (cb->args[1]) {
+ if (ct != last)
+@@ -704,20 +702,11 @@ static int nfnetlink_parse_nat_proto(struct nlattr *attr,
+ if (err < 0)
+ return err;
+
+- npt = nf_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
+-
+- if (!npt->nlattr_to_range) {
+- nf_nat_proto_put(npt);
+- return 0;
+- }
+-
+- /* nlattr_to_range returns 1 if it parsed, 0 if not, neg. on error */
+- if (npt->nlattr_to_range(tb, range) > 0)
+- range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
+-
++ npt = nf_nat_proto_find_get(nf_ct_protonum(ct));
++ if (npt->nlattr_to_range)
++ err = npt->nlattr_to_range(tb, range);
+ nf_nat_proto_put(npt);
+-
+- return 0;
++ return err;
+ }
+
+ static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = {
+@@ -1010,14 +999,11 @@ ctnetlink_change_protoinfo(struct nf_conn *ct, struct nlattr *cda[])
+ {
+ struct nlattr *tb[CTA_PROTOINFO_MAX+1], *attr = cda[CTA_PROTOINFO];
+ struct nf_conntrack_l4proto *l4proto;
+- u_int16_t npt = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
+- u_int16_t l3num = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ int err = 0;
+
+ nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr, NULL);
+
+- l4proto = nf_ct_l4proto_find_get(l3num, npt);
+-
++ l4proto = nf_ct_l4proto_find_get(nf_ct_l3num(ct), nf_ct_protonum(ct));
+ if (l4proto->from_nlattr)
+ err = l4proto->from_nlattr(tb, ct);
+ nf_ct_l4proto_put(l4proto);
+diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
+index b5cb8e8..97e54b0 100644
+--- a/net/netfilter/nf_conntrack_pptp.c
++++ b/net/netfilter/nf_conntrack_pptp.c
+@@ -119,7 +119,7 @@ static void pptp_expectfn(struct nf_conn *ct,
+ /* obviously this tuple inversion only works until you do NAT */
+ nf_ct_invert_tuplepr(&inv_t, &exp->tuple);
+ pr_debug("trying to unexpect other dir: ");
+- NF_CT_DUMP_TUPLE(&inv_t);
++ nf_ct_dump_tuple(&inv_t);
+
+ exp_other = nf_ct_expect_find_get(&inv_t);
+ if (exp_other) {
+@@ -141,7 +141,7 @@ static int destroy_sibling_or_exp(const struct nf_conntrack_tuple *t)
+ struct nf_conn *sibling;
+
+ pr_debug("trying to timeout ct or exp for tuple ");
+- NF_CT_DUMP_TUPLE(t);
++ nf_ct_dump_tuple(t);
+
+ h = nf_conntrack_find_get(t);
+ if (h) {
+@@ -208,7 +208,8 @@ static int exp_gre(struct nf_conn *ct, __be16 callid, __be16 peer_callid)
+
+ /* original direction, PNS->PAC */
+ dir = IP_CT_DIR_ORIGINAL;
+- nf_ct_expect_init(exp_orig, ct->tuplehash[dir].tuple.src.l3num,
++ nf_ct_expect_init(exp_orig, NF_CT_EXPECT_CLASS_DEFAULT,
++ nf_ct_l3num(ct),
+ &ct->tuplehash[dir].tuple.src.u3,
+ &ct->tuplehash[dir].tuple.dst.u3,
+ IPPROTO_GRE, &peer_callid, &callid);
+@@ -216,7 +217,8 @@ static int exp_gre(struct nf_conn *ct, __be16 callid, __be16 peer_callid)
+
+ /* reply direction, PAC->PNS */
+ dir = IP_CT_DIR_REPLY;
+- nf_ct_expect_init(exp_reply, ct->tuplehash[dir].tuple.src.l3num,
++ nf_ct_expect_init(exp_reply, NF_CT_EXPECT_CLASS_DEFAULT,
++ nf_ct_l3num(ct),
+ &ct->tuplehash[dir].tuple.src.u3,
+ &ct->tuplehash[dir].tuple.dst.u3,
+ IPPROTO_GRE, &callid, &peer_callid);
+@@ -575,17 +577,21 @@ conntrack_pptp_help(struct sk_buff *skb, unsigned int protoff,
+ return ret;
+ }
+
++static const struct nf_conntrack_expect_policy pptp_exp_policy = {
++ .max_expected = 2,
++ .timeout = 5 * 60,
++};
++
+ /* control protocol helper */
+ static struct nf_conntrack_helper pptp __read_mostly = {
+ .name = "pptp",
+ .me = THIS_MODULE,
+- .max_expected = 2,
+- .timeout = 5 * 60,
+ .tuple.src.l3num = AF_INET,
+ .tuple.src.u.tcp.port = __constant_htons(PPTP_CONTROL_PORT),
+ .tuple.dst.protonum = IPPROTO_TCP,
+ .help = conntrack_pptp_help,
+ .destroy = pptp_destroy_siblings,
++ .expect_policy = &pptp_exp_policy,
+ };
+
+ static int __init nf_conntrack_pptp_init(void)
+diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
+index 8595b59..a49fc93 100644
+--- a/net/netfilter/nf_conntrack_proto.c
++++ b/net/netfilter/nf_conntrack_proto.c
+@@ -146,18 +146,15 @@ EXPORT_SYMBOL_GPL(nf_ct_l3proto_module_put);
+
+ static int kill_l3proto(struct nf_conn *i, void *data)
+ {
+- return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num ==
+- ((struct nf_conntrack_l3proto *)data)->l3proto);
++ return nf_ct_l3num(i) == ((struct nf_conntrack_l3proto *)data)->l3proto;
+ }
+
+ static int kill_l4proto(struct nf_conn *i, void *data)
+ {
+ struct nf_conntrack_l4proto *l4proto;
+ l4proto = (struct nf_conntrack_l4proto *)data;
+- return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum ==
+- l4proto->l4proto) &&
+- (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num ==
+- l4proto->l3proto);
++ return nf_ct_protonum(i) == l4proto->l4proto &&
++ nf_ct_l3num(i) == l4proto->l3proto;
+ }
+
+ static int nf_ct_l3proto_register_sysctl(struct nf_conntrack_l3proto *l3proto)
+diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c
+new file mode 100644
+index 0000000..afb4a18
+--- /dev/null
++++ b/net/netfilter/nf_conntrack_proto_dccp.c
+@@ -0,0 +1,815 @@
++/*
++ * DCCP connection tracking protocol helper
++ *
++ * Copyright (c) 2005, 2006, 2008 Patrick McHardy <kaber at trash.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/sysctl.h>
++#include <linux/spinlock.h>
++#include <linux/skbuff.h>
++#include <linux/dccp.h>
++
++#include <linux/netfilter/nfnetlink_conntrack.h>
++#include <net/netfilter/nf_conntrack.h>
++#include <net/netfilter/nf_conntrack_l4proto.h>
++#include <net/netfilter/nf_log.h>
++
++static DEFINE_RWLOCK(dccp_lock);
++
++static int nf_ct_dccp_loose __read_mostly = 1;
++
++/* Timeouts are based on values from RFC4340:
++ *
++ * - REQUEST:
++ *
++ * 8.1.2. Client Request
++ *
++ * A client MAY give up on its DCCP-Requests after some time
++ * (3 minutes, for example).
++ *
++ * - RESPOND:
++ *
++ * 8.1.3. Server Response
++ *
++ * It MAY also leave the RESPOND state for CLOSED after a timeout of
++ * not less than 4MSL (8 minutes);
++ *
++ * - PARTOPEN:
++ *
++ * 8.1.5. Handshake Completion
++ *
++ * If the client remains in PARTOPEN for more than 4MSL (8 minutes),
++ * it SHOULD reset the connection with Reset Code 2, "Aborted".
++ *
++ * - OPEN:
++ *
++ * The DCCP timestamp overflows after 11.9 hours. If the connection
++ * stays idle this long the sequence number won't be recognized
++ * as valid anymore.
++ *
++ * - CLOSEREQ/CLOSING:
++ *
++ * 8.3. Termination
++ *
++ * The retransmission timer should initially be set to go off in two
++ * round-trip times and should back off to not less than once every
++ * 64 seconds ...
++ *
++ * - TIMEWAIT:
++ *
++ * 4.3. States
++ *
++ * A server or client socket remains in this state for 2MSL (4 minutes)
++ * after the connection has been town down, ...
++ */
++
++#define DCCP_MSL (2 * 60 * HZ)
++
++static unsigned int dccp_timeout[CT_DCCP_MAX + 1] __read_mostly = {
++ [CT_DCCP_REQUEST] = 2 * DCCP_MSL,
++ [CT_DCCP_RESPOND] = 4 * DCCP_MSL,
++ [CT_DCCP_PARTOPEN] = 4 * DCCP_MSL,
++ [CT_DCCP_OPEN] = 12 * 3600 * HZ,
++ [CT_DCCP_CLOSEREQ] = 64 * HZ,
++ [CT_DCCP_CLOSING] = 64 * HZ,
++ [CT_DCCP_TIMEWAIT] = 2 * DCCP_MSL,
++};
++
++static const char * const dccp_state_names[] = {
++ [CT_DCCP_NONE] = "NONE",
++ [CT_DCCP_REQUEST] = "REQUEST",
++ [CT_DCCP_RESPOND] = "RESPOND",
++ [CT_DCCP_PARTOPEN] = "PARTOPEN",
++ [CT_DCCP_OPEN] = "OPEN",
++ [CT_DCCP_CLOSEREQ] = "CLOSEREQ",
++ [CT_DCCP_CLOSING] = "CLOSING",
++ [CT_DCCP_TIMEWAIT] = "TIMEWAIT",
++ [CT_DCCP_IGNORE] = "IGNORE",
++ [CT_DCCP_INVALID] = "INVALID",
++};
++
++#define sNO CT_DCCP_NONE
++#define sRQ CT_DCCP_REQUEST
++#define sRS CT_DCCP_RESPOND
++#define sPO CT_DCCP_PARTOPEN
++#define sOP CT_DCCP_OPEN
++#define sCR CT_DCCP_CLOSEREQ
++#define sCG CT_DCCP_CLOSING
++#define sTW CT_DCCP_TIMEWAIT
++#define sIG CT_DCCP_IGNORE
++#define sIV CT_DCCP_INVALID
++
++/*
++ * DCCP state transistion table
++ *
++ * The assumption is the same as for TCP tracking:
++ *
++ * We are the man in the middle. All the packets go through us but might
++ * get lost in transit to the destination. It is assumed that the destination
++ * can't receive segments we haven't seen.
++ *
++ * The following states exist:
++ *
++ * NONE: Initial state, expecting Request
++ * REQUEST: Request seen, waiting for Response from server
++ * RESPOND: Response from server seen, waiting for Ack from client
++ * PARTOPEN: Ack after Response seen, waiting for packet other than Response,
++ * Reset or Sync from server
++ * OPEN: Packet other than Response, Reset or Sync seen
++ * CLOSEREQ: CloseReq from server seen, expecting Close from client
++ * CLOSING: Close seen, expecting Reset
++ * TIMEWAIT: Reset seen
++ * IGNORE: Not determinable whether packet is valid
++ *
++ * Some states exist only on one side of the connection: REQUEST, RESPOND,
++ * PARTOPEN, CLOSEREQ. For the other side these states are equivalent to
++ * the one it was in before.
++ *
++ * Packets are marked as ignored (sIG) if we don't know if they're valid
++ * (for example a reincarnation of a connection we didn't notice is dead
++ * already) and the server may send back a connection closing Reset or a
++ * Response. They're also used for Sync/SyncAck packets, which we don't
++ * care about.
++ */
++static const u_int8_t
++dccp_state_table[CT_DCCP_ROLE_MAX + 1][DCCP_PKT_SYNCACK + 1][CT_DCCP_MAX + 1] = {
++ [CT_DCCP_ROLE_CLIENT] = {
++ [DCCP_PKT_REQUEST] = {
++ /*
++ * sNO -> sRQ Regular Request
++ * sRQ -> sRQ Retransmitted Request or reincarnation
++ * sRS -> sRS Retransmitted Request (apparently Response
++ * got lost after we saw it) or reincarnation
++ * sPO -> sIG Ignore, conntrack might be out of sync
++ * sOP -> sIG Ignore, conntrack might be out of sync
++ * sCR -> sIG Ignore, conntrack might be out of sync
++ * sCG -> sIG Ignore, conntrack might be out of sync
++ * sTW -> sRQ Reincarnation
++ *
++ * sNO, sRQ, sRS, sPO. sOP, sCR, sCG, sTW, */
++ sRQ, sRQ, sRS, sIG, sIG, sIG, sIG, sRQ,
++ },
++ [DCCP_PKT_RESPONSE] = {
++ /*
++ * sNO -> sIV Invalid
++ * sRQ -> sIG Ignore, might be response to ignored Request
++ * sRS -> sIG Ignore, might be response to ignored Request
++ * sPO -> sIG Ignore, might be response to ignored Request
++ * sOP -> sIG Ignore, might be response to ignored Request
++ * sCR -> sIG Ignore, might be response to ignored Request
++ * sCG -> sIG Ignore, might be response to ignored Request
++ * sTW -> sIV Invalid, reincarnation in reverse direction
++ * goes through sRQ
++ *
++ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++ sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIV,
++ },
++ [DCCP_PKT_ACK] = {
++ /*
++ * sNO -> sIV No connection
++ * sRQ -> sIV No connection
++ * sRS -> sPO Ack for Response, move to PARTOPEN (8.1.5.)
++ * sPO -> sPO Retransmitted Ack for Response, remain in PARTOPEN
++ * sOP -> sOP Regular ACK, remain in OPEN
++ * sCR -> sCR Ack in CLOSEREQ MAY be processed (8.3.)
++ * sCG -> sCG Ack in CLOSING MAY be processed (8.3.)
++ * sTW -> sIV
++ *
++ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++ sIV, sIV, sPO, sPO, sOP, sCR, sCG, sIV
++ },
++ [DCCP_PKT_DATA] = {
++ /*
++ * sNO -> sIV No connection
++ * sRQ -> sIV No connection
++ * sRS -> sIV No connection
++ * sPO -> sIV MUST use DataAck in PARTOPEN state (8.1.5.)
++ * sOP -> sOP Regular Data packet
++ * sCR -> sCR Data in CLOSEREQ MAY be processed (8.3.)
++ * sCG -> sCG Data in CLOSING MAY be processed (8.3.)
++ * sTW -> sIV
++ *
++ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++ sIV, sIV, sIV, sIV, sOP, sCR, sCG, sIV,
++ },
++ [DCCP_PKT_DATAACK] = {
++ /*
++ * sNO -> sIV No connection
++ * sRQ -> sIV No connection
++ * sRS -> sPO Ack for Response, move to PARTOPEN (8.1.5.)
++ * sPO -> sPO Remain in PARTOPEN state
++ * sOP -> sOP Regular DataAck packet in OPEN state
++ * sCR -> sCR DataAck in CLOSEREQ MAY be processed (8.3.)
++ * sCG -> sCG DataAck in CLOSING MAY be processed (8.3.)
++ * sTW -> sIV
++ *
++ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++ sIV, sIV, sPO, sPO, sOP, sCR, sCG, sIV
++ },
++ [DCCP_PKT_CLOSEREQ] = {
++ /*
++ * CLOSEREQ may only be sent by the server.
++ *
++ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++ sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV
++ },
++ [DCCP_PKT_CLOSE] = {
++ /*
++ * sNO -> sIV No connection
++ * sRQ -> sIV No connection
++ * sRS -> sIV No connection
++ * sPO -> sCG Client-initiated close
++ * sOP -> sCG Client-initiated close
++ * sCR -> sCG Close in response to CloseReq (8.3.)
++ * sCG -> sCG Retransmit
++ * sTW -> sIV Late retransmit, already in TIME_WAIT
++ *
++ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++ sIV, sIV, sIV, sCG, sCG, sCG, sIV, sIV
++ },
++ [DCCP_PKT_RESET] = {
++ /*
++ * sNO -> sIV No connection
++ * sRQ -> sTW Sync received or timeout, SHOULD send Reset (8.1.1.)
++ * sRS -> sTW Response received without Request
++ * sPO -> sTW Timeout, SHOULD send Reset (8.1.5.)
++ * sOP -> sTW Connection reset
++ * sCR -> sTW Connection reset
++ * sCG -> sTW Connection reset
++ * sTW -> sIG Ignore (don't refresh timer)
++ *
++ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++ sIV, sTW, sTW, sTW, sTW, sTW, sTW, sIG
++ },
++ [DCCP_PKT_SYNC] = {
++ /*
++ * We currently ignore Sync packets
++ *
++ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++ sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG,
++ },
++ [DCCP_PKT_SYNCACK] = {
++ /*
++ * We currently ignore SyncAck packets
++ *
++ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++ sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG,
++ },
++ },
++ [CT_DCCP_ROLE_SERVER] = {
++ [DCCP_PKT_REQUEST] = {
++ /*
++ * sNO -> sIV Invalid
++ * sRQ -> sIG Ignore, conntrack might be out of sync
++ * sRS -> sIG Ignore, conntrack might be out of sync
++ * sPO -> sIG Ignore, conntrack might be out of sync
++ * sOP -> sIG Ignore, conntrack might be out of sync
++ * sCR -> sIG Ignore, conntrack might be out of sync
++ * sCG -> sIG Ignore, conntrack might be out of sync
++ * sTW -> sRQ Reincarnation, must reverse roles
++ *
++ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++ sIV, sIG, sIG, sIG, sIG, sIG, sIG, sRQ
++ },
++ [DCCP_PKT_RESPONSE] = {
++ /*
++ * sNO -> sIV Response without Request
++ * sRQ -> sRS Response to clients Request
++ * sRS -> sRS Retransmitted Response (8.1.3. SHOULD NOT)
++ * sPO -> sIG Response to an ignored Request or late retransmit
++ * sOP -> sIG Ignore, might be response to ignored Request
++ * sCR -> sIG Ignore, might be response to ignored Request
++ * sCG -> sIG Ignore, might be response to ignored Request
++ * sTW -> sIV Invalid, Request from client in sTW moves to sRQ
++ *
++ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++ sIV, sRS, sRS, sIG, sIG, sIG, sIG, sIV
++ },
++ [DCCP_PKT_ACK] = {
++ /*
++ * sNO -> sIV No connection
++ * sRQ -> sIV No connection
++ * sRS -> sIV No connection
++ * sPO -> sOP Enter OPEN state (8.1.5.)
++ * sOP -> sOP Regular Ack in OPEN state
++ * sCR -> sIV Waiting for Close from client
++ * sCG -> sCG Ack in CLOSING MAY be processed (8.3.)
++ * sTW -> sIV
++ *
++ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++ sIV, sIV, sIV, sOP, sOP, sIV, sCG, sIV
++ },
++ [DCCP_PKT_DATA] = {
++ /*
++ * sNO -> sIV No connection
++ * sRQ -> sIV No connection
++ * sRS -> sIV No connection
++ * sPO -> sOP Enter OPEN state (8.1.5.)
++ * sOP -> sOP Regular Data packet in OPEN state
++ * sCR -> sIV Waiting for Close from client
++ * sCG -> sCG Data in CLOSING MAY be processed (8.3.)
++ * sTW -> sIV
++ *
++ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++ sIV, sIV, sIV, sOP, sOP, sIV, sCG, sIV
++ },
++ [DCCP_PKT_DATAACK] = {
++ /*
++ * sNO -> sIV No connection
++ * sRQ -> sIV No connection
++ * sRS -> sIV No connection
++ * sPO -> sOP Enter OPEN state (8.1.5.)
++ * sOP -> sOP Regular DataAck in OPEN state
++ * sCR -> sIV Waiting for Close from client
++ * sCG -> sCG Data in CLOSING MAY be processed (8.3.)
++ * sTW -> sIV
++ *
++ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++ sIV, sIV, sIV, sOP, sOP, sIV, sCG, sIV
++ },
++ [DCCP_PKT_CLOSEREQ] = {
++ /*
++ * sNO -> sIV No connection
++ * sRQ -> sIV No connection
++ * sRS -> sIV No connection
++ * sPO -> sOP -> sCR Move directly to CLOSEREQ (8.1.5.)
++ * sOP -> sCR CloseReq in OPEN state
++ * sCR -> sCR Retransmit
++ * sCG -> sCR Simultaneous close, client sends another Close
++ * sTW -> sIV Already closed
++ *
++ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++ sIV, sIV, sIV, sCR, sCR, sCR, sCR, sIV
++ },
++ [DCCP_PKT_CLOSE] = {
++ /*
++ * sNO -> sIV No connection
++ * sRQ -> sIV No connection
++ * sRS -> sIV No connection
++ * sPO -> sOP -> sCG Move direcly to CLOSING
++ * sOP -> sCG Move to CLOSING
++ * sCR -> sIV Close after CloseReq is invalid
++ * sCG -> sCG Retransmit
++ * sTW -> sIV Already closed
++ *
++ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++ sIV, sIV, sIV, sCG, sCG, sIV, sCG, sIV
++ },
++ [DCCP_PKT_RESET] = {
++ /*
++ * sNO -> sIV No connection
++ * sRQ -> sTW Reset in response to Request
++ * sRS -> sTW Timeout, SHOULD send Reset (8.1.3.)
++ * sPO -> sTW Timeout, SHOULD send Reset (8.1.3.)
++ * sOP -> sTW
++ * sCR -> sTW
++ * sCG -> sTW
++ * sTW -> sIG Ignore (don't refresh timer)
++ *
++ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW, sTW */
++ sIV, sTW, sTW, sTW, sTW, sTW, sTW, sTW, sIG
++ },
++ [DCCP_PKT_SYNC] = {
++ /*
++ * We currently ignore Sync packets
++ *
++ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++ sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG,
++ },
++ [DCCP_PKT_SYNCACK] = {
++ /*
++ * We currently ignore SyncAck packets
++ *
++ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
++ sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG,
++ },
++ },
++};
++
++static bool dccp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
++ struct nf_conntrack_tuple *tuple)
++{
++ struct dccp_hdr _hdr, *dh;
++
++ dh = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
++ if (dh == NULL)
++ return false;
++
++ tuple->src.u.dccp.port = dh->dccph_sport;
++ tuple->dst.u.dccp.port = dh->dccph_dport;
++ return true;
++}
++
++static bool dccp_invert_tuple(struct nf_conntrack_tuple *inv,
++ const struct nf_conntrack_tuple *tuple)
++{
++ inv->src.u.dccp.port = tuple->dst.u.dccp.port;
++ inv->dst.u.dccp.port = tuple->src.u.dccp.port;
++ return true;
++}
++
++static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb,
++ unsigned int dataoff)
++{
++ struct dccp_hdr _dh, *dh;
++ const char *msg;
++ u_int8_t state;
++
++ dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh);
++ BUG_ON(dh == NULL);
++
++ state = dccp_state_table[CT_DCCP_ROLE_CLIENT][dh->dccph_type][CT_DCCP_NONE];
++ switch (state) {
++ default:
++ if (nf_ct_dccp_loose == 0) {
++ msg = "nf_ct_dccp: not picking up existing connection ";
++ goto out_invalid;
++ }
++ case CT_DCCP_REQUEST:
++ break;
++ case CT_DCCP_INVALID:
++ msg = "nf_ct_dccp: invalid state transition ";
++ goto out_invalid;
++ }
++
++ ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_CLIENT;
++ ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_SERVER;
++ ct->proto.dccp.state = CT_DCCP_NONE;
++ return true;
++
++out_invalid:
++ if (LOG_INVALID(IPPROTO_DCCP))
++ nf_log_packet(nf_ct_l3num(ct), 0, skb, NULL, NULL, NULL, msg);
++ return false;
++}
++
++static u64 dccp_ack_seq(const struct dccp_hdr *dh)
++{
++ const struct dccp_hdr_ack_bits *dhack;
++
++ dhack = (void *)dh + __dccp_basic_hdr_len(dh);
++ return ((u64)ntohs(dhack->dccph_ack_nr_high) << 32) +
++ ntohl(dhack->dccph_ack_nr_low);
++}
++
++static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
++ unsigned int dataoff, enum ip_conntrack_info ctinfo,
++ int pf, unsigned int hooknum)
++{
++ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
++ struct dccp_hdr _dh, *dh;
++ u_int8_t type, old_state, new_state;
++ enum ct_dccp_roles role;
++
++ dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh);
++ BUG_ON(dh == NULL);
++ type = dh->dccph_type;
++
++ if (type == DCCP_PKT_RESET &&
++ !test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
++ /* Tear down connection immediately if only reply is a RESET */
++ if (del_timer(&ct->timeout))
++ ct->timeout.function((unsigned long)ct);
++ return NF_ACCEPT;
++ }
++
++ write_lock_bh(&dccp_lock);
++
++ role = ct->proto.dccp.role[dir];
++ old_state = ct->proto.dccp.state;
++ new_state = dccp_state_table[role][type][old_state];
++
++ switch (new_state) {
++ case CT_DCCP_REQUEST:
++ if (old_state == CT_DCCP_TIMEWAIT &&
++ role == CT_DCCP_ROLE_SERVER) {
++ /* Reincarnation in the reverse direction: reopen and
++ * reverse client/server roles. */
++ ct->proto.dccp.role[dir] = CT_DCCP_ROLE_CLIENT;
++ ct->proto.dccp.role[!dir] = CT_DCCP_ROLE_SERVER;
++ }
++ break;
++ case CT_DCCP_RESPOND:
++ if (old_state == CT_DCCP_REQUEST)
++ ct->proto.dccp.handshake_seq = dccp_hdr_seq(dh);
++ break;
++ case CT_DCCP_PARTOPEN:
++ if (old_state == CT_DCCP_RESPOND &&
++ type == DCCP_PKT_ACK &&
++ dccp_ack_seq(dh) == ct->proto.dccp.handshake_seq)
++ set_bit(IPS_ASSURED_BIT, &ct->status);
++ break;
++ case CT_DCCP_IGNORE:
++ /*
++ * Connection tracking might be out of sync, so we ignore
++ * packets that might establish a new connection and resync
++ * if the server responds with a valid Response.
++ */
++ if (ct->proto.dccp.last_dir == !dir &&
++ ct->proto.dccp.last_pkt == DCCP_PKT_REQUEST &&
++ type == DCCP_PKT_RESPONSE) {
++ ct->proto.dccp.role[!dir] = CT_DCCP_ROLE_CLIENT;
++ ct->proto.dccp.role[dir] = CT_DCCP_ROLE_SERVER;
++ ct->proto.dccp.handshake_seq = dccp_hdr_seq(dh);
++ new_state = CT_DCCP_RESPOND;
++ break;
++ }
++ ct->proto.dccp.last_dir = dir;
++ ct->proto.dccp.last_pkt = type;
++
++ write_unlock_bh(&dccp_lock);
++ if (LOG_INVALID(IPPROTO_DCCP))
++ nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
++ "nf_ct_dccp: invalid packet ignored ");
++ return NF_ACCEPT;
++ case CT_DCCP_INVALID:
++ write_unlock_bh(&dccp_lock);
++ if (LOG_INVALID(IPPROTO_DCCP))
++ nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
++ "nf_ct_dccp: invalid state transition ");
++ return -NF_ACCEPT;
++ }
++
++ ct->proto.dccp.last_dir = dir;
++ ct->proto.dccp.last_pkt = type;
++ ct->proto.dccp.state = new_state;
++ write_unlock_bh(&dccp_lock);
++ nf_ct_refresh_acct(ct, ctinfo, skb, dccp_timeout[new_state]);
++
++ return NF_ACCEPT;
++}
++
++static int dccp_error(struct sk_buff *skb, unsigned int dataoff,
++ enum ip_conntrack_info *ctinfo, int pf,
++ unsigned int hooknum)
++{
++ struct dccp_hdr _dh, *dh;
++ unsigned int dccp_len = skb->len - dataoff;
++ unsigned int cscov;
++ const char *msg;
++
++ dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh);
++ if (dh == NULL) {
++ msg = "nf_ct_dccp: short packet ";
++ goto out_invalid;
++ }
++
++ if (dh->dccph_doff * 4 < sizeof(struct dccp_hdr) ||
++ dh->dccph_doff * 4 > dccp_len) {
++ msg = "nf_ct_dccp: truncated/malformed packet ";
++ goto out_invalid;
++ }
++
++ cscov = dccp_len;
++ if (dh->dccph_cscov) {
++ cscov = (dh->dccph_cscov - 1) * 4;
++ if (cscov > dccp_len) {
++ msg = "nf_ct_dccp: bad checksum coverage ";
++ goto out_invalid;
++ }
++ }
++
++ if (nf_conntrack_checksum && hooknum == NF_INET_PRE_ROUTING &&
++ nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_DCCP,
++ pf)) {
++ msg = "nf_ct_dccp: bad checksum ";
++ goto out_invalid;
++ }
++
++ if (dh->dccph_type >= DCCP_PKT_INVALID) {
++ msg = "nf_ct_dccp: reserved packet type ";
++ goto out_invalid;
++ }
++
++ return NF_ACCEPT;
++
++out_invalid:
++ if (LOG_INVALID(IPPROTO_DCCP))
++ nf_log_packet(pf, 0, skb, NULL, NULL, NULL, msg);
++ return -NF_ACCEPT;
++}
++
++static int dccp_print_tuple(struct seq_file *s,
++ const struct nf_conntrack_tuple *tuple)
++{
++ return seq_printf(s, "sport=%hu dport=%hu ",
++ ntohs(tuple->src.u.dccp.port),
++ ntohs(tuple->dst.u.dccp.port));
++}
++
++static int dccp_print_conntrack(struct seq_file *s, const struct nf_conn *ct)
++{
++ return seq_printf(s, "%s ", dccp_state_names[ct->proto.dccp.state]);
++}
++
++#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
++static int dccp_to_nlattr(struct sk_buff *skb, struct nlattr *nla,
++ const struct nf_conn *ct)
++{
++ struct nlattr *nest_parms;
++
++ read_lock_bh(&dccp_lock);
++ nest_parms = nla_nest_start(skb, CTA_PROTOINFO_DCCP | NLA_F_NESTED);
++ if (!nest_parms)
++ goto nla_put_failure;
++ NLA_PUT_U8(skb, CTA_PROTOINFO_DCCP_STATE, ct->proto.dccp.state);
++ nla_nest_end(skb, nest_parms);
++ read_unlock_bh(&dccp_lock);
++ return 0;
++
++nla_put_failure:
++ read_unlock_bh(&dccp_lock);
++ return -1;
++}
++
++static const struct nla_policy dccp_nla_policy[CTA_PROTOINFO_DCCP_MAX + 1] = {
++ [CTA_PROTOINFO_DCCP_STATE] = { .type = NLA_U8 },
++};
++
++static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct)
++{
++ struct nlattr *attr = cda[CTA_PROTOINFO_DCCP];
++ struct nlattr *tb[CTA_PROTOINFO_DCCP_MAX + 1];
++ int err;
++
++ if (!attr)
++ return 0;
++
++ err = nla_parse_nested(tb, CTA_PROTOINFO_DCCP_MAX, attr,
++ dccp_nla_policy);
++ if (err < 0)
++ return err;
++
++ if (!tb[CTA_PROTOINFO_DCCP_STATE] ||
++ nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]) >= CT_DCCP_IGNORE)
++ return -EINVAL;
++
++ write_lock_bh(&dccp_lock);
++ ct->proto.dccp.state = nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]);
++ write_unlock_bh(&dccp_lock);
++ return 0;
++}
++#endif
++
++#ifdef CONFIG_SYSCTL
++static unsigned int dccp_sysctl_table_users;
++static struct ctl_table_header *dccp_sysctl_header;
++static ctl_table dccp_sysctl_table[] = {
++ {
++ .ctl_name = CTL_UNNUMBERED,
++ .procname = "nf_conntrack_dccp_timeout_request",
++ .data = &dccp_timeout[CT_DCCP_REQUEST],
++ .maxlen = sizeof(unsigned int),
++ .mode = 0644,
++ .proc_handler = proc_dointvec_jiffies,
++ },
++ {
++ .ctl_name = CTL_UNNUMBERED,
++ .procname = "nf_conntrack_dccp_timeout_respond",
++ .data = &dccp_timeout[CT_DCCP_RESPOND],
++ .maxlen = sizeof(unsigned int),
++ .mode = 0644,
++ .proc_handler = proc_dointvec_jiffies,
++ },
++ {
++ .ctl_name = CTL_UNNUMBERED,
++ .procname = "nf_conntrack_dccp_timeout_partopen",
++ .data = &dccp_timeout[CT_DCCP_PARTOPEN],
++ .maxlen = sizeof(unsigned int),
++ .mode = 0644,
++ .proc_handler = proc_dointvec_jiffies,
++ },
++ {
++ .ctl_name = CTL_UNNUMBERED,
++ .procname = "nf_conntrack_dccp_timeout_open",
++ .data = &dccp_timeout[CT_DCCP_OPEN],
++ .maxlen = sizeof(unsigned int),
++ .mode = 0644,
++ .proc_handler = proc_dointvec_jiffies,
++ },
++ {
++ .ctl_name = CTL_UNNUMBERED,
++ .procname = "nf_conntrack_dccp_timeout_closereq",
++ .data = &dccp_timeout[CT_DCCP_CLOSEREQ],
++ .maxlen = sizeof(unsigned int),
++ .mode = 0644,
++ .proc_handler = proc_dointvec_jiffies,
++ },
++ {
++ .ctl_name = CTL_UNNUMBERED,
++ .procname = "nf_conntrack_dccp_timeout_closing",
++ .data = &dccp_timeout[CT_DCCP_CLOSING],
++ .maxlen = sizeof(unsigned int),
++ .mode = 0644,
++ .proc_handler = proc_dointvec_jiffies,
++ },
++ {
++ .ctl_name = CTL_UNNUMBERED,
++ .procname = "nf_conntrack_dccp_timeout_timewait",
++ .data = &dccp_timeout[CT_DCCP_TIMEWAIT],
++ .maxlen = sizeof(unsigned int),
++ .mode = 0644,
++ .proc_handler = proc_dointvec_jiffies,
++ },
++ {
++ .ctl_name = CTL_UNNUMBERED,
++ .procname = "nf_conntrack_dccp_loose",
++ .data = &nf_ct_dccp_loose,
++ .maxlen = sizeof(nf_ct_dccp_loose),
++ .mode = 0644,
++ .proc_handler = proc_dointvec,
++ },
++ {
++ .ctl_name = 0,
++ }
++};
++#endif /* CONFIG_SYSCTL */
++
++static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = {
++ .l3proto = AF_INET,
++ .l4proto = IPPROTO_DCCP,
++ .name = "dccp",
++ .pkt_to_tuple = dccp_pkt_to_tuple,
++ .invert_tuple = dccp_invert_tuple,
++ .new = dccp_new,
++ .packet = dccp_packet,
++ .error = dccp_error,
++ .print_tuple = dccp_print_tuple,
++ .print_conntrack = dccp_print_conntrack,
++#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
++ .to_nlattr = dccp_to_nlattr,
++ .from_nlattr = nlattr_to_dccp,
++ .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
++ .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
++ .nla_policy = nf_ct_port_nla_policy,
++#endif
++#ifdef CONFIG_SYSCTL
++ .ctl_table_users = &dccp_sysctl_table_users,
++ .ctl_table_header = &dccp_sysctl_header,
++ .ctl_table = dccp_sysctl_table,
++#endif
++};
++
++static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = {
++ .l3proto = AF_INET6,
++ .l4proto = IPPROTO_DCCP,
++ .name = "dccp",
++ .pkt_to_tuple = dccp_pkt_to_tuple,
++ .invert_tuple = dccp_invert_tuple,
++ .new = dccp_new,
++ .packet = dccp_packet,
++ .error = dccp_error,
++ .print_tuple = dccp_print_tuple,
++ .print_conntrack = dccp_print_conntrack,
++#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
++ .to_nlattr = dccp_to_nlattr,
++ .from_nlattr = nlattr_to_dccp,
++ .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
++ .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
++ .nla_policy = nf_ct_port_nla_policy,
++#endif
++#ifdef CONFIG_SYSCTL
++ .ctl_table_users = &dccp_sysctl_table_users,
++ .ctl_table_header = &dccp_sysctl_header,
++ .ctl_table = dccp_sysctl_table,
++#endif
++};
++
++static int __init nf_conntrack_proto_dccp_init(void)
++{
++ int err;
++
++ err = nf_conntrack_l4proto_register(&dccp_proto4);
++ if (err < 0)
++ goto err1;
++
++ err = nf_conntrack_l4proto_register(&dccp_proto6);
++ if (err < 0)
++ goto err2;
++ return 0;
++
++err2:
++ nf_conntrack_l4proto_unregister(&dccp_proto4);
++err1:
++ return err;
++}
++
++static void __exit nf_conntrack_proto_dccp_fini(void)
++{
++ nf_conntrack_l4proto_unregister(&dccp_proto6);
++ nf_conntrack_l4proto_unregister(&dccp_proto4);
++}
++
++module_init(nf_conntrack_proto_dccp_init);
++module_exit(nf_conntrack_proto_dccp_fini);
++
++MODULE_AUTHOR("Patrick McHardy <kaber at trash.net>");
++MODULE_DESCRIPTION("DCCP connection tracking protocol helper");
++MODULE_LICENSE("GPL");
+diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c
+index 5545891..e31b0e7 100644
+--- a/net/netfilter/nf_conntrack_proto_generic.c
++++ b/net/netfilter/nf_conntrack_proto_generic.c
+@@ -14,23 +14,23 @@
+
+ static unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ;
+
+-static int generic_pkt_to_tuple(const struct sk_buff *skb,
+- unsigned int dataoff,
+- struct nf_conntrack_tuple *tuple)
++static bool generic_pkt_to_tuple(const struct sk_buff *skb,
++ unsigned int dataoff,
++ struct nf_conntrack_tuple *tuple)
+ {
+ tuple->src.u.all = 0;
+ tuple->dst.u.all = 0;
+
+- return 1;
++ return true;
+ }
+
+-static int generic_invert_tuple(struct nf_conntrack_tuple *tuple,
+- const struct nf_conntrack_tuple *orig)
++static bool generic_invert_tuple(struct nf_conntrack_tuple *tuple,
++ const struct nf_conntrack_tuple *orig)
+ {
+ tuple->src.u.all = 0;
+ tuple->dst.u.all = 0;
+
+- return 1;
++ return true;
+ }
+
+ /* Print out the per-protocol part of the tuple. */
+@@ -53,10 +53,10 @@ static int packet(struct nf_conn *ct,
+ }
+
+ /* Called when a new connection for this protocol found. */
+-static int new(struct nf_conn *ct, const struct sk_buff *skb,
+- unsigned int dataoff)
++static bool new(struct nf_conn *ct, const struct sk_buff *skb,
++ unsigned int dataoff)
+ {
+- return 1;
++ return true;
+ }
+
+ #ifdef CONFIG_SYSCTL
+diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c
+index e10024a..654a4f7 100644
+--- a/net/netfilter/nf_conntrack_proto_gre.c
++++ b/net/netfilter/nf_conntrack_proto_gre.c
+@@ -82,7 +82,7 @@ static __be16 gre_keymap_lookup(struct nf_conntrack_tuple *t)
+ read_unlock_bh(&nf_ct_gre_lock);
+
+ pr_debug("lookup src key 0x%x for ", key);
+- NF_CT_DUMP_TUPLE(t);
++ nf_ct_dump_tuple(t);
+
+ return key;
+ }
+@@ -113,7 +113,7 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
+ *kmp = km;
+
+ pr_debug("adding new entry %p: ", km);
+- NF_CT_DUMP_TUPLE(&km->tuple);
++ nf_ct_dump_tuple(&km->tuple);
+
+ write_lock_bh(&nf_ct_gre_lock);
+ list_add_tail(&km->list, &gre_keymap_list);
+@@ -148,18 +148,17 @@ EXPORT_SYMBOL_GPL(nf_ct_gre_keymap_destroy);
+ /* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */
+
+ /* invert gre part of tuple */
+-static int gre_invert_tuple(struct nf_conntrack_tuple *tuple,
+- const struct nf_conntrack_tuple *orig)
++static bool gre_invert_tuple(struct nf_conntrack_tuple *tuple,
++ const struct nf_conntrack_tuple *orig)
+ {
+ tuple->dst.u.gre.key = orig->src.u.gre.key;
+ tuple->src.u.gre.key = orig->dst.u.gre.key;
+- return 1;
++ return true;
+ }
+
+ /* gre hdr info to tuple */
+-static int gre_pkt_to_tuple(const struct sk_buff *skb,
+- unsigned int dataoff,
+- struct nf_conntrack_tuple *tuple)
++static bool gre_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
++ struct nf_conntrack_tuple *tuple)
+ {
+ const struct gre_hdr_pptp *pgrehdr;
+ struct gre_hdr_pptp _pgrehdr;
+@@ -173,24 +172,24 @@ static int gre_pkt_to_tuple(const struct sk_buff *skb,
+ /* try to behave like "nf_conntrack_proto_generic" */
+ tuple->src.u.all = 0;
+ tuple->dst.u.all = 0;
+- return 1;
++ return true;
+ }
+
+ /* PPTP header is variable length, only need up to the call_id field */
+ pgrehdr = skb_header_pointer(skb, dataoff, 8, &_pgrehdr);
+ if (!pgrehdr)
+- return 1;
++ return true;
+
+ if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) {
+ pr_debug("GRE_VERSION_PPTP but unknown proto\n");
+- return 0;
++ return false;
+ }
+
+ tuple->dst.u.gre.key = pgrehdr->call_id;
+ srckey = gre_keymap_lookup(tuple);
+ tuple->src.u.gre.key = srckey;
+
+- return 1;
++ return true;
+ }
+
+ /* print gre part of tuple */
+@@ -235,18 +234,18 @@ static int gre_packet(struct nf_conn *ct,
+ }
+
+ /* Called when a new connection for this protocol found. */
+-static int gre_new(struct nf_conn *ct, const struct sk_buff *skb,
+- unsigned int dataoff)
++static bool gre_new(struct nf_conn *ct, const struct sk_buff *skb,
++ unsigned int dataoff)
+ {
+ pr_debug(": ");
+- NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
++ nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+
+ /* initialize to sane value. Ideally a conntrack helper
+ * (e.g. in case of pptp) is increasing them */
+ ct->proto.gre.stream_timeout = GRE_STREAM_TIMEOUT;
+ ct->proto.gre.timeout = GRE_TIMEOUT;
+
+- return 1;
++ return true;
+ }
+
+ /* Called when a conntrack entry has already been removed from the hashes
+diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
+index f9a0837..cbf2e27 100644
+--- a/net/netfilter/nf_conntrack_proto_sctp.c
++++ b/net/netfilter/nf_conntrack_proto_sctp.c
+@@ -33,7 +33,7 @@ static DEFINE_RWLOCK(sctp_lock);
+
+ And so for me for SCTP :D -Kiran */
+
+-static const char *sctp_conntrack_names[] = {
++static const char *const sctp_conntrack_names[] = {
+ "NONE",
+ "CLOSED",
+ "COOKIE_WAIT",
+@@ -130,28 +130,28 @@ static const u8 sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
+ }
+ };
+
+-static int sctp_pkt_to_tuple(const struct sk_buff *skb,
+- unsigned int dataoff,
+- struct nf_conntrack_tuple *tuple)
++static bool sctp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
++ struct nf_conntrack_tuple *tuple)
+ {
+- sctp_sctphdr_t _hdr, *hp;
++ const struct sctphdr *hp;
++ struct sctphdr _hdr;
+
+ /* Actually only need first 8 bytes. */
+ hp = skb_header_pointer(skb, dataoff, 8, &_hdr);
+ if (hp == NULL)
+- return 0;
++ return false;
+
+ tuple->src.u.sctp.port = hp->source;
+ tuple->dst.u.sctp.port = hp->dest;
+- return 1;
++ return true;
+ }
+
+-static int sctp_invert_tuple(struct nf_conntrack_tuple *tuple,
+- const struct nf_conntrack_tuple *orig)
++static bool sctp_invert_tuple(struct nf_conntrack_tuple *tuple,
++ const struct nf_conntrack_tuple *orig)
+ {
+ tuple->src.u.sctp.port = orig->dst.u.sctp.port;
+ tuple->dst.u.sctp.port = orig->src.u.sctp.port;
+- return 1;
++ return true;
+ }
+
+ /* Print out the per-protocol part of the tuple. */
+@@ -292,8 +292,10 @@ static int sctp_packet(struct nf_conn *ct,
+ {
+ enum sctp_conntrack new_state, old_state;
+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+- sctp_sctphdr_t _sctph, *sh;
+- sctp_chunkhdr_t _sch, *sch;
++ const struct sctphdr *sh;
++ struct sctphdr _sctph;
++ const struct sctp_chunkhdr *sch;
++ struct sctp_chunkhdr _sch;
+ u_int32_t offset, count;
+ unsigned long map[256 / sizeof(unsigned long)] = { 0 };
+
+@@ -390,27 +392,29 @@ out:
+ }
+
+ /* Called when a new connection for this protocol found. */
+-static int sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
+- unsigned int dataoff)
++static bool sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
++ unsigned int dataoff)
+ {
+ enum sctp_conntrack new_state;
+- sctp_sctphdr_t _sctph, *sh;
+- sctp_chunkhdr_t _sch, *sch;
++ const struct sctphdr *sh;
++ struct sctphdr _sctph;
++ const struct sctp_chunkhdr *sch;
++ struct sctp_chunkhdr _sch;
+ u_int32_t offset, count;
+ unsigned long map[256 / sizeof(unsigned long)] = { 0 };
+
+ sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph);
+ if (sh == NULL)
+- return 0;
++ return false;
+
+ if (do_basic_checks(ct, skb, dataoff, map) != 0)
+- return 0;
++ return false;
+
+ /* If an OOTB packet has any of these chunks discard (Sec 8.4) */
+ if (test_bit(SCTP_CID_ABORT, map) ||
+ test_bit(SCTP_CID_SHUTDOWN_COMPLETE, map) ||
+ test_bit(SCTP_CID_COOKIE_ACK, map))
+- return 0;
++ return false;
+
+ new_state = SCTP_CONNTRACK_MAX;
+ for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
+@@ -422,7 +426,7 @@ static int sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
+ if (new_state == SCTP_CONNTRACK_NONE ||
+ new_state == SCTP_CONNTRACK_MAX) {
+ pr_debug("nf_conntrack_sctp: invalid new deleting.\n");
+- return 0;
++ return false;
+ }
+
+ /* Copy the vtag into the state info */
+@@ -433,7 +437,7 @@ static int sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
+ ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t),
+ sizeof(_inithdr), &_inithdr);
+ if (ih == NULL)
+- return 0;
++ return false;
+
+ pr_debug("Setting vtag %x for new conn\n",
+ ih->init_tag);
+@@ -442,7 +446,7 @@ static int sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
+ ih->init_tag;
+ } else {
+ /* Sec 8.5.1 (A) */
+- return 0;
++ return false;
+ }
+ }
+ /* If it is a shutdown ack OOTB packet, we expect a return
+@@ -456,7 +460,7 @@ static int sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
+ ct->proto.sctp.state = new_state;
+ }
+
+- return 1;
++ return true;
+ }
+
+ #ifdef CONFIG_SYSCTL
+diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
+index 6256795..ba94004 100644
+--- a/net/netfilter/nf_conntrack_proto_tcp.c
++++ b/net/netfilter/nf_conntrack_proto_tcp.c
+@@ -257,9 +257,8 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
+ }
+ };
+
+-static int tcp_pkt_to_tuple(const struct sk_buff *skb,
+- unsigned int dataoff,
+- struct nf_conntrack_tuple *tuple)
++static bool tcp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
++ struct nf_conntrack_tuple *tuple)
+ {
+ const struct tcphdr *hp;
+ struct tcphdr _hdr;
+@@ -267,20 +266,20 @@ static int tcp_pkt_to_tuple(const struct sk_buff *skb,
+ /* Actually only need first 8 bytes. */
+ hp = skb_header_pointer(skb, dataoff, 8, &_hdr);
+ if (hp == NULL)
+- return 0;
++ return false;
+
+ tuple->src.u.tcp.port = hp->source;
+ tuple->dst.u.tcp.port = hp->dest;
+
+- return 1;
++ return true;
+ }
+
+-static int tcp_invert_tuple(struct nf_conntrack_tuple *tuple,
+- const struct nf_conntrack_tuple *orig)
++static bool tcp_invert_tuple(struct nf_conntrack_tuple *tuple,
++ const struct nf_conntrack_tuple *orig)
+ {
+ tuple->src.u.tcp.port = orig->dst.u.tcp.port;
+ tuple->dst.u.tcp.port = orig->src.u.tcp.port;
+- return 1;
++ return true;
+ }
+
+ /* Print out the per-protocol part of the tuple. */
+@@ -478,20 +477,20 @@ static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff,
+ }
+ }
+
+-static int tcp_in_window(const struct nf_conn *ct,
+- struct ip_ct_tcp *state,
+- enum ip_conntrack_dir dir,
+- unsigned int index,
+- const struct sk_buff *skb,
+- unsigned int dataoff,
+- const struct tcphdr *tcph,
+- int pf)
++static bool tcp_in_window(const struct nf_conn *ct,
++ struct ip_ct_tcp *state,
++ enum ip_conntrack_dir dir,
++ unsigned int index,
++ const struct sk_buff *skb,
++ unsigned int dataoff,
++ const struct tcphdr *tcph,
++ int pf)
+ {
+ struct ip_ct_tcp_state *sender = &state->seen[dir];
+ struct ip_ct_tcp_state *receiver = &state->seen[!dir];
+ const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple;
+ __u32 seq, ack, sack, end, win, swin;
+- int res;
++ bool res;
+
+ /*
+ * Get the required data from the packet.
+@@ -506,7 +505,7 @@ static int tcp_in_window(const struct nf_conn *ct,
+
+ pr_debug("tcp_in_window: START\n");
+ pr_debug("tcp_in_window: ");
+- NF_CT_DUMP_TUPLE(tuple);
++ nf_ct_dump_tuple(tuple);
+ pr_debug("seq=%u ack=%u sack=%u win=%u end=%u\n",
+ seq, ack, sack, win, end);
+ pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
+@@ -593,7 +592,7 @@ static int tcp_in_window(const struct nf_conn *ct,
+ seq = end = sender->td_end;
+
+ pr_debug("tcp_in_window: ");
+- NF_CT_DUMP_TUPLE(tuple);
++ nf_ct_dump_tuple(tuple);
+ pr_debug("seq=%u ack=%u sack =%u win=%u end=%u\n",
+ seq, ack, sack, win, end);
+ pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
+@@ -657,12 +656,12 @@ static int tcp_in_window(const struct nf_conn *ct,
+ state->retrans = 0;
+ }
+ }
+- res = 1;
++ res = true;
+ } else {
+- res = 0;
++ res = false;
+ if (sender->flags & IP_CT_TCP_FLAG_BE_LIBERAL ||
+ nf_ct_tcp_be_liberal)
+- res = 1;
++ res = true;
+ if (!res && LOG_INVALID(IPPROTO_TCP))
+ nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
+ "nf_ct_tcp: %s ",
+@@ -676,7 +675,7 @@ static int tcp_in_window(const struct nf_conn *ct,
+ : "SEQ is over the upper bound (over the window of the receiver)");
+ }
+
+- pr_debug("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u "
++ pr_debug("tcp_in_window: res=%u sender end=%u maxend=%u maxwin=%u "
+ "receiver end=%u maxend=%u maxwin=%u\n",
+ res, sender->td_end, sender->td_maxend, sender->td_maxwin,
+ receiver->td_end, receiver->td_maxend, receiver->td_maxwin);
+@@ -937,7 +936,7 @@ static int tcp_packet(struct nf_conn *ct,
+ ct->proto.tcp.last_dir = dir;
+
+ pr_debug("tcp_conntracks: ");
+- NF_CT_DUMP_TUPLE(tuple);
++ nf_ct_dump_tuple(tuple);
+ pr_debug("syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n",
+ (th->syn ? 1 : 0), (th->ack ? 1 : 0),
+ (th->fin ? 1 : 0), (th->rst ? 1 : 0),
+@@ -982,9 +981,8 @@ static int tcp_packet(struct nf_conn *ct,
+ }
+
+ /* Called when a new connection for this protocol found. */
+-static int tcp_new(struct nf_conn *ct,
+- const struct sk_buff *skb,
+- unsigned int dataoff)
++static bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb,
++ unsigned int dataoff)
+ {
+ enum tcp_conntrack new_state;
+ const struct tcphdr *th;
+@@ -1003,7 +1001,7 @@ static int tcp_new(struct nf_conn *ct,
+ /* Invalid: delete conntrack */
+ if (new_state >= TCP_CONNTRACK_MAX) {
+ pr_debug("nf_ct_tcp: invalid new deleting.\n");
+- return 0;
++ return false;
+ }
+
+ if (new_state == TCP_CONNTRACK_SYN_SENT) {
+@@ -1021,7 +1019,7 @@ static int tcp_new(struct nf_conn *ct,
+ ct->proto.tcp.seen[1].flags = 0;
+ } else if (nf_ct_tcp_loose == 0) {
+ /* Don't try to pick up connections. */
+- return 0;
++ return false;
+ } else {
+ /*
+ * We are in the middle of a connection,
+@@ -1061,7 +1059,7 @@ static int tcp_new(struct nf_conn *ct,
+ sender->td_scale,
+ receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
+ receiver->td_scale);
+- return 1;
++ return true;
+ }
+
+ #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+@@ -1129,11 +1127,13 @@ static int nlattr_to_tcp(struct nlattr *cda[], struct nf_conn *ct)
+ if (err < 0)
+ return err;
+
+- if (!tb[CTA_PROTOINFO_TCP_STATE])
++ if (tb[CTA_PROTOINFO_TCP_STATE] &&
++ nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]) >= TCP_CONNTRACK_MAX)
+ return -EINVAL;
+
+ write_lock_bh(&tcp_lock);
+- ct->proto.tcp.state = nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]);
++ if (tb[CTA_PROTOINFO_TCP_STATE])
++ ct->proto.tcp.state = nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]);
+
+ if (tb[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL]) {
+ struct nf_ct_tcp_flags *attr =
+diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
+index b8a35cc..8b21762 100644
+--- a/net/netfilter/nf_conntrack_proto_udp.c
++++ b/net/netfilter/nf_conntrack_proto_udp.c
+@@ -26,7 +26,7 @@
+ static unsigned int nf_ct_udp_timeout __read_mostly = 30*HZ;
+ static unsigned int nf_ct_udp_timeout_stream __read_mostly = 180*HZ;
+
+-static int udp_pkt_to_tuple(const struct sk_buff *skb,
++static bool udp_pkt_to_tuple(const struct sk_buff *skb,
+ unsigned int dataoff,
+ struct nf_conntrack_tuple *tuple)
+ {
+@@ -36,20 +36,20 @@ static int udp_pkt_to_tuple(const struct sk_buff *skb,
+ /* Actually only need first 8 bytes. */
+ hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
+ if (hp == NULL)
+- return 0;
++ return false;
+
+ tuple->src.u.udp.port = hp->source;
+ tuple->dst.u.udp.port = hp->dest;
+
+- return 1;
++ return true;
+ }
+
+-static int udp_invert_tuple(struct nf_conntrack_tuple *tuple,
+- const struct nf_conntrack_tuple *orig)
++static bool udp_invert_tuple(struct nf_conntrack_tuple *tuple,
++ const struct nf_conntrack_tuple *orig)
+ {
+ tuple->src.u.udp.port = orig->dst.u.udp.port;
+ tuple->dst.u.udp.port = orig->src.u.udp.port;
+- return 1;
++ return true;
+ }
+
+ /* Print out the per-protocol part of the tuple. */
+@@ -83,10 +83,10 @@ static int udp_packet(struct nf_conn *ct,
+ }
+
+ /* Called when a new connection for this protocol found. */
+-static int udp_new(struct nf_conn *ct, const struct sk_buff *skb,
+- unsigned int dataoff)
++static bool udp_new(struct nf_conn *ct, const struct sk_buff *skb,
++ unsigned int dataoff)
+ {
+- return 1;
++ return true;
+ }
+
+ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
+diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c
+index 9dd03c7..1fa62f3 100644
+--- a/net/netfilter/nf_conntrack_proto_udplite.c
++++ b/net/netfilter/nf_conntrack_proto_udplite.c
+@@ -27,28 +27,28 @@
+ static unsigned int nf_ct_udplite_timeout __read_mostly = 30*HZ;
+ static unsigned int nf_ct_udplite_timeout_stream __read_mostly = 180*HZ;
+
+-static int udplite_pkt_to_tuple(const struct sk_buff *skb,
+- unsigned int dataoff,
+- struct nf_conntrack_tuple *tuple)
++static bool udplite_pkt_to_tuple(const struct sk_buff *skb,
++ unsigned int dataoff,
++ struct nf_conntrack_tuple *tuple)
+ {
+ const struct udphdr *hp;
+ struct udphdr _hdr;
+
+ hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
+ if (hp == NULL)
+- return 0;
++ return false;
+
+ tuple->src.u.udp.port = hp->source;
+ tuple->dst.u.udp.port = hp->dest;
+- return 1;
++ return true;
+ }
+
+-static int udplite_invert_tuple(struct nf_conntrack_tuple *tuple,
+- const struct nf_conntrack_tuple *orig)
++static bool udplite_invert_tuple(struct nf_conntrack_tuple *tuple,
++ const struct nf_conntrack_tuple *orig)
+ {
+ tuple->src.u.udp.port = orig->dst.u.udp.port;
+ tuple->dst.u.udp.port = orig->src.u.udp.port;
+- return 1;
++ return true;
+ }
+
+ /* Print out the per-protocol part of the tuple. */
+@@ -83,10 +83,10 @@ static int udplite_packet(struct nf_conn *ct,
+ }
+
+ /* Called when a new connection for this protocol found. */
+-static int udplite_new(struct nf_conn *ct, const struct sk_buff *skb,
+- unsigned int dataoff)
++static bool udplite_new(struct nf_conn *ct, const struct sk_buff *skb,
++ unsigned int dataoff)
+ {
+- return 1;
++ return true;
+ }
+
+ static int udplite_error(struct sk_buff *skb, unsigned int dataoff,
+@@ -127,32 +127,13 @@ static int udplite_error(struct sk_buff *skb, unsigned int dataoff,
+ }
+
+ /* Checksum invalid? Ignore. */
+- if (nf_conntrack_checksum && !skb_csum_unnecessary(skb) &&
+- hooknum == NF_INET_PRE_ROUTING) {
+- if (pf == PF_INET) {
+- struct iphdr *iph = ip_hdr(skb);
+-
+- skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
+- udplen, IPPROTO_UDPLITE, 0);
+- } else {
+- struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+- __wsum hsum = skb_checksum(skb, 0, dataoff, 0);
+-
+- skb->csum = ~csum_unfold(
+- csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr,
+- udplen, IPPROTO_UDPLITE,
+- csum_sub(0, hsum)));
+- }
+-
+- skb->ip_summed = CHECKSUM_NONE;
+- if (__skb_checksum_complete_head(skb, dataoff + cscov)) {
+- if (LOG_INVALID(IPPROTO_UDPLITE))
+- nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
+- "nf_ct_udplite: bad UDPLite "
+- "checksum ");
+- return -NF_ACCEPT;
+- }
+- skb->ip_summed = CHECKSUM_UNNECESSARY;
++ if (nf_conntrack_checksum && hooknum == NF_INET_PRE_ROUTING &&
++ nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_UDP,
++ pf)) {
++ if (LOG_INVALID(IPPROTO_UDPLITE))
++ nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
++ "nf_ct_udplite: bad UDPLite checksum ");
++ return -NF_ACCEPT;
+ }
+
+ return NF_ACCEPT;
+diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c
+index a70051d..a94294b 100644
+--- a/net/netfilter/nf_conntrack_sane.c
++++ b/net/netfilter/nf_conntrack_sane.c
+@@ -72,7 +72,6 @@ static int help(struct sk_buff *skb,
+ struct nf_conntrack_tuple *tuple;
+ struct sane_request *req;
+ struct sane_reply_net_start *reply;
+- int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+
+ ct_sane_info = &nfct_help(ct)->help.ct_sane_info;
+ /* Until there's been traffic both ways, don't look in packets. */
+@@ -143,11 +142,12 @@ static int help(struct sk_buff *skb,
+ }
+
+ tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
+- nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3,
++ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
++ &tuple->src.u3, &tuple->dst.u3,
+ IPPROTO_TCP, NULL, &reply->port);
+
+ pr_debug("nf_ct_sane: expect: ");
+- NF_CT_DUMP_TUPLE(&exp->tuple);
++ nf_ct_dump_tuple(&exp->tuple);
+
+ /* Can't expect this? Best to drop packet now. */
+ if (nf_ct_expect_related(exp) != 0)
+@@ -163,6 +163,11 @@ out:
+ static struct nf_conntrack_helper sane[MAX_PORTS][2] __read_mostly;
+ static char sane_names[MAX_PORTS][2][sizeof("sane-65535")] __read_mostly;
+
++static const struct nf_conntrack_expect_policy sane_exp_policy = {
++ .max_expected = 1,
++ .timeout = 5 * 60,
++};
++
+ /* don't make this __exit, since it's called from __init ! */
+ static void nf_conntrack_sane_fini(void)
+ {
+@@ -200,8 +205,7 @@ static int __init nf_conntrack_sane_init(void)
+ for (j = 0; j < 2; j++) {
+ sane[i][j].tuple.src.u.tcp.port = htons(ports[i]);
+ sane[i][j].tuple.dst.protonum = IPPROTO_TCP;
+- sane[i][j].max_expected = 1;
+- sane[i][j].timeout = 5 * 60; /* 5 Minutes */
++ sane[i][j].expect_policy = &sane_exp_policy;
+ sane[i][j].me = THIS_MODULE;
+ sane[i][j].help = help;
+ tmpname = &sane_names[i][j][0];
+diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
+index c521c89..9f49000 100644
+--- a/net/netfilter/nf_conntrack_sip.c
++++ b/net/netfilter/nf_conntrack_sip.c
+@@ -2,6 +2,8 @@
+ *
+ * (C) 2005 by Christian Hentschel <chentschel at arnet.com.ar>
+ * based on RR's ip_conntrack_ftp.c and other modules.
++ * (C) 2007 United Security Providers
++ * (C) 2007, 2008 Patrick McHardy <kaber at trash.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+@@ -17,6 +19,7 @@
+ #include <linux/netfilter.h>
+
+ #include <net/netfilter/nf_conntrack.h>
++#include <net/netfilter/nf_conntrack_core.h>
+ #include <net/netfilter/nf_conntrack_expect.h>
+ #include <net/netfilter/nf_conntrack_helper.h>
+ #include <linux/netfilter/nf_conntrack_sip.h>
+@@ -36,214 +39,102 @@ static unsigned int sip_timeout __read_mostly = SIP_TIMEOUT;
+ module_param(sip_timeout, uint, 0600);
+ MODULE_PARM_DESC(sip_timeout, "timeout for the master SIP session");
+
++static int sip_direct_signalling __read_mostly = 1;
++module_param(sip_direct_signalling, int, 0600);
++MODULE_PARM_DESC(sip_direct_signalling, "expect incoming calls from registrar "
++ "only (default 1)");
++
++static int sip_direct_media __read_mostly = 1;
++module_param(sip_direct_media, int, 0600);
++MODULE_PARM_DESC(sip_direct_media, "Expect Media streams between signalling "
++ "endpoints only (default 1)");
++
+ unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb,
+- enum ip_conntrack_info ctinfo,
+- struct nf_conn *ct,
+- const char **dptr) __read_mostly;
++ const char **dptr,
++ unsigned int *datalen) __read_mostly;
+ EXPORT_SYMBOL_GPL(nf_nat_sip_hook);
+
+-unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb,
+- enum ip_conntrack_info ctinfo,
+- struct nf_conntrack_expect *exp,
+- const char *dptr) __read_mostly;
+-EXPORT_SYMBOL_GPL(nf_nat_sdp_hook);
+-
+-static int digits_len(const struct nf_conn *, const char *, const char *, int *);
+-static int epaddr_len(const struct nf_conn *, const char *, const char *, int *);
+-static int skp_digits_len(const struct nf_conn *, const char *, const char *, int *);
+-static int skp_epaddr_len(const struct nf_conn *, const char *, const char *, int *);
+-
+-struct sip_header_nfo {
+- const char *lname;
+- const char *sname;
+- const char *ln_str;
+- size_t lnlen;
+- size_t snlen;
+- size_t ln_strlen;
+- int case_sensitive;
+- int (*match_len)(const struct nf_conn *, const char *,
+- const char *, int *);
+-};
++unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb,
++ const char **dptr,
++ unsigned int *datalen,
++ struct nf_conntrack_expect *exp,
++ unsigned int matchoff,
++ unsigned int matchlen) __read_mostly;
++EXPORT_SYMBOL_GPL(nf_nat_sip_expect_hook);
+
+-static const struct sip_header_nfo ct_sip_hdrs[] = {
+- [POS_REG_REQ_URI] = { /* SIP REGISTER request URI */
+- .lname = "sip:",
+- .lnlen = sizeof("sip:") - 1,
+- .ln_str = ":",
+- .ln_strlen = sizeof(":") - 1,
+- .match_len = epaddr_len,
+- },
+- [POS_REQ_URI] = { /* SIP request URI */
+- .lname = "sip:",
+- .lnlen = sizeof("sip:") - 1,
+- .ln_str = "@",
+- .ln_strlen = sizeof("@") - 1,
+- .match_len = epaddr_len,
+- },
+- [POS_FROM] = { /* SIP From header */
+- .lname = "From:",
+- .lnlen = sizeof("From:") - 1,
+- .sname = "\r\nf:",
+- .snlen = sizeof("\r\nf:") - 1,
+- .ln_str = "sip:",
+- .ln_strlen = sizeof("sip:") - 1,
+- .match_len = skp_epaddr_len,
+- },
+- [POS_TO] = { /* SIP To header */
+- .lname = "To:",
+- .lnlen = sizeof("To:") - 1,
+- .sname = "\r\nt:",
+- .snlen = sizeof("\r\nt:") - 1,
+- .ln_str = "sip:",
+- .ln_strlen = sizeof("sip:") - 1,
+- .match_len = skp_epaddr_len
+- },
+- [POS_VIA] = { /* SIP Via header */
+- .lname = "Via:",
+- .lnlen = sizeof("Via:") - 1,
+- .sname = "\r\nv:",
+- .snlen = sizeof("\r\nv:") - 1, /* rfc3261 "\r\n" */
+- .ln_str = "UDP ",
+- .ln_strlen = sizeof("UDP ") - 1,
+- .match_len = epaddr_len,
+- },
+- [POS_CONTACT] = { /* SIP Contact header */
+- .lname = "Contact:",
+- .lnlen = sizeof("Contact:") - 1,
+- .sname = "\r\nm:",
+- .snlen = sizeof("\r\nm:") - 1,
+- .ln_str = "sip:",
+- .ln_strlen = sizeof("sip:") - 1,
+- .match_len = skp_epaddr_len
+- },
+- [POS_CONTENT] = { /* SIP Content length header */
+- .lname = "Content-Length:",
+- .lnlen = sizeof("Content-Length:") - 1,
+- .sname = "\r\nl:",
+- .snlen = sizeof("\r\nl:") - 1,
+- .ln_str = ":",
+- .ln_strlen = sizeof(":") - 1,
+- .match_len = skp_digits_len
+- },
+- [POS_MEDIA] = { /* SDP media info */
+- .case_sensitive = 1,
+- .lname = "\nm=",
+- .lnlen = sizeof("\nm=") - 1,
+- .sname = "\rm=",
+- .snlen = sizeof("\rm=") - 1,
+- .ln_str = "audio ",
+- .ln_strlen = sizeof("audio ") - 1,
+- .match_len = digits_len
+- },
+- [POS_OWNER_IP4] = { /* SDP owner address*/
+- .case_sensitive = 1,
+- .lname = "\no=",
+- .lnlen = sizeof("\no=") - 1,
+- .sname = "\ro=",
+- .snlen = sizeof("\ro=") - 1,
+- .ln_str = "IN IP4 ",
+- .ln_strlen = sizeof("IN IP4 ") - 1,
+- .match_len = epaddr_len
+- },
+- [POS_CONNECTION_IP4] = {/* SDP connection info */
+- .case_sensitive = 1,
+- .lname = "\nc=",
+- .lnlen = sizeof("\nc=") - 1,
+- .sname = "\rc=",
+- .snlen = sizeof("\rc=") - 1,
+- .ln_str = "IN IP4 ",
+- .ln_strlen = sizeof("IN IP4 ") - 1,
+- .match_len = epaddr_len
+- },
+- [POS_OWNER_IP6] = { /* SDP owner address*/
+- .case_sensitive = 1,
+- .lname = "\no=",
+- .lnlen = sizeof("\no=") - 1,
+- .sname = "\ro=",
+- .snlen = sizeof("\ro=") - 1,
+- .ln_str = "IN IP6 ",
+- .ln_strlen = sizeof("IN IP6 ") - 1,
+- .match_len = epaddr_len
+- },
+- [POS_CONNECTION_IP6] = {/* SDP connection info */
+- .case_sensitive = 1,
+- .lname = "\nc=",
+- .lnlen = sizeof("\nc=") - 1,
+- .sname = "\rc=",
+- .snlen = sizeof("\rc=") - 1,
+- .ln_str = "IN IP6 ",
+- .ln_strlen = sizeof("IN IP6 ") - 1,
+- .match_len = epaddr_len
+- },
+- [POS_SDP_HEADER] = { /* SDP version header */
+- .case_sensitive = 1,
+- .lname = "\nv=",
+- .lnlen = sizeof("\nv=") - 1,
+- .sname = "\rv=",
+- .snlen = sizeof("\rv=") - 1,
+- .ln_str = "=",
+- .ln_strlen = sizeof("=") - 1,
+- .match_len = digits_len
+- }
+-};
++unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb,
++ const char **dptr,
++ unsigned int dataoff,
++ unsigned int *datalen,
++ enum sdp_header_types type,
++ enum sdp_header_types term,
++ const union nf_inet_addr *addr)
++ __read_mostly;
++EXPORT_SYMBOL_GPL(nf_nat_sdp_addr_hook);
+
+-/* get line length until first CR or LF seen. */
+-int ct_sip_lnlen(const char *line, const char *limit)
+-{
+- const char *k = line;
++unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb,
++ const char **dptr,
++ unsigned int *datalen,
++ unsigned int matchoff,
++ unsigned int matchlen,
++ u_int16_t port) __read_mostly;
++EXPORT_SYMBOL_GPL(nf_nat_sdp_port_hook);
+
+- while ((line <= limit) && (*line == '\r' || *line == '\n'))
+- line++;
++unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb,
++ const char **dptr,
++ unsigned int dataoff,
++ unsigned int *datalen,
++ const union nf_inet_addr *addr)
++ __read_mostly;
++EXPORT_SYMBOL_GPL(nf_nat_sdp_session_hook);
+
+- while (line <= limit) {
+- if (*line == '\r' || *line == '\n')
+- break;
+- line++;
+- }
+- return line - k;
+-}
+-EXPORT_SYMBOL_GPL(ct_sip_lnlen);
++unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb,
++ const char **dptr,
++ unsigned int *datalen,
++ struct nf_conntrack_expect *rtp_exp,
++ struct nf_conntrack_expect *rtcp_exp,
++ unsigned int mediaoff,
++ unsigned int medialen,
++ union nf_inet_addr *rtp_addr)
++ __read_mostly;
++EXPORT_SYMBOL_GPL(nf_nat_sdp_media_hook);
+
+-/* Linear string search, case sensitive. */
+-const char *ct_sip_search(const char *needle, const char *haystack,
+- size_t needle_len, size_t haystack_len,
+- int case_sensitive)
++static int string_len(const struct nf_conn *ct, const char *dptr,
++ const char *limit, int *shift)
+ {
+- const char *limit = haystack + (haystack_len - needle_len);
++ int len = 0;
+
+- while (haystack <= limit) {
+- if (case_sensitive) {
+- if (strncmp(haystack, needle, needle_len) == 0)
+- return haystack;
+- } else {
+- if (strnicmp(haystack, needle, needle_len) == 0)
+- return haystack;
+- }
+- haystack++;
++ while (dptr < limit && isalpha(*dptr)) {
++ dptr++;
++ len++;
+ }
+- return NULL;
++ return len;
+ }
+-EXPORT_SYMBOL_GPL(ct_sip_search);
+
+ static int digits_len(const struct nf_conn *ct, const char *dptr,
+ const char *limit, int *shift)
+ {
+ int len = 0;
+- while (dptr <= limit && isdigit(*dptr)) {
++ while (dptr < limit && isdigit(*dptr)) {
+ dptr++;
+ len++;
+ }
+ return len;
+ }
+
+-/* get digits length, skipping blank spaces. */
+-static int skp_digits_len(const struct nf_conn *ct, const char *dptr,
+- const char *limit, int *shift)
++/* get media type + port length */
++static int media_len(const struct nf_conn *ct, const char *dptr,
++ const char *limit, int *shift)
+ {
+- for (; dptr <= limit && *dptr == ' '; dptr++)
+- (*shift)++;
++ int len = string_len(ct, dptr, limit, shift);
++
++ dptr += len;
++ if (dptr >= limit || *dptr != ' ')
++ return 0;
++ len++;
++ dptr++;
+
+- return digits_len(ct, dptr, limit, shift);
++ return len + digits_len(ct, dptr, limit, shift);
+ }
+
+ static int parse_addr(const struct nf_conn *ct, const char *cp,
+@@ -251,10 +142,10 @@ static int parse_addr(const struct nf_conn *ct, const char *cp,
+ const char *limit)
+ {
+ const char *end;
+- int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ int ret = 0;
+
+- switch (family) {
++ memset(addr, 0, sizeof(*addr));
++ switch (nf_ct_l3num(ct)) {
+ case AF_INET:
+ ret = in4_pton(cp, limit - cp, (u8 *)&addr->ip, -1, &end);
+ break;
+@@ -302,13 +193,13 @@ static int skp_epaddr_len(const struct nf_conn *ct, const char *dptr,
+ /* Search for @, but stop at the end of the line.
+ * We are inside a sip: URI, so we don't need to worry about
+ * continuation lines. */
+- while (dptr <= limit &&
++ while (dptr < limit &&
+ *dptr != '@' && *dptr != '\r' && *dptr != '\n') {
+ (*shift)++;
+ dptr++;
+ }
+
+- if (dptr <= limit && *dptr == '@') {
++ if (dptr < limit && *dptr == '@') {
+ dptr++;
+ (*shift)++;
+ } else {
+@@ -319,74 +210,892 @@ static int skp_epaddr_len(const struct nf_conn *ct, const char *dptr,
+ return epaddr_len(ct, dptr, limit, shift);
+ }
+
+-/* Returns 0 if not found, -1 error parsing. */
+-int ct_sip_get_info(const struct nf_conn *ct,
+- const char *dptr, size_t dlen,
+- unsigned int *matchoff,
+- unsigned int *matchlen,
+- enum sip_header_pos pos)
++/* Parse a SIP request line of the form:
++ *
++ * Request-Line = Method SP Request-URI SP SIP-Version CRLF
++ *
++ * and return the offset and length of the address contained in the Request-URI.
++ */
++int ct_sip_parse_request(const struct nf_conn *ct,
++ const char *dptr, unsigned int datalen,
++ unsigned int *matchoff, unsigned int *matchlen,
++ union nf_inet_addr *addr, __be16 *port)
+ {
+- const struct sip_header_nfo *hnfo = &ct_sip_hdrs[pos];
+- const char *limit, *aux, *k = dptr;
++ const char *start = dptr, *limit = dptr + datalen, *end;
++ unsigned int mlen;
++ unsigned int p;
+ int shift = 0;
+
+- limit = dptr + (dlen - hnfo->lnlen);
++ /* Skip method and following whitespace */
++ mlen = string_len(ct, dptr, limit, NULL);
++ if (!mlen)
++ return 0;
++ dptr += mlen;
++ if (++dptr >= limit)
++ return 0;
+
+- while (dptr <= limit) {
+- if ((strncmp(dptr, hnfo->lname, hnfo->lnlen) != 0) &&
+- (hnfo->sname == NULL ||
+- strncmp(dptr, hnfo->sname, hnfo->snlen) != 0)) {
+- dptr++;
++ /* Find SIP URI */
++ limit -= strlen("sip:");
++ for (; dptr < limit; dptr++) {
++ if (*dptr == '\r' || *dptr == '\n')
++ return -1;
++ if (strnicmp(dptr, "sip:", strlen("sip:")) == 0)
++ break;
++ }
++ if (!skp_epaddr_len(ct, dptr, limit, &shift))
++ return 0;
++ dptr += shift;
++
++ if (!parse_addr(ct, dptr, &end, addr, limit))
++ return -1;
++ if (end < limit && *end == ':') {
++ end++;
++ p = simple_strtoul(end, (char **)&end, 10);
++ if (p < 1024 || p > 65535)
++ return -1;
++ *port = htons(p);
++ } else
++ *port = htons(SIP_PORT);
++
++ if (end == dptr)
++ return 0;
++ *matchoff = dptr - start;
++ *matchlen = end - dptr;
++ return 1;
++}
++EXPORT_SYMBOL_GPL(ct_sip_parse_request);
++
++/* SIP header parsing: SIP headers are located at the beginning of a line, but
++ * may span several lines, in which case the continuation lines begin with a
++ * whitespace character. RFC 2543 allows lines to be terminated with CR, LF or
++ * CRLF, RFC 3261 allows only CRLF, we support both.
++ *
++ * Headers are followed by (optionally) whitespace, a colon, again (optionally)
++ * whitespace and the values. Whitespace in this context means any amount of
++ * tabs, spaces and continuation lines, which are treated as a single whitespace
++ * character.
++ *
++ * Some headers may appear multiple times. A comma seperated list of values is
++ * equivalent to multiple headers.
++ */
++static const struct sip_header ct_sip_hdrs[] = {
++ [SIP_HDR_CSEQ] = SIP_HDR("CSeq", NULL, NULL, digits_len),
++ [SIP_HDR_FROM] = SIP_HDR("From", "f", "sip:", skp_epaddr_len),
++ [SIP_HDR_TO] = SIP_HDR("To", "t", "sip:", skp_epaddr_len),
++ [SIP_HDR_CONTACT] = SIP_HDR("Contact", "m", "sip:", skp_epaddr_len),
++ [SIP_HDR_VIA] = SIP_HDR("Via", "v", "UDP ", epaddr_len),
++ [SIP_HDR_EXPIRES] = SIP_HDR("Expires", NULL, NULL, digits_len),
++ [SIP_HDR_CONTENT_LENGTH] = SIP_HDR("Content-Length", "l", NULL, digits_len),
++};
++
++static const char *sip_follow_continuation(const char *dptr, const char *limit)
++{
++ /* Walk past newline */
++ if (++dptr >= limit)
++ return NULL;
++
++ /* Skip '\n' in CR LF */
++ if (*(dptr - 1) == '\r' && *dptr == '\n') {
++ if (++dptr >= limit)
++ return NULL;
++ }
++
++ /* Continuation line? */
++ if (*dptr != ' ' && *dptr != '\t')
++ return NULL;
++
++ /* skip leading whitespace */
++ for (; dptr < limit; dptr++) {
++ if (*dptr != ' ' && *dptr != '\t')
++ break;
++ }
++ return dptr;
++}
++
++static const char *sip_skip_whitespace(const char *dptr, const char *limit)
++{
++ for (; dptr < limit; dptr++) {
++ if (*dptr == ' ')
++ continue;
++ if (*dptr != '\r' && *dptr != '\n')
++ break;
++ dptr = sip_follow_continuation(dptr, limit);
++ if (dptr == NULL)
++ return NULL;
++ }
++ return dptr;
++}
++
++/* Search within a SIP header value, dealing with continuation lines */
++static const char *ct_sip_header_search(const char *dptr, const char *limit,
++ const char *needle, unsigned int len)
++{
++ for (limit -= len; dptr < limit; dptr++) {
++ if (*dptr == '\r' || *dptr == '\n') {
++ dptr = sip_follow_continuation(dptr, limit);
++ if (dptr == NULL)
++ break;
+ continue;
+ }
+- aux = ct_sip_search(hnfo->ln_str, dptr, hnfo->ln_strlen,
+- ct_sip_lnlen(dptr, limit),
+- hnfo->case_sensitive);
+- if (!aux) {
+- pr_debug("'%s' not found in '%s'.\n", hnfo->ln_str,
+- hnfo->lname);
+- return -1;
++
++ if (strnicmp(dptr, needle, len) == 0)
++ return dptr;
++ }
++ return NULL;
++}
++
++int ct_sip_get_header(const struct nf_conn *ct, const char *dptr,
++ unsigned int dataoff, unsigned int datalen,
++ enum sip_header_types type,
++ unsigned int *matchoff, unsigned int *matchlen)
++{
++ const struct sip_header *hdr = &ct_sip_hdrs[type];
++ const char *start = dptr, *limit = dptr + datalen;
++ int shift = 0;
++
++ for (dptr += dataoff; dptr < limit; dptr++) {
++ /* Find beginning of line */
++ if (*dptr != '\r' && *dptr != '\n')
++ continue;
++ if (++dptr >= limit)
++ break;
++ if (*(dptr - 1) == '\r' && *dptr == '\n') {
++ if (++dptr >= limit)
++ break;
++ }
++
++ /* Skip continuation lines */
++ if (*dptr == ' ' || *dptr == '\t')
++ continue;
++
++ /* Find header. Compact headers must be followed by a
++ * non-alphabetic character to avoid mismatches. */
++ if (limit - dptr >= hdr->len &&
++ strnicmp(dptr, hdr->name, hdr->len) == 0)
++ dptr += hdr->len;
++ else if (hdr->cname && limit - dptr >= hdr->clen + 1 &&
++ strnicmp(dptr, hdr->cname, hdr->clen) == 0 &&
++ !isalpha(*(dptr + hdr->clen + 1)))
++ dptr += hdr->clen;
++ else
++ continue;
++
++ /* Find and skip colon */
++ dptr = sip_skip_whitespace(dptr, limit);
++ if (dptr == NULL)
++ break;
++ if (*dptr != ':' || ++dptr >= limit)
++ break;
++
++ /* Skip whitespace after colon */
++ dptr = sip_skip_whitespace(dptr, limit);
++ if (dptr == NULL)
++ break;
++
++ *matchoff = dptr - start;
++ if (hdr->search) {
++ dptr = ct_sip_header_search(dptr, limit, hdr->search,
++ hdr->slen);
++ if (!dptr)
++ return -1;
++ dptr += hdr->slen;
+ }
+- aux += hnfo->ln_strlen;
+
+- *matchlen = hnfo->match_len(ct, aux, limit, &shift);
++ *matchlen = hdr->match_len(ct, dptr, limit, &shift);
+ if (!*matchlen)
+ return -1;
++ *matchoff = dptr - start + shift;
++ return 1;
++ }
++ return 0;
++}
++EXPORT_SYMBOL_GPL(ct_sip_get_header);
++
++/* Get next header field in a list of comma seperated values */
++static int ct_sip_next_header(const struct nf_conn *ct, const char *dptr,
++ unsigned int dataoff, unsigned int datalen,
++ enum sip_header_types type,
++ unsigned int *matchoff, unsigned int *matchlen)
++{
++ const struct sip_header *hdr = &ct_sip_hdrs[type];
++ const char *start = dptr, *limit = dptr + datalen;
++ int shift = 0;
++
++ dptr += dataoff;
++
++ dptr = ct_sip_header_search(dptr, limit, ",", strlen(","));
++ if (!dptr)
++ return 0;
++
++ dptr = ct_sip_header_search(dptr, limit, hdr->search, hdr->slen);
++ if (!dptr)
++ return 0;
++ dptr += hdr->slen;
++
++ *matchoff = dptr - start;
++ *matchlen = hdr->match_len(ct, dptr, limit, &shift);
++ if (!*matchlen)
++ return -1;
++ *matchoff += shift;
++ return 1;
++}
++
++/* Walk through headers until a parsable one is found or no header of the
++ * given type is left. */
++static int ct_sip_walk_headers(const struct nf_conn *ct, const char *dptr,
++ unsigned int dataoff, unsigned int datalen,
++ enum sip_header_types type, int *in_header,
++ unsigned int *matchoff, unsigned int *matchlen)
++{
++ int ret;
++
++ if (in_header && *in_header) {
++ while (1) {
++ ret = ct_sip_next_header(ct, dptr, dataoff, datalen,
++ type, matchoff, matchlen);
++ if (ret > 0)
++ return ret;
++ if (ret == 0)
++ break;
++ dataoff += *matchoff;
++ }
++ *in_header = 0;
++ }
++
++ while (1) {
++ ret = ct_sip_get_header(ct, dptr, dataoff, datalen,
++ type, matchoff, matchlen);
++ if (ret > 0)
++ break;
++ if (ret == 0)
++ return ret;
++ dataoff += *matchoff;
++ }
++
++ if (in_header)
++ *in_header = 1;
++ return 1;
++}
++
++/* Locate a SIP header, parse the URI and return the offset and length of
++ * the address as well as the address and port themselves. A stream of
++ * headers can be parsed by handing in a non-NULL datalen and in_header
++ * pointer.
++ */
++int ct_sip_parse_header_uri(const struct nf_conn *ct, const char *dptr,
++ unsigned int *dataoff, unsigned int datalen,
++ enum sip_header_types type, int *in_header,
++ unsigned int *matchoff, unsigned int *matchlen,
++ union nf_inet_addr *addr, __be16 *port)
++{
++ const char *c, *limit = dptr + datalen;
++ unsigned int p;
++ int ret;
++
++ ret = ct_sip_walk_headers(ct, dptr, dataoff ? *dataoff : 0, datalen,
++ type, in_header, matchoff, matchlen);
++ WARN_ON(ret < 0);
++ if (ret == 0)
++ return ret;
++
++ if (!parse_addr(ct, dptr + *matchoff, &c, addr, limit))
++ return -1;
++ if (*c == ':') {
++ c++;
++ p = simple_strtoul(c, (char **)&c, 10);
++ if (p < 1024 || p > 65535)
++ return -1;
++ *port = htons(p);
++ } else
++ *port = htons(SIP_PORT);
++
++ if (dataoff)
++ *dataoff = c - dptr;
++ return 1;
++}
++EXPORT_SYMBOL_GPL(ct_sip_parse_header_uri);
++
++/* Parse address from header parameter and return address, offset and length */
++int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr,
++ unsigned int dataoff, unsigned int datalen,
++ const char *name,
++ unsigned int *matchoff, unsigned int *matchlen,
++ union nf_inet_addr *addr)
++{
++ const char *limit = dptr + datalen;
++ const char *start, *end;
+
+- *matchoff = (aux - k) + shift;
++ limit = ct_sip_header_search(dptr + dataoff, limit, ",", strlen(","));
++ if (!limit)
++ limit = dptr + datalen;
+
+- pr_debug("%s match succeeded! - len: %u\n", hnfo->lname,
+- *matchlen);
++ start = ct_sip_header_search(dptr + dataoff, limit, name, strlen(name));
++ if (!start)
++ return 0;
++
++ start += strlen(name);
++ if (!parse_addr(ct, start, &end, addr, limit))
++ return 0;
++ *matchoff = start - dptr;
++ *matchlen = end - start;
++ return 1;
++}
++EXPORT_SYMBOL_GPL(ct_sip_parse_address_param);
++
++/* Parse numerical header parameter and return value, offset and length */
++int ct_sip_parse_numerical_param(const struct nf_conn *ct, const char *dptr,
++ unsigned int dataoff, unsigned int datalen,
++ const char *name,
++ unsigned int *matchoff, unsigned int *matchlen,
++ unsigned int *val)
++{
++ const char *limit = dptr + datalen;
++ const char *start;
++ char *end;
++
++ limit = ct_sip_header_search(dptr + dataoff, limit, ",", strlen(","));
++ if (!limit)
++ limit = dptr + datalen;
++
++ start = ct_sip_header_search(dptr + dataoff, limit, name, strlen(name));
++ if (!start)
++ return 0;
++
++ start += strlen(name);
++ *val = simple_strtoul(start, &end, 0);
++ if (start == end)
++ return 0;
++ if (matchoff && matchlen) {
++ *matchoff = start - dptr;
++ *matchlen = end - start;
++ }
++ return 1;
++}
++EXPORT_SYMBOL_GPL(ct_sip_parse_numerical_param);
++
++/* SDP header parsing: a SDP session description contains an ordered set of
++ * headers, starting with a section containing general session parameters,
++ * optionally followed by multiple media descriptions.
++ *
++ * SDP headers always start at the beginning of a line. According to RFC 2327:
++ * "The sequence CRLF (0x0d0a) is used to end a record, although parsers should
++ * be tolerant and also accept records terminated with a single newline
++ * character". We handle both cases.
++ */
++static const struct sip_header ct_sdp_hdrs[] = {
++ [SDP_HDR_VERSION] = SDP_HDR("v=", NULL, digits_len),
++ [SDP_HDR_OWNER_IP4] = SDP_HDR("o=", "IN IP4 ", epaddr_len),
++ [SDP_HDR_CONNECTION_IP4] = SDP_HDR("c=", "IN IP4 ", epaddr_len),
++ [SDP_HDR_OWNER_IP6] = SDP_HDR("o=", "IN IP6 ", epaddr_len),
++ [SDP_HDR_CONNECTION_IP6] = SDP_HDR("c=", "IN IP6 ", epaddr_len),
++ [SDP_HDR_MEDIA] = SDP_HDR("m=", NULL, media_len),
++};
++
++/* Linear string search within SDP header values */
++static const char *ct_sdp_header_search(const char *dptr, const char *limit,
++ const char *needle, unsigned int len)
++{
++ for (limit -= len; dptr < limit; dptr++) {
++ if (*dptr == '\r' || *dptr == '\n')
++ break;
++ if (strncmp(dptr, needle, len) == 0)
++ return dptr;
++ }
++ return NULL;
++}
++
++/* Locate a SDP header (optionally a substring within the header value),
++ * optionally stopping at the first occurence of the term header, parse
++ * it and return the offset and length of the data we're interested in.
++ */
++int ct_sip_get_sdp_header(const struct nf_conn *ct, const char *dptr,
++ unsigned int dataoff, unsigned int datalen,
++ enum sdp_header_types type,
++ enum sdp_header_types term,
++ unsigned int *matchoff, unsigned int *matchlen)
++{
++ const struct sip_header *hdr = &ct_sdp_hdrs[type];
++ const struct sip_header *thdr = &ct_sdp_hdrs[term];
++ const char *start = dptr, *limit = dptr + datalen;
++ int shift = 0;
++
++ for (dptr += dataoff; dptr < limit; dptr++) {
++ /* Find beginning of line */
++ if (*dptr != '\r' && *dptr != '\n')
++ continue;
++ if (++dptr >= limit)
++ break;
++ if (*(dptr - 1) == '\r' && *dptr == '\n') {
++ if (++dptr >= limit)
++ break;
++ }
++
++ if (term != SDP_HDR_UNSPEC &&
++ limit - dptr >= thdr->len &&
++ strnicmp(dptr, thdr->name, thdr->len) == 0)
++ break;
++ else if (limit - dptr >= hdr->len &&
++ strnicmp(dptr, hdr->name, hdr->len) == 0)
++ dptr += hdr->len;
++ else
++ continue;
++
++ *matchoff = dptr - start;
++ if (hdr->search) {
++ dptr = ct_sdp_header_search(dptr, limit, hdr->search,
++ hdr->slen);
++ if (!dptr)
++ return -1;
++ dptr += hdr->slen;
++ }
++
++ *matchlen = hdr->match_len(ct, dptr, limit, &shift);
++ if (!*matchlen)
++ return -1;
++ *matchoff = dptr - start + shift;
+ return 1;
+ }
+- pr_debug("%s header not found.\n", hnfo->lname);
+ return 0;
+ }
+-EXPORT_SYMBOL_GPL(ct_sip_get_info);
++EXPORT_SYMBOL_GPL(ct_sip_get_sdp_header);
++
++static int ct_sip_parse_sdp_addr(const struct nf_conn *ct, const char *dptr,
++ unsigned int dataoff, unsigned int datalen,
++ enum sdp_header_types type,
++ enum sdp_header_types term,
++ unsigned int *matchoff, unsigned int *matchlen,
++ union nf_inet_addr *addr)
++{
++ int ret;
++
++ ret = ct_sip_get_sdp_header(ct, dptr, dataoff, datalen, type, term,
++ matchoff, matchlen);
++ if (ret <= 0)
++ return ret;
++
++ if (!parse_addr(ct, dptr + *matchoff, NULL, addr,
++ dptr + *matchoff + *matchlen))
++ return -1;
++ return 1;
++}
++
++static int refresh_signalling_expectation(struct nf_conn *ct,
++ union nf_inet_addr *addr,
++ __be16 port,
++ unsigned int expires)
++{
++ struct nf_conn_help *help = nfct_help(ct);
++ struct nf_conntrack_expect *exp;
++ struct hlist_node *n, *next;
++ int found = 0;
++
++ spin_lock_bh(&nf_conntrack_lock);
++ hlist_for_each_entry_safe(exp, n, next, &help->expectations, lnode) {
++ if (exp->class != SIP_EXPECT_SIGNALLING ||
++ !nf_inet_addr_cmp(&exp->tuple.dst.u3, addr) ||
++ exp->tuple.dst.u.udp.port != port)
++ continue;
++ if (!del_timer(&exp->timeout))
++ continue;
++ exp->flags &= ~NF_CT_EXPECT_INACTIVE;
++ exp->timeout.expires = jiffies + expires * HZ;
++ add_timer(&exp->timeout);
++ found = 1;
++ break;
++ }
++ spin_unlock_bh(&nf_conntrack_lock);
++ return found;
++}
+
+-static int set_expected_rtp(struct sk_buff *skb,
+- struct nf_conn *ct,
+- enum ip_conntrack_info ctinfo,
+- union nf_inet_addr *addr,
+- __be16 port,
+- const char *dptr)
++static void flush_expectations(struct nf_conn *ct, bool media)
+ {
++ struct nf_conn_help *help = nfct_help(ct);
+ struct nf_conntrack_expect *exp;
++ struct hlist_node *n, *next;
++
++ spin_lock_bh(&nf_conntrack_lock);
++ hlist_for_each_entry_safe(exp, n, next, &help->expectations, lnode) {
++ if ((exp->class != SIP_EXPECT_SIGNALLING) ^ media)
++ continue;
++ if (!del_timer(&exp->timeout))
++ continue;
++ nf_ct_unlink_expect(exp);
++ nf_ct_expect_put(exp);
++ if (!media)
++ break;
++ }
++ spin_unlock_bh(&nf_conntrack_lock);
++}
++
++static int set_expected_rtp_rtcp(struct sk_buff *skb,
++ const char **dptr, unsigned int *datalen,
++ union nf_inet_addr *daddr, __be16 port,
++ enum sip_expectation_classes class,
++ unsigned int mediaoff, unsigned int medialen)
++{
++ struct nf_conntrack_expect *exp, *rtp_exp, *rtcp_exp;
++ enum ip_conntrack_info ctinfo;
++ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
++ union nf_inet_addr *saddr;
++ struct nf_conntrack_tuple tuple;
++ int direct_rtp = 0, skip_expect = 0, ret = NF_DROP;
++ u_int16_t base_port;
++ __be16 rtp_port, rtcp_port;
++ typeof(nf_nat_sdp_port_hook) nf_nat_sdp_port;
++ typeof(nf_nat_sdp_media_hook) nf_nat_sdp_media;
++
++ saddr = NULL;
++ if (sip_direct_media) {
++ if (!nf_inet_addr_cmp(daddr, &ct->tuplehash[dir].tuple.src.u3))
++ return NF_ACCEPT;
++ saddr = &ct->tuplehash[!dir].tuple.src.u3;
++ }
++
++ /* We need to check whether the registration exists before attempting
++ * to register it since we can see the same media description multiple
++ * times on different connections in case multiple endpoints receive
++ * the same call.
++ *
++ * RTP optimization: if we find a matching media channel expectation
++ * and both the expectation and this connection are SNATed, we assume
++ * both sides can reach each other directly and use the final
++ * destination address from the expectation. We still need to keep
++ * the NATed expectations for media that might arrive from the
++ * outside, and additionally need to expect the direct RTP stream
++ * in case it passes through us even without NAT.
++ */
++ memset(&tuple, 0, sizeof(tuple));
++ if (saddr)
++ tuple.src.u3 = *saddr;
++ tuple.src.l3num = nf_ct_l3num(ct);
++ tuple.dst.protonum = IPPROTO_UDP;
++ tuple.dst.u3 = *daddr;
++ tuple.dst.u.udp.port = port;
++
++ rcu_read_lock();
++ do {
++ exp = __nf_ct_expect_find(&tuple);
++
++ if (!exp || exp->master == ct ||
++ nfct_help(exp->master)->helper != nfct_help(ct)->helper ||
++ exp->class != class)
++ break;
++#ifdef CONFIG_NF_NAT_NEEDED
++ if (exp->tuple.src.l3num == AF_INET && !direct_rtp &&
++ (exp->saved_ip != exp->tuple.dst.u3.ip ||
++ exp->saved_proto.udp.port != exp->tuple.dst.u.udp.port) &&
++ ct->status & IPS_NAT_MASK) {
++ daddr->ip = exp->saved_ip;
++ tuple.dst.u3.ip = exp->saved_ip;
++ tuple.dst.u.udp.port = exp->saved_proto.udp.port;
++ direct_rtp = 1;
++ } else
++#endif
++ skip_expect = 1;
++ } while (!skip_expect);
++ rcu_read_unlock();
++
++ base_port = ntohs(tuple.dst.u.udp.port) & ~1;
++ rtp_port = htons(base_port);
++ rtcp_port = htons(base_port + 1);
++
++ if (direct_rtp) {
++ nf_nat_sdp_port = rcu_dereference(nf_nat_sdp_port_hook);
++ if (nf_nat_sdp_port &&
++ !nf_nat_sdp_port(skb, dptr, datalen,
++ mediaoff, medialen, ntohs(rtp_port)))
++ goto err1;
++ }
++
++ if (skip_expect)
++ return NF_ACCEPT;
++
++ rtp_exp = nf_ct_expect_alloc(ct);
++ if (rtp_exp == NULL)
++ goto err1;
++ nf_ct_expect_init(rtp_exp, class, nf_ct_l3num(ct), saddr, daddr,
++ IPPROTO_UDP, NULL, &rtp_port);
++
++ rtcp_exp = nf_ct_expect_alloc(ct);
++ if (rtcp_exp == NULL)
++ goto err2;
++ nf_ct_expect_init(rtcp_exp, class, nf_ct_l3num(ct), saddr, daddr,
++ IPPROTO_UDP, NULL, &rtcp_port);
++
++ nf_nat_sdp_media = rcu_dereference(nf_nat_sdp_media_hook);
++ if (nf_nat_sdp_media && ct->status & IPS_NAT_MASK && !direct_rtp)
++ ret = nf_nat_sdp_media(skb, dptr, datalen, rtp_exp, rtcp_exp,
++ mediaoff, medialen, daddr);
++ else {
++ if (nf_ct_expect_related(rtp_exp) == 0) {
++ if (nf_ct_expect_related(rtcp_exp) != 0)
++ nf_ct_unexpect_related(rtp_exp);
++ else
++ ret = NF_ACCEPT;
++ }
++ }
++ nf_ct_expect_put(rtcp_exp);
++err2:
++ nf_ct_expect_put(rtp_exp);
++err1:
++ return ret;
++}
++
++static const struct sdp_media_type sdp_media_types[] = {
++ SDP_MEDIA_TYPE("audio ", SIP_EXPECT_AUDIO),
++ SDP_MEDIA_TYPE("video ", SIP_EXPECT_VIDEO),
++};
++
++static const struct sdp_media_type *sdp_media_type(const char *dptr,
++ unsigned int matchoff,
++ unsigned int matchlen)
++{
++ const struct sdp_media_type *t;
++ unsigned int i;
++
++ for (i = 0; i < ARRAY_SIZE(sdp_media_types); i++) {
++ t = &sdp_media_types[i];
++ if (matchlen < t->len ||
++ strncmp(dptr + matchoff, t->name, t->len))
++ continue;
++ return t;
++ }
++ return NULL;
++}
++
++static int process_sdp(struct sk_buff *skb,
++ const char **dptr, unsigned int *datalen,
++ unsigned int cseq)
++{
++ enum ip_conntrack_info ctinfo;
++ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++ unsigned int matchoff, matchlen;
++ unsigned int mediaoff, medialen;
++ unsigned int sdpoff;
++ unsigned int caddr_len, maddr_len;
++ unsigned int i;
++ union nf_inet_addr caddr, maddr, rtp_addr;
++ unsigned int port;
++ enum sdp_header_types c_hdr;
++ const struct sdp_media_type *t;
++ int ret = NF_ACCEPT;
++ typeof(nf_nat_sdp_addr_hook) nf_nat_sdp_addr;
++ typeof(nf_nat_sdp_session_hook) nf_nat_sdp_session;
++
++ nf_nat_sdp_addr = rcu_dereference(nf_nat_sdp_addr_hook);
++ c_hdr = nf_ct_l3num(ct) == AF_INET ? SDP_HDR_CONNECTION_IP4 :
++ SDP_HDR_CONNECTION_IP6;
++
++ /* Find beginning of session description */
++ if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen,
++ SDP_HDR_VERSION, SDP_HDR_UNSPEC,
++ &matchoff, &matchlen) <= 0)
++ return NF_ACCEPT;
++ sdpoff = matchoff;
++
++ /* The connection information is contained in the session description
++ * and/or once per media description. The first media description marks
++ * the end of the session description. */
++ caddr_len = 0;
++ if (ct_sip_parse_sdp_addr(ct, *dptr, sdpoff, *datalen,
++ c_hdr, SDP_HDR_MEDIA,
++ &matchoff, &matchlen, &caddr) > 0)
++ caddr_len = matchlen;
++
++ mediaoff = sdpoff;
++ for (i = 0; i < ARRAY_SIZE(sdp_media_types); ) {
++ if (ct_sip_get_sdp_header(ct, *dptr, mediaoff, *datalen,
++ SDP_HDR_MEDIA, SDP_HDR_UNSPEC,
++ &mediaoff, &medialen) <= 0)
++ break;
++
++ /* Get media type and port number. A media port value of zero
++ * indicates an inactive stream. */
++ t = sdp_media_type(*dptr, mediaoff, medialen);
++ if (!t) {
++ mediaoff += medialen;
++ continue;
++ }
++ mediaoff += t->len;
++ medialen -= t->len;
++
++ port = simple_strtoul(*dptr + mediaoff, NULL, 10);
++ if (port == 0)
++ continue;
++ if (port < 1024 || port > 65535)
++ return NF_DROP;
++
++ /* The media description overrides the session description. */
++ maddr_len = 0;
++ if (ct_sip_parse_sdp_addr(ct, *dptr, mediaoff, *datalen,
++ c_hdr, SDP_HDR_MEDIA,
++ &matchoff, &matchlen, &maddr) > 0) {
++ maddr_len = matchlen;
++ memcpy(&rtp_addr, &maddr, sizeof(rtp_addr));
++ } else if (caddr_len)
++ memcpy(&rtp_addr, &caddr, sizeof(rtp_addr));
++ else
++ return NF_DROP;
++
++ ret = set_expected_rtp_rtcp(skb, dptr, datalen,
++ &rtp_addr, htons(port), t->class,
++ mediaoff, medialen);
++ if (ret != NF_ACCEPT)
++ return ret;
++
++ /* Update media connection address if present */
++ if (maddr_len && nf_nat_sdp_addr && ct->status & IPS_NAT_MASK) {
++ ret = nf_nat_sdp_addr(skb, dptr, mediaoff, datalen,
++ c_hdr, SDP_HDR_MEDIA, &rtp_addr);
++ if (ret != NF_ACCEPT)
++ return ret;
++ }
++ i++;
++ }
++
++ /* Update session connection and owner addresses */
++ nf_nat_sdp_session = rcu_dereference(nf_nat_sdp_session_hook);
++ if (nf_nat_sdp_session && ct->status & IPS_NAT_MASK)
++ ret = nf_nat_sdp_session(skb, dptr, sdpoff, datalen, &rtp_addr);
++
++ return ret;
++}
++static int process_invite_response(struct sk_buff *skb,
++ const char **dptr, unsigned int *datalen,
++ unsigned int cseq, unsigned int code)
++{
++ enum ip_conntrack_info ctinfo;
++ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++
++ if ((code >= 100 && code <= 199) ||
++ (code >= 200 && code <= 299))
++ return process_sdp(skb, dptr, datalen, cseq);
++ else {
++ flush_expectations(ct, true);
++ return NF_ACCEPT;
++ }
++}
++
++static int process_update_response(struct sk_buff *skb,
++ const char **dptr, unsigned int *datalen,
++ unsigned int cseq, unsigned int code)
++{
++ enum ip_conntrack_info ctinfo;
++ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++
++ if ((code >= 100 && code <= 199) ||
++ (code >= 200 && code <= 299))
++ return process_sdp(skb, dptr, datalen, cseq);
++ else {
++ flush_expectations(ct, true);
++ return NF_ACCEPT;
++ }
++}
++
++static int process_prack_response(struct sk_buff *skb,
++ const char **dptr, unsigned int *datalen,
++ unsigned int cseq, unsigned int code)
++{
++ enum ip_conntrack_info ctinfo;
++ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++
++ if ((code >= 100 && code <= 199) ||
++ (code >= 200 && code <= 299))
++ return process_sdp(skb, dptr, datalen, cseq);
++ else {
++ flush_expectations(ct, true);
++ return NF_ACCEPT;
++ }
++}
++
++static int process_bye_request(struct sk_buff *skb,
++ const char **dptr, unsigned int *datalen,
++ unsigned int cseq)
++{
++ enum ip_conntrack_info ctinfo;
++ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++
++ flush_expectations(ct, true);
++ return NF_ACCEPT;
++}
++
++/* Parse a REGISTER request and create a permanent expectation for incoming
++ * signalling connections. The expectation is marked inactive and is activated
++ * when receiving a response indicating success from the registrar.
++ */
++static int process_register_request(struct sk_buff *skb,
++ const char **dptr, unsigned int *datalen,
++ unsigned int cseq)
++{
++ enum ip_conntrack_info ctinfo;
++ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++ struct nf_conn_help *help = nfct_help(ct);
+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+- int family = ct->tuplehash[!dir].tuple.src.l3num;
++ unsigned int matchoff, matchlen;
++ struct nf_conntrack_expect *exp;
++ union nf_inet_addr *saddr, daddr;
++ __be16 port;
++ unsigned int expires = 0;
+ int ret;
+- typeof(nf_nat_sdp_hook) nf_nat_sdp;
++ typeof(nf_nat_sip_expect_hook) nf_nat_sip_expect;
++
++ /* Expected connections can not register again. */
++ if (ct->status & IPS_EXPECTED)
++ return NF_ACCEPT;
++
++ /* We must check the expiration time: a value of zero signals the
++ * registrar to release the binding. We'll remove our expectation
++ * when receiving the new bindings in the response, but we don't
++ * want to create new ones.
++ *
++ * The expiration time may be contained in Expires: header, the
++ * Contact: header parameters or the URI parameters.
++ */
++ if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_EXPIRES,
++ &matchoff, &matchlen) > 0)
++ expires = simple_strtoul(*dptr + matchoff, NULL, 10);
++
++ ret = ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen,
++ SIP_HDR_CONTACT, NULL,
++ &matchoff, &matchlen, &daddr, &port);
++ if (ret < 0)
++ return NF_DROP;
++ else if (ret == 0)
++ return NF_ACCEPT;
++
++ /* We don't support third-party registrations */
++ if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, &daddr))
++ return NF_ACCEPT;
++
++ if (ct_sip_parse_numerical_param(ct, *dptr,
++ matchoff + matchlen, *datalen,
++ "expires=", NULL, NULL, &expires) < 0)
++ return NF_DROP;
++
++ if (expires == 0) {
++ ret = NF_ACCEPT;
++ goto store_cseq;
++ }
+
+ exp = nf_ct_expect_alloc(ct);
+- if (exp == NULL)
++ if (!exp)
+ return NF_DROP;
+- nf_ct_expect_init(exp, family,
+- &ct->tuplehash[!dir].tuple.src.u3, addr,
+- IPPROTO_UDP, NULL, &port);
+
+- nf_nat_sdp = rcu_dereference(nf_nat_sdp_hook);
+- if (nf_nat_sdp && ct->status & IPS_NAT_MASK)
+- ret = nf_nat_sdp(skb, ctinfo, exp, dptr);
++ saddr = NULL;
++ if (sip_direct_signalling)
++ saddr = &ct->tuplehash[!dir].tuple.src.u3;
++
++ nf_ct_expect_init(exp, SIP_EXPECT_SIGNALLING, nf_ct_l3num(ct),
++ saddr, &daddr, IPPROTO_UDP, NULL, &port);
++ exp->timeout.expires = sip_timeout * HZ;
++ exp->helper = nfct_help(ct)->helper;
++ exp->flags = NF_CT_EXPECT_PERMANENT | NF_CT_EXPECT_INACTIVE;
++
++ nf_nat_sip_expect = rcu_dereference(nf_nat_sip_expect_hook);
++ if (nf_nat_sip_expect && ct->status & IPS_NAT_MASK)
++ ret = nf_nat_sip_expect(skb, dptr, datalen, exp,
++ matchoff, matchlen);
+ else {
+ if (nf_ct_expect_related(exp) != 0)
+ ret = NF_DROP;
+@@ -395,22 +1104,160 @@ static int set_expected_rtp(struct sk_buff *skb,
+ }
+ nf_ct_expect_put(exp);
+
++store_cseq:
++ if (ret == NF_ACCEPT)
++ help->help.ct_sip_info.register_cseq = cseq;
+ return ret;
+ }
+
++static int process_register_response(struct sk_buff *skb,
++ const char **dptr, unsigned int *datalen,
++ unsigned int cseq, unsigned int code)
++{
++ enum ip_conntrack_info ctinfo;
++ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++ struct nf_conn_help *help = nfct_help(ct);
++ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
++ union nf_inet_addr addr;
++ __be16 port;
++ unsigned int matchoff, matchlen, dataoff = 0;
++ unsigned int expires = 0;
++ int in_contact = 0, ret;
++
++ /* According to RFC 3261, "UAs MUST NOT send a new registration until
++ * they have received a final response from the registrar for the
++ * previous one or the previous REGISTER request has timed out".
++ *
++ * However, some servers fail to detect retransmissions and send late
++ * responses, so we store the sequence number of the last valid
++ * request and compare it here.
++ */
++ if (help->help.ct_sip_info.register_cseq != cseq)
++ return NF_ACCEPT;
++
++ if (code >= 100 && code <= 199)
++ return NF_ACCEPT;
++ if (code < 200 || code > 299)
++ goto flush;
++
++ if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_EXPIRES,
++ &matchoff, &matchlen) > 0)
++ expires = simple_strtoul(*dptr + matchoff, NULL, 10);
++
++ while (1) {
++ unsigned int c_expires = expires;
++
++ ret = ct_sip_parse_header_uri(ct, *dptr, &dataoff, *datalen,
++ SIP_HDR_CONTACT, &in_contact,
++ &matchoff, &matchlen,
++ &addr, &port);
++ if (ret < 0)
++ return NF_DROP;
++ else if (ret == 0)
++ break;
++
++ /* We don't support third-party registrations */
++ if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3, &addr))
++ continue;
++
++ ret = ct_sip_parse_numerical_param(ct, *dptr,
++ matchoff + matchlen,
++ *datalen, "expires=",
++ NULL, NULL, &c_expires);
++ if (ret < 0)
++ return NF_DROP;
++ if (c_expires == 0)
++ break;
++ if (refresh_signalling_expectation(ct, &addr, port, c_expires))
++ return NF_ACCEPT;
++ }
++
++flush:
++ flush_expectations(ct, false);
++ return NF_ACCEPT;
++}
++
++static const struct sip_handler sip_handlers[] = {
++ SIP_HANDLER("INVITE", process_sdp, process_invite_response),
++ SIP_HANDLER("UPDATE", process_sdp, process_update_response),
++ SIP_HANDLER("ACK", process_sdp, NULL),
++ SIP_HANDLER("PRACK", process_sdp, process_prack_response),
++ SIP_HANDLER("BYE", process_bye_request, NULL),
++ SIP_HANDLER("REGISTER", process_register_request, process_register_response),
++};
++
++static int process_sip_response(struct sk_buff *skb,
++ const char **dptr, unsigned int *datalen)
++{
++ static const struct sip_handler *handler;
++ enum ip_conntrack_info ctinfo;
++ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++ unsigned int matchoff, matchlen;
++ unsigned int code, cseq, dataoff, i;
++
++ if (*datalen < strlen("SIP/2.0 200"))
++ return NF_ACCEPT;
++ code = simple_strtoul(*dptr + strlen("SIP/2.0 "), NULL, 10);
++ if (!code)
++ return NF_DROP;
++
++ if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CSEQ,
++ &matchoff, &matchlen) <= 0)
++ return NF_DROP;
++ cseq = simple_strtoul(*dptr + matchoff, NULL, 10);
++ if (!cseq)
++ return NF_DROP;
++ dataoff = matchoff + matchlen + 1;
++
++ for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) {
++ handler = &sip_handlers[i];
++ if (handler->response == NULL)
++ continue;
++ if (*datalen < dataoff + handler->len ||
++ strnicmp(*dptr + dataoff, handler->method, handler->len))
++ continue;
++ return handler->response(skb, dptr, datalen, cseq, code);
++ }
++ return NF_ACCEPT;
++}
++
++static int process_sip_request(struct sk_buff *skb,
++ const char **dptr, unsigned int *datalen)
++{
++ static const struct sip_handler *handler;
++ enum ip_conntrack_info ctinfo;
++ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++ unsigned int matchoff, matchlen;
++ unsigned int cseq, i;
++
++ for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) {
++ handler = &sip_handlers[i];
++ if (handler->request == NULL)
++ continue;
++ if (*datalen < handler->len ||
++ strnicmp(*dptr, handler->method, handler->len))
++ continue;
++
++ if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CSEQ,
++ &matchoff, &matchlen) <= 0)
++ return NF_DROP;
++ cseq = simple_strtoul(*dptr + matchoff, NULL, 10);
++ if (!cseq)
++ return NF_DROP;
++
++ return handler->request(skb, dptr, datalen, cseq);
++ }
++ return NF_ACCEPT;
++}
++
+ static int sip_help(struct sk_buff *skb,
+ unsigned int protoff,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo)
+ {
+- int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+- union nf_inet_addr addr;
+ unsigned int dataoff, datalen;
+ const char *dptr;
+- int ret = NF_ACCEPT;
+- unsigned int matchoff, matchlen;
+- u_int16_t port;
+- enum sip_header_pos pos;
++ int ret;
+ typeof(nf_nat_sip_hook) nf_nat_sip;
+
+ /* No Data ? */
+@@ -424,58 +1271,45 @@ static int sip_help(struct sk_buff *skb,
+ dptr = skb->data + dataoff;
+ else {
+ pr_debug("Copy of skbuff not supported yet.\n");
+- goto out;
+- }
+-
+- nf_nat_sip = rcu_dereference(nf_nat_sip_hook);
+- if (nf_nat_sip && ct->status & IPS_NAT_MASK) {
+- if (!nf_nat_sip(skb, ctinfo, ct, &dptr)) {
+- ret = NF_DROP;
+- goto out;
+- }
++ return NF_ACCEPT;
+ }
+
+ datalen = skb->len - dataoff;
+- if (datalen < sizeof("SIP/2.0 200") - 1)
+- goto out;
+-
+- /* RTP info only in some SDP pkts */
+- if (memcmp(dptr, "INVITE", sizeof("INVITE") - 1) != 0 &&
+- memcmp(dptr, "UPDATE", sizeof("UPDATE") - 1) != 0 &&
+- memcmp(dptr, "SIP/2.0 180", sizeof("SIP/2.0 180") - 1) != 0 &&
+- memcmp(dptr, "SIP/2.0 183", sizeof("SIP/2.0 183") - 1) != 0 &&
+- memcmp(dptr, "SIP/2.0 200", sizeof("SIP/2.0 200") - 1) != 0) {
+- goto out;
+- }
+- /* Get address and port from SDP packet. */
+- pos = family == AF_INET ? POS_CONNECTION_IP4 : POS_CONNECTION_IP6;
+- if (ct_sip_get_info(ct, dptr, datalen, &matchoff, &matchlen, pos) > 0) {
+-
+- /* We'll drop only if there are parse problems. */
+- if (!parse_addr(ct, dptr + matchoff, NULL, &addr,
+- dptr + datalen)) {
+- ret = NF_DROP;
+- goto out;
+- }
+- if (ct_sip_get_info(ct, dptr, datalen, &matchoff, &matchlen,
+- POS_MEDIA) > 0) {
++ if (datalen < strlen("SIP/2.0 200"))
++ return NF_ACCEPT;
+
+- port = simple_strtoul(dptr + matchoff, NULL, 10);
+- if (port < 1024) {
+- ret = NF_DROP;
+- goto out;
+- }
+- ret = set_expected_rtp(skb, ct, ctinfo, &addr,
+- htons(port), dptr);
+- }
++ if (strnicmp(dptr, "SIP/2.0 ", strlen("SIP/2.0 ")) != 0)
++ ret = process_sip_request(skb, &dptr, &datalen);
++ else
++ ret = process_sip_response(skb, &dptr, &datalen);
++
++ if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) {
++ nf_nat_sip = rcu_dereference(nf_nat_sip_hook);
++ if (nf_nat_sip && !nf_nat_sip(skb, &dptr, &datalen))
++ ret = NF_DROP;
+ }
+-out:
++
+ return ret;
+ }
+
+ static struct nf_conntrack_helper sip[MAX_PORTS][2] __read_mostly;
+ static char sip_names[MAX_PORTS][2][sizeof("sip-65535")] __read_mostly;
+
++static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1] = {
++ [SIP_EXPECT_SIGNALLING] = {
++ .max_expected = 1,
++ .timeout = 3 * 60,
++ },
++ [SIP_EXPECT_AUDIO] = {
++ .max_expected = 2 * IP_CT_DIR_MAX,
++ .timeout = 3 * 60,
++ },
++ [SIP_EXPECT_VIDEO] = {
++ .max_expected = 2 * IP_CT_DIR_MAX,
++ .timeout = 3 * 60,
++ },
++};
++
+ static void nf_conntrack_sip_fini(void)
+ {
+ int i, j;
+@@ -505,8 +1339,8 @@ static int __init nf_conntrack_sip_init(void)
+ for (j = 0; j < 2; j++) {
+ sip[i][j].tuple.dst.protonum = IPPROTO_UDP;
+ sip[i][j].tuple.src.u.udp.port = htons(ports[i]);
+- sip[i][j].max_expected = 2;
+- sip[i][j].timeout = 3 * 60; /* 3 minutes */
++ sip[i][j].expect_policy = sip_exp_policy;
++ sip[i][j].expect_class_max = SIP_EXPECT_MAX;
+ sip[i][j].me = THIS_MODULE;
+ sip[i][j].help = sip_help;
+
+diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
+index 8599068..b59871f 100644
+--- a/net/netfilter/nf_conntrack_standalone.c
++++ b/net/netfilter/nf_conntrack_standalone.c
+@@ -127,21 +127,14 @@ static int ct_seq_show(struct seq_file *s, void *v)
+ if (NF_CT_DIRECTION(hash))
+ return 0;
+
+- l3proto = __nf_ct_l3proto_find(ct->tuplehash[IP_CT_DIR_ORIGINAL]
+- .tuple.src.l3num);
+-
++ l3proto = __nf_ct_l3proto_find(nf_ct_l3num(ct));
+ NF_CT_ASSERT(l3proto);
+- l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_ORIGINAL]
+- .tuple.src.l3num,
+- ct->tuplehash[IP_CT_DIR_ORIGINAL]
+- .tuple.dst.protonum);
++ l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
+ NF_CT_ASSERT(l4proto);
+
+ if (seq_printf(s, "%-8s %u %-8s %u %ld ",
+- l3proto->name,
+- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num,
+- l4proto->name,
+- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,
++ l3proto->name, nf_ct_l3num(ct),
++ l4proto->name, nf_ct_protonum(ct),
+ timer_pending(&ct->timeout)
+ ? (long)(ct->timeout.expires - jiffies)/HZ : 0) != 0)
+ return -ENOSPC;
+@@ -293,8 +286,43 @@ static const struct file_operations ct_cpu_seq_fops = {
+ .open = ct_cpu_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = seq_release_private,
++ .release = seq_release,
+ };
++
++static int nf_conntrack_standalone_init_proc(void)
++{
++ struct proc_dir_entry *pde;
++
++ pde = proc_net_fops_create(&init_net, "nf_conntrack", 0440, &ct_file_ops);
++ if (!pde)
++ goto out_nf_conntrack;
++ pde = create_proc_entry("nf_conntrack", S_IRUGO, init_net.proc_net_stat);
++ if (!pde)
++ goto out_stat_nf_conntrack;
++ pde->proc_fops = &ct_cpu_seq_fops;
++ pde->owner = THIS_MODULE;
++ return 0;
++
++out_stat_nf_conntrack:
++ proc_net_remove(&init_net, "nf_conntrack");
++out_nf_conntrack:
++ return -ENOMEM;
++}
++
++static void nf_conntrack_standalone_fini_proc(void)
++{
++ remove_proc_entry("nf_conntrack", init_net.proc_net_stat);
++ proc_net_remove(&init_net, "nf_conntrack");
++}
++#else
++static int nf_conntrack_standalone_init_proc(void)
++{
++ return 0;
++}
++
++static void nf_conntrack_standalone_fini_proc(void)
++{
++}
+ #endif /* CONFIG_PROC_FS */
+
+ /* Sysctl support */
+@@ -390,60 +418,61 @@ static struct ctl_path nf_ct_path[] = {
+ };
+
+ EXPORT_SYMBOL_GPL(nf_ct_log_invalid);
++
++static int nf_conntrack_standalone_init_sysctl(void)
++{
++ nf_ct_sysctl_header =
++ register_sysctl_paths(nf_ct_path, nf_ct_netfilter_table);
++ if (nf_ct_sysctl_header == NULL) {
++ printk("nf_conntrack: can't register to sysctl.\n");
++ return -ENOMEM;
++ }
++ return 0;
++
++}
++
++static void nf_conntrack_standalone_fini_sysctl(void)
++{
++ unregister_sysctl_table(nf_ct_sysctl_header);
++}
++#else
++static int nf_conntrack_standalone_init_sysctl(void)
++{
++ return 0;
++}
++
++static void nf_conntrack_standalone_fini_sysctl(void)
++{
++}
+ #endif /* CONFIG_SYSCTL */
+
+ static int __init nf_conntrack_standalone_init(void)
+ {
+-#ifdef CONFIG_PROC_FS
+- struct proc_dir_entry *proc;
+-#endif
+- int ret = 0;
++ int ret;
+
+ ret = nf_conntrack_init();
+ if (ret < 0)
+- return ret;
+-
+-#ifdef CONFIG_PROC_FS
+- proc = proc_net_fops_create(&init_net, "nf_conntrack", 0440, &ct_file_ops);
+- if (!proc) goto cleanup_init;
+-
+- if (!proc_create("nf_conntrack", S_IRUGO,
+- init_net.proc_net_stat, &ct_cpu_seq_fops))
+- goto cleanup_proc;
+-#endif
+-#ifdef CONFIG_SYSCTL
+- nf_ct_sysctl_header = register_sysctl_paths(nf_ct_path,
+- nf_ct_netfilter_table);
+- if (nf_ct_sysctl_header == NULL) {
+- printk("nf_conntrack: can't register to sysctl.\n");
+- ret = -ENOMEM;
+- goto cleanup_proc_stat;
+- }
+-#endif
+- return ret;
++ goto out;
++ ret = nf_conntrack_standalone_init_proc();
++ if (ret < 0)
++ goto out_proc;
++ ret = nf_conntrack_standalone_init_sysctl();
++ if (ret < 0)
++ goto out_sysctl;
++ return 0;
+
+-#ifdef CONFIG_SYSCTL
+- cleanup_proc_stat:
+-#endif
+-#ifdef CONFIG_PROC_FS
+- remove_proc_entry("nf_conntrack", init_net. proc_net_stat);
+- cleanup_proc:
+- proc_net_remove(&init_net, "nf_conntrack");
+- cleanup_init:
+-#endif /* CNFIG_PROC_FS */
++out_sysctl:
++ nf_conntrack_standalone_fini_proc();
++out_proc:
+ nf_conntrack_cleanup();
++out:
+ return ret;
+ }
+
+ static void __exit nf_conntrack_standalone_fini(void)
+ {
+-#ifdef CONFIG_SYSCTL
+- unregister_sysctl_table(nf_ct_sysctl_header);
+-#endif
+-#ifdef CONFIG_PROC_FS
+- remove_proc_entry("nf_conntrack", init_net.proc_net_stat);
+- proc_net_remove(&init_net, "nf_conntrack");
+-#endif /* CNFIG_PROC_FS */
++ nf_conntrack_standalone_fini_sysctl();
++ nf_conntrack_standalone_fini_proc();
+ nf_conntrack_cleanup();
+ }
+
+diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c
+index bd2e800..f57f6e7 100644
+--- a/net/netfilter/nf_conntrack_tftp.c
++++ b/net/netfilter/nf_conntrack_tftp.c
+@@ -44,7 +44,6 @@ static int tftp_help(struct sk_buff *skb,
+ struct nf_conntrack_expect *exp;
+ struct nf_conntrack_tuple *tuple;
+ unsigned int ret = NF_ACCEPT;
+- int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ typeof(nf_nat_tftp_hook) nf_nat_tftp;
+
+ tfh = skb_header_pointer(skb, protoff + sizeof(struct udphdr),
+@@ -56,18 +55,20 @@ static int tftp_help(struct sk_buff *skb,
+ case TFTP_OPCODE_READ:
+ case TFTP_OPCODE_WRITE:
+ /* RRQ and WRQ works the same way */
+- NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+- NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
++ nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
++ nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
+
+ exp = nf_ct_expect_alloc(ct);
+ if (exp == NULL)
+ return NF_DROP;
+ tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
+- nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3,
++ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,
++ nf_ct_l3num(ct),
++ &tuple->src.u3, &tuple->dst.u3,
+ IPPROTO_UDP, NULL, &tuple->dst.u.udp.port);
+
+ pr_debug("expect: ");
+- NF_CT_DUMP_TUPLE(&exp->tuple);
++ nf_ct_dump_tuple(&exp->tuple);
+
+ nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook);
+ if (nf_nat_tftp && ct->status & IPS_NAT_MASK)
+@@ -92,6 +93,11 @@ static int tftp_help(struct sk_buff *skb,
+ static struct nf_conntrack_helper tftp[MAX_PORTS][2] __read_mostly;
+ static char tftp_names[MAX_PORTS][2][sizeof("tftp-65535")] __read_mostly;
+
++static const struct nf_conntrack_expect_policy tftp_exp_policy = {
++ .max_expected = 1,
++ .timeout = 5 * 60,
++};
++
+ static void nf_conntrack_tftp_fini(void)
+ {
+ int i, j;
+@@ -118,8 +124,7 @@ static int __init nf_conntrack_tftp_init(void)
+ for (j = 0; j < 2; j++) {
+ tftp[i][j].tuple.dst.protonum = IPPROTO_UDP;
+ tftp[i][j].tuple.src.u.udp.port = htons(ports[i]);
+- tftp[i][j].max_expected = 1;
+- tftp[i][j].timeout = 5 * 60; /* 5 minutes */
++ tftp[i][j].expect_policy = &tftp_exp_policy;
+ tftp[i][j].me = THIS_MODULE;
+ tftp[i][j].help = tftp_help;
+
+diff --git a/net/netfilter/nf_sockopt.c b/net/netfilter/nf_sockopt.c
+index 3dd4b3c..69d699f 100644
+--- a/net/netfilter/nf_sockopt.c
++++ b/net/netfilter/nf_sockopt.c
+@@ -65,7 +65,7 @@ static struct nf_sockopt_ops *nf_sockopt_find(struct sock *sk, int pf,
+ {
+ struct nf_sockopt_ops *ops;
+
+- if (sk->sk_net != &init_net)
++ if (sock_net(sk) != &init_net)
+ return ERR_PTR(-ENOPROTOOPT);
+
+ if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0)
+diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
+index 10522c0..2c9fe5c 100644
+--- a/net/netfilter/nfnetlink_queue.c
++++ b/net/netfilter/nfnetlink_queue.c
+@@ -557,7 +557,7 @@ nfqnl_rcv_dev_event(struct notifier_block *this,
+ {
+ struct net_device *dev = ptr;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ /* Drop any packets associated with the downed device */
+diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
+index a679208..f52f7f8 100644
+--- a/net/netfilter/x_tables.c
++++ b/net/netfilter/x_tables.c
+@@ -58,7 +58,7 @@ static struct xt_af *xt;
+ #define duprintf(format, args...)
+ #endif
+
+-static const char *xt_prefix[NPROTO] = {
++static const char *const xt_prefix[NPROTO] = {
+ [AF_INET] = "ip",
+ [AF_INET6] = "ip6",
+ [NF_ARP] = "arp",
+@@ -248,7 +248,7 @@ EXPORT_SYMBOL_GPL(xt_request_find_target);
+
+ static int match_revfn(int af, const char *name, u8 revision, int *bestp)
+ {
+- struct xt_match *m;
++ const struct xt_match *m;
+ int have_rev = 0;
+
+ list_for_each_entry(m, &xt[af].match, list) {
+@@ -264,7 +264,7 @@ static int match_revfn(int af, const char *name, u8 revision, int *bestp)
+
+ static int target_revfn(int af, const char *name, u8 revision, int *bestp)
+ {
+- struct xt_target *t;
++ const struct xt_target *t;
+ int have_rev = 0;
+
+ list_for_each_entry(t, &xt[af].target, list) {
+@@ -385,7 +385,7 @@ short xt_compat_calc_jump(int af, unsigned int offset)
+ }
+ EXPORT_SYMBOL_GPL(xt_compat_calc_jump);
+
+-int xt_compat_match_offset(struct xt_match *match)
++int xt_compat_match_offset(const struct xt_match *match)
+ {
+ u_int16_t csize = match->compatsize ? : match->matchsize;
+ return XT_ALIGN(match->matchsize) - COMPAT_XT_ALIGN(csize);
+@@ -395,7 +395,7 @@ EXPORT_SYMBOL_GPL(xt_compat_match_offset);
+ int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
+ unsigned int *size)
+ {
+- struct xt_match *match = m->u.kernel.match;
++ const struct xt_match *match = m->u.kernel.match;
+ struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m;
+ int pad, off = xt_compat_match_offset(match);
+ u_int16_t msize = cm->u.user.match_size;
+@@ -422,7 +422,7 @@ EXPORT_SYMBOL_GPL(xt_compat_match_from_user);
+ int xt_compat_match_to_user(struct xt_entry_match *m, void __user **dstptr,
+ unsigned int *size)
+ {
+- struct xt_match *match = m->u.kernel.match;
++ const struct xt_match *match = m->u.kernel.match;
+ struct compat_xt_entry_match __user *cm = *dstptr;
+ int off = xt_compat_match_offset(match);
+ u_int16_t msize = m->u.user.match_size - off;
+@@ -479,7 +479,7 @@ int xt_check_target(const struct xt_target *target, unsigned short family,
+ EXPORT_SYMBOL_GPL(xt_check_target);
+
+ #ifdef CONFIG_COMPAT
+-int xt_compat_target_offset(struct xt_target *target)
++int xt_compat_target_offset(const struct xt_target *target)
+ {
+ u_int16_t csize = target->compatsize ? : target->targetsize;
+ return XT_ALIGN(target->targetsize) - COMPAT_XT_ALIGN(csize);
+@@ -489,7 +489,7 @@ EXPORT_SYMBOL_GPL(xt_compat_target_offset);
+ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
+ unsigned int *size)
+ {
+- struct xt_target *target = t->u.kernel.target;
++ const struct xt_target *target = t->u.kernel.target;
+ struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t;
+ int pad, off = xt_compat_target_offset(target);
+ u_int16_t tsize = ct->u.user.target_size;
+@@ -515,7 +515,7 @@ EXPORT_SYMBOL_GPL(xt_compat_target_from_user);
+ int xt_compat_target_to_user(struct xt_entry_target *t, void __user **dstptr,
+ unsigned int *size)
+ {
+- struct xt_target *target = t->u.kernel.target;
++ const struct xt_target *target = t->u.kernel.target;
+ struct compat_xt_entry_target __user *ct = *dstptr;
+ int off = xt_compat_target_offset(target);
+ u_int16_t tsize = t->u.user.target_size - off;
+@@ -727,7 +727,7 @@ struct xt_names_priv {
+ static void *xt_table_seq_start(struct seq_file *seq, loff_t *pos)
+ {
+ struct xt_names_priv *priv = seq->private;
+- struct net *net = priv->p.net;
++ struct net *net = seq_file_net(seq);
+ int af = priv->af;
+
+ mutex_lock(&xt[af].mutex);
+@@ -737,7 +737,7 @@ static void *xt_table_seq_start(struct seq_file *seq, loff_t *pos)
+ static void *xt_table_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+ {
+ struct xt_names_priv *priv = seq->private;
+- struct net *net = priv->p.net;
++ struct net *net = seq_file_net(seq);
+ int af = priv->af;
+
+ return seq_list_next(v, &net->xt.tables[af], pos);
+diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c
+index 1faa913..211189e 100644
+--- a/net/netfilter/xt_CONNSECMARK.c
++++ b/net/netfilter/xt_CONNSECMARK.c
+@@ -55,7 +55,7 @@ static void secmark_save(const struct sk_buff *skb)
+ static void secmark_restore(struct sk_buff *skb)
+ {
+ if (!skb->secmark) {
+- struct nf_conn *ct;
++ const struct nf_conn *ct;
+ enum ip_conntrack_info ctinfo;
+
+ ct = nf_ct_get(skb, &ctinfo);
+diff --git a/net/netfilter/xt_RATEEST.c b/net/netfilter/xt_RATEEST.c
+index 24c73ba..64d6ad3 100644
+--- a/net/netfilter/xt_RATEEST.c
++++ b/net/netfilter/xt_RATEEST.c
+@@ -96,7 +96,7 @@ xt_rateest_tg_checkentry(const char *tablename,
+ void *targinfo,
+ unsigned int hook_mask)
+ {
+- struct xt_rateest_target_info *info = (void *)targinfo;
++ struct xt_rateest_target_info *info = targinfo;
+ struct xt_rateest *est;
+ struct {
+ struct nlattr opt;
+diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c
+index 3b01119..2e89a00 100644
+--- a/net/netfilter/xt_connlimit.c
++++ b/net/netfilter/xt_connlimit.c
+@@ -72,9 +72,7 @@ connlimit_iphash6(const union nf_inet_addr *addr,
+
+ static inline bool already_closed(const struct nf_conn *conn)
+ {
+- u_int16_t proto = conn->tuplehash[0].tuple.dst.protonum;
+-
+- if (proto == IPPROTO_TCP)
++ if (nf_ct_protonum(conn) == IPPROTO_TCP)
+ return conn->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT;
+ else
+ return 0;
+@@ -106,10 +104,10 @@ static int count_them(struct xt_connlimit_data *data,
+ const union nf_inet_addr *mask,
+ const struct xt_match *match)
+ {
+- struct nf_conntrack_tuple_hash *found;
++ const struct nf_conntrack_tuple_hash *found;
+ struct xt_connlimit_conn *conn;
+ struct xt_connlimit_conn *tmp;
+- struct nf_conn *found_ct;
++ const struct nf_conn *found_ct;
+ struct list_head *hash;
+ bool addit = true;
+ int matches = 0;
+@@ -256,7 +254,7 @@ connlimit_mt_check(const char *tablename, const void *ip,
+ static void
+ connlimit_mt_destroy(const struct xt_match *match, void *matchinfo)
+ {
+- struct xt_connlimit_info *info = matchinfo;
++ const struct xt_connlimit_info *info = matchinfo;
+ struct xt_connlimit_conn *conn;
+ struct xt_connlimit_conn *tmp;
+ struct list_head *hash = info->data->iphash;
+diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
+index 0c50b28..d61412f 100644
+--- a/net/netfilter/xt_conntrack.c
++++ b/net/netfilter/xt_conntrack.c
+@@ -65,7 +65,7 @@ conntrack_mt_v0(const struct sk_buff *skb, const struct net_device *in,
+ }
+
+ if (sinfo->flags & XT_CONNTRACK_PROTO &&
+- FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum !=
++ FWINV(nf_ct_protonum(ct) !=
+ sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum,
+ XT_CONNTRACK_PROTO))
+ return false;
+@@ -174,7 +174,7 @@ ct_proto_port_check(const struct xt_conntrack_mtinfo1 *info,
+
+ tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
+ if ((info->match_flags & XT_CONNTRACK_PROTO) &&
+- (tuple->dst.protonum == info->l4proto) ^
++ (nf_ct_protonum(ct) == info->l4proto) ^
+ !(info->invert_flags & XT_CONNTRACK_PROTO))
+ return false;
+
+diff --git a/net/netfilter/xt_dccp.c b/net/netfilter/xt_dccp.c
+index 667f45e..8b65221 100644
+--- a/net/netfilter/xt_dccp.c
++++ b/net/netfilter/xt_dccp.c
+@@ -98,7 +98,8 @@ dccp_mt(const struct sk_buff *skb, const struct net_device *in,
+ const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
+ {
+ const struct xt_dccp_info *info = matchinfo;
+- struct dccp_hdr _dh, *dh;
++ const struct dccp_hdr *dh;
++ struct dccp_hdr _dh;
+
+ if (offset)
+ return false;
+diff --git a/net/netfilter/xt_esp.c b/net/netfilter/xt_esp.c
+index 71c7c37..a133eb9 100644
+--- a/net/netfilter/xt_esp.c
++++ b/net/netfilter/xt_esp.c
+@@ -47,7 +47,8 @@ esp_mt(const struct sk_buff *skb, const struct net_device *in,
+ const struct net_device *out, const struct xt_match *match,
+ const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
+ {
+- struct ip_esp_hdr _esp, *eh;
++ const struct ip_esp_hdr *eh;
++ struct ip_esp_hdr _esp;
+ const struct xt_esp *espinfo = matchinfo;
+
+ /* Must not be a fragment. */
+diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c
+index 31daa81..fd88c48 100644
+--- a/net/netfilter/xt_multiport.c
++++ b/net/netfilter/xt_multiport.c
+@@ -100,7 +100,8 @@ multiport_mt_v0(const struct sk_buff *skb, const struct net_device *in,
+ const void *matchinfo, int offset, unsigned int protoff,
+ bool *hotdrop)
+ {
+- __be16 _ports[2], *pptr;
++ const __be16 *pptr;
++ __be16 _ports[2];
+ const struct xt_multiport *multiinfo = matchinfo;
+
+ if (offset)
+@@ -126,7 +127,8 @@ multiport_mt(const struct sk_buff *skb, const struct net_device *in,
+ const void *matchinfo, int offset, unsigned int protoff,
+ bool *hotdrop)
+ {
+- __be16 _ports[2], *pptr;
++ const __be16 *pptr;
++ __be16 _ports[2];
+ const struct xt_multiport_v1 *multiinfo = matchinfo;
+
+ if (offset)
+diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c
+index 9e918ad..d351582 100644
+--- a/net/netfilter/xt_policy.c
++++ b/net/netfilter/xt_policy.c
+@@ -136,7 +136,7 @@ policy_mt_check(const char *tablename, const void *ip_void,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
+ {
+- struct xt_policy_info *info = matchinfo;
++ const struct xt_policy_info *info = matchinfo;
+
+ if (!(info->flags & (XT_POLICY_MATCH_IN|XT_POLICY_MATCH_OUT))) {
+ printk(KERN_ERR "xt_policy: neither incoming nor "
+diff --git a/net/netfilter/xt_rateest.c b/net/netfilter/xt_rateest.c
+index fdb86a5..ebd84f1 100644
+--- a/net/netfilter/xt_rateest.c
++++ b/net/netfilter/xt_rateest.c
+@@ -86,7 +86,7 @@ static bool xt_rateest_mt_checkentry(const char *tablename,
+ void *matchinfo,
+ unsigned int hook_mask)
+ {
+- struct xt_rateest_match_info *info = (void *)matchinfo;
++ struct xt_rateest_match_info *info = matchinfo;
+ struct xt_rateest *est1, *est2;
+
+ if (hweight32(info->flags & (XT_RATEEST_MATCH_ABS |
+@@ -130,7 +130,7 @@ err1:
+ static void xt_rateest_mt_destroy(const struct xt_match *match,
+ void *matchinfo)
+ {
+- struct xt_rateest_match_info *info = (void *)matchinfo;
++ struct xt_rateest_match_info *info = matchinfo;
+
+ xt_rateest_put(info->est1);
+ if (info->est2)
+diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c
+index b718ec6..e6e4681 100644
+--- a/net/netfilter/xt_sctp.c
++++ b/net/netfilter/xt_sctp.c
+@@ -46,7 +46,8 @@ match_packet(const struct sk_buff *skb,
+ bool *hotdrop)
+ {
+ u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
+- sctp_chunkhdr_t _sch, *sch;
++ const sctp_chunkhdr_t *sch;
++ sctp_chunkhdr_t _sch;
+ int chunk_match_type = info->chunk_match_type;
+ const struct xt_sctp_flag_info *flag_info = info->flag_info;
+ int flag_count = info->flag_count;
+@@ -121,7 +122,8 @@ sctp_mt(const struct sk_buff *skb, const struct net_device *in,
+ const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
+ {
+ const struct xt_sctp_info *info = matchinfo;
+- sctp_sctphdr_t _sh, *sh;
++ const sctp_sctphdr_t *sh;
++ sctp_sctphdr_t _sh;
+
+ if (offset) {
+ duprintf("Dropping non-first fragment.. FIXME\n");
+diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c
+index d7a5b27..6771bf0 100644
+--- a/net/netfilter/xt_tcpmss.c
++++ b/net/netfilter/xt_tcpmss.c
+@@ -31,9 +31,11 @@ tcpmss_mt(const struct sk_buff *skb, const struct net_device *in,
+ bool *hotdrop)
+ {
+ const struct xt_tcpmss_match_info *info = matchinfo;
+- struct tcphdr _tcph, *th;
++ const struct tcphdr *th;
++ struct tcphdr _tcph;
+ /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
+- u8 _opt[15 * 4 - sizeof(_tcph)], *op;
++ const u_int8_t *op;
++ u8 _opt[15 * 4 - sizeof(_tcph)];
+ unsigned int i, optlen;
+
+ /* If we don't have the whole header, drop packet. */
+diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
+index 4fa3b66..951b06b 100644
+--- a/net/netfilter/xt_tcpudp.c
++++ b/net/netfilter/xt_tcpudp.c
+@@ -42,7 +42,8 @@ tcp_find_option(u_int8_t option,
+ bool *hotdrop)
+ {
+ /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
+- u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
++ const u_int8_t *op;
++ u_int8_t _opt[60 - sizeof(struct tcphdr)];
+ unsigned int i;
+
+ duprintf("tcp_match: finding option\n");
+@@ -72,7 +73,8 @@ tcp_mt(const struct sk_buff *skb, const struct net_device *in,
+ const struct net_device *out, const struct xt_match *match,
+ const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
+ {
+- struct tcphdr _tcph, *th;
++ const struct tcphdr *th;
++ struct tcphdr _tcph;
+ const struct xt_tcp *tcpinfo = matchinfo;
+
+ if (offset) {
+@@ -144,7 +146,8 @@ udp_mt(const struct sk_buff *skb, const struct net_device *in,
+ const struct net_device *out, const struct xt_match *match,
+ const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
+ {
+- struct udphdr _udph, *uh;
++ const struct udphdr *uh;
++ struct udphdr _udph;
+ const struct xt_udp *udpinfo = matchinfo;
+
+ /* Must not be a fragment. */
+diff --git a/net/netfilter/xt_time.c b/net/netfilter/xt_time.c
+index 9fa2e08..ed76baa 100644
+--- a/net/netfilter/xt_time.c
++++ b/net/netfilter/xt_time.c
+@@ -223,7 +223,7 @@ time_mt_check(const char *tablename, const void *ip,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
+ {
+- struct xt_time_info *info = matchinfo;
++ const struct xt_time_info *info = matchinfo;
+
+ if (info->daytime_start > XT_TIME_MAX_DAYTIME ||
+ info->daytime_stop > XT_TIME_MAX_DAYTIME) {
+diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
+index 4478f2f..d282ad1 100644
+--- a/net/netlabel/netlabel_unlabeled.c
++++ b/net/netlabel/netlabel_unlabeled.c
+@@ -954,7 +954,7 @@ static int netlbl_unlhsh_netdev_handler(struct notifier_block *this,
+ struct net_device *dev = ptr;
+ struct netlbl_unlhsh_iface *iface = NULL;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ /* XXX - should this be a check for NETDEV_DOWN or _UNREGISTER? */
+@@ -1339,6 +1339,10 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
+
+ if (iface->ifindex > 0) {
+ dev = dev_get_by_index(&init_net, iface->ifindex);
++ if (!dev) {
++ ret_val = -ENODEV;
++ goto list_cb_failure;
++ }
+ ret_val = nla_put_string(cb_arg->skb,
+ NLBL_UNLABEL_A_IFACE, dev->name);
+ dev_put(dev);
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+index 1ab0da2..46f3e44 100644
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -54,7 +54,6 @@
+ #include <linux/mm.h>
+ #include <linux/types.h>
+ #include <linux/audit.h>
+-#include <linux/selinux.h>
+ #include <linux/mutex.h>
+
+ #include <net/net_namespace.h>
+@@ -228,7 +227,7 @@ static inline struct sock *netlink_lookup(struct net *net, int protocol,
+ read_lock(&nl_table_lock);
+ head = nl_pid_hashfn(hash, pid);
+ sk_for_each(sk, node, head) {
+- if ((sk->sk_net == net) && (nlk_sk(sk)->pid == pid)) {
++ if (net_eq(sock_net(sk), net) && (nlk_sk(sk)->pid == pid)) {
+ sock_hold(sk);
+ goto found;
+ }
+@@ -348,7 +347,7 @@ static int netlink_insert(struct sock *sk, struct net *net, u32 pid)
+ head = nl_pid_hashfn(hash, pid);
+ len = 0;
+ sk_for_each(osk, node, head) {
+- if ((osk->sk_net == net) && (nlk_sk(osk)->pid == pid))
++ if (net_eq(sock_net(osk), net) && (nlk_sk(osk)->pid == pid))
+ break;
+ len++;
+ }
+@@ -486,7 +485,7 @@ static int netlink_release(struct socket *sock)
+
+ if (nlk->pid && !nlk->subscriptions) {
+ struct netlink_notify n = {
+- .net = sk->sk_net,
++ .net = sock_net(sk),
+ .protocol = sk->sk_protocol,
+ .pid = nlk->pid,
+ };
+@@ -518,7 +517,7 @@ static int netlink_release(struct socket *sock)
+ static int netlink_autobind(struct socket *sock)
+ {
+ struct sock *sk = sock->sk;
+- struct net *net = sk->sk_net;
++ struct net *net = sock_net(sk);
+ struct nl_pid_hash *hash = &nl_table[sk->sk_protocol].hash;
+ struct hlist_head *head;
+ struct sock *osk;
+@@ -532,7 +531,7 @@ retry:
+ netlink_table_grab();
+ head = nl_pid_hashfn(hash, pid);
+ sk_for_each(osk, node, head) {
+- if ((osk->sk_net != net))
++ if (!net_eq(sock_net(osk), net))
+ continue;
+ if (nlk_sk(osk)->pid == pid) {
+ /* Bind collision, search negative pid values. */
+@@ -611,7 +610,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
+ int addr_len)
+ {
+ struct sock *sk = sock->sk;
+- struct net *net = sk->sk_net;
++ struct net *net = sock_net(sk);
+ struct netlink_sock *nlk = nlk_sk(sk);
+ struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr;
+ int err;
+@@ -720,7 +719,7 @@ static struct sock *netlink_getsockbypid(struct sock *ssk, u32 pid)
+ struct sock *sock;
+ struct netlink_sock *nlk;
+
+- sock = netlink_lookup(ssk->sk_net, ssk->sk_protocol, pid);
++ sock = netlink_lookup(sock_net(ssk), ssk->sk_protocol, pid);
+ if (!sock)
+ return ERR_PTR(-ECONNREFUSED);
+
+@@ -886,6 +885,13 @@ retry:
+ if (netlink_is_kernel(sk))
+ return netlink_unicast_kernel(sk, skb);
+
++ if (sk_filter(sk, skb)) {
++ int err = skb->len;
++ kfree_skb(skb);
++ sock_put(sk);
++ return err;
++ }
++
+ err = netlink_attachskb(sk, skb, nonblock, &timeo, ssk);
+ if (err == 1)
+ goto retry;
+@@ -955,7 +961,7 @@ static inline int do_one_broadcast(struct sock *sk,
+ !test_bit(p->group - 1, nlk->groups))
+ goto out;
+
+- if ((sk->sk_net != p->net))
++ if (!net_eq(sock_net(sk), p->net))
+ goto out;
+
+ if (p->failure) {
+@@ -980,6 +986,9 @@ static inline int do_one_broadcast(struct sock *sk,
+ netlink_overrun(sk);
+ /* Clone failed. Notify ALL listeners. */
+ p->failure = 1;
++ } else if (sk_filter(sk, p->skb2)) {
++ kfree_skb(p->skb2);
++ p->skb2 = NULL;
+ } else if ((val = netlink_broadcast_deliver(sk, p->skb2)) < 0) {
+ netlink_overrun(sk);
+ } else {
+@@ -996,7 +1005,7 @@ out:
+ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid,
+ u32 group, gfp_t allocation)
+ {
+- struct net *net = ssk->sk_net;
++ struct net *net = sock_net(ssk);
+ struct netlink_broadcast_data info;
+ struct hlist_node *node;
+ struct sock *sk;
+@@ -1054,7 +1063,7 @@ static inline int do_one_set_err(struct sock *sk,
+ if (sk == p->exclude_sk)
+ goto out;
+
+- if (sk->sk_net != p->exclude_sk->sk_net)
++ if (sock_net(sk) != sock_net(p->exclude_sk))
+ goto out;
+
+ if (nlk->pid == p->pid || p->group - 1 >= nlk->ngroups ||
+@@ -1239,7 +1248,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
+ NETLINK_CB(skb).pid = nlk->pid;
+ NETLINK_CB(skb).dst_group = dst_group;
+ NETLINK_CB(skb).loginuid = audit_get_loginuid(current);
+- selinux_get_task_sid(current, &(NETLINK_CB(skb).sid));
++ security_task_getsecid(current, &(NETLINK_CB(skb).sid));
+ memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
+
+ /* What can I do? Netlink is asynchronous, so that
+@@ -1344,22 +1353,6 @@ static void netlink_data_ready(struct sock *sk, int len)
+ * queueing.
+ */
+
+-static void __netlink_release(struct sock *sk)
+-{
+- /*
+- * Last sock_put should drop referrence to sk->sk_net. It has already
+- * been dropped in netlink_kernel_create. Taking referrence to stopping
+- * namespace is not an option.
+- * Take referrence to a socket to remove it from netlink lookup table
+- * _alive_ and after that destroy it in the context of init_net.
+- */
+-
+- sock_hold(sk);
+- sock_release(sk->sk_socket);
+- sk->sk_net = get_net(&init_net);
+- sock_put(sk);
+-}
+-
+ struct sock *
+ netlink_kernel_create(struct net *net, int unit, unsigned int groups,
+ void (*input)(struct sk_buff *skb),
+@@ -1388,8 +1381,7 @@ netlink_kernel_create(struct net *net, int unit, unsigned int groups,
+ goto out_sock_release_nosk;
+
+ sk = sock->sk;
+- put_net(sk->sk_net);
+- sk->sk_net = net;
++ sk_change_net(sk, net);
+
+ if (groups < 32)
+ groups = 32;
+@@ -1424,7 +1416,7 @@ netlink_kernel_create(struct net *net, int unit, unsigned int groups,
+
+ out_sock_release:
+ kfree(listeners);
+- __netlink_release(sk);
++ netlink_kernel_release(sk);
+ return NULL;
+
+ out_sock_release_nosk:
+@@ -1437,10 +1429,7 @@ EXPORT_SYMBOL(netlink_kernel_create);
+ void
+ netlink_kernel_release(struct sock *sk)
+ {
+- if (sk == NULL || sk->sk_socket == NULL)
+- return;
+-
+- __netlink_release(sk);
++ sk_release_kernel(sk);
+ }
+ EXPORT_SYMBOL(netlink_kernel_release);
+
+@@ -1553,8 +1542,13 @@ static int netlink_dump(struct sock *sk)
+
+ if (len > 0) {
+ mutex_unlock(nlk->cb_mutex);
+- skb_queue_tail(&sk->sk_receive_queue, skb);
+- sk->sk_data_ready(sk, len);
++
++ if (sk_filter(sk, skb))
++ kfree_skb(skb);
++ else {
++ skb_queue_tail(&sk->sk_receive_queue, skb);
++ sk->sk_data_ready(sk, skb->len);
++ }
+ return 0;
+ }
+
+@@ -1564,8 +1558,12 @@ static int netlink_dump(struct sock *sk)
+
+ memcpy(nlmsg_data(nlh), &len, sizeof(len));
+
+- skb_queue_tail(&sk->sk_receive_queue, skb);
+- sk->sk_data_ready(sk, skb->len);
++ if (sk_filter(sk, skb))
++ kfree_skb(skb);
++ else {
++ skb_queue_tail(&sk->sk_receive_queue, skb);
++ sk->sk_data_ready(sk, skb->len);
++ }
+
+ if (cb->done)
+ cb->done(cb);
+@@ -1602,7 +1600,7 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
+ atomic_inc(&skb->users);
+ cb->skb = skb;
+
+- sk = netlink_lookup(ssk->sk_net, ssk->sk_protocol, NETLINK_CB(skb).pid);
++ sk = netlink_lookup(sock_net(ssk), ssk->sk_protocol, NETLINK_CB(skb).pid);
+ if (sk == NULL) {
+ netlink_destroy_callback(cb);
+ return -ECONNREFUSED;
+@@ -1644,7 +1642,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err)
+ if (!skb) {
+ struct sock *sk;
+
+- sk = netlink_lookup(in_skb->sk->sk_net,
++ sk = netlink_lookup(sock_net(in_skb->sk),
+ in_skb->sk->sk_protocol,
+ NETLINK_CB(in_skb).pid);
+ if (sk) {
+@@ -1759,7 +1757,7 @@ static struct sock *netlink_seq_socket_idx(struct seq_file *seq, loff_t pos)
+
+ for (j = 0; j <= hash->mask; j++) {
+ sk_for_each(s, node, &hash->table[j]) {
+- if (iter->p.net != s->sk_net)
++ if (sock_net(s) != seq_file_net(seq))
+ continue;
+ if (off == pos) {
+ iter->link = i;
+@@ -1795,7 +1793,7 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+ s = v;
+ do {
+ s = sk_next(s);
+- } while (s && (iter->p.net != s->sk_net));
++ } while (s && sock_net(s) != seq_file_net(seq));
+ if (s)
+ return s;
+
+@@ -1807,7 +1805,7 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+
+ for (; j <= hash->mask; j++) {
+ s = sk_head(&hash->table[j]);
+- while (s && (iter->p.net != s->sk_net))
++ while (s && sock_net(s) != seq_file_net(seq))
+ s = sk_next(s);
+ if (s) {
+ iter->link = i;
+diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
+index 972250c..4bae8b9 100644
+--- a/net/netrom/af_netrom.c
++++ b/net/netrom/af_netrom.c
+@@ -106,7 +106,7 @@ static int nr_device_event(struct notifier_block *this, unsigned long event, voi
+ {
+ struct net_device *dev = (struct net_device *)ptr;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ if (event != NETDEV_DOWN)
+@@ -466,7 +466,7 @@ static struct sock *nr_make_new(struct sock *osk)
+ if (osk->sk_type != SOCK_SEQPACKET)
+ return NULL;
+
+- sk = sk_alloc(osk->sk_net, PF_NETROM, GFP_ATOMIC, osk->sk_prot);
++ sk = sk_alloc(sock_net(osk), PF_NETROM, GFP_ATOMIC, osk->sk_prot);
+ if (sk == NULL)
+ return NULL;
+
+diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
+index b8b827c..2507024 100644
+--- a/net/packet/af_packet.c
++++ b/net/packet/af_packet.c
+@@ -263,7 +263,7 @@ static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev, struct
+ if (skb->pkt_type == PACKET_LOOPBACK)
+ goto out;
+
+- if (dev->nd_net != sk->sk_net)
++ if (dev_net(dev) != sock_net(sk))
+ goto out;
+
+ if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+@@ -337,7 +337,7 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock,
+ */
+
+ saddr->spkt_device[13] = 0;
+- dev = dev_get_by_name(sk->sk_net, saddr->spkt_device);
++ dev = dev_get_by_name(sock_net(sk), saddr->spkt_device);
+ err = -ENODEV;
+ if (dev == NULL)
+ goto out_unlock;
+@@ -451,7 +451,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
+ sk = pt->af_packet_priv;
+ po = pkt_sk(sk);
+
+- if (dev->nd_net != sk->sk_net)
++ if (dev_net(dev) != sock_net(sk))
+ goto drop;
+
+ skb->dev = dev;
+@@ -568,7 +568,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
+ sk = pt->af_packet_priv;
+ po = pkt_sk(sk);
+
+- if (dev->nd_net != sk->sk_net)
++ if (dev_net(dev) != sock_net(sk))
+ goto drop;
+
+ if (dev->header_ops) {
+@@ -728,7 +728,7 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock,
+ }
+
+
+- dev = dev_get_by_index(sk->sk_net, ifindex);
++ dev = dev_get_by_index(sock_net(sk), ifindex);
+ err = -ENXIO;
+ if (dev == NULL)
+ goto out_unlock;
+@@ -800,7 +800,7 @@ static int packet_release(struct socket *sock)
+ if (!sk)
+ return 0;
+
+- net = sk->sk_net;
++ net = sock_net(sk);
+ po = pkt_sk(sk);
+
+ write_lock_bh(&net->packet.sklist_lock);
+@@ -914,7 +914,7 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr, int add
+ return -EINVAL;
+ strlcpy(name,uaddr->sa_data,sizeof(name));
+
+- dev = dev_get_by_name(sk->sk_net, name);
++ dev = dev_get_by_name(sock_net(sk), name);
+ if (dev) {
+ err = packet_do_bind(sk, dev, pkt_sk(sk)->num);
+ dev_put(dev);
+@@ -941,7 +941,7 @@ static int packet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len
+
+ if (sll->sll_ifindex) {
+ err = -ENODEV;
+- dev = dev_get_by_index(sk->sk_net, sll->sll_ifindex);
++ dev = dev_get_by_index(sock_net(sk), sll->sll_ifindex);
+ if (dev == NULL)
+ goto out;
+ }
+@@ -1135,7 +1135,7 @@ static int packet_getname_spkt(struct socket *sock, struct sockaddr *uaddr,
+ return -EOPNOTSUPP;
+
+ uaddr->sa_family = AF_PACKET;
+- dev = dev_get_by_index(sk->sk_net, pkt_sk(sk)->ifindex);
++ dev = dev_get_by_index(sock_net(sk), pkt_sk(sk)->ifindex);
+ if (dev) {
+ strlcpy(uaddr->sa_data, dev->name, 15);
+ dev_put(dev);
+@@ -1160,7 +1160,7 @@ static int packet_getname(struct socket *sock, struct sockaddr *uaddr,
+ sll->sll_family = AF_PACKET;
+ sll->sll_ifindex = po->ifindex;
+ sll->sll_protocol = po->num;
+- dev = dev_get_by_index(sk->sk_net, po->ifindex);
++ dev = dev_get_by_index(sock_net(sk), po->ifindex);
+ if (dev) {
+ sll->sll_hatype = dev->type;
+ sll->sll_halen = dev->addr_len;
+@@ -1212,7 +1212,7 @@ static int packet_mc_add(struct sock *sk, struct packet_mreq_max *mreq)
+ rtnl_lock();
+
+ err = -ENODEV;
+- dev = __dev_get_by_index(sk->sk_net, mreq->mr_ifindex);
++ dev = __dev_get_by_index(sock_net(sk), mreq->mr_ifindex);
+ if (!dev)
+ goto done;
+
+@@ -1266,7 +1266,7 @@ static int packet_mc_drop(struct sock *sk, struct packet_mreq_max *mreq)
+ if (--ml->count == 0) {
+ struct net_device *dev;
+ *mlp = ml->next;
+- dev = dev_get_by_index(sk->sk_net, ml->ifindex);
++ dev = dev_get_by_index(sock_net(sk), ml->ifindex);
+ if (dev) {
+ packet_dev_mc(dev, ml, -1);
+ dev_put(dev);
+@@ -1294,7 +1294,7 @@ static void packet_flush_mclist(struct sock *sk)
+ struct net_device *dev;
+
+ po->mclist = ml->next;
+- if ((dev = dev_get_by_index(sk->sk_net, ml->ifindex)) != NULL) {
++ if ((dev = dev_get_by_index(sock_net(sk), ml->ifindex)) != NULL) {
+ packet_dev_mc(dev, ml, -1);
+ dev_put(dev);
+ }
+@@ -1450,7 +1450,7 @@ static int packet_notifier(struct notifier_block *this, unsigned long msg, void
+ struct sock *sk;
+ struct hlist_node *node;
+ struct net_device *dev = data;
+- struct net *net = dev->nd_net;
++ struct net *net = dev_net(dev);
+
+ read_lock(&net->packet.sklist_lock);
+ sk_for_each(sk, node, &net->packet.sklist) {
+@@ -1540,7 +1540,7 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd,
+ case SIOCGIFDSTADDR:
+ case SIOCSIFDSTADDR:
+ case SIOCSIFFLAGS:
+- if (sk->sk_net != &init_net)
++ if (sock_net(sk) != &init_net)
+ return -ENOIOCTLCMD;
+ return inet_dgram_ops.ioctl(sock, cmd, arg);
+ #endif
+@@ -1658,7 +1658,7 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing
+ int err = 0;
+
+ if (req->tp_block_nr) {
+- int i, l;
++ int i;
+
+ /* Sanity tests and some calculations */
+
+@@ -1687,7 +1687,6 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing
+ if (unlikely(!pg_vec))
+ goto out;
+
+- l = 0;
+ for (i = 0; i < req->tp_block_nr; i++) {
+ char *ptr = pg_vec[i];
+ struct tpacket_hdr *header;
+diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
+index 063cbc5..1ebf652 100644
+--- a/net/rose/af_rose.c
++++ b/net/rose/af_rose.c
+@@ -197,7 +197,7 @@ static int rose_device_event(struct notifier_block *this, unsigned long event,
+ {
+ struct net_device *dev = (struct net_device *)ptr;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ if (event != NETDEV_DOWN)
+@@ -551,7 +551,7 @@ static struct sock *rose_make_new(struct sock *osk)
+ if (osk->sk_type != SOCK_SEQPACKET)
+ return NULL;
+
+- sk = sk_alloc(osk->sk_net, PF_ROSE, GFP_ATOMIC, &rose_proto);
++ sk = sk_alloc(sock_net(osk), PF_ROSE, GFP_ATOMIC, &rose_proto);
+ if (sk == NULL)
+ return NULL;
+
+@@ -760,8 +760,10 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
+
+ rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause,
+ &diagnostic);
+- if (!rose->neighbour)
+- return -ENETUNREACH;
++ if (!rose->neighbour) {
++ err = -ENETUNREACH;
++ goto out_release;
++ }
+
+ rose->lci = rose_new_lci(rose->neighbour);
+ if (!rose->lci) {
+diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
+index fb9359f..5053a53 100644
+--- a/net/rose/rose_route.c
++++ b/net/rose/rose_route.c
+@@ -857,7 +857,6 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
+ src_addr = (rose_address *)(skb->data + 9);
+ dest_addr = (rose_address *)(skb->data + 4);
+
+- spin_lock_bh(&rose_node_list_lock);
+ spin_lock_bh(&rose_neigh_list_lock);
+ spin_lock_bh(&rose_route_list_lock);
+
+@@ -1060,7 +1059,6 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
+ out:
+ spin_unlock_bh(&rose_route_list_lock);
+ spin_unlock_bh(&rose_neigh_list_lock);
+- spin_unlock_bh(&rose_node_list_lock);
+
+ return res;
+ }
+diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
+index 53fe94c..3e7318c 100644
+--- a/net/rxrpc/ar-internal.h
++++ b/net/rxrpc/ar-internal.h
+@@ -619,8 +619,8 @@ void _dbprintk(const char *fmt, ...)
+ {
+ }
+
+-#define kenter(FMT,...) dbgprintk("==> %s("FMT")",__FUNCTION__ ,##__VA_ARGS__)
+-#define kleave(FMT,...) dbgprintk("<== %s()"FMT"",__FUNCTION__ ,##__VA_ARGS__)
++#define kenter(FMT,...) dbgprintk("==> %s("FMT")",__func__ ,##__VA_ARGS__)
++#define kleave(FMT,...) dbgprintk("<== %s()"FMT"",__func__ ,##__VA_ARGS__)
+ #define kdebug(FMT,...) dbgprintk(" "FMT ,##__VA_ARGS__)
+ #define kproto(FMT,...) dbgprintk("### "FMT ,##__VA_ARGS__)
+ #define knet(FMT,...) dbgprintk("@@@ "FMT ,##__VA_ARGS__)
+@@ -671,8 +671,8 @@ do { \
+ } while (0)
+
+ #else
+-#define _enter(FMT,...) _dbprintk("==> %s("FMT")",__FUNCTION__ ,##__VA_ARGS__)
+-#define _leave(FMT,...) _dbprintk("<== %s()"FMT"",__FUNCTION__ ,##__VA_ARGS__)
++#define _enter(FMT,...) _dbprintk("==> %s("FMT")",__func__ ,##__VA_ARGS__)
++#define _leave(FMT,...) _dbprintk("<== %s()"FMT"",__func__ ,##__VA_ARGS__)
+ #define _debug(FMT,...) _dbprintk(" "FMT ,##__VA_ARGS__)
+ #define _proto(FMT,...) _dbprintk("### "FMT ,##__VA_ARGS__)
+ #define _net(FMT,...) _dbprintk("@@@ "FMT ,##__VA_ARGS__)
+diff --git a/net/rxrpc/ar-proc.c b/net/rxrpc/ar-proc.c
+index 83eda24..017322e 100644
+--- a/net/rxrpc/ar-proc.c
++++ b/net/rxrpc/ar-proc.c
+@@ -103,7 +103,7 @@ const struct file_operations rxrpc_call_seq_fops = {
+ .open = rxrpc_call_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = seq_release_private,
++ .release = seq_release,
+ };
+
+ /*
+@@ -188,5 +188,5 @@ const struct file_operations rxrpc_connection_seq_fops = {
+ .open = rxrpc_connection_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+- .release = seq_release_private,
++ .release = seq_release,
+ };
+diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
+index 6d38a81..ba3f6e4 100644
+--- a/net/rxrpc/rxkad.c
++++ b/net/rxrpc/rxkad.c
+@@ -493,8 +493,8 @@ static int rxkad_verify_packet(const struct rxrpc_call *call,
+ __be32 x[2];
+ } tmpbuf __attribute__((aligned(8))); /* must all be in same page */
+ __be32 x;
+- u16 y;
+ __be16 cksum;
++ u32 y;
+ int ret;
+
+ sp = rxrpc_skb(skb);
+diff --git a/net/sched/act_api.c b/net/sched/act_api.c
+index 0b8eb23..74e662c 100644
+--- a/net/sched/act_api.c
++++ b/net/sched/act_api.c
+@@ -951,7 +951,7 @@ done:
+
+ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct nlattr *tca[TCA_ACT_MAX + 1];
+ u32 pid = skb ? NETLINK_CB(skb).pid : 0;
+ int ret = 0, ovr = 0;
+@@ -1029,7 +1029,7 @@ find_dump_kind(struct nlmsghdr *n)
+ static int
+ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct nlmsghdr *nlh;
+ unsigned char *b = skb_tail_pointer(skb);
+ struct nlattr *nest;
+diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
+index fbde461..64b2d13 100644
+--- a/net/sched/act_simple.c
++++ b/net/sched/act_simple.c
+@@ -115,7 +115,7 @@ static int tcf_simp_init(struct nlattr *nla, struct nlattr *est,
+ return -EINVAL;
+
+ datalen = nla_len(tb[TCA_DEF_DATA]);
+- if (datalen <= 0)
++ if (datalen == 0)
+ return -EINVAL;
+
+ pc = tcf_hash_check(parm->index, a, bind, &simp_hash_info);
+diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
+index 0fbedca..1086df7 100644
+--- a/net/sched/cls_api.c
++++ b/net/sched/cls_api.c
+@@ -118,7 +118,7 @@ static inline u32 tcf_auto_prio(struct tcf_proto *tp)
+
+ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct nlattr *tca[TCA_MAX + 1];
+ struct tcmsg *t;
+ u32 protocol;
+@@ -389,7 +389,7 @@ static int tcf_node_dump(struct tcf_proto *tp, unsigned long n,
+
+ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ int t;
+ int s_t;
+ struct net_device *dev;
+diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
+index 3da4129..72cf86e 100644
+--- a/net/sched/em_meta.c
++++ b/net/sched/em_meta.c
+@@ -256,10 +256,10 @@ META_COLLECTOR(int_rtclassid)
+
+ META_COLLECTOR(int_rtiif)
+ {
+- if (unlikely(skb->dst == NULL))
++ if (unlikely(skb->rtable == NULL))
+ *err = -1;
+ else
+- dst->value = ((struct rtable*) skb->dst)->fl.iif;
++ dst->value = skb->rtable->fl.iif;
+ }
+
+ /**************************************************************************
+diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
+index fc8708a..c40773c 100644
+--- a/net/sched/sch_api.c
++++ b/net/sched/sch_api.c
+@@ -608,7 +608,7 @@ check_loop_fn(struct Qdisc *q, unsigned long cl, struct qdisc_walker *w)
+
+ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct tcmsg *tcm = NLMSG_DATA(n);
+ struct nlattr *tca[TCA_MAX + 1];
+ struct net_device *dev;
+@@ -677,7 +677,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+
+ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct tcmsg *tcm;
+ struct nlattr *tca[TCA_MAX + 1];
+ struct net_device *dev;
+@@ -896,7 +896,7 @@ err_out:
+
+ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ int idx, q_idx;
+ int s_idx, s_q_idx;
+ struct net_device *dev;
+@@ -948,7 +948,7 @@ done:
+
+ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ struct tcmsg *tcm = NLMSG_DATA(n);
+ struct nlattr *tca[TCA_MAX + 1];
+ struct net_device *dev;
+@@ -1142,7 +1142,7 @@ static int qdisc_class_dump(struct Qdisc *q, unsigned long cl, struct qdisc_walk
+
+ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+- struct net *net = skb->sk->sk_net;
++ struct net *net = sock_net(skb->sk);
+ int t;
+ int s_t;
+ struct net_device *dev;
+diff --git a/net/sctp/associola.c b/net/sctp/associola.c
+index d29f792..b4cd2b7 100644
+--- a/net/sctp/associola.c
++++ b/net/sctp/associola.c
+@@ -718,12 +718,11 @@ struct sctp_transport *sctp_assoc_lookup_paddr(
+ const union sctp_addr *address)
+ {
+ struct sctp_transport *t;
+- struct list_head *pos;
+
+ /* Cycle through all transports searching for a peer address. */
+
+- list_for_each(pos, &asoc->peer.transport_addr_list) {
+- t = list_entry(pos, struct sctp_transport, transports);
++ list_for_each_entry(t, &asoc->peer.transport_addr_list,
++ transports) {
+ if (sctp_cmp_addr_exact(address, &t->ipaddr))
+ return t;
+ }
+@@ -762,7 +761,6 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
+ struct sctp_transport *second;
+ struct sctp_ulpevent *event;
+ struct sockaddr_storage addr;
+- struct list_head *pos;
+ int spc_state = 0;
+
+ /* Record the transition on the transport. */
+@@ -814,8 +812,8 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
+ */
+ first = NULL; second = NULL;
+
+- list_for_each(pos, &asoc->peer.transport_addr_list) {
+- t = list_entry(pos, struct sctp_transport, transports);
++ list_for_each_entry(t, &asoc->peer.transport_addr_list,
++ transports) {
+
+ if ((t->state == SCTP_INACTIVE) ||
+ (t->state == SCTP_UNCONFIRMED))
+@@ -932,7 +930,6 @@ struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *asoc,
+ {
+ struct sctp_transport *active;
+ struct sctp_transport *match;
+- struct list_head *entry, *pos;
+ struct sctp_transport *transport;
+ struct sctp_chunk *chunk;
+ __be32 key = htonl(tsn);
+@@ -956,8 +953,8 @@ struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *asoc,
+
+ active = asoc->peer.active_path;
+
+- list_for_each(entry, &active->transmitted) {
+- chunk = list_entry(entry, struct sctp_chunk, transmitted_list);
++ list_for_each_entry(chunk, &active->transmitted,
++ transmitted_list) {
+
+ if (key == chunk->subh.data_hdr->tsn) {
+ match = active;
+@@ -966,14 +963,13 @@ struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *asoc,
+ }
+
+ /* If not found, go search all the other transports. */
+- list_for_each(pos, &asoc->peer.transport_addr_list) {
+- transport = list_entry(pos, struct sctp_transport, transports);
++ list_for_each_entry(transport, &asoc->peer.transport_addr_list,
++ transports) {
+
+ if (transport == active)
+ break;
+- list_for_each(entry, &transport->transmitted) {
+- chunk = list_entry(entry, struct sctp_chunk,
+- transmitted_list);
++ list_for_each_entry(chunk, &transport->transmitted,
++ transmitted_list) {
+ if (key == chunk->subh.data_hdr->tsn) {
+ match = transport;
+ goto out;
+@@ -1154,9 +1150,8 @@ void sctp_assoc_update(struct sctp_association *asoc,
+
+ } else {
+ /* Add any peer addresses from the new association. */
+- list_for_each(pos, &new->peer.transport_addr_list) {
+- trans = list_entry(pos, struct sctp_transport,
+- transports);
++ list_for_each_entry(trans, &new->peer.transport_addr_list,
++ transports) {
+ if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr))
+ sctp_assoc_add_peer(asoc, &trans->ipaddr,
+ GFP_ATOMIC, trans->state);
+@@ -1306,15 +1301,14 @@ struct sctp_transport *sctp_assoc_choose_shutdown_transport(
+ void sctp_assoc_sync_pmtu(struct sctp_association *asoc)
+ {
+ struct sctp_transport *t;
+- struct list_head *pos;
+ __u32 pmtu = 0;
+
+ if (!asoc)
+ return;
+
+ /* Get the lowest pmtu of all the transports. */
+- list_for_each(pos, &asoc->peer.transport_addr_list) {
+- t = list_entry(pos, struct sctp_transport, transports);
++ list_for_each_entry(t, &asoc->peer.transport_addr_list,
++ transports) {
+ if (t->pmtu_pending && t->dst) {
+ sctp_transport_update_pmtu(t, dst_mtu(t->dst));
+ t->pmtu_pending = 0;
+@@ -1330,7 +1324,7 @@ void sctp_assoc_sync_pmtu(struct sctp_association *asoc)
+ }
+
+ SCTP_DEBUG_PRINTK("%s: asoc:%p, pmtu:%d, frag_point:%d\n",
+- __FUNCTION__, asoc, asoc->pathmtu, asoc->frag_point);
++ __func__, asoc, asoc->pathmtu, asoc->frag_point);
+ }
+
+ /* Should we send a SACK to update our peer? */
+@@ -1370,7 +1364,7 @@ void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned len)
+ }
+
+ SCTP_DEBUG_PRINTK("%s: asoc %p rwnd increased by %d to (%u, %u) "
+- "- %u\n", __FUNCTION__, asoc, len, asoc->rwnd,
++ "- %u\n", __func__, asoc, len, asoc->rwnd,
+ asoc->rwnd_over, asoc->a_rwnd);
+
+ /* Send a window update SACK if the rwnd has increased by at least the
+@@ -1381,7 +1375,7 @@ void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned len)
+ if (sctp_peer_needs_update(asoc)) {
+ asoc->a_rwnd = asoc->rwnd;
+ SCTP_DEBUG_PRINTK("%s: Sending window update SACK- asoc: %p "
+- "rwnd: %u a_rwnd: %u\n", __FUNCTION__,
++ "rwnd: %u a_rwnd: %u\n", __func__,
+ asoc, asoc->rwnd, asoc->a_rwnd);
+ sack = sctp_make_sack(asoc);
+ if (!sack)
+@@ -1410,7 +1404,7 @@ void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned len)
+ asoc->rwnd = 0;
+ }
+ SCTP_DEBUG_PRINTK("%s: asoc %p rwnd decreased by %d to (%u, %u)\n",
+- __FUNCTION__, asoc, len, asoc->rwnd,
++ __func__, asoc, len, asoc->rwnd,
+ asoc->rwnd_over);
+ }
+
+diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
+index ceefda0..80e6df0 100644
+--- a/net/sctp/bind_addr.c
++++ b/net/sctp/bind_addr.c
+@@ -67,15 +67,13 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
+ int flags)
+ {
+ struct sctp_sockaddr_entry *addr;
+- struct list_head *pos;
+ int error = 0;
+
+ /* All addresses share the same port. */
+ dest->port = src->port;
+
+ /* Extract the addresses which are relevant for this scope. */
+- list_for_each(pos, &src->address_list) {
+- addr = list_entry(pos, struct sctp_sockaddr_entry, list);
++ list_for_each_entry(addr, &src->address_list, list) {
+ error = sctp_copy_one_addr(dest, &addr->a, scope,
+ gfp, flags);
+ if (error < 0)
+@@ -87,9 +85,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
+ * the assumption that we must be sitting behind a NAT.
+ */
+ if (list_empty(&dest->address_list) && (SCTP_SCOPE_GLOBAL == scope)) {
+- list_for_each(pos, &src->address_list) {
+- addr = list_entry(pos, struct sctp_sockaddr_entry,
+- list);
++ list_for_each_entry(addr, &src->address_list, list) {
+ error = sctp_copy_one_addr(dest, &addr->a,
+ SCTP_SCOPE_LINK, gfp,
+ flags);
+@@ -115,14 +111,12 @@ int sctp_bind_addr_dup(struct sctp_bind_addr *dest,
+ gfp_t gfp)
+ {
+ struct sctp_sockaddr_entry *addr;
+- struct list_head *pos;
+ int error = 0;
+
+ /* All addresses share the same port. */
+ dest->port = src->port;
+
+- list_for_each(pos, &src->address_list) {
+- addr = list_entry(pos, struct sctp_sockaddr_entry, list);
++ list_for_each_entry(addr, &src->address_list, list) {
+ error = sctp_add_bind_addr(dest, &addr->a, 1, gfp);
+ if (error < 0)
+ break;
+@@ -273,8 +267,7 @@ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp,
+
+ addrparms = retval;
+
+- list_for_each(pos, &bp->address_list) {
+- addr = list_entry(pos, struct sctp_sockaddr_entry, list);
++ list_for_each_entry(addr, &bp->address_list, list) {
+ af = sctp_get_af_specific(addr->a.v4.sin_family);
+ len = af->to_addr_param(&addr->a, &rawaddr);
+ memcpy(addrparms.v, &rawaddr, len);
+diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
+index 4d3128f..1748ef9 100644
+--- a/net/sctp/chunk.c
++++ b/net/sctp/chunk.c
+@@ -66,9 +66,10 @@ SCTP_STATIC struct sctp_datamsg *sctp_datamsg_new(gfp_t gfp)
+ {
+ struct sctp_datamsg *msg;
+ msg = kmalloc(sizeof(struct sctp_datamsg), gfp);
+- if (msg)
++ if (msg) {
+ sctp_datamsg_init(msg);
+- SCTP_DBG_OBJCNT_INC(datamsg);
++ SCTP_DBG_OBJCNT_INC(datamsg);
++ }
+ return msg;
+ }
+
+@@ -136,20 +137,6 @@ void sctp_datamsg_put(struct sctp_datamsg *msg)
+ sctp_datamsg_destroy(msg);
+ }
+
+-/* Free a message. Really just give up a reference, the
+- * really free happens in sctp_datamsg_destroy().
+- */
+-void sctp_datamsg_free(struct sctp_datamsg *msg)
+-{
+- sctp_datamsg_put(msg);
+-}
+-
+-/* Hold on to all the fragments until all chunks have been sent. */
+-void sctp_datamsg_track(struct sctp_chunk *chunk)
+-{
+- sctp_chunk_hold(chunk);
+-}
+-
+ /* Assign a chunk to this datamsg. */
+ static void sctp_datamsg_assign(struct sctp_datamsg *msg, struct sctp_chunk *chunk)
+ {
+@@ -189,7 +176,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
+ msecs_to_jiffies(sinfo->sinfo_timetolive);
+ msg->can_abandon = 1;
+ SCTP_DEBUG_PRINTK("%s: msg:%p expires_at: %ld jiffies:%ld\n",
+- __FUNCTION__, msg, msg->expires_at, jiffies);
++ __func__, msg, msg->expires_at, jiffies);
+ }
+
+ max = asoc->frag_point;
+@@ -295,7 +282,7 @@ errout:
+ chunk = list_entry(pos, struct sctp_chunk, frag_list);
+ sctp_chunk_free(chunk);
+ }
+- sctp_datamsg_free(msg);
++ sctp_datamsg_put(msg);
+ return NULL;
+ }
+
+diff --git a/net/sctp/command.c b/net/sctp/command.c
+index bb97733..c004401 100644
+--- a/net/sctp/command.c
++++ b/net/sctp/command.c
+@@ -52,18 +52,12 @@ int sctp_init_cmd_seq(sctp_cmd_seq_t *seq)
+ /* Add a command to a sctp_cmd_seq_t.
+ * Return 0 if the command sequence is full.
+ */
+-int sctp_add_cmd(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_arg_t obj)
++void sctp_add_cmd_sf(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_arg_t obj)
+ {
+- if (seq->next_free_slot >= SCTP_MAX_NUM_COMMANDS)
+- goto fail;
++ BUG_ON(seq->next_free_slot >= SCTP_MAX_NUM_COMMANDS);
+
+ seq->cmds[seq->next_free_slot].verb = verb;
+ seq->cmds[seq->next_free_slot++].obj = obj;
+-
+- return 1;
+-
+-fail:
+- return 0;
+ }
+
+ /* Return the next command structure in a sctp_cmd_seq.
+diff --git a/net/sctp/input.c b/net/sctp/input.c
+index 812ff17..ca6b022 100644
+--- a/net/sctp/input.c
++++ b/net/sctp/input.c
+@@ -409,7 +409,7 @@ void sctp_icmp_proto_unreachable(struct sock *sk,
+ struct sctp_association *asoc,
+ struct sctp_transport *t)
+ {
+- SCTP_DEBUG_PRINTK("%s\n", __FUNCTION__);
++ SCTP_DEBUG_PRINTK("%s\n", __func__);
+
+ sctp_do_sm(SCTP_EVENT_T_OTHER,
+ SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),
+@@ -725,7 +725,6 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *l
+ }
+
+ ep = sctp_sk((sctp_get_ctl_sock()))->ep;
+- epb = &ep->base;
+
+ hit:
+ sctp_endpoint_hold(ep);
+diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
+index 85f1495..e45e44c 100644
+--- a/net/sctp/ipv6.c
++++ b/net/sctp/ipv6.c
+@@ -226,7 +226,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport,
+
+ SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, "
+ "src:" NIP6_FMT " dst:" NIP6_FMT "\n",
+- __FUNCTION__, skb, skb->len,
++ __func__, skb, skb->len,
+ NIP6(fl.fl6_src), NIP6(fl.fl6_dst));
+
+ SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
+@@ -251,7 +251,7 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc,
+
+
+ SCTP_DEBUG_PRINTK("%s: DST=" NIP6_FMT " ",
+- __FUNCTION__, NIP6(fl.fl6_dst));
++ __func__, NIP6(fl.fl6_dst));
+
+ if (saddr) {
+ ipv6_addr_copy(&fl.fl6_src, &saddr->v6.sin6_addr);
+@@ -260,7 +260,7 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc,
+ NIP6(fl.fl6_src));
+ }
+
+- dst = ip6_route_output(NULL, &fl);
++ dst = ip6_route_output(&init_net, NULL, &fl);
+ if (!dst->error) {
+ struct rt6_info *rt;
+ rt = (struct rt6_info *)dst;
+@@ -313,10 +313,13 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc,
+
+ SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p "
+ "daddr:" NIP6_FMT " ",
+- __FUNCTION__, asoc, dst, NIP6(daddr->v6.sin6_addr));
++ __func__, asoc, dst, NIP6(daddr->v6.sin6_addr));
+
+ if (!asoc) {
+- ipv6_get_saddr(dst, &daddr->v6.sin6_addr,&saddr->v6.sin6_addr);
++ ipv6_dev_get_saddr(dst ? ip6_dst_idev(dst)->dev : NULL,
++ &daddr->v6.sin6_addr,
++ inet6_sk(asoc->base.sk)->srcprefs,
++ &saddr->v6.sin6_addr);
+ SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: " NIP6_FMT "\n",
+ NIP6(saddr->v6.sin6_addr));
+ return;
+@@ -351,7 +354,7 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc,
+ } else {
+ printk(KERN_ERR "%s: asoc:%p Could not find a valid source "
+ "address for the dest:" NIP6_FMT "\n",
+- __FUNCTION__, asoc, NIP6(daddr->v6.sin6_addr));
++ __func__, asoc, NIP6(daddr->v6.sin6_addr));
+ }
+
+ rcu_read_unlock();
+@@ -634,7 +637,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
+ struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
+ struct sctp6_sock *newsctp6sk;
+
+- newsk = sk_alloc(sk->sk_net, PF_INET6, GFP_KERNEL, sk->sk_prot);
++ newsk = sk_alloc(sock_net(sk), PF_INET6, GFP_KERNEL, sk->sk_prot);
+ if (!newsk)
+ goto out;
+
+diff --git a/net/sctp/objcnt.c b/net/sctp/objcnt.c
+index cfeb07e..f73ec0e 100644
+--- a/net/sctp/objcnt.c
++++ b/net/sctp/objcnt.c
+@@ -83,13 +83,12 @@ static sctp_dbg_objcnt_entry_t sctp_dbg_objcnt[] = {
+ */
+ static int sctp_objcnt_seq_show(struct seq_file *seq, void *v)
+ {
+- int i;
+- char temp[128];
++ int i, len;
+
+ i = (int)*(loff_t *)v;
+- sprintf(temp, "%s: %d", sctp_dbg_objcnt[i].label,
+- atomic_read(sctp_dbg_objcnt[i].counter));
+- seq_printf(seq, "%-127s\n", temp);
++ seq_printf(seq, "%s: %d%n", sctp_dbg_objcnt[i].label,
++ atomic_read(sctp_dbg_objcnt[i].counter), &len);
++ seq_printf(seq, "%*s\n", 127 - len, "");
+ return 0;
+ }
+
+diff --git a/net/sctp/output.c b/net/sctp/output.c
+index aa700fe..cf4f9fb 100644
+--- a/net/sctp/output.c
++++ b/net/sctp/output.c
+@@ -74,7 +74,7 @@ struct sctp_packet *sctp_packet_config(struct sctp_packet *packet,
+ {
+ struct sctp_chunk *chunk = NULL;
+
+- SCTP_DEBUG_PRINTK("%s: packet:%p vtag:0x%x\n", __FUNCTION__,
++ SCTP_DEBUG_PRINTK("%s: packet:%p vtag:0x%x\n", __func__,
+ packet, vtag);
+
+ packet->vtag = vtag;
+@@ -106,7 +106,7 @@ struct sctp_packet *sctp_packet_init(struct sctp_packet *packet,
+ struct sctp_association *asoc = transport->asoc;
+ size_t overhead;
+
+- SCTP_DEBUG_PRINTK("%s: packet:%p transport:%p\n", __FUNCTION__,
++ SCTP_DEBUG_PRINTK("%s: packet:%p transport:%p\n", __func__,
+ packet, transport);
+
+ packet->transport = transport;
+@@ -138,7 +138,7 @@ void sctp_packet_free(struct sctp_packet *packet)
+ {
+ struct sctp_chunk *chunk, *tmp;
+
+- SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet);
++ SCTP_DEBUG_PRINTK("%s: packet:%p\n", __func__, packet);
+
+ list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) {
+ list_del_init(&chunk->list);
+@@ -162,7 +162,7 @@ sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *packet,
+ sctp_xmit_t retval;
+ int error = 0;
+
+- SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __FUNCTION__,
++ SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __func__,
+ packet, chunk);
+
+ switch ((retval = (sctp_packet_append_chunk(packet, chunk)))) {
+@@ -264,7 +264,7 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
+ size_t pmtu;
+ int too_big;
+
+- SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __FUNCTION__, packet,
++ SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __func__, packet,
+ chunk);
+
+ /* Try to bundle AUTH chunk */
+@@ -372,7 +372,7 @@ int sctp_packet_transmit(struct sctp_packet *packet)
+ unsigned char *auth = NULL; /* pointer to auth in skb data */
+ __u32 cksum_buf_len = sizeof(struct sctphdr);
+
+- SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet);
++ SCTP_DEBUG_PRINTK("%s: packet:%p\n", __func__, packet);
+
+ /* Do NOT generate a chunkless packet. */
+ if (list_empty(&packet->chunk_list))
+@@ -677,7 +677,7 @@ static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet,
+ "transport: %p, cwnd: %d, "
+ "ssthresh: %d, flight_size: %d, "
+ "pba: %d\n",
+- __FUNCTION__, transport,
++ __func__, transport,
+ transport->cwnd,
+ transport->ssthresh,
+ transport->flight_size,
+diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
+index c071446..59edfd2 100644
+--- a/net/sctp/outqueue.c
++++ b/net/sctp/outqueue.c
+@@ -221,12 +221,12 @@ void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q)
+ void sctp_outq_teardown(struct sctp_outq *q)
+ {
+ struct sctp_transport *transport;
+- struct list_head *lchunk, *pos, *temp;
++ struct list_head *lchunk, *temp;
+ struct sctp_chunk *chunk, *tmp;
+
+ /* Throw away unacknowledged chunks. */
+- list_for_each(pos, &q->asoc->peer.transport_addr_list) {
+- transport = list_entry(pos, struct sctp_transport, transports);
++ list_for_each_entry(transport, &q->asoc->peer.transport_addr_list,
++ transports) {
+ while ((lchunk = sctp_list_dequeue(&transport->transmitted)) != NULL) {
+ chunk = list_entry(lchunk, struct sctp_chunk,
+ transmitted_list);
+@@ -469,7 +469,7 @@ void sctp_retransmit_mark(struct sctp_outq *q,
+
+ SCTP_DEBUG_PRINTK("%s: transport: %p, reason: %d, "
+ "cwnd: %d, ssthresh: %d, flight_size: %d, "
+- "pba: %d\n", __FUNCTION__,
++ "pba: %d\n", __func__,
+ transport, reason,
+ transport->cwnd, transport->ssthresh,
+ transport->flight_size,
+@@ -494,6 +494,8 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
+ */
+ if (transport == transport->asoc->peer.retran_path)
+ sctp_assoc_update_retran_path(transport->asoc);
++ transport->asoc->rtx_data_chunks +=
++ transport->asoc->unack_data;
+ break;
+ case SCTP_RTXR_FAST_RTX:
+ SCTP_INC_STATS(SCTP_MIB_FAST_RETRANSMITS);
+@@ -504,6 +506,7 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
+ break;
+ case SCTP_RTXR_T1_RTX:
+ SCTP_INC_STATS(SCTP_MIB_T1_RETRANSMITS);
++ transport->asoc->init_retries++;
+ break;
+ default:
+ BUG();
+@@ -535,7 +538,7 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
+ int rtx_timeout, int *start_timer)
+ {
+ struct list_head *lqueue;
+- struct list_head *lchunk, *lchunk1;
++ struct list_head *lchunk;
+ struct sctp_transport *transport = pkt->transport;
+ sctp_xmit_t status;
+ struct sctp_chunk *chunk, *chunk1;
+@@ -646,9 +649,7 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
+ * to be marked as ineligible for a subsequent fast retransmit.
+ */
+ if (rtx_timeout && !lchunk) {
+- list_for_each(lchunk1, lqueue) {
+- chunk1 = list_entry(lchunk1, struct sctp_chunk,
+- transmitted_list);
++ list_for_each_entry(chunk1, lqueue, transmitted_list) {
+ if (chunk1->fast_retransmit > 0)
+ chunk1->fast_retransmit = -1;
+ }
+@@ -1037,7 +1038,6 @@ static void sctp_sack_update_unack_data(struct sctp_association *assoc,
+ static __u32 sctp_highest_new_tsn(struct sctp_sackhdr *sack,
+ struct sctp_association *asoc)
+ {
+- struct list_head *ltransport, *lchunk;
+ struct sctp_transport *transport;
+ struct sctp_chunk *chunk;
+ __u32 highest_new_tsn, tsn;
+@@ -1045,12 +1045,9 @@ static __u32 sctp_highest_new_tsn(struct sctp_sackhdr *sack,
+
+ highest_new_tsn = ntohl(sack->cum_tsn_ack);
+
+- list_for_each(ltransport, transport_list) {
+- transport = list_entry(ltransport, struct sctp_transport,
+- transports);
+- list_for_each(lchunk, &transport->transmitted) {
+- chunk = list_entry(lchunk, struct sctp_chunk,
+- transmitted_list);
++ list_for_each_entry(transport, transport_list, transports) {
++ list_for_each_entry(chunk, &transport->transmitted,
++ transmitted_list) {
+ tsn = ntohl(chunk->subh.data_hdr->tsn);
+
+ if (!chunk->tsn_gap_acked &&
+@@ -1073,7 +1070,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
+ struct sctp_association *asoc = q->asoc;
+ struct sctp_transport *transport;
+ struct sctp_chunk *tchunk = NULL;
+- struct list_head *lchunk, *transport_list, *pos, *temp;
++ struct list_head *lchunk, *transport_list, *temp;
+ sctp_sack_variable_t *frags = sack->variable;
+ __u32 sack_ctsn, ctsn, tsn;
+ __u32 highest_tsn, highest_new_tsn;
+@@ -1099,9 +1096,8 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
+ */
+ if (TSN_lte(primary->cacc.next_tsn_at_change, sack_ctsn)) {
+ primary->cacc.changeover_active = 0;
+- list_for_each(pos, transport_list) {
+- transport = list_entry(pos, struct sctp_transport,
+- transports);
++ list_for_each_entry(transport, transport_list,
++ transports) {
+ transport->cacc.cycling_changeover = 0;
+ }
+ }
+@@ -1116,9 +1112,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
+ */
+ if (sack->num_gap_ack_blocks &&
+ primary->cacc.changeover_active) {
+- list_for_each(pos, transport_list) {
+- transport = list_entry(pos, struct sctp_transport,
+- transports);
++ list_for_each_entry(transport, transport_list, transports) {
+ transport->cacc.cacc_saw_newack = 0;
+ }
+ }
+@@ -1147,9 +1141,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
+ *
+ * This is a MASSIVE candidate for optimization.
+ */
+- list_for_each(pos, transport_list) {
+- transport = list_entry(pos, struct sctp_transport,
+- transports);
++ list_for_each_entry(transport, transport_list, transports) {
+ sctp_check_transmitted(q, &transport->transmitted,
+ transport, sack, highest_new_tsn);
+ /*
+@@ -1161,9 +1153,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
+ count_of_newacks ++;
+ }
+
+- list_for_each(pos, transport_list) {
+- transport = list_entry(pos, struct sctp_transport,
+- transports);
++ list_for_each_entry(transport, transport_list, transports) {
+ sctp_mark_missing(q, &transport->transmitted, transport,
+ highest_new_tsn, count_of_newacks);
+ }
+@@ -1206,10 +1196,10 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
+ sctp_generate_fwdtsn(q, sack_ctsn);
+
+ SCTP_DEBUG_PRINTK("%s: sack Cumulative TSN Ack is 0x%x.\n",
+- __FUNCTION__, sack_ctsn);
++ __func__, sack_ctsn);
+ SCTP_DEBUG_PRINTK("%s: Cumulative TSN Ack of association, "
+ "%p is 0x%x. Adv peer ack point: 0x%x\n",
+- __FUNCTION__, asoc, ctsn, asoc->adv_peer_ack_point);
++ __func__, asoc, ctsn, asoc->adv_peer_ack_point);
+
+ /* See if all chunks are acked.
+ * Make sure the empty queue handler will get run later.
+@@ -1220,9 +1210,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
+ if (!q->empty)
+ goto finish;
+
+- list_for_each(pos, transport_list) {
+- transport = list_entry(pos, struct sctp_transport,
+- transports);
++ list_for_each_entry(transport, transport_list, transports) {
+ q->empty = q->empty && list_empty(&transport->transmitted);
+ if (!q->empty)
+ goto finish;
+@@ -1444,7 +1432,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
+ if (tchunk->tsn_gap_acked) {
+ SCTP_DEBUG_PRINTK("%s: Receiver reneged on "
+ "data TSN: 0x%x\n",
+- __FUNCTION__,
++ __func__,
+ tsn);
+ tchunk->tsn_gap_acked = 0;
+
+@@ -1544,6 +1532,8 @@ static void sctp_check_transmitted(struct sctp_outq *q,
+ bytes_acked);
+
+ transport->flight_size -= bytes_acked;
++ if (transport->flight_size == 0)
++ transport->partial_bytes_acked = 0;
+ q->outstanding_bytes -= bytes_acked;
+ } else {
+ /* RFC 2960 6.1, sctpimpguide-06 2.15.2
+@@ -1561,7 +1551,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
+ (sack_ctsn+2 == q->asoc->next_tsn)) {
+ SCTP_DEBUG_PRINTK("%s: SACK received for zero "
+ "window probe: %u\n",
+- __FUNCTION__, sack_ctsn);
++ __func__, sack_ctsn);
+ q->asoc->overall_error_count = 0;
+ transport->error_count = 0;
+ }
+@@ -1596,14 +1586,12 @@ static void sctp_mark_missing(struct sctp_outq *q,
+ int count_of_newacks)
+ {
+ struct sctp_chunk *chunk;
+- struct list_head *pos;
+ __u32 tsn;
+ char do_fast_retransmit = 0;
+ struct sctp_transport *primary = q->asoc->peer.primary_path;
+
+- list_for_each(pos, transmitted_queue) {
++ list_for_each_entry(chunk, transmitted_queue, transmitted_list) {
+
+- chunk = list_entry(pos, struct sctp_chunk, transmitted_list);
+ tsn = ntohl(chunk->subh.data_hdr->tsn);
+
+ /* RFC 2960 7.2.4, sctpimpguide-05 2.8.2 M3) Examine all
+@@ -1626,7 +1614,7 @@ static void sctp_mark_missing(struct sctp_outq *q,
+
+ SCTP_DEBUG_PRINTK(
+ "%s: TSN 0x%x missing counter: %d\n",
+- __FUNCTION__, tsn,
++ __func__, tsn,
+ chunk->tsn_missing_report);
+ }
+ }
+@@ -1649,7 +1637,7 @@ static void sctp_mark_missing(struct sctp_outq *q,
+
+ SCTP_DEBUG_PRINTK("%s: transport: %p, cwnd: %d, "
+ "ssthresh: %d, flight_size: %d, pba: %d\n",
+- __FUNCTION__, transport, transport->cwnd,
++ __func__, transport, transport->cwnd,
+ transport->ssthresh, transport->flight_size,
+ transport->partial_bytes_acked);
+ }
+diff --git a/net/sctp/proc.c b/net/sctp/proc.c
+index 973f1db..0aba759 100644
+--- a/net/sctp/proc.c
++++ b/net/sctp/proc.c
+@@ -124,7 +124,6 @@ void sctp_snmp_proc_exit(void)
+ /* Dump local addresses of an association/endpoint. */
+ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_common *epb)
+ {
+- struct list_head *pos;
+ struct sctp_association *asoc;
+ struct sctp_sockaddr_entry *laddr;
+ struct sctp_transport *peer;
+@@ -137,8 +136,7 @@ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_commo
+ primary = &peer->saddr;
+ }
+
+- list_for_each(pos, &epb->bind_addr.address_list) {
+- laddr = list_entry(pos, struct sctp_sockaddr_entry, list);
++ list_for_each_entry(laddr, &epb->bind_addr.address_list, list) {
+ addr = &laddr->a;
+ af = sctp_get_af_specific(addr->sa.sa_family);
+ if (primary && af->cmp_addr(addr, primary)) {
+@@ -151,14 +149,13 @@ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_commo
+ /* Dump remote addresses of an association. */
+ static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_association *assoc)
+ {
+- struct list_head *pos;
+ struct sctp_transport *transport;
+ union sctp_addr *addr, *primary;
+ struct sctp_af *af;
+
+ primary = &assoc->peer.primary_addr;
+- list_for_each(pos, &assoc->peer.transport_addr_list) {
+- transport = list_entry(pos, struct sctp_transport, transports);
++ list_for_each_entry(transport, &assoc->peer.transport_addr_list,
++ transports) {
+ addr = &transport->ipaddr;
+ af = sctp_get_af_specific(addr->sa.sa_family);
+ if (af->cmp_addr(addr, primary)) {
+@@ -279,8 +276,10 @@ static void * sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos)
+ *pos = 0;
+
+ if (*pos == 0)
+- seq_printf(seq, " ASSOC SOCK STY SST ST HBKT ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT "
+- "RPORT LADDRS <-> RADDRS\n");
++ seq_printf(seq, " ASSOC SOCK STY SST ST HBKT "
++ "ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT "
++ "RPORT LADDRS <-> RADDRS "
++ "HBINT INS OUTS MAXRT T1X T2X RTXC\n");
+
+ return (void *)pos;
+ }
+@@ -319,19 +318,25 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
+ assoc = sctp_assoc(epb);
+ sk = epb->sk;
+ seq_printf(seq,
+- "%8p %8p %-3d %-3d %-2d %-4d %4d %8d %8d %7d %5lu %-5d %5d ",
++ "%8p %8p %-3d %-3d %-2d %-4d "
++ "%4d %8d %8d %7d %5lu %-5d %5d ",
+ assoc, sk, sctp_sk(sk)->type, sk->sk_state,
+- assoc->state, hash, assoc->assoc_id,
++ assoc->state, hash,
++ assoc->assoc_id,
+ assoc->sndbuf_used,
+ atomic_read(&assoc->rmem_alloc),
+ sock_i_uid(sk), sock_i_ino(sk),
+ epb->bind_addr.port,
+ assoc->peer.port);
+-
+ seq_printf(seq, " ");
+ sctp_seq_dump_local_addrs(seq, epb);
+ seq_printf(seq, "<-> ");
+ sctp_seq_dump_remote_addrs(seq, assoc);
++ seq_printf(seq, "\t%8lu %5d %5d %4d %4d %4d %8d ",
++ assoc->hbinterval, assoc->c.sinit_max_instreams,
++ assoc->c.sinit_num_ostreams, assoc->max_retrans,
++ assoc->init_retries, assoc->shutdown_retries,
++ assoc->rtx_data_chunks);
+ seq_printf(seq, "\n");
+ }
+ read_unlock(&head->lock);
+diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
+index c2dd65d..0ec234b 100644
+--- a/net/sctp/protocol.c
++++ b/net/sctp/protocol.c
+@@ -74,7 +74,7 @@ DEFINE_SPINLOCK(sctp_assocs_id_lock);
+ * the Out-of-the-blue (OOTB) packets. A control sock will be created
+ * for this socket at the initialization time.
+ */
+-static struct socket *sctp_ctl_socket;
++static struct sock *sctp_ctl_sock;
+
+ static struct sctp_pf *sctp_pf_inet6_specific;
+ static struct sctp_pf *sctp_pf_inet_specific;
+@@ -91,7 +91,7 @@ int sysctl_sctp_wmem[3];
+ /* Return the address of the control sock. */
+ struct sock *sctp_get_ctl_sock(void)
+ {
+- return sctp_ctl_socket->sk;
++ return sctp_ctl_sock;
+ }
+
+ /* Set up the proc fs entry for the SCTP protocol. */
+@@ -363,7 +363,7 @@ static int sctp_v4_addr_valid(union sctp_addr *addr,
+ return 0;
+
+ /* Is this a broadcast address? */
+- if (skb && ((struct rtable *)skb->dst)->rt_flags & RTCF_BROADCAST)
++ if (skb && skb->rtable->rt_flags & RTCF_BROADCAST)
+ return 0;
+
+ return 1;
+@@ -451,7 +451,7 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
+ fl.fl4_src = saddr->v4.sin_addr.s_addr;
+
+ SCTP_DEBUG_PRINTK("%s: DST:%u.%u.%u.%u, SRC:%u.%u.%u.%u - ",
+- __FUNCTION__, NIPQUAD(fl.fl4_dst),
++ __func__, NIPQUAD(fl.fl4_dst),
+ NIPQUAD(fl.fl4_src));
+
+ if (!ip_route_output_key(&init_net, &rt, &fl)) {
+@@ -539,7 +539,7 @@ static void sctp_v4_get_saddr(struct sctp_association *asoc,
+ /* What interface did this skb arrive on? */
+ static int sctp_v4_skb_iif(const struct sk_buff *skb)
+ {
+- return ((struct rtable *)skb->dst)->rt_iif;
++ return skb->rtable->rt_iif;
+ }
+
+ /* Was this packet marked by Explicit Congestion Notification? */
+@@ -554,7 +554,7 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
+ {
+ struct inet_sock *inet = inet_sk(sk);
+ struct inet_sock *newinet;
+- struct sock *newsk = sk_alloc(sk->sk_net, PF_INET, GFP_KERNEL,
++ struct sock *newsk = sk_alloc(sock_net(sk), PF_INET, GFP_KERNEL,
+ sk->sk_prot);
+
+ if (!newsk)
+@@ -630,6 +630,9 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
+ struct sctp_sockaddr_entry *temp;
+ int found = 0;
+
++ if (dev_net(ifa->ifa_dev->dev) != &init_net)
++ return NOTIFY_DONE;
++
+ switch (ev) {
+ case NETDEV_UP:
+ addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
+@@ -679,16 +682,13 @@ static int sctp_ctl_sock_init(void)
+ else
+ family = PF_INET;
+
+- err = sock_create_kern(family, SOCK_SEQPACKET, IPPROTO_SCTP,
+- &sctp_ctl_socket);
++ err = inet_ctl_sock_create(&sctp_ctl_sock, family,
++ SOCK_SEQPACKET, IPPROTO_SCTP, &init_net);
+ if (err < 0) {
+ printk(KERN_ERR
+ "SCTP: Failed to create the SCTP control socket.\n");
+ return err;
+ }
+- sctp_ctl_socket->sk->sk_allocation = GFP_ATOMIC;
+- inet_sk(sctp_ctl_socket->sk)->uc_ttl = -1;
+-
+ return 0;
+ }
+
+@@ -828,9 +828,9 @@ static inline int sctp_v4_xmit(struct sk_buff *skb,
+ {
+ SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, "
+ "src:%u.%u.%u.%u, dst:%u.%u.%u.%u\n",
+- __FUNCTION__, skb, skb->len,
+- NIPQUAD(((struct rtable *)skb->dst)->rt_src),
+- NIPQUAD(((struct rtable *)skb->dst)->rt_dst));
++ __func__, skb, skb->len,
++ NIPQUAD(skb->rtable->rt_src),
++ NIPQUAD(skb->rtable->rt_dst));
+
+ SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
+ return ip_queue_xmit(skb, ipfragok);
+@@ -974,24 +974,14 @@ int sctp_register_pf(struct sctp_pf *pf, sa_family_t family)
+ return 1;
+ }
+
+-static int __init init_sctp_mibs(void)
++static inline int init_sctp_mibs(void)
+ {
+- sctp_statistics[0] = alloc_percpu(struct sctp_mib);
+- if (!sctp_statistics[0])
+- return -ENOMEM;
+- sctp_statistics[1] = alloc_percpu(struct sctp_mib);
+- if (!sctp_statistics[1]) {
+- free_percpu(sctp_statistics[0]);
+- return -ENOMEM;
+- }
+- return 0;
+-
++ return snmp_mib_init((void**)sctp_statistics, sizeof(struct sctp_mib));
+ }
+
+-static void cleanup_sctp_mibs(void)
++static inline void cleanup_sctp_mibs(void)
+ {
+- free_percpu(sctp_statistics[0]);
+- free_percpu(sctp_statistics[1]);
++ snmp_mib_free((void**)sctp_statistics);
+ }
+
+ static void sctp_v4_pf_init(void)
+@@ -1286,7 +1276,7 @@ err_v6_add_protocol:
+ sctp_v6_del_protocol();
+ err_add_protocol:
+ sctp_v4_del_protocol();
+- sock_release(sctp_ctl_socket);
++ inet_ctl_sock_destroy(sctp_ctl_sock);
+ err_ctl_sock_init:
+ sctp_v6_protosw_exit();
+ err_v6_protosw_init:
+@@ -1330,7 +1320,7 @@ SCTP_STATIC __exit void sctp_exit(void)
+ sctp_v4_del_protocol();
+
+ /* Free the control endpoint. */
+- sock_release(sctp_ctl_socket);
++ inet_ctl_sock_destroy(sctp_ctl_sock);
+
+ /* Free protosw registrations */
+ sctp_v6_protosw_exit();
+diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
+index 36ebb39..81b6064 100644
+--- a/net/sctp/sm_make_chunk.c
++++ b/net/sctp/sm_make_chunk.c
+@@ -1782,7 +1782,7 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc,
+ const struct sctp_chunk *chunk,
+ struct sctp_chunk **errp)
+ {
+- char error[] = "The following parameter had invalid length:";
++ static const char error[] = "The following parameter had invalid length:";
+ size_t payload_len = WORD_ROUND(sizeof(error)) +
+ sizeof(sctp_paramhdr_t);
+
+@@ -2269,8 +2269,8 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
+ * high (for example, implementations MAY use the size of the receiver
+ * advertised window).
+ */
+- list_for_each(pos, &asoc->peer.transport_addr_list) {
+- transport = list_entry(pos, struct sctp_transport, transports);
++ list_for_each_entry(transport, &asoc->peer.transport_addr_list,
++ transports) {
+ transport->ssthresh = asoc->peer.i.a_rwnd;
+ }
+
+@@ -3066,7 +3066,6 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
+ union sctp_addr addr;
+ struct sctp_bind_addr *bp = &asoc->base.bind_addr;
+ union sctp_addr_param *addr_param;
+- struct list_head *pos;
+ struct sctp_transport *transport;
+ struct sctp_sockaddr_entry *saddr;
+ int retval = 0;
+@@ -3094,9 +3093,8 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
+ local_bh_disable();
+ retval = sctp_del_bind_addr(bp, &addr);
+ local_bh_enable();
+- list_for_each(pos, &asoc->peer.transport_addr_list) {
+- transport = list_entry(pos, struct sctp_transport,
+- transports);
++ list_for_each_entry(transport, &asoc->peer.transport_addr_list,
++ transports) {
+ dst_release(transport->dst);
+ sctp_transport_route(transport, NULL,
+ sctp_sk(asoc->base.sk));
+diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
+index a4763fd..23a9f1a 100644
+--- a/net/sctp/sm_sideeffect.c
++++ b/net/sctp/sm_sideeffect.c
+@@ -243,7 +243,7 @@ void sctp_generate_t3_rtx_event(unsigned long peer)
+
+ sctp_bh_lock_sock(asoc->base.sk);
+ if (sock_owned_by_user(asoc->base.sk)) {
+- SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __FUNCTION__);
++ SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __func__);
+
+ /* Try again later. */
+ if (!mod_timer(&transport->T3_rtx_timer, jiffies + (HZ/20)))
+@@ -283,7 +283,7 @@ static void sctp_generate_timeout_event(struct sctp_association *asoc,
+ sctp_bh_lock_sock(asoc->base.sk);
+ if (sock_owned_by_user(asoc->base.sk)) {
+ SCTP_DEBUG_PRINTK("%s:Sock is busy: timer %d\n",
+- __FUNCTION__,
++ __func__,
+ timeout_type);
+
+ /* Try again later. */
+@@ -361,7 +361,7 @@ void sctp_generate_heartbeat_event(unsigned long data)
+
+ sctp_bh_lock_sock(asoc->base.sk);
+ if (sock_owned_by_user(asoc->base.sk)) {
+- SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __FUNCTION__);
++ SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __func__);
+
+ /* Try again later. */
+ if (!mod_timer(&transport->hb_timer, jiffies + (HZ/20)))
+@@ -545,14 +545,12 @@ static void sctp_cmd_hb_timers_start(sctp_cmd_seq_t *cmds,
+ struct sctp_association *asoc)
+ {
+ struct sctp_transport *t;
+- struct list_head *pos;
+
+ /* Start a heartbeat timer for each transport on the association.
+ * hold a reference on the transport to make sure none of
+ * the needed data structures go away.
+ */
+- list_for_each(pos, &asoc->peer.transport_addr_list) {
+- t = list_entry(pos, struct sctp_transport, transports);
++ list_for_each_entry(t, &asoc->peer.transport_addr_list, transports) {
+
+ if (!mod_timer(&t->hb_timer, sctp_transport_timeout(t)))
+ sctp_transport_hold(t);
+@@ -563,12 +561,11 @@ static void sctp_cmd_hb_timers_stop(sctp_cmd_seq_t *cmds,
+ struct sctp_association *asoc)
+ {
+ struct sctp_transport *t;
+- struct list_head *pos;
+
+ /* Stop all heartbeat timers. */
+
+- list_for_each(pos, &asoc->peer.transport_addr_list) {
+- t = list_entry(pos, struct sctp_transport, transports);
++ list_for_each_entry(t, &asoc->peer.transport_addr_list,
++ transports) {
+ if (del_timer(&t->hb_timer))
+ sctp_transport_put(t);
+ }
+@@ -579,10 +576,9 @@ static void sctp_cmd_t3_rtx_timers_stop(sctp_cmd_seq_t *cmds,
+ struct sctp_association *asoc)
+ {
+ struct sctp_transport *t;
+- struct list_head *pos;
+
+- list_for_each(pos, &asoc->peer.transport_addr_list) {
+- t = list_entry(pos, struct sctp_transport, transports);
++ list_for_each_entry(t, &asoc->peer.transport_addr_list,
++ transports) {
+ if (timer_pending(&t->T3_rtx_timer) &&
+ del_timer(&t->T3_rtx_timer)) {
+ sctp_transport_put(t);
+@@ -593,7 +589,6 @@ static void sctp_cmd_t3_rtx_timers_stop(sctp_cmd_seq_t *cmds,
+
+ /* Helper function to update the heartbeat timer. */
+ static void sctp_cmd_hb_timer_update(sctp_cmd_seq_t *cmds,
+- struct sctp_association *asoc,
+ struct sctp_transport *t)
+ {
+ /* Update the heartbeat timer. */
+@@ -1065,7 +1060,6 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
+ struct sctp_chunk *new_obj;
+ struct sctp_chunk *chunk = NULL;
+ struct sctp_packet *packet;
+- struct list_head *pos;
+ struct timer_list *timer;
+ unsigned long timeout;
+ struct sctp_transport *t;
+@@ -1397,9 +1391,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
+ /* If we've sent any data bundled with
+ * COOKIE-ECHO we need to resend.
+ */
+- list_for_each(pos, &asoc->peer.transport_addr_list) {
+- t = list_entry(pos, struct sctp_transport,
+- transports);
++ list_for_each_entry(t, &asoc->peer.transport_addr_list,
++ transports) {
+ sctp_retransmit_mark(&asoc->outqueue, t,
+ SCTP_RTXR_T1_RTX);
+ }
+@@ -1457,7 +1450,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
+
+ case SCTP_CMD_HB_TIMER_UPDATE:
+ t = cmd->obj.transport;
+- sctp_cmd_hb_timer_update(commands, asoc, t);
++ sctp_cmd_hb_timer_update(commands, t);
+ break;
+
+ case SCTP_CMD_HB_TIMERS_STOP:
+diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
+index 07194c2..0c9d5a6 100644
+--- a/net/sctp/sm_statefuns.c
++++ b/net/sctp/sm_statefuns.c
+@@ -1124,7 +1124,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
+ printk(KERN_WARNING
+ "%s association %p could not find address "
+ NIP6_FMT "\n",
+- __FUNCTION__,
++ __func__,
+ asoc,
+ NIP6(from_addr.v6.sin6_addr));
+ } else {
+@@ -1132,7 +1132,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
+ printk(KERN_WARNING
+ "%s association %p could not find address "
+ NIPQUAD_FMT "\n",
+- __FUNCTION__,
++ __func__,
+ asoc,
+ NIPQUAD(from_addr.v4.sin_addr.s_addr));
+ }
+@@ -1150,7 +1150,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
+ time_after(jiffies, hbinfo->sent_at + max_interval)) {
+ SCTP_DEBUG_PRINTK("%s: HEARTBEAT ACK with invalid timestamp "
+ "received for transport: %p\n",
+- __FUNCTION__, link);
++ __func__, link);
+ return SCTP_DISPOSITION_DISCARD;
+ }
+
+@@ -1226,7 +1226,6 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc,
+ sctp_cmd_seq_t *commands)
+ {
+ struct sctp_transport *new_addr, *addr;
+- struct list_head *pos, *pos2;
+ int found;
+
+ /* Implementor's Guide - Sectin 5.2.2
+@@ -1243,12 +1242,11 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc,
+ new_addr = NULL;
+ found = 0;
+
+- list_for_each(pos, &new_asoc->peer.transport_addr_list) {
+- new_addr = list_entry(pos, struct sctp_transport, transports);
++ list_for_each_entry(new_addr, &new_asoc->peer.transport_addr_list,
++ transports) {
+ found = 0;
+- list_for_each(pos2, &asoc->peer.transport_addr_list) {
+- addr = list_entry(pos2, struct sctp_transport,
+- transports);
++ list_for_each_entry(addr, &asoc->peer.transport_addr_list,
++ transports) {
+ if (sctp_cmp_addr_exact(&new_addr->ipaddr,
+ &addr->ipaddr)) {
+ found = 1;
+@@ -3135,12 +3133,8 @@ sctp_disposition_t sctp_sf_operr_notify(const struct sctp_endpoint *ep,
+ if (!ev)
+ goto nomem;
+
+- if (!sctp_add_cmd(commands, SCTP_CMD_EVENT_ULP,
+- SCTP_ULPEVENT(ev))) {
+- sctp_ulpevent_free(ev);
+- goto nomem;
+- }
+-
++ sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
++ SCTP_ULPEVENT(ev));
+ sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_OPERR,
+ SCTP_CHUNK(chunk));
+ }
+@@ -3668,7 +3662,7 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn(const struct sctp_endpoint *ep,
+ skb_pull(chunk->skb, len);
+
+ tsn = ntohl(fwdtsn_hdr->new_cum_tsn);
+- SCTP_DEBUG_PRINTK("%s: TSN 0x%x.\n", __FUNCTION__, tsn);
++ SCTP_DEBUG_PRINTK("%s: TSN 0x%x.\n", __func__, tsn);
+
+ /* The TSN is too high--silently discard the chunk and count on it
+ * getting retransmitted later.
+@@ -3728,7 +3722,7 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn_fast(
+ skb_pull(chunk->skb, len);
+
+ tsn = ntohl(fwdtsn_hdr->new_cum_tsn);
+- SCTP_DEBUG_PRINTK("%s: TSN 0x%x.\n", __FUNCTION__, tsn);
++ SCTP_DEBUG_PRINTK("%s: TSN 0x%x.\n", __func__, tsn);
+
+ /* The TSN is too high--silently discard the chunk and count on it
+ * getting retransmitted later.
+@@ -4237,7 +4231,7 @@ static sctp_disposition_t sctp_sf_violation_chunklen(
+ void *arg,
+ sctp_cmd_seq_t *commands)
+ {
+- char err_str[]="The following chunk had invalid length:";
++ static const char err_str[]="The following chunk had invalid length:";
+
+ return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str,
+ sizeof(err_str));
+@@ -4254,7 +4248,7 @@ static sctp_disposition_t sctp_sf_violation_paramlen(
+ const sctp_subtype_t type,
+ void *arg,
+ sctp_cmd_seq_t *commands) {
+- char err_str[] = "The following parameter had invalid length:";
++ static const char err_str[] = "The following parameter had invalid length:";
+
+ return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str,
+ sizeof(err_str));
+@@ -4273,7 +4267,7 @@ static sctp_disposition_t sctp_sf_violation_ctsn(
+ void *arg,
+ sctp_cmd_seq_t *commands)
+ {
+- char err_str[]="The cumulative tsn ack beyond the max tsn currently sent:";
++ static const char err_str[]="The cumulative tsn ack beyond the max tsn currently sent:";
+
+ return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str,
+ sizeof(err_str));
+@@ -4292,7 +4286,7 @@ static sctp_disposition_t sctp_sf_violation_chunk(
+ void *arg,
+ sctp_cmd_seq_t *commands)
+ {
+- char err_str[]="The following chunk violates protocol:";
++ static const char err_str[]="The following chunk violates protocol:";
+
+ if (!asoc)
+ return sctp_sf_violation(ep, asoc, type, arg, commands);
+@@ -5331,6 +5325,8 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep,
+ SCTP_DEBUG_PRINTK("Timer T2 expired.\n");
+ SCTP_INC_STATS(SCTP_MIB_T2_SHUTDOWN_EXPIREDS);
+
++ ((struct sctp_association *)asoc)->shutdown_retries++;
++
+ if (asoc->overall_error_count >= asoc->max_retrans) {
+ sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
+ SCTP_ERROR(ETIMEDOUT));
+diff --git a/net/sctp/socket.c b/net/sctp/socket.c
+index 998e63a..e7e3baf 100644
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -513,7 +513,6 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
+ union sctp_addr saveaddr;
+ void *addr_buf;
+ struct sctp_af *af;
+- struct list_head *pos;
+ struct list_head *p;
+ int i;
+ int retval = 0;
+@@ -525,10 +524,9 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
+ ep = sp->ep;
+
+ SCTP_DEBUG_PRINTK("%s: (sk: %p, addrs: %p, addrcnt: %d)\n",
+- __FUNCTION__, sk, addrs, addrcnt);
++ __func__, sk, addrs, addrcnt);
+
+- list_for_each(pos, &ep->asocs) {
+- asoc = list_entry(pos, struct sctp_association, asocs);
++ list_for_each_entry(asoc, &ep->asocs, asocs) {
+
+ if (!asoc->peer.asconf_capable)
+ continue;
+@@ -699,7 +697,6 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
+ union sctp_addr *laddr;
+ void *addr_buf;
+ struct sctp_af *af;
+- struct list_head *pos, *pos1;
+ struct sctp_sockaddr_entry *saddr;
+ int i;
+ int retval = 0;
+@@ -711,10 +708,9 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
+ ep = sp->ep;
+
+ SCTP_DEBUG_PRINTK("%s: (sk: %p, addrs: %p, addrcnt: %d)\n",
+- __FUNCTION__, sk, addrs, addrcnt);
++ __func__, sk, addrs, addrcnt);
+
+- list_for_each(pos, &ep->asocs) {
+- asoc = list_entry(pos, struct sctp_association, asocs);
++ list_for_each_entry(asoc, &ep->asocs, asocs) {
+
+ if (!asoc->peer.asconf_capable)
+ continue;
+@@ -787,9 +783,8 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
+ * as some of the addresses in the bind address list are
+ * about to be deleted and cannot be used as source addresses.
+ */
+- list_for_each(pos1, &asoc->peer.transport_addr_list) {
+- transport = list_entry(pos1, struct sctp_transport,
+- transports);
++ list_for_each_entry(transport, &asoc->peer.transport_addr_list,
++ transports) {
+ dst_release(transport->dst);
+ sctp_transport_route(transport, NULL,
+ sctp_sk(asoc->base.sk));
+@@ -1197,7 +1192,7 @@ SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk,
+ struct sockaddr *kaddrs;
+
+ SCTP_DEBUG_PRINTK("%s - sk %p addrs %p addrs_size %d\n",
+- __FUNCTION__, sk, addrs, addrs_size);
++ __func__, sk, addrs, addrs_size);
+
+ if (unlikely(addrs_size <= 0))
+ return -EINVAL;
+@@ -1397,7 +1392,6 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
+ long timeo;
+ __u16 sinfo_flags = 0;
+ struct sctp_datamsg *datamsg;
+- struct list_head *pos;
+ int msg_flags = msg->msg_flags;
+
+ SCTP_DEBUG_PRINTK("sctp_sendmsg(sk: %p, msg: %p, msg_len: %zu)\n",
+@@ -1727,9 +1721,8 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
+ }
+
+ /* Now send the (possibly) fragmented message. */
+- list_for_each(pos, &datamsg->chunks) {
+- chunk = list_entry(pos, struct sctp_chunk, frag_list);
+- sctp_datamsg_track(chunk);
++ list_for_each_entry(chunk, &datamsg->chunks, frag_list) {
++ sctp_chunk_hold(chunk);
+
+ /* Do accounting for the write space. */
+ sctp_set_owner_w(chunk);
+@@ -1748,7 +1741,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
+ SCTP_DEBUG_PRINTK("We sent primitively.\n");
+ }
+
+- sctp_datamsg_free(datamsg);
++ sctp_datamsg_put(datamsg);
+ if (err)
+ goto out_free;
+ else
+@@ -2301,11 +2294,8 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk,
+ * transport.
+ */
+ if (!trans && asoc) {
+- struct list_head *pos;
+-
+- list_for_each(pos, &asoc->peer.transport_addr_list) {
+- trans = list_entry(pos, struct sctp_transport,
+- transports);
++ list_for_each_entry(trans, &asoc->peer.transport_addr_list,
++ transports) {
+ sctp_apply_peer_addr_params(¶ms, trans, asoc, sp,
+ hb_change, pmtud_change,
+ sackdelay_change);
+@@ -2396,11 +2386,8 @@ static int sctp_setsockopt_delayed_ack_time(struct sock *sk,
+
+ /* If change is for association, also apply to each transport. */
+ if (asoc) {
+- struct list_head *pos;
+-
+- list_for_each(pos, &asoc->peer.transport_addr_list) {
+- trans = list_entry(pos, struct sctp_transport,
+- transports);
++ list_for_each_entry(trans, &asoc->peer.transport_addr_list,
++ transports) {
+ if (params.assoc_value) {
+ trans->sackdelay =
+ msecs_to_jiffies(params.assoc_value);
+@@ -2632,13 +2619,10 @@ static int sctp_setsockopt_associnfo(struct sock *sk, char __user *optval, int o
+ if (assocparams.sasoc_asocmaxrxt != 0) {
+ __u32 path_sum = 0;
+ int paths = 0;
+- struct list_head *pos;
+ struct sctp_transport *peer_addr;
+
+- list_for_each(pos, &asoc->peer.transport_addr_list) {
+- peer_addr = list_entry(pos,
+- struct sctp_transport,
+- transports);
++ list_for_each_entry(peer_addr, &asoc->peer.transport_addr_list,
++ transports) {
+ path_sum += peer_addr->pathmaxrxt;
+ paths++;
+ }
+@@ -2716,7 +2700,6 @@ static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, int op
+ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optlen)
+ {
+ struct sctp_association *asoc;
+- struct list_head *pos;
+ struct sctp_sock *sp = sctp_sk(sk);
+ int val;
+
+@@ -2729,8 +2712,7 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optl
+ sp->user_frag = val;
+
+ /* Update the frag_point of the existing associations. */
+- list_for_each(pos, &(sp->ep->asocs)) {
+- asoc = list_entry(pos, struct sctp_association, asocs);
++ list_for_each_entry(asoc, &(sp->ep->asocs), asocs) {
+ asoc->frag_point = sctp_frag_point(sp, asoc->pathmtu);
+ }
+
+@@ -3302,7 +3284,7 @@ SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *addr,
+ sctp_lock_sock(sk);
+
+ SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d\n",
+- __FUNCTION__, sk, addr, addr_len);
++ __func__, sk, addr, addr_len);
+
+ /* Validate addr_len before calling common connect/connectx routine. */
+ af = sctp_get_af_specific(addr->sa_family);
+@@ -3823,7 +3805,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval
+ goto out;
+ }
+
+- SCTP_DEBUG_PRINTK("%s: sk: %p asoc: %p\n", __FUNCTION__, sk, asoc);
++ SCTP_DEBUG_PRINTK("%s: sk: %p asoc: %p\n", __func__, sk, asoc);
+
+ retval = sctp_do_peeloff(asoc, &newsock);
+ if (retval < 0)
+@@ -3837,7 +3819,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval
+ }
+
+ SCTP_DEBUG_PRINTK("%s: sk: %p asoc: %p newsk: %p sd: %d\n",
+- __FUNCTION__, sk, asoc, newsock->sk, retval);
++ __func__, sk, asoc, newsock->sk, retval);
+
+ /* Return the fd mapped to the new socket. */
+ peeloff.sd = retval;
+@@ -4151,7 +4133,6 @@ static int sctp_getsockopt_peer_addrs_old(struct sock *sk, int len,
+ int __user *optlen)
+ {
+ struct sctp_association *asoc;
+- struct list_head *pos;
+ int cnt = 0;
+ struct sctp_getaddrs_old getaddrs;
+ struct sctp_transport *from;
+@@ -4176,8 +4157,8 @@ static int sctp_getsockopt_peer_addrs_old(struct sock *sk, int len,
+ return -EINVAL;
+
+ to = (void __user *)getaddrs.addrs;
+- list_for_each(pos, &asoc->peer.transport_addr_list) {
+- from = list_entry(pos, struct sctp_transport, transports);
++ list_for_each_entry(from, &asoc->peer.transport_addr_list,
++ transports) {
+ memcpy(&temp, &from->ipaddr, sizeof(temp));
+ sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
+ addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len;
+@@ -4200,7 +4181,6 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
+ char __user *optval, int __user *optlen)
+ {
+ struct sctp_association *asoc;
+- struct list_head *pos;
+ int cnt = 0;
+ struct sctp_getaddrs getaddrs;
+ struct sctp_transport *from;
+@@ -4225,8 +4205,8 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
+ to = optval + offsetof(struct sctp_getaddrs,addrs);
+ space_left = len - offsetof(struct sctp_getaddrs,addrs);
+
+- list_for_each(pos, &asoc->peer.transport_addr_list) {
+- from = list_entry(pos, struct sctp_transport, transports);
++ list_for_each_entry(from, &asoc->peer.transport_addr_list,
++ transports) {
+ memcpy(&temp, &from->ipaddr, sizeof(temp));
+ sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
+ addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len;
+@@ -5761,8 +5741,8 @@ static struct sctp_bind_bucket *sctp_bucket_create(
+ struct sctp_bind_bucket *pp;
+
+ pp = kmem_cache_alloc(sctp_bucket_cachep, GFP_ATOMIC);
+- SCTP_DBG_OBJCNT_INC(bind_bucket);
+ if (pp) {
++ SCTP_DBG_OBJCNT_INC(bind_bucket);
+ pp->port = snum;
+ pp->fastreuse = 0;
+ INIT_HLIST_HEAD(&pp->owner);
+@@ -6194,11 +6174,9 @@ do_nonblock:
+ void sctp_write_space(struct sock *sk)
+ {
+ struct sctp_association *asoc;
+- struct list_head *pos;
+
+ /* Wake up the tasks in each wait queue. */
+- list_for_each(pos, &((sctp_sk(sk))->ep->asocs)) {
+- asoc = list_entry(pos, struct sctp_association, asocs);
++ list_for_each_entry(asoc, &((sctp_sk(sk))->ep->asocs), asocs) {
+ __sctp_write_space(asoc);
+ }
+ }
+@@ -6234,7 +6212,7 @@ static int sctp_wait_for_connect(struct sctp_association *asoc, long *timeo_p)
+ long current_timeo = *timeo_p;
+ DEFINE_WAIT(wait);
+
+- SCTP_DEBUG_PRINTK("%s: asoc=%p, timeo=%ld\n", __FUNCTION__, asoc,
++ SCTP_DEBUG_PRINTK("%s: asoc=%p, timeo=%ld\n", __func__, asoc,
+ (long)(*timeo_p));
+
+ /* Increment the association's refcnt. */
+@@ -6514,8 +6492,6 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
+ }
+
+
+-DEFINE_PROTO_INUSE(sctp)
+-
+ /* This proto struct describes the ULP interface for SCTP. */
+ struct proto sctp_prot = {
+ .name = "SCTP",
+@@ -6545,11 +6521,9 @@ struct proto sctp_prot = {
+ .enter_memory_pressure = sctp_enter_memory_pressure,
+ .memory_allocated = &sctp_memory_allocated,
+ .sockets_allocated = &sctp_sockets_allocated,
+- REF_PROTO_INUSE(sctp)
+ };
+
+ #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+-DEFINE_PROTO_INUSE(sctpv6)
+
+ struct proto sctpv6_prot = {
+ .name = "SCTPv6",
+@@ -6579,6 +6553,5 @@ struct proto sctpv6_prot = {
+ .enter_memory_pressure = sctp_enter_memory_pressure,
+ .memory_allocated = &sctp_memory_allocated,
+ .sockets_allocated = &sctp_sockets_allocated,
+- REF_PROTO_INUSE(sctpv6)
+ };
+ #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
+diff --git a/net/sctp/transport.c b/net/sctp/transport.c
+index d9f8af8..f4938f6 100644
+--- a/net/sctp/transport.c
++++ b/net/sctp/transport.c
+@@ -260,7 +260,7 @@ void sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu)
+ if (unlikely(pmtu < SCTP_DEFAULT_MINSEGMENT)) {
+ printk(KERN_WARNING "%s: Reported pmtu %d too low, "
+ "using default minimum of %d\n",
+- __FUNCTION__, pmtu,
++ __func__, pmtu,
+ SCTP_DEFAULT_MINSEGMENT);
+ /* Use default minimum segment size and disable
+ * pmtu discovery on this transport.
+@@ -388,7 +388,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt)
+ tp->rto_pending = 0;
+
+ SCTP_DEBUG_PRINTK("%s: transport: %p, rtt: %d, srtt: %d "
+- "rttvar: %d, rto: %ld\n", __FUNCTION__,
++ "rttvar: %d, rto: %ld\n", __func__,
+ tp, rtt, tp->srtt, tp->rttvar, tp->rto);
+ }
+
+@@ -434,7 +434,7 @@ void sctp_transport_raise_cwnd(struct sctp_transport *transport,
+ SCTP_DEBUG_PRINTK("%s: SLOW START: transport: %p, "
+ "bytes_acked: %d, cwnd: %d, ssthresh: %d, "
+ "flight_size: %d, pba: %d\n",
+- __FUNCTION__,
++ __func__,
+ transport, bytes_acked, cwnd,
+ ssthresh, flight_size, pba);
+ } else {
+@@ -460,7 +460,7 @@ void sctp_transport_raise_cwnd(struct sctp_transport *transport,
+ SCTP_DEBUG_PRINTK("%s: CONGESTION AVOIDANCE: "
+ "transport: %p, bytes_acked: %d, cwnd: %d, "
+ "ssthresh: %d, flight_size: %d, pba: %d\n",
+- __FUNCTION__,
++ __func__,
+ transport, bytes_acked, cwnd,
+ ssthresh, flight_size, pba);
+ }
+@@ -546,7 +546,7 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport,
+
+ transport->partial_bytes_acked = 0;
+ SCTP_DEBUG_PRINTK("%s: transport: %p reason: %d cwnd: "
+- "%d ssthresh: %d\n", __FUNCTION__,
++ "%d ssthresh: %d\n", __func__,
+ transport, reason,
+ transport->cwnd, transport->ssthresh);
+ }
+diff --git a/net/socket.c b/net/socket.c
+index 9d3fbfb..66c4a8c 100644
+--- a/net/socket.c
++++ b/net/socket.c
+@@ -857,7 +857,7 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
+
+ sock = file->private_data;
+ sk = sock->sk;
+- net = sk->sk_net;
++ net = sock_net(sk);
+ if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
+ err = dev_ioctl(net, cmd, argp);
+ } else
+@@ -1375,7 +1375,7 @@ asmlinkage long sys_listen(int fd, int backlog)
+
+ sock = sockfd_lookup_light(fd, &err, &fput_needed);
+ if (sock) {
+- somaxconn = sock->sk->sk_net->sysctl_somaxconn;
++ somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
+ if ((unsigned)backlog > somaxconn)
+ backlog = somaxconn;
+
+@@ -2327,9 +2327,6 @@ int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
+ return sock->ops->shutdown(sock, how);
+ }
+
+-/* ABI emulation layers need these two */
+-EXPORT_SYMBOL(move_addr_to_kernel);
+-EXPORT_SYMBOL(move_addr_to_user);
+ EXPORT_SYMBOL(sock_create);
+ EXPORT_SYMBOL(sock_create_kern);
+ EXPORT_SYMBOL(sock_create_lite);
+diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
+index 92e1dbe..5369aa3 100644
+--- a/net/sunrpc/Makefile
++++ b/net/sunrpc/Makefile
+@@ -8,7 +8,7 @@ obj-$(CONFIG_SUNRPC_GSS) += auth_gss/
+ obj-$(CONFIG_SUNRPC_XPRT_RDMA) += xprtrdma/
+
+ sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \
+- auth.o auth_null.o auth_unix.o \
++ auth.o auth_null.o auth_unix.o auth_generic.o \
+ svc.o svcsock.o svcauth.o svcauth_unix.o \
+ rpcb_clnt.o timer.o xdr.o \
+ sunrpc_syms.o cache.o rpc_pipe.o \
+diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
+index eca941c..6bfea9e 100644
+--- a/net/sunrpc/auth.c
++++ b/net/sunrpc/auth.c
+@@ -11,6 +11,7 @@
+ #include <linux/module.h>
+ #include <linux/slab.h>
+ #include <linux/errno.h>
++#include <linux/hash.h>
+ #include <linux/sunrpc/clnt.h>
+ #include <linux/spinlock.h>
+
+@@ -219,6 +220,9 @@ rpcauth_destroy_credcache(struct rpc_auth *auth)
+ }
+ EXPORT_SYMBOL_GPL(rpcauth_destroy_credcache);
+
++
++#define RPC_AUTH_EXPIRY_MORATORIUM (60 * HZ)
++
+ /*
+ * Remove stale credentials. Avoid sleeping inside the loop.
+ */
+@@ -227,6 +231,7 @@ rpcauth_prune_expired(struct list_head *free, int nr_to_scan)
+ {
+ spinlock_t *cache_lock;
+ struct rpc_cred *cred;
++ unsigned long expired = jiffies - RPC_AUTH_EXPIRY_MORATORIUM;
+
+ while (!list_empty(&cred_unused)) {
+ cred = list_entry(cred_unused.next, struct rpc_cred, cr_lru);
+@@ -234,6 +239,10 @@ rpcauth_prune_expired(struct list_head *free, int nr_to_scan)
+ number_cred_unused--;
+ if (atomic_read(&cred->cr_count) != 0)
+ continue;
++ /* Enforce a 5 second garbage collection moratorium */
++ if (time_in_range(cred->cr_expire, expired, jiffies) &&
++ test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0)
++ continue;
+ cache_lock = &cred->cr_auth->au_credcache->lock;
+ spin_lock(cache_lock);
+ if (atomic_read(&cred->cr_count) == 0) {
+@@ -280,10 +289,9 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
+ struct hlist_node *pos;
+ struct rpc_cred *cred = NULL,
+ *entry, *new;
+- int nr = 0;
++ unsigned int nr;
+
+- if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS))
+- nr = acred->uid & RPC_CREDCACHE_MASK;
++ nr = hash_long(acred->uid, RPC_CREDCACHE_HASHBITS);
+
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) {
+@@ -356,7 +364,6 @@ rpcauth_lookupcred(struct rpc_auth *auth, int flags)
+ put_group_info(acred.group_info);
+ return ret;
+ }
+-EXPORT_SYMBOL_GPL(rpcauth_lookupcred);
+
+ void
+ rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred,
+@@ -375,41 +382,58 @@ rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred,
+ }
+ EXPORT_SYMBOL_GPL(rpcauth_init_cred);
+
+-struct rpc_cred *
+-rpcauth_bindcred(struct rpc_task *task)
++void
++rpcauth_generic_bind_cred(struct rpc_task *task, struct rpc_cred *cred)
++{
++ task->tk_msg.rpc_cred = get_rpccred(cred);
++ dprintk("RPC: %5u holding %s cred %p\n", task->tk_pid,
++ cred->cr_auth->au_ops->au_name, cred);
++}
++EXPORT_SYMBOL_GPL(rpcauth_generic_bind_cred);
++
++static void
++rpcauth_bind_root_cred(struct rpc_task *task)
+ {
+ struct rpc_auth *auth = task->tk_client->cl_auth;
+ struct auth_cred acred = {
+- .uid = current->fsuid,
+- .gid = current->fsgid,
+- .group_info = current->group_info,
++ .uid = 0,
++ .gid = 0,
+ };
+ struct rpc_cred *ret;
+- int flags = 0;
+
+ dprintk("RPC: %5u looking up %s cred\n",
+ task->tk_pid, task->tk_client->cl_auth->au_ops->au_name);
+- get_group_info(acred.group_info);
+- if (task->tk_flags & RPC_TASK_ROOTCREDS)
+- flags |= RPCAUTH_LOOKUP_ROOTCREDS;
+- ret = auth->au_ops->lookup_cred(auth, &acred, flags);
++ ret = auth->au_ops->lookup_cred(auth, &acred, 0);
++ if (!IS_ERR(ret))
++ task->tk_msg.rpc_cred = ret;
++ else
++ task->tk_status = PTR_ERR(ret);
++}
++
++static void
++rpcauth_bind_new_cred(struct rpc_task *task)
++{
++ struct rpc_auth *auth = task->tk_client->cl_auth;
++ struct rpc_cred *ret;
++
++ dprintk("RPC: %5u looking up %s cred\n",
++ task->tk_pid, auth->au_ops->au_name);
++ ret = rpcauth_lookupcred(auth, 0);
+ if (!IS_ERR(ret))
+ task->tk_msg.rpc_cred = ret;
+ else
+ task->tk_status = PTR_ERR(ret);
+- put_group_info(acred.group_info);
+- return ret;
+ }
+
+ void
+-rpcauth_holdcred(struct rpc_task *task)
++rpcauth_bindcred(struct rpc_task *task, struct rpc_cred *cred, int flags)
+ {
+- struct rpc_cred *cred = task->tk_msg.rpc_cred;
+- if (cred != NULL) {
+- get_rpccred(cred);
+- dprintk("RPC: %5u holding %s cred %p\n", task->tk_pid,
+- cred->cr_auth->au_ops->au_name, cred);
+- }
++ if (cred != NULL)
++ cred->cr_ops->crbind(task, cred);
++ else if (flags & RPC_TASK_ROOTCREDS)
++ rpcauth_bind_root_cred(task);
++ else
++ rpcauth_bind_new_cred(task);
+ }
+
+ void
+@@ -550,6 +574,7 @@ static struct shrinker rpc_cred_shrinker = {
+ void __init rpcauth_init_module(void)
+ {
+ rpc_init_authunix();
++ rpc_init_generic_auth();
+ register_shrinker(&rpc_cred_shrinker);
+ }
+
+diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c
+new file mode 100644
+index 0000000..d927d9f
+--- /dev/null
++++ b/net/sunrpc/auth_generic.c
+@@ -0,0 +1,177 @@
++/*
++ * Generic RPC credential
++ *
++ * Copyright (C) 2008, Trond Myklebust <Trond.Myklebust at netapp.com>
++ */
++
++#include <linux/err.h>
++#include <linux/types.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/sunrpc/auth.h>
++#include <linux/sunrpc/clnt.h>
++#include <linux/sunrpc/debug.h>
++#include <linux/sunrpc/sched.h>
++
++#ifdef RPC_DEBUG
++# define RPCDBG_FACILITY RPCDBG_AUTH
++#endif
++
++#define RPC_ANONYMOUS_USERID ((uid_t)-2)
++#define RPC_ANONYMOUS_GROUPID ((gid_t)-2)
++
++struct generic_cred {
++ struct rpc_cred gc_base;
++ struct auth_cred acred;
++};
++
++static struct rpc_auth generic_auth;
++static struct rpc_cred_cache generic_cred_cache;
++static const struct rpc_credops generic_credops;
++
++/*
++ * Public call interface
++ */
++struct rpc_cred *rpc_lookup_cred(void)
++{
++ return rpcauth_lookupcred(&generic_auth, 0);
++}
++EXPORT_SYMBOL_GPL(rpc_lookup_cred);
++
++/*
++ * Public call interface for looking up machine creds.
++ */
++struct rpc_cred *rpc_lookup_machine_cred(void)
++{
++ struct auth_cred acred = {
++ .uid = RPC_ANONYMOUS_USERID,
++ .gid = RPC_ANONYMOUS_GROUPID,
++ .machine_cred = 1,
++ };
++
++ dprintk("RPC: looking up machine cred\n");
++ return generic_auth.au_ops->lookup_cred(&generic_auth, &acred, 0);
++}
++EXPORT_SYMBOL_GPL(rpc_lookup_machine_cred);
++
++static void
++generic_bind_cred(struct rpc_task *task, struct rpc_cred *cred)
++{
++ struct rpc_auth *auth = task->tk_client->cl_auth;
++ struct auth_cred *acred = &container_of(cred, struct generic_cred, gc_base)->acred;
++ struct rpc_cred *ret;
++
++ ret = auth->au_ops->lookup_cred(auth, acred, 0);
++ if (!IS_ERR(ret))
++ task->tk_msg.rpc_cred = ret;
++ else
++ task->tk_status = PTR_ERR(ret);
++}
++
++/*
++ * Lookup generic creds for current process
++ */
++static struct rpc_cred *
++generic_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
++{
++ return rpcauth_lookup_credcache(&generic_auth, acred, flags);
++}
++
++static struct rpc_cred *
++generic_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
++{
++ struct generic_cred *gcred;
++
++ gcred = kmalloc(sizeof(*gcred), GFP_KERNEL);
++ if (gcred == NULL)
++ return ERR_PTR(-ENOMEM);
++
++ rpcauth_init_cred(&gcred->gc_base, acred, &generic_auth, &generic_credops);
++ gcred->gc_base.cr_flags = 1UL << RPCAUTH_CRED_UPTODATE;
++
++ gcred->acred.uid = acred->uid;
++ gcred->acred.gid = acred->gid;
++ gcred->acred.group_info = acred->group_info;
++ if (gcred->acred.group_info != NULL)
++ get_group_info(gcred->acred.group_info);
++ gcred->acred.machine_cred = acred->machine_cred;
++
++ dprintk("RPC: allocated %s cred %p for uid %d gid %d\n",
++ gcred->acred.machine_cred ? "machine" : "generic",
++ gcred, acred->uid, acred->gid);
++ return &gcred->gc_base;
++}
++
++static void
++generic_free_cred(struct rpc_cred *cred)
++{
++ struct generic_cred *gcred = container_of(cred, struct generic_cred, gc_base);
++
++ dprintk("RPC: generic_free_cred %p\n", gcred);
++ if (gcred->acred.group_info != NULL)
++ put_group_info(gcred->acred.group_info);
++ kfree(gcred);
++}
++
++static void
++generic_free_cred_callback(struct rcu_head *head)
++{
++ struct rpc_cred *cred = container_of(head, struct rpc_cred, cr_rcu);
++ generic_free_cred(cred);
++}
++
++static void
++generic_destroy_cred(struct rpc_cred *cred)
++{
++ call_rcu(&cred->cr_rcu, generic_free_cred_callback);
++}
++
++/*
++ * Match credentials against current process creds.
++ */
++static int
++generic_match(struct auth_cred *acred, struct rpc_cred *cred, int flags)
++{
++ struct generic_cred *gcred = container_of(cred, struct generic_cred, gc_base);
++
++ if (gcred->acred.uid != acred->uid ||
++ gcred->acred.gid != acred->gid ||
++ gcred->acred.group_info != acred->group_info ||
++ gcred->acred.machine_cred != acred->machine_cred)
++ return 0;
++ return 1;
++}
++
++void __init rpc_init_generic_auth(void)
++{
++ spin_lock_init(&generic_cred_cache.lock);
++}
++
++void __exit rpc_destroy_generic_auth(void)
++{
++ rpcauth_clear_credcache(&generic_cred_cache);
++}
++
++static struct rpc_cred_cache generic_cred_cache = {
++ {{ NULL, },},
++};
++
++static const struct rpc_authops generic_auth_ops = {
++ .owner = THIS_MODULE,
++ .au_name = "Generic",
++ .lookup_cred = generic_lookup_cred,
++ .crcreate = generic_create_cred,
++};
++
++static struct rpc_auth generic_auth = {
++ .au_ops = &generic_auth_ops,
++ .au_count = ATOMIC_INIT(0),
++ .au_credcache = &generic_cred_cache,
++};
++
++static const struct rpc_credops generic_credops = {
++ .cr_name = "Generic cred",
++ .crdestroy = generic_destroy_cred,
++ .crbind = generic_bind_cred,
++ .crmatch = generic_match,
++};
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index 6dac387..cc12d5f 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -114,27 +114,14 @@ static void
+ gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx)
+ {
+ struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
+- struct gss_cl_ctx *old;
+
+- old = gss_cred->gc_ctx;
++ if (!test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags))
++ return;
++ gss_get_ctx(ctx);
+ rcu_assign_pointer(gss_cred->gc_ctx, ctx);
+ set_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
++ smp_mb__before_clear_bit();
+ clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags);
+- if (old)
+- gss_put_ctx(old);
+-}
+-
+-static int
+-gss_cred_is_uptodate_ctx(struct rpc_cred *cred)
+-{
+- struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
+- int res = 0;
+-
+- rcu_read_lock();
+- if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) && gss_cred->gc_ctx)
+- res = 1;
+- rcu_read_unlock();
+- return res;
+ }
+
+ static const void *
+@@ -266,6 +253,7 @@ gss_release_msg(struct gss_upcall_msg *gss_msg)
+ BUG_ON(!list_empty(&gss_msg->list));
+ if (gss_msg->ctx != NULL)
+ gss_put_ctx(gss_msg->ctx);
++ rpc_destroy_wait_queue(&gss_msg->rpc_waitqueue);
+ kfree(gss_msg);
+ }
+
+@@ -339,7 +327,7 @@ gss_upcall_callback(struct rpc_task *task)
+
+ spin_lock(&inode->i_lock);
+ if (gss_msg->ctx)
+- gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_get_ctx(gss_msg->ctx));
++ gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_msg->ctx);
+ else
+ task->tk_status = gss_msg->msg.errno;
+ gss_cred->gc_upcall = NULL;
+@@ -370,9 +358,16 @@ gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid)
+ static struct gss_upcall_msg *
+ gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cred *cred)
+ {
++ struct gss_cred *gss_cred = container_of(cred,
++ struct gss_cred, gc_base);
+ struct gss_upcall_msg *gss_new, *gss_msg;
++ uid_t uid = cred->cr_uid;
+
+- gss_new = gss_alloc_msg(gss_auth, cred->cr_uid);
++ /* Special case: rpc.gssd assumes that uid == 0 implies machine creds */
++ if (gss_cred->gc_machine_cred != 0)
++ uid = 0;
++
++ gss_new = gss_alloc_msg(gss_auth, uid);
+ if (gss_new == NULL)
+ return ERR_PTR(-ENOMEM);
+ gss_msg = gss_add_msg(gss_auth, gss_new);
+@@ -408,13 +403,17 @@ gss_refresh_upcall(struct rpc_task *task)
+ }
+ spin_lock(&inode->i_lock);
+ if (gss_cred->gc_upcall != NULL)
+- rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL, NULL);
+- else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) {
++ rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL);
++ else if (gss_msg->ctx != NULL) {
++ gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_msg->ctx);
++ gss_cred->gc_upcall = NULL;
++ rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
++ } else if (gss_msg->msg.errno >= 0) {
+ task->tk_timeout = 0;
+ gss_cred->gc_upcall = gss_msg;
+ /* gss_upcall_callback will release the reference to gss_upcall_msg */
+ atomic_inc(&gss_msg->count);
+- rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback, NULL);
++ rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback);
+ } else
+ err = gss_msg->msg.errno;
+ spin_unlock(&inode->i_lock);
+@@ -454,7 +453,7 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
+ schedule();
+ }
+ if (gss_msg->ctx)
+- gss_cred_set_ctx(cred, gss_get_ctx(gss_msg->ctx));
++ gss_cred_set_ctx(cred, gss_msg->ctx);
+ else
+ err = gss_msg->msg.errno;
+ spin_unlock(&inode->i_lock);
+@@ -625,7 +624,7 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
+ gss_auth->mech = gss_mech_get_by_pseudoflavor(flavor);
+ if (!gss_auth->mech) {
+ printk(KERN_WARNING "%s: Pseudoflavor %d not found!\n",
+- __FUNCTION__, flavor);
++ __func__, flavor);
+ goto err_free;
+ }
+ gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor);
+@@ -709,7 +708,7 @@ gss_destroying_context(struct rpc_cred *cred)
+ struct rpc_task *task;
+
+ if (gss_cred->gc_ctx == NULL ||
+- gss_cred->gc_ctx->gc_proc == RPC_GSS_PROC_DESTROY)
++ test_and_clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0)
+ return 0;
+
+ gss_cred->gc_ctx->gc_proc = RPC_GSS_PROC_DESTROY;
+@@ -719,7 +718,7 @@ gss_destroying_context(struct rpc_cred *cred)
+ * by the RPC call or by the put_rpccred() below */
+ get_rpccred(cred);
+
+- task = rpc_call_null(gss_auth->client, cred, RPC_TASK_ASYNC);
++ task = rpc_call_null(gss_auth->client, cred, RPC_TASK_ASYNC|RPC_TASK_SOFT);
+ if (!IS_ERR(task))
+ rpc_put_task(task);
+
+@@ -817,6 +816,7 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
+ */
+ cred->gc_base.cr_flags = 1UL << RPCAUTH_CRED_NEW;
+ cred->gc_service = gss_auth->service;
++ cred->gc_machine_cred = acred->machine_cred;
+ kref_get(&gss_auth->kref);
+ return &cred->gc_base;
+
+@@ -843,17 +843,16 @@ gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags)
+ {
+ struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base);
+
+- /*
+- * If the searchflags have set RPCAUTH_LOOKUP_NEW, then
+- * we don't really care if the credential has expired or not,
+- * since the caller should be prepared to reinitialise it.
+- */
+- if ((flags & RPCAUTH_LOOKUP_NEW) && test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags))
++ if (test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags))
+ goto out;
+ /* Don't match with creds that have expired. */
+- if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry))
++ if (time_after(jiffies, gss_cred->gc_ctx->gc_expiry))
++ return 0;
++ if (!test_bit(RPCAUTH_CRED_UPTODATE, &rc->cr_flags))
+ return 0;
+ out:
++ if (acred->machine_cred != gss_cred->gc_machine_cred)
++ return 0;
+ return (rc->cr_uid == acred->uid);
+ }
+
+@@ -917,16 +916,48 @@ out_put_ctx:
+ return NULL;
+ }
+
++static int gss_renew_cred(struct rpc_task *task)
++{
++ struct rpc_cred *oldcred = task->tk_msg.rpc_cred;
++ struct gss_cred *gss_cred = container_of(oldcred,
++ struct gss_cred,
++ gc_base);
++ struct rpc_auth *auth = oldcred->cr_auth;
++ struct auth_cred acred = {
++ .uid = oldcred->cr_uid,
++ .machine_cred = gss_cred->gc_machine_cred,
++ };
++ struct rpc_cred *new;
++
++ new = gss_lookup_cred(auth, &acred, RPCAUTH_LOOKUP_NEW);
++ if (IS_ERR(new))
++ return PTR_ERR(new);
++ task->tk_msg.rpc_cred = new;
++ put_rpccred(oldcred);
++ return 0;
++}
++
+ /*
+ * Refresh credentials. XXX - finish
+ */
+ static int
+ gss_refresh(struct rpc_task *task)
+ {
++ struct rpc_cred *cred = task->tk_msg.rpc_cred;
++ int ret = 0;
++
++ if (!test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags) &&
++ !test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags)) {
++ ret = gss_renew_cred(task);
++ if (ret < 0)
++ goto out;
++ cred = task->tk_msg.rpc_cred;
++ }
+
+- if (!gss_cred_is_uptodate_ctx(task->tk_msg.rpc_cred))
+- return gss_refresh_upcall(task);
+- return 0;
++ if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags))
++ ret = gss_refresh_upcall(task);
++out:
++ return ret;
+ }
+
+ /* Dummy refresh routine: used only when destroying the context */
+@@ -1286,9 +1317,7 @@ out:
+ static const struct rpc_authops authgss_ops = {
+ .owner = THIS_MODULE,
+ .au_flavor = RPC_AUTH_GSS,
+-#ifdef RPC_DEBUG
+ .au_name = "RPCSEC_GSS",
+-#endif
+ .create = gss_create,
+ .destroy = gss_destroy,
+ .lookup_cred = gss_lookup_cred,
+@@ -1299,6 +1328,7 @@ static const struct rpc_credops gss_credops = {
+ .cr_name = "AUTH_GSS",
+ .crdestroy = gss_destroy_cred,
+ .cr_init = gss_cred_init,
++ .crbind = rpcauth_generic_bind_cred,
+ .crmatch = gss_match,
+ .crmarshal = gss_marshal,
+ .crrefresh = gss_refresh,
+@@ -1310,6 +1340,7 @@ static const struct rpc_credops gss_credops = {
+ static const struct rpc_credops gss_nullops = {
+ .cr_name = "AUTH_GSS",
+ .crdestroy = gss_destroy_cred,
++ .crbind = rpcauth_generic_bind_cred,
+ .crmatch = gss_match,
+ .crmarshal = gss_marshal,
+ .crrefresh = gss_refresh_null,
+diff --git a/net/sunrpc/auth_gss/gss_generic_token.c b/net/sunrpc/auth_gss/gss_generic_token.c
+index ea8c92e..d83b881 100644
+--- a/net/sunrpc/auth_gss/gss_generic_token.c
++++ b/net/sunrpc/auth_gss/gss_generic_token.c
+@@ -148,7 +148,7 @@ int
+ g_token_size(struct xdr_netobj *mech, unsigned int body_size)
+ {
+ /* set body_size to sequence contents size */
+- body_size += 4 + (int) mech->len; /* NEED overflow check */
++ body_size += 2 + (int) mech->len; /* NEED overflow check */
+ return(1 + der_length_size(body_size) + body_size);
+ }
+
+@@ -161,7 +161,7 @@ void
+ g_make_token_header(struct xdr_netobj *mech, int body_size, unsigned char **buf)
+ {
+ *(*buf)++ = 0x60;
+- der_write_length(buf, 4 + mech->len + body_size);
++ der_write_length(buf, 2 + mech->len + body_size);
+ *(*buf)++ = 0x06;
+ *(*buf)++ = (unsigned char) mech->len;
+ TWRITE_STR(*buf, mech->data, ((int) mech->len));
+diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+index 0dd7923..1d52308 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
++++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+@@ -66,8 +66,8 @@ krb5_encrypt(
+ goto out;
+
+ if (crypto_blkcipher_ivsize(tfm) > 16) {
+- dprintk("RPC: gss_k5encrypt: tfm iv size to large %d\n",
+- crypto_blkcipher_ivsize(tfm));
++ dprintk("RPC: gss_k5encrypt: tfm iv size too large %d\n",
++ crypto_blkcipher_ivsize(tfm));
+ goto out;
+ }
+
+@@ -102,7 +102,7 @@ krb5_decrypt(
+ goto out;
+
+ if (crypto_blkcipher_ivsize(tfm) > 16) {
+- dprintk("RPC: gss_k5decrypt: tfm iv size to large %d\n",
++ dprintk("RPC: gss_k5decrypt: tfm iv size too large %d\n",
+ crypto_blkcipher_ivsize(tfm));
+ goto out;
+ }
+diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
+index dedcbd6..5f1d36d 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
+@@ -87,10 +87,10 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
+
+ now = get_seconds();
+
+- token->len = g_token_size(&ctx->mech_used, 22);
++ token->len = g_token_size(&ctx->mech_used, 24);
+
+ ptr = token->data;
+- g_make_token_header(&ctx->mech_used, 22, &ptr);
++ g_make_token_header(&ctx->mech_used, 24, &ptr);
+
+ *ptr++ = (unsigned char) ((KG_TOK_MIC_MSG>>8)&0xff);
+ *ptr++ = (unsigned char) (KG_TOK_MIC_MSG&0xff);
+@@ -109,15 +109,14 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
+ md5cksum.data, md5cksum.len))
+ return GSS_S_FAILURE;
+
+- memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - KRB5_CKSUM_LENGTH,
+- KRB5_CKSUM_LENGTH);
++ memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - 8, 8);
+
+ spin_lock(&krb5_seq_lock);
+ seq_send = ctx->seq_send++;
+ spin_unlock(&krb5_seq_lock);
+
+ if (krb5_make_seq_num(ctx->seq, ctx->initiate ? 0 : 0xff,
+- ctx->seq_send, krb5_hdr + 16, krb5_hdr + 8))
++ seq_send, krb5_hdr + 16, krb5_hdr + 8))
+ return GSS_S_FAILURE;
+
+ return (ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE;
+diff --git a/net/sunrpc/auth_gss/gss_krb5_seqnum.c b/net/sunrpc/auth_gss/gss_krb5_seqnum.c
+index 43f3421..f160be6 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_seqnum.c
++++ b/net/sunrpc/auth_gss/gss_krb5_seqnum.c
+@@ -43,7 +43,7 @@
+ s32
+ krb5_make_seq_num(struct crypto_blkcipher *key,
+ int direction,
+- s32 seqnum,
++ u32 seqnum,
+ unsigned char *cksum, unsigned char *buf)
+ {
+ unsigned char plain[8];
+@@ -65,7 +65,7 @@ s32
+ krb5_get_seq_num(struct crypto_blkcipher *key,
+ unsigned char *cksum,
+ unsigned char *buf,
+- int *direction, s32 * seqnum)
++ int *direction, u32 *seqnum)
+ {
+ s32 code;
+ unsigned char plain[8];
+diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
+index e30a993..d91a5d0 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
++++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
+@@ -82,7 +82,7 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
+ struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata};
+ s32 now;
+ int direction;
+- s32 seqnum;
++ u32 seqnum;
+ unsigned char *ptr = (unsigned char *)read_token->data;
+ int bodysize;
+
+diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+index 3bdc527..b00b1b4 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
++++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+@@ -137,7 +137,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
+ BUG_ON((buf->len - offset) % blocksize);
+ plainlen = blocksize + buf->len - offset;
+
+- headlen = g_token_size(&kctx->mech_used, 22 + plainlen) -
++ headlen = g_token_size(&kctx->mech_used, 24 + plainlen) -
+ (buf->len - offset);
+
+ ptr = buf->head[0].iov_base + offset;
+@@ -149,7 +149,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
+ buf->len += headlen;
+ BUG_ON((buf->len - offset - headlen) % blocksize);
+
+- g_make_token_header(&kctx->mech_used, 22 + plainlen, &ptr);
++ g_make_token_header(&kctx->mech_used, 24 + plainlen, &ptr);
+
+
+ *ptr++ = (unsigned char) ((KG_TOK_WRAP_MSG>>8)&0xff);
+@@ -176,9 +176,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
+ if (krb5_encrypt(kctx->seq, NULL, md5cksum.data,
+ md5cksum.data, md5cksum.len))
+ return GSS_S_FAILURE;
+- memcpy(krb5_hdr + 16,
+- md5cksum.data + md5cksum.len - KRB5_CKSUM_LENGTH,
+- KRB5_CKSUM_LENGTH);
++ memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - 8, 8);
+
+ spin_lock(&krb5_seq_lock);
+ seq_send = kctx->seq_send++;
+diff --git a/net/sunrpc/auth_gss/gss_spkm3_seal.c b/net/sunrpc/auth_gss/gss_spkm3_seal.c
+index abf17ce..c832712 100644
+--- a/net/sunrpc/auth_gss/gss_spkm3_seal.c
++++ b/net/sunrpc/auth_gss/gss_spkm3_seal.c
+@@ -107,10 +107,10 @@ spkm3_make_token(struct spkm3_ctx *ctx,
+ tokenlen = 10 + ctxelen + 1 + md5elen + 1;
+
+ /* Create token header using generic routines */
+- token->len = g_token_size(&ctx->mech_used, tokenlen);
++ token->len = g_token_size(&ctx->mech_used, tokenlen + 2);
+
+ ptr = token->data;
+- g_make_token_header(&ctx->mech_used, tokenlen, &ptr);
++ g_make_token_header(&ctx->mech_used, tokenlen + 2, &ptr);
+
+ spkm3_make_mic_token(&ptr, tokenlen, &mic_hdr, &md5cksum, md5elen, md5zbit);
+ } else if (toktype == SPKM_WRAP_TOK) { /* Not Supported */
+diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
+index 481f984..5905d56 100644
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -1146,7 +1146,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
+ case RPC_GSS_SVC_INTEGRITY:
+ if (unwrap_integ_data(&rqstp->rq_arg,
+ gc->gc_seq, rsci->mechctx))
+- goto auth_err;
++ goto garbage_args;
+ /* placeholders for length and seq. number: */
+ svc_putnl(resv, 0);
+ svc_putnl(resv, 0);
+@@ -1154,7 +1154,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
+ case RPC_GSS_SVC_PRIVACY:
+ if (unwrap_priv_data(rqstp, &rqstp->rq_arg,
+ gc->gc_seq, rsci->mechctx))
+- goto auth_err;
++ goto garbage_args;
+ /* placeholders for length and seq. number: */
+ svc_putnl(resv, 0);
+ svc_putnl(resv, 0);
+@@ -1169,6 +1169,11 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
+ ret = SVC_OK;
+ goto out;
+ }
++garbage_args:
++ /* Restore write pointer to its original value: */
++ xdr_ressize_check(rqstp, reject_stat);
++ ret = SVC_GARBAGE;
++ goto out;
+ auth_err:
+ /* Restore write pointer to its original value: */
+ xdr_ressize_check(rqstp, reject_stat);
+diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c
+index 537d0e8..c70dd7f 100644
+--- a/net/sunrpc/auth_null.c
++++ b/net/sunrpc/auth_null.c
+@@ -104,9 +104,7 @@ nul_validate(struct rpc_task *task, __be32 *p)
+ const struct rpc_authops authnull_ops = {
+ .owner = THIS_MODULE,
+ .au_flavor = RPC_AUTH_NULL,
+-#ifdef RPC_DEBUG
+ .au_name = "NULL",
+-#endif
+ .create = nul_create,
+ .destroy = nul_destroy,
+ .lookup_cred = nul_lookup_cred,
+@@ -125,6 +123,7 @@ static
+ const struct rpc_credops null_credops = {
+ .cr_name = "AUTH_NULL",
+ .crdestroy = nul_destroy_cred,
++ .crbind = rpcauth_generic_bind_cred,
+ .crmatch = nul_match,
+ .crmarshal = nul_marshal,
+ .crrefresh = nul_refresh,
+diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c
+index 5ed91e5..44920b9 100644
+--- a/net/sunrpc/auth_unix.c
++++ b/net/sunrpc/auth_unix.c
+@@ -60,7 +60,8 @@ static struct rpc_cred *
+ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
+ {
+ struct unx_cred *cred;
+- int i;
++ unsigned int groups = 0;
++ unsigned int i;
+
+ dprintk("RPC: allocating UNIX cred for uid %d gid %d\n",
+ acred->uid, acred->gid);
+@@ -70,21 +71,17 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
+
+ rpcauth_init_cred(&cred->uc_base, acred, auth, &unix_credops);
+ cred->uc_base.cr_flags = 1UL << RPCAUTH_CRED_UPTODATE;
+- if (flags & RPCAUTH_LOOKUP_ROOTCREDS) {
+- cred->uc_uid = 0;
+- cred->uc_gid = 0;
+- cred->uc_gids[0] = NOGROUP;
+- } else {
+- int groups = acred->group_info->ngroups;
+- if (groups > NFS_NGROUPS)
+- groups = NFS_NGROUPS;
+-
+- cred->uc_gid = acred->gid;
+- for (i = 0; i < groups; i++)
+- cred->uc_gids[i] = GROUP_AT(acred->group_info, i);
+- if (i < NFS_NGROUPS)
+- cred->uc_gids[i] = NOGROUP;
+- }
++
++ if (acred->group_info != NULL)
++ groups = acred->group_info->ngroups;
++ if (groups > NFS_NGROUPS)
++ groups = NFS_NGROUPS;
++
++ cred->uc_gid = acred->gid;
++ for (i = 0; i < groups; i++)
++ cred->uc_gids[i] = GROUP_AT(acred->group_info, i);
++ if (i < NFS_NGROUPS)
++ cred->uc_gids[i] = NOGROUP;
+
+ return &cred->uc_base;
+ }
+@@ -118,26 +115,21 @@ static int
+ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags)
+ {
+ struct unx_cred *cred = container_of(rcred, struct unx_cred, uc_base);
+- int i;
++ unsigned int groups = 0;
++ unsigned int i;
+
+- if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS)) {
+- int groups;
+
+- if (cred->uc_uid != acred->uid
+- || cred->uc_gid != acred->gid)
+- return 0;
++ if (cred->uc_uid != acred->uid || cred->uc_gid != acred->gid)
++ return 0;
+
++ if (acred->group_info != NULL)
+ groups = acred->group_info->ngroups;
+- if (groups > NFS_NGROUPS)
+- groups = NFS_NGROUPS;
+- for (i = 0; i < groups ; i++)
+- if (cred->uc_gids[i] != GROUP_AT(acred->group_info, i))
+- return 0;
+- return 1;
+- }
+- return (cred->uc_uid == 0
+- && cred->uc_gid == 0
+- && cred->uc_gids[0] == (gid_t) NOGROUP);
++ if (groups > NFS_NGROUPS)
++ groups = NFS_NGROUPS;
++ for (i = 0; i < groups ; i++)
++ if (cred->uc_gids[i] != GROUP_AT(acred->group_info, i))
++ return 0;
++ return 1;
+ }
+
+ /*
+@@ -218,9 +210,7 @@ void __init rpc_init_authunix(void)
+ const struct rpc_authops authunix_ops = {
+ .owner = THIS_MODULE,
+ .au_flavor = RPC_AUTH_UNIX,
+-#ifdef RPC_DEBUG
+ .au_name = "UNIX",
+-#endif
+ .create = unx_create,
+ .destroy = unx_destroy,
+ .lookup_cred = unx_lookup_cred,
+@@ -245,6 +235,7 @@ static
+ const struct rpc_credops unix_credops = {
+ .cr_name = "AUTH_UNIX",
+ .crdestroy = unx_destroy_cred,
++ .crbind = rpcauth_generic_bind_cred,
+ .crmatch = unx_match,
+ .crmarshal = unx_marshal,
+ .crrefresh = unx_refresh,
+diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
+index b5f2786..d75530f 100644
+--- a/net/sunrpc/cache.c
++++ b/net/sunrpc/cache.c
+@@ -571,7 +571,6 @@ static int cache_defer_req(struct cache_req *req, struct cache_head *item)
+ return -ETIMEDOUT;
+
+ dreq->item = item;
+- dreq->recv_time = get_seconds();
+
+ spin_lock(&cache_defer_lock);
+
+diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
+index 8834d68..8945307 100644
+--- a/net/sunrpc/clnt.c
++++ b/net/sunrpc/clnt.c
+@@ -43,7 +43,7 @@
+
+ #define dprint_status(t) \
+ dprintk("RPC: %5u %s (status %d)\n", t->tk_pid, \
+- __FUNCTION__, t->tk_status)
++ __func__, t->tk_status)
+
+ /*
+ * All RPC clients are linked into this list
+@@ -368,7 +368,7 @@ out_no_path:
+ out_no_stats:
+ kfree(new);
+ out_no_clnt:
+- dprintk("RPC: %s: returned error %d\n", __FUNCTION__, err);
++ dprintk("RPC: %s: returned error %d\n", __func__, err);
+ return ERR_PTR(err);
+ }
+ EXPORT_SYMBOL_GPL(rpc_clone_client);
+@@ -544,7 +544,7 @@ EXPORT_SYMBOL_GPL(rpc_run_task);
+ * @msg: RPC call parameters
+ * @flags: RPC call flags
+ */
+-int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
++int rpc_call_sync(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags)
+ {
+ struct rpc_task *task;
+ struct rpc_task_setup task_setup_data = {
+@@ -575,7 +575,7 @@ EXPORT_SYMBOL_GPL(rpc_call_sync);
+ * @data: user call data
+ */
+ int
+-rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
++rpc_call_async(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags,
+ const struct rpc_call_ops *tk_ops, void *data)
+ {
+ struct rpc_task *task;
+@@ -752,7 +752,7 @@ call_reserveresult(struct rpc_task *task)
+ }
+
+ printk(KERN_ERR "%s: status=%d, but no request slot, exiting\n",
+- __FUNCTION__, status);
++ __func__, status);
+ rpc_exit(task, -EIO);
+ return;
+ }
+@@ -763,7 +763,7 @@ call_reserveresult(struct rpc_task *task)
+ */
+ if (task->tk_rqstp) {
+ printk(KERN_ERR "%s: status=%d, request allocated anyway\n",
+- __FUNCTION__, status);
++ __func__, status);
+ xprt_release(task);
+ }
+
+@@ -775,7 +775,7 @@ call_reserveresult(struct rpc_task *task)
+ break;
+ default:
+ printk(KERN_ERR "%s: unrecognized error %d, exiting\n",
+- __FUNCTION__, status);
++ __func__, status);
+ break;
+ }
+ rpc_exit(task, status);
+@@ -1062,7 +1062,7 @@ call_transmit(struct rpc_task *task)
+ if (task->tk_msg.rpc_proc->p_decode != NULL)
+ return;
+ task->tk_action = rpc_exit_task;
+- rpc_wake_up_task(task);
++ rpc_wake_up_queued_task(&task->tk_xprt->pending, task);
+ }
+
+ /*
+@@ -1116,7 +1116,8 @@ call_status(struct rpc_task *task)
+ case -ETIMEDOUT:
+ task->tk_action = call_timeout;
+ if (task->tk_client->cl_discrtry)
+- xprt_force_disconnect(task->tk_xprt);
++ xprt_conditional_disconnect(task->tk_xprt,
++ req->rq_connect_cookie);
+ break;
+ case -ECONNREFUSED:
+ case -ENOTCONN:
+@@ -1168,6 +1169,11 @@ call_timeout(struct rpc_task *task)
+ clnt->cl_protname, clnt->cl_server);
+ }
+ rpc_force_rebind(clnt);
++ /*
++ * Did our request time out due to an RPCSEC_GSS out-of-sequence
++ * event? RFC2203 requires the server to drop all such requests.
++ */
++ rpcauth_invalcred(task);
+
+ retry:
+ clnt->cl_stats->rpcretrans++;
+@@ -1195,18 +1201,6 @@ call_decode(struct rpc_task *task)
+ task->tk_flags &= ~RPC_CALL_MAJORSEEN;
+ }
+
+- if (task->tk_status < 12) {
+- if (!RPC_IS_SOFT(task)) {
+- task->tk_action = call_bind;
+- clnt->cl_stats->rpcretrans++;
+- goto out_retry;
+- }
+- dprintk("RPC: %s: too small RPC reply size (%d bytes)\n",
+- clnt->cl_protname, task->tk_status);
+- task->tk_action = call_timeout;
+- goto out_retry;
+- }
+-
+ /*
+ * Ensure that we see all writes made by xprt_complete_rqst()
+ * before it changed req->rq_received.
+@@ -1218,6 +1212,18 @@ call_decode(struct rpc_task *task)
+ WARN_ON(memcmp(&req->rq_rcv_buf, &req->rq_private_buf,
+ sizeof(req->rq_rcv_buf)) != 0);
+
++ if (req->rq_rcv_buf.len < 12) {
++ if (!RPC_IS_SOFT(task)) {
++ task->tk_action = call_bind;
++ clnt->cl_stats->rpcretrans++;
++ goto out_retry;
++ }
++ dprintk("RPC: %s: too small RPC reply size (%d bytes)\n",
++ clnt->cl_protname, task->tk_status);
++ task->tk_action = call_timeout;
++ goto out_retry;
++ }
++
+ /* Verify the RPC header */
+ p = call_verify(task);
+ if (IS_ERR(p)) {
+@@ -1236,10 +1242,14 @@ call_decode(struct rpc_task *task)
+ task->tk_status);
+ return;
+ out_retry:
+- req->rq_received = req->rq_private_buf.len = 0;
+ task->tk_status = 0;
+- if (task->tk_client->cl_discrtry)
+- xprt_force_disconnect(task->tk_xprt);
++ /* Note: call_verify() may have freed the RPC slot */
++ if (task->tk_rqstp == req) {
++ req->rq_received = req->rq_rcv_buf.len = 0;
++ if (task->tk_client->cl_discrtry)
++ xprt_conditional_disconnect(task->tk_xprt,
++ req->rq_connect_cookie);
++ }
+ }
+
+ /*
+@@ -1323,7 +1333,7 @@ call_verify(struct rpc_task *task)
+ * undefined results
+ */
+ dprintk("RPC: %5u %s: XDR representation not a multiple of"
+- " 4 bytes: 0x%x\n", task->tk_pid, __FUNCTION__,
++ " 4 bytes: 0x%x\n", task->tk_pid, __func__,
+ task->tk_rqstp->rq_rcv_buf.len);
+ goto out_eio;
+ }
+@@ -1333,7 +1343,7 @@ call_verify(struct rpc_task *task)
+
+ if ((n = ntohl(*p++)) != RPC_REPLY) {
+ dprintk("RPC: %5u %s: not an RPC reply: %x\n",
+- task->tk_pid, __FUNCTION__, n);
++ task->tk_pid, __func__, n);
+ goto out_garbage;
+ }
+ if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) {
+@@ -1345,13 +1355,13 @@ call_verify(struct rpc_task *task)
+ case RPC_MISMATCH:
+ dprintk("RPC: %5u %s: RPC call version "
+ "mismatch!\n",
+- task->tk_pid, __FUNCTION__);
++ task->tk_pid, __func__);
+ error = -EPROTONOSUPPORT;
+ goto out_err;
+ default:
+ dprintk("RPC: %5u %s: RPC call rejected, "
+ "unknown error: %x\n",
+- task->tk_pid, __FUNCTION__, n);
++ task->tk_pid, __func__, n);
+ goto out_eio;
+ }
+ if (--len < 0)
+@@ -1365,7 +1375,7 @@ call_verify(struct rpc_task *task)
+ break;
+ task->tk_cred_retry--;
+ dprintk("RPC: %5u %s: retry stale creds\n",
+- task->tk_pid, __FUNCTION__);
++ task->tk_pid, __func__);
+ rpcauth_invalcred(task);
+ /* Ensure we obtain a new XID! */
+ xprt_release(task);
+@@ -1378,7 +1388,7 @@ call_verify(struct rpc_task *task)
+ break;
+ task->tk_garb_retry--;
+ dprintk("RPC: %5u %s: retry garbled creds\n",
+- task->tk_pid, __FUNCTION__);
++ task->tk_pid, __func__);
+ task->tk_action = call_bind;
+ goto out_retry;
+ case RPC_AUTH_TOOWEAK:
+@@ -1387,16 +1397,16 @@ call_verify(struct rpc_task *task)
+ break;
+ default:
+ dprintk("RPC: %5u %s: unknown auth error: %x\n",
+- task->tk_pid, __FUNCTION__, n);
++ task->tk_pid, __func__, n);
+ error = -EIO;
+ }
+ dprintk("RPC: %5u %s: call rejected %d\n",
+- task->tk_pid, __FUNCTION__, n);
++ task->tk_pid, __func__, n);
+ goto out_err;
+ }
+ if (!(p = rpcauth_checkverf(task, p))) {
+ dprintk("RPC: %5u %s: auth check failed\n",
+- task->tk_pid, __FUNCTION__);
++ task->tk_pid, __func__);
+ goto out_garbage; /* bad verifier, retry */
+ }
+ len = p - (__be32 *)iov->iov_base - 1;
+@@ -1407,14 +1417,14 @@ call_verify(struct rpc_task *task)
+ return p;
+ case RPC_PROG_UNAVAIL:
+ dprintk("RPC: %5u %s: program %u is unsupported by server %s\n",
+- task->tk_pid, __FUNCTION__,
++ task->tk_pid, __func__,
+ (unsigned int)task->tk_client->cl_prog,
+ task->tk_client->cl_server);
+ error = -EPFNOSUPPORT;
+ goto out_err;
+ case RPC_PROG_MISMATCH:
+ dprintk("RPC: %5u %s: program %u, version %u unsupported by "
+- "server %s\n", task->tk_pid, __FUNCTION__,
++ "server %s\n", task->tk_pid, __func__,
+ (unsigned int)task->tk_client->cl_prog,
+ (unsigned int)task->tk_client->cl_vers,
+ task->tk_client->cl_server);
+@@ -1423,7 +1433,7 @@ call_verify(struct rpc_task *task)
+ case RPC_PROC_UNAVAIL:
+ dprintk("RPC: %5u %s: proc %p unsupported by program %u, "
+ "version %u on server %s\n",
+- task->tk_pid, __FUNCTION__,
++ task->tk_pid, __func__,
+ task->tk_msg.rpc_proc,
+ task->tk_client->cl_prog,
+ task->tk_client->cl_vers,
+@@ -1432,11 +1442,11 @@ call_verify(struct rpc_task *task)
+ goto out_err;
+ case RPC_GARBAGE_ARGS:
+ dprintk("RPC: %5u %s: server saw garbage\n",
+- task->tk_pid, __FUNCTION__);
++ task->tk_pid, __func__);
+ break; /* retry */
+ default:
+ dprintk("RPC: %5u %s: server accept status: %x\n",
+- task->tk_pid, __FUNCTION__, n);
++ task->tk_pid, __func__, n);
+ /* Also retry */
+ }
+
+@@ -1445,7 +1455,7 @@ out_garbage:
+ if (task->tk_garb_retry) {
+ task->tk_garb_retry--;
+ dprintk("RPC: %5u %s: retrying\n",
+- task->tk_pid, __FUNCTION__);
++ task->tk_pid, __func__);
+ task->tk_action = call_bind;
+ out_retry:
+ return ERR_PTR(-EAGAIN);
+@@ -1455,11 +1465,11 @@ out_eio:
+ out_err:
+ rpc_exit(task, error);
+ dprintk("RPC: %5u %s: call failed with error %d\n", task->tk_pid,
+- __FUNCTION__, error);
++ __func__, error);
+ return ERR_PTR(error);
+ out_overflow:
+ dprintk("RPC: %5u %s: server reply was truncated.\n", task->tk_pid,
+- __FUNCTION__);
++ __func__);
+ goto out_garbage;
+ }
+
+@@ -1531,7 +1541,7 @@ void rpc_show_tasks(void)
+ proc = -1;
+
+ if (RPC_IS_QUEUED(t))
+- rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq);
++ rpc_waitq = rpc_qname(t->tk_waitqueue);
+
+ printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n",
+ t->tk_pid, proc,
+diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
+index 1b395a4..5a9b0e7 100644
+--- a/net/sunrpc/rpc_pipe.c
++++ b/net/sunrpc/rpc_pipe.c
+@@ -479,13 +479,13 @@ rpc_lookup_parent(char *path, struct nameidata *nd)
+ mnt = rpc_get_mount();
+ if (IS_ERR(mnt)) {
+ printk(KERN_WARNING "%s: %s failed to mount "
+- "pseudofilesystem \n", __FILE__, __FUNCTION__);
++ "pseudofilesystem \n", __FILE__, __func__);
+ return PTR_ERR(mnt);
+ }
+
+ if (vfs_path_lookup(mnt->mnt_root, mnt, path, LOOKUP_PARENT, nd)) {
+ printk(KERN_WARNING "%s: %s failed to find path %s\n",
+- __FILE__, __FUNCTION__, path);
++ __FILE__, __func__, path);
+ rpc_put_mount();
+ return -ENOENT;
+ }
+@@ -604,7 +604,7 @@ rpc_populate(struct dentry *parent,
+ out_bad:
+ mutex_unlock(&dir->i_mutex);
+ printk(KERN_WARNING "%s: %s failed to populate directory %s\n",
+- __FILE__, __FUNCTION__, parent->d_name.name);
++ __FILE__, __func__, parent->d_name.name);
+ return -ENOMEM;
+ }
+
+@@ -623,7 +623,7 @@ __rpc_mkdir(struct inode *dir, struct dentry *dentry)
+ return 0;
+ out_err:
+ printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %s\n",
+- __FILE__, __FUNCTION__, dentry->d_name.name);
++ __FILE__, __func__, dentry->d_name.name);
+ return -ENOMEM;
+ }
+
+@@ -715,7 +715,7 @@ err_depopulate:
+ err_dput:
+ dput(dentry);
+ printk(KERN_WARNING "%s: %s() failed to create directory %s (errno = %d)\n",
+- __FILE__, __FUNCTION__, path, error);
++ __FILE__, __func__, path, error);
+ dentry = ERR_PTR(error);
+ goto out;
+ }
+@@ -804,7 +804,7 @@ err_dput:
+ dput(dentry);
+ dentry = ERR_PTR(-ENOMEM);
+ printk(KERN_WARNING "%s: %s() failed to create pipe %s/%s (errno = %d)\n",
+- __FILE__, __FUNCTION__, parent->d_name.name, name,
++ __FILE__, __func__, parent->d_name.name, name,
+ -ENOMEM);
+ goto out;
+ }
+diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
+index 3164a08..0517967 100644
+--- a/net/sunrpc/rpcb_clnt.c
++++ b/net/sunrpc/rpcb_clnt.c
+@@ -224,7 +224,7 @@ int rpcb_getport_sync(struct sockaddr_in *sin, u32 prog, u32 vers, int prot)
+ int status;
+
+ dprintk("RPC: %s(" NIPQUAD_FMT ", %u, %u, %d)\n",
+- __FUNCTION__, NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
++ __func__, NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
+
+ rpcb_clnt = rpcb_create(NULL, (struct sockaddr *)sin,
+ sizeof(*sin), prot, 2, 0);
+@@ -283,7 +283,7 @@ void rpcb_getport_async(struct rpc_task *task)
+ struct rpcb_info *info;
+
+ dprintk("RPC: %5u %s(%s, %u, %u, %d)\n",
+- task->tk_pid, __FUNCTION__,
++ task->tk_pid, __func__,
+ clnt->cl_server, clnt->cl_prog, clnt->cl_vers, xprt->prot);
+
+ /* Autobind on cloned rpc clients is discouraged */
+@@ -292,19 +292,19 @@ void rpcb_getport_async(struct rpc_task *task)
+ if (xprt_test_and_set_binding(xprt)) {
+ status = -EAGAIN; /* tell caller to check again */
+ dprintk("RPC: %5u %s: waiting for another binder\n",
+- task->tk_pid, __FUNCTION__);
++ task->tk_pid, __func__);
+ goto bailout_nowake;
+ }
+
+ /* Put self on queue before sending rpcbind request, in case
+ * rpcb_getport_done completes before we return from rpc_run_task */
+- rpc_sleep_on(&xprt->binding, task, NULL, NULL);
++ rpc_sleep_on(&xprt->binding, task, NULL);
+
+ /* Someone else may have bound if we slept */
+ if (xprt_bound(xprt)) {
+ status = 0;
+ dprintk("RPC: %5u %s: already bound\n",
+- task->tk_pid, __FUNCTION__);
++ task->tk_pid, __func__);
+ goto bailout_nofree;
+ }
+
+@@ -321,27 +321,27 @@ void rpcb_getport_async(struct rpc_task *task)
+ default:
+ status = -EAFNOSUPPORT;
+ dprintk("RPC: %5u %s: bad address family\n",
+- task->tk_pid, __FUNCTION__);
++ task->tk_pid, __func__);
+ goto bailout_nofree;
+ }
+ if (info[xprt->bind_index].rpc_proc == NULL) {
+ xprt->bind_index = 0;
+ status = -EPFNOSUPPORT;
+ dprintk("RPC: %5u %s: no more getport versions available\n",
+- task->tk_pid, __FUNCTION__);
++ task->tk_pid, __func__);
+ goto bailout_nofree;
+ }
+ bind_version = info[xprt->bind_index].rpc_vers;
+
+ dprintk("RPC: %5u %s: trying rpcbind version %u\n",
+- task->tk_pid, __FUNCTION__, bind_version);
++ task->tk_pid, __func__, bind_version);
+
+ rpcb_clnt = rpcb_create(clnt->cl_server, sap, salen, xprt->prot,
+ bind_version, 0);
+ if (IS_ERR(rpcb_clnt)) {
+ status = PTR_ERR(rpcb_clnt);
+ dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n",
+- task->tk_pid, __FUNCTION__, PTR_ERR(rpcb_clnt));
++ task->tk_pid, __func__, PTR_ERR(rpcb_clnt));
+ goto bailout_nofree;
+ }
+
+@@ -349,7 +349,7 @@ void rpcb_getport_async(struct rpc_task *task)
+ if (!map) {
+ status = -ENOMEM;
+ dprintk("RPC: %5u %s: no memory available\n",
+- task->tk_pid, __FUNCTION__);
++ task->tk_pid, __func__);
+ goto bailout_nofree;
+ }
+ map->r_prog = clnt->cl_prog;
+@@ -366,7 +366,7 @@ void rpcb_getport_async(struct rpc_task *task)
+ if (IS_ERR(child)) {
+ status = -EIO;
+ dprintk("RPC: %5u %s: rpc_run_task failed\n",
+- task->tk_pid, __FUNCTION__);
++ task->tk_pid, __func__);
+ goto bailout;
+ }
+ rpc_put_task(child);
+diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
+index 4c66912..6eab9bf 100644
+--- a/net/sunrpc/sched.c
++++ b/net/sunrpc/sched.c
+@@ -38,9 +38,9 @@ static struct kmem_cache *rpc_buffer_slabp __read_mostly;
+ static mempool_t *rpc_task_mempool __read_mostly;
+ static mempool_t *rpc_buffer_mempool __read_mostly;
+
+-static void __rpc_default_timer(struct rpc_task *task);
+ static void rpc_async_schedule(struct work_struct *);
+ static void rpc_release_task(struct rpc_task *task);
++static void __rpc_queue_timer_fn(unsigned long ptr);
+
+ /*
+ * RPC tasks sit here while waiting for conditions to improve.
+@@ -57,41 +57,30 @@ struct workqueue_struct *rpciod_workqueue;
+ * queue->lock and bh_disabled in order to avoid races within
+ * rpc_run_timer().
+ */
+-static inline void
+-__rpc_disable_timer(struct rpc_task *task)
++static void
++__rpc_disable_timer(struct rpc_wait_queue *queue, struct rpc_task *task)
+ {
++ if (task->tk_timeout == 0)
++ return;
+ dprintk("RPC: %5u disabling timer\n", task->tk_pid);
+- task->tk_timeout_fn = NULL;
+ task->tk_timeout = 0;
++ list_del(&task->u.tk_wait.timer_list);
++ if (list_empty(&queue->timer_list.list))
++ del_timer(&queue->timer_list.timer);
+ }
+
+-/*
+- * Run a timeout function.
+- * We use the callback in order to allow __rpc_wake_up_task()
+- * and friends to disable the timer synchronously on SMP systems
+- * without calling del_timer_sync(). The latter could cause a
+- * deadlock if called while we're holding spinlocks...
+- */
+-static void rpc_run_timer(struct rpc_task *task)
++static void
++rpc_set_queue_timer(struct rpc_wait_queue *queue, unsigned long expires)
+ {
+- void (*callback)(struct rpc_task *);
+-
+- callback = task->tk_timeout_fn;
+- task->tk_timeout_fn = NULL;
+- if (callback && RPC_IS_QUEUED(task)) {
+- dprintk("RPC: %5u running timer\n", task->tk_pid);
+- callback(task);
+- }
+- smp_mb__before_clear_bit();
+- clear_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate);
+- smp_mb__after_clear_bit();
++ queue->timer_list.expires = expires;
++ mod_timer(&queue->timer_list.timer, expires);
+ }
+
+ /*
+ * Set up a timer for the current task.
+ */
+-static inline void
+-__rpc_add_timer(struct rpc_task *task, rpc_action timer)
++static void
++__rpc_add_timer(struct rpc_wait_queue *queue, struct rpc_task *task)
+ {
+ if (!task->tk_timeout)
+ return;
+@@ -99,27 +88,10 @@ __rpc_add_timer(struct rpc_task *task, rpc_action timer)
+ dprintk("RPC: %5u setting alarm for %lu ms\n",
+ task->tk_pid, task->tk_timeout * 1000 / HZ);
+
+- if (timer)
+- task->tk_timeout_fn = timer;
+- else
+- task->tk_timeout_fn = __rpc_default_timer;
+- set_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate);
+- mod_timer(&task->tk_timer, jiffies + task->tk_timeout);
+-}
+-
+-/*
+- * Delete any timer for the current task. Because we use del_timer_sync(),
+- * this function should never be called while holding queue->lock.
+- */
+-static void
+-rpc_delete_timer(struct rpc_task *task)
+-{
+- if (RPC_IS_QUEUED(task))
+- return;
+- if (test_and_clear_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate)) {
+- del_singleshot_timer_sync(&task->tk_timer);
+- dprintk("RPC: %5u deleting timer\n", task->tk_pid);
+- }
++ task->u.tk_wait.expires = jiffies + task->tk_timeout;
++ if (list_empty(&queue->timer_list.list) || time_before(task->u.tk_wait.expires, queue->timer_list.expires))
++ rpc_set_queue_timer(queue, task->u.tk_wait.expires);
++ list_add(&task->u.tk_wait.timer_list, &queue->timer_list.list);
+ }
+
+ /*
+@@ -161,7 +133,7 @@ static void __rpc_add_wait_queue(struct rpc_wait_queue *queue, struct rpc_task *
+ list_add(&task->u.tk_wait.list, &queue->tasks[0]);
+ else
+ list_add_tail(&task->u.tk_wait.list, &queue->tasks[0]);
+- task->u.tk_wait.rpc_waitq = queue;
++ task->tk_waitqueue = queue;
+ queue->qlen++;
+ rpc_set_queued(task);
+
+@@ -181,22 +153,18 @@ static void __rpc_remove_wait_queue_priority(struct rpc_task *task)
+ list_move(&t->u.tk_wait.list, &task->u.tk_wait.list);
+ list_splice_init(&task->u.tk_wait.links, &t->u.tk_wait.links);
+ }
+- list_del(&task->u.tk_wait.list);
+ }
+
+ /*
+ * Remove request from queue.
+ * Note: must be called with spin lock held.
+ */
+-static void __rpc_remove_wait_queue(struct rpc_task *task)
++static void __rpc_remove_wait_queue(struct rpc_wait_queue *queue, struct rpc_task *task)
+ {
+- struct rpc_wait_queue *queue;
+- queue = task->u.tk_wait.rpc_waitq;
+-
++ __rpc_disable_timer(queue, task);
+ if (RPC_IS_PRIORITY(queue))
+ __rpc_remove_wait_queue_priority(task);
+- else
+- list_del(&task->u.tk_wait.list);
++ list_del(&task->u.tk_wait.list);
+ queue->qlen--;
+ dprintk("RPC: %5u removed from queue %p \"%s\"\n",
+ task->tk_pid, queue, rpc_qname(queue));
+@@ -229,6 +197,9 @@ static void __rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const c
+ INIT_LIST_HEAD(&queue->tasks[i]);
+ queue->maxpriority = nr_queues - 1;
+ rpc_reset_waitqueue_priority(queue);
++ queue->qlen = 0;
++ setup_timer(&queue->timer_list.timer, __rpc_queue_timer_fn, (unsigned long)queue);
++ INIT_LIST_HEAD(&queue->timer_list.list);
+ #ifdef RPC_DEBUG
+ queue->name = qname;
+ #endif
+@@ -245,6 +216,12 @@ void rpc_init_wait_queue(struct rpc_wait_queue *queue, const char *qname)
+ }
+ EXPORT_SYMBOL_GPL(rpc_init_wait_queue);
+
++void rpc_destroy_wait_queue(struct rpc_wait_queue *queue)
++{
++ del_timer_sync(&queue->timer_list.timer);
++}
++EXPORT_SYMBOL_GPL(rpc_destroy_wait_queue);
++
+ static int rpc_wait_bit_killable(void *word)
+ {
+ if (fatal_signal_pending(current))
+@@ -313,7 +290,6 @@ EXPORT_SYMBOL_GPL(__rpc_wait_for_completion_task);
+ */
+ static void rpc_make_runnable(struct rpc_task *task)
+ {
+- BUG_ON(task->tk_timeout_fn);
+ rpc_clear_queued(task);
+ if (rpc_test_and_set_running(task))
+ return;
+@@ -326,7 +302,7 @@ static void rpc_make_runnable(struct rpc_task *task)
+ int status;
+
+ INIT_WORK(&task->u.tk_work, rpc_async_schedule);
+- status = queue_work(task->tk_workqueue, &task->u.tk_work);
++ status = queue_work(rpciod_workqueue, &task->u.tk_work);
+ if (status < 0) {
+ printk(KERN_WARNING "RPC: failed to add task to queue: error: %d!\n", status);
+ task->tk_status = status;
+@@ -343,7 +319,7 @@ static void rpc_make_runnable(struct rpc_task *task)
+ * as it's on a wait queue.
+ */
+ static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
+- rpc_action action, rpc_action timer)
++ rpc_action action)
+ {
+ dprintk("RPC: %5u sleep_on(queue \"%s\" time %lu)\n",
+ task->tk_pid, rpc_qname(q), jiffies);
+@@ -357,11 +333,11 @@ static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
+
+ BUG_ON(task->tk_callback != NULL);
+ task->tk_callback = action;
+- __rpc_add_timer(task, timer);
++ __rpc_add_timer(q, task);
+ }
+
+ void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
+- rpc_action action, rpc_action timer)
++ rpc_action action)
+ {
+ /* Mark the task as being activated if so needed */
+ rpc_set_active(task);
+@@ -370,18 +346,19 @@ void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
+ * Protect the queue operations.
+ */
+ spin_lock_bh(&q->lock);
+- __rpc_sleep_on(q, task, action, timer);
++ __rpc_sleep_on(q, task, action);
+ spin_unlock_bh(&q->lock);
+ }
+ EXPORT_SYMBOL_GPL(rpc_sleep_on);
+
+ /**
+ * __rpc_do_wake_up_task - wake up a single rpc_task
++ * @queue: wait queue
+ * @task: task to be woken up
+ *
+ * Caller must hold queue->lock, and have cleared the task queued flag.
+ */
+-static void __rpc_do_wake_up_task(struct rpc_task *task)
++static void __rpc_do_wake_up_task(struct rpc_wait_queue *queue, struct rpc_task *task)
+ {
+ dprintk("RPC: %5u __rpc_wake_up_task (now %lu)\n",
+ task->tk_pid, jiffies);
+@@ -395,8 +372,7 @@ static void __rpc_do_wake_up_task(struct rpc_task *task)
+ return;
+ }
+
+- __rpc_disable_timer(task);
+- __rpc_remove_wait_queue(task);
++ __rpc_remove_wait_queue(queue, task);
+
+ rpc_make_runnable(task);
+
+@@ -404,48 +380,32 @@ static void __rpc_do_wake_up_task(struct rpc_task *task)
+ }
+
+ /*
+- * Wake up the specified task
++ * Wake up a queued task while the queue lock is being held
+ */
+-static void __rpc_wake_up_task(struct rpc_task *task)
++static void rpc_wake_up_task_queue_locked(struct rpc_wait_queue *queue, struct rpc_task *task)
+ {
+- if (rpc_start_wakeup(task)) {
+- if (RPC_IS_QUEUED(task))
+- __rpc_do_wake_up_task(task);
+- rpc_finish_wakeup(task);
+- }
++ if (RPC_IS_QUEUED(task) && task->tk_waitqueue == queue)
++ __rpc_do_wake_up_task(queue, task);
+ }
+
+ /*
+- * Default timeout handler if none specified by user
++ * Wake up a task on a specific queue
+ */
+-static void
+-__rpc_default_timer(struct rpc_task *task)
++void rpc_wake_up_queued_task(struct rpc_wait_queue *queue, struct rpc_task *task)
+ {
+- dprintk("RPC: %5u timeout (default timer)\n", task->tk_pid);
+- task->tk_status = -ETIMEDOUT;
+- rpc_wake_up_task(task);
++ spin_lock_bh(&queue->lock);
++ rpc_wake_up_task_queue_locked(queue, task);
++ spin_unlock_bh(&queue->lock);
+ }
++EXPORT_SYMBOL_GPL(rpc_wake_up_queued_task);
+
+ /*
+ * Wake up the specified task
+ */
+-void rpc_wake_up_task(struct rpc_task *task)
++static void rpc_wake_up_task(struct rpc_task *task)
+ {
+- rcu_read_lock_bh();
+- if (rpc_start_wakeup(task)) {
+- if (RPC_IS_QUEUED(task)) {
+- struct rpc_wait_queue *queue = task->u.tk_wait.rpc_waitq;
+-
+- /* Note: we're already in a bh-safe context */
+- spin_lock(&queue->lock);
+- __rpc_do_wake_up_task(task);
+- spin_unlock(&queue->lock);
+- }
+- rpc_finish_wakeup(task);
+- }
+- rcu_read_unlock_bh();
++ rpc_wake_up_queued_task(task->tk_waitqueue, task);
+ }
+-EXPORT_SYMBOL_GPL(rpc_wake_up_task);
+
+ /*
+ * Wake up the next task on a priority queue.
+@@ -495,7 +455,7 @@ new_queue:
+ new_owner:
+ rpc_set_waitqueue_owner(queue, task->tk_owner);
+ out:
+- __rpc_wake_up_task(task);
++ rpc_wake_up_task_queue_locked(queue, task);
+ return task;
+ }
+
+@@ -508,16 +468,14 @@ struct rpc_task * rpc_wake_up_next(struct rpc_wait_queue *queue)
+
+ dprintk("RPC: wake_up_next(%p \"%s\")\n",
+ queue, rpc_qname(queue));
+- rcu_read_lock_bh();
+- spin_lock(&queue->lock);
++ spin_lock_bh(&queue->lock);
+ if (RPC_IS_PRIORITY(queue))
+ task = __rpc_wake_up_next_priority(queue);
+ else {
+ task_for_first(task, &queue->tasks[0])
+- __rpc_wake_up_task(task);
++ rpc_wake_up_task_queue_locked(queue, task);
+ }
+- spin_unlock(&queue->lock);
+- rcu_read_unlock_bh();
++ spin_unlock_bh(&queue->lock);
+
+ return task;
+ }
+@@ -534,18 +492,16 @@ void rpc_wake_up(struct rpc_wait_queue *queue)
+ struct rpc_task *task, *next;
+ struct list_head *head;
+
+- rcu_read_lock_bh();
+- spin_lock(&queue->lock);
++ spin_lock_bh(&queue->lock);
+ head = &queue->tasks[queue->maxpriority];
+ for (;;) {
+ list_for_each_entry_safe(task, next, head, u.tk_wait.list)
+- __rpc_wake_up_task(task);
++ rpc_wake_up_task_queue_locked(queue, task);
+ if (head == &queue->tasks[0])
+ break;
+ head--;
+ }
+- spin_unlock(&queue->lock);
+- rcu_read_unlock_bh();
++ spin_unlock_bh(&queue->lock);
+ }
+ EXPORT_SYMBOL_GPL(rpc_wake_up);
+
+@@ -561,26 +517,48 @@ void rpc_wake_up_status(struct rpc_wait_queue *queue, int status)
+ struct rpc_task *task, *next;
+ struct list_head *head;
+
+- rcu_read_lock_bh();
+- spin_lock(&queue->lock);
++ spin_lock_bh(&queue->lock);
+ head = &queue->tasks[queue->maxpriority];
+ for (;;) {
+ list_for_each_entry_safe(task, next, head, u.tk_wait.list) {
+ task->tk_status = status;
+- __rpc_wake_up_task(task);
++ rpc_wake_up_task_queue_locked(queue, task);
+ }
+ if (head == &queue->tasks[0])
+ break;
+ head--;
+ }
+- spin_unlock(&queue->lock);
+- rcu_read_unlock_bh();
++ spin_unlock_bh(&queue->lock);
+ }
+ EXPORT_SYMBOL_GPL(rpc_wake_up_status);
+
++static void __rpc_queue_timer_fn(unsigned long ptr)
++{
++ struct rpc_wait_queue *queue = (struct rpc_wait_queue *)ptr;
++ struct rpc_task *task, *n;
++ unsigned long expires, now, timeo;
++
++ spin_lock(&queue->lock);
++ expires = now = jiffies;
++ list_for_each_entry_safe(task, n, &queue->timer_list.list, u.tk_wait.timer_list) {
++ timeo = task->u.tk_wait.expires;
++ if (time_after_eq(now, timeo)) {
++ dprintk("RPC: %5u timeout\n", task->tk_pid);
++ task->tk_status = -ETIMEDOUT;
++ rpc_wake_up_task_queue_locked(queue, task);
++ continue;
++ }
++ if (expires == now || time_after(expires, timeo))
++ expires = timeo;
++ }
++ if (!list_empty(&queue->timer_list.list))
++ rpc_set_queue_timer(queue, expires);
++ spin_unlock(&queue->lock);
++}
++
+ static void __rpc_atrun(struct rpc_task *task)
+ {
+- rpc_wake_up_task(task);
++ task->tk_status = 0;
+ }
+
+ /*
+@@ -589,7 +567,7 @@ static void __rpc_atrun(struct rpc_task *task)
+ void rpc_delay(struct rpc_task *task, unsigned long delay)
+ {
+ task->tk_timeout = delay;
+- rpc_sleep_on(&delay_queue, task, NULL, __rpc_atrun);
++ rpc_sleep_on(&delay_queue, task, __rpc_atrun);
+ }
+ EXPORT_SYMBOL_GPL(rpc_delay);
+
+@@ -644,10 +622,6 @@ static void __rpc_execute(struct rpc_task *task)
+ BUG_ON(RPC_IS_QUEUED(task));
+
+ for (;;) {
+- /*
+- * Garbage collection of pending timers...
+- */
+- rpc_delete_timer(task);
+
+ /*
+ * Execute any pending callback.
+@@ -816,8 +790,6 @@ EXPORT_SYMBOL_GPL(rpc_free);
+ static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *task_setup_data)
+ {
+ memset(task, 0, sizeof(*task));
+- setup_timer(&task->tk_timer, (void (*)(unsigned long))rpc_run_timer,
+- (unsigned long)task);
+ atomic_set(&task->tk_count, 1);
+ task->tk_flags = task_setup_data->flags;
+ task->tk_ops = task_setup_data->callback_ops;
+@@ -832,7 +804,7 @@ static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *ta
+ task->tk_owner = current->tgid;
+
+ /* Initialize workqueue for async tasks */
+- task->tk_workqueue = rpciod_workqueue;
++ task->tk_workqueue = task_setup_data->workqueue;
+
+ task->tk_client = task_setup_data->rpc_client;
+ if (task->tk_client != NULL) {
+@@ -845,12 +817,11 @@ static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *ta
+ task->tk_action = rpc_prepare_task;
+
+ if (task_setup_data->rpc_message != NULL) {
+- memcpy(&task->tk_msg, task_setup_data->rpc_message, sizeof(task->tk_msg));
++ task->tk_msg.rpc_proc = task_setup_data->rpc_message->rpc_proc;
++ task->tk_msg.rpc_argp = task_setup_data->rpc_message->rpc_argp;
++ task->tk_msg.rpc_resp = task_setup_data->rpc_message->rpc_resp;
+ /* Bind the user cred */
+- if (task->tk_msg.rpc_cred != NULL)
+- rpcauth_holdcred(task);
+- else
+- rpcauth_bindcred(task);
++ rpcauth_bindcred(task, task_setup_data->rpc_message->rpc_cred, task_setup_data->flags);
+ if (task->tk_action == NULL)
+ rpc_call_start(task);
+ }
+@@ -868,13 +839,6 @@ rpc_alloc_task(void)
+ return (struct rpc_task *)mempool_alloc(rpc_task_mempool, GFP_NOFS);
+ }
+
+-static void rpc_free_task(struct rcu_head *rcu)
+-{
+- struct rpc_task *task = container_of(rcu, struct rpc_task, u.tk_rcu);
+- dprintk("RPC: %5u freeing task\n", task->tk_pid);
+- mempool_free(task, rpc_task_mempool);
+-}
+-
+ /*
+ * Create a new task for the specified client.
+ */
+@@ -898,12 +862,25 @@ out:
+ return task;
+ }
+
+-
+-void rpc_put_task(struct rpc_task *task)
++static void rpc_free_task(struct rpc_task *task)
+ {
+ const struct rpc_call_ops *tk_ops = task->tk_ops;
+ void *calldata = task->tk_calldata;
+
++ if (task->tk_flags & RPC_TASK_DYNAMIC) {
++ dprintk("RPC: %5u freeing task\n", task->tk_pid);
++ mempool_free(task, rpc_task_mempool);
++ }
++ rpc_release_calldata(tk_ops, calldata);
++}
++
++static void rpc_async_release(struct work_struct *work)
++{
++ rpc_free_task(container_of(work, struct rpc_task, u.tk_work));
++}
++
++void rpc_put_task(struct rpc_task *task)
++{
+ if (!atomic_dec_and_test(&task->tk_count))
+ return;
+ /* Release resources */
+@@ -915,9 +892,11 @@ void rpc_put_task(struct rpc_task *task)
+ rpc_release_client(task->tk_client);
+ task->tk_client = NULL;
+ }
+- if (task->tk_flags & RPC_TASK_DYNAMIC)
+- call_rcu_bh(&task->u.tk_rcu, rpc_free_task);
+- rpc_release_calldata(tk_ops, calldata);
++ if (task->tk_workqueue != NULL) {
++ INIT_WORK(&task->u.tk_work, rpc_async_release);
++ queue_work(task->tk_workqueue, &task->u.tk_work);
++ } else
++ rpc_free_task(task);
+ }
+ EXPORT_SYMBOL_GPL(rpc_put_task);
+
+@@ -937,9 +916,6 @@ static void rpc_release_task(struct rpc_task *task)
+ }
+ BUG_ON (RPC_IS_QUEUED(task));
+
+- /* Synchronously delete any running timer */
+- rpc_delete_timer(task);
+-
+ #ifdef RPC_DEBUG
+ task->tk_magic = 0;
+ #endif
+@@ -1029,11 +1005,20 @@ rpc_destroy_mempool(void)
+ kmem_cache_destroy(rpc_task_slabp);
+ if (rpc_buffer_slabp)
+ kmem_cache_destroy(rpc_buffer_slabp);
++ rpc_destroy_wait_queue(&delay_queue);
+ }
+
+ int
+ rpc_init_mempool(void)
+ {
++ /*
++ * The following is not strictly a mempool initialisation,
++ * but there is no harm in doing it here
++ */
++ rpc_init_wait_queue(&delay_queue, "delayq");
++ if (!rpciod_start())
++ goto err_nomem;
++
+ rpc_task_slabp = kmem_cache_create("rpc_tasks",
+ sizeof(struct rpc_task),
+ 0, SLAB_HWCACHE_ALIGN,
+@@ -1054,13 +1039,6 @@ rpc_init_mempool(void)
+ rpc_buffer_slabp);
+ if (!rpc_buffer_mempool)
+ goto err_nomem;
+- if (!rpciod_start())
+- goto err_nomem;
+- /*
+- * The following is not strictly a mempool initialisation,
+- * but there is no harm in doing it here
+- */
+- rpc_init_wait_queue(&delay_queue, "delayq");
+ return 0;
+ err_nomem:
+ rpc_destroy_mempool();
+diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
+index a290e15..d74c2d2 100644
+--- a/net/sunrpc/svc.c
++++ b/net/sunrpc/svc.c
+@@ -301,7 +301,6 @@ static inline int
+ svc_pool_map_set_cpumask(unsigned int pidx, cpumask_t *oldmask)
+ {
+ struct svc_pool_map *m = &svc_pool_map;
+- unsigned int node; /* or cpu */
+
+ /*
+ * The caller checks for sv_nrpools > 1, which
+@@ -314,16 +313,23 @@ svc_pool_map_set_cpumask(unsigned int pidx, cpumask_t *oldmask)
+ default:
+ return 0;
+ case SVC_POOL_PERCPU:
+- node = m->pool_to[pidx];
++ {
++ unsigned int cpu = m->pool_to[pidx];
++
+ *oldmask = current->cpus_allowed;
+- set_cpus_allowed(current, cpumask_of_cpu(node));
++ set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+ return 1;
++ }
+ case SVC_POOL_PERNODE:
+- node = m->pool_to[pidx];
++ {
++ unsigned int node = m->pool_to[pidx];
++ node_to_cpumask_ptr(nodecpumask, node);
++
+ *oldmask = current->cpus_allowed;
+- set_cpus_allowed(current, node_to_cpumask(node));
++ set_cpus_allowed_ptr(current, nodecpumask);
+ return 1;
+ }
++ }
+ }
+
+ /*
+@@ -504,8 +510,7 @@ EXPORT_SYMBOL(svc_destroy);
+ static int
+ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size)
+ {
+- int pages;
+- int arghi;
++ unsigned int pages, arghi;
+
+ pages = size / PAGE_SIZE + 1; /* extra page as we hold both request and reply.
+ * We assume one is at most one page
+@@ -519,7 +524,7 @@ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size)
+ rqstp->rq_pages[arghi++] = p;
+ pages--;
+ }
+- return ! pages;
++ return pages == 0;
+ }
+
+ /*
+@@ -528,8 +533,9 @@ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size)
+ static void
+ svc_release_buffer(struct svc_rqst *rqstp)
+ {
+- int i;
+- for (i=0; i<ARRAY_SIZE(rqstp->rq_pages); i++)
++ unsigned int i;
++
++ for (i = 0; i < ARRAY_SIZE(rqstp->rq_pages); i++)
+ if (rqstp->rq_pages[i])
+ put_page(rqstp->rq_pages[i]);
+ }
+@@ -584,7 +590,7 @@ __svc_create_thread(svc_thread_fn func, struct svc_serv *serv,
+ struct svc_rqst *rqstp;
+ int error = -ENOMEM;
+ int have_oldmask = 0;
+- cpumask_t oldmask;
++ cpumask_t uninitialized_var(oldmask);
+
+ rqstp = svc_prepare_thread(serv, pool);
+ if (IS_ERR(rqstp)) {
+@@ -613,16 +619,6 @@ out_thread:
+ }
+
+ /*
+- * Create a thread in the default pool. Caller must hold BKL.
+- */
+-int
+-svc_create_thread(svc_thread_fn func, struct svc_serv *serv)
+-{
+- return __svc_create_thread(func, serv, &serv->sv_pools[0]);
+-}
+-EXPORT_SYMBOL(svc_create_thread);
+-
+-/*
+ * Choose a pool in which to create a new thread, for svc_set_num_threads
+ */
+ static inline struct svc_pool *
+@@ -915,8 +911,7 @@ svc_process(struct svc_rqst *rqstp)
+ case SVC_OK:
+ break;
+ case SVC_GARBAGE:
+- rpc_stat = rpc_garbage_args;
+- goto err_bad;
++ goto err_garbage;
+ case SVC_SYSERR:
+ rpc_stat = rpc_system_err;
+ goto err_bad;
+diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
+index 332eb47..d8e8d79 100644
+--- a/net/sunrpc/svc_xprt.c
++++ b/net/sunrpc/svc_xprt.c
+@@ -18,6 +18,7 @@
+ #include <linux/skbuff.h>
+ #include <linux/file.h>
+ #include <linux/freezer.h>
++#include <linux/kthread.h>
+ #include <net/sock.h>
+ #include <net/checksum.h>
+ #include <net/ip.h>
+@@ -586,8 +587,12 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
+ while (rqstp->rq_pages[i] == NULL) {
+ struct page *p = alloc_page(GFP_KERNEL);
+ if (!p) {
+- int j = msecs_to_jiffies(500);
+- schedule_timeout_uninterruptible(j);
++ set_current_state(TASK_INTERRUPTIBLE);
++ if (signalled() || kthread_should_stop()) {
++ set_current_state(TASK_RUNNING);
++ return -EINTR;
++ }
++ schedule_timeout(msecs_to_jiffies(500));
+ }
+ rqstp->rq_pages[i] = p;
+ }
+@@ -607,7 +612,7 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
+
+ try_to_freeze();
+ cond_resched();
+- if (signalled())
++ if (signalled() || kthread_should_stop())
+ return -EINTR;
+
+ spin_lock_bh(&pool->sp_lock);
+@@ -626,6 +631,20 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
+ * to bring down the daemons ...
+ */
+ set_current_state(TASK_INTERRUPTIBLE);
++
++ /*
++ * checking kthread_should_stop() here allows us to avoid
++ * locking and signalling when stopping kthreads that call
++ * svc_recv. If the thread has already been woken up, then
++ * we can exit here without sleeping. If not, then it
++ * it'll be woken up quickly during the schedule_timeout
++ */
++ if (kthread_should_stop()) {
++ set_current_state(TASK_RUNNING);
++ spin_unlock_bh(&pool->sp_lock);
++ return -EINTR;
++ }
++
+ add_wait_queue(&rqstp->rq_wait, &wait);
+ spin_unlock_bh(&pool->sp_lock);
+
+@@ -641,7 +660,10 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
+ svc_thread_dequeue(pool, rqstp);
+ spin_unlock_bh(&pool->sp_lock);
+ dprintk("svc: server %p, no data yet\n", rqstp);
+- return signalled()? -EINTR : -EAGAIN;
++ if (signalled() || kthread_should_stop())
++ return -EINTR;
++ else
++ return -EAGAIN;
+ }
+ }
+ spin_unlock_bh(&pool->sp_lock);
+diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
+index 3c64051..3f30ee6 100644
+--- a/net/sunrpc/svcauth_unix.c
++++ b/net/sunrpc/svcauth_unix.c
+@@ -11,7 +11,8 @@
+ #include <linux/hash.h>
+ #include <linux/string.h>
+ #include <net/sock.h>
+-
++#include <net/ipv6.h>
++#include <linux/kernel.h>
+ #define RPCDBG_FACILITY RPCDBG_AUTH
+
+
+@@ -85,7 +86,7 @@ static void svcauth_unix_domain_release(struct auth_domain *dom)
+ struct ip_map {
+ struct cache_head h;
+ char m_class[8]; /* e.g. "nfsd" */
+- struct in_addr m_addr;
++ struct in6_addr m_addr;
+ struct unix_domain *m_client;
+ int m_add_change;
+ };
+@@ -113,12 +114,19 @@ static inline int hash_ip(__be32 ip)
+ return (hash ^ (hash>>8)) & 0xff;
+ }
+ #endif
++static inline int hash_ip6(struct in6_addr ip)
++{
++ return (hash_ip(ip.s6_addr32[0]) ^
++ hash_ip(ip.s6_addr32[1]) ^
++ hash_ip(ip.s6_addr32[2]) ^
++ hash_ip(ip.s6_addr32[3]));
++}
+ static int ip_map_match(struct cache_head *corig, struct cache_head *cnew)
+ {
+ struct ip_map *orig = container_of(corig, struct ip_map, h);
+ struct ip_map *new = container_of(cnew, struct ip_map, h);
+ return strcmp(orig->m_class, new->m_class) == 0
+- && orig->m_addr.s_addr == new->m_addr.s_addr;
++ && ipv6_addr_equal(&orig->m_addr, &new->m_addr);
+ }
+ static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
+ {
+@@ -126,7 +134,7 @@ static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
+ struct ip_map *item = container_of(citem, struct ip_map, h);
+
+ strcpy(new->m_class, item->m_class);
+- new->m_addr.s_addr = item->m_addr.s_addr;
++ ipv6_addr_copy(&new->m_addr, &item->m_addr);
+ }
+ static void update(struct cache_head *cnew, struct cache_head *citem)
+ {
+@@ -150,22 +158,24 @@ static void ip_map_request(struct cache_detail *cd,
+ struct cache_head *h,
+ char **bpp, int *blen)
+ {
+- char text_addr[20];
++ char text_addr[40];
+ struct ip_map *im = container_of(h, struct ip_map, h);
+- __be32 addr = im->m_addr.s_addr;
+-
+- snprintf(text_addr, 20, "%u.%u.%u.%u",
+- ntohl(addr) >> 24 & 0xff,
+- ntohl(addr) >> 16 & 0xff,
+- ntohl(addr) >> 8 & 0xff,
+- ntohl(addr) >> 0 & 0xff);
+
++ if (ipv6_addr_v4mapped(&(im->m_addr))) {
++ snprintf(text_addr, 20, NIPQUAD_FMT,
++ ntohl(im->m_addr.s6_addr32[3]) >> 24 & 0xff,
++ ntohl(im->m_addr.s6_addr32[3]) >> 16 & 0xff,
++ ntohl(im->m_addr.s6_addr32[3]) >> 8 & 0xff,
++ ntohl(im->m_addr.s6_addr32[3]) >> 0 & 0xff);
++ } else {
++ snprintf(text_addr, 40, NIP6_FMT, NIP6(im->m_addr));
++ }
+ qword_add(bpp, blen, im->m_class);
+ qword_add(bpp, blen, text_addr);
+ (*bpp)[-1] = '\n';
+ }
+
+-static struct ip_map *ip_map_lookup(char *class, struct in_addr addr);
++static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr);
+ static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry);
+
+ static int ip_map_parse(struct cache_detail *cd,
+@@ -176,10 +186,10 @@ static int ip_map_parse(struct cache_detail *cd,
+ * for scratch: */
+ char *buf = mesg;
+ int len;
+- int b1,b2,b3,b4;
++ int b1, b2, b3, b4, b5, b6, b7, b8;
+ char c;
+ char class[8];
+- struct in_addr addr;
++ struct in6_addr addr;
+ int err;
+
+ struct ip_map *ipmp;
+@@ -198,7 +208,23 @@ static int ip_map_parse(struct cache_detail *cd,
+ len = qword_get(&mesg, buf, mlen);
+ if (len <= 0) return -EINVAL;
+
+- if (sscanf(buf, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4)
++ if (sscanf(buf, NIPQUAD_FMT "%c", &b1, &b2, &b3, &b4, &c) == 4) {
++ addr.s6_addr32[0] = 0;
++ addr.s6_addr32[1] = 0;
++ addr.s6_addr32[2] = htonl(0xffff);
++ addr.s6_addr32[3] =
++ htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
++ } else if (sscanf(buf, NIP6_FMT "%c",
++ &b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &c) == 8) {
++ addr.s6_addr16[0] = htons(b1);
++ addr.s6_addr16[1] = htons(b2);
++ addr.s6_addr16[2] = htons(b3);
++ addr.s6_addr16[3] = htons(b4);
++ addr.s6_addr16[4] = htons(b5);
++ addr.s6_addr16[5] = htons(b6);
++ addr.s6_addr16[6] = htons(b7);
++ addr.s6_addr16[7] = htons(b8);
++ } else
+ return -EINVAL;
+
+ expiry = get_expiry(&mesg);
+@@ -216,10 +242,7 @@ static int ip_map_parse(struct cache_detail *cd,
+ } else
+ dom = NULL;
+
+- addr.s_addr =
+- htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
+-
+- ipmp = ip_map_lookup(class,addr);
++ ipmp = ip_map_lookup(class, &addr);
+ if (ipmp) {
+ err = ip_map_update(ipmp,
+ container_of(dom, struct unix_domain, h),
+@@ -239,7 +262,7 @@ static int ip_map_show(struct seq_file *m,
+ struct cache_head *h)
+ {
+ struct ip_map *im;
+- struct in_addr addr;
++ struct in6_addr addr;
+ char *dom = "-no-domain-";
+
+ if (h == NULL) {
+@@ -248,20 +271,24 @@ static int ip_map_show(struct seq_file *m,
+ }
+ im = container_of(h, struct ip_map, h);
+ /* class addr domain */
+- addr = im->m_addr;
++ ipv6_addr_copy(&addr, &im->m_addr);
+
+ if (test_bit(CACHE_VALID, &h->flags) &&
+ !test_bit(CACHE_NEGATIVE, &h->flags))
+ dom = im->m_client->h.name;
+
+- seq_printf(m, "%s %d.%d.%d.%d %s\n",
+- im->m_class,
+- ntohl(addr.s_addr) >> 24 & 0xff,
+- ntohl(addr.s_addr) >> 16 & 0xff,
+- ntohl(addr.s_addr) >> 8 & 0xff,
+- ntohl(addr.s_addr) >> 0 & 0xff,
+- dom
+- );
++ if (ipv6_addr_v4mapped(&addr)) {
++ seq_printf(m, "%s" NIPQUAD_FMT "%s\n",
++ im->m_class,
++ ntohl(addr.s6_addr32[3]) >> 24 & 0xff,
++ ntohl(addr.s6_addr32[3]) >> 16 & 0xff,
++ ntohl(addr.s6_addr32[3]) >> 8 & 0xff,
++ ntohl(addr.s6_addr32[3]) >> 0 & 0xff,
++ dom);
++ } else {
++ seq_printf(m, "%s" NIP6_FMT "%s\n",
++ im->m_class, NIP6(addr), dom);
++ }
+ return 0;
+ }
+
+@@ -281,16 +308,16 @@ struct cache_detail ip_map_cache = {
+ .alloc = ip_map_alloc,
+ };
+
+-static struct ip_map *ip_map_lookup(char *class, struct in_addr addr)
++static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr)
+ {
+ struct ip_map ip;
+ struct cache_head *ch;
+
+ strcpy(ip.m_class, class);
+- ip.m_addr = addr;
++ ipv6_addr_copy(&ip.m_addr, addr);
+ ch = sunrpc_cache_lookup(&ip_map_cache, &ip.h,
+ hash_str(class, IP_HASHBITS) ^
+- hash_ip(addr.s_addr));
++ hash_ip6(*addr));
+
+ if (ch)
+ return container_of(ch, struct ip_map, h);
+@@ -319,14 +346,14 @@ static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t ex
+ ch = sunrpc_cache_update(&ip_map_cache,
+ &ip.h, &ipm->h,
+ hash_str(ipm->m_class, IP_HASHBITS) ^
+- hash_ip(ipm->m_addr.s_addr));
++ hash_ip6(ipm->m_addr));
+ if (!ch)
+ return -ENOMEM;
+ cache_put(ch, &ip_map_cache);
+ return 0;
+ }
+
+-int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom)
++int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom)
+ {
+ struct unix_domain *udom;
+ struct ip_map *ipmp;
+@@ -355,7 +382,7 @@ int auth_unix_forget_old(struct auth_domain *dom)
+ }
+ EXPORT_SYMBOL(auth_unix_forget_old);
+
+-struct auth_domain *auth_unix_lookup(struct in_addr addr)
++struct auth_domain *auth_unix_lookup(struct in6_addr *addr)
+ {
+ struct ip_map *ipm;
+ struct auth_domain *rv;
+@@ -650,9 +677,24 @@ static int unix_gid_find(uid_t uid, struct group_info **gip,
+ int
+ svcauth_unix_set_client(struct svc_rqst *rqstp)
+ {
+- struct sockaddr_in *sin = svc_addr_in(rqstp);
++ struct sockaddr_in *sin;
++ struct sockaddr_in6 *sin6, sin6_storage;
+ struct ip_map *ipm;
+
++ switch (rqstp->rq_addr.ss_family) {
++ case AF_INET:
++ sin = svc_addr_in(rqstp);
++ sin6 = &sin6_storage;
++ ipv6_addr_set(&sin6->sin6_addr, 0, 0,
++ htonl(0x0000FFFF), sin->sin_addr.s_addr);
++ break;
++ case AF_INET6:
++ sin6 = svc_addr_in6(rqstp);
++ break;
++ default:
++ BUG();
++ }
++
+ rqstp->rq_client = NULL;
+ if (rqstp->rq_proc == 0)
+ return SVC_OK;
+@@ -660,7 +702,7 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
+ ipm = ip_map_cached_get(rqstp);
+ if (ipm == NULL)
+ ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class,
+- sin->sin_addr);
++ &sin6->sin6_addr);
+
+ if (ipm == NULL)
+ return SVC_DENIED;
+diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
+index c475977..3e65719 100644
+--- a/net/sunrpc/svcsock.c
++++ b/net/sunrpc/svcsock.c
+@@ -38,6 +38,7 @@
+ #include <net/checksum.h>
+ #include <net/ip.h>
+ #include <net/ipv6.h>
++#include <net/tcp.h>
+ #include <net/tcp_states.h>
+ #include <asm/uaccess.h>
+ #include <asm/ioctls.h>
+@@ -45,6 +46,7 @@
+ #include <linux/sunrpc/types.h>
+ #include <linux/sunrpc/clnt.h>
+ #include <linux/sunrpc/xdr.h>
++#include <linux/sunrpc/msg_prot.h>
+ #include <linux/sunrpc/svcsock.h>
+ #include <linux/sunrpc/stats.h>
+
+@@ -822,8 +824,8 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
+ * the next four bytes. Otherwise try to gobble up as much as
+ * possible up to the complete record length.
+ */
+- if (svsk->sk_tcplen < 4) {
+- unsigned long want = 4 - svsk->sk_tcplen;
++ if (svsk->sk_tcplen < sizeof(rpc_fraghdr)) {
++ int want = sizeof(rpc_fraghdr) - svsk->sk_tcplen;
+ struct kvec iov;
+
+ iov.iov_base = ((char *) &svsk->sk_reclen) + svsk->sk_tcplen;
+@@ -833,32 +835,31 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
+ svsk->sk_tcplen += len;
+
+ if (len < want) {
+- dprintk("svc: short recvfrom while reading record length (%d of %lu)\n",
+- len, want);
++ dprintk("svc: short recvfrom while reading record "
++ "length (%d of %d)\n", len, want);
+ svc_xprt_received(&svsk->sk_xprt);
+ return -EAGAIN; /* record header not complete */
+ }
+
+ svsk->sk_reclen = ntohl(svsk->sk_reclen);
+- if (!(svsk->sk_reclen & 0x80000000)) {
++ if (!(svsk->sk_reclen & RPC_LAST_STREAM_FRAGMENT)) {
+ /* FIXME: technically, a record can be fragmented,
+ * and non-terminal fragments will not have the top
+ * bit set in the fragment length header.
+ * But apparently no known nfs clients send fragmented
+ * records. */
+ if (net_ratelimit())
+- printk(KERN_NOTICE "RPC: bad TCP reclen 0x%08lx"
+- " (non-terminal)\n",
+- (unsigned long) svsk->sk_reclen);
++ printk(KERN_NOTICE "RPC: multiple fragments "
++ "per record not supported\n");
+ goto err_delete;
+ }
+- svsk->sk_reclen &= 0x7fffffff;
++ svsk->sk_reclen &= RPC_FRAGMENT_SIZE_MASK;
+ dprintk("svc: TCP record, %d bytes\n", svsk->sk_reclen);
+ if (svsk->sk_reclen > serv->sv_max_mesg) {
+ if (net_ratelimit())
+- printk(KERN_NOTICE "RPC: bad TCP reclen 0x%08lx"
+- " (large)\n",
+- (unsigned long) svsk->sk_reclen);
++ printk(KERN_NOTICE "RPC: "
++ "fragment too large: 0x%08lx\n",
++ (unsigned long)svsk->sk_reclen);
+ goto err_delete;
+ }
+ }
+@@ -1045,7 +1046,6 @@ void svc_cleanup_xprt_sock(void)
+ static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv)
+ {
+ struct sock *sk = svsk->sk_sk;
+- struct tcp_sock *tp = tcp_sk(sk);
+
+ svc_xprt_init(&svc_tcp_class, &svsk->sk_xprt, serv);
+ set_bit(XPT_CACHE_AUTH, &svsk->sk_xprt.xpt_flags);
+@@ -1063,7 +1063,7 @@ static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv)
+ svsk->sk_reclen = 0;
+ svsk->sk_tcplen = 0;
+
+- tp->nonagle = 1; /* disable Nagle's algorithm */
++ tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF;
+
+ /* initialise setting must have enough space to
+ * receive and respond to one request.
+@@ -1101,6 +1101,7 @@ void svc_sock_update_bufs(struct svc_serv *serv)
+ }
+ spin_unlock_bh(&serv->sv_lock);
+ }
++EXPORT_SYMBOL(svc_sock_update_bufs);
+
+ /*
+ * Initialize socket for RPC use and create svc_sock struct
+diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
+index d5553b8..75d748e 100644
+--- a/net/sunrpc/xprt.c
++++ b/net/sunrpc/xprt.c
+@@ -188,9 +188,9 @@ out_sleep:
+ task->tk_timeout = 0;
+ task->tk_status = -EAGAIN;
+ if (req && req->rq_ntrans)
+- rpc_sleep_on(&xprt->resend, task, NULL, NULL);
++ rpc_sleep_on(&xprt->resend, task, NULL);
+ else
+- rpc_sleep_on(&xprt->sending, task, NULL, NULL);
++ rpc_sleep_on(&xprt->sending, task, NULL);
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(xprt_reserve_xprt);
+@@ -238,9 +238,9 @@ out_sleep:
+ task->tk_timeout = 0;
+ task->tk_status = -EAGAIN;
+ if (req && req->rq_ntrans)
+- rpc_sleep_on(&xprt->resend, task, NULL, NULL);
++ rpc_sleep_on(&xprt->resend, task, NULL);
+ else
+- rpc_sleep_on(&xprt->sending, task, NULL, NULL);
++ rpc_sleep_on(&xprt->sending, task, NULL);
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(xprt_reserve_xprt_cong);
+@@ -447,13 +447,13 @@ EXPORT_SYMBOL_GPL(xprt_wake_pending_tasks);
+ * @task: task to be put to sleep
+ *
+ */
+-void xprt_wait_for_buffer_space(struct rpc_task *task)
++void xprt_wait_for_buffer_space(struct rpc_task *task, rpc_action action)
+ {
+ struct rpc_rqst *req = task->tk_rqstp;
+ struct rpc_xprt *xprt = req->rq_xprt;
+
+ task->tk_timeout = req->rq_timeout;
+- rpc_sleep_on(&xprt->pending, task, NULL, NULL);
++ rpc_sleep_on(&xprt->pending, task, action);
+ }
+ EXPORT_SYMBOL_GPL(xprt_wait_for_buffer_space);
+
+@@ -472,7 +472,7 @@ void xprt_write_space(struct rpc_xprt *xprt)
+ if (xprt->snd_task) {
+ dprintk("RPC: write space: waking waiting task on "
+ "xprt %p\n", xprt);
+- rpc_wake_up_task(xprt->snd_task);
++ rpc_wake_up_queued_task(&xprt->pending, xprt->snd_task);
+ }
+ spin_unlock_bh(&xprt->transport_lock);
+ }
+@@ -602,11 +602,37 @@ void xprt_force_disconnect(struct rpc_xprt *xprt)
+ /* Try to schedule an autoclose RPC call */
+ if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
+ queue_work(rpciod_workqueue, &xprt->task_cleanup);
+- else if (xprt->snd_task != NULL)
+- rpc_wake_up_task(xprt->snd_task);
++ xprt_wake_pending_tasks(xprt, -ENOTCONN);
++ spin_unlock_bh(&xprt->transport_lock);
++}
++
++/**
++ * xprt_conditional_disconnect - force a transport to disconnect
++ * @xprt: transport to disconnect
++ * @cookie: 'connection cookie'
++ *
++ * This attempts to break the connection if and only if 'cookie' matches
++ * the current transport 'connection cookie'. It ensures that we don't
++ * try to break the connection more than once when we need to retransmit
++ * a batch of RPC requests.
++ *
++ */
++void xprt_conditional_disconnect(struct rpc_xprt *xprt, unsigned int cookie)
++{
++ /* Don't race with the test_bit() in xprt_clear_locked() */
++ spin_lock_bh(&xprt->transport_lock);
++ if (cookie != xprt->connect_cookie)
++ goto out;
++ if (test_bit(XPRT_CLOSING, &xprt->state) || !xprt_connected(xprt))
++ goto out;
++ set_bit(XPRT_CLOSE_WAIT, &xprt->state);
++ /* Try to schedule an autoclose RPC call */
++ if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
++ queue_work(rpciod_workqueue, &xprt->task_cleanup);
++ xprt_wake_pending_tasks(xprt, -ENOTCONN);
++out:
+ spin_unlock_bh(&xprt->transport_lock);
+ }
+-EXPORT_SYMBOL_GPL(xprt_force_disconnect);
+
+ static void
+ xprt_init_autodisconnect(unsigned long data)
+@@ -653,7 +679,7 @@ void xprt_connect(struct rpc_task *task)
+ task->tk_rqstp->rq_bytes_sent = 0;
+
+ task->tk_timeout = xprt->connect_timeout;
+- rpc_sleep_on(&xprt->pending, task, xprt_connect_status, NULL);
++ rpc_sleep_on(&xprt->pending, task, xprt_connect_status);
+ xprt->stat.connect_start = jiffies;
+ xprt->ops->connect(task);
+ }
+@@ -749,18 +775,20 @@ EXPORT_SYMBOL_GPL(xprt_update_rtt);
+ void xprt_complete_rqst(struct rpc_task *task, int copied)
+ {
+ struct rpc_rqst *req = task->tk_rqstp;
++ struct rpc_xprt *xprt = req->rq_xprt;
+
+ dprintk("RPC: %5u xid %08x complete (%d bytes received)\n",
+ task->tk_pid, ntohl(req->rq_xid), copied);
+
+- task->tk_xprt->stat.recvs++;
++ xprt->stat.recvs++;
+ task->tk_rtt = (long)jiffies - req->rq_xtime;
+
+ list_del_init(&req->rq_list);
++ req->rq_private_buf.len = copied;
+ /* Ensure all writes are done before we update req->rq_received */
+ smp_wmb();
+- req->rq_received = req->rq_private_buf.len = copied;
+- rpc_wake_up_task(task);
++ req->rq_received = copied;
++ rpc_wake_up_queued_task(&xprt->pending, task);
+ }
+ EXPORT_SYMBOL_GPL(xprt_complete_rqst);
+
+@@ -769,17 +797,17 @@ static void xprt_timer(struct rpc_task *task)
+ struct rpc_rqst *req = task->tk_rqstp;
+ struct rpc_xprt *xprt = req->rq_xprt;
+
++ if (task->tk_status != -ETIMEDOUT)
++ return;
+ dprintk("RPC: %5u xprt_timer\n", task->tk_pid);
+
+- spin_lock(&xprt->transport_lock);
++ spin_lock_bh(&xprt->transport_lock);
+ if (!req->rq_received) {
+ if (xprt->ops->timer)
+ xprt->ops->timer(task);
+- task->tk_status = -ETIMEDOUT;
+- }
+- task->tk_timeout = 0;
+- rpc_wake_up_task(task);
+- spin_unlock(&xprt->transport_lock);
++ } else
++ task->tk_status = 0;
++ spin_unlock_bh(&xprt->transport_lock);
+ }
+
+ /**
+@@ -849,6 +877,7 @@ void xprt_transmit(struct rpc_task *task)
+ } else if (!req->rq_bytes_sent)
+ return;
+
++ req->rq_connect_cookie = xprt->connect_cookie;
+ status = xprt->ops->send_request(task);
+ if (status == 0) {
+ dprintk("RPC: %5u xmit complete\n", task->tk_pid);
+@@ -864,7 +893,7 @@ void xprt_transmit(struct rpc_task *task)
+ if (!xprt_connected(xprt))
+ task->tk_status = -ENOTCONN;
+ else if (!req->rq_received)
+- rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);
++ rpc_sleep_on(&xprt->pending, task, xprt_timer);
+ spin_unlock_bh(&xprt->transport_lock);
+ return;
+ }
+@@ -875,7 +904,7 @@ void xprt_transmit(struct rpc_task *task)
+ */
+ task->tk_status = status;
+ if (status == -ECONNREFUSED)
+- rpc_sleep_on(&xprt->sending, task, NULL, NULL);
++ rpc_sleep_on(&xprt->sending, task, NULL);
+ }
+
+ static inline void do_xprt_reserve(struct rpc_task *task)
+@@ -895,7 +924,7 @@ static inline void do_xprt_reserve(struct rpc_task *task)
+ dprintk("RPC: waiting for request slot\n");
+ task->tk_status = -EAGAIN;
+ task->tk_timeout = 0;
+- rpc_sleep_on(&xprt->backlog, task, NULL, NULL);
++ rpc_sleep_on(&xprt->backlog, task, NULL);
+ }
+
+ /**
+@@ -1052,6 +1081,11 @@ static void xprt_destroy(struct kref *kref)
+ xprt->shutdown = 1;
+ del_timer_sync(&xprt->timer);
+
++ rpc_destroy_wait_queue(&xprt->binding);
++ rpc_destroy_wait_queue(&xprt->pending);
++ rpc_destroy_wait_queue(&xprt->sending);
++ rpc_destroy_wait_queue(&xprt->resend);
++ rpc_destroy_wait_queue(&xprt->backlog);
+ /*
+ * Tear down transport state and free the rpc_xprt
+ */
+diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c
+index 16fd3f6..af408fc 100644
+--- a/net/sunrpc/xprtrdma/svc_rdma_transport.c
++++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c
+@@ -1036,6 +1036,8 @@ int svc_rdma_send(struct svcxprt_rdma *xprt, struct ib_send_wr *wr)
+ wait_event(xprt->sc_send_wait,
+ atomic_read(&xprt->sc_sq_count) <
+ xprt->sc_sq_depth);
++ if (test_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags))
++ return 0;
+ continue;
+ }
+ /* Bumped used SQ WR count and post */
+diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
+index ffbf22a..8ea283e 100644
+--- a/net/sunrpc/xprtrdma/verbs.c
++++ b/net/sunrpc/xprtrdma/verbs.c
+@@ -1573,7 +1573,6 @@ rpcrdma_ep_post(struct rpcrdma_ia *ia,
+ send_wr.sg_list = req->rl_send_iov;
+ send_wr.num_sge = req->rl_niovs;
+ send_wr.opcode = IB_WR_SEND;
+- send_wr.imm_data = 0;
+ if (send_wr.num_sge == 4) /* no need to sync any pad (constant) */
+ ib_dma_sync_single_for_device(ia->ri_id->device,
+ req->rl_send_iov[3].addr, req->rl_send_iov[3].length,
+diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
+index 30e7ac2..ddbe981 100644
+--- a/net/sunrpc/xprtsock.c
++++ b/net/sunrpc/xprtsock.c
+@@ -136,12 +136,6 @@ static ctl_table sunrpc_table[] = {
+ #endif
+
+ /*
+- * How many times to try sending a request on a socket before waiting
+- * for the socket buffer to clear.
+- */
+-#define XS_SENDMSG_RETRY (10U)
+-
+-/*
+ * Time out for an RPC UDP socket connect. UDP socket connects are
+ * synchronous, but we set a timeout anyway in case of resource
+ * exhaustion on the local host.
+@@ -516,6 +510,14 @@ out:
+ return sent;
+ }
+
++static void xs_nospace_callback(struct rpc_task *task)
++{
++ struct sock_xprt *transport = container_of(task->tk_rqstp->rq_xprt, struct sock_xprt, xprt);
++
++ transport->inet->sk_write_pending--;
++ clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
++}
++
+ /**
+ * xs_nospace - place task on wait queue if transmit was incomplete
+ * @task: task to put to sleep
+@@ -531,20 +533,27 @@ static void xs_nospace(struct rpc_task *task)
+ task->tk_pid, req->rq_slen - req->rq_bytes_sent,
+ req->rq_slen);
+
+- if (test_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags)) {
+- /* Protect against races with write_space */
+- spin_lock_bh(&xprt->transport_lock);
+-
+- /* Don't race with disconnect */
+- if (!xprt_connected(xprt))
+- task->tk_status = -ENOTCONN;
+- else if (test_bit(SOCK_NOSPACE, &transport->sock->flags))
+- xprt_wait_for_buffer_space(task);
++ /* Protect against races with write_space */
++ spin_lock_bh(&xprt->transport_lock);
++
++ /* Don't race with disconnect */
++ if (xprt_connected(xprt)) {
++ if (test_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags)) {
++ /*
++ * Notify TCP that we're limited by the application
++ * window size
++ */
++ set_bit(SOCK_NOSPACE, &transport->sock->flags);
++ transport->inet->sk_write_pending++;
++ /* ...and wait for more buffer space */
++ xprt_wait_for_buffer_space(task, xs_nospace_callback);
++ }
++ } else {
++ clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
++ task->tk_status = -ENOTCONN;
++ }
+
+- spin_unlock_bh(&xprt->transport_lock);
+- } else
+- /* Keep holding the socket if it is blocked */
+- rpc_delay(task, HZ>>4);
++ spin_unlock_bh(&xprt->transport_lock);
+ }
+
+ /**
+@@ -588,19 +597,20 @@ static int xs_udp_send_request(struct rpc_task *task)
+ }
+
+ switch (status) {
++ case -EAGAIN:
++ xs_nospace(task);
++ break;
+ case -ENETUNREACH:
+ case -EPIPE:
+ case -ECONNREFUSED:
+ /* When the server has died, an ICMP port unreachable message
+ * prompts ECONNREFUSED. */
+- break;
+- case -EAGAIN:
+- xs_nospace(task);
++ clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
+ break;
+ default:
++ clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
+ dprintk("RPC: sendmsg returned unrecognized error %d\n",
+ -status);
+- break;
+ }
+
+ return status;
+@@ -650,7 +660,6 @@ static int xs_tcp_send_request(struct rpc_task *task)
+ struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
+ struct xdr_buf *xdr = &req->rq_snd_buf;
+ int status;
+- unsigned int retry = 0;
+
+ xs_encode_tcp_record_marker(&req->rq_snd_buf);
+
+@@ -681,9 +690,10 @@ static int xs_tcp_send_request(struct rpc_task *task)
+ return 0;
+ }
+
++ if (status != 0)
++ continue;
+ status = -EAGAIN;
+- if (retry++ > XS_SENDMSG_RETRY)
+- break;
++ break;
+ }
+
+ switch (status) {
+@@ -695,12 +705,13 @@ static int xs_tcp_send_request(struct rpc_task *task)
+ case -ENOTCONN:
+ case -EPIPE:
+ status = -ENOTCONN;
++ clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
+ break;
+ default:
+ dprintk("RPC: sendmsg returned unrecognized error %d\n",
+ -status);
++ clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
+ xs_tcp_shutdown(xprt);
+- break;
+ }
+
+ return status;
+@@ -1073,6 +1084,7 @@ static void xs_tcp_data_ready(struct sock *sk, int bytes)
+ {
+ struct rpc_xprt *xprt;
+ read_descriptor_t rd_desc;
++ int read;
+
+ dprintk("RPC: xs_tcp_data_ready...\n");
+
+@@ -1084,8 +1096,10 @@ static void xs_tcp_data_ready(struct sock *sk, int bytes)
+
+ /* We use rd_desc to pass struct xprt to xs_tcp_data_recv */
+ rd_desc.arg.data = xprt;
+- rd_desc.count = 65536;
+- tcp_read_sock(sk, &rd_desc, xs_tcp_data_recv);
++ do {
++ rd_desc.count = 65536;
++ read = tcp_read_sock(sk, &rd_desc, xs_tcp_data_recv);
++ } while (read > 0);
+ out:
+ read_unlock(&sk->sk_callback_lock);
+ }
+@@ -1128,6 +1142,7 @@ static void xs_tcp_state_change(struct sock *sk)
+ break;
+ case TCP_FIN_WAIT1:
+ /* The client initiated a shutdown of the socket */
++ xprt->connect_cookie++;
+ xprt->reestablish_timeout = 0;
+ set_bit(XPRT_CLOSING, &xprt->state);
+ smp_mb__before_clear_bit();
+@@ -1140,6 +1155,7 @@ static void xs_tcp_state_change(struct sock *sk)
+ set_bit(XPRT_CLOSING, &xprt->state);
+ xprt_force_disconnect(xprt);
+ case TCP_SYN_SENT:
++ xprt->connect_cookie++;
+ case TCP_CLOSING:
+ /*
+ * If the server closed down the connection, make sure that
+@@ -1186,9 +1202,11 @@ static void xs_udp_write_space(struct sock *sk)
+
+ if (unlikely(!(sock = sk->sk_socket)))
+ goto out;
++ clear_bit(SOCK_NOSPACE, &sock->flags);
++
+ if (unlikely(!(xprt = xprt_from_sock(sk))))
+ goto out;
+- if (unlikely(!test_and_clear_bit(SOCK_NOSPACE, &sock->flags)))
++ if (test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags) == 0)
+ goto out;
+
+ xprt_write_space(xprt);
+@@ -1219,9 +1237,11 @@ static void xs_tcp_write_space(struct sock *sk)
+
+ if (unlikely(!(sock = sk->sk_socket)))
+ goto out;
++ clear_bit(SOCK_NOSPACE, &sock->flags);
++
+ if (unlikely(!(xprt = xprt_from_sock(sk))))
+ goto out;
+- if (unlikely(!test_and_clear_bit(SOCK_NOSPACE, &sock->flags)))
++ if (test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags) == 0)
+ goto out;
+
+ xprt_write_space(xprt);
+@@ -1359,7 +1379,7 @@ static int xs_bind4(struct sock_xprt *transport, struct socket *sock)
+ nloop++;
+ } while (err == -EADDRINUSE && nloop != 2);
+ dprintk("RPC: %s "NIPQUAD_FMT":%u: %s (%d)\n",
+- __FUNCTION__, NIPQUAD(myaddr.sin_addr),
++ __func__, NIPQUAD(myaddr.sin_addr),
+ port, err ? "failed" : "ok", err);
+ return err;
+ }
+diff --git a/net/tipc/core.c b/net/tipc/core.c
+index d2d7d32..740aac5 100644
+--- a/net/tipc/core.c
++++ b/net/tipc/core.c
+@@ -48,16 +48,8 @@
+ #include "subscr.h"
+ #include "config.h"
+
+-int tipc_eth_media_start(void);
+-void tipc_eth_media_stop(void);
+-int tipc_handler_start(void);
+-void tipc_handler_stop(void);
+-int tipc_socket_init(void);
+-void tipc_socket_stop(void);
+-int tipc_netlink_start(void);
+-void tipc_netlink_stop(void);
+
+-#define TIPC_MOD_VER "1.6.2"
++#define TIPC_MOD_VER "1.6.3"
+
+ #ifndef CONFIG_TIPC_ZONES
+ #define CONFIG_TIPC_ZONES 3
+@@ -277,7 +269,6 @@ EXPORT_SYMBOL(tipc_register_media);
+ /* TIPC API for external APIs (see tipc_port.h) */
+
+ EXPORT_SYMBOL(tipc_createport_raw);
+-EXPORT_SYMBOL(tipc_set_msg_option);
+ EXPORT_SYMBOL(tipc_reject_msg);
+ EXPORT_SYMBOL(tipc_send_buf_fast);
+ EXPORT_SYMBOL(tipc_acknowledge);
+diff --git a/net/tipc/core.h b/net/tipc/core.h
+index feabca5..325404f 100644
+--- a/net/tipc/core.h
++++ b/net/tipc/core.h
+@@ -180,6 +180,12 @@ extern int tipc_core_start(void);
+ extern void tipc_core_stop(void);
+ extern int tipc_core_start_net(void);
+ extern void tipc_core_stop_net(void);
++extern int tipc_handler_start(void);
++extern void tipc_handler_stop(void);
++extern int tipc_netlink_start(void);
++extern void tipc_netlink_stop(void);
++extern int tipc_socket_init(void);
++extern void tipc_socket_stop(void);
+
+ static inline int delimit(int val, int min, int max)
+ {
+@@ -310,7 +316,7 @@ static inline struct sk_buff *buf_acquire(u32 size)
+ struct sk_buff *skb;
+ unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u;
+
+- skb = alloc_skb(buf_size, GFP_ATOMIC);
++ skb = alloc_skb_fclone(buf_size, GFP_ATOMIC);
+ if (skb) {
+ skb_reserve(skb, BUF_HEADROOM);
+ skb_put(skb, size);
+@@ -328,8 +334,19 @@ static inline struct sk_buff *buf_acquire(u32 size)
+
+ static inline void buf_discard(struct sk_buff *skb)
+ {
+- if (likely(skb != NULL))
+- kfree_skb(skb);
++ kfree_skb(skb);
++}
++
++/**
++ * buf_linearize - convert a TIPC message buffer into a single contiguous piece
++ * @skb: message buffer
++ *
++ * Returns 0 on success.
++ */
++
++static inline int buf_linearize(struct sk_buff *skb)
++{
++ return skb_linearize(skb);
+ }
+
+ #endif
+diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
+index 3bbef2a..9cd35ee 100644
+--- a/net/tipc/eth_media.c
++++ b/net/tipc/eth_media.c
+@@ -101,7 +101,7 @@ static int recv_msg(struct sk_buff *buf, struct net_device *dev,
+ struct eth_bearer *eb_ptr = (struct eth_bearer *)pt->af_packet_priv;
+ u32 size;
+
+- if (dev->nd_net != &init_net) {
++ if (dev_net(dev) != &init_net) {
+ kfree_skb(buf);
+ return 0;
+ }
+@@ -198,7 +198,7 @@ static int recv_notification(struct notifier_block *nb, unsigned long evt,
+ struct eth_bearer *eb_ptr = ð_bearers[0];
+ struct eth_bearer *stop = ð_bearers[MAX_ETH_BEARERS];
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ while ((eb_ptr->dev != dev)) {
+diff --git a/net/tipc/link.c b/net/tipc/link.c
+index cefa998..2a26a16 100644
+--- a/net/tipc/link.c
++++ b/net/tipc/link.c
+@@ -1785,6 +1785,56 @@ static struct sk_buff *link_insert_deferred_queue(struct link *l_ptr,
+ return buf;
+ }
+
++/**
++ * link_recv_buf_validate - validate basic format of received message
++ *
++ * This routine ensures a TIPC message has an acceptable header, and at least
++ * as much data as the header indicates it should. The routine also ensures
++ * that the entire message header is stored in the main fragment of the message
++ * buffer, to simplify future access to message header fields.
++ *
++ * Note: Having extra info present in the message header or data areas is OK.
++ * TIPC will ignore the excess, under the assumption that it is optional info
++ * introduced by a later release of the protocol.
++ */
++
++static int link_recv_buf_validate(struct sk_buff *buf)
++{
++ static u32 min_data_hdr_size[8] = {
++ SHORT_H_SIZE, MCAST_H_SIZE, LONG_H_SIZE, DIR_MSG_H_SIZE,
++ MAX_H_SIZE, MAX_H_SIZE, MAX_H_SIZE, MAX_H_SIZE
++ };
++
++ struct tipc_msg *msg;
++ u32 tipc_hdr[2];
++ u32 size;
++ u32 hdr_size;
++ u32 min_hdr_size;
++
++ if (unlikely(buf->len < MIN_H_SIZE))
++ return 0;
++
++ msg = skb_header_pointer(buf, 0, sizeof(tipc_hdr), tipc_hdr);
++ if (msg == NULL)
++ return 0;
++
++ if (unlikely(msg_version(msg) != TIPC_VERSION))
++ return 0;
++
++ size = msg_size(msg);
++ hdr_size = msg_hdr_sz(msg);
++ min_hdr_size = msg_isdata(msg) ?
++ min_data_hdr_size[msg_type(msg)] : INT_H_SIZE;
++
++ if (unlikely((hdr_size < min_hdr_size) ||
++ (size < hdr_size) ||
++ (buf->len < size) ||
++ (size - hdr_size > TIPC_MAX_USER_MSG_SIZE)))
++ return 0;
++
++ return pskb_may_pull(buf, hdr_size);
++}
++
+ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
+ {
+ read_lock_bh(&tipc_net_lock);
+@@ -1794,9 +1844,9 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
+ struct link *l_ptr;
+ struct sk_buff *crs;
+ struct sk_buff *buf = head;
+- struct tipc_msg *msg = buf_msg(buf);
+- u32 seq_no = msg_seqno(msg);
+- u32 ackd = msg_ack(msg);
++ struct tipc_msg *msg;
++ u32 seq_no;
++ u32 ackd;
+ u32 released = 0;
+ int type;
+
+@@ -1804,12 +1854,21 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
+ TIPC_SKB_CB(buf)->handle = b_ptr;
+
+ head = head->next;
+- if (unlikely(msg_version(msg) != TIPC_VERSION))
++
++ /* Ensure message is well-formed */
++
++ if (unlikely(!link_recv_buf_validate(buf)))
+ goto cont;
+-#if 0
+- if (msg_user(msg) != LINK_PROTOCOL)
+-#endif
+- msg_dbg(msg,"<REC<");
++
++ /* Ensure message data is a single contiguous unit */
++
++ if (unlikely(buf_linearize(buf))) {
++ goto cont;
++ }
++
++ /* Handle arrival of a non-unicast link message */
++
++ msg = buf_msg(buf);
+
+ if (unlikely(msg_non_seq(msg))) {
+ link_recv_non_seq(buf);
+@@ -1820,19 +1879,26 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
+ (msg_destnode(msg) != tipc_own_addr)))
+ goto cont;
+
++ /* Locate unicast link endpoint that should handle message */
++
+ n_ptr = tipc_node_find(msg_prevnode(msg));
+ if (unlikely(!n_ptr))
+ goto cont;
+-
+ tipc_node_lock(n_ptr);
++
+ l_ptr = n_ptr->links[b_ptr->identity];
+ if (unlikely(!l_ptr)) {
+ tipc_node_unlock(n_ptr);
+ goto cont;
+ }
+- /*
+- * Release acked messages
+- */
++
++ /* Validate message sequence number info */
++
++ seq_no = msg_seqno(msg);
++ ackd = msg_ack(msg);
++
++ /* Release acked messages */
++
+ if (less(n_ptr->bclink.acked, msg_bcast_ack(msg))) {
+ if (tipc_node_is_up(n_ptr) && n_ptr->bclink.supported)
+ tipc_bclink_acknowledge(n_ptr, msg_bcast_ack(msg));
+@@ -1851,6 +1917,9 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
+ l_ptr->first_out = crs;
+ l_ptr->out_queue_size -= released;
+ }
++
++ /* Try sending any messages link endpoint has pending */
++
+ if (unlikely(l_ptr->next_out))
+ tipc_link_push_queue(l_ptr);
+ if (unlikely(!list_empty(&l_ptr->waiting_ports)))
+@@ -1860,6 +1929,8 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
+ tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
+ }
+
++ /* Now (finally!) process the incoming message */
++
+ protocol_check:
+ if (likely(link_working_working(l_ptr))) {
+ if (likely(seq_no == mod(l_ptr->next_in_no))) {
+@@ -2832,15 +2903,15 @@ static void link_set_supervision_props(struct link *l_ptr, u32 tolerance)
+ void tipc_link_set_queue_limits(struct link *l_ptr, u32 window)
+ {
+ /* Data messages from this node, inclusive FIRST_FRAGM */
+- l_ptr->queue_limit[DATA_LOW] = window;
+- l_ptr->queue_limit[DATA_MEDIUM] = (window / 3) * 4;
+- l_ptr->queue_limit[DATA_HIGH] = (window / 3) * 5;
+- l_ptr->queue_limit[DATA_CRITICAL] = (window / 3) * 6;
++ l_ptr->queue_limit[TIPC_LOW_IMPORTANCE] = window;
++ l_ptr->queue_limit[TIPC_MEDIUM_IMPORTANCE] = (window / 3) * 4;
++ l_ptr->queue_limit[TIPC_HIGH_IMPORTANCE] = (window / 3) * 5;
++ l_ptr->queue_limit[TIPC_CRITICAL_IMPORTANCE] = (window / 3) * 6;
+ /* Transiting data messages,inclusive FIRST_FRAGM */
+- l_ptr->queue_limit[DATA_LOW + 4] = 300;
+- l_ptr->queue_limit[DATA_MEDIUM + 4] = 600;
+- l_ptr->queue_limit[DATA_HIGH + 4] = 900;
+- l_ptr->queue_limit[DATA_CRITICAL + 4] = 1200;
++ l_ptr->queue_limit[TIPC_LOW_IMPORTANCE + 4] = 300;
++ l_ptr->queue_limit[TIPC_MEDIUM_IMPORTANCE + 4] = 600;
++ l_ptr->queue_limit[TIPC_HIGH_IMPORTANCE + 4] = 900;
++ l_ptr->queue_limit[TIPC_CRITICAL_IMPORTANCE + 4] = 1200;
+ l_ptr->queue_limit[CONN_MANAGER] = 1200;
+ l_ptr->queue_limit[ROUTE_DISTRIBUTOR] = 1200;
+ l_ptr->queue_limit[CHANGEOVER_PROTOCOL] = 2500;
+diff --git a/net/tipc/msg.c b/net/tipc/msg.c
+index 7824854..696a863 100644
+--- a/net/tipc/msg.c
++++ b/net/tipc/msg.c
+@@ -73,10 +73,10 @@ void tipc_msg_print(struct print_buf *buf, struct tipc_msg *msg, const char *str
+ tipc_printf(buf, "NO(%u/%u):",msg_long_msgno(msg),
+ msg_fragm_no(msg));
+ break;
+- case DATA_LOW:
+- case DATA_MEDIUM:
+- case DATA_HIGH:
+- case DATA_CRITICAL:
++ case TIPC_LOW_IMPORTANCE:
++ case TIPC_MEDIUM_IMPORTANCE:
++ case TIPC_HIGH_IMPORTANCE:
++ case TIPC_CRITICAL_IMPORTANCE:
+ tipc_printf(buf, "DAT%u:", msg_user(msg));
+ if (msg_short(msg)) {
+ tipc_printf(buf, "CON:");
+@@ -229,10 +229,10 @@ void tipc_msg_print(struct print_buf *buf, struct tipc_msg *msg, const char *str
+ switch (usr) {
+ case CONN_MANAGER:
+ case NAME_DISTRIBUTOR:
+- case DATA_LOW:
+- case DATA_MEDIUM:
+- case DATA_HIGH:
+- case DATA_CRITICAL:
++ case TIPC_LOW_IMPORTANCE:
++ case TIPC_MEDIUM_IMPORTANCE:
++ case TIPC_HIGH_IMPORTANCE:
++ case TIPC_CRITICAL_IMPORTANCE:
+ if (msg_short(msg))
+ break; /* No error */
+ switch (msg_errcode(msg)) {
+diff --git a/net/tipc/msg.h b/net/tipc/msg.h
+index e9ef6df..6ad070d 100644
+--- a/net/tipc/msg.h
++++ b/net/tipc/msg.h
+@@ -40,18 +40,16 @@
+ #include "core.h"
+
+ #define TIPC_VERSION 2
+-#define DATA_LOW TIPC_LOW_IMPORTANCE
+-#define DATA_MEDIUM TIPC_MEDIUM_IMPORTANCE
+-#define DATA_HIGH TIPC_HIGH_IMPORTANCE
+-#define DATA_CRITICAL TIPC_CRITICAL_IMPORTANCE
+-#define SHORT_H_SIZE 24 /* Connected,in cluster */
++
++#define SHORT_H_SIZE 24 /* Connected, in-cluster messages */
+ #define DIR_MSG_H_SIZE 32 /* Directly addressed messages */
+-#define CONN_MSG_H_SIZE 36 /* Routed connected msgs*/
+-#define LONG_H_SIZE 40 /* Named Messages */
++#define LONG_H_SIZE 40 /* Named messages */
+ #define MCAST_H_SIZE 44 /* Multicast messages */
+-#define MAX_H_SIZE 60 /* Inclusive full options */
++#define INT_H_SIZE 40 /* Internal messages */
++#define MIN_H_SIZE 24 /* Smallest legal TIPC header size */
++#define MAX_H_SIZE 60 /* Largest possible TIPC header size */
++
+ #define MAX_MSG_SIZE (MAX_H_SIZE + TIPC_MAX_USER_MSG_SIZE)
+-#define LINK_CONFIG 13
+
+
+ /*
+@@ -72,8 +70,10 @@ static inline void msg_set_bits(struct tipc_msg *m, u32 w,
+ u32 pos, u32 mask, u32 val)
+ {
+ val = (val & mask) << pos;
+- m->hdr[w] &= ~htonl(mask << pos);
+- m->hdr[w] |= htonl(val);
++ val = htonl(val);
++ mask = htonl(mask << pos);
++ m->hdr[w] &= ~mask;
++ m->hdr[w] |= val;
+ }
+
+ /*
+@@ -87,7 +87,7 @@ static inline u32 msg_version(struct tipc_msg *m)
+
+ static inline void msg_set_version(struct tipc_msg *m)
+ {
+- msg_set_bits(m, 0, 29, 0xf, TIPC_VERSION);
++ msg_set_bits(m, 0, 29, 7, TIPC_VERSION);
+ }
+
+ static inline u32 msg_user(struct tipc_msg *m)
+@@ -97,7 +97,7 @@ static inline u32 msg_user(struct tipc_msg *m)
+
+ static inline u32 msg_isdata(struct tipc_msg *m)
+ {
+- return (msg_user(m) <= DATA_CRITICAL);
++ return (msg_user(m) <= TIPC_CRITICAL_IMPORTANCE);
+ }
+
+ static inline void msg_set_user(struct tipc_msg *m, u32 n)
+@@ -190,18 +190,6 @@ static inline void msg_set_lookup_scope(struct tipc_msg *m, u32 n)
+ msg_set_bits(m, 1, 19, 0x3, n);
+ }
+
+-static inline void msg_set_options(struct tipc_msg *m, const char *opt, u32 sz)
+-{
+- u32 hsz = msg_hdr_sz(m);
+- char *to = (char *)&m->hdr[hsz/4];
+-
+- if ((hsz < DIR_MSG_H_SIZE) || ((hsz + sz) > MAX_H_SIZE))
+- return;
+- msg_set_bits(m, 1, 16, 0x7, (hsz - 28)/4);
+- msg_set_hdr_sz(m, hsz + sz);
+- memcpy(to, opt, sz);
+-}
+-
+ static inline u32 msg_bcast_ack(struct tipc_msg *m)
+ {
+ return msg_bits(m, 1, 0, 0xffff);
+@@ -330,17 +318,6 @@ static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m)
+ return (struct tipc_msg *)msg_data(m);
+ }
+
+-static inline void msg_expand(struct tipc_msg *m, u32 destnode)
+-{
+- if (!msg_short(m))
+- return;
+- msg_set_hdr_sz(m, LONG_H_SIZE);
+- msg_set_orignode(m, msg_prevnode(m));
+- msg_set_destnode(m, destnode);
+- memset(&m->hdr[8], 0, 12);
+-}
+-
+-
+
+ /*
+ TIPC internal message header format, version 2
+@@ -388,7 +365,6 @@ static inline void msg_expand(struct tipc_msg *m, u32 destnode)
+ #define NAME_DISTRIBUTOR 11
+ #define MSG_FRAGMENTER 12
+ #define LINK_CONFIG 13
+-#define INT_H_SIZE 40
+ #define DSC_H_SIZE 40
+
+ /*
+diff --git a/net/tipc/port.c b/net/tipc/port.c
+index f508614..2f58064 100644
+--- a/net/tipc/port.c
++++ b/net/tipc/port.c
+@@ -242,7 +242,8 @@ u32 tipc_createport_raw(void *usr_handle,
+ p_ptr->publ.max_pkt = MAX_PKT_DEFAULT;
+ p_ptr->publ.ref = ref;
+ msg = &p_ptr->publ.phdr;
+- msg_init(msg, DATA_LOW, TIPC_NAMED_MSG, TIPC_OK, LONG_H_SIZE, 0);
++ msg_init(msg, TIPC_LOW_IMPORTANCE, TIPC_NAMED_MSG, TIPC_OK, LONG_H_SIZE,
++ 0);
+ msg_set_orignode(msg, tipc_own_addr);
+ msg_set_prevnode(msg, tipc_own_addr);
+ msg_set_origport(msg, ref);
+@@ -413,13 +414,6 @@ static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode,
+ return buf;
+ }
+
+-int tipc_set_msg_option(struct tipc_port *tp_ptr, const char *opt, const u32 sz)
+-{
+- msg_expand(&tp_ptr->phdr, msg_destnode(&tp_ptr->phdr));
+- msg_set_options(&tp_ptr->phdr, opt, sz);
+- return TIPC_OK;
+-}
+-
+ int tipc_reject_msg(struct sk_buff *buf, u32 err)
+ {
+ struct tipc_msg *msg = buf_msg(buf);
+@@ -632,7 +626,7 @@ void tipc_port_recv_proto_msg(struct sk_buff *buf)
+ msg_orignode(msg),
+ msg_destport(msg),
+ tipc_own_addr,
+- DATA_HIGH,
++ TIPC_HIGH_IMPORTANCE,
+ TIPC_CONN_MSG,
+ err,
+ 0,
+@@ -1246,6 +1240,28 @@ exit:
+ return res;
+ }
+
++/**
++ * tipc_disconnect_port - disconnect port from peer
++ *
++ * Port must be locked.
++ */
++
++int tipc_disconnect_port(struct tipc_port *tp_ptr)
++{
++ int res;
++
++ if (tp_ptr->connected) {
++ tp_ptr->connected = 0;
++ /* let timer expire on it's own to avoid deadlock! */
++ tipc_nodesub_unsubscribe(
++ &((struct port *)tp_ptr)->subscription);
++ res = TIPC_OK;
++ } else {
++ res = -ENOTCONN;
++ }
++ return res;
++}
++
+ /*
+ * tipc_disconnect(): Disconnect port form peer.
+ * This is a node local operation.
+@@ -1254,17 +1270,12 @@ exit:
+ int tipc_disconnect(u32 ref)
+ {
+ struct port *p_ptr;
+- int res = -ENOTCONN;
++ int res;
+
+ p_ptr = tipc_port_lock(ref);
+ if (!p_ptr)
+ return -EINVAL;
+- if (p_ptr->publ.connected) {
+- p_ptr->publ.connected = 0;
+- /* let timer expire on it's own to avoid deadlock! */
+- tipc_nodesub_unsubscribe(&p_ptr->subscription);
+- res = TIPC_OK;
+- }
++ res = tipc_disconnect_port((struct tipc_port *)p_ptr);
+ tipc_port_unlock(p_ptr);
+ return res;
+ }
+diff --git a/net/tipc/ref.c b/net/tipc/ref.c
+index c38744c..89cbab2 100644
+--- a/net/tipc/ref.c
++++ b/net/tipc/ref.c
+@@ -2,7 +2,7 @@
+ * net/tipc/ref.c: TIPC object registry code
+ *
+ * Copyright (c) 1991-2006, Ericsson AB
+- * Copyright (c) 2004-2005, Wind River Systems
++ * Copyright (c) 2004-2007, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -36,32 +36,60 @@
+
+ #include "core.h"
+ #include "ref.h"
+-#include "port.h"
+-#include "subscr.h"
+-#include "name_distr.h"
+-#include "name_table.h"
+-#include "config.h"
+-#include "discover.h"
+-#include "bearer.h"
+-#include "node.h"
+-#include "bcast.h"
++
++/**
++ * struct reference - TIPC object reference entry
++ * @object: pointer to object associated with reference entry
++ * @lock: spinlock controlling access to object
++ * @ref: reference value for object (combines instance & array index info)
++ */
++
++struct reference {
++ void *object;
++ spinlock_t lock;
++ u32 ref;
++};
++
++/**
++ * struct tipc_ref_table - table of TIPC object reference entries
++ * @entries: pointer to array of reference entries
++ * @capacity: array index of first unusable entry
++ * @init_point: array index of first uninitialized entry
++ * @first_free: array index of first unused object reference entry
++ * @last_free: array index of last unused object reference entry
++ * @index_mask: bitmask for array index portion of reference values
++ * @start_mask: initial value for instance value portion of reference values
++ */
++
++struct ref_table {
++ struct reference *entries;
++ u32 capacity;
++ u32 init_point;
++ u32 first_free;
++ u32 last_free;
++ u32 index_mask;
++ u32 start_mask;
++};
+
+ /*
+ * Object reference table consists of 2**N entries.
+ *
+- * A used entry has object ptr != 0, reference == XXXX|own index
+- * (XXXX changes each time entry is acquired)
+- * A free entry has object ptr == 0, reference == YYYY|next free index
+- * (YYYY is one more than last used XXXX)
++ * State Object ptr Reference
++ * ----- ---------- ---------
++ * In use non-NULL XXXX|own index
++ * (XXXX changes each time entry is acquired)
++ * Free NULL YYYY|next free index
++ * (YYYY is one more than last used XXXX)
++ * Uninitialized NULL 0
+ *
+- * Free list is initially chained from entry (2**N)-1 to entry 1.
+- * Entry 0 is not used to allow index 0 to indicate the end of the free list.
++ * Entry 0 is not used; this allows index 0 to denote the end of the free list.
+ *
+- * Note: Any accidental reference of the form XXXX|0--0 won't match entry 0
+- * because entry 0's reference field has the form XXXX|1--1.
++ * Note that a reference value of 0 does not necessarily indicate that an
++ * entry is uninitialized, since the last entry in the free list could also
++ * have a reference value of 0 (although this is unlikely).
+ */
+
+-struct ref_table tipc_ref_table = { NULL };
++static struct ref_table tipc_ref_table = { NULL };
+
+ static DEFINE_RWLOCK(ref_table_lock);
+
+@@ -72,29 +100,29 @@ static DEFINE_RWLOCK(ref_table_lock);
+ int tipc_ref_table_init(u32 requested_size, u32 start)
+ {
+ struct reference *table;
+- u32 sz = 1 << 4;
+- u32 index_mask;
+- int i;
++ u32 actual_size;
+
+- while (sz < requested_size) {
+- sz <<= 1;
+- }
+- table = vmalloc(sz * sizeof(*table));
++ /* account for unused entry, then round up size to a power of 2 */
++
++ requested_size++;
++ for (actual_size = 16; actual_size < requested_size; actual_size <<= 1)
++ /* do nothing */ ;
++
++ /* allocate table & mark all entries as uninitialized */
++
++ table = __vmalloc(actual_size * sizeof(struct reference),
++ GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
+ if (table == NULL)
+ return -ENOMEM;
+
+- write_lock_bh(&ref_table_lock);
+- index_mask = sz - 1;
+- for (i = sz - 1; i >= 0; i--) {
+- table[i].object = NULL;
+- spin_lock_init(&table[i].lock);
+- table[i].data.next_plus_upper = (start & ~index_mask) + i - 1;
+- }
+ tipc_ref_table.entries = table;
+- tipc_ref_table.index_mask = index_mask;
+- tipc_ref_table.first_free = sz - 1;
+- tipc_ref_table.last_free = 1;
+- write_unlock_bh(&ref_table_lock);
++ tipc_ref_table.capacity = requested_size;
++ tipc_ref_table.init_point = 1;
++ tipc_ref_table.first_free = 0;
++ tipc_ref_table.last_free = 0;
++ tipc_ref_table.index_mask = actual_size - 1;
++ tipc_ref_table.start_mask = start & ~tipc_ref_table.index_mask;
++
+ return TIPC_OK;
+ }
+
+@@ -125,7 +153,7 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock)
+ u32 index;
+ u32 index_mask;
+ u32 next_plus_upper;
+- u32 reference = 0;
++ u32 ref;
+
+ if (!object) {
+ err("Attempt to acquire reference to non-existent object\n");
+@@ -136,6 +164,8 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock)
+ return 0;
+ }
+
++ /* take a free entry, if available; otherwise initialize a new entry */
++
+ write_lock_bh(&ref_table_lock);
+ if (tipc_ref_table.first_free) {
+ index = tipc_ref_table.first_free;
+@@ -143,17 +173,29 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock)
+ index_mask = tipc_ref_table.index_mask;
+ /* take lock in case a previous user of entry still holds it */
+ spin_lock_bh(&entry->lock);
+- next_plus_upper = entry->data.next_plus_upper;
++ next_plus_upper = entry->ref;
+ tipc_ref_table.first_free = next_plus_upper & index_mask;
+- reference = (next_plus_upper & ~index_mask) + index;
+- entry->data.reference = reference;
++ ref = (next_plus_upper & ~index_mask) + index;
++ entry->ref = ref;
+ entry->object = object;
+- if (lock != NULL)
+- *lock = &entry->lock;
+ spin_unlock_bh(&entry->lock);
++ *lock = &entry->lock;
++ }
++ else if (tipc_ref_table.init_point < tipc_ref_table.capacity) {
++ index = tipc_ref_table.init_point++;
++ entry = &(tipc_ref_table.entries[index]);
++ spin_lock_init(&entry->lock);
++ ref = tipc_ref_table.start_mask + index;
++ entry->ref = ref;
++ entry->object = object;
++ *lock = &entry->lock;
++ }
++ else {
++ ref = 0;
+ }
+ write_unlock_bh(&ref_table_lock);
+- return reference;
++
++ return ref;
+ }
+
+ /**
+@@ -169,42 +211,99 @@ void tipc_ref_discard(u32 ref)
+ u32 index;
+ u32 index_mask;
+
+- if (!ref) {
+- err("Attempt to discard reference 0\n");
+- return;
+- }
+ if (!tipc_ref_table.entries) {
+ err("Reference table not found during discard attempt\n");
+ return;
+ }
+
+- write_lock_bh(&ref_table_lock);
+ index_mask = tipc_ref_table.index_mask;
+ index = ref & index_mask;
+ entry = &(tipc_ref_table.entries[index]);
+
++ write_lock_bh(&ref_table_lock);
++
+ if (!entry->object) {
+ err("Attempt to discard reference to non-existent object\n");
+ goto exit;
+ }
+- if (entry->data.reference != ref) {
++ if (entry->ref != ref) {
+ err("Attempt to discard non-existent reference\n");
+ goto exit;
+ }
+
+- /* mark entry as unused */
++ /*
++ * mark entry as unused; increment instance part of entry's reference
++ * to invalidate any subsequent references
++ */
++
+ entry->object = NULL;
++ entry->ref = (ref & ~index_mask) + (index_mask + 1);
++
++ /* append entry to free entry list */
++
+ if (tipc_ref_table.first_free == 0)
+ tipc_ref_table.first_free = index;
+ else
+- /* next_plus_upper is always XXXX|0--0 for last free entry */
+- tipc_ref_table.entries[tipc_ref_table.last_free].data.next_plus_upper
+- |= index;
++ tipc_ref_table.entries[tipc_ref_table.last_free].ref |= index;
+ tipc_ref_table.last_free = index;
+
+- /* increment upper bits of entry to invalidate subsequent references */
+- entry->data.next_plus_upper = (ref & ~index_mask) + (index_mask + 1);
+ exit:
+ write_unlock_bh(&ref_table_lock);
+ }
+
++/**
++ * tipc_ref_lock - lock referenced object and return pointer to it
++ */
++
++void *tipc_ref_lock(u32 ref)
++{
++ if (likely(tipc_ref_table.entries)) {
++ struct reference *entry;
++
++ entry = &tipc_ref_table.entries[ref &
++ tipc_ref_table.index_mask];
++ if (likely(entry->ref != 0)) {
++ spin_lock_bh(&entry->lock);
++ if (likely((entry->ref == ref) && (entry->object)))
++ return entry->object;
++ spin_unlock_bh(&entry->lock);
++ }
++ }
++ return NULL;
++}
++
++/**
++ * tipc_ref_unlock - unlock referenced object
++ */
++
++void tipc_ref_unlock(u32 ref)
++{
++ if (likely(tipc_ref_table.entries)) {
++ struct reference *entry;
++
++ entry = &tipc_ref_table.entries[ref &
++ tipc_ref_table.index_mask];
++ if (likely((entry->ref == ref) && (entry->object)))
++ spin_unlock_bh(&entry->lock);
++ else
++ err("Attempt to unlock non-existent reference\n");
++ }
++}
++
++/**
++ * tipc_ref_deref - return pointer referenced object (without locking it)
++ */
++
++void *tipc_ref_deref(u32 ref)
++{
++ if (likely(tipc_ref_table.entries)) {
++ struct reference *entry;
++
++ entry = &tipc_ref_table.entries[ref &
++ tipc_ref_table.index_mask];
++ if (likely(entry->ref == ref))
++ return entry->object;
++ }
++ return NULL;
++}
++
+diff --git a/net/tipc/ref.h b/net/tipc/ref.h
+index 38f3a7f..7e3798e 100644
+--- a/net/tipc/ref.h
++++ b/net/tipc/ref.h
+@@ -2,7 +2,7 @@
+ * net/tipc/ref.h: Include file for TIPC object registry code
+ *
+ * Copyright (c) 1991-2006, Ericsson AB
+- * Copyright (c) 2005, Wind River Systems
++ * Copyright (c) 2005-2006, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -37,95 +37,14 @@
+ #ifndef _TIPC_REF_H
+ #define _TIPC_REF_H
+
+-/**
+- * struct reference - TIPC object reference entry
+- * @object: pointer to object associated with reference entry
+- * @lock: spinlock controlling access to object
+- * @data: reference value associated with object (or link to next unused entry)
+- */
+-
+-struct reference {
+- void *object;
+- spinlock_t lock;
+- union {
+- u32 next_plus_upper;
+- u32 reference;
+- } data;
+-};
+-
+-/**
+- * struct tipc_ref_table - table of TIPC object reference entries
+- * @entries: pointer to array of reference entries
+- * @index_mask: bitmask for array index portion of reference values
+- * @first_free: array index of first unused object reference entry
+- * @last_free: array index of last unused object reference entry
+- */
+-
+-struct ref_table {
+- struct reference *entries;
+- u32 index_mask;
+- u32 first_free;
+- u32 last_free;
+-};
+-
+-extern struct ref_table tipc_ref_table;
+-
+ int tipc_ref_table_init(u32 requested_size, u32 start);
+ void tipc_ref_table_stop(void);
+
+ u32 tipc_ref_acquire(void *object, spinlock_t **lock);
+ void tipc_ref_discard(u32 ref);
+
+-
+-/**
+- * tipc_ref_lock - lock referenced object and return pointer to it
+- */
+-
+-static inline void *tipc_ref_lock(u32 ref)
+-{
+- if (likely(tipc_ref_table.entries)) {
+- struct reference *r =
+- &tipc_ref_table.entries[ref & tipc_ref_table.index_mask];
+-
+- spin_lock_bh(&r->lock);
+- if (likely(r->data.reference == ref))
+- return r->object;
+- spin_unlock_bh(&r->lock);
+- }
+- return NULL;
+-}
+-
+-/**
+- * tipc_ref_unlock - unlock referenced object
+- */
+-
+-static inline void tipc_ref_unlock(u32 ref)
+-{
+- if (likely(tipc_ref_table.entries)) {
+- struct reference *r =
+- &tipc_ref_table.entries[ref & tipc_ref_table.index_mask];
+-
+- if (likely(r->data.reference == ref))
+- spin_unlock_bh(&r->lock);
+- else
+- err("tipc_ref_unlock() invoked using obsolete reference\n");
+- }
+-}
+-
+-/**
+- * tipc_ref_deref - return pointer referenced object (without locking it)
+- */
+-
+-static inline void *tipc_ref_deref(u32 ref)
+-{
+- if (likely(tipc_ref_table.entries)) {
+- struct reference *r =
+- &tipc_ref_table.entries[ref & tipc_ref_table.index_mask];
+-
+- if (likely(r->data.reference == ref))
+- return r->object;
+- }
+- return NULL;
+-}
++void *tipc_ref_lock(u32 ref);
++void tipc_ref_unlock(u32 ref);
++void *tipc_ref_deref(u32 ref);
+
+ #endif
+diff --git a/net/tipc/socket.c b/net/tipc/socket.c
+index 2290903..230f9ca 100644
+--- a/net/tipc/socket.c
++++ b/net/tipc/socket.c
+@@ -43,7 +43,6 @@
+ #include <linux/slab.h>
+ #include <linux/poll.h>
+ #include <linux/fcntl.h>
+-#include <asm/semaphore.h>
+ #include <asm/string.h>
+ #include <asm/atomic.h>
+ #include <net/sock.h>
+@@ -58,16 +57,18 @@
+ #define SS_LISTENING -1 /* socket is listening */
+ #define SS_READY -2 /* socket is connectionless */
+
+-#define OVERLOAD_LIMIT_BASE 5000
++#define OVERLOAD_LIMIT_BASE 5000
++#define CONN_TIMEOUT_DEFAULT 8000 /* default connect timeout = 8s */
+
+ struct tipc_sock {
+ struct sock sk;
+ struct tipc_port *p;
+- struct semaphore sem;
+ };
+
+-#define tipc_sk(sk) ((struct tipc_sock*)sk)
++#define tipc_sk(sk) ((struct tipc_sock *)(sk))
++#define tipc_sk_port(sk) ((struct tipc_port *)(tipc_sk(sk)->p))
+
++static int backlog_rcv(struct sock *sk, struct sk_buff *skb);
+ static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf);
+ static void wakeupdispatch(struct tipc_port *tport);
+
+@@ -81,93 +82,115 @@ static int sockets_enabled = 0;
+
+ static atomic_t tipc_queue_size = ATOMIC_INIT(0);
+
+-
+ /*
+- * sock_lock(): Lock a port/socket pair. lock_sock() can
+- * not be used here, since the same lock must protect ports
+- * with non-socket interfaces.
+- * See net.c for description of locking policy.
++ * Revised TIPC socket locking policy:
++ *
++ * Most socket operations take the standard socket lock when they start
++ * and hold it until they finish (or until they need to sleep). Acquiring
++ * this lock grants the owner exclusive access to the fields of the socket
++ * data structures, with the exception of the backlog queue. A few socket
++ * operations can be done without taking the socket lock because they only
++ * read socket information that never changes during the life of the socket.
++ *
++ * Socket operations may acquire the lock for the associated TIPC port if they
++ * need to perform an operation on the port. If any routine needs to acquire
++ * both the socket lock and the port lock it must take the socket lock first
++ * to avoid the risk of deadlock.
++ *
++ * The dispatcher handling incoming messages cannot grab the socket lock in
++ * the standard fashion, since invoked it runs at the BH level and cannot block.
++ * Instead, it checks to see if the socket lock is currently owned by someone,
++ * and either handles the message itself or adds it to the socket's backlog
++ * queue; in the latter case the queued message is processed once the process
++ * owning the socket lock releases it.
++ *
++ * NOTE: Releasing the socket lock while an operation is sleeping overcomes
++ * the problem of a blocked socket operation preventing any other operations
++ * from occurring. However, applications must be careful if they have
++ * multiple threads trying to send (or receive) on the same socket, as these
++ * operations might interfere with each other. For example, doing a connect
++ * and a receive at the same time might allow the receive to consume the
++ * ACK message meant for the connect. While additional work could be done
++ * to try and overcome this, it doesn't seem to be worthwhile at the present.
++ *
++ * NOTE: Releasing the socket lock while an operation is sleeping also ensures
++ * that another operation that must be performed in a non-blocking manner is
++ * not delayed for very long because the lock has already been taken.
++ *
++ * NOTE: This code assumes that certain fields of a port/socket pair are
++ * constant over its lifetime; such fields can be examined without taking
++ * the socket lock and/or port lock, and do not need to be re-read even
++ * after resuming processing after waiting. These fields include:
++ * - socket type
++ * - pointer to socket sk structure (aka tipc_sock structure)
++ * - pointer to port structure
++ * - port reference
+ */
+-static void sock_lock(struct tipc_sock* tsock)
+-{
+- spin_lock_bh(tsock->p->lock);
+-}
+
+-/*
+- * sock_unlock(): Unlock a port/socket pair
++/**
++ * advance_rx_queue - discard first buffer in socket receive queue
++ *
++ * Caller must hold socket lock
+ */
+-static void sock_unlock(struct tipc_sock* tsock)
++
++static void advance_rx_queue(struct sock *sk)
+ {
+- spin_unlock_bh(tsock->p->lock);
++ buf_discard(__skb_dequeue(&sk->sk_receive_queue));
++ atomic_dec(&tipc_queue_size);
+ }
+
+ /**
+- * pollmask - determine the current set of poll() events for a socket
+- * @sock: socket structure
+- *
+- * TIPC sets the returned events as follows:
+- * a) POLLRDNORM and POLLIN are set if the socket's receive queue is non-empty
+- * or if a connection-oriented socket is does not have an active connection
+- * (i.e. a read operation will not block).
+- * b) POLLOUT is set except when a socket's connection has been terminated
+- * (i.e. a write operation will not block).
+- * c) POLLHUP is set when a socket's connection has been terminated.
+- *
+- * IMPORTANT: The fact that a read or write operation will not block does NOT
+- * imply that the operation will succeed!
++ * discard_rx_queue - discard all buffers in socket receive queue
+ *
+- * Returns pollmask value
++ * Caller must hold socket lock
+ */
+
+-static u32 pollmask(struct socket *sock)
++static void discard_rx_queue(struct sock *sk)
+ {
+- u32 mask;
+-
+- if ((skb_queue_len(&sock->sk->sk_receive_queue) != 0) ||
+- (sock->state == SS_UNCONNECTED) ||
+- (sock->state == SS_DISCONNECTING))
+- mask = (POLLRDNORM | POLLIN);
+- else
+- mask = 0;
+-
+- if (sock->state == SS_DISCONNECTING)
+- mask |= POLLHUP;
+- else
+- mask |= POLLOUT;
++ struct sk_buff *buf;
+
+- return mask;
++ while ((buf = __skb_dequeue(&sk->sk_receive_queue))) {
++ atomic_dec(&tipc_queue_size);
++ buf_discard(buf);
++ }
+ }
+
+-
+ /**
+- * advance_queue - discard first buffer in queue
+- * @tsock: TIPC socket
++ * reject_rx_queue - reject all buffers in socket receive queue
++ *
++ * Caller must hold socket lock
+ */
+
+-static void advance_queue(struct tipc_sock *tsock)
++static void reject_rx_queue(struct sock *sk)
+ {
+- sock_lock(tsock);
+- buf_discard(skb_dequeue(&tsock->sk.sk_receive_queue));
+- sock_unlock(tsock);
+- atomic_dec(&tipc_queue_size);
++ struct sk_buff *buf;
++
++ while ((buf = __skb_dequeue(&sk->sk_receive_queue))) {
++ tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
++ atomic_dec(&tipc_queue_size);
++ }
+ }
+
+ /**
+ * tipc_create - create a TIPC socket
++ * @net: network namespace (must be default network)
+ * @sock: pre-allocated socket structure
+ * @protocol: protocol indicator (must be 0)
+ *
+- * This routine creates and attaches a 'struct sock' to the 'struct socket',
+- * then create and attaches a TIPC port to the 'struct sock' part.
++ * This routine creates additional data structures used by the TIPC socket,
++ * initializes them, and links them together.
+ *
+ * Returns 0 on success, errno otherwise
+ */
++
+ static int tipc_create(struct net *net, struct socket *sock, int protocol)
+ {
+- struct tipc_sock *tsock;
+- struct tipc_port *port;
++ const struct proto_ops *ops;
++ socket_state state;
+ struct sock *sk;
+- u32 ref;
++ u32 portref;
++
++ /* Validate arguments */
+
+ if (net != &init_net)
+ return -EAFNOSUPPORT;
+@@ -175,54 +198,56 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol)
+ if (unlikely(protocol != 0))
+ return -EPROTONOSUPPORT;
+
+- ref = tipc_createport_raw(NULL, &dispatch, &wakeupdispatch, TIPC_LOW_IMPORTANCE);
+- if (unlikely(!ref))
+- return -ENOMEM;
+-
+- sock->state = SS_UNCONNECTED;
+-
+ switch (sock->type) {
+ case SOCK_STREAM:
+- sock->ops = &stream_ops;
++ ops = &stream_ops;
++ state = SS_UNCONNECTED;
+ break;
+ case SOCK_SEQPACKET:
+- sock->ops = &packet_ops;
++ ops = &packet_ops;
++ state = SS_UNCONNECTED;
+ break;
+ case SOCK_DGRAM:
+- tipc_set_portunreliable(ref, 1);
+- /* fall through */
+ case SOCK_RDM:
+- tipc_set_portunreturnable(ref, 1);
+- sock->ops = &msg_ops;
+- sock->state = SS_READY;
++ ops = &msg_ops;
++ state = SS_READY;
+ break;
+ default:
+- tipc_deleteport(ref);
+ return -EPROTOTYPE;
+ }
+
++ /* Allocate socket's protocol area */
++
+ sk = sk_alloc(net, AF_TIPC, GFP_KERNEL, &tipc_proto);
+- if (!sk) {
+- tipc_deleteport(ref);
++ if (sk == NULL)
+ return -ENOMEM;
+- }
+
+- sock_init_data(sock, sk);
+- init_waitqueue_head(sk->sk_sleep);
+- sk->sk_rcvtimeo = 8 * HZ; /* default connect timeout = 8s */
++ /* Allocate TIPC port for socket to use */
+
+- tsock = tipc_sk(sk);
+- port = tipc_get_port(ref);
++ portref = tipc_createport_raw(sk, &dispatch, &wakeupdispatch,
++ TIPC_LOW_IMPORTANCE);
++ if (unlikely(portref == 0)) {
++ sk_free(sk);
++ return -ENOMEM;
++ }
+
+- tsock->p = port;
+- port->usr_handle = tsock;
++ /* Finish initializing socket data structures */
+
+- init_MUTEX(&tsock->sem);
++ sock->ops = ops;
++ sock->state = state;
+
+- dbg("sock_create: %x\n",tsock);
++ sock_init_data(sock, sk);
++ sk->sk_rcvtimeo = msecs_to_jiffies(CONN_TIMEOUT_DEFAULT);
++ sk->sk_backlog_rcv = backlog_rcv;
++ tipc_sk(sk)->p = tipc_get_port(portref);
+
+- atomic_inc(&tipc_user_count);
++ if (sock->state == SS_READY) {
++ tipc_set_portunreturnable(portref, 1);
++ if (sock->type == SOCK_DGRAM)
++ tipc_set_portunreliable(portref, 1);
++ }
+
++ atomic_inc(&tipc_user_count);
+ return 0;
+ }
+
+@@ -245,52 +270,62 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol)
+
+ static int release(struct socket *sock)
+ {
+- struct tipc_sock *tsock = tipc_sk(sock->sk);
+ struct sock *sk = sock->sk;
+- int res = TIPC_OK;
++ struct tipc_port *tport;
+ struct sk_buff *buf;
++ int res;
+
+- dbg("sock_delete: %x\n",tsock);
+- if (!tsock)
+- return 0;
+- down(&tsock->sem);
+- if (!sock->sk) {
+- up(&tsock->sem);
++ /*
++ * Exit if socket isn't fully initialized (occurs when a failed accept()
++ * releases a pre-allocated child socket that was never used)
++ */
++
++ if (sk == NULL)
+ return 0;
+- }
+
+- /* Reject unreceived messages, unless no longer connected */
++ tport = tipc_sk_port(sk);
++ lock_sock(sk);
++
++ /*
++ * Reject all unreceived messages, except on an active connection
++ * (which disconnects locally & sends a 'FIN+' to peer)
++ */
+
+ while (sock->state != SS_DISCONNECTING) {
+- sock_lock(tsock);
+- buf = skb_dequeue(&sk->sk_receive_queue);
+- if (!buf)
+- tsock->p->usr_handle = NULL;
+- sock_unlock(tsock);
+- if (!buf)
++ buf = __skb_dequeue(&sk->sk_receive_queue);
++ if (buf == NULL)
+ break;
++ atomic_dec(&tipc_queue_size);
+ if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf)))
+ buf_discard(buf);
+- else
++ else {
++ if ((sock->state == SS_CONNECTING) ||
++ (sock->state == SS_CONNECTED)) {
++ sock->state = SS_DISCONNECTING;
++ tipc_disconnect(tport->ref);
++ }
+ tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
+- atomic_dec(&tipc_queue_size);
++ }
+ }
+
+- /* Delete TIPC port */
++ /*
++ * Delete TIPC port; this ensures no more messages are queued
++ * (also disconnects an active connection & sends a 'FIN-' to peer)
++ */
+
+- res = tipc_deleteport(tsock->p->ref);
+- sock->sk = NULL;
++ res = tipc_deleteport(tport->ref);
+
+- /* Discard any remaining messages */
++ /* Discard any remaining (connection-based) messages in receive queue */
+
+- while ((buf = skb_dequeue(&sk->sk_receive_queue))) {
+- buf_discard(buf);
+- atomic_dec(&tipc_queue_size);
+- }
++ discard_rx_queue(sk);
++
++ /* Reject any messages that accumulated in backlog queue */
+
+- up(&tsock->sem);
++ sock->state = SS_DISCONNECTING;
++ release_sock(sk);
+
+ sock_put(sk);
++ sock->sk = NULL;
+
+ atomic_dec(&tipc_user_count);
+ return res;
+@@ -307,47 +342,32 @@ static int release(struct socket *sock)
+ * (i.e. a socket address length of 0) unbinds all names from the socket.
+ *
+ * Returns 0 on success, errno otherwise
++ *
++ * NOTE: This routine doesn't need to take the socket lock since it doesn't
++ * access any non-constant socket information.
+ */
+
+ static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len)
+ {
+- struct tipc_sock *tsock = tipc_sk(sock->sk);
+ struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
+- int res;
++ u32 portref = tipc_sk_port(sock->sk)->ref;
+
+- if (down_interruptible(&tsock->sem))
+- return -ERESTARTSYS;
++ if (unlikely(!uaddr_len))
++ return tipc_withdraw(portref, 0, NULL);
+
+- if (unlikely(!uaddr_len)) {
+- res = tipc_withdraw(tsock->p->ref, 0, NULL);
+- goto exit;
+- }
+-
+- if (uaddr_len < sizeof(struct sockaddr_tipc)) {
+- res = -EINVAL;
+- goto exit;
+- }
++ if (uaddr_len < sizeof(struct sockaddr_tipc))
++ return -EINVAL;
++ if (addr->family != AF_TIPC)
++ return -EAFNOSUPPORT;
+
+- if (addr->family != AF_TIPC) {
+- res = -EAFNOSUPPORT;
+- goto exit;
+- }
+ if (addr->addrtype == TIPC_ADDR_NAME)
+ addr->addr.nameseq.upper = addr->addr.nameseq.lower;
+- else if (addr->addrtype != TIPC_ADDR_NAMESEQ) {
+- res = -EAFNOSUPPORT;
+- goto exit;
+- }
++ else if (addr->addrtype != TIPC_ADDR_NAMESEQ)
++ return -EAFNOSUPPORT;
+
+- if (addr->scope > 0)
+- res = tipc_publish(tsock->p->ref, addr->scope,
+- &addr->addr.nameseq);
+- else
+- res = tipc_withdraw(tsock->p->ref, -addr->scope,
+- &addr->addr.nameseq);
+-exit:
+- up(&tsock->sem);
+- return res;
++ return (addr->scope > 0) ?
++ tipc_publish(portref, addr->scope, &addr->addr.nameseq) :
++ tipc_withdraw(portref, -addr->scope, &addr->addr.nameseq);
+ }
+
+ /**
+@@ -358,30 +378,33 @@ exit:
+ * @peer: 0 to obtain socket name, 1 to obtain peer socket name
+ *
+ * Returns 0 on success, errno otherwise
++ *
++ * NOTE: This routine doesn't need to take the socket lock since it doesn't
++ * access any non-constant socket information.
+ */
+
+ static int get_name(struct socket *sock, struct sockaddr *uaddr,
+ int *uaddr_len, int peer)
+ {
+- struct tipc_sock *tsock = tipc_sk(sock->sk);
+ struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
++ u32 portref = tipc_sk_port(sock->sk)->ref;
+ u32 res;
+
+- if (down_interruptible(&tsock->sem))
+- return -ERESTARTSYS;
++ if (peer) {
++ res = tipc_peer(portref, &addr->addr.id);
++ if (res)
++ return res;
++ } else {
++ tipc_ownidentity(portref, &addr->addr.id);
++ }
+
+ *uaddr_len = sizeof(*addr);
+ addr->addrtype = TIPC_ADDR_ID;
+ addr->family = AF_TIPC;
+ addr->scope = 0;
+- if (peer)
+- res = tipc_peer(tsock->p->ref, &addr->addr.id);
+- else
+- res = tipc_ownidentity(tsock->p->ref, &addr->addr.id);
+ addr->addr.name.domain = 0;
+
+- up(&tsock->sem);
+- return res;
++ return 0;
+ }
+
+ /**
+@@ -390,15 +413,47 @@ static int get_name(struct socket *sock, struct sockaddr *uaddr,
+ * @sock: socket for which to calculate the poll bits
+ * @wait: ???
+ *
+- * Returns the pollmask
++ * Returns pollmask value
++ *
++ * COMMENTARY:
++ * It appears that the usual socket locking mechanisms are not useful here
++ * since the pollmask info is potentially out-of-date the moment this routine
++ * exits. TCP and other protocols seem to rely on higher level poll routines
++ * to handle any preventable race conditions, so TIPC will do the same ...
++ *
++ * TIPC sets the returned events as follows:
++ * a) POLLRDNORM and POLLIN are set if the socket's receive queue is non-empty
++ * or if a connection-oriented socket is does not have an active connection
++ * (i.e. a read operation will not block).
++ * b) POLLOUT is set except when a socket's connection has been terminated
++ * (i.e. a write operation will not block).
++ * c) POLLHUP is set when a socket's connection has been terminated.
++ *
++ * IMPORTANT: The fact that a read or write operation will not block does NOT
++ * imply that the operation will succeed!
+ */
+
+ static unsigned int poll(struct file *file, struct socket *sock,
+ poll_table *wait)
+ {
+- poll_wait(file, sock->sk->sk_sleep, wait);
+- /* NEED LOCK HERE? */
+- return pollmask(sock);
++ struct sock *sk = sock->sk;
++ u32 mask;
++
++ poll_wait(file, sk->sk_sleep, wait);
++
++ if (!skb_queue_empty(&sk->sk_receive_queue) ||
++ (sock->state == SS_UNCONNECTED) ||
++ (sock->state == SS_DISCONNECTING))
++ mask = (POLLRDNORM | POLLIN);
++ else
++ mask = 0;
++
++ if (sock->state == SS_DISCONNECTING)
++ mask |= POLLHUP;
++ else
++ mask |= POLLOUT;
++
++ return mask;
+ }
+
+ /**
+@@ -420,7 +475,6 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m)
+ return 0;
+ if (likely(dest->addr.name.name.type == TIPC_TOP_SRV))
+ return 0;
+-
+ if (likely(dest->addr.name.name.type != TIPC_CFG_SRV))
+ return -EACCES;
+
+@@ -434,7 +488,7 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m)
+
+ /**
+ * send_msg - send message in connectionless manner
+- * @iocb: (unused)
++ * @iocb: if NULL, indicates that socket lock is already held
+ * @sock: socket structure
+ * @m: message to send
+ * @total_len: length of message
+@@ -450,9 +504,9 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m)
+ static int send_msg(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *m, size_t total_len)
+ {
+- struct tipc_sock *tsock = tipc_sk(sock->sk);
++ struct sock *sk = sock->sk;
++ struct tipc_port *tport = tipc_sk_port(sk);
+ struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name;
+- struct sk_buff *buf;
+ int needs_conn;
+ int res = -EINVAL;
+
+@@ -462,48 +516,46 @@ static int send_msg(struct kiocb *iocb, struct socket *sock,
+ (dest->family != AF_TIPC)))
+ return -EINVAL;
+
++ if (iocb)
++ lock_sock(sk);
++
+ needs_conn = (sock->state != SS_READY);
+ if (unlikely(needs_conn)) {
+- if (sock->state == SS_LISTENING)
+- return -EPIPE;
+- if (sock->state != SS_UNCONNECTED)
+- return -EISCONN;
+- if ((tsock->p->published) ||
+- ((sock->type == SOCK_STREAM) && (total_len != 0)))
+- return -EOPNOTSUPP;
++ if (sock->state == SS_LISTENING) {
++ res = -EPIPE;
++ goto exit;
++ }
++ if (sock->state != SS_UNCONNECTED) {
++ res = -EISCONN;
++ goto exit;
++ }
++ if ((tport->published) ||
++ ((sock->type == SOCK_STREAM) && (total_len != 0))) {
++ res = -EOPNOTSUPP;
++ goto exit;
++ }
+ if (dest->addrtype == TIPC_ADDR_NAME) {
+- tsock->p->conn_type = dest->addr.name.name.type;
+- tsock->p->conn_instance = dest->addr.name.name.instance;
++ tport->conn_type = dest->addr.name.name.type;
++ tport->conn_instance = dest->addr.name.name.instance;
+ }
+- }
+-
+- if (down_interruptible(&tsock->sem))
+- return -ERESTARTSYS;
+-
+- if (needs_conn) {
+
+ /* Abort any pending connection attempts (very unlikely) */
+
+- while ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) {
+- tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
+- atomic_dec(&tipc_queue_size);
+- }
+-
+- sock->state = SS_CONNECTING;
++ reject_rx_queue(sk);
+ }
+
+ do {
+ if (dest->addrtype == TIPC_ADDR_NAME) {
+ if ((res = dest_name_check(dest, m)))
+- goto exit;
+- res = tipc_send2name(tsock->p->ref,
++ break;
++ res = tipc_send2name(tport->ref,
+ &dest->addr.name.name,
+ dest->addr.name.domain,
+ m->msg_iovlen,
+ m->msg_iov);
+ }
+ else if (dest->addrtype == TIPC_ADDR_ID) {
+- res = tipc_send2port(tsock->p->ref,
++ res = tipc_send2port(tport->ref,
+ &dest->addr.id,
+ m->msg_iovlen,
+ m->msg_iov);
+@@ -511,36 +563,43 @@ static int send_msg(struct kiocb *iocb, struct socket *sock,
+ else if (dest->addrtype == TIPC_ADDR_MCAST) {
+ if (needs_conn) {
+ res = -EOPNOTSUPP;
+- goto exit;
++ break;
+ }
+ if ((res = dest_name_check(dest, m)))
+- goto exit;
+- res = tipc_multicast(tsock->p->ref,
++ break;
++ res = tipc_multicast(tport->ref,
+ &dest->addr.nameseq,
+ 0,
+ m->msg_iovlen,
+ m->msg_iov);
+ }
+ if (likely(res != -ELINKCONG)) {
+-exit:
+- up(&tsock->sem);
+- return res;
++ if (needs_conn && (res >= 0)) {
++ sock->state = SS_CONNECTING;
++ }
++ break;
+ }
+ if (m->msg_flags & MSG_DONTWAIT) {
+ res = -EWOULDBLOCK;
+- goto exit;
+- }
+- if (wait_event_interruptible(*sock->sk->sk_sleep,
+- !tsock->p->congested)) {
+- res = -ERESTARTSYS;
+- goto exit;
++ break;
+ }
++ release_sock(sk);
++ res = wait_event_interruptible(*sk->sk_sleep,
++ !tport->congested);
++ lock_sock(sk);
++ if (res)
++ break;
+ } while (1);
++
++exit:
++ if (iocb)
++ release_sock(sk);
++ return res;
+ }
+
+ /**
+ * send_packet - send a connection-oriented message
+- * @iocb: (unused)
++ * @iocb: if NULL, indicates that socket lock is already held
+ * @sock: socket structure
+ * @m: message to send
+ * @total_len: length of message
+@@ -553,7 +612,8 @@ exit:
+ static int send_packet(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *m, size_t total_len)
+ {
+- struct tipc_sock *tsock = tipc_sk(sock->sk);
++ struct sock *sk = sock->sk;
++ struct tipc_port *tport = tipc_sk_port(sk);
+ struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name;
+ int res;
+
+@@ -562,9 +622,8 @@ static int send_packet(struct kiocb *iocb, struct socket *sock,
+ if (unlikely(dest))
+ return send_msg(iocb, sock, m, total_len);
+
+- if (down_interruptible(&tsock->sem)) {
+- return -ERESTARTSYS;
+- }
++ if (iocb)
++ lock_sock(sk);
+
+ do {
+ if (unlikely(sock->state != SS_CONNECTED)) {
+@@ -572,25 +631,28 @@ static int send_packet(struct kiocb *iocb, struct socket *sock,
+ res = -EPIPE;
+ else
+ res = -ENOTCONN;
+- goto exit;
++ break;
+ }
+
+- res = tipc_send(tsock->p->ref, m->msg_iovlen, m->msg_iov);
++ res = tipc_send(tport->ref, m->msg_iovlen, m->msg_iov);
+ if (likely(res != -ELINKCONG)) {
+-exit:
+- up(&tsock->sem);
+- return res;
++ break;
+ }
+ if (m->msg_flags & MSG_DONTWAIT) {
+ res = -EWOULDBLOCK;
+- goto exit;
+- }
+- if (wait_event_interruptible(*sock->sk->sk_sleep,
+- !tsock->p->congested)) {
+- res = -ERESTARTSYS;
+- goto exit;
++ break;
+ }
++ release_sock(sk);
++ res = wait_event_interruptible(*sk->sk_sleep,
++ (!tport->congested || !tport->connected));
++ lock_sock(sk);
++ if (res)
++ break;
+ } while (1);
++
++ if (iocb)
++ release_sock(sk);
++ return res;
+ }
+
+ /**
+@@ -606,11 +668,11 @@ exit:
+ * or errno if no data sent
+ */
+
+-
+ static int send_stream(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *m, size_t total_len)
+ {
+- struct tipc_port *tport;
++ struct sock *sk = sock->sk;
++ struct tipc_port *tport = tipc_sk_port(sk);
+ struct msghdr my_msg;
+ struct iovec my_iov;
+ struct iovec *curr_iov;
+@@ -622,19 +684,27 @@ static int send_stream(struct kiocb *iocb, struct socket *sock,
+ int bytes_sent;
+ int res;
+
++ lock_sock(sk);
++
+ /* Handle special cases where there is no connection */
+
+ if (unlikely(sock->state != SS_CONNECTED)) {
+- if (sock->state == SS_UNCONNECTED)
+- return send_packet(iocb, sock, m, total_len);
+- else if (sock->state == SS_DISCONNECTING)
+- return -EPIPE;
+- else
+- return -ENOTCONN;
++ if (sock->state == SS_UNCONNECTED) {
++ res = send_packet(NULL, sock, m, total_len);
++ goto exit;
++ } else if (sock->state == SS_DISCONNECTING) {
++ res = -EPIPE;
++ goto exit;
++ } else {
++ res = -ENOTCONN;
++ goto exit;
++ }
+ }
+
+- if (unlikely(m->msg_name))
+- return -EISCONN;
++ if (unlikely(m->msg_name)) {
++ res = -EISCONN;
++ goto exit;
++ }
+
+ /*
+ * Send each iovec entry using one or more messages
+@@ -652,7 +722,6 @@ static int send_stream(struct kiocb *iocb, struct socket *sock,
+ my_msg.msg_name = NULL;
+ bytes_sent = 0;
+
+- tport = tipc_sk(sock->sk)->p;
+ hdr_size = msg_hdr_sz(&tport->phdr);
+
+ while (curr_iovlen--) {
+@@ -667,10 +736,10 @@ static int send_stream(struct kiocb *iocb, struct socket *sock,
+ bytes_to_send = curr_left;
+ my_iov.iov_base = curr_start;
+ my_iov.iov_len = bytes_to_send;
+- if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0) {
+- if (bytes_sent != 0)
++ if ((res = send_packet(NULL, sock, &my_msg, 0)) < 0) {
++ if (bytes_sent)
+ res = bytes_sent;
+- return res;
++ goto exit;
+ }
+ curr_left -= bytes_to_send;
+ curr_start += bytes_to_send;
+@@ -679,22 +748,23 @@ static int send_stream(struct kiocb *iocb, struct socket *sock,
+
+ curr_iov++;
+ }
+-
+- return bytes_sent;
++ res = bytes_sent;
++exit:
++ release_sock(sk);
++ return res;
+ }
+
+ /**
+ * auto_connect - complete connection setup to a remote port
+ * @sock: socket structure
+- * @tsock: TIPC-specific socket structure
+ * @msg: peer's response message
+ *
+ * Returns 0 on success, errno otherwise
+ */
+
+-static int auto_connect(struct socket *sock, struct tipc_sock *tsock,
+- struct tipc_msg *msg)
++static int auto_connect(struct socket *sock, struct tipc_msg *msg)
+ {
++ struct tipc_port *tport = tipc_sk_port(sock->sk);
+ struct tipc_portid peer;
+
+ if (msg_errcode(msg)) {
+@@ -704,8 +774,8 @@ static int auto_connect(struct socket *sock, struct tipc_sock *tsock,
+
+ peer.ref = msg_origport(msg);
+ peer.node = msg_orignode(msg);
+- tipc_connect2port(tsock->p->ref, &peer);
+- tipc_set_portimportance(tsock->p->ref, msg_importance(msg));
++ tipc_connect2port(tport->ref, &peer);
++ tipc_set_portimportance(tport->ref, msg_importance(msg));
+ sock->state = SS_CONNECTED;
+ return 0;
+ }
+@@ -818,62 +888,54 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg,
+ static int recv_msg(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *m, size_t buf_len, int flags)
+ {
+- struct tipc_sock *tsock = tipc_sk(sock->sk);
++ struct sock *sk = sock->sk;
++ struct tipc_port *tport = tipc_sk_port(sk);
+ struct sk_buff *buf;
+ struct tipc_msg *msg;
+- unsigned int q_len;
+ unsigned int sz;
+ u32 err;
+ int res;
+
+- /* Currently doesn't support receiving into multiple iovec entries */
++ /* Catch invalid receive requests */
+
+ if (m->msg_iovlen != 1)
+- return -EOPNOTSUPP;
+-
+- /* Catch invalid receive attempts */
++ return -EOPNOTSUPP; /* Don't do multiple iovec entries yet */
+
+ if (unlikely(!buf_len))
+ return -EINVAL;
+
+- if (sock->type == SOCK_SEQPACKET) {
+- if (unlikely(sock->state == SS_UNCONNECTED))
+- return -ENOTCONN;
+- if (unlikely((sock->state == SS_DISCONNECTING) &&
+- (skb_queue_len(&sock->sk->sk_receive_queue) == 0)))
+- return -ENOTCONN;
+- }
++ lock_sock(sk);
+
+- /* Look for a message in receive queue; wait if necessary */
+-
+- if (unlikely(down_interruptible(&tsock->sem)))
+- return -ERESTARTSYS;
+-
+-restart:
+- if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) &&
+- (flags & MSG_DONTWAIT))) {
+- res = -EWOULDBLOCK;
++ if (unlikely(sock->state == SS_UNCONNECTED)) {
++ res = -ENOTCONN;
+ goto exit;
+ }
+
+- if ((res = wait_event_interruptible(
+- *sock->sk->sk_sleep,
+- ((q_len = skb_queue_len(&sock->sk->sk_receive_queue)) ||
+- (sock->state == SS_DISCONNECTING))) )) {
+- goto exit;
+- }
++restart:
+
+- /* Catch attempt to receive on an already terminated connection */
+- /* [THIS CHECK MAY OVERLAP WITH AN EARLIER CHECK] */
++ /* Look for a message in receive queue; wait if necessary */
+
+- if (!q_len) {
+- res = -ENOTCONN;
+- goto exit;
++ while (skb_queue_empty(&sk->sk_receive_queue)) {
++ if (sock->state == SS_DISCONNECTING) {
++ res = -ENOTCONN;
++ goto exit;
++ }
++ if (flags & MSG_DONTWAIT) {
++ res = -EWOULDBLOCK;
++ goto exit;
++ }
++ release_sock(sk);
++ res = wait_event_interruptible(*sk->sk_sleep,
++ (!skb_queue_empty(&sk->sk_receive_queue) ||
++ (sock->state == SS_DISCONNECTING)));
++ lock_sock(sk);
++ if (res)
++ goto exit;
+ }
+
+- /* Get access to first message in receive queue */
++ /* Look at first message in receive queue */
+
+- buf = skb_peek(&sock->sk->sk_receive_queue);
++ buf = skb_peek(&sk->sk_receive_queue);
+ msg = buf_msg(buf);
+ sz = msg_data_sz(msg);
+ err = msg_errcode(msg);
+@@ -881,14 +943,15 @@ restart:
+ /* Complete connection setup for an implied connect */
+
+ if (unlikely(sock->state == SS_CONNECTING)) {
+- if ((res = auto_connect(sock, tsock, msg)))
++ res = auto_connect(sock, msg);
++ if (res)
+ goto exit;
+ }
+
+ /* Discard an empty non-errored message & try again */
+
+ if ((!sz) && (!err)) {
+- advance_queue(tsock);
++ advance_rx_queue(sk);
+ goto restart;
+ }
+
+@@ -898,7 +961,8 @@ restart:
+
+ /* Capture ancillary data (optional) */
+
+- if ((res = anc_data_recv(m, msg, tsock->p)))
++ res = anc_data_recv(m, msg, tport);
++ if (res)
+ goto exit;
+
+ /* Capture message data (if valid) & compute return value (always) */
+@@ -925,12 +989,13 @@ restart:
+ /* Consume received message (optional) */
+
+ if (likely(!(flags & MSG_PEEK))) {
+- if (unlikely(++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
+- tipc_acknowledge(tsock->p->ref, tsock->p->conn_unacked);
+- advance_queue(tsock);
++ if ((sock->state != SS_READY) &&
++ (++tport->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
++ tipc_acknowledge(tport->ref, tport->conn_unacked);
++ advance_rx_queue(sk);
+ }
+ exit:
+- up(&tsock->sem);
++ release_sock(sk);
+ return res;
+ }
+
+@@ -950,10 +1015,10 @@ exit:
+ static int recv_stream(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *m, size_t buf_len, int flags)
+ {
+- struct tipc_sock *tsock = tipc_sk(sock->sk);
++ struct sock *sk = sock->sk;
++ struct tipc_port *tport = tipc_sk_port(sk);
+ struct sk_buff *buf;
+ struct tipc_msg *msg;
+- unsigned int q_len;
+ unsigned int sz;
+ int sz_to_copy;
+ int sz_copied = 0;
+@@ -961,54 +1026,49 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock,
+ char __user *crs = m->msg_iov->iov_base;
+ unsigned char *buf_crs;
+ u32 err;
+- int res;
++ int res = 0;
+
+- /* Currently doesn't support receiving into multiple iovec entries */
++ /* Catch invalid receive attempts */
+
+ if (m->msg_iovlen != 1)
+- return -EOPNOTSUPP;
+-
+- /* Catch invalid receive attempts */
++ return -EOPNOTSUPP; /* Don't do multiple iovec entries yet */
+
+ if (unlikely(!buf_len))
+ return -EINVAL;
+
+- if (unlikely(sock->state == SS_DISCONNECTING)) {
+- if (skb_queue_len(&sock->sk->sk_receive_queue) == 0)
+- return -ENOTCONN;
+- } else if (unlikely(sock->state != SS_CONNECTED))
+- return -ENOTCONN;
++ lock_sock(sk);
+
+- /* Look for a message in receive queue; wait if necessary */
+-
+- if (unlikely(down_interruptible(&tsock->sem)))
+- return -ERESTARTSYS;
+-
+-restart:
+- if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) &&
+- (flags & MSG_DONTWAIT))) {
+- res = -EWOULDBLOCK;
++ if (unlikely((sock->state == SS_UNCONNECTED) ||
++ (sock->state == SS_CONNECTING))) {
++ res = -ENOTCONN;
+ goto exit;
+ }
+
+- if ((res = wait_event_interruptible(
+- *sock->sk->sk_sleep,
+- ((q_len = skb_queue_len(&sock->sk->sk_receive_queue)) ||
+- (sock->state == SS_DISCONNECTING))) )) {
+- goto exit;
+- }
++restart:
+
+- /* Catch attempt to receive on an already terminated connection */
+- /* [THIS CHECK MAY OVERLAP WITH AN EARLIER CHECK] */
++ /* Look for a message in receive queue; wait if necessary */
+
+- if (!q_len) {
+- res = -ENOTCONN;
+- goto exit;
++ while (skb_queue_empty(&sk->sk_receive_queue)) {
++ if (sock->state == SS_DISCONNECTING) {
++ res = -ENOTCONN;
++ goto exit;
++ }
++ if (flags & MSG_DONTWAIT) {
++ res = -EWOULDBLOCK;
++ goto exit;
++ }
++ release_sock(sk);
++ res = wait_event_interruptible(*sk->sk_sleep,
++ (!skb_queue_empty(&sk->sk_receive_queue) ||
++ (sock->state == SS_DISCONNECTING)));
++ lock_sock(sk);
++ if (res)
++ goto exit;
+ }
+
+- /* Get access to first message in receive queue */
++ /* Look at first message in receive queue */
+
+- buf = skb_peek(&sock->sk->sk_receive_queue);
++ buf = skb_peek(&sk->sk_receive_queue);
+ msg = buf_msg(buf);
+ sz = msg_data_sz(msg);
+ err = msg_errcode(msg);
+@@ -1016,7 +1076,7 @@ restart:
+ /* Discard an empty non-errored message & try again */
+
+ if ((!sz) && (!err)) {
+- advance_queue(tsock);
++ advance_rx_queue(sk);
+ goto restart;
+ }
+
+@@ -1024,7 +1084,8 @@ restart:
+
+ if (sz_copied == 0) {
+ set_orig_addr(m, msg);
+- if ((res = anc_data_recv(m, msg, tsock->p)))
++ res = anc_data_recv(m, msg, tport);
++ if (res)
+ goto exit;
+ }
+
+@@ -1032,7 +1093,7 @@ restart:
+
+ if (!err) {
+ buf_crs = (unsigned char *)(TIPC_SKB_CB(buf)->handle);
+- sz = skb_tail_pointer(buf) - buf_crs;
++ sz = (unsigned char *)msg + msg_size(msg) - buf_crs;
+
+ needed = (buf_len - sz_copied);
+ sz_to_copy = (sz <= needed) ? sz : needed;
+@@ -1062,35 +1123,37 @@ restart:
+ /* Consume received message (optional) */
+
+ if (likely(!(flags & MSG_PEEK))) {
+- if (unlikely(++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
+- tipc_acknowledge(tsock->p->ref, tsock->p->conn_unacked);
+- advance_queue(tsock);
++ if (unlikely(++tport->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
++ tipc_acknowledge(tport->ref, tport->conn_unacked);
++ advance_rx_queue(sk);
+ }
+
+ /* Loop around if more data is required */
+
+ if ((sz_copied < buf_len) /* didn't get all requested data */
+- && (flags & MSG_WAITALL) /* ... and need to wait for more */
++ && (!skb_queue_empty(&sock->sk->sk_receive_queue) ||
++ (flags & MSG_WAITALL))
++ /* ... and more is ready or required */
+ && (!(flags & MSG_PEEK)) /* ... and aren't just peeking at data */
+ && (!err) /* ... and haven't reached a FIN */
+ )
+ goto restart;
+
+ exit:
+- up(&tsock->sem);
++ release_sock(sk);
+ return sz_copied ? sz_copied : res;
+ }
+
+ /**
+- * queue_overloaded - test if queue overload condition exists
++ * rx_queue_full - determine if receive queue can accept another message
++ * @msg: message to be added to queue
+ * @queue_size: current size of queue
+ * @base: nominal maximum size of queue
+- * @msg: message to be added to queue
+ *
+- * Returns 1 if queue is currently overloaded, 0 otherwise
++ * Returns 1 if queue is unable to accept message, 0 otherwise
+ */
+
+-static int queue_overloaded(u32 queue_size, u32 base, struct tipc_msg *msg)
++static int rx_queue_full(struct tipc_msg *msg, u32 queue_size, u32 base)
+ {
+ u32 threshold;
+ u32 imp = msg_importance(msg);
+@@ -1107,41 +1170,28 @@ static int queue_overloaded(u32 queue_size, u32 base, struct tipc_msg *msg)
+ if (msg_connected(msg))
+ threshold *= 4;
+
+- return (queue_size > threshold);
+-}
+-
+-/**
+- * async_disconnect - wrapper function used to disconnect port
+- * @portref: TIPC port reference (passed as pointer-sized value)
+- */
+-
+-static void async_disconnect(unsigned long portref)
+-{
+- tipc_disconnect((u32)portref);
++ return (queue_size >= threshold);
+ }
+
+ /**
+- * dispatch - handle arriving message
+- * @tport: TIPC port that received message
++ * filter_rcv - validate incoming message
++ * @sk: socket
+ * @buf: message
+ *
+- * Called with port locked. Must not take socket lock to avoid deadlock risk.
++ * Enqueues message on receive queue if acceptable; optionally handles
++ * disconnect indication for a connected socket.
++ *
++ * Called with socket lock already taken; port lock may also be taken.
+ *
+ * Returns TIPC error status code (TIPC_OK if message is not to be rejected)
+ */
+
+-static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf)
++static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
+ {
++ struct socket *sock = sk->sk_socket;
+ struct tipc_msg *msg = buf_msg(buf);
+- struct tipc_sock *tsock = (struct tipc_sock *)tport->usr_handle;
+- struct socket *sock;
+ u32 recv_q_len;
+
+- /* Reject message if socket is closing */
+-
+- if (!tsock)
+- return TIPC_ERR_NO_PORT;
+-
+ /* Reject message if it is wrong sort of message for socket */
+
+ /*
+@@ -1149,7 +1199,7 @@ static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf)
+ * "NO PORT" ISN'T REALLY THE RIGHT ERROR CODE, AND THERE MAY
+ * BE SECURITY IMPLICATIONS INHERENT IN REJECTING INVALID TRAFFIC
+ */
+- sock = tsock->sk.sk_socket;
++
+ if (sock->state == SS_READY) {
+ if (msg_connected(msg)) {
+ msg_dbg(msg, "dispatch filter 1\n");
+@@ -1192,52 +1242,103 @@ static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf)
+
+ /* Reject message if there isn't room to queue it */
+
+- if (unlikely((u32)atomic_read(&tipc_queue_size) >
+- OVERLOAD_LIMIT_BASE)) {
+- if (queue_overloaded(atomic_read(&tipc_queue_size),
+- OVERLOAD_LIMIT_BASE, msg))
++ recv_q_len = (u32)atomic_read(&tipc_queue_size);
++ if (unlikely(recv_q_len >= OVERLOAD_LIMIT_BASE)) {
++ if (rx_queue_full(msg, recv_q_len, OVERLOAD_LIMIT_BASE))
+ return TIPC_ERR_OVERLOAD;
+ }
+- recv_q_len = skb_queue_len(&tsock->sk.sk_receive_queue);
+- if (unlikely(recv_q_len > (OVERLOAD_LIMIT_BASE / 2))) {
+- if (queue_overloaded(recv_q_len,
+- OVERLOAD_LIMIT_BASE / 2, msg))
++ recv_q_len = skb_queue_len(&sk->sk_receive_queue);
++ if (unlikely(recv_q_len >= (OVERLOAD_LIMIT_BASE / 2))) {
++ if (rx_queue_full(msg, recv_q_len, OVERLOAD_LIMIT_BASE / 2))
+ return TIPC_ERR_OVERLOAD;
+ }
+
++ /* Enqueue message (finally!) */
++
++ msg_dbg(msg, "<DISP<: ");
++ TIPC_SKB_CB(buf)->handle = msg_data(msg);
++ atomic_inc(&tipc_queue_size);
++ __skb_queue_tail(&sk->sk_receive_queue, buf);
++
+ /* Initiate connection termination for an incoming 'FIN' */
+
+ if (unlikely(msg_errcode(msg) && (sock->state == SS_CONNECTED))) {
+ sock->state = SS_DISCONNECTING;
+- /* Note: Use signal since port lock is already taken! */
+- tipc_k_signal((Handler)async_disconnect, tport->ref);
++ tipc_disconnect_port(tipc_sk_port(sk));
+ }
+
+- /* Enqueue message (finally!) */
++ if (waitqueue_active(sk->sk_sleep))
++ wake_up_interruptible(sk->sk_sleep);
++ return TIPC_OK;
++}
+
+- msg_dbg(msg,"<DISP<: ");
+- TIPC_SKB_CB(buf)->handle = msg_data(msg);
+- atomic_inc(&tipc_queue_size);
+- skb_queue_tail(&sock->sk->sk_receive_queue, buf);
++/**
++ * backlog_rcv - handle incoming message from backlog queue
++ * @sk: socket
++ * @buf: message
++ *
++ * Caller must hold socket lock, but not port lock.
++ *
++ * Returns 0
++ */
+
+- if (waitqueue_active(sock->sk->sk_sleep))
+- wake_up_interruptible(sock->sk->sk_sleep);
+- return TIPC_OK;
++static int backlog_rcv(struct sock *sk, struct sk_buff *buf)
++{
++ u32 res;
++
++ res = filter_rcv(sk, buf);
++ if (res)
++ tipc_reject_msg(buf, res);
++ return 0;
++}
++
++/**
++ * dispatch - handle incoming message
++ * @tport: TIPC port that received message
++ * @buf: message
++ *
++ * Called with port lock already taken.
++ *
++ * Returns TIPC error status code (TIPC_OK if message is not to be rejected)
++ */
++
++static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf)
++{
++ struct sock *sk = (struct sock *)tport->usr_handle;
++ u32 res;
++
++ /*
++ * Process message if socket is unlocked; otherwise add to backlog queue
++ *
++ * This code is based on sk_receive_skb(), but must be distinct from it
++ * since a TIPC-specific filter/reject mechanism is utilized
++ */
++
++ bh_lock_sock(sk);
++ if (!sock_owned_by_user(sk)) {
++ res = filter_rcv(sk, buf);
++ } else {
++ sk_add_backlog(sk, buf);
++ res = TIPC_OK;
++ }
++ bh_unlock_sock(sk);
++
++ return res;
+ }
+
+ /**
+ * wakeupdispatch - wake up port after congestion
+ * @tport: port to wakeup
+ *
+- * Called with port lock on.
++ * Called with port lock already taken.
+ */
+
+ static void wakeupdispatch(struct tipc_port *tport)
+ {
+- struct tipc_sock *tsock = (struct tipc_sock *)tport->usr_handle;
++ struct sock *sk = (struct sock *)tport->usr_handle;
+
+- if (waitqueue_active(tsock->sk.sk_sleep))
+- wake_up_interruptible(tsock->sk.sk_sleep);
++ if (waitqueue_active(sk->sk_sleep))
++ wake_up_interruptible(sk->sk_sleep);
+ }
+
+ /**
+@@ -1245,7 +1346,7 @@ static void wakeupdispatch(struct tipc_port *tport)
+ * @sock: socket structure
+ * @dest: socket address for destination port
+ * @destlen: size of socket address data structure
+- * @flags: (unused)
++ * @flags: file-related flags associated with socket
+ *
+ * Returns 0 on success, errno otherwise
+ */
+@@ -1253,72 +1354,105 @@ static void wakeupdispatch(struct tipc_port *tport)
+ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
+ int flags)
+ {
+- struct tipc_sock *tsock = tipc_sk(sock->sk);
+- struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest;
+- struct msghdr m = {NULL,};
+- struct sk_buff *buf;
+- struct tipc_msg *msg;
+- int res;
+-
+- /* For now, TIPC does not allow use of connect() with DGRAM or RDM types */
+-
+- if (sock->state == SS_READY)
+- return -EOPNOTSUPP;
+-
+- /* Issue Posix-compliant error code if socket is in the wrong state */
+-
+- if (sock->state == SS_LISTENING)
+- return -EOPNOTSUPP;
+- if (sock->state == SS_CONNECTING)
+- return -EALREADY;
+- if (sock->state != SS_UNCONNECTED)
+- return -EISCONN;
+-
+- /*
+- * Reject connection attempt using multicast address
+- *
+- * Note: send_msg() validates the rest of the address fields,
+- * so there's no need to do it here
+- */
+-
+- if (dst->addrtype == TIPC_ADDR_MCAST)
+- return -EINVAL;
+-
+- /* Send a 'SYN-' to destination */
+-
+- m.msg_name = dest;
+- m.msg_namelen = destlen;
+- if ((res = send_msg(NULL, sock, &m, 0)) < 0) {
+- sock->state = SS_DISCONNECTING;
+- return res;
+- }
+-
+- if (down_interruptible(&tsock->sem))
+- return -ERESTARTSYS;
+-
+- /* Wait for destination's 'ACK' response */
+-
+- res = wait_event_interruptible_timeout(*sock->sk->sk_sleep,
+- skb_queue_len(&sock->sk->sk_receive_queue),
+- sock->sk->sk_rcvtimeo);
+- buf = skb_peek(&sock->sk->sk_receive_queue);
+- if (res > 0) {
+- msg = buf_msg(buf);
+- res = auto_connect(sock, tsock, msg);
+- if (!res) {
+- if (!msg_data_sz(msg))
+- advance_queue(tsock);
+- }
+- } else {
+- if (res == 0) {
+- res = -ETIMEDOUT;
+- } else
+- { /* leave "res" unchanged */ }
+- sock->state = SS_DISCONNECTING;
+- }
+-
+- up(&tsock->sem);
+- return res;
++ struct sock *sk = sock->sk;
++ struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest;
++ struct msghdr m = {NULL,};
++ struct sk_buff *buf;
++ struct tipc_msg *msg;
++ int res;
++
++ lock_sock(sk);
++
++ /* For now, TIPC does not allow use of connect() with DGRAM/RDM types */
++
++ if (sock->state == SS_READY) {
++ res = -EOPNOTSUPP;
++ goto exit;
++ }
++
++ /* For now, TIPC does not support the non-blocking form of connect() */
++
++ if (flags & O_NONBLOCK) {
++ res = -EWOULDBLOCK;
++ goto exit;
++ }
++
++ /* Issue Posix-compliant error code if socket is in the wrong state */
++
++ if (sock->state == SS_LISTENING) {
++ res = -EOPNOTSUPP;
++ goto exit;
++ }
++ if (sock->state == SS_CONNECTING) {
++ res = -EALREADY;
++ goto exit;
++ }
++ if (sock->state != SS_UNCONNECTED) {
++ res = -EISCONN;
++ goto exit;
++ }
++
++ /*
++ * Reject connection attempt using multicast address
++ *
++ * Note: send_msg() validates the rest of the address fields,
++ * so there's no need to do it here
++ */
++
++ if (dst->addrtype == TIPC_ADDR_MCAST) {
++ res = -EINVAL;
++ goto exit;
++ }
++
++ /* Reject any messages already in receive queue (very unlikely) */
++
++ reject_rx_queue(sk);
++
++ /* Send a 'SYN-' to destination */
++
++ m.msg_name = dest;
++ m.msg_namelen = destlen;
++ res = send_msg(NULL, sock, &m, 0);
++ if (res < 0) {
++ goto exit;
++ }
++
++ /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */
++
++ release_sock(sk);
++ res = wait_event_interruptible_timeout(*sk->sk_sleep,
++ (!skb_queue_empty(&sk->sk_receive_queue) ||
++ (sock->state != SS_CONNECTING)),
++ sk->sk_rcvtimeo);
++ lock_sock(sk);
++
++ if (res > 0) {
++ buf = skb_peek(&sk->sk_receive_queue);
++ if (buf != NULL) {
++ msg = buf_msg(buf);
++ res = auto_connect(sock, msg);
++ if (!res) {
++ if (!msg_data_sz(msg))
++ advance_rx_queue(sk);
++ }
++ } else {
++ if (sock->state == SS_CONNECTED) {
++ res = -EISCONN;
++ } else {
++ res = -ECONNREFUSED;
++ }
++ }
++ } else {
++ if (res == 0)
++ res = -ETIMEDOUT;
++ else
++ ; /* leave "res" unchanged */
++ sock->state = SS_DISCONNECTING;
++ }
++
++exit:
++ release_sock(sk);
++ return res;
+ }
+
+ /**
+@@ -1331,14 +1465,22 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
+
+ static int listen(struct socket *sock, int len)
+ {
+- /* REQUIRES SOCKET LOCKING OF SOME SORT? */
++ struct sock *sk = sock->sk;
++ int res;
++
++ lock_sock(sk);
+
+ if (sock->state == SS_READY)
+- return -EOPNOTSUPP;
+- if (sock->state != SS_UNCONNECTED)
+- return -EINVAL;
+- sock->state = SS_LISTENING;
+- return 0;
++ res = -EOPNOTSUPP;
++ else if (sock->state != SS_UNCONNECTED)
++ res = -EINVAL;
++ else {
++ sock->state = SS_LISTENING;
++ res = 0;
++ }
++
++ release_sock(sk);
++ return res;
+ }
+
+ /**
+@@ -1350,50 +1492,69 @@ static int listen(struct socket *sock, int len)
+ * Returns 0 on success, errno otherwise
+ */
+
+-static int accept(struct socket *sock, struct socket *newsock, int flags)
++static int accept(struct socket *sock, struct socket *new_sock, int flags)
+ {
+- struct tipc_sock *tsock = tipc_sk(sock->sk);
++ struct sock *sk = sock->sk;
+ struct sk_buff *buf;
+- int res = -EFAULT;
+-
+- if (sock->state == SS_READY)
+- return -EOPNOTSUPP;
+- if (sock->state != SS_LISTENING)
+- return -EINVAL;
+-
+- if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) &&
+- (flags & O_NONBLOCK)))
+- return -EWOULDBLOCK;
++ int res;
+
+- if (down_interruptible(&tsock->sem))
+- return -ERESTARTSYS;
++ lock_sock(sk);
+
+- if (wait_event_interruptible(*sock->sk->sk_sleep,
+- skb_queue_len(&sock->sk->sk_receive_queue))) {
+- res = -ERESTARTSYS;
++ if (sock->state == SS_READY) {
++ res = -EOPNOTSUPP;
++ goto exit;
++ }
++ if (sock->state != SS_LISTENING) {
++ res = -EINVAL;
+ goto exit;
+ }
+- buf = skb_peek(&sock->sk->sk_receive_queue);
+
+- res = tipc_create(sock->sk->sk_net, newsock, 0);
++ while (skb_queue_empty(&sk->sk_receive_queue)) {
++ if (flags & O_NONBLOCK) {
++ res = -EWOULDBLOCK;
++ goto exit;
++ }
++ release_sock(sk);
++ res = wait_event_interruptible(*sk->sk_sleep,
++ (!skb_queue_empty(&sk->sk_receive_queue)));
++ lock_sock(sk);
++ if (res)
++ goto exit;
++ }
++
++ buf = skb_peek(&sk->sk_receive_queue);
++
++ res = tipc_create(sock_net(sock->sk), new_sock, 0);
+ if (!res) {
+- struct tipc_sock *new_tsock = tipc_sk(newsock->sk);
++ struct sock *new_sk = new_sock->sk;
++ struct tipc_port *new_tport = tipc_sk_port(new_sk);
++ u32 new_ref = new_tport->ref;
+ struct tipc_portid id;
+ struct tipc_msg *msg = buf_msg(buf);
+- u32 new_ref = new_tsock->p->ref;
++
++ lock_sock(new_sk);
++
++ /*
++ * Reject any stray messages received by new socket
++ * before the socket lock was taken (very, very unlikely)
++ */
++
++ reject_rx_queue(new_sk);
++
++ /* Connect new socket to it's peer */
+
+ id.ref = msg_origport(msg);
+ id.node = msg_orignode(msg);
+ tipc_connect2port(new_ref, &id);
+- newsock->state = SS_CONNECTED;
++ new_sock->state = SS_CONNECTED;
+
+ tipc_set_portimportance(new_ref, msg_importance(msg));
+ if (msg_named(msg)) {
+- new_tsock->p->conn_type = msg_nametype(msg);
+- new_tsock->p->conn_instance = msg_nameinst(msg);
++ new_tport->conn_type = msg_nametype(msg);
++ new_tport->conn_instance = msg_nameinst(msg);
+ }
+
+- /*
++ /*
+ * Respond to 'SYN-' by discarding it & returning 'ACK'-.
+ * Respond to 'SYN+' by queuing it on new socket.
+ */
+@@ -1402,24 +1563,23 @@ static int accept(struct socket *sock, struct socket *newsock, int flags)
+ if (!msg_data_sz(msg)) {
+ struct msghdr m = {NULL,};
+
+- send_packet(NULL, newsock, &m, 0);
+- advance_queue(tsock);
++ advance_rx_queue(sk);
++ send_packet(NULL, new_sock, &m, 0);
+ } else {
+- sock_lock(tsock);
+- skb_dequeue(&sock->sk->sk_receive_queue);
+- sock_unlock(tsock);
+- skb_queue_head(&newsock->sk->sk_receive_queue, buf);
++ __skb_dequeue(&sk->sk_receive_queue);
++ __skb_queue_head(&new_sk->sk_receive_queue, buf);
+ }
++ release_sock(new_sk);
+ }
+ exit:
+- up(&tsock->sem);
++ release_sock(sk);
+ return res;
+ }
+
+ /**
+ * shutdown - shutdown socket connection
+ * @sock: socket structure
+- * @how: direction to close (unused; always treated as read + write)
++ * @how: direction to close (must be SHUT_RDWR)
+ *
+ * Terminates connection (if necessary), then purges socket's receive queue.
+ *
+@@ -1428,53 +1588,46 @@ exit:
+
+ static int shutdown(struct socket *sock, int how)
+ {
+- struct tipc_sock* tsock = tipc_sk(sock->sk);
++ struct sock *sk = sock->sk;
++ struct tipc_port *tport = tipc_sk_port(sk);
+ struct sk_buff *buf;
+ int res;
+
+- /* Could return -EINVAL for an invalid "how", but why bother? */
+-
+- if (down_interruptible(&tsock->sem))
+- return -ERESTARTSYS;
++ if (how != SHUT_RDWR)
++ return -EINVAL;
+
+- sock_lock(tsock);
++ lock_sock(sk);
+
+ switch (sock->state) {
++ case SS_CONNECTING:
+ case SS_CONNECTED:
+
+- /* Send 'FIN+' or 'FIN-' message to peer */
+-
+- sock_unlock(tsock);
++ /* Disconnect and send a 'FIN+' or 'FIN-' message to peer */
+ restart:
+- if ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) {
++ buf = __skb_dequeue(&sk->sk_receive_queue);
++ if (buf) {
+ atomic_dec(&tipc_queue_size);
+ if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) {
+ buf_discard(buf);
+ goto restart;
+ }
++ tipc_disconnect(tport->ref);
+ tipc_reject_msg(buf, TIPC_CONN_SHUTDOWN);
++ } else {
++ tipc_shutdown(tport->ref);
+ }
+- else {
+- tipc_shutdown(tsock->p->ref);
+- }
+- sock_lock(tsock);
++
++ sock->state = SS_DISCONNECTING;
+
+ /* fall through */
+
+ case SS_DISCONNECTING:
+
+- /* Discard any unreceived messages */
++ /* Discard any unreceived messages; wake up sleeping tasks */
+
+- while ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) {
+- atomic_dec(&tipc_queue_size);
+- buf_discard(buf);
+- }
+- tsock->p->conn_unacked = 0;
+-
+- /* fall through */
+-
+- case SS_CONNECTING:
+- sock->state = SS_DISCONNECTING;
++ discard_rx_queue(sk);
++ if (waitqueue_active(sk->sk_sleep))
++ wake_up_interruptible(sk->sk_sleep);
+ res = 0;
+ break;
+
+@@ -1482,9 +1635,7 @@ restart:
+ res = -ENOTCONN;
+ }
+
+- sock_unlock(tsock);
+-
+- up(&tsock->sem);
++ release_sock(sk);
+ return res;
+ }
+
+@@ -1505,7 +1656,8 @@ restart:
+ static int setsockopt(struct socket *sock,
+ int lvl, int opt, char __user *ov, int ol)
+ {
+- struct tipc_sock *tsock = tipc_sk(sock->sk);
++ struct sock *sk = sock->sk;
++ struct tipc_port *tport = tipc_sk_port(sk);
+ u32 value;
+ int res;
+
+@@ -1518,30 +1670,31 @@ static int setsockopt(struct socket *sock,
+ if ((res = get_user(value, (u32 __user *)ov)))
+ return res;
+
+- if (down_interruptible(&tsock->sem))
+- return -ERESTARTSYS;
++ lock_sock(sk);
+
+ switch (opt) {
+ case TIPC_IMPORTANCE:
+- res = tipc_set_portimportance(tsock->p->ref, value);
++ res = tipc_set_portimportance(tport->ref, value);
+ break;
+ case TIPC_SRC_DROPPABLE:
+ if (sock->type != SOCK_STREAM)
+- res = tipc_set_portunreliable(tsock->p->ref, value);
++ res = tipc_set_portunreliable(tport->ref, value);
+ else
+ res = -ENOPROTOOPT;
+ break;
+ case TIPC_DEST_DROPPABLE:
+- res = tipc_set_portunreturnable(tsock->p->ref, value);
++ res = tipc_set_portunreturnable(tport->ref, value);
+ break;
+ case TIPC_CONN_TIMEOUT:
+- sock->sk->sk_rcvtimeo = (value * HZ / 1000);
++ sk->sk_rcvtimeo = msecs_to_jiffies(value);
++ /* no need to set "res", since already 0 at this point */
+ break;
+ default:
+ res = -EINVAL;
+ }
+
+- up(&tsock->sem);
++ release_sock(sk);
++
+ return res;
+ }
+
+@@ -1562,7 +1715,8 @@ static int setsockopt(struct socket *sock,
+ static int getsockopt(struct socket *sock,
+ int lvl, int opt, char __user *ov, int __user *ol)
+ {
+- struct tipc_sock *tsock = tipc_sk(sock->sk);
++ struct sock *sk = sock->sk;
++ struct tipc_port *tport = tipc_sk_port(sk);
+ int len;
+ u32 value;
+ int res;
+@@ -1574,40 +1728,41 @@ static int getsockopt(struct socket *sock,
+ if ((res = get_user(len, ol)))
+ return res;
+
+- if (down_interruptible(&tsock->sem))
+- return -ERESTARTSYS;
++ lock_sock(sk);
+
+ switch (opt) {
+ case TIPC_IMPORTANCE:
+- res = tipc_portimportance(tsock->p->ref, &value);
++ res = tipc_portimportance(tport->ref, &value);
+ break;
+ case TIPC_SRC_DROPPABLE:
+- res = tipc_portunreliable(tsock->p->ref, &value);
++ res = tipc_portunreliable(tport->ref, &value);
+ break;
+ case TIPC_DEST_DROPPABLE:
+- res = tipc_portunreturnable(tsock->p->ref, &value);
++ res = tipc_portunreturnable(tport->ref, &value);
+ break;
+ case TIPC_CONN_TIMEOUT:
+- value = (sock->sk->sk_rcvtimeo * 1000) / HZ;
++ value = jiffies_to_msecs(sk->sk_rcvtimeo);
++ /* no need to set "res", since already 0 at this point */
+ break;
+ default:
+ res = -EINVAL;
+ }
+
++ release_sock(sk);
++
+ if (res) {
+ /* "get" failed */
+ }
+ else if (len < sizeof(value)) {
+ res = -EINVAL;
+ }
+- else if ((res = copy_to_user(ov, &value, sizeof(value)))) {
+- /* couldn't return value */
++ else if (copy_to_user(ov, &value, sizeof(value))) {
++ res = -EFAULT;
+ }
+ else {
+ res = put_user(sizeof(value), ol);
+ }
+
+- up(&tsock->sem);
+ return res;
+ }
+
+@@ -1720,6 +1875,7 @@ int tipc_socket_init(void)
+ /**
+ * tipc_socket_stop - stop TIPC socket interface
+ */
++
+ void tipc_socket_stop(void)
+ {
+ if (!sockets_enabled)
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
+index b8788fd..e18cd36 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -252,7 +252,7 @@ static struct sock *__unix_find_socket_byname(struct net *net,
+ sk_for_each(s, node, &unix_socket_table[hash ^ type]) {
+ struct unix_sock *u = unix_sk(s);
+
+- if (s->sk_net != net)
++ if (!net_eq(sock_net(s), net))
+ continue;
+
+ if (u->addr->len == len &&
+@@ -289,7 +289,7 @@ static struct sock *unix_find_socket_byinode(struct net *net, struct inode *i)
+ &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) {
+ struct dentry *dentry = unix_sk(s)->dentry;
+
+- if (s->sk_net != net)
++ if (!net_eq(sock_net(s), net))
+ continue;
+
+ if(dentry && dentry->d_inode == i)
+@@ -654,7 +654,7 @@ static int unix_release(struct socket *sock)
+ static int unix_autobind(struct socket *sock)
+ {
+ struct sock *sk = sock->sk;
+- struct net *net = sk->sk_net;
++ struct net *net = sock_net(sk);
+ struct unix_sock *u = unix_sk(sk);
+ static u32 ordernum = 1;
+ struct unix_address * addr;
+@@ -758,7 +758,7 @@ fail:
+ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ {
+ struct sock *sk = sock->sk;
+- struct net *net = sk->sk_net;
++ struct net *net = sock_net(sk);
+ struct unix_sock *u = unix_sk(sk);
+ struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
+ struct dentry * dentry = NULL;
+@@ -819,7 +819,11 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ */
+ mode = S_IFSOCK |
+ (SOCK_INODE(sock)->i_mode & ~current->fs->umask);
++ err = mnt_want_write(nd.path.mnt);
++ if (err)
++ goto out_mknod_dput;
+ err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0);
++ mnt_drop_write(nd.path.mnt);
+ if (err)
+ goto out_mknod_dput;
+ mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+@@ -899,7 +903,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
+ int alen, int flags)
+ {
+ struct sock *sk = sock->sk;
+- struct net *net = sk->sk_net;
++ struct net *net = sock_net(sk);
+ struct sockaddr_un *sunaddr=(struct sockaddr_un*)addr;
+ struct sock *other;
+ unsigned hash;
+@@ -996,7 +1000,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
+ {
+ struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
+ struct sock *sk = sock->sk;
+- struct net *net = sk->sk_net;
++ struct net *net = sock_net(sk);
+ struct unix_sock *u = unix_sk(sk), *newu, *otheru;
+ struct sock *newsk = NULL;
+ struct sock *other = NULL;
+@@ -1025,7 +1029,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
+ err = -ENOMEM;
+
+ /* create new sock for complete connection */
+- newsk = unix_create1(sk->sk_net, NULL);
++ newsk = unix_create1(sock_net(sk), NULL);
+ if (newsk == NULL)
+ goto out;
+
+@@ -1312,7 +1316,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
+ {
+ struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
+ struct sock *sk = sock->sk;
+- struct net *net = sk->sk_net;
++ struct net *net = sock_net(sk);
+ struct unix_sock *u = unix_sk(sk);
+ struct sockaddr_un *sunaddr=msg->msg_name;
+ struct sock *other = NULL;
+@@ -2016,13 +2020,14 @@ struct unix_iter_state {
+ struct seq_net_private p;
+ int i;
+ };
+-static struct sock *unix_seq_idx(struct unix_iter_state *iter, loff_t pos)
++static struct sock *unix_seq_idx(struct seq_file *seq, loff_t pos)
+ {
++ struct unix_iter_state *iter = seq->private;
+ loff_t off = 0;
+ struct sock *s;
+
+ for (s = first_unix_socket(&iter->i); s; s = next_unix_socket(&iter->i, s)) {
+- if (s->sk_net != iter->p.net)
++ if (sock_net(s) != seq_file_net(seq))
+ continue;
+ if (off == pos)
+ return s;
+@@ -2035,9 +2040,8 @@ static struct sock *unix_seq_idx(struct unix_iter_state *iter, loff_t pos)
+ static void *unix_seq_start(struct seq_file *seq, loff_t *pos)
+ __acquires(unix_table_lock)
+ {
+- struct unix_iter_state *iter = seq->private;
+ spin_lock(&unix_table_lock);
+- return *pos ? unix_seq_idx(iter, *pos - 1) : ((void *) 1);
++ return *pos ? unix_seq_idx(seq, *pos - 1) : SEQ_START_TOKEN;
+ }
+
+ static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+@@ -2046,11 +2050,11 @@ static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+ struct sock *sk = v;
+ ++*pos;
+
+- if (v == (void *)1)
++ if (v == SEQ_START_TOKEN)
+ sk = first_unix_socket(&iter->i);
+ else
+ sk = next_unix_socket(&iter->i, sk);
+- while (sk && (sk->sk_net != iter->p.net))
++ while (sk && (sock_net(sk) != seq_file_net(seq)))
+ sk = next_unix_socket(&iter->i, sk);
+ return sk;
+ }
+@@ -2064,7 +2068,7 @@ static void unix_seq_stop(struct seq_file *seq, void *v)
+ static int unix_seq_show(struct seq_file *seq, void *v)
+ {
+
+- if (v == (void *)1)
++ if (v == SEQ_START_TOKEN)
+ seq_puts(seq, "Num RefCount Protocol Flags Type St "
+ "Inode Path\n");
+ else {
+@@ -2176,7 +2180,7 @@ static int __init af_unix_init(void)
+ rc = proto_register(&unix_proto, 1);
+ if (rc != 0) {
+ printk(KERN_CRIT "%s: Cannot create unix_sock SLAB cache!\n",
+- __FUNCTION__);
++ __func__);
+ goto out;
+ }
+
+@@ -2193,7 +2197,11 @@ static void __exit af_unix_exit(void)
+ unregister_pernet_subsys(&unix_net_ops);
+ }
+
+-module_init(af_unix_init);
++/* Earlier than device_initcall() so that other drivers invoking
++ request_module() don't end up in a loop when modprobe tries
++ to use a UNIX socket. But later than subsys_initcall() because
++ we depend on stuff initialised there */
++fs_initcall(af_unix_init);
+ module_exit(af_unix_exit);
+
+ MODULE_LICENSE("GPL");
+diff --git a/net/wireless/Makefile b/net/wireless/Makefile
+index 65710a4..b9f943c 100644
+--- a/net/wireless/Makefile
++++ b/net/wireless/Makefile
+@@ -1,5 +1,5 @@
+ obj-$(CONFIG_WIRELESS_EXT) += wext.o
+ obj-$(CONFIG_CFG80211) += cfg80211.o
+
+-cfg80211-y += core.o sysfs.o radiotap.o
++cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o
+ cfg80211-$(CONFIG_NL80211) += nl80211.o
+diff --git a/net/wireless/core.c b/net/wireless/core.c
+index cfc5fc5..80afacd 100644
+--- a/net/wireless/core.c
++++ b/net/wireless/core.c
+@@ -232,6 +232,47 @@ int wiphy_register(struct wiphy *wiphy)
+ {
+ struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
+ int res;
++ enum ieee80211_band band;
++ struct ieee80211_supported_band *sband;
++ bool have_band = false;
++ int i;
++
++ /* sanity check supported bands/channels */
++ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
++ sband = wiphy->bands[band];
++ if (!sband)
++ continue;
++
++ sband->band = band;
++
++ if (!sband->n_channels || !sband->n_bitrates) {
++ WARN_ON(1);
++ return -EINVAL;
++ }
++
++ for (i = 0; i < sband->n_channels; i++) {
++ sband->channels[i].orig_flags =
++ sband->channels[i].flags;
++ sband->channels[i].orig_mag =
++ sband->channels[i].max_antenna_gain;
++ sband->channels[i].orig_mpwr =
++ sband->channels[i].max_power;
++ sband->channels[i].band = band;
++ }
++
++ have_band = true;
++ }
++
++ if (!have_band) {
++ WARN_ON(1);
++ return -EINVAL;
++ }
++
++ /* check and set up bitrates */
++ ieee80211_set_bitrate_flags(wiphy);
++
++ /* set up regulatory info */
++ wiphy_update_regulatory(wiphy);
+
+ mutex_lock(&cfg80211_drv_mutex);
+
+diff --git a/net/wireless/core.h b/net/wireless/core.h
+index eb0f846..7a02c35 100644
+--- a/net/wireless/core.h
++++ b/net/wireless/core.h
+@@ -78,4 +78,7 @@ extern void cfg80211_dev_free(struct cfg80211_registered_device *drv);
+ extern int cfg80211_dev_rename(struct cfg80211_registered_device *drv,
+ char *newname);
+
++void ieee80211_set_bitrate_flags(struct wiphy *wiphy);
++void wiphy_update_regulatory(struct wiphy *wiphy);
++
+ #endif /* __NET_WIRELESS_CORE_H */
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index f68a5c8..2bdd4dd 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -81,7 +81,12 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
+ [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 },
+ [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
+ .len = NL80211_MAX_SUPP_RATES },
++ [NL80211_ATTR_STA_PLINK_ACTION] = { .type = NLA_U8 },
+ [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
++ [NL80211_ATTR_MNTR_FLAGS] = { .type = NLA_NESTED },
++ [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
++ .len = IEEE80211_MAX_MESH_ID_LEN },
++ [NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 },
+ };
+
+ /* message building helper */
+@@ -98,6 +103,13 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
+ struct cfg80211_registered_device *dev)
+ {
+ void *hdr;
++ struct nlattr *nl_bands, *nl_band;
++ struct nlattr *nl_freqs, *nl_freq;
++ struct nlattr *nl_rates, *nl_rate;
++ enum ieee80211_band band;
++ struct ieee80211_channel *chan;
++ struct ieee80211_rate *rate;
++ int i;
+
+ hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY);
+ if (!hdr)
+@@ -105,6 +117,73 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
+
+ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx);
+ NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy));
++
++ nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS);
++ if (!nl_bands)
++ goto nla_put_failure;
++
++ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
++ if (!dev->wiphy.bands[band])
++ continue;
++
++ nl_band = nla_nest_start(msg, band);
++ if (!nl_band)
++ goto nla_put_failure;
++
++ /* add frequencies */
++ nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS);
++ if (!nl_freqs)
++ goto nla_put_failure;
++
++ for (i = 0; i < dev->wiphy.bands[band]->n_channels; i++) {
++ nl_freq = nla_nest_start(msg, i);
++ if (!nl_freq)
++ goto nla_put_failure;
++
++ chan = &dev->wiphy.bands[band]->channels[i];
++ NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_FREQ,
++ chan->center_freq);
++
++ if (chan->flags & IEEE80211_CHAN_DISABLED)
++ NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_DISABLED);
++ if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
++ NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN);
++ if (chan->flags & IEEE80211_CHAN_NO_IBSS)
++ NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_NO_IBSS);
++ if (chan->flags & IEEE80211_CHAN_RADAR)
++ NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR);
++
++ nla_nest_end(msg, nl_freq);
++ }
++
++ nla_nest_end(msg, nl_freqs);
++
++ /* add bitrates */
++ nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES);
++ if (!nl_rates)
++ goto nla_put_failure;
++
++ for (i = 0; i < dev->wiphy.bands[band]->n_bitrates; i++) {
++ nl_rate = nla_nest_start(msg, i);
++ if (!nl_rate)
++ goto nla_put_failure;
++
++ rate = &dev->wiphy.bands[band]->bitrates[i];
++ NLA_PUT_U32(msg, NL80211_BITRATE_ATTR_RATE,
++ rate->bitrate);
++ if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
++ NLA_PUT_FLAG(msg,
++ NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE);
++
++ nla_nest_end(msg, nl_rate);
++ }
++
++ nla_nest_end(msg, nl_rates);
++
++ nla_nest_end(msg, nl_band);
++ }
++ nla_nest_end(msg, nl_bands);
++
+ return genlmsg_end(msg, hdr);
+
+ nla_put_failure:
+@@ -262,12 +341,45 @@ static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
+ return -ENOBUFS;
+ }
+
++static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = {
++ [NL80211_MNTR_FLAG_FCSFAIL] = { .type = NLA_FLAG },
++ [NL80211_MNTR_FLAG_PLCPFAIL] = { .type = NLA_FLAG },
++ [NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG },
++ [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG },
++ [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG },
++};
++
++static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
++{
++ struct nlattr *flags[NL80211_MNTR_FLAG_MAX + 1];
++ int flag;
++
++ *mntrflags = 0;
++
++ if (!nla)
++ return -EINVAL;
++
++ if (nla_parse_nested(flags, NL80211_MNTR_FLAG_MAX,
++ nla, mntr_flags_policy))
++ return -EINVAL;
++
++ for (flag = 1; flag <= NL80211_MNTR_FLAG_MAX; flag++)
++ if (flags[flag])
++ *mntrflags |= (1<<flag);
++
++ return 0;
++}
++
+ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
+ {
+ struct cfg80211_registered_device *drv;
++ struct vif_params params;
+ int err, ifindex;
+ enum nl80211_iftype type;
+ struct net_device *dev;
++ u32 flags;
++
++ memset(¶ms, 0, sizeof(params));
+
+ if (info->attrs[NL80211_ATTR_IFTYPE]) {
+ type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
+@@ -287,8 +399,18 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
+ goto unlock;
+ }
+
++ if (type == NL80211_IFTYPE_MESH_POINT &&
++ info->attrs[NL80211_ATTR_MESH_ID]) {
++ params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
++ params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
++ }
++
+ rtnl_lock();
+- err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, type);
++ err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
++ info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
++ &flags);
++ err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex,
++ type, err ? NULL : &flags, ¶ms);
+ rtnl_unlock();
+
+ unlock:
+@@ -299,8 +421,12 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
+ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
+ {
+ struct cfg80211_registered_device *drv;
++ struct vif_params params;
+ int err;
+ enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
++ u32 flags;
++
++ memset(¶ms, 0, sizeof(params));
+
+ if (!info->attrs[NL80211_ATTR_IFNAME])
+ return -EINVAL;
+@@ -320,11 +446,22 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
+ goto unlock;
+ }
+
++ if (type == NL80211_IFTYPE_MESH_POINT &&
++ info->attrs[NL80211_ATTR_MESH_ID]) {
++ params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
++ params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
++ }
++
+ rtnl_lock();
++ err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
++ info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
++ &flags);
+ err = drv->ops->add_virtual_intf(&drv->wiphy,
+- nla_data(info->attrs[NL80211_ATTR_IFNAME]), type);
++ nla_data(info->attrs[NL80211_ATTR_IFNAME]),
++ type, err ? NULL : &flags, ¶ms);
+ rtnl_unlock();
+
++
+ unlock:
+ cfg80211_put_dev(drv);
+ return err;
+@@ -752,10 +889,10 @@ static int parse_station_flags(struct nlattr *nla, u32 *staflags)
+
+ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
+ int flags, struct net_device *dev,
+- u8 *mac_addr, struct station_stats *stats)
++ u8 *mac_addr, struct station_info *sinfo)
+ {
+ void *hdr;
+- struct nlattr *statsattr;
++ struct nlattr *sinfoattr;
+
+ hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
+ if (!hdr)
+@@ -764,20 +901,29 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
+ NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
+
+- statsattr = nla_nest_start(msg, NL80211_ATTR_STA_STATS);
+- if (!statsattr)
++ sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO);
++ if (!sinfoattr)
+ goto nla_put_failure;
+- if (stats->filled & STATION_STAT_INACTIVE_TIME)
+- NLA_PUT_U32(msg, NL80211_STA_STAT_INACTIVE_TIME,
+- stats->inactive_time);
+- if (stats->filled & STATION_STAT_RX_BYTES)
+- NLA_PUT_U32(msg, NL80211_STA_STAT_RX_BYTES,
+- stats->rx_bytes);
+- if (stats->filled & STATION_STAT_TX_BYTES)
+- NLA_PUT_U32(msg, NL80211_STA_STAT_TX_BYTES,
+- stats->tx_bytes);
+-
+- nla_nest_end(msg, statsattr);
++ if (sinfo->filled & STATION_INFO_INACTIVE_TIME)
++ NLA_PUT_U32(msg, NL80211_STA_INFO_INACTIVE_TIME,
++ sinfo->inactive_time);
++ if (sinfo->filled & STATION_INFO_RX_BYTES)
++ NLA_PUT_U32(msg, NL80211_STA_INFO_RX_BYTES,
++ sinfo->rx_bytes);
++ if (sinfo->filled & STATION_INFO_TX_BYTES)
++ NLA_PUT_U32(msg, NL80211_STA_INFO_TX_BYTES,
++ sinfo->tx_bytes);
++ if (sinfo->filled & STATION_INFO_LLID)
++ NLA_PUT_U16(msg, NL80211_STA_INFO_LLID,
++ sinfo->llid);
++ if (sinfo->filled & STATION_INFO_PLID)
++ NLA_PUT_U16(msg, NL80211_STA_INFO_PLID,
++ sinfo->plid);
++ if (sinfo->filled & STATION_INFO_PLINK_STATE)
++ NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
++ sinfo->plink_state);
++
++ nla_nest_end(msg, sinfoattr);
+
+ return genlmsg_end(msg, hdr);
+
+@@ -785,17 +931,80 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
+ return genlmsg_cancel(msg, hdr);
+ }
+
++static int nl80211_dump_station(struct sk_buff *skb,
++ struct netlink_callback *cb)
++{
++ int wp_idx = 0;
++ int if_idx = 0;
++ int sta_idx = cb->args[2];
++ int wp_start = cb->args[0];
++ int if_start = cb->args[1];
++ struct station_info sinfo;
++ struct cfg80211_registered_device *dev;
++ struct wireless_dev *wdev;
++ u8 mac_addr[ETH_ALEN];
++ int err;
++ int exit = 0;
++
++ /* TODO: filter by device */
++ mutex_lock(&cfg80211_drv_mutex);
++ list_for_each_entry(dev, &cfg80211_drv_list, list) {
++ if (exit)
++ break;
++ if (++wp_idx < wp_start)
++ continue;
++ if_idx = 0;
++
++ mutex_lock(&dev->devlist_mtx);
++ list_for_each_entry(wdev, &dev->netdev_list, list) {
++ if (exit)
++ break;
++ if (++if_idx < if_start)
++ continue;
++ if (!dev->ops->dump_station)
++ continue;
++
++ for (;; ++sta_idx) {
++ rtnl_lock();
++ err = dev->ops->dump_station(&dev->wiphy,
++ wdev->netdev, sta_idx, mac_addr,
++ &sinfo);
++ rtnl_unlock();
++ if (err) {
++ sta_idx = 0;
++ break;
++ }
++ if (nl80211_send_station(skb,
++ NETLINK_CB(cb->skb).pid,
++ cb->nlh->nlmsg_seq, NLM_F_MULTI,
++ wdev->netdev, mac_addr,
++ &sinfo) < 0) {
++ exit = 1;
++ break;
++ }
++ }
++ }
++ mutex_unlock(&dev->devlist_mtx);
++ }
++ mutex_unlock(&cfg80211_drv_mutex);
++
++ cb->args[0] = wp_idx;
++ cb->args[1] = if_idx;
++ cb->args[2] = sta_idx;
++
++ return skb->len;
++}
+
+ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
+ {
+ struct cfg80211_registered_device *drv;
+ int err;
+ struct net_device *dev;
+- struct station_stats stats;
++ struct station_info sinfo;
+ struct sk_buff *msg;
+ u8 *mac_addr = NULL;
+
+- memset(&stats, 0, sizeof(stats));
++ memset(&sinfo, 0, sizeof(sinfo));
+
+ if (!info->attrs[NL80211_ATTR_MAC])
+ return -EINVAL;
+@@ -812,15 +1021,18 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
+ }
+
+ rtnl_lock();
+- err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &stats);
++ err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &sinfo);
+ rtnl_unlock();
+
++ if (err)
++ goto out;
++
+ msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ if (!msg)
+ goto out;
+
+ if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0,
+- dev, mac_addr, &stats) < 0)
++ dev, mac_addr, &sinfo) < 0)
+ goto out_free;
+
+ err = genlmsg_unicast(msg, info->snd_pid);
+@@ -891,6 +1103,10 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
+ ¶ms.station_flags))
+ return -EINVAL;
+
++ if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
++ params.plink_action =
++ nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
++
+ err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
+ if (err)
+ return err;
+@@ -1005,6 +1221,273 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
+ return err;
+ }
+
++static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq,
++ int flags, struct net_device *dev,
++ u8 *dst, u8 *next_hop,
++ struct mpath_info *pinfo)
++{
++ void *hdr;
++ struct nlattr *pinfoattr;
++
++ hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
++ if (!hdr)
++ return -1;
++
++ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
++ NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst);
++ NLA_PUT(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop);
++
++ pinfoattr = nla_nest_start(msg, NL80211_ATTR_MPATH_INFO);
++ if (!pinfoattr)
++ goto nla_put_failure;
++ if (pinfo->filled & MPATH_INFO_FRAME_QLEN)
++ NLA_PUT_U32(msg, NL80211_MPATH_INFO_FRAME_QLEN,
++ pinfo->frame_qlen);
++ if (pinfo->filled & MPATH_INFO_DSN)
++ NLA_PUT_U32(msg, NL80211_MPATH_INFO_DSN,
++ pinfo->dsn);
++ if (pinfo->filled & MPATH_INFO_METRIC)
++ NLA_PUT_U32(msg, NL80211_MPATH_INFO_METRIC,
++ pinfo->metric);
++ if (pinfo->filled & MPATH_INFO_EXPTIME)
++ NLA_PUT_U32(msg, NL80211_MPATH_INFO_EXPTIME,
++ pinfo->exptime);
++ if (pinfo->filled & MPATH_INFO_FLAGS)
++ NLA_PUT_U8(msg, NL80211_MPATH_INFO_FLAGS,
++ pinfo->flags);
++ if (pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT)
++ NLA_PUT_U32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
++ pinfo->discovery_timeout);
++ if (pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES)
++ NLA_PUT_U8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES,
++ pinfo->discovery_retries);
++
++ nla_nest_end(msg, pinfoattr);
++
++ return genlmsg_end(msg, hdr);
++
++ nla_put_failure:
++ return genlmsg_cancel(msg, hdr);
++}
++
++static int nl80211_dump_mpath(struct sk_buff *skb,
++ struct netlink_callback *cb)
++{
++ int wp_idx = 0;
++ int if_idx = 0;
++ int sta_idx = cb->args[2];
++ int wp_start = cb->args[0];
++ int if_start = cb->args[1];
++ struct mpath_info pinfo;
++ struct cfg80211_registered_device *dev;
++ struct wireless_dev *wdev;
++ u8 dst[ETH_ALEN];
++ u8 next_hop[ETH_ALEN];
++ int err;
++ int exit = 0;
++
++ /* TODO: filter by device */
++ mutex_lock(&cfg80211_drv_mutex);
++ list_for_each_entry(dev, &cfg80211_drv_list, list) {
++ if (exit)
++ break;
++ if (++wp_idx < wp_start)
++ continue;
++ if_idx = 0;
++
++ mutex_lock(&dev->devlist_mtx);
++ list_for_each_entry(wdev, &dev->netdev_list, list) {
++ if (exit)
++ break;
++ if (++if_idx < if_start)
++ continue;
++ if (!dev->ops->dump_mpath)
++ continue;
++
++ for (;; ++sta_idx) {
++ rtnl_lock();
++ err = dev->ops->dump_mpath(&dev->wiphy,
++ wdev->netdev, sta_idx, dst,
++ next_hop, &pinfo);
++ rtnl_unlock();
++ if (err) {
++ sta_idx = 0;
++ break;
++ }
++ if (nl80211_send_mpath(skb,
++ NETLINK_CB(cb->skb).pid,
++ cb->nlh->nlmsg_seq, NLM_F_MULTI,
++ wdev->netdev, dst, next_hop,
++ &pinfo) < 0) {
++ exit = 1;
++ break;
++ }
++ }
++ }
++ mutex_unlock(&dev->devlist_mtx);
++ }
++ mutex_unlock(&cfg80211_drv_mutex);
++
++ cb->args[0] = wp_idx;
++ cb->args[1] = if_idx;
++ cb->args[2] = sta_idx;
++
++ return skb->len;
++}
++
++static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
++{
++ struct cfg80211_registered_device *drv;
++ int err;
++ struct net_device *dev;
++ struct mpath_info pinfo;
++ struct sk_buff *msg;
++ u8 *dst = NULL;
++ u8 next_hop[ETH_ALEN];
++
++ memset(&pinfo, 0, sizeof(pinfo));
++
++ if (!info->attrs[NL80211_ATTR_MAC])
++ return -EINVAL;
++
++ dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
++
++ err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
++ if (err)
++ return err;
++
++ if (!drv->ops->get_mpath) {
++ err = -EOPNOTSUPP;
++ goto out;
++ }
++
++ rtnl_lock();
++ err = drv->ops->get_mpath(&drv->wiphy, dev, dst, next_hop, &pinfo);
++ rtnl_unlock();
++
++ if (err)
++ goto out;
++
++ msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
++ if (!msg)
++ goto out;
++
++ if (nl80211_send_mpath(msg, info->snd_pid, info->snd_seq, 0,
++ dev, dst, next_hop, &pinfo) < 0)
++ goto out_free;
++
++ err = genlmsg_unicast(msg, info->snd_pid);
++ goto out;
++
++ out_free:
++ nlmsg_free(msg);
++
++ out:
++ cfg80211_put_dev(drv);
++ dev_put(dev);
++ return err;
++}
++
++static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
++{
++ struct cfg80211_registered_device *drv;
++ int err;
++ struct net_device *dev;
++ u8 *dst = NULL;
++ u8 *next_hop = NULL;
++
++ if (!info->attrs[NL80211_ATTR_MAC])
++ return -EINVAL;
++
++ if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
++ return -EINVAL;
++
++ dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
++ next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
++
++ err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
++ if (err)
++ return err;
++
++ if (!drv->ops->change_mpath) {
++ err = -EOPNOTSUPP;
++ goto out;
++ }
++
++ rtnl_lock();
++ err = drv->ops->change_mpath(&drv->wiphy, dev, dst, next_hop);
++ rtnl_unlock();
++
++ out:
++ cfg80211_put_dev(drv);
++ dev_put(dev);
++ return err;
++}
++static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
++{
++ struct cfg80211_registered_device *drv;
++ int err;
++ struct net_device *dev;
++ u8 *dst = NULL;
++ u8 *next_hop = NULL;
++
++ if (!info->attrs[NL80211_ATTR_MAC])
++ return -EINVAL;
++
++ if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
++ return -EINVAL;
++
++ dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
++ next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
++
++ err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
++ if (err)
++ return err;
++
++ if (!drv->ops->add_mpath) {
++ err = -EOPNOTSUPP;
++ goto out;
++ }
++
++ rtnl_lock();
++ err = drv->ops->add_mpath(&drv->wiphy, dev, dst, next_hop);
++ rtnl_unlock();
++
++ out:
++ cfg80211_put_dev(drv);
++ dev_put(dev);
++ return err;
++}
++
++static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
++{
++ struct cfg80211_registered_device *drv;
++ int err;
++ struct net_device *dev;
++ u8 *dst = NULL;
++
++ if (info->attrs[NL80211_ATTR_MAC])
++ dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
++
++ err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
++ if (err)
++ return err;
++
++ if (!drv->ops->del_mpath) {
++ err = -EOPNOTSUPP;
++ goto out;
++ }
++
++ rtnl_lock();
++ err = drv->ops->del_mpath(&drv->wiphy, dev, dst);
++ rtnl_unlock();
++
++ out:
++ cfg80211_put_dev(drv);
++ dev_put(dev);
++ return err;
++}
++
+ static struct genl_ops nl80211_ops[] = {
+ {
+ .cmd = NL80211_CMD_GET_WIPHY,
+@@ -1089,7 +1572,7 @@ static struct genl_ops nl80211_ops[] = {
+ {
+ .cmd = NL80211_CMD_GET_STATION,
+ .doit = nl80211_get_station,
+- /* TODO: implement dumpit */
++ .dumpit = nl80211_dump_station,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
+@@ -1111,6 +1594,31 @@ static struct genl_ops nl80211_ops[] = {
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
++ {
++ .cmd = NL80211_CMD_GET_MPATH,
++ .doit = nl80211_get_mpath,
++ .dumpit = nl80211_dump_mpath,
++ .policy = nl80211_policy,
++ .flags = GENL_ADMIN_PERM,
++ },
++ {
++ .cmd = NL80211_CMD_SET_MPATH,
++ .doit = nl80211_set_mpath,
++ .policy = nl80211_policy,
++ .flags = GENL_ADMIN_PERM,
++ },
++ {
++ .cmd = NL80211_CMD_NEW_MPATH,
++ .doit = nl80211_new_mpath,
++ .policy = nl80211_policy,
++ .flags = GENL_ADMIN_PERM,
++ },
++ {
++ .cmd = NL80211_CMD_DEL_MPATH,
++ .doit = nl80211_del_mpath,
++ .policy = nl80211_policy,
++ .flags = GENL_ADMIN_PERM,
++ },
+ };
+
+ /* multicast groups */
+diff --git a/net/wireless/reg.c b/net/wireless/reg.c
+new file mode 100644
+index 0000000..185488d
+--- /dev/null
++++ b/net/wireless/reg.c
+@@ -0,0 +1,162 @@
++/*
++ * Copyright 2002-2005, Instant802 Networks, Inc.
++ * Copyright 2005-2006, Devicescape Software, Inc.
++ * Copyright 2007 Johannes Berg <johannes at sipsolutions.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++/*
++ * This regulatory domain control implementation is highly incomplete, it
++ * only exists for the purpose of not regressing mac80211.
++ *
++ * For now, drivers can restrict the set of allowed channels by either
++ * not registering those channels or setting the IEEE80211_CHAN_DISABLED
++ * flag; that flag will only be *set* by this code, never *cleared.
++ *
++ * The usual implementation is for a driver to read a device EEPROM to
++ * determine which regulatory domain it should be operating under, then
++ * looking up the allowable channels in a driver-local table and finally
++ * registering those channels in the wiphy structure.
++ *
++ * Alternatively, drivers that trust the regulatory domain control here
++ * will register a complete set of capabilities and the control code
++ * will restrict the set by setting the IEEE80211_CHAN_* flags.
++ */
++#include <linux/kernel.h>
++#include <net/wireless.h>
++#include "core.h"
++
++static char *ieee80211_regdom = "US";
++module_param(ieee80211_regdom, charp, 0444);
++MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
++
++struct ieee80211_channel_range {
++ short start_freq;
++ short end_freq;
++ int max_power;
++ int max_antenna_gain;
++ u32 flags;
++};
++
++struct ieee80211_regdomain {
++ const char *code;
++ const struct ieee80211_channel_range *ranges;
++ int n_ranges;
++};
++
++#define RANGE_PWR(_start, _end, _pwr, _ag, _flags) \
++ { _start, _end, _pwr, _ag, _flags }
++
++
++/*
++ * Ideally, in the future, these definitions will be loaded from a
++ * userspace table via some daemon.
++ */
++static const struct ieee80211_channel_range ieee80211_US_channels[] = {
++ /* IEEE 802.11b/g, channels 1..11 */
++ RANGE_PWR(2412, 2462, 27, 6, 0),
++ /* IEEE 802.11a, channel 36*/
++ RANGE_PWR(5180, 5180, 23, 6, 0),
++ /* IEEE 802.11a, channel 40*/
++ RANGE_PWR(5200, 5200, 23, 6, 0),
++ /* IEEE 802.11a, channel 44*/
++ RANGE_PWR(5220, 5220, 23, 6, 0),
++ /* IEEE 802.11a, channels 48..64 */
++ RANGE_PWR(5240, 5320, 23, 6, 0),
++ /* IEEE 802.11a, channels 149..165, outdoor */
++ RANGE_PWR(5745, 5825, 30, 6, 0),
++};
++
++static const struct ieee80211_channel_range ieee80211_JP_channels[] = {
++ /* IEEE 802.11b/g, channels 1..14 */
++ RANGE_PWR(2412, 2484, 20, 6, 0),
++ /* IEEE 802.11a, channels 34..48 */
++ RANGE_PWR(5170, 5240, 20, 6, IEEE80211_CHAN_PASSIVE_SCAN),
++ /* IEEE 802.11a, channels 52..64 */
++ RANGE_PWR(5260, 5320, 20, 6, IEEE80211_CHAN_NO_IBSS |
++ IEEE80211_CHAN_RADAR),
++};
++
++#define REGDOM(_code) \
++ { \
++ .code = __stringify(_code), \
++ .ranges = ieee80211_ ##_code## _channels, \
++ .n_ranges = ARRAY_SIZE(ieee80211_ ##_code## _channels), \
++ }
++
++static const struct ieee80211_regdomain ieee80211_regdoms[] = {
++ REGDOM(US),
++ REGDOM(JP),
++};
++
++
++static const struct ieee80211_regdomain *get_regdom(void)
++{
++ static const struct ieee80211_channel_range
++ ieee80211_world_channels[] = {
++ /* IEEE 802.11b/g, channels 1..11 */
++ RANGE_PWR(2412, 2462, 27, 6, 0),
++ };
++ static const struct ieee80211_regdomain regdom_world = REGDOM(world);
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(ieee80211_regdoms); i++)
++ if (strcmp(ieee80211_regdom, ieee80211_regdoms[i].code) == 0)
++ return &ieee80211_regdoms[i];
++
++ return ®dom_world;
++}
++
++
++static void handle_channel(struct ieee80211_channel *chan,
++ const struct ieee80211_regdomain *rd)
++{
++ int i;
++ u32 flags = chan->orig_flags;
++ const struct ieee80211_channel_range *rg = NULL;
++
++ for (i = 0; i < rd->n_ranges; i++) {
++ if (rd->ranges[i].start_freq <= chan->center_freq &&
++ chan->center_freq <= rd->ranges[i].end_freq) {
++ rg = &rd->ranges[i];
++ break;
++ }
++ }
++
++ if (!rg) {
++ /* not found */
++ flags |= IEEE80211_CHAN_DISABLED;
++ chan->flags = flags;
++ return;
++ }
++
++ chan->flags = flags;
++ chan->max_antenna_gain = min(chan->orig_mag,
++ rg->max_antenna_gain);
++ if (chan->orig_mpwr)
++ chan->max_power = min(chan->orig_mpwr, rg->max_power);
++ else
++ chan->max_power = rg->max_power;
++}
++
++static void handle_band(struct ieee80211_supported_band *sband,
++ const struct ieee80211_regdomain *rd)
++{
++ int i;
++
++ for (i = 0; i < sband->n_channels; i++)
++ handle_channel(&sband->channels[i], rd);
++}
++
++void wiphy_update_regulatory(struct wiphy *wiphy)
++{
++ enum ieee80211_band band;
++ const struct ieee80211_regdomain *rd = get_regdom();
++
++ for (band = 0; band < IEEE80211_NUM_BANDS; band++)
++ if (wiphy->bands[band])
++ handle_band(wiphy->bands[band], rd);
++}
+diff --git a/net/wireless/util.c b/net/wireless/util.c
+new file mode 100644
+index 0000000..f544246
+--- /dev/null
++++ b/net/wireless/util.c
+@@ -0,0 +1,121 @@
++/*
++ * Wireless utility functions
++ *
++ * Copyright 2007 Johannes Berg <johannes at sipsolutions.net>
++ */
++#include <net/wireless.h>
++#include <asm/bitops.h>
++#include "core.h"
++
++int ieee80211_channel_to_frequency(int chan)
++{
++ if (chan < 14)
++ return 2407 + chan * 5;
++
++ if (chan == 14)
++ return 2484;
++
++ /* FIXME: 802.11j 17.3.8.3.2 */
++ return (chan + 1000) * 5;
++}
++EXPORT_SYMBOL(ieee80211_channel_to_frequency);
++
++int ieee80211_frequency_to_channel(int freq)
++{
++ if (freq == 2484)
++ return 14;
++
++ if (freq < 2484)
++ return (freq - 2407) / 5;
++
++ /* FIXME: 802.11j 17.3.8.3.2 */
++ return freq/5 - 1000;
++}
++EXPORT_SYMBOL(ieee80211_frequency_to_channel);
++
++struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy,
++ int freq)
++{
++ enum ieee80211_band band;
++ struct ieee80211_supported_band *sband;
++ int i;
++
++ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
++ sband = wiphy->bands[band];
++
++ if (!sband)
++ continue;
++
++ for (i = 0; i < sband->n_channels; i++) {
++ if (sband->channels[i].center_freq == freq)
++ return &sband->channels[i];
++ }
++ }
++
++ return NULL;
++}
++EXPORT_SYMBOL(__ieee80211_get_channel);
++
++static void set_mandatory_flags_band(struct ieee80211_supported_band *sband,
++ enum ieee80211_band band)
++{
++ int i, want;
++
++ switch (band) {
++ case IEEE80211_BAND_5GHZ:
++ want = 3;
++ for (i = 0; i < sband->n_bitrates; i++) {
++ if (sband->bitrates[i].bitrate == 60 ||
++ sband->bitrates[i].bitrate == 120 ||
++ sband->bitrates[i].bitrate == 240) {
++ sband->bitrates[i].flags |=
++ IEEE80211_RATE_MANDATORY_A;
++ want--;
++ }
++ }
++ WARN_ON(want);
++ break;
++ case IEEE80211_BAND_2GHZ:
++ want = 7;
++ for (i = 0; i < sband->n_bitrates; i++) {
++ if (sband->bitrates[i].bitrate == 10) {
++ sband->bitrates[i].flags |=
++ IEEE80211_RATE_MANDATORY_B |
++ IEEE80211_RATE_MANDATORY_G;
++ want--;
++ }
++
++ if (sband->bitrates[i].bitrate == 20 ||
++ sband->bitrates[i].bitrate == 55 ||
++ sband->bitrates[i].bitrate == 110 ||
++ sband->bitrates[i].bitrate == 60 ||
++ sband->bitrates[i].bitrate == 120 ||
++ sband->bitrates[i].bitrate == 240) {
++ sband->bitrates[i].flags |=
++ IEEE80211_RATE_MANDATORY_G;
++ want--;
++ }
++
++ if (sband->bitrates[i].bitrate != 10 &&
++ sband->bitrates[i].bitrate != 20 &&
++ sband->bitrates[i].bitrate != 55 &&
++ sband->bitrates[i].bitrate != 110)
++ sband->bitrates[i].flags |=
++ IEEE80211_RATE_ERP_G;
++ }
++ WARN_ON(want != 0 && want != 3 && want != 6);
++ break;
++ case IEEE80211_NUM_BANDS:
++ WARN_ON(1);
++ break;
++ }
++}
++
++void ieee80211_set_bitrate_flags(struct wiphy *wiphy)
++{
++ enum ieee80211_band band;
++
++ for (band = 0; band < IEEE80211_NUM_BANDS; band++)
++ if (wiphy->bands[band])
++ set_mandatory_flags_band(wiphy->bands[band], band);
++}
+diff --git a/net/wireless/wext.c b/net/wireless/wext.c
+index 2c569b6..947188a 100644
+--- a/net/wireless/wext.c
++++ b/net/wireless/wext.c
+@@ -1157,7 +1157,7 @@ static void rtmsg_iwinfo(struct net_device *dev, char *event, int event_len)
+ struct sk_buff *skb;
+ int err;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return;
+
+ skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
+diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
+index 339ca4a..6ba67c5 100644
+--- a/net/x25/af_x25.c
++++ b/net/x25/af_x25.c
+@@ -191,7 +191,7 @@ static int x25_device_event(struct notifier_block *this, unsigned long event,
+ struct net_device *dev = ptr;
+ struct x25_neigh *nb;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ if (dev->type == ARPHRD_X25
+@@ -549,7 +549,7 @@ static struct sock *x25_make_new(struct sock *osk)
+ if (osk->sk_type != SOCK_SEQPACKET)
+ goto out;
+
+- if ((sk = x25_alloc_socket(osk->sk_net)) == NULL)
++ if ((sk = x25_alloc_socket(sock_net(osk))) == NULL)
+ goto out;
+
+ x25 = x25_sk(sk);
+diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c
+index f0679d2..3ff206c 100644
+--- a/net/x25/x25_dev.c
++++ b/net/x25/x25_dev.c
+@@ -95,7 +95,7 @@ int x25_lapb_receive_frame(struct sk_buff *skb, struct net_device *dev,
+ struct sk_buff *nskb;
+ struct x25_neigh *nb;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ goto drop;
+
+ nskb = skb_copy(skb, GFP_ATOMIC);
+diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
+index 9fc4c31..e0c0390 100644
+--- a/net/xfrm/xfrm_policy.c
++++ b/net/xfrm/xfrm_policy.c
+@@ -46,6 +46,7 @@ EXPORT_SYMBOL(xfrm_cfg_mutex);
+
+ static DEFINE_RWLOCK(xfrm_policy_lock);
+
++static struct list_head xfrm_policy_bytype[XFRM_POLICY_TYPE_MAX];
+ unsigned int xfrm_policy_count[XFRM_POLICY_MAX*2];
+ EXPORT_SYMBOL(xfrm_policy_count);
+
+@@ -96,25 +97,52 @@ int xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl,
+ return 0;
+ }
+
++static inline struct dst_entry *__xfrm_dst_lookup(int tos,
++ xfrm_address_t *saddr,
++ xfrm_address_t *daddr,
++ int family)
++{
++ struct xfrm_policy_afinfo *afinfo;
++ struct dst_entry *dst;
++
++ afinfo = xfrm_policy_get_afinfo(family);
++ if (unlikely(afinfo == NULL))
++ return ERR_PTR(-EAFNOSUPPORT);
++
++ dst = afinfo->dst_lookup(tos, saddr, daddr);
++
++ xfrm_policy_put_afinfo(afinfo);
++
++ return dst;
++}
++
+ static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x, int tos,
++ xfrm_address_t *prev_saddr,
++ xfrm_address_t *prev_daddr,
+ int family)
+ {
+ xfrm_address_t *saddr = &x->props.saddr;
+ xfrm_address_t *daddr = &x->id.daddr;
+- struct xfrm_policy_afinfo *afinfo;
+ struct dst_entry *dst;
+
+- if (x->type->flags & XFRM_TYPE_LOCAL_COADDR)
++ if (x->type->flags & XFRM_TYPE_LOCAL_COADDR) {
+ saddr = x->coaddr;
+- if (x->type->flags & XFRM_TYPE_REMOTE_COADDR)
++ daddr = prev_daddr;
++ }
++ if (x->type->flags & XFRM_TYPE_REMOTE_COADDR) {
++ saddr = prev_saddr;
+ daddr = x->coaddr;
++ }
+
+- afinfo = xfrm_policy_get_afinfo(family);
+- if (unlikely(afinfo == NULL))
+- return ERR_PTR(-EAFNOSUPPORT);
++ dst = __xfrm_dst_lookup(tos, saddr, daddr, family);
++
++ if (!IS_ERR(dst)) {
++ if (prev_saddr != saddr)
++ memcpy(prev_saddr, saddr, sizeof(*prev_saddr));
++ if (prev_daddr != daddr)
++ memcpy(prev_daddr, daddr, sizeof(*prev_daddr));
++ }
+
+- dst = afinfo->dst_lookup(tos, saddr, daddr);
+- xfrm_policy_put_afinfo(afinfo);
+ return dst;
+ }
+
+@@ -208,6 +236,7 @@ struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp)
+ policy = kzalloc(sizeof(struct xfrm_policy), gfp);
+
+ if (policy) {
++ INIT_LIST_HEAD(&policy->bytype);
+ INIT_HLIST_NODE(&policy->bydst);
+ INIT_HLIST_NODE(&policy->byidx);
+ rwlock_init(&policy->lock);
+@@ -230,7 +259,11 @@ void xfrm_policy_destroy(struct xfrm_policy *policy)
+ if (del_timer(&policy->timer))
+ BUG();
+
+- security_xfrm_policy_free(policy);
++ write_lock_bh(&xfrm_policy_lock);
++ list_del(&policy->bytype);
++ write_unlock_bh(&xfrm_policy_lock);
++
++ security_xfrm_policy_free(policy->security);
+ kfree(policy);
+ }
+ EXPORT_SYMBOL(xfrm_policy_destroy);
+@@ -584,6 +617,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
+ policy->curlft.use_time = 0;
+ if (!mod_timer(&policy->timer, jiffies + HZ))
+ xfrm_pol_hold(policy);
++ list_add_tail(&policy->bytype, &xfrm_policy_bytype[policy->type]);
+ write_unlock_bh(&xfrm_policy_lock);
+
+ if (delpol)
+@@ -642,7 +676,8 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
+ xfrm_sec_ctx_match(ctx, pol->security)) {
+ xfrm_pol_hold(pol);
+ if (delete) {
+- *err = security_xfrm_policy_delete(pol);
++ *err = security_xfrm_policy_delete(
++ pol->security);
+ if (*err) {
+ write_unlock_bh(&xfrm_policy_lock);
+ return pol;
+@@ -684,7 +719,8 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete,
+ if (pol->type == type && pol->index == id) {
+ xfrm_pol_hold(pol);
+ if (delete) {
+- *err = security_xfrm_policy_delete(pol);
++ *err = security_xfrm_policy_delete(
++ pol->security);
+ if (*err) {
+ write_unlock_bh(&xfrm_policy_lock);
+ return pol;
+@@ -722,7 +758,7 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
+ &xfrm_policy_inexact[dir], bydst) {
+ if (pol->type != type)
+ continue;
+- err = security_xfrm_policy_delete(pol);
++ err = security_xfrm_policy_delete(pol->security);
+ if (err) {
+ xfrm_audit_policy_delete(pol, 0,
+ audit_info->loginuid,
+@@ -736,7 +772,8 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
+ bydst) {
+ if (pol->type != type)
+ continue;
+- err = security_xfrm_policy_delete(pol);
++ err = security_xfrm_policy_delete(
++ pol->security);
+ if (err) {
+ xfrm_audit_policy_delete(pol, 0,
+ audit_info->loginuid,
+@@ -822,57 +859,60 @@ out:
+ }
+ EXPORT_SYMBOL(xfrm_policy_flush);
+
+-int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, void*),
++int xfrm_policy_walk(struct xfrm_policy_walk *walk,
++ int (*func)(struct xfrm_policy *, int, int, void*),
+ void *data)
+ {
+- struct xfrm_policy *pol, *last = NULL;
+- struct hlist_node *entry;
+- int dir, last_dir = 0, count, error;
++ struct xfrm_policy *old, *pol, *last = NULL;
++ int error = 0;
+
++ if (walk->type >= XFRM_POLICY_TYPE_MAX &&
++ walk->type != XFRM_POLICY_TYPE_ANY)
++ return -EINVAL;
++
++ if (walk->policy == NULL && walk->count != 0)
++ return 0;
++
++ old = pol = walk->policy;
++ walk->policy = NULL;
+ read_lock_bh(&xfrm_policy_lock);
+- count = 0;
+
+- for (dir = 0; dir < 2*XFRM_POLICY_MAX; dir++) {
+- struct hlist_head *table = xfrm_policy_bydst[dir].table;
+- int i;
++ for (; walk->cur_type < XFRM_POLICY_TYPE_MAX; walk->cur_type++) {
++ if (walk->type != walk->cur_type &&
++ walk->type != XFRM_POLICY_TYPE_ANY)
++ continue;
+
+- hlist_for_each_entry(pol, entry,
+- &xfrm_policy_inexact[dir], bydst) {
+- if (pol->type != type)
++ if (pol == NULL) {
++ pol = list_first_entry(&xfrm_policy_bytype[walk->cur_type],
++ struct xfrm_policy, bytype);
++ }
++ list_for_each_entry_from(pol, &xfrm_policy_bytype[walk->cur_type], bytype) {
++ if (pol->dead)
+ continue;
+ if (last) {
+- error = func(last, last_dir % XFRM_POLICY_MAX,
+- count, data);
+- if (error)
++ error = func(last, xfrm_policy_id2dir(last->index),
++ walk->count, data);
++ if (error) {
++ xfrm_pol_hold(last);
++ walk->policy = last;
+ goto out;
+- }
+- last = pol;
+- last_dir = dir;
+- count++;
+- }
+- for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) {
+- hlist_for_each_entry(pol, entry, table + i, bydst) {
+- if (pol->type != type)
+- continue;
+- if (last) {
+- error = func(last, last_dir % XFRM_POLICY_MAX,
+- count, data);
+- if (error)
+- goto out;
+ }
+- last = pol;
+- last_dir = dir;
+- count++;
+ }
++ last = pol;
++ walk->count++;
+ }
++ pol = NULL;
+ }
+- if (count == 0) {
++ if (walk->count == 0) {
+ error = -ENOENT;
+ goto out;
+ }
+- error = func(last, last_dir % XFRM_POLICY_MAX, 0, data);
++ if (last)
++ error = func(last, xfrm_policy_id2dir(last->index), 0, data);
+ out:
+ read_unlock_bh(&xfrm_policy_lock);
++ if (old != NULL)
++ xfrm_pol_put(old);
+ return error;
+ }
+ EXPORT_SYMBOL(xfrm_policy_walk);
+@@ -894,7 +934,8 @@ static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl,
+
+ match = xfrm_selector_match(sel, fl, family);
+ if (match)
+- ret = security_xfrm_policy_lookup(pol, fl->secid, dir);
++ ret = security_xfrm_policy_lookup(pol->security, fl->secid,
++ dir);
+
+ return ret;
+ }
+@@ -1011,8 +1052,9 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc
+ int err = 0;
+
+ if (match) {
+- err = security_xfrm_policy_lookup(pol, fl->secid,
+- policy_to_flow_dir(dir));
++ err = security_xfrm_policy_lookup(pol->security,
++ fl->secid,
++ policy_to_flow_dir(dir));
+ if (!err)
+ xfrm_pol_hold(pol);
+ else if (err == -ESRCH)
+@@ -1101,7 +1143,8 @@ static struct xfrm_policy *clone_policy(struct xfrm_policy *old, int dir)
+
+ if (newp) {
+ newp->selector = old->selector;
+- if (security_xfrm_policy_clone(old, newp)) {
++ if (security_xfrm_policy_clone(old->security,
++ &newp->security)) {
+ kfree(newp);
+ return NULL; /* ENOMEM */
+ }
+@@ -1344,6 +1387,9 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
+ int trailer_len = 0;
+ int tos;
+ int family = policy->selector.family;
++ xfrm_address_t saddr, daddr;
++
++ xfrm_flowi_addr_get(fl, &saddr, &daddr, family);
+
+ tos = xfrm_get_tos(fl, family);
+ err = tos;
+@@ -1374,7 +1420,8 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
+
+ if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
+ family = xfrm[i]->props.family;
+- dst = xfrm_dst_lookup(xfrm[i], tos, family);
++ dst = xfrm_dst_lookup(xfrm[i], tos, &saddr, &daddr,
++ family);
+ err = PTR_ERR(dst);
+ if (IS_ERR(dst))
+ goto put_states;
+@@ -1772,7 +1819,7 @@ xfrm_state_ok(struct xfrm_tmpl *tmpl, struct xfrm_state *x,
+ (x->id.spi == tmpl->id.spi || !tmpl->id.spi) &&
+ (x->props.reqid == tmpl->reqid || !tmpl->reqid) &&
+ x->props.mode == tmpl->mode &&
+- ((tmpl->aalgos & (1<<x->props.aalgo)) ||
++ (tmpl->allalgs || (tmpl->aalgos & (1<<x->props.aalgo)) ||
+ !(xfrm_id_proto_match(tmpl->id.proto, IPSEC_PROTO_ANY))) &&
+ !(x->props.mode != XFRM_MODE_TRANSPORT &&
+ xfrm_state_addr_cmp(tmpl, x, family));
+@@ -2038,7 +2085,7 @@ static int stale_bundle(struct dst_entry *dst)
+ void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev)
+ {
+ while ((dst = dst->child) && dst->xfrm && dst->dev == dev) {
+- dst->dev = dev->nd_net->loopback_dev;
++ dst->dev = dev_net(dev)->loopback_dev;
+ dev_hold(dst->dev);
+ dev_put(dev);
+ }
+@@ -2309,7 +2356,7 @@ static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void
+ {
+ struct net_device *dev = ptr;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ switch (event) {
+@@ -2365,6 +2412,9 @@ static void __init xfrm_policy_init(void)
+ panic("XFRM: failed to allocate bydst hash\n");
+ }
+
++ for (dir = 0; dir < XFRM_POLICY_TYPE_MAX; dir++)
++ INIT_LIST_HEAD(&xfrm_policy_bytype[dir]);
++
+ INIT_WORK(&xfrm_policy_gc_work, xfrm_policy_gc_task);
+ register_netdevice_notifier(&xfrm_dev_notifier);
+ }
+diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+index 58f1f93..5dcc10b 100644
+--- a/net/xfrm/xfrm_state.c
++++ b/net/xfrm/xfrm_state.c
+@@ -50,6 +50,7 @@ static DEFINE_SPINLOCK(xfrm_state_lock);
+ * Main use is finding SA after policy selected tunnel or transport mode.
+ * Also, it can be used by ah/esp icmp error handler to find offending SA.
+ */
++static LIST_HEAD(xfrm_state_all);
+ static struct hlist_head *xfrm_state_bydst __read_mostly;
+ static struct hlist_head *xfrm_state_bysrc __read_mostly;
+ static struct hlist_head *xfrm_state_byspi __read_mostly;
+@@ -512,6 +513,7 @@ struct xfrm_state *xfrm_state_alloc(void)
+ if (x) {
+ atomic_set(&x->refcnt, 1);
+ atomic_set(&x->tunnel_users, 0);
++ INIT_LIST_HEAD(&x->all);
+ INIT_HLIST_NODE(&x->bydst);
+ INIT_HLIST_NODE(&x->bysrc);
+ INIT_HLIST_NODE(&x->byspi);
+@@ -537,6 +539,10 @@ void __xfrm_state_destroy(struct xfrm_state *x)
+ {
+ BUG_TRAP(x->km.state == XFRM_STATE_DEAD);
+
++ spin_lock_bh(&xfrm_state_lock);
++ list_del(&x->all);
++ spin_unlock_bh(&xfrm_state_lock);
++
+ spin_lock_bh(&xfrm_state_gc_lock);
+ hlist_add_head(&x->bydst, &xfrm_state_gc_list);
+ spin_unlock_bh(&xfrm_state_gc_lock);
+@@ -913,6 +919,8 @@ static void __xfrm_state_insert(struct xfrm_state *x)
+
+ x->genid = ++xfrm_state_genid;
+
++ list_add_tail(&x->all, &xfrm_state_all);
++
+ h = xfrm_dst_hash(&x->id.daddr, &x->props.saddr,
+ x->props.reqid, x->props.family);
+ hlist_add_head(&x->bydst, xfrm_state_bydst+h);
+@@ -1522,36 +1530,47 @@ unlock:
+ }
+ EXPORT_SYMBOL(xfrm_alloc_spi);
+
+-int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*),
++int xfrm_state_walk(struct xfrm_state_walk *walk,
++ int (*func)(struct xfrm_state *, int, void*),
+ void *data)
+ {
+- int i;
+- struct xfrm_state *x, *last = NULL;
+- struct hlist_node *entry;
+- int count = 0;
++ struct xfrm_state *old, *x, *last = NULL;
+ int err = 0;
+
++ if (walk->state == NULL && walk->count != 0)
++ return 0;
++
++ old = x = walk->state;
++ walk->state = NULL;
+ spin_lock_bh(&xfrm_state_lock);
+- for (i = 0; i <= xfrm_state_hmask; i++) {
+- hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
+- if (!xfrm_id_proto_match(x->id.proto, proto))
+- continue;
+- if (last) {
+- err = func(last, count, data);
+- if (err)
+- goto out;
++ if (x == NULL)
++ x = list_first_entry(&xfrm_state_all, struct xfrm_state, all);
++ list_for_each_entry_from(x, &xfrm_state_all, all) {
++ if (x->km.state == XFRM_STATE_DEAD)
++ continue;
++ if (!xfrm_id_proto_match(x->id.proto, walk->proto))
++ continue;
++ if (last) {
++ err = func(last, walk->count, data);
++ if (err) {
++ xfrm_state_hold(last);
++ walk->state = last;
++ goto out;
+ }
+- last = x;
+- count++;
+ }
++ last = x;
++ walk->count++;
+ }
+- if (count == 0) {
++ if (walk->count == 0) {
+ err = -ENOENT;
+ goto out;
+ }
+- err = func(last, 0, data);
++ if (last)
++ err = func(last, 0, data);
+ out:
+ spin_unlock_bh(&xfrm_state_lock);
++ if (old != NULL)
++ xfrm_state_put(old);
+ return err;
+ }
+ EXPORT_SYMBOL(xfrm_state_walk);
+diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
+index 019d21d..22a30ae 100644
+--- a/net/xfrm/xfrm_user.c
++++ b/net/xfrm/xfrm_user.c
+@@ -529,8 +529,6 @@ struct xfrm_dump_info {
+ struct sk_buff *out_skb;
+ u32 nlmsg_seq;
+ u16 nlmsg_flags;
+- int start_idx;
+- int this_idx;
+ };
+
+ static int copy_sec_ctx(struct xfrm_sec_ctx *s, struct sk_buff *skb)
+@@ -597,9 +595,6 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr)
+ struct nlmsghdr *nlh;
+ int err;
+
+- if (sp->this_idx < sp->start_idx)
+- goto out;
+-
+ nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, sp->nlmsg_seq,
+ XFRM_MSG_NEWSA, sizeof(*p), sp->nlmsg_flags);
+ if (nlh == NULL)
+@@ -612,8 +607,6 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr)
+ goto nla_put_failure;
+
+ nlmsg_end(skb, nlh);
+-out:
+- sp->this_idx++;
+ return 0;
+
+ nla_put_failure:
+@@ -621,18 +614,32 @@ nla_put_failure:
+ return err;
+ }
+
++static int xfrm_dump_sa_done(struct netlink_callback *cb)
++{
++ struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1];
++ xfrm_state_walk_done(walk);
++ return 0;
++}
++
+ static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb)
+ {
++ struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1];
+ struct xfrm_dump_info info;
+
++ BUILD_BUG_ON(sizeof(struct xfrm_state_walk) >
++ sizeof(cb->args) - sizeof(cb->args[0]));
++
+ info.in_skb = cb->skb;
+ info.out_skb = skb;
+ info.nlmsg_seq = cb->nlh->nlmsg_seq;
+ info.nlmsg_flags = NLM_F_MULTI;
+- info.this_idx = 0;
+- info.start_idx = cb->args[0];
+- (void) xfrm_state_walk(0, dump_one_state, &info);
+- cb->args[0] = info.this_idx;
++
++ if (!cb->args[0]) {
++ cb->args[0] = 1;
++ xfrm_state_walk_init(walk, 0);
++ }
++
++ (void) xfrm_state_walk(walk, dump_one_state, &info);
+
+ return skb->len;
+ }
+@@ -651,7 +658,6 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb,
+ info.out_skb = skb;
+ info.nlmsg_seq = seq;
+ info.nlmsg_flags = 0;
+- info.this_idx = info.start_idx = 0;
+
+ if (dump_one_state(x, 0, &info)) {
+ kfree_skb(skb);
+@@ -953,7 +959,7 @@ static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct nlattr **attrs
+ return 0;
+
+ uctx = nla_data(rt);
+- return security_xfrm_policy_alloc(pol, uctx);
++ return security_xfrm_policy_alloc(&pol->security, uctx);
+ }
+
+ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
+@@ -975,6 +981,8 @@ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
+ t->aalgos = ut->aalgos;
+ t->ealgos = ut->ealgos;
+ t->calgos = ut->calgos;
++ /* If all masks are ~0, then we allow all algorithms. */
++ t->allalgs = !~(t->aalgos & t->ealgos & t->calgos);
+ t->encap_family = ut->family;
+ }
+ }
+@@ -1137,7 +1145,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
+ NETLINK_CB(skb).sid);
+
+ if (err) {
+- security_xfrm_policy_free(xp);
++ security_xfrm_policy_free(xp->security);
+ kfree(xp);
+ return err;
+ }
+@@ -1229,9 +1237,6 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr
+ struct sk_buff *skb = sp->out_skb;
+ struct nlmsghdr *nlh;
+
+- if (sp->this_idx < sp->start_idx)
+- goto out;
+-
+ nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, sp->nlmsg_seq,
+ XFRM_MSG_NEWPOLICY, sizeof(*p), sp->nlmsg_flags);
+ if (nlh == NULL)
+@@ -1247,8 +1252,6 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr
+ goto nlmsg_failure;
+
+ nlmsg_end(skb, nlh);
+-out:
+- sp->this_idx++;
+ return 0;
+
+ nlmsg_failure:
+@@ -1256,21 +1259,33 @@ nlmsg_failure:
+ return -EMSGSIZE;
+ }
+
++static int xfrm_dump_policy_done(struct netlink_callback *cb)
++{
++ struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1];
++
++ xfrm_policy_walk_done(walk);
++ return 0;
++}
++
+ static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb)
+ {
++ struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1];
+ struct xfrm_dump_info info;
+
++ BUILD_BUG_ON(sizeof(struct xfrm_policy_walk) >
++ sizeof(cb->args) - sizeof(cb->args[0]));
++
+ info.in_skb = cb->skb;
+ info.out_skb = skb;
+ info.nlmsg_seq = cb->nlh->nlmsg_seq;
+ info.nlmsg_flags = NLM_F_MULTI;
+- info.this_idx = 0;
+- info.start_idx = cb->args[0];
+- (void) xfrm_policy_walk(XFRM_POLICY_TYPE_MAIN, dump_one_policy, &info);
+-#ifdef CONFIG_XFRM_SUB_POLICY
+- (void) xfrm_policy_walk(XFRM_POLICY_TYPE_SUB, dump_one_policy, &info);
+-#endif
+- cb->args[0] = info.this_idx;
++
++ if (!cb->args[0]) {
++ cb->args[0] = 1;
++ xfrm_policy_walk_init(walk, XFRM_POLICY_TYPE_ANY);
++ }
++
++ (void) xfrm_policy_walk(walk, dump_one_policy, &info);
+
+ return skb->len;
+ }
+@@ -1290,7 +1305,6 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb,
+ info.out_skb = skb;
+ info.nlmsg_seq = seq;
+ info.nlmsg_flags = 0;
+- info.this_idx = info.start_idx = 0;
+
+ if (dump_one_policy(xp, dir, 0, &info) < 0) {
+ kfree_skb(skb);
+@@ -1325,22 +1339,23 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
+ xp = xfrm_policy_byid(type, p->dir, p->index, delete, &err);
+ else {
+ struct nlattr *rt = attrs[XFRMA_SEC_CTX];
+- struct xfrm_policy tmp;
++ struct xfrm_sec_ctx *ctx;
+
+ err = verify_sec_ctx_len(attrs);
+ if (err)
+ return err;
+
+- memset(&tmp, 0, sizeof(struct xfrm_policy));
++ ctx = NULL;
+ if (rt) {
+ struct xfrm_user_sec_ctx *uctx = nla_data(rt);
+
+- if ((err = security_xfrm_policy_alloc(&tmp, uctx)))
++ err = security_xfrm_policy_alloc(&ctx, uctx);
++ if (err)
+ return err;
+ }
+- xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security,
++ xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, ctx,
+ delete, &err);
+- security_xfrm_policy_free(&tmp);
++ security_xfrm_policy_free(ctx);
+ }
+ if (xp == NULL)
+ return -ENOENT;
+@@ -1560,26 +1575,26 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
+ xp = xfrm_policy_byid(type, p->dir, p->index, 0, &err);
+ else {
+ struct nlattr *rt = attrs[XFRMA_SEC_CTX];
+- struct xfrm_policy tmp;
++ struct xfrm_sec_ctx *ctx;
+
+ err = verify_sec_ctx_len(attrs);
+ if (err)
+ return err;
+
+- memset(&tmp, 0, sizeof(struct xfrm_policy));
++ ctx = NULL;
+ if (rt) {
+ struct xfrm_user_sec_ctx *uctx = nla_data(rt);
+
+- if ((err = security_xfrm_policy_alloc(&tmp, uctx)))
++ err = security_xfrm_policy_alloc(&ctx, uctx);
++ if (err)
+ return err;
+ }
+- xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security,
+- 0, &err);
+- security_xfrm_policy_free(&tmp);
++ xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, ctx, 0, &err);
++ security_xfrm_policy_free(ctx);
+ }
+-
+ if (xp == NULL)
+ return -ENOENT;
++
+ read_lock(&xp->lock);
+ if (xp->dead) {
+ read_unlock(&xp->lock);
+@@ -1888,15 +1903,18 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
+ static struct xfrm_link {
+ int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **);
+ int (*dump)(struct sk_buff *, struct netlink_callback *);
++ int (*done)(struct netlink_callback *);
+ } xfrm_dispatch[XFRM_NR_MSGTYPES] = {
+ [XFRM_MSG_NEWSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa },
+ [XFRM_MSG_DELSA - XFRM_MSG_BASE] = { .doit = xfrm_del_sa },
+ [XFRM_MSG_GETSA - XFRM_MSG_BASE] = { .doit = xfrm_get_sa,
+- .dump = xfrm_dump_sa },
++ .dump = xfrm_dump_sa,
++ .done = xfrm_dump_sa_done },
+ [XFRM_MSG_NEWPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_add_policy },
+ [XFRM_MSG_DELPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy },
+ [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy,
+- .dump = xfrm_dump_policy },
++ .dump = xfrm_dump_policy,
++ .done = xfrm_dump_policy_done },
+ [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi },
+ [XFRM_MSG_ACQUIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_acquire },
+ [XFRM_MSG_EXPIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_sa_expire },
+@@ -1935,7 +1953,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ if (link->dump == NULL)
+ return -EINVAL;
+
+- return netlink_dump_start(xfrm_nl, skb, nlh, link->dump, NULL);
++ return netlink_dump_start(xfrm_nl, skb, nlh, link->dump, link->done);
+ }
+
+ err = nlmsg_parse(nlh, xfrm_msg_min[type], attrs, XFRMA_MAX,
+diff --git a/samples/firmware_class/firmware_sample_driver.c b/samples/firmware_class/firmware_sample_driver.c
+new file mode 100644
+index 0000000..11114f3
+--- /dev/null
++++ b/samples/firmware_class/firmware_sample_driver.c
+@@ -0,0 +1,121 @@
++/*
++ * firmware_sample_driver.c -
++ *
++ * Copyright (c) 2003 Manuel Estrada Sainz
++ *
++ * Sample code on how to use request_firmware() from drivers.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/device.h>
++#include <linux/string.h>
++#include <linux/firmware.h>
++
++static struct device ghost_device = {
++ .bus_id = "ghost0",
++};
++
++
++static void sample_firmware_load(char *firmware, int size)
++{
++ u8 buf[size+1];
++ memcpy(buf, firmware, size);
++ buf[size] = '\0';
++ printk(KERN_INFO "firmware_sample_driver: firmware: %s\n", buf);
++}
++
++static void sample_probe_default(void)
++{
++ /* uses the default method to get the firmware */
++ const struct firmware *fw_entry;
++ int retval;
++
++ printk(KERN_INFO "firmware_sample_driver: "
++ "a ghost device got inserted :)\n");
++
++ retval = request_firmware(&fw_entry, "sample_driver_fw", &ghost_device);
++ if (retval) {
++ printk(KERN_ERR
++ "firmware_sample_driver: Firmware not available\n");
++ return;
++ }
++
++ sample_firmware_load(fw_entry->data, fw_entry->size);
++
++ release_firmware(fw_entry);
++
++ /* finish setting up the device */
++}
++
++static void sample_probe_specific(void)
++{
++ int retval;
++ /* Uses some specific hotplug support to get the firmware from
++ * userspace directly into the hardware, or via some sysfs file */
++
++ /* NOTE: This currently doesn't work */
++
++ printk(KERN_INFO "firmware_sample_driver: "
++ "a ghost device got inserted :)\n");
++
++ retval = request_firmware(NULL, "sample_driver_fw", &ghost_device);
++ if (retval) {
++ printk(KERN_ERR
++ "firmware_sample_driver: Firmware load failed\n");
++ return;
++ }
++
++ /* request_firmware blocks until userspace finished, so at
++ * this point the firmware should be already in the device */
++
++ /* finish setting up the device */
++}
++
++static void sample_probe_async_cont(const struct firmware *fw, void *context)
++{
++ if (!fw) {
++ printk(KERN_ERR
++ "firmware_sample_driver: firmware load failed\n");
++ return;
++ }
++
++ printk(KERN_INFO "firmware_sample_driver: device pointer \"%s\"\n",
++ (char *)context);
++ sample_firmware_load(fw->data, fw->size);
++}
++
++static void sample_probe_async(void)
++{
++ /* Let's say that I can't sleep */
++ int error;
++ error = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
++ "sample_driver_fw", &ghost_device,
++ "my device pointer",
++ sample_probe_async_cont);
++ if (error)
++ printk(KERN_ERR "firmware_sample_driver:"
++ " request_firmware_nowait failed\n");
++}
++
++static int sample_init(void)
++{
++ device_initialize(&ghost_device);
++ /* since there is no real hardware insertion I just call the
++ * sample probe functions here */
++ sample_probe_specific();
++ sample_probe_default();
++ sample_probe_async();
++ return 0;
++}
++
++static void __exit sample_exit(void)
++{
++}
++
++module_init(sample_init);
++module_exit(sample_exit);
++
++MODULE_LICENSE("GPL");
+diff --git a/samples/firmware_class/firmware_sample_firmware_class.c b/samples/firmware_class/firmware_sample_firmware_class.c
+new file mode 100644
+index 0000000..9392116
+--- /dev/null
++++ b/samples/firmware_class/firmware_sample_firmware_class.c
+@@ -0,0 +1,204 @@
++/*
++ * firmware_sample_firmware_class.c -
++ *
++ * Copyright (c) 2003 Manuel Estrada Sainz
++ *
++ * NOTE: This is just a probe of concept, if you think that your driver would
++ * be well served by this mechanism please contact me first.
++ *
++ * DON'T USE THIS CODE AS IS
++ *
++ */
++
++#include <linux/device.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/timer.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/firmware.h>
++
++
++MODULE_AUTHOR("Manuel Estrada Sainz");
++MODULE_DESCRIPTION("Hackish sample for using firmware class directly");
++MODULE_LICENSE("GPL");
++
++static inline struct class_device *to_class_dev(struct kobject *obj)
++{
++ return container_of(obj, struct class_device, kobj);
++}
++
++static inline
++struct class_device_attribute *to_class_dev_attr(struct attribute *_attr)
++{
++ return container_of(_attr, struct class_device_attribute, attr);
++}
++
++struct firmware_priv {
++ char fw_id[FIRMWARE_NAME_MAX];
++ s32 loading:2;
++ u32 abort:1;
++};
++
++static ssize_t firmware_loading_show(struct class_device *class_dev, char *buf)
++{
++ struct firmware_priv *fw_priv = class_get_devdata(class_dev);
++ return sprintf(buf, "%d\n", fw_priv->loading);
++}
++
++static ssize_t firmware_loading_store(struct class_device *class_dev,
++ const char *buf, size_t count)
++{
++ struct firmware_priv *fw_priv = class_get_devdata(class_dev);
++ int prev_loading = fw_priv->loading;
++
++ fw_priv->loading = simple_strtol(buf, NULL, 10);
++
++ switch (fw_priv->loading) {
++ case -1:
++ /* abort load an panic */
++ break;
++ case 1:
++ /* setup load */
++ break;
++ case 0:
++ if (prev_loading == 1) {
++ /* finish load and get the device back to working
++ * state */
++ }
++ break;
++ }
++
++ return count;
++}
++static CLASS_DEVICE_ATTR(loading, 0644,
++ firmware_loading_show, firmware_loading_store);
++
++static ssize_t firmware_data_read(struct kobject *kobj,
++ struct bin_attribute *bin_attr,
++ char *buffer, loff_t offset, size_t count)
++{
++ struct class_device *class_dev = to_class_dev(kobj);
++ struct firmware_priv *fw_priv = class_get_devdata(class_dev);
++
++ /* read from the devices firmware memory */
++
++ return count;
++}
++static ssize_t firmware_data_write(struct kobject *kobj,
++ struct bin_attribute *bin_attr,
++ char *buffer, loff_t offset, size_t count)
++{
++ struct class_device *class_dev = to_class_dev(kobj);
++ struct firmware_priv *fw_priv = class_get_devdata(class_dev);
++
++ /* write to the devices firmware memory */
++
++ return count;
++}
++static struct bin_attribute firmware_attr_data = {
++ .attr = {.name = "data", .mode = 0644},
++ .size = 0,
++ .read = firmware_data_read,
++ .write = firmware_data_write,
++};
++static int fw_setup_class_device(struct class_device *class_dev,
++ const char *fw_name,
++ struct device *device)
++{
++ int retval;
++ struct firmware_priv *fw_priv;
++
++ fw_priv = kzalloc(sizeof(struct firmware_priv), GFP_KERNEL);
++ if (!fw_priv) {
++ retval = -ENOMEM;
++ goto out;
++ }
++
++ memset(class_dev, 0, sizeof(*class_dev));
++
++ strncpy(fw_priv->fw_id, fw_name, FIRMWARE_NAME_MAX);
++ fw_priv->fw_id[FIRMWARE_NAME_MAX-1] = '\0';
++
++ strncpy(class_dev->class_id, device->bus_id, BUS_ID_SIZE);
++ class_dev->class_id[BUS_ID_SIZE-1] = '\0';
++ class_dev->dev = device;
++
++ class_dev->class = &firmware_class,
++ class_set_devdata(class_dev, fw_priv);
++ retval = class_device_register(class_dev);
++ if (retval) {
++ printk(KERN_ERR "%s: class_device_register failed\n",
++ __func__);
++ goto error_free_fw_priv;
++ }
++
++ retval = sysfs_create_bin_file(&class_dev->kobj, &firmware_attr_data);
++ if (retval) {
++ printk(KERN_ERR "%s: sysfs_create_bin_file failed\n",
++ __func__);
++ goto error_unreg_class_dev;
++ }
++
++ retval = class_device_create_file(class_dev,
++ &class_device_attr_loading);
++ if (retval) {
++ printk(KERN_ERR "%s: class_device_create_file failed\n",
++ __func__);
++ goto error_remove_data;
++ }
++
++ goto out;
++
++error_remove_data:
++ sysfs_remove_bin_file(&class_dev->kobj, &firmware_attr_data);
++error_unreg_class_dev:
++ class_device_unregister(class_dev);
++error_free_fw_priv:
++ kfree(fw_priv);
++out:
++ return retval;
++}
++static void fw_remove_class_device(struct class_device *class_dev)
++{
++ struct firmware_priv *fw_priv = class_get_devdata(class_dev);
++
++ class_device_remove_file(class_dev, &class_device_attr_loading);
++ sysfs_remove_bin_file(&class_dev->kobj, &firmware_attr_data);
++ class_device_unregister(class_dev);
++}
++
++static struct class_device *class_dev;
++
++static struct device my_device = {
++ .bus_id = "my_dev0",
++};
++
++static int __init firmware_sample_init(void)
++{
++ int error;
++
++ device_initialize(&my_device);
++ class_dev = kmalloc(sizeof(struct class_device), GFP_KERNEL);
++ if (!class_dev)
++ return -ENOMEM;
++
++ error = fw_setup_class_device(class_dev, "my_firmware_image",
++ &my_device);
++ if (error) {
++ kfree(class_dev);
++ return error;
++ }
++ return 0;
++
++}
++static void __exit firmware_sample_exit(void)
++{
++ struct firmware_priv *fw_priv = class_get_devdata(class_dev);
++ fw_remove_class_device(class_dev);
++ kfree(fw_priv);
++ kfree(class_dev);
++}
++
++module_init(firmware_sample_init);
++module_exit(firmware_sample_exit);
+diff --git a/scripts/Makefile.build b/scripts/Makefile.build
+index 67fb453..277cfe0 100644
+--- a/scripts/Makefile.build
++++ b/scripts/Makefile.build
+@@ -27,12 +27,12 @@ ccflags-y :=
+ cppflags-y :=
+ ldflags-y :=
+
+-# Read .config if it exist, otherwise ignore
++# Read auto.conf if it exists, otherwise ignore
+ -include include/config/auto.conf
+
+ include scripts/Kbuild.include
+
+-# For backward compatibility check that these variables does not change
++# For backward compatibility check that these variables do not change
+ save-cflags := $(CFLAGS)
+
+ # The filename Kbuild has precedence over Makefile
+@@ -55,7 +55,7 @@ hostprogs-y += $(host-progs)
+ endif
+ endif
+
+-# Do not include host rules unles needed
++# Do not include host rules unless needed
+ ifneq ($(hostprogs-y)$(hostprogs-m),)
+ include scripts/Makefile.host
+ endif
+diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
+index 2c64710..6f89fbb 100644
+--- a/scripts/Makefile.clean
++++ b/scripts/Makefile.clean
+@@ -37,7 +37,7 @@ subdir-ymn := $(sort $(subdir-ym) $(subdir-n) $(subdir-))
+
+ subdir-ymn := $(addprefix $(obj)/,$(subdir-ymn))
+
+-# build a list of files to remove, usually releative to the current
++# build a list of files to remove, usually relative to the current
+ # directory
+
+ __clean-files := $(extra-y) $(always) \
+diff --git a/scripts/Makefile.host b/scripts/Makefile.host
+index 6943a7a..1ac414f 100644
+--- a/scripts/Makefile.host
++++ b/scripts/Makefile.host
+@@ -3,9 +3,9 @@
+ # Binaries are used during the compilation of the kernel, for example
+ # to preprocess a data file.
+ #
+-# Both C and C++ is supported, but preferred language is C for such utilities.
++# Both C and C++ are supported, but preferred language is C for such utilities.
+ #
+-# Samle syntax (see Documentation/kbuild/makefile.txt for reference)
++# Sample syntax (see Documentation/kbuild/makefiles.txt for reference)
+ # hostprogs-y := bin2hex
+ # Will compile bin2hex.c and create an executable named bin2hex
+ #
+@@ -23,10 +23,10 @@
+ # hostprogs-y := conf
+ # conf-objs := conf.o libkconfig.so
+ # libkconfig-objs := expr.o type.o
+-# Will create a shared library named libkconfig.so that consist of
+-# expr.o and type.o (they are both compiled as C code and the object file
++# Will create a shared library named libkconfig.so that consists of
++# expr.o and type.o (they are both compiled as C code and the object files
+ # are made as position independent code).
+-# conf.c is compiled as a c program, and conf.o is linked together with
++# conf.c is compiled as a C program, and conf.o is linked together with
+ # libkconfig.so as the executable conf.
+ # Note: Shared libraries consisting of C++ files are not supported
+
+@@ -61,7 +61,7 @@ host-cobjs := $(filter-out %.so,$(host-cobjs))
+ host-cshobjs := $(sort $(foreach m,$(host-cshlib),$($(m:.so=-objs))))
+
+ # output directory for programs/.o files
+-# hostprogs-y := tools/build may have been specified. Retreive directory
++# hostprogs-y := tools/build may have been specified. Retrieve directory
+ host-objdirs := $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f))))
+ # directory of .o files from prog-objs notation
+ host-objdirs += $(foreach f,$(host-cmulti), \
+diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
+index 2d20640..24b3c8f 100644
+--- a/scripts/Makefile.modpost
++++ b/scripts/Makefile.modpost
+@@ -42,6 +42,13 @@ _modpost: __modpost
+
+ include include/config/auto.conf
+ include scripts/Kbuild.include
++
++ifneq ($(KBUILD_EXTMOD),)
++# Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS
++include $(if $(wildcard $(KBUILD_EXTMOD)/Kbuild), \
++ $(KBUILD_EXTMOD)/Kbuild, $(KBUILD_EXTMOD)/Makefile)
++endif
++
+ include scripts/Makefile.lib
+
+ kernelsymfile := $(objtree)/Module.symvers
+@@ -69,6 +76,7 @@ modpost = scripts/mod/modpost \
+ $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,) \
+ $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \
+ $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \
++ $(if $(iKBUILD_EXTRA_SYMBOLS), $(patsubst %, -e %,$(EXTRA_SYMBOLS))) \
+ $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
+ $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S) \
+ $(if $(CONFIG_MARKERS),-K $(kernelmarkersfile)) \
+diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
+index 58a9494..64ec4b8 100755
+--- a/scripts/checkpatch.pl
++++ b/scripts/checkpatch.pl
+@@ -1889,6 +1889,13 @@ sub process {
+ WARN("kfree(NULL) is safe this check is probabally not required\n" . $hereprev);
+ }
+ }
++# check for needless usb_free_urb() checks
++ if ($prevline =~ /\bif\s*\(([^\)]*)\)/) {
++ my $expr = $1;
++ if ($line =~ /\busb_free_urb\(\Q$expr\E\);/) {
++ WARN("usb_free_urb(NULL) is safe this check is probabally not required\n" . $hereprev);
++ }
++ }
+
+ # warn about #ifdefs in C files
+ # if ($line =~ /^.#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
+diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
+index 32e8c5a..fa1a7d5 100644
+--- a/scripts/kconfig/Makefile
++++ b/scripts/kconfig/Makefile
+@@ -36,10 +36,10 @@ update-po-config: $(obj)/kxgettext $(obj)/gconf.glade.h
+ --output $(obj)/config.pot
+ $(Q)sed -i s/CHARSET/UTF-8/ $(obj)/config.pot
+ $(Q)ln -fs Kconfig.i386 arch/um/Kconfig.arch
+- $(Q)(for i in `ls arch/`; \
++ $(Q)(for i in `ls arch/*/Kconfig`; \
+ do \
+ echo " GEN $$i"; \
+- $(obj)/kxgettext arch/$$i/Kconfig \
++ $(obj)/kxgettext $$i \
+ >> $(obj)/config.pot; \
+ done )
+ $(Q)msguniq --sort-by-file --to-code=UTF-8 $(obj)/config.pot \
+diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
+index 348d868..769b69d 100644
+--- a/scripts/mod/file2alias.c
++++ b/scripts/mod/file2alias.c
+@@ -328,19 +328,52 @@ static int do_pnp_entry(const char *filename,
+ return 1;
+ }
+
+-/* looks like: "pnp:cCdD..." */
+-static int do_pnp_card_entry(const char *filename,
+- struct pnp_card_device_id *id, char *alias)
++/* looks like: "pnp:dD" for every device of the card */
++static void do_pnp_card_entries(void *symval, unsigned long size,
++ struct module *mod)
+ {
+- int i;
++ const unsigned long id_size = sizeof(struct pnp_card_device_id);
++ const unsigned int count = (size / id_size)-1;
++ const struct pnp_card_device_id *cards = symval;
++ unsigned int i;
+
+- sprintf(alias, "pnp:c%s", id->id);
+- for (i = 0; i < PNP_MAX_DEVICES; i++) {
+- if (! *id->devs[i].id)
+- break;
+- sprintf(alias + strlen(alias), "d%s", id->devs[i].id);
++ device_id_check(mod->name, "pnp", size, id_size, symval);
++
++ for (i = 0; i < count; i++) {
++ unsigned int j;
++ const struct pnp_card_device_id *card = &cards[i];
++
++ for (j = 0; j < PNP_MAX_DEVICES; j++) {
++ const char *id = (char *)card->devs[j].id;
++ int i2, j2;
++ int dup = 0;
++
++ if (!id[0])
++ break;
++
++ /* find duplicate, already added value */
++ for (i2 = 0; i2 < i && !dup; i2++) {
++ const struct pnp_card_device_id *card2 = &cards[i2];
++
++ for (j2 = 0; j2 < PNP_MAX_DEVICES; j2++) {
++ const char *id2 = (char *)card2->devs[j2].id;
++
++ if (!id2[0])
++ break;
++
++ if (!strcmp(id, id2)) {
++ dup = 1;
++ break;
++ }
++ }
++ }
++
++ /* add an individual alias for every device entry */
++ if (!dup)
++ buf_printf(&mod->dev_table_buf,
++ "MODULE_ALIAS(\"pnp:d%s*\");\n", id);
++ }
+ }
+- return 1;
+ }
+
+ /* Looks like: pcmcia:mNcNfNfnNpfnNvaNvbNvcNvdN. */
+@@ -634,9 +667,7 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
+ sizeof(struct pnp_device_id), "pnp",
+ do_pnp_entry, mod);
+ else if (sym_is(symname, "__mod_pnp_card_device_table"))
+- do_table(symval, sym->st_size,
+- sizeof(struct pnp_card_device_id), "pnp_card",
+- do_pnp_card_entry, mod);
++ do_pnp_card_entries(symval, sym->st_size, mod);
+ else if (sym_is(symname, "__mod_pcmcia_device_table"))
+ do_table(symval, sym->st_size,
+ sizeof(struct pcmcia_device_id), "pcmcia",
+diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
+index 110cf24..f8b42ab 100644
+--- a/scripts/mod/modpost.c
++++ b/scripts/mod/modpost.c
+@@ -1552,6 +1552,10 @@ static void read_symbols(char *modname)
+ }
+
+ license = get_modinfo(info.modinfo, info.modinfo_len, "license");
++ if (!license && !is_vmlinux(modname))
++ fatal("modpost: missing MODULE_LICENSE() in %s\n"
++ "see include/linux/module.h for "
++ "more information\n", modname);
+ while (license) {
+ if (license_is_gpl_compatible(license))
+ mod->gpl_compatible = 1;
+@@ -2015,6 +2019,11 @@ static void write_markers(const char *fname)
+ write_if_changed(&buf, fname);
+ }
+
++struct ext_sym_list {
++ struct ext_sym_list *next;
++ const char *file;
++};
++
+ int main(int argc, char **argv)
+ {
+ struct module *mod;
+@@ -2025,8 +2034,10 @@ int main(int argc, char **argv)
+ char *markers_write = NULL;
+ int opt;
+ int err;
++ struct ext_sym_list *extsym_iter;
++ struct ext_sym_list *extsym_start = NULL;
+
+- while ((opt = getopt(argc, argv, "i:I:cmsSo:awM:K:")) != -1) {
++ while ((opt = getopt(argc, argv, "i:I:e:cmsSo:awM:K:")) != -1) {
+ switch (opt) {
+ case 'i':
+ kernel_read = optarg;
+@@ -2038,6 +2049,14 @@ int main(int argc, char **argv)
+ case 'c':
+ cross_build = 1;
+ break;
++ case 'e':
++ external_module = 1;
++ extsym_iter =
++ NOFAIL(malloc(sizeof(*extsym_iter)));
++ extsym_iter->next = extsym_start;
++ extsym_iter->file = optarg;
++ extsym_start = extsym_iter;
++ break;
+ case 'm':
+ modversions = 1;
+ break;
+@@ -2071,6 +2090,12 @@ int main(int argc, char **argv)
+ read_dump(kernel_read, 1);
+ if (module_read)
+ read_dump(module_read, 0);
++ while (extsym_start) {
++ read_dump(extsym_start->file, 0);
++ extsym_iter = extsym_start->next;
++ free(extsym_start);
++ extsym_start = extsym_iter;
++ }
+
+ while (optind < argc)
+ read_symbols(argv[optind++]);
+diff --git a/security/Kconfig b/security/Kconfig
+index 5dfc206..49b51f9 100644
+--- a/security/Kconfig
++++ b/security/Kconfig
+@@ -113,10 +113,12 @@ config SECURITY_DEFAULT_MMAP_MIN_ADDR
+ from userspace allocation. Keeping a user from writing to low pages
+ can help reduce the impact of kernel NULL pointer bugs.
+
+- For most users with lots of address space a value of 65536 is
+- reasonable and should cause no problems. Programs which use vm86
+- functionality would either need additional permissions from either
+- the LSM or the capabilities module or have this protection disabled.
++ For most ia64, ppc64 and x86 users with lots of address space
++ a value of 65536 is reasonable and should cause no problems.
++ On arm and other archs it should not be higher than 32768.
++ Programs which use vm86 functionality would either need additional
++ permissions from either the LSM or the capabilities module or have
++ this protection disabled.
+
+ This value can be changed after boot using the
+ /proc/sys/vm/mmap_min_addr tunable.
+diff --git a/security/commoncap.c b/security/commoncap.c
+index 06d5c94..8529057 100644
+--- a/security/commoncap.c
++++ b/security/commoncap.c
+@@ -267,7 +267,7 @@ static int get_file_caps(struct linux_binprm *bprm)
+ rc = cap_from_disk(&vcaps, bprm, rc);
+ if (rc)
+ printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n",
+- __FUNCTION__, rc, bprm->filename);
++ __func__, rc, bprm->filename);
+
+ out:
+ dput(dentry);
+@@ -302,7 +302,7 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
+ ret = get_file_caps(bprm);
+ if (ret)
+ printk(KERN_NOTICE "%s: get_file_caps returned %d for %s\n",
+- __FUNCTION__, ret, bprm->filename);
++ __func__, ret, bprm->filename);
+
+ /* To support inheritance of root-permissions and suid-root
+ * executables under compatibility mode, we raise all three
+diff --git a/security/dummy.c b/security/dummy.c
+index 78d8f92..b0232bb 100644
+--- a/security/dummy.c
++++ b/security/dummy.c
+@@ -196,13 +196,13 @@ static int dummy_sb_statfs (struct dentry *dentry)
+ return 0;
+ }
+
+-static int dummy_sb_mount (char *dev_name, struct nameidata *nd, char *type,
++static int dummy_sb_mount (char *dev_name, struct path *path, char *type,
+ unsigned long flags, void *data)
+ {
+ return 0;
+ }
+
+-static int dummy_sb_check_sb (struct vfsmount *mnt, struct nameidata *nd)
++static int dummy_sb_check_sb (struct vfsmount *mnt, struct path *path)
+ {
+ return 0;
+ }
+@@ -229,17 +229,17 @@ static void dummy_sb_post_remount (struct vfsmount *mnt, unsigned long flags,
+ }
+
+
+-static void dummy_sb_post_addmount (struct vfsmount *mnt, struct nameidata *nd)
++static void dummy_sb_post_addmount (struct vfsmount *mnt, struct path *path)
+ {
+ return;
+ }
+
+-static int dummy_sb_pivotroot (struct nameidata *old_nd, struct nameidata *new_nd)
++static int dummy_sb_pivotroot (struct path *old_path, struct path *new_path)
+ {
+ return 0;
+ }
+
+-static void dummy_sb_post_pivotroot (struct nameidata *old_nd, struct nameidata *new_nd)
++static void dummy_sb_post_pivotroot (struct path *old_path, struct path *new_path)
+ {
+ return;
+ }
+@@ -424,6 +424,11 @@ static int dummy_inode_listsecurity(struct inode *inode, char *buffer, size_t bu
+ return 0;
+ }
+
++static void dummy_inode_getsecid(const struct inode *inode, u32 *secid)
++{
++ *secid = 0;
++}
++
+ static int dummy_file_permission (struct file *file, int mask)
+ {
+ return 0;
+@@ -542,7 +547,9 @@ static int dummy_task_getsid (struct task_struct *p)
+ }
+
+ static void dummy_task_getsecid (struct task_struct *p, u32 *secid)
+-{ }
++{
++ *secid = 0;
++}
+
+ static int dummy_task_setgroups (struct group_info *group_info)
+ {
+@@ -616,6 +623,11 @@ static int dummy_ipc_permission (struct kern_ipc_perm *ipcp, short flag)
+ return 0;
+ }
+
++static void dummy_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
++{
++ *secid = 0;
++}
++
+ static int dummy_msg_msg_alloc_security (struct msg_msg *msg)
+ {
+ return 0;
+@@ -876,22 +888,23 @@ static inline void dummy_req_classify_flow(const struct request_sock *req,
+ #endif /* CONFIG_SECURITY_NETWORK */
+
+ #ifdef CONFIG_SECURITY_NETWORK_XFRM
+-static int dummy_xfrm_policy_alloc_security(struct xfrm_policy *xp,
+- struct xfrm_user_sec_ctx *sec_ctx)
++static int dummy_xfrm_policy_alloc_security(struct xfrm_sec_ctx **ctxp,
++ struct xfrm_user_sec_ctx *sec_ctx)
+ {
+ return 0;
+ }
+
+-static inline int dummy_xfrm_policy_clone_security(struct xfrm_policy *old, struct xfrm_policy *new)
++static inline int dummy_xfrm_policy_clone_security(struct xfrm_sec_ctx *old_ctx,
++ struct xfrm_sec_ctx **new_ctxp)
+ {
+ return 0;
+ }
+
+-static void dummy_xfrm_policy_free_security(struct xfrm_policy *xp)
++static void dummy_xfrm_policy_free_security(struct xfrm_sec_ctx *ctx)
+ {
+ }
+
+-static int dummy_xfrm_policy_delete_security(struct xfrm_policy *xp)
++static int dummy_xfrm_policy_delete_security(struct xfrm_sec_ctx *ctx)
+ {
+ return 0;
+ }
+@@ -911,7 +924,8 @@ static int dummy_xfrm_state_delete_security(struct xfrm_state *x)
+ return 0;
+ }
+
+-static int dummy_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir)
++static int dummy_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx,
++ u32 sk_sid, u8 dir)
+ {
+ return 0;
+ }
+@@ -981,7 +995,33 @@ static inline int dummy_key_permission(key_ref_t key_ref,
+ }
+ #endif /* CONFIG_KEYS */
+
+-struct security_operations dummy_security_ops;
++#ifdef CONFIG_AUDIT
++static inline int dummy_audit_rule_init(u32 field, u32 op, char *rulestr,
++ void **lsmrule)
++{
++ return 0;
++}
++
++static inline int dummy_audit_rule_known(struct audit_krule *krule)
++{
++ return 0;
++}
++
++static inline int dummy_audit_rule_match(u32 secid, u32 field, u32 op,
++ void *lsmrule,
++ struct audit_context *actx)
++{
++ return 0;
++}
++
++static inline void dummy_audit_rule_free(void *lsmrule)
++{ }
++
++#endif /* CONFIG_AUDIT */
++
++struct security_operations dummy_security_ops = {
++ .name = "dummy",
++};
+
+ #define set_to_dummy_if_null(ops, function) \
+ do { \
+@@ -1058,6 +1098,7 @@ void security_fixup_ops (struct security_operations *ops)
+ set_to_dummy_if_null(ops, inode_getsecurity);
+ set_to_dummy_if_null(ops, inode_setsecurity);
+ set_to_dummy_if_null(ops, inode_listsecurity);
++ set_to_dummy_if_null(ops, inode_getsecid);
+ set_to_dummy_if_null(ops, file_permission);
+ set_to_dummy_if_null(ops, file_alloc_security);
+ set_to_dummy_if_null(ops, file_free_security);
+@@ -1094,6 +1135,7 @@ void security_fixup_ops (struct security_operations *ops)
+ set_to_dummy_if_null(ops, task_reparent_to_init);
+ set_to_dummy_if_null(ops, task_to_inode);
+ set_to_dummy_if_null(ops, ipc_permission);
++ set_to_dummy_if_null(ops, ipc_getsecid);
+ set_to_dummy_if_null(ops, msg_msg_alloc_security);
+ set_to_dummy_if_null(ops, msg_msg_free_security);
+ set_to_dummy_if_null(ops, msg_queue_alloc_security);
+@@ -1168,6 +1210,11 @@ void security_fixup_ops (struct security_operations *ops)
+ set_to_dummy_if_null(ops, key_free);
+ set_to_dummy_if_null(ops, key_permission);
+ #endif /* CONFIG_KEYS */
+-
++#ifdef CONFIG_AUDIT
++ set_to_dummy_if_null(ops, audit_rule_init);
++ set_to_dummy_if_null(ops, audit_rule_known);
++ set_to_dummy_if_null(ops, audit_rule_match);
++ set_to_dummy_if_null(ops, audit_rule_free);
++#endif
+ }
+
+diff --git a/security/keys/internal.h b/security/keys/internal.h
+index d36d693..7d894ef 100644
+--- a/security/keys/internal.h
++++ b/security/keys/internal.h
+@@ -22,16 +22,16 @@ void no_printk(const char *fmt, ...)
+
+ #ifdef __KDEBUG
+ #define kenter(FMT, ...) \
+- printk(KERN_DEBUG "==> %s("FMT")\n", __FUNCTION__, ##__VA_ARGS__)
++ printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__)
+ #define kleave(FMT, ...) \
+- printk(KERN_DEBUG "<== %s()"FMT"\n", __FUNCTION__, ##__VA_ARGS__)
++ printk(KERN_DEBUG "<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
+ #define kdebug(FMT, ...) \
+ printk(KERN_DEBUG "xxx" FMT"yyy\n", ##__VA_ARGS__)
+ #else
+ #define kenter(FMT, ...) \
+- no_printk(KERN_DEBUG "==> %s("FMT")\n", __FUNCTION__, ##__VA_ARGS__)
++ no_printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__)
+ #define kleave(FMT, ...) \
+- no_printk(KERN_DEBUG "<== %s()"FMT"\n", __FUNCTION__, ##__VA_ARGS__)
++ no_printk(KERN_DEBUG "<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
+ #define kdebug(FMT, ...) \
+ no_printk(KERN_DEBUG FMT"\n", ##__VA_ARGS__)
+ #endif
+diff --git a/security/root_plug.c b/security/root_plug.c
+index 870f130..6112d14 100644
+--- a/security/root_plug.c
++++ b/security/root_plug.c
+@@ -49,7 +49,7 @@ module_param(debug, bool, 0600);
+ do { \
+ if (debug) \
+ printk(KERN_DEBUG "%s: %s: " fmt , \
+- MY_NAME , __FUNCTION__ , \
++ MY_NAME , __func__ , \
+ ## arg); \
+ } while (0)
+
+diff --git a/security/security.c b/security/security.c
+index b1387a6..8a285c7 100644
+--- a/security/security.c
++++ b/security/security.c
+@@ -17,6 +17,8 @@
+ #include <linux/kernel.h>
+ #include <linux/security.h>
+
++/* Boot-time LSM user choice */
++static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1];
+
+ /* things that live in dummy.c */
+ extern struct security_operations dummy_security_ops;
+@@ -57,7 +59,7 @@ int __init security_init(void)
+
+ if (verify(&dummy_security_ops)) {
+ printk(KERN_ERR "%s could not verify "
+- "dummy_security_ops structure.\n", __FUNCTION__);
++ "dummy_security_ops structure.\n", __func__);
+ return -EIO;
+ }
+
+@@ -67,13 +69,47 @@ int __init security_init(void)
+ return 0;
+ }
+
++/* Save user chosen LSM */
++static int __init choose_lsm(char *str)
++{
++ strncpy(chosen_lsm, str, SECURITY_NAME_MAX);
++ return 1;
++}
++__setup("security=", choose_lsm);
++
++/**
++ * security_module_enable - Load given security module on boot ?
++ * @ops: a pointer to the struct security_operations that is to be checked.
++ *
++ * Each LSM must pass this method before registering its own operations
++ * to avoid security registration races. This method may also be used
++ * to check if your LSM is currently loaded during kernel initialization.
++ *
++ * Return true if:
++ * -The passed LSM is the one chosen by user at boot time,
++ * -or user didsn't specify a specific LSM and we're the first to ask
++ * for registeration permissoin,
++ * -or the passed LSM is currently loaded.
++ * Otherwise, return false.
++ */
++int __init security_module_enable(struct security_operations *ops)
++{
++ if (!*chosen_lsm)
++ strncpy(chosen_lsm, ops->name, SECURITY_NAME_MAX);
++ else if (strncmp(ops->name, chosen_lsm, SECURITY_NAME_MAX))
++ return 0;
++
++ return 1;
++}
++
+ /**
+ * register_security - registers a security framework with the kernel
+ * @ops: a pointer to the struct security_options that is to be registered
+ *
+ * This function is to allow a security module to register itself with the
+ * kernel security subsystem. Some rudimentary checking is done on the @ops
+- * value passed to this function.
++ * value passed to this function. You'll need to check first if your LSM
++ * is allowed to register its @ops by calling security_module_enable(@ops).
+ *
+ * If there is already a security module registered with the kernel,
+ * an error will be returned. Otherwise 0 is returned on success.
+@@ -82,7 +118,7 @@ int register_security(struct security_operations *ops)
+ {
+ if (verify(ops)) {
+ printk(KERN_DEBUG "%s could not verify "
+- "security_operations structure.\n", __FUNCTION__);
++ "security_operations structure.\n", __func__);
+ return -EINVAL;
+ }
+
+@@ -110,13 +146,13 @@ int mod_reg_security(const char *name, struct security_operations *ops)
+ {
+ if (verify(ops)) {
+ printk(KERN_INFO "%s could not verify "
+- "security operations.\n", __FUNCTION__);
++ "security operations.\n", __func__);
+ return -EINVAL;
+ }
+
+ if (ops == security_ops) {
+ printk(KERN_INFO "%s security operations "
+- "already registered.\n", __FUNCTION__);
++ "already registered.\n", __func__);
+ return -EINVAL;
+ }
+
+@@ -260,15 +296,15 @@ int security_sb_statfs(struct dentry *dentry)
+ return security_ops->sb_statfs(dentry);
+ }
+
+-int security_sb_mount(char *dev_name, struct nameidata *nd,
++int security_sb_mount(char *dev_name, struct path *path,
+ char *type, unsigned long flags, void *data)
+ {
+- return security_ops->sb_mount(dev_name, nd, type, flags, data);
++ return security_ops->sb_mount(dev_name, path, type, flags, data);
+ }
+
+-int security_sb_check_sb(struct vfsmount *mnt, struct nameidata *nd)
++int security_sb_check_sb(struct vfsmount *mnt, struct path *path)
+ {
+- return security_ops->sb_check_sb(mnt, nd);
++ return security_ops->sb_check_sb(mnt, path);
+ }
+
+ int security_sb_umount(struct vfsmount *mnt, int flags)
+@@ -291,19 +327,19 @@ void security_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *d
+ security_ops->sb_post_remount(mnt, flags, data);
+ }
+
+-void security_sb_post_addmount(struct vfsmount *mnt, struct nameidata *mountpoint_nd)
++void security_sb_post_addmount(struct vfsmount *mnt, struct path *mountpoint)
+ {
+- security_ops->sb_post_addmount(mnt, mountpoint_nd);
++ security_ops->sb_post_addmount(mnt, mountpoint);
+ }
+
+-int security_sb_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd)
++int security_sb_pivotroot(struct path *old_path, struct path *new_path)
+ {
+- return security_ops->sb_pivotroot(old_nd, new_nd);
++ return security_ops->sb_pivotroot(old_path, new_path);
+ }
+
+-void security_sb_post_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd)
++void security_sb_post_pivotroot(struct path *old_path, struct path *new_path)
+ {
+- security_ops->sb_post_pivotroot(old_nd, new_nd);
++ security_ops->sb_post_pivotroot(old_path, new_path);
+ }
+
+ int security_sb_get_mnt_opts(const struct super_block *sb,
+@@ -523,6 +559,11 @@ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer
+ return security_ops->inode_listsecurity(inode, buffer, buffer_size);
+ }
+
++void security_inode_getsecid(const struct inode *inode, u32 *secid)
++{
++ security_ops->inode_getsecid(inode, secid);
++}
++
+ int security_file_permission(struct file *file, int mask)
+ {
+ return security_ops->file_permission(file, mask);
+@@ -712,6 +753,11 @@ int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
+ return security_ops->ipc_permission(ipcp, flag);
+ }
+
++void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
++{
++ security_ops->ipc_getsecid(ipcp, secid);
++}
++
+ int security_msg_msg_alloc(struct msg_msg *msg)
+ {
+ return security_ops->msg_msg_alloc_security(msg);
+@@ -1014,26 +1060,27 @@ void security_inet_conn_established(struct sock *sk,
+
+ #ifdef CONFIG_SECURITY_NETWORK_XFRM
+
+-int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx)
++int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx)
+ {
+- return security_ops->xfrm_policy_alloc_security(xp, sec_ctx);
++ return security_ops->xfrm_policy_alloc_security(ctxp, sec_ctx);
+ }
+ EXPORT_SYMBOL(security_xfrm_policy_alloc);
+
+-int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
++int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
++ struct xfrm_sec_ctx **new_ctxp)
+ {
+- return security_ops->xfrm_policy_clone_security(old, new);
++ return security_ops->xfrm_policy_clone_security(old_ctx, new_ctxp);
+ }
+
+-void security_xfrm_policy_free(struct xfrm_policy *xp)
++void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
+ {
+- security_ops->xfrm_policy_free_security(xp);
++ security_ops->xfrm_policy_free_security(ctx);
+ }
+ EXPORT_SYMBOL(security_xfrm_policy_free);
+
+-int security_xfrm_policy_delete(struct xfrm_policy *xp)
++int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
+ {
+- return security_ops->xfrm_policy_delete_security(xp);
++ return security_ops->xfrm_policy_delete_security(ctx);
+ }
+
+ int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx)
+@@ -1065,9 +1112,9 @@ void security_xfrm_state_free(struct xfrm_state *x)
+ security_ops->xfrm_state_free_security(x);
+ }
+
+-int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir)
++int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
+ {
+- return security_ops->xfrm_policy_lookup(xp, fl_secid, dir);
++ return security_ops->xfrm_policy_lookup(ctx, fl_secid, dir);
+ }
+
+ int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
+@@ -1110,3 +1157,28 @@ int security_key_permission(key_ref_t key_ref,
+ }
+
+ #endif /* CONFIG_KEYS */
++
++#ifdef CONFIG_AUDIT
++
++int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule)
++{
++ return security_ops->audit_rule_init(field, op, rulestr, lsmrule);
++}
++
++int security_audit_rule_known(struct audit_krule *krule)
++{
++ return security_ops->audit_rule_known(krule);
++}
++
++void security_audit_rule_free(void *lsmrule)
++{
++ security_ops->audit_rule_free(lsmrule);
++}
++
++int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
++ struct audit_context *actx)
++{
++ return security_ops->audit_rule_match(secid, field, op, lsmrule, actx);
++}
++
++#endif /* CONFIG_AUDIT */
+diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
+index 2b517d6..a436d1c 100644
+--- a/security/selinux/Kconfig
++++ b/security/selinux/Kconfig
+@@ -145,7 +145,7 @@ config SECURITY_SELINUX_POLICYDB_VERSION_MAX
+ config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
+ int "NSA SELinux maximum supported policy format version value"
+ depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX
+- range 15 22
++ range 15 23
+ default 19
+ help
+ This option sets the value for the maximum policy format version
+diff --git a/security/selinux/Makefile b/security/selinux/Makefile
+index 00afd85..d47fc5e 100644
+--- a/security/selinux/Makefile
++++ b/security/selinux/Makefile
+@@ -11,6 +11,7 @@ selinux-y := avc.o \
+ nlmsgtab.o \
+ netif.o \
+ netnode.o \
++ netport.o \
+ exports.o
+
+ selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
+diff --git a/security/selinux/avc.c b/security/selinux/avc.c
+index 187964e..95a8ef4 100644
+--- a/security/selinux/avc.c
++++ b/security/selinux/avc.c
+@@ -2,16 +2,16 @@
+ * Implementation of the kernel access vector cache (AVC).
+ *
+ * Authors: Stephen Smalley, <sds at epoch.ncsc.mil>
+- * James Morris <jmorris at redhat.com>
++ * James Morris <jmorris at redhat.com>
+ *
+ * Update: KaiGai, Kohei <kaigai at ak.jp.nec.com>
+- * Replaced the avc_lock spinlock by RCU.
++ * Replaced the avc_lock spinlock by RCU.
+ *
+ * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris at redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+- * as published by the Free Software Foundation.
++ * as published by the Free Software Foundation.
+ */
+ #include <linux/types.h>
+ #include <linux/stddef.h>
+@@ -44,7 +44,7 @@ static const char *class_to_string[] = {
+ #undef S_
+ };
+
+-#define TB_(s) static const char * s [] = {
++#define TB_(s) static const char *s[] = {
+ #define TE_(s) };
+ #define S_(s) s,
+ #include "common_perm_to_string.h"
+@@ -72,7 +72,7 @@ const struct selinux_class_perm selinux_class_perm = {
+ #define AVC_CACHE_RECLAIM 16
+
+ #ifdef CONFIG_SECURITY_SELINUX_AVC_STATS
+-#define avc_cache_stats_incr(field) \
++#define avc_cache_stats_incr(field) \
+ do { \
+ per_cpu(avc_cache_stats, get_cpu()).field++; \
+ put_cpu(); \
+@@ -92,7 +92,7 @@ struct avc_entry {
+ struct avc_node {
+ struct avc_entry ae;
+ struct list_head list;
+- struct rcu_head rhead;
++ struct rcu_head rhead;
+ };
+
+ struct avc_cache {
+@@ -105,8 +105,8 @@ struct avc_cache {
+
+ struct avc_callback_node {
+ int (*callback) (u32 event, u32 ssid, u32 tsid,
+- u16 tclass, u32 perms,
+- u32 *out_retained);
++ u16 tclass, u32 perms,
++ u32 *out_retained);
+ u32 events;
+ u32 ssid;
+ u32 tsid;
+@@ -202,7 +202,7 @@ static void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tcla
+ char *scontext;
+ u32 scontext_len;
+
+- rc = security_sid_to_context(ssid, &scontext, &scontext_len);
++ rc = security_sid_to_context(ssid, &scontext, &scontext_len);
+ if (rc)
+ audit_log_format(ab, "ssid=%d", ssid);
+ else {
+@@ -306,12 +306,13 @@ static inline int avc_reclaim_node(void)
+ int hvalue, try, ecx;
+ unsigned long flags;
+
+- for (try = 0, ecx = 0; try < AVC_CACHE_SLOTS; try++ ) {
++ for (try = 0, ecx = 0; try < AVC_CACHE_SLOTS; try++) {
+ hvalue = atomic_inc_return(&avc_cache.lru_hint) & (AVC_CACHE_SLOTS - 1);
+
+ if (!spin_trylock_irqsave(&avc_cache.slots_lock[hvalue], flags))
+ continue;
+
++ rcu_read_lock();
+ list_for_each_entry(node, &avc_cache.slots[hvalue], list) {
+ if (atomic_dec_and_test(&node->ae.used)) {
+ /* Recently Unused */
+@@ -319,11 +320,13 @@ static inline int avc_reclaim_node(void)
+ avc_cache_stats_incr(reclaims);
+ ecx++;
+ if (ecx >= AVC_CACHE_RECLAIM) {
++ rcu_read_unlock();
+ spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flags);
+ goto out;
+ }
+ }
+ }
++ rcu_read_unlock();
+ spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flags);
+ }
+ out:
+@@ -426,7 +429,7 @@ static int avc_latest_notif_update(int seqno, int is_insert)
+ spin_lock_irqsave(¬if_lock, flag);
+ if (is_insert) {
+ if (seqno < avc_cache.latest_notif) {
+- printk(KERN_WARNING "avc: seqno %d < latest_notif %d\n",
++ printk(KERN_WARNING "SELinux: avc: seqno %d < latest_notif %d\n",
+ seqno, avc_cache.latest_notif);
+ ret = -EAGAIN;
+ }
+@@ -475,7 +478,7 @@ static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, struct avc_en
+ if (pos->ae.ssid == ssid &&
+ pos->ae.tsid == tsid &&
+ pos->ae.tclass == tclass) {
+- avc_node_replace(node, pos);
++ avc_node_replace(node, pos);
+ goto found;
+ }
+ }
+@@ -526,8 +529,8 @@ static inline void avc_print_ipv4_addr(struct audit_buffer *ab, __be32 addr,
+ * before calling the auditing code.
+ */
+ void avc_audit(u32 ssid, u32 tsid,
+- u16 tclass, u32 requested,
+- struct av_decision *avd, int result, struct avc_audit_data *a)
++ u16 tclass, u32 requested,
++ struct av_decision *avd, int result, struct avc_audit_data *a)
+ {
+ struct task_struct *tsk = current;
+ struct inode *inode = NULL;
+@@ -541,7 +544,7 @@ void avc_audit(u32 ssid, u32 tsid,
+ return;
+ } else if (result) {
+ audited = denied = requested;
+- } else {
++ } else {
+ audited = requested;
+ if (!(audited & avd->auditallow))
+ return;
+@@ -551,7 +554,7 @@ void avc_audit(u32 ssid, u32 tsid,
+ if (!ab)
+ return; /* audit_panic has been called */
+ audit_log_format(ab, "avc: %s ", denied ? "denied" : "granted");
+- avc_dump_av(ab, tclass,audited);
++ avc_dump_av(ab, tclass, audited);
+ audit_log_format(ab, " for ");
+ if (a && a->tsk)
+ tsk = a->tsk;
+@@ -647,7 +650,7 @@ void avc_audit(u32 ssid, u32 tsid,
+ break;
+ }
+ }
+-
++
+ switch (a->u.net.family) {
+ case AF_INET:
+ avc_print_ipv4_addr(ab, a->u.net.v4info.saddr,
+@@ -702,10 +705,10 @@ void avc_audit(u32 ssid, u32 tsid,
+ * -%ENOMEM if insufficient memory exists to add the callback.
+ */
+ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
+- u16 tclass, u32 perms,
+- u32 *out_retained),
+- u32 events, u32 ssid, u32 tsid,
+- u16 tclass, u32 perms)
++ u16 tclass, u32 perms,
++ u32 *out_retained),
++ u32 events, u32 ssid, u32 tsid,
++ u16 tclass, u32 perms)
+ {
+ struct avc_callback_node *c;
+ int rc = 0;
+@@ -759,10 +762,10 @@ static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass)
+ hvalue = avc_hash(ssid, tsid, tclass);
+ spin_lock_irqsave(&avc_cache.slots_lock[hvalue], flag);
+
+- list_for_each_entry(pos, &avc_cache.slots[hvalue], list){
+- if ( ssid==pos->ae.ssid &&
+- tsid==pos->ae.tsid &&
+- tclass==pos->ae.tclass ){
++ list_for_each_entry(pos, &avc_cache.slots[hvalue], list) {
++ if (ssid == pos->ae.ssid &&
++ tsid == pos->ae.tsid &&
++ tclass == pos->ae.tclass){
+ orig = pos;
+ break;
+ }
+@@ -821,15 +824,21 @@ int avc_ss_reset(u32 seqno)
+
+ for (i = 0; i < AVC_CACHE_SLOTS; i++) {
+ spin_lock_irqsave(&avc_cache.slots_lock[i], flag);
++ /*
++ * With preemptable RCU, the outer spinlock does not
++ * prevent RCU grace periods from ending.
++ */
++ rcu_read_lock();
+ list_for_each_entry(node, &avc_cache.slots[i], list)
+ avc_node_delete(node);
++ rcu_read_unlock();
+ spin_unlock_irqrestore(&avc_cache.slots_lock[i], flag);
+ }
+
+ for (c = avc_callbacks; c; c = c->next) {
+ if (c->events & AVC_CALLBACK_RESET) {
+ tmprc = c->callback(AVC_CALLBACK_RESET,
+- 0, 0, 0, 0, NULL);
++ 0, 0, 0, 0, NULL);
+ /* save the first error encountered for the return
+ value and continue processing the callbacks */
+ if (!rc)
+@@ -871,16 +880,18 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
+ int rc = 0;
+ u32 denied;
+
++ BUG_ON(!requested);
++
+ rcu_read_lock();
+
+ node = avc_lookup(ssid, tsid, tclass, requested);
+ if (!node) {
+ rcu_read_unlock();
+- rc = security_compute_av(ssid,tsid,tclass,requested,&entry.avd);
++ rc = security_compute_av(ssid, tsid, tclass, requested, &entry.avd);
+ if (rc)
+ goto out;
+ rcu_read_lock();
+- node = avc_insert(ssid,tsid,tclass,&entry);
++ node = avc_insert(ssid, tsid, tclass, &entry);
+ }
+
+ p_ae = node ? &node->ae : &entry;
+@@ -890,13 +901,14 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
+
+ denied = requested & ~(p_ae->avd.allowed);
+
+- if (!requested || denied) {
+- if (selinux_enforcing || (flags & AVC_STRICT))
++ if (denied) {
++ if (flags & AVC_STRICT)
+ rc = -EACCES;
++ else if (!selinux_enforcing || security_permissive_sid(ssid))
++ avc_update_node(AVC_CALLBACK_GRANT, requested, ssid,
++ tsid, tclass);
+ else
+- if (node)
+- avc_update_node(AVC_CALLBACK_GRANT,requested,
+- ssid,tsid,tclass);
++ rc = -EACCES;
+ }
+
+ rcu_read_unlock();
+@@ -921,7 +933,7 @@ out:
+ * another -errno upon other errors.
+ */
+ int avc_has_perm(u32 ssid, u32 tsid, u16 tclass,
+- u32 requested, struct avc_audit_data *auditdata)
++ u32 requested, struct avc_audit_data *auditdata)
+ {
+ struct av_decision avd;
+ int rc;
+diff --git a/security/selinux/exports.c b/security/selinux/exports.c
+index 87d2bb3..64af2d3 100644
+--- a/security/selinux/exports.c
++++ b/security/selinux/exports.c
+@@ -25,48 +25,6 @@
+ /* SECMARK reference count */
+ extern atomic_t selinux_secmark_refcount;
+
+-int selinux_sid_to_string(u32 sid, char **ctx, u32 *ctxlen)
+-{
+- if (selinux_enabled)
+- return security_sid_to_context(sid, ctx, ctxlen);
+- else {
+- *ctx = NULL;
+- *ctxlen = 0;
+- }
+-
+- return 0;
+-}
+-
+-void selinux_get_inode_sid(const struct inode *inode, u32 *sid)
+-{
+- if (selinux_enabled) {
+- struct inode_security_struct *isec = inode->i_security;
+- *sid = isec->sid;
+- return;
+- }
+- *sid = 0;
+-}
+-
+-void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid)
+-{
+- if (selinux_enabled) {
+- struct ipc_security_struct *isec = ipcp->security;
+- *sid = isec->sid;
+- return;
+- }
+- *sid = 0;
+-}
+-
+-void selinux_get_task_sid(struct task_struct *tsk, u32 *sid)
+-{
+- if (selinux_enabled) {
+- struct task_security_struct *tsec = tsk->security;
+- *sid = tsec->sid;
+- return;
+- }
+- *sid = 0;
+-}
+-
+ int selinux_string_to_sid(char *str, u32 *sid)
+ {
+ if (selinux_enabled)
+diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
+index d39b59c..308e2cf 100644
+--- a/security/selinux/hooks.c
++++ b/security/selinux/hooks.c
+@@ -4,22 +4,22 @@
+ * This file contains the SELinux hook function implementations.
+ *
+ * Authors: Stephen Smalley, <sds at epoch.ncsc.mil>
+- * Chris Vance, <cvance at nai.com>
+- * Wayne Salamon, <wsalamon at nai.com>
+- * James Morris <jmorris at redhat.com>
++ * Chris Vance, <cvance at nai.com>
++ * Wayne Salamon, <wsalamon at nai.com>
++ * James Morris <jmorris at redhat.com>
+ *
+ * Copyright (C) 2001,2002 Networks Associates Technology, Inc.
+ * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris at redhat.com>
+ * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
+- * <dgoeddel at trustedcs.com>
++ * <dgoeddel at trustedcs.com>
+ * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
+- * Paul Moore <paul.moore at hp.com>
++ * Paul Moore <paul.moore at hp.com>
+ * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
+- * Yuichi Nakamura <ynakam at hitachisoft.jp>
++ * Yuichi Nakamura <ynakam at hitachisoft.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+- * as published by the Free Software Foundation.
++ * as published by the Free Software Foundation.
+ */
+
+ #include <linux/init.h>
+@@ -80,8 +80,10 @@
+ #include "objsec.h"
+ #include "netif.h"
+ #include "netnode.h"
++#include "netport.h"
+ #include "xfrm.h"
+ #include "netlabel.h"
++#include "audit.h"
+
+ #define XATTR_SELINUX_SUFFIX "selinux"
+ #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
+@@ -97,11 +99,11 @@ extern struct security_operations *security_ops;
+ atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
+
+ #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
+-int selinux_enforcing = 0;
++int selinux_enforcing;
+
+ static int __init enforcing_setup(char *str)
+ {
+- selinux_enforcing = simple_strtol(str,NULL,0);
++ selinux_enforcing = simple_strtol(str, NULL, 0);
+ return 1;
+ }
+ __setup("enforcing=", enforcing_setup);
+@@ -121,13 +123,13 @@ int selinux_enabled = 1;
+ #endif
+
+ /* Original (dummy) security module. */
+-static struct security_operations *original_ops = NULL;
++static struct security_operations *original_ops;
+
+ /* Minimal support for a secondary security module,
+ just to allow the use of the dummy or capability modules.
+ The owlsm module can alternatively be used as a secondary
+ module as long as CONFIG_OWLSM_FD is not enabled. */
+-static struct security_operations *secondary_ops = NULL;
++static struct security_operations *secondary_ops;
+
+ /* Lists of inode and superblock security structures initialized
+ before the policy was loaded. */
+@@ -161,8 +163,7 @@ static int task_alloc_security(struct task_struct *task)
+ if (!tsec)
+ return -ENOMEM;
+
+- tsec->task = task;
+- tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;
++ tsec->osid = tsec->sid = SECINITSID_UNLABELED;
+ task->security = tsec;
+
+ return 0;
+@@ -218,7 +219,6 @@ static int file_alloc_security(struct file *file)
+ if (!fsec)
+ return -ENOMEM;
+
+- fsec->file = file;
+ fsec->sid = tsec->sid;
+ fsec->fown_sid = tsec->sid;
+ file->f_security = fsec;
+@@ -275,12 +275,11 @@ static int sk_alloc_security(struct sock *sk, int family, gfp_t priority)
+ if (!ssec)
+ return -ENOMEM;
+
+- ssec->sk = sk;
+ ssec->peer_sid = SECINITSID_UNLABELED;
+ ssec->sid = SECINITSID_UNLABELED;
+ sk->sk_security = ssec;
+
+- selinux_netlbl_sk_security_init(ssec, family);
++ selinux_netlbl_sk_security_reset(ssec, family);
+
+ return 0;
+ }
+@@ -324,10 +323,10 @@ enum {
+ };
+
+ static match_table_t tokens = {
+- {Opt_context, "context=%s"},
+- {Opt_fscontext, "fscontext=%s"},
+- {Opt_defcontext, "defcontext=%s"},
+- {Opt_rootcontext, "rootcontext=%s"},
++ {Opt_context, CONTEXT_STR "%s"},
++ {Opt_fscontext, FSCONTEXT_STR "%s"},
++ {Opt_defcontext, DEFCONTEXT_STR "%s"},
++ {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
+ {Opt_error, NULL},
+ };
+
+@@ -576,8 +575,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
+ goto out;
+ }
+ rc = -EINVAL;
+- printk(KERN_WARNING "Unable to set superblock options before "
+- "the security server is initialized\n");
++ printk(KERN_WARNING "SELinux: Unable to set superblock options "
++ "before the security server is initialized\n");
+ goto out;
+ }
+
+@@ -671,7 +670,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
+ rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid);
+ if (rc) {
+ printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
+- __FUNCTION__, sb->s_type->name, rc);
++ __func__, sb->s_type->name, rc);
+ goto out;
+ }
+
+@@ -756,9 +755,18 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
+ int set_context = (oldsbsec->flags & CONTEXT_MNT);
+ int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
+
+- /* we can't error, we can't save the info, this shouldn't get called
+- * this early in the boot process. */
+- BUG_ON(!ss_initialized);
++ /*
++ * if the parent was able to be mounted it clearly had no special lsm
++ * mount options. thus we can safely put this sb on the list and deal
++ * with it later
++ */
++ if (!ss_initialized) {
++ spin_lock(&sb_security_lock);
++ if (list_empty(&newsbsec->list))
++ list_add(&newsbsec->list, &superblock_security_head);
++ spin_unlock(&sb_security_lock);
++ return;
++ }
+
+ /* how can we clone if the old one wasn't set up?? */
+ BUG_ON(!oldsbsec->initialized);
+@@ -1055,7 +1063,7 @@ static int selinux_proc_get_sid(struct proc_dir_entry *de,
+ int buflen, rc;
+ char *buffer, *path, *end;
+
+- buffer = (char*)__get_free_page(GFP_KERNEL);
++ buffer = (char *)__get_free_page(GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+@@ -1136,8 +1144,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
+ dentry = d_find_alias(inode);
+ }
+ if (!dentry) {
+- printk(KERN_WARNING "%s: no dentry for dev=%s "
+- "ino=%ld\n", __FUNCTION__, inode->i_sb->s_id,
++ printk(KERN_WARNING "SELinux: %s: no dentry for dev=%s "
++ "ino=%ld\n", __func__, inode->i_sb->s_id,
+ inode->i_ino);
+ goto out_unlock;
+ }
+@@ -1174,8 +1182,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
+ dput(dentry);
+ if (rc < 0) {
+ if (rc != -ENODATA) {
+- printk(KERN_WARNING "%s: getxattr returned "
+- "%d for dev=%s ino=%ld\n", __FUNCTION__,
++ printk(KERN_WARNING "SELinux: %s: getxattr returned "
++ "%d for dev=%s ino=%ld\n", __func__,
+ -rc, inode->i_sb->s_id, inode->i_ino);
+ kfree(context);
+ goto out_unlock;
+@@ -1188,9 +1196,9 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
+ sbsec->def_sid,
+ GFP_NOFS);
+ if (rc) {
+- printk(KERN_WARNING "%s: context_to_sid(%s) "
++ printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
+ "returned %d for dev=%s ino=%ld\n",
+- __FUNCTION__, context, -rc,
++ __func__, context, -rc,
+ inode->i_sb->s_id, inode->i_ino);
+ kfree(context);
+ /* Leave with the unlabeled SID */
+@@ -1306,7 +1314,7 @@ static int task_has_capability(struct task_struct *tsk,
+
+ tsec = tsk->security;
+
+- AVC_AUDIT_DATA_INIT(&ad,CAP);
++ AVC_AUDIT_DATA_INIT(&ad, CAP);
+ ad.tsk = tsk;
+ ad.u.cap = cap;
+
+@@ -1349,7 +1357,7 @@ static int inode_has_perm(struct task_struct *tsk,
+ struct inode_security_struct *isec;
+ struct avc_audit_data ad;
+
+- if (unlikely (IS_PRIVATE (inode)))
++ if (unlikely(IS_PRIVATE(inode)))
+ return 0;
+
+ tsec = tsk->security;
+@@ -1374,7 +1382,7 @@ static inline int dentry_has_perm(struct task_struct *tsk,
+ {
+ struct inode *inode = dentry->d_inode;
+ struct avc_audit_data ad;
+- AVC_AUDIT_DATA_INIT(&ad,FS);
++ AVC_AUDIT_DATA_INIT(&ad, FS);
+ ad.u.fs.path.mnt = mnt;
+ ad.u.fs.path.dentry = dentry;
+ return inode_has_perm(tsk, inode, av, &ad);
+@@ -1471,9 +1479,9 @@ static int may_create_key(u32 ksid,
+ return avc_has_perm(tsec->sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
+ }
+
+-#define MAY_LINK 0
+-#define MAY_UNLINK 1
+-#define MAY_RMDIR 2
++#define MAY_LINK 0
++#define MAY_UNLINK 1
++#define MAY_RMDIR 2
+
+ /* Check whether a task can link, unlink, or rmdir a file/directory. */
+ static int may_link(struct inode *dir,
+@@ -1511,7 +1519,8 @@ static int may_link(struct inode *dir,
+ av = DIR__RMDIR;
+ break;
+ default:
+- printk(KERN_WARNING "may_link: unrecognized kind %d\n", kind);
++ printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
++ __func__, kind);
+ return 0;
+ }
+
+@@ -1618,6 +1627,35 @@ static inline u32 file_mask_to_av(int mode, int mask)
+ return av;
+ }
+
++/*
++ * Convert a file mask to an access vector and include the correct open
++ * open permission.
++ */
++static inline u32 open_file_mask_to_av(int mode, int mask)
++{
++ u32 av = file_mask_to_av(mode, mask);
++
++ if (selinux_policycap_openperm) {
++ /*
++ * lnk files and socks do not really have an 'open'
++ */
++ if (S_ISREG(mode))
++ av |= FILE__OPEN;
++ else if (S_ISCHR(mode))
++ av |= CHR_FILE__OPEN;
++ else if (S_ISBLK(mode))
++ av |= BLK_FILE__OPEN;
++ else if (S_ISFIFO(mode))
++ av |= FIFO_FILE__OPEN;
++ else if (S_ISDIR(mode))
++ av |= DIR__OPEN;
++ else
++ printk(KERN_ERR "SELinux: WARNING: inside %s with "
++ "unknown mode:%x\n", __func__, mode);
++ }
++ return av;
++}
++
+ /* Convert a Linux file to an access vector. */
+ static inline u32 file_to_av(struct file *file)
+ {
+@@ -1645,23 +1683,17 @@ static inline u32 file_to_av(struct file *file)
+
+ static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
+ {
+- struct task_security_struct *psec = parent->security;
+- struct task_security_struct *csec = child->security;
+ int rc;
+
+- rc = secondary_ops->ptrace(parent,child);
++ rc = secondary_ops->ptrace(parent, child);
+ if (rc)
+ return rc;
+
+- rc = task_has_perm(parent, child, PROCESS__PTRACE);
+- /* Save the SID of the tracing process for later use in apply_creds. */
+- if (!(child->ptrace & PT_PTRACED) && !rc)
+- csec->ptrace_sid = psec->sid;
+- return rc;
++ return task_has_perm(parent, child, PROCESS__PTRACE);
+ }
+
+ static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
+- kernel_cap_t *inheritable, kernel_cap_t *permitted)
++ kernel_cap_t *inheritable, kernel_cap_t *permitted)
+ {
+ int error;
+
+@@ -1673,7 +1705,7 @@ static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
+ }
+
+ static int selinux_capset_check(struct task_struct *target, kernel_cap_t *effective,
+- kernel_cap_t *inheritable, kernel_cap_t *permitted)
++ kernel_cap_t *inheritable, kernel_cap_t *permitted)
+ {
+ int error;
+
+@@ -1685,7 +1717,7 @@ static int selinux_capset_check(struct task_struct *target, kernel_cap_t *effect
+ }
+
+ static void selinux_capset_set(struct task_struct *target, kernel_cap_t *effective,
+- kernel_cap_t *inheritable, kernel_cap_t *permitted)
++ kernel_cap_t *inheritable, kernel_cap_t *permitted)
+ {
+ secondary_ops->capset_set(target, effective, inheritable, permitted);
+ }
+@@ -1698,7 +1730,7 @@ static int selinux_capable(struct task_struct *tsk, int cap)
+ if (rc)
+ return rc;
+
+- return task_has_capability(tsk,cap);
++ return task_has_capability(tsk, cap);
+ }
+
+ static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
+@@ -1707,7 +1739,7 @@ static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
+ char *buffer, *path, *end;
+
+ rc = -ENOMEM;
+- buffer = (char*)__get_free_page(GFP_KERNEL);
++ buffer = (char *)__get_free_page(GFP_KERNEL);
+ if (!buffer)
+ goto out;
+
+@@ -1765,7 +1797,7 @@ static int selinux_sysctl(ctl_table *table, int op)
+
+ /* The op values are "defined" in sysctl.c, thereby creating
+ * a bad coupling between this module and sysctl.c */
+- if(op == 001) {
++ if (op == 001) {
+ error = avc_has_perm(tsec->sid, tsid,
+ SECCLASS_DIR, DIR__SEARCH, NULL);
+ } else {
+@@ -1777,7 +1809,7 @@ static int selinux_sysctl(ctl_table *table, int op)
+ if (av)
+ error = avc_has_perm(tsec->sid, tsid,
+ SECCLASS_FILE, av, NULL);
+- }
++ }
+
+ return error;
+ }
+@@ -1790,25 +1822,23 @@ static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
+ return 0;
+
+ switch (cmds) {
+- case Q_SYNC:
+- case Q_QUOTAON:
+- case Q_QUOTAOFF:
+- case Q_SETINFO:
+- case Q_SETQUOTA:
+- rc = superblock_has_perm(current,
+- sb,
+- FILESYSTEM__QUOTAMOD, NULL);
+- break;
+- case Q_GETFMT:
+- case Q_GETINFO:
+- case Q_GETQUOTA:
+- rc = superblock_has_perm(current,
+- sb,
+- FILESYSTEM__QUOTAGET, NULL);
+- break;
+- default:
+- rc = 0; /* let the kernel handle invalid cmds */
+- break;
++ case Q_SYNC:
++ case Q_QUOTAON:
++ case Q_QUOTAOFF:
++ case Q_SETINFO:
++ case Q_SETQUOTA:
++ rc = superblock_has_perm(current, sb, FILESYSTEM__QUOTAMOD,
++ NULL);
++ break;
++ case Q_GETFMT:
++ case Q_GETINFO:
++ case Q_GETQUOTA:
++ rc = superblock_has_perm(current, sb, FILESYSTEM__QUOTAGET,
++ NULL);
++ break;
++ default:
++ rc = 0; /* let the kernel handle invalid cmds */
++ break;
+ }
+ return rc;
+ }
+@@ -1827,23 +1857,23 @@ static int selinux_syslog(int type)
+ return rc;
+
+ switch (type) {
+- case 3: /* Read last kernel messages */
+- case 10: /* Return size of the log buffer */
+- rc = task_has_system(current, SYSTEM__SYSLOG_READ);
+- break;
+- case 6: /* Disable logging to console */
+- case 7: /* Enable logging to console */
+- case 8: /* Set level of messages printed to console */
+- rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
+- break;
+- case 0: /* Close log */
+- case 1: /* Open log */
+- case 2: /* Read from log */
+- case 4: /* Read/clear last kernel messages */
+- case 5: /* Clear ring buffer */
+- default:
+- rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
+- break;
++ case 3: /* Read last kernel messages */
++ case 10: /* Return size of the log buffer */
++ rc = task_has_system(current, SYSTEM__SYSLOG_READ);
++ break;
++ case 6: /* Disable logging to console */
++ case 7: /* Enable logging to console */
++ case 8: /* Set level of messages printed to console */
++ rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
++ break;
++ case 0: /* Close log */
++ case 1: /* Open log */
++ case 2: /* Read from log */
++ case 4: /* Read/clear last kernel messages */
++ case 5: /* Clear ring buffer */
++ default:
++ rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
++ break;
+ }
+ return rc;
+ }
+@@ -1879,6 +1909,22 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
+ return __vm_enough_memory(mm, pages, cap_sys_admin);
+ }
+
++/**
++ * task_tracer_task - return the task that is tracing the given task
++ * @task: task to consider
++ *
++ * Returns NULL if noone is tracing @task, or the &struct task_struct
++ * pointer to its tracer.
++ *
++ * Must be called under rcu_read_lock().
++ */
++static struct task_struct *task_tracer_task(struct task_struct *task)
++{
++ if (task->ptrace & PT_PTRACED)
++ return rcu_dereference(task->parent);
++ return NULL;
++}
++
+ /* binprm security operations */
+
+ static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
+@@ -1889,7 +1935,6 @@ static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
+ if (!bsec)
+ return -ENOMEM;
+
+- bsec->bprm = bprm;
+ bsec->sid = SECINITSID_UNLABELED;
+ bsec->set = 0;
+
+@@ -1934,7 +1979,7 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm)
+ } else {
+ /* Check for a default transition on this program. */
+ rc = security_transition_sid(tsec->sid, isec->sid,
+- SECCLASS_PROCESS, &newsid);
++ SECCLASS_PROCESS, &newsid);
+ if (rc)
+ return rc;
+ }
+@@ -1945,7 +1990,7 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm)
+ if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
+ newsid = tsec->sid;
+
+- if (tsec->sid == newsid) {
++ if (tsec->sid == newsid) {
+ rc = avc_has_perm(tsec->sid, isec->sid,
+ SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
+ if (rc)
+@@ -1973,13 +2018,13 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm)
+ return 0;
+ }
+
+-static int selinux_bprm_check_security (struct linux_binprm *bprm)
++static int selinux_bprm_check_security(struct linux_binprm *bprm)
+ {
+ return secondary_ops->bprm_check_security(bprm);
+ }
+
+
+-static int selinux_bprm_secureexec (struct linux_binprm *bprm)
++static int selinux_bprm_secureexec(struct linux_binprm *bprm)
+ {
+ struct task_security_struct *tsec = current->security;
+ int atsecure = 0;
+@@ -2006,7 +2051,7 @@ extern struct vfsmount *selinuxfs_mount;
+ extern struct dentry *selinux_null;
+
+ /* Derived from fs/exec.c:flush_old_files. */
+-static inline void flush_unauthorized_files(struct files_struct * files)
++static inline void flush_unauthorized_files(struct files_struct *files)
+ {
+ struct avc_audit_data ad;
+ struct file *file, *devnull = NULL;
+@@ -2041,7 +2086,7 @@ static inline void flush_unauthorized_files(struct files_struct * files)
+
+ /* Revalidate access to inherited open files. */
+
+- AVC_AUDIT_DATA_INIT(&ad,FS);
++ AVC_AUDIT_DATA_INIT(&ad, FS);
+
+ spin_lock(&files->file_lock);
+ for (;;) {
+@@ -2057,7 +2102,7 @@ static inline void flush_unauthorized_files(struct files_struct * files)
+ if (!set)
+ continue;
+ spin_unlock(&files->file_lock);
+- for ( ; set ; i++,set >>= 1) {
++ for ( ; set ; i++, set >>= 1) {
+ if (set & 1) {
+ file = fget(i);
+ if (!file)
+@@ -2126,12 +2171,25 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
+ /* Check for ptracing, and update the task SID if ok.
+ Otherwise, leave SID unchanged and kill. */
+ if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
+- rc = avc_has_perm(tsec->ptrace_sid, sid,
+- SECCLASS_PROCESS, PROCESS__PTRACE,
+- NULL);
+- if (rc) {
+- bsec->unsafe = 1;
+- return;
++ struct task_struct *tracer;
++ struct task_security_struct *sec;
++ u32 ptsid = 0;
++
++ rcu_read_lock();
++ tracer = task_tracer_task(current);
++ if (likely(tracer != NULL)) {
++ sec = tracer->security;
++ ptsid = sec->sid;
++ }
++ rcu_read_unlock();
++
++ if (ptsid != 0) {
++ rc = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
++ PROCESS__PTRACE, NULL);
++ if (rc) {
++ bsec->unsafe = 1;
++ return;
++ }
+ }
+ }
+ tsec->sid = sid;
+@@ -2201,7 +2259,7 @@ static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm)
+ for (i = 0; i < RLIM_NLIMITS; i++) {
+ rlim = current->signal->rlim + i;
+ initrlim = init_task.signal->rlim+i;
+- rlim->rlim_cur = min(rlim->rlim_max,initrlim->rlim_cur);
++ rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
+ }
+ if (current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {
+ /*
+@@ -2239,10 +2297,10 @@ static inline int match_prefix(char *prefix, int plen, char *option, int olen)
+
+ static inline int selinux_option(char *option, int len)
+ {
+- return (match_prefix("context=", sizeof("context=")-1, option, len) ||
+- match_prefix("fscontext=", sizeof("fscontext=")-1, option, len) ||
+- match_prefix("defcontext=", sizeof("defcontext=")-1, option, len) ||
+- match_prefix("rootcontext=", sizeof("rootcontext=")-1, option, len));
++ return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
++ match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
++ match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
++ match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len));
+ }
+
+ static inline void take_option(char **to, char *from, int *first, int len)
+@@ -2256,16 +2314,15 @@ static inline void take_option(char **to, char *from, int *first, int len)
+ *to += len;
+ }
+
+-static inline void take_selinux_option(char **to, char *from, int *first,
+- int len)
++static inline void take_selinux_option(char **to, char *from, int *first,
++ int len)
+ {
+ int current_size = 0;
+
+ if (!*first) {
+ **to = '|';
+ *to += 1;
+- }
+- else
++ } else
+ *first = 0;
+
+ while (current_size < len) {
+@@ -2329,7 +2386,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, void *data)
+ if (rc)
+ return rc;
+
+- AVC_AUDIT_DATA_INIT(&ad,FS);
++ AVC_AUDIT_DATA_INIT(&ad, FS);
+ ad.u.fs.path.dentry = sb->s_root;
+ return superblock_has_perm(current, sb, FILESYSTEM__MOUNT, &ad);
+ }
+@@ -2338,29 +2395,29 @@ static int selinux_sb_statfs(struct dentry *dentry)
+ {
+ struct avc_audit_data ad;
+
+- AVC_AUDIT_DATA_INIT(&ad,FS);
++ AVC_AUDIT_DATA_INIT(&ad, FS);
+ ad.u.fs.path.dentry = dentry->d_sb->s_root;
+ return superblock_has_perm(current, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
+ }
+
+-static int selinux_mount(char * dev_name,
+- struct nameidata *nd,
+- char * type,
+- unsigned long flags,
+- void * data)
++static int selinux_mount(char *dev_name,
++ struct path *path,
++ char *type,
++ unsigned long flags,
++ void *data)
+ {
+ int rc;
+
+- rc = secondary_ops->sb_mount(dev_name, nd, type, flags, data);
++ rc = secondary_ops->sb_mount(dev_name, path, type, flags, data);
+ if (rc)
+ return rc;
+
+ if (flags & MS_REMOUNT)
+- return superblock_has_perm(current, nd->path.mnt->mnt_sb,
+- FILESYSTEM__REMOUNT, NULL);
++ return superblock_has_perm(current, path->mnt->mnt_sb,
++ FILESYSTEM__REMOUNT, NULL);
+ else
+- return dentry_has_perm(current, nd->path.mnt, nd->path.dentry,
+- FILE__MOUNTON);
++ return dentry_has_perm(current, path->mnt, path->dentry,
++ FILE__MOUNTON);
+ }
+
+ static int selinux_umount(struct vfsmount *mnt, int flags)
+@@ -2371,8 +2428,8 @@ static int selinux_umount(struct vfsmount *mnt, int flags)
+ if (rc)
+ return rc;
+
+- return superblock_has_perm(current,mnt->mnt_sb,
+- FILESYSTEM__UNMOUNT,NULL);
++ return superblock_has_perm(current, mnt->mnt_sb,
++ FILESYSTEM__UNMOUNT, NULL);
+ }
+
+ /* inode security operations */
+@@ -2412,7 +2469,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
+ printk(KERN_WARNING "%s: "
+ "security_transition_sid failed, rc=%d (dev=%s "
+ "ino=%ld)\n",
+- __FUNCTION__,
++ __func__,
+ -rc, inode->i_sb->s_id, inode->i_ino);
+ return rc;
+ }
+@@ -2458,7 +2515,7 @@ static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, stru
+ {
+ int rc;
+
+- rc = secondary_ops->inode_link(old_dentry,dir,new_dentry);
++ rc = secondary_ops->inode_link(old_dentry, dir, new_dentry);
+ if (rc)
+ return rc;
+ return may_link(dir, old_dentry, MAY_LINK);
+@@ -2501,7 +2558,7 @@ static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mod
+ }
+
+ static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
+- struct inode *new_inode, struct dentry *new_dentry)
++ struct inode *new_inode, struct dentry *new_dentry)
+ {
+ return may_rename(old_inode, old_dentry, new_inode, new_dentry);
+ }
+@@ -2515,7 +2572,7 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na
+ {
+ int rc;
+
+- rc = secondary_ops->inode_follow_link(dentry,nameidata);
++ rc = secondary_ops->inode_follow_link(dentry, nameidata);
+ if (rc)
+ return rc;
+ return dentry_has_perm(current, NULL, dentry, FILE__READ);
+@@ -2536,7 +2593,7 @@ static int selinux_inode_permission(struct inode *inode, int mask,
+ }
+
+ return inode_has_perm(current, inode,
+- file_mask_to_av(inode->i_mode, mask), NULL);
++ open_file_mask_to_av(inode->i_mode, mask), NULL);
+ }
+
+ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
+@@ -2601,7 +2658,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value
+ if (!is_owner_or_cap(inode))
+ return -EPERM;
+
+- AVC_AUDIT_DATA_INIT(&ad,FS);
++ AVC_AUDIT_DATA_INIT(&ad, FS);
+ ad.u.fs.path.dentry = dentry;
+
+ rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass,
+@@ -2619,7 +2676,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value
+ return rc;
+
+ rc = security_validate_transition(isec->sid, newsid, tsec->sid,
+- isec->sclass);
++ isec->sclass);
+ if (rc)
+ return rc;
+
+@@ -2631,7 +2688,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value
+ }
+
+ static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
+- void *value, size_t size, int flags)
++ void *value, size_t size, int flags)
+ {
+ struct inode *inode = dentry->d_inode;
+ struct inode_security_struct *isec = inode->i_security;
+@@ -2646,7 +2703,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
+ rc = security_context_to_sid(value, size, &newsid);
+ if (rc) {
+ printk(KERN_WARNING "%s: unable to obtain SID for context "
+- "%s, rc=%d\n", __FUNCTION__, (char*)value, -rc);
++ "%s, rc=%d\n", __func__, (char *)value, -rc);
+ return;
+ }
+
+@@ -2654,17 +2711,17 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
+ return;
+ }
+
+-static int selinux_inode_getxattr (struct dentry *dentry, char *name)
++static int selinux_inode_getxattr(struct dentry *dentry, char *name)
+ {
+ return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
+ }
+
+-static int selinux_inode_listxattr (struct dentry *dentry)
++static int selinux_inode_listxattr(struct dentry *dentry)
+ {
+ return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
+ }
+
+-static int selinux_inode_removexattr (struct dentry *dentry, char *name)
++static int selinux_inode_removexattr(struct dentry *dentry, char *name)
+ {
+ if (strcmp(name, XATTR_NAME_SELINUX))
+ return selinux_inode_setotherxattr(dentry, name);
+@@ -2705,7 +2762,7 @@ out_nofree:
+ }
+
+ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
+- const void *value, size_t size, int flags)
++ const void *value, size_t size, int flags)
+ {
+ struct inode_security_struct *isec = inode->i_security;
+ u32 newsid;
+@@ -2717,7 +2774,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
+ if (!value || !size)
+ return -EACCES;
+
+- rc = security_context_to_sid((void*)value, size, &newsid);
++ rc = security_context_to_sid((void *)value, size, &newsid);
+ if (rc)
+ return rc;
+
+@@ -2743,6 +2800,12 @@ static int selinux_inode_killpriv(struct dentry *dentry)
+ return secondary_ops->inode_killpriv(dentry);
+ }
+
++static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
++{
++ struct inode_security_struct *isec = inode->i_security;
++ *secid = isec->sid;
++}
++
+ /* file security operations */
+
+ static int selinux_revalidate_file_permission(struct file *file, int mask)
+@@ -2802,42 +2865,41 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
+ int error = 0;
+
+ switch (cmd) {
+- case FIONREAD:
+- /* fall through */
+- case FIBMAP:
+- /* fall through */
+- case FIGETBSZ:
+- /* fall through */
+- case EXT2_IOC_GETFLAGS:
+- /* fall through */
+- case EXT2_IOC_GETVERSION:
+- error = file_has_perm(current, file, FILE__GETATTR);
+- break;
+-
+- case EXT2_IOC_SETFLAGS:
+- /* fall through */
+- case EXT2_IOC_SETVERSION:
+- error = file_has_perm(current, file, FILE__SETATTR);
+- break;
++ case FIONREAD:
++ /* fall through */
++ case FIBMAP:
++ /* fall through */
++ case FIGETBSZ:
++ /* fall through */
++ case EXT2_IOC_GETFLAGS:
++ /* fall through */
++ case EXT2_IOC_GETVERSION:
++ error = file_has_perm(current, file, FILE__GETATTR);
++ break;
+
+- /* sys_ioctl() checks */
+- case FIONBIO:
+- /* fall through */
+- case FIOASYNC:
+- error = file_has_perm(current, file, 0);
+- break;
++ case EXT2_IOC_SETFLAGS:
++ /* fall through */
++ case EXT2_IOC_SETVERSION:
++ error = file_has_perm(current, file, FILE__SETATTR);
++ break;
+
+- case KDSKBENT:
+- case KDSKBSENT:
+- error = task_has_capability(current,CAP_SYS_TTY_CONFIG);
+- break;
++ /* sys_ioctl() checks */
++ case FIONBIO:
++ /* fall through */
++ case FIOASYNC:
++ error = file_has_perm(current, file, 0);
++ break;
+
+- /* default case assumes that the command will go
+- * to the file's ioctl() function.
+- */
+- default:
+- error = file_has_perm(current, file, FILE__IOCTL);
++ case KDSKBENT:
++ case KDSKBSENT:
++ error = task_has_capability(current, CAP_SYS_TTY_CONFIG);
++ break;
+
++ /* default case assumes that the command will go
++ * to the file's ioctl() function.
++ */
++ default:
++ error = file_has_perm(current, file, FILE__IOCTL);
+ }
+ return error;
+ }
+@@ -2878,7 +2940,7 @@ static int selinux_file_mmap(struct file *file, unsigned long reqprot,
+ unsigned long addr, unsigned long addr_only)
+ {
+ int rc = 0;
+- u32 sid = ((struct task_security_struct*)(current->security))->sid;
++ u32 sid = ((struct task_security_struct *)(current->security))->sid;
+
+ if (addr < mmap_min_addr)
+ rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
+@@ -2947,39 +3009,39 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
+ int err = 0;
+
+ switch (cmd) {
+- case F_SETFL:
+- if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
+- err = -EINVAL;
+- break;
+- }
++ case F_SETFL:
++ if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
++ err = -EINVAL;
++ break;
++ }
+
+- if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
+- err = file_has_perm(current, file,FILE__WRITE);
+- break;
+- }
+- /* fall through */
+- case F_SETOWN:
+- case F_SETSIG:
+- case F_GETFL:
+- case F_GETOWN:
+- case F_GETSIG:
+- /* Just check FD__USE permission */
+- err = file_has_perm(current, file, 0);
++ if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
++ err = file_has_perm(current, file, FILE__WRITE);
+ break;
+- case F_GETLK:
+- case F_SETLK:
+- case F_SETLKW:
++ }
++ /* fall through */
++ case F_SETOWN:
++ case F_SETSIG:
++ case F_GETFL:
++ case F_GETOWN:
++ case F_GETSIG:
++ /* Just check FD__USE permission */
++ err = file_has_perm(current, file, 0);
++ break;
++ case F_GETLK:
++ case F_SETLK:
++ case F_SETLKW:
+ #if BITS_PER_LONG == 32
+- case F_GETLK64:
+- case F_SETLK64:
+- case F_SETLKW64:
++ case F_GETLK64:
++ case F_SETLK64:
++ case F_SETLKW64:
+ #endif
+- if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
+- err = -EINVAL;
+- break;
+- }
+- err = file_has_perm(current, file, FILE__LOCK);
++ if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
++ err = -EINVAL;
+ break;
++ }
++ err = file_has_perm(current, file, FILE__LOCK);
++ break;
+ }
+
+ return err;
+@@ -3000,13 +3062,13 @@ static int selinux_file_set_fowner(struct file *file)
+ static int selinux_file_send_sigiotask(struct task_struct *tsk,
+ struct fown_struct *fown, int signum)
+ {
+- struct file *file;
++ struct file *file;
+ u32 perm;
+ struct task_security_struct *tsec;
+ struct file_security_struct *fsec;
+
+ /* struct fown_struct is never outside the context of a struct file */
+- file = container_of(fown, struct file, f_owner);
++ file = container_of(fown, struct file, f_owner);
+
+ tsec = tsk->security;
+ fsec = file->f_security;
+@@ -3087,11 +3149,6 @@ static int selinux_task_alloc_security(struct task_struct *tsk)
+ tsec2->keycreate_sid = tsec1->keycreate_sid;
+ tsec2->sockcreate_sid = tsec1->sockcreate_sid;
+
+- /* Retain ptracer SID across fork, if any.
+- This will be reset by the ptrace hook upon any
+- subsequent ptrace_attach operations. */
+- tsec2->ptrace_sid = tsec1->ptrace_sid;
+-
+ return 0;
+ }
+
+@@ -3113,7 +3170,7 @@ static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
+
+ static int selinux_task_post_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
+ {
+- return secondary_ops->task_post_setuid(id0,id1,id2,flags);
++ return secondary_ops->task_post_setuid(id0, id1, id2, flags);
+ }
+
+ static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags)
+@@ -3139,7 +3196,8 @@ static int selinux_task_getsid(struct task_struct *p)
+
+ static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
+ {
+- selinux_get_task_sid(p, secid);
++ struct task_security_struct *tsec = p->security;
++ *secid = tsec->sid;
+ }
+
+ static int selinux_task_setgroups(struct group_info *group_info)
+@@ -3156,7 +3214,7 @@ static int selinux_task_setnice(struct task_struct *p, int nice)
+ if (rc)
+ return rc;
+
+- return task_has_perm(current,p, PROCESS__SETSCHED);
++ return task_has_perm(current, p, PROCESS__SETSCHED);
+ }
+
+ static int selinux_task_setioprio(struct task_struct *p, int ioprio)
+@@ -3260,7 +3318,7 @@ static int selinux_task_wait(struct task_struct *p)
+
+ static void selinux_task_reparent_to_init(struct task_struct *p)
+ {
+- struct task_security_struct *tsec;
++ struct task_security_struct *tsec;
+
+ secondary_ops->task_reparent_to_init(p);
+
+@@ -3305,11 +3363,11 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
+ *proto = ih->protocol;
+
+ switch (ih->protocol) {
+- case IPPROTO_TCP: {
+- struct tcphdr _tcph, *th;
++ case IPPROTO_TCP: {
++ struct tcphdr _tcph, *th;
+
+- if (ntohs(ih->frag_off) & IP_OFFSET)
+- break;
++ if (ntohs(ih->frag_off) & IP_OFFSET)
++ break;
+
+ offset += ihlen;
+ th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
+@@ -3319,23 +3377,23 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
+ ad->u.net.sport = th->source;
+ ad->u.net.dport = th->dest;
+ break;
+- }
+-
+- case IPPROTO_UDP: {
+- struct udphdr _udph, *uh;
+-
+- if (ntohs(ih->frag_off) & IP_OFFSET)
+- break;
+-
++ }
++
++ case IPPROTO_UDP: {
++ struct udphdr _udph, *uh;
++
++ if (ntohs(ih->frag_off) & IP_OFFSET)
++ break;
++
+ offset += ihlen;
+- uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
++ uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
+ if (uh == NULL)
+- break;
++ break;
+
+- ad->u.net.sport = uh->source;
+- ad->u.net.dport = uh->dest;
+- break;
+- }
++ ad->u.net.sport = uh->source;
++ ad->u.net.dport = uh->dest;
++ break;
++ }
+
+ case IPPROTO_DCCP: {
+ struct dccp_hdr _dccph, *dh;
+@@ -3351,11 +3409,11 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
+ ad->u.net.sport = dh->dccph_sport;
+ ad->u.net.dport = dh->dccph_dport;
+ break;
+- }
++ }
+
+- default:
+- break;
+- }
++ default:
++ break;
++ }
+ out:
+ return ret;
+ }
+@@ -3390,7 +3448,7 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
+
+ switch (nexthdr) {
+ case IPPROTO_TCP: {
+- struct tcphdr _tcph, *th;
++ struct tcphdr _tcph, *th;
+
+ th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
+ if (th == NULL)
+@@ -3423,7 +3481,7 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
+ ad->u.net.sport = dh->dccph_sport;
+ ad->u.net.dport = dh->dccph_dport;
+ break;
+- }
++ }
+
+ /* includes fragments */
+ default:
+@@ -3521,7 +3579,7 @@ static int socket_has_perm(struct task_struct *task, struct socket *sock,
+ if (isec->sid == SECINITSID_KERNEL)
+ goto out;
+
+- AVC_AUDIT_DATA_INIT(&ad,NET);
++ AVC_AUDIT_DATA_INIT(&ad, NET);
+ ad.u.net.sk = sock->sk;
+ err = avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
+
+@@ -3627,13 +3685,11 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
+ inet_get_local_port_range(&low, &high);
+
+ if (snum < max(PROT_SOCK, low) || snum > high) {
+- err = security_port_sid(sk->sk_family,
+- sk->sk_type,
+- sk->sk_protocol, snum,
+- &sid);
++ err = sel_netport_sid(sk->sk_protocol,
++ snum, &sid);
+ if (err)
+ goto out;
+- AVC_AUDIT_DATA_INIT(&ad,NET);
++ AVC_AUDIT_DATA_INIT(&ad, NET);
+ ad.u.net.sport = htons(snum);
+ ad.u.net.family = family;
+ err = avc_has_perm(isec->sid, sid,
+@@ -3643,12 +3699,12 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
+ goto out;
+ }
+ }
+-
+- switch(isec->sclass) {
++
++ switch (isec->sclass) {
+ case SECCLASS_TCP_SOCKET:
+ node_perm = TCP_SOCKET__NODE_BIND;
+ break;
+-
++
+ case SECCLASS_UDP_SOCKET:
+ node_perm = UDP_SOCKET__NODE_BIND;
+ break;
+@@ -3661,12 +3717,12 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
+ node_perm = RAWIP_SOCKET__NODE_BIND;
+ break;
+ }
+-
++
+ err = sel_netnode_sid(addrp, family, &sid);
+ if (err)
+ goto out;
+-
+- AVC_AUDIT_DATA_INIT(&ad,NET);
++
++ AVC_AUDIT_DATA_INIT(&ad, NET);
+ ad.u.net.sport = htons(snum);
+ ad.u.net.family = family;
+
+@@ -3676,7 +3732,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
+ ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr);
+
+ err = avc_has_perm(isec->sid, sid,
+- isec->sclass, node_perm, &ad);
++ isec->sclass, node_perm, &ad);
+ if (err)
+ goto out;
+ }
+@@ -3718,15 +3774,14 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
+ snum = ntohs(addr6->sin6_port);
+ }
+
+- err = security_port_sid(sk->sk_family, sk->sk_type,
+- sk->sk_protocol, snum, &sid);
++ err = sel_netport_sid(sk->sk_protocol, snum, &sid);
+ if (err)
+ goto out;
+
+ perm = (isec->sclass == SECCLASS_TCP_SOCKET) ?
+ TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
+
+- AVC_AUDIT_DATA_INIT(&ad,NET);
++ AVC_AUDIT_DATA_INIT(&ad, NET);
+ ad.u.net.dport = htons(snum);
+ ad.u.net.family = sk->sk_family;
+ err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad);
+@@ -3764,7 +3819,7 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
+ }
+
+ static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
+- int size)
++ int size)
+ {
+ int rc;
+
+@@ -3791,7 +3846,7 @@ static int selinux_socket_getpeername(struct socket *sock)
+ return socket_has_perm(current, sock, SOCKET__GETATTR);
+ }
+
+-static int selinux_socket_setsockopt(struct socket *sock,int level,int optname)
++static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
+ {
+ int err;
+
+@@ -3830,7 +3885,7 @@ static int selinux_socket_unix_stream_connect(struct socket *sock,
+ isec = SOCK_INODE(sock)->i_security;
+ other_isec = SOCK_INODE(other)->i_security;
+
+- AVC_AUDIT_DATA_INIT(&ad,NET);
++ AVC_AUDIT_DATA_INIT(&ad, NET);
+ ad.u.net.sk = other->sk;
+
+ err = avc_has_perm(isec->sid, other_isec->sid,
+@@ -3842,7 +3897,7 @@ static int selinux_socket_unix_stream_connect(struct socket *sock,
+ /* connecting socket */
+ ssec = sock->sk->sk_security;
+ ssec->peer_sid = other_isec->sid;
+-
++
+ /* server child socket */
+ ssec = newsk->sk_security;
+ ssec->peer_sid = isec->sid;
+@@ -3862,7 +3917,7 @@ static int selinux_socket_unix_may_send(struct socket *sock,
+ isec = SOCK_INODE(sock)->i_security;
+ other_isec = SOCK_INODE(other)->i_security;
+
+- AVC_AUDIT_DATA_INIT(&ad,NET);
++ AVC_AUDIT_DATA_INIT(&ad, NET);
+ ad.u.net.sk = other->sk;
+
+ err = avc_has_perm(isec->sid, other_isec->sid,
+@@ -3940,7 +3995,7 @@ static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
+ err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
+ if (err)
+ return err;
+-
++
+ err = sel_netnode_sid(addrp, family, &node_sid);
+ if (err)
+ return err;
+@@ -3950,9 +4005,8 @@ static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
+
+ if (!recv_perm)
+ return 0;
+- err = security_port_sid(sk->sk_family, sk->sk_type,
+- sk->sk_protocol, ntohs(ad->u.net.sport),
+- &port_sid);
++ err = sel_netport_sid(sk->sk_protocol,
++ ntohs(ad->u.net.sport), &port_sid);
+ if (unlikely(err)) {
+ printk(KERN_WARNING
+ "SELinux: failure in"
+@@ -4092,7 +4146,7 @@ out_len:
+ err = -EFAULT;
+
+ kfree(scontext);
+-out:
++out:
+ return err;
+ }
+
+@@ -4109,7 +4163,7 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
+ goto out;
+
+ if (sock && family == PF_UNIX)
+- selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
++ selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
+ else if (skb)
+ selinux_skb_peerlbl_sid(skb, family, &peer_secid);
+
+@@ -4139,7 +4193,7 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
+ newssec->peer_sid = ssec->peer_sid;
+ newssec->sclass = ssec->sclass;
+
+- selinux_netlbl_sk_security_clone(ssec, newssec);
++ selinux_netlbl_sk_security_reset(newssec, newsk->sk_family);
+ }
+
+ static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
+@@ -4153,7 +4207,7 @@ static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
+ }
+ }
+
+-static void selinux_sock_graft(struct sock* sk, struct socket *parent)
++static void selinux_sock_graft(struct sock *sk, struct socket *parent)
+ {
+ struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
+ struct sk_security_struct *sksec = sk->sk_security;
+@@ -4230,13 +4284,13 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
+ struct nlmsghdr *nlh;
+ struct socket *sock = sk->sk_socket;
+ struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
+-
++
+ if (skb->len < NLMSG_SPACE(0)) {
+ err = -EINVAL;
+ goto out;
+ }
+ nlh = nlmsg_hdr(skb);
+-
++
+ err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm);
+ if (err) {
+ if (err == -EINVAL) {
+@@ -4362,7 +4416,7 @@ static int selinux_ip_postroute_iptables_compat(struct sock *sk,
+ return err;
+ err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
+ return err;
+-
++
+ err = sel_netnode_sid(addrp, family, &node_sid);
+ if (err)
+ return err;
+@@ -4373,9 +4427,8 @@ static int selinux_ip_postroute_iptables_compat(struct sock *sk,
+ if (send_perm != 0)
+ return 0;
+
+- err = security_port_sid(sk->sk_family, sk->sk_type,
+- sk->sk_protocol, ntohs(ad->u.net.dport),
+- &port_sid);
++ err = sel_netport_sid(sk->sk_protocol,
++ ntohs(ad->u.net.dport), &port_sid);
+ if (unlikely(err)) {
+ printk(KERN_WARNING
+ "SELinux: failure in"
+@@ -4546,7 +4599,7 @@ static int selinux_netlink_recv(struct sk_buff *skb, int capability)
+ ad.u.cap = capability;
+
+ return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid,
+- SECCLASS_CAPABILITY, CAP_TO_MASK(capability), &ad);
++ SECCLASS_CAPABILITY, CAP_TO_MASK(capability), &ad);
+ }
+
+ static int ipc_alloc_security(struct task_struct *task,
+@@ -4561,7 +4614,6 @@ static int ipc_alloc_security(struct task_struct *task,
+ return -ENOMEM;
+
+ isec->sclass = sclass;
+- isec->ipc_perm = perm;
+ isec->sid = tsec->sid;
+ perm->security = isec;
+
+@@ -4583,7 +4635,6 @@ static int msg_msg_alloc_security(struct msg_msg *msg)
+ if (!msec)
+ return -ENOMEM;
+
+- msec->msg = msg;
+ msec->sid = SECINITSID_UNLABELED;
+ msg->security = msec;
+
+@@ -4640,7 +4691,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
+ isec = msq->q_perm.security;
+
+ AVC_AUDIT_DATA_INIT(&ad, IPC);
+- ad.u.ipc_id = msq->q_perm.key;
++ ad.u.ipc_id = msq->q_perm.key;
+
+ rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
+ MSGQ__CREATE, &ad);
+@@ -4677,7 +4728,7 @@ static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
+ int err;
+ int perms;
+
+- switch(cmd) {
++ switch (cmd) {
+ case IPC_INFO:
+ case MSG_INFO:
+ /* No specific object, just general system-wide information. */
+@@ -4761,7 +4812,7 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
+ msec = msg->security;
+
+ AVC_AUDIT_DATA_INIT(&ad, IPC);
+- ad.u.ipc_id = msq->q_perm.key;
++ ad.u.ipc_id = msq->q_perm.key;
+
+ rc = avc_has_perm(tsec->sid, isec->sid,
+ SECCLASS_MSGQ, MSGQ__READ, &ad);
+@@ -4787,7 +4838,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp)
+ isec = shp->shm_perm.security;
+
+ AVC_AUDIT_DATA_INIT(&ad, IPC);
+- ad.u.ipc_id = shp->shm_perm.key;
++ ad.u.ipc_id = shp->shm_perm.key;
+
+ rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
+ SHM__CREATE, &ad);
+@@ -4825,7 +4876,7 @@ static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
+ int perms;
+ int err;
+
+- switch(cmd) {
++ switch (cmd) {
+ case IPC_INFO:
+ case SHM_INFO:
+ /* No specific object, just general system-wide information. */
+@@ -4886,7 +4937,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma)
+ isec = sma->sem_perm.security;
+
+ AVC_AUDIT_DATA_INIT(&ad, IPC);
+- ad.u.ipc_id = sma->sem_perm.key;
++ ad.u.ipc_id = sma->sem_perm.key;
+
+ rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
+ SEM__CREATE, &ad);
+@@ -4924,7 +4975,7 @@ static int selinux_sem_semctl(struct sem_array *sma, int cmd)
+ int err;
+ u32 perms;
+
+- switch(cmd) {
++ switch (cmd) {
+ case IPC_INFO:
+ case SEM_INFO:
+ /* No specific object, just general system-wide information. */
+@@ -4989,25 +5040,31 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
+ return ipc_has_perm(ipcp, av);
+ }
+
++static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
++{
++ struct ipc_security_struct *isec = ipcp->security;
++ *secid = isec->sid;
++}
++
+ /* module stacking operations */
+-static int selinux_register_security (const char *name, struct security_operations *ops)
++static int selinux_register_security(const char *name, struct security_operations *ops)
+ {
+ if (secondary_ops != original_ops) {
+ printk(KERN_ERR "%s: There is already a secondary security "
+- "module registered.\n", __FUNCTION__);
++ "module registered.\n", __func__);
+ return -EINVAL;
+- }
++ }
+
+ secondary_ops = ops;
+
+ printk(KERN_INFO "%s: Registering secondary module %s\n",
+- __FUNCTION__,
++ __func__,
+ name);
+
+ return 0;
+ }
+
+-static void selinux_d_instantiate (struct dentry *dentry, struct inode *inode)
++static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
+ {
+ if (inode)
+ inode_doinit_with_dentry(inode, dentry);
+@@ -5057,6 +5114,7 @@ static int selinux_setprocattr(struct task_struct *p,
+ char *name, void *value, size_t size)
+ {
+ struct task_security_struct *tsec;
++ struct task_struct *tracer;
+ u32 sid = 0;
+ int error;
+ char *str = value;
+@@ -5134,34 +5192,39 @@ static int selinux_setprocattr(struct task_struct *p,
+ }
+ while_each_thread(g, t);
+ read_unlock(&tasklist_lock);
+- }
++ }
+
+ /* Check permissions for the transition. */
+ error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
+- PROCESS__DYNTRANSITION, NULL);
++ PROCESS__DYNTRANSITION, NULL);
+ if (error)
+ return error;
+
+ /* Check for ptracing, and update the task SID if ok.
+ Otherwise, leave SID unchanged and fail. */
+ task_lock(p);
+- if (p->ptrace & PT_PTRACED) {
+- error = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
++ rcu_read_lock();
++ tracer = task_tracer_task(p);
++ if (tracer != NULL) {
++ struct task_security_struct *ptsec = tracer->security;
++ u32 ptsid = ptsec->sid;
++ rcu_read_unlock();
++ error = avc_has_perm_noaudit(ptsid, sid,
+ SECCLASS_PROCESS,
+ PROCESS__PTRACE, 0, &avd);
+ if (!error)
+ tsec->sid = sid;
+ task_unlock(p);
+- avc_audit(tsec->ptrace_sid, sid, SECCLASS_PROCESS,
++ avc_audit(ptsid, sid, SECCLASS_PROCESS,
+ PROCESS__PTRACE, &avd, error, NULL);
+ if (error)
+ return error;
+ } else {
++ rcu_read_unlock();
+ tsec->sid = sid;
+ task_unlock(p);
+ }
+- }
+- else
++ } else
+ return -EINVAL;
+
+ return size;
+@@ -5194,7 +5257,6 @@ static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
+ if (!ksec)
+ return -ENOMEM;
+
+- ksec->obj = k;
+ if (tsec->keycreate_sid)
+ ksec->sid = tsec->keycreate_sid;
+ else
+@@ -5238,6 +5300,8 @@ static int selinux_key_permission(key_ref_t key_ref,
+ #endif
+
+ static struct security_operations selinux_ops = {
++ .name = "selinux",
++
+ .ptrace = selinux_ptrace,
+ .capget = selinux_capget,
+ .capset_check = selinux_capset_check,
+@@ -5250,7 +5314,7 @@ static struct security_operations selinux_ops = {
+ .vm_enough_memory = selinux_vm_enough_memory,
+
+ .netlink_send = selinux_netlink_send,
+- .netlink_recv = selinux_netlink_recv,
++ .netlink_recv = selinux_netlink_recv,
+
+ .bprm_alloc_security = selinux_bprm_alloc_security,
+ .bprm_free_security = selinux_bprm_free_security,
+@@ -5263,13 +5327,13 @@ static struct security_operations selinux_ops = {
+ .sb_alloc_security = selinux_sb_alloc_security,
+ .sb_free_security = selinux_sb_free_security,
+ .sb_copy_data = selinux_sb_copy_data,
+- .sb_kern_mount = selinux_sb_kern_mount,
++ .sb_kern_mount = selinux_sb_kern_mount,
+ .sb_statfs = selinux_sb_statfs,
+ .sb_mount = selinux_mount,
+ .sb_umount = selinux_umount,
+ .sb_get_mnt_opts = selinux_get_mnt_opts,
+ .sb_set_mnt_opts = selinux_set_mnt_opts,
+- .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
++ .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
+ .sb_parse_opts_str = selinux_parse_opts_str,
+
+
+@@ -5294,11 +5358,12 @@ static struct security_operations selinux_ops = {
+ .inode_getxattr = selinux_inode_getxattr,
+ .inode_listxattr = selinux_inode_listxattr,
+ .inode_removexattr = selinux_inode_removexattr,
+- .inode_getsecurity = selinux_inode_getsecurity,
+- .inode_setsecurity = selinux_inode_setsecurity,
+- .inode_listsecurity = selinux_inode_listsecurity,
++ .inode_getsecurity = selinux_inode_getsecurity,
++ .inode_setsecurity = selinux_inode_setsecurity,
++ .inode_listsecurity = selinux_inode_listsecurity,
+ .inode_need_killpriv = selinux_inode_need_killpriv,
+ .inode_killpriv = selinux_inode_killpriv,
++ .inode_getsecid = selinux_inode_getsecid,
+
+ .file_permission = selinux_file_permission,
+ .file_alloc_security = selinux_file_alloc_security,
+@@ -5312,7 +5377,7 @@ static struct security_operations selinux_ops = {
+ .file_send_sigiotask = selinux_file_send_sigiotask,
+ .file_receive = selinux_file_receive,
+
+- .dentry_open = selinux_dentry_open,
++ .dentry_open = selinux_dentry_open,
+
+ .task_create = selinux_task_create,
+ .task_alloc_security = selinux_task_alloc_security,
+@@ -5322,7 +5387,7 @@ static struct security_operations selinux_ops = {
+ .task_setgid = selinux_task_setgid,
+ .task_setpgid = selinux_task_setpgid,
+ .task_getpgid = selinux_task_getpgid,
+- .task_getsid = selinux_task_getsid,
++ .task_getsid = selinux_task_getsid,
+ .task_getsecid = selinux_task_getsecid,
+ .task_setgroups = selinux_task_setgroups,
+ .task_setnice = selinux_task_setnice,
+@@ -5336,9 +5401,10 @@ static struct security_operations selinux_ops = {
+ .task_wait = selinux_task_wait,
+ .task_prctl = selinux_task_prctl,
+ .task_reparent_to_init = selinux_task_reparent_to_init,
+- .task_to_inode = selinux_task_to_inode,
++ .task_to_inode = selinux_task_to_inode,
+
+ .ipc_permission = selinux_ipc_permission,
++ .ipc_getsecid = selinux_ipc_getsecid,
+
+ .msg_msg_alloc_security = selinux_msg_msg_alloc_security,
+ .msg_msg_free_security = selinux_msg_msg_free_security,
+@@ -5356,24 +5422,24 @@ static struct security_operations selinux_ops = {
+ .shm_shmctl = selinux_shm_shmctl,
+ .shm_shmat = selinux_shm_shmat,
+
+- .sem_alloc_security = selinux_sem_alloc_security,
+- .sem_free_security = selinux_sem_free_security,
++ .sem_alloc_security = selinux_sem_alloc_security,
++ .sem_free_security = selinux_sem_free_security,
+ .sem_associate = selinux_sem_associate,
+ .sem_semctl = selinux_sem_semctl,
+ .sem_semop = selinux_sem_semop,
+
+ .register_security = selinux_register_security,
+
+- .d_instantiate = selinux_d_instantiate,
++ .d_instantiate = selinux_d_instantiate,
+
+- .getprocattr = selinux_getprocattr,
+- .setprocattr = selinux_setprocattr,
++ .getprocattr = selinux_getprocattr,
++ .setprocattr = selinux_setprocattr,
+
+ .secid_to_secctx = selinux_secid_to_secctx,
+ .secctx_to_secid = selinux_secctx_to_secid,
+ .release_secctx = selinux_release_secctx,
+
+- .unix_stream_connect = selinux_socket_unix_stream_connect,
++ .unix_stream_connect = selinux_socket_unix_stream_connect,
+ .unix_may_send = selinux_socket_unix_may_send,
+
+ .socket_create = selinux_socket_create,
+@@ -5395,7 +5461,7 @@ static struct security_operations selinux_ops = {
+ .sk_alloc_security = selinux_sk_alloc_security,
+ .sk_free_security = selinux_sk_free_security,
+ .sk_clone_security = selinux_sk_clone_security,
+- .sk_getsecid = selinux_sk_getsecid,
++ .sk_getsecid = selinux_sk_getsecid,
+ .sock_graft = selinux_sock_graft,
+ .inet_conn_request = selinux_inet_conn_request,
+ .inet_csk_clone = selinux_inet_csk_clone,
+@@ -5410,15 +5476,22 @@ static struct security_operations selinux_ops = {
+ .xfrm_state_alloc_security = selinux_xfrm_state_alloc,
+ .xfrm_state_free_security = selinux_xfrm_state_free,
+ .xfrm_state_delete_security = selinux_xfrm_state_delete,
+- .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
++ .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
+ .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
+ .xfrm_decode_session = selinux_xfrm_decode_session,
+ #endif
+
+ #ifdef CONFIG_KEYS
+- .key_alloc = selinux_key_alloc,
+- .key_free = selinux_key_free,
+- .key_permission = selinux_key_permission,
++ .key_alloc = selinux_key_alloc,
++ .key_free = selinux_key_free,
++ .key_permission = selinux_key_permission,
++#endif
++
++#ifdef CONFIG_AUDIT
++ .audit_rule_init = selinux_audit_rule_init,
++ .audit_rule_known = selinux_audit_rule_known,
++ .audit_rule_match = selinux_audit_rule_match,
++ .audit_rule_free = selinux_audit_rule_free,
+ #endif
+ };
+
+@@ -5426,6 +5499,11 @@ static __init int selinux_init(void)
+ {
+ struct task_security_struct *tsec;
+
++ if (!security_module_enable(&selinux_ops)) {
++ selinux_enabled = 0;
++ return 0;
++ }
++
+ if (!selinux_enabled) {
+ printk(KERN_INFO "SELinux: Disabled at boot.\n");
+ return 0;
+@@ -5446,15 +5524,14 @@ static __init int selinux_init(void)
+
+ original_ops = secondary_ops = security_ops;
+ if (!secondary_ops)
+- panic ("SELinux: No initial security operations\n");
+- if (register_security (&selinux_ops))
++ panic("SELinux: No initial security operations\n");
++ if (register_security(&selinux_ops))
+ panic("SELinux: Unable to register with kernel.\n");
+
+- if (selinux_enforcing) {
++ if (selinux_enforcing)
+ printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
+- } else {
++ else
+ printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
+- }
+
+ #ifdef CONFIG_KEYS
+ /* Add security information to initial keyrings */
+@@ -5479,8 +5556,8 @@ next_sb:
+ if (!list_empty(&superblock_security_head)) {
+ struct superblock_security_struct *sbsec =
+ list_entry(superblock_security_head.next,
+- struct superblock_security_struct,
+- list);
++ struct superblock_security_struct,
++ list);
+ struct super_block *sb = sbsec->sb;
+ sb->s_count++;
+ spin_unlock(&sb_security_lock);
+@@ -5599,10 +5676,11 @@ static void selinux_nf_ip_exit(void)
+ #endif /* CONFIG_NETFILTER */
+
+ #ifdef CONFIG_SECURITY_SELINUX_DISABLE
++static int selinux_disabled;
++
+ int selinux_disable(void)
+ {
+ extern void exit_sel_fs(void);
+- static int selinux_disabled = 0;
+
+ if (ss_initialized) {
+ /* Not permitted after initial policy load. */
+@@ -5631,5 +5709,3 @@ int selinux_disable(void)
+ return 0;
+ }
+ #endif
+-
+-
+diff --git a/security/selinux/include/audit.h b/security/selinux/include/audit.h
+new file mode 100644
+index 0000000..6c8b9ef
+--- /dev/null
++++ b/security/selinux/include/audit.h
+@@ -0,0 +1,65 @@
++/*
++ * SELinux support for the Audit LSM hooks
++ *
++ * Most of below header was moved from include/linux/selinux.h which
++ * is released under below copyrights:
++ *
++ * Author: James Morris <jmorris at redhat.com>
++ *
++ * Copyright (C) 2005 Red Hat, Inc., James Morris <jmorris at redhat.com>
++ * Copyright (C) 2006 Trusted Computer Solutions, Inc. <dgoeddel at trustedcs.com>
++ * Copyright (C) 2006 IBM Corporation, Timothy R. Chavez <tinytim at us.ibm.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2,
++ * as published by the Free Software Foundation.
++ */
++
++#ifndef _SELINUX_AUDIT_H
++#define _SELINUX_AUDIT_H
++
++/**
++ * selinux_audit_rule_init - alloc/init an selinux audit rule structure.
++ * @field: the field this rule refers to
++ * @op: the operater the rule uses
++ * @rulestr: the text "target" of the rule
++ * @rule: pointer to the new rule structure returned via this
++ *
++ * Returns 0 if successful, -errno if not. On success, the rule structure
++ * will be allocated internally. The caller must free this structure with
++ * selinux_audit_rule_free() after use.
++ */
++int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **rule);
++
++/**
++ * selinux_audit_rule_free - free an selinux audit rule structure.
++ * @rule: pointer to the audit rule to be freed
++ *
++ * This will free all memory associated with the given rule.
++ * If @rule is NULL, no operation is performed.
++ */
++void selinux_audit_rule_free(void *rule);
++
++/**
++ * selinux_audit_rule_match - determine if a context ID matches a rule.
++ * @sid: the context ID to check
++ * @field: the field this rule refers to
++ * @op: the operater the rule uses
++ * @rule: pointer to the audit rule to check against
++ * @actx: the audit context (can be NULL) associated with the check
++ *
++ * Returns 1 if the context id matches the rule, 0 if it does not, and
++ * -errno on failure.
++ */
++int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *rule,
++ struct audit_context *actx);
++
++/**
++ * selinux_audit_rule_known - check to see if rule contains selinux fields.
++ * @rule: rule to be checked
++ * Returns 1 if there are selinux fields specified in the rule, 0 otherwise.
++ */
++int selinux_audit_rule_known(struct audit_krule *krule);
++
++#endif /* _SELINUX_AUDIT_H */
++
+diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
+index d569669..1223b4f 100644
+--- a/security/selinux/include/av_perm_to_string.h
++++ b/security/selinux/include/av_perm_to_string.h
+@@ -14,12 +14,17 @@
+ S_(SECCLASS_DIR, DIR__REPARENT, "reparent")
+ S_(SECCLASS_DIR, DIR__SEARCH, "search")
+ S_(SECCLASS_DIR, DIR__RMDIR, "rmdir")
++ S_(SECCLASS_DIR, DIR__OPEN, "open")
+ S_(SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, "execute_no_trans")
+ S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint")
+ S_(SECCLASS_FILE, FILE__EXECMOD, "execmod")
++ S_(SECCLASS_FILE, FILE__OPEN, "open")
+ S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans")
+ S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint")
+ S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod")
++ S_(SECCLASS_CHR_FILE, CHR_FILE__OPEN, "open")
++ S_(SECCLASS_BLK_FILE, BLK_FILE__OPEN, "open")
++ S_(SECCLASS_FIFO_FILE, FIFO_FILE__OPEN, "open")
+ S_(SECCLASS_FD, FD__USE, "use")
+ S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__CONNECTTO, "connectto")
+ S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NEWCONN, "newconn")
+diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
+index 75b4131..c4c5116 100644
+--- a/security/selinux/include/av_permissions.h
++++ b/security/selinux/include/av_permissions.h
+@@ -79,6 +79,7 @@
+ #define DIR__REPARENT 0x00080000UL
+ #define DIR__SEARCH 0x00100000UL
+ #define DIR__RMDIR 0x00200000UL
++#define DIR__OPEN 0x00400000UL
+ #define FILE__IOCTL 0x00000001UL
+ #define FILE__READ 0x00000002UL
+ #define FILE__WRITE 0x00000004UL
+@@ -99,6 +100,7 @@
+ #define FILE__EXECUTE_NO_TRANS 0x00020000UL
+ #define FILE__ENTRYPOINT 0x00040000UL
+ #define FILE__EXECMOD 0x00080000UL
++#define FILE__OPEN 0x00100000UL
+ #define LNK_FILE__IOCTL 0x00000001UL
+ #define LNK_FILE__READ 0x00000002UL
+ #define LNK_FILE__WRITE 0x00000004UL
+@@ -136,6 +138,7 @@
+ #define CHR_FILE__EXECUTE_NO_TRANS 0x00020000UL
+ #define CHR_FILE__ENTRYPOINT 0x00040000UL
+ #define CHR_FILE__EXECMOD 0x00080000UL
++#define CHR_FILE__OPEN 0x00100000UL
+ #define BLK_FILE__IOCTL 0x00000001UL
+ #define BLK_FILE__READ 0x00000002UL
+ #define BLK_FILE__WRITE 0x00000004UL
+@@ -153,6 +156,7 @@
+ #define BLK_FILE__SWAPON 0x00004000UL
+ #define BLK_FILE__QUOTAON 0x00008000UL
+ #define BLK_FILE__MOUNTON 0x00010000UL
++#define BLK_FILE__OPEN 0x00020000UL
+ #define SOCK_FILE__IOCTL 0x00000001UL
+ #define SOCK_FILE__READ 0x00000002UL
+ #define SOCK_FILE__WRITE 0x00000004UL
+@@ -187,6 +191,7 @@
+ #define FIFO_FILE__SWAPON 0x00004000UL
+ #define FIFO_FILE__QUOTAON 0x00008000UL
+ #define FIFO_FILE__MOUNTON 0x00010000UL
++#define FIFO_FILE__OPEN 0x00020000UL
+ #define FD__USE 0x00000001UL
+ #define SOCKET__IOCTL 0x00000001UL
+ #define SOCKET__READ 0x00000002UL
+diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h
+index 00a2809..9a9e7cd 100644
+--- a/security/selinux/include/netlabel.h
++++ b/security/selinux/include/netlabel.h
+@@ -41,10 +41,6 @@ void selinux_netlbl_cache_invalidate(void);
+
+ void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
+ int family);
+-void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
+- int family);
+-void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
+- struct sk_security_struct *newssec);
+
+ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
+ u16 family,
+@@ -73,18 +69,6 @@ static inline void selinux_netlbl_sk_security_reset(
+ {
+ return;
+ }
+-static inline void selinux_netlbl_sk_security_init(
+- struct sk_security_struct *ssec,
+- int family)
+-{
+- return;
+-}
+-static inline void selinux_netlbl_sk_security_clone(
+- struct sk_security_struct *ssec,
+- struct sk_security_struct *newssec)
+-{
+- return;
+-}
+
+ static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
+ u16 family,
+diff --git a/security/selinux/include/netport.h b/security/selinux/include/netport.h
+new file mode 100644
+index 0000000..8991752
+--- /dev/null
++++ b/security/selinux/include/netport.h
+@@ -0,0 +1,31 @@
++/*
++ * Network port table
++ *
++ * SELinux must keep a mapping of network ports to labels/SIDs. This
++ * mapping is maintained as part of the normal policy but a fast cache is
++ * needed to reduce the lookup overhead.
++ *
++ * Author: Paul Moore <paul.moore at hp.com>
++ *
++ */
++
++/*
++ * (c) Copyright Hewlett-Packard Development Company, L.P., 2008
++ *
++ * This program is free software: you can redistribute it and/or modify
++ * it under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ */
++
++#ifndef _SELINUX_NETPORT_H
++#define _SELINUX_NETPORT_H
++
++int sel_netport_sid(u8 protocol, u16 pnum, u32 *sid);
++
++#endif
+diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
+index c6c2bb4..300b61b 100644
+--- a/security/selinux/include/objsec.h
++++ b/security/selinux/include/objsec.h
+@@ -28,14 +28,12 @@
+ #include "avc.h"
+
+ struct task_security_struct {
+- struct task_struct *task; /* back pointer to task object */
+ u32 osid; /* SID prior to last execve */
+ u32 sid; /* current SID */
+ u32 exec_sid; /* exec SID */
+ u32 create_sid; /* fscreate SID */
+ u32 keycreate_sid; /* keycreate SID */
+ u32 sockcreate_sid; /* fscreate SID */
+- u32 ptrace_sid; /* SID of ptrace parent */
+ };
+
+ struct inode_security_struct {
+@@ -50,7 +48,6 @@ struct inode_security_struct {
+ };
+
+ struct file_security_struct {
+- struct file *file; /* back pointer to file object */
+ u32 sid; /* SID of open file description */
+ u32 fown_sid; /* SID of file owner (for SIGIO) */
+ u32 isid; /* SID of inode at the time of file open */
+@@ -73,18 +70,15 @@ struct superblock_security_struct {
+ };
+
+ struct msg_security_struct {
+- struct msg_msg *msg; /* back pointer */
+ u32 sid; /* SID of message */
+ };
+
+ struct ipc_security_struct {
+- struct kern_ipc_perm *ipc_perm; /* back pointer */
+ u16 sclass; /* security class of this object */
+ u32 sid; /* SID of IPC resource */
+ };
+
+ struct bprm_security_struct {
+- struct linux_binprm *bprm; /* back pointer to bprm object */
+ u32 sid; /* SID for transformed process */
+ unsigned char set;
+
+@@ -109,8 +103,13 @@ struct netnode_security_struct {
+ u16 family; /* address family */
+ };
+
++struct netport_security_struct {
++ u32 sid; /* SID for this node */
++ u16 port; /* port number */
++ u8 protocol; /* transport protocol */
++};
++
+ struct sk_security_struct {
+- struct sock *sk; /* back pointer to sk object */
+ u32 sid; /* SID of this object */
+ u32 peer_sid; /* SID of peer */
+ u16 sclass; /* sock security class */
+@@ -120,12 +119,10 @@ struct sk_security_struct {
+ NLBL_REQUIRE,
+ NLBL_LABELED,
+ } nlbl_state;
+- spinlock_t nlbl_lock; /* protects nlbl_state */
+ #endif
+ };
+
+ struct key_security_struct {
+- struct key *obj; /* back pointer */
+ u32 sid; /* SID of key */
+ };
+
+diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
+index 44e12ec..1904c46 100644
+--- a/security/selinux/include/security.h
++++ b/security/selinux/include/security.h
+@@ -26,13 +26,14 @@
+ #define POLICYDB_VERSION_AVTAB 20
+ #define POLICYDB_VERSION_RANGETRANS 21
+ #define POLICYDB_VERSION_POLCAP 22
++#define POLICYDB_VERSION_PERMISSIVE 23
+
+ /* Range of policy versions we understand*/
+ #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
+ #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
+ #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
+ #else
+-#define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP
++#define POLICYDB_VERSION_MAX POLICYDB_VERSION_PERMISSIVE
+ #endif
+
+ #define CONTEXT_MNT 0x01
+@@ -40,6 +41,11 @@
+ #define ROOTCONTEXT_MNT 0x04
+ #define DEFCONTEXT_MNT 0x08
+
++#define CONTEXT_STR "context="
++#define FSCONTEXT_STR "fscontext="
++#define ROOTCONTEXT_STR "rootcontext="
++#define DEFCONTEXT_STR "defcontext="
++
+ struct netlbl_lsm_secattr;
+
+ extern int selinux_enabled;
+@@ -48,11 +54,13 @@ extern int selinux_mls_enabled;
+ /* Policy capabilities */
+ enum {
+ POLICYDB_CAPABILITY_NETPEER,
++ POLICYDB_CAPABILITY_OPENPERM,
+ __POLICYDB_CAPABILITY_MAX
+ };
+ #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
+
+ extern int selinux_policycap_netpeer;
++extern int selinux_policycap_openperm;
+
+ int security_load_policy(void * data, size_t len);
+
+@@ -67,6 +75,8 @@ struct av_decision {
+ u32 seqno;
+ };
+
++int security_permissive_sid(u32 sid);
++
+ int security_compute_av(u32 ssid, u32 tsid,
+ u16 tclass, u32 requested,
+ struct av_decision *avd);
+@@ -92,8 +102,7 @@ int security_context_to_sid_default(char *scontext, u32 scontext_len,
+ int security_get_user_sids(u32 callsid, char *username,
+ u32 **sids, u32 *nel);
+
+-int security_port_sid(u16 domain, u16 type, u8 protocol, u16 port,
+- u32 *out_sid);
++int security_port_sid(u8 protocol, u16 port, u32 *out_sid);
+
+ int security_netif_sid(char *name, u32 *if_sid);
+
+diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
+index 36b0510..289e24b 100644
+--- a/security/selinux/include/xfrm.h
++++ b/security/selinux/include/xfrm.h
+@@ -7,16 +7,17 @@
+ #ifndef _SELINUX_XFRM_H_
+ #define _SELINUX_XFRM_H_
+
+-int selinux_xfrm_policy_alloc(struct xfrm_policy *xp,
+- struct xfrm_user_sec_ctx *sec_ctx);
+-int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new);
+-void selinux_xfrm_policy_free(struct xfrm_policy *xp);
+-int selinux_xfrm_policy_delete(struct xfrm_policy *xp);
++int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
++ struct xfrm_user_sec_ctx *sec_ctx);
++int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
++ struct xfrm_sec_ctx **new_ctxp);
++void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx);
++int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx);
+ int selinux_xfrm_state_alloc(struct xfrm_state *x,
+ struct xfrm_user_sec_ctx *sec_ctx, u32 secid);
+ void selinux_xfrm_state_free(struct xfrm_state *x);
+ int selinux_xfrm_state_delete(struct xfrm_state *x);
+-int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
++int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir);
+ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
+ struct xfrm_policy *xp, struct flowi *fl);
+
+diff --git a/security/selinux/netif.c b/security/selinux/netif.c
+index 013d311..b4e14bc 100644
+--- a/security/selinux/netif.c
++++ b/security/selinux/netif.c
+@@ -8,7 +8,7 @@
+ *
+ * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris at redhat.com>
+ * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
+- * Paul Moore <paul.moore at hp.com>
++ * Paul Moore <paul.moore at hp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+@@ -31,8 +31,7 @@
+ #define SEL_NETIF_HASH_SIZE 64
+ #define SEL_NETIF_HASH_MAX 1024
+
+-struct sel_netif
+-{
++struct sel_netif {
+ struct list_head list;
+ struct netif_security_struct nsec;
+ struct rcu_head rcu_head;
+@@ -92,10 +91,10 @@ static inline struct sel_netif *sel_netif_find(int ifindex)
+ static int sel_netif_insert(struct sel_netif *netif)
+ {
+ int idx;
+-
++
+ if (sel_netif_total >= SEL_NETIF_HASH_MAX)
+ return -ENOSPC;
+-
++
+ idx = sel_netif_hashfn(netif->nsec.ifindex);
+ list_add_rcu(&netif->list, &sel_netif_hash[idx]);
+ sel_netif_total++;
+@@ -240,11 +239,13 @@ static void sel_netif_kill(int ifindex)
+ {
+ struct sel_netif *netif;
+
++ rcu_read_lock();
+ spin_lock_bh(&sel_netif_lock);
+ netif = sel_netif_find(ifindex);
+ if (netif)
+ sel_netif_destroy(netif);
+ spin_unlock_bh(&sel_netif_lock);
++ rcu_read_unlock();
+ }
+
+ /**
+@@ -267,7 +268,7 @@ static void sel_netif_flush(void)
+ }
+
+ static int sel_netif_avc_callback(u32 event, u32 ssid, u32 tsid,
+- u16 class, u32 perms, u32 *retained)
++ u16 class, u32 perms, u32 *retained)
+ {
+ if (event == AVC_CALLBACK_RESET) {
+ sel_netif_flush();
+@@ -277,11 +278,11 @@ static int sel_netif_avc_callback(u32 event, u32 ssid, u32 tsid,
+ }
+
+ static int sel_netif_netdev_notifier_handler(struct notifier_block *this,
+- unsigned long event, void *ptr)
++ unsigned long event, void *ptr)
+ {
+ struct net_device *dev = ptr;
+
+- if (dev->nd_net != &init_net)
++ if (dev_net(dev) != &init_net)
+ return NOTIFY_DONE;
+
+ if (event == NETDEV_DOWN)
+@@ -297,7 +298,7 @@ static struct notifier_block sel_netif_netdev_notifier = {
+ static __init int sel_netif_init(void)
+ {
+ int i, err;
+-
++
+ if (!selinux_enabled)
+ return 0;
+
+@@ -305,9 +306,9 @@ static __init int sel_netif_init(void)
+ INIT_LIST_HEAD(&sel_netif_hash[i]);
+
+ register_netdevice_notifier(&sel_netif_netdev_notifier);
+-
++
+ err = avc_add_callback(sel_netif_avc_callback, AVC_CALLBACK_RESET,
+- SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
++ SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
+ if (err)
+ panic("avc_add_callback() failed, error %d\n", err);
+
+diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
+index 0fa2be4..89b4183 100644
+--- a/security/selinux/netlabel.c
++++ b/security/selinux/netlabel.c
+@@ -34,6 +34,7 @@
+
+ #include "objsec.h"
+ #include "security.h"
++#include "netlabel.h"
+
+ /**
+ * selinux_netlbl_sidlookup_cached - Cache a SID lookup
+@@ -69,9 +70,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
+ *
+ * Description:
+ * Attempt to label a socket using the NetLabel mechanism using the given
+- * SID. Returns zero values on success, negative values on failure. The
+- * caller is responsibile for calling rcu_read_lock() before calling this
+- * this function and rcu_read_unlock() after this function returns.
++ * SID. Returns zero values on success, negative values on failure.
+ *
+ */
+ static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid)
+@@ -86,11 +85,8 @@ static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid)
+ if (rc != 0)
+ goto sock_setsid_return;
+ rc = netlbl_sock_setattr(sk, &secattr);
+- if (rc == 0) {
+- spin_lock_bh(&sksec->nlbl_lock);
++ if (rc == 0)
+ sksec->nlbl_state = NLBL_LABELED;
+- spin_unlock_bh(&sksec->nlbl_lock);
+- }
+
+ sock_setsid_return:
+ netlbl_secattr_destroy(&secattr);
+@@ -122,52 +118,13 @@ void selinux_netlbl_cache_invalidate(void)
+ void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
+ int family)
+ {
+- if (family == PF_INET)
++ if (family == PF_INET)
+ ssec->nlbl_state = NLBL_REQUIRE;
+ else
+ ssec->nlbl_state = NLBL_UNSET;
+ }
+
+ /**
+- * selinux_netlbl_sk_security_init - Setup the NetLabel fields
+- * @ssec: the sk_security_struct
+- * @family: the socket family
+- *
+- * Description:
+- * Called when a new sk_security_struct is allocated to initialize the NetLabel
+- * fields.
+- *
+- */
+-void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
+- int family)
+-{
+- /* No locking needed, we are the only one who has access to ssec */
+- selinux_netlbl_sk_security_reset(ssec, family);
+- spin_lock_init(&ssec->nlbl_lock);
+-}
+-
+-/**
+- * selinux_netlbl_sk_security_clone - Copy the NetLabel fields
+- * @ssec: the original sk_security_struct
+- * @newssec: the cloned sk_security_struct
+- *
+- * Description:
+- * Clone the NetLabel specific sk_security_struct fields from @ssec to
+- * @newssec.
+- *
+- */
+-void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
+- struct sk_security_struct *newssec)
+-{
+- /* We don't need to take newssec->nlbl_lock because we are the only
+- * thread with access to newssec, but we do need to take the RCU read
+- * lock as other threads could have access to ssec */
+- rcu_read_lock();
+- selinux_netlbl_sk_security_reset(newssec, ssec->sk->sk_family);
+- rcu_read_unlock();
+-}
+-
+-/**
+ * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel
+ * @skb: the packet
+ * @family: protocol family
+@@ -221,12 +178,8 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
+ struct netlbl_lsm_secattr secattr;
+ u32 nlbl_peer_sid;
+
+- rcu_read_lock();
+-
+- if (sksec->nlbl_state != NLBL_REQUIRE) {
+- rcu_read_unlock();
++ if (sksec->nlbl_state != NLBL_REQUIRE)
+ return;
+- }
+
+ netlbl_secattr_init(&secattr);
+ if (netlbl_sock_getattr(sk, &secattr) == 0 &&
+@@ -239,8 +192,6 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
+ * here we will pick up the pieces in later calls to
+ * selinux_netlbl_inode_permission(). */
+ selinux_netlbl_sock_setsid(sk, sksec->sid);
+-
+- rcu_read_unlock();
+ }
+
+ /**
+@@ -254,16 +205,13 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
+ */
+ int selinux_netlbl_socket_post_create(struct socket *sock)
+ {
+- int rc = 0;
+ struct sock *sk = sock->sk;
+ struct sk_security_struct *sksec = sk->sk_security;
+
+- rcu_read_lock();
+- if (sksec->nlbl_state == NLBL_REQUIRE)
+- rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
+- rcu_read_unlock();
++ if (sksec->nlbl_state != NLBL_REQUIRE)
++ return 0;
+
+- return rc;
++ return selinux_netlbl_sock_setsid(sk, sksec->sid);
+ }
+
+ /**
+@@ -288,21 +236,21 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask)
+ if (!S_ISSOCK(inode->i_mode) ||
+ ((mask & (MAY_WRITE | MAY_APPEND)) == 0))
+ return 0;
++
+ sock = SOCKET_I(inode);
+ sk = sock->sk;
+ sksec = sk->sk_security;
+-
+- rcu_read_lock();
+- if (sksec->nlbl_state != NLBL_REQUIRE) {
+- rcu_read_unlock();
++ if (sksec->nlbl_state != NLBL_REQUIRE)
+ return 0;
+- }
++
+ local_bh_disable();
+ bh_lock_sock_nested(sk);
+- rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
++ if (likely(sksec->nlbl_state == NLBL_REQUIRE))
++ rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
++ else
++ rc = 0;
+ bh_unlock_sock(sk);
+ local_bh_enable();
+- rcu_read_unlock();
+
+ return rc;
+ }
+@@ -385,7 +333,6 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
+ struct sk_security_struct *sksec = sk->sk_security;
+ struct netlbl_lsm_secattr secattr;
+
+- rcu_read_lock();
+ if (level == IPPROTO_IP && optname == IP_OPTIONS &&
+ sksec->nlbl_state == NLBL_LABELED) {
+ netlbl_secattr_init(&secattr);
+@@ -396,7 +343,6 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
+ rc = -EACCES;
+ netlbl_secattr_destroy(&secattr);
+ }
+- rcu_read_unlock();
+
+ return rc;
+ }
+diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c
+index b59871d..1ae5564 100644
+--- a/security/selinux/netlink.c
++++ b/security/selinux/netlink.c
+@@ -24,16 +24,16 @@ static struct sock *selnl;
+ static int selnl_msglen(int msgtype)
+ {
+ int ret = 0;
+-
++
+ switch (msgtype) {
+ case SELNL_MSG_SETENFORCE:
+ ret = sizeof(struct selnl_msg_setenforce);
+ break;
+-
++
+ case SELNL_MSG_POLICYLOAD:
+ ret = sizeof(struct selnl_msg_policyload);
+ break;
+-
++
+ default:
+ BUG();
+ }
+@@ -45,15 +45,15 @@ static void selnl_add_payload(struct nlmsghdr *nlh, int len, int msgtype, void *
+ switch (msgtype) {
+ case SELNL_MSG_SETENFORCE: {
+ struct selnl_msg_setenforce *msg = NLMSG_DATA(nlh);
+-
++
+ memset(msg, 0, len);
+ msg->val = *((int *)data);
+ break;
+ }
+-
++
+ case SELNL_MSG_POLICYLOAD: {
+ struct selnl_msg_policyload *msg = NLMSG_DATA(nlh);
+-
++
+ memset(msg, 0, len);
+ msg->seqno = *((u32 *)data);
+ break;
+@@ -70,9 +70,9 @@ static void selnl_notify(int msgtype, void *data)
+ sk_buff_data_t tmp;
+ struct sk_buff *skb;
+ struct nlmsghdr *nlh;
+-
++
+ len = selnl_msglen(msgtype);
+-
++
+ skb = alloc_skb(NLMSG_SPACE(len), GFP_USER);
+ if (!skb)
+ goto oom;
+@@ -85,11 +85,11 @@ static void selnl_notify(int msgtype, void *data)
+ netlink_broadcast(selnl, skb, 0, SELNLGRP_AVC, GFP_USER);
+ out:
+ return;
+-
++
+ nlmsg_failure:
+ kfree_skb(skb);
+ oom:
+- printk(KERN_ERR "SELinux: OOM in %s\n", __FUNCTION__);
++ printk(KERN_ERR "SELinux: OOM in %s\n", __func__);
+ goto out;
+ }
+
+@@ -109,7 +109,7 @@ static int __init selnl_init(void)
+ SELNLGRP_MAX, NULL, NULL, THIS_MODULE);
+ if (selnl == NULL)
+ panic("SELinux: Cannot create netlink socket.");
+- netlink_set_nonroot(NETLINK_SELINUX, NL_NONROOT_RECV);
++ netlink_set_nonroot(NETLINK_SELINUX, NL_NONROOT_RECV);
+ return 0;
+ }
+
+diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c
+index f3c526f..2edc4c5 100644
+--- a/security/selinux/netnode.c
++++ b/security/selinux/netnode.c
+@@ -344,7 +344,7 @@ static __init int sel_netnode_init(void)
+ INIT_LIST_HEAD(&sel_netnode_hash[iter]);
+
+ ret = avc_add_callback(sel_netnode_avc_callback, AVC_CALLBACK_RESET,
+- SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
++ SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
+ if (ret != 0)
+ panic("avc_add_callback() failed, error %d\n", ret);
+
+diff --git a/security/selinux/netport.c b/security/selinux/netport.c
+new file mode 100644
+index 0000000..68ede3c
+--- /dev/null
++++ b/security/selinux/netport.c
+@@ -0,0 +1,286 @@
++/*
++ * Network port table
++ *
++ * SELinux must keep a mapping of network ports to labels/SIDs. This
++ * mapping is maintained as part of the normal policy but a fast cache is
++ * needed to reduce the lookup overhead.
++ *
++ * Author: Paul Moore <paul.moore at hp.com>
++ *
++ * This code is heavily based on the "netif" concept originally developed by
++ * James Morris <jmorris at redhat.com>
++ * (see security/selinux/netif.c for more information)
++ *
++ */
++
++/*
++ * (c) Copyright Hewlett-Packard Development Company, L.P., 2008
++ *
++ * This program is free software: you can redistribute it and/or modify
++ * it under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ */
++
++#include <linux/types.h>
++#include <linux/rcupdate.h>
++#include <linux/list.h>
++#include <linux/spinlock.h>
++#include <linux/in.h>
++#include <linux/in6.h>
++#include <linux/ip.h>
++#include <linux/ipv6.h>
++#include <net/ip.h>
++#include <net/ipv6.h>
++#include <asm/bug.h>
++
++#include "netport.h"
++#include "objsec.h"
++
++#define SEL_NETPORT_HASH_SIZE 256
++#define SEL_NETPORT_HASH_BKT_LIMIT 16
++
++struct sel_netport_bkt {
++ int size;
++ struct list_head list;
++};
++
++struct sel_netport {
++ struct netport_security_struct psec;
++
++ struct list_head list;
++ struct rcu_head rcu;
++};
++
++/* NOTE: we are using a combined hash table for both IPv4 and IPv6, the reason
++ * for this is that I suspect most users will not make heavy use of both
++ * address families at the same time so one table will usually end up wasted,
++ * if this becomes a problem we can always add a hash table for each address
++ * family later */
++
++static LIST_HEAD(sel_netport_list);
++static DEFINE_SPINLOCK(sel_netport_lock);
++static struct sel_netport_bkt sel_netport_hash[SEL_NETPORT_HASH_SIZE];
++
++/**
++ * sel_netport_free - Frees a port entry
++ * @p: the entry's RCU field
++ *
++ * Description:
++ * This function is designed to be used as a callback to the call_rcu()
++ * function so that memory allocated to a hash table port entry can be
++ * released safely.
++ *
++ */
++static void sel_netport_free(struct rcu_head *p)
++{
++ struct sel_netport *port = container_of(p, struct sel_netport, rcu);
++ kfree(port);
++}
++
++/**
++ * sel_netport_hashfn - Hashing function for the port table
++ * @pnum: port number
++ *
++ * Description:
++ * This is the hashing function for the port table, it returns the bucket
++ * number for the given port.
++ *
++ */
++static unsigned int sel_netport_hashfn(u16 pnum)
++{
++ return (pnum & (SEL_NETPORT_HASH_SIZE - 1));
++}
++
++/**
++ * sel_netport_find - Search for a port record
++ * @protocol: protocol
++ * @port: pnum
++ *
++ * Description:
++ * Search the network port table and return the matching record. If an entry
++ * can not be found in the table return NULL.
++ *
++ */
++static struct sel_netport *sel_netport_find(u8 protocol, u16 pnum)
++{
++ unsigned int idx;
++ struct sel_netport *port;
++
++ idx = sel_netport_hashfn(pnum);
++ list_for_each_entry_rcu(port, &sel_netport_hash[idx].list, list)
++ if (port->psec.port == pnum &&
++ port->psec.protocol == protocol)
++ return port;
++
++ return NULL;
++}
++
++/**
++ * sel_netport_insert - Insert a new port into the table
++ * @port: the new port record
++ *
++ * Description:
++ * Add a new port record to the network address hash table. Returns zero on
++ * success, negative values on failure.
++ *
++ */
++static int sel_netport_insert(struct sel_netport *port)
++{
++ unsigned int idx;
++
++ /* we need to impose a limit on the growth of the hash table so check
++ * this bucket to make sure it is within the specified bounds */
++ idx = sel_netport_hashfn(port->psec.port);
++ list_add_rcu(&port->list, &sel_netport_hash[idx].list);
++ if (sel_netport_hash[idx].size == SEL_NETPORT_HASH_BKT_LIMIT) {
++ struct sel_netport *tail;
++ tail = list_entry(port->list.prev, struct sel_netport, list);
++ list_del_rcu(port->list.prev);
++ call_rcu(&tail->rcu, sel_netport_free);
++ } else
++ sel_netport_hash[idx].size++;
++
++ return 0;
++}
++
++/**
++ * sel_netport_sid_slow - Lookup the SID of a network address using the policy
++ * @protocol: protocol
++ * @pnum: port
++ * @sid: port SID
++ *
++ * Description:
++ * This function determines the SID of a network port by quering the security
++ * policy. The result is added to the network port table to speedup future
++ * queries. Returns zero on success, negative values on failure.
++ *
++ */
++static int sel_netport_sid_slow(u8 protocol, u16 pnum, u32 *sid)
++{
++ int ret;
++ struct sel_netport *port;
++ struct sel_netport *new = NULL;
++
++ spin_lock_bh(&sel_netport_lock);
++ port = sel_netport_find(protocol, pnum);
++ if (port != NULL) {
++ *sid = port->psec.sid;
++ ret = 0;
++ goto out;
++ }
++ new = kzalloc(sizeof(*new), GFP_ATOMIC);
++ if (new == NULL) {
++ ret = -ENOMEM;
++ goto out;
++ }
++ ret = security_port_sid(protocol, pnum, &new->psec.sid);
++ if (ret != 0)
++ goto out;
++ new->psec.port = pnum;
++ new->psec.protocol = protocol;
++ ret = sel_netport_insert(new);
++ if (ret != 0)
++ goto out;
++ *sid = new->psec.sid;
++
++out:
++ spin_unlock_bh(&sel_netport_lock);
++ if (unlikely(ret)) {
++ printk(KERN_WARNING
++ "SELinux: failure in sel_netport_sid_slow(),"
++ " unable to determine network port label\n");
++ kfree(new);
++ }
++ return ret;
++}
++
++/**
++ * sel_netport_sid - Lookup the SID of a network port
++ * @protocol: protocol
++ * @pnum: port
++ * @sid: port SID
++ *
++ * Description:
++ * This function determines the SID of a network port using the fastest method
++ * possible. First the port table is queried, but if an entry can't be found
++ * then the policy is queried and the result is added to the table to speedup
++ * future queries. Returns zero on success, negative values on failure.
++ *
++ */
++int sel_netport_sid(u8 protocol, u16 pnum, u32 *sid)
++{
++ struct sel_netport *port;
++
++ rcu_read_lock();
++ port = sel_netport_find(protocol, pnum);
++ if (port != NULL) {
++ *sid = port->psec.sid;
++ rcu_read_unlock();
++ return 0;
++ }
++ rcu_read_unlock();
++
++ return sel_netport_sid_slow(protocol, pnum, sid);
++}
++
++/**
++ * sel_netport_flush - Flush the entire network port table
++ *
++ * Description:
++ * Remove all entries from the network address table.
++ *
++ */
++static void sel_netport_flush(void)
++{
++ unsigned int idx;
++ struct sel_netport *port;
++
++ spin_lock_bh(&sel_netport_lock);
++ for (idx = 0; idx < SEL_NETPORT_HASH_SIZE; idx++) {
++ list_for_each_entry(port, &sel_netport_hash[idx].list, list) {
++ list_del_rcu(&port->list);
++ call_rcu(&port->rcu, sel_netport_free);
++ }
++ sel_netport_hash[idx].size = 0;
++ }
++ spin_unlock_bh(&sel_netport_lock);
++}
++
++static int sel_netport_avc_callback(u32 event, u32 ssid, u32 tsid,
++ u16 class, u32 perms, u32 *retained)
++{
++ if (event == AVC_CALLBACK_RESET) {
++ sel_netport_flush();
++ synchronize_net();
++ }
++ return 0;
++}
++
++static __init int sel_netport_init(void)
++{
++ int iter;
++ int ret;
++
++ if (!selinux_enabled)
++ return 0;
++
++ for (iter = 0; iter < SEL_NETPORT_HASH_SIZE; iter++) {
++ INIT_LIST_HEAD(&sel_netport_hash[iter].list);
++ sel_netport_hash[iter].size = 0;
++ }
++
++ ret = avc_add_callback(sel_netport_avc_callback, AVC_CALLBACK_RESET,
++ SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
++ if (ret != 0)
++ panic("avc_add_callback() failed, error %d\n", ret);
++
++ return ret;
++}
++
++__initcall(sel_netport_init);
+diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
+index eddc7b4..ff59c0c 100644
+--- a/security/selinux/nlmsgtab.c
++++ b/security/selinux/nlmsgtab.c
+@@ -23,8 +23,7 @@
+ #include "flask.h"
+ #include "av_permissions.h"
+
+-struct nlmsg_perm
+-{
++struct nlmsg_perm {
+ u16 nlmsg_type;
+ u32 perm;
+ };
+@@ -159,7 +158,7 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm)
+ if ((nlmsg_type >= AUDIT_FIRST_USER_MSG &&
+ nlmsg_type <= AUDIT_LAST_USER_MSG) ||
+ (nlmsg_type >= AUDIT_FIRST_USER_MSG2 &&
+- nlmsg_type <= AUDIT_LAST_USER_MSG2)) {
++ nlmsg_type <= AUDIT_LAST_USER_MSG2)) {
+ *perm = NETLINK_AUDIT_SOCKET__NLMSG_RELAY;
+ } else {
+ err = nlmsg_perm(nlmsg_type, perm, nlmsg_audit_perms,
+diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
+index 0341567..ac1ccc1 100644
+--- a/security/selinux/selinuxfs.c
++++ b/security/selinux/selinuxfs.c
+@@ -1,16 +1,16 @@
+ /* Updated: Karl MacMillan <kmacmillan at tresys.com>
+ *
+- * Added conditional policy language extensions
++ * Added conditional policy language extensions
+ *
+ * Updated: Hewlett-Packard <paul.moore at hp.com>
+ *
+- * Added support for the policy capability bitmap
++ * Added support for the policy capability bitmap
+ *
+ * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
+ * Copyright (C) 2003 - 2004 Tresys Technology, LLC
+ * Copyright (C) 2004 Red Hat, Inc., James Morris <jmorris at redhat.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
++ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ */
+
+@@ -28,7 +28,6 @@
+ #include <linux/percpu.h>
+ #include <linux/audit.h>
+ #include <asm/uaccess.h>
+-#include <asm/semaphore.h>
+
+ /* selinuxfs pseudo filesystem for exporting the security policy API.
+ Based on the proc code and the fs/nfsd/nfsctl.c code. */
+@@ -42,7 +41,8 @@
+
+ /* Policy capability filenames */
+ static char *policycap_names[] = {
+- "network_peer_controls"
++ "network_peer_controls",
++ "open_perms"
+ };
+
+ unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
+@@ -57,14 +57,14 @@ int selinux_compat_net = SELINUX_COMPAT_NET_VALUE;
+
+ static int __init checkreqprot_setup(char *str)
+ {
+- selinux_checkreqprot = simple_strtoul(str,NULL,0) ? 1 : 0;
++ selinux_checkreqprot = simple_strtoul(str, NULL, 0) ? 1 : 0;
+ return 1;
+ }
+ __setup("checkreqprot=", checkreqprot_setup);
+
+ static int __init selinux_compat_net_setup(char *str)
+ {
+- selinux_compat_net = simple_strtoul(str,NULL,0) ? 1 : 0;
++ selinux_compat_net = simple_strtoul(str, NULL, 0) ? 1 : 0;
+ return 1;
+ }
+ __setup("selinux_compat_net=", selinux_compat_net_setup);
+@@ -73,17 +73,17 @@ __setup("selinux_compat_net=", selinux_compat_net_setup);
+ static DEFINE_MUTEX(sel_mutex);
+
+ /* global data for booleans */
+-static struct dentry *bool_dir = NULL;
+-static int bool_num = 0;
++static struct dentry *bool_dir;
++static int bool_num;
+ static char **bool_pending_names;
+-static int *bool_pending_values = NULL;
++static int *bool_pending_values;
+
+ /* global data for classes */
+-static struct dentry *class_dir = NULL;
++static struct dentry *class_dir;
+ static unsigned long last_class_ino;
+
+ /* global data for policy capabilities */
+-static struct dentry *policycap_dir = NULL;
++static struct dentry *policycap_dir;
+
+ extern void selnl_notify_setenforce(int val);
+
+@@ -142,7 +142,7 @@ static ssize_t sel_read_enforce(struct file *filp, char __user *buf,
+ }
+
+ #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
+-static ssize_t sel_write_enforce(struct file * file, const char __user * buf,
++static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+
+ {
+@@ -156,7 +156,7 @@ static ssize_t sel_write_enforce(struct file * file, const char __user * buf,
+ /* No partial writes. */
+ return -EINVAL;
+ }
+- page = (char*)get_zeroed_page(GFP_KERNEL);
++ page = (char *)get_zeroed_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+ length = -EFAULT;
+@@ -213,7 +213,7 @@ static const struct file_operations sel_handle_unknown_ops = {
+ };
+
+ #ifdef CONFIG_SECURITY_SELINUX_DISABLE
+-static ssize_t sel_write_disable(struct file * file, const char __user * buf,
++static ssize_t sel_write_disable(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+
+ {
+@@ -228,7 +228,7 @@ static ssize_t sel_write_disable(struct file * file, const char __user * buf,
+ /* No partial writes. */
+ return -EINVAL;
+ }
+- page = (char*)get_zeroed_page(GFP_KERNEL);
++ page = (char *)get_zeroed_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+ length = -EFAULT;
+@@ -263,7 +263,7 @@ static const struct file_operations sel_disable_ops = {
+ };
+
+ static ssize_t sel_read_policyvers(struct file *filp, char __user *buf,
+- size_t count, loff_t *ppos)
++ size_t count, loff_t *ppos)
+ {
+ char tmpbuf[TMPBUFLEN];
+ ssize_t length;
+@@ -299,7 +299,7 @@ static const struct file_operations sel_mls_ops = {
+ .read = sel_read_mls,
+ };
+
+-static ssize_t sel_write_load(struct file * file, const char __user * buf,
++static ssize_t sel_write_load(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+
+ {
+@@ -371,7 +371,7 @@ static const struct file_operations sel_load_ops = {
+ .write = sel_write_load,
+ };
+
+-static ssize_t sel_write_context(struct file * file, char *buf, size_t size)
++static ssize_t sel_write_context(struct file *file, char *buf, size_t size)
+ {
+ char *canon;
+ u32 sid, len;
+@@ -390,8 +390,8 @@ static ssize_t sel_write_context(struct file * file, char *buf, size_t size)
+ return length;
+
+ if (len > SIMPLE_TRANSACTION_LIMIT) {
+- printk(KERN_ERR "%s: context size (%u) exceeds payload "
+- "max\n", __FUNCTION__, len);
++ printk(KERN_ERR "SELinux: %s: context size (%u) exceeds "
++ "payload max\n", __func__, len);
+ length = -ERANGE;
+ goto out;
+ }
+@@ -413,7 +413,7 @@ static ssize_t sel_read_checkreqprot(struct file *filp, char __user *buf,
+ return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
+ }
+
+-static ssize_t sel_write_checkreqprot(struct file * file, const char __user * buf,
++static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+ {
+ char *page;
+@@ -430,7 +430,7 @@ static ssize_t sel_write_checkreqprot(struct file * file, const char __user * bu
+ /* No partial writes. */
+ return -EINVAL;
+ }
+- page = (char*)get_zeroed_page(GFP_KERNEL);
++ page = (char *)get_zeroed_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+ length = -EFAULT;
+@@ -462,7 +462,7 @@ static ssize_t sel_read_compat_net(struct file *filp, char __user *buf,
+ return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
+ }
+
+-static ssize_t sel_write_compat_net(struct file * file, const char __user * buf,
++static ssize_t sel_write_compat_net(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+ {
+ char *page;
+@@ -479,7 +479,7 @@ static ssize_t sel_write_compat_net(struct file * file, const char __user * buf,
+ /* No partial writes. */
+ return -EINVAL;
+ }
+- page = (char*)get_zeroed_page(GFP_KERNEL);
++ page = (char *)get_zeroed_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+ length = -EFAULT;
+@@ -504,11 +504,11 @@ static const struct file_operations sel_compat_net_ops = {
+ /*
+ * Remaining nodes use transaction based IO methods like nfsd/nfsctl.c
+ */
+-static ssize_t sel_write_access(struct file * file, char *buf, size_t size);
+-static ssize_t sel_write_create(struct file * file, char *buf, size_t size);
+-static ssize_t sel_write_relabel(struct file * file, char *buf, size_t size);
+-static ssize_t sel_write_user(struct file * file, char *buf, size_t size);
+-static ssize_t sel_write_member(struct file * file, char *buf, size_t size);
++static ssize_t sel_write_access(struct file *file, char *buf, size_t size);
++static ssize_t sel_write_create(struct file *file, char *buf, size_t size);
++static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size);
++static ssize_t sel_write_user(struct file *file, char *buf, size_t size);
++static ssize_t sel_write_member(struct file *file, char *buf, size_t size);
+
+ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
+ [SEL_ACCESS] = sel_write_access,
+@@ -521,7 +521,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
+
+ static ssize_t selinux_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
+ {
+- ino_t ino = file->f_path.dentry->d_inode->i_ino;
++ ino_t ino = file->f_path.dentry->d_inode->i_ino;
+ char *data;
+ ssize_t rv;
+
+@@ -532,8 +532,8 @@ static ssize_t selinux_transaction_write(struct file *file, const char __user *b
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+
+- rv = write_op[ino](file, data, size);
+- if (rv>0) {
++ rv = write_op[ino](file, data, size);
++ if (rv > 0) {
+ simple_transaction_set(file, rv);
+ rv = size;
+ }
+@@ -552,7 +552,7 @@ static const struct file_operations transaction_ops = {
+ * and the length returned. Otherwise return 0 or and -error.
+ */
+
+-static ssize_t sel_write_access(struct file * file, char *buf, size_t size)
++static ssize_t sel_write_access(struct file *file, char *buf, size_t size)
+ {
+ char *scon, *tcon;
+ u32 ssid, tsid;
+@@ -601,7 +601,7 @@ out:
+ return length;
+ }
+
+-static ssize_t sel_write_create(struct file * file, char *buf, size_t size)
++static ssize_t sel_write_create(struct file *file, char *buf, size_t size)
+ {
+ char *scon, *tcon;
+ u32 ssid, tsid, newsid;
+@@ -643,8 +643,8 @@ static ssize_t sel_write_create(struct file * file, char *buf, size_t size)
+ goto out2;
+
+ if (len > SIMPLE_TRANSACTION_LIMIT) {
+- printk(KERN_ERR "%s: context size (%u) exceeds payload "
+- "max\n", __FUNCTION__, len);
++ printk(KERN_ERR "SELinux: %s: context size (%u) exceeds "
++ "payload max\n", __func__, len);
+ length = -ERANGE;
+ goto out3;
+ }
+@@ -660,7 +660,7 @@ out:
+ return length;
+ }
+
+-static ssize_t sel_write_relabel(struct file * file, char *buf, size_t size)
++static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size)
+ {
+ char *scon, *tcon;
+ u32 ssid, tsid, newsid;
+@@ -717,7 +717,7 @@ out:
+ return length;
+ }
+
+-static ssize_t sel_write_user(struct file * file, char *buf, size_t size)
++static ssize_t sel_write_user(struct file *file, char *buf, size_t size)
+ {
+ char *con, *user, *ptr;
+ u32 sid, *sids;
+@@ -778,7 +778,7 @@ out:
+ return length;
+ }
+
+-static ssize_t sel_write_member(struct file * file, char *buf, size_t size)
++static ssize_t sel_write_member(struct file *file, char *buf, size_t size)
+ {
+ char *scon, *tcon;
+ u32 ssid, tsid, newsid;
+@@ -820,8 +820,8 @@ static ssize_t sel_write_member(struct file * file, char *buf, size_t size)
+ goto out2;
+
+ if (len > SIMPLE_TRANSACTION_LIMIT) {
+- printk(KERN_ERR "%s: context size (%u) exceeds payload "
+- "max\n", __FUNCTION__, len);
++ printk(KERN_ERR "SELinux: %s: context size (%u) exceeds "
++ "payload max\n", __func__, len);
+ length = -ERANGE;
+ goto out3;
+ }
+@@ -872,7 +872,8 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
+ ret = -EINVAL;
+ goto out;
+ }
+- if (!(page = (char*)get_zeroed_page(GFP_KERNEL))) {
++ page = (char *)get_zeroed_page(GFP_KERNEL);
++ if (!page) {
+ ret = -ENOMEM;
+ goto out;
+ }
+@@ -923,7 +924,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
+ length = -EINVAL;
+ goto out;
+ }
+- page = (char*)get_zeroed_page(GFP_KERNEL);
++ page = (char *)get_zeroed_page(GFP_KERNEL);
+ if (!page) {
+ length = -ENOMEM;
+ goto out;
+@@ -951,8 +952,8 @@ out:
+ }
+
+ static const struct file_operations sel_bool_ops = {
+- .read = sel_read_bool,
+- .write = sel_write_bool,
++ .read = sel_read_bool,
++ .write = sel_write_bool,
+ };
+
+ static ssize_t sel_commit_bools_write(struct file *filep,
+@@ -977,7 +978,7 @@ static ssize_t sel_commit_bools_write(struct file *filep,
+ /* No partial writes. */
+ goto out;
+ }
+- page = (char*)get_zeroed_page(GFP_KERNEL);
++ page = (char *)get_zeroed_page(GFP_KERNEL);
+ if (!page) {
+ length = -ENOMEM;
+ goto out;
+@@ -991,9 +992,8 @@ static ssize_t sel_commit_bools_write(struct file *filep,
+ if (sscanf(page, "%d", &new_value) != 1)
+ goto out;
+
+- if (new_value && bool_pending_values) {
++ if (new_value && bool_pending_values)
+ security_set_bools(bool_num, bool_pending_values);
+- }
+
+ length = count;
+
+@@ -1005,7 +1005,7 @@ out:
+ }
+
+ static const struct file_operations sel_commit_bools_ops = {
+- .write = sel_commit_bools_write,
++ .write = sel_commit_bools_write,
+ };
+
+ static void sel_remove_entries(struct dentry *de)
+@@ -1055,7 +1055,8 @@ static int sel_make_bools(void)
+
+ sel_remove_entries(dir);
+
+- if (!(page = (char*)get_zeroed_page(GFP_KERNEL)))
++ page = (char *)get_zeroed_page(GFP_KERNEL);
++ if (!page)
+ return -ENOMEM;
+
+ ret = security_get_bools(&num, &names, &values);
+@@ -1082,8 +1083,9 @@ static int sel_make_bools(void)
+ ret = -ENAMETOOLONG;
+ goto err;
+ }
+- isec = (struct inode_security_struct*)inode->i_security;
+- if ((ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid)))
++ isec = (struct inode_security_struct *)inode->i_security;
++ ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid);
++ if (ret)
+ goto err;
+ isec->sid = sid;
+ isec->initialized = 1;
+@@ -1111,7 +1113,7 @@ err:
+
+ #define NULL_FILE_NAME "null"
+
+-struct dentry *selinux_null = NULL;
++struct dentry *selinux_null;
+
+ static ssize_t sel_read_avc_cache_threshold(struct file *filp, char __user *buf,
+ size_t count, loff_t *ppos)
+@@ -1123,8 +1125,8 @@ static ssize_t sel_read_avc_cache_threshold(struct file *filp, char __user *buf,
+ return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
+ }
+
+-static ssize_t sel_write_avc_cache_threshold(struct file * file,
+- const char __user * buf,
++static ssize_t sel_write_avc_cache_threshold(struct file *file,
++ const char __user *buf,
+ size_t count, loff_t *ppos)
+
+ {
+@@ -1143,7 +1145,7 @@ static ssize_t sel_write_avc_cache_threshold(struct file * file,
+ goto out;
+ }
+
+- page = (char*)get_zeroed_page(GFP_KERNEL);
++ page = (char *)get_zeroed_page(GFP_KERNEL);
+ if (!page) {
+ ret = -ENOMEM;
+ goto out;
+@@ -1301,7 +1303,7 @@ out:
+ return ret;
+ }
+
+-static ssize_t sel_read_initcon(struct file * file, char __user *buf,
++static ssize_t sel_read_initcon(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+ {
+ struct inode *inode;
+@@ -1375,7 +1377,7 @@ static inline u32 sel_ino_to_perm(unsigned long ino)
+ return (ino & SEL_INO_MASK) % (SEL_VEC_MAX + 1);
+ }
+
+-static ssize_t sel_read_class(struct file * file, char __user *buf,
++static ssize_t sel_read_class(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+ {
+ ssize_t rc, len;
+@@ -1399,7 +1401,7 @@ static const struct file_operations sel_class_ops = {
+ .read = sel_read_class,
+ };
+
+-static ssize_t sel_read_perm(struct file * file, char __user *buf,
++static ssize_t sel_read_perm(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+ {
+ ssize_t rc, len;
+@@ -1412,7 +1414,7 @@ static ssize_t sel_read_perm(struct file * file, char __user *buf,
+ goto out;
+ }
+
+- len = snprintf(page, PAGE_SIZE,"%d", sel_ino_to_perm(ino));
++ len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_perm(ino));
+ rc = simple_read_from_buffer(buf, count, ppos, page, len);
+ free_page((unsigned long)page);
+ out:
+@@ -1640,7 +1642,7 @@ out:
+ return ret;
+ }
+
+-static int sel_fill_super(struct super_block * sb, void * data, int silent)
++static int sel_fill_super(struct super_block *sb, void *data, int silent)
+ {
+ int ret;
+ struct dentry *dentry;
+@@ -1696,7 +1698,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
+ goto err;
+ }
+ inode->i_ino = ++sel_last_ino;
+- isec = (struct inode_security_struct*)inode->i_security;
++ isec = (struct inode_security_struct *)inode->i_security;
+ isec->sid = SECINITSID_DEVNULL;
+ isec->sclass = SECCLASS_CHR_FILE;
+ isec->initialized = 1;
+@@ -1760,7 +1762,8 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
+ out:
+ return ret;
+ err:
+- printk(KERN_ERR "%s: failed while creating inodes\n", __FUNCTION__);
++ printk(KERN_ERR "SELinux: %s: failed while creating inodes\n",
++ __func__);
+ goto out;
+ }
+
+diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
+index cd10e27..9e66263 100644
+--- a/security/selinux/ss/avtab.c
++++ b/security/selinux/ss/avtab.c
+@@ -6,15 +6,15 @@
+
+ /* Updated: Frank Mayer <mayerf at tresys.com> and Karl MacMillan <kmacmillan at tresys.com>
+ *
+- * Added conditional policy language extensions
++ * Added conditional policy language extensions
+ *
+ * Copyright (C) 2003 Tresys Technology, LLC
+ * 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
++ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ *
+ * Updated: Yuichi Nakamura <ynakam at hitachisoft.jp>
+- * Tuned number of hash slots for avtab to reduce memory usage
++ * Tuned number of hash slots for avtab to reduce memory usage
+ */
+
+ #include <linux/kernel.h>
+@@ -33,10 +33,10 @@ static inline int avtab_hash(struct avtab_key *keyp, u16 mask)
+
+ static struct avtab_node*
+ avtab_insert_node(struct avtab *h, int hvalue,
+- struct avtab_node * prev, struct avtab_node * cur,
++ struct avtab_node *prev, struct avtab_node *cur,
+ struct avtab_key *key, struct avtab_datum *datum)
+ {
+- struct avtab_node * newnode;
++ struct avtab_node *newnode;
+ newnode = kmem_cache_zalloc(avtab_node_cachep, GFP_KERNEL);
+ if (newnode == NULL)
+ return NULL;
+@@ -84,7 +84,7 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat
+ }
+
+ newnode = avtab_insert_node(h, hvalue, prev, cur, key, datum);
+- if(!newnode)
++ if (!newnode)
+ return -ENOMEM;
+
+ return 0;
+@@ -95,7 +95,7 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat
+ * It also returns a pointer to the node inserted.
+ */
+ struct avtab_node *
+-avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_datum * datum)
++avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum)
+ {
+ int hvalue;
+ struct avtab_node *prev, *cur, *newnode;
+@@ -280,8 +280,8 @@ int avtab_alloc(struct avtab *h, u32 nrules)
+ h->nel = 0;
+ h->nslot = nslot;
+ h->mask = mask;
+- printk(KERN_DEBUG "SELinux:%d avtab hash slots allocated. "
+- "Num of rules:%d\n", h->nslot, nrules);
++ printk(KERN_DEBUG "SELinux: %d avtab hash slots, %d rules.\n",
++ h->nslot, nrules);
+ return 0;
+ }
+
+@@ -310,8 +310,8 @@ void avtab_hash_eval(struct avtab *h, char *tag)
+ }
+ }
+
+- printk(KERN_DEBUG "%s: %d entries and %d/%d buckets used, longest "
+- "chain length %d sum of chain length^2 %Lu\n",
++ printk(KERN_DEBUG "SELinux: %s: %d entries and %d/%d buckets used, "
++ "longest chain length %d sum of chain length^2 %Lu\n",
+ tag, h->nel, slots_used, h->nslot, max_chain_len,
+ chain2_len_sum);
+ }
+@@ -326,7 +326,7 @@ static uint16_t spec_order[] = {
+ };
+
+ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
+- int (*insertf)(struct avtab *a, struct avtab_key *k,
++ int (*insertf)(struct avtab *a, struct avtab_key *k,
+ struct avtab_datum *d, void *p),
+ void *p)
+ {
+@@ -345,18 +345,18 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
+ if (vers < POLICYDB_VERSION_AVTAB) {
+ rc = next_entry(buf32, fp, sizeof(u32));
+ if (rc < 0) {
+- printk(KERN_ERR "security: avtab: truncated entry\n");
++ printk(KERN_ERR "SELinux: avtab: truncated entry\n");
+ return -1;
+ }
+ items2 = le32_to_cpu(buf32[0]);
+ if (items2 > ARRAY_SIZE(buf32)) {
+- printk(KERN_ERR "security: avtab: entry overflow\n");
++ printk(KERN_ERR "SELinux: avtab: entry overflow\n");
+ return -1;
+
+ }
+ rc = next_entry(buf32, fp, sizeof(u32)*items2);
+ if (rc < 0) {
+- printk(KERN_ERR "security: avtab: truncated entry\n");
++ printk(KERN_ERR "SELinux: avtab: truncated entry\n");
+ return -1;
+ }
+ items = 0;
+@@ -364,19 +364,19 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
+ val = le32_to_cpu(buf32[items++]);
+ key.source_type = (u16)val;
+ if (key.source_type != val) {
+- printk("security: avtab: truncated source type\n");
++ printk(KERN_ERR "SELinux: avtab: truncated source type\n");
+ return -1;
+ }
+ val = le32_to_cpu(buf32[items++]);
+ key.target_type = (u16)val;
+ if (key.target_type != val) {
+- printk("security: avtab: truncated target type\n");
++ printk(KERN_ERR "SELinux: avtab: truncated target type\n");
+ return -1;
+ }
+ val = le32_to_cpu(buf32[items++]);
+ key.target_class = (u16)val;
+ if (key.target_class != val) {
+- printk("security: avtab: truncated target class\n");
++ printk(KERN_ERR "SELinux: avtab: truncated target class\n");
+ return -1;
+ }
+
+@@ -384,12 +384,12 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
+ enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0;
+
+ if (!(val & (AVTAB_AV | AVTAB_TYPE))) {
+- printk("security: avtab: null entry\n");
++ printk(KERN_ERR "SELinux: avtab: null entry\n");
+ return -1;
+ }
+ if ((val & AVTAB_AV) &&
+ (val & AVTAB_TYPE)) {
+- printk("security: avtab: entry has both access vectors and types\n");
++ printk(KERN_ERR "SELinux: avtab: entry has both access vectors and types\n");
+ return -1;
+ }
+
+@@ -398,12 +398,13 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
+ key.specified = spec_order[i] | enabled;
+ datum.data = le32_to_cpu(buf32[items++]);
+ rc = insertf(a, &key, &datum, p);
+- if (rc) return rc;
++ if (rc)
++ return rc;
+ }
+ }
+
+ if (items != items2) {
+- printk("security: avtab: entry only had %d items, expected %d\n", items2, items);
++ printk(KERN_ERR "SELinux: avtab: entry only had %d items, expected %d\n", items2, items);
+ return -1;
+ }
+ return 0;
+@@ -411,7 +412,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
+
+ rc = next_entry(buf16, fp, sizeof(u16)*4);
+ if (rc < 0) {
+- printk("security: avtab: truncated entry\n");
++ printk(KERN_ERR "SELinux: avtab: truncated entry\n");
+ return -1;
+ }
+
+@@ -424,7 +425,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
+ if (!policydb_type_isvalid(pol, key.source_type) ||
+ !policydb_type_isvalid(pol, key.target_type) ||
+ !policydb_class_isvalid(pol, key.target_class)) {
+- printk(KERN_WARNING "security: avtab: invalid type or class\n");
++ printk(KERN_ERR "SELinux: avtab: invalid type or class\n");
+ return -1;
+ }
+
+@@ -434,20 +435,19 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
+ set++;
+ }
+ if (!set || set > 1) {
+- printk(KERN_WARNING
+- "security: avtab: more than one specifier\n");
++ printk(KERN_ERR "SELinux: avtab: more than one specifier\n");
+ return -1;
+ }
+
+ rc = next_entry(buf32, fp, sizeof(u32));
+ if (rc < 0) {
+- printk("security: avtab: truncated entry\n");
++ printk(KERN_ERR "SELinux: avtab: truncated entry\n");
+ return -1;
+ }
+ datum.data = le32_to_cpu(*buf32);
+ if ((key.specified & AVTAB_TYPE) &&
+ !policydb_type_isvalid(pol, datum.data)) {
+- printk(KERN_WARNING "security: avtab: invalid type\n");
++ printk(KERN_ERR "SELinux: avtab: invalid type\n");
+ return -1;
+ }
+ return insertf(a, &key, &datum, p);
+@@ -468,12 +468,12 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol)
+
+ rc = next_entry(buf, fp, sizeof(u32));
+ if (rc < 0) {
+- printk(KERN_ERR "security: avtab: truncated table\n");
++ printk(KERN_ERR "SELinux: avtab: truncated table\n");
+ goto bad;
+ }
+ nel = le32_to_cpu(buf[0]);
+ if (!nel) {
+- printk(KERN_ERR "security: avtab: table is empty\n");
++ printk(KERN_ERR "SELinux: avtab: table is empty\n");
+ rc = -EINVAL;
+ goto bad;
+ }
+@@ -486,9 +486,9 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol)
+ rc = avtab_read_item(a, fp, pol, avtab_insertf, NULL);
+ if (rc) {
+ if (rc == -ENOMEM)
+- printk(KERN_ERR "security: avtab: out of memory\n");
++ printk(KERN_ERR "SELinux: avtab: out of memory\n");
+ else if (rc == -EEXIST)
+- printk(KERN_ERR "security: avtab: duplicate entry\n");
++ printk(KERN_ERR "SELinux: avtab: duplicate entry\n");
+ else
+ rc = -EINVAL;
+ goto bad;
+@@ -513,5 +513,5 @@ void avtab_cache_init(void)
+
+ void avtab_cache_destroy(void)
+ {
+- kmem_cache_destroy (avtab_node_cachep);
++ kmem_cache_destroy(avtab_node_cachep);
+ }
+diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
+index 50ad85d..fb4efe4 100644
+--- a/security/selinux/ss/conditional.c
++++ b/security/selinux/ss/conditional.c
+@@ -1,9 +1,9 @@
+ /* Authors: Karl MacMillan <kmacmillan at tresys.com>
+- * Frank Mayer <mayerf at tresys.com>
++ * Frank Mayer <mayerf at tresys.com>
+ *
+ * Copyright (C) 2003 - 2004 Tresys Technology, LLC
+ * 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
++ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ */
+
+@@ -11,7 +11,6 @@
+ #include <linux/errno.h>
+ #include <linux/string.h>
+ #include <linux/spinlock.h>
+-#include <asm/semaphore.h>
+ #include <linux/slab.h>
+
+ #include "security.h"
+@@ -90,29 +89,27 @@ static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr)
+ int evaluate_cond_node(struct policydb *p, struct cond_node *node)
+ {
+ int new_state;
+- struct cond_av_list* cur;
++ struct cond_av_list *cur;
+
+ new_state = cond_evaluate_expr(p, node->expr);
+ if (new_state != node->cur_state) {
+ node->cur_state = new_state;
+ if (new_state == -1)
+- printk(KERN_ERR "security: expression result was undefined - disabling all rules.\n");
++ printk(KERN_ERR "SELinux: expression result was undefined - disabling all rules.\n");
+ /* turn the rules on or off */
+ for (cur = node->true_list; cur != NULL; cur = cur->next) {
+- if (new_state <= 0) {
++ if (new_state <= 0)
+ cur->node->key.specified &= ~AVTAB_ENABLED;
+- } else {
++ else
+ cur->node->key.specified |= AVTAB_ENABLED;
+- }
+ }
+
+ for (cur = node->false_list; cur != NULL; cur = cur->next) {
+ /* -1 or 1 */
+- if (new_state) {
++ if (new_state)
+ cur->node->key.specified &= ~AVTAB_ENABLED;
+- } else {
++ else
+ cur->node->key.specified |= AVTAB_ENABLED;
+- }
+ }
+ }
+ return 0;
+@@ -174,8 +171,8 @@ void cond_policydb_destroy(struct policydb *p)
+ int cond_init_bool_indexes(struct policydb *p)
+ {
+ kfree(p->bool_val_to_struct);
+- p->bool_val_to_struct = (struct cond_bool_datum**)
+- kmalloc(p->p_bools.nprim * sizeof(struct cond_bool_datum*), GFP_KERNEL);
++ p->bool_val_to_struct = (struct cond_bool_datum **)
++ kmalloc(p->p_bools.nprim * sizeof(struct cond_bool_datum *), GFP_KERNEL);
+ if (!p->bool_val_to_struct)
+ return -1;
+ return 0;
+@@ -200,7 +197,7 @@ int cond_index_bool(void *key, void *datum, void *datap)
+ return -EINVAL;
+
+ p->p_bool_val_to_name[booldatum->value - 1] = key;
+- p->bool_val_to_struct[booldatum->value -1] = booldatum;
++ p->bool_val_to_struct[booldatum->value - 1] = booldatum;
+
+ return 0;
+ }
+@@ -252,8 +249,7 @@ err:
+ return -1;
+ }
+
+-struct cond_insertf_data
+-{
++struct cond_insertf_data {
+ struct policydb *p;
+ struct cond_av_list *other;
+ struct cond_av_list *head;
+@@ -276,7 +272,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
+ */
+ if (k->specified & AVTAB_TYPE) {
+ if (avtab_search(&p->te_avtab, k)) {
+- printk("security: type rule already exists outside of a conditional.");
++ printk(KERN_ERR "SELinux: type rule already exists outside of a conditional.\n");
+ goto err;
+ }
+ /*
+@@ -291,7 +287,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
+ node_ptr = avtab_search_node(&p->te_cond_avtab, k);
+ if (node_ptr) {
+ if (avtab_search_node_next(node_ptr, k->specified)) {
+- printk("security: too many conflicting type rules.");
++ printk(KERN_ERR "SELinux: too many conflicting type rules.\n");
+ goto err;
+ }
+ found = 0;
+@@ -302,13 +298,13 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
+ }
+ }
+ if (!found) {
+- printk("security: conflicting type rules.\n");
++ printk(KERN_ERR "SELinux: conflicting type rules.\n");
+ goto err;
+ }
+ }
+ } else {
+ if (avtab_search(&p->te_cond_avtab, k)) {
+- printk("security: conflicting type rules when adding type rule for true.\n");
++ printk(KERN_ERR "SELinux: conflicting type rules when adding type rule for true.\n");
+ goto err;
+ }
+ }
+@@ -316,7 +312,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
+
+ node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
+ if (!node_ptr) {
+- printk("security: could not insert rule.");
++ printk(KERN_ERR "SELinux: could not insert rule.\n");
+ goto err;
+ }
+
+@@ -353,9 +349,8 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list *
+ return -1;
+
+ len = le32_to_cpu(buf[0]);
+- if (len == 0) {
++ if (len == 0)
+ return 0;
+- }
+
+ data.p = p;
+ data.other = other;
+@@ -376,12 +371,12 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list *
+ static int expr_isvalid(struct policydb *p, struct cond_expr *expr)
+ {
+ if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) {
+- printk("security: conditional expressions uses unknown operator.\n");
++ printk(KERN_ERR "SELinux: conditional expressions uses unknown operator.\n");
+ return 0;
+ }
+
+ if (expr->bool > p->p_bools.nprim) {
+- printk("security: conditional expressions uses unknown bool.\n");
++ printk(KERN_ERR "SELinux: conditional expressions uses unknown bool.\n");
+ return 0;
+ }
+ return 1;
+@@ -408,15 +403,14 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
+ /* expr */
+ len = le32_to_cpu(buf[0]);
+
+- for (i = 0; i < len; i++ ) {
++ for (i = 0; i < len; i++) {
+ rc = next_entry(buf, fp, sizeof(u32) * 2);
+ if (rc < 0)
+ goto err;
+
+ expr = kzalloc(sizeof(struct cond_expr), GFP_KERNEL);
+- if (!expr) {
++ if (!expr)
+ goto err;
+- }
+
+ expr->expr_type = le32_to_cpu(buf[0]);
+ expr->bool = le32_to_cpu(buf[1]);
+@@ -426,11 +420,10 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
+ goto err;
+ }
+
+- if (i == 0) {
++ if (i == 0)
+ node->expr = expr;
+- } else {
++ else
+ last->next = expr;
+- }
+ last = expr;
+ }
+
+@@ -469,11 +462,10 @@ int cond_read_list(struct policydb *p, void *fp)
+ if (cond_read_node(p, node, fp) != 0)
+ goto err;
+
+- if (i == 0) {
++ if (i == 0)
+ p->cond_list = node;
+- } else {
++ else
+ last->next = node;
+- }
+ last = node;
+ }
+ return 0;
+@@ -490,24 +482,24 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decisi
+ {
+ struct avtab_node *node;
+
+- if(!ctab || !key || !avd)
++ if (!ctab || !key || !avd)
+ return;
+
+- for(node = avtab_search_node(ctab, key); node != NULL;
++ for (node = avtab_search_node(ctab, key); node != NULL;
+ node = avtab_search_node_next(node, key->specified)) {
+- if ( (u16) (AVTAB_ALLOWED|AVTAB_ENABLED) ==
+- (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED)))
++ if ((u16)(AVTAB_ALLOWED|AVTAB_ENABLED) ==
++ (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED)))
+ avd->allowed |= node->datum.data;
+- if ( (u16) (AVTAB_AUDITDENY|AVTAB_ENABLED) ==
+- (node->key.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED)))
++ if ((u16)(AVTAB_AUDITDENY|AVTAB_ENABLED) ==
++ (node->key.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED)))
+ /* Since a '0' in an auditdeny mask represents a
+ * permission we do NOT want to audit (dontaudit), we use
+ * the '&' operand to ensure that all '0's in the mask
+ * are retained (much unlike the allow and auditallow cases).
+ */
+ avd->auditdeny &= node->datum.data;
+- if ( (u16) (AVTAB_AUDITALLOW|AVTAB_ENABLED) ==
+- (node->key.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED)))
++ if ((u16)(AVTAB_AUDITALLOW|AVTAB_ENABLED) ==
++ (node->key.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED)))
+ avd->auditallow |= node->datum.data;
+ }
+ return;
+diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
+index 920b5e3..ddc2754 100644
+--- a/security/selinux/ss/ebitmap.c
++++ b/security/selinux/ss/ebitmap.c
+@@ -364,7 +364,7 @@ int ebitmap_read(struct ebitmap *e, void *fp)
+ count = le32_to_cpu(buf[2]);
+
+ if (mapunit != sizeof(u64) * 8) {
+- printk(KERN_ERR "security: ebitmap: map size %u does not "
++ printk(KERN_ERR "SELinux: ebitmap: map size %u does not "
+ "match my size %Zd (high bit was %d)\n",
+ mapunit, sizeof(u64) * 8, e->highbit);
+ goto bad;
+@@ -382,19 +382,19 @@ int ebitmap_read(struct ebitmap *e, void *fp)
+ for (i = 0; i < count; i++) {
+ rc = next_entry(&startbit, fp, sizeof(u32));
+ if (rc < 0) {
+- printk(KERN_ERR "security: ebitmap: truncated map\n");
++ printk(KERN_ERR "SELinux: ebitmap: truncated map\n");
+ goto bad;
+ }
+ startbit = le32_to_cpu(startbit);
+
+ if (startbit & (mapunit - 1)) {
+- printk(KERN_ERR "security: ebitmap start bit (%d) is "
++ printk(KERN_ERR "SELinux: ebitmap start bit (%d) is "
+ "not a multiple of the map unit size (%u)\n",
+ startbit, mapunit);
+ goto bad;
+ }
+ if (startbit > e->highbit - mapunit) {
+- printk(KERN_ERR "security: ebitmap start bit (%d) is "
++ printk(KERN_ERR "SELinux: ebitmap start bit (%d) is "
+ "beyond the end of the bitmap (%u)\n",
+ startbit, (e->highbit - mapunit));
+ goto bad;
+@@ -405,20 +405,19 @@ int ebitmap_read(struct ebitmap *e, void *fp)
+ tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
+ if (!tmp) {
+ printk(KERN_ERR
+- "security: ebitmap: out of memory\n");
++ "SELinux: ebitmap: out of memory\n");
+ rc = -ENOMEM;
+ goto bad;
+ }
+ /* round down */
+ tmp->startbit = startbit - (startbit % EBITMAP_SIZE);
+- if (n) {
++ if (n)
+ n->next = tmp;
+- } else {
++ else
+ e->node = tmp;
+- }
+ n = tmp;
+ } else if (startbit <= n->startbit) {
+- printk(KERN_ERR "security: ebitmap: start bit %d"
++ printk(KERN_ERR "SELinux: ebitmap: start bit %d"
+ " comes after start bit %d\n",
+ startbit, n->startbit);
+ goto bad;
+@@ -426,7 +425,7 @@ int ebitmap_read(struct ebitmap *e, void *fp)
+
+ rc = next_entry(&map, fp, sizeof(u64));
+ if (rc < 0) {
+- printk(KERN_ERR "security: ebitmap: truncated map\n");
++ printk(KERN_ERR "SELinux: ebitmap: truncated map\n");
+ goto bad;
+ }
+ map = le64_to_cpu(map);
+diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c
+index 77b530c..2e7788e 100644
+--- a/security/selinux/ss/hashtab.c
++++ b/security/selinux/ss/hashtab.c
+@@ -9,8 +9,8 @@
+ #include "hashtab.h"
+
+ struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, const void *key),
+- int (*keycmp)(struct hashtab *h, const void *key1, const void *key2),
+- u32 size)
++ int (*keycmp)(struct hashtab *h, const void *key1, const void *key2),
++ u32 size)
+ {
+ struct hashtab *p;
+ u32 i;
+diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
+index feaf0a5..8b1706b 100644
+--- a/security/selinux/ss/mls.c
++++ b/security/selinux/ss/mls.c
+@@ -32,7 +32,7 @@
+ * Return the length in bytes for the MLS fields of the
+ * security context string representation of `context'.
+ */
+-int mls_compute_context_len(struct context * context)
++int mls_compute_context_len(struct context *context)
+ {
+ int i, l, len, head, prev;
+ char *nm;
+@@ -86,7 +86,7 @@ int mls_compute_context_len(struct context * context)
+ * Update `*scontext' to point to the end of the MLS fields.
+ */
+ void mls_sid_to_context(struct context *context,
+- char **scontext)
++ char **scontext)
+ {
+ char *scontextp, *nm;
+ int i, l, head, prev;
+@@ -146,7 +146,7 @@ void mls_sid_to_context(struct context *context,
+
+ if (l == 0) {
+ if (mls_level_eq(&context->range.level[0],
+- &context->range.level[1]))
++ &context->range.level[1]))
+ break;
+ else
+ *scontextp++ = '-';
+@@ -305,20 +305,21 @@ int mls_context_to_sid(char oldc,
+ *p++ = 0;
+
+ /* Separate into range if exists */
+- if ((rngptr = strchr(scontextp, '.')) != NULL) {
++ rngptr = strchr(scontextp, '.');
++ if (rngptr != NULL) {
+ /* Remove '.' */
+ *rngptr++ = 0;
+ }
+
+ catdatum = hashtab_search(policydb.p_cats.table,
+- scontextp);
++ scontextp);
+ if (!catdatum) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ rc = ebitmap_set_bit(&context->range.level[l].cat,
+- catdatum->value - 1, 1);
++ catdatum->value - 1, 1);
+ if (rc)
+ goto out;
+
+@@ -395,7 +396,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
+ rc = -ENOMEM;
+ } else {
+ rc = mls_context_to_sid(':', &tmpstr, context,
+- NULL, SECSID_NULL);
++ NULL, SECSID_NULL);
+ kfree(freestr);
+ }
+
+@@ -406,7 +407,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
+ * Copies the MLS range `range' into `context'.
+ */
+ static inline int mls_range_set(struct context *context,
+- struct mls_range *range)
++ struct mls_range *range)
+ {
+ int l, rc = 0;
+
+@@ -423,7 +424,7 @@ static inline int mls_range_set(struct context *context,
+ }
+
+ int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
+- struct context *usercon)
++ struct context *usercon)
+ {
+ if (selinux_mls_enabled) {
+ struct mls_level *fromcon_sen = &(fromcon->range.level[0]);
+@@ -449,11 +450,11 @@ int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
+ that of the user's default clearance (but
+ only if the "fromcon" clearance dominates
+ the user's computed sensitivity level) */
+- if (mls_level_dom(user_clr, fromcon_clr)) {
++ if (mls_level_dom(user_clr, fromcon_clr))
+ *usercon_clr = *fromcon_clr;
+- } else if (mls_level_dom(fromcon_clr, user_clr)) {
++ else if (mls_level_dom(fromcon_clr, user_clr))
+ *usercon_clr = *user_clr;
+- } else
++ else
+ return -EINVAL;
+ }
+
+@@ -525,7 +526,7 @@ int mls_compute_sid(struct context *scontext,
+ rtr->target_class == tclass) {
+ /* Set the range from the rule */
+ return mls_range_set(newcontext,
+- &rtr->target_range);
++ &rtr->target_range);
+ }
+ }
+ /* Fallthrough */
+diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
+index bd7d6a0..84f8cc7 100644
+--- a/security/selinux/ss/policydb.c
++++ b/security/selinux/ss/policydb.c
+@@ -11,7 +11,7 @@
+ *
+ * Updated: Frank Mayer <mayerf at tresys.com> and Karl MacMillan <kmacmillan at tresys.com>
+ *
+- * Added conditional policy language extensions
++ * Added conditional policy language extensions
+ *
+ * Updated: Hewlett-Packard <paul.moore at hp.com>
+ *
+@@ -21,7 +21,7 @@
+ * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
+ * Copyright (C) 2003 - 2004 Tresys Technology, LLC
+ * 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
++ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ */
+
+@@ -51,7 +51,7 @@ static char *symtab_name[SYM_NUM] = {
+ };
+ #endif
+
+-int selinux_mls_enabled = 0;
++int selinux_mls_enabled;
+
+ static unsigned int symtab_sizes[SYM_NUM] = {
+ 2,
+@@ -73,44 +73,49 @@ struct policydb_compat_info {
+ /* These need to be updated if SYM_NUM or OCON_NUM changes */
+ static struct policydb_compat_info policydb_compat[] = {
+ {
+- .version = POLICYDB_VERSION_BASE,
+- .sym_num = SYM_NUM - 3,
+- .ocon_num = OCON_NUM - 1,
++ .version = POLICYDB_VERSION_BASE,
++ .sym_num = SYM_NUM - 3,
++ .ocon_num = OCON_NUM - 1,
+ },
+ {
+- .version = POLICYDB_VERSION_BOOL,
+- .sym_num = SYM_NUM - 2,
+- .ocon_num = OCON_NUM - 1,
++ .version = POLICYDB_VERSION_BOOL,
++ .sym_num = SYM_NUM - 2,
++ .ocon_num = OCON_NUM - 1,
+ },
+ {
+- .version = POLICYDB_VERSION_IPV6,
+- .sym_num = SYM_NUM - 2,
+- .ocon_num = OCON_NUM,
++ .version = POLICYDB_VERSION_IPV6,
++ .sym_num = SYM_NUM - 2,
++ .ocon_num = OCON_NUM,
+ },
+ {
+- .version = POLICYDB_VERSION_NLCLASS,
+- .sym_num = SYM_NUM - 2,
+- .ocon_num = OCON_NUM,
++ .version = POLICYDB_VERSION_NLCLASS,
++ .sym_num = SYM_NUM - 2,
++ .ocon_num = OCON_NUM,
+ },
+ {
+- .version = POLICYDB_VERSION_MLS,
+- .sym_num = SYM_NUM,
+- .ocon_num = OCON_NUM,
++ .version = POLICYDB_VERSION_MLS,
++ .sym_num = SYM_NUM,
++ .ocon_num = OCON_NUM,
+ },
+ {
+- .version = POLICYDB_VERSION_AVTAB,
+- .sym_num = SYM_NUM,
+- .ocon_num = OCON_NUM,
++ .version = POLICYDB_VERSION_AVTAB,
++ .sym_num = SYM_NUM,
++ .ocon_num = OCON_NUM,
+ },
+ {
+- .version = POLICYDB_VERSION_RANGETRANS,
+- .sym_num = SYM_NUM,
+- .ocon_num = OCON_NUM,
++ .version = POLICYDB_VERSION_RANGETRANS,
++ .sym_num = SYM_NUM,
++ .ocon_num = OCON_NUM,
+ },
+ {
+ .version = POLICYDB_VERSION_POLCAP,
+ .sym_num = SYM_NUM,
+ .ocon_num = OCON_NUM,
++ },
++ {
++ .version = POLICYDB_VERSION_PERMISSIVE,
++ .sym_num = SYM_NUM,
++ .ocon_num = OCON_NUM,
+ }
+ };
+
+@@ -147,7 +152,7 @@ static int roles_init(struct policydb *p)
+ rc = -EINVAL;
+ goto out_free_role;
+ }
+- key = kmalloc(strlen(OBJECT_R)+1,GFP_KERNEL);
++ key = kmalloc(strlen(OBJECT_R)+1, GFP_KERNEL);
+ if (!key) {
+ rc = -ENOMEM;
+ goto out_free_role;
+@@ -194,6 +199,7 @@ static int policydb_init(struct policydb *p)
+ goto out_free_symtab;
+
+ ebitmap_init(&p->policycaps);
++ ebitmap_init(&p->permissive_map);
+
+ out:
+ return rc;
+@@ -384,7 +390,7 @@ static void symtab_hash_eval(struct symtab *s)
+ struct hashtab_info info;
+
+ hashtab_stat(h, &info);
+- printk(KERN_DEBUG "%s: %d entries and %d/%d buckets used, "
++ printk(KERN_DEBUG "SELinux: %s: %d entries and %d/%d buckets used, "
+ "longest chain length %d\n", symtab_name[i], h->nel,
+ info.slots_used, h->size, info.max_chain_len);
+ }
+@@ -401,14 +407,14 @@ static int policydb_index_others(struct policydb *p)
+ {
+ int i, rc = 0;
+
+- printk(KERN_DEBUG "security: %d users, %d roles, %d types, %d bools",
++ printk(KERN_DEBUG "SELinux: %d users, %d roles, %d types, %d bools",
+ p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim);
+ if (selinux_mls_enabled)
+ printk(", %d sens, %d cats", p->p_levels.nprim,
+ p->p_cats.nprim);
+ printk("\n");
+
+- printk(KERN_DEBUG "security: %d classes, %d rules\n",
++ printk(KERN_DEBUG "SELinux: %d classes, %d rules\n",
+ p->p_classes.nprim, p->te_avtab.nel);
+
+ #ifdef DEBUG_HASHES
+@@ -418,7 +424,7 @@ static int policydb_index_others(struct policydb *p)
+
+ p->role_val_to_struct =
+ kmalloc(p->p_roles.nprim * sizeof(*(p->role_val_to_struct)),
+- GFP_KERNEL);
++ GFP_KERNEL);
+ if (!p->role_val_to_struct) {
+ rc = -ENOMEM;
+ goto out;
+@@ -426,7 +432,7 @@ static int policydb_index_others(struct policydb *p)
+
+ p->user_val_to_struct =
+ kmalloc(p->p_users.nprim * sizeof(*(p->user_val_to_struct)),
+- GFP_KERNEL);
++ GFP_KERNEL);
+ if (!p->user_val_to_struct) {
+ rc = -ENOMEM;
+ goto out;
+@@ -628,7 +634,7 @@ void policydb_destroy(struct policydb *p)
+ while (c) {
+ ctmp = c;
+ c = c->next;
+- ocontext_destroy(ctmp,i);
++ ocontext_destroy(ctmp, i);
+ }
+ p->ocontexts[i] = NULL;
+ }
+@@ -641,7 +647,7 @@ void policydb_destroy(struct policydb *p)
+ while (c) {
+ ctmp = c;
+ c = c->next;
+- ocontext_destroy(ctmp,OCON_FSUSE);
++ ocontext_destroy(ctmp, OCON_FSUSE);
+ }
+ gtmp = g;
+ g = g->next;
+@@ -658,14 +664,14 @@ void policydb_destroy(struct policydb *p)
+ }
+ kfree(ltr);
+
+- for (ra = p->role_allow; ra; ra = ra -> next) {
++ for (ra = p->role_allow; ra; ra = ra->next) {
+ cond_resched();
+ kfree(lra);
+ lra = ra;
+ }
+ kfree(lra);
+
+- for (rt = p->range_tr; rt; rt = rt -> next) {
++ for (rt = p->range_tr; rt; rt = rt->next) {
+ cond_resched();
+ if (lrt) {
+ ebitmap_destroy(&lrt->target_range.level[0].cat);
+@@ -687,6 +693,7 @@ void policydb_destroy(struct policydb *p)
+ kfree(p->type_attr_map);
+ kfree(p->undefined_perms);
+ ebitmap_destroy(&p->policycaps);
++ ebitmap_destroy(&p->permissive_map);
+
+ return;
+ }
+@@ -702,20 +709,20 @@ int policydb_load_isids(struct policydb *p, struct sidtab *s)
+
+ rc = sidtab_init(s);
+ if (rc) {
+- printk(KERN_ERR "security: out of memory on SID table init\n");
++ printk(KERN_ERR "SELinux: out of memory on SID table init\n");
+ goto out;
+ }
+
+ head = p->ocontexts[OCON_ISID];
+ for (c = head; c; c = c->next) {
+ if (!c->context[0].user) {
+- printk(KERN_ERR "security: SID %s was never "
++ printk(KERN_ERR "SELinux: SID %s was never "
+ "defined.\n", c->u.name);
+ rc = -EINVAL;
+ goto out;
+ }
+ if (sidtab_insert(s, c->sid[0], &c->context[0])) {
+- printk(KERN_ERR "security: unable to load initial "
++ printk(KERN_ERR "SELinux: unable to load initial "
+ "SID %s.\n", c->u.name);
+ rc = -EINVAL;
+ goto out;
+@@ -809,13 +816,13 @@ static int mls_read_range_helper(struct mls_range *r, void *fp)
+
+ items = le32_to_cpu(buf[0]);
+ if (items > ARRAY_SIZE(buf)) {
+- printk(KERN_ERR "security: mls: range overflow\n");
++ printk(KERN_ERR "SELinux: mls: range overflow\n");
+ rc = -EINVAL;
+ goto out;
+ }
+ rc = next_entry(buf, fp, sizeof(u32) * items);
+ if (rc < 0) {
+- printk(KERN_ERR "security: mls: truncated range\n");
++ printk(KERN_ERR "SELinux: mls: truncated range\n");
+ goto out;
+ }
+ r->level[0].sens = le32_to_cpu(buf[0]);
+@@ -826,21 +833,21 @@ static int mls_read_range_helper(struct mls_range *r, void *fp)
+
+ rc = ebitmap_read(&r->level[0].cat, fp);
+ if (rc) {
+- printk(KERN_ERR "security: mls: error reading low "
++ printk(KERN_ERR "SELinux: mls: error reading low "
+ "categories\n");
+ goto out;
+ }
+ if (items > 1) {
+ rc = ebitmap_read(&r->level[1].cat, fp);
+ if (rc) {
+- printk(KERN_ERR "security: mls: error reading high "
++ printk(KERN_ERR "SELinux: mls: error reading high "
+ "categories\n");
+ goto bad_high;
+ }
+ } else {
+ rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat);
+ if (rc) {
+- printk(KERN_ERR "security: mls: out of memory\n");
++ printk(KERN_ERR "SELinux: mls: out of memory\n");
+ goto bad_high;
+ }
+ }
+@@ -866,7 +873,7 @@ static int context_read_and_validate(struct context *c,
+
+ rc = next_entry(buf, fp, sizeof buf);
+ if (rc < 0) {
+- printk(KERN_ERR "security: context truncated\n");
++ printk(KERN_ERR "SELinux: context truncated\n");
+ goto out;
+ }
+ c->user = le32_to_cpu(buf[0]);
+@@ -874,7 +881,7 @@ static int context_read_and_validate(struct context *c,
+ c->type = le32_to_cpu(buf[2]);
+ if (p->policyvers >= POLICYDB_VERSION_MLS) {
+ if (mls_read_range_helper(&c->range, fp)) {
+- printk(KERN_ERR "security: error reading MLS range of "
++ printk(KERN_ERR "SELinux: error reading MLS range of "
+ "context\n");
+ rc = -EINVAL;
+ goto out;
+@@ -882,7 +889,7 @@ static int context_read_and_validate(struct context *c,
+ }
+
+ if (!policydb_context_isvalid(p, c)) {
+- printk(KERN_ERR "security: invalid security context\n");
++ printk(KERN_ERR "SELinux: invalid security context\n");
+ context_destroy(c);
+ rc = -EINVAL;
+ }
+@@ -917,7 +924,7 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
+ len = le32_to_cpu(buf[0]);
+ perdatum->value = le32_to_cpu(buf[1]);
+
+- key = kmalloc(len + 1,GFP_KERNEL);
++ key = kmalloc(len + 1, GFP_KERNEL);
+ if (!key) {
+ rc = -ENOMEM;
+ goto bad;
+@@ -964,7 +971,7 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp)
+ comdatum->permissions.nprim = le32_to_cpu(buf[2]);
+ nel = le32_to_cpu(buf[3]);
+
+- key = kmalloc(len + 1,GFP_KERNEL);
++ key = kmalloc(len + 1, GFP_KERNEL);
+ if (!key) {
+ rc = -ENOMEM;
+ goto bad;
+@@ -991,7 +998,7 @@ bad:
+ }
+
+ static int read_cons_helper(struct constraint_node **nodep, int ncons,
+- int allowxtarget, void *fp)
++ int allowxtarget, void *fp)
+ {
+ struct constraint_node *c, *lc;
+ struct constraint_expr *e, *le;
+@@ -1005,11 +1012,10 @@ static int read_cons_helper(struct constraint_node **nodep, int ncons,
+ if (!c)
+ return -ENOMEM;
+
+- if (lc) {
++ if (lc)
+ lc->next = c;
+- } else {
++ else
+ *nodep = c;
+- }
+
+ rc = next_entry(buf, fp, (sizeof(u32) * 2));
+ if (rc < 0)
+@@ -1023,11 +1029,10 @@ static int read_cons_helper(struct constraint_node **nodep, int ncons,
+ if (!e)
+ return -ENOMEM;
+
+- if (le) {
++ if (le)
+ le->next = e;
+- } else {
++ else
+ c->expr = e;
+- }
+
+ rc = next_entry(buf, fp, (sizeof(u32) * 3));
+ if (rc < 0)
+@@ -1104,7 +1109,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
+
+ ncons = le32_to_cpu(buf[5]);
+
+- key = kmalloc(len + 1,GFP_KERNEL);
++ key = kmalloc(len + 1, GFP_KERNEL);
+ if (!key) {
+ rc = -ENOMEM;
+ goto bad;
+@@ -1115,7 +1120,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
+ key[len] = 0;
+
+ if (len2) {
+- cladatum->comkey = kmalloc(len2 + 1,GFP_KERNEL);
++ cladatum->comkey = kmalloc(len2 + 1, GFP_KERNEL);
+ if (!cladatum->comkey) {
+ rc = -ENOMEM;
+ goto bad;
+@@ -1128,7 +1133,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
+ cladatum->comdatum = hashtab_search(p->p_commons.table,
+ cladatum->comkey);
+ if (!cladatum->comdatum) {
+- printk(KERN_ERR "security: unknown common %s\n",
++ printk(KERN_ERR "SELinux: unknown common %s\n",
+ cladatum->comkey);
+ rc = -EINVAL;
+ goto bad;
+@@ -1188,7 +1193,7 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp)
+ len = le32_to_cpu(buf[0]);
+ role->value = le32_to_cpu(buf[1]);
+
+- key = kmalloc(len + 1,GFP_KERNEL);
++ key = kmalloc(len + 1, GFP_KERNEL);
+ if (!key) {
+ rc = -ENOMEM;
+ goto bad;
+@@ -1208,7 +1213,7 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp)
+
+ if (strcmp(key, OBJECT_R) == 0) {
+ if (role->value != OBJECT_R_VAL) {
+- printk(KERN_ERR "Role %s has wrong value %d\n",
++ printk(KERN_ERR "SELinux: Role %s has wrong value %d\n",
+ OBJECT_R, role->value);
+ rc = -EINVAL;
+ goto bad;
+@@ -1235,7 +1240,7 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp)
+ __le32 buf[3];
+ u32 len;
+
+- typdatum = kzalloc(sizeof(*typdatum),GFP_KERNEL);
++ typdatum = kzalloc(sizeof(*typdatum), GFP_KERNEL);
+ if (!typdatum) {
+ rc = -ENOMEM;
+ return rc;
+@@ -1249,7 +1254,7 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp)
+ typdatum->value = le32_to_cpu(buf[1]);
+ typdatum->primary = le32_to_cpu(buf[2]);
+
+- key = kmalloc(len + 1,GFP_KERNEL);
++ key = kmalloc(len + 1, GFP_KERNEL);
+ if (!key) {
+ rc = -ENOMEM;
+ goto bad;
+@@ -1283,13 +1288,13 @@ static int mls_read_level(struct mls_level *lp, void *fp)
+
+ rc = next_entry(buf, fp, sizeof buf);
+ if (rc < 0) {
+- printk(KERN_ERR "security: mls: truncated level\n");
++ printk(KERN_ERR "SELinux: mls: truncated level\n");
+ goto bad;
+ }
+ lp->sens = le32_to_cpu(buf[0]);
+
+ if (ebitmap_read(&lp->cat, fp)) {
+- printk(KERN_ERR "security: mls: error reading level "
++ printk(KERN_ERR "SELinux: mls: error reading level "
+ "categories\n");
+ goto bad;
+ }
+@@ -1321,7 +1326,7 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp)
+ len = le32_to_cpu(buf[0]);
+ usrdatum->value = le32_to_cpu(buf[1]);
+
+- key = kmalloc(len + 1,GFP_KERNEL);
++ key = kmalloc(len + 1, GFP_KERNEL);
+ if (!key) {
+ rc = -ENOMEM;
+ goto bad;
+@@ -1375,7 +1380,7 @@ static int sens_read(struct policydb *p, struct hashtab *h, void *fp)
+ len = le32_to_cpu(buf[0]);
+ levdatum->isalias = le32_to_cpu(buf[1]);
+
+- key = kmalloc(len + 1,GFP_ATOMIC);
++ key = kmalloc(len + 1, GFP_ATOMIC);
+ if (!key) {
+ rc = -ENOMEM;
+ goto bad;
+@@ -1427,7 +1432,7 @@ static int cat_read(struct policydb *p, struct hashtab *h, void *fp)
+ catdatum->value = le32_to_cpu(buf[1]);
+ catdatum->isalias = le32_to_cpu(buf[2]);
+
+- key = kmalloc(len + 1,GFP_ATOMIC);
++ key = kmalloc(len + 1, GFP_ATOMIC);
+ if (!key) {
+ rc = -ENOMEM;
+ goto bad;
+@@ -1486,12 +1491,12 @@ int policydb_read(struct policydb *p, void *fp)
+ goto out;
+
+ /* Read the magic number and string length. */
+- rc = next_entry(buf, fp, sizeof(u32)* 2);
++ rc = next_entry(buf, fp, sizeof(u32) * 2);
+ if (rc < 0)
+ goto bad;
+
+ if (le32_to_cpu(buf[0]) != POLICYDB_MAGIC) {
+- printk(KERN_ERR "security: policydb magic number 0x%x does "
++ printk(KERN_ERR "SELinux: policydb magic number 0x%x does "
+ "not match expected magic number 0x%x\n",
+ le32_to_cpu(buf[0]), POLICYDB_MAGIC);
+ goto bad;
+@@ -1499,27 +1504,27 @@ int policydb_read(struct policydb *p, void *fp)
+
+ len = le32_to_cpu(buf[1]);
+ if (len != strlen(POLICYDB_STRING)) {
+- printk(KERN_ERR "security: policydb string length %d does not "
++ printk(KERN_ERR "SELinux: policydb string length %d does not "
+ "match expected length %Zu\n",
+ len, strlen(POLICYDB_STRING));
+ goto bad;
+ }
+- policydb_str = kmalloc(len + 1,GFP_KERNEL);
++ policydb_str = kmalloc(len + 1, GFP_KERNEL);
+ if (!policydb_str) {
+- printk(KERN_ERR "security: unable to allocate memory for policydb "
++ printk(KERN_ERR "SELinux: unable to allocate memory for policydb "
+ "string of length %d\n", len);
+ rc = -ENOMEM;
+ goto bad;
+ }
+ rc = next_entry(policydb_str, fp, len);
+ if (rc < 0) {
+- printk(KERN_ERR "security: truncated policydb string identifier\n");
++ printk(KERN_ERR "SELinux: truncated policydb string identifier\n");
+ kfree(policydb_str);
+ goto bad;
+ }
+ policydb_str[len] = 0;
+ if (strcmp(policydb_str, POLICYDB_STRING)) {
+- printk(KERN_ERR "security: policydb string %s does not match "
++ printk(KERN_ERR "SELinux: policydb string %s does not match "
+ "my string %s\n", policydb_str, POLICYDB_STRING);
+ kfree(policydb_str);
+ goto bad;
+@@ -1536,30 +1541,31 @@ int policydb_read(struct policydb *p, void *fp)
+ p->policyvers = le32_to_cpu(buf[0]);
+ if (p->policyvers < POLICYDB_VERSION_MIN ||
+ p->policyvers > POLICYDB_VERSION_MAX) {
+- printk(KERN_ERR "security: policydb version %d does not match "
+- "my version range %d-%d\n",
+- le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
+- goto bad;
++ printk(KERN_ERR "SELinux: policydb version %d does not match "
++ "my version range %d-%d\n",
++ le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
++ goto bad;
+ }
+
+ if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) {
+ if (ss_initialized && !selinux_mls_enabled) {
+- printk(KERN_ERR "Cannot switch between non-MLS and MLS "
+- "policies\n");
++ printk(KERN_ERR "SELinux: Cannot switch between non-MLS"
++ " and MLS policies\n");
+ goto bad;
+ }
+ selinux_mls_enabled = 1;
+ config |= POLICYDB_CONFIG_MLS;
+
+ if (p->policyvers < POLICYDB_VERSION_MLS) {
+- printk(KERN_ERR "security policydb version %d (MLS) "
+- "not backwards compatible\n", p->policyvers);
++ printk(KERN_ERR "SELinux: security policydb version %d "
++ "(MLS) not backwards compatible\n",
++ p->policyvers);
+ goto bad;
+ }
+ } else {
+ if (ss_initialized && selinux_mls_enabled) {
+- printk(KERN_ERR "Cannot switch between MLS and non-MLS "
+- "policies\n");
++ printk(KERN_ERR "SELinux: Cannot switch between MLS and"
++ " non-MLS policies\n");
+ goto bad;
+ }
+ }
+@@ -1570,16 +1576,20 @@ int policydb_read(struct policydb *p, void *fp)
+ ebitmap_read(&p->policycaps, fp) != 0)
+ goto bad;
+
++ if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE &&
++ ebitmap_read(&p->permissive_map, fp) != 0)
++ goto bad;
++
+ info = policydb_lookup_compat(p->policyvers);
+ if (!info) {
+- printk(KERN_ERR "security: unable to find policy compat info "
++ printk(KERN_ERR "SELinux: unable to find policy compat info "
+ "for version %d\n", p->policyvers);
+ goto bad;
+ }
+
+ if (le32_to_cpu(buf[2]) != info->sym_num ||
+ le32_to_cpu(buf[3]) != info->ocon_num) {
+- printk(KERN_ERR "security: policydb table sizes (%d,%d) do "
++ printk(KERN_ERR "SELinux: policydb table sizes (%d,%d) do "
+ "not match mine (%d,%d)\n", le32_to_cpu(buf[2]),
+ le32_to_cpu(buf[3]),
+ info->sym_num, info->ocon_num);
+@@ -1622,11 +1632,10 @@ int policydb_read(struct policydb *p, void *fp)
+ rc = -ENOMEM;
+ goto bad;
+ }
+- if (ltr) {
++ if (ltr)
+ ltr->next = tr;
+- } else {
++ else
+ p->role_tr = tr;
+- }
+ rc = next_entry(buf, fp, sizeof(u32)*3);
+ if (rc < 0)
+ goto bad;
+@@ -1653,11 +1662,10 @@ int policydb_read(struct policydb *p, void *fp)
+ rc = -ENOMEM;
+ goto bad;
+ }
+- if (lra) {
++ if (lra)
+ lra->next = ra;
+- } else {
++ else
+ p->role_allow = ra;
+- }
+ rc = next_entry(buf, fp, sizeof(u32)*2);
+ if (rc < 0)
+ goto bad;
+@@ -1691,11 +1699,10 @@ int policydb_read(struct policydb *p, void *fp)
+ rc = -ENOMEM;
+ goto bad;
+ }
+- if (l) {
++ if (l)
+ l->next = c;
+- } else {
++ else
+ p->ocontexts[i] = c;
+- }
+ l = c;
+ rc = -EINVAL;
+ switch (i) {
+@@ -1714,7 +1721,7 @@ int policydb_read(struct policydb *p, void *fp)
+ if (rc < 0)
+ goto bad;
+ len = le32_to_cpu(buf[0]);
+- c->u.name = kmalloc(len + 1,GFP_KERNEL);
++ c->u.name = kmalloc(len + 1, GFP_KERNEL);
+ if (!c->u.name) {
+ rc = -ENOMEM;
+ goto bad;
+@@ -1742,7 +1749,7 @@ int policydb_read(struct policydb *p, void *fp)
+ goto bad;
+ break;
+ case OCON_NODE:
+- rc = next_entry(buf, fp, sizeof(u32)* 2);
++ rc = next_entry(buf, fp, sizeof(u32) * 2);
+ if (rc < 0)
+ goto bad;
+ c->u.node.addr = le32_to_cpu(buf[0]);
+@@ -1759,7 +1766,7 @@ int policydb_read(struct policydb *p, void *fp)
+ if (c->v.behavior > SECURITY_FS_USE_NONE)
+ goto bad;
+ len = le32_to_cpu(buf[1]);
+- c->u.name = kmalloc(len + 1,GFP_KERNEL);
++ c->u.name = kmalloc(len + 1, GFP_KERNEL);
+ if (!c->u.name) {
+ rc = -ENOMEM;
+ goto bad;
+@@ -1807,7 +1814,7 @@ int policydb_read(struct policydb *p, void *fp)
+ goto bad;
+ }
+
+- newgenfs->fstype = kmalloc(len + 1,GFP_KERNEL);
++ newgenfs->fstype = kmalloc(len + 1, GFP_KERNEL);
+ if (!newgenfs->fstype) {
+ rc = -ENOMEM;
+ kfree(newgenfs);
+@@ -1823,7 +1830,7 @@ int policydb_read(struct policydb *p, void *fp)
+ for (genfs_p = NULL, genfs = p->genfs; genfs;
+ genfs_p = genfs, genfs = genfs->next) {
+ if (strcmp(newgenfs->fstype, genfs->fstype) == 0) {
+- printk(KERN_ERR "security: dup genfs "
++ printk(KERN_ERR "SELinux: dup genfs "
+ "fstype %s\n", newgenfs->fstype);
+ kfree(newgenfs->fstype);
+ kfree(newgenfs);
+@@ -1853,7 +1860,7 @@ int policydb_read(struct policydb *p, void *fp)
+ goto bad;
+ }
+
+- newc->u.name = kmalloc(len + 1,GFP_KERNEL);
++ newc->u.name = kmalloc(len + 1, GFP_KERNEL);
+ if (!newc->u.name) {
+ rc = -ENOMEM;
+ goto bad_newc;
+@@ -1873,7 +1880,7 @@ int policydb_read(struct policydb *p, void *fp)
+ if (!strcmp(newc->u.name, c->u.name) &&
+ (!c->v.sclass || !newc->v.sclass ||
+ newc->v.sclass == c->v.sclass)) {
+- printk(KERN_ERR "security: dup genfs "
++ printk(KERN_ERR "SELinux: dup genfs "
+ "entry (%s,%s)\n",
+ newgenfs->fstype, c->u.name);
+ goto bad_newc;
+@@ -1931,7 +1938,7 @@ int policydb_read(struct policydb *p, void *fp)
+ if (rc)
+ goto bad;
+ if (!mls_range_isvalid(p, &rt->target_range)) {
+- printk(KERN_WARNING "security: rangetrans: invalid range\n");
++ printk(KERN_WARNING "SELinux: rangetrans: invalid range\n");
+ goto bad;
+ }
+ lrt = rt;
+@@ -1957,7 +1964,7 @@ int policydb_read(struct policydb *p, void *fp)
+ out:
+ return rc;
+ bad_newc:
+- ocontext_destroy(newc,OCON_FSUSE);
++ ocontext_destroy(newc, OCON_FSUSE);
+ bad:
+ if (!rc)
+ rc = -EINVAL;
+diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
+index c4ce996..ba593a3 100644
+--- a/security/selinux/ss/policydb.h
++++ b/security/selinux/ss/policydb.h
+@@ -243,6 +243,8 @@ struct policydb {
+
+ struct ebitmap policycaps;
+
++ struct ebitmap permissive_map;
++
+ unsigned int policyvers;
+
+ unsigned int reject_unknown : 1;
+diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
+index 3f2bad2..2daaddb 100644
+--- a/security/selinux/ss/services.c
++++ b/security/selinux/ss/services.c
+@@ -2,7 +2,7 @@
+ * Implementation of the security services.
+ *
+ * Authors : Stephen Smalley, <sds at epoch.ncsc.mil>
+- * James Morris <jmorris at redhat.com>
++ * James Morris <jmorris at redhat.com>
+ *
+ * Updated: Trusted Computer Solutions, Inc. <dgoeddel at trustedcs.com>
+ *
+@@ -11,7 +11,7 @@
+ *
+ * Updated: Frank Mayer <mayerf at tresys.com> and Karl MacMillan <kmacmillan at tresys.com>
+ *
+- * Added conditional policy language extensions
++ * Added conditional policy language extensions
+ *
+ * Updated: Hewlett-Packard <paul.moore at hp.com>
+ *
+@@ -27,7 +27,7 @@
+ * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC
+ * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris at redhat.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
++ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ */
+ #include <linux/kernel.h>
+@@ -40,6 +40,7 @@
+ #include <linux/sched.h>
+ #include <linux/audit.h>
+ #include <linux/mutex.h>
++#include <linux/selinux.h>
+ #include <net/netlabel.h>
+
+ #include "flask.h"
+@@ -56,11 +57,13 @@
+ #include "netlabel.h"
+ #include "xfrm.h"
+ #include "ebitmap.h"
++#include "audit.h"
+
+ extern void selnl_notify_policyload(u32 seqno);
+ unsigned int policydb_loaded_version;
+
+ int selinux_policycap_netpeer;
++int selinux_policycap_openperm;
+
+ /*
+ * This is declared in avc.c
+@@ -79,7 +82,7 @@ static DEFINE_MUTEX(load_mutex);
+
+ static struct sidtab sidtab;
+ struct policydb policydb;
+-int ss_initialized = 0;
++int ss_initialized;
+
+ /*
+ * The largest sequence number that has been used when
+@@ -87,7 +90,7 @@ int ss_initialized = 0;
+ * The sequence number only changes when a policy change
+ * occurs.
+ */
+-static u32 latest_granting = 0;
++static u32 latest_granting;
+
+ /* Forward declaration. */
+ static int context_struct_to_string(struct context *context, char **scontext,
+@@ -160,10 +163,10 @@ static int constraint_expr_eval(struct context *scontext,
+ val1 - 1);
+ continue;
+ case CEXPR_INCOMP:
+- s[++sp] = ( !ebitmap_get_bit(&r1->dominates,
+- val2 - 1) &&
+- !ebitmap_get_bit(&r2->dominates,
+- val1 - 1) );
++ s[++sp] = (!ebitmap_get_bit(&r1->dominates,
++ val2 - 1) &&
++ !ebitmap_get_bit(&r2->dominates,
++ val1 - 1));
+ continue;
+ default:
+ break;
+@@ -406,20 +409,46 @@ static int context_struct_compute_av(struct context *scontext,
+ }
+ if (!ra)
+ avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION |
+- PROCESS__DYNTRANSITION);
++ PROCESS__DYNTRANSITION);
+ }
+
+ return 0;
+
+ inval_class:
+- printk(KERN_ERR "%s: unrecognized class %d\n", __FUNCTION__, tclass);
++ printk(KERN_ERR "SELinux: %s: unrecognized class %d\n", __func__,
++ tclass);
+ return -EINVAL;
+ }
+
++/*
++ * Given a sid find if the type has the permissive flag set
++ */
++int security_permissive_sid(u32 sid)
++{
++ struct context *context;
++ u32 type;
++ int rc;
++
++ POLICY_RDLOCK;
++
++ context = sidtab_search(&sidtab, sid);
++ BUG_ON(!context);
++
++ type = context->type;
++ /*
++ * we are intentionally using type here, not type-1, the 0th bit may
++ * someday indicate that we are globally setting permissive in policy.
++ */
++ rc = ebitmap_get_bit(&policydb.permissive_map, type);
++
++ POLICY_RDUNLOCK;
++ return rc;
++}
++
+ static int security_validtrans_handle_fail(struct context *ocontext,
+- struct context *ncontext,
+- struct context *tcontext,
+- u16 tclass)
++ struct context *ncontext,
++ struct context *tcontext,
++ u16 tclass)
+ {
+ char *o = NULL, *n = NULL, *t = NULL;
+ u32 olen, nlen, tlen;
+@@ -431,9 +460,9 @@ static int security_validtrans_handle_fail(struct context *ocontext,
+ if (context_struct_to_string(tcontext, &t, &tlen) < 0)
+ goto out;
+ audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR,
+- "security_validate_transition: denied for"
+- " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
+- o, n, t, policydb.p_class_val_to_name[tclass-1]);
++ "security_validate_transition: denied for"
++ " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
++ o, n, t, policydb.p_class_val_to_name[tclass-1]);
+ out:
+ kfree(o);
+ kfree(n);
+@@ -445,7 +474,7 @@ out:
+ }
+
+ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
+- u16 tclass)
++ u16 tclass)
+ {
+ struct context *ocontext;
+ struct context *ncontext;
+@@ -471,8 +500,8 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
+ tclass = SECCLASS_NETLINK_SOCKET;
+
+ if (!tclass || tclass > policydb.p_classes.nprim) {
+- printk(KERN_ERR "security_validate_transition: "
+- "unrecognized class %d\n", tclass);
++ printk(KERN_ERR "SELinux: %s: unrecognized class %d\n",
++ __func__, tclass);
+ rc = -EINVAL;
+ goto out;
+ }
+@@ -480,24 +509,24 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
+
+ ocontext = sidtab_search(&sidtab, oldsid);
+ if (!ocontext) {
+- printk(KERN_ERR "security_validate_transition: "
+- " unrecognized SID %d\n", oldsid);
++ printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
++ __func__, oldsid);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ ncontext = sidtab_search(&sidtab, newsid);
+ if (!ncontext) {
+- printk(KERN_ERR "security_validate_transition: "
+- " unrecognized SID %d\n", newsid);
++ printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
++ __func__, newsid);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ tcontext = sidtab_search(&sidtab, tasksid);
+ if (!tcontext) {
+- printk(KERN_ERR "security_validate_transition: "
+- " unrecognized SID %d\n", tasksid);
++ printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
++ __func__, tasksid);
+ rc = -EINVAL;
+ goto out;
+ }
+@@ -505,9 +534,9 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
+ constraint = tclass_datum->validatetrans;
+ while (constraint) {
+ if (!constraint_expr_eval(ocontext, ncontext, tcontext,
+- constraint->expr)) {
++ constraint->expr)) {
+ rc = security_validtrans_handle_fail(ocontext, ncontext,
+- tcontext, tclass);
++ tcontext, tclass);
+ goto out;
+ }
+ constraint = constraint->next;
+@@ -553,15 +582,15 @@ int security_compute_av(u32 ssid,
+
+ scontext = sidtab_search(&sidtab, ssid);
+ if (!scontext) {
+- printk(KERN_ERR "security_compute_av: unrecognized SID %d\n",
+- ssid);
++ printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
++ __func__, ssid);
+ rc = -EINVAL;
+ goto out;
+ }
+ tcontext = sidtab_search(&sidtab, tsid);
+ if (!tcontext) {
+- printk(KERN_ERR "security_compute_av: unrecognized SID %d\n",
+- tsid);
++ printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
++ __func__, tsid);
+ rc = -EINVAL;
+ goto out;
+ }
+@@ -595,9 +624,8 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
+
+ /* Allocate space for the context; caller must free this space. */
+ scontextp = kmalloc(*scontext_len, GFP_ATOMIC);
+- if (!scontextp) {
++ if (!scontextp)
+ return -ENOMEM;
+- }
+ *scontext = scontextp;
+
+ /*
+@@ -608,8 +636,8 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
+ policydb.p_role_val_to_name[context->role - 1],
+ policydb.p_type_val_to_name[context->type - 1]);
+ scontextp += strlen(policydb.p_user_val_to_name[context->user - 1]) +
+- 1 + strlen(policydb.p_role_val_to_name[context->role - 1]) +
+- 1 + strlen(policydb.p_type_val_to_name[context->type - 1]);
++ 1 + strlen(policydb.p_role_val_to_name[context->role - 1]) +
++ 1 + strlen(policydb.p_type_val_to_name[context->type - 1]);
+
+ mls_sid_to_context(context, &scontextp);
+
+@@ -650,7 +678,7 @@ int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
+ char *scontextp;
+
+ *scontext_len = strlen(initial_sid_to_string[sid]) + 1;
+- scontextp = kmalloc(*scontext_len,GFP_ATOMIC);
++ scontextp = kmalloc(*scontext_len, GFP_ATOMIC);
+ if (!scontextp) {
+ rc = -ENOMEM;
+ goto out;
+@@ -659,16 +687,16 @@ int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
+ *scontext = scontextp;
+ goto out;
+ }
+- printk(KERN_ERR "security_sid_to_context: called before initial "
+- "load_policy on unknown SID %d\n", sid);
++ printk(KERN_ERR "SELinux: %s: called before initial "
++ "load_policy on unknown SID %d\n", __func__, sid);
+ rc = -EINVAL;
+ goto out;
+ }
+ POLICY_RDLOCK;
+ context = sidtab_search(&sidtab, sid);
+ if (!context) {
+- printk(KERN_ERR "security_sid_to_context: unrecognized SID "
+- "%d\n", sid);
++ printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
++ __func__, sid);
+ rc = -EINVAL;
+ goto out_unlock;
+ }
+@@ -898,15 +926,15 @@ static int security_compute_sid(u32 ssid,
+
+ scontext = sidtab_search(&sidtab, ssid);
+ if (!scontext) {
+- printk(KERN_ERR "security_compute_sid: unrecognized SID %d\n",
+- ssid);
++ printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
++ __func__, ssid);
+ rc = -EINVAL;
+ goto out_unlock;
+ }
+ tcontext = sidtab_search(&sidtab, tsid);
+ if (!tcontext) {
+- printk(KERN_ERR "security_compute_sid: unrecognized SID %d\n",
+- tsid);
++ printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
++ __func__, tsid);
+ rc = -EINVAL;
+ goto out_unlock;
+ }
+@@ -946,7 +974,7 @@ static int security_compute_sid(u32 ssid,
+ avdatum = avtab_search(&policydb.te_avtab, &avkey);
+
+ /* If no permanent rule, also check for enabled conditional rules */
+- if(!avdatum) {
++ if (!avdatum) {
+ node = avtab_search_node(&policydb.te_cond_avtab, &avkey);
+ for (; node != NULL; node = avtab_search_node_next(node, specified)) {
+ if (node->key.specified & AVTAB_ENABLED) {
+@@ -1096,7 +1124,7 @@ static int validate_classes(struct policydb *p)
+ continue;
+ if (i > p->p_classes.nprim) {
+ printk(KERN_INFO
+- "security: class %s not defined in policy\n",
++ "SELinux: class %s not defined in policy\n",
+ def_class);
+ if (p->reject_unknown)
+ return -EINVAL;
+@@ -1107,7 +1135,7 @@ static int validate_classes(struct policydb *p)
+ pol_class = p->p_class_val_to_name[i-1];
+ if (strcmp(pol_class, def_class)) {
+ printk(KERN_ERR
+- "security: class %d is incorrect, found %s but should be %s\n",
++ "SELinux: class %d is incorrect, found %s but should be %s\n",
+ i, pol_class, def_class);
+ return -EINVAL;
+ }
+@@ -1125,7 +1153,7 @@ static int validate_classes(struct policydb *p)
+ nprim = 1 << (perms->nprim - 1);
+ if (perm_val > nprim) {
+ printk(KERN_INFO
+- "security: permission %s in class %s not defined in policy\n",
++ "SELinux: permission %s in class %s not defined in policy\n",
+ def_perm, pol_class);
+ if (p->reject_unknown)
+ return -EINVAL;
+@@ -1136,14 +1164,14 @@ static int validate_classes(struct policydb *p)
+ perdatum = hashtab_search(perms->table, def_perm);
+ if (perdatum == NULL) {
+ printk(KERN_ERR
+- "security: permission %s in class %s not found in policy, bad policy\n",
++ "SELinux: permission %s in class %s not found in policy, bad policy\n",
+ def_perm, pol_class);
+ return -EINVAL;
+ }
+ pol_val = 1 << (perdatum->value - 1);
+ if (pol_val != perm_val) {
+ printk(KERN_ERR
+- "security: permission %s in class %s has incorrect value\n",
++ "SELinux: permission %s in class %s has incorrect value\n",
+ def_perm, pol_class);
+ return -EINVAL;
+ }
+@@ -1157,7 +1185,7 @@ static int validate_classes(struct policydb *p)
+ BUG_ON(!cladatum);
+ if (!cladatum->comdatum) {
+ printk(KERN_ERR
+- "security: class %s should have an inherits clause but does not\n",
++ "SELinux: class %s should have an inherits clause but does not\n",
+ pol_class);
+ return -EINVAL;
+ }
+@@ -1172,7 +1200,7 @@ static int validate_classes(struct policydb *p)
+ def_perm = kdefs->av_inherit[i].common_pts[j];
+ if (j >= perms->nprim) {
+ printk(KERN_INFO
+- "security: permission %s in class %s not defined in policy\n",
++ "SELinux: permission %s in class %s not defined in policy\n",
+ def_perm, pol_class);
+ if (p->reject_unknown)
+ return -EINVAL;
+@@ -1183,13 +1211,13 @@ static int validate_classes(struct policydb *p)
+ perdatum = hashtab_search(perms->table, def_perm);
+ if (perdatum == NULL) {
+ printk(KERN_ERR
+- "security: permission %s in class %s not found in policy, bad policy\n",
++ "SELinux: permission %s in class %s not found in policy, bad policy\n",
+ def_perm, pol_class);
+ return -EINVAL;
+ }
+ if (perdatum->value != j + 1) {
+ printk(KERN_ERR
+- "security: permission %s in class %s has incorrect value\n",
++ "SELinux: permission %s in class %s has incorrect value\n",
+ def_perm, pol_class);
+ return -EINVAL;
+ }
+@@ -1219,7 +1247,7 @@ static inline int convert_context_handle_invalid_context(struct context *context
+ u32 len;
+
+ context_struct_to_string(context, &s, &len);
+- printk(KERN_ERR "security: context %s is invalid\n", s);
++ printk(KERN_ERR "SELinux: context %s is invalid\n", s);
+ kfree(s);
+ }
+ return rc;
+@@ -1260,26 +1288,23 @@ static int convert_context(u32 key,
+
+ /* Convert the user. */
+ usrdatum = hashtab_search(args->newp->p_users.table,
+- args->oldp->p_user_val_to_name[c->user - 1]);
+- if (!usrdatum) {
++ args->oldp->p_user_val_to_name[c->user - 1]);
++ if (!usrdatum)
+ goto bad;
+- }
+ c->user = usrdatum->value;
+
+ /* Convert the role. */
+ role = hashtab_search(args->newp->p_roles.table,
+- args->oldp->p_role_val_to_name[c->role - 1]);
+- if (!role) {
++ args->oldp->p_role_val_to_name[c->role - 1]);
++ if (!role)
+ goto bad;
+- }
+ c->role = role->value;
+
+ /* Convert the type. */
+ typdatum = hashtab_search(args->newp->p_types.table,
+- args->oldp->p_type_val_to_name[c->type - 1]);
+- if (!typdatum) {
++ args->oldp->p_type_val_to_name[c->type - 1]);
++ if (!typdatum)
+ goto bad;
+- }
+ c->type = typdatum->value;
+
+ rc = mls_convert_context(args->oldp, args->newp, c);
+@@ -1299,7 +1324,7 @@ out:
+ bad:
+ context_struct_to_string(&oldc, &s, &len);
+ context_destroy(&oldc);
+- printk(KERN_ERR "security: invalidating context %s\n", s);
++ printk(KERN_ERR "SELinux: invalidating context %s\n", s);
+ kfree(s);
+ goto out;
+ }
+@@ -1308,6 +1333,8 @@ static void security_load_policycaps(void)
+ {
+ selinux_policycap_netpeer = ebitmap_get_bit(&policydb.policycaps,
+ POLICYDB_CAPABILITY_NETPEER);
++ selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
++ POLICYDB_CAPABILITY_OPENPERM);
+ }
+
+ extern void selinux_complete_init(void);
+@@ -1350,7 +1377,7 @@ int security_load_policy(void *data, size_t len)
+ /* Verify that the kernel defined classes are correct. */
+ if (validate_classes(&policydb)) {
+ printk(KERN_ERR
+- "security: the definition of a class is incorrect\n");
++ "SELinux: the definition of a class is incorrect\n");
+ LOAD_UNLOCK;
+ sidtab_destroy(&sidtab);
+ policydb_destroy(&policydb);
+@@ -1384,14 +1411,14 @@ int security_load_policy(void *data, size_t len)
+ /* Verify that the kernel defined classes are correct. */
+ if (validate_classes(&newpolicydb)) {
+ printk(KERN_ERR
+- "security: the definition of a class is incorrect\n");
++ "SELinux: the definition of a class is incorrect\n");
+ rc = -EINVAL;
+ goto err;
+ }
+
+ rc = security_preserve_bools(&newpolicydb);
+ if (rc) {
+- printk(KERN_ERR "security: unable to preserve booleans\n");
++ printk(KERN_ERR "SELinux: unable to preserve booleans\n");
+ goto err;
+ }
+
+@@ -1443,17 +1470,11 @@ err:
+
+ /**
+ * security_port_sid - Obtain the SID for a port.
+- * @domain: communication domain aka address family
+- * @type: socket type
+ * @protocol: protocol number
+ * @port: port number
+ * @out_sid: security identifier
+ */
+-int security_port_sid(u16 domain,
+- u16 type,
+- u8 protocol,
+- u16 port,
+- u32 *out_sid)
++int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
+ {
+ struct ocontext *c;
+ int rc = 0;
+@@ -1532,8 +1553,8 @@ static int match_ipv6_addrmask(u32 *input, u32 *addr, u32 *mask)
+ {
+ int i, fail = 0;
+
+- for(i = 0; i < 4; i++)
+- if(addr[i] != (input[i] & mask[i])) {
++ for (i = 0; i < 4; i++)
++ if (addr[i] != (input[i] & mask[i])) {
+ fail = 1;
+ break;
+ }
+@@ -1632,7 +1653,7 @@ out:
+ */
+
+ int security_get_user_sids(u32 fromsid,
+- char *username,
++ char *username,
+ u32 **sids,
+ u32 *nel)
+ {
+@@ -1742,7 +1763,7 @@ out:
+ * transition SIDs or task SIDs.
+ */
+ int security_genfs_sid(const char *fstype,
+- char *path,
++ char *path,
+ u16 sclass,
+ u32 *sid)
+ {
+@@ -1857,7 +1878,7 @@ int security_get_bools(int *len, char ***names, int **values)
+ goto out;
+ }
+
+- *names = kcalloc(*len, sizeof(char*), GFP_ATOMIC);
++ *names = kcalloc(*len, sizeof(char *), GFP_ATOMIC);
+ if (!*names)
+ goto err;
+
+@@ -1869,7 +1890,7 @@ int security_get_bools(int *len, char ***names, int **values)
+ size_t name_len;
+ (*values)[i] = policydb.bool_val_to_struct[i]->state;
+ name_len = strlen(policydb.p_bool_val_to_name[i]) + 1;
+- (*names)[i] = kmalloc(sizeof(char) * name_len, GFP_ATOMIC);
++ (*names)[i] = kmalloc(sizeof(char) * name_len, GFP_ATOMIC);
+ if (!(*names)[i])
+ goto err;
+ strncpy((*names)[i], policydb.p_bool_val_to_name[i], name_len);
+@@ -1914,11 +1935,10 @@ int security_set_bools(int len, int *values)
+ audit_get_loginuid(current),
+ audit_get_sessionid(current));
+ }
+- if (values[i]) {
++ if (values[i])
+ policydb.bool_val_to_struct[i]->state = 1;
+- } else {
++ else
+ policydb.bool_val_to_struct[i]->state = 0;
+- }
+ }
+
+ for (cur = policydb.cond_list; cur != NULL; cur = cur->next) {
+@@ -2012,16 +2032,16 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
+ POLICY_RDLOCK;
+ context1 = sidtab_search(&sidtab, sid);
+ if (!context1) {
+- printk(KERN_ERR "security_sid_mls_copy: unrecognized SID "
+- "%d\n", sid);
++ printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
++ __func__, sid);
+ rc = -EINVAL;
+ goto out_unlock;
+ }
+
+ context2 = sidtab_search(&sidtab, mls_sid);
+ if (!context2) {
+- printk(KERN_ERR "security_sid_mls_copy: unrecognized SID "
+- "%d\n", mls_sid);
++ printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
++ __func__, mls_sid);
+ rc = -EINVAL;
+ goto out_unlock;
+ }
+@@ -2112,17 +2132,15 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
+
+ nlbl_ctx = sidtab_search(&sidtab, nlbl_sid);
+ if (!nlbl_ctx) {
+- printk(KERN_ERR
+- "security_sid_mls_cmp: unrecognized SID %d\n",
+- nlbl_sid);
++ printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
++ __func__, nlbl_sid);
+ rc = -EINVAL;
+ goto out_slowpath;
+ }
+ xfrm_ctx = sidtab_search(&sidtab, xfrm_sid);
+ if (!xfrm_ctx) {
+- printk(KERN_ERR
+- "security_sid_mls_cmp: unrecognized SID %d\n",
+- xfrm_sid);
++ printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
++ __func__, xfrm_sid);
+ rc = -EINVAL;
+ goto out_slowpath;
+ }
+@@ -2202,8 +2220,8 @@ int security_get_permissions(char *class, char ***perms, int *nperms)
+
+ match = hashtab_search(policydb.p_classes.table, class);
+ if (!match) {
+- printk(KERN_ERR "%s: unrecognized class %s\n",
+- __FUNCTION__, class);
++ printk(KERN_ERR "SELinux: %s: unrecognized class %s\n",
++ __func__, class);
+ rc = -EINVAL;
+ goto out;
+ }
+@@ -2273,21 +2291,23 @@ struct selinux_audit_rule {
+ struct context au_ctxt;
+ };
+
+-void selinux_audit_rule_free(struct selinux_audit_rule *rule)
++void selinux_audit_rule_free(void *vrule)
+ {
++ struct selinux_audit_rule *rule = vrule;
++
+ if (rule) {
+ context_destroy(&rule->au_ctxt);
+ kfree(rule);
+ }
+ }
+
+-int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
+- struct selinux_audit_rule **rule)
++int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
+ {
+ struct selinux_audit_rule *tmprule;
+ struct role_datum *roledatum;
+ struct type_datum *typedatum;
+ struct user_datum *userdatum;
++ struct selinux_audit_rule **rule = (struct selinux_audit_rule **)vrule;
+ int rc = 0;
+
+ *rule = NULL;
+@@ -2374,17 +2394,42 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
+ return rc;
+ }
+
+-int selinux_audit_rule_match(u32 sid, u32 field, u32 op,
+- struct selinux_audit_rule *rule,
++/* Check to see if the rule contains any selinux fields */
++int selinux_audit_rule_known(struct audit_krule *rule)
++{
++ int i;
++
++ for (i = 0; i < rule->field_count; i++) {
++ struct audit_field *f = &rule->fields[i];
++ switch (f->type) {
++ case AUDIT_SUBJ_USER:
++ case AUDIT_SUBJ_ROLE:
++ case AUDIT_SUBJ_TYPE:
++ case AUDIT_SUBJ_SEN:
++ case AUDIT_SUBJ_CLR:
++ case AUDIT_OBJ_USER:
++ case AUDIT_OBJ_ROLE:
++ case AUDIT_OBJ_TYPE:
++ case AUDIT_OBJ_LEV_LOW:
++ case AUDIT_OBJ_LEV_HIGH:
++ return 1;
++ }
++ }
++
++ return 0;
++}
++
++int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
+ struct audit_context *actx)
+ {
+ struct context *ctxt;
+ struct mls_level *level;
++ struct selinux_audit_rule *rule = vrule;
+ int match = 0;
+
+ if (!rule) {
+ audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR,
+- "selinux_audit_rule_match: missing rule\n");
++ "selinux_audit_rule_match: missing rule\n");
+ return -ENOENT;
+ }
+
+@@ -2392,7 +2437,7 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op,
+
+ if (rule->au_seqno < latest_granting) {
+ audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR,
+- "selinux_audit_rule_match: stale rule\n");
++ "selinux_audit_rule_match: stale rule\n");
+ match = -ESTALE;
+ goto out;
+ }
+@@ -2400,8 +2445,8 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op,
+ ctxt = sidtab_search(&sidtab, sid);
+ if (!ctxt) {
+ audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR,
+- "selinux_audit_rule_match: unrecognized SID %d\n",
+- sid);
++ "selinux_audit_rule_match: unrecognized SID %d\n",
++ sid);
+ match = -ENOENT;
+ goto out;
+ }
+@@ -2447,36 +2492,36 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op,
+ case AUDIT_OBJ_LEV_LOW:
+ case AUDIT_OBJ_LEV_HIGH:
+ level = ((field == AUDIT_SUBJ_SEN ||
+- field == AUDIT_OBJ_LEV_LOW) ?
+- &ctxt->range.level[0] : &ctxt->range.level[1]);
++ field == AUDIT_OBJ_LEV_LOW) ?
++ &ctxt->range.level[0] : &ctxt->range.level[1]);
+ switch (op) {
+ case AUDIT_EQUAL:
+ match = mls_level_eq(&rule->au_ctxt.range.level[0],
+- level);
++ level);
+ break;
+ case AUDIT_NOT_EQUAL:
+ match = !mls_level_eq(&rule->au_ctxt.range.level[0],
+- level);
++ level);
+ break;
+ case AUDIT_LESS_THAN:
+ match = (mls_level_dom(&rule->au_ctxt.range.level[0],
+- level) &&
+- !mls_level_eq(&rule->au_ctxt.range.level[0],
+- level));
++ level) &&
++ !mls_level_eq(&rule->au_ctxt.range.level[0],
++ level));
+ break;
+ case AUDIT_LESS_THAN_OR_EQUAL:
+ match = mls_level_dom(&rule->au_ctxt.range.level[0],
+- level);
++ level);
+ break;
+ case AUDIT_GREATER_THAN:
+ match = (mls_level_dom(level,
+- &rule->au_ctxt.range.level[0]) &&
+- !mls_level_eq(level,
+- &rule->au_ctxt.range.level[0]));
++ &rule->au_ctxt.range.level[0]) &&
++ !mls_level_eq(level,
++ &rule->au_ctxt.range.level[0]));
+ break;
+ case AUDIT_GREATER_THAN_OR_EQUAL:
+ match = mls_level_dom(level,
+- &rule->au_ctxt.range.level[0]);
++ &rule->au_ctxt.range.level[0]);
+ break;
+ }
+ }
+@@ -2486,7 +2531,7 @@ out:
+ return match;
+ }
+
+-static int (*aurule_callback)(void) = NULL;
++static int (*aurule_callback)(void) = audit_update_lsm_rules;
+
+ static int aurule_avc_callback(u32 event, u32 ssid, u32 tsid,
+ u16 class, u32 perms, u32 *retained)
+@@ -2503,7 +2548,7 @@ static int __init aurule_init(void)
+ int err;
+
+ err = avc_add_callback(aurule_avc_callback, AVC_CALLBACK_RESET,
+- SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
++ SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
+ if (err)
+ panic("avc_add_callback() failed, error %d\n", err);
+
+@@ -2511,11 +2556,6 @@ static int __init aurule_init(void)
+ }
+ __initcall(aurule_init);
+
+-void selinux_audit_set_callback(int (*callback)(void))
+-{
+- aurule_callback = callback;
+-}
+-
+ #ifdef CONFIG_NETLABEL
+ /**
+ * security_netlbl_cache_add - Add an entry to the NetLabel cache
+@@ -2651,7 +2691,7 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
+ goto netlbl_sid_to_secattr_failure;
+ secattr->domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1],
+ GFP_ATOMIC);
+- secattr->flags |= NETLBL_SECATTR_DOMAIN;
++ secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY;
+ mls_export_netlbl_lvl(ctx, secattr);
+ rc = mls_export_netlbl_cat(ctx, secattr);
+ if (rc != 0)
+diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c
+index 53a54a7..4a516ff 100644
+--- a/security/selinux/ss/sidtab.c
++++ b/security/selinux/ss/sidtab.c
+@@ -156,12 +156,10 @@ void sidtab_map_remove_on_error(struct sidtab *s,
+ while (cur != NULL) {
+ ret = apply(cur->sid, &cur->context, args);
+ if (ret) {
+- if (last) {
++ if (last)
+ last->next = cur->next;
+- } else {
++ else
+ s->htable[i] = cur->next;
+- }
+-
+ temp = cur;
+ cur = cur->next;
+ context_destroy(&temp->context);
+diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
+index 7e15820..8f17f54 100644
+--- a/security/selinux/xfrm.c
++++ b/security/selinux/xfrm.c
+@@ -45,7 +45,6 @@
+ #include <net/xfrm.h>
+ #include <net/checksum.h>
+ #include <net/udp.h>
+-#include <asm/semaphore.h>
+ #include <asm/atomic.h>
+
+ #include "avc.h"
+@@ -77,20 +76,18 @@ static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
+ * LSM hook implementation that authorizes that a flow can use
+ * a xfrm policy rule.
+ */
+-int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir)
++int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
+ {
+ int rc;
+ u32 sel_sid;
+- struct xfrm_sec_ctx *ctx;
+
+ /* Context sid is either set to label or ANY_ASSOC */
+- if ((ctx = xp->security)) {
++ if (ctx) {
+ if (!selinux_authorizable_ctx(ctx))
+ return -EINVAL;
+
+ sel_sid = ctx->ctx_sid;
+- }
+- else
++ } else
+ /*
+ * All flows should be treated as polmatch'ing an
+ * otherwise applicable "non-labeled" policy. This
+@@ -103,7 +100,7 @@ int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir)
+ NULL);
+
+ if (rc == -EACCES)
+- rc = -ESRCH;
++ return -ESRCH;
+
+ return rc;
+ }
+@@ -183,8 +180,7 @@ int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
+
+ if (!ckall)
+ break;
+- }
+- else if (*sid != ctx->ctx_sid)
++ } else if (*sid != ctx->ctx_sid)
+ return -EINVAL;
+ }
+ }
+@@ -287,15 +283,14 @@ out2:
+ * LSM hook implementation that allocs and transfers uctx spec to
+ * xfrm_policy.
+ */
+-int selinux_xfrm_policy_alloc(struct xfrm_policy *xp,
+- struct xfrm_user_sec_ctx *uctx)
++int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
++ struct xfrm_user_sec_ctx *uctx)
+ {
+ int err;
+
+- BUG_ON(!xp);
+ BUG_ON(!uctx);
+
+- err = selinux_xfrm_sec_ctx_alloc(&xp->security, uctx, 0);
++ err = selinux_xfrm_sec_ctx_alloc(ctxp, uctx, 0);
+ if (err == 0)
+ atomic_inc(&selinux_xfrm_refcount);
+
+@@ -307,43 +302,38 @@ int selinux_xfrm_policy_alloc(struct xfrm_policy *xp,
+ * LSM hook implementation that copies security data structure from old to
+ * new for policy cloning.
+ */
+-int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
++int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
++ struct xfrm_sec_ctx **new_ctxp)
+ {
+- struct xfrm_sec_ctx *old_ctx, *new_ctx;
+-
+- old_ctx = old->security;
++ struct xfrm_sec_ctx *new_ctx;
+
+ if (old_ctx) {
+- new_ctx = new->security = kmalloc(sizeof(*new_ctx) +
+- old_ctx->ctx_len,
+- GFP_KERNEL);
+-
++ new_ctx = kmalloc(sizeof(*old_ctx) + old_ctx->ctx_len,
++ GFP_KERNEL);
+ if (!new_ctx)
+ return -ENOMEM;
+
+ memcpy(new_ctx, old_ctx, sizeof(*new_ctx));
+ memcpy(new_ctx->ctx_str, old_ctx->ctx_str, new_ctx->ctx_len);
++ *new_ctxp = new_ctx;
+ }
+ return 0;
+ }
+
+ /*
+- * LSM hook implementation that frees xfrm_policy security information.
++ * LSM hook implementation that frees xfrm_sec_ctx security information.
+ */
+-void selinux_xfrm_policy_free(struct xfrm_policy *xp)
++void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
+ {
+- struct xfrm_sec_ctx *ctx = xp->security;
+- if (ctx)
+- kfree(ctx);
++ kfree(ctx);
+ }
+
+ /*
+ * LSM hook implementation that authorizes deletion of labeled policies.
+ */
+-int selinux_xfrm_policy_delete(struct xfrm_policy *xp)
++int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
+ {
+ struct task_security_struct *tsec = current->security;
+- struct xfrm_sec_ctx *ctx = xp->security;
+ int rc = 0;
+
+ if (ctx) {
+@@ -380,8 +370,7 @@ int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uct
+ void selinux_xfrm_state_free(struct xfrm_state *x)
+ {
+ struct xfrm_sec_ctx *ctx = x->security;
+- if (ctx)
+- kfree(ctx);
++ kfree(ctx);
+ }
+
+ /*
+diff --git a/security/smack/smack.h b/security/smack/smack.h
+index 62c1e98..4a4477f 100644
+--- a/security/smack/smack.h
++++ b/security/smack/smack.h
+@@ -15,6 +15,7 @@
+
+ #include <linux/capability.h>
+ #include <linux/spinlock.h>
++#include <linux/security.h>
+ #include <net/netlabel.h>
+
+ /*
+@@ -187,6 +188,7 @@ extern struct smack_known smack_known_star;
+ extern struct smack_known smack_known_unset;
+
+ extern struct smk_list_entry *smack_list;
++extern struct security_operations smack_ops;
+
+ /*
+ * Stricly for CIPSO level manipulation.
+diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
+index 732ba27..4215971 100644
+--- a/security/smack/smack_lsm.c
++++ b/security/smack/smack_lsm.c
+@@ -315,10 +315,10 @@ static int smack_sb_statfs(struct dentry *dentry)
+ * Returns 0 if current can write the floor of the filesystem
+ * being mounted on, an error code otherwise.
+ */
+-static int smack_sb_mount(char *dev_name, struct nameidata *nd,
++static int smack_sb_mount(char *dev_name, struct path *path,
+ char *type, unsigned long flags, void *data)
+ {
+- struct superblock_smack *sbp = nd->path.mnt->mnt_sb->s_security;
++ struct superblock_smack *sbp = path->mnt->mnt_sb->s_security;
+
+ return smk_curacc(sbp->smk_floor, MAY_WRITE);
+ }
+@@ -1275,7 +1275,7 @@ static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
+
+ switch (smack_net_nltype) {
+ case NETLBL_NLTYPE_CIPSOV4:
+- nlsp->domain = kstrdup(smack, GFP_ATOMIC);
++ nlsp->domain = smack;
+ nlsp->flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
+
+ rc = smack_to_cipso(smack, &cipso);
+@@ -2424,7 +2424,9 @@ static void smack_release_secctx(char *secdata, u32 seclen)
+ {
+ }
+
+-static struct security_operations smack_ops = {
++struct security_operations smack_ops = {
++ .name = "smack",
++
+ .ptrace = smack_ptrace,
+ .capget = cap_capget,
+ .capset_check = cap_capset_check,
+@@ -2557,6 +2559,9 @@ static struct security_operations smack_ops = {
+ */
+ static __init int smack_init(void)
+ {
++ if (!security_module_enable(&smack_ops))
++ return 0;
++
+ printk(KERN_INFO "Smack: Initializing.\n");
+
+ /*
+diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
+index cfae8af..6ba2837 100644
+--- a/security/smack/smackfs.c
++++ b/security/smack/smackfs.c
+@@ -965,12 +965,21 @@ static struct vfsmount *smackfs_mount;
+ *
+ * register the smackfs
+ *
+- * Returns 0 unless the registration fails.
++ * Do not register smackfs if Smack wasn't enabled
++ * on boot. We can not put this method normally under the
++ * smack_init() code path since the security subsystem get
++ * initialized before the vfs caches.
++ *
++ * Returns true if we were not chosen on boot or if
++ * we were chosen and filesystem registration succeeded.
+ */
+ static int __init init_smk_fs(void)
+ {
+ int err;
+
++ if (!security_module_enable(&smack_ops))
++ return 0;
++
+ err = register_filesystem(&smk_fs_type);
+ if (!err) {
+ smackfs_mount = kern_mount(&smk_fs_type);
+diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
+index 5d86e68..5b3274b 100644
+--- a/sound/arm/pxa2xx-ac97.c
++++ b/sound/arm/pxa2xx-ac97.c
+@@ -16,6 +16,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/interrupt.h>
+ #include <linux/wait.h>
++#include <linux/clk.h>
+ #include <linux/delay.h>
+
+ #include <sound/core.h>
+@@ -27,6 +28,7 @@
+ #include <linux/mutex.h>
+ #include <asm/hardware.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/audio.h>
+
+ #include "pxa2xx-pcm.h"
+@@ -35,6 +37,10 @@
+ static DEFINE_MUTEX(car_mutex);
+ static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
+ static volatile long gsr_bits;
++static struct clk *ac97_clk;
++#ifdef CONFIG_PXA27x
++static struct clk *ac97conf_clk;
++#endif
+
+ /*
+ * Beware PXA27x bugs:
+@@ -66,7 +72,7 @@ static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg
+ if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1) <= 0 &&
+ !((GSR | gsr_bits) & GSR_SDONE)) {
+ printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n",
+- __FUNCTION__, reg, GSR | gsr_bits);
++ __func__, reg, GSR | gsr_bits);
+ val = -1;
+ goto out;
+ }
+@@ -98,7 +104,7 @@ static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigne
+ if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1) <= 0 &&
+ !((GSR | gsr_bits) & GSR_CDONE))
+ printk(KERN_ERR "%s: write error (ac97_reg=%d GSR=%#lx)\n",
+- __FUNCTION__, reg, GSR | gsr_bits);
++ __func__, reg, GSR | gsr_bits);
+
+ mutex_unlock(&car_mutex);
+ }
+@@ -106,17 +112,35 @@ static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigne
+ static void pxa2xx_ac97_reset(struct snd_ac97 *ac97)
+ {
+ /* First, try cold reset */
++#ifdef CONFIG_PXA3xx
++ int timeout;
++
++ /* Hold CLKBPB for 100us */
++ GCR = 0;
++ GCR = GCR_CLKBPB;
++ udelay(100);
++ GCR = 0;
++#endif
++
+ GCR &= GCR_COLD_RST; /* clear everything but nCRST */
+ GCR &= ~GCR_COLD_RST; /* then assert nCRST */
+
+ gsr_bits = 0;
+ #ifdef CONFIG_PXA27x
+ /* PXA27x Developers Manual section 13.5.2.2.1 */
+- pxa_set_cken(CKEN_AC97CONF, 1);
++ clk_enable(ac97conf_clk);
+ udelay(5);
+- pxa_set_cken(CKEN_AC97CONF, 0);
++ clk_disable(ac97conf_clk);
+ GCR = GCR_COLD_RST;
+ udelay(50);
++#elif defined(CONFIG_PXA3xx)
++ timeout = 1000;
++ /* Can't use interrupts on PXA3xx */
++ GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
++
++ GCR = GCR_WARM_RST | GCR_COLD_RST;
++ while (!(GSR & (GSR_PCR | GSR_SCR)) && timeout--)
++ mdelay(10);
+ #else
+ GCR = GCR_COLD_RST;
+ GCR |= GCR_CDONE_IE|GCR_SDONE_IE;
+@@ -125,7 +149,7 @@ static void pxa2xx_ac97_reset(struct snd_ac97 *ac97)
+
+ if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) {
+ printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n",
+- __FUNCTION__, gsr_bits);
++ __func__, gsr_bits);
+
+ /* let's try warm reset */
+ gsr_bits = 0;
+@@ -137,6 +161,12 @@ static void pxa2xx_ac97_reset(struct snd_ac97 *ac97)
+ GCR |= GCR_WARM_RST;
+ pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+ udelay(500);
++#elif defined(CONFIG_PXA3xx)
++ timeout = 100;
++ /* Can't use interrupts */
++ GCR |= GCR_WARM_RST;
++ while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
++ mdelay(1);
+ #else
+ GCR |= GCR_WARM_RST|GCR_PRIRDY_IEN|GCR_SECRDY_IEN;
+ wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
+@@ -144,7 +174,7 @@ static void pxa2xx_ac97_reset(struct snd_ac97 *ac97)
+
+ if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
+ printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",
+- __FUNCTION__, gsr_bits);
++ __func__, gsr_bits);
+ }
+
+ GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
+@@ -259,7 +289,7 @@ static int pxa2xx_ac97_do_suspend(struct snd_card *card, pm_message_t state)
+ if (platform_ops && platform_ops->suspend)
+ platform_ops->suspend(platform_ops->priv);
+ GCR |= GCR_ACLINK_OFF;
+- pxa_set_cken(CKEN_AC97, 0);
++ clk_disable(ac97_clk);
+
+ return 0;
+ }
+@@ -268,7 +298,7 @@ static int pxa2xx_ac97_do_resume(struct snd_card *card)
+ {
+ pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data;
+
+- pxa_set_cken(CKEN_AC97, 1);
++ clk_enable(ac97_clk);
+ if (platform_ops && platform_ops->resume)
+ platform_ops->resume(platform_ops->priv);
+ snd_ac97_resume(pxa2xx_ac97_ac97);
+@@ -335,8 +365,21 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev)
+ #ifdef CONFIG_PXA27x
+ /* Use GPIO 113 as AC97 Reset on Bulverde */
+ pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
++ ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK");
++ if (IS_ERR(ac97conf_clk)) {
++ ret = PTR_ERR(ac97conf_clk);
++ ac97conf_clk = NULL;
++ goto err;
++ }
+ #endif
+- pxa_set_cken(CKEN_AC97, 1);
++
++ ac97_clk = clk_get(&dev->dev, "AC97CLK");
++ if (IS_ERR(ac97_clk)) {
++ ret = PTR_ERR(ac97_clk);
++ ac97_clk = NULL;
++ goto err;
++ }
++ clk_enable(ac97_clk);
+
+ ret = snd_ac97_bus(card, 0, &pxa2xx_ac97_ops, NULL, &ac97_bus);
+ if (ret)
+@@ -361,11 +404,19 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev)
+ err:
+ if (card)
+ snd_card_free(card);
+- if (CKEN & (1 << CKEN_AC97)) {
++ if (ac97_clk) {
+ GCR |= GCR_ACLINK_OFF;
+ free_irq(IRQ_AC97, NULL);
+- pxa_set_cken(CKEN_AC97, 0);
++ clk_disable(ac97_clk);
++ clk_put(ac97_clk);
++ ac97_clk = NULL;
++ }
++#ifdef CONFIG_PXA27x
++ if (ac97conf_clk) {
++ clk_put(ac97conf_clk);
++ ac97conf_clk = NULL;
+ }
++#endif
+ return ret;
+ }
+
+@@ -378,7 +429,13 @@ static int __devexit pxa2xx_ac97_remove(struct platform_device *dev)
+ platform_set_drvdata(dev, NULL);
+ GCR |= GCR_ACLINK_OFF;
+ free_irq(IRQ_AC97, NULL);
+- pxa_set_cken(CKEN_AC97, 0);
++ clk_disable(ac97_clk);
++ clk_put(ac97_clk);
++ ac97_clk = NULL;
++#ifdef CONFIG_PXA27x
++ clk_put(ac97conf_clk);
++ ac97conf_clk = NULL;
++#endif
+ }
+
+ return 0;
+@@ -391,6 +448,7 @@ static struct platform_driver pxa2xx_ac97_driver = {
+ .resume = pxa2xx_ac97_resume,
+ .driver = {
+ .name = "pxa2xx-ac97",
++ .owner = THIS_MODULE,
+ },
+ };
+
+@@ -410,3 +468,4 @@ module_exit(pxa2xx_ac97_exit);
+ MODULE_AUTHOR("Nicolas Pitre");
+ MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:pxa2xx-ac97");
+diff --git a/sound/core/Kconfig b/sound/core/Kconfig
+index 829ca38..a8d71c6 100644
+--- a/sound/core/Kconfig
++++ b/sound/core/Kconfig
+@@ -181,3 +181,7 @@ config SND_PCM_XRUN_DEBUG
+ It is usually not required, but if you have trouble with
+ sound clicking when system is loaded, it may help to determine
+ the process or driver which causes the scheduling gaps.
++
++config SND_VMASTER
++ bool
++ depends on SND
+diff --git a/sound/core/Makefile b/sound/core/Makefile
+index 267039a..da8e685 100644
+--- a/sound/core/Makefile
++++ b/sound/core/Makefile
+@@ -6,6 +6,7 @@
+ snd-y := sound.o init.o memory.o info.o control.o misc.o device.o
+ snd-$(CONFIG_ISA_DMA_API) += isadma.o
+ snd-$(CONFIG_SND_OSSEMUL) += sound_oss.o info_oss.o
++snd-$(CONFIG_SND_VMASTER) += vmaster.o
+
+ snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
+ pcm_memory.o
+diff --git a/sound/core/init.c b/sound/core/init.c
+index e3338d6..ac05734 100644
+--- a/sound/core/init.c
++++ b/sound/core/init.c
+@@ -254,7 +254,7 @@ static int snd_disconnect_release(struct inode *inode, struct file *file)
+ if (likely(df))
+ return df->disconnected_f_op->release(inode, file);
+
+- panic("%s(%p, %p) failed!", __FUNCTION__, inode, file);
++ panic("%s(%p, %p) failed!", __func__, inode, file);
+ }
+
+ static unsigned int snd_disconnect_poll(struct file * file, poll_table * wait)
+@@ -311,6 +311,9 @@ int snd_card_disconnect(struct snd_card *card)
+ struct file *file;
+ int err;
+
++ if (!card)
++ return -EINVAL;
++
+ spin_lock(&card->files_lock);
+ if (card->shutdown) {
+ spin_unlock(&card->files_lock);
+@@ -322,6 +325,7 @@ int snd_card_disconnect(struct snd_card *card)
+ /* phase 1: disable fops (user space) operations for ALSA API */
+ mutex_lock(&snd_card_mutex);
+ snd_cards[card->number] = NULL;
++ snd_cards_lock &= ~(1 << card->number);
+ mutex_unlock(&snd_card_mutex);
+
+ /* phase 2: replace file->f_op with special dummy operations */
+@@ -360,6 +364,15 @@ int snd_card_disconnect(struct snd_card *card)
+ snd_printk(KERN_ERR "not all devices for card %i can be disconnected\n", card->number);
+
+ snd_info_card_disconnect(card);
++#ifndef CONFIG_SYSFS_DEPRECATED
++ if (card->card_dev) {
++ device_unregister(card->card_dev);
++ card->card_dev = NULL;
++ }
++#endif
++#ifdef CONFIG_PM
++ wake_up(&card->power_sleep);
++#endif
+ return 0;
+ }
+
+@@ -401,33 +414,14 @@ static int snd_card_do_free(struct snd_card *card)
+ snd_printk(KERN_WARNING "unable to free card info\n");
+ /* Not fatal error */
+ }
+-#ifndef CONFIG_SYSFS_DEPRECATED
+- if (card->card_dev)
+- device_unregister(card->card_dev);
+-#endif
+ kfree(card);
+ return 0;
+ }
+
+-static int snd_card_free_prepare(struct snd_card *card)
+-{
+- if (card == NULL)
+- return -EINVAL;
+- (void) snd_card_disconnect(card);
+- mutex_lock(&snd_card_mutex);
+- snd_cards[card->number] = NULL;
+- snd_cards_lock &= ~(1 << card->number);
+- mutex_unlock(&snd_card_mutex);
+-#ifdef CONFIG_PM
+- wake_up(&card->power_sleep);
+-#endif
+- return 0;
+-}
+-
+ int snd_card_free_when_closed(struct snd_card *card)
+ {
+ int free_now = 0;
+- int ret = snd_card_free_prepare(card);
++ int ret = snd_card_disconnect(card);
+ if (ret)
+ return ret;
+
+@@ -447,7 +441,7 @@ EXPORT_SYMBOL(snd_card_free_when_closed);
+
+ int snd_card_free(struct snd_card *card)
+ {
+- int ret = snd_card_free_prepare(card);
++ int ret = snd_card_disconnect(card);
+ if (ret)
+ return ret;
+
+diff --git a/sound/core/misc.c b/sound/core/misc.c
+index 102d1c3..38524f6 100644
+--- a/sound/core/misc.c
++++ b/sound/core/misc.c
+@@ -39,7 +39,7 @@ void snd_verbose_printk(const char *file, int line, const char *format, ...)
+ {
+ va_list args;
+
+- if (format[0] == '<' && format[1] >= '0' && format[1] <= '9' && format[2] == '>') {
++ if (format[0] == '<' && format[1] >= '0' && format[1] <= '7' && format[2] == '>') {
+ char tmp[] = "<0>";
+ tmp[1] = format[1];
+ printk("%sALSA %s:%d: ", tmp, file, line);
+@@ -60,7 +60,7 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
+ {
+ va_list args;
+
+- if (format[0] == '<' && format[1] >= '0' && format[1] <= '9' && format[2] == '>') {
++ if (format[0] == '<' && format[1] >= '0' && format[1] <= '7' && format[2] == '>') {
+ char tmp[] = "<0>";
+ tmp[1] = format[1];
+ printk("%sALSA %s:%d: ", tmp, file, line);
+diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
+index 75daed2..581aa2c 100644
+--- a/sound/core/oss/mixer_oss.c
++++ b/sound/core/oss/mixer_oss.c
+@@ -1257,6 +1257,8 @@ static void snd_mixer_oss_build(struct snd_mixer_oss *mixer)
+ { SOUND_MIXER_DIGITAL3, "Digital", 2 },
+ { SOUND_MIXER_PHONEIN, "Phone", 0 },
+ { SOUND_MIXER_PHONEOUT, "Master Mono", 0 },
++ { SOUND_MIXER_PHONEOUT, "Speaker", 0 }, /*fallback*/
++ { SOUND_MIXER_PHONEOUT, "Mono", 0 }, /*fallback*/
+ { SOUND_MIXER_PHONEOUT, "Phone", 0 }, /* fallback */
+ { SOUND_MIXER_VIDEO, "Video", 0 },
+ { SOUND_MIXER_RADIO, "Radio", 0 },
+diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
+index ab570a0..558dadb 100644
+--- a/sound/core/seq/oss/seq_oss_synth.c
++++ b/sound/core/seq/oss/seq_oss_synth.c
+@@ -245,8 +245,13 @@ snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp)
+ info->nr_voices = rec->nr_voices;
+ if (info->nr_voices > 0) {
+ info->ch = kcalloc(info->nr_voices, sizeof(struct seq_oss_chinfo), GFP_KERNEL);
+- if (!info->ch)
+- BUG();
++ if (!info->ch) {
++ snd_printk(KERN_ERR "Cannot malloc\n");
++ rec->oper.close(&info->arg);
++ module_put(rec->oper.owner);
++ snd_use_lock_free(&rec->use_lock);
++ continue;
++ }
+ reset_channels(info);
+ }
+ debug_printk(("synth %d assigned\n", i));
+diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c
+new file mode 100644
+index 0000000..4cc57f9
+--- /dev/null
++++ b/sound/core/vmaster.c
+@@ -0,0 +1,371 @@
++/*
++ * Virtual master and slave controls
++ *
++ * Copyright (c) 2008 by Takashi Iwai <tiwai at suse.de>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation, version 2.
++ *
++ */
++
++#include <linux/slab.h>
++#include <sound/core.h>
++#include <sound/control.h>
++#include <sound/tlv.h>
++
++/*
++ * a subset of information returned via ctl info callback
++ */
++struct link_ctl_info {
++ int type; /* value type */
++ int count; /* item count */
++ int min_val, max_val; /* min, max values */
++};
++
++/*
++ * link master - this contains a list of slave controls that are
++ * identical types, i.e. info returns the same value type and value
++ * ranges, but may have different number of counts.
++ *
++ * The master control is so far only mono volume/switch for simplicity.
++ * The same value will be applied to all slaves.
++ */
++struct link_master {
++ struct list_head slaves;
++ struct link_ctl_info info;
++ int val; /* the master value */
++ unsigned int tlv[4];
++};
++
++/*
++ * link slave - this contains a slave control element
++ *
++ * It fakes the control callbacsk with additional attenuation by the
++ * master control. A slave may have either one or two channels.
++ */
++
++struct link_slave {
++ struct list_head list;
++ struct link_master *master;
++ struct link_ctl_info info;
++ int vals[2]; /* current values */
++ struct snd_kcontrol slave; /* the copy of original control entry */
++};
++
++/* get the slave ctl info and save the initial values */
++static int slave_init(struct link_slave *slave)
++{
++ struct snd_ctl_elem_info *uinfo;
++ struct snd_ctl_elem_value *uctl;
++ int err, ch;
++
++ if (slave->info.count)
++ return 0; /* already initialized */
++
++ uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL);
++ if (!uinfo)
++ return -ENOMEM;
++ uinfo->id = slave->slave.id;
++ err = slave->slave.info(&slave->slave, uinfo);
++ if (err < 0) {
++ kfree(uinfo);
++ return err;
++ }
++ slave->info.type = uinfo->type;
++ slave->info.count = uinfo->count;
++ if (slave->info.count > 2 ||
++ (slave->info.type != SNDRV_CTL_ELEM_TYPE_INTEGER &&
++ slave->info.type != SNDRV_CTL_ELEM_TYPE_BOOLEAN)) {
++ snd_printk(KERN_ERR "invalid slave element\n");
++ kfree(uinfo);
++ return -EINVAL;
++ }
++ slave->info.min_val = uinfo->value.integer.min;
++ slave->info.max_val = uinfo->value.integer.max;
++ kfree(uinfo);
++
++ uctl = kmalloc(sizeof(*uctl), GFP_KERNEL);
++ if (!uctl)
++ return -ENOMEM;
++ uctl->id = slave->slave.id;
++ err = slave->slave.get(&slave->slave, uctl);
++ for (ch = 0; ch < slave->info.count; ch++)
++ slave->vals[ch] = uctl->value.integer.value[ch];
++ kfree(uctl);
++ return 0;
++}
++
++/* initialize master volume */
++static int master_init(struct link_master *master)
++{
++ struct link_slave *slave;
++
++ if (master->info.count)
++ return 0; /* already initialized */
++
++ list_for_each_entry(slave, &master->slaves, list) {
++ int err = slave_init(slave);
++ if (err < 0)
++ return err;
++ master->info = slave->info;
++ master->info.count = 1; /* always mono */
++ /* set full volume as default (= no attenuation) */
++ master->val = master->info.max_val;
++ return 0;
++ }
++ return -ENOENT;
++}
++
++static int slave_get_val(struct link_slave *slave,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ int err, ch;
++
++ err = slave_init(slave);
++ if (err < 0)
++ return err;
++ for (ch = 0; ch < slave->info.count; ch++)
++ ucontrol->value.integer.value[ch] = slave->vals[ch];
++ return 0;
++}
++
++static int slave_put_val(struct link_slave *slave,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ int err, ch, vol;
++
++ err = master_init(slave->master);
++ if (err < 0)
++ return err;
++
++ switch (slave->info.type) {
++ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
++ for (ch = 0; ch < slave->info.count; ch++)
++ ucontrol->value.integer.value[ch] &=
++ !!slave->master->val;
++ break;
++ case SNDRV_CTL_ELEM_TYPE_INTEGER:
++ for (ch = 0; ch < slave->info.count; ch++) {
++ /* max master volume is supposed to be 0 dB */
++ vol = ucontrol->value.integer.value[ch];
++ vol += slave->master->val - slave->master->info.max_val;
++ if (vol < slave->info.min_val)
++ vol = slave->info.min_val;
++ else if (vol > slave->info.max_val)
++ vol = slave->info.max_val;
++ ucontrol->value.integer.value[ch] = vol;
++ }
++ break;
++ }
++ return slave->slave.put(&slave->slave, ucontrol);
++}
++
++/*
++ * ctl callbacks for slaves
++ */
++static int slave_info(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++ struct link_slave *slave = snd_kcontrol_chip(kcontrol);
++ return slave->slave.info(&slave->slave, uinfo);
++}
++
++static int slave_get(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct link_slave *slave = snd_kcontrol_chip(kcontrol);
++ return slave_get_val(slave, ucontrol);
++}
++
++static int slave_put(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct link_slave *slave = snd_kcontrol_chip(kcontrol);
++ int err, ch, changed = 0;
++
++ err = slave_init(slave);
++ if (err < 0)
++ return err;
++ for (ch = 0; ch < slave->info.count; ch++) {
++ if (slave->vals[ch] != ucontrol->value.integer.value[ch]) {
++ changed = 1;
++ slave->vals[ch] = ucontrol->value.integer.value[ch];
++ }
++ }
++ if (!changed)
++ return 0;
++ return slave_put_val(slave, ucontrol);
++}
++
++static int slave_tlv_cmd(struct snd_kcontrol *kcontrol,
++ int op_flag, unsigned int size,
++ unsigned int __user *tlv)
++{
++ struct link_slave *slave = snd_kcontrol_chip(kcontrol);
++ /* FIXME: this assumes that the max volume is 0 dB */
++ return slave->slave.tlv.c(&slave->slave, op_flag, size, tlv);
++}
++
++static void slave_free(struct snd_kcontrol *kcontrol)
++{
++ struct link_slave *slave = snd_kcontrol_chip(kcontrol);
++ if (slave->slave.private_free)
++ slave->slave.private_free(&slave->slave);
++ if (slave->master)
++ list_del(&slave->list);
++ kfree(slave);
++}
++
++/*
++ * Add a slave control to the group with the given master control
++ *
++ * All slaves must be the same type (returning the same information
++ * via info callback). The fucntion doesn't check it, so it's your
++ * responsibility.
++ *
++ * Also, some additional limitations:
++ * - at most two channels
++ * - logarithmic volume control (dB level), no linear volume
++ * - master can only attenuate the volume, no gain
++ */
++int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
++{
++ struct link_master *master_link = snd_kcontrol_chip(master);
++ struct link_slave *srec;
++
++ srec = kzalloc(sizeof(*srec) +
++ slave->count * sizeof(*slave->vd), GFP_KERNEL);
++ if (!srec)
++ return -ENOMEM;
++ srec->slave = *slave;
++ memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd));
++ srec->master = master_link;
++
++ /* override callbacks */
++ slave->info = slave_info;
++ slave->get = slave_get;
++ slave->put = slave_put;
++ if (slave->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)
++ slave->tlv.c = slave_tlv_cmd;
++ slave->private_data = srec;
++ slave->private_free = slave_free;
++
++ list_add_tail(&srec->list, &master_link->slaves);
++ return 0;
++}
++
++EXPORT_SYMBOL(snd_ctl_add_slave);
++
++/*
++ * ctl callbacks for master controls
++ */
++static int master_info(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++ struct link_master *master = snd_kcontrol_chip(kcontrol);
++ int ret;
++
++ ret = master_init(master);
++ if (ret < 0)
++ return ret;
++ uinfo->type = master->info.type;
++ uinfo->count = master->info.count;
++ uinfo->value.integer.min = master->info.min_val;
++ uinfo->value.integer.max = master->info.max_val;
++ return 0;
++}
++
++static int master_get(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct link_master *master = snd_kcontrol_chip(kcontrol);
++ int err = master_init(master);
++ if (err < 0)
++ return err;
++ ucontrol->value.integer.value[0] = master->val;
++ return 0;
++}
++
++static int master_put(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct link_master *master = snd_kcontrol_chip(kcontrol);
++ struct link_slave *slave;
++ struct snd_ctl_elem_value *uval;
++ int err, old_val;
++
++ err = master_init(master);
++ if (err < 0)
++ return err;
++ old_val = master->val;
++ if (ucontrol->value.integer.value[0] == old_val)
++ return 0;
++
++ uval = kmalloc(sizeof(*uval), GFP_KERNEL);
++ if (!uval)
++ return -ENOMEM;
++ list_for_each_entry(slave, &master->slaves, list) {
++ master->val = old_val;
++ uval->id = slave->slave.id;
++ slave_get_val(slave, uval);
++ master->val = ucontrol->value.integer.value[0];
++ slave_put_val(slave, uval);
++ }
++ kfree(uval);
++ return 1;
++}
++
++static void master_free(struct snd_kcontrol *kcontrol)
++{
++ struct link_master *master = snd_kcontrol_chip(kcontrol);
++ struct link_slave *slave;
++
++ list_for_each_entry(slave, &master->slaves, list)
++ slave->master = NULL;
++ kfree(master);
++}
++
++
++/*
++ * Create a virtual master control with the given name
++ */
++struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
++ const unsigned int *tlv)
++{
++ struct link_master *master;
++ struct snd_kcontrol *kctl;
++ struct snd_kcontrol_new knew;
++
++ memset(&knew, 0, sizeof(knew));
++ knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
++ knew.name = name;
++ knew.info = master_info;
++
++ master = kzalloc(sizeof(*master), GFP_KERNEL);
++ if (!master)
++ return NULL;
++ INIT_LIST_HEAD(&master->slaves);
++
++ kctl = snd_ctl_new1(&knew, master);
++ if (!kctl) {
++ kfree(master);
++ return NULL;
++ }
++ /* override some callbacks */
++ kctl->info = master_info;
++ kctl->get = master_get;
++ kctl->put = master_put;
++ kctl->private_free = master_free;
++
++ /* additional (constant) TLV read */
++ if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE) {
++ kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
++ memcpy(master->tlv, tlv, sizeof(master->tlv));
++ kctl->tlv.p = master->tlv;
++ }
++
++ return kctl;
++}
++
++EXPORT_SYMBOL(snd_ctl_make_virtual_master);
+diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
+index 75d4fe0..fe85af1 100644
+--- a/sound/drivers/Kconfig
++++ b/sound/drivers/Kconfig
+@@ -4,6 +4,24 @@ menu "Generic devices"
+ depends on SND!=n
+
+
++config SND_PCSP
++ tristate "Internal PC speaker support"
++ depends on X86_PC && HIGH_RES_TIMERS
++ depends on INPUT
++ help
++ If you don't have a sound card in your computer, you can include a
++ driver for the PC speaker which allows it to act like a primitive
++ sound card.
++ This driver also replaces the pcspkr driver for beeps.
++
++ You can compile this as a module which will be called snd-pcsp.
++
++ You don't need this driver if you only want your pc-speaker to beep.
++ You don't need this driver if you have a tablet piezo beeper
++ in your PC instead of the real speaker.
++
++ It should not hurt to say Y or M here in all other cases.
++
+ config SND_MPU401_UART
+ tristate
+ select SND_RAWMIDI
+diff --git a/sound/drivers/Makefile b/sound/drivers/Makefile
+index 8e55300..d4a07f9 100644
+--- a/sound/drivers/Makefile
++++ b/sound/drivers/Makefile
+@@ -20,4 +20,4 @@ obj-$(CONFIG_SND_MTS64) += snd-mts64.o
+ obj-$(CONFIG_SND_PORTMAN2X4) += snd-portman2x4.o
+ obj-$(CONFIG_SND_ML403_AC97CR) += snd-ml403-ac97cr.o
+
+-obj-$(CONFIG_SND) += opl3/ opl4/ mpu401/ vx/
++obj-$(CONFIG_SND) += opl3/ opl4/ mpu401/ vx/ pcsp/
+diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
+index a240eae..4e4c69e 100644
+--- a/sound/drivers/dummy.c
++++ b/sound/drivers/dummy.c
+@@ -181,10 +181,10 @@ struct snd_dummy_pcm {
+ struct snd_dummy *dummy;
+ spinlock_t lock;
+ struct timer_list timer;
+- unsigned int pcm_size;
+- unsigned int pcm_count;
++ unsigned int pcm_buffer_size;
++ unsigned int pcm_period_size;
+ unsigned int pcm_bps; /* bytes per second */
+- unsigned int pcm_jiffie; /* bytes per one jiffie */
++ unsigned int pcm_hz; /* HZ */
+ unsigned int pcm_irq_pos; /* IRQ position */
+ unsigned int pcm_buf_pos; /* position in buffer */
+ struct snd_pcm_substream *substream;
+@@ -230,19 +230,24 @@ static int snd_card_dummy_pcm_prepare(struct snd_pcm_substream *substream)
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_dummy_pcm *dpcm = runtime->private_data;
+- unsigned int bps;
++ int bps;
++
++ bps = snd_pcm_format_width(runtime->format) * runtime->rate *
++ runtime->channels / 8;
+
+- bps = runtime->rate * runtime->channels;
+- bps *= snd_pcm_format_width(runtime->format);
+- bps /= 8;
+ if (bps <= 0)
+ return -EINVAL;
++
+ dpcm->pcm_bps = bps;
+- dpcm->pcm_jiffie = bps / HZ;
+- dpcm->pcm_size = snd_pcm_lib_buffer_bytes(substream);
+- dpcm->pcm_count = snd_pcm_lib_period_bytes(substream);
++ dpcm->pcm_hz = HZ;
++ dpcm->pcm_buffer_size = snd_pcm_lib_buffer_bytes(substream);
++ dpcm->pcm_period_size = snd_pcm_lib_period_bytes(substream);
+ dpcm->pcm_irq_pos = 0;
+ dpcm->pcm_buf_pos = 0;
++
++ snd_pcm_format_set_silence(runtime->format, runtime->dma_area,
++ bytes_to_samples(runtime, runtime->dma_bytes));
++
+ return 0;
+ }
+
+@@ -254,11 +259,11 @@ static void snd_card_dummy_pcm_timer_function(unsigned long data)
+ spin_lock_irqsave(&dpcm->lock, flags);
+ dpcm->timer.expires = 1 + jiffies;
+ add_timer(&dpcm->timer);
+- dpcm->pcm_irq_pos += dpcm->pcm_jiffie;
+- dpcm->pcm_buf_pos += dpcm->pcm_jiffie;
+- dpcm->pcm_buf_pos %= dpcm->pcm_size;
+- if (dpcm->pcm_irq_pos >= dpcm->pcm_count) {
+- dpcm->pcm_irq_pos %= dpcm->pcm_count;
++ dpcm->pcm_irq_pos += dpcm->pcm_bps;
++ dpcm->pcm_buf_pos += dpcm->pcm_bps;
++ dpcm->pcm_buf_pos %= dpcm->pcm_buffer_size * dpcm->pcm_hz;
++ if (dpcm->pcm_irq_pos >= dpcm->pcm_period_size * dpcm->pcm_hz) {
++ dpcm->pcm_irq_pos %= dpcm->pcm_period_size * dpcm->pcm_hz;
+ spin_unlock_irqrestore(&dpcm->lock, flags);
+ snd_pcm_period_elapsed(dpcm->substream);
+ } else
+@@ -270,7 +275,7 @@ static snd_pcm_uframes_t snd_card_dummy_pcm_pointer(struct snd_pcm_substream *su
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_dummy_pcm *dpcm = runtime->private_data;
+
+- return bytes_to_frames(runtime, dpcm->pcm_buf_pos);
++ return bytes_to_frames(runtime, dpcm->pcm_buf_pos / dpcm->pcm_hz);
+ }
+
+ static struct snd_pcm_hardware snd_card_dummy_playback =
+diff --git a/sound/drivers/ml403-ac97cr.c b/sound/drivers/ml403-ac97cr.c
+index 05a871a..ecdbeb6 100644
+--- a/sound/drivers/ml403-ac97cr.c
++++ b/sound/drivers/ml403-ac97cr.c
+@@ -1191,8 +1191,6 @@ snd_ml403_ac97cr_create(struct snd_card *card, struct platform_device *pfdev,
+ return err;
+ }
+
+- snd_card_set_dev(card, &pfdev->dev);
+-
+ *rml403_ac97cr = ml403_ac97cr;
+ return 0;
+ }
+@@ -1330,11 +1328,15 @@ static int snd_ml403_ac97cr_remove(struct platform_device *pfdev)
+ return 0;
+ }
+
++/* work with hotplug and coldplug */
++MODULE_ALIAS("platform:" SND_ML403_AC97CR_DRIVER);
++
+ static struct platform_driver snd_ml403_ac97cr_driver = {
+ .probe = snd_ml403_ac97cr_probe,
+ .remove = snd_ml403_ac97cr_remove,
+ .driver = {
+ .name = SND_ML403_AC97CR_DRIVER,
++ .owner = THIS_MODULE,
+ },
+ };
+
+diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
+index 5993864..18cca24 100644
+--- a/sound/drivers/mpu401/mpu401_uart.c
++++ b/sound/drivers/mpu401/mpu401_uart.c
+@@ -49,12 +49,10 @@ static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu);
+
+ */
+
+-#define snd_mpu401_input_avail(mpu) (!(mpu->read(mpu, MPU401C(mpu)) & 0x80))
+-#define snd_mpu401_output_ready(mpu) (!(mpu->read(mpu, MPU401C(mpu)) & 0x40))
+-
+-#define MPU401_RESET 0xff
+-#define MPU401_ENTER_UART 0x3f
+-#define MPU401_ACK 0xfe
++#define snd_mpu401_input_avail(mpu) \
++ (!(mpu->read(mpu, MPU401C(mpu)) & MPU401_RX_EMPTY))
++#define snd_mpu401_output_ready(mpu) \
++ (!(mpu->read(mpu, MPU401C(mpu)) & MPU401_TX_FULL))
+
+ /* Build in lowlevel io */
+ static void mpu401_write_port(struct snd_mpu401 *mpu, unsigned char data,
+@@ -425,16 +423,17 @@ static void snd_mpu401_uart_input_read(struct snd_mpu401 * mpu)
+ static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu)
+ {
+ unsigned char byte;
+- int max = 256, timeout;
++ int max = 256;
+
+ do {
+ if (snd_rawmidi_transmit_peek(mpu->substream_output,
+ &byte, 1) == 1) {
+- for (timeout = 100; timeout > 0; timeout--) {
+- if (snd_mpu401_output_ready(mpu))
+- break;
+- }
+- if (timeout == 0)
++ /*
++ * Try twice because there is hardware that insists on
++ * setting the output busy bit after each write.
++ */
++ if (!snd_mpu401_output_ready(mpu) &&
++ !snd_mpu401_output_ready(mpu))
+ break; /* Tx FIFO full - try again later */
+ mpu->write(mpu, byte, MPU401D(mpu));
+ snd_rawmidi_transmit_ack(mpu->substream_output, 1);
+diff --git a/sound/drivers/pcsp/Makefile b/sound/drivers/pcsp/Makefile
+new file mode 100644
+index 0000000..b19555b
+--- /dev/null
++++ b/sound/drivers/pcsp/Makefile
+@@ -0,0 +1,2 @@
++snd-pcsp-objs := pcsp.o pcsp_lib.o pcsp_mixer.o pcsp_input.o
++obj-$(CONFIG_SND_PCSP) += snd-pcsp.o
+diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c
+new file mode 100644
+index 0000000..5920351
+--- /dev/null
++++ b/sound/drivers/pcsp/pcsp.c
+@@ -0,0 +1,235 @@
++/*
++ * PC-Speaker driver for Linux
++ *
++ * Copyright (C) 1997-2001 David Woodhouse
++ * Copyright (C) 2001-2008 Stas Sergeev
++ */
++
++#include <linux/init.h>
++#include <linux/moduleparam.h>
++#include <linux/platform_device.h>
++#include <sound/core.h>
++#include <sound/initval.h>
++#include <sound/pcm.h>
++#include <linux/input.h>
++#include <linux/delay.h>
++#include <asm/bitops.h>
++#include "pcsp_input.h"
++#include "pcsp.h"
++
++MODULE_AUTHOR("Stas Sergeev <stsp at users.sourceforge.net>");
++MODULE_DESCRIPTION("PC-Speaker driver");
++MODULE_LICENSE("GPL");
++MODULE_SUPPORTED_DEVICE("{{PC-Speaker, pcsp}}");
++MODULE_ALIAS("platform:pcspkr");
++
++static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
++static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
++static int enable = SNDRV_DEFAULT_ENABLE1; /* Enable this card */
++
++module_param(index, int, 0444);
++MODULE_PARM_DESC(index, "Index value for pcsp soundcard.");
++module_param(id, charp, 0444);
++MODULE_PARM_DESC(id, "ID string for pcsp soundcard.");
++module_param(enable, bool, 0444);
++MODULE_PARM_DESC(enable, "Enable PC-Speaker sound.");
++
++struct snd_pcsp pcsp_chip;
++
++static int __devinit snd_pcsp_create(struct snd_card *card)
++{
++ static struct snd_device_ops ops = { };
++ struct timespec tp;
++ int err;
++ int div, min_div, order;
++
++ hrtimer_get_res(CLOCK_MONOTONIC, &tp);
++ if (tp.tv_sec || tp.tv_nsec > PCSP_MAX_PERIOD_NS) {
++ printk(KERN_ERR "PCSP: Timer resolution is not sufficient "
++ "(%linS)\n", tp.tv_nsec);
++ printk(KERN_ERR "PCSP: Make sure you have HPET and ACPI "
++ "enabled.\n");
++ return -EIO;
++ }
++
++ if (loops_per_jiffy >= PCSP_MIN_LPJ && tp.tv_nsec <= PCSP_MIN_PERIOD_NS)
++ min_div = MIN_DIV;
++ else
++ min_div = MAX_DIV;
++#if PCSP_DEBUG
++ printk("PCSP: lpj=%li, min_div=%i, res=%li\n",
++ loops_per_jiffy, min_div, tp.tv_nsec);
++#endif
++
++ div = MAX_DIV / min_div;
++ order = fls(div) - 1;
++
++ pcsp_chip.max_treble = min(order, PCSP_MAX_TREBLE);
++ pcsp_chip.treble = min(pcsp_chip.max_treble, PCSP_DEFAULT_TREBLE);
++ pcsp_chip.playback_ptr = 0;
++ pcsp_chip.period_ptr = 0;
++ atomic_set(&pcsp_chip.timer_active, 0);
++ pcsp_chip.enable = 1;
++ pcsp_chip.pcspkr = 1;
++
++ spin_lock_init(&pcsp_chip.substream_lock);
++
++ pcsp_chip.card = card;
++ pcsp_chip.port = 0x61;
++ pcsp_chip.irq = -1;
++ pcsp_chip.dma = -1;
++
++ /* Register device */
++ err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, &pcsp_chip, &ops);
++ if (err < 0)
++ return err;
++
++ return 0;
++}
++
++static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev)
++{
++ struct snd_card *card;
++ int err;
++
++ if (devnum != 0)
++ return -EINVAL;
++
++ hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
++ pcsp_chip.timer.cb_mode = HRTIMER_CB_IRQSAFE;
++ pcsp_chip.timer.function = pcsp_do_timer;
++
++ card = snd_card_new(index, id, THIS_MODULE, 0);
++ if (!card)
++ return -ENOMEM;
++
++ err = snd_pcsp_create(card);
++ if (err < 0) {
++ snd_card_free(card);
++ return err;
++ }
++ err = snd_pcsp_new_pcm(&pcsp_chip);
++ if (err < 0) {
++ snd_card_free(card);
++ return err;
++ }
++ err = snd_pcsp_new_mixer(&pcsp_chip);
++ if (err < 0) {
++ snd_card_free(card);
++ return err;
++ }
++
++ snd_card_set_dev(pcsp_chip.card, dev);
++
++ strcpy(card->driver, "PC-Speaker");
++ strcpy(card->shortname, "pcsp");
++ sprintf(card->longname, "Internal PC-Speaker at port 0x%x",
++ pcsp_chip.port);
++
++ err = snd_card_register(card);
++ if (err < 0) {
++ snd_card_free(card);
++ return err;
++ }
++
++ return 0;
++}
++
++static int __devinit alsa_card_pcsp_init(struct device *dev)
++{
++ int err;
++
++ err = snd_card_pcsp_probe(0, dev);
++ if (err) {
++ printk(KERN_ERR "PC-Speaker initialization failed.\n");
++ return err;
++ }
++
++#ifdef CONFIG_DEBUG_PAGEALLOC
++ /* Well, CONFIG_DEBUG_PAGEALLOC makes the sound horrible. Lets alert */
++ printk(KERN_WARNING "PCSP: CONFIG_DEBUG_PAGEALLOC is enabled, "
++ "which may make the sound noisy.\n");
++#endif
++
++ return 0;
++}
++
++static void __devexit alsa_card_pcsp_exit(struct snd_pcsp *chip)
++{
++ snd_card_free(chip->card);
++}
++
++static int __devinit pcsp_probe(struct platform_device *dev)
++{
++ int err;
++
++ err = pcspkr_input_init(&pcsp_chip.input_dev, &dev->dev);
++ if (err < 0)
++ return err;
++
++ err = alsa_card_pcsp_init(&dev->dev);
++ if (err < 0) {
++ pcspkr_input_remove(pcsp_chip.input_dev);
++ return err;
++ }
++
++ platform_set_drvdata(dev, &pcsp_chip);
++ return 0;
++}
++
++static int __devexit pcsp_remove(struct platform_device *dev)
++{
++ struct snd_pcsp *chip = platform_get_drvdata(dev);
++ alsa_card_pcsp_exit(chip);
++ pcspkr_input_remove(chip->input_dev);
++ platform_set_drvdata(dev, NULL);
++ return 0;
++}
++
++static void pcsp_stop_beep(struct snd_pcsp *chip)
++{
++ spin_lock_irq(&chip->substream_lock);
++ if (!chip->playback_substream)
++ pcspkr_stop_sound();
++ spin_unlock_irq(&chip->substream_lock);
++}
++
++static int pcsp_suspend(struct platform_device *dev, pm_message_t state)
++{
++ struct snd_pcsp *chip = platform_get_drvdata(dev);
++ pcsp_stop_beep(chip);
++ snd_pcm_suspend_all(chip->pcm);
++ return 0;
++}
++
++static void pcsp_shutdown(struct platform_device *dev)
++{
++ struct snd_pcsp *chip = platform_get_drvdata(dev);
++ pcsp_stop_beep(chip);
++}
++
++static struct platform_driver pcsp_platform_driver = {
++ .driver = {
++ .name = "pcspkr",
++ .owner = THIS_MODULE,
++ },
++ .probe = pcsp_probe,
++ .remove = __devexit_p(pcsp_remove),
++ .suspend = pcsp_suspend,
++ .shutdown = pcsp_shutdown,
++};
++
++static int __init pcsp_init(void)
++{
++ if (!enable)
++ return -ENODEV;
++ return platform_driver_register(&pcsp_platform_driver);
++}
++
++static void __exit pcsp_exit(void)
++{
++ platform_driver_unregister(&pcsp_platform_driver);
++}
++
++module_init(pcsp_init);
++module_exit(pcsp_exit);
+diff --git a/sound/drivers/pcsp/pcsp.h b/sound/drivers/pcsp/pcsp.h
+new file mode 100644
+index 0000000..f07cc1e
+--- /dev/null
++++ b/sound/drivers/pcsp/pcsp.h
+@@ -0,0 +1,82 @@
++/*
++ * PC-Speaker driver for Linux
++ *
++ * Copyright (C) 1993-1997 Michael Beck
++ * Copyright (C) 1997-2001 David Woodhouse
++ * Copyright (C) 2001-2008 Stas Sergeev
++ */
++
++#ifndef __PCSP_H__
++#define __PCSP_H__
++
++#include <linux/hrtimer.h>
++#if defined(CONFIG_MIPS) || defined(CONFIG_X86)
++/* Use the global PIT lock ! */
++#include <asm/i8253.h>
++#else
++#include <asm/8253pit.h>
++static DEFINE_SPINLOCK(i8253_lock);
++#endif
++
++#define PCSP_SOUND_VERSION 0x400 /* read 4.00 */
++#define PCSP_DEBUG 0
++
++/* default timer freq for PC-Speaker: 18643 Hz */
++#define DIV_18KHZ 64
++#define MAX_DIV DIV_18KHZ
++#define CUR_DIV() (MAX_DIV >> chip->treble)
++#define PCSP_MAX_TREBLE 1
++
++/* unfortunately, with hrtimers 37KHz does not work very well :( */
++#define PCSP_DEFAULT_TREBLE 0
++#define MIN_DIV (MAX_DIV >> PCSP_MAX_TREBLE)
++
++/* wild guess */
++#define PCSP_MIN_LPJ 1000000
++#define PCSP_DEFAULT_SDIV (DIV_18KHZ >> 1)
++#define PCSP_DEFAULT_SRATE (PIT_TICK_RATE / PCSP_DEFAULT_SDIV)
++#define PCSP_INDEX_INC() (1 << (PCSP_MAX_TREBLE - chip->treble))
++#define PCSP_RATE() (PIT_TICK_RATE / CUR_DIV())
++#define PCSP_MIN_RATE__1 MAX_DIV/PIT_TICK_RATE
++#define PCSP_MAX_RATE__1 MIN_DIV/PIT_TICK_RATE
++#define PCSP_MAX_PERIOD_NS (1000000000ULL * PCSP_MIN_RATE__1)
++#define PCSP_MIN_PERIOD_NS (1000000000ULL * PCSP_MAX_RATE__1)
++#define PCSP_CALC_NS(div) ({ \
++ u64 __val = 1000000000ULL * (div); \
++ do_div(__val, PIT_TICK_RATE); \
++ __val; \
++})
++#define PCSP_PERIOD_NS() PCSP_CALC_NS(CUR_DIV())
++
++#define PCSP_MAX_PERIOD_SIZE (64*1024)
++#define PCSP_MAX_PERIODS 512
++#define PCSP_BUFFER_SIZE (128*1024)
++
++struct snd_pcsp {
++ struct snd_card *card;
++ struct snd_pcm *pcm;
++ struct input_dev *input_dev;
++ struct hrtimer timer;
++ unsigned short port, irq, dma;
++ spinlock_t substream_lock;
++ struct snd_pcm_substream *playback_substream;
++ size_t playback_ptr;
++ size_t period_ptr;
++ atomic_t timer_active;
++ int thalf;
++ u64 ns_rem;
++ unsigned char val61;
++ int enable;
++ int max_treble;
++ int treble;
++ int pcspkr;
++};
++
++extern struct snd_pcsp pcsp_chip;
++
++extern enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle);
++
++extern int snd_pcsp_new_pcm(struct snd_pcsp *chip);
++extern int snd_pcsp_new_mixer(struct snd_pcsp *chip);
++
++#endif
+diff --git a/sound/drivers/pcsp/pcsp_input.c b/sound/drivers/pcsp/pcsp_input.c
+new file mode 100644
+index 0000000..cd9b83e
+--- /dev/null
++++ b/sound/drivers/pcsp/pcsp_input.c
+@@ -0,0 +1,116 @@
++/*
++ * PC Speaker beeper driver for Linux
++ *
++ * Copyright (c) 2002 Vojtech Pavlik
++ * Copyright (c) 1992 Orest Zborowski
++ *
++ */
++
++/*
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation
++ */
++
++#include <linux/init.h>
++#include <linux/input.h>
++#include <asm/io.h>
++#include "pcsp.h"
++
++static void pcspkr_do_sound(unsigned int count)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&i8253_lock, flags);
++
++ if (count) {
++ /* enable counter 2 */
++ outb_p(inb_p(0x61) | 3, 0x61);
++ /* set command for counter 2, 2 byte write */
++ outb_p(0xB6, 0x43);
++ /* select desired HZ */
++ outb_p(count & 0xff, 0x42);
++ outb((count >> 8) & 0xff, 0x42);
++ } else {
++ /* disable counter 2 */
++ outb(inb_p(0x61) & 0xFC, 0x61);
++ }
++
++ spin_unlock_irqrestore(&i8253_lock, flags);
++}
++
++void pcspkr_stop_sound(void)
++{
++ pcspkr_do_sound(0);
++}
++
++static int pcspkr_input_event(struct input_dev *dev, unsigned int type,
++ unsigned int code, int value)
++{
++ unsigned int count = 0;
++
++ if (atomic_read(&pcsp_chip.timer_active) || !pcsp_chip.pcspkr)
++ return 0;
++
++ switch (type) {
++ case EV_SND:
++ switch (code) {
++ case SND_BELL:
++ if (value)
++ value = 1000;
++ case SND_TONE:
++ break;
++ default:
++ return -1;
++ }
++ break;
++
++ default:
++ return -1;
++ }
++
++ if (value > 20 && value < 32767)
++ count = PIT_TICK_RATE / value;
++
++ pcspkr_do_sound(count);
++
++ return 0;
++}
++
++int __devinit pcspkr_input_init(struct input_dev **rdev, struct device *dev)
++{
++ int err;
++
++ struct input_dev *input_dev = input_allocate_device();
++ if (!input_dev)
++ return -ENOMEM;
++
++ input_dev->name = "PC Speaker";
++ input_dev->phys = "isa0061/input0";
++ input_dev->id.bustype = BUS_ISA;
++ input_dev->id.vendor = 0x001f;
++ input_dev->id.product = 0x0001;
++ input_dev->id.version = 0x0100;
++ input_dev->dev.parent = dev;
++
++ input_dev->evbit[0] = BIT(EV_SND);
++ input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
++ input_dev->event = pcspkr_input_event;
++
++ err = input_register_device(input_dev);
++ if (err) {
++ input_free_device(input_dev);
++ return err;
++ }
++
++ *rdev = input_dev;
++ return 0;
++}
++
++int pcspkr_input_remove(struct input_dev *dev)
++{
++ pcspkr_stop_sound();
++ input_unregister_device(dev); /* this also does kfree() */
++
++ return 0;
++}
+diff --git a/sound/drivers/pcsp/pcsp_input.h b/sound/drivers/pcsp/pcsp_input.h
+new file mode 100644
+index 0000000..e66738c
+--- /dev/null
++++ b/sound/drivers/pcsp/pcsp_input.h
+@@ -0,0 +1,14 @@
++/*
++ * PC-Speaker driver for Linux
++ *
++ * Copyright (C) 2001-2008 Stas Sergeev
++ */
++
++#ifndef __PCSP_INPUT_H__
++#define __PCSP_INPUT_H__
++
++int __devinit pcspkr_input_init(struct input_dev **rdev, struct device *dev);
++int pcspkr_input_remove(struct input_dev *dev);
++void pcspkr_stop_sound(void);
++
++#endif
+diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c
+new file mode 100644
+index 0000000..ac6238e
+--- /dev/null
++++ b/sound/drivers/pcsp/pcsp_lib.c
+@@ -0,0 +1,338 @@
++/*
++ * PC-Speaker driver for Linux
++ *
++ * Copyright (C) 1993-1997 Michael Beck
++ * Copyright (C) 1997-2001 David Woodhouse
++ * Copyright (C) 2001-2008 Stas Sergeev
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <sound/pcm.h>
++#include <linux/interrupt.h>
++#include <asm/io.h>
++#include "pcsp.h"
++
++static int nforce_wa;
++module_param(nforce_wa, bool, 0444);
++MODULE_PARM_DESC(nforce_wa, "Apply NForce chipset workaround "
++ "(expect bad sound)");
++
++static void pcsp_start_timer(unsigned long dummy)
++{
++ hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL);
++}
++
++/*
++ * We need the hrtimer_start as a tasklet to avoid
++ * the nasty locking problem. :(
++ * The problem:
++ * - The timer handler is called with the cpu_base->lock
++ * already held by hrtimer code.
++ * - snd_pcm_period_elapsed() takes the
++ * substream->self_group.lock.
++ * So far so good.
++ * But the snd_pcsp_trigger() is called with the
++ * substream->self_group.lock held, and it calls
++ * hrtimer_start(), which takes the cpu_base->lock.
++ * You see the problem. We have the code pathes
++ * which take two locks in a reverse order. This
++ * can deadlock and the lock validator complains.
++ * The only solution I could find was to move the
++ * hrtimer_start() into a tasklet. -stsp
++ */
++static DECLARE_TASKLET(pcsp_start_timer_tasklet, pcsp_start_timer, 0);
++
++enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
++{
++ unsigned long flags;
++ unsigned char timer_cnt, val;
++ int periods_elapsed;
++ u64 ns;
++ size_t period_bytes, buffer_bytes;
++ struct snd_pcm_substream *substream;
++ struct snd_pcm_runtime *runtime;
++ struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer);
++
++ if (chip->thalf) {
++ outb(chip->val61, 0x61);
++ chip->thalf = 0;
++ if (!atomic_read(&chip->timer_active))
++ return HRTIMER_NORESTART;
++ hrtimer_forward(&chip->timer, chip->timer.expires,
++ ktime_set(0, chip->ns_rem));
++ return HRTIMER_RESTART;
++ }
++
++ /* hrtimer calls us from both hardirq and softirq contexts,
++ * so irqsave :( */
++ spin_lock_irqsave(&chip->substream_lock, flags);
++ /* Takashi Iwai says regarding this extra lock:
++
++ If the irq handler handles some data on the DMA buffer, it should
++ do snd_pcm_stream_lock().
++ That protects basically against all races among PCM callbacks, yes.
++ However, there are two remaining issues:
++ 1. The substream pointer you try to lock isn't protected _before_
++ this lock yet.
++ 2. snd_pcm_period_elapsed() itself acquires the lock.
++ The requirement of another lock is because of 1. When you get
++ chip->playback_substream, it's not protected.
++ Keeping this lock while snd_pcm_period_elapsed() assures the substream
++ is still protected (at least, not released). And the other status is
++ handled properly inside snd_pcm_stream_lock() in
++ snd_pcm_period_elapsed().
++
++ */
++ if (!chip->playback_substream)
++ goto exit_nr_unlock1;
++ substream = chip->playback_substream;
++ snd_pcm_stream_lock(substream);
++ if (!atomic_read(&chip->timer_active))
++ goto exit_nr_unlock2;
++
++ runtime = substream->runtime;
++ /* assume it is u8 mono */
++ val = runtime->dma_area[chip->playback_ptr];
++ timer_cnt = val * CUR_DIV() / 256;
++
++ if (timer_cnt && chip->enable) {
++ spin_lock(&i8253_lock);
++ if (!nforce_wa) {
++ outb_p(chip->val61, 0x61);
++ outb_p(timer_cnt, 0x42);
++ outb(chip->val61 ^ 1, 0x61);
++ } else {
++ outb(chip->val61 ^ 2, 0x61);
++ chip->thalf = 1;
++ }
++ spin_unlock(&i8253_lock);
++ }
++
++ period_bytes = snd_pcm_lib_period_bytes(substream);
++ buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
++ chip->playback_ptr += PCSP_INDEX_INC();
++ periods_elapsed = chip->playback_ptr - chip->period_ptr;
++ if (periods_elapsed < 0) {
++ printk(KERN_WARNING "PCSP: playback_ptr inconsistent "
++ "(%zi %zi %zi)\n",
++ chip->playback_ptr, period_bytes, buffer_bytes);
++ periods_elapsed += buffer_bytes;
++ }
++ periods_elapsed /= period_bytes;
++ /* wrap the pointer _before_ calling snd_pcm_period_elapsed(),
++ * or ALSA will BUG on us. */
++ chip->playback_ptr %= buffer_bytes;
++
++ snd_pcm_stream_unlock(substream);
++
++ if (periods_elapsed) {
++ snd_pcm_period_elapsed(substream);
++ chip->period_ptr += periods_elapsed * period_bytes;
++ chip->period_ptr %= buffer_bytes;
++ }
++
++ spin_unlock_irqrestore(&chip->substream_lock, flags);
++
++ if (!atomic_read(&chip->timer_active))
++ return HRTIMER_NORESTART;
++
++ chip->ns_rem = PCSP_PERIOD_NS();
++ ns = (chip->thalf ? PCSP_CALC_NS(timer_cnt) : chip->ns_rem);
++ chip->ns_rem -= ns;
++ hrtimer_forward(&chip->timer, chip->timer.expires, ktime_set(0, ns));
++ return HRTIMER_RESTART;
++
++exit_nr_unlock2:
++ snd_pcm_stream_unlock(substream);
++exit_nr_unlock1:
++ spin_unlock_irqrestore(&chip->substream_lock, flags);
++ return HRTIMER_NORESTART;
++}
++
++static void pcsp_start_playing(struct snd_pcsp *chip)
++{
++#if PCSP_DEBUG
++ printk(KERN_INFO "PCSP: start_playing called\n");
++#endif
++ if (atomic_read(&chip->timer_active)) {
++ printk(KERN_ERR "PCSP: Timer already active\n");
++ return;
++ }
++
++ spin_lock(&i8253_lock);
++ chip->val61 = inb(0x61) | 0x03;
++ outb_p(0x92, 0x43); /* binary, mode 1, LSB only, ch 2 */
++ spin_unlock(&i8253_lock);
++ atomic_set(&chip->timer_active, 1);
++ chip->thalf = 0;
++
++ tasklet_schedule(&pcsp_start_timer_tasklet);
++}
++
++static void pcsp_stop_playing(struct snd_pcsp *chip)
++{
++#if PCSP_DEBUG
++ printk(KERN_INFO "PCSP: stop_playing called\n");
++#endif
++ if (!atomic_read(&chip->timer_active))
++ return;
++
++ atomic_set(&chip->timer_active, 0);
++ spin_lock(&i8253_lock);
++ /* restore the timer */
++ outb_p(0xb6, 0x43); /* binary, mode 3, LSB/MSB, ch 2 */
++ outb(chip->val61 & 0xFC, 0x61);
++ spin_unlock(&i8253_lock);
++}
++
++static int snd_pcsp_playback_close(struct snd_pcm_substream *substream)
++{
++ struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
++#if PCSP_DEBUG
++ printk(KERN_INFO "PCSP: close called\n");
++#endif
++ if (atomic_read(&chip->timer_active)) {
++ printk(KERN_ERR "PCSP: timer still active\n");
++ pcsp_stop_playing(chip);
++ }
++ spin_lock_irq(&chip->substream_lock);
++ chip->playback_substream = NULL;
++ spin_unlock_irq(&chip->substream_lock);
++ return 0;
++}
++
++static int snd_pcsp_playback_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *hw_params)
++{
++ int err;
++ err = snd_pcm_lib_malloc_pages(substream,
++ params_buffer_bytes(hw_params));
++ if (err < 0)
++ return err;
++ return 0;
++}
++
++static int snd_pcsp_playback_hw_free(struct snd_pcm_substream *substream)
++{
++#if PCSP_DEBUG
++ printk(KERN_INFO "PCSP: hw_free called\n");
++#endif
++ return snd_pcm_lib_free_pages(substream);
++}
++
++static int snd_pcsp_playback_prepare(struct snd_pcm_substream *substream)
++{
++ struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
++#if PCSP_DEBUG
++ printk(KERN_INFO "PCSP: prepare called, "
++ "size=%zi psize=%zi f=%zi f1=%i\n",
++ snd_pcm_lib_buffer_bytes(substream),
++ snd_pcm_lib_period_bytes(substream),
++ snd_pcm_lib_buffer_bytes(substream) /
++ snd_pcm_lib_period_bytes(substream),
++ substream->runtime->periods);
++#endif
++ chip->playback_ptr = 0;
++ chip->period_ptr = 0;
++ return 0;
++}
++
++static int snd_pcsp_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++ struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
++#if PCSP_DEBUG
++ printk(KERN_INFO "PCSP: trigger called\n");
++#endif
++ switch (cmd) {
++ case SNDRV_PCM_TRIGGER_START:
++ case SNDRV_PCM_TRIGGER_RESUME:
++ pcsp_start_playing(chip);
++ break;
++ case SNDRV_PCM_TRIGGER_STOP:
++ case SNDRV_PCM_TRIGGER_SUSPEND:
++ pcsp_stop_playing(chip);
++ break;
++ default:
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static snd_pcm_uframes_t snd_pcsp_playback_pointer(struct snd_pcm_substream
++ *substream)
++{
++ struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
++ return bytes_to_frames(substream->runtime, chip->playback_ptr);
++}
++
++static struct snd_pcm_hardware snd_pcsp_playback = {
++ .info = (SNDRV_PCM_INFO_INTERLEAVED |
++ SNDRV_PCM_INFO_HALF_DUPLEX |
++ SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
++ .formats = SNDRV_PCM_FMTBIT_U8,
++ .rates = SNDRV_PCM_RATE_KNOT,
++ .rate_min = PCSP_DEFAULT_SRATE,
++ .rate_max = PCSP_DEFAULT_SRATE,
++ .channels_min = 1,
++ .channels_max = 1,
++ .buffer_bytes_max = PCSP_BUFFER_SIZE,
++ .period_bytes_min = 64,
++ .period_bytes_max = PCSP_MAX_PERIOD_SIZE,
++ .periods_min = 2,
++ .periods_max = PCSP_MAX_PERIODS,
++ .fifo_size = 0,
++};
++
++static int snd_pcsp_playback_open(struct snd_pcm_substream *substream)
++{
++ struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
++ struct snd_pcm_runtime *runtime = substream->runtime;
++#if PCSP_DEBUG
++ printk(KERN_INFO "PCSP: open called\n");
++#endif
++ if (atomic_read(&chip->timer_active)) {
++ printk(KERN_ERR "PCSP: still active!!\n");
++ return -EBUSY;
++ }
++ runtime->hw = snd_pcsp_playback;
++ spin_lock_irq(&chip->substream_lock);
++ chip->playback_substream = substream;
++ spin_unlock_irq(&chip->substream_lock);
++ return 0;
++}
++
++static struct snd_pcm_ops snd_pcsp_playback_ops = {
++ .open = snd_pcsp_playback_open,
++ .close = snd_pcsp_playback_close,
++ .ioctl = snd_pcm_lib_ioctl,
++ .hw_params = snd_pcsp_playback_hw_params,
++ .hw_free = snd_pcsp_playback_hw_free,
++ .prepare = snd_pcsp_playback_prepare,
++ .trigger = snd_pcsp_trigger,
++ .pointer = snd_pcsp_playback_pointer,
++};
++
++int __devinit snd_pcsp_new_pcm(struct snd_pcsp *chip)
++{
++ int err;
++
++ err = snd_pcm_new(chip->card, "pcspeaker", 0, 1, 0, &chip->pcm);
++ if (err < 0)
++ return err;
++
++ snd_pcm_set_ops(chip->pcm, SNDRV_PCM_STREAM_PLAYBACK,
++ &snd_pcsp_playback_ops);
++
++ chip->pcm->private_data = chip;
++ chip->pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
++ strcpy(chip->pcm->name, "pcsp");
++
++ snd_pcm_lib_preallocate_pages_for_all(chip->pcm,
++ SNDRV_DMA_TYPE_CONTINUOUS,
++ snd_dma_continuous_data
++ (GFP_KERNEL), PCSP_BUFFER_SIZE,
++ PCSP_BUFFER_SIZE);
++
++ return 0;
++}
+diff --git a/sound/drivers/pcsp/pcsp_mixer.c b/sound/drivers/pcsp/pcsp_mixer.c
+new file mode 100644
+index 0000000..64a695f
+--- /dev/null
++++ b/sound/drivers/pcsp/pcsp_mixer.c
+@@ -0,0 +1,143 @@
++/*
++ * PC-Speaker driver for Linux
++ *
++ * Mixer implementation.
++ * Copyright (C) 2001-2008 Stas Sergeev
++ */
++
++#include <sound/core.h>
++#include <sound/control.h>
++#include "pcsp.h"
++
++
++static int pcsp_enable_info(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
++ uinfo->count = 1;
++ uinfo->value.integer.min = 0;
++ uinfo->value.integer.max = 1;
++ return 0;
++}
++
++static int pcsp_enable_get(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
++ ucontrol->value.integer.value[0] = chip->enable;
++ return 0;
++}
++
++static int pcsp_enable_put(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
++ int changed = 0;
++ int enab = ucontrol->value.integer.value[0];
++ if (enab != chip->enable) {
++ chip->enable = enab;
++ changed = 1;
++ }
++ return changed;
++}
++
++static int pcsp_treble_info(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++ struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
++ uinfo->count = 1;
++ uinfo->value.enumerated.items = chip->max_treble + 1;
++ if (uinfo->value.enumerated.item > chip->max_treble)
++ uinfo->value.enumerated.item = chip->max_treble;
++ sprintf(uinfo->value.enumerated.name, "%d", PCSP_RATE());
++ return 0;
++}
++
++static int pcsp_treble_get(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
++ ucontrol->value.enumerated.item[0] = chip->treble;
++ return 0;
++}
++
++static int pcsp_treble_put(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
++ int changed = 0;
++ int treble = ucontrol->value.enumerated.item[0];
++ if (treble != chip->treble) {
++ chip->treble = treble;
++#if PCSP_DEBUG
++ printk(KERN_INFO "PCSP: rate set to %i\n", PCSP_RATE());
++#endif
++ changed = 1;
++ }
++ return changed;
++}
++
++static int pcsp_pcspkr_info(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
++ uinfo->count = 1;
++ uinfo->value.integer.min = 0;
++ uinfo->value.integer.max = 1;
++ return 0;
++}
++
++static int pcsp_pcspkr_get(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
++ ucontrol->value.integer.value[0] = chip->pcspkr;
++ return 0;
++}
++
++static int pcsp_pcspkr_put(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol);
++ int changed = 0;
++ int spkr = ucontrol->value.integer.value[0];
++ if (spkr != chip->pcspkr) {
++ chip->pcspkr = spkr;
++ changed = 1;
++ }
++ return changed;
++}
++
++#define PCSP_MIXER_CONTROL(ctl_type, ctl_name) \
++{ \
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
++ .name = ctl_name, \
++ .info = pcsp_##ctl_type##_info, \
++ .get = pcsp_##ctl_type##_get, \
++ .put = pcsp_##ctl_type##_put, \
++}
++
++static struct snd_kcontrol_new __devinitdata snd_pcsp_controls[] = {
++ PCSP_MIXER_CONTROL(enable, "Master Playback Switch"),
++ PCSP_MIXER_CONTROL(treble, "BaseFRQ Playback Volume"),
++ PCSP_MIXER_CONTROL(pcspkr, "PC Speaker Playback Switch"),
++};
++
++int __devinit snd_pcsp_new_mixer(struct snd_pcsp *chip)
++{
++ struct snd_card *card = chip->card;
++ int i, err;
++
++ for (i = 0; i < ARRAY_SIZE(snd_pcsp_controls); i++) {
++ err = snd_ctl_add(card,
++ snd_ctl_new1(snd_pcsp_controls + i,
++ chip));
++ if (err < 0)
++ return err;
++ }
++
++ strcpy(card->mixername, "PC-Speaker");
++
++ return 0;
++}
+diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
+index 15061bd..d20d893 100644
+--- a/sound/i2c/other/ak4114.c
++++ b/sound/i2c/other/ak4114.c
+@@ -27,6 +27,7 @@
+ #include <sound/pcm.h>
+ #include <sound/ak4114.h>
+ #include <sound/asoundef.h>
++#include <sound/info.h>
+
+ MODULE_AUTHOR("Jaroslav Kysela <perex at perex.cz>");
+ MODULE_DESCRIPTION("AK4114 IEC958 (S/PDIF) receiver by Asahi Kasei");
+@@ -446,6 +447,26 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = {
+ }
+ };
+
++
++static void snd_ak4114_proc_regs_read(struct snd_info_entry *entry,
++ struct snd_info_buffer *buffer)
++{
++ struct ak4114 *ak4114 = entry->private_data;
++ int reg, val;
++ /* all ak4114 registers 0x00 - 0x1f */
++ for (reg = 0; reg < 0x20; reg++) {
++ val = reg_read(ak4114, reg);
++ snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val);
++ }
++}
++
++static void snd_ak4114_proc_init(struct ak4114 *ak4114)
++{
++ struct snd_info_entry *entry;
++ if (!snd_card_proc_new(ak4114->card, "ak4114", &entry))
++ snd_info_set_text_ops(entry, ak4114, snd_ak4114_proc_regs_read);
++}
++
+ int snd_ak4114_build(struct ak4114 *ak4114,
+ struct snd_pcm_substream *ply_substream,
+ struct snd_pcm_substream *cap_substream)
+@@ -478,6 +499,7 @@ int snd_ak4114_build(struct ak4114 *ak4114,
+ return err;
+ ak4114->kctls[idx] = kctl;
+ }
++ snd_ak4114_proc_init(ak4114);
+ /* trigger workq */
+ schedule_delayed_work(&ak4114->work, HZ / 10);
+ return 0;
+@@ -590,7 +612,7 @@ static void ak4114_stats(struct work_struct *work)
+ struct ak4114 *chip = container_of(work, struct ak4114, work.work);
+
+ if (!chip->init)
+- snd_ak4114_check_rate_and_errors(chip, 0);
++ snd_ak4114_check_rate_and_errors(chip, chip->check_flags);
+
+ schedule_delayed_work(&chip->work, HZ / 10);
+ }
+diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
+index 35fbbf2..288926d 100644
+--- a/sound/i2c/other/ak4xxx-adda.c
++++ b/sound/i2c/other/ak4xxx-adda.c
+@@ -70,7 +70,8 @@ static void ak4524_reset(struct snd_akm4xxx *ak, int state)
+ }
+
+ /* reset procedure for AK4355 and AK4358 */
+-static void ak4355_reset(struct snd_akm4xxx *ak, int state)
++static void ak435X_reset(struct snd_akm4xxx *ak, int state,
++ unsigned char total_regs)
+ {
+ unsigned char reg;
+
+@@ -78,7 +79,7 @@ static void ak4355_reset(struct snd_akm4xxx *ak, int state)
+ snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */
+ return;
+ }
+- for (reg = 0x00; reg < 0x0b; reg++)
++ for (reg = 0x00; reg < total_regs; reg++)
+ if (reg != 0x01)
+ snd_akm4xxx_write(ak, 0, reg,
+ snd_akm4xxx_get(ak, 0, reg));
+@@ -118,8 +119,10 @@ void snd_akm4xxx_reset(struct snd_akm4xxx *ak, int state)
+ /* FIXME: needed for ak4529? */
+ break;
+ case SND_AK4355:
++ ak435X_reset(ak, state, 0x0b);
++ break;
+ case SND_AK4358:
+- ak4355_reset(ak, state);
++ ak435X_reset(ak, state, 0x10);
+ break;
+ case SND_AK4381:
+ ak4381_reset(ak, state);
+@@ -292,11 +295,6 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak)
+ case SND_AK5365:
+ /* FIXME: any init sequence? */
+ return;
+- case NON_AKM:
+- /* fake value for non-akm codecs using akm infrastructure
+- * (e.g. of ice1724) - certainly FIXME
+- */
+- return;
+ default:
+ snd_BUG();
+ return;
+@@ -374,6 +372,8 @@ static int put_ak_reg(struct snd_kcontrol *kcontrol, int addr,
+ nval = mask - nval;
+ if (AK_GET_NEEDSMSB(kcontrol->private_value))
+ nval |= 0x80;
++ /* printk(KERN_DEBUG "DEBUG - AK writing reg: chip %x addr %x,
++ nval %x\n", chip, addr, nval); */
+ snd_akm4xxx_write(ak, chip, addr, nval);
+ return 1;
+ }
+diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
+index bed29ca..f3fd7b4 100644
+--- a/sound/isa/sb/sb16_csp.c
++++ b/sound/isa/sb/sb16_csp.c
+@@ -331,7 +331,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
+ return -EFAULT;
+ if ((file_h.name != RIFF_HEADER) ||
+ (le32_to_cpu(file_h.len) >= SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE - sizeof(file_h))) {
+- snd_printd("%s: Invalid RIFF header\n", __FUNCTION__);
++ snd_printd("%s: Invalid RIFF header\n", __func__);
+ return -EINVAL;
+ }
+ data_ptr += sizeof(file_h);
+@@ -340,7 +340,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
+ if (copy_from_user(&item_type, data_ptr, sizeof(item_type)))
+ return -EFAULT;
+ if (item_type != CSP__HEADER) {
+- snd_printd("%s: Invalid RIFF file type\n", __FUNCTION__);
++ snd_printd("%s: Invalid RIFF file type\n", __func__);
+ return -EINVAL;
+ }
+ data_ptr += sizeof (item_type);
+@@ -395,7 +395,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
+ return -EFAULT;
+
+ if (code_h.name != MAIN_HEADER) {
+- snd_printd("%s: Missing 'main' microcode\n", __FUNCTION__);
++ snd_printd("%s: Missing 'main' microcode\n", __func__);
+ return -EINVAL;
+ }
+ data_ptr += sizeof(code_h);
+@@ -439,7 +439,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
+ p->acc_format = p->acc_width = p->acc_rates = 0;
+ p->mode = 0;
+ snd_printd("%s: Unsupported CSP codec type: 0x%04x\n",
+- __FUNCTION__,
++ __func__,
+ le16_to_cpu(funcdesc_h.VOC_type));
+ return -EINVAL;
+ }
+@@ -458,7 +458,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
+ return 0;
+ }
+ }
+- snd_printd("%s: Function #%d not found\n", __FUNCTION__, info.func_req);
++ snd_printd("%s: Function #%d not found\n", __func__, info.func_req);
+ return -EINVAL;
+ }
+
+@@ -612,7 +612,7 @@ static int get_version(struct snd_sb *chip)
+ static int snd_sb_csp_check_version(struct snd_sb_csp * p)
+ {
+ if (p->version < 0x10 || p->version > 0x1f) {
+- snd_printd("%s: Invalid CSP version: 0x%x\n", __FUNCTION__, p->version);
++ snd_printd("%s: Invalid CSP version: 0x%x\n", __func__, p->version);
+ return 1;
+ }
+ return 0;
+@@ -631,7 +631,7 @@ static int snd_sb_csp_load(struct snd_sb_csp * p, const unsigned char *buf, int
+ spin_lock_irqsave(&p->chip->reg_lock, flags);
+ snd_sbdsp_command(p->chip, 0x01); /* CSP download command */
+ if (snd_sbdsp_get_byte(p->chip)) {
+- snd_printd("%s: Download command failed\n", __FUNCTION__);
++ snd_printd("%s: Download command failed\n", __func__);
+ goto __fail;
+ }
+ /* Send CSP low byte (size - 1) */
+@@ -658,7 +658,7 @@ static int snd_sb_csp_load(struct snd_sb_csp * p, const unsigned char *buf, int
+ udelay (10);
+ }
+ if (status != 0x55) {
+- snd_printd("%s: Microcode initialization failed\n", __FUNCTION__);
++ snd_printd("%s: Microcode initialization failed\n", __func__);
+ goto __fail;
+ }
+ } else {
+@@ -824,19 +824,19 @@ static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channel
+ unsigned long flags;
+
+ if (!(p->running & (SNDRV_SB_CSP_ST_LOADED | SNDRV_SB_CSP_ST_AUTO))) {
+- snd_printd("%s: Microcode not loaded\n", __FUNCTION__);
++ snd_printd("%s: Microcode not loaded\n", __func__);
+ return -ENXIO;
+ }
+ if (p->running & SNDRV_SB_CSP_ST_RUNNING) {
+- snd_printd("%s: CSP already running\n", __FUNCTION__);
++ snd_printd("%s: CSP already running\n", __func__);
+ return -EBUSY;
+ }
+ if (!(sample_width & p->acc_width)) {
+- snd_printd("%s: Unsupported PCM sample width\n", __FUNCTION__);
++ snd_printd("%s: Unsupported PCM sample width\n", __func__);
+ return -EINVAL;
+ }
+ if (!(channels & p->acc_channels)) {
+- snd_printd("%s: Invalid number of channels\n", __FUNCTION__);
++ snd_printd("%s: Invalid number of channels\n", __func__);
+ return -EINVAL;
+ }
+
+@@ -858,11 +858,11 @@ static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channel
+ s_type |= 0x22; /* 00dX 00dX (d = 1 if 8 bit samples) */
+
+ if (set_codec_parameter(p->chip, 0x81, s_type)) {
+- snd_printd("%s: Set sample type command failed\n", __FUNCTION__);
++ snd_printd("%s: Set sample type command failed\n", __func__);
+ goto __fail;
+ }
+ if (set_codec_parameter(p->chip, 0x80, 0x00)) {
+- snd_printd("%s: Codec start command failed\n", __FUNCTION__);
++ snd_printd("%s: Codec start command failed\n", __func__);
+ goto __fail;
+ }
+ p->run_width = sample_width;
+diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c
+index d63c1af..b432d9a 100644
+--- a/sound/isa/sb/sb_common.c
++++ b/sound/isa/sb/sb_common.c
+@@ -51,7 +51,7 @@ int snd_sbdsp_command(struct snd_sb *chip, unsigned char val)
+ outb(val, SBP(chip, COMMAND));
+ return 1;
+ }
+- snd_printd("%s [0x%lx]: timeout (0x%x)\n", __FUNCTION__, chip->port, val);
++ snd_printd("%s [0x%lx]: timeout (0x%x)\n", __func__, chip->port, val);
+ return 0;
+ }
+
+@@ -68,7 +68,7 @@ int snd_sbdsp_get_byte(struct snd_sb *chip)
+ return val;
+ }
+ }
+- snd_printd("%s [0x%lx]: timeout\n", __FUNCTION__, chip->port);
++ snd_printd("%s [0x%lx]: timeout\n", __func__, chip->port);
+ return -ENODEV;
+ }
+
+@@ -87,7 +87,7 @@ int snd_sbdsp_reset(struct snd_sb *chip)
+ else
+ break;
+ }
+- snd_printdd("%s [0x%lx] failed...\n", __FUNCTION__, chip->port);
++ snd_printdd("%s [0x%lx] failed...\n", __func__, chip->port);
+ return -ENODEV;
+ }
+
+diff --git a/sound/oss/dmabuf.c b/sound/oss/dmabuf.c
+index eaf6997..1e90d76 100644
+--- a/sound/oss/dmabuf.c
++++ b/sound/oss/dmabuf.c
+@@ -795,9 +795,9 @@ static int find_output_space(int dev, char **buf, int *size)
+ #ifdef BE_CONSERVATIVE
+ active_offs = dmap->byte_counter + dmap->qhead * dmap->fragment_size;
+ #else
+- active_offs = DMAbuf_get_buffer_pointer(dev, dmap, DMODE_OUTPUT);
++ active_offs = max(DMAbuf_get_buffer_pointer(dev, dmap, DMODE_OUTPUT), 0);
+ /* Check for pointer wrapping situation */
+- if (active_offs < 0 || active_offs >= dmap->bytes_in_use)
++ if (active_offs >= dmap->bytes_in_use)
+ active_offs = 0;
+ active_offs += dmap->byte_counter;
+ #endif
+diff --git a/sound/oss/trident.c b/sound/oss/trident.c
+index d6af906..f43f91e 100644
+--- a/sound/oss/trident.c
++++ b/sound/oss/trident.c
+@@ -3076,8 +3076,7 @@ ali_ac97_get(struct trident_card *card, int secondary, u8 reg)
+ u16 wcontrol;
+ unsigned long flags;
+
+- if (!card)
+- BUG();
++ BUG_ON(!card);
+
+ address = ALI_AC97_READ;
+ if (card->revision == ALI_5451_V02) {
+@@ -3148,8 +3147,7 @@ ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val)
+
+ data = ((u32) val) << 16;
+
+- if (!card)
+- BUG();
++ BUG_ON(!card);
+
+ address = ALI_AC97_WRITE;
+ mask = ALI_AC97_WRITE_ACTION | ALI_AC97_AUDIO_BUSY;
+@@ -3213,8 +3211,7 @@ ali_ac97_read(struct ac97_codec *codec, u8 reg)
+ struct trident_card *card = NULL;
+
+ /* Added by Matt Wu */
+- if (!codec)
+- BUG();
++ BUG_ON(!codec);
+
+ card = (struct trident_card *) codec->private_data;
+
+@@ -3240,8 +3237,7 @@ ali_ac97_write(struct ac97_codec *codec, u8 reg, u16 val)
+ struct trident_card *card;
+
+ /* Added by Matt Wu */
+- if (!codec)
+- BUG();
++ BUG_ON(!codec);
+
+ card = (struct trident_card *) codec->private_data;
+
+diff --git a/sound/oss/trident.h b/sound/oss/trident.h
+index 4713b49..ff30a1d 100644
+--- a/sound/oss/trident.h
++++ b/sound/oss/trident.h
+@@ -322,7 +322,7 @@ enum miscint_bits {
+ #define VALIDATE_MAGIC(FOO,MAG) \
+ ({ \
+ if (!(FOO) || (FOO)->magic != MAG) { \
+- printk(invalid_magic,__FUNCTION__); \
++ printk(invalid_magic,__func__); \
+ return -ENXIO; \
+ } \
+ })
+diff --git a/sound/oss/vwsnd.c b/sound/oss/vwsnd.c
+index d25249a..2c5aaa5 100644
+--- a/sound/oss/vwsnd.c
++++ b/sound/oss/vwsnd.c
+@@ -194,11 +194,11 @@ static void dbgassert(const char *fcn, int line, const char *expr)
+ * DBGRV - debug print function return when verbose
+ */
+
+-#define ASSERT(e) ((e) ? (void) 0 : dbgassert(__FUNCTION__, __LINE__, #e))
++#define ASSERT(e) ((e) ? (void) 0 : dbgassert(__func__, __LINE__, #e))
+ #define DBGDO(x) x
+ #define DBGX(fmt, args...) (in_interrupt() ? 0 : printk(KERN_ERR fmt, ##args))
+-#define DBGP(fmt, args...) (DBGX("%s: " fmt, __FUNCTION__ , ##args))
+-#define DBGE(fmt, args...) (DBGX("%s" fmt, __FUNCTION__ , ##args))
++#define DBGP(fmt, args...) (DBGX("%s: " fmt, __func__ , ##args))
++#define DBGE(fmt, args...) (DBGX("%s" fmt, __func__ , ##args))
+ #define DBGC(rtn) (DBGP("calling %s\n", rtn))
+ #define DBGR() (DBGP("returning\n"))
+ #define DBGXV(fmt, args...) (shut_up ? 0 : DBGX(fmt, ##args))
+diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
+index 812085d..581debf 100644
+--- a/sound/pci/Kconfig
++++ b/sound/pci/Kconfig
+@@ -122,6 +122,21 @@ config SND_AU8830
+ To compile this driver as a module, choose M here: the module
+ will be called snd-au8830.
+
++config SND_AW2
++ tristate "Emagic Audiowerk 2"
++ depends on SND
++ help
++ Say Y here to include support for Emagic Audiowerk 2 soundcards.
++
++ Supported features: Analog and SPDIF output. Analog or SPDIF input.
++ Note: Switch between analog and digital input does not always work.
++ It can produce continuous noise. The workaround is to switch again
++ (and again) between digital and analog input until it works.
++
++ To compile this driver as a module, choose M here: the module
++ will be called snd-aw2.
++
++
+ config SND_AZT3328
+ tristate "Aztech AZF3328 / PCI168 (EXPERIMENTAL)"
+ depends on SND && EXPERIMENTAL
+@@ -162,6 +177,7 @@ config SND_CA0106
+ depends on SND
+ select SND_AC97_CODEC
+ select SND_RAWMIDI
++ select SND_VMASTER
+ help
+ Say Y here to include support for the Sound Blaster Audigy LS
+ and Live 24bit.
+@@ -517,6 +533,7 @@ config SND_HDA_INTEL
+ tristate "Intel HD Audio"
+ depends on SND
+ select SND_PCM
++ select SND_VMASTER
+ help
+ Say Y here to include support for Intel "High Definition
+ Audio" (Azalia) motherboard devices.
+@@ -680,6 +697,7 @@ config SND_ICE1724
+ depends on SND
+ select SND_MPU401_UART
+ select SND_AC97_CODEC
++ select SND_VMASTER
+ help
+ Say Y here to include support for soundcards based on
+ ICE/VT1724/1720 (Envy24HT/PT) chips.
+@@ -896,12 +914,12 @@ config SND_VIA82XX_MODEM
+ will be called snd-via82xx-modem.
+
+ config SND_VIRTUOSO
+- tristate "Asus Virtuoso 200 (Xonar)"
++ tristate "Asus Virtuoso 100/200 (Xonar)"
+ depends on SND
+ select SND_OXYGEN_LIB
+ help
+ Say Y here to include support for sound cards based on the
+- Asus AV200 chip, i.e., Xonar D2 and Xonar D2X.
++ Asus AV100/AV200 chips, i.e., Xonar D2, DX and D2X.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-virtuoso.
+diff --git a/sound/pci/Makefile b/sound/pci/Makefile
+index 2d42fd2..85ef14b 100644
+--- a/sound/pci/Makefile
++++ b/sound/pci/Makefile
+@@ -58,6 +58,7 @@ obj-$(CONFIG_SND) += \
+ ac97/ \
+ ali5451/ \
+ au88x0/ \
++ aw2/ \
+ ca0106/ \
+ cs46xx/ \
+ cs5535audio/ \
+diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
+index 50c637e..39198e5 100644
+--- a/sound/pci/ac97/ac97_patch.c
++++ b/sound/pci/ac97/ac97_patch.c
+@@ -114,10 +114,9 @@ static int ac97_surround_jack_mode_put(struct snd_kcontrol *kcontrol, struct snd
+
+ static int ac97_channel_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+ {
+- static const char *texts[] = { "2ch", "4ch", "6ch" };
+- if (kcontrol->private_value)
+- return ac97_enum_text_info(kcontrol, uinfo, texts, 2); /* 4ch only */
+- return ac97_enum_text_info(kcontrol, uinfo, texts, 3);
++ static const char *texts[] = { "2ch", "4ch", "6ch", "8ch" };
++ return ac97_enum_text_info(kcontrol, uinfo, texts,
++ kcontrol->private_value);
+ }
+
+ static int ac97_channel_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+@@ -133,13 +132,8 @@ static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
+ unsigned char mode = ucontrol->value.enumerated.item[0];
+
+- if (kcontrol->private_value) {
+- if (mode >= 2)
+- return -EINVAL;
+- } else {
+- if (mode >= 3)
+- return -EINVAL;
+- }
++ if (mode >= kcontrol->private_value)
++ return -EINVAL;
+
+ if (mode != ac97->channel_mode) {
+ ac97->channel_mode = mode;
+@@ -158,6 +152,7 @@ static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
+ .get = ac97_surround_jack_mode_get, \
+ .put = ac97_surround_jack_mode_put, \
+ }
++/* 6ch */
+ #define AC97_CHANNEL_MODE_CTL \
+ { \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+@@ -165,7 +160,9 @@ static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
+ .info = ac97_channel_mode_info, \
+ .get = ac97_channel_mode_get, \
+ .put = ac97_channel_mode_put, \
++ .private_value = 3, \
+ }
++/* 4ch */
+ #define AC97_CHANNEL_MODE_4CH_CTL \
+ { \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+@@ -173,7 +170,17 @@ static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
+ .info = ac97_channel_mode_info, \
+ .get = ac97_channel_mode_get, \
+ .put = ac97_channel_mode_put, \
+- .private_value = 1, \
++ .private_value = 2, \
++ }
++/* 8ch */
++#define AC97_CHANNEL_MODE_8CH_CTL \
++ { \
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
++ .name = "Channel Mode", \
++ .info = ac97_channel_mode_info, \
++ .get = ac97_channel_mode_get, \
++ .put = ac97_channel_mode_put, \
++ .private_value = 4, \
+ }
+
+ static inline int is_surround_on(struct snd_ac97 *ac97)
+@@ -210,6 +217,10 @@ static inline int is_shared_micin(struct snd_ac97 *ac97)
+ return !ac97->indep_surround && !is_clfe_on(ac97);
+ }
+
++static inline int alc850_is_aux_back_surround(struct snd_ac97 *ac97)
++{
++ return is_surround_on(ac97);
++}
+
+ /* The following snd_ac97_ymf753_... items added by David Shust (dshust at shustring.com) */
+ /* Modified for YMF743 by Keita Maehara <maehara at debian.org> */
+@@ -2816,10 +2827,12 @@ static int patch_alc655(struct snd_ac97 * ac97)
+
+ #define AC97_ALC850_JACK_SELECT 0x76
+ #define AC97_ALC850_MISC1 0x7a
++#define AC97_ALC850_MULTICH 0x6a
+
+ static void alc850_update_jacks(struct snd_ac97 *ac97)
+ {
+ int shared;
++ int aux_is_back_surround;
+
+ /* shared Line-In / Surround Out */
+ shared = is_shared_surrout(ac97);
+@@ -2837,13 +2850,18 @@ static void alc850_update_jacks(struct snd_ac97 *ac97)
+ /* MIC-IN = 1, CENTER-LFE = 5 */
+ snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4,
+ shared ? (5<<4) : (1<<4));
++
++ aux_is_back_surround = alc850_is_aux_back_surround(ac97);
++ /* Aux is Back Surround */
++ snd_ac97_update_bits(ac97, AC97_ALC850_MULTICH, 1 << 10,
++ aux_is_back_surround ? (1<<10) : (0<<10));
+ }
+
+ static const struct snd_kcontrol_new snd_ac97_controls_alc850[] = {
+ AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
+ AC97_SINGLE("Mic Front Input Switch", AC97_ALC850_JACK_SELECT, 15, 1, 1),
+ AC97_SURROUND_JACK_MODE_CTL,
+- AC97_CHANNEL_MODE_CTL,
++ AC97_CHANNEL_MODE_8CH_CTL,
+ };
+
+ static int patch_alc850_specific(struct snd_ac97 *ac97)
+@@ -2869,6 +2887,7 @@ static int patch_alc850(struct snd_ac97 *ac97)
+ ac97->build_ops = &patch_alc850_ops;
+
+ ac97->spec.dev_flags = 0; /* for IEC958 playback route - ALC655 compatible */
++ ac97->flags |= AC97_HAS_8CH;
+
+ /* assume only page 0 for writing cache */
+ snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
+@@ -2878,6 +2897,7 @@ static int patch_alc850(struct snd_ac97 *ac97)
+ spdif-in monitor off, spdif-in PCM off
+ center on mic off, surround on line-in off
+ duplicate front off
++ NB default bit 10=0 = Aux is Capture, not Back Surround
+ */
+ snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15);
+ /* SURR_OUT: on, Surr 1kOhm: on, Surr Amp: off, Front 1kOhm: off
+diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c
+index 3674f35..48cbda9 100644
+--- a/sound/pci/ac97/ac97_pcm.c
++++ b/sound/pci/ac97/ac97_pcm.c
+@@ -574,7 +574,6 @@ int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate,
+ r = rate > 48000;
+ bus = pcm->bus;
+ if (cfg == AC97_PCM_CFG_SPDIF) {
+- int err;
+ for (cidx = 0; cidx < 4; cidx++)
+ if (bus->codec[cidx] && (bus->codec[cidx]->ext_id & AC97_EI_SPDIF)) {
+ err = set_spdif_rate(bus->codec[cidx], rate);
+diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
+index a66d515..39ec55b 100644
+--- a/sound/pci/ad1889.c
++++ b/sound/pci/ad1889.c
+@@ -264,10 +264,10 @@ snd_ad1889_ac97_ready(struct snd_ad1889 *chip)
+ mdelay(1);
+ if (!retry) {
+ snd_printk(KERN_ERR PFX "[%s] Link is not ready.\n",
+- __FUNCTION__);
++ __func__);
+ return -EIO;
+ }
+- ad1889_debug("[%s] ready after %d ms\n", __FUNCTION__, 400 - retry);
++ ad1889_debug("[%s] ready after %d ms\n", __func__, 400 - retry);
+
+ return 0;
+ }
+@@ -854,8 +854,6 @@ snd_ad1889_free(struct snd_ad1889 *chip)
+
+ spin_unlock_irq(&chip->lock);
+
+- synchronize_irq(chip->irq);
+-
+ if (chip->irq >= 0)
+ free_irq(chip->irq, chip);
+
+diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
+index 6a905ed..1a0fd65 100644
+--- a/sound/pci/ali5451/ali5451.c
++++ b/sound/pci/ali5451/ali5451.c
+@@ -1809,26 +1809,26 @@ static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+ {
+ struct snd_ali *codec = kcontrol->private_data;
+- unsigned int enable;
++ unsigned int spdif_enable;
+
+- enable = ucontrol->value.integer.value[0] ? 1 : 0;
++ spdif_enable = ucontrol->value.integer.value[0] ? 1 : 0;
+
+ spin_lock_irq(&codec->reg_lock);
+ switch (kcontrol->private_value) {
+ case 0:
+- enable = (codec->spdif_mask & 0x02) ? 1 : 0;
++ spdif_enable = (codec->spdif_mask & 0x02) ? 1 : 0;
+ break;
+ case 1:
+- enable = ((codec->spdif_mask & 0x02) &&
++ spdif_enable = ((codec->spdif_mask & 0x02) &&
+ (codec->spdif_mask & 0x04)) ? 1 : 0;
+ break;
+ case 2:
+- enable = (codec->spdif_mask & 0x01) ? 1 : 0;
++ spdif_enable = (codec->spdif_mask & 0x01) ? 1 : 0;
+ break;
+ default:
+ break;
+ }
+- ucontrol->value.integer.value[0] = enable;
++ ucontrol->value.integer.value[0] = spdif_enable;
+ spin_unlock_irq(&codec->reg_lock);
+ return 0;
+ }
+@@ -1837,17 +1837,17 @@ static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+ {
+ struct snd_ali *codec = kcontrol->private_data;
+- unsigned int change = 0, enable = 0;
++ unsigned int change = 0, spdif_enable = 0;
+
+- enable = ucontrol->value.integer.value[0] ? 1 : 0;
++ spdif_enable = ucontrol->value.integer.value[0] ? 1 : 0;
+
+ spin_lock_irq(&codec->reg_lock);
+ switch (kcontrol->private_value) {
+ case 0:
+ change = (codec->spdif_mask & 0x02) ? 1 : 0;
+- change = change ^ enable;
++ change = change ^ spdif_enable;
+ if (change) {
+- if (enable) {
++ if (spdif_enable) {
+ codec->spdif_mask |= 0x02;
+ snd_ali_enable_spdif_out(codec);
+ } else {
+@@ -1859,9 +1859,9 @@ static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol,
+ break;
+ case 1:
+ change = (codec->spdif_mask & 0x04) ? 1 : 0;
+- change = change ^ enable;
++ change = change ^ spdif_enable;
+ if (change && (codec->spdif_mask & 0x02)) {
+- if (enable) {
++ if (spdif_enable) {
+ codec->spdif_mask |= 0x04;
+ snd_ali_enable_spdif_chnout(codec);
+ } else {
+@@ -1872,9 +1872,9 @@ static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol,
+ break;
+ case 2:
+ change = (codec->spdif_mask & 0x01) ? 1 : 0;
+- change = change ^ enable;
++ change = change ^ spdif_enable;
+ if (change) {
+- if (enable) {
++ if (spdif_enable) {
+ codec->spdif_mask |= 0x01;
+ snd_ali_enable_spdif_in(codec);
+ } else {
+@@ -2047,10 +2047,8 @@ static int snd_ali_free(struct snd_ali * codec)
+ {
+ if (codec->hw_initialized)
+ snd_ali_disable_address_interrupt(codec);
+- if (codec->irq >= 0) {
+- synchronize_irq(codec->irq);
++ if (codec->irq >= 0)
+ free_irq(codec->irq, codec);
+- }
+ if (codec->port)
+ pci_release_regions(codec->pci);
+ pci_disable_device(codec->pci);
+diff --git a/sound/pci/als300.c b/sound/pci/als300.c
+index 0e990a7..8df6824 100644
+--- a/sound/pci/als300.c
++++ b/sound/pci/als300.c
+@@ -92,8 +92,8 @@
+
+ #if DEBUG_CALLS
+ #define snd_als300_dbgcalls(format, args...) printk(format, ##args)
+-#define snd_als300_dbgcallenter() printk(KERN_ERR "--> %s\n", __FUNCTION__)
+-#define snd_als300_dbgcallleave() printk(KERN_ERR "<-- %s\n", __FUNCTION__)
++#define snd_als300_dbgcallenter() printk(KERN_ERR "--> %s\n", __func__)
++#define snd_als300_dbgcallleave() printk(KERN_ERR "<-- %s\n", __func__)
+ #else
+ #define snd_als300_dbgcalls(format, args...)
+ #define snd_als300_dbgcallenter()
+diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
+index 4594186..457228f 100644
+--- a/sound/pci/atiixp.c
++++ b/sound/pci/atiixp.c
+@@ -1553,7 +1553,7 @@ static int snd_atiixp_free(struct atiixp *chip)
+ if (chip->irq < 0)
+ goto __hw_end;
+ snd_atiixp_chip_stop(chip);
+- synchronize_irq(chip->irq);
++
+ __hw_end:
+ if (chip->irq >= 0)
+ free_irq(chip->irq, chip);
+diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
+index a67a869..d457a32 100644
+--- a/sound/pci/atiixp_modem.c
++++ b/sound/pci/atiixp_modem.c
+@@ -1197,7 +1197,7 @@ static int snd_atiixp_free(struct atiixp_modem *chip)
+ if (chip->irq < 0)
+ goto __hw_end;
+ snd_atiixp_chip_stop(chip);
+- synchronize_irq(chip->irq);
++
+ __hw_end:
+ if (chip->irq >= 0)
+ free_irq(chip->irq, chip);
+diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
+index 26819e2..68368e4 100644
+--- a/sound/pci/au88x0/au88x0.c
++++ b/sound/pci/au88x0/au88x0.c
+@@ -126,7 +126,6 @@ static int snd_vortex_dev_free(struct snd_device *device)
+ vortex_gameport_unregister(vortex);
+ vortex_core_shutdown(vortex);
+ // Take down PCI interface.
+- synchronize_irq(vortex->irq);
+ free_irq(vortex->irq, vortex);
+ iounmap(vortex->mmio);
+ pci_release_regions(vortex->pci_dev);
+@@ -220,7 +219,6 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
+ return 0;
+
+ alloc_out:
+- synchronize_irq(chip->irq);
+ free_irq(chip->irq, chip);
+ irq_out:
+ vortex_core_shutdown(chip);
+diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c
+index 526c6c5..f9a58b4 100644
+--- a/sound/pci/au88x0/au88x0_pcm.c
++++ b/sound/pci/au88x0/au88x0_pcm.c
+@@ -498,14 +498,14 @@ static struct snd_kcontrol_new snd_vortex_mixer_spdif[] __devinitdata = {
+ };
+
+ /* create a pcm device */
+-static int __devinit snd_vortex_new_pcm(vortex_t * chip, int idx, int nr)
++static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
+ {
+ struct snd_pcm *pcm;
+ struct snd_kcontrol *kctl;
+ int i;
+ int err, nr_capt;
+
+- if ((chip == 0) || (idx < 0) || (idx >= VORTEX_PCM_LAST))
++ if (!chip || idx < 0 || idx >= VORTEX_PCM_LAST)
+ return -ENODEV;
+
+ /* idx indicates which kind of PCM device. ADB, SPDIF, I2S and A3D share the
+@@ -514,9 +514,9 @@ static int __devinit snd_vortex_new_pcm(vortex_t * chip, int idx, int nr)
+ nr_capt = nr;
+ else
+ nr_capt = 0;
+- if ((err =
+- snd_pcm_new(chip->card, vortex_pcm_prettyname[idx], idx, nr,
+- nr_capt, &pcm)) < 0)
++ err = snd_pcm_new(chip->card, vortex_pcm_prettyname[idx], idx, nr,
++ nr_capt, &pcm);
++ if (err < 0)
+ return err;
+ strcpy(pcm->name, vortex_pcm_name[idx]);
+ chip->pcm[idx] = pcm;
+diff --git a/sound/pci/aw2/Makefile b/sound/pci/aw2/Makefile
+new file mode 100644
+index 0000000..842335d
+--- /dev/null
++++ b/sound/pci/aw2/Makefile
+@@ -0,0 +1,3 @@
++snd-aw2-objs := aw2-alsa.o aw2-saa7146.o
++
++obj-$(CONFIG_SND_AW2) += snd-aw2.o
+diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
+new file mode 100644
+index 0000000..56f87cd
+--- /dev/null
++++ b/sound/pci/aw2/aw2-alsa.c
+@@ -0,0 +1,794 @@
++/*****************************************************************************
++ *
++ * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis at free.fr> and
++ * Jean-Christian Hassler <jhassler at free.fr>
++ *
++ * This file is part of the Audiowerk2 ALSA driver
++ *
++ * The Audiowerk2 ALSA driver is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2.
++ *
++ * The Audiowerk2 ALSA driver 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 the Audiowerk2 ALSA driver; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
++ * USA.
++ *
++ *****************************************************************************/
++#include <linux/init.h>
++#include <linux/pci.h>
++#include <linux/dma-mapping.h>
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <asm/io.h>
++#include <sound/core.h>
++#include <sound/initval.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/control.h>
++
++#include "saa7146.h"
++#include "aw2-saa7146.h"
++
++MODULE_AUTHOR("Cedric Bregardis <cedric.bregardis at free.fr>, "
++ "Jean-Christian Hassler <jhassler at free.fr>");
++MODULE_DESCRIPTION("Emagic Audiowerk 2 sound driver");
++MODULE_LICENSE("GPL");
++
++/*********************************
++ * DEFINES
++ ********************************/
++#define PCI_VENDOR_ID_SAA7146 0x1131
++#define PCI_DEVICE_ID_SAA7146 0x7146
++
++#define CTL_ROUTE_ANALOG 0
++#define CTL_ROUTE_DIGITAL 1
++
++/*********************************
++ * TYPEDEFS
++ ********************************/
++ /* hardware definition */
++static struct snd_pcm_hardware snd_aw2_playback_hw = {
++ .info = (SNDRV_PCM_INFO_MMAP |
++ SNDRV_PCM_INFO_INTERLEAVED |
++ SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID),
++ .formats = SNDRV_PCM_FMTBIT_S16_LE,
++ .rates = SNDRV_PCM_RATE_44100,
++ .rate_min = 44100,
++ .rate_max = 44100,
++ .channels_min = 2,
++ .channels_max = 4,
++ .buffer_bytes_max = 32768,
++ .period_bytes_min = 4096,
++ .period_bytes_max = 32768,
++ .periods_min = 1,
++ .periods_max = 1024,
++};
++
++static struct snd_pcm_hardware snd_aw2_capture_hw = {
++ .info = (SNDRV_PCM_INFO_MMAP |
++ SNDRV_PCM_INFO_INTERLEAVED |
++ SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID),
++ .formats = SNDRV_PCM_FMTBIT_S16_LE,
++ .rates = SNDRV_PCM_RATE_44100,
++ .rate_min = 44100,
++ .rate_max = 44100,
++ .channels_min = 2,
++ .channels_max = 2,
++ .buffer_bytes_max = 32768,
++ .period_bytes_min = 4096,
++ .period_bytes_max = 32768,
++ .periods_min = 1,
++ .periods_max = 1024,
++};
++
++struct aw2_pcm_device {
++ struct snd_pcm *pcm;
++ unsigned int stream_number;
++ struct aw2 *chip;
++};
++
++struct aw2 {
++ struct snd_aw2_saa7146 saa7146;
++
++ struct pci_dev *pci;
++ int irq;
++ spinlock_t reg_lock;
++ struct mutex mtx;
++
++ unsigned long iobase_phys;
++ void __iomem *iobase_virt;
++
++ struct snd_card *card;
++
++ struct aw2_pcm_device device_playback[NB_STREAM_PLAYBACK];
++ struct aw2_pcm_device device_capture[NB_STREAM_CAPTURE];
++};
++
++/*********************************
++ * FUNCTION DECLARATIONS
++ ********************************/
++static int __init alsa_card_aw2_init(void);
++static void __exit alsa_card_aw2_exit(void);
++static int snd_aw2_dev_free(struct snd_device *device);
++static int __devinit snd_aw2_create(struct snd_card *card,
++ struct pci_dev *pci, struct aw2 **rchip);
++static int __devinit snd_aw2_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id);
++static void __devexit snd_aw2_remove(struct pci_dev *pci);
++static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream);
++static int snd_aw2_pcm_playback_close(struct snd_pcm_substream *substream);
++static int snd_aw2_pcm_capture_open(struct snd_pcm_substream *substream);
++static int snd_aw2_pcm_capture_close(struct snd_pcm_substream *substream);
++static int snd_aw2_pcm_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *hw_params);
++static int snd_aw2_pcm_hw_free(struct snd_pcm_substream *substream);
++static int snd_aw2_pcm_prepare_playback(struct snd_pcm_substream *substream);
++static int snd_aw2_pcm_prepare_capture(struct snd_pcm_substream *substream);
++static int snd_aw2_pcm_trigger_playback(struct snd_pcm_substream *substream,
++ int cmd);
++static int snd_aw2_pcm_trigger_capture(struct snd_pcm_substream *substream,
++ int cmd);
++static snd_pcm_uframes_t snd_aw2_pcm_pointer_playback(struct snd_pcm_substream
++ *substream);
++static snd_pcm_uframes_t snd_aw2_pcm_pointer_capture(struct snd_pcm_substream
++ *substream);
++static int __devinit snd_aw2_new_pcm(struct aw2 *chip);
++
++static int snd_aw2_control_switch_capture_info(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo);
++static int snd_aw2_control_switch_capture_get(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value
++ *ucontrol);
++static int snd_aw2_control_switch_capture_put(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value
++ *ucontrol);
++
++/*********************************
++ * VARIABLES
++ ********************************/
++static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
++static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
++static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
++
++module_param_array(index, int, NULL, 0444);
++MODULE_PARM_DESC(index, "Index value for Audiowerk2 soundcard.");
++module_param_array(id, charp, NULL, 0444);
++MODULE_PARM_DESC(id, "ID string for the Audiowerk2 soundcard.");
++module_param_array(enable, bool, NULL, 0444);
++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,
++ 0, 0, 0},
++ {0}
++};
++
++MODULE_DEVICE_TABLE(pci, snd_aw2_ids);
++
++/* pci_driver definition */
++static struct pci_driver driver = {
++ .name = "Emagic Audiowerk 2",
++ .id_table = snd_aw2_ids,
++ .probe = snd_aw2_probe,
++ .remove = __devexit_p(snd_aw2_remove),
++};
++
++/* operators for playback PCM alsa interface */
++static struct snd_pcm_ops snd_aw2_playback_ops = {
++ .open = snd_aw2_pcm_playback_open,
++ .close = snd_aw2_pcm_playback_close,
++ .ioctl = snd_pcm_lib_ioctl,
++ .hw_params = snd_aw2_pcm_hw_params,
++ .hw_free = snd_aw2_pcm_hw_free,
++ .prepare = snd_aw2_pcm_prepare_playback,
++ .trigger = snd_aw2_pcm_trigger_playback,
++ .pointer = snd_aw2_pcm_pointer_playback,
++};
++
++/* operators for capture PCM alsa interface */
++static struct snd_pcm_ops snd_aw2_capture_ops = {
++ .open = snd_aw2_pcm_capture_open,
++ .close = snd_aw2_pcm_capture_close,
++ .ioctl = snd_pcm_lib_ioctl,
++ .hw_params = snd_aw2_pcm_hw_params,
++ .hw_free = snd_aw2_pcm_hw_free,
++ .prepare = snd_aw2_pcm_prepare_capture,
++ .trigger = snd_aw2_pcm_trigger_capture,
++ .pointer = snd_aw2_pcm_pointer_capture,
++};
++
++static struct snd_kcontrol_new aw2_control __devinitdata = {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "PCM Capture Route",
++ .index = 0,
++ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
++ .private_value = 0xffff,
++ .info = snd_aw2_control_switch_capture_info,
++ .get = snd_aw2_control_switch_capture_get,
++ .put = snd_aw2_control_switch_capture_put
++};
++
++/*********************************
++ * FUNCTION IMPLEMENTATIONS
++ ********************************/
++
++/* initialization of the module */
++static int __init alsa_card_aw2_init(void)
++{
++ snd_printdd(KERN_DEBUG "aw2: Load aw2 module\n");
++ return pci_register_driver(&driver);
++}
++
++/* clean up the module */
++static void __exit alsa_card_aw2_exit(void)
++{
++ snd_printdd(KERN_DEBUG "aw2: Unload aw2 module\n");
++ pci_unregister_driver(&driver);
++}
++
++module_init(alsa_card_aw2_init);
++module_exit(alsa_card_aw2_exit);
++
++/* component-destructor */
++static int snd_aw2_dev_free(struct snd_device *device)
++{
++ struct aw2 *chip = device->device_data;
++
++ /* Free hardware */
++ snd_aw2_saa7146_free(&chip->saa7146);
++
++ /* release the irq */
++ if (chip->irq >= 0)
++ free_irq(chip->irq, (void *)chip);
++ /* release the i/o ports & memory */
++ if (chip->iobase_virt)
++ iounmap(chip->iobase_virt);
++
++ pci_release_regions(chip->pci);
++ /* disable the PCI entry */
++ pci_disable_device(chip->pci);
++ /* release the data */
++ kfree(chip);
++
++ return 0;
++}
++
++/* chip-specific constructor */
++static int __devinit snd_aw2_create(struct snd_card *card,
++ struct pci_dev *pci, struct aw2 **rchip)
++{
++ struct aw2 *chip;
++ int err;
++ static struct snd_device_ops ops = {
++ .dev_free = snd_aw2_dev_free,
++ };
++
++ *rchip = NULL;
++
++ /* initialize the PCI entry */
++ err = pci_enable_device(pci);
++ if (err < 0)
++ return err;
++ pci_set_master(pci);
++
++ /* check PCI availability (32bit DMA) */
++ if ((pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0) ||
++ (pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0)) {
++ printk(KERN_ERR "aw2: Impossible to set 32bit mask DMA\n");
++ pci_disable_device(pci);
++ return -ENXIO;
++ }
++ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
++ if (chip == NULL) {
++ pci_disable_device(pci);
++ return -ENOMEM;
++ }
++
++ /* initialize the stuff */
++ chip->card = card;
++ chip->pci = pci;
++ chip->irq = -1;
++
++ /* (1) PCI resource allocation */
++ err = pci_request_regions(pci, "Audiowerk2");
++ if (err < 0) {
++ pci_disable_device(pci);
++ kfree(chip);
++ return err;
++ }
++ chip->iobase_phys = pci_resource_start(pci, 0);
++ chip->iobase_virt =
++ ioremap_nocache(chip->iobase_phys,
++ pci_resource_len(pci, 0));
++
++ if (chip->iobase_virt == NULL) {
++ printk(KERN_ERR "aw2: unable to remap memory region");
++ pci_release_regions(pci);
++ pci_disable_device(pci);
++ kfree(chip);
++ return -ENOMEM;
++ }
++
++
++ if (request_irq(pci->irq, snd_aw2_saa7146_interrupt,
++ IRQF_SHARED, "Audiowerk2", chip)) {
++ printk(KERN_ERR "aw2: Cannot grab irq %d\n", pci->irq);
++
++ iounmap(chip->iobase_virt);
++ pci_release_regions(chip->pci);
++ pci_disable_device(chip->pci);
++ kfree(chip);
++ return -EBUSY;
++ }
++ chip->irq = pci->irq;
++
++ /* (2) initialization of the chip hardware */
++ snd_aw2_saa7146_setup(&chip->saa7146, chip->iobase_virt);
++ err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
++ if (err < 0) {
++ free_irq(chip->irq, (void *)chip);
++ iounmap(chip->iobase_virt);
++ pci_release_regions(chip->pci);
++ pci_disable_device(chip->pci);
++ kfree(chip);
++ return err;
++ }
++
++ snd_card_set_dev(card, &pci->dev);
++ *rchip = chip;
++
++ printk(KERN_INFO
++ "Audiowerk 2 sound card (saa7146 chipset) detected and "
++ "managed\n");
++ return 0;
++}
++
++/* constructor */
++static int __devinit snd_aw2_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ static int dev;
++ struct snd_card *card;
++ struct aw2 *chip;
++ int err;
++
++ /* (1) Continue if device is not enabled, else inc dev */
++ if (dev >= SNDRV_CARDS)
++ return -ENODEV;
++ if (!enable[dev]) {
++ dev++;
++ return -ENOENT;
++ }
++
++ /* (2) Create card instance */
++ card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
++ if (card == NULL)
++ return -ENOMEM;
++
++ /* (3) Create main component */
++ err = snd_aw2_create(card, pci, &chip);
++ if (err < 0) {
++ snd_card_free(card);
++ return err;
++ }
++
++ /* initialize mutex */
++ mutex_init(&chip->mtx);
++ /* init spinlock */
++ spin_lock_init(&chip->reg_lock);
++ /* (4) Define driver ID and name string */
++ strcpy(card->driver, "aw2");
++ strcpy(card->shortname, "Audiowerk2");
++
++ sprintf(card->longname, "%s with SAA7146 irq %i",
++ card->shortname, chip->irq);
++
++ /* (5) Create other components */
++ snd_aw2_new_pcm(chip);
++
++ /* (6) Register card instance */
++ err = snd_card_register(card);
++ if (err < 0) {
++ snd_card_free(card);
++ return err;
++ }
++
++ /* (7) Set PCI driver data */
++ pci_set_drvdata(pci, card);
++
++ dev++;
++ return 0;
++}
++
++/* destructor */
++static void __devexit snd_aw2_remove(struct pci_dev *pci)
++{
++ snd_card_free(pci_get_drvdata(pci));
++ pci_set_drvdata(pci, NULL);
++}
++
++/* open callback */
++static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++
++ snd_printdd(KERN_DEBUG "aw2: Playback_open \n");
++ runtime->hw = snd_aw2_playback_hw;
++ return 0;
++}
++
++/* close callback */
++static int snd_aw2_pcm_playback_close(struct snd_pcm_substream *substream)
++{
++ return 0;
++
++}
++
++static int snd_aw2_pcm_capture_open(struct snd_pcm_substream *substream)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++
++ snd_printdd(KERN_DEBUG "aw2: Capture_open \n");
++ runtime->hw = snd_aw2_capture_hw;
++ return 0;
++}
++
++/* close callback */
++static int snd_aw2_pcm_capture_close(struct snd_pcm_substream *substream)
++{
++ /* TODO: something to do ? */
++ return 0;
++}
++
++ /* hw_params callback */
++static int snd_aw2_pcm_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *hw_params)
++{
++ return snd_pcm_lib_malloc_pages(substream,
++ params_buffer_bytes(hw_params));
++}
++
++/* hw_free callback */
++static int snd_aw2_pcm_hw_free(struct snd_pcm_substream *substream)
++{
++ return snd_pcm_lib_free_pages(substream);
++}
++
++/* prepare callback for playback */
++static int snd_aw2_pcm_prepare_playback(struct snd_pcm_substream *substream)
++{
++ struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
++ struct aw2 *chip = pcm_device->chip;
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ unsigned long period_size, buffer_size;
++
++ mutex_lock(&chip->mtx);
++
++ period_size = snd_pcm_lib_period_bytes(substream);
++ buffer_size = snd_pcm_lib_buffer_bytes(substream);
++
++ snd_aw2_saa7146_pcm_init_playback(&chip->saa7146,
++ pcm_device->stream_number,
++ runtime->dma_addr, period_size,
++ buffer_size);
++
++ /* Define Interrupt callback */
++ snd_aw2_saa7146_define_it_playback_callback(pcm_device->stream_number,
++ (snd_aw2_saa7146_it_cb)
++ snd_pcm_period_elapsed,
++ (void *)substream);
++
++ mutex_unlock(&chip->mtx);
++
++ return 0;
++}
++
++/* prepare callback for capture */
++static int snd_aw2_pcm_prepare_capture(struct snd_pcm_substream *substream)
++{
++ struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
++ struct aw2 *chip = pcm_device->chip;
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ unsigned long period_size, buffer_size;
++
++ mutex_lock(&chip->mtx);
++
++ period_size = snd_pcm_lib_period_bytes(substream);
++ buffer_size = snd_pcm_lib_buffer_bytes(substream);
++
++ snd_aw2_saa7146_pcm_init_capture(&chip->saa7146,
++ pcm_device->stream_number,
++ runtime->dma_addr, period_size,
++ buffer_size);
++
++ /* Define Interrupt callback */
++ snd_aw2_saa7146_define_it_capture_callback(pcm_device->stream_number,
++ (snd_aw2_saa7146_it_cb)
++ snd_pcm_period_elapsed,
++ (void *)substream);
++
++ mutex_unlock(&chip->mtx);
++
++ return 0;
++}
++
++/* playback trigger callback */
++static int snd_aw2_pcm_trigger_playback(struct snd_pcm_substream *substream,
++ int cmd)
++{
++ int status = 0;
++ struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
++ struct aw2 *chip = pcm_device->chip;
++ spin_lock(&chip->reg_lock);
++ switch (cmd) {
++ case SNDRV_PCM_TRIGGER_START:
++ snd_aw2_saa7146_pcm_trigger_start_playback(&chip->saa7146,
++ pcm_device->
++ stream_number);
++ break;
++ case SNDRV_PCM_TRIGGER_STOP:
++ snd_aw2_saa7146_pcm_trigger_stop_playback(&chip->saa7146,
++ pcm_device->
++ stream_number);
++ break;
++ default:
++ status = -EINVAL;
++ }
++ spin_unlock(&chip->reg_lock);
++ return status;
++}
++
++/* capture trigger callback */
++static int snd_aw2_pcm_trigger_capture(struct snd_pcm_substream *substream,
++ int cmd)
++{
++ int status = 0;
++ struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
++ struct aw2 *chip = pcm_device->chip;
++ spin_lock(&chip->reg_lock);
++ switch (cmd) {
++ case SNDRV_PCM_TRIGGER_START:
++ snd_aw2_saa7146_pcm_trigger_start_capture(&chip->saa7146,
++ pcm_device->
++ stream_number);
++ break;
++ case SNDRV_PCM_TRIGGER_STOP:
++ snd_aw2_saa7146_pcm_trigger_stop_capture(&chip->saa7146,
++ pcm_device->
++ stream_number);
++ break;
++ default:
++ status = -EINVAL;
++ }
++ spin_unlock(&chip->reg_lock);
++ return status;
++}
++
++/* playback pointer callback */
++static snd_pcm_uframes_t snd_aw2_pcm_pointer_playback(struct snd_pcm_substream
++ *substream)
++{
++ struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
++ struct aw2 *chip = pcm_device->chip;
++ unsigned int current_ptr;
++
++ /* get the current hardware pointer */
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ current_ptr =
++ snd_aw2_saa7146_get_hw_ptr_playback(&chip->saa7146,
++ pcm_device->stream_number,
++ runtime->dma_area,
++ runtime->buffer_size);
++
++ return bytes_to_frames(substream->runtime, current_ptr);
++}
++
++/* capture pointer callback */
++static snd_pcm_uframes_t snd_aw2_pcm_pointer_capture(struct snd_pcm_substream
++ *substream)
++{
++ struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
++ struct aw2 *chip = pcm_device->chip;
++ unsigned int current_ptr;
++
++ /* get the current hardware pointer */
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ current_ptr =
++ snd_aw2_saa7146_get_hw_ptr_capture(&chip->saa7146,
++ pcm_device->stream_number,
++ runtime->dma_area,
++ runtime->buffer_size);
++
++ return bytes_to_frames(substream->runtime, current_ptr);
++}
++
++/* create a pcm device */
++static int __devinit snd_aw2_new_pcm(struct aw2 *chip)
++{
++ struct snd_pcm *pcm_playback_ana;
++ struct snd_pcm *pcm_playback_num;
++ struct snd_pcm *pcm_capture;
++ struct aw2_pcm_device *pcm_device;
++ int err = 0;
++
++ /* Create new Alsa PCM device */
++
++ err = snd_pcm_new(chip->card, "Audiowerk2 analog playback", 0, 1, 0,
++ &pcm_playback_ana);
++ if (err < 0) {
++ printk(KERN_ERR "aw2: snd_pcm_new error (0x%X)\n", err);
++ return err;
++ }
++
++ /* Creation ok */
++ pcm_device = &chip->device_playback[NUM_STREAM_PLAYBACK_ANA];
++
++ /* Set PCM device name */
++ strcpy(pcm_playback_ana->name, "Analog playback");
++ /* Associate private data to PCM device */
++ pcm_playback_ana->private_data = pcm_device;
++ /* set operators of PCM device */
++ snd_pcm_set_ops(pcm_playback_ana, SNDRV_PCM_STREAM_PLAYBACK,
++ &snd_aw2_playback_ops);
++ /* store PCM device */
++ pcm_device->pcm = pcm_playback_ana;
++ /* give base chip pointer to our internal pcm device
++ structure */
++ pcm_device->chip = chip;
++ /* Give stream number to PCM device */
++ pcm_device->stream_number = NUM_STREAM_PLAYBACK_ANA;
++
++ /* pre-allocation of buffers */
++ /* Preallocate continuous pages. */
++ err = snd_pcm_lib_preallocate_pages_for_all(pcm_playback_ana,
++ SNDRV_DMA_TYPE_DEV,
++ snd_dma_pci_data
++ (chip->pci),
++ 64 * 1024, 64 * 1024);
++ if (err)
++ printk(KERN_ERR "aw2: snd_pcm_lib_preallocate_pages_for_all "
++ "error (0x%X)\n", err);
++
++ err = snd_pcm_new(chip->card, "Audiowerk2 digital playback", 1, 1, 0,
++ &pcm_playback_num);
++
++ if (err < 0) {
++ printk(KERN_ERR "aw2: snd_pcm_new error (0x%X)\n", err);
++ return err;
++ }
++ /* Creation ok */
++ pcm_device = &chip->device_playback[NUM_STREAM_PLAYBACK_DIG];
++
++ /* Set PCM device name */
++ strcpy(pcm_playback_num->name, "Digital playback");
++ /* Associate private data to PCM device */
++ pcm_playback_num->private_data = pcm_device;
++ /* set operators of PCM device */
++ snd_pcm_set_ops(pcm_playback_num, SNDRV_PCM_STREAM_PLAYBACK,
++ &snd_aw2_playback_ops);
++ /* store PCM device */
++ pcm_device->pcm = pcm_playback_num;
++ /* give base chip pointer to our internal pcm device
++ structure */
++ pcm_device->chip = chip;
++ /* Give stream number to PCM device */
++ pcm_device->stream_number = NUM_STREAM_PLAYBACK_DIG;
++
++ /* pre-allocation of buffers */
++ /* Preallocate continuous pages. */
++ err = snd_pcm_lib_preallocate_pages_for_all(pcm_playback_num,
++ SNDRV_DMA_TYPE_DEV,
++ snd_dma_pci_data
++ (chip->pci),
++ 64 * 1024, 64 * 1024);
++ if (err)
++ printk(KERN_ERR
++ "aw2: snd_pcm_lib_preallocate_pages_for_all error "
++ "(0x%X)\n", err);
++
++
++
++ err = snd_pcm_new(chip->card, "Audiowerk2 capture", 2, 0, 1,
++ &pcm_capture);
++
++ if (err < 0) {
++ printk(KERN_ERR "aw2: snd_pcm_new error (0x%X)\n", err);
++ return err;
++ }
++
++ /* Creation ok */
++ pcm_device = &chip->device_capture[NUM_STREAM_CAPTURE_ANA];
++
++ /* Set PCM device name */
++ strcpy(pcm_capture->name, "Capture");
++ /* Associate private data to PCM device */
++ pcm_capture->private_data = pcm_device;
++ /* set operators of PCM device */
++ snd_pcm_set_ops(pcm_capture, SNDRV_PCM_STREAM_CAPTURE,
++ &snd_aw2_capture_ops);
++ /* store PCM device */
++ pcm_device->pcm = pcm_capture;
++ /* give base chip pointer to our internal pcm device
++ structure */
++ pcm_device->chip = chip;
++ /* Give stream number to PCM device */
++ pcm_device->stream_number = NUM_STREAM_CAPTURE_ANA;
++
++ /* pre-allocation of buffers */
++ /* Preallocate continuous pages. */
++ err = snd_pcm_lib_preallocate_pages_for_all(pcm_capture,
++ SNDRV_DMA_TYPE_DEV,
++ snd_dma_pci_data
++ (chip->pci),
++ 64 * 1024, 64 * 1024);
++ if (err)
++ printk(KERN_ERR
++ "aw2: snd_pcm_lib_preallocate_pages_for_all error "
++ "(0x%X)\n", err);
++
++
++ /* Create control */
++ err = snd_ctl_add(chip->card, snd_ctl_new1(&aw2_control, chip));
++ if (err < 0) {
++ printk(KERN_ERR "aw2: snd_ctl_add error (0x%X)\n", err);
++ return err;
++ }
++
++ return 0;
++}
++
++static int snd_aw2_control_switch_capture_info(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++ static char *texts[2] = {
++ "Analog", "Digital"
++ };
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
++ uinfo->count = 1;
++ uinfo->value.enumerated.items = 2;
++ if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) {
++ uinfo->value.enumerated.item =
++ uinfo->value.enumerated.items - 1;
++ }
++ strcpy(uinfo->value.enumerated.name,
++ texts[uinfo->value.enumerated.item]);
++ return 0;
++}
++
++static int snd_aw2_control_switch_capture_get(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value
++ *ucontrol)
++{
++ struct aw2 *chip = snd_kcontrol_chip(kcontrol);
++ if (snd_aw2_saa7146_is_using_digital_input(&chip->saa7146))
++ ucontrol->value.enumerated.item[0] = CTL_ROUTE_DIGITAL;
++ else
++ ucontrol->value.enumerated.item[0] = CTL_ROUTE_ANALOG;
++ return 0;
++}
++
++static int snd_aw2_control_switch_capture_put(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value
++ *ucontrol)
++{
++ struct aw2 *chip = snd_kcontrol_chip(kcontrol);
++ int changed = 0;
++ int is_disgital =
++ snd_aw2_saa7146_is_using_digital_input(&chip->saa7146);
++
++ if (((ucontrol->value.integer.value[0] == CTL_ROUTE_DIGITAL)
++ && !is_disgital)
++ || ((ucontrol->value.integer.value[0] == CTL_ROUTE_ANALOG)
++ && is_disgital)) {
++ snd_aw2_saa7146_use_digital_input(&chip->saa7146, !is_disgital);
++ changed = 1;
++ }
++ return changed;
++}
+diff --git a/sound/pci/aw2/aw2-saa7146.c b/sound/pci/aw2/aw2-saa7146.c
+new file mode 100644
+index 0000000..6a3891a
+--- /dev/null
++++ b/sound/pci/aw2/aw2-saa7146.c
+@@ -0,0 +1,465 @@
++/*****************************************************************************
++ *
++ * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis at free.fr> and
++ * Jean-Christian Hassler <jhassler at free.fr>
++ *
++ * This file is part of the Audiowerk2 ALSA driver
++ *
++ * The Audiowerk2 ALSA driver is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2.
++ *
++ * The Audiowerk2 ALSA driver 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 the Audiowerk2 ALSA driver; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
++ * USA.
++ *
++ *****************************************************************************/
++
++#define AW2_SAA7146_M
++
++#include <linux/init.h>
++#include <linux/pci.h>
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <asm/system.h>
++#include <asm/io.h>
++#include <sound/core.h>
++#include <sound/initval.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++
++#include "saa7146.h"
++#include "aw2-saa7146.h"
++
++#include "aw2-tsl.c"
++
++#define WRITEREG(value, addr) writel((value), chip->base_addr + (addr))
++#define READREG(addr) readl(chip->base_addr + (addr))
++
++static struct snd_aw2_saa7146_cb_param
++ arr_substream_it_playback_cb[NB_STREAM_PLAYBACK];
++static struct snd_aw2_saa7146_cb_param
++ arr_substream_it_capture_cb[NB_STREAM_CAPTURE];
++
++static int snd_aw2_saa7146_get_limit(int size);
++
++/* chip-specific destructor */
++int snd_aw2_saa7146_free(struct snd_aw2_saa7146 *chip)
++{
++ /* disable all irqs */
++ WRITEREG(0, IER);
++
++ /* reset saa7146 */
++ WRITEREG((MRST_N << 16), MC1);
++
++ /* Unset base addr */
++ chip->base_addr = NULL;
++
++ return 0;
++}
++
++void snd_aw2_saa7146_setup(struct snd_aw2_saa7146 *chip,
++ void __iomem *pci_base_addr)
++{
++ /* set PCI burst/threshold
++
++ Burst length definition
++ VALUE BURST LENGTH
++ 000 1 Dword
++ 001 2 Dwords
++ 010 4 Dwords
++ 011 8 Dwords
++ 100 16 Dwords
++ 101 32 Dwords
++ 110 64 Dwords
++ 111 128 Dwords
++
++ Threshold definition
++ VALUE WRITE MODE READ MODE
++ 00 1 Dword of valid data 1 empty Dword
++ 01 4 Dwords of valid data 4 empty Dwords
++ 10 8 Dwords of valid data 8 empty Dwords
++ 11 16 Dwords of valid data 16 empty Dwords */
++
++ unsigned int acon2;
++ unsigned int acon1 = 0;
++ int i;
++
++ /* Set base addr */
++ chip->base_addr = pci_base_addr;
++
++ /* disable all irqs */
++ WRITEREG(0, IER);
++
++ /* reset saa7146 */
++ WRITEREG((MRST_N << 16), MC1);
++
++ /* enable audio interface */
++#ifdef __BIG_ENDIAN
++ acon1 |= A1_SWAP;
++ acon1 |= A2_SWAP;
++#endif
++ /* WS0_CTRL, WS0_SYNC: input TSL1, I2S */
++
++ /* At initialization WS1 and WS2 are disbaled (configured as input */
++ acon1 |= 0 * WS1_CTRL;
++ acon1 |= 0 * WS2_CTRL;
++
++ /* WS4 is not used. So it must not restart A2.
++ This is why it is configured as output (force to low) */
++ acon1 |= 3 * WS4_CTRL;
++
++ /* WS3_CTRL, WS3_SYNC: output TSL2, I2S */
++ acon1 |= 2 * WS3_CTRL;
++
++ /* A1 and A2 are active and asynchronous */
++ acon1 |= 3 * AUDIO_MODE;
++ WRITEREG(acon1, ACON1);
++
++ /* The following comes from original windows driver.
++ It is needed to have a correct behavior of input and output
++ simultenously, but I don't know why ! */
++ WRITEREG(3 * (BurstA1_in) + 3 * (ThreshA1_in) +
++ 3 * (BurstA1_out) + 3 * (ThreshA1_out) +
++ 3 * (BurstA2_out) + 3 * (ThreshA2_out), PCI_BT_A);
++
++ /* enable audio port pins */
++ WRITEREG((EAP << 16) | EAP, MC1);
++
++ /* enable I2C */
++ WRITEREG((EI2C << 16) | EI2C, MC1);
++ /* enable interrupts */
++ WRITEREG(A1_out | A2_out | A1_in | IIC_S | IIC_E, IER);
++
++ /* audio configuration */
++ acon2 = A2_CLKSRC | BCLK1_OEN;
++ WRITEREG(acon2, ACON2);
++
++ /* By default use analog input */
++ snd_aw2_saa7146_use_digital_input(chip, 0);
++
++ /* TSL setup */
++ for (i = 0; i < 8; ++i) {
++ WRITEREG(tsl1[i], TSL1 + (i * 4));
++ WRITEREG(tsl2[i], TSL2 + (i * 4));
++ }
++
++}
++
++void snd_aw2_saa7146_pcm_init_playback(struct snd_aw2_saa7146 *chip,
++ int stream_number,
++ unsigned long dma_addr,
++ unsigned long period_size,
++ unsigned long buffer_size)
++{
++ unsigned long dw_page, dw_limit;
++
++ /* Configure DMA for substream
++ Configuration informations: ALSA has allocated continuous memory
++ pages. So we don't need to use MMU of saa7146.
++ */
++
++ /* No MMU -> nothing to do with PageA1, we only configure the limit of
++ PageAx_out register */
++ /* Disable MMU */
++ dw_page = (0L << 11);
++
++ /* Configure Limit for DMA access.
++ The limit register defines an address limit, which generates
++ an interrupt if passed by the actual PCI address pointer.
++ '0001' means an interrupt will be generated if the lower
++ 6 bits (64 bytes) of the PCI address are zero. '0010'
++ defines a limit of 128 bytes, '0011' one of 256 bytes, and
++ so on up to 1 Mbyte defined by '1111'. This interrupt range
++ can be calculated as follows:
++ Range = 2^(5 + Limit) bytes.
++ */
++ dw_limit = snd_aw2_saa7146_get_limit(period_size);
++ dw_page |= (dw_limit << 4);
++
++ if (stream_number == 0) {
++ WRITEREG(dw_page, PageA2_out);
++
++ /* Base address for DMA transfert. */
++ /* This address has been reserved by ALSA. */
++ /* This is a physical address */
++ WRITEREG(dma_addr, BaseA2_out);
++
++ /* Define upper limit for DMA access */
++ WRITEREG(dma_addr + buffer_size, ProtA2_out);
++
++ } else if (stream_number == 1) {
++ WRITEREG(dw_page, PageA1_out);
++
++ /* Base address for DMA transfert. */
++ /* This address has been reserved by ALSA. */
++ /* This is a physical address */
++ WRITEREG(dma_addr, BaseA1_out);
++
++ /* Define upper limit for DMA access */
++ WRITEREG(dma_addr + buffer_size, ProtA1_out);
++ } else {
++ printk(KERN_ERR
++ "aw2: snd_aw2_saa7146_pcm_init_playback: "
++ "Substream number is not 0 or 1 -> not managed\n");
++ }
++}
++
++void snd_aw2_saa7146_pcm_init_capture(struct snd_aw2_saa7146 *chip,
++ int stream_number, unsigned long dma_addr,
++ unsigned long period_size,
++ unsigned long buffer_size)
++{
++ unsigned long dw_page, dw_limit;
++
++ /* Configure DMA for substream
++ Configuration informations: ALSA has allocated continuous memory
++ pages. So we don't need to use MMU of saa7146.
++ */
++
++ /* No MMU -> nothing to do with PageA1, we only configure the limit of
++ PageAx_out register */
++ /* Disable MMU */
++ dw_page = (0L << 11);
++
++ /* Configure Limit for DMA access.
++ The limit register defines an address limit, which generates
++ an interrupt if passed by the actual PCI address pointer.
++ '0001' means an interrupt will be generated if the lower
++ 6 bits (64 bytes) of the PCI address are zero. '0010'
++ defines a limit of 128 bytes, '0011' one of 256 bytes, and
++ so on up to 1 Mbyte defined by '1111'. This interrupt range
++ can be calculated as follows:
++ Range = 2^(5 + Limit) bytes.
++ */
++ dw_limit = snd_aw2_saa7146_get_limit(period_size);
++ dw_page |= (dw_limit << 4);
++
++ if (stream_number == 0) {
++ WRITEREG(dw_page, PageA1_in);
++
++ /* Base address for DMA transfert. */
++ /* This address has been reserved by ALSA. */
++ /* This is a physical address */
++ WRITEREG(dma_addr, BaseA1_in);
++
++ /* Define upper limit for DMA access */
++ WRITEREG(dma_addr + buffer_size, ProtA1_in);
++ } else {
++ printk(KERN_ERR
++ "aw2: snd_aw2_saa7146_pcm_init_capture: "
++ "Substream number is not 0 -> not managed\n");
++ }
++}
++
++void snd_aw2_saa7146_define_it_playback_callback(unsigned int stream_number,
++ snd_aw2_saa7146_it_cb
++ p_it_callback,
++ void *p_callback_param)
++{
++ if (stream_number < NB_STREAM_PLAYBACK) {
++ arr_substream_it_playback_cb[stream_number].p_it_callback =
++ (snd_aw2_saa7146_it_cb) p_it_callback;
++ arr_substream_it_playback_cb[stream_number].p_callback_param =
++ (void *)p_callback_param;
++ }
++}
++
++void snd_aw2_saa7146_define_it_capture_callback(unsigned int stream_number,
++ snd_aw2_saa7146_it_cb
++ p_it_callback,
++ void *p_callback_param)
++{
++ if (stream_number < NB_STREAM_CAPTURE) {
++ arr_substream_it_capture_cb[stream_number].p_it_callback =
++ (snd_aw2_saa7146_it_cb) p_it_callback;
++ arr_substream_it_capture_cb[stream_number].p_callback_param =
++ (void *)p_callback_param;
++ }
++}
++
++void snd_aw2_saa7146_pcm_trigger_start_playback(struct snd_aw2_saa7146 *chip,
++ int stream_number)
++{
++ unsigned int acon1 = 0;
++ /* In aw8 driver, dma transfert is always active. It is
++ started and stopped in a larger "space" */
++ acon1 = READREG(ACON1);
++ if (stream_number == 0) {
++ WRITEREG((TR_E_A2_OUT << 16) | TR_E_A2_OUT, MC1);
++
++ /* WS2_CTRL, WS2_SYNC: output TSL2, I2S */
++ acon1 |= 2 * WS2_CTRL;
++ WRITEREG(acon1, ACON1);
++
++ } else if (stream_number == 1) {
++ WRITEREG((TR_E_A1_OUT << 16) | TR_E_A1_OUT, MC1);
++
++ /* WS1_CTRL, WS1_SYNC: output TSL1, I2S */
++ acon1 |= 1 * WS1_CTRL;
++ WRITEREG(acon1, ACON1);
++ }
++}
++
++void snd_aw2_saa7146_pcm_trigger_stop_playback(struct snd_aw2_saa7146 *chip,
++ int stream_number)
++{
++ unsigned int acon1 = 0;
++ acon1 = READREG(ACON1);
++ if (stream_number == 0) {
++ /* WS2_CTRL, WS2_SYNC: output TSL2, I2S */
++ acon1 &= ~(3 * WS2_CTRL);
++ WRITEREG(acon1, ACON1);
++
++ WRITEREG((TR_E_A2_OUT << 16), MC1);
++ } else if (stream_number == 1) {
++ /* WS1_CTRL, WS1_SYNC: output TSL1, I2S */
++ acon1 &= ~(3 * WS1_CTRL);
++ WRITEREG(acon1, ACON1);
++
++ WRITEREG((TR_E_A1_OUT << 16), MC1);
++ }
++}
++
++void snd_aw2_saa7146_pcm_trigger_start_capture(struct snd_aw2_saa7146 *chip,
++ int stream_number)
++{
++ /* In aw8 driver, dma transfert is always active. It is
++ started and stopped in a larger "space" */
++ if (stream_number == 0)
++ WRITEREG((TR_E_A1_IN << 16) | TR_E_A1_IN, MC1);
++}
++
++void snd_aw2_saa7146_pcm_trigger_stop_capture(struct snd_aw2_saa7146 *chip,
++ int stream_number)
++{
++ if (stream_number == 0)
++ WRITEREG((TR_E_A1_IN << 16), MC1);
++}
++
++irqreturn_t snd_aw2_saa7146_interrupt(int irq, void *dev_id)
++{
++ unsigned int isr;
++ unsigned int iicsta;
++ struct snd_aw2_saa7146 *chip = dev_id;
++
++ isr = READREG(ISR);
++ if (!isr)
++ return IRQ_NONE;
++
++ WRITEREG(isr, ISR);
++
++ if (isr & (IIC_S | IIC_E)) {
++ iicsta = READREG(IICSTA);
++ WRITEREG(0x100, IICSTA);
++ }
++
++ if (isr & A1_out) {
++ if (arr_substream_it_playback_cb[1].p_it_callback != NULL) {
++ arr_substream_it_playback_cb[1].
++ p_it_callback(arr_substream_it_playback_cb[1].
++ p_callback_param);
++ }
++ }
++ if (isr & A2_out) {
++ if (arr_substream_it_playback_cb[0].p_it_callback != NULL) {
++ arr_substream_it_playback_cb[0].
++ p_it_callback(arr_substream_it_playback_cb[0].
++ p_callback_param);
++ }
++
++ }
++ if (isr & A1_in) {
++ if (arr_substream_it_capture_cb[0].p_it_callback != NULL) {
++ arr_substream_it_capture_cb[0].
++ p_it_callback(arr_substream_it_capture_cb[0].
++ p_callback_param);
++ }
++ }
++ return IRQ_HANDLED;
++}
++
++unsigned int snd_aw2_saa7146_get_hw_ptr_playback(struct snd_aw2_saa7146 *chip,
++ int stream_number,
++ unsigned char *start_addr,
++ unsigned int buffer_size)
++{
++ long pci_adp = 0;
++ size_t ptr = 0;
++
++ if (stream_number == 0) {
++ pci_adp = READREG(PCI_ADP3);
++ ptr = pci_adp - (long)start_addr;
++
++ if (ptr == buffer_size)
++ ptr = 0;
++ }
++ if (stream_number == 1) {
++ pci_adp = READREG(PCI_ADP1);
++ ptr = pci_adp - (size_t) start_addr;
++
++ if (ptr == buffer_size)
++ ptr = 0;
++ }
++ return ptr;
++}
++
++unsigned int snd_aw2_saa7146_get_hw_ptr_capture(struct snd_aw2_saa7146 *chip,
++ int stream_number,
++ unsigned char *start_addr,
++ unsigned int buffer_size)
++{
++ size_t pci_adp = 0;
++ size_t ptr = 0;
++ if (stream_number == 0) {
++ pci_adp = READREG(PCI_ADP2);
++ ptr = pci_adp - (size_t) start_addr;
++
++ if (ptr == buffer_size)
++ ptr = 0;
++ }
++ return ptr;
++}
++
++void snd_aw2_saa7146_use_digital_input(struct snd_aw2_saa7146 *chip,
++ int use_digital)
++{
++ /* FIXME: switch between analog and digital input does not always work.
++ It can produce a kind of white noise. It seams that received data
++ are inverted sometime (endian inversion). Why ? I don't know, maybe
++ a problem of synchronization... However for the time being I have
++ not found the problem. Workaround: switch again (and again) between
++ digital and analog input until it works. */
++ if (use_digital)
++ WRITEREG(0x40, GPIO_CTRL);
++ else
++ WRITEREG(0x50, GPIO_CTRL);
++}
++
++int snd_aw2_saa7146_is_using_digital_input(struct snd_aw2_saa7146 *chip)
++{
++ unsigned int reg_val = READREG(GPIO_CTRL);
++ if ((reg_val & 0xFF) == 0x40)
++ return 1;
++ else
++ return 0;
++}
++
++
++static int snd_aw2_saa7146_get_limit(int size)
++{
++ int limitsize = 32;
++ int limit = 0;
++ while (limitsize < size) {
++ limitsize *= 2;
++ limit++;
++ }
++ return limit;
++}
+diff --git a/sound/pci/aw2/aw2-saa7146.h b/sound/pci/aw2/aw2-saa7146.h
+new file mode 100644
+index 0000000..5b35e35
+--- /dev/null
++++ b/sound/pci/aw2/aw2-saa7146.h
+@@ -0,0 +1,105 @@
++/*****************************************************************************
++ *
++ * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis at free.fr> and
++ * Jean-Christian Hassler <jhassler at free.fr>
++ *
++ * This file is part of the Audiowerk2 ALSA driver
++ *
++ * The Audiowerk2 ALSA driver is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2.
++ *
++ * The Audiowerk2 ALSA driver 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 the Audiowerk2 ALSA driver; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
++ * USA.
++ *
++ *****************************************************************************/
++
++#ifndef AW2_SAA7146_H
++#define AW2_SAA7146_H
++
++#define NB_STREAM_PLAYBACK 2
++#define NB_STREAM_CAPTURE 1
++
++#define NUM_STREAM_PLAYBACK_ANA 0
++#define NUM_STREAM_PLAYBACK_DIG 1
++
++#define NUM_STREAM_CAPTURE_ANA 0
++
++typedef void (*snd_aw2_saa7146_it_cb) (void *);
++
++struct snd_aw2_saa7146_cb_param {
++ snd_aw2_saa7146_it_cb p_it_callback;
++ void *p_callback_param;
++};
++
++/* definition of the chip-specific record */
++
++struct snd_aw2_saa7146 {
++ void __iomem *base_addr;
++};
++
++extern void snd_aw2_saa7146_setup(struct snd_aw2_saa7146 *chip,
++ void __iomem *pci_base_addr);
++extern int snd_aw2_saa7146_free(struct snd_aw2_saa7146 *chip);
++
++extern void snd_aw2_saa7146_pcm_init_playback(struct snd_aw2_saa7146 *chip,
++ int stream_number,
++ unsigned long dma_addr,
++ unsigned long period_size,
++ unsigned long buffer_size);
++extern void snd_aw2_saa7146_pcm_init_capture(struct snd_aw2_saa7146 *chip,
++ int stream_number,
++ unsigned long dma_addr,
++ unsigned long period_size,
++ unsigned long buffer_size);
++extern void snd_aw2_saa7146_define_it_playback_callback(unsigned int
++ stream_number,
++ snd_aw2_saa7146_it_cb
++ p_it_callback,
++ void *p_callback_param);
++extern void snd_aw2_saa7146_define_it_capture_callback(unsigned int
++ stream_number,
++ snd_aw2_saa7146_it_cb
++ p_it_callback,
++ void *p_callback_param);
++extern void snd_aw2_saa7146_pcm_trigger_start_capture(struct snd_aw2_saa7146
++ *chip, int stream_number);
++extern void snd_aw2_saa7146_pcm_trigger_stop_capture(struct snd_aw2_saa7146
++ *chip, int stream_number);
++
++extern void snd_aw2_saa7146_pcm_trigger_start_playback(struct snd_aw2_saa7146
++ *chip,
++ int stream_number);
++extern void snd_aw2_saa7146_pcm_trigger_stop_playback(struct snd_aw2_saa7146
++ *chip, int stream_number);
++
++extern irqreturn_t snd_aw2_saa7146_interrupt(int irq, void *dev_id);
++extern unsigned int snd_aw2_saa7146_get_hw_ptr_playback(struct snd_aw2_saa7146
++ *chip,
++ int stream_number,
++ unsigned char
++ *start_addr,
++ unsigned int
++ buffer_size);
++extern unsigned int snd_aw2_saa7146_get_hw_ptr_capture(struct snd_aw2_saa7146
++ *chip,
++ int stream_number,
++ unsigned char
++ *start_addr,
++ unsigned int
++ buffer_size);
++
++extern void snd_aw2_saa7146_use_digital_input(struct snd_aw2_saa7146 *chip,
++ int use_digital);
++
++extern int snd_aw2_saa7146_is_using_digital_input(struct snd_aw2_saa7146
++ *chip);
++
++#endif
+diff --git a/sound/pci/aw2/aw2-tsl.c b/sound/pci/aw2/aw2-tsl.c
+new file mode 100644
+index 0000000..459b031
+--- /dev/null
++++ b/sound/pci/aw2/aw2-tsl.c
+@@ -0,0 +1,110 @@
++/*****************************************************************************
++ *
++ * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis at free.fr> and
++ * Jean-Christian Hassler <jhassler at free.fr>
++ * Copyright 1998 Emagic Soft- und Hardware GmbH
++ * Copyright 2002 Martijn Sipkema
++ *
++ * This file is part of the Audiowerk2 ALSA driver
++ *
++ * The Audiowerk2 ALSA driver is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2.
++ *
++ * The Audiowerk2 ALSA driver 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 the Audiowerk2 ALSA driver; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
++ * USA.
++ *
++ *****************************************************************************/
++
++#define TSL_WS0 (1UL << 31)
++#define TSL_WS1 (1UL << 30)
++#define TSL_WS2 (1UL << 29)
++#define TSL_WS3 (1UL << 28)
++#define TSL_WS4 (1UL << 27)
++#define TSL_DIS_A1 (1UL << 24)
++#define TSL_SDW_A1 (1UL << 23)
++#define TSL_SIB_A1 (1UL << 22)
++#define TSL_SF_A1 (1UL << 21)
++#define TSL_LF_A1 (1UL << 20)
++#define TSL_BSEL_A1 (1UL << 17)
++#define TSL_DOD_A1 (1UL << 15)
++#define TSL_LOW_A1 (1UL << 14)
++#define TSL_DIS_A2 (1UL << 11)
++#define TSL_SDW_A2 (1UL << 10)
++#define TSL_SIB_A2 (1UL << 9)
++#define TSL_SF_A2 (1UL << 8)
++#define TSL_LF_A2 (1UL << 7)
++#define TSL_BSEL_A2 (1UL << 4)
++#define TSL_DOD_A2 (1UL << 2)
++#define TSL_LOW_A2 (1UL << 1)
++#define TSL_EOS (1UL << 0)
++
++ /* Audiowerk8 hardware setup: */
++ /* WS0, SD4, TSL1 - Analog/ digital in */
++ /* WS1, SD0, TSL1 - Analog out #1, digital out */
++ /* WS2, SD2, TSL1 - Analog out #2 */
++ /* WS3, SD1, TSL2 - Analog out #3 */
++ /* WS4, SD3, TSL2 - Analog out #4 */
++
++ /* Audiowerk8 timing: */
++ /* Timeslot: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ... */
++
++ /* A1_INPUT: */
++ /* SD4: <_ADC-L_>-------<_ADC-R_>-------< */
++ /* WS0: _______________/---------------\_ */
++
++ /* A1_OUTPUT: */
++ /* SD0: <_1-L___>-------<_1-R___>-------< */
++ /* WS1: _______________/---------------\_ */
++ /* SD2: >-------<_2-L___>-------<_2-R___> */
++ /* WS2: -------\_______________/--------- */
++
++ /* A2_OUTPUT: */
++ /* SD1: <_3-L___>-------<_3-R___>-------< */
++ /* WS3: _______________/---------------\_ */
++ /* SD3: >-------<_4-L___>-------<_4-R___> */
++ /* WS4: -------\_______________/--------- */
++
++static int tsl1[8] = {
++ 1 * TSL_SDW_A1 | 3 * TSL_BSEL_A1 |
++ 0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_LF_A1,
++
++ 1 * TSL_SDW_A1 | 2 * TSL_BSEL_A1 |
++ 0 * TSL_DIS_A1 | 0 * TSL_DOD_A1,
++
++ 0 * TSL_SDW_A1 | 3 * TSL_BSEL_A1 |
++ 0 * TSL_DIS_A1 | 0 * TSL_DOD_A1,
++
++ 0 * TSL_SDW_A1 | 2 * TSL_BSEL_A1 |
++ 0 * TSL_DIS_A1 | 0 * TSL_DOD_A1,
++
++ 1 * TSL_SDW_A1 | 1 * TSL_BSEL_A1 |
++ 0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0,
++
++ 1 * TSL_SDW_A1 | 0 * TSL_BSEL_A1 |
++ 0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0,
++
++ 0 * TSL_SDW_A1 | 1 * TSL_BSEL_A1 |
++ 0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0,
++
++ 0 * TSL_SDW_A1 | 0 * TSL_BSEL_A1 | 0 * TSL_DIS_A1 |
++ 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0 | TSL_SF_A1 | TSL_EOS,
++};
++
++static int tsl2[8] = {
++ 0 * TSL_SDW_A2 | 3 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_LF_A2,
++ 0 * TSL_SDW_A2 | 2 * TSL_BSEL_A2 | 2 * TSL_DOD_A2,
++ 0 * TSL_SDW_A2 | 3 * TSL_BSEL_A2 | 2 * TSL_DOD_A2,
++ 0 * TSL_SDW_A2 | 2 * TSL_BSEL_A2 | 2 * TSL_DOD_A2,
++ 0 * TSL_SDW_A2 | 1 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2,
++ 0 * TSL_SDW_A2 | 0 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2,
++ 0 * TSL_SDW_A2 | 1 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2,
++ 0 * TSL_SDW_A2 | 0 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2 | TSL_EOS
++};
+diff --git a/sound/pci/aw2/saa7146.h b/sound/pci/aw2/saa7146.h
+new file mode 100644
+index 0000000..ce0ab5f
+--- /dev/null
++++ b/sound/pci/aw2/saa7146.h
+@@ -0,0 +1,168 @@
++/*****************************************************************************
++ *
++ * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis at free.fr> and
++ * Jean-Christian Hassler <jhassler at free.fr>
++ *
++ * This file is part of the Audiowerk2 ALSA driver
++ *
++ * The Audiowerk2 ALSA driver is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2.
++ *
++ * The Audiowerk2 ALSA driver 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 the Audiowerk2 ALSA driver; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
++ * USA.
++ *
++ *****************************************************************************/
++
++/* SAA7146 registers */
++#define PCI_BT_A 0x4C
++#define IICTFR 0x8C
++#define IICSTA 0x90
++#define BaseA1_in 0x94
++#define ProtA1_in 0x98
++#define PageA1_in 0x9C
++#define BaseA1_out 0xA0
++#define ProtA1_out 0xA4
++#define PageA1_out 0xA8
++#define BaseA2_in 0xAC
++#define ProtA2_in 0xB0
++#define PageA2_in 0xB4
++#define BaseA2_out 0xB8
++#define ProtA2_out 0xBC
++#define PageA2_out 0xC0
++#define IER 0xDC
++#define GPIO_CTRL 0xE0
++#define ACON1 0xF4
++#define ACON2 0xF8
++#define MC1 0xFC
++#define MC2 0x100
++#define ISR 0x10C
++#define PSR 0x110
++#define SSR 0x114
++#define PCI_ADP1 0x12C
++#define PCI_ADP2 0x130
++#define PCI_ADP3 0x134
++#define PCI_ADP4 0x138
++#define LEVEL_REP 0x140
++#define FB_BUFFER1 0x144
++#define FB_BUFFER2 0x148
++#define TSL1 0x180
++#define TSL2 0x1C0
++
++#define ME (1UL << 11)
++#define LIMIT (1UL << 4)
++#define PV (1UL << 3)
++
++/* PSR/ISR/IER */
++#define PPEF (1UL << 31)
++#define PABO (1UL << 30)
++#define IIC_S (1UL << 17)
++#define IIC_E (1UL << 16)
++#define A2_in (1UL << 15)
++#define A2_out (1UL << 14)
++#define A1_in (1UL << 13)
++#define A1_out (1UL << 12)
++#define AFOU (1UL << 11)
++#define PIN3 (1UL << 6)
++#define PIN2 (1UL << 5)
++#define PIN1 (1UL << 4)
++#define PIN0 (1UL << 3)
++#define ECS (1UL << 2)
++#define EC3S (1UL << 1)
++#define EC0S (1UL << 0)
++
++/* SSR */
++#define PRQ (1UL << 31)
++#define PMA (1UL << 30)
++#define IIC_EA (1UL << 21)
++#define IIC_EW (1UL << 20)
++#define IIC_ER (1UL << 19)
++#define IIC_EL (1UL << 18)
++#define IIC_EF (1UL << 17)
++#define AF2_in (1UL << 10)
++#define AF2_out (1UL << 9)
++#define AF1_in (1UL << 8)
++#define AF1_out (1UL << 7)
++#define EC5S (1UL << 3)
++#define EC4S (1UL << 2)
++#define EC2S (1UL << 1)
++#define EC1S (1UL << 0)
++
++/* PCI_BT_A */
++#define BurstA1_in (1UL << 26)
++#define ThreshA1_in (1UL << 24)
++#define BurstA1_out (1UL << 18)
++#define ThreshA1_out (1UL << 16)
++#define BurstA2_in (1UL << 10)
++#define ThreshA2_in (1UL << 8)
++#define BurstA2_out (1UL << 2)
++#define ThreshA2_out (1UL << 0)
++
++/* MC1 */
++#define MRST_N (1UL << 15)
++#define EAP (1UL << 9)
++#define EI2C (1UL << 8)
++#define TR_E_A2_OUT (1UL << 3)
++#define TR_E_A2_IN (1UL << 2)
++#define TR_E_A1_OUT (1UL << 1)
++#define TR_E_A1_IN (1UL << 0)
++
++/* MC2 */
++#define UPLD_IIC (1UL << 0)
++
++/* ACON1 */
++#define AUDIO_MODE (1UL << 29)
++#define MAXLEVEL (1UL << 22)
++#define A1_SWAP (1UL << 21)
++#define A2_SWAP (1UL << 20)
++#define WS0_CTRL (1UL << 18)
++#define WS0_SYNC (1UL << 16)
++#define WS1_CTRL (1UL << 14)
++#define WS1_SYNC (1UL << 12)
++#define WS2_CTRL (1UL << 10)
++#define WS2_SYNC (1UL << 8)
++#define WS3_CTRL (1UL << 6)
++#define WS3_SYNC (1UL << 4)
++#define WS4_CTRL (1UL << 2)
++#define WS4_SYNC (1UL << 0)
++
++/* ACON2 */
++#define A1_CLKSRC (1UL << 27)
++#define A2_CLKSRC (1UL << 22)
++#define INVERT_BCLK1 (1UL << 21)
++#define INVERT_BCLK2 (1UL << 20)
++#define BCLK1_OEN (1UL << 19)
++#define BCLK2_OEN (1UL << 18)
++
++/* IICSTA */
++#define IICCC (1UL << 8)
++#define ABORT (1UL << 7)
++#define SPERR (1UL << 6)
++#define APERR (1UL << 5)
++#define DTERR (1UL << 4)
++#define DRERR (1UL << 3)
++#define AL (1UL << 2)
++#define ERR (1UL << 1)
++#define BUSY (1UL << 0)
++
++/* IICTFR */
++#define BYTE2 (1UL << 24)
++#define BYTE1 (1UL << 16)
++#define BYTE0 (1UL << 8)
++#define ATRR2 (1UL << 6)
++#define ATRR1 (1UL << 4)
++#define ATRR0 (1UL << 2)
++#define ERR (1UL << 1)
++#define BUSY (1UL << 0)
++
++#define START 3
++#define CONT 2
++#define STOP 1
++#define NOP 0
+diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
+index 4e71a55..5f63af6 100644
+--- a/sound/pci/azt3328.c
++++ b/sound/pci/azt3328.c
+@@ -157,8 +157,8 @@ MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}");
+
+ #if DEBUG_CALLS
+ #define snd_azf3328_dbgcalls(format, args...) printk(format, ##args)
+-#define snd_azf3328_dbgcallenter() printk(KERN_ERR "--> %s\n", __FUNCTION__)
+-#define snd_azf3328_dbgcallleave() printk(KERN_ERR "<-- %s\n", __FUNCTION__)
++#define snd_azf3328_dbgcallenter() printk(KERN_ERR "--> %s\n", __func__)
++#define snd_azf3328_dbgcallleave() printk(KERN_ERR "<-- %s\n", __func__)
+ #else
+ #define snd_azf3328_dbgcalls(format, args...)
+ #define snd_azf3328_dbgcallenter()
+@@ -1514,7 +1514,8 @@ snd_azf3328_free(struct snd_azf3328 *chip)
+ /* well, at least we know how to disable the timer IRQ */
+ snd_azf3328_codec_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x00);
+
+- synchronize_irq(chip->irq);
++ if (chip->irq >= 0)
++ synchronize_irq(chip->irq);
+ __end_hw:
+ snd_azf3328_free_joystick(chip);
+ if (chip->irq >= 0)
+diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
+index 176e0f0..ecbe79b 100644
+--- a/sound/pci/ca0106/ca0106_main.c
++++ b/sound/pci/ca0106/ca0106_main.c
+@@ -435,22 +435,22 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu,
+ static void snd_ca0106_intr_enable(struct snd_ca0106 *emu, unsigned int intrenb)
+ {
+ unsigned long flags;
+- unsigned int enable;
+-
++ unsigned int intr_enable;
++
+ spin_lock_irqsave(&emu->emu_lock, flags);
+- enable = inl(emu->port + INTE) | intrenb;
+- outl(enable, emu->port + INTE);
++ intr_enable = inl(emu->port + INTE) | intrenb;
++ outl(intr_enable, emu->port + INTE);
+ spin_unlock_irqrestore(&emu->emu_lock, flags);
+ }
+
+ static void snd_ca0106_intr_disable(struct snd_ca0106 *emu, unsigned int intrenb)
+ {
+ unsigned long flags;
+- unsigned int enable;
+-
++ unsigned int intr_enable;
++
+ spin_lock_irqsave(&emu->emu_lock, flags);
+- enable = inl(emu->port + INTE) & ~intrenb;
+- outl(enable, emu->port + INTE);
++ intr_enable = inl(emu->port + INTE) & ~intrenb;
++ outl(intr_enable, emu->port + INTE);
+ spin_unlock_irqrestore(&emu->emu_lock, flags);
+ }
+
+@@ -1114,6 +1114,8 @@ static int snd_ca0106_free(struct snd_ca0106 *chip)
+ * So we can fix: snd-malloc: Memory leak? pages not freed = 8
+ */
+ }
++ if (chip->irq >= 0)
++ free_irq(chip->irq, chip);
+ // release the data
+ #if 1
+ if (chip->buffer.area)
+@@ -1123,9 +1125,6 @@ static int snd_ca0106_free(struct snd_ca0106 *chip)
+ // release the i/o port
+ release_and_free_resource(chip->res_port);
+
+- // release the irq
+- if (chip->irq >= 0)
+- free_irq(chip->irq, chip);
+ pci_disable_device(chip->pci);
+ kfree(chip);
+ return 0;
+diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
+index af73686..3025ed1 100644
+--- a/sound/pci/ca0106/ca0106_mixer.c
++++ b/sound/pci/ca0106/ca0106_mixer.c
+@@ -650,19 +650,55 @@ static int __devinit rename_ctl(struct snd_card *card, const char *src, const ch
+
+ #define ADD_CTLS(emu, ctls) \
+ do { \
+- int i, err; \
++ int i, _err; \
+ for (i = 0; i < ARRAY_SIZE(ctls); i++) { \
+- err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \
+- if (err < 0) \
+- return err; \
++ _err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \
++ if (_err < 0) \
++ return _err; \
+ } \
+ } while (0)
+
++static __devinitdata
++DECLARE_TLV_DB_SCALE(snd_ca0106_master_db_scale, -6375, 50, 1);
++
++static char *slave_vols[] __devinitdata = {
++ "Analog Front Playback Volume",
++ "Analog Rear Playback Volume",
++ "Analog Center/LFE Playback Volume",
++ "Analog Side Playback Volume",
++ "IEC958 Front Playback Volume",
++ "IEC958 Rear Playback Volume",
++ "IEC958 Center/LFE Playback Volume",
++ "IEC958 Unknown Playback Volume",
++ "CAPTURE feedback Playback Volume",
++ NULL
++};
++
++static char *slave_sws[] __devinitdata = {
++ "Analog Front Playback Switch",
++ "Analog Rear Playback Switch",
++ "Analog Center/LFE Playback Switch",
++ "Analog Side Playback Switch",
++ "IEC958 Playback Switch",
++ NULL
++};
++
++static void __devinit add_slaves(struct snd_card *card,
++ struct snd_kcontrol *master, char **list)
++{
++ for (; *list; list++) {
++ struct snd_kcontrol *slave = ctl_find(card, *list);
++ if (slave)
++ snd_ctl_add_slave(master, slave);
++ }
++}
++
+ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
+ {
+ int err;
+ struct snd_card *card = emu->card;
+ char **c;
++ struct snd_kcontrol *vmaster;
+ static char *ca0106_remove_ctls[] = {
+ "Master Mono Playback Switch",
+ "Master Mono Playback Volume",
+@@ -719,6 +755,21 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
+ }
+ if (emu->details->spi_dac == 1)
+ ADD_CTLS(emu, snd_ca0106_volume_spi_dac_ctls);
++
++ /* Create virtual master controls */
++ vmaster = snd_ctl_make_virtual_master("Master Playback Volume",
++ snd_ca0106_master_db_scale);
++ if (!vmaster)
++ return -ENOMEM;
++ add_slaves(card, vmaster, slave_vols);
++
++ if (emu->details->spi_dac == 1) {
++ vmaster = snd_ctl_make_virtual_master("Master Playback Switch",
++ NULL);
++ if (!vmaster)
++ return -ENOMEM;
++ add_slaves(card, vmaster, slave_sws);
++ }
+ return 0;
+ }
+
+diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
+index 135f308..9971b5b 100644
+--- a/sound/pci/cmipci.c
++++ b/sound/pci/cmipci.c
+@@ -2744,12 +2744,13 @@ static int __devinit snd_cmipci_mixer_new(struct cmipci *cm, int pcm_spdif_devic
+ }
+
+ for (idx = 0; idx < CM_SAVED_MIXERS; idx++) {
+- struct snd_ctl_elem_id id;
++ struct snd_ctl_elem_id elem_id;
+ struct snd_kcontrol *ctl;
+- memset(&id, 0, sizeof(id));
+- id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+- strcpy(id.name, cm_saved_mixer[idx].name);
+- if ((ctl = snd_ctl_find_id(cm->card, &id)) != NULL)
++ memset(&elem_id, 0, sizeof(elem_id));
++ elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
++ strcpy(elem_id.name, cm_saved_mixer[idx].name);
++ ctl = snd_ctl_find_id(cm->card, &elem_id);
++ if (ctl)
+ cm->mixer_res_ctl[idx] = ctl;
+ }
+
+@@ -2932,8 +2933,6 @@ static int snd_cmipci_free(struct cmipci *cm)
+ /* reset mixer */
+ snd_cmipci_mixer_write(cm, 0, 0);
+
+- synchronize_irq(cm->irq);
+-
+ free_irq(cm->irq, cm);
+ }
+
+diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
+index 87ddffc..e214e56 100644
+--- a/sound/pci/cs46xx/cs46xx_lib.c
++++ b/sound/pci/cs46xx/cs46xx_lib.c
+@@ -2772,6 +2772,9 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip)
+ if (chip->irq >= 0)
+ free_irq(chip->irq, chip);
+
++ if (chip->active_ctrl)
++ chip->active_ctrl(chip, -chip->amplifier);
++
+ for (idx = 0; idx < 5; idx++) {
+ struct snd_cs46xx_region *region = &chip->region.idx[idx];
+ if (region->remap_addr)
+@@ -2779,9 +2782,6 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip)
+ release_and_free_resource(region->resource);
+ }
+
+- if (chip->active_ctrl)
+- chip->active_ctrl(chip, -chip->amplifier);
+-
+ #ifdef CONFIG_SND_CS46XX_NEW_DSP
+ if (chip->dsp_spos_instance) {
+ cs46xx_dsp_spos_destroy(chip);
+diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
+index 90ec090..e16dc92 100644
+--- a/sound/pci/echoaudio/echoaudio.c
++++ b/sound/pci/echoaudio/echoaudio.c
+@@ -1852,15 +1852,16 @@ static irqreturn_t snd_echo_interrupt(int irq, void *dev_id)
+ static int snd_echo_free(struct echoaudio *chip)
+ {
+ DE_INIT(("Stop DSP...\n"));
+- if (chip->comm_page) {
++ if (chip->comm_page)
+ rest_in_peace(chip);
+- snd_dma_free_pages(&chip->commpage_dma_buf);
+- }
+ DE_INIT(("Stopped.\n"));
+
+ if (chip->irq >= 0)
+ free_irq(chip->irq, chip);
+
++ if (chip->comm_page)
++ snd_dma_free_pages(&chip->commpage_dma_buf);
++
+ if (chip->dsp_registers)
+ iounmap(chip->dsp_registers);
+
+diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
+index 9a9b977..abde5b9 100644
+--- a/sound/pci/emu10k1/emu10k1_main.c
++++ b/sound/pci/emu10k1/emu10k1_main.c
+@@ -1249,11 +1249,6 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
+ if (emu->port) { /* avoid access to already used hardware */
+ snd_emu10k1_fx8010_tram_setup(emu, 0);
+ snd_emu10k1_done(emu);
+- /* remove reserved page */
+- if (emu->reserved_page) {
+- snd_emu10k1_synth_free(emu, (struct snd_util_memblk *)emu->reserved_page);
+- emu->reserved_page = NULL;
+- }
+ snd_emu10k1_free_efx(emu);
+ }
+ if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010) {
+@@ -1262,6 +1257,14 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
+ }
+ if (emu->emu1010.firmware_thread)
+ kthread_stop(emu->emu1010.firmware_thread);
++ if (emu->irq >= 0)
++ free_irq(emu->irq, emu);
++ /* remove reserved page */
++ if (emu->reserved_page) {
++ snd_emu10k1_synth_free(emu,
++ (struct snd_util_memblk *)emu->reserved_page);
++ emu->reserved_page = NULL;
++ }
+ if (emu->memhdr)
+ snd_util_memhdr_free(emu->memhdr);
+ if (emu->silent_page.area)
+@@ -1273,8 +1276,6 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
+ #ifdef CONFIG_PM
+ free_pm_buffer(emu);
+ #endif
+- if (emu->irq >= 0)
+- free_irq(emu->irq, emu);
+ if (emu->port)
+ pci_release_regions(emu->pci);
+ if (emu->card_capabilities->ca0151_chip) /* P16V */
+diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
+index 5512abd..491a4a5 100644
+--- a/sound/pci/emu10k1/emu10k1x.c
++++ b/sound/pci/emu10k1/emu10k1x.c
+@@ -327,22 +327,22 @@ static void snd_emu10k1x_ptr_write(struct emu10k1x *emu,
+ static void snd_emu10k1x_intr_enable(struct emu10k1x *emu, unsigned int intrenb)
+ {
+ unsigned long flags;
+- unsigned int enable;
+-
++ unsigned int intr_enable;
++
+ spin_lock_irqsave(&emu->emu_lock, flags);
+- enable = inl(emu->port + INTE) | intrenb;
+- outl(enable, emu->port + INTE);
++ intr_enable = inl(emu->port + INTE) | intrenb;
++ outl(intr_enable, emu->port + INTE);
+ spin_unlock_irqrestore(&emu->emu_lock, flags);
+ }
+
+ static void snd_emu10k1x_intr_disable(struct emu10k1x *emu, unsigned int intrenb)
+ {
+ unsigned long flags;
+- unsigned int enable;
+-
++ unsigned int intr_enable;
++
+ spin_lock_irqsave(&emu->emu_lock, flags);
+- enable = inl(emu->port + INTE) & ~intrenb;
+- outl(enable, emu->port + INTE);
++ intr_enable = inl(emu->port + INTE) & ~intrenb;
++ outl(intr_enable, emu->port + INTE);
+ spin_unlock_irqrestore(&emu->emu_lock, flags);
+ }
+
+@@ -754,13 +754,13 @@ static int snd_emu10k1x_free(struct emu10k1x *chip)
+ // disable audio
+ outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG);
+
+- // release the i/o port
+- release_and_free_resource(chip->res_port);
+-
+- // release the irq
++ /* release the irq */
+ if (chip->irq >= 0)
+ free_irq(chip->irq, chip);
+
++ // release the i/o port
++ release_and_free_resource(chip->res_port);
++
+ // release the DMA
+ if (chip->dma_buffer.area) {
+ snd_dma_free_pages(&chip->dma_buffer);
+@@ -795,9 +795,9 @@ static irqreturn_t snd_emu10k1x_interrupt(int irq, void *dev_id)
+
+ // capture interrupt
+ if (status & (IPR_CAP_0_LOOP | IPR_CAP_0_HALF_LOOP)) {
+- struct emu10k1x_voice *pvoice = &chip->capture_voice;
+- if (pvoice->use)
+- snd_emu10k1x_pcm_interrupt(chip, pvoice);
++ struct emu10k1x_voice *cap_voice = &chip->capture_voice;
++ if (cap_voice->use)
++ snd_emu10k1x_pcm_interrupt(chip, cap_voice);
+ else
+ snd_emu10k1x_intr_disable(chip,
+ INTE_CAP_0_LOOP |
+diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c
+index f3caa3f..216f974 100644
+--- a/sound/pci/emu10k1/emuproc.c
++++ b/sound/pci/emu10k1/emuproc.c
+@@ -412,7 +412,7 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
+ {
+ struct snd_emu10k1 *emu = entry->private_data;
+- int value;
++ u32 value;
+ unsigned long flags;
+ int i;
+ snd_iprintf(buffer, "EMU1010 Registers:\n\n");
+diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
+index 72d85a5..fbf1124 100644
+--- a/sound/pci/ens1370.c
++++ b/sound/pci/ens1370.c
+@@ -1635,20 +1635,20 @@ static int __devinit snd_ensoniq_1371_mixer(struct ensoniq *ensoniq,
+ if (has_spdif > 0 ||
+ (!has_spdif && es1371_quirk_lookup(ensoniq, es1371_spdif_present))) {
+ struct snd_kcontrol *kctl;
+- int i, index = 0;
++ int i, is_spdif = 0;
+
+ ensoniq->spdif_default = ensoniq->spdif_stream =
+ SNDRV_PCM_DEFAULT_CON_SPDIF;
+ outl(ensoniq->spdif_default, ES_REG(ensoniq, CHANNEL_STATUS));
+
+ if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SPDIF)
+- index++;
++ is_spdif++;
+
+ for (i = 0; i < ARRAY_SIZE(snd_es1371_mixer_spdif); i++) {
+ kctl = snd_ctl_new1(&snd_es1371_mixer_spdif[i], ensoniq);
+ if (!kctl)
+ return -ENOMEM;
+- kctl->id.index = index;
++ kctl->id.index = is_spdif;
+ err = snd_ctl_add(card, kctl);
+ if (err < 0)
+ return err;
+@@ -1910,7 +1910,8 @@ static int snd_ensoniq_free(struct ensoniq *ensoniq)
+ outl(0, ES_REG(ensoniq, CONTROL)); /* switch everything off */
+ outl(0, ES_REG(ensoniq, SERIAL)); /* clear serial interface */
+ #endif
+- synchronize_irq(ensoniq->irq);
++ if (ensoniq->irq >= 0)
++ synchronize_irq(ensoniq->irq);
+ pci_set_power_state(ensoniq->pci, 3);
+ __hw_end:
+ #ifdef CHIP1370
+diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
+index 1a314fa..84fac1f 100644
+--- a/sound/pci/es1938.c
++++ b/sound/pci/es1938.c
+@@ -1488,7 +1488,6 @@ static int es1938_suspend(struct pci_dev *pci, pm_message_t state)
+
+ outb(0x00, SLIO_REG(chip, IRQCONTROL)); /* disable irqs */
+ if (chip->irq >= 0) {
+- synchronize_irq(chip->irq);
+ free_irq(chip->irq, chip);
+ chip->irq = -1;
+ }
+@@ -1578,10 +1577,8 @@ static int snd_es1938_free(struct es1938 *chip)
+
+ snd_es1938_free_gameport(chip);
+
+- if (chip->irq >= 0) {
+- synchronize_irq(chip->irq);
++ if (chip->irq >= 0)
+ free_irq(chip->irq, chip);
+- }
+ pci_release_regions(chip->pci);
+ pci_disable_device(chip->pci);
+ kfree(chip);
+diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
+index 7d911a1..1bf298d 100644
+--- a/sound/pci/es1968.c
++++ b/sound/pci/es1968.c
+@@ -1827,6 +1827,22 @@ snd_es1968_pcm(struct es1968 *chip, int device)
+
+ return 0;
+ }
++/*
++ * suppress jitter on some maestros when playing stereo
++ */
++static void snd_es1968_suppress_jitter(struct es1968 *chip, struct esschan *es)
++{
++ unsigned int cp1;
++ unsigned int cp2;
++ unsigned int diff;
++
++ cp1 = __apu_get_register(chip, 0, 5);
++ cp2 = __apu_get_register(chip, 1, 5);
++ diff = (cp1 > cp2 ? cp1 - cp2 : cp2 - cp1);
++
++ if (diff > 1)
++ __maestro_write(chip, IDR0_DATA_PORT, cp1);
++}
+
+ /*
+ * update pointer
+@@ -1948,8 +1964,11 @@ static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id)
+ struct esschan *es;
+ spin_lock(&chip->substream_lock);
+ list_for_each_entry(es, &chip->substream_list, list) {
+- if (es->running)
++ if (es->running) {
+ snd_es1968_update_pcm(chip, es);
++ if (es->fmt & ESS_FMT_STEREO)
++ snd_es1968_suppress_jitter(chip, es);
++ }
+ }
+ spin_unlock(&chip->substream_lock);
+ if (chip->in_measurement) {
+@@ -1972,7 +1991,7 @@ snd_es1968_mixer(struct es1968 *chip)
+ {
+ struct snd_ac97_bus *pbus;
+ struct snd_ac97_template ac97;
+- struct snd_ctl_elem_id id;
++ struct snd_ctl_elem_id elem_id;
+ int err;
+ static struct snd_ac97_bus_ops ops = {
+ .write = snd_es1968_ac97_write,
+@@ -1989,14 +2008,14 @@ snd_es1968_mixer(struct es1968 *chip)
+ return err;
+
+ /* attach master switch / volumes for h/w volume control */
+- memset(&id, 0, sizeof(id));
+- id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+- strcpy(id.name, "Master Playback Switch");
+- chip->master_switch = snd_ctl_find_id(chip->card, &id);
+- memset(&id, 0, sizeof(id));
+- id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+- strcpy(id.name, "Master Playback Volume");
+- chip->master_volume = snd_ctl_find_id(chip->card, &id);
++ memset(&elem_id, 0, sizeof(elem_id));
++ elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
++ strcpy(elem_id.name, "Master Playback Switch");
++ chip->master_switch = snd_ctl_find_id(chip->card, &elem_id);
++ memset(&elem_id, 0, sizeof(elem_id));
++ elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
++ strcpy(elem_id.name, "Master Playback Volume");
++ chip->master_volume = snd_ctl_find_id(chip->card, &elem_id);
+
+ return 0;
+ }
+@@ -2456,7 +2475,8 @@ static inline void snd_es1968_free_gameport(struct es1968 *chip) { }
+ static int snd_es1968_free(struct es1968 *chip)
+ {
+ if (chip->io_port) {
+- synchronize_irq(chip->irq);
++ if (chip->irq >= 0)
++ synchronize_irq(chip->irq);
+ outw(1, chip->io_port + 0x04); /* clear WP interrupts */
+ outw(0, chip->io_port + ESM_PORT_HOST_IRQ); /* disable IRQ */
+ }
+diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
+index 4c300e6..c129f9e 100644
+--- a/sound/pci/fm801.c
++++ b/sound/pci/fm801.c
+@@ -1285,7 +1285,6 @@ static int wait_for_codec(struct fm801 *chip, unsigned int codec_id,
+
+ static int snd_fm801_chip_init(struct fm801 *chip, int resume)
+ {
+- int id;
+ unsigned short cmdw;
+
+ if (chip->tea575x_tuner & 0x0010)
+@@ -1310,13 +1309,14 @@ static int snd_fm801_chip_init(struct fm801 *chip, int resume)
+ } else {
+ /* my card has the secondary codec */
+ /* at address #3, so the loop is inverted */
+- for (id = 3; id > 0; id--) {
+- if (! wait_for_codec(chip, id, AC97_VENDOR_ID1,
++ int i;
++ for (i = 3; i > 0; i--) {
++ if (!wait_for_codec(chip, i, AC97_VENDOR_ID1,
+ msecs_to_jiffies(50))) {
+ cmdw = inw(FM801_REG(chip, AC97_DATA));
+ if (cmdw != 0xffff && cmdw != 0) {
+ chip->secondary = 1;
+- chip->secondary_addr = id;
++ chip->secondary_addr = i;
+ break;
+ }
+ }
+diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
+index 9e0d8a1..ab0c726 100644
+--- a/sound/pci/hda/Makefile
++++ b/sound/pci/hda/Makefile
+@@ -2,7 +2,7 @@ snd-hda-intel-y := hda_intel.o
+ # since snd-hda-intel is the only driver using hda-codec,
+ # merge it into a single module although it was originally
+ # designed to be individual modules
+-snd-hda-intel-y += hda_codec.o vmaster.o
++snd-hda-intel-y += hda_codec.o
+ snd-hda-intel-$(CONFIG_PROC_FS) += hda_proc.o
+ snd-hda-intel-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
+ snd-hda-intel-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o
+diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
+index 37c4139..a6be6e3 100644
+--- a/sound/pci/hda/hda_codec.c
++++ b/sound/pci/hda/hda_codec.c
+@@ -31,6 +31,7 @@
+ #include <sound/initval.h>
+ #include "hda_local.h"
+ #include <sound/hda_hwdep.h>
++#include "hda_patch.h" /* codec presets */
+
+ #ifdef CONFIG_SND_HDA_POWER_SAVE
+ /* define this option here to hide as static */
+@@ -51,21 +52,50 @@ struct hda_vendor_id {
+
+ /* codec vendor labels */
+ static struct hda_vendor_id hda_vendor_ids[] = {
+- { 0x10ec, "Realtek" },
++ { 0x1002, "ATI" },
+ { 0x1057, "Motorola" },
++ { 0x1095, "Silicon Image" },
++ { 0x10ec, "Realtek" },
+ { 0x1106, "VIA" },
+ { 0x111d, "IDT" },
++ { 0x11c1, "LSI" },
+ { 0x11d4, "Analog Devices" },
+ { 0x13f6, "C-Media" },
+ { 0x14f1, "Conexant" },
++ { 0x17e8, "Chrontel" },
++ { 0x1854, "LG" },
+ { 0x434d, "C-Media" },
+ { 0x8384, "SigmaTel" },
+ {} /* terminator */
+ };
+
+-/* codec presets */
+-#include "hda_patch.h"
+-
++static const struct hda_codec_preset *hda_preset_tables[] = {
++#ifdef CONFIG_SND_HDA_CODEC_REALTEK
++ snd_hda_preset_realtek,
++#endif
++#ifdef CONFIG_SND_HDA_CODEC_CMEDIA
++ snd_hda_preset_cmedia,
++#endif
++#ifdef CONFIG_SND_HDA_CODEC_ANALOG
++ snd_hda_preset_analog,
++#endif
++#ifdef CONFIG_SND_HDA_CODEC_SIGMATEL
++ snd_hda_preset_sigmatel,
++#endif
++#ifdef CONFIG_SND_HDA_CODEC_SI3054
++ snd_hda_preset_si3054,
++#endif
++#ifdef CONFIG_SND_HDA_CODEC_ATIHDMI
++ snd_hda_preset_atihdmi,
++#endif
++#ifdef CONFIG_SND_HDA_CODEC_CONEXANT
++ snd_hda_preset_conexant,
++#endif
++#ifdef CONFIG_SND_HDA_CODEC_VIA
++ snd_hda_preset_via,
++#endif
++ NULL
++};
+
+ #ifdef CONFIG_SND_HDA_POWER_SAVE
+ static void hda_power_work(struct work_struct *work);
+@@ -690,6 +720,19 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
+ }
+
++void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
++{
++ if (!nid)
++ return;
++
++ snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
++ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
++#if 0 /* keep the format */
++ msleep(1);
++ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
++#endif
++}
++
+ /*
+ * amp access functions
+ */
+@@ -1037,16 +1080,24 @@ void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
+ }
+
+ /* find a mixer control element with the given name */
+-struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
+- const char *name)
++static struct snd_kcontrol *
++_snd_hda_find_mixer_ctl(struct hda_codec *codec,
++ const char *name, int idx)
+ {
+ struct snd_ctl_elem_id id;
+ memset(&id, 0, sizeof(id));
+ id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
++ id.index = idx;
+ strcpy(id.name, name);
+ return snd_ctl_find_id(codec->bus->card, &id);
+ }
+
++struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
++ const char *name)
++{
++ return _snd_hda_find_mixer_ctl(codec, name, 0);
++}
++
+ /* create a virtual master control and add slaves */
+ int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
+ unsigned int *tlv, const char **slaves)
+@@ -1481,6 +1532,8 @@ static struct snd_kcontrol_new dig_mixes[] = {
+ { } /* end */
+ };
+
++#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */
++
+ /**
+ * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
+ * @codec: the HDA codec
+@@ -1496,9 +1549,20 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
+ int err;
+ struct snd_kcontrol *kctl;
+ struct snd_kcontrol_new *dig_mix;
++ int idx;
+
++ for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
++ if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
++ idx))
++ break;
++ }
++ if (idx >= SPDIF_MAX_IDX) {
++ printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
++ return -EBUSY;
++ }
+ for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
+ kctl = snd_ctl_new1(dig_mix, codec);
++ kctl->id.index = idx;
+ kctl->private_value = nid;
+ err = snd_ctl_add(codec->bus->card, kctl);
+ if (err < 0)
+@@ -1512,6 +1576,43 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
+ }
+
+ /*
++ * SPDIF sharing with analog output
++ */
++static int spdif_share_sw_get(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
++ ucontrol->value.integer.value[0] = mout->share_spdif;
++ return 0;
++}
++
++static int spdif_share_sw_put(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol);
++ mout->share_spdif = !!ucontrol->value.integer.value[0];
++ return 0;
++}
++
++static struct snd_kcontrol_new spdif_share_sw = {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "IEC958 Default PCM Playback Switch",
++ .info = snd_ctl_boolean_mono_info,
++ .get = spdif_share_sw_get,
++ .put = spdif_share_sw_put,
++};
++
++int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
++ struct hda_multi_out *mout)
++{
++ if (!mout->dig_out_nid)
++ return 0;
++ /* ATTENTION: here mout is passed as private_data, instead of codec */
++ return snd_ctl_add(codec->bus->card,
++ snd_ctl_new1(&spdif_share_sw, mout));
++}
++
++/*
+ * SPDIF input
+ */
+
+@@ -1595,7 +1696,17 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
+ int err;
+ struct snd_kcontrol *kctl;
+ struct snd_kcontrol_new *dig_mix;
++ int idx;
+
++ for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
++ if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
++ idx))
++ break;
++ }
++ if (idx >= SPDIF_MAX_IDX) {
++ printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
++ return -EBUSY;
++ }
+ for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
+ kctl = snd_ctl_new1(dig_mix, codec);
+ kctl->private_value = nid;
+@@ -2106,7 +2217,7 @@ static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ struct snd_pcm_substream *substream)
+ {
+- snd_hda_codec_setup_stream(codec, hinfo->nid, 0, 0, 0);
++ snd_hda_codec_cleanup_stream(codec, hinfo->nid);
+ return 0;
+ }
+
+@@ -2491,7 +2602,7 @@ int snd_hda_multi_out_dig_open(struct hda_codec *codec,
+ mutex_lock(&codec->spdif_mutex);
+ if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
+ /* already opened as analog dup; reset it once */
+- snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0);
++ snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid);
+ mout->dig_out_used = HDA_DIG_EXCLUSIVE;
+ mutex_unlock(&codec->spdif_mutex);
+ return 0;
+@@ -2526,9 +2637,36 @@ int snd_hda_multi_out_dig_close(struct hda_codec *codec,
+ */
+ int snd_hda_multi_out_analog_open(struct hda_codec *codec,
+ struct hda_multi_out *mout,
+- struct snd_pcm_substream *substream)
+-{
+- substream->runtime->hw.channels_max = mout->max_channels;
++ struct snd_pcm_substream *substream,
++ struct hda_pcm_stream *hinfo)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ runtime->hw.channels_max = mout->max_channels;
++ if (mout->dig_out_nid) {
++ if (!mout->analog_rates) {
++ mout->analog_rates = hinfo->rates;
++ mout->analog_formats = hinfo->formats;
++ mout->analog_maxbps = hinfo->maxbps;
++ } else {
++ runtime->hw.rates = mout->analog_rates;
++ runtime->hw.formats = mout->analog_formats;
++ hinfo->maxbps = mout->analog_maxbps;
++ }
++ if (!mout->spdif_rates) {
++ snd_hda_query_supported_pcm(codec, mout->dig_out_nid,
++ &mout->spdif_rates,
++ &mout->spdif_formats,
++ &mout->spdif_maxbps);
++ }
++ mutex_lock(&codec->spdif_mutex);
++ if (mout->share_spdif) {
++ runtime->hw.rates &= mout->spdif_rates;
++ runtime->hw.formats &= mout->spdif_formats;
++ if (mout->spdif_maxbps < hinfo->maxbps)
++ hinfo->maxbps = mout->spdif_maxbps;
++ }
++ mutex_unlock(&codec->spdif_mutex);
++ }
+ return snd_pcm_hw_constraint_step(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS, 2);
+ }
+@@ -2548,7 +2686,8 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
+ int i;
+
+ mutex_lock(&codec->spdif_mutex);
+- if (mout->dig_out_nid && mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
++ if (mout->dig_out_nid && mout->share_spdif &&
++ mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
+ if (chs == 2 &&
+ snd_hda_is_supported_format(codec, mout->dig_out_nid,
+ format) &&
+@@ -2558,8 +2697,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
+ stream_tag, format);
+ } else {
+ mout->dig_out_used = 0;
+- snd_hda_codec_setup_stream(codec, mout->dig_out_nid,
+- 0, 0, 0);
++ snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid);
+ }
+ }
+ mutex_unlock(&codec->spdif_mutex);
+@@ -2601,17 +2739,16 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
+ int i;
+
+ for (i = 0; i < mout->num_dacs; i++)
+- snd_hda_codec_setup_stream(codec, nids[i], 0, 0, 0);
++ snd_hda_codec_cleanup_stream(codec, nids[i]);
+ if (mout->hp_nid)
+- snd_hda_codec_setup_stream(codec, mout->hp_nid, 0, 0, 0);
++ snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
+ for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
+ if (mout->extra_out_nid[i])
+- snd_hda_codec_setup_stream(codec,
+- mout->extra_out_nid[i],
+- 0, 0, 0);
++ snd_hda_codec_cleanup_stream(codec,
++ mout->extra_out_nid[i]);
+ mutex_lock(&codec->spdif_mutex);
+ if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
+- snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0);
++ snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid);
+ mout->dig_out_used = 0;
+ }
+ mutex_unlock(&codec->spdif_mutex);
+@@ -2790,6 +2927,30 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
+ }
+ }
+
++ /* FIX-UP:
++ * If no line-out is defined but multiple HPs are found,
++ * some of them might be the real line-outs.
++ */
++ if (!cfg->line_outs && cfg->hp_outs > 1) {
++ int i = 0;
++ while (i < cfg->hp_outs) {
++ /* The real HPs should have the sequence 0x0f */
++ if ((sequences_hp[i] & 0x0f) == 0x0f) {
++ i++;
++ continue;
++ }
++ /* Move it to the line-out table */
++ cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i];
++ sequences_line_out[cfg->line_outs] = sequences_hp[i];
++ cfg->line_outs++;
++ cfg->hp_outs--;
++ memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1,
++ sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i));
++ memmove(sequences_hp + i - 1, sequences_hp + i,
++ sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
++ }
++ }
++
+ /* sort by sequence */
+ sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
+ cfg->line_outs);
+diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
+index f148711..dcd390b 100644
+--- a/sound/pci/hda/hda_codec.h
++++ b/sound/pci/hda/hda_codec.h
+@@ -590,11 +590,21 @@ struct hda_pcm_stream {
+ struct hda_pcm_ops ops;
+ };
+
++/* PCM types */
++enum {
++ HDA_PCM_TYPE_AUDIO,
++ HDA_PCM_TYPE_SPDIF,
++ HDA_PCM_TYPE_HDMI,
++ HDA_PCM_TYPE_MODEM,
++ HDA_PCM_NTYPES
++};
++
+ /* for PCM creation */
+ struct hda_pcm {
+ char *name;
+ struct hda_pcm_stream stream[2];
+- unsigned int is_modem; /* modem codec? */
++ unsigned int pcm_type; /* HDA_PCM_TYPE_XXX */
++ int device; /* assigned device number */
+ };
+
+ /* codec information */
+@@ -712,6 +722,7 @@ int snd_hda_build_pcms(struct hda_bus *bus);
+ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
+ u32 stream_tag,
+ int channel_id, int format);
++void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid);
+ unsigned int snd_hda_calc_stream_format(unsigned int rate,
+ unsigned int channels,
+ unsigned int format,
+diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
+index f9de7c4..59e4389 100644
+--- a/sound/pci/hda/hda_generic.c
++++ b/sound/pci/hda/hda_generic.c
+@@ -1007,8 +1007,8 @@ static int generic_pcm2_cleanup(struct hda_pcm_stream *hinfo,
+ {
+ struct hda_gspec *spec = codec->spec;
+
+- snd_hda_codec_setup_stream(codec, hinfo->nid, 0, 0, 0);
+- snd_hda_codec_setup_stream(codec, spec->dac_node[1]->nid, 0, 0, 0);
++ snd_hda_codec_cleanup_stream(codec, hinfo->nid);
++ snd_hda_codec_cleanup_stream(codec, spec->dac_node[1]->nid);
+ return 0;
+ }
+
+diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
+index 4be36c8..b3a618e 100644
+--- a/sound/pci/hda/hda_intel.c
++++ b/sound/pci/hda/hda_intel.c
+@@ -39,6 +39,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
++#include <linux/dma-mapping.h>
+ #include <linux/moduleparam.h>
+ #include <linux/init.h>
+ #include <linux/slab.h>
+@@ -185,35 +186,28 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
+
+ /* max number of SDs */
+ /* ICH, ATI and VIA have 4 playback and 4 capture */
+-#define ICH6_CAPTURE_INDEX 0
+ #define ICH6_NUM_CAPTURE 4
+-#define ICH6_PLAYBACK_INDEX 4
+ #define ICH6_NUM_PLAYBACK 4
+
+ /* ULI has 6 playback and 5 capture */
+-#define ULI_CAPTURE_INDEX 0
+ #define ULI_NUM_CAPTURE 5
+-#define ULI_PLAYBACK_INDEX 5
+ #define ULI_NUM_PLAYBACK 6
+
+ /* ATI HDMI has 1 playback and 0 capture */
+-#define ATIHDMI_CAPTURE_INDEX 0
+ #define ATIHDMI_NUM_CAPTURE 0
+-#define ATIHDMI_PLAYBACK_INDEX 0
+ #define ATIHDMI_NUM_PLAYBACK 1
+
+ /* this number is statically defined for simplicity */
+ #define MAX_AZX_DEV 16
+
+ /* max number of fragments - we may use more if allocating more pages for BDL */
+-#define BDL_SIZE PAGE_ALIGN(8192)
+-#define AZX_MAX_FRAG (BDL_SIZE / (MAX_AZX_DEV * 16))
++#define BDL_SIZE 4096
++#define AZX_MAX_BDL_ENTRIES (BDL_SIZE / 16)
++#define AZX_MAX_FRAG 32
+ /* max buffer size - no h/w limit, you can increase as you like */
+ #define AZX_MAX_BUF_SIZE (1024*1024*1024)
+ /* max number of PCM devics per card */
+-#define AZX_MAX_AUDIO_PCMS 6
+-#define AZX_MAX_MODEM_PCMS 2
+-#define AZX_MAX_PCMS (AZX_MAX_AUDIO_PCMS + AZX_MAX_MODEM_PCMS)
++#define AZX_MAX_PCMS 8
+
+ /* RIRB int mask: overrun[2], response[0] */
+ #define RIRB_INT_RESPONSE 0x01
+@@ -227,6 +221,9 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
+ /* SD_CTL bits */
+ #define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */
+ #define SD_CTL_DMA_START 0x02 /* stream DMA start bit */
++#define SD_CTL_STRIPE (3 << 16) /* stripe control */
++#define SD_CTL_TRAFFIC_PRIO (1 << 18) /* traffic priority */
++#define SD_CTL_DIR (1 << 19) /* bi-directional stream */
+ #define SD_CTL_STREAM_TAG_MASK (0xf << 20)
+ #define SD_CTL_STREAM_TAG_SHIFT 20
+
+@@ -284,12 +281,10 @@ enum {
+ */
+
+ struct azx_dev {
+- u32 *bdl; /* virtual address of the BDL */
+- dma_addr_t bdl_addr; /* physical address of the BDL */
++ struct snd_dma_buffer bdl; /* BDL buffer */
+ u32 *posbuf; /* position buffer pointer */
+
+ unsigned int bufsize; /* size of the play buffer in bytes */
+- unsigned int fragsize; /* size of each period in bytes */
+ unsigned int frags; /* number for period in the play buffer */
+ unsigned int fifo_size; /* FIFO size */
+
+@@ -350,7 +345,6 @@ struct azx {
+ struct azx_dev *azx_dev;
+
+ /* PCM */
+- unsigned int pcm_devs;
+ struct snd_pcm *pcm[AZX_MAX_PCMS];
+
+ /* HD codec */
+@@ -361,8 +355,7 @@ struct azx {
+ struct azx_rb corb;
+ struct azx_rb rirb;
+
+- /* BDL, CORB/RIRB and position buffers */
+- struct snd_dma_buffer bdl;
++ /* CORB/RIRB and position buffers */
+ struct snd_dma_buffer rb;
+ struct snd_dma_buffer posbuf;
+
+@@ -546,8 +539,9 @@ static void azx_update_rirb(struct azx *chip)
+ if (res_ex & ICH6_RIRB_EX_UNSOL_EV)
+ snd_hda_queue_unsol_event(chip->bus, res, res_ex);
+ else if (chip->rirb.cmds) {
+- chip->rirb.cmds--;
+ chip->rirb.res = res;
++ smp_wmb();
++ chip->rirb.cmds--;
+ }
+ }
+ }
+@@ -566,8 +560,10 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec)
+ azx_update_rirb(chip);
+ spin_unlock_irq(&chip->reg_lock);
+ }
+- if (!chip->rirb.cmds)
++ if (!chip->rirb.cmds) {
++ smp_rmb();
+ return chip->rirb.res; /* the last value */
++ }
+ if (time_after(jiffies, timeout))
+ break;
+ if (codec->bus->needs_damn_long_delay)
+@@ -965,30 +961,57 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
+ /*
+ * set up BDL entries
+ */
+-static void azx_setup_periods(struct azx_dev *azx_dev)
++static int azx_setup_periods(struct snd_pcm_substream *substream,
++ struct azx_dev *azx_dev)
+ {
+- u32 *bdl = azx_dev->bdl;
+- dma_addr_t dma_addr = azx_dev->substream->runtime->dma_addr;
+- int idx;
++ struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
++ u32 *bdl;
++ int i, ofs, periods, period_bytes;
+
+ /* reset BDL address */
+ azx_sd_writel(azx_dev, SD_BDLPL, 0);
+ azx_sd_writel(azx_dev, SD_BDLPU, 0);
+
++ period_bytes = snd_pcm_lib_period_bytes(substream);
++ periods = azx_dev->bufsize / period_bytes;
++
+ /* program the initial BDL entries */
+- for (idx = 0; idx < azx_dev->frags; idx++) {
+- unsigned int off = idx << 2; /* 4 dword step */
+- dma_addr_t addr = dma_addr + idx * azx_dev->fragsize;
+- /* program the address field of the BDL entry */
+- bdl[off] = cpu_to_le32((u32)addr);
+- bdl[off+1] = cpu_to_le32(upper_32bit(addr));
+-
+- /* program the size field of the BDL entry */
+- bdl[off+2] = cpu_to_le32(azx_dev->fragsize);
+-
+- /* program the IOC to enable interrupt when buffer completes */
+- bdl[off+3] = cpu_to_le32(0x01);
++ bdl = (u32 *)azx_dev->bdl.area;
++ ofs = 0;
++ azx_dev->frags = 0;
++ for (i = 0; i < periods; i++) {
++ int size, rest;
++ if (i >= AZX_MAX_BDL_ENTRIES) {
++ snd_printk(KERN_ERR "Too many BDL entries: "
++ "buffer=%d, period=%d\n",
++ azx_dev->bufsize, period_bytes);
++ /* reset */
++ azx_sd_writel(azx_dev, SD_BDLPL, 0);
++ azx_sd_writel(azx_dev, SD_BDLPU, 0);
++ return -EINVAL;
++ }
++ rest = period_bytes;
++ do {
++ dma_addr_t addr = snd_pcm_sgbuf_get_addr(sgbuf, ofs);
++ /* program the address field of the BDL entry */
++ bdl[0] = cpu_to_le32((u32)addr);
++ bdl[1] = cpu_to_le32(upper_32bit(addr));
++ /* program the size field of the BDL entry */
++ size = PAGE_SIZE - (ofs % PAGE_SIZE);
++ if (rest < size)
++ size = rest;
++ bdl[2] = cpu_to_le32(size);
++ /* program the IOC to enable interrupt
++ * only when the whole fragment is processed
++ */
++ rest -= size;
++ bdl[3] = rest ? 0 : cpu_to_le32(0x01);
++ bdl += 4;
++ azx_dev->frags++;
++ ofs += size;
++ } while (rest > 0);
+ }
++ return 0;
+ }
+
+ /*
+@@ -1037,14 +1060,17 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
+
+ /* program the BDL address */
+ /* lower BDL address */
+- azx_sd_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl_addr);
++ azx_sd_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl.addr);
+ /* upper BDL address */
+- azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr));
++ azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl.addr));
+
+ /* enable the position buffer */
+- if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
+- azx_writel(chip, DPLBASE,
+- (u32)chip->posbuf.addr |ICH6_DPLBASE_ENABLE);
++ if (chip->position_fix == POS_FIX_POSBUF ||
++ chip->position_fix == POS_FIX_AUTO) {
++ if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
++ azx_writel(chip, DPLBASE,
++ (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
++ }
+
+ /* set the interrupt enable bits in the descriptor control register */
+ azx_sd_writel(azx_dev, SD_CTL,
+@@ -1157,7 +1183,8 @@ static struct snd_pcm_hardware azx_pcm_hw = {
+ SNDRV_PCM_INFO_MMAP_VALID |
+ /* No full-resume yet implemented */
+ /* SNDRV_PCM_INFO_RESUME |*/
+- SNDRV_PCM_INFO_PAUSE),
++ SNDRV_PCM_INFO_PAUSE |
++ SNDRV_PCM_INFO_SYNC_START),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+@@ -1219,6 +1246,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+
+ runtime->private_data = azx_dev;
++ snd_pcm_set_sync(substream);
+ mutex_unlock(&chip->open_mutex);
+ return 0;
+ }
+@@ -1275,8 +1303,6 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ azx_dev->bufsize = snd_pcm_lib_buffer_bytes(substream);
+- azx_dev->fragsize = snd_pcm_lib_period_bytes(substream);
+- azx_dev->frags = azx_dev->bufsize / azx_dev->fragsize;
+ azx_dev->format_val = snd_hda_calc_stream_format(runtime->rate,
+ runtime->channels,
+ runtime->format,
+@@ -1288,10 +1314,10 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
+ return -EINVAL;
+ }
+
+- snd_printdd("azx_pcm_prepare: bufsize=0x%x, fragsize=0x%x, "
+- "format=0x%x\n",
+- azx_dev->bufsize, azx_dev->fragsize, azx_dev->format_val);
+- azx_setup_periods(azx_dev);
++ snd_printdd("azx_pcm_prepare: bufsize=0x%x, format=0x%x\n",
++ azx_dev->bufsize, azx_dev->format_val);
++ if (azx_setup_periods(substream, azx_dev) < 0)
++ return -EINVAL;
+ azx_setup_controller(chip, azx_dev);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1;
+@@ -1305,37 +1331,94 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
+ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+ {
+ struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
+- struct azx_dev *azx_dev = get_azx_dev(substream);
+ struct azx *chip = apcm->chip;
+- int err = 0;
++ struct azx_dev *azx_dev;
++ struct snd_pcm_substream *s;
++ int start, nsync = 0, sbits = 0;
++ int nwait, timeout;
+
+- spin_lock(&chip->reg_lock);
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_START:
+- azx_stream_start(chip, azx_dev);
+- azx_dev->running = 1;
++ start = 1;
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_STOP:
+- azx_stream_stop(chip, azx_dev);
+- azx_dev->running = 0;
++ start = 0;
+ break;
+ default:
+- err = -EINVAL;
++ return -EINVAL;
++ }
++
++ snd_pcm_group_for_each_entry(s, substream) {
++ if (s->pcm->card != substream->pcm->card)
++ continue;
++ azx_dev = get_azx_dev(s);
++ sbits |= 1 << azx_dev->index;
++ nsync++;
++ snd_pcm_trigger_done(s, substream);
++ }
++
++ spin_lock(&chip->reg_lock);
++ if (nsync > 1) {
++ /* first, set SYNC bits of corresponding streams */
++ azx_writel(chip, SYNC, azx_readl(chip, SYNC) | sbits);
++ }
++ snd_pcm_group_for_each_entry(s, substream) {
++ if (s->pcm->card != substream->pcm->card)
++ continue;
++ azx_dev = get_azx_dev(s);
++ if (start)
++ azx_stream_start(chip, azx_dev);
++ else
++ azx_stream_stop(chip, azx_dev);
++ azx_dev->running = start;
+ }
+ spin_unlock(&chip->reg_lock);
+- if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH ||
+- cmd == SNDRV_PCM_TRIGGER_SUSPEND ||
+- cmd == SNDRV_PCM_TRIGGER_STOP) {
+- int timeout = 5000;
+- while ((azx_sd_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START) &&
+- --timeout)
+- ;
++ if (start) {
++ if (nsync == 1)
++ return 0;
++ /* wait until all FIFOs get ready */
++ for (timeout = 5000; timeout; timeout--) {
++ nwait = 0;
++ snd_pcm_group_for_each_entry(s, substream) {
++ if (s->pcm->card != substream->pcm->card)
++ continue;
++ azx_dev = get_azx_dev(s);
++ if (!(azx_sd_readb(azx_dev, SD_STS) &
++ SD_STS_FIFO_READY))
++ nwait++;
++ }
++ if (!nwait)
++ break;
++ cpu_relax();
++ }
++ } else {
++ /* wait until all RUN bits are cleared */
++ for (timeout = 5000; timeout; timeout--) {
++ nwait = 0;
++ snd_pcm_group_for_each_entry(s, substream) {
++ if (s->pcm->card != substream->pcm->card)
++ continue;
++ azx_dev = get_azx_dev(s);
++ if (azx_sd_readb(azx_dev, SD_CTL) &
++ SD_CTL_DMA_START)
++ nwait++;
++ }
++ if (!nwait)
++ break;
++ cpu_relax();
++ }
+ }
+- return err;
++ if (nsync > 1) {
++ spin_lock(&chip->reg_lock);
++ /* reset SYNC bits */
++ azx_writel(chip, SYNC, azx_readl(chip, SYNC) & ~sbits);
++ spin_unlock(&chip->reg_lock);
++ }
++ return 0;
+ }
+
+ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
+@@ -1378,6 +1461,7 @@ static struct snd_pcm_ops azx_pcm_ops = {
+ .prepare = azx_pcm_prepare,
+ .trigger = azx_pcm_trigger,
+ .pointer = azx_pcm_pointer,
++ .page = snd_pcm_sgbuf_ops_page,
+ };
+
+ static void azx_pcm_free(struct snd_pcm *pcm)
+@@ -1386,7 +1470,7 @@ static void azx_pcm_free(struct snd_pcm *pcm)
+ }
+
+ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
+- struct hda_pcm *cpcm, int pcm_dev)
++ struct hda_pcm *cpcm)
+ {
+ int err;
+ struct snd_pcm *pcm;
+@@ -1400,7 +1484,7 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
+
+ snd_assert(cpcm->name, return -EINVAL);
+
+- err = snd_pcm_new(chip->card, cpcm->name, pcm_dev,
++ err = snd_pcm_new(chip->card, cpcm->name, cpcm->device,
+ cpcm->stream[0].substreams,
+ cpcm->stream[1].substreams,
+ &pcm);
+@@ -1420,62 +1504,70 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &azx_pcm_ops);
+ if (cpcm->stream[1].substreams)
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &azx_pcm_ops);
+- snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
++ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
+ snd_dma_pci_data(chip->pci),
+ 1024 * 64, 1024 * 1024);
+- chip->pcm[pcm_dev] = pcm;
+- if (chip->pcm_devs < pcm_dev + 1)
+- chip->pcm_devs = pcm_dev + 1;
+-
++ chip->pcm[cpcm->device] = pcm;
+ return 0;
+ }
+
+ static int __devinit azx_pcm_create(struct azx *chip)
+ {
++ static const char *dev_name[HDA_PCM_NTYPES] = {
++ "Audio", "SPDIF", "HDMI", "Modem"
++ };
++ /* starting device index for each PCM type */
++ static int dev_idx[HDA_PCM_NTYPES] = {
++ [HDA_PCM_TYPE_AUDIO] = 0,
++ [HDA_PCM_TYPE_SPDIF] = 1,
++ [HDA_PCM_TYPE_HDMI] = 3,
++ [HDA_PCM_TYPE_MODEM] = 6
++ };
++ /* normal audio device indices; not linear to keep compatibility */
++ static int audio_idx[4] = { 0, 2, 4, 5 };
+ struct hda_codec *codec;
+ int c, err;
+- int pcm_dev;
++ int num_devs[HDA_PCM_NTYPES];
+
+ err = snd_hda_build_pcms(chip->bus);
+ if (err < 0)
+ return err;
+
+ /* create audio PCMs */
+- pcm_dev = 0;
+- list_for_each_entry(codec, &chip->bus->codec_list, list) {
+- for (c = 0; c < codec->num_pcms; c++) {
+- if (codec->pcm_info[c].is_modem)
+- continue; /* create later */
+- if (pcm_dev >= AZX_MAX_AUDIO_PCMS) {
+- snd_printk(KERN_ERR SFX
+- "Too many audio PCMs\n");
+- return -EINVAL;
+- }
+- err = create_codec_pcm(chip, codec,
+- &codec->pcm_info[c], pcm_dev);
+- if (err < 0)
+- return err;
+- pcm_dev++;
+- }
+- }
+-
+- /* create modem PCMs */
+- pcm_dev = AZX_MAX_AUDIO_PCMS;
++ memset(num_devs, 0, sizeof(num_devs));
+ list_for_each_entry(codec, &chip->bus->codec_list, list) {
+ for (c = 0; c < codec->num_pcms; c++) {
+- if (!codec->pcm_info[c].is_modem)
+- continue; /* already created */
+- if (pcm_dev >= AZX_MAX_PCMS) {
+- snd_printk(KERN_ERR SFX
+- "Too many modem PCMs\n");
+- return -EINVAL;
++ struct hda_pcm *cpcm = &codec->pcm_info[c];
++ int type = cpcm->pcm_type;
++ switch (type) {
++ case HDA_PCM_TYPE_AUDIO:
++ if (num_devs[type] >= ARRAY_SIZE(audio_idx)) {
++ snd_printk(KERN_WARNING
++ "Too many audio devices\n");
++ continue;
++ }
++ cpcm->device = audio_idx[num_devs[type]];
++ break;
++ case HDA_PCM_TYPE_SPDIF:
++ case HDA_PCM_TYPE_HDMI:
++ case HDA_PCM_TYPE_MODEM:
++ if (num_devs[type]) {
++ snd_printk(KERN_WARNING
++ "%s already defined\n",
++ dev_name[type]);
++ continue;
++ }
++ cpcm->device = dev_idx[type];
++ break;
++ default:
++ snd_printk(KERN_WARNING
++ "Invalid PCM type %d\n", type);
++ continue;
+ }
+- err = create_codec_pcm(chip, codec,
+- &codec->pcm_info[c], pcm_dev);
++ num_devs[type]++;
++ err = create_codec_pcm(chip, codec, cpcm);
+ if (err < 0)
+ return err;
+- chip->pcm[pcm_dev]->dev_class = SNDRV_PCM_CLASS_MODEM;
+- pcm_dev++;
+ }
+ }
+ return 0;
+@@ -1502,10 +1594,7 @@ static int __devinit azx_init_stream(struct azx *chip)
+ * and initialize
+ */
+ for (i = 0; i < chip->num_streams; i++) {
+- unsigned int off = sizeof(u32) * (i * AZX_MAX_FRAG * 4);
+ struct azx_dev *azx_dev = &chip->azx_dev[i];
+- azx_dev->bdl = (u32 *)(chip->bdl.area + off);
+- azx_dev->bdl_addr = chip->bdl.addr + off;
+ azx_dev->posbuf = (u32 __iomem *)(chip->posbuf.area + i * 8);
+ /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
+ azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80);
+@@ -1587,13 +1676,12 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state)
+ int i;
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+- for (i = 0; i < chip->pcm_devs; i++)
++ for (i = 0; i < AZX_MAX_PCMS; i++)
+ snd_pcm_suspend_all(chip->pcm[i]);
+ if (chip->initialized)
+ snd_hda_suspend(chip->bus, state);
+ azx_stop_chip(chip);
+ if (chip->irq >= 0) {
+- synchronize_irq(chip->irq);
+ free_irq(chip->irq, chip);
+ chip->irq = -1;
+ }
+@@ -1641,24 +1729,26 @@ static int azx_resume(struct pci_dev *pci)
+ */
+ static int azx_free(struct azx *chip)
+ {
++ int i;
++
+ if (chip->initialized) {
+- int i;
+ for (i = 0; i < chip->num_streams; i++)
+ azx_stream_stop(chip, &chip->azx_dev[i]);
+ azx_stop_chip(chip);
+ }
+
+- if (chip->irq >= 0) {
+- synchronize_irq(chip->irq);
++ if (chip->irq >= 0)
+ free_irq(chip->irq, (void*)chip);
+- }
+ if (chip->msi)
+ pci_disable_msi(chip->pci);
+ if (chip->remap_addr)
+ iounmap(chip->remap_addr);
+
+- if (chip->bdl.area)
+- snd_dma_free_pages(&chip->bdl);
++ if (chip->azx_dev) {
++ for (i = 0; i < chip->num_streams; i++)
++ if (chip->azx_dev[i].bdl.area)
++ snd_dma_free_pages(&chip->azx_dev[i].bdl);
++ }
+ if (chip->rb.area)
+ snd_dma_free_pages(&chip->rb);
+ if (chip->posbuf.area)
+@@ -1682,6 +1772,7 @@ static int azx_dev_free(struct snd_device *device)
+ static struct snd_pci_quirk position_fix_list[] __devinitdata = {
+ SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_NONE),
+ SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_NONE),
++ SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_NONE),
+ {}
+ };
+
+@@ -1740,7 +1831,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
+ struct azx **rchip)
+ {
+ struct azx *chip;
+- int err;
++ int i, err;
+ unsigned short gcap;
+ static struct snd_device_ops ops = {
+ .dev_free = azx_dev_free,
+@@ -1812,38 +1903,35 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
+ gcap = azx_readw(chip, GCAP);
+ snd_printdd("chipset global capabilities = 0x%x\n", gcap);
+
+- if (gcap) {
+- /* read number of streams from GCAP register instead of using
+- * hardcoded value
+- */
+- chip->playback_streams = (gcap & (0xF << 12)) >> 12;
+- chip->capture_streams = (gcap & (0xF << 8)) >> 8;
+- chip->playback_index_offset = chip->capture_streams;
+- chip->capture_index_offset = 0;
+- } else {
++ /* allow 64bit DMA address if supported by H/W */
++ if ((gcap & 0x01) && !pci_set_dma_mask(pci, DMA_64BIT_MASK))
++ pci_set_consistent_dma_mask(pci, DMA_64BIT_MASK);
++
++ /* read number of streams from GCAP register instead of using
++ * hardcoded value
++ */
++ chip->capture_streams = (gcap >> 8) & 0x0f;
++ chip->playback_streams = (gcap >> 12) & 0x0f;
++ if (!chip->playback_streams && !chip->capture_streams) {
+ /* gcap didn't give any info, switching to old method */
+
+ switch (chip->driver_type) {
+ case AZX_DRIVER_ULI:
+ chip->playback_streams = ULI_NUM_PLAYBACK;
+ chip->capture_streams = ULI_NUM_CAPTURE;
+- chip->playback_index_offset = ULI_PLAYBACK_INDEX;
+- chip->capture_index_offset = ULI_CAPTURE_INDEX;
+ break;
+ case AZX_DRIVER_ATIHDMI:
+ chip->playback_streams = ATIHDMI_NUM_PLAYBACK;
+ chip->capture_streams = ATIHDMI_NUM_CAPTURE;
+- chip->playback_index_offset = ATIHDMI_PLAYBACK_INDEX;
+- chip->capture_index_offset = ATIHDMI_CAPTURE_INDEX;
+ break;
+ default:
+ chip->playback_streams = ICH6_NUM_PLAYBACK;
+ chip->capture_streams = ICH6_NUM_CAPTURE;
+- chip->playback_index_offset = ICH6_PLAYBACK_INDEX;
+- chip->capture_index_offset = ICH6_CAPTURE_INDEX;
+ break;
+ }
+ }
++ chip->capture_index_offset = 0;
++ chip->playback_index_offset = chip->capture_streams;
+ chip->num_streams = chip->playback_streams + chip->capture_streams;
+ chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev),
+ GFP_KERNEL);
+@@ -1852,13 +1940,15 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
+ goto errout;
+ }
+
+- /* allocate memory for the BDL for each stream */
+- err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
+- snd_dma_pci_data(chip->pci),
+- BDL_SIZE, &chip->bdl);
+- if (err < 0) {
+- snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
+- goto errout;
++ for (i = 0; i < chip->num_streams; i++) {
++ /* allocate memory for the BDL for each stream */
++ err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
++ snd_dma_pci_data(chip->pci),
++ BDL_SIZE, &chip->azx_dev[i].bdl);
++ if (err < 0) {
++ snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
++ goto errout;
++ }
+ }
+ /* allocate memory for the position buffer */
+ err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
+@@ -1994,48 +2084,63 @@ static void __devexit azx_remove(struct pci_dev *pci)
+
+ /* PCI IDs */
+ static struct pci_device_id azx_ids[] = {
+- { 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH6 */
+- { 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH7 */
+- { 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ESB2 */
+- { 0x8086, 0x284b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH8 */
+- { 0x8086, 0x293e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH9 */
+- { 0x8086, 0x293f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH9 */
+- { 0x8086, 0x3a3e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH10 */
+- { 0x8086, 0x3a6e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH10 */
+- { 0x8086, 0x811b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SCH }, /* SCH*/
+- { 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */
+- { 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */
+- { 0x1002, 0x793b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS600 HDMI */
+- { 0x1002, 0x7919, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS690 HDMI */
+- { 0x1002, 0x960f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS780 HDMI */
+- { 0x1002, 0xaa00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI R600 HDMI */
+- { 0x1002, 0xaa08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV630 HDMI */
+- { 0x1002, 0xaa10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV610 HDMI */
+- { 0x1002, 0xaa18, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV670 HDMI */
+- { 0x1002, 0xaa20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV635 HDMI */
+- { 0x1002, 0xaa28, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV620 HDMI */
+- { 0x1002, 0xaa30, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV770 HDMI */
+- { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */
+- { 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */
+- { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */
+- { 0x10de, 0x026c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP51 */
+- { 0x10de, 0x0371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP55 */
+- { 0x10de, 0x03e4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP61 */
+- { 0x10de, 0x03f0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP61 */
+- { 0x10de, 0x044a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP65 */
+- { 0x10de, 0x044b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP65 */
+- { 0x10de, 0x055c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */
+- { 0x10de, 0x055d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */
+- { 0x10de, 0x07fc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP73 */
+- { 0x10de, 0x07fd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP73 */
+- { 0x10de, 0x0774, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
+- { 0x10de, 0x0775, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
+- { 0x10de, 0x0776, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
+- { 0x10de, 0x0777, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
+- { 0x10de, 0x0ac0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */
+- { 0x10de, 0x0ac1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */
+- { 0x10de, 0x0ac2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */
+- { 0x10de, 0x0ac3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */
++ /* ICH 6..10 */
++ { PCI_DEVICE(0x8086, 0x2668), .driver_data = AZX_DRIVER_ICH },
++ { PCI_DEVICE(0x8086, 0x27d8), .driver_data = AZX_DRIVER_ICH },
++ { PCI_DEVICE(0x8086, 0x269a), .driver_data = AZX_DRIVER_ICH },
++ { PCI_DEVICE(0x8086, 0x284b), .driver_data = AZX_DRIVER_ICH },
++ { PCI_DEVICE(0x8086, 0x293e), .driver_data = AZX_DRIVER_ICH },
++ { PCI_DEVICE(0x8086, 0x293f), .driver_data = AZX_DRIVER_ICH },
++ { PCI_DEVICE(0x8086, 0x3a3e), .driver_data = AZX_DRIVER_ICH },
++ { PCI_DEVICE(0x8086, 0x3a6e), .driver_data = AZX_DRIVER_ICH },
++ /* SCH */
++ { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH },
++ /* ATI SB 450/600 */
++ { PCI_DEVICE(0x1002, 0x437b), .driver_data = AZX_DRIVER_ATI },
++ { PCI_DEVICE(0x1002, 0x4383), .driver_data = AZX_DRIVER_ATI },
++ /* ATI HDMI */
++ { PCI_DEVICE(0x1002, 0x793b), .driver_data = AZX_DRIVER_ATIHDMI },
++ { PCI_DEVICE(0x1002, 0x7919), .driver_data = AZX_DRIVER_ATIHDMI },
++ { PCI_DEVICE(0x1002, 0x960f), .driver_data = AZX_DRIVER_ATIHDMI },
++ { PCI_DEVICE(0x1002, 0xaa00), .driver_data = AZX_DRIVER_ATIHDMI },
++ { PCI_DEVICE(0x1002, 0xaa08), .driver_data = AZX_DRIVER_ATIHDMI },
++ { PCI_DEVICE(0x1002, 0xaa10), .driver_data = AZX_DRIVER_ATIHDMI },
++ { PCI_DEVICE(0x1002, 0xaa18), .driver_data = AZX_DRIVER_ATIHDMI },
++ { PCI_DEVICE(0x1002, 0xaa20), .driver_data = AZX_DRIVER_ATIHDMI },
++ { PCI_DEVICE(0x1002, 0xaa28), .driver_data = AZX_DRIVER_ATIHDMI },
++ { PCI_DEVICE(0x1002, 0xaa30), .driver_data = AZX_DRIVER_ATIHDMI },
++ { PCI_DEVICE(0x1002, 0xaa38), .driver_data = AZX_DRIVER_ATIHDMI },
++ { PCI_DEVICE(0x1002, 0xaa40), .driver_data = AZX_DRIVER_ATIHDMI },
++ { PCI_DEVICE(0x1002, 0xaa48), .driver_data = AZX_DRIVER_ATIHDMI },
++ /* VIA VT8251/VT8237A */
++ { PCI_DEVICE(0x1106, 0x3288), .driver_data = AZX_DRIVER_VIA },
++ /* SIS966 */
++ { PCI_DEVICE(0x1039, 0x7502), .driver_data = AZX_DRIVER_SIS },
++ /* ULI M5461 */
++ { PCI_DEVICE(0x10b9, 0x5461), .driver_data = AZX_DRIVER_ULI },
++ /* NVIDIA MCP */
++ { PCI_DEVICE(0x10de, 0x026c), .driver_data = AZX_DRIVER_NVIDIA },
++ { PCI_DEVICE(0x10de, 0x0371), .driver_data = AZX_DRIVER_NVIDIA },
++ { PCI_DEVICE(0x10de, 0x03e4), .driver_data = AZX_DRIVER_NVIDIA },
++ { PCI_DEVICE(0x10de, 0x03f0), .driver_data = AZX_DRIVER_NVIDIA },
++ { PCI_DEVICE(0x10de, 0x044a), .driver_data = AZX_DRIVER_NVIDIA },
++ { PCI_DEVICE(0x10de, 0x044b), .driver_data = AZX_DRIVER_NVIDIA },
++ { PCI_DEVICE(0x10de, 0x055c), .driver_data = AZX_DRIVER_NVIDIA },
++ { PCI_DEVICE(0x10de, 0x055d), .driver_data = AZX_DRIVER_NVIDIA },
++ { PCI_DEVICE(0x10de, 0x0774), .driver_data = AZX_DRIVER_NVIDIA },
++ { PCI_DEVICE(0x10de, 0x0775), .driver_data = AZX_DRIVER_NVIDIA },
++ { PCI_DEVICE(0x10de, 0x0776), .driver_data = AZX_DRIVER_NVIDIA },
++ { PCI_DEVICE(0x10de, 0x0777), .driver_data = AZX_DRIVER_NVIDIA },
++ { PCI_DEVICE(0x10de, 0x07fc), .driver_data = AZX_DRIVER_NVIDIA },
++ { PCI_DEVICE(0x10de, 0x07fd), .driver_data = AZX_DRIVER_NVIDIA },
++ { PCI_DEVICE(0x10de, 0x0ac0), .driver_data = AZX_DRIVER_NVIDIA },
++ { PCI_DEVICE(0x10de, 0x0ac1), .driver_data = AZX_DRIVER_NVIDIA },
++ { PCI_DEVICE(0x10de, 0x0ac2), .driver_data = AZX_DRIVER_NVIDIA },
++ { PCI_DEVICE(0x10de, 0x0ac3), .driver_data = AZX_DRIVER_NVIDIA },
++ { PCI_DEVICE(0x10de, 0x0bd4), .driver_data = AZX_DRIVER_NVIDIA },
++ { PCI_DEVICE(0x10de, 0x0bd5), .driver_data = AZX_DRIVER_NVIDIA },
++ { PCI_DEVICE(0x10de, 0x0bd6), .driver_data = AZX_DRIVER_NVIDIA },
++ { PCI_DEVICE(0x10de, 0x0bd7), .driver_data = AZX_DRIVER_NVIDIA },
+ { 0, }
+ };
+ MODULE_DEVICE_TABLE(pci, azx_ids);
+diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
+index ad0014a..5c9e578 100644
+--- a/sound/pci/hda/hda_local.h
++++ b/sound/pci/hda/hda_local.h
+@@ -228,8 +228,18 @@ struct hda_multi_out {
+ int max_channels; /* currently supported analog channels */
+ int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */
+ int no_share_stream; /* don't share a stream with multiple pins */
++ int share_spdif; /* share SPDIF pin */
++ /* PCM information for both analog and SPDIF DACs */
++ unsigned int analog_rates;
++ unsigned int analog_maxbps;
++ u64 analog_formats;
++ unsigned int spdif_rates;
++ unsigned int spdif_maxbps;
++ u64 spdif_formats;
+ };
+
++int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
++ struct hda_multi_out *mout);
+ int snd_hda_multi_out_dig_open(struct hda_codec *codec,
+ struct hda_multi_out *mout);
+ int snd_hda_multi_out_dig_close(struct hda_codec *codec,
+@@ -241,7 +251,8 @@ int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
+ struct snd_pcm_substream *substream);
+ int snd_hda_multi_out_analog_open(struct hda_codec *codec,
+ struct hda_multi_out *mout,
+- struct snd_pcm_substream *substream);
++ struct snd_pcm_substream *substream,
++ struct hda_pcm_stream *hinfo);
+ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
+ struct hda_multi_out *mout,
+ unsigned int stream_tag,
+@@ -407,11 +418,4 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
+ hda_nid_t nid);
+ #endif /* CONFIG_SND_HDA_POWER_SAVE */
+
+-/*
+- * virtual master control
+- */
+-struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
+- const unsigned int *tlv);
+-int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave);
+-
+ #endif /* __SOUND_HDA_LOCAL_H */
+diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h
+index f5c23bb..2fdf235 100644
+--- a/sound/pci/hda/hda_patch.h
++++ b/sound/pci/hda/hda_patch.h
+@@ -18,31 +18,3 @@ extern struct hda_codec_preset snd_hda_preset_atihdmi[];
+ extern struct hda_codec_preset snd_hda_preset_conexant[];
+ /* VIA codecs */
+ extern struct hda_codec_preset snd_hda_preset_via[];
+-
+-static const struct hda_codec_preset *hda_preset_tables[] = {
+-#ifdef CONFIG_SND_HDA_CODEC_REALTEK
+- snd_hda_preset_realtek,
+-#endif
+-#ifdef CONFIG_SND_HDA_CODEC_CMEDIA
+- snd_hda_preset_cmedia,
+-#endif
+-#ifdef CONFIG_SND_HDA_CODEC_ANALOG
+- snd_hda_preset_analog,
+-#endif
+-#ifdef CONFIG_SND_HDA_CODEC_SIGMATEL
+- snd_hda_preset_sigmatel,
+-#endif
+-#ifdef CONFIG_SND_HDA_CODEC_SI3054
+- snd_hda_preset_si3054,
+-#endif
+-#ifdef CONFIG_SND_HDA_CODEC_ATIHDMI
+- snd_hda_preset_atihdmi,
+-#endif
+-#ifdef CONFIG_SND_HDA_CODEC_CONEXANT
+- snd_hda_preset_conexant,
+-#endif
+-#ifdef CONFIG_SND_HDA_CODEC_VIA
+- snd_hda_preset_via,
+-#endif
+- NULL
+-};
+diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
+index c864928..e0a605a 100644
+--- a/sound/pci/hda/patch_analog.c
++++ b/sound/pci/hda/patch_analog.c
+@@ -28,6 +28,7 @@
+ #include <sound/core.h>
+ #include "hda_codec.h"
+ #include "hda_local.h"
++#include "hda_patch.h"
+
+ struct ad198x_spec {
+ struct snd_kcontrol_new *mixers[5];
+@@ -80,7 +81,6 @@ struct ad198x_spec {
+ #endif
+ /* for virtual master */
+ hda_nid_t vmaster_nid;
+- u32 vmaster_tlv[4];
+ const char **slave_vols;
+ const char **slave_sws;
+ };
+@@ -171,6 +171,11 @@ static int ad198x_build_controls(struct hda_codec *codec)
+ err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
+ if (err < 0)
+ return err;
++ err = snd_hda_create_spdif_share_sw(codec,
++ &spec->multiout);
++ if (err < 0)
++ return err;
++ spec->multiout.share_spdif = 1;
+ }
+ if (spec->dig_in_nid) {
+ err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
+@@ -180,10 +185,11 @@ static int ad198x_build_controls(struct hda_codec *codec)
+
+ /* if we have no master control, let's create it */
+ if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
++ unsigned int vmaster_tlv[4];
+ snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
+- HDA_OUTPUT, spec->vmaster_tlv);
++ HDA_OUTPUT, vmaster_tlv);
+ err = snd_hda_add_vmaster(codec, "Master Playback Volume",
+- spec->vmaster_tlv,
++ vmaster_tlv,
+ (spec->slave_vols ?
+ spec->slave_vols : ad_slave_vols));
+ if (err < 0)
+@@ -217,7 +223,8 @@ static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct snd_pcm_substream *substream)
+ {
+ struct ad198x_spec *spec = codec->spec;
+- return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
++ return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
++ hinfo);
+ }
+
+ static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+@@ -289,8 +296,7 @@ static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct snd_pcm_substream *substream)
+ {
+ struct ad198x_spec *spec = codec->spec;
+- snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
+- 0, 0, 0);
++ snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
+ return 0;
+ }
+
+@@ -359,6 +365,7 @@ static int ad198x_build_pcms(struct hda_codec *codec)
+ info++;
+ codec->num_pcms++;
+ info->name = "AD198x Digital";
++ info->pcm_type = HDA_PCM_TYPE_SPDIF;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
+ if (spec->dig_in_nid) {
+@@ -611,13 +618,19 @@ static struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
+ },
+ };
+
++static struct hda_input_mux ad1986a_automic_capture_source = {
++ .num_items = 2,
++ .items = {
++ { "Mic", 0x0 },
++ { "Mix", 0x5 },
++ },
++};
++
+ static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
+ HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
+ HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
+ HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
+- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT),
+- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
+@@ -641,6 +654,33 @@ static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
+ { } /* end */
+ };
+
++/* re-connect the mic boost input according to the jack sensing */
++static void ad1986a_automic(struct hda_codec *codec)
++{
++ unsigned int present;
++ present = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_PIN_SENSE, 0);
++ /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
++ snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
++ (present & AC_PINSENSE_PRESENCE) ? 0 : 2);
++}
++
++#define AD1986A_MIC_EVENT 0x36
++
++static void ad1986a_automic_unsol_event(struct hda_codec *codec,
++ unsigned int res)
++{
++ if ((res >> 26) != AD1986A_MIC_EVENT)
++ return;
++ ad1986a_automic(codec);
++}
++
++static int ad1986a_automic_init(struct hda_codec *codec)
++{
++ ad198x_init(codec);
++ ad1986a_automic(codec);
++ return 0;
++}
++
+ /* laptop-automute - 2ch only */
+
+ static void ad1986a_update_hp(struct hda_codec *codec)
+@@ -844,6 +884,15 @@ static struct hda_verb ad1986a_eapd_init_verbs[] = {
+ {}
+ };
+
++static struct hda_verb ad1986a_automic_verbs[] = {
++ {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
++ {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
++ /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
++ {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
++ {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT},
++ {}
++};
++
+ /* Ultra initialization */
+ static struct hda_verb ad1986a_ultra_init[] = {
+ /* eapd initialization */
+@@ -986,14 +1035,17 @@ static int patch_ad1986a(struct hda_codec *codec)
+ break;
+ case AD1986A_LAPTOP_EAPD:
+ spec->mixers[0] = ad1986a_laptop_eapd_mixers;
+- spec->num_init_verbs = 2;
++ spec->num_init_verbs = 3;
+ spec->init_verbs[1] = ad1986a_eapd_init_verbs;
++ spec->init_verbs[2] = ad1986a_automic_verbs;
+ spec->multiout.max_channels = 2;
+ spec->multiout.num_dacs = 1;
+ spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
+ if (!is_jack_available(codec, 0x25))
+ spec->multiout.dig_out_nid = 0;
+- spec->input_mux = &ad1986a_laptop_eapd_capture_source;
++ spec->input_mux = &ad1986a_automic_capture_source;
++ codec->patch_ops.unsol_event = ad1986a_automic_unsol_event;
++ codec->patch_ops.init = ad1986a_automic_init;
+ break;
+ case AD1986A_LAPTOP_AUTOMUTE:
+ spec->mixers[0] = ad1986a_laptop_automute_mixers;
+@@ -1365,7 +1417,10 @@ static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
+
+ if (! ad198x_eapd_put(kcontrol, ucontrol))
+ return 0;
+-
++ /* change speaker pin appropriately */
++ snd_hda_codec_write(codec, 0x05, 0,
++ AC_VERB_SET_PIN_WIDGET_CONTROL,
++ spec->cur_eapd ? PIN_OUT : 0);
+ /* toggle HP mute appropriately */
+ snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE,
+@@ -2087,6 +2142,10 @@ static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
+ { } /* end */
+ };
+
++static struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
++ HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
++ { } /* end */
++};
+
+ /*
+ * initialization verbs
+@@ -2187,6 +2246,13 @@ static struct hda_verb ad1988_spdif_init_verbs[] = {
+ { }
+ };
+
++/* AD1989 has no ADC -> SPDIF route */
++static struct hda_verb ad1989_spdif_init_verbs[] = {
++ /* SPDIF out pin */
++ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
++ { }
++};
++
+ /*
+ * verbs for 3stack (+dig)
+ */
+@@ -2894,10 +2960,19 @@ static int patch_ad1988(struct hda_codec *codec)
+ spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
+ spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
+ if (spec->multiout.dig_out_nid) {
+- spec->mixers[spec->num_mixers++] = ad1988_spdif_out_mixers;
+- spec->init_verbs[spec->num_init_verbs++] = ad1988_spdif_init_verbs;
++ if (codec->vendor_id >= 0x11d4989a) {
++ spec->mixers[spec->num_mixers++] =
++ ad1989_spdif_out_mixers;
++ spec->init_verbs[spec->num_init_verbs++] =
++ ad1989_spdif_init_verbs;
++ } else {
++ spec->mixers[spec->num_mixers++] =
++ ad1988_spdif_out_mixers;
++ spec->init_verbs[spec->num_init_verbs++] =
++ ad1988_spdif_init_verbs;
++ }
+ }
+- if (spec->dig_in_nid)
++ if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a)
+ spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
+
+ codec->patch_ops = ad198x_patch_ops;
+@@ -3133,11 +3208,12 @@ static int patch_ad1884(struct hda_codec *codec)
+ * Lenovo Thinkpad T61/X61
+ */
+ static struct hda_input_mux ad1984_thinkpad_capture_source = {
+- .num_items = 3,
++ .num_items = 4,
+ .items = {
+ { "Mic", 0x0 },
+ { "Internal Mic", 0x1 },
+ { "Mix", 0x3 },
++ { "Docking-Station", 0x4 },
+ },
+ };
+
+@@ -3268,8 +3344,7 @@ static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ struct snd_pcm_substream *substream)
+ {
+- snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
+- 0, 0, 0);
++ snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number);
+ return 0;
+ }
+
+@@ -3356,6 +3431,472 @@ static int patch_ad1984(struct hda_codec *codec)
+
+
+ /*
++ * AD1883 / AD1884A / AD1984A / AD1984B
++ *
++ * port-B (0x14) - front mic-in
++ * port-E (0x1c) - rear mic-in
++ * port-F (0x16) - CD / ext out
++ * port-C (0x15) - rear line-in
++ * port-D (0x12) - rear line-out
++ * port-A (0x11) - front hp-out
++ *
++ * AD1984A = AD1884A + digital-mic
++ * AD1883 = equivalent with AD1984A
++ * AD1984B = AD1984A + extra SPDIF-out
++ *
++ * FIXME:
++ * We share the single DAC for both HP and line-outs (see AD1884/1984).
++ */
++
++static hda_nid_t ad1884a_dac_nids[1] = {
++ 0x03,
++};
++
++#define ad1884a_adc_nids ad1884_adc_nids
++#define ad1884a_capsrc_nids ad1884_capsrc_nids
++
++#define AD1884A_SPDIF_OUT 0x02
++
++static struct hda_input_mux ad1884a_capture_source = {
++ .num_items = 5,
++ .items = {
++ { "Front Mic", 0x0 },
++ { "Mic", 0x4 },
++ { "Line", 0x1 },
++ { "CD", 0x2 },
++ { "Mix", 0x3 },
++ },
++};
++
++static struct snd_kcontrol_new ad1884a_base_mixers[] = {
++ HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
++ HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
++ HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
++ HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
++ HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
++ HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT),
++ HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
++ HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
++ HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
++ HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
++ HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT),
++ HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
++ HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
++ HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
++ HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT),
++ HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT),
++ HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
++ HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
++ HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT),
++ HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT),
++ HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
++ HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
++ HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
++ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
++ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ /* The multiple "Capture Source" controls confuse alsamixer
++ * So call somewhat different..
++ */
++ /* .name = "Capture Source", */
++ .name = "Input Source",
++ .count = 2,
++ .info = ad198x_mux_enum_info,
++ .get = ad198x_mux_enum_get,
++ .put = ad198x_mux_enum_put,
++ },
++ /* SPDIF controls */
++ HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
++ /* identical with ad1983 */
++ .info = ad1983_spdif_route_info,
++ .get = ad1983_spdif_route_get,
++ .put = ad1983_spdif_route_put,
++ },
++ { } /* end */
++};
++
++/*
++ * initialization verbs
++ */
++static struct hda_verb ad1884a_init_verbs[] = {
++ /* DACs; unmute as default */
++ {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
++ {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
++ /* Port-A (HP) mixer - route only from analog mixer */
++ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
++ /* Port-A pin */
++ {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
++ {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++ /* Port-D (Line-out) mixer - route only from analog mixer */
++ {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++ {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
++ /* Port-D pin */
++ {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
++ {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++ /* Mono-out mixer - route only from analog mixer */
++ {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++ {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
++ /* Mono-out pin */
++ {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
++ {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++ /* Port-B (front mic) pin */
++ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
++ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++ /* Port-C (rear line-in) pin */
++ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
++ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++ /* Port-E (rear mic) pin */
++ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
++ {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++ {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */
++ /* Port-F (CD) pin */
++ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
++ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++ /* Analog mixer; mute as default */
++ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
++ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
++ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
++ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */
++ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
++ /* Analog Mix output amp */
++ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++ /* capture sources */
++ {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
++ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++ {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
++ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++ /* SPDIF output amp */
++ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
++ { } /* end */
++};
++
++#ifdef CONFIG_SND_HDA_POWER_SAVE
++static struct hda_amp_list ad1884a_loopbacks[] = {
++ { 0x20, HDA_INPUT, 0 }, /* Front Mic */
++ { 0x20, HDA_INPUT, 1 }, /* Mic */
++ { 0x20, HDA_INPUT, 2 }, /* CD */
++ { 0x20, HDA_INPUT, 4 }, /* Docking */
++ { } /* end */
++};
++#endif
++
++/*
++ * Laptop model
++ *
++ * Port A: Headphone jack
++ * Port B: MIC jack
++ * Port C: Internal MIC
++ * Port D: Dock Line Out (if enabled)
++ * Port E: Dock Line In (if enabled)
++ * Port F: Internal speakers
++ */
++
++static struct hda_input_mux ad1884a_laptop_capture_source = {
++ .num_items = 4,
++ .items = {
++ { "Mic", 0x0 }, /* port-B */
++ { "Internal Mic", 0x1 }, /* port-C */
++ { "Dock Mic", 0x4 }, /* port-E */
++ { "Mix", 0x3 },
++ },
++};
++
++static struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
++ HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
++ HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
++ HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT),
++ HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
++ HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
++ HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
++ HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
++ HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
++ HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
++ HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
++ HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT),
++ HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
++ HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
++ HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
++ HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT),
++ HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT),
++ HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
++ HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
++ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
++ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ /* The multiple "Capture Source" controls confuse alsamixer
++ * So call somewhat different..
++ */
++ /* .name = "Capture Source", */
++ .name = "Input Source",
++ .count = 2,
++ .info = ad198x_mux_enum_info,
++ .get = ad198x_mux_enum_get,
++ .put = ad198x_mux_enum_put,
++ },
++ { } /* end */
++};
++
++static struct hda_input_mux ad1884a_mobile_capture_source = {
++ .num_items = 2,
++ .items = {
++ { "Mic", 0x1 }, /* port-C */
++ { "Mix", 0x3 },
++ },
++};
++
++static struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
++ HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
++ HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
++ HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
++ HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
++ HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
++ HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
++ HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
++ HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
++ HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT),
++ HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
++ HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Capture Source",
++ .info = ad198x_mux_enum_info,
++ .get = ad198x_mux_enum_get,
++ .put = ad198x_mux_enum_put,
++ },
++ { } /* end */
++};
++
++/* mute internal speaker if HP is plugged */
++static void ad1884a_hp_automute(struct hda_codec *codec)
++{
++ unsigned int present;
++
++ present = snd_hda_codec_read(codec, 0x11, 0,
++ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
++ snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
++ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
++ snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
++ present ? 0x00 : 0x02);
++}
++
++#define AD1884A_HP_EVENT 0x37
++
++/* unsolicited event for HP jack sensing */
++static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res)
++{
++ if ((res >> 26) != AD1884A_HP_EVENT)
++ return;
++ ad1884a_hp_automute(codec);
++}
++
++/* initialize jack-sensing, too */
++static int ad1884a_hp_init(struct hda_codec *codec)
++{
++ ad198x_init(codec);
++ ad1884a_hp_automute(codec);
++ return 0;
++}
++
++/* additional verbs for laptop model */
++static struct hda_verb ad1884a_laptop_verbs[] = {
++ /* Port-A (HP) pin - always unmuted */
++ {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
++ /* Port-F (int speaker) mixer - route only from analog mixer */
++ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
++ /* Port-F pin */
++ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
++ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++ /* analog mix */
++ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
++ /* unsolicited event for pin-sense */
++ {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
++ { } /* end */
++};
++
++/*
++ * Thinkpad X300
++ * 0x11 - HP
++ * 0x12 - speaker
++ * 0x14 - mic-in
++ * 0x17 - built-in mic
++ */
++
++static struct hda_verb ad1984a_thinkpad_verbs[] = {
++ /* HP unmute */
++ {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
++ /* analog mix */
++ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
++ /* turn on EAPD */
++ {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
++ /* unsolicited event for pin-sense */
++ {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
++ /* internal mic - dmic */
++ {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
++ /* set magic COEFs for dmic */
++ {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
++ {0x01, AC_VERB_SET_PROC_COEF, 0x08},
++ { } /* end */
++};
++
++static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
++ HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
++ HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
++ HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
++ HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
++ HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
++ HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
++ HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT),
++ HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT),
++ HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
++ HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
++ HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
++ HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Capture Source",
++ .info = ad198x_mux_enum_info,
++ .get = ad198x_mux_enum_get,
++ .put = ad198x_mux_enum_put,
++ },
++ { } /* end */
++};
++
++static struct hda_input_mux ad1984a_thinkpad_capture_source = {
++ .num_items = 3,
++ .items = {
++ { "Mic", 0x0 },
++ { "Internal Mic", 0x5 },
++ { "Mix", 0x3 },
++ },
++};
++
++/* mute internal speaker if HP is plugged */
++static void ad1984a_thinkpad_automute(struct hda_codec *codec)
++{
++ unsigned int present;
++
++ present = snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0)
++ & AC_PINSENSE_PRESENCE;
++ snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
++ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
++}
++
++/* unsolicited event for HP jack sensing */
++static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec,
++ unsigned int res)
++{
++ if ((res >> 26) != AD1884A_HP_EVENT)
++ return;
++ ad1984a_thinkpad_automute(codec);
++}
++
++/* initialize jack-sensing, too */
++static int ad1984a_thinkpad_init(struct hda_codec *codec)
++{
++ ad198x_init(codec);
++ ad1984a_thinkpad_automute(codec);
++ return 0;
++}
++
++/*
++ */
++
++enum {
++ AD1884A_DESKTOP,
++ AD1884A_LAPTOP,
++ AD1884A_MOBILE,
++ AD1884A_THINKPAD,
++ AD1884A_MODELS
++};
++
++static const char *ad1884a_models[AD1884A_MODELS] = {
++ [AD1884A_DESKTOP] = "desktop",
++ [AD1884A_LAPTOP] = "laptop",
++ [AD1884A_MOBILE] = "mobile",
++ [AD1884A_THINKPAD] = "thinkpad",
++};
++
++static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
++ SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
++ SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
++ {}
++};
++
++static int patch_ad1884a(struct hda_codec *codec)
++{
++ struct ad198x_spec *spec;
++ int board_config;
++
++ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
++ if (spec == NULL)
++ return -ENOMEM;
++
++ mutex_init(&spec->amp_mutex);
++ codec->spec = spec;
++
++ spec->multiout.max_channels = 2;
++ spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
++ spec->multiout.dac_nids = ad1884a_dac_nids;
++ spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT;
++ spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids);
++ spec->adc_nids = ad1884a_adc_nids;
++ spec->capsrc_nids = ad1884a_capsrc_nids;
++ spec->input_mux = &ad1884a_capture_source;
++ spec->num_mixers = 1;
++ spec->mixers[0] = ad1884a_base_mixers;
++ spec->num_init_verbs = 1;
++ spec->init_verbs[0] = ad1884a_init_verbs;
++ spec->spdif_route = 0;
++#ifdef CONFIG_SND_HDA_POWER_SAVE
++ spec->loopback.amplist = ad1884a_loopbacks;
++#endif
++ codec->patch_ops = ad198x_patch_ops;
++
++ /* override some parameters */
++ board_config = snd_hda_check_board_config(codec, AD1884A_MODELS,
++ ad1884a_models,
++ ad1884a_cfg_tbl);
++ switch (board_config) {
++ case AD1884A_LAPTOP:
++ spec->mixers[0] = ad1884a_laptop_mixers;
++ spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
++ spec->multiout.dig_out_nid = 0;
++ spec->input_mux = &ad1884a_laptop_capture_source;
++ codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
++ codec->patch_ops.init = ad1884a_hp_init;
++ break;
++ case AD1884A_MOBILE:
++ spec->mixers[0] = ad1884a_mobile_mixers;
++ spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
++ spec->multiout.dig_out_nid = 0;
++ spec->input_mux = &ad1884a_mobile_capture_source;
++ codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
++ codec->patch_ops.init = ad1884a_hp_init;
++ break;
++ case AD1884A_THINKPAD:
++ spec->mixers[0] = ad1984a_thinkpad_mixers;
++ spec->init_verbs[spec->num_init_verbs++] =
++ ad1984a_thinkpad_verbs;
++ spec->multiout.dig_out_nid = 0;
++ spec->input_mux = &ad1984a_thinkpad_capture_source;
++ codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
++ codec->patch_ops.init = ad1984a_thinkpad_init;
++ break;
++ }
++
++ return 0;
++}
++
++
++/*
+ * AD1882
+ *
+ * port-A - front hp-out
+@@ -3654,13 +4195,19 @@ static int patch_ad1882(struct hda_codec *codec)
+ * patch entries
+ */
+ struct hda_codec_preset snd_hda_preset_analog[] = {
++ { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
+ { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
++ { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
+ { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
++ { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a },
++ { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a },
+ { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
+ { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
+ { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 },
+ { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
+ { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
+ { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
++ { .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 },
++ { .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
+ {} /* terminator */
+ };
+diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c
+index 9a8bb4c..1227250 100644
+--- a/sound/pci/hda/patch_atihdmi.c
++++ b/sound/pci/hda/patch_atihdmi.c
+@@ -27,6 +27,7 @@
+ #include <sound/core.h>
+ #include "hda_codec.h"
+ #include "hda_local.h"
++#include "hda_patch.h"
+
+ struct atihdmi_spec {
+ struct hda_multi_out multiout;
+@@ -58,6 +59,10 @@ static int atihdmi_build_controls(struct hda_codec *codec)
+ static int atihdmi_init(struct hda_codec *codec)
+ {
+ snd_hda_sequence_write(codec, atihdmi_basic_init);
++ /* SI codec requires to unmute the pin */
++ if (get_wcaps(codec, 0x03) & AC_WCAP_OUT_AMP)
++ snd_hda_codec_write(codec, 0x03, 0, AC_VERB_SET_AMP_GAIN_MUTE,
++ AMP_OUT_UNMUTE);
+ return 0;
+ }
+
+@@ -112,6 +117,7 @@ static int atihdmi_build_pcms(struct hda_codec *codec)
+ codec->pcm_info = info;
+
+ info->name = "ATI HDMI";
++ info->pcm_type = HDA_PCM_TYPE_HDMI;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = atihdmi_pcm_digital_playback;
+
+ return 0;
+@@ -158,5 +164,7 @@ struct hda_codec_preset snd_hda_preset_atihdmi[] = {
+ { .id = 0x10027919, .name = "ATI RS600 HDMI", .patch = patch_atihdmi },
+ { .id = 0x1002791a, .name = "ATI RS690/780 HDMI", .patch = patch_atihdmi },
+ { .id = 0x1002aa01, .name = "ATI R6xx HDMI", .patch = patch_atihdmi },
++ { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_atihdmi },
++ { .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_atihdmi },
+ {} /* terminator */
+ };
+diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
+index 3d6097b..c73ce07 100644
+--- a/sound/pci/hda/patch_cmedia.c
++++ b/sound/pci/hda/patch_cmedia.c
+@@ -28,6 +28,7 @@
+ #include <sound/core.h>
+ #include "hda_codec.h"
+ #include "hda_local.h"
++#include "hda_patch.h"
+ #define NUM_PINS 11
+
+
+@@ -329,6 +330,11 @@ static int cmi9880_build_controls(struct hda_codec *codec)
+ err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
+ if (err < 0)
+ return err;
++ err = snd_hda_create_spdif_share_sw(codec,
++ &spec->multiout);
++ if (err < 0)
++ return err;
++ spec->multiout.share_spdif = 1;
+ }
+ if (spec->dig_in_nid) {
+ err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
+@@ -432,7 +438,8 @@ static int cmi9880_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct snd_pcm_substream *substream)
+ {
+ struct cmi_spec *spec = codec->spec;
+- return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
++ return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
++ hinfo);
+ }
+
+ static int cmi9880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+@@ -506,7 +513,7 @@ static int cmi9880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ {
+ struct cmi_spec *spec = codec->spec;
+
+- snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
++ snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
+ return 0;
+ }
+
+@@ -571,6 +578,7 @@ static int cmi9880_build_pcms(struct hda_codec *codec)
+ codec->num_pcms++;
+ info++;
+ info->name = "CMI9880 Digital";
++ info->pcm_type = HDA_PCM_TYPE_SPDIF;
+ if (spec->multiout.dig_out_nid) {
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_digital_playback;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
+@@ -603,6 +611,7 @@ static const char *cmi9880_models[CMI_MODELS] = {
+
+ static struct snd_pci_quirk cmi9880_cfg_tbl[] = {
+ SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", CMI_FULL_DIG),
++ SND_PCI_QUIRK(0x1854, 0x0032, "LG", CMI_FULL_DIG),
+ {} /* terminator */
+ };
+
+diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
+index 7206b30..36fd852 100644
+--- a/sound/pci/hda/patch_conexant.c
++++ b/sound/pci/hda/patch_conexant.c
+@@ -27,6 +27,7 @@
+ #include <sound/core.h>
+ #include "hda_codec.h"
+ #include "hda_local.h"
++#include "hda_patch.h"
+
+ #define CXT_PIN_DIR_IN 0x00
+ #define CXT_PIN_DIR_OUT 0x01
+@@ -98,7 +99,8 @@ static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct snd_pcm_substream *substream)
+ {
+ struct conexant_spec *spec = codec->spec;
+- return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
++ return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
++ hinfo);
+ }
+
+ static int conexant_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+@@ -172,8 +174,7 @@ static int conexant_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct snd_pcm_substream *substream)
+ {
+ struct conexant_spec *spec = codec->spec;
+- snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
+- 0, 0, 0);
++ snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
+ return 0;
+ }
+
+@@ -241,7 +242,7 @@ static int cx5051_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct snd_pcm_substream *substream)
+ {
+ struct conexant_spec *spec = codec->spec;
+- snd_hda_codec_setup_stream(codec, spec->cur_adc, 0, 0, 0);
++ snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
+ spec->cur_adc = 0;
+ return 0;
+ }
+@@ -284,6 +285,7 @@ static int conexant_build_pcms(struct hda_codec *codec)
+ info++;
+ codec->num_pcms++;
+ info->name = "Conexant Digital";
++ info->pcm_type = HDA_PCM_TYPE_SPDIF;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
+ conexant_pcm_digital_playback;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
+@@ -371,6 +373,11 @@ static int conexant_build_controls(struct hda_codec *codec)
+ spec->multiout.dig_out_nid);
+ if (err < 0)
+ return err;
++ err = snd_hda_create_spdif_share_sw(codec,
++ &spec->multiout);
++ if (err < 0)
++ return err;
++ spec->multiout.share_spdif = 1;
+ }
+ if (spec->dig_in_nid) {
+ err = snd_hda_create_spdif_in_ctls(codec,spec->dig_in_nid);
+@@ -511,6 +518,14 @@ static struct hda_input_mux cxt5045_capture_source_benq = {
+ }
+ };
+
++static struct hda_input_mux cxt5045_capture_source_hp530 = {
++ .num_items = 2,
++ .items = {
++ { "ExtMic", 0x1 },
++ { "IntMic", 0x2 },
++ }
++};
++
+ /* turn on/off EAPD (+ mute HP) as a master switch */
+ static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+@@ -639,6 +654,37 @@ static struct snd_kcontrol_new cxt5045_benq_mixers[] = {
+ {}
+ };
+
++static struct snd_kcontrol_new cxt5045_mixers_hp530[] = {
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Capture Source",
++ .info = conexant_mux_enum_info,
++ .get = conexant_mux_enum_get,
++ .put = conexant_mux_enum_put
++ },
++ HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x02, HDA_INPUT),
++ HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x02, HDA_INPUT),
++ HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x01, HDA_INPUT),
++ HDA_CODEC_MUTE("Ext Mic Capture Switch", 0x1a, 0x01, HDA_INPUT),
++ HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT),
++ HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT),
++ HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x17, 0x2, HDA_INPUT),
++ HDA_CODEC_MUTE("Int Mic Playback Switch", 0x17, 0x2, HDA_INPUT),
++ HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x17, 0x1, HDA_INPUT),
++ HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x17, 0x1, HDA_INPUT),
++ HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol),
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Master Playback Switch",
++ .info = cxt_eapd_info,
++ .get = cxt_eapd_get,
++ .put = cxt5045_hp_master_sw_put,
++ .private_value = 0x10,
++ },
++
++ {}
++};
++
+ static struct hda_verb cxt5045_init_verbs[] = {
+ /* Line in, Mic */
+ {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+@@ -833,6 +879,7 @@ enum {
+ CXT5045_LAPTOP_MICSENSE,
+ CXT5045_LAPTOP_HPMICSENSE,
+ CXT5045_BENQ,
++ CXT5045_LAPTOP_HP530,
+ #ifdef CONFIG_SND_DEBUG
+ CXT5045_TEST,
+ #endif
+@@ -844,6 +891,7 @@ static const char *cxt5045_models[CXT5045_MODELS] = {
+ [CXT5045_LAPTOP_MICSENSE] = "laptop-micsense",
+ [CXT5045_LAPTOP_HPMICSENSE] = "laptop-hpmicsense",
+ [CXT5045_BENQ] = "benq",
++ [CXT5045_LAPTOP_HP530] = "laptop-hp530",
+ #ifdef CONFIG_SND_DEBUG
+ [CXT5045_TEST] = "test",
+ #endif
+@@ -857,7 +905,7 @@ static struct snd_pci_quirk cxt5045_cfg_tbl[] = {
+ SND_PCI_QUIRK(0x103c, 0x30bb, "HP DV8000", CXT5045_LAPTOP_HPSENSE),
+ SND_PCI_QUIRK(0x103c, 0x30cd, "HP DV Series", CXT5045_LAPTOP_HPSENSE),
+ SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV9533EG", CXT5045_LAPTOP_HPSENSE),
+- SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HPSENSE),
++ SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HP530),
+ SND_PCI_QUIRK(0x103c, 0x30d9, "HP Spartan", CXT5045_LAPTOP_HPSENSE),
+ SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ),
+ SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE),
+@@ -941,6 +989,14 @@ static int patch_cxt5045(struct hda_codec *codec)
+ spec->num_mixers = 2;
+ codec->patch_ops.init = cxt5045_init;
+ break;
++ case CXT5045_LAPTOP_HP530:
++ codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
++ spec->input_mux = &cxt5045_capture_source_hp530;
++ spec->num_init_verbs = 2;
++ spec->init_verbs[1] = cxt5045_hp_sense_init_verbs;
++ spec->mixers[0] = cxt5045_mixers_hp530;
++ codec->patch_ops.init = cxt5045_init;
++ break;
+ #ifdef CONFIG_SND_DEBUG
+ case CXT5045_TEST:
+ spec->input_mux = &cxt5045_test_capture_source;
+@@ -1537,7 +1593,7 @@ static void cxt5051_portc_automic(struct hda_codec *codec)
+ new_adc = spec->adc_nids[spec->cur_adc_idx];
+ if (spec->cur_adc && spec->cur_adc != new_adc) {
+ /* stream is running, let's swap the current ADC */
+- snd_hda_codec_setup_stream(codec, spec->cur_adc, 0, 0, 0);
++ snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
+ spec->cur_adc = new_adc;
+ snd_hda_codec_setup_stream(codec, new_adc,
+ spec->cur_adc_stream_tag, 0,
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 33282f9..cdda64b 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -30,6 +30,7 @@
+ #include <sound/core.h>
+ #include "hda_codec.h"
+ #include "hda_local.h"
++#include "hda_patch.h"
+
+ #define ALC880_FRONT_EVENT 0x01
+ #define ALC880_DCVOL_EVENT 0x02
+@@ -97,16 +98,19 @@ enum {
+ ALC262_SONY_ASSAMD,
+ ALC262_BENQ_T31,
+ ALC262_ULTRA,
++ ALC262_LENOVO_3000,
+ ALC262_AUTO,
+ ALC262_MODEL_LAST /* last tag */
+ };
+
+ /* ALC268 models */
+ enum {
++ ALC267_QUANTA_IL1,
+ ALC268_3ST,
+ ALC268_TOSHIBA,
+ ALC268_ACER,
+ ALC268_DELL,
++ ALC268_ZEPTO,
+ #ifdef CONFIG_SND_DEBUG
+ ALC268_TEST,
+ #endif
+@@ -195,10 +199,11 @@ enum {
+ ALC883_LENOVO_NB0763,
+ ALC888_LENOVO_MS7195_DIG,
+ ALC883_HAIER_W66,
+- ALC888_6ST_HP,
+ ALC888_3ST_HP,
+ ALC888_6ST_DELL,
+ ALC883_MITAC,
++ ALC883_CLEVO_M720,
++ ALC883_FUJITSU_PI2515,
+ ALC883_AUTO,
+ ALC883_MODEL_LAST,
+ };
+@@ -237,6 +242,7 @@ struct alc_spec {
+ /* capture */
+ unsigned int num_adc_nids;
+ hda_nid_t *adc_nids;
++ hda_nid_t *capsrc_nids;
+ hda_nid_t dig_in_nid; /* digital-in NID; optional */
+
+ /* capture source */
+@@ -270,7 +276,6 @@ struct alc_spec {
+
+ /* for virtual master */
+ hda_nid_t vmaster_nid;
+- u32 vmaster_tlv[4];
+ #ifdef CONFIG_SND_HDA_POWER_SAVE
+ struct hda_loopback_check loopback;
+ #endif
+@@ -290,6 +295,7 @@ struct alc_config_preset {
+ hda_nid_t hp_nid; /* optional */
+ unsigned int num_adc_nids;
+ hda_nid_t *adc_nids;
++ hda_nid_t *capsrc_nids;
+ hda_nid_t dig_in_nid;
+ unsigned int num_channel_mode;
+ const struct hda_channel_mode *channel_mode;
+@@ -336,9 +342,10 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
+ struct alc_spec *spec = codec->spec;
+ unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+ unsigned int mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
++ hda_nid_t nid = spec->capsrc_nids ?
++ spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
+ return snd_hda_input_mux_put(codec, &spec->input_mux[mux_idx], ucontrol,
+- spec->adc_nids[adc_idx],
+- &spec->cur_mux[adc_idx]);
++ nid, &spec->cur_mux[adc_idx]);
+ }
+
+
+@@ -707,6 +714,7 @@ static void setup_preset(struct alc_spec *spec,
+
+ spec->num_adc_nids = preset->num_adc_nids;
+ spec->adc_nids = preset->adc_nids;
++ spec->capsrc_nids = preset->capsrc_nids;
+ spec->dig_in_nid = preset->dig_in_nid;
+
+ spec->unsol_event = preset->unsol_event;
+@@ -741,7 +749,6 @@ static struct hda_verb alc_gpio3_init_verbs[] = {
+ static void alc_sku_automute(struct hda_codec *codec)
+ {
+ struct alc_spec *spec = codec->spec;
+- unsigned int mute;
+ unsigned int present;
+ unsigned int hp_nid = spec->autocfg.hp_pins[0];
+ unsigned int sp_nid = spec->autocfg.speaker_pins[0];
+@@ -751,16 +758,8 @@ static void alc_sku_automute(struct hda_codec *codec)
+ present = snd_hda_codec_read(codec, hp_nid, 0,
+ AC_VERB_GET_PIN_SENSE, 0);
+ spec->jack_present = (present & 0x80000000) != 0;
+- if (spec->jack_present) {
+- /* mute internal speaker */
+- snd_hda_codec_amp_stereo(codec, sp_nid, HDA_OUTPUT, 0,
+- HDA_AMP_MUTE, HDA_AMP_MUTE);
+- } else {
+- /* unmute internal speaker if necessary */
+- mute = snd_hda_codec_amp_read(codec, hp_nid, 0, HDA_OUTPUT, 0);
+- snd_hda_codec_amp_stereo(codec, sp_nid, HDA_OUTPUT, 0,
+- HDA_AMP_MUTE, mute);
+- }
++ snd_hda_codec_write(codec, sp_nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
++ spec->jack_present ? 0 : PIN_OUT);
+ }
+
+ /* unsolicited event for HP jack sensing */
+@@ -1319,11 +1318,19 @@ static struct snd_kcontrol_new alc880_f1734_mixer[] = {
+ HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
++ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
++ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+ { } /* end */
+ };
+
++static struct hda_input_mux alc880_f1734_capture_source = {
++ .num_items = 2,
++ .items = {
++ { "Mic", 0x1 },
++ { "CD", 0x4 },
++ },
++};
++
+
+ /*
+ * ALC880 ASUS model
+@@ -1516,6 +1523,11 @@ static int alc_build_controls(struct hda_codec *codec)
+ spec->multiout.dig_out_nid);
+ if (err < 0)
+ return err;
++ err = snd_hda_create_spdif_share_sw(codec,
++ &spec->multiout);
++ if (err < 0)
++ return err;
++ spec->multiout.share_spdif = 1;
+ }
+ if (spec->dig_in_nid) {
+ err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
+@@ -1525,10 +1537,11 @@ static int alc_build_controls(struct hda_codec *codec)
+
+ /* if we have no master control, let's create it */
+ if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
++ unsigned int vmaster_tlv[4];
+ snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
+- HDA_OUTPUT, spec->vmaster_tlv);
++ HDA_OUTPUT, vmaster_tlv);
+ err = snd_hda_add_vmaster(codec, "Master Playback Volume",
+- spec->vmaster_tlv, alc_slave_vols);
++ vmaster_tlv, alc_slave_vols);
+ if (err < 0)
+ return err;
+ }
+@@ -1882,7 +1895,7 @@ static void alc880_uniwill_p53_hp_automute(struct hda_codec *codec)
+ present = snd_hda_codec_read(codec, 0x14, 0,
+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+ bits = present ? HDA_AMP_MUTE : 0;
+- snd_hda_codec_amp_stereo(codec, 0x15, HDA_INPUT, 0, HDA_AMP_MUTE, bits);
++ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, HDA_AMP_MUTE, bits);
+ }
+
+ static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
+@@ -1915,6 +1928,7 @@ static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
+ * HP = 0x14, speaker-out = 0x15, mic = 0x18
+ */
+ static struct hda_verb alc880_pin_f1734_init_verbs[] = {
++ {0x07, AC_VERB_SET_CONNECT_SEL, 0x01},
+ {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
+ {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
+@@ -1927,7 +1941,7 @@ static struct hda_verb alc880_pin_f1734_init_verbs[] = {
+
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
++ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+@@ -1935,6 +1949,9 @@ static struct hda_verb alc880_pin_f1734_init_verbs[] = {
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
++ {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
++ {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_DCVOL_EVENT},
++
+ { }
+ };
+
+@@ -2318,7 +2335,8 @@ static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct snd_pcm_substream *substream)
+ {
+ struct alc_spec *spec = codec->spec;
+- return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
++ return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
++ hinfo);
+ }
+
+ static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+@@ -2392,8 +2410,8 @@ static int alc880_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ {
+ struct alc_spec *spec = codec->spec;
+
+- snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
+- 0, 0, 0);
++ snd_hda_codec_cleanup_stream(codec,
++ spec->adc_nids[substream->number + 1]);
+ return 0;
+ }
+
+@@ -2498,6 +2516,7 @@ static int alc_build_pcms(struct hda_codec *codec)
+ codec->num_pcms = 2;
+ info = spec->pcm_rec + 1;
+ info->name = spec->stream_name_digital;
++ info->pcm_type = HDA_PCM_TYPE_SPDIF;
+ if (spec->multiout.dig_out_nid &&
+ spec->stream_digital_playback) {
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
+@@ -2560,6 +2579,7 @@ static void alc_free(struct hda_codec *codec)
+ kfree(spec->kctl_alloc);
+ }
+ kfree(spec);
++ codec->spec = NULL; /* to be sure */
+ }
+
+ /*
+@@ -3057,7 +3077,9 @@ static struct alc_config_preset alc880_presets[] = {
+ .hp_nid = 0x02,
+ .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
+ .channel_mode = alc880_2_jack_modes,
+- .input_mux = &alc880_capture_source,
++ .input_mux = &alc880_f1734_capture_source,
++ .unsol_event = alc880_uniwill_p53_unsol_event,
++ .init_hook = alc880_uniwill_p53_hp_automute,
+ },
+ [ALC880_ASUS] = {
+ .mixers = { alc880_asus_mixer },
+@@ -3467,15 +3489,21 @@ static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec,
+ return 0;
+ }
+
+-static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,
+- hda_nid_t nid, int pin_type,
+- int dac_idx)
++static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
++ unsigned int pin_type)
+ {
+- /* set as output */
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+ pin_type);
++ /* unmute pin */
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+ AMP_OUT_UNMUTE);
++}
++
++static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,
++ hda_nid_t nid, int pin_type,
++ int dac_idx)
++{
++ alc_set_pin_output(codec, nid, pin_type);
+ /* need the manual connection? */
+ if (alc880_is_multi_pin(nid)) {
+ struct alc_spec *spec = codec->spec;
+@@ -3597,9 +3625,12 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
+ /* additional initialization for auto-configuration model */
+ static void alc880_auto_init(struct hda_codec *codec)
+ {
++ struct alc_spec *spec = codec->spec;
+ alc880_auto_init_multi_out(codec);
+ alc880_auto_init_extra_out(codec);
+ alc880_auto_init_analog_input(codec);
++ if (spec->unsol_event)
++ alc_sku_automute(codec);
+ }
+
+ /*
+@@ -4795,11 +4826,7 @@ static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
+ hda_nid_t nid, int pin_type,
+ int sel_idx)
+ {
+- /* set as output */
+- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+- pin_type);
+- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+- AMP_OUT_UNMUTE);
++ alc_set_pin_output(codec, nid, pin_type);
+ /* need the manual connection? */
+ if (nid >= 0x12) {
+ int idx = nid - 0x12;
+@@ -4929,7 +4956,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
+ /* check whether NID 0x04 is valid */
+ wcap = get_wcaps(codec, 0x04);
+ wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
+- if (wcap != AC_WID_AUD_IN) {
++ if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
+ spec->adc_nids = alc260_adc_nids_alt;
+ spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt);
+ spec->mixers[spec->num_mixers] = alc260_capture_alt_mixer;
+@@ -4946,8 +4973,11 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
+ /* additional initialization for auto-configuration model */
+ static void alc260_auto_init(struct hda_codec *codec)
+ {
++ struct alc_spec *spec = codec->spec;
+ alc260_auto_init_multi_out(codec);
+ alc260_auto_init_analog_input(codec);
++ if (spec->unsol_event)
++ alc_sku_automute(codec);
+ }
+
+ #ifdef CONFIG_SND_HDA_POWER_SAVE
+@@ -5204,6 +5234,9 @@ static hda_nid_t alc882_dac_nids[4] = {
+ #define alc882_adc_nids alc880_adc_nids
+ #define alc882_adc_nids_alt alc880_adc_nids_alt
+
++static hda_nid_t alc882_capsrc_nids[3] = { 0x24, 0x23, 0x22 };
++static hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 };
++
+ /* input MUX */
+ /* FIXME: should be a matrix-type input source selection */
+
+@@ -5226,15 +5259,11 @@ static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol,
+ struct alc_spec *spec = codec->spec;
+ const struct hda_input_mux *imux = spec->input_mux;
+ unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+- static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
+- hda_nid_t nid;
++ hda_nid_t nid = spec->capsrc_nids ?
++ spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
+ unsigned int *cur_val = &spec->cur_mux[adc_idx];
+ unsigned int i, idx;
+
+- if (spec->num_adc_nids < 3)
+- nid = capture_mixers[adc_idx + 1];
+- else
+- nid = capture_mixers[adc_idx];
+ idx = ucontrol->value.enumerated.item[0];
+ if (idx >= imux->num_items)
+ idx = imux->num_items - 1;
+@@ -6111,6 +6140,7 @@ static struct alc_config_preset alc882_presets[] = {
+ .dig_out_nid = ALC882_DIGOUT_NID,
+ .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
+ .adc_nids = alc882_adc_nids,
++ .capsrc_nids = alc882_capsrc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
+ .channel_mode = alc882_3ST_6ch_modes,
+ .need_dac_fix = 1,
+@@ -6127,6 +6157,7 @@ static struct alc_config_preset alc882_presets[] = {
+ .dig_out_nid = ALC882_DIGOUT_NID,
+ .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
+ .adc_nids = alc882_adc_nids,
++ .capsrc_nids = alc882_capsrc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
+ .channel_mode = alc882_3ST_6ch_modes,
+ .need_dac_fix = 1,
+@@ -6182,15 +6213,11 @@ static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
+ struct alc_spec *spec = codec->spec;
+ int idx;
+
++ alc_set_pin_output(codec, nid, pin_type);
+ if (spec->multiout.dac_nids[dac_idx] == 0x25)
+ idx = 4;
+ else
+ idx = spec->multiout.dac_nids[dac_idx] - 2;
+-
+- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+- pin_type);
+- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+- AMP_OUT_UNMUTE);
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
+
+ }
+@@ -6219,6 +6246,9 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec)
+ if (pin) /* connect to front */
+ /* use dac 0 */
+ alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
++ pin = spec->autocfg.speaker_pins[0];
++ if (pin)
++ alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
+ }
+
+ #define alc882_is_input_pin(nid) alc880_is_input_pin(nid)
+@@ -6231,16 +6261,21 @@ static void alc882_auto_init_analog_input(struct hda_codec *codec)
+
+ for (i = 0; i < AUTO_PIN_LAST; i++) {
+ hda_nid_t nid = spec->autocfg.input_pins[i];
+- if (alc882_is_input_pin(nid)) {
+- snd_hda_codec_write(codec, nid, 0,
+- AC_VERB_SET_PIN_WIDGET_CONTROL,
+- i <= AUTO_PIN_FRONT_MIC ?
+- PIN_VREF80 : PIN_IN);
+- if (nid != ALC882_PIN_CD_NID)
+- snd_hda_codec_write(codec, nid, 0,
+- AC_VERB_SET_AMP_GAIN_MUTE,
+- AMP_OUT_MUTE);
++ unsigned int vref;
++ if (!nid)
++ continue;
++ vref = PIN_IN;
++ if (1 /*i <= AUTO_PIN_FRONT_MIC*/) {
++ if (snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP) &
++ AC_PINCAP_VREF_80)
++ vref = PIN_VREF80;
+ }
++ snd_hda_codec_write(codec, nid, 0,
++ AC_VERB_SET_PIN_WIDGET_CONTROL, vref);
++ if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
++ snd_hda_codec_write(codec, nid, 0,
++ AC_VERB_SET_AMP_GAIN_MUTE,
++ AMP_OUT_MUTE);
+ }
+ }
+
+@@ -6294,11 +6329,16 @@ static int alc882_parse_auto_config(struct hda_codec *codec)
+ /* additional initialization for auto-configuration model */
+ static void alc882_auto_init(struct hda_codec *codec)
+ {
++ struct alc_spec *spec = codec->spec;
+ alc882_auto_init_multi_out(codec);
+ alc882_auto_init_hp_out(codec);
+ alc882_auto_init_analog_input(codec);
++ if (spec->unsol_event)
++ alc_sku_automute(codec);
+ }
+
++static int patch_alc883(struct hda_codec *codec); /* called in patch_alc882() */
++
+ static int patch_alc882(struct hda_codec *codec)
+ {
+ struct alc_spec *spec;
+@@ -6328,6 +6368,11 @@ static int patch_alc882(struct hda_codec *codec)
+ board_config = ALC885_MBP3;
+ break;
+ default:
++ /* ALC889A is handled better as ALC888-compatible */
++ if (codec->revision_id == 0x100103) {
++ alc_free(codec);
++ return patch_alc883(codec);
++ }
+ printk(KERN_INFO "hda_codec: Unknown model for ALC882, "
+ "trying auto-probe from BIOS...\n");
+ board_config = ALC882_AUTO;
+@@ -6372,12 +6417,14 @@ static int patch_alc882(struct hda_codec *codec)
+ if (wcap != AC_WID_AUD_IN) {
+ spec->adc_nids = alc882_adc_nids_alt;
+ spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt);
++ spec->capsrc_nids = alc882_capsrc_nids_alt;
+ spec->mixers[spec->num_mixers] =
+ alc882_capture_alt_mixer;
+ spec->num_mixers++;
+ } else {
+ spec->adc_nids = alc882_adc_nids;
+ spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
++ spec->capsrc_nids = alc882_capsrc_nids;
+ spec->mixers[spec->num_mixers] = alc882_capture_mixer;
+ spec->num_mixers++;
+ }
+@@ -6412,7 +6459,7 @@ static int patch_alc882(struct hda_codec *codec)
+
+ static hda_nid_t alc883_dac_nids[4] = {
+ /* front, rear, clfe, rear_surr */
+- 0x02, 0x04, 0x03, 0x05
++ 0x02, 0x03, 0x04, 0x05
+ };
+
+ static hda_nid_t alc883_adc_nids[2] = {
+@@ -6420,6 +6467,8 @@ static hda_nid_t alc883_adc_nids[2] = {
+ 0x08, 0x09,
+ };
+
++static hda_nid_t alc883_capsrc_nids[2] = { 0x23, 0x22 };
++
+ /* input MUX */
+ /* FIXME: should be a matrix-type input source selection */
+
+@@ -6451,35 +6500,18 @@ static struct hda_input_mux alc883_lenovo_nb0763_capture_source = {
+ },
+ };
+
++static struct hda_input_mux alc883_fujitsu_pi2515_capture_source = {
++ .num_items = 2,
++ .items = {
++ { "Mic", 0x0 },
++ { "Int Mic", 0x1 },
++ },
++};
++
+ #define alc883_mux_enum_info alc_mux_enum_info
+ #define alc883_mux_enum_get alc_mux_enum_get
+-
+-static int alc883_mux_enum_put(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_value *ucontrol)
+-{
+- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+- struct alc_spec *spec = codec->spec;
+- const struct hda_input_mux *imux = spec->input_mux;
+- unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+- static hda_nid_t capture_mixers[2] = { 0x23, 0x22 };
+- hda_nid_t nid = capture_mixers[adc_idx];
+- unsigned int *cur_val = &spec->cur_mux[adc_idx];
+- unsigned int i, idx;
+-
+- idx = ucontrol->value.enumerated.item[0];
+- if (idx >= imux->num_items)
+- idx = imux->num_items - 1;
+- if (*cur_val == idx)
+- return 0;
+- for (i = 0; i < imux->num_items; i++) {
+- unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
+- snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
+- imux->items[i].index,
+- HDA_AMP_MUTE, v);
+- }
+- *cur_val = idx;
+- return 1;
+-}
++/* ALC883 has the ALC882-type input selection */
++#define alc883_mux_enum_put alc882_mux_enum_put
+
+ /*
+ * 2ch mode
+@@ -6638,6 +6670,60 @@ static struct snd_kcontrol_new alc883_mitac_mixer[] = {
+ { } /* end */
+ };
+
++static struct snd_kcontrol_new alc883_clevo_m720_mixer[] = {
++ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
++ HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
++ HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
++ HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
++ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
++ HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
++ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
++ HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
++ HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
++ HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
++ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
++ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
++ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
++ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ /* .name = "Capture Source", */
++ .name = "Input Source",
++ .count = 2,
++ .info = alc883_mux_enum_info,
++ .get = alc883_mux_enum_get,
++ .put = alc883_mux_enum_put,
++ },
++ { } /* end */
++};
++
++static struct snd_kcontrol_new alc883_2ch_fujitsu_pi2515_mixer[] = {
++ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
++ HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
++ HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
++ HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
++ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
++ HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
++ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
++ HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
++ HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
++ HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
++ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
++ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
++ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
++ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ /* .name = "Capture Source", */
++ .name = "Input Source",
++ .count = 2,
++ .info = alc883_mux_enum_info,
++ .get = alc883_mux_enum_get,
++ .put = alc883_mux_enum_put,
++ },
++ { } /* end */
++};
++
+ static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+@@ -6787,6 +6873,9 @@ static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = {
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
++ HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
++ HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
++ HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+@@ -6878,124 +6967,6 @@ static struct snd_kcontrol_new alc883_medion_md2_mixer[] = {
+ { } /* end */
+ };
+
+-static struct snd_kcontrol_new alc888_6st_hp_mixer[] = {
+- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
+- HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),
+- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
+- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
+- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
+- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
+- HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+- HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
+- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+- HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+- HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
+- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+- HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+- HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+- HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+- HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+- HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+- HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+- {
+- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+- /* .name = "Capture Source", */
+- .name = "Input Source",
+- .count = 2,
+- .info = alc883_mux_enum_info,
+- .get = alc883_mux_enum_get,
+- .put = alc883_mux_enum_put,
+- },
+- { } /* end */
+-};
+-
+-static struct snd_kcontrol_new alc888_3st_hp_mixer[] = {
+- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
+- HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),
+- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
+- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
+- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
+- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
+- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+- HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+- HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
+- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+- HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+- HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+- HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+- HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+- HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+- HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+- {
+- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+- /* .name = "Capture Source", */
+- .name = "Input Source",
+- .count = 2,
+- .info = alc883_mux_enum_info,
+- .get = alc883_mux_enum_get,
+- .put = alc883_mux_enum_put,
+- },
+- { } /* end */
+-};
+-
+-static struct snd_kcontrol_new alc888_6st_dell_mixer[] = {
+- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
+- HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),
+- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
+- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
+- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
+- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
+- HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+- HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
+- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+- HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+- HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
+- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+- HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+- HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+- HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+- HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+- HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+- HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+- {
+- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+- /* .name = "Capture Source", */
+- .name = "Input Source",
+- .count = 2,
+- .info = alc883_mux_enum_info,
+- .get = alc883_mux_enum_get,
+- .put = alc883_mux_enum_put,
+- },
+- { } /* end */
+-};
+-
+ static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+@@ -7171,6 +7142,35 @@ static struct hda_verb alc883_mitac_verbs[] = {
+ { } /* end */
+ };
+
++static struct hda_verb alc883_clevo_m720_verbs[] = {
++ /* HP */
++ {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
++ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
++ /* Int speaker */
++ {0x14, AC_VERB_SET_CONNECT_SEL, 0x01},
++ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
++
++ /* enable unsolicited event */
++ {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
++ {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
++
++ { } /* end */
++};
++
++static struct hda_verb alc883_2ch_fujitsu_pi2515_verbs[] = {
++ /* HP */
++ {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
++ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
++ /* Subwoofer */
++ {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
++ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
++
++ /* enable unsolicited event */
++ {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
++
++ { } /* end */
++};
++
+ static struct hda_verb alc883_tagra_verbs[] = {
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+@@ -7227,26 +7227,14 @@ static struct hda_verb alc883_haier_w66_verbs[] = {
+ { } /* end */
+ };
+
+-static struct hda_verb alc888_6st_hp_verbs[] = {
+- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */
+- {0x15, AC_VERB_SET_CONNECT_SEL, 0x02}, /* Rear : output 2 (0x0e) */
+- {0x16, AC_VERB_SET_CONNECT_SEL, 0x01}, /* CLFE : output 1 (0x0d) */
+- {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, /* Side : output 3 (0x0f) */
+- { }
+-};
+-
+ static struct hda_verb alc888_3st_hp_verbs[] = {
+ {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */
+- {0x18, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Rear : output 1 (0x0d) */
+- {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, /* CLFE : output 2 (0x0e) */
++ {0x16, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Rear : output 1 (0x0d) */
++ {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* CLFE : output 2 (0x0e) */
+ { }
+ };
+
+ static struct hda_verb alc888_6st_dell_verbs[] = {
+- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */
+- {0x15, AC_VERB_SET_CONNECT_SEL, 0x02}, /* Rear : output 1 (0x0e) */
+- {0x16, AC_VERB_SET_CONNECT_SEL, 0x01}, /* CLFE : output 2 (0x0d) */
+- {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, /* Side : output 3 (0x0f) */
+ {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+ { }
+ };
+@@ -7354,6 +7342,68 @@ static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res)
+ alc883_tagra_automute(codec);
+ }
+
++/* toggle speaker-output according to the hp-jack state */
++static void alc883_clevo_m720_hp_automute(struct hda_codec *codec)
++{
++ unsigned int present;
++ unsigned char bits;
++
++ present = snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_PIN_SENSE, 0)
++ & AC_PINSENSE_PRESENCE;
++ bits = present ? HDA_AMP_MUTE : 0;
++ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
++ HDA_AMP_MUTE, bits);
++}
++
++static void alc883_clevo_m720_mic_automute(struct hda_codec *codec)
++{
++ unsigned int present;
++
++ present = snd_hda_codec_read(codec, 0x18, 0,
++ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
++ snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1,
++ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
++}
++
++static void alc883_clevo_m720_automute(struct hda_codec *codec)
++{
++ alc883_clevo_m720_hp_automute(codec);
++ alc883_clevo_m720_mic_automute(codec);
++}
++
++static void alc883_clevo_m720_unsol_event(struct hda_codec *codec,
++ unsigned int res)
++{
++ switch (res >> 26) {
++ case ALC880_HP_EVENT:
++ alc883_clevo_m720_hp_automute(codec);
++ break;
++ case ALC880_MIC_EVENT:
++ alc883_clevo_m720_mic_automute(codec);
++ break;
++ }
++}
++
++/* toggle speaker-output according to the hp-jack state */
++static void alc883_2ch_fujitsu_pi2515_automute(struct hda_codec *codec)
++{
++ unsigned int present;
++ unsigned char bits;
++
++ present = snd_hda_codec_read(codec, 0x14, 0, AC_VERB_GET_PIN_SENSE, 0)
++ & AC_PINSENSE_PRESENCE;
++ bits = present ? HDA_AMP_MUTE : 0;
++ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
++ HDA_AMP_MUTE, bits);
++}
++
++static void alc883_2ch_fujitsu_pi2515_unsol_event(struct hda_codec *codec,
++ unsigned int res)
++{
++ if ((res >> 26) == ALC880_HP_EVENT)
++ alc883_2ch_fujitsu_pi2515_automute(codec);
++}
++
+ static void alc883_haier_w66_automute(struct hda_codec *codec)
+ {
+ unsigned int present;
+@@ -7587,10 +7637,11 @@ static const char *alc883_models[ALC883_MODEL_LAST] = {
+ [ALC883_LENOVO_NB0763] = "lenovo-nb0763",
+ [ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig",
+ [ALC883_HAIER_W66] = "haier-w66",
+- [ALC888_6ST_HP] = "6stack-hp",
+ [ALC888_3ST_HP] = "3stack-hp",
+ [ALC888_6ST_DELL] = "6stack-dell",
+ [ALC883_MITAC] = "mitac",
++ [ALC883_CLEVO_M720] = "clevo-m720",
++ [ALC883_FUJITSU_PI2515] = "fujitsu-pi2515",
+ [ALC883_AUTO] = "auto",
+ };
+
+@@ -7604,7 +7655,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
+ SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG),
+ SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),
+ SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP),
+- SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC888_6ST_HP),
++ SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG),
+ SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
+ SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG),
+ SND_PCI_QUIRK(0x1071, 0x8253, "Mitac 8252d", ALC883_MITAC),
+@@ -7614,7 +7665,9 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
+ SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG),
+ SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
+ SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
++ SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC883_TARGA_2ch_DIG),
+ SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),
++ SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG),
+ SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG),
+ SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG),
+ SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG),
+@@ -7627,13 +7680,17 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
+ SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),
+ SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
+ SND_PCI_QUIRK(0x1462, 0x7250, "MSI", ALC883_6ST_DIG),
++ SND_PCI_QUIRK(0x1462, 0x7267, "MSI", ALC883_3ST_6ch_DIG),
+ SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
+ SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG),
+ SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
+ SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG),
++ SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720),
++ SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720),
+ SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD),
+ SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
+ SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
++ SND_PCI_QUIRK(0x1734, 0x1108, "Fujitsu AMILO Pi2515", ALC883_FUJITSU_PI2515),
+ SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch),
+ SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763),
+ SND_PCI_QUIRK(0x17aa, 0x3bfc, "Lenovo NB0763", ALC883_LENOVO_NB0763),
+@@ -7652,8 +7709,6 @@ static struct alc_config_preset alc883_presets[] = {
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+ .dig_out_nid = ALC883_DIGOUT_NID,
+- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+- .adc_nids = alc883_adc_nids,
+ .dig_in_nid = ALC883_DIGIN_NID,
+ .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ .channel_mode = alc883_3ST_2ch_modes,
+@@ -7665,8 +7720,6 @@ static struct alc_config_preset alc883_presets[] = {
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+ .dig_out_nid = ALC883_DIGOUT_NID,
+- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+- .adc_nids = alc883_adc_nids,
+ .dig_in_nid = ALC883_DIGIN_NID,
+ .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
+ .channel_mode = alc883_3ST_6ch_modes,
+@@ -7678,8 +7731,6 @@ static struct alc_config_preset alc883_presets[] = {
+ .init_verbs = { alc883_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+- .adc_nids = alc883_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
+ .channel_mode = alc883_3ST_6ch_modes,
+ .need_dac_fix = 1,
+@@ -7691,8 +7742,6 @@ static struct alc_config_preset alc883_presets[] = {
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+ .dig_out_nid = ALC883_DIGOUT_NID,
+- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+- .adc_nids = alc883_adc_nids,
+ .dig_in_nid = ALC883_DIGIN_NID,
+ .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
+ .channel_mode = alc883_sixstack_modes,
+@@ -7704,8 +7753,6 @@ static struct alc_config_preset alc883_presets[] = {
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+ .dig_out_nid = ALC883_DIGOUT_NID,
+- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+- .adc_nids = alc883_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
+ .channel_mode = alc883_3ST_6ch_modes,
+ .need_dac_fix = 1,
+@@ -7719,8 +7766,6 @@ static struct alc_config_preset alc883_presets[] = {
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+ .dig_out_nid = ALC883_DIGOUT_NID,
+- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+- .adc_nids = alc883_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ .channel_mode = alc883_3ST_2ch_modes,
+ .input_mux = &alc883_capture_source,
+@@ -7737,8 +7782,6 @@ static struct alc_config_preset alc883_presets[] = {
+ .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+- .adc_nids = alc883_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ .channel_mode = alc883_3ST_2ch_modes,
+ .input_mux = &alc883_capture_source,
+@@ -7749,8 +7792,6 @@ static struct alc_config_preset alc883_presets[] = {
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+ .dig_out_nid = ALC883_DIGOUT_NID,
+- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+- .adc_nids = alc883_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ .channel_mode = alc883_3ST_2ch_modes,
+ .input_mux = &alc883_capture_source,
+@@ -7764,8 +7805,6 @@ static struct alc_config_preset alc883_presets[] = {
+ alc883_medion_eapd_verbs },
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+- .adc_nids = alc883_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
+ .channel_mode = alc883_sixstack_modes,
+ .input_mux = &alc883_capture_source,
+@@ -7776,8 +7815,6 @@ static struct alc_config_preset alc883_presets[] = {
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+ .dig_out_nid = ALC883_DIGOUT_NID,
+- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+- .adc_nids = alc883_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ .channel_mode = alc883_3ST_2ch_modes,
+ .input_mux = &alc883_capture_source,
+@@ -7789,19 +7826,27 @@ static struct alc_config_preset alc883_presets[] = {
+ .init_verbs = { alc883_init_verbs, alc882_eapd_verbs },
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+- .adc_nids = alc883_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ .channel_mode = alc883_3ST_2ch_modes,
+ .input_mux = &alc883_capture_source,
+ },
++ [ALC883_CLEVO_M720] = {
++ .mixers = { alc883_clevo_m720_mixer },
++ .init_verbs = { alc883_init_verbs, alc883_clevo_m720_verbs },
++ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
++ .dac_nids = alc883_dac_nids,
++ .dig_out_nid = ALC883_DIGOUT_NID,
++ .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
++ .channel_mode = alc883_3ST_2ch_modes,
++ .input_mux = &alc883_capture_source,
++ .unsol_event = alc883_clevo_m720_unsol_event,
++ .init_hook = alc883_clevo_m720_automute,
++ },
+ [ALC883_LENOVO_101E_2ch] = {
+ .mixers = { alc883_lenovo_101e_2ch_mixer},
+ .init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs},
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+- .adc_nids = alc883_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ .channel_mode = alc883_3ST_2ch_modes,
+ .input_mux = &alc883_lenovo_101e_capture_source,
+@@ -7813,8 +7858,6 @@ static struct alc_config_preset alc883_presets[] = {
+ .init_verbs = { alc883_init_verbs, alc883_lenovo_nb0763_verbs},
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+- .adc_nids = alc883_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ .channel_mode = alc883_3ST_2ch_modes,
+ .need_dac_fix = 1,
+@@ -7828,8 +7871,6 @@ static struct alc_config_preset alc883_presets[] = {
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+ .dig_out_nid = ALC883_DIGOUT_NID,
+- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+- .adc_nids = alc883_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
+ .channel_mode = alc883_3ST_6ch_modes,
+ .need_dac_fix = 1,
+@@ -7843,47 +7884,28 @@ static struct alc_config_preset alc883_presets[] = {
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+ .dig_out_nid = ALC883_DIGOUT_NID,
+- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+- .adc_nids = alc883_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ .channel_mode = alc883_3ST_2ch_modes,
+ .input_mux = &alc883_capture_source,
+ .unsol_event = alc883_haier_w66_unsol_event,
+ .init_hook = alc883_haier_w66_automute,
+- },
+- [ALC888_6ST_HP] = {
+- .mixers = { alc888_6st_hp_mixer, alc883_chmode_mixer },
+- .init_verbs = { alc883_init_verbs, alc888_6st_hp_verbs },
+- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+- .dac_nids = alc883_dac_nids,
+- .dig_out_nid = ALC883_DIGOUT_NID,
+- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+- .adc_nids = alc883_adc_nids,
+- .dig_in_nid = ALC883_DIGIN_NID,
+- .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
+- .channel_mode = alc883_sixstack_modes,
+- .input_mux = &alc883_capture_source,
+ },
+ [ALC888_3ST_HP] = {
+- .mixers = { alc888_3st_hp_mixer, alc883_chmode_mixer },
++ .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
+ .init_verbs = { alc883_init_verbs, alc888_3st_hp_verbs },
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+- .adc_nids = alc883_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc888_3st_hp_modes),
+ .channel_mode = alc888_3st_hp_modes,
+ .need_dac_fix = 1,
+ .input_mux = &alc883_capture_source,
+ },
+ [ALC888_6ST_DELL] = {
+- .mixers = { alc888_6st_dell_mixer, alc883_chmode_mixer },
++ .mixers = { alc883_base_mixer, alc883_chmode_mixer },
+ .init_verbs = { alc883_init_verbs, alc888_6st_dell_verbs },
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+ .dig_out_nid = ALC883_DIGOUT_NID,
+- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+- .adc_nids = alc883_adc_nids,
+ .dig_in_nid = ALC883_DIGIN_NID,
+ .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
+ .channel_mode = alc883_sixstack_modes,
+@@ -7896,14 +7918,25 @@ static struct alc_config_preset alc883_presets[] = {
+ .init_verbs = { alc883_init_verbs, alc883_mitac_verbs },
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+- .adc_nids = alc883_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ .channel_mode = alc883_3ST_2ch_modes,
+ .input_mux = &alc883_capture_source,
+ .unsol_event = alc883_mitac_unsol_event,
+ .init_hook = alc883_mitac_automute,
+ },
++ [ALC883_FUJITSU_PI2515] = {
++ .mixers = { alc883_2ch_fujitsu_pi2515_mixer },
++ .init_verbs = { alc883_init_verbs,
++ alc883_2ch_fujitsu_pi2515_verbs},
++ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
++ .dac_nids = alc883_dac_nids,
++ .dig_out_nid = ALC883_DIGOUT_NID,
++ .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
++ .channel_mode = alc883_3ST_2ch_modes,
++ .input_mux = &alc883_fujitsu_pi2515_capture_source,
++ .unsol_event = alc883_2ch_fujitsu_pi2515_unsol_event,
++ .init_hook = alc883_2ch_fujitsu_pi2515_automute,
++ },
+ };
+
+
+@@ -7918,15 +7951,11 @@ static void alc883_auto_set_output_and_unmute(struct hda_codec *codec,
+ struct alc_spec *spec = codec->spec;
+ int idx;
+
++ alc_set_pin_output(codec, nid, pin_type);
+ if (spec->multiout.dac_nids[dac_idx] == 0x25)
+ idx = 4;
+ else
+ idx = spec->multiout.dac_nids[dac_idx] - 2;
+-
+- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+- pin_type);
+- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+- AMP_OUT_UNMUTE);
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
+
+ }
+@@ -7955,6 +7984,9 @@ static void alc883_auto_init_hp_out(struct hda_codec *codec)
+ if (pin) /* connect to front */
+ /* use dac 0 */
+ alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
++ pin = spec->autocfg.speaker_pins[0];
++ if (pin)
++ alc883_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
+ }
+
+ #define alc883_is_input_pin(nid) alc880_is_input_pin(nid)
+@@ -8006,9 +8038,12 @@ static int alc883_parse_auto_config(struct hda_codec *codec)
+ /* additional initialization for auto-configuration model */
+ static void alc883_auto_init(struct hda_codec *codec)
+ {
++ struct alc_spec *spec = codec->spec;
+ alc883_auto_init_multi_out(codec);
+ alc883_auto_init_hp_out(codec);
+ alc883_auto_init_analog_input(codec);
++ if (spec->unsol_event)
++ alc_sku_automute(codec);
+ }
+
+ static int patch_alc883(struct hda_codec *codec)
+@@ -8057,10 +8092,9 @@ static int patch_alc883(struct hda_codec *codec)
+ spec->stream_digital_playback = &alc883_pcm_digital_playback;
+ spec->stream_digital_capture = &alc883_pcm_digital_capture;
+
+- if (!spec->adc_nids && spec->input_mux) {
+- spec->adc_nids = alc883_adc_nids;
+- spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);
+- }
++ spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);
++ spec->adc_nids = alc883_adc_nids;
++ spec->capsrc_nids = alc883_capsrc_nids;
+
+ spec->vmaster_nid = 0x0c;
+
+@@ -8085,6 +8119,8 @@ static int patch_alc883(struct hda_codec *codec)
+ #define alc262_dac_nids alc260_dac_nids
+ #define alc262_adc_nids alc882_adc_nids
+ #define alc262_adc_nids_alt alc882_adc_nids_alt
++#define alc262_capsrc_nids alc882_capsrc_nids
++#define alc262_capsrc_nids_alt alc882_capsrc_nids_alt
+
+ #define alc262_modes alc260_modes
+ #define alc262_capture_source alc882_capture_source
+@@ -8585,7 +8621,8 @@ static void alc262_hippo1_unsol_event(struct hda_codec *codec,
+
+ /*
+ * fujitsu model
+- * 0x14 = headphone/spdif-out, 0x15 = internal speaker
++ * 0x14 = headphone/spdif-out, 0x15 = internal speaker,
++ * 0x1b = port replicator headphone out
+ */
+
+ #define ALC_HP_EVENT 0x37
+@@ -8593,6 +8630,14 @@ static void alc262_hippo1_unsol_event(struct hda_codec *codec,
+ static struct hda_verb alc262_fujitsu_unsol_verbs[] = {
+ {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
++ {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
++ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
++ {}
++};
++
++static struct hda_verb alc262_lenovo_3000_unsol_verbs[] = {
++ {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
++ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {}
+ };
+
+@@ -8633,12 +8678,16 @@ static void alc262_fujitsu_automute(struct hda_codec *codec, int force)
+ unsigned int mute;
+
+ if (force || !spec->sense_updated) {
+- unsigned int present;
++ unsigned int present_int_hp, present_dock_hp;
+ /* need to execute and sync at first */
+ snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0);
+- present = snd_hda_codec_read(codec, 0x14, 0,
+- AC_VERB_GET_PIN_SENSE, 0);
+- spec->jack_present = (present & 0x80000000) != 0;
++ present_int_hp = snd_hda_codec_read(codec, 0x14, 0,
++ AC_VERB_GET_PIN_SENSE, 0);
++ snd_hda_codec_read(codec, 0x1B, 0, AC_VERB_SET_PIN_SENSE, 0);
++ present_dock_hp = snd_hda_codec_read(codec, 0x1b, 0,
++ AC_VERB_GET_PIN_SENSE, 0);
++ spec->jack_present = (present_int_hp & 0x80000000) != 0;
++ spec->jack_present |= (present_dock_hp & 0x80000000) != 0;
+ spec->sense_updated = 1;
+ }
+ if (spec->jack_present) {
+@@ -8672,6 +8721,46 @@ static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {
+ },
+ };
+
++/* mute/unmute internal speaker according to the hp jack and mute state */
++static void alc262_lenovo_3000_automute(struct hda_codec *codec, int force)
++{
++ struct alc_spec *spec = codec->spec;
++ unsigned int mute;
++
++ if (force || !spec->sense_updated) {
++ unsigned int present_int_hp;
++ /* need to execute and sync at first */
++ snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0);
++ present_int_hp = snd_hda_codec_read(codec, 0x1b, 0,
++ AC_VERB_GET_PIN_SENSE, 0);
++ spec->jack_present = (present_int_hp & 0x80000000) != 0;
++ spec->sense_updated = 1;
++ }
++ if (spec->jack_present) {
++ /* mute internal speaker */
++ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
++ HDA_AMP_MUTE, HDA_AMP_MUTE);
++ snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
++ HDA_AMP_MUTE, HDA_AMP_MUTE);
++ } else {
++ /* unmute internal speaker if necessary */
++ mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0);
++ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
++ HDA_AMP_MUTE, mute);
++ snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
++ HDA_AMP_MUTE, mute);
++ }
++}
++
++/* unsolicited event for HP jack sensing */
++static void alc262_lenovo_3000_unsol_event(struct hda_codec *codec,
++ unsigned int res)
++{
++ if ((res >> 26) != ALC_HP_EVENT)
++ return;
++ alc262_lenovo_3000_automute(codec, 1);
++}
++
+ /* bind hp and internal speaker mute (with plug check) */
+ static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+@@ -8680,12 +8769,13 @@ static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
+ long *valp = ucontrol->value.integer.value;
+ int change;
+
+- change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
+- HDA_AMP_MUTE,
+- valp[0] ? 0 : HDA_AMP_MUTE);
+- change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
+- HDA_AMP_MUTE,
+- valp[1] ? 0 : HDA_AMP_MUTE);
++ change = snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
++ HDA_AMP_MUTE,
++ valp ? 0 : HDA_AMP_MUTE);
++ change |= snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
++ HDA_AMP_MUTE,
++ valp ? 0 : HDA_AMP_MUTE);
++
+ if (change)
+ alc262_fujitsu_automute(codec, 0);
+ return change;
+@@ -8703,6 +8793,46 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
+ },
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
++ HDA_CODEC_VOLUME("PC Speaker Volume", 0x0b, 0x05, HDA_INPUT),
++ HDA_CODEC_MUTE("PC Speaker Switch", 0x0b, 0x05, HDA_INPUT),
++ HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
++ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
++ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
++ HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
++ HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
++ HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
++ { } /* end */
++};
++
++/* bind hp and internal speaker mute (with plug check) */
++static int alc262_lenovo_3000_master_sw_put(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
++ long *valp = ucontrol->value.integer.value;
++ int change;
++
++ change = snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
++ HDA_AMP_MUTE,
++ valp ? 0 : HDA_AMP_MUTE);
++
++ if (change)
++ alc262_lenovo_3000_automute(codec, 0);
++ return change;
++}
++
++static struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = {
++ HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Master Playback Switch",
++ .info = snd_hda_mixer_amp_switch_info,
++ .get = snd_hda_mixer_amp_switch_get,
++ .put = alc262_lenovo_3000_master_sw_put,
++ .private_value = HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
++ },
++ HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
++ HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+@@ -8730,59 +8860,72 @@ static struct hda_verb alc262_benq_t31_EAPD_verbs[] = {
+
+ /* Samsung Q1 Ultra Vista model setup */
+ static struct snd_kcontrol_new alc262_ultra_mixer[] = {
+- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+- HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+- HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
++ HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
++ HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Boost", 0x19, 0, HDA_INPUT),
++ HDA_CODEC_VOLUME("Headphone Mic Boost", 0x15, 0, HDA_INPUT),
+ { } /* end */
+ };
+
+ static struct hda_verb alc262_ultra_verbs[] = {
+- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
++ /* output mixer */
++ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
++ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
++ /* speaker */
++ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
++ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
++ {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
++ /* HP */
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+- /* Mic is on Node 0x19 */
+- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+- {0x22, AC_VERB_SET_CONNECT_SEL, 0x01},
+- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+- {0x23, AC_VERB_SET_CONNECT_SEL, 0x01},
+- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+- {0x24, AC_VERB_SET_CONNECT_SEL, 0x01},
+- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
++ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
++ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
++ {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
++ {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
++ /* internal mic */
++ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
++ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
++ /* ADC, choose mic */
++ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
++ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
++ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
++ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
++ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
++ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
++ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
++ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
++ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(8)},
+ {}
+ };
+
+-static struct hda_input_mux alc262_ultra_capture_source = {
+- .num_items = 1,
+- .items = {
+- { "Mic", 0x1 },
+- },
+-};
+-
+ /* mute/unmute internal speaker according to the hp jack and mute state */
+ static void alc262_ultra_automute(struct hda_codec *codec)
+ {
+ struct alc_spec *spec = codec->spec;
+ unsigned int mute;
+- unsigned int present;
+
+- /* need to execute and sync at first */
+- snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0);
+- present = snd_hda_codec_read(codec, 0x15, 0,
+- AC_VERB_GET_PIN_SENSE, 0);
+- spec->jack_present = (present & 0x80000000) != 0;
+- if (spec->jack_present) {
+- /* mute internal speaker */
+- snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+- HDA_AMP_MUTE, HDA_AMP_MUTE);
+- } else {
+- /* unmute internal speaker if necessary */
+- mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0);
+- snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+- HDA_AMP_MUTE, mute);
++ mute = 0;
++ /* auto-mute only when HP is used as HP */
++ if (!spec->cur_mux[0]) {
++ unsigned int present;
++ /* need to execute and sync at first */
++ snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0);
++ present = snd_hda_codec_read(codec, 0x15, 0,
++ AC_VERB_GET_PIN_SENSE, 0);
++ spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0;
++ if (spec->jack_present)
++ mute = HDA_AMP_MUTE;
+ }
++ /* mute/unmute internal speaker */
++ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
++ HDA_AMP_MUTE, mute);
++ /* mute/unmute HP */
++ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
++ HDA_AMP_MUTE, mute ? 0 : HDA_AMP_MUTE);
+ }
+
+ /* unsolicited event for HP jack sensing */
+@@ -8794,6 +8937,45 @@ static void alc262_ultra_unsol_event(struct hda_codec *codec,
+ alc262_ultra_automute(codec);
+ }
+
++static struct hda_input_mux alc262_ultra_capture_source = {
++ .num_items = 2,
++ .items = {
++ { "Mic", 0x1 },
++ { "Headphone", 0x7 },
++ },
++};
++
++static int alc262_ultra_mux_enum_put(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
++ struct alc_spec *spec = codec->spec;
++ int ret;
++
++ ret = alc882_mux_enum_put(kcontrol, ucontrol);
++ if (!ret)
++ return 0;
++ /* reprogram the HP pin as mic or HP according to the input source */
++ snd_hda_codec_write_cache(codec, 0x15, 0,
++ AC_VERB_SET_PIN_WIDGET_CONTROL,
++ spec->cur_mux[0] ? PIN_VREF80 : PIN_HP);
++ alc262_ultra_automute(codec); /* mute/unmute HP */
++ return ret;
++}
++
++static struct snd_kcontrol_new alc262_ultra_capture_mixer[] = {
++ HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
++ HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Capture Source",
++ .info = alc882_mux_enum_info,
++ .get = alc882_mux_enum_get,
++ .put = alc262_ultra_mux_enum_put,
++ },
++ { } /* end */
++};
++
+ /* add playback controls from the parsed DAC table */
+ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
+ const struct auto_pin_cfg *cfg)
+@@ -9185,9 +9367,12 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
+ /* init callback for auto-configuration model -- overriding the default init */
+ static void alc262_auto_init(struct hda_codec *codec)
+ {
++ struct alc_spec *spec = codec->spec;
+ alc262_auto_init_multi_out(codec);
+ alc262_auto_init_hp_out(codec);
+ alc262_auto_init_analog_input(codec);
++ if (spec->unsol_event)
++ alc_sku_automute(codec);
+ }
+
+ /*
+@@ -9206,6 +9391,7 @@ static const char *alc262_models[ALC262_MODEL_LAST] = {
+ [ALC262_BENQ_T31] = "benq-t31",
+ [ALC262_SONY_ASSAMD] = "sony-assamd",
+ [ALC262_ULTRA] = "ultra",
++ [ALC262_LENOVO_3000] = "lenovo-3000",
+ [ALC262_AUTO] = "auto",
+ };
+
+@@ -9241,6 +9427,8 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = {
+ SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
+ SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU),
+ SND_PCI_QUIRK(0x144d, 0xc032, "Samsung Q1 Ultra", ALC262_ULTRA),
++ SND_PCI_QUIRK(0x144d, 0xc039, "Samsung Q1U EL", ALC262_ULTRA),
++ SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 y410", ALC262_LENOVO_3000),
+ SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
+ SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31),
+ SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),
+@@ -9390,18 +9578,32 @@ static struct alc_config_preset alc262_presets[] = {
+ .init_hook = alc262_hippo_automute,
+ },
+ [ALC262_ULTRA] = {
+- .mixers = { alc262_ultra_mixer },
+- .init_verbs = { alc262_init_verbs, alc262_ultra_verbs },
++ .mixers = { alc262_ultra_mixer, alc262_ultra_capture_mixer },
++ .init_verbs = { alc262_ultra_verbs },
+ .num_dacs = ARRAY_SIZE(alc262_dac_nids),
+ .dac_nids = alc262_dac_nids,
+- .hp_nid = 0x03,
+- .dig_out_nid = ALC262_DIGOUT_NID,
+ .num_channel_mode = ARRAY_SIZE(alc262_modes),
+ .channel_mode = alc262_modes,
+ .input_mux = &alc262_ultra_capture_source,
++ .adc_nids = alc262_adc_nids, /* ADC0 */
++ .capsrc_nids = alc262_capsrc_nids,
++ .num_adc_nids = 1, /* single ADC */
+ .unsol_event = alc262_ultra_unsol_event,
+ .init_hook = alc262_ultra_automute,
+ },
++ [ALC262_LENOVO_3000] = {
++ .mixers = { alc262_lenovo_3000_mixer },
++ .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
++ alc262_lenovo_3000_unsol_verbs },
++ .num_dacs = ARRAY_SIZE(alc262_dac_nids),
++ .dac_nids = alc262_dac_nids,
++ .hp_nid = 0x03,
++ .dig_out_nid = ALC262_DIGOUT_NID,
++ .num_channel_mode = ARRAY_SIZE(alc262_modes),
++ .channel_mode = alc262_modes,
++ .input_mux = &alc262_fujitsu_capture_source,
++ .unsol_event = alc262_lenovo_3000_unsol_event,
++ },
+ };
+
+ static int patch_alc262(struct hda_codec *codec)
+@@ -9472,12 +9674,14 @@ static int patch_alc262(struct hda_codec *codec)
+ if (wcap != AC_WID_AUD_IN) {
+ spec->adc_nids = alc262_adc_nids_alt;
+ spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt);
++ spec->capsrc_nids = alc262_capsrc_nids_alt;
+ spec->mixers[spec->num_mixers] =
+ alc262_capture_alt_mixer;
+ spec->num_mixers++;
+ } else {
+ spec->adc_nids = alc262_adc_nids;
+ spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids);
++ spec->capsrc_nids = alc262_capsrc_nids;
+ spec->mixers[spec->num_mixers] = alc262_capture_mixer;
+ spec->num_mixers++;
+ }
+@@ -9517,6 +9721,8 @@ static hda_nid_t alc268_adc_nids_alt[1] = {
+ 0x08
+ };
+
++static hda_nid_t alc268_capsrc_nids[2] = { 0x23, 0x24 };
++
+ static struct snd_kcontrol_new alc268_base_mixer[] = {
+ /* output mixer control */
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
+@@ -9529,6 +9735,22 @@ static struct snd_kcontrol_new alc268_base_mixer[] = {
+ { }
+ };
+
++/* bind Beep switches of both NID 0x0f and 0x10 */
++static struct hda_bind_ctls alc268_bind_beep_sw = {
++ .ops = &snd_hda_bind_sw,
++ .values = {
++ HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
++ HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
++ 0
++ },
++};
++
++static struct snd_kcontrol_new alc268_beep_mixer[] = {
++ HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
++ HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
++ { }
++};
++
+ static struct hda_verb alc268_eapd_verbs[] = {
+ {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
+ {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
+@@ -9613,8 +9835,12 @@ static struct snd_kcontrol_new alc268_acer_mixer[] = {
+ };
+
+ static struct hda_verb alc268_acer_verbs[] = {
++ {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* internal dmic? */
++ {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
++ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
++ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+
+ {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+ { }
+@@ -9685,6 +9911,64 @@ static void alc268_dell_unsol_event(struct hda_codec *codec,
+
+ #define alc268_dell_init_hook alc268_dell_automute
+
++static struct snd_kcontrol_new alc267_quanta_il1_mixer[] = {
++ HDA_CODEC_VOLUME("Speaker Playback Volume", 0x2, 0x0, HDA_OUTPUT),
++ HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
++ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
++ HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
++ HDA_CODEC_VOLUME("Mic Capture Volume", 0x23, 0x0, HDA_OUTPUT),
++ HDA_BIND_MUTE("Mic Capture Switch", 0x23, 2, HDA_OUTPUT),
++ HDA_CODEC_VOLUME("Ext Mic Boost", 0x18, 0, HDA_INPUT),
++ HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
++ { }
++};
++
++static struct hda_verb alc267_quanta_il1_verbs[] = {
++ {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
++ {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
++ { }
++};
++
++static void alc267_quanta_il1_hp_automute(struct hda_codec *codec)
++{
++ unsigned int present;
++
++ present = snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_PIN_SENSE, 0)
++ & AC_PINSENSE_PRESENCE;
++ snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
++ present ? 0 : PIN_OUT);
++}
++
++static void alc267_quanta_il1_mic_automute(struct hda_codec *codec)
++{
++ unsigned int present;
++
++ present = snd_hda_codec_read(codec, 0x18, 0,
++ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
++ snd_hda_codec_write(codec, 0x23, 0,
++ AC_VERB_SET_CONNECT_SEL,
++ present ? 0x00 : 0x01);
++}
++
++static void alc267_quanta_il1_automute(struct hda_codec *codec)
++{
++ alc267_quanta_il1_hp_automute(codec);
++ alc267_quanta_il1_mic_automute(codec);
++}
++
++static void alc267_quanta_il1_unsol_event(struct hda_codec *codec,
++ unsigned int res)
++{
++ switch (res >> 26) {
++ case ALC880_HP_EVENT:
++ alc267_quanta_il1_hp_automute(codec);
++ break;
++ case ALC880_MIC_EVENT:
++ alc267_quanta_il1_mic_automute(codec);
++ break;
++ }
++}
++
+ /*
+ * generic initialization of ADC, input mixers and output mixers
+ */
+@@ -9725,7 +10009,11 @@ static struct hda_verb alc268_base_init_verbs[] = {
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+- {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
++
++ /* set PCBEEP vol = 0, mute connections */
++ {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
++ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
++ {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+
+ /* Unmute Selector 23h,24h and set the default input to mic-in */
+
+@@ -9764,29 +10052,17 @@ static struct hda_verb alc268_volume_init_verbs[] = {
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+
+- /* set PCBEEP vol = 0 */
+- {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, (0xb000 | (0x00 << 8))},
++ /* set PCBEEP vol = 0, mute connections */
++ {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
++ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
++ {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+
+ { }
+ };
+
+ #define alc268_mux_enum_info alc_mux_enum_info
+ #define alc268_mux_enum_get alc_mux_enum_get
+-
+-static int alc268_mux_enum_put(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_value *ucontrol)
+-{
+- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+- struct alc_spec *spec = codec->spec;
+-
+- unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+- static hda_nid_t capture_mixers[3] = { 0x23, 0x24 };
+- hda_nid_t nid = capture_mixers[adc_idx];
+-
+- return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
+- nid,
+- &spec->cur_mux[adc_idx]);
+-}
++#define alc268_mux_enum_put alc_mux_enum_put
+
+ static struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
+ HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
+@@ -9836,13 +10112,17 @@ static struct hda_input_mux alc268_capture_source = {
+ },
+ };
+
++static struct hda_input_mux alc268_acer_capture_source = {
++ .num_items = 3,
++ .items = {
++ { "Mic", 0x0 },
++ { "Internal Mic", 0x6 },
++ { "Line", 0x2 },
++ },
++};
++
+ #ifdef CONFIG_SND_DEBUG
+ static struct snd_kcontrol_new alc268_test_mixer[] = {
+- HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
+- HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
+- HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+-
+ /* Volume widgets */
+ HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+@@ -9981,6 +10261,10 @@ static int alc268_auto_create_analog_input_ctls(struct alc_spec *spec,
+ case 0x1c:
+ idx1 = 3; /* CD */
+ break;
++ case 0x12:
++ case 0x13:
++ idx1 = 6; /* digital mics */
++ break;
+ default:
+ continue;
+ }
+@@ -10073,6 +10357,9 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
+ if (spec->kctl_alloc)
+ spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+
++ if (spec->autocfg.speaker_pins[0] != 0x1d)
++ spec->mixers[spec->num_mixers++] = alc268_beep_mixer;
++
+ spec->init_verbs[spec->num_init_verbs++] = alc268_volume_init_verbs;
+ spec->num_mux_defs = 1;
+ spec->input_mux = &spec->private_imux;
+@@ -10091,20 +10378,25 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
+ /* init callback for auto-configuration model -- overriding the default init */
+ static void alc268_auto_init(struct hda_codec *codec)
+ {
++ struct alc_spec *spec = codec->spec;
+ alc268_auto_init_multi_out(codec);
+ alc268_auto_init_hp_out(codec);
+ alc268_auto_init_mono_speaker_out(codec);
+ alc268_auto_init_analog_input(codec);
++ if (spec->unsol_event)
++ alc_sku_automute(codec);
+ }
+
+ /*
+ * configuration and preset
+ */
+ static const char *alc268_models[ALC268_MODEL_LAST] = {
++ [ALC267_QUANTA_IL1] = "quanta-il1",
+ [ALC268_3ST] = "3stack",
+ [ALC268_TOSHIBA] = "toshiba",
+ [ALC268_ACER] = "acer",
+ [ALC268_DELL] = "dell",
++ [ALC268_ZEPTO] = "zepto",
+ #ifdef CONFIG_SND_DEBUG
+ [ALC268_TEST] = "test",
+ #endif
+@@ -10112,6 +10404,7 @@ static const char *alc268_models[ALC268_MODEL_LAST] = {
+ };
+
+ static struct snd_pci_quirk alc268_cfg_tbl[] = {
++ SND_PCI_QUIRK(0x1025, 0x011e, "Acer Aspire 5720z", ALC268_ACER),
+ SND_PCI_QUIRK(0x1025, 0x0126, "Acer", ALC268_ACER),
+ SND_PCI_QUIRK(0x1025, 0x012e, "Acer Aspire 5310", ALC268_ACER),
+ SND_PCI_QUIRK(0x1025, 0x0130, "Acer Extensa 5210", ALC268_ACER),
+@@ -10122,17 +10415,36 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = {
+ SND_PCI_QUIRK(0x1179, 0xff10, "TOSHIBA A205", ALC268_TOSHIBA),
+ SND_PCI_QUIRK(0x1179, 0xff50, "TOSHIBA A305", ALC268_TOSHIBA),
+ SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER),
++ SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1),
++ SND_PCI_QUIRK(0x1170, 0x0040, "ZEPTO", ALC268_ZEPTO),
+ {}
+ };
+
+ static struct alc_config_preset alc268_presets[] = {
++ [ALC267_QUANTA_IL1] = {
++ .mixers = { alc267_quanta_il1_mixer },
++ .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
++ alc267_quanta_il1_verbs },
++ .num_dacs = ARRAY_SIZE(alc268_dac_nids),
++ .dac_nids = alc268_dac_nids,
++ .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
++ .adc_nids = alc268_adc_nids_alt,
++ .hp_nid = 0x03,
++ .num_channel_mode = ARRAY_SIZE(alc268_modes),
++ .channel_mode = alc268_modes,
++ .input_mux = &alc268_capture_source,
++ .unsol_event = alc267_quanta_il1_unsol_event,
++ .init_hook = alc267_quanta_il1_automute,
++ },
+ [ALC268_3ST] = {
+- .mixers = { alc268_base_mixer, alc268_capture_alt_mixer },
++ .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
++ alc268_beep_mixer },
+ .init_verbs = { alc268_base_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc268_dac_nids),
+ .dac_nids = alc268_dac_nids,
+ .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+ .adc_nids = alc268_adc_nids_alt,
++ .capsrc_nids = alc268_capsrc_nids,
+ .hp_nid = 0x03,
+ .dig_out_nid = ALC268_DIGOUT_NID,
+ .num_channel_mode = ARRAY_SIZE(alc268_modes),
+@@ -10140,13 +10452,15 @@ static struct alc_config_preset alc268_presets[] = {
+ .input_mux = &alc268_capture_source,
+ },
+ [ALC268_TOSHIBA] = {
+- .mixers = { alc268_base_mixer, alc268_capture_alt_mixer },
++ .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
++ alc268_beep_mixer },
+ .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
+ alc268_toshiba_verbs },
+ .num_dacs = ARRAY_SIZE(alc268_dac_nids),
+ .dac_nids = alc268_dac_nids,
+ .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+ .adc_nids = alc268_adc_nids_alt,
++ .capsrc_nids = alc268_capsrc_nids,
+ .hp_nid = 0x03,
+ .num_channel_mode = ARRAY_SIZE(alc268_modes),
+ .channel_mode = alc268_modes,
+@@ -10155,22 +10469,24 @@ static struct alc_config_preset alc268_presets[] = {
+ .init_hook = alc268_toshiba_automute,
+ },
+ [ALC268_ACER] = {
+- .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer },
++ .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer,
++ alc268_beep_mixer },
+ .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
+ alc268_acer_verbs },
+ .num_dacs = ARRAY_SIZE(alc268_dac_nids),
+ .dac_nids = alc268_dac_nids,
+ .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+ .adc_nids = alc268_adc_nids_alt,
++ .capsrc_nids = alc268_capsrc_nids,
+ .hp_nid = 0x02,
+ .num_channel_mode = ARRAY_SIZE(alc268_modes),
+ .channel_mode = alc268_modes,
+- .input_mux = &alc268_capture_source,
++ .input_mux = &alc268_acer_capture_source,
+ .unsol_event = alc268_acer_unsol_event,
+ .init_hook = alc268_acer_init_hook,
+ },
+ [ALC268_DELL] = {
+- .mixers = { alc268_dell_mixer },
++ .mixers = { alc268_dell_mixer, alc268_beep_mixer },
+ .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
+ alc268_dell_verbs },
+ .num_dacs = ARRAY_SIZE(alc268_dac_nids),
+@@ -10182,6 +10498,24 @@ static struct alc_config_preset alc268_presets[] = {
+ .init_hook = alc268_dell_init_hook,
+ .input_mux = &alc268_capture_source,
+ },
++ [ALC268_ZEPTO] = {
++ .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
++ alc268_beep_mixer },
++ .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
++ alc268_toshiba_verbs },
++ .num_dacs = ARRAY_SIZE(alc268_dac_nids),
++ .dac_nids = alc268_dac_nids,
++ .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
++ .adc_nids = alc268_adc_nids_alt,
++ .capsrc_nids = alc268_capsrc_nids,
++ .hp_nid = 0x03,
++ .dig_out_nid = ALC268_DIGOUT_NID,
++ .num_channel_mode = ARRAY_SIZE(alc268_modes),
++ .channel_mode = alc268_modes,
++ .input_mux = &alc268_capture_source,
++ .unsol_event = alc268_toshiba_unsol_event,
++ .init_hook = alc268_toshiba_automute
++ },
+ #ifdef CONFIG_SND_DEBUG
+ [ALC268_TEST] = {
+ .mixers = { alc268_test_mixer, alc268_capture_mixer },
+@@ -10191,6 +10525,7 @@ static struct alc_config_preset alc268_presets[] = {
+ .dac_nids = alc268_dac_nids,
+ .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+ .adc_nids = alc268_adc_nids_alt,
++ .capsrc_nids = alc268_capsrc_nids,
+ .hp_nid = 0x03,
+ .dig_out_nid = ALC268_DIGOUT_NID,
+ .num_channel_mode = ARRAY_SIZE(alc268_modes),
+@@ -10247,13 +10582,22 @@ static int patch_alc268(struct hda_codec *codec)
+ spec->stream_name_digital = "ALC268 Digital";
+ spec->stream_digital_playback = &alc268_pcm_digital_playback;
+
++ if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
++ /* override the amp caps for beep generator */
++ snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
++ (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
++ (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
++ (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
++ (0 << AC_AMPCAP_MUTE_SHIFT));
++
+ if (!spec->adc_nids && spec->input_mux) {
+ /* check whether NID 0x07 is valid */
+ unsigned int wcap = get_wcaps(codec, 0x07);
++ int i;
+
+ /* get type */
+ wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+- if (wcap != AC_WID_AUD_IN) {
++ if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
+ spec->adc_nids = alc268_adc_nids_alt;
+ spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt);
+ spec->mixers[spec->num_mixers] =
+@@ -10266,6 +10610,12 @@ static int patch_alc268(struct hda_codec *codec)
+ alc268_capture_mixer;
+ spec->num_mixers++;
+ }
++ spec->capsrc_nids = alc268_capsrc_nids;
++ /* set default input source */
++ for (i = 0; i < spec->num_adc_nids; i++)
++ snd_hda_codec_write_cache(codec, alc268_capsrc_nids[i],
++ 0, AC_VERB_SET_CONNECT_SEL,
++ spec->input_mux->items[0].index);
+ }
+
+ spec->vmaster_nid = 0x02;
+@@ -10539,9 +10889,12 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
+ /* init callback for auto-configuration model -- overriding the default init */
+ static void alc269_auto_init(struct hda_codec *codec)
+ {
++ struct alc_spec *spec = codec->spec;
+ alc269_auto_init_multi_out(codec);
+ alc269_auto_init_hp_out(codec);
+ alc269_auto_init_analog_input(codec);
++ if (spec->unsol_event)
++ alc_sku_automute(codec);
+ }
+
+ /*
+@@ -11463,13 +11816,7 @@ static void alc861_auto_set_output_and_unmute(struct hda_codec *codec,
+ hda_nid_t nid,
+ int pin_type, int dac_idx)
+ {
+- /* set as output */
+-
+- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+- pin_type);
+- snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+- AMP_OUT_UNMUTE);
+-
++ alc_set_pin_output(codec, nid, pin_type);
+ }
+
+ static void alc861_auto_init_multi_out(struct hda_codec *codec)
+@@ -11496,6 +11843,9 @@ static void alc861_auto_init_hp_out(struct hda_codec *codec)
+ if (pin) /* connect to front */
+ alc861_auto_set_output_and_unmute(codec, pin, PIN_HP,
+ spec->multiout.dac_nids[0]);
++ pin = spec->autocfg.speaker_pins[0];
++ if (pin)
++ alc861_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
+ }
+
+ static void alc861_auto_init_analog_input(struct hda_codec *codec)
+@@ -11568,9 +11918,12 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
+ /* additional initialization for auto-configuration model */
+ static void alc861_auto_init(struct hda_codec *codec)
+ {
++ struct alc_spec *spec = codec->spec;
+ alc861_auto_init_multi_out(codec);
+ alc861_auto_init_hp_out(codec);
+ alc861_auto_init_analog_input(codec);
++ if (spec->unsol_event)
++ alc_sku_automute(codec);
+ }
+
+ #ifdef CONFIG_SND_HDA_POWER_SAVE
+@@ -11822,6 +12175,8 @@ static hda_nid_t alc861vd_adc_nids[1] = {
+ 0x09,
+ };
+
++static hda_nid_t alc861vd_capsrc_nids[1] = { 0x22 };
++
+ /* input MUX */
+ /* FIXME: should be a matrix-type input source selection */
+ static struct hda_input_mux alc861vd_capture_source = {
+@@ -11835,11 +12190,10 @@ static struct hda_input_mux alc861vd_capture_source = {
+ };
+
+ static struct hda_input_mux alc861vd_dallas_capture_source = {
+- .num_items = 3,
++ .num_items = 2,
+ .items = {
+- { "Front Mic", 0x0 },
+- { "ATAPI Mic", 0x1 },
+- { "Line In", 0x5 },
++ { "Ext Mic", 0x0 },
++ { "Int Mic", 0x1 },
+ },
+ };
+
+@@ -11853,33 +12207,8 @@ static struct hda_input_mux alc861vd_hp_capture_source = {
+
+ #define alc861vd_mux_enum_info alc_mux_enum_info
+ #define alc861vd_mux_enum_get alc_mux_enum_get
+-
+-static int alc861vd_mux_enum_put(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_value *ucontrol)
+-{
+- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+- struct alc_spec *spec = codec->spec;
+- const struct hda_input_mux *imux = spec->input_mux;
+- unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+- static hda_nid_t capture_mixers[1] = { 0x22 };
+- hda_nid_t nid = capture_mixers[adc_idx];
+- unsigned int *cur_val = &spec->cur_mux[adc_idx];
+- unsigned int i, idx;
+-
+- idx = ucontrol->value.enumerated.item[0];
+- if (idx >= imux->num_items)
+- idx = imux->num_items - 1;
+- if (*cur_val == idx)
+- return 0;
+- for (i = 0; i < imux->num_items; i++) {
+- unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
+- snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
+- imux->items[i].index,
+- HDA_AMP_MUTE, v);
+- }
+- *cur_val = idx;
+- return 1;
+-}
++/* ALC861VD has the ALC882-type input selection (but has only one ADC) */
++#define alc861vd_mux_enum_put alc882_mux_enum_put
+
+ /*
+ * 2ch mode
+@@ -12034,20 +12363,22 @@ static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = {
+ { } /* end */
+ };
+
+-/* Pin assignment: Front=0x14, HP = 0x15,
+- * Front Mic=0x18, ATAPI Mic = 0x19, Line In = 0x1d
++/* Pin assignment: Speaker=0x14, HP = 0x15,
++ * Ext Mic=0x18, Int Mic = 0x19, CD = 0x1c, PC Beep = 0x1d
+ */
+ static struct snd_kcontrol_new alc861vd_dallas_mixer[] = {
+- HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
++ HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
++ HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
+- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+- HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+- HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x05, HDA_INPUT),
+- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x05, HDA_INPUT),
++ HDA_CODEC_VOLUME("Ext Mic Boost", 0x18, 0, HDA_INPUT),
++ HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
++ HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
++ HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
++ HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
++ HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
++ HDA_CODEC_VOLUME("PC Beep Volume", 0x0b, 0x05, HDA_INPUT),
++ HDA_CODEC_MUTE("PC Beep Switch", 0x0b, 0x05, HDA_INPUT),
+ { } /* end */
+ };
+
+@@ -12348,6 +12679,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
+ /*SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),*/ /*lenovo*/
+ SND_PCI_QUIRK(0x1179, 0xff01, "DALLAS", ALC861VD_DALLAS),
+ SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO),
++ SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_DALLAS),
+ SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG),
+ SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO),
+ SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO),
+@@ -12362,8 +12694,6 @@ static struct alc_config_preset alc861vd_presets[] = {
+ alc861vd_3stack_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
+ .dac_nids = alc660vd_dac_nids,
+- .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
+- .adc_nids = alc861vd_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+ .channel_mode = alc861vd_3stack_2ch_modes,
+ .input_mux = &alc861vd_capture_source,
+@@ -12375,8 +12705,6 @@ static struct alc_config_preset alc861vd_presets[] = {
+ .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
+ .dac_nids = alc660vd_dac_nids,
+ .dig_out_nid = ALC861VD_DIGOUT_NID,
+- .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
+- .adc_nids = alc861vd_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+ .channel_mode = alc861vd_3stack_2ch_modes,
+ .input_mux = &alc861vd_capture_source,
+@@ -12421,8 +12749,6 @@ static struct alc_config_preset alc861vd_presets[] = {
+ alc861vd_lenovo_unsol_verbs },
+ .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
+ .dac_nids = alc660vd_dac_nids,
+- .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
+- .adc_nids = alc861vd_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+ .channel_mode = alc861vd_3stack_2ch_modes,
+ .input_mux = &alc861vd_capture_source,
+@@ -12434,8 +12760,6 @@ static struct alc_config_preset alc861vd_presets[] = {
+ .init_verbs = { alc861vd_dallas_verbs },
+ .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
+ .dac_nids = alc861vd_dac_nids,
+- .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
+- .adc_nids = alc861vd_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+ .channel_mode = alc861vd_3stack_2ch_modes,
+ .input_mux = &alc861vd_dallas_capture_source,
+@@ -12447,9 +12771,7 @@ static struct alc_config_preset alc861vd_presets[] = {
+ .init_verbs = { alc861vd_dallas_verbs, alc861vd_eapd_verbs },
+ .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
+ .dac_nids = alc861vd_dac_nids,
+- .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
+ .dig_out_nid = ALC861VD_DIGOUT_NID,
+- .adc_nids = alc861vd_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+ .channel_mode = alc861vd_3stack_2ch_modes,
+ .input_mux = &alc861vd_hp_capture_source,
+@@ -12464,11 +12786,7 @@ static struct alc_config_preset alc861vd_presets[] = {
+ static void alc861vd_auto_set_output_and_unmute(struct hda_codec *codec,
+ hda_nid_t nid, int pin_type, int dac_idx)
+ {
+- /* set as output */
+- snd_hda_codec_write(codec, nid, 0,
+- AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
+- snd_hda_codec_write(codec, nid, 0,
+- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
++ alc_set_pin_output(codec, nid, pin_type);
+ }
+
+ static void alc861vd_auto_init_multi_out(struct hda_codec *codec)
+@@ -12495,6 +12813,9 @@ static void alc861vd_auto_init_hp_out(struct hda_codec *codec)
+ pin = spec->autocfg.hp_pins[0];
+ if (pin) /* connect to front and use dac 0 */
+ alc861vd_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
++ pin = spec->autocfg.speaker_pins[0];
++ if (pin)
++ alc861vd_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
+ }
+
+ #define alc861vd_is_input_pin(nid) alc880_is_input_pin(nid)
+@@ -12698,9 +13019,12 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
+ /* additional initialization for auto-configuration model */
+ static void alc861vd_auto_init(struct hda_codec *codec)
+ {
++ struct alc_spec *spec = codec->spec;
+ alc861vd_auto_init_multi_out(codec);
+ alc861vd_auto_init_hp_out(codec);
+ alc861vd_auto_init_analog_input(codec);
++ if (spec->unsol_event)
++ alc_sku_automute(codec);
+ }
+
+ static int patch_alc861vd(struct hda_codec *codec)
+@@ -12751,6 +13075,7 @@ static int patch_alc861vd(struct hda_codec *codec)
+
+ spec->adc_nids = alc861vd_adc_nids;
+ spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
++ spec->capsrc_nids = alc861vd_capsrc_nids;
+
+ spec->mixers[spec->num_mixers] = alc861vd_capture_mixer;
+ spec->num_mixers++;
+@@ -12792,9 +13117,11 @@ static hda_nid_t alc662_adc_nids[1] = {
+ /* ADC1-2 */
+ 0x09,
+ };
++
++static hda_nid_t alc662_capsrc_nids[1] = { 0x22 };
++
+ /* input MUX */
+ /* FIXME: should be a matrix-type input source selection */
+-
+ static struct hda_input_mux alc662_capture_source = {
+ .num_items = 4,
+ .items = {
+@@ -12823,33 +13150,8 @@ static struct hda_input_mux alc662_eeepc_capture_source = {
+
+ #define alc662_mux_enum_info alc_mux_enum_info
+ #define alc662_mux_enum_get alc_mux_enum_get
++#define alc662_mux_enum_put alc882_mux_enum_put
+
+-static int alc662_mux_enum_put(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_value *ucontrol)
+-{
+- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+- struct alc_spec *spec = codec->spec;
+- const struct hda_input_mux *imux = spec->input_mux;
+- unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+- static hda_nid_t capture_mixers[2] = { 0x23, 0x22 };
+- hda_nid_t nid = capture_mixers[adc_idx];
+- unsigned int *cur_val = &spec->cur_mux[adc_idx];
+- unsigned int i, idx;
+-
+- idx = ucontrol->value.enumerated.item[0];
+- if (idx >= imux->num_items)
+- idx = imux->num_items - 1;
+- if (*cur_val == idx)
+- return 0;
+- for (i = 0; i < imux->num_items; i++) {
+- unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
+- snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
+- imux->items[i].index,
+- HDA_AMP_MUTE, v);
+- }
+- *cur_val = idx;
+- return 1;
+-}
+ /*
+ * 2ch mode
+ */
+@@ -12918,13 +13220,13 @@ static struct hda_channel_mode alc662_5stack_modes[2] = {
+ static struct snd_kcontrol_new alc662_base_mixer[] = {
+ /* output mixer control */
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
+- HDA_CODEC_MUTE("Front Playback Switch", 0x02, 0x0, HDA_OUTPUT),
++ HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Surround Playback Volume", 0x3, 0x0, HDA_OUTPUT),
+- HDA_CODEC_MUTE("Surround Playback Switch", 0x03, 0x0, HDA_OUTPUT),
++ HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
+- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT),
+- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT),
++ HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
++ HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+
+ /*Input mixer control */
+@@ -12941,7 +13243,7 @@ static struct snd_kcontrol_new alc662_base_mixer[] = {
+
+ static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+- HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
++ HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+@@ -12958,13 +13260,13 @@ static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
+
+ static struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+- HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
++ HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+- HDA_BIND_MUTE("Surround Playback Switch", 0x03, 2, HDA_INPUT),
++ HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
+- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT),
+- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT),
++ HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
++ HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+@@ -13313,6 +13615,7 @@ static const char *alc662_models[ALC662_MODEL_LAST] = {
+ };
+
+ static struct snd_pci_quirk alc662_cfg_tbl[] = {
++ SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG),
+ SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701),
+ SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20),
+ SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
+@@ -13326,8 +13629,6 @@ static struct alc_config_preset alc662_presets[] = {
+ .num_dacs = ARRAY_SIZE(alc662_dac_nids),
+ .dac_nids = alc662_dac_nids,
+ .dig_out_nid = ALC662_DIGOUT_NID,
+- .num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
+- .adc_nids = alc662_adc_nids,
+ .dig_in_nid = ALC662_DIGIN_NID,
+ .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+ .channel_mode = alc662_3ST_2ch_modes,
+@@ -13340,8 +13641,6 @@ static struct alc_config_preset alc662_presets[] = {
+ .num_dacs = ARRAY_SIZE(alc662_dac_nids),
+ .dac_nids = alc662_dac_nids,
+ .dig_out_nid = ALC662_DIGOUT_NID,
+- .num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
+- .adc_nids = alc662_adc_nids,
+ .dig_in_nid = ALC662_DIGIN_NID,
+ .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
+ .channel_mode = alc662_3ST_6ch_modes,
+@@ -13354,8 +13653,6 @@ static struct alc_config_preset alc662_presets[] = {
+ .init_verbs = { alc662_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc662_dac_nids),
+ .dac_nids = alc662_dac_nids,
+- .num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
+- .adc_nids = alc662_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
+ .channel_mode = alc662_3ST_6ch_modes,
+ .need_dac_fix = 1,
+@@ -13368,8 +13665,6 @@ static struct alc_config_preset alc662_presets[] = {
+ .num_dacs = ARRAY_SIZE(alc662_dac_nids),
+ .dac_nids = alc662_dac_nids,
+ .dig_out_nid = ALC662_DIGOUT_NID,
+- .num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
+- .adc_nids = alc662_adc_nids,
+ .dig_in_nid = ALC662_DIGIN_NID,
+ .num_channel_mode = ARRAY_SIZE(alc662_5stack_modes),
+ .channel_mode = alc662_5stack_modes,
+@@ -13380,8 +13675,6 @@ static struct alc_config_preset alc662_presets[] = {
+ .init_verbs = { alc662_init_verbs, alc662_sue_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc662_dac_nids),
+ .dac_nids = alc662_dac_nids,
+- .num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
+- .adc_nids = alc662_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+ .channel_mode = alc662_3ST_2ch_modes,
+ .input_mux = &alc662_lenovo_101e_capture_source,
+@@ -13394,8 +13687,6 @@ static struct alc_config_preset alc662_presets[] = {
+ alc662_eeepc_sue_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc662_dac_nids),
+ .dac_nids = alc662_dac_nids,
+- .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
+- .adc_nids = alc662_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+ .channel_mode = alc662_3ST_2ch_modes,
+ .input_mux = &alc662_eeepc_capture_source,
+@@ -13409,8 +13700,6 @@ static struct alc_config_preset alc662_presets[] = {
+ alc662_eeepc_ep20_sue_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc662_dac_nids),
+ .dac_nids = alc662_dac_nids,
+- .num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
+- .adc_nids = alc662_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
+ .channel_mode = alc662_3ST_6ch_modes,
+ .input_mux = &alc662_lenovo_101e_capture_source,
+@@ -13556,11 +13845,7 @@ static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
+ hda_nid_t nid, int pin_type,
+ int dac_idx)
+ {
+- /* set as output */
+- snd_hda_codec_write(codec, nid, 0,
+- AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
+- snd_hda_codec_write(codec, nid, 0,
+- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
++ alc_set_pin_output(codec, nid, pin_type);
+ /* need the manual connection? */
+ if (alc880_is_multi_pin(nid)) {
+ struct alc_spec *spec = codec->spec;
+@@ -13595,6 +13880,9 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec)
+ if (pin) /* connect to front */
+ /* use dac 0 */
+ alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
++ pin = spec->autocfg.speaker_pins[0];
++ if (pin)
++ alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
+ }
+
+ #define alc662_is_input_pin(nid) alc880_is_input_pin(nid)
+@@ -13672,9 +13960,12 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
+ /* additional initialization for auto-configuration model */
+ static void alc662_auto_init(struct hda_codec *codec)
+ {
++ struct alc_spec *spec = codec->spec;
+ alc662_auto_init_multi_out(codec);
+ alc662_auto_init_hp_out(codec);
+ alc662_auto_init_analog_input(codec);
++ if (spec->unsol_event)
++ alc_sku_automute(codec);
+ }
+
+ static int patch_alc662(struct hda_codec *codec)
+@@ -13722,10 +14013,9 @@ static int patch_alc662(struct hda_codec *codec)
+ spec->stream_digital_playback = &alc662_pcm_digital_playback;
+ spec->stream_digital_capture = &alc662_pcm_digital_capture;
+
+- if (!spec->adc_nids && spec->input_mux) {
+- spec->adc_nids = alc662_adc_nids;
+- spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
+- }
++ spec->adc_nids = alc662_adc_nids;
++ spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
++ spec->capsrc_nids = alc662_capsrc_nids;
+
+ spec->vmaster_nid = 0x02;
+
+@@ -13761,6 +14051,8 @@ struct hda_codec_preset snd_hda_preset_realtek[] = {
+ { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
+ { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
+ { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 },
++ { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
++ .patch = patch_alc882 }, /* should be patch_alc883() in future */
+ { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
+ { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 },
+ { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc883 },
+diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c
+index d22f5a6..9332b63 100644
+--- a/sound/pci/hda/patch_si3054.c
++++ b/sound/pci/hda/patch_si3054.c
+@@ -28,7 +28,7 @@
+ #include <sound/core.h>
+ #include "hda_codec.h"
+ #include "hda_local.h"
+-
++#include "hda_patch.h"
+
+ /* si3054 verbs */
+ #define SI3054_VERB_READ_NODE 0x900
+@@ -206,7 +206,7 @@ static int si3054_build_pcms(struct hda_codec *codec)
+ info->name = "Si3054 Modem";
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = si3054_pcm;
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] = si3054_pcm;
+- info->is_modem = 1;
++ info->pcm_type = HDA_PCM_TYPE_MODEM;
+ return 0;
+ }
+
+diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
+index caf48ed..b3a15d6 100644
+--- a/sound/pci/hda/patch_sigmatel.c
++++ b/sound/pci/hda/patch_sigmatel.c
+@@ -32,6 +32,7 @@
+ #include <sound/asoundef.h>
+ #include "hda_codec.h"
+ #include "hda_local.h"
++#include "hda_patch.h"
+
+ #define NUM_CONTROL_ALLOC 32
+ #define STAC_PWR_EVENT 0x20
+@@ -39,6 +40,7 @@
+
+ enum {
+ STAC_REF,
++ STAC_9200_OQO,
+ STAC_9200_DELL_D21,
+ STAC_9200_DELL_D22,
+ STAC_9200_DELL_D23,
+@@ -50,6 +52,7 @@ enum {
+ STAC_9200_DELL_M26,
+ STAC_9200_DELL_M27,
+ STAC_9200_GATEWAY,
++ STAC_9200_PANASONIC,
+ STAC_9200_MODELS
+ };
+
+@@ -63,11 +66,14 @@ enum {
+
+ enum {
+ STAC_92HD73XX_REF,
++ STAC_DELL_M6,
+ STAC_92HD73XX_MODELS
+ };
+
+ enum {
+ STAC_92HD71BXX_REF,
++ STAC_DELL_M4_1,
++ STAC_DELL_M4_2,
+ STAC_92HD71BXX_MODELS
+ };
+
+@@ -123,6 +129,7 @@ struct sigmatel_spec {
+ unsigned int hp_detect: 1;
+
+ /* gpio lines */
++ unsigned int eapd_mask;
+ unsigned int gpio_mask;
+ unsigned int gpio_dir;
+ unsigned int gpio_data;
+@@ -135,6 +142,7 @@ struct sigmatel_spec {
+ /* power management */
+ unsigned int num_pwrs;
+ hda_nid_t *pwr_nids;
++ hda_nid_t *dac_list;
+
+ /* playback */
+ struct hda_input_mux *mono_mux;
+@@ -173,6 +181,7 @@ struct sigmatel_spec {
+ /* i/o switches */
+ unsigned int io_switch[2];
+ unsigned int clfe_swap;
++ unsigned int hp_switch;
+ unsigned int aloopback;
+
+ struct hda_pcm pcm_rec[2]; /* PCM information */
+@@ -184,9 +193,6 @@ struct sigmatel_spec {
+ struct hda_input_mux private_dimux;
+ struct hda_input_mux private_imux;
+ struct hda_input_mux private_mono_mux;
+-
+- /* virtual master */
+- unsigned int vmaster_tlv[4];
+ };
+
+ static hda_nid_t stac9200_adc_nids[1] = {
+@@ -244,7 +250,7 @@ static hda_nid_t stac92hd71bxx_dmux_nids[1] = {
+ 0x1c,
+ };
+
+-static hda_nid_t stac92hd71bxx_dac_nids[2] = {
++static hda_nid_t stac92hd71bxx_dac_nids[1] = {
+ 0x10, /*0x11, */
+ };
+
+@@ -290,6 +296,10 @@ static hda_nid_t stac927x_mux_nids[3] = {
+ 0x15, 0x16, 0x17
+ };
+
++static hda_nid_t stac927x_dac_nids[6] = {
++ 0x02, 0x03, 0x04, 0x05, 0x06, 0
++};
++
+ static hda_nid_t stac927x_dmux_nids[1] = {
+ 0x1b,
+ };
+@@ -331,10 +341,10 @@ static hda_nid_t stac922x_pin_nids[10] = {
+ 0x0f, 0x10, 0x11, 0x15, 0x1b,
+ };
+
+-static hda_nid_t stac92hd73xx_pin_nids[12] = {
++static hda_nid_t stac92hd73xx_pin_nids[13] = {
+ 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+ 0x0f, 0x10, 0x11, 0x12, 0x13,
+- 0x14, 0x22
++ 0x14, 0x1e, 0x22
+ };
+
+ static hda_nid_t stac92hd71bxx_pin_nids[10] = {
+@@ -527,6 +537,43 @@ static struct hda_verb stac92hd73xx_6ch_core_init[] = {
+ {}
+ };
+
++static struct hda_verb dell_eq_core_init[] = {
++ /* set master volume to max value without distortion
++ * and direct control */
++ { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xec},
++ /* setup audio connections */
++ { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
++ { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01},
++ { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x02},
++ /* setup adcs to point to mixer */
++ { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b},
++ { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b},
++ /* setup import muxs */
++ { 0x28, AC_VERB_SET_CONNECT_SEL, 0x01},
++ { 0x29, AC_VERB_SET_CONNECT_SEL, 0x01},
++ { 0x2a, AC_VERB_SET_CONNECT_SEL, 0x01},
++ { 0x2b, AC_VERB_SET_CONNECT_SEL, 0x00},
++ {}
++};
++
++static struct hda_verb dell_m6_core_init[] = {
++ /* set master volume and direct control */
++ { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
++ /* setup audio connections */
++ { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
++ { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01},
++ { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x02},
++ /* setup adcs to point to mixer */
++ { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b},
++ { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b},
++ /* setup import muxs */
++ { 0x28, AC_VERB_SET_CONNECT_SEL, 0x01},
++ { 0x29, AC_VERB_SET_CONNECT_SEL, 0x01},
++ { 0x2a, AC_VERB_SET_CONNECT_SEL, 0x01},
++ { 0x2b, AC_VERB_SET_CONNECT_SEL, 0x00},
++ {}
++};
++
+ static struct hda_verb stac92hd73xx_8ch_core_init[] = {
+ /* set master volume and direct control */
+ { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
+@@ -910,6 +957,11 @@ static int stac92xx_build_controls(struct hda_codec *codec)
+ err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
+ if (err < 0)
+ return err;
++ err = snd_hda_create_spdif_share_sw(codec,
++ &spec->multiout);
++ if (err < 0)
++ return err;
++ spec->multiout.share_spdif = 1;
+ }
+ if (spec->dig_in_nid) {
+ err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
+@@ -919,10 +971,11 @@ static int stac92xx_build_controls(struct hda_codec *codec)
+
+ /* if we have no master control, let's create it */
+ if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
++ unsigned int vmaster_tlv[4];
+ snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0],
+- HDA_OUTPUT, spec->vmaster_tlv);
++ HDA_OUTPUT, vmaster_tlv);
+ err = snd_hda_add_vmaster(codec, "Master Playback Volume",
+- spec->vmaster_tlv, slave_vols);
++ vmaster_tlv, slave_vols);
+ if (err < 0)
+ return err;
+ }
+@@ -1052,9 +1105,15 @@ static unsigned int dell9200_m27_pin_configs[8] = {
+ 0x90170310, 0x04a11020, 0x90170310, 0x40f003fc,
+ };
+
++static unsigned int oqo9200_pin_configs[8] = {
++ 0x40c000f0, 0x404000f1, 0x0221121f, 0x02211210,
++ 0x90170111, 0x90a70120, 0x400000f2, 0x400000f3,
++};
++
+
+ static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = {
+ [STAC_REF] = ref9200_pin_configs,
++ [STAC_9200_OQO] = oqo9200_pin_configs,
+ [STAC_9200_DELL_D21] = dell9200_d21_pin_configs,
+ [STAC_9200_DELL_D22] = dell9200_d22_pin_configs,
+ [STAC_9200_DELL_D23] = dell9200_d23_pin_configs,
+@@ -1065,10 +1124,12 @@ static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = {
+ [STAC_9200_DELL_M25] = dell9200_m25_pin_configs,
+ [STAC_9200_DELL_M26] = dell9200_m26_pin_configs,
+ [STAC_9200_DELL_M27] = dell9200_m27_pin_configs,
++ [STAC_9200_PANASONIC] = ref9200_pin_configs,
+ };
+
+ static const char *stac9200_models[STAC_9200_MODELS] = {
+ [STAC_REF] = "ref",
++ [STAC_9200_OQO] = "oqo",
+ [STAC_9200_DELL_D21] = "dell-d21",
+ [STAC_9200_DELL_D22] = "dell-d22",
+ [STAC_9200_DELL_D23] = "dell-d23",
+@@ -1080,6 +1141,7 @@ static const char *stac9200_models[STAC_9200_MODELS] = {
+ [STAC_9200_DELL_M26] = "dell-m26",
+ [STAC_9200_DELL_M27] = "dell-m27",
+ [STAC_9200_GATEWAY] = "gateway",
++ [STAC_9200_PANASONIC] = "panasonic",
+ };
+
+ static struct snd_pci_quirk stac9200_cfg_tbl[] = {
+@@ -1146,13 +1208,15 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = {
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f6,
+ "unknown Dell", STAC_9200_DELL_M26),
+ /* Panasonic */
+- SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_REF),
++ SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_9200_PANASONIC),
+ /* Gateway machines needs EAPD to be set on resume */
+ SND_PCI_QUIRK(0x107b, 0x0205, "Gateway S-7110M", STAC_9200_GATEWAY),
+ SND_PCI_QUIRK(0x107b, 0x0317, "Gateway MT3423, MX341*",
+ STAC_9200_GATEWAY),
+ SND_PCI_QUIRK(0x107b, 0x0318, "Gateway ML3019, MT3707",
+ STAC_9200_GATEWAY),
++ /* OQO Mobile */
++ SND_PCI_QUIRK(0x1106, 0x3288, "OQO Model 2", STAC_9200_OQO),
+ {} /* terminator */
+ };
+
+@@ -1202,24 +1266,48 @@ static struct snd_pci_quirk stac925x_cfg_tbl[] = {
+ {} /* terminator */
+ };
+
+-static unsigned int ref92hd73xx_pin_configs[12] = {
++static unsigned int ref92hd73xx_pin_configs[13] = {
+ 0x02214030, 0x02a19040, 0x01a19020, 0x02214030,
+ 0x0181302e, 0x01014010, 0x01014020, 0x01014030,
+ 0x02319040, 0x90a000f0, 0x90a000f0, 0x01452050,
++ 0x01452050,
++};
++
++static unsigned int dell_m6_pin_configs[13] = {
++ 0x0321101f, 0x4f00000f, 0x4f0000f0, 0x90170110,
++ 0x03a11020, 0x0321101f, 0x4f0000f0, 0x4f0000f0,
++ 0x4f0000f0, 0x90a60160, 0x4f0000f0, 0x4f0000f0,
++ 0x4f0000f0,
+ };
+
+ static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = {
+- [STAC_92HD73XX_REF] = ref92hd73xx_pin_configs,
++ [STAC_92HD73XX_REF] = ref92hd73xx_pin_configs,
++ [STAC_DELL_M6] = dell_m6_pin_configs,
+ };
+
+ static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = {
+ [STAC_92HD73XX_REF] = "ref",
++ [STAC_DELL_M6] = "dell-m6",
+ };
+
+ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {
+ /* SigmaTel reference board */
+ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
+- "DFI LanParty", STAC_92HD73XX_REF),
++ "DFI LanParty", STAC_92HD73XX_REF),
++ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0254,
++ "unknown Dell", STAC_DELL_M6),
++ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0255,
++ "unknown Dell", STAC_DELL_M6),
++ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0256,
++ "unknown Dell", STAC_DELL_M6),
++ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0257,
++ "unknown Dell", STAC_DELL_M6),
++ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x025e,
++ "unknown Dell", STAC_DELL_M6),
++ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x025f,
++ "unknown Dell", STAC_DELL_M6),
++ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0271,
++ "unknown Dell", STAC_DELL_M6),
+ {} /* terminator */
+ };
+
+@@ -1229,18 +1317,56 @@ static unsigned int ref92hd71bxx_pin_configs[10] = {
+ 0x90a000f0, 0x01452050,
+ };
+
++static unsigned int dell_m4_1_pin_configs[13] = {
++ 0x0421101f, 0x04a11221, 0x40f000f0, 0x90170110,
++ 0x23a1902e, 0x23014250, 0x40f000f0, 0x90a000f0,
++ 0x40f000f0, 0x4f0000f0,
++};
++
++static unsigned int dell_m4_2_pin_configs[13] = {
++ 0x0421101f, 0x04a11221, 0x90a70330, 0x90170110,
++ 0x23a1902e, 0x23014250, 0x40f000f0, 0x40f000f0,
++ 0x40f000f0, 0x044413b0,
++};
++
+ static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = {
+ [STAC_92HD71BXX_REF] = ref92hd71bxx_pin_configs,
++ [STAC_DELL_M4_1] = dell_m4_1_pin_configs,
++ [STAC_DELL_M4_2] = dell_m4_2_pin_configs,
+ };
+
+ static const char *stac92hd71bxx_models[STAC_92HD71BXX_MODELS] = {
+ [STAC_92HD71BXX_REF] = "ref",
++ [STAC_DELL_M4_1] = "dell-m4-1",
++ [STAC_DELL_M4_2] = "dell-m4-2",
+ };
+
+ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = {
+ /* SigmaTel reference board */
+ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
+ "DFI LanParty", STAC_92HD71BXX_REF),
++ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233,
++ "unknown Dell", STAC_DELL_M4_1),
++ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0234,
++ "unknown Dell", STAC_DELL_M4_1),
++ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0250,
++ "unknown Dell", STAC_DELL_M4_1),
++ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x024f,
++ "unknown Dell", STAC_DELL_M4_1),
++ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x024d,
++ "unknown Dell", STAC_DELL_M4_1),
++ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0251,
++ "unknown Dell", STAC_DELL_M4_1),
++ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0277,
++ "unknown Dell", STAC_DELL_M4_1),
++ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0263,
++ "unknown Dell", STAC_DELL_M4_2),
++ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0265,
++ "unknown Dell", STAC_DELL_M4_2),
++ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0262,
++ "unknown Dell", STAC_DELL_M4_2),
++ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0264,
++ "unknown Dell", STAC_DELL_M4_2),
+ {} /* terminator */
+ };
+
+@@ -1733,7 +1859,8 @@ static int stac92xx_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct snd_pcm_substream *substream)
+ {
+ struct sigmatel_spec *spec = codec->spec;
+- return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
++ return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
++ hinfo);
+ }
+
+ static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+@@ -1807,7 +1934,7 @@ static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ {
+ struct sigmatel_spec *spec = codec->spec;
+
+- snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
++ snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
+ return 0;
+ }
+
+@@ -1889,6 +2016,7 @@ static int stac92xx_build_pcms(struct hda_codec *codec)
+ codec->num_pcms++;
+ info++;
+ info->name = "STAC92xx Digital";
++ info->pcm_type = HDA_PCM_TYPE_SPDIF;
+ if (spec->multiout.dig_out_nid) {
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
+@@ -1925,6 +2053,34 @@ static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int
+ AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
+ }
+
++#define stac92xx_hp_switch_info snd_ctl_boolean_mono_info
++
++static int stac92xx_hp_switch_get(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
++ struct sigmatel_spec *spec = codec->spec;
++
++ ucontrol->value.integer.value[0] = spec->hp_switch;
++ return 0;
++}
++
++static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
++ struct sigmatel_spec *spec = codec->spec;
++
++ spec->hp_switch = ucontrol->value.integer.value[0];
++
++ /* check to be sure that the ports are upto date with
++ * switch changes
++ */
++ codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
++
++ return 1;
++}
++
+ #define stac92xx_io_switch_info snd_ctl_boolean_mono_info
+
+ static int stac92xx_io_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+@@ -1996,6 +2152,15 @@ static int stac92xx_clfe_switch_put(struct snd_kcontrol *kcontrol,
+ return 1;
+ }
+
++#define STAC_CODEC_HP_SWITCH(xname) \
++ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
++ .name = xname, \
++ .index = 0, \
++ .info = stac92xx_hp_switch_info, \
++ .get = stac92xx_hp_switch_get, \
++ .put = stac92xx_hp_switch_put, \
++ }
++
+ #define STAC_CODEC_IO_SWITCH(xname, xpval) \
+ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = xname, \
+@@ -2020,6 +2185,7 @@ enum {
+ STAC_CTL_WIDGET_VOL,
+ STAC_CTL_WIDGET_MUTE,
+ STAC_CTL_WIDGET_MONO_MUX,
++ STAC_CTL_WIDGET_HP_SWITCH,
+ STAC_CTL_WIDGET_IO_SWITCH,
+ STAC_CTL_WIDGET_CLFE_SWITCH
+ };
+@@ -2028,6 +2194,7 @@ static struct snd_kcontrol_new stac92xx_control_templates[] = {
+ HDA_CODEC_VOLUME(NULL, 0, 0, 0),
+ HDA_CODEC_MUTE(NULL, 0, 0, 0),
+ STAC_MONO_MUX,
++ STAC_CODEC_HP_SWITCH(NULL),
+ STAC_CODEC_IO_SWITCH(NULL, 0),
+ STAC_CODEC_CLFE_SWITCH(NULL, 0),
+ };
+@@ -2222,6 +2389,29 @@ static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_
+ return 0;
+ }
+
++static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid)
++{
++ if (!spec->multiout.hp_nid)
++ spec->multiout.hp_nid = nid;
++ else if (spec->multiout.num_dacs > 4) {
++ printk(KERN_WARNING "stac92xx: No space for DAC 0x%x\n", nid);
++ return 1;
++ } else {
++ spec->multiout.dac_nids[spec->multiout.num_dacs] = nid;
++ spec->multiout.num_dacs++;
++ }
++ return 0;
++}
++
++static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
++{
++ if (is_in_dac_nids(spec, nid))
++ return 1;
++ if (spec->multiout.hp_nid == nid)
++ return 1;
++ return 0;
++}
++
+ /* add playback controls from the parsed DAC table */
+ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
+ const struct auto_pin_cfg *cfg)
+@@ -2236,7 +2426,7 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
+ unsigned int wid_caps, pincap;
+
+
+- for (i = 0; i < cfg->line_outs; i++) {
++ for (i = 0; i < cfg->line_outs && i < spec->multiout.num_dacs; i++) {
+ if (!spec->multiout.dac_nids[i])
+ continue;
+
+@@ -2269,6 +2459,14 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
+ }
+ }
+
++ if (cfg->hp_outs > 1) {
++ err = stac92xx_add_control(spec,
++ STAC_CTL_WIDGET_HP_SWITCH,
++ "Headphone as Line Out Switch", 0);
++ if (err < 0)
++ return err;
++ }
++
+ if (spec->line_switch) {
+ nid = cfg->input_pins[AUTO_PIN_LINE];
+ pincap = snd_hda_param_read(codec, nid,
+@@ -2284,10 +2482,11 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
+
+ if (spec->mic_switch) {
+ unsigned int def_conf;
+- nid = cfg->input_pins[AUTO_PIN_MIC];
++ unsigned int mic_pin = AUTO_PIN_MIC;
++again:
++ nid = cfg->input_pins[mic_pin];
+ def_conf = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_CONFIG_DEFAULT, 0);
+-
+ /* some laptops have an internal analog microphone
+ * which can't be used as a output */
+ if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) {
+@@ -2297,38 +2496,22 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
+ err = stac92xx_add_control(spec,
+ STAC_CTL_WIDGET_IO_SWITCH,
+ "Mic as Output Switch", (nid << 8) | 1);
++ nid = snd_hda_codec_read(codec, nid, 0,
++ AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
++ if (!check_in_dac_nids(spec, nid))
++ add_spec_dacs(spec, nid);
+ if (err < 0)
+ return err;
+ }
++ } else if (mic_pin == AUTO_PIN_MIC) {
++ mic_pin = AUTO_PIN_FRONT_MIC;
++ goto again;
+ }
+ }
+
+ return 0;
+ }
+
+-static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
+-{
+- if (is_in_dac_nids(spec, nid))
+- return 1;
+- if (spec->multiout.hp_nid == nid)
+- return 1;
+- return 0;
+-}
+-
+-static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid)
+-{
+- if (!spec->multiout.hp_nid)
+- spec->multiout.hp_nid = nid;
+- else if (spec->multiout.num_dacs > 4) {
+- printk(KERN_WARNING "stac92xx: No space for DAC 0x%x\n", nid);
+- return 1;
+- } else {
+- spec->multiout.dac_nids[spec->multiout.num_dacs] = nid;
+- spec->multiout.num_dacs++;
+- }
+- return 0;
+-}
+-
+ /* add playback controls for Speaker and HP outputs */
+ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
+ struct auto_pin_cfg *cfg)
+@@ -2378,12 +2561,8 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
+ return err;
+ }
+ if (spec->multiout.hp_nid) {
+- const char *pfx;
+- if (old_num_dacs == spec->multiout.num_dacs)
+- pfx = "Master";
+- else
+- pfx = "Headphone";
+- err = create_controls(spec, pfx, spec->multiout.hp_nid, 3);
++ err = create_controls(spec, "Headphone",
++ spec->multiout.hp_nid, 3);
+ if (err < 0)
+ return err;
+ }
+@@ -2745,7 +2924,7 @@ static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec,
+ */
+ for (i = 0; i < spec->autocfg.speaker_outs && lfe_pin == 0x0; i++) {
+ hda_nid_t pin = spec->autocfg.speaker_pins[i];
+- unsigned long wcaps = get_wcaps(codec, pin);
++ unsigned int wcaps = get_wcaps(codec, pin);
+ wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP);
+ if (wcaps == AC_WCAP_OUT_AMP)
+ /* found a mono speaker with an amp, must be lfe */
+@@ -2756,12 +2935,12 @@ static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec,
+ if (lfe_pin == 0 && spec->autocfg.speaker_outs == 0) {
+ for (i = 0; i < spec->autocfg.line_outs && lfe_pin == 0x0; i++) {
+ hda_nid_t pin = spec->autocfg.line_out_pins[i];
+- unsigned long cfg;
+- cfg = snd_hda_codec_read(codec, pin, 0,
++ unsigned int defcfg;
++ defcfg = snd_hda_codec_read(codec, pin, 0,
+ AC_VERB_GET_CONFIG_DEFAULT,
+ 0x00);
+- if (get_defcfg_device(cfg) == AC_JACK_SPEAKER) {
+- unsigned long wcaps = get_wcaps(codec, pin);
++ if (get_defcfg_device(defcfg) == AC_JACK_SPEAKER) {
++ unsigned int wcaps = get_wcaps(codec, pin);
+ wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP);
+ if (wcaps == AC_WCAP_OUT_AMP)
+ /* found a mono speaker with an amp,
+@@ -2866,6 +3045,19 @@ static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid)
+ return 0; /* nid is not a HP-Out */
+ };
+
++static void stac92xx_power_down(struct hda_codec *codec)
++{
++ struct sigmatel_spec *spec = codec->spec;
++
++ /* power down inactive DACs */
++ hda_nid_t *dac;
++ for (dac = spec->dac_list; *dac; dac++)
++ if (!is_in_dac_nids(spec, *dac) &&
++ spec->multiout.hp_nid != *dac)
++ snd_hda_codec_write_cache(codec, *dac, 0,
++ AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
++}
++
+ static int stac92xx_init(struct hda_codec *codec)
+ {
+ struct sigmatel_spec *spec = codec->spec;
+@@ -2909,16 +3101,21 @@ static int stac92xx_init(struct hda_codec *codec)
+ ? STAC_HP_EVENT : STAC_PWR_EVENT;
+ int pinctl = snd_hda_codec_read(codec, spec->pwr_nids[i],
+ 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
++ int def_conf = snd_hda_codec_read(codec, spec->pwr_nids[i],
++ 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+ /* outputs are only ports capable of power management
+ * any attempts on powering down a input port cause the
+ * referenced VREF to act quirky.
+ */
+ if (pinctl & AC_PINCTL_IN_EN)
+ continue;
++ if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED)
++ continue;
+ enable_pin_detect(codec, spec->pwr_nids[i], event | i);
+ codec->patch_ops.unsol_event(codec, (event | i) << 26);
+ }
+-
++ if (spec->dac_list)
++ stac92xx_power_down(codec);
+ if (cfg->dig_out_pin)
+ stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin,
+ AC_PINCTL_OUT_EN);
+@@ -3014,6 +3211,7 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
+ {
+ struct sigmatel_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
++ int nid = cfg->hp_pins[cfg->hp_outs - 1];
+ int i, presence;
+
+ presence = 0;
+@@ -3024,26 +3222,42 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
+ for (i = 0; i < cfg->hp_outs; i++) {
+ if (presence)
+ break;
++ if (spec->hp_switch && cfg->hp_pins[i] == nid)
++ break;
+ presence = get_hp_pin_presence(codec, cfg->hp_pins[i]);
+ }
+
+ if (presence) {
+ /* disable lineouts, enable hp */
++ if (spec->hp_switch)
++ stac92xx_reset_pinctl(codec, nid, AC_PINCTL_OUT_EN);
+ for (i = 0; i < cfg->line_outs; i++)
+ stac92xx_reset_pinctl(codec, cfg->line_out_pins[i],
+ AC_PINCTL_OUT_EN);
+ for (i = 0; i < cfg->speaker_outs; i++)
+ stac92xx_reset_pinctl(codec, cfg->speaker_pins[i],
+ AC_PINCTL_OUT_EN);
++ if (spec->eapd_mask)
++ stac_gpio_set(codec, spec->gpio_mask,
++ spec->gpio_dir, spec->gpio_data &
++ ~spec->eapd_mask);
+ } else {
+ /* enable lineouts, disable hp */
++ if (spec->hp_switch)
++ stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
+ for (i = 0; i < cfg->line_outs; i++)
+ stac92xx_set_pinctl(codec, cfg->line_out_pins[i],
+ AC_PINCTL_OUT_EN);
+ for (i = 0; i < cfg->speaker_outs; i++)
+ stac92xx_set_pinctl(codec, cfg->speaker_pins[i],
+ AC_PINCTL_OUT_EN);
++ if (spec->eapd_mask)
++ stac_gpio_set(codec, spec->gpio_mask,
++ spec->gpio_dir, spec->gpio_data |
++ spec->eapd_mask);
+ }
++ if (!spec->hp_switch && cfg->hp_outs > 1 && presence)
++ stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
+ }
+
+ static void stac92xx_pin_sense(struct hda_codec *codec, int idx)
+@@ -3091,6 +3305,9 @@ static int stac92xx_resume(struct hda_codec *codec)
+ spec->gpio_dir, spec->gpio_data);
+ snd_hda_codec_resume_amp(codec);
+ snd_hda_codec_resume_cache(codec);
++ /* power down inactive DACs */
++ if (spec->dac_list)
++ stac92xx_power_down(codec);
+ /* invoke unsolicited event to reset the HP state */
+ if (spec->hp_detect)
+ codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
+@@ -3147,12 +3364,18 @@ static int patch_stac9200(struct hda_codec *codec)
+ spec->num_adcs = 1;
+ spec->num_pwrs = 0;
+
+- if (spec->board_config == STAC_9200_GATEWAY)
++ if (spec->board_config == STAC_9200_GATEWAY ||
++ spec->board_config == STAC_9200_OQO)
+ spec->init = stac9200_eapd_init;
+ else
+ spec->init = stac9200_core_init;
+ spec->mixer = stac9200_mixer;
+
++ if (spec->board_config == STAC_9200_PANASONIC) {
++ spec->gpio_mask = spec->gpio_dir = 0x09;
++ spec->gpio_data = 0x00;
++ }
++
+ err = stac9200_parse_auto_config(codec);
+ if (err < 0) {
+ stac92xx_free(codec);
+@@ -3293,6 +3516,7 @@ again:
+
+ switch (spec->multiout.num_dacs) {
+ case 0x3: /* 6 Channel */
++ spec->multiout.hp_nid = 0x17;
+ spec->mixer = stac92hd73xx_6ch_mixer;
+ spec->init = stac92hd73xx_6ch_core_init;
+ break;
+@@ -3318,13 +3542,42 @@ again:
+
+ spec->num_muxes = ARRAY_SIZE(stac92hd73xx_mux_nids);
+ spec->num_adcs = ARRAY_SIZE(stac92hd73xx_adc_nids);
+- spec->num_dmics = STAC92HD73XX_NUM_DMICS;
+ spec->num_dmuxes = ARRAY_SIZE(stac92hd73xx_dmux_nids);
+ spec->dinput_mux = &stac92hd73xx_dmux;
+ /* GPIO0 High = Enable EAPD */
+- spec->gpio_mask = spec->gpio_dir = 0x1;
++ spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1;
+ spec->gpio_data = 0x01;
+
++ switch (spec->board_config) {
++ case STAC_DELL_M6:
++ spec->init = dell_eq_core_init;
++ switch (codec->subsystem_id) {
++ case 0x1028025e: /* Analog Mics */
++ case 0x1028025f:
++ stac92xx_set_config_reg(codec, 0x0b, 0x90A70170);
++ spec->num_dmics = 0;
++ break;
++ case 0x10280271: /* Digital Mics */
++ case 0x10280272:
++ spec->init = dell_m6_core_init;
++ /* fall-through */
++ case 0x10280254:
++ case 0x10280255:
++ stac92xx_set_config_reg(codec, 0x13, 0x90A60160);
++ spec->num_dmics = 1;
++ break;
++ case 0x10280256: /* Both */
++ case 0x10280057:
++ stac92xx_set_config_reg(codec, 0x0b, 0x90A70170);
++ stac92xx_set_config_reg(codec, 0x13, 0x90A60160);
++ spec->num_dmics = 1;
++ break;
++ }
++ break;
++ default:
++ spec->num_dmics = STAC92HD73XX_NUM_DMICS;
++ }
++
+ spec->num_pwrs = ARRAY_SIZE(stac92hd73xx_pwr_nids);
+ spec->pwr_nids = stac92hd73xx_pwr_nids;
+
+@@ -3398,7 +3651,10 @@ again:
+ spec->aloopback_shift = 0;
+
+ /* GPIO0 High = EAPD */
+- spec->gpio_mask = spec->gpio_dir = spec->gpio_data = 0x1;
++ spec->gpio_mask = 0x01;
++ spec->gpio_dir = 0x01;
++ spec->gpio_mask = 0x01;
++ spec->gpio_data = 0x01;
+
+ spec->mux_nids = stac92hd71bxx_mux_nids;
+ spec->adc_nids = stac92hd71bxx_adc_nids;
+@@ -3413,7 +3669,7 @@ again:
+ spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids);
+ spec->pwr_nids = stac92hd71bxx_pwr_nids;
+
+- spec->multiout.num_dacs = 2;
++ spec->multiout.num_dacs = 1;
+ spec->multiout.hp_nid = 0x11;
+ spec->multiout.dac_nids = stac92hd71bxx_dac_nids;
+
+@@ -3577,13 +3833,14 @@ static int patch_stac927x(struct hda_codec *codec)
+ spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids);
+ spec->mux_nids = stac927x_mux_nids;
+ spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids);
++ spec->dac_list = stac927x_dac_nids;
+ spec->multiout.dac_nids = spec->dac_nids;
+
+ switch (spec->board_config) {
+ case STAC_D965_3ST:
+ case STAC_D965_5ST:
+ /* GPIO0 High = Enable EAPD */
+- spec->gpio_mask = spec->gpio_dir = 0x01;
++ spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x01;
+ spec->gpio_data = 0x01;
+ spec->num_dmics = 0;
+
+@@ -3591,14 +3848,23 @@ static int patch_stac927x(struct hda_codec *codec)
+ spec->mixer = stac927x_mixer;
+ break;
+ case STAC_DELL_BIOS:
++ switch (codec->subsystem_id) {
++ case 0x10280209:
++ case 0x1028022e:
++ /* correct the device field to SPDIF out */
++ stac92xx_set_config_reg(codec, 0x21, 0x01442070);
++ break;
++ };
++ /* configure the analog microphone on some laptops */
++ stac92xx_set_config_reg(codec, 0x0c, 0x90a79130);
+ /* correct the front output jack as a hp out */
+- stac92xx_set_config_reg(codec, 0x0f, 0x02270110);
++ stac92xx_set_config_reg(codec, 0x0f, 0x0227011f);
+ /* correct the front input jack as a mic */
+ stac92xx_set_config_reg(codec, 0x0e, 0x02a79130);
+ /* fallthru */
+ case STAC_DELL_3ST:
+ /* GPIO2 High = Enable EAPD */
+- spec->gpio_mask = spec->gpio_dir = 0x04;
++ spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x04;
+ spec->gpio_data = 0x04;
+ spec->dmic_nids = stac927x_dmic_nids;
+ spec->num_dmics = STAC927X_NUM_DMICS;
+@@ -3610,7 +3876,7 @@ static int patch_stac927x(struct hda_codec *codec)
+ break;
+ default:
+ /* GPIO0 High = Enable EAPD */
+- spec->gpio_mask = spec->gpio_dir = 0x1;
++ spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1;
+ spec->gpio_data = 0x01;
+ spec->num_dmics = 0;
+
+@@ -3714,6 +3980,7 @@ static int patch_stac9205(struct hda_codec *codec)
+ (AC_USRSP_EN | STAC_HP_EVENT));
+
+ spec->gpio_dir = 0x0b;
++ spec->eapd_mask = 0x01;
+ spec->gpio_mask = 0x1b;
+ spec->gpio_mute = 0x10;
+ /* GPIO0 High = EAPD, GPIO1 Low = Headphone Mute,
+@@ -3723,7 +3990,7 @@ static int patch_stac9205(struct hda_codec *codec)
+ break;
+ default:
+ /* GPIO0 High = EAPD */
+- spec->gpio_mask = spec->gpio_dir = 0x1;
++ spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1;
+ spec->gpio_data = 0x01;
+ break;
+ }
+diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
+index 4e5dd4c..52b1d81 100644
+--- a/sound/pci/hda/patch_via.c
++++ b/sound/pci/hda/patch_via.c
+@@ -39,7 +39,7 @@
+ #include <sound/core.h>
+ #include "hda_codec.h"
+ #include "hda_local.h"
+-
++#include "hda_patch.h"
+
+ /* amp values */
+ #define AMP_VAL_IDX_SHIFT 19
+@@ -357,7 +357,8 @@ static int via_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct snd_pcm_substream *substream)
+ {
+ struct via_spec *spec = codec->spec;
+- return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
++ return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
++ hinfo);
+ }
+
+ static int via_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+@@ -430,8 +431,7 @@ static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct snd_pcm_substream *substream)
+ {
+ struct via_spec *spec = codec->spec;
+- snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
+- 0, 0, 0);
++ snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
+ return 0;
+ }
+
+@@ -493,6 +493,11 @@ static int via_build_controls(struct hda_codec *codec)
+ spec->multiout.dig_out_nid);
+ if (err < 0)
+ return err;
++ err = snd_hda_create_spdif_share_sw(codec,
++ &spec->multiout);
++ if (err < 0)
++ return err;
++ spec->multiout.share_spdif = 1;
+ }
+ if (spec->dig_in_nid) {
+ err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
+@@ -523,6 +528,7 @@ static int via_build_pcms(struct hda_codec *codec)
+ codec->num_pcms++;
+ info++;
+ info->name = spec->stream_name_digital;
++ info->pcm_type = HDA_PCM_TYPE_SPDIF;
+ if (spec->multiout.dig_out_nid) {
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
+ *(spec->stream_digital_playback);
+diff --git a/sound/pci/hda/vmaster.c b/sound/pci/hda/vmaster.c
+deleted file mode 100644
+index 2da49d2..0000000
+--- a/sound/pci/hda/vmaster.c
++++ /dev/null
+@@ -1,364 +0,0 @@
+-/*
+- * Virtual master and slave controls
+- *
+- * Copyright (c) 2008 by Takashi Iwai <tiwai at suse.de>
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License as
+- * published by the Free Software Foundation, version 2.
+- *
+- */
+-
+-#include <linux/slab.h>
+-#include <sound/core.h>
+-#include <sound/control.h>
+-
+-/*
+- * a subset of information returned via ctl info callback
+- */
+-struct link_ctl_info {
+- int type; /* value type */
+- int count; /* item count */
+- int min_val, max_val; /* min, max values */
+-};
+-
+-/*
+- * link master - this contains a list of slave controls that are
+- * identical types, i.e. info returns the same value type and value
+- * ranges, but may have different number of counts.
+- *
+- * The master control is so far only mono volume/switch for simplicity.
+- * The same value will be applied to all slaves.
+- */
+-struct link_master {
+- struct list_head slaves;
+- struct link_ctl_info info;
+- int val; /* the master value */
+-};
+-
+-/*
+- * link slave - this contains a slave control element
+- *
+- * It fakes the control callbacsk with additional attenuation by the
+- * master control. A slave may have either one or two channels.
+- */
+-
+-struct link_slave {
+- struct list_head list;
+- struct link_master *master;
+- struct link_ctl_info info;
+- int vals[2]; /* current values */
+- struct snd_kcontrol slave; /* the copy of original control entry */
+-};
+-
+-/* get the slave ctl info and save the initial values */
+-static int slave_init(struct link_slave *slave)
+-{
+- struct snd_ctl_elem_info *uinfo;
+- struct snd_ctl_elem_value *uctl;
+- int err, ch;
+-
+- if (slave->info.count)
+- return 0; /* already initialized */
+-
+- uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL);
+- if (!uinfo)
+- return -ENOMEM;
+- uinfo->id = slave->slave.id;
+- err = slave->slave.info(&slave->slave, uinfo);
+- if (err < 0) {
+- kfree(uinfo);
+- return err;
+- }
+- slave->info.type = uinfo->type;
+- slave->info.count = uinfo->count;
+- if (slave->info.count > 2 ||
+- (slave->info.type != SNDRV_CTL_ELEM_TYPE_INTEGER &&
+- slave->info.type != SNDRV_CTL_ELEM_TYPE_BOOLEAN)) {
+- snd_printk(KERN_ERR "invalid slave element\n");
+- kfree(uinfo);
+- return -EINVAL;
+- }
+- slave->info.min_val = uinfo->value.integer.min;
+- slave->info.max_val = uinfo->value.integer.max;
+- kfree(uinfo);
+-
+- uctl = kmalloc(sizeof(*uctl), GFP_KERNEL);
+- if (!uctl)
+- return -ENOMEM;
+- uctl->id = slave->slave.id;
+- err = slave->slave.get(&slave->slave, uctl);
+- for (ch = 0; ch < slave->info.count; ch++)
+- slave->vals[ch] = uctl->value.integer.value[ch];
+- kfree(uctl);
+- return 0;
+-}
+-
+-/* initialize master volume */
+-static int master_init(struct link_master *master)
+-{
+- struct link_slave *slave;
+-
+- if (master->info.count)
+- return 0; /* already initialized */
+-
+- list_for_each_entry(slave, &master->slaves, list) {
+- int err = slave_init(slave);
+- if (err < 0)
+- return err;
+- master->info = slave->info;
+- master->info.count = 1; /* always mono */
+- /* set full volume as default (= no attenuation) */
+- master->val = master->info.max_val;
+- return 0;
+- }
+- return -ENOENT;
+-}
+-
+-static int slave_get_val(struct link_slave *slave,
+- struct snd_ctl_elem_value *ucontrol)
+-{
+- int err, ch;
+-
+- err = slave_init(slave);
+- if (err < 0)
+- return err;
+- for (ch = 0; ch < slave->info.count; ch++)
+- ucontrol->value.integer.value[ch] = slave->vals[ch];
+- return 0;
+-}
+-
+-static int slave_put_val(struct link_slave *slave,
+- struct snd_ctl_elem_value *ucontrol)
+-{
+- int err, ch, vol;
+-
+- err = master_init(slave->master);
+- if (err < 0)
+- return err;
+-
+- switch (slave->info.type) {
+- case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+- for (ch = 0; ch < slave->info.count; ch++)
+- ucontrol->value.integer.value[ch] &=
+- !!slave->master->val;
+- break;
+- case SNDRV_CTL_ELEM_TYPE_INTEGER:
+- for (ch = 0; ch < slave->info.count; ch++) {
+- /* max master volume is supposed to be 0 dB */
+- vol = ucontrol->value.integer.value[ch];
+- vol += slave->master->val - slave->master->info.max_val;
+- if (vol < slave->info.min_val)
+- vol = slave->info.min_val;
+- else if (vol > slave->info.max_val)
+- vol = slave->info.max_val;
+- ucontrol->value.integer.value[ch] = vol;
+- }
+- break;
+- }
+- return slave->slave.put(&slave->slave, ucontrol);
+-}
+-
+-/*
+- * ctl callbacks for slaves
+- */
+-static int slave_info(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_info *uinfo)
+-{
+- struct link_slave *slave = snd_kcontrol_chip(kcontrol);
+- return slave->slave.info(&slave->slave, uinfo);
+-}
+-
+-static int slave_get(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_value *ucontrol)
+-{
+- struct link_slave *slave = snd_kcontrol_chip(kcontrol);
+- return slave_get_val(slave, ucontrol);
+-}
+-
+-static int slave_put(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_value *ucontrol)
+-{
+- struct link_slave *slave = snd_kcontrol_chip(kcontrol);
+- int err, ch, changed = 0;
+-
+- err = slave_init(slave);
+- if (err < 0)
+- return err;
+- for (ch = 0; ch < slave->info.count; ch++) {
+- if (slave->vals[ch] != ucontrol->value.integer.value[ch]) {
+- changed = 1;
+- slave->vals[ch] = ucontrol->value.integer.value[ch];
+- }
+- }
+- if (!changed)
+- return 0;
+- return slave_put_val(slave, ucontrol);
+-}
+-
+-static int slave_tlv_cmd(struct snd_kcontrol *kcontrol,
+- int op_flag, unsigned int size,
+- unsigned int __user *tlv)
+-{
+- struct link_slave *slave = snd_kcontrol_chip(kcontrol);
+- /* FIXME: this assumes that the max volume is 0 dB */
+- return slave->slave.tlv.c(&slave->slave, op_flag, size, tlv);
+-}
+-
+-static void slave_free(struct snd_kcontrol *kcontrol)
+-{
+- struct link_slave *slave = snd_kcontrol_chip(kcontrol);
+- if (slave->slave.private_free)
+- slave->slave.private_free(&slave->slave);
+- if (slave->master)
+- list_del(&slave->list);
+- kfree(slave);
+-}
+-
+-/*
+- * Add a slave control to the group with the given master control
+- *
+- * All slaves must be the same type (returning the same information
+- * via info callback). The fucntion doesn't check it, so it's your
+- * responsibility.
+- *
+- * Also, some additional limitations:
+- * - at most two channels
+- * - logarithmic volume control (dB level), no linear volume
+- * - master can only attenuate the volume, no gain
+- */
+-int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
+-{
+- struct link_master *master_link = snd_kcontrol_chip(master);
+- struct link_slave *srec;
+-
+- srec = kzalloc(sizeof(*srec) +
+- slave->count * sizeof(*slave->vd), GFP_KERNEL);
+- if (!srec)
+- return -ENOMEM;
+- srec->slave = *slave;
+- memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd));
+- srec->master = master_link;
+-
+- /* override callbacks */
+- slave->info = slave_info;
+- slave->get = slave_get;
+- slave->put = slave_put;
+- if (slave->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)
+- slave->tlv.c = slave_tlv_cmd;
+- slave->private_data = srec;
+- slave->private_free = slave_free;
+-
+- list_add_tail(&srec->list, &master_link->slaves);
+- return 0;
+-}
+-
+-/*
+- * ctl callbacks for master controls
+- */
+-static int master_info(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_info *uinfo)
+-{
+- struct link_master *master = snd_kcontrol_chip(kcontrol);
+- int ret;
+-
+- ret = master_init(master);
+- if (ret < 0)
+- return ret;
+- uinfo->type = master->info.type;
+- uinfo->count = master->info.count;
+- uinfo->value.integer.min = master->info.min_val;
+- uinfo->value.integer.max = master->info.max_val;
+- return 0;
+-}
+-
+-static int master_get(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_value *ucontrol)
+-{
+- struct link_master *master = snd_kcontrol_chip(kcontrol);
+- int err = master_init(master);
+- if (err < 0)
+- return err;
+- ucontrol->value.integer.value[0] = master->val;
+- return 0;
+-}
+-
+-static int master_put(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_value *ucontrol)
+-{
+- struct link_master *master = snd_kcontrol_chip(kcontrol);
+- struct link_slave *slave;
+- struct snd_ctl_elem_value *uval;
+- int err, old_val;
+-
+- err = master_init(master);
+- if (err < 0)
+- return err;
+- old_val = master->val;
+- if (ucontrol->value.integer.value[0] == old_val)
+- return 0;
+-
+- uval = kmalloc(sizeof(*uval), GFP_KERNEL);
+- if (!uval)
+- return -ENOMEM;
+- list_for_each_entry(slave, &master->slaves, list) {
+- master->val = old_val;
+- uval->id = slave->slave.id;
+- slave_get_val(slave, uval);
+- master->val = ucontrol->value.integer.value[0];
+- slave_put_val(slave, uval);
+- }
+- kfree(uval);
+- return 1;
+-}
+-
+-static void master_free(struct snd_kcontrol *kcontrol)
+-{
+- struct link_master *master = snd_kcontrol_chip(kcontrol);
+- struct link_slave *slave;
+-
+- list_for_each_entry(slave, &master->slaves, list)
+- slave->master = NULL;
+- kfree(master);
+-}
+-
+-
+-/*
+- * Create a virtual master control with the given name
+- */
+-struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
+- const unsigned int *tlv)
+-{
+- struct link_master *master;
+- struct snd_kcontrol *kctl;
+- struct snd_kcontrol_new knew;
+-
+- memset(&knew, 0, sizeof(knew));
+- knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+- knew.name = name;
+- knew.info = master_info;
+-
+- master = kzalloc(sizeof(*master), GFP_KERNEL);
+- if (!master)
+- return NULL;
+- INIT_LIST_HEAD(&master->slaves);
+-
+- kctl = snd_ctl_new1(&knew, master);
+- if (!kctl) {
+- kfree(master);
+- return NULL;
+- }
+- /* override some callbacks */
+- kctl->info = master_info;
+- kctl->get = master_get;
+- kctl->put = master_put;
+- kctl->private_free = master_free;
+-
+- /* additional (constant) TLV read */
+- if (tlv) {
+- /* FIXME: this assumes that the max volume is 0 dB */
+- kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+- kctl->tlv.p = tlv;
+- }
+- return kctl;
+-}
+diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c
+index efd180b..0ed96c1 100644
+--- a/sound/pci/ice1712/delta.c
++++ b/sound/pci/ice1712/delta.c
+@@ -1,8 +1,8 @@
+ /*
+ * ALSA driver for ICEnsemble ICE1712 (Envy24)
+ *
+- * Lowlevel functions for M-Audio Delta 1010, 44, 66, Dio2496, Audiophile
+- * Digigram VX442
++ * Lowlevel functions for M-Audio Delta 1010, 1010E, 44, 66, 66E, Dio2496,
++ * Audiophile, Digigram VX442
+ *
+ * Copyright (c) 2000 Jaroslav Kysela <perex at perex.cz>
+ *
+@@ -86,6 +86,7 @@ static unsigned char ap_cs8427_codec_select(struct snd_ice1712 *ice)
+ unsigned char tmp;
+ tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA);
+ switch (ice->eeprom.subvendor) {
++ case ICE1712_SUBDEVICE_DELTA1010E:
+ case ICE1712_SUBDEVICE_DELTA1010LT:
+ tmp &= ~ICE1712_DELTA_1010LT_CS;
+ tmp |= ICE1712_DELTA_1010LT_CCLK | ICE1712_DELTA_1010LT_CS_CS8427;
+@@ -109,6 +110,7 @@ static unsigned char ap_cs8427_codec_select(struct snd_ice1712 *ice)
+ static void ap_cs8427_codec_deassert(struct snd_ice1712 *ice, unsigned char tmp)
+ {
+ switch (ice->eeprom.subvendor) {
++ case ICE1712_SUBDEVICE_DELTA1010E:
+ case ICE1712_SUBDEVICE_DELTA1010LT:
+ tmp &= ~ICE1712_DELTA_1010LT_CS;
+ tmp |= ICE1712_DELTA_1010LT_CS_NONE;
+@@ -534,6 +536,14 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
+ int err;
+ struct snd_akm4xxx *ak;
+
++ if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DELTA1010 &&
++ ice->eeprom.gpiodir == 0x7b)
++ ice->eeprom.subvendor = ICE1712_SUBDEVICE_DELTA1010E;
++
++ if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DELTA66 &&
++ ice->eeprom.gpiodir == 0xfb)
++ ice->eeprom.subvendor = ICE1712_SUBDEVICE_DELTA66E;
++
+ /* determine I2C, DACs and ADCs */
+ switch (ice->eeprom.subvendor) {
+ case ICE1712_SUBDEVICE_AUDIOPHILE:
+@@ -550,6 +560,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
+ ice->num_total_adcs = ice->omni ? 8 : 4;
+ break;
+ case ICE1712_SUBDEVICE_DELTA1010:
++ case ICE1712_SUBDEVICE_DELTA1010E:
+ case ICE1712_SUBDEVICE_DELTA1010LT:
+ case ICE1712_SUBDEVICE_MEDIASTATION:
+ ice->num_total_dacs = 8;
+@@ -559,6 +570,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
+ ice->num_total_dacs = 4; /* two AK4324 codecs */
+ break;
+ case ICE1712_SUBDEVICE_VX442:
++ case ICE1712_SUBDEVICE_DELTA66E: /* omni not suported yet */
+ ice->num_total_dacs = 4;
+ ice->num_total_adcs = 4;
+ break;
+@@ -568,8 +580,10 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
+ switch (ice->eeprom.subvendor) {
+ case ICE1712_SUBDEVICE_AUDIOPHILE:
+ case ICE1712_SUBDEVICE_DELTA410:
++ case ICE1712_SUBDEVICE_DELTA1010E:
+ case ICE1712_SUBDEVICE_DELTA1010LT:
+ case ICE1712_SUBDEVICE_VX442:
++ case ICE1712_SUBDEVICE_DELTA66E:
+ if ((err = snd_i2c_bus_create(ice->card, "ICE1712 GPIO 1", NULL, &ice->i2c)) < 0) {
+ snd_printk(KERN_ERR "unable to create I2C bus\n");
+ return err;
+@@ -601,6 +615,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
+ /* no analog? */
+ switch (ice->eeprom.subvendor) {
+ case ICE1712_SUBDEVICE_DELTA1010:
++ case ICE1712_SUBDEVICE_DELTA1010E:
+ case ICE1712_SUBDEVICE_DELTADIO2496:
+ case ICE1712_SUBDEVICE_MEDIASTATION:
+ return 0;
+@@ -627,6 +642,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
+ err = snd_ice1712_akm4xxx_init(ak, &akm_delta44, &akm_delta44_priv, ice);
+ break;
+ case ICE1712_SUBDEVICE_VX442:
++ case ICE1712_SUBDEVICE_DELTA66E:
+ err = snd_ice1712_akm4xxx_init(ak, &akm_vx442, &akm_vx442_priv, ice);
+ break;
+ default:
+@@ -674,6 +690,7 @@ static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice)
+ if (err < 0)
+ return err;
+ break;
++ case ICE1712_SUBDEVICE_DELTA1010E:
+ case ICE1712_SUBDEVICE_DELTA1010LT:
+ err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_delta1010lt_wordclock_select, ice));
+ if (err < 0)
+@@ -716,6 +733,7 @@ static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice)
+ case ICE1712_SUBDEVICE_DELTA44:
+ case ICE1712_SUBDEVICE_DELTA66:
+ case ICE1712_SUBDEVICE_VX442:
++ case ICE1712_SUBDEVICE_DELTA66E:
+ err = snd_ice1712_akm4xxx_build_controls(ice);
+ if (err < 0)
+ return err;
+diff --git a/sound/pci/ice1712/delta.h b/sound/pci/ice1712/delta.h
+index 26ea05a..ea7116c 100644
+--- a/sound/pci/ice1712/delta.h
++++ b/sound/pci/ice1712/delta.h
+@@ -36,8 +36,10 @@
+ "{Lionstracs,Mediastation},"
+
+ #define ICE1712_SUBDEVICE_DELTA1010 0x121430d6
++#define ICE1712_SUBDEVICE_DELTA1010E 0xff1430d6
+ #define ICE1712_SUBDEVICE_DELTADIO2496 0x121431d6
+ #define ICE1712_SUBDEVICE_DELTA66 0x121432d6
++#define ICE1712_SUBDEVICE_DELTA66E 0xff1432d6
+ #define ICE1712_SUBDEVICE_DELTA44 0x121433d6
+ #define ICE1712_SUBDEVICE_AUDIOPHILE 0x121434d6
+ #define ICE1712_SUBDEVICE_DELTA410 0x121438d6
+diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c
+index 064760d..013fc4f 100644
+--- a/sound/pci/ice1712/ews.c
++++ b/sound/pci/ice1712/ews.c
+@@ -238,6 +238,7 @@ static void snd_ice1712_ews_cs8404_spdif_write(struct snd_ice1712 *ice, unsigned
+ case ICE1712_SUBDEVICE_EWS88MT:
+ case ICE1712_SUBDEVICE_EWS88MT_NEW:
+ case ICE1712_SUBDEVICE_PHASE88:
++ case ICE1712_SUBDEVICE_TS88:
+ if (snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_CS8404], &bits, 1)
+ != 1)
+ goto _error;
+@@ -433,6 +434,7 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice)
+ case ICE1712_SUBDEVICE_EWS88MT:
+ case ICE1712_SUBDEVICE_EWS88MT_NEW:
+ case ICE1712_SUBDEVICE_PHASE88:
++ case ICE1712_SUBDEVICE_TS88:
+ ice->num_total_dacs = 8;
+ ice->num_total_adcs = 8;
+ break;
+@@ -475,6 +477,8 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice)
+ case ICE1712_SUBDEVICE_EWS88MT:
+ case ICE1712_SUBDEVICE_EWS88MT_NEW:
+ case ICE1712_SUBDEVICE_PHASE88:
++ case ICE1712_SUBDEVICE_TS88:
++
+ err = snd_i2c_device_create(ice->i2c, "CS8404",
+ ICE1712_EWS88MT_CS8404_ADDR,
+ &spec->i2cdevs[EWS_I2C_CS8404]);
+@@ -518,6 +522,7 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice)
+ case ICE1712_SUBDEVICE_EWS88MT:
+ case ICE1712_SUBDEVICE_EWS88MT_NEW:
+ case ICE1712_SUBDEVICE_PHASE88:
++ case ICE1712_SUBDEVICE_TS88:
+ case ICE1712_SUBDEVICE_EWS88D:
+ /* set up CS8404 */
+ ice->spdif.ops.open = ews88_open_spdif;
+@@ -547,6 +552,7 @@ static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice)
+ case ICE1712_SUBDEVICE_EWS88MT:
+ case ICE1712_SUBDEVICE_EWS88MT_NEW:
+ case ICE1712_SUBDEVICE_PHASE88:
++ case ICE1712_SUBDEVICE_TS88:
+ err = snd_ice1712_akm4xxx_init(ak, &akm_ews88mt, &akm_ews88mt_priv, ice);
+ break;
+ case ICE1712_SUBDEVICE_EWX2496:
+@@ -973,6 +979,7 @@ static int __devinit snd_ice1712_ews_add_controls(struct snd_ice1712 *ice)
+ case ICE1712_SUBDEVICE_EWS88MT:
+ case ICE1712_SUBDEVICE_EWS88MT_NEW:
+ case ICE1712_SUBDEVICE_PHASE88:
++ case ICE1712_SUBDEVICE_TS88:
+ case ICE1712_SUBDEVICE_DMX6FIRE:
+ err = snd_ice1712_akm4xxx_build_controls(ice);
+ if (err < 0)
+@@ -992,6 +999,7 @@ static int __devinit snd_ice1712_ews_add_controls(struct snd_ice1712 *ice)
+ case ICE1712_SUBDEVICE_EWS88MT:
+ case ICE1712_SUBDEVICE_EWS88MT_NEW:
+ case ICE1712_SUBDEVICE_PHASE88:
++ case ICE1712_SUBDEVICE_TS88:
+ err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_ews88mt_input_sense, ice));
+ if (err < 0)
+ return err;
+@@ -1049,6 +1057,13 @@ struct snd_ice1712_card_info snd_ice1712_ews_cards[] __devinitdata = {
+ .build_controls = snd_ice1712_ews_add_controls,
+ },
+ {
++ .subvendor = ICE1712_SUBDEVICE_TS88,
++ .name = "terrasoniq TS88",
++ .model = "phase88",
++ .chip_init = snd_ice1712_ews_init,
++ .build_controls = snd_ice1712_ews_add_controls,
++ },
++ {
+ .subvendor = ICE1712_SUBDEVICE_EWS88D,
+ .name = "TerraTec EWS88D",
+ .model = "ews88d",
+diff --git a/sound/pci/ice1712/ews.h b/sound/pci/ice1712/ews.h
+index e4ed1b4..1c44371 100644
+--- a/sound/pci/ice1712/ews.h
++++ b/sound/pci/ice1712/ews.h
+@@ -30,7 +30,8 @@
+ "{TerraTec,EWS 88MT},"\
+ "{TerraTec,EWS 88D},"\
+ "{TerraTec,DMX 6Fire},"\
+- "{TerraTec,Phase 88},"
++ "{TerraTec,Phase 88}," \
++ "{terrasoniq,TS 88},"
+
+ #define ICE1712_SUBDEVICE_EWX2496 0x3b153011
+ #define ICE1712_SUBDEVICE_EWS88MT 0x3b151511
+@@ -38,6 +39,7 @@
+ #define ICE1712_SUBDEVICE_EWS88D 0x3b152b11
+ #define ICE1712_SUBDEVICE_DMX6FIRE 0x3b153811
+ #define ICE1712_SUBDEVICE_PHASE88 0x3b155111
++#define ICE1712_SUBDEVICE_TS88 0x3b157c11
+
+ /* entry point */
+ extern struct snd_ice1712_card_info snd_ice1712_ews_cards[];
+diff --git a/sound/pci/ice1712/hoontech.c b/sound/pci/ice1712/hoontech.c
+index cf5c7c0..6914189 100644
+--- a/sound/pci/ice1712/hoontech.c
++++ b/sound/pci/ice1712/hoontech.c
+@@ -208,6 +208,19 @@ static int __devinit snd_ice1712_hoontech_init(struct snd_ice1712 *ice)
+ /* ICE1712_STDSP24_MUTE |
+ ICE1712_STDSP24_INSEL |
+ ICE1712_STDSP24_DAREAR; */
++ /* These boxconfigs have caused problems in the past.
++ * The code is not optimal, but should now enable a working config to
++ * be achieved.
++ * ** MIDI IN can only be configured on one box **
++ * ICE1712_STDSP24_BOX_MIDI1 needs to be set for that box.
++ * Tests on a ADAC2000 box suggest the box config flags do not
++ * work as would be expected, and the inputs are crossed.
++ * Setting ICE1712_STDSP24_BOX_MIDI1 and ICE1712_STDSP24_BOX_MIDI2
++ * on the same box connects MIDI-In to both 401 uarts; both outputs
++ * are then active on all boxes.
++ * The default config here sets up everything on the first box.
++ * Alan Horstmann 5.2.2008
++ */
+ spec->boxconfig[0] = ICE1712_STDSP24_BOX_CHN1 |
+ ICE1712_STDSP24_BOX_CHN2 |
+ ICE1712_STDSP24_BOX_CHN3 |
+@@ -223,14 +236,14 @@ static int __devinit snd_ice1712_hoontech_init(struct snd_ice1712 *ice)
+ (spec->config & ICE1712_STDSP24_MUTE) ? 1 : 0);
+ snd_ice1712_stdsp24_insel(ice,
+ (spec->config & ICE1712_STDSP24_INSEL) ? 1 : 0);
+- for (box = 0; box < 1; box++) {
++ for (box = 0; box < 4; box++) {
+ if (spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI2)
+ snd_ice1712_stdsp24_midi2(ice, 1);
+ for (chn = 0; chn < 4; chn++)
+ snd_ice1712_stdsp24_box_channel(ice, box, chn,
+ (spec->boxconfig[box] & (1 << chn)) ? 1 : 0);
+- snd_ice1712_stdsp24_box_midi(ice, box,
+- (spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI1) ? 1 : 0);
++ if (spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI1)
++ snd_ice1712_stdsp24_box_midi(ice, box, 1);
+ }
+
+ return 0;
+@@ -322,6 +335,8 @@ struct snd_ice1712_card_info snd_ice1712_hoontech_cards[] __devinitdata = {
+ .name = "Hoontech SoundTrack Audio DSP24",
+ .model = "dsp24",
+ .chip_init = snd_ice1712_hoontech_init,
++ .mpu401_1_name = "MIDI-1 Hoontech/STA DSP24",
++ .mpu401_2_name = "MIDI-2 Hoontech/STA DSP24",
+ },
+ {
+ .subvendor = ICE1712_SUBDEVICE_STDSP24_VALUE, /* a dummy id */
+diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
+index df292af..29d449d 100644
+--- a/sound/pci/ice1712/ice1712.c
++++ b/sound/pci/ice1712/ice1712.c
+@@ -1297,11 +1297,14 @@ static void snd_ice1712_update_volume(struct snd_ice1712 *ice, int index)
+ static int snd_ice1712_pro_mixer_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+ {
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+- int index = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value;
++ int priv_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) +
++ kcontrol->private_value;
+
+ spin_lock_irq(&ice->reg_lock);
+- ucontrol->value.integer.value[0] = !((ice->pro_volumes[index] >> 15) & 1);
+- ucontrol->value.integer.value[1] = !((ice->pro_volumes[index] >> 31) & 1);
++ ucontrol->value.integer.value[0] =
++ !((ice->pro_volumes[priv_idx] >> 15) & 1);
++ ucontrol->value.integer.value[1] =
++ !((ice->pro_volumes[priv_idx] >> 31) & 1);
+ spin_unlock_irq(&ice->reg_lock);
+ return 0;
+ }
+@@ -1309,16 +1312,17 @@ static int snd_ice1712_pro_mixer_switch_get(struct snd_kcontrol *kcontrol, struc
+ static int snd_ice1712_pro_mixer_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+ {
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+- int index = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value;
++ int priv_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) +
++ kcontrol->private_value;
+ unsigned int nval, change;
+
+ nval = (ucontrol->value.integer.value[0] ? 0 : 0x00008000) |
+ (ucontrol->value.integer.value[1] ? 0 : 0x80000000);
+ spin_lock_irq(&ice->reg_lock);
+- nval |= ice->pro_volumes[index] & ~0x80008000;
+- change = nval != ice->pro_volumes[index];
+- ice->pro_volumes[index] = nval;
+- snd_ice1712_update_volume(ice, index);
++ nval |= ice->pro_volumes[priv_idx] & ~0x80008000;
++ change = nval != ice->pro_volumes[priv_idx];
++ ice->pro_volumes[priv_idx] = nval;
++ snd_ice1712_update_volume(ice, priv_idx);
+ spin_unlock_irq(&ice->reg_lock);
+ return change;
+ }
+@@ -1335,11 +1339,14 @@ static int snd_ice1712_pro_mixer_volume_info(struct snd_kcontrol *kcontrol, stru
+ static int snd_ice1712_pro_mixer_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+ {
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+- int index = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value;
++ int priv_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) +
++ kcontrol->private_value;
+
+ spin_lock_irq(&ice->reg_lock);
+- ucontrol->value.integer.value[0] = (ice->pro_volumes[index] >> 0) & 127;
+- ucontrol->value.integer.value[1] = (ice->pro_volumes[index] >> 16) & 127;
++ ucontrol->value.integer.value[0] =
++ (ice->pro_volumes[priv_idx] >> 0) & 127;
++ ucontrol->value.integer.value[1] =
++ (ice->pro_volumes[priv_idx] >> 16) & 127;
+ spin_unlock_irq(&ice->reg_lock);
+ return 0;
+ }
+@@ -1347,16 +1354,17 @@ static int snd_ice1712_pro_mixer_volume_get(struct snd_kcontrol *kcontrol, struc
+ static int snd_ice1712_pro_mixer_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+ {
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+- int index = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value;
++ int priv_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) +
++ kcontrol->private_value;
+ unsigned int nval, change;
+
+ nval = (ucontrol->value.integer.value[0] & 127) |
+ ((ucontrol->value.integer.value[1] & 127) << 16);
+ spin_lock_irq(&ice->reg_lock);
+- nval |= ice->pro_volumes[index] & ~0x007f007f;
+- change = nval != ice->pro_volumes[index];
+- ice->pro_volumes[index] = nval;
+- snd_ice1712_update_volume(ice, index);
++ nval |= ice->pro_volumes[priv_idx] & ~0x007f007f;
++ change = nval != ice->pro_volumes[priv_idx];
++ ice->pro_volumes[priv_idx] = nval;
++ snd_ice1712_update_volume(ice, priv_idx);
+ spin_unlock_irq(&ice->reg_lock);
+ return change;
+ }
+@@ -2482,10 +2490,9 @@ static int snd_ice1712_free(struct snd_ice1712 *ice)
+ outb(0xff, ICEREG(ice, IRQMASK));
+ /* --- */
+ __hw_end:
+- if (ice->irq >= 0) {
+- synchronize_irq(ice->irq);
++ if (ice->irq >= 0)
+ free_irq(ice->irq, ice);
+- }
++
+ if (ice->port)
+ pci_release_regions(ice->pci);
+ snd_ice1712_akm4xxx_free(ice);
+diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
+index 303cffe..3208901 100644
+--- a/sound/pci/ice1712/ice1712.h
++++ b/sound/pci/ice1712/ice1712.h
+@@ -367,6 +367,15 @@ struct snd_ice1712 {
+
+ /* other board-specific data */
+ void *spec;
++
++ /* VT172x specific */
++ int pro_rate_default;
++ int (*is_spdif_master)(struct snd_ice1712 *ice);
++ unsigned int (*get_rate)(struct snd_ice1712 *ice);
++ void (*set_rate)(struct snd_ice1712 *ice, unsigned int rate);
++ unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate);
++ void (*set_spdif_clock)(struct snd_ice1712 *ice);
++
+ };
+
+
+@@ -429,10 +438,14 @@ int snd_ice1712_gpio_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu
+ static inline void snd_ice1712_gpio_write_bits(struct snd_ice1712 *ice,
+ unsigned int mask, unsigned int bits)
+ {
++ unsigned val;
++
+ ice->gpio.direction |= mask;
+ snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
+- snd_ice1712_gpio_set_mask(ice, ~mask);
+- snd_ice1712_gpio_write(ice, mask & bits);
++ val = snd_ice1712_gpio_read(ice);
++ val &= ~mask;
++ val |= mask & bits;
++ snd_ice1712_gpio_write(ice, val);
+ }
+
+ static inline int snd_ice1712_gpio_read_bits(struct snd_ice1712 *ice,
+diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
+index f533850..4490422 100644
+--- a/sound/pci/ice1712/ice1724.c
++++ b/sound/pci/ice1712/ice1724.c
+@@ -106,15 +106,19 @@ static unsigned int PRO_RATE_DEFAULT = 44100;
+ * Basic I/O
+ */
+
++/*
++ * default rates, default clock routines
++ */
++
+ /* check whether the clock mode is spdif-in */
+-static inline int is_spdif_master(struct snd_ice1712 *ice)
++static inline int stdclock_is_spdif_master(struct snd_ice1712 *ice)
+ {
+ return (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER) ? 1 : 0;
+ }
+
+ static inline int is_pro_rate_locked(struct snd_ice1712 *ice)
+ {
+- return is_spdif_master(ice) || PRO_RATE_LOCKED;
++ return ice->is_spdif_master(ice) || PRO_RATE_LOCKED;
+ }
+
+ /*
+@@ -219,6 +223,32 @@ static unsigned int snd_vt1724_get_gpio_data(struct snd_ice1712 *ice)
+ }
+
+ /*
++ * MPU401 accessor
++ */
++static unsigned char snd_vt1724_mpu401_read(struct snd_mpu401 *mpu,
++ unsigned long addr)
++{
++ /* fix status bits to the standard position */
++ /* only RX_EMPTY and TX_FULL are checked */
++ if (addr == MPU401C(mpu))
++ return (inb(addr) & 0x0c) << 4;
++ else
++ return inb(addr);
++}
++
++static void snd_vt1724_mpu401_write(struct snd_mpu401 *mpu,
++ unsigned char data, unsigned long addr)
++{
++ if (addr == MPU401C(mpu)) {
++ if (data == MPU401_ENTER_UART)
++ outb(0x01, addr);
++ /* what else? */
++ } else
++ outb(data, addr);
++}
++
++
++/*
+ * Interrupt handler
+ */
+
+@@ -226,24 +256,53 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id)
+ {
+ struct snd_ice1712 *ice = dev_id;
+ unsigned char status;
++ unsigned char status_mask =
++ VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX | VT1724_IRQ_MTPCM;
+ int handled = 0;
++#ifdef CONFIG_SND_DEBUG
++ int timeout = 0;
++#endif
+
+ while (1) {
+ status = inb(ICEREG1724(ice, IRQSTAT));
++ status &= status_mask;
+ if (status == 0)
+ break;
+-
++#ifdef CONFIG_SND_DEBUG
++ if (++timeout > 10) {
++ printk(KERN_ERR
++ "ice1724: Too long irq loop, status = 0x%x\n",
++ status);
++ break;
++ }
++#endif
+ handled = 1;
+- /* these should probably be separated at some point,
+- * but as we don't currently have MPU support on the board
+- * I will leave it
+- */
+- if ((status & VT1724_IRQ_MPU_RX)||(status & VT1724_IRQ_MPU_TX)) {
++ if (status & VT1724_IRQ_MPU_TX) {
++ if (ice->rmidi[0])
++ snd_mpu401_uart_interrupt_tx(irq,
++ ice->rmidi[0]->private_data);
++ else /* disable TX to be sure */
++ outb(inb(ICEREG1724(ice, IRQMASK)) |
++ VT1724_IRQ_MPU_TX,
++ ICEREG1724(ice, IRQMASK));
++ /* Due to mysterical reasons, MPU_TX is always
++ * generated (and can't be cleared) when a PCM
++ * playback is going. So let's ignore at the
++ * next loop.
++ */
++ status_mask &= ~VT1724_IRQ_MPU_TX;
++ }
++ if (status & VT1724_IRQ_MPU_RX) {
+ if (ice->rmidi[0])
+- snd_mpu401_uart_interrupt(irq, ice->rmidi[0]->private_data);
+- outb(status & (VT1724_IRQ_MPU_RX|VT1724_IRQ_MPU_TX), ICEREG1724(ice, IRQSTAT));
+- status &= ~(VT1724_IRQ_MPU_RX|VT1724_IRQ_MPU_TX);
++ snd_mpu401_uart_interrupt(irq,
++ ice->rmidi[0]->private_data);
++ else /* disable RX to be sure */
++ outb(inb(ICEREG1724(ice, IRQMASK)) |
++ VT1724_IRQ_MPU_RX,
++ ICEREG1724(ice, IRQMASK));
+ }
++ /* ack MPU irq */
++ outb(status, ICEREG1724(ice, IRQSTAT));
+ if (status & VT1724_IRQ_MTPCM) {
+ /*
+ * Multi-track PCM
+@@ -391,51 +450,61 @@ static int snd_vt1724_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+ #define DMA_PAUSES (VT1724_RDMA0_PAUSE|VT1724_PDMA0_PAUSE|VT1724_RDMA1_PAUSE|\
+ VT1724_PDMA1_PAUSE|VT1724_PDMA2_PAUSE|VT1724_PDMA3_PAUSE|VT1724_PDMA4_PAUSE)
+
+-static int get_max_rate(struct snd_ice1712 *ice)
++static const unsigned int stdclock_rate_list[16] = {
++ 48000, 24000, 12000, 9600, 32000, 16000, 8000, 96000, 44100,
++ 22050, 11025, 88200, 176400, 0, 192000, 64000
++};
++
++static unsigned int stdclock_get_rate(struct snd_ice1712 *ice)
+ {
++ unsigned int rate;
++ rate = stdclock_rate_list[inb(ICEMT1724(ice, RATE)) & 15];
++ return rate;
++}
++
++static void stdclock_set_rate(struct snd_ice1712 *ice, unsigned int rate)
++{
++ int i;
++ for (i = 0; i < ARRAY_SIZE(stdclock_rate_list); i++) {
++ if (stdclock_rate_list[i] == rate) {
++ outb(i, ICEMT1724(ice, RATE));
++ return;
++ }
++ }
++}
++
++static unsigned char stdclock_set_mclk(struct snd_ice1712 *ice,
++ unsigned int rate)
++{
++ unsigned char val, old;
++ /* check MT02 */
+ if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
+- if ((ice->eeprom.data[ICE_EEP2_I2S] & 0x08) && !ice->vt1720)
+- return 192000;
++ val = old = inb(ICEMT1724(ice, I2S_FORMAT));
++ if (rate > 96000)
++ val |= VT1724_MT_I2S_MCLK_128X; /* 128x MCLK */
+ else
+- return 96000;
+- } else
+- return 48000;
++ val &= ~VT1724_MT_I2S_MCLK_128X; /* 256x MCLK */
++ if (val != old) {
++ outb(val, ICEMT1724(ice, I2S_FORMAT));
++ /* master clock changed */
++ return 1;
++ }
++ }
++ /* no change in master clock */
++ return 0;
+ }
+
+ static void snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
+ int force)
+ {
+ unsigned long flags;
+- unsigned char val, old;
+- unsigned int i, mclk_change;
++ unsigned char mclk_change;
++ unsigned int i, old_rate;
+
+- if (rate > get_max_rate(ice))
++ if (rate > ice->hw_rates->list[ice->hw_rates->count - 1])
+ return;
+-
+- switch (rate) {
+- case 8000: val = 6; break;
+- case 9600: val = 3; break;
+- case 11025: val = 10; break;
+- case 12000: val = 2; break;
+- case 16000: val = 5; break;
+- case 22050: val = 9; break;
+- case 24000: val = 1; break;
+- case 32000: val = 4; break;
+- case 44100: val = 8; break;
+- case 48000: val = 0; break;
+- case 64000: val = 15; break;
+- case 88200: val = 11; break;
+- case 96000: val = 7; break;
+- case 176400: val = 12; break;
+- case 192000: val = 14; break;
+- default:
+- snd_BUG();
+- val = 0;
+- break;
+- }
+-
+ spin_lock_irqsave(&ice->reg_lock, flags);
+- if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) ||
++ if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) ||
+ (inb(ICEMT1724(ice, DMA_PAUSE)) & DMA_PAUSES)) {
+ /* running? we cannot change the rate now... */
+ spin_unlock_irqrestore(&ice->reg_lock, flags);
+@@ -446,9 +515,9 @@ static void snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
+ return;
+ }
+
+- old = inb(ICEMT1724(ice, RATE));
+- if (force || old != val)
+- outb(val, ICEMT1724(ice, RATE));
++ old_rate = ice->get_rate(ice);
++ if (force || (old_rate != rate))
++ ice->set_rate(ice, rate);
+ else if (rate == ice->cur_rate) {
+ spin_unlock_irqrestore(&ice->reg_lock, flags);
+ return;
+@@ -456,19 +525,9 @@ static void snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
+
+ ice->cur_rate = rate;
+
+- /* check MT02 */
+- mclk_change = 0;
+- if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
+- val = old = inb(ICEMT1724(ice, I2S_FORMAT));
+- if (rate > 96000)
+- val |= VT1724_MT_I2S_MCLK_128X; /* 128x MCLK */
+- else
+- val &= ~VT1724_MT_I2S_MCLK_128X; /* 256x MCLK */
+- if (val != old) {
+- outb(val, ICEMT1724(ice, I2S_FORMAT));
+- mclk_change = 1;
+- }
+- }
++ /* setting master clock */
++ mclk_change = ice->set_mclk(ice, rate);
++
+ spin_unlock_irqrestore(&ice->reg_lock, flags);
+
+ if (mclk_change && ice->gpio.i2s_mclk_changed)
+@@ -727,43 +786,32 @@ static const struct snd_pcm_hardware snd_vt1724_2ch_stereo =
+ /*
+ * set rate constraints
+ */
+-static int set_rate_constraints(struct snd_ice1712 *ice,
+- struct snd_pcm_substream *substream)
++static void set_std_hw_rates(struct snd_ice1712 *ice)
+ {
+- struct snd_pcm_runtime *runtime = substream->runtime;
+- if (ice->hw_rates) {
+- /* hardware specific */
+- runtime->hw.rate_min = ice->hw_rates->list[0];
+- runtime->hw.rate_max = ice->hw_rates->list[ice->hw_rates->count - 1];
+- runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
+- return snd_pcm_hw_constraint_list(runtime, 0,
+- SNDRV_PCM_HW_PARAM_RATE,
+- ice->hw_rates);
+- }
+ if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
+ /* I2S */
+ /* VT1720 doesn't support more than 96kHz */
+ if ((ice->eeprom.data[ICE_EEP2_I2S] & 0x08) && !ice->vt1720)
+- return snd_pcm_hw_constraint_list(runtime, 0,
+- SNDRV_PCM_HW_PARAM_RATE,
+- &hw_constraints_rates_192);
+- else {
+- runtime->hw.rates = SNDRV_PCM_RATE_KNOT |
+- SNDRV_PCM_RATE_8000_96000;
+- runtime->hw.rate_max = 96000;
+- return snd_pcm_hw_constraint_list(runtime, 0,
+- SNDRV_PCM_HW_PARAM_RATE,
+- &hw_constraints_rates_96);
+- }
+- } else if (ice->ac97) {
++ ice->hw_rates = &hw_constraints_rates_192;
++ else
++ ice->hw_rates = &hw_constraints_rates_96;
++ } else {
+ /* ACLINK */
+- runtime->hw.rate_max = 48000;
+- runtime->hw.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000;
+- return snd_pcm_hw_constraint_list(runtime, 0,
+- SNDRV_PCM_HW_PARAM_RATE,
+- &hw_constraints_rates_48);
++ ice->hw_rates = &hw_constraints_rates_48;
+ }
+- return 0;
++}
++
++static int set_rate_constraints(struct snd_ice1712 *ice,
++ struct snd_pcm_substream *substream)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++
++ runtime->hw.rate_min = ice->hw_rates->list[0];
++ runtime->hw.rate_max = ice->hw_rates->list[ice->hw_rates->count - 1];
++ runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
++ return snd_pcm_hw_constraint_list(runtime, 0,
++ SNDRV_PCM_HW_PARAM_RATE,
++ ice->hw_rates);
+ }
+
+ /* multi-channel playback needs alignment 8x32bit regardless of the channels
+@@ -824,7 +872,7 @@ static int snd_vt1724_playback_pro_close(struct snd_pcm_substream *substream)
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
+
+ if (PRO_RATE_RESET)
+- snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
++ snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
+ ice->playback_pro_substream = NULL;
+
+ return 0;
+@@ -835,7 +883,7 @@ static int snd_vt1724_capture_pro_close(struct snd_pcm_substream *substream)
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
+
+ if (PRO_RATE_RESET)
+- snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
++ snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
+ ice->capture_pro_substream = NULL;
+ return 0;
+ }
+@@ -970,6 +1018,8 @@ static int snd_vt1724_playback_spdif_open(struct snd_pcm_substream *substream)
+ VT1724_BUFFER_ALIGN);
+ snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+ VT1724_BUFFER_ALIGN);
++ if (ice->spdif.ops.open)
++ ice->spdif.ops.open(ice, substream);
+ return 0;
+ }
+
+@@ -978,8 +1028,10 @@ static int snd_vt1724_playback_spdif_close(struct snd_pcm_substream *substream)
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
+
+ if (PRO_RATE_RESET)
+- snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
++ snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
+ ice->playback_con_substream = NULL;
++ if (ice->spdif.ops.close)
++ ice->spdif.ops.close(ice, substream);
+
+ return 0;
+ }
+@@ -1002,6 +1054,8 @@ static int snd_vt1724_capture_spdif_open(struct snd_pcm_substream *substream)
+ VT1724_BUFFER_ALIGN);
+ snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+ VT1724_BUFFER_ALIGN);
++ if (ice->spdif.ops.open)
++ ice->spdif.ops.open(ice, substream);
+ return 0;
+ }
+
+@@ -1010,8 +1064,10 @@ static int snd_vt1724_capture_spdif_close(struct snd_pcm_substream *substream)
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
+
+ if (PRO_RATE_RESET)
+- snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
++ snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
+ ice->capture_con_substream = NULL;
++ if (ice->spdif.ops.close)
++ ice->spdif.ops.close(ice, substream);
+
+ return 0;
+ }
+@@ -1154,7 +1210,7 @@ static int snd_vt1724_playback_indep_close(struct snd_pcm_substream *substream)
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
+
+ if (PRO_RATE_RESET)
+- snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
++ snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
+ ice->playback_con_substream_ds[substream->number] = NULL;
+ ice->pcm_reserved[substream->number] = NULL;
+
+@@ -1572,50 +1628,18 @@ int snd_ice1712_gpio_put(struct snd_kcontrol *kcontrol,
+ static int snd_vt1724_pro_internal_clock_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+ {
+- static const char * const texts_1724[] = {
+- "8000", /* 0: 6 */
+- "9600", /* 1: 3 */
+- "11025", /* 2: 10 */
+- "12000", /* 3: 2 */
+- "16000", /* 4: 5 */
+- "22050", /* 5: 9 */
+- "24000", /* 6: 1 */
+- "32000", /* 7: 4 */
+- "44100", /* 8: 8 */
+- "48000", /* 9: 0 */
+- "64000", /* 10: 15 */
+- "88200", /* 11: 11 */
+- "96000", /* 12: 7 */
+- "176400", /* 13: 12 */
+- "192000", /* 14: 14 */
+- "IEC958 Input", /* 15: -- */
+- };
+- static const char * const texts_1720[] = {
+- "8000", /* 0: 6 */
+- "9600", /* 1: 3 */
+- "11025", /* 2: 10 */
+- "12000", /* 3: 2 */
+- "16000", /* 4: 5 */
+- "22050", /* 5: 9 */
+- "24000", /* 6: 1 */
+- "32000", /* 7: 4 */
+- "44100", /* 8: 8 */
+- "48000", /* 9: 0 */
+- "64000", /* 10: 15 */
+- "88200", /* 11: 11 */
+- "96000", /* 12: 7 */
+- "IEC958 Input", /* 13: -- */
+- };
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+- uinfo->value.enumerated.items = ice->vt1720 ? 14 : 16;
++ uinfo->value.enumerated.items = ice->hw_rates->count + 1;
+ if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+ uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+- strcpy(uinfo->value.enumerated.name,
+- ice->vt1720 ? texts_1720[uinfo->value.enumerated.item] :
+- texts_1724[uinfo->value.enumerated.item]);
++ if (uinfo->value.enumerated.item == uinfo->value.enumerated.items - 1)
++ strcpy(uinfo->value.enumerated.name, "IEC958 Input");
++ else
++ sprintf(uinfo->value.enumerated.name, "%d",
++ ice->hw_rates->list[uinfo->value.enumerated.item]);
+ return 0;
+ }
+
+@@ -1623,68 +1647,79 @@ static int snd_vt1724_pro_internal_clock_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+ {
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+- static const unsigned char xlate[16] = {
+- 9, 6, 3, 1, 7, 4, 0, 12, 8, 5, 2, 11, 13, 255, 14, 10
+- };
+- unsigned char val;
++ unsigned int i, rate;
+
+ spin_lock_irq(&ice->reg_lock);
+- if (is_spdif_master(ice)) {
+- ucontrol->value.enumerated.item[0] = ice->vt1720 ? 13 : 15;
++ if (ice->is_spdif_master(ice)) {
++ ucontrol->value.enumerated.item[0] = ice->hw_rates->count;
+ } else {
+- val = xlate[inb(ICEMT1724(ice, RATE)) & 15];
+- if (val == 255) {
+- snd_BUG();
+- val = 0;
++ rate = ice->get_rate(ice);
++ ucontrol->value.enumerated.item[0] = 0;
++ for (i = 0; i < ice->hw_rates->count; i++) {
++ if (ice->hw_rates->list[i] == rate) {
++ ucontrol->value.enumerated.item[0] = i;
++ break;
++ }
+ }
+- ucontrol->value.enumerated.item[0] = val;
+ }
+ spin_unlock_irq(&ice->reg_lock);
+ return 0;
+ }
+
++/* setting clock to external - SPDIF */
++static void stdclock_set_spdif_clock(struct snd_ice1712 *ice)
++{
++ unsigned char oval;
++ unsigned char i2s_oval;
++ oval = inb(ICEMT1724(ice, RATE));
++ outb(oval | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE));
++ /* setting 256fs */
++ i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT));
++ outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X, ICEMT1724(ice, I2S_FORMAT));
++}
++
+ static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+ {
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+- unsigned char oval;
+- int rate;
+- int change = 0;
+- int spdif = ice->vt1720 ? 13 : 15;
++ unsigned int old_rate, new_rate;
++ unsigned int item = ucontrol->value.enumerated.item[0];
++ unsigned int spdif = ice->hw_rates->count;
++
++ if (item > spdif)
++ return -EINVAL;
+
+ spin_lock_irq(&ice->reg_lock);
+- oval = inb(ICEMT1724(ice, RATE));
+- if (ucontrol->value.enumerated.item[0] == spdif) {
+- unsigned char i2s_oval;
+- outb(oval | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE));
+- /* setting 256fs */
+- i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT));
+- outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X,
+- ICEMT1724(ice, I2S_FORMAT));
++ if (ice->is_spdif_master(ice))
++ old_rate = 0;
++ else
++ old_rate = ice->get_rate(ice);
++ if (item == spdif) {
++ /* switching to external clock via SPDIF */
++ ice->set_spdif_clock(ice);
++ new_rate = 0;
+ } else {
+- rate = rates[ucontrol->value.integer.value[0] % 15];
+- if (rate <= get_max_rate(ice)) {
+- PRO_RATE_DEFAULT = rate;
+- spin_unlock_irq(&ice->reg_lock);
+- snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 1);
+- spin_lock_irq(&ice->reg_lock);
+- }
++ /* internal on-card clock */
++ new_rate = ice->hw_rates->list[item];
++ ice->pro_rate_default = new_rate;
++ spin_unlock_irq(&ice->reg_lock);
++ snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1);
++ spin_lock_irq(&ice->reg_lock);
+ }
+- change = inb(ICEMT1724(ice, RATE)) != oval;
+ spin_unlock_irq(&ice->reg_lock);
+
+- if ((oval & VT1724_SPDIF_MASTER) !=
+- (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER)) {
++ /* the first reset to the SPDIF master mode? */
++ if (old_rate != new_rate && !new_rate) {
+ /* notify akm chips as well */
+- if (is_spdif_master(ice)) {
+- unsigned int i;
+- for (i = 0; i < ice->akm_codecs; i++) {
+- if (ice->akm[i].ops.set_rate_val)
+- ice->akm[i].ops.set_rate_val(&ice->akm[i], 0);
+- }
++ unsigned int i;
++ if (ice->gpio.set_pro_rate)
++ ice->gpio.set_pro_rate(ice, 0);
++ for (i = 0; i < ice->akm_codecs; i++) {
++ if (ice->akm[i].ops.set_rate_val)
++ ice->akm[i].ops.set_rate_val(&ice->akm[i], 0);
+ }
+ }
+- return change;
++ return old_rate != new_rate;
+ }
+
+ static struct snd_kcontrol_new snd_vt1724_pro_internal_clock __devinitdata = {
+@@ -2065,12 +2100,16 @@ static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
+
+
+
+-static int __devinit snd_vt1724_chip_init(struct snd_ice1712 *ice)
++static void __devinit snd_vt1724_chip_reset(struct snd_ice1712 *ice)
+ {
+ outb(VT1724_RESET , ICEREG1724(ice, CONTROL));
+- udelay(200);
++ msleep(10);
+ outb(0, ICEREG1724(ice, CONTROL));
+- udelay(200);
++ msleep(10);
++}
++
++static int __devinit snd_vt1724_chip_init(struct snd_ice1712 *ice)
++{
+ outb(ice->eeprom.data[ICE_EEP2_SYSCONF], ICEREG1724(ice, SYS_CFG));
+ outb(ice->eeprom.data[ICE_EEP2_ACLINK], ICEREG1724(ice, AC97_CFG));
+ outb(ice->eeprom.data[ICE_EEP2_I2S], ICEREG1724(ice, I2S_FEATURES));
+@@ -2169,10 +2208,8 @@ static int snd_vt1724_free(struct snd_ice1712 *ice)
+ outb(0xff, ICEREG1724(ice, IRQMASK));
+ /* --- */
+ __hw_end:
+- if (ice->irq >= 0) {
+- synchronize_irq(ice->irq);
++ if (ice->irq >= 0)
+ free_irq(ice->irq, ice);
+- }
+ pci_release_regions(ice->pci);
+ snd_ice1712_akm4xxx_free(ice);
+ pci_disable_device(ice->pci);
+@@ -2243,6 +2280,7 @@ static int __devinit snd_vt1724_create(struct snd_card *card,
+
+ ice->irq = pci->irq;
+
++ snd_vt1724_chip_reset(ice);
+ if (snd_vt1724_read_eeprom(ice, modelname) < 0) {
+ snd_vt1724_free(ice);
+ return -EIO;
+@@ -2253,10 +2291,7 @@ static int __devinit snd_vt1724_create(struct snd_card *card,
+ }
+
+ /* unmask used interrupts */
+- if (! (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401))
+- mask = VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX;
+- else
+- mask = 0;
++ mask = VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX;
+ outb(mask, ICEREG1724(ice, IRQMASK));
+ /* don't handle FIFO overrun/underruns (just yet),
+ * since they cause machine lockups
+@@ -2335,6 +2370,19 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,
+ * was called so in ice1712 driver, and vt1724 driver is derived from
+ * ice1712 driver.
+ */
++ ice->pro_rate_default = PRO_RATE_DEFAULT;
++ if (!ice->is_spdif_master)
++ ice->is_spdif_master = stdclock_is_spdif_master;
++ if (!ice->get_rate)
++ ice->get_rate = stdclock_get_rate;
++ if (!ice->set_rate)
++ ice->set_rate = stdclock_set_rate;
++ if (!ice->set_mclk)
++ ice->set_mclk = stdclock_set_mclk;
++ if (!ice->set_spdif_clock)
++ ice->set_spdif_clock = stdclock_set_spdif_clock;
++ if (!ice->hw_rates)
++ set_std_hw_rates(ice);
+
+ if ((err = snd_vt1724_pcm_profi(ice, pcm_dev++)) < 0) {
+ snd_card_free(card);
+@@ -2377,14 +2425,29 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,
+
+ if (! c->no_mpu401) {
+ if (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401) {
++ struct snd_mpu401 *mpu;
+ if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712,
+ ICEREG1724(ice, MPU_CTRL),
+- MPU401_INFO_INTEGRATED,
++ (MPU401_INFO_INTEGRATED |
++ MPU401_INFO_TX_IRQ),
+ ice->irq, 0,
+ &ice->rmidi[0])) < 0) {
+ snd_card_free(card);
+ return err;
+ }
++ mpu = ice->rmidi[0]->private_data;
++ mpu->read = snd_vt1724_mpu401_read;
++ mpu->write = snd_vt1724_mpu401_write;
++ /* unmask MPU RX/TX irqs */
++ outb(inb(ICEREG1724(ice, IRQMASK)) &
++ ~(VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX),
++ ICEREG1724(ice, IRQMASK));
++#if 0 /* for testing */
++ /* set watermarks */
++ outb(VT1724_MPU_RX_FIFO | 0x1,
++ ICEREG1724(ice, MPU_FIFO_WM));
++ outb(0x1, ICEREG1724(ice, MPU_FIFO_WM));
++#endif
+ }
+ }
+
+diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c
+index e8038c0..b4e0c16 100644
+--- a/sound/pci/ice1712/juli.c
++++ b/sound/pci/ice1712/juli.c
+@@ -4,6 +4,8 @@
+ * Lowlevel functions for ESI Juli@ cards
+ *
+ * Copyright (c) 2004 Jaroslav Kysela <perex at perex.cz>
++ * 2008 Pavel Hofman <dustin at seznam.cz>
++ *
+ *
+ * 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
+@@ -27,11 +29,11 @@
+ #include <linux/init.h>
+ #include <linux/slab.h>
+ #include <sound/core.h>
++#include <sound/tlv.h>
+
+ #include "ice1712.h"
+ #include "envy24ht.h"
+ #include "juli.h"
+-
+ struct juli_spec {
+ struct ak4114 *ak4114;
+ unsigned int analog: 1;
+@@ -44,6 +46,32 @@ struct juli_spec {
+ #define AK4358_ADDR 0x22 /* DAC */
+
+ /*
++ * Juli does not use the standard ICE1724 clock scheme. Juli's ice1724 chip is
++ * supplied by external clock provided by Xilinx array and MK73-1 PLL frequency
++ * multiplier. Actual frequency is set by ice1724 GPIOs hooked to the Xilinx.
++ *
++ * The clock circuitry is supplied by the two ice1724 crystals. This
++ * arrangement allows to generate independent clock signal for AK4114's input
++ * rate detection circuit. As a result, Juli, unlike most other
++ * ice1724+ak4114-based cards, detects spdif input rate correctly.
++ * This fact is applied in the driver, allowing to modify PCM stream rate
++ * parameter according to the actual input rate.
++ *
++ * Juli uses the remaining three stereo-channels of its DAC to optionally
++ * monitor analog input, digital input, and digital output. The corresponding
++ * I2S signals are routed by Xilinx, controlled by GPIOs.
++ *
++ * The master mute is implemented using output muting transistors (GPIO) in
++ * combination with smuting the DAC.
++ *
++ * The card itself has no HW master volume control, implemented using the
++ * vmaster control.
++ *
++ * TODO:
++ * researching and fixing the input monitors
++ */
++
++/*
+ * GPIO pins
+ */
+ #define GPIO_FREQ_MASK (3<<0)
+@@ -55,17 +83,82 @@ struct juli_spec {
+ #define GPIO_MULTI_2X (1<<2)
+ #define GPIO_MULTI_1X (2<<2) /* also external */
+ #define GPIO_MULTI_HALF (3<<2)
+-#define GPIO_INTERNAL_CLOCK (1<<4)
++#define GPIO_INTERNAL_CLOCK (1<<4) /* 0 = external, 1 = internal */
++#define GPIO_CLOCK_MASK (1<<4)
+ #define GPIO_ANALOG_PRESENT (1<<5) /* RO only: 0 = present */
+ #define GPIO_RXMCLK_SEL (1<<7) /* must be 0 */
+ #define GPIO_AK5385A_CKS0 (1<<8)
+-#define GPIO_AK5385A_DFS0 (1<<9) /* swapped with DFS1 according doc? */
+-#define GPIO_AK5385A_DFS1 (1<<10)
++#define GPIO_AK5385A_DFS1 (1<<9)
++#define GPIO_AK5385A_DFS0 (1<<10)
+ #define GPIO_DIGOUT_MONITOR (1<<11) /* 1 = active */
+ #define GPIO_DIGIN_MONITOR (1<<12) /* 1 = active */
+ #define GPIO_ANAIN_MONITOR (1<<13) /* 1 = active */
+-#define GPIO_AK5385A_MCLK (1<<14) /* must be 0 */
+-#define GPIO_MUTE_CONTROL (1<<15) /* 0 = off, 1 = on */
++#define GPIO_AK5385A_CKS1 (1<<14) /* must be 0 */
++#define GPIO_MUTE_CONTROL (1<<15) /* output mute, 1 = muted */
++
++#define GPIO_RATE_MASK (GPIO_FREQ_MASK | GPIO_MULTI_MASK | \
++ GPIO_CLOCK_MASK)
++#define GPIO_AK5385A_MASK (GPIO_AK5385A_CKS0 | GPIO_AK5385A_DFS0 | \
++ GPIO_AK5385A_DFS1 | GPIO_AK5385A_CKS1)
++
++#define JULI_PCM_RATE (SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
++ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
++ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \
++ SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \
++ SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
++
++#define GPIO_RATE_16000 (GPIO_FREQ_32KHZ | GPIO_MULTI_HALF | \
++ GPIO_INTERNAL_CLOCK)
++#define GPIO_RATE_22050 (GPIO_FREQ_44KHZ | GPIO_MULTI_HALF | \
++ GPIO_INTERNAL_CLOCK)
++#define GPIO_RATE_24000 (GPIO_FREQ_48KHZ | GPIO_MULTI_HALF | \
++ GPIO_INTERNAL_CLOCK)
++#define GPIO_RATE_32000 (GPIO_FREQ_32KHZ | GPIO_MULTI_1X | \
++ GPIO_INTERNAL_CLOCK)
++#define GPIO_RATE_44100 (GPIO_FREQ_44KHZ | GPIO_MULTI_1X | \
++ GPIO_INTERNAL_CLOCK)
++#define GPIO_RATE_48000 (GPIO_FREQ_48KHZ | GPIO_MULTI_1X | \
++ GPIO_INTERNAL_CLOCK)
++#define GPIO_RATE_64000 (GPIO_FREQ_32KHZ | GPIO_MULTI_2X | \
++ GPIO_INTERNAL_CLOCK)
++#define GPIO_RATE_88200 (GPIO_FREQ_44KHZ | GPIO_MULTI_2X | \
++ GPIO_INTERNAL_CLOCK)
++#define GPIO_RATE_96000 (GPIO_FREQ_48KHZ | GPIO_MULTI_2X | \
++ GPIO_INTERNAL_CLOCK)
++#define GPIO_RATE_176400 (GPIO_FREQ_44KHZ | GPIO_MULTI_4X | \
++ GPIO_INTERNAL_CLOCK)
++#define GPIO_RATE_192000 (GPIO_FREQ_48KHZ | GPIO_MULTI_4X | \
++ GPIO_INTERNAL_CLOCK)
++
++/*
++ * Initial setup of the conversion array GPIO <-> rate
++ */
++static unsigned int juli_rates[] = {
++ 16000, 22050, 24000, 32000,
++ 44100, 48000, 64000, 88200,
++ 96000, 176400, 192000,
++};
++
++static unsigned int gpio_vals[] = {
++ GPIO_RATE_16000, GPIO_RATE_22050, GPIO_RATE_24000, GPIO_RATE_32000,
++ GPIO_RATE_44100, GPIO_RATE_48000, GPIO_RATE_64000, GPIO_RATE_88200,
++ GPIO_RATE_96000, GPIO_RATE_176400, GPIO_RATE_192000,
++};
++
++static struct snd_pcm_hw_constraint_list juli_rates_info = {
++ .count = ARRAY_SIZE(juli_rates),
++ .list = juli_rates,
++ .mask = 0,
++};
++
++static int get_gpio_val(int rate)
++{
++ int i;
++ for (i = 0; i < ARRAY_SIZE(juli_rates); i++)
++ if (juli_rates[i] == rate)
++ return gpio_vals[i];
++ return 0;
++}
+
+ static void juli_ak4114_write(void *private_data, unsigned char reg, unsigned char val)
+ {
+@@ -78,6 +171,27 @@ static unsigned char juli_ak4114_read(void *private_data, unsigned char reg)
+ }
+
+ /*
++ * If SPDIF capture and slaved to SPDIF-IN, setting runtime rate
++ * to the external rate
++ */
++static void juli_spdif_in_open(struct snd_ice1712 *ice,
++ struct snd_pcm_substream *substream)
++{
++ struct juli_spec *spec = ice->spec;
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ int rate;
++
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
++ !ice->is_spdif_master(ice))
++ return;
++ rate = snd_ak4114_external_rate(spec->ak4114);
++ if (rate >= runtime->hw.rate_min && rate <= runtime->hw.rate_max) {
++ runtime->hw.rate_min = rate;
++ runtime->hw.rate_max = rate;
++ }
++}
++
++/*
+ * AK4358 section
+ */
+
+@@ -99,57 +213,285 @@ static void juli_akm_write(struct snd_akm4xxx *ak, int chip,
+ }
+
+ /*
+- * change the rate of envy24HT, AK4358
++ * change the rate of envy24HT, AK4358, AK5385
+ */
+ static void juli_akm_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
+ {
+- unsigned char old, tmp, dfs;
++ unsigned char old, tmp, ak4358_dfs;
++ unsigned int ak5385_pins, old_gpio, new_gpio;
++ struct snd_ice1712 *ice = ak->private_data[0];
++ struct juli_spec *spec = ice->spec;
+
+- if (rate == 0) /* no hint - S/PDIF input is master, simply return */
++ if (rate == 0) /* no hint - S/PDIF input is master or the new spdif
++ input rate undetected, simply return */
+ return;
+-
++
+ /* adjust DFS on codecs */
+- if (rate > 96000)
+- dfs = 2;
+- else if (rate > 48000)
+- dfs = 1;
+- else
+- dfs = 0;
+-
++ if (rate > 96000) {
++ ak4358_dfs = 2;
++ ak5385_pins = GPIO_AK5385A_DFS1 | GPIO_AK5385A_CKS0;
++ } else if (rate > 48000) {
++ ak4358_dfs = 1;
++ ak5385_pins = GPIO_AK5385A_DFS0;
++ } else {
++ ak4358_dfs = 0;
++ ak5385_pins = 0;
++ }
++ /* AK5385 first, since it requires cold reset affecting both codecs */
++ old_gpio = ice->gpio.get_data(ice);
++ new_gpio = (old_gpio & ~GPIO_AK5385A_MASK) | ak5385_pins;
++ /* printk(KERN_DEBUG "JULI - ak5385 set_rate_val: new gpio 0x%x\n",
++ new_gpio); */
++ ice->gpio.set_data(ice, new_gpio);
++
++ /* cold reset */
++ old = inb(ICEMT1724(ice, AC97_CMD));
++ outb(old | VT1724_AC97_COLD, ICEMT1724(ice, AC97_CMD));
++ udelay(1);
++ outb(old & ~VT1724_AC97_COLD, ICEMT1724(ice, AC97_CMD));
++
++ /* AK4358 */
++ /* set new value, reset DFS */
+ tmp = snd_akm4xxx_get(ak, 0, 2);
+- old = (tmp >> 4) & 0x03;
+- if (old == dfs)
+- return;
+- /* reset DFS */
+ snd_akm4xxx_reset(ak, 1);
+ tmp = snd_akm4xxx_get(ak, 0, 2);
+ tmp &= ~(0x03 << 4);
+- tmp |= dfs << 4;
++ tmp |= ak4358_dfs << 4;
+ snd_akm4xxx_set(ak, 0, 2, tmp);
+ snd_akm4xxx_reset(ak, 0);
++
++ /* reinit ak4114 */
++ snd_ak4114_reinit(spec->ak4114);
+ }
+
++#define AK_DAC(xname, xch) { .name = xname, .num_channels = xch }
++#define PCM_VOLUME "PCM Playback Volume"
++#define MONITOR_AN_IN_VOLUME "Monitor Analog In Volume"
++#define MONITOR_DIG_IN_VOLUME "Monitor Digital In Volume"
++#define MONITOR_DIG_OUT_VOLUME "Monitor Digital Out Volume"
++
++static const struct snd_akm4xxx_dac_channel juli_dac[] = {
++ AK_DAC(PCM_VOLUME, 2),
++ AK_DAC(MONITOR_AN_IN_VOLUME, 2),
++ AK_DAC(MONITOR_DIG_OUT_VOLUME, 2),
++ AK_DAC(MONITOR_DIG_IN_VOLUME, 2),
++};
++
++
+ static struct snd_akm4xxx akm_juli_dac __devinitdata = {
+ .type = SND_AK4358,
+- .num_dacs = 2,
++ .num_dacs = 8, /* DAC1 - analog out
++ DAC2 - analog in monitor
++ DAC3 - digital out monitor
++ DAC4 - digital in monitor
++ */
+ .ops = {
+ .lock = juli_akm_lock,
+ .unlock = juli_akm_unlock,
+ .write = juli_akm_write,
+ .set_rate_val = juli_akm_set_rate_val
++ },
++ .dac_info = juli_dac,
++};
++
++#define juli_mute_info snd_ctl_boolean_mono_info
++
++static int juli_mute_get(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
++ unsigned int val;
++ val = ice->gpio.get_data(ice) & (unsigned int) kcontrol->private_value;
++ if (kcontrol->private_value == GPIO_MUTE_CONTROL)
++ /* val 0 = signal on */
++ ucontrol->value.integer.value[0] = (val) ? 0 : 1;
++ else
++ /* val 1 = signal on */
++ ucontrol->value.integer.value[0] = (val) ? 1 : 0;
++ return 0;
++}
++
++static int juli_mute_put(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
++ unsigned int old_gpio, new_gpio;
++ old_gpio = ice->gpio.get_data(ice);
++ if (ucontrol->value.integer.value[0]) {
++ /* unmute */
++ if (kcontrol->private_value == GPIO_MUTE_CONTROL) {
++ /* 0 = signal on */
++ new_gpio = old_gpio & ~GPIO_MUTE_CONTROL;
++ /* un-smuting DAC */
++ snd_akm4xxx_write(ice->akm, 0, 0x01, 0x01);
++ } else
++ /* 1 = signal on */
++ new_gpio = old_gpio |
++ (unsigned int) kcontrol->private_value;
++ } else {
++ /* mute */
++ if (kcontrol->private_value == GPIO_MUTE_CONTROL) {
++ /* 1 = signal off */
++ new_gpio = old_gpio | GPIO_MUTE_CONTROL;
++ /* smuting DAC */
++ snd_akm4xxx_write(ice->akm, 0, 0x01, 0x03);
++ } else
++ /* 0 = signal off */
++ new_gpio = old_gpio &
++ ~((unsigned int) kcontrol->private_value);
++ }
++ /* printk("JULI - mute/unmute: control_value: 0x%x, old_gpio: 0x%x, \
++ new_gpio 0x%x\n",
++ (unsigned int)ucontrol->value.integer.value[0], old_gpio,
++ new_gpio); */
++ if (old_gpio != new_gpio) {
++ ice->gpio.set_data(ice, new_gpio);
++ return 1;
++ }
++ /* no change */
++ return 0;
++}
++
++static struct snd_kcontrol_new juli_mute_controls[] __devinitdata = {
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Master Playback Switch",
++ .info = juli_mute_info,
++ .get = juli_mute_get,
++ .put = juli_mute_put,
++ .private_value = GPIO_MUTE_CONTROL,
++ },
++ /* Although the following functionality respects the succint NDA'd
++ * documentation from the card manufacturer, and the same way of
++ * operation is coded in OSS Juli driver, only Digital Out monitor
++ * seems to work. Surprisingly, Analog input monitor outputs Digital
++ * output data. The two are independent, as enabling both doubles
++ * volume of the monitor sound.
++ *
++ * Checking traces on the board suggests the functionality described
++ * by the manufacturer is correct - I2S from ADC and AK4114
++ * go to ICE as well as to Xilinx, I2S inputs of DAC2,3,4 (the monitor
++ * inputs) are fed from Xilinx.
++ *
++ * I even checked traces on board and coded a support in driver for
++ * an alternative possiblity - the unused I2S ICE output channels
++ * switched to HW-IN/SPDIF-IN and providing the monitoring signal to
++ * the DAC - to no avail. The I2S outputs seem to be unconnected.
++ *
++ * The windows driver supports the monitoring correctly.
++ */
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Monitor Analog In Switch",
++ .info = juli_mute_info,
++ .get = juli_mute_get,
++ .put = juli_mute_put,
++ .private_value = GPIO_ANAIN_MONITOR,
++ },
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Monitor Digital Out Switch",
++ .info = juli_mute_info,
++ .get = juli_mute_get,
++ .put = juli_mute_put,
++ .private_value = GPIO_DIGOUT_MONITOR,
++ },
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Monitor Digital In Switch",
++ .info = juli_mute_info,
++ .get = juli_mute_get,
++ .put = juli_mute_put,
++ .private_value = GPIO_DIGIN_MONITOR,
++ },
++};
++
++
++static void ak4358_proc_regs_read(struct snd_info_entry *entry,
++ struct snd_info_buffer *buffer)
++{
++ struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data;
++ int reg, val;
++ for (reg = 0; reg <= 0xf; reg++) {
++ val = snd_akm4xxx_get(ice->akm, 0, reg);
++ snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val);
+ }
++}
++
++static void ak4358_proc_init(struct snd_ice1712 *ice)
++{
++ struct snd_info_entry *entry;
++ if (!snd_card_proc_new(ice->card, "ak4358_codec", &entry))
++ snd_info_set_text_ops(entry, ice, ak4358_proc_regs_read);
++}
++
++static char *slave_vols[] __devinitdata = {
++ PCM_VOLUME,
++ MONITOR_AN_IN_VOLUME,
++ MONITOR_DIG_IN_VOLUME,
++ MONITOR_DIG_OUT_VOLUME,
++ NULL
+ };
+
++static __devinitdata
++DECLARE_TLV_DB_SCALE(juli_master_db_scale, -6350, 50, 1);
++
++static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card,
++ const char *name)
++{
++ struct snd_ctl_elem_id sid;
++ memset(&sid, 0, sizeof(sid));
++ /* FIXME: strcpy is bad. */
++ strcpy(sid.name, name);
++ sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
++ return snd_ctl_find_id(card, &sid);
++}
++
++static void __devinit add_slaves(struct snd_card *card,
++ struct snd_kcontrol *master, char **list)
++{
++ for (; *list; list++) {
++ struct snd_kcontrol *slave = ctl_find(card, *list);
++ /* printk(KERN_DEBUG "add_slaves - %s\n", *list); */
++ if (slave) {
++ /* printk(KERN_DEBUG "slave %s found\n", *list); */
++ snd_ctl_add_slave(master, slave);
++ }
++ }
++}
++
+ static int __devinit juli_add_controls(struct snd_ice1712 *ice)
+ {
+ struct juli_spec *spec = ice->spec;
+ int err;
++ unsigned int i;
++ struct snd_kcontrol *vmaster;
++
+ err = snd_ice1712_akm4xxx_build_controls(ice);
+ if (err < 0)
+ return err;
++
++ for (i = 0; i < ARRAY_SIZE(juli_mute_controls); i++) {
++ err = snd_ctl_add(ice->card,
++ snd_ctl_new1(&juli_mute_controls[i], ice));
++ if (err < 0)
++ return err;
++ }
++ /* Create virtual master control */
++ vmaster = snd_ctl_make_virtual_master("Master Playback Volume",
++ juli_master_db_scale);
++ if (!vmaster)
++ return -ENOMEM;
++ add_slaves(ice->card, vmaster, slave_vols);
++ err = snd_ctl_add(ice->card, vmaster);
++ if (err < 0)
++ return err;
++
+ /* only capture SPDIF over AK4114 */
+ err = snd_ak4114_build(spec->ak4114, NULL,
+- ice->pcm_pro->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
++ ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
++
++ ak4358_proc_init(ice);
+ if (err < 0)
+ return err;
+ return 0;
+@@ -158,6 +500,74 @@ static int __devinit juli_add_controls(struct snd_ice1712 *ice)
+ /*
+ * initialize the chip
+ */
++
++static inline int juli_is_spdif_master(struct snd_ice1712 *ice)
++{
++ return (ice->gpio.get_data(ice) & GPIO_INTERNAL_CLOCK) ? 0 : 1;
++}
++
++static unsigned int juli_get_rate(struct snd_ice1712 *ice)
++{
++ int i;
++ unsigned char result;
++
++ result = ice->gpio.get_data(ice) & GPIO_RATE_MASK;
++ for (i = 0; i < ARRAY_SIZE(gpio_vals); i++)
++ if (gpio_vals[i] == result)
++ return juli_rates[i];
++ return 0;
++}
++
++/* setting new rate */
++static void juli_set_rate(struct snd_ice1712 *ice, unsigned int rate)
++{
++ unsigned int old, new;
++ unsigned char val;
++
++ old = ice->gpio.get_data(ice);
++ new = (old & ~GPIO_RATE_MASK) | get_gpio_val(rate);
++ /* printk(KERN_DEBUG "JULI - set_rate: old %x, new %x\n",
++ old & GPIO_RATE_MASK,
++ new & GPIO_RATE_MASK); */
++
++ ice->gpio.set_data(ice, new);
++ /* switching to external clock - supplied by external circuits */
++ val = inb(ICEMT1724(ice, RATE));
++ outb(val | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE));
++}
++
++static inline unsigned char juli_set_mclk(struct snd_ice1712 *ice,
++ unsigned int rate)
++{
++ /* no change in master clock */
++ return 0;
++}
++
++/* setting clock to external - SPDIF */
++static void juli_set_spdif_clock(struct snd_ice1712 *ice)
++{
++ unsigned int old;
++ old = ice->gpio.get_data(ice);
++ /* external clock (= 0), multiply 1x, 48kHz */
++ ice->gpio.set_data(ice, (old & ~GPIO_RATE_MASK) | GPIO_MULTI_1X |
++ GPIO_FREQ_48KHZ);
++}
++
++/* Called when ak4114 detects change in the input SPDIF stream */
++static void juli_ak4114_change(struct ak4114 *ak4114, unsigned char c0,
++ unsigned char c1)
++{
++ struct snd_ice1712 *ice = ak4114->change_callback_private;
++ int rate;
++ if (ice->is_spdif_master(ice) && c1) {
++ /* only for SPDIF master mode, rate was changed */
++ rate = snd_ak4114_external_rate(ak4114);
++ /* printk(KERN_DEBUG "ak4114 - input rate changed to %d\n",
++ rate); */
++ juli_akm_set_rate_val(ice->akm, rate);
++ }
++}
++
+ static int __devinit juli_init(struct snd_ice1712 *ice)
+ {
+ static const unsigned char ak4114_init_vals[] = {
+@@ -187,6 +597,11 @@ static int __devinit juli_init(struct snd_ice1712 *ice)
+ ice, &spec->ak4114);
+ if (err < 0)
+ return err;
++ /* callback for codecs rate setting */
++ spec->ak4114->change_callback = juli_ak4114_change;
++ spec->ak4114->change_callback_private = ice;
++ /* AK4114 in Juli can detect external rate correctly */
++ spec->ak4114->check_flags = 0;
+
+ #if 0
+ /* it seems that the analog doughter board detection does not work
+@@ -210,6 +625,15 @@ static int __devinit juli_init(struct snd_ice1712 *ice)
+ return err;
+ }
+
++ /* juli is clocked by Xilinx array */
++ ice->hw_rates = &juli_rates_info;
++ ice->is_spdif_master = juli_is_spdif_master;
++ ice->get_rate = juli_get_rate;
++ ice->set_rate = juli_set_rate;
++ ice->set_mclk = juli_set_mclk;
++ ice->set_spdif_clock = juli_set_spdif_clock;
++
++ ice->spdif.ops.open = juli_spdif_in_open;
+ return 0;
+ }
+
+@@ -220,18 +644,20 @@ static int __devinit juli_init(struct snd_ice1712 *ice)
+ */
+
+ static unsigned char juli_eeprom[] __devinitdata = {
+- [ICE_EEP2_SYSCONF] = 0x20, /* clock 512, mpu401, 1xADC, 1xDACs */
++ [ICE_EEP2_SYSCONF] = 0x2b, /* clock 512, mpu401, 1xADC, 1xDACs,
++ SPDIF in */
+ [ICE_EEP2_ACLINK] = 0x80, /* I2S */
+ [ICE_EEP2_I2S] = 0xf8, /* vol, 96k, 24bit, 192k */
+ [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
+- [ICE_EEP2_GPIO_DIR] = 0x9f,
++ [ICE_EEP2_GPIO_DIR] = 0x9f, /* 5, 6:inputs; 7, 4-0 outputs*/
+ [ICE_EEP2_GPIO_DIR1] = 0xff,
+ [ICE_EEP2_GPIO_DIR2] = 0x7f,
+- [ICE_EEP2_GPIO_MASK] = 0x9f,
+- [ICE_EEP2_GPIO_MASK1] = 0xff,
++ [ICE_EEP2_GPIO_MASK] = 0x60, /* 5, 6: locked; 7, 4-0 writable */
++ [ICE_EEP2_GPIO_MASK1] = 0x00, /* 0-7 writable */
+ [ICE_EEP2_GPIO_MASK2] = 0x7f,
+- [ICE_EEP2_GPIO_STATE] = 0x16, /* internal clock, multiple 1x, 48kHz */
+- [ICE_EEP2_GPIO_STATE1] = 0x80, /* mute */
++ [ICE_EEP2_GPIO_STATE] = GPIO_FREQ_48KHZ | GPIO_MULTI_1X |
++ GPIO_INTERNAL_CLOCK, /* internal clock, multiple 1x, 48kHz*/
++ [ICE_EEP2_GPIO_STATE1] = 0x00, /* unmuted */
+ [ICE_EEP2_GPIO_STATE2] = 0x00,
+ };
+
+diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c
+index 4945c81..203cdc1 100644
+--- a/sound/pci/ice1712/pontis.c
++++ b/sound/pci/ice1712/pontis.c
+@@ -246,7 +246,7 @@ static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val
+ wm_put(ice, WM_ADC_MUX, nval);
+ }
+ mutex_unlock(&ice->gpio_mutex);
+- return 0;
++ return change;
+ }
+
+ /*
+@@ -450,7 +450,7 @@ static int cs_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu
+ change = 1;
+ }
+ mutex_unlock(&ice->gpio_mutex);
+- return 0;
++ return change;
+ }
+
+
+diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c
+index 48cf40a..48d3679 100644
+--- a/sound/pci/ice1712/prodigy192.c
++++ b/sound/pci/ice1712/prodigy192.c
+@@ -319,12 +319,11 @@ static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
+ /*
+ * Handler for setting correct codec rate - called when rate change is detected
+ */
+-static void stac9460_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
++static void stac9460_set_rate_val(struct snd_ice1712 *ice, unsigned int rate)
+ {
+ unsigned char old, new;
+ int idx;
+ unsigned char changed[7];
+- struct snd_ice1712 *ice = ak->private_data[0];
+ struct prodigy192_spec *spec = ice->spec;
+
+ if (rate == 0) /* no hint - S/PDIF input is master, simply return */
+@@ -357,16 +356,6 @@ static void stac9460_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
+ mutex_unlock(&spec->mute_mutex);
+ }
+
+-/* using akm infrastructure for setting rate of the codec */
+-static struct snd_akm4xxx akmlike_stac9460 __devinitdata = {
+- .type = NON_AKM, /* special value */
+- .num_adcs = 6, /* not used in any way, just for completeness */
+- .num_dacs = 2,
+- .ops = {
+- .set_rate_val = stac9460_set_rate_val
+- }
+-};
+-
+
+ static const DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0);
+ static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0);
+@@ -642,12 +631,19 @@ static int prodigy192_ak4114_init(struct snd_ice1712 *ice)
+ 0x41, 0x02, 0x2c, 0x00, 0x00
+ };
+ struct prodigy192_spec *spec = ice->spec;
++ int err;
+
+- return snd_ak4114_create(ice->card,
++ err = snd_ak4114_create(ice->card,
+ prodigy192_ak4114_read,
+ prodigy192_ak4114_write,
+ ak4114_init_vals, ak4114_init_txcsb,
+ ice, &spec->ak4114);
++ if (err < 0)
++ return err;
++ /* AK4114 in Prodigy192 cannot detect external rate correctly.
++ * No reason to stop capture stream due to incorrect checks */
++ spec->ak4114->check_flags = AK4114_CHECK_NO_RATE;
++ return 0;
+ }
+
+ static void stac9460_proc_regs_read(struct snd_info_entry *entry,
+@@ -743,7 +739,6 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice)
+ };
+ const unsigned short *p;
+ int err = 0;
+- struct snd_akm4xxx *ak;
+ struct prodigy192_spec *spec;
+
+ /* prodigy 192 */
+@@ -761,15 +756,7 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice)
+ p = stac_inits_prodigy;
+ for (; *p != (unsigned short)-1; p += 2)
+ stac9460_put(ice, p[0], p[1]);
+- /* reusing the akm codecs infrastructure,
+- * for setting rate on stac9460 */
+- ak = ice->akm = kmalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
+- if (!ak)
+- return -ENOMEM;
+- ice->akm_codecs = 1;
+- err = snd_ice1712_akm4xxx_init(ak, &akmlike_stac9460, NULL, ice);
+- if (err < 0)
+- return err;
++ ice->gpio.set_pro_rate = stac9460_set_rate_val;
+
+ /* MI/ODI/O add on card with AK4114 */
+ if (prodigy192_miodio_exists(ice)) {
+@@ -825,10 +812,6 @@ struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] __devinitdata = {
+ .build_controls = prodigy192_add_controls,
+ .eeprom_size = sizeof(prodigy71_eeprom),
+ .eeprom_data = prodigy71_eeprom,
+- /* the current MPU401 code loops infinitely
+- * when opening midi device
+- */
+- .no_mpu401 = 1,
+ },
+ { } /* terminator */
+ };
+diff --git a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c
+index 301bf92..4d26314 100644
+--- a/sound/pci/ice1712/revo.c
++++ b/sound/pci/ice1712/revo.c
+@@ -322,17 +322,23 @@ static struct snd_pt2258 ptc_revo51_volume;
+ static void ap192_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
+ {
+ struct snd_ice1712 *ice = ak->private_data[0];
++ int dfs;
+
+ revo_set_rate_val(ak, rate);
+
+-#if 1 /* FIXME: do we need this procedure? */
+- /* reset DFS pin of AK5385A for ADC, too */
+- /* DFS0 (pin 18) -- GPIO10 pin 77 */
+- snd_ice1712_save_gpio_status(ice);
+- snd_ice1712_gpio_write_bits(ice, 1 << 10,
+- rate > 48000 ? (1 << 10) : 0);
+- snd_ice1712_restore_gpio_status(ice);
+-#endif
++ /* reset CKS */
++ snd_ice1712_gpio_write_bits(ice, 1 << 8, rate > 96000 ? 1 << 8 : 0);
++ /* reset DFS pins of AK5385A for ADC, too */
++ if (rate > 96000)
++ dfs = 2;
++ else if (rate > 48000)
++ dfs = 1;
++ else
++ dfs = 0;
++ snd_ice1712_gpio_write_bits(ice, 3 << 9, dfs << 9);
++ /* reset ADC */
++ snd_ice1712_gpio_write_bits(ice, 1 << 11, 0);
++ snd_ice1712_gpio_write_bits(ice, 1 << 11, 1 << 11);
+ }
+
+ static const struct snd_akm4xxx_dac_channel ap192_dac[] = {
+@@ -353,28 +359,20 @@ static struct snd_ak4xxx_private akm_ap192_priv __devinitdata = {
+ .cif = 0,
+ .data_mask = VT1724_REVO_CDOUT,
+ .clk_mask = VT1724_REVO_CCLK,
+- .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS3,
+- .cs_addr = VT1724_REVO_CS3,
+- .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS3,
++ .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1,
++ .cs_addr = VT1724_REVO_CS1,
++ .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1,
+ .add_flags = VT1724_REVO_CCLK, /* high at init */
+ .mask_flags = 0,
+ };
+
+-#if 0
+-/* FIXME: ak4114 makes the sound much lower due to some confliction,
+- * so let's disable it right now...
+- */
+-#define BUILD_AK4114_AP192
+-#endif
+-
+-#ifdef BUILD_AK4114_AP192
+ /* AK4114 support on Audiophile 192 */
+ /* CDTO (pin 32) -- GPIO2 pin 52
+ * CDTI (pin 33) -- GPIO3 pin 53 (shared with AK4358)
+ * CCLK (pin 34) -- GPIO1 pin 51 (shared with AK4358)
+ * CSN (pin 35) -- GPIO7 pin 59
+ */
+-#define AK4114_ADDR 0x00
++#define AK4114_ADDR 0x02
+
+ static void write_data(struct snd_ice1712 *ice, unsigned int gpio,
+ unsigned int data, int idx)
+@@ -428,7 +426,7 @@ static unsigned int ap192_4wire_start(struct snd_ice1712 *ice)
+ tmp = snd_ice1712_gpio_read(ice);
+ tmp |= VT1724_REVO_CCLK; /* high at init */
+ tmp |= VT1724_REVO_CS0;
+- tmp &= ~VT1724_REVO_CS3;
++ tmp &= ~VT1724_REVO_CS1;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(1);
+ return tmp;
+@@ -436,7 +434,7 @@ static unsigned int ap192_4wire_start(struct snd_ice1712 *ice)
+
+ static void ap192_4wire_finish(struct snd_ice1712 *ice, unsigned int tmp)
+ {
+- tmp |= VT1724_REVO_CS3;
++ tmp |= VT1724_REVO_CS1;
+ tmp |= VT1724_REVO_CS0;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(1);
+@@ -485,13 +483,17 @@ static int __devinit ap192_ak4114_init(struct snd_ice1712 *ice)
+ struct ak4114 *ak;
+ int err;
+
+- return snd_ak4114_create(ice->card,
++ err = snd_ak4114_create(ice->card,
+ ap192_ak4114_read,
+ ap192_ak4114_write,
+ ak4114_init_vals, ak4114_init_txcsb,
+ ice, &ak);
++ /* AK4114 in Revo cannot detect external rate correctly.
++ * No reason to stop capture stream due to incorrect checks */
++ ak->check_flags = AK4114_CHECK_NO_RATE;
++
++ return 0; /* error ignored; it's no fatal error */
+ }
+-#endif /* BUILD_AK4114_AP192 */
+
+ static int __devinit revo_init(struct snd_ice1712 *ice)
+ {
+@@ -557,6 +559,9 @@ static int __devinit revo_init(struct snd_ice1712 *ice)
+ if (err < 0)
+ return err;
+
++ /* unmute all codecs */
++ snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE,
++ VT1724_REVO_MUTE);
+ break;
+ }
+
+@@ -588,11 +593,9 @@ static int __devinit revo_add_controls(struct snd_ice1712 *ice)
+ err = snd_ice1712_akm4xxx_build_controls(ice);
+ if (err < 0)
+ return err;
+-#ifdef BUILD_AK4114_AP192
+ err = ap192_ak4114_init(ice);
+ if (err < 0)
+ return err;
+-#endif
+ break;
+ }
+ return 0;
+diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
+index c52abd0..048d99e 100644
+--- a/sound/pci/intel8x0.c
++++ b/sound/pci/intel8x0.c
+@@ -155,7 +155,8 @@ DEFINE_REGSET(SP, 0x60); /* SPDIF out */
+ #define ICH_PCM_SPDIF_69 0x80000000 /* s/pdif pcm on slots 6&9 */
+ #define ICH_PCM_SPDIF_1011 0xc0000000 /* s/pdif pcm on slots 10&11 */
+ #define ICH_PCM_20BIT 0x00400000 /* 20-bit samples (ICH4) */
+-#define ICH_PCM_246_MASK 0x00300000 /* 6 channels (not all chips) */
++#define ICH_PCM_246_MASK 0x00300000 /* chan mask (not all chips) */
++#define ICH_PCM_8 0x00300000 /* 8 channels (not all chips) */
+ #define ICH_PCM_6 0x00200000 /* 6 channels (not all chips) */
+ #define ICH_PCM_4 0x00100000 /* 4 channels (not all chips) */
+ #define ICH_PCM_2 0x00000000 /* 2 channels (stereo) */
+@@ -382,6 +383,7 @@ struct intel8x0 {
+
+ unsigned multi4: 1,
+ multi6: 1,
++ multi8 :1,
+ dra: 1,
+ smp20bit: 1;
+ unsigned in_ac97_init: 1,
+@@ -997,6 +999,8 @@ static void snd_intel8x0_setup_pcm_out(struct intel8x0 *chip,
+ cnt |= ICH_PCM_4;
+ else if (runtime->channels == 6)
+ cnt |= ICH_PCM_6;
++ else if (runtime->channels == 8)
++ cnt |= ICH_PCM_8;
+ if (chip->device_type == DEVICE_NFORCE) {
+ /* reset to 2ch once to keep the 6 channel data in alignment,
+ * to start from Front Left always
+@@ -1106,6 +1110,16 @@ static struct snd_pcm_hw_constraint_list hw_constraints_channels6 = {
+ .mask = 0,
+ };
+
++static unsigned int channels8[] = {
++ 2, 4, 6, 8,
++};
++
++static struct snd_pcm_hw_constraint_list hw_constraints_channels8 = {
++ .count = ARRAY_SIZE(channels8),
++ .list = channels8,
++ .mask = 0,
++};
++
+ static int snd_intel8x0_pcm_open(struct snd_pcm_substream *substream, struct ichdev *ichdev)
+ {
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
+@@ -1136,7 +1150,12 @@ static int snd_intel8x0_playback_open(struct snd_pcm_substream *substream)
+ if (err < 0)
+ return err;
+
+- if (chip->multi6) {
++ if (chip->multi8) {
++ runtime->hw.channels_max = 8;
++ snd_pcm_hw_constraint_list(runtime, 0,
++ SNDRV_PCM_HW_PARAM_CHANNELS,
++ &hw_constraints_channels8);
++ } else if (chip->multi6) {
+ runtime->hw.channels_max = 6;
+ snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+ &hw_constraints_channels6);
+@@ -2203,8 +2222,11 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
+ }
+ if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_PCM_SLEFT)) {
+ chip->multi4 = 1;
+- if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_LFE))
++ if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_LFE)) {
+ chip->multi6 = 1;
++ if (chip->ac97[0]->flags & AC97_HAS_8CH)
++ chip->multi8 = 1;
++ }
+ }
+ if (pbus->pcms[0].r[1].rslots[0]) {
+ chip->dra = 1;
+@@ -2446,7 +2468,7 @@ static int snd_intel8x0_free(struct intel8x0 *chip)
+ pci_write_config_dword(chip->pci, 0x4c, val);
+ }
+ /* --- */
+- synchronize_irq(chip->irq);
++
+ __hw_end:
+ if (chip->irq >= 0)
+ free_irq(chip->irq, chip);
+@@ -2495,7 +2517,6 @@ static int intel8x0_suspend(struct pci_dev *pci, pm_message_t state)
+ chip->sdm_saved = igetbyte(chip, ICHREG(SDM));
+
+ if (chip->irq >= 0) {
+- synchronize_irq(chip->irq);
+ free_irq(chip->irq, chip);
+ chip->irq = -1;
+ }
+@@ -2648,7 +2669,7 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip)
+ t = stop_time.tv_sec - start_time.tv_sec;
+ t *= 1000000;
+ t += stop_time.tv_usec - start_time.tv_usec;
+- printk(KERN_INFO "%s: measured %lu usecs\n", __FUNCTION__, t);
++ printk(KERN_INFO "%s: measured %lu usecs\n", __func__, t);
+ if (t == 0) {
+ snd_printk(KERN_ERR "?? calculation error..\n");
+ return;
+diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
+index cadda8d..faf674e 100644
+--- a/sound/pci/intel8x0m.c
++++ b/sound/pci/intel8x0m.c
+@@ -985,17 +985,15 @@ static int snd_intel8x0_free(struct intel8x0m *chip)
+ /* reset channels */
+ for (i = 0; i < chip->bdbars_count; i++)
+ iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS);
+- /* --- */
+- synchronize_irq(chip->irq);
+- __hw_end:
++ __hw_end:
++ if (chip->irq >= 0)
++ free_irq(chip->irq, chip);
+ if (chip->bdbars.area)
+ snd_dma_free_pages(&chip->bdbars);
+ if (chip->addr)
+ pci_iounmap(chip->pci, chip->addr);
+ if (chip->bmaddr)
+ pci_iounmap(chip->pci, chip->bmaddr);
+- if (chip->irq >= 0)
+- free_irq(chip->irq, chip);
+ pci_release_regions(chip->pci);
+ pci_disable_device(chip->pci);
+ kfree(chip);
+@@ -1017,7 +1015,6 @@ static int intel8x0m_suspend(struct pci_dev *pci, pm_message_t state)
+ snd_pcm_suspend_all(chip->pcm[i]);
+ snd_ac97_suspend(chip->ac97);
+ if (chip->irq >= 0) {
+- synchronize_irq(chip->irq);
+ free_irq(chip->irq, chip);
+ chip->irq = -1;
+ }
+diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
+index 10c713d..f4c85b5 100644
+--- a/sound/pci/korg1212/korg1212.c
++++ b/sound/pci/korg1212/korg1212.c
+@@ -2102,7 +2102,6 @@ snd_korg1212_free(struct snd_korg1212 *korg1212)
+ snd_korg1212_TurnOffIdleMonitor(korg1212);
+
+ if (korg1212->irq >= 0) {
+- synchronize_irq(korg1212->irq);
+ snd_korg1212_DisableCardInterrupts(korg1212);
+ free_irq(korg1212->irq, korg1212);
+ korg1212->irq = -1;
+diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
+index 04fa0a6..a536c59 100644
+--- a/sound/pci/maestro3.c
++++ b/sound/pci/maestro3.c
+@@ -2068,7 +2068,7 @@ static int __devinit snd_m3_mixer(struct snd_m3 *chip)
+ {
+ struct snd_ac97_bus *pbus;
+ struct snd_ac97_template ac97;
+- struct snd_ctl_elem_id id;
++ struct snd_ctl_elem_id elem_id;
+ int err;
+ static struct snd_ac97_bus_ops ops = {
+ .write = snd_m3_ac97_write,
+@@ -2088,14 +2088,14 @@ static int __devinit snd_m3_mixer(struct snd_m3 *chip)
+ schedule_timeout_uninterruptible(msecs_to_jiffies(100));
+ snd_ac97_write(chip->ac97, AC97_PCM, 0);
+
+- memset(&id, 0, sizeof(id));
+- id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+- strcpy(id.name, "Master Playback Switch");
+- chip->master_switch = snd_ctl_find_id(chip->card, &id);
+- memset(&id, 0, sizeof(id));
+- id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+- strcpy(id.name, "Master Playback Volume");
+- chip->master_volume = snd_ctl_find_id(chip->card, &id);
++ memset(&elem_id, 0, sizeof(elem_id));
++ elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
++ strcpy(elem_id.name, "Master Playback Switch");
++ chip->master_switch = snd_ctl_find_id(chip->card, &elem_id);
++ memset(&elem_id, 0, sizeof(elem_id));
++ elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
++ strcpy(elem_id.name, "Master Playback Volume");
++ chip->master_volume = snd_ctl_find_id(chip->card, &elem_id);
+
+ return 0;
+ }
+@@ -2542,10 +2542,8 @@ static int snd_m3_free(struct snd_m3 *chip)
+ vfree(chip->suspend_mem);
+ #endif
+
+- if (chip->irq >= 0) {
+- synchronize_irq(chip->irq);
++ if (chip->irq >= 0)
+ free_irq(chip->irq, chip);
+- }
+
+ if (chip->iobase)
+ pci_release_regions(chip->pci);
+@@ -2569,7 +2567,7 @@ static int m3_suspend(struct pci_dev *pci, pm_message_t state)
+ {
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_m3 *chip = card->private_data;
+- int i, index;
++ int i, dsp_index;
+
+ if (chip->suspend_mem == NULL)
+ return 0;
+@@ -2583,12 +2581,12 @@ static int m3_suspend(struct pci_dev *pci, pm_message_t state)
+ snd_m3_assp_halt(chip);
+
+ /* save dsp image */
+- index = 0;
++ dsp_index = 0;
+ for (i = REV_B_CODE_MEMORY_BEGIN; i <= REV_B_CODE_MEMORY_END; i++)
+- chip->suspend_mem[index++] =
++ chip->suspend_mem[dsp_index++] =
+ snd_m3_assp_read(chip, MEMTYPE_INTERNAL_CODE, i);
+ for (i = REV_B_DATA_MEMORY_BEGIN ; i <= REV_B_DATA_MEMORY_END; i++)
+- chip->suspend_mem[index++] =
++ chip->suspend_mem[dsp_index++] =
+ snd_m3_assp_read(chip, MEMTYPE_INTERNAL_DATA, i);
+
+ pci_disable_device(pci);
+@@ -2601,7 +2599,7 @@ static int m3_resume(struct pci_dev *pci)
+ {
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_m3 *chip = card->private_data;
+- int i, index;
++ int i, dsp_index;
+
+ if (chip->suspend_mem == NULL)
+ return 0;
+@@ -2625,13 +2623,13 @@ static int m3_resume(struct pci_dev *pci)
+ snd_m3_ac97_reset(chip);
+
+ /* restore dsp image */
+- index = 0;
++ dsp_index = 0;
+ for (i = REV_B_CODE_MEMORY_BEGIN; i <= REV_B_CODE_MEMORY_END; i++)
+ snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, i,
+- chip->suspend_mem[index++]);
++ chip->suspend_mem[dsp_index++]);
+ for (i = REV_B_DATA_MEMORY_BEGIN ; i <= REV_B_DATA_MEMORY_END; i++)
+ snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, i,
+- chip->suspend_mem[index++]);
++ chip->suspend_mem[dsp_index++]);
+
+ /* tell the dma engine to restart itself */
+ snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,
+diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
+index 7ac654e..7efb838 100644
+--- a/sound/pci/nm256/nm256.c
++++ b/sound/pci/nm256/nm256.c
+@@ -1439,7 +1439,7 @@ static int snd_nm256_free(struct nm256 *chip)
+ snd_nm256_capture_stop(chip);
+
+ if (chip->irq >= 0)
+- synchronize_irq(chip->irq);
++ free_irq(chip->irq, chip);
+
+ if (chip->cport)
+ iounmap(chip->cport);
+@@ -1447,8 +1447,6 @@ static int snd_nm256_free(struct nm256 *chip)
+ iounmap(chip->buffer);
+ release_and_free_resource(chip->res_cport);
+ release_and_free_resource(chip->res_buffer);
+- if (chip->irq >= 0)
+- free_irq(chip->irq, chip);
+
+ pci_disable_device(chip->pci);
+ kfree(chip->ac97_regs);
+diff --git a/sound/pci/oxygen/cs4362a.h b/sound/pci/oxygen/cs4362a.h
+new file mode 100644
+index 0000000..6a4fedf
+--- /dev/null
++++ b/sound/pci/oxygen/cs4362a.h
+@@ -0,0 +1,69 @@
++/* register 01h */
++#define CS4362A_PDN 0x01
++#define CS4362A_DAC1_DIS 0x02
++#define CS4362A_DAC2_DIS 0x04
++#define CS4362A_DAC3_DIS 0x08
++#define CS4362A_MCLKDIV 0x20
++#define CS4362A_FREEZE 0x40
++#define CS4362A_CPEN 0x80
++/* register 02h */
++#define CS4362A_DIF_MASK 0x70
++#define CS4362A_DIF_LJUST 0x00
++#define CS4362A_DIF_I2S 0x10
++#define CS4362A_DIF_RJUST_16 0x20
++#define CS4362A_DIF_RJUST_24 0x30
++#define CS4362A_DIF_RJUST_20 0x40
++#define CS4362A_DIF_RJUST_18 0x50
++/* register 03h */
++#define CS4362A_MUTEC_MASK 0x03
++#define CS4362A_MUTEC_6 0x00
++#define CS4362A_MUTEC_1 0x01
++#define CS4362A_MUTEC_3 0x03
++#define CS4362A_AMUTE 0x04
++#define CS4362A_MUTEC_POL 0x08
++#define CS4362A_RMP_UP 0x10
++#define CS4362A_SNGLVOL 0x20
++#define CS4362A_ZERO_CROSS 0x40
++#define CS4362A_SOFT_RAMP 0x80
++/* register 04h */
++#define CS4362A_RMP_DN 0x01
++#define CS4362A_DEM_MASK 0x06
++#define CS4362A_DEM_NONE 0x00
++#define CS4362A_DEM_44100 0x02
++#define CS4362A_DEM_48000 0x04
++#define CS4362A_DEM_32000 0x06
++#define CS4362A_FILT_SEL 0x10
++/* register 05h */
++#define CS4362A_INV_A1 0x01
++#define CS4362A_INV_B1 0x02
++#define CS4362A_INV_A2 0x04
++#define CS4362A_INV_B2 0x08
++#define CS4362A_INV_A3 0x10
++#define CS4362A_INV_B3 0x20
++/* register 06h */
++#define CS4362A_FM_MASK 0x03
++#define CS4362A_FM_SINGLE 0x00
++#define CS4362A_FM_DOUBLE 0x01
++#define CS4362A_FM_QUAD 0x02
++#define CS4362A_FM_DSD 0x03
++#define CS4362A_ATAPI_MASK 0x7c
++#define CS4362A_ATAPI_B_MUTE 0x00
++#define CS4362A_ATAPI_B_R 0x04
++#define CS4362A_ATAPI_B_L 0x08
++#define CS4362A_ATAPI_B_LR 0x0c
++#define CS4362A_ATAPI_A_MUTE 0x00
++#define CS4362A_ATAPI_A_R 0x10
++#define CS4362A_ATAPI_A_L 0x20
++#define CS4362A_ATAPI_A_LR 0x30
++#define CS4362A_ATAPI_MIX_LR_VOL 0x40
++#define CS4362A_A_EQ_B 0x80
++/* register 07h */
++#define CS4362A_VOL_MASK 0x7f
++#define CS4362A_MUTE 0x80
++/* register 08h: like 07h */
++/* registers 09h..0Bh: like 06h..08h */
++/* registers 0Ch..0Eh: like 06h..08h */
++/* register 12h */
++#define CS4362A_REV_MASK 0x07
++#define CS4362A_PART_MASK 0xf8
++#define CS4362A_PART_CS4362A 0x50
+diff --git a/sound/pci/oxygen/cs4398.h b/sound/pci/oxygen/cs4398.h
+new file mode 100644
+index 0000000..5faf5ef
+--- /dev/null
++++ b/sound/pci/oxygen/cs4398.h
+@@ -0,0 +1,69 @@
++/* register 1 */
++#define CS4398_REV_MASK 0x07
++#define CS4398_PART_MASK 0xf8
++#define CS4398_PART_CS4398 0x70
++/* register 2 */
++#define CS4398_FM_MASK 0x03
++#define CS4398_FM_SINGLE 0x00
++#define CS4398_FM_DOUBLE 0x01
++#define CS4398_FM_QUAD 0x02
++#define CS4398_FM_DSD 0x03
++#define CS4398_DEM_MASK 0x0c
++#define CS4398_DEM_NONE 0x00
++#define CS4398_DEM_44100 0x04
++#define CS4398_DEM_48000 0x08
++#define CS4398_DEM_32000 0x0c
++#define CS4398_DIF_MASK 0x70
++#define CS4398_DIF_LJUST 0x00
++#define CS4398_DIF_I2S 0x10
++#define CS4398_DIF_RJUST_16 0x20
++#define CS4398_DIF_RJUST_24 0x30
++#define CS4398_DIF_RJUST_20 0x40
++#define CS4398_DIF_RJUST_18 0x50
++#define CS4398_DSD_SRC 0x80
++/* register 3 */
++#define CS4398_ATAPI_MASK 0x1f
++#define CS4398_ATAPI_B_MUTE 0x00
++#define CS4398_ATAPI_B_R 0x01
++#define CS4398_ATAPI_B_L 0x02
++#define CS4398_ATAPI_B_LR 0x03
++#define CS4398_ATAPI_A_MUTE 0x00
++#define CS4398_ATAPI_A_R 0x04
++#define CS4398_ATAPI_A_L 0x08
++#define CS4398_ATAPI_A_LR 0x0c
++#define CS4398_ATAPI_MIX_LR_VOL 0x10
++#define CS4398_INVERT_B 0x20
++#define CS4398_INVERT_A 0x40
++#define CS4398_VOL_B_EQ_A 0x80
++/* register 4 */
++#define CS4398_MUTEP_MASK 0x03
++#define CS4398_MUTEP_AUTO 0x00
++#define CS4398_MUTEP_LOW 0x02
++#define CS4398_MUTEP_HIGH 0x03
++#define CS4398_MUTE_B 0x08
++#define CS4398_MUTE_A 0x10
++#define CS4398_MUTEC_A_EQ_B 0x20
++#define CS4398_DAMUTE 0x40
++#define CS4398_PAMUTE 0x80
++/* register 5 */
++#define CS4398_VOL_A_MASK 0xff
++/* register 6 */
++#define CS4398_VOL_B_MASK 0xff
++/* register 7 */
++#define CS4398_DIR_DSD 0x01
++#define CS4398_FILT_SEL 0x04
++#define CS4398_RMP_DN 0x10
++#define CS4398_RMP_UP 0x20
++#define CS4398_ZERO_CROSS 0x40
++#define CS4398_SOFT_RAMP 0x80
++/* register 8 */
++#define CS4398_MCLKDIV3 0x08
++#define CS4398_MCLKDIV2 0x10
++#define CS4398_FREEZE 0x20
++#define CS4398_CPEN 0x40
++#define CS4398_PDN 0x80
++/* register 9 */
++#define CS4398_DSD_PM_EN 0x01
++#define CS4398_DSD_PM_MODE 0x02
++#define CS4398_INVALID_DSD 0x04
++#define CS4398_STATIC_DSD 0x08
+diff --git a/sound/pci/oxygen/hifier.c b/sound/pci/oxygen/hifier.c
+index 666f69a..090dd43 100644
+--- a/sound/pci/oxygen/hifier.c
++++ b/sound/pci/oxygen/hifier.c
+@@ -66,12 +66,12 @@ static void hifier_init(struct oxygen *chip)
+ {
+ struct hifier_data *data = chip->model_data;
+
+- data->ak4396_ctl2 = AK4396_DEM_OFF | AK4396_DFS_NORMAL;
++ data->ak4396_ctl2 = AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL;
+ ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN);
+ ak4396_write(chip, AK4396_CONTROL_2, data->ak4396_ctl2);
+ ak4396_write(chip, AK4396_CONTROL_3, AK4396_PCM);
+- ak4396_write(chip, AK4396_LCH_ATT, 0xff);
+- ak4396_write(chip, AK4396_RCH_ATT, 0xff);
++ ak4396_write(chip, AK4396_LCH_ATT, 0);
++ ak4396_write(chip, AK4396_RCH_ATT, 0);
+
+ snd_component_add(chip->card, "AK4396");
+ snd_component_add(chip->card, "CS5340");
+@@ -127,22 +127,8 @@ static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
+
+ static int hifier_control_filter(struct snd_kcontrol_new *template)
+ {
+- if (!strcmp(template->name, "Master Playback Volume")) {
+- template->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+- template->tlv.p = ak4396_db_scale;
+- } else if (!strcmp(template->name, "Stereo Upmixing")) {
++ if (!strcmp(template->name, "Stereo Upmixing"))
+ return 1; /* stereo only - we don't need upmixing */
+- } else if (!strcmp(template->name,
+- SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK)) ||
+- !strcmp(template->name,
+- SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT))) {
+- return 1; /* no digital input */
+- }
+- return 0;
+-}
+-
+-static int hifier_mixer_init(struct oxygen *chip)
+-{
+ return 0;
+ }
+
+@@ -153,18 +139,20 @@ static const struct oxygen_model model_hifier = {
+ .owner = THIS_MODULE,
+ .init = hifier_init,
+ .control_filter = hifier_control_filter,
+- .mixer_init = hifier_mixer_init,
+ .cleanup = hifier_cleanup,
+ .set_dac_params = set_ak4396_params,
+ .set_adc_params = set_cs5340_params,
+ .update_dac_volume = update_ak4396_volume,
+ .update_dac_mute = update_ak4396_mute,
++ .dac_tlv = ak4396_db_scale,
+ .model_data_size = sizeof(struct hifier_data),
++ .pcm_dev_cfg = PLAYBACK_0_TO_I2S |
++ PLAYBACK_1_TO_SPDIF |
++ CAPTURE_0_FROM_I2S_1,
+ .dac_channels = 2,
+- .used_channels = OXYGEN_CHANNEL_A |
+- OXYGEN_CHANNEL_SPDIF |
+- OXYGEN_CHANNEL_MULTICH,
+- .function_flags = 0,
++ .dac_volume_min = 0,
++ .dac_volume_max = 255,
++ .function_flags = OXYGEN_FUNCTION_SPI,
+ .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+ .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+ };
+@@ -181,7 +169,7 @@ static int __devinit hifier_probe(struct pci_dev *pci,
+ ++dev;
+ return -ENOENT;
+ }
+- err = oxygen_pci_probe(pci, index[dev], id[dev], 0, &model_hifier);
++ err = oxygen_pci_probe(pci, index[dev], id[dev], &model_hifier);
+ if (err >= 0)
+ ++dev;
+ return err;
+diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
+index 9a9941b..63f185c 100644
+--- a/sound/pci/oxygen/oxygen.c
++++ b/sound/pci/oxygen/oxygen.c
+@@ -39,7 +39,7 @@
+ #include <sound/tlv.h>
+ #include "oxygen.h"
+ #include "ak4396.h"
+-#include "cm9780.h"
++#include "wm8785.h"
+
+ MODULE_AUTHOR("Clemens Ladisch <clemens at ladisch.de>");
+ MODULE_DESCRIPTION("C-Media CMI8788 driver");
+@@ -78,49 +78,6 @@ MODULE_DEVICE_TABLE(pci, oxygen_ids);
+ #define GPIO_AK5385_DFS_DOUBLE 0x0001
+ #define GPIO_AK5385_DFS_QUAD 0x0002
+
+-#define GPIO_LINE_MUTE CM9780_GPO0
+-
+-#define WM8785_R0 0
+-#define WM8785_R1 1
+-#define WM8785_R2 2
+-#define WM8785_R7 7
+-
+-/* R0 */
+-#define WM8785_MCR_MASK 0x007
+-#define WM8785_MCR_SLAVE 0x000
+-#define WM8785_MCR_MASTER_128 0x001
+-#define WM8785_MCR_MASTER_192 0x002
+-#define WM8785_MCR_MASTER_256 0x003
+-#define WM8785_MCR_MASTER_384 0x004
+-#define WM8785_MCR_MASTER_512 0x005
+-#define WM8785_MCR_MASTER_768 0x006
+-#define WM8785_OSR_MASK 0x018
+-#define WM8785_OSR_SINGLE 0x000
+-#define WM8785_OSR_DOUBLE 0x008
+-#define WM8785_OSR_QUAD 0x010
+-#define WM8785_FORMAT_MASK 0x060
+-#define WM8785_FORMAT_RJUST 0x000
+-#define WM8785_FORMAT_LJUST 0x020
+-#define WM8785_FORMAT_I2S 0x040
+-#define WM8785_FORMAT_DSP 0x060
+-/* R1 */
+-#define WM8785_WL_MASK 0x003
+-#define WM8785_WL_16 0x000
+-#define WM8785_WL_20 0x001
+-#define WM8785_WL_24 0x002
+-#define WM8785_WL_32 0x003
+-#define WM8785_LRP 0x004
+-#define WM8785_BCLKINV 0x008
+-#define WM8785_LRSWAP 0x010
+-#define WM8785_DEVNO_MASK 0x0e0
+-/* R2 */
+-#define WM8785_HPFR 0x001
+-#define WM8785_HPFL 0x002
+-#define WM8785_SDODIS 0x004
+-#define WM8785_PWRDNR 0x008
+-#define WM8785_PWRDNL 0x010
+-#define WM8785_TDM_MASK 0x1c0
+-
+ struct generic_data {
+ u8 ak4396_ctl2;
+ };
+@@ -155,7 +112,7 @@ static void ak4396_init(struct oxygen *chip)
+ struct generic_data *data = chip->model_data;
+ unsigned int i;
+
+- data->ak4396_ctl2 = AK4396_DEM_OFF | AK4396_DFS_NORMAL;
++ data->ak4396_ctl2 = AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL;
+ for (i = 0; i < 4; ++i) {
+ ak4396_write(chip, i,
+ AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN);
+@@ -163,8 +120,8 @@ static void ak4396_init(struct oxygen *chip)
+ AK4396_CONTROL_2, data->ak4396_ctl2);
+ ak4396_write(chip, i,
+ AK4396_CONTROL_3, AK4396_PCM);
+- ak4396_write(chip, i, AK4396_LCH_ATT, 0xff);
+- ak4396_write(chip, i, AK4396_RCH_ATT, 0xff);
++ ak4396_write(chip, i, AK4396_LCH_ATT, 0);
++ ak4396_write(chip, i, AK4396_RCH_ATT, 0);
+ }
+ snd_component_add(chip->card, "AK4396");
+ }
+@@ -185,23 +142,16 @@ static void wm8785_init(struct oxygen *chip)
+ snd_component_add(chip->card, "WM8785");
+ }
+
+-static void cmi9780_init(struct oxygen *chip)
+-{
+- oxygen_ac97_clear_bits(chip, 0, CM9780_GPIO_STATUS, GPIO_LINE_MUTE);
+-}
+-
+ static void generic_init(struct oxygen *chip)
+ {
+ ak4396_init(chip);
+ wm8785_init(chip);
+- cmi9780_init(chip);
+ }
+
+ static void meridian_init(struct oxygen *chip)
+ {
+ ak4396_init(chip);
+ ak5385_init(chip);
+- cmi9780_init(chip);
+ }
+
+ static void generic_cleanup(struct oxygen *chip)
+@@ -297,59 +247,32 @@ static void set_ak5385_params(struct oxygen *chip,
+ value, GPIO_AK5385_DFS_MASK);
+ }
+
+-static void cmi9780_switch_hook(struct oxygen *chip, unsigned int codec,
+- unsigned int reg, int mute)
+-{
+- if (codec != 0)
+- return;
+- switch (reg) {
+- case AC97_LINE:
+- oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS,
+- mute ? GPIO_LINE_MUTE : 0,
+- GPIO_LINE_MUTE);
+- break;
+- case AC97_MIC:
+- case AC97_CD:
+- case AC97_AUX:
+- if (!mute)
+- oxygen_ac97_set_bits(chip, 0, CM9780_GPIO_STATUS,
+- GPIO_LINE_MUTE);
+- break;
+- }
+-}
+-
+ static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
+
+-static int ak4396_control_filter(struct snd_kcontrol_new *template)
+-{
+- if (!strcmp(template->name, "Master Playback Volume")) {
+- template->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+- template->tlv.p = ak4396_db_scale;
+- }
+- return 0;
+-}
+-
+ static const struct oxygen_model model_generic = {
+ .shortname = "C-Media CMI8788",
+ .longname = "C-Media Oxygen HD Audio",
+ .chip = "CMI8788",
+ .owner = THIS_MODULE,
+ .init = generic_init,
+- .control_filter = ak4396_control_filter,
+ .cleanup = generic_cleanup,
+ .set_dac_params = set_ak4396_params,
+ .set_adc_params = set_wm8785_params,
+ .update_dac_volume = update_ak4396_volume,
+ .update_dac_mute = update_ak4396_mute,
+- .ac97_switch_hook = cmi9780_switch_hook,
++ .dac_tlv = ak4396_db_scale,
+ .model_data_size = sizeof(struct generic_data),
++ .pcm_dev_cfg = PLAYBACK_0_TO_I2S |
++ PLAYBACK_1_TO_SPDIF |
++ PLAYBACK_2_TO_AC97_1 |
++ CAPTURE_0_FROM_I2S_1 |
++ CAPTURE_1_FROM_SPDIF |
++ CAPTURE_2_FROM_AC97_1,
+ .dac_channels = 8,
+- .used_channels = OXYGEN_CHANNEL_A |
+- OXYGEN_CHANNEL_C |
+- OXYGEN_CHANNEL_SPDIF |
+- OXYGEN_CHANNEL_MULTICH |
+- OXYGEN_CHANNEL_AC97,
+- .function_flags = OXYGEN_FUNCTION_ENABLE_SPI_4_5,
++ .dac_volume_min = 0,
++ .dac_volume_max = 255,
++ .function_flags = OXYGEN_FUNCTION_SPI |
++ OXYGEN_FUNCTION_ENABLE_SPI_4_5,
+ .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+ .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+ };
+@@ -359,21 +282,25 @@ static const struct oxygen_model model_meridian = {
+ .chip = "CMI8788",
+ .owner = THIS_MODULE,
+ .init = meridian_init,
+- .control_filter = ak4396_control_filter,
+ .cleanup = generic_cleanup,
+ .set_dac_params = set_ak4396_params,
+ .set_adc_params = set_ak5385_params,
+ .update_dac_volume = update_ak4396_volume,
+ .update_dac_mute = update_ak4396_mute,
+- .ac97_switch_hook = cmi9780_switch_hook,
++ .dac_tlv = ak4396_db_scale,
+ .model_data_size = sizeof(struct generic_data),
++ .pcm_dev_cfg = PLAYBACK_0_TO_I2S |
++ PLAYBACK_1_TO_SPDIF |
++ PLAYBACK_2_TO_AC97_1 |
++ CAPTURE_0_FROM_I2S_2 |
++ CAPTURE_1_FROM_SPDIF |
++ CAPTURE_2_FROM_AC97_1,
+ .dac_channels = 8,
+- .used_channels = OXYGEN_CHANNEL_B |
+- OXYGEN_CHANNEL_C |
+- OXYGEN_CHANNEL_SPDIF |
+- OXYGEN_CHANNEL_MULTICH |
+- OXYGEN_CHANNEL_AC97,
+- .function_flags = OXYGEN_FUNCTION_ENABLE_SPI_4_5,
++ .dac_volume_min = 0,
++ .dac_volume_max = 255,
++ .misc_flags = OXYGEN_MISC_MIDI,
++ .function_flags = OXYGEN_FUNCTION_SPI |
++ OXYGEN_FUNCTION_ENABLE_SPI_4_5,
+ .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+ .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+ };
+@@ -392,7 +319,7 @@ static int __devinit generic_oxygen_probe(struct pci_dev *pci,
+ return -ENOENT;
+ }
+ is_meridian = pci_id->driver_data;
+- err = oxygen_pci_probe(pci, index[dev], id[dev], is_meridian,
++ err = oxygen_pci_probe(pci, index[dev], id[dev],
+ is_meridian ? &model_meridian : &model_generic);
+ if (err >= 0)
+ ++dev;
+diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h
+index ad50fb8..a71c6e0 100644
+--- a/sound/pci/oxygen/oxygen.h
++++ b/sound/pci/oxygen/oxygen.h
+@@ -16,6 +16,16 @@
+ #define PCM_AC97 5
+ #define PCM_COUNT 6
+
++/* model-specific configuration of outputs/inputs */
++#define PLAYBACK_0_TO_I2S 0x001
++#define PLAYBACK_1_TO_SPDIF 0x004
++#define PLAYBACK_2_TO_AC97_1 0x008
++#define CAPTURE_0_FROM_I2S_1 0x010
++#define CAPTURE_0_FROM_I2S_2 0x020
++#define CAPTURE_1_FROM_SPDIF 0x080
++#define CAPTURE_2_FROM_I2S_2 0x100
++#define CAPTURE_2_FROM_AC97_1 0x200
++
+ enum {
+ CONTROL_SPDIF_PCM,
+ CONTROL_SPDIF_INPUT_BITS,
+@@ -87,12 +97,16 @@ struct oxygen_model {
+ struct snd_pcm_hw_params *params);
+ void (*update_dac_volume)(struct oxygen *chip);
+ void (*update_dac_mute)(struct oxygen *chip);
+- void (*ac97_switch_hook)(struct oxygen *chip, unsigned int codec,
+- unsigned int reg, int mute);
+ void (*gpio_changed)(struct oxygen *chip);
++ void (*ac97_switch)(struct oxygen *chip,
++ unsigned int reg, unsigned int mute);
++ const unsigned int *dac_tlv;
+ size_t model_data_size;
++ unsigned int pcm_dev_cfg;
+ u8 dac_channels;
+- u8 used_channels;
++ u8 dac_volume_min;
++ u8 dac_volume_max;
++ u8 misc_flags;
+ u8 function_flags;
+ u16 dac_i2s_format;
+ u16 adc_i2s_format;
+@@ -100,7 +114,7 @@ struct oxygen_model {
+
+ /* oxygen_lib.c */
+
+-int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, int midi,
++int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
+ const struct oxygen_model *model);
+ void oxygen_pci_remove(struct pci_dev *pci);
+
+@@ -137,6 +151,7 @@ void oxygen_write_ac97_masked(struct oxygen *chip, unsigned int codec,
+ unsigned int index, u16 data, u16 mask);
+
+ void oxygen_write_spi(struct oxygen *chip, u8 control, unsigned int data);
++void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data);
+
+ static inline void oxygen_set_bits8(struct oxygen *chip,
+ unsigned int reg, u8 value)
+diff --git a/sound/pci/oxygen/oxygen_io.c b/sound/pci/oxygen/oxygen_io.c
+index 74e23ef..5569606 100644
+--- a/sound/pci/oxygen/oxygen_io.c
++++ b/sound/pci/oxygen/oxygen_io.c
+@@ -190,12 +190,31 @@ void oxygen_write_spi(struct oxygen *chip, u8 control, unsigned int data)
+ --count;
+ }
+
+- spin_lock_irq(&chip->reg_lock);
+ oxygen_write8(chip, OXYGEN_SPI_DATA1, data);
+ oxygen_write8(chip, OXYGEN_SPI_DATA2, data >> 8);
+ if (control & OXYGEN_SPI_DATA_LENGTH_3)
+ oxygen_write8(chip, OXYGEN_SPI_DATA3, data >> 16);
+ oxygen_write8(chip, OXYGEN_SPI_CONTROL, control);
+- spin_unlock_irq(&chip->reg_lock);
+ }
+ EXPORT_SYMBOL(oxygen_write_spi);
++
++void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data)
++{
++ unsigned long timeout;
++
++ /* should not need more than about 300 us */
++ timeout = jiffies + msecs_to_jiffies(1);
++ do {
++ if (!(oxygen_read16(chip, OXYGEN_2WIRE_BUS_STATUS)
++ & OXYGEN_2WIRE_BUSY))
++ break;
++ udelay(1);
++ cond_resched();
++ } while (time_after_eq(timeout, jiffies));
++
++ oxygen_write8(chip, OXYGEN_2WIRE_MAP, map);
++ oxygen_write8(chip, OXYGEN_2WIRE_DATA, data);
++ oxygen_write8(chip, OXYGEN_2WIRE_CONTROL,
++ device | OXYGEN_2WIRE_DIR_WRITE);
++}
++EXPORT_SYMBOL(oxygen_write_i2c);
+diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
+index 78c2115..897697d 100644
+--- a/sound/pci/oxygen/oxygen_lib.c
++++ b/sound/pci/oxygen/oxygen_lib.c
+@@ -221,7 +221,8 @@ static void oxygen_init(struct oxygen *chip)
+
+ chip->dac_routing = 1;
+ for (i = 0; i < 8; ++i)
+- chip->dac_volume[i] = 0xff;
++ chip->dac_volume[i] = chip->model->dac_volume_min;
++ chip->dac_mute = 1;
+ chip->spdif_playback_enable = 1;
+ chip->spdif_bits = OXYGEN_SPDIF_C | OXYGEN_SPDIF_ORIGINAL |
+ (IEC958_AES1_CON_PCM_CODER << OXYGEN_SPDIF_CATEGORY_SHIFT);
+@@ -240,12 +241,12 @@ static void oxygen_init(struct oxygen *chip)
+ chip->has_ac97_0 = (i & OXYGEN_AC97_CODEC_0) != 0;
+ chip->has_ac97_1 = (i & OXYGEN_AC97_CODEC_1) != 0;
+
+- oxygen_set_bits8(chip, OXYGEN_FUNCTION,
+- OXYGEN_FUNCTION_RESET_CODEC |
+- chip->model->function_flags);
+ oxygen_write8_masked(chip, OXYGEN_FUNCTION,
+- OXYGEN_FUNCTION_SPI,
+- OXYGEN_FUNCTION_2WIRE_SPI_MASK);
++ OXYGEN_FUNCTION_RESET_CODEC |
++ chip->model->function_flags,
++ OXYGEN_FUNCTION_RESET_CODEC |
++ OXYGEN_FUNCTION_2WIRE_SPI_MASK |
++ OXYGEN_FUNCTION_ENABLE_SPI_4_5);
+ oxygen_write8(chip, OXYGEN_DMA_STATUS, 0);
+ oxygen_write8(chip, OXYGEN_DMA_PAUSE, 0);
+ oxygen_write8(chip, OXYGEN_PLAY_CHANNELS,
+@@ -253,11 +254,13 @@ static void oxygen_init(struct oxygen *chip)
+ OXYGEN_DMA_A_BURST_8 |
+ OXYGEN_DMA_MULTICH_BURST_8);
+ oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0);
+- oxygen_write8_masked(chip, OXYGEN_MISC, 0,
++ oxygen_write8_masked(chip, OXYGEN_MISC,
++ chip->model->misc_flags,
+ OXYGEN_MISC_WRITE_PCI_SUBID |
+ OXYGEN_MISC_REC_C_FROM_SPDIF |
+ OXYGEN_MISC_REC_B_FROM_AC97 |
+- OXYGEN_MISC_REC_A_FROM_MULTICH);
++ OXYGEN_MISC_REC_A_FROM_MULTICH |
++ OXYGEN_MISC_MIDI);
+ oxygen_write8(chip, OXYGEN_REC_FORMAT,
+ (OXYGEN_FORMAT_16 << OXYGEN_REC_FORMAT_A_SHIFT) |
+ (OXYGEN_FORMAT_16 << OXYGEN_REC_FORMAT_B_SHIFT) |
+@@ -267,35 +270,49 @@ static void oxygen_init(struct oxygen *chip)
+ (OXYGEN_FORMAT_16 << OXYGEN_MULTICH_FORMAT_SHIFT));
+ oxygen_write8(chip, OXYGEN_REC_CHANNELS, OXYGEN_REC_CHANNELS_2_2_2);
+ oxygen_write16(chip, OXYGEN_I2S_MULTICH_FORMAT,
+- OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST |
+- OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 |
+- OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
+- oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,
+- OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST |
+- OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 |
+- OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
+- oxygen_write16(chip, OXYGEN_I2S_B_FORMAT,
+- OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST |
+- OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 |
++ OXYGEN_RATE_48000 | chip->model->dac_i2s_format |
++ OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
+ OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
++ if (chip->model->pcm_dev_cfg & CAPTURE_0_FROM_I2S_1)
++ oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,
++ OXYGEN_RATE_48000 | chip->model->adc_i2s_format |
++ OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
++ OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
++ else
++ oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,
++ OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK);
++ if (chip->model->pcm_dev_cfg & (CAPTURE_0_FROM_I2S_2 |
++ CAPTURE_2_FROM_I2S_2))
++ oxygen_write16(chip, OXYGEN_I2S_B_FORMAT,
++ OXYGEN_RATE_48000 | chip->model->adc_i2s_format |
++ OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
++ OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
++ else
++ oxygen_write16(chip, OXYGEN_I2S_B_FORMAT,
++ OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK);
+ oxygen_write16(chip, OXYGEN_I2S_C_FORMAT,
+- OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_LJUST |
+- OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 |
+- OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
+- oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL,
+- OXYGEN_SPDIF_SENSE_MASK |
+- OXYGEN_SPDIF_LOCK_MASK |
+- OXYGEN_SPDIF_RATE_MASK |
+- OXYGEN_SPDIF_LOCK_PAR |
+- OXYGEN_SPDIF_IN_CLOCK_96,
+- OXYGEN_SPDIF_OUT_ENABLE |
+- OXYGEN_SPDIF_LOOPBACK |
+- OXYGEN_SPDIF_SENSE_MASK |
+- OXYGEN_SPDIF_LOCK_MASK |
+- OXYGEN_SPDIF_RATE_MASK |
+- OXYGEN_SPDIF_SENSE_PAR |
+- OXYGEN_SPDIF_LOCK_PAR |
+- OXYGEN_SPDIF_IN_CLOCK_MASK);
++ OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK);
++ oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL,
++ OXYGEN_SPDIF_OUT_ENABLE |
++ OXYGEN_SPDIF_LOOPBACK);
++ if (chip->model->pcm_dev_cfg & CAPTURE_1_FROM_SPDIF)
++ oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL,
++ OXYGEN_SPDIF_SENSE_MASK |
++ OXYGEN_SPDIF_LOCK_MASK |
++ OXYGEN_SPDIF_RATE_MASK |
++ OXYGEN_SPDIF_LOCK_PAR |
++ OXYGEN_SPDIF_IN_CLOCK_96,
++ OXYGEN_SPDIF_SENSE_MASK |
++ OXYGEN_SPDIF_LOCK_MASK |
++ OXYGEN_SPDIF_RATE_MASK |
++ OXYGEN_SPDIF_SENSE_PAR |
++ OXYGEN_SPDIF_LOCK_PAR |
++ OXYGEN_SPDIF_IN_CLOCK_MASK);
++ else
++ oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL,
++ OXYGEN_SPDIF_SENSE_MASK |
++ OXYGEN_SPDIF_LOCK_MASK |
++ OXYGEN_SPDIF_RATE_MASK);
+ oxygen_write32(chip, OXYGEN_SPDIF_OUTPUT_BITS, chip->spdif_bits);
+ oxygen_clear_bits8(chip, OXYGEN_MPU401_CONTROL, OXYGEN_MPU401_LOOPBACK);
+ oxygen_write8(chip, OXYGEN_GPI_INTERRUPT_MASK, 0);
+@@ -318,9 +335,12 @@ static void oxygen_init(struct oxygen *chip)
+ (2 << OXYGEN_A_MONITOR_ROUTE_2_SHIFT) |
+ (3 << OXYGEN_A_MONITOR_ROUTE_3_SHIFT));
+
+- oxygen_write8(chip, OXYGEN_AC97_INTERRUPT_MASK,
+- OXYGEN_AC97_INT_READ_DONE |
+- OXYGEN_AC97_INT_WRITE_DONE);
++ if (chip->has_ac97_0 | chip->has_ac97_1)
++ oxygen_write8(chip, OXYGEN_AC97_INTERRUPT_MASK,
++ OXYGEN_AC97_INT_READ_DONE |
++ OXYGEN_AC97_INT_WRITE_DONE);
++ else
++ oxygen_write8(chip, OXYGEN_AC97_INTERRUPT_MASK, 0);
+ oxygen_write32(chip, OXYGEN_AC97_OUT_CONFIG, 0);
+ oxygen_write32(chip, OXYGEN_AC97_IN_CONFIG, 0);
+ if (!(chip->has_ac97_0 | chip->has_ac97_1))
+@@ -351,6 +371,8 @@ static void oxygen_init(struct oxygen *chip)
+ oxygen_write_ac97(chip, 0, AC97_REC_GAIN, 0x8000);
+ oxygen_write_ac97(chip, 0, AC97_CENTER_LFE_MASTER, 0x8080);
+ oxygen_write_ac97(chip, 0, AC97_SURROUND_MASTER, 0x8080);
++ oxygen_ac97_clear_bits(chip, 0, CM9780_GPIO_STATUS,
++ CM9780_GPO0);
+ /* power down unused ADCs and DACs */
+ oxygen_ac97_set_bits(chip, 0, AC97_POWERDOWN,
+ AC97_PD_PR0 | AC97_PD_PR1);
+@@ -388,10 +410,8 @@ static void oxygen_card_free(struct snd_card *card)
+ oxygen_write16(chip, OXYGEN_DMA_STATUS, 0);
+ oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0);
+ spin_unlock_irq(&chip->reg_lock);
+- if (chip->irq >= 0) {
++ if (chip->irq >= 0)
+ free_irq(chip->irq, chip);
+- synchronize_irq(chip->irq);
+- }
+ flush_scheduled_work();
+ chip->model->cleanup(chip);
+ mutex_destroy(&chip->mutex);
+@@ -400,7 +420,7 @@ static void oxygen_card_free(struct snd_card *card)
+ }
+
+ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
+- int midi, const struct oxygen_model *model)
++ const struct oxygen_model *model)
+ {
+ struct snd_card *card;
+ struct oxygen *chip;
+@@ -472,9 +492,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
+ if (err < 0)
+ goto err_card;
+
+- oxygen_write8_masked(chip, OXYGEN_MISC,
+- midi ? OXYGEN_MISC_MIDI : 0, OXYGEN_MISC_MIDI);
+- if (midi) {
++ if (model->misc_flags & OXYGEN_MISC_MIDI) {
+ err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI,
+ chip->addr + OXYGEN_MPU401,
+ MPU401_INFO_INTEGRATED, 0, 0,
+@@ -486,7 +504,10 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
+ oxygen_proc_init(chip);
+
+ spin_lock_irq(&chip->reg_lock);
+- chip->interrupt_mask |= OXYGEN_INT_SPDIF_IN_DETECT | OXYGEN_INT_AC97;
++ if (chip->model->pcm_dev_cfg & CAPTURE_1_FROM_SPDIF)
++ chip->interrupt_mask |= OXYGEN_INT_SPDIF_IN_DETECT;
++ if (chip->has_ac97_0 | chip->has_ac97_1)
++ chip->interrupt_mask |= OXYGEN_INT_AC97;
+ oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask);
+ spin_unlock_irq(&chip->reg_lock);
+
+diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c
+index a8e4623..cc0cdda 100644
+--- a/sound/pci/oxygen/oxygen_mixer.c
++++ b/sound/pci/oxygen/oxygen_mixer.c
+@@ -32,8 +32,8 @@ static int dac_volume_info(struct snd_kcontrol *ctl,
+
+ info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ info->count = chip->model->dac_channels;
+- info->value.integer.min = 0;
+- info->value.integer.max = 0xff;
++ info->value.integer.min = chip->model->dac_volume_min;
++ info->value.integer.max = chip->model->dac_volume_max;
+ return 0;
+ }
+
+@@ -446,6 +446,50 @@ static int spdif_loopback_put(struct snd_kcontrol *ctl,
+ return changed;
+ }
+
++static int monitor_volume_info(struct snd_kcontrol *ctl,
++ struct snd_ctl_elem_info *info)
++{
++ info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++ info->count = 1;
++ info->value.integer.min = 0;
++ info->value.integer.max = 1;
++ return 0;
++}
++
++static int monitor_get(struct snd_kcontrol *ctl,
++ struct snd_ctl_elem_value *value)
++{
++ struct oxygen *chip = ctl->private_data;
++ u8 bit = ctl->private_value;
++ int invert = ctl->private_value & (1 << 8);
++
++ value->value.integer.value[0] =
++ !!invert ^ !!(oxygen_read8(chip, OXYGEN_ADC_MONITOR) & bit);
++ return 0;
++}
++
++static int monitor_put(struct snd_kcontrol *ctl,
++ struct snd_ctl_elem_value *value)
++{
++ struct oxygen *chip = ctl->private_data;
++ u8 bit = ctl->private_value;
++ int invert = ctl->private_value & (1 << 8);
++ u8 oldreg, newreg;
++ int changed;
++
++ spin_lock_irq(&chip->reg_lock);
++ oldreg = oxygen_read8(chip, OXYGEN_ADC_MONITOR);
++ if ((!!value->value.integer.value[0] ^ !!invert) != 0)
++ newreg = oldreg | bit;
++ else
++ newreg = oldreg & ~bit;
++ changed = newreg != oldreg;
++ if (changed)
++ oxygen_write8(chip, OXYGEN_ADC_MONITOR, newreg);
++ spin_unlock_irq(&chip->reg_lock);
++ return changed;
++}
++
+ static int ac97_switch_get(struct snd_kcontrol *ctl,
+ struct snd_ctl_elem_value *value)
+ {
+@@ -466,6 +510,21 @@ static int ac97_switch_get(struct snd_kcontrol *ctl,
+ return 0;
+ }
+
++static void mute_ac97_ctl(struct oxygen *chip, unsigned int control)
++{
++ unsigned int priv_idx = chip->controls[control]->private_value & 0xff;
++ u16 value;
++
++ value = oxygen_read_ac97(chip, 0, priv_idx);
++ if (!(value & 0x8000)) {
++ oxygen_write_ac97(chip, 0, priv_idx, value | 0x8000);
++ if (chip->model->ac97_switch)
++ chip->model->ac97_switch(chip, priv_idx, 0x8000);
++ snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
++ &chip->controls[control]->id);
++ }
++}
++
+ static int ac97_switch_put(struct snd_kcontrol *ctl,
+ struct snd_ctl_elem_value *value)
+ {
+@@ -487,9 +546,24 @@ static int ac97_switch_put(struct snd_kcontrol *ctl,
+ change = newreg != oldreg;
+ if (change) {
+ oxygen_write_ac97(chip, codec, index, newreg);
+- if (bitnr == 15 && chip->model->ac97_switch_hook)
+- chip->model->ac97_switch_hook(chip, codec, index,
+- newreg & 0x8000);
++ if (codec == 0 && chip->model->ac97_switch)
++ chip->model->ac97_switch(chip, index, newreg & 0x8000);
++ if (index == AC97_LINE) {
++ oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS,
++ newreg & 0x8000 ?
++ CM9780_GPO0 : 0, CM9780_GPO0);
++ if (!(newreg & 0x8000)) {
++ mute_ac97_ctl(chip, CONTROL_MIC_CAPTURE_SWITCH);
++ mute_ac97_ctl(chip, CONTROL_CD_CAPTURE_SWITCH);
++ mute_ac97_ctl(chip, CONTROL_AUX_CAPTURE_SWITCH);
++ }
++ } else if ((index == AC97_MIC || index == AC97_CD ||
++ index == AC97_VIDEO || index == AC97_AUX) &&
++ bitnr == 15 && !(newreg & 0x8000)) {
++ mute_ac97_ctl(chip, CONTROL_LINE_CAPTURE_SWITCH);
++ oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS,
++ CM9780_GPO0, CM9780_GPO0);
++ }
+ }
+ mutex_unlock(&chip->mutex);
+ return change;
+@@ -608,6 +682,7 @@ static int ac97_fp_rec_volume_put(struct snd_kcontrol *ctl,
+ .private_value = ((codec) << 24) | (index), \
+ }
+
++static DECLARE_TLV_DB_SCALE(monitor_db_scale, -1000, 1000, 0);
+ static DECLARE_TLV_DB_SCALE(ac97_db_scale, -3450, 150, 0);
+ static DECLARE_TLV_DB_SCALE(ac97_rec_db_scale, 0, 150, 0);
+
+@@ -667,6 +742,9 @@ static const struct snd_kcontrol_new controls[] = {
+ .get = spdif_pcm_get,
+ .put = spdif_pcm_put,
+ },
++};
++
++static const struct snd_kcontrol_new spdif_input_controls[] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .device = 1,
+@@ -692,11 +770,118 @@ static const struct snd_kcontrol_new controls[] = {
+ },
+ };
+
++static const struct {
++ unsigned int pcm_dev;
++ struct snd_kcontrol_new controls[2];
++} monitor_controls[] = {
++ {
++ .pcm_dev = CAPTURE_0_FROM_I2S_1,
++ .controls = {
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Analog Input Monitor Switch",
++ .info = snd_ctl_boolean_mono_info,
++ .get = monitor_get,
++ .put = monitor_put,
++ .private_value = OXYGEN_ADC_MONITOR_A,
++ },
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Analog Input Monitor Volume",
++ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
++ SNDRV_CTL_ELEM_ACCESS_TLV_READ,
++ .info = monitor_volume_info,
++ .get = monitor_get,
++ .put = monitor_put,
++ .private_value = OXYGEN_ADC_MONITOR_A_HALF_VOL
++ | (1 << 8),
++ .tlv = { .p = monitor_db_scale, },
++ },
++ },
++ },
++ {
++ .pcm_dev = CAPTURE_0_FROM_I2S_2,
++ .controls = {
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Analog Input Monitor Switch",
++ .info = snd_ctl_boolean_mono_info,
++ .get = monitor_get,
++ .put = monitor_put,
++ .private_value = OXYGEN_ADC_MONITOR_B,
++ },
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Analog Input Monitor Volume",
++ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
++ SNDRV_CTL_ELEM_ACCESS_TLV_READ,
++ .info = monitor_volume_info,
++ .get = monitor_get,
++ .put = monitor_put,
++ .private_value = OXYGEN_ADC_MONITOR_B_HALF_VOL
++ | (1 << 8),
++ .tlv = { .p = monitor_db_scale, },
++ },
++ },
++ },
++ {
++ .pcm_dev = CAPTURE_2_FROM_I2S_2,
++ .controls = {
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Analog Input Monitor Switch",
++ .index = 1,
++ .info = snd_ctl_boolean_mono_info,
++ .get = monitor_get,
++ .put = monitor_put,
++ .private_value = OXYGEN_ADC_MONITOR_B,
++ },
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Analog Input Monitor Volume",
++ .index = 1,
++ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
++ SNDRV_CTL_ELEM_ACCESS_TLV_READ,
++ .info = monitor_volume_info,
++ .get = monitor_get,
++ .put = monitor_put,
++ .private_value = OXYGEN_ADC_MONITOR_B_HALF_VOL
++ | (1 << 8),
++ .tlv = { .p = monitor_db_scale, },
++ },
++ },
++ },
++ {
++ .pcm_dev = CAPTURE_1_FROM_SPDIF,
++ .controls = {
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Digital Input Monitor Switch",
++ .info = snd_ctl_boolean_mono_info,
++ .get = monitor_get,
++ .put = monitor_put,
++ .private_value = OXYGEN_ADC_MONITOR_C,
++ },
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Digital Input Monitor Volume",
++ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
++ SNDRV_CTL_ELEM_ACCESS_TLV_READ,
++ .info = monitor_volume_info,
++ .get = monitor_get,
++ .put = monitor_put,
++ .private_value = OXYGEN_ADC_MONITOR_C_HALF_VOL
++ | (1 << 8),
++ .tlv = { .p = monitor_db_scale, },
++ },
++ },
++ },
++};
++
+ static const struct snd_kcontrol_new ac97_controls[] = {
+ AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC),
+ AC97_SWITCH("Mic Capture Switch", 0, AC97_MIC, 15, 1),
+ AC97_SWITCH("Mic Boost (+20dB)", 0, AC97_MIC, 6, 0),
+- AC97_VOLUME("Line Capture Volume", 0, AC97_LINE),
+ AC97_SWITCH("Line Capture Switch", 0, AC97_LINE, 15, 1),
+ AC97_VOLUME("CD Capture Volume", 0, AC97_CD),
+ AC97_SWITCH("CD Capture Switch", 0, AC97_CD, 15, 1),
+@@ -756,6 +941,11 @@ static int add_controls(struct oxygen *chip,
+ return err;
+ if (err == 1)
+ continue;
++ if (!strcmp(template.name, "Master Playback Volume") &&
++ chip->model->dac_tlv) {
++ template.tlv.p = chip->model->dac_tlv;
++ template.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
++ }
+ ctl = snd_ctl_new1(&template, chip);
+ if (!ctl)
+ return -ENOMEM;
+@@ -773,11 +963,26 @@ static int add_controls(struct oxygen *chip,
+
+ int oxygen_mixer_init(struct oxygen *chip)
+ {
++ unsigned int i;
+ int err;
+
+ err = add_controls(chip, controls, ARRAY_SIZE(controls));
+ if (err < 0)
+ return err;
++ if (chip->model->pcm_dev_cfg & CAPTURE_1_FROM_SPDIF) {
++ err = add_controls(chip, spdif_input_controls,
++ ARRAY_SIZE(spdif_input_controls));
++ if (err < 0)
++ return err;
++ }
++ for (i = 0; i < ARRAY_SIZE(monitor_controls); ++i) {
++ if (!(chip->model->pcm_dev_cfg & monitor_controls[i].pcm_dev))
++ continue;
++ err = add_controls(chip, monitor_controls[i].controls,
++ ARRAY_SIZE(monitor_controls[i].controls));
++ if (err < 0)
++ return err;
++ }
+ if (chip->has_ac97_0) {
+ err = add_controls(chip, ac97_controls,
+ ARRAY_SIZE(ac97_controls));
+diff --git a/sound/pci/oxygen/oxygen_pcm.c b/sound/pci/oxygen/oxygen_pcm.c
+index b70046a..b17c405 100644
+--- a/sound/pci/oxygen/oxygen_pcm.c
++++ b/sound/pci/oxygen/oxygen_pcm.c
+@@ -119,7 +119,7 @@ static int oxygen_open(struct snd_pcm_substream *substream,
+
+ runtime->private_data = (void *)(uintptr_t)channel;
+ if (channel == PCM_B && chip->has_ac97_1 &&
+- (chip->model->used_channels & OXYGEN_CHANNEL_AC97))
++ (chip->model->pcm_dev_cfg & CAPTURE_2_FROM_AC97_1))
+ runtime->hw = oxygen_ac97_hardware;
+ else
+ runtime->hw = *oxygen_hardware[channel];
+@@ -365,7 +365,7 @@ static int oxygen_rec_b_hw_params(struct snd_pcm_substream *substream,
+ return err;
+
+ is_ac97 = chip->has_ac97_1 &&
+- (chip->model->used_channels & OXYGEN_CHANNEL_AC97);
++ (chip->model->pcm_dev_cfg & CAPTURE_2_FROM_AC97_1);
+
+ spin_lock_irq(&chip->reg_lock);
+ oxygen_write8_masked(chip, OXYGEN_REC_FORMAT,
+@@ -640,34 +640,39 @@ int oxygen_pcm_init(struct oxygen *chip)
+ int outs, ins;
+ int err;
+
+- outs = 1; /* OXYGEN_CHANNEL_MULTICH is always used */
+- ins = !!(chip->model->used_channels & (OXYGEN_CHANNEL_A |
+- OXYGEN_CHANNEL_B));
+- err = snd_pcm_new(chip->card, "Analog", 0, outs, ins, &pcm);
+- if (err < 0)
+- return err;
+- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &oxygen_multich_ops);
+- if (chip->model->used_channels & OXYGEN_CHANNEL_A)
+- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+- &oxygen_rec_a_ops);
+- else if (chip->model->used_channels & OXYGEN_CHANNEL_B)
+- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+- &oxygen_rec_b_ops);
+- pcm->private_data = chip;
+- pcm->private_free = oxygen_pcm_free;
+- strcpy(pcm->name, "Analog");
+- snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
+- SNDRV_DMA_TYPE_DEV,
+- snd_dma_pci_data(chip->pci),
+- 512 * 1024, 2048 * 1024);
+- if (ins)
+- snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
+- SNDRV_DMA_TYPE_DEV,
+- snd_dma_pci_data(chip->pci),
+- 128 * 1024, 256 * 1024);
+-
+- outs = !!(chip->model->used_channels & OXYGEN_CHANNEL_SPDIF);
+- ins = !!(chip->model->used_channels & OXYGEN_CHANNEL_C);
++ outs = !!(chip->model->pcm_dev_cfg & PLAYBACK_0_TO_I2S);
++ ins = !!(chip->model->pcm_dev_cfg & (CAPTURE_0_FROM_I2S_1 |
++ CAPTURE_0_FROM_I2S_2));
++ if (outs | ins) {
++ err = snd_pcm_new(chip->card, "Analog", 0, outs, ins, &pcm);
++ if (err < 0)
++ return err;
++ if (outs)
++ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
++ &oxygen_multich_ops);
++ if (chip->model->pcm_dev_cfg & CAPTURE_0_FROM_I2S_1)
++ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
++ &oxygen_rec_a_ops);
++ else if (chip->model->pcm_dev_cfg & CAPTURE_0_FROM_I2S_2)
++ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
++ &oxygen_rec_b_ops);
++ pcm->private_data = chip;
++ pcm->private_free = oxygen_pcm_free;
++ strcpy(pcm->name, "Analog");
++ if (outs)
++ snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
++ SNDRV_DMA_TYPE_DEV,
++ snd_dma_pci_data(chip->pci),
++ 512 * 1024, 2048 * 1024);
++ if (ins)
++ snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
++ SNDRV_DMA_TYPE_DEV,
++ snd_dma_pci_data(chip->pci),
++ 128 * 1024, 256 * 1024);
++ }
++
++ outs = !!(chip->model->pcm_dev_cfg & PLAYBACK_1_TO_SPDIF);
++ ins = !!(chip->model->pcm_dev_cfg & CAPTURE_1_FROM_SPDIF);
+ if (outs | ins) {
+ err = snd_pcm_new(chip->card, "Digital", 1, outs, ins, &pcm);
+ if (err < 0)
+@@ -686,12 +691,13 @@ int oxygen_pcm_init(struct oxygen *chip)
+ 128 * 1024, 256 * 1024);
+ }
+
+- outs = chip->has_ac97_1 &&
+- (chip->model->used_channels & OXYGEN_CHANNEL_AC97);
+- ins = outs ||
+- (chip->model->used_channels & (OXYGEN_CHANNEL_A |
+- OXYGEN_CHANNEL_B))
+- == (OXYGEN_CHANNEL_A | OXYGEN_CHANNEL_B);
++ if (chip->has_ac97_1) {
++ outs = !!(chip->model->pcm_dev_cfg & PLAYBACK_2_TO_AC97_1);
++ ins = !!(chip->model->pcm_dev_cfg & CAPTURE_2_FROM_AC97_1);
++ } else {
++ outs = 0;
++ ins = !!(chip->model->pcm_dev_cfg & CAPTURE_2_FROM_I2S_2);
++ }
+ if (outs | ins) {
+ err = snd_pcm_new(chip->card, outs ? "AC97" : "Analog2",
+ 2, outs, ins, &pcm);
+diff --git a/sound/pci/oxygen/pcm1796.h b/sound/pci/oxygen/pcm1796.h
+new file mode 100644
+index 0000000..698bf46
+--- /dev/null
++++ b/sound/pci/oxygen/pcm1796.h
+@@ -0,0 +1,58 @@
++#ifndef PCM1796_H_INCLUDED
++#define PCM1796_H_INCLUDED
++
++/* register 16 */
++#define PCM1796_ATL_MASK 0xff
++/* register 17 */
++#define PCM1796_ATR_MASK 0xff
++/* register 18 */
++#define PCM1796_MUTE 0x01
++#define PCM1796_DME 0x02
++#define PCM1796_DMF_MASK 0x0c
++#define PCM1796_DMF_DISABLED 0x00
++#define PCM1796_DMF_48 0x04
++#define PCM1796_DMF_441 0x08
++#define PCM1796_DMF_32 0x0c
++#define PCM1796_FMT_MASK 0x70
++#define PCM1796_FMT_16_RJUST 0x00
++#define PCM1796_FMT_20_RJUST 0x10
++#define PCM1796_FMT_24_RJUST 0x20
++#define PCM1796_FMT_24_LJUST 0x30
++#define PCM1796_FMT_16_I2S 0x40
++#define PCM1796_FMT_24_I2S 0x50
++#define PCM1796_ATLD 0x80
++/* register 19 */
++#define PCM1796_INZD 0x01
++#define PCM1796_FLT_MASK 0x02
++#define PCM1796_FLT_SHARP 0x00
++#define PCM1796_FLT_SLOW 0x02
++#define PCM1796_DFMS 0x04
++#define PCM1796_OPE 0x10
++#define PCM1796_ATS_MASK 0x60
++#define PCM1796_ATS_1 0x00
++#define PCM1796_ATS_2 0x20
++#define PCM1796_ATS_4 0x40
++#define PCM1796_ATS_8 0x60
++#define PCM1796_REV 0x80
++/* register 20 */
++#define PCM1796_OS_MASK 0x03
++#define PCM1796_OS_64 0x00
++#define PCM1796_OS_32 0x01
++#define PCM1796_OS_128 0x02
++#define PCM1796_CHSL_MASK 0x04
++#define PCM1796_CHSL_LEFT 0x00
++#define PCM1796_CHSL_RIGHT 0x04
++#define PCM1796_MONO 0x08
++#define PCM1796_DFTH 0x10
++#define PCM1796_DSD 0x20
++#define PCM1796_SRST 0x40
++/* register 21 */
++#define PCM1796_PCMZ 0x01
++#define PCM1796_DZ_MASK 0x06
++/* register 22 */
++#define PCM1796_ZFGL 0x01
++#define PCM1796_ZFGR 0x02
++/* register 23 */
++#define PCM1796_ID_MASK 0x1f
++
++#endif
+diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
+index d163397..7f84fa5 100644
+--- a/sound/pci/oxygen/virtuoso.c
++++ b/sound/pci/oxygen/virtuoso.c
+@@ -18,6 +18,9 @@
+ */
+
+ /*
++ * Xonar D2/D2X
++ * ------------
++ *
+ * CMI8788:
+ *
+ * SPI 0 -> 1st PCM1796 (front)
+@@ -30,10 +33,33 @@
+ * GPIO 5 <- external power present (D2X only)
+ * GPIO 7 -> ALT
+ * GPIO 8 -> enable output to speakers
++ */
++
++/*
++ * Xonar DX
++ * --------
++ *
++ * CMI8788:
++ *
++ * I²C <-> CS4398 (front)
++ * <-> CS4362A (surround, center/LFE, back)
++ *
++ * GPI 0 <- external power present
+ *
+- * CM9780:
++ * GPIO 0 -> enable output to speakers
++ * GPIO 1 -> enable front panel I/O
++ * GPIO 2 -> M0 of CS5361
++ * GPIO 3 -> M1 of CS5361
++ * GPIO 8 -> route input jack to line-in (0) or mic-in (1)
+ *
+- * GPIO 0 -> enable AC'97 bypass (line in -> ADC)
++ * CS4398:
++ *
++ * AD0 <- 1
++ * AD1 <- 1
++ *
++ * CS4362A:
++ *
++ * AD0 <- 0
+ */
+
+ #include <linux/pci.h>
+@@ -47,11 +73,14 @@
+ #include <sound/tlv.h>
+ #include "oxygen.h"
+ #include "cm9780.h"
++#include "pcm1796.h"
++#include "cs4398.h"
++#include "cs4362a.h"
+
+ MODULE_AUTHOR("Clemens Ladisch <clemens at ladisch.de>");
+-MODULE_DESCRIPTION("Asus AV200 driver");
++MODULE_DESCRIPTION("Asus AVx00 driver");
+ MODULE_LICENSE("GPL");
+-MODULE_SUPPORTED_DEVICE("{{Asus,AV200}}");
++MODULE_SUPPORTED_DEVICE("{{Asus,AV100},{Asus,AV200}}");
+
+ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+@@ -64,80 +93,44 @@ MODULE_PARM_DESC(id, "ID string");
+ module_param_array(enable, bool, NULL, 0444);
+ MODULE_PARM_DESC(enable, "enable card");
+
++enum {
++ MODEL_D2,
++ MODEL_D2X,
++ MODEL_DX,
++};
++
+ static struct pci_device_id xonar_ids[] __devinitdata = {
+- { OXYGEN_PCI_SUBID(0x1043, 0x8269) }, /* Asus Xonar D2 */
+- { OXYGEN_PCI_SUBID(0x1043, 0x82b7) }, /* Asus Xonar D2X */
++ { OXYGEN_PCI_SUBID(0x1043, 0x8269), .driver_data = MODEL_D2 },
++ { OXYGEN_PCI_SUBID(0x1043, 0x8275), .driver_data = MODEL_DX },
++ { OXYGEN_PCI_SUBID(0x1043, 0x82b7), .driver_data = MODEL_D2X },
+ { }
+ };
+ MODULE_DEVICE_TABLE(pci, xonar_ids);
+
+
+-#define GPIO_CS5381_M_MASK 0x000c
+-#define GPIO_CS5381_M_SINGLE 0x0000
+-#define GPIO_CS5381_M_DOUBLE 0x0004
+-#define GPIO_CS5381_M_QUAD 0x0008
+-#define GPIO_EXT_POWER 0x0020
+-#define GPIO_ALT 0x0080
+-#define GPIO_OUTPUT_ENABLE 0x0100
+-
+-#define GPIO_LINE_MUTE CM9780_GPO0
+-
+-/* register 16 */
+-#define PCM1796_ATL_MASK 0xff
+-/* register 17 */
+-#define PCM1796_ATR_MASK 0xff
+-/* register 18 */
+-#define PCM1796_MUTE 0x01
+-#define PCM1796_DME 0x02
+-#define PCM1796_DMF_MASK 0x0c
+-#define PCM1796_DMF_DISABLED 0x00
+-#define PCM1796_DMF_48 0x04
+-#define PCM1796_DMF_441 0x08
+-#define PCM1796_DMF_32 0x0c
+-#define PCM1796_FMT_MASK 0x70
+-#define PCM1796_FMT_16_RJUST 0x00
+-#define PCM1796_FMT_20_RJUST 0x10
+-#define PCM1796_FMT_24_RJUST 0x20
+-#define PCM1796_FMT_24_LJUST 0x30
+-#define PCM1796_FMT_16_I2S 0x40
+-#define PCM1796_FMT_24_I2S 0x50
+-#define PCM1796_ATLD 0x80
+-/* register 19 */
+-#define PCM1796_INZD 0x01
+-#define PCM1796_FLT_MASK 0x02
+-#define PCM1796_FLT_SHARP 0x00
+-#define PCM1796_FLT_SLOW 0x02
+-#define PCM1796_DFMS 0x04
+-#define PCM1796_OPE 0x10
+-#define PCM1796_ATS_MASK 0x60
+-#define PCM1796_ATS_1 0x00
+-#define PCM1796_ATS_2 0x20
+-#define PCM1796_ATS_4 0x40
+-#define PCM1796_ATS_8 0x60
+-#define PCM1796_REV 0x80
+-/* register 20 */
+-#define PCM1796_OS_MASK 0x03
+-#define PCM1796_OS_64 0x00
+-#define PCM1796_OS_32 0x01
+-#define PCM1796_OS_128 0x02
+-#define PCM1796_CHSL_MASK 0x04
+-#define PCM1796_CHSL_LEFT 0x00
+-#define PCM1796_CHSL_RIGHT 0x04
+-#define PCM1796_MONO 0x08
+-#define PCM1796_DFTH 0x10
+-#define PCM1796_DSD 0x20
+-#define PCM1796_SRST 0x40
+-/* register 21 */
+-#define PCM1796_PCMZ 0x01
+-#define PCM1796_DZ_MASK 0x06
+-/* register 22 */
+-#define PCM1796_ZFGL 0x01
+-#define PCM1796_ZFGR 0x02
+-/* register 23 */
+-#define PCM1796_ID_MASK 0x1f
++#define GPIO_CS53x1_M_MASK 0x000c
++#define GPIO_CS53x1_M_SINGLE 0x0000
++#define GPIO_CS53x1_M_DOUBLE 0x0004
++#define GPIO_CS53x1_M_QUAD 0x0008
++
++#define GPIO_D2X_EXT_POWER 0x0020
++#define GPIO_D2_ALT 0x0080
++#define GPIO_D2_OUTPUT_ENABLE 0x0100
++
++#define GPI_DX_EXT_POWER 0x01
++#define GPIO_DX_OUTPUT_ENABLE 0x0001
++#define GPIO_DX_FRONT_PANEL 0x0002
++#define GPIO_DX_INPUT_ROUTE 0x0100
++
++#define I2C_DEVICE_CS4398 0x9e /* 10011, AD1=1, AD0=1, /W=0 */
++#define I2C_DEVICE_CS4362A 0x30 /* 001100, AD0=0, /W=0 */
+
+ struct xonar_data {
+- u8 is_d2x;
++ unsigned int anti_pop_delay;
++ u16 output_enable_bit;
++ u8 ext_power_reg;
++ u8 ext_power_int_reg;
++ u8 ext_power_bit;
+ u8 has_power;
+ };
+
+@@ -156,62 +149,157 @@ static void pcm1796_write(struct oxygen *chip, unsigned int codec,
+ (reg << 8) | value);
+ }
+
+-static void xonar_init(struct oxygen *chip)
++static void cs4398_write(struct oxygen *chip, u8 reg, u8 value)
++{
++ oxygen_write_i2c(chip, I2C_DEVICE_CS4398, reg, value);
++}
++
++static void cs4362a_write(struct oxygen *chip, u8 reg, u8 value)
++{
++ oxygen_write_i2c(chip, I2C_DEVICE_CS4362A, reg, value);
++}
++
++static void xonar_common_init(struct oxygen *chip)
++{
++ struct xonar_data *data = chip->model_data;
++
++ if (data->ext_power_reg) {
++ oxygen_set_bits8(chip, data->ext_power_int_reg,
++ data->ext_power_bit);
++ chip->interrupt_mask |= OXYGEN_INT_GPIO;
++ data->has_power = !!(oxygen_read8(chip, data->ext_power_reg)
++ & data->ext_power_bit);
++ }
++ oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CS53x1_M_MASK);
++ oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
++ GPIO_CS53x1_M_SINGLE, GPIO_CS53x1_M_MASK);
++ oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC);
++ msleep(data->anti_pop_delay);
++ oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, data->output_enable_bit);
++ oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit);
++}
++
++static void xonar_d2_init(struct oxygen *chip)
+ {
+ struct xonar_data *data = chip->model_data;
+ unsigned int i;
+
+- data->is_d2x = chip->pci->subsystem_device == 0x82b7;
++ data->anti_pop_delay = 300;
++ data->output_enable_bit = GPIO_D2_OUTPUT_ENABLE;
+
+ for (i = 0; i < 4; ++i) {
+- pcm1796_write(chip, i, 18, PCM1796_FMT_24_LJUST | PCM1796_ATLD);
++ pcm1796_write(chip, i, 18, PCM1796_MUTE | PCM1796_DMF_DISABLED |
++ PCM1796_FMT_24_LJUST | PCM1796_ATLD);
+ pcm1796_write(chip, i, 19, PCM1796_FLT_SHARP | PCM1796_ATS_1);
+ pcm1796_write(chip, i, 20, PCM1796_OS_64);
+ pcm1796_write(chip, i, 21, 0);
+- pcm1796_write(chip, i, 16, 0xff); /* set ATL/ATR after ATLD */
+- pcm1796_write(chip, i, 17, 0xff);
++ pcm1796_write(chip, i, 16, 0x0f); /* set ATL/ATR after ATLD */
++ pcm1796_write(chip, i, 17, 0x0f);
+ }
+
+- oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
+- GPIO_CS5381_M_MASK | GPIO_ALT);
+- oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
+- GPIO_CS5381_M_SINGLE,
+- GPIO_CS5381_M_MASK | GPIO_ALT);
+- if (data->is_d2x) {
+- oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
+- GPIO_EXT_POWER);
+- oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK,
+- GPIO_EXT_POWER);
+- chip->interrupt_mask |= OXYGEN_INT_GPIO;
+- data->has_power = !!(oxygen_read16(chip, OXYGEN_GPIO_DATA)
+- & GPIO_EXT_POWER);
+- }
+- oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC);
+- oxygen_ac97_clear_bits(chip, 0, CM9780_GPIO_STATUS, GPIO_LINE_MUTE);
+- msleep(300);
+- oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_OUTPUT_ENABLE);
+- oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE);
++ oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2_ALT);
++ oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_D2_ALT);
++
++ xonar_common_init(chip);
+
+ snd_component_add(chip->card, "PCM1796");
+ snd_component_add(chip->card, "CS5381");
+ }
+
++static void xonar_d2x_init(struct oxygen *chip)
++{
++ struct xonar_data *data = chip->model_data;
++
++ data->ext_power_reg = OXYGEN_GPIO_DATA;
++ data->ext_power_int_reg = OXYGEN_GPIO_INTERRUPT_MASK;
++ data->ext_power_bit = GPIO_D2X_EXT_POWER;
++ oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2X_EXT_POWER);
++ xonar_d2_init(chip);
++}
++
++static void xonar_dx_init(struct oxygen *chip)
++{
++ struct xonar_data *data = chip->model_data;
++
++ data->anti_pop_delay = 800;
++ data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE;
++ data->ext_power_reg = OXYGEN_GPI_DATA;
++ data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
++ data->ext_power_bit = GPI_DX_EXT_POWER;
++
++ oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
++ OXYGEN_2WIRE_LENGTH_8 |
++ OXYGEN_2WIRE_INTERRUPT_MASK |
++ OXYGEN_2WIRE_SPEED_FAST);
++
++ /* set CPEN (control port mode) and power down */
++ cs4398_write(chip, 8, CS4398_CPEN | CS4398_PDN);
++ cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN);
++ /* configure */
++ cs4398_write(chip, 2, CS4398_FM_SINGLE |
++ CS4398_DEM_NONE | CS4398_DIF_LJUST);
++ cs4398_write(chip, 3, CS4398_ATAPI_B_R | CS4398_ATAPI_A_L);
++ cs4398_write(chip, 4, CS4398_MUTEP_LOW | CS4398_PAMUTE);
++ cs4398_write(chip, 5, 0xfe);
++ cs4398_write(chip, 6, 0xfe);
++ cs4398_write(chip, 7, CS4398_RMP_DN | CS4398_RMP_UP |
++ CS4398_ZERO_CROSS | CS4398_SOFT_RAMP);
++ cs4362a_write(chip, 0x02, CS4362A_DIF_LJUST);
++ cs4362a_write(chip, 0x03, CS4362A_MUTEC_6 | CS4362A_AMUTE |
++ CS4362A_RMP_UP | CS4362A_ZERO_CROSS | CS4362A_SOFT_RAMP);
++ cs4362a_write(chip, 0x04, CS4362A_RMP_DN | CS4362A_DEM_NONE);
++ cs4362a_write(chip, 0x05, 0);
++ cs4362a_write(chip, 0x06, CS4362A_FM_SINGLE |
++ CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L);
++ cs4362a_write(chip, 0x07, 0x7f | CS4362A_MUTE);
++ cs4362a_write(chip, 0x08, 0x7f | CS4362A_MUTE);
++ cs4362a_write(chip, 0x09, CS4362A_FM_SINGLE |
++ CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L);
++ cs4362a_write(chip, 0x0a, 0x7f | CS4362A_MUTE);
++ cs4362a_write(chip, 0x0b, 0x7f | CS4362A_MUTE);
++ cs4362a_write(chip, 0x0c, CS4362A_FM_SINGLE |
++ CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L);
++ cs4362a_write(chip, 0x0d, 0x7f | CS4362A_MUTE);
++ cs4362a_write(chip, 0x0e, 0x7f | CS4362A_MUTE);
++ /* clear power down */
++ cs4398_write(chip, 8, CS4398_CPEN);
++ cs4362a_write(chip, 0x01, CS4362A_CPEN);
++
++ oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
++ GPIO_DX_FRONT_PANEL | GPIO_DX_INPUT_ROUTE);
++ oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA,
++ GPIO_DX_FRONT_PANEL | GPIO_DX_INPUT_ROUTE);
++
++ xonar_common_init(chip);
++
++ snd_component_add(chip->card, "CS4398");
++ snd_component_add(chip->card, "CS4362A");
++ snd_component_add(chip->card, "CS5361");
++}
++
+ static void xonar_cleanup(struct oxygen *chip)
+ {
+- oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE);
++ struct xonar_data *data = chip->model_data;
++
++ oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit);
++}
++
++static void xonar_dx_cleanup(struct oxygen *chip)
++{
++ xonar_cleanup(chip);
++ cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN);
++ oxygen_clear_bits8(chip, OXYGEN_FUNCTION, OXYGEN_FUNCTION_RESET_CODEC);
+ }
+
+ static void set_pcm1796_params(struct oxygen *chip,
+ struct snd_pcm_hw_params *params)
+ {
+-#if 0
+ unsigned int i;
+ u8 value;
+
+ value = params_rate(params) >= 96000 ? PCM1796_OS_32 : PCM1796_OS_64;
+ for (i = 0; i < 4; ++i)
+ pcm1796_write(chip, i, 20, value);
+-#endif
+ }
+
+ static void update_pcm1796_volume(struct oxygen *chip)
+@@ -236,19 +324,73 @@ static void update_pcm1796_mute(struct oxygen *chip)
+ pcm1796_write(chip, i, 18, value);
+ }
+
+-static void set_cs5381_params(struct oxygen *chip,
++static void set_cs53x1_params(struct oxygen *chip,
+ struct snd_pcm_hw_params *params)
+ {
+ unsigned int value;
+
+ if (params_rate(params) <= 54000)
+- value = GPIO_CS5381_M_SINGLE;
++ value = GPIO_CS53x1_M_SINGLE;
+ else if (params_rate(params) <= 108000)
+- value = GPIO_CS5381_M_DOUBLE;
++ value = GPIO_CS53x1_M_DOUBLE;
+ else
+- value = GPIO_CS5381_M_QUAD;
++ value = GPIO_CS53x1_M_QUAD;
+ oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
+- value, GPIO_CS5381_M_MASK);
++ value, GPIO_CS53x1_M_MASK);
++}
++
++static void set_cs43xx_params(struct oxygen *chip,
++ struct snd_pcm_hw_params *params)
++{
++ u8 fm_cs4398, fm_cs4362a;
++
++ fm_cs4398 = CS4398_DEM_NONE | CS4398_DIF_LJUST;
++ fm_cs4362a = CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L;
++ if (params_rate(params) <= 50000) {
++ fm_cs4398 |= CS4398_FM_SINGLE;
++ fm_cs4362a |= CS4362A_FM_SINGLE;
++ } else if (params_rate(params) <= 100000) {
++ fm_cs4398 |= CS4398_FM_DOUBLE;
++ fm_cs4362a |= CS4362A_FM_DOUBLE;
++ } else {
++ fm_cs4398 |= CS4398_FM_QUAD;
++ fm_cs4362a |= CS4362A_FM_QUAD;
++ }
++ cs4398_write(chip, 2, fm_cs4398);
++ cs4362a_write(chip, 0x06, fm_cs4362a);
++ cs4362a_write(chip, 0x09, fm_cs4362a);
++ cs4362a_write(chip, 0x0c, fm_cs4362a);
++}
++
++static void update_cs4362a_volumes(struct oxygen *chip)
++{
++ u8 mute;
++
++ mute = chip->dac_mute ? CS4362A_MUTE : 0;
++ cs4362a_write(chip, 7, (127 - chip->dac_volume[2]) | mute);
++ cs4362a_write(chip, 8, (127 - chip->dac_volume[3]) | mute);
++ cs4362a_write(chip, 10, (127 - chip->dac_volume[4]) | mute);
++ cs4362a_write(chip, 11, (127 - chip->dac_volume[5]) | mute);
++ cs4362a_write(chip, 13, (127 - chip->dac_volume[6]) | mute);
++ cs4362a_write(chip, 14, (127 - chip->dac_volume[7]) | mute);
++}
++
++static void update_cs43xx_volume(struct oxygen *chip)
++{
++ cs4398_write(chip, 5, (127 - chip->dac_volume[0]) * 2);
++ cs4398_write(chip, 6, (127 - chip->dac_volume[1]) * 2);
++ update_cs4362a_volumes(chip);
++}
++
++static void update_cs43xx_mute(struct oxygen *chip)
++{
++ u8 reg;
++
++ reg = CS4398_MUTEP_LOW | CS4398_PAMUTE;
++ if (chip->dac_mute)
++ reg |= CS4398_MUTE_B | CS4398_MUTE_A;
++ cs4398_write(chip, 4, reg);
++ update_cs4362a_volumes(chip);
+ }
+
+ static void xonar_gpio_changed(struct oxygen *chip)
+@@ -256,10 +398,8 @@ static void xonar_gpio_changed(struct oxygen *chip)
+ struct xonar_data *data = chip->model_data;
+ u8 has_power;
+
+- if (!data->is_d2x)
+- return;
+- has_power = !!(oxygen_read16(chip, OXYGEN_GPIO_DATA)
+- & GPIO_EXT_POWER);
++ has_power = !!(oxygen_read8(chip, data->ext_power_reg)
++ & data->ext_power_bit);
+ if (has_power != data->has_power) {
+ data->has_power = has_power;
+ if (has_power) {
+@@ -272,66 +412,13 @@ static void xonar_gpio_changed(struct oxygen *chip)
+ }
+ }
+
+-static void mute_ac97_ctl(struct oxygen *chip, unsigned int control)
+-{
+- unsigned int index = chip->controls[control]->private_value & 0xff;
+- u16 value;
+-
+- value = oxygen_read_ac97(chip, 0, index);
+- if (!(value & 0x8000)) {
+- oxygen_write_ac97(chip, 0, index, value | 0x8000);
+- snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+- &chip->controls[control]->id);
+- }
+-}
+-
+-static void xonar_ac97_switch_hook(struct oxygen *chip, unsigned int codec,
+- unsigned int reg, int mute)
+-{
+- if (codec != 0)
+- return;
+- /* line-in is exclusive */
+- switch (reg) {
+- case AC97_LINE:
+- oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS,
+- mute ? GPIO_LINE_MUTE : 0,
+- GPIO_LINE_MUTE);
+- if (!mute) {
+- mute_ac97_ctl(chip, CONTROL_MIC_CAPTURE_SWITCH);
+- mute_ac97_ctl(chip, CONTROL_CD_CAPTURE_SWITCH);
+- mute_ac97_ctl(chip, CONTROL_AUX_CAPTURE_SWITCH);
+- }
+- break;
+- case AC97_MIC:
+- case AC97_CD:
+- case AC97_VIDEO:
+- case AC97_AUX:
+- if (!mute) {
+- oxygen_ac97_set_bits(chip, 0, CM9780_GPIO_STATUS,
+- GPIO_LINE_MUTE);
+- mute_ac97_ctl(chip, CONTROL_LINE_CAPTURE_SWITCH);
+- }
+- break;
+- }
+-}
+-
+-static int pcm1796_volume_info(struct snd_kcontrol *ctl,
+- struct snd_ctl_elem_info *info)
+-{
+- info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+- info->count = 8;
+- info->value.integer.min = 0x0f;
+- info->value.integer.max = 0xff;
+- return 0;
+-}
+-
+ static int alt_switch_get(struct snd_kcontrol *ctl,
+ struct snd_ctl_elem_value *value)
+ {
+ struct oxygen *chip = ctl->private_data;
+
+ value->value.integer.value[0] =
+- !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_ALT);
++ !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_D2_ALT);
+ return 0;
+ }
+
+@@ -345,9 +432,9 @@ static int alt_switch_put(struct snd_kcontrol *ctl,
+ spin_lock_irq(&chip->reg_lock);
+ old_bits = oxygen_read16(chip, OXYGEN_GPIO_DATA);
+ if (value->value.integer.value[0])
+- new_bits = old_bits | GPIO_ALT;
++ new_bits = old_bits | GPIO_D2_ALT;
+ else
+- new_bits = old_bits & ~GPIO_ALT;
++ new_bits = old_bits & ~GPIO_D2_ALT;
+ changed = new_bits != old_bits;
+ if (changed)
+ oxygen_write16(chip, OXYGEN_GPIO_DATA, new_bits);
+@@ -363,20 +450,68 @@ static const struct snd_kcontrol_new alt_switch = {
+ .put = alt_switch_put,
+ };
+
++static int front_panel_get(struct snd_kcontrol *ctl,
++ struct snd_ctl_elem_value *value)
++{
++ struct oxygen *chip = ctl->private_data;
++
++ value->value.integer.value[0] =
++ !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_DX_FRONT_PANEL);
++ return 0;
++}
++
++static int front_panel_put(struct snd_kcontrol *ctl,
++ struct snd_ctl_elem_value *value)
++{
++ struct oxygen *chip = ctl->private_data;
++ u16 old_reg, new_reg;
++
++ spin_lock_irq(&chip->reg_lock);
++ old_reg = oxygen_read16(chip, OXYGEN_GPIO_DATA);
++ if (value->value.integer.value[0])
++ new_reg = old_reg | GPIO_DX_FRONT_PANEL;
++ else
++ new_reg = old_reg & ~GPIO_DX_FRONT_PANEL;
++ oxygen_write16(chip, OXYGEN_GPIO_DATA, new_reg);
++ spin_unlock_irq(&chip->reg_lock);
++ return old_reg != new_reg;
++}
++
++static const struct snd_kcontrol_new front_panel_switch = {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "Front Panel Switch",
++ .info = snd_ctl_boolean_mono_info,
++ .get = front_panel_get,
++ .put = front_panel_put,
++};
++
++static void xonar_dx_ac97_switch(struct oxygen *chip,
++ unsigned int reg, unsigned int mute)
++{
++ if (reg == AC97_LINE) {
++ spin_lock_irq(&chip->reg_lock);
++ oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
++ mute ? GPIO_DX_INPUT_ROUTE : 0,
++ GPIO_DX_INPUT_ROUTE);
++ spin_unlock_irq(&chip->reg_lock);
++ }
++}
++
+ static const DECLARE_TLV_DB_SCALE(pcm1796_db_scale, -12000, 50, 0);
++static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -12700, 100, 0);
+
+-static int xonar_control_filter(struct snd_kcontrol_new *template)
++static int xonar_d2_control_filter(struct snd_kcontrol_new *template)
+ {
+- if (!strcmp(template->name, "Master Playback Volume")) {
+- template->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+- template->info = pcm1796_volume_info,
+- template->tlv.p = pcm1796_db_scale;
+- } else if (!strncmp(template->name, "CD Capture ", 11)) {
++ if (!strncmp(template->name, "CD Capture ", 11))
+ /* CD in is actually connected to the video in pin */
+ template->private_value ^= AC97_CD ^ AC97_VIDEO;
+- } else if (!strcmp(template->name, "Line Capture Volume")) {
+- return 1; /* line-in bypasses the AC'97 mixer */
+- }
++ return 0;
++}
++
++static int xonar_dx_control_filter(struct snd_kcontrol_new *template)
++{
++ if (!strncmp(template->name, "CD Capture ", 11))
++ return 1; /* no CD input */
+ return 0;
+ }
+
+@@ -385,30 +520,96 @@ static int xonar_mixer_init(struct oxygen *chip)
+ return snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip));
+ }
+
+-static const struct oxygen_model model_xonar = {
+- .shortname = "Asus AV200",
+- .longname = "Asus Virtuoso 200",
+- .chip = "AV200",
+- .owner = THIS_MODULE,
+- .init = xonar_init,
+- .control_filter = xonar_control_filter,
+- .mixer_init = xonar_mixer_init,
+- .cleanup = xonar_cleanup,
+- .set_dac_params = set_pcm1796_params,
+- .set_adc_params = set_cs5381_params,
+- .update_dac_volume = update_pcm1796_volume,
+- .update_dac_mute = update_pcm1796_mute,
+- .ac97_switch_hook = xonar_ac97_switch_hook,
+- .gpio_changed = xonar_gpio_changed,
+- .model_data_size = sizeof(struct xonar_data),
+- .dac_channels = 8,
+- .used_channels = OXYGEN_CHANNEL_B |
+- OXYGEN_CHANNEL_C |
+- OXYGEN_CHANNEL_SPDIF |
+- OXYGEN_CHANNEL_MULTICH,
+- .function_flags = OXYGEN_FUNCTION_ENABLE_SPI_4_5,
+- .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+- .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
++static int xonar_dx_mixer_init(struct oxygen *chip)
++{
++ return snd_ctl_add(chip->card, snd_ctl_new1(&front_panel_switch, chip));
++}
++
++static const struct oxygen_model xonar_models[] = {
++ [MODEL_D2] = {
++ .shortname = "Xonar D2",
++ .longname = "Asus Virtuoso 200",
++ .chip = "AV200",
++ .owner = THIS_MODULE,
++ .init = xonar_d2_init,
++ .control_filter = xonar_d2_control_filter,
++ .mixer_init = xonar_mixer_init,
++ .cleanup = xonar_cleanup,
++ .set_dac_params = set_pcm1796_params,
++ .set_adc_params = set_cs53x1_params,
++ .update_dac_volume = update_pcm1796_volume,
++ .update_dac_mute = update_pcm1796_mute,
++ .dac_tlv = pcm1796_db_scale,
++ .model_data_size = sizeof(struct xonar_data),
++ .pcm_dev_cfg = PLAYBACK_0_TO_I2S |
++ PLAYBACK_1_TO_SPDIF |
++ CAPTURE_0_FROM_I2S_2 |
++ CAPTURE_1_FROM_SPDIF,
++ .dac_channels = 8,
++ .dac_volume_min = 0x0f,
++ .dac_volume_max = 0xff,
++ .misc_flags = OXYGEN_MISC_MIDI,
++ .function_flags = OXYGEN_FUNCTION_SPI |
++ OXYGEN_FUNCTION_ENABLE_SPI_4_5,
++ .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
++ .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
++ },
++ [MODEL_D2X] = {
++ .shortname = "Xonar D2X",
++ .longname = "Asus Virtuoso 200",
++ .chip = "AV200",
++ .owner = THIS_MODULE,
++ .init = xonar_d2x_init,
++ .control_filter = xonar_d2_control_filter,
++ .mixer_init = xonar_mixer_init,
++ .cleanup = xonar_cleanup,
++ .set_dac_params = set_pcm1796_params,
++ .set_adc_params = set_cs53x1_params,
++ .update_dac_volume = update_pcm1796_volume,
++ .update_dac_mute = update_pcm1796_mute,
++ .gpio_changed = xonar_gpio_changed,
++ .dac_tlv = pcm1796_db_scale,
++ .model_data_size = sizeof(struct xonar_data),
++ .pcm_dev_cfg = PLAYBACK_0_TO_I2S |
++ PLAYBACK_1_TO_SPDIF |
++ CAPTURE_0_FROM_I2S_2 |
++ CAPTURE_1_FROM_SPDIF,
++ .dac_channels = 8,
++ .dac_volume_min = 0x0f,
++ .dac_volume_max = 0xff,
++ .misc_flags = OXYGEN_MISC_MIDI,
++ .function_flags = OXYGEN_FUNCTION_SPI |
++ OXYGEN_FUNCTION_ENABLE_SPI_4_5,
++ .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
++ .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
++ },
++ [MODEL_DX] = {
++ .shortname = "Xonar DX",
++ .longname = "Asus Virtuoso 100",
++ .chip = "AV200",
++ .owner = THIS_MODULE,
++ .init = xonar_dx_init,
++ .control_filter = xonar_dx_control_filter,
++ .mixer_init = xonar_dx_mixer_init,
++ .cleanup = xonar_dx_cleanup,
++ .set_dac_params = set_cs43xx_params,
++ .set_adc_params = set_cs53x1_params,
++ .update_dac_volume = update_cs43xx_volume,
++ .update_dac_mute = update_cs43xx_mute,
++ .gpio_changed = xonar_gpio_changed,
++ .ac97_switch = xonar_dx_ac97_switch,
++ .dac_tlv = cs4362a_db_scale,
++ .model_data_size = sizeof(struct xonar_data),
++ .pcm_dev_cfg = PLAYBACK_0_TO_I2S |
++ PLAYBACK_1_TO_SPDIF |
++ CAPTURE_0_FROM_I2S_2,
++ .dac_channels = 8,
++ .dac_volume_min = 0,
++ .dac_volume_max = 127,
++ .function_flags = OXYGEN_FUNCTION_2WIRE,
++ .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
++ .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
++ },
+ };
+
+ static int __devinit xonar_probe(struct pci_dev *pci,
+@@ -423,7 +624,8 @@ static int __devinit xonar_probe(struct pci_dev *pci,
+ ++dev;
+ return -ENOENT;
+ }
+- err = oxygen_pci_probe(pci, index[dev], id[dev], 1, &model_xonar);
++ err = oxygen_pci_probe(pci, index[dev], id[dev],
++ &xonar_models[pci_id->driver_data]);
+ if (err >= 0)
+ ++dev;
+ return err;
+diff --git a/sound/pci/oxygen/wm8785.h b/sound/pci/oxygen/wm8785.h
+new file mode 100644
+index 0000000..8c23e31
+--- /dev/null
++++ b/sound/pci/oxygen/wm8785.h
+@@ -0,0 +1,45 @@
++#ifndef WM8785_H_INCLUDED
++#define WM8785_H_INCLUDED
++
++#define WM8785_R0 0
++#define WM8785_R1 1
++#define WM8785_R2 2
++#define WM8785_R7 7
++
++/* R0 */
++#define WM8785_MCR_MASK 0x007
++#define WM8785_MCR_SLAVE 0x000
++#define WM8785_MCR_MASTER_128 0x001
++#define WM8785_MCR_MASTER_192 0x002
++#define WM8785_MCR_MASTER_256 0x003
++#define WM8785_MCR_MASTER_384 0x004
++#define WM8785_MCR_MASTER_512 0x005
++#define WM8785_MCR_MASTER_768 0x006
++#define WM8785_OSR_MASK 0x018
++#define WM8785_OSR_SINGLE 0x000
++#define WM8785_OSR_DOUBLE 0x008
++#define WM8785_OSR_QUAD 0x010
++#define WM8785_FORMAT_MASK 0x060
++#define WM8785_FORMAT_RJUST 0x000
++#define WM8785_FORMAT_LJUST 0x020
++#define WM8785_FORMAT_I2S 0x040
++#define WM8785_FORMAT_DSP 0x060
++/* R1 */
++#define WM8785_WL_MASK 0x003
++#define WM8785_WL_16 0x000
++#define WM8785_WL_20 0x001
++#define WM8785_WL_24 0x002
++#define WM8785_WL_32 0x003
++#define WM8785_LRP 0x004
++#define WM8785_BCLKINV 0x008
++#define WM8785_LRSWAP 0x010
++#define WM8785_DEVNO_MASK 0x0e0
++/* R2 */
++#define WM8785_HPFR 0x001
++#define WM8785_HPFL 0x002
++#define WM8785_SDODIS 0x004
++#define WM8785_PWRDNR 0x008
++#define WM8785_PWRDNL 0x010
++#define WM8785_TDM_MASK 0x1c0
++
++#endif
+diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
+index 9d5bb76..7fdcdc8 100644
+--- a/sound/pci/pcxhr/pcxhr.c
++++ b/sound/pci/pcxhr/pcxhr.c
+@@ -458,7 +458,7 @@ static int pcxhr_update_r_buffer(struct pcxhr_stream *stream)
+
+ snd_printdd("pcxhr_update_r_buffer(pcm%c%d) : addr(%p) bytes(%zx) subs(%d)\n",
+ is_capture ? 'c' : 'p',
+- chip->chip_idx, (void*)subs->runtime->dma_addr,
++ chip->chip_idx, (void *)(long)subs->runtime->dma_addr,
+ subs->runtime->dma_bytes, subs->number);
+
+ pcxhr_init_rmh(&rmh, CMD_UPDATE_R_BUFFERS);
+@@ -626,7 +626,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
+ #ifdef CONFIG_SND_DEBUG_DETECT
+ do_gettimeofday(&my_tv2);
+ snd_printdd("***TRIGGER TASKLET*** TIME = %ld (err = %x)\n",
+- my_tv2.tv_usec - my_tv1.tv_usec, err);
++ (long)(my_tv2.tv_usec - my_tv1.tv_usec), err);
+ #endif
+ }
+
+@@ -846,7 +846,6 @@ static int pcxhr_open(struct snd_pcm_substream *subs)
+ struct pcxhr_mgr *mgr = chip->mgr;
+ struct snd_pcm_runtime *runtime = subs->runtime;
+ struct pcxhr_stream *stream;
+- int is_capture;
+
+ mutex_lock(&mgr->setup_mutex);
+
+@@ -856,12 +855,10 @@ static int pcxhr_open(struct snd_pcm_substream *subs)
+ if( subs->stream == SNDRV_PCM_STREAM_PLAYBACK ) {
+ snd_printdd("pcxhr_open playback chip%d subs%d\n",
+ chip->chip_idx, subs->number);
+- is_capture = 0;
+ stream = &chip->playback_stream[subs->number];
+ } else {
+ snd_printdd("pcxhr_open capture chip%d subs%d\n",
+ chip->chip_idx, subs->number);
+- is_capture = 1;
+ if (mgr->mono_capture)
+ runtime->hw.channels_max = 1;
+ else
+diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c
+index c4e415d..78aa81f 100644
+--- a/sound/pci/pcxhr/pcxhr_core.c
++++ b/sound/pci/pcxhr/pcxhr_core.c
+@@ -897,7 +897,7 @@ int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, int capture_m
+ #ifdef CONFIG_SND_DEBUG_DETECT
+ do_gettimeofday(&my_tv2);
+ snd_printdd("***SET PIPE STATE*** TIME = %ld (err = %x)\n",
+- my_tv2.tv_usec - my_tv1.tv_usec, err);
++ (long)(my_tv2.tv_usec - my_tv1.tv_usec), err);
+ #endif
+ return 0;
+ }
+@@ -1005,30 +1005,37 @@ void pcxhr_msg_tasklet(unsigned long arg)
+ int nb_stream = (prmh->stat[i] >> (2*FIELD_SIZE)) & MASK_FIRST_FIELD;
+ int pipe = prmh->stat[i] & MASK_FIRST_FIELD;
+ int is_capture = prmh->stat[i] & 0x400000;
+- u32 err;
++ u32 err2;
+
+ if (prmh->stat[i] & 0x800000) { /* if BIT_END */
+ snd_printdd("TASKLET : End%sPipe %d\n",
+ is_capture ? "Record" : "Play", pipe);
+ }
+ i++;
+- err = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1];
+- if (err)
+- pcxhr_handle_async_err(mgr, err, PCXHR_ERR_PIPE,
++ err2 = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1];
++ if (err2)
++ pcxhr_handle_async_err(mgr, err2,
++ PCXHR_ERR_PIPE,
+ pipe, is_capture);
+ i += 2;
+ for (j = 0; j < nb_stream; j++) {
+- err = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1];
+- if (err)
+- pcxhr_handle_async_err(mgr, err, PCXHR_ERR_STREAM,
+- pipe, is_capture);
++ err2 = prmh->stat[i] ?
++ prmh->stat[i] : prmh->stat[i+1];
++ if (err2)
++ pcxhr_handle_async_err(mgr, err2,
++ PCXHR_ERR_STREAM,
++ pipe,
++ is_capture);
+ i += 2;
+ }
+ for (j = 0; j < nb_audio; j++) {
+- err = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1];
+- if (err)
+- pcxhr_handle_async_err(mgr, err, PCXHR_ERR_AUDIO,
+- pipe, is_capture);
++ err2 = prmh->stat[i] ?
++ prmh->stat[i] : prmh->stat[i+1];
++ if (err2)
++ pcxhr_handle_async_err(mgr, err2,
++ PCXHR_ERR_AUDIO,
++ pipe,
++ is_capture);
+ i += 2;
+ }
+ }
+diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
+index 9408b1e..979f7da 100644
+--- a/sound/pci/riptide/riptide.c
++++ b/sound/pci/riptide/riptide.c
+@@ -1630,14 +1630,14 @@ static int snd_riptide_playback_open(struct snd_pcm_substream *substream)
+ struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct pcmhw *data;
+- int index = substream->number;
++ int sub_num = substream->number;
+
+- chip->playback_substream[index] = substream;
++ chip->playback_substream[sub_num] = substream;
+ runtime->hw = snd_riptide_playback;
+ data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL);
+- data->paths = lbus_play_paths[index];
+- data->id = play_ids[index];
+- data->source = play_sources[index];
++ data->paths = lbus_play_paths[sub_num];
++ data->id = play_ids[sub_num];
++ data->source = play_sources[sub_num];
+ data->intdec[0] = 0xff;
+ data->intdec[1] = 0xff;
+ data->state = ST_STOP;
+@@ -1670,10 +1670,10 @@ static int snd_riptide_playback_close(struct snd_pcm_substream *substream)
+ {
+ struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+ struct pcmhw *data = get_pcmhwdev(substream);
+- int index = substream->number;
++ int sub_num = substream->number;
+
+ substream->runtime->private_data = NULL;
+- chip->playback_substream[index] = NULL;
++ chip->playback_substream[sub_num] = NULL;
+ kfree(data);
+ return 0;
+ }
+diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
+index df184aa..e7ef3a1 100644
+--- a/sound/pci/rme32.c
++++ b/sound/pci/rme32.c
+@@ -1350,7 +1350,8 @@ static int __devinit snd_rme32_create(struct rme32 * rme32)
+ return err;
+ rme32->port = pci_resource_start(rme32->pci, 0);
+
+- if ((rme32->iobase = ioremap_nocache(rme32->port, RME32_IO_SIZE)) == 0) {
++ rme32->iobase = ioremap_nocache(rme32->port, RME32_IO_SIZE);
++ if (!rme32->iobase) {
+ snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n",
+ rme32->port, rme32->port + RME32_IO_SIZE - 1);
+ return -ENOMEM;
+diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
+index fb0a4ee..3fdd488 100644
+--- a/sound/pci/rme96.c
++++ b/sound/pci/rme96.c
+@@ -1559,7 +1559,8 @@ snd_rme96_create(struct rme96 *rme96)
+ return err;
+ rme96->port = pci_resource_start(rme96->pci, 0);
+
+- if ((rme96->iobase = ioremap_nocache(rme96->port, RME96_IO_SIZE)) == 0) {
++ rme96->iobase = ioremap_nocache(rme96->port, RME96_IO_SIZE);
++ if (!rme96->iobase) {
+ snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", rme96->port, rme96->port + RME96_IO_SIZE - 1);
+ return -ENOMEM;
+ }
+diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
+index 1be84f2..4d6fbb3 100644
+--- a/sound/pci/rme9652/hdsp.c
++++ b/sound/pci/rme9652/hdsp.c
+@@ -318,6 +318,10 @@ MODULE_FIRMWARE("digiface_firmware_rev11.bin");
+ #define HDSP_midi1IRQPending (1<<31)
+
+ #define HDSP_spdifFrequencyMask (HDSP_spdifFrequency0|HDSP_spdifFrequency1|HDSP_spdifFrequency2)
++#define HDSP_spdifFrequencyMask_9632 (HDSP_spdifFrequency0|\
++ HDSP_spdifFrequency1|\
++ HDSP_spdifFrequency2|\
++ HDSP_spdifFrequency3)
+
+ #define HDSP_spdifFrequency32KHz (HDSP_spdifFrequency0)
+ #define HDSP_spdifFrequency44_1KHz (HDSP_spdifFrequency1)
+@@ -328,7 +332,9 @@ MODULE_FIRMWARE("digiface_firmware_rev11.bin");
+ #define HDSP_spdifFrequency96KHz (HDSP_spdifFrequency2|HDSP_spdifFrequency1)
+
+ /* This is for H9632 cards */
+-#define HDSP_spdifFrequency128KHz HDSP_spdifFrequencyMask
++#define HDSP_spdifFrequency128KHz (HDSP_spdifFrequency0|\
++ HDSP_spdifFrequency1|\
++ HDSP_spdifFrequency2)
+ #define HDSP_spdifFrequency176_4KHz HDSP_spdifFrequency3
+ #define HDSP_spdifFrequency192KHz (HDSP_spdifFrequency3|HDSP_spdifFrequency0)
+
+@@ -885,28 +891,15 @@ static int snd_hdsp_use_is_exclusive(struct hdsp *hdsp)
+ return ret;
+ }
+
+-static int hdsp_external_sample_rate (struct hdsp *hdsp)
+-{
+- unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
+- unsigned int rate_bits = status2 & HDSP_systemFrequencyMask;
+-
+- switch (rate_bits) {
+- case HDSP_systemFrequency32: return 32000;
+- case HDSP_systemFrequency44_1: return 44100;
+- case HDSP_systemFrequency48: return 48000;
+- case HDSP_systemFrequency64: return 64000;
+- case HDSP_systemFrequency88_2: return 88200;
+- case HDSP_systemFrequency96: return 96000;
+- default:
+- return 0;
+- }
+-}
+-
+ static int hdsp_spdif_sample_rate(struct hdsp *hdsp)
+ {
+ unsigned int status = hdsp_read(hdsp, HDSP_statusRegister);
+ unsigned int rate_bits = (status & HDSP_spdifFrequencyMask);
+
++ /* For the 9632, the mask is different */
++ if (hdsp->io_type == H9632)
++ rate_bits = (status & HDSP_spdifFrequencyMask_9632);
++
+ if (status & HDSP_SPDIFErrorFlag)
+ return 0;
+
+@@ -933,6 +926,31 @@ static int hdsp_spdif_sample_rate(struct hdsp *hdsp)
+ return 0;
+ }
+
++static int hdsp_external_sample_rate(struct hdsp *hdsp)
++{
++ unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
++ unsigned int rate_bits = status2 & HDSP_systemFrequencyMask;
++
++ /* For the 9632 card, there seems to be no bit for indicating external
++ * sample rate greater than 96kHz. The card reports the corresponding
++ * single speed. So the best means seems to get spdif rate when
++ * autosync reference is spdif */
++ if (hdsp->io_type == H9632 &&
++ hdsp_autosync_ref(hdsp) == HDSP_AUTOSYNC_FROM_SPDIF)
++ return hdsp_spdif_sample_rate(hdsp);
++
++ switch (rate_bits) {
++ case HDSP_systemFrequency32: return 32000;
++ case HDSP_systemFrequency44_1: return 44100;
++ case HDSP_systemFrequency48: return 48000;
++ case HDSP_systemFrequency64: return 64000;
++ case HDSP_systemFrequency88_2: return 88200;
++ case HDSP_systemFrequency96: return 96000;
++ default:
++ return 0;
++ }
++}
++
+ static void hdsp_compute_period_size(struct hdsp *hdsp)
+ {
+ hdsp->period_bytes = 1 << ((hdsp_decode_latency(hdsp->control_register) + 8));
+diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
+index 9a19ae6..ab423bc 100644
+--- a/sound/pci/rme9652/hdspm.c
++++ b/sound/pci/rme9652/hdspm.c
+@@ -540,7 +540,8 @@ static void hdspm_set_sgbuf(struct hdspm * hdspm, struct snd_sg_buf *sgbuf,
+
+ static inline int HDSPM_bit2freq(int n)
+ {
+- static int bit2freq_tab[] = { 0, 32000, 44100, 48000, 64000, 88200,
++ static const int bit2freq_tab[] = {
++ 0, 32000, 44100, 48000, 64000, 88200,
+ 96000, 128000, 176400, 192000 };
+ if (n < 1 || n > 9)
+ return 0;
+@@ -582,7 +583,7 @@ static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,
+ return hdspm->mixer->ch[chan].pb[pb];
+ }
+
+-static inline int hdspm_write_in_gain(struct hdspm * hdspm, unsigned int chan,
++static int hdspm_write_in_gain(struct hdspm *hdspm, unsigned int chan,
+ unsigned int in, unsigned short data)
+ {
+ if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
+@@ -595,7 +596,7 @@ static inline int hdspm_write_in_gain(struct hdspm * hdspm, unsigned int chan,
+ return 0;
+ }
+
+-static inline int hdspm_write_pb_gain(struct hdspm * hdspm, unsigned int chan,
++static int hdspm_write_pb_gain(struct hdspm *hdspm, unsigned int chan,
+ unsigned int pb, unsigned short data)
+ {
+ if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
+@@ -621,7 +622,7 @@ static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v)
+ }
+
+ /* check if same process is writing and reading */
+-static inline int snd_hdspm_use_is_exclusive(struct hdspm * hdspm)
++static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm)
+ {
+ unsigned long flags;
+ int ret = 1;
+@@ -636,7 +637,7 @@ static inline int snd_hdspm_use_is_exclusive(struct hdspm * hdspm)
+ }
+
+ /* check for external sample rate */
+-static inline int hdspm_external_sample_rate(struct hdspm * hdspm)
++static int hdspm_external_sample_rate(struct hdspm *hdspm)
+ {
+ if (hdspm->is_aes32) {
+ unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+@@ -787,7 +788,7 @@ static inline void hdspm_stop_audio(struct hdspm * s)
+ }
+
+ /* should I silence all or only opened ones ? doit all for first even is 4MB*/
+-static inline void hdspm_silence_playback(struct hdspm * hdspm)
++static void hdspm_silence_playback(struct hdspm *hdspm)
+ {
+ int i;
+ int n = hdspm->period_bytes;
+@@ -1028,9 +1029,9 @@ static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id,
+ {
+ /* the hardware already does the relevant bit-mask with 0xff */
+ if (id)
+- return hdspm_write(hdspm, HDSPM_midiDataOut1, val);
++ hdspm_write(hdspm, HDSPM_midiDataOut1, val);
+ else
+- return hdspm_write(hdspm, HDSPM_midiDataOut0, val);
++ hdspm_write(hdspm, HDSPM_midiDataOut0, val);
+ }
+
+ static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
+@@ -1057,7 +1058,7 @@ static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
+ return 0;
+ }
+
+-static inline void snd_hdspm_flush_midi_input (struct hdspm *hdspm, int id)
++static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id)
+ {
+ while (snd_hdspm_midi_input_available (hdspm, id))
+ snd_hdspm_midi_read_byte (hdspm, id);
+diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c
+index dcd7cd0..df2007e 100644
+--- a/sound/pci/sis7019.c
++++ b/sound/pci/sis7019.c
+@@ -920,7 +920,7 @@ static unsigned short sis_ac97_rw(struct sis7019 *sis, int codec, u32 cmd)
+ u16 status;
+ u16 rdy;
+ int count;
+- const static u16 codec_ready[3] = {
++ static const u16 codec_ready[3] = {
+ SIS_AC97_STATUS_CODEC_READY,
+ SIS_AC97_STATUS_CODEC2_READY,
+ SIS_AC97_STATUS_CODEC3_READY,
+@@ -984,7 +984,7 @@ timeout:
+ static void sis_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
+ unsigned short val)
+ {
+- const static u32 cmd[3] = {
++ static const u32 cmd[3] = {
+ SIS_AC97_CMD_CODEC_WRITE,
+ SIS_AC97_CMD_CODEC2_WRITE,
+ SIS_AC97_CMD_CODEC3_WRITE,
+@@ -995,7 +995,7 @@ static void sis_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
+
+ static unsigned short sis_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
+ {
+- const static u32 cmd[3] = {
++ static const u32 cmd[3] = {
+ SIS_AC97_CMD_CODEC_READ,
+ SIS_AC97_CMD_CODEC2_READ,
+ SIS_AC97_CMD_CODEC3_READ,
+@@ -1194,7 +1194,6 @@ static int sis_suspend(struct pci_dev *pci, pm_message_t state)
+ /* snd_pcm_suspend_all() stopped all channels, so we're quiescent.
+ */
+ if (sis->irq >= 0) {
+- synchronize_irq(sis->irq);
+ free_irq(sis->irq, sis);
+ sis->irq = -1;
+ }
+diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
+index 71138ff..bbcee2c 100644
+--- a/sound/pci/trident/trident_main.c
++++ b/sound/pci/trident/trident_main.c
+@@ -3676,6 +3676,8 @@ static int snd_trident_free(struct snd_trident *trident)
+ else if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
+ outl(0, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
+ }
++ if (trident->irq >= 0)
++ free_irq(trident->irq, trident);
+ if (trident->tlb.buffer.area) {
+ outl(0, TRID_REG(trident, NX_TLBC));
+ if (trident->tlb.memhdr)
+@@ -3685,8 +3687,6 @@ static int snd_trident_free(struct snd_trident *trident)
+ vfree(trident->tlb.shadow_entries);
+ snd_dma_free_pages(&trident->tlb.buffer);
+ }
+- if (trident->irq >= 0)
+- free_irq(trident->irq, trident);
+ pci_release_regions(trident->pci);
+ pci_disable_device(trident->pci);
+ kfree(trident);
+diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
+index a756be6..b585cc3 100644
+--- a/sound/pci/via82xx.c
++++ b/sound/pci/via82xx.c
+@@ -2236,7 +2236,7 @@ static int snd_via82xx_free(struct via82xx *chip)
+ /* disable interrupts */
+ for (i = 0; i < chip->num_devs; i++)
+ snd_via82xx_channel_reset(chip, &chip->devs[i]);
+- synchronize_irq(chip->irq);
++
+ if (chip->irq >= 0)
+ free_irq(chip->irq, chip);
+ __end_hw:
+diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
+index f5df1c7..31f64ee 100644
+--- a/sound/pci/via82xx_modem.c
++++ b/sound/pci/via82xx_modem.c
+@@ -1075,7 +1075,7 @@ static int snd_via82xx_free(struct via82xx_modem *chip)
+ /* disable interrupts */
+ for (i = 0; i < chip->num_devs; i++)
+ snd_via82xx_channel_reset(chip, &chip->devs[i]);
+- synchronize_irq(chip->irq);
++
+ __end_hw:
+ if (chip->irq >= 0)
+ free_irq(chip->irq, chip);
+diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
+index 42c1eb7..29b3056 100644
+--- a/sound/pci/ymfpci/ymfpci_main.c
++++ b/sound/pci/ymfpci/ymfpci_main.c
+@@ -2249,6 +2249,8 @@ static int snd_ymfpci_free(struct snd_ymfpci *chip)
+ #ifdef CONFIG_PM
+ vfree(chip->saved_regs);
+ #endif
++ if (chip->irq >= 0)
++ free_irq(chip->irq, chip);
+ release_and_free_resource(chip->mpu_res);
+ release_and_free_resource(chip->fm_res);
+ snd_ymfpci_free_gameport(chip);
+@@ -2257,8 +2259,6 @@ static int snd_ymfpci_free(struct snd_ymfpci *chip)
+ if (chip->work_ptr.area)
+ snd_dma_free_pages(&chip->work_ptr);
+
+- if (chip->irq >= 0)
+- free_irq(chip->irq, chip);
+ release_and_free_resource(chip->res_reg_area);
+
+ pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl);
+diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c
+index 8441e78..566a6d0 100644
+--- a/sound/ppc/awacs.c
++++ b/sound/ppc/awacs.c
+@@ -141,7 +141,7 @@ static int snd_pmac_awacs_info_volume(struct snd_kcontrol *kcontrol,
+ uinfo->value.integer.max = 15;
+ return 0;
+ }
+-
++
+ static int snd_pmac_awacs_get_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+ {
+@@ -267,7 +267,8 @@ static int snd_pmac_awacs_put_switch(struct snd_kcontrol *kcontrol,
+ static void awacs_set_cuda(int reg, int val)
+ {
+ struct adb_request req;
+- cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, 0x8a, reg, val);
++ cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, 0x8a,
++ reg, val);
+ while (! req.complete)
+ cuda_poll();
+ }
+@@ -289,11 +290,11 @@ static void awacs_amp_set_tone(struct awacs_amp *amp, int bass, int treble)
+ /*
+ * vol = 0 - 31 (attenuation), 32 = mute bit, stereo
+ */
+-static int awacs_amp_set_vol(struct awacs_amp *amp, int index, int lvol, int rvol,
+- int do_check)
++static int awacs_amp_set_vol(struct awacs_amp *amp, int index,
++ int lvol, int rvol, int do_check)
+ {
+ if (do_check && amp->amp_vol[index][0] == lvol &&
+- amp->amp_vol[index][1] == rvol)
++ amp->amp_vol[index][1] == rvol)
+ return 0;
+ awacs_set_cuda(3 + index, lvol);
+ awacs_set_cuda(5 + index, rvol);
+@@ -337,7 +338,7 @@ static int snd_pmac_awacs_info_volume_amp(struct snd_kcontrol *kcontrol,
+ uinfo->value.integer.max = 31;
+ return 0;
+ }
+-
++
+ static int snd_pmac_awacs_get_volume_amp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+ {
+@@ -361,8 +362,10 @@ static int snd_pmac_awacs_put_volume_amp(struct snd_kcontrol *kcontrol,
+ snd_assert(amp, return -EINVAL);
+ snd_assert(index >= 0 && index <= 1, return -EINVAL);
+
+- vol[0] = (31 - (ucontrol->value.integer.value[0] & 31)) | (amp->amp_vol[index][0] & 32);
+- vol[1] = (31 - (ucontrol->value.integer.value[1] & 31)) | (amp->amp_vol[index][1] & 32);
++ vol[0] = (31 - (ucontrol->value.integer.value[0] & 31))
++ | (amp->amp_vol[index][0] & 32);
++ vol[1] = (31 - (ucontrol->value.integer.value[1] & 31))
++ | (amp->amp_vol[index][1] & 32);
+ return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1);
+ }
+
+@@ -374,8 +377,10 @@ static int snd_pmac_awacs_get_switch_amp(struct snd_kcontrol *kcontrol,
+ struct awacs_amp *amp = chip->mixer_data;
+ snd_assert(amp, return -EINVAL);
+ snd_assert(index >= 0 && index <= 1, return -EINVAL);
+- ucontrol->value.integer.value[0] = (amp->amp_vol[index][0] & 32) ? 0 : 1;
+- ucontrol->value.integer.value[1] = (amp->amp_vol[index][1] & 32) ? 0 : 1;
++ ucontrol->value.integer.value[0] = (amp->amp_vol[index][0] & 32)
++ ? 0 : 1;
++ ucontrol->value.integer.value[1] = (amp->amp_vol[index][1] & 32)
++ ? 0 : 1;
+ return 0;
+ }
+
+@@ -389,8 +394,10 @@ static int snd_pmac_awacs_put_switch_amp(struct snd_kcontrol *kcontrol,
+ snd_assert(amp, return -EINVAL);
+ snd_assert(index >= 0 && index <= 1, return -EINVAL);
+
+- vol[0] = (ucontrol->value.integer.value[0] ? 0 : 32) | (amp->amp_vol[index][0] & 31);
+- vol[1] = (ucontrol->value.integer.value[1] ? 0 : 32) | (amp->amp_vol[index][1] & 31);
++ vol[0] = (ucontrol->value.integer.value[0] ? 0 : 32)
++ | (amp->amp_vol[index][0] & 31);
++ vol[1] = (ucontrol->value.integer.value[1] ? 0 : 32)
++ | (amp->amp_vol[index][1] & 31);
+ return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1);
+ }
+
+@@ -403,7 +410,7 @@ static int snd_pmac_awacs_info_tone_amp(struct snd_kcontrol *kcontrol,
+ uinfo->value.integer.max = 14;
+ return 0;
+ }
+-
++
+ static int snd_pmac_awacs_get_tone_amp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+ {
+@@ -445,7 +452,7 @@ static int snd_pmac_awacs_info_master_amp(struct snd_kcontrol *kcontrol,
+ uinfo->value.integer.max = 99;
+ return 0;
+ }
+-
++
+ static int snd_pmac_awacs_get_master_amp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+ {
+@@ -544,7 +551,7 @@ static int snd_pmac_screamer_mic_boost_info(struct snd_kcontrol *kcontrol,
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+- uinfo->value.integer.max = 2;
++ uinfo->value.integer.max = 3;
+ return 0;
+ }
+
+@@ -552,16 +559,14 @@ static int snd_pmac_screamer_mic_boost_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+ {
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+- int val;
++ int val = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ if (chip->awacs_reg[6] & MASK_MIC_BOOST)
+- val = 2;
+- else if (chip->awacs_reg[0] & MASK_GAINLINE)
+- val = 1;
+- else
+- val = 0;
++ val |= 2;
++ if (chip->awacs_reg[0] & MASK_GAINLINE)
++ val |= 1;
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ ucontrol->value.integer.value[0] = val;
+ return 0;
+@@ -578,11 +583,10 @@ static int snd_pmac_screamer_mic_boost_put(struct snd_kcontrol *kcontrol,
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ val0 = chip->awacs_reg[0] & ~MASK_GAINLINE;
+ val6 = chip->awacs_reg[6] & ~MASK_MIC_BOOST;
+- if (ucontrol->value.integer.value[0] > 0) {
++ if (ucontrol->value.integer.value[0] & 1)
+ val0 |= MASK_GAINLINE;
+- if (ucontrol->value.integer.value[0] > 1)
+- val6 |= MASK_MIC_BOOST;
+- }
++ if (ucontrol->value.integer.value[0] & 2)
++ val6 |= MASK_MIC_BOOST;
+ if (val0 != chip->awacs_reg[0]) {
+ snd_pmac_awacs_write_reg(chip, 0, val0);
+ changed = 1;
+@@ -599,9 +603,32 @@ static int snd_pmac_screamer_mic_boost_put(struct snd_kcontrol *kcontrol,
+ * lists of mixer elements
+ */
+ static struct snd_kcontrol_new snd_pmac_awacs_mixers[] __initdata = {
+- AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
+ AWACS_SWITCH("Master Capture Switch", 1, SHIFT_LOOPTHRU, 0),
+- AWACS_VOLUME("Capture Volume", 0, 4, 0),
++ AWACS_VOLUME("Master Capture Volume", 0, 4, 0),
++/* AWACS_SWITCH("Unknown Playback Switch", 6, SHIFT_PAROUT0, 0), */
++};
++
++static struct snd_kcontrol_new snd_pmac_screamer_mixers_beige[] __initdata = {
++ AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
++ AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1),
++ AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
++ AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_LINE, 0),
++};
++
++static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] __initdata = {
++ AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
++ AWACS_VOLUME("Master Playback Volume", 5, 6, 1),
++ AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
++};
++
++static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac7500[] __initdata = {
++ AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
++ AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
++ AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
++};
++
++static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] __initdata = {
++ AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
+ AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
+ };
+
+@@ -621,35 +648,61 @@ static struct snd_kcontrol_new snd_pmac_screamer_mixers2[] __initdata = {
+ static struct snd_kcontrol_new snd_pmac_awacs_master_sw __initdata =
+ AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1);
+
++static struct snd_kcontrol_new snd_pmac_awacs_master_sw_imac __initdata =
++AWACS_SWITCH("Line out Playback Switch", 1, SHIFT_HDMUTE, 1);
++
+ static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] __initdata = {
+- AWACS_SWITCH("Mic Boost", 0, SHIFT_GAINLINE, 0),
++ AWACS_SWITCH("Mic Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
+ };
+
+ static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] __initdata = {
+ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+- .name = "Mic Boost",
++ .name = "Mic Boost Capture Volume",
+ .info = snd_pmac_screamer_mic_boost_info,
+ .get = snd_pmac_screamer_mic_boost_get,
+ .put = snd_pmac_screamer_mic_boost_put,
+ },
+ };
+
++static struct snd_kcontrol_new snd_pmac_awacs_mic_boost_pmac7500[] __initdata =
++{
++ AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
++};
++
++static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_beige[] __initdata =
++{
++ AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
++ AWACS_SWITCH("CD Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0),
++};
++
++static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_imac[] __initdata =
++{
++ AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
++ AWACS_SWITCH("Mic Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0),
++};
++
+ static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] __initdata = {
+ AWACS_VOLUME("PC Speaker Playback Volume", 4, 6, 1),
+ };
++
+ static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw __initdata =
+ AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1);
+
++static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac __initdata =
++AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_PAROUT1, 0);
++
+
+ /*
+ * add new mixer elements to the card
+ */
+-static int build_mixers(struct snd_pmac *chip, int nums, struct snd_kcontrol_new *mixers)
++static int build_mixers(struct snd_pmac *chip, int nums,
++ struct snd_kcontrol_new *mixers)
+ {
+ int i, err;
+
+ for (i = 0; i < nums; i++) {
+- if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&mixers[i], chip))) < 0)
++ err = snd_ctl_add(chip->card, snd_ctl_new1(&mixers[i], chip));
++ if (err < 0)
+ return err;
+ }
+ return 0;
+@@ -699,8 +752,10 @@ static void snd_pmac_awacs_resume(struct snd_pmac *chip)
+ #ifdef PMAC_AMP_AVAIL
+ if (chip->mixer_data) {
+ struct awacs_amp *amp = chip->mixer_data;
+- awacs_amp_set_vol(amp, 0, amp->amp_vol[0][0], amp->amp_vol[0][1], 0);
+- awacs_amp_set_vol(amp, 1, amp->amp_vol[1][0], amp->amp_vol[1][1], 0);
++ awacs_amp_set_vol(amp, 0,
++ amp->amp_vol[0][0], amp->amp_vol[0][1], 0);
++ awacs_amp_set_vol(amp, 1,
++ amp->amp_vol[1][0], amp->amp_vol[1][1], 0);
+ awacs_amp_set_tone(amp, amp->amp_tone[0], amp->amp_tone[1]);
+ awacs_amp_set_master(amp, amp->amp_master);
+ }
+@@ -708,6 +763,14 @@ static void snd_pmac_awacs_resume(struct snd_pmac *chip)
+ }
+ #endif /* CONFIG_PM */
+
++#define IS_PM7500 (machine_is_compatible("AAPL,7500"))
++#define IS_BEIGE (machine_is_compatible("AAPL,Gossamer"))
++#define IS_IMAC (machine_is_compatible("PowerMac2,1") \
++ || machine_is_compatible("PowerMac2,2") \
++ || machine_is_compatible("PowerMac4,1"))
++
++static int imac;
++
+ #ifdef PMAC_SUPPORT_AUTOMUTE
+ /*
+ * auto-mute stuffs
+@@ -750,9 +813,16 @@ static void snd_pmac_awacs_update_automute(struct snd_pmac *chip, int do_notify)
+ } else
+ #endif
+ {
+- int reg = chip->awacs_reg[1] | (MASK_HDMUTE|MASK_SPKMUTE);
++ int reg = chip->awacs_reg[1]
++ | (MASK_HDMUTE | MASK_SPKMUTE);
++ if (imac) {
++ reg &= ~MASK_SPKMUTE;
++ reg &= ~MASK_PAROUT1;
++ }
+ if (snd_pmac_awacs_detect_headphone(chip))
+ reg &= ~MASK_HDMUTE;
++ else if (imac)
++ reg |= MASK_PAROUT1;
+ else
+ reg &= ~MASK_SPKMUTE;
+ if (do_notify && reg == chip->awacs_reg[1])
+@@ -778,8 +848,11 @@ static void snd_pmac_awacs_update_automute(struct snd_pmac *chip, int do_notify)
+ int __init
+ snd_pmac_awacs_init(struct snd_pmac *chip)
+ {
++ int pm7500 = IS_PM7500;
++ int beige = IS_BEIGE;
+ int err, vol;
+
++ imac = IS_IMAC;
+ /* looks like MASK_GAINLINE triggers something, so we set here
+ * as start-up
+ */
+@@ -787,7 +860,7 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
+ chip->awacs_reg[1] = MASK_CMUTE | MASK_AMUTE;
+ /* FIXME: Only machines with external SRS module need MASK_PAROUT */
+ if (chip->has_iic || chip->device_id == 0x5 ||
+- /*chip->_device_id == 0x8 || */
++ /* chip->_device_id == 0x8 || */
+ chip->device_id == 0xb)
+ chip->awacs_reg[1] |= MASK_PAROUT;
+ /* get default volume from nvram */
+@@ -798,8 +871,10 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
+ chip->awacs_reg[2] = vol;
+ chip->awacs_reg[4] = vol;
+ if (chip->model == PMAC_SCREAMER) {
+- chip->awacs_reg[5] = vol; /* FIXME: screamer has loopthru vol control */
+- chip->awacs_reg[6] = MASK_MIC_BOOST; /* FIXME: maybe should be vol << 3 for PCMCIA speaker */
++ /* FIXME: screamer has loopthru vol control */
++ chip->awacs_reg[5] = vol;
++ /* FIXME: maybe should be vol << 3 for PCMCIA speaker */
++ chip->awacs_reg[6] = MASK_MIC_BOOST;
+ chip->awacs_reg[7] = 0;
+ }
+
+@@ -815,7 +890,8 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
+ return -ENOMEM;
+ chip->mixer_data = amp;
+ chip->mixer_free = awacs_amp_free;
+- awacs_amp_set_vol(amp, 0, 63, 63, 0); /* mute and zero vol */
++ /* mute and zero vol */
++ awacs_amp_set_vol(amp, 0, 63, 63, 0);
+ awacs_amp_set_vol(amp, 1, 63, 63, 0);
+ awacs_amp_set_tone(amp, 7, 7); /* 0 dB */
+ awacs_amp_set_master(amp, 79); /* 0 dB */
+@@ -826,20 +902,25 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
+ /* set headphone-jack detection bit */
+ switch (chip->model) {
+ case PMAC_AWACS:
+- chip->hp_stat_mask = 0x04;
++ chip->hp_stat_mask = pm7500 ? MASK_HDPCONN
++ : MASK_LOCONN;
+ break;
+ case PMAC_SCREAMER:
+ switch (chip->device_id) {
+ case 0x08:
+- /* 1 = side jack, 2 = front jack */
+- chip->hp_stat_mask = 0x03;
++ case 0x0B:
++ chip->hp_stat_mask = imac
++ ? MASK_LOCONN_IMAC |
++ MASK_HDPLCONN_IMAC |
++ MASK_HDPRCONN_IMAC
++ : MASK_HDPCONN;
+ break;
+ case 0x00:
+ case 0x05:
+- chip->hp_stat_mask = 0x04;
++ chip->hp_stat_mask = MASK_LOCONN;
+ break;
+ default:
+- chip->hp_stat_mask = 0x08;
++ chip->hp_stat_mask = MASK_HDPCONN;
+ break;
+ }
+ break;
+@@ -854,19 +935,43 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
+ */
+ strcpy(chip->card->mixername, "PowerMac AWACS");
+
+- if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers),
+- snd_pmac_awacs_mixers)) < 0)
++ err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers),
++ snd_pmac_awacs_mixers);
++ if (err < 0)
+ return err;
+- if (chip->model == PMAC_SCREAMER)
++ if (beige)
++ ;
++ else if (chip->model == PMAC_SCREAMER)
+ err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mixers2),
+ snd_pmac_screamer_mixers2);
+- else
++ else if (!pm7500)
+ err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers2),
+ snd_pmac_awacs_mixers2);
+ if (err < 0)
+ return err;
+- chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_master_sw, chip);
+- if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
++ if (pm7500)
++ err = build_mixers(chip,
++ ARRAY_SIZE(snd_pmac_awacs_mixers_pmac7500),
++ snd_pmac_awacs_mixers_pmac7500);
++ else if (beige)
++ err = build_mixers(chip,
++ ARRAY_SIZE(snd_pmac_screamer_mixers_beige),
++ snd_pmac_screamer_mixers_beige);
++ else if (imac)
++ err = build_mixers(chip,
++ ARRAY_SIZE(snd_pmac_screamer_mixers_imac),
++ snd_pmac_screamer_mixers_imac);
++ else
++ err = build_mixers(chip,
++ ARRAY_SIZE(snd_pmac_awacs_mixers_pmac),
++ snd_pmac_awacs_mixers_pmac);
++ if (err < 0)
++ return err;
++ chip->master_sw_ctl = snd_ctl_new1((pm7500 || imac)
++ ? &snd_pmac_awacs_master_sw_imac
++ : &snd_pmac_awacs_master_sw, chip);
++ err = snd_ctl_add(chip->card, chip->master_sw_ctl);
++ if (err < 0)
+ return err;
+ #ifdef PMAC_AMP_AVAIL
+ if (chip->mixer_data) {
+@@ -876,37 +981,58 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
+ * screamer registers.
+ * in this case, it seems the route C is not used.
+ */
+- if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_amp_vol),
+- snd_pmac_awacs_amp_vol)) < 0)
++ err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_amp_vol),
++ snd_pmac_awacs_amp_vol);
++ if (err < 0)
+ return err;
+ /* overwrite */
+- chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_hp_sw, chip);
+- if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
++ chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_hp_sw,
++ chip);
++ err = snd_ctl_add(chip->card, chip->master_sw_ctl);
++ if (err < 0)
+ return err;
+- chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_spk_sw, chip);
+- if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
++ chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_spk_sw,
++ chip);
++ err = snd_ctl_add(chip->card, chip->speaker_sw_ctl);
++ if (err < 0)
+ return err;
+ } else
+ #endif /* PMAC_AMP_AVAIL */
+ {
+ /* route A = headphone, route C = speaker */
+- if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_speaker_vol),
+- snd_pmac_awacs_speaker_vol)) < 0)
++ err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_speaker_vol),
++ snd_pmac_awacs_speaker_vol);
++ if (err < 0)
+ return err;
+- chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_speaker_sw, chip);
+- if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
++ chip->speaker_sw_ctl = snd_ctl_new1(imac
++ ? &snd_pmac_awacs_speaker_sw_imac
++ : &snd_pmac_awacs_speaker_sw, chip);
++ err = snd_ctl_add(chip->card, chip->speaker_sw_ctl);
++ if (err < 0)
+ return err;
+ }
+
+- if (chip->model == PMAC_SCREAMER) {
+- if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mic_boost),
+- snd_pmac_screamer_mic_boost)) < 0)
+- return err;
+- } else {
+- if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mic_boost),
+- snd_pmac_awacs_mic_boost)) < 0)
+- return err;
+- }
++ if (beige)
++ err = build_mixers(chip,
++ ARRAY_SIZE(snd_pmac_screamer_mic_boost_beige),
++ snd_pmac_screamer_mic_boost_beige);
++ else if (imac)
++ err = build_mixers(chip,
++ ARRAY_SIZE(snd_pmac_screamer_mic_boost_imac),
++ snd_pmac_screamer_mic_boost_imac);
++ else if (chip->model == PMAC_SCREAMER)
++ err = build_mixers(chip,
++ ARRAY_SIZE(snd_pmac_screamer_mic_boost),
++ snd_pmac_screamer_mic_boost);
++ else if (pm7500)
++ err = build_mixers(chip,
++ ARRAY_SIZE(snd_pmac_awacs_mic_boost_pmac7500),
++ snd_pmac_awacs_mic_boost_pmac7500);
++ else
++ err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mic_boost),
++ snd_pmac_awacs_mic_boost);
++ if (err < 0)
++ return err;
+
+ /*
+ * set lowlevel callbacks
+@@ -917,7 +1043,8 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
+ chip->resume = snd_pmac_awacs_resume;
+ #endif
+ #ifdef PMAC_SUPPORT_AUTOMUTE
+- if ((err = snd_pmac_add_automute(chip)) < 0)
++ err = snd_pmac_add_automute(chip);
++ if (err < 0)
+ return err;
+ chip->detect_headphone = snd_pmac_awacs_detect_headphone;
+ chip->update_automute = snd_pmac_awacs_update_automute;
+diff --git a/sound/ppc/awacs.h b/sound/ppc/awacs.h
+index 1b2cc44..c33e6a5 100644
+--- a/sound/ppc/awacs.h
++++ b/sound/ppc/awacs.h
+@@ -116,6 +116,11 @@ struct awacs_regs {
+ #define MASK_HDMUTE MASK_AMUTE
+ #define SHIFT_HDMUTE 9
+ #define MASK_PAROUT (0x3 << 10) /* Parallel Out (???) */
++#define MASK_PAROUT0 (0x1 << 10) /* Parallel Out (???) */
++#define MASK_PAROUT1 (0x1 << 11) /* Parallel Out (enable speaker) */
++#define SHIFT_PAROUT 10
++#define SHIFT_PAROUT0 10
++#define SHIFT_PAROUT1 11
+
+ #define SAMPLERATE_48000 (0x0 << 3) /* 48 or 44.1 kHz */
+ #define SAMPLERATE_32000 (0x1 << 3) /* 32 or 29.4 kHz */
+@@ -139,7 +144,7 @@ struct awacs_regs {
+ #define VOLLEFT(x) (((~(x)) << 6) & MASK_OUTVOLLEFT)
+
+ /* address 6 */
+-#define MASK_MIC_BOOST (0x4) /* screamer mic boost */
++#define MASK_MIC_BOOST (0x4) /* screamer mic boost */
+ #define SHIFT_MIC_BOOST 2
+
+ /* Audio Codec Status Reg Bit Masks */
+@@ -152,8 +157,15 @@ struct awacs_regs {
+ #define MASK_REVISION (0xf << 12) /* Revision Number */
+ #define MASK_MFGID (0xf << 8) /* Mfg. ID */
+ #define MASK_CODSTATRES (0xf << 4) /* bits 4 - 7 reserved */
+-#define MASK_INPPORT (0xf) /* Input Port */
+-#define MASK_HDPCONN 8 /* headphone plugged in */
++#define MASK_INSENSE (0xf) /* port sense bits: */
++#define MASK_HDPCONN 8 /* headphone plugged in */
++#define MASK_LOCONN 4 /* line-out plugged in */
++#define MASK_LICONN 2 /* line-in plugged in */
++#define MASK_MICCONN 1 /* microphone plugged in */
++#define MASK_LICONN_IMAC 8 /* line-in plugged in */
++#define MASK_HDPRCONN_IMAC 4 /* headphone right plugged in */
++#define MASK_HDPLCONN_IMAC 2 /* headphone left plugged in */
++#define MASK_LOCONN_IMAC 1 /* line-out plugged in */
+
+ /* Clipping Count Reg Bit Masks */
+ /* -------- ----- --- --- ----- */
+@@ -163,7 +175,8 @@ struct awacs_regs {
+ /* DBDMA ChannelStatus Bit Masks */
+ /* ----- ------------- --- ----- */
+ #define MASK_CSERR (0x1 << 7) /* Error */
+-#define MASK_EOI (0x1 << 6) /* End of Input -- only for Input Channel */
++#define MASK_EOI (0x1 << 6) /* End of Input --
++ only for Input Channel */
+ #define MASK_CSUNUSED (0x1f << 1) /* bits 1-5 not used */
+ #define MASK_WAIT (0x1) /* Wait */
+
+diff --git a/sound/ppc/burgundy.c b/sound/ppc/burgundy.c
+index 1a545ac..f860d39 100644
+--- a/sound/ppc/burgundy.c
++++ b/sound/ppc/burgundy.c
+@@ -102,7 +102,8 @@ snd_pmac_burgundy_rcw(struct snd_pmac *chip, unsigned addr)
+ }
+
+ static void
+-snd_pmac_burgundy_wcb(struct snd_pmac *chip, unsigned int addr, unsigned int val)
++snd_pmac_burgundy_wcb(struct snd_pmac *chip, unsigned int addr,
++ unsigned int val)
+ {
+ out_le32(&chip->awacs->codec_ctrl, addr + 0x300000 + (val & 0xff));
+ snd_pmac_burgundy_busy_wait(chip);
+@@ -126,8 +127,11 @@ snd_pmac_burgundy_rcb(struct snd_pmac *chip, unsigned int addr)
+ return val;
+ }
+
++#define BASE2ADDR(base) ((base) << 12)
++#define ADDR2BASE(addr) ((addr) >> 12)
++
+ /*
+- * Burgundy volume: 0 - 100, stereo
++ * Burgundy volume: 0 - 100, stereo, word reg
+ */
+ static void
+ snd_pmac_burgundy_write_volume(struct snd_pmac *chip, unsigned int address,
+@@ -168,13 +172,6 @@ snd_pmac_burgundy_read_volume(struct snd_pmac *chip, unsigned int address,
+ volume[1] = 0;
+ }
+
+-
+-/*
+- */
+-
+-#define BASE2ADDR(base) ((base) << 12)
+-#define ADDR2BASE(addr) ((addr) >> 12)
+-
+ static int snd_pmac_burgundy_info_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+ {
+@@ -191,8 +188,8 @@ static int snd_pmac_burgundy_get_volume(struct snd_kcontrol *kcontrol,
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
+ int shift = (kcontrol->private_value >> 8) & 0xff;
+- snd_pmac_burgundy_read_volume(chip, addr, ucontrol->value.integer.value,
+- shift);
++ snd_pmac_burgundy_read_volume(chip, addr,
++ ucontrol->value.integer.value, shift);
+ return 0;
+ }
+
+@@ -204,24 +201,163 @@ static int snd_pmac_burgundy_put_volume(struct snd_kcontrol *kcontrol,
+ int shift = (kcontrol->private_value >> 8) & 0xff;
+ long nvoices[2];
+
+- snd_pmac_burgundy_write_volume(chip, addr, ucontrol->value.integer.value,
+- shift);
++ snd_pmac_burgundy_write_volume(chip, addr,
++ ucontrol->value.integer.value, shift);
+ snd_pmac_burgundy_read_volume(chip, addr, nvoices, shift);
+ return (nvoices[0] != ucontrol->value.integer.value[0] ||
+ nvoices[1] != ucontrol->value.integer.value[1]);
+ }
+
+-#define BURGUNDY_VOLUME(xname, xindex, addr, shift) \
++#define BURGUNDY_VOLUME_W(xname, xindex, addr, shift) \
+ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
+ .info = snd_pmac_burgundy_info_volume,\
+ .get = snd_pmac_burgundy_get_volume,\
+ .put = snd_pmac_burgundy_put_volume,\
+ .private_value = ((ADDR2BASE(addr) & 0xff) | ((shift) << 8)) }
+
+-/* lineout/speaker */
++/*
++ * Burgundy volume: 0 - 100, stereo, 2-byte reg
++ */
++static void
++snd_pmac_burgundy_write_volume_2b(struct snd_pmac *chip, unsigned int address,
++ long *volume, int off)
++{
++ int lvolume, rvolume;
+
+-static int snd_pmac_burgundy_info_switch_out(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_info *uinfo)
++ off |= off << 2;
++ lvolume = volume[0] ? volume[0] + BURGUNDY_VOLUME_OFFSET : 0;
++ rvolume = volume[1] ? volume[1] + BURGUNDY_VOLUME_OFFSET : 0;
++
++ snd_pmac_burgundy_wcb(chip, address + off, lvolume);
++ snd_pmac_burgundy_wcb(chip, address + off + 0x500, rvolume);
++}
++
++static void
++snd_pmac_burgundy_read_volume_2b(struct snd_pmac *chip, unsigned int address,
++ long *volume, int off)
++{
++ volume[0] = snd_pmac_burgundy_rcb(chip, address + off);
++ if (volume[0] >= BURGUNDY_VOLUME_OFFSET)
++ volume[0] -= BURGUNDY_VOLUME_OFFSET;
++ else
++ volume[0] = 0;
++ volume[1] = snd_pmac_burgundy_rcb(chip, address + off + 0x100);
++ if (volume[1] >= BURGUNDY_VOLUME_OFFSET)
++ volume[1] -= BURGUNDY_VOLUME_OFFSET;
++ else
++ volume[1] = 0;
++}
++
++static int snd_pmac_burgundy_info_volume_2b(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++ uinfo->count = 2;
++ uinfo->value.integer.min = 0;
++ uinfo->value.integer.max = 100;
++ return 0;
++}
++
++static int snd_pmac_burgundy_get_volume_2b(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
++ unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
++ int off = kcontrol->private_value & 0x300;
++ snd_pmac_burgundy_read_volume_2b(chip, addr,
++ ucontrol->value.integer.value, off);
++ return 0;
++}
++
++static int snd_pmac_burgundy_put_volume_2b(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
++ unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
++ int off = kcontrol->private_value & 0x300;
++ long nvoices[2];
++
++ snd_pmac_burgundy_write_volume_2b(chip, addr,
++ ucontrol->value.integer.value, off);
++ snd_pmac_burgundy_read_volume_2b(chip, addr, nvoices, off);
++ return (nvoices[0] != ucontrol->value.integer.value[0] ||
++ nvoices[1] != ucontrol->value.integer.value[1]);
++}
++
++#define BURGUNDY_VOLUME_2B(xname, xindex, addr, off) \
++{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
++ .info = snd_pmac_burgundy_info_volume_2b,\
++ .get = snd_pmac_burgundy_get_volume_2b,\
++ .put = snd_pmac_burgundy_put_volume_2b,\
++ .private_value = ((ADDR2BASE(addr) & 0xff) | ((off) << 8)) }
++
++/*
++ * Burgundy gain/attenuation: 0 - 15, mono/stereo, byte reg
++ */
++static int snd_pmac_burgundy_info_gain(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++ int stereo = (kcontrol->private_value >> 24) & 1;
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++ uinfo->count = stereo + 1;
++ uinfo->value.integer.min = 0;
++ uinfo->value.integer.max = 15;
++ return 0;
++}
++
++static int snd_pmac_burgundy_get_gain(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
++ unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
++ int stereo = (kcontrol->private_value >> 24) & 1;
++ int atten = (kcontrol->private_value >> 25) & 1;
++ int oval;
++
++ oval = snd_pmac_burgundy_rcb(chip, addr);
++ if (atten)
++ oval = ~oval & 0xff;
++ ucontrol->value.integer.value[0] = oval & 0xf;
++ if (stereo)
++ ucontrol->value.integer.value[1] = (oval >> 4) & 0xf;
++ return 0;
++}
++
++static int snd_pmac_burgundy_put_gain(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
++ unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
++ int stereo = (kcontrol->private_value >> 24) & 1;
++ int atten = (kcontrol->private_value >> 25) & 1;
++ int oval, val;
++
++ oval = snd_pmac_burgundy_rcb(chip, addr);
++ if (atten)
++ oval = ~oval & 0xff;
++ val = ucontrol->value.integer.value[0];
++ if (stereo)
++ val |= ucontrol->value.integer.value[1] << 4;
++ else
++ val |= ucontrol->value.integer.value[0] << 4;
++ if (atten)
++ val = ~val & 0xff;
++ snd_pmac_burgundy_wcb(chip, addr, val);
++ return val != oval;
++}
++
++#define BURGUNDY_VOLUME_B(xname, xindex, addr, stereo, atten) \
++{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
++ .info = snd_pmac_burgundy_info_gain,\
++ .get = snd_pmac_burgundy_get_gain,\
++ .put = snd_pmac_burgundy_put_gain,\
++ .private_value = (ADDR2BASE(addr) | ((stereo) << 24) | ((atten) << 25)) }
++
++/*
++ * Burgundy switch: 0/1, mono/stereo, word reg
++ */
++static int snd_pmac_burgundy_info_switch_w(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
+ {
+ int stereo = (kcontrol->private_value >> 24) & 1;
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+@@ -231,111 +367,207 @@ static int snd_pmac_burgundy_info_switch_out(struct snd_kcontrol *kcontrol,
+ return 0;
+ }
+
+-static int snd_pmac_burgundy_get_switch_out(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_value *ucontrol)
++static int snd_pmac_burgundy_get_switch_w(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
+ {
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+- int lmask = kcontrol->private_value & 0xff;
+- int rmask = (kcontrol->private_value >> 8) & 0xff;
++ unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
++ int lmask = 1 << (kcontrol->private_value & 0xff);
++ int rmask = 1 << ((kcontrol->private_value >> 8) & 0xff);
+ int stereo = (kcontrol->private_value >> 24) & 1;
+- int val = snd_pmac_burgundy_rcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
++ int val = snd_pmac_burgundy_rcw(chip, addr);
+ ucontrol->value.integer.value[0] = (val & lmask) ? 1 : 0;
+ if (stereo)
+ ucontrol->value.integer.value[1] = (val & rmask) ? 1 : 0;
+ return 0;
+ }
+
+-static int snd_pmac_burgundy_put_switch_out(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_value *ucontrol)
++static int snd_pmac_burgundy_put_switch_w(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
+ {
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+- int lmask = kcontrol->private_value & 0xff;
+- int rmask = (kcontrol->private_value >> 8) & 0xff;
++ unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
++ int lmask = 1 << (kcontrol->private_value & 0xff);
++ int rmask = 1 << ((kcontrol->private_value >> 8) & 0xff);
+ int stereo = (kcontrol->private_value >> 24) & 1;
+ int val, oval;
+- oval = snd_pmac_burgundy_rcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
+- val = oval & ~(lmask | rmask);
++ oval = snd_pmac_burgundy_rcw(chip, addr);
++ val = oval & ~(lmask | (stereo ? rmask : 0));
+ if (ucontrol->value.integer.value[0])
+ val |= lmask;
+ if (stereo && ucontrol->value.integer.value[1])
+ val |= rmask;
+- snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, val);
++ snd_pmac_burgundy_wcw(chip, addr, val);
+ return val != oval;
+ }
+
+-#define BURGUNDY_OUTPUT_SWITCH(xname, xindex, lmask, rmask, stereo) \
++#define BURGUNDY_SWITCH_W(xname, xindex, addr, lbit, rbit, stereo) \
+ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
+- .info = snd_pmac_burgundy_info_switch_out,\
+- .get = snd_pmac_burgundy_get_switch_out,\
+- .put = snd_pmac_burgundy_put_switch_out,\
+- .private_value = ((lmask) | ((rmask) << 8) | ((stereo) << 24)) }
+-
+-/* line/speaker output volume */
+-static int snd_pmac_burgundy_info_volume_out(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_info *uinfo)
++ .info = snd_pmac_burgundy_info_switch_w,\
++ .get = snd_pmac_burgundy_get_switch_w,\
++ .put = snd_pmac_burgundy_put_switch_w,\
++ .private_value = ((lbit) | ((rbit) << 8)\
++ | (ADDR2BASE(addr) << 16) | ((stereo) << 24)) }
++
++/*
++ * Burgundy switch: 0/1, mono/stereo, byte reg, bit mask
++ */
++static int snd_pmac_burgundy_info_switch_b(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
+ {
+ int stereo = (kcontrol->private_value >> 24) & 1;
+- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = stereo + 1;
+ uinfo->value.integer.min = 0;
+- uinfo->value.integer.max = 15;
++ uinfo->value.integer.max = 1;
+ return 0;
+ }
+
+-static int snd_pmac_burgundy_get_volume_out(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_value *ucontrol)
++static int snd_pmac_burgundy_get_switch_b(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
+ {
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+- unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
++ unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
++ int lmask = kcontrol->private_value & 0xff;
++ int rmask = (kcontrol->private_value >> 8) & 0xff;
+ int stereo = (kcontrol->private_value >> 24) & 1;
+- int oval;
+-
+- oval = ~snd_pmac_burgundy_rcb(chip, addr) & 0xff;
+- ucontrol->value.integer.value[0] = oval & 0xf;
++ int val = snd_pmac_burgundy_rcb(chip, addr);
++ ucontrol->value.integer.value[0] = (val & lmask) ? 1 : 0;
+ if (stereo)
+- ucontrol->value.integer.value[1] = (oval >> 4) & 0xf;
++ ucontrol->value.integer.value[1] = (val & rmask) ? 1 : 0;
+ return 0;
+ }
+
+-static int snd_pmac_burgundy_put_volume_out(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_value *ucontrol)
++static int snd_pmac_burgundy_put_switch_b(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
+ {
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+- unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
++ unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
++ int lmask = kcontrol->private_value & 0xff;
++ int rmask = (kcontrol->private_value >> 8) & 0xff;
+ int stereo = (kcontrol->private_value >> 24) & 1;
+- unsigned int oval, val;
+-
+- oval = ~snd_pmac_burgundy_rcb(chip, addr) & 0xff;
+- val = ucontrol->value.integer.value[0] & 15;
+- if (stereo)
+- val |= (ucontrol->value.integer.value[1] & 15) << 4;
+- else
+- val |= val << 4;
+- val = ~val & 0xff;
++ int val, oval;
++ oval = snd_pmac_burgundy_rcb(chip, addr);
++ val = oval & ~(lmask | rmask);
++ if (ucontrol->value.integer.value[0])
++ val |= lmask;
++ if (stereo && ucontrol->value.integer.value[1])
++ val |= rmask;
+ snd_pmac_burgundy_wcb(chip, addr, val);
+ return val != oval;
+ }
+
+-#define BURGUNDY_OUTPUT_VOLUME(xname, xindex, addr, stereo) \
++#define BURGUNDY_SWITCH_B(xname, xindex, addr, lmask, rmask, stereo) \
+ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
+- .info = snd_pmac_burgundy_info_volume_out,\
+- .get = snd_pmac_burgundy_get_volume_out,\
+- .put = snd_pmac_burgundy_put_volume_out,\
+- .private_value = (ADDR2BASE(addr) | ((stereo) << 24)) }
++ .info = snd_pmac_burgundy_info_switch_b,\
++ .get = snd_pmac_burgundy_get_switch_b,\
++ .put = snd_pmac_burgundy_put_switch_b,\
++ .private_value = ((lmask) | ((rmask) << 8)\
++ | (ADDR2BASE(addr) << 16) | ((stereo) << 24)) }
+
++/*
++ * Burgundy mixers
++ */
+ static struct snd_kcontrol_new snd_pmac_burgundy_mixers[] __initdata = {
+- BURGUNDY_VOLUME("Master Playback Volume", 0, MASK_ADDR_BURGUNDY_MASTER_VOLUME, 8),
+- BURGUNDY_VOLUME("Line Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLLINE, 16),
+- BURGUNDY_VOLUME("CD Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLCD, 16),
+- BURGUNDY_VOLUME("Mic Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLMIC, 16),
+- BURGUNDY_OUTPUT_VOLUME("PC Speaker Playback Volume", 0, MASK_ADDR_BURGUNDY_ATTENHP, 0),
+- /*BURGUNDY_OUTPUT_VOLUME("PCM Playback Volume", 0, MASK_ADDR_BURGUNDY_ATTENLINEOUT, 1),*/
+- BURGUNDY_OUTPUT_VOLUME("Headphone Playback Volume", 0, MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1),
+-};
+-static struct snd_kcontrol_new snd_pmac_burgundy_master_sw __initdata =
+-BURGUNDY_OUTPUT_SWITCH("Headphone Playback Switch", 0, BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
+-static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw __initdata =
+-BURGUNDY_OUTPUT_SWITCH("PC Speaker Playback Switch", 0, BURGUNDY_OUTPUT_INTERN, 0, 0);
++ BURGUNDY_VOLUME_W("Master Playback Volume", 0,
++ MASK_ADDR_BURGUNDY_MASTER_VOLUME, 8),
++ BURGUNDY_VOLUME_W("CD Capture Volume", 0,
++ MASK_ADDR_BURGUNDY_VOLCD, 16),
++ BURGUNDY_VOLUME_2B("Input Capture Volume", 0,
++ MASK_ADDR_BURGUNDY_VOLMIX01, 2),
++ BURGUNDY_VOLUME_2B("Mixer Playback Volume", 0,
++ MASK_ADDR_BURGUNDY_VOLMIX23, 0),
++ BURGUNDY_VOLUME_B("CD Gain Capture Volume", 0,
++ MASK_ADDR_BURGUNDY_GAINCD, 1, 0),
++ BURGUNDY_SWITCH_W("Master Capture Switch", 0,
++ MASK_ADDR_BURGUNDY_OUTPUTENABLES, 24, 0, 0),
++ BURGUNDY_SWITCH_W("CD Capture Switch", 0,
++ MASK_ADDR_BURGUNDY_CAPTURESELECTS, 0, 16, 1),
++ BURGUNDY_SWITCH_W("CD Playback Switch", 0,
++ MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 0, 16, 1),
++/* BURGUNDY_SWITCH_W("Loop Capture Switch", 0,
++ * MASK_ADDR_BURGUNDY_CAPTURESELECTS, 8, 24, 1),
++ * BURGUNDY_SWITCH_B("Mixer out Capture Switch", 0,
++ * MASK_ADDR_BURGUNDY_HOSTIFAD, 0x02, 0, 0),
++ * BURGUNDY_SWITCH_B("Mixer Capture Switch", 0,
++ * MASK_ADDR_BURGUNDY_HOSTIFAD, 0x01, 0, 0),
++ * BURGUNDY_SWITCH_B("PCM out Capture Switch", 0,
++ * MASK_ADDR_BURGUNDY_HOSTIFEH, 0x02, 0, 0),
++ */ BURGUNDY_SWITCH_B("PCM Capture Switch", 0,
++ MASK_ADDR_BURGUNDY_HOSTIFEH, 0x01, 0, 0)
++};
++static struct snd_kcontrol_new snd_pmac_burgundy_mixers_imac[] __initdata = {
++ BURGUNDY_VOLUME_W("Line in Capture Volume", 0,
++ MASK_ADDR_BURGUNDY_VOLLINE, 16),
++ BURGUNDY_VOLUME_W("Mic Capture Volume", 0,
++ MASK_ADDR_BURGUNDY_VOLMIC, 16),
++ BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0,
++ MASK_ADDR_BURGUNDY_GAINLINE, 1, 0),
++ BURGUNDY_VOLUME_B("Mic Gain Capture Volume", 0,
++ MASK_ADDR_BURGUNDY_GAINMIC, 1, 0),
++ BURGUNDY_VOLUME_B("PC Speaker Playback Volume", 0,
++ MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1),
++ BURGUNDY_VOLUME_B("Line out Playback Volume", 0,
++ MASK_ADDR_BURGUNDY_ATTENLINEOUT, 1, 1),
++ BURGUNDY_VOLUME_B("Headphone Playback Volume", 0,
++ MASK_ADDR_BURGUNDY_ATTENHP, 1, 1),
++ BURGUNDY_SWITCH_W("Line in Capture Switch", 0,
++ MASK_ADDR_BURGUNDY_CAPTURESELECTS, 1, 17, 1),
++ BURGUNDY_SWITCH_W("Mic Capture Switch", 0,
++ MASK_ADDR_BURGUNDY_CAPTURESELECTS, 2, 18, 1),
++ BURGUNDY_SWITCH_W("Line in Playback Switch", 0,
++ MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 1, 17, 1),
++ BURGUNDY_SWITCH_W("Mic Playback Switch", 0,
++ MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 2, 18, 1),
++ BURGUNDY_SWITCH_B("Mic Boost Capture Switch", 0,
++ MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1)
++};
++static struct snd_kcontrol_new snd_pmac_burgundy_mixers_pmac[] __initdata = {
++ BURGUNDY_VOLUME_W("Line in Capture Volume", 0,
++ MASK_ADDR_BURGUNDY_VOLMIC, 16),
++ BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0,
++ MASK_ADDR_BURGUNDY_GAINMIC, 1, 0),
++ BURGUNDY_VOLUME_B("PC Speaker Playback Volume", 0,
++ MASK_ADDR_BURGUNDY_ATTENMONO, 0, 1),
++ BURGUNDY_VOLUME_B("Line out Playback Volume", 0,
++ MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1),
++ BURGUNDY_SWITCH_W("Line in Capture Switch", 0,
++ MASK_ADDR_BURGUNDY_CAPTURESELECTS, 2, 18, 1),
++ BURGUNDY_SWITCH_W("Line in Playback Switch", 0,
++ MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 2, 18, 1),
++/* BURGUNDY_SWITCH_B("Line in Boost Capture Switch", 0,
++ * MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1) */
++};
++static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_imac __initdata =
++BURGUNDY_SWITCH_B("Master Playback Switch", 0,
++ MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
++ BURGUNDY_OUTPUT_LEFT | BURGUNDY_LINEOUT_LEFT | BURGUNDY_HP_LEFT,
++ BURGUNDY_OUTPUT_RIGHT | BURGUNDY_LINEOUT_RIGHT | BURGUNDY_HP_RIGHT, 1);
++static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_pmac __initdata =
++BURGUNDY_SWITCH_B("Master Playback Switch", 0,
++ MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
++ BURGUNDY_OUTPUT_INTERN
++ | BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
++static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_imac __initdata =
++BURGUNDY_SWITCH_B("PC Speaker Playback Switch", 0,
++ MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
++ BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
++static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_pmac __initdata =
++BURGUNDY_SWITCH_B("PC Speaker Playback Switch", 0,
++ MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
++ BURGUNDY_OUTPUT_INTERN, 0, 0);
++static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_imac __initdata =
++BURGUNDY_SWITCH_B("Line out Playback Switch", 0,
++ MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
++ BURGUNDY_LINEOUT_LEFT, BURGUNDY_LINEOUT_RIGHT, 1);
++static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_pmac __initdata =
++BURGUNDY_SWITCH_B("Line out Playback Switch", 0,
++ MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
++ BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
++static struct snd_kcontrol_new snd_pmac_burgundy_hp_sw_imac __initdata =
++BURGUNDY_SWITCH_B("Headphone Playback Switch", 0,
++ MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
++ BURGUNDY_HP_LEFT, BURGUNDY_HP_RIGHT, 1);
+
+
+ #ifdef PMAC_SUPPORT_AUTOMUTE
+@@ -350,16 +582,26 @@ static int snd_pmac_burgundy_detect_headphone(struct snd_pmac *chip)
+ static void snd_pmac_burgundy_update_automute(struct snd_pmac *chip, int do_notify)
+ {
+ if (chip->auto_mute) {
++ int imac = machine_is_compatible("iMac");
+ int reg, oreg;
+- reg = oreg = snd_pmac_burgundy_rcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
+- reg &= ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT | BURGUNDY_OUTPUT_INTERN);
++ reg = oreg = snd_pmac_burgundy_rcb(chip,
++ MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
++ reg &= imac ? ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT
++ | BURGUNDY_HP_LEFT | BURGUNDY_HP_RIGHT)
++ : ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT
++ | BURGUNDY_OUTPUT_INTERN);
+ if (snd_pmac_burgundy_detect_headphone(chip))
+- reg |= BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT;
++ reg |= imac ? (BURGUNDY_HP_LEFT | BURGUNDY_HP_RIGHT)
++ : (BURGUNDY_OUTPUT_LEFT
++ | BURGUNDY_OUTPUT_RIGHT);
+ else
+- reg |= BURGUNDY_OUTPUT_INTERN;
++ reg |= imac ? (BURGUNDY_OUTPUT_LEFT
++ | BURGUNDY_OUTPUT_RIGHT)
++ : (BURGUNDY_OUTPUT_INTERN);
+ if (do_notify && reg == oreg)
+ return;
+- snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, reg);
++ snd_pmac_burgundy_wcb(chip,
++ MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, reg);
+ if (do_notify) {
+ snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &chip->master_sw_ctl->id);
+@@ -378,6 +620,7 @@ static void snd_pmac_burgundy_update_automute(struct snd_pmac *chip, int do_noti
+ */
+ int __init snd_pmac_burgundy_init(struct snd_pmac *chip)
+ {
++ int imac = machine_is_compatible("iMac");
+ int i, err;
+
+ /* Checks to see the chip is alive and kicking */
+@@ -386,7 +629,7 @@ int __init snd_pmac_burgundy_init(struct snd_pmac *chip)
+ return 1;
+ }
+
+- snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_OUTPUTENABLES,
++ snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_OUTPUTENABLES,
+ DEF_BURGUNDY_OUTPUTENABLES);
+ snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+ DEF_BURGUNDY_MORE_OUTPUTENABLES);
+@@ -396,7 +639,8 @@ int __init snd_pmac_burgundy_init(struct snd_pmac *chip)
+ snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_INPSEL21,
+ DEF_BURGUNDY_INPSEL21);
+ snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_INPSEL3,
+- DEF_BURGUNDY_INPSEL3);
++ imac ? DEF_BURGUNDY_INPSEL3_IMAC
++ : DEF_BURGUNDY_INPSEL3_PMAC);
+ snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINCD,
+ DEF_BURGUNDY_GAINCD);
+ snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINLINE,
+@@ -422,27 +666,62 @@ int __init snd_pmac_burgundy_init(struct snd_pmac *chip)
+ snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_VOLMIC,
+ DEF_BURGUNDY_VOLMIC);
+
+- if (chip->hp_stat_mask == 0)
++ if (chip->hp_stat_mask == 0) {
+ /* set headphone-jack detection bit */
+- chip->hp_stat_mask = 0x04;
+-
++ if (imac)
++ chip->hp_stat_mask = BURGUNDY_HPDETECT_IMAC_UPPER
++ | BURGUNDY_HPDETECT_IMAC_LOWER
++ | BURGUNDY_HPDETECT_IMAC_SIDE;
++ else
++ chip->hp_stat_mask = BURGUNDY_HPDETECT_PMAC_BACK;
++ }
+ /*
+ * build burgundy mixers
+ */
+ strcpy(chip->card->mixername, "PowerMac Burgundy");
+
+ for (i = 0; i < ARRAY_SIZE(snd_pmac_burgundy_mixers); i++) {
+- if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_pmac_burgundy_mixers[i], chip))) < 0)
++ err = snd_ctl_add(chip->card,
++ snd_ctl_new1(&snd_pmac_burgundy_mixers[i], chip));
++ if (err < 0)
++ return err;
++ }
++ for (i = 0; i < (imac ? ARRAY_SIZE(snd_pmac_burgundy_mixers_imac)
++ : ARRAY_SIZE(snd_pmac_burgundy_mixers_pmac)); i++) {
++ err = snd_ctl_add(chip->card,
++ snd_ctl_new1(imac ? &snd_pmac_burgundy_mixers_imac[i]
++ : &snd_pmac_burgundy_mixers_pmac[i], chip));
++ if (err < 0)
+ return err;
+ }
+- chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_burgundy_master_sw, chip);
+- if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
++ chip->master_sw_ctl = snd_ctl_new1(imac
++ ? &snd_pmac_burgundy_master_sw_imac
++ : &snd_pmac_burgundy_master_sw_pmac, chip);
++ err = snd_ctl_add(chip->card, chip->master_sw_ctl);
++ if (err < 0)
++ return err;
++ chip->master_sw_ctl = snd_ctl_new1(imac
++ ? &snd_pmac_burgundy_line_sw_imac
++ : &snd_pmac_burgundy_line_sw_pmac, chip);
++ err = snd_ctl_add(chip->card, chip->master_sw_ctl);
++ if (err < 0)
+ return err;
+- chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_burgundy_speaker_sw, chip);
+- if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
++ if (imac) {
++ chip->master_sw_ctl = snd_ctl_new1(
++ &snd_pmac_burgundy_hp_sw_imac, chip);
++ err = snd_ctl_add(chip->card, chip->master_sw_ctl);
++ if (err < 0)
++ return err;
++ }
++ chip->speaker_sw_ctl = snd_ctl_new1(imac
++ ? &snd_pmac_burgundy_speaker_sw_imac
++ : &snd_pmac_burgundy_speaker_sw_pmac, chip);
++ err = snd_ctl_add(chip->card, chip->speaker_sw_ctl);
++ if (err < 0)
+ return err;
+ #ifdef PMAC_SUPPORT_AUTOMUTE
+- if ((err = snd_pmac_add_automute(chip)) < 0)
++ err = snd_pmac_add_automute(chip);
++ if (err < 0)
+ return err;
+
+ chip->detect_headphone = snd_pmac_burgundy_detect_headphone;
+diff --git a/sound/ppc/burgundy.h b/sound/ppc/burgundy.h
+index ebb457a..7a7f9cf 100644
+--- a/sound/ppc/burgundy.h
++++ b/sound/ppc/burgundy.h
+@@ -22,6 +22,7 @@
+ #ifndef __BURGUNDY_H
+ #define __BURGUNDY_H
+
++#define MASK_ADDR_BURGUNDY_INPBOOST (0x10 << 12)
+ #define MASK_ADDR_BURGUNDY_INPSEL21 (0x11 << 12)
+ #define MASK_ADDR_BURGUNDY_INPSEL3 (0x12 << 12)
+
+@@ -35,7 +36,10 @@
+ #define MASK_ADDR_BURGUNDY_VOLCH3 (0x22 << 12)
+ #define MASK_ADDR_BURGUNDY_VOLCH4 (0x23 << 12)
+
++#define MASK_ADDR_BURGUNDY_CAPTURESELECTS (0x2A << 12)
+ #define MASK_ADDR_BURGUNDY_OUTPUTSELECTS (0x2B << 12)
++#define MASK_ADDR_BURGUNDY_VOLMIX01 (0x2D << 12)
++#define MASK_ADDR_BURGUNDY_VOLMIX23 (0x2E << 12)
+ #define MASK_ADDR_BURGUNDY_OUTPUTENABLES (0x2F << 12)
+
+ #define MASK_ADDR_BURGUNDY_MASTER_VOLUME (0x30 << 12)
+@@ -45,6 +49,10 @@
+ #define MASK_ADDR_BURGUNDY_ATTENSPEAKER (0x62 << 12)
+ #define MASK_ADDR_BURGUNDY_ATTENLINEOUT (0x63 << 12)
+ #define MASK_ADDR_BURGUNDY_ATTENHP (0x64 << 12)
++#define MASK_ADDR_BURGUNDY_ATTENMONO (0x65 << 12)
++
++#define MASK_ADDR_BURGUNDY_HOSTIFAD (0x78 << 12)
++#define MASK_ADDR_BURGUNDY_HOSTIFEH (0x79 << 12)
+
+ #define MASK_ADDR_BURGUNDY_VOLCD (MASK_ADDR_BURGUNDY_VOLCH1)
+ #define MASK_ADDR_BURGUNDY_VOLLINE (MASK_ADDR_BURGUNDY_VOLCH2)
+@@ -59,21 +67,22 @@
+
+ /* These are all default values for the burgundy */
+ #define DEF_BURGUNDY_INPSEL21 (0xAA)
+-#define DEF_BURGUNDY_INPSEL3 (0x0A)
++#define DEF_BURGUNDY_INPSEL3_IMAC (0x0A)
++#define DEF_BURGUNDY_INPSEL3_PMAC (0x05)
+
+ #define DEF_BURGUNDY_GAINCD (0x33)
+ #define DEF_BURGUNDY_GAINLINE (0x44)
+ #define DEF_BURGUNDY_GAINMIC (0x44)
+ #define DEF_BURGUNDY_GAINMODEM (0x06)
+
+-/* Remember: lowest volume here is 0x9b */
++/* Remember: lowest volume here is 0x9B (155) */
+ #define DEF_BURGUNDY_VOLCD (0xCCCCCCCC)
+ #define DEF_BURGUNDY_VOLLINE (0x00000000)
+ #define DEF_BURGUNDY_VOLMIC (0x00000000)
+ #define DEF_BURGUNDY_VOLMODEM (0xCCCCCCCC)
+
+-#define DEF_BURGUNDY_OUTPUTSELECTS (0x010f010f)
+-#define DEF_BURGUNDY_OUTPUTENABLES (0x0A)
++#define DEF_BURGUNDY_OUTPUTSELECTS (0x010F010F)
++#define DEF_BURGUNDY_OUTPUTENABLES (0x0100000A)
+
+ /* #define DEF_BURGUNDY_MASTER_VOLUME (0xFFFFFFFF) */ /* too loud */
+ #define DEF_BURGUNDY_MASTER_VOLUME (0xDDDDDDDD)
+@@ -84,12 +93,22 @@
+ #define DEF_BURGUNDY_ATTENLINEOUT (0xCC)
+ #define DEF_BURGUNDY_ATTENHP (0xCC)
+
+-/* OUTPUTENABLES bits */
++/* MORE_OUTPUTENABLES bits */
+ #define BURGUNDY_OUTPUT_LEFT 0x02
+ #define BURGUNDY_OUTPUT_RIGHT 0x04
++#define BURGUNDY_LINEOUT_LEFT 0x08
++#define BURGUNDY_LINEOUT_RIGHT 0x10
++#define BURGUNDY_HP_LEFT 0x20
++#define BURGUNDY_HP_RIGHT 0x40
+ #define BURGUNDY_OUTPUT_INTERN 0x80
+
+-/* volume offset */
++/* Headphone detection bits */
++#define BURGUNDY_HPDETECT_PMAC_BACK 0x04
++#define BURGUNDY_HPDETECT_IMAC_SIDE 0x04
++#define BURGUNDY_HPDETECT_IMAC_UPPER 0x08
++#define BURGUNDY_HPDETECT_IMAC_LOWER 0x01
++
++/* Volume offset */
+ #define BURGUNDY_VOLUME_OFFSET 155
+
+ #endif /* __BURGUNDY_H */
+diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
+index 613a565..a38c0c7 100644
+--- a/sound/ppc/pmac.c
++++ b/sound/ppc/pmac.c
+@@ -214,7 +214,7 @@ static int snd_pmac_pcm_prepare(struct snd_pmac *chip, struct pmac_stream *rec,
+ int rate_index;
+ long offset;
+ struct pmac_stream *astr;
+-
++
+ rec->dma_size = snd_pcm_lib_buffer_bytes(subs);
+ rec->period_size = snd_pcm_lib_period_bytes(subs);
+ rec->nperiods = rec->dma_size / rec->period_size;
+@@ -643,7 +643,7 @@ static int snd_pmac_pcm_close(struct snd_pmac *chip, struct pmac_stream *rec,
+ /* reset constraints */
+ astr->cur_freqs = chip->freqs_ok;
+ astr->cur_formats = chip->formats_ok;
+-
++
+ return 0;
+ }
+
+@@ -1300,9 +1300,9 @@ int __init snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return)
+
+ snd_pmac_sound_feature(chip, 1);
+
+- /* reset */
+- if (chip->model == PMAC_AWACS)
+- out_le32(&chip->awacs->control, 0x11);
++ /* reset & enable interrupts */
++ if (chip->model <= PMAC_BURGUNDY)
++ out_le32(&chip->awacs->control, chip->control_mask);
+
+ /* Powerbooks have odd ways of enabling inputs such as
+ an expansion-bay CD or sound from an internal modem
+diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c
+index d8d0b4b..20d0e32 100644
+--- a/sound/ppc/snd_ps3.c
++++ b/sound/ppc/snd_ps3.c
+@@ -137,7 +137,7 @@ static inline void update_mask_reg(unsigned int reg, u32 mask, u32 or_val)
+ /*
+ * ALSA defs
+ */
+-const static struct snd_pcm_hardware snd_ps3_pcm_hw = {
++static const struct snd_pcm_hardware snd_ps3_pcm_hw = {
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_NONINTERLEAVED |
+ SNDRV_PCM_INFO_MMAP_VALID),
+diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
+index 2765852..a3b51df 100644
+--- a/sound/soc/Kconfig
++++ b/sound/soc/Kconfig
+@@ -29,6 +29,7 @@ source "sound/soc/pxa/Kconfig"
+ source "sound/soc/s3c24xx/Kconfig"
+ source "sound/soc/sh/Kconfig"
+ source "sound/soc/fsl/Kconfig"
++source "sound/soc/davinci/Kconfig"
+
+ # Supported codecs
+ source "sound/soc/codecs/Kconfig"
+diff --git a/sound/soc/Makefile b/sound/soc/Makefile
+index 4869c9a..e489dbd 100644
+--- a/sound/soc/Makefile
++++ b/sound/soc/Makefile
+@@ -1,4 +1,4 @@
+ snd-soc-core-objs := soc-core.o soc-dapm.o
+
+ obj-$(CONFIG_SND_SOC) += snd-soc-core.o
+-obj-$(CONFIG_SND_SOC) += codecs/ at91/ pxa/ s3c24xx/ sh/ fsl/
++obj-$(CONFIG_SND_SOC) += codecs/ at91/ pxa/ s3c24xx/ sh/ fsl/ davinci/
+diff --git a/sound/soc/at91/eti_b1_wm8731.c b/sound/soc/at91/eti_b1_wm8731.c
+index ad3ad9d..1347dcf 100644
+--- a/sound/soc/at91/eti_b1_wm8731.c
++++ b/sound/soc/at91/eti_b1_wm8731.c
+@@ -33,8 +33,7 @@
+ #include <sound/soc.h>
+ #include <sound/soc-dapm.h>
+
+-#include <asm/arch/hardware.h>
+-#include <asm/arch/at91_pio.h>
++#include <asm/hardware.h>
+ #include <asm/arch/gpio.h>
+
+ #include "../codecs/wm8731.h"
+@@ -47,13 +46,6 @@
+ #define DBG(x...)
+ #endif
+
+-#define AT91_PIO_TF1 (1 << (AT91_PIN_PB6 - PIN_BASE) % 32)
+-#define AT91_PIO_TK1 (1 << (AT91_PIN_PB7 - PIN_BASE) % 32)
+-#define AT91_PIO_TD1 (1 << (AT91_PIN_PB8 - PIN_BASE) % 32)
+-#define AT91_PIO_RD1 (1 << (AT91_PIN_PB9 - PIN_BASE) % 32)
+-#define AT91_PIO_RK1 (1 << (AT91_PIN_PB10 - PIN_BASE) % 32)
+-#define AT91_PIO_RF1 (1 << (AT91_PIN_PB11 - PIN_BASE) % 32)
+-
+ static struct clk *pck1_clk;
+ static struct clk *pllb_clk;
+
+@@ -276,7 +268,6 @@ static struct platform_device *eti_b1_snd_device;
+ static int __init eti_b1_init(void)
+ {
+ int ret;
+- u32 ssc_pio_lines;
+ struct at91_ssc_periph *ssc = eti_b1_dai.cpu_dai->private_data;
+
+ if (!request_mem_region(AT91RM9200_BASE_SSC1, SZ_16K, "soc-audio")) {
+@@ -310,19 +301,12 @@ static int __init eti_b1_init(void)
+ goto fail_io_unmap;
+ }
+
+- ssc_pio_lines = AT91_PIO_TF1 | AT91_PIO_TK1 | AT91_PIO_TD1
+- | AT91_PIO_RD1 /* | AT91_PIO_RK1 */ | AT91_PIO_RF1;
+-
+- /* Reset all PIO registers and assign lines to peripheral A */
+- at91_sys_write(AT91_PIOB + PIO_PDR, ssc_pio_lines);
+- at91_sys_write(AT91_PIOB + PIO_ODR, ssc_pio_lines);
+- at91_sys_write(AT91_PIOB + PIO_IFDR, ssc_pio_lines);
+- at91_sys_write(AT91_PIOB + PIO_CODR, ssc_pio_lines);
+- at91_sys_write(AT91_PIOB + PIO_IDR, ssc_pio_lines);
+- at91_sys_write(AT91_PIOB + PIO_MDDR, ssc_pio_lines);
+- at91_sys_write(AT91_PIOB + PIO_PUDR, ssc_pio_lines);
+- at91_sys_write(AT91_PIOB + PIO_ASR, ssc_pio_lines);
+- at91_sys_write(AT91_PIOB + PIO_OWDR, ssc_pio_lines);
++ at91_set_A_periph(AT91_PIN_PB6, 0); /* TF1 */
++ at91_set_A_periph(AT91_PIN_PB7, 0); /* TK1 */
++ at91_set_A_periph(AT91_PIN_PB8, 0); /* TD1 */
++ at91_set_A_periph(AT91_PIN_PB9, 0); /* RD1 */
++/* at91_set_A_periph(AT91_PIN_PB10, 0);*/ /* RK1 */
++ at91_set_A_periph(AT91_PIN_PB11, 0); /* RF1 */
+
+ /*
+ * Set PCK1 parent to PLLB and its rate to 12 Mhz.
+diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
+index 898a7d3..3903ab7 100644
+--- a/sound/soc/codecs/Kconfig
++++ b/sound/soc/codecs/Kconfig
+@@ -18,6 +18,10 @@ config SND_SOC_WM9712
+ tristate
+ depends on SND_SOC
+
++config SND_SOC_WM9713
++ tristate
++ depends on SND_SOC
++
+ # Cirrus Logic CS4270 Codec
+ config SND_SOC_CS4270
+ tristate
+diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
+index c6e5338..4e1314c 100644
+--- a/sound/soc/codecs/Makefile
++++ b/sound/soc/codecs/Makefile
+@@ -3,6 +3,7 @@ snd-soc-wm8731-objs := wm8731.o
+ snd-soc-wm8750-objs := wm8750.o
+ snd-soc-wm8753-objs := wm8753.o
+ snd-soc-wm9712-objs := wm9712.o
++snd-soc-wm9713-objs := wm9713.o
+ snd-soc-cs4270-objs := cs4270.o
+ snd-soc-tlv320aic3x-objs := tlv320aic3x.o
+
+@@ -11,5 +12,6 @@ obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o
+ obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o
+ obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o
+ obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o
++obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o
+ obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
+ obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
+diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
+index 242130c..2a1ffe3 100644
+--- a/sound/soc/codecs/ac97.c
++++ b/sound/soc/codecs/ac97.c
+@@ -40,7 +40,8 @@ static int ac97_prepare(struct snd_pcm_substream *substream)
+ }
+
+ #define STD_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
+- SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
++ SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\
++ SNDRV_PCM_RATE_48000)
+
+ struct snd_soc_codec_dai ac97_dai = {
+ .name = "AC97 HiFi",
+@@ -86,7 +87,7 @@ static int ac97_soc_probe(struct platform_device *pdev)
+ printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION);
+
+ socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+- if (socdev->codec == NULL)
++ if (!socdev->codec)
+ return -ENOMEM;
+ codec = socdev->codec;
+ mutex_init(&codec->mutex);
+@@ -102,17 +103,17 @@ static int ac97_soc_probe(struct platform_device *pdev)
+
+ /* register pcms */
+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+- if(ret < 0)
++ if (ret < 0)
+ goto err;
+
+ /* add codec as bus device for standard ac97 */
+ ret = snd_ac97_bus(codec->card, 0, &soc_ac97_ops, NULL, &ac97_bus);
+- if(ret < 0)
++ if (ret < 0)
+ goto bus_err;
+
+ memset(&ac97_template, 0, sizeof(struct snd_ac97_template));
+ ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97);
+- if(ret < 0)
++ if (ret < 0)
+ goto bus_err;
+
+ ret = snd_soc_register_card(socdev);
+@@ -135,7 +136,7 @@ static int ac97_soc_remove(struct platform_device *pdev)
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->codec;
+
+- if(codec == NULL)
++ if (!codec)
+ return 0;
+
+ snd_soc_free_pcms(socdev);
+@@ -145,11 +146,10 @@ static int ac97_soc_remove(struct platform_device *pdev)
+ return 0;
+ }
+
+-struct snd_soc_codec_device soc_codec_dev_ac97= {
++struct snd_soc_codec_device soc_codec_dev_ac97 = {
+ .probe = ac97_soc_probe,
+ .remove = ac97_soc_remove,
+ };
+-
+ EXPORT_SYMBOL_GPL(soc_codec_dev_ac97);
+
+ MODULE_DESCRIPTION("Soc Generic AC97 driver");
+diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
+index bf2ab72..e73fcfd 100644
+--- a/sound/soc/codecs/cs4270.c
++++ b/sound/soc/codecs/cs4270.c
+@@ -372,7 +372,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+ struct cs4270_private *cs4270 = codec->private_data;
+- unsigned int ret = 0;
++ int ret;
+ unsigned int i;
+ unsigned int rate;
+ unsigned int ratio;
+diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
+index 889a897..630684f 100644
+--- a/sound/soc/codecs/tlv320aic3x.c
++++ b/sound/soc/codecs/tlv320aic3x.c
+@@ -660,33 +660,53 @@ struct aic3x_rate_divs {
+ /* AIC3X codec mclk clock divider coefficients */
+ static const struct aic3x_rate_divs aic3x_divs[] = {
+ /* 8k */
++ {12000000, 8000, 48000, 0xa, 16, 3840},
++ {19200000, 8000, 48000, 0xa, 10, 2400},
+ {22579200, 8000, 48000, 0xa, 8, 7075},
+ {33868800, 8000, 48000, 0xa, 5, 8049},
+ /* 11.025k */
++ {12000000, 11025, 44100, 0x6, 15, 528},
++ {19200000, 11025, 44100, 0x6, 9, 4080},
+ {22579200, 11025, 44100, 0x6, 8, 0},
+ {33868800, 11025, 44100, 0x6, 5, 3333},
+ /* 16k */
++ {12000000, 16000, 48000, 0x4, 16, 3840},
++ {19200000, 16000, 48000, 0x4, 10, 2400},
+ {22579200, 16000, 48000, 0x4, 8, 7075},
+ {33868800, 16000, 48000, 0x4, 5, 8049},
+ /* 22.05k */
++ {12000000, 22050, 44100, 0x2, 15, 528},
++ {19200000, 22050, 44100, 0x2, 9, 4080},
+ {22579200, 22050, 44100, 0x2, 8, 0},
+ {33868800, 22050, 44100, 0x2, 5, 3333},
+ /* 32k */
++ {12000000, 32000, 48000, 0x1, 16, 3840},
++ {19200000, 32000, 48000, 0x1, 10, 2400},
+ {22579200, 32000, 48000, 0x1, 8, 7075},
+ {33868800, 32000, 48000, 0x1, 5, 8049},
+ /* 44.1k */
++ {12000000, 44100, 44100, 0x0, 15, 528},
++ {19200000, 44100, 44100, 0x0, 9, 4080},
+ {22579200, 44100, 44100, 0x0, 8, 0},
+ {33868800, 44100, 44100, 0x0, 5, 3333},
+ /* 48k */
++ {12000000, 48000, 48000, 0x0, 16, 3840},
++ {19200000, 48000, 48000, 0x0, 10, 2400},
+ {22579200, 48000, 48000, 0x0, 8, 7075},
+ {33868800, 48000, 48000, 0x0, 5, 8049},
+ /* 64k */
++ {12000000, 64000, 96000, 0x1, 16, 3840},
++ {19200000, 64000, 96000, 0x1, 10, 2400},
+ {22579200, 64000, 96000, 0x1, 8, 7075},
+ {33868800, 64000, 96000, 0x1, 5, 8049},
+ /* 88.2k */
++ {12000000, 88200, 88200, 0x0, 15, 528},
++ {19200000, 88200, 88200, 0x0, 9, 4080},
+ {22579200, 88200, 88200, 0x0, 8, 0},
+ {33868800, 88200, 88200, 0x0, 5, 3333},
+ /* 96k */
++ {12000000, 96000, 96000, 0x0, 16, 3840},
++ {19200000, 96000, 96000, 0x0, 10, 2400},
+ {22579200, 96000, 96000, 0x0, 8, 7075},
+ {33868800, 96000, 96000, 0x0, 5, 8049},
+ };
+@@ -807,6 +827,8 @@ static int aic3x_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
+ struct aic3x_priv *aic3x = codec->private_data;
+
+ switch (freq) {
++ case 12000000:
++ case 19200000:
+ case 22579200:
+ case 33868800:
+ aic3x->sysclk = freq;
+diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
+index 9c33fe8..0cf9265 100644
+--- a/sound/soc/codecs/wm8731.c
++++ b/sound/soc/codecs/wm8731.c
+@@ -110,7 +110,7 @@ static int wm8731_write(struct snd_soc_codec *codec, unsigned int reg,
+ data[0] = (reg << 1) | ((value >> 8) & 0x0001);
+ data[1] = value & 0x00ff;
+
+- wm8731_write_reg_cache (codec, reg, value);
++ wm8731_write_reg_cache(codec, reg, value);
+ if (codec->hw_write(codec->control_data, data, 2) == 2)
+ return 0;
+ else
+@@ -154,8 +154,10 @@ static int wm8731_add_controls(struct snd_soc_codec *codec)
+ int err, i;
+
+ for (i = 0; i < ARRAY_SIZE(wm8731_snd_controls); i++) {
+- if ((err = snd_ctl_add(codec->card,
+- snd_soc_cnew(&wm8731_snd_controls[i],codec, NULL))) < 0)
++ err = snd_ctl_add(codec->card,
++ snd_soc_cnew(&wm8731_snd_controls[i],
++ codec, NULL));
++ if (err < 0)
+ return err;
+ }
+
+@@ -221,15 +223,13 @@ static int wm8731_add_widgets(struct snd_soc_codec *codec)
+ {
+ int i;
+
+- for(i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) {
++ for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++)
+ snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
+- }
+
+ /* set up audio path interconnects */
+- for(i = 0; intercon[i][0] != NULL; i++) {
++ for (i = 0; intercon[i][0] != NULL; i++)
+ snd_soc_dapm_connect_input(codec, intercon[i][0],
+ intercon[i][1], intercon[i][2]);
+- }
+
+ snd_soc_dapm_new_widgets(codec);
+ return 0;
+@@ -589,7 +589,7 @@ pcm_err:
+
+ static struct snd_soc_device *wm8731_socdev;
+
+-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+
+ /*
+ * WM8731 2 wire address is determined by GPIO5
+@@ -651,7 +651,7 @@ err:
+
+ static int wm8731_i2c_detach(struct i2c_client *client)
+ {
+- struct snd_soc_codec* codec = i2c_get_clientdata(client);
++ struct snd_soc_codec *codec = i2c_get_clientdata(client);
+ i2c_detach_client(client);
+ kfree(codec->reg_cache);
+ kfree(client);
+@@ -709,7 +709,7 @@ static int wm8731_probe(struct platform_device *pdev)
+ INIT_LIST_HEAD(&codec->dapm_paths);
+
+ wm8731_socdev = socdev;
+-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ if (setup->i2c_address) {
+ normal_i2c[0] = setup->i2c_address;
+ codec->hw_write = (hw_write_t)i2c_master_send;
+@@ -734,7 +734,7 @@ static int wm8731_remove(struct platform_device *pdev)
+
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ i2c_del_driver(&wm8731_i2c_driver);
+ #endif
+ kfree(codec->private_data);
+@@ -749,7 +749,6 @@ struct snd_soc_codec_device soc_codec_dev_wm8731 = {
+ .suspend = wm8731_suspend,
+ .resume = wm8731_resume,
+ };
+-
+ EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
+
+ MODULE_DESCRIPTION("ASoC WM8731 driver");
+diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
+index 77a857b..16cd5d4 100644
+--- a/sound/soc/codecs/wm8750.c
++++ b/sound/soc/codecs/wm8750.c
+@@ -110,7 +110,7 @@ static int wm8750_write(struct snd_soc_codec *codec, unsigned int reg,
+ data[0] = (reg << 1) | ((value >> 8) & 0x0001);
+ data[1] = value & 0x00ff;
+
+- wm8750_write_reg_cache (codec, reg, value);
++ wm8750_write_reg_cache(codec, reg, value);
+ if (codec->hw_write(codec->control_data, data, 2) == 2)
+ return 0;
+ else
+@@ -257,7 +257,8 @@ static int wm8750_add_controls(struct snd_soc_codec *codec)
+
+ for (i = 0; i < ARRAY_SIZE(wm8750_snd_controls); i++) {
+ err = snd_ctl_add(codec->card,
+- snd_soc_cnew(&wm8750_snd_controls[i],codec, NULL));
++ snd_soc_cnew(&wm8750_snd_controls[i],
++ codec, NULL));
+ if (err < 0)
+ return err;
+ }
+@@ -478,15 +479,13 @@ static int wm8750_add_widgets(struct snd_soc_codec *codec)
+ {
+ int i;
+
+- for(i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++) {
++ for (i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++)
+ snd_soc_dapm_new_control(codec, &wm8750_dapm_widgets[i]);
+- }
+
+ /* set up audio path audio_mapnects */
+- for(i = 0; audio_map[i][0] != NULL; i++) {
++ for (i = 0; audio_map[i][0] != NULL; i++)
+ snd_soc_dapm_connect_input(codec, audio_map[i][0],
+ audio_map[i][1], audio_map[i][2]);
+- }
+
+ snd_soc_dapm_new_widgets(codec);
+ return 0;
+@@ -714,8 +713,8 @@ static int wm8750_dapm_event(struct snd_soc_codec *codec, int event)
+ }
+
+ #define WM8750_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
+- SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
+- SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
++ SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
++ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
+
+ #define WM8750_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE)
+@@ -784,7 +783,8 @@ static int wm8750_resume(struct platform_device *pdev)
+ if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0) {
+ wm8750_dapm_event(codec, SNDRV_CTL_POWER_D2);
+ codec->dapm_state = SNDRV_CTL_POWER_D0;
+- schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(1000));
++ schedule_delayed_work(&codec->delayed_work,
++ msecs_to_jiffies(1000));
+ }
+
+ return 0;
+@@ -864,7 +864,7 @@ pcm_err:
+ around */
+ static struct snd_soc_device *wm8750_socdev;
+
+-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+
+ /*
+ * WM8731 2 wire address is determined by GPIO5
+@@ -979,8 +979,8 @@ static int wm8750_probe(struct platform_device *pdev)
+ INIT_LIST_HEAD(&codec->dapm_paths);
+ wm8750_socdev = socdev;
+ INIT_DELAYED_WORK(&codec->delayed_work, wm8750_work);
+-
+-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++
++#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ if (setup->i2c_address) {
+ normal_i2c[0] = setup->i2c_address;
+ codec->hw_write = (hw_write_t)i2c_master_send;
+@@ -1025,7 +1025,7 @@ static int wm8750_remove(struct platform_device *pdev)
+ run_delayed_work(&codec->delayed_work);
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
++#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ i2c_del_driver(&wm8750_i2c_driver);
+ #endif
+ kfree(codec->private_data);
+@@ -1040,7 +1040,6 @@ struct snd_soc_codec_device soc_codec_dev_wm8750 = {
+ .suspend = wm8750_suspend,
+ .resume = wm8750_resume,
+ };
+-
+ EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750);
+
+ MODULE_DESCRIPTION("ASoC WM8750 driver");
+diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
+index ddd9c71..76a5c7b 100644
+--- a/sound/soc/codecs/wm8753.c
++++ b/sound/soc/codecs/wm8753.c
+@@ -198,6 +198,7 @@ static const char *wm8753_mic_sel[] = {"Mic 1", "Mic 2", "Mic 3"};
+ static const char *wm8753_dai_mode[] = {"DAI 0", "DAI 1", "DAI 2", "DAI 3"};
+ static const char *wm8753_dat_sel[] = {"Stereo", "Left ADC", "Right ADC",
+ "Channel Swap"};
++static const char *wm8753_rout2_phase[] = {"Non Inverted", "Inverted"};
+
+ static const struct soc_enum wm8753_enum[] = {
+ SOC_ENUM_SINGLE(WM8753_BASS, 7, 2, wm8753_base),
+@@ -228,6 +229,7 @@ SOC_ENUM_SINGLE(WM8753_ADC, 4, 2, wm8753_adc_filter),
+ SOC_ENUM_SINGLE(WM8753_MICBIAS, 6, 3, wm8753_mic_sel),
+ SOC_ENUM_SINGLE(WM8753_IOCTL, 2, 4, wm8753_dai_mode),
+ SOC_ENUM_SINGLE(WM8753_ADC, 7, 4, wm8753_dat_sel),
++SOC_ENUM_SINGLE(WM8753_OUTCTL, 2, 2, wm8753_rout2_phase),
+ };
+
+
+@@ -279,7 +281,7 @@ SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8753_LOUT2V, WM8753_ROUT2V, 7, 1, 0
+
+ SOC_SINGLE("Mono Bypass Playback Volume", WM8753_MOUTM1, 4, 7, 1),
+ SOC_SINGLE("Mono Sidetone Playback Volume", WM8753_MOUTM2, 4, 7, 1),
+-SOC_SINGLE("Mono Voice Playback Volume", WM8753_MOUTM2, 4, 7, 1),
++SOC_SINGLE("Mono Voice Playback Volume", WM8753_MOUTM2, 0, 7, 1),
+ SOC_SINGLE("Mono Playback ZC Switch", WM8753_MOUTV, 7, 1, 0),
+
+ SOC_ENUM("Bass Boost", wm8753_enum[0]),
+@@ -330,6 +332,7 @@ SOC_SINGLE("Mic1 Capture Volume", WM8753_INCTL1, 5, 3, 0),
+ SOC_ENUM_EXT("DAI Mode", wm8753_enum[26], wm8753_get_dai, wm8753_set_dai),
+
+ SOC_ENUM("ADC Data Select", wm8753_enum[27]),
++SOC_ENUM("ROUT2 Phase", wm8753_enum[28]),
+ };
+
+ /* add non dapm controls */
+diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
+index 524f745..d2d79e1 100644
+--- a/sound/soc/codecs/wm9712.c
++++ b/sound/soc/codecs/wm9712.c
+@@ -581,22 +581,14 @@ static int wm9712_dapm_event(struct snd_soc_codec *codec, int event)
+
+ switch (event) {
+ case SNDRV_CTL_POWER_D0: /* full On */
+- /* liam - maybe enable thermal shutdown */
+- reg = ac97_read(codec, AC97_EXTENDED_MID) & 0xdfff;
+- ac97_write(codec, AC97_EXTENDED_MID, reg);
+- break;
+ case SNDRV_CTL_POWER_D1: /* partial On */
+ case SNDRV_CTL_POWER_D2: /* partial On */
+ break;
+ case SNDRV_CTL_POWER_D3hot: /* Off, with power */
+- /* enable master bias and vmid */
+- reg = ac97_read(codec, AC97_EXTENDED_MID) & 0xbbff;
+- ac97_write(codec, AC97_EXTENDED_MID, reg);
+ ac97_write(codec, AC97_POWERDOWN, 0x0000);
+ break;
+ case SNDRV_CTL_POWER_D3cold: /* Off, without power */
+ /* disable everything including AC link */
+- ac97_write(codec, AC97_EXTENDED_MID, 0xffff);
+ ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
+ ac97_write(codec, AC97_POWERDOWN, 0xffff);
+ break;
+diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
+new file mode 100644
+index 0000000..1f24116
+--- /dev/null
++++ b/sound/soc/codecs/wm9713.c
+@@ -0,0 +1,1300 @@
++/*
++ * wm9713.c -- ALSA Soc WM9713 codec support
++ *
++ * Copyright 2006 Wolfson Microelectronics PLC.
++ * Author: Liam Girdwood
++ * liam.girdwood at wolfsonmicro.com or linux at wolfsonmicro.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.
++ *
++ * Revision history
++ * 4th Feb 2006 Initial version.
++ *
++ * Features:-
++ *
++ * o Support for AC97 Codec, Voice DAC and Aux DAC
++ * o Support for DAPM
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/device.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/ac97_codec.h>
++#include <sound/initval.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <sound/soc-dapm.h>
++
++#include "wm9713.h"
++
++#define WM9713_VERSION "0.15"
++
++struct wm9713_priv {
++ u32 pll_in; /* PLL input frequency */
++ u32 pll_out; /* PLL output frequency */
++};
++
++static unsigned int ac97_read(struct snd_soc_codec *codec,
++ unsigned int reg);
++static int ac97_write(struct snd_soc_codec *codec,
++ unsigned int reg, unsigned int val);
++
++/*
++ * WM9713 register cache
++ * Reg 0x3c bit 15 is used by touch driver.
++ */
++static const u16 wm9713_reg[] = {
++ 0x6174, 0x8080, 0x8080, 0x8080,
++ 0xc880, 0xe808, 0xe808, 0x0808,
++ 0x00da, 0x8000, 0xd600, 0xaaa0,
++ 0xaaa0, 0xaaa0, 0x0000, 0x0000,
++ 0x0f0f, 0x0040, 0x0000, 0x7f00,
++ 0x0405, 0x0410, 0xbb80, 0xbb80,
++ 0x0000, 0xbb80, 0x0000, 0x4523,
++ 0x0000, 0x2000, 0x7eff, 0xffff,
++ 0x0000, 0x0000, 0x0080, 0x0000,
++ 0x0000, 0x0000, 0xfffe, 0xffff,
++ 0x0000, 0x0000, 0x0000, 0xfffe,
++ 0x4000, 0x0000, 0x0000, 0x0000,
++ 0xb032, 0x3e00, 0x0000, 0x0000,
++ 0x0000, 0x0000, 0x0000, 0x0000,
++ 0x0000, 0x0000, 0x0000, 0x0006,
++ 0x0001, 0x0000, 0x574d, 0x4c13,
++ 0x0000, 0x0000, 0x0000
++};
++
++/* virtual HP mixers regs */
++#define HPL_MIXER 0x80
++#define HPR_MIXER 0x82
++#define MICB_MUX 0x82
++
++static const char *wm9713_mic_mixer[] = {"Stereo", "Mic 1", "Mic 2", "Mute"};
++static const char *wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"};
++static const char *wm9713_rec_src[] =
++ {"Mic 1", "Mic 2", "Line", "Mono In", "Headphone", "Speaker",
++ "Mono Out", "Zh"};
++static const char *wm9713_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"};
++static const char *wm9713_alc_select[] = {"None", "Left", "Right", "Stereo"};
++static const char *wm9713_mono_pga[] = {"Vmid", "Zh", "Mono", "Inv",
++ "Mono Vmid", "Inv Vmid"};
++static const char *wm9713_spk_pga[] =
++ {"Vmid", "Zh", "Headphone", "Speaker", "Inv", "Headphone Vmid",
++ "Speaker Vmid", "Inv Vmid"};
++static const char *wm9713_hp_pga[] = {"Vmid", "Zh", "Headphone",
++ "Headphone Vmid"};
++static const char *wm9713_out3_pga[] = {"Vmid", "Zh", "Inv 1", "Inv 1 Vmid"};
++static const char *wm9713_out4_pga[] = {"Vmid", "Zh", "Inv 2", "Inv 2 Vmid"};
++static const char *wm9713_dac_inv[] =
++ {"Off", "Mono", "Speaker", "Left Headphone", "Right Headphone",
++ "Headphone Mono", "NC", "Vmid"};
++static const char *wm9713_bass[] = {"Linear Control", "Adaptive Boost"};
++static const char *wm9713_ng_type[] = {"Constant Gain", "Mute"};
++static const char *wm9713_mic_select[] = {"Mic 1", "Mic 2 A", "Mic 2 B"};
++static const char *wm9713_micb_select[] = {"MPB", "MPA"};
++
++static const struct soc_enum wm9713_enum[] = {
++SOC_ENUM_SINGLE(AC97_LINE, 3, 4, wm9713_mic_mixer), /* record mic mixer 0 */
++SOC_ENUM_SINGLE(AC97_VIDEO, 14, 4, wm9713_rec_mux), /* record mux hp 1 */
++SOC_ENUM_SINGLE(AC97_VIDEO, 9, 4, wm9713_rec_mux), /* record mux mono 2 */
++SOC_ENUM_SINGLE(AC97_VIDEO, 3, 8, wm9713_rec_src), /* record mux left 3 */
++SOC_ENUM_SINGLE(AC97_VIDEO, 0, 8, wm9713_rec_src), /* record mux right 4*/
++SOC_ENUM_DOUBLE(AC97_CD, 14, 6, 2, wm9713_rec_gain), /* record step size 5 */
++SOC_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9713_alc_select), /* alc source select 6*/
++SOC_ENUM_SINGLE(AC97_REC_GAIN, 14, 4, wm9713_mono_pga), /* mono input select 7 */
++SOC_ENUM_SINGLE(AC97_REC_GAIN, 11, 8, wm9713_spk_pga), /* speaker left input select 8 */
++SOC_ENUM_SINGLE(AC97_REC_GAIN, 8, 8, wm9713_spk_pga), /* speaker right input select 9 */
++SOC_ENUM_SINGLE(AC97_REC_GAIN, 6, 3, wm9713_hp_pga), /* headphone left input 10 */
++SOC_ENUM_SINGLE(AC97_REC_GAIN, 4, 3, wm9713_hp_pga), /* headphone right input 11 */
++SOC_ENUM_SINGLE(AC97_REC_GAIN, 2, 4, wm9713_out3_pga), /* out 3 source 12 */
++SOC_ENUM_SINGLE(AC97_REC_GAIN, 0, 4, wm9713_out4_pga), /* out 4 source 13 */
++SOC_ENUM_SINGLE(AC97_REC_GAIN_MIC, 13, 8, wm9713_dac_inv), /* dac invert 1 14 */
++SOC_ENUM_SINGLE(AC97_REC_GAIN_MIC, 10, 8, wm9713_dac_inv), /* dac invert 2 15 */
++SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, wm9713_bass), /* bass control 16 */
++SOC_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9713_ng_type), /* noise gate type 17 */
++SOC_ENUM_SINGLE(AC97_3D_CONTROL, 12, 3, wm9713_mic_select), /* mic selection 18 */
++SOC_ENUM_SINGLE(MICB_MUX, 0, 2, wm9713_micb_select), /* mic selection 19 */
++};
++
++static const struct snd_kcontrol_new wm9713_snd_ac97_controls[] = {
++SOC_DOUBLE("Speaker Playback Volume", AC97_MASTER, 8, 0, 31, 1),
++SOC_DOUBLE("Speaker Playback Switch", AC97_MASTER, 15, 7, 1, 1),
++SOC_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1),
++SOC_DOUBLE("Headphone Playback Switch", AC97_HEADPHONE, 15, 7, 1, 1),
++SOC_DOUBLE("Line In Volume", AC97_PC_BEEP, 8, 0, 31, 1),
++SOC_DOUBLE("PCM Playback Volume", AC97_PHONE, 8, 0, 31, 1),
++SOC_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
++SOC_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
++
++SOC_SINGLE("Mic Boost (+20dB) Switch", AC97_LINE, 5, 1, 0),
++SOC_SINGLE("Mic Headphone Mixer Volume", AC97_LINE, 0, 7, 1),
++
++SOC_SINGLE("Capture Switch", AC97_CD, 15, 1, 1),
++SOC_ENUM("Capture Volume Steps", wm9713_enum[5]),
++SOC_DOUBLE("Capture Volume", AC97_CD, 8, 0, 31, 0),
++SOC_SINGLE("Capture ZC Switch", AC97_CD, 7, 1, 0),
++
++SOC_SINGLE("Capture to Headphone Volume", AC97_VIDEO, 11, 7, 1),
++SOC_SINGLE("Capture to Mono Boost (+20dB) Switch", AC97_VIDEO, 8, 1, 0),
++SOC_SINGLE("Capture ADC Boost (+20dB) Switch", AC97_VIDEO, 6, 1, 0),
++
++SOC_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0),
++SOC_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),
++SOC_SINGLE("ALC Decay Time ", AC97_CODEC_CLASS_REV, 4, 15, 0),
++SOC_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0),
++SOC_ENUM("ALC Function", wm9713_enum[6]),
++SOC_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 0),
++SOC_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 0),
++SOC_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0),
++SOC_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0),
++SOC_ENUM("ALC NG Type", wm9713_enum[17]),
++SOC_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 0),
++
++SOC_DOUBLE("Speaker Playback ZC Switch", AC97_MASTER, 14, 6, 1, 0),
++SOC_DOUBLE("Headphone Playback ZC Switch", AC97_HEADPHONE, 14, 6, 1, 0),
++
++SOC_SINGLE("Out4 Playback Switch", AC97_MASTER_MONO, 15, 1, 1),
++SOC_SINGLE("Out4 Playback ZC Switch", AC97_MASTER_MONO, 14, 1, 0),
++SOC_SINGLE("Out4 Playback Volume", AC97_MASTER_MONO, 8, 63, 1),
++
++SOC_SINGLE("Out3 Playback Switch", AC97_MASTER_MONO, 7, 1, 1),
++SOC_SINGLE("Out3 Playback ZC Switch", AC97_MASTER_MONO, 6, 1, 0),
++SOC_SINGLE("Out3 Playback Volume", AC97_MASTER_MONO, 0, 63, 1),
++
++SOC_SINGLE("Mono Capture Volume", AC97_MASTER_TONE, 8, 31, 1),
++SOC_SINGLE("Mono Playback Switch", AC97_MASTER_TONE, 7, 1, 1),
++SOC_SINGLE("Mono Playback ZC Switch", AC97_MASTER_TONE, 6, 1, 0),
++SOC_SINGLE("Mono Playback Volume", AC97_MASTER_TONE, 0, 31, 1),
++
++SOC_SINGLE("PC Beep Playback Headphone Volume", AC97_AUX, 12, 7, 1),
++SOC_SINGLE("PC Beep Playback Speaker Volume", AC97_AUX, 8, 7, 1),
++SOC_SINGLE("PC Beep Playback Mono Volume", AC97_AUX, 4, 7, 1),
++
++SOC_SINGLE("Voice Playback Headphone Volume", AC97_PCM, 12, 7, 1),
++SOC_SINGLE("Voice Playback Master Volume", AC97_PCM, 8, 7, 1),
++SOC_SINGLE("Voice Playback Mono Volume", AC97_PCM, 4, 7, 1),
++
++SOC_SINGLE("Aux Playback Headphone Volume", AC97_REC_SEL, 12, 7, 1),
++SOC_SINGLE("Aux Playback Master Volume", AC97_REC_SEL, 8, 7, 1),
++SOC_SINGLE("Aux Playback Mono Volume", AC97_REC_SEL, 4, 7, 1),
++
++SOC_ENUM("Bass Control", wm9713_enum[16]),
++SOC_SINGLE("Bass Cut-off Switch", AC97_GENERAL_PURPOSE, 12, 1, 1),
++SOC_SINGLE("Tone Cut-off Switch", AC97_GENERAL_PURPOSE, 4, 1, 1),
++SOC_SINGLE("Playback Attenuate (-6dB) Switch", AC97_GENERAL_PURPOSE, 6, 1, 0),
++SOC_SINGLE("Bass Volume", AC97_GENERAL_PURPOSE, 8, 15, 1),
++SOC_SINGLE("Tone Volume", AC97_GENERAL_PURPOSE, 0, 15, 1),
++
++SOC_SINGLE("3D Upper Cut-off Switch", AC97_REC_GAIN_MIC, 5, 1, 0),
++SOC_SINGLE("3D Lower Cut-off Switch", AC97_REC_GAIN_MIC, 4, 1, 0),
++SOC_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1),
++};
++
++/* add non dapm controls */
++static int wm9713_add_controls(struct snd_soc_codec *codec)
++{
++ int err, i;
++
++ for (i = 0; i < ARRAY_SIZE(wm9713_snd_ac97_controls); i++) {
++ err = snd_ctl_add(codec->card,
++ snd_soc_cnew(&wm9713_snd_ac97_controls[i],
++ codec, NULL));
++ if (err < 0)
++ return err;
++ }
++ return 0;
++}
++
++/* We have to create a fake left and right HP mixers because
++ * the codec only has a single control that is shared by both channels.
++ * This makes it impossible to determine the audio path using the current
++ * register map, thus we add a new (virtual) register to help determine the
++ * audio route within the device.
++ */
++static int mixer_event(struct snd_soc_dapm_widget *w,
++ struct snd_kcontrol *kcontrol, int event)
++{
++ u16 l, r, beep, tone, phone, rec, pcm, aux;
++
++ l = ac97_read(w->codec, HPL_MIXER);
++ r = ac97_read(w->codec, HPR_MIXER);
++ beep = ac97_read(w->codec, AC97_PC_BEEP);
++ tone = ac97_read(w->codec, AC97_MASTER_TONE);
++ phone = ac97_read(w->codec, AC97_PHONE);
++ rec = ac97_read(w->codec, AC97_REC_SEL);
++ pcm = ac97_read(w->codec, AC97_PCM);
++ aux = ac97_read(w->codec, AC97_AUX);
++
++ if (event & SND_SOC_DAPM_PRE_REG)
++ return 0;
++ if ((l & 0x1) || (r & 0x1))
++ ac97_write(w->codec, AC97_PC_BEEP, beep & 0x7fff);
++ else
++ ac97_write(w->codec, AC97_PC_BEEP, beep | 0x8000);
++
++ if ((l & 0x2) || (r & 0x2))
++ ac97_write(w->codec, AC97_MASTER_TONE, tone & 0x7fff);
++ else
++ ac97_write(w->codec, AC97_MASTER_TONE, tone | 0x8000);
++
++ if ((l & 0x4) || (r & 0x4))
++ ac97_write(w->codec, AC97_PHONE, phone & 0x7fff);
++ else
++ ac97_write(w->codec, AC97_PHONE, phone | 0x8000);
++
++ if ((l & 0x8) || (r & 0x8))
++ ac97_write(w->codec, AC97_REC_SEL, rec & 0x7fff);
++ else
++ ac97_write(w->codec, AC97_REC_SEL, rec | 0x8000);
++
++ if ((l & 0x10) || (r & 0x10))
++ ac97_write(w->codec, AC97_PCM, pcm & 0x7fff);
++ else
++ ac97_write(w->codec, AC97_PCM, pcm | 0x8000);
++
++ if ((l & 0x20) || (r & 0x20))
++ ac97_write(w->codec, AC97_AUX, aux & 0x7fff);
++ else
++ ac97_write(w->codec, AC97_AUX, aux | 0x8000);
++
++ return 0;
++}
++
++/* Left Headphone Mixers */
++static const struct snd_kcontrol_new wm9713_hpl_mixer_controls[] = {
++SOC_DAPM_SINGLE("PC Beep Playback Switch", HPL_MIXER, 5, 1, 0),
++SOC_DAPM_SINGLE("Voice Playback Switch", HPL_MIXER, 4, 1, 0),
++SOC_DAPM_SINGLE("Aux Playback Switch", HPL_MIXER, 3, 1, 0),
++SOC_DAPM_SINGLE("PCM Playback Switch", HPL_MIXER, 2, 1, 0),
++SOC_DAPM_SINGLE("MonoIn Playback Switch", HPL_MIXER, 1, 1, 0),
++SOC_DAPM_SINGLE("Bypass Playback Switch", HPL_MIXER, 0, 1, 0),
++};
++
++/* Right Headphone Mixers */
++static const struct snd_kcontrol_new wm9713_hpr_mixer_controls[] = {
++SOC_DAPM_SINGLE("PC Beep Playback Switch", HPR_MIXER, 5, 1, 0),
++SOC_DAPM_SINGLE("Voice Playback Switch", HPR_MIXER, 4, 1, 0),
++SOC_DAPM_SINGLE("Aux Playback Switch", HPR_MIXER, 3, 1, 0),
++SOC_DAPM_SINGLE("PCM Playback Switch", HPR_MIXER, 2, 1, 0),
++SOC_DAPM_SINGLE("MonoIn Playback Switch", HPR_MIXER, 1, 1, 0),
++SOC_DAPM_SINGLE("Bypass Playback Switch", HPR_MIXER, 0, 1, 0),
++};
++
++/* headphone capture mux */
++static const struct snd_kcontrol_new wm9713_hp_rec_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[1]);
++
++/* headphone mic mux */
++static const struct snd_kcontrol_new wm9713_hp_mic_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[0]);
++
++/* Speaker Mixer */
++static const struct snd_kcontrol_new wm9713_speaker_mixer_controls[] = {
++SOC_DAPM_SINGLE("PC Beep Playback Switch", AC97_AUX, 11, 1, 1),
++SOC_DAPM_SINGLE("Voice Playback Switch", AC97_PCM, 11, 1, 1),
++SOC_DAPM_SINGLE("Aux Playback Switch", AC97_REC_SEL, 11, 1, 1),
++SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PHONE, 14, 1, 1),
++SOC_DAPM_SINGLE("MonoIn Playback Switch", AC97_MASTER_TONE, 14, 1, 1),
++SOC_DAPM_SINGLE("Bypass Playback Switch", AC97_PC_BEEP, 14, 1, 1),
++};
++
++/* Mono Mixer */
++static const struct snd_kcontrol_new wm9713_mono_mixer_controls[] = {
++SOC_DAPM_SINGLE("PC Beep Playback Switch", AC97_AUX, 7, 1, 1),
++SOC_DAPM_SINGLE("Voice Playback Switch", AC97_PCM, 7, 1, 1),
++SOC_DAPM_SINGLE("Aux Playback Switch", AC97_REC_SEL, 7, 1, 1),
++SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PHONE, 13, 1, 1),
++SOC_DAPM_SINGLE("MonoIn Playback Switch", AC97_MASTER_TONE, 13, 1, 1),
++SOC_DAPM_SINGLE("Bypass Playback Switch", AC97_PC_BEEP, 13, 1, 1),
++SOC_DAPM_SINGLE("Mic 1 Sidetone Switch", AC97_LINE, 7, 1, 1),
++SOC_DAPM_SINGLE("Mic 2 Sidetone Switch", AC97_LINE, 6, 1, 1),
++};
++
++/* mono mic mux */
++static const struct snd_kcontrol_new wm9713_mono_mic_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[2]);
++
++/* mono output mux */
++static const struct snd_kcontrol_new wm9713_mono_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[7]);
++
++/* speaker left output mux */
++static const struct snd_kcontrol_new wm9713_hp_spkl_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[8]);
++
++/* speaker right output mux */
++static const struct snd_kcontrol_new wm9713_hp_spkr_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[9]);
++
++/* headphone left output mux */
++static const struct snd_kcontrol_new wm9713_hpl_out_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[10]);
++
++/* headphone right output mux */
++static const struct snd_kcontrol_new wm9713_hpr_out_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[11]);
++
++/* Out3 mux */
++static const struct snd_kcontrol_new wm9713_out3_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[12]);
++
++/* Out4 mux */
++static const struct snd_kcontrol_new wm9713_out4_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[13]);
++
++/* DAC inv mux 1 */
++static const struct snd_kcontrol_new wm9713_dac_inv1_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[14]);
++
++/* DAC inv mux 2 */
++static const struct snd_kcontrol_new wm9713_dac_inv2_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[15]);
++
++/* Capture source left */
++static const struct snd_kcontrol_new wm9713_rec_srcl_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[3]);
++
++/* Capture source right */
++static const struct snd_kcontrol_new wm9713_rec_srcr_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[4]);
++
++/* mic source */
++static const struct snd_kcontrol_new wm9713_mic_sel_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[18]);
++
++/* mic source B virtual control */
++static const struct snd_kcontrol_new wm9713_micb_sel_mux_controls =
++SOC_DAPM_ENUM("Route", wm9713_enum[19]);
++
++static const struct snd_soc_dapm_widget wm9713_dapm_widgets[] = {
++SND_SOC_DAPM_MUX("Capture Headphone Mux", SND_SOC_NOPM, 0, 0,
++ &wm9713_hp_rec_mux_controls),
++SND_SOC_DAPM_MUX("Sidetone Mux", SND_SOC_NOPM, 0, 0,
++ &wm9713_hp_mic_mux_controls),
++SND_SOC_DAPM_MUX("Capture Mono Mux", SND_SOC_NOPM, 0, 0,
++ &wm9713_mono_mic_mux_controls),
++SND_SOC_DAPM_MUX("Mono Out Mux", SND_SOC_NOPM, 0, 0,
++ &wm9713_mono_mux_controls),
++SND_SOC_DAPM_MUX("Left Speaker Out Mux", SND_SOC_NOPM, 0, 0,
++ &wm9713_hp_spkl_mux_controls),
++SND_SOC_DAPM_MUX("Right Speaker Out Mux", SND_SOC_NOPM, 0, 0,
++ &wm9713_hp_spkr_mux_controls),
++SND_SOC_DAPM_MUX("Left Headphone Out Mux", SND_SOC_NOPM, 0, 0,
++ &wm9713_hpl_out_mux_controls),
++SND_SOC_DAPM_MUX("Right Headphone Out Mux", SND_SOC_NOPM, 0, 0,
++ &wm9713_hpr_out_mux_controls),
++SND_SOC_DAPM_MUX("Out 3 Mux", SND_SOC_NOPM, 0, 0,
++ &wm9713_out3_mux_controls),
++SND_SOC_DAPM_MUX("Out 4 Mux", SND_SOC_NOPM, 0, 0,
++ &wm9713_out4_mux_controls),
++SND_SOC_DAPM_MUX("DAC Inv Mux 1", SND_SOC_NOPM, 0, 0,
++ &wm9713_dac_inv1_mux_controls),
++SND_SOC_DAPM_MUX("DAC Inv Mux 2", SND_SOC_NOPM, 0, 0,
++ &wm9713_dac_inv2_mux_controls),
++SND_SOC_DAPM_MUX("Left Capture Source", SND_SOC_NOPM, 0, 0,
++ &wm9713_rec_srcl_mux_controls),
++SND_SOC_DAPM_MUX("Right Capture Source", SND_SOC_NOPM, 0, 0,
++ &wm9713_rec_srcr_mux_controls),
++SND_SOC_DAPM_MUX("Mic A Source", SND_SOC_NOPM, 0, 0,
++ &wm9713_mic_sel_mux_controls),
++SND_SOC_DAPM_MUX("Mic B Source", SND_SOC_NOPM, 0, 0,
++ &wm9713_micb_sel_mux_controls),
++SND_SOC_DAPM_MIXER_E("Left HP Mixer", AC97_EXTENDED_MID, 3, 1,
++ &wm9713_hpl_mixer_controls[0], ARRAY_SIZE(wm9713_hpl_mixer_controls),
++ mixer_event, SND_SOC_DAPM_POST_REG),
++SND_SOC_DAPM_MIXER_E("Right HP Mixer", AC97_EXTENDED_MID, 2, 1,
++ &wm9713_hpr_mixer_controls[0], ARRAY_SIZE(wm9713_hpr_mixer_controls),
++ mixer_event, SND_SOC_DAPM_POST_REG),
++SND_SOC_DAPM_MIXER("Mono Mixer", AC97_EXTENDED_MID, 0, 1,
++ &wm9713_mono_mixer_controls[0], ARRAY_SIZE(wm9713_mono_mixer_controls)),
++SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_EXTENDED_MID, 1, 1,
++ &wm9713_speaker_mixer_controls[0],
++ ARRAY_SIZE(wm9713_speaker_mixer_controls)),
++SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", AC97_EXTENDED_MID, 7, 1),
++SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", AC97_EXTENDED_MID, 6, 1),
++SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
++SND_SOC_DAPM_MIXER("HP Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
++SND_SOC_DAPM_MIXER("Line Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
++SND_SOC_DAPM_MIXER("Capture Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
++SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback", AC97_EXTENDED_MID, 12, 1),
++SND_SOC_DAPM_DAC("Aux DAC", "Aux Playback", AC97_EXTENDED_MID, 11, 1),
++SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture", AC97_EXTENDED_MID, 5, 1),
++SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture", AC97_EXTENDED_MID, 4, 1),
++SND_SOC_DAPM_PGA("Left Headphone", AC97_EXTENDED_MSTATUS, 10, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Right Headphone", AC97_EXTENDED_MSTATUS, 9, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Left Speaker", AC97_EXTENDED_MSTATUS, 8, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Right Speaker", AC97_EXTENDED_MSTATUS, 7, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Out 3", AC97_EXTENDED_MSTATUS, 11, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Out 4", AC97_EXTENDED_MSTATUS, 12, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Mono Out", AC97_EXTENDED_MSTATUS, 13, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Left Line In", AC97_EXTENDED_MSTATUS, 6, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Right Line In", AC97_EXTENDED_MSTATUS, 5, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Mono In", AC97_EXTENDED_MSTATUS, 4, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Mic A PGA", AC97_EXTENDED_MSTATUS, 3, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Mic B PGA", AC97_EXTENDED_MSTATUS, 2, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Mic A Pre Amp", AC97_EXTENDED_MSTATUS, 1, 1, NULL, 0),
++SND_SOC_DAPM_PGA("Mic B Pre Amp", AC97_EXTENDED_MSTATUS, 0, 1, NULL, 0),
++SND_SOC_DAPM_MICBIAS("Mic Bias", AC97_EXTENDED_MSTATUS, 14, 1),
++SND_SOC_DAPM_OUTPUT("MONO"),
++SND_SOC_DAPM_OUTPUT("HPL"),
++SND_SOC_DAPM_OUTPUT("HPR"),
++SND_SOC_DAPM_OUTPUT("SPKL"),
++SND_SOC_DAPM_OUTPUT("SPKR"),
++SND_SOC_DAPM_OUTPUT("OUT3"),
++SND_SOC_DAPM_OUTPUT("OUT4"),
++SND_SOC_DAPM_INPUT("LINEL"),
++SND_SOC_DAPM_INPUT("LINER"),
++SND_SOC_DAPM_INPUT("MONOIN"),
++SND_SOC_DAPM_INPUT("PCBEEP"),
++SND_SOC_DAPM_INPUT("MIC1"),
++SND_SOC_DAPM_INPUT("MIC2A"),
++SND_SOC_DAPM_INPUT("MIC2B"),
++SND_SOC_DAPM_VMID("VMID"),
++};
++
++static const char *audio_map[][3] = {
++ /* left HP mixer */
++ {"Left HP Mixer", "PC Beep Playback Switch", "PCBEEP"},
++ {"Left HP Mixer", "Voice Playback Switch", "Voice DAC"},
++ {"Left HP Mixer", "Aux Playback Switch", "Aux DAC"},
++ {"Left HP Mixer", "Bypass Playback Switch", "Left Line In"},
++ {"Left HP Mixer", "PCM Playback Switch", "Left DAC"},
++ {"Left HP Mixer", "MonoIn Playback Switch", "Mono In"},
++ {"Left HP Mixer", NULL, "Capture Headphone Mux"},
++
++ /* right HP mixer */
++ {"Right HP Mixer", "PC Beep Playback Switch", "PCBEEP"},
++ {"Right HP Mixer", "Voice Playback Switch", "Voice DAC"},
++ {"Right HP Mixer", "Aux Playback Switch", "Aux DAC"},
++ {"Right HP Mixer", "Bypass Playback Switch", "Right Line In"},
++ {"Right HP Mixer", "PCM Playback Switch", "Right DAC"},
++ {"Right HP Mixer", "MonoIn Playback Switch", "Mono In"},
++ {"Right HP Mixer", NULL, "Capture Headphone Mux"},
++
++ /* virtual mixer - mixes left & right channels for spk and mono */
++ {"AC97 Mixer", NULL, "Left DAC"},
++ {"AC97 Mixer", NULL, "Right DAC"},
++ {"Line Mixer", NULL, "Right Line In"},
++ {"Line Mixer", NULL, "Left Line In"},
++ {"HP Mixer", NULL, "Left HP Mixer"},
++ {"HP Mixer", NULL, "Right HP Mixer"},
++ {"Capture Mixer", NULL, "Left Capture Source"},
++ {"Capture Mixer", NULL, "Right Capture Source"},
++
++ /* speaker mixer */
++ {"Speaker Mixer", "PC Beep Playback Switch", "PCBEEP"},
++ {"Speaker Mixer", "Voice Playback Switch", "Voice DAC"},
++ {"Speaker Mixer", "Aux Playback Switch", "Aux DAC"},
++ {"Speaker Mixer", "Bypass Playback Switch", "Line Mixer"},
++ {"Speaker Mixer", "PCM Playback Switch", "AC97 Mixer"},
++ {"Speaker Mixer", "MonoIn Playback Switch", "Mono In"},
++
++ /* mono mixer */
++ {"Mono Mixer", "PC Beep Playback Switch", "PCBEEP"},
++ {"Mono Mixer", "Voice Playback Switch", "Voice DAC"},
++ {"Mono Mixer", "Aux Playback Switch", "Aux DAC"},
++ {"Mono Mixer", "Bypass Playback Switch", "Line Mixer"},
++ {"Mono Mixer", "PCM Playback Switch", "AC97 Mixer"},
++ {"Mono Mixer", "Mic 1 Sidetone Switch", "Mic A PGA"},
++ {"Mono Mixer", "Mic 2 Sidetone Switch", "Mic B PGA"},
++ {"Mono Mixer", NULL, "Capture Mono Mux"},
++
++ /* DAC inv mux 1 */
++ {"DAC Inv Mux 1", "Mono", "Mono Mixer"},
++ {"DAC Inv Mux 1", "Speaker", "Speaker Mixer"},
++ {"DAC Inv Mux 1", "Left Headphone", "Left HP Mixer"},
++ {"DAC Inv Mux 1", "Right Headphone", "Right HP Mixer"},
++ {"DAC Inv Mux 1", "Headphone Mono", "HP Mixer"},
++
++ /* DAC inv mux 2 */
++ {"DAC Inv Mux 2", "Mono", "Mono Mixer"},
++ {"DAC Inv Mux 2", "Speaker", "Speaker Mixer"},
++ {"DAC Inv Mux 2", "Left Headphone", "Left HP Mixer"},
++ {"DAC Inv Mux 2", "Right Headphone", "Right HP Mixer"},
++ {"DAC Inv Mux 2", "Headphone Mono", "HP Mixer"},
++
++ /* headphone left mux */
++ {"Left Headphone Out Mux", "Headphone", "Left HP Mixer"},
++
++ /* headphone right mux */
++ {"Right Headphone Out Mux", "Headphone", "Right HP Mixer"},
++
++ /* speaker left mux */
++ {"Left Speaker Out Mux", "Headphone", "Left HP Mixer"},
++ {"Left Speaker Out Mux", "Speaker", "Speaker Mixer"},
++ {"Left Speaker Out Mux", "Inv", "DAC Inv Mux 1"},
++
++ /* speaker right mux */
++ {"Right Speaker Out Mux", "Headphone", "Right HP Mixer"},
++ {"Right Speaker Out Mux", "Speaker", "Speaker Mixer"},
++ {"Right Speaker Out Mux", "Inv", "DAC Inv Mux 2"},
++
++ /* mono mux */
++ {"Mono Out Mux", "Mono", "Mono Mixer"},
++ {"Mono Out Mux", "Inv", "DAC Inv Mux 1"},
++
++ /* out 3 mux */
++ {"Out 3 Mux", "Inv 1", "DAC Inv Mux 1"},
++
++ /* out 4 mux */
++ {"Out 4 Mux", "Inv 2", "DAC Inv Mux 2"},
++
++ /* output pga */
++ {"HPL", NULL, "Left Headphone"},
++ {"Left Headphone", NULL, "Left Headphone Out Mux"},
++ {"HPR", NULL, "Right Headphone"},
++ {"Right Headphone", NULL, "Right Headphone Out Mux"},
++ {"OUT3", NULL, "Out 3"},
++ {"Out 3", NULL, "Out 3 Mux"},
++ {"OUT4", NULL, "Out 4"},
++ {"Out 4", NULL, "Out 4 Mux"},
++ {"SPKL", NULL, "Left Speaker"},
++ {"Left Speaker", NULL, "Left Speaker Out Mux"},
++ {"SPKR", NULL, "Right Speaker"},
++ {"Right Speaker", NULL, "Right Speaker Out Mux"},
++ {"MONO", NULL, "Mono Out"},
++ {"Mono Out", NULL, "Mono Out Mux"},
++
++ /* input pga */
++ {"Left Line In", NULL, "LINEL"},
++ {"Right Line In", NULL, "LINER"},
++ {"Mono In", NULL, "MONOIN"},
++ {"Mic A PGA", NULL, "Mic A Pre Amp"},
++ {"Mic B PGA", NULL, "Mic B Pre Amp"},
++
++ /* left capture select */
++ {"Left Capture Source", "Mic 1", "Mic A Pre Amp"},
++ {"Left Capture Source", "Mic 2", "Mic B Pre Amp"},
++ {"Left Capture Source", "Line", "LINEL"},
++ {"Left Capture Source", "Mono In", "MONOIN"},
++ {"Left Capture Source", "Headphone", "Left HP Mixer"},
++ {"Left Capture Source", "Speaker", "Speaker Mixer"},
++ {"Left Capture Source", "Mono Out", "Mono Mixer"},
++
++ /* right capture select */
++ {"Right Capture Source", "Mic 1", "Mic A Pre Amp"},
++ {"Right Capture Source", "Mic 2", "Mic B Pre Amp"},
++ {"Right Capture Source", "Line", "LINER"},
++ {"Right Capture Source", "Mono In", "MONOIN"},
++ {"Right Capture Source", "Headphone", "Right HP Mixer"},
++ {"Right Capture Source", "Speaker", "Speaker Mixer"},
++ {"Right Capture Source", "Mono Out", "Mono Mixer"},
++
++ /* left ADC */
++ {"Left ADC", NULL, "Left Capture Source"},
++
++ /* right ADC */
++ {"Right ADC", NULL, "Right Capture Source"},
++
++ /* mic */
++ {"Mic A Pre Amp", NULL, "Mic A Source"},
++ {"Mic A Source", "Mic 1", "MIC1"},
++ {"Mic A Source", "Mic 2 A", "MIC2A"},
++ {"Mic A Source", "Mic 2 B", "Mic B Source"},
++ {"Mic B Pre Amp", "MPB", "Mic B Source"},
++ {"Mic B Source", NULL, "MIC2B"},
++
++ /* headphone capture */
++ {"Capture Headphone Mux", "Stereo", "Capture Mixer"},
++ {"Capture Headphone Mux", "Left", "Left Capture Source"},
++ {"Capture Headphone Mux", "Right", "Right Capture Source"},
++
++ /* mono capture */
++ {"Capture Mono Mux", "Stereo", "Capture Mixer"},
++ {"Capture Mono Mux", "Left", "Left Capture Source"},
++ {"Capture Mono Mux", "Right", "Right Capture Source"},
++
++ {NULL, NULL, NULL},
++};
++
++static int wm9713_add_widgets(struct snd_soc_codec *codec)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(wm9713_dapm_widgets); i++)
++ snd_soc_dapm_new_control(codec, &wm9713_dapm_widgets[i]);
++
++ /* set up audio path audio_mapnects */
++ for (i = 0; audio_map[i][0] != NULL; i++)
++ snd_soc_dapm_connect_input(codec, audio_map[i][0],
++ audio_map[i][1], audio_map[i][2]);
++
++ snd_soc_dapm_new_widgets(codec);
++ return 0;
++}
++
++static unsigned int ac97_read(struct snd_soc_codec *codec,
++ unsigned int reg)
++{
++ u16 *cache = codec->reg_cache;
++
++ if (reg == AC97_RESET || reg == AC97_GPIO_STATUS ||
++ reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 ||
++ reg == AC97_CD)
++ return soc_ac97_ops.read(codec->ac97, reg);
++ else {
++ reg = reg >> 1;
++
++ if (reg > (ARRAY_SIZE(wm9713_reg)))
++ return -EIO;
++
++ return cache[reg];
++ }
++}
++
++static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
++ unsigned int val)
++{
++ u16 *cache = codec->reg_cache;
++ if (reg < 0x7c)
++ soc_ac97_ops.write(codec->ac97, reg, val);
++ reg = reg >> 1;
++ if (reg <= (ARRAY_SIZE(wm9713_reg)))
++ cache[reg] = val;
++
++ return 0;
++}
++
++/* PLL divisors */
++struct _pll_div {
++ u32 divsel:1;
++ u32 divctl:1;
++ u32 lf:1;
++ u32 n:4;
++ u32 k:24;
++};
++
++/* The size in bits of the PLL divide multiplied by 10
++ * to allow rounding later */
++#define FIXED_PLL_SIZE ((1 << 22) * 10)
++
++static void pll_factors(struct _pll_div *pll_div, unsigned int source)
++{
++ u64 Kpart;
++ unsigned int K, Ndiv, Nmod, target;
++
++ /* The the PLL output is always 98.304MHz. */
++ target = 98304000;
++
++ /* If the input frequency is over 14.4MHz then scale it down. */
++ if (source > 14400000) {
++ source >>= 1;
++ pll_div->divsel = 1;
++
++ if (source > 14400000) {
++ source >>= 1;
++ pll_div->divctl = 1;
++ } else
++ pll_div->divctl = 0;
++
++ } else {
++ pll_div->divsel = 0;
++ pll_div->divctl = 0;
++ }
++
++ /* Low frequency sources require an additional divide in the
++ * loop.
++ */
++ if (source < 8192000) {
++ pll_div->lf = 1;
++ target >>= 2;
++ } else
++ pll_div->lf = 0;
++
++ Ndiv = target / source;
++ if ((Ndiv < 5) || (Ndiv > 12))
++ printk(KERN_WARNING
++ "WM9713 PLL N value %d out of recommended range!\n",
++ Ndiv);
++
++ pll_div->n = Ndiv;
++ Nmod = target % source;
++ Kpart = FIXED_PLL_SIZE * (long long)Nmod;
++
++ do_div(Kpart, source);
++
++ K = Kpart & 0xFFFFFFFF;
++
++ /* Check if we need to round */
++ if ((K % 10) >= 5)
++ K += 5;
++
++ /* Move down to proper range now rounding is done */
++ K /= 10;
++
++ pll_div->k = K;
++}
++
++/**
++ * Please note that changing the PLL input frequency may require
++ * resynchronisation with the AC97 controller.
++ */
++static int wm9713_set_pll(struct snd_soc_codec *codec,
++ int pll_id, unsigned int freq_in, unsigned int freq_out)
++{
++ struct wm9713_priv *wm9713 = codec->private_data;
++ u16 reg, reg2;
++ struct _pll_div pll_div;
++
++ /* turn PLL off ? */
++ if (freq_in == 0 || freq_out == 0) {
++ /* disable PLL power and select ext source */
++ reg = ac97_read(codec, AC97_HANDSET_RATE);
++ ac97_write(codec, AC97_HANDSET_RATE, reg | 0x0080);
++ reg = ac97_read(codec, AC97_EXTENDED_MID);
++ ac97_write(codec, AC97_EXTENDED_MID, reg | 0x0200);
++ wm9713->pll_out = 0;
++ return 0;
++ }
++
++ pll_factors(&pll_div, freq_in);
++
++ if (pll_div.k == 0) {
++ reg = (pll_div.n << 12) | (pll_div.lf << 11) |
++ (pll_div.divsel << 9) | (pll_div.divctl << 8);
++ ac97_write(codec, AC97_LINE1_LEVEL, reg);
++ } else {
++ /* write the fractional k to the reg 0x46 pages */
++ reg2 = (pll_div.n << 12) | (pll_div.lf << 11) | (1 << 10) |
++ (pll_div.divsel << 9) | (pll_div.divctl << 8);
++
++ /* K [21:20] */
++ reg = reg2 | (0x5 << 4) | (pll_div.k >> 20);
++ ac97_write(codec, AC97_LINE1_LEVEL, reg);
++
++ /* K [19:16] */
++ reg = reg2 | (0x4 << 4) | ((pll_div.k >> 16) & 0xf);
++ ac97_write(codec, AC97_LINE1_LEVEL, reg);
++
++ /* K [15:12] */
++ reg = reg2 | (0x3 << 4) | ((pll_div.k >> 12) & 0xf);
++ ac97_write(codec, AC97_LINE1_LEVEL, reg);
++
++ /* K [11:8] */
++ reg = reg2 | (0x2 << 4) | ((pll_div.k >> 8) & 0xf);
++ ac97_write(codec, AC97_LINE1_LEVEL, reg);
++
++ /* K [7:4] */
++ reg = reg2 | (0x1 << 4) | ((pll_div.k >> 4) & 0xf);
++ ac97_write(codec, AC97_LINE1_LEVEL, reg);
++
++ reg = reg2 | (0x0 << 4) | (pll_div.k & 0xf); /* K [3:0] */
++ ac97_write(codec, AC97_LINE1_LEVEL, reg);
++ }
++
++ /* turn PLL on and select as source */
++ reg = ac97_read(codec, AC97_EXTENDED_MID);
++ ac97_write(codec, AC97_EXTENDED_MID, reg & 0xfdff);
++ reg = ac97_read(codec, AC97_HANDSET_RATE);
++ ac97_write(codec, AC97_HANDSET_RATE, reg & 0xff7f);
++ wm9713->pll_out = freq_out;
++ wm9713->pll_in = freq_in;
++
++ /* wait 10ms AC97 link frames for the link to stabilise */
++ schedule_timeout_interruptible(msecs_to_jiffies(10));
++ return 0;
++}
++
++static int wm9713_set_dai_pll(struct snd_soc_codec_dai *codec_dai,
++ int pll_id, unsigned int freq_in, unsigned int freq_out)
++{
++ struct snd_soc_codec *codec = codec_dai->codec;
++ return wm9713_set_pll(codec, pll_id, freq_in, freq_out);
++}
++
++/*
++ * Tristate the PCM DAI lines, tristate can be disabled by calling
++ * wm9713_set_dai_fmt()
++ */
++static int wm9713_set_dai_tristate(struct snd_soc_codec_dai *codec_dai,
++ int tristate)
++{
++ struct snd_soc_codec *codec = codec_dai->codec;
++ u16 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0x9fff;
++
++ if (tristate)
++ ac97_write(codec, AC97_CENTER_LFE_MASTER, reg);
++
++ return 0;
++}
++
++/*
++ * Configure WM9713 clock dividers.
++ * Voice DAC needs 256 FS
++ */
++static int wm9713_set_dai_clkdiv(struct snd_soc_codec_dai *codec_dai,
++ int div_id, int div)
++{
++ struct snd_soc_codec *codec = codec_dai->codec;
++ u16 reg;
++
++ switch (div_id) {
++ case WM9713_PCMCLK_DIV:
++ reg = ac97_read(codec, AC97_HANDSET_RATE) & 0xf0ff;
++ ac97_write(codec, AC97_HANDSET_RATE, reg | div);
++ break;
++ case WM9713_CLKA_MULT:
++ reg = ac97_read(codec, AC97_HANDSET_RATE) & 0xfffd;
++ ac97_write(codec, AC97_HANDSET_RATE, reg | div);
++ break;
++ case WM9713_CLKB_MULT:
++ reg = ac97_read(codec, AC97_HANDSET_RATE) & 0xfffb;
++ ac97_write(codec, AC97_HANDSET_RATE, reg | div);
++ break;
++ case WM9713_HIFI_DIV:
++ reg = ac97_read(codec, AC97_HANDSET_RATE) & 0x8fff;
++ ac97_write(codec, AC97_HANDSET_RATE, reg | div);
++ break;
++ case WM9713_PCMBCLK_DIV:
++ reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0xf1ff;
++ ac97_write(codec, AC97_CENTER_LFE_MASTER, reg | div);
++ break;
++ case WM9713_PCMCLK_PLL_DIV:
++ reg = ac97_read(codec, AC97_LINE1_LEVEL) & 0xff80;
++ ac97_write(codec, AC97_LINE1_LEVEL, reg | 0x60 | div);
++ break;
++ case WM9713_HIFI_PLL_DIV:
++ reg = ac97_read(codec, AC97_LINE1_LEVEL) & 0xff80;
++ ac97_write(codec, AC97_LINE1_LEVEL, reg | 0x70 | div);
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static int wm9713_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
++ unsigned int fmt)
++{
++ struct snd_soc_codec *codec = codec_dai->codec;
++ u16 gpio = ac97_read(codec, AC97_GPIO_CFG) & 0xffc5;
++ u16 reg = 0x8000;
++
++ /* clock masters */
++ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
++ case SND_SOC_DAIFMT_CBM_CFM:
++ reg |= 0x4000;
++ gpio |= 0x0010;
++ break;
++ case SND_SOC_DAIFMT_CBM_CFS:
++ reg |= 0x6000;
++ gpio |= 0x0018;
++ break;
++ case SND_SOC_DAIFMT_CBS_CFS:
++ reg |= 0x0200;
++ gpio |= 0x001a;
++ break;
++ case SND_SOC_DAIFMT_CBS_CFM:
++ gpio |= 0x0012;
++ break;
++ }
++
++ /* clock inversion */
++ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
++ case SND_SOC_DAIFMT_IB_IF:
++ reg |= 0x00c0;
++ break;
++ case SND_SOC_DAIFMT_IB_NF:
++ reg |= 0x0080;
++ break;
++ case SND_SOC_DAIFMT_NB_IF:
++ reg |= 0x0040;
++ break;
++ }
++
++ /* DAI format */
++ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++ case SND_SOC_DAIFMT_I2S:
++ reg |= 0x0002;
++ break;
++ case SND_SOC_DAIFMT_RIGHT_J:
++ break;
++ case SND_SOC_DAIFMT_LEFT_J:
++ reg |= 0x0001;
++ break;
++ case SND_SOC_DAIFMT_DSP_A:
++ reg |= 0x0003;
++ break;
++ case SND_SOC_DAIFMT_DSP_B:
++ reg |= 0x0043;
++ break;
++ }
++
++ ac97_write(codec, AC97_GPIO_CFG, gpio);
++ ac97_write(codec, AC97_CENTER_LFE_MASTER, reg);
++ return 0;
++}
++
++static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params)
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_device *socdev = rtd->socdev;
++ struct snd_soc_codec *codec = socdev->codec;
++ u16 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0xfff3;
++
++ switch (params_format(params)) {
++ case SNDRV_PCM_FORMAT_S16_LE:
++ break;
++ case SNDRV_PCM_FORMAT_S20_3LE:
++ reg |= 0x0004;
++ break;
++ case SNDRV_PCM_FORMAT_S24_LE:
++ reg |= 0x0008;
++ break;
++ case SNDRV_PCM_FORMAT_S32_LE:
++ reg |= 0x000c;
++ break;
++ }
++
++ /* enable PCM interface in master mode */
++ ac97_write(codec, AC97_CENTER_LFE_MASTER, reg);
++ return 0;
++}
++
++static void wm9713_voiceshutdown(struct snd_pcm_substream *substream)
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_device *socdev = rtd->socdev;
++ struct snd_soc_codec *codec = socdev->codec;
++ u16 status;
++
++ /* Gracefully shut down the voice interface. */
++ status = ac97_read(codec, AC97_EXTENDED_STATUS) | 0x1000;
++ ac97_write(codec, AC97_HANDSET_RATE, 0x0280);
++ schedule_timeout_interruptible(msecs_to_jiffies(1));
++ ac97_write(codec, AC97_HANDSET_RATE, 0x0F80);
++ ac97_write(codec, AC97_EXTENDED_MID, status);
++}
++
++static int ac97_hifi_prepare(struct snd_pcm_substream *substream)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_device *socdev = rtd->socdev;
++ struct snd_soc_codec *codec = socdev->codec;
++ int reg;
++ u16 vra;
++
++ vra = ac97_read(codec, AC97_EXTENDED_STATUS);
++ ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
++
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++ reg = AC97_PCM_FRONT_DAC_RATE;
++ else
++ reg = AC97_PCM_LR_ADC_RATE;
++
++ return ac97_write(codec, reg, runtime->rate);
++}
++
++static int ac97_aux_prepare(struct snd_pcm_substream *substream)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_device *socdev = rtd->socdev;
++ struct snd_soc_codec *codec = socdev->codec;
++ u16 vra, xsle;
++
++ vra = ac97_read(codec, AC97_EXTENDED_STATUS);
++ ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
++ xsle = ac97_read(codec, AC97_PCI_SID);
++ ac97_write(codec, AC97_PCI_SID, xsle | 0x8000);
++
++ if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
++ return -ENODEV;
++
++ return ac97_write(codec, AC97_PCM_SURR_DAC_RATE, runtime->rate);
++}
++
++#define WM9713_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
++ SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\
++ SNDRV_PCM_RATE_48000)
++
++#define WM9713_PCM_FORMATS \
++ (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
++ SNDRV_PCM_FORMAT_S24_LE)
++
++struct snd_soc_codec_dai wm9713_dai[] = {
++{
++ .name = "AC97 HiFi",
++ .type = SND_SOC_DAI_AC97_BUS,
++ .playback = {
++ .stream_name = "HiFi Playback",
++ .channels_min = 1,
++ .channels_max = 2,
++ .rates = WM9713_RATES,
++ .formats = SNDRV_PCM_FMTBIT_S16_LE,},
++ .capture = {
++ .stream_name = "HiFi Capture",
++ .channels_min = 1,
++ .channels_max = 2,
++ .rates = WM9713_RATES,
++ .formats = SNDRV_PCM_FMTBIT_S16_LE,},
++ .ops = {
++ .prepare = ac97_hifi_prepare,},
++ .dai_ops = {
++ .set_clkdiv = wm9713_set_dai_clkdiv,
++ .set_pll = wm9713_set_dai_pll,},
++ },
++ {
++ .name = "AC97 Aux",
++ .playback = {
++ .stream_name = "Aux Playback",
++ .channels_min = 1,
++ .channels_max = 1,
++ .rates = WM9713_RATES,
++ .formats = SNDRV_PCM_FMTBIT_S16_LE,},
++ .ops = {
++ .prepare = ac97_aux_prepare,},
++ .dai_ops = {
++ .set_clkdiv = wm9713_set_dai_clkdiv,
++ .set_pll = wm9713_set_dai_pll,},
++ },
++ {
++ .name = "WM9713 Voice",
++ .playback = {
++ .stream_name = "Voice Playback",
++ .channels_min = 1,
++ .channels_max = 1,
++ .rates = WM9713_RATES,
++ .formats = WM9713_PCM_FORMATS,},
++ .capture = {
++ .stream_name = "Voice Capture",
++ .channels_min = 1,
++ .channels_max = 2,
++ .rates = WM9713_RATES,
++ .formats = WM9713_PCM_FORMATS,},
++ .ops = {
++ .hw_params = wm9713_pcm_hw_params,
++ .shutdown = wm9713_voiceshutdown,},
++ .dai_ops = {
++ .set_clkdiv = wm9713_set_dai_clkdiv,
++ .set_pll = wm9713_set_dai_pll,
++ .set_fmt = wm9713_set_dai_fmt,
++ .set_tristate = wm9713_set_dai_tristate,
++ },
++ },
++};
++EXPORT_SYMBOL_GPL(wm9713_dai);
++
++int wm9713_reset(struct snd_soc_codec *codec, int try_warm)
++{
++ if (try_warm && soc_ac97_ops.warm_reset) {
++ soc_ac97_ops.warm_reset(codec->ac97);
++ if (!(ac97_read(codec, 0) & 0x8000))
++ return 1;
++ }
++
++ soc_ac97_ops.reset(codec->ac97);
++ if (ac97_read(codec, 0) & 0x8000)
++ return -EIO;
++ return 0;
++}
++EXPORT_SYMBOL_GPL(wm9713_reset);
++
++static int wm9713_dapm_event(struct snd_soc_codec *codec, int event)
++{
++ u16 reg;
++
++ switch (event) {
++ case SNDRV_CTL_POWER_D0: /* full On */
++ /* enable thermal shutdown */
++ reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x1bff;
++ ac97_write(codec, AC97_EXTENDED_MID, reg);
++ break;
++ case SNDRV_CTL_POWER_D1: /* partial On */
++ case SNDRV_CTL_POWER_D2: /* partial On */
++ break;
++ case SNDRV_CTL_POWER_D3hot: /* Off, with power */
++ /* enable master bias and vmid */
++ reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x3bff;
++ ac97_write(codec, AC97_EXTENDED_MID, reg);
++ ac97_write(codec, AC97_POWERDOWN, 0x0000);
++ break;
++ case SNDRV_CTL_POWER_D3cold: /* Off, without power */
++ /* disable everything including AC link */
++ ac97_write(codec, AC97_EXTENDED_MID, 0xffff);
++ ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
++ ac97_write(codec, AC97_POWERDOWN, 0xffff);
++ break;
++ }
++ codec->dapm_state = event;
++ return 0;
++}
++
++static int wm9713_soc_suspend(struct platform_device *pdev,
++ pm_message_t state)
++{
++ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++ struct snd_soc_codec *codec = socdev->codec;
++ u16 reg;
++
++ /* Disable everything except touchpanel - that will be handled
++ * by the touch driver and left disabled if touch is not in
++ * use. */
++ reg = ac97_read(codec, AC97_EXTENDED_MID);
++ ac97_write(codec, AC97_EXTENDED_MID, reg | 0x7fff);
++ ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
++ ac97_write(codec, AC97_POWERDOWN, 0x6f00);
++ ac97_write(codec, AC97_POWERDOWN, 0xffff);
++
++ return 0;
++}
++
++static int wm9713_soc_resume(struct platform_device *pdev)
++{
++ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++ struct snd_soc_codec *codec = socdev->codec;
++ struct wm9713_priv *wm9713 = codec->private_data;
++ int i, ret;
++ u16 *cache = codec->reg_cache;
++
++ ret = wm9713_reset(codec, 1);
++ if (ret < 0) {
++ printk(KERN_ERR "could not reset AC97 codec\n");
++ return ret;
++ }
++
++ wm9713_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++
++ /* do we need to re-start the PLL ? */
++ if (wm9713->pll_out)
++ wm9713_set_pll(codec, 0, wm9713->pll_in, wm9713->pll_out);
++
++ /* only synchronise the codec if warm reset failed */
++ if (ret == 0) {
++ for (i = 2; i < ARRAY_SIZE(wm9713_reg) << 1; i += 2) {
++ if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID ||
++ i == AC97_EXTENDED_MSTATUS || i > 0x66)
++ continue;
++ soc_ac97_ops.write(codec->ac97, i, cache[i>>1]);
++ }
++ }
++
++ if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0)
++ wm9713_dapm_event(codec, SNDRV_CTL_POWER_D0);
++
++ return ret;
++}
++
++static int wm9713_soc_probe(struct platform_device *pdev)
++{
++ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++ struct snd_soc_codec *codec;
++ int ret = 0, reg;
++
++ printk(KERN_INFO "WM9713/WM9714 SoC Audio Codec %s\n", WM9713_VERSION);
++
++ socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
++ if (socdev->codec == NULL)
++ return -ENOMEM;
++ codec = socdev->codec;
++ mutex_init(&codec->mutex);
++
++ codec->reg_cache = kmemdup(wm9713_reg, sizeof(wm9713_reg), GFP_KERNEL);
++ if (codec->reg_cache == NULL) {
++ ret = -ENOMEM;
++ goto cache_err;
++ }
++ codec->reg_cache_size = sizeof(wm9713_reg);
++ codec->reg_cache_step = 2;
++
++ codec->private_data = kzalloc(sizeof(struct wm9713_priv), GFP_KERNEL);
++ if (codec->private_data == NULL) {
++ ret = -ENOMEM;
++ goto priv_err;
++ }
++
++ codec->name = "WM9713";
++ codec->owner = THIS_MODULE;
++ codec->dai = wm9713_dai;
++ codec->num_dai = ARRAY_SIZE(wm9713_dai);
++ codec->write = ac97_write;
++ codec->read = ac97_read;
++ codec->dapm_event = wm9713_dapm_event;
++ INIT_LIST_HEAD(&codec->dapm_widgets);
++ INIT_LIST_HEAD(&codec->dapm_paths);
++
++ ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
++ if (ret < 0)
++ goto codec_err;
++
++ /* register pcms */
++ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
++ if (ret < 0)
++ goto pcm_err;
++
++ /* do a cold reset for the controller and then try
++ * a warm reset followed by an optional cold reset for codec */
++ wm9713_reset(codec, 0);
++ ret = wm9713_reset(codec, 1);
++ if (ret < 0) {
++ printk(KERN_ERR "AC97 link error\n");
++ goto reset_err;
++ }
++
++ wm9713_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++
++ /* unmute the adc - move to kcontrol */
++ reg = ac97_read(codec, AC97_CD) & 0x7fff;
++ ac97_write(codec, AC97_CD, reg);
++
++ wm9713_add_controls(codec);
++ wm9713_add_widgets(codec);
++ ret = snd_soc_register_card(socdev);
++ if (ret < 0)
++ goto reset_err;
++ return 0;
++
++reset_err:
++ snd_soc_free_pcms(socdev);
++
++pcm_err:
++ snd_soc_free_ac97_codec(codec);
++
++codec_err:
++ kfree(codec->private_data);
++
++priv_err:
++ kfree(codec->reg_cache);
++
++cache_err:
++ kfree(socdev->codec);
++ socdev->codec = NULL;
++ return ret;
++}
++
++static int wm9713_soc_remove(struct platform_device *pdev)
++{
++ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++ struct snd_soc_codec *codec = socdev->codec;
++
++ if (codec == NULL)
++ return 0;
++
++ snd_soc_dapm_free(socdev);
++ snd_soc_free_pcms(socdev);
++ snd_soc_free_ac97_codec(codec);
++ kfree(codec->private_data);
++ kfree(codec->reg_cache);
++ kfree(codec->dai);
++ kfree(codec);
++ return 0;
++}
++
++struct snd_soc_codec_device soc_codec_dev_wm9713 = {
++ .probe = wm9713_soc_probe,
++ .remove = wm9713_soc_remove,
++ .suspend = wm9713_soc_suspend,
++ .resume = wm9713_soc_resume,
++};
++EXPORT_SYMBOL_GPL(soc_codec_dev_wm9713);
++
++MODULE_DESCRIPTION("ASoC WM9713/WM9714 driver");
++MODULE_AUTHOR("Liam Girdwood");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/codecs/wm9713.h b/sound/soc/codecs/wm9713.h
+new file mode 100644
+index 0000000..d357b6c
+--- /dev/null
++++ b/sound/soc/codecs/wm9713.h
+@@ -0,0 +1,53 @@
++/*
++ * wm9713.h -- WM9713 Soc Audio driver
++ */
++
++#ifndef _WM9713_H
++#define _WM9713_H
++
++/* clock inputs */
++#define WM9713_CLKA_PIN 0
++#define WM9713_CLKB_PIN 1
++
++/* clock divider ID's */
++#define WM9713_PCMCLK_DIV 0
++#define WM9713_CLKA_MULT 1
++#define WM9713_CLKB_MULT 2
++#define WM9713_HIFI_DIV 3
++#define WM9713_PCMBCLK_DIV 4
++#define WM9713_PCMCLK_PLL_DIV 5
++#define WM9713_HIFI_PLL_DIV 6
++
++/* Calculate the appropriate bit mask for the external PCM clock divider */
++#define WM9713_PCMDIV(x) ((x - 1) << 8)
++
++/* Calculate the appropriate bit mask for the external HiFi clock divider */
++#define WM9713_HIFIDIV(x) ((x - 1) << 12)
++
++/* MCLK clock mulitipliers */
++#define WM9713_CLKA_X1 (0 << 1)
++#define WM9713_CLKA_X2 (1 << 1)
++#define WM9713_CLKB_X1 (0 << 2)
++#define WM9713_CLKB_X2 (1 << 2)
++
++/* MCLK clock MUX */
++#define WM9713_CLK_MUX_A (0 << 0)
++#define WM9713_CLK_MUX_B (1 << 0)
++
++/* Voice DAI BCLK divider */
++#define WM9713_PCMBCLK_DIV_1 (0 << 9)
++#define WM9713_PCMBCLK_DIV_2 (1 << 9)
++#define WM9713_PCMBCLK_DIV_4 (2 << 9)
++#define WM9713_PCMBCLK_DIV_8 (3 << 9)
++#define WM9713_PCMBCLK_DIV_16 (4 << 9)
++
++#define WM9713_DAI_AC97_HIFI 0
++#define WM9713_DAI_AC97_AUX 1
++#define WM9713_DAI_PCM_VOICE 2
++
++extern struct snd_soc_codec_device soc_codec_dev_wm9713;
++extern struct snd_soc_codec_dai wm9713_dai[3];
++
++int wm9713_reset(struct snd_soc_codec *codec, int try_warm);
++
++#endif
+diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
+new file mode 100644
+index 0000000..20680c5
+--- /dev/null
++++ b/sound/soc/davinci/Kconfig
+@@ -0,0 +1,19 @@
++config SND_DAVINCI_SOC
++ tristate "SoC Audio for the TI DAVINCI chip"
++ depends on ARCH_DAVINCI && SND_SOC
++ help
++ Say Y or M if you want to add support for codecs attached to
++ the DAVINCI AC97 or I2S interface. You will also need
++ to select the audio interfaces to support below.
++
++config SND_DAVINCI_SOC_I2S
++ tristate
++
++config SND_DAVINCI_SOC_EVM
++ tristate "SoC Audio support for DaVinci EVM"
++ depends on SND_DAVINCI_SOC && MACH_DAVINCI_EVM
++ select SND_DAVINCI_SOC_I2S
++ select SND_SOC_TLV320AIC3X
++ help
++ Say Y if you want to add support for SoC audio on TI
++ DaVinci EVM platform.
+diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile
+new file mode 100644
+index 0000000..ca772e5
+--- /dev/null
++++ b/sound/soc/davinci/Makefile
+@@ -0,0 +1,11 @@
++# DAVINCI Platform Support
++snd-soc-davinci-objs := davinci-pcm.o
++snd-soc-davinci-i2s-objs := davinci-i2s.o
++
++obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o
++obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o
++
++# DAVINCI Machine Support
++snd-soc-evm-objs := davinci-evm.o
++
++obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o
+diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
+new file mode 100644
+index 0000000..fcd1652
+--- /dev/null
++++ b/sound/soc/davinci/davinci-evm.c
+@@ -0,0 +1,208 @@
++/*
++ * ASoC driver for TI DAVINCI EVM platform
++ *
++ * Author: Vladimir Barinov, <vbarinov at ru.mvista.com>
++ * Copyright: (C) 2007 MontaVista Software, Inc., <source at mvista.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/timer.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/soc.h>
++#include <sound/soc-dapm.h>
++
++#include <asm/mach-types.h>
++#include <asm/dma.h>
++#include <asm/arch/hardware.h>
++
++#include "../codecs/tlv320aic3x.h"
++#include "davinci-pcm.h"
++#include "davinci-i2s.h"
++
++#define EVM_CODEC_CLOCK 22579200
++
++static int evm_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params)
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
++ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
++ int ret = 0;
++
++ /* set codec DAI configuration */
++ ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
++ SND_SOC_DAIFMT_CBM_CFM);
++ if (ret < 0)
++ return ret;
++
++ /* set cpu DAI configuration */
++ ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM |
++ SND_SOC_DAIFMT_IB_NF);
++ if (ret < 0)
++ return ret;
++
++ /* set the codec system clock */
++ ret = codec_dai->dai_ops.set_sysclk(codec_dai, 0, EVM_CODEC_CLOCK,
++ SND_SOC_CLOCK_OUT);
++ if (ret < 0)
++ return ret;
++
++ return 0;
++}
++
++static struct snd_soc_ops evm_ops = {
++ .hw_params = evm_hw_params,
++};
++
++/* davinci-evm machine dapm widgets */
++static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
++ SND_SOC_DAPM_HP("Headphone Jack", NULL),
++ SND_SOC_DAPM_LINE("Line Out", NULL),
++ SND_SOC_DAPM_MIC("Mic Jack", NULL),
++ SND_SOC_DAPM_LINE("Line In", NULL),
++};
++
++/* davinci-evm machine audio_mapnections to the codec pins */
++static const char *audio_map[][3] = {
++ /* Headphone connected to HPLOUT, HPROUT */
++ {"Headphone Jack", NULL, "HPLOUT"},
++ {"Headphone Jack", NULL, "HPROUT"},
++
++ /* Line Out connected to LLOUT, RLOUT */
++ {"Line Out", NULL, "LLOUT"},
++ {"Line Out", NULL, "RLOUT"},
++
++ /* Mic connected to (MIC3L | MIC3R) */
++ {"MIC3L", NULL, "Mic Bias 2V"},
++ {"MIC3R", NULL, "Mic Bias 2V"},
++ {"Mic Bias 2V", NULL, "Mic Jack"},
++
++ /* Line In connected to (LINE1L | LINE2L), (LINE1R | LINE2R) */
++ {"LINE1L", NULL, "Line In"},
++ {"LINE2L", NULL, "Line In"},
++ {"LINE1R", NULL, "Line In"},
++ {"LINE2R", NULL, "Line In"},
++
++ {NULL, NULL, NULL},
++};
++
++/* Logic for a aic3x as connected on a davinci-evm */
++static int evm_aic3x_init(struct snd_soc_codec *codec)
++{
++ int i;
++
++ /* Add davinci-evm specific widgets */
++ for (i = 0; i < ARRAY_SIZE(aic3x_dapm_widgets); i++)
++ snd_soc_dapm_new_control(codec, &aic3x_dapm_widgets[i]);
++
++ /* Set up davinci-evm specific audio path audio_map */
++ for (i = 0; audio_map[i][0] != NULL; i++)
++ snd_soc_dapm_connect_input(codec, audio_map[i][0],
++ audio_map[i][1], audio_map[i][2]);
++
++ /* not connected */
++ snd_soc_dapm_set_endpoint(codec, "MONO_LOUT", 0);
++ snd_soc_dapm_set_endpoint(codec, "HPLCOM", 0);
++ snd_soc_dapm_set_endpoint(codec, "HPRCOM", 0);
++
++ /* always connected */
++ snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 1);
++ snd_soc_dapm_set_endpoint(codec, "Line Out", 1);
++ snd_soc_dapm_set_endpoint(codec, "Mic Jack", 1);
++ snd_soc_dapm_set_endpoint(codec, "Line In", 1);
++
++ snd_soc_dapm_sync_endpoints(codec);
++
++ return 0;
++}
++
++/* davinci-evm digital audio interface glue - connects codec <--> CPU */
++static struct snd_soc_dai_link evm_dai = {
++ .name = "TLV320AIC3X",
++ .stream_name = "AIC3X",
++ .cpu_dai = &davinci_i2s_dai,
++ .codec_dai = &aic3x_dai,
++ .init = evm_aic3x_init,
++ .ops = &evm_ops,
++};
++
++/* davinci-evm audio machine driver */
++static struct snd_soc_machine snd_soc_machine_evm = {
++ .name = "DaVinci EVM",
++ .dai_link = &evm_dai,
++ .num_links = 1,
++};
++
++/* evm audio private data */
++static struct aic3x_setup_data evm_aic3x_setup = {
++ .i2c_address = 0x1b,
++};
++
++/* evm audio subsystem */
++static struct snd_soc_device evm_snd_devdata = {
++ .machine = &snd_soc_machine_evm,
++ .platform = &davinci_soc_platform,
++ .codec_dev = &soc_codec_dev_aic3x,
++ .codec_data = &evm_aic3x_setup,
++};
++
++static struct resource evm_snd_resources[] = {
++ {
++ .start = DAVINCI_MCBSP_BASE,
++ .end = DAVINCI_MCBSP_BASE + SZ_8K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++};
++
++static struct evm_snd_platform_data evm_snd_data = {
++ .tx_dma_ch = DM644X_DMACH_MCBSP_TX,
++ .rx_dma_ch = DM644X_DMACH_MCBSP_RX,
++};
++
++static struct platform_device *evm_snd_device;
++
++static int __init evm_init(void)
++{
++ int ret;
++
++ evm_snd_device = platform_device_alloc("soc-audio", 0);
++ if (!evm_snd_device)
++ return -ENOMEM;
++
++ platform_set_drvdata(evm_snd_device, &evm_snd_devdata);
++ evm_snd_devdata.dev = &evm_snd_device->dev;
++ evm_snd_device->dev.platform_data = &evm_snd_data;
++
++ ret = platform_device_add_resources(evm_snd_device, evm_snd_resources,
++ ARRAY_SIZE(evm_snd_resources));
++ if (ret) {
++ platform_device_put(evm_snd_device);
++ return ret;
++ }
++
++ ret = platform_device_add(evm_snd_device);
++ if (ret)
++ platform_device_put(evm_snd_device);
++
++ return ret;
++}
++
++static void __exit evm_exit(void)
++{
++ platform_device_unregister(evm_snd_device);
++}
++
++module_init(evm_init);
++module_exit(evm_exit);
++
++MODULE_AUTHOR("Vladimir Barinov");
++MODULE_DESCRIPTION("TI DAVINCI EVM ASoC driver");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
+new file mode 100644
+index 0000000..c421774
+--- /dev/null
++++ b/sound/soc/davinci/davinci-i2s.c
+@@ -0,0 +1,407 @@
++/*
++ * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor
++ *
++ * Author: Vladimir Barinov, <vbarinov at ru.mvista.com>
++ * Copyright: (C) 2007 MontaVista Software, Inc., <source at mvista.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/device.h>
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <linux/clk.h>
++
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/initval.h>
++#include <sound/soc.h>
++
++#include "davinci-pcm.h"
++
++#define DAVINCI_MCBSP_DRR_REG 0x00
++#define DAVINCI_MCBSP_DXR_REG 0x04
++#define DAVINCI_MCBSP_SPCR_REG 0x08
++#define DAVINCI_MCBSP_RCR_REG 0x0c
++#define DAVINCI_MCBSP_XCR_REG 0x10
++#define DAVINCI_MCBSP_SRGR_REG 0x14
++#define DAVINCI_MCBSP_PCR_REG 0x24
++
++#define DAVINCI_MCBSP_SPCR_RRST (1 << 0)
++#define DAVINCI_MCBSP_SPCR_RINTM(v) ((v) << 4)
++#define DAVINCI_MCBSP_SPCR_XRST (1 << 16)
++#define DAVINCI_MCBSP_SPCR_XINTM(v) ((v) << 20)
++#define DAVINCI_MCBSP_SPCR_GRST (1 << 22)
++#define DAVINCI_MCBSP_SPCR_FRST (1 << 23)
++#define DAVINCI_MCBSP_SPCR_FREE (1 << 25)
++
++#define DAVINCI_MCBSP_RCR_RWDLEN1(v) ((v) << 5)
++#define DAVINCI_MCBSP_RCR_RFRLEN1(v) ((v) << 8)
++#define DAVINCI_MCBSP_RCR_RDATDLY(v) ((v) << 16)
++#define DAVINCI_MCBSP_RCR_RWDLEN2(v) ((v) << 21)
++
++#define DAVINCI_MCBSP_XCR_XWDLEN1(v) ((v) << 5)
++#define DAVINCI_MCBSP_XCR_XFRLEN1(v) ((v) << 8)
++#define DAVINCI_MCBSP_XCR_XDATDLY(v) ((v) << 16)
++#define DAVINCI_MCBSP_XCR_XFIG (1 << 18)
++#define DAVINCI_MCBSP_XCR_XWDLEN2(v) ((v) << 21)
++
++#define DAVINCI_MCBSP_SRGR_FWID(v) ((v) << 8)
++#define DAVINCI_MCBSP_SRGR_FPER(v) ((v) << 16)
++#define DAVINCI_MCBSP_SRGR_FSGM (1 << 28)
++
++#define DAVINCI_MCBSP_PCR_CLKRP (1 << 0)
++#define DAVINCI_MCBSP_PCR_CLKXP (1 << 1)
++#define DAVINCI_MCBSP_PCR_FSRP (1 << 2)
++#define DAVINCI_MCBSP_PCR_FSXP (1 << 3)
++#define DAVINCI_MCBSP_PCR_CLKRM (1 << 8)
++#define DAVINCI_MCBSP_PCR_CLKXM (1 << 9)
++#define DAVINCI_MCBSP_PCR_FSRM (1 << 10)
++#define DAVINCI_MCBSP_PCR_FSXM (1 << 11)
++
++#define MOD_REG_BIT(val, mask, set) do { \
++ if (set) { \
++ val |= mask; \
++ } else { \
++ val &= ~mask; \
++ } \
++} while (0)
++
++enum {
++ DAVINCI_MCBSP_WORD_8 = 0,
++ DAVINCI_MCBSP_WORD_12,
++ DAVINCI_MCBSP_WORD_16,
++ DAVINCI_MCBSP_WORD_20,
++ DAVINCI_MCBSP_WORD_24,
++ DAVINCI_MCBSP_WORD_32,
++};
++
++static struct davinci_pcm_dma_params davinci_i2s_pcm_out = {
++ .name = "I2S PCM Stereo out",
++};
++
++static struct davinci_pcm_dma_params davinci_i2s_pcm_in = {
++ .name = "I2S PCM Stereo in",
++};
++
++struct davinci_mcbsp_dev {
++ void __iomem *base;
++ struct clk *clk;
++ struct davinci_pcm_dma_params *dma_params[2];
++};
++
++static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev,
++ int reg, u32 val)
++{
++ __raw_writel(val, dev->base + reg);
++}
++
++static inline u32 davinci_mcbsp_read_reg(struct davinci_mcbsp_dev *dev, int reg)
++{
++ return __raw_readl(dev->base + reg);
++}
++
++static void davinci_mcbsp_start(struct snd_pcm_substream *substream)
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
++ u32 w;
++
++ /* Start the sample generator and enable transmitter/receiver */
++ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
++ MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST, 1);
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++ MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1);
++ else
++ MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 1);
++ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
++
++ /* Start frame sync */
++ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
++ MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_FRST, 1);
++ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
++}
++
++static void davinci_mcbsp_stop(struct snd_pcm_substream *substream)
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
++ u32 w;
++
++ /* Reset transmitter/receiver and sample rate/frame sync generators */
++ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
++ MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST |
++ DAVINCI_MCBSP_SPCR_FRST, 0);
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++ MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 0);
++ else
++ MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 0);
++ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
++}
++
++static int davinci_i2s_startup(struct snd_pcm_substream *substream)
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
++ struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
++
++ cpu_dai->dma_data = dev->dma_params[substream->stream];
++
++ return 0;
++}
++
++static int davinci_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
++ unsigned int fmt)
++{
++ struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
++ u32 w;
++
++ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
++ case SND_SOC_DAIFMT_CBS_CFS:
++ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG,
++ DAVINCI_MCBSP_PCR_FSXM |
++ DAVINCI_MCBSP_PCR_FSRM |
++ DAVINCI_MCBSP_PCR_CLKXM |
++ DAVINCI_MCBSP_PCR_CLKRM);
++ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG,
++ DAVINCI_MCBSP_SRGR_FSGM);
++ break;
++ case SND_SOC_DAIFMT_CBM_CFM:
++ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, 0);
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
++ case SND_SOC_DAIFMT_IB_NF:
++ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_PCR_REG);
++ MOD_REG_BIT(w, DAVINCI_MCBSP_PCR_CLKXP |
++ DAVINCI_MCBSP_PCR_CLKRP, 1);
++ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, w);
++ break;
++ case SND_SOC_DAIFMT_NB_IF:
++ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_PCR_REG);
++ MOD_REG_BIT(w, DAVINCI_MCBSP_PCR_FSXP |
++ DAVINCI_MCBSP_PCR_FSRP, 1);
++ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, w);
++ break;
++ case SND_SOC_DAIFMT_IB_IF:
++ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_PCR_REG);
++ MOD_REG_BIT(w, DAVINCI_MCBSP_PCR_CLKXP |
++ DAVINCI_MCBSP_PCR_CLKRP |
++ DAVINCI_MCBSP_PCR_FSXP |
++ DAVINCI_MCBSP_PCR_FSRP, 1);
++ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, w);
++ break;
++ case SND_SOC_DAIFMT_NB_NF:
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params)
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct davinci_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data;
++ struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
++ struct snd_interval *i = NULL;
++ int mcbsp_word_length;
++ u32 w;
++
++ /* general line settings */
++ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG,
++ DAVINCI_MCBSP_SPCR_RINTM(3) |
++ DAVINCI_MCBSP_SPCR_XINTM(3) |
++ DAVINCI_MCBSP_SPCR_FREE);
++ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG,
++ DAVINCI_MCBSP_RCR_RFRLEN1(1) |
++ DAVINCI_MCBSP_RCR_RDATDLY(1));
++ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG,
++ DAVINCI_MCBSP_XCR_XFRLEN1(1) |
++ DAVINCI_MCBSP_XCR_XDATDLY(1) |
++ DAVINCI_MCBSP_XCR_XFIG);
++
++ i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
++ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SRGR_REG);
++ MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1), 1);
++ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, w);
++
++ i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS);
++ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SRGR_REG);
++ MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1), 1);
++ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, w);
++
++ /* Determine xfer data type */
++ switch (params_format(params)) {
++ case SNDRV_PCM_FORMAT_S8:
++ dma_params->data_type = 1;
++ mcbsp_word_length = DAVINCI_MCBSP_WORD_8;
++ break;
++ case SNDRV_PCM_FORMAT_S16_LE:
++ dma_params->data_type = 2;
++ mcbsp_word_length = DAVINCI_MCBSP_WORD_16;
++ break;
++ case SNDRV_PCM_FORMAT_S32_LE:
++ dma_params->data_type = 4;
++ mcbsp_word_length = DAVINCI_MCBSP_WORD_32;
++ break;
++ default:
++ printk(KERN_WARNING "davinci-i2s: unsupported PCM format");
++ return -EINVAL;
++ }
++
++ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_RCR_REG);
++ MOD_REG_BIT(w, DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
++ DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length), 1);
++ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, w);
++
++ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_XCR_REG);
++ MOD_REG_BIT(w, DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) |
++ DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length), 1);
++ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, w);
++
++ return 0;
++}
++
++static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++ int ret = 0;
++
++ switch (cmd) {
++ case SNDRV_PCM_TRIGGER_START:
++ case SNDRV_PCM_TRIGGER_RESUME:
++ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++ davinci_mcbsp_start(substream);
++ break;
++ case SNDRV_PCM_TRIGGER_STOP:
++ case SNDRV_PCM_TRIGGER_SUSPEND:
++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++ davinci_mcbsp_stop(substream);
++ break;
++ default:
++ ret = -EINVAL;
++ }
++
++ return ret;
++}
++
++static int davinci_i2s_probe(struct platform_device *pdev)
++{
++ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++ struct snd_soc_machine *machine = socdev->machine;
++ struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai;
++ struct davinci_mcbsp_dev *dev;
++ struct resource *mem, *ioarea;
++ struct evm_snd_platform_data *pdata;
++ int ret;
++
++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!mem) {
++ dev_err(&pdev->dev, "no mem resource?\n");
++ return -ENODEV;
++ }
++
++ ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1,
++ pdev->name);
++ if (!ioarea) {
++ dev_err(&pdev->dev, "McBSP region already claimed\n");
++ return -EBUSY;
++ }
++
++ dev = kzalloc(sizeof(struct davinci_mcbsp_dev), GFP_KERNEL);
++ if (!dev) {
++ ret = -ENOMEM;
++ goto err_release_region;
++ }
++
++ cpu_dai->private_data = dev;
++
++ dev->clk = clk_get(&pdev->dev, "McBSPCLK");
++ if (IS_ERR(dev->clk)) {
++ ret = -ENODEV;
++ goto err_free_mem;
++ }
++ clk_enable(dev->clk);
++
++ dev->base = (void __iomem *)IO_ADDRESS(mem->start);
++ pdata = pdev->dev.platform_data;
++
++ dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK] = &davinci_i2s_pcm_out;
++ dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->channel = pdata->tx_dma_ch;
++ dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->dma_addr =
++ (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DXR_REG);
++
++ dev->dma_params[SNDRV_PCM_STREAM_CAPTURE] = &davinci_i2s_pcm_in;
++ dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->channel = pdata->rx_dma_ch;
++ dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->dma_addr =
++ (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DRR_REG);
++
++ return 0;
++
++err_free_mem:
++ kfree(dev);
++err_release_region:
++ release_mem_region(mem->start, (mem->end - mem->start) + 1);
++
++ return ret;
++}
++
++static void davinci_i2s_remove(struct platform_device *pdev)
++{
++ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++ struct snd_soc_machine *machine = socdev->machine;
++ struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai;
++ struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
++ struct resource *mem;
++
++ clk_disable(dev->clk);
++ clk_put(dev->clk);
++ dev->clk = NULL;
++
++ kfree(dev);
++
++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ release_mem_region(mem->start, (mem->end - mem->start) + 1);
++}
++
++#define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000
++
++struct snd_soc_cpu_dai davinci_i2s_dai = {
++ .name = "davinci-i2s",
++ .id = 0,
++ .type = SND_SOC_DAI_I2S,
++ .probe = davinci_i2s_probe,
++ .remove = davinci_i2s_remove,
++ .playback = {
++ .channels_min = 2,
++ .channels_max = 2,
++ .rates = DAVINCI_I2S_RATES,
++ .formats = SNDRV_PCM_FMTBIT_S16_LE,},
++ .capture = {
++ .channels_min = 2,
++ .channels_max = 2,
++ .rates = DAVINCI_I2S_RATES,
++ .formats = SNDRV_PCM_FMTBIT_S16_LE,},
++ .ops = {
++ .startup = davinci_i2s_startup,
++ .trigger = davinci_i2s_trigger,
++ .hw_params = davinci_i2s_hw_params,},
++ .dai_ops = {
++ .set_fmt = davinci_i2s_set_dai_fmt,
++ },
++};
++EXPORT_SYMBOL_GPL(davinci_i2s_dai);
++
++MODULE_AUTHOR("Vladimir Barinov");
++MODULE_DESCRIPTION("TI DAVINCI I2S (McBSP) SoC Interface");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/davinci/davinci-i2s.h b/sound/soc/davinci/davinci-i2s.h
+new file mode 100644
+index 0000000..9592d17
+--- /dev/null
++++ b/sound/soc/davinci/davinci-i2s.h
+@@ -0,0 +1,17 @@
++/*
++ * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor
++ *
++ * Author: Vladimir Barinov, <vbarinov at ru.mvista.com>
++ * Copyright: (C) 2007 MontaVista Software, Inc., <source at mvista.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef _DAVINCI_I2S_H
++#define _DAVINCI_I2S_H
++
++extern struct snd_soc_cpu_dai davinci_i2s_dai;
++
++#endif
+diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
+new file mode 100644
+index 0000000..6a76927
+--- /dev/null
++++ b/sound/soc/davinci/davinci-pcm.c
+@@ -0,0 +1,389 @@
++/*
++ * ALSA PCM interface for the TI DAVINCI processor
++ *
++ * Author: Vladimir Barinov, <vbarinov at ru.mvista.com>
++ * Copyright: (C) 2007 MontaVista Software, Inc., <source at mvista.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++#include <linux/dma-mapping.h>
++
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++
++#include <asm/dma.h>
++
++#include "davinci-pcm.h"
++
++#define DAVINCI_PCM_DEBUG 0
++#if DAVINCI_PCM_DEBUG
++#define DPRINTK(x...) printk(KERN_DEBUG x)
++#else
++#define DPRINTK(x...)
++#endif
++
++static struct snd_pcm_hardware davinci_pcm_hardware = {
++ .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
++ SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
++ SNDRV_PCM_INFO_PAUSE),
++ .formats = (SNDRV_PCM_FMTBIT_S16_LE),
++ .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
++ SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
++ SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
++ SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
++ SNDRV_PCM_RATE_KNOT),
++ .rate_min = 8000,
++ .rate_max = 96000,
++ .channels_min = 2,
++ .channels_max = 2,
++ .buffer_bytes_max = 128 * 1024,
++ .period_bytes_min = 32,
++ .period_bytes_max = 8 * 1024,
++ .periods_min = 16,
++ .periods_max = 255,
++ .fifo_size = 0,
++};
++
++struct davinci_runtime_data {
++ spinlock_t lock;
++ int period; /* current DMA period */
++ int master_lch; /* Master DMA channel */
++ int slave_lch; /* Slave DMA channel */
++ struct davinci_pcm_dma_params *params; /* DMA params */
++};
++
++static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
++{
++ struct davinci_runtime_data *prtd = substream->runtime->private_data;
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ int lch = prtd->slave_lch;
++ unsigned int period_size;
++ unsigned int dma_offset;
++ dma_addr_t dma_pos;
++ dma_addr_t src, dst;
++ unsigned short src_bidx, dst_bidx;
++ unsigned int data_type;
++ unsigned int count;
++
++ period_size = snd_pcm_lib_period_bytes(substream);
++ dma_offset = prtd->period * period_size;
++ dma_pos = runtime->dma_addr + dma_offset;
++
++ DPRINTK("audio_set_dma_params_play channel = %d dma_ptr = %x "
++ "period_size=%x\n", lch, dma_pos, period_size);
++
++ data_type = prtd->params->data_type;
++ count = period_size / data_type;
++
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++ src = dma_pos;
++ dst = prtd->params->dma_addr;
++ src_bidx = data_type;
++ dst_bidx = 0;
++ } else {
++ src = prtd->params->dma_addr;
++ dst = dma_pos;
++ src_bidx = 0;
++ dst_bidx = data_type;
++ }
++
++ davinci_set_dma_src_params(lch, src, INCR, W8BIT);
++ davinci_set_dma_dest_params(lch, dst, INCR, W8BIT);
++ davinci_set_dma_src_index(lch, src_bidx, 0);
++ davinci_set_dma_dest_index(lch, dst_bidx, 0);
++ davinci_set_dma_transfer_params(lch, data_type, count, 1, 0, ASYNC);
++
++ prtd->period++;
++ if (unlikely(prtd->period >= runtime->periods))
++ prtd->period = 0;
++}
++
++static void davinci_pcm_dma_irq(int lch, u16 ch_status, void *data)
++{
++ struct snd_pcm_substream *substream = data;
++ struct davinci_runtime_data *prtd = substream->runtime->private_data;
++
++ DPRINTK("lch=%d, status=0x%x\n", lch, ch_status);
++
++ if (unlikely(ch_status != DMA_COMPLETE))
++ return;
++
++ if (snd_pcm_running(substream)) {
++ snd_pcm_period_elapsed(substream);
++
++ spin_lock(&prtd->lock);
++ davinci_pcm_enqueue_dma(substream);
++ spin_unlock(&prtd->lock);
++ }
++}
++
++static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
++{
++ struct davinci_runtime_data *prtd = substream->runtime->private_data;
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct davinci_pcm_dma_params *dma_data = rtd->dai->cpu_dai->dma_data;
++ int tcc = TCC_ANY;
++ int ret;
++
++ if (!dma_data)
++ return -ENODEV;
++
++ prtd->params = dma_data;
++
++ /* Request master DMA channel */
++ ret = davinci_request_dma(prtd->params->channel, prtd->params->name,
++ davinci_pcm_dma_irq, substream,
++ &prtd->master_lch, &tcc, EVENTQ_0);
++ if (ret)
++ return ret;
++
++ /* Request slave DMA channel */
++ ret = davinci_request_dma(PARAM_ANY, "Link",
++ NULL, NULL, &prtd->slave_lch, &tcc, EVENTQ_0);
++ if (ret) {
++ davinci_free_dma(prtd->master_lch);
++ return ret;
++ }
++
++ /* Link slave DMA channel in loopback */
++ davinci_dma_link_lch(prtd->slave_lch, prtd->slave_lch);
++
++ return 0;
++}
++
++static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++ struct davinci_runtime_data *prtd = substream->runtime->private_data;
++ int ret = 0;
++
++ spin_lock(&prtd->lock);
++
++ switch (cmd) {
++ case SNDRV_PCM_TRIGGER_START:
++ case SNDRV_PCM_TRIGGER_RESUME:
++ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++ davinci_start_dma(prtd->master_lch);
++ break;
++ case SNDRV_PCM_TRIGGER_STOP:
++ case SNDRV_PCM_TRIGGER_SUSPEND:
++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++ davinci_stop_dma(prtd->master_lch);
++ break;
++ default:
++ ret = -EINVAL;
++ break;
++ }
++
++ spin_unlock(&prtd->lock);
++
++ return ret;
++}
++
++static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
++{
++ struct davinci_runtime_data *prtd = substream->runtime->private_data;
++ struct paramentry_descriptor temp;
++
++ prtd->period = 0;
++ davinci_pcm_enqueue_dma(substream);
++
++ /* Get slave channel dma params for master channel startup */
++ davinci_get_dma_params(prtd->slave_lch, &temp);
++ davinci_set_dma_params(prtd->master_lch, &temp);
++
++ return 0;
++}
++
++static snd_pcm_uframes_t
++davinci_pcm_pointer(struct snd_pcm_substream *substream)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ struct davinci_runtime_data *prtd = runtime->private_data;
++ unsigned int offset;
++ dma_addr_t count;
++ dma_addr_t src, dst;
++
++ spin_lock(&prtd->lock);
++
++ davinci_dma_getposition(prtd->master_lch, &src, &dst);
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++ count = src - runtime->dma_addr;
++ else
++ count = dst - runtime->dma_addr;;
++
++ spin_unlock(&prtd->lock);
++
++ offset = bytes_to_frames(runtime, count);
++ if (offset >= runtime->buffer_size)
++ offset = 0;
++
++ return offset;
++}
++
++static int davinci_pcm_open(struct snd_pcm_substream *substream)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ struct davinci_runtime_data *prtd;
++ int ret = 0;
++
++ snd_soc_set_runtime_hwparams(substream, &davinci_pcm_hardware);
++
++ prtd = kzalloc(sizeof(struct davinci_runtime_data), GFP_KERNEL);
++ if (prtd == NULL)
++ return -ENOMEM;
++
++ spin_lock_init(&prtd->lock);
++
++ runtime->private_data = prtd;
++
++ ret = davinci_pcm_dma_request(substream);
++ if (ret) {
++ printk(KERN_ERR "davinci_pcm: Failed to get dma channels\n");
++ kfree(prtd);
++ }
++
++ return ret;
++}
++
++static int davinci_pcm_close(struct snd_pcm_substream *substream)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ struct davinci_runtime_data *prtd = runtime->private_data;
++
++ davinci_dma_unlink_lch(prtd->slave_lch, prtd->slave_lch);
++
++ davinci_free_dma(prtd->slave_lch);
++ davinci_free_dma(prtd->master_lch);
++
++ kfree(prtd);
++
++ return 0;
++}
++
++static int davinci_pcm_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *hw_params)
++{
++ return snd_pcm_lib_malloc_pages(substream,
++ params_buffer_bytes(hw_params));
++}
++
++static int davinci_pcm_hw_free(struct snd_pcm_substream *substream)
++{
++ return snd_pcm_lib_free_pages(substream);
++}
++
++static int davinci_pcm_mmap(struct snd_pcm_substream *substream,
++ struct vm_area_struct *vma)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++
++ return dma_mmap_writecombine(substream->pcm->card->dev, vma,
++ runtime->dma_area,
++ runtime->dma_addr,
++ runtime->dma_bytes);
++}
++
++struct snd_pcm_ops davinci_pcm_ops = {
++ .open = davinci_pcm_open,
++ .close = davinci_pcm_close,
++ .ioctl = snd_pcm_lib_ioctl,
++ .hw_params = davinci_pcm_hw_params,
++ .hw_free = davinci_pcm_hw_free,
++ .prepare = davinci_pcm_prepare,
++ .trigger = davinci_pcm_trigger,
++ .pointer = davinci_pcm_pointer,
++ .mmap = davinci_pcm_mmap,
++};
++
++static int davinci_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
++{
++ struct snd_pcm_substream *substream = pcm->streams[stream].substream;
++ struct snd_dma_buffer *buf = &substream->dma_buffer;
++ size_t size = davinci_pcm_hardware.buffer_bytes_max;
++
++ buf->dev.type = SNDRV_DMA_TYPE_DEV;
++ buf->dev.dev = pcm->card->dev;
++ buf->private_data = NULL;
++ buf->area = dma_alloc_writecombine(pcm->card->dev, size,
++ &buf->addr, GFP_KERNEL);
++
++ DPRINTK("preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
++ (void *) buf->area, (void *) buf->addr, size);
++
++ if (!buf->area)
++ return -ENOMEM;
++
++ buf->bytes = size;
++ return 0;
++}
++
++static void davinci_pcm_free(struct snd_pcm *pcm)
++{
++ struct snd_pcm_substream *substream;
++ struct snd_dma_buffer *buf;
++ int stream;
++
++ for (stream = 0; stream < 2; stream++) {
++ substream = pcm->streams[stream].substream;
++ if (!substream)
++ continue;
++
++ buf = &substream->dma_buffer;
++ if (!buf->area)
++ continue;
++
++ dma_free_writecombine(pcm->card->dev, buf->bytes,
++ buf->area, buf->addr);
++ buf->area = NULL;
++ }
++}
++
++static u64 davinci_pcm_dmamask = 0xffffffff;
++
++static int davinci_pcm_new(struct snd_card *card,
++ struct snd_soc_codec_dai *dai, struct snd_pcm *pcm)
++{
++ int ret;
++
++ if (!card->dev->dma_mask)
++ card->dev->dma_mask = &davinci_pcm_dmamask;
++ if (!card->dev->coherent_dma_mask)
++ card->dev->coherent_dma_mask = 0xffffffff;
++
++ if (dai->playback.channels_min) {
++ ret = davinci_pcm_preallocate_dma_buffer(pcm,
++ SNDRV_PCM_STREAM_PLAYBACK);
++ if (ret)
++ return ret;
++ }
++
++ if (dai->capture.channels_min) {
++ ret = davinci_pcm_preallocate_dma_buffer(pcm,
++ SNDRV_PCM_STREAM_CAPTURE);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++}
++
++struct snd_soc_platform davinci_soc_platform = {
++ .name = "davinci-audio",
++ .pcm_ops = &davinci_pcm_ops,
++ .pcm_new = davinci_pcm_new,
++ .pcm_free = davinci_pcm_free,
++};
++EXPORT_SYMBOL_GPL(davinci_soc_platform);
++
++MODULE_AUTHOR("Vladimir Barinov");
++MODULE_DESCRIPTION("TI DAVINCI PCM DMA module");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h
+new file mode 100644
+index 0000000..8d6a45e
+--- /dev/null
++++ b/sound/soc/davinci/davinci-pcm.h
+@@ -0,0 +1,29 @@
++/*
++ * ALSA PCM interface for the TI DAVINCI processor
++ *
++ * Author: Vladimir Barinov, <vbarinov at ru.mvista.com>
++ * Copyright: (C) 2007 MontaVista Software, Inc., <source at mvista.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef _DAVINCI_PCM_H
++#define _DAVINCI_PCM_H
++
++struct davinci_pcm_dma_params {
++ char *name; /* stream identifier */
++ int channel; /* sync dma channel ID */
++ dma_addr_t dma_addr; /* device physical address for DMA */
++ unsigned int data_type; /* xfer data type */
++};
++
++struct evm_snd_platform_data {
++ int tx_dma_ch;
++ int rx_dma_ch;
++};
++
++extern struct snd_soc_platform davinci_soc_platform;
++
++#endif
+diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
+index 652514f..78de716 100644
+--- a/sound/soc/fsl/fsl_dma.c
++++ b/sound/soc/fsl/fsl_dma.c
+@@ -20,7 +20,6 @@
+ #include <linux/interrupt.h>
+ #include <linux/delay.h>
+
+-#include <sound/driver.h>
+ #include <sound/core.h>
+ #include <sound/pcm.h>
+ #include <sound/pcm_params.h>
+diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
+index 145ad13..b2a11b0 100644
+--- a/sound/soc/fsl/fsl_ssi.c
++++ b/sound/soc/fsl/fsl_ssi.c
+@@ -15,7 +15,6 @@
+ #include <linux/device.h>
+ #include <linux/delay.h>
+
+-#include <sound/driver.h>
+ #include <sound/core.h>
+ #include <sound/pcm.h>
+ #include <sound/pcm_params.h>
+diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
+index 1a70a6a..7f32a11 100644
+--- a/sound/soc/pxa/corgi.c
++++ b/sound/soc/pxa/corgi.c
+@@ -297,21 +297,19 @@ static int corgi_wm8731_init(struct snd_soc_codec *codec)
+ /* Add corgi specific controls */
+ for (i = 0; i < ARRAY_SIZE(wm8731_corgi_controls); i++) {
+ err = snd_ctl_add(codec->card,
+- snd_soc_cnew(&wm8731_corgi_controls[i],codec, NULL));
++ snd_soc_cnew(&wm8731_corgi_controls[i], codec, NULL));
+ if (err < 0)
+ return err;
+ }
+
+ /* Add corgi specific widgets */
+- for(i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) {
++ for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++)
+ snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
+- }
+
+ /* Set up corgi specific audio path audio_map */
+- for(i = 0; audio_map[i][0] != NULL; i++) {
++ for (i = 0; audio_map[i][0] != NULL; i++)
+ snd_soc_dapm_connect_input(codec, audio_map[i][0],
+ audio_map[i][1], audio_map[i][2]);
+- }
+
+ snd_soc_dapm_sync_endpoints(codec);
+ return 0;
+@@ -353,7 +351,8 @@ static int __init corgi_init(void)
+ {
+ int ret;
+
+- if (!(machine_is_corgi() || machine_is_shepherd() || machine_is_husky()))
++ if (!(machine_is_corgi() || machine_is_shepherd() ||
++ machine_is_husky()))
+ return -ENODEV;
+
+ corgi_snd_device = platform_device_alloc("soc-audio", -1);
+diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
+index 4fbf8bb..7e830b2 100644
+--- a/sound/soc/pxa/poodle.c
++++ b/sound/soc/pxa/poodle.c
+@@ -257,21 +257,19 @@ static int poodle_wm8731_init(struct snd_soc_codec *codec)
+ /* Add poodle specific controls */
+ for (i = 0; i < ARRAY_SIZE(wm8731_poodle_controls); i++) {
+ err = snd_ctl_add(codec->card,
+- snd_soc_cnew(&wm8731_poodle_controls[i],codec, NULL));
++ snd_soc_cnew(&wm8731_poodle_controls[i], codec, NULL));
+ if (err < 0)
+ return err;
+ }
+
+ /* Add poodle specific widgets */
+- for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) {
++ for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++)
+ snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
+- }
+
+ /* Set up poodle specific audio path audio_map */
+- for (i = 0; audio_map[i][0] != NULL; i++) {
++ for (i = 0; audio_map[i][0] != NULL; i++)
+ snd_soc_dapm_connect_input(codec, audio_map[i][0],
+ audio_map[i][1], audio_map[i][2]);
+- }
+
+ snd_soc_dapm_sync_endpoints(codec);
+ return 0;
+diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
+index 815c153..97ec2d9 100644
+--- a/sound/soc/pxa/pxa2xx-ac97.c
++++ b/sound/soc/pxa/pxa2xx-ac97.c
+@@ -15,6 +15,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/interrupt.h>
+ #include <linux/wait.h>
++#include <linux/clk.h>
+ #include <linux/delay.h>
+
+ #include <sound/core.h>
+@@ -27,6 +28,7 @@
+ #include <linux/mutex.h>
+ #include <asm/hardware.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/audio.h>
+
+ #include "pxa2xx-pcm.h"
+@@ -35,6 +37,10 @@
+ static DEFINE_MUTEX(car_mutex);
+ static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
+ static volatile long gsr_bits;
++static struct clk *ac97_clk;
++#ifdef CONFIG_PXA27x
++static struct clk *ac97conf_clk;
++#endif
+
+ /*
+ * Beware PXA27x bugs:
+@@ -55,7 +61,7 @@ static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97,
+ mutex_lock(&car_mutex);
+
+ /* set up primary or secondary codec/modem space */
+-#ifdef CONFIG_PXA27x
++#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+ reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
+ #else
+ if (reg == AC97_GPIO_STATUS)
+@@ -81,7 +87,7 @@ static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97,
+ wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
+ if (!((GSR | gsr_bits) & GSR_SDONE)) {
+ printk(KERN_ERR "%s: read error (ac97_reg=%x GSR=%#lx)\n",
+- __FUNCTION__, reg, GSR | gsr_bits);
++ __func__, reg, GSR | gsr_bits);
+ val = -1;
+ goto out;
+ }
+@@ -105,7 +111,7 @@ static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
+ mutex_lock(&car_mutex);
+
+ /* set up primary or secondary codec/modem space */
+-#ifdef CONFIG_PXA27x
++#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+ reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
+ #else
+ if (reg == AC97_GPIO_STATUS)
+@@ -121,13 +127,16 @@ static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
+ wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1);
+ if (!((GSR | gsr_bits) & GSR_CDONE))
+ printk(KERN_ERR "%s: write error (ac97_reg=%x GSR=%#lx)\n",
+- __FUNCTION__, reg, GSR | gsr_bits);
++ __func__, reg, GSR | gsr_bits);
+
+ mutex_unlock(&car_mutex);
+ }
+
+ static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
+ {
++#ifdef CONFIG_PXA3xx
++ int timeout = 100;
++#endif
+ gsr_bits = 0;
+
+ #ifdef CONFIG_PXA27x
+@@ -138,6 +147,11 @@ static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
+ GCR |= GCR_WARM_RST;
+ pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+ udelay(500);
++#elif defined(CONFIG_PXA3xx)
++ /* Can't use interrupts */
++ GCR |= GCR_WARM_RST;
++ while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
++ mdelay(1);
+ #else
+ GCR |= GCR_WARM_RST | GCR_PRIRDY_IEN | GCR_SECRDY_IEN;
+ wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
+@@ -145,7 +159,7 @@ static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
+
+ if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
+ printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",
+- __FUNCTION__, gsr_bits);
++ __func__, gsr_bits);
+
+ GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
+ GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
+@@ -153,17 +167,34 @@ static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
+
+ static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97)
+ {
++#ifdef CONFIG_PXA3xx
++ int timeout = 1000;
++
++ /* Hold CLKBPB for 100us */
++ GCR = 0;
++ GCR = GCR_CLKBPB;
++ udelay(100);
++ GCR = 0;
++#endif
++
+ GCR &= GCR_COLD_RST; /* clear everything but nCRST */
+ GCR &= ~GCR_COLD_RST; /* then assert nCRST */
+
+ gsr_bits = 0;
+ #ifdef CONFIG_PXA27x
+ /* PXA27x Developers Manual section 13.5.2.2.1 */
+- pxa_set_cken(CKEN_AC97CONF, 1);
++ clk_enable(ac97conf_clk);
+ udelay(5);
+- pxa_set_cken(CKEN_AC97CONF, 0);
++ clk_disable(ac97conf_clk);
+ GCR = GCR_COLD_RST;
+ udelay(50);
++#elif defined(CONFIG_PXA3xx)
++ /* Can't use interrupts on PXA3xx */
++ GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
++
++ GCR = GCR_WARM_RST | GCR_COLD_RST;
++ while (!(GSR & (GSR_PCR | GSR_SCR)) && timeout--)
++ mdelay(10);
+ #else
+ GCR = GCR_COLD_RST;
+ GCR |= GCR_CDONE_IE|GCR_SDONE_IE;
+@@ -172,7 +203,7 @@ static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97)
+
+ if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
+ printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n",
+- __FUNCTION__, gsr_bits);
++ __func__, gsr_bits);
+
+ GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
+ GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
+@@ -255,7 +286,7 @@ static int pxa2xx_ac97_suspend(struct platform_device *pdev,
+ struct snd_soc_cpu_dai *dai)
+ {
+ GCR |= GCR_ACLINK_OFF;
+- pxa_set_cken(CKEN_AC97, 0);
++ clk_disable(ac97_clk);
+ return 0;
+ }
+
+@@ -270,7 +301,7 @@ static int pxa2xx_ac97_resume(struct platform_device *pdev,
+ /* Use GPIO 113 as AC97 Reset on Bulverde */
+ pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+ #endif
+- pxa_set_cken(CKEN_AC97, 1);
++ clk_enable(ac97_clk);
+ return 0;
+ }
+
+@@ -294,16 +325,33 @@ static int pxa2xx_ac97_probe(struct platform_device *pdev)
+ #ifdef CONFIG_PXA27x
+ /* Use GPIO 113 as AC97 Reset on Bulverde */
+ pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
++
++ ac97conf_clk = clk_get(&pdev->dev, "AC97CONFCLK");
++ if (IS_ERR(ac97conf_clk)) {
++ ret = PTR_ERR(ac97conf_clk);
++ ac97conf_clk = NULL;
++ goto err_irq;
++ }
+ #endif
+- pxa_set_cken(CKEN_AC97, 1);
++ ac97_clk = clk_get(&pdev->dev, "AC97CLK");
++ if (IS_ERR(ac97_clk)) {
++ ret = PTR_ERR(ac97_clk);
++ ac97_clk = NULL;
++ goto err_irq;
++ }
++ clk_enable(ac97_clk);
+ return 0;
+
+- err:
+- if (CKEN & (1 << CKEN_AC97)) {
+- GCR |= GCR_ACLINK_OFF;
+- free_irq(IRQ_AC97, NULL);
+- pxa_set_cken(CKEN_AC97, 0);
++ err_irq:
++ GCR |= GCR_ACLINK_OFF;
++#ifdef CONFIG_PXA27x
++ if (ac97conf_clk) {
++ clk_put(ac97conf_clk);
++ ac97conf_clk = NULL;
+ }
++#endif
++ free_irq(IRQ_AC97, NULL);
++ err:
+ return ret;
+ }
+
+@@ -311,7 +359,13 @@ static void pxa2xx_ac97_remove(struct platform_device *pdev)
+ {
+ GCR |= GCR_ACLINK_OFF;
+ free_irq(IRQ_AC97, NULL);
+- pxa_set_cken(CKEN_AC97, 0);
++#ifdef CONFIG_PXA27x
++ clk_put(ac97conf_clk);
++ ac97conf_clk = NULL;
++#endif
++ clk_disable(ac97_clk);
++ clk_put(ac97_clk);
++ ac97_clk = NULL;
+ }
+
+ static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
+diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
+index 692b900..4250710 100644
+--- a/sound/soc/pxa/pxa2xx-i2s.c
++++ b/sound/soc/pxa/pxa2xx-i2s.c
+@@ -25,6 +25,7 @@
+
+ #include <asm/hardware.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-gpio.h>
+ #include <asm/arch/audio.h>
+
+ #include "pxa2xx-pcm.h"
+diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
+index daeaa4c..01ad7bf 100644
+--- a/sound/soc/pxa/pxa2xx-pcm.c
++++ b/sound/soc/pxa/pxa2xx-pcm.c
+@@ -64,8 +64,8 @@ static void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
+ if (dcsr & DCSR_ENDINTR) {
+ snd_pcm_period_elapsed(substream);
+ } else {
+- printk( KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
+- prtd->params->name, dma_ch, dcsr );
++ printk(KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
++ prtd->params->name, dma_ch, dcsr);
+ }
+ }
+
+@@ -84,8 +84,8 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
+
+ /* return if this is a bufferless transfer e.g.
+ * codec <--> BT codec or GSM modem -- lg FIXME */
+- if (!dma)
+- return 0;
++ if (!dma)
++ return 0;
+
+ /* this may get called several times by oss emulation
+ * with different params */
+@@ -363,7 +363,6 @@ struct snd_soc_platform pxa2xx_soc_platform = {
+ .pcm_new = pxa2xx_pcm_new,
+ .pcm_free = pxa2xx_pcm_free_dma_buffers,
+ };
+-
+ EXPORT_SYMBOL_GPL(pxa2xx_soc_platform);
+
+ MODULE_AUTHOR("Nicolas Pitre");
+diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
+index ecca390..d8b8372 100644
+--- a/sound/soc/pxa/spitz.c
++++ b/sound/soc/pxa/spitz.c
+@@ -313,15 +313,13 @@ static int spitz_wm8750_init(struct snd_soc_codec *codec)
+ }
+
+ /* Add spitz specific widgets */
+- for (i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++) {
++ for (i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++)
+ snd_soc_dapm_new_control(codec, &wm8750_dapm_widgets[i]);
+- }
+
+ /* Set up spitz specific audio path audio_map */
+- for (i = 0; audio_map[i][0] != NULL; i++) {
++ for (i = 0; audio_map[i][0] != NULL; i++)
+ snd_soc_dapm_connect_input(codec, audio_map[i][0],
+ audio_map[i][1], audio_map[i][2]);
+- }
+
+ snd_soc_dapm_sync_endpoints(codec);
+ return 0;
+diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c
+index 6ee115c..962cc20 100644
+--- a/sound/soc/s3c24xx/neo1973_wm8753.c
++++ b/sound/soc/s3c24xx/neo1973_wm8753.c
+@@ -659,6 +659,7 @@ static int __init neo1973_init(void)
+
+ static void __exit neo1973_exit(void)
+ {
++ i2c_del_driver(&lm4857_i2c_driver);
+ platform_device_unregister(neo1973_snd_device);
+ }
+
+diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
+index 0a3c630..4ebcd6a 100644
+--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
++++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
+@@ -25,6 +25,7 @@
+ #include <linux/delay.h>
+ #include <linux/clk.h>
+ #include <linux/jiffies.h>
++#include <linux/io.h>
+ #include <sound/core.h>
+ #include <sound/pcm.h>
+ #include <sound/pcm_params.h>
+@@ -32,7 +33,6 @@
+ #include <sound/soc.h>
+
+ #include <asm/hardware.h>
+-#include <asm/io.h>
+ #include <asm/arch/regs-gpio.h>
+ #include <asm/arch/regs-clock.h>
+ #include <asm/arch/audio.h>
+@@ -46,7 +46,7 @@
+
+ #define S3C24XX_I2S_DEBUG 0
+ #if S3C24XX_I2S_DEBUG
+-#define DBG(x...) printk(KERN_DEBUG x)
++#define DBG(x...) printk(KERN_DEBUG "s3c24xx-i2s: " x)
+ #else
+ #define DBG(x...)
+ #endif
+@@ -89,7 +89,7 @@ static void s3c24xx_snd_txctrl(int on)
+ u32 iiscon;
+ u32 iismod;
+
+- DBG("Entered %s\n", __FUNCTION__);
++ DBG("Entered %s\n", __func__);
+
+ iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON);
+ iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
+@@ -134,7 +134,7 @@ static void s3c24xx_snd_rxctrl(int on)
+ u32 iiscon;
+ u32 iismod;
+
+- DBG("Entered %s\n", __FUNCTION__);
++ DBG("Entered %s\n", __func__);
+
+ iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON);
+ iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
+@@ -159,10 +159,10 @@ static void s3c24xx_snd_rxctrl(int on)
+ * DMA engine will simply freeze randomly.
+ */
+
+- iisfcon &= ~S3C2410_IISFCON_RXENABLE;
+- iisfcon &= ~S3C2410_IISFCON_RXDMA;
+- iiscon |= S3C2410_IISCON_RXIDLE;
+- iiscon &= ~S3C2410_IISCON_RXDMAEN;
++ iisfcon &= ~S3C2410_IISFCON_RXENABLE;
++ iisfcon &= ~S3C2410_IISFCON_RXDMA;
++ iiscon |= S3C2410_IISCON_RXIDLE;
++ iiscon &= ~S3C2410_IISCON_RXDMAEN;
+ iismod &= ~S3C2410_IISMOD_RXMODE;
+
+ writel(iisfcon, s3c24xx_i2s.regs + S3C2410_IISFCON);
+@@ -182,7 +182,7 @@ static int s3c24xx_snd_lrsync(void)
+ u32 iiscon;
+ unsigned long timeout = jiffies + msecs_to_jiffies(5);
+
+- DBG("Entered %s\n", __FUNCTION__);
++ DBG("Entered %s\n", __func__);
+
+ while (1) {
+ iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
+@@ -201,7 +201,7 @@ static int s3c24xx_snd_lrsync(void)
+ */
+ static inline int s3c24xx_snd_is_clkmaster(void)
+ {
+- DBG("Entered %s\n", __FUNCTION__);
++ DBG("Entered %s\n", __func__);
+
+ return (readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & S3C2410_IISMOD_SLAVE) ? 0:1;
+ }
+@@ -214,7 +214,7 @@ static int s3c24xx_i2s_set_fmt(struct snd_soc_cpu_dai *cpu_dai,
+ {
+ u32 iismod;
+
+- DBG("Entered %s\n", __FUNCTION__);
++ DBG("Entered %s\n", __func__);
+
+ iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
+ DBG("hw_params r: IISMOD: %lx \n", iismod);
+@@ -250,7 +250,7 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ u32 iismod;
+
+- DBG("Entered %s\n", __FUNCTION__);
++ DBG("Entered %s\n", __func__);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ rtd->dai->cpu_dai->dma_data = &s3c24xx_i2s_pcm_stereo_out;
+@@ -278,7 +278,7 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
+ {
+ int ret = 0;
+
+- DBG("Entered %s\n", __FUNCTION__);
++ DBG("Entered %s\n", __func__);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+@@ -320,7 +320,7 @@ static int s3c24xx_i2s_set_sysclk(struct snd_soc_cpu_dai *cpu_dai,
+ {
+ u32 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
+
+- DBG("Entered %s\n", __FUNCTION__);
++ DBG("Entered %s\n", __func__);
+
+ iismod &= ~S3C2440_IISMOD_MPLL;
+
+@@ -346,7 +346,7 @@ static int s3c24xx_i2s_set_clkdiv(struct snd_soc_cpu_dai *cpu_dai,
+ {
+ u32 reg;
+
+- DBG("Entered %s\n", __FUNCTION__);
++ DBG("Entered %s\n", __func__);
+
+ switch (div_id) {
+ case S3C24XX_DIV_BCLK:
+@@ -381,13 +381,13 @@ EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate);
+
+ static int s3c24xx_i2s_probe(struct platform_device *pdev)
+ {
+- DBG("Entered %s\n", __FUNCTION__);
++ DBG("Entered %s\n", __func__);
+
+ s3c24xx_i2s.regs = ioremap(S3C2410_PA_IIS, 0x100);
+ if (s3c24xx_i2s.regs == NULL)
+ return -ENXIO;
+
+- s3c24xx_i2s.iis_clk=clk_get(&pdev->dev, "iis");
++ s3c24xx_i2s.iis_clk = clk_get(&pdev->dev, "iis");
+ if (s3c24xx_i2s.iis_clk == NULL) {
+ DBG("failed to get iis_clock\n");
+ iounmap(s3c24xx_i2s.regs);
+@@ -411,9 +411,11 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev)
+ }
+
+ #ifdef CONFIG_PM
+-int s3c24xx_i2s_suspend(struct platform_device *pdev,
++static int s3c24xx_i2s_suspend(struct platform_device *pdev,
+ struct snd_soc_cpu_dai *cpu_dai)
+ {
++ DBG("Entered %s\n", __func__);
++
+ s3c24xx_i2s.iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
+ s3c24xx_i2s.iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
+ s3c24xx_i2s.iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON);
+@@ -424,9 +426,10 @@ int s3c24xx_i2s_suspend(struct platform_device *pdev,
+ return 0;
+ }
+
+-int s3c24xx_i2s_resume(struct platform_device *pdev,
++static int s3c24xx_i2s_resume(struct platform_device *pdev,
+ struct snd_soc_cpu_dai *cpu_dai)
+ {
++ DBG("Entered %s\n", __func__);
+ clk_enable(s3c24xx_i2s.iis_clk);
+
+ writel(s3c24xx_i2s.iiscon, s3c24xx_i2s.regs + S3C2410_IISCON);
+diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c
+index 29a6c82..49580fb 100644
+--- a/sound/soc/s3c24xx/s3c24xx-pcm.c
++++ b/sound/soc/s3c24xx/s3c24xx-pcm.c
+@@ -39,7 +39,7 @@
+
+ #define S3C24XX_PCM_DEBUG 0
+ #if S3C24XX_PCM_DEBUG
+-#define DBG(x...) printk(KERN_DEBUG x)
++#define DBG(x...) printk(KERN_DEBUG "s3c24xx-pcm: " x)
+ #else
+ #define DBG(x...)
+ #endif
+@@ -88,7 +88,7 @@ static void s3c24xx_pcm_enqueue(struct snd_pcm_substream *substream)
+ dma_addr_t pos = prtd->dma_pos;
+ int ret;
+
+- DBG("Entered %s\n", __FUNCTION__);
++ DBG("Entered %s\n", __func__);
+
+ while (prtd->dma_loaded < prtd->dma_limit) {
+ unsigned long len = prtd->dma_period;
+@@ -98,7 +98,7 @@ static void s3c24xx_pcm_enqueue(struct snd_pcm_substream *substream)
+ if ((pos + len) > prtd->dma_end) {
+ len = prtd->dma_end - pos;
+ DBG(KERN_DEBUG "%s: corrected dma len %ld\n",
+- __FUNCTION__, len);
++ __func__, len);
+ }
+
+ ret = s3c2410_dma_enqueue(prtd->params->channel,
+@@ -123,7 +123,7 @@ static void s3c24xx_audio_buffdone(struct s3c2410_dma_chan *channel,
+ struct snd_pcm_substream *substream = dev_id;
+ struct s3c24xx_runtime_data *prtd;
+
+- DBG("Entered %s\n", __FUNCTION__);
++ DBG("Entered %s\n", __func__);
+
+ if (result == S3C2410_RES_ABORT || result == S3C2410_RES_ERR)
+ return;
+@@ -152,7 +152,7 @@ static int s3c24xx_pcm_hw_params(struct snd_pcm_substream *substream,
+ unsigned long totbytes = params_buffer_bytes(params);
+ int ret=0;
+
+- DBG("Entered %s\n", __FUNCTION__);
++ DBG("Entered %s\n", __func__);
+
+ /* return if this is a bufferless transfer e.g.
+ * codec <--> BT codec or GSM modem -- lg FIXME */
+@@ -200,7 +200,7 @@ static int s3c24xx_pcm_hw_free(struct snd_pcm_substream *substream)
+ {
+ struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
+
+- DBG("Entered %s\n", __FUNCTION__);
++ DBG("Entered %s\n", __func__);
+
+ /* TODO - do we need to ensure DMA flushed */
+ snd_pcm_set_runtime_buffer(substream, NULL);
+@@ -218,7 +218,7 @@ static int s3c24xx_pcm_prepare(struct snd_pcm_substream *substream)
+ struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
+ int ret = 0;
+
+- DBG("Entered %s\n", __FUNCTION__);
++ DBG("Entered %s\n", __func__);
+
+ /* return if this is a bufferless transfer e.g.
+ * codec <--> BT codec or GSM modem -- lg FIXME */
+@@ -263,7 +263,7 @@ static int s3c24xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+ struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
+ int ret = 0;
+
+- DBG("Entered %s\n", __FUNCTION__);
++ DBG("Entered %s\n", __func__);
+
+ spin_lock(&prtd->lock);
+
+@@ -301,7 +301,7 @@ static snd_pcm_uframes_t
+ unsigned long res;
+ dma_addr_t src, dst;
+
+- DBG("Entered %s\n", __FUNCTION__);
++ DBG("Entered %s\n", __func__);
+
+ spin_lock(&prtd->lock);
+ s3c2410_dma_getposition(prtd->params->channel, &src, &dst);
+@@ -334,7 +334,7 @@ static int s3c24xx_pcm_open(struct snd_pcm_substream *substream)
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct s3c24xx_runtime_data *prtd;
+
+- DBG("Entered %s\n", __FUNCTION__);
++ DBG("Entered %s\n", __func__);
+
+ snd_soc_set_runtime_hwparams(substream, &s3c24xx_pcm_hardware);
+
+@@ -353,7 +353,7 @@ static int s3c24xx_pcm_close(struct snd_pcm_substream *substream)
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct s3c24xx_runtime_data *prtd = runtime->private_data;
+
+- DBG("Entered %s\n", __FUNCTION__);
++ DBG("Entered %s\n", __func__);
+
+ if (prtd)
+ kfree(prtd);
+@@ -368,7 +368,7 @@ static int s3c24xx_pcm_mmap(struct snd_pcm_substream *substream,
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+- DBG("Entered %s\n", __FUNCTION__);
++ DBG("Entered %s\n", __func__);
+
+ return dma_mmap_writecombine(substream->pcm->card->dev, vma,
+ runtime->dma_area,
+@@ -394,7 +394,7 @@ static int s3c24xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+ struct snd_dma_buffer *buf = &substream->dma_buffer;
+ size_t size = s3c24xx_pcm_hardware.buffer_bytes_max;
+
+- DBG("Entered %s\n", __FUNCTION__);
++ DBG("Entered %s\n", __func__);
+
+ buf->dev.type = SNDRV_DMA_TYPE_DEV;
+ buf->dev.dev = pcm->card->dev;
+@@ -413,7 +413,7 @@ static void s3c24xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
+ struct snd_dma_buffer *buf;
+ int stream;
+
+- DBG("Entered %s\n", __FUNCTION__);
++ DBG("Entered %s\n", __func__);
+
+ for (stream = 0; stream < 2; stream++) {
+ substream = pcm->streams[stream].substream;
+@@ -437,7 +437,7 @@ static int s3c24xx_pcm_new(struct snd_card *card,
+ {
+ int ret = 0;
+
+- DBG("Entered %s\n", __FUNCTION__);
++ DBG("Entered %s\n", __func__);
+
+ if (!card->dev->dma_mask)
+ card->dev->dma_mask = &s3c24xx_pcm_dmamask;
+diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
+index f03220d..4c1e013 100644
+--- a/sound/soc/sh/Kconfig
++++ b/sound/soc/sh/Kconfig
+@@ -1,4 +1,5 @@
+ menu "SoC Audio support for SuperH"
++ depends on SUPERH
+
+ config SND_SOC_PCM_SH7760
+ tristate "SoC Audio support for Renesas SH7760"
+diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
+index 9eb5479..e148db9 100644
+--- a/sound/soc/soc-core.c
++++ b/sound/soc/soc-core.c
+@@ -839,6 +839,7 @@ static int soc_remove(struct platform_device *pdev)
+ static struct platform_driver soc_driver = {
+ .driver = {
+ .name = "soc-audio",
++ .owner = THIS_MODULE,
+ },
+ .probe = soc_probe,
+ .remove = soc_remove,
+@@ -1601,3 +1602,4 @@ module_exit(snd_soc_exit);
+ MODULE_AUTHOR("Liam Girdwood, liam.girdwood at wolfsonmicro.com, www.wolfsonmicro.com");
+ MODULE_DESCRIPTION("ALSA SoC Core");
+ MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:soc-audio");
+diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
+index 620d7ea..af3326c 100644
+--- a/sound/soc/soc-dapm.c
++++ b/sound/soc/soc-dapm.c
+@@ -226,7 +226,7 @@ static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
+ snd_soc_write(codec, widget->reg, new);
+ pop_wait(POP_TIME);
+ }
+- dbg("reg old %x new %x change %d\n", old, new, change);
++ dbg("reg %x old %x new %x change %d\n", widget->reg, old, new, change);
+ return change;
+ }
+
+@@ -1288,7 +1288,7 @@ int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
+ mutex_unlock(&codec->mutex);
+
+ dapm_power_widgets(codec, event);
+- dump_dapm(codec, __FUNCTION__);
++ dump_dapm(codec, __func__);
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event);
+@@ -1334,10 +1334,11 @@ int snd_soc_dapm_set_endpoint(struct snd_soc_codec *codec,
+ list_for_each_entry(w, &codec->dapm_widgets, list) {
+ if (!strcmp(w->name, endpoint)) {
+ w->connected = status;
++ return 0;
+ }
+ }
+
+- return 0;
++ return -ENODEV;
+ }
+ EXPORT_SYMBOL_GPL(snd_soc_dapm_set_endpoint);
+
+diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c
+index 89d6e9c..09802e8 100644
+--- a/sound/spi/at73c213.c
++++ b/sound/spi/at73c213.c
+@@ -118,7 +118,7 @@ static struct snd_pcm_hardware snd_at73c213_playback_hw = {
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .rate_min = 8000, /* Replaced by chip->bitrate later. */
+ .rate_max = 50000, /* Replaced by chip->bitrate later. */
+- .channels_min = 2,
++ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = 64 * 1024 - 1,
+ .period_bytes_min = 512,
+@@ -133,7 +133,8 @@ static struct snd_pcm_hardware snd_at73c213_playback_hw = {
+ static int snd_at73c213_set_bitrate(struct snd_at73c213 *chip)
+ {
+ unsigned long ssc_rate = clk_get_rate(chip->ssc->clk);
+- unsigned long dac_rate_new, ssc_div, status;
++ unsigned long dac_rate_new, ssc_div;
++ int status;
+ unsigned long ssc_div_max, ssc_div_min;
+ int max_tries;
+
+@@ -209,7 +210,13 @@ static int snd_at73c213_pcm_open(struct snd_pcm_substream *substream)
+ {
+ struct snd_at73c213 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
++ int err;
+
++ /* ensure buffer_size is a multiple of period_size */
++ err = snd_pcm_hw_constraint_integer(runtime,
++ SNDRV_PCM_HW_PARAM_PERIODS);
++ if (err < 0)
++ return err;
+ snd_at73c213_playback_hw.rate_min = chip->bitrate;
+ snd_at73c213_playback_hw.rate_max = chip->bitrate;
+ runtime->hw = snd_at73c213_playback_hw;
+@@ -228,6 +235,14 @@ static int snd_at73c213_pcm_close(struct snd_pcm_substream *substream)
+ static int snd_at73c213_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
+ {
++ struct snd_at73c213 *chip = snd_pcm_substream_chip(substream);
++ int channels = params_channels(hw_params);
++ int val;
++
++ val = ssc_readl(chip->ssc->regs, TFMR);
++ val = SSC_BFINS(TFMR_DATNB, channels - 1, val);
++ ssc_writel(chip->ssc->regs, TFMR, val);
++
+ return snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
+ }
+@@ -249,10 +264,12 @@ static int snd_at73c213_pcm_prepare(struct snd_pcm_substream *substream)
+
+ ssc_writel(chip->ssc->regs, PDC_TPR,
+ (long)runtime->dma_addr);
+- ssc_writel(chip->ssc->regs, PDC_TCR, runtime->period_size * 2);
++ ssc_writel(chip->ssc->regs, PDC_TCR,
++ runtime->period_size * runtime->channels);
+ ssc_writel(chip->ssc->regs, PDC_TNPR,
+ (long)runtime->dma_addr + block_size);
+- ssc_writel(chip->ssc->regs, PDC_TNCR, runtime->period_size * 2);
++ ssc_writel(chip->ssc->regs, PDC_TNCR,
++ runtime->period_size * runtime->channels);
+
+ return 0;
+ }
+@@ -314,15 +331,6 @@ static struct snd_pcm_ops at73c213_playback_ops = {
+ .pointer = snd_at73c213_pcm_pointer,
+ };
+
+-static void snd_at73c213_pcm_free(struct snd_pcm *pcm)
+-{
+- struct snd_at73c213 *chip = snd_pcm_chip(pcm);
+- if (chip->pcm) {
+- snd_pcm_lib_preallocate_free_for_all(chip->pcm);
+- chip->pcm = NULL;
+- }
+-}
+-
+ static int __devinit snd_at73c213_pcm_new(struct snd_at73c213 *chip, int device)
+ {
+ struct snd_pcm *pcm;
+@@ -334,7 +342,6 @@ static int __devinit snd_at73c213_pcm_new(struct snd_at73c213 *chip, int device)
+ goto out;
+
+ pcm->private_data = chip;
+- pcm->private_free = snd_at73c213_pcm_free;
+ pcm->info_flags = SNDRV_PCM_INFO_BLOCK_TRANSFER;
+ strcpy(pcm->name, "at73c213");
+ chip->pcm = pcm;
+@@ -375,7 +382,8 @@ static irqreturn_t snd_at73c213_interrupt(int irq, void *dev_id)
+
+ ssc_writel(chip->ssc->regs, PDC_TNPR,
+ (long)runtime->dma_addr + offset);
+- ssc_writel(chip->ssc->regs, PDC_TNCR, runtime->period_size * 2);
++ ssc_writel(chip->ssc->regs, PDC_TNCR,
++ runtime->period_size * runtime->channels);
+ retval = IRQ_HANDLED;
+ }
+
+@@ -737,7 +745,7 @@ cleanup:
+ /*
+ * Device functions
+ */
+-static int snd_at73c213_ssc_init(struct snd_at73c213 *chip)
++static int __devinit snd_at73c213_ssc_init(struct snd_at73c213 *chip)
+ {
+ /*
+ * Continuous clock output.
+@@ -767,7 +775,7 @@ static int snd_at73c213_ssc_init(struct snd_at73c213 *chip)
+ return 0;
+ }
+
+-static int snd_at73c213_chip_init(struct snd_at73c213 *chip)
++static int __devinit snd_at73c213_chip_init(struct snd_at73c213 *chip)
+ {
+ int retval;
+ unsigned char dac_ctrl = 0;
+@@ -933,7 +941,7 @@ out:
+ return retval;
+ }
+
+-static int snd_at73c213_probe(struct spi_device *spi)
++static int __devinit snd_at73c213_probe(struct spi_device *spi)
+ {
+ struct snd_card *card;
+ struct snd_at73c213 *chip;
+diff --git a/sound/usb/caiaq/caiaq-audio.c b/sound/usb/caiaq/caiaq-audio.c
+index 9cc4cd8..24970a5 100644
+--- a/sound/usb/caiaq/caiaq-audio.c
++++ b/sound/usb/caiaq/caiaq-audio.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006,2007 Daniel Mack, Karsten Wiese
++ * Copyright (c) 2006-2008 Daniel Mack, Karsten Wiese
+ *
+ * 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
+@@ -39,7 +39,8 @@
+ #define BYTES_PER_SAMPLE 3
+ #define BYTES_PER_SAMPLE_USB 4
+ #define MAX_BUFFER_SIZE (128*1024)
+-
++#define MAX_ENDPOINT_SIZE 512
++
+ #define ENDPOINT_CAPTURE 2
+ #define ENDPOINT_PLAYBACK 6
+
+@@ -77,10 +78,15 @@ static void
+ deactivate_substream(struct snd_usb_caiaqdev *dev,
+ struct snd_pcm_substream *sub)
+ {
++ unsigned long flags;
++ spin_lock_irqsave(&dev->spinlock, flags);
++
+ if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ dev->sub_playback[sub->number] = NULL;
+ else
+ dev->sub_capture[sub->number] = NULL;
++
++ spin_unlock_irqrestore(&dev->spinlock, flags);
+ }
+
+ static int
+@@ -97,13 +103,13 @@ static int stream_start(struct snd_usb_caiaqdev *dev)
+ {
+ int i, ret;
+
+- debug("stream_start(%p)\n", dev);
+- spin_lock_irq(&dev->spinlock);
+- if (dev->streaming) {
+- spin_unlock_irq(&dev->spinlock);
++ debug("%s(%p)\n", __func__, dev);
++
++ if (dev->streaming)
+ return -EINVAL;
+- }
+
++ memset(dev->sub_playback, 0, sizeof(dev->sub_playback));
++ memset(dev->sub_capture, 0, sizeof(dev->sub_capture));
+ dev->input_panic = 0;
+ dev->output_panic = 0;
+ dev->first_packet = 1;
+@@ -112,37 +118,35 @@ static int stream_start(struct snd_usb_caiaqdev *dev)
+ for (i = 0; i < N_URBS; i++) {
+ ret = usb_submit_urb(dev->data_urbs_in[i], GFP_ATOMIC);
+ if (ret) {
+- log("unable to trigger initial read #%d! (ret = %d)\n",
+- i, ret);
++ log("unable to trigger read #%d! (ret %d)\n", i, ret);
+ dev->streaming = 0;
+- spin_unlock_irq(&dev->spinlock);
+ return -EPIPE;
+ }
+ }
+
+- spin_unlock_irq(&dev->spinlock);
+ return 0;
+ }
+
+ static void stream_stop(struct snd_usb_caiaqdev *dev)
+ {
+ int i;
+-
+- debug("stream_stop(%p)\n", dev);
++
++ debug("%s(%p)\n", __func__, dev);
+ if (!dev->streaming)
+ return;
+
+ dev->streaming = 0;
++
+ for (i = 0; i < N_URBS; i++) {
+- usb_unlink_urb(dev->data_urbs_in[i]);
+- usb_unlink_urb(dev->data_urbs_out[i]);
++ usb_kill_urb(dev->data_urbs_in[i]);
++ usb_kill_urb(dev->data_urbs_out[i]);
+ }
+ }
+
+ static int snd_usb_caiaq_substream_open(struct snd_pcm_substream *substream)
+ {
+ struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
+- debug("snd_usb_caiaq_substream_open(%p)\n", substream);
++ debug("%s(%p)\n", __func__, substream);
+ substream->runtime->hw = dev->pcm_info;
+ snd_pcm_limit_hw_rates(substream->runtime);
+ return 0;
+@@ -152,7 +156,7 @@ static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream)
+ {
+ struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
+
+- debug("snd_usb_caiaq_substream_close(%p)\n", substream);
++ debug("%s(%p)\n", __func__, substream);
+ if (all_substreams_zero(dev->sub_playback) &&
+ all_substreams_zero(dev->sub_capture)) {
+ /* when the last client has stopped streaming,
+@@ -160,24 +164,22 @@ static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream)
+ stream_stop(dev);
+ dev->pcm_info.rates = dev->samplerates;
+ }
+-
++
+ return 0;
+ }
+
+ static int snd_usb_caiaq_pcm_hw_params(struct snd_pcm_substream *sub,
+ struct snd_pcm_hw_params *hw_params)
+ {
+- debug("snd_usb_caiaq_pcm_hw_params(%p)\n", sub);
++ debug("%s(%p)\n", __func__, sub);
+ return snd_pcm_lib_malloc_pages(sub, params_buffer_bytes(hw_params));
+ }
+
+ static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *sub)
+ {
+ struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub);
+- debug("snd_usb_caiaq_pcm_hw_free(%p)\n", sub);
+- spin_lock_irq(&dev->spinlock);
++ debug("%s(%p)\n", __func__, sub);
+ deactivate_substream(dev, sub);
+- spin_unlock_irq(&dev->spinlock);
+ return snd_pcm_lib_free_pages(sub);
+ }
+
+@@ -196,12 +198,12 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
+ struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+- debug("snd_usb_caiaq_pcm_prepare(%p)\n", substream);
++ debug("%s(%p)\n", __func__, substream);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ dev->audio_out_buf_pos[index] = BYTES_PER_SAMPLE + 1;
+ else
+- dev->audio_in_buf_pos[index] = 0;
++ dev->audio_in_buf_pos[index] = BYTES_PER_SAMPLE;
+
+ if (dev->streaming)
+ return 0;
+@@ -220,7 +222,10 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
+
+ bpp = ((runtime->rate / 8000) + CLOCK_DRIFT_TOLERANCE)
+ * bytes_per_sample * CHANNELS_PER_STREAM * dev->n_streams;
+-
++
++ if (bpp > MAX_ENDPOINT_SIZE)
++ bpp = MAX_ENDPOINT_SIZE;
++
+ ret = snd_usb_caiaq_set_audio_params(dev, runtime->rate,
+ runtime->sample_bits, bpp);
+ if (ret)
+@@ -247,15 +252,11 @@ static int snd_usb_caiaq_pcm_trigger(struct snd_pcm_substream *sub, int cmd)
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+- spin_lock(&dev->spinlock);
+ activate_substream(dev, sub);
+- spin_unlock(&dev->spinlock);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+- spin_lock(&dev->spinlock);
+ deactivate_substream(dev, sub);
+- spin_unlock(&dev->spinlock);
+ break;
+ default:
+ return -EINVAL;
+@@ -328,8 +329,6 @@ static void read_in_urb_mode0(struct snd_usb_caiaqdev *dev,
+ if (all_substreams_zero(dev->sub_capture))
+ return;
+
+- spin_lock(&dev->spinlock);
+-
+ for (i = 0; i < iso->actual_length;) {
+ for (stream = 0; stream < dev->n_streams; stream++, i++) {
+ sub = dev->sub_capture[stream];
+@@ -345,8 +344,6 @@ static void read_in_urb_mode0(struct snd_usb_caiaqdev *dev,
+ }
+ }
+ }
+-
+- spin_unlock(&dev->spinlock);
+ }
+
+ static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev,
+@@ -358,8 +355,6 @@ static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev,
+ struct snd_pcm_substream *sub;
+ int stream, i;
+
+- spin_lock(&dev->spinlock);
+-
+ for (i = 0; i < iso->actual_length;) {
+ if (i % (dev->n_streams * BYTES_PER_SAMPLE_USB) == 0) {
+ for (stream = 0;
+@@ -393,8 +388,6 @@ static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev,
+ }
+ }
+ }
+-
+- spin_unlock(&dev->spinlock);
+ }
+
+ static void read_in_urb(struct snd_usb_caiaqdev *dev,
+@@ -418,8 +411,6 @@ static void read_in_urb(struct snd_usb_caiaqdev *dev,
+ dev->input_panic ? "(input)" : "",
+ dev->output_panic ? "(output)" : "");
+ }
+-
+- check_for_elapsed_periods(dev, dev->sub_capture);
+ }
+
+ static void fill_out_urb(struct snd_usb_caiaqdev *dev,
+@@ -429,8 +420,6 @@ static void fill_out_urb(struct snd_usb_caiaqdev *dev,
+ unsigned char *usb_buf = urb->transfer_buffer + iso->offset;
+ struct snd_pcm_substream *sub;
+ int stream, i;
+-
+- spin_lock(&dev->spinlock);
+
+ for (i = 0; i < iso->length;) {
+ for (stream = 0; stream < dev->n_streams; stream++, i++) {
+@@ -456,9 +445,6 @@ static void fill_out_urb(struct snd_usb_caiaqdev *dev,
+ for (stream = 0; stream < dev->n_streams; stream++, i++)
+ usb_buf[i] = MAKE_CHECKBYTE(dev, stream, i);
+ }
+-
+- spin_unlock(&dev->spinlock);
+- check_for_elapsed_periods(dev, dev->sub_playback);
+ }
+
+ static void read_completed(struct urb *urb)
+@@ -472,6 +458,7 @@ static void read_completed(struct urb *urb)
+ return;
+
+ dev = info->dev;
++
+ if (!dev->streaming)
+ return;
+
+@@ -489,8 +476,12 @@ static void read_completed(struct urb *urb)
+ out->iso_frame_desc[outframe].offset = BYTES_PER_FRAME * frame;
+
+ if (len > 0) {
++ spin_lock(&dev->spinlock);
+ fill_out_urb(dev, out, &out->iso_frame_desc[outframe]);
+ read_in_urb(dev, urb, &urb->iso_frame_desc[frame]);
++ spin_unlock(&dev->spinlock);
++ check_for_elapsed_periods(dev, dev->sub_playback);
++ check_for_elapsed_periods(dev, dev->sub_capture);
+ send_it = 1;
+ }
+
+@@ -696,7 +687,7 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev)
+
+ void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *dev)
+ {
+- debug("snd_usb_caiaq_audio_free (%p)\n", dev);
++ debug("%s(%p)\n", __func__, dev);
+ stream_stop(dev);
+ free_urbs(dev->data_urbs_in);
+ free_urbs(dev->data_urbs_out);
+diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c
+index 7c44a2c..e97d8b2 100644
+--- a/sound/usb/caiaq/caiaq-device.c
++++ b/sound/usb/caiaq/caiaq-device.c
+@@ -42,7 +42,7 @@
+ #endif
+
+ MODULE_AUTHOR("Daniel Mack <daniel at caiaq.de>");
+-MODULE_DESCRIPTION("caiaq USB audio, version 1.3.2");
++MODULE_DESCRIPTION("caiaq USB audio, version 1.3.6");
+ MODULE_LICENSE("GPL");
+ MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
+ "{Native Instruments, RigKontrol3},"
+@@ -456,7 +456,7 @@ static void snd_disconnect(struct usb_interface *intf)
+ struct snd_usb_caiaqdev *dev;
+ struct snd_card *card = dev_get_drvdata(&intf->dev);
+
+- debug("snd_disconnect(%p)\n", intf);
++ debug("%s(%p)\n", __func__, intf);
+
+ if (!card)
+ return;
+diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
+index f48838a..410be4a 100644
+--- a/sound/usb/usbaudio.c
++++ b/sound/usb/usbaudio.c
+@@ -64,9 +64,10 @@ MODULE_SUPPORTED_DEVICE("{{Generic,USB Audio}}");
+
+ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
+ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
+-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+-static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Vendor ID for this card */
+-static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Product ID for this card */
++static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
++/* Vendor/product IDs for this card */
++static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
++static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
+ static int nrpacks = 8; /* max. number of packets per urb */
+ static int async_unlink = 1;
+ static int device_setup[SNDRV_CARDS]; /* device parameter for this card*/
+@@ -687,7 +688,7 @@ static void snd_complete_urb(struct urb *urb)
+ int err = 0;
+
+ if ((subs->running && subs->ops.retire(subs, substream->runtime, urb)) ||
+- ! subs->running || /* can be stopped during retire callback */
++ !subs->running || /* can be stopped during retire callback */
+ (err = subs->ops.prepare(subs, substream->runtime, urb)) < 0 ||
+ (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+ clear_bit(ctx->index, &subs->active_mask);
+@@ -710,7 +711,7 @@ static void snd_complete_sync_urb(struct urb *urb)
+ int err = 0;
+
+ if ((subs->running && subs->ops.retire_sync(subs, substream->runtime, urb)) ||
+- ! subs->running || /* can be stopped during retire callback */
++ !subs->running || /* can be stopped during retire callback */
+ (err = subs->ops.prepare_sync(subs, substream->runtime, urb)) < 0 ||
+ (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+ clear_bit(ctx->index + 16, &subs->active_mask);
+@@ -740,7 +741,7 @@ static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t s
+ vfree(runtime->dma_area);
+ }
+ runtime->dma_area = vmalloc(size);
+- if (! runtime->dma_area)
++ if (!runtime->dma_area)
+ return -ENOMEM;
+ runtime->dma_bytes = size;
+ return 0;
+@@ -772,12 +773,12 @@ static int deactivate_urbs(struct snd_usb_substream *subs, int force, int can_sl
+
+ async = !can_sleep && async_unlink;
+
+- if (! async && in_interrupt())
++ if (!async && in_interrupt())
+ return 0;
+
+ for (i = 0; i < subs->nurbs; i++) {
+ if (test_bit(i, &subs->active_mask)) {
+- if (! test_and_set_bit(i, &subs->unlink_mask)) {
++ if (!test_and_set_bit(i, &subs->unlink_mask)) {
+ struct urb *u = subs->dataurb[i].urb;
+ if (async)
+ usb_unlink_urb(u);
+@@ -789,7 +790,7 @@ static int deactivate_urbs(struct snd_usb_substream *subs, int force, int can_sl
+ if (subs->syncpipe) {
+ for (i = 0; i < SYNC_URBS; i++) {
+ if (test_bit(i+16, &subs->active_mask)) {
+- if (! test_and_set_bit(i+16, &subs->unlink_mask)) {
++ if (!test_and_set_bit(i+16, &subs->unlink_mask)) {
+ struct urb *u = subs->syncurb[i].urb;
+ if (async)
+ usb_unlink_urb(u);
+@@ -1137,12 +1138,12 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
+ if (subs->fmt_type == USB_FORMAT_TYPE_II)
+ u->packets++; /* for transfer delimiter */
+ u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);
+- if (! u->urb)
++ if (!u->urb)
+ goto out_of_memory;
+ u->urb->transfer_buffer =
+ usb_buffer_alloc(subs->dev, u->buffer_size, GFP_KERNEL,
+ &u->urb->transfer_dma);
+- if (! u->urb->transfer_buffer)
++ if (!u->urb->transfer_buffer)
+ goto out_of_memory;
+ u->urb->pipe = subs->datapipe;
+ u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+@@ -1155,7 +1156,7 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
+ /* allocate and initialize sync urbs */
+ subs->syncbuf = usb_buffer_alloc(subs->dev, SYNC_URBS * 4,
+ GFP_KERNEL, &subs->sync_dma);
+- if (! subs->syncbuf)
++ if (!subs->syncbuf)
+ goto out_of_memory;
+ for (i = 0; i < SYNC_URBS; i++) {
+ struct snd_urb_ctx *u = &subs->syncurb[i];
+@@ -1163,7 +1164,7 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
+ u->subs = subs;
+ u->packets = 1;
+ u->urb = usb_alloc_urb(1, GFP_KERNEL);
+- if (! u->urb)
++ if (!u->urb)
+ goto out_of_memory;
+ u->urb->transfer_buffer = subs->syncbuf + i * 4;
+ u->urb->transfer_dma = subs->sync_dma + i * 4;
+@@ -1427,8 +1428,8 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
+ subs->cur_audiofmt = fmt;
+
+ #if 0
+- printk("setting done: format = %d, rate = %d, channels = %d\n",
+- fmt->format, fmt->rate, fmt->channels);
++ printk("setting done: format = %d, rate = %d..%d, channels = %d\n",
++ fmt->format, fmt->rate_min, fmt->rate_max, fmt->channels);
+ printk(" datapipe = 0x%0x, syncpipe = 0x%0x\n",
+ subs->datapipe, subs->syncpipe);
+ #endif
+@@ -1463,7 +1464,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
+ rate = params_rate(hw_params);
+ channels = params_channels(hw_params);
+ fmt = find_format(subs, format, rate, channels);
+- if (! fmt) {
++ if (!fmt) {
+ snd_printd(KERN_DEBUG "cannot set format: format = 0x%x, rate = %d, channels = %d\n",
+ format, rate, channels);
+ return -EINVAL;
+@@ -1584,7 +1585,7 @@ static int hw_check_valid_format(struct snd_pcm_hw_params *params, struct audiof
+ struct snd_mask *fmts = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+
+ /* check the format */
+- if (! snd_mask_test(fmts, fp->format)) {
++ if (!snd_mask_test(fmts, fp->format)) {
+ hwc_debug(" > check: no supported format %d\n", fp->format);
+ return 0;
+ }
+@@ -1620,7 +1621,7 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params,
+ list_for_each(p, &subs->fmt_list) {
+ struct audioformat *fp;
+ fp = list_entry(p, struct audioformat, list);
+- if (! hw_check_valid_format(params, fp))
++ if (!hw_check_valid_format(params, fp))
+ continue;
+ if (changed++) {
+ if (rmin > fp->rate_min)
+@@ -1633,7 +1634,7 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params,
+ }
+ }
+
+- if (! changed) {
++ if (!changed) {
+ hwc_debug(" --> get empty\n");
+ it->empty = 1;
+ return -EINVAL;
+@@ -1674,7 +1675,7 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params,
+ list_for_each(p, &subs->fmt_list) {
+ struct audioformat *fp;
+ fp = list_entry(p, struct audioformat, list);
+- if (! hw_check_valid_format(params, fp))
++ if (!hw_check_valid_format(params, fp))
+ continue;
+ if (changed++) {
+ if (rmin > fp->channels)
+@@ -1687,7 +1688,7 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params,
+ }
+ }
+
+- if (! changed) {
++ if (!changed) {
+ hwc_debug(" --> get empty\n");
+ it->empty = 1;
+ return -EINVAL;
+@@ -1727,7 +1728,7 @@ static int hw_rule_format(struct snd_pcm_hw_params *params,
+ list_for_each(p, &subs->fmt_list) {
+ struct audioformat *fp;
+ fp = list_entry(p, struct audioformat, list);
+- if (! hw_check_valid_format(params, fp))
++ if (!hw_check_valid_format(params, fp))
+ continue;
+ fbits |= (1ULL << fp->format);
+ }
+@@ -1736,7 +1737,7 @@ static int hw_rule_format(struct snd_pcm_hw_params *params,
+ oldbits[1] = fmt->bits[1];
+ fmt->bits[0] &= (u32)fbits;
+ fmt->bits[1] &= (u32)(fbits >> 32);
+- if (! fmt->bits[0] && ! fmt->bits[1]) {
++ if (!fmt->bits[0] && !fmt->bits[1]) {
+ hwc_debug(" --> get empty\n");
+ return -EINVAL;
+ }
+@@ -1762,8 +1763,10 @@ static int check_hw_params_convention(struct snd_usb_substream *subs)
+
+ channels = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL);
+ rates = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL);
+- if (!channels || !rates)
++ if (!channels || !rates) {
++ err = -ENOMEM;
+ goto __out;
++ }
+
+ list_for_each(p, &subs->fmt_list) {
+ struct audioformat *f;
+@@ -1916,7 +1919,10 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
+ 1000 * MIN_PACKS_URB,
+ /*(nrpacks * MAX_URBS) * 1000*/ UINT_MAX);
+
+- if (check_hw_params_convention(subs)) {
++ err = check_hw_params_convention(subs);
++ if (err < 0)
++ return err;
++ else if (err) {
+ hwc_debug("setting extra hw constraints...\n");
+ if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+ hw_rule_rate, subs,
+@@ -2222,7 +2228,7 @@ static void proc_pcm_format_add(struct snd_usb_stream *stream)
+ struct snd_card *card = stream->chip->card;
+
+ sprintf(name, "stream%d", stream->pcm_index);
+- if (! snd_card_proc_new(card, name, &entry))
++ if (!snd_card_proc_new(card, name, &entry))
+ snd_info_set_text_ops(entry, stream, proc_pcm_format_read);
+ }
+
+@@ -2278,7 +2284,7 @@ static void free_substream(struct snd_usb_substream *subs)
+ {
+ struct list_head *p, *n;
+
+- if (! subs->num_formats)
++ if (!subs->num_formats)
+ return; /* not initialized */
+ list_for_each_safe(p, n, &subs->fmt_list) {
+ struct audioformat *fp = list_entry(p, struct audioformat, list);
+@@ -2328,7 +2334,7 @@ static int add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct aud
+ if (as->fmt_type != fp->fmt_type)
+ continue;
+ subs = &as->substream[stream];
+- if (! subs->endpoint)
++ if (!subs->endpoint)
+ continue;
+ if (subs->endpoint == fp->endpoint) {
+ list_add_tail(&fp->list, &subs->fmt_list);
+@@ -2354,7 +2360,7 @@ static int add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct aud
+
+ /* create a new pcm */
+ as = kzalloc(sizeof(*as), GFP_KERNEL);
+- if (! as)
++ if (!as)
+ return -ENOMEM;
+ as->pcm_index = chip->pcm_devs;
+ as->chip = chip;
+@@ -2463,11 +2469,12 @@ static int parse_audio_format_i_type(struct snd_usb_audio *chip, struct audiofor
+ }
+ break;
+ case USB_AUDIO_FORMAT_PCM8:
+- /* Dallas DS4201 workaround */
++ pcm_format = SNDRV_PCM_FORMAT_U8;
++
++ /* Dallas DS4201 workaround: it advertises U8 format, but really
++ supports S8. */
+ if (chip->usb_id == USB_ID(0x04fa, 0x4201))
+ pcm_format = SNDRV_PCM_FORMAT_S8;
+- else
+- pcm_format = SNDRV_PCM_FORMAT_U8;
+ break;
+ case USB_AUDIO_FORMAT_IEEE_FLOAT:
+ pcm_format = SNDRV_PCM_FORMAT_FLOAT_LE;
+@@ -2671,12 +2678,23 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
+ int format;
+ struct audioformat *fp;
+ unsigned char *fmt, *csep;
++ int num;
+
+ dev = chip->dev;
+
+ /* parse the interface's altsettings */
+ iface = usb_ifnum_to_if(dev, iface_no);
+- for (i = 0; i < iface->num_altsetting; i++) {
++
++ num = iface->num_altsetting;
++
++ /*
++ * Dallas DS4201 workaround: It presents 5 altsettings, but the last
++ * one misses syncpipe, and does not produce any sound.
++ */
++ if (chip->usb_id == USB_ID(0x04fa, 0x4201))
++ num = 4;
++
++ for (i = 0; i < num; i++) {
+ alts = &iface->altsetting[i];
+ altsd = get_iface_desc(alts);
+ /* skip invalid one */
+@@ -3375,14 +3393,14 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip,
+ static void proc_audio_usbbus_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
+ {
+ struct snd_usb_audio *chip = entry->private_data;
+- if (! chip->shutdown)
++ if (!chip->shutdown)
+ snd_iprintf(buffer, "%03d/%03d\n", chip->dev->bus->busnum, chip->dev->devnum);
+ }
+
+ static void proc_audio_usbid_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
+ {
+ struct snd_usb_audio *chip = entry->private_data;
+- if (! chip->shutdown)
++ if (!chip->shutdown)
+ snd_iprintf(buffer, "%04x:%04x\n",
+ USB_ID_VENDOR(chip->usb_id),
+ USB_ID_PRODUCT(chip->usb_id));
+@@ -3391,9 +3409,9 @@ static void proc_audio_usbid_read(struct snd_info_entry *entry, struct snd_info_
+ static void snd_usb_audio_create_proc(struct snd_usb_audio *chip)
+ {
+ struct snd_info_entry *entry;
+- if (! snd_card_proc_new(chip->card, "usbbus", &entry))
++ if (!snd_card_proc_new(chip->card, "usbbus", &entry))
+ snd_info_set_text_ops(entry, chip, proc_audio_usbbus_read);
+- if (! snd_card_proc_new(chip->card, "usbid", &entry))
++ if (!snd_card_proc_new(chip->card, "usbid", &entry))
+ snd_info_set_text_ops(entry, chip, proc_audio_usbid_read);
+ }
+
+@@ -3406,7 +3424,6 @@ static void snd_usb_audio_create_proc(struct snd_usb_audio *chip)
+
+ static int snd_usb_audio_free(struct snd_usb_audio *chip)
+ {
+- usb_chip[chip->index] = NULL;
+ kfree(chip);
+ return 0;
+ }
+@@ -3600,8 +3617,8 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
+ snd_card_set_dev(chip->card, &intf->dev);
+ break;
+ }
+- if (! chip) {
+- snd_printk(KERN_ERR "no available usb audio device\n");
++ if (!chip) {
++ printk(KERN_ERR "no available usb audio device\n");
+ goto __error;
+ }
+ }
+@@ -3671,6 +3688,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr)
+ list_for_each(p, &chip->mixer_list) {
+ snd_usb_mixer_disconnect(p);
+ }
++ usb_chip[chip->index] = NULL;
+ mutex_unlock(®ister_mutex);
+ snd_card_free_when_closed(card);
+ } else {
+diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
+index 938dff5..82a8d14 100644
+--- a/sound/usb/usbquirks.h
++++ b/sound/usb/usbquirks.h
+@@ -39,6 +39,30 @@
+ .idProduct = prod, \
+ .bInterfaceClass = USB_CLASS_VENDOR_SPEC
+
++/* Creative/E-Mu devices */
++{
++ USB_DEVICE(0x041e, 0x3010),
++ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++ .vendor_name = "Creative Labs",
++ .product_name = "Sound Blaster MP3+",
++ .ifnum = QUIRK_NO_INTERFACE
++ }
++},
++{
++ /* E-Mu 0202 USB */
++ .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
++ .idVendor = 0x041e,
++ .idProduct = 0x3f02,
++ .bInterfaceClass = USB_CLASS_AUDIO,
++},
++{
++ /* E-Mu 0404 USB */
++ .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
++ .idVendor = 0x041e,
++ .idProduct = 0x3f04,
++ .bInterfaceClass = USB_CLASS_AUDIO,
++},
++
+ /*
+ * Logitech QuickCam: bDeviceClass is vendor-specific, so generic interface
+ * class matches do not take effect without an explicit ID match.
+@@ -97,19 +121,7 @@
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL
+ },
+-/* E-Mu devices */
+-{
+- .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+- .idVendor = 0x041e,
+- .idProduct = 0x3f02,
+- .bInterfaceClass = USB_CLASS_AUDIO,
+-},
+-{
+- .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+- .idVendor = 0x041e,
+- .idProduct = 0x3f04,
+- .bInterfaceClass = USB_CLASS_AUDIO,
+-},
++
+ /*
+ * Yamaha devices
+ */
+@@ -1165,19 +1177,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ }
+ }
+ },
+-{
+- USB_DEVICE(0x582, 0x00a6),
+- .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+- .vendor_name = "Roland",
+- .product_name = "Juno-G",
+- .ifnum = 0,
+- .type = QUIRK_MIDI_FIXED_ENDPOINT,
+- .data = & (const struct snd_usb_midi_endpoint_info) {
+- .out_cables = 0x0001,
+- .in_cables = 0x0001
+- }
+- }
+-},
+ { /*
+ * This quirk is for the "Advanced" modes of the Edirol UA-25.
+ * If the switch is not in an advanced setting, the UA-25 has
+@@ -1336,6 +1335,19 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ },
+ /* TODO: add Edirol MD-P1 support */
+ {
++ USB_DEVICE(0x582, 0x00a6),
++ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
++ .vendor_name = "Roland",
++ .product_name = "Juno-G",
++ .ifnum = 0,
++ .type = QUIRK_MIDI_FIXED_ENDPOINT,
++ .data = & (const struct snd_usb_midi_endpoint_info) {
++ .out_cables = 0x0001,
++ .in_cables = 0x0001
++ }
++ }
++},
++{
+ /* Roland SH-201 */
+ USB_DEVICE(0x0582, 0x00ad),
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+@@ -1719,17 +1731,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
+ }
+ },
+
+-{
+- /* Creative Sound Blaster MP3+ */
+- USB_DEVICE(0x041e, 0x3010),
+- .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+- .vendor_name = "Creative Labs",
+- .product_name = "Sound Blaster MP3+",
+- .ifnum = QUIRK_NO_INTERFACE
+- }
+-
+-},
+-
+ /* Emagic devices */
+ {
+ USB_DEVICE(0x086a, 0x0001),
Modified: dists/trunk/linux-2.6/debian/patches/series/1~experimental.1
==============================================================================
--- dists/trunk/linux-2.6/debian/patches/series/1~experimental.1 (original)
+++ dists/trunk/linux-2.6/debian/patches/series/1~experimental.1 Sat Apr 26 21:59:14 2008
@@ -1,3 +1,4 @@
++ bugfix/all/patch-2.6.25-git9
+ debian/version.patch
+ debian/kernelvariables.patch
+ debian/doc-build-parallel.patch
More information about the Kernel-svn-changes
mailing list